diff --git a/component/common/api/at_cmd/atcmd_google.c b/component/common/api/at_cmd/atcmd_google.c new file mode 100644 index 0000000..1daaf43 --- /dev/null +++ b/component/common/api/at_cmd/atcmd_google.c @@ -0,0 +1,193 @@ +#include +#include +#include "log_service.h" +#include "cmsis_os.h" +#include +#include +#include +#include "wifi_conf.h" +#include "google_nest.h" +#include + +#define GN_PORT 443 + + +#define _AT_GOOGLE_NEST_ "ATG0" + +//functions that using Google Nest's API +void google_data_retrieve_cb(char *response_buf); + +void googlenest_get(char *host_addr, char *host_file) +{ + unsigned char buffer[512]; + googlenest_context googlenest; + char *googlenest_host = host_addr; + char *googlenest_uri = host_file; + + + memset(&googlenest, 0, sizeof(googlenest_context)); + if(gn_connect(&googlenest, googlenest_host, GN_PORT) == 0) { + if(gn_get(&googlenest, googlenest_uri, buffer, sizeof(buffer)) == 0) + printf("\r\n\r\nGet data from googlenest: %s", buffer); + gn_close(&googlenest); + + } +} + +void google_data_retrieve_cb(char *response_buf) { + printf("\r\nResponse_buf:\r\n%s\r\n", response_buf); + +} + +void googlenest_stream(char *host_addr, char *host_file) +{ + googlenest_context googlenest; + char *googlenest_host = host_addr; + char *googlenest_uri = host_file; + + memset(&googlenest, 0, sizeof(googlenest_context)); + if(gn_connect(&googlenest, googlenest_host, GN_PORT) == 0) { + google_retrieve_data_hook_callback(google_data_retrieve_cb); + gn_stream(&googlenest, googlenest_uri); + gn_close(&googlenest); + + } +} + +void googlenest_delete(char *host_addr, char *host_file) +{ + googlenest_context googlenest; + char *googlenest_host = host_addr; + char *googlenest_uri = host_file; + + + memset(&googlenest, 0, sizeof(googlenest_context)); + if(gn_connect(&googlenest, googlenest_host, GN_PORT) == 0) { + if(gn_delete(&googlenest, googlenest_uri) == 0) + printf("\r\n\r\nDelete the data is successful!"); + gn_close(&googlenest); + + } +} + +void googlenest_put(char *host_addr, char *host_file, char *data) +{ + googlenest_context googlenest; + char *googlenest_host = host_addr; + char *googlenest_uri = host_file; + + memset(&googlenest, 0, sizeof(googlenest_context)); + if(gn_connect(&googlenest, googlenest_host, GN_PORT) == 0) { + if(gn_put(&googlenest, googlenest_uri, data) == 0) + printf("\r\n\r\nSaving data in firebase is successful!"); + gn_close(&googlenest); + } +} + +void googlenest_patch(char *host_addr, char *host_file, char *data) +{ + googlenest_context googlenest; + char *googlenest_host = host_addr; + char *googlenest_uri = host_file; + + memset(&googlenest, 0, sizeof(googlenest_context)); + if(gn_connect(&googlenest, googlenest_host, GN_PORT) == 0) { + if(gn_patch(&googlenest, googlenest_uri, data) == 0) + printf("\r\n\r\nUpdating data in firebase is successful!"); + gn_close(&googlenest); + } +} + +void googlenest_post(char *host_addr, char *host_file, char *data) +{ + googlenest_context googlenest; + char *googlenest_host = host_addr; + char *googlenest_uri = host_file; + unsigned char buffer[64]; + + memset(&googlenest, 0, sizeof(googlenest_context)); + if(gn_connect(&googlenest, googlenest_host, GN_PORT) == 0) { + if(gn_post(&googlenest, googlenest_uri, data, buffer, sizeof(buffer)) == 0) + printf("\r\n\r\nInserting data to firebase is successful!\r\n\r\nThe unique name for this list of data is: %s", buffer); + gn_close(&googlenest); + } +} + +void cmd_googlenest(int argc, char **argv) +{ + if(strcmp(argv[1], "get") == 0) { + if(argc != 4) + printf("\n\rUsage: gn get address file"); + else { + googlenest_get(argv[2], argv[3]); + } + } + else if(strcmp(argv[1], "delete") ==0){ + if(argc != 4) + printf("\n\rUsage: gn delete address file"); + else { + googlenest_delete(argv[2], argv[3]); + } + } + else if(strcmp(argv[1], "put") ==0){ + if(argc != 5) + printf("\n\rUsage: gn put address file data"); + else { + googlenest_put(argv[2], argv[3], argv[4]); + } + } + else if(strcmp(argv[1], "patch") ==0){ + if(argc != 5) + printf("\n\rUsage: gn patch address file data"); + else { + googlenest_patch(argv[2], argv[3], argv[4]); + } + } + else if(strcmp(argv[1], "post") ==0){ + if(argc != 5) + printf("\n\rUsage: gn post address file data"); + else { + googlenest_post(argv[2], argv[3], argv[4]); + } + } + else if(strcmp(argv[1], "stream") ==0){ + if(argc != 4) + printf("\n\rUsage: gn stream address file"); + else { + googlenest_stream(argv[2], argv[3]); + } + } + else + printf("\n\rUsage: gn method addr file (data)"); +} + +//AT Command function + +void fATG0(void *arg){ + int argc; + char *argv[MAX_ARGC] = {0}; + printf("[ATG0]: _AT_WLAN_GOOGLENEST_\n\r"); + if(!arg){ + printf("[ATG0]Usage: ATWG=[method,address,file,data] or ATG0=[method,address,file]\n\r"); + return; + } + argv[0] = "gn"; + if((argc = parse_param(arg, argv)) > 1){ + cmd_googlenest(argc, argv); + } + else + printf("[ATG0]Usage: ATG0=[method,address,file,data] or ATG0=[method,address,file]\n\r"); +} + +log_item_t at_google_items[ ] = { + + {"ATG0", fATG0,} + +}; + +void at_google_init(void) +{ + log_service_add_table(at_google_items, sizeof(at_google_items)/sizeof(at_google_items[0])); +} + +log_module_init(at_google_init); diff --git a/component/common/api/at_cmd/atcmd_sys.c b/component/common/api/at_cmd/atcmd_sys.c new file mode 100644 index 0000000..cc198d2 --- /dev/null +++ b/component/common/api/at_cmd/atcmd_sys.c @@ -0,0 +1,512 @@ +#include +#include +#include +#include // mbed +#include +#include +#include +#include "analogin_api.h" +#include "log_service.h" +#include "atcmd_sys.h" + +#if defined(configUSE_WAKELOCK_PMU) && (configUSE_WAKELOCK_PMU == 1) +#include "freertos_pmu.h" +#endif + +extern u32 ConfigDebugErr; +extern u32 ConfigDebugInfo; +extern u32 ConfigDebugWarn; +extern u32 CmdDumpWord(IN u16 argc, IN u8 *argv[]); +extern u32 CmdWriteWord(IN u16 argc, IN u8 *argv[]); + +//-------- AT SYS commands --------------------------------------------------------------- + +void fATSD(void *arg) +{ + int argc = 0; + char *argv[MAX_ARGC] = {0}; + + AT_DBG_MSG(AT_FLAG_DUMP, AT_DBG_ALWAYS, "[ATSD]: _AT_SYSTEM_DUMP_REGISTER_"); + if(!arg){ + AT_DBG_MSG(AT_FLAG_DUMP, AT_DBG_ALWAYS, "[ATSD] Usage: ATSD=REGISTER"); + return; + } + argc = parse_param(arg, argv); + if(argc == 2 || argc == 3) + CmdDumpWord(argc-1, (unsigned char**)(argv+1)); +} + +void fATSE(void *arg) +{ + int argc = 0; + char *argv[MAX_ARGC] = {0}; + + AT_DBG_MSG(AT_FLAG_EDIT, AT_DBG_ALWAYS, "[ATSE]: _AT_SYSTEM_EDIT_REGISTER_"); + if(!arg){ + AT_DBG_MSG(AT_FLAG_EDIT, AT_DBG_ALWAYS, "[ATSE] Usage: ATSE=REGISTER[VALUE]"); + return; + } + argc = parse_param(arg, argv); + if(argc == 3) + CmdWriteWord(argc-1, (unsigned char**)(argv+1)); +} + +#if SUPPORT_MP_MODE +void fATSA(void *arg) +{ + u32 tConfigDebugInfo = ConfigDebugInfo; + int argc = 0, channel; + char *argv[MAX_ARGC] = {0}, *ptmp; + u16 offset, gain; + + AT_DBG_MSG(AT_FLAG_ADC, AT_DBG_ALWAYS, "[ATSA]: _AT_SYSTEM_ADC_TEST_"); + if(!arg){ + AT_DBG_MSG(AT_FLAG_ADC, AT_DBG_ALWAYS, "[ATSA] Usage: ATSA=CHANNEL(0~2)"); + AT_DBG_MSG(AT_FLAG_ADC, AT_DBG_ALWAYS, "[ATSA] Usage: ATSA=k_get"); + AT_DBG_MSG(AT_FLAG_ADC, AT_DBG_ALWAYS, "[ATSA] Usage: ATSA=k_set[offet(hex),gain(hex)]"); + return; + } + + argc = parse_param(arg, argv); + if(strcmp(argv[1], "k_get") == 0){ + sys_adc_calibration(0, &offset, &gain); + AT_DBG_MSG(AT_FLAG_ADC, AT_DBG_ALWAYS, "[ATSA] offset = 0x%04X, gain = 0x%04X", offset, gain); + }else if(strcmp(argv[1], "k_set") == 0){ + if(argc != 4){ + AT_DBG_MSG(AT_FLAG_ADC, AT_DBG_ALWAYS, "[ATSA] Usage: ATSA=k_set[offet(hex),gain(hex)]"); + return; + } + offset = strtoul(argv[2], &ptmp, 16); + gain = strtoul(argv[3], &ptmp, 16); + sys_adc_calibration(1, &offset, &gain); + AT_DBG_MSG(AT_FLAG_ADC, AT_DBG_ALWAYS, "[ATSA] offset = 0x%04X, gain = 0x%04X", offset, gain); + }else{ + channel = atoi(argv[1]); + if(channel < 0 || channel > 2){ + AT_DBG_MSG(AT_FLAG_ADC, AT_DBG_ALWAYS, "[ATSA] Usage: ATSA=CHANNEL(0~2)"); + return; + } + analogin_t adc; + u16 adcdat; + + // Remove debug info massage + ConfigDebugInfo = 0; + if(channel == 0) + analogin_init(&adc, AD_1); + else if(channel == 1) + analogin_init(&adc, AD_2); + else + analogin_init(&adc, AD_3); + adcdat = analogin_read_u16(&adc)>>4; + // Recover debug info massage + ConfigDebugInfo = tConfigDebugInfo; + + AT_DBG_MSG(AT_FLAG_ADC, AT_DBG_ALWAYS, "[ATSA] A%d = 0x%04X", channel, adcdat); + } +} + +void fATSG(void *arg) +{ + gpio_t gpio_test; + int argc = 0, val; + char *argv[MAX_ARGC] = {0}, port, num; + PinName pin = NC; + u32 tConfigDebugInfo = ConfigDebugInfo; + + AT_DBG_MSG(AT_FLAG_GPIO, AT_DBG_ALWAYS, "[ATSG]: _AT_SYSTEM_GPIO_TEST_"); + if(!arg){ + AT_DBG_MSG(AT_FLAG_GPIO, AT_DBG_ALWAYS, "[ATSG] Usage: ATSG=PINNAME(ex:A0)"); + return; + }else{ + argc = parse_param(arg, argv); + if(argc != 2){ + AT_DBG_MSG(AT_FLAG_GPIO, AT_DBG_ALWAYS, "[ATSG] Usage: ATSG=PINNAME(ex:A0)"); + return; + } + } + port = argv[1][0]; + num = argv[1][1]; + if(port >= 'a' && port <= 'z') + port -= ('a' - 'A'); + if(num >= 'a' && num <= 'z') + num -= ('a' - 'A'); + switch(port){ + case 'A': + switch(num){ + case '0': pin = PA_0; break; case '1': pin = PA_1; break; case '2': pin = PA_2; break; case '3': pin = PA_3; break; + case '4': pin = PA_4; break; case '5': pin = PA_5; break; case '6': pin = PA_6; break; case '7': pin = PA_7; break; + } + break; + case 'B': + switch(num){ + case '0': pin = PB_0; break; case '1': pin = PB_1; break; case '2': pin = PB_2; break; case '3': pin = PB_3; break; + case '4': pin = PB_4; break; case '5': pin = PB_5; break; case '6': pin = PB_6; break; case '7': pin = PB_7; break; + } + break; + case 'C': + switch(num){ + case '0': pin = PC_0; break; case '1': pin = PC_1; break; case '2': pin = PC_2; break; case '3': pin = PC_3; break; + case '4': pin = PC_4; break; case '5': pin = PC_5; break; case '6': pin = PC_6; break; case '7': pin = PC_7; break; + case '8': pin = PC_8; break; case '9': pin = PC_9; break; + } + break; + case 'D': + switch(num){ + case '0': pin = PD_0; break; case '1': pin = PD_1; break; case '2': pin = PD_2; break; case '3': pin = PD_3; break; + case '4': pin = PD_4; break; case '5': pin = PD_5; break; case '6': pin = PD_6; break; case '7': pin = PD_7; break; + case '8': pin = PD_8; break; case '9': pin = PD_9; break; + } + break; + case 'E': + switch(num){ + case '0': pin = PE_0; break; case '1': pin = PE_1; break; case '2': pin = PE_2; break; case '3': pin = PE_3; break; + case '4': pin = PE_4; break; case '5': pin = PE_5; break; case '6': pin = PE_6; break; case '7': pin = PE_7; break; + case '8': pin = PE_8; break; case '9': pin = PE_9; break; case 'A': pin = PE_A; break; + } + break; + case 'F': + switch(num){ + case '0': pin = PF_0; break; case '1': pin = PF_1; break; case '2': pin = PF_2; break; case '3': pin = PF_3; break; + case '4': pin = PF_4; break; case '5': pin = PF_5; break; + } + break; + case 'G': + switch(num){ + case '0': pin = PG_0; break; case '1': pin = PG_1; break; case '2': pin = PG_2; break; case '3': pin = PG_3; break; + case '4': pin = PG_4; break; case '5': pin = PG_5; break; case '6': pin = PG_6; break; case '7': pin = PG_7; break; + } + break; + case 'H': + switch(num){ + case '0': pin = PH_0; break; case '1': pin = PH_1; break; case '2': pin = PH_2; break; case '3': pin = PH_3; break; + case '4': pin = PH_4; break; case '5': pin = PH_5; break; case '6': pin = PH_6; break; case '7': pin = PH_7; break; + } + break; + case 'I': + switch(num){ + case '0': pin = PI_0; break; case '1': pin = PI_1; break; case '2': pin = PI_2; break; case '3': pin = PI_3; break; + case '4': pin = PI_4; break; case '5': pin = PI_5; break; case '6': pin = PI_6; break; case '7': pin = PI_7; break; + } + break; + case 'J': + switch(num){ + case '0': pin = PJ_0; break; case '1': pin = PJ_1; break; case '2': pin = PJ_2; break; case '3': pin = PJ_3; break; + case '4': pin = PJ_4; break; case '5': pin = PJ_5; break; case '6': pin = PJ_6; break; + } + break; + case 'K': + switch(num){ + case '0': pin = PK_0; break; case '1': pin = PK_1; break; case '2': pin = PK_2; break; case '3': pin = PK_3; break; + case '4': pin = PK_4; break; case '5': pin = PK_5; break; case '6': pin = PK_6; break; + } + break; + } + if(pin == NC){ + AT_DBG_MSG(AT_FLAG_GPIO, AT_DBG_ALWAYS, "[ATSG]: Invalid Pin Name"); + return; + } + // Remove debug info massage + ConfigDebugInfo = 0; + // Initial input control pin + gpio_init(&gpio_test, pin); + gpio_dir(&gpio_test, PIN_INPUT); // Direction: Input + gpio_mode(&gpio_test, PullUp); // Pull-High + val = gpio_read(&gpio_test); + // Recover debug info massage + ConfigDebugInfo = tConfigDebugInfo; + AT_DBG_MSG(AT_FLAG_GPIO, AT_DBG_ALWAYS, "[ATSG] %c%c = %d", port, num, val); +} + +void fATSC(void *arg) +{ + AT_DBG_MSG(AT_FLAG_OTA, AT_DBG_ALWAYS, "[ATSC]: _AT_SYSTEM_CLEAR_OTA_SIGNATURE_"); + sys_clear_ota_signature(); +} + +void fATSR(void *arg) +{ + AT_DBG_MSG(AT_FLAG_OTA, AT_DBG_ALWAYS, "[ATSR]: _AT_SYSTEM_RECOVER_OTA_SIGNATURE_"); + sys_recover_ota_signature(); +} + +void fATSP(void *arg) +{ + int argc = 0; + char *argv[MAX_ARGC] = {0}; + + unsigned long timeout; // ms + unsigned long time_begin, time_current; + + gpio_t gpiob_1; + int val_old, val_new; + + int expected_zerocount, zerocount; + int test_result; + + // parameter check + AT_DBG_MSG(AT_FLAG_GPIO, AT_DBG_ALWAYS, "[ATSP]: _AT_SYSTEM_POWER_PIN_TEST_"); + if(!arg) { + AT_DBG_MSG(AT_FLAG_GPIO, AT_DBG_ALWAYS, "[ATSP]: Usage: ATSP=gpiob1[timeout,zerocount]"); + } else { + argc = parse_param(arg, argv); + if (argc < 2) { + AT_DBG_MSG(AT_FLAG_GPIO, AT_DBG_ALWAYS, "[ATSP]: Usage: ATSP=gpiob1[timeout,zerocount]"); + return; + } + } + + if ( strcmp(argv[1], "gpiob1" ) == 0 ) { + if (argc < 4) { + AT_DBG_MSG(AT_FLAG_GPIO, AT_DBG_ALWAYS, "[ATSP]: Usage: ATSP=gpiob1[timeout,zerocount]"); + return; + } + + // init gpiob1 test + test_result = 0; + timeout = strtoul(argv[2], NULL, 10); + expected_zerocount = atoi(argv[3]); + zerocount = 0; + val_old = 1; + + sys_log_uart_off(); + + gpio_init(&gpiob_1, PB_1); + gpio_dir(&gpiob_1, PIN_INPUT); + gpio_mode(&gpiob_1, PullDown); + + // gpiob1 test ++ + time_begin = time_current = xTaskGetTickCount(); + while (time_current < time_begin + timeout) { + val_new = gpio_read(&gpiob_1); + + if (val_new != val_old && val_new == 0) { + + zerocount ++; + if (zerocount == expected_zerocount) { + test_result = 1; + break; + } + } + + val_old = val_new; + time_current = xTaskGetTickCount(); + } + // gpio test -- + + sys_log_uart_on(); + + if (test_result == 1) { + AT_DBG_MSG(AT_FLAG_GPIO, AT_DBG_ALWAYS, "[ATSP]: success"); + } else { + AT_DBG_MSG(AT_FLAG_GPIO, AT_DBG_ALWAYS, "[ATSP]: fail, it only got %d zeros", zerocount); + } + } +} +#endif + +#if defined(configUSE_WAKELOCK_PMU) && (configUSE_WAKELOCK_PMU == 1) +void fATSL(void *arg) +{ + int argc = 0; + char *argv[MAX_ARGC] = {0}; + + uint32_t lock_id; + + AT_DBG_MSG(AT_FLAG_OS, AT_DBG_ALWAYS, "[ATSL]: _AT_SYS_WAKELOCK_TEST_"); + + if (!arg) { + AT_DBG_MSG(AT_FLAG_OS, AT_DBG_ALWAYS, "[ATSL] Usage ATSL=[a/r/?][bitmask]"); + return; + } else { + argc = parse_param(arg, argv); + if (argc < 2) { + AT_DBG_MSG(AT_FLAG_OS, AT_DBG_ALWAYS, "[ATSL] Usage ATSL=[a/r/?][bitmask]"); + return; + } + } + + switch(argv[1][0]) { + case 'a': // acquire + { + if (argc == 3) { + lock_id = strtoul(argv[2], NULL, 16); + acquire_wakelock(lock_id); + } + AT_DBG_MSG(AT_FLAG_OS, AT_DBG_ALWAYS, "[ATSL] wakelock:0x%08x", get_wakelock_status()); + break; + } + + case 'r': // release + { + if (argc == 3) { + lock_id = strtoul(argv[2], NULL, 16); + release_wakelock(lock_id); + } + AT_DBG_MSG(AT_FLAG_OS, AT_DBG_ALWAYS, "[ATSL] wakelock:0x%08x", get_wakelock_status()); + break; + } + + case '?': // get status + AT_DBG_MSG(AT_FLAG_OS, AT_DBG_ALWAYS, "[ATSL] wakelock:0x%08x", get_wakelock_status()); + break; + + default: + AT_DBG_MSG(AT_FLAG_OS, AT_DBG_ALWAYS, "[ATSL] Usage ATSL=[a/r/?][bitmask]"); + break; + } +} +#endif + +void fATSs(void *arg) +{ + int argc = 0; + char *argv[MAX_ARGC] = {0}; + + AT_PRINTK("[ATS@]: _AT_SYSTEM_DBG_SETTING_"); + if(!arg){ + AT_PRINTK("[ATS@] Usage: ATS@=[LEVLE,FLAG]"); + }else{ + argc = parse_param(arg, argv); + if(argc == 3){ + char *ptmp; + gDbgLevel = atoi(argv[1]); + gDbgFlag = strtoul(argv[2], &ptmp, 16); + } + } + AT_PRINTK("[ATS@] level = %d, flag = 0x%08X", gDbgLevel, gDbgFlag); +} + +void fATSc(void *arg) +{ + int argc = 0, config = 0; + char *argv[MAX_ARGC] = {0}; + + AT_PRINTK("[ATS!]: _AT_SYSTEM_CONFIG_SETTING_"); + if(!arg){ + AT_PRINTK("[ATS!] Usage: ATS!=[CONFIG(0,1,2),FLAG]"); + }else{ + argc = parse_param(arg, argv); + if(argc == 3){ + char *ptmp; + config = atoi(argv[1]); + gDbgFlag = strtoul(argv[2], &ptmp, 16); + if(config == 0) + ConfigDebugErr = strtoul(argv[2], &ptmp, 16); + if(config == 1) + ConfigDebugInfo = strtoul(argv[2], &ptmp, 16); + if(config == 2) + ConfigDebugWarn = strtoul(argv[2], &ptmp, 16); + } + } + AT_PRINTK("[ATS!] ConfigDebugErr = 0x%08X", ConfigDebugErr); + AT_PRINTK("[ATS!] ConfigDebugInfo = 0x%08X", ConfigDebugInfo); + AT_PRINTK("[ATS!] ConfigDebugWarn = 0x%08X", ConfigDebugWarn); +} + +void fATSt(void *arg) +{ + AT_PRINTK("[ATS#]: _AT_SYSTEM_TEST_"); +} + +void fATSx(void *arg) +{ + AT_PRINTK("[ATS?]: _AT_SYSTEM_HELP_"); + AT_PRINTK("[ATS?]: COMPILE TIME: %s", RTL8195AFW_COMPILE_TIME); +} + + + +void fATGR(void *arg) { + + u32 val; + + printf("=== GPIO_REG_BASE ===\n"); + + printf("GPIO_PORTA_DR = 0x%08x\n", HAL_READ32(GPIO_REG_BASE, GPIO_PORTA_DR)); + printf("GPIO_PORTA_DDR = 0x%08x\n", HAL_READ32(GPIO_REG_BASE, GPIO_PORTA_DDR)); + printf("GPIO_PORTA_CTRL = 0x%08x\n", HAL_READ32(GPIO_REG_BASE, GPIO_PORTA_CTRL)); + + gpio_t gpio; + + printf("PA_0\n"); + + printf("gpio_init\n"); + gpio_init(&gpio, PA_0); + + printf("GPIO_PORTA_DR = 0x%08x\n", HAL_READ32(GPIO_REG_BASE, GPIO_PORTA_DR)); + printf("GPIO_PORTA_DDR = 0x%08x\n", HAL_READ32(GPIO_REG_BASE, GPIO_PORTA_DDR)); + printf("GPIO_PORTA_CTRL = 0x%08x\n", HAL_READ32(GPIO_REG_BASE, GPIO_PORTA_CTRL)); + + printf("gpio_dir PIN_OUTPUT\n"); + gpio_dir(&gpio, PIN_OUTPUT); + + printf("GPIO_PORTA_DR = 0x%08x\n", HAL_READ32(GPIO_REG_BASE, GPIO_PORTA_DR)); + printf("GPIO_PORTA_DDR = 0x%08x\n", HAL_READ32(GPIO_REG_BASE, GPIO_PORTA_DDR)); + printf("GPIO_PORTA_CTRL = 0x%08x\n", HAL_READ32(GPIO_REG_BASE, GPIO_PORTA_CTRL)); + + printf("gpio_mode PullNone\n"); + gpio_mode(&gpio, PullNone); + + printf("GPIO_PORTA_DR = 0x%08x\n", HAL_READ32(GPIO_REG_BASE, GPIO_PORTA_DR)); + printf("GPIO_PORTA_DDR = 0x%08x\n", HAL_READ32(GPIO_REG_BASE, GPIO_PORTA_DDR)); + printf("GPIO_PORTA_CTRL = 0x%08x\n", HAL_READ32(GPIO_REG_BASE, GPIO_PORTA_CTRL)); + + printf("gpio_write 1\n"); + gpio_write(&gpio, 1); + + printf("GPIO_PORTA_DR = 0x%08x\n", HAL_READ32(GPIO_REG_BASE, GPIO_PORTA_DR)); + printf("GPIO_PORTA_DDR = 0x%08x\n", HAL_READ32(GPIO_REG_BASE, GPIO_PORTA_DDR)); + printf("GPIO_PORTA_CTRL = 0x%08x\n", HAL_READ32(GPIO_REG_BASE, GPIO_PORTA_CTRL)); + + printf("gpio_write 0\n"); + gpio_write(&gpio, 0); + + printf("GPIO_PORTA_DR = 0x%08x\n", HAL_READ32(GPIO_REG_BASE, GPIO_PORTA_DR)); + printf("GPIO_PORTA_DDR = 0x%08x\n", HAL_READ32(GPIO_REG_BASE, GPIO_PORTA_DDR)); + printf("GPIO_PORTA_CTRL = 0x%08x\n", HAL_READ32(GPIO_REG_BASE, GPIO_PORTA_CTRL)); + + printf("gpio_write 1\n"); + HAL_WRITE32(GPIO_REG_BASE, GPIO_PORTA_DR, 0x00000001); + + printf("GPIO_PORTA_DR = 0x%08x\n", HAL_READ32(GPIO_REG_BASE, GPIO_PORTA_DR)); + printf("GPIO_PORTA_DDR = 0x%08x\n", HAL_READ32(GPIO_REG_BASE, GPIO_PORTA_DDR)); + printf("GPIO_PORTA_CTRL = 0x%08x\n", HAL_READ32(GPIO_REG_BASE, GPIO_PORTA_CTRL)); + + + +} + + + +log_item_t at_sys_items[] = { + {"ATSD", fATSD,}, // Dump register + {"ATSE", fATSE,}, // Edit register +#if SUPPORT_MP_MODE + {"ATSA", fATSA,}, // MP ADC test + {"ATSG", fATSG,}, // MP GPIO test + {"ATSC", fATSC,}, // Clear OTA signature + {"ATSR", fATSR,}, // Recover OTA signature + {"ATSP", fATSP,}, // MP Power related test +#endif +#if defined(configUSE_WAKELOCK_PMU) && (configUSE_WAKELOCK_PMU == 1) + {"ATSL", fATSL,}, // wakelock test +#endif + {"ATS@", fATSs,}, // Debug message setting + {"ATS!", fATSc,}, // Debug config setting + {"ATS#", fATSt,}, // test command + {"ATS?", fATSx,}, // Help + + + + {"ATGR", fATGR,}, // gpio register test + + + +}; + +void at_sys_init(void) +{ + log_service_add_table(at_sys_items, sizeof(at_sys_items)/sizeof(at_sys_items[0])); +} + +log_module_init(at_sys_init); diff --git a/component/common/api/at_cmd/atcmd_sys.h b/component/common/api/at_cmd/atcmd_sys.h new file mode 100644 index 0000000..3a1cf7a --- /dev/null +++ b/component/common/api/at_cmd/atcmd_sys.h @@ -0,0 +1,5 @@ +#ifndef __ATCMD_SYS_H__ +#define __ATCMD_SYS_H__ + + +#endif diff --git a/component/common/api/at_cmd/atcmd_wifi.c b/component/common/api/at_cmd/atcmd_wifi.c new file mode 100644 index 0000000..4675ae1 --- /dev/null +++ b/component/common/api/at_cmd/atcmd_wifi.c @@ -0,0 +1,979 @@ +#include "FreeRTOS.h" +#include "task.h" +#include "semphr.h" +#include "log_service.h" +#include "atcmd_wifi.h" +#include +#include "tcpip.h" +#include +#include +#include +#include +#if SUPPORT_LOG_SERVICE +/******************************************************************************/ +#define _AT_WLAN_SET_SSID_ "ATW0" +#define _AT_WLAN_SET_PASSPHRASE_ "ATW1" +#define _AT_WLAN_SET_KEY_ID_ "ATW2" +#define _AT_WLAN_AP_SET_SSID_ "ATW3" +#define _AT_WLAN_AP_SET_SEC_KEY_ "ATW4" +#define _AT_WLAN_AP_SET_CHANNEL_ "ATW5" +#define _AT_WLAN_AP_ACTIVATE_ "ATWA" +#define _AT_WLAN_AP_STA_ACTIVATE_ "ATWB" +#define _AT_WLAN_JOIN_NET_ "ATWC" +#define _AT_WLAN_DISC_NET_ "ATWD" +#define _AT_WLAN_WEB_SERVER_ "ATWE" +#define _AT_WLAN_PING_TEST_ "ATWI" +#define _AT_WLAN_SSL_CLIENT_ "ATWL" +#define _AT_WLAN_WIFI_PROMISC_ "ATWM" +#define _AT_WLAN_POWER_ "ATWP" +#define _AT_WLAN_SIMPLE_CONFIG_ "ATWQ" +#define _AT_WLAN_GET_RSSI_ "ATWR" +#define _AT_WLAN_SCAN_ "ATWS" +#define _AT_WLAN_TCP_TEST_ "ATWT" +#define _AT_WLAN_UDP_TEST_ "ATWU" +#define _AT_WLAN_WPS_ "ATWW" +#define _AT_WLAN_IWPRIV_ "ATWZ" +#define _AT_WLAN_INFO_ "ATW?" + +#ifndef CONFIG_SSL_CLIENT +#define CONFIG_SSL_CLIENT 0 +#endif +#ifndef CONFIG_WEBSERVER +#define CONFIG_WEBSERVER 0 +#endif +#ifndef CONFIG_OTA_UPDATE +#define CONFIG_OTA_UPDATE 0 +#endif +#ifndef CONFIG_BSD_TCP +#define CONFIG_BSD_TCP 1 +#endif +#ifndef CONFIG_ENABLE_P2P +#define CONFIG_ENABLE_P2P 0 +#endif +#define SCAN_WITH_SSID 0 +#if CONFIG_WEBSERVER +#define CONFIG_READ_FLASH 1 +extern rtw_wifi_setting_t wifi_setting; +#endif +#if CONFIG_WLAN + +extern void cmd_promisc(int argc, char **argv); +extern void cmd_update(int argc, char **argv); +extern void cmd_tcp(int argc, char **argv); +extern void cmd_udp(int argc, char **argv); +extern void cmd_simple_config(int argc, char **argv); +#if CONFIG_ENABLE_WPS +extern void cmd_wps(int argc, char **argv); +#endif +extern void cmd_ssl_client(int argc, char **argv); +#ifdef CONFIG_WPS_AP +extern void cmd_ap_wps(int argc, char **argv); +extern int wpas_wps_dev_config(u8 *dev_addr, u8 bregistrar); +#endif //CONFIG_WPS_AP +#if CONFIG_ENABLE_P2P +extern void cmd_wifi_p2p_start(int argc, char **argv); +extern void cmd_wifi_p2p_stop(int argc, char **argv); +extern void cmd_p2p_listen(int argc, char **argv); +extern void cmd_p2p_find(int argc, char **argv); +extern void cmd_p2p_peers(int argc, char **argv); +extern void cmd_p2p_info(int argc, char **argv); +extern void cmd_p2p_disconnect(int argc, char **argv); +extern void cmd_p2p_connect(int argc, char **argv); +#endif //CONFIG_ENABLE_P2P +#if CONFIG_LWIP_LAYER +extern struct netif xnetif[NET_IF_NUM]; +#endif +static rtw_network_info_t wifi = {0}; +static rtw_ap_info_t ap = {0}; +static unsigned char password[65] = {0}; +static void init_wifi_struct(void) +{ + memset(wifi.ssid.val, 0, sizeof(wifi.ssid.val)); + memset(wifi.bssid.octet, 0, ETH_ALEN); + memset(password, 0, sizeof(password)); + wifi.ssid.len = 0; + wifi.password = NULL; + wifi.password_len = 0; + wifi.key_id = -1; + memset(ap.ssid.val, 0, sizeof(ap.ssid.val)); + ap.ssid.len = 0; + ap.password = NULL; + ap.password_len = 0; + ap.channel = 1; +} + +static void print_scan_result( rtw_scan_result_t* record ) +{ + RTW_API_INFO( ( "%s\t ", ( record->bss_type == RTW_BSS_TYPE_ADHOC ) ? "Adhoc" : "Infra" ) ); + RTW_API_INFO( ( MAC_FMT, MAC_ARG(record->BSSID.octet) ) ); + RTW_API_INFO( ( " %d\t ", record->signal_strength ) ); + RTW_API_INFO( ( " %d\t ", record->channel ) ); + RTW_API_INFO( ( " %d\t ", record->wps_type ) ); + RTW_API_INFO( ( "%s\t\t ", ( record->security == RTW_SECURITY_OPEN ) ? "Open" : + ( record->security == RTW_SECURITY_WEP_PSK ) ? "WEP" : + ( record->security == RTW_SECURITY_WPA_TKIP_PSK ) ? "WPA TKIP" : + ( record->security == RTW_SECURITY_WPA_AES_PSK ) ? "WPA AES" : + ( record->security == RTW_SECURITY_WPA2_AES_PSK ) ? "WPA2 AES" : + ( record->security == RTW_SECURITY_WPA2_TKIP_PSK ) ? "WPA2 TKIP" : + ( record->security == RTW_SECURITY_WPA2_MIXED_PSK ) ? "WPA2 Mixed" : + "Unknown" ) ); + + RTW_API_INFO( ( " %s ", record->SSID.val ) ); + RTW_API_INFO( ( "\r\n" ) ); +} + +static rtw_result_t app_scan_result_handler( rtw_scan_handler_result_t* malloced_scan_result ) +{ + static int ApNum = 0; + + if (malloced_scan_result->scan_complete != RTW_TRUE) { + rtw_scan_result_t* record = &malloced_scan_result->ap_details; + record->SSID.val[record->SSID.len] = 0; /* Ensure the SSID is null terminated */ + + RTW_API_INFO( ( "%d\t ", ++ApNum ) ); + + print_scan_result(record); + } else{ + ApNum = 0; + } + return RTW_SUCCESS; +} + +void fATW0(void *arg){ + if(!arg){ + printf("[ATW0]Usage: ATW0=SSID\n\r"); + return; + } + printf("[ATW0]: _AT_WLAN_SET_SSID_ [%s]\n\r", (char*)arg); + strcpy((char *)wifi.ssid.val, (char*)arg); + wifi.ssid.len = strlen((char*)arg); +} + +void fATW1(void *arg){ + printf("[ATW1]: _AT_WLAN_SET_PASSPHRASE_ [%s]\n\r", (char*)arg); + strcpy((char *)password, (char*)arg); + wifi.password = password; + wifi.password_len = strlen((char*)arg); + + /* + * note:rtw_wx_set_passphrase will clear psecuritypriv->wpa_passphrase when len=64 + * so psk_derive will return because passphrase[0] == 0, then psk_passphrase + * will not be set. Here set psk_passphrase64 to make restore_wifi_info_to_flash working + * + */ + extern unsigned char psk_passphrase64[64 + 1]; + if (wifi.password_len == 64) + strcpy(psk_passphrase64, wifi.password); +} + +void fATW2(void *arg){ + printf("[ATW2]: _AT_WLAN_SET_KEY_ID_ [%s]\n\r", (char*)arg); + if((strlen((const char *)arg) != 1 ) || (*(char*)arg <'0' ||*(char*)arg >'3')) { + printf("\n\rWrong WEP key id. Must be one of 0,1,2, or 3."); + return; + } + wifi.key_id = atoi((const char *)(arg)); +} + +void fATW3(void *arg){ + if(!arg){ + printf("[ATW3]Usage: ATW3=SSID\n\r"); + return; + } + + ap.ssid.len = strlen((char*)arg); + + if(ap.ssid.len > 32){ + printf("[ATW3]Error: SSID length can't exceed 32\n\r"); + return; + } + strcpy((char *)ap.ssid.val, (char*)arg); + + printf("[ATW3]: _AT_WLAN_AP_SET_SSID_ [%s]\n\r", ap.ssid.val); +} + +void fATW4(void *arg){ + strcpy((char *)password, (char*)arg); + ap.password = password; + ap.password_len = strlen((char*)arg); + printf("[ATW4]: _AT_WLAN_AP_SET_SEC_KEY_ [%s]\n\r", ap.password); +} + +void fATW5(void *arg){ + ap.channel = (unsigned char) atoi((const char *)arg); + printf("[ATW5]: _AT_WLAN_AP_SET_CHANNEL_ [channel %d]\n\r", ap.channel); +} + +void fATW6(void *arg){ + u32 mac[ETH_ALEN]; + u32 i; + if(!arg){ + printf("[ATW6]Usage: ATW6=BSSID\n\r"); + return; + } + printf("[ATW6]: _AT_WLAN_SET_BSSID_ [%s]\n\r", (char*)arg); + sscanf(arg, MAC_FMT, mac, mac + 1, mac + 2, mac + 3, mac + 4, mac + 5); + for(i = 0; i < ETH_ALEN; i ++) + wifi.bssid.octet[i] = (u8)mac[i] & 0xFF; +} + +void fATWA(void *arg){ +#if CONFIG_LWIP_LAYER + struct ip_addr ipaddr; + struct ip_addr netmask; + struct ip_addr gw; + struct netif * pnetif = &xnetif[0]; +#endif + int timeout = 20; + printf("[ATWA]: _AT_WLAN_AP_ACTIVATE_\n\r"); + if(ap.ssid.val[0] == 0){ + printf("[ATWA]Error: SSID can't be empty\n\r"); + return; + } + if(ap.password == NULL){ + ap.security_type = RTW_SECURITY_OPEN; + } + else{ + ap.security_type = RTW_SECURITY_WPA2_AES_PSK; + } + +#if CONFIG_WEBSERVER + //store into flash + memset(wifi_setting.ssid, 0, sizeof(wifi_setting.ssid));; + memcpy(wifi_setting.ssid, ap.ssid.val, strlen((char*)ap.ssid.val)); + wifi_setting.ssid[ap.ssid.len] = '\0'; + wifi_setting.security_type = ap.security_type; + if(ap.security_type !=0) + wifi_setting.security_type = 1; + else + wifi_setting.security_type = 0; + if (ap.password) + memcpy(wifi_setting.password, ap.password, strlen((char*)ap.password)); + else + memset(wifi_setting.password, 0, sizeof(wifi_setting.password));; + wifi_setting.channel = ap.channel; +#if CONFIG_READ_FLASH + StoreApInfo(); +#endif +#endif + +#if CONFIG_LWIP_LAYER + dhcps_deinit(); + IP4_ADDR(&ipaddr, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3); + IP4_ADDR(&netmask, NETMASK_ADDR0, NETMASK_ADDR1 , NETMASK_ADDR2, NETMASK_ADDR3); + IP4_ADDR(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3); + netif_set_addr(pnetif, &ipaddr, &netmask,&gw); +#ifdef CONFIG_DONT_CARE_TP + pnetif->flags |= NETIF_FLAG_IPSWITCH; +#endif +#endif + wifi_off(); + vTaskDelay(20); + if (wifi_on(RTW_MODE_AP) < 0){ + printf("\n\rERROR: Wifi on failed!"); + return; + } + printf("\n\rStarting AP ..."); + +#ifdef CONFIG_WPS_AP + wpas_wps_dev_config(pnetif->hwaddr, 1); +#endif + if(wifi_start_ap((char*)ap.ssid.val, ap.security_type, (char*)ap.password, ap.ssid.len, ap.password_len, ap.channel) < 0) { + printf("\n\rERROR: Operation failed!"); + return; + } + + while(1) { + char essid[33]; + + if(wext_get_ssid(WLAN0_NAME, (unsigned char *) essid) > 0) { + if(strcmp((const char *) essid, (const char *)ap.ssid.val) == 0) { + printf("\n\r%s started\n", ap.ssid.val); + break; + } + } + + if(timeout == 0) { + printf("\n\rERROR: Start AP timeout!"); + break; + } + + vTaskDelay(1 * configTICK_RATE_HZ); + timeout --; + } +#if CONFIG_LWIP_LAYER + //LwIP_UseStaticIP(pnetif); + dhcps_init(pnetif); +#endif + + init_wifi_struct( ); +} +void fATWC(void *arg){ + int mode, ret; + unsigned long tick1 = xTaskGetTickCount(); + unsigned long tick2, tick3; + char empty_bssid[6] = {0}, assoc_by_bssid = 0; + + printf("[ATWC]: _AT_WLAN_JOIN_NET_\n\r"); + if(memcmp (wifi.bssid.octet, empty_bssid, 6)) + assoc_by_bssid = 1; + else if(wifi.ssid.val[0] == 0){ + printf("[ATWC]Error: SSID can't be empty\n\r"); + goto EXIT; + } + if(wifi.password != NULL){ + if((wifi.key_id >= 0)&&(wifi.key_id <= 3)) { + wifi.security_type = RTW_SECURITY_WEP_PSK; + } + else{ + wifi.security_type = RTW_SECURITY_WPA2_AES_PSK; + } + } + else{ + wifi.security_type = RTW_SECURITY_OPEN; + } + //Check if in AP mode + wext_get_mode(WLAN0_NAME, &mode); + if(mode == IW_MODE_MASTER) { +#if CONFIG_LWIP_LAYER + dhcps_deinit(); +#endif + wifi_off(); + vTaskDelay(20); + if (wifi_on(RTW_MODE_STA) < 0){ + printf("\n\rERROR: Wifi on failed!"); + goto EXIT; + } + } + if(assoc_by_bssid){ + printf("\n\rJoining BSS by BSSID "MAC_FMT" ...\n\r", MAC_ARG(wifi.bssid.octet)); + ret = wifi_connect_bssid(wifi.bssid.octet, (char*)wifi.ssid.val, wifi.security_type, (char*)wifi.password, + ETH_ALEN, wifi.ssid.len, wifi.password_len, wifi.key_id, NULL); + } else { + printf("\n\rJoining BSS by SSID %s...\n\r", (char*)wifi.ssid.val); + ret = wifi_connect((char*)wifi.ssid.val, wifi.security_type, (char*)wifi.password, wifi.ssid.len, + wifi.password_len, wifi.key_id, NULL); + } + + if(ret!= RTW_SUCCESS){ + printf("\n\rERROR: Operation failed!"); + goto EXIT; + } + tick2 = xTaskGetTickCount(); + printf("\r\nConnected after %dms.\n", (tick2-tick1)); +#if CONFIG_LWIP_LAYER + /* Start DHCPClient */ + LwIP_DHCP(0, DHCP_START); + tick3 = xTaskGetTickCount(); + printf("\r\n\nGot IP after %dms.\n", (tick3-tick1)); +#endif + printf("\n\r"); +EXIT: + init_wifi_struct( ); +} + +void fATWD(void *arg){ + int timeout = 20; + char essid[33]; + printf("[ATWD]: _AT_WLAN_DISC_NET_\n\r"); + printf("\n\rDeassociating AP ..."); + + if(wext_get_ssid(WLAN0_NAME, (unsigned char *) essid) < 0) { + printf("\n\rWIFI disconnected"); + return; + } + + if(wifi_disconnect() < 0) { + printf("\n\rERROR: Operation failed!"); + return; + } + + while(1) { + if(wext_get_ssid(WLAN0_NAME, (unsigned char *) essid) < 0) { + printf("\n\rWIFI disconnected"); + break; + } + + if(timeout == 0) { + printf("\n\rERROR: Deassoc timeout!"); + break; + } + + vTaskDelay(1 * configTICK_RATE_HZ); + timeout --; + } + printf("\n\r"); + init_wifi_struct( ); +} + +void fATWS(void *arg){ + char buf[32] = {0}; + u8 *channel_list = NULL; + u8 *pscan_config = NULL; + int num_channel = 0; + int i, argc = 0; + char *argv[MAX_ARGC] = {0}; + printf("[ATWS]: _AT_WLAN_SCAN_\n\r"); + if(arg){ + strcpy(buf, arg); + argc = parse_param(buf, argv); + if(argc < 2) + goto exit; + num_channel = atoi(argv[1]); + channel_list = (u8*)malloc(num_channel); + if(!channel_list){ + printf("[ATWS]ERROR: Can't malloc memory for channel list\n\r"); + goto exit; + } + pscan_config = (u8*)malloc(num_channel); + if(!pscan_config){ + printf("[ATWS]ERROR: Can't malloc memory for pscan_config\n\r"); + goto exit; + } + //parse command channel list + for(i = 2; i <= argc -1 ; i++){ + *(channel_list + i - 2) = (u8)atoi(argv[i]); + *(pscan_config + i - 2) = PSCAN_ENABLE; + } + + if(wifi_set_pscan_chan(channel_list, pscan_config, num_channel) < 0){ + printf("[ATWS]ERROR: wifi set partial scan channel fail\n\r"); + goto exit; + } + } + + if(wifi_scan_networks(app_scan_result_handler, NULL ) != RTW_SUCCESS){ + printf("[ATWS]ERROR: wifi scan failed\n\r"); + goto exit; + } +exit: + if(arg && channel_list) + free(channel_list); +} + +#if SCAN_WITH_SSID +void fATWs(void *arg){ + char buf[32] = {0}; + u8 *channel_list = NULL; + int scan_buf_len = 500; + int num_channel = 0; + int i, argc = 0; + char *argv[MAX_ARGC] = {0}; + printf("[ATWs]: _AT_WLAN_SCAN_WITH_SSID_ [%s]\n\r", (char*)wifi.ssid.val); + if(arg){ + strcpy(buf, arg); + argc = parse_param(buf, argv); + if(argc == 2){ + scan_buf_len = atoi(argv[1]); + }else if(argc > 2){ + num_channel = atoi(argv[1]); + channel_list = (u8*)malloc(num_channel); + if(!channel_list){ + printf("[ATWS]ERROR: Can't malloc memory for channel list\n\r"); + goto exit; + } + //parse command channel list + for(i = 2; i <= argc -1 ; i++){ + *(channel_list + i - 2) = (u8)atoi(argv[i]); + } + + if(wifi_set_pscan_chan(channel_list, num_channel) < 0){ + printf("[ATWS]ERROR: wifi set partial scan channel fail\n\r"); + goto exit; + } + } + }else{ + printf("[ATWs]For Scan all channel Usage: ATWs=BUFFER_LENGTH\n\r"); + printf("[ATWs]For Scan partial channel Usage: ATWs=num_channels[channel_num1, ...]\n\r"); + goto exit; + } + + if(wifi_scan_networks_with_ssid(NULL, &scan_buf_len, wifi.ssid.val, wifi.ssid.len) != RTW_SUCCESS){ + printf("[ATWS]ERROR: wifi scan failed\n\r"); + } +exit: + if(arg && channel_list) + free(channel_list); +} +#endif + +void fATWR(void *arg){ + int rssi = 0; + printf("[ATWR]: _AT_WLAN_GET_RSSI_\n\r"); + wifi_get_rssi(&rssi); + printf("\n\rwifi_get_rssi: rssi = %d", rssi); + printf("\n\r"); +} + +void fATWP(void *arg){ + unsigned int parm = atoi((const char *)(arg)); + printf("[ATWP]: _AT_WLAN_POWER_[%s]\n\r", parm?"ON":"OFF"); + if(parm == 1){ + if(wifi_on(RTW_MODE_STA)<0){ + printf("\n\rERROR: Wifi on failed!\n"); + } + } + else if(parm == 0) + { +#if CONFIG_WEBSERVER + stop_web_server(); +#endif + wifi_off(); + } + else + printf("[ATWP]Usage: ATWP=0/1\n\r"); +} +#ifdef CONFIG_CONCURRENT_MODE +void fATWB(void *arg) +{ + int timeout = 20;//, mode; +#if CONFIG_LWIP_LAYER + struct netif * pnetiff = (struct netif *)&xnetif[1]; +#endif + printf("[ATWB](_AT_WLAN_AP_STA_ACTIVATE_)\n\r"); + if(ap.ssid.val[0] == 0){ + printf("[ATWB]Error: SSID can't be empty\n\r"); + return; + } + if(ap.channel > 14){ + printf("[ATWB]Error:bad channel! channel is from 1 to 14\n\r"); + return; + } + if(ap.password == NULL){ + ap.security_type = RTW_SECURITY_OPEN; + } + else{ + ap.security_type = RTW_SECURITY_WPA2_AES_PSK; + } + +#if CONFIG_LWIP_LAYER + dhcps_deinit(); +#endif + + wifi_off(); + vTaskDelay(20); + if (wifi_on(RTW_MODE_STA_AP) < 0){ + printf("\n\rERROR: Wifi on failed!"); + return; + } + + printf("\n\rStarting AP ..."); + if(wifi_start_ap((char*)ap.ssid.val, ap.security_type, (char*)ap.password, ap.ssid.len, ap.password_len, ap.channel) < 0) { + printf("\n\rERROR: Operation failed!"); + return; + } + while(1) { + char essid[33]; + + if(wext_get_ssid(WLAN1_NAME, (unsigned char *) essid) > 0) { + if(strcmp((const char *) essid, (const char *)ap.ssid.val) == 0) { + printf("\n\r%s started\n", ap.ssid.val); + break; + } + } + + if(timeout == 0) { + printf("\n\rERROR: Start AP timeout!"); + break; + } + + vTaskDelay(1 * configTICK_RATE_HZ); + timeout --; + } +#if CONFIG_LWIP_LAYER + LwIP_UseStaticIP(&xnetif[1]); +#ifdef CONFIG_DONT_CARE_TP + pnetiff->flags |= NETIF_FLAG_IPSWITCH; +#endif + dhcps_init(pnetiff); +#endif +} +#endif + +void fATWI(void *arg){ + int count, argc = 0; + char buf[32] = {0}; + char *argv[MAX_ARGC] = {0}; + printf("[ATWI]: _AT_WLAN_PING_TEST_\n\r"); + if(!arg){ + printf("[ATWI]Usage: ATWI=xxxx.xxxx.xxxx.xxxx[y/loop]\n\r"); + return; + } + strcpy(buf, arg); + argv[0] = "ping"; + argc = parse_param(buf, argv); + printf("[ATWI]Target address: %s\n\r", argv[1]); + if(argc == 2){ + printf("[ATWI]Repeat Count: 5\n\r"); + do_ping_call(argv[1], 0, 5); //Not loop, count=5 + }else{ + if(strcmp(argv[2], "loop") == 0){ + printf("[ATWI]Repeat Count: %s\n\r", "loop"); + do_ping_call(argv[1], 1, 0); //loop, no count + } + else{ + count = atoi(argv[2]); + printf("[ATWI]Repeat Count: %d\n\r", count); + do_ping_call(argv[1], 0, count); //Not loop, with count + } + } +} + +#if CONFIG_BSD_TCP +void fATWT(void *arg){ + int argc; + char *argv[MAX_ARGC] = {0}; + printf("[ATWT]: _AT_WLAN_TCP_TEST_\n\r"); + if(!arg){ + printf("[ATWT]Usage: ATWT=[-c/c,xxxx.xxxx.xxxx.xxxx,buf_len,count] or ATWT=[-s/s] or ATWT=[stop]\n\r"); + return; + } + argv[0] = "tcp"; + if((argc = parse_param(arg, argv)) > 1){ + cmd_tcp(argc, argv); + } + else + printf("[ATWT]Usage: ATWT=[-c/c,xxxx.xxxx.xxxx.xxxx,buf_len,count] or ATWT=[-s/s] or ATWT=[stop]\n\r"); +} + +void fATWU(void *arg){ + int argc; + char *argv[MAX_ARGC] = {0}; + printf("[ATWU]: _AT_WLAN_UDP_TEST_\n\r"); + if(!arg){ + printf("[ATWU]Usage: ATWU=[-c/c,xxxx.xxxx.xxxx.xxxx,buf_len,count] or ATWU=[-s/s] or ATWU=[stop]\n\r"); + return; + } + argv[0] = "ucp"; + if((argc = parse_param(arg, argv)) > 1){ + cmd_udp(argc, argv); + } + else + printf("[ATWU]Usage: ATWU=[-c/c,xxxx.xxxx.xxxx.xxxx,buf_len,count] or ATWU=[-s/s] or ATWU=[stop]\n\r"); +} +#endif + +void fATWM(void *arg){ + int argc; + char *argv[MAX_ARGC] = {0}; + argv[0] = "wifi_promisc"; + printf("[ATWM]: _AT_WLAN_PROMISC_\n\r"); + if(!arg){ + printf("[ATWM]Usage: ATWM=DURATION_SECONDS[with_len]"); + return; + } + if((argc = parse_param(arg, argv)) > 1){ + cmd_promisc(argc, argv); + } +} + +void fATWL(void *arg){ + int argc; + char *argv[MAX_ARGC] = {0}; + printf("[ATWL]: _AT_WLAN_SSL_CLIENT_\n\r"); + argv[0] = "ssl_client"; + if(!arg){ + printf("ATWL=SSL_SERVER_HOST[SRP_USER_NAME,SRP_PASSWORD]\n\r"); + return; + } + if((argc = parse_param(arg, argv)) > 1){ + cmd_ssl_client(argc, argv); + } +} + + +#if CONFIG_WEBSERVER +void fATWE(void *arg){ + printf("[ATWE]: _AT_WLAN_START_WEB_SERVER_\n\r"); + start_web_server(); +} +#endif + +void fATWQ(void *arg){ + int argc=0; + char *argv[2] = {0}; + printf("[ATWQ]: _AT_WLAN_SIMPLE_CONFIG_\n\r"); + argv[argc++] = "wifi_simple_config"; + if(arg){ + argv[argc++] = arg; + } + cmd_simple_config(argc, argv); +} +#if CONFIG_ENABLE_WPS +void fATWW(void *arg){ + int argc = 0; + char *argv[4]; + printf("[ATWW]: _AT_WLAN_WPS_\n\r"); + if(!arg){ + printf("[ATWW]Usage: ATWW=pbc/pin\n\r"); + return; + } + argv[argc++] = "wifi_wps"; + argv[argc++] = arg; + cmd_wps(argc, argv); +} +#endif +void fATWw(void *arg){ +#ifdef CONFIG_WPS_AP + int argc = 0; + char *argv[4]; + printf("[ATWw]: _AT_WLAN_AP_WPS_\n\r"); + if(!arg){ + printf("[ATWw]Usage: ATWw=pbc/pin\n\r"); + return; + } + argv[argc++] = "wifi_ap_wps"; + argv[argc++] = arg; + cmd_ap_wps(argc, argv); +#endif +} + +#if CONFIG_ENABLE_P2P +void fATWG(void *arg){ + int argc = 0; + char *argv[4]; + printf("[ATWa]: _AT_WLAN_P2P_START_\n\r"); + argv[argc++] = "p2p_start"; + cmd_wifi_p2p_start(argc, argv); +} +void fATWH(void *arg){ + int argc = 0; + char *argv[4]; + printf("[ATWb]: _AT_WLAN_P2P_STOP_\n\r"); + argv[argc++] = "p2p_stop"; + cmd_wifi_p2p_stop(argc, argv); +} +void fATWJ(void *arg){ + int argc = 0; + char *argv[4]; + printf("[ATWc]: _AT_WLAN_P2P_CONNECT_\n\r"); + argv[0] = "p2p_connect"; + if(!arg){ + printf("ATWc=[DEST_MAC,pbc/pin]\n\r"); + return; + } + if((argc = parse_param(arg, argv)) > 1){ + cmd_p2p_connect(argc, argv); + } +} +void fATWK(void *arg){ + int argc = 0; + char *argv[4]; + printf("[ATWd]: _AT_WLAN_P2P_DISCONNECT_\n\r"); + argv[argc++] = "p2p_disconnect"; + cmd_p2p_disconnect(argc, argv); +} +void fATWN(void *arg){ + int argc = 0; + char *argv[4]; + printf("[ATWe]: _AT_WLAN_P2P_INFO_\n\r"); + argv[argc++] = "p2p_info"; + cmd_p2p_info(argc, argv); +} +void fATWF(void *arg){ + int argc = 0; + char *argv[4]; + printf("[ATWf]: _AT_WLAN_P2P_FIND_\n\r"); + argv[argc++] = "p2p_find"; + cmd_p2p_find(argc, argv); +} +#endif +#if CONFIG_OTA_UPDATE +void fATWO(void *arg){ + int argc = 0; + char *argv[MAX_ARGC] = {0}; + printf("[ATWO]: _AT_WLAN_OTA_UPDATE_\n\r"); + if(!arg){ + printf("[ATWO]Usage: ATWO=IP[PORT] or ATWO= REPOSITORY[FILE_PATH]\n\r"); + return; + } + argv[0] = "update"; + if((argc = parse_param(arg, argv)) != 3){ + printf("[ATWO]Usage: ATWO=IP[PORT] or ATWO= REPOSITORY[FILE_PATH]\n\r"); + return; + } + cmd_update(argc, argv); +} +#endif +void fATWx(void *arg){ + int i = 0; +#if CONFIG_LWIP_LAYER + u8 *mac = LwIP_GetMAC(&xnetif[0]); + u8 *ip = LwIP_GetIP(&xnetif[0]); + u8 *gw = LwIP_GetGW(&xnetif[0]); +#endif + u8 *ifname[2] = {WLAN0_NAME,WLAN1_NAME}; + rtw_wifi_setting_t setting; + printf("[ATW?]: _AT_WLAN_INFO_\n\r"); + + for(i=0;i %02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]) ; + printf("\n\r\tIP => %d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); + printf("\n\r\tGW => %d.%d.%d.%d\n\r", gw[0], gw[1], gw[2], gw[3]); +#endif + if(setting.mode == RTW_MODE_AP || i == 1) + { + int client_number; + struct { + int count; + rtw_mac_t mac_list[3]; + } client_info; + + client_info.count = 3; + wifi_get_associated_client_list(&client_info, sizeof(client_info)); + + printf("\n\rAssociated Client List:"); + printf("\n\r=============================="); + + if(client_info.count == 0) + printf("\n\rClient Num: 0\n\r", client_info.count); + else + { + printf("\n\rClient Num: %d", client_info.count); + for( client_number=0; client_number < client_info.count; client_number++ ) + { + printf("\n\rClient %d:", client_number + 1); + printf("\n\r\tMAC => "MAC_FMT"", + MAC_ARG(client_info.mac_list[client_number].octet)); + } + printf("\n\r"); + } + } + } + } + +#if defined(configUSE_TRACE_FACILITY) && (configUSE_TRACE_FACILITY == 1) && (configUSE_STATS_FORMATTING_FUNCTIONS == 1) + { + signed char pcWriteBuffer[1024]; + vTaskList((char*)pcWriteBuffer); + printf("\n\rTask List: \n\r%s", pcWriteBuffer); + } +#endif +} + +void fATWZ(void *arg){ + char buf[32] = {0}; + char *copy = buf; + int i = 0; + int len = 0; + printf("[ATWZ]: _AT_WLAN_IWPRIV_\n\r"); + if(!arg){ + printf("[ATWZ]Usage: ATWZ=COMMAND[PARAMETERS]\n\r"); + return; + } + strcpy(copy, arg); + len = strlen(copy); + do{ + if((*(copy+i)=='[')) + *(copy+i)=' '; + if((*(copy+i)==']')||(*(copy+i)=='\0')){ + *(copy+i)='\0'; + break; + } + }while((i++) < len); + wext_private_command(WLAN0_NAME, copy, 1); +} + +void print_wlan_help(void *arg){ + printf("\n\rWLAN AT COMMAND SET:"); + printf("\n\r=============================="); + printf("\n\r1. Wlan Scan for Network Access Point"); + printf("\n\r # ATWS"); + printf("\n\r2. Connect to an AES AP"); + printf("\n\r # ATW0=SSID"); + printf("\n\r # ATW1=PASSPHRASE"); + printf("\n\r # ATWC"); + printf("\n\r3. Create an AES AP"); + printf("\n\r # ATW3=SSID"); + printf("\n\r # ATW4=PASSPHRASE"); + printf("\n\r # ATW5=CHANNEL"); + printf("\n\r # ATWA"); + printf("\n\r4. Ping"); + printf("\n\r # ATWI=xxx.xxx.xxx.xxx"); +} + +log_item_t at_wifi_items[ ] = { + {"ATW0", fATW0,}, + {"ATW1", fATW1,}, + {"ATW2", fATW2,}, + {"ATW3", fATW3,}, + {"ATW4", fATW4,}, + {"ATW5", fATW5,}, + {"ATW6", fATW6,}, + {"ATWA", fATWA,}, +#ifdef CONFIG_CONCURRENT_MODE + {"ATWB", fATWB,}, +#endif + {"ATWC", fATWC,}, + {"ATWD", fATWD,}, + {"ATWP", fATWP,}, + {"ATWR", fATWR,}, + {"ATWS", fATWS,}, +#if SCAN_WITH_SSID + {"ATWs", fATWs,}, +#endif + {"ATWM", fATWM,}, + {"ATWZ", fATWZ,}, +#if CONFIG_OTA_UPDATE + {"ATWO", fATWO,}, +#endif +#if CONFIG_WEBSERVER + {"ATWE", fATWE,}, +#endif +#if (CONFIG_INCLUDE_SIMPLE_CONFIG) + {"ATWQ", fATWQ,}, +#endif +#ifdef CONFIG_WPS +#if CONFIG_ENABLE_WPS + {"ATWW", fATWW,}, +#endif + {"ATWw", fATWw,}, //wps registrar for softap +#if CONFIG_ENABLE_P2P + {"ATWG", fATWG,}, //p2p start + {"ATWH", fATWH,}, //p2p stop + {"ATWJ", fATWJ,}, //p2p connect + {"ATWK", fATWK,}, //p2p disconnect + {"ATWN", fATWN,}, //p2p info + {"ATWF", fATWF,}, //p2p find +#endif +#endif +#if CONFIG_SSL_CLIENT + {"ATWL", fATWL,}, +#endif +#if CONFIG_LWIP_LAYER + {"ATWI", fATWI,}, +#if CONFIG_BSD_TCP + {"ATWT", fATWT,}, + {"ATWU", fATWU,}, +#endif +#endif + {"ATW?", fATWx,}, + {"ATW+ABC", fATWx,} +}; + +void at_wifi_init(void) +{ + init_wifi_struct(); + log_service_add_table(at_wifi_items, sizeof(at_wifi_items)/sizeof(at_wifi_items[0])); +} + +log_module_init(at_wifi_init); + +#endif // end of #if CONFIG_WLAN +#endif //end of #if SUPPORT_LOG_SERVICE diff --git a/component/common/api/at_cmd/atcmd_wifi.h b/component/common/api/at_cmd/atcmd_wifi.h new file mode 100644 index 0000000..8e05312 --- /dev/null +++ b/component/common/api/at_cmd/atcmd_wifi.h @@ -0,0 +1,67 @@ +#ifndef __ATCMD_WIFI_H__ +#define __ATCMD_WIFI_H__ +#include "main.h" +#ifndef WLAN0_NAME + #define WLAN0_NAME "wlan0" +#endif +#ifndef WLAN1_NAME + #define WLAN1_NAME "wlan1" +#endif +/* Give default value if not defined */ +#ifndef NET_IF_NUM +#ifdef CONFIG_CONCURRENT_MODE +#define NET_IF_NUM 2 +#else +#define NET_IF_NUM 1 +#endif +#endif + +/*Static IP ADDRESS*/ +#ifndef IP_ADDR0 +#define IP_ADDR0 192 +#define IP_ADDR1 168 +#define IP_ADDR2 1 +#define IP_ADDR3 80 +#endif + +/*NETMASK*/ +#ifndef NETMASK_ADDR0 +#define NETMASK_ADDR0 255 +#define NETMASK_ADDR1 255 +#define NETMASK_ADDR2 255 +#define NETMASK_ADDR3 0 +#endif + +/*Gateway Address*/ +#ifndef GW_ADDR0 +#define GW_ADDR0 192 +#define GW_ADDR1 168 +#define GW_ADDR2 1 +#define GW_ADDR3 1 +#endif + +/*Static IP ADDRESS*/ +#ifndef AP_IP_ADDR0 +#define AP_IP_ADDR0 192 +#define AP_IP_ADDR1 168 +#define AP_IP_ADDR2 43 +#define AP_IP_ADDR3 1 +#endif + +/*NETMASK*/ +#ifndef AP_NETMASK_ADDR0 +#define AP_NETMASK_ADDR0 255 +#define AP_NETMASK_ADDR1 255 +#define AP_NETMASK_ADDR2 255 +#define AP_NETMASK_ADDR3 0 +#endif + +/*Gateway Address*/ +#ifndef AP_GW_ADDR0 +#define AP_GW_ADDR0 192 +#define AP_GW_ADDR1 168 +#define AP_GW_ADDR2 43 +#define AP_GW_ADDR3 1 +#endif + +#endif diff --git a/component/common/api/at_cmd/log_service.c b/component/common/api/at_cmd/log_service.c new file mode 100644 index 0000000..85e29ab --- /dev/null +++ b/component/common/api/at_cmd/log_service.c @@ -0,0 +1,323 @@ +#include +#include +#include +#include "FreeRTOS.h" +#if defined(configUSE_WAKELOCK_PMU) && (configUSE_WAKELOCK_PMU == 1) +#include "freertos_pmu.h" +#endif +#include "log_service.h" +#include "task.h" +#include "semphr.h" +#include "main.h" +#include "wifi_util.h" + +#if SUPPORT_LOG_SERVICE +//====================================================== +struct list_head log_hash[ATC_INDEX_NUM]; + +extern void at_wifi_init(void); +extern void at_fs_init(void); +extern void at_sys_init(void); +//extern void at_app_init(void); +char log_buf[LOG_SERVICE_BUFLEN]; +#if CONFIG_LOG_HISTORY +char log_history[LOG_HISTORY_LEN][LOG_SERVICE_BUFLEN]; +static unsigned int log_history_count = 0; +#endif +xSemaphoreHandle log_rx_interrupt_sema = NULL; +extern xSemaphoreHandle uart_rx_interrupt_sema; + +#if defined (__ICCARM__) +#pragma section=".data.log_init" + +unsigned int __log_init_begin__; +unsigned int __log_init_end__; +#elif defined ( __CC_ARM ) +//#pragma section=".data.log_init" +log_init_t* __log_init_begin__; +log_init_t* __log_init_end__; +log_init_t log_init_table[] = { + at_wifi_init, + at_fs_init, + at_sys_init +// at_app_init +}; +#else +#error "not implement, add to linker script" +extern unsigned int __log_init_begin__; +extern unsigned int __log_init_end__; +#endif + +//====================================================== +int hash_index(char *str) +{ + unsigned int seed = 131; // 31 131 1313 13131 131313 etc.. + unsigned int hash = 0; + + while (*str) + { + hash = hash * seed + (*str++); + } + + return (hash & 0x7FFFFFFF); +} + +void log_add_new_command(log_item_t *new) +{ + int index = hash_index(new->log_cmd)%ATC_INDEX_NUM; + + list_add(&new->node, &log_hash[index]); +} +void start_log_service(void); +void log_service_init(void) +{ + int i; + +#if defined (__ICCARM__) + log_init_t *log_init_table; + __log_init_begin__ = (unsigned int)__section_begin(".data.log_init"); + __log_init_end__ = (unsigned int)__section_end(".data.log_init"); + log_init_table = (log_init_t *)__log_init_begin__; +#elif defined(__CC_ARM) + __log_init_begin__ = log_init_table; + __log_init_end__ = log_init_table + sizeof(log_init_table); +#else + #error "not implement" +#endif + + + for(i=0;ilog_cmd, cmd) == 0){ + //printf("%s match %s, search cnt %d\n\r", cmd, item->log_cmd, search_cnt); + act = (void*)item->at_act; + break; + } + } + + return act; +} + +void* log_handler(char *cmd) +{ + log_act_t action=NULL; + char buf[100] = {0}; + char *copy=buf; + char *token = NULL; + char *param = NULL; + char tok[5] = {0};//'\0' +#if CONFIG_LOG_HISTORY + strcpy(log_history[((log_history_count++)%LOG_HISTORY_LEN)], log_buf); +#endif + strcpy(copy, cmd); + //token = _strsep(©, "="); + token = strtok(copy, "="); + if(token && (strlen(token) <= 4)) + strcpy(tok, token); + else{ + //printf("\n\rAT Cmd format error!\n"); + return NULL; + }; + //printf(" Command %s \n\r ", tok); + param = strtok(NULL, NULL); + //printf(" Param %s \n\r", param); + action = (log_act_t)log_action(tok); + + if(action){ + action(param); + } + return (void*)action; + +} + +int parse_param(char *buf, char **argv) +{ + int argc = 1; + while((argc < MAX_ARGC) && (*buf != '\0')) { + while((*buf == '[')||(*buf == ' ')) + buf ++; + if((*buf == ']')||(*buf == '\0')) + break; + argv[argc] = buf; + argc ++; + buf ++; + + while((*buf != ',')&&(*buf != '[')&&(*buf != ']')&&(*buf != '\0')) + buf ++; + + while((*buf == ',')||(*buf == '[')||(*buf == ']')) { + *buf = '\0'; + buf ++; + } + } + return argc; +} + +void at_set_debug_level(unsigned char newDbgLevel) +{ + gDbgLevel = newDbgLevel; +} + +void at_set_debug_mask(unsigned int newDbgFlag) +{ + gDbgFlag = newDbgFlag; +} + +#if SUPPORT_INTERACTIVE_MODE +extern char uart_buf[64]; +void legency_interactive_handler(unsigned char argc, unsigned char **argv) +{ +#if 0 //defined(CONFIG_PLATFORM_8195A) + if(argc<1) + { + DiagPrintf("Wrong argument number!\r\n"); + return; + } + + + DiagPrintf("Wlan Normal Mode\n"); + + WlanNormal( argc, argv); +#else + strncpy(uart_buf, log_buf, 63);//uart_buf[64] + xSemaphoreGive(uart_rx_interrupt_sema); +#endif +} +#endif + +#if CONFIG_WLAN +#ifndef WLAN0_NAME + #define WLAN0_NAME "wlan0" +#endif +#ifndef WLAN1_NAME + #define WLAN1_NAME "wlan1" +#endif +int mp_commnad_handler(char *cmd) +{ + char buf[64] = {0}; + char *token = NULL; + + strcpy(buf, cmd); + token = strtok(buf, " "); + if(token && (strcmp(buf, "iwpriv") == 0)){ + token = strtok(NULL, ""); + wext_private_command(WLAN0_NAME, token, 1); + return 0; + } + return -1; +} +#endif +void print_help_msg(void){ +#if CONFIG_WLAN +extern void print_wlan_help(void); + print_wlan_help(); +#endif +//add other help message print here +} + +int print_help_handler(char *cmd){ + if(strcmp(cmd, "help") == 0){ + print_help_msg(); + return 0; + } + return -1; +} + +void log_service(void *param) +{ + printf("\n\rStart LOG SERVICE MODE\n\r"); + printf("\n\r# "); + while(1){ + while(xSemaphoreTake(log_rx_interrupt_sema, portMAX_DELAY) != pdTRUE); + if(log_handler((char *)log_buf) == NULL){ +#if CONFIG_WLAN + if(mp_commnad_handler((char *)log_buf) < 0) +#endif + { + #if SUPPORT_INTERACTIVE_MODE + print_help_handler((char *)log_buf); + legency_interactive_handler(NULL, NULL); + continue; + #else + if(print_help_handler((char *)log_buf) < 0){ + printf("\n\runknown command '%s'", log_buf); + } + #endif + } + } + log_buf[0] = '\0'; + printf("\n\r[MEM] After do cmd, available heap %d\n\r", xPortGetFreeHeapSize()); + printf("\r\n\n# "); +#if defined(configUSE_WAKELOCK_PMU) && (configUSE_WAKELOCK_PMU == 1) + release_wakelock(WAKELOCK_LOGUART); +#endif + } +} + +#define STACKSIZE 1280 +void start_log_service(void) +{ + if(xTaskCreate(log_service, (char const*)"log_service", STACKSIZE, NULL, tskIDLE_PRIORITY + 5, NULL) != pdPASS) + printf("\n\r%s xTaskCreate failed", __FUNCTION__); +} +void fAT_exit(void *arg){ + printf("\n\rLeave LOG SERVICE"); + vTaskDelete(NULL); +} +#if CONFIG_LOG_HISTORY +void fAT_log(void *arg){ + int i = 0; + printf("[AT]log history:\n\n\r"); + if(log_history_count > LOG_HISTORY_LEN){ + for(i=0; i<4; i++) + printf(" %s\n\r", log_history[((log_history_count+i)%LOG_HISTORY_LEN)]); + } + else{ + for(i=0; i<(log_history_count-1); i++) + printf(" %s\n\r", log_history[i]); + } +} +#endif +log_item_t at_log_items[ ] = { + {"AT--", fAT_exit,}, +#if CONFIG_LOG_HISTORY + {"AT??", fAT_log,}, +#endif + {"ATxx", fAT_exit,} +}; +void at_log_init(void) +{ + log_service_add_table(at_log_items, sizeof(at_log_items)/sizeof(at_log_items[0])); +} +log_module_init(at_log_init); +#endif \ No newline at end of file diff --git a/component/common/api/at_cmd/log_service.h b/component/common/api/at_cmd/log_service.h new file mode 100644 index 0000000..2a27fee --- /dev/null +++ b/component/common/api/at_cmd/log_service.h @@ -0,0 +1,95 @@ +#ifndef LOG_SERVICE_H +#define LOG_SERVICE_H + +#include "dlist.h" +/* + * Include user defined options first. Anything not defined in these files + * will be set to standard values. Override anything you dont like! + */ + #if defined(CONFIG_PLATFORM_8195A) || defined(CONFIG_PLATFORM_8711B) +#include "platform_opts.h" +#endif + +#ifdef __ICCARM__ +#define STRINGIFY(s) #s +#define SECTION(_name) _Pragma( STRINGIFY(location=##_name##)) +#define log_module_init(fn) \ + SECTION(".data.log_init") __root static void* log_##fn = (void*)fn +#elif defined(__CC_ARM) +#define log_module_init(fn) \ +static void* log_##fn __attribute__((section(".data.log_init"))) = (void*)fn; +#define DiagPrintf printf +#else +#error "not implement" +#endif + +#define ATC_INDEX_NUM 32 + +#ifndef SUPPORT_LOG_SERVICE +#define SUPPORT_LOG_SERVICE 1 +#endif + +#if SUPPORT_LOG_SERVICE + +//LOG_SERVICE_BUFLEN: default, only 63 bytes could be used for keeping input +// cmd, the last byte is for string end ('\0'). +#ifndef LOG_SERVICE_BUFLEN +#define LOG_SERVICE_BUFLEN 64 +#endif + +#ifndef CONFIG_LOG_HISTORY +#define CONFIG_LOG_HISTORY 0 +#if CONFIG_LOG_HISTORY +#define LOG_HISTORY_LEN 5 +#endif +#endif //#ifndef CONFIG_LOG_HISTORY + +#ifndef MAX_ARGC +#define MAX_ARGC 6 +#endif + +#define AT_BIT(n) (1< + +/* Give default value if not defined */ +#ifndef NET_IF_NUM +#ifdef CONFIG_CONCURRENT_MODE +#define NET_IF_NUM 2 +#else +#define NET_IF_NUM 1 +#endif +#endif + +/*Static IP ADDRESS*/ +#ifndef IP_ADDR0 +#define IP_ADDR0 192 +#define IP_ADDR1 168 +#define IP_ADDR2 1 +#define IP_ADDR3 80 +#endif + +/*NETMASK*/ +#ifndef NETMASK_ADDR0 +#define NETMASK_ADDR0 255 +#define NETMASK_ADDR1 255 +#define NETMASK_ADDR2 255 +#define NETMASK_ADDR3 0 +#endif + +/*Gateway Address*/ +#ifndef GW_ADDR0 +#define GW_ADDR0 192 +#define GW_ADDR1 168 +#define GW_ADDR2 1 +#define GW_ADDR3 1 +#endif + +/*Static IP ADDRESS*/ +#ifndef AP_IP_ADDR0 +#define AP_IP_ADDR0 192 +#define AP_IP_ADDR1 168 +#define AP_IP_ADDR2 43 +#define AP_IP_ADDR3 1 +#endif + +/*NETMASK*/ +#ifndef AP_NETMASK_ADDR0 +#define AP_NETMASK_ADDR0 255 +#define AP_NETMASK_ADDR1 255 +#define AP_NETMASK_ADDR2 255 +#define AP_NETMASK_ADDR3 0 +#endif + +/*Gateway Address*/ +#ifndef AP_GW_ADDR0 +#define AP_GW_ADDR0 192 +#define AP_GW_ADDR1 168 +#define AP_GW_ADDR2 43 +#define AP_GW_ADDR3 1 +#endif + +_WEAK void user_wifi_beacon_hdl( char* buf, int buf_len, int flags, void* userdata) { + //printf("Beacon!\n"); +} + +/* Private define ------------------------------------------------------------*/ +#define MAX_DHCP_TRIES 5 + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ + +struct netif xnetif[NET_IF_NUM]; /* network interface structure */ +/* Private functions ---------------------------------------------------------*/ +/** + * @brief Initializes the lwIP stack + * @param None + * @retval None + */ +void LwIP_Init(void) +{ + struct ip_addr ipaddr; + struct ip_addr netmask; + struct ip_addr gw; + int8_t idx = 0; + /* Create tcp_ip stack thread */ + tcpip_init( NULL, NULL ); + + /* - netif_add(struct netif *netif, struct ip_addr *ipaddr, + struct ip_addr *netmask, struct ip_addr *gw, + void *state, err_t (* init)(struct netif *netif), + err_t (* input)(struct pbuf *p, struct netif *netif)) + + Adds your network interface to the netif_list. Allocate a struct + netif and pass a pointer to this structure as the first argument. + Give pointers to cleared ip_addr structures when using DHCP, + or fill them with sane numbers otherwise. The state pointer may be NULL. + + The init function pointer must point to a initialization function for + your ethernet netif interface. The following code illustrates it's use.*/ + //printf("NET_IF_NUM:%d\n\r",NET_IF_NUM); + for(idx=NET_IF_NUM - 1;idx>=0;idx--){ + if(idx==0){ + IP4_ADDR(&ipaddr, IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3); + IP4_ADDR(&netmask, NETMASK_ADDR0, NETMASK_ADDR1 , NETMASK_ADDR2, NETMASK_ADDR3); + IP4_ADDR(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3); + } + else{ + IP4_ADDR(&ipaddr, AP_IP_ADDR0, AP_IP_ADDR1, AP_IP_ADDR2, AP_IP_ADDR3); + IP4_ADDR(&netmask, AP_NETMASK_ADDR0, AP_NETMASK_ADDR1 , AP_NETMASK_ADDR2, AP_NETMASK_ADDR3); + IP4_ADDR(&gw, AP_GW_ADDR0, AP_GW_ADDR1, AP_GW_ADDR2, AP_GW_ADDR3); + } + xnetif[idx].name[0] = 'r'; + xnetif[idx].name[1] = '0'+idx; + netif_add(&xnetif[idx], &ipaddr, &netmask, &gw, NULL, ðernetif_init, &tcpip_input); + } + + /* Registers the default network interface. */ + netif_set_default(&xnetif[0]); + + /* When the netif is fully configured this function must be called.*/ + for(idx = 0;idx < NET_IF_NUM;idx++) + netif_set_up(&xnetif[idx]); +} + +/** + * @brief LwIP_DHCP_Process_Handle + * @param None + * @retval None + */ +uint8_t LwIP_DHCP(uint8_t idx, uint8_t dhcp_state) +{ + struct ip_addr ipaddr; + struct ip_addr netmask; + struct ip_addr gw; + uint32_t IPaddress; + uint8_t iptab[4]; + uint8_t DHCP_state; + int mscnt = 0; + struct netif *pnetif = NULL; + + DHCP_state = dhcp_state; + + if(idx > 1) + idx = 1; + pnetif = &xnetif[idx]; + if(DHCP_state == 0){ + pnetif->ip_addr.addr = 0; + pnetif->netmask.addr = 0; + pnetif->gw.addr = 0; + } + + for (;;) + { + //printf("\n\r ========DHCP_state:%d============\n\r",DHCP_state); + switch (DHCP_state) + { + case DHCP_START: + { + wifi_unreg_event_handler(WIFI_EVENT_BEACON_AFTER_DHCP, user_wifi_beacon_hdl); + dhcp_start(pnetif); + IPaddress = 0; + DHCP_state = DHCP_WAIT_ADDRESS; + } + break; + + case DHCP_WAIT_ADDRESS: + { + /* Read the new IP address */ + IPaddress = pnetif->ip_addr.addr; + + if (IPaddress!=0) + { + DHCP_state = DHCP_ADDRESS_ASSIGNED; + + wifi_reg_event_handler(WIFI_EVENT_BEACON_AFTER_DHCP, user_wifi_beacon_hdl, NULL); + + + /* Stop DHCP */ + dhcp_stop(pnetif); + + iptab[0] = (uint8_t)(IPaddress >> 24); + iptab[1] = (uint8_t)(IPaddress >> 16); + iptab[2] = (uint8_t)(IPaddress >> 8); + iptab[3] = (uint8_t)(IPaddress); + printf("\n\rIP address : %d.%d.%d.%d", iptab[3], iptab[2], iptab[1], iptab[0]); + return DHCP_ADDRESS_ASSIGNED; + } + else + { + /* DHCP timeout */ + if (pnetif->dhcp->tries > MAX_DHCP_TRIES) + { + DHCP_state = DHCP_TIMEOUT; + + /* Stop DHCP */ + dhcp_stop(pnetif); + + /* Static address used */ + IP4_ADDR(&ipaddr, IP_ADDR0 ,IP_ADDR1 , IP_ADDR2 , IP_ADDR3 ); + IP4_ADDR(&netmask, NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3); + IP4_ADDR(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3); + netif_set_addr(pnetif, &ipaddr , &netmask, &gw); + + iptab[0] = IP_ADDR3; + iptab[1] = IP_ADDR2; + iptab[2] = IP_ADDR1; + iptab[3] = IP_ADDR0; + printf("\n\rDHCP timeout"); + printf("\n\rStatic IP address : %d.%d.%d.%d", iptab[3], iptab[2], iptab[1], iptab[0]); + + return DHCP_TIMEOUT; + }else + { + //sys_msleep(DHCP_FINE_TIMER_MSECS); + vTaskDelay(DHCP_FINE_TIMER_MSECS); + dhcp_fine_tmr(); + mscnt += DHCP_FINE_TIMER_MSECS; + if (mscnt >= DHCP_COARSE_TIMER_SECS*1000) + { + dhcp_coarse_tmr(); + mscnt = 0; + } + } + } + } + break; + case DHCP_RELEASE_IP: + wifi_unreg_event_handler(WIFI_EVENT_BEACON_AFTER_DHCP, user_wifi_beacon_hdl); + printf("\n\rLwIP_DHCP: Release ip"); + dhcp_release_unicast(pnetif); + return DHCP_RELEASE_IP; + case DHCP_STOP: + wifi_unreg_event_handler(WIFI_EVENT_BEACON_AFTER_DHCP, user_wifi_beacon_hdl); + printf("\n\rLwIP_DHCP: dhcp stop."); + dhcp_stop(pnetif); + return DHCP_STOP; + default: + break; + } + + } +} + +uint8_t* LwIP_GetMAC(struct netif *pnetif) +{ + return (uint8_t *) (pnetif->hwaddr); +} + +uint8_t* LwIP_GetIP(struct netif *pnetif) +{ + return (uint8_t *) &(pnetif->ip_addr); +} + +uint8_t* LwIP_GetGW(struct netif *pnetif) +{ + return (uint8_t *) &(pnetif->gw); +} + +uint8_t* LwIP_GetMASK(struct netif *pnetif) +{ + return (uint8_t *) &(pnetif->netmask); +} + +uint8_t* LwIP_GetBC(struct netif *pnetif) +{ + return (uint8_t *) &(pnetif->dhcp->offered_bc_addr); +} + +#if LWIP_DNS +void LwIP_GetDNS(struct ip_addr* dns) +{ + *dns = dns_getserver(0); +} + +void LwIP_SetDNS(struct ip_addr* dns) +{ + dns_setserver(0, dns); +} +#endif +void LwIP_UseStaticIP(struct netif *pnetif) +{ + struct ip_addr ipaddr; + struct ip_addr netmask; + struct ip_addr gw; + + /* Static address used */ + if(pnetif->name[1] == '0'){ + IP4_ADDR(&ipaddr, IP_ADDR0 ,IP_ADDR1 , IP_ADDR2 , IP_ADDR3 ); + IP4_ADDR(&netmask, NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3); + IP4_ADDR(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3); + }else{ + IP4_ADDR(&ipaddr, AP_IP_ADDR0, AP_IP_ADDR1, AP_IP_ADDR2, AP_IP_ADDR3); + IP4_ADDR(&netmask, AP_NETMASK_ADDR0, AP_NETMASK_ADDR1 , AP_NETMASK_ADDR2, AP_NETMASK_ADDR3); + IP4_ADDR(&gw, AP_GW_ADDR0, AP_GW_ADDR1, AP_GW_ADDR2, AP_GW_ADDR3); + } + + netif_set_addr(pnetif, &ipaddr , &netmask, &gw); +} +#if LWIP_AUTOIP +#include + +void LwIP_AUTOIP(struct netif *pnetif) +{ + uint8_t *ip = LwIP_GetIP(pnetif); + + autoip_start(pnetif); + + while((pnetif->autoip->state == AUTOIP_STATE_PROBING) || (pnetif->autoip->state == AUTOIP_STATE_ANNOUNCING)) { + vTaskDelay(1000); + } + + if(*((uint32_t *) ip) == 0) { + struct ip_addr ipaddr; + struct ip_addr netmask; + struct ip_addr gw; + + printf("AUTOIP timeout\n"); + + /* Static address used */ + IP4_ADDR(&ipaddr, IP_ADDR0 ,IP_ADDR1 , IP_ADDR2 , IP_ADDR3 ); + IP4_ADDR(&netmask, NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3); + IP4_ADDR(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3); + netif_set_addr(pnetif, &ipaddr , &netmask, &gw); + printf("Static IP address : %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]); + } + else { + printf("\nLink-local address: %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]); + } +} +#endif +#if LWIP_IPV6 +void LwIP_AUTOIP_IPv6(struct netif *pnetif) +{ + uint8_t *ipv6 = (uint8_t *) &(pnetif->ip6_addr[0].addr[0]); + + netif_create_ip6_linklocal_address(pnetif, 1); + netif_ip6_addr_set_state(pnetif, 0, IP6_ADDR_TENTATIVE); + printf("\nIPv6 link-local address: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\n", + ipv6[0], ipv6[1], ipv6[2], ipv6[3], ipv6[4], ipv6[5], ipv6[6], ipv6[7], + ipv6[8], ipv6[9], ipv6[10], ipv6[11], ipv6[12], ipv6[13], ipv6[14], ipv6[15]); +} +#endif diff --git a/component/common/api/lwip_netconf.h b/component/common/api/lwip_netconf.h new file mode 100644 index 0000000..cfec88a --- /dev/null +++ b/component/common/api/lwip_netconf.h @@ -0,0 +1,74 @@ +/** + ****************************************************************************** + * @file netconf.h + * @author MCD Application Team + * @version V1.1.0 + * @date 07-October-2011 + * @brief This file contains all the functions prototypes for the netconf.c + * file. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __NETCONF_H +#define __NETCONF_H + +#ifdef __cplusplus + extern "C" { +#endif + +#include "tcpip.h" +/* Includes ------------------------------------------------------------------*/ +#include +/* Private typedef -----------------------------------------------------------*/ +typedef enum +{ + DHCP_START=0, + DHCP_WAIT_ADDRESS, + DHCP_ADDRESS_ASSIGNED, + DHCP_RELEASE_IP, + DHCP_STOP, + DHCP_TIMEOUT +} DHCP_State_TypeDef; + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions ------------------------------------------------------- */ +void LwIP_Init(void); +uint8_t LwIP_DHCP(uint8_t idx, uint8_t dhcp_state); +unsigned char* LwIP_GetMAC(struct netif *pnetif); +unsigned char* LwIP_GetIP(struct netif *pnetif); +unsigned char* LwIP_GetGW(struct netif *pnetif); +uint8_t* LwIP_GetMASK(struct netif *pnetif); +uint8_t* LwIP_GetBC(struct netif *pnetif); +#if LWIP_DNS +void LwIP_GetDNS(struct ip_addr* dns); +void LwIP_SetDNS(struct ip_addr* dns); +#endif +void LwIP_UseStaticIP(struct netif *pnetif); +#if LWIP_AUTOIP +void LwIP_AUTOIP(struct netif *pnetif); +#endif +#if LWIP_IPV6 +void LwIP_AUTOIP_IPv6(struct netif *pnetif); +#endif +#ifdef __cplusplus +} +#endif + +#endif /* __NETCONF_H */ + + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/component/common/api/network/include/lwipopts.h b/component/common/api/network/include/lwipopts.h new file mode 100644 index 0000000..d704f8d --- /dev/null +++ b/component/common/api/network/include/lwipopts.h @@ -0,0 +1,236 @@ +/** + ****************************************************************************** + * @file lwipopts.h + * @author MCD Application Team + * @version V1.1.0 + * @date 07-October-2011 + * @brief lwIP Options Configuration. + * This file is based on Utilities\lwip_v1.3.2\src\include\lwip\opt.h + * and contains the lwIP configuration for the STM32F2x7 demonstration. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +#ifndef __LWIPOPTS_H__ +#define __LWIPOPTS_H__ + +#include + +/** + * SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain + * critical regions during buffer allocation, deallocation and memory + * allocation and deallocation. + */ +#define SYS_LIGHTWEIGHT_PROT 1 + +/* Define LWIP_COMPAT_MUTEX if the port has no mutexes and binary semaphores + should be used instead */ +#define LWIP_COMPAT_MUTEX 1 + +#define ETHARP_TRUST_IP_MAC 0 +#define IP_REASSEMBLY 1 +#define IP_FRAG 1 +#define ARP_QUEUEING 0 + +/** + * NO_SYS==1: Provides VERY minimal functionality. Otherwise, + * use lwIP facilities. + */ +#define NO_SYS 0 + +/* ---------- Memory options ---------- */ +/* MEM_ALIGNMENT: should be set to the alignment of the CPU for which + lwIP is compiled. 4 byte alignment -> define MEM_ALIGNMENT to 4, 2 + byte alignment -> define MEM_ALIGNMENT to 2. */ +#define MEM_ALIGNMENT 4 + +/* MEM_SIZE: the size of the heap memory. If the application will send +a lot of data that needs to be copied, this should be set high. */ +#define MEM_SIZE (5*1024) + +/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application + sends a lot of data out of ROM (or other static memory), this + should be set high. */ +#define MEMP_NUM_PBUF 100 +/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One + per active UDP "connection". */ +#define MEMP_NUM_UDP_PCB 6 +/* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP + connections. */ +#define MEMP_NUM_TCP_PCB 10 +/* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP + connections. */ +#define MEMP_NUM_TCP_PCB_LISTEN 5 +/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP + segments. */ +#define MEMP_NUM_TCP_SEG 20 +/* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active + timeouts. */ +#define MEMP_NUM_SYS_TIMEOUT 10 + + +/* ---------- Pbuf options ---------- */ +/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */ +#define PBUF_POOL_SIZE 20 + +/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */ +#define PBUF_POOL_BUFSIZE 500 + + +/* ---------- TCP options ---------- */ +#define LWIP_TCP 1 +#define TCP_TTL 255 + +/* Controls if TCP should queue segments that arrive out of + order. Define to 0 if your device is low on memory. */ +#define TCP_QUEUE_OOSEQ 1 + +/* TCP Maximum segment size. */ +#define TCP_MSS (1500 - 40) /* TCP_MSS = (Ethernet MTU - IP header size - TCP header size) */ + +/* TCP sender buffer space (bytes). */ +#define TCP_SND_BUF (5*TCP_MSS) + +/* TCP_SND_QUEUELEN: TCP sender buffer space (pbufs). This must be at least + as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. */ + +#define TCP_SND_QUEUELEN (4* TCP_SND_BUF/TCP_MSS) + +/* TCP receive window. */ +#define TCP_WND (2*TCP_MSS) + + +/* ---------- ICMP options ---------- */ +#define LWIP_ICMP 1 + +/* ---------- ARP options ----------- */ +#define LWIP_ARP 1 + +/* ---------- DHCP options ---------- */ +/* Define LWIP_DHCP to 1 if you want DHCP configuration of + interfaces. DHCP is not implemented in lwIP 0.5.1, however, so + turning this on does currently not work. */ +#define LWIP_DHCP 1 + + +/* ---------- UDP options ---------- */ +#define LWIP_UDP 1 +#define UDP_TTL 255 + + +/* ---------- UPNP options --------- */ +#define LWIP_UPNP 0 + +/* Support Multicast */ +#define LWIP_IGMP 0 +#define LWIP_RAND() rand() + +#define LWIP_TCP_DELAY_DISABLE 0 + +/* ---------- Statistics options ---------- */ +#define LWIP_STATS 0 +#define LWIP_PROVIDE_ERRNO 1 + + +/* + -------------------------------------- + ---------- Checksum options ---------- + -------------------------------------- +*/ + +/* +The STM32F2x7 allows computing and verifying the IP, UDP, TCP and ICMP checksums by hardware: + - To use this feature let the following define uncommented. + - To disable it and process by CPU comment the the checksum. +*/ +//Do checksum by lwip - WLAN nic does not support Checksum offload +//#define CHECKSUM_BY_HARDWARE + + +#ifdef CHECKSUM_BY_HARDWARE + /* CHECKSUM_GEN_IP==0: Generate checksums by hardware for outgoing IP packets.*/ + #define CHECKSUM_GEN_IP 0 + /* CHECKSUM_GEN_UDP==0: Generate checksums by hardware for outgoing UDP packets.*/ + #define CHECKSUM_GEN_UDP 0 + /* CHECKSUM_GEN_TCP==0: Generate checksums by hardware for outgoing TCP packets.*/ + #define CHECKSUM_GEN_TCP 0 + /* CHECKSUM_CHECK_IP==0: Check checksums by hardware for incoming IP packets.*/ + #define CHECKSUM_CHECK_IP 0 + /* CHECKSUM_CHECK_UDP==0: Check checksums by hardware for incoming UDP packets.*/ + #define CHECKSUM_CHECK_UDP 0 + /* CHECKSUM_CHECK_TCP==0: Check checksums by hardware for incoming TCP packets.*/ + #define CHECKSUM_CHECK_TCP 0 +#else + /* CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets.*/ + #define CHECKSUM_GEN_IP 1 + /* CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets.*/ + #define CHECKSUM_GEN_UDP 1 + /* CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets.*/ + #define CHECKSUM_GEN_TCP 1 + /* CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets.*/ + #define CHECKSUM_CHECK_IP 1 + /* CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets.*/ + #define CHECKSUM_CHECK_UDP 1 + /* CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets.*/ + #define CHECKSUM_CHECK_TCP 1 +#endif + + +/* + ---------------------------------------------- + ---------- Sequential layer options ---------- + ---------------------------------------------- +*/ +/** + * LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c) + */ +#define LWIP_NETCONN 1 + +/* + ------------------------------------ + ---------- Socket options ---------- + ------------------------------------ +*/ +/** + * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c) + */ +#define LWIP_SOCKET 1 + +/* + ----------------------------------- + ---------- DEBUG options ---------- + ----------------------------------- +*/ + +#define LWIP_DEBUG 0 + + +/* + --------------------------------- + ---------- OS options ---------- + --------------------------------- +*/ + +#define TCPIP_THREAD_STACKSIZE 1000 +#define TCPIP_MBOX_SIZE 5 +#define DEFAULT_UDP_RECVMBOX_SIZE 2000 +#define DEFAULT_TCP_RECVMBOX_SIZE 2000 +#define DEFAULT_ACCEPTMBOX_SIZE 2000 +#define DEFAULT_THREAD_STACKSIZE 500 +#define TCPIP_THREAD_PRIO (configMAX_PRIORITIES - 2) + + + +#endif /* __LWIPOPTS_H__ */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/component/common/api/network/include/main.h b/component/common/api/network/include/main.h new file mode 100644 index 0000000..7c352c0 --- /dev/null +++ b/component/common/api/network/include/main.h @@ -0,0 +1,68 @@ +#ifndef MAIN_H +#define MAIN_H + +#include + +#define CONFIG_WLAN 1 + + +/* Header file declaration*/ +void wlan_network(); + + +/* Interactive Mode */ +#define SERIAL_DEBUG_RX 1 +#if defined(__ICCARM__) +static +#endif +char uart_buf[64]; + + +/* WLAN and Netork */ +#define STA_MODE_SSID "ap" /* Set SSID here */ +#define AP_MODE_SSID "wlan_ap_ssid" /* Set SSID here */ +#define AP_DEFAULT_CH 6 +#define WLAN0_NAME "wlan0" +#define WLAN1_NAME "wlan1" +#define WPA_PASSPHRASE "1234567890" /* Max 32 cahracters */ +#define WEP40_KEY {0x12, 0x34, 0x56, 0x78, 0x90} + +/*Static IP ADDRESS*/ +#define IP_ADDR0 192 +#define IP_ADDR1 168 +#define IP_ADDR2 1 +#define IP_ADDR3 80 + +/*NETMASK*/ +#define NETMASK_ADDR0 255 +#define NETMASK_ADDR1 255 +#define NETMASK_ADDR2 255 +#define NETMASK_ADDR3 0 + +/*Gateway Address*/ +#define GW_ADDR0 192 +#define GW_ADDR1 168 +#define GW_ADDR2 1 +#define GW_ADDR3 1 + +/*******************************************/ + +/*Static IP ADDRESS*/ +#define AP_IP_ADDR0 192 +#define AP_IP_ADDR1 168 +#define AP_IP_ADDR2 43 +#define AP_IP_ADDR3 1 + +/*NETMASK*/ +#define AP_NETMASK_ADDR0 255 +#define AP_NETMASK_ADDR1 255 +#define AP_NETMASK_ADDR2 255 +#define AP_NETMASK_ADDR3 0 + +/*Gateway Address*/ +#define AP_GW_ADDR0 192 +#define AP_GW_ADDR1 168 +#define AP_GW_ADDR2 43 +#define AP_GW_ADDR3 1 + +#endif diff --git a/component/common/api/network/include/main_test.h b/component/common/api/network/include/main_test.h new file mode 100644 index 0000000..c9f3227 --- /dev/null +++ b/component/common/api/network/include/main_test.h @@ -0,0 +1,21 @@ +//----------------------------------------------------------------------------// +#ifndef __MAIN_TEST_H +#define __MAIN_TEST_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Exported test functions ------------------------------------------------------- */ +void do_ping_test(char *ip, int size, int count, int interval); +void do_ping_call(char *ip, int loop, int count); +void interactive_question(char *question, char *choice, char *buf, int buf_size); +void start_interactive_mode(void); + +#ifdef __cplusplus + } +#endif + +#endif // __MAIN_TEST_H + +//----------------------------------------------------------------------------// diff --git a/component/common/api/network/include/netconf.h b/component/common/api/network/include/netconf.h new file mode 100644 index 0000000..600cd06 --- /dev/null +++ b/component/common/api/network/include/netconf.h @@ -0,0 +1,50 @@ +/** + ****************************************************************************** + * @file netconf.h + * @author MCD Application Team + * @version V1.1.0 + * @date 07-October-2011 + * @brief This file contains all the functions prototypes for the netconf.c + * file. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __NETCONF_H +#define __NETCONF_H + +#ifdef __cplusplus + extern "C" { +#endif + +// TODO: remove this file +#include "lwip_netconf.h" +#if 0 +/* Includes ------------------------------------------------------------------*/ +#include "main.h" +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions ------------------------------------------------------- */ +void LwIP_Init(void); +void LwIP_DHCP(void); +#endif +#ifdef __cplusplus +} +#endif + +#endif /* __NETCONF_H */ + + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/component/common/api/network/include/rtl8195a_it.h b/component/common/api/network/include/rtl8195a_it.h new file mode 100644 index 0000000..8d5cf19 --- /dev/null +++ b/component/common/api/network/include/rtl8195a_it.h @@ -0,0 +1,8 @@ + +#ifndef __RTL8195A_IT_H_ +#define __RTL8195A_IT_H_ + + +int irq_alloc_wlan(void *contex); + +#endif //__RTL8195A_IT_H_ \ No newline at end of file diff --git a/component/common/api/network/include/util.h b/component/common/api/network/include/util.h new file mode 100644 index 0000000..9af5cbc --- /dev/null +++ b/component/common/api/network/include/util.h @@ -0,0 +1,47 @@ +#ifndef _UTIL_H +#define _UTIL_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#include "wifi_util.h" +#if 0 +typedef enum _WIFI_EVENT_INDICATE{ + WIFI_EVENT_CONNECT = 0, + WIFI_EVENT_DISCONNECT = 1, + WIFI_EVENT_FOURWAY_HANDSHAKE_DONE = 2, +}WIFI_EVENT_INDICATE; + +int wext_get_ssid(const char *ifname, __u8 *ssid); +int wext_set_ssid(const char *ifname, const __u8 *ssid, __u16 ssid_len); +int wext_set_auth_param(const char *ifname, __u16 idx, __u32 value); +int wext_set_key_ext(const char *ifname, __u16 alg, const __u8 *addr, int key_idx, int set_tx, const __u8 *seq, __u16 seq_len, __u8 *key, __u16 key_len); +int wext_get_enc_ext(const char *ifname, __u16 *alg); +int wext_set_passphrase(const char *ifname, const __u8 *passphrase, __u16 passphrase_len); +int wext_get_passphrase(const char *ifname, __u8 *passphrase); +int wext_disconnect(const char *ifname); +int wext_set_mode(const char *ifname, int mode); +int wext_get_mode(const char *ifname, int *mode); +int wext_set_ap_ssid(const char *ifname, const __u8 *ssid, __u16 ssid_len); +int wext_set_country(const char *ifname, char *country_code); +int wext_get_rssi(const char *ifname, int *rssi); +int wext_set_channel(const char *ifname, __u8 ch); +int wext_get_channel(const char *ifname, __u8 *ch); +int wext_set_scan(const char *ifname, char *buf, __u16 buf_len); +int wext_get_scan(const char *ifname, char *buf, __u16 buf_len); +int wext_mp_command(const char *ifname, char *cmd, int show_msg); +int wext_wifi_priv(const char *ifname, int argc, char **argv); +void wext_wlan_indicate(unsigned int cmd, union iwreq_data *wrqu, char *extra); +#endif + +#define wext_handshake_done rltk_wlan_handshake_done + +#ifdef __cplusplus +} +#endif + +#endif /* _UTIL_H */ diff --git a/component/common/api/network/include/wificonf.h b/component/common/api/network/include/wificonf.h new file mode 100644 index 0000000..0538016 --- /dev/null +++ b/component/common/api/network/include/wificonf.h @@ -0,0 +1,88 @@ +//----------------------------------------------------------------------------// +#ifndef __WIFICONF_H +#define __WIFICONF_H + +#ifdef __cplusplus + extern "C" { +#endif + +#include "main.h" +#include "util.h" + +typedef enum _WIFI_SECURITY_TYPE{ + WIFI_SECURITY_OPEN = 0, + WIFI_SECURITY_WEP, + WIFI_SECURITY_WPA, + WIFI_SECURITY_WPA2 +}WIFI_SECURITY_TYPE; + +typedef enum _WIFI_COUNTRY_CODE{ + WIFI_COUNTRY_US = 0, + WIFI_COUNTRY_EU, + WIFI_COUNTRY_JP, + WIFI_COUNTRY_CN +}WIFI_COUNTRY_CODE; + +typedef enum _WIFI_MODE_TYPE{ + WIFI_MODE_STA = 0, + WIFI_MODE_AP +}WIFI_MODE_TYPE; + +typedef enum _WIFI_LINK_STATUS{ + WIFI_LINK_DISCONNECTED = 0, + WIFI_LINK_CONNECTED +}WIFI_LINK_STATUS; + +typedef struct _WIFI_AP{ + unsigned char *ssid; + WIFI_SECURITY_TYPE security_type; + unsigned char *password; + int ssid_len; + int password_len; + int channel; +}WIFI_AP; + +typedef struct _WIFI_NETWORK{ + unsigned char *ssid; + WIFI_SECURITY_TYPE security_type; + unsigned char *password; + int ssid_len; + int password_len; + int key_id; +}WIFI_NETWORK; + +typedef struct _WIFI_SETTING{ + WIFI_MODE_TYPE mode; + unsigned char ssid[33]; + unsigned char channel; + WIFI_SECURITY_TYPE security_type; + unsigned char password[33]; +}WIFI_SETTING; + +typedef enum _WIFI_NETWORK_MODE { + WIFI_NETWORK_B = 1, + WIFI_NETWORK_BG = 3, + WIFI_NETWORK_BGN = 11 +} WIFI_NETWORK_MODE; + +int wifi_connect(WIFI_NETWORK *pNetwork); +int wifi_disconnect(void); +WIFI_LINK_STATUS wifi_get_connect_status(WIFI_NETWORK *pWifi); +int wifi_set_country(WIFI_COUNTRY_CODE country_code); +int wifi_get_rssi(int *pRSSI); +int wifi_rf_on(void); +int wifi_rf_off(void); +int wifi_active_ap(WIFI_AP *pAP); +int wifi_scan(char *buf, int buf_len); +int wifi_get_setting(WIFI_SETTING *pSetting); +int wifi_show_setting(WIFI_SETTING *pSetting); +int wifi_set_network_mode(WIFI_NETWORK_MODE mode); +void wifi_indication( WIFI_EVENT_INDICATE event, char *buf, int buf_len); + +#ifdef __cplusplus + } +#endif + +#endif // __WIFICONF_H + +//----------------------------------------------------------------------------// diff --git a/component/common/api/network/src/ping_test.c b/component/common/api/network/src/ping_test.c new file mode 100644 index 0000000..887d129 --- /dev/null +++ b/component/common/api/network/src/ping_test.c @@ -0,0 +1,136 @@ +#include "FreeRTOS.h" +#include "task.h" +#include "main.h" + +#include +#include +#include +#include +#include + +#include "diag.h" + +//#define PING_IP "192.168.0.1" +#define PING_IP "192.168.159.1" +#define PING_TO 1000 +#define PING_ID 0xABCD +#define BUF_SIZE 200 +#define STACKSIZE 1024 + +static unsigned short ping_seq = 0; +static int infinite_loop, ping_count, data_size, ping_interval, ping_call; +static char ping_ip[16]; + +static void generate_ping_echo(unsigned char *buf, int size) +{ + int i; + struct icmp_echo_hdr *pecho; + + for(i = 0; i < size; i ++) { + buf[sizeof(struct icmp_echo_hdr) + i] = (unsigned char) i; + } + + pecho = (struct icmp_echo_hdr *) buf; + ICMPH_TYPE_SET(pecho, ICMP_ECHO); + ICMPH_CODE_SET(pecho, 0); + pecho->chksum = 0; + pecho->id = PING_ID; + pecho->seqno = htons(++ ping_seq); + + //Checksum includes icmp header and data. Need to calculate after fill up icmp header + pecho->chksum = inet_chksum(pecho, sizeof(struct icmp_echo_hdr) + size); +} + +void ping_test(void *param) +//void ping_test() +{ + int i, ping_socket; + int pint_timeout = PING_TO; + struct sockaddr_in to_addr, from_addr; + int from_addr_len; + int ping_size, reply_size; + unsigned char ping_buf[BUF_SIZE], reply_buf[BUF_SIZE]; + unsigned int ping_time, reply_time; + struct ip_hdr *iphdr; + struct icmp_echo_hdr *pecho; + + //Ping size = icmp header(8 bytes) + data size + ping_size = sizeof(struct icmp_echo_hdr) + data_size; + printf("\n\r[%s] PING %s %d(%d) bytes of data\n", __FUNCTION__, ping_ip, data_size, sizeof(struct ip_hdr) + sizeof(struct icmp_echo_hdr) + data_size); + + for(i = 0; (i < ping_count) || (infinite_loop == 1); i ++) { + ping_socket = socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP); + setsockopt(ping_socket, SOL_SOCKET, SO_RCVTIMEO, &pint_timeout, sizeof(pint_timeout)); + + to_addr.sin_len = sizeof(to_addr); + to_addr.sin_family = AF_INET; + to_addr.sin_addr.s_addr = inet_addr(ping_ip); + + generate_ping_echo(ping_buf, data_size); + sendto(ping_socket, ping_buf, ping_size, 0, (struct sockaddr *) &to_addr, sizeof(to_addr)); + + ping_time = xTaskGetTickCount(); + if((reply_size = recvfrom(ping_socket, reply_buf, sizeof(reply_buf), 0, (struct sockaddr *) &from_addr, (socklen_t *) &from_addr_len)) + >= (int)(sizeof(struct ip_hdr) + sizeof(struct icmp_echo_hdr))) { + + reply_time = xTaskGetTickCount(); + iphdr = (struct ip_hdr *)reply_buf; + pecho = (struct icmp_echo_hdr *)(reply_buf + (IPH_HL(iphdr) * 4)); + + if((pecho->id == PING_ID) && (pecho->seqno == htons(ping_seq))) { + printf("\n\r[%s] %d bytes from %s: icmp_seq=%d time=%d ms", __FUNCTION__, reply_size - sizeof(struct ip_hdr), inet_ntoa(from_addr.sin_addr), htons(pecho->seqno), (reply_time - ping_time) * portTICK_RATE_MS); + } + } + else + printf("\n\r[%s] Request timeout for icmp_seq %d\n", __FUNCTION__, ping_seq); + + close(ping_socket); + vTaskDelay(ping_interval * configTICK_RATE_HZ); + } + + if(!ping_call) + vTaskDelete(NULL); +} + +void do_ping_call(char *ip, int loop, int count) +{ + ping_call = 1; + ping_seq = 0; + data_size = 120; + ping_interval = 1; + infinite_loop = loop; + ping_count = count; + strcpy(ping_ip, ip); + + ping_test(NULL); +} + +void do_ping_test(char *ip, int size, int count, int interval) +{ + if((sizeof(struct icmp_echo_hdr) + size) > BUF_SIZE) { + printf("\n\r%s BUF_SIZE(%d) is too small", __FUNCTION__, BUF_SIZE); + return; + } + + if(ip == NULL) + strcpy(ping_ip, PING_IP); + else + strcpy(ping_ip, ip); + + ping_call = 0; + ping_seq = 0; + data_size = size; + ping_interval = interval; + + if(count == 0) { + infinite_loop = 1; + ping_count = 0; + } + else { + infinite_loop = 0; + ping_count = count; + } + + if(xTaskCreate(ping_test, ((const signed char*)"ping_test"), STACKSIZE, NULL, tskIDLE_PRIORITY + 1, NULL) != pdPASS) + printf("\n\r%s xTaskCreate failed", __FUNCTION__); +} diff --git a/component/common/api/network/src/rtl8195a_it.c b/component/common/api/network/src/rtl8195a_it.c new file mode 100644 index 0000000..91c0667 --- /dev/null +++ b/component/common/api/network/src/rtl8195a_it.c @@ -0,0 +1,110 @@ +#include "rtl8195a.h" +#include +#include "rtl8195a_it.h" + +/* os dependent*/ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "semphr.h" + + +#include +#define printf DiagPrintf + +/*-----------------------------Global Variable ---------------------*/ +//#ifdef CONFIG_WLAN +//#ifdef CONFIG_ISR_THREAD_MODE_INTERRUPT +extern xSemaphoreHandle *pExportWlanIrqSemaphore; +//#endif +//#endif + + +#ifdef CONFIG_WLAN +#ifdef CONFIG_ISR_THREAD_MODE_INTERRUPT + +//TODO: chris +#define IRQ_HANDLED 1 +#define IRQ_NONE 0 + +int wlan_Interrupt ( + IN VOID* Data +) +{ +#if 1 + + portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; + + printf("wlan interrupt\n"); + /* This semaphore is initialized once wlan interrupt handler thread is created and initialized*/ + if(!pExportWlanIrqSemaphore) + { + printf("%s(%d)\n", __FUNCTION__, __LINE__); + goto exit; + } + + printf("%s(%d)\n", __FUNCTION__, __LINE__); + xSemaphoreGiveFromISR( *pExportWlanIrqSemaphore, &xHigherPriorityTaskWoken ); + + printf("%s(%d)\n", __FUNCTION__, __LINE__); + /* Switch tasks if necessary. */ + if( xHigherPriorityTaskWoken != pdFALSE ) + { + printf("%s(%d)\n", __FUNCTION__, __LINE__); + portEND_SWITCHING_ISR( xHigherPriorityTaskWoken ); + } + +exit: + + return IRQ_HANDLED; +#else + struct dvobj_priv *dvobj = (struct dvobj_priv *)Data; + _adapter *adapter = dvobj->if1; + DBG_8192C("Dma isr\n"); + + if (dvobj->irq_enabled == 0) { + return IRQ_HANDLED; + } +DBG_871X("%s(%d)\n", __FUNCTION__, __LINE__); + if(rtw_hal_interrupt_handler(adapter) == _FAIL) + return IRQ_HANDLED; + //return IRQ_NONE; +DBG_871X("%s(%d)\n", __FUNCTION__, __LINE__); + return IRQ_HANDLED; +#endif + +} + + +VOID +lextra_bus_dma_Interrupt ( + IN VOID* Data +); + + +/* + * This function register interrupt handler and is called by wlan driver + * Return 0 if success, Others if fail + */ + +int irq_alloc_wlan(void *contex) +{ + int ret = 0; + IRQ_HANDLE IrqHandle = {0}; + + printf("Register Interrupt\n"); + IrqHandle.Data = (u32) (contex); + IrqHandle.IrqNum = WL_DMA_IRQ; + IrqHandle.IrqFun = (IRQ_FUN)wlan_Interrupt; + //IrqHandle.IrqFun = (IRQ_FUN)lextra_bus_dma_Interrupt; + IrqHandle.Priority = 0; + + InterruptRegister(&IrqHandle); + InterruptEn(&IrqHandle); + + return ret; + +} +#endif +#endif + diff --git a/component/common/api/network/src/wlan_network.c b/component/common/api/network/src/wlan_network.c new file mode 100644 index 0000000..ac66aea --- /dev/null +++ b/component/common/api/network/src/wlan_network.c @@ -0,0 +1,65 @@ +/* + * Hello World + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#include "FreeRTOS.h" +#include "task.h" +#include "semphr.h" + +#include "main.h" +#include "main_test.h" +#include "wifi_conf.h" +#include "wlan_intf.h" +#include "lwip_netconf.h" +#include "wifi_constants.h" + +#include + +#ifndef CONFIG_INIT_NET +#define CONFIG_INIT_NET 1 +#endif +#ifndef CONFIG_INTERACTIVE_MODE +#define CONFIG_INTERACTIVE_MODE 1 +#endif + +#define STACKSIZE (512 + 768) + +xSemaphoreHandle uart_rx_interrupt_sema = NULL; + +void init_thread(void *param) +{ + +#if CONFIG_INIT_NET +#if CONFIG_LWIP_LAYER + /* Initilaize the LwIP stack */ + LwIP_Init(); +#endif +#endif + +#if CONFIG_WLAN + wifi_on(RTW_MODE_STA); + + printf("\n\r%s(%d), Available heap 0x%x", __FUNCTION__, __LINE__, xPortGetFreeHeapSize()); +#endif + +#if CONFIG_INTERACTIVE_MODE + /* Initial uart rx swmaphore*/ + vSemaphoreCreateBinary(uart_rx_interrupt_sema); + xSemaphoreTake(uart_rx_interrupt_sema, 1/portTICK_RATE_MS); + start_interactive_mode(); +#endif + + /* Kill init thread after all init tasks done */ + vTaskDelete(NULL); +} + +void wlan_network() +{ + if(xTaskCreate(init_thread, ((const char*)"init"), STACKSIZE, NULL, tskIDLE_PRIORITY + 3 + PRIORITIE_OFFSET, NULL) != pdPASS) + printf("\n\r%s xTaskCreate(init_thread) failed", __FUNCTION__); +} diff --git a/component/common/api/platform/dlist.h b/component/common/api/platform/dlist.h new file mode 100644 index 0000000..28ec5a8 --- /dev/null +++ b/component/common/api/platform/dlist.h @@ -0,0 +1,250 @@ +#ifndef __LIST_H +#define __LIST_H + +#if defined ( __CC_ARM ) +#ifndef inline +#define inline __inline +#endif +#endif + +/* This file is from Linux Kernel (include/linux/list.h) + * and modified by simply removing hardware prefetching of list items. + * Here by copyright, credits attributed to wherever they belong. + * Kulesh Shanmugasundaram (kulesh [squiggly] isis.poly.edu) + */ + +/* + * Simple doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +struct list_head { + struct list_head *next, *prev; +}; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +#define INIT_LIST_HEAD(ptr) do { \ + (ptr)->next = (ptr); (ptr)->prev = (ptr); \ +} while (0) + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_add(struct list_head *new, + struct list_head *prev, + struct list_head *next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/** + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_del(struct list_head *prev, struct list_head *next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty on entry does not return true after this, the entry is in an undefined state. + */ +static inline void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + entry->next = (void *) 0; + entry->prev = (void *) 0; +} + +/** + * list_del_init - deletes entry from list and reinitialize it. + * @entry: the element to delete from the list. + */ +static inline void list_del_init(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + INIT_LIST_HEAD(entry); +} + +/** + * list_move - delete from one list and add as another's head + * @list: the entry to move + * @head: the head that will precede our entry + */ +static inline void list_move(struct list_head *list, struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add(list, head); +} + +/** + * list_move_tail - delete from one list and add as another's tail + * @list: the entry to move + * @head: the head that will follow our entry + */ +static inline void list_move_tail(struct list_head *list, + struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add_tail(list, head); +} + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_empty(struct list_head *head) +{ + return head->next == head; +} + +static inline void __list_splice(struct list_head *list, + struct list_head *head) +{ + struct list_head *first = list->next; + struct list_head *last = list->prev; + struct list_head *at = head->next; + + first->prev = head; + head->next = first; + + last->next = at; + at->prev = last; +} + +/** + * list_splice - join two lists + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static inline void list_splice(struct list_head *list, struct list_head *head) +{ + if (!list_empty(list)) + __list_splice(list, head); +} + +/** + * list_splice_init - join two lists and reinitialise the emptied list. + * @list: the new list to add. + * @head: the place to add it in the first list. + * + * The list at @list is reinitialised + */ +static inline void list_splice_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head); + INIT_LIST_HEAD(list); + } +} + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#define list_entry(ptr, type, member) \ + ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) + +/** + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); \ + pos = pos->next) +/** + * list_for_each_prev - iterate over a list backwards + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each_prev(pos, head) \ + for (pos = (head)->prev; pos != (head); \ + pos = pos->prev) + +/** + * list_for_each_safe - iterate over a list safe against removal of list entry + * @pos: the &struct list_head to use as a loop counter. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +/** + * list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +/** + * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop counter. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + + +#endif diff --git a/component/common/api/platform/platform_stdlib.h b/component/common/api/platform/platform_stdlib.h new file mode 100644 index 0000000..e53c0ca --- /dev/null +++ b/component/common/api/platform/platform_stdlib.h @@ -0,0 +1,145 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2014 Realtek Corporation. All rights reserved. + * + * + ******************************************************************************/ +#ifndef __PLATFORM_STDLIB_H__ +#define __PLATFORM_STDLIB_H__ + +#define USE_CLIB_PATCH 0 +#if defined (__GNUC__) +#define USE_RTL_ROM_CLIB 0 +#else +#define USE_RTL_ROM_CLIB 1 +#endif + +#if defined(CONFIG_PLATFORM_8195A) || defined(CONFIG_PLATFORM_8711B) +#if defined (__IARSTDLIB__) + #include + #include + #include + #include + #include "diag.h" + + #define strsep(str, delim) _strsep(str, delim) +#else + #include + #include + #include + #include "diag.h" + #include "strproc.h" + #include "basic_types.h" + #include "hal_misc.h" + #if USE_RTL_ROM_CLIB + #include "rtl_lib.h" + #endif + + #undef printf + #undef sprintf + #undef snprintf + #undef atoi + #undef memcmp + #undef memcpy + #undef memset + #undef strcmp + #undef strcpy + #undef strlen + #undef strncmp + #undef strncpy + #undef strsep + #undef strtok + #if USE_RTL_ROM_CLIB + #undef memchr + #undef memmove + #undef strcat + #undef strchr + #undef strncat + #undef strstr + #endif + + #if USE_RTL_ROM_CLIB + #define printf rtl_printf + #define sprintf rtl_sprintf + #define snprintf rtl_snprintf + #define memchr rtl_memchr + #define memcmp rtl_memcmp + #define memcpy rtl_memcpy + #define memmove rtl_memmove + #define memset rtl_memset + #define strcat rtl_strcat + #define strchr rtl_strchr + #define strcmp(s1, s2) rtl_strcmp((const char *)s1, (const char *)s2) + #define strcpy rtl_strcpy + #define strlen(str) rtl_strlen((const char *)str) + #define strncat rtl_strncat + #define strncmp(s1, s2, n) rtl_strncmp((const char *)s1, (const char *)s2, n) + #define strncpy rtl_strncpy + #define strstr rtl_strstr + #define strsep rtl_strsep + #define strtok rtl_strtok + #else + #if USE_CLIB_PATCH + extern int DiagSscanfPatch(const char *buf, const char *fmt, ...); + extern char* DiagStrtokPatch(char *str, const char* delim); + extern char* DiagStrstrPatch(char *string, char *substring); + extern int DiagSnPrintfPatch(char *buf, size_t size, const char *fmt, ...); + extern u32 DiagPrintfPatch(const char *fmt, ...); + extern u32 DiagSPrintfPatch(u8 *buf, const char *fmt, ...); + #define printf DiagPrintfPatch + #define sprintf DiagSPrintfPatch + #define snprintf DiagSnPrintfPatch + #define strstr(a, b) DiagStrstrPatch((char *)(a), (char *)(b)) + #define strtok DiagStrtokPatch + #else + #define printf DiagPrintf + #define sprintf(fmt, arg...) DiagSPrintf((u8*)fmt, ##arg) + #if defined (__GNUC__) + #define snprintf DiagSnPrintf // NULL function + #define strstr(str1, str2) prvStrStr(str1, str2) // NULL function + #endif + #define strtok(str, delim) _strsep(str, delim) + #endif + #define memcmp(dst, src, sz) _memcmp(dst, src, sz) + #define memcpy(dst, src, sz) _memcpy(dst, src, sz) + #define memset(dst, val, sz) _memset(dst, val, sz) + #define strchr(s, c) _strchr(s, c) // for B-cut ROM + #define strcmp(str1, str2) prvStrCmp((const unsigned char *) str1, (const unsigned char *) str2) + #define strcpy(dest, src) _strcpy(dest, src) + #define strlen(str) prvStrLen((const unsigned char *) str) + #define strncmp(str1, str2, cnt) _strncmp(str1, str2, cnt) + #define strncpy(dest, src, count) _strncpy(dest, src, count) + #define strsep(str, delim) _strsep(str, delim) + #endif + + #define atoi(str) prvAtoi(str) + #define strpbrk(cs, ct) _strpbrk(cs, ct) // for B-cut ROM + + #if USE_CLIB_PATCH + #undef sscanf + #define sscanf DiagSscanfPatch + #else + #if defined (__GNUC__) + #undef sscanf + #define sscanf _sscanf + #endif + #endif +#endif // defined (__IARSTDLIB__) + +// +// memory management +// +extern void *pvPortMalloc( size_t xWantedSize ); +extern void vPortFree( void *pv ); +#define malloc pvPortMalloc +#define free vPortFree + +#elif defined(USE_STM322xG_EVAL) || defined(USE_STM324xG_EVAL) || defined(STM32F10X_XL) + #include + #include + #include + #include +#endif + + +#endif //__PLATFORM_STDLIB_H__ diff --git a/component/common/api/platform/stdlib_patch.c b/component/common/api/platform/stdlib_patch.c new file mode 100644 index 0000000..c86f4f9 --- /dev/null +++ b/component/common/api/platform/stdlib_patch.c @@ -0,0 +1,846 @@ + + +#include +#include +#include +#include + + +#define DiagPutChar HalSerialPutcRtl8195a + + + +#define u32 unsigned int +#define IN +#define u8 unsigned char +#define s16 signed short int +#define u16 unsigned short int +typedef signed int s32; +typedef unsigned char bool; +typedef unsigned long long u64; +typedef signed long long s64; +#define SIZE_T unsigned int + + + + + +#define in_range(c, lo, up) ((u8)c >= lo && (u8)c <= up) +#define isprint(c) in_range(c, 0x20, 0x7f) +#define isdigit(c) in_range(c, '0', '9') +#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F')) +#define islower(c) in_range(c, 'a', 'z') +#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v' || c == ',') +#define ULLONG_MAX (~0ULL) +#define USHRT_MAX ((u16)(~0U)) +#define KSTRTOX_OVERFLOW (1U << 31) +#define SHRT_MAX ((s16)(USHRT_MAX>>1)) + +static inline char _tolower(const char c) +{ + return c | 0x20; +} + + +extern s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder); +extern s64 div_s64(s64 dividend, s32 divisor); +extern inline char _tolower(const char c); +extern u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder); +extern u64 div_u64(u64 dividend, u32 divisor); +extern unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long *p); +extern const char *_parse_integer_fixup_radix(const char *s, unsigned int *base); +extern char *skip_spaces(const char *str); +extern int skip_atoi(const char **s); + + +static unsigned long long simple_strtoull_patch(const char *cp, char **endp, unsigned int base) +{ + unsigned long long result; + unsigned int rv; + + cp = _parse_integer_fixup_radix(cp, &base); + rv = _parse_integer(cp, base, &result); + + +//troy delete + /* FIXME */ +// cp += (rv & ~KSTRTOX_OVERFLOW); +// if(endp) +// *endp = (char *)cp; + + return result; +} + +static long long simple_strtoll_patch(const char *cp, char **endp, unsigned int base) +{ + if(*cp == '-') + return -simple_strtoull_patch(cp + 1, endp, base); + + return simple_strtoull_patch(cp, endp, base); +} +static unsigned long simple_strtoul_patch(const char *cp, char **endp, unsigned int base) +{ + return simple_strtoull_patch(cp, endp, base); +} + +static long simple_strtol_patch(const char *cp, char **endp, unsigned int base) +{ + if(*cp == '-') + return -simple_strtoul_patch(cp + 1, endp, base); + + return simple_strtoul_patch(cp, endp, base); +} + + + + +static int judge_digit_width(const char *str) +{ + + int width = 0; + while(isxdigit(*str)) { + width++; + str++; + } + return width; +} + + +static int _vsscanf_patch(const char *buf, const char *fmt, va_list args) +{ + const char *str = buf; + char *next; + char digit; + int num = 0; + int i =0; + u8 qualifier; + unsigned int base; + union { + long long s; + unsigned long long u; + } val; + s16 field_width; + bool is_sign; + + char str_store[20] = {0}; + + + + while(*fmt) { + /* skip any white space in format */ + /* white space in format matchs any amount of + * white space, including none, in the input. + */ + if(isspace(*fmt)) { + fmt = skip_spaces(++fmt); + str = skip_spaces(str); + } + + /* anything that is not a conversion must match exactly */ + if(*fmt != '%' && *fmt) { + if(*fmt++ != *str++) { + break; + } + + continue; + } + + if(!*fmt) { + break; + } + + ++fmt; + + /* skip this conversion. + * advance both strings to next white space + */ + if(*fmt == '*') { + if(!*str) { + break; + } + + while(!isspace(*fmt) && *fmt != '%' && *fmt) + fmt++; + + while(!isspace(*str) && *str) + str++; + + continue; + } + + /* get field width */ + field_width = -1; + + if(isdigit(*fmt)) { + + field_width = skip_atoi(&fmt); + + + + if(field_width <= 0) { + + break; + } + } + + /* get conversion qualifier */ + qualifier = -1; + + if(*fmt == 'h' || _tolower(*fmt) == 'l' || + _tolower(*fmt) == 'z') { + qualifier = *fmt++; + + if(qualifier == *fmt) { + if(qualifier == 'h') { + qualifier = 'H'; + fmt++; + } else if(qualifier == 'l') { + qualifier = 'L'; + fmt++; + } + } + } + + if(!*fmt) { + break; + } + + if(*fmt == 'n') { + /* return number of characters read so far */ + *va_arg(args, int *) = str - buf; + ++fmt; + continue; + } + + if(!*str) { + break; + } + + base = 10; + is_sign = 0; + + switch(*fmt++) { + case 'c': { + char *s = (char *)va_arg(args, char*); + + if(field_width == -1) + field_width = 1; + + do { + *s++ = *str++; + } while(--field_width > 0 && *str); + + num++; + } + + continue; + + case 's': { + char *s = (char *)va_arg(args, char *); + + if(field_width == -1) + field_width = SHRT_MAX; + + /* first, skip leading white space in buffer */ + str = skip_spaces(str); + + /* now copy until next white space */ + while(*str && !isspace(*str) && field_width--) { + *s++ = *str++; + } + + *s = '\0'; + num++; + } + + continue; + + case 'o': + base = 8; + break; + + case 'x': + case 'X': + base = 16; + break; + + case 'i': + base = 0; + + case 'd': + is_sign = 1; + + case 'u': + break; + + case '%': + + /* looking for '%' in str */ + if(*str++ != '%') { + return num; + } + + continue; + + default: + /* invalid format; stop here */ + return num; + } + + /* have some sort of integer conversion. + * first, skip white space in buffer. + */ + str = skip_spaces(str); + + digit = *str; + + if(is_sign && digit == '-') + digit = *(str + 1); + + if(!digit + || (base == 16 && !isxdigit(digit)) + || (base == 10 && !isdigit(digit)) + || (base == 8 && (!isdigit(digit) || digit > '7')) + || (base == 0 && !isdigit(digit))) { + break; + } + + //here problem ******************************************* + + + + //troy add ,fix support %2d, but not support %d + if(field_width <= 0) { + + field_width = judge_digit_width(str); + } + + + /////troy add, fix str passed inwidth wrong + for(i = 0; i 0 && next - str > field_width) { + if(base == 0) + _parse_integer_fixup_radix(str, &base); + + while(next - str > field_width) { + if(is_sign) { + val.s = div_s64(val.s, base); + } else { + val.u = div_u64(val.u, base); + } + + --next; + } + } + + switch(qualifier) { + case 'H': /* that's 'hh' in format */ + if(is_sign) + *va_arg(args, signed char *) = val.s; + else + *va_arg(args, unsigned char *) = val.u; + + break; + + case 'h': + if(is_sign) + *va_arg(args, short *) = val.s; + else + *va_arg(args, unsigned short *) = val.u; + + break; + + case 'l': + if(is_sign) + *va_arg(args, long *) = val.s; + else + *va_arg(args, unsigned long *) = val.u; + + break; + + case 'L': + if(is_sign) + *va_arg(args, long long *) = val.s; + else + *va_arg(args, unsigned long long *) = val.u; + + break; + + case 'Z': + case 'z': + *va_arg(args, size_t *) = val.u; + break; + + default: + if(is_sign) + *va_arg(args, int *) = val.s; + else + *va_arg(args, unsigned int *) = val.u; + + break; + } + + num++; + + if(!next) { + break; + } + + str = next; + } + + return num; +} + + +int DiagSscanfPatch(const char *buf, const char *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i = _vsscanf_patch(buf, fmt, args); + va_end(args); + + return i; +} + + + +/*********************************************************/ + + + +char* DiagStrtokPatch(char *str, const char* delim) { + static char* _buffer; + if(str != NULL) _buffer = str; + if(_buffer[0] == '\0') return NULL; + + char *ret = _buffer, *b; + const char *d; + + for(b = _buffer; *b !='\0'; b++) { + for(d = delim; *d != '\0'; d++) { + if(*b == *d) { + *b = '\0'; + _buffer = b+1; + + // skip the beginning delimiters + if(b == ret) { + ret++; + continue; + } + return ret; + } + } + } + + return ret; +} + + + +/*********************************************************/ + + + +char *DiagStrstrPatch(char *string, char *substring) +{ + register char *a, *b; + + /* First scan quickly through the two strings looking for a + * single-character match. When it's found, then compare the + * rest of the substring. + */ + + b = substring; + if (*b == 0) { + return string; + } + for ( ; *string != 0; string += 1) { + if (*string != *b) { + continue; + } + a = string; + while (1) { + if (*b == 0) { + return string; + } + if (*a++ != *b++) { + break; + } + } + b = substring; + } + return (char *) 0; +} + + + + + +/*********************************************************/ + + + + +int DiagSnPrintfPatch(char *buf, size_t size, const char *fmt, ...) +{ + + va_list ap; + char *p, *s, *buf_end = NULL; + const int *dp = ((const int *)&fmt)+1; + + if(buf == NULL) + return 0; + + + va_start(ap, fmt); + s = buf; + buf_end = size? (buf + size):(char*)~0; + for ( ; *fmt != '\0'; ++fmt) { + + if (*fmt != '%') { + *s++ = *fmt; + if(s >= buf_end){ + goto Exit; + } + continue; + } + + if (*++fmt == 's') { + for (p = (char *)*dp++; *p != '\0'; p++){ + *s++ = *p; + + if(s >= buf_end){ + goto Exit; + } + } + } + else { /* Length of item is bounded */ + char tmp[20], *q = tmp; + int alt = 0; + int shift = 0;// = 12; + const long *lpforchk = (const long *)dp; + + if ((*lpforchk) < 0x10) { + shift = 0; + } + else if (((*lpforchk) >= 0x10) && ((*lpforchk) < 0x100)) { + shift = 4; + } + else if (((*lpforchk) >= 0x100) && ((*lpforchk) < 0x1000)) { + shift = 8; + } + else if (((*lpforchk) >= 0x1000) && ((*lpforchk) < 0x10000)) { + shift = 12; + } + else if (((*lpforchk) >= 0x10000) && ((*lpforchk) < 0x100000)) { + shift = 16; + } + else if (((*lpforchk) >= 0x100000) && ((*lpforchk) < 0x1000000)) { + shift = 20; + } + else if (((*lpforchk) >= 0x1000000) && ((*lpforchk) < 0x10000000)) { + shift = 24; + } + else if ((*lpforchk) >= 0x10000000) { + shift = 28; + } + else { + shift = 28; + } + + if ((*fmt >= '0') && (*fmt <= '9')) + { + int width; + unsigned char fch = *fmt; + for (width=0; (fch>='0') && (fch<='9'); fch=*++fmt) + { width = width * 10 + fch - '0'; + } + shift=(width-1)*4; + } + + /* + * Before each format q points to tmp buffer + * After each format q points past end of item + */ + if ((*fmt == 'x')||(*fmt == 'X') || (*fmt == 'p') || (*fmt == 'P')) { + /* With x86 gcc, sizeof(long) == sizeof(int) */ + const long *lp = (const long *)dp; + long h = *lp++; + int hex_count = 0; + unsigned long h_back = h; + int ncase = (*fmt & 0x20); + dp = (const int *)lp; + if((*fmt == 'p') || (*fmt == 'P')) + alt=1; + if (alt) { + *q++ = '0'; + *q++ = 'X' | ncase; + } + while (h_back) { + hex_count += (h_back & 0xF) ? 1 : 0; + h_back = h_back >> 4; + } + + if (shift < (hex_count - 1)*4) + shift = (hex_count - 1)*4; + for ( ; shift >= 0; shift -= 4) + *q++ = "0123456789ABCDEF"[(h >> shift) & 0xF] | ncase; + } + else if (*fmt == 'd') { + int i = *dp++; + char *r; + int digit_space = 0; + + + if (i < 0) { + *q++ = '-'; + i = -i; + digit_space++; + } + p = q; /* save beginning of digits */ + + + do { + *q++ = '0' + (i % 10); + i /= 10; + digit_space++; + } while (i); + + + for ( ; shift >= 0; shift -= 4) { + + if(digit_space-- > 0) { + ; //do nothing + } else { + *q++ = '0'; + } + } + + /* reverse digits, stop in middle */ + r = q; /* don't alter q */ + while (--r > p) { + i = *r; + *r = *p; + *p++ = i; + } + } + else if (*fmt == 'c') + *q++ = *dp++; + else + *q++ = *fmt; + /* now output the saved string */ + for (p = tmp; p < q; ++p){ + *s++ = *p; + if(s >= buf_end){ + goto Exit; + } + } + } + } + +Exit: + if (buf) + *s = '\0'; + + va_end(ap); + return(s-buf); + +} + + + + + + +/*********************************************************/ + +static int VSprintfPatch(char *buf, const char *fmt, const int *dp) +{ + char *p, *s; + s = buf; + for ( ; *fmt != '\0'; ++fmt) { + if (*fmt != '%') { + buf ? *s++ = *fmt : DiagPutChar(*fmt); + continue; + } + if (*++fmt == 's') { + for (p = (char *)*dp++; *p != '\0'; p++) + buf ? *s++ = *p : DiagPutChar(*p); + } + else { /* Length of item is bounded */ + char tmp[20], *q = tmp; + int alt = 0; + int shift = 0;// = 12; + const long *lpforchk = (const long *)dp; + + if ((*lpforchk) < 0x10) { + shift = 0; + } + else if (((*lpforchk) >= 0x10) && ((*lpforchk) < 0x100)) { + shift = 4; + } + else if (((*lpforchk) >= 0x100) && ((*lpforchk) < 0x1000)) { + shift = 8; + } + else if (((*lpforchk) >= 0x1000) && ((*lpforchk) < 0x10000)) { + shift = 12; + } + else if (((*lpforchk) >= 0x10000) && ((*lpforchk) < 0x100000)) { + shift = 16; + } + else if (((*lpforchk) >= 0x100000) && ((*lpforchk) < 0x1000000)) { + shift = 20; + } + else if (((*lpforchk) >= 0x1000000) && ((*lpforchk) < 0x10000000)) { + shift = 24; + } + else if ((*lpforchk) >= 0x10000000) { + shift = 28; + } + else { + shift = 28; + } + +#if 1 //wei patch for %02x + if ((*fmt >= '0') && (*fmt <= '9')) + { + int width; + unsigned char fch = *fmt; + for (width=0; (fch>='0') && (fch<='9'); fch=*++fmt) + { width = width * 10 + fch - '0'; + } + shift=(width-1)*4; + } +#endif + + /* + * Before each format q points to tmp buffer + * After each format q points past end of item + */ + + if ((*fmt == 'x')||(*fmt == 'X') || (*fmt == 'p') || (*fmt == 'P')) { + /* With x86 gcc, sizeof(long) == sizeof(int) */ + const long *lp = (const long *)dp; + long h = *lp++; + int hex_count = 0; + unsigned long h_back = h; + int ncase = (*fmt & 0x20); + dp = (const int *)lp; + if((*fmt == 'p') || (*fmt == 'P')) + alt=1; + if (alt) { + *q++ = '0'; + *q++ = 'X' | ncase; + } + //hback 是实际得到的数æ®ï¼Œhex_count是统计数æ®çš„HEX字符个数 + while (h_back) { + hex_count += (h_back & 0xF) ? 1 : 0; + h_back = h_back >> 4; + } + //è¿™é‡Œä¿®å¤ example: 字符有4个,但是用了%02x导致字符被截断的情况 + if (shift < (hex_count - 1)*4) + shift = (hex_count - 1)*4; + //printf("(%d,%d)", hex_count, shift); + + for ( ; shift >= 0; shift -= 4) { + + *q++ = "0123456789ABCDEF"[(h >> shift) & 0xF] | ncase; + } + + } + else if (*fmt == 'd') { + int i = *dp++; + char *r; + int digit_space = 0; + if (i < 0) { + *q++ = '-'; + i = -i; + digit_space++; + } + p = q; /* save beginning of digits */ + do { + *q++ = '0' + (i % 10); + i /= 10; + digit_space++; + } while (i); + //è¿™é‡Œä¿®å¤ example:用了%08dåŽï¼Œåœ¨æ•°å­—å‰é¢æ²¡æœ‰0的情况 + for ( ; shift >= 0; shift -= 4) { + + if(digit_space-- > 0) { + ; //do nothing + } else { + *q++ = '0'; + } + } + /* reverse digits, stop in middle */ + r = q; /* don't alter q */ + while (--r > p) { + i = *r; + *r = *p; + *p++ = i; + } + } + else if (*fmt == 'c') + *q++ = *dp++; + else + *q++ = *fmt; + /* now output the saved string */ + for (p = tmp; p < q; ++p){ + buf ? *s++ = *p : DiagPutChar(*p); + if ((*p) == '\n') { + DiagPutChar('\r'); + } + } + } + } + if (buf) + *s = '\0'; + return (s - buf); +} + + +u32 DiagPrintfPatch( + IN const char *fmt, ... +) +{ + (void)VSprintfPatch(0, fmt, ((const int *)&fmt)+1); + return 1; +} + +u32 DiagSPrintfPatch( + IN u8 *buf, + IN const char *fmt, ... +) +{ + (void)VSprintfPatch((char*)buf, fmt, ((const int *)&fmt)+1); + return 1; +} + + + diff --git a/component/common/api/wifi/rtw_wpa_supplicant/src/utils/os.h b/component/common/api/wifi/rtw_wpa_supplicant/src/utils/os.h new file mode 100644 index 0000000..4cbfb01 --- /dev/null +++ b/component/common/api/wifi/rtw_wpa_supplicant/src/utils/os.h @@ -0,0 +1,578 @@ +/* + * OS specific functions + * Copyright (c) 2005-2009, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef OS_H +#define OS_H + +//#include "basic_types.h" +#include +#include "osdep_service.h" +#include "utils/rom/rom_wps_os.h" + +typedef void* xqueue_handle_t; + +typedef long os_time_t; + +typedef _timer os_timer; + +/** + * os_sleep - Sleep (sec, usec) + * @sec: Number of seconds to sleep + * @usec: Number of microseconds to sleep + */ +void os_sleep(os_time_t sec, os_time_t usec); + +struct os_time { + os_time_t sec; + os_time_t usec; +}; + +struct os_reltime { + os_time_t sec; + os_time_t usec; +}; + +/** + * os_get_time - Get current time (sec, usec) + * @t: Pointer to buffer for the time + * Returns: 0 on success, -1 on failure + */ +int os_get_time(struct os_time *t); + +int os_get_reltime(struct os_reltime *t); +/* Helper macros for handling struct os_time */ +/* (&timeout->time, &tmp->time) */ +#define os_time_before(a, b) \ + ((a)->sec < (b)->sec || \ + ((a)->sec == (b)->sec && (a)->usec < (b)->usec)) + +#define os_time_sub(a, b, res) do { \ + (res)->sec = (a)->sec - (b)->sec; \ + (res)->usec = (a)->usec - (b)->usec; \ + if ((res)->usec < 0) { \ + (res)->sec--; \ + (res)->usec += 1000000; \ + } \ +} while (0) + +/** + * os_mktime - Convert broken-down time into seconds since 1970-01-01 + * @year: Four digit year + * @month: Month (1 .. 12) + * @day: Day of month (1 .. 31) + * @hour: Hour (0 .. 23) + * @min: Minute (0 .. 59) + * @sec: Second (0 .. 60) + * @t: Buffer for returning calendar time representation (seconds since + * 1970-01-01 00:00:00) + * Returns: 0 on success, -1 on failure + * + * Note: The result is in seconds from Epoch, i.e., in UTC, not in local time + * which is used by POSIX mktime(). + */ +int os_mktime(int year, int month, int day, int hour, int min, int sec, + os_time_t *t); + +struct os_tm { + int sec; /* 0..59 or 60 for leap seconds */ + int min; /* 0..59 */ + int hour; /* 0..23 */ + int day; /* 1..31 */ + int month; /* 1..12 */ + int year; /* Four digit year */ +}; + +int os_gmtime(os_time_t t, struct os_tm *tm); + +/* Helpers for handling struct os_time */ + +/* Helpers for handling struct os_reltime */ + +static inline int os_reltime_before(struct os_reltime *a, + struct os_reltime *b) +{ + return os_time_before(a,b); +} + + +static inline void os_reltime_sub(struct os_reltime *a, struct os_reltime *b, + struct os_reltime *res) +{ + os_time_sub(a,b,res); +} + + +static inline void os_reltime_age(struct os_reltime *start, + struct os_reltime *age) +{ + struct os_reltime now; + + os_get_time((struct os_time *)&now); + os_reltime_sub(&now, start, age); +} + + +static inline int os_reltime_expired(struct os_reltime *now, + struct os_reltime *ts, + os_time_t timeout_secs) +{ + struct os_reltime age; + + os_reltime_sub(now, ts, &age); + return (age.sec > timeout_secs) || + (age.sec == timeout_secs && age.usec > 0); +} + +/** + * os_daemonize - Run in the background (detach from the controlling terminal) + * @pid_file: File name to write the process ID to or %NULL to skip this + * Returns: 0 on success, -1 on failure + */ +int os_daemonize(const char *pid_file); + +/** + * os_daemonize_terminate - Stop running in the background (remove pid file) + * @pid_file: File name to write the process ID to or %NULL to skip this + */ +void os_daemonize_terminate(const char *pid_file); + +/** + * os_get_random - Get cryptographically strong pseudo random data + * @buf: Buffer for pseudo random data + * @len: Length of the buffer + * Returns: 0 on success, -1 on failure + */ +int os_get_random(unsigned char *buf, size_t len); + +/** + * os_random - Get pseudo random value (not necessarily very strong) + * Returns: Pseudo random value + */ +unsigned long os_random(void); + +/** + * os_rel2abs_path - Get an absolute path for a file + * @rel_path: Relative path to a file + * Returns: Absolute path for the file or %NULL on failure + * + * This function tries to convert a relative path of a file to an absolute path + * in order for the file to be found even if current working directory has + * changed. The returned value is allocated and caller is responsible for + * freeing it. It is acceptable to just return the same path in an allocated + * buffer, e.g., return strdup(rel_path). This function is only used to find + * configuration files when os_daemonize() may have changed the current working + * directory and relative path would be pointing to a different location. + */ +char * os_rel2abs_path(const char *rel_path); + +/** + * os_program_init - Program initialization (called at start) + * Returns: 0 on success, -1 on failure + * + * This function is called when a programs starts. If there are any OS specific + * processing that is needed, it can be placed here. It is also acceptable to + * just return 0 if not special processing is needed. + */ +int os_program_init(void); + +/** + * os_program_deinit - Program deinitialization (called just before exit) + * + * This function is called just before a program exists. If there are any OS + * specific processing, e.g., freeing resourced allocated in os_program_init(), + * it should be done here. It is also acceptable for this function to do + * nothing. + */ +void os_program_deinit(void); + +/** + * os_setenv - Set environment variable + * @name: Name of the variable + * @value: Value to set to the variable + * @overwrite: Whether existing variable should be overwritten + * Returns: 0 on success, -1 on error + * + * This function is only used for wpa_cli action scripts. OS wrapper does not + * need to implement this if such functionality is not needed. + */ +int os_setenv(const char *name, const char *value, int overwrite); + +/** + * os_unsetenv - Delete environent variable + * @name: Name of the variable + * Returns: 0 on success, -1 on error + * + * This function is only used for wpa_cli action scripts. OS wrapper does not + * need to implement this if such functionality is not needed. + */ +int os_unsetenv(const char *name); + +/** + * os_readfile - Read a file to an allocated memory buffer + * @name: Name of the file to read + * @len: For returning the length of the allocated buffer + * Returns: Pointer to the allocated buffer or %NULL on failure + * + * This function allocates memory and reads the given file to this buffer. Both + * binary and text files can be read with this function. The caller is + * responsible for freeing the returned buffer with os_free(). + */ +char * os_readfile(const char *name, size_t *len); + +#if 0 +/** + * os_zalloc - Allocate and zero memory + * @size: Number of bytes to allocate + * Returns: Pointer to allocated and zeroed memory or %NULL on failure + * + * Caller is responsible for freeing the returned buffer with os_free(). + */ +void * os_zalloc(size_t size); + +/** + * os_calloc - Allocate and zero memory for an array + * @nmemb: Number of members in the array + * @size: Number of bytes in each member + * Returns: Pointer to allocated and zeroed memory or %NULL on failure + * + * This function can be used as a wrapper for os_zalloc(nmemb * size) when an + * allocation is used for an array. The main benefit over os_zalloc() is in + * having an extra check to catch integer overflows in multiplication. + * + * Caller is responsible for freeing the returned buffer with os_free(). + */ +static inline void * os_calloc(size_t nmemb, size_t size) +{ + if (size && nmemb > (~(size_t) 0) / size) + return NULL; + return os_zalloc(nmemb * size); +} +#endif + +/* + * The following functions are wrapper for standard ANSI C or POSIX functions. + * By default, they are just defined to use the standard function name and no + * os_*.c implementation is needed for them. This avoids extra function calls + * by allowing the C pre-processor take care of the function name mapping. + * + * If the target system uses a C library that does not provide these functions, + * build_config.h can be used to define the wrappers to use a different + * function name. This can be done on function-by-function basis since the + * defines here are only used if build_config.h does not define the os_* name. + * If needed, os_*.c file can be used to implement the functions that are not + * included in the C library on the target system. Alternatively, + * OS_NO_C_LIB_DEFINES can be defined to skip all defines here in which case + * these functions need to be implemented in os_*.c file for the target system. + */ + +#ifdef OS_NO_C_LIB_DEFINES + +/** + * os_malloc - Allocate dynamic memory + * @size: Size of the buffer to allocate + * Returns: Allocated buffer or %NULL on failure + * + * Caller is responsible for freeing the returned buffer with os_free(). + */ +void * os_malloc(size_t size); + +/** + * os_realloc - Re-allocate dynamic memory + * @ptr: Old buffer from os_malloc() or os_realloc() + * @size: Size of the new buffer + * Returns: Allocated buffer or %NULL on failure + * + * Caller is responsible for freeing the returned buffer with os_free(). + * If re-allocation fails, %NULL is returned and the original buffer (ptr) is + * not freed and caller is still responsible for freeing it. + */ +void * os_realloc(void *ptr, size_t size); + +/** + * os_free - Free dynamic memory + * @ptr: Old buffer from os_malloc() or os_realloc(); can be %NULL + */ +void os_free(void *ptr); + +/** + * os_memcpy - Copy memory area + * @dest: Destination + * @src: Source + * @n: Number of bytes to copy + * Returns: dest + * + * The memory areas src and dst must not overlap. os_memmove() can be used with + * overlapping memory. + */ +void * os_memcpy(void *dest, const void *src, size_t n); + +/** + * os_memmove - Copy memory area + * @dest: Destination + * @src: Source + * @n: Number of bytes to copy + * Returns: dest + * + * The memory areas src and dst may overlap. + */ +void *os_memmove(void *dest, const void *src, size_t n); + +/** + * os_memset - Fill memory with a constant byte + * @s: Memory area to be filled + * @c: Constant byte + * @n: Number of bytes started from s to fill with c + * Returns: s + */ +void *os_memset(void *s, int c, size_t n); + +/** + * os_memcmp - Compare memory areas + * @s1: First buffer + * @s2: Second buffer + * @n: Maximum numbers of octets to compare + * Returns: An integer less than, equal to, or greater than zero if s1 is + * found to be less than, to match, or be greater than s2. Only first n + * characters will be compared. + */ +int os_memcmp(const void *s1, const void *s2, size_t n); + +/** + * os_strdup - Duplicate a string + * @s: Source string + * Returns: Allocated buffer with the string copied into it or %NULL on failure + * + * Caller is responsible for freeing the returned buffer with os_free(). + */ +char *os_strdup(const char *s); + +/** + * os_strlen - Calculate the length of a string + * @s: '\0' terminated string + * Returns: Number of characters in s (not counting the '\0' terminator) + */ +size_t os_strlen(const char *s); + +/** + * os_strcasecmp - Compare two strings ignoring case + * @s1: First string + * @s2: Second string + * Returns: An integer less than, equal to, or greater than zero if s1 is + * found to be less than, to match, or be greatred than s2 + */ +int os_strcasecmp(const char *s1, const char *s2); + +/** + * os_strncasecmp - Compare two strings ignoring case + * @s1: First string + * @s2: Second string + * @n: Maximum numbers of characters to compare + * Returns: An integer less than, equal to, or greater than zero if s1 is + * found to be less than, to match, or be greater than s2. Only first n + * characters will be compared. + */ +int os_strncasecmp(const char *s1, const char *s2, size_t n); + +/** + * os_strchr - Locate the first occurrence of a character in string + * @s: String + * @c: Character to search for + * Returns: Pointer to the matched character or %NULL if not found + */ +char *os_strchr(const char *s, int c); + +/** + * os_strrchr - Locate the last occurrence of a character in string + * @s: String + * @c: Character to search for + * Returns: Pointer to the matched character or %NULL if not found + */ +char *os_strrchr(const char *s, int c); + +/** + * os_strcmp - Compare two strings + * @s1: First string + * @s2: Second string + * Returns: An integer less than, equal to, or greater than zero if s1 is + * found to be less than, to match, or be greatred than s2 + */ +int os_strcmp(const char *s1, const char *s2); + +/** + * os_strncmp - Compare two strings + * @s1: First string + * @s2: Second string + * @n: Maximum numbers of characters to compare + * Returns: An integer less than, equal to, or greater than zero if s1 is + * found to be less than, to match, or be greater than s2. Only first n + * characters will be compared. + */ +int os_strncmp(const char *s1, const char *s2, size_t n); + +/** + * os_strncpy - Copy a string + * @dest: Destination + * @src: Source + * @n: Maximum number of characters to copy + * Returns: dest + */ +char *os_strncpy(char *dest, const char *src, size_t n); + +/** + * os_strstr - Locate a substring + * @haystack: String (haystack) to search from + * @needle: Needle to search from haystack + * Returns: Pointer to the beginning of the substring or %NULL if not found + */ +char *os_strstr(const char *haystack, const char *needle); + +/** + * os_snprintf - Print to a memory buffer + * @str: Memory buffer to print into + * @size: Maximum length of the str buffer + * @format: printf format + * Returns: Number of characters printed (not including trailing '\0'). + * + * If the output buffer is truncated, number of characters which would have + * been written is returned. Since some C libraries return -1 in such a case, + * the caller must be prepared on that value, too, to indicate truncation. + * + * Note: Some C library implementations of snprintf() may not guarantee null + * termination in case the output is truncated. The OS wrapper function of + * os_snprintf() should provide this guarantee, i.e., to null terminate the + * output buffer if a C library version of the function is used and if that + * function does not guarantee null termination. + * + * If the target system does not include snprintf(), see, e.g., + * http://www.ijs.si/software/snprintf/ for an example of a portable + * implementation of snprintf. + */ +int os_snprintf(char *str, size_t size, const char *format, ...); + +#else /* OS_NO_C_LIB_DEFINES */ + +#if !defined(CONFIG_PLATFORM_8195A) && !defined(CONFIG_PLATFORM_8711B) +#ifdef CONFIG_MEM_MONITOR + u8* os_malloc(u32 sz); + void os_mfree(u8 *pbuf, u32 sz); + #ifndef os_free + #define os_free(p, sz) os_mfree(((u8*)(p)), (sz)) + #endif +#else + #ifndef os_malloc + #define os_malloc(sz) _rtw_malloc(sz) + #endif + #ifndef os_free + #define os_free(p, sz) _rtw_mfree(((u8*)(p)), (sz)) + #endif +#endif +#endif + extern void *os_zalloc(size_t size); + extern char *os_strdup(const char *string_copy_from); + + #ifndef os_sleep + #define os_sleep(s, us) rtw_mdelay_os((s)*1000 + (us)/1000) + #endif + #ifndef os_memcpy + #define os_memcpy(d, s, n) rtw_memcpy((void*)(d), ((void*)(s)), (n)) + #endif + #ifndef os_memmove + #define os_memmove(d, s, n) memmove((d), (s), (n)) + #endif + #ifndef os_memset + #define os_memset(pbuf, c, sz) rtw_memset(pbuf, c, sz) + #endif + #ifndef os_memcmp + #define os_memcmp(s1, s2, n) rtw_memcmp(((void*)(s1)), ((void*)(s2)), (n)) + #endif + #ifndef os_memcmp_p2p + #define os_memcmp_p2p(s1, s2, n) memcmp((s1), (s2), (n)) + #endif + #ifndef os_get_random_bytes + #define os_get_random_bytes(d,sz) rtw_get_random_bytes(((void*)(d)), (sz)) + #endif + #ifndef os_strlen + #define os_strlen(s) strlen(s) + #endif + #ifndef os_strcasecmp + #ifdef _MSC_VER + #define os_strcasecmp(s1, s2) _stricmp((s1), (s2)) + #else + #define os_strcasecmp(s1, s2) strcasecmp((s1), (s2)) + #endif + #endif + #ifndef os_strncasecmp + #ifdef _MSC_VER + #define os_strncasecmp(s1, s2, n) _strnicmp((s1), (s2), (n)) + #else + #define os_strncasecmp(s1, s2, n) strncasecmp((s1), (s2), (n)) + #endif + #endif + #ifndef os_init_timer + #define os_init_timer(t, p, f, x, n) rtw_init_timer((t), (p), (f), (x), (n)) + #endif + #ifndef os_set_timer + #define os_set_timer(t, d) rtw_set_timer((t), (d)) + #endif + #ifndef os_cancel_timer + #define os_cancel_timer(t) rtw_cancel_timer(t) + #endif + #ifndef os_del_timer + #define os_del_timer(t) rtw_del_timer(t) + #endif + #ifndef os_atoi + #define os_atoi(s) rtw_atoi(s) + #endif + +#ifndef os_strchr +#define os_strchr(s, c) strchr((s), (c)) +#endif +#ifndef os_strcmp +#define os_strcmp(s1, s2) strcmp((s1), (s2)) +#endif +#ifndef os_strncmp +#define os_strncmp(s1, s2, n) strncmp((s1), (s2), (n)) +#endif +#ifndef os_strncpy +#define os_strncpy(d, s, n) strncpy((d), (s), (n)) +#endif +#ifndef os_strrchr +#define os_strrchr(s, c) strrchr((s), (c)) +#endif +#ifndef os_strstr +#define os_strstr(h, n) strstr((h), (n)) +#endif + +#ifndef os_snprintf + #ifdef _MSC_VER + #define os_snprintf _snprintf + #else + #define os_snprintf snprintf + #endif +#endif + +#endif /* OS_NO_C_LIB_DEFINES */ + + +static inline void * os_realloc_array(void *ptr, size_t nmemb, size_t size) +{ + if (size && nmemb > (~(size_t) 0) / size) + return NULL; + return os_realloc(ptr, nmemb * size, nmemb * size); +} + +void *os_xqueue_create(unsigned long uxQueueLength, unsigned long uxItemSize) ; + +int os_xqueue_receive(xqueue_handle_t xQueue, void * const pvBuffer, unsigned long xSecsToWait); + +void os_xqueue_delete(xqueue_handle_t xQueue ); + +int os_xqueue_send(xqueue_handle_t xQueue, const void * const pvItemToQueue, unsigned long xSecsToWait); + + +#endif /* OS_H */ diff --git a/component/common/api/wifi/rtw_wpa_supplicant/src/utils/os_freertos.c b/component/common/api/wifi/rtw_wpa_supplicant/src/utils/os_freertos.c new file mode 100644 index 0000000..3d298e3 --- /dev/null +++ b/component/common/api/wifi/rtw_wpa_supplicant/src/utils/os_freertos.c @@ -0,0 +1,100 @@ +/* + * OS specific functions for UNIX/POSIX systems + * Copyright (c) 2005-2009, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ +#include +#include +#include +#include + +#ifdef CONFIG_WPS +#include "utils/os.h" + +#if !defined(CONFIG_PLATFORM_8195A) && !defined(CONFIG_PLATFORM_8711B) +#ifdef CONFIG_MEM_MONITOR +#if CONFIG_MEM_MONITOR & MEM_MONITOR_LEAK +_list wpa_mem_table; +int wpa_mem_used_num; +//int wpa_mem_used_size; +#endif +extern int min_free_heap_size; +u8* os_malloc(u32 sz) +{ + int free_heap_size = rtw_getFreeHeapSize(); + u8 *pbuf = _rtw_malloc(sz); +#if CONFIG_MEM_MONITOR & MEM_MONITOR_LEAK + add_mem_usage(&wpa_mem_table, pbuf, sz, &wpa_mem_used_num, MEM_MONITOR_FLAG_WPAS); +#else + add_mem_usage(NULL, pbuf, sz, NULL, MEM_MONITOR_FLAG_WPAS); +#endif + if(min_free_heap_size > free_heap_size) + min_free_heap_size = free_heap_size; + return pbuf; +} + +void os_mfree(u8 *pbuf, u32 sz) +{ + _rtw_mfree(pbuf, sz); +#if CONFIG_MEM_MONITOR & MEM_MONITOR_LEAK + del_mem_usage(&wpa_mem_table, pbuf, &wpa_mem_used_num, MEM_MONITOR_FLAG_WPAS); +#else + del_mem_usage(NULL, pbuf, NULL, MEM_MONITOR_FLAG_WPAS); +#endif +} +#endif//CONFIG_MEM_MONITOR + +#endif// !defined(CONFIG_PLATFORM_8195A) + +#ifndef OS_NO_C_LIB_DEFINES +char *os_strdup(const char *string_copy_from) +{ + char *string_copy_to = NULL; + string_copy_to = os_zalloc(strlen(string_copy_from) + 1); + os_memcpy((void *)string_copy_to, string_copy_from, strlen(string_copy_from)); + string_copy_to[strlen(string_copy_from)] = '\0'; + return string_copy_to; +} +#endif + +int os_get_random(unsigned char *buf, size_t len) +{ + //TODO implement it + rtw_get_random_bytes(buf, len); + return 0; +} + +int os_get_time(struct os_time *t){ + unsigned int tt = rtw_get_current_time(); + t->sec = (os_time_t) (tt / 1000); + t->usec = (os_time_t) (tt % 1000)*1000; + return 0; +} + +int os_get_reltime(struct os_reltime *t){ + os_get_time((struct os_time *)t); + return 0; +} + +void *os_xqueue_create(unsigned long uxQueueLength, unsigned long uxItemSize) +{ + return xQueueCreate( uxQueueLength, uxItemSize ); +} + +int os_xqueue_receive(xqueue_handle_t xQueue, void * const pvBuffer, unsigned long xSecsToWait) +{ + return xQueueReceive((xQueueHandle)xQueue, pvBuffer, (portTickType)(xSecsToWait*configTICK_RATE_HZ)); +} + +void os_xqueue_delete(xqueue_handle_t xQueue ) +{ + vQueueDelete((xQueueHandle)xQueue); +} + +int os_xqueue_send(xqueue_handle_t xQueue, const void * const pvItemToQueue, unsigned long xSecsToWait) +{ + return xQueueSendToBack((xQueueHandle)xQueue, pvItemToQueue, (portTickType)(xSecsToWait*configTICK_RATE_HZ)); +} +#endif diff --git a/component/common/api/wifi/rtw_wpa_supplicant/src/utils/rom/rom_wps_os.h b/component/common/api/wifi/rtw_wpa_supplicant/src/utils/rom/rom_wps_os.h new file mode 100644 index 0000000..cd41061 --- /dev/null +++ b/component/common/api/wifi/rtw_wpa_supplicant/src/utils/rom/rom_wps_os.h @@ -0,0 +1,24 @@ +/* + * OS specific functions + * Copyright (c) 2005-2009, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef ROM_WPS_OS_H +#define ROM_WPS_OS_H + +#if defined(CONFIG_PLATFORM_8195A) || defined(CONFIG_PLATFORM_8711B) + +#include +extern struct _rom_wlan_ram_map rom_wlan_ram_map; +#define os_malloc(sz) rom_wlan_ram_map.rtw_malloc(sz) +#define os_free(p, sz) rom_wlan_ram_map.rtw_mfree(((u8*)(p)), (sz)) + +#endif + +extern u8 *WPS_realloc(u8 *old_buf, u32 old_sz, u32 new_sz); +#define os_realloc(p, os, ns) WPS_realloc(((u8*)(p)),(os),(ns)) + +#endif /* ROM_WPS_OS_H */ diff --git a/component/common/api/wifi/rtw_wpa_supplicant/src/wps/wps_defs.h b/component/common/api/wifi/rtw_wpa_supplicant/src/wps/wps_defs.h new file mode 100644 index 0000000..73d5940 --- /dev/null +++ b/component/common/api/wifi/rtw_wpa_supplicant/src/wps/wps_defs.h @@ -0,0 +1,319 @@ + +/* + * Wi-Fi Protected Setup - message definitions + * Copyright (c) 2008, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WPS_DEFS_H +#define WPS_DEFS_H + + +/* Diffie-Hellman 1536-bit MODP Group; RFC 3526, Group 5 */ +#define WPS_DH_GROUP (5) + +#define WPS_UUID_LEN (16) +#define WPS_NONCE_LEN (16) +#define WPS_AUTHENTICATOR_LEN (8) +#define WPS_AUTHKEY_LEN (32) +#define WPS_KEYWRAPKEY_LEN (16) +#define WPS_EMSK_LEN (32) +#define WPS_PSK_LEN (16) +#define WPS_SECRET_NONCE_LEN (16) +#define WPS_HASH_LEN (32) +#define WPS_KWA_LEN (8) +#define WPS_MGMTAUTHKEY_LEN (32) +#define WPS_MGMTENCKEY_LEN (16) +#define WPS_MGMT_KEY_ID_LEN (16) +#define WPS_OOB_DEVICE_PASSWORD_MIN_LEN (16) +#define WPS_OOB_DEVICE_PASSWORD_LEN (32) +#define WPS_OOB_PUBKEY_HASH_LEN (20) + +/* Attribute Types */ +enum wps_attribute { + ATTR_AP_CHANNEL = 0x1001, + ATTR_ASSOC_STATE = 0x1002, + ATTR_AUTH_TYPE = 0x1003, + ATTR_AUTH_TYPE_FLAGS = 0x1004, + ATTR_AUTHENTICATOR = 0x1005, + ATTR_CONFIG_METHODS = 0x1008, + ATTR_CONFIG_ERROR = 0x1009, + ATTR_CONFIRM_URL4 = 0x100a, + ATTR_CONFIRM_URL6 = 0x100b, + ATTR_CONN_TYPE = 0x100c, + ATTR_CONN_TYPE_FLAGS = 0x100d, + ATTR_CRED = 0x100e, + ATTR_ENCR_TYPE = 0x100f, + ATTR_ENCR_TYPE_FLAGS = 0x1010, + ATTR_DEV_NAME = 0x1011, + ATTR_DEV_PASSWORD_ID = 0x1012, + ATTR_E_HASH1 = 0x1014, + ATTR_E_HASH2 = 0x1015, + ATTR_E_SNONCE1 = 0x1016, + ATTR_E_SNONCE2 = 0x1017, + ATTR_ENCR_SETTINGS = 0x1018, + ATTR_ENROLLEE_NONCE = 0x101a, + ATTR_FEATURE_ID = 0x101b, + ATTR_IDENTITY = 0x101c, + ATTR_IDENTITY_PROOF = 0x101d, + ATTR_KEY_WRAP_AUTH = 0x101e, + ATTR_KEY_ID = 0x101f, + ATTR_MAC_ADDR = 0x1020, + ATTR_MANUFACTURER = 0x1021, + ATTR_MSG_TYPE = 0x1022, + ATTR_MODEL_NAME = 0x1023, + ATTR_MODEL_NUMBER = 0x1024, + ATTR_NETWORK_INDEX = 0x1026, + ATTR_NETWORK_KEY = 0x1027, + ATTR_NETWORK_KEY_INDEX = 0x1028, + ATTR_NEW_DEVICE_NAME = 0x1029, + ATTR_NEW_PASSWORD = 0x102a, + ATTR_OOB_DEVICE_PASSWORD = 0x102c, + ATTR_OS_VERSION = 0x102d, + ATTR_POWER_LEVEL = 0x102f, + ATTR_PSK_CURRENT = 0x1030, + ATTR_PSK_MAX = 0x1031, + ATTR_PUBLIC_KEY = 0x1032, + ATTR_RADIO_ENABLE = 0x1033, + ATTR_REBOOT = 0x1034, + ATTR_REGISTRAR_CURRENT = 0x1035, + ATTR_REGISTRAR_ESTABLISHED = 0x1036, + ATTR_REGISTRAR_LIST = 0x1037, + ATTR_REGISTRAR_MAX = 0x1038, + ATTR_REGISTRAR_NONCE = 0x1039, + ATTR_REQUEST_TYPE = 0x103a, + ATTR_RESPONSE_TYPE = 0x103b, + ATTR_RF_BANDS = 0x103c, + ATTR_R_HASH1 = 0x103d, + ATTR_R_HASH2 = 0x103e, + ATTR_R_SNONCE1 = 0x103f, + ATTR_R_SNONCE2 = 0x1040, + ATTR_SELECTED_REGISTRAR = 0x1041, + ATTR_SERIAL_NUMBER = 0x1042, + ATTR_WPS_STATE = 0x1044, + ATTR_SSID = 0x1045, + ATTR_TOTAL_NETWORKS = 0x1046, + ATTR_UUID_E = 0x1047, + ATTR_UUID_R = 0x1048, + ATTR_VENDOR_EXT = 0x1049, + ATTR_VERSION = 0x104a, + ATTR_X509_CERT_REQ = 0x104b, + ATTR_X509_CERT = 0x104c, + ATTR_EAP_IDENTITY = 0x104d, + ATTR_MSG_COUNTER = 0x104e, + ATTR_PUBKEY_HASH = 0x104f, + ATTR_REKEY_KEY = 0x1050, + ATTR_KEY_LIFETIME = 0x1051, + ATTR_PERMITTED_CFG_METHODS = 0x1052, + ATTR_SELECTED_REGISTRAR_CONFIG_METHODS = 0x1053, + ATTR_PRIMARY_DEV_TYPE = 0x1054, + ATTR_SECONDARY_DEV_TYPE_LIST = 0x1055, + ATTR_PORTABLE_DEV = 0x1056, + ATTR_AP_SETUP_LOCKED = 0x1057, + ATTR_APPLICATION_EXT = 0x1058, + ATTR_EAP_TYPE = 0x1059, + ATTR_IV = 0x1060, + ATTR_KEY_PROVIDED_AUTO = 0x1061, + ATTR_802_1X_ENABLED = 0x1062, + ATTR_APPSESSIONKEY = 0x1063, + ATTR_WEPTRANSMITKEY = 0x1064, + ATTR_REQUESTED_DEV_TYPE = 0x106a, + ATTR_EXTENSIBILITY_TEST = 0x10fa /* _NOT_ defined in the spec */ +}; + +#define WPS_VENDOR_ID_WFA 14122 + +/* WFA Vendor Extension subelements */ +enum { + WFA_ELEM_VERSION2 = 0x00, + WFA_ELEM_AUTHORIZEDMACS = 0x01, + WFA_ELEM_NETWORK_KEY_SHAREABLE = 0x02, + WFA_ELEM_REQUEST_TO_ENROLL = 0x03, + WFA_ELEM_SETTINGS_DELAY_TIME = 0x04 +}; + +/* Device Password ID */ +enum wps_dev_password_id { + DEV_PW_DEFAULT = 0x0000, + DEV_PW_USER_SPECIFIED = 0x0001, + DEV_PW_MACHINE_SPECIFIED = 0x0002, + DEV_PW_REKEY = 0x0003, + DEV_PW_PUSHBUTTON = 0x0004, + DEV_PW_REGISTRAR_SPECIFIED = 0x0005 +}; + +/* Message Type */ +enum wps_msg_type { + WPS_START = 0x00, + WPS_Beacon = 0x01, + WPS_ProbeRequest = 0x02, + WPS_ProbeResponse = 0x03, + WPS_M1 = 0x04, + WPS_M2 = 0x05, + WPS_M2D = 0x06, + WPS_M3 = 0x07, + WPS_M4 = 0x08, + WPS_M5 = 0x09, + WPS_M6 = 0x0a, + WPS_M7 = 0x0b, + WPS_M8 = 0x0c, + WPS_WSC_ACK = 0x0d, + WPS_WSC_NACK = 0x0e, + WPS_WSC_DONE = 0x0f +}; + +/* Authentication Type Flags */ +#define WPS_AUTH_OPEN 0x0001 +#define WPS_AUTH_WPAPSK 0x0002 +#define WPS_AUTH_SHARED 0x0004 +#define WPS_AUTH_WPA 0x0008 +#define WPS_AUTH_WPA2 0x0010 +#define WPS_AUTH_WPA2PSK 0x0020 +#define WPS_AUTH_TYPES (WPS_AUTH_OPEN | WPS_AUTH_WPAPSK | WPS_AUTH_SHARED | \ + WPS_AUTH_WPA | WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK) + +/* Encryption Type Flags */ +#define WPS_ENCR_NONE 0x0001 +#define WPS_ENCR_WEP 0x0002 +#define WPS_ENCR_TKIP 0x0004 +#define WPS_ENCR_AES 0x0008 +#define WPS_ENCR_TYPES (WPS_ENCR_NONE | WPS_ENCR_WEP | WPS_ENCR_TKIP | \ + WPS_ENCR_AES) + +/* Configuration Error */ +enum wps_config_error { + WPS_CFG_NO_ERROR = 0, + WPS_CFG_OOB_IFACE_READ_ERROR = 1, + WPS_CFG_DECRYPTION_CRC_FAILURE = 2, + WPS_CFG_24_CHAN_NOT_SUPPORTED = 3, + WPS_CFG_50_CHAN_NOT_SUPPORTED = 4, + WPS_CFG_SIGNAL_TOO_WEAK = 5, + WPS_CFG_NETWORK_AUTH_FAILURE = 6, + WPS_CFG_NETWORK_ASSOC_FAILURE = 7, + WPS_CFG_NO_DHCP_RESPONSE = 8, + WPS_CFG_FAILED_DHCP_CONFIG = 9, + WPS_CFG_IP_ADDR_CONFLICT = 10, + WPS_CFG_NO_CONN_TO_REGISTRAR = 11, + WPS_CFG_MULTIPLE_PBC_DETECTED = 12, + WPS_CFG_ROGUE_SUSPECTED = 13, + WPS_CFG_DEVICE_BUSY = 14, + WPS_CFG_SETUP_LOCKED = 15, + WPS_CFG_MSG_TIMEOUT = 16, + WPS_CFG_REG_SESS_TIMEOUT = 17, + WPS_CFG_DEV_PASSWORD_AUTH_FAILURE = 18 +}; + +/* RF Bands */ +#define WPS_RF_24GHZ (0x01) +#define WPS_RF_50GHZ (0x02) + +/* Config Methods */ +#define WPS_CONFIG_USBA (0x0001) +#define WPS_CONFIG_ETHERNET (0x0002) +#define WPS_CONFIG_LABEL (0x0004) +#define WPS_CONFIG_DISPLAY (0x0008) +#define WPS_CONFIG_EXT_NFC_TOKEN (0x0010) +#define WPS_CONFIG_INT_NFC_TOKEN (0x0020) +#define WPS_CONFIG_NFC_INTERFACE (0x0040) +#define WPS_CONFIG_PUSHBUTTON (0x0080) +#define WPS_CONFIG_KEYPAD (0x0100) + +#ifdef CONFIG_WPS2 +#define WPS_CONFIG_VIRT_PUSHBUTTON (0x0280) +#define WPS_CONFIG_PHY_PUSHBUTTON (0x0480) +#define WPS_CONFIG_VIRT_DISPLAY (0x2008) +#define WPS_CONFIG_PHY_DISPLAY (0x4008) +#endif /* CONFIG_WPS2 */ + +/* Connection Type Flags */ +#define WPS_CONN_ESS (0x01) +#define WPS_CONN_IBSS (0x02) + +/* Wi-Fi Protected Setup State */ +enum wps_state { + WPS_STATE_NOT_CONFIGURED = 1, + WPS_STATE_CONFIGURED = 2 +}; + +/* Association State */ +enum wps_assoc_state { + WPS_ASSOC_NOT_ASSOC = 0, + WPS_ASSOC_CONN_SUCCESS = 1, + WPS_ASSOC_CFG_FAILURE = 2, + WPS_ASSOC_FAILURE = 3, + WPS_ASSOC_IP_FAILURE = 4 +}; + + +#define WPS_DEV_OUI_WFA (0x0050f204) + +enum wps_dev_categ { + WPS_DEV_COMPUTER = 1, + WPS_DEV_INPUT = 2, + WPS_DEV_PRINTER = 3, + WPS_DEV_CAMERA = 4, + WPS_DEV_STORAGE = 5, + WPS_DEV_NETWORK_INFRA = 6, + WPS_DEV_DISPLAY = 7, + WPS_DEV_MULTIMEDIA = 8, + WPS_DEV_GAMING = 9, + WPS_DEV_PHONE = 10 +}; + +enum wps_dev_subcateg { + WPS_DEV_COMPUTER_PC = 1, + WPS_DEV_COMPUTER_SERVER = 2, + WPS_DEV_COMPUTER_MEDIA_CENTER = 3, + + WPS_DEV_PRINTER_PRINTER = 1, + WPS_DEV_PRINTER_SCANNER = 2, + + WPS_DEV_CAMERA_DIGITAL_STILL_CAMERA = 1, + + WPS_DEV_STORAGE_NAS = 1, + + WPS_DEV_NETWORK_INFRA_AP = 1, + WPS_DEV_NETWORK_INFRA_ROUTER = 2, + WPS_DEV_NETWORK_INFRA_SWITCH = 3, + + WPS_DEV_DISPLAY_TV = 1, + WPS_DEV_DISPLAY_PICTURE_FRAME = 2, + WPS_DEV_DISPLAY_PROJECTOR = 3, + + WPS_DEV_MULTIMEDIA_DAR = 1, + WPS_DEV_MULTIMEDIA_PVR = 2, + WPS_DEV_MULTIMEDIA_MCX = 3, + + WPS_DEV_GAMING_XBOX = 1, + WPS_DEV_GAMING_XBOX360 = 2, + WPS_DEV_GAMING_PLAYSTATION = 3, + + WPS_DEV_PHONE_WINDOWS_MOBILE = 1 +}; + + +/* Request Type */ +enum wps_request_type { + WPS_REQ_ENROLLEE_INFO = 0, + WPS_REQ_ENROLLEE = 1, + WPS_REQ_REGISTRAR = 2, + WPS_REQ_WLAN_MANAGER_REGISTRAR = 3 +}; + +/* Response Type */ +enum wps_response_type { + WPS_RESP_ENROLLEE_INFO = 0, + WPS_RESP_ENROLLEE = 1, + WPS_RESP_REGISTRAR = 2, + WPS_RESP_AP = 3 +}; + +/* Walk Time for push button configuration (in seconds) */ +#define WPS_PBC_WALK_TIME (120) + +#define WPS_MAX_AUTHORIZED_MACS (5) + +#endif /* WPS_DEFS_H */ + diff --git a/component/common/api/wifi/rtw_wpa_supplicant/wpa_supplicant/wifi_wps_config.c b/component/common/api/wifi/rtw_wpa_supplicant/wpa_supplicant/wifi_wps_config.c new file mode 100644 index 0000000..3ca472d --- /dev/null +++ b/component/common/api/wifi/rtw_wpa_supplicant/wpa_supplicant/wifi_wps_config.c @@ -0,0 +1,528 @@ +#include +#include +#include +#include "FreeRTOS.h" +#include "task.h" +#include "main.h" +#include "queue.h" +#include "utils/os.h" +#include +#include +#include "wifi/wifi_conf.h" +#include "wps/wps_defs.h" +#include + +/** + * struct wps_credential - WPS Credential + * @ssid: SSID + * @ssid_len: Length of SSID + * @auth_type: Authentication Type (WPS_AUTH_OPEN, .. flags) + * @encr_type: Encryption Type (WPS_ENCR_NONE, .. flags) + * @key_idx: Key index + * @key: Key + * @key_len: Key length in octets + * @mac_addr: MAC address of the Credential receiver + * @cred_attr: Unparsed Credential attribute data (used only in cred_cb()); + * this may be %NULL, if not used + * @cred_attr_len: Length of cred_attr in octets + * @ap_channel: AP channel + */ +struct dev_credential { + u8 ssid[32]; + size_t ssid_len; + u16 auth_type; + u16 encr_type; + u8 key_idx; + u8 key[65]; + size_t key_len; + u8 mac_addr[6]; + const u8 *cred_attr; + size_t cred_attr_len; + u16 ap_channel; +}; + +typedef struct { + char *target_ssid; + u16 config_method; + _sema scan_sema; + int isoverlap; +} internal_wps_scan_handler_arg_t; + +#define WLAN0_NAME "wlan0" +#ifndef ENABLE +#define ENABLE (1) +#endif +#ifndef DISABLE +#define DISABLE (0) +#endif +#define STACKSIZE 512 + + +//static xSemaphoreHandle wps_reconnect_semaphore; +//static struct _WIFI_NETWORK wifi_get_from_certificate = {0}; + +#define WPS_AUTH_TYPE_OPEN (0x0001) +#define WPS_AUTH_TYPE_WPA_PERSONAL (0x0002) +#define WPS_AUTH_TYPE_WPA_ENTERPRISE (0x0008) +#define WPS_AUTH_TYPE_WPA2_PERSONAL (0x0010) +#define WPS_AUTH_TYPE_WPA2_ENTERPRISE (0x0020) + +#define WIFI_LINK_DISCONNECTED (0) +#define WIFI_LINK_CONNECTED (1) +#define SCAN_BUFFER_LENGTH (4096) + + +#ifdef CONFIG_WPS +#if CONFIG_ENABLE_WPS +xqueue_handle_t queue_for_credential; +char wps_pin_code[32]; +u16 config_method; +u8 wps_password_id; + +void wps_check_and_show_connection_info(void) +{ + rtw_wifi_setting_t setting; +#if CONFIG_LWIP_LAYER + /* Start DHCP Client */ + LwIP_DHCP(0, DHCP_START); +#endif + wifi_get_setting(WLAN0_NAME, &setting); + wifi_show_setting(WLAN0_NAME, &setting); +} + +static void wps_config_wifi_setting(rtw_network_info_t *wifi, struct dev_credential *dev_cred) +{ + printf("\r\nwps_config_wifi_setting\n"); + //memcpy((void *)wifi->ssid, (void *)dev_cred->ssid, dev_cred->ssid_len); + strcpy((char*)wifi->ssid.val, (char*)&dev_cred->ssid[0]); + printf("\r\nwps_wifi.ssid = %s\n", wifi->ssid.val); + wifi->ssid.len = dev_cred->ssid_len; + printf("\r\nwps_wifi.ssid_len = %d\n", wifi->ssid.len); + + switch(dev_cred->auth_type) { + case WPS_AUTH_TYPE_OPEN : + printf("\r\nsecurity_type = RTW_SECURITY_OPEN\n"); + wifi->security_type = RTW_SECURITY_OPEN; + break; + case WPS_AUTH_TYPE_WPA_PERSONAL : + case WPS_AUTH_TYPE_WPA_ENTERPRISE : + printf("\r\nsecurity_type = RTW_SECURITY_WPA_AES_PSK\n"); + wifi->security_type = RTW_SECURITY_WPA_AES_PSK; + break; + case WPS_AUTH_TYPE_WPA2_PERSONAL : + case WPS_AUTH_TYPE_WPA2_ENTERPRISE : + printf("\r\nsecurity_type = RTW_SECURITY_WPA2_AES_PSK\n"); + wifi->security_type = RTW_SECURITY_WPA2_AES_PSK; + break; + } + + printf("\r\nwps_wifi.security_type = %d\n", wifi->security_type); + + //memcpy(wifi->password, dev_cred->key, dev_cred->key_len); + wifi->password = dev_cred->key; + printf("\r\nwps_wifi.password = %s\n", wifi->password); + wifi->password_len = dev_cred->key_len; + printf("\r\nwps_wifi.password_len = %d", wifi->password_len); + //xSemaphoreGive(wps_reconnect_semaphore); + //printf("\r\nrelease wps_reconnect_semaphore"); +} + +static void wps_connect_to_AP_by_certificate(rtw_network_info_t *wifi) +{ +#define RETRY_COUNT 3 + int retry_count = RETRY_COUNT, ret; + + printf("\r\n=============== wifi_certificate_info ===============\n"); + printf("\r\nwps_wifi.ssid = %s\n", wifi->ssid.val); + printf("\r\nsecurity_type = %d\n", wifi->security_type); + printf("\r\nwps_wifi.password = %s\n", wifi->password); + printf("\r\nssid_len = %d\n", wifi->ssid.len); + printf("\r\npassword_len = %d\n", wifi->password_len); + while (1) { + ret = wifi_connect((char*)wifi->ssid.val, + wifi->security_type, + (char*)wifi->password, + wifi->ssid.len, + wifi->password_len, + wifi->key_id, + NULL); + if (ret == RTW_SUCCESS) { + if(retry_count == RETRY_COUNT) + rtw_msleep_os(1000); //When start wps with OPEN AP, AP will send a disassociate frame after STA connected, need reconnect here. + if(RTW_SUCCESS == wifi_is_ready_to_transceive(RTW_STA_INTERFACE)){ + //printf("\r\n[WPS]Ready to tranceive!!\n"); + wps_check_and_show_connection_info(); + break; + } + } + if (retry_count == 0) { + printf("\r\n[WPS]Join bss failed\n"); + break; + } + retry_count --; + } +} + +static int wps_connect_to_AP_by_open_system(char *target_ssid) +{ + int retry_count = 3, ret; + + if (target_ssid != NULL) { + rtw_msleep_os(500); //wait scan complete. + while (1) { + ret = wifi_connect(target_ssid, + RTW_SECURITY_OPEN, + NULL, + strlen(target_ssid), + 0, + 0, + NULL); + if (ret == RTW_SUCCESS) { + //wps_check_and_show_connection_info(); + break; + } + if (retry_count == 0) { + printf("\r\n[WPS]Join bss failed\n"); + return -1; + } + retry_count --; + } + // + } else { + printf("\r\n[WPS]Target SSID is NULL\n"); + } + + return 0; +} + +static void process_wps_scan_result( rtw_scan_result_t* record, void * user_data ) +{ + internal_wps_scan_handler_arg_t *wps_arg = (internal_wps_scan_handler_arg_t *)user_data; + + if (record->wps_type != 0xff) { + if (wps_arg->config_method == WPS_CONFIG_PUSHBUTTON) { + if (record->wps_type == 0x04) { + wps_password_id = record->wps_type; + if (++wps_arg->isoverlap == 0) { + memcpy(&wps_arg->target_ssid[0], record->SSID.val, record->SSID.len); + wps_arg->target_ssid[record->SSID.len] = '\0'; + printf("\r\n[pbc]Record first triger wps AP = %s\n", wps_arg->target_ssid); + } + } + } else if (wps_arg->config_method == WPS_CONFIG_DISPLAY) { + if (record->wps_type == 0x00) { + wps_arg->isoverlap = 0; + wps_password_id = record->wps_type; + memcpy(&wps_arg->target_ssid[0], record->SSID.val, record->SSID.len); + wps_arg->target_ssid[record->SSID.len] = '\0'; + printf("\r\n[pin]find out first triger wps AP = %s\n", wps_arg->target_ssid); + } + } + } +} + +static rtw_result_t wps_scan_result_handler( rtw_scan_handler_result_t* malloced_scan_result ) +{ + internal_wps_scan_handler_arg_t *wps_arg = (internal_wps_scan_handler_arg_t *)malloced_scan_result->user_data; + if (malloced_scan_result->scan_complete != RTW_TRUE) + { + rtw_scan_result_t* record = &malloced_scan_result->ap_details; + record->SSID.val[record->SSID.len] = 0; /* Ensure the SSID is null terminated */ + + process_wps_scan_result(record, malloced_scan_result->user_data); + } + else + { + printf("\r\nWPS scan done!\r\n"); + rtw_up_sema(&wps_arg->scan_sema); + } + return RTW_SUCCESS; +} + + +static int wps_find_out_triger_wps_AP(char *target_ssid, u16 config_method) +{ + internal_wps_scan_handler_arg_t wps_arg = {0}; + + wps_password_id = 0xFF; + + wps_arg.isoverlap = -1; + wps_arg.config_method = config_method; + wps_arg.target_ssid = target_ssid; + rtw_init_sema(&wps_arg.scan_sema, 0); + if(wps_arg.scan_sema == NULL) return RTW_ERROR; + + if(wifi_scan_networks(wps_scan_result_handler, &wps_arg ) != RTW_SUCCESS){ + printf("\n\rERROR: wifi scan failed"); + goto exit; + } + if(rtw_down_timeout_sema(&wps_arg.scan_sema, SCAN_LONGEST_WAIT_TIME) == RTW_FALSE){ + printf("\r\nWPS scan done early!\r\n"); + } + +exit: + rtw_free_sema(&wps_arg.scan_sema); + + return wps_arg.isoverlap; +} +extern void wpas_wps_notify_wps_finish_hdl(char *buf, int buf_len, int flags, void *userdata); +extern void wpas_wsc_eapol_recvd_hdl(char *buf, int buf_len, int flags, void* handler_user_data); +int wps_start(u16 wps_config, char *pin, u8 channel, char *ssid) +{ + struct dev_credential dev_cred; + rtw_network_info_t wifi = {0}; + char target_ssid[64]; + int is_overlap = -1; + u32 start_time = rtw_get_current_time(); + int ret = 0; + + memset(&dev_cred, 0, sizeof(struct dev_credential)); + memset(target_ssid, 0, 64); + if((wps_config != WPS_CONFIG_PUSHBUTTON) + && (wps_config != WPS_CONFIG_DISPLAY) + && (wps_config != WPS_CONFIG_KEYPAD)){ + printf("\n\rWPS: Wps method(%d) is wrong. Not triger WPS.\n", wps_config); + return -1; + } + config_method = wps_config; + + if(wps_config == WPS_CONFIG_DISPLAY + || wps_config == WPS_CONFIG_KEYPAD) { + if(pin) + strcpy(wps_pin_code, pin); + else{ + printf("\n\rWPS: PIN is NULL. Not triger WPS.\n"); + return -1; + } + } + + if(!ssid) { + while (1) { + unsigned int current_time = rtw_get_current_time(); + if (rtw_systime_to_sec(current_time - start_time) < 120) { + is_overlap = wps_find_out_triger_wps_AP(&target_ssid[0], wps_config); + if ((is_overlap == 0) || (is_overlap > 0)) + break; + } else { + printf("\r\nWPS: WPS Walking Time Out\n"); + return 0; + } + } + + if (is_overlap > 0) { + printf("\r\nWPS: WPS session overlap. Not triger WPS.\n"); + return 0; + } + }else{ + rtw_memcpy(target_ssid, ssid, strlen(ssid)); + } + + if (queue_for_credential != NULL) { + os_xqueue_delete(queue_for_credential); + queue_for_credential = NULL; + } + queue_for_credential = os_xqueue_create(1, sizeof(struct dev_credential)); + if(!queue_for_credential) + return -1; + + wifi_reg_event_handler(WIFI_EVENT_WPS_FINISH, wpas_wps_notify_wps_finish_hdl, NULL); + wifi_reg_event_handler(WIFI_EVENT_EAPOL_RECVD, wpas_wsc_eapol_recvd_hdl, NULL); + + wifi_set_wps_phase(ENABLE); + ret = wps_connect_to_AP_by_open_system(target_ssid); + if(ret < 0){ + printf("\n\rWPS: WPS Fail!!\n"); + goto exit; + } + os_xqueue_receive(queue_for_credential, &dev_cred, 120); + if (dev_cred.ssid[0] != 0 && dev_cred.ssid_len <= 32) { + wps_config_wifi_setting(&wifi, &dev_cred); + wifi_set_wps_phase(DISABLE); + wps_connect_to_AP_by_certificate(&wifi); + goto exit1; + } else { + printf("\n\rWPS: WPS FAIL!!!\n"); + } +exit: + wifi_set_wps_phase(DISABLE); +exit1: + if (queue_for_credential != NULL) { + os_xqueue_delete(queue_for_credential); + queue_for_credential = NULL; + } + + wifi_unreg_event_handler(WIFI_EVENT_WPS_FINISH, wpas_wps_notify_wps_finish_hdl); + wifi_unreg_event_handler(WIFI_EVENT_EAPOL_RECVD, wpas_wsc_eapol_recvd_hdl); + + return 0; +} + +#ifdef CONFIG_WPS_AP +int ap_wps_start(u16 wps_config, char *pin) +{ + u8 authorized_mac[ETH_ALEN]; + int ret = 0; + u32 pin_val = 0; + + printf("\n\rWPS-AP: wps_config(%x).\n", wps_config); + if((wps_config != WPS_CONFIG_PUSHBUTTON) + && (wps_config != WPS_CONFIG_DISPLAY) + && (wps_config != WPS_CONFIG_KEYPAD)){ + printf("\n\rWPS-AP: Wps method(%d) is wrong. Not triger WPS.\n", wps_config); + return -1; + } + config_method = wps_config; + if(wps_config == WPS_CONFIG_DISPLAY + || wps_config == WPS_CONFIG_KEYPAD) { + if(pin) + strcpy(wps_pin_code, pin); + else{ + printf("\n\rWPS-AP: PIN is NULL. Not triger WPS.\n"); + return -1; + } + } + + if (queue_for_credential != NULL) { + os_xqueue_delete(queue_for_credential); + queue_for_credential = NULL; + } + + queue_for_credential = os_xqueue_create(1, sizeof(authorized_mac)); + if(!queue_for_credential) + return -1; + + wifi_set_wps_phase(1); + + if(wps_config == WPS_CONFIG_KEYPAD) + { + pin_val = atoi(pin); + if (!wps_pin_valid(pin_val)) { + printf("\n\rWPS-AP: Enter pin code is unvalid."); + goto exit; + } + ret = wpas_wps_registrar_add_pin((unsigned char const*)pin, strlen(pin)); + } + else if(wps_config == WPS_CONFIG_DISPLAY) + ret = wpas_wps_registrar_add_pin((unsigned char const*)pin, strlen(pin)); + else + ret = wpas_wps_registrar_button_pushed(); + + if(ret<0) + goto exit; + + printf("\n\rWPS-AP: wait for STA connect!\n"); + os_xqueue_receive(queue_for_credential, authorized_mac, 120); //max wait 2min + + if(!wpas_wps_registrar_check_done()) + { + ret = -1; + wpas_wps_registrar_wps_cancel(); + } + +exit: + wifi_set_wps_phase(0); + os_xqueue_delete(queue_for_credential); + queue_for_credential = NULL; + + return ret; +} +#endif //CONFIG_WPS_AP + +void wps_judge_staion_disconnect(void) +{ + int mode = 0; + unsigned char ssid[33]; + + wext_get_mode(WLAN0_NAME, &mode); + + switch(mode) { + case IW_MODE_MASTER: //In AP mode + rltk_wlan_deinit(); + rltk_wlan_init(0,RTW_MODE_STA); + rltk_wlan_start(0); + break; + case IW_MODE_INFRA: //In STA mode + if(wext_get_ssid(WLAN0_NAME, ssid) > 0) + wifi_disconnect(); + } +} + +void cmd_wps(int argc, char **argv) +{ + wps_judge_staion_disconnect(); + + if((argc == 2 || argc == 3 ) && (argv[1] != NULL)){ + if(strcmp(argv[1],"pin") == 0){ + unsigned int pin_val = 0; + /* start pin */ + if(argc == 2){ + char device_pin[10]; + pin_val = wps_generate_pin(); + sprintf(device_pin, "%08d", pin_val); + printf("\n\rWPS: Start WPS PIN Display. PIN: %s\n\r", device_pin); + wps_start(WPS_CONFIG_DISPLAY, (char*)device_pin, 0, NULL); + }else{ + pin_val = atoi(argv[2]); + if (!wps_pin_valid(pin_val)) { + printf("\n\rWPS: Device pin code is invalid. Not triger WPS.\n"); + return; + } + printf("\n\rWPS: Start WPS PIN Keypad.\n\r"); + wps_start(WPS_CONFIG_KEYPAD, argv[2], 0, NULL); + } + }else if(strcmp(argv[1],"pbc") == 0){ + /* start pbc */ + printf("\n\rWPS: Start WPS PBC.\n\r"); + wps_start(WPS_CONFIG_PUSHBUTTON, NULL, 0, NULL); + }else{ + printf("\n\rWPS: Wps Method is wrong. Not triger WPS.\n"); + return; + } + } +} + +#ifdef CONFIG_WPS_AP +/* +cmd_ap_wps for AP WSC setting. command style: +cmd_ap_wps pbc or cmd_ap_wps pin 12345678 +*/ +void cmd_ap_wps(int argc, char **argv) +{ + if(rltk_wlan_running(WLAN1_IDX)){ + printf("\n\rNot support con-current softAP WSC!\n\r"); + return; + } + + if((argc == 2 || argc == 3) && (argv[1] != NULL)) { + if (strcmp(argv[1],"pin") == 0 ) { + unsigned int pin_val = 0; + if(argc == 3){ + pin_val = atoi(argv[2]); + if (!wps_pin_valid(pin_val)) { + printf("\n\rWPS-AP: Device pin code is invalid. Not trigger WPS.\n\r"); + return; + } + printf("\n\rWPS-AP: Start AP WPS PIN Keypad.\n"); + ap_wps_start(WPS_CONFIG_KEYPAD, argv[2]); + }else{ + char device_pin[10]; + pin_val = wps_generate_pin(); + sprintf(device_pin, "%08d", pin_val); + printf("\n\rWPS: Start WPS PIN Display. PIN: %s\n\r", device_pin); + ap_wps_start(WPS_CONFIG_DISPLAY, (char*)device_pin); + } + }else if (strcmp(argv[1],"pbc") == 0) { + printf("\n\rWPS-AP: Start AP WPS PBC\n"); + ap_wps_start(WPS_CONFIG_PUSHBUTTON, NULL); + }else{ + printf("\n\rWPS-AP Usage:\"wifi_ap_wps pin [pin_code]\" or \"wifi_ap_wps pbc\"\n"); + return; + } + } else { + printf("\n\rWPS-AP Usage:\"wifi_ap_wps pin [pin_code]\" or \"wifi_ap_wps pbc\"\n"); + } + return; +} +#endif //CONFIG_WPS_AP +#endif //CONFIG_ENABLE_WPS +#endif //#ifdef CONFIG_WPS diff --git a/component/common/api/wifi/wifi_conf.c b/component/common/api/wifi/wifi_conf.c new file mode 100644 index 0000000..27743a1 --- /dev/null +++ b/component/common/api/wifi/wifi_conf.c @@ -0,0 +1,1609 @@ +//----------------------------------------------------------------------------// +#include "FreeRTOS.h" +#include "task.h" +#include "semphr.h" +#include +#include "main.h" +#include +//#include +#include +#include +#include +#include +#include "tcpip.h" +#include + +#if CONFIG_EXAMPLE_WLAN_FAST_CONNECT +#include "wlan_fast_connect/example_wlan_fast_connect.h" +#endif + +/****************************************************** + * Constants + ******************************************************/ +#define SCAN_USE_SEMAPHORE 0 + +#define RTW_JOIN_TIMEOUT 15000 + +#define JOIN_ASSOCIATED (uint32_t)(1 << 0) +#define JOIN_AUTHENTICATED (uint32_t)(1 << 1) +#define JOIN_LINK_READY (uint32_t)(1 << 2) +#define JOIN_SECURITY_COMPLETE (uint32_t)(1 << 3) +#define JOIN_COMPLETE (uint32_t)(1 << 4) +#define JOIN_NO_NETWORKS (uint32_t)(1 << 5) +#define JOIN_WRONG_SECURITY (uint32_t)(1 << 6) +#define JOIN_HANDSHAKE_DONE (uint32_t)(1 << 7) + +/****************************************************** + * Type Definitions + ******************************************************/ + +/****************************************************** + * Variables Declarations + ******************************************************/ + +extern struct netif xnetif[NET_IF_NUM]; + +/****************************************************** + * Variables Definitions + ******************************************************/ +static internal_scan_handler_t scan_result_handler_ptr = {0, 0, 0, RTW_FALSE, 0, 0, 0, 0, 0}; +static internal_join_result_t* join_user_data; +static rtw_mode_t wifi_mode; +static int error_flag; +uint32_t rtw_join_status; + +/****************************************************** + * Variables Definitions + ******************************************************/ + +#ifndef WLAN0_NAME + #define WLAN0_NAME "wlan0" +#endif +#ifndef WLAN1_NAME + #define WLAN1_NAME "wlan1" +#endif +/* Give default value if not defined */ +#ifndef NET_IF_NUM +#ifdef CONFIG_CONCURRENT_MODE +#define NET_IF_NUM 2 +#else +#define NET_IF_NUM 1 +#endif +#endif + +/*Static IP ADDRESS*/ +#ifndef IP_ADDR0 +#define IP_ADDR0 192 +#define IP_ADDR1 168 +#define IP_ADDR2 1 +#define IP_ADDR3 80 +#endif + +/*NETMASK*/ +#ifndef NETMASK_ADDR0 +#define NETMASK_ADDR0 255 +#define NETMASK_ADDR1 255 +#define NETMASK_ADDR2 255 +#define NETMASK_ADDR3 0 +#endif + +/*Gateway Address*/ +#ifndef GW_ADDR0 +#define GW_ADDR0 192 +#define GW_ADDR1 168 +#define GW_ADDR2 1 +#define GW_ADDR3 1 +#endif + +/*Static IP ADDRESS*/ +#ifndef AP_IP_ADDR0 +#define AP_IP_ADDR0 192 +#define AP_IP_ADDR1 168 +#define AP_IP_ADDR2 43 +#define AP_IP_ADDR3 1 +#endif + +/*NETMASK*/ +#ifndef AP_NETMASK_ADDR0 +#define AP_NETMASK_ADDR0 255 +#define AP_NETMASK_ADDR1 255 +#define AP_NETMASK_ADDR2 255 +#define AP_NETMASK_ADDR3 0 +#endif + +/*Gateway Address*/ +#ifndef AP_GW_ADDR0 +#define AP_GW_ADDR0 192 +#define AP_GW_ADDR1 168 +#define AP_GW_ADDR2 43 +#define AP_GW_ADDR3 1 +#endif + +/****************************************************** + * Function Definitions + ******************************************************/ + +#if CONFIG_WLAN +//----------------------------------------------------------------------------// +static int wifi_connect_local(rtw_network_info_t *pWifi) +{ + int ret = 0; + u8 bssid[12] = {0}; + + if(is_promisc_enabled()) + promisc_set(0, NULL, 0); + + if(!pWifi) return -1; + switch(pWifi->security_type){ + case RTW_SECURITY_OPEN: + ret = wext_set_key_ext(WLAN0_NAME, IW_ENCODE_ALG_NONE, NULL, 0, 0, 0, 0, NULL, 0); + break; + case RTW_SECURITY_WEP_PSK: + case RTW_SECURITY_WEP_SHARED: + ret = wext_set_auth_param(WLAN0_NAME, IW_AUTH_80211_AUTH_ALG, IW_AUTH_ALG_SHARED_KEY); + if(ret == 0) + ret = wext_set_key_ext(WLAN0_NAME, IW_ENCODE_ALG_WEP, NULL, pWifi->key_id, 1 /* set tx key */, 0, 0, pWifi->password, pWifi->password_len); + break; + case RTW_SECURITY_WPA_TKIP_PSK: + case RTW_SECURITY_WPA2_TKIP_PSK: + ret = wext_set_auth_param(WLAN0_NAME, IW_AUTH_80211_AUTH_ALG, IW_AUTH_ALG_OPEN_SYSTEM); + if(ret == 0) + ret = wext_set_key_ext(WLAN0_NAME, IW_ENCODE_ALG_TKIP, NULL, 0, 0, 0, 0, NULL, 0); + if(ret == 0) + ret = wext_set_passphrase(WLAN0_NAME, pWifi->password, pWifi->password_len); + break; + case RTW_SECURITY_WPA_AES_PSK: + case RTW_SECURITY_WPA2_AES_PSK: + case RTW_SECURITY_WPA2_MIXED_PSK: + ret = wext_set_auth_param(WLAN0_NAME, IW_AUTH_80211_AUTH_ALG, IW_AUTH_ALG_OPEN_SYSTEM); + if(ret == 0) + ret = wext_set_key_ext(WLAN0_NAME, IW_ENCODE_ALG_CCMP, NULL, 0, 0, 0, 0, NULL, 0); + if(ret == 0) + ret = wext_set_passphrase(WLAN0_NAME, pWifi->password, pWifi->password_len); + break; + default: + ret = -1; + printf("\n\rWIFICONF: security type(0x%x) is not supported.\n\r", pWifi->security_type); + break; + } + if(ret == 0) + ret = wext_set_ssid(WLAN0_NAME, pWifi->ssid.val, pWifi->ssid.len); + return ret; +} + +static int wifi_connect_bssid_local(rtw_network_info_t *pWifi) +{ + int ret = 0; + u8 bssid[12] = {0}; + + if(is_promisc_enabled()) + promisc_set(0, NULL, 0); + + if(!pWifi) return -1; + switch(pWifi->security_type){ + case RTW_SECURITY_OPEN: + ret = wext_set_key_ext(WLAN0_NAME, IW_ENCODE_ALG_NONE, NULL, 0, 0, 0, 0, NULL, 0); + break; + case RTW_SECURITY_WEP_PSK: + case RTW_SECURITY_WEP_SHARED: + ret = wext_set_auth_param(WLAN0_NAME, IW_AUTH_80211_AUTH_ALG, IW_AUTH_ALG_SHARED_KEY); + if(ret == 0) + ret = wext_set_key_ext(WLAN0_NAME, IW_ENCODE_ALG_WEP, NULL, pWifi->key_id, 1 /* set tx key */, 0, 0, pWifi->password, pWifi->password_len); + break; + case RTW_SECURITY_WPA_TKIP_PSK: + case RTW_SECURITY_WPA2_TKIP_PSK: + ret = wext_set_auth_param(WLAN0_NAME, IW_AUTH_80211_AUTH_ALG, IW_AUTH_ALG_OPEN_SYSTEM); + if(ret == 0) + ret = wext_set_key_ext(WLAN0_NAME, IW_ENCODE_ALG_TKIP, NULL, 0, 0, 0, 0, NULL, 0); + if(ret == 0) + ret = wext_set_passphrase(WLAN0_NAME, pWifi->password, pWifi->password_len); + break; + case RTW_SECURITY_WPA_AES_PSK: + case RTW_SECURITY_WPA2_AES_PSK: + case RTW_SECURITY_WPA2_MIXED_PSK: + ret = wext_set_auth_param(WLAN0_NAME, IW_AUTH_80211_AUTH_ALG, IW_AUTH_ALG_OPEN_SYSTEM); + if(ret == 0) + ret = wext_set_key_ext(WLAN0_NAME, IW_ENCODE_ALG_CCMP, NULL, 0, 0, 0, 0, NULL, 0); + if(ret == 0) + ret = wext_set_passphrase(WLAN0_NAME, pWifi->password, pWifi->password_len); + break; + default: + ret = -1; + printf("\n\rWIFICONF: security type(0x%x) is not supported.\n\r", pWifi->security_type); + break; + } + if(ret == 0){ + memcpy(bssid, pWifi->bssid.octet, ETH_ALEN); + if(pWifi->ssid.len){ + bssid[ETH_ALEN] = '#'; + bssid[ETH_ALEN + 1] = '@'; + memcpy(bssid + ETH_ALEN + 2, &pWifi, sizeof(pWifi)); + } + ret = wext_set_bssid(WLAN0_NAME, bssid); + } + return ret; +} + +static void wifi_no_network_hdl(char* buf, int buf_len, int flags, void* userdata) +{ + if(join_user_data!=NULL) + rtw_join_status = JOIN_NO_NETWORKS; +} + +static void wifi_connected_hdl( char* buf, int buf_len, int flags, void* userdata) +{ + if((join_user_data!=NULL)&&((join_user_data->network_info.security_type == RTW_SECURITY_OPEN) || + (join_user_data->network_info.security_type == RTW_SECURITY_WEP_PSK))){ + error_flag = RTW_NO_ERROR; + rtw_join_status = JOIN_COMPLETE | JOIN_SECURITY_COMPLETE | JOIN_ASSOCIATED | JOIN_AUTHENTICATED | JOIN_LINK_READY; + rtw_up_sema(&join_user_data->join_sema); + }else if((join_user_data!=NULL)&&((join_user_data->network_info.security_type == RTW_SECURITY_WPA2_AES_PSK) )){ + rtw_join_status = JOIN_COMPLETE | JOIN_SECURITY_COMPLETE | JOIN_ASSOCIATED | JOIN_AUTHENTICATED | JOIN_LINK_READY; + } +} +static void wifi_handshake_done_hdl( char* buf, int buf_len, int flags, void* userdata) +{ + error_flag = RTW_NO_ERROR; + rtw_join_status = JOIN_COMPLETE | JOIN_SECURITY_COMPLETE | JOIN_ASSOCIATED | JOIN_AUTHENTICATED | JOIN_LINK_READY|JOIN_HANDSHAKE_DONE; + if(join_user_data != NULL) + rtw_up_sema(&join_user_data->join_sema); +} + +static void wifi_disconn_hdl( char* buf, int buf_len, int flags, void* userdata) +{ + if(join_user_data != NULL){ + if(join_user_data->network_info.security_type == RTW_SECURITY_OPEN){ + + if(rtw_join_status == JOIN_NO_NETWORKS) + error_flag = RTW_NONE_NETWORK; + else if(rtw_join_status ==JOIN_COMPLETE | JOIN_SECURITY_COMPLETE | JOIN_ASSOCIATED | JOIN_AUTHENTICATED | JOIN_LINK_READY) + error_flag = RTW_DHCP_FAIL; + + }else if(join_user_data->network_info.security_type == RTW_SECURITY_WEP_PSK){ + if(rtw_join_status == JOIN_NO_NETWORKS) + error_flag = RTW_NONE_NETWORK; + else if(rtw_join_status == 0) + error_flag = RTW_CONNECT_FAIL; + else if(rtw_join_status ==JOIN_COMPLETE | JOIN_SECURITY_COMPLETE | JOIN_ASSOCIATED | JOIN_AUTHENTICATED | JOIN_LINK_READY){ + error_flag = RTW_DHCP_FAIL; + printf("\r\n IN WEP SECURITY MODE,wrong password is the same to dhcp fail"); + } + }else if(join_user_data->network_info.security_type == RTW_SECURITY_WPA2_AES_PSK){ + if(rtw_join_status ==JOIN_NO_NETWORKS) + error_flag = RTW_NONE_NETWORK; + else if(rtw_join_status == 0) + error_flag = RTW_CONNECT_FAIL; + else if(rtw_join_status ==JOIN_COMPLETE | JOIN_SECURITY_COMPLETE | JOIN_ASSOCIATED | JOIN_AUTHENTICATED | JOIN_LINK_READY) + error_flag = RTW_WRONG_PASSWORD; + else if(rtw_join_status == JOIN_COMPLETE | JOIN_SECURITY_COMPLETE | JOIN_ASSOCIATED | JOIN_AUTHENTICATED | JOIN_LINK_READY|JOIN_HANDSHAKE_DONE) + error_flag = RTW_DHCP_FAIL; + } + + }else{ + if(error_flag == RTW_NO_ERROR) //wifi_disconn_hdl will be dispatched one more time after join_user_data = NULL add by frankie + error_flag = RTW_DHCP_FAIL; + } + + if(join_user_data != NULL) + rtw_up_sema(&join_user_data->join_sema); + //printf("\r\nWiFi Disconnect. Error flag is %d.\n", error_flag); +} + +#if CONFIG_EXAMPLE_WLAN_FAST_CONNECT +#define WLAN0_NAME "wlan0" + +void restore_wifi_info_to_flash() +{ + + u8 * data_to_flash; + u32 data_to_flash_len = 0, channel = 0; + u8 index = 0; + u8 *ifname[1] = {WLAN0_NAME}; + rtw_wifi_setting_t setting; + //struct security_priv *psecuritypriv = &padapter->securitypriv; + //WLAN_BSSID_EX *pcur_bss = pmlmepriv->cur_network.network; + + // SSID + passphrase + psk + channel + data_to_flash_len = NDIS_802_11_LENGTH_SSID + 4 + (IW_PASSPHRASE_MAX_SIZE + 1) + A_SHA_DIGEST_LEN * 2 + 4; + data_to_flash = rtw_zmalloc(data_to_flash_len); + + if(data_to_flash && p_write_reconnect_ptr){ + if(wifi_get_setting((const char*)ifname[0],&setting) || setting.mode == RTW_MODE_AP){ + printf("\r\n %s():wifi_get_setting fail or ap mode", __func__); + return; + } + channel = setting.channel; + + rtw_memset(psk_essid[index], 0, sizeof(psk_essid[index])); + strncpy(psk_essid[index], setting.ssid, strlen(setting.ssid)); + switch(setting.security_type){ + case RTW_SECURITY_OPEN: + rtw_memset(psk_passphrase[index], 0, sizeof(psk_passphrase[index])); + rtw_memset(wpa_global_PSK[index], 0, sizeof(wpa_global_PSK[index])); + break; + case RTW_SECURITY_WEP_PSK: + channel |= (setting.key_idx) << 28; + rtw_memset(psk_passphrase[index], 0, sizeof(psk_passphrase[index])); + rtw_memset(wpa_global_PSK[index], 0, sizeof(wpa_global_PSK[index])); + rtw_memcpy(psk_passphrase[index], setting.password, sizeof(psk_passphrase[index])); + break; + case RTW_SECURITY_WPA_AES_PSK: + case RTW_SECURITY_WPA2_AES_PSK: + default: + break; + } + + memcpy(data_to_flash, psk_essid[index], NDIS_802_11_LENGTH_SSID + 4); + if (strlen(psk_passphrase64) == 64) { + memcpy(data_to_flash + NDIS_802_11_LENGTH_SSID + 4, psk_passphrase64, IW_PASSPHRASE_MAX_SIZE + 1); + } else { + memcpy(data_to_flash + NDIS_802_11_LENGTH_SSID + 4, psk_passphrase[index], IW_PASSPHRASE_MAX_SIZE + 1); + } + memcpy(data_to_flash + NDIS_802_11_LENGTH_SSID + 4 + (IW_PASSPHRASE_MAX_SIZE + 1), wpa_global_PSK[index], A_SHA_DIGEST_LEN * 2); + memcpy(data_to_flash + NDIS_802_11_LENGTH_SSID + 4 + (IW_PASSPHRASE_MAX_SIZE + 1) + A_SHA_DIGEST_LEN * 2, &channel, 4); + + //call callback function in user program + p_write_reconnect_ptr(data_to_flash, data_to_flash_len); + + if(data_to_flash) + rtw_free(data_to_flash); + } +} + +#endif + +//----------------------------------------------------------------------------// +int wifi_connect( + char *ssid, + rtw_security_t security_type, + char *password, + int ssid_len, + int password_len, + int key_id, + void *semaphore) +{ + xSemaphoreHandle join_semaphore; + rtw_result_t result = RTW_SUCCESS; + u8 wep_hex = 0; + u8 wep_pwd[14] = {0}; + + rtw_join_status = 0;//clear for last connect status + error_flag = 0 ;//clear for last connect status + internal_join_result_t *join_result = (internal_join_result_t *)rtw_zmalloc(sizeof(internal_join_result_t)); + if(!join_result) { + return RTW_NOMEM; + } + + join_result->network_info.ssid.len = ssid_len > 32 ? 32 : ssid_len; + rtw_memcpy(join_result->network_info.ssid.val, ssid, ssid_len); + + if ( ( ( ( password_len > RTW_MAX_PSK_LEN ) || + ( password_len < RTW_MIN_PSK_LEN ) ) && + ( ( security_type == RTW_SECURITY_WPA_TKIP_PSK ) || + ( security_type == RTW_SECURITY_WPA_AES_PSK ) || + ( security_type == RTW_SECURITY_WPA2_AES_PSK ) || + ( security_type == RTW_SECURITY_WPA2_TKIP_PSK ) || + ( security_type == RTW_SECURITY_WPA2_MIXED_PSK ) ) )) { + return RTW_INVALID_KEY; + } + + if ((security_type == RTW_SECURITY_WEP_PSK)|| + (security_type ==RTW_SECURITY_WEP_SHARED)) { + if ((password_len != 5) && (password_len != 13) && + (password_len != 10)&& (password_len != 26)) { + return RTW_INVALID_KEY; + } else { + + if(password_len == 10) { + + u32 p[5]; + u8 i = 0; + sscanf((const char*)password, "%02x%02x%02x%02x%02x", &p[0], &p[1], &p[2], &p[3], &p[4]); + for(i=0; i< 5; i++) + wep_pwd[i] = (u8)p[i]; + wep_pwd[5] = '\0'; + password_len = 5; + wep_hex = 1; + } else if (password_len == 26) { + u32 p[13]; + u8 i = 0; + sscanf((const char*)password, "%02x%02x%02x%02x%02x%02x%02x"\ + "%02x%02x%02x%02x%02x%02x", &p[0], &p[1], &p[2], &p[3], &p[4],\ + &p[5], &p[6], &p[7], &p[8], &p[9], &p[10], &p[11], &p[12]); + for(i=0; i< 13; i++) + wep_pwd[i] = (u8)p[i]; + wep_pwd[13] = '\0'; + password_len = 13; + wep_hex = 1; + } + } + } + + + join_result->network_info.password_len = password_len; + if(password_len) { + /* add \0 to the end */ + join_result->network_info.password = rtw_zmalloc(password_len + 1); + if(!join_result->network_info.password) { + return RTW_NOMEM; + } + if (0 == wep_hex) + rtw_memcpy(join_result->network_info.password, password, password_len); + else + rtw_memcpy(join_result->network_info.password, wep_pwd, password_len); + + } + + join_result->network_info.security_type = security_type; + join_result->network_info.key_id = key_id; + + if(semaphore == NULL) { + rtw_init_sema( &join_result->join_sema, 0 ); + if(!join_result->join_sema) return RTW_NORESOURCE; + join_semaphore = join_result->join_sema; + } else { + join_result->join_sema = semaphore; + } + wifi_reg_event_handler(WIFI_EVENT_NO_NETWORK,wifi_no_network_hdl,NULL); + wifi_reg_event_handler(WIFI_EVENT_CONNECT, wifi_connected_hdl, NULL); + wifi_reg_event_handler(WIFI_EVENT_DISCONNECT, wifi_disconn_hdl, NULL); + wifi_reg_event_handler(WIFI_EVENT_FOURWAY_HANDSHAKE_DONE, wifi_handshake_done_hdl, NULL); + + wifi_connect_local(&join_result->network_info); + + join_user_data = join_result; + + if(semaphore == NULL) { + if(rtw_down_timeout_sema( &join_result->join_sema, RTW_JOIN_TIMEOUT ) == RTW_FALSE) { + printf("RTW API: Join bss timeout\r\n"); + if(password_len) { + rtw_free(join_result->network_info.password); + } + rtw_free((u8*)join_result); + rtw_free_sema( &join_semaphore); + result = RTW_TIMEOUT; + goto error; + } else { + rtw_free_sema( &join_semaphore ); + if(join_result->network_info.password_len) { + rtw_free(join_result->network_info.password); + } + rtw_free((u8*)join_result); + if(wifi_is_ready_to_transceive(RTW_STA_INTERFACE) != RTW_SUCCESS) { + result = RTW_ERROR; + goto error; + } + } + } + + result = RTW_SUCCESS; + +#if CONFIG_EXAMPLE_WLAN_FAST_CONNECT + restore_wifi_info_to_flash(); +#endif + +error: + join_user_data = NULL; + wifi_unreg_event_handler(WIFI_EVENT_CONNECT, wifi_connected_hdl); + wifi_unreg_event_handler(WIFI_EVENT_NO_NETWORK,wifi_no_network_hdl); + wifi_unreg_event_handler(WIFI_EVENT_FOURWAY_HANDSHAKE_DONE, wifi_handshake_done_hdl); + return result; +} + +int wifi_connect_bssid( + unsigned char bssid[ETH_ALEN], + char *ssid, + rtw_security_t security_type, + char *password, + int bssid_len, + int ssid_len, + int password_len, + int key_id, + void *semaphore) +{ + xSemaphoreHandle join_semaphore; + rtw_result_t result = RTW_SUCCESS; + + rtw_join_status = 0;//clear for last connect status + error_flag = 0 ;//clear for last connect status + internal_join_result_t *join_result = (internal_join_result_t *)rtw_zmalloc(sizeof(internal_join_result_t)); + if(!join_result) { + return RTW_NOMEM; + } + if(ssid_len && ssid){ + join_result->network_info.ssid.len = ssid_len > 32 ? 32 : ssid_len; + rtw_memcpy(join_result->network_info.ssid.val, ssid, ssid_len); + } + rtw_memcpy(join_result->network_info.bssid.octet, bssid, bssid_len); + + if ( ( ( ( password_len > RTW_MAX_PSK_LEN ) || + ( password_len < RTW_MIN_PSK_LEN ) ) && + ( ( security_type == RTW_SECURITY_WPA_TKIP_PSK ) || + ( security_type == RTW_SECURITY_WPA_AES_PSK ) || + ( security_type == RTW_SECURITY_WPA2_AES_PSK ) || + ( security_type == RTW_SECURITY_WPA2_TKIP_PSK ) || + ( security_type == RTW_SECURITY_WPA2_MIXED_PSK ) ) )|| + (((password_len != 5)&& (password_len != 13))&& + ((security_type == RTW_SECURITY_WEP_PSK)|| + (security_type ==RTW_SECURITY_WEP_SHARED ) ))) { + return RTW_INVALID_KEY; + } + join_result->network_info.password_len = password_len; + if(password_len) { + /* add \0 to the end */ + join_result->network_info.password = rtw_zmalloc(password_len + 1); + if(!join_result->network_info.password) { + return RTW_NOMEM; + } + rtw_memcpy(join_result->network_info.password, password, password_len); + } + + join_result->network_info.security_type = security_type; + join_result->network_info.key_id = key_id; + + if(semaphore == NULL) { + rtw_init_sema( &join_result->join_sema, 0 ); + if(!join_result->join_sema) return RTW_NORESOURCE; + join_semaphore = join_result->join_sema; + } else { + join_result->join_sema = semaphore; + } + wifi_reg_event_handler(WIFI_EVENT_NO_NETWORK,wifi_no_network_hdl,NULL); + wifi_reg_event_handler(WIFI_EVENT_CONNECT, wifi_connected_hdl, NULL); + wifi_reg_event_handler(WIFI_EVENT_DISCONNECT, wifi_disconn_hdl, NULL); + wifi_reg_event_handler(WIFI_EVENT_FOURWAY_HANDSHAKE_DONE, wifi_handshake_done_hdl, NULL); + + wifi_connect_bssid_local(&join_result->network_info); + + join_user_data = join_result; + + if(semaphore == NULL) { + if(rtw_down_timeout_sema( &join_result->join_sema, RTW_JOIN_TIMEOUT ) == RTW_FALSE) { + printf("RTW API: Join bss timeout\r\n"); + if(password_len) { + rtw_free(join_result->network_info.password); + } + rtw_free((u8*)join_result); + rtw_free_sema( &join_semaphore); + result = RTW_TIMEOUT; + goto error; + } else { + rtw_free_sema( &join_semaphore ); + if(join_result->network_info.password_len) { + rtw_free(join_result->network_info.password); + } + rtw_free((u8*)join_result); + if(wifi_is_ready_to_transceive(RTW_STA_INTERFACE) != RTW_SUCCESS) { + result = RTW_ERROR; + goto error; + } + } + } + + result = RTW_SUCCESS; + +#if CONFIG_EXAMPLE_WLAN_FAST_CONNECT + restore_wifi_info_to_flash(); +#endif + +error: + join_user_data = NULL; + wifi_unreg_event_handler(WIFI_EVENT_CONNECT, wifi_connected_hdl); + wifi_unreg_event_handler(WIFI_EVENT_NO_NETWORK,wifi_no_network_hdl); + wifi_unreg_event_handler(WIFI_EVENT_FOURWAY_HANDSHAKE_DONE, wifi_handshake_done_hdl); + return result; +} + +int wifi_disconnect(void) +{ + int ret = 0; + const __u8 null_bssid[ETH_ALEN] = {0, 0, 0, 0, 0, 1}; //set the last to 1 since driver will filter the mac with all 0x00 or 0xff + + if (wext_set_bssid(WLAN0_NAME, null_bssid) < 0){ + printf("\n\rWEXT: Failed to set bogus BSSID to disconnect"); + ret = -1; + } + return ret; +} + +//----------------------------------------------------------------------------// +int wifi_is_up(rtw_interface_t interface) +{ + if(interface == RTW_AP_INTERFACE) { + if(wifi_mode == RTW_MODE_STA_AP) { + return rltk_wlan_running(WLAN1_IDX); + } + } + + return rltk_wlan_running(WLAN0_IDX); +} + +int wifi_is_ready_to_transceive(rtw_interface_t interface) +{ + switch ( interface ) + { + case RTW_AP_INTERFACE: + return ( wifi_is_up(interface) == RTW_TRUE ) ? RTW_SUCCESS : RTW_ERROR; + + case RTW_STA_INTERFACE: + switch ( rtw_join_status ) + { + case JOIN_NO_NETWORKS: + return RTW_NOTFOUND; + + case JOIN_AUTHENTICATED | JOIN_ASSOCIATED | JOIN_LINK_READY | JOIN_SECURITY_COMPLETE | JOIN_COMPLETE: + if(join_user_data->network_info.security_type == RTW_SECURITY_WPA2_AES_PSK) + return RTW_ERROR; + else + return RTW_SUCCESS; + case JOIN_AUTHENTICATED | JOIN_ASSOCIATED | JOIN_LINK_READY | JOIN_SECURITY_COMPLETE | JOIN_COMPLETE|JOIN_HANDSHAKE_DONE: + return RTW_SUCCESS; + case 0: + case JOIN_SECURITY_COMPLETE: /* For open/WEP */ + return RTW_NOT_AUTHENTICATED; + + case JOIN_AUTHENTICATED | JOIN_LINK_READY | JOIN_SECURITY_COMPLETE: + return RTW_UNFINISHED; + + case JOIN_AUTHENTICATED | JOIN_LINK_READY: + case JOIN_AUTHENTICATED | JOIN_LINK_READY | JOIN_COMPLETE: + return RTW_NOT_KEYED; + + default: + return RTW_ERROR; + } + default: + return RTW_ERROR; + } +} + +//----------------------------------------------------------------------------// +int wifi_set_mac_address(char * mac) +{ + char buf[13+17+1]; + rtw_memset(buf, 0, sizeof(buf)); + snprintf(buf, 13+17, "write_mac %s", mac); + return wext_private_command(WLAN0_NAME, buf, 0); +} + +int wifi_get_mac_address(char * mac) +{ + int ret = 0; + char buf[32]; + rtw_memset(buf, 0, sizeof(buf)); + rtw_memcpy(buf, "read_mac", 8); + ret = wext_private_command_with_retval(WLAN0_NAME, buf, buf, 32); + strcpy(mac, buf); + return ret; +} + +//----------------------------------------------------------------------------// +int wifi_enable_powersave(void) +{ + return wext_enable_powersave(WLAN0_NAME); +} + +int wifi_disable_powersave(void) +{ + return wext_disable_powersave(WLAN0_NAME); +} + +#if 0 //Not ready +//----------------------------------------------------------------------------// +int wifi_get_txpower(int *poweridx) +{ + int ret = 0; + char buf[11]; + + rtw_memset(buf, 0, sizeof(buf)); + rtw_memcpy(buf, "txpower", 11); + ret = wext_private_command_with_retval(WLAN0_NAME, buf, buf, 11); + sscanf(buf, "%d", poweridx); + + return ret; +} + +int wifi_set_txpower(int poweridx) +{ + int ret = 0; + char buf[24]; + + rtw_memset(buf, 0, sizeof(buf)); + snprintf(buf, 24, "txpower patha=%d", poweridx); + ret = wext_private_command(WLAN0_NAME, buf, 0); + + return ret; +} +#endif + +//----------------------------------------------------------------------------// +int wifi_get_associated_client_list(void * client_list_buffer, uint16_t buffer_length) +{ + const char * ifname = WLAN0_NAME; + int ret = 0; + char buf[25]; + + if(wifi_mode == RTW_MODE_STA_AP) { + ifname = WLAN1_NAME; + } + + rtw_memset(buf, 0, sizeof(buf)); + snprintf(buf, 25, "get_client_list %x", client_list_buffer); + ret = wext_private_command(ifname, buf, 0); + + return ret; +} + +//----------------------------------------------------------------------------// +int wifi_get_ap_info(rtw_bss_info_t * ap_info, rtw_security_t* security) +{ + const char * ifname = WLAN0_NAME; + int ret = 0; + char buf[24]; + + if(wifi_mode == RTW_MODE_STA_AP) { + ifname = WLAN1_NAME; + } + + rtw_memset(buf, 0, sizeof(buf)); + snprintf(buf, 24, "get_ap_info %x", ap_info); + ret = wext_private_command(ifname, buf, 0); + + snprintf(buf, 24, "get_security"); + ret = wext_private_command_with_retval(ifname, buf, buf, 24); + sscanf(buf, "%d", security); + + return ret; +} + +//----------------------------------------------------------------------------// +int wifi_set_country(rtw_country_code_t country_code) +{ + int ret; + switch(country_code){ + case RTW_COUNTRY_US: ret = wext_set_country(WLAN0_NAME, "US"); break; + case RTW_COUNTRY_EU: ret = wext_set_country(WLAN0_NAME, "EU"); break; + case RTW_COUNTRY_JP: ret = wext_set_country(WLAN0_NAME, "JP"); break; + case RTW_COUNTRY_CN: ret = wext_set_country(WLAN0_NAME, "CN"); break; + default: printf("\n\rUnknown country_code\n"); ret = -1; break; + } + return ret; +} + +//----------------------------------------------------------------------------// +int wifi_get_rssi(int *pRSSI) +{ + return wext_get_rssi(WLAN0_NAME, pRSSI); +} + +//----------------------------------------------------------------------------// +int wifi_set_channel(int channel) +{ + return wext_set_channel(WLAN0_NAME, channel); +} + +int wifi_get_channel(int *channel) +{ + return wext_get_channel(WLAN0_NAME, (u8*)channel); +} + +//----------------------------------------------------------------------------// +int wifi_register_multicast_address(rtw_mac_t *mac) +{ + return wext_register_multicast_address(WLAN0_NAME, mac); +} + +int wifi_unregister_multicast_address(rtw_mac_t *mac) +{ + return wext_unregister_multicast_address(WLAN0_NAME, mac); +} + +//----------------------------------------------------------------------------// +int wifi_rf_on(void) +{ + int ret; + ret = rltk_wlan_rf_on(); + return ret; +} + +//----------------------------------------------------------------------------// +int wifi_rf_off(void) +{ + int ret; + ret = rltk_wlan_rf_off(); + return ret; +} +int wifi_on(rtw_mode_t mode) +{ + int ret = 1; + int timeout = 20; + int idx; + int devnum = 1; + + wifi_mode = mode; + + init_event_callback_list(); + if(mode == RTW_MODE_STA_AP) + devnum = 2; + + if(rltk_wlan_running(WLAN0_IDX)) { + printf("\n\rWIFI is already running"); + return 1; + } + + printf("\n\rInitializing WIFI ..."); + for(idx=0;idx RTW_MAX_PSK_LEN) || + (password_len < RTW_MIN_PSK_LEN)) { + ret = -1; + printf("\nstart ap fail, please check password length\n"); + break; + } + + ret = wext_set_auth_param(ifname, IW_AUTH_80211_AUTH_ALG, IW_AUTH_ALG_OPEN_SYSTEM); + if(ret == 0) + ret = wext_set_key_ext(ifname, IW_ENCODE_ALG_CCMP, NULL, 0, 0, 0, 0, NULL, 0); + if(ret == 0) + ret = wext_set_passphrase(ifname, (u8*)password, password_len); + break; + default: + ret = -1; + printf("\n\rWIFICONF: security type is not supported"); + break; + } + if(ret < 0) goto exit; +#if 0 +//hide beacon SSID, add by serena_li + u8 value = 1; // 1: ssid = NUll, 2: ssid = ......, other: ssid = ssid + ret = set_hidden_ssid(ifname, value); + if(ret < 0) goto exit; +#endif + ret = wext_set_ap_ssid(ifname, (u8*)ssid, ssid_len); +#ifdef CONFIG_WPS //construct WPS IE +#if CONFIG_WPS_AP + wpas_wps_init(ifname); +#endif +#endif +exit: + return ret; +} + +static void wifi_scan_each_report_hdl( char* buf, int buf_len, int flags, void* userdata) +{ + int i =0; + int insert_pos = 0; + rtw_scan_result_t** result_ptr = (rtw_scan_result_t**)buf; + rtw_scan_result_t* temp = NULL; + + for(i=0; iBSSID.octet)){ + memset(*result_ptr, 0, sizeof(rtw_scan_result_t)); + return; + } + } + + scan_result_handler_ptr.scan_cnt++; + + if(scan_result_handler_ptr.scan_cnt > scan_result_handler_ptr.max_ap_size){ + scan_result_handler_ptr.scan_cnt = scan_result_handler_ptr.max_ap_size; + if((*result_ptr)->signal_strength > scan_result_handler_ptr.pap_details[scan_result_handler_ptr.max_ap_size-1]->signal_strength){ + rtw_memcpy(scan_result_handler_ptr.pap_details[scan_result_handler_ptr.max_ap_size-1], *result_ptr, sizeof(rtw_scan_result_t)); + temp = scan_result_handler_ptr.pap_details[scan_result_handler_ptr.max_ap_size -1]; + }else + return; + }else{ + rtw_memcpy(&scan_result_handler_ptr.ap_details[scan_result_handler_ptr.scan_cnt-1], *result_ptr, sizeof(rtw_scan_result_t)); + } + + for(i=0; i< scan_result_handler_ptr.scan_cnt-1; i++){ + if((*result_ptr)->signal_strength > scan_result_handler_ptr.pap_details[i]->signal_strength) + break; + } + insert_pos = i; + + for(i = scan_result_handler_ptr.scan_cnt-1; i>insert_pos; i--) + scan_result_handler_ptr.pap_details[i] = scan_result_handler_ptr.pap_details[i-1]; + + if(temp != NULL) + scan_result_handler_ptr.pap_details[insert_pos] = temp; + else + scan_result_handler_ptr.pap_details[insert_pos] = &scan_result_handler_ptr.ap_details[scan_result_handler_ptr.scan_cnt-1]; + rtw_memset(*result_ptr, 0, sizeof(rtw_scan_result_t)); +} + +static void wifi_scan_done_hdl( char* buf, int buf_len, int flags, void* userdata) +{ + int i = 0; + rtw_scan_handler_result_t scan_result_report; + + for(i=0; ibuf, pscan_buf->buf_len, flags); + }else{ + wifi_reg_event_handler(WIFI_EVENT_SCAN_RESULT_REPORT, wifi_scan_each_report_hdl, NULL); + wifi_reg_event_handler(WIFI_EVENT_SCAN_DONE, wifi_scan_done_hdl, NULL); + ret = wext_set_scan(WLAN0_NAME, NULL, 0, flags); + } + + if(ret == 0) { + if(result_ptr != NULL){ + ret = wext_get_scan(WLAN0_NAME, pscan_buf->buf, pscan_buf->buf_len); + } + } + return ret; +} +int wifi_scan_networks_with_ssid(rtw_scan_result_handler_t results_handler, void* user_data, char* ssid, int ssid_len){ + int scan_cnt = 0, add_cnt = 0; + scan_buf_arg scan_buf; + int ret; + + scan_buf.buf_len = *((int*)user_data); + scan_buf.buf = (char*)pvPortMalloc(scan_buf.buf_len); + if(!scan_buf.buf){ + printf("\n\rERROR: Can't malloc memory"); + return RTW_NOMEM; + } + //set ssid + memset(scan_buf.buf, 0, scan_buf.buf_len); + memcpy(scan_buf.buf, &ssid_len, sizeof(int)); + memcpy(scan_buf.buf+sizeof(int), ssid, ssid_len); + + //Scan channel + if(scan_cnt = (wifi_scan(RTW_SCAN_TYPE_ACTIVE, RTW_BSS_TYPE_ANY, &scan_buf)) < 0){ + printf("\n\rERROR: wifi scan failed"); + ret = RTW_ERROR; + }else{ + int plen = 0; + while(plen < scan_buf.buf_len){ + int len, rssi, ssid_len, i, security_mode; + int wps_password_id; + char *mac, *ssid; + //u8 *security_mode; + printf("\n\r"); + // len + len = (int)*(scan_buf.buf + plen); + printf("len = %d, ", len); + // check end + if(len == 0) break; + // mac + mac = scan_buf.buf + plen + 1; + printf("mac = "); + for(i=0; i<6; i++) + printf("%02x,", *(mac+i)); + // rssi + rssi = *(int*)(scan_buf.buf + plen + 1 + 6); + printf(" rssi = %d, ", rssi); + // security_mode + security_mode = (int)*(scan_buf.buf + plen + 1 + 6 + 4); + switch (security_mode) { + case RTW_SECURITY_OPEN: + printf("sec = open , "); + break; + case RTW_SECURITY_WEP_PSK: + printf("sec = wep , "); + break; + case RTW_SECURITY_WPA2_AES_PSK: + printf("sec = wpa/wpa2, "); + break; + } + // password id + wps_password_id = (int)*(scan_buf.buf + plen + 1 + 6 + 4 + 1); + printf("wps password id = %d, ", wps_password_id); + + printf("channel = %d ", *(scan_buf.buf + plen + 1 + 6 + 4 + 1 + 1)); + // ssid + ssid_len = len - 1 - 6 - 4 - 1 - 1 - 1; + ssid = scan_buf.buf + plen + 1 + 6 + 4 + 1 + 1 + 1; + printf("ssid = "); + for(i=0; i 0) + { + rtw_msleep_os(20); + count --; + } + if(count == 0){ + printf("\n\r[%d]WiFi: Scan is running. Wait 2s timeout.", rtw_get_current_time()); + return RTW_TIMEOUT; + } + } + scan_result_handler_ptr.scan_start_time = rtw_get_current_time(); + scan_result_handler_ptr.scan_running = 1; +#endif + + scan_result_handler_ptr.gscan_result_handler = results_handler; + + scan_result_handler_ptr.max_ap_size = max_ap_size; + scan_result_handler_ptr.ap_details = (rtw_scan_result_t*)rtw_zmalloc(max_ap_size*sizeof(rtw_scan_result_t)); + if(scan_result_handler_ptr.ap_details == NULL){ + goto error_with_result_ptr; + } + rtw_memset(scan_result_handler_ptr.ap_details, 0, max_ap_size*sizeof(rtw_scan_result_t)); + + scan_result_handler_ptr.pap_details = (rtw_scan_result_t**)rtw_zmalloc(max_ap_size*sizeof(rtw_scan_result_t*)); + if(scan_result_handler_ptr.pap_details == NULL) + return RTW_ERROR; + rtw_memset(scan_result_handler_ptr.pap_details, 0, max_ap_size); + + scan_result_handler_ptr.scan_cnt = 0; + + scan_result_handler_ptr.scan_complete = RTW_FALSE; + scan_result_handler_ptr.user_data = user_data; + + if (wifi_scan( RTW_SCAN_COMMAMD<<4 | RTW_SCAN_TYPE_ACTIVE, RTW_BSS_TYPE_ANY, NULL) != RTW_SUCCESS) + { + goto error_with_result_ptr; + } + + return RTW_SUCCESS; + +error_with_result_ptr: + rtw_free((u8*)scan_result_handler_ptr.pap_details); + scan_result_handler_ptr.pap_details = NULL; + return RTW_ERROR; +} +//----------------------------------------------------------------------------// +int wifi_set_pscan_chan(__u8 * channel_list,__u8 * pscan_config, __u8 length) +{ + if(channel_list) + return wext_set_pscan_channel(WLAN0_NAME, channel_list, pscan_config, length); + else + return -1; +} + +//----------------------------------------------------------------------------// +int wifi_get_setting(const char *ifname, rtw_wifi_setting_t *pSetting) +{ + int ret = 0; + int mode = 0; + unsigned short security = 0; + + memset(pSetting, 0, sizeof(rtw_wifi_setting_t)); + if(wext_get_mode(ifname, &mode) < 0) + ret = -1; + + switch(mode) { + case IW_MODE_MASTER: + pSetting->mode = RTW_MODE_AP; + break; + case IW_MODE_INFRA: + default: + pSetting->mode = RTW_MODE_STA; + break; + //default: + //printf("\r\n%s(): Unknown mode %d\n", __func__, mode); + //break; + } + + if(wext_get_ssid(ifname, pSetting->ssid) < 0) + ret = -1; + if(wext_get_channel(ifname, &pSetting->channel) < 0) + ret = -1; + if(wext_get_enc_ext(ifname, &security, &pSetting->key_idx, pSetting->password) < 0) + ret = -1; + + switch(security){ + case IW_ENCODE_ALG_NONE: + pSetting->security_type = RTW_SECURITY_OPEN; + break; + case IW_ENCODE_ALG_WEP: + pSetting->security_type = RTW_SECURITY_WEP_PSK; + break; + case IW_ENCODE_ALG_TKIP: + pSetting->security_type = RTW_SECURITY_WPA_TKIP_PSK; + break; + case IW_ENCODE_ALG_CCMP: + pSetting->security_type = RTW_SECURITY_WPA2_AES_PSK; + break; + default: + break; + } + + if(security == IW_ENCODE_ALG_TKIP || security == IW_ENCODE_ALG_CCMP) + if(wext_get_passphrase(ifname, pSetting->password) < 0) + ret = -1; + + return ret; +} +//----------------------------------------------------------------------------// +int wifi_show_setting(const char *ifname, rtw_wifi_setting_t *pSetting) +{ + int ret = 0; + + printf("\n\r\nWIFI %s Setting:",ifname); + printf("\n\r=============================="); + + switch(pSetting->mode) { + case RTW_MODE_AP: + printf("\n\r MODE => AP"); + break; + case RTW_MODE_STA: + printf("\n\r MODE => STATION"); + break; + default: + printf("\n\r MODE => UNKNOWN"); + } + + printf("\n\r SSID => %s", pSetting->ssid); + printf("\n\r CHANNEL => %d", pSetting->channel); + + switch(pSetting->security_type) { + case RTW_SECURITY_OPEN: + printf("\n\r SECURITY => OPEN"); + break; + case RTW_SECURITY_WEP_PSK: + printf("\n\r SECURITY => WEP"); + printf("\n\r KEY INDEX => %d", pSetting->key_idx); + break; + case RTW_SECURITY_WPA_TKIP_PSK: + printf("\n\r SECURITY => TKIP"); + break; + case RTW_SECURITY_WPA2_AES_PSK: + printf("\n\r SECURITY => AES"); + break; + default: + printf("\n\r SECURITY => UNKNOWN"); + } + + printf("\n\r PASSWORD => %s", pSetting->password); + printf("\n\r"); + + return ret; +} + +//----------------------------------------------------------------------------// +int wifi_set_network_mode(rtw_network_mode_t mode) +{ + if((mode == RTW_NETWORK_B) || (mode == RTW_NETWORK_BG) || (mode == RTW_NETWORK_BGN)) + return rltk_wlan_wireless_mode((unsigned char) mode); + + return -1; +} + +int wifi_set_wps_phase(unsigned char is_trigger_wps) +{ + return rltk_wlan_set_wps_phase(is_trigger_wps); +} + +//----------------------------------------------------------------------------// +int wifi_set_promisc(rtw_rcr_level_t enabled, void (*callback)(unsigned char*, unsigned int, void*), unsigned char len_used) +{ + return promisc_set(enabled, callback, len_used); +} + +void wifi_enter_promisc_mode(){ + int mode = 0; + unsigned char ssid[33]; + + if(wifi_mode == RTW_MODE_STA_AP){ + wifi_off(); + vTaskDelay(20); + wifi_on(RTW_MODE_PROMISC); + }else{ + wext_get_mode(WLAN0_NAME, &mode); + + switch(mode) { + case IW_MODE_MASTER: //In AP mode + rltk_wlan_deinit(); + vTaskDelay(20); + rltk_wlan_init(0, RTW_MODE_PROMISC); + rltk_wlan_start(0); + break; + case IW_MODE_INFRA: //In STA mode + if(wext_get_ssid(WLAN0_NAME, ssid) > 0) + wifi_disconnect(); + } + } +} + +int wifi_restart_ap( + unsigned char *ssid, + rtw_security_t security_type, + unsigned char *password, + int ssid_len, + int password_len, + int channel) +{ + unsigned char idx = 0; + struct ip_addr ipaddr; + struct ip_addr netmask; + struct ip_addr gw; + struct netif * pnetif = &xnetif[0]; +#ifdef CONFIG_CONCURRENT_MODE + rtw_wifi_setting_t setting; + int sta_linked = 0; +#endif + + if(rltk_wlan_running(WLAN1_IDX)){ + idx = 1; + } + + // stop dhcp server + dhcps_deinit(); + +#ifdef CONFIG_CONCURRENT_MODE + if(idx > 0){ + sta_linked = wifi_get_setting(WLAN0_NAME, &setting); + wifi_off(); + vTaskDelay(20); + wifi_on(RTW_MODE_STA_AP); + } + else +#endif + { + IP4_ADDR(&ipaddr, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3); + IP4_ADDR(&netmask, NETMASK_ADDR0, NETMASK_ADDR1 , NETMASK_ADDR2, NETMASK_ADDR3); + IP4_ADDR(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3); + netif_set_addr(pnetif, &ipaddr, &netmask,&gw); + wifi_off(); + vTaskDelay(20); + wifi_on(RTW_MODE_AP); + } + // start ap + if(wifi_start_ap((char*)ssid, security_type, (char*)password, ssid_len, password_len, channel) < 0) { + printf("\n\rERROR: Operation failed!"); + return -1; + } + +#if (INCLUDE_uxTaskGetStackHighWaterMark == 1) + printf("\r\nWebServer Thread: High Water Mark is %ld\n", uxTaskGetStackHighWaterMark(NULL)); +#endif +#ifdef CONFIG_CONCURRENT_MODE + // connect to ap if wlan0 was linked with ap + if(idx > 0 && sta_linked == 0){ + int ret; + printf("\r\nAP: ssid=%s", (char*)setting.ssid); + printf("\r\nAP: security_type=%d", setting.security_type); + printf("\r\nAP: password=%s", (char*)setting.password); + printf("\r\nAP: key_idx =%d\n", setting.key_idx); + ret = wifi_connect((char*)setting.ssid, + setting.security_type, + (char*)setting.password, + strlen((char*)setting.ssid), + strlen((char*)setting.password), + setting.key_idx, + NULL); +#if CONFIG_DHCP_CLIENT + if(ret == RTW_SUCCESS) { + /* Start DHCPClient */ + LwIP_DHCP(0, DHCP_START); + } +#endif + } +#endif +#if (INCLUDE_uxTaskGetStackHighWaterMark == 1) + printf("\r\nWebServer Thread: High Water Mark is %ld\n", uxTaskGetStackHighWaterMark(NULL)); +#endif + // start dhcp server + dhcps_init(&xnetif[idx]); + + return 0; +} + +#ifdef CONFIG_AUTO_RECONNECT +extern void (*p_wlan_autoreconnect_hdl)(rtw_security_t, char*, int, char*, int, int); + +struct wifi_autoreconnect_param { + rtw_security_t security_type; + char *ssid; + int ssid_len; + char *password; + int password_len; + int key_id; +}; + +static void wifi_autoreconnect_thread(void *param) +{ + int ret = RTW_ERROR; + struct wifi_autoreconnect_param *reconnect_param = (struct wifi_autoreconnect_param *) param; + ret = wifi_connect(reconnect_param->ssid, reconnect_param->security_type, reconnect_param->password, + reconnect_param->ssid_len, reconnect_param->password_len, reconnect_param->key_id, NULL); +#if CONFIG_LWIP_LAYER + if(ret == RTW_SUCCESS) + LwIP_DHCP(0, DHCP_START); +#endif + vTaskDelete(NULL); +} + +void wifi_autoreconnect_hdl(rtw_security_t security_type, + char *ssid, int ssid_len, + char *password, int password_len, + int key_id) +{ + static struct wifi_autoreconnect_param param; + param.security_type = security_type; + param.ssid = ssid; + param.ssid_len = ssid_len; + param.password = password; + param.password_len = password_len; + param.key_id = key_id; + xTaskCreate(wifi_autoreconnect_thread, (const char *)"wifi_autoreconnect", 512, ¶m, tskIDLE_PRIORITY + 1, NULL); +} + +int wifi_set_autoreconnect(__u8 mode) +{ + p_wlan_autoreconnect_hdl = wifi_autoreconnect_hdl; + return wext_set_autoreconnect(WLAN0_NAME, mode); +} + +int wifi_get_autoreconnect(__u8 *mode) +{ + return wext_get_autoreconnect(WLAN0_NAME, mode); +} +#endif + +#ifdef CONFIG_CUSTOM_IE +/* + * Example for custom ie + * + * u8 test_1[] = {221, 2, 2, 2}; + * u8 test_2[] = {221, 2, 1, 1}; + * cus_ie buf[2] = {{test_1, PROBE_REQ}, + * {test_2, PROBE_RSP | BEACON}}; + * u8 buf_test2[] = {221, 2, 1, 3} ; + * cus_ie buf_update = {buf_test2, PROBE_REQ}; + * + * add ie list + * static void cmd_add_ie(int argc, char **argv) + * { + * wifi_add_custom_ie((void *)buf, 2); + * } + * + * update current ie + * static void cmd_update_ie(int argc, char **argv) + * { + * wifi_update_custom_ie(&buf_update, 2); + * } + * + * delete all ie + * static void cmd_del_ie(int argc, char **argv) + * { + * wifi_del_custom_ie(); + * } + */ + +int wifi_add_custom_ie(void *cus_ie, int ie_num) +{ + return wext_add_custom_ie(WLAN0_NAME, cus_ie, ie_num); +} + + +int wifi_update_custom_ie(void *cus_ie, int ie_index) +{ + return wext_update_custom_ie(WLAN0_NAME, cus_ie, ie_index); +} + +int wifi_del_custom_ie() +{ + return wext_del_custom_ie(WLAN0_NAME); +} + +#endif + +#ifdef CONFIG_PROMISC +extern void promisc_init_packet_filter(void); +extern int promisc_add_packet_filter(u8 filter_id, rtw_packet_filter_pattern_t *patt, rtw_packet_filter_rule_e rule); +extern int promisc_enable_packet_filter(u8 filter_id); +extern int promisc_disable_packet_filter(u8 filter_id); +extern int promisc_remove_packet_filter(u8 filter_id); +void wifi_init_packet_filter() +{ + promisc_init_packet_filter(); +} + +int wifi_add_packet_filter(unsigned char filter_id, rtw_packet_filter_pattern_t *patt, rtw_packet_filter_rule_e rule) +{ + return promisc_add_packet_filter(filter_id, patt, rule); +} + +int wifi_enable_packet_filter(unsigned char filter_id) +{ + return promisc_enable_packet_filter(filter_id); +} + +int wifi_disable_packet_filter(unsigned char filter_id) +{ + return promisc_disable_packet_filter(filter_id); +} + +int wifi_remove_packet_filter(unsigned char filter_id) +{ + return promisc_remove_packet_filter(filter_id); +} +#endif + +#ifdef CONFIG_AP_MODE +int wifi_enable_forwarding(void) +{ + return wext_enable_forwarding(WLAN0_NAME); +} + +int wifi_disable_forwarding(void) +{ + return wext_disable_forwarding(WLAN0_NAME); +} +#endif + +//----------------------------------------------------------------------------// +#endif //#if CONFIG_WLAN diff --git a/component/common/api/wifi/wifi_conf.h b/component/common/api/wifi/wifi_conf.h new file mode 100644 index 0000000..7cd7abf --- /dev/null +++ b/component/common/api/wifi/wifi_conf.h @@ -0,0 +1,612 @@ +//----------------------------------------------------------------------------// +#ifndef __WIFI_API_H +#define __WIFI_API_H + +#include "FreeRTOS.h" +#include "wifi_constants.h" +#include "wifi_structures.h" +#include "wifi_util.h" +#include "wifi_ind.h" + +#ifdef __cplusplus + extern "C" { +#endif + +/****************************************************** + * Macros + ******************************************************/ + +#define RTW_ENABLE_API_INFO + +#ifdef RTW_ENABLE_API_INFO + #define RTW_API_INFO(args) do {printf args;} while(0) +#else + #define RTW_API_INFO(args) +#endif + +#define MAC_ARG(x) ((u8*)(x))[0],((u8*)(x))[1],((u8*)(x))[2],((u8*)(x))[3],((u8*)(x))[4],((u8*)(x))[5] +#define CMP_MAC( a, b ) (((a[0])==(b[0]))&& \ + ((a[1])==(b[1]))&& \ + ((a[2])==(b[2]))&& \ + ((a[3])==(b[3]))&& \ + ((a[4])==(b[4]))&& \ + ((a[5])==(b[5]))) + +/****************************************************** + * Constants + ******************************************************/ +#define SCAN_LONGEST_WAIT_TIME (4500) + + +#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x" + +#define PSCAN_ENABLE 0x01 //enable for partial channel scan +#define PSCAN_FAST_SURVEY 0x02 //set to select scan time to FAST_SURVEY_TO, otherwise SURVEY_TO + + +/****************************************************** + * Type Definitions + ******************************************************/ + +/** Scan result callback function pointer type + * + * @param result_ptr : A pointer to the pointer that indicates where to put the next scan result + * @param user_data : User provided data + */ +typedef void (*rtw_scan_result_callback_t)( rtw_scan_result_t** result_ptr, void* user_data ); +typedef rtw_result_t (*rtw_scan_result_handler_t)( rtw_scan_handler_result_t* malloced_scan_result ); + +/****************************************************** + * Structures + ******************************************************/ +typedef enum _WIFI_LINK_STATUS{ + WIFI_LINK_DISCONNECTED = 0, + WIFI_LINK_CONNECTED +}WIFI_LINK_STATUS; + +typedef struct { + char *buf; + int buf_len; +} scan_buf_arg; + +/****************************************************** + * Structures + ******************************************************/ +typedef struct internal_scan_handler{ + rtw_scan_result_t** pap_details; + rtw_scan_result_t * ap_details; + int scan_cnt; + rtw_bool_t scan_complete; + unsigned char max_ap_size; + rtw_scan_result_handler_t gscan_result_handler; +#if SCAN_USE_SEMAPHORE + void *scan_semaphore; +#else + int scan_running; +#endif + void* user_data; + unsigned int scan_start_time; +} internal_scan_handler_t; + +typedef struct { + rtw_network_info_t network_info; + void *join_sema; +} internal_join_result_t; + +/****************************************************** + * Function Declarations + ******************************************************/ +/** + * Initialises Realtek WiFi API System + * + * - Initialises the required parts of the software platform + * i.e. worker, event registering, semaphore, etc. + * + * - Initialises the RTW API thread which handles the asynchronous event + * + * @return RTW_SUCCESS if initialization is successful, RTW_ERROR otherwise + */ +int wifi_manager_init(void); + +/** Joins a Wi-Fi network + * + * Scans for, associates and authenticates with a Wi-Fi network. + * On successful return, the system is ready to send data packets. + * + * @param[in] ssid : A null terminated string containing the SSID name of the network to join + * @param[in] security_type : Authentication type: + * - RTW_SECURITY_OPEN - Open Security + * - RTW_SECURITY_WEP_PSK - WEP Security with open authentication + * - RTW_SECURITY_WEP_SHARED - WEP Security with shared authentication + * - RTW_SECURITY_WPA_TKIP_PSK - WPA Security + * - RTW_SECURITY_WPA2_AES_PSK - WPA2 Security using AES cipher + * - RTW_SECURITY_WPA2_TKIP_PSK - WPA2 Security using TKIP cipher + * - RTW_SECURITY_WPA2_MIXED_PSK - WPA2 Security using AES and/or TKIP ciphers + * @param[in] password : A byte array containing either the + * cleartext security key for WPA/WPA2 + * secured networks, or a pointer to + * an array of rtw_wep_key_t + * structures for WEP secured networks + * @param[in] ssid_len : The length of the SSID in + * bytes. + * @param[in] password_len : The length of the security_key in + * bytes. + * @param[in] key_id : The index of the wep key. + * @param[in] semaphore : A user provided semaphore that is flagged when the join is complete + * + * @return RTW_SUCCESS : when the system is joined and ready + * to send data packets + * RTW_ERROR : if an error occurred + */ +int wifi_connect( + char *ssid, + rtw_security_t security_type, + char *password, + int ssid_len, + int password_len, + int key_id, + void *semaphore); + +int wifi_connect_bssid( + unsigned char bssid[ETH_ALEN], + char *ssid, + rtw_security_t security_type, + char *password, + int bssid_len, + int ssid_len, + int password_len, + int key_id, + void *semaphore); + +/** Disassociates from a Wi-Fi network. + * + * @return RTW_SUCCESS : On successful disassociation from + * the AP + * RTW_ERROR : If an error occurred +*/ +int wifi_disconnect(void); + +/** Check if the interface specified is up. + * + * @return RTW_TRUE : If it's up + * RTW_FALSE : If it's not +*/ +int wifi_is_up(rtw_interface_t interface); + +/** Determines if a particular interface is ready to transceive ethernet packets + * + * @param Radio interface to check, options are + * RTW_STA_INTERFACE, RTW_AP_INTERFACE + * @return RTW_SUCCESS : if the interface is ready to + * transceive ethernet packets + * @return RTW_NOTFOUND : no AP with a matching SSID was + * found + * @return RTW_NOT_AUTHENTICATED: a matching AP was found but + * it won't let you + * authenticate. This can + * occur if this device is + * in the block list on the + * AP. + * @return RTW_NOT_KEYED: the device has authenticated and + * associated but has not completed + * the key exchange. This can occur + * if the passphrase is incorrect. + * @return RTW_ERROR : if the interface is not ready to + * transceive ethernet packets + */ +int wifi_is_ready_to_transceive(rtw_interface_t interface); + +/** ---------------------------------------------------------------------- + * WARNING : This function is for internal use only! + * ---------------------------------------------------------------------- + * This function sets the current Media Access Control (MAC) address of the + * 802.11 device. + * + * @param[in] mac Wi-Fi MAC address + * @return RTW_SUCCESS or RTW_ERROR + */ +int wifi_set_mac_address(char * mac); + +/** Retrieves the current Media Access Control (MAC) address + * (or Ethernet hardware address) of the 802.11 device + * + * @param mac Pointer to a variable that the current MAC address will be written to + * @return RTW_SUCCESS or RTW_ERROR + */ +int wifi_get_mac_address(char * mac); + +/** Enables powersave mode + * + * @return @ref rtw_result_t + */ +int wifi_enable_powersave(void); + +/** Disables 802.11 power save mode + * + * @return RTW_SUCCESS : if power save mode was successfully + * disabled + * RTW_ERROR : if power save mode was not successfully + * disabled + */ +int wifi_disable_powersave(void); + +/** Gets the tx power in index units + * + * @param dbm : The variable to receive the tx power in index. + * + * @return RTW_SUCCESS : if successful + * RTW_ERROR : if not successful + */ +int wifi_get_txpower(int *poweridx); + +/** Sets the tx power in index units + * + * @param dbm : The desired tx power in index. + * + * @return RTW_SUCCESS : if tx power was successfully set + * RTW_ERROR : if tx power was not successfully set + */ +int wifi_set_txpower(int poweridx); + +/** Get the associated clients with SoftAP + * + * @param client_list_buffer : the location where the client + * list will be stored + * @param buffer_length : the buffer length. + * + * @return RTW_SUCCESS : if result was successfully get + * RTW_ERROR : if result was not successfully get + */ +int wifi_get_associated_client_list(void * client_list_buffer, unsigned short buffer_length); + +/** Get the SoftAP information + * + * @param ap_info : the location where the AP info will be + * stored + * @param security : the security type. + * + * @return RTW_SUCCESS : if result was successfully get + * RTW_ERROR : if result was not successfully get + */ +int wifi_get_ap_info(rtw_bss_info_t * ap_info, rtw_security_t* security); + +/** Set the country code to driver to determine the channel set + * + * @param country_code : the country code. + * + * @return RTW_SUCCESS : if result was successfully set + * RTW_ERROR : if result was not successfully set + */ +int wifi_set_country(rtw_country_code_t country_code); + +/** Retrieve the latest RSSI value + * + * @param rssi: The location where the RSSI value will be stored + * + * @return RTW_SUCCESS : if the RSSI was succesfully retrieved + * RTW_ERROR : if the RSSI was not retrieved + */ +int wifi_get_rssi(int *pRSSI); + +/** Set the current channel on STA interface + * + * @param channel : The desired channel + * + * @return RTW_SUCCESS : if the channel was successfully set + * RTW_ERROR : if the channel was not successfully + * set + */ +int wifi_set_channel(int channel); + +/** Get the current channel on STA interface + * + * @param channel : A pointer to the variable where the + * channel value will be written + * + * @return RTW_SUCCESS : if the channel was successfully read + * RTW_ERROR : if the channel was not successfully + * read + */ +int wifi_get_channel(int *channel); + +/** Registers interest in a multicast address + * Once a multicast address has been registered, all packets detected on the + * medium destined for that address are forwarded to the host. + * Otherwise they are ignored. + * + * @param mac: Ethernet MAC address + * + * @return RTW_SUCCESS : if the address was registered + * successfully + * RTW_ERROR : if the address was not registered + */ +int wifi_register_multicast_address(rtw_mac_t *mac); + +/** Unregisters interest in a multicast address + * Once a multicast address has been unregistered, all packets detected on the + * medium destined for that address are ignored. + * + * @param mac: Ethernet MAC address + * + * @return RTW_SUCCESS : if the address was unregistered + * successfully + * RTW_ERROR : if the address was not unregistered + */ +int wifi_unregister_multicast_address(rtw_mac_t *mac); + +int wifi_rf_on(void); +int wifi_rf_off(void); + +/** Turn on the Wi-Fi device + * + * - Bring the Wireless interface "Up" + * - Initialises the driver thread which arbitrates access + * to the SDIO/SPI bus + * + * @param mode: wifi work mode + * + * @return RTW_SUCCESS : if the WiFi chip was initialised + * successfully + * RTW_ERROR : if the WiFi chip was not initialised + * successfully + */ +int wifi_on(rtw_mode_t mode); + +/** + * Turn off the Wi-Fi device + * + * - Bring the Wireless interface "Down" + * - De-Initialises the driver thread which arbitrates access + * to the SDIO/SPI bus + * + * @return RTW_SUCCESS if deinitialization is successful, + * RTW_ERROR otherwise + */ +int wifi_off(void); + +/** Starts an infrastructure WiFi network + * + * @warning If a STA interface is active when this function is called, the softAP will\n + * start on the same channel as the STA. It will NOT use the channel provided! + * + * @param[in] ssid : A null terminated string containing + * the SSID name of the network to join + * @param[in] security_type : Authentication type: \n + * - RTW_SECURITY_OPEN - Open Security \n + * - RTW_SECURITY_WPA_TKIP_PSK - WPA Security \n + * - RTW_SECURITY_WPA2_AES_PSK - WPA2 Security using AES cipher \n + * - RTW_SECURITY_WPA2_MIXED_PSK - WPA2 Security using AES and/or TKIP ciphers \n + * - WEP security is NOT IMPLEMENTED. It is NOT SECURE! \n + * @param[in] password : A byte array containing the cleartext + * security key for the network + * @param[in] ssid_len : The length of the SSID in + * bytes. + * @param[in] password_len : The length of the security_key in + * bytes. + * @param[in] channel : 802.11 channel number + * + * @return RTW_SUCCESS : if successfully creates an AP + * RTW_ERROR : if an error occurred + */ +int wifi_start_ap( + char *ssid, + rtw_security_t security_type, + char *password, + int ssid_len, + int password_len, + int channel); + +/** Initiates a scan to search for 802.11 networks. + * + * The scan progressively accumulates results over time, and + * may take between 1 and 3 seconds to complete. The results of + * the scan will be individually provided to the callback + * function. Note: The callback function will be executed in + * the context of the RTW thread. + * + * @param[in] scan_type : Specifies whether the scan should + * be Active, Passive or scan Prohibited channels + * @param[in] bss_type : Specifies whether the scan should + * search for Infrastructure + * networks (those using an Access + * Point), Ad-hoc networks, or both + * types. + * @param callback[in] : the callback function which will + * receive and process the result data. + * @param result_ptr[in] : a pointer to a pointer to a result + * storage structure. + * @param user_data[in] : user specific data that will be + * passed directly to the callback function + * + * @note : When scanning specific channels, devices with a + * strong signal strength on nearby channels may be + * detected + * @note : Callback must not use blocking functions, since it is + * called from the context of the RTW thread. + * @note : The callback, result_ptr and user_data variables will + * be referenced after the function returns. Those + * variables must remain valid until the scan is + * complete. + * + * @return RTW_SUCCESS or RTW_ERROR + */ +int wifi_scan(rtw_scan_type_t scan_type, + rtw_bss_type_t bss_type, + void* result_ptr); + +/** Initiates a scan to search for 802.11 networks, a higher + * level API based on wifi_scan to simplify the scan + * operation. + * + * The scan results will be list by the order of RSSI. + * It may demand hundreds bytes memory during scan + * processing according to the quantity of AP nearby. + * + * @param results_handler[in] : the callback function which + * will receive and process the result data. + * @param user_data[in] : user specific data that will be + * passed directly to the callback function + * + * @note : Callback must not use blocking functions, since it is + * called from the context of the RTW thread. + * @note : The callback, user_data variables will + * be referenced after the function returns. Those + * variables must remain valid until the scan is + * complete. + * + * @return RTW_SUCCESS or RTW_ERROR + */ +int wifi_scan_networks(rtw_scan_result_handler_t results_handler, void* user_data); +int wifi_scan_networks_with_ssid(rtw_scan_result_handler_t results_handler, void* user_data, char* ssid, int ssid_len); + +/** Set the partical scan + * + * @param channel_list[in] : the channel set the scan will + * stay on + * @param pscan_config[in] : the pscan_config of the channel set + * + * @param length[in] : the channel list length + * + * @return RTW_SUCCESS or RTW_ERROR + */ +int wifi_set_pscan_chan(__u8 * channel_list,__u8 * pscan_config, __u8 length); + +/** Get the network information + * + * @param ifname[in] : the name of the interface we are care + * @param pSetting[in] : the location where the network + * information will be stored + * + * @return RTW_SUCCESS or RTW_ERROR + */ +int wifi_get_setting(const char *ifname,rtw_wifi_setting_t *pSetting); + +/** Show the network information + * + * @param ifname[in] : the name of the interface we are care + * @param pSetting[in] : the location where the network + * information was stored + * + * @return RTW_SUCCESS or RTW_ERROR + */ +int wifi_show_setting(const char *ifname,rtw_wifi_setting_t *pSetting); + +/** Set the network mode according to the data rate it's + * supported + * + * @param mode[in] : the network mode + * + * @return RTW_SUCCESS or RTW_ERROR + */ +int wifi_set_network_mode(rtw_network_mode_t mode); + +/** Set the chip to worke in the promisc mode + * + * @param enabled[in] : enabled can be set 0, 1 and 2. if enabled is zero, disable the promisc, else enable the promisc. + * 0 means disable the promisc + * 1 means enable the promisc + * 2 means enable the promisc special for length is used + * @param callback[in] : the callback function which will + * receive and process the netowork data. + * @param len_used[in] : specify if the the promisc length is + * used. + * + * @return RTW_SUCCESS or RTW_ERROR + */ +int wifi_set_promisc(rtw_rcr_level_t enabled, void (*callback)(unsigned char*, unsigned int, void*), unsigned char len_used); + +/** Set the wps phase + * + * @param is_trigger_wps[in] : to trigger wps function or not + * + * @return RTW_SUCCESS or RTW_ERROR + */ +int wifi_set_wps_phase(unsigned char is_trigger_wps); + +/** Restarts an infrastructure WiFi network + * + * @warning If a STA interface is active when this function is called, the softAP will\n + * start on the same channel as the STA. It will NOT use the channel provided! + * + * @param[in] ssid : A null terminated string containing + * the SSID name of the network to join + * @param[in] security_type : Authentication type: \n + * - RTW_SECURITY_OPEN - Open Security \n + * - RTW_SECURITY_WPA_TKIP_PSK - WPA Security \n + * - RTW_SECURITY_WPA2_AES_PSK - WPA2 Security using AES cipher \n + * - RTW_SECURITY_WPA2_MIXED_PSK - WPA2 Security using AES and/or TKIP ciphers \n + * - WEP security is NOT IMPLEMENTED. It is NOT SECURE! \n + * @param[in] password : A byte array containing the cleartext + * security key for the network + * @param[in] ssid_len : The length of the SSID in + * bytes. + * @param[in] password_len : The length of the security_key in + * bytes. + * @param[in] channel : 802.11 channel number + * + * @return RTW_SUCCESS : if successfully creates an AP + * RTW_ERROR : if an error occurred + */ +int wifi_restart_ap( + unsigned char *ssid, + rtw_security_t security_type, + unsigned char *password, + int ssid_len, + int password_len, + int channel); + + +int wifi_set_autoreconnect(__u8 mode); +int wifi_get_autoreconnect(__u8 *mode); +int wifi_get_last_error( ); +#ifdef CONFIG_CUSTOM_IE +#ifndef BIT +#define BIT(x) ((__u32)1 << (x)) +#endif + +#ifndef _CUSTOM_IE_TYPE_ +#define _CUSTOM_IE_TYPE_ +enum CUSTOM_IE_TYPE{ + PROBE_REQ = BIT(0), + PROBE_RSP = BIT(1), + BEACON = BIT(2), +}; +#endif /* _CUSTOM_IE_TYPE_ */ + +/* ie format + * +-----------+--------+-----------------------+ + * |element ID | length | content in length byte| + * +-----------+--------+-----------------------+ + * + * type: refer to CUSTOM_IE_TYPE + */ +#ifndef _CUS_IE_ +#define _CUS_IE_ +typedef struct _cus_ie{ + __u8 *ie; + __u8 type; +}cus_ie, *p_cus_ie; +#endif /* _CUS_IE_ */ + +int wifi_add_custom_ie(void *cus_ie, int ie_num); + +int wifi_update_custom_ie(void *cus_ie, int ie_index); + +int wifi_del_custom_ie(void); +#endif + +#ifdef CONFIG_PROMISC +void wifi_init_packet_filter(void); +int wifi_add_packet_filter(unsigned char filter_id, rtw_packet_filter_pattern_t *patt, rtw_packet_filter_rule_e rule); +int wifi_enable_packet_filter(unsigned char filter_id); +int wifi_disable_packet_filter(unsigned char filter_id); +int wifi_remove_packet_filter(unsigned char filter_id); +#endif + +#ifdef __cplusplus + } +#endif + +#endif // __WIFI_API_H + +//----------------------------------------------------------------------------// diff --git a/component/common/api/wifi/wifi_ind.c b/component/common/api/wifi/wifi_ind.c new file mode 100644 index 0000000..b5ed305 --- /dev/null +++ b/component/common/api/wifi/wifi_ind.c @@ -0,0 +1,236 @@ +//----------------------------------------------------------------------------// +#include "wifi/wifi_ind.h" +#include "wifi/wifi_conf.h" +#include "osdep_service.h" + +/****************************************************** + * Constants + ******************************************************/ + +#define WIFI_INDICATE_MSG 0 +#define WIFI_MANAGER_STACKSIZE 128 +#define WIFI_MANAGER_PRIORITY (5) +#define WIFI_MANAGER_PRIO 2 + +#define INDICATE_USE_THREAD 0 +#define WIFI_EVENT_MAX_ROW 3 +/****************************************************** + * Globals + ******************************************************/ + +static event_list_elem_t event_callback_list[WIFI_EVENT_MAX][WIFI_EVENT_MAX_ROW]; +#if INDICATE_USE_THREAD +static rtw_worker_thread_t wifi_worker_thread; +#endif + +//----------------------------------------------------------------------------// +#if INDICATE_USE_THREAD +static rtw_result_t rtw_send_event_to_worker(int event_cmd, char *buf, int buf_len, int flags) +{ + rtw_event_message_t message; + int i; + rtw_result_t ret = RTW_SUCCESS; + + if(event_cmd >= WIFI_EVENT_MAX) + return RTW_BADARG; + for(i = 0; i < WIFI_EVENT_MAX_ROW; i++){ + if(event_callback_list[event_cmd][i].handler == NULL) + continue; + + message.function = (event_handler_t)event_callback_list[event_cmd][i].handler; + message.buf = buf; + message.buf_len = buf_len; + message.flags = flags; + message.user_data = event_callback_list[event_cmd][i].handler_user_data; + + ret = rtw_push_to_xqueue(&wifi_worker_thread->event_queue, &message, 0); + if(ret != RTW_SUCCESS) + break; + } + return ret; +} +#else +static rtw_result_t rtw_indicate_event_handle(int event_cmd, char *buf, int buf_len, int flags) +{ + rtw_event_handler_t handle = NULL; + int i; + + if(event_cmd >= WIFI_EVENT_MAX) + return RTW_BADARG; + + for(i = 0; i < WIFI_EVENT_MAX_ROW; i++){ + handle = event_callback_list[event_cmd][i].handler; + if(handle == NULL) + continue; + handle(buf, buf_len, flags, event_callback_list[event_cmd][i].handler_user_data); + } + + return RTW_SUCCESS; +} +#endif + +void wifi_indication( WIFI_EVENT_INDICATE event, char *buf, int buf_len, int flags) +{ + // + // If upper layer application triggers additional operations on receiving of wext_wlan_indicate, + // please strictly check current stack size usage (by using uxTaskGetStackHighWaterMark() ) + // , and tries not to share the same stack with wlan driver if remaining stack space is + // not available for the following operations. + // ex: using semaphore to notice another thread. + switch(event) + { + case WIFI_EVENT_DISCONNECT: +#if(WIFI_INDICATE_MSG==1) + printf("\n\r %s():Disconnection indication received", __FUNCTION__); +#endif +#if CONFIG_INIC_EN + inic_indicate_event(WIFI_LINK_DISCONNECTED); +#endif//CONFIG_INIC_EN + break; + case WIFI_EVENT_CONNECT: + // For WPA/WPA2 mode, indication of connection does not mean data can be + // correctly transmitted or received. Data can be correctly transmitted or + // received only when 4-way handshake is done. + // Please check WIFI_EVENT_FOURWAY_HANDSHAKE_DONE event +#if(WIFI_INDICATE_MSG==1) + // Sample: return mac address + if(buf != NULL && buf_len == 6) + { + printf("\n\r%s():Connect indication received: %02x:%02x:%02x:%02x:%02x:%02x", __FUNCTION__, + buf[0],buf[1],buf[2],buf[3],buf[4],buf[5]); + } +#endif +#if CONFIG_INIC_EN + inic_indicate_event(WIFI_LINK_CONNECTED); +#endif//CONFIG_INIC_EN + break; + case WIFI_EVENT_FOURWAY_HANDSHAKE_DONE: +#if(WIFI_INDICATE_MSG==1) + if(buf != NULL) + { + if(buf_len == strlen(IW_EXT_STR_FOURWAY_DONE)) + printf("\n\r%s():%s", __FUNCTION__, buf); + } +#endif + break; + case WIFI_EVENT_SCAN_RESULT_REPORT: +#if(WIFI_INDICATE_MSG==1) + printf("\n\r%s(): WIFI_EVENT_SCAN_RESULT_REPORT\n", __func__); +#endif + break; + case WIFI_EVENT_SCAN_DONE: +#if(WIFI_INDICATE_MSG==1) + printf("\n\r%s(): WIFI_EVENT_SCAN_DONE\n", __func__); +#endif + break; + case WIFI_EVENT_RECONNECTION_FAIL: +#if(WIFI_INDICATE_MSG==1) + if(buf != NULL){ + if(buf_len == strlen(IW_EXT_STR_RECONNECTION_FAIL)) + printf("\n\r%s", buf); + } +#endif + break; + case WIFI_EVENT_NO_NETWORK: +#if(WIFI_INDICATE_MSG==1) + printf("\n\r%s(): WIFI_EVENT_NO_NETWORK\n", __func__); +#endif + break; +#ifdef CONFIG_P2P_NEW + case WIFI_EVENT_SEND_ACTION_DONE: +#if(WIFI_INDICATE_MSG==1) + printf("\n\r%s(): WIFI_EVENT_SEND_ACTION_DONE\n", __func__); +#endif + break; + case WIFI_EVENT_RX_MGNT: +#if(WIFI_INDICATE_MSG==1) + printf("\n\r%s(): WIFI_EVENT_RX_MGNT\n", __func__); +#endif + break; + case WIFI_EVENT_STA_ASSOC: +#if(WIFI_INDICATE_MSG==1) + printf("\n\r%s(): WIFI_EVENT_STA_ASSOC\n", __func__); +#endif + break; + case WIFI_EVENT_STA_DISASSOC: +#if(WIFI_INDICATE_MSG==1) + printf("\n\r%s(): WIFI_EVENT_STA_DISASSOC\n", __func__); +#endif + break; +#endif //CONFIG_P2P_NEW +#ifdef CONFIG_WPS + case WIFI_EVENT_WPS_FINISH: +#if(WIFI_INDICATE_MSG==1) + printf("\n\r%s(): WIFI_EVENT_WPS_FINISH\n", __func__); +#endif + break; + case WIFI_EVENT_EAPOL_RECVD: +#if(WIFI_INDICATE_MSG==1) + printf("\n\r%s(): WIFI_EVENT_EAPOL_RECVD\n", __func__); +#endif + break; +#endif + case WIFI_EVENT_BEACON_AFTER_DHCP: +#if(WIFI_INDICATE_MSG==1) + printf("\n\r%s(): WIFI_EVENT_BEACON_AFTER_DHCP\n", __func__); +#endif + break; + } + +#if INDICATE_USE_THREAD + rtw_send_event_to_worker(event, buf, buf_len, flags); +#else + rtw_indicate_event_handle(event, buf, buf_len, flags); +#endif +} + +void wifi_reg_event_handler(unsigned int event_cmds, rtw_event_handler_t handler_func, void *handler_user_data) +{ + int i = 0; + if(event_cmds < WIFI_EVENT_MAX){ + for(i=0; i < WIFI_EVENT_MAX_ROW; i++){ + if(event_callback_list[event_cmds][i].handler == NULL){ + event_callback_list[event_cmds][i].handler = handler_func; + event_callback_list[event_cmds][i].handler_user_data = handler_user_data; + return; + } + } + } +} + +void wifi_unreg_event_handler(unsigned int event_cmds, rtw_event_handler_t handler_func) +{ + int i; + if(event_cmds < WIFI_EVENT_MAX){ + for(i = 0; i < WIFI_EVENT_MAX_ROW; i++){ + if(event_callback_list[event_cmds][i].handler == handler_func){ + event_callback_list[event_cmds][i].handler = NULL; + event_callback_list[event_cmds][i].handler_user_data = NULL; + return; + } + } + } +} + +void init_event_callback_list(){ + memset(event_callback_list, 0, sizeof(event_callback_list)); +} + +int wifi_manager_init() +{ +#if INDICATE_USE_THREAD + rtw_create_worker_thread(&wifi_worker_thread, + WIFI_MANAGER_PRIORITY, + WIFI_MANAGER_STACKSIZE, + WIFI_MANAGER_PRIO); +#endif + return 0; +} + +void rtw_wifi_manager_deinit() +{ +#if INDICATE_USE_THREAD + rtw_delete_worker_thread(&wifi_worker_thread); +#endif +} + diff --git a/component/common/api/wifi/wifi_ind.h b/component/common/api/wifi/wifi_ind.h new file mode 100644 index 0000000..be708ea --- /dev/null +++ b/component/common/api/wifi/wifi_ind.h @@ -0,0 +1,52 @@ +#ifndef _WIFI_INDICATE_H +#define _WIFI_INDICATE_H +#include "wifi_conf.h" + +typedef enum _WIFI_EVENT_INDICATE{ + WIFI_EVENT_CONNECT = 0, + WIFI_EVENT_DISCONNECT = 1, + WIFI_EVENT_FOURWAY_HANDSHAKE_DONE = 2, + WIFI_EVENT_SCAN_RESULT_REPORT = 3, + WIFI_EVENT_SCAN_DONE = 4, + WIFI_EVENT_RECONNECTION_FAIL = 5, + WIFI_EVENT_SEND_ACTION_DONE = 6, + WIFI_EVENT_RX_MGNT = 7, + WIFI_EVENT_STA_ASSOC = 8, + WIFI_EVENT_STA_DISASSOC = 9, + WIFI_EVENT_WPS_FINISH = 10, + WIFI_EVENT_EAPOL_RECVD = 11, + WIFI_EVENT_NO_NETWORK = 12, + WIFI_EVENT_BEACON_AFTER_DHCP = 13, + WIFI_EVENT_MAX, +}WIFI_EVENT_INDICATE; + +typedef void (*rtw_event_handler_t)(char *buf, int buf_len, int flags, void* handler_user_data ); + +typedef struct +{ +// WIFI_EVENT_INDICATE event_cmd; + rtw_event_handler_t handler; + void* handler_user_data; +} event_list_elem_t; + +void init_event_callback_list(void); +extern void wifi_indication( WIFI_EVENT_INDICATE event, char *buf, int buf_len, int flags); +/** Register the event listener + * + * @param[in] event_cmds : The event command number indicated + * @param[in] handler_func : the callback function which will + * receive and process the event + * @param[in] handler_user_data : user specific data that will be + * passed directly to the callback function + * + * @note : Set the same event_cmds with empty handler_func will + * unregister the event_cmds + * + * @return RTW_SUCCESS : if successfully registers the event + * RTW_ERROR : if an error occurred + */ +extern void wifi_reg_event_handler(unsigned int event_cmds, rtw_event_handler_t handler_func, void *handler_user_data); +extern void wifi_unreg_event_handler(unsigned int event_cmds, rtw_event_handler_t handler_func); + +#endif //_WIFI_INDICATE_H + diff --git a/component/common/api/wifi/wifi_promisc.c b/component/common/api/wifi/wifi_promisc.c new file mode 100644 index 0000000..51c0633 --- /dev/null +++ b/component/common/api/wifi/wifi_promisc.c @@ -0,0 +1,333 @@ +#include "FreeRTOS.h" +#include "task.h" +#include "main.h" +#include "tcpip.h" +#include "wifi/wifi_conf.h" + +#ifndef CONFIG_WLAN +#define CONFIG_WLAN 1 +#endif + +#if CONFIG_WLAN +#include + +struct eth_frame { + struct eth_frame *prev; + struct eth_frame *next; + unsigned char da[6]; + unsigned char sa[6]; + unsigned int len; + unsigned char type; +}; + +struct eth_buffer { + struct eth_frame *head; + struct eth_frame *tail; +}; + +static struct eth_buffer eth_buffer; + +#ifdef CONFIG_PROMISC +#define MAX_PACKET_FILTER_INFO 5 +#define FILTER_ID_INIT_VALUE 10 +rtw_packet_filter_info_t paff_array[MAX_PACKET_FILTER_INFO]={0, 0, 0, 0, 0}; +static u8 packet_filter_enable_num = 0; + +void promisc_init_packet_filter() +{ + int i = 0; + for(i=0; ioffset; + paff_array[i].patt.mask_size = patt->mask_size; + paff_array[i].patt.mask = pvPortMalloc(patt->mask_size); + memcpy(paff_array[i].patt.mask, patt->mask, patt->mask_size); + paff_array[i].patt.pattern= pvPortMalloc(patt->mask_size); + memcpy(paff_array[i].patt.pattern, patt->pattern, patt->mask_size); + + paff_array[i].rule = rule; + paff_array[i].enable = 0; + + return 0; +} + +int promisc_enable_packet_filter(u8 filter_id) +{ + int i = 0; + while(i < MAX_PACKET_FILTER_INFO){ + if(paff_array[i].filter_id == filter_id) + break; + i++; + } + + if(i == MAX_PACKET_FILTER_INFO) + return -1; + + paff_array[i].enable = 1; + packet_filter_enable_num++; + return 0; +} + +int promisc_disable_packet_filter(u8 filter_id) +{ + int i = 0; + while(i < MAX_PACKET_FILTER_INFO){ + if(paff_array[i].filter_id == filter_id) + break; + i++; + } + + if(i == MAX_PACKET_FILTER_INFO) + return -1; + + paff_array[i].enable = 0; + packet_filter_enable_num--; + return 0; +} + +int promisc_remove_packet_filter(u8 filter_id) +{ + int i = 0; + while(i < MAX_PACKET_FILTER_INFO){ + if(paff_array[i].filter_id == filter_id) + break; + i++; + } + + if(i == MAX_PACKET_FILTER_INFO) + return -1; + + paff_array[i].filter_id = FILTER_ID_INIT_VALUE; + paff_array[i].enable = 0; + paff_array[i].patt.mask_size = 0; + paff_array[i].rule = 0; + if(paff_array[i].patt.mask){ + vPortFree(paff_array[i].patt.mask); + paff_array[i].patt.mask = NULL; + } + + if(paff_array[i].patt.pattern){ + vPortFree(paff_array[i].patt.pattern); + paff_array[i].patt.pattern = NULL; + } + return 0; +} +#endif + +/* Make callback simple to prevent latency to wlan rx when promiscuous mode */ +static void promisc_callback(unsigned char *buf, unsigned int len, void* userdata) +{ + struct eth_frame *frame = (struct eth_frame *) pvPortMalloc(sizeof(struct eth_frame)); + + if(frame) { + frame->prev = NULL; + frame->next = NULL; + memcpy(frame->da, buf, 6); + memcpy(frame->sa, buf+6, 6); + frame->len = len; + + taskENTER_CRITICAL(); + + if(eth_buffer.tail) { + eth_buffer.tail->next = frame; + frame->prev = eth_buffer.tail; + eth_buffer.tail = frame; + } + else { + eth_buffer.head = frame; + eth_buffer.tail = frame; + } + + taskEXIT_CRITICAL(); + } +} + +struct eth_frame* retrieve_frame(void) +{ + struct eth_frame *frame = NULL; + + taskENTER_CRITICAL(); + + if(eth_buffer.head) { + frame = eth_buffer.head; + + if(eth_buffer.head->next) { + eth_buffer.head = eth_buffer.head->next; + eth_buffer.head->prev = NULL; + } + else { + eth_buffer.head = NULL; + eth_buffer.tail = NULL; + } + } + + taskEXIT_CRITICAL(); + + return frame; +} + +static void promisc_test(int duration, unsigned char len_used) +{ + int ch; + unsigned int start_time; + struct eth_frame *frame; + eth_buffer.head = NULL; + eth_buffer.tail = NULL; + + wifi_enter_promisc_mode(); + wifi_set_promisc(RTW_PROMISC_ENABLE, promisc_callback, len_used); + + for(ch = 1; ch <= 13; ch ++) { + if(wifi_set_channel(ch) == 0) + printf("\n\n\rSwitch to channel(%d)", ch); + + start_time = xTaskGetTickCount(); + + while(1) { + unsigned int current_time = xTaskGetTickCount(); + + if((current_time - start_time) < (duration * configTICK_RATE_HZ)) { + frame = retrieve_frame(); + + if(frame) { + int i; + printf("\n\rDA:"); + for(i = 0; i < 6; i ++) + printf(" %02x", frame->da[i]); + printf(", SA:"); + for(i = 0; i < 6; i ++) + printf(" %02x", frame->sa[i]); + printf(", len=%d", frame->len); + + vPortFree((void *) frame); + } + else + vTaskDelay(1); //delay 1 tick + } + else + break; + } + } + + wifi_set_promisc(RTW_PROMISC_DISABLE, NULL, 0); + + while((frame = retrieve_frame()) != NULL) + vPortFree((void *) frame); +} + +static void promisc_callback_all(unsigned char *buf, unsigned int len, void* userdata) +{ + struct eth_frame *frame = (struct eth_frame *) pvPortMalloc(sizeof(struct eth_frame)); + + if(frame) { + frame->prev = NULL; + frame->next = NULL; + memcpy(frame->da, buf+4, 6); + memcpy(frame->sa, buf+10, 6); + frame->len = len; + frame->type = *buf; + + taskENTER_CRITICAL(); + + if(eth_buffer.tail) { + eth_buffer.tail->next = frame; + frame->prev = eth_buffer.tail; + eth_buffer.tail = frame; + } + else { + eth_buffer.head = frame; + eth_buffer.tail = frame; + } + + taskEXIT_CRITICAL(); + } +} +static void promisc_test_all(int duration, unsigned char len_used) +{ + int ch; + unsigned int start_time; + struct eth_frame *frame; + eth_buffer.head = NULL; + eth_buffer.tail = NULL; + + wifi_enter_promisc_mode(); + wifi_set_promisc(RTW_PROMISC_ENABLE_2, promisc_callback_all, len_used); + + for(ch = 1; ch <= 13; ch ++) { + if(wifi_set_channel(ch) == 0) + printf("\n\n\rSwitch to channel(%d)", ch); + + start_time = xTaskGetTickCount(); + + while(1) { + unsigned int current_time = xTaskGetTickCount(); + + if((current_time - start_time) < (duration * configTICK_RATE_HZ)) { + frame = retrieve_frame(); + + if(frame) { + int i; + printf("\n\rTYPE: 0x%x, ", frame->type); + printf("DA:"); + for(i = 0; i < 6; i ++) + printf(" %02x", frame->da[i]); + printf(", SA:"); + for(i = 0; i < 6; i ++) + printf(" %02x", frame->sa[i]); + printf(", len=%d", frame->len); + + vPortFree((void *) frame); + } + else + vTaskDelay(1); //delay 1 tick + } + else + break; + } + } + + wifi_set_promisc(RTW_PROMISC_DISABLE, NULL, 0); + + while((frame = retrieve_frame()) != NULL) + vPortFree((void *) frame); +} + +void cmd_promisc(int argc, char **argv) +{ + int duration; + #ifdef CONFIG_PROMISC + wifi_init_packet_filter(); + #endif + if((argc == 2) && ((duration = atoi(argv[1])) > 0)) + //promisc_test(duration, 0); + promisc_test_all(duration, 0); + else if((argc == 3) && ((duration = atoi(argv[1])) > 0) && (strcmp(argv[2], "with_len") == 0)) + promisc_test(duration, 1); + else + printf("\n\rUsage: %s DURATION_SECONDS [with_len]", argv[0]); +} +#endif //#if CONFIG_WLAN diff --git a/component/common/api/wifi/wifi_simple_config.c b/component/common/api/wifi/wifi_simple_config.c new file mode 100644 index 0000000..a34bcc6 --- /dev/null +++ b/component/common/api/wifi/wifi_simple_config.c @@ -0,0 +1,602 @@ +#include +#include +#include +#include "FreeRTOS.h" +#include "task.h" +#include "main.h" +#include "udp.h" +#include +#include +#include +#include "platform_stdlib.h" + +#define STACKSIZE 512 + + +#if CONFIG_WLAN +#if (CONFIG_INCLUDE_SIMPLE_CONFIG) +#include "wifi/wifi_conf.h" +int is_promisc_callback_unlock = 0; +static int is_fixed_channel; +int fixed_channel_num; +unsigned char g_ssid[32]; +int g_ssid_len; +extern unsigned char g_bssid[]; +extern unsigned char g_security_mode; +extern int promisc_get_fixed_channel( void *, u8 *, int* ); +struct pattern_test_ops; +struct rtk_test_sc; + +typedef int (*sc_test_check_pattern_call_back)(struct pattern_test_ops *pp, struct rtk_test_sc *pSc); +typedef int (*sc_test_get_cipher_info_call_back)(struct pattern_test_ops *pp, struct rtk_test_sc *pSc); +typedef int (*sc_test_generate_key_call_back)(struct pattern_test_ops *pp, struct rtk_test_sc *pSc); +typedef int (*sc_test_decode_profile_call_back)(struct pattern_test_ops *pp, struct rtk_test_sc *pSc); +typedef int (*sc_test_get_tlv_info_call_back)(struct pattern_test_ops *pp, struct rtk_test_sc *pSc); + +struct pattern_test_ops { + unsigned int index; + unsigned flag; + unsigned char name[64]; + sc_test_check_pattern_call_back check_pattern; + sc_test_get_cipher_info_call_back get_cipher_info; + sc_test_generate_key_call_back generate_key; + sc_test_decode_profile_call_back decode_profile; + sc_test_get_tlv_info_call_back get_tlv_info; +}; + + +struct rtk_test_sc { + int pattern_type; + unsigned char smac[6]; /* the source mac of the profile packet, it maybe the Phone MAC */ + unsigned char dmac[6]; /* the destination mac, it is the DUT wlan MAC for send ack packet */ + unsigned char ssid[32]; + unsigned char password[65]; + unsigned int ip_addr; + unsigned char sync_pkt[9][6]; /* parser syn start */ + unsigned char profile_pkt[256][6]; + unsigned int profile_pkt_len; + unsigned char plain_buf[256]; + unsigned int plain_len; + unsigned char key_buf[32]; /* kek */ + unsigned int key_len; + unsigned char crypt_buf[256]; + unsigned int crypt_len; + int pattern_index; /* pattern start index */ + struct pattern_ops *pattern[64]; /* pattern array */ + int max_pattern_num; /* total register pattern num */ + unsigned char pin[65]; + unsigned char default_pin[65]; + unsigned char have_pin; + unsigned short device_type; + unsigned char device_name[64]; +}; + +enum sc_result { + SC_ERROR = -1, /* default error code*/ + SC_NO_CONTROLLER_FOUND = 1, /* cannot get sta(controller) in the air which starts a simple config session */ + SC_CONTROLLER_INFO_PARSE_FAIL, /* cannot parse the sta's info */ + SC_TARGET_CHANNEL_SCAN_FAIL, /* cannot scan the target channel */ + SC_JOIN_BSS_FAIL, /* fail to connect to target ap */ + SC_DHCP_FAIL, /* fail to get ip address from target ap */ + /* fail to create udp socket to send info to controller. note that client isolation + must be turned off in ap. we cannot know if ap has configured this */ + SC_UDP_SOCKET_CREATE_FAIL, + SC_SUCCESS, /* default success code */ + +}; + +#ifdef PACK_STRUCT_USE_INCLUDES +#include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ack_msg { + PACK_STRUCT_FIELD(u8_t flag); + PACK_STRUCT_FIELD(u16_t length); + PACK_STRUCT_FIELD(u8_t smac[6]); + PACK_STRUCT_FIELD(u8_t status); + PACK_STRUCT_FIELD(u16_t device_type); + PACK_STRUCT_FIELD(u32_t device_ip); + PACK_STRUCT_FIELD(u8_t device_name[64]); +};PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +#include "arch/epstruct.h" +#endif + + + +#define MULCAST_PORT (8864) + +#define WIFI_LINK_CONNECTED (1) + +#define SCAN_BUFFER_LENGTH (1024) + +#ifndef WLAN0_NAME + #define WLAN0_NAME "wlan0" +#endif + +int simple_config_result; +static struct ack_msg *ack_content; +static struct rtk_test_sc *backup_sc_ctx; +extern struct netif xnetif[NET_IF_NUM]; +void SC_set_ack_content() +{ + memset(ack_content, 0, sizeof(struct ack_msg)); + ack_content->flag = 0x20; + ack_content->length = htons(sizeof(struct ack_msg)-3); + memcpy(ack_content->smac, xnetif[0].hwaddr, 6); + ack_content->status = 0; + ack_content->device_type = 0; + ack_content->device_ip = xnetif[0].ip_addr.addr; + memset(ack_content->device_name, 0, 64); +} + +int SC_send_simple_config_ack() +{ + + int ack_transmit_round, ack_num_each_sec; + int ack_socket; + //int sended_data = 0; + struct sockaddr_in to_addr; + + SC_set_ack_content(); + + ack_socket = socket(PF_INET, SOCK_DGRAM, IP_PROTO_UDP); + if (ack_socket == -1) { + return -1; + } + + FD_ZERO(&to_addr); + to_addr.sin_family = AF_INET; + to_addr.sin_port = htons(8864); + to_addr.sin_addr.s_addr = (backup_sc_ctx->ip_addr); + + for (ack_transmit_round = 0;ack_transmit_round < 10; ack_transmit_round++) { + for (ack_num_each_sec = 0;ack_num_each_sec < 20; ack_num_each_sec++) { + //sended_data = + sendto(ack_socket, (unsigned char *)ack_content, sizeof(struct ack_msg), 0, (struct sockaddr *) &to_addr, sizeof(struct sockaddr)); + //printf("\r\nAlready send %d bytes data\n", sended_data); + vTaskDelay(50); /* delay 50 ms */ + } + } + close(ack_socket); + return 0; +} + + + +static int SC_check_and_show_connection_info(void) +{ + rtw_wifi_setting_t setting; + int ret = -1; + + /* If not rise priority, LwIP DHCP may timeout */ + vTaskPrioritySet(NULL, tskIDLE_PRIORITY + 3); + /* Start DHCP Client */ + ret = LwIP_DHCP(0, DHCP_START); + vTaskPrioritySet(NULL, tskIDLE_PRIORITY + 1); + + wifi_get_setting(WLAN0_NAME, &setting); + wifi_show_setting(WLAN0_NAME, &setting); + + if (ret == DHCP_ADDRESS_ASSIGNED) + return SC_SUCCESS; + else + return SC_DHCP_FAIL; +} + +static void check_and_set_security_in_connection(rtw_security_t security_mode, rtw_network_info_t *wifi) +{ + + if (security_mode == RTW_SECURITY_WPA2_AES_PSK) { + printf("\r\nwifi->security_type = RTW_SECURITY_WPA2_AES_PSK\n"); + wifi->security_type = RTW_SECURITY_WPA2_AES_PSK; + } else if (security_mode == RTW_SECURITY_WEP_PSK) { + printf("\r\nwifi->security_type = RTW_SECURITY_WEP_PSK\n"); + wifi->security_type = RTW_SECURITY_WEP_PSK; + wifi->key_id = 0; + } else if (security_mode == RTW_SECURITY_WPA_AES_PSK) { + printf("\r\nwifi->security_type = RTW_SECURITY_WPA_AES_PSK\n"); + wifi->security_type = RTW_SECURITY_WPA_AES_PSK; + } else { + printf("\r\nwifi->security_type = RTW_SECURITY_OPEN\n"); + wifi->security_type = RTW_SECURITY_OPEN; + } +} + +static int get_connection_info_from_profile(rtw_security_t security_mode, rtw_network_info_t *wifi) +{ + + printf("\r\n======= Connection Information =======\n"); + check_and_set_security_in_connection(security_mode, wifi); + + wifi->password = backup_sc_ctx->password; + wifi->password_len = (int)strlen((char const *)backup_sc_ctx->password); + + if ( g_ssid_len > 0 && g_ssid_len < 33){ + wifi->ssid.len = g_ssid_len; + rtw_memcpy(wifi->ssid.val, g_ssid, wifi->ssid.len); + }else if(strlen(backup_sc_ctx->ssid) > 0 && strlen(backup_sc_ctx->ssid) < 33){ + wifi->ssid.len = strlen(backup_sc_ctx->ssid); + rtw_memcpy(wifi->ssid.val, backup_sc_ctx->ssid, wifi->ssid.len); + }else{ + printf("\r\n SSID is NULL or SSID length is over 32!!"); + return -1; + } + + if(wifi->security_type == RTW_SECURITY_WEP_PSK) + { + if(wifi->password_len == 10) + { + u32 p[5]; + u8 pwd[6], i = 0; + sscanf((const char*)backup_sc_ctx->password, "%02x%02x%02x%02x%02x", &p[0], &p[1], &p[2], &p[3], &p[4]); + for(i=0; i< 5; i++) + pwd[i] = (u8)p[i]; + pwd[5] = '\0'; + memset(backup_sc_ctx->password, 0, 65); + strcpy((char*)backup_sc_ctx->password, (char*)pwd); + wifi->password_len = 5; + }else if(wifi->password_len == 26){ + u32 p[13]; + u8 pwd[14], i = 0; + sscanf((const char*)backup_sc_ctx->password, "%02x%02x%02x%02x%02x%02x%02x"\ + "%02x%02x%02x%02x%02x%02x", &p[0], &p[1], &p[2], &p[3], &p[4],\ + &p[5], &p[6], &p[7], &p[8], &p[9], &p[10], &p[11], &p[12]); + for(i=0; i< 13; i++) + pwd[i] = (u8)p[i]; + pwd[13] = '\0'; + memset(backup_sc_ctx->password, 0, 64); + strcpy((char*)backup_sc_ctx->password, (char*)pwd); + wifi->password_len = 13; + } + } + printf("\r\nwifi.password = %s\n", wifi->password); + printf("\r\nwifi.password_len = %d\n", wifi->password_len); + printf("\r\nwifi.ssid = %s\n", wifi->ssid.val); + printf("\r\nwifi.ssid_len = %d\n", wifi->ssid.len); + printf("\r\nwifi.channel = %d\n", fixed_channel_num); + printf("\r\n===== start to connect target AP =====\n"); + return 0; +} + +int SC_connect_to_AP(void) +{ + int ret = SC_ERROR; + u8 scan_channel; + u8 pscan_config; + int retry = 3; + rtw_security_t security_mode; + rtw_network_info_t wifi = {0}; + if(!(fixed_channel_num == 0)){ + scan_channel = fixed_channel_num; + } + pscan_config = PSCAN_ENABLE; + switch(g_security_mode){ + case RTW_ENCRYPTION_OPEN: + security_mode = RTW_SECURITY_OPEN; + break; + case RTW_ENCRYPTION_WEP40: + case RTW_ENCRYPTION_WEP104: + security_mode = RTW_SECURITY_WEP_PSK; + break; + case RTW_ENCRYPTION_WPA_TKIP: + case RTW_ENCRYPTION_WPA_AES: + case RTW_ENCRYPTION_WPA2_TKIP: + case RTW_ENCRYPTION_WPA2_AES: + case RTW_ENCRYPTION_WPA2_MIXED: + security_mode = RTW_SECURITY_WPA2_AES_PSK; + break; + case RTW_ENCRYPTION_UNKNOWN: + case RTW_ENCRYPTION_UNDEF: + default: + printf("\r\n unknow security mode,connect fail!"); + return ret; + } + g_security_mode = 0xff;//clear it + + if (-1 == get_connection_info_from_profile(security_mode, &wifi)) { + ret = SC_CONTROLLER_INFO_PARSE_FAIL; + return ret; + } + + while (1) { + if(wifi_set_pscan_chan(&scan_channel, &pscan_config, 1) < 0){ + printf("\n\rERROR: wifi set partial scan channel fail"); + ret = SC_TARGET_CHANNEL_SCAN_FAIL; + return ret; + } +#if 0 + ret = wifi_connect((char*)wifi.ssid.val, + wifi.security_type, + (char*)wifi.password, + wifi.ssid.len, + wifi.password_len, + wifi.key_id, + NULL); +#else + ret = wifi_connect_bssid(g_bssid, + (char*)wifi.ssid.val, + wifi.security_type, + (char*)wifi.password, + 6, + wifi.ssid.len, + wifi.password_len, + wifi.key_id, + NULL); +#endif + if (ret == RTW_SUCCESS) { + ret = SC_check_and_show_connection_info(); + break; + } + + if (retry == 0) { + ret = SC_JOIN_BSS_FAIL; + break; + } + retry --; + } + + return ret; +} +/* Make callback one by one to wlan rx when promiscuous mode */ +extern int rtk_start_parse_packet(unsigned char *da, unsigned char *sa, int len, void *user_data, struct rtk_test_sc *backup_sc_ctx); +void simple_config_callback(unsigned char *buf, unsigned int len, void* userdata) +{ + unsigned char * da = buf; + unsigned char * sa = buf + ETH_ALEN; + taskENTER_CRITICAL(); + if (is_promisc_callback_unlock == 1) { + simple_config_result = rtk_start_parse_packet(da, sa, len, userdata, backup_sc_ctx); + //printf("\r\nresult in callback function = %d\n",simple_config_result); + } + taskEXIT_CRITICAL(); + +} + +static unsigned int simple_config_cmd_start_time; +static unsigned int simple_config_cmd_current_time; +extern int simple_config_status; +extern void rtk_restart_simple_config(void); + +extern int rtk_sc_init(char *custom_pin_code); +extern void rtk_sc_deinit(void); + +int init_test_data(char *custom_pin_code) +{ +#if (CONFIG_INCLUDE_SIMPLE_CONFIG) + is_promisc_callback_unlock = 1; + is_fixed_channel = 0; + fixed_channel_num = 0; + simple_config_result = 0; + rtw_memset(g_ssid, 0, 32); + g_ssid_len = 0; + simple_config_cmd_start_time = xTaskGetTickCount(); + + if (ack_content != NULL) { + vPortFree(ack_content); + ack_content = NULL; + } + ack_content = pvPortMalloc(sizeof(struct ack_msg)); + if (!ack_content) { + printf("\n\rrtk_sc_init fail by allocate ack\n"); + } + memset(ack_content, 0, sizeof(struct ack_msg)); + + + if(custom_pin_code) { + backup_sc_ctx = pvPortMalloc(sizeof(struct rtk_test_sc)); + if (!backup_sc_ctx) { + printf("\n\r[Mem]malloc SC context fail\n"); + } else { + memset(backup_sc_ctx, 0, sizeof(struct rtk_test_sc)); + if (rtk_sc_init(custom_pin_code) < 0) { + printf("\n\rRtk_sc_init fail\n"); + } else { + return 0; + } + } + } else{ + backup_sc_ctx = pvPortMalloc(sizeof(struct rtk_test_sc)); + if (!backup_sc_ctx) { + printf("\n\r[Mem]malloc SC context fail\n"); + } else { + memset(backup_sc_ctx, 0, sizeof(struct rtk_test_sc)); + if (rtk_sc_init(NULL) < 0){ + printf("\n\rRtk_sc_init fail\n"); + } else { + return 0; + } + } + } +#else + printf("\n\rPlatform no include simple config now\n"); +#endif + return -1; +} + +void deinit_test_data(){ +#if (CONFIG_INCLUDE_SIMPLE_CONFIG) + rtk_sc_deinit(); + if (backup_sc_ctx != NULL) { + vPortFree(backup_sc_ctx); + backup_sc_ctx = NULL; + } + if (ack_content != NULL) { + vPortFree(ack_content); + ack_content = NULL; + } +#endif +} + +int simple_config_test(void) +{ + int channel = 1; + int ret = SC_SUCCESS; + unsigned int start_time; + int is_need_connect_to_AP = 0; + int fix_channel = 0; + int delta_time = 0; + wifi_set_promisc(RTW_PROMISC_ENABLE, simple_config_callback, 1); + start_time = xTaskGetTickCount(); + printf("\n\r"); + wifi_set_channel(channel); + while (1) { + vTaskDelay(50); //delay 0.5s to release CPU usage + simple_config_cmd_current_time = xTaskGetTickCount(); + if (simple_config_cmd_current_time - simple_config_cmd_start_time < ((120 + delta_time)*configTICK_RATE_HZ)) { + unsigned int current_time = xTaskGetTickCount(); + if (((current_time - start_time)*1000 /configTICK_RATE_HZ < 100) + || (is_fixed_channel == 1)) { + if((is_fixed_channel == 0)&&(!((fix_channel = promisc_get_fixed_channel(g_bssid,g_ssid,&g_ssid_len))== 0))){ + //printf("\r\n in simple_config_test fix channel = %d ",fix_channel); + is_fixed_channel = 1; + fixed_channel_num = fix_channel; + wifi_set_channel(fix_channel); + } + if (simple_config_result == 1) { + is_need_connect_to_AP = 1; + is_fixed_channel = 0; + break; + } + if (simple_config_result == -1) { + printf("\r\nsimple_config_test restart for result = -1"); + delta_time = 60; + wifi_set_channel(1); + is_need_connect_to_AP = 0; + is_fixed_channel = 0; + fixed_channel_num = 0; + memset(g_ssid, 0, 32); + g_ssid_len = 0; + simple_config_result = 0; + g_security_mode = 0xff; + rtk_restart_simple_config(); + } + if (simple_config_result == -2) { + printf("\n\rThe APP or client must have pin!\n"); + break; + } + } else { + channel++; + if ((1 <= channel) && (channel <= 13)) { + if (wifi_set_channel(channel) == 0) { + start_time = xTaskGetTickCount(); + printf("\n\rSwitch to channel(%d)\n", channel); + } + } else { + channel = 1; + if (wifi_set_channel(channel) == 0) { + start_time = xTaskGetTickCount(); + printf("\n\rSwitch to channel(%d)\n", channel); + } + } + + } + } else { + ret = SC_NO_CONTROLLER_FOUND; + break; + } + } + wifi_set_promisc(RTW_PROMISC_DISABLE, NULL, 0); + if (is_need_connect_to_AP == 1) { + int tmp_res = SC_connect_to_AP(); + if (SC_SUCCESS == tmp_res) { + if(-1 == SC_send_simple_config_ack()) + ret = SC_UDP_SOCKET_CREATE_FAIL; + } else { + return tmp_res; + } + + } else { + ret = SC_NO_CONTROLLER_FOUND; + } + + deinit_test_data(); + return ret; +} + +//Filter packet da[] = {0x01, 0x00, 0x5e} +#define MASK_SIZE 3 +void filter_add_enable(){ + u8 mask[MASK_SIZE]={0xFF,0xFF,0xFF}; + u8 pattern[MASK_SIZE]={0x01,0x00,0x5e}; + + rtw_packet_filter_pattern_t packet_filter; + rtw_packet_filter_rule_e rule; + + packet_filter.offset = 0; + packet_filter.mask_size = 3; + packet_filter.mask = mask; + packet_filter.pattern = pattern; + rule = RTW_POSITIVE_MATCHING; + + wifi_init_packet_filter(); + wifi_add_packet_filter(1, &packet_filter,rule); + wifi_enable_packet_filter(1); +} +void remove_filter(){ + wifi_disable_packet_filter(1); + wifi_remove_packet_filter(1); +} + +void print_simple_config_result(enum sc_result sc_code) +{ + printf("\r\n"); + switch (sc_code) { + case SC_NO_CONTROLLER_FOUND: + printf("Simple Config timeout!! Can't get Ap profile. Please try again\n"); + break; + case SC_CONTROLLER_INFO_PARSE_FAIL: + printf("Simple Config fail, cannot parse target ap info from controller\n"); + break; + case SC_TARGET_CHANNEL_SCAN_FAIL: + printf("Simple Config cannot scan the target channel\n"); + break; + case SC_JOIN_BSS_FAIL: + printf("Simple Config Join bss failed\n"); + break; + case SC_DHCP_FAIL: + printf("Simple Config fail, cannot get dhcp ip address\n"); + break; + case SC_UDP_SOCKET_CREATE_FAIL: + printf("Simple Config Ack socket create fail!!!\n"); + break; + case SC_SUCCESS: + printf("Simple Config success\n"); + break; + + case SC_ERROR: + default: + printf("unknown error when simple config!\n"); + + } + +} + + + + +#endif //CONFIG_INCLUDE_SIMPLE_CONFIG + +void cmd_simple_config(int argc, char **argv){ +#if CONFIG_INCLUDE_SIMPLE_CONFIG + char *custom_pin_code = NULL; + int ret = SC_ERROR; + + if(argc > 2){ + printf("\n\rInput Error!"); + } + + if(argc == 2) + custom_pin_code = (argv[1]); + + wifi_enter_promisc_mode(); + if(init_test_data(custom_pin_code) == 0){ + filter_add_enable(); + ret = simple_config_test(); + print_simple_config_result(ret); + remove_filter(); + } +#endif +} +#endif //#if CONFIG_WLAN diff --git a/component/common/api/wifi/wifi_util.c b/component/common/api/wifi/wifi_util.c new file mode 100644 index 0000000..2031d77 --- /dev/null +++ b/component/common/api/wifi/wifi_util.c @@ -0,0 +1,933 @@ +#include +#include +#include "FreeRTOS.h" +#include +#include +#include +#include + +int iw_ioctl(const char * ifname, unsigned long request, struct iwreq * pwrq) +{ + memcpy(pwrq->ifr_name, ifname, 5); + return rltk_wlan_control(request, (void *) pwrq); +} + +int wext_get_ssid(const char *ifname, __u8 *ssid) +{ + struct iwreq iwr; + int ret = 0; + + memset(&iwr, 0, sizeof(iwr)); + iwr.u.essid.pointer = ssid; + iwr.u.essid.length = 32; + + if (iw_ioctl(ifname, SIOCGIWESSID, &iwr) < 0) { + printf("\n\rioctl[SIOCGIWESSID] ssid = NULL, not connected"); //do not use perror + ret = -1; + } else { + ret = iwr.u.essid.length; + if (ret > 32) + ret = 32; + /* Some drivers include nul termination in the SSID, so let's + * remove it here before further processing. WE-21 changes this + * to explicitly require the length _not_ to include nul + * termination. */ + if (ret > 0 && ssid[ret - 1] == '\0') + ret--; + ssid[ret] = '\0'; + } + + return ret; +} + +int wext_set_ssid(const char *ifname, const __u8 *ssid, __u16 ssid_len) +{ + struct iwreq iwr; + int ret = 0; + + memset(&iwr, 0, sizeof(iwr)); + iwr.u.essid.pointer = (void *) ssid; + iwr.u.essid.length = ssid_len; + iwr.u.essid.flags = (ssid_len != 0); + + if (iw_ioctl(ifname, SIOCSIWESSID, &iwr) < 0) { + printf("\n\rioctl[SIOCSIWESSID] error"); + ret = -1; + } + + return ret; +} + +int wext_set_bssid(const char *ifname, const __u8 *bssid) +{ + struct iwreq iwr; + int ret = 0; + + memset(&iwr, 0, sizeof(iwr)); + iwr.u.ap_addr.sa_family = ARPHRD_ETHER; + memcpy(iwr.u.ap_addr.sa_data, bssid, ETH_ALEN); + + if(bssid[ETH_ALEN]=='#' && bssid[ETH_ALEN + 1]=='@'){ + memcpy(iwr.u.ap_addr.sa_data + ETH_ALEN, bssid + ETH_ALEN, 6); + } + + if (iw_ioctl(ifname, SIOCSIWAP, &iwr) < 0) { + printf("\n\rioctl[SIOCSIWAP] error"); + ret = -1; + } + + return ret; +} + +int is_broadcast_ether_addr(const unsigned char *addr) +{ + return (addr[0] & addr[1] & addr[2] & addr[3] & addr[4] & addr[5]) == 0xff; +} + +int wext_set_auth_param(const char *ifname, __u16 idx, __u32 value) +{ + struct iwreq iwr; + int ret = 0; + + memset(&iwr, 0, sizeof(iwr)); + iwr.u.param.flags = idx & IW_AUTH_INDEX; + iwr.u.param.value = value; + + if (iw_ioctl(ifname, SIOCSIWAUTH, &iwr) < 0) { + printf("\n\rWEXT: SIOCSIWAUTH(param %d value 0x%x) failed)", idx, value); + } + + return ret; +} + +int wext_set_key_ext(const char *ifname, __u16 alg, const __u8 *addr, int key_idx, int set_tx, const __u8 *seq, __u16 seq_len, __u8 *key, __u16 key_len) +{ + struct iwreq iwr; + int ret = 0; + struct iw_encode_ext *ext; + + ext = (struct iw_encode_ext *) malloc(sizeof(struct iw_encode_ext) + key_len); + if (ext == NULL) + return -1; + else + memset(ext, 0, sizeof(struct iw_encode_ext) + key_len); + + memset(&iwr, 0, sizeof(iwr)); + iwr.u.encoding.flags = key_idx + 1; + iwr.u.encoding.flags |= IW_ENCODE_TEMP; + iwr.u.encoding.pointer = ext; + iwr.u.encoding.length = sizeof(struct iw_encode_ext) + key_len; + + if (alg == IW_ENCODE_DISABLED) + iwr.u.encoding.flags |= IW_ENCODE_DISABLED; + + if (addr == NULL || is_broadcast_ether_addr(addr)) + ext->ext_flags |= IW_ENCODE_EXT_GROUP_KEY; + + if (set_tx) + ext->ext_flags |= IW_ENCODE_EXT_SET_TX_KEY; + + ext->addr.sa_family = ARPHRD_ETHER; + + if (addr) + memcpy(ext->addr.sa_data, addr, ETH_ALEN); + else + memset(ext->addr.sa_data, 0xff, ETH_ALEN); + + if (key && key_len) { + memcpy(ext->key, key, key_len); + ext->key_len = key_len; + } + + ext->alg = alg; + + if (seq && seq_len) { + ext->ext_flags |= IW_ENCODE_EXT_RX_SEQ_VALID; + memcpy(ext->rx_seq, seq, seq_len); + } + + if (iw_ioctl(ifname, SIOCSIWENCODEEXT, &iwr) < 0) { + ret = -2; + printf("\n\rioctl[SIOCSIWENCODEEXT] set key fail"); + } + + if(ext != NULL) + free(ext); + + return ret; +} + +int wext_get_enc_ext(const char *ifname, __u16 *alg, __u8 *key_idx, __u8 *passphrase) +{ + struct iwreq iwr; + int ret = 0; + struct iw_encode_ext *ext; + + ext = (struct iw_encode_ext *) malloc(sizeof(struct iw_encode_ext) + 16); + if (ext == NULL) + return -1; + else + memset(ext, 0, sizeof(struct iw_encode_ext) + 16); + + iwr.u.encoding.pointer = ext; + + if (iw_ioctl(ifname, SIOCGIWENCODEEXT, &iwr) < 0) { + printf("\n\rioctl[SIOCGIWENCODEEXT] error"); + ret = -1; + } + else + { + *alg = ext->alg; + if(key_idx) + *key_idx = (__u8)iwr.u.encoding.flags; + if(passphrase) + memcpy(passphrase, ext->key, ext->key_len); + } + + if(ext != NULL) + free(ext); + + return ret; +} + +int wext_set_passphrase(const char *ifname, const __u8 *passphrase, __u16 passphrase_len) +{ + struct iwreq iwr; + int ret = 0; + + memset(&iwr, 0, sizeof(iwr)); + iwr.u.passphrase.pointer = (void *) passphrase; + iwr.u.passphrase.length = passphrase_len; + iwr.u.passphrase.flags = (passphrase_len != 0); + + if (iw_ioctl(ifname, SIOCSIWPRIVPASSPHRASE, &iwr) < 0) { + printf("\n\rioctl[SIOCSIWESSID+0x1f] error"); + ret = -1; + } + + return ret; +} + +int wext_get_passphrase(const char *ifname, __u8 *passphrase) +{ + struct iwreq iwr; + int ret = 0; + + memset(&iwr, 0, sizeof(iwr)); + iwr.u.passphrase.pointer = (void *) passphrase; + + if (iw_ioctl(ifname, SIOCGIWPRIVPASSPHRASE, &iwr) < 0) { + printf("\n\rioctl[SIOCGIWPRIVPASSPHRASE] error"); + ret = -1; + } + else { + ret = iwr.u.passphrase.length; + passphrase[ret] = '\0'; + } + + return ret; +} + +#if 0 +int wext_disconnect(const char *ifname) +{ + int ret = 0; + const __u8 null_bssid[ETH_ALEN] = {0, 0, 0, 0, 0, 1}; //set the last to 1 since driver will filter the mac with all 0x00 or 0xff + + if (wext_set_bssid(ifname, null_bssid) < 0){ + printf("\n\rWEXT: Failed to set bogus BSSID to disconnect"); + ret = -1; + } + return ret; +} + +int wext_set_mac_address(const char *ifname, char * mac) +{ + char buf[13+17+1]; + rtw_memset(buf, 0, sizeof(buf)); + snprintf(buf, 13+17, "write_mac %s", mac); + return wext_private_command(ifname, buf, 0); +} + +int wext_get_mac_address(const char *ifname, char * mac) +{ + int ret = 0; + char buf[32]; + + rtw_memset(buf, 0, sizeof(buf)); + rtw_memcpy(buf, "read_mac", 8); + ret = wext_private_command_with_retval(ifname, buf, buf, 32); + strcpy(mac, buf); + return ret; +} +#endif + +int wext_enable_powersave(const char *ifname) +{ + struct iwreq iwr; + int ret = 0; + __u8 *para = NULL; + int cmd_len = 0; + + memset(&iwr, 0, sizeof(iwr)); + cmd_len = sizeof("pm_set"); + para = pvPortMalloc(24); + + snprintf((char*)para, cmd_len, "pm_set"); + *(para+cmd_len) = 1; //ips=1; + *(para+cmd_len+1) = 1;//lps=1 + + iwr.u.essid.pointer = para; + iwr.u.essid.length = cmd_len + 2; + + if (iw_ioctl(ifname, SIOCDEVPRIVATE, &iwr) < 0) { + printf("\n\rioctl[SIOCSIWPRIVAPESSID] error"); + ret = -1; + } + + vPortFree(para); + return ret; +} + +int wext_disable_powersave(const char *ifname) +{ + struct iwreq iwr; + int ret = 0; + __u8 *para = NULL; + int cmd_len = 0; + + memset(&iwr, 0, sizeof(iwr)); + cmd_len = sizeof("pm_set"); + para = pvPortMalloc(24); + + snprintf((char*)para, cmd_len, "pm_set"); + *(para+cmd_len) = 0; //ips=0; + *(para+cmd_len+1) = 0;//lps=0 + + iwr.u.essid.pointer = para; + iwr.u.essid.length = cmd_len + 2; + + if (iw_ioctl(ifname, SIOCDEVPRIVATE, &iwr) < 0) { + printf("\n\rioctl[SIOCSIWPRIVAPESSID] error"); + ret = -1; + } + + vPortFree(para); + return ret; + +} + +#if 0 +int wext_get_txpower(const char *ifname, int *poweridx) +{ + int ret = 0; + char buf[11]; + + rtw_memset(buf, 0, sizeof(buf)); + rtw_memcpy(buf, "txpower", 11); + ret = wext_private_command_with_retval(ifname, buf, buf, 11); + sscanf(buf, "%d", poweridx); + + return ret; +} + +int wext_set_txpower(const char *ifname, int poweridx) +{ + int ret = 0; + char buf[24]; + + rtw_memset(buf, 0, sizeof(buf)); + snprintf(buf, 24, "txpower patha=%d", poweridx); + ret = wext_private_command(ifname, buf, 0); + + return ret; +} + +int wext_get_associated_client_list(const char *ifname, void * client_list_buffer, uint16_t buffer_length) +{ + int ret = 0; + char buf[25]; + + rtw_memset(buf, 0, sizeof(buf)); + snprintf(buf, 25, "get_client_list %x", client_list_buffer); + ret = wext_private_command(ifname, buf, 0); + + return ret; +} + +int wext_get_ap_info(const char *ifname, rtw_bss_info_t * ap_info, rtw_security_t* security) +{ + int ret = 0; + char buf[24]; + + rtw_memset(buf, 0, sizeof(buf)); + snprintf(buf, 24, "get_ap_info %x", ap_info); + ret = wext_private_command(ifname, buf, 0); + + snprintf(buf, 24, "get_security"); + ret = wext_private_command_with_retval(ifname, buf, buf, 24); + sscanf(buf, "%d", security); + + return ret; +} +#endif + +int wext_set_mode(const char *ifname, int mode) +{ + struct iwreq iwr; + int ret = 0; + + memset(&iwr, 0, sizeof(iwr)); + iwr.u.mode = mode; + if (iw_ioctl(ifname, SIOCSIWMODE, &iwr) < 0) { + printf("\n\rioctl[SIOCSIWMODE] error"); + ret = -1; + } + + return ret; +} + +int wext_get_mode(const char *ifname, int *mode) +{ + struct iwreq iwr; + int ret = 0; + + memset(&iwr, 0, sizeof(iwr)); + + if (iw_ioctl(ifname, SIOCGIWMODE, &iwr) < 0) { + printf("\n\rioctl[SIOCGIWMODE] error"); + ret = -1; + } + else + *mode = iwr.u.mode; + + return ret; +} + +int wext_set_ap_ssid(const char *ifname, const __u8 *ssid, __u16 ssid_len) +{ + struct iwreq iwr; + int ret = 0; + + memset(&iwr, 0, sizeof(iwr)); + iwr.u.essid.pointer = (void *) ssid; + iwr.u.essid.length = ssid_len; + iwr.u.essid.flags = (ssid_len != 0); + + if (iw_ioctl(ifname, SIOCSIWPRIVAPESSID, &iwr) < 0) { + printf("\n\rioctl[SIOCSIWPRIVAPESSID] error"); + ret = -1; + } + + return ret; +} + +int wext_set_country(const char *ifname, char *country_code) +{ + struct iwreq iwr; + int ret = 0; + + memset(&iwr, 0, sizeof(iwr)); + + iwr.u.data.pointer = country_code; + if (iw_ioctl(ifname, SIOCSIWPRIVCOUNTRY, &iwr) < 0) { + printf("\n\rioctl[SIOCSIWPRIVCOUNTRY] error"); + ret = -1; + } + return ret; +} + +int wext_get_rssi(const char *ifname, int *rssi) +{ + struct iwreq iwr; + int ret = 0; + + memset(&iwr, 0, sizeof(iwr)); + + if (iw_ioctl(ifname, SIOCGIWSENS, &iwr) < 0) { + printf("\n\rioctl[SIOCGIWSENS] error"); + ret = -1; + } else { + *rssi = 0 - iwr.u.sens.value; + } + return ret; +} + +int wext_set_pscan_channel(const char *ifname, __u8 *ch, __u8 *pscan_config, __u8 length) +{ + struct iwreq iwr; + int ret = 0; + __u8 *para = NULL; + int i =0; + + memset(&iwr, 0, sizeof(iwr)); + //Format of para:function_name num_channel chan1... pscan_config1 ... + para = pvPortMalloc((length + length + 1) + 12);//size:num_chan + num_time + length + function_name + //Cmd + snprintf((char*)para, 12, "PartialScan"); + //length + *(para+12) = length; + for(i = 0; i < length; i++){ + *(para + 13 + i)= *(ch + i); + *((__u16*) (para + 13 + length + i))= *(pscan_config + i); + } + + iwr.u.data.pointer = para; + iwr.u.data.length = (length + length + 1) + 12; + if (iw_ioctl(ifname, SIOCDEVPRIVATE, &iwr) < 0) { + printf("\n\rwext_set_pscan_channel():ioctl[SIOCDEVPRIVATE] error"); + ret = -1; + } + vPortFree(para); + return ret; +} +int wext_set_channel(const char *ifname, __u8 ch) +{ + struct iwreq iwr; + int ret = 0; + + memset(&iwr, 0, sizeof(iwr)); + iwr.u.freq.m = 0; + iwr.u.freq.e = 0; + iwr.u.freq.i = ch; + + if (iw_ioctl(ifname, SIOCSIWFREQ, &iwr) < 0) { + printf("\n\rioctl[SIOCSIWFREQ] error"); + ret = -1; + } + + return ret; +} + +int wext_get_channel(const char *ifname, __u8 *ch) +{ + struct iwreq iwr; + int ret = 0; + + memset(&iwr, 0, sizeof(iwr)); + + if (iw_ioctl(ifname, SIOCGIWFREQ, &iwr) < 0) { + printf("\n\rioctl[SIOCGIWFREQ] error"); + ret = -1; + } + else + *ch = iwr.u.freq.i; + + return ret; +} + +int wext_register_multicast_address(const char *ifname, rtw_mac_t *mac) +{ + int ret = 0; + char buf[32]; + + rtw_memset(buf, 0, sizeof(buf)); + snprintf(buf, 32, "reg_multicast "MAC_FMT, MAC_ARG(mac->octet)); + ret = wext_private_command(ifname, buf, 0); + + return ret; +} + +int wext_unregister_multicast_address(const char *ifname, rtw_mac_t *mac) +{ + int ret = 0; + char buf[35]; + + rtw_memset(buf, 0, sizeof(buf)); + snprintf(buf, 35, "reg_multicast -d "MAC_FMT, MAC_ARG(mac->octet)); + ret = wext_private_command(ifname, buf, 0); + + return ret; +} + +int wext_set_scan(const char *ifname, char *buf, __u16 buf_len, __u16 flags) +{ + struct iwreq iwr; + int ret = 0; + + memset(&iwr, 0, sizeof(iwr)); +#if 0 //for scan_with_ssid + if(buf) + memset(buf, 0, buf_len); +#endif + iwr.u.data.pointer = buf; + iwr.u.data.flags = flags; + iwr.u.data.length = buf_len; + if (iw_ioctl(ifname, SIOCSIWSCAN, &iwr) < 0) { + printf("\n\rioctl[SIOCSIWSCAN] error"); + ret = -1; + } + return ret; +} + +int wext_get_scan(const char *ifname, char *buf, __u16 buf_len) +{ + struct iwreq iwr; + int ret = 0; + + iwr.u.data.pointer = buf; + iwr.u.data.length = buf_len; + if (iw_ioctl(ifname, SIOCGIWSCAN, &iwr) < 0) { + printf("\n\rioctl[SIOCGIWSCAN] error"); + ret = -1; + }else + ret = iwr.u.data.flags; + return ret; +} + +int wext_private_command_with_retval(const char *ifname, char *cmd, char *ret_buf, int ret_len) +{ + struct iwreq iwr; + int ret = 0, buf_size; + char *buf; + + buf_size = 128; + if(strlen(cmd) >= buf_size) + buf_size = strlen(cmd) + 1; // 1 : '\0' + buf = (char*)pvPortMalloc(buf_size); + if(!buf){ + printf("\n\rWEXT: Can't malloc memory"); + return -1; + } + memset(buf, 0, buf_size); + strcpy(buf, cmd); + memset(&iwr, 0, sizeof(iwr)); + iwr.u.data.pointer = buf; + iwr.u.data.length = buf_size; + iwr.u.data.flags = 0; + + if ((ret = iw_ioctl(ifname, SIOCDEVPRIVATE, &iwr)) < 0) { + printf("\n\rioctl[SIOCDEVPRIVATE] error. ret=%d\n", ret); + } + if(ret_buf){ + if(ret_len > iwr.u.data.length) + ret_len = iwr.u.data.length; + rtw_memcpy(ret_buf, (char *) iwr.u.data.pointer, ret_len); + } + vPortFree(buf); + return ret; +} + +int wext_private_command(const char *ifname, char *cmd, int show_msg) +{ + struct iwreq iwr; + int ret = 0, buf_size; + char *buf; + + buf_size = 2048; // 2048 for efuse_get realmap + if(strlen(cmd) >= buf_size) + buf_size = strlen(cmd) + 1; // 1 : '\0' + buf = (char*)pvPortMalloc(buf_size); + if(!buf){ + printf("\n\rWEXT: Can't malloc memory"); + return -1; + } + memset(buf, 0, buf_size); + strcpy(buf, cmd); + memset(&iwr, 0, sizeof(iwr)); + iwr.u.data.pointer = buf; + iwr.u.data.length = buf_size; + iwr.u.data.flags = 0; + + if ((ret = iw_ioctl(ifname, SIOCDEVPRIVATE, &iwr)) < 0) { + printf("\n\rioctl[SIOCDEVPRIVATE] error. ret=%d\n", ret); + } + if (show_msg && iwr.u.data.length) { + if(iwr.u.data.length > buf_size) + printf("\n\rWEXT: Malloc memory is not enough"); + printf("\n\rPrivate Message: %s", (char *) iwr.u.data.pointer); + } + vPortFree(buf); + return ret; +} + +void wext_wlan_indicate(unsigned int cmd, union iwreq_data *wrqu, char *extra) +{ + unsigned char null_mac[6] = {0}; + + switch(cmd) + { + case SIOCGIWAP: + if(wrqu->ap_addr.sa_family == ARPHRD_ETHER) + { + if(!memcmp(wrqu->ap_addr.sa_data, null_mac, sizeof(null_mac))) + wifi_indication(WIFI_EVENT_DISCONNECT, NULL, 0, 0); + else + wifi_indication(WIFI_EVENT_CONNECT, wrqu->ap_addr.sa_data, sizeof(null_mac), 0); + } + break; + + case IWEVCUSTOM: + if(extra) + { + if(!memcmp(IW_EXT_STR_FOURWAY_DONE, extra, strlen(IW_EXT_STR_FOURWAY_DONE))) + wifi_indication(WIFI_EVENT_FOURWAY_HANDSHAKE_DONE, extra, strlen(IW_EXT_STR_FOURWAY_DONE), 0); + else if(!memcmp(IW_EXT_STR_RECONNECTION_FAIL, extra, strlen(IW_EXT_STR_RECONNECTION_FAIL))) + wifi_indication(WIFI_EVENT_RECONNECTION_FAIL, extra, strlen(IW_EXT_STR_RECONNECTION_FAIL), 0); + else if(!memcmp(IW_EVT_STR_NO_NETWORK, extra, strlen(IW_EVT_STR_NO_NETWORK))) + wifi_indication(WIFI_EVENT_NO_NETWORK, extra, strlen(IW_EVT_STR_NO_NETWORK), 0); +#ifdef CONFIG_P2P_NEW + else if(!memcmp(IW_EVT_STR_STA_ASSOC, extra, strlen(IW_EVT_STR_STA_ASSOC))) + wifi_indication(WIFI_EVENT_STA_ASSOC, wrqu->data.pointer, wrqu->data.length, 0); + else if(!memcmp(IW_EVT_STR_STA_DISASSOC, extra, strlen(IW_EVT_STR_STA_DISASSOC))) + wifi_indication(WIFI_EVENT_STA_DISASSOC, wrqu->addr.sa_data, sizeof(null_mac), 0); + else if(!memcmp(IW_EVT_STR_SEND_ACTION_DONE, extra, strlen(IW_EVT_STR_SEND_ACTION_DONE))) + wifi_indication(WIFI_EVENT_SEND_ACTION_DONE, NULL, 0, wrqu->data.flags); +#endif + } + break; + case SIOCGIWSCAN: + if(wrqu->data.pointer == NULL) + wifi_indication(WIFI_EVENT_SCAN_DONE, wrqu->data.pointer, 0, 0); + else + wifi_indication(WIFI_EVENT_SCAN_RESULT_REPORT, wrqu->data.pointer, 0, 0); + break; +#ifdef CONFIG_P2P_NEW + case IWEVMGNTRECV: + wifi_indication(WIFI_EVENT_RX_MGNT, wrqu->data.pointer, wrqu->data.length, wrqu->data.flags); + break; +#endif + default: + break; + + } + +} + +#ifdef CONFIG_P2P_NEW +int wext_send_mgnt(const char *ifname, char *buf, __u16 buf_len, __u16 flags) +{ + struct iwreq iwr; + int ret = 0; + + memset(&iwr, 0, sizeof(iwr)); + iwr.u.data.pointer = buf; + iwr.u.data.length = buf_len; + iwr.u.data.flags = flags; + if (iw_ioctl(ifname, SIOCSIWMGNTSEND, &iwr) < 0) { + printf("\n\rioctl[SIOCSIWMGNTSEND] error"); + ret = -1; + } + return ret; +} +#endif + +int wext_set_gen_ie(const char *ifname, char *buf, __u16 buf_len, __u16 flags) +{ + struct iwreq iwr; + int ret = 0; + + memset(&iwr, 0, sizeof(iwr)); + iwr.u.data.pointer = buf; + iwr.u.data.length = buf_len; + iwr.u.data.flags = flags; + if (iw_ioctl(ifname, SIOCSIWGENIE, &iwr) < 0) { + printf("\n\rioctl[SIOCSIWGENIE] error"); + ret = -1; + } + return ret; +} + +int wext_set_autoreconnect(const char *ifname, __u8 mode) +{ + struct iwreq iwr; + int ret = 0; + __u8 *para = NULL; + int cmd_len = 0; + + memset(&iwr, 0, sizeof(iwr)); + cmd_len = sizeof("SetAutoRecnt"); + para = pvPortMalloc((1) + cmd_len);//size:para_len+cmd_len + //Cmd + snprintf((char*)para, cmd_len, "SetAutoRecnt"); + //length + *(para+cmd_len) = mode; //para + + iwr.u.data.pointer = para; + iwr.u.data.length = (1) + cmd_len; + if (iw_ioctl(ifname, SIOCDEVPRIVATE, &iwr) < 0) { + printf("\n\rwext_set_autoreconnect():ioctl[SIOCDEVPRIVATE] error"); + ret = -1; + } + vPortFree(para); + return ret; +} + +int wext_get_autoreconnect(const char *ifname, __u8 *mode) +{ + struct iwreq iwr; + int ret = 0; + __u8 *para = NULL; + int cmd_len = 0; + + memset(&iwr, 0, sizeof(iwr)); + cmd_len = sizeof("GetAutoRecnt"); + //para = pvPortMalloc((1) + cmd_len);//size:para_len+cmd_len + para = pvPortMalloc(cmd_len);//size:para_len+cmd_len + //Cmd + snprintf((char*)para, cmd_len, "GetAutoRecnt"); + //length + //*(para+cmd_len) = *mode; //para + + iwr.u.data.pointer = para; + //iwr.u.data.length = (1) + cmd_len; + iwr.u.data.length = cmd_len; + if (iw_ioctl(ifname, SIOCDEVPRIVATE, &iwr) < 0) { + printf("\n\rwext_set_autoreconnect():ioctl[SIOCDEVPRIVATE] error"); + ret = -1; + } + *mode = *(__u8 *)(iwr.u.data.pointer); + vPortFree(para); + return ret; +} + +#ifdef CONFIG_CUSTOM_IE +int wext_add_custom_ie(const char *ifname, void *cus_ie, int ie_num) +{ + struct iwreq iwr; + int ret = 0; + __u8 *para = NULL; + int cmd_len = 0; + if(ie_num <= 0 || !cus_ie){ + printf("\n\rwext_add_custom_ie():wrong parameter"); + ret = -1; + return ret; + } + memset(&iwr, 0, sizeof(iwr)); + cmd_len = sizeof("SetCusIE"); + para = pvPortMalloc((4)* 2 + cmd_len);//size:addr len+cmd_len + //Cmd + snprintf(para, cmd_len, "SetCusIE"); + //addr length + *(__u32 *)(para + cmd_len) = (__u32)cus_ie; //ie addr + //ie_num + *(__u32 *)(para + cmd_len + 4) = ie_num; //num of ie + + iwr.u.data.pointer = para; + iwr.u.data.length = (4)* 2 + cmd_len;// 2 input + if (iw_ioctl(ifname, SIOCDEVPRIVATE, &iwr) < 0) { + printf("\n\rwext_add_custom_ie():ioctl[SIOCDEVPRIVATE] error"); + ret = -1; + } + vPortFree(para); + + return ret; +} + +int wext_update_custom_ie(const char *ifname, void * cus_ie, int ie_index) +{ + struct iwreq iwr; + int ret = 0; + __u8 *para = NULL; + int cmd_len = 0; + if(ie_index <= 0 || !cus_ie){ + printf("\n\rwext_update_custom_ie():wrong parameter"); + ret = -1; + return ret; + } + memset(&iwr, 0, sizeof(iwr)); + cmd_len = sizeof("UpdateIE"); + para = pvPortMalloc((4)* 2 + cmd_len);//size:addr len+cmd_len + //Cmd + snprintf(para, cmd_len, "UpdateIE"); + //addr length + *(__u32 *)(para + cmd_len) = (__u32)cus_ie; //ie addr + //ie_index + *(__u32 *)(para + cmd_len + 4) = ie_index; //num of ie + + iwr.u.data.pointer = para; + iwr.u.data.length = (4)* 2 + cmd_len;// 2 input + if (iw_ioctl(ifname, SIOCDEVPRIVATE, &iwr) < 0) { + printf("\n\rwext_update_custom_ie():ioctl[SIOCDEVPRIVATE] error"); + ret = -1; + } + vPortFree(para); + + return ret; + +} + +int wext_del_custom_ie(const char *ifname) +{ + struct iwreq iwr; + int ret = 0; + __u8 *para = NULL; + int cmd_len = 0; + + memset(&iwr, 0, sizeof(iwr)); + cmd_len = sizeof("DelIE"); + para = pvPortMalloc(cmd_len);//size:addr len+cmd_len + //Cmd + snprintf(para, cmd_len, "DelIE"); + + iwr.u.data.pointer = para; + iwr.u.data.length = cmd_len; + if (iw_ioctl(ifname, SIOCDEVPRIVATE, &iwr) < 0) { + printf("\n\rwext_del_custom_ie():ioctl[SIOCDEVPRIVATE] error"); + ret = -1; + } + vPortFree(para); + + return ret; + + +} + +#endif + +#ifdef CONFIG_AP_MODE +int wext_enable_forwarding(const char *ifname) +{ + struct iwreq iwr; + int ret = 0; + __u8 *para = NULL; + int cmd_len = 0; + + memset(&iwr, 0, sizeof(iwr)); + cmd_len = sizeof("forwarding_set"); + para = pvPortMalloc(cmd_len + 1); + + // forwarding_set 1 + snprintf((char *) para, cmd_len, "forwarding_set"); + *(para + cmd_len) = '1'; + + iwr.u.essid.pointer = para; + iwr.u.essid.length = cmd_len + 1; + + if (iw_ioctl(ifname, SIOCDEVPRIVATE, &iwr) < 0) { + printf("\n\rwext_enable_forwarding(): ioctl[SIOCDEVPRIVATE] error"); + ret = -1; + } + + vPortFree(para); + return ret; +} + +int wext_disable_forwarding(const char *ifname) +{ + struct iwreq iwr; + int ret = 0; + __u8 *para = NULL; + int cmd_len = 0; + + memset(&iwr, 0, sizeof(iwr)); + cmd_len = sizeof("forwarding_set"); + para = pvPortMalloc(cmd_len + 1); + + // forwarding_set 0 + snprintf((char *) para, cmd_len, "forwarding_set"); + *(para + cmd_len) = '0'; + + iwr.u.essid.pointer = para; + iwr.u.essid.length = cmd_len + 1; + + if (iw_ioctl(ifname, SIOCDEVPRIVATE, &iwr) < 0) { + printf("\n\rwext_disable_forwarding(): ioctl[SIOCDEVPRIVATE] error"); + ret = -1; + } + + vPortFree(para); + return ret; + +} +#endif diff --git a/component/common/api/wifi/wifi_util.h b/component/common/api/wifi/wifi_util.h new file mode 100644 index 0000000..27645ba --- /dev/null +++ b/component/common/api/wifi/wifi_util.h @@ -0,0 +1,64 @@ +#ifndef _UTIL_H +#define _UTIL_H + +#include +#include +#include +#include "wifi_structures.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int wext_get_ssid(const char *ifname, __u8 *ssid); +int wext_set_ssid(const char *ifname, const __u8 *ssid, __u16 ssid_len); +int wext_set_auth_param(const char *ifname, __u16 idx, __u32 value); +int wext_set_key_ext(const char *ifname, __u16 alg, const __u8 *addr, int key_idx, int set_tx, const __u8 *seq, __u16 seq_len, __u8 *key, __u16 key_len); +int wext_get_enc_ext(const char *ifname, __u16 *alg, __u8 *key_idx, __u8 *passphrase); +int wext_set_passphrase(const char *ifname, const __u8 *passphrase, __u16 passphrase_len); +int wext_get_passphrase(const char *ifname, __u8 *passphrase); +int wext_disconnect(const char *ifname); +int wext_set_mode(const char *ifname, int mode); +int wext_get_mode(const char *ifname, int *mode); +int wext_set_ap_ssid(const char *ifname, const __u8 *ssid, __u16 ssid_len); +int wext_set_country(const char *ifname, char *country_code); +int wext_get_rssi(const char *ifname, int *rssi); +int wext_set_channel(const char *ifname, __u8 ch); +int wext_get_channel(const char *ifname, __u8 *ch); +int wext_register_multicast_address(const char *ifname, rtw_mac_t *mac); +int wext_unregister_multicast_address(const char *ifname, rtw_mac_t *mac); +int wext_set_scan(const char *ifname, char *buf, __u16 buf_len, __u16 flags); +int wext_get_scan(const char *ifname, char *buf, __u16 buf_len); +int wext_set_mac_address(const char *ifname, char * mac); +int wext_get_mac_address(const char *ifname, char * mac); +int wext_enable_powersave(const char *ifname); +int wext_disable_powersave(const char *ifname); +int wext_get_txpower(const char *ifname, int *poweridx); +int wext_set_txpower(const char *ifname, int poweridx); +int wext_get_associated_client_list(const char *ifname, void * client_list_buffer, __u16 buffer_length); +int wext_get_ap_info(const char *ifname, rtw_bss_info_t * ap_info, rtw_security_t* security); +int wext_mp_command(const char *ifname, char *cmd, int show_msg); +int wext_private_command(const char *ifname, char *cmd, int show_msg); +int wext_private_command_with_retval(const char *ifname, char *cmd, char *ret_buf, int ret_len); +void wext_wlan_indicate(unsigned int cmd, union iwreq_data *wrqu, char *extra); +int wext_set_pscan_channel(const char *ifname, __u8 *ch, __u8 *pscan_config, __u8 length); +int wext_set_autoreconnect(const char *ifname, __u8 mode); +int wext_get_autoreconnect(const char *ifname, __u8 *mode); +#ifdef CONFIG_CUSTOM_IE +int wext_add_custom_ie(const char *ifname, void * cus_ie, int ie_num); +int wext_update_custom_ie(const char *ifname, void * cus_ie, int ie_index); +int wext_del_custom_ie(const char *ifname); +#endif + +#define wext_handshake_done rltk_wlan_handshake_done + +#ifdef CONFIG_P2P_NEW +int wext_send_mgnt(const char *ifname, char *buf, __u16 buf_len, __u16 flags); +#endif +int wext_set_gen_ie(const char *ifname, char *buf, __u16 buf_len, __u16 flags); + +#ifdef __cplusplus +} +#endif + +#endif /* _UTIL_H */ diff --git a/component/common/api/wifi_interactive_ext.h b/component/common/api/wifi_interactive_ext.h new file mode 100644 index 0000000..774b482 --- /dev/null +++ b/component/common/api/wifi_interactive_ext.h @@ -0,0 +1,41 @@ +#define CONFIG_EXTERN_TEST 0 +#define CONFIG_EXTERN_HW 0 +#define CONFIG_EXTERN_CLOUD 0 +#define CONFIG_TTCP 0 + +/* External Function */ +#if CONFIG_EXTERN_TEST +extern void cmd_tcpecho(int argc, char **argv); +#endif +#if CONFIG_EXTERN_HW +extern void cmd_led(int argc, char **argv); +extern void cmd_tmp75(int argc, char **argv); +#endif +#if CONFIG_EXTERN_CLOUD +extern void cmd_cloud(int argc, char **argv); +extern void cmd_reboot(int argc, char **argv); +extern void cmd_config(int argc, char **argv); +#endif + +#if CONFIG_TTCP +extern void cmd_ttcp(int argc, char **argv); +#endif + +static const cmd_entry ext_cmd_table[] = { +#if CONFIG_EXTERN_TEST + {"tcpecho", cmd_tcpecho}, +#endif +#if CONFIG_EXTERN_HW + {"led", cmd_led}, + {"tmp75", cmd_tmp75}, +#endif +#if CONFIG_EXTERN_CLOUD + {"cloud", cmd_cloud}, + {"reboot", cmd_reboot}, + {"config", cmd_config}, +#endif +#if CONFIG_TTCP + {"ttcp", cmd_ttcp}, +#endif + {"", NULL} +}; diff --git a/component/common/api/wifi_interactive_mode.c b/component/common/api/wifi_interactive_mode.c new file mode 100644 index 0000000..adc8941 --- /dev/null +++ b/component/common/api/wifi_interactive_mode.c @@ -0,0 +1,1237 @@ + +#include "FreeRTOS.h" +#include "task.h" +#include "semphr.h" +#include "main.h" +#include +#include "tcpip.h" +#include +#include +#include +#include +#include +#include +#if defined(CONFIG_PLATFORM_8195A) || defined(CONFIG_PLATFORM_8711B) +#include "platform_opts.h" +#endif + +#ifndef CONFIG_INTERACTIVE_EXT +#define CONFIG_INTERACTIVE_EXT 0 +#endif +#ifndef CONFIG_SSL_CLIENT +#if defined(CONFIG_PLATFORM_8711B) +#define CONFIG_SSL_CLIENT 0 +#else +#define CONFIG_SSL_CLIENT 1 +#endif +#endif + +#ifndef CONFIG_GOOGLENEST +#define CONFIG_GOOGLENEST 0 +#endif +#if CONFIG_LWIP_LAYER +#ifndef CONFIG_WEBSERVER +#define CONFIG_WEBSERVER 0 +#endif +#endif +#ifndef CONFIG_OTA_UPDATE +#define CONFIG_OTA_UPDATE 0 +#endif +#ifndef CONFIG_BSD_TCP +#define CONFIG_BSD_TCP 0 +#endif +#define CONFIG_JD_SMART 0 +#ifndef CONFIG_ENABLE_P2P +#define CONFIG_ENABLE_P2P 0 +#endif +#define SCAN_WITH_SSID 0 + +#ifdef CONFIG_WPS +#define STACKSIZE 1280 +#else +#define STACKSIZE 1024 +#endif + +#ifndef WLAN0_NAME + #define WLAN0_NAME "wlan0" +#endif +#ifndef WLAN1_NAME + #define WLAN1_NAME "wlan1" +#endif +/* Give default value if not defined */ +#ifndef NET_IF_NUM +#ifdef CONFIG_CONCURRENT_MODE +#define NET_IF_NUM 2 +#else +#define NET_IF_NUM 1 +#endif +#endif + +/*Static IP ADDRESS*/ +#ifndef IP_ADDR0 +#define IP_ADDR0 192 +#define IP_ADDR1 168 +#define IP_ADDR2 1 +#define IP_ADDR3 80 +#endif + +/*NETMASK*/ +#ifndef NETMASK_ADDR0 +#define NETMASK_ADDR0 255 +#define NETMASK_ADDR1 255 +#define NETMASK_ADDR2 255 +#define NETMASK_ADDR3 0 +#endif + +/*Gateway Address*/ +#ifndef GW_ADDR0 +#define GW_ADDR0 192 +#define GW_ADDR1 168 +#define GW_ADDR2 1 +#define GW_ADDR3 1 +#endif + +/*Static IP ADDRESS*/ +#ifndef AP_IP_ADDR0 +#define AP_IP_ADDR0 192 +#define AP_IP_ADDR1 168 +#define AP_IP_ADDR2 43 +#define AP_IP_ADDR3 1 +#endif + +/*NETMASK*/ +#ifndef AP_NETMASK_ADDR0 +#define AP_NETMASK_ADDR0 255 +#define AP_NETMASK_ADDR1 255 +#define AP_NETMASK_ADDR2 255 +#define AP_NETMASK_ADDR3 0 +#endif + +/*Gateway Address*/ +#ifndef AP_GW_ADDR0 +#define AP_GW_ADDR0 192 +#define AP_GW_ADDR1 168 +#define AP_GW_ADDR2 43 +#define AP_GW_ADDR3 1 +#endif + +static void cmd_help(int argc, char **argv); +#if CONFIG_SSL_CLIENT +extern void cmd_ssl_client(int argc, char **argv); +#endif + +#if CONFIG_GOOGLENEST +extern void cmd_googlenest(int argc, char **argv); +#endif +#if CONFIG_JD_SMART +extern void cmd_jd_smart(int argc, char **argv); +#endif +#if CONFIG_WLAN +static void cmd_wifi_on(int argc, char **argv); +static void cmd_wifi_off(int argc, char **argv); +static void cmd_wifi_disconnect(int argc, char **argv); +extern void cmd_promisc(int argc, char **argv); +extern void cmd_simple_config(int argc, char **argv); + +#if CONFIG_OTA_UPDATE +extern void cmd_update(int argc, char **argv); +#endif +#if CONFIG_BSD_TCP +extern void cmd_tcp(int argc, char **argv); +extern void cmd_udp(int argc, char **argv); +#endif +#if CONFIG_WEBSERVER +extern void start_web_server(void); +extern void stop_web_server(void); +#endif +extern void cmd_app(int argc, char **argv); + +#if CONFIG_EXAMPLE_UART_ADAPTER +extern void cmd_uart_adapter(int argc, char **argv); +#endif + +#ifdef CONFIG_WPS +#if CONFIG_ENABLE_WPS +extern void cmd_wps(int argc, char **argv); +#endif +#ifdef CONFIG_WPS_AP +extern void cmd_ap_wps(int argc, char **argv); +extern int wpas_wps_dev_config(u8 *dev_addr, u8 bregistrar); +#endif //CONFIG_WPS_AP +#endif //CONFIG_WPS +#if CONFIG_ENABLE_P2P +extern void cmd_wifi_p2p_start(int argc, char **argv); +extern void cmd_wifi_p2p_stop(int argc, char **argv); +extern void cmd_p2p_listen(int argc, char **argv); +extern void cmd_p2p_find(int argc, char **argv); +extern void cmd_p2p_peers(int argc, char **argv); +extern void cmd_p2p_info(int argc, char **argv); +extern void cmd_p2p_disconnect(int argc, char **argv); +extern void cmd_p2p_connect(int argc, char **argv); +#endif //CONFIG_ENABLE_P2P +#if defined(CONFIG_RTL8195A) || defined(CONFIG_RTL8711B) +extern u32 CmdDumpWord(IN u16 argc, IN u8 *argv[]); +extern u32 CmdWriteWord(IN u16 argc, IN u8 *argv[]); +#endif +#if CONFIG_LWIP_LAYER +extern struct netif xnetif[NET_IF_NUM]; +#endif +#ifdef CONFIG_CONCURRENT_MODE +static void cmd_wifi_sta_and_ap(int argc, char **argv) +{ + int timeout = 20;//, mode; +#if CONFIG_LWIP_LAYER + struct netif * pnetiff = (struct netif *)&xnetif[1]; +#endif + int channel; + + if((argc != 3) && (argc != 4)) { + printf("\n\rUsage: wifi_ap SSID CHANNEL [PASSWORD]"); + return; + } + + if(atoi((const char *)argv[2]) > 14){ + printf("\n\r bad channel!Usage: wifi_ap SSID CHANNEL [PASSWORD]"); + return; + } +#if CONFIG_LWIP_LAYER + dhcps_deinit(); +#endif + +#if 0 + //Check mode + wext_get_mode(WLAN0_NAME, &mode); + + switch(mode) { + case IW_MODE_MASTER: //In AP mode + cmd_wifi_off(0, NULL); + cmd_wifi_on(0, NULL); + break; + case IW_MODE_INFRA: //In STA mode + if(wext_get_ssid(WLAN0_NAME, ssid) > 0) + cmd_wifi_disconnect(0, NULL); + } +#endif + wifi_off(); + vTaskDelay(20); + if (wifi_on(RTW_MODE_STA_AP) < 0){ + printf("\n\rERROR: Wifi on failed!"); + return; + } + + printf("\n\rStarting AP ..."); + channel = atoi((const char *)argv[2]); + if(channel > 13){ + printf("\n\rChannel is from 1 to 13. Set channel 1 as default!\n"); + channel = 1; + } + + if(argc == 4) { + if(wifi_start_ap(argv[1], + RTW_SECURITY_WPA2_AES_PSK, + argv[3], + strlen((const char *)argv[1]), + strlen((const char *)argv[3]), + channel + ) != RTW_SUCCESS) { + printf("\n\rERROR: Operation failed!"); + return; + } + } + else { + if(wifi_start_ap(argv[1], + RTW_SECURITY_OPEN, + NULL, + strlen((const char *)argv[1]), + 0, + channel + ) != RTW_SUCCESS) { + printf("\n\rERROR: Operation failed!"); + return; + } + } + + while(1) { + char essid[33]; + + if(wext_get_ssid(WLAN1_NAME, (unsigned char *) essid) > 0) { + if(strcmp((const char *) essid, (const char *)argv[1]) == 0) { + printf("\n\r%s started", argv[1]); + break; + } + } + + if(timeout == 0) { + printf("\n\rERROR: Start AP timeout!"); + break; + } + + vTaskDelay(1 * configTICK_RATE_HZ); + timeout --; + } +#if CONFIG_LWIP_LAYER + LwIP_UseStaticIP(&xnetif[1]); +#ifdef CONFIG_DONT_CARE_TP + pnetiff->flags |= NETIF_FLAG_IPSWITCH; +#endif + dhcps_init(pnetiff); +#endif +} +#endif + +static void cmd_wifi_ap(int argc, char **argv) +{ + int timeout = 20; +#if CONFIG_LWIP_LAYER + struct ip_addr ipaddr; + struct ip_addr netmask; + struct ip_addr gw; + struct netif * pnetif = &xnetif[0]; +#endif + int channel; + + if((argc != 3) && (argc != 4)) { + printf("\n\rUsage: wifi_ap SSID CHANNEL [PASSWORD]"); + return; + } +#if CONFIG_LWIP_LAYER + dhcps_deinit(); + IP4_ADDR(&ipaddr, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3); + IP4_ADDR(&netmask, NETMASK_ADDR0, NETMASK_ADDR1 , NETMASK_ADDR2, NETMASK_ADDR3); + IP4_ADDR(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3); + netif_set_addr(pnetif, &ipaddr, &netmask,&gw); +#ifdef CONFIG_DONT_CARE_TP + pnetif->flags |= NETIF_FLAG_IPSWITCH; +#endif +#endif +#if 0 + //Check mode + wext_get_mode(WLAN0_NAME, &mode); + + switch(mode) { + case IW_MODE_MASTER: //In AP mode + wifi_off(); + wifi_on(1); + break; + case IW_MODE_INFRA: //In STA mode + if(wext_get_ssid(WLAN0_NAME, ssid) > 0) + cmd_wifi_disconnect(0, NULL); + } +#else + wifi_off(); + vTaskDelay(20); + if (wifi_on(RTW_MODE_AP) < 0){ + printf("\n\rERROR: Wifi on failed!"); + return; + } +#endif + + printf("\n\rStarting AP ..."); + channel = atoi((const char *)argv[2]); + if(channel > 13){ + printf("\n\rChannel is from 1 to 13. Set channel 1 as default!\n"); + channel = 1; + } +#ifdef CONFIG_WPS_AP + wpas_wps_dev_config(pnetif->hwaddr, 1); +#endif + + if(argc == 4) { + if(wifi_start_ap(argv[1], + RTW_SECURITY_WPA2_AES_PSK, + argv[3], + strlen((const char *)argv[1]), + strlen((const char *)argv[3]), + channel + ) != RTW_SUCCESS) { + printf("\n\rERROR: Operation failed!"); + return; + } + } + else { + if(wifi_start_ap(argv[1], + RTW_SECURITY_OPEN, + NULL, + strlen((const char *)argv[1]), + 0, + channel + ) != RTW_SUCCESS) { + printf("\n\rERROR: Operation failed!"); + return; + } + } + + while(1) { + char essid[33]; + + if(wext_get_ssid(WLAN0_NAME, (unsigned char *) essid) > 0) { + if(strcmp((const char *) essid, (const char *)argv[1]) == 0) { + printf("\n\r%s started\n", argv[1]); + break; + } + } + + if(timeout == 0) { + printf("\n\rERROR: Start AP timeout!"); + break; + } + + vTaskDelay(1 * configTICK_RATE_HZ); + timeout --; + } +#if CONFIG_LWIP_LAYER + //LwIP_UseStaticIP(pnetif); + dhcps_init(pnetif); +#endif +} + +static void cmd_wifi_connect(int argc, char **argv) +{ + int ret = RTW_ERROR; + unsigned long tick1 = xTaskGetTickCount(); + unsigned long tick2, tick3; + int mode; + char *ssid; + rtw_security_t security_type; + char *password; + int ssid_len; + int password_len; + int key_id; + void *semaphore; + + if((argc != 2) && (argc != 3) && (argc != 4)) { + printf("\n\rUsage: wifi_connect SSID [WPA PASSWORD / (5 or 13) ASCII WEP KEY] [WEP KEY ID 0/1/2/3]"); + return; + } + + //Check if in AP mode + wext_get_mode(WLAN0_NAME, &mode); + + if(mode == IW_MODE_MASTER) { +#if CONFIG_LWIP_LAYER + dhcps_deinit(); +#endif + wifi_off(); + vTaskDelay(20); + if (wifi_on(RTW_MODE_STA) < 0){ + printf("\n\rERROR: Wifi on failed!"); + return; + } + } + + ssid = argv[1]; + if(argc == 2){ + security_type = RTW_SECURITY_OPEN; + password = NULL; + ssid_len = strlen((const char *)argv[1]); + password_len = 0; + key_id = 0; + semaphore = NULL; + }else if(argc ==3){ + security_type = RTW_SECURITY_WPA2_AES_PSK; + password = argv[2]; + ssid_len = strlen((const char *)argv[1]); + password_len = strlen((const char *)argv[2]); + key_id = 0; + semaphore = NULL; + }else{ + security_type = RTW_SECURITY_WEP_PSK; + password = argv[2]; + ssid_len = strlen((const char *)argv[1]); + password_len = strlen((const char *)argv[2]); + key_id = atoi(argv[3]); + if(( password_len != 5) && (password_len != 13)) { + printf("\n\rWrong WEP key length. Must be 5 or 13 ASCII characters."); + return; + } + if((key_id < 0) || (key_id > 3)) { + printf("\n\rWrong WEP key id. Must be one of 0,1,2, or 3."); + return; + } + semaphore = NULL; + } + + ret = wifi_connect(ssid, + security_type, + password, + ssid_len, + password_len, + key_id, + semaphore); + + tick2 = xTaskGetTickCount(); + printf("\r\nConnected after %dms.\n", (tick2-tick1)); + if(ret != RTW_SUCCESS) { + printf("\n\rERROR: Operation failed!"); + return; + } else { +#if CONFIG_LWIP_LAYER + /* Start DHCPClient */ + LwIP_DHCP(0, DHCP_START); +#endif + } + tick3 = xTaskGetTickCount(); + printf("\r\n\nGot IP after %dms.\n", (tick3-tick1)); +} + +static void cmd_wifi_connect_bssid(int argc, char **argv) +{ + int ret = RTW_ERROR; + unsigned long tick1 = xTaskGetTickCount(); + unsigned long tick2, tick3; + int mode; + unsigned char bssid[ETH_ALEN]; + char *ssid = NULL; + rtw_security_t security_type; + char *password; + int bssid_len; + int ssid_len = 0; + int password_len; + int key_id; + void *semaphore; + u32 mac[ETH_ALEN]; + u32 i; + u32 index = 0; + + if((argc != 3) && (argc != 4) && (argc != 5) && (argc != 6)) { + printf("\n\rUsage: wifi_connect_bssid 0/1 [SSID] BSSID / xx:xx:xx:xx:xx:xx [WPA PASSWORD / (5 or 13) ASCII WEP KEY] [WEP KEY ID 0/1/2/3]"); + return; + } + + //Check if in AP mode + wext_get_mode(WLAN0_NAME, &mode); + + if(mode == IW_MODE_MASTER) { +#if CONFIG_LWIP_LAYER + dhcps_deinit(); +#endif + wifi_off(); + vTaskDelay(20); + if (wifi_on(RTW_MODE_STA) < 0){ + printf("\n\rERROR: Wifi on failed!"); + return; + } + } + //check ssid + if(memcmp(argv[1], "0", 1)){ + index = 1; + ssid_len = strlen((const char *)argv[2]); + if((ssid_len <= 0) || (ssid_len > 32)) { + printf("\n\rWrong ssid. Length must be less than 32."); + return; + } + ssid = argv[2]; + } + sscanf(argv[2 + index], MAC_FMT, mac, mac + 1, mac + 2, mac + 3, mac + 4, mac + 5); + for(i=0; i 3)) { + printf("\n\rWrong WEP key id. Must be one of 0,1,2, or 3."); + return; + } + semaphore = NULL; + } + + ret = wifi_connect_bssid(bssid, + ssid, + security_type, + password, + bssid_len, + ssid_len, + password_len, + key_id, + semaphore); + + tick2 = xTaskGetTickCount(); + printf("\r\nConnected after %dms.\n", (tick2-tick1)); + if(ret != RTW_SUCCESS) { + printf("\n\rERROR: Operation failed!"); + return; + } else { +#if CONFIG_LWIP_LAYER + /* Start DHCPClient */ + LwIP_DHCP(0, DHCP_START); +#endif + } + tick3 = xTaskGetTickCount(); + printf("\r\n\nGot IP after %dms.\n", (tick3-tick1)); +} + +static void cmd_wifi_disconnect(int argc, char **argv) +{ + int timeout = 20; + char essid[33]; + + printf("\n\rDeassociating AP ..."); + + if(wext_get_ssid(WLAN0_NAME, (unsigned char *) essid) < 0) { + printf("\n\rWIFI disconnected"); + return; + } + + if(wifi_disconnect() < 0) { + printf("\n\rERROR: Operation failed!"); + return; + } + + while(1) { + if(wext_get_ssid(WLAN0_NAME, (unsigned char *) essid) < 0) { + printf("\n\rWIFI disconnected"); + break; + } + + if(timeout == 0) { + printf("\n\rERROR: Deassoc timeout!"); + break; + } + + vTaskDelay(1 * configTICK_RATE_HZ); + timeout --; + } +} + +static void cmd_wifi_info(int argc, char **argv) +{ + int i = 0; +#if CONFIG_LWIP_LAYER + u8 *mac = LwIP_GetMAC(&xnetif[0]); + u8 *ip = LwIP_GetIP(&xnetif[0]); + u8 *gw = LwIP_GetGW(&xnetif[0]); +#endif + u8 *ifname[2] = {WLAN0_NAME,WLAN1_NAME}; +#ifdef CONFIG_MEM_MONITOR + extern int min_free_heap_size; +#endif + + rtw_wifi_setting_t setting; + for(i=0;i %02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]) ; + printf("\n\r\tIP => %d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); + printf("\n\r\tGW => %d.%d.%d.%d\n\r", gw[0], gw[1], gw[2], gw[3]); +#endif + if(setting.mode == RTW_MODE_AP || i == 1) + { + int client_number; + struct { + int count; + rtw_mac_t mac_list[3]; + } client_info; + + client_info.count = 3; + wifi_get_associated_client_list(&client_info, sizeof(client_info)); + + printf("\n\rAssociated Client List:"); + printf("\n\r=============================="); + + if(client_info.count == 0) + printf("\n\rClient Num: 0\n\r"); + else + { + printf("\n\rClient Num: %d", client_info.count); + for( client_number=0; client_number < client_info.count; client_number++ ) + { + printf("\n\rClient [%d]:", client_number); + printf("\n\r\tMAC => "MAC_FMT"", + MAC_ARG(client_info.mac_list[client_number].octet)); + } + printf("\n\r"); + } + } + + { + int error = wifi_get_last_error(); + printf("\n\rLast Link Error"); + printf("\n\r=============================="); + switch(error) + { + case RTW_NO_ERROR: + printf("\n\r\tNo Error"); + break; + case RTW_NONE_NETWORK: + printf("\n\r\tTarget AP Not Found"); + break; + case RTW_CONNECT_FAIL: + printf("\n\r\tAssociation Failed"); + break; + case RTW_WRONG_PASSWORD: + printf("\n\r\tWrong Password"); + break; + case RTW_DHCP_FAIL: + printf("\n\r\tDHCP Failed"); + break; + default: + printf("\n\r\tUnknown Error(%d)", error); + } + printf("\n\r"); + } + } + } + +#if defined(configUSE_TRACE_FACILITY) && (configUSE_TRACE_FACILITY == 1) + { + signed char pcWriteBuffer[1024]; + vTaskList((char*)pcWriteBuffer); + printf("\n\rTask List: \n%s", pcWriteBuffer); + } +#endif +#ifdef CONFIG_MEM_MONITOR + printf("\n\rMemory Usage"); + printf("\n\r=============================="); + printf("\r\nMin Free Heap Size: %d", min_free_heap_size); + printf("\r\nCur Free Heap Size: %d\n", xPortGetFreeHeapSize()); +#endif +} + +static void cmd_wifi_on(int argc, char **argv) +{ + if(wifi_on(RTW_MODE_STA)<0){ + printf("\n\rERROR: Wifi on failed!\n"); + } +} + +static void cmd_wifi_off(int argc, char **argv) +{ +#if CONFIG_WEBSERVER + stop_web_server(); +#endif +#if CONFIG_ENABLE_P2P + cmd_wifi_p2p_stop(0, NULL); +#else + wifi_off(); +#endif +} + +static void print_scan_result( rtw_scan_result_t* record ) +{ + RTW_API_INFO( ( "%s\t ", ( record->bss_type == RTW_BSS_TYPE_ADHOC ) ? "Adhoc" : "Infra" ) ); + RTW_API_INFO( ( MAC_FMT, MAC_ARG(record->BSSID.octet) ) ); + RTW_API_INFO( ( " %d\t ", record->signal_strength ) ); + RTW_API_INFO( ( " %d\t ", record->channel ) ); + RTW_API_INFO( ( " %d\t ", record->wps_type ) ); + RTW_API_INFO( ( "%s\t\t ", ( record->security == RTW_SECURITY_OPEN ) ? "Open" : + ( record->security == RTW_SECURITY_WEP_PSK ) ? "WEP" : + ( record->security == RTW_SECURITY_WPA_TKIP_PSK ) ? "WPA TKIP" : + ( record->security == RTW_SECURITY_WPA_AES_PSK ) ? "WPA AES" : + ( record->security == RTW_SECURITY_WPA2_AES_PSK ) ? "WPA2 AES" : + ( record->security == RTW_SECURITY_WPA2_TKIP_PSK ) ? "WPA2 TKIP" : + ( record->security == RTW_SECURITY_WPA2_MIXED_PSK ) ? "WPA2 Mixed" : + "Unknown" ) ); + + RTW_API_INFO( ( " %s ", record->SSID.val ) ); + RTW_API_INFO( ( "\r\n" ) ); +} + +static rtw_result_t app_scan_result_handler( rtw_scan_handler_result_t* malloced_scan_result ) +{ + static int ApNum = 0; + + if (malloced_scan_result->scan_complete != RTW_TRUE) { + rtw_scan_result_t* record = &malloced_scan_result->ap_details; + record->SSID.val[record->SSID.len] = 0; /* Ensure the SSID is null terminated */ + + RTW_API_INFO( ( "%d\t ", ++ApNum ) ); + + print_scan_result(record); + } else{ + ApNum = 0; + } + return RTW_SUCCESS; +} +#if SCAN_WITH_SSID +static void cmd_wifi_scan_with_ssid(int argc, char **argv) +{ + + u8 *channel_list = NULL; + char *ssid = NULL; + int ssid_len; + //Fully scan + int scan_buf_len = 500; + if(argc == 3 && argv[1] && argv[2]){ + ssid = argv[1]; + ssid_len = strlen((const char *)argv[1]); + scan_buf_len = atoi(argv[2]); + }else if(argc > 3){ + int i = 0; + int num_channel = atoi(argv[2]); + ssid = argv[1]; + ssid_len = strlen((const char *)argv[1]); + channel_list = (u8*)pvPortMalloc(num_channel); + if(!channel_list){ + printf("\n\r ERROR: Can't malloc memory for channel list"); + goto exit; + } + //parse command channel list + for(i = 3; i <= argc -1 ; i++){ + *(channel_list + i - 3) = (u8)atoi(argv[i]); + } + if(wifi_set_pscan_chan(channel_list,num_channel) < 0){ + printf("\n\rERROR: wifi set partial scan channel fail"); + goto exit; + } + }else{ + printf("\n\r For Scan all channel Usage: wifi_scan_with_ssid ssid BUFFER_LENGTH"); + printf("\n\r For Scan partial channel Usage: wifi_scan_with_ssid ssid num_channels channel_num1 ..."); + return; + } + + if(wifi_scan_networks_with_ssid(NULL, &scan_buf_len, ssid, ssid_len) != RTW_SUCCESS){ + printf("\n\rERROR: wifi scan failed"); + goto exit; + } + +exit: + if(argc > 2 && channel_list) + vPortFree(channel_list); + +} +#endif +static void cmd_wifi_scan(int argc, char **argv) +{ + + u8 *channel_list = NULL; + u8 *pscan_config = NULL; + + if(argc > 2){ + int i = 0; + int num_channel = atoi(argv[1]); + + channel_list = (u8*)pvPortMalloc(num_channel); + if(!channel_list){ + printf("\n\r ERROR: Can't malloc memory for channel list"); + goto exit; + } + pscan_config = (u8*)pvPortMalloc(num_channel); + if(!pscan_config){ + printf("\n\r ERROR: Can't malloc memory for pscan_config"); + goto exit; + } + //parse command channel list + for(i = 2; i <= argc -1 ; i++){ + *(channel_list + i - 2) = (u8)atoi(argv[i]); + *(pscan_config + i - 2) = PSCAN_ENABLE; + } + + if(wifi_set_pscan_chan(channel_list, pscan_config, num_channel) < 0){ + printf("\n\rERROR: wifi set partial scan channel fail"); + goto exit; + } + + } + + if(wifi_scan_networks(app_scan_result_handler, NULL ) != RTW_SUCCESS){ + printf("\n\rERROR: wifi scan failed"); + goto exit; + } +exit: + if(argc > 2 && channel_list) + vPortFree(channel_list); + +} + +#if CONFIG_WEBSERVER +static void cmd_wifi_start_webserver(int argc, char **argv) +{ + start_web_server(); +} +#endif + +static void cmd_wifi_iwpriv(int argc, char **argv) +{ + if(argc == 2 && argv[1]) { + wext_private_command(WLAN0_NAME, argv[1], 1); + } + else { + printf("\n\rUsage: iwpriv COMMAND PARAMETERS"); + } +} +#endif //#if CONFIG_WLAN + +static void cmd_ping(int argc, char **argv) +{ + if(argc == 2) { + do_ping_call(argv[1], 0, 5); //Not loop, count=5 + } + else if(argc == 3) { + if(strcmp(argv[2], "loop") == 0) + do_ping_call(argv[1], 1, 0); //loop, no count + else + do_ping_call(argv[1], 0, atoi(argv[2])); //Not loop, with count + } + else { + printf("\n\rUsage: ping IP [COUNT/loop]"); + } +} +#if ( configGENERATE_RUN_TIME_STATS == 1 ) +static char cBuffer[ 512 ]; +static void cmd_cpustat(int argc, char **argv) +{ + vTaskGetRunTimeStats( ( char * ) cBuffer ); + printf( cBuffer ); +} +#endif +#if defined(CONFIG_RTL8195A) || defined(CONFIG_RTL8711B) +static void cmd_dump_reg(int argc, char **argv) +{ + CmdDumpWord(argc-1, (u8**)(argv+1)); +} +static void cmd_edit_reg(int argc, char **argv) +{ + CmdWriteWord(argc-1, (u8**)(argv+1)); +} +#endif +static void cmd_exit(int argc, char **argv) +{ + printf("\n\rLeave INTERACTIVE MODE"); + vTaskDelete(NULL); +} + +static void cmd_debug(int argc, char **argv) +{ + if(strcmp(argv[1], "ready_trx") == 0) { + printf("\r\n%d", wifi_is_ready_to_transceive((rtw_interface_t)rtw_atoi((u8*)argv[2]))); + } else if(strcmp(argv[1], "is_up") == 0) { + printf("\r\n%d", wifi_is_up((rtw_interface_t)rtw_atoi((u8*)argv[2]))); + } else if(strcmp(argv[1], "set_mac") == 0) { + printf("\r\n%d", wifi_set_mac_address(argv[2])); + } else if(strcmp(argv[1], "get_mac") == 0) { + u8 mac[18] = {0}; + wifi_get_mac_address((char*)mac); + printf("\r\n%s", mac); + } else if(strcmp(argv[1], "ps_on") == 0) { + printf("\r\n%d", wifi_enable_powersave()); + } else if(strcmp(argv[1], "ps_off") == 0) { + printf("\r\n%d", wifi_disable_powersave()); +#if 0 //TODO + } else if(strcmp(argv[1], "get_txpwr") == 0) { + int idx; + wifi_get_txpower(&idx); + printf("\r\n%d", idx); + } else if(strcmp(argv[1], "set_txpwr") == 0) { + printf("\r\n%d", wifi_set_txpower(rtw_atoi((u8*)argv[2]))); +#endif + } else if(strcmp(argv[1], "get_clientlist") == 0) { + int client_number; + struct { + int count; + rtw_mac_t mac_list[3]; + } client_info; + + client_info.count = 3; + + printf("\r\n%d\r\n", wifi_get_associated_client_list(&client_info, sizeof(client_info))); + + if( client_info.count == 0 ) + { + RTW_API_INFO(("Clients connected 0..\r\n")); + } + else + { + RTW_API_INFO(("Clients connected %d..\r\n", client_info.count)); + for( client_number=0; client_number < client_info.count; client_number++ ) + { + RTW_API_INFO(("------------------------------------\r\n")); + RTW_API_INFO(("| %d | "MAC_FMT" |\r\n", + client_number, + MAC_ARG(client_info.mac_list[client_number].octet) + )); + } + RTW_API_INFO(("------------------------------------\r\n")); + } + } else if(strcmp(argv[1], "get_apinfo") == 0) { + rtw_bss_info_t ap_info; + rtw_security_t sec; + if(wifi_get_ap_info(&ap_info, &sec) == RTW_SUCCESS) { + RTW_API_INFO( ("\r\nSSID : %s\r\n", (char*)ap_info.SSID ) ); + RTW_API_INFO( ("BSSID : "MAC_FMT"\r\n", MAC_ARG(ap_info.BSSID.octet)) ); + RTW_API_INFO( ("RSSI : %d\r\n", ap_info.RSSI) ); + //RTW_API_INFO( ("SNR : %d\r\n", ap_info.SNR) ); + RTW_API_INFO( ("Beacon period : %d\r\n", ap_info.beacon_period) ); + RTW_API_INFO( ( "Security : %s\r\n", ( sec == RTW_SECURITY_OPEN ) ? "Open" : + ( sec == RTW_SECURITY_WEP_PSK ) ? "WEP" : + ( sec == RTW_SECURITY_WPA_TKIP_PSK ) ? "WPA TKIP" : + ( sec == RTW_SECURITY_WPA_AES_PSK ) ? "WPA AES" : + ( sec == RTW_SECURITY_WPA2_AES_PSK ) ? "WPA2 AES" : + ( sec == RTW_SECURITY_WPA2_TKIP_PSK ) ? "WPA2 TKIP" : + ( sec == RTW_SECURITY_WPA2_MIXED_PSK ) ? "WPA2 Mixed" : + "Unknown" ) ); + } + } else if(strcmp(argv[1], "reg_mc") == 0) { + rtw_mac_t mac; + sscanf(argv[2], MAC_FMT, (int*)(mac.octet+0), (int*)(mac.octet+1), (int*)(mac.octet+2), (int*)(mac.octet+3), (int*)(mac.octet+4), (int*)(mac.octet+5)); + printf("\r\n%d", wifi_register_multicast_address(&mac)); + } else if(strcmp(argv[1], "unreg_mc") == 0) { + rtw_mac_t mac; + sscanf(argv[2], MAC_FMT, (int*)(mac.octet+0), (int*)(mac.octet+1), (int*)(mac.octet+2), (int*)(mac.octet+3), (int*)(mac.octet+4), (int*)(mac.octet+5)); + printf("\r\n%d", wifi_unregister_multicast_address(&mac)); + } else if(strcmp(argv[1], "get_rssi") == 0) { + int rssi = 0; + wifi_get_rssi(&rssi); + printf("\n\rwifi_get_rssi: rssi = %d", rssi); + } else { + printf("\r\nUnknown CMD\r\n"); + } +} + +typedef struct _cmd_entry { + char *command; + void (*function)(int, char **); +} cmd_entry; + +static const cmd_entry cmd_table[] = { +#if CONFIG_WLAN + {"wifi_connect", cmd_wifi_connect}, + {"wifi_connect_bssid", cmd_wifi_connect_bssid}, + {"wifi_disconnect", cmd_wifi_disconnect}, + {"wifi_info", cmd_wifi_info}, + {"wifi_on", cmd_wifi_on}, + {"wifi_off", cmd_wifi_off}, + {"wifi_ap", cmd_wifi_ap}, + {"wifi_scan", cmd_wifi_scan}, +#if SCAN_WITH_SSID + {"wifi_scan_with_ssid", cmd_wifi_scan_with_ssid}, +#endif + {"iwpriv", cmd_wifi_iwpriv}, + {"wifi_promisc", cmd_promisc}, +#if CONFIG_OTA_UPDATE + {"wifi_update", cmd_update}, +#endif +#if CONFIG_WEBSERVER + {"wifi_start_webserver", cmd_wifi_start_webserver}, +#endif +#if (CONFIG_INCLUDE_SIMPLE_CONFIG) + {"wifi_simple_config", cmd_simple_config}, +#endif +#ifdef CONFIG_WPS +#if CONFIG_ENABLE_WPS + {"wifi_wps", cmd_wps}, +#endif +#ifdef CONFIG_WPS_AP + {"wifi_ap_wps", cmd_ap_wps}, +#endif +#if CONFIG_ENABLE_P2P + {"wifi_p2p_start", cmd_wifi_p2p_start}, + {"wifi_p2p_stop", cmd_wifi_p2p_stop}, + {"p2p_find", cmd_p2p_find}, + {"p2p_info", cmd_p2p_info}, + {"p2p_disconnect", cmd_p2p_disconnect}, + {"p2p_connect", cmd_p2p_connect}, +#endif +#endif +#ifdef CONFIG_CONCURRENT_MODE + {"wifi_sta_ap",cmd_wifi_sta_and_ap}, +#endif + +#if CONFIG_SSL_CLIENT + {"ssl_client", cmd_ssl_client}, +#endif +#if CONFIG_GOOGLENEST + {"gn", cmd_googlenest}, +#endif +#if CONFIG_EXAMPLE_UART_ADAPTER + {"ut", cmd_uart_adapter}, +#endif +#endif + +#if CONFIG_LWIP_LAYER +// {"app", cmd_app}, + {"wifi_debug", cmd_debug}, +#if CONFIG_BSD_TCP + {"tcp", cmd_tcp}, + {"udp", cmd_udp}, +#endif +#if CONFIG_JD_SMART + {"jd_smart", cmd_jd_smart}, +#endif + {"ping", cmd_ping}, +#endif +#if ( configGENERATE_RUN_TIME_STATS == 1 ) + {"cpu", cmd_cpustat}, +#endif +#if defined(CONFIG_RTL8195A) || defined(CONFIG_RTL8711B) + {"dw", cmd_dump_reg}, + {"ew", cmd_edit_reg}, +#endif + {"exit", cmd_exit}, + {"help", cmd_help} +}; + +#if CONFIG_INTERACTIVE_EXT +/* must include here, ext_cmd_table in wifi_interactive_ext.h uses struct cmd_entry */ +#include +#endif + +static void cmd_help(int argc, char **argv) +{ + int i; + + printf("\n\rCOMMAND LIST:"); + printf("\n\r=============================="); + + for(i = 0; i < sizeof(cmd_table) / sizeof(cmd_table[0]); i ++) + printf("\n\r %s", cmd_table[i].command); +#if CONFIG_INTERACTIVE_EXT + for(i = 0; i < sizeof(ext_cmd_table) / sizeof(ext_cmd_table[0]); i ++) + printf("\n\r %s", ext_cmd_table[i].command); +#endif +} + +#define MAX_ARGC 6 + +static int parse_cmd(char *buf, char **argv) +{ + int argc = 0; + + memset(argv, 0, sizeof(argv)*MAX_ARGC); + while((argc < MAX_ARGC) && (*buf != '\0')) { + argv[argc] = buf; + argc ++; + buf ++; + + while((*buf != ' ') && (*buf != '\0')) + buf ++; + + while(*buf == ' ') { + *buf = '\0'; + buf ++; + } + // Don't replace space + if(argc == 1){ + if(strcmp(argv[0], "iwpriv") == 0){ + if(*buf != '\0'){ + argv[1] = buf; + argc ++; + } + break; + } + } + } + + return argc; +} + +char uart_buf[64]; +void interactive_mode(void *param) +{ + int i, argc; + char *argv[MAX_ARGC]; + extern xSemaphoreHandle uart_rx_interrupt_sema; + + printf("\n\rEnter INTERACTIVE MODE\n\r"); + printf("\n\r# "); + + while(1){ + while(xSemaphoreTake(uart_rx_interrupt_sema, portMAX_DELAY) != pdTRUE); + + if((argc = parse_cmd(uart_buf, argv)) > 0) { + int found = 0; + + for(i = 0; i < sizeof(cmd_table) / sizeof(cmd_table[0]); i ++) { + if(strcmp((const char *)argv[0], (const char *)(cmd_table[i].command)) == 0) { + cmd_table[i].function(argc, argv); + found = 1; + break; + } + } +#if CONFIG_INTERACTIVE_EXT + if(!found) { + for(i = 0; i < sizeof(ext_cmd_table) / sizeof(ext_cmd_table[0]); i ++) { + if(strcmp(argv[0], ext_cmd_table[i].command) == 0) { + ext_cmd_table[i].function(argc, argv); + found = 1; + break; + } + } + } +#endif + if(!found) + printf("\n\runknown command '%s'", argv[0]); + printf("\n\r[MEM] After do cmd, available heap %d\n\r", xPortGetFreeHeapSize()); + } + + printf("\r\n\n# "); + uart_buf[0] = '\0'; + } +} + +void start_interactive_mode(void) +{ +#ifdef SERIAL_DEBUG_RX + if(xTaskCreate(interactive_mode, (char const *)"interactive_mode", STACKSIZE, NULL, tskIDLE_PRIORITY + 4, NULL) != pdPASS) + printf("\n\r%s xTaskCreate failed", __FUNCTION__); +#else + printf("\n\rERROR: No SERIAL_DEBUG_RX to support interactive mode!"); +#endif +} + +#if defined(CONFIG_PLATFORM_8195A) || defined(CONFIG_PLATFORM_8711B) +VOID WlanNormal( IN u16 argc, IN u8 *argv[]) +{ + u8 i, j= 0; + u8* pbuf = (u8*)uart_buf; + extern xSemaphoreHandle uart_rx_interrupt_sema; + + memset(uart_buf, 0, sizeof(uart_buf)); + + printf("argc=%d\n", argc); + for(i = 0 ; i < argc ; i++) + { + printf("command element [%d] = %s\n", i, argv[i]); + for(j = 0; j + +typedef struct { + int socket; + char *host; + ssl_context ssl; +} googlenest_context; + +int gn_connect(googlenest_context *googlenest, char *host, int port); +void gn_close(googlenest_context *googlenest); +int gn_put(googlenest_context *googlenest, char *uri, char *content); +int gn_patch(googlenest_context *googlenest, char *uri, char *content); +int gn_post(googlenest_context *googlenest, char *uri, char *content, unsigned char *out_buffer, size_t out_len); +int gn_get(googlenest_context *googlenest, char *uri, unsigned char *out_buffer, size_t out_len); +int gn_delete(googlenest_context *googlenest, char *uri); +int gn_stream(googlenest_context *googlenest, char *uri); +void google_retrieve_data_hook_callback(void (*callback)(char *)); + +#endif + diff --git a/component/common/application/uart_adapter/uart_adapter.c b/component/common/application/uart_adapter/uart_adapter.c new file mode 100644 index 0000000..ee11102 --- /dev/null +++ b/component/common/application/uart_adapter/uart_adapter.c @@ -0,0 +1,1549 @@ +#include "FreeRTOS.h" +#include "task.h" +#include "main.h" + +#include +#include +#include +#include +#include + +#include + +#include "stdlib.h" +#include "string.h" +#include +#include "autoconf.h" +#include "PinNames.h" + +#include "hal_platform.h" +#include "serial_api.h" +#include "serial_ex_api.h" +#include "lwip/api.h" +#include "uart_adapter.h" +#include "wifi_conf.h" +#include "wifi_util.h" +#include "gpio_api.h" // mbed +#include "gpio_irq_api.h" // mbed +#include "osdep_service.h" +//#include "utils/common.h" +#include + +#include "flash_api.h" +#include + +#include +/*********************************************************************** + * Macros * + ***********************************************************************/ +#define UA_TCP_SERVER_FD_NUM 1 +#define UA_TCP_CLIENT_FD_NUM 1 + +#define UA_UART_RECV_BUFFER_LEN 8192 +#define UA_UART_FRAME_LEN 1400 +#define UA_UART_MAX_DELAY_TIME 100 + +#define UA_DATA_SOCKET_PORT 5001 +#define UA_CONTROL_SOCKET_PORT 6001 + +//in 8711am,there are 1 uart +#define UA_MAX_UART_NUM 1 + +#define UA_GPIO_LED_PIN PC_5 +#define UA_GPIO_IRQ_PIN PC_4 + +#define UA_CONTROL_PREFIX "AMEBA_UART" + +/*********************************************************************** + * Variables Declarations * + ***********************************************************************/ +unsigned char ua_work_thread_terminate = 0; +unsigned char ua_work_thread_suspend = 0; + +int ua_tcp_data_fd_list[UA_TCP_SERVER_FD_NUM] = {-1}; +int ua_tcp_control_fd_list[UA_TCP_CLIENT_FD_NUM] = {-1}; +int ua_tcp_data_client_fd = -1; + +int ua_tcp_data_server_listen_fd = -1; +int ua_tcp_control_server_listen_fd = -1; + +char ua_tcp_server_ip[16]; + +char ua_uart_recv_buf[UA_UART_RECV_BUFFER_LEN] = {0}; +int ua_uart_recv_bytes = 0; +static int ua_pread = 0, ua_pwrite= 0; +static char ua_overlap = 0; + +static volatile char ua_rcv_ch=0; +unsigned int ua_tick_last_update = 0; +unsigned int ua_tick_current = 0; + +xSemaphoreHandle ua_uart_action_sema = NULL; +xSemaphoreHandle ua_tcp_sema = NULL; +xSemaphoreHandle ua_work_thread_sema = NULL; +xSemaphoreHandle ua_main_sema = NULL; + +int ua_gpio_irq_happen = 0; +//int ua_gpio_irq_happen = 0; + +long irq_rx_cnt = 0; +long tcp_tx_cnt = 0; +long irq_tx_cnt = 0; +long irq_miss_cnt = 0; + +int ua_debug_print_en = 0; +int ua_tcp_send_flag = 0; + +serial_t ua_uart_config[UA_MAX_UART_NUM]; //gloable uart_config +serial_t ua_sobj; + +static gpio_t gpio_led; +static gpio_irq_t gpio_btn; + +struct ua_tcp_rx_buffer +{ + char data[UA_UART_FRAME_LEN]; + int data_len; +}; +sys_mbox_t mbox_for_uart_tx; + +rtw_wifi_setting_t ua_wifi_setting = {RTW_MODE_NONE, {0}, 0, RTW_SECURITY_OPEN, {0}}; + +/************************************************************************ + * extern variables * + ************************************************************************/ +extern struct netif xnetif[NET_IF_NUM]; + +//static int is_fixed_channel; +//extern int fixed_channel_num; +//extern unsigned char g_ssid[32]; +//extern int g_ssid_len; +//extern unsigned char g_bssid[]; +//extern unsigned char g_security_mode; +//extern int simple_config_result; +//extern unsigned int simple_config_cmd_start_time; +enum ua_sc_result { + SC_ERROR = -1, /* default error code*/ + SC_NO_CONTROLLER_FOUND = 1, /* cannot get sta(controller) in the air which starts a simple config session */ + SC_CONTROLLER_INFO_PARSE_FAIL, /* cannot parse the sta's info */ + SC_TARGET_CHANNEL_SCAN_FAIL, /* cannot scan the target channel */ + SC_JOIN_BSS_FAIL, /* fail to connect to target ap */ + SC_DHCP_FAIL, /* fail to get ip address from target ap */ + /* fail to create udp socket to send info to controller. note that client isolation + must be turned off in ap. we cannot know if ap has configured this */ + SC_UDP_SOCKET_CREATE_FAIL, + SC_SUCCESS, /* default success code */ +}; + +//typedef int (*wlan_init_done_ptr)(void); +extern unsigned char psk_essid[NET_IF_NUM][NDIS_802_11_LENGTH_SSID+4]; +extern unsigned char psk_passphrase[NET_IF_NUM][IW_PASSPHRASE_MAX_SIZE + 1]; +extern unsigned char wpa_global_PSK[NET_IF_NUM][A_SHA_DIGEST_LEN * 2]; + +extern wlan_init_done_ptr p_wlan_uart_adapter_callback; + +/************************************************************************ + * extern funtions * + ************************************************************************/ +#if CONFIG_INCLUDE_SIMPLE_CONFIG +//extern void simple_config_callback(unsigned char *buf, unsigned int len, void* userdata); +//extern int SC_connect_to_AP(void); +//extern int SC_send_simple_config_ack(void); +//extern void SC_check_and_show_connection_info(void); +extern int simple_config_test(void); +//extern void print_simple_config_result(enum sc_result sc_code); +extern int init_test_data(char *custom_pin_code); +extern void deinit_test_data(void); +extern void filter_add_enable(); +extern void remove_filter(); +//extern void rtk_restart_simple_config(void); +//extern int promisc_fixed_channel_num(void * fixed_bssid, u8 *ssid, int * ssid_length); +//extern int promisc_get_fixed_channel(void * fixed_bssid, u8 * ssid, int * ssid_length); +//extern void get_connection_info_from_profile(rtw_security_t security_mode, rtw_network_info_t *wifi); +extern void wifi_enter_promisc_mode(); +#endif +/************************************************************************* +* uart releated * +*************************************************************************/ +#define UA_PRINT_DATA(_HexData, _HexDataLen) \ + if(UA_DEBUG_LEVEL == UA_DEBUG) \ + { \ + int __i; \ + u8 *ptr = (u8 *)_HexData; \ + printf("--------Len=%d\n\r", _HexDataLen); \ + for( __i=0; __i<(int)_HexDataLen; __i++ ) \ + { \ + printf("%02X%s", ptr[__i], (((__i + 1) % 4) == 0)?" ":" "); \ + if (((__i + 1) % 16) == 0) printf("\n\r"); \ + } \ + printf("\n\r"); \ + } + +#define ____________UART__RELATED____________________ +static void uartadapter_uart_irq(uint32_t id, SerialIrq event) +{ + portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; + + if(event == RxIrq) { + ua_rcv_ch = serial_getc(&ua_sobj); + ua_uart_recv_buf[ua_pwrite] = ua_rcv_ch; + ua_pwrite++; //point to uart data recved + xSemaphoreGiveFromISR( ua_uart_action_sema, &xHigherPriorityTaskWoken ); //up action semaphore + + if(ua_pwrite > (UA_UART_RECV_BUFFER_LEN -1)){ //restart from head if reach tail + ua_pwrite = 0; + ua_overlap = 1; + } + + if(ua_overlap && (ua_pwrite - 1) >= ua_pread ){ + //ua_printf(UA_ERROR, "IRQ missing data %d byte!", ua_pread - ua_pwrite + 1); + irq_miss_cnt ++; + ua_pread = ua_pwrite; //if pwrite overhead pread ,pread is always flow rwrite + } + ua_tick_last_update = xTaskGetTickCountFromISR(); // update tick everytime recved data + irq_rx_cnt ++; + } +} + +static int uartadapter_uart_recv_data(void) +{ + //int ret = 0; + int uart_recv_len = 0; + + ua_tick_current = xTaskGetTickCount(); + while((ua_tick_current -ua_tick_last_update) < (UA_UART_MAX_DELAY_TIME/portTICK_RATE_MS) + || ua_tick_current <= ua_tick_last_update){ + if(!ua_overlap){ + uart_recv_len = ua_pwrite - ua_pread; + }else{ + uart_recv_len = (UA_UART_RECV_BUFFER_LEN - ua_pread) + ua_pwrite; + } + + if(uart_recv_len >= UA_UART_FRAME_LEN){ + return 2; + } + ua_tick_current = xTaskGetTickCount(); + } + + return 1; +} + +int uartadapter_uart_read(void *read_buf, size_t size) +{ + /*the same as socket*/ + int ret = 0; + int read_bytes; + int pread_local,pwrite_local; + char *ptr; + ua_printf(UA_DEBUG, "==>uart adapter read uart"); + if(!size || !read_buf){ + ua_printf(UA_ERROR, "inpua error,size should not be null"); + ret = -1; + return ret; + } + + pread_local = ua_pread; + pwrite_local = ua_pwrite; + ptr = (char *)read_buf; + + /*calculate how much data not read */ + if(!ua_overlap){ + ua_uart_recv_bytes = pwrite_local - pread_local; + }else{ + ua_uart_recv_bytes = (UA_UART_RECV_BUFFER_LEN - pread_local) + pwrite_local; + } + + /*decide how much data shoule copy to application*/ + if(size >= ua_uart_recv_bytes ){ + read_bytes = ua_uart_recv_bytes; + ret = ua_uart_recv_bytes; + }else{ + read_bytes = size; + ret = size; + } + + if(!ua_overlap){ + memcpy(ptr, (ua_uart_recv_buf+ pread_local), read_bytes ); + }else { + ua_printf(UA_DEBUG, "uart recv buf is write overlap!!"); + if((pread_local + read_bytes) > UA_UART_RECV_BUFFER_LEN){ + memcpy(ptr,(ua_uart_recv_buf+ pread_local),(UA_UART_RECV_BUFFER_LEN-pread_local)); + memcpy(ptr+(UA_UART_RECV_BUFFER_LEN-pread_local),ua_uart_recv_buf,read_bytes-(UA_UART_RECV_BUFFER_LEN- pread_local)); + }else{ + memcpy(ptr,(ua_uart_recv_buf+ pread_local),read_bytes); + } + } + + ua_uart_recv_bytes = 0; + if((pread_local + read_bytes) >= UA_UART_RECV_BUFFER_LEN){ //update pread + ua_pread = (pread_local + read_bytes) - UA_UART_RECV_BUFFER_LEN; + ua_overlap = 0; //clean overlap flags + }else{ + ua_pread = pread_local + read_bytes; + } + + return ret; +} + + +int uartadapter_uart_write(char *pbuf, size_t size) +{ + /*the same as socket*/ + int ret = 0; + //int cnt = 0; + + if(!size || !pbuf){ + //ua_printf(UA_ERROR, "inpua error,please check!"); + ret = -1; + return ret; + } + +#if 1 + do{ + ret = serial_send_stream_dma(&ua_sobj, pbuf, size); + }while(ret != HAL_OK); +#else + while (size){ + serial_putc(&ua_sobj, *pbuf); + //printf("uart write %d \n", *pbuf); + size--; + pbuf++; + } +#endif + return ret; +} + +static void uartadapter_uart_rx_handle(void* param) +{ + char *rxbuf = NULL; + int ret =0; + int read_len = 0; + + rxbuf = pvPortMalloc(UA_UART_FRAME_LEN); + if(NULL == rxbuf){ + ua_printf(UA_ERROR, "TCP: Allocate rx buffer failed.\n"); + return; + } + + while(xSemaphoreTake(ua_uart_action_sema, portMAX_DELAY) == pdTRUE){ + if(ua_debug_print_en) { + //ua_printf(UA_INFO, "uartadapter_uart_thread_handle loop!"); + } + + ret = uartadapter_uart_recv_data(); + if(ret == -1){ + ua_printf(UA_ERROR, "uart recv data error!"); + }else{ + read_len = uartadapter_uart_read(rxbuf, UA_UART_FRAME_LEN); + if(read_len > 0){ + uartadapter_tcpsend(rxbuf, read_len, 0); + }else if(read_len < 0){ + ua_printf(UA_ERROR, "tcp send read_len = %d", read_len); + } + } + } +} + +static void uartadapter_uart_tx_handle(void* param) +{ + struct ua_tcp_rx_buffer *uart_tx; + //int ret; + + while(1) + { + sys_mbox_fetch(&mbox_for_uart_tx, (void *)&uart_tx); + uartadapter_uart_write(uart_tx->data, uart_tx->data_len); + vPortFree(uart_tx); + } +} + +int uartadapter_uart_open(char *uartname, ua_uart_set_str *puartpara) +{ + PinName uart_tx,uart_rx; + + if(!strcmp("uart0", uartname)){ + uart_tx = PA_7; + uart_rx = PA_6; + ua_uart_config[0].hal_uart_adp.BaudRate = puartpara->BaudRate; + ua_uart_config[0].hal_uart_adp.FlowControl = puartpara->FlowControl; + ua_uart_config[0].hal_uart_adp.WordLen = puartpara->number; + ua_uart_config[0].hal_uart_adp.Parity = puartpara->parity; + ua_uart_config[0].hal_uart_adp.StopBit = puartpara->StopBits; + }else{ + ua_printf(UA_ERROR, "please check uart name!"); + return RTW_ERROR; + } + + /*initial uart */ + serial_init(&ua_sobj,uart_tx,uart_rx); + serial_baud(&ua_sobj,puartpara->BaudRate); + serial_format(&ua_sobj, puartpara->number, (SerialParity)puartpara->parity, puartpara->StopBits); + + /*uart irq handle*/ + serial_irq_handler(&ua_sobj, uartadapter_uart_irq, (uint32_t)&ua_sobj); + serial_irq_set(&ua_sobj, RxIrq, 1); + serial_irq_set(&ua_sobj, TxIrq, 1); + + return 0; +} + +int uartadapter_uart_baud(int baud_rate) +{ + int ret = 0; + serial_baud(&ua_sobj, baud_rate); + + return ret; +} + +int uartadapter_uart_para(int word_len, int parity, int stop_bits) +{ + int ret = 0; + + serial_format(&ua_sobj, word_len, (SerialParity)parity, stop_bits); + + return ret; +} + +int uartadapter_uart_getnum(char *uartname) +{ + /*only uart 0 can used*/ + strcpy(uartname, "uart0\\"); + return UA_MAX_UART_NUM; +} + +int uartadapter_uart_getpara(char *uart_name, ua_uart_get_str *uart_para) +{ + int ret = 0; + + /*get the uart para according to uart_name*/ + if(!strcmp("uart0", uart_name)){ + uart_para->BaudRate =ua_uart_config[0].hal_uart_adp.BaudRate; + uart_para->FlowControl =ua_uart_config[0].hal_uart_adp.FlowControl; + uart_para->number = ua_uart_config[0].hal_uart_adp.WordLen; + uart_para->parity = ua_uart_config[0].hal_uart_adp.Parity; + uart_para->StopBits = ua_uart_config[0].hal_uart_adp.StopBit; + }else{ + ua_printf(UA_ERROR, "please check uart name!"); + return -1; + } + + return ret; +} +void uartadapter_uart_init() +{ + ua_uart_set_str uartset; + ua_uart_get_str uartget; + int uartnum; + char uarttest[]="uart0"; + char uartname[32] = {0}; + + uartset.BaudRate = 9600; + uartset.number = 8; + uartset.StopBits = 0; + uartset.FlowControl = 0; + uartset.parity = 0; + strcpy(uartset.UartName,uarttest); + + uartnum = uartadapter_uart_getnum(uartname); + ua_printf(UA_DEBUG, "there is %d uart on this platform",uartnum); + ua_printf(UA_DEBUG, "uartname = %s",uartname); + + uartadapter_uart_open("uart0", &uartset); + + if(uartadapter_uart_getpara("uart0", &uartget)) + ua_printf(UA_ERROR, "get uart failed!"); + else + ua_printf(UA_DEBUG,"uart pata:\r\n"\ + "uart->BaudRate = %d\r\n"\ + "uart->number = %d\r\n"\ + "uart->FlowControl = %d\r\n"\ + "uart->parity = %d\r\n"\ + "uart->StopBits = %d\r\n"\ + "\r\n",\ + uartget.BaudRate,\ + uartget.number,\ + uartget.FlowControl,\ + uartget.parity,\ + uartget.StopBits\ + ); +} + +#define _________FLASH___RELATED________________________ + +int uartadapter_flashread(int flashadd, char *pbuf, int len) +{ + int ret = 0; + flash_t flash; + + if( len == 0){ + ua_printf(UA_ERROR, "inpua error,data length should not be null!"); + ret = -1; + return ret; + }else //as 8711am only canbe r/w in words.so make len is 4-bytes aligmented. + len += 4 - ((len%4)==0 ? 4 : (len%4)); + + while(len){ + if(flash_read_word(&flash, flashadd, (unsigned int *)pbuf) !=1 ){ + ua_printf(UA_ERROR, "read flash error!"); + ret = -1; + return ret; + } + len -= 4; + pbuf += 4; + flashadd += 4; + } + + return len; +} + +int uartadapter_flashwrite(int flashadd, char *pbuf, int len) +{ + int ret = 0; + flash_t flash; + + if( len == 0){ + ua_printf(UA_ERROR, "inpua error,data length should not be null!"); + ret = -1; + return ret; + } + else //as 8711am only canbe r/w in words.so make len is 4-bytes aligmented. + len += 4 - ((len%4)==0 ? 4 : (len%4)); + + while(len){ + if(flash_write_word(&flash, flashadd, *(unsigned int *)pbuf) !=1 ){ + ua_printf(UA_ERROR, "write flash error!"); + ret = -1; + return ret; + } + len -= 4; + pbuf += 4; + flashadd += 4; + } + + return ret; +} + +int uartadapter_flasherase(int flashadd, int erase_bytelen) +{ + int ret = 0; + flash_t flash; + + flash_erase_sector(&flash, flashadd); + + return ret; +} + +#define _________GPIO___RELATED________________________ +void uartadapter_systemreload(void) +{ + // Cortex-M3 SCB->AIRCR + HAL_WRITE32(0xE000ED00, 0x0C, (0x5FA << 16) | // VECTKEY + (HAL_READ32(0xE000ED00, 0x0C) & (7 << 8)) | // PRIGROUP + (1 << 2)); // SYSRESETREQ +} +void uartadapter_gpio_irq (uint32_t id, gpio_irq_event event) +{ + //int ret = 0; + //int address = FAST_RECONNECT_DATA; + + ua_printf(UA_DEBUG, "GPIO push button!!"); + + + ua_gpio_irq_happen = 1; + xSemaphoreGive(ua_main_sema); + + +} + +void uartadapter_gpio_init() +{ + gpio_init(&gpio_led, UA_GPIO_IRQ_PIN); + gpio_dir(&gpio_led, PIN_INPUT); // Direction: Output + gpio_mode(&gpio_led, PullNone); // No pull + + gpio_irq_init(&gpio_btn, UA_GPIO_IRQ_PIN, uartadapter_gpio_irq, (uint32_t)(&gpio_led)); + gpio_irq_set(&gpio_btn, IRQ_FALL, 1); // Falling Edge Trigger + gpio_irq_enable(&gpio_btn); +} + + +#define _________CONTROL__DATA__RELATED________________________ +int uartadapter_strncmp(char *cs, char *ct, size_t count) +{ + unsigned char c1, c2; + + while (count) { + c1 = *cs++; + c2 = *ct++; + if (c1 != c2) + return c1 < c2 ? -1 : 1; + if (!c1) + break; + count--; + } + + return 0; +} +int uartadapter_control_set_req_handle(u8 *pbuf, u32 sz) +{ + u8 *p = pbuf; + u8 type = 0, len = 0; + + ua_printf(UA_DEBUG, "\n===>uartadapter_control_set_req_handle()"); + UA_PRINT_DATA(pbuf, sz); + + while(p < (pbuf+sz)){ + type = *p++; + len = *p++; + ua_printf(UA_DEBUG, "type=%d len=%d\n", type, len); + switch(type) + { + case UART_CTRL_TYPE_BAUD_RATE: + ua_uart_config[0].hal_uart_adp.BaudRate = *(u32 *)p; + ua_printf(UA_INFO, "SET UART BAUD_RATE to %d.\n", ua_uart_config[0].hal_uart_adp.BaudRate); + serial_baud(&ua_sobj, ua_uart_config[0].hal_uart_adp.BaudRate); + break; + case UART_CTRL_TYPE_WORD_LEN: + ua_uart_config[0].hal_uart_adp.WordLen = *p; + ua_printf(UA_INFO, "SET UART WORD_LEN to %d.\n", ua_uart_config[0].hal_uart_adp.WordLen); + serial_format(&ua_sobj, + ua_uart_config[0].hal_uart_adp.WordLen, + (SerialParity)ua_uart_config[0].hal_uart_adp.Parity, + ua_uart_config[0].hal_uart_adp.StopBit); + break; + case UART_CTRL_TYPE_PARITY: + ua_uart_config[0].hal_uart_adp.Parity = *p; + ua_printf(UA_INFO, "SET UART PARITY to %d.\n", ua_uart_config[0].hal_uart_adp.Parity); + serial_format(&ua_sobj, + ua_uart_config[0].hal_uart_adp.WordLen, + (SerialParity)ua_uart_config[0].hal_uart_adp.Parity, + ua_uart_config[0].hal_uart_adp.StopBit); + break; + case UART_CTRL_TYPE_STOP_BIT: + ua_uart_config[0].hal_uart_adp.StopBit = *p; + ua_printf(UA_INFO, "SET UART STOP_BIT to %d.\n", ua_uart_config[0].hal_uart_adp.StopBit); + serial_format(&ua_sobj, + ua_uart_config[0].hal_uart_adp.WordLen, + (SerialParity)ua_uart_config[0].hal_uart_adp.Parity, + ua_uart_config[0].hal_uart_adp.StopBit); + break; + case UART_CTRL_TYPE_FLOW_CTRL: + ua_uart_config[0].hal_uart_adp.FlowControl = *p; + ua_printf(UA_INFO, "SET UART FLOW_CTRL to %d.\n", ua_uart_config[0].hal_uart_adp.FlowControl); + ua_printf(UA_INFO, "SET UART FLOW_CTRL not support now.\n"); + //TODO + break; + } + p += len; + } + return 0; +} + +int uartadapter_control_get_req_handle(u8 type, u8 *prsp, u32 *sz) +{ + u8 *p = prsp; + + ua_printf(UA_DEBUG, "===>uartadapter_control_get_req_handle()"); + sprintf((char *)p, UA_CONTROL_PREFIX); + p += strlen(UA_CONTROL_PREFIX); + *p++ = UART_CTRL_MODE_GET_RSP; + + if(type & UART_CTRL_TYPE_BAUD_RATE){ + *p++ = UART_CTRL_TYPE_BAUD_RATE; + *p++ = 4; + *(u32*)p = ua_uart_config[0].hal_uart_adp.BaudRate; + p += 4; + } + if(type & UART_CTRL_TYPE_WORD_LEN){ + *p++ = UART_CTRL_TYPE_WORD_LEN; + *p++ = 1; + *p = ua_uart_config[0].hal_uart_adp.WordLen; + p += 1; + } + if(type & UART_CTRL_TYPE_PARITY){ + *p++ = UART_CTRL_TYPE_PARITY; + *p++ = 1; + *p = ua_uart_config[0].hal_uart_adp.Parity; + p += 1; + } + if(type & UART_CTRL_TYPE_STOP_BIT){ + *p++ = UART_CTRL_TYPE_STOP_BIT; + *p++ = 1; + *p = ua_uart_config[0].hal_uart_adp.StopBit; + p += 1; + } + if(type & UART_CTRL_TYPE_FLOW_CTRL){ + *p++ = UART_CTRL_TYPE_FLOW_CTRL; + *p++ = 1; + *p = ua_uart_config[0].hal_uart_adp.FlowControl; + p += 1; + } + *sz = p - prsp; + + UA_PRINT_DATA(prsp, *sz); + return 0; +} + +int uartadapter_control_process(int fd, char *pbuf, size_t size) +{ + /*the same as socket*/ + int ret = 0; + + if(!size || !pbuf){ + //ua_printf(UA_ERROR, "control data input error,please check!"); + ret = -1; + return ret; + } + + UA_PRINT_DATA(pbuf, size); + + if(uartadapter_strncmp(pbuf, UA_CONTROL_PREFIX, 10) != 0) + { + ua_printf(UA_ERROR, "control data prefix wrong!"); + return -1; + } + else + { + u8 *p = (u8*)pbuf + strlen(UA_CONTROL_PREFIX); + u8 mode = *p++; + switch(mode) + { + case UART_CTRL_MODE_SET_REQ: //AMEBA_UART-MODE-TYPE-LEN-VAL-TYPE-LEN-VAL... + { + char rsp[32] = {0}; //AMEBA_UART-MODE + u32 sz = strlen(UA_CONTROL_PREFIX); + uartadapter_control_set_req_handle(p, (size - strlen(UA_CONTROL_PREFIX))); + sprintf(rsp, UA_CONTROL_PREFIX); + *(rsp + sz) = UART_CTRL_MODE_SET_RSP; + sz ++; + sprintf(rsp + sz, "\n"); + sz ++; + uartadapter_tcpsend(rsp, sz, 1); + break; + } + case UART_CTRL_MODE_GET_REQ: //AMEBA_UART-MODE-TYPE + { + char rsp[128] = {0}; + u32 sz = 0; + u8 type = *p; + uartadapter_control_get_req_handle(type, (u8*)rsp, &sz); + sprintf(rsp + sz, "\n"); + sz ++; + uartadapter_tcpsend(rsp, sz, 1); + break; + } + default: + ua_printf(UA_ERROR, UA_CONTROL_PREFIX": Mode (%d) not support!", mode); + break; + } + } + return 0; +} + +#define _________TCP__RELATED________________________ +int uartadapter_tcpclient(const char *host_ip, unsigned short usPort) +{ + int iAddrSize; + int iSockFD = -1; + int iStatus; + //int enable = 1; + struct sockaddr_in sAddr; + + FD_ZERO(&sAddr); + sAddr.sin_family = AF_INET; + sAddr.sin_port = htons(usPort); + sAddr.sin_addr.s_addr = inet_addr(host_ip); + + iAddrSize = sizeof(struct sockaddr_in); + + iSockFD = socket(AF_INET, SOCK_STREAM, 0); + if( iSockFD < 0 ) { + ua_printf(UA_ERROR, "TCP ERROR: create tcp client socket fd error!"); + return 0; + } + + ua_printf(UA_DEBUG, "TCP: ServerIP=%s port=%d.", host_ip, usPort); + ua_printf(UA_DEBUG, "TCP: Create socket %d.", iSockFD); + // connecting to TCP server + iStatus = connect(iSockFD, (struct sockaddr *)&sAddr, iAddrSize); + if (iStatus < 0) { + ua_printf(UA_ERROR, "TCP ERROR: tcp client connect server error! "); + goto Exit; + } + +#if 0 + iStatus = setsockopt(iSockFD, IPPROTO_TCP, TCP_NODELAY, &enable, sizeof(enable)); + if (iStatus < 0) { + printf("\n\rTCP ERROR: tcp client socket set opt error! "); + goto Exit; + } +#endif + + ua_printf(UA_INFO, "TCP: Connect server successfully."); +#if 1 + ua_work_thread_suspend = 1; + vTaskDelay(1500); + if(ua_tcp_data_fd_list[0] != -1){ + ua_printf(UA_INFO, "TCP: Close old data client fd %d.", ua_tcp_data_fd_list[0]); + close(ua_tcp_data_fd_list[0]); + } + ua_tcp_data_fd_list[0] = iSockFD; + ua_printf(UA_INFO, "connect new data socket %d successfully.", iSockFD); + ua_work_thread_suspend = 0; + xSemaphoreGive(ua_work_thread_sema); +#else + ua_tcp_data_client_fd = iSockFD; +#endif + + return 0; + +Exit: + //ua_printf(UA_ERROR, "TCP client fd list exceed."); + close(iSockFD); + return 0; +} + + +int uartadapter_tcpserver(unsigned short usPort, u8 isctrl) +{ + struct sockaddr_in sLocalAddr; + int iAddrSize; + int iSockFD; + int iStatus; + + iSockFD = socket(AF_INET, SOCK_STREAM, 0); + if( iSockFD < 0 ) { + ua_printf(UA_ERROR, "create server_socket error!"); + goto Exit; + } + + ua_printf(UA_DEBUG, "TCP: Create Tcp server socket %d", iSockFD); + + //filling the TCP server socket address + memset((char *)&sLocalAddr, 0, sizeof(sLocalAddr)); + sLocalAddr.sin_family = AF_INET; + sLocalAddr.sin_len = sizeof(sLocalAddr); + sLocalAddr.sin_port = htons(usPort); + sLocalAddr.sin_addr.s_addr = htonl(INADDR_ANY); + + iAddrSize = sizeof(sLocalAddr); + + iStatus = bind(iSockFD, (struct sockaddr *)&sLocalAddr, iAddrSize); + if( iStatus < 0 ) { + ua_printf(UA_ERROR, "bind tcp server socket fd error! "); + goto Exit; + } + ua_printf(UA_DEBUG, "TCP: Bind successfully."); + + iStatus = listen(iSockFD, 10); + if( iStatus != 0 ) { + ua_printf(UA_ERROR, "listen tcp server socket fd error!"); + goto Exit; + } + ua_printf(UA_INFO, "TCP Server: Listen on port %d", usPort); + + if(isctrl) + ua_tcp_control_server_listen_fd = iSockFD; + else + ua_tcp_data_server_listen_fd = iSockFD; + + return 0; + +Exit: + close(iSockFD); + ua_printf(UA_INFO, "Tcp server listen on port %d closed!", usPort); + return 0; +} + +void uartadapter_tcp_data_server_handler(void *param) +{ + unsigned short port = UA_DATA_SOCKET_PORT; + + ua_printf(UA_DEBUG, "Uart Adapter: Start Tcp Data Server!"); + uartadapter_tcpserver(port, 0); + +#if defined(INCLUDE_uxTaskGetStackHighWaterMark) && (INCLUDE_uxTaskGetStackHighWaterMark == 1) + ua_printf(UA_DEBUG, "Min available stack size of %s = %d * %d bytes\n\r", __FUNCTION__, uxTaskGetStackHighWaterMark(NULL), sizeof(portBASE_TYPE)); +#endif + ua_printf(UA_DEBUG, "TCP: Tcp data server stopped!"); + vTaskDelete(NULL); +} + +void uartadapter_tcp_data_client_handler(void *param) +{ + unsigned short port = UA_DATA_SOCKET_PORT; + + ua_printf(UA_DEBUG, "Uart Adapter: Start Tcp Data Client!"); + uartadapter_tcpclient(ua_tcp_server_ip, port); + +#if defined(INCLUDE_uxTaskGetStackHighWaterMark) && (INCLUDE_uxTaskGetStackHighWaterMark == 1) + ua_printf(UA_DEBUG, "Min available stack size of %s = %d * %d bytes\n\r", __FUNCTION__, uxTaskGetStackHighWaterMark(NULL), sizeof(portBASE_TYPE)); +#endif + ua_printf(UA_DEBUG, "TCP: Tcp data client stopped!"); + vTaskDelete(NULL); +} + +void uartadapter_tcp_control_server_handler(void *param) +{ + unsigned short port = UA_CONTROL_SOCKET_PORT; + + ua_printf(UA_DEBUG, "Uart Adapter: Start Tcp Control Server!"); + uartadapter_tcpserver(port, 1); + +#if defined(INCLUDE_uxTaskGetStackHighWaterMark) && (INCLUDE_uxTaskGetStackHighWaterMark == 1) + ua_printf(UA_DEBUG, "Min available stack size of %s = %d * %d bytes", __FUNCTION__, uxTaskGetStackHighWaterMark(NULL), sizeof(portBASE_TYPE)); +#endif + ua_printf(UA_DEBUG, "TCP: Tcp control server stopped!"); + vTaskDelete(NULL); +} + +void uartadapter_tcpsend(char *buffer, int size, u8 isctrl) +{ + int iStatus; + + ua_tcp_send_flag = 1; + + if(!isctrl){ + if(ua_tcp_data_fd_list[0] != -1){ + //xSemaphoreTake(ua_tcp_sema, portMAX_DELAY); + iStatus = send(ua_tcp_data_fd_list[0], buffer, size, 0 ); + //xSemaphoreGive(ua_tcp_sema); + + if( iStatus <= 0 ){ + ua_printf(UA_ERROR, "tcp data socket send data error! iStatus:%d!", iStatus); + //goto Exit; + }else if(iStatus != size){ + ua_printf(UA_DEBUG, "uart tcp data socket send: size %d, ret = %d!", size, iStatus); + } + + if(ua_debug_print_en){ + ua_printf(UA_INFO, "uart tcp data socket send %d bytes, ret %d!", size, iStatus); + } + } + } + else{ + if(ua_tcp_control_fd_list[0] != -1){ + //xSemaphoreTake(ua_tcp_sema, portMAX_DELAY); + iStatus = send(ua_tcp_control_fd_list[0], buffer, size, 0 ); + //xSemaphoreGive(ua_tcp_sema); + + if( iStatus <= 0 ){ + ua_printf(UA_ERROR,"tcp control socket send data error! iStatus:%d!", iStatus); + goto Exit; + }else if(iStatus != size){ + ua_printf(UA_DEBUG,"uart tcp control socket send: size %d, ret = %d!", size, iStatus); + } + + if(ua_debug_print_en){ + ua_printf(UA_INFO,"uart tcp control socket send %d bytes, ret %d!", size, iStatus); + } + } + } + + ua_tcp_send_flag = 0; + +Exit: + + return; +} + +void uartadapter_tcp_data_fd_handler(char *tcp_rxbuf) +{ + int recv_len; + struct ua_tcp_rx_buffer *rx_buffer; + rx_buffer = pvPortMalloc(sizeof(struct ua_tcp_rx_buffer)); + if(NULL == rx_buffer){ + ua_printf(UA_ERROR, "Allocate tcp data buffer failed.\n"); + return; + } + + //xSemaphoreTake(ua_tcp_sema, portMAX_DELAY); + recv_len = recv(ua_tcp_data_fd_list[0], tcp_rxbuf, UA_UART_FRAME_LEN, 0); + //xSemaphoreGive(ua_tcp_sema); + + if(recv_len < 0){ + ua_printf(UA_ERROR, "Tcp Data Socket %d Recv Error", ua_tcp_data_fd_list[0]); + //goto EXIT; + } + ua_printf(UA_DEBUG, "Tcp Data Socket %d Recv %d Data", ua_tcp_data_fd_list[0], recv_len); + +#if 1 + if(recv_len > 0){ + memcpy(rx_buffer->data, tcp_rxbuf, recv_len); + rx_buffer->data_len = recv_len; + sys_mbox_post(&mbox_for_uart_tx, (void *)rx_buffer); + }else{ + vPortFree(rx_buffer); + } +#else + uartadapter_uart_write(tcp_rxbuf, recv_len); +#endif + + tcp_tx_cnt += recv_len; + + return; +} + +void uartadapter_tcp_control_fd_handler() +{ + char tcp_rxbuf[UA_UART_FRAME_LEN]; + int recv_len; + + //xSemaphoreTake(ua_tcp_sema, portMAX_DELAY); + recv_len = recv(ua_tcp_control_fd_list[0], tcp_rxbuf, UA_UART_FRAME_LEN, 0); //MSG_DONTWAIT MSG_WAITALL + //xSemaphoreGive(ua_tcp_sema); + + if(recv_len<0){ + ua_printf(UA_ERROR, "Tcp Control Socket %d Recv Error", ua_tcp_control_fd_list[0]); + //goto EXIT; + } + ua_printf(UA_DEBUG, "Tcp Control Socket %d Recv %d Data", ua_tcp_control_fd_list[0], recv_len); + + uartadapter_control_process(ua_tcp_control_fd_list[0], (void*)tcp_rxbuf, recv_len); + + return; + +} + +void uartadapter_tcp_data_listen_fd_handler(int old_data_fd) +{ + struct sockaddr_in sAddr; + int addrlen = sizeof(sAddr); + + ua_tcp_data_fd_list[0] = accept(ua_tcp_data_server_listen_fd, (struct sockaddr *)&sAddr, (socklen_t*)&addrlen); + if( ua_tcp_data_fd_list[0] < 0 ) { + ua_printf(UA_ERROR, "Accept tcp data client socket fd error"); + goto EXIT; + } + ua_printf(UA_INFO, "Accept new data socket %d on port %d successfully.", ua_tcp_data_fd_list[0], sAddr.sin_port); + if(old_data_fd != -1) + { + shutdown(old_data_fd, 2); + close(old_data_fd); + ua_printf(UA_INFO, "Close old data socket %d.", old_data_fd); + old_data_fd = -1; + } + + return; + +EXIT: + if(ua_tcp_data_server_listen_fd != -1){ + close(ua_tcp_data_server_listen_fd); + ua_tcp_data_server_listen_fd = -1; + } +} + +void uartadapter_tcp_control_listen_fd_handler(int old_control_fd) +{ + struct sockaddr_in sAddr; + int addrlen = sizeof(sAddr); + + ua_tcp_control_fd_list[0] = accept(ua_tcp_control_server_listen_fd, (struct sockaddr *)&sAddr, (socklen_t*)&addrlen); + if( ua_tcp_control_fd_list[0] < 0 ) { + ua_printf(UA_ERROR, "Accept tcp control client socket fd error"); + goto EXIT; + } + ua_printf(UA_INFO, "Accept new control socket %d on port %d successfully.", ua_tcp_control_fd_list[0], sAddr.sin_port); + if(old_control_fd != -1) + { + close(old_control_fd); + ua_printf(UA_INFO, "Close old control socket %d.", old_control_fd); + old_control_fd = -1; + } + + return; + +EXIT: + if(ua_tcp_data_server_listen_fd != -1){ + close(ua_tcp_data_server_listen_fd); + ua_tcp_data_server_listen_fd = -1; + } +} + +void uartadapter_tcp_select(void *param) +{ + int max_fd; + struct timeval tv; + fd_set readfds; + int ret = 0; + char *tcp_rxbuf; + tcp_rxbuf = pvPortMalloc(UA_UART_FRAME_LEN); + if(NULL == tcp_rxbuf){ + printf("\n\rTCP: Allocate client buffer failed.\n"); + return; + } + + + while(1){ + if(ua_work_thread_suspend){ + ua_printf(UA_DEBUG, "uart adapter test thread suspended!"); + if(xSemaphoreTake(ua_work_thread_sema, portMAX_DELAY) == TRUE) + ua_printf(UA_DEBUG, "uart adapter test thread take semaphore!"); + } + + FD_ZERO(&readfds); + max_fd = -1; + + if(ua_tcp_data_fd_list[0] != -1){ + FD_SET(ua_tcp_data_fd_list[0], &readfds); + if(ua_tcp_data_fd_list[0] > max_fd) + max_fd = ua_tcp_data_fd_list[0]; + } + + if(ua_tcp_control_fd_list[0] != -1){ + FD_SET(ua_tcp_control_fd_list[0], &readfds); + if(ua_tcp_control_fd_list[0] > max_fd) + max_fd = ua_tcp_control_fd_list[0]; + } + + if(ua_tcp_control_server_listen_fd != -1){ + FD_SET(ua_tcp_control_server_listen_fd, &readfds); + if(ua_tcp_control_server_listen_fd > max_fd) + max_fd = ua_tcp_control_server_listen_fd; + } + + if(ua_tcp_data_server_listen_fd != -1){ + FD_SET(ua_tcp_data_server_listen_fd, &readfds); + if(ua_tcp_data_server_listen_fd > max_fd) + max_fd = ua_tcp_data_server_listen_fd; + } + + tv.tv_sec = 1; + tv.tv_usec = 0; + + ret = select(max_fd + 1, &readfds, NULL, NULL, &tv); + + if(ua_debug_print_en){ + ua_printf(UA_INFO, "uart adapter test select ret = %x",ret); + } + if(ret > 0){ + if(ua_tcp_data_fd_list[0] != -1 && FD_ISSET(ua_tcp_data_fd_list[0], &readfds)){ + uartadapter_tcp_data_fd_handler(tcp_rxbuf); + } + + if(ua_tcp_control_fd_list[0] != -1 && FD_ISSET(ua_tcp_control_fd_list[0], &readfds)){ + uartadapter_tcp_control_fd_handler(); + } + + if(ua_tcp_data_server_listen_fd != -1 && FD_ISSET(ua_tcp_data_server_listen_fd, &readfds)){ + uartadapter_tcp_data_listen_fd_handler(ua_tcp_data_fd_list[0]); + } + + if(ua_tcp_control_server_listen_fd != -1 && FD_ISSET(ua_tcp_control_server_listen_fd, &readfds)){ + uartadapter_tcp_control_listen_fd_handler(ua_tcp_control_fd_list[0]); + } + } + } + + //vTaskDelete(NULL); +} + + +#define _________WIFI__RELATED________________________ + +int uartadapter_connect_wifi(rtw_network_info_t *p_wifi, uint32_t channel, uint8_t pscan_config) +{ + int retry = 3; + rtw_wifi_setting_t setting; + int ret; + while (1) { + if(wifi_set_pscan_chan((uint8_t *)&channel, &pscan_config, 1) < 0){ + printf("\n\rERROR: wifi set partial scan channel fail"); + ret = SC_TARGET_CHANNEL_SCAN_FAIL; + return ret; + } + + ret = wifi_connect((char*)p_wifi->ssid.val, + p_wifi->security_type, + (char*)p_wifi->password, + p_wifi->ssid.len, + p_wifi->password_len, + p_wifi->key_id, + NULL); + + if (ret == RTW_SUCCESS) { + ret = LwIP_DHCP(0, DHCP_START); + wifi_get_setting(WLAN0_NAME, &setting); + wifi_show_setting(WLAN0_NAME, &setting); + if (ret == DHCP_ADDRESS_ASSIGNED) + return SC_SUCCESS; + else + return SC_DHCP_FAIL; + } + + if (retry == 0) { + ret = SC_JOIN_BSS_FAIL; + break; + } + retry --; + } + + return ret; +} + + +static int uartadapter_load_wifi_config() +{ + flash_t flash; + uint8_t *data; + uint32_t channel; + uint8_t pscan_config; + char key_id; + rtw_network_info_t wifi = {0}; + int ret = SC_SUCCESS; + + + data = (uint8_t *)rtw_zmalloc(FAST_RECONNECT_DATA_LEN); + flash_stream_read(&flash, FAST_RECONNECT_DATA, FAST_RECONNECT_DATA_LEN, (uint8_t *)data); + if(*((uint32_t *) data) != ~0x0) + { + ua_printf(UA_INFO, "AP Profile read from FLASH, try to connect"); + memcpy(psk_essid, (uint8_t *)data, NDIS_802_11_LENGTH_SSID + 4); + memcpy(psk_passphrase, (uint8_t *)data + NDIS_802_11_LENGTH_SSID + 4, (IW_PASSPHRASE_MAX_SIZE + 1)); + memcpy(wpa_global_PSK, (uint8_t *)data + NDIS_802_11_LENGTH_SSID + 4 + (IW_PASSPHRASE_MAX_SIZE + 1), A_SHA_DIGEST_LEN * 2); + memcpy(&channel, (uint8_t *)data + NDIS_802_11_LENGTH_SSID + 4 + (IW_PASSPHRASE_MAX_SIZE + 1) + A_SHA_DIGEST_LEN * 2, 4); + sprintf(&key_id,"%d",(channel >> 28)); + channel &= 0xff; + pscan_config = PSCAN_ENABLE | PSCAN_FAST_SURVEY; + //set partial scan for entering to listen beacon quickly + //wifi_set_pscan_chan((uint8_t *)&channel, &pscan_config, 1); + +#ifdef CONFIG_AUTO_RECONNECT + wifi_set_autoreconnect(1); +#endif + //set wifi connect + wifi.ssid.len = (int)strlen((char*)psk_essid); + memcpy(wifi.ssid.val, psk_essid, wifi.ssid.len); + wifi.key_id = key_id; + + //open mode + if(!strlen((char*)psk_passphrase)){ + wifi.security_type = RTW_SECURITY_OPEN; + } + //wep mode + else if( strlen((char*)psk_passphrase) == 5 || strlen((char*)psk_passphrase) == 13){ + wifi.security_type = RTW_SECURITY_WEP_PSK; + wifi.password = (unsigned char *)psk_passphrase; + wifi.password_len = (int)strlen((char const *)psk_passphrase); + } + //WPA/WPA2 + else{ + wifi.security_type = RTW_SECURITY_WPA2_AES_PSK; + wifi.password = (unsigned char *)psk_passphrase; + wifi.password_len = (int)strlen((char const *)psk_passphrase); + } + + ret = uartadapter_connect_wifi(&wifi, channel, pscan_config); + + //print_simple_config_result((enum ua_sc_result)ret); + + if(data) + rtw_mfree(data, FAST_RECONNECT_DATA_LEN); + + if(ret == SC_SUCCESS) + return RTW_SUCCESS; + else + return RTW_ERROR; + }else{ + ua_printf(UA_INFO, "No AP Profile read from FLASH, start simple configure"); + + if(data) + rtw_mfree(data, FAST_RECONNECT_DATA_LEN); + + return RTW_ERROR; + } +} + +int uartadapter_simple_config(char *pin_code){ +#if CONFIG_INCLUDE_SIMPLE_CONFIG + int ret = SC_SUCCESS; + wifi_enter_promisc_mode(); + if(init_test_data(pin_code) == 0){ + filter_add_enable(); + //uartadapter_simple_config_handler(); + ret = simple_config_test(); + //print_simple_config_result(ret); + remove_filter(); + if(ret == SC_SUCCESS) + return RTW_SUCCESS; + else + return RTW_ERROR; + }else{ + return RTW_ERROR; + } +#endif +} + +#define _________MDNS__RELATED________________________ +static void uartadapter_mdns_thread(void *param) +{ + DNSServiceRef dnsServiceRef = NULL; + DNSServiceRef dnsServiceRef2 = NULL; + //TXTRecordRef txtRecord; + //unsigned char txt_buf[100]; // use fixed buffer for text record to prevent malloc/free + //TXTRecordCreate(&txtRecord, sizeof(txt_buf), txt_buf); + //TXTRecordSetValue(&txtRecord, "text1", strlen("text1_content_new"), "text1_content_new"); + + // Delay to wait for IP by DHCP + //vTaskDelay(5000); + struct netif * pnetif = &xnetif[0]; + + ua_printf(UA_DEBUG, "Uart Adapter mDNS Init"); + + if(mDNSResponderInit() == 0) { + ua_printf(UA_INFO, "mDNS Register service"); + char hostname[32] = {0}; //AMEBA_UART-MODE + u32 prefix_len = strlen("AMEBA_"); + sprintf(hostname, "AMEBA_"); + sprintf(hostname+prefix_len, "%02x%02x%02x%02x%02x%02x", + pnetif->hwaddr[0], pnetif->hwaddr[1], pnetif->hwaddr[2], + pnetif->hwaddr[3], pnetif->hwaddr[4], pnetif->hwaddr[5]); + + //TXTRecordCreate(&txtRecord, sizeof(txt_buf), txt_buf); + //TXTRecordSetValue(&txtRecord, "text1", strlen("text1_content"), "text1_content"); + //TXTRecordSetValue(&txtRecord, "text2", strlen("text2_content"), "text2_content"); + dnsServiceRef = mDNSRegisterService(hostname, "_uart_data._tcp", "local", 5001, NULL); + if(dnsServiceRef == NULL) + ua_printf(UA_ERROR, "mdns data service register failed!"); + dnsServiceRef2 = mDNSRegisterService(hostname, "_uart_control._tcp", "local", 6001, NULL); + if(dnsServiceRef2 == NULL) + ua_printf(UA_ERROR, "mdns control service register failed!"); + + }else{ + ua_printf(UA_INFO, "mDNS Init Failed"); + } + + //vTaskDelete(NULL); +} + +#define _________INIT__RELATED________________________ +void uartadapter_auto_connect(void *param) +{ + int ret = 0; + + if(wifi_is_ready_to_transceive(RTW_STA_INTERFACE) == RTW_SUCCESS) { + ua_printf(UA_INFO, "wifi connect successfully!"); + goto START; + }else{ +RETRY: + ret = uartadapter_load_wifi_config(); + if(ret != RTW_SUCCESS){ + ret = uartadapter_simple_config(NULL); + if(ret != RTW_SUCCESS){ + ua_printf(UA_INFO, "Simple configure connect failed, try again!"); + goto RETRY; + } + } + } + +START: + if(!sys_thread_new("tcp data server", uartadapter_tcp_data_server_handler, NULL, 256, UA_UART_THREAD_PRIORITY)) + ua_printf(UA_ERROR, "%s sys_thread_new data server failed\n", __FUNCTION__); + + vTaskDelay(50); + if(!sys_thread_new("tcp control server", uartadapter_tcp_control_server_handler, NULL, 256, UA_UART_THREAD_PRIORITY)) + ua_printf(UA_ERROR, "%s sys_thread_new control server failed\n", __FUNCTION__); + + vTaskDelay(50); + + if(!sys_thread_new("tcp control server", uartadapter_tcp_select, NULL, 1024, UA_UART_THREAD_PRIORITY)) + ua_printf(UA_ERROR, "%s sys_thread_new tcp select failed\n", __FUNCTION__); + + + vTaskDelay(50); + + //if(!sys_thread_new("MDNS thread", uartadapter_mdns_thread, NULL, 768, 6)) + // ua_printf(UA_ERROR, "%s sys_thread_new serial failed\n", __FUNCTION__); + + uartadapter_mdns_thread(NULL); + + vTaskDelay(50); + + ua_printf(UA_INFO, "[MEM] After auao connect, available heap %d", xPortGetFreeHeapSize()); + + /* Kill init thread after all init tasks done */ + vTaskDelete(NULL); + //auao_config = NULL; +} + +void uartadapter_main(void *param) +{ + int ret = 0; + unsigned int tick_start; + unsigned int tick_current; + int pin_high = 0; + int address = FAST_RECONNECT_DATA; + + while(xSemaphoreTake(ua_main_sema, portMAX_DELAY) == pdTRUE){ + if(ua_gpio_irq_happen){ + pin_high = 0; + tick_start = xTaskGetTickCount(); + tick_current = xTaskGetTickCount(); + while(tick_current - tick_start < 3000){ + if (gpio_read(&gpio_led)){ + pin_high = 1; + break; + }else{ + tick_current = xTaskGetTickCount(); + } + vTaskDelay(10); + } + + ua_gpio_irq_happen = 0; + if(!pin_high){ + ret = uartadapter_flasherase(address, sizeof(rtw_wifi_config_t)); + if(ret < 0){ + ua_printf(UA_ERROR, "flash erase error!"); + } + + uartadapter_systemreload(); + } + + } + + + + } + /* Kill init thread after all init tasks done */ + vTaskDelete(NULL); + //auao_config = NULL; +} + + +int uartadapter_init() +{ + int ret = 0; + + ua_printf(UA_INFO, "==============>%s()\n", __func__); + + uartadapter_uart_init(); + uartadapter_gpio_init(); + + ua_uart_action_sema = xSemaphoreCreateCounting(300, 0); + + vSemaphoreCreateBinary(ua_tcp_sema); + + vSemaphoreCreateBinary(ua_work_thread_sema); + xSemaphoreTake(ua_work_thread_sema, 1/portTICK_RATE_MS); + + vSemaphoreCreateBinary(ua_main_sema); + xSemaphoreTake(ua_main_sema, 1/portTICK_RATE_MS); + + + ret= sys_mbox_new(&mbox_for_uart_tx, sizeof(struct ua_tcp_rx_buffer)); + if(ret != ERR_OK) + { + ua_printf(UA_ERROR, "mbox_for_uart_tx create failed"); + goto Exit; + } + + //wifi_reg_event_handler(WIFI_EVENT_DISCONNECT, _uartadapter_event_handler, NULL); + + /*create uart_thread to handle send&recv data*/ + if(xTaskCreate(uartadapter_uart_rx_handle, ((const char*)"uart_rx"), 768, NULL, UA_UART_THREAD_PRIORITY, NULL) != pdPASS) + ua_printf(UA_ERROR, "%s xTaskCreate(uart_rx) failed", __FUNCTION__); + + vTaskDelay(50); + + /*create uart_thread to handle send&recv data*/ + if(xTaskCreate(uartadapter_uart_tx_handle, ((const char*)"uart_tx"), 512, NULL, UA_UART_THREAD_PRIORITY, NULL) != pdPASS) + ua_printf(UA_ERROR, "%s xTaskCreate(uart_tx) failed", __FUNCTION__); + + vTaskDelay(50); + + if(xTaskCreate(uartadapter_auto_connect, ((const char*)"auto connnect"), 1024, NULL, UA_UART_THREAD_PRIORITY, NULL) != pdPASS) + ua_printf(UA_ERROR, "%s xTaskCreate(auao connnect) failed", __FUNCTION__); + + if(xTaskCreate(uartadapter_main, ((const char*)"uart main"), 256, NULL, UA_UART_THREAD_PRIORITY, NULL) != pdPASS) + ua_printf(UA_ERROR, "%s xTaskCreate(auao connnect) failed", __FUNCTION__); + + + return 0; +Exit: + ua_printf(UA_ERROR, "%s(): Initialization failed!", __func__); + return ret; +} + +void example_uart_adapter_init() +{ + // Call back from wlan driver after wlan init done + p_wlan_uart_adapter_callback = uartadapter_init; +} + +#define _________CMD__RELATED________________________ +void uartadapter_print_irq_rx_count() +{ + ua_printf(UA_INFO, "ua_tick_last_update: %d!\n", ua_tick_last_update); + ua_printf(UA_INFO, "ua_tick_current: %d!\n", ua_tick_current); + ua_printf(UA_INFO, "ua current tick: %d!\n", xTaskGetTickCount()); + ua_printf(UA_INFO, "ua_pwrite: %d!\n", ua_pwrite); + ua_printf(UA_INFO, "ua_pread: %d!\n", ua_pread); + ua_printf(UA_INFO, "ua_overlap: %d!\n", ua_overlap); + ua_printf(UA_INFO, "ua_rcv_ch: %d!\n", ua_rcv_ch); + ua_printf(UA_INFO, "ua_uart_recv_bytes: %d!\n", ua_uart_recv_bytes); + ua_printf(UA_INFO, "ua_rcv_ch: %d!\n", ua_rcv_ch); + ua_printf(UA_INFO, "irq_rx_cnt: %d!\n", irq_rx_cnt); + ua_printf(UA_INFO, "irq_tx_cnt: %d!\n", irq_tx_cnt); + ua_printf(UA_INFO, "irq_miss_cnt: %d!\n", irq_miss_cnt); + ua_printf(UA_INFO, "tcp_tx_cnt: %d!\n", tcp_tx_cnt); + ua_printf(UA_INFO, "tcp_send_flag: %d!\n", ua_tcp_send_flag); + ua_printf(UA_INFO, "ua_tcp_data_fd_list: %d!\n", ua_tcp_data_fd_list[0]); + ua_printf(UA_INFO, "ua_tcp_control_fd_list: %d!\n", ua_tcp_control_fd_list[0]); + ua_printf(UA_INFO, "ua_tcp_data_server_listen_fd: %d!\n", ua_tcp_data_server_listen_fd); + ua_printf(UA_INFO, "ua_tcp_control_server_listen_fd: %d!\n", ua_tcp_control_server_listen_fd); + +} + +void uartadapter_reset_irq_rx_count() +{ + irq_rx_cnt = 0; + irq_tx_cnt = 0; + tcp_tx_cnt = 0; + irq_miss_cnt = 0; +} + +void uartadapter_set_debug_print(bool enable) +{ + ua_debug_print_en = enable; +} + +void cmd_uart_adapter(int argc, char **argv) +{ + if(argc < 2) { + printf("\n\r inpua error\n"); + return; + } + + //printf("\n\r haier_test: argv[1]=%s\n", argv[1]); + + if(strcmp(argv[1], "help") == 0){ + printf("\r\nUART THROUGH COMMAND LIST:"); + printf("\r\n=============================="); + printf("\r\n\tuart_baud"); + printf("\r\n"); + }else if(strcmp(argv[1], "irq_rx_get") == 0){ + uartadapter_print_irq_rx_count(); + }else if(strcmp(argv[1], "debug_print_en") == 0){ + uartadapter_set_debug_print(TRUE); + }else if(strcmp(argv[1], "debug_print_dis") == 0){ + uartadapter_set_debug_print(FALSE); + }else if(strcmp(argv[1], "irq_rx_reset") == 0){ + uartadapter_reset_irq_rx_count(); + }else if(strcmp(argv[1], "tcp") == 0){ + if(strcmp(argv[2], "-c") == 0 || strcmp(argv[2], "c") == 0){ + strncpy(ua_tcp_server_ip, argv[3], (strlen(argv[3])>16)?16:strlen(argv[3])); + if(!sys_thread_new("tcp dclient", uartadapter_tcp_data_client_handler, NULL, 768, UA_UART_THREAD_PRIORITY)) + printf("%s sys_thread_new serial failed\n", __FUNCTION__); + }else if(strcmp(argv[2], "-s") == 0 || strcmp(argv[2], "s") == 0){ + if(!sys_thread_new("tcp dserver", uartadapter_tcp_data_server_handler, NULL, 768, UA_UART_THREAD_PRIORITY)) + printf("%s sys_thread_new serial failed\n", __FUNCTION__); + } + }else if(strcmp(argv[1], "uart_baud") == 0){ + uartadapter_uart_baud(atoi(argv[2])); + }else if(strcmp(argv[1], "uart_para") == 0){ + uartadapter_uart_para(atoi(argv[2]), atoi(argv[3]), atoi(argv[4])); + }else{ + printf("\n\rCan not find the inpua commond!"); + } +} + diff --git a/component/common/application/uart_adapter/uart_adapter.h b/component/common/application/uart_adapter/uart_adapter.h new file mode 100644 index 0000000..80a3e24 --- /dev/null +++ b/component/common/application/uart_adapter/uart_adapter.h @@ -0,0 +1,166 @@ +#include +#include "gpio_api.h" // mbed +#include "gpio_irq_api.h" // mbed +/****************************************************** + * Macros + ******************************************************/ +#define UA_ERROR 0 +#define UA_WARNING 1 +#define UA_INFO 2 +#define UA_DEBUG 3 +#define UA_NONE 0xFF +#define UA_DEBUG_LEVEL UA_INFO + +#define UA_UART_THREAD_PRIORITY 5 +#define UA_UART_THREAD_STACKSIZE 512 + +#if (UA_DEBUG_LEVEL== UA_NONE) +#define ua_printf(level, fmt, arg...) +#else +#define ua_printf(level, fmt, arg...) \ +do {\ + if (level <= UA_DEBUG_LEVEL) {\ + if (level <= UA_ERROR) {\ + printf("\r\nERROR: " fmt, ##arg);\ + } \ + else {\ + printf("\r\n"fmt, ##arg);\ + } \ + }\ +}while(0) +#endif + +/****************************************************** + * Constants + ******************************************************/ +typedef enum +{ + UART_CTRL_MODE_SET_REQ = 0, + UART_CTRL_MODE_SET_RSP = 1, + UART_CTRL_MODE_GET_REQ = 2, + UART_CTRL_MODE_GET_RSP = 3, +}ua_ctrl_mode_t; + +typedef enum +{ + UART_CTRL_TYPE_BAUD_RATE = 0x01, + UART_CTRL_TYPE_WORD_LEN = 0x02, + UART_CTRL_TYPE_PARITY = 0x04, + UART_CTRL_TYPE_STOP_BIT = 0x08, + UART_CTRL_TYPE_FLOW_CTRL = 0x10, +}ua_ctrl_type_t; + +/****************************************************** + * Structures + ******************************************************/ +typedef long time_t; + +typedef struct _uartadapter_timeval_st{ + long tv_sec; //Ãë + long tv_hmsec; //°ÙºÁÃë +}UARTTHROUGH_TIMEVAL_st; + +//»ñÈ¡ÍøÂçDHCP²ÎÊýʱ´æ´¢·µ»ØµÄIP£¬MAC,GW£¬MASK£¬DNSµÈ +typedef struct _ua_net_para { + char dhcp; + char ip[16]; // such as string "192.168.1.1" + char gate[16]; + char mask[16]; + char dns[16]; + char mac[16]; // such as string "7E0000001111" + char broadcastip[16]; +} ua_net_para_st; + +//softAPģʽʱ´æ´¢ËÑË÷µ½µÄ APÁбíÐÅÏ¢ +typedef struct _ua_ApList_str +{ + char ssid[32]; + char ApPower; // min:0, max:100 + char channel; + char encryption; +}ua_ApList_str; + +//softAPģʽʱ´æ´¢ËÑË÷µ½µÄ APÁбíÐÅÏ¢ +typedef struct _ua_UwtPara_str +{ + char ApNum; //AP number + ua_ApList_str * ApList; +} ua_UwtPara_str; + + +//»ñÈ¡UARTÅäÖÃÐÅϢʱ£¬´æ´¢»ñµÃµÄ´®¿ÚÅäÖÃÐÅÏ¢ +typedef struct _ua_uart_get_str +{ + int BaudRate; //The baud rate + char number; //The number of data bits + char parity; //The parity(0: none, 1:odd, 2:evn, default:0) + char StopBits; //The number of stop bits + char FlowControl; //support flow control is 1 +}ua_uart_get_str; +//ÅäÖÃUART²ÎÊýʱ£¬´æ´¢Ïà¹ØµÄÅäÖÃÐÅÏ¢ +typedef struct _ua_uart_set_str +{ + char UartName[8]; // the name of uart + int BaudRate; //The baud rate + char number; //The number of data bits + char parity; //The parity(default NONE) + char StopBits; //The number of stop bits + char FlowControl; //support flow control is 1 +}ua_uart_set_str; + + + +//Æô¶¯wifiÁ¬½Óʱ´æ´¢WIFIµÄÅäÖÃÐÅÏ¢ +typedef struct _ua_network_InitTypeDef_st +{ + char wifi_mode; // SoftAp(0)station(1) + char wifi_ssid[32]; + char wifi_key[32]; + char local_ip_addr[16]; + char net_mask[16]; + char gateway_ip_addr[16]; + char dnsServer_ip_addr[16]; + char dhcpMode; // disable(0), client mode(1), server mode(2) + char address_pool_start[16]; + char address_pool_end[16]; + int wifi_retry_interval;//sta reconnect interval, ms + char channel; + char encryption; +} ua_network_InitTypeDef_st; + +#pragma pack(1) +struct ua_ieee80211_frame +{ + unsigned char i_fc[2]; + unsigned char i_dur[2]; + unsigned char i_addr1[6]; + unsigned char i_addr2[6]; + unsigned char i_addr3[6]; + unsigned char i_seq[2]; +}; +#pragma pack() + +//extern void uartadapter_netcallback(ua_net_para_st *pnet); +//extern void uartadapter_wifistatushandler(int status); +extern int uartadapter_init(); +//extern void uartadapter_deinit(); +//extern void uartadapter_wifipoweron(void); +//extern void uartadapter_wifipoweroff(void); + +//extern int uartadapter_startnetwork(ua_network_InitTypeDef_st* pNetworkInitPara); +//extern void uartadapter_wifidisconnect (void); +extern int uartadapter_getnetpara(ua_net_para_st * pnetpara); + +//extern int uartadapter_sethostname(char* name); + +extern int uartadapter_readuart(int fd, void *read_buf, size_t size); +void uartadapter_tcp_data_fd_handler(); +extern void uartadapter_tcpsend(char *buffer, int size, u8 isctrl); +//extern void uartadapter_test(void *param); +//extern void uartadapter_tcp_control_server_handler(void *param); +//extern void uartadapter_tcp_data_server_handler(void *param); +//extern void uartadapter_gpio_irq (uint32_t id, gpio_irq_event event); +void example_uart_adapter_init(); +extern void cmd_uart_adapter(int argc, char **argv); +//#define cmd_uart_adapter cmd_ua + diff --git a/component/common/drivers/wlan/realtek/include/autoconf.h b/component/common/drivers/wlan/realtek/include/autoconf.h new file mode 100644 index 0000000..d88f594 --- /dev/null +++ b/component/common/drivers/wlan/realtek/include/autoconf.h @@ -0,0 +1,347 @@ +#ifndef WLANCONFIG_H +#define WLANCONFIG_H + +/* + * Include user defined options first. Anything not defined in these files + * will be set to standard values. Override anything you dont like! + */ + #if defined(CONFIG_PLATFORM_8195A) || defined(CONFIG_PLATFORM_8711B) +#include "platform_opts.h" +#endif + +#if defined(CONFIG_PLATFORM_8195A) || defined(CONFIG_PLATFORM_8711B) +#define CONFIG_PLATFORM_AMEBA_X +#endif + +#if !defined(CONFIG_PLATFORM_AMEBA_X) +#define PLATFORM_FREERTOS 1 +#define CONFIG_GSPI_HCI +#else +#define CONFIG_LX_HCI +#endif + +#ifndef CONFIG_INIC_EN +#define CONFIG_INIC_EN 0 //For iNIC project +#if CONFIG_INIC_EN +#define CONFIG_LWIP_LAYER 0 +#endif +#endif + +#define CONFIG_LITTLE_ENDIAN +#define CONFIG_80211N_HT +//#define CONFIG_RECV_REORDERING_CTRL +#define RTW_NOTCH_FILTER 0 +#define CONFIG_EMBEDDED_FWIMG 1 +#define CONFIG_PHY_SETTING_WITH_ODM +#if !defined(CONFIG_PLATFORM_AMEBA_X) +#define CONFIG_ODM_REFRESH_RAMASK +#define HAL_MAC_ENABLE 1 +#define HAL_BB_ENABLE 1 +#define HAL_RF_ENABLE 1 +#endif +#if defined(CONFIG_PLATFORM_AMEBA_X) +/* Patch when dynamic mechanism is not ready */ +//#define CONFIG_DM_PATCH +#endif + +//#define CONFIG_DEBUG +//#define CONFIG_DEBUG_RTL871X +#if defined(CONFIG_PLATFORM_AMEBA_X) + #define CONFIG_MEM_MONITOR MEM_MONITOR_SIMPLE + #define WLAN_INTF_DBG 0 + #define CONFIG_DEBUG_DYNAMIC + //#define DBG_TX 1 + //#define DBG_XMIT_BUF 1 + //#define DBG_XMIT_BUF_EXT 1 + #define DBG_TX_DROP_FRAME + /* For DM debug*/ + #define DBG_PWR_TRACKING 0 + #define DBG_PWR_INDEX 0 + #define DBG_DM_RA 0 + #define DBG_DM_DIG 0 +#else + #define CONFIG_MEM_MONITOR MEM_MONITOR_LEAK + //#define CONFIG_TRACE_SKB + //#define WLAN_INTF_DBG +#endif // CONFIG_PLATFORM_AMEBA_X + +//#define CONFIG_DONT_CARE_TP +//#define CONFIG_MEMORY_ACCESS_ALIGNED +#define CONFIG_POWER_SAVING +#ifdef CONFIG_POWER_SAVING +#define CONFIG_LPS +#define CONFIG_IPS +//#define CONFIG_LPS_LCLK +#define CONFIG_WAIT_PS_ACK +#endif + +#if defined(CONFIG_PLATFORM_AMEBA_X) + #if !defined(CONFIG_PLATFORM_8711B) + #define CONFIG_USE_TCM_HEAP 1 /* USE TCM HEAP */ + #endif + #define CONFIG_RECV_TASKLET_THREAD + #define CONFIG_XMIT_TASKLET_THREAD +#else + #define CONFIG_XMIT_THREAD_MODE +#endif // CONFIG_PLATFORM_AMEBA_X +//#define CONFIG_RECV_THREAD_MODE /* Wlan IRQ Polling Mode*/ +//#define CONFIG_ISR_THREAD_MODE_POLLING /* Wlan IRQ Polling Mode*/ + +//1 Chris +#ifndef CONFIG_SDIO_HCI +#define CONFIG_ISR_THREAD_MODE_INTERRUPT /* Wlan IRQ Interrupt Mode*/ +#endif + +#if defined(CONFIG_ISR_THREAD_MODE_POLLING) && defined(CONFIG_ISR_THREAD_MODE_INTERRUPT) +#error "CONFIG_ISR_THREAD_MODE_POLLING and CONFIG_ISR_THREAD_MODE_INTERRUPT are mutually exclusive. " +#endif + +#if defined(CONFIG_PLATFORM_AMEBA_X) +/* CRC DMEM optimized mode consume 1k less SRM memory consumption */ +#define CRC_IMPLEMENTATION_MODE CRC_IMPLEMENTATION_DMEM_OPTIMIZED +#endif + +/* AES DMEM optimized mode comsume 10k less memory compare to + IMEM optimized mode AES_IMPLEMENTATION_IMEM_OPTIMIZED */ +#define AES_IMPLEMENTATION_MODE AES_IMPLEMENTATION_DMEM_OPTIMIZED + +#define USE_SKB_AS_XMITBUF 1 +#if defined(CONFIG_PLATFORM_AMEBA_X) +#define USE_XMIT_EXTBUFF 1 +#else +#define USE_XMIT_EXTBUFF 0 +#endif +#define USE_MUTEX_FOR_SPINLOCK 1 +#define SUPPORT_5G_CHANNEL 0 +#define SUPPORT_FAKE_EFUSE 0 + +#define CONFIG_AUTO_RECONNECT 1 +#define ENABLE_HWPDN_PIN +#define SUPPORT_SCAN_BUF 1 +#if !defined(CONFIG_PLATFORM_AMEBA_X) +#define BE_I_CUT 1 +#endif + +/* For WPA2 */ +#define CONFIG_INCLUDE_WPA_PSK +#ifdef CONFIG_INCLUDE_WPA_PSK +#define CONFIG_MULTIPLE_WPA_STA +//#define CONFIG_WPA2_PREAUTH +#define PSK_SUPPORT_TKIP 1 +#endif + +/* For promiscuous mode */ +#define CONFIG_PROMISC + +#define PROMISC_DENY_PAIRWISE 0 + +/* For Simple Link */ +#ifndef CONFIG_INCLUDE_SIMPLE_CONFIG +//#define CONFIG_INCLUDE_SIMPLE_CONFIG 1 +#endif + +// for probe request with custom vendor specific IE +#define CONFIG_CUSTOM_IE + +#if !defined(CONFIG_PLATFORM_AMEBA_X) +/* For multicast */ +#define CONFIG_MULTICAST +#endif + +/* For STA+AP Concurrent MODE */ +#if !defined(CONFIG_PLATFORM_8711B) +#define CONFIG_CONCURRENT_MODE +#endif +#ifdef CONFIG_CONCURRENT_MODE +#if defined(CONFIG_PLATFORM_8195A) +#define CONFIG_RUNTIME_PORT_SWITCH +#endif +#define NET_IF_NUM 2 +#else +#define NET_IF_NUM 1 +#endif + + +/* For WPS and P2P */ +#ifndef CONFIG_WPS +#define CONFIG_WPS +#if defined(CONFIG_WPS) +#define CONFIG_ENABLE_WPS 1 +#endif +#if 0//def CONFIG_WPS +#define CONFIG_WPS_AP +#define CONFIG_P2P_NEW +#if (!defined(SUPPORT_SCAN_BUF)||!defined(CONFIG_WPS_AP)) && defined(CONFIG_P2P_NEW) +#error "If CONFIG_P2P_NEW, need to SUPPORT_SCAN_BUF" +#endif +#endif +#endif + +#if !defined(CONFIG_PLATFORM_AMEBA_X) +#define CONFIG_NEW_SIGNAL_STAT_PROCESS +#endif + +/* For AP_MODE */ +#define CONFIG_AP_MODE +#if defined(CONFIG_PLATFORM_AMEBA_X) +#define AP_STA_NUM 3 //2014/10/27 modify to 3 +#define USE_DEDICATED_BCN_TX 0 +#if USE_DEDICATED_BCN_TX +#error "WLAN driver for Ameba should not enable USE_DEDICATED_BCN_TX" +#endif +#else +extern unsigned int g_ap_sta_num; +#define AP_STA_NUM g_ap_sta_num +#endif +#ifdef CONFIG_AP_MODE + #define CONFIG_NATIVEAP_MLME +#if defined(CONFIG_PLATFORM_AMEBA_X) + #define CONFIG_INTERRUPT_BASED_TXBCN +#endif + #ifdef CONFIG_INTERRUPT_BASED_TXBCN + //#define CONFIG_INTERRUPT_BASED_TXBCN_EARLY_INT + #define CONFIG_INTERRUPT_BASED_TXBCN_BCN_OK_ERR + #endif +// #define CONFIG_GK_REKEY +#if !defined(CONFIG_PLATFORM_AMEBA_X) + #define USE_DEDICATED_BCN_TX 1 +#endif +#else +#if !defined(CONFIG_PLATFORM_AMEBA_X) + #define USE_DEDICATED_BCN_TX 0 +#endif +#endif + +#if defined(CONFIG_AP_MODE) && defined(CONFIG_GK_REKEY) && !defined(CONFIG_MULTIPLE_WPA_STA) +#error "If CONFIG_GK_REKEY when CONFIG_AP_MODE, need to CONFIG_MULTIPLE_WPA_STA" +#endif + +#if !defined(CONFIG_PLATFORM_AMEBA_X) +#if !defined(CONFIG_AP_MODE) && defined(CONFIG_CONCURRENT_MODE) +#error "If CONFIG_CONCURRENT_MODEE, need to CONFIG_AP_MODE" +#endif +#endif + +/* For efuse or flash config */ +#if defined(CONFIG_PLATFORM_AMEBA_X) + #define CONFIG_RW_PHYSICAL_EFUSE 1 + #define CONFIG_HIDE_PROTECT_EFUSE 1 + #define CONFIG_ADAPTOR_INFO_CACHING_FLASH 1 + #define CHECK_FLASH_VALID_MASK 1 + /* For K-free */ + #if !defined(CONFIG_PLATFORM_8711B) + #define CONFIG_RF_GAIN_OFFSET + #endif +#endif // CONFIG_PLATFORM_AMEBA_X + +/* For MP_MODE */ +//#define CONFIG_MP_INCLUDED +#ifdef CONFIG_MP_INCLUDED + #define MP_DRIVER 1 + #define CONFIG_MP_IWPRIV_SUPPORT +// #define HAL_EFUSE_MEMORY + #if defined(CONFIG_PLATFORM_AMEBA_X) + #define MP_REG_TEST + #define MP_DISABLE_SDR + #endif +#else + #define MP_DRIVER 0 + #if defined(CONFIG_PLATFORM_AMEBA_X) + //Control wifi mcu function + #define CONFIG_LITTLE_WIFI_MCU_FUNCTION_THREAD + #define CONFIG_ODM_REFRESH_RAMASK + #endif +#endif // #ifdef CONFIG_MP_INCLUDED + +#if defined(CONFIG_PLATFORM_AMEBA_X) +#if defined(CONFIG_PLATFORM_8195A) +#define CONFIG_RTL8195A +#endif +#if defined(CONFIG_PLATFORM_8711B) +#define CONFIG_RTL8711B +#endif +#else +#define CONFIG_RTL8188E +#endif +#define RTL8192C_SUPPORT 0 +#define RTL8192CE_SUPPORT 0 +#define RTL8192CU_SUPPORT 0 +#define RTL8192D_SUPPORT 0 +#define RTL8192DE_SUPPORT 0 +#define RTL8192DU_SUPPORT 0 +#define RTL8723A_SUPPORT 0 +#define RTL8723AU_SUPPORT 0 +#define RTL8723AS_SUPPORT 0 +#define RTL8192E_SUPPORT 0 +#define RTL8812A_SUPPORT 0 +#define RTL8821A_SUPPORT 0 +#define RTL8723B_SUPPORT 0 +#if defined(CONFIG_PLATFORM_AMEBA_X) +#define RTL8195A_SUPPORT 1 +#define RTL8188E_SUPPORT 0 +#else +#define RTL8188E_SUPPORT 1 +#define RTL8195A_SUPPORT 0 +#endif +#define TEST_CHIP_SUPPORT 0 + +#define RTL8188E_FOR_TEST_CHIP 0 +#define RTL8188E_FPGA_TRUE_PHY_VERIFICATION 0 +#define DBG 0 + +/* For DM support */ +#define RATE_ADAPTIVE_SUPPORT 1 +#if defined(CONFIG_PLATFORM_AMEBA_X) + #define CONFIG_RTW_ADAPTIVITY_EN 0 + #define CONFIG_POWER_TRAINING_WIL 0 // in RA +#else + #define CONFIG_RTW_ADAPTIVITY_EN 1 + #define POWER_BY_RATE_SUPPORT 0 +#endif + +#if defined(CONFIG_PLATFORM_AMEBA_X) +#define RTL8195A_FOR_TEST_CHIP 0 + +//#define CONFIG_WIFI_TEST 1 +//#define CONFIG_MAC_LOOPBACK_DRIVER 1 +//#define CONFIG_WLAN_HAL_TEST 1 +//#define SKB_PRE_ALLOCATE_TX 1 +#define SKB_PRE_ALLOCATE_RX 1 +#define TX_CHECK_DSEC_ALWAYS 1 +#define EXCHANGE_LUBUX_RX_SKB 0 +#define CONFIG_DBG_DISABLE_RDU_INTERRUPT +//#define CONFIG_WLAN_HAL_RX_TASK + +//Enable mac loopback for test mode (Ameba) +//#define ENABLE_MAC_LB_FOR_TEST_MODE // for test mode +#ifdef ENABLE_MAC_LB_FOR_TEST_MODE + #define CONFIG_SUDO_PHY_SETTING + #define INT_HANDLE_IN_ISR 1 + #define CONFIG_LWIP_LAYER 0 + #define CONFIG_WLAN_HAL_TEST + #define CONFIG_WLAN_HAL_RX_TASK + #define CONFIG_MAC_LOOPBACK_DRIVER_RTL8195A 1 + //#define CONFIG_TWO_MAC_TEST_MODE + #define DISABLE_BB_RF 1 +#else + //#define CONFIG_TWO_MAC_DRIVER //for mornal driver; two mac + #ifdef CONFIG_TWO_MAC_DRIVER + #define CONFIG_SUDO_PHY_SETTING + #define DISABLE_BB_RF 1 + #else + #define HAL_MAC_ENABLE 1 + #define HAL_BB_ENABLE 1 + #define HAL_RF_ENABLE 1 + #define DISABLE_BB_RF 0 + #endif + //#define INT_HANDLE_IN_ISR 1 +#endif +#endif // CONFIG_PLATFORM_AMEBA_X + +#ifndef CONFIG_LWIP_LAYER +#define CONFIG_LWIP_LAYER 1 +#endif +#define CONFIG_MAC_ADDRESS 0 +//fast reconnection +//#define CONFIG_FAST_RECONNECTION 1 +#endif //WLANCONFIG_H diff --git a/component/common/drivers/wlan/realtek/include/drv_conf.h b/component/common/drivers/wlan/realtek/include/drv_conf.h new file mode 100644 index 0000000..115bb54 --- /dev/null +++ b/component/common/drivers/wlan/realtek/include/drv_conf.h @@ -0,0 +1,106 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * + ******************************************************************************/ +#ifndef __DRV_CONF_H__ +#define __DRV_CONF_H__ + +#include "autoconf.h" +#if (RTL8195A_SUPPORT==1) +#include "platform_autoconf.h" +#endif + +#if defined (PLATFORM_LINUX) && defined (PLATFORM_WINDOWS) + +#error "Shall be Linux or Windows, but not both!\n" + +#endif + +//Older Android kernel doesn't has CONFIG_ANDROID defined, +//add this to force CONFIG_ANDROID defined +#ifdef CONFIG_PLATFORM_ANDROID +#define CONFIG_ANDROID +#endif + +#ifdef CONFIG_ANDROID +//Some Android build will restart the UI while non-printable ascii is passed +//between java and c/c++ layer (JNI). We force CONFIG_VALIDATE_SSID +//for Android here. If you are sure there is no risk on your system about this, +//mask this macro define to support non-printable ascii ssid. +//#define CONFIG_VALIDATE_SSID +#ifdef CONFIG_PLATFORM_ARM_SUNxI + #ifdef CONFIG_VALIDATE_SSID + #undef CONFIG_VALIDATE_SSID + #endif +#endif + +//Android expect dbm as the rx signal strength unit +#define CONFIG_SIGNAL_DISPLAY_DBM +#endif + +#if defined(CONFIG_HAS_EARLYSUSPEND) && defined (CONFIG_RESUME_IN_WORKQUEUE) + #warning "You have CONFIG_HAS_EARLYSUSPEND enabled in your system, we disable CONFIG_RESUME_IN_WORKQUEUE automatically" + #undef CONFIG_RESUME_IN_WORKQUEUE +#endif + +#if defined(CONFIG_ANDROID_POWER) && defined (CONFIG_RESUME_IN_WORKQUEUE) + #warning "You have CONFIG_ANDROID_POWER enabled in your system, we disable CONFIG_RESUME_IN_WORKQUEUE automatically" + #undef CONFIG_RESUME_IN_WORKQUEUE +#endif + +#ifdef CONFIG_RESUME_IN_WORKQUEUE //this can be removed, because there is no case for this... + #if !defined( CONFIG_WAKELOCK) && !defined(CONFIG_ANDROID_POWER) + #error "enable CONFIG_RESUME_IN_WORKQUEUE without CONFIG_WAKELOCK or CONFIG_ANDROID_POWER will suffer from the danger of wifi's unfunctionality..." + #error "If you still want to enable CONFIG_RESUME_IN_WORKQUEUE in this case, mask this preprossor checking and GOOD LUCK..." + #endif +#endif + +//About USB VENDOR REQ +#if defined(CONFIG_USB_VENDOR_REQ_BUFFER_PREALLOC) && !defined(CONFIG_USB_VENDOR_REQ_MUTEX) + #warning "define CONFIG_USB_VENDOR_REQ_MUTEX for CONFIG_USB_VENDOR_REQ_BUFFER_PREALLOC automatically" + #define CONFIG_USB_VENDOR_REQ_MUTEX +#endif +#if defined(CONFIG_VENDOR_REQ_RETRY) && !defined(CONFIG_USB_VENDOR_REQ_MUTEX) + #warning "define CONFIG_USB_VENDOR_REQ_MUTEX for CONFIG_VENDOR_REQ_RETRY automatically" + #define CONFIG_USB_VENDOR_REQ_MUTEX +#endif + +#ifndef CONFIG_RTW_ADAPTIVITY_EN + #define CONFIG_RTW_ADAPTIVITY_EN 0 +#endif + +#ifndef CONFIG_RTW_ADAPTIVITY_MODE + #define CONFIG_RTW_ADAPTIVITY_MODE 0 +#endif + +#ifndef CONFIG_RTW_ADAPTIVITY_DML + #define CONFIG_RTW_ADAPTIVITY_DML 0 +#endif + +#ifndef CONFIG_RTW_ADAPTIVITY_DC_BACKOFF + #define CONFIG_RTW_ADAPTIVITY_DC_BACKOFF 4 +#endif + +#ifndef CONFIG_RTW_NHM_EN + #define CONFIG_RTW_NHM_EN 0 +#endif + +//#include + +#endif // __DRV_CONF_H__ + diff --git a/component/common/drivers/wlan/realtek/include/wifi_constants.h b/component/common/drivers/wlan/realtek/include/wifi_constants.h new file mode 100644 index 0000000..6469a0f --- /dev/null +++ b/component/common/drivers/wlan/realtek/include/wifi_constants.h @@ -0,0 +1,221 @@ +#ifndef _WIFI_CONSTANTS_H +#define _WIFI_CONSTANTS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define WEP_ENABLED 0x0001 +#define TKIP_ENABLED 0x0002 +#define AES_ENABLED 0x0004 +#define WSEC_SWFLAG 0x0008 + +#define SHARED_ENABLED 0x00008000 +#define WPA_SECURITY 0x00200000 +#define WPA2_SECURITY 0x00400000 +#define WPS_ENABLED 0x10000000 + +#define RTW_MAX_PSK_LEN (64) +#define RTW_MIN_PSK_LEN (8) + +#define MCSSET_LEN 16 + +typedef enum +{ + RTW_SUCCESS = 0, /**< Success */ + RTW_PENDING = 1, /**< Pending */ + RTW_TIMEOUT = 2, /**< Timeout */ + RTW_PARTIAL_RESULTS = 3, /**< Partial results */ + RTW_INVALID_KEY = 4, /**< Invalid key */ + RTW_DOES_NOT_EXIST = 5, /**< Does not exist */ + RTW_NOT_AUTHENTICATED = 6, /**< Not authenticated */ + RTW_NOT_KEYED = 7, /**< Not keyed */ + RTW_IOCTL_FAIL = 8, /**< IOCTL fail */ + RTW_BUFFER_UNAVAILABLE_TEMPORARY = 9, /**< Buffer unavailable temporarily */ + RTW_BUFFER_UNAVAILABLE_PERMANENT = 10, /**< Buffer unavailable permanently */ + RTW_WPS_PBC_OVERLAP = 11, /**< WPS PBC overlap */ + RTW_CONNECTION_LOST = 12, /**< Connection lost */ + + RTW_ERROR = -1, /**< Generic Error */ + RTW_BADARG = -2, /**< Bad Argument */ + RTW_BADOPTION = -3, /**< Bad option */ + RTW_NOTUP = -4, /**< Not up */ + RTW_NOTDOWN = -5, /**< Not down */ + RTW_NOTAP = -6, /**< Not AP */ + RTW_NOTSTA = -7, /**< Not STA */ + RTW_BADKEYIDX = -8, /**< BAD Key Index */ + RTW_RADIOOFF = -9, /**< Radio Off */ + RTW_NOTBANDLOCKED = -10, /**< Not band locked */ + RTW_NOCLK = -11, /**< No Clock */ + RTW_BADRATESET = -12, /**< BAD Rate valueset */ + RTW_BADBAND = -13, /**< BAD Band */ + RTW_BUFTOOSHORT = -14, /**< Buffer too short */ + RTW_BUFTOOLONG = -15, /**< Buffer too long */ + RTW_BUSY = -16, /**< Busy */ + RTW_NOTASSOCIATED = -17, /**< Not Associated */ + RTW_BADSSIDLEN = -18, /**< Bad SSID len */ + RTW_OUTOFRANGECHAN = -19, /**< Out of Range Channel */ + RTW_BADCHAN = -20, /**< Bad Channel */ + RTW_BADADDR = -21, /**< Bad Address */ + RTW_NORESOURCE = -22, /**< Not Enough Resources */ + RTW_UNSUPPORTED = -23, /**< Unsupported */ + RTW_BADLEN = -24, /**< Bad length */ + RTW_NOTREADY = -25, /**< Not Ready */ + RTW_EPERM = -26, /**< Not Permitted */ + RTW_NOMEM = -27, /**< No Memory */ + RTW_ASSOCIATED = -28, /**< Associated */ + RTW_RANGE = -29, /**< Not In Range */ + RTW_NOTFOUND = -30, /**< Not Found */ + RTW_WME_NOT_ENABLED = -31, /**< WME Not Enabled */ + RTW_TSPEC_NOTFOUND = -32, /**< TSPEC Not Found */ + RTW_ACM_NOTSUPPORTED = -33, /**< ACM Not Supported */ + RTW_NOT_WME_ASSOCIATION = -34, /**< Not WME Association */ + RTW_SDIO_ERROR = -35, /**< SDIO Bus Error */ + RTW_WLAN_DOWN = -36, /**< WLAN Not Accessible */ + RTW_BAD_VERSION = -37, /**< Incorrect version */ + RTW_TXFAIL = -38, /**< TX failure */ + RTW_RXFAIL = -39, /**< RX failure */ + RTW_NODEVICE = -40, /**< Device not present */ + RTW_UNFINISHED = -41, /**< To be finished */ + RTW_NONRESIDENT = -42, /**< access to nonresident overlay */ + RTW_DISABLED = -43 /**< Disabled in this build */ +} rtw_result_t; + +typedef enum { + RTW_SECURITY_OPEN = 0, /**< Open security */ + RTW_SECURITY_WEP_PSK = WEP_ENABLED, /**< WEP Security with open authentication */ + RTW_SECURITY_WEP_SHARED = ( WEP_ENABLED | SHARED_ENABLED ), /**< WEP Security with shared authentication */ + RTW_SECURITY_WPA_TKIP_PSK = ( WPA_SECURITY | TKIP_ENABLED ), /**< WPA Security with TKIP */ + RTW_SECURITY_WPA_AES_PSK = ( WPA_SECURITY | AES_ENABLED ), /**< WPA Security with AES */ + RTW_SECURITY_WPA2_AES_PSK = ( WPA2_SECURITY | AES_ENABLED ), /**< WPA2 Security with AES */ + RTW_SECURITY_WPA2_TKIP_PSK = ( WPA2_SECURITY | TKIP_ENABLED ), /**< WPA2 Security with TKIP */ + RTW_SECURITY_WPA2_MIXED_PSK = ( WPA2_SECURITY | AES_ENABLED | TKIP_ENABLED ), /**< WPA2 Security with AES & TKIP */ + + RTW_SECURITY_WPS_OPEN = WPS_ENABLED, /**< WPS with open security */ + RTW_SECURITY_WPS_SECURE = (WPS_ENABLED | AES_ENABLED), /**< WPS with AES security */ + + RTW_SECURITY_UNKNOWN = -1, /**< May be returned by scan function if security is unknown. Do not pass this to the join function! */ + + RTW_SECURITY_FORCE_32_BIT = 0x7fffffff /**< Exists only to force rtw_security_t type to 32 bits */ +} rtw_security_t; + +typedef enum { + RTW_ENCRYPTION_UNKNOWN = 0, + RTW_ENCRYPTION_OPEN = 1, + RTW_ENCRYPTION_WEP40 = 2, + RTW_ENCRYPTION_WPA_TKIP = 3, + RTW_ENCRYPTION_WPA_AES = 4, + RTW_ENCRYPTION_WPA2_TKIP = 5, + RTW_ENCRYPTION_WPA2_AES = 6, + RTW_ENCRYPTION_WPA2_MIXED = 7, + RTW_ENCRYPTION_WEP104 = 9, + RTW_ENCRYPTION_UNDEF = 0xFF, +} rtw_encryption_t; + +typedef enum { + RTW_FALSE = 0, + RTW_TRUE = 1 +} rtw_bool_t; + +typedef enum { + RTW_802_11_BAND_5GHZ = 0, /**< Denotes 5GHz radio band */ + RTW_802_11_BAND_2_4GHZ = 1 /**< Denotes 2.4GHz radio band */ +} rtw_802_11_band_t; + +typedef enum { + RTW_COUNTRY_US = 0, + RTW_COUNTRY_EU, + RTW_COUNTRY_JP, + RTW_COUNTRY_CN +}rtw_country_code_t; + +typedef enum { + RTW_MODE_NONE = 0, + RTW_MODE_STA, + RTW_MODE_AP, + RTW_MODE_STA_AP, + RTW_MODE_PROMISC, + RTW_MODE_P2P +}rtw_mode_t; + +typedef enum { + RTW_SCAN_FULL = 0, + RTW_SCAN_SOCIAL, + RTW_SCAN_ONE +}rtw_scan_mode_t; + +typedef enum { + RTW_LINK_DISCONNECTED = 0, + RTW_LINK_CONNECTED +} rtw_link_status_t; + +typedef enum { + RTW_SCAN_TYPE_ACTIVE = 0x00, /**< Actively scan a network by sending 802.11 probe(s) */ + RTW_SCAN_TYPE_PASSIVE = 0x01, /**< Passively scan a network by listening for beacons from APs */ + RTW_SCAN_TYPE_PROHIBITED_CHANNELS = 0x04 /**< Passively scan on channels not enabled by the country code */ +} rtw_scan_type_t; + +typedef enum { + RTW_BSS_TYPE_INFRASTRUCTURE = 0, /**< Denotes infrastructure network */ + RTW_BSS_TYPE_ADHOC = 1, /**< Denotes an 802.11 ad-hoc IBSS network */ + RTW_BSS_TYPE_ANY = 2, /**< Denotes either infrastructure or ad-hoc network */ + + RTW_BSS_TYPE_UNKNOWN = -1 /**< May be returned by scan function if BSS type is unknown. Do not pass this to the Join function */ +} rtw_bss_type_t; + +typedef enum { + RTW_SCAN_COMMAMD = 0x01 +} rtw_scan_command_t; + +typedef enum{ + COMMAND1 = 0x01 +}rtw_command_type; + +typedef enum { + RTW_WPS_TYPE_DEFAULT = 0x0000, + RTW_WPS_TYPE_USER_SPECIFIED = 0x0001, + RTW_WPS_TYPE_MACHINE_SPECIFIED = 0x0002, + RTW_WPS_TYPE_REKEY = 0x0003, + RTW_WPS_TYPE_PUSHBUTTON = 0x0004, + RTW_WPS_TYPE_REGISTRAR_SPECIFIED = 0x0005, + RTW_WPS_TYPE_NONE = 0x0006 +} rtw_wps_type_t; + +typedef enum { + RTW_NETWORK_B = 1, + RTW_NETWORK_BG = 3, + RTW_NETWORK_BGN = 11 +} rtw_network_mode_t; + +typedef enum { + RTW_STA_INTERFACE = 0, /**< STA or Client Interface */ + RTW_AP_INTERFACE = 1, /**< softAP Interface */ +} rtw_interface_t; + +/** + * Enumeration of packet filter rules + */ +typedef enum { + RTW_POSITIVE_MATCHING = 0, /**< Specifies that a filter should match a given pattern */ + RTW_NEGATIVE_MATCHING = 1 /**< Specifies that a filter should NOT match a given pattern */ +} rtw_packet_filter_rule_e; + +typedef enum { + RTW_PROMISC_DISABLE = 0, /**< disable the promisc */ + RTW_PROMISC_ENABLE = 1, /**< enable the promisc */ + RTW_PROMISC_ENABLE_1 = 2, /**< enable the promisc special for length is used */ + RTW_PROMISC_ENABLE_2 = 3, /**< fetch all packets*/ +} rtw_rcr_level_t; + +typedef enum{ + RTW_NO_ERROR = 0, + RTW_NONE_NETWORK = 1, + RTW_CONNECT_FAIL = 2, + RTW_WRONG_PASSWORD = 3 , + RTW_DHCP_FAIL = 4, +}rtw_connect_error_flag_t; + +#ifdef __cplusplus +} +#endif +#endif /* _WIFI_CONSTANTS_H */ diff --git a/component/common/drivers/wlan/realtek/include/wifi_structures.h b/component/common/drivers/wlan/realtek/include/wifi_structures.h new file mode 100644 index 0000000..079f1b6 --- /dev/null +++ b/component/common/drivers/wlan/realtek/include/wifi_structures.h @@ -0,0 +1,134 @@ +#ifndef _WIFI_STRUCTURES_H +#define _WIFI_STRUCTURES_H + +//#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct rtw_ssid { + unsigned char len; /**< SSID length */ + unsigned char val[33]; /**< SSID name (AP name) */ +} rtw_ssid_t; + +typedef struct rtw_mac { + unsigned char octet[6]; /**< Unique 6-byte MAC address */ +} rtw_mac_t; + +typedef struct rtw_ap_info { + rtw_ssid_t ssid; + rtw_security_t security_type; + unsigned char *password; + int password_len; + int channel; +}rtw_ap_info_t; + +typedef struct rtw_network_info { + rtw_ssid_t ssid; + rtw_mac_t bssid; + rtw_security_t security_type; + unsigned char *password; + int password_len; + int key_id; +}rtw_network_info_t; + +typedef struct rtw_scan_result { + rtw_ssid_t SSID; /**< Service Set Identification (i.e. Name of Access Point) */ + rtw_mac_t BSSID; /**< Basic Service Set Identification (i.e. MAC address of Access Point) */ + signed short signal_strength; /**< Receive Signal Strength Indication in dBm. <-90=Very poor, >-30=Excellent */ + rtw_bss_type_t bss_type; /**< Network type */ + rtw_security_t security; /**< Security type */ + rtw_wps_type_t wps_type; /**< WPS type */ + unsigned char channel; /**< Radio channel that the AP beacon was received on */ + rtw_802_11_band_t band; /**< Radio band */ +} rtw_scan_result_t; + +typedef struct rtw_scan_handler_result { + rtw_scan_result_t ap_details; + rtw_bool_t scan_complete; + void* user_data; + +} rtw_scan_handler_result_t; + +typedef struct rtw_wifi_setting { + rtw_mode_t mode; + unsigned char ssid[33]; + unsigned char channel; + rtw_security_t security_type; + unsigned char password[65]; + unsigned char key_idx; +}rtw_wifi_setting_t; + +typedef struct rtw_wifi_config { + unsigned int boot_mode; + unsigned char ssid[32]; + unsigned char ssid_len; + unsigned char security_type; + unsigned char password[65]; + unsigned char password_len; + unsigned char channel; +} rtw_wifi_config_t; + +typedef struct +{ + unsigned int count; /**< Number of MAC addresses in the list */ + rtw_mac_t mac_list[1]; /**< Variable length array of MAC addresses */ +} rtw_maclist_t; + +typedef struct { + unsigned int version; /* version field */ + unsigned int length; /* byte length of data in this record, */ + /* starting at version and including IEs */ + rtw_mac_t BSSID; + unsigned short beacon_period; /* units are Kusec */ + unsigned short capability; /* Capability information */ + unsigned char SSID_len; + unsigned char SSID[32]; + unsigned char channel; +// struct { +// uint32_t count; /* # rates in this set */ +// uint8_t rates[16]; /* rates in 500kbps units w/hi bit set if basic */ +// } rateset; /* supported rates */ +// rtw_chanspec_t chanspec; /* chanspec for bss */ + unsigned short atim_window; /* units are Kusec */ + unsigned char dtim_period; /* DTIM period */ + signed short RSSI; /* receive signal strength (in dBm) */ + + unsigned char n_cap; /* BSS is 802.11N Capable */ + unsigned int nbss_cap; /* 802.11N BSS Capabilities (based on HT_CAP_*) */ + unsigned char basic_mcs[MCSSET_LEN]; /* 802.11N BSS required MCS set */ + + unsigned short ie_offset; /* offset at which IEs start, from beginning */ + unsigned int ie_length; /* byte length of Information Elements */ +} rtw_bss_info_t; + +typedef struct { + unsigned short offset; /**< Offset in bytes to start filtering (referenced to the start of the ethernet packet) */ + unsigned short mask_size; /**< Size of the mask in bytes */ + unsigned char* mask; /**< Pattern mask bytes to be ANDed with the pattern eg. "\xff00" (must be in network byte order) */ + unsigned char* pattern; /**< Pattern bytes used to filter eg. "\x0800" (must be in network byte order) */ +} rtw_packet_filter_pattern_t; + +typedef struct ieee80211_frame_info{ + unsigned short i_fc; + unsigned short i_dur; + unsigned char i_addr1[6]; + unsigned char i_addr2[6]; + unsigned char i_addr3[6]; + unsigned short i_seq; + unsigned char bssid[6]; + unsigned char encrypt; +}ieee80211_frame_info_t; + +typedef struct { + char filter_id; + rtw_packet_filter_pattern_t patt; + rtw_packet_filter_rule_e rule; + unsigned char enable; +}rtw_packet_filter_info_t; +#ifdef __cplusplus +} +#endif + +#endif /* _WIFI_STRUCTURES_H */ diff --git a/component/common/drivers/wlan/realtek/src/osdep/freertos/freertos_service.h b/component/common/drivers/wlan/realtek/src/osdep/freertos/freertos_service.h new file mode 100644 index 0000000..be7b54f --- /dev/null +++ b/component/common/drivers/wlan/realtek/src/osdep/freertos/freertos_service.h @@ -0,0 +1,285 @@ +#ifndef _FREERTOS_SERVICE_H_ +#define _FREERTOS_SERVICE_H_ + +//----- ------------------------------------------------------------------ +// Include Files +//----- ------------------------------------------------------------------ +#include "wireless.h" + +// -------------------------------------------- +// Platform dependent include file +// -------------------------------------------- +#if defined(CONFIG_PLATFORM_8195A) || defined(CONFIG_PLATFORM_8711B) +#include "platform/platform_stdlib.h" +extern VOID RtlUdelayOS(u32 us); +#else +// other MCU may use standard library +#include +#endif + + +#if (defined CONFIG_GSPI_HCI || defined CONFIG_SDIO_HCI) || defined(CONFIG_LX_HCI) +/* For SPI interface transfer and us delay implementation */ +#if !defined(CONFIG_PLATFORM_8195A) && !defined(CONFIG_PLATFORM_8711B) +#include +#endif +#endif + + +// -------------------------------------------- +// Platform dependent type define +// -------------------------------------------- +#if !defined(CONFIG_PLATFORM_8195A) && !defined(CONFIG_PLATFORM_8711B) +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef signed char s8; +typedef signed short s16; +typedef signed int s32; +typedef signed long long s64; +typedef unsigned long long u64; +typedef unsigned int uint; +typedef signed int sint; + +#ifndef bool +typedef int bool; +#define true 1 +#define false 0 +#endif + +#define IN +#define OUT +#define VOID void +#define NDIS_OID uint +#define NDIS_STATUS uint +#ifndef PVOID +typedef void * PVOID; +#endif + +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef __kernel_size_t SIZE_T; +typedef __kernel_ssize_t SSIZE_T; + +#endif //CONFIG_PLATFORM_8195A + +#define FIELD_OFFSET(s,field) ((SSIZE_T)&((s*)(0))->field) + +// os types +typedef char osdepCHAR; +typedef float osdepFLOAT; +typedef double osdepDOUBLE; +typedef long osdepLONG; +typedef short osdepSHORT; +typedef unsigned long osdepSTACK_TYPE; +typedef long osdepBASE_TYPE; +typedef unsigned long osdepTickType; + +typedef void* _timerHandle; +typedef void* _sema; +typedef void* _mutex; +typedef void* _lock; +typedef void* _queueHandle; +typedef void* _xqueue; +typedef struct timer_list _timer; + +typedef struct sk_buff _pkt; +typedef unsigned char _buffer; + +struct list_head { + struct list_head *next, *prev; +}; + +struct __queue { + struct list_head queue; + _lock lock; +}; + +typedef struct __queue _queue; +typedef struct list_head _list; +typedef unsigned long _irqL; + +typedef void* _thread_hdl_; +typedef void thread_return; +typedef void* thread_context; + +#define ATOMIC_T atomic_t +#define HZ configTICK_RATE_HZ + +#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) +/* emulate a modern version */ +#define LINUX_VERSION_CODE KERNEL_VERSION(2, 6, 17) + +static __inline _list *get_next(_list *list) +{ + return list->next; +} + +static __inline _list *get_list_head(_queue *queue) +{ + return (&(queue->queue)); +} + +#define LIST_CONTAINOR(ptr, type, member) \ + ((type *)((char *)(ptr)-(SIZE_T)((char *)&((type *)ptr)->member - (char *)ptr))) +#define container_of(p,t,n) (t*)((p)-&(((t*)0)->n)) + +#define TASK_PRORITY_LOW 1 +#define TASK_PRORITY_MIDDLE 2 +#define TASK_PRORITY_HIGH 3 +#define TASK_PRORITY_SUPER 4 + +#define TIMER_MAX_DELAY 0xFFFFFFFF + +// rtl8195a uses receive_tasklet for wps +// 8189em uses interrupt_thread for wps +#if defined(CONFIG_WPS) +#define RECV_STACK_FOR_WPS 448//512//384 //Change to 512 for WPS (IAR STM32) stack overflow +#else +#define RECV_STACK_FOR_WPS 0 +#endif + +#ifdef CONFIG_DONT_CARE_TP +#define XMIT_STACKSIZE 192 //256 +#define CMD_STACKSIZE 384 //512 +#else +#define XMIT_STACKSIZE 256 +#define CMD_STACKSIZE 512 //1024 +#endif //CONFIG_DONT_CARE_TP + +#ifdef CONFIG_PLATFORM_8195A +#define RECV_STACKSIZE 256 +#else //CONFIG_PLATFORM_8195A +#ifdef CONFIG_INCLUDE_WPA_PSK +#if PSK_SUPPORT_TKIP +#define RECV_STACKSIZE (512 + 256 + 128 + RECV_STACK_FOR_WPS) +#else +#define RECV_STACKSIZE (512 + 256 + RECV_STACK_FOR_WPS ) +#endif +#else +#define RECV_STACKSIZE (512 + 256 + RECV_STACK_FOR_WPS) //Can be reduced +#endif +#endif //CONFIG_PLATFORM_8195A + +#define XMIT_TASKLET_STACKSIZE 256 +#define RECV_TASKLET_STACKSIZE (1024 + RECV_STACK_FOR_WPS) +#define SDIOXMIT_STACKSIZE 256 + + +struct rtw_netdev_priv_indicator { + void *priv; + u32 sizeof_priv; +}; + +#define rtw_netdev_priv(netdev) ( ((struct rtw_netdev_priv_indicator *)netdev_priv(netdev))->priv ) + +#define ADPT_FMT "%s" +#define ADPT_ARG(adapter) adapter->pnetdev->name +#define FUNC_NDEV_FMT "%s" +#define FUNC_NDEV_ARG(ndev) __func__ +#define FUNC_ADPT_FMT "%s(%s)" +#define FUNC_ADPT_ARG(adapter) __func__, adapter->pnetdev->name + +void save_and_cli(void); +void restore_flags(void); +void cli(void); + +//----- ------------------------------------------------------------------ +// Common Definition +//----- ------------------------------------------------------------------ + +#define __init +#define __exit +#define __devinit +#define __devexit + +#define KERN_ERR +#define KERN_INFO +#define KERN_NOTICE + +#define GFP_KERNEL 1 +#define GFP_ATOMIC 1 + +#define SET_MODULE_OWNER(some_struct) do { } while (0) +#define SET_NETDEV_DEV(dev, obj) do { } while (0) +#define register_netdev(dev) (0) +#define unregister_netdev(dev) do { } while (0) +#define netif_queue_stopped(dev) (0) +#define netif_wake_queue(dev) do { } while (0) +#define printk printf + +#define DBG_ERR(fmt, args...) printf("\n\r[%s] " fmt, __FUNCTION__, ## args) +#if WLAN_INTF_DBG +#define DBG_TRACE(fmt, args...) printf("\n\r[%s] " fmt, __FUNCTION__, ## args) +#define DBG_INFO(fmt, args...) printf("\n\r[%s] " fmt, __FUNCTION__, ## args) +#else +#define DBG_TRACE(fmt, args...) +#define DBG_INFO(fmt, args...) +#endif +#define HALT() do { cli(); for(;;);} while(0) +#define ASSERT(x) do { \ + if((x) == 0) \ + printf("\n\rAssert(" #x ") failed on line %d in file %s", __LINE__, __FILE__); \ + HALT(); \ + } while(0) + +#undef DBG_ASSERT +#define DBG_ASSERT(x, msg) do { \ + if((x) == 0) \ + printf("\n\r%s, Assert(" #x ") failed on line %d in file %s", msg, __LINE__, __FILE__); \ + } while(0) + +//----- ------------------------------------------------------------------ +// Atomic Operation +//----- ------------------------------------------------------------------ +#if !defined(CONFIG_PLATFORM_8195A) && !defined(CONFIG_PLATFORM_8711B) // for 8195A, it is defined in ..system../basic_types.h +typedef struct { volatile int counter; } atomic_t; +#endif + + +/* + * atomic_read - read atomic variable + * @v: pointer of type atomic_t + * + * Atomically reads the value of @v. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +#define atomic_read(v) ((v)->counter) + +/* + * atomic_set - set atomic variable + * @v: pointer of type atomic_t + * @i: required value + * + * Atomically sets the value of @v to @i. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +#define atomic_set(v,i) ((v)->counter = (i)) + + /* + * These inlines deal with timer wrapping correctly. You are + * strongly encouraged to use them + * 1. Because people otherwise forget + * 2. Because if the timer wrap changes in future you wont have to + * alter your driver code. + * + * time_after(a,b) returns true if the time a is after time b. + * + * Do this with "<0" and ">=0" to only test the sign of the result. A + * good compiler would generate better code (and a really good compiler + * wouldn't care). Gcc is currently neither. + */ + #define time_after(a,b) ((long)(b) - (long)(a) < 0) + #define time_before(a,b) time_after(b,a) + + #define time_after_eq(a,b) ((long)(a) - (long)(b) >= 0) + #define time_before_eq(a,b) time_after_eq(b,a) + + +extern void rtw_init_listhead(_list *list); +extern u32 rtw_is_list_empty(_list *phead); +extern void rtw_list_insert_head(_list *plist, _list *phead); +extern void rtw_list_insert_tail(_list *plist, _list *phead); +extern void rtw_list_delete(_list *plist); + +#endif /* _FREERTOS_SERVICE_H_ */ diff --git a/component/common/drivers/wlan/realtek/src/osdep/freertos/wrapper.h b/component/common/drivers/wlan/realtek/src/osdep/freertos/wrapper.h new file mode 100644 index 0000000..1d8cce1 --- /dev/null +++ b/component/common/drivers/wlan/realtek/src/osdep/freertos/wrapper.h @@ -0,0 +1,432 @@ +#ifndef __WRAPPER_H__ +#define __WRAPPER_H__ +/************************************************************************** + * Wrapper provide a linux-like interface + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + ************************************************************************/ + +//----- ------------------------------------------------------------------ +// Include Files +//----- ------------------------------------------------------------------ +#include +#include +#include "wireless.h" +#include +#include "freertos_service.h" + + +//----- ------------------------------------------------------------------ +// Linled List +//----- ------------------------------------------------------------------ +/* + * Simple doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ +// struct list_head { +// struct list_head *next, *prev; +// }; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define INIT_LIST_HEAD(ptr) do { \ + (ptr)->next = (ptr); (ptr)->prev = (ptr); \ +} while (0) + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static __inline void __list_add(struct list_head * new, + struct list_head * prev, + struct list_head * next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static __inline void __list_del(struct list_head * prev, + struct list_head * next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty on entry does not return true after this, the entry is in an undefined state. + */ +static __inline void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); +} + +/** + * list_del_init - deletes entry from list and reinitialize it. + * @entry: the element to delete from the list. + */ +static __inline void list_del_init(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + INIT_LIST_HEAD(entry); +} + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static __inline int list_empty(struct list_head *head) +{ + return head->next == head; +} + +/** + * list_splice - join two lists + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static __inline void list_splice(struct list_head *list, struct list_head *head) +{ + struct list_head *first = list->next; + + if (first != list) { + struct list_head *last = list->prev; + struct list_head *at = head->next; + + first->prev = head; + head->next = first; + + last->next = at; + at->prev = last; + } +} + +void list_add(struct list_head *new, struct list_head *head); +void list_add_tail(struct list_head *new, struct list_head *head); + +extern void save_and_cli(void); +extern void restore_flags(void); +//----- ------------------------------------------------------------------ +// SKB Operation +//----- ------------------------------------------------------------------ + +#define SMP_CACHE_BYTES 4 +#define SKB_DATA_ALIGN(X) (((X) + (SMP_CACHE_BYTES - 1)) & ~(SMP_CACHE_BYTES - 1)) + +// Consideration for SKB size +// Tx: [INTF_CMD][TX_DESC][WLAN_HDR][QoS][IV][SNAP][Data][MIC][ICV][INTF_STATUS] +// Since SKB is used to accept ethernet packet from upper layer, SKB length of WLAN_MAX_ETHFRM_LEN +// (= 1514) is enough. But since SKB is also used to get spi receive packet, overall buffer space +// should be taken into consideration. +// RX: [INTF_CMD][RX_DESC][Drv_Info][WLAN_HDR][QoS][IV][SNAP][Data][MIC][ICV][CRC][INTF_STATUS] +// +// 32: Driver_Info that carry phy related information for each packets. Required only for receive case. +// WLAN_MAX_ETHFRM_LEN : May not be required because WLAN_HEADER +SNAP can totally +// cover ethernet header. Keep in only for safety. +// +// **Notes** SDIO requires 512 blocks r/w, so 512*4 = 2048 is required. +// 2003/12/26. The value is reduced from 2048 to 1658 for GSPI +// 2014/02/05. The value is 1650 for 8195A LX_BUS +#define SKB_RESERVED_FOR_SAFETY 0 +#define SKB_WLAN_TX_EXTRA_LEN (TXDESC_SIZE + WLAN_HDR_A4_QOS_LEN + WLAN_MAX_IV_LEN + WLAN_SNAP_HEADER - WLAN_ETHHDR_LEN) +#define RX_DRIVER_INFO 32 + +#if (defined CONFIG_GSPI_HCI || defined CONFIG_SDIO_HCI) +#define HAL_INTERFACE_OVERHEAD_SKB_DATA 12 //HAL_INTERFACE_CMD (4) + HAL_INTERFACE_STATUS (8) +#elif defined(CONFIG_LX_HCI) +#define HAL_INTERFACE_OVERHEAD_SKB_DATA 0 +#endif + +#if defined CONFIG_GSPI_HCI || defined CONFIG_SDIO_HCI || defined(CONFIG_LX_HCI) + #if defined(CONFIG_RTL8195A) || defined(CONFIG_RTL8711B) + #if defined(CONFIG_MP_INCLUDED) + #ifdef CONFIG_DONT_CARE_TP + #define MAX_RX_PKT_LIMIT ((WLAN_MAX_PROTOCOL_OVERHEAD + WLAN_MAX_RX_ETHFRM_LEN + 511) / 512) // 4, for lxbus + #else + #define MAX_RX_PKT_LIMIT ((WLAN_MAX_PROTOCOL_OVERHEAD + WLAN_MAX_ETHFRM_LEN + 511) / 512) // 4, for lxbus + #endif + #define MAX_RX_PKT_SIZE MAX_RX_PKT_LIMIT*512 // MAX_SKB_BUF_SIZE = 0+32+40+512*4+0 = 2120 + #else + #define MAX_RX_PKT_LIMIT 4 // MAX_SKB_BUF_SIZE = 0+32+40+64+1514+0 = 1650 + #ifdef CONFIG_DONT_CARE_TP + #define MAX_RX_PKT_SIZE WLAN_MAX_PROTOCOL_OVERHEAD + WLAN_MAX_RX_ETHFRM_LEN + #else + #define MAX_RX_PKT_SIZE WLAN_MAX_PROTOCOL_OVERHEAD + WLAN_MAX_ETHFRM_LEN + #endif + #endif + #else + #ifdef CONFIG_DONT_CARE_TP + #define MAX_RX_PKT_SIZE WLAN_MAX_PROTOCOL_OVERHEAD + WLAN_MAX_RX_ETHFRM_LEN + #else + #define MAX_RX_PKT_SIZE WLAN_MAX_PROTOCOL_OVERHEAD + WLAN_MAX_ETHFRM_LEN + #endif + #endif + + #ifdef CONFIG_DONT_CARE_TP + #define MAX_TX_SKB_BUF_SIZE (HAL_INTERFACE_OVERHEAD_SKB_DATA+RX_DRIVER_INFO+\ + ((TXDESC_SIZE>RXDESC_SIZE)? TXDESC_SIZE:RXDESC_SIZE) +\ + WLAN_MAX_PROTOCOL_OVERHEAD + WLAN_MAX_TX_ETHFRM_LEN +\ + SKB_RESERVED_FOR_SAFETY) + #define MAX_RX_SKB_BUF_SIZE (HAL_INTERFACE_OVERHEAD_SKB_DATA+RX_DRIVER_INFO+\ + ((TXDESC_SIZE>RXDESC_SIZE)? TXDESC_SIZE:RXDESC_SIZE) +\ + MAX_RX_PKT_SIZE +\ + SKB_RESERVED_FOR_SAFETY) + #else + #define MAX_SKB_BUF_SIZE (HAL_INTERFACE_OVERHEAD_SKB_DATA+RX_DRIVER_INFO+\ + ((TXDESC_SIZE>RXDESC_SIZE)? TXDESC_SIZE:RXDESC_SIZE) +\ + MAX_RX_PKT_SIZE +\ + SKB_RESERVED_FOR_SAFETY) + #endif +#else +#define MAX_SKB_BUF_SIZE 2048 +#endif + +#if 0 +struct sk_buff_head { + struct list_head *next, *prev; + u32 qlen; +}; + +struct sk_buff { + /* These two members must be first. */ + struct sk_buff *next; /* Next buffer in list */ + struct sk_buff *prev; /* Previous buffer in list */ + + struct sk_buff_head *list; /* List we are on */ + unsigned char *head; /* Head of buffer */ + unsigned char *data; /* Data head pointer */ + unsigned char *tail; /* Tail pointer */ + unsigned char *end; /* End pointer */ + struct net_device *dev; /* Device we arrived on/are leaving by */ + unsigned int len; /* Length of actual data */ +}; + +/** + * skb_put - add data to a buffer + * @skb: buffer to use + * @len: amount of data to add + * + * This function extends the used data area of the buffer. If this would + * exceed the total buffer size the kernel will panic. A pointer to the + * first byte of the extra data is returned. + */ + +static __inline__ unsigned char *skb_put(struct sk_buff *skb, unsigned int len) +{ + unsigned char *tmp=skb->tail; + skb->tail+=len; + skb->len+=len; + if(skb->tail>skb->end) { + ASSERT(0); + } + + return tmp; +} + +static __inline__ unsigned char *__skb_pull(struct sk_buff *skb, unsigned int len) +{ + skb->len-=len; + skb->data = (unsigned char *)(((unsigned int)skb->data) + len); + + return skb->data; +} + +/** + * skb_reserve - adjust headroom + * @skb: buffer to alter + * @len: bytes to move + * + * Increase the headroom of an empty &sk_buff by reducing the tail + * room. This is only allowed for an empty buffer. + */ + +static __inline__ void skb_reserve(struct sk_buff *skb, unsigned int len) +{ + skb->data+=len; + skb->tail+=len; +} + +static __inline__ void skb_queue_head_init(struct sk_buff_head *list) +{ + list->prev = (struct list_head *)list; + list->next = (struct list_head *)list; + list->qlen = 0; +} + +/** + * __skb_queue_tail - queue a buffer at the list tail + * @list: list to use + * @newsk: buffer to queue + * + * Queue a buffer at the end of a list. This function takes no locks + * and you must therefore hold required locks before calling it. + * + * A buffer cannot be placed on two lists at the same time. + */ + +static __inline__ void __skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk) +{ + struct sk_buff *prev, *next; + + newsk->list = list; + list->qlen++; + next = (struct sk_buff *)list; + prev = next->prev; + newsk->next = next; + newsk->prev = prev; + next->prev = newsk; + prev->next = newsk; +} + +/** + * skb_queue_tail - queue a buffer at the list tail + * @list: list to use + * @newsk: buffer to queue + * + * Queue a buffer at the tail of the list. This function takes the + * list lock and can be used safely with other locking &sk_buff functions + * safely. + * + * A buffer cannot be placed on two lists at the same time. + */ + +static __inline__ void skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk) +{ + save_and_cli(); + __skb_queue_tail(list, newsk); + restore_flags(); +} + +static __inline__ void skb_assign_buf(struct sk_buff *skb, unsigned char *buf, unsigned int len) +{ + skb->head = buf; + skb->data = buf; + skb->tail = buf; + skb->end = buf + len; +} + +static __inline__ unsigned char *skb_tail_pointer(const struct sk_buff *skb) +{ + return skb->tail; +} + +static __inline__ void skb_reset_tail_pointer(struct sk_buff *skb) +{ + skb->tail = skb->data; +} + +static __inline__ void skb_set_tail_pointer(struct sk_buff *skb, const int offset) +{ + skb->tail = skb->data + offset; +} + +static __inline__ unsigned char *skb_end_pointer(const struct sk_buff *skb) +{ + return skb->end; +} +#endif +/* + * External functions + */ +struct net_device; +extern void kfree_skb_chk_key(struct sk_buff *skb, struct net_device *root_dev); +#ifdef CONFIG_TRACE_SKB +extern void show_skb(void); +extern int _set_skb_list_flag(struct sk_buff *skb, unsigned int queueflag); +extern void dump_skb_list(void); +#define set_skb_list_flag(skb, queueflag) \ + (\ + _set_skb_list_flag((skb), queueflag), \ + (skb) ? (skb)->funcname[(skb)->list_idx] = __FUNCTION__:NULL \ + ) +extern int _clear_skb_list_flag(struct sk_buff *skb, unsigned int queueflag); +#define clear_skb_list_flag(skb, queueflag) \ + (\ + _clear_skb_list_flag((skb), queueflag), \ + (skb) ? (skb)->funcname[(skb)->list_idx] = __FUNCTION__ : NULL \ + ) +#define dev_kfree_skb_any(trx, holder, skb) \ + do{\ + clear_skb_list_flag(skb, SKBLIST_##trx##holder##_MASK);\ + set_skb_list_flag(skb, SKBLIST_POOL);\ + kfree_skb_chk_key(skb, skb->dev);\ + }while (0) +#else +#define dev_kfree_skb_any(skb) kfree_skb_chk_key(skb, skb->dev) +#endif +extern struct sk_buff *dev_alloc_skb(unsigned int length, unsigned int reserve_len); +extern struct sk_buff *skb_clone(struct sk_buff *skb, int gfp_mask); +extern struct sk_buff *skb_copy(const struct sk_buff *skb, int gfp_mask, unsigned int reserve_len); +extern unsigned char *skb_pull(struct sk_buff *skb, unsigned int len); + +//----- ------------------------------------------------------------------ +// Device structure +//----- ------------------------------------------------------------------ +struct net_device_stats { + unsigned long rx_packets; /* total packets received */ + unsigned long tx_packets; /* total packets transmitted */ + unsigned long rx_dropped; /* no space in linux buffers */ + unsigned long tx_dropped; /* no space available in linux */ + unsigned long rx_bytes; /* total bytes received */ + unsigned long tx_bytes; /* total bytes transmitted */ +}; + +struct net_device { + char name[16]; + void *priv; /* pointer to private data */ + unsigned char dev_addr[6]; /* set during bootup */ + int (*init)(void); + int (*open)(struct net_device *dev); + int (*stop)(struct net_device *dev); + int (*hard_start_xmit)(struct sk_buff *skb, struct net_device *dev); + int (*do_ioctl)(struct net_device *dev, struct iwreq *ifr, int cmd); + struct net_device_stats* (*get_stats)(struct net_device *dev); +}; + +typedef struct { + struct net_device *dev; /* Binding wlan driver netdev */ + void *skb; /* pending Rx packet */ + unsigned int tx_busy; + unsigned int rx_busy; + unsigned char enable; + unsigned char mac[6]; +} Rltk_wlan_t; + +#define netdev_priv(dev) dev->priv + +extern struct net_device *alloc_etherdev(int sizeof_priv); +void free_netdev(struct net_device *dev); +int dev_alloc_name(struct net_device *net_dev, const char *ifname); + + +//----- ------------------------------------------------------------------ +// Timer Operation +//----- ------------------------------------------------------------------ +void init_timer(struct timer_list *timer); +void mod_timer(struct timer_list *timer, u32 delay_time_ms); +void cancel_timer_ex(struct timer_list * timer); +void del_timer_sync(struct timer_list * timer); +void init_timer_wrapper(void); +void deinit_timer_wrapper(void); + +#endif //__WRAPPER_H__ + + + diff --git a/component/common/drivers/wlan/realtek/src/osdep/lwip_intf.c b/component/common/drivers/wlan/realtek/src/osdep/lwip_intf.c new file mode 100644 index 0000000..8a0b776 --- /dev/null +++ b/component/common/drivers/wlan/realtek/src/osdep/lwip_intf.c @@ -0,0 +1,222 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * + ******************************************************************************/ +//#define _LWIP_INTF_C_ + +#include +#include +#include +#include +#include +#include +#include +//----- ------------------------------------------------------------------ +// External Reference +//----- ------------------------------------------------------------------ +#if (CONFIG_LWIP_LAYER == 1) +extern struct netif xnetif[]; //LWIP netif +#endif + +/** + * rltk_wlan_set_netif_info - set netif hw address and register dev pointer to netif device + * @idx_wlan: netif index + * 0 for STA only or SoftAP only or STA in STA+SoftAP concurrent mode, + * 1 for SoftAP in STA+SoftAP concurrent mode + * @dev: register netdev pointer to LWIP. Reserved. + * @dev_addr: set netif hw address + * + * Return Value: None + */ +void rltk_wlan_set_netif_info(int idx_wlan, void * dev, unsigned char * dev_addr) +{ +#if (CONFIG_LWIP_LAYER == 1) + rtw_memcpy(xnetif[idx_wlan].hwaddr, dev_addr, 6); + xnetif[idx_wlan].state = dev; +#endif +} + +/** + * rltk_wlan_send - send IP packets to WLAN. Called by low_level_output(). + * @idx: netif index + * @sg_list: data buffer list + * @sg_len: size of each data buffer + * @total_len: total data len + * + * Return Value: None + */ +int rltk_wlan_send(int idx, struct eth_drv_sg *sg_list, int sg_len, int total_len) +{ + struct eth_drv_sg *last_sg; + struct sk_buff *skb = NULL; + int ret = 0; + + if(idx == -1){ + DBG_ERR("netif is DOWN"); + return -1; + } + DBG_TRACE("%s is called", __FUNCTION__); + + save_and_cli(); + if(rltk_wlan_check_isup(idx)) + rltk_wlan_tx_inc(idx); + else { + DBG_ERR("netif is DOWN"); + restore_flags(); + return -1; + } + restore_flags(); + + skb = rltk_wlan_alloc_skb(total_len); + if (skb == NULL) { + DBG_ERR("rltk_wlan_alloc_skb() for data len=%d failed!", total_len); + ret = -1; + goto exit; + } + + for (last_sg = &sg_list[sg_len]; sg_list < last_sg; ++sg_list) { + rtw_memcpy(skb->tail, (void *)(sg_list->buf), sg_list->len); + skb_put(skb, sg_list->len); + } + + rltk_wlan_send_skb(idx, skb); + +exit: + save_and_cli(); + rltk_wlan_tx_dec(idx); + restore_flags(); + return ret; +} + +/** + * rltk_wlan_recv - indicate packets to LWIP. Called by ethernetif_recv(). + * @idx: netif index + * @sg_list: data buffer list + * @sg_len: size of each data buffer + * + * Return Value: None + */ +void rltk_wlan_recv(int idx, struct eth_drv_sg *sg_list, int sg_len) +{ + struct eth_drv_sg *last_sg; + struct sk_buff *skb; + + DBG_TRACE("%s is called", __FUNCTION__); + if(idx == -1){ + DBG_ERR("skb is NULL"); + return; + } + skb = rltk_wlan_get_recv_skb(idx); + DBG_ASSERT(skb, "No pending rx skb"); + + for (last_sg = &sg_list[sg_len]; sg_list < last_sg; ++sg_list) { + if (sg_list->buf != 0) { + rtw_memcpy((void *)(sg_list->buf), skb->data, sg_list->len); + skb_pull(skb, sg_list->len); + } + } +} + +int netif_is_valid_IP(int idx, unsigned char *ip_dest) +{ +#if CONFIG_LWIP_LAYER == 1 + struct netif * pnetif = &xnetif[idx]; + struct ip_addr addr = { 0 }; +#ifdef CONFIG_MEMORY_ACCESS_ALIGNED + unsigned int temp; + memcpy(&temp, ip_dest, sizeof(unsigned int)); + u32_t *ip_dest_addr = &temp; +#else + u32_t *ip_dest_addr = (u32_t*)ip_dest; +#endif + addr.addr = *ip_dest_addr; + + if(pnetif->ip_addr.addr == 0) + return 1; + + if(ip_addr_ismulticast(&addr) || ip_addr_isbroadcast(&addr,pnetif)){ + return 1; + } + + //if(ip_addr_netcmp(&(pnetif->ip_addr), &addr, &(pnetif->netmask))) //addr&netmask + // return 1; + + if(ip_addr_cmp(&(pnetif->ip_addr),&addr)) + return 1; + + DBG_TRACE("invalid IP: %d.%d.%d.%d ",ip_dest[0],ip_dest[1],ip_dest[2],ip_dest[3]); +#endif +#ifdef CONFIG_DONT_CARE_TP + if(pnetif->flags & NETIF_FLAG_IPSWITCH) + return 1; + else +#endif + return 0; +} + +int netif_get_idx(struct netif* pnetif) +{ +#if CONFIG_LWIP_LAYER == 1 + int idx = pnetif - xnetif; + + switch(idx) { + case 0: + return 0; + case 1: + return 1; + default: + return -1; + } +#else + return -1; +#endif +} + +unsigned char *netif_get_hwaddr(int idx_wlan) +{ +#if (CONFIG_LWIP_LAYER == 1) + return xnetif[idx_wlan].hwaddr; +#else + return NULL; +#endif +} + +void netif_rx(int idx, unsigned int len) +{ +#if (CONFIG_LWIP_LAYER == 1) + ethernetif_recv(&xnetif[idx], len); +#endif +#if (CONFIG_INIC_EN == 1) + inic_netif_rx(idx, len); +#endif +} + +void netif_post_sleep_processing(void) +{ +#if (CONFIG_LWIP_LAYER == 1) + lwip_POST_SLEEP_PROCESSING(); //For FreeRTOS tickless to enable Lwip ARP timer when leaving IPS - Alex Fang +#endif +} + +void netif_pre_sleep_processing(void) +{ +#if (CONFIG_LWIP_LAYER == 1) + lwip_PRE_SLEEP_PROCESSING(); +#endif +} + diff --git a/component/common/drivers/wlan/realtek/src/osdep/lwip_intf.h b/component/common/drivers/wlan/realtek/src/osdep/lwip_intf.h new file mode 100644 index 0000000..3478de3 --- /dev/null +++ b/component/common/drivers/wlan/realtek/src/osdep/lwip_intf.h @@ -0,0 +1,56 @@ +#ifndef __LWIP_INTF_H__ +#define __LWIP_INTF_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +//----- ------------------------------------------------------------------ +// Ethernet Buffer +//----- ------------------------------------------------------------------ +struct eth_drv_sg { + unsigned int buf; + unsigned int len; +}; + +#define MAX_ETH_DRV_SG 32 +#define MAX_ETH_MSG 1540 + +//----- ------------------------------------------------------------------ +// Wlan Interface Provided +//----- ------------------------------------------------------------------ +unsigned char rltk_wlan_check_isup(int idx); +void rltk_wlan_tx_inc(int idx); +void rltk_wlan_tx_dec(int idx); +struct sk_buff * rltk_wlan_get_recv_skb(int idx); +struct sk_buff * rltk_wlan_alloc_skb(unsigned int total_len); +void rltk_wlan_set_netif_info(int idx_wlan, void * dev, unsigned char * dev_addr); +void rltk_wlan_send_skb(int idx, struct sk_buff *skb); //struct sk_buff as defined above comment line +int rltk_wlan_send(int idx, struct eth_drv_sg *sg_list, int sg_len, int total_len); +void rltk_wlan_recv(int idx, struct eth_drv_sg *sg_list, int sg_len); +unsigned char rltk_wlan_running(unsigned char idx); // interface is up. 0: interface is down + +//----- ------------------------------------------------------------------ +// Network Interface provided +//----- ------------------------------------------------------------------ +struct netif; +int netif_is_valid_IP(int idx,unsigned char * ip_dest); +int netif_get_idx(struct netif *pnetif); +unsigned char *netif_get_hwaddr(int idx_wlan); +void netif_rx(int idx, unsigned int len); +void netif_post_sleep_processing(void); +void netif_pre_sleep_processing(void); +#if (CONFIG_LWIP_LAYER == 1) +extern void ethernetif_recv(struct netif *netif, int total_len); +extern void lwip_PRE_SLEEP_PROCESSING(void); +extern void lwip_POST_SLEEP_PROCESSING(void); +#endif //CONFIG_LWIP_LAYER == 1 + +#ifdef __cplusplus +} +#endif + +#endif //#ifndef __LWIP_INTF_H__ diff --git a/component/common/drivers/wlan/realtek/src/osdep/osdep_service.h b/component/common/drivers/wlan/realtek/src/osdep/osdep_service.h new file mode 100644 index 0000000..8541247 --- /dev/null +++ b/component/common/drivers/wlan/realtek/src/osdep/osdep_service.h @@ -0,0 +1,523 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * + ******************************************************************************/ +#ifndef __OSDEP_SERVICE_H_ +#define __OSDEP_SERVICE_H_ + +/* Define compilor specific symbol */ +// +// inline function +// + +#if defined ( __ICCARM__ ) +#define __inline__ inline +#define __inline inline +#define __inline_definition //In dialect C99, inline means that a function's definition is provided + //only for inlining, and that there is another definition + //(without inline) somewhere else in the program. + //That means that this program is incomplete, because if + //add isn't inlined (for example, when compiling without optimization), + //then main will have an unresolved reference to that other definition. + + // Do not inline function is the function body is defined .c file and this + // function will be called somewhere else, otherwise there is compile error +#elif defined ( __CC_ARM ) +#define __inline__ __inline //__linine__ is not supported in keil compilor, use __inline instead +#define inline __inline +#define __inline_definition // for dialect C99 +#elif defined ( __GNUC__ ) +#define __inline__ inline +#define __inline inline +#define __inline_definition inline +#endif + +#include +#include +#if defined( PLATFORM_FREERTOS) +#include "freertos/freertos_service.h" +#elif defined( PLATFORM_ECOS) +#include "ecos/ecos_service.h" +#endif + +#include "wifi_constants.h" +#include "wifi_structures.h" + +#define RTW_MAX_DELAY 0xFFFFFFFF +#define RTW_WAIT_FOREVER 0xFFFFFFFF + +struct timer_list { + _timerHandle timer_hdl; + unsigned long data; + void (*function)(void *); +}; + +typedef thread_return (*thread_func_t)(thread_context context); +typedef void (*TIMER_FUN)(void *context); +typedef int (*event_handler_t)(char *buf, int buf_len, int flags, void *user_data); + +#define CONFIG_THREAD_COMM_SEMA +struct task_struct { + const char *task_name; + _thread_hdl_ task; /* I: workqueue thread */ + +#ifdef CONFIG_THREAD_COMM_SIGNAL + const char *name; /* I: workqueue thread name */ + u32 queue_num; /* total signal num */ + u32 cur_queue_num; /* cur signal num should < queue_num */ +#elif defined(CONFIG_THREAD_COMM_SEMA) + _sema wakeup_sema; + _sema terminate_sema; +// _queue work_queue; //TODO +#endif + u32 blocked; + u32 callback_running; +}; + +typedef struct { + _xqueue event_queue; + struct task_struct thread; +}rtw_worker_thread_t; + +typedef struct +{ + event_handler_t function; + char *buf; + int buf_len; + int flags; + void *user_data; +} rtw_event_message_t; + +struct worker_timer_entry { + struct list_head list; + _timerHandle timer_hdl; + rtw_event_message_t message; + rtw_worker_thread_t *worker_thread; + u32 timeout; +}; +#ifdef CONFIG_THREAD_COMM_SIGNAL +struct work_struct; +typedef void (*work_func_t)(void *context); +struct work_struct { + _list list; + u32 data; + work_func_t func; + void *context; + struct task_struct *used_wq; +}; + +struct delayed_work { + struct work_struct work; + struct timer_list timer; +}; +#endif + +#ifdef CONFIG_MEM_MONITOR +//----- ------------------------------------------------------------------ +// Memory Monitor +//----- ------------------------------------------------------------------ +#define MEM_MONITOR_SIMPLE 0x1 +#define MEM_MONITOR_LEAK 0x2 + +#define MEM_MONITOR_FLAG_WIFI_DRV 0x1 +#define MEM_MONITOR_FLAG_WPAS 0x2 +#if CONFIG_MEM_MONITOR & MEM_MONITOR_LEAK +struct mem_entry { + struct list_head list; + int size; + void *ptr; +}; +#endif + +void init_mem_monitor(_list *pmem_table, int *used_num); +void deinit_mem_monitor(_list *pmem_table, int *used_num); +void add_mem_usage(_list *pmem_table, void *ptr, int size, int *used_num, int flag); +void del_mem_usage(_list *pmem_table, void *ptr, int *used_num, int flag); +int get_mem_usage(_list *pmem_table); +#endif + +/*********************************** OSDEP API *****************************************/ +u8* _rtw_vmalloc(u32 sz); +u8* _rtw_zvmalloc(u32 sz); +void _rtw_vmfree(u8 *pbuf, u32 sz); +u8* _rtw_zmalloc(u32 sz); +u8* _rtw_malloc(u32 sz); +void _rtw_mfree(u8 *pbuf, u32 sz); +#ifdef CONFIG_MEM_MONITOR +u8* rtw_vmalloc(u32 sz); +u8* rtw_zvmalloc(u32 sz); +void rtw_vmfree(u8 *pbuf, u32 sz); +u8* rtw_zmalloc(u32 sz); +u8* rtw_malloc(u32 sz); +void rtw_mfree(u8 *pbuf, u32 sz); +#else +#define rtw_vmalloc _rtw_vmalloc +#define rtw_zvmalloc _rtw_zvmalloc +#define rtw_vmfree _rtw_vmfree +#define rtw_zmalloc _rtw_zmalloc +#define rtw_malloc _rtw_malloc +#define rtw_mfree _rtw_mfree +#endif +#define rtw_free(buf) rtw_mfree((u8 *)buf, 0) +void* rtw_malloc2d(int h, int w, int size); +void rtw_mfree2d(void *pbuf, int h, int w, int size); +void rtw_memcpy(void* dst, void* src, u32 sz); +int rtw_memcmp(void *dst, void *src, u32 sz); +void rtw_memset(void *pbuf, int c, u32 sz); + +void rtw_init_listhead(_list *list); +u32 rtw_is_list_empty(_list *phead); +void rtw_list_insert_head(_list *plist, _list *phead); +void rtw_list_insert_tail(_list *plist, _list *phead); +void rtw_list_delete(_list *plist); + +void rtw_init_sema(_sema *sema, int init_val); +void rtw_free_sema(_sema *sema); +void rtw_up_sema(_sema *sema); +u32 rtw_down_sema(_sema *sema); +u32 rtw_down_timeout_sema(_sema *sema, u32 timeout); +void rtw_mutex_init(_mutex *pmutex); +void rtw_mutex_free(_mutex *pmutex); +void rtw_mutex_put(_mutex *pmutex); +void rtw_mutex_get(_mutex *pmutex); +void rtw_enter_critical(_lock *plock, _irqL *pirqL); +void rtw_exit_critical(_lock *plock, _irqL *pirqL); +void rtw_enter_critical_bh(_lock *plock, _irqL *pirqL); +void rtw_exit_critical_bh(_lock *plock, _irqL *pirqL); +int rtw_enter_critical_mutex(_mutex *pmutex, _irqL *pirqL); +void rtw_exit_critical_mutex(_mutex *pmutex, _irqL *pirqL); +void rtw_spinlock_init(_lock *plock); +void rtw_spinlock_free(_lock *plock); +void rtw_spinlock_init(_lock *plock); +void rtw_spinlock_free(_lock *plock); +void rtw_spin_lock(_lock *plock); +void rtw_spin_unlock(_lock *plock); +void rtw_spinlock_irqsave(_lock *plock, _irqL *irqL); +void rtw_spinunlock_irqsave(_lock *plock, _irqL *irqL); + +rtw_result_t rtw_init_xqueue( _xqueue* queue, const char* name, u32 message_size, u32 number_of_messages ); +rtw_result_t rtw_push_to_xqueue( _xqueue* queue, void* message, u32 timeout_ms ); +rtw_result_t rtw_pop_from_xqueue( _xqueue* queue, void* message, u32 timeout_ms ); +rtw_result_t rtw_deinit_xqueue( _xqueue* queue ); + +void rtw_init_queue(_queue *pqueue); +void rtw_deinit_queue(_queue *pqueue); +u32 rtw_is_queue_empty(_queue *pqueue); +u32 rtw_queue_empty(_queue *pqueue); +u32 rtw_end_of_queue_search(_list *queue, _list *pelement); +_list* rtw_get_queue_head(_queue *queue); + +u32 rtw_get_current_time(void); +u32 rtw_systime_to_ms(u32 systime); +u32 rtw_systime_to_sec(u32 systime); +u32 rtw_ms_to_systime(u32 ms); +u32 rtw_sec_to_systime(u32 sec); +s32 rtw_get_passing_time_ms(u32 start); +s32 rtw_get_time_interval_ms(u32 start, u32 end); + +void rtw_msleep_os(int ms); +void rtw_usleep_os(int us); +u32 rtw_atoi(u8* s); +void rtw_mdelay_os(int ms); +void rtw_udelay_os(int us); +void rtw_yield_os(void); + +void rtw_init_timer(_timer *ptimer, void *adapter, TIMER_FUN pfunc,void* cntx, const char *name); +void rtw_set_timer(_timer *ptimer,u32 delay_time); +u8 rtw_cancel_timer(_timer *ptimer); +void rtw_del_timer(_timer *ptimer); + +//Atomic integer operations +void ATOMIC_SET(ATOMIC_T *v, int i); +int ATOMIC_READ(ATOMIC_T *v); +void ATOMIC_ADD(ATOMIC_T *v, int i); +void ATOMIC_SUB(ATOMIC_T *v, int i); +void ATOMIC_INC(ATOMIC_T *v); +void ATOMIC_DEC(ATOMIC_T *v); +int ATOMIC_ADD_RETURN(ATOMIC_T *v, int i); +int ATOMIC_SUB_RETURN(ATOMIC_T *v, int i); +int ATOMIC_INC_RETURN(ATOMIC_T *v); +int ATOMIC_DEC_RETURN(ATOMIC_T *v); +int ATOMIC_DEC_AND_TEST(ATOMIC_T *v); + +u64 rtw_modular64(u64 x, u64 y); +int rtw_get_random_bytes(void* dst, u32 size); +u32 rtw_getFreeHeapSize(void); +void flush_signals_thread(void); + +/*********************************** Thread related *****************************************/ +int rtw_create_task(struct task_struct *task, const char *name, u32 stack_size, u32 priority, thread_func_t func, void *thctx); +void rtw_delete_task(struct task_struct * task); +void rtw_wakeup_task(struct task_struct *task); +rtw_result_t rtw_create_worker_thread( rtw_worker_thread_t* worker_thread, u8 priority, u32 stack_size, u32 event_queue_size ); +rtw_result_t rtw_delete_worker_thread( rtw_worker_thread_t* worker_thread ); + +#if 0 //TODO +void rtw_init_delayed_work(struct delayed_work *dwork, work_func_t func, const char *name); +void rtw_deinit_delayed_work(struct delayed_work *dwork); +int rtw_queue_delayed_work(struct workqueue_struct *wq, struct delayed_work *dwork, u32 delay, void* context); +BOOLEAN rtw_cancel_delayed_work(struct delayed_work *dwork); +#endif + +void rtw_thread_enter(char *name); +void rtw_thread_exit(void); +#ifdef PLATFORM_LINUX +#define rtw_warn_on(condition) WARN_ON(condition) +#else +#define rtw_warn_on(condition) do {} while (0) +#endif + +/*********************************** Timer related *****************************************/ +_timerHandle rtw_timerCreate( const signed char *pcTimerName, + osdepTickType xTimerPeriodInTicks, + u32 uxAutoReload, + void * pvTimerID, + TIMER_FUN pxCallbackFunction ); +u32 rtw_timerDelete( _timerHandle xTimer, + osdepTickType xBlockTime ); +u32 rtw_timerIsTimerActive( _timerHandle xTimer ); +u32 rtw_timerStop( _timerHandle xTimer, + osdepTickType xBlockTime ); +u32 rtw_timerChangePeriod( _timerHandle xTimer, + osdepTickType xNewPeriod, + osdepTickType xBlockTime ); + +/*********************************** OSDEP API end *****************************************/ +#define LIST_CONTAINOR(ptr, type, member) \ + ((type *)((char *)(ptr)-(SIZE_T)((char *)&((type *)ptr)->member - (char *)ptr))) + +#define time_after(a,b) ((long)(b) - (long)(a) < 0) +#define time_before(a,b) time_after(b,a) +#define time_after_eq(a,b) ((long)(a) - (long)(b) >= 0) +#define time_before_eq(a,b) time_after_eq(b,a) + +#define _RND(sz, r) ((((sz)+((r)-1))/(r))*(r)) +#define RND4(x) (((x >> 2) + (((x & 3) == 0) ? 0: 1)) << 2) + +__inline static u32 _RND4(u32 sz) +{ + u32 val; + + val = ((sz >> 2) + ((sz & 3) ? 1: 0)) << 2; + + return val; +} + +__inline static u32 _RND8(u32 sz) +{ + u32 val; + + val = ((sz >> 3) + ((sz & 7) ? 1: 0)) << 3; + + return val; +} + +__inline static u32 _RND128(u32 sz) +{ + u32 val; + + val = ((sz >> 7) + ((sz & 127) ? 1: 0)) << 7; + + return val; +} + +__inline static u32 _RND256(u32 sz) +{ + u32 val; + + val = ((sz >> 8) + ((sz & 255) ? 1: 0)) << 8; + + return val; +} + +__inline static u32 _RND512(u32 sz) +{ + u32 val; + + val = ((sz >> 9) + ((sz & 511) ? 1: 0)) << 9; + + return val; +} + +__inline static u32 bitshift(u32 bitmask) +{ + u32 i; + + for (i = 0; i <= 31; i++) + if (((bitmask>>i) & 0x1) == 1) break; + + return i; +} + +/* Macros for handling unaligned memory accesses */ + +#define RTW_GET_BE16(a) ((u16) (((a)[0] << 8) | (a)[1])) +#define RTW_PUT_BE16(a, val) \ + do { \ + (a)[0] = ((u16) (val)) >> 8; \ + (a)[1] = ((u16) (val)) & 0xff; \ + } while (0) + +#define RTW_GET_LE16(a) ((u16) (((a)[1] << 8) | (a)[0])) +#define RTW_PUT_LE16(a, val) \ + do { \ + (a)[1] = ((u16) (val)) >> 8; \ + (a)[0] = ((u16) (val)) & 0xff; \ + } while (0) + +#define RTW_GET_BE24(a) ((((u32) (a)[0]) << 16) | (((u32) (a)[1]) << 8) | \ + ((u32) (a)[2])) +#define RTW_PUT_BE24(a, val) \ + do { \ + (a)[0] = (u8) ((((u32) (val)) >> 16) & 0xff); \ + (a)[1] = (u8) ((((u32) (val)) >> 8) & 0xff); \ + (a)[2] = (u8) (((u32) (val)) & 0xff); \ + } while (0) + +#define RTW_GET_BE32(a) ((((u32) (a)[0]) << 24) | (((u32) (a)[1]) << 16) | \ + (((u32) (a)[2]) << 8) | ((u32) (a)[3])) +#define RTW_PUT_BE32(a, val) \ + do { \ + (a)[0] = (u8) ((((u32) (val)) >> 24) & 0xff); \ + (a)[1] = (u8) ((((u32) (val)) >> 16) & 0xff); \ + (a)[2] = (u8) ((((u32) (val)) >> 8) & 0xff); \ + (a)[3] = (u8) (((u32) (val)) & 0xff); \ + } while (0) + +#define RTW_GET_LE32(a) ((((u32) (a)[3]) << 24) | (((u32) (a)[2]) << 16) | \ + (((u32) (a)[1]) << 8) | ((u32) (a)[0])) +#define RTW_PUT_LE32(a, val) \ + do { \ + (a)[3] = (u8) ((((u32) (val)) >> 24) & 0xff); \ + (a)[2] = (u8) ((((u32) (val)) >> 16) & 0xff); \ + (a)[1] = (u8) ((((u32) (val)) >> 8) & 0xff); \ + (a)[0] = (u8) (((u32) (val)) & 0xff); \ + } while (0) + +#define RTW_GET_BE64(a) ((((u64) (a)[0]) << 56) | (((u64) (a)[1]) << 48) | \ + (((u64) (a)[2]) << 40) | (((u64) (a)[3]) << 32) | \ + (((u64) (a)[4]) << 24) | (((u64) (a)[5]) << 16) | \ + (((u64) (a)[6]) << 8) | ((u64) (a)[7])) +#define RTW_PUT_BE64(a, val) \ + do { \ + (a)[0] = (u8) (((u64) (val)) >> 56); \ + (a)[1] = (u8) (((u64) (val)) >> 48); \ + (a)[2] = (u8) (((u64) (val)) >> 40); \ + (a)[3] = (u8) (((u64) (val)) >> 32); \ + (a)[4] = (u8) (((u64) (val)) >> 24); \ + (a)[5] = (u8) (((u64) (val)) >> 16); \ + (a)[6] = (u8) (((u64) (val)) >> 8); \ + (a)[7] = (u8) (((u64) (val)) & 0xff); \ + } while (0) + +#define RTW_GET_LE64(a) ((((u64) (a)[7]) << 56) | (((u64) (a)[6]) << 48) | \ + (((u64) (a)[5]) << 40) | (((u64) (a)[4]) << 32) | \ + (((u64) (a)[3]) << 24) | (((u64) (a)[2]) << 16) | \ + (((u64) (a)[1]) << 8) | ((u64) (a)[0])) + +struct osdep_service_ops { + u8* (*rtw_vmalloc)(u32 sz); + u8* (*rtw_zvmalloc)(u32 sz); + void (*rtw_vmfree)(u8 *pbuf, u32 sz); + u8* (*rtw_malloc)(u32 sz); + u8* (*rtw_zmalloc)(u32 sz); + void (*rtw_mfree)(u8 *pbuf, u32 sz); + void (*rtw_memcpy)(void* dst, void* src, u32 sz); + int (*rtw_memcmp)(void *dst, void *src, u32 sz); + void (*rtw_memset)(void *pbuf, int c, u32 sz); + void (*rtw_init_sema)(_sema *sema, int init_val); + void (*rtw_free_sema)(_sema *sema); + void (*rtw_up_sema)(_sema *sema); + u32 (*rtw_down_timeout_sema)(_sema *sema, u32 timeout); + void (*rtw_mutex_init)(_mutex *pmutex); + void (*rtw_mutex_free)(_mutex *pmutex); + void (*rtw_mutex_get)(_mutex *pmutex); + void (*rtw_mutex_put)(_mutex *pmutex); + void (*rtw_enter_critical)(_lock *plock, _irqL *pirqL); + void (*rtw_exit_critical)(_lock *plock, _irqL *pirqL); + void (*rtw_enter_critical_bh)(_lock *plock, _irqL *pirqL); + void (*rtw_exit_critical_bh)(_lock *plock, _irqL *pirqL); + int (*rtw_enter_critical_mutex)(_mutex *pmutex, _irqL *pirqL); + void (*rtw_exit_critical_mutex)(_mutex *pmutex, _irqL *pirqL); + void (*rtw_spinlock_init)(_lock *plock); + void (*rtw_spinlock_free)(_lock *plock); + void (*rtw_spin_lock)(_lock *plock); + void (*rtw_spin_unlock)(_lock *plock); + void (*rtw_spinlock_irqsave)(_lock *plock, _irqL *irqL); + void (*rtw_spinunlock_irqsave)(_lock *plock, _irqL *irqL); + int (*rtw_init_xqueue)( _xqueue* queue, const char* name, u32 message_size, u32 number_of_messages ); + int (*rtw_push_to_xqueue)( _xqueue* queue, void* message, u32 timeout_ms ); + int (*rtw_pop_from_xqueue)( _xqueue* queue, void* message, u32 timeout_ms ); + int (*rtw_deinit_xqueue)( _xqueue* queue ); + u32 (*rtw_get_current_time)(void); + u32 (*rtw_systime_to_ms)(u32 systime); + u32 (*rtw_systime_to_sec)(u32 systime); + u32 (*rtw_ms_to_systime)(u32 ms); + u32 (*rtw_sec_to_systime)(u32 sec); + void (*rtw_msleep_os)(int ms); + void (*rtw_usleep_os)(int us); + void (*rtw_mdelay_os)(int ms); + void (*rtw_udelay_os)(int us); + void (*rtw_yield_os)(void); + void (*rtw_init_timer)(_timer *ptimer, void *adapter, TIMER_FUN pfunc,void* cntx, const char *name); + void (*rtw_set_timer)(_timer *ptimer,u32 delay_time); + u8 (*rtw_cancel_timer)(_timer *ptimer); + void (*rtw_del_timer)(_timer *ptimer); + void (*ATOMIC_SET)(ATOMIC_T *v, int i); + int (*ATOMIC_READ)(ATOMIC_T *v); + void (*ATOMIC_ADD)(ATOMIC_T *v, int i); + void (*ATOMIC_SUB)(ATOMIC_T *v, int i); + void (*ATOMIC_INC)(ATOMIC_T *v); + void (*ATOMIC_DEC)(ATOMIC_T *v); + int (*ATOMIC_ADD_RETURN)(ATOMIC_T *v, int i); + int (*ATOMIC_SUB_RETURN)(ATOMIC_T *v, int i); + int (*ATOMIC_INC_RETURN)(ATOMIC_T *v); + int (*ATOMIC_DEC_RETURN)(ATOMIC_T *v); + u64 (*rtw_modular64)(u64 x, u64 y); + int (*rtw_get_random_bytes)(void* dst, u32 size); + u32 (*rtw_getFreeHeapSize)(void); + int (*rtw_create_task)(struct task_struct *task, const char *name, u32 stack_size, u32 priority, thread_func_t func, void *thctx); + void (*rtw_delete_task)(struct task_struct *task); + void (*rtw_wakeup_task)(struct task_struct *task); + +#if 0 //TODO + void (*rtw_init_delayed_work)(struct delayed_work *dwork, work_func_t func, const char *name); + void (*rtw_deinit_delayed_work)(struct delayed_work *dwork); + int (*rtw_queue_delayed_work)(struct workqueue_struct *wq, struct delayed_work *dwork, unsigned long delay, void* context); + BOOLEAN (*rtw_cancel_delayed_work)(struct delayed_work *dwork); +#endif + void (*rtw_thread_enter)(char *name); + void (*rtw_thread_exit)(void); + _timerHandle (*rtw_timerCreate)( const signed char *pcTimerName, + osdepTickType xTimerPeriodInTicks, + u32 uxAutoReload, + void * pvTimerID, + TIMER_FUN pxCallbackFunction ); + u32 (*rtw_timerDelete)( _timerHandle xTimer, + osdepTickType xBlockTime ); + u32 (*rtw_timerIsTimerActive)( _timerHandle xTimer ); + u32 (*rtw_timerStop)( _timerHandle xTimer, + osdepTickType xBlockTime ); + u32 (*rtw_timerChangePeriod)( _timerHandle xTimer, + osdepTickType xNewPeriod, + osdepTickType xBlockTime ); +}; +/*********************************** OSDEP API end *****************************************/ + + +#endif //#ifndef __OSDEP_SERVICE_H_ diff --git a/component/common/drivers/wlan/realtek/src/osdep/skbuff.h b/component/common/drivers/wlan/realtek/src/osdep/skbuff.h new file mode 100644 index 0000000..8f11a42 --- /dev/null +++ b/component/common/drivers/wlan/realtek/src/osdep/skbuff.h @@ -0,0 +1,54 @@ +#ifndef __SKBUFF_H__ +#define __SKBUFF_H__ + +struct sk_buff_head { + struct list_head *next, *prev; + unsigned int qlen; +}; + +#ifdef CONFIG_TRACE_SKB +#define TRACE_SKB_DEPTH 8 +#endif + +struct sk_buff { + /* These two members must be first. */ + struct sk_buff *next; /* Next buffer in list */ + struct sk_buff *prev; /* Previous buffer in list */ + + struct sk_buff_head *list; /* List we are on */ + unsigned char *head; /* Head of buffer */ + unsigned char *data; /* Data head pointer */ + unsigned char *tail; /* Tail pointer */ + unsigned char *end; /* End pointer */ + void *dev; /* Device we arrived on/are leaving by */ + unsigned int len; /* Length of actual data */ +#ifdef CONFIG_TRACE_SKB + unsigned int liston[TRACE_SKB_DEPTH]; /* Trace the Lists we went through */ + const char *funcname[TRACE_SKB_DEPTH]; + unsigned int list_idx; /* Trace the List we are on */ +#endif +}; + +unsigned char *skb_put(struct sk_buff *skb, unsigned int len); +unsigned char *skb_pull(struct sk_buff *skb, unsigned int len); +void skb_reserve(struct sk_buff *skb, unsigned int len); +void skb_assign_buf(struct sk_buff *skb, unsigned char *buf, unsigned int len); +unsigned char *skb_tail_pointer(const struct sk_buff *skb); +void skb_set_tail_pointer(struct sk_buff *skb, const int offset); +unsigned char *skb_end_pointer(const struct sk_buff *skb); + +void init_skb_pool(void); +void init_skb_data_pool(void); + +#ifndef CONFIG_DONT_CARE_TP +struct sk_buff *dev_alloc_skb(unsigned int length, unsigned int reserve_len); +#else +struct sk_buff *dev_alloc_tx_skb(unsigned int length, unsigned int reserve_len); +struct sk_buff *dev_alloc_rx_skb(unsigned int length, unsigned int reserve_len); +#define dev_alloc_skb dev_alloc_tx_skb +#endif +void kfree_skb(struct sk_buff *skb); + + +#endif //__SKBUFF_H__ + diff --git a/component/common/drivers/wlan/realtek/src/osdep/wireless.h b/component/common/drivers/wlan/realtek/src/osdep/wireless.h new file mode 100644 index 0000000..9fcf208 --- /dev/null +++ b/component/common/drivers/wlan/realtek/src/osdep/wireless.h @@ -0,0 +1,1206 @@ +/* + * This file define a set of standard wireless extensions + * + * Version : 22 16.3.07 + * + * Authors : Jean Tourrilhes - HPL - + * Copyright (c) 1997-2007 Jean Tourrilhes, All Rights Reserved. + */ + +#ifndef _LINUX_WIRELESS_H +#define _LINUX_WIRELESS_H + +/************************** DOCUMENTATION **************************/ +/* + * Initial APIs (1996 -> onward) : + * ----------------------------- + * Basically, the wireless extensions are for now a set of standard ioctl + * call + /proc/net/wireless + * + * The entry /proc/net/wireless give statistics and information on the + * driver. + * This is better than having each driver having its entry because + * its centralised and we may remove the driver module safely. + * + * Ioctl are used to configure the driver and issue commands. This is + * better than command line options of insmod because we may want to + * change dynamically (while the driver is running) some parameters. + * + * The ioctl mechanimsm are copied from standard devices ioctl. + * We have the list of command plus a structure descibing the + * data exchanged... + * Note that to add these ioctl, I was obliged to modify : + * # net/core/dev.c (two place + add include) + * # net/ipv4/af_inet.c (one place + add include) + * + * /proc/net/wireless is a copy of /proc/net/dev. + * We have a structure for data passed from the driver to /proc/net/wireless + * Too add this, I've modified : + * # net/core/dev.c (two other places) + * # include/linux/netdevice.h (one place) + * # include/linux/proc_fs.h (one place) + * + * New driver API (2002 -> onward) : + * ------------------------------- + * This file is only concerned with the user space API and common definitions. + * The new driver API is defined and documented in : + * # include/net/iw_handler.h + * + * Note as well that /proc/net/wireless implementation has now moved in : + * # net/core/wireless.c + * + * Wireless Events (2002 -> onward) : + * -------------------------------- + * Events are defined at the end of this file, and implemented in : + * # net/core/wireless.c + * + * Other comments : + * -------------- + * Do not add here things that are redundant with other mechanisms + * (drivers init, ifconfig, /proc/net/dev, ...) and with are not + * wireless specific. + * + * These wireless extensions are not magic : each driver has to provide + * support for them... + * + * IMPORTANT NOTE : As everything in the kernel, this is very much a + * work in progress. Contact me if you have ideas of improvements... + */ + +/***************************** INCLUDES *****************************/ + +/* This header is used in user-space, therefore need to be sanitised + * for that purpose. Those includes are usually not compatible with glibc. + * To know which includes to use in user-space, check iwlib.h. */ +#ifdef __KERNEL__ +#include /* for "caddr_t" et al */ +#include /* for "struct sockaddr" et al */ +#include /* for IFNAMSIZ and co... */ +#endif /* __KERNEL__ */ + +//#include +#define IFNAMSIZ 16 +#define ARPHRD_ETHER 1 /* ethernet hardware format */ + +/***************************** VERSION *****************************/ +/* + * This constant is used to know the availability of the wireless + * extensions and to know which version of wireless extensions it is + * (there is some stuff that will be added in the future...) + * I just plan to increment with each new version. + */ +#define WIRELESS_EXT 22 + +/* + * Changes : + * + * V2 to V3 + * -------- + * Alan Cox start some incompatibles changes. I've integrated a bit more. + * - Encryption renamed to Encode to avoid US regulation problems + * - Frequency changed from float to struct to avoid problems on old 386 + * + * V3 to V4 + * -------- + * - Add sensitivity + * + * V4 to V5 + * -------- + * - Missing encoding definitions in range + * - Access points stuff + * + * V5 to V6 + * -------- + * - 802.11 support (ESSID ioctls) + * + * V6 to V7 + * -------- + * - define IW_ESSID_MAX_SIZE and IW_MAX_AP + * + * V7 to V8 + * -------- + * - Changed my e-mail address + * - More 802.11 support (nickname, rate, rts, frag) + * - List index in frequencies + * + * V8 to V9 + * -------- + * - Support for 'mode of operation' (ad-hoc, managed...) + * - Support for unicast and multicast power saving + * - Change encoding to support larger tokens (>64 bits) + * - Updated iw_params (disable, flags) and use it for NWID + * - Extracted iw_point from iwreq for clarity + * + * V9 to V10 + * --------- + * - Add PM capability to range structure + * - Add PM modifier : MAX/MIN/RELATIVE + * - Add encoding option : IW_ENCODE_NOKEY + * - Add TxPower ioctls (work like TxRate) + * + * V10 to V11 + * ---------- + * - Add WE version in range (help backward/forward compatibility) + * - Add retry ioctls (work like PM) + * + * V11 to V12 + * ---------- + * - Add SIOCSIWSTATS to get /proc/net/wireless programatically + * - Add DEV PRIVATE IOCTL to avoid collisions in SIOCDEVPRIVATE space + * - Add new statistics (frag, retry, beacon) + * - Add average quality (for user space calibration) + * + * V12 to V13 + * ---------- + * - Document creation of new driver API. + * - Extract union iwreq_data from struct iwreq (for new driver API). + * - Rename SIOCSIWNAME as SIOCSIWCOMMIT + * + * V13 to V14 + * ---------- + * - Wireless Events support : define struct iw_event + * - Define additional specific event numbers + * - Add "addr" and "param" fields in union iwreq_data + * - AP scanning stuff (SIOCSIWSCAN and friends) + * + * V14 to V15 + * ---------- + * - Add IW_PRIV_TYPE_ADDR for struct sockaddr private arg + * - Make struct iw_freq signed (both m & e), add explicit padding + * - Add IWEVCUSTOM for driver specific event/scanning token + * - Add IW_MAX_GET_SPY for driver returning a lot of addresses + * - Add IW_TXPOW_RANGE for range of Tx Powers + * - Add IWEVREGISTERED & IWEVEXPIRED events for Access Points + * - Add IW_MODE_MONITOR for passive monitor + * + * V15 to V16 + * ---------- + * - Increase the number of bitrates in iw_range to 32 (for 802.11g) + * - Increase the number of frequencies in iw_range to 32 (for 802.11b+a) + * - Reshuffle struct iw_range for increases, add filler + * - Increase IW_MAX_AP to 64 for driver returning a lot of addresses + * - Remove IW_MAX_GET_SPY because conflict with enhanced spy support + * - Add SIOCSIWTHRSPY/SIOCGIWTHRSPY and "struct iw_thrspy" + * - Add IW_ENCODE_TEMP and iw_range->encoding_login_index + * + * V16 to V17 + * ---------- + * - Add flags to frequency -> auto/fixed + * - Document (struct iw_quality *)->updated, add new flags (INVALID) + * - Wireless Event capability in struct iw_range + * - Add support for relative TxPower (yick !) + * + * V17 to V18 (From Jouni Malinen ) + * ---------- + * - Add support for WPA/WPA2 + * - Add extended encoding configuration (SIOCSIWENCODEEXT and + * SIOCGIWENCODEEXT) + * - Add SIOCSIWGENIE/SIOCGIWGENIE + * - Add SIOCSIWMLME + * - Add SIOCSIWPMKSA + * - Add struct iw_range bit field for supported encoding capabilities + * - Add optional scan request parameters for SIOCSIWSCAN + * - Add SIOCSIWAUTH/SIOCGIWAUTH for setting authentication and WPA + * related parameters (extensible up to 4096 parameter values) + * - Add wireless events: IWEVGENIE, IWEVMICHAELMICFAILURE, + * IWEVASSOCREQIE, IWEVASSOCRESPIE, IWEVPMKIDCAND + * + * V18 to V19 + * ---------- + * - Remove (struct iw_point *)->pointer from events and streams + * - Remove header includes to help user space + * - Increase IW_ENCODING_TOKEN_MAX from 32 to 64 + * - Add IW_QUAL_ALL_UPDATED and IW_QUAL_ALL_INVALID macros + * - Add explicit flag to tell stats are in dBm : IW_QUAL_DBM + * - Add IW_IOCTL_IDX() and IW_EVENT_IDX() macros + * + * V19 to V20 + * ---------- + * - RtNetlink requests support (SET/GET) + * + * V20 to V21 + * ---------- + * - Remove (struct net_device *)->get_wireless_stats() + * - Change length in ESSID and NICK to strlen() instead of strlen()+1 + * - Add IW_RETRY_SHORT/IW_RETRY_LONG retry modifiers + * - Power/Retry relative values no longer * 100000 + * - Add explicit flag to tell stats are in 802.11k RCPI : IW_QUAL_RCPI + * + * V21 to V22 + * ---------- + * - Prevent leaking of kernel space in stream on 64 bits. + */ + +/**************************** CONSTANTS ****************************/ +typedef unsigned char __u8; +typedef char __s8; +typedef unsigned short __u16; +typedef short __s16; +typedef unsigned int __u32; +typedef int __s32; +typedef unsigned long long __u64; +typedef long long __i64; + +#define E2BIG 7 /* Argument list too long */ + +#define ETH_ALEN 6 /* Octets in one ethernet addr */ + +/* Device private ioctl calls */ + +/* + * These 16 ioctls are available to devices via the do_ioctl() device + * vector. Each device should include this file and redefine these names + * as their own. Because these are device dependent it is a good idea + * _NOT_ to issue them to random objects and hope. + * + * THESE IOCTLS ARE _DEPRECATED_ AND WILL DISAPPEAR IN 2.5.X -DaveM + */ + +#define SIOCDEVPRIVATE 0x89F0 /* to 89FF */ + +/* + * These 16 ioctl calls are protocol private + */ + +#define SIOCPROTOPRIVATE 0x89E0 /* to 89EF */ + +/* -------------------------- IOCTL LIST -------------------------- */ + +/* Wireless Identification */ +#define SIOCSIWCOMMIT 0x8B00 /* Commit pending changes to driver */ +#define SIOCGIWNAME 0x8B01 /* get name == wireless protocol */ +/* SIOCGIWNAME is used to verify the presence of Wireless Extensions. + * Common values : "IEEE 802.11-DS", "IEEE 802.11-FH", "IEEE 802.11b"... + * Don't put the name of your driver there, it's useless. */ + +/* Basic operations */ +#define SIOCSIWNWID 0x8B02 /* set network id (pre-802.11) */ +#define SIOCGIWNWID 0x8B03 /* get network id (the cell) */ +#define SIOCSIWFREQ 0x8B04 /* set channel/frequency (Hz) */ +#define SIOCGIWFREQ 0x8B05 /* get channel/frequency (Hz) */ +#define SIOCSIWMODE 0x8B06 /* set operation mode */ +#define SIOCGIWMODE 0x8B07 /* get operation mode */ +#define SIOCSIWSENS 0x8B08 /* set sensitivity (dBm) */ +#define SIOCGIWSENS 0x8B09 /* get sensitivity (dBm) */ + +/* Informative stuff */ +#define SIOCSIWRANGE 0x8B0A /* Unused */ +#define SIOCGIWRANGE 0x8B0B /* Get range of parameters */ +#define SIOCSIWPRIV 0x8B0C /* Unused */ +#define SIOCGIWPRIV 0x8B0D /* get private ioctl interface info */ +#define SIOCSIWSTATS 0x8B0E /* Unused */ +#define SIOCGIWSTATS 0x8B0F /* Get /proc/net/wireless stats */ +/* SIOCGIWSTATS is strictly used between user space and the kernel, and + * is never passed to the driver (i.e. the driver will never see it). */ + +/* Spy support (statistics per MAC address - used for Mobile IP support) */ +#define SIOCSIWSPY 0x8B10 /* set spy addresses */ +#define SIOCGIWSPY 0x8B11 /* get spy info (quality of link) */ +#define SIOCSIWTHRSPY 0x8B12 /* set spy threshold (spy event) */ +#define SIOCGIWTHRSPY 0x8B13 /* get spy threshold */ + +/* Access Point manipulation */ +#define SIOCSIWAP 0x8B14 /* set access point MAC addresses */ +#define SIOCGIWAP 0x8B15 /* get access point MAC addresses */ +#define SIOCGIWAPLIST 0x8B17 /* Deprecated in favor of scanning */ +#define SIOCSIWSCAN 0x8B18 /* trigger scanning (list cells) */ +#define SIOCGIWSCAN 0x8B19 /* get scanning results */ + +/* 802.11 specific support */ +#define SIOCSIWESSID 0x8B1A /* set ESSID (network name) */ +#define SIOCGIWESSID 0x8B1B /* get ESSID */ +#define SIOCSIWNICKN 0x8B1C /* set node name/nickname */ +#define SIOCGIWNICKN 0x8B1D /* get node name/nickname */ +/* As the ESSID and NICKN are strings up to 32 bytes long, it doesn't fit + * within the 'iwreq' structure, so we need to use the 'data' member to + * point to a string in user space, like it is done for RANGE... */ + +/* Other parameters useful in 802.11 and some other devices */ +#define SIOCSIWRATE 0x8B20 /* set default bit rate (bps) */ +#define SIOCGIWRATE 0x8B21 /* get default bit rate (bps) */ +#define SIOCSIWRTS 0x8B22 /* set RTS/CTS threshold (bytes) */ +#define SIOCGIWRTS 0x8B23 /* get RTS/CTS threshold (bytes) */ +#define SIOCSIWFRAG 0x8B24 /* set fragmentation thr (bytes) */ +#define SIOCGIWFRAG 0x8B25 /* get fragmentation thr (bytes) */ +#define SIOCSIWTXPOW 0x8B26 /* set transmit power (dBm) */ +#define SIOCGIWTXPOW 0x8B27 /* get transmit power (dBm) */ +#define SIOCSIWRETRY 0x8B28 /* set retry limits and lifetime */ +#define SIOCGIWRETRY 0x8B29 /* get retry limits and lifetime */ + +/* Encoding stuff (scrambling, hardware security, WEP...) */ +#define SIOCSIWENCODE 0x8B2A /* set encoding token & mode */ +#define SIOCGIWENCODE 0x8B2B /* get encoding token & mode */ +/* Power saving stuff (power management, unicast and multicast) */ +#define SIOCSIWPOWER 0x8B2C /* set Power Management settings */ +#define SIOCGIWPOWER 0x8B2D /* get Power Management settings */ +/* Modulation bitmask */ +#define SIOCSIWMODUL 0x8B2E /* set Modulations settings */ +#define SIOCGIWMODUL 0x8B2F /* get Modulations settings */ + +/* WPA : Generic IEEE 802.11 informatiom element (e.g., for WPA/RSN/WMM). + * This ioctl uses struct iw_point and data buffer that includes IE id and len + * fields. More than one IE may be included in the request. Setting the generic + * IE to empty buffer (len=0) removes the generic IE from the driver. Drivers + * are allowed to generate their own WPA/RSN IEs, but in these cases, drivers + * are required to report the used IE as a wireless event, e.g., when + * associating with an AP. */ +#define SIOCSIWGENIE 0x8B30 /* set generic IE */ +#define SIOCGIWGENIE 0x8B31 /* get generic IE */ + +/* WPA : IEEE 802.11 MLME requests */ +#define SIOCSIWMLME 0x8B16 /* request MLME operation; uses + * struct iw_mlme */ +/* WPA : Authentication mode parameters */ +#define SIOCSIWAUTH 0x8B32 /* set authentication mode params */ +#define SIOCGIWAUTH 0x8B33 /* get authentication mode params */ + +/* WPA : Extended version of encoding configuration */ +#define SIOCSIWENCODEEXT 0x8B34 /* set encoding token & mode */ +#define SIOCGIWENCODEEXT 0x8B35 /* get encoding token & mode */ + +/* WPA2 : PMKSA cache management */ +#define SIOCSIWPMKSA 0x8B36 /* PMKSA cache operation */ + +/* Send Mgnt Frame or Action Frame */ +#define SIOCSIWMGNTSEND 0x8B37 /* Send Mgnt Frame or Action Frame */ + +/* -------------------- DEV PRIVATE IOCTL LIST -------------------- */ + +/* These 32 ioctl are wireless device private, for 16 commands. + * Each driver is free to use them for whatever purpose it chooses, + * however the driver *must* export the description of those ioctls + * with SIOCGIWPRIV and *must* use arguments as defined below. + * If you don't follow those rules, DaveM is going to hate you (reason : + * it make mixed 32/64bit operation impossible). + */ +#define SIOCIWFIRSTPRIV 0x8BE0 +#define SIOCIWLASTPRIV 0x8BFF + +#define SIOCGIWPRIVPASSPHRASE 0x8BFC +#define SIOCSIWPRIVCOUNTRY 0x8BFD +#define SIOCSIWPRIVAPESSID 0x8BFE +#define SIOCSIWPRIVPASSPHRASE 0x8BFF +/* Previously, we were using SIOCDEVPRIVATE, but we now have our + * separate range because of collisions with other tools such as + * 'mii-tool'. + * We now have 32 commands, so a bit more space ;-). + * Also, all 'even' commands are only usable by root and don't return the + * content of ifr/iwr to user (but you are not obliged to use the set/get + * convention, just use every other two command). More details in iwpriv.c. + * And I repeat : you are not forced to use them with iwpriv, but you + * must be compliant with it. + */ + +/* ------------------------- IOCTL STUFF ------------------------- */ + +/* The first and the last (range) */ +#define SIOCIWFIRST 0x8B00 +#define SIOCIWLAST SIOCIWLASTPRIV /* 0x8BFF */ +#define IW_IOCTL_IDX(cmd) ((cmd) - SIOCIWFIRST) + +/* Odd : get (world access), even : set (root access) */ +#define IW_IS_SET(cmd) (!((cmd) & 0x1)) +#define IW_IS_GET(cmd) ((cmd) & 0x1) + +/* ----------------------- WIRELESS EVENTS ----------------------- */ +/* Those are *NOT* ioctls, do not issue request on them !!! */ +/* Most events use the same identifier as ioctl requests */ + +#define IWEVTXDROP 0x8C00 /* Packet dropped to excessive retry */ +#define IWEVQUAL 0x8C01 /* Quality part of statistics (scan) */ +#define IWEVCUSTOM 0x8C02 /* Driver specific ascii string */ +#define IWEVREGISTERED 0x8C03 /* Discovered a new node (AP mode) */ +#define IWEVEXPIRED 0x8C04 /* Expired a node (AP mode) */ +#define IWEVGENIE 0x8C05 /* Generic IE (WPA, RSN, WMM, ..) + * (scan results); This includes id and + * length fields. One IWEVGENIE may + * contain more than one IE. Scan + * results may contain one or more + * IWEVGENIE events. */ +#define IWEVMICHAELMICFAILURE 0x8C06 /* Michael MIC failure + * (struct iw_michaelmicfailure) + */ +#define IWEVASSOCREQIE 0x8C07 /* IEs used in (Re)Association Request. + * The data includes id and length + * fields and may contain more than one + * IE. This event is required in + * Managed mode if the driver + * generates its own WPA/RSN IE. This + * should be sent just before + * IWEVREGISTERED event for the + * association. */ +#define IWEVASSOCRESPIE 0x8C08 /* IEs used in (Re)Association + * Response. The data includes id and + * length fields and may contain more + * than one IE. This may be sent + * between IWEVASSOCREQIE and + * IWEVREGISTERED events for the + * association. */ +#define IWEVPMKIDCAND 0x8C09 /* PMKID candidate for RSN + * pre-authentication + * (struct iw_pmkid_cand) */ + +#define IWEVFIRST 0x8C00 +#define IW_EVENT_IDX(cmd) ((cmd) - IWEVFIRST) + +/* Indicate Mgnt Frame and Action Frame to uplayer*/ +#define IWEVMGNTRECV 0x8C10 /* Indicate Mgnt Frame to uplayer */ + +/* ------------------------- PRIVATE INFO ------------------------- */ +/* + * The following is used with SIOCGIWPRIV. It allow a driver to define + * the interface (name, type of data) for its private ioctl. + * Privates ioctl are SIOCIWFIRSTPRIV -> SIOCIWLASTPRIV + */ + +#define IW_PRIV_TYPE_MASK 0x7000 /* Type of arguments */ +#define IW_PRIV_TYPE_NONE 0x0000 +#define IW_PRIV_TYPE_BYTE 0x1000 /* Char as number */ +#define IW_PRIV_TYPE_CHAR 0x2000 /* Char as character */ +#define IW_PRIV_TYPE_INT 0x4000 /* 32 bits int */ +#define IW_PRIV_TYPE_FLOAT 0x5000 /* struct iw_freq */ +#define IW_PRIV_TYPE_ADDR 0x6000 /* struct sockaddr */ + +#define IW_PRIV_SIZE_FIXED 0x0800 /* Variable or fixed number of args */ + +#define IW_PRIV_SIZE_MASK 0x07FF /* Max number of those args */ + +/* + * Note : if the number of args is fixed and the size < 16 octets, + * instead of passing a pointer we will put args in the iwreq struct... + */ + +/* ----------------------- OTHER CONSTANTS ----------------------- */ + +/* Maximum frequencies in the range struct */ +#define IW_MAX_FREQUENCIES 32 +/* Note : if you have something like 80 frequencies, + * don't increase this constant and don't fill the frequency list. + * The user will be able to set by channel anyway... */ + +/* Maximum bit rates in the range struct */ +#define IW_MAX_BITRATES 32 + +/* Maximum tx powers in the range struct */ +#define IW_MAX_TXPOWER 8 +/* Note : if you more than 8 TXPowers, just set the max and min or + * a few of them in the struct iw_range. */ + +/* Maximum of address that you may set with SPY */ +#define IW_MAX_SPY 8 + +/* Maximum of address that you may get in the + list of access points in range */ +#define IW_MAX_AP 64 + +/* Maximum size of the ESSID and NICKN strings */ +#define IW_ESSID_MAX_SIZE 32 + +/* Modes of operation */ +#define IW_MODE_AUTO 0 /* Let the driver decides */ +#define IW_MODE_ADHOC 1 /* Single cell network */ +#define IW_MODE_INFRA 2 /* Multi cell network, roaming, ... */ +#define IW_MODE_MASTER 3 /* Synchronisation master or Access Point */ +#define IW_MODE_REPEAT 4 /* Wireless Repeater (forwarder) */ +#define IW_MODE_SECOND 5 /* Secondary master/repeater (backup) */ +#define IW_MODE_MONITOR 6 /* Passive monitor (listen only) */ + +/* Statistics flags (bitmask in updated) */ +#define IW_QUAL_QUAL_UPDATED 0x01 /* Value was updated since last read */ +#define IW_QUAL_LEVEL_UPDATED 0x02 +#define IW_QUAL_NOISE_UPDATED 0x04 +#define IW_QUAL_ALL_UPDATED 0x07 +#define IW_QUAL_DBM 0x08 /* Level + Noise are dBm */ +#define IW_QUAL_QUAL_INVALID 0x10 /* Driver doesn't provide value */ +#define IW_QUAL_LEVEL_INVALID 0x20 +#define IW_QUAL_NOISE_INVALID 0x40 +#define IW_QUAL_RCPI 0x80 /* Level + Noise are 802.11k RCPI */ +#define IW_QUAL_ALL_INVALID 0x70 + +/* Frequency flags */ +#define IW_FREQ_AUTO 0x00 /* Let the driver decides */ +#define IW_FREQ_FIXED 0x01 /* Force a specific value */ + +/* Maximum number of size of encoding token available + * they are listed in the range structure */ +#define IW_MAX_ENCODING_SIZES 8 + +/* Maximum size of the encoding token in bytes */ +#define IW_ENCODING_TOKEN_MAX 64 /* 512 bits (for now) */ + +/* Flags for encoding (along with the token) */ +#define IW_ENCODE_INDEX 0x00FF /* Token index (if needed) */ +#define IW_ENCODE_FLAGS 0xFF00 /* Flags defined below */ +#define IW_ENCODE_MODE 0xF000 /* Modes defined below */ +#define IW_ENCODE_DISABLED 0x8000 /* Encoding disabled */ +#define IW_ENCODE_ENABLED 0x0000 /* Encoding enabled */ +#define IW_ENCODE_RESTRICTED 0x4000 /* Refuse non-encoded packets */ +#define IW_ENCODE_OPEN 0x2000 /* Accept non-encoded packets */ +#define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */ +#define IW_ENCODE_TEMP 0x0400 /* Temporary key */ + +/* Power management flags available (along with the value, if any) */ +#define IW_POWER_ON 0x0000 /* No details... */ +#define IW_POWER_TYPE 0xF000 /* Type of parameter */ +#define IW_POWER_PERIOD 0x1000 /* Value is a period/duration of */ +#define IW_POWER_TIMEOUT 0x2000 /* Value is a timeout (to go asleep) */ +#define IW_POWER_SAVING 0x4000 /* Value is relative (how aggressive)*/ +#define IW_POWER_MODE 0x0F00 /* Power Management mode */ +#define IW_POWER_UNICAST_R 0x0100 /* Receive only unicast messages */ +#define IW_POWER_MULTICAST_R 0x0200 /* Receive only multicast messages */ +#define IW_POWER_ALL_R 0x0300 /* Receive all messages though PM */ +#define IW_POWER_FORCE_S 0x0400 /* Force PM procedure for sending unicast */ +#define IW_POWER_REPEATER 0x0800 /* Repeat broadcast messages in PM period */ +#define IW_POWER_MODIFIER 0x000F /* Modify a parameter */ +#define IW_POWER_MIN 0x0001 /* Value is a minimum */ +#define IW_POWER_MAX 0x0002 /* Value is a maximum */ +#define IW_POWER_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ + +/* Transmit Power flags available */ +#define IW_TXPOW_TYPE 0x00FF /* Type of value */ +#define IW_TXPOW_DBM 0x0000 /* Value is in dBm */ +#define IW_TXPOW_MWATT 0x0001 /* Value is in mW */ +#define IW_TXPOW_RELATIVE 0x0002 /* Value is in arbitrary units */ +#define IW_TXPOW_RANGE 0x1000 /* Range of value between min/max */ + +/* Retry limits and lifetime flags available */ +#define IW_RETRY_ON 0x0000 /* No details... */ +#define IW_RETRY_TYPE 0xF000 /* Type of parameter */ +#define IW_RETRY_LIMIT 0x1000 /* Maximum number of retries*/ +#define IW_RETRY_LIFETIME 0x2000 /* Maximum duration of retries in us */ +#define IW_RETRY_MODIFIER 0x00FF /* Modify a parameter */ +#define IW_RETRY_MIN 0x0001 /* Value is a minimum */ +#define IW_RETRY_MAX 0x0002 /* Value is a maximum */ +#define IW_RETRY_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ +#define IW_RETRY_SHORT 0x0010 /* Value is for short packets */ +#define IW_RETRY_LONG 0x0020 /* Value is for long packets */ + +/* Scanning request flags */ +#define IW_SCAN_DEFAULT 0x0000 /* Default scan of the driver */ +#define IW_SCAN_ALL_ESSID 0x0001 /* Scan all ESSIDs */ +#define IW_SCAN_THIS_ESSID 0x0002 /* Scan only this ESSID */ +#define IW_SCAN_ALL_FREQ 0x0004 /* Scan all Frequencies */ +#define IW_SCAN_THIS_FREQ 0x0008 /* Scan only this Frequency */ +#define IW_SCAN_ALL_MODE 0x0010 /* Scan all Modes */ +#define IW_SCAN_THIS_MODE 0x0020 /* Scan only this Mode */ +#define IW_SCAN_ALL_RATE 0x0040 /* Scan all Bit-Rates */ +#define IW_SCAN_THIS_RATE 0x0080 /* Scan only this Bit-Rate */ +/* struct iw_scan_req scan_type */ +#define IW_SCAN_TYPE_ACTIVE 0 +#define IW_SCAN_TYPE_PASSIVE 1 +/* Maximum size of returned data */ +#define IW_SCAN_MAX_DATA 4096 /* In bytes */ + +/* Max number of char in custom event - use multiple of them if needed */ +#define IW_CUSTOM_MAX 256 /* In bytes */ + +/* Generic information element */ +#define IW_GENERIC_IE_MAX 1024 + +/* MLME requests (SIOCSIWMLME / struct iw_mlme) */ +#define IW_MLME_DEAUTH 0 +#define IW_MLME_DISASSOC 1 +#define IW_MLME_AUTH 2 +#define IW_MLME_ASSOC 3 + +/* SIOCSIWAUTH/SIOCGIWAUTH struct iw_param flags */ +#define IW_AUTH_INDEX 0x0FFF +#define IW_AUTH_FLAGS 0xF000 +/* SIOCSIWAUTH/SIOCGIWAUTH parameters (0 .. 4095) + * (IW_AUTH_INDEX mask in struct iw_param flags; this is the index of the + * parameter that is being set/get to; value will be read/written to + * struct iw_param value field) */ +#define IW_AUTH_WPA_VERSION 0 +#define IW_AUTH_CIPHER_PAIRWISE 1 +#define IW_AUTH_CIPHER_GROUP 2 +#define IW_AUTH_KEY_MGMT 3 +#define IW_AUTH_TKIP_COUNTERMEASURES 4 +#define IW_AUTH_DROP_UNENCRYPTED 5 +#define IW_AUTH_80211_AUTH_ALG 6 +#define IW_AUTH_WPA_ENABLED 7 +#define IW_AUTH_RX_UNENCRYPTED_EAPOL 8 +#define IW_AUTH_ROAMING_CONTROL 9 +#define IW_AUTH_PRIVACY_INVOKED 10 + +/* IW_AUTH_WPA_VERSION values (bit field) */ +#define IW_AUTH_WPA_VERSION_DISABLED 0x00000001 +#define IW_AUTH_WPA_VERSION_WPA 0x00000002 +#define IW_AUTH_WPA_VERSION_WPA2 0x00000004 + +/* IW_AUTH_PAIRWISE_CIPHER and IW_AUTH_GROUP_CIPHER values (bit field) */ +#define IW_AUTH_CIPHER_NONE 0x00000001 +#define IW_AUTH_CIPHER_WEP40 0x00000002 +#define IW_AUTH_CIPHER_TKIP 0x00000004 +#define IW_AUTH_CIPHER_CCMP 0x00000008 +#define IW_AUTH_CIPHER_WEP104 0x00000010 + +/* IW_AUTH_KEY_MGMT values (bit field) */ +#define IW_AUTH_KEY_MGMT_802_1X 1 +#define IW_AUTH_KEY_MGMT_PSK 2 + +/* IW_AUTH_80211_AUTH_ALG values (bit field) */ +#define IW_AUTH_ALG_OPEN_SYSTEM 0x00000001 +#define IW_AUTH_ALG_SHARED_KEY 0x00000002 +#define IW_AUTH_ALG_LEAP 0x00000004 + +/* IW_AUTH_ROAMING_CONTROL values */ +#define IW_AUTH_ROAMING_ENABLE 0 /* driver/firmware based roaming */ +#define IW_AUTH_ROAMING_DISABLE 1 /* user space program used for roaming + * control */ + +/* SIOCSIWENCODEEXT definitions */ +#define IW_ENCODE_SEQ_MAX_SIZE 8 +/* struct iw_encode_ext ->alg */ +#define IW_ENCODE_ALG_NONE 0 +#define IW_ENCODE_ALG_WEP 1 +#define IW_ENCODE_ALG_TKIP 2 +#define IW_ENCODE_ALG_CCMP 3 +/* struct iw_encode_ext ->ext_flags */ +#define IW_ENCODE_EXT_TX_SEQ_VALID 0x00000001 +#define IW_ENCODE_EXT_RX_SEQ_VALID 0x00000002 +#define IW_ENCODE_EXT_GROUP_KEY 0x00000004 +#define IW_ENCODE_EXT_SET_TX_KEY 0x00000008 + +/* IWEVMICHAELMICFAILURE : struct iw_michaelmicfailure ->flags */ +#define IW_MICFAILURE_KEY_ID 0x00000003 /* Key ID 0..3 */ +#define IW_MICFAILURE_GROUP 0x00000004 +#define IW_MICFAILURE_PAIRWISE 0x00000008 +#define IW_MICFAILURE_STAKEY 0x00000010 +#define IW_MICFAILURE_COUNT 0x00000060 /* 1 or 2 (0 = count not supported) + */ + +/* Bit field values for enc_capa in struct iw_range */ +#define IW_ENC_CAPA_WPA 0x00000001 +#define IW_ENC_CAPA_WPA2 0x00000002 +#define IW_ENC_CAPA_CIPHER_TKIP 0x00000004 +#define IW_ENC_CAPA_CIPHER_CCMP 0x00000008 + +/* Event capability macros - in (struct iw_range *)->event_capa + * Because we have more than 32 possible events, we use an array of + * 32 bit bitmasks. Note : 32 bits = 0x20 = 2^5. */ +#define IW_EVENT_CAPA_BASE(cmd) ((cmd >= SIOCIWFIRSTPRIV) ? \ + (cmd - SIOCIWFIRSTPRIV + 0x60) : \ + (cmd - SIOCSIWCOMMIT)) +#define IW_EVENT_CAPA_INDEX(cmd) (IW_EVENT_CAPA_BASE(cmd) >> 5) +#define IW_EVENT_CAPA_MASK(cmd) (1 << (IW_EVENT_CAPA_BASE(cmd) & 0x1F)) +/* Event capability constants - event autogenerated by the kernel + * This list is valid for most 802.11 devices, customise as needed... */ +#define IW_EVENT_CAPA_K_0 (IW_EVENT_CAPA_MASK(0x8B04) | \ + IW_EVENT_CAPA_MASK(0x8B06) | \ + IW_EVENT_CAPA_MASK(0x8B1A)) +#define IW_EVENT_CAPA_K_1 (IW_EVENT_CAPA_MASK(0x8B2A)) +/* "Easy" macro to set events in iw_range (less efficient) */ +#define IW_EVENT_CAPA_SET(event_capa, cmd) (event_capa[IW_EVENT_CAPA_INDEX(cmd)] |= IW_EVENT_CAPA_MASK(cmd)) +#define IW_EVENT_CAPA_SET_KERNEL(event_capa) {event_capa[0] |= IW_EVENT_CAPA_K_0; event_capa[1] |= IW_EVENT_CAPA_K_1; } + +/* Modulations bitmasks */ +#define IW_MODUL_ALL 0x00000000 /* Everything supported */ +#define IW_MODUL_FH 0x00000001 /* Frequency Hopping */ +#define IW_MODUL_DS 0x00000002 /* Original Direct Sequence */ +#define IW_MODUL_CCK 0x00000004 /* 802.11b : 5.5 + 11 Mb/s */ +#define IW_MODUL_11B (IW_MODUL_DS | IW_MODUL_CCK) +#define IW_MODUL_PBCC 0x00000008 /* TI : 5.5 + 11 + 22 Mb/s */ +#define IW_MODUL_OFDM_A 0x00000010 /* 802.11a : 54 Mb/s */ +#define IW_MODUL_11A (IW_MODUL_OFDM_A) +#define IW_MODUL_11AB (IW_MODUL_11B | IW_MODUL_11A) +#define IW_MODUL_OFDM_G 0x00000020 /* 802.11g : 54 Mb/s */ +#define IW_MODUL_11G (IW_MODUL_11B | IW_MODUL_OFDM_G) +#define IW_MODUL_11AG (IW_MODUL_11G | IW_MODUL_11A) +#define IW_MODUL_TURBO 0x00000040 /* ATH : bonding, 108 Mb/s */ +/* In here we should define MIMO stuff. Later... */ +#define IW_MODUL_CUSTOM 0x40000000 /* Driver specific */ + +/* Bitrate flags available */ +#define IW_BITRATE_TYPE 0x00FF /* Type of value */ +#define IW_BITRATE_UNICAST 0x0001 /* Maximum/Fixed unicast bitrate */ +#define IW_BITRATE_BROADCAST 0x0002 /* Fixed broadcast bitrate */ + +/****************************** TYPES ******************************/ + +/* --------------------------- SUBTYPES --------------------------- */ + +struct sockaddr_t { + __u8 sa_len; + __u8 sa_family; + char sa_data[14]; +}; + +/* + * Generic format for most parameters that fit in an int + */ +struct iw_param +{ + __s32 value; /* The value of the parameter itself */ + __u8 fixed; /* Hardware should not use auto select */ + __u8 disabled; /* Disable the feature */ + __u16 flags; /* Various specifc flags (if any) */ +}; + +/* + * For all data larger than 16 octets, we need to use a + * pointer to memory allocated in user space. + */ +struct iw_point +{ + void *pointer; /* Pointer to the data (in user space) */ + __u16 length; /* number of fields or size in bytes */ + __u16 flags; /* Optional params */ +}; + +/* + * A frequency + * For numbers lower than 10^9, we encode the number in 'm' and + * set 'e' to 0 + * For number greater than 10^9, we divide it by the lowest power + * of 10 to get 'm' lower than 10^9, with 'm'= f / (10^'e')... + * The power of 10 is in 'e', the result of the division is in 'm'. + */ +struct iw_freq +{ + __s32 m; /* Mantissa */ + __s16 e; /* Exponent */ + __u8 i; /* List index (when in range struct) */ + __u8 flags; /* Flags (fixed/auto) */ +}; + +/* + * Quality of the link + */ +struct iw_quality +{ + __u8 qual; /* link quality (%retries, SNR, + %missed beacons or better...) */ + __u8 level; /* signal level (dBm) */ + __u8 noise; /* noise level (dBm) */ + __u8 updated; /* Flags to know if updated */ +}; + +/* + * Packet discarded in the wireless adapter due to + * "wireless" specific problems... + * Note : the list of counter and statistics in net_device_stats + * is already pretty exhaustive, and you should use that first. + * This is only additional stats... + */ +struct iw_discarded +{ + __u32 nwid; /* Rx : Wrong nwid/essid */ + __u32 code; /* Rx : Unable to code/decode (WEP) */ + __u32 fragment; /* Rx : Can't perform MAC reassembly */ + __u32 retries; /* Tx : Max MAC retries num reached */ + __u32 misc; /* Others cases */ +}; + +/* + * Packet/Time period missed in the wireless adapter due to + * "wireless" specific problems... + */ +struct iw_missed +{ + __u32 beacon; /* Missed beacons/superframe */ +}; + +/* + * Quality range (for spy threshold) + */ +struct iw_thrspy +{ + struct sockaddr_t addr; /* Source address (hw/mac) */ + struct iw_quality qual; /* Quality of the link */ + struct iw_quality low; /* Low threshold */ + struct iw_quality high; /* High threshold */ +}; + +/* + * Optional data for scan request + * + * Note: these optional parameters are controlling parameters for the + * scanning behavior, these do not apply to getting scan results + * (SIOCGIWSCAN). Drivers are expected to keep a local BSS table and + * provide a merged results with all BSSes even if the previous scan + * request limited scanning to a subset, e.g., by specifying an SSID. + * Especially, scan results are required to include an entry for the + * current BSS if the driver is in Managed mode and associated with an AP. + */ +struct iw_scan_req +{ + __u8 scan_type; /* IW_SCAN_TYPE_{ACTIVE,PASSIVE} */ + __u8 essid_len; + __u8 num_channels; /* num entries in channel_list; + * 0 = scan all allowed channels */ + __u8 flags; /* reserved as padding; use zero, this may + * be used in the future for adding flags + * to request different scan behavior */ + struct sockaddr_t bssid; /* ff:ff:ff:ff:ff:ff for broadcast BSSID or + * individual address of a specific BSS */ + + /* + * Use this ESSID if IW_SCAN_THIS_ESSID flag is used instead of using + * the current ESSID. This allows scan requests for specific ESSID + * without having to change the current ESSID and potentially breaking + * the current association. + */ + __u8 essid[IW_ESSID_MAX_SIZE]; + + /* + * Optional parameters for changing the default scanning behavior. + * These are based on the MLME-SCAN.request from IEEE Std 802.11. + * TU is 1.024 ms. If these are set to 0, driver is expected to use + * reasonable default values. min_channel_time defines the time that + * will be used to wait for the first reply on each channel. If no + * replies are received, next channel will be scanned after this. If + * replies are received, total time waited on the channel is defined by + * max_channel_time. + */ + __u32 min_channel_time; /* in TU */ + __u32 max_channel_time; /* in TU */ + + struct iw_freq channel_list[IW_MAX_FREQUENCIES]; +}; + +/* ------------------------- WPA SUPPORT ------------------------- */ + +/* + * Extended data structure for get/set encoding (this is used with + * SIOCSIWENCODEEXT/SIOCGIWENCODEEXT. struct iw_point and IW_ENCODE_* + * flags are used in the same way as with SIOCSIWENCODE/SIOCGIWENCODE and + * only the data contents changes (key data -> this structure, including + * key data). + * + * If the new key is the first group key, it will be set as the default + * TX key. Otherwise, default TX key index is only changed if + * IW_ENCODE_EXT_SET_TX_KEY flag is set. + * + * Key will be changed with SIOCSIWENCODEEXT in all cases except for + * special "change TX key index" operation which is indicated by setting + * key_len = 0 and ext_flags |= IW_ENCODE_EXT_SET_TX_KEY. + * + * tx_seq/rx_seq are only used when respective + * IW_ENCODE_EXT_{TX,RX}_SEQ_VALID flag is set in ext_flags. Normal + * TKIP/CCMP operation is to set RX seq with SIOCSIWENCODEEXT and start + * TX seq from zero whenever key is changed. SIOCGIWENCODEEXT is normally + * used only by an Authenticator (AP or an IBSS station) to get the + * current TX sequence number. Using TX_SEQ_VALID for SIOCSIWENCODEEXT and + * RX_SEQ_VALID for SIOCGIWENCODEEXT are optional, but can be useful for + * debugging/testing. + */ +struct iw_encode_ext +{ + __u32 ext_flags; /* IW_ENCODE_EXT_* */ + __u8 tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */ + __u8 rx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */ + struct sockaddr_t addr; /* ff:ff:ff:ff:ff:ff for broadcast/multicast + * (group) keys or unicast address for + * individual keys */ + __u16 alg; /* IW_ENCODE_ALG_* */ + __u16 key_len; +#ifdef __CC_ARM //Fix Keil compile error, must modify sizeof iw_encode_ext - Alex Fang + __u8 key[1]; +#else + __u8 key[0]; +#endif +}; + +/* SIOCSIWMLME data */ +struct iw_mlme +{ + __u16 cmd; /* IW_MLME_* */ + __u16 reason_code; + struct sockaddr_t addr; +}; + +/* SIOCSIWPMKSA data */ +#define IW_PMKSA_ADD 1 +#define IW_PMKSA_REMOVE 2 +#define IW_PMKSA_FLUSH 3 + +#define IW_PMKID_LEN 16 + +struct iw_pmksa +{ + __u32 cmd; /* IW_PMKSA_* */ + struct sockaddr_t bssid; + __u8 pmkid[IW_PMKID_LEN]; +}; + +/* IWEVMICHAELMICFAILURE data */ +struct iw_michaelmicfailure +{ + __u32 flags; + struct sockaddr_t src_addr; + __u8 tsc[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */ +}; + +/* IWEVPMKIDCAND data */ +#define IW_PMKID_CAND_PREAUTH 0x00000001 /* RNS pre-authentication enabled */ +struct iw_pmkid_cand +{ + __u32 flags; /* IW_PMKID_CAND_* */ + __u32 index; /* the smaller the index, the higher the + * priority */ + struct sockaddr_t bssid; +}; + +/* ------------------------ WIRELESS STATS ------------------------ */ +/* + * Wireless statistics (used for /proc/net/wireless) + */ +struct iw_statistics +{ + __u16 status; /* Status + * - device dependent for now */ + + struct iw_quality qual; /* Quality of the link + * (instant/mean/max) */ + struct iw_discarded discard; /* Packet discarded counts */ + struct iw_missed miss; /* Packet missed counts */ +}; + +/* ------------------------ IOCTL REQUEST ------------------------ */ +/* + * This structure defines the payload of an ioctl, and is used + * below. + * + * Note that this structure should fit on the memory footprint + * of iwreq (which is the same as ifreq), which mean a max size of + * 16 octets = 128 bits. Warning, pointers might be 64 bits wide... + * You should check this when increasing the structures defined + * above in this file... + */ +union iwreq_data +{ + /* Config - generic */ + char name[IFNAMSIZ]; + /* Name : used to verify the presence of wireless extensions. + * Name of the protocol/provider... */ + + struct iw_point essid; /* Extended network name */ + struct iw_param nwid; /* network id (or domain - the cell) */ + struct iw_freq freq; /* frequency or channel : + * 0-1000 = channel + * > 1000 = frequency in Hz */ + + struct iw_param sens; /* signal level threshold */ + struct iw_param bitrate; /* default bit rate */ + struct iw_param txpower; /* default transmit power */ + struct iw_param rts; /* RTS threshold threshold */ + struct iw_param frag; /* Fragmentation threshold */ + __u32 mode; /* Operation mode */ + struct iw_param retry; /* Retry limits & lifetime */ + + struct iw_point encoding; /* Encoding stuff : tokens */ + struct iw_param power; /* PM duration/timeout */ + struct iw_quality qual; /* Quality part of statistics */ + + struct sockaddr_t ap_addr; /* Access point address */ + struct sockaddr_t addr; /* Destination address (hw/mac) */ + + struct iw_param param; /* Other small parameters */ + struct iw_point data; /* Other large parameters */ + struct iw_point passphrase; /* Extended network name */ +}; + +/* + * The structure to exchange data for ioctl. + * This structure is the same as 'struct ifreq', but (re)defined for + * convenience... + * Do I need to remind you about structure size (32 octets) ? + */ +struct iwreq +{ +#if 0 + union + { + char ifrn_name[IFNAMSIZ]; /* if name, e.g. "eth0" */ + } ifr_ifrn; +#endif + char ifr_name[IFNAMSIZ]; /* if name, e.g. "eth0" */ + + /* Data part (defined just above) */ + union iwreq_data u; +}; + +/* -------------------------- IOCTL DATA -------------------------- */ +/* + * For those ioctl which want to exchange mode data that what could + * fit in the above structure... + */ + +/* + * Range of parameters + */ + +struct iw_range +{ + /* Informative stuff (to choose between different interface) */ + __u32 throughput; /* To give an idea... */ + /* In theory this value should be the maximum benchmarked + * TCP/IP throughput, because with most of these devices the + * bit rate is meaningless (overhead an co) to estimate how + * fast the connection will go and pick the fastest one. + * I suggest people to play with Netperf or any benchmark... + */ + + /* NWID (or domain id) */ + __u32 min_nwid; /* Minimal NWID we are able to set */ + __u32 max_nwid; /* Maximal NWID we are able to set */ + + /* Old Frequency (backward compat - moved lower ) */ + __u16 old_num_channels; + __u8 old_num_frequency; + + /* Wireless event capability bitmasks */ + __u32 event_capa[6]; + + /* signal level threshold range */ + __s32 sensitivity; + + /* Quality of link & SNR stuff */ + /* Quality range (link, level, noise) + * If the quality is absolute, it will be in the range [0 ; max_qual], + * if the quality is dBm, it will be in the range [max_qual ; 0]. + * Don't forget that we use 8 bit arithmetics... */ + struct iw_quality max_qual; /* Quality of the link */ + /* This should contain the average/typical values of the quality + * indicator. This should be the threshold between a "good" and + * a "bad" link (example : monitor going from green to orange). + * Currently, user space apps like quality monitors don't have any + * way to calibrate the measurement. With this, they can split + * the range between 0 and max_qual in different quality level + * (using a geometric subdivision centered on the average). + * I expect that people doing the user space apps will feedback + * us on which value we need to put in each driver... */ + struct iw_quality avg_qual; /* Quality of the link */ + + /* Rates */ + __u8 num_bitrates; /* Number of entries in the list */ + __s32 bitrate[IW_MAX_BITRATES]; /* list, in bps */ + + /* RTS threshold */ + __s32 min_rts; /* Minimal RTS threshold */ + __s32 max_rts; /* Maximal RTS threshold */ + + /* Frag threshold */ + __s32 min_frag; /* Minimal frag threshold */ + __s32 max_frag; /* Maximal frag threshold */ + + /* Power Management duration & timeout */ + __s32 min_pmp; /* Minimal PM period */ + __s32 max_pmp; /* Maximal PM period */ + __s32 min_pmt; /* Minimal PM timeout */ + __s32 max_pmt; /* Maximal PM timeout */ + __u16 pmp_flags; /* How to decode max/min PM period */ + __u16 pmt_flags; /* How to decode max/min PM timeout */ + __u16 pm_capa; /* What PM options are supported */ + + /* Encoder stuff */ + __u16 encoding_size[IW_MAX_ENCODING_SIZES]; /* Different token sizes */ + __u8 num_encoding_sizes; /* Number of entry in the list */ + __u8 max_encoding_tokens; /* Max number of tokens */ + /* For drivers that need a "login/passwd" form */ + __u8 encoding_login_index; /* token index for login token */ + + /* Transmit power */ + __u16 txpower_capa; /* What options are supported */ + __u8 num_txpower; /* Number of entries in the list */ + __s32 txpower[IW_MAX_TXPOWER]; /* list, in bps */ + + /* Wireless Extension version info */ + __u8 we_version_compiled; /* Must be WIRELESS_EXT */ + __u8 we_version_source; /* Last update of source */ + + /* Retry limits and lifetime */ + __u16 retry_capa; /* What retry options are supported */ + __u16 retry_flags; /* How to decode max/min retry limit */ + __u16 r_time_flags; /* How to decode max/min retry life */ + __s32 min_retry; /* Minimal number of retries */ + __s32 max_retry; /* Maximal number of retries */ + __s32 min_r_time; /* Minimal retry lifetime */ + __s32 max_r_time; /* Maximal retry lifetime */ + + /* Frequency */ + __u16 num_channels; /* Number of channels [0; num - 1] */ + __u8 num_frequency; /* Number of entry in the list */ + struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */ + /* Note : this frequency list doesn't need to fit channel numbers, + * because each entry contain its channel index */ + + __u32 enc_capa; /* IW_ENC_CAPA_* bit field */ + + /* More power management stuff */ + __s32 min_pms; /* Minimal PM saving */ + __s32 max_pms; /* Maximal PM saving */ + __u16 pms_flags; /* How to decode max/min PM saving */ + + /* All available modulations for driver (hw may support less) */ + __s32 modul_capa; /* IW_MODUL_* bit field */ + + /* More bitrate stuff */ + __u32 bitrate_capa; /* Types of bitrates supported */ +}; + +/* + * Private ioctl interface information + */ + +struct iw_priv_args +{ + __u32 cmd; /* Number of the ioctl to issue */ + __u16 set_args; /* Type and number of args */ + __u16 get_args; /* Type and number of args */ + char name[IFNAMSIZ]; /* Name of the extension */ +}; + +/* ----------------------- WIRELESS EVENTS ----------------------- */ +/* + * Wireless events are carried through the rtnetlink socket to user + * space. They are encapsulated in the IFLA_WIRELESS field of + * a RTM_NEWLINK message. + */ + +/* + * A Wireless Event. Contains basically the same data as the ioctl... + */ +struct iw_event +{ + __u16 len; /* Real lenght of this stuff */ + __u16 cmd; /* Wireless IOCTL */ + union iwreq_data u; /* IOCTL fixed payload */ +}; + +/* Size of the Event prefix (including padding and alignement junk) */ +#define IW_EV_LCP_LEN (sizeof(struct iw_event) - sizeof(union iwreq_data)) +/* Size of the various events */ +#define IW_EV_CHAR_LEN (IW_EV_LCP_LEN + IFNAMSIZ) +#define IW_EV_UINT_LEN (IW_EV_LCP_LEN + sizeof(__u32)) +#define IW_EV_FREQ_LEN (IW_EV_LCP_LEN + sizeof(struct iw_freq)) +#define IW_EV_PARAM_LEN (IW_EV_LCP_LEN + sizeof(struct iw_param)) +#define IW_EV_ADDR_LEN (IW_EV_LCP_LEN + sizeof(struct sockaddr_t)) +#define IW_EV_QUAL_LEN (IW_EV_LCP_LEN + sizeof(struct iw_quality)) + +/* iw_point events are special. First, the payload (extra data) come at + * the end of the event, so they are bigger than IW_EV_POINT_LEN. Second, + * we omit the pointer, so start at an offset. */ +#define IW_EV_POINT_OFF (((char *) &(((struct iw_point *) NULL)->length)) - \ + (char *) NULL) +#define IW_EV_POINT_LEN (IW_EV_LCP_LEN + sizeof(struct iw_point) - \ + IW_EV_POINT_OFF) + +/* Size of the Event prefix when packed in stream */ +#define IW_EV_LCP_PK_LEN (4) +/* Size of the various events when packed in stream */ +#define IW_EV_CHAR_PK_LEN (IW_EV_LCP_PK_LEN + IFNAMSIZ) +#define IW_EV_UINT_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(__u32)) +#define IW_EV_FREQ_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct iw_freq)) +#define IW_EV_PARAM_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct iw_param)) +#define IW_EV_ADDR_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct sockaddr_t)) +#define IW_EV_QUAL_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct iw_quality)) +#define IW_EV_POINT_PK_LEN (IW_EV_LCP_LEN + 4) + +#define IW_EXT_STR_FOURWAY_DONE "WPA/WPA2 handshake done" +#define IW_EXT_STR_RECONNECTION_FAIL "RECONNECTION FAILURE" +#define IW_EVT_STR_STA_ASSOC "STA Assoc" +#define IW_EVT_STR_STA_DISASSOC "STA Disassoc" +#define IW_EVT_STR_SEND_ACTION_DONE "Send Action Done" +#define IW_EVT_STR_NO_NETWORK "No Assoc Network After Scan Done" +#endif /* _LINUX_WIRELESS_H */ diff --git a/component/common/drivers/wlan/realtek/src/osdep/wlan_intf.h b/component/common/drivers/wlan/realtek/src/osdep/wlan_intf.h new file mode 100644 index 0000000..ebabd19 --- /dev/null +++ b/component/common/drivers/wlan/realtek/src/osdep/wlan_intf.h @@ -0,0 +1,66 @@ +#ifndef __WLAN_INTF_H__ +#define __WLAN_INTF_H__ + +#ifdef __cplusplus +extern "C" { +#endif +#include + +#include +#include "wifi_constants.h" + +#ifndef WLAN0_IDX + #define WLAN0_IDX 0 +#endif +#ifndef WLAN1_IDX + #define WLAN1_IDX 1 +#endif +#ifndef WLAN_UNDEF + #define WLAN_UNDEF -1 +#endif + +/***********************************************************/ +/* +struct sk_buff { + // These two members must be first. + struct sk_buff *next; // Next buffer in list + struct sk_buff *prev; // Previous buffer in list + + struct sk_buff_head *list; // List we are on + unsigned char *head; // Head of buffer + unsigned char *data; // Data head pointer + unsigned char *tail; // Tail pointer + unsigned char *end; //End pointer + struct net_device *dev; //Device we arrived on/are leaving by + unsigned int len; // Length of actual data +}; +*/ +/************************************************************/ + +//----- ------------------------------------------------------------------ +// Wlan Interface opened for upper layer +//----- ------------------------------------------------------------------ +int rltk_wlan_init(int idx_wlan, rtw_mode_t mode); //return 0: success. -1:fail +void rltk_wlan_deinit(void); +void rltk_wlan_start(int idx_wlan); +void rltk_wlan_statistic(unsigned char idx); +unsigned char rltk_wlan_running(unsigned char idx); // interface is up. 0: interface is down +int rltk_wlan_control(unsigned long cmd, void *data); +int rltk_wlan_handshake_done(void); +int rltk_wlan_rf_on(void); +int rltk_wlan_rf_off(void); +int rltk_wlan_check_bus(void); +int rltk_wlan_wireless_mode(unsigned char mode); +int rltk_wlan_set_wps_phase(unsigned char is_trigger_wps); +int rtw_ps_enable(int enable); +void rltk_wlan_pre_sleep_processing(void); +void rltk_wlan_post_sleep_processing(void); + + +#ifdef __cplusplus +} +#endif + + + +#endif //#ifndef __WLAN_INTF_H__ diff --git a/component/common/example/cJSON/cJSON_example.c b/component/common/example/cJSON/cJSON_example.c new file mode 100644 index 0000000..f336a36 --- /dev/null +++ b/component/common/example/cJSON/cJSON_example.c @@ -0,0 +1,84 @@ +#include "cmsis_os.h" +#include + +#define malloc pvPortMalloc +#define free vPortFree + +/* The data structure for this example + +{ + "Motion_Sensor" : "i", + "Light" : { + "Red" : "0", + "Green" : "0", + "Blue" : "0", + } + +} + +*/ +static void gen_json_data(int i, int r, int g, int b) +{ + + + cJSON_Hooks memoryHook; + + memoryHook.malloc_fn = malloc; + memoryHook.free_fn = free; + cJSON_InitHooks(&memoryHook); + + + cJSON *IOTJSObject = NULL, *colorJSObject = NULL; + char *iot_json = NULL; + + if((IOTJSObject = cJSON_CreateObject()) != NULL) { + + cJSON_AddItemToObject(IOTJSObject, "Motion_Sensor", cJSON_CreateNumber(i)); + cJSON_AddItemToObject(IOTJSObject, "Light", colorJSObject = cJSON_CreateObject()); + + cJSON_AddItemToObject(colorJSObject, "Red", cJSON_CreateNumber(r)); + cJSON_AddItemToObject(colorJSObject, "Green", cJSON_CreateNumber(g)); + cJSON_AddItemToObject(colorJSObject, "Blue", cJSON_CreateNumber(b)); + + iot_json = cJSON_Print(IOTJSObject); + cJSON_Delete(IOTJSObject); + + } + +} + +static void handle_json_data(char *iot_json) +{ + cJSON_Hooks memoryHook; + + memoryHook.malloc_fn = malloc; + memoryHook.free_fn = free; + cJSON_InitHooks(&memoryHook); + + + cJSON *IOTJSObject, *sensorJSObject, *lightJSObject, *redJSObject, *greenJSObject, *blueJSObject; + int sensor_data, red, green, blue; + + if((IOTJSObject = cJSON_Parse(iot_json)) != NULL) { + sensorJSObject = cJSON_GetObjectItem(IOTJSObject, "Motion_Sensor"); + if(sensorJSObject) + sensor_data = sensorJSObject->valueint; + + lightJSObject = cJSON_GetObjectItem(IOTJSObject, "Light"); + + if(lightJSObject){ + redJSObject = cJSON_GetObjectItem(lightJSObject, "Red"); + greenJSObject = cJSON_GetObjectItem(lightJSObject, "Green"); + blueJSObject = cJSON_GetObjectItem(lightJSObject, "Blue"); + + if(redJSObject) + red = redJSObject->valueint; + if(greenJSObject) + green = greenJSObject->valueint; + if(blueJSObject) + blue = blueJSObject->valueint; + } + + cJSON_Delete(IOTJSObject); + } +} diff --git a/component/common/example/example_entry.c b/component/common/example/example_entry.c new file mode 100644 index 0000000..37d9f0f --- /dev/null +++ b/component/common/example/example_entry.c @@ -0,0 +1,59 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2015 Realtek Corporation. All rights reserved. + * + * + ******************************************************************************/ +#include + +#if CONFIG_EXAMPLE_MDNS +#include +#endif + +#if CONFIG_EXAMPLE_MCAST +#include +#endif + +#if CONFIG_EXAMPLE_GOOGLE_NEST +#include +#define FromDevice 1 +#define ToDevice 2 +#define TYPE "ToDevice" +#endif + +#if CONFIG_EXAMPLE_WLAN_FAST_CONNECT +#include +#endif + +/* + Preprocessor of example +*/ +void pre_example_entry(void) +{ +#if CONFIG_EXAMPLE_WLAN_FAST_CONNECT + example_wlan_fast_connect(); +#endif + +#if CONFIG_EXAMPLE_UART_ADAPTER + example_uart_adapter_init(); +#endif +} + +/* + All of the examples are disabled by default for code size consideration + The configuration is enabled in platform_opts.h +*/ +void example_entry(void) +{ +#if (CONFIG_EXAMPLE_MDNS && !CONFIG_EXAMPLE_UART_ADAPTER) + example_mdns(); +#endif + +#if CONFIG_EXAMPLE_MCAST + example_mcast(); +#endif + +#if CONFIG_EXAMPLE_GOOGLE_NEST + example_google(TYPE); +#endif +} diff --git a/component/common/example/example_entry.h b/component/common/example/example_entry.h new file mode 100644 index 0000000..2cdd514 --- /dev/null +++ b/component/common/example/example_entry.h @@ -0,0 +1,8 @@ +#ifndef __EXAMPLE_ENTRY_H__ +#define __EXAMPLE_ENTRY_H__ + + +void example_entry(void); +void pre_example_entry(void); + +#endif //#ifndef __EXAMPLE_ENTRY_H__ diff --git a/component/common/example/googlenest/example.html b/component/common/example/googlenest/example.html new file mode 100644 index 0000000..858f0d4 --- /dev/null +++ b/component/common/example/googlenest/example.html @@ -0,0 +1,38 @@ + + + + + + + +

Realtek Google Nest API example

+
+ + +

Data To Device

+ +

Input the value of RGB to change the state of light:

+

Red +Green +Blue + +

+ + + + + diff --git a/component/common/example/googlenest/example_google.c b/component/common/example/googlenest/example_google.c new file mode 100644 index 0000000..bf9803c --- /dev/null +++ b/component/common/example/googlenest/example_google.c @@ -0,0 +1,185 @@ +#include "cmsis_os.h" +#include "diag.h" +#include "wifi_conf.h" +#include "wifi_ind.h" +#include "google_nest.h" + + +#include +#include "cJSON.h" + +osThreadId google_thread_id; +#define malloc pvPortMalloc +#define free vPortFree + +void google_data_retrieve(char *response_buf); + +void google_data_retrieve(char *response_buf) { + //printf("\r\n\r\n\r\nResponse_buf:\r\n%s\r\n", response_buf); + char *event = NULL; + char *delims = "\n"; + char *data = NULL, *backup = NULL; + char *info = NULL; + cJSON_Hooks memoryHook; + + event = strtok_r(response_buf, delims, &backup); + data = strtok_r( NULL, delims, &backup ); + + if (!strncmp(data, "data: ", strlen("data: "))){ + info = data + strlen("data: "); + if(info != NULL){ + memoryHook.malloc_fn = malloc; + memoryHook.free_fn = free; + cJSON_InitHooks(&memoryHook); + + cJSON *infoJSObject, *pathJSObject, *dataJSObject; + cJSON *redJSObject, *greenJSObject, *blueJSObject; + char *red, *green, *blue; + + + if((infoJSObject = cJSON_Parse(info)) != NULL) { + pathJSObject = cJSON_GetObjectItem(infoJSObject, "path"); + dataJSObject = cJSON_GetObjectItem(infoJSObject, "data"); + if(dataJSObject != NULL) { + + redJSObject = cJSON_GetObjectItem(dataJSObject, "Red"); + greenJSObject = cJSON_GetObjectItem(dataJSObject, "Green"); + blueJSObject = cJSON_GetObjectItem(dataJSObject, "Blue"); + + if(redJSObject) + red = redJSObject->valuestring; + + if(greenJSObject) + green = greenJSObject->valuestring; + + if(blueJSObject) + blue = blueJSObject->valuestring; + + printf("\n\rThe latest RGB information: RGB(%s, %s, %s)\n\r", red, green, blue); + + cJSON_Delete(dataJSObject); + } + cJSON_Delete(infoJSObject); + } + else + printf("\r\nCannot parse the message to JSON!\r\n"); + + } + else + printf("\r\n This is the keep alive message or cannot get the information!\r\n"); + } + else + printf("\r\nData structure may wrong!\r\n"); +} + + +void gn_todevice_start(void) { + + googlenest_context googlenest; + char *googlenest_host = HOST_ADDR; + char *googlenest_uri = "light.json"; + + printf("\r\nStart connecting to Google Nest Server...\r\n"); + memset(&googlenest, 0, sizeof(googlenest_context)); + +reconnect: + if(gn_connect(&googlenest, googlenest_host, GN_PORT) == 0) { + printf("\r\n Connection is OK!\r\n"); + + google_retrieve_data_hook_callback(google_data_retrieve); + if(gn_stream(&googlenest, googlenest_uri) != 0){ + printf("\r\n Connection is fail! \r\n Start Reconnecting...\r\n"); + goto reconnect; + } + + gn_close(&googlenest); + + } + else{ + printf("\r\n Connection is fail! \r\n\r\n\r\n\r\nStart Reconnecting...\r\n"); + goto reconnect; + } + +} + +void gn_fromdevice_start(void) { + googlenest_context googlenest; + char *googlenest_uri = "MotionSensor.json"; + cJSON_Hooks memoryHook; + int j = 0; + + memoryHook.malloc_fn = malloc; + memoryHook.free_fn = free; + cJSON_InitHooks(&memoryHook); + printf("\r\nStart connecting to Google Nest Server!\r\n"); + + while(1) { + memset(&googlenest, 0, sizeof(googlenest_context)); + if(gn_connect(&googlenest, HOST_ADDR, GN_PORT) == 0) { + cJSON *MSJSObject; + char *data; + + if((MSJSObject = cJSON_CreateObject()) != NULL) { + cJSON_AddItemToObject(MSJSObject, "MotionSenser", cJSON_CreateNumber(j++)); + data = cJSON_Print(MSJSObject); + cJSON_Delete(MSJSObject); + } + + if(gn_put(&googlenest, googlenest_uri, data) == 0) + printf("\n\rUpdate the Motion Sensor's data to %d\n\r", (j-1)); + free(data); + gn_close(&googlenest); + } + else{ + printf("\n\rConnection failed!\n\r"); + break; + } + + vTaskDelay(5 * configTICK_RATE_HZ); + } +} + +void gn_fromdevice_task(void *arg) { + int i; + + printf("\n\r\n\r\n\r\n\r<<<<<>>>>>>\n\r\n\r\n\r\n\r"); + for (i = 0; i<120; i++) + vTaskDelay(1000 / portTICK_PERIOD_MS); + + gn_fromdevice_start(); +} + +void gn_todevice_task(void *arg) { + int i; + + printf("\n\r\n\r\n\r\n\r<<<<<>>>>>>\n\r\n\r\n\r\n\r"); + for (i = 0; i<120; i++) + vTaskDelay(1000 / portTICK_PERIOD_MS); + + gn_todevice_start(); +} + +void example_google(char *type) { + + + if(strcmp(type, "FromDevice") == 0){ + osThreadDef_t google_thread; + google_thread.instances = 1; + google_thread.name = "google thread"; + google_thread.stacksize = 4096; + google_thread.pthread = (os_pthread)gn_fromdevice_task; + google_thread.tpriority = tskIDLE_PRIORITY+6; + google_thread_id = osThreadCreate(&google_thread, NULL); + } + else if(strcmp(type, "ToDevice") == 0){ + osThreadDef_t google_thread; + google_thread.instances = 1; + google_thread.name = "google thread"; + google_thread.stacksize = 4096; + google_thread.pthread = (os_pthread)gn_todevice_task; + google_thread.tpriority = tskIDLE_PRIORITY+6; + google_thread_id = osThreadCreate(&google_thread, NULL); + } + +} + diff --git a/component/common/example/googlenest/example_google.h b/component/common/example/googlenest/example_google.h new file mode 100644 index 0000000..8de92d0 --- /dev/null +++ b/component/common/example/googlenest/example_google.h @@ -0,0 +1,10 @@ +#ifndef GOOGLE_THREAD_H +#define GOOGLE_THREAD_H + +#define HOST_ADDR "your_firebase_address.firebaseio.com" +#define GN_PORT 443 + +void example_google(char *type); + + +#endif diff --git a/component/common/example/mcast/example_mcast.c b/component/common/example/mcast/example_mcast.c new file mode 100644 index 0000000..b18dae8 --- /dev/null +++ b/component/common/example/mcast/example_mcast.c @@ -0,0 +1,98 @@ +#include "FreeRTOS.h" +#include "task.h" +#include + +#include +#include +#include +extern struct netif xnetif[]; + +static void example_mcast_thread(void *param) +{ +#if LWIP_IGMP + int err = 0; + int socket = -1; + char *group_ip = "224.0.0.251"; + uint16_t port = 5353; + + // Set NETIF_FLAG_IGMP flag for netif which should process IGMP messages + xnetif[0].flags |= NETIF_FLAG_IGMP; + + if((socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + printf("ERROR: socket - AF_INET, SOCK_DGRAM\n"); + err = -1; + } + + // Add multicast group membership on this interface + if(err == 0) { + struct ip_mreq imr; + imr.imr_multiaddr.s_addr = inet_addr(group_ip); + imr.imr_interface.s_addr = INADDR_ANY; + err = setsockopt(socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &imr, sizeof(imr)); + if(err < 0) printf("ERROR: setsockopt - IP_ADD_MEMBERSHIP\n"); + } + + // Specify outgoing interface too + if(err == 0) { + struct in_addr intfAddr; + intfAddr.s_addr = INADDR_ANY; + err = setsockopt(socket, IPPROTO_IP, IP_MULTICAST_IF, &intfAddr, sizeof(struct in_addr)); + if(err < 0) printf("ERROR: setsockopt - IP_MULTICAST_IF\n"); + } + + // And start listening for packets + if(err == 0) { + struct sockaddr_in bindAddr; + bindAddr.sin_family = AF_INET; + bindAddr.sin_port = htons(port); + bindAddr.sin_addr.s_addr = INADDR_ANY; + err = bind(socket, (struct sockaddr *) &bindAddr, sizeof(bindAddr)); + if(err < 0) printf("ERROR: bind\n"); + } + + if(err == 0) { + unsigned char packet[1024]; + + while(1) { + // Receive multicast + int packetLen; + struct sockaddr from; + struct sockaddr_in *from_sin = (struct sockaddr_in*) &from; + socklen_t fromLen = sizeof(from); + + if((packetLen = recvfrom(socket, &packet, sizeof(packet), 0, &from, &fromLen)) >= 0) { + uint8_t *ip = (uint8_t *) &from_sin->sin_addr.s_addr; + uint16_t from_port = ntohs(from_sin->sin_port); + printf("recvfrom - %d bytes from %d.%d.%d.%d:%d\n", packetLen, ip[0], ip[1], ip[2], ip[3], from_port); + } + + // Send multicast + if(packetLen > 0) { + int sendLen; + struct sockaddr to; + struct sockaddr_in *to_sin = (struct sockaddr_in*) &to; + to_sin->sin_family = AF_INET; + to_sin->sin_port = htons(port); + to_sin->sin_addr.s_addr = inet_addr(group_ip); + + if((sendLen = sendto(socket, packet, packetLen, 0, &to, sizeof(struct sockaddr))) < 0) + printf("ERROR: sendto %s\n", group_ip); + else + printf("sendto - %d bytes to %s:%d\n", sendLen, group_ip, port); + } + } + } + else if(socket != -1) { + close(socket); + } +#else + printf("\nSHOULD ENABLE LWIP_IGMP\n"); +#endif + vTaskDelete(NULL); +} + +void example_mcast(void) +{ + if(xTaskCreate(example_mcast_thread, ((const char*)"example_mcast_thread"), 2048, NULL, tskIDLE_PRIORITY + 1, NULL) != pdPASS) + printf("\n\r%s xTaskCreate(init_thread) failed", __FUNCTION__); +} diff --git a/component/common/example/mcast/example_mcast.h b/component/common/example/mcast/example_mcast.h new file mode 100644 index 0000000..7be6823 --- /dev/null +++ b/component/common/example/mcast/example_mcast.h @@ -0,0 +1,6 @@ +#ifndef EXAMPLE_MCAST_H +#define EXAMPLE_MCAST_H + +void example_mcast(void); + +#endif /* EXAMPLE_MCAST_H */ diff --git a/component/common/example/mcast/readme.txt b/component/common/example/mcast/readme.txt new file mode 100644 index 0000000..1a6409d --- /dev/null +++ b/component/common/example/mcast/readme.txt @@ -0,0 +1,17 @@ +LWIP MULTICAST EXAMPLE + +Description: +Join multicast group of 224.0.0.251 and listen on port 5353. +Send packet with the content of received packet to multicast group of 224.0.0.251. + +Configuration: +[lwipopts.h] + #define LWIP_UDP 1 + #define LWIP_IGMP 1 +[platform_opts.h] + #define CONFIG_EXAMPLE_MCAST 1 + +Execution: +Can make automatical Wi-Fi connection when booting by using wlan fast connect example. +A multicast example thread will be started automatically when booting. + diff --git a/component/common/example/mdns/example_mdns.c b/component/common/example/mdns/example_mdns.c new file mode 100644 index 0000000..3dd66a4 --- /dev/null +++ b/component/common/example/mdns/example_mdns.c @@ -0,0 +1,55 @@ +#include "FreeRTOS.h" +#include "task.h" +#include + +#include + +#include +#include +extern struct netif xnetif[]; + +static void example_mdns_thread(void *param) +{ + DNSServiceRef dnsServiceRef = NULL; + TXTRecordRef txtRecord; + unsigned char txt_buf[100]; // use fixed buffer for text record to prevent malloc/free + + // Delay to wait for IP by DHCP + vTaskDelay(10000); + + printf("\nmDNS Init\n"); + if(mDNSResponderInit() == 0) { + printf("mDNS Register service\n"); + TXTRecordCreate(&txtRecord, sizeof(txt_buf), txt_buf); + TXTRecordSetValue(&txtRecord, "text1", strlen("text1_content"), "text1_content"); + TXTRecordSetValue(&txtRecord, "text2", strlen("text2_content"), "text2_content"); + dnsServiceRef = mDNSRegisterService("ameba", "_service1._tcp", "local", 5000, &txtRecord); + TXTRecordDeallocate(&txtRecord); + printf("wait for 30s ... \n"); + vTaskDelay(30*1000); + + printf("mDNS Update service\n"); + TXTRecordCreate(&txtRecord, sizeof(txt_buf), txt_buf); + TXTRecordSetValue(&txtRecord, "text1", strlen("text1_content_new"), "text1_content_new"); + mDNSUpdateService(dnsServiceRef, &txtRecord); + TXTRecordDeallocate(&txtRecord); + printf("wait for 30s ... \n"); + vTaskDelay(30*1000); + + if(dnsServiceRef) + mDNSDeregisterService(dnsServiceRef); + + // deregister service before mdns deinit is not necessary + // mDNS deinit will also deregister all services + printf("mDNS Deinit\n"); + mDNSResponderDeinit(); + } + + vTaskDelete(NULL); +} + +void example_mdns(void) +{ + if(xTaskCreate(example_mdns_thread, ((const char*)"example_mdns_thread"), 1024, NULL, tskIDLE_PRIORITY + 1, NULL) != pdPASS) + printf("\n\r%s xTaskCreate(init_thread) failed", __FUNCTION__); +} diff --git a/component/common/example/mdns/example_mdns.h b/component/common/example/mdns/example_mdns.h new file mode 100644 index 0000000..39c4914 --- /dev/null +++ b/component/common/example/mdns/example_mdns.h @@ -0,0 +1,6 @@ +#ifndef EXAMPLE_MDNS_H +#define EXAMPLE_MDNS_H + +void example_mdns(void); + +#endif /* EXAMPLE_MDNS_H */ diff --git a/component/common/example/wlan_fast_connect/example_wlan_fast_connect.c b/component/common/example/wlan_fast_connect/example_wlan_fast_connect.c new file mode 100644 index 0000000..07e6caa --- /dev/null +++ b/component/common/example/wlan_fast_connect/example_wlan_fast_connect.c @@ -0,0 +1,125 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2015 Realtek Corporation. All rights reserved. + * + * + ******************************************************************************/ + + /** @file + + This example demonstrate how to implement wifi fast reconnection +**/ +#include +#include + + +#include "task.h" +#include +#include +#include "flash_api.h" + +write_reconnect_ptr p_write_reconnect_ptr; + +extern void fATW0(void *arg); +extern void fATW1(void *arg); +extern void fATW2(void *arg); +extern void fATWC(void *arg); + +/* +* Usage: +* wifi connection indication trigger this function to save current +* wifi profile in flash +* +* Condition: +* CONFIG_EXAMPLE_WLAN_FAST_CONNECT flag is set +*/ + +int wlan_wrtie_reconnect_data_to_flash(uint8_t *data, uint32_t len) +{ + flash_t flash; + uint8_t read_data [FAST_RECONNECT_DATA_LEN]; + if(!data) + return -1; + + flash_stream_read(&flash, FAST_RECONNECT_DATA, FAST_RECONNECT_DATA_LEN, (uint8_t *) read_data); + + //wirte it to flash if different content: SSID, Passphrase, Channel + if(memcmp((void *)data, (void *)read_data, NDIS_802_11_LENGTH_SSID) || + memcmp((void *)(data + NDIS_802_11_LENGTH_SSID + 4), (void *)(read_data + NDIS_802_11_LENGTH_SSID + 4), 32) || + memcmp((void *)(data + NDIS_802_11_LENGTH_SSID + 4 + 32 + A_SHA_DIGEST_LEN * 2), (void *)(read_data + NDIS_802_11_LENGTH_SSID + 4 + 32 + A_SHA_DIGEST_LEN * 2), 4)){ + printf("\r\n %s():not the same ssid/passphrase/channel, need to flash it", __func__); + + flash_erase_sector(&flash, FAST_RECONNECT_DATA); + flash_stream_write(&flash, FAST_RECONNECT_DATA, len, (uint8_t *) data); + } + + return 0; +} + +/* +* Usage: +* After wifi init done, waln driver call this function to check whether +* auto-connect is required. +* +* This function read previous saved wlan profile in flash and execute connection. +* +* Condition: +* CONFIG_EXAMPLE_WLAN_FAST_CONNECT flag is set +*/ +int wlan_init_done_callback() +{ + flash_t flash; + uint8_t *data; + uint32_t channel; + uint8_t pscan_config; + char key_id; + + data = (uint8_t *)rtw_zmalloc(FAST_RECONNECT_DATA_LEN); + flash_stream_read(&flash, FAST_RECONNECT_DATA, FAST_RECONNECT_DATA_LEN, (uint8_t *)data); + if(*((uint32_t *) data) != ~0x0){ + memcpy(psk_essid, (uint8_t *)data, NDIS_802_11_LENGTH_SSID + 4); + memcpy(psk_passphrase, (uint8_t *)data + NDIS_802_11_LENGTH_SSID + 4, (IW_PASSPHRASE_MAX_SIZE + 1)); + memcpy(wpa_global_PSK, (uint8_t *)data + NDIS_802_11_LENGTH_SSID + 4 + (IW_PASSPHRASE_MAX_SIZE + 1), A_SHA_DIGEST_LEN * 2); + memcpy(&channel, (uint8_t *)data + NDIS_802_11_LENGTH_SSID + 4 + (IW_PASSPHRASE_MAX_SIZE + 1) + A_SHA_DIGEST_LEN * 2, 4); + sprintf(&key_id,"%d",(channel >> 28)); + channel &= 0xff; + pscan_config = PSCAN_ENABLE | PSCAN_FAST_SURVEY; + //set partial scan for entering to listen beacon quickly + wifi_set_pscan_chan((uint8_t *)&channel, &pscan_config, 1); + +#ifdef CONFIG_AUTO_RECONNECT + wifi_set_autoreconnect(1); +#endif + //set wifi connect + //open mode + if(!strlen((char*)psk_passphrase)){ + fATW0((char*)psk_essid); + } + //wep mode + else if( strlen((char*)psk_passphrase) == 5 || strlen((char*)psk_passphrase) == 13){ + fATW0((char*)psk_essid); + fATW1((char*)psk_passphrase); + fATW2(&key_id); + } + //WPA/WPA2 + else{ + fATW0((char*)psk_essid); + fATW1((char*)psk_passphrase); + } + fATWC(NULL); + } + if(data) + rtw_mfree(data); + return 0; +} + + +void example_wlan_fast_connect() +{ + // Call back from wlan driver after wlan init done + p_wlan_init_done_callback = wlan_init_done_callback; + + // Call back from application layer after wifi_connection success + p_write_reconnect_ptr = wlan_wrtie_reconnect_data_to_flash; + +} diff --git a/component/common/example/wlan_fast_connect/example_wlan_fast_connect.h b/component/common/example/wlan_fast_connect/example_wlan_fast_connect.h new file mode 100644 index 0000000..d8851dd --- /dev/null +++ b/component/common/example/wlan_fast_connect/example_wlan_fast_connect.h @@ -0,0 +1,35 @@ +#ifndef __EXAMPLE_FAST_RECONNECTION_H__ +#define __EXAMPLE_FAST_RECONNECTION_H__ + + +/****************************************************************************** + * + * Copyright(c) 2007 - 2015 Realtek Corporation. All rights reserved. + * + * + ******************************************************************************/ +#include "FreeRTOS.h" +#include + +#define IW_PASSPHRASE_MAX_SIZE 64 +#define FAST_RECONNECT_DATA (0xC0000 - 0x1000) +#define NDIS_802_11_LENGTH_SSID 32 +#define A_SHA_DIGEST_LEN 20 +#define FAST_RECONNECT_DATA_LEN (NDIS_802_11_LENGTH_SSID+4 +(IW_PASSPHRASE_MAX_SIZE + 1)+ A_SHA_DIGEST_LEN * 2 + 4) + +typedef int (*wlan_init_done_ptr)(void); +typedef int (*write_reconnect_ptr)(uint8_t *data, uint32_t len); + +//Variable +extern unsigned char psk_essid[NET_IF_NUM][NDIS_802_11_LENGTH_SSID+4]; +extern unsigned char psk_passphrase[NET_IF_NUM][IW_PASSPHRASE_MAX_SIZE + 1]; +extern unsigned char wpa_global_PSK[NET_IF_NUM][A_SHA_DIGEST_LEN * 2]; +extern unsigned char psk_passphrase64[IW_PASSPHRASE_MAX_SIZE + 1]; + +//Function +extern wlan_init_done_ptr p_wlan_init_done_callback; +extern write_reconnect_ptr p_write_reconnect_ptr; + +void example_wlan_fast_connect(void); + +#endif //#ifndef __EXAMPLE_FAST_RECONNECTION_H__ diff --git a/component/common/mbed/api/error.h b/component/common/mbed/api/error.h new file mode 100644 index 0000000..3a40358 --- /dev/null +++ b/component/common/mbed/api/error.h @@ -0,0 +1,66 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * 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 MBED_ERROR_H +#define MBED_ERROR_H + +/** To generate a fatal compile-time error, you can use the pre-processor #error directive. + * + * @code + * #error "That shouldn't have happened!" + * @endcode + * + * If the compiler evaluates this line, it will report the error and stop the compile. + * + * For example, you could use this to check some user-defined compile-time variables: + * + * @code + * #define NUM_PORTS 7 + * #if (NUM_PORTS > 4) + * #error "NUM_PORTS must be less than 4" + * #endif + * @endcode + * + * Reporting Run-Time Errors: + * To generate a fatal run-time error, you can use the mbed error() function. + * + * @code + * error("That shouldn't have happened!"); + * @endcode + * + * If the mbed running the program executes this function, it will print the + * message via the USB serial port, and then die with the blue lights of death! + * + * The message can use printf-style formatting, so you can report variables in the + * message too. For example, you could use this to check a run-time condition: + * + * @code + * if(x >= 5) { + * error("expected x to be less than 5, but got %d", x); + * } + * #endcode + */ + +#ifdef __cplusplus +extern "C" { +#endif + +void error(const char* format, ...); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/component/common/mbed/api/mbed_assert.h b/component/common/mbed/api/mbed_assert.h new file mode 100644 index 0000000..1bcfb09 --- /dev/null +++ b/component/common/mbed/api/mbed_assert.h @@ -0,0 +1,50 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * 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 MBED_ASSERT_H +#define MBED_ASSERT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** Internal mbed assert function which is invoked when MBED_ASSERT macro failes. + * This function is active only if NDEBUG is not defined prior to including this + * assert header file. + * In case of MBED_ASSERT failing condition, the assertation message is printed + * to stderr and mbed_die() is called. + * @param expr Expresion to be checked. + * @param file File where assertation failed. + * @param line Failing assertation line number. + */ +void mbed_assert_internal(const char *expr, const char *file, int line); + +#ifdef __cplusplus +} +#endif + +#ifdef NDEBUG +#define MBED_ASSERT(expr) ((void)0) + +#else +#define MBED_ASSERT(expr) \ +do { \ + if (!(expr)) { \ + mbed_assert_internal(#expr, __FILE__, __LINE__); \ + } \ +} while (0) +#endif + +#endif diff --git a/component/common/mbed/api/wait_api.h b/component/common/mbed/api/wait_api.h new file mode 100644 index 0000000..03c2714 --- /dev/null +++ b/component/common/mbed/api/wait_api.h @@ -0,0 +1,66 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * 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 MBED_WAIT_API_H +#define MBED_WAIT_API_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** Generic wait functions. + * + * These provide simple NOP type wait capabilities. + * + * Example: + * @code + * #include "mbed.h" + * + * DigitalOut heartbeat(LED1); + * + * int main() { + * while (1) { + * heartbeat = 1; + * wait(0.5); + * heartbeat = 0; + * wait(0.5); + * } + * } + */ + +/** Waits for a number of seconds, with microsecond resolution (within + * the accuracy of single precision floating point). + * + * @param s number of seconds to wait + */ +void wait(float s); + +/** Waits a number of milliseconds. + * + * @param ms the whole number of milliseconds to wait + */ +void wait_ms(int ms); + +/** Waits a number of microseconds. + * + * @param us the whole number of microseconds to wait + */ +void wait_us(int us); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/component/common/mbed/common/.gitkeep b/component/common/mbed/common/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/component/common/mbed/common/Makefile b/component/common/mbed/common/Makefile new file mode 100644 index 0000000..dd65552 --- /dev/null +++ b/component/common/mbed/common/Makefile @@ -0,0 +1,52 @@ + +include $(MAKE_INCLUDE_GEN) + +.PHONY: all clean + +MODULE_IFLAGS = -I../ + +#*****************************************************************************# +# Object FILE LIST # +#*****************************************************************************# +OBJS = +OBJS_ROM = +OBJS_RAM = +ifeq ($(CONFIG_TIMER_MODULE),y) + OBJS += us_ticker_api.o wait_api.o +endif + +ifeq ($(CONFIG_LIB_BUILD_RAM),y) + OBJS = $(OBJS_RAM) +else ifeq ($(CONFIG_RELEASE_BUILD_RAM_ALL),y) + OBJS += $(OBJS_RAM) +else ifeq ($(CONFIG_RELEASE_BUILD_LIBRARIES),y) + OBJS = $(CSRC_ROM) +else ifeq ($(CONFIG_NORMAL_BUILD),y) + OBJS += $(CSRC_ROM) + OBJS += $(CSRC_RAM) +endif + + +#*****************************************************************************# +# RULES TO GENERATE TARGETS # +#*****************************************************************************# + +# Define the Rules to build the core targets +all: CORE_TARGETS COPY_RAM_OBJS + +#*****************************************************************************# +# GENERATE OBJECT FILE +#*****************************************************************************# +CORE_TARGETS: $(OBJS) + + +#*****************************************************************************# +# RULES TO CLEAN TARGETS # +#*****************************************************************************# +clean: + $(REMOVE) *.o + $(REMOVE) *.i + $(REMOVE) *.s + $(REMOVE) *.d + +-include $(DEPS) \ No newline at end of file diff --git a/component/common/mbed/common/us_ticker_api.c b/component/common/mbed/common/us_ticker_api.c new file mode 100644 index 0000000..8218b9c --- /dev/null +++ b/component/common/mbed/common/us_ticker_api.c @@ -0,0 +1,118 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * 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. + */ +#include +#include "us_ticker_api.h" +#include "cmsis.h" + +static ticker_event_handler event_handler; +static ticker_event_t *head = NULL; + +void us_ticker_set_handler(ticker_event_handler handler) { + us_ticker_init(); + + event_handler = handler; +} + +void us_ticker_irq_handler(void) { + us_ticker_clear_interrupt(); + + /* Go through all the pending TimerEvents */ + while (1) { + if (head == NULL) { + // There are no more TimerEvents left, so disable matches. + us_ticker_disable_interrupt(); + return; + } + + if ((int)(head->timestamp - us_ticker_read()) <= 0) { + // This event was in the past: + // point to the following one and execute its handler + ticker_event_t *p = head; + head = head->next; + if (event_handler != NULL) { + event_handler(p->id); // NOTE: the handler can set new events + } + /* Note: We continue back to examining the head because calling the + * event handler may have altered the chain of pending events. */ + } else { + // This event and the following ones in the list are in the future: + // set it as next interrupt and return + us_ticker_set_interrupt(head->timestamp); + return; + } + } +} + +void us_ticker_insert_event(ticker_event_t *obj, timestamp_t timestamp, uint32_t id) { + /* disable interrupts for the duration of the function */ + __disable_irq(); + + // initialise our data + obj->timestamp = timestamp; + obj->id = id; + + /* Go through the list until we either reach the end, or find + an element this should come before (which is possibly the + head). */ + ticker_event_t *prev = NULL, *p = head; + while (p != NULL) { + /* check if we come before p */ + if ((int)(timestamp - p->timestamp) <= 0) { + break; + } + /* go to the next element */ + prev = p; + p = p->next; + } + /* if prev is NULL we're at the head */ + if (prev == NULL) { + head = obj; + us_ticker_set_interrupt(timestamp); + } else { + prev->next = obj; + } + /* if we're at the end p will be NULL, which is correct */ + obj->next = p; + + __enable_irq(); +} + +void us_ticker_remove_event(ticker_event_t *obj) { + __disable_irq(); + + // remove this object from the list + if (head == obj) { + // first in the list, so just drop me + head = obj->next; + if (head == NULL) { + us_ticker_disable_interrupt(); + } else { + us_ticker_set_interrupt(head->timestamp); + } + } else { + // find the object before me, then drop me + ticker_event_t* p = head; + while (p != NULL) { + if (p->next == obj) { + p->next = obj->next; + break; + } + p = p->next; + } + } + + __enable_irq(); +} diff --git a/component/common/mbed/common/wait_api.c b/component/common/mbed/common/wait_api.c new file mode 100644 index 0000000..f7e8884 --- /dev/null +++ b/component/common/mbed/common/wait_api.c @@ -0,0 +1,30 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * 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. + */ +#include "wait_api.h" +#include "us_ticker_api.h" + +void wait(float s) { + wait_us((int)(s * 1000000.0f)); +} + +void wait_ms(int ms) { + wait_us(ms * 1000); +} + +void wait_us(int us) { + uint32_t start = us_ticker_read(); + while ((us_ticker_read() - start) < (uint32_t)us); +} diff --git a/component/common/mbed/hal/analogin_api.h b/component/common/mbed/hal/analogin_api.h new file mode 100644 index 0000000..98d02c1 --- /dev/null +++ b/component/common/mbed/hal/analogin_api.h @@ -0,0 +1,39 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * 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 MBED_ANALOGIN_API_H +#define MBED_ANALOGIN_API_H + +#include "device.h" + +#if DEVICE_ANALOGIN + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct analogin_s analogin_t; + +void analogin_init (analogin_t *obj, PinName pin); +float analogin_read (analogin_t *obj); +uint16_t analogin_read_u16(analogin_t *obj); + +#ifdef __cplusplus +} +#endif + +#endif + +#endif diff --git a/component/common/mbed/hal/analogout_api.h b/component/common/mbed/hal/analogout_api.h new file mode 100644 index 0000000..97a2013 --- /dev/null +++ b/component/common/mbed/hal/analogout_api.h @@ -0,0 +1,42 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * 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 MBED_ANALOGOUT_API_H +#define MBED_ANALOGOUT_API_H + +#include "device.h" + +#if DEVICE_ANALOGOUT + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct dac_s dac_t; + +void analogout_init (dac_t *obj, PinName pin); +void analogout_free (dac_t *obj); +void analogout_write (dac_t *obj, float value); +void analogout_write_u16(dac_t *obj, uint16_t value); +float analogout_read (dac_t *obj); +uint16_t analogout_read_u16 (dac_t *obj); + +#ifdef __cplusplus +} +#endif + +#endif + +#endif diff --git a/component/common/mbed/hal/can_api.h b/component/common/mbed/hal/can_api.h new file mode 100644 index 0000000..48bc104 --- /dev/null +++ b/component/common/mbed/hal/can_api.h @@ -0,0 +1,80 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * 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 MBED_CAN_API_H +#define MBED_CAN_API_H + +#include "device.h" + +#if DEVICE_CAN + +#include "PinNames.h" +#include "PeripheralNames.h" +#include "can_helper.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + IRQ_RX, + IRQ_TX, + IRQ_ERROR, + IRQ_OVERRUN, + IRQ_WAKEUP, + IRQ_PASSIVE, + IRQ_ARB, + IRQ_BUS, + IRQ_READY +} CanIrqType; + + +typedef enum { + MODE_RESET, + MODE_NORMAL, + MODE_SILENT, + MODE_TEST_GLOBAL, + MODE_TEST_LOCAL, + MODE_TEST_SILENT +} CanMode; + +typedef void (*can_irq_handler)(uint32_t id, CanIrqType type); + +typedef struct can_s can_t; + +void can_init (can_t *obj, PinName rd, PinName td); +void can_free (can_t *obj); +int can_frequency(can_t *obj, int hz); + +void can_irq_init (can_t *obj, can_irq_handler handler, uint32_t id); +void can_irq_free (can_t *obj); +void can_irq_set (can_t *obj, CanIrqType irq, uint32_t enable); + +int can_write (can_t *obj, CAN_Message, int cc); +int can_read (can_t *obj, CAN_Message *msg, int handle); +int can_mode (can_t *obj, CanMode mode); +int can_filter(can_t *obj, uint32_t id, uint32_t mask, CANFormat format, int32_t handle); +void can_reset (can_t *obj); +unsigned char can_rderror (can_t *obj); +unsigned char can_tderror (can_t *obj); +void can_monitor (can_t *obj, int silent); + +#ifdef __cplusplus +}; +#endif + +#endif // MBED_CAN_API_H + +#endif diff --git a/component/common/mbed/hal/ethernet_api.h b/component/common/mbed/hal/ethernet_api.h new file mode 100644 index 0000000..4cae77e --- /dev/null +++ b/component/common/mbed/hal/ethernet_api.h @@ -0,0 +1,63 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * 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 MBED_ETHERNET_API_H +#define MBED_ETHERNET_API_H + +#include "device.h" + +#if DEVICE_ETHERNET + +#ifdef __cplusplus +extern "C" { +#endif + +// Connection constants + +int ethernet_init(void); +void ethernet_free(void); + +// write size bytes from data to ethernet buffer +// return num bytes written +// or -1 if size is too big +int ethernet_write(const char *data, int size); + +// send ethernet write buffer, returning the packet size sent +int ethernet_send(void); + +// recieve from ethernet buffer, returning packet size, or 0 if no packet +int ethernet_receive(void); + +// read size bytes in to data, return actual num bytes read (0..size) +// if data == NULL, throw the bytes away +int ethernet_read(char *data, int size); + +// get the ethernet address +void ethernet_address(char *mac); + +// see if the link is up +int ethernet_link(void); + +// force link settings +void ethernet_set_link(int speed, int duplex); + +#ifdef __cplusplus +} +#endif + +#endif + +#endif + diff --git a/component/common/mbed/hal/gpio_api.h b/component/common/mbed/hal/gpio_api.h new file mode 100644 index 0000000..e4cf7fd --- /dev/null +++ b/component/common/mbed/hal/gpio_api.h @@ -0,0 +1,51 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * 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 MBED_GPIO_API_H +#define MBED_GPIO_API_H + +#include "device.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Set the given pin as GPIO + * @param pin The pin to be set as GPIO + * @return The GPIO port mask for this pin + **/ +uint32_t gpio_set(PinName pin); + +/* GPIO object */ +void gpio_init(gpio_t *obj, PinName pin); + +void gpio_mode (gpio_t *obj, PinMode mode); +void gpio_dir (gpio_t *obj, PinDirection direction); + +void gpio_write(gpio_t *obj, int value); +int gpio_read (gpio_t *obj); + +// the following set of functions are generic and are implemented in the common gpio.c file +void gpio_init_in(gpio_t* gpio, PinName pin); +void gpio_init_in_ex(gpio_t* gpio, PinName pin, PinMode mode); +void gpio_init_out(gpio_t* gpio, PinName pin); +void gpio_init_out_ex(gpio_t* gpio, PinName pin, int value); +void gpio_init_inout(gpio_t* gpio, PinName pin, PinDirection direction, PinMode mode, int value); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/component/common/mbed/hal/gpio_irq_api.h b/component/common/mbed/hal/gpio_irq_api.h new file mode 100644 index 0000000..ccdb30c --- /dev/null +++ b/component/common/mbed/hal/gpio_irq_api.h @@ -0,0 +1,47 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * 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 MBED_GPIO_IRQ_API_H +#define MBED_GPIO_IRQ_API_H + +#include "device.h" + +#if DEVICE_INTERRUPTIN + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + IRQ_NONE, + IRQ_RISE, + IRQ_FALL +} gpio_irq_event; + +typedef void (*gpio_irq_handler)(uint32_t id, gpio_irq_event event); + +int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id); +void gpio_irq_free(gpio_irq_t *obj); +void gpio_irq_set (gpio_irq_t *obj, gpio_irq_event event, uint32_t enable); +void gpio_irq_enable(gpio_irq_t *obj); +void gpio_irq_disable(gpio_irq_t *obj); + +#ifdef __cplusplus +} +#endif + +#endif + +#endif diff --git a/component/common/mbed/hal/i2c_api.h b/component/common/mbed/hal/i2c_api.h new file mode 100644 index 0000000..adc9443 --- /dev/null +++ b/component/common/mbed/hal/i2c_api.h @@ -0,0 +1,58 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * 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 MBED_I2C_API_H +#define MBED_I2C_API_H + +#include "device.h" + +#if DEVICE_I2C + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct i2c_s i2c_t; + +enum { + I2C_ERROR_NO_SLAVE = -1, + I2C_ERROR_BUS_BUSY = -2 +}; + +void i2c_init (i2c_t *obj, PinName sda, PinName scl); +void i2c_frequency (i2c_t *obj, int hz); +int i2c_start (i2c_t *obj); +int i2c_stop (i2c_t *obj); +int i2c_read (i2c_t *obj, int address, char *data, int length, int stop); +int i2c_write (i2c_t *obj, int address, const char *data, int length, int stop); +void i2c_reset (i2c_t *obj); +int i2c_byte_read (i2c_t *obj, int last); +int i2c_byte_write (i2c_t *obj, int data); + +#if DEVICE_I2CSLAVE +void i2c_slave_mode (i2c_t *obj, int enable_slave); +int i2c_slave_receive(i2c_t *obj); +int i2c_slave_read (i2c_t *obj, char *data, int length); +int i2c_slave_write (i2c_t *obj, const char *data, int length); +void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask); +#endif + +#ifdef __cplusplus +} +#endif + +#endif + +#endif diff --git a/component/common/mbed/hal/pinmap.h b/component/common/mbed/hal/pinmap.h new file mode 100644 index 0000000..653d5fe --- /dev/null +++ b/component/common/mbed/hal/pinmap.h @@ -0,0 +1,43 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * 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 MBED_PINMAP_H +#define MBED_PINMAP_H + +#include "PinNames.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + PinName pin; + int peripheral; + int function; +} PinMap; + +void pin_function(PinName pin, int function); +void pin_mode (PinName pin, PinMode mode); + +uint32_t pinmap_peripheral(PinName pin, const PinMap* map); +uint32_t pinmap_merge (uint32_t a, uint32_t b); +void pinmap_pinout (PinName pin, const PinMap *map); +uint32_t pinmap_find_peripheral(PinName pin, const PinMap* map); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/component/common/mbed/hal/port_api.h b/component/common/mbed/hal/port_api.h new file mode 100644 index 0000000..f687cfe --- /dev/null +++ b/component/common/mbed/hal/port_api.h @@ -0,0 +1,42 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * 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 MBED_PORTMAP_H +#define MBED_PORTMAP_H + +#include "device.h" + +#if DEVICE_PORTIN || DEVICE_PORTOUT + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct port_s port_t; + +PinName port_pin(PortName port, int pin_n); + +void port_init (port_t *obj, PortName port, int mask, PinDirection dir); +void port_mode (port_t *obj, PinMode mode); +void port_dir (port_t *obj, PinDirection dir); +void port_write(port_t *obj, int value); +int port_read (port_t *obj); + +#ifdef __cplusplus +} +#endif +#endif + +#endif diff --git a/component/common/mbed/hal/pwmout_api.h b/component/common/mbed/hal/pwmout_api.h new file mode 100644 index 0000000..6557fcd --- /dev/null +++ b/component/common/mbed/hal/pwmout_api.h @@ -0,0 +1,49 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * 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 MBED_PWMOUT_API_H +#define MBED_PWMOUT_API_H + +#include "device.h" + +#if DEVICE_PWMOUT + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct pwmout_s pwmout_t; + +void pwmout_init (pwmout_t* obj, PinName pin); +void pwmout_free (pwmout_t* obj); + +void pwmout_write (pwmout_t* obj, float percent); +float pwmout_read (pwmout_t* obj); + +void pwmout_period (pwmout_t* obj, float seconds); +void pwmout_period_ms (pwmout_t* obj, int ms); +void pwmout_period_us (pwmout_t* obj, int us); + +void pwmout_pulsewidth (pwmout_t* obj, float seconds); +void pwmout_pulsewidth_ms(pwmout_t* obj, int ms); +void pwmout_pulsewidth_us(pwmout_t* obj, int us); + +#ifdef __cplusplus +} +#endif + +#endif + +#endif diff --git a/component/common/mbed/hal/rtc_api.h b/component/common/mbed/hal/rtc_api.h new file mode 100644 index 0000000..663f888 --- /dev/null +++ b/component/common/mbed/hal/rtc_api.h @@ -0,0 +1,42 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * 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 MBED_RTC_API_H +#define MBED_RTC_API_H + +#include "device.h" + +#if DEVICE_RTC + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void rtc_init(void); +void rtc_free(void); +int rtc_isenabled(void); + +time_t rtc_read(void); +void rtc_write(time_t t); + +#ifdef __cplusplus +} +#endif + +#endif + +#endif diff --git a/component/common/mbed/hal/serial_api.h b/component/common/mbed/hal/serial_api.h new file mode 100644 index 0000000..2b0f0c4 --- /dev/null +++ b/component/common/mbed/hal/serial_api.h @@ -0,0 +1,78 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * 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 MBED_SERIAL_API_H +#define MBED_SERIAL_API_H + +#include "device.h" + +#if DEVICE_SERIAL + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + ParityNone = 0, + ParityOdd = 1, + ParityEven = 2, + ParityForced1 = 3, + ParityForced0 = 4 +} SerialParity; + +typedef enum { + RxIrq, + TxIrq +} SerialIrq; + +typedef enum { + FlowControlNone, + FlowControlRTS, + FlowControlCTS, + FlowControlRTSCTS +} FlowControl; + +typedef void (*uart_irq_handler)(uint32_t id, SerialIrq event); + +typedef struct serial_s serial_t; + +void serial_init (serial_t *obj, PinName tx, PinName rx); +void serial_free (serial_t *obj); +void serial_baud (serial_t *obj, int baudrate); +void serial_format (serial_t *obj, int data_bits, SerialParity parity, int stop_bits); + +void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id); +void serial_irq_set (serial_t *obj, SerialIrq irq, uint32_t enable); + +int serial_getc (serial_t *obj); +void serial_putc (serial_t *obj, int c); +int serial_readable (serial_t *obj); +int serial_writable (serial_t *obj); +void serial_clear (serial_t *obj); + +void serial_break_set (serial_t *obj); +void serial_break_clear(serial_t *obj); + +void serial_pinout_tx(PinName tx); + +void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow); + +#ifdef __cplusplus +} +#endif + +#endif + +#endif diff --git a/component/common/mbed/hal/sleep_api.h b/component/common/mbed/hal/sleep_api.h new file mode 100644 index 0000000..c8cf3b6 --- /dev/null +++ b/component/common/mbed/hal/sleep_api.h @@ -0,0 +1,64 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * 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 MBED_SLEEP_API_H +#define MBED_SLEEP_API_H + +#include "device.h" + +#if DEVICE_SLEEP + +#ifdef __cplusplus +extern "C" { +#endif + +/** Send the microcontroller to sleep + * + * The processor is setup ready for sleep, and sent to sleep using __WFI(). In this mode, the + * system clock to the core is stopped until a reset or an interrupt occurs. This eliminates + * dynamic power used by the processor, memory systems and buses. The processor, peripheral and + * memory state are maintained, and the peripherals continue to work and can generate interrupts. + * + * The processor can be woken up by any internal peripheral interrupt or external pin interrupt. + * + * @note + * The mbed interface semihosting is disconnected as part of going to sleep, and can not be restored. + * Flash re-programming and the USB serial port will remain active, but the mbed program will no longer be + * able to access the LocalFileSystem + */ +void sleep(void); + +/** Send the microcontroller to deep sleep + * + * This processor is setup ready for deep sleep, and sent to sleep using __WFI(). This mode + * has the same sleep features as sleep plus it powers down peripherals and clocks. All state + * is still maintained. + * + * The processor can only be woken up by an external interrupt on a pin or a watchdog timer. + * + * @note + * The mbed interface semihosting is disconnected as part of going to sleep, and can not be restored. + * Flash re-programming and the USB serial port will remain active, but the mbed program will no longer be + * able to access the LocalFileSystem + */ +void deepsleep(void); + +#ifdef __cplusplus +} +#endif + +#endif + +#endif diff --git a/component/common/mbed/hal/spi_api.h b/component/common/mbed/hal/spi_api.h new file mode 100644 index 0000000..f605ba3 --- /dev/null +++ b/component/common/mbed/hal/spi_api.h @@ -0,0 +1,73 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * 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 MBED_SPI_API_H +#define MBED_SPI_API_H + +#include "device.h" + +#if DEVICE_SPI + +#ifdef __cplusplus +extern "C" { +#endif + +#define SPI_DMA_RX_EN (1<<0) +#define SPI_DMA_TX_EN (1<<1) + +//#define SPI_SCLK_IDLE_LOW 0 // the SCLK is Low when SPI is inactive +//#define SPI_SCLK_IDLE_HIGH 2 // the SCLK is High when SPI is inactive +enum { + SPI_SCLK_IDLE_LOW=0, // the SCLK is Low when SPI is inactive + SPI_SCLK_IDLE_HIGH=2 // the SCLK is High when SPI is inactive +}; + +//#define SPI_CS_TOGGLE_EVERY_FRAME 0 // the CS toggle every frame +//#define SPI_CS_TOGGLE_START_STOP 1 // the CS toggle at start and stop +enum { + SPI_CS_TOGGLE_EVERY_FRAME=0, // the CS toggle every frame + SPI_CS_TOGGLE_START_STOP=1 // the CS toggle at start and stop +}; + +typedef enum { + CS_0 = 0, + CS_1 = 1, + CS_2 = 2, + CS_3 = 3, + CS_4 = 4, + CS_5 = 5, + CS_6 = 6, + CS_7 = 7 +}ChipSelect; + +typedef struct spi_s spi_t; + +void spi_init (spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel); +void spi_free (spi_t *obj); +void spi_format (spi_t *obj, int bits, int mode, int slave); +void spi_frequency (spi_t *obj, int hz); +int spi_master_write (spi_t *obj, int value); +int spi_slave_receive(spi_t *obj); +int spi_slave_read (spi_t *obj); +void spi_slave_write (spi_t *obj, int value); +int spi_busy (spi_t *obj); + +#ifdef __cplusplus +} +#endif + +#endif + +#endif diff --git a/component/common/mbed/hal/us_ticker_api.h b/component/common/mbed/hal/us_ticker_api.h new file mode 100644 index 0000000..ea62d7c --- /dev/null +++ b/component/common/mbed/hal/us_ticker_api.h @@ -0,0 +1,51 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * 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 MBED_US_TICKER_API_H +#define MBED_US_TICKER_API_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef uint64_t timestamp_t; + +uint32_t us_ticker_read(void); + +typedef void (*ticker_event_handler)(uint32_t id); +void us_ticker_set_handler(ticker_event_handler handler); + +typedef struct ticker_event_s { + timestamp_t timestamp; + uint32_t id; + struct ticker_event_s *next; +} ticker_event_t; + +void us_ticker_init(void); +void us_ticker_set_interrupt(timestamp_t timestamp); +void us_ticker_disable_interrupt(void); +void us_ticker_clear_interrupt(void); +void us_ticker_irq_handler(void); + +void us_ticker_insert_event(ticker_event_t *obj, timestamp_t timestamp, uint32_t id); +void us_ticker_remove_event(ticker_event_t *obj); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/component/common/mbed/hal_ext/dma_api.h b/component/common/mbed/hal_ext/dma_api.h new file mode 100644 index 0000000..7c627cb --- /dev/null +++ b/component/common/mbed/hal_ext/dma_api.h @@ -0,0 +1,42 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * 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 MBED_GDMA_API_H +#define MBED_GDMA_API_H + +#include "device.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct gdma_s { + HAL_GDMA_OBJ gdma_obj; + uint8_t gdma_allocated; +}; + +typedef struct gdma_s gdma_t; + +typedef void (*dma_irq_handler)(uint32_t id); + +void dma_memcpy_init(gdma_t *dma_obj, dma_irq_handler handler, uint32_t id); +void dma_memcpy_deinit(gdma_t *dma_obj); +void dma_memcpy(gdma_t *dma_obj, void *dst, void* src, uint32_t len); + +#ifdef __cplusplus +} +#endif + +#endif // end of "#define MBED_GDMA_API_H" diff --git a/component/common/mbed/hal_ext/flash_api.h b/component/common/mbed/hal_ext/flash_api.h new file mode 100644 index 0000000..375e17d --- /dev/null +++ b/component/common/mbed/hal_ext/flash_api.h @@ -0,0 +1,45 @@ +/* mbed Microcontroller Library + ******************************************************************************* + * Copyright (c) 2014, Realtek Semiconductor Corp. + * All rights reserved. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + ******************************************************************************* + */ + + #ifndef MBED_EXT_FLASH_API_EXT_H +#define MBED_EXT_FLASH_API_EXT_H + +#include "device.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct flash_s flash_t; + +/** + * global data structure + */ +extern flash_t flash; + +enum { + FLASH_COMPLETE = 0, + FLASH_ERROR_2 = 1, +}; + +//void flash_init (flash_t *obj); +void flash_erase_sector (flash_t *obj, uint32_t address); +int flash_read_word (flash_t *obj, uint32_t address, uint32_t * data); +int flash_write_word (flash_t *obj, uint32_t address, uint32_t data); +int flash_stream_read (flash_t *obj, uint32_t address, uint32_t len, uint8_t * data); +int flash_stream_write (flash_t *obj, uint32_t address, uint32_t len, uint8_t * data); +void flash_write_protect (flash_t *obj, uint32_t protect); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/component/common/mbed/hal_ext/i2s_api.h b/component/common/mbed/hal_ext/i2s_api.h new file mode 100644 index 0000000..8533af3 --- /dev/null +++ b/component/common/mbed/hal_ext/i2s_api.h @@ -0,0 +1,76 @@ +/* mbed Microcontroller Library + ******************************************************************************* + * Copyright (c) 2015, Realtek Semiconductor Corp. + * All rights reserved. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + ******************************************************************************* + */ + +#ifndef MBED_EXT_I2S_API_EXT_H +#define MBED_EXT_I2S_API_EXT_H + +#include "device.h" +#include "rtl8195a.h" +#include "hal_i2s.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + SR_8KHZ = I2S_SR_8KHZ, + SR_16KHZ = I2S_SR_16KHZ, + SR_24KHZ = I2S_SR_24KHZ, + SR_32KHZ = I2S_SR_32KHZ, + SR_48KHZ = I2S_SR_48KHZ, + SR_96KHZ = I2S_SR_96KHZ, + SR_7p35KHZ = I2S_SR_7p35KHZ, + SR_11p02KHZ = I2S_SR_11p02KHZ, + SR_22p05KHZ = I2S_SR_22p05KHZ, + SR_29p4KHZ = I2S_SR_29p4KHZ, + SR_44p1KHZ = I2S_SR_44p1KHZ, + SR_88p2KHZ = I2S_SR_88p2KHZ +}; + +enum { + CH_STEREO = I2S_CH_STEREO, + CH_MONO = I2S_CH_MONO +}; + +enum { + WL_16b = I2S_WL_16, + WL_24b = I2S_WL_24 +}; + +enum { + I2S_DIR_RX = I2S_ONLY_RX, // Rx Only + I2S_DIR_TX = I2S_ONLY_TX, // Tx Only + I2S_DIR_TXRX = I2S_TXRX // Tx & Rx (BiDirection) +}; + +typedef void (*i2s_irq_handler)(uint32_t id, char *pbuf); + +typedef struct i2s_s i2s_t; + +void i2s_init(i2s_t *obj, PinName sck, PinName ws, PinName sd); +void i2s_set_dma_buffer(i2s_t *obj, char *tx_buf, char *rx_buf, + uint32_t page_num, uint32_t page_size); +void i2s_tx_irq_handler(i2s_t *obj, i2s_irq_handler handler, uint32_t id); +void i2s_rx_irq_handler(i2s_t *obj, i2s_irq_handler handler, uint32_t id); +void i2s_set_direction(i2s_t *obj, int trx_type); +void i2s_set_param(i2s_t *obj, int channel_num, int rate, int word_len); +void i2s_deinit(i2s_t *obj); +int* i2s_get_tx_page(i2s_t *obj); +void i2s_send_page(i2s_t *obj, uint32_t *pbuf); +void i2s_recv_page(i2s_t *obj); +void i2s_enable(i2s_t *obj); +void i2s_disable(i2s_t *obj); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/component/common/mbed/hal_ext/nfc_api.h b/component/common/mbed/hal_ext/nfc_api.h new file mode 100644 index 0000000..d282568 --- /dev/null +++ b/component/common/mbed/hal_ext/nfc_api.h @@ -0,0 +1,70 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * 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 MBED_NFC_API_H +#define MBED_NFC_API_H + +#include "device.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define NFCTAGLENGTH 36 // maximum 36*4=144 bytes +#define NFC_MAX_CACHE_PAGE_NUM 36 // maximum 36*4=144 bytes + +typedef enum _NFC_STATUS_ { + NFC_OK = 0, + NFC_ERROR = -1 +}NFC_STATUS, *PNFC_STATUS; + +typedef enum _NFC_PWR_STATUS_ { + NFC_PWR_DISABLE = 0, + NFC_PWR_RUNNING = 1, + NFC_PWR_SLEEP0 = 2, + NFC_PWR_SLEEP1 = 3, + NFC_PWR_DOWN = 4, + NFC_PWR_ERROR = -1 +}NFC_PWR_STATUS, *PNFC_PWR_STATUS; + +typedef enum _NFC_EVENT_ { + NFC_EV_READER_PRESENT = (1<<0), + NFC_EV_READ = (1<<1), + NFC_EV_WRITE = (1<<2), + NFC_EV_ERR = (1<<3), + NFC_EV_CACHE_READ = (1<<4) +}NFC_EVENT, *PNFC_EVENT; + +typedef struct nfctag_s nfctag_t; + +typedef void (*nfc_read_cb)(void *arg, void *buf, unsigned int page); +typedef void(*nfc_write_cb)(void *arg, unsigned int page, uint32_t pgdat); +typedef void(*nfc_event_cb)(void *arg, unsigned int event); +typedef void(*nfc_cache_read_cb)(void *arg, void *buf, unsigned int page); + +int nfc_init(nfctag_t *obj, uint32_t *pg_init_val); +void nfc_read(nfctag_t *obj, nfc_read_cb handler, void *arg); +void nfc_write(nfctag_t *obj, nfc_write_cb handler, void *arg); +void nfc_event(nfctag_t *obj, nfc_event_cb handler, void *arg, unsigned int event_mask); +int nfc_power(nfctag_t *obj, int pwr_mode, int wake_event); +int nfc_cache_write(nfctag_t *obj, uint32_t *tbuf, unsigned int spage, unsigned int pg_num); +int nfc_cache_raed(nfctag_t *obj, nfc_cache_read_cb handler, void *arg, unsigned int start_pg); +int nfc_status(nfctag_t *obj); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/component/common/mbed/hal_ext/serial_ex_api.h b/component/common/mbed/hal_ext/serial_ex_api.h new file mode 100644 index 0000000..cd58938 --- /dev/null +++ b/component/common/mbed/hal_ext/serial_ex_api.h @@ -0,0 +1,42 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * 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 MBED_SERIAL_EX_API_H +#define MBED_SERIAL_EX_API_H + +#include "device.h" + +#if DEVICE_SERIAL + +#ifdef __cplusplus +extern "C" { +#endif + +void serial_send_comp_handler(serial_t *obj, void *handler, uint32_t id); +void serial_recv_comp_handler(serial_t *obj, void *handler, uint32_t id); +int32_t serial_recv_stream (serial_t *obj, char *prxbuf, uint32_t len); +int32_t serial_send_stream (serial_t *obj, char *ptxbuf, uint32_t len); +int32_t serial_recv_stream_dma (serial_t *obj, char *prxbuf, uint32_t len); +int32_t serial_send_stream_dma (serial_t *obj, char *ptxbuf, uint32_t len); +int32_t serial_send_stream_abort (serial_t *obj); +int32_t serial_recv_stream_abort (serial_t *obj); + +#ifdef __cplusplus +} +#endif + +#endif + +#endif // #ifndef MBED_SERIAL_EX_API_H diff --git a/component/common/mbed/hal_ext/sleep_ex_api.h b/component/common/mbed/hal_ext/sleep_ex_api.h new file mode 100644 index 0000000..19efbb0 --- /dev/null +++ b/component/common/mbed/hal_ext/sleep_ex_api.h @@ -0,0 +1,97 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * 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 MBED_SLEEP_EX_API_H +#define MBED_SLEEP_EX_API_H + +#include "device.h" + +#if DEVICE_SLEEP + +#ifdef __cplusplus +extern "C" { +#endif + +/* Sleep Eake Up event, the User application also + need to config the peripheral to trigger wake up event */ +#define SLEEP_WAKEUP_BY_STIMER (SLP_STIMER) // wake up by system timer +#define SLEEP_WAKEUP_BY_GTIMER (SLP_GTIMER) // wake up by General purpose timer timeout +#define SLEEP_WAKEUP_BY_GPIO_INT (SLP_GPIO) // wake up by GPIO Port A[7:0] Interrupt +#define SLEEP_WAKEUP_BY_WLAN (SLP_WL) // wake up by WLan event +#define SLEEP_WAKEUP_BY_NFC (SLP_NFC) // wake up by NFC event +#define SLEEP_WAKEUP_BY_SDIO (SLP_SDIO) // wake up by SDIO event +#define SLEEP_WAKEUP_BY_USB (SLP_USB) // wake up by USB event + +// Deep Standby Wakeup event +#define STANDBY_WAKEUP_BY_STIMER (BIT0) // wake up by system timer +#define STANDBY_WAKEUP_BY_NFC (BIT1) // wake up by NFC event +//#define SLEEP_WAKEUP_BY_DS_TIMER (BIT2) // The timer to wakeup from Deep Sleep timer +// Do not modify these definition, or need to modify the code also. +#define STANDBY_WAKEUP_BY_PA5 (BIT4) // GPIO Port A[5] +#define STANDBY_WAKEUP_BY_PC7 (BIT5) // GPIO Port C[7] +#define STANDBY_WAKEUP_BY_PD5 (BIT6) // GPIO Port D[5] +#define STANDBY_WAKEUP_BY_PE3 (BIT7) // GPIO Port E[3] + +// Deep Sleep Wakeup event +#define DSLEEP_WAKEUP_BY_TIMER (DS_TIMER33) +#define DSLEEP_WAKEUP_BY_GPIO (DS_GPIO) // GPIO Port B[1] + +typedef struct _SLEEP_WKUP_EVENT_ { + u8 wakeup_event; // Wake up event: Timer, NFC, GPIO + u8 gpio_option; // GPIO Wakeup setting: [3:0]: Pin 3~0 enable, [7:4]: pin3~0 active high/low + u32 timer_duration; // the sleep duration and then wakeup +} SLEEP_WAKEUP_EVENT, *PSLEEP_WAKEUP_EVENT; +/** Send the microcontroller to sleep + * + * The processor is setup ready for sleep, and sent to sleep using __WFI(). In this mode, the + * system clock to the core is stopped until a reset or an interrupt occurs. This eliminates + * dynamic power used by the processor, memory systems and buses. The processor, peripheral and + * memory state are maintained, and the peripherals continue to work and can generate interrupts. + * + * The processor can be woken up by any internal peripheral interrupt or external pin interrupt. + * + * @note + * The mbed interface semihosting is disconnected as part of going to sleep, and can not be restored. + * Flash re-programming and the USB serial port will remain active, but the mbed program will no longer be + * able to access the LocalFileSystem + */ +void sleep_ex(uint32_t wakeup_event, uint32_t sleep_duration); + +void standby_wakeup_event_add(uint32_t wakeup_event, uint32_t sleep_duration_ms, uint32_t gpio_active); +void standby_wakeup_event_del(uint32_t wakeup_event); +void deepstandby_ex(void); + +/** Send the microcontroller to deep sleep + * + * This processor is setup ready for deep sleep, and sent to sleep using __WFI(). This mode + * has the same sleep features as sleep plus it powers down peripherals and clocks. All state + * is still maintained. + * + * The processor can only be woken up by an external interrupt on a pin or a timer. + * + * @note + * The mbed interface semihosting is disconnected as part of going to sleep, and can not be restored. + * Flash re-programming and the USB serial port will remain active, but the mbed program will no longer be + * able to access the LocalFileSystem + */ +void deepsleep_ex(uint32_t wakeup_event, uint32_t sleep_duration); + +#ifdef __cplusplus +} +#endif + +#endif + +#endif diff --git a/component/common/mbed/hal_ext/spi_ex_api.h b/component/common/mbed/hal_ext/spi_ex_api.h new file mode 100644 index 0000000..89149b8 --- /dev/null +++ b/component/common/mbed/hal_ext/spi_ex_api.h @@ -0,0 +1,58 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * 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 MBED_SPI_EXT_API_H +#define MBED_SPI_EXT_API_H + +#include "device.h" + +#if DEVICE_SPI + +#ifdef __cplusplus +extern "C" { +#endif + +#define SPI_STATE_READY 0x00 +#define SPI_STATE_RX_BUSY (1<<1) +#define SPI_STATE_TX_BUSY (1<<2) + +typedef enum { + SpiRxIrq, + SpiTxIrq +} SpiIrq; + +typedef void (*spi_irq_handler)(uint32_t id, SpiIrq event); + +void spi_irq_hook(spi_t *obj, spi_irq_handler handler, uint32_t id); +int32_t spi_slave_read_stream(spi_t *obj, char *rx_buffer, uint32_t length); +int32_t spi_slave_write_stream(spi_t *obj, char *tx_buffer, uint32_t length); +int32_t spi_master_read_stream(spi_t *obj, char *rx_buffer, uint32_t length); +int32_t spi_master_write_stream(spi_t *obj, char *tx_buffer, uint32_t length); +int32_t spi_master_write_read_stream(spi_t *obj, char *tx_buffer, + char *rx_buffer, uint32_t length); +#ifdef CONFIG_GDMA_EN +int32_t spi_slave_read_stream_dma(spi_t *obj, char *rx_buffer, uint32_t length); +int32_t spi_slave_write_stream_dma(spi_t *obj, char *tx_buffer, uint32_t length); +int32_t spi_master_read_stream_dma(spi_t *obj, char *rx_buffer, uint32_t length); +int32_t spi_master_write_stream_dma(spi_t *obj, char *tx_buffer, uint32_t length); +#endif + +#ifdef __cplusplus +} +#endif + +#endif + +#endif diff --git a/component/common/mbed/hal_ext/sys_api.h b/component/common/mbed/hal_ext/sys_api.h new file mode 100644 index 0000000..73d8d54 --- /dev/null +++ b/component/common/mbed/hal_ext/sys_api.h @@ -0,0 +1,50 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * 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 MBED_WATCHDOG_API_H +#define MBED_WATCHDOG_API_H + +#include "device.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Turn off the JTAG function + * + * @return None + * + */ +void sys_jtag_off(void); +void sys_clear_ota_signature(void); +void sys_recover_ota_signature(void); +void sys_log_uart_on(void); +void sys_log_uart_off(void); +void sys_adc_calibration(u8 write, u16 *offset, u16 *gain); + +/** + * @brief system software reset + * + * @return None + * + */ +void sys_reset(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/component/common/mbed/hal_ext/wdt_api.h b/component/common/mbed/hal_ext/wdt_api.h new file mode 100644 index 0000000..7531c34 --- /dev/null +++ b/component/common/mbed/hal_ext/wdt_api.h @@ -0,0 +1,61 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * 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 MBED_WATCHDOG_API_H +#define MBED_WATCHDOG_API_H + +#include "device.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*wdt_irq_handler)(uint32_t id); + +/** Initial the watch dog time setting + * + * This function will initial and enable the watchdog timer with a given timeout value. + * When the watchdog timer timeout event is triggered, the system will be reset. User also can + * register a callback function to handle the watchdog timer timeout event. + */ +void watchdog_init(uint32_t timeout_ms); + +/** Start the watchdog counting + * + * This function will active the watchdog timer down counting. When the watchdog timer count down + * to 0, a callback function will be called or the system will be reset. + */ +void watchdog_start(void); + +/** Stop the watchdog counting + * + * This function will stop the watchdog timer down counting. If a user application aware a + * procedure may takes too long and cause the watchdog timer timeout, the application use this + * function to stop the watchdog timer to prevent the watchdog timer timeout. + */ +void watchdog_stop(void); + +/** Refresh the watchdog counting + * + * This function will reload the watchdog timer counting value. Usually a application do the watchdog + * timer reflash in the main loop to prevent the watchdog timer timeout. + */ +void watchdog_refresh(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/component/common/mbed/targets/cmsis/rtl8195a b/component/common/mbed/targets/cmsis/rtl8195a new file mode 100644 index 0000000..c9c1d60 --- /dev/null +++ b/component/common/mbed/targets/cmsis/rtl8195a @@ -0,0 +1,14 @@ +/* mbed Microcontroller Library - CMSIS + * Copyright (C) 2009-2011 ARM Limited. All rights reserved. + * + * A generic CMSIS include header, pulling in RTL8195A specifics + */ + +#ifndef MBED_CMSIS_H +#define MBED_CMSIS_H + +#include +#include + +#endif + diff --git a/component/common/mbed/targets/hal/rtl8195a/PeripheralNames.h b/component/common/mbed/targets/hal/rtl8195a/PeripheralNames.h new file mode 100644 index 0000000..1496e8f --- /dev/null +++ b/component/common/mbed/targets/hal/rtl8195a/PeripheralNames.h @@ -0,0 +1,94 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * 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 MBED_PERIPHERALNAMES_H +#define MBED_PERIPHERALNAMES_H + +#include "cmsis.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if 0 +typedef enum { + UART_1 = (int)USART1_BASE, + UART_2 = (int)USART2_BASE, + UART_3 = (int)USART3_BASE, + UART_4 = (int)UART4_BASE, + UART_5 = (int)UART5_BASE, + UART_6 = (int)USART6_BASE +} UARTName; + +typedef enum { + ADC0_0 = 0, + ADC0_1, + ADC0_2, + ADC0_3, + ADC0_4, + ADC0_5, + ADC0_6, + ADC0_7, + ADC0_8, + ADC0_9, + ADC0_10, + ADC0_11, + ADC0_12, + ADC0_13, + ADC0_14, + ADC0_15 +} ADCName; + +typedef enum { + DAC_0 = 0, + DAC_1 +} DACName; + +typedef enum { + SPI_1 = (int)SPI1_BASE, + SPI_2 = (int)SPI2_BASE, + SPI_3 = (int)SPI3_BASE, +} SPIName; + +typedef enum { + I2C_1 = (int)I2C1_BASE, + I2C_2 = (int)I2C2_BASE, + I2C_3 = (int)I2C3_BASE +} I2CName; + +typedef enum { + PWM_1 = 1, + PWM_2, + PWM_3, + PWM_4, + PWM_5, + PWM_6 +} PWMName; + +typedef enum { + CAN_1 = (int)CAN1_BASE, + CAN_2 = (int)CAN2_BASE +} CANName; +#endif + +#define STDIO_UART_TX PA_6 +#define STDIO_UART_RX PA_7 +#define STDIO_UART UART0 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/component/common/mbed/targets/hal/rtl8195a/PinNames.h b/component/common/mbed/targets/hal/rtl8195a/PinNames.h new file mode 100644 index 0000000..3b3795f --- /dev/null +++ b/component/common/mbed/targets/hal/rtl8195a/PinNames.h @@ -0,0 +1,212 @@ + +#ifndef _PINNAMES_H_ +#define _PINNAMES_H_ + +#include "cmsis.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + PORT_A = 0, + PORT_B = 1, + PORT_C = 2, + PORT_D = 3, + PORT_E = 4, + PORT_F = 5, + PORT_G = 6, + PORT_H = 7, + PORT_I = 8, + PORT_J = 9, + PORT_K = 10, + + PORT_V = 11, + PORT_MAX +} GPIO_PORT; + +#define RTL_PIN_PERI(FUN, IDX, SEL) ((int)(((FUN) << 8) | ((IDX)<<4) | (SEL))) +#define RTL_PIN_FUNC(FUN, SEL) ((int)(((FUN) << 7) | (SEL))) +#define RTL_GET_PERI_SEL(peri) ((int)((peri)&0x0F)) +#define RTL_GET_PERI_IDX(peri) ((int)(((peri) >> 4)&0x0F)) + +typedef enum { + PIN_INPUT=0, + PIN_OUTPUT +} PinDirection; + +typedef enum { + PA_0 = (PORT_A<<4|0), + PA_1 = (PORT_A<<4|1), + PA_2 = (PORT_A<<4|2), + PA_3 = (PORT_A<<4|3), + PA_4 = (PORT_A<<4|4), + PA_5 = (PORT_A<<4|5), + PA_6 = (PORT_A<<4|6), + PA_7 = (PORT_A<<4|7), + + PB_0 = (PORT_B<<4|0), + PB_1 = (PORT_B<<4|1), + PB_2 = (PORT_B<<4|2), + PB_3 = (PORT_B<<4|3), + PB_4 = (PORT_B<<4|4), + PB_5 = (PORT_B<<4|5), + PB_6 = (PORT_B<<4|6), + PB_7 = (PORT_B<<4|7), + + PC_0 = (PORT_C<<4|0), + PC_1 = (PORT_C<<4|1), + PC_2 = (PORT_C<<4|2), + PC_3 = (PORT_C<<4|3), + PC_4 = (PORT_C<<4|4), + PC_5 = (PORT_C<<4|5), + PC_6 = (PORT_C<<4|6), + PC_7 = (PORT_C<<4|7), + PC_8 = (PORT_C<<4|8), + PC_9 = (PORT_C<<4|9), + + PD_0 = (PORT_D<<4|0), + PD_1 = (PORT_D<<4|1), + PD_2 = (PORT_D<<4|2), + PD_3 = (PORT_D<<4|3), + PD_4 = (PORT_D<<4|4), + PD_5 = (PORT_D<<4|5), + PD_6 = (PORT_D<<4|6), + PD_7 = (PORT_D<<4|7), + PD_8 = (PORT_D<<4|8), + PD_9 = (PORT_D<<4|9), + + PE_0 = (PORT_E<<4|0), + PE_1 = (PORT_E<<4|1), + PE_2 = (PORT_E<<4|2), + PE_3 = (PORT_E<<4|3), + PE_4 = (PORT_E<<4|4), + PE_5 = (PORT_E<<4|5), + PE_6 = (PORT_E<<4|6), + PE_7 = (PORT_E<<4|7), + PE_8 = (PORT_E<<4|8), + PE_9 = (PORT_E<<4|9), + PE_A = (PORT_E<<4|10), + + PF_0 = (PORT_F<<4|0), + PF_1 = (PORT_F<<4|1), + PF_2 = (PORT_F<<4|2), + PF_3 = (PORT_F<<4|3), + PF_4 = (PORT_F<<4|4), + PF_5 = (PORT_F<<4|5), +// PF_6 = (PORT_F<<4|6), +// PF_7 = (PORT_F<<4|7), + + PG_0 = (PORT_G<<4|0), + PG_1 = (PORT_G<<4|1), + PG_2 = (PORT_G<<4|2), + PG_3 = (PORT_G<<4|3), + PG_4 = (PORT_G<<4|4), + PG_5 = (PORT_G<<4|5), + PG_6 = (PORT_G<<4|6), + PG_7 = (PORT_G<<4|7), + + PH_0 = (PORT_H<<4|0), + PH_1 = (PORT_H<<4|1), + PH_2 = (PORT_H<<4|2), + PH_3 = (PORT_H<<4|3), + PH_4 = (PORT_H<<4|4), + PH_5 = (PORT_H<<4|5), + PH_6 = (PORT_H<<4|6), + PH_7 = (PORT_H<<4|7), + + PI_0 = (PORT_I<<4|0), + PI_1 = (PORT_I<<4|1), + PI_2 = (PORT_I<<4|2), + PI_3 = (PORT_I<<4|3), + PI_4 = (PORT_I<<4|4), + PI_5 = (PORT_I<<4|5), + PI_6 = (PORT_I<<4|6), + PI_7 = (PORT_I<<4|7), + + PJ_0 = (PORT_J<<4|0), + PJ_1 = (PORT_J<<4|1), + PJ_2 = (PORT_J<<4|2), + PJ_3 = (PORT_J<<4|3), + PJ_4 = (PORT_J<<4|4), + PJ_5 = (PORT_J<<4|5), + PJ_6 = (PORT_J<<4|6), +// PJ_7 = (PORT_J<<4|7), + + PK_0 = (PORT_K<<4|0), + PK_1 = (PORT_K<<4|1), + PK_2 = (PORT_K<<4|2), + PK_3 = (PORT_K<<4|3), + PK_4 = (PORT_K<<4|4), + PK_5 = (PORT_K<<4|5), + PK_6 = (PORT_K<<4|6), +// PK_7 = (PORT_K<<4|7), + + AD_1 = (PORT_V<<4|1), + AD_2 = (PORT_V<<4|2), + AD_3 = (PORT_V<<4|3), + + // Arduino connector namings +/* + A0 = PA_0, + A1 = PA_1, + A2 = PA_4, + A3 = PB_0, + A4 = PC_1, + A5 = PC_0, + D0 = PA_3, + D1 = PA_2, + D2 = PA_10, + D3 = PB_3, + D4 = PB_5, + D5 = PB_4, + D6 = PB_10, + D7 = PA_8, + D8 = PA_9, + D9 = PC_7, + D10 = PB_6, + D11 = PA_7, + D12 = PA_6, + D13 = PA_5, + D14 = PB_9, + D15 = PB_8, +*/ + + // Generic signals namings + LED1 = PB_4, + LED2 = PB_5, + LED3 = PB_6, + LED4 = PB_7, + USER_BUTTON = PA_3, + SERIAL_TX = PA_7, + SERIAL_RX = PA_6, + USBTX = PA_7, + USBRX = PA_6, + I2C_SCL = PC_5, + I2C_SDA = PC_4, + SPI_MOSI = PC_2, + SPI_MISO = PC_3, + SPI_SCK = PC_1, + SPI_CS = PC_0, + PWM_OUT = PD_4, + + // Not connected + NC = (uint32_t)0xFFFFFFFF +} PinName; + +typedef enum { + PullNone = 0, + PullUp = 1, + PullDown = 2, + OpenDrain = 3, + PullDefault = PullNone +} PinMode; + +#define PORT_NUM(pin) (((uint32_t)(pin) >> 4) & 0xF) +#define PIN_NUM(pin) ((uint32_t)(pin) & 0xF) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/component/common/mbed/targets/hal/rtl8195a/PortNames.h b/component/common/mbed/targets/hal/rtl8195a/PortNames.h new file mode 100644 index 0000000..29a5324 --- /dev/null +++ b/component/common/mbed/targets/hal/rtl8195a/PortNames.h @@ -0,0 +1,38 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * 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 MBED_PORTNAMES_H +#define MBED_PORTNAMES_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + PortA = 0, + PortB = 1, + PortC = 2, + PortD = 3, + PortE = 4, + PortF = 5, + PortG = 6, + PortH = 7, + PortI = 8 +} PortName; + +#ifdef __cplusplus +} +#endif +#endif diff --git a/component/common/mbed/targets/hal/rtl8195a/analogin_api.c b/component/common/mbed/targets/hal/rtl8195a/analogin_api.c new file mode 100644 index 0000000..c09b8d0 --- /dev/null +++ b/component/common/mbed/targets/hal/rtl8195a/analogin_api.c @@ -0,0 +1,160 @@ +/* mbed Microcontroller Library + ******************************************************************************* + * Copyright (c) 2014, Realtek Semiconductor Corp. + * All rights reserved. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + ******************************************************************************* + */ + +#include "objects.h" +#include "PinNames.h" +#include "hal_adc.h" +#include "analogin_api.h" + + + +#if CONFIG_ADC_EN +//#include "cmsis.h" +#include "pinmap.h" + + +extern u32 ConfigDebugErr; +extern u32 ConfigDebuginfo; + + +void analogin_init (analogin_t *obj, PinName pin){ + + uint32_t adc_idx; + PSAL_ADC_MNGT_ADPT pSalADCMngtAdpt = NULL; + PSAL_ADC_USERCB_ADPT pSalADCUserCBAdpt = NULL; + PSAL_ADC_HND pSalADCHND = NULL; + + ConfigDebugErr &= (~(_DBG_ADC_|_DBG_GDMA_)); + ConfigDebugInfo&= (~(_DBG_ADC_|_DBG_GDMA_)); + + adc_idx = pin & 0x0F; + + /* Get I2C device handler */ + pSalADCMngtAdpt = &(obj->SalADCMngtAdpt); + pSalADCUserCBAdpt = (PSAL_ADC_USERCB_ADPT)&(obj->SalADCUserCBAdpt); + + /*To assign the rest pointers*/ + pSalADCMngtAdpt->pSalHndPriv = &(obj->SalADCHndPriv); + pSalADCMngtAdpt->pSalHndPriv->ppSalADCHnd = (void**)&(pSalADCMngtAdpt->pSalHndPriv); + + /* To assign the default (ROM) HAL OP initialization function */ + pSalADCMngtAdpt->pHalOpInit = &HalADCOpInit; + + /* To assign the default (ROM) HAL GDMA OP initialization function */ + pSalADCMngtAdpt->pHalGdmaOpInit = &HalGdmaOpInit; + + /* To assign the default (ROM) SAL interrupt function */ + pSalADCMngtAdpt->pSalIrqFunc = &ADCISRHandle; + + /* To assign the default (ROM) SAL DMA TX interrupt function */ + pSalADCMngtAdpt->pSalDMAIrqFunc = &ADCGDMAISRHandle; + + pSalADCMngtAdpt->pHalInitDat = &(obj->HalADCInitData); + pSalADCMngtAdpt->pHalOp = &(obj->HalADCOp); + pSalADCMngtAdpt->pIrqHnd = &(obj->ADCIrqHandleDat); + pSalADCMngtAdpt->pHalGdmaAdp = &(obj->HalADCGdmaAdpt); + pSalADCMngtAdpt->pHalGdmaOp = &(obj->HalADCGdmaOp); + pSalADCMngtAdpt->pIrqGdmaHnd = &(obj->ADCGdmaIrqHandleDat); + pSalADCMngtAdpt->pUserCB = &(obj->SalADCUserCB); + + /* Assign the private SAL handle to public SAL handle */ + pSalADCHND = &(pSalADCMngtAdpt->pSalHndPriv->SalADCHndPriv); + + /* Assign the internal HAL initial data pointer to the SAL handle */ + pSalADCHND->pInitDat = pSalADCMngtAdpt->pHalInitDat; + + /* Assign the internal user callback pointer to the SAL handle */ + pSalADCHND->pUserCB = pSalADCMngtAdpt->pUserCB; + + /*To assign user callback pointers*/ + pSalADCMngtAdpt->pUserCB->pTXCB = pSalADCUserCBAdpt; + pSalADCMngtAdpt->pUserCB->pTXCCB = (pSalADCUserCBAdpt+1); + pSalADCMngtAdpt->pUserCB->pRXCB = (pSalADCUserCBAdpt+2); + pSalADCMngtAdpt->pUserCB->pRXCCB = (pSalADCUserCBAdpt+3); + pSalADCMngtAdpt->pUserCB->pRDREQCB = (pSalADCUserCBAdpt+4); + pSalADCMngtAdpt->pUserCB->pERRCB = (pSalADCUserCBAdpt+5); + pSalADCMngtAdpt->pUserCB->pDMATXCB = (pSalADCUserCBAdpt+6); + pSalADCMngtAdpt->pUserCB->pDMATXCCB = (pSalADCUserCBAdpt+7); + pSalADCMngtAdpt->pUserCB->pDMARXCB = (pSalADCUserCBAdpt+8); + pSalADCMngtAdpt->pUserCB->pDMARXCCB = (pSalADCUserCBAdpt+9); + + /* Set ADC Device Number */ + pSalADCHND->DevNum = adc_idx; + + /* Load ADC default value */ + RtkADCLoadDefault(pSalADCHND); + + /* Assign ADC Pin Mux */ + pSalADCHND->PinMux = 0; + pSalADCHND->OpType = ADC_RDREG_TYPE; + + /* Init ADC now */ + pSalADCHND->pInitDat->ADCBurstSz = 8; + pSalADCHND->pInitDat->ADCOneShotTD = 8; + RtkADCInit(pSalADCHND); +} + +float analogin_read(analogin_t *obj){ + float value; + uint32_t AnaloginTmp[2] = {0,0}; + uint32_t AanloginCh = 0; + uint32_t AnaloginDatMsk = 0xFFFF; + uint8_t AnaloginIdx = 0; + uint32_t AnalogDat = 0; + + uint32_t AnalogDatFull = 0; + + PSAL_ADC_MNGT_ADPT pSalADCMngtAdpt = NULL; + PSAL_ADC_HND pSalADCHND = NULL; + + pSalADCMngtAdpt = &(obj->SalADCMngtAdpt); + pSalADCHND = &(pSalADCMngtAdpt->pSalHndPriv->SalADCHndPriv); + AnaloginIdx = pSalADCHND->DevNum; + RtkADCReceiveBuf(pSalADCHND,&AnaloginTmp[0]); + + AnaloginDatMsk = (u32)(AnaloginDatMsk<<((u32)(16*(AnaloginIdx&0x01)))); + AnalogDat = AnaloginTmp[(AnaloginIdx/2)]; + AnalogDat = (AnalogDat & AnaloginDatMsk); + AnalogDat = (AnalogDat>>((u32)(16*(AnaloginIdx&0x01)))); + + AnalogDatFull = 0xCE80; + + value = (float)(AnalogDat) / (float)(AnalogDatFull); + + return (float)value; +} + +uint16_t analogin_read_u16(analogin_t *obj){ + uint32_t AnaloginTmp[2] = {0,0}; + uint32_t AanloginCh = 0; + uint32_t AnaloginDatMsk = 0xFFFF; + uint8_t AnaloginIdx = 0; + uint32_t AnalogDat = 0; + + PSAL_ADC_MNGT_ADPT pSalADCMngtAdpt = NULL; + PSAL_ADC_HND pSalADCHND = NULL; + + pSalADCMngtAdpt = &(obj->SalADCMngtAdpt); + pSalADCHND = &(pSalADCMngtAdpt->pSalHndPriv->SalADCHndPriv); + AnaloginIdx = pSalADCHND->DevNum; + RtkADCReceiveBuf(pSalADCHND,&AnaloginTmp[0]); + + + //DBG_8195A("[0]:%08x, %08x\n", AnaloginTmp[0], AnaloginTmp[1] ); + AnaloginDatMsk = (u32)(AnaloginDatMsk<<((u32)(16*(AnaloginIdx&0x01)))); + AnalogDat = AnaloginTmp[(AnaloginIdx/2)]; + AnalogDat = (AnalogDat & AnaloginDatMsk); + AnalogDat = (AnalogDat>>((u32)(16*(AnaloginIdx&0x01)))); + + return (uint16_t)AnalogDat; + +} + +#endif diff --git a/component/common/mbed/targets/hal/rtl8195a/device.h b/component/common/mbed/targets/hal/rtl8195a/device.h new file mode 100644 index 0000000..2ab06fa --- /dev/null +++ b/component/common/mbed/targets/hal/rtl8195a/device.h @@ -0,0 +1,48 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * 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 MBED_DEVICE_H +#define MBED_DEVICE_H + +#define DEVICE_PORTIN 1 +#define DEVICE_PORTOUT 1 +#define DEVICE_PORTINOUT 1 + +#define DEVICE_INTERRUPTIN 1 + +#define DEVICE_ANALOGIN 1 +#define DEVICE_ANALOGOUT 0 + +#define DEVICE_SERIAL 1 + +#define DEVICE_I2C 1 +#define DEVICE_I2CSLAVE 1 + +#define DEVICE_SPI 1 +#define DEVICE_SPISLAVE 1 + +#define DEVICE_CAN 0 + +#define DEVICE_RTC 1 + +#define DEVICE_ETHERNET 0 + +#define DEVICE_PWMOUT 1 + +#define DEVICE_SLEEP 1 + +#include "objects.h" + +#endif diff --git a/component/common/mbed/targets/hal/rtl8195a/dma_api.c b/component/common/mbed/targets/hal/rtl8195a/dma_api.c new file mode 100644 index 0000000..316a487 --- /dev/null +++ b/component/common/mbed/targets/hal/rtl8195a/dma_api.c @@ -0,0 +1,77 @@ +/* mbed Microcontroller Library + ******************************************************************************* + * Copyright (c) 2014, Realtek + * All rights reserved. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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. + ******************************************************************************* + */ +#include "dma_api.h" +#include "cmsis.h" + +extern BOOL HalGdmaMemCpyInit(PHAL_GDMA_OBJ pHalGdmaObj); +extern VOID HalGdmaMemCpyDeInit(PHAL_GDMA_OBJ pHalGdmaObj); +extern VOID* HalGdmaMemCpy(PHAL_GDMA_OBJ pHalGdmaObj, void* pDest, void* pSrc, u32 len); + + +/** + * @brief Initial the GDMA + * + * @param dma_obj: the GDMA object + * handler: the callback function for a DMA transfer complete. + * id: the argument of the callback function. + * @return None + * + */ +void dma_memcpy_init(gdma_t *dma_obj, dma_irq_handler handler, uint32_t id) +{ + dma_obj->gdma_obj.GdmaIrqHandle.IrqFun = (IRQ_FUN)handler; + dma_obj->gdma_obj.GdmaIrqHandle.Data = (u32)id; + dma_obj->gdma_allocated = HalGdmaMemCpyInit(&(dma_obj->gdma_obj)); +} + +/** + * @brief De-Initial the GDMA + * + * @param dma_obj: the GDMA object + * @return None + * + */ +void dma_memcpy_deinit(gdma_t *dma_obj) +{ + if (dma_obj->gdma_allocated) { + HalGdmaMemCpyDeInit(&(dma_obj->gdma_obj)); + } +} + +/** + * @brief To do a memory copy by DMA + * + * @param None + * @return None + * + */ +void dma_memcpy(gdma_t *dma_obj, void *dst, void* src, uint32_t len) +{ +#if 0 + if (!dma_obj->gdma_allocated) { + dma_irq_handler handler; + + _memcpy(dst, src, len); + handler = dma_obj->GdmaIrqHandle.IrqFun; + handler(dma_obj->GdmaIrqHandle.Data); + } +#endif + HalGdmaMemCpy(&(dma_obj->gdma_obj), dst, src, len); +} + + diff --git a/component/common/mbed/targets/hal/rtl8195a/flash_api.c b/component/common/mbed/targets/hal/rtl8195a/flash_api.c new file mode 100644 index 0000000..0d628b9 --- /dev/null +++ b/component/common/mbed/targets/hal/rtl8195a/flash_api.c @@ -0,0 +1,321 @@ +/* mbed Microcontroller Library + ******************************************************************************* + * Copyright (c) 2014, Realtek Semiconductor Corp. + * All rights reserved. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + ******************************************************************************* + */ + + +#include "objects.h" +#include "PinNames.h" + + +#include "pinmap.h" + +#include "rtl8195a.h" +#include "hal_spi_flash.h" +#include "hal_platform.h" +#include "rtl8195a_spi_flash.h" +#include "hal_api.h" +#include "flash_api.h" + +extern u32 ConfigDebugInfo; + +/** + * global data structure + */ +flash_t flash; + +static void flash_init(flash_t *obj); + +/** + * @brief lock flash access + * @param none + * @retval none + */ +void flash_lock() +{ + + HAL_WRITE32(0xE000ED00, 0x9C, 0x9807E012); + HAL_WRITE32(0xE000ED00, 0xA0, 0x06000017); +} + +/** + * @brief unlock flash access + * @param none + * @retval none + */ +void flash_unlock() +{ + HAL_WRITE32(0xE000ED00, 0x9C, 0x9807E012); + HAL_WRITE32(0xE000ED00, 0xA0, 0x03000017); +} + +/** + * @brief Control the flash chip write protect enable/disable + * @param protect: 1/0: protect/unprotect + * @retval none + */ +void flash_write_protect(flash_t *obj, uint32_t protect) +{ + flash_init(obj); + SpicWriteProtectFlashRtl8195A(protect); + SpicDisableRtl8195A(); +} + +/** + * @brief Init Flash + * @param obj: address of the flash object + * @retval none + */ +static void flash_init(flash_t *obj) +{ + //SPIC_INIT_PARA spic_init_para; + + // Init SPI Flash Controller +// DBG_8195A("Initial Spi Flash Controller\n"); + SPI_FLASH_PIN_FCTRL(ON); + + if (!SpicFlashInitRtl8195A(SpicOneBitMode)){ + + DBG_8195A("SPI Init Fail!!!!!!\n"); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSTBY_INFO3, HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSTBY_INFO3)|0xf); + } + else { +// DBG_8195A("SPI Init SUCCESS\n"); + } +} + +/** + * @brief Erase flash sector + * @param address: Specifies the starting address to be erased. + * @retval none + */ +void flash_erase_sector(flash_t *obj, uint32_t address) +{ + flash_init(obj); + SpicSectorEraseFlashRtl8195A(SPI_FLASH_BASE + address); + SpicDisableRtl8195A(); +} + +/** + * @brief Read a word from specified address + * @param obj: Specifies the parameter of flash object. + * @param address: Specifies the address to be read. + * @param data: Specified the address to save the readback data. + * @retval status: Success:1 or Failure: Others. + */ +int flash_read_word(flash_t *obj, uint32_t address, uint32_t * data) +{ + + // Check address + + // Read Word + flash_init(obj); + + // Wait flash busy done (wip=0) + SpicWaitWipDoneRefinedRtl8195A(obj->SpicInitPara); + + * data = HAL_READ32(SPI_FLASH_BASE, address); + SpicDisableRtl8195A(); + + return 1; +} + +/** + * @brief Write a word to specified address + * @param obj: Specifies the parameter of flash object. + * @param address: Specifies the address to be programmed. + * @param data: Specified the data to be programmed. + * @retval status: Success:1 or Failure: Others. + */ +int flash_write_word(flash_t *obj, uint32_t address, uint32_t data) +{ + // Disable write protection +// flash_unlock(); + flash_init(obj); + + //Write word + HAL_WRITE32(SPI_FLASH_BASE, address, data); + + // Wait spic busy done + SpicWaitBusyDoneRtl8195A(); + + // Wait flash busy done (wip=0) + SpicWaitWipDoneRefinedRtl8195A(obj->SpicInitPara); + + SpicDisableRtl8195A(); + // Enable write protection +// flash_lock(); + return 1; +} + + +/** + * @brief Read a stream of data from specified address + * @param obj: Specifies the parameter of flash object. + * @param address: Specifies the address to be read. + * @param len: Specifies the length of the data to read. + * @param data: Specified the address to save the readback data. + * @retval status: Success:1 or Failure: Others. + */ +int flash_stream_read(flash_t *obj, uint32_t address, uint32_t len, uint8_t * data) +{ + u32 offset_to_align; + u32 i; + u32 read_word; + uint8_t *ptr; + uint8_t *pbuf; + + flash_init(obj); + + // Wait flash busy done (wip=0) + SpicWaitWipDoneRefinedRtl8195A(obj->SpicInitPara); + + offset_to_align = address & 0x03; + pbuf = data; + if (offset_to_align != 0) { + // the start address is not 4-bytes aligned + read_word = HAL_READ32(SPI_FLASH_BASE, (address - offset_to_align)); + ptr = (uint8_t*)&read_word + offset_to_align; + offset_to_align = 4 - offset_to_align; + for (i=0;i> 2) + 1) << 2; // address = next 4-bytes aligned + + ptr = (uint8_t*)&read_word; + if ((u32)pbuf & 0x03) { + while (len >= 4) { + read_word = HAL_READ32(SPI_FLASH_BASE, address); + for (i=0;i<4;i++) { + *pbuf = *(ptr+i); + pbuf++; + } + address += 4; + len -= 4; + } + } + else { + while (len >= 4) { + *((u32 *)pbuf) = HAL_READ32(SPI_FLASH_BASE, address); + pbuf += 4; + address += 4; + len -= 4; + } + } + + if (len > 0) { + read_word = HAL_READ32(SPI_FLASH_BASE, address); + for (i=0;iSpicInitPara); + } + + address = (((address-1) >> 2) + 1) << 2; // address = next 4-bytes aligned + + if ((u32)pbuf & 0x03) { + while (len >= 4) { + write_word = (u32)(*pbuf) | ((u32)(*(pbuf+1)) << 8) | ((u32)(*(pbuf+2)) << 16) | ((u32)(*(pbuf+3)) << 24); + //Write word + HAL_WRITE32(SPI_FLASH_BASE, address, write_word); + // Wait spic busy done + SpicWaitBusyDoneRtl8195A(); + // Wait flash busy done (wip=0) + SpicWaitWipDoneRefinedRtl8195A(obj->SpicInitPara); + pbuf += 4; + address += 4; + len -= 4; + } + } + else { + while (len >= 4) { + //Write word + HAL_WRITE32(SPI_FLASH_BASE, address, (u32)*((u32 *)pbuf)); + // Wait spic busy done + SpicWaitBusyDoneRtl8195A(); + // Wait flash busy done (wip=0) + SpicWaitWipDoneRefinedRtl8195A(obj->SpicInitPara); + pbuf += 4; + address += 4; + len -= 4; + } + } + + if (len > 0) { + write_word = HAL_READ32(SPI_FLASH_BASE, address); + ptr = (uint8_t*)&write_word; + for (i=0;iSpicInitPara); + } + + SpicDisableRtl8195A(); + return 1; +} + diff --git a/component/common/mbed/targets/hal/rtl8195a/gpio_api.c b/component/common/mbed/targets/hal/rtl8195a/gpio_api.c new file mode 100644 index 0000000..6dbf718 --- /dev/null +++ b/component/common/mbed/targets/hal/rtl8195a/gpio_api.c @@ -0,0 +1,114 @@ +/* mbed Microcontroller Library + ******************************************************************************* + * Copyright (c) 2014, Realtek Semiconductor Corp. + * All rights reserved. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + ******************************************************************************* + */ +#include "objects.h" +#include "pinmap.h" + +#if CONFIG_GPIO_EN + +#include "gpio_api.h" + +void gpio_set_hal_pin_mode(gpio_t *obj) +{ + if (obj->direction == PIN_OUTPUT) { + switch (obj->mode) { + case PullNone: + case PullDown: + case PullUp: + obj->hal_pin.pin_mode = DOUT_PUSH_PULL; + break; + + case OpenDrain: + obj->hal_pin.pin_mode = DOUT_OPEN_DRAIN; + break; + + default: + obj->hal_pin.pin_mode = DOUT_PUSH_PULL; + break; + } + } + else { + switch (obj->mode) { + case PullNone: + case OpenDrain: + obj->hal_pin.pin_mode = DIN_PULL_NONE; + break; + + case PullDown: + obj->hal_pin.pin_mode = DIN_PULL_LOW; + break; + + case PullUp: + obj->hal_pin.pin_mode = DIN_PULL_HIGH; + break; + + default: + obj->hal_pin.pin_mode = DIN_PULL_NONE; + break; + } + } +} + +uint32_t gpio_set(PinName pin) +{ + u32 ip_pin; + + //MBED_ASSERT(pin != (PinName)NC); + DBG_ASSERT(pin != (PinName)NC); + pin_function(pin, 0); + ip_pin = HAL_GPIO_GetPinName((u32)pin); +// DBG_GPIO_INFO("%s chip_pin[0x%x]->ip_pin[0x%x]\n", __FUNCTION__, pin, ip_pin); + + return ip_pin; +} + +void gpio_init(gpio_t *obj, PinName pin) +{ + if (pin == (PinName)NC) + return; + + obj->pin = pin; + obj->mode = PullNone; + obj->direction = PIN_INPUT; + obj->hal_pin.pin_name = gpio_set(pin); // get the IP pin name + obj->hal_pin.pin_mode = DIN_PULL_NONE; + HAL_GPIO_Init(&obj->hal_pin); +} + +void gpio_mode(gpio_t *obj, PinMode mode) +{ + obj->mode = mode; + gpio_set_hal_pin_mode(obj); + //DBG_GPIO_INFO("%s GPIO[0x%x], mode=%d\n", __FUNCTION__, obj->hal_pin.pin_name, obj->hal_pin.pin_mode); + HAL_GPIO_Init(&obj->hal_pin); +} + +void gpio_dir(gpio_t *obj, PinDirection direction) { +// MBED_ASSERT(obj->pin != (PinName)NC); + DBG_ASSERT(obj->pin != (PinName)NC); + obj->direction = direction; + gpio_set_hal_pin_mode(obj); + //DBG_GPIO_INFO("%s GPIO[0x%x], mode=%d\n", __FUNCTION__, obj->hal_pin.pin_name, obj->hal_pin.pin_mode); + HAL_GPIO_Init(&obj->hal_pin); +} + +void gpio_write(gpio_t *obj, int value) +{ +// MBED_ASSERT(obj->pin != (PinName)NC); + DBG_ASSERT(obj->pin != (PinName)NC); + HAL_GPIO_WritePin(&obj->hal_pin, value); +} + +int gpio_read(gpio_t *obj) { +// MBED_ASSERT(obj->pin != (PinName)NC); + DBG_ASSERT(obj->pin != (PinName)NC); + return HAL_GPIO_ReadPin(&obj->hal_pin); +} + +#endif \ No newline at end of file diff --git a/component/common/mbed/targets/hal/rtl8195a/gpio_irq_api.c b/component/common/mbed/targets/hal/rtl8195a/gpio_irq_api.c new file mode 100644 index 0000000..efce684 --- /dev/null +++ b/component/common/mbed/targets/hal/rtl8195a/gpio_irq_api.c @@ -0,0 +1,73 @@ +/* mbed Microcontroller Library + ******************************************************************************* + * Copyright (c) 2014, Realtek Semiconductor Corp. + * All rights reserved. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + ******************************************************************************* + */ +#include "objects.h" +#include "pinmap.h" + +//static uint32_t channel_ids[32] = {0}; + +//static gpio_irq_handler irq_handler; + +#if CONFIG_GPIO_EN +#include "gpio_irq_api.h" + +int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id) +{ + + if (pin == NC) return -1; + + obj->pin = pin; + obj->hal_pin.pin_name = HAL_GPIO_GetPinName((u32)pin);; // get the IP pin name + obj->hal_pin.pin_mode = INT_FALLING; // default use Falling trigger + HAL_GPIO_Irq_Init(&obj->hal_pin); + HAL_GPIO_UserRegIrq(&obj->hal_pin, (VOID*) handler, (VOID*) id); + + return 0; +} + +void gpio_irq_free(gpio_irq_t *obj) +{ + HAL_GPIO_UserUnRegIrq(&obj->hal_pin); + HAL_GPIO_DeInit(&obj->hal_pin); +} + +void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable) +{ + switch(event) { + case IRQ_RISE: + obj->hal_pin.pin_mode = INT_RISING; + break; + + case IRQ_FALL: + obj->hal_pin.pin_mode = INT_FALLING; + break; + + case IRQ_NONE: + // ? + break; + + default: + break; + } + HAL_GPIO_Irq_Init(&obj->hal_pin); + + HAL_GPIO_IntCtrl(&obj->hal_pin, enable); +} + +void gpio_irq_enable(gpio_irq_t *obj) +{ + HAL_GPIO_UnMaskIrq(&obj->hal_pin); +} + +void gpio_irq_disable(gpio_irq_t *obj) +{ + HAL_GPIO_MaskIrq(&obj->hal_pin); +} + +#endif diff --git a/component/common/mbed/targets/hal/rtl8195a/gpio_object.h b/component/common/mbed/targets/hal/rtl8195a/gpio_object.h new file mode 100644 index 0000000..63820cf --- /dev/null +++ b/component/common/mbed/targets/hal/rtl8195a/gpio_object.h @@ -0,0 +1,39 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * 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 MBED_GPIO_OBJECT_H +#define MBED_GPIO_OBJECT_H + +#include "mbed_assert.h" + +#include "basic_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + PinName pin; + uint32_t mask; + + uint32_t reg_out_offset; + uint32_t reg_dir_offset; +} gpio_t; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/component/common/mbed/targets/hal/rtl8195a/i2c_api.c b/component/common/mbed/targets/hal/rtl8195a/i2c_api.c new file mode 100644 index 0000000..7a73af1 --- /dev/null +++ b/component/common/mbed/targets/hal/rtl8195a/i2c_api.c @@ -0,0 +1,593 @@ +/* mbed Microcontroller Library + ******************************************************************************* + * Copyright (c) 2014, Realtek Semiconductor Corp. + * All rights reserved. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + ******************************************************************************* + */ + +//#include "mbed_assert.h" +#include "objects.h" +#include "PinNames.h" +//#include +#include "hal_i2c.h" +#include "i2c_api.h" + + + +#if CONFIG_I2C_EN + +//#include "cmsis.h" +#include "pinmap.h" + + +static const PinMap PinMap_I2C_SDA[] = { + {PD_4, RTL_PIN_PERI(I2C0, 0, S0), RTL_PIN_FUNC(I2C0, S0)}, + {PH_1, RTL_PIN_PERI(I2C0, 0, S1), RTL_PIN_FUNC(I2C0, S1)}, + {PC_8, RTL_PIN_PERI(I2C0, 0, S2), RTL_PIN_FUNC(I2C0, S2)}, + {PE_7, RTL_PIN_PERI(I2C0, 0, S3), RTL_PIN_FUNC(I2C0, S3)}, + + {PC_4, RTL_PIN_PERI(I2C1, 1, S0), RTL_PIN_FUNC(I2C1, S0)}, + {PH_3, RTL_PIN_PERI(I2C1, 1, S1), RTL_PIN_FUNC(I2C1, S1)}, + {PD_7, RTL_PIN_PERI(I2C1, 1, S2), RTL_PIN_FUNC(I2C1, S2)}, + + {PB_7, RTL_PIN_PERI(I2C2, 2, S0), RTL_PIN_FUNC(I2C2, S0)}, + {PE_1, RTL_PIN_PERI(I2C2, 2, S1), RTL_PIN_FUNC(I2C2, S1)}, + {PC_7, RTL_PIN_PERI(I2C2, 2, S2), RTL_PIN_FUNC(I2C2, S2)}, + + {PB_3, RTL_PIN_PERI(I2C3, 3, S0), RTL_PIN_FUNC(I2C3, S0)}, + {PE_3, RTL_PIN_PERI(I2C3, 3, S1), RTL_PIN_FUNC(I2C3, S1)}, + {PE_5, RTL_PIN_PERI(I2C3, 3, S2), RTL_PIN_FUNC(I2C3, S2)}, + {PD_9, RTL_PIN_PERI(I2C3, 3, S3), RTL_PIN_FUNC(I2C3, S3)}, + + {NC, NC, 0} +}; + +static const PinMap PinMap_I2C_SCL[] = { + {PD_5, RTL_PIN_PERI(I2C0, 0, S0), RTL_PIN_FUNC(I2C0, S0)}, + {PH_0, RTL_PIN_PERI(I2C0, 0, S1), RTL_PIN_FUNC(I2C0, S1)}, + {PC_9, RTL_PIN_PERI(I2C0, 0, S2), RTL_PIN_FUNC(I2C0, S2)}, + {PE_6, RTL_PIN_PERI(I2C0, 0, S3), RTL_PIN_FUNC(I2C0, S3)}, + + {PC_5, RTL_PIN_PERI(I2C1, 1, S0), RTL_PIN_FUNC(I2C1, S0)}, + {PH_2, RTL_PIN_PERI(I2C1, 1, S1), RTL_PIN_FUNC(I2C1, S1)}, + {PD_6, RTL_PIN_PERI(I2C1, 1, S2), RTL_PIN_FUNC(I2C1, S2)}, + + {PB_6, RTL_PIN_PERI(I2C2, 2, S0), RTL_PIN_FUNC(I2C2, S0)}, + {PE_0, RTL_PIN_PERI(I2C2, 2, S1), RTL_PIN_FUNC(I2C2, S1)}, + {PC_6, RTL_PIN_PERI(I2C2, 2, S2), RTL_PIN_FUNC(I2C2, S2)}, + + {PB_2, RTL_PIN_PERI(I2C3, 3, S0), RTL_PIN_FUNC(I2C3, S0)}, + {PE_2, RTL_PIN_PERI(I2C3, 3, S1), RTL_PIN_FUNC(I2C3, S1)}, + {PE_4, RTL_PIN_PERI(I2C3, 3, S2), RTL_PIN_FUNC(I2C3, S2)}, + {PD_8, RTL_PIN_PERI(I2C3, 3, S3), RTL_PIN_FUNC(I2C3, S3)}, + + {NC, NC, 0} +}; + +static uint16_t i2c_target_addr[4]; +static SAL_I2C_TRANSFER_BUF i2ctxtranbuf[4]; +static SAL_I2C_TRANSFER_BUF i2crxtranbuf[4]; +extern u32 ConfigDebugErr; +extern u32 ConfigDebuginfo; +void i2c_init(i2c_t *obj, PinName sda, PinName scl) { + + uint32_t i2c_sel; + uint32_t i2c_idx; + PSAL_I2C_MNGT_ADPT pSalI2CMngtAdpt = NULL; + PSAL_I2C_USERCB_ADPT pSalI2CUserCBAdpt = NULL; + PSAL_I2C_HND pSalI2CHND = NULL; + + // Determine the I2C to use + uint32_t i2c_sda = (uint32_t)pinmap_peripheral(sda, PinMap_I2C_SDA); + uint32_t i2c_scl = (uint32_t)pinmap_peripheral(scl, PinMap_I2C_SCL); + ConfigDebugErr &= (~(_DBG_I2C_|_DBG_GDMA_)); + ConfigDebugInfo&= (~(_DBG_I2C_|_DBG_GDMA_)); + i2c_sel = (uint32_t)pinmap_merge(i2c_sda, i2c_scl); + i2c_idx = RTL_GET_PERI_IDX(i2c_sel); + if (unlikely(i2c_idx == NC)) { + DBG_8195A("%s: Cannot find matched UART\n", __FUNCTION__); + return; + } + + DBG_8195A("i2c_sel:%x\n",i2c_sel); + DBG_8195A("i2c_idx:%x\n",i2c_idx); + + /* Get I2C device handler */ + pSalI2CMngtAdpt = &(obj->SalI2CMngtAdpt); + pSalI2CUserCBAdpt = (PSAL_I2C_USERCB_ADPT)&(obj->SalI2CUserCBAdpt); + + + + /*To assign the rest pointers*/ + pSalI2CMngtAdpt->MstRDCmdCnt = 0; + pSalI2CMngtAdpt->InnerTimeOut = 2000; // inner time-out count, 2000 ms + pSalI2CMngtAdpt->pSalHndPriv = &(obj->SalI2CHndPriv); + pSalI2CMngtAdpt->pSalHndPriv->ppSalI2CHnd = (void**)&(pSalI2CMngtAdpt->pSalHndPriv); + + /* To assign the default (ROM) HAL OP initialization function */ + pSalI2CMngtAdpt->pHalOpInit = &HalI2COpInit; + + /* To assign the default (ROM) HAL GDMA OP initialization function */ + pSalI2CMngtAdpt->pHalGdmaOpInit = &HalGdmaOpInit; + + /* To assign the default (ROM) SAL interrupt function */ + pSalI2CMngtAdpt->pSalIrqFunc = &I2CISRHandle; + + /* To assign the default (ROM) SAL DMA TX interrupt function */ + pSalI2CMngtAdpt->pSalDMATxIrqFunc = &I2CTXGDMAISRHandle; + + /* To assign the default (ROM) SAL DMA RX interrupt function */ + pSalI2CMngtAdpt->pSalDMARxIrqFunc = &I2CRXGDMAISRHandle; + + pSalI2CMngtAdpt->pHalInitDat = &(obj->HalI2CInitData); + pSalI2CMngtAdpt->pHalOp = &(obj->HalI2COp); + pSalI2CMngtAdpt->pIrqHnd = &(obj->I2CIrqHandleDat); + pSalI2CMngtAdpt->pHalTxGdmaAdp = &(obj->HalI2CTxGdmaAdpt); + pSalI2CMngtAdpt->pHalRxGdmaAdp = &(obj->HalI2CRxGdmaAdpt); + pSalI2CMngtAdpt->pHalGdmaOp = &(obj->HalI2CGdmaOp); + pSalI2CMngtAdpt->pIrqTxGdmaHnd = &(obj->I2CTxGdmaIrqHandleDat); + pSalI2CMngtAdpt->pIrqRxGdmaHnd = &(obj->I2CRxGdmaIrqHandleDat); + pSalI2CMngtAdpt->pUserCB = &(obj->SalI2CUserCB); + pSalI2CMngtAdpt->pDMAConf = &(obj->SalI2CDmaUserDef); + + /* Assign the private SAL handle to public SAL handle */ + pSalI2CHND = &(pSalI2CMngtAdpt->pSalHndPriv->SalI2CHndPriv); + + /* Assign the internal HAL initial data pointer to the SAL handle */ + pSalI2CHND->pInitDat = pSalI2CMngtAdpt->pHalInitDat; + + /* Assign the internal user callback pointer to the SAL handle */ + pSalI2CHND->pUserCB = pSalI2CMngtAdpt->pUserCB; + + /* Assign the internal user define DMA configuration to the SAL handle */ + pSalI2CHND->pDMAConf = pSalI2CMngtAdpt->pDMAConf; + + /*To assign user callback pointers*/ + pSalI2CMngtAdpt->pUserCB->pTXCB = pSalI2CUserCBAdpt; + pSalI2CMngtAdpt->pUserCB->pTXCCB = (pSalI2CUserCBAdpt+1); + pSalI2CMngtAdpt->pUserCB->pRXCB = (pSalI2CUserCBAdpt+2); + pSalI2CMngtAdpt->pUserCB->pRXCCB = (pSalI2CUserCBAdpt+3); + pSalI2CMngtAdpt->pUserCB->pRDREQCB = (pSalI2CUserCBAdpt+4); + pSalI2CMngtAdpt->pUserCB->pERRCB = (pSalI2CUserCBAdpt+5); + pSalI2CMngtAdpt->pUserCB->pDMATXCB = (pSalI2CUserCBAdpt+6); + pSalI2CMngtAdpt->pUserCB->pDMATXCCB = (pSalI2CUserCBAdpt+7); + pSalI2CMngtAdpt->pUserCB->pDMARXCB = (pSalI2CUserCBAdpt+8); + pSalI2CMngtAdpt->pUserCB->pDMARXCCB = (pSalI2CUserCBAdpt+9); + pSalI2CMngtAdpt->pUserCB->pGENCALLCB= (pSalI2CUserCBAdpt+10); + + /* Set I2C Device Number */ + pSalI2CHND->DevNum = i2c_idx; + + /* Load I2C default value */ + RtkI2CLoadDefault(pSalI2CHND); + + /* Assign I2C Pin Mux */ + pSalI2CHND->PinMux = RTL_GET_PERI_SEL(i2c_sel); + pSalI2CHND->OpType = I2C_INTR_TYPE; + pSalI2CHND->I2CMaster = I2C_MASTER_MODE; + pSalI2CHND->I2CSpdMod = I2C_SS_MODE; + pSalI2CHND->I2CClk = 100; + pSalI2CHND->I2CAckAddr = 0; + pSalI2CHND->TimeOut = 300; + pSalI2CHND->I2CExd |= (I2C_EXD_MTR_ADDR_RTY); + + pSalI2CMngtAdpt->InnerTimeOut = pSalI2CHND->TimeOut; + + + /* Deinit I2C first */ + //i2c_reset(obj); + + /* Init I2C now */ + RtkI2CInit(pSalI2CHND); +} + +void i2c_frequency(i2c_t *obj, int hz) { + PSAL_I2C_MNGT_ADPT pSalI2CMngtAdpt = NULL; + PSAL_I2C_HND pSalI2CHND = NULL; + pSalI2CMngtAdpt = &(obj->SalI2CMngtAdpt); + pSalI2CHND = &(pSalI2CMngtAdpt->pSalHndPriv->SalI2CHndPriv); + + uint16_t i2c_default_clk = (uint16_t) pSalI2CHND->I2CClk; + uint16_t i2c_user_clk = (uint16_t) (hz/1000); + + + + if (i2c_default_clk != i2c_user_clk) { + /* Deinit I2C first */ + i2c_reset(obj); + if (i2c_user_clk <= 100) { + pSalI2CHND->I2CSpdMod = I2C_SS_MODE; + } + else if ((i2c_user_clk > 100) && (i2c_user_clk <= 400)) { + pSalI2CHND->I2CSpdMod = I2C_FS_MODE; + } + else if (i2c_user_clk > 400) { + pSalI2CHND->I2CSpdMod = I2C_HS_MODE; + } + else { + pSalI2CHND->I2CSpdMod = I2C_SS_MODE; + } + + /* Load the user defined I2C clock */ + pSalI2CHND->I2CClk = i2c_user_clk; + + /* Init I2C now */ + RtkI2CInit(pSalI2CHND); + } +} + +inline int i2c_start(i2c_t *obj) { + return 0; +} + +inline int i2c_stop(i2c_t *obj) { + return 0; +} + +extern u32 +HalDelayUs( + IN u32 us +); + +int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) { + + PSAL_I2C_MNGT_ADPT pSalI2CMngtAdpt = NULL; + PSAL_I2C_HND pSalI2CHND = NULL; + u32 I2CInTOTcnt = 0; + u32 InTimeoutCount = 0; + u32 InStartCount = 0; + pSalI2CMngtAdpt = &(obj->SalI2CMngtAdpt); + pSalI2CHND = &(pSalI2CMngtAdpt->pSalHndPriv->SalI2CHndPriv); + + if (i2c_target_addr[pSalI2CHND->DevNum] != address) { + /* Deinit I2C first */ + i2c_reset(obj); + + /* Load the user defined I2C target slave address */ + i2c_target_addr[pSalI2CHND->DevNum] = address; + pSalI2CHND->I2CAckAddr = address; + + /* Init I2C now */ + RtkI2CInit(pSalI2CHND); + } + + /* Check if the it's the last byte or not */ + pSalI2CHND->I2CExd &= (~I2C_EXD_MTR_HOLD_BUS); + if (!stop) { + pSalI2CHND->I2CExd |= I2C_EXD_MTR_HOLD_BUS; + } + + pSalI2CHND->pRXBuf = &i2crxtranbuf[pSalI2CHND->DevNum]; + pSalI2CHND->pRXBuf->DataLen = length; + pSalI2CHND->pRXBuf->TargetAddr= pSalI2CHND->I2CAckAddr; + pSalI2CHND->pRXBuf->RegAddr = 0; + pSalI2CHND->pRXBuf->pDataBuf = (u8 *)data; + + if (RtkI2CReceive(pSalI2CHND) != HAL_OK) { + length = length - pSalI2CHND->pRXBuf->DataLen; + return ((int)length); + } + else { + //DBG_8195A(">\n"); + /* Calculate user time out parameters */ + I2CInTOTcnt = 300; + if ((I2CInTOTcnt != 0) && (I2CInTOTcnt != I2C_TIMEOOUT_ENDLESS)) { + InTimeoutCount = (I2CInTOTcnt*1000/TIMER_TICK_US); + InStartCount = HalTimerOp.HalTimerReadCount(1); + } + while((pSalI2CHND->DevSts != I2C_STS_IDLE) && + (pSalI2CHND->DevSts != I2C_STS_ERROR) && + (pSalI2CHND->DevSts != I2C_STS_TIMEOUT)) { + /* Time-Out check */ + if (InTimeoutCount > 0) { + if (HAL_TIMEOUT == I2CIsTimeout(InStartCount, InTimeoutCount)) { + pSalI2CHND->DevSts = I2C_STS_TIMEOUT; + pSalI2CHND->ErrType = I2C_ERR_RX_ADD_TO; + + /* DeInit I2C, Init I2C */ + //RtkI2CDeInit(pSalI2CHND); + //HalDelayUs(1000); + //RtkI2CInit(pSalI2CHND); + + return ((int)(length)); + } + } + else { + if (I2CInTOTcnt == 0) { + pSalI2CHND->DevSts = I2C_STS_TIMEOUT; + pSalI2CHND->ErrType = I2C_ERR_RX_ADD_TO; + /* DeInit I2C, Init I2C */ + //RtkI2CDeInit(pSalI2CHND); + + //RtkI2CInit(pSalI2CHND); + + return ((int)(length)); + } + } + } + //DBG_8195A("<\n"); + if (pSalI2CHND->DevSts != I2C_STS_TIMEOUT) + return ((int)(length - pSalI2CHND->pRXBuf->DataLen)); + else + return ((int)(length)); + } +} + +int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) { + + PSAL_I2C_MNGT_ADPT pSalI2CMngtAdpt = NULL; + PSAL_I2C_HND pSalI2CHND = NULL; + u32 I2CInTOTcnt = 0; + u32 InTimeoutCount = 0; + u32 InStartCount = 0; + + pSalI2CMngtAdpt = &(obj->SalI2CMngtAdpt); + pSalI2CHND = &(pSalI2CMngtAdpt->pSalHndPriv->SalI2CHndPriv); + + if (i2c_target_addr[pSalI2CHND->DevNum] != address) { + /* Deinit I2C first */ + i2c_reset(obj); + + /* Load the user defined I2C target slave address */ + i2c_target_addr[pSalI2CHND->DevNum] = address; + pSalI2CHND->I2CAckAddr = address; + + /* Init I2C now */ + RtkI2CInit(pSalI2CHND); + } + + /* Check if the it's the last byte or not */ + pSalI2CHND->I2CExd &= (~I2C_EXD_MTR_HOLD_BUS); + if (!stop) { + pSalI2CHND->I2CExd |= I2C_EXD_MTR_HOLD_BUS; + } + + pSalI2CHND->pTXBuf = &i2ctxtranbuf[pSalI2CHND->DevNum]; + pSalI2CHND->pTXBuf->DataLen = length; + pSalI2CHND->pTXBuf->TargetAddr= pSalI2CHND->I2CAckAddr; + pSalI2CHND->pTXBuf->RegAddr = 0; + pSalI2CHND->pTXBuf->pDataBuf = (u8 *)data; + + if (RtkI2CSend(pSalI2CHND) != HAL_OK) { + length = length - pSalI2CHND->pTXBuf->DataLen; + return ((int)length); + } + else { + //DBG_8195A("(\n"); + /* Calculate user time out parameters */ + I2CInTOTcnt = 300; + if ((I2CInTOTcnt != 0) && (I2CInTOTcnt != I2C_TIMEOOUT_ENDLESS)) { + InTimeoutCount = (I2CInTOTcnt*1000/TIMER_TICK_US); + InStartCount = HalTimerOp.HalTimerReadCount(1); + } + while((pSalI2CHND->DevSts != I2C_STS_IDLE) && + (pSalI2CHND->DevSts != I2C_STS_ERROR) && + (pSalI2CHND->DevSts != I2C_STS_TIMEOUT)) { + /* Time-Out check */ + if (InTimeoutCount > 0) { + if (HAL_TIMEOUT == I2CIsTimeout(InStartCount, InTimeoutCount)) { + pSalI2CHND->DevSts = I2C_STS_TIMEOUT; + pSalI2CHND->ErrType = I2C_ERR_TX_ADD_TO; + /* DeInit I2C, Init I2C */ + //RtkI2CDeInit(pSalI2CHND); + + //RtkI2CInit(pSalI2CHND); + return ((int)(length)); + } + } + else { + if (I2CInTOTcnt == 0) { + pSalI2CHND->DevSts = I2C_STS_TIMEOUT; + pSalI2CHND->ErrType = I2C_ERR_TX_ADD_TO; + /* DeInit I2C, Init I2C */ + //RtkI2CDeInit(pSalI2CHND); + + //RtkI2CInit(pSalI2CHND); + return ((int)(length)); + } + } + } + + if (pSalI2CHND->DevSts != I2C_STS_TIMEOUT) + return ((int)(length - pSalI2CHND->pTXBuf->DataLen)); + else + return ((int)(length)); + } +} + +int i2c_byte_read(i2c_t *obj, int last) { + uint8_t i2cdatlocal; + PSAL_I2C_MNGT_ADPT pSalI2CMngtAdpt = NULL; + PSAL_I2C_HND pSalI2CHND = NULL; + pSalI2CMngtAdpt = &(obj->SalI2CMngtAdpt); + pSalI2CHND = &(pSalI2CMngtAdpt->pSalHndPriv->SalI2CHndPriv); + + /* Check if the it's the last byte or not */ + pSalI2CHND->I2CExd &= (~I2C_EXD_MTR_HOLD_BUS); + if (!last) { + pSalI2CHND->I2CExd |= I2C_EXD_MTR_HOLD_BUS; + } + + pSalI2CHND->pRXBuf = &i2crxtranbuf[pSalI2CHND->DevNum]; + pSalI2CHND->pRXBuf->DataLen = 1; + pSalI2CHND->pRXBuf->TargetAddr= pSalI2CHND->I2CAckAddr; + pSalI2CHND->pRXBuf->RegAddr = 0; + pSalI2CHND->pRXBuf->pDataBuf = &i2cdatlocal; + RtkI2CReceive(pSalI2CHND); + + return (int)i2cdatlocal; +} + +int i2c_byte_write(i2c_t *obj, int data) { + + PSAL_I2C_MNGT_ADPT pSalI2CMngtAdpt = NULL; + PSAL_I2C_HND pSalI2CHND = NULL; + pSalI2CMngtAdpt = &(obj->SalI2CMngtAdpt); + pSalI2CHND = &(pSalI2CMngtAdpt->pSalHndPriv->SalI2CHndPriv); + + pSalI2CHND->I2CExd &= (~I2C_EXD_MTR_HOLD_BUS); + pSalI2CHND->I2CExd |= I2C_EXD_MTR_HOLD_BUS; + + pSalI2CHND->pTXBuf = &i2ctxtranbuf[pSalI2CHND->DevNum]; + pSalI2CHND->pTXBuf->DataLen = 1; + pSalI2CHND->pTXBuf->TargetAddr= pSalI2CHND->I2CAckAddr; + pSalI2CHND->pTXBuf->RegAddr = 0; + pSalI2CHND->pTXBuf->pDataBuf = (unsigned char*)&data; + + if (RtkI2CSend(pSalI2CHND) != HAL_OK) { + return 0; + } + + return 1; +} + +void i2c_reset(i2c_t *obj) { + PSAL_I2C_MNGT_ADPT pSalI2CMngtAdpt = NULL; + PSAL_I2C_HND pSalI2CHND = NULL; + pSalI2CMngtAdpt = &(obj->SalI2CMngtAdpt); + pSalI2CHND = &(pSalI2CMngtAdpt->pSalHndPriv->SalI2CHndPriv); + + /* Deinit I2C directly */ + RtkI2CDeInit(pSalI2CHND); +} + +#if DEVICE_I2CSLAVE + +void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask) { + PSAL_I2C_MNGT_ADPT pSalI2CMngtAdpt = NULL; + PSAL_I2C_HND pSalI2CHND = NULL; + pSalI2CMngtAdpt = &(obj->SalI2CMngtAdpt); + pSalI2CHND = &(pSalI2CMngtAdpt->pSalHndPriv->SalI2CHndPriv); + + uint16_t i2c_default_addr = (uint16_t) pSalI2CHND->I2CAckAddr; + uint16_t i2c_user_addr = (uint16_t) address; + + if (i2c_default_addr != i2c_user_addr) { + /* Deinit I2C first */ + i2c_reset(obj); + + /* Load the user defined I2C clock */ + pSalI2CHND->I2CAckAddr = i2c_user_addr; + + /* Init I2C now */ + RtkI2CInit(pSalI2CHND); + } +} + +void i2c_slave_mode(i2c_t *obj, int enable_slave) { + + PSAL_I2C_MNGT_ADPT pSalI2CMngtAdpt = NULL; + PSAL_I2C_HND pSalI2CHND = NULL; + pSalI2CMngtAdpt = &(obj->SalI2CMngtAdpt); + pSalI2CHND = &(pSalI2CMngtAdpt->pSalHndPriv->SalI2CHndPriv); + + /* Deinit I2C first */ + i2c_reset(obj); + + /* Load the user defined I2C clock */ + pSalI2CHND->I2CMaster = I2C_MASTER_MODE; + if (enable_slave) + pSalI2CHND->I2CMaster = I2C_SLAVE_MODE; + + /* Init I2C now */ + RtkI2CInit(pSalI2CHND); +} + +// See I2CSlave.h +#define NoData 0 // the slave has not been addressed +#define ReadAddressed 1 // the master has requested a read from this slave (slave = transmitter) +#define WriteGeneral 2 // the master is writing to all slave +#define WriteAddressed 3 // the master is writing to this slave (slave = receiver) + +int i2c_slave_receive(i2c_t *obj) { + + int i2cslvrevsts = NoData; + PSAL_I2C_MNGT_ADPT pSalI2CMngtAdpt = NULL; + PSAL_I2C_HND pSalI2CHND = NULL; + pSalI2CMngtAdpt = &(obj->SalI2CMngtAdpt); + pSalI2CHND = &(pSalI2CMngtAdpt->pSalHndPriv->SalI2CHndPriv); + + i2cslvrevsts = RtkSalI2CSts(pSalI2CHND); + return i2cslvrevsts; +} + +int i2c_slave_read(i2c_t *obj, char *data, int length) { + + u32 I2CInTOTcnt = 0; + u32 InTimeoutCount = 0; + u32 InStartCount = 0; + + //uint8_t i2cdatlocal; + PSAL_I2C_MNGT_ADPT pSalI2CMngtAdpt = NULL; + PSAL_I2C_HND pSalI2CHND = NULL; + pSalI2CMngtAdpt = &(obj->SalI2CMngtAdpt); + pSalI2CHND = &(pSalI2CMngtAdpt->pSalHndPriv->SalI2CHndPriv); + + pSalI2CHND->pRXBuf = &i2crxtranbuf[pSalI2CHND->DevNum]; + pSalI2CHND->pRXBuf->DataLen = length; + pSalI2CHND->pRXBuf->pDataBuf = (u8 *)data; + + if (RtkI2CReceive(pSalI2CHND) != HAL_OK) { + return 0; //error + } + else { + /* Calculate user time out parameters */ + I2CInTOTcnt = I2C_TIMEOOUT_ENDLESS; + if ((I2CInTOTcnt != 0) && (I2CInTOTcnt != I2C_TIMEOOUT_ENDLESS)) { + InTimeoutCount = (I2CInTOTcnt*1000/TIMER_TICK_US); + InStartCount = HalTimerOp.HalTimerReadCount(1); + } + while((pSalI2CHND->DevSts != I2C_STS_IDLE) && + (pSalI2CHND->DevSts != I2C_STS_ERROR) && + (pSalI2CHND->DevSts != I2C_STS_TIMEOUT)) { + /* Time-Out check */ + if (InTimeoutCount > 0) { + if (HAL_TIMEOUT == I2CIsTimeout(InStartCount, InTimeoutCount)) { + pSalI2CHND->DevSts = I2C_STS_TIMEOUT; + pSalI2CHND->ErrType = I2C_ERR_RX_ADD_TO; + return ((int)(length)); + } + } + else { + if (I2CInTOTcnt == 0) { + pSalI2CHND->DevSts = I2C_STS_TIMEOUT; + pSalI2CHND->ErrType = I2C_ERR_RX_ADD_TO; + return ((int)(length)); + } + } + } + + if (pSalI2CHND->DevSts != I2C_STS_TIMEOUT) + return ((int)(length - pSalI2CHND->pTXBuf->DataLen)); + else + return ((int)(length)); + } +} + +int i2c_slave_write(i2c_t *obj, const char *data, int length) { + PSAL_I2C_MNGT_ADPT pSalI2CMngtAdpt = NULL; + PSAL_I2C_HND pSalI2CHND = NULL; + pSalI2CMngtAdpt = &(obj->SalI2CMngtAdpt); + pSalI2CHND = &(pSalI2CMngtAdpt->pSalHndPriv->SalI2CHndPriv); + + pSalI2CHND->pTXBuf = &i2ctxtranbuf[pSalI2CHND->DevNum]; + pSalI2CHND->pTXBuf->DataLen = length; + //obj->i2c->pTXBuf->TargetAddr= obj->i2c->I2CAckAddr; + //obj->i2c->pTXBuf->RegAddr = 0; + pSalI2CHND->pTXBuf->pDataBuf = (u8 *)data; + + if (RtkI2CSend(pSalI2CHND) != HAL_OK) { + return 0; //error + } + + return 1; +} + + +#endif // CONFIG_I2C_SLAVE_EN + +#endif // CONFIG_I2C_EN + diff --git a/component/common/mbed/targets/hal/rtl8195a/i2s_api.c b/component/common/mbed/targets/hal/rtl8195a/i2s_api.c new file mode 100644 index 0000000..a4b7ee5 --- /dev/null +++ b/component/common/mbed/targets/hal/rtl8195a/i2s_api.c @@ -0,0 +1,244 @@ +/* mbed Microcontroller Library + ******************************************************************************* + * Copyright (c) 2015, Realtek Semiconductor Corp. + * All rights reserved. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + ******************************************************************************* + */ +#include "objects.h" +#include "i2s_api.h" +#include "pinmap.h" + +#if CONFIG_I2S_EN +static const PinMap PinMap_I2S_TX[] = { + {PE_2, RTL_PIN_PERI(I2S0, 0, S0), RTL_PIN_FUNC(I2S0, S0)}, + {PH_2, RTL_PIN_PERI(I2S0, 0, S1), RTL_PIN_FUNC(I2S0, S1)}, + {PD_2, RTL_PIN_PERI(I2S0, 0, S2), RTL_PIN_FUNC(I2S0, S2)}, + {PC_7, RTL_PIN_PERI(I2S0, 0, S3), RTL_PIN_FUNC(I2S0, S3)}, + {PC_2, RTL_PIN_PERI(I2S1, 1, S0), RTL_PIN_FUNC(I2S1, S0)}, + {PD_6, RTL_PIN_PERI(I2S1, 1, S1), RTL_PIN_FUNC(I2S1, S1)}, + {PE_6, RTL_PIN_PERI(I2S1, 1, S2), RTL_PIN_FUNC(I2S1, S2)}, + {NC, NC, 0} +}; + +static const PinMap PinMap_I2S_RX[] = { + {PH_5, RTL_PIN_PERI(I2S0, 0, S1), RTL_PIN_FUNC(I2S0, S1)}, + {PC_5, RTL_PIN_PERI(I2S0, 0, S3), RTL_PIN_FUNC(I2S0, S3)}, + {PC_4, RTL_PIN_PERI(I2S1, 1, S0), RTL_PIN_FUNC(I2S1, S0)}, + {PD_3, RTL_PIN_PERI(I2S1, 1, S1), RTL_PIN_FUNC(I2S1, S1)}, + {PE_8, RTL_PIN_PERI(I2S1, 1, S2), RTL_PIN_FUNC(I2S1, S1)}, + {NC, NC, 0} +}; + +static const PinMap PinMap_I2S_CLK[] = { + {PE_1, RTL_PIN_PERI(I2S0, 0, S0), RTL_PIN_FUNC(I2S0, S0)}, + {PH_1, RTL_PIN_PERI(I2S0, 0, S1), RTL_PIN_FUNC(I2S0, S1)}, + {PD_1, RTL_PIN_PERI(I2S0, 0, S2), RTL_PIN_FUNC(I2S0, S2)}, + {PC_8, RTL_PIN_PERI(I2S0, 0, S3), RTL_PIN_FUNC(I2S0, S3)}, + {PC_1, RTL_PIN_PERI(I2S1, 1, S0), RTL_PIN_FUNC(I2S1, S0)}, + {PD_5, RTL_PIN_PERI(I2S1, 1, S1), RTL_PIN_FUNC(I2S1, S1)}, + {PE_5, RTL_PIN_PERI(I2S1, 1, S2), RTL_PIN_FUNC(I2S1, S2)}, + {NC, NC, 0} +}; + +static const PinMap PinMap_I2S_WS[] = { + {PE_0, RTL_PIN_PERI(I2S0, 0, S0), RTL_PIN_FUNC(I2S0, S0)}, + {PH_0, RTL_PIN_PERI(I2S0, 0, S1), RTL_PIN_FUNC(I2S0, S1)}, + {PD_0, RTL_PIN_PERI(I2S0, 0, S2), RTL_PIN_FUNC(I2S0, S2)}, + {PC_9, RTL_PIN_PERI(I2S0, 0, S3), RTL_PIN_FUNC(I2S0, S3)}, + {PC_0, RTL_PIN_PERI(I2S1, 1, S0), RTL_PIN_FUNC(I2S1, S0)}, + {PD_4, RTL_PIN_PERI(I2S1, 1, S1), RTL_PIN_FUNC(I2S1, S1)}, + {PE_4, RTL_PIN_PERI(I2S1, 1, S2), RTL_PIN_FUNC(I2S1, S2)}, + {NC, NC, 0} +}; + +static const HAL_I2S_DEF_SETTING I2SDefaultSetting = { + .I2SMaster = I2S_MASTER_MODE, // I2S Function Mode + .DevSts = I2S_STS_UNINITIAL, //I2S device status + .I2SChNum = I2S_CH_STEREO, //I2S Channel number mono or stereo + .I2SPageNum = I2S_4PAGE, //I2S Page number 2~4 + .I2STRxAct = I2S_TXRX, //I2S tx rx act, tx only or rx only or tx+rx + .I2SWordLen = I2S_WL_16, //I2S Word length 16bit or 24bit + .I2SPageSize = (768/4)-1, //I2S Page size 1~4096 word + .I2SRate = I2S_SR_48KHZ, //I2S sample rate 8k ~ 96khz + + .I2STxIntrMSK = I2S_TX_INT_PAGE0_OK|I2S_TX_INT_PAGE1_OK| \ + I2S_TX_INT_PAGE2_OK|I2S_TX_INT_PAGE3_OK, /*I2S Tx Interrupt Mask*/ + .I2SRxIntrMSK = I2S_RX_INT_PAGE0_OK|I2S_RX_INT_PAGE1_OK| \ + I2S_RX_INT_PAGE2_OK|I2S_RX_INT_PAGE3_OK /*I2S Rx Interrupt Mask*/ +}; + +void i2s_init(i2s_t *obj, PinName sck, PinName ws, PinName sd) +{ + uint32_t i2s_sck, i2s_ws, i2s_tx, i2s_rx; + uint32_t i2s_sck_ws, i2s_sel;; + uint8_t i2s_idx; + PHAL_I2S_ADAPTER pI2SAdapter = (PHAL_I2S_ADAPTER) &obj->I2SAdapter; + u8 trx_act; + + // Determine the UART to use (UART0, UART1, or UART3) + i2s_sck = pinmap_peripheral(sck, PinMap_I2S_CLK); + i2s_ws = pinmap_peripheral(ws, PinMap_I2S_WS); + i2s_tx = pinmap_peripheral(sd, PinMap_I2S_TX); + i2s_rx = pinmap_peripheral(sd, PinMap_I2S_RX); + + i2s_sck_ws = pinmap_merge(i2s_sck, i2s_ws); + if (unlikely(i2s_sck_ws == NC)) { + DBG_I2S_ERR("%s: Cannot find matched I2S for given pin\n", __FUNCTION__); + return; + } + + trx_act = I2S_TXRX; + i2s_sel = pinmap_merge(i2s_sck_ws, i2s_tx); + if (i2s_sel == NC) { + i2s_sel = pinmap_merge(i2s_sck_ws, i2s_rx); + trx_act = I2S_ONLY_RX; + if (unlikely(i2s_sel == NC)) { + DBG_I2S_ERR("%s: Cannot find matched I2S for given pin\n", __FUNCTION__); + return; + } + } + + i2s_idx = RTL_GET_PERI_IDX(i2s_sel); + + pI2SAdapter->DevNum = i2s_idx; + pI2SAdapter->PinMux = RTL_GET_PERI_SEL(i2s_sel);; + DBG_I2S_INFO("%s: Use I2S%d Sel%d\r\n", __FUNCTION__, pI2SAdapter->DevNum, pI2SAdapter->PinMux); + + pI2SAdapter->pInitDat = &obj->InitDat; + RtkI2SLoadDefault(pI2SAdapter, (VOID*)&I2SDefaultSetting); + pI2SAdapter->pInitDat->I2STRxAct = trx_act; + + // Load user defined parameters + pI2SAdapter->pInitDat->I2SChNum = obj->channel_num; + pI2SAdapter->pInitDat->I2SRate = obj->sampling_rate; + pI2SAdapter->pInitDat->I2SWordLen = obj->word_length; + pI2SAdapter->pInitDat->I2STRxAct = obj->direction; + + RtkI2SInit(pI2SAdapter); +} + +void i2s_set_dma_buffer(i2s_t *obj, char *tx_buf, char *rx_buf, + uint32_t page_num, uint32_t page_size) +{ + PHAL_I2S_ADAPTER pI2SAdapter = (PHAL_I2S_ADAPTER) &obj->I2SAdapter; + u32 i; + + if ((page_num < 2) || (page_num > 4) || (page_size < 8)) { + DBG_I2S_INFO("%s: PageNum(%d) valid value is 2~4; PageSize(%d must > 8)\r\n", \ + __FUNCTION__, page_num, page_size); + return; + } + + pI2SAdapter->pInitDat->I2SPageNum = page_num - 1; + pI2SAdapter->pInitDat->I2SPageSize = page_size/4 - 1; // unit is 4-bytes + pI2SAdapter->pInitDat->I2STxData = (u8*)tx_buf; + pI2SAdapter->pInitDat->I2SRxData = (u8*)rx_buf; + HalI2SSetDMABuf(pI2SAdapter->pInitDat); + + for (i=0;iTxPageList[i] = (uint32_t*)(tx_buf + ((page_size) * i)); + pI2SAdapter->RxPageList[i] = (uint32_t*)(rx_buf + ((page_size) * i)); + } +} + +void i2s_tx_irq_handler(i2s_t *obj, i2s_irq_handler handler, uint32_t id) +{ + PHAL_I2S_ADAPTER pI2SAdapter = (PHAL_I2S_ADAPTER) &obj->I2SAdapter; + + pI2SAdapter->UserCB.TxCCB = handler; + pI2SAdapter->UserCB.TxCBId = id; +} + +void i2s_rx_irq_handler(i2s_t *obj, i2s_irq_handler handler, uint32_t id) +{ + PHAL_I2S_ADAPTER pI2SAdapter = (PHAL_I2S_ADAPTER) &obj->I2SAdapter; + + pI2SAdapter->UserCB.RxCCB = handler; + pI2SAdapter->UserCB.RxCBId = id; +} + +void i2s_set_direction(i2s_t *obj, int trx_type) +{ + PHAL_I2S_ADAPTER pI2SAdapter = (PHAL_I2S_ADAPTER) &obj->I2SAdapter; + + obj->direction = trx_type; + pI2SAdapter->pInitDat->I2STRxAct = trx_type; + HalI2SSetDirection(pI2SAdapter->pInitDat); +} + +void i2s_set_param(i2s_t *obj, int channel_num, int rate, int word_len) +{ + PHAL_I2S_ADAPTER pI2SAdapter = (PHAL_I2S_ADAPTER) &obj->I2SAdapter; + + obj->channel_num = channel_num; + obj->sampling_rate = rate; + obj->word_length = word_len; + pI2SAdapter->pInitDat->I2SChNum = channel_num; + pI2SAdapter->pInitDat->I2SRate = rate; + pI2SAdapter->pInitDat->I2SWordLen = word_len; + HalI2SSetChNum(pI2SAdapter->pInitDat); + HalI2SSetRate(pI2SAdapter->pInitDat); + HalI2SSetWordLen(pI2SAdapter->pInitDat); +} + +void i2s_deinit(i2s_t *obj) +{ + RtkI2SDeInit((VOID*)&obj->I2SAdapter); +} + +int* i2s_get_tx_page(i2s_t *obj) +{ + PHAL_I2S_ADAPTER pI2SAdapter = (PHAL_I2S_ADAPTER) &obj->I2SAdapter; + u8 page_idx; + + page_idx = HalI2SGetTxPage((VOID*)pI2SAdapter->pInitDat); + if (page_idx <= pI2SAdapter->pInitDat->I2SPageNum) { + return ((int*)pI2SAdapter->TxPageList[page_idx]); + } else { + return NULL; + } +} + +void i2s_send_page(i2s_t *obj, uint32_t *pbuf) +{ + PHAL_I2S_ADAPTER pI2SAdapter = (PHAL_I2S_ADAPTER) &obj->I2SAdapter; + u32 page_num, i; + + page_num = pI2SAdapter->pInitDat->I2SPageNum + 1; + for (i=0;iTxPageList[i] == pbuf) { + HalI2SPageSend(pI2SAdapter->pInitDat, i); + break; // break the for loop + } + } + + if (i == page_num) { + DBG_I2S_ERR("i2s_send_page: the pbuf(0x%x) is not a DMA buffer\r\n", pbuf); + } +} + +void i2s_recv_page(i2s_t *obj) +{ + PHAL_I2S_ADAPTER pI2SAdapter = (PHAL_I2S_ADAPTER) &obj->I2SAdapter; + + HalI2SPageRecv(pI2SAdapter->pInitDat); +} + +void i2s_enable(i2s_t *obj) +{ + PHAL_I2S_ADAPTER pI2SAdapter = (PHAL_I2S_ADAPTER) &obj->I2SAdapter; + + RtkI2SEnable(pI2SAdapter); +} + +void i2s_disable(i2s_t *obj) +{ + PHAL_I2S_ADAPTER pI2SAdapter = (PHAL_I2S_ADAPTER) &obj->I2SAdapter; + + RtkI2SDisable(pI2SAdapter); +} + +#endif // end of "#if CONFIG_I2S_EN" diff --git a/component/common/mbed/targets/hal/rtl8195a/nfc_api.c b/component/common/mbed/targets/hal/rtl8195a/nfc_api.c new file mode 100644 index 0000000..87aa22d --- /dev/null +++ b/component/common/mbed/targets/hal/rtl8195a/nfc_api.c @@ -0,0 +1,243 @@ +/* mbed Microcontroller Library + ******************************************************************************* + * Copyright (c) 2014, Realtek Semiconductor Corp. + * All rights reserved. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + ******************************************************************************* + */ +#include "objects.h" +#include "pinmap.h" + +#if CONFIG_NFC_NORMAL + +#include "nfc_api.h" + +/** + * @brief The NFC tag write callback function wrapper + * + * @return None + * + */ +void nfc_tagwrite_callback(PNFC_ADAPTER pNFCAdp, uint32_t page, uint32_t wr_data) +{ + nfctag_t *obj; + nfc_write_cb handler; + + obj = pNFCAdp->nfc_obj; + + handler = (nfc_write_cb)obj->nfc_wr_cb; + if (NULL != handler) { + handler(obj->wr_cb_arg, page, wr_data); + } +} + +/** + * @brief The NFC tag read callback function wrapper + * + * @return None + * + */ +void nfc_event_callback(PNFC_ADAPTER pNFCAdp, uint32_t event) +{ + nfctag_t *obj; + nfc_event_cb handler; + + obj = pNFCAdp->nfc_obj; + + handler = (nfc_event_cb)obj->nfc_ev_cb; + if (NULL != handler) { + if (obj->event_mask & event) { + handler(obj->ev_cb_arg, event); + } + } +} + +/** + * @brief The NFC tag read callback function wrapper + * + * @return None + * + */ +void nfc_tagread_callback(PNFC_ADAPTER pNFCAdp, uint32_t page) +{ + // notify upper layer when read tag page 0 only + if (0 == page) { + nfc_event_callback(pNFCAdp, NFC_EV_READ); + } +} + + +/** + * @brief The NFC cache read done callback function wrapper + * + * @return None + * + */ +void nfc_cache_read_callback(PNFC_ADAPTER pNFCAdp, uint32_t start_pg, uint32_t *pbuf) +{ + nfctag_t *obj; + nfc_write_cb handler; + + obj = pNFCAdp->nfc_obj; + + handler = (nfc_write_cb)obj->nfc_cache_rd_cb; + if (NULL != handler) { + handler(obj->cache_read_cb_arg, start_pg, (uint32_t)pbuf); + } +} + +/** + * @brief To initial NFC tag hardware and resource + * + * @return The result + * + */ +int nfc_init(nfctag_t *obj, uint32_t *pg_init_val) +{ + _memset((void *)obj, 0, sizeof(nfctag_t)); + HalNFCDmemInit(pg_init_val, NFCTAGLENGTH); + HalNFCInit(&(obj->NFCAdapter)); + HalNFCFwDownload(); + obj->NFCAdapter.nfc_obj = obj; + obj->pwr_status = NFC_PWR_RUNNING; + + return NFC_OK; +} + +/** + * @brief To free NFC tag hardware and resource + * + * @return The result + * + */ +int nfc_free(nfctag_t *obj) +{ + HalNFCDeinit(&(obj->NFCAdapter)); + return NFC_OK; +} + +/** + * @brief To register the callback function for NFC read occurred + * + * @return None + * + */ +void nfc_read(nfctag_t *obj, nfc_read_cb handler, void *arg) +{ + obj->nfc_rd_cb = (void *)handler; + obj->rd_cb_arg = arg; +} + +/** + * @brief To register the callback function for NFC write occurred + * + * @return None + * + */ +void nfc_write(nfctag_t *obj, nfc_write_cb handler, void *arg) +{ + obj->nfc_wr_cb = (void *)handler; + obj->wr_cb_arg = arg; +} + +/** + * @brief To register the callback function for NFC events occurred + * and the event mask + * + * @return None + * + */ +void nfc_event(nfctag_t *obj, nfc_event_cb handler, void *arg, unsigned int event_mask) +{ + obj->nfc_ev_cb = (void *)handler; + obj->ev_cb_arg = arg; + obj->event_mask = event_mask; +} + +/** + * @brief To set a new power mode to the NFC device + * + * @return The result + * + */ +int nfc_power(nfctag_t *obj, int pwr_mode, int wake_event) +{ + // TODO: + + return NFC_OK; +} + + +/** + * @brief to update the NFC read cache. The data in the NFC read cache + * buffer will be transmitted out when NFC read occurred + * + * @return The result + * + */ +int nfc_cache_write(nfctag_t *obj, uint32_t *tbuf, unsigned int spage, unsigned int pg_num) +{ + u8 remain_pg; + u8 pg_offset=0; + u8 i; + + if ((spage+pg_num) > NFC_MAX_CACHE_PAGE_NUM) { + return NFC_ERROR; + } + + remain_pg = pg_num; + while (remain_pg > 0) { + if (remain_pg >= 4) { + A2NWriteCatch (&obj->NFCAdapter, (spage+pg_offset), 4, (u32*)(&tbuf[pg_offset])); + remain_pg -= 4; + pg_offset += 4; + } + else { + for(i=0;iNFCAdapter, (spage+pg_offset), 1, (u32*)(&tbuf[pg_offset])); + pg_offset++; + } + remain_pg = 0; + } + } + + return NFC_OK; +} + +/** + * @brief To get current NFC status + * + * @return The result + * + */ +int nfc_cache_raed(nfctag_t *obj, nfc_cache_read_cb handler, + void *arg, unsigned int start_pg) +{ + if (start_pg > NFC_MAX_CACHE_PAGE_NUM) { + return NFC_ERROR; + } + + obj->nfc_cache_rd_cb = (void *)handler; + obj->cache_read_cb_arg = arg; + + A2NReadCatch(&(obj->NFCAdapter), (u8)start_pg); + + return NFC_OK; +} + +/** + * @brief to read back the NFC read cache. + * + * @return The result + * + */ +int nfc_status(nfctag_t *obj) +{ + // TODO: + + return (obj->pwr_status); +} + +#endif diff --git a/component/common/mbed/targets/hal/rtl8195a/objects.h b/component/common/mbed/targets/hal/rtl8195a/objects.h new file mode 100644 index 0000000..0cf6346 --- /dev/null +++ b/component/common/mbed/targets/hal/rtl8195a/objects.h @@ -0,0 +1,174 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * 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 MBED_OBJECTS_H +#define MBED_OBJECTS_H + +#include "cmsis.h" +#include "PortNames.h" +#include "PeripheralNames.h" +#include "PinNames.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef CONFIG_GPIO_EN +struct gpio_irq_s { + PinName pin; + uint32_t event; + HAL_GPIO_PIN hal_pin; +}; + +typedef struct gpio_irq_s gpio_irq_t; + +struct gpio_s { + PinName pin; + PinMode mode; + PinDirection direction; + HAL_GPIO_PIN hal_pin; +}; + +typedef struct gpio_s gpio_t; + +struct port_s { + PortName port; + uint32_t mask; + PinDirection direction; + uint8_t *pin_def; +}; +#endif // end of "#ifdef CONFIG_GPIO_EN" + +#ifdef CONFIG_UART_EN +struct serial_s { + HAL_RUART_OP hal_uart_op; + HAL_RUART_ADAPTER hal_uart_adp; +#ifdef CONFIG_GDMA_EN + UART_DMA_CONFIG uart_gdma_cfg; + HAL_GDMA_ADAPTER uart_gdma_adp_tx; + HAL_GDMA_ADAPTER uart_gdma_adp_rx; +#endif +}; +#endif // end of "#ifdef CONFIG_UART_EN" + +#ifdef CONFIG_SPI_COM_EN + +#endif + +#ifdef CONFIG_PWM_EN +struct pwmout_s { + uint8_t pwm_idx; + uint8_t pin_sel; + uint32_t period; + uint32_t pulse; + +}; +#endif + +#ifdef CONFIG_I2C_EN +struct i2c_s { + SAL_I2C_MNGT_ADPT SalI2CMngtAdpt; + SAL_I2C_HND_PRIV SalI2CHndPriv; + HAL_I2C_INIT_DAT HalI2CInitData; + HAL_I2C_OP HalI2COp; + IRQ_HANDLE I2CIrqHandleDat; + HAL_GDMA_ADAPTER HalI2CTxGdmaAdpt; + HAL_GDMA_ADAPTER HalI2CRxGdmaAdpt; + HAL_GDMA_OP HalI2CGdmaOp; + IRQ_HANDLE I2CTxGdmaIrqHandleDat; + IRQ_HANDLE I2CRxGdmaIrqHandleDat; + SAL_I2C_USER_CB SalI2CUserCB; + SAL_I2C_USERCB_ADPT SalI2CUserCBAdpt[SAL_USER_CB_NUM]; + SAL_I2C_DMA_USER_DEF SalI2CDmaUserDef; +}; +#endif + + +struct flash_s +{ + SPIC_INIT_PARA SpicInitPara; +}; + + + +#ifdef CONFIG_ADC_EN +struct analogin_s { + SAL_ADC_MNGT_ADPT SalADCMngtAdpt; + SAL_ADC_HND_PRIV SalADCHndPriv; + HAL_ADC_INIT_DAT HalADCInitData; + HAL_ADC_OP HalADCOp; + IRQ_HANDLE ADCIrqHandleDat; + HAL_GDMA_ADAPTER HalADCGdmaAdpt; + HAL_GDMA_OP HalADCGdmaOp; + IRQ_HANDLE ADCGdmaIrqHandleDat; + SAL_ADC_USER_CB SalADCUserCB; + SAL_ADC_USERCB_ADPT SalADCUserCBAdpt[SAL_USER_CB_NUM]; +}; +#endif + +#if 0 +struct i2c_s { + I2C_Type *i2c; +}; + +struct spi_s { + SPI_Type *spi; +}; + +#endif + +#ifdef CONFIG_NFC_EN +struct nfctag_s { + NFC_ADAPTER NFCAdapter; + void *nfc_rd_cb; // read callback function + void *rd_cb_arg; + void *nfc_wr_cb; // write callback function + void *wr_cb_arg; + void *nfc_ev_cb; // event callback function + void *ev_cb_arg; + void *nfc_cache_rd_cb; // cache read callback function + void *cache_read_cb_arg; + unsigned int event_mask; + int pwr_status; +}; +#endif + +#ifdef CONFIG_TIMER_EN +struct gtimer_s { + TIMER_ADAPTER hal_gtimer_adp; + void *handler; + u32 hid; + u8 timer_id; + u8 is_periodcal; +}; +#endif + +#ifdef CONFIG_I2S_EN +struct i2s_s { + HAL_I2S_ADAPTER I2SAdapter; + HAL_I2S_INIT_DAT InitDat; + u8 sampling_rate; + u8 channel_num; + u8 word_length; + u8 direction; +}; + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/component/common/mbed/targets/hal/rtl8195a/pinmap.c b/component/common/mbed/targets/hal/rtl8195a/pinmap.c new file mode 100644 index 0000000..c0dfdf0 --- /dev/null +++ b/component/common/mbed/targets/hal/rtl8195a/pinmap.c @@ -0,0 +1,34 @@ +/* mbed Microcontroller Library + ******************************************************************************* + * Copyright (c) 2014, Realtek Semiconductor Corp. + * All rights reserved. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + ******************************************************************************* + */ +//#include "mbed_assert.h" +#include "objects.h" +#include "pinmap.h" +//#include "error.h" + +/** + * Configure pin enable and function + */ +void pin_function(PinName pin, int function) +{ + // MBED_ASSERT(pin != (PinName)NC); + //1 Our HAL API cannot support to configure the pin function by this way + /* the pin function (pin mux) is depends on each IP On/Off and priority, so we cannot + set the pin function directly */ +} + +/** + * Configure pin pull-up/pull-down + */ +void pin_mode(PinName pin, PinMode mode) +{ +// MBED_ASSERT(pin != (PinName)NC); + HAL_GPIO_PullCtrl((u32)pin, (u32)mode); + +} diff --git a/component/common/mbed/targets/hal/rtl8195a/pinmap_common.c b/component/common/mbed/targets/hal/rtl8195a/pinmap_common.c new file mode 100644 index 0000000..1a1001a --- /dev/null +++ b/component/common/mbed/targets/hal/rtl8195a/pinmap_common.c @@ -0,0 +1,73 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * 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. + */ +#include "basic_types.h" +#include "diag.h" +#include "pinmap.h" +//#include "error.h" + +__weak void pinmap_pinout(PinName pin, const PinMap *map) { +#if 0 + if (pin == NC) + return; + + while (map->pin != NC) { + if (map->pin == pin) { + pin_function(pin, map->function); + + pin_mode(pin, PullNone); + return; + } + map++; + } + DBG_GPIO_ERR("%s: could not pinout\n", __FUNCTION__); +#endif +} + +__weak uint32_t pinmap_merge(uint32_t a, uint32_t b) { + // both are the same (inc both NC) + if (a == b) + return a; + + // one (or both) is not connected + if (a == (uint32_t)NC) + return b; + if (b == (uint32_t)NC) + return a; + + // mis-match error case + DBG_GPIO_ERR("%s: pinmap mis-match\n", __FUNCTION__); + return (uint32_t)NC; +} + +__weak uint32_t pinmap_find_peripheral(PinName pin, const PinMap* map) { + while (map->pin != NC) { + if (map->pin == pin) + return map->peripheral; + map++; + } + return (uint32_t)NC; +} + +__weak uint32_t pinmap_peripheral(PinName pin, const PinMap* map) { + uint32_t peripheral = (uint32_t)NC; + + if (pin == (PinName)NC) + return (uint32_t)NC; + peripheral = pinmap_find_peripheral(pin, map); + if ((uint32_t)NC == peripheral) // no mapping available + DBG_GPIO_ERR("%s: pinmap not found for peripheral\n", __FUNCTION__); + return peripheral; +} diff --git a/component/common/mbed/targets/hal/rtl8195a/port_api.c b/component/common/mbed/targets/hal/rtl8195a/port_api.c new file mode 100644 index 0000000..f5ad6da --- /dev/null +++ b/component/common/mbed/targets/hal/rtl8195a/port_api.c @@ -0,0 +1,150 @@ +/* mbed Microcontroller Library + ******************************************************************************* + * Copyright (c) 2014, Realtek Semiconductor Corp. + * All rights reserved. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + ******************************************************************************* + */ +#include "objects.h" +#include "port_api.h" +#include "pinmap.h" +#include "gpio_api.h" +#include "PinNames.h" +//#include "mbed_error.h" + +#if CONFIG_GPIO_EN + +#if DEVICE_PORTIN || DEVICE_PORTOUT + +#define GPIO_PORT_NUM 2 +#define GPIO_PORT_WIDTH 8 +#define GPIO_PORT_WIDTH_MAX 16 + +const u8 Default_Port_PinDef[GPIO_PORT_NUM][GPIO_PORT_WIDTH+1] = { + // Port 0 + {PA_6, PA_7, PA_5, PD_4, + PD_5, PA_4, PA_3, PA_2, + 0xFF}, + + // Port 1 + {PB_4, PB_5, PC_0, PC_2, + PC_3, PC_1, PB_3, PB_2, + 0xFF} +}; + +extern VOID HAL_GPIO_Init(HAL_GPIO_PIN *GPIO_Pin); +extern u32 HAL_GPIO_GetPinName(u32 chip_pin); + +// high nibble = port number (0=A, 1=B, 2=C, 3=D, 4=E, 5=F, ...) +// low nibble = pin number +PinName port_pin(PortName port, int pin_n) { + return (PinName)(pin_n + (port << 4)); +} + +void port_init(port_t *obj, PortName port, int mask, PinDirection dir) +{ + u32 i; + u32 port_width=0; + + if (port >= GPIO_PORT_NUM) { + DBG_GPIO_ERR("port_init: Invalid port num(%d), max port num is %d\r\n", \ + port, (GPIO_PORT_NUM-1)); + } + + // Fill PORT object structure for future use + obj->port = port; + obj->mask = mask; + obj->direction = dir; + +// if (obj->pin_def == NULL) { + obj->pin_def = (uint8_t*)&Default_Port_PinDef[port][0]; +// } + + i=0; + while (obj->pin_def[i] != 0xff) { + i++; + if (i == GPIO_PORT_WIDTH_MAX) { + break; + } + } + + obj->mask &= ((1<direction = dir; + for (i = 0; i < GPIO_PORT_WIDTH_MAX; i++) { // Process all pins + if (obj->mask & (1 << i)) { // If the pin is used + + GPIO_Pin.pin_name = HAL_GPIO_GetPinName(obj->pin_def[i]); // get the IP pin name + + if (dir == PIN_OUTPUT) { + GPIO_Pin.pin_mode = DOUT_PUSH_PULL; + } else { // PIN_INPUT + GPIO_Pin.pin_mode = DIN_PULL_NONE; + } + HAL_GPIO_Init(&GPIO_Pin); + } + } +} + +void port_mode(port_t *obj, PinMode mode) +{ + uint32_t i; + + for (i = 0; i < GPIO_PORT_WIDTH_MAX; i++) { // Process all pins + if (obj->mask & (1 << i)) { // If the pin is used + pin_mode(obj->pin_def[i], mode); + } + } +} + +void port_write(port_t *obj, int value) +{ + uint32_t i; + HAL_GPIO_PIN GPIO_Pin; + + for (i = 0; i < GPIO_PORT_WIDTH_MAX; i++) { // Process all pins + if (obj->mask & (1 << i)) { // If the pin is used + GPIO_Pin.pin_name = HAL_GPIO_GetPinName(obj->pin_def[i]); // get the IP pin name + GPIO_Pin.pin_mode = DOUT_PUSH_PULL; + HAL_GPIO_WritePin(&GPIO_Pin, ((value>>i) & 0x01)); + } + } +} + +int port_read(port_t *obj) +{ + int value=0; + u32 i; + HAL_GPIO_PIN_MODE pin_mode; + HAL_GPIO_PIN GPIO_Pin; + + if (obj->direction == PIN_OUTPUT) { + pin_mode = DOUT_PUSH_PULL; + } else { // PIN_INPUT + pin_mode = DIN_PULL_NONE; + } + + for (i = 0; i < GPIO_PORT_WIDTH_MAX; i++) { // Process all pins + if (obj->mask & (1 << i)) { // If the pin is used + GPIO_Pin.pin_name = HAL_GPIO_GetPinName(obj->pin_def[i]); // get the IP pin name + GPIO_Pin.pin_mode = pin_mode; + if (HAL_GPIO_ReadPin(&GPIO_Pin)) { + value |= (1< + +#if DEVICE_PWMOUT + +#ifdef CONFIG_PWM_EN +#include "pwmout_api.h" + +static const PinMap PinMap_PWM[] = { + {PB_4, RTL_PIN_PERI(PWM0, 0, S0), RTL_PIN_FUNC(PWM0, S0)}, + {PB_5, RTL_PIN_PERI(PWM1, 1, S0), RTL_PIN_FUNC(PWM1, S0)}, + {PB_6, RTL_PIN_PERI(PWM2, 2, S0), RTL_PIN_FUNC(PWM2, S0)}, + {PB_7, RTL_PIN_PERI(PWM3, 3, S0), RTL_PIN_FUNC(PWM3, S0)}, + + {PC_0, RTL_PIN_PERI(PWM0, 0, S1), RTL_PIN_FUNC(PWM0, S1)}, + {PC_1, RTL_PIN_PERI(PWM1, 1, S1), RTL_PIN_FUNC(PWM1, S1)}, + {PC_2, RTL_PIN_PERI(PWM2, 2, S1), RTL_PIN_FUNC(PWM2, S1)}, + {PC_3, RTL_PIN_PERI(PWM3, 3, S1), RTL_PIN_FUNC(PWM3, S1)}, + + {PD_3, RTL_PIN_PERI(PWM0, 0, S2), RTL_PIN_FUNC(PWM0, S2)}, + {PD_4, RTL_PIN_PERI(PWM1, 1, S2), RTL_PIN_FUNC(PWM1, S2)}, + {PD_5, RTL_PIN_PERI(PWM2, 2, S2), RTL_PIN_FUNC(PWM2, S2)}, + {PD_6, RTL_PIN_PERI(PWM3, 3, S2), RTL_PIN_FUNC(PWM3, S2)}, + + {PE_0, RTL_PIN_PERI(PWM0, 0, S3), RTL_PIN_FUNC(PWM0, S3)}, + {PE_1, RTL_PIN_PERI(PWM1, 1, S3), RTL_PIN_FUNC(PWM1, S3)}, + {PE_2, RTL_PIN_PERI(PWM2, 2, S3), RTL_PIN_FUNC(PWM2, S3)}, + {PE_3, RTL_PIN_PERI(PWM3, 3, S3), RTL_PIN_FUNC(PWM3, S3)}, + + {NC, NC, 0} +}; + +void pwmout_init(pwmout_t* obj, PinName pin) +{ + uint32_t peripheral; + u32 pwm_idx; + u32 pin_sel; + + DBG_PWM_INFO("%s: Init PWM for pin(0x%x)\n", __FUNCTION__, pin); + + // Get the peripheral name from the pin and assign it to the object + peripheral = pinmap_peripheral(pin, PinMap_PWM); + + if (unlikely(peripheral == NC)) { + DBG_PWM_ERR("%s: Cannot find matched pwm for this pin(0x%x)\n", __FUNCTION__, pin); + return; + } + + pwm_idx = RTL_GET_PERI_IDX(peripheral); + pin_sel = RTL_GET_PERI_SEL(peripheral); + + obj->pwm_idx = pwm_idx; + obj->pin_sel = pin_sel; + obj->period = 0; + obj->pulse = 0; + HAL_Pwm_Init(pwm_idx, pin_sel); + pwmout_period_us(obj, 20000); // 20 ms per default + HAL_Pwm_Enable(pwm_idx); +} + +void pwmout_free(pwmout_t* obj) +{ + HAL_Pwm_Disable(obj->pwm_idx); +} + +void pwmout_write(pwmout_t* obj, float value) +{ + if (value < (float)0.0) { + value = 0.0; + } + else if (value > (float)1.0) { + value = 1.0; + } + + obj->pulse = (uint32_t)((float)obj->period * value); + HAL_Pwm_SetDuty(obj->pwm_idx, obj->period, obj->pulse); +} + +float pwmout_read(pwmout_t* obj) +{ + float value = 0; + if (obj->period > 0) { + value = (float)(obj->pulse) / (float)(obj->period); + } + return ((value > (float)1.0) ? (float)(1.0) : (value)); +} + +void pwmout_period(pwmout_t* obj, float seconds) +{ + pwmout_period_us(obj, (int)(seconds * 1000000.0f)); +} + +void pwmout_period_ms(pwmout_t* obj, int ms) +{ + pwmout_period_us(obj, (int)(ms * 1000)); +} + +void pwmout_period_us(pwmout_t* obj, int us) +{ + float dc = pwmout_read(obj); + + obj->period = us; + // Set duty cycle again + pwmout_write(obj, dc); +} + +void pwmout_pulsewidth(pwmout_t* obj, float seconds) +{ + pwmout_pulsewidth_us(obj, (int)(seconds * 1000000.0f)); +} + +void pwmout_pulsewidth_ms(pwmout_t* obj, int ms) +{ + pwmout_pulsewidth_us(obj, ms * 1000); +} + +void pwmout_pulsewidth_us(pwmout_t* obj, int us) +{ + float value = (float)us / (float)obj->period; + pwmout_write(obj, value); +} + +#endif // #ifdef CONFIG_PWM_EN +#endif diff --git a/component/common/mbed/targets/hal/rtl8195a/rtc_api.c b/component/common/mbed/targets/hal/rtl8195a/rtc_api.c new file mode 100644 index 0000000..8beee24 --- /dev/null +++ b/component/common/mbed/targets/hal/rtl8195a/rtc_api.c @@ -0,0 +1,115 @@ +/* mbed Microcontroller Library + ******************************************************************************* + * Copyright (c) 2015, Realtek Semiconductor Corp. + * All rights reserved. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + *******************************************************************************/ +#include "rtc_api.h" + +#if DEVICE_RTC +#include +#include "timer_api.h" // software-RTC: use a g-timer for the tick of the RTC + +#define SW_RTC_TIMER_ID TIMER5 + +static gtimer_t sw_rtc; +static struct tm rtc_timeinfo; +static int sw_rtc_en=0; + +const static u8 dim[14] = { + 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31, 28 }; + +static inline bool is_leap_year(unsigned int year) +{ + return (!(year % 4) && (year % 100)) || !(year % 400); +} + + +static u8 days_in_month (u8 month, u8 year) +{ + u8 ret = dim [ month - 1 ]; + if (ret == 0) + ret = is_leap_year (year) ? 29 : 28; + return ret; +} + +void sw_rtc_tick_handler(uint32_t id) +{ + if(++rtc_timeinfo.tm_sec > 59) { // Increment seconds, check for overflow + rtc_timeinfo.tm_sec = 0; // Reset seconds + if(++rtc_timeinfo.tm_min > 59) { // Increment minutes, check for overflow + rtc_timeinfo.tm_min = 0; // Reset minutes + if(++rtc_timeinfo.tm_hour > 23) { // Increment hours, check for overflow + rtc_timeinfo.tm_hour = 0; // Reset hours + ++rtc_timeinfo.tm_yday; // Increment day of year + if(++rtc_timeinfo.tm_wday > 6) // Increment day of week, check for overflow + rtc_timeinfo.tm_wday = 0; // Reset day of week + // Increment day of month, check for overflow + if(++rtc_timeinfo.tm_mday > + days_in_month(rtc_timeinfo.tm_mon, rtc_timeinfo.tm_year + 1900)) { + rtc_timeinfo.tm_mday = 1; // Reset day of month + if(++rtc_timeinfo.tm_mon > 11) { // Increment month, check for overflow + rtc_timeinfo.tm_mon = 0; // Reset month + rtc_timeinfo.tm_yday = 0; // Reset day of year + ++rtc_timeinfo.tm_year; // Increment year + } // - year + } // - month + } // - day + } // - hour + } +} + +void rtc_init(void) +{ + // Initial a periodical timer + gtimer_init(&sw_rtc, SW_RTC_TIMER_ID); + // Tick every 1 sec + gtimer_start_periodical(&sw_rtc, 1000000, (void*)sw_rtc_tick_handler, (uint32_t)&sw_rtc); + sw_rtc_en = 1; +} + +void rtc_free(void) +{ + sw_rtc_en = 0; + gtimer_stop(&sw_rtc); + gtimer_deinit(&sw_rtc); +} + +int rtc_isenabled(void) +{ + return(sw_rtc_en); +} + +time_t rtc_read(void) +{ + time_t t; + + // Convert to timestamp + t = mktime(&rtc_timeinfo); + + return t; +} + +void rtc_write(time_t t) +{ + // Convert the time in to a tm + struct tm *timeinfo = localtime(&t); + + gtimer_stop(&sw_rtc); + + // Set the RTC + rtc_timeinfo.tm_sec = timeinfo->tm_sec; + rtc_timeinfo.tm_min = timeinfo->tm_min; + rtc_timeinfo.tm_hour = timeinfo->tm_hour; + rtc_timeinfo.tm_mday = timeinfo->tm_mday; + rtc_timeinfo.tm_wday = timeinfo->tm_wday; + rtc_timeinfo.tm_yday = timeinfo->tm_yday; + rtc_timeinfo.tm_mon = timeinfo->tm_mon; + rtc_timeinfo.tm_year = timeinfo->tm_year; + + gtimer_start(&sw_rtc); +} + +#endif // endof "#if DEVICE_RTC" diff --git a/component/common/mbed/targets/hal/rtl8195a/serial_api.c b/component/common/mbed/targets/hal/rtl8195a/serial_api.c new file mode 100644 index 0000000..a5c5e4d --- /dev/null +++ b/component/common/mbed/targets/hal/rtl8195a/serial_api.c @@ -0,0 +1,536 @@ +/* mbed Microcontroller Library + ******************************************************************************* + * Copyright (c) 2014, Realtek Semiconductor Corp. + * All rights reserved. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + ******************************************************************************* + */ + +#include "objects.h" +//#include "mbed_assert.h" +#include "serial_api.h" +#include "serial_ex_api.h" + +#if CONFIG_UART_EN + +//#include "cmsis.h" +#include "pinmap.h" +#include + +static const PinMap PinMap_UART_TX[] = { + {PC_3, RTL_PIN_PERI(UART0, 0, S0), RTL_PIN_FUNC(UART0, S0)}, + {PE_0, RTL_PIN_PERI(UART0, 0, S1), RTL_PIN_FUNC(UART0, S1)}, + {PA_7, RTL_PIN_PERI(UART0, 0, S2), RTL_PIN_FUNC(UART0, S2)}, + {PD_3, RTL_PIN_PERI(UART1, 1, S0), RTL_PIN_FUNC(UART1, S0)}, + {PE_4, RTL_PIN_PERI(UART1, 1, S1), RTL_PIN_FUNC(UART1, S1)}, + {PB_5, RTL_PIN_PERI(UART1, 1, S2), RTL_PIN_FUNC(UART1, S2)}, + {PA_4, RTL_PIN_PERI(UART2, 2, S0), RTL_PIN_FUNC(UART2, S0)}, + {PC_9, RTL_PIN_PERI(UART2, 2, S1), RTL_PIN_FUNC(UART2, S1)}, + {PD_7, RTL_PIN_PERI(UART2, 2, S2), RTL_PIN_FUNC(UART2, S2)}, + {NC, NC, 0} +}; + +static const PinMap PinMap_UART_RX[] = { + {PC_0, RTL_PIN_PERI(UART0, 0, S0), RTL_PIN_FUNC(UART0, S0)}, + {PE_3, RTL_PIN_PERI(UART0, 0, S1), RTL_PIN_FUNC(UART0, S1)}, + {PA_6, RTL_PIN_PERI(UART0, 0, S2), RTL_PIN_FUNC(UART0, S2)}, + {PD_0, RTL_PIN_PERI(UART1, 1, S0), RTL_PIN_FUNC(UART1, S0)}, + {PE_7, RTL_PIN_PERI(UART1, 1, S1), RTL_PIN_FUNC(UART1, S1)}, + {PB_4, RTL_PIN_PERI(UART1, 1, S2), RTL_PIN_FUNC(UART1, S2)}, + {PA_0, RTL_PIN_PERI(UART2, 2, S0), RTL_PIN_FUNC(UART2, S0)}, + {PC_6, RTL_PIN_PERI(UART2, 2, S1), RTL_PIN_FUNC(UART2, S1)}, + {PD_4, RTL_PIN_PERI(UART2, 2, S2), RTL_PIN_FUNC(UART2, S2)}, + {NC, NC, 0} +}; + +#define UART_NUM (3) +#define SERIAL_TX_IRQ_EN 0x01 +#define SERIAL_RX_IRQ_EN 0x02 +#define SERIAL_TX_DMA_EN 0x01 +#define SERIAL_RX_DMA_EN 0x02 + +static uint32_t serial_irq_ids[UART_NUM] = {0, 0, 0}; + +static uart_irq_handler irq_handler[UART_NUM]; +static uint32_t serial_irq_en[UART_NUM]={0, 0, 0}; + +#ifdef CONFIG_GDMA_EN +static uint32_t serial_dma_en[UART_NUM] = {0, 0, 0}; +static HAL_GDMA_OP UartGdmaOp; +#endif + +#ifdef CONFIG_MBED_ENABLED +int stdio_uart_inited = 0; +serial_t stdio_uart; +#endif + +static void SerialTxDoneCallBack(VOID *pAdapter); +static void SerialRxDoneCallBack(VOID *pAdapter); + +void serial_init(serial_t *obj, PinName tx, PinName rx) +{ + uint32_t uart_tx, uart_rx; + uint32_t uart_sel; + uint8_t uart_idx; + PHAL_RUART_OP pHalRuartOp; + PHAL_RUART_ADAPTER pHalRuartAdapter; +#ifdef CONFIG_GDMA_EN + PUART_DMA_CONFIG pHalRuartDmaCfg; + PHAL_GDMA_OP pHalGdmaOp=&UartGdmaOp; +#endif + + // Determine the UART to use (UART0, UART1, or UART3) + uart_tx = pinmap_peripheral(tx, PinMap_UART_TX); + uart_rx = pinmap_peripheral(rx, PinMap_UART_RX); + + uart_sel = pinmap_merge(uart_tx, uart_rx); + uart_idx = RTL_GET_PERI_IDX(uart_sel); + if (unlikely(uart_idx == (uint8_t)NC)) { + DBG_UART_ERR("%s: Cannot find matched UART\n", __FUNCTION__); + return; + } + + pHalRuartOp = &(obj->hal_uart_op); + pHalRuartAdapter = &(obj->hal_uart_adp); + + if ((NULL == pHalRuartOp) || (NULL == pHalRuartAdapter)) { + DBG_UART_ERR("%s: Allocate Adapter Failed\n", __FUNCTION__); + return; + } + + HalRuartOpInit((VOID*)pHalRuartOp); + +#ifdef CONFIG_GDMA_EN + HalGdmaOpInit((VOID*)pHalGdmaOp); + pHalRuartDmaCfg = &obj->uart_gdma_cfg; + pHalRuartDmaCfg->pHalGdmaOp = pHalGdmaOp; + pHalRuartDmaCfg->pTxHalGdmaAdapter = &obj->uart_gdma_adp_tx; + pHalRuartDmaCfg->pRxHalGdmaAdapter = &obj->uart_gdma_adp_rx; +#endif + + pHalRuartOp->HalRuartAdapterLoadDef(pHalRuartAdapter, uart_idx); + pHalRuartAdapter->PinmuxSelect = RTL_GET_PERI_SEL(uart_sel); + pHalRuartAdapter->BaudRate = 9600; + + // Configure the UART pins + // TODO: +// pinmap_pinout(tx, PinMap_UART_TX); +// pinmap_pinout(rx, PinMap_UART_RX); +// pin_mode(tx, PullUp); +// pin_mode(rx, PullUp); + + pHalRuartOp->HalRuartInit(pHalRuartAdapter); + pHalRuartOp->HalRuartRegIrq(pHalRuartAdapter); + pHalRuartOp->HalRuartIntEnable(pHalRuartAdapter); + +#ifdef CONFIG_MBED_ENABLED + // For stdio management + if (uart_idx == STDIO_UART) { + stdio_uart_inited = 1; + memcpy(&stdio_uart, obj, sizeof(serial_t)); + } +#endif +} + +void serial_free(serial_t *obj) +{ + PHAL_RUART_ADAPTER pHalRuartAdapter; + PHAL_RUART_OP pHalRuartOp; +#ifdef CONFIG_GDMA_EN + u8 uart_idx; + PUART_DMA_CONFIG pHalRuartDmaCfg; + +#endif + + pHalRuartAdapter = &(obj->hal_uart_adp); + pHalRuartOp = &(obj->hal_uart_op); + + pHalRuartOp->HalRuartDeInit(pHalRuartAdapter); + +#ifdef CONFIG_GDMA_EN + uart_idx = pHalRuartAdapter->UartIndex; + pHalRuartDmaCfg = &obj->uart_gdma_cfg; + if (serial_dma_en[uart_idx] & SERIAL_RX_DMA_EN) { + HalRuartRxGdmaDeInit(pHalRuartDmaCfg); + serial_dma_en[uart_idx] &= ~SERIAL_RX_DMA_EN; + } + + if (serial_dma_en[uart_idx] & SERIAL_TX_DMA_EN) { + HalRuartTxGdmaDeInit(pHalRuartDmaCfg); + serial_dma_en[uart_idx] &= ~SERIAL_TX_DMA_EN; + } +#endif + // TODO: recovery Pin Mux + +} + +void serial_baud(serial_t *obj, int baudrate) { + PHAL_RUART_ADAPTER pHalRuartAdapter; + PHAL_RUART_OP pHalRuartOp; + + pHalRuartAdapter = &(obj->hal_uart_adp); + pHalRuartOp = &(obj->hal_uart_op); + + pHalRuartAdapter->BaudRate = baudrate; + pHalRuartOp->HalRuartInit(pHalRuartAdapter); +} + +void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits) +{ + PHAL_RUART_ADAPTER pHalRuartAdapter; + PHAL_RUART_OP pHalRuartOp; + + pHalRuartAdapter = &(obj->hal_uart_adp); + pHalRuartOp = &(obj->hal_uart_op); + + if (data_bits == 8) { + pHalRuartAdapter->WordLen = RUART_WLS_8BITS; + } else { + pHalRuartAdapter->WordLen = RUART_WLS_7BITS; + } + + + switch (parity) { + case ParityOdd: + case ParityForced0: + pHalRuartAdapter->Parity = RUART_PARITY_ENABLE; + pHalRuartAdapter->ParityType = RUART_ODD_PARITY; + break; + case ParityEven: + case ParityForced1: + pHalRuartAdapter->Parity = RUART_PARITY_ENABLE; + pHalRuartAdapter->ParityType = RUART_EVEN_PARITY; + break; + default: // ParityNone + pHalRuartAdapter->Parity = RUART_PARITY_DISABLE; + break; + } + + if (stop_bits == 1) { + pHalRuartAdapter->StopBit = RUART_1_STOP_BIT; + } else { + pHalRuartAdapter->StopBit = RUART_NO_STOP_BIT; + } + + pHalRuartOp->HalRuartInit(pHalRuartAdapter); +} + +/****************************************************************************** + * INTERRUPTS HANDLING + ******************************************************************************/ + +static void SerialTxDoneCallBack(VOID *pAdapter) +{ + PHAL_RUART_ADAPTER pHalRuartAdapter = pAdapter; + u8 uart_idx = pHalRuartAdapter->UartIndex; + + // Mask UART TX FIFI empty + pHalRuartAdapter->Interrupts &= ~RUART_IER_ETBEI; + HalRuartSetIMRRtl8195a (pHalRuartAdapter); + + if (irq_handler[uart_idx] != NULL) { + irq_handler[uart_idx](serial_irq_ids[uart_idx], TxIrq); + } +} + +static void SerialRxDoneCallBack(VOID *pAdapter) +{ + PHAL_RUART_ADAPTER pHalRuartAdapter = pAdapter; + u8 uart_idx = pHalRuartAdapter->UartIndex; + + if (irq_handler[uart_idx] != NULL) { + irq_handler[uart_idx](serial_irq_ids[uart_idx], RxIrq); + } +} + +void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id) +{ + PHAL_RUART_ADAPTER pHalRuartAdapter; +// PHAL_RUART_OP pHalRuartOp; + u8 uart_idx; + + pHalRuartAdapter = &(obj->hal_uart_adp); +// pHalRuartOp = &(obj->hal_uart_op); + + uart_idx = pHalRuartAdapter->UartIndex; + + irq_handler[uart_idx] = handler; + serial_irq_ids[uart_idx] = id; + + pHalRuartAdapter->TxTDCallback = SerialTxDoneCallBack; + pHalRuartAdapter->TxTDCbPara = (void*)pHalRuartAdapter; + pHalRuartAdapter->RxDRCallback = SerialRxDoneCallBack; + pHalRuartAdapter->RxDRCbPara = (void*)pHalRuartAdapter; + +// pHalRuartOp->HalRuartRegIrq(pHalRuartAdapter); +// pHalRuartOp->HalRuartIntEnable(pHalRuartAdapter); +} + + +void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) +{ + PHAL_RUART_ADAPTER pHalRuartAdapter; + PHAL_RUART_OP pHalRuartOp; + u8 uart_idx; + + pHalRuartAdapter = &(obj->hal_uart_adp); + pHalRuartOp = &(obj->hal_uart_op); + uart_idx = pHalRuartAdapter->UartIndex; + + if (enable) { + if (irq == RxIrq) { + pHalRuartAdapter->Interrupts |= RUART_IER_ERBI | RUART_IER_ELSI; + serial_irq_en[uart_idx] |= SERIAL_RX_IRQ_EN; + HalRuartSetIMRRtl8195a (pHalRuartAdapter); + } + else { + serial_irq_en[uart_idx] |= SERIAL_TX_IRQ_EN; + } + pHalRuartOp->HalRuartRegIrq(pHalRuartAdapter); + pHalRuartOp->HalRuartIntEnable(pHalRuartAdapter); + } + else { // disable + if (irq == RxIrq) { + pHalRuartAdapter->Interrupts &= ~(RUART_IER_ERBI | RUART_IER_ELSI); + serial_irq_en[uart_idx] &= ~SERIAL_RX_IRQ_EN; + } + else { + pHalRuartAdapter->Interrupts &= RUART_IER_ETBEI; + serial_irq_en[uart_idx] &= ~SERIAL_TX_IRQ_EN; + } + HalRuartSetIMRRtl8195a (pHalRuartAdapter); + if (pHalRuartAdapter->Interrupts == 0) { + InterruptUnRegister(&pHalRuartAdapter->IrqHandle); + InterruptDis(&pHalRuartAdapter->IrqHandle); + } + } +} + +/****************************************************************************** + * READ/WRITE + ******************************************************************************/ + +int serial_getc(serial_t *obj) +{ + PHAL_RUART_ADAPTER pHalRuartAdapter=(PHAL_RUART_ADAPTER)&(obj->hal_uart_adp); + u8 uart_idx = pHalRuartAdapter->UartIndex; + + while (!serial_readable(obj)); + return (int)((HAL_RUART_READ32(uart_idx, RUART_REV_BUF_REG_OFF)) & 0xFF); +} + +void serial_putc(serial_t *obj, int c) +{ + PHAL_RUART_ADAPTER pHalRuartAdapter=(PHAL_RUART_ADAPTER)&(obj->hal_uart_adp); + u8 uart_idx = pHalRuartAdapter->UartIndex; + + while (!serial_writable(obj)); + HAL_RUART_WRITE32(uart_idx, RUART_TRAN_HOLD_REG_OFF, (c & 0xFF)); + + if (serial_irq_en[uart_idx] & SERIAL_TX_IRQ_EN) { + // UnMask TX FIFO empty IRQ + pHalRuartAdapter->Interrupts |= RUART_IER_ETBEI; + HalRuartSetIMRRtl8195a (pHalRuartAdapter); + } +} + +int serial_readable(serial_t *obj) +{ + PHAL_RUART_ADAPTER pHalRuartAdapter=(PHAL_RUART_ADAPTER)&(obj->hal_uart_adp); + u8 uart_idx = pHalRuartAdapter->UartIndex; + + if ((HAL_RUART_READ32(uart_idx, RUART_LINE_STATUS_REG_OFF)) & RUART_LINE_STATUS_REG_DR) { + return 1; + } + else { + return 0; + } +} + +int serial_writable(serial_t *obj) +{ + PHAL_RUART_ADAPTER pHalRuartAdapter=(PHAL_RUART_ADAPTER)&(obj->hal_uart_adp); + u8 uart_idx = pHalRuartAdapter->UartIndex; + + if (HAL_RUART_READ32(uart_idx, RUART_LINE_STATUS_REG_OFF) & + (RUART_LINE_STATUS_REG_THRE)) { + return 1; + } + else { + return 0; + } +} + +void serial_clear(serial_t *obj) +{ + PHAL_RUART_ADAPTER pHalRuartAdapter; + PHAL_RUART_OP pHalRuartOp; + + pHalRuartAdapter = &(obj->hal_uart_adp); + pHalRuartOp = &(obj->hal_uart_op); + + pHalRuartOp->HalRuartResetRxFifo(pHalRuartAdapter); +} + +void serial_pinout_tx(PinName tx) +{ + pinmap_pinout(tx, PinMap_UART_TX); +} + +void serial_break_set(serial_t *obj) +{ + PHAL_RUART_ADAPTER pHalRuartAdapter=(PHAL_RUART_ADAPTER)&(obj->hal_uart_adp); + u8 uart_idx = pHalRuartAdapter->UartIndex; + u32 RegValue; + + RegValue = HAL_RUART_READ32(uart_idx, RUART_LINE_CTL_REG_OFF); + RegValue |= BIT_UART_LCR_BREAK_CTRL; + HAL_RUART_WRITE32(uart_idx, RUART_LINE_CTL_REG_OFF, RegValue); +} + +void serial_break_clear(serial_t *obj) +{ + PHAL_RUART_ADAPTER pHalRuartAdapter=(PHAL_RUART_ADAPTER)&(obj->hal_uart_adp); + u8 uart_idx = pHalRuartAdapter->UartIndex; + u32 RegValue; + + RegValue = HAL_RUART_READ32(uart_idx, RUART_LINE_CTL_REG_OFF); + RegValue &= ~(BIT_UART_LCR_BREAK_CTRL); + HAL_RUART_WRITE32(uart_idx, RUART_LINE_CTL_REG_OFF, RegValue); +} + +void serial_send_comp_handler(serial_t *obj, void *handler, uint32_t id) +{ + PHAL_RUART_ADAPTER pHalRuartAdapter; + + pHalRuartAdapter = &(obj->hal_uart_adp); + pHalRuartAdapter->TxCompCallback = (void(*)(void*))handler; + pHalRuartAdapter->TxCompCbPara = (void*)id; +} + +void serial_recv_comp_handler(serial_t *obj, void *handler, uint32_t id) +{ + PHAL_RUART_ADAPTER pHalRuartAdapter; + + pHalRuartAdapter = &(obj->hal_uart_adp); + pHalRuartAdapter->RxCompCallback = (void(*)(void*))handler; + pHalRuartAdapter->RxCompCbPara = (void*)id; +} + +int32_t serial_recv_stream (serial_t *obj, char *prxbuf, uint32_t len) +{ + PHAL_RUART_OP pHalRuartOp; + PHAL_RUART_ADAPTER pHalRuartAdapter=(PHAL_RUART_ADAPTER)&(obj->hal_uart_adp); + int ret; + + pHalRuartOp = &(obj->hal_uart_op); + ret = pHalRuartOp->HalRuartIntRecv(pHalRuartAdapter, (u8*)prxbuf, len); + return (ret); +} + +int32_t serial_send_stream (serial_t *obj, char *ptxbuf, uint32_t len) +{ + PHAL_RUART_OP pHalRuartOp; + PHAL_RUART_ADAPTER pHalRuartAdapter=(PHAL_RUART_ADAPTER)&(obj->hal_uart_adp); + int ret; + + pHalRuartOp = &(obj->hal_uart_op); + ret = pHalRuartOp->HalRuartIntSend(pHalRuartAdapter, (u8*)ptxbuf, len); + return (ret); +} + +#ifdef CONFIG_GDMA_EN + +int32_t serial_recv_stream_dma (serial_t *obj, char *prxbuf, uint32_t len) +{ + PHAL_RUART_OP pHalRuartOp; + PHAL_RUART_ADAPTER pHalRuartAdapter=(PHAL_RUART_ADAPTER)&(obj->hal_uart_adp); + u8 uart_idx = pHalRuartAdapter->UartIndex; + int32_t ret; + + pHalRuartOp = &(obj->hal_uart_op); + if ((serial_dma_en[uart_idx] & SERIAL_RX_DMA_EN)==0) { + PUART_DMA_CONFIG pHalRuartDmaCfg; + + pHalRuartDmaCfg = &obj->uart_gdma_cfg; +#if 0 + pHalRuartOp->HalRuartRxGdmaLoadDef (pHalRuartAdapter, pHalRuartDmaCfg); + pHalRuartOp->HalRuartDmaInit (pHalRuartAdapter); + InterruptRegister(&pHalRuartDmaCfg->RxGdmaIrqHandle); + InterruptEn(&pHalRuartDmaCfg->RxGdmaIrqHandle); + serial_dma_en[uart_idx] |= SERIAL_RX_DMA_EN; +#else + if (HAL_OK == HalRuartRxGdmaInit(pHalRuartOp, pHalRuartAdapter, pHalRuartDmaCfg)) { + serial_dma_en[uart_idx] |= SERIAL_RX_DMA_EN; + } + else { + return HAL_BUSY; + } +#endif + } + ret = pHalRuartOp->HalRuartDmaRecv(pHalRuartAdapter, (u8*)prxbuf, len); + return (ret); +} + +int32_t serial_send_stream_dma (serial_t *obj, char *ptxbuf, uint32_t len) +{ + PHAL_RUART_OP pHalRuartOp; + PHAL_RUART_ADAPTER pHalRuartAdapter=(PHAL_RUART_ADAPTER)&(obj->hal_uart_adp); + u8 uart_idx = pHalRuartAdapter->UartIndex; + int32_t ret; + + pHalRuartOp = &(obj->hal_uart_op); + + if ((serial_dma_en[uart_idx] & SERIAL_TX_DMA_EN)==0) { + PUART_DMA_CONFIG pHalRuartDmaCfg; + + pHalRuartDmaCfg = &obj->uart_gdma_cfg; +#if 0 + pHalRuartOp->HalRuartTxGdmaLoadDef (pHalRuartAdapter, pHalRuartDmaCfg); + pHalRuartOp->HalRuartDmaInit (pHalRuartAdapter); + InterruptRegister(&pHalRuartDmaCfg->TxGdmaIrqHandle); + InterruptEn(&pHalRuartDmaCfg->TxGdmaIrqHandle); + serial_dma_en[uart_idx] |= SERIAL_TX_DMA_EN; +#else + if (HAL_OK == HalRuartTxGdmaInit(pHalRuartOp, pHalRuartAdapter, pHalRuartDmaCfg)) { + serial_dma_en[uart_idx] |= SERIAL_TX_DMA_EN; + } + else { + return HAL_BUSY; + } +#endif + } + ret = pHalRuartOp->HalRuartDmaSend(pHalRuartAdapter, (u8*)ptxbuf, len); + return (ret); +} +#endif // end of "#ifdef CONFIG_GDMA_EN" + +int32_t serial_send_stream_abort (serial_t *obj) +{ + PHAL_RUART_OP pHalRuartOp; + PHAL_RUART_ADAPTER pHalRuartAdapter=(PHAL_RUART_ADAPTER)&(obj->hal_uart_adp); + int ret; + + pHalRuartOp = &(obj->hal_uart_op); + + ret = pHalRuartOp->HalRuartStopSend((VOID*)pHalRuartAdapter); + HalRuartResetTxFifo((VOID*)pHalRuartAdapter); + return (ret); +} + +int32_t serial_recv_stream_abort (serial_t *obj) +{ + PHAL_RUART_OP pHalRuartOp; + PHAL_RUART_ADAPTER pHalRuartAdapter=(PHAL_RUART_ADAPTER)&(obj->hal_uart_adp); + int ret; + + pHalRuartOp = &(obj->hal_uart_op); + + ret = pHalRuartOp->HalRuartStopRecv((VOID*)pHalRuartAdapter); + ret = pHalRuartOp->HalRuartResetRxFifo((VOID*)pHalRuartAdapter); + return (ret); +} + +#endif diff --git a/component/common/mbed/targets/hal/rtl8195a/sleep.c b/component/common/mbed/targets/hal/rtl8195a/sleep.c new file mode 100644 index 0000000..5a47673 --- /dev/null +++ b/component/common/mbed/targets/hal/rtl8195a/sleep.c @@ -0,0 +1,245 @@ +/* mbed Microcontroller Library + ******************************************************************************* + * Copyright (c) 2014, STMicroelectronics + * 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 STMicroelectronics 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 HOLDERS 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. + ******************************************************************************* + */ +#include "sleep_ex_api.h" +#include "cmsis.h" + +extern VOID SleepCG(u8 Option, u32 SDuration); +extern VOID DeepStandby(u8 Option, u32 SDuration, u8 GpioOption); +extern VOID DeepSleep(u8 Option, u32 SDuration); + +SLEEP_WAKEUP_EVENT DStandbyWakeupEvent={0}; + +/** + * @brief To make the system entering the Clock Gated power saving. + * This function just make the system to enter the clock gated + * power saving mode and pending on wake up event waitting. + * The user application need to configure the peripheral to + * generate system wake up event, like GPIO interrupt + * , G-Timer timeout, etc. befor entering power saving mode. + * + * @param wakeup_event: A bit map of wake up event. Available event: + * SLEEP_WAKEUP_BY_STIMER + * SLEEP_WAKEUP_BY_GTIMER + * SLEEP_WAKEUP_BY_GPIO_INT + * SLEEP_WAKEUP_BY_WLAN + * SLEEP_WAKEUP_BY_NFC + * SLEEP_WAKEUP_BY_SDIO + * SLEEP_WAKEUP_BY_USB + * sleep_duration: the system sleep duration in ms, only valid + * for SLEEP_WAKEUP_BY_STIMER wake up event. + * + * @retval None + */ +void sleep_ex(uint32_t wakeup_event, uint32_t sleep_duration) +{ + u8 wake_ev=0; + + wake_ev = wakeup_event & 0xff; + + if (sleep_duration == 0) { + wake_ev &= ~SLP_STIMER; + } + + if (wake_ev == 0) { + // error: No wakeup event, skip the entering sleep mode + return; + } + SleepCG(wake_ev, sleep_duration); +} + + +/** + * @brief To add a wake up event to wake up the system from the + * deep standby power saving mode. + * + * @param wakeup_event: A bit map of wake up event. Available event: + * STANDBY_WAKEUP_BY_STIMER + * STANDBY_WAKEUP_BY_NFC + * STANDBY_WAKEUP_BY_PA5 (GPIO) + * STANDBY_WAKEUP_BY_PC7 (GPIO) + * STANDBY_WAKEUP_BY_PD5 (GPIO) + * STANDBY_WAKEUP_BY_PE3 (GPIO) + * sleep_duration_ms: the system sleep duration in ms, only valid + * for STANDBY_WAKEUP_BY_STIMER wake up event. + * gpio_active: for a GPIO pin to wake up the system by + * goes high(1) or low(0) + * + * @retval None + */ +void standby_wakeup_event_add(uint32_t wakeup_event, uint32_t sleep_duration_ms, uint32_t gpio_active) +{ + u32 i; + u8 gpio_event; + u8 gpio_en; + u8 gpio_act; + + if (wakeup_event & STANDBY_WAKEUP_BY_STIMER) { + DStandbyWakeupEvent.wakeup_event |= DSTBY_STIMER; + DStandbyWakeupEvent.timer_duration = sleep_duration_ms; + } + +#if 0 + if (wakeup_event & STANDBY_WAKEUP_BY_DS_TIMER) { + DStandbyWakeupEvent.wakeup_event |= DSTBY_TIMER33; + // TODO: Sleep Duration ? + } +#endif + + if (wakeup_event & STANDBY_WAKEUP_BY_NFC) { + DStandbyWakeupEvent.wakeup_event |= DSTBY_NFC; + } + + gpio_event = STANDBY_WAKEUP_BY_PA5; + gpio_en = BIT0; + gpio_act = BIT4; + // Loop 4 to check 4 GPIO wake up event + for (i=0;i<4;i++) { + if (wakeup_event & gpio_event) { + DStandbyWakeupEvent.wakeup_event |= DSTBY_GPIO; + DStandbyWakeupEvent.gpio_option |= gpio_en; + if (gpio_active) { + // Active High + DStandbyWakeupEvent.gpio_option |= gpio_act; + } + else { + // Active Low + DStandbyWakeupEvent.gpio_option &= ~gpio_act; + } + } + gpio_event = gpio_event << 1; + gpio_en = gpio_en << 1; + gpio_act = gpio_act << 1; + } +} + +/** + * @brief To delete a wake up event for wakeing up the system from the + * deep standby power saving mode. + * + * @param wakeup_event: A bit map of wake up event. Available event: + * STANDBY_WAKEUP_BY_STIMER + * STANDBY_WAKEUP_BY_NFC + * STANDBY_WAKEUP_BY_PA5 (GPIO) + * STANDBY_WAKEUP_BY_PC7 (GPIO) + * STANDBY_WAKEUP_BY_PD5 (GPIO) + * STANDBY_WAKEUP_BY_PE3 (GPIO) + * @retval None + */ +void standby_wakeup_event_del(uint32_t wakeup_event) +{ + if (wakeup_event & STANDBY_WAKEUP_BY_STIMER) { + DStandbyWakeupEvent.wakeup_event &= ~DSTBY_STIMER; + } + +#if 0 + if (wakeup_event & STANDBY_WAKEUP_BY_DS_TIMER) { + DStandbyWakeupEvent.wakeup_event &= ~DSTBY_TIMER33; + } +#endif + + if (wakeup_event & STANDBY_WAKEUP_BY_NFC) { + DStandbyWakeupEvent.wakeup_event &= ~DSTBY_NFC; + } + + if (wakeup_event & STANDBY_WAKEUP_BY_PA5) { + DStandbyWakeupEvent.gpio_option &= ~BIT0; + } + + if (wakeup_event & STANDBY_WAKEUP_BY_PC7) { + DStandbyWakeupEvent.gpio_option &= ~BIT1; + } + + if (wakeup_event & STANDBY_WAKEUP_BY_PD5) { + DStandbyWakeupEvent.gpio_option &= ~BIT2; + } + + if (wakeup_event & STANDBY_WAKEUP_BY_PE3) { + DStandbyWakeupEvent.gpio_option &= ~BIT3; + } + + if ((DStandbyWakeupEvent.gpio_option & 0x0f) == 0) { + // All GPIO wake up pin are disabled + DStandbyWakeupEvent.wakeup_event &= ~DSTBY_GPIO; + } +} + +/** + * @brief To make the system entering the Deep Standby power saving. + * The CPU, memory and part fo peripheral power is off when + * entering deep standby power saving mode. The program needs + * to be reload from the flash at system resume. + * + * @retval None + */ +void deepstandby_ex(void) +{ + if ((DStandbyWakeupEvent.wakeup_event & (DSTBY_STIMER|DSTBY_NFC|DSTBY_GPIO)) == 0) { + // error: no wakeup event was added, so skip the entering standby power saving + return; + } + + DeepStandby(DStandbyWakeupEvent.wakeup_event, + DStandbyWakeupEvent.timer_duration, DStandbyWakeupEvent.gpio_option); +} + +/** + * @brief To make the system entering the Deep Sleep power saving mode. + * The CPU, memory and peripheral power is off when entering + * deep sleep power saving mode. The program needs to be reload + * and all peripheral needs be re-configure when system resume. + * + * @param wakeup_event: A bit map of wake up event. Available event: + * DSLEEP_WAKEUP_BY_TIMER + * DSLEEP_WAKEUP_BY_GPIO + * sleep_duration: the system sleep duration in ms, only valid + * for DSLEEP_WAKEUP_BY_TIMER wake up event. + * + * @retval None + */ +void deepsleep_ex(uint32_t wakeup_event, uint32_t sleep_duration) +{ + u8 wake_ev=0; + + if ((wakeup_event & DSLEEP_WAKEUP_BY_TIMER) && (sleep_duration > 0)) { + // wake up by timeout or GPIO pin goes high + wake_ev |= DS_TIMER33; + } + + if (wakeup_event & DSLEEP_WAKEUP_BY_GPIO) { + // wake up by GPIO pin goes high + wake_ev |= DS_GPIO; + } + + if (wake_ev == 0) { + // error: No wake up event, skip entering deep sleep mode + return; + } + DeepSleep (wake_ev, sleep_duration); +} diff --git a/component/common/mbed/targets/hal/rtl8195a/spi_api.c b/component/common/mbed/targets/hal/rtl8195a/spi_api.c new file mode 100644 index 0000000..2573232 --- /dev/null +++ b/component/common/mbed/targets/hal/rtl8195a/spi_api.c @@ -0,0 +1,681 @@ + +#include "objects.h" +#include "spi_api.h" +#include "spi_ex_api.h" +#include "PinNames.h" +#include "pinmap.h" +#include "hal_ssi.h" + +extern u32 SystemGetCpuClk(VOID); +extern VOID HAL_GPIO_PullCtrl(u32 pin, u32 mode); + +void spi_tx_done_callback(VOID *obj); +void spi_rx_done_callback(VOID *obj); + +#ifdef CONFIG_GDMA_EN +HAL_GDMA_OP SpiGdmaOp; +#endif + +uint8_t SPI0_IS_AS_SLAVE = 0; + +//TODO: Load default Setting: It should be loaded from external setting file. +extern const DW_SSI_DEFAULT_SETTING SpiDefaultSetting; + +static const PinMap PinMap_SSI_MOSI[] = { + {PE_2, RTL_PIN_PERI(SPI0, 0, S0), RTL_PIN_FUNC(SPI0, S0)}, + {PC_2, RTL_PIN_PERI(SPI0, 0, S1), RTL_PIN_FUNC(SPI0, S1)}, + {PA_1, RTL_PIN_PERI(SPI1, 1, S0), RTL_PIN_FUNC(SPI1, S0)}, + {PB_6, RTL_PIN_PERI(SPI1, 1, S1), RTL_PIN_FUNC(SPI1, S1)}, + {PD_6, RTL_PIN_PERI(SPI1, 1, S2), RTL_PIN_FUNC(SPI1, S2)}, + {PG_2, RTL_PIN_PERI(SPI2, 2, S0), RTL_PIN_FUNC(SPI2, S0)}, + {PE_6, RTL_PIN_PERI(SPI2, 2, S1), RTL_PIN_FUNC(SPI2, S1)}, + {PD_2, RTL_PIN_PERI(SPI2, 2, S2), RTL_PIN_FUNC(SPI2, S2)}, + {NC, NC, 0} +}; + +static const PinMap PinMap_SSI_MISO[] = { + {PE_3, RTL_PIN_PERI(SPI0, 0, S0), RTL_PIN_FUNC(SPI0, S0)}, + {PC_3, RTL_PIN_PERI(SPI0, 0, S1), RTL_PIN_FUNC(SPI0, S1)}, + {PA_0, RTL_PIN_PERI(SPI1, 1, S0), RTL_PIN_FUNC(SPI1, S0)}, + {PB_7, RTL_PIN_PERI(SPI1, 1, S1), RTL_PIN_FUNC(SPI1, S1)}, + {PD_7, RTL_PIN_PERI(SPI1, 1, S2), RTL_PIN_FUNC(SPI1, S2)}, + {PG_3, RTL_PIN_PERI(SPI2, 2, S0), RTL_PIN_FUNC(SPI2, S0)}, + {PE_7, RTL_PIN_PERI(SPI2, 2, S1), RTL_PIN_FUNC(SPI2, S1)}, + {PD_3, RTL_PIN_PERI(SPI2, 2, S2), RTL_PIN_FUNC(SPI2, S2)}, + {NC, NC, 0} +}; + + +void spi_init (spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) +{ + SSI_DBG_ENTRANCE("spi_init()\n"); + + uint32_t ssi_mosi, ssi_miso, ssi_peri; + uint8_t ssi_idx, ssi_pinmux; + PHAL_SSI_ADAPTOR pHalSsiAdaptor; + PHAL_SSI_OP pHalSsiOp; + + obj->state = 0; + uint32_t SystemClock = SystemGetCpuClk(); + uint32_t MaxSsiFreq = (SystemClock >> 2) >> 1; + + /* SsiClockDivider doesn't support odd number */ + + DBG_SSI_INFO("SystemClock: %d\n", SystemClock); + DBG_SSI_INFO("MaxSsiFreq : %d\n", MaxSsiFreq); + + ssi_mosi = pinmap_peripheral(mosi, PinMap_SSI_MOSI); + ssi_miso = pinmap_peripheral(miso, PinMap_SSI_MISO); + //DBG_SSI_INFO("ssi_mosi: %d, ssi_miso: %d\n", ssi_mosi, ssi_miso); + + ssi_peri = pinmap_merge(ssi_mosi, ssi_miso); + if (unlikely(ssi_peri == NC)) { + DBG_SSI_ERR("spi_init(): Cannot find matched SSI index.\n"); + return; + } + obj->sclk = (u8)sclk; + ssi_idx = RTL_GET_PERI_IDX(ssi_peri); + ssi_pinmux = RTL_GET_PERI_SEL(ssi_peri); + DBG_SSI_INFO("ssi_peri: %d, ssi_idx: %d, ssi_pinmux: %d\n", ssi_peri, ssi_idx, ssi_pinmux); + + pHalSsiAdaptor = &obj->spi_adp; + pHalSsiOp = &obj->spi_op; + + pHalSsiAdaptor->Index = ssi_idx; + pHalSsiAdaptor->PinmuxSelect = ssi_pinmux; + +#if 0 + // XXX: Only for test + if ((ssi_idx == 0) && (SPI0_IS_AS_SLAVE == 1)) { + //DBG_SSI_INFO("SSI%d will be as slave. (spi0_is_slave: %d)\n", index, spi0_is_slave); + pHalSsiAdaptor->Role = SSI_SLAVE; + } + else +#endif + { + //DBG_SSI_INFO("SSI%d will be as master. (spi0_is_slave: %d)\n", index, spi0_is_slave); + pHalSsiAdaptor->Role = SSI_MASTER; + } + + HalSsiOpInit((VOID*)pHalSsiOp); + + pHalSsiOp->HalSsiSetDeviceRole(pHalSsiAdaptor, pHalSsiAdaptor->Role); + + /* Pinmux workaround */ + if ((ssi_idx == 0) && (ssi_pinmux == SSI0_MUX_TO_GPIOC)) { + EEPROM_PIN_CTRL(OFF); + } + + if ((ssi_idx == 0) && (ssi_pinmux == SSI0_MUX_TO_GPIOE)) { + DBG_SSI_WARN(ANSI_COLOR_MAGENTA"SPI0 Pin may conflict with JTAG\r\n"ANSI_COLOR_RESET); + } + + + pHalSsiOp->HalSsiPinmuxEnable(pHalSsiAdaptor); + + + //TODO: Implement default setting structure. + pHalSsiOp->HalSsiLoadSetting(pHalSsiAdaptor, (void*)&SpiDefaultSetting); + pHalSsiAdaptor->DefaultRxThresholdLevel = SpiDefaultSetting.RxThresholdLevel; + + pHalSsiOp->HalSsiInit(pHalSsiAdaptor); + + pHalSsiAdaptor->TxCompCallback = spi_tx_done_callback; + pHalSsiAdaptor->TxCompCbPara = (void*)obj; + pHalSsiAdaptor->RxCompCallback = spi_rx_done_callback; + pHalSsiAdaptor->RxCompCbPara = (void*)obj; + +#ifdef CONFIG_GDMA_EN + HalGdmaOpInit((VOID*)&SpiGdmaOp); + pHalSsiAdaptor->DmaConfig.pHalGdmaOp = &SpiGdmaOp; + pHalSsiAdaptor->DmaConfig.pRxHalGdmaAdapter = &obj->spi_gdma_adp_rx; + pHalSsiAdaptor->DmaConfig.pTxHalGdmaAdapter = &obj->spi_gdma_adp_tx; + obj->dma_en = 0; +#endif +} + +void spi_free (spi_t *obj) +{ + PHAL_SSI_ADAPTOR pHalSsiAdaptor; + PHAL_SSI_OP pHalSsiOp; + + + pHalSsiAdaptor = &obj->spi_adp; + pHalSsiOp = &obj->spi_op; + + pHalSsiOp->HalSsiInterruptDisable(pHalSsiAdaptor); + pHalSsiOp->HalSsiDisable(pHalSsiAdaptor); + pHalSsiOp->HalSsiPinmuxDisable(pHalSsiAdaptor); + + SPI0_MULTI_CS_CTRL(OFF); + +#ifdef CONFIG_GDMA_EN + if (obj->dma_en & SPI_DMA_RX_EN) { + HalSsiRxGdmaDeInit(pHalSsiAdaptor); + } + + if (obj->dma_en & SPI_DMA_TX_EN) { + HalSsiTxGdmaDeInit(pHalSsiAdaptor); + } + obj->dma_en = 0; +#endif +} + +void spi_format (spi_t *obj, int bits, int mode, int slave) +{ + PHAL_SSI_ADAPTOR pHalSsiAdaptor; + PHAL_SSI_OP pHalSsiOp; + + pHalSsiAdaptor = &obj->spi_adp; + pHalSsiOp = &obj->spi_op; + + pHalSsiAdaptor->DataFrameSize = (bits - 1); + + /* + * mode | POL PHA + * -----+-------- + * 0 | 0 0 + * 1 | 0 1 + * 2 | 1 0 + * 3 | 1 1 + * + * SCPOL_INACTIVE_IS_LOW = 0, + * SCPOL_INACTIVE_IS_HIGH = 1 + * + * SCPH_TOGGLES_IN_MIDDLE = 0, + * SCPH_TOGGLES_AT_START = 1 + */ + switch (mode) + { + case 0: + pHalSsiAdaptor->SclkPolarity = SCPOL_INACTIVE_IS_LOW; + pHalSsiAdaptor->SclkPhase = SCPH_TOGGLES_IN_MIDDLE; + break; + case 1: + pHalSsiAdaptor->SclkPolarity = SCPOL_INACTIVE_IS_LOW; + pHalSsiAdaptor->SclkPhase = SCPH_TOGGLES_AT_START; + break; + case 2: + pHalSsiAdaptor->SclkPolarity = SCPOL_INACTIVE_IS_HIGH; + pHalSsiAdaptor->SclkPhase = SCPH_TOGGLES_IN_MIDDLE; + break; + case 3: + pHalSsiAdaptor->SclkPolarity = SCPOL_INACTIVE_IS_HIGH; + pHalSsiAdaptor->SclkPhase = SCPH_TOGGLES_AT_START; + break; + default: // same as 3 + pHalSsiAdaptor->SclkPolarity = SCPOL_INACTIVE_IS_HIGH; + pHalSsiAdaptor->SclkPhase = SCPH_TOGGLES_AT_START; + break; + } + + if (slave == 1) { + if (pHalSsiAdaptor->Index == 0) { + pHalSsiAdaptor->Role = SSI_SLAVE; + pHalSsiAdaptor->SlaveOutputEnable = SLV_TXD_ENABLE; // <-- Slave only + SPI0_IS_AS_SLAVE = 1; + DBG_SSI_INFO("SPI0 is as slave\n"); + } + else { + DBG_SSI_ERR("The SPI%d cannot work as Slave mode, only SPI0 does.\r\n", pHalSsiAdaptor->Index); + pHalSsiAdaptor->Role = SSI_MASTER; + } + } + else { + pHalSsiAdaptor->Role = SSI_MASTER; + } + pHalSsiOp->HalSsiSetDeviceRole(pHalSsiAdaptor, pHalSsiAdaptor->Role); + +#ifdef CONFIG_GPIO_EN + if (pHalSsiAdaptor->Role == SSI_SLAVE) { + if (pHalSsiAdaptor->SclkPolarity == SCPOL_INACTIVE_IS_LOW) { + HAL_GPIO_PullCtrl((u32)obj->sclk, hal_PullDown); + } + else { + HAL_GPIO_PullCtrl((u32)obj->sclk, hal_PullUp); + } + } +#endif + pHalSsiOp->HalSsiInit(pHalSsiAdaptor); +} + +void spi_frequency (spi_t *obj, int hz) +{ + PHAL_SSI_ADAPTOR pHalSsiAdaptor; + + pHalSsiAdaptor = &obj->spi_adp; + HalSsiSetSclk(pHalSsiAdaptor, (u32)hz); +} + +void spi_slave_select(spi_t *obj, ChipSelect slaveindex) +{ + PHAL_SSI_ADAPTOR pHalSsiAdaptor; + PHAL_SSI_OP pHalSsiOp; + u8 Index; + + pHalSsiAdaptor = &obj->spi_adp; + pHalSsiOp = &obj->spi_op; + Index = pHalSsiAdaptor->Index; + + if((pHalSsiAdaptor->Role == SSI_MASTER) && (Index == 0)){ + pHalSsiOp->HalSsiSetSlaveEnableRegister((VOID*)pHalSsiAdaptor,slaveindex); + if(slaveindex != CS_0){ + SPI0_MULTI_CS_CTRL(ON); + } + } + else{ + DBG_SSI_ERR("Only SPI 0 master mode supports slave selection.\n"); + } +} + +static inline void ssi_write (spi_t *obj, int value) +{ + PHAL_SSI_ADAPTOR pHalSsiAdaptor; + PHAL_SSI_OP pHalSsiOp; + + pHalSsiAdaptor = &obj->spi_adp; + pHalSsiOp = &obj->spi_op; + + while (!pHalSsiOp->HalSsiWriteable(pHalSsiAdaptor)); + pHalSsiOp->HalSsiWrite((VOID*)pHalSsiAdaptor, value); +} + +static inline int ssi_read(spi_t *obj) +{ + PHAL_SSI_ADAPTOR pHalSsiAdaptor; + PHAL_SSI_OP pHalSsiOp; + + pHalSsiAdaptor = &obj->spi_adp; + pHalSsiOp = &obj->spi_op; + + while (!pHalSsiOp->HalSsiReadable(pHalSsiAdaptor)); + return (int)pHalSsiOp->HalSsiRead(pHalSsiAdaptor); +} + +int spi_master_write (spi_t *obj, int value) +{ + ssi_write(obj, value); + return ssi_read(obj); +} + +int spi_slave_receive (spi_t *obj) +{ + PHAL_SSI_ADAPTOR pHalSsiAdaptor; + PHAL_SSI_OP pHalSsiOp; + int Readable; + int Busy; + + pHalSsiAdaptor = &obj->spi_adp; + pHalSsiOp = &obj->spi_op; + + Readable = pHalSsiOp->HalSsiReadable(pHalSsiAdaptor); + Busy = (int)pHalSsiOp->HalSsiBusy(pHalSsiAdaptor); + return ((Readable && !Busy) ? 1 : 0); +} + +int spi_slave_read (spi_t *obj) +{ + return ssi_read(obj); +} + +void spi_slave_write (spi_t *obj, int value) +{ + ssi_write(obj, value); +} + +int spi_busy (spi_t *obj) +{ + PHAL_SSI_ADAPTOR pHalSsiAdaptor; + PHAL_SSI_OP pHalSsiOp; + + pHalSsiAdaptor = &obj->spi_adp; + pHalSsiOp = &obj->spi_op; + + return (int)pHalSsiOp->HalSsiBusy(pHalSsiAdaptor); +} + +void spi_flush_rx_fifo (spi_t *obj) +{ + PHAL_SSI_ADAPTOR pHalSsiAdaptor; + PHAL_SSI_OP pHalSsiOp; + u32 rx_fifo_level; + u32 i; + u16 rx_dummy; + + pHalSsiAdaptor = &obj->spi_adp; + pHalSsiOp = &obj->spi_op; + + while(pHalSsiOp->HalSsiReadable(pHalSsiAdaptor)){ + rx_fifo_level = pHalSsiOp->HalSsiGetRxFifoLevel(pHalSsiAdaptor); + for(i=0;iHalSsiRead(pHalSsiAdaptor); + } + } +} + +// Slave mode read a sequence of data by interrupt mode +int32_t spi_slave_read_stream(spi_t *obj, char *rx_buffer, uint32_t length) +{ + PHAL_SSI_ADAPTOR pHalSsiAdaptor; + PHAL_SSI_OP pHalSsiOp; + int32_t ret; + + if (obj->state & SPI_STATE_RX_BUSY) { + DBG_SSI_WARN("spi_slave_read_stream: state(0x%x) is not ready\r\n", + obj->state); + return HAL_BUSY; + } + + pHalSsiAdaptor = &obj->spi_adp; + pHalSsiOp = &obj->spi_op; + + //DBG_SSI_INFO("rx_buffer addr: %X, length: %d\n", rx_buffer, length); + obj->state |= SPI_STATE_RX_BUSY; + if ((ret=pHalSsiOp->HalSsiReadInterrupt(pHalSsiAdaptor, rx_buffer, length)) != HAL_OK) { + obj->state &= ~SPI_STATE_RX_BUSY; + } + + return ret; +} + +// Slave mode write a sequence of data by interrupt mode +int32_t spi_slave_write_stream(spi_t *obj, char *tx_buffer, uint32_t length) +{ + PHAL_SSI_ADAPTOR pHalSsiAdaptor; + PHAL_SSI_OP pHalSsiOp; + int32_t ret; + + if (obj->state & SPI_STATE_TX_BUSY) { + DBG_SSI_WARN("spi_slave_write_stream: state(0x%x) is not ready\r\n", + obj->state); + return HAL_BUSY; + } + + pHalSsiAdaptor = &obj->spi_adp; + pHalSsiOp = &obj->spi_op; + + obj->state |= SPI_STATE_TX_BUSY; + if ((ret=pHalSsiOp->HalSsiWriteInterrupt(pHalSsiAdaptor, tx_buffer, length)) != HAL_OK) { + obj->state &= ~SPI_STATE_TX_BUSY; + } + return ret; +} + +// Master mode read a sequence of data by interrupt mode +// The length unit is byte, for both 16-bits and 8-bits mode +int32_t spi_master_read_stream(spi_t *obj, char *rx_buffer, uint32_t length) +{ + PHAL_SSI_ADAPTOR pHalSsiAdaptor; + PHAL_SSI_OP pHalSsiOp; + int32_t ret; + + if (obj->state & SPI_STATE_RX_BUSY) { + DBG_SSI_WARN("spi_master_read_stream: state(0x%x) is not ready\r\n", + obj->state); + return HAL_BUSY; + } + + pHalSsiAdaptor = &obj->spi_adp; + pHalSsiOp = &obj->spi_op; + // wait bus idle + while(pHalSsiOp->HalSsiBusy(pHalSsiAdaptor)); + + obj->state |= SPI_STATE_RX_BUSY; + if ((ret=pHalSsiOp->HalSsiReadInterrupt(pHalSsiAdaptor, rx_buffer, length)) == HAL_OK) { + /* as Master mode, it need to push data to TX FIFO to generate clock out + then the slave can transmit data out */ + // send some dummy data out + if ((ret=pHalSsiOp->HalSsiWriteInterrupt(pHalSsiAdaptor, NULL, length)) != HAL_OK) { + obj->state &= ~SPI_STATE_RX_BUSY; + } + } + else { + obj->state &= ~SPI_STATE_RX_BUSY; + } + + return ret; +} + +// Master mode write a sequence of data by interrupt mode +// The length unit is byte, for both 16-bits and 8-bits mode +int32_t spi_master_write_stream(spi_t *obj, char *tx_buffer, uint32_t length) +{ + PHAL_SSI_ADAPTOR pHalSsiAdaptor; + PHAL_SSI_OP pHalSsiOp; + int32_t ret; + + if (obj->state & SPI_STATE_TX_BUSY) { + DBG_SSI_WARN("spi_master_write_stream: state(0x%x) is not ready\r\n", + obj->state); + return HAL_BUSY; + } + + pHalSsiAdaptor = &obj->spi_adp; + pHalSsiOp = &obj->spi_op; + + obj->state |= SPI_STATE_TX_BUSY; + /* as Master mode, sending data will receive data at sametime, so we need to + drop those received dummy data */ + if ((ret=pHalSsiOp->HalSsiWriteInterrupt(pHalSsiAdaptor, tx_buffer, length)) != HAL_OK) { + obj->state &= ~SPI_STATE_TX_BUSY; + } + return ret; +} + +// Master mode write a sequence of data by interrupt mode +// The length unit is byte, for both 16-bits and 8-bits mode +int32_t spi_master_write_read_stream(spi_t *obj, char *tx_buffer, + char *rx_buffer, uint32_t length) +{ + PHAL_SSI_ADAPTOR pHalSsiAdaptor; + PHAL_SSI_OP pHalSsiOp; + int32_t ret; + + if (obj->state & (SPI_STATE_RX_BUSY|SPI_STATE_TX_BUSY)) { + DBG_SSI_WARN("spi_master_write_and_read_stream: state(0x%x) is not ready\r\n", + obj->state); + return HAL_BUSY; + } + + pHalSsiAdaptor = &obj->spi_adp; + pHalSsiOp = &obj->spi_op; + // wait bus idle + while(pHalSsiOp->HalSsiBusy(pHalSsiAdaptor)); + + obj->state |= SPI_STATE_RX_BUSY; + /* as Master mode, sending data will receive data at sametime */ + if ((ret=pHalSsiOp->HalSsiReadInterrupt(pHalSsiAdaptor, rx_buffer, length)) == HAL_OK) { + obj->state |= SPI_STATE_TX_BUSY; + if ((ret=pHalSsiOp->HalSsiWriteInterrupt(pHalSsiAdaptor, tx_buffer, length)) != HAL_OK) { + obj->state &= ~(SPI_STATE_RX_BUSY|SPI_STATE_TX_BUSY); + // Disable RX IRQ + pHalSsiAdaptor->InterruptMask &= ~(BIT_IMR_RXFIM | BIT_IMR_RXOIM | BIT_IMR_RXUIM); + pHalSsiOp->HalSsiSetInterruptMask((VOID*)pHalSsiAdaptor); + } + } + else { + obj->state &= ~(SPI_STATE_RX_BUSY); + } + + return ret; +} + +void spi_tx_done_callback(VOID *obj) +{ + spi_t *spi_obj = (spi_t *)obj; + spi_irq_handler handler; + + if (spi_obj->state & SPI_STATE_TX_BUSY) { + spi_obj->state &= ~SPI_STATE_TX_BUSY; + if (spi_obj->irq_handler) { + handler = (spi_irq_handler)spi_obj->irq_handler; + handler(spi_obj->irq_id, SpiTxIrq); + } + } +} + +void spi_rx_done_callback(VOID *obj) +{ + spi_t *spi_obj = (spi_t *)obj; + spi_irq_handler handler; + + spi_obj->state &= ~SPI_STATE_RX_BUSY; + if (spi_obj->irq_handler) { + handler = (spi_irq_handler)spi_obj->irq_handler; + handler(spi_obj->irq_id, SpiRxIrq); + } +} + +void spi_irq_hook(spi_t *obj, spi_irq_handler handler, uint32_t id) +{ + obj->irq_handler = (u32)handler; + obj->irq_id = (u32)id; +} + +#ifdef CONFIG_GDMA_EN +int32_t spi_slave_read_stream_dma(spi_t *obj, char *rx_buffer, uint32_t length) +{ + PHAL_SSI_ADAPTOR pHalSsiAdaptor; + PHAL_SSI_OP pHalSsiOp; + int32_t ret; + + if (obj->state & SPI_STATE_RX_BUSY) { + DBG_SSI_WARN("spi_slave_read_stream_dma: state(0x%x) is not ready\r\n", + obj->state); + return HAL_BUSY; + } + + pHalSsiAdaptor = &obj->spi_adp; + pHalSsiOp = &obj->spi_op; + + if ((obj->dma_en & SPI_DMA_RX_EN)==0) { + if (HAL_OK == HalSsiRxGdmaInit(pHalSsiOp, pHalSsiAdaptor)) { + obj->dma_en |= SPI_DMA_RX_EN; + } + else { + return HAL_BUSY; + } + } + + obj->state |= SPI_STATE_RX_BUSY; + ret = HalSsiDmaRecv(pHalSsiAdaptor, rx_buffer, length); + if (ret != HAL_OK) { + obj->state &= ~SPI_STATE_RX_BUSY; + } + return (ret); +} + +int32_t spi_slave_write_stream_dma(spi_t *obj, char *tx_buffer, uint32_t length) +{ + PHAL_SSI_ADAPTOR pHalSsiAdaptor; + PHAL_SSI_OP pHalSsiOp; + int32_t ret; + + if (obj->state & SPI_STATE_TX_BUSY) { + DBG_SSI_WARN("spi_slave_write_stream_dma: state(0x%x) is not ready\r\n", + obj->state); + return HAL_BUSY; + } + + pHalSsiAdaptor = &obj->spi_adp; + pHalSsiOp = &obj->spi_op; + + if ((obj->dma_en & SPI_DMA_TX_EN)==0) { + if (HAL_OK == HalSsiTxGdmaInit(pHalSsiOp, pHalSsiAdaptor)) { + obj->dma_en |= SPI_DMA_TX_EN; + } + else { + return HAL_BUSY; + } + } + obj->state |= SPI_STATE_TX_BUSY; + ret = HalSsiDmaSend(pHalSsiAdaptor, tx_buffer, length); + if (ret != HAL_OK) { + obj->state &= ~SPI_STATE_TX_BUSY; + } + return (ret); +} + +int32_t spi_master_read_stream_dma(spi_t *obj, char *rx_buffer, uint32_t length) +{ + PHAL_SSI_ADAPTOR pHalSsiAdaptor; + PHAL_SSI_OP pHalSsiOp; + int32_t ret; + + if (obj->state & SPI_STATE_RX_BUSY) { + DBG_SSI_WARN("spi_master_read_stream_dma: state(0x%x) is not ready\r\n", + obj->state); + return HAL_BUSY; + } + + pHalSsiAdaptor = &obj->spi_adp; + pHalSsiOp = &obj->spi_op; + + if ((obj->dma_en & SPI_DMA_RX_EN)==0) { + if (HAL_OK == HalSsiRxGdmaInit(pHalSsiOp, pHalSsiAdaptor)) { + obj->dma_en |= SPI_DMA_RX_EN; + } + else { + return HAL_BUSY; + } + } + + obj->state |= SPI_STATE_RX_BUSY; + ret = HalSsiDmaRecv(pHalSsiAdaptor, rx_buffer, length); + if (ret != HAL_OK) { + obj->state &= ~SPI_STATE_RX_BUSY; + } + + // for master mode, we need to send data to generate clock out + if (obj->dma_en & SPI_DMA_TX_EN) { + // TX DMA is on already, so use DMA to TX data + // Make the GDMA to use the rx_buffer too + ret = HalSsiDmaSend(pHalSsiAdaptor, rx_buffer, length); + if (ret != HAL_OK) { + obj->state &= ~SPI_STATE_RX_BUSY; + } + } + else { + // TX DMA isn't enabled, so we just use Interrupt mode to TX dummy data + if ((ret=pHalSsiOp->HalSsiWriteInterrupt(pHalSsiAdaptor, NULL, length)) != HAL_OK) { + obj->state &= ~SPI_STATE_RX_BUSY; + } + } + + return ret; +} + +int32_t spi_master_write_stream_dma(spi_t *obj, char *tx_buffer, uint32_t length) +{ + PHAL_SSI_ADAPTOR pHalSsiAdaptor; + PHAL_SSI_OP pHalSsiOp; + int32_t ret; + + if (obj->state & SPI_STATE_TX_BUSY) { + DBG_SSI_WARN("spi_master_write_stream_dma: state(0x%x) is not ready\r\n", + obj->state); + return HAL_BUSY; + } + + pHalSsiAdaptor = &obj->spi_adp; + pHalSsiOp = &obj->spi_op; + + if ((obj->dma_en & SPI_DMA_TX_EN)==0) { + if (HAL_OK == HalSsiTxGdmaInit(pHalSsiOp, pHalSsiAdaptor)) { + obj->dma_en |= SPI_DMA_TX_EN; + } + else { + return HAL_BUSY; + } + } + + obj->state |= SPI_STATE_TX_BUSY; + ret = HalSsiDmaSend(pHalSsiAdaptor, tx_buffer, length); + if (ret != HAL_OK) { + obj->state &= ~SPI_STATE_TX_BUSY; + } + + return ret; +} + +#endif // end of "#ifdef CONFIG_GDMA_EN" diff --git a/component/common/mbed/targets/hal/rtl8195a/sys_api.c b/component/common/mbed/targets/hal/rtl8195a/sys_api.c new file mode 100644 index 0000000..d01fa9a --- /dev/null +++ b/component/common/mbed/targets/hal/rtl8195a/sys_api.c @@ -0,0 +1,180 @@ +/* mbed Microcontroller Library + ******************************************************************************* + * Copyright (c) 2014, Realtek + * All rights reserved. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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. + ******************************************************************************* + */ +#include "cmsis.h" +#include "sys_api.h" +#include "flash_api.h" + +#define OTA_Signature "81958711" +#define OTA_Clear "00000000" +#define OTA_Signature_len 8 +#define OTA_Signature_offset 8 +#define OTA_valid_offset 0x100000 +#define printf DiagPrintf + +extern VOID HalJtagPinOff(VOID); + +extern void HalInitLogUart(void); +extern void HalDeinitLogUart(void); + +/** + * @brief Turn off the JTAG function + * + * @return None + * + */ +void sys_jtag_off(void) +{ + HalJtagPinOff(); +} + +void sys_clear_ota_signature(void) +{ + flash_t flash; + u32 ota_offset = 0xFFFFFFFF, part1_offset, part2_offset; + u8 signature[OTA_Signature_len+1]; + + flash_stream_read(&flash, 0x18, 4, (u8*)&part1_offset); + part1_offset = (part1_offset&0xFFFF) * 1024; + flash_stream_read(&flash, part1_offset+OTA_Signature_offset, OTA_Signature_len, signature); + if(!memcmp((char const*)signature, OTA_Signature, OTA_Signature_len)){ + ota_offset = part1_offset; + } + + flash_stream_read(&flash, FLASH_SYSTEM_DATA_ADDR, 4, (u8*)&part2_offset); + flash_stream_read(&flash, part2_offset+OTA_Signature_offset, OTA_Signature_len, signature); + if(!memcmp((char const*)signature, OTA_Signature, OTA_Signature_len)){ + ota_offset = part2_offset; + } + + printf("\n\rOTA offset = 0x%08X", ota_offset); + + if(ota_offset < OTA_valid_offset){ + flash_stream_read(&flash, ota_offset+OTA_Signature_offset, OTA_Signature_len, signature); + signature[OTA_Signature_len] = '\0'; + printf("\n\rSignature = %s", signature); + if(!memcmp((char const*)signature, OTA_Signature, OTA_Signature_len)){ + memcpy((char*)signature, OTA_Clear, OTA_Signature_len); + flash_stream_write(&flash, ota_offset+OTA_Signature_offset, OTA_Signature_len, signature); + flash_stream_read(&flash, ota_offset+OTA_Signature_offset, OTA_Signature_len, signature); + signature[OTA_Signature_len] = '\0'; + printf("\n\rSignature = %s", signature); + printf("\n\rClear OTA signature success."); + } + } +} + +void sys_recover_ota_signature(void) +{ + flash_t flash; + u32 ota_offset = 0xFFFFFFFF, part1_offset, part2_offset; + u8 signature[OTA_Signature_len+1]; + u8* pbuf; + + flash_stream_read(&flash, 0x18, 4, (u8*)&part1_offset); + part1_offset = (part1_offset&0xFFFF) * 1024; + flash_stream_read(&flash, part1_offset+OTA_Signature_offset, OTA_Signature_len, signature); + if(!memcmp((char const*)signature, OTA_Clear, OTA_Signature_len)){ + ota_offset = part1_offset; + } + + flash_stream_read(&flash, FLASH_SYSTEM_DATA_ADDR, 4, (u8*)&part2_offset); + flash_stream_read(&flash, part2_offset+OTA_Signature_offset, OTA_Signature_len, signature); + if(!memcmp((char const*)signature, OTA_Clear, OTA_Signature_len)){ + ota_offset = part2_offset; + } + + printf("\n\rOTA offset = 0x%08X", ota_offset); + + if(ota_offset < OTA_valid_offset){ + flash_stream_read(&flash, ota_offset+OTA_Signature_offset, OTA_Signature_len, signature); + signature[OTA_Signature_len] = '\0'; + printf("\n\rSignature = %s", signature); + if(!memcmp((char const*)signature, OTA_Clear, OTA_Signature_len)){ + // backup + pbuf = RtlMalloc(FLASH_SECTOR_SIZE); + if(!pbuf) return; + flash_stream_read(&flash, ota_offset, FLASH_SECTOR_SIZE, pbuf); + memcpy((char*)pbuf+OTA_Signature_offset, OTA_Signature, OTA_Signature_len); + flash_erase_sector(&flash, FLASH_RESERVED_DATA_BASE); + flash_stream_write(&flash, FLASH_RESERVED_DATA_BASE, FLASH_SECTOR_SIZE, pbuf); + // Write + flash_stream_read(&flash, FLASH_RESERVED_DATA_BASE, FLASH_SECTOR_SIZE, pbuf); + flash_erase_sector(&flash, ota_offset); + flash_stream_write(&flash, ota_offset, FLASH_SECTOR_SIZE, pbuf); + flash_stream_read(&flash, ota_offset+OTA_Signature_offset, OTA_Signature_len, signature); + signature[OTA_Signature_len] = '\0'; + printf("\n\rSignature = %s", signature); + RtlMfree(pbuf, FLASH_SECTOR_SIZE); + printf("\n\rRecover OTA signature success."); + } + } +} + +void sys_log_uart_on(void) +{ + HalInitLogUart(); +} + +void sys_log_uart_off(void) +{ + HalDeinitLogUart(); +} + +void sys_adc_calibration(u8 write, u16 *offset, u16 *gain) +{ + flash_t flash; + u8* pbuf; + + if(write){ + // backup + pbuf = RtlMalloc(FLASH_SECTOR_SIZE); + if(!pbuf) return; + flash_stream_read(&flash, FLASH_SYSTEM_DATA_ADDR, FLASH_SECTOR_SIZE, pbuf); + memcpy((char*)pbuf+FLASH_ADC_PARA_OFFSET, offset, 2); + memcpy((char*)pbuf+FLASH_ADC_PARA_OFFSET+2, gain, 2); + flash_erase_sector(&flash, FLASH_RESERVED_DATA_BASE); + flash_stream_write(&flash, FLASH_RESERVED_DATA_BASE, FLASH_SECTOR_SIZE, pbuf); + // Write + flash_stream_read(&flash, FLASH_RESERVED_DATA_BASE, FLASH_SECTOR_SIZE, pbuf); + flash_erase_sector(&flash, FLASH_SYSTEM_DATA_ADDR); + flash_stream_write(&flash, FLASH_SYSTEM_DATA_ADDR, FLASH_SECTOR_SIZE, pbuf); + RtlMfree(pbuf, FLASH_SECTOR_SIZE); + printf("\n\rStore ADC calibration success."); + } + flash_stream_read(&flash, FLASH_ADC_PARA_BASE, 2, (u8*)offset); + flash_stream_read(&flash, FLASH_ADC_PARA_BASE+2, 2, (u8*)gain); + printf("\n\rADC offset = 0x%04X, gain = 0x%04X.\n\r", *offset, *gain); +} + +/** + * @brief system software reset + * + * @return None + * + */ +void sys_reset(void) +{ + // Set processor clock to default before system reset + HAL_WRITE32(SYSTEM_CTRL_BASE, 0x14, 0x00000021); + HalDelayUs(100*1000); + + // Cortex-M3 SCB->AIRCR + HAL_WRITE32(0xE000ED00, 0x0C, (0x5FA << 16) | // VECTKEY + (HAL_READ32(0xE000ED00, 0x0C) & (7 << 8)) | // PRIGROUP + (1 << 2)); // SYSRESETREQ +} diff --git a/component/common/mbed/targets/hal/rtl8195a/timer_api.c b/component/common/mbed/targets/hal/rtl8195a/timer_api.c new file mode 100644 index 0000000..0bfb9ad --- /dev/null +++ b/component/common/mbed/targets/hal/rtl8195a/timer_api.c @@ -0,0 +1,135 @@ +/* mbed Microcontroller Library + ******************************************************************************* + * Copyright (c) 2014, Realtek Semiconductor Corp. + * All rights reserved. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + ******************************************************************************* + */ + +#include "objects.h" +//#include +#include "timer_api.h" +//#include "PeripheralNames.h" + +#if CONFIG_TIMER_EN + +extern HAL_TIMER_OP HalTimerOp; + +extern HAL_Status HalTimerInitRtl8195a_Patch( + IN VOID *Data +); + +static void gtimer_timeout_handler (uint32_t tid) +{ + gtimer_t *obj = (gtimer_t *)tid; + PTIMER_ADAPTER pTimerAdapter = &(obj->hal_gtimer_adp); + gtimer_irq_handler handler; + + if (obj->handler != NULL) { + handler = (gtimer_irq_handler)obj->handler; + handler(obj->hid); + } + + if (!obj->is_periodcal) { + gtimer_stop(obj); + } +} + +void gtimer_init (gtimer_t *obj, uint32_t tid) +{ + PTIMER_ADAPTER pTimerAdapter = &(obj->hal_gtimer_adp); + + if (tid > GTIMER_MAX) { + DBG_TIMER_ERR("%s: Invalid TimerId=%d\r\n", __FUNCTION__, tid); + return; + } + + pTimerAdapter->IrqDis = 0; // Enable Irq @ initial + pTimerAdapter->IrqHandle.IrqFun = (IRQ_FUN) gtimer_timeout_handler; + pTimerAdapter->IrqHandle.IrqNum = TIMER2_7_IRQ; + pTimerAdapter->IrqHandle.Priority = 0; + pTimerAdapter->IrqHandle.Data = (u32)obj; + pTimerAdapter->TimerId = (u8)tid; + pTimerAdapter->TimerIrqPriority = 0; + pTimerAdapter->TimerLoadValueUs = 0xFFFFFFFF; // Just a whatever value + pTimerAdapter->TimerMode = USER_DEFINED; + + HalTimerInit ((VOID*) pTimerAdapter); +// gtimer_stop(obj); // HAL Initial will let the timer started, just stop it after initial +} + +void gtimer_deinit (gtimer_t *obj) +{ + PTIMER_ADAPTER pTimerAdapter = &(obj->hal_gtimer_adp); + + HalTimerDeInit((void*)pTimerAdapter); +} + +uint32_t gtimer_read_tick (gtimer_t *obj) +{ + PTIMER_ADAPTER pTimerAdapter = &obj->hal_gtimer_adp; + + return (HalTimerOp.HalTimerReadCount(pTimerAdapter->TimerId)); +} + +uint64_t gtimer_read_us (gtimer_t *obj) +{ + uint64_t time_us; + + time_us = gtimer_read_tick(obj)*1000000/32768; + + return (time_us); +} + +void gtimer_reload (gtimer_t *obj, uint32_t duration_us) +{ + PTIMER_ADAPTER pTimerAdapter = &obj->hal_gtimer_adp; + + HalTimerReLoad(pTimerAdapter->TimerId, duration_us); +} + + +void gtimer_start (gtimer_t *obj) +{ + PTIMER_ADAPTER pTimerAdapter = &obj->hal_gtimer_adp; + u8 TimerId = pTimerAdapter->TimerId; + + HalTimerEnable(TimerId); +#if 0 + HalTimerOp.HalTimerEn(pTimerAdapter->TimerId); + + HAL_TIMER_WRITE32((TIMER_INTERVAL*TimerId + TIMER_CTL_REG_OFF), + HAL_TIMER_READ32(TIMER_INTERVAL*TimerId + TIMER_CTL_REG_OFF) | (BIT0)); +#endif +} + +void gtimer_start_one_shout (gtimer_t *obj, uint32_t duration_us, void* handler, uint32_t hid) +{ + obj->is_periodcal = _FALSE; + obj->handler = handler; + obj->hid = hid; + gtimer_reload(obj, duration_us); + gtimer_start(obj); +} + +void gtimer_start_periodical (gtimer_t *obj, uint32_t duration_us, void* handler, uint32_t hid) +{ + obj->is_periodcal = _TRUE; + obj->handler = handler; + obj->hid = hid; + gtimer_reload(obj, duration_us); + gtimer_start(obj); +} + +void gtimer_stop (gtimer_t *obj) +{ + PTIMER_ADAPTER pTimerAdapter = &obj->hal_gtimer_adp; + +// obj->handler = NULL; +// HalTimerOp.HalTimerDis(pTimerAdapter->TimerId); + HalTimerDisable(pTimerAdapter->TimerId); +} + +#endif // end of "#if CONFIG_TIMER_EN" diff --git a/component/common/mbed/targets/hal/rtl8195a/timer_api.h b/component/common/mbed/targets/hal/rtl8195a/timer_api.h new file mode 100644 index 0000000..81193b4 --- /dev/null +++ b/component/common/mbed/targets/hal/rtl8195a/timer_api.h @@ -0,0 +1,38 @@ +/******************************************************************************* +* Copyright (c) 2014, Realtek Semiconductor Corp. +* All rights reserved. +* +* This module is a confidential and proprietary property of RealTek and +* possession or use of this module requires written permission of RealTek. +*******************************************************************************/ +#ifndef MBED_EXT_TIMER_API_EXT_H +#define MBED_EXT_TIMER_API_EXT_H + +#include "device.h" +//#include "rtl8195a.h" + +typedef void (*gtimer_irq_handler)(uint32_t id); + +typedef struct gtimer_s gtimer_t; +enum { + TIMER0 = 2, // GTimer 2, share with us_tick(wait_ms()) functions + TIMER1 = 3, // GTimer 3, share with PWM_0 + TIMER2 = 4, // GTimer 4, share with PWM_1 + TIMER3 = 5, // GTimer 5, share with PWM_2 + TIMER4 = 6, // GTimer 6, share with PWM_3 + TIMER5 = 7, // share with the software-RTC + + GTIMER_MAX = 7 +}; + +void gtimer_init (gtimer_t *obj, uint32_t tid); +void gtimer_deinit (gtimer_t *obj); +uint32_t gtimer_read_tick (gtimer_t *obj); +uint64_t gtimer_read_us (gtimer_t *obj); +void gtimer_reload (gtimer_t *obj, uint32_t duration_us); +void gtimer_start (gtimer_t *obj); +void gtimer_start_one_shout (gtimer_t *obj, uint32_t duration_us, void* handler, uint32_t hid); +void gtimer_start_periodical (gtimer_t *obj, uint32_t duration_us, void* handler, uint32_t hid); +void gtimer_stop (gtimer_t *obj); + +#endif diff --git a/component/common/mbed/targets/hal/rtl8195a/us_ticker.c b/component/common/mbed/targets/hal/rtl8195a/us_ticker.c new file mode 100644 index 0000000..84d0f95 --- /dev/null +++ b/component/common/mbed/targets/hal/rtl8195a/us_ticker.c @@ -0,0 +1,103 @@ +/* mbed Microcontroller Library + ******************************************************************************* + * Copyright (c) 2014, Realtek Semiconductor Corp. + * All rights reserved. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + ******************************************************************************* + */ +#include "objects.h" +#include +#include "us_ticker_api.h" +#include "PeripheralNames.h" + +#define SYS_TIM_ID 1 // the G-Timer ID for System +#define APP_TIM_ID 6 // the G-Timer ID for Application + +static int us_ticker_inited = 0; +static TIMER_ADAPTER TimerAdapter; + +extern HAL_TIMER_OP HalTimerOp; + +VOID _us_ticker_irq_handler(IN VOID *Data) +{ + us_ticker_irq_handler(); +} + +void us_ticker_init(void) +{ + + if (us_ticker_inited) return; + us_ticker_inited = 1; + + // Initial a G-Timer + TimerAdapter.IrqDis = 1; // Disable Irq + TimerAdapter.IrqHandle.IrqFun = (IRQ_FUN) _us_ticker_irq_handler; + TimerAdapter.IrqHandle.IrqNum = TIMER2_7_IRQ; + TimerAdapter.IrqHandle.Priority = 0x20; + TimerAdapter.IrqHandle.Data = (u32)NULL; + TimerAdapter.TimerId = APP_TIM_ID; + TimerAdapter.TimerIrqPriority = 0; + TimerAdapter.TimerLoadValueUs = 1; + TimerAdapter.TimerMode = FREE_RUN_MODE; // Countdown Free Run + + HalTimerOp.HalTimerInit((VOID*) &TimerAdapter); + + DBG_TIMER_INFO("%s: Timer_Id=%d\n", __FUNCTION__, APP_TIM_ID); +} + +uint32_t us_ticker_read() +{ + uint32_t tick_cnt; + uint32_t tick_cnt_div_4; + uint32_t tick_cnt_mod_4; + uint64_t us_tick; + + //1 Our G-timer resolution is ~31 us (1/32K), and is a countdown timer +// if (!us_ticker_inited) { +// us_ticker_init(); +// } + tick_cnt = HalTimerOp.HalTimerReadCount(SYS_TIM_ID); + tick_cnt = 0xffffffff - tick_cnt; // it's a down counter + tick_cnt_div_4 = tick_cnt >> 2; + tick_cnt_mod_4 = tick_cnt - (tick_cnt_div_4 << 2); + us_tick = (TIMER_TICK_US_X4*tick_cnt_div_4) + (TIMER_TICK_US*tick_cnt_mod_4); + + // TODO: handle overflow + return ((uint32_t)us_tick); +} + +void us_ticker_set_interrupt(timestamp_t timestamp) +{ + uint32_t cur_time_us; + uint32_t time_def; + + cur_time_us = us_ticker_read(); + if ((uint32_t)timestamp >= cur_time_us) { + time_def = (uint32_t)timestamp - cur_time_us; + } + else { + time_def = 0xffffffff - cur_time_us + (uint32_t)timestamp; + } + + if (time_def < TIMER_TICK_US) { + time_def = TIMER_TICK_US; // at least 1 tick + } + + TimerAdapter.IrqDis = 0; // Enable Irq + TimerAdapter.TimerLoadValueUs = time_def; + TimerAdapter.TimerMode = USER_DEFINED; // Countdown Free Run + + HalTimerOp.HalTimerInit((VOID*) &TimerAdapter); +} + +void us_ticker_disable_interrupt(void) +{ + HalTimerOp.HalTimerDis((u32)TimerAdapter.TimerId); +} + +void us_ticker_clear_interrupt(void) +{ + HalTimerOp.HalTimerIrqClear((u32)TimerAdapter.TimerId); +} diff --git a/component/common/mbed/targets/hal/rtl8195a/wdt_api.c b/component/common/mbed/targets/hal/rtl8195a/wdt_api.c new file mode 100644 index 0000000..bb24caf --- /dev/null +++ b/component/common/mbed/targets/hal/rtl8195a/wdt_api.c @@ -0,0 +1,94 @@ +/* mbed Microcontroller Library + ******************************************************************************* + * Copyright (c) 2014, Realtek + * All rights reserved. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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. + ******************************************************************************* + */ +#include "wdt_api.h" +#include "cmsis.h" + +extern VOID WDGInitial(u32 Period); +extern VOID WDGStart(VOID); +extern VOID WDGStop(VOID); +extern VOID WDGRefresh(VOID); +extern VOID WDGIrqInitial(VOID); +extern VOID WDGIrqCallBackReg(VOID *CallBack, u32 Id); + +/** + * @brief Initial the watch dog time setting + * + * @param timeout_ms: the watch-dog timer timeout value, in ms. + * default action of timeout is to reset the whole system. + * @return None + * + */ +void watchdog_init(uint32_t timeout_ms) +{ + WDGInitial(timeout_ms); +} + +/** + * @brief Start the watchdog counting + * + * @param None + * @return None + * + */ +void watchdog_start(void) +{ + WDGStart(); +} + +/** + * @brief Stop the watchdog counting + * + * @param None + * @return None + * + */ +void watchdog_stop(void) +{ + WDGStop(); +} + +/** + * @brief Refresh the watchdog counting to prevent WDT timeout + * + * @param None + * @return None + * + */ +void watchdog_refresh(void) +{ + WDGRefresh(); +} + +/** + * @brief Switch the watchdog timer to interrupt mode and + * register a watchdog timer timeout interrupt handler. + * The interrupt handler will be called when the watch-dog + * timer is timeout. + * + * @param handler: the callback function for WDT timeout interrupt. + * id: the parameter for the callback function + * @return None + * + */ +void watchdog_irq_init(wdt_irq_handler handler, uint32_t id) +{ + WDGIrqCallBackReg((VOID*)handler, (u32)id); + WDGIrqInitial(); +} + + diff --git a/component/common/network/dhcp/dhcps.c b/component/common/network/dhcp/dhcps.c new file mode 100644 index 0000000..a684fe6 --- /dev/null +++ b/component/common/network/dhcp/dhcps.c @@ -0,0 +1,618 @@ + +#include "dhcps.h" +#include "tcpip.h" + +//static struct dhcp_server_state dhcp_server_state_machine; +static uint8_t dhcp_server_state_machine = DHCP_SERVER_STATE_IDLE; +/* recorded the client MAC addr(default sudo mac) */ +//static uint8_t dhcps_record_first_client_mac[6] = {0xff,0xff,0xff,0xff,0xff,0xff}; +/* recorded transaction ID (default sudo id)*/ +static uint8_t dhcp_recorded_xid[4] = {0xff, 0xff, 0xff, 0xff}; + +/* UDP Protocol Control Block(PCB) */ +static struct udp_pcb *dhcps_pcb; + +static struct ip_addr dhcps_send_broadcast_address; +static struct ip_addr dhcps_local_address; +static struct ip_addr dhcps_local_mask; +static struct ip_addr dhcps_local_gateway; +static struct ip_addr dhcps_network_id; +static struct ip_addr dhcps_subnet_broadcast; +static struct ip_addr dhcps_allocated_client_address; +static int dhcps_addr_pool_set = 0; +static struct ip_addr dhcps_addr_pool_start; +static struct ip_addr dhcps_addr_pool_end; +#if 0 +static struct ip_addr dhcps_owned_first_ip; +static struct ip_addr dhcps_owned_last_ip; +static uint8_t dhcps_num_of_available_ips; +#endif +static struct dhcp_msg *dhcp_message_repository; +static int dhcp_message_total_options_lenth; + +/* allocated IP range */ +static struct table ip_table; +static struct ip_addr client_request_ip; + +static uint8_t dhcp_client_ethernet_address[16]; +static uint8_t bound_client_ethernet_address[16]; + +static xSemaphoreHandle dhcps_ip_table_semaphore; + +static struct netif * dhcps_netif = NULL; +/** + * @brief latch the specific ip in the ip table. + * @param d the specific index + * @retval None. + */ +#if (!IS_USE_FIXED_IP) +static void mark_ip_in_table(uint8_t d) +{ +#if (debug_dhcps) + printf("\r\n mark ip %d\r\n",d); +#endif + xSemaphoreTake(dhcps_ip_table_semaphore, portMAX_DELAY); + if (0 < d && d <= 32) { + ip_table.ip_range[0] = MARK_RANGE1_IP_BIT(ip_table, d); +#if (debug_dhcps) + printf("\r\n ip_table.ip_range[0] = 0x%x\r\n",ip_table.ip_range[0]); +#endif + } else if (32 < d && d <= 64) { + ip_table.ip_range[1] = MARK_RANGE2_IP_BIT(ip_table, (d - 32)); +#if (debug_dhcps) + printf("\r\n ip_table.ip_range[1] = 0x%x\r\n",ip_table.ip_range[1]); +#endif + } else if (64 < d && d <= 96) { + ip_table.ip_range[2] = MARK_RANGE3_IP_BIT(ip_table, (d - 64)); +#if (debug_dhcps) + printf("\r\n ip_table.ip_range[2] = 0x%x\r\n",ip_table.ip_range[2]); +#endif + } else if (96 < d && d <= 128) { + ip_table.ip_range[3] = MARK_RANGE4_IP_BIT(ip_table, (d - 96)); +#if (debug_dhcps) + printf("\r\n ip_table.ip_range[3] = 0x%x\r\n",ip_table.ip_range[3]); +#endif + } else { + printf("\r\n Request ip over the range(1-128) \r\n"); + } + xSemaphoreGive(dhcps_ip_table_semaphore); + +} +#endif + +/** + * @brief get one usable ip from the ip table of dhcp server. + * @param: None + * @retval the usable index which represent the ip4_addr(ip) of allocated ip addr. + */ +#if (!IS_USE_FIXED_IP) +static uint8_t search_next_ip(void) +{ + uint8_t range_count, offset_count; + uint8_t start, end; + if(dhcps_addr_pool_set){ + start = (uint8_t)ip4_addr4(&dhcps_addr_pool_start); + end = (uint8_t)ip4_addr4(&dhcps_addr_pool_end); + }else{ + start = 0; + end = 255; + } + xSemaphoreTake(dhcps_ip_table_semaphore, portMAX_DELAY); + for (range_count = 0; range_count < 4; range_count++) { + for (offset_count = 0;offset_count < 32; offset_count++) { + if ((((ip_table.ip_range[range_count] >> offset_count) & 0x01) == 0) + &&(((range_count * 32) + (offset_count + 1)) >= start) + &&(((range_count * 32) + (offset_count + 1)) <= end)) { + xSemaphoreGive(dhcps_ip_table_semaphore); + return ((range_count * 32) + (offset_count + 1)); + } + } + } + xSemaphoreGive(dhcps_ip_table_semaphore); + return 0; +} +#endif + +/** + * @brief fill in the option field with message type of a dhcp message. + * @param msg_option_base_addr: the addr be filled start. + * message_type: the type code you want to fill in + * @retval the start addr of the next dhcp option. + */ +static uint8_t *add_msg_type(uint8_t *msg_option_base_addr, uint8_t message_type) +{ + uint8_t *option_start; + msg_option_base_addr[0] = DHCP_OPTION_CODE_MSG_TYPE; + msg_option_base_addr[1] = DHCP_OPTION_LENGTH_ONE; + msg_option_base_addr[2] = message_type; + option_start = msg_option_base_addr + 3; + if (DHCP_MESSAGE_TYPE_NAK == message_type) + *option_start++ = DHCP_OPTION_CODE_END; + return option_start; +} + + +static uint8_t *fill_one_option_content(uint8_t *option_base_addr, + uint8_t option_code, uint8_t option_length, void *copy_info) +{ + uint8_t *option_data_base_address; + uint8_t *next_option_start_address = NULL; + option_base_addr[0] = option_code; + option_base_addr[1] = option_length; + option_data_base_address = option_base_addr + 2; + switch (option_length) { + case DHCP_OPTION_LENGTH_FOUR: + memcpy(option_data_base_address, copy_info, DHCP_OPTION_LENGTH_FOUR); + next_option_start_address = option_data_base_address + 4; + break; + case DHCP_OPTION_LENGTH_TWO: + memcpy(option_data_base_address, copy_info, DHCP_OPTION_LENGTH_TWO); + next_option_start_address = option_data_base_address + 2; + break; + case DHCP_OPTION_LENGTH_ONE: + memcpy(option_data_base_address, copy_info, DHCP_OPTION_LENGTH_ONE); + next_option_start_address = option_data_base_address + 1; + break; + } + + return next_option_start_address; +} + +/** + * @brief fill in the needed content of the dhcp offer message. + * @param optptr the addr which the tail of dhcp magic field. + * @retval the addr represent to add the end of option. + */ +static void add_offer_options(uint8_t *option_start_address) +{ + uint8_t *temp_option_addr; + /* add DHCP options 1. + The subnet mask option specifies the client's subnet mask */ + temp_option_addr = fill_one_option_content(option_start_address, + DHCP_OPTION_CODE_SUBNET_MASK, DHCP_OPTION_LENGTH_FOUR, + (void *)&dhcps_local_mask); + + /* add DHCP options 3 (i.e router(gateway)). The time server option + specifies a list of RFC 868 [6] time servers available to the client. */ + temp_option_addr = fill_one_option_content(temp_option_addr, + DHCP_OPTION_CODE_ROUTER, DHCP_OPTION_LENGTH_FOUR, + (void *)&dhcps_local_address); + + /* add DHCP options 6 (i.e DNS). + The option specifies a list of DNS servers available to the client. */ + temp_option_addr = fill_one_option_content(temp_option_addr, + DHCP_OPTION_CODE_DNS_SERVER, DHCP_OPTION_LENGTH_FOUR, + (void *)&dhcps_local_address); + /* add DHCP options 51. + This option is used to request a lease time for the IP address. */ + temp_option_addr = fill_one_option_content(temp_option_addr, + DHCP_OPTION_CODE_LEASE_TIME, DHCP_OPTION_LENGTH_FOUR, + (void *)&dhcp_option_lease_time_one_day); + /* add DHCP options 54. + The identifier is the IP address of the selected server. */ + temp_option_addr = fill_one_option_content(temp_option_addr, + DHCP_OPTION_CODE_SERVER_ID, DHCP_OPTION_LENGTH_FOUR, + (void *)&dhcps_local_address); + /* add DHCP options 28. + This option specifies the broadcast address in use on client's subnet.*/ + temp_option_addr = fill_one_option_content(temp_option_addr, + DHCP_OPTION_CODE_BROADCAST_ADDRESS, DHCP_OPTION_LENGTH_FOUR, + (void *)&dhcps_subnet_broadcast); + /* add DHCP options 26. + This option specifies the Maximum transmission unit to use */ + temp_option_addr = fill_one_option_content(temp_option_addr, + DHCP_OPTION_CODE_INTERFACE_MTU, DHCP_OPTION_LENGTH_TWO, + (void *) &dhcp_option_interface_mtu_576); + /* add DHCP options 31. + This option specifies whether or not the client should solicit routers */ + temp_option_addr = fill_one_option_content(temp_option_addr, + DHCP_OPTION_CODE_PERFORM_ROUTER_DISCOVERY, DHCP_OPTION_LENGTH_ONE, + NULL); + *temp_option_addr++ = DHCP_OPTION_CODE_END; + +} + + +/** + * @brief fill in common content of a dhcp message. + * @param m the pointer which point to the dhcp message store in. + * @retval None. + */ +static void dhcps_initialize_message(struct dhcp_msg *dhcp_message_repository, struct ip_addr yiaddr) +{ + + dhcp_message_repository->op = DHCP_MESSAGE_OP_REPLY; + dhcp_message_repository->htype = DHCP_MESSAGE_HTYPE; + dhcp_message_repository->hlen = DHCP_MESSAGE_HLEN; + dhcp_message_repository->hops = 0; + memcpy((char *)dhcp_recorded_xid, (char *) dhcp_message_repository->xid, + sizeof(dhcp_message_repository->xid)); + dhcp_message_repository->secs = 0; + dhcp_message_repository->flags = htons(BOOTP_BROADCAST); + + memcpy((char *)dhcp_message_repository->yiaddr, + (char *)&yiaddr, + sizeof(dhcp_message_repository->yiaddr)); + + memset((char *)dhcp_message_repository->ciaddr, 0, + sizeof(dhcp_message_repository->ciaddr)); + memset((char *)dhcp_message_repository->siaddr, 0, + sizeof(dhcp_message_repository->siaddr)); + memset((char *)dhcp_message_repository->giaddr, 0, + sizeof(dhcp_message_repository->giaddr)); + memcpy((char *)dhcp_message_repository->chaddr, &dhcp_client_ethernet_address, + sizeof(dhcp_message_repository->chaddr)); + memset((char *)dhcp_message_repository->sname, 0, + sizeof(dhcp_message_repository->sname)); + memset((char *)dhcp_message_repository->file, 0, + sizeof(dhcp_message_repository->file)); + memset((char *)dhcp_message_repository->options, 0, + dhcp_message_total_options_lenth); + memcpy((char *)dhcp_message_repository->options, (char *)dhcp_magic_cookie, + sizeof(dhcp_magic_cookie)); +} + +/** + * @brief init and fill in the needed content of dhcp offer message. + * @param packet_buffer packet buffer for UDP. + * @retval None. + */ +static void dhcps_send_offer(struct pbuf *packet_buffer) +{ + uint8_t temp_ip = 0; + dhcp_message_repository = (struct dhcp_msg *)packet_buffer->payload; +#if (!IS_USE_FIXED_IP) + if ((ip4_addr4(&dhcps_allocated_client_address) != 0) && + (memcmp((void *)&dhcps_allocated_client_address, (void *)&client_request_ip, 4) == 0) && + (memcmp((void *)&bound_client_ethernet_address, (void *)&dhcp_client_ethernet_address, 16) == 0)) { + temp_ip = (uint8_t) ip4_addr4(&client_request_ip); + } else if ((ip4_addr1(&client_request_ip) == ip4_addr1(&dhcps_network_id)) && + (ip4_addr2(&client_request_ip) == ip4_addr2(&dhcps_network_id)) && + (ip4_addr3(&client_request_ip) == ip4_addr3(&dhcps_network_id))) { + uint8_t request_ip4 = (uint8_t) ip4_addr4(&client_request_ip); + if ((request_ip4 != 0) && (((request_ip4 - 1) / 32) >= 0) && (((request_ip4 - 1) / 32) <= 3) && + (((ip_table.ip_range[(request_ip4 - 1) / 32] >> ((request_ip4 - 1) % 32)) & 0x01) == 0)) { + temp_ip = request_ip4; + } + } + + /* create new client ip */ + if(temp_ip == 0) temp_ip = search_next_ip(); +#if (debug_dhcps) + printf("\r\n temp_ip = %d",temp_ip); +#endif + if (temp_ip == 0) { +#if 0 + memset(&ip_table, 0, sizeof(struct table)); + mark_ip_in_table((uint8_t)ip4_addr4(&dhcps_local_address)); + printf("\r\n reset ip table!!\r\n"); +#endif + printf("\r\n No useable ip!!!!\r\n"); + } + + IP4_ADDR(&dhcps_allocated_client_address, (ip4_addr1(&dhcps_network_id)), + ip4_addr2(&dhcps_network_id), ip4_addr3(&dhcps_network_id), temp_ip); + memcpy(bound_client_ethernet_address, dhcp_client_ethernet_address, sizeof(bound_client_ethernet_address)); +#endif + dhcps_initialize_message(dhcp_message_repository, dhcps_allocated_client_address); + add_offer_options(add_msg_type(&dhcp_message_repository->options[4], + DHCP_MESSAGE_TYPE_OFFER)); + udp_sendto_if(dhcps_pcb, packet_buffer, + &dhcps_send_broadcast_address, DHCP_CLIENT_PORT, dhcps_netif); +} + +/** + * @brief init and fill in the needed content of dhcp nak message. + * @param packet buffer packet buffer for UDP. + * @retval None. + */ +static void dhcps_send_nak(struct pbuf *packet_buffer) +{ + struct ip_addr zero_address; + IP4_ADDR(&zero_address, 0, 0, 0, 0); + + dhcp_message_repository = (struct dhcp_msg *)packet_buffer->payload; + dhcps_initialize_message(dhcp_message_repository, zero_address); + add_msg_type(&dhcp_message_repository->options[4], DHCP_MESSAGE_TYPE_NAK); + udp_sendto_if(dhcps_pcb, packet_buffer, + &dhcps_send_broadcast_address, DHCP_CLIENT_PORT, dhcps_netif); +} + +/** + * @brief init and fill in the needed content of dhcp ack message. + * @param packet buffer packet buffer for UDP. + * @retval None. + */ +static void dhcps_send_ack(struct pbuf *packet_buffer) +{ + dhcp_message_repository = (struct dhcp_msg *)packet_buffer->payload; + dhcps_initialize_message(dhcp_message_repository, dhcps_allocated_client_address); + add_offer_options(add_msg_type(&dhcp_message_repository->options[4], + DHCP_MESSAGE_TYPE_ACK)); + udp_sendto_if(dhcps_pcb, packet_buffer, + &dhcps_send_broadcast_address, DHCP_CLIENT_PORT, dhcps_netif); +} + +/** + * @brief according by the input message type to reflect the correspond state. + * @param option_message_type the input server state + * @retval the server state which already transfer to. + */ +uint8_t dhcps_handle_state_machine_change(uint8_t option_message_type) +{ + switch (option_message_type) { + case DHCP_MESSAGE_TYPE_DECLINE: + dhcp_server_state_machine = DHCP_SERVER_STATE_IDLE; + break; + case DHCP_MESSAGE_TYPE_DISCOVER: + if (dhcp_server_state_machine == DHCP_SERVER_STATE_IDLE) { + dhcp_server_state_machine = DHCP_SERVER_STATE_OFFER; + } + break; + case DHCP_MESSAGE_TYPE_REQUEST: + +#if (!IS_USE_FIXED_IP) + if (dhcp_server_state_machine == DHCP_SERVER_STATE_OFFER) { + if (ip4_addr4(&dhcps_allocated_client_address) != 0) { + if (memcmp((void *)&dhcps_allocated_client_address, (void *)&client_request_ip, 4) == 0) { + dhcp_server_state_machine = DHCP_SERVER_STATE_ACK; + } else { + dhcp_server_state_machine = DHCP_SERVER_STATE_NAK; + } + } else { + dhcp_server_state_machine = DHCP_SERVER_STATE_NAK; + } + } else if (dhcp_server_state_machine == DHCP_SERVER_STATE_IDLE) { + if ((ip4_addr4(&dhcps_allocated_client_address) != 0) && + (memcmp((void *)&dhcps_allocated_client_address, (void *)&client_request_ip, 4) == 0) && + (memcmp((void *)&bound_client_ethernet_address, (void *)&dhcp_client_ethernet_address, 16) == 0)) { + dhcp_server_state_machine = DHCP_SERVER_STATE_ACK; + } else if ((ip4_addr1(&client_request_ip) == ip4_addr1(&dhcps_network_id)) && + (ip4_addr2(&client_request_ip) == ip4_addr2(&dhcps_network_id)) && + (ip4_addr3(&client_request_ip) == ip4_addr3(&dhcps_network_id))) { + uint8_t request_ip4 = (uint8_t) ip4_addr4(&client_request_ip); + if ((request_ip4 != 0) && (((request_ip4 - 1) / 32) >= 0) && (((request_ip4 - 1) / 32) <= 3) && + (((ip_table.ip_range[(request_ip4 - 1) / 32] >> ((request_ip4 - 1) % 32)) & 0x01) == 0)) { + IP4_ADDR(&dhcps_allocated_client_address, (ip4_addr1(&dhcps_network_id)), + ip4_addr2(&dhcps_network_id), ip4_addr3(&dhcps_network_id), request_ip4); + memcpy(bound_client_ethernet_address, dhcp_client_ethernet_address, sizeof(bound_client_ethernet_address)); + dhcp_server_state_machine = DHCP_SERVER_STATE_ACK; + } else { + dhcp_server_state_machine = DHCP_SERVER_STATE_NAK; + } + } else { + dhcp_server_state_machine = DHCP_SERVER_STATE_NAK; + } + } else { + dhcp_server_state_machine = DHCP_SERVER_STATE_NAK; + } +#else + if (!(dhcp_server_state_machine == DHCP_SERVER_STATE_ACK || + dhcp_server_state_machine == DHCP_SERVER_STATE_NAK)) { + dhcp_server_state_machine = DHCP_SERVER_STATE_NAK; + } +#endif + break; + case DHCP_MESSAGE_TYPE_RELEASE: + dhcp_server_state_machine = DHCP_SERVER_STATE_IDLE; + break; + } + + return dhcp_server_state_machine; +} +/** + * @brief parse the dhcp message option part. + * @param optptr: the addr of the first option field. + * len: the total length of all option fields. + * @retval dhcp server state. + */ +static uint8_t dhcps_handle_msg_options(uint8_t *option_start, int16_t total_option_length) +{ + + int16_t option_message_type = 0; + uint8_t *option_end = option_start + total_option_length; + //dhcp_server_state_machine = DHCP_SERVER_STATE_IDLE; + + /* begin process the dhcp option info */ + while (option_start < option_end) { + switch ((uint8_t)*option_start) { + case DHCP_OPTION_CODE_MSG_TYPE: + option_message_type = *(option_start + 2); // 2 => code(1)+lenth(1) + break; + case DHCP_OPTION_CODE_REQUEST_IP_ADDRESS : +#if IS_USE_FIXED_IP + if (memcmp((char *)&dhcps_allocated_client_address, + (char *)option_start + 2, 4) == 0) + dhcp_server_state_machine = DHCP_SERVER_STATE_ACK; + else + dhcp_server_state_machine = DHCP_SERVER_STATE_NAK; +#else + memcpy((char *)&client_request_ip, (char *)option_start + 2, 4); +#endif + break; + } + // calculate the options offset to get next option's base addr + option_start += option_start[1] + 2; // optptr[1]: length value + (code(1)+ Len(1)) + } + return dhcps_handle_state_machine_change(option_message_type); +} + +/** + * @brief get message from buffer then check whether it is dhcp related or not. + * if yes , parse it more to undersatnd the client's request. + * @param same as recv callback function definition + * @retval if message is dhcp related then return dhcp server state, + * otherwise return 0 + */ +static uint8_t dhcps_check_msg_and_handle_options(struct pbuf *packet_buffer) +{ + int dhcp_message_option_offset; + dhcp_message_repository = (struct dhcp_msg *)packet_buffer->payload; + memcpy(dhcp_client_ethernet_address, dhcp_message_repository->chaddr, sizeof(dhcp_client_ethernet_address)); + dhcp_message_option_offset = ((int)dhcp_message_repository->options + - (int)packet_buffer->payload); + dhcp_message_total_options_lenth = (packet_buffer->len + - dhcp_message_option_offset); + /* check the magic number,if correct parse the content of options */ + if (memcmp((char *)dhcp_message_repository->options, + (char *)dhcp_magic_cookie, sizeof(dhcp_magic_cookie)) == 0) { + return dhcps_handle_msg_options(&dhcp_message_repository->options[4], + (dhcp_message_total_options_lenth - 4)); + } + + return 0; +} + + +/** + * @brief handle imcoming dhcp message and response message to client + * @param same as recv callback function definition + * @retval None + */ +static void dhcps_receive_udp_packet_handler(void *arg, struct udp_pcb *udp_pcb, +struct pbuf *udp_packet_buffer, struct ip_addr *sender_addr, uint16_t sender_port) +{ + int16_t total_length_of_packet_buffer; + struct pbuf *merged_packet_buffer = NULL; + + dhcp_message_repository = (struct dhcp_msg *)udp_packet_buffer->payload; + if (udp_packet_buffer == NULL) { + printf("\n\r Error!!!! System doesn't allocate any buffer \n\r"); + return; + } + if (sender_port == DHCP_CLIENT_PORT) { + total_length_of_packet_buffer = udp_packet_buffer->tot_len; + if (udp_packet_buffer->next != NULL) { + merged_packet_buffer = pbuf_coalesce(udp_packet_buffer, + PBUF_TRANSPORT); + if (merged_packet_buffer->tot_len != + total_length_of_packet_buffer) { + pbuf_free(udp_packet_buffer); + return; + } + } + switch (dhcps_check_msg_and_handle_options(udp_packet_buffer)) { + case DHCP_SERVER_STATE_OFFER: + dhcps_send_offer(udp_packet_buffer); + break; + case DHCP_SERVER_STATE_ACK: + dhcps_send_ack(udp_packet_buffer); +#if (!IS_USE_FIXED_IP) + mark_ip_in_table((uint8_t)ip4_addr4(&dhcps_allocated_client_address)); +#endif + dhcp_server_state_machine = DHCP_SERVER_STATE_IDLE; + break; + case DHCP_SERVER_STATE_NAK: + dhcps_send_nak(udp_packet_buffer); + dhcp_server_state_machine = DHCP_SERVER_STATE_IDLE; + break; + case DHCP_OPTION_CODE_END: + break; + } + } + + /* free the UDP connection, so we can accept new clients */ + udp_disconnect(udp_pcb); + + /* Free the packet buffer */ + if (merged_packet_buffer != NULL) + pbuf_free(merged_packet_buffer); + else + pbuf_free(udp_packet_buffer); +} + +void dhcps_set_addr_pool(int addr_pool_set, struct ip_addr * addr_pool_start, struct ip_addr *addr_pool_end) +{ + if(addr_pool_set){ + dhcps_addr_pool_set = 1; + + memcpy(&dhcps_addr_pool_start, addr_pool_start, + sizeof(struct ip_addr)); + + memcpy(&dhcps_addr_pool_end, addr_pool_end, + sizeof(struct ip_addr)); + }else{ + dhcps_addr_pool_set = 0; + } +} +/** + * @brief Initialize dhcp server. + * @param None. + * @retval None. + * Note, for now,we assume the server latch ip 192.168.1.1 and support dynamic + * or fixed IP allocation. + */ +void dhcps_init(struct netif * pnetif) +{ +// printf("dhcps_init,wlan:%c\n\r",pnetif->name[1]); + + dhcps_netif = pnetif; + + if (dhcps_pcb != NULL) { + udp_remove(dhcps_pcb); + dhcps_pcb = NULL; + } + + dhcps_pcb = udp_new(); + IP4_ADDR(&dhcps_send_broadcast_address, 255, 255, 255, 255); + /* get net info from net interface */ + + memcpy(&dhcps_local_address, &pnetif->ip_addr, + sizeof(struct ip_addr)); + memcpy(&dhcps_local_mask, &pnetif->netmask, + sizeof(struct ip_addr)); + + memcpy(&dhcps_local_gateway, &pnetif->gw, + sizeof(struct ip_addr)); + + /* calculate the usable network ip range */ + dhcps_network_id.addr = ((pnetif->ip_addr.addr) & + (pnetif->netmask.addr)); + + dhcps_subnet_broadcast.addr = ((dhcps_network_id.addr | + ~(pnetif->netmask.addr))); +#if 0 + dhcps_owned_first_ip.addr = htonl((ntohl(dhcps_network_id.addr) + 1)); + dhcps_owned_last_ip.addr = htonl(ntohl(dhcps_subnet_broadcast.addr) - 1); + dhcps_num_of_available_ips = ((ntohl(dhcps_owned_last_ip.addr) + - ntohl(dhcps_owned_first_ip.addr)) + 1); +#endif + +#if IS_USE_FIXED_IP + IP4_ADDR(&dhcps_allocated_client_address, ip4_addr1(&dhcps_local_address) + , ip4_addr2(&dhcps_local_address), ip4_addr3(&dhcps_local_address), + (ip4_addr4(&dhcps_local_address)) + 1 ); +#else + if (dhcps_ip_table_semaphore != NULL) { + vSemaphoreDelete(dhcps_ip_table_semaphore); + dhcps_ip_table_semaphore = NULL; + } + dhcps_ip_table_semaphore = xSemaphoreCreateMutex(); + + //dhcps_ip_table = (struct ip_table *)(pvPortMalloc(sizeof(struct ip_table))); + memset(&ip_table, 0, sizeof(struct table)); + memset(&dhcps_allocated_client_address, 0, sizeof(struct ip_addr)); + memset(bound_client_ethernet_address, 0, sizeof(bound_client_ethernet_address)); + mark_ip_in_table((uint8_t)ip4_addr4(&dhcps_local_address)); + mark_ip_in_table((uint8_t)ip4_addr4(&dhcps_local_gateway)); +#if 0 + for (i = 1; i < ip4_addr4(&dhcps_local_address); i++) { + mark_ip_in_table(i); + } +#endif +#endif + udp_bind(dhcps_pcb, IP_ADDR_ANY, DHCP_SERVER_PORT); + udp_recv(dhcps_pcb, dhcps_receive_udp_packet_handler, NULL); +} + +void dhcps_deinit(void) +{ + if (dhcps_pcb != NULL) { + udp_remove(dhcps_pcb); + dhcps_pcb = NULL; + } + if (dhcps_ip_table_semaphore != NULL) { + vSemaphoreDelete(dhcps_ip_table_semaphore); + dhcps_ip_table_semaphore = NULL; + } +} diff --git a/component/common/network/dhcp/dhcps.h b/component/common/network/dhcp/dhcps.h new file mode 100644 index 0000000..e3253f9 --- /dev/null +++ b/component/common/network/dhcp/dhcps.h @@ -0,0 +1,123 @@ + +#ifndef __DHCPS_H__ +#define __DHCPS_H__ + +#include "lwip/arch.h" +#include "lwip/netif.h" +#include "lwip/udp.h" +#include "lwip/stats.h" +#include "lwip/sys.h" + +#include + + +#define IS_USE_FIXED_IP 0 +#define debug_dhcps 0 + +/* dhcp server states */ +#define DHCP_SERVER_STATE_OFFER (1) +#define DHCP_SERVER_STATE_DECLINE (2) +#define DHCP_SERVER_STATE_ACK (3) +#define DHCP_SERVER_STATE_NAK (4) +#define DHCP_SERVER_STATE_IDLE (5) + + +#define BOOTP_BROADCAST (0x8000) + +#define DHCP_MESSAGE_OP_REQUEST (1) +#define DHCP_MESSAGE_OP_REPLY (2) + +#define DHCP_MESSAGE_HTYPE (1) +#define DHCP_MESSAGE_HLEN (6) + +#define DHCP_SERVER_PORT (67) +#define DHCP_CLIENT_PORT (68) + +#define DHCP_MESSAGE_TYPE_DISCOVER (1) +#define DHCP_MESSAGE_TYPE_OFFER (2) +#define DHCP_MESSAGE_TYPE_REQUEST (3) +#define DHCP_MESSAGE_TYPE_DECLINE (4) +#define DHCP_MESSAGE_TYPE_ACK (5) +#define DHCP_MESSAGE_TYPE_NAK (6) +#define DHCP_MESSAGE_TYPE_RELEASE (7) + +#define DHCP_OPTION_LENGTH_ONE (1) +#define DHCP_OPTION_LENGTH_TWO (2) +#define DHCP_OPTION_LENGTH_THREE (3) +#define DHCP_OPTION_LENGTH_FOUR (4) + +#define DHCP_OPTION_CODE_SUBNET_MASK (1) +#define DHCP_OPTION_CODE_ROUTER (3) +#define DHCP_OPTION_CODE_DNS_SERVER (6) +#define DHCP_OPTION_CODE_INTERFACE_MTU (26) +#define DHCP_OPTION_CODE_BROADCAST_ADDRESS (28) +#define DHCP_OPTION_CODE_PERFORM_ROUTER_DISCOVERY (31) +#define DHCP_OPTION_CODE_REQUEST_IP_ADDRESS (50) +#define DHCP_OPTION_CODE_LEASE_TIME (51) +#define DHCP_OPTION_CODE_MSG_TYPE (53) +#define DHCP_OPTION_CODE_SERVER_ID (54) +#define DHCP_OPTION_CODE_REQ_LIST (55) +#define DHCP_OPTION_CODE_END (255) + +#define IP_FREE_TO_USE (1) +#define IP_ALREADY_IN_USE (0) + +#define HW_ADDRESS_LENGTH (6) + +/* Reference by RFC 2131 */ +struct dhcp_msg { + uint8_t op; /* Message op code/message type. 1 = BOOTREQUEST, 2 = BOOTREPLY */ + uint8_t htype; /* Hardware address type */ + uint8_t hlen; /* Hardware address length */ + uint8_t hops; /* Client sets to zero, optionally used by relay agents + when booting via a relay agent */ + uint8_t xid[4]; /* Transaction ID, a random number chosen by the client, + used by the client and server to associate messages and + responses between a client and a server */ + uint16_t secs; /* Filled in by client, seconds elapsed since client began address + acquisition or renewal process.*/ + uint16_t flags; /* bit 0: Broadcast flag, bit 1~15:MBZ must 0*/ + uint8_t ciaddr[4]; /* Client IP address; only filled in if client is in BOUND, + RENEW or REBINDING state and can respond to ARP requests. */ + 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]; /* Relay agent IP address, used in booting via a relay agent.*/ + uint8_t chaddr[16]; /* Client hardware address */ + uint8_t sname[64]; /* Optional server host name, null terminated string.*/ + uint8_t file[128]; /* Boot file name, null terminated string; "generic" name or + null in DHCPDISCOVER, fully qualified directory-path name in DHCPOFFER.*/ + uint8_t options[312]; /* Optional parameters field. reference the RFC 2132 */ +}; + +/* use this to check whether the message is dhcp related or not */ +static const uint8_t dhcp_magic_cookie[4] = {99, 130, 83, 99}; +static const uint8_t dhcp_option_lease_time_one_day[] = {0x00, 0x01, 0x51, 0x80}; +static const uint8_t dhcp_option_interface_mtu_576[] = {0x02, 0x40}; + +struct table { + uint32_t ip_range[4]; +}; + +struct address_pool{ + uint32_t start; + uint32_t end; +}; + +/* 01~32 */ +#define MARK_RANGE1_IP_BIT(table, ip) ((table.ip_range[0]) | (1 << ((ip) - 1))) +/* 33~64 */ +#define MARK_RANGE2_IP_BIT(table, ip) ((table.ip_range[1]) | (1 << ((ip) - 1))) +/* 65~96 */ +#define MARK_RANGE3_IP_BIT(table, ip) ((table.ip_range[2]) | (1 << ((ip) - 1))) +/* 97~128 */ +#define MARK_RANGE4_IP_BIT(table, ip) ((table.ip_range[3]) | (1 << ((ip) - 1))) + +/* expose API */ +void dhcps_set_addr_pool(int addr_pool_set, struct ip_addr * addr_pool_start, struct ip_addr *addr_pool_end); +void dhcps_init(struct netif * pnetif); +void dhcps_deinit(void); + +extern struct netif *netif_default; + +#endif diff --git a/component/common/network/lwip/lwip_v1.3.2/CHANGELOG b/component/common/network/lwip/lwip_v1.3.2/CHANGELOG new file mode 100644 index 0000000..860d1c4 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/CHANGELOG @@ -0,0 +1,2419 @@ +FUTURE + + * TODO: The lwIP source code makes some invalid assumptions on processor + word-length, storage sizes and alignment. See the mailing lists for + problems with exoteric (/DSP) architectures showing these problems. + We still have to fix some of these issues neatly. + + * TODO: the PPP code is broken in a few ways. There are namespace + collisions on BSD systems and many assumptions on word-length + (sizeof(int)). In ppp.c an assumption is made on the availability of + a thread subsystem. Either PPP needs to be moved to contrib/ports/??? + or rearranged to be more generic. + +HISTORY + +(CVS HEAD) + + * [Enter new changes just after this line - do not remove this line] + + ++ New features: + + + ++ Bugfixes: + + +(STABLE-1.3.2) + + ++ New features: + + 2009-10-27 Simon Goldschmidt/Stephan Lesage + * netifapi.c/.h: Added netifapi_netif_set_addr() + + 2009-10-07 Simon Goldschmidt/Fabian Koch + * api_msg.c, netbuf.c/.h, opt.h: patch #6888: Patch for UDP Netbufs to + support dest-addr and dest-port (optional: LWIP_NETBUF_RECVINFO) + + 2009-08-26 Simon Goldschmidt/Simon Kallweit + * slipif.c/.h: bug #26397: SLIP polling support + + 2009-08-25 Simon Goldschmidt + * opt.h, etharp.h/.c: task #9033: Support IEEE 802.1q tagged frame (VLAN), + New configuration options ETHARP_SUPPORT_VLAN and ETHARP_VLAN_CHECK. + + 2009-08-25 Simon Goldschmidt + * ip_addr.h, netdb.c: patch #6900: added define ip_ntoa(struct ip_addr*) + + 2009-08-24 Jakob Stoklund Olesen + * autoip.c, dhcp.c, netif.c: patch #6725: Teach AutoIP and DHCP to respond + to netif_set_link_up(). + + 2009-08-23 Simon Goldschmidt + * tcp.h/.c: Added function tcp_debug_state_str() to convert a tcp state + to a human-readable string. + + ++ Bugfixes: + + 2009-12-24: Kieran Mansley + * tcp_in.c Apply patches from Oleg Tyshev to improve OOS processing + (BUG#28241) + + 2009-12-06: Simon Goldschmidt + * ppp.h/.c: Fixed bug #27079 (Yet another leak in PPP): outpacket_buf can + be statically allocated (like in ucip) + + 2009-12-04: Simon Goldschmidt (patch by Ioardan Neshev) + * pap.c: patch #6969: PPP: missing PAP authentication UNTIMEOUT + + 2009-12-03: Simon Goldschmidt + * tcp.h, tcp_in.c, tcp_out.c: Fixed bug #28106: dup ack for fast retransmit + could have non-zero length + + 2009-12-02: Simon Goldschmidt + * tcp_in.c: Fixed bug #27904: TCP sends too many ACKs: delay resetting + tcp_input_pcb until after calling the pcb's callbacks + + 2009-11-29: Simon Goldschmidt + * tcp_in.c: Fixed bug #28054: Two segments with FIN flag on the out-of- + sequence queue, also fixed PBUF_POOL leak in the out-of-sequence code + + 2009-11-29: Simon Goldschmidt + * pbuf.c: Fixed bug #28064: pbuf_alloc(PBUF_POOL) is not thread-safe by + queueing a call into tcpip_thread to free ooseq-bufs if the pool is empty + + 2009-11-26: Simon Goldschmidt + * tcp.h: Fixed bug #28098: Nagle can prevent fast retransmit from sending + segment + + 2009-11-26: Simon Goldschmidt + * tcp.h, sockets.c: Fixed bug #28099: API required to disable Nagle + algorithm at PCB level + + 2009-11-22: Simon Goldschmidt + * tcp_out.c: Fixed bug #27905: FIN isn't combined with data on unsent + + 2009-11-22: Simon Goldschmidt (suggested by Bill Auerbach) + * tcp.c: tcp_alloc: prevent increasing stats.err for MEMP_TCP_PCB when + reusing time-wait pcb + + 2009-11-20: Simon Goldschmidt (patch by Albert Bartel) + * sockets.c: Fixed bug #28062: Data received directly after accepting + does not wake up select + + 2009-11-11: Simon Goldschmidt + * netdb.h: Fixed bug #27994: incorrect define for freeaddrinfo(addrinfo) + + 2009-10-30: Simon Goldschmidt + * opt.h: Increased default value for TCP_MSS to 536, updated default + value for TCP_WND to 4*TCP_MSS to keep delayed ACK working. + + 2009-10-28: Kieran Mansley + * tcp_in.c, tcp_out.c, tcp.h: re-work the fast retransmission code + to follow algorithm from TCP/IP Illustrated + + 2009-10-27: Kieran Mansley + * tcp_in.c: fix BUG#27445: grow cwnd with every duplicate ACK + + 2009-10-25: Simon Goldschmidt + * tcp.h: bug-fix in the TCP_EVENT_RECV macro (has to call tcp_recved if + pcb->recv is NULL to keep rcv_wnd correct) + + 2009-10-25: Simon Goldschmidt + * tcp_in.c: Fixed bug #26251: RST process in TIME_WAIT TCP state + + 2009-10-23: Simon Goldschmidt (David Empson) + * tcp.c: Fixed bug #27783: Silly window avoidance for small window sizes + + 2009-10-21: Simon Goldschmidt + * tcp_in.c: Fixed bug #27215: TCP sent() callback gives leading and + trailing 1 byte len (SYN/FIN) + + 2009-10-21: Simon Goldschmidt + * tcp_out.c: Fixed bug #27315: zero window probe and FIN + + 2009-10-19: Simon Goldschmidt + * dhcp.c/.h: Minor code simplification (don't store received pbuf, change + conditional code to assert where applicable), check pbuf length before + testing for valid reply + + 2009-10-19: Simon Goldschmidt + * dhcp.c: Removed most calls to udp_connect since they aren't necessary + when using udp_sendto_if() - always stay connected to IP_ADDR_ANY. + + 2009-10-16: Simon Goldschmidt + * ip.c: Fixed bug #27390: Source IP check in ip_input() causes it to drop + valid DHCP packets -> allow 0.0.0.0 as source address when LWIP_DHCP is + enabled + + 2009-10-15: Simon Goldschmidt (Oleg Tyshev) + * tcp_in.c: Fixed bug #27329: dupacks by unidirectional data transmit + + 2009-10-15: Simon Goldschmidt + * api_lib.c: Fixed bug #27709: conn->err race condition on netconn_recv() + timeout + + 2009-10-15: Simon Goldschmidt + * autoip.c: Fixed bug #27704: autoip starts with wrong address + LWIP_AUTOIP_CREATE_SEED_ADDR() returned address in host byte order instead + of network byte order + + 2009-10-11 Simon Goldschmidt (Jörg Kesten) + * tcp_out.c: Fixed bug #27504: tcp_enqueue wrongly concatenates segments + which are not consecutive when retransmitting unacked segments + + 2009-10-09 Simon Goldschmidt + * opt.h: Fixed default values of some stats to only be enabled if used + Fixes bug #27338: sys_stats is defined when NO_SYS = 1 + + 2009-08-30 Simon Goldschmidt + * ip.c: Fixed bug bug #27345: "ip_frag() does not use the LWIP_NETIF_LOOPBACK + function" by checking for loopback before calling ip_frag + + 2009-08-25 Simon Goldschmidt + * dhcp.c: fixed invalid dependency to etharp_query if DHCP_DOES_ARP_CHECK==0 + + 2009-08-23 Simon Goldschmidt + * ppp.c: bug #27078: Possible memory leak in pppInit() + + 2009-08-23 Simon Goldschmidt + * netdb.c, dns.c: bug #26657: DNS, if host name is "localhost", result + is error. + + 2009-08-23 Simon Goldschmidt + * opt.h, init.c: bug #26649: TCP fails when TCP_MSS > TCP_SND_BUF + Fixed wrong parenthesis, added check in init.c + + 2009-08-23 Simon Goldschmidt + * ppp.c: bug #27266: wait-state debug message in pppMain occurs every ms + + 2009-08-23 Simon Goldschmidt + * many ppp files: bug #27267: Added include to string.h where needed + + 2009-08-23 Simon Goldschmidt + * tcp.h: patch #6843: tcp.h macro optimization patch (for little endian) + + +(STABLE-1.3.1) + + ++ New features: + + 2009-05-10 Simon Goldschmidt + * opt.h, sockets.c, pbuf.c, netbuf.h, pbuf.h: task #7013: Added option + LWIP_NETIF_TX_SINGLE_PBUF to try to create transmit packets from only + one pbuf to help MACs that don't support scatter-gather DMA. + + 2009-05-09 Simon Goldschmidt + * icmp.h, icmp.c: Shrinked ICMP code, added option to NOT check icoming + ECHO pbuf for size (just use it): LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN + + 2009-05-05 Simon Goldschmidt, Jakob Stoklund Olesen + * ip.h, ip.c: Added ip_current_netif() & ip_current_header() to receive + extended info about the currently received packet. + + 2009-04-27 Simon Goldschmidt + * sys.h: Made SYS_LIGHTWEIGHT_PROT and sys_now() work with NO_SYS=1 + + 2009-04-25 Simon Goldschmidt + * mem.c, opt.h: Added option MEM_USE_POOLS_TRY_BIGGER_POOL to try the next + bigger malloc pool if one is empty (only usable with MEM_USE_POOLS). + + 2009-04-21 Simon Goldschmidt + * dns.c, init.c, dns.h, opt.h: task #7507, patch #6786: DNS supports static + hosts table. New configuration options DNS_LOCAL_HOSTLIST and + DNS_LOCAL_HOSTLIST_IS_DYNAMIC. Also, DNS_LOOKUP_LOCAL_EXTERN() can be defined + as an external function for lookup. + + 2009-04-15 Simon Goldschmidt + * dhcp.c: patch #6763: Global DHCP XID can be redefined to something more unique + + 2009-03-31 Kieran Mansley + * tcp.c, tcp_out.c, tcp_in.c, sys.h, tcp.h, opts.h: add support for + TCP timestamp options, off by default. Rework tcp_enqueue() to + take option flags rather than specified option data + + 2009-02-18 Simon Goldschmidt + * cc.h: Added printf formatter for size_t: SZT_F + + 2009-02-16 Simon Goldschmidt (patch by Rishi Khan) + * icmp.c, opt.h: patch #6539: (configurable) response to broadcast- and multicast + pings + + 2009-02-12 Simon Goldschmidt + * init.h: Added LWIP_VERSION to get the current version of the stack + + 2009-02-11 Simon Goldschmidt (suggested by Gottfried Spitaler) + * opt.h, memp.h/.c: added MEMP_MEM_MALLOC to use mem_malloc/mem_free instead + of the pool allocator (can save code size with MEM_LIBC_MALLOC if libc-malloc + is otherwise used) + + 2009-01-28 Jonathan Larmour (suggested by Bill Bauerbach) + * ipv4/inet_chksum.c, ipv4/lwip/inet_chksum.h: inet_chksum_pseudo_partial() + is only used by UDPLITE at present, so conditionalise it. + + 2008-12-03 Simon Goldschmidt (base on patch from Luca Ceresoli) + * autoip.c: checked in (slightly modified) patch #6683: Customizable AUTOIP + "seed" address. This should reduce AUTOIP conflicts if + LWIP_AUTOIP_CREATE_SEED_ADDR is overridden. + + 2008-10-02 Jonathan Larmour and Rishi Khan + * sockets.c (lwip_accept): Return EWOULDBLOCK if would block on non-blocking + socket. + + 2008-06-30 Simon Goldschmidt + * mem.c, opt.h, stats.h: fixed bug #21433: Calling mem_free/pbuf_free from + interrupt context isn't safe: LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT allows + mem_free to run between mem_malloc iterations. Added illegal counter for + mem stats. + + 2008-06-27 Simon Goldschmidt + * stats.h/.c, some other files: patch #6483: stats module improvement: + Added defines to display each module's statistic individually, added stats + defines for MEM, MEMP and SYS modules, removed (unused) rexmit counter. + + 2008-06-17 Simon Goldschmidt + * err.h: patch #6459: Made err_t overridable to use a more efficient type + (define LWIP_ERR_T in cc.h) + + 2008-06-17 Simon Goldschmidt + * slipif.c: patch #6480: Added a configuration option for slipif for symmetry + to loopif + + 2008-06-17 Simon Goldschmidt (patch by Luca Ceresoli) + * netif.c, loopif.c, ip.c, netif.h, loopif.h, opt.h: Checked in slightly + modified version of patch # 6370: Moved loopif code to netif.c so that + loopback traffic is supported on all netifs (all local IPs). + Added option to limit loopback packets for each netifs. + + + ++ Bugfixes: + 2009-08-12 Kieran Mansley + * tcp_in.c, tcp.c: Fix bug #27209: handle trimming of segments when + out of window or out of order properly + + 2009-08-12 Kieran Mansley + * tcp_in.c: Fix bug #27199: use snd_wl2 instead of snd_wl1 + + 2009-07-28 Simon Goldschmidt + * mem.h: Fixed bug #27105: "realloc() cannot replace mem_realloc()"s + + 2009-07-27 Kieran Mansley + * api.h api_msg.h netdb.h sockets.h: add missing #include directives + + 2009-07-09 Kieran Mansley + * api_msg.c, sockets.c, api.h: BUG23240 use signed counters for + recv_avail and don't increment counters until message successfully + sent to mbox + + 2009-06-25 Kieran Mansley + * api_msg.c api.h: BUG26722: initialise netconn write variables + in netconn_alloc + + 2009-06-25 Kieran Mansley + * tcp.h: BUG26879: set ret value in TCP_EVENT macros when function is not set + + 2009-06-25 Kieran Mansley + * tcp.c, tcp_in.c, tcp_out.c, tcp.h: BUG26301 and BUG26267: correct + simultaneous close behaviour, and make snd_nxt have the same meaning + as in the RFCs. + + 2009-05-12 Simon Goldschmidt + * etharp.h, etharp.c, netif.c: fixed bug #26507: "Gratuitous ARP depends on + arp_table / uses etharp_query" by adding etharp_gratuitous() + + 2009-05-12 Simon Goldschmidt + * ip.h, ip.c, igmp.c: bug #26487: Added ip_output_if_opt that can add IP options + to the IP header (used by igmp_ip_output_if) + + 2009-05-06 Simon Goldschmidt + * inet_chksum.c: On little endian architectures, use LWIP_PLATFORM_HTONS (if + defined) for SWAP_BYTES_IN_WORD to speed up checksumming. + + 2009-05-05 Simon Goldschmidt + * sockets.c: bug #26405: Prematurely released semaphore causes lwip_select() + to crash + + 2009-05-04 Simon Goldschmidt + * init.c: snmp was not initialized in lwip_init() + + 2009-05-04 Frédéric Bernon + * dhcp.c, netbios.c: Changes if IP_SOF_BROADCAST is enabled. + + 2009-05-03 Simon Goldschmidt + * tcp.h: bug #26349: Nagle algorithm doesn't send although segment is full + (and unsent->next == NULL) + + 2009-05-02 Simon Goldschmidt + * tcpip.h, tcpip.c: fixed tcpip_untimeout (does not need the time, broken after + 1.3.0 in CVS only) - fixes compilation of ppp_oe.c + + 2009-05-02 Simon Goldschmidt + * msg_in.c: fixed bug #25636: SNMPSET value is ignored for integer fields + + 2009-05-01 Simon Goldschmidt + * pap.c: bug #21680: PPP upap_rauthnak() drops legal NAK packets + + 2009-05-01 Simon Goldschmidt + * ppp.c: bug #24228: Memory corruption with PPP and DHCP + + 2009-04-29 Frédéric Bernon + * raw.c, udp.c, init.c, opt.h, ip.h, sockets.h: bug #26309: Implement the + SO(F)_BROADCAST filter for all API layers. Avoid the unindented reception + of broadcast packets even when this option wasn't set. Port maintainers + which want to enable this filter have to set IP_SOF_BROADCAST=1 in opt.h. + If you want this option also filter broadcast on recv operations, you also + have to set IP_SOF_BROADCAST_RECV=1 in opt.h. + + 2009-04-28 Simon Goldschmidt, Jakob Stoklund Olesen + * dhcp.c: patch #6721, bugs #25575, #25576: Some small fixes to DHCP and + DHCP/AUTOIP cooperation + + 2009-04-25 Simon Goldschmidt, Oleg Tyshev + * tcp_out.c: bug #24212: Deadlocked tcp_retransmit due to exceeded pcb->cwnd + Fixed by sorting the unsent and unacked queues (segments are inserted at the + right place in tcp_output and tcp_rexmit). + + 2009-04-25 Simon Goldschmidt + * memp.c, mem.c, memp.h, mem_std.h: bug #26213 "Problem with memory allocation + when debugging": memp_sizes contained the wrong sizes (including sanity + regions); memp pools for MEM_USE_POOLS were too small + + 2009-04-24 Simon Goldschmidt, Frédéric Bernon + * inet.c: patch #6765: Fix a small problem with the last changes (incorrect + behavior, with with ip address string not ended by a '\0', a space or a + end of line) + + 2009-04-19 Simon Goldschmidt + * rawapi.txt: Fixed bug #26069: Corrected documentation: if tcp_connect fails, + pcb->err is called, not pcb->connected (with an error code). + + 2009-04-19 Simon Goldschmidt + * tcp_out.c: Fixed bug #26236: "TCP options (timestamp) don't work with + no-copy-tcpwrite": deallocate option data, only concat segments with same flags + + 2009-04-19 Simon Goldschmidt + * tcp_out.c: Fixed bug #25094: "Zero-length pbuf" (options are now allocated + in the header pbuf, not the data pbuf) + + 2009-04-18 Simon Goldschmidt + * api_msg.c: fixed bug #25695: Segmentation fault in do_writemore() + + 2009-04-15 Simon Goldschmidt + * sockets.c: tried to fix bug #23559: lwip_recvfrom problem with tcp + + 2009-04-15 Simon Goldschmidt + * dhcp.c: task #9192: mem_free of dhcp->options_in and dhcp->msg_in + + 2009-04-15 Simon Goldschmidt + * ip.c, ip6.c, tcp_out.c, ip.h: patch #6808: Add a utility function + ip_hinted_output() (for smaller code mainly) + + 2009-04-15 Simon Goldschmidt + * inet.c: patch #6765: Supporting new line characters in inet_aton() + + 2009-04-15 Simon Goldschmidt + * dhcp.c: patch #6764: DHCP rebind and renew did not send hostnam option; + Converted constant OPTION_MAX_MSG_SIZE to netif->mtu, check if netif->mtu + is big enough in dhcp_start + + 2009-04-15 Simon Goldschmidt + * netbuf.c: bug #26027: netbuf_chain resulted in pbuf memory leak + + 2009-04-15 Simon Goldschmidt + * sockets.c, ppp.c: bug #25763: corrected 4 occurrences of SMEMCPY to MEMCPY + + 2009-04-15 Simon Goldschmidt + * sockets.c: bug #26121: set_errno can be overridden + + 2009-04-09 Kieran Mansley (patch from Luca Ceresoli ) + * init.c, opt.h: Patch#6774 TCP_QUEUE_OOSEQ breaks compilation when + LWIP_TCP==0 + + 2009-04-09 Kieran Mansley (patch from Roy Lee ) + * tcp.h: Patch#6802 Add do-while-clauses to those function like + macros in tcp.h + + 2009-03-31 Kieran Mansley + * tcp.c, tcp_in.c, tcp_out.c, tcp.h, opt.h: Rework the way window + updates are calculated and sent (BUG20515) + + * tcp_in.c: cope with SYN packets received during established states, + and retransmission of initial SYN. + + * tcp_out.c: set push bit correctly when tcp segments are merged + + 2009-03-27 Kieran Mansley + * tcp_out.c set window correctly on probes (correcting change made + yesterday) + + 2009-03-26 Kieran Mansley + * tcp.c, tcp_in.c, tcp.h: add tcp_abandon() to cope with dropping + connections where no reset required (bug #25622) + + * tcp_out.c: set TCP_ACK flag on keepalive and zero window probes + (bug #20779) + + 2009-02-18 Simon Goldschmidt (Jonathan Larmour and Bill Auerbach) + * ip_frag.c: patch #6528: the buffer used for IP_FRAG_USES_STATIC_BUF could be + too small depending on MEM_ALIGNMENT + + 2009-02-16 Simon Goldschmidt + * sockets.h/.c, api_*.h/.c: fixed arguments of socket functions to match the standard; + converted size argument of netconn_write to 'size_t' + + 2009-02-16 Simon Goldschmidt + * tcp.h, tcp.c: fixed bug #24440: TCP connection close problem on 64-bit host + by moving accept callback function pointer to TCP_PCB_COMMON + + 2009-02-12 Simon Goldschmidt + * dhcp.c: fixed bug #25345 (DHCPDECLINE is sent with "Maximum message size" + option) + + 2009-02-11 Simon Goldschmidt + * dhcp.c: fixed bug #24480 (releasing old udp_pdb and pbuf in dhcp_start) + + 2009-02-11 Simon Goldschmidt + * opt.h, api_msg.c: added configurable default valud for netconn->recv_bufsize: + RECV_BUFSIZE_DEFAULT (fixes bug #23726: pbuf pool exhaustion on slow recv()) + + 2009-02-10 Simon Goldschmidt + * tcp.c: fixed bug #25467: Listen backlog is not reset on timeout in SYN_RCVD: + Accepts_pending is decrease on a corresponding listen pcb when a connection + in state SYN_RCVD is close. + + 2009-01-28 Jonathan Larmour + * pbuf.c: reclaim pbufs from TCP out-of-sequence segments if we run + out of pool pbufs. + + 2008-12-19 Simon Goldschmidt + * many files: patch #6699: fixed some warnings on platform where sizeof(int) == 2 + + 2008-12-10 Tamas Somogyi, Frédéric Bernon + * sockets.c: fixed bug #25051: lwip_recvfrom problem with udp: fromaddr and + port uses deleted netbuf. + + 2008-10-18 Simon Goldschmidt + * tcp_in.c: fixed bug ##24596: Vulnerability on faulty TCP options length + in tcp_parseopt + + 2008-10-15 Simon Goldschmidt + * ip_frag.c: fixed bug #24517: IP reassembly crashes on unaligned IP headers + by packing the struct ip_reass_helper. + + 2008-10-03 David Woodhouse, Jonathan Larmour + * etharp.c (etharp_arp_input): Fix type aliasing problem copying ip address. + + 2008-10-02 Jonathan Larmour + * dns.c: Hard-code structure sizes, to avoid issues on some compilers where + padding is included. + + 2008-09-30 Jonathan Larmour + * sockets.c (lwip_accept): check addr isn't NULL. If it's valid, do an + assertion check that addrlen isn't NULL. + + 2008-09-30 Jonathan Larmour + * tcp.c: Fix bug #24227, wrong error message in tcp_bind. + + 2008-08-26 Simon Goldschmidt + * inet.h, ip_addr.h: fixed bug #24132: Cross-dependency between ip_addr.h and + inet.h -> moved declaration of struct in_addr from ip_addr.h to inet.h + + 2008-08-14 Simon Goldschmidt + * api_msg.c: fixed bug #23847: do_close_internal references freed memory (when + tcp_close returns != ERR_OK) + + 2008-07-08 Frédéric Bernon + * stats.h: Fix some build bugs introduced with patch #6483 (missing some parameters + in macros, mainly if MEM_STATS=0 and MEMP_STATS=0). + + 2008-06-24 Jonathan Larmour + * tcp_in.c: Fix for bug #23693 as suggested by Art R. Ensure cseg is unused + if tcp_seg_copy fails. + + 2008-06-17 Simon Goldschmidt + * inet_chksum.c: Checked in some ideas of patch #6460 (loop optimizations) + and created defines for swapping bytes and folding u32 to u16. + + 2008-05-30 Kieran Mansley + * tcp_in.c Remove redundant "if" statement, and use real rcv_wnd + rather than rcv_ann_wnd when deciding if packets are in-window. + Contributed by + + 2008-05-30 Kieran Mansley + * mem.h: Fix BUG#23254. Change macro definition of mem_* to allow + passing as function pointers when MEM_LIBC_MALLOC is defined. + + 2008-05-09 Jonathan Larmour + * err.h, err.c, sockets.c: Fix bug #23119: Reorder timeout error code to + stop it being treated as a fatal error. + + 2008-04-15 Simon Goldschmidt + * dhcp.c: fixed bug #22804: dhcp_stop doesn't clear NETIF_FLAG_DHCP + (flag now cleared) + + 2008-03-27 Simon Goldschmidt + * mem.c, tcpip.c, tcpip.h, opt.h: fixed bug #21433 (Calling mem_free/pbuf_free + from interrupt context isn't safe): set LWIP_USE_HEAP_FROM_INTERRUPT to 1 + in lwipopts.h or use pbuf_free_callback(p)/mem_free_callback(m) to free pbufs + or heap memory from interrupt context + + 2008-03-26 Simon Goldschmidt + * tcp_in.c, tcp.c: fixed bug #22249: division by zero could occur if a remote + host sent a zero mss as TCP option. + + +(STABLE-1.3.0) + + ++ New features: + + 2008-03-10 Jonathan Larmour + * inet_chksum.c: Allow choice of one of the sample algorithms to be + made from lwipopts.h. Fix comment on how to override LWIP_CHKSUM. + + 2008-01-22 Frédéric Bernon + * tcp.c, tcp_in.c, tcp.h, opt.h: Rename LWIP_CALCULATE_EFF_SEND_MSS in + TCP_CALCULATE_EFF_SEND_MSS to have coherent TCP options names. + + 2008-01-14 Frédéric Bernon + * rawapi.txt, api_msg.c, tcp.c, tcp_in.c, tcp.h: changes for task #7675 "Enable + to refuse data on a TCP_EVENT_RECV call". Important, behavior changes for the + tcp_recv callback (see rawapi.txt). + + 2008-01-14 Frédéric Bernon, Marc Chaland + * ip.c: Integrate patch #6369" ip_input : checking before realloc". + + 2008-01-12 Frédéric Bernon + * tcpip.h, tcpip.c, api.h, api_lib.c, api_msg.c, sockets.c: replace the field + netconn::sem per netconn::op_completed like suggested for the task #7490 + "Add return value to sys_mbox_post". + + 2008-01-12 Frédéric Bernon + * api_msg.c, opt.h: replace DEFAULT_RECVMBOX_SIZE per DEFAULT_TCP_RECVMBOX_SIZE, + DEFAULT_UDP_RECVMBOX_SIZE and DEFAULT_RAW_RECVMBOX_SIZE (to optimize queues + sizes), like suggested for the task #7490 "Add return value to sys_mbox_post". + + 2008-01-10 Frédéric Bernon + * tcpip.h, tcpip.c: add tcpip_callback_with_block function for the task #7490 + "Add return value to sys_mbox_post". tcpip_callback is always defined as + "blocking" ("block" parameter = 1). + + 2008-01-10 Frédéric Bernon + * tcpip.h, tcpip.c, api.h, api_lib.c, api_msg.c, sockets.c: replace the field + netconn::mbox (sys_mbox_t) per netconn::sem (sys_sem_t) for the task #7490 + "Add return value to sys_mbox_post". + + 2008-01-05 Frédéric Bernon + * sys_arch.txt, api.h, api_lib.c, api_msg.h, api_msg.c, tcpip.c, sys.h, opt.h: + Introduce changes for task #7490 "Add return value to sys_mbox_post" with some + modifications in the sys_mbox api: sys_mbox_new take a "size" parameters which + indicate the number of pointers query by the mailbox. There is three defines + in opt.h to indicate sizes for tcpip::mbox, netconn::recvmbox, and for the + netconn::acceptmbox. Port maintainers, you can decide to just add this new + parameter in your implementation, but to ignore it to keep the previous behavior. + The new sys_mbox_trypost function return a value to know if the mailbox is + full or if the message is posted. Take a look to sys_arch.txt for more details. + This new function is used in tcpip_input (so, can be called in an interrupt + context since the function is not blocking), and in recv_udp and recv_raw. + + 2008-01-04 Frédéric Bernon, Simon Goldschmidt, Jonathan Larmour + * rawapi.txt, api.h, api_lib.c, api_msg.h, api_msg.c, sockets.c, tcp.h, tcp.c, + tcp_in.c, init.c, opt.h: rename backlog options with TCP_ prefix, limit the + "backlog" parameter in an u8_t, 0 is interpreted as "smallest queue", add + documentation in the rawapi.txt file. + + 2007-12-31 Kieran Mansley (based on patch from Per-Henrik Lundbolm) + * tcp.c, tcp_in.c, tcp_out.c, tcp.h: Add TCP persist timer + + 2007-12-31 Frédéric Bernon, Luca Ceresoli + * autoip.c, etharp.c: ip_addr.h: Integrate patch #6348: "Broadcast ARP packets + in autoip". The change in etharp_raw could be removed, since all calls to + etharp_raw use ethbroadcast for the "ethdst_addr" parameter. But it could be + wrong in the future. + + 2007-12-30 Frédéric Bernon, Tom Evans + * ip.c: Fix bug #21846 "LwIP doesn't appear to perform any IP Source Address + Filtering" reported by Tom Evans. + + 2007-12-21 Frédéric Bernon, Simon Goldschmidt, Jonathan Larmour + * tcp.h, opt.h, api.h, api_msg.h, tcp.c, tcp_in.c, api_lib.c, api_msg.c, + sockets.c, init.c: task #7252: Implement TCP listen backlog: Warning: raw API + applications have to call 'tcp_accepted(pcb)' in their accept callback to + keep accepting new connections. + + 2007-12-13 Frédéric Bernon + * api_msg.c, err.h, err.c, sockets.c, dns.c, dns.h: replace "enum dns_result" + by err_t type. Add a new err_t code "ERR_INPROGRESS". + + 2007-12-12 Frédéric Bernon + * dns.h, dns.c, opt.h: move DNS options to the "right" place. Most visibles + are the one which have ram usage. + + 2007-12-05 Frédéric Bernon + * netdb.c: add a LWIP_DNS_API_HOSTENT_STORAGE option to decide to use a static + set of variables (=0) or a local one (=1). In this last case, your port should + provide a function "struct hostent* sys_thread_hostent( struct hostent* h)" + which have to do a copy of "h" and return a pointer ont the "per-thread" copy. + + 2007-12-03 Simon Goldschmidt + * ip.c: ip_input: check if a packet is for inp first before checking all other + netifs on netif_list (speeds up packet receiving in most cases) + + 2007-11-30 Simon Goldschmidt + * udp.c, raw.c: task #7497: Sort lists (pcb, netif, ...) for faster access + UDP: move a (connected) pcb selected for input to the front of the list of + pcbs so that it is found faster next time. Same for RAW pcbs that have eaten + a packet. + + 2007-11-28 Simon Goldschmidt + * etharp.c, stats.c, stats.h, opt.h: Introduced ETHARP_STATS + + 2007-11-25 Simon Goldschmidt + * dhcp.c: dhcp_unfold_reply() uses pbuf_copy_partial instead of its own copy + algorithm. + + 2007-11-24 Simon Goldschmidt + * netdb.h, netdb.c, sockets.h/.c: Moved lwip_gethostbyname from sockets.c + to the new file netdb.c; included lwip_getaddrinfo. + + 2007-11-21 Simon Goldschmidt + * tcp.h, opt.h, tcp.c, tcp_in.c: implemented calculating the effective send-mss + based on the MTU of the netif used to send. Enabled by default. Disable by + setting LWIP_CALCULATE_EFF_SEND_MSS to 0. This fixes bug #21492. + + 2007-11-19 Frédéric Bernon + * api_msg.c, dns.h, dns.c: Implement DNS_DOES_NAME_CHECK option (check if name + received match the name query), implement DNS_USES_STATIC_BUF (the place where + copy dns payload to parse the response), return an error if there is no place + for a new query, and fix some minor problems. + + 2007-11-16 Simon Goldschmidt + * new files: ipv4/inet.c, ipv4/inet_chksum.c, ipv6/inet6.c + removed files: core/inet.c, core/inet6.c + Moved inet files into ipv4/ipv6 directory; splitted inet.c/inet.h into + inet and chksum part; changed includes in all lwIP files as appropriate + + 2007-11-16 Simon Goldschmidt + * api.h, api_msg.h, api_lib.c, api_msg.c, socket.h, socket.c: Added sequential + dns resolver function for netconn api (netconn_gethostbyname) and socket api + (gethostbyname/gethostbyname_r). + + 2007-11-15 Jim Pettinato, Frédéric Bernon + * opt.h, init.c, tcpip.c, dhcp.c, dns.h, dns.c: add DNS client for simple name + requests with RAW api interface. Initialization is done in lwip_init() with + build time options. DNS timer is added in tcpip_thread context. DHCP can set + DNS server ip addresses when options are received. You need to set LWIP_DNS=1 + in your lwipopts.h file (LWIP_DNS=0 in opt.h). DNS_DEBUG can be set to get + some traces with LWIP_DEBUGF. Sanity check have been added. There is a "todo" + list with points to improve. + + 2007-11-06 Simon Goldschmidt + * opt.h, mib2.c: Patch #6215: added ifAdminStatus write support (if explicitly + enabled by defining SNMP_SAFE_REQUESTS to 0); added code to check link status + for ifOperStatus if LWIP_NETIF_LINK_CALLBACK is defined. + + 2007-11-06 Simon Goldschmidt + * api.h, api_msg.h and dependent files: Task #7410: Removed the need to include + core header files in api.h (ip/tcp/udp/raw.h) to hide the internal + implementation from netconn api applications. + + 2007-11-03 Frédéric Bernon + * api.h, api_lib.c, api_msg.c, sockets.c, opt.h: add SO_RCVBUF option for UDP & + RAW netconn. You need to set LWIP_SO_RCVBUF=1 in your lwipopts.h (it's disabled + by default). Netconn API users can use the netconn_recv_bufsize macro to access + it. This is a first release which have to be improve for TCP. Note it used the + netconn::recv_avail which need to be more "thread-safe" (note there is already + the problem for FIONREAD with lwip_ioctl/ioctlsocket). + + 2007-11-01 Frédéric Bernon, Marc Chaland + * sockets.h, sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c, tcp.h, tcp_out.c: + Integrate "patch #6250 : MSG_MORE flag for send". MSG_MORE is used at socket api + layer, NETCONN_MORE at netconn api layer, and TCP_WRITE_FLAG_MORE at raw api + layer. This option enable to delayed TCP PUSH flag on multiple "write" calls. + Note that previous "copy" parameter for "write" APIs is now called "apiflags". + + 2007-10-24 Frédéric Bernon + * api.h, api_lib.c, api_msg.c: Add macro API_EVENT in the same spirit than + TCP_EVENT_xxx macros to get a code more readable. It could also help to remove + some code (like we have talk in "patch #5919 : Create compile switch to remove + select code"), but it could be done later. + + 2007-10-08 Simon Goldschmidt + * many files: Changed initialization: many init functions are not needed any + more since we now rely on the compiler initializing global and static + variables to zero! + + 2007-10-06 Simon Goldschmidt + * ip_frag.c, memp.c, mib2.c, ip_frag.h, memp_std.h, opt.h: Changed IP_REASSEMBLY + to enqueue the received pbufs so that multiple packets can be reassembled + simultaneously and no static reassembly buffer is needed. + + 2007-10-05 Simon Goldschmidt + * tcpip.c, etharp.h, etharp.c: moved ethernet_input from tcpip.c to etharp.c so + all netifs (or ports) can use it. + + 2007-10-05 Frédéric Bernon + * netifapi.h, netifapi.c: add function netifapi_netif_set_default. Change the + common function to reduce a little bit the footprint (for all functions using + only the "netif" parameter). + + 2007-10-03 Frédéric Bernon + * netifapi.h, netifapi.c: add functions netifapi_netif_set_up, netifapi_netif_set_down, + netifapi_autoip_start and netifapi_autoip_stop. Use a common function to reduce + a little bit the footprint (for all functions using only the "netif" parameter). + + 2007-09-15 Frédéric Bernon + * udp.h, udp.c, sockets.c: Changes for "#20503 IGMP Improvement". Add IP_MULTICAST_IF + option in socket API, and a new field "multicast_ip" in "struct udp_pcb" (for + netconn and raw API users), only if LWIP_IGMP=1. Add getsockopt processing for + IP_MULTICAST_TTL and IP_MULTICAST_IF. + + 2007-09-10 Frédéric Bernon + * snmp.h, mib2.c: enable to remove SNMP timer (which consumne several cycles + even when it's not necessary). snmp_agent.txt tell to call snmp_inc_sysuptime() + each 10ms (but, it's intrusive if you use sys_timeout feature). Now, you can + decide to call snmp_add_sysuptime(100) each 1000ms (which is bigger "step", but + call to a lower frequency). Or, you can decide to not call snmp_inc_sysuptime() + or snmp_add_sysuptime(), and to define the SNMP_GET_SYSUPTIME(sysuptime) macro. + This one is undefined by default in mib2.c. SNMP_GET_SYSUPTIME is called inside + snmp_get_sysuptime(u32_t *value), and enable to change "sysuptime" value only + when it's queried (any direct call to "sysuptime" is changed by a call to + snmp_get_sysuptime). + + 2007-09-09 Frédéric Bernon, Bill Florac + * igmp.h, igmp.c, netif.h, netif.c, ip.c: To enable to have interfaces with IGMP, + and others without it, there is a new NETIF_FLAG_IGMP flag to set in netif->flags + if you want IGMP on an interface. igmp_stop() is now called inside netif_remove(). + igmp_report_groups() is now called inside netif_set_link_up() (need to have + LWIP_NETIF_LINK_CALLBACK=1) to resend reports once the link is up (avoid to wait + the next query message to receive the matching multicast streams). + + 2007-09-08 Frédéric Bernon + * sockets.c, ip.h, api.h, tcp.h: declare a "struct ip_pcb" which only contains + IP_PCB. Add in the netconn's "pcb" union a "struct ip_pcb *ip;" (no size change). + Use this new field to access to common pcb fields (ttl, tos, so_options, etc...). + Enable to access to these fields with LWIP_TCP=0. + + 2007-09-05 Frédéric Bernon + * udp.c, ipv4/icmp.c, ipv4/ip.c, ipv6/icmp.c, ipv6/ip6.c, ipv4/icmp.h, + ipv6/icmp.h, opt.h: Integrate "task #7272 : LWIP_ICMP option". The new option + LWIP_ICMP enable/disable ICMP module inside the IP stack (enable per default). + Be careful, disabling ICMP make your product non-compliant to RFC1122, but + help to reduce footprint, and to reduce "visibility" on the Internet. + + 2007-09-05 Frédéric Bernon, Bill Florac + * opt.h, sys.h, tcpip.c, slipif.c, ppp.c, sys_arch.txt: Change parameters list + for sys_thread_new (see "task #7252 : Create sys_thread_new_ex()"). Two new + parameters have to be provided: a task name, and a task stack size. For this + one, since it's platform dependant, you could define the best one for you in + your lwipopts.h. For port maintainers, you can just add these new parameters + in your sys_arch.c file, and but it's not mandatory, use them in your OS + specific functions. + + 2007-09-05 Frédéric Bernon + * inet.c, autoip.c, msg_in.c, msg_out.c, init.c: Move some build time checkings + inside init.c for task #7142 "Sanity check user-configurable values". + + 2007-09-04 Frédéric Bernon, Bill Florac + * igmp.h, igmp.c, memp_std.h, memp.c, init.c, opt.h: Replace mem_malloc call by + memp_malloc, and use a new MEMP_NUM_IGMP_GROUP option (see opt.h to define the + value). It will avoid potential fragmentation problems, use a counter to know + how many times a group is used on an netif, and free it when all applications + leave it. MEMP_NUM_IGMP_GROUP got 8 as default value (and init.c got a sanity + check if LWIP_IGMP!=0). + + 2007-09-03 Frédéric Bernon + * igmp.h, igmp.c, sockets.c, api_msg.c: Changes for "#20503 IGMP Improvement". + Initialize igmp_mac_filter to NULL in netif_add (this field should be set in + the netif's "init" function). Use the "imr_interface" field (for socket layer) + and/or the "interface" field (for netconn layer), for join/leave operations. + The igmp_join/leavegroup first parameter change from a netif to an ipaddr. + This field could be a netif's ipaddr, or "any" (same meaning than ip_addr_isany). + + 2007-08-30 Frédéric Bernon + * Add netbuf.h, netbuf.c, Change api.h, api_lib.c: #7249 "Split netbuf functions + from api/api_lib". Now netbuf API is independant of netconn, and can be used + with other API (application based on raw API, or future "socket2" API). Ports + maintainers just have to add src/api/netbuf.c in their makefile/projects. + + 2007-08-30 Frédéric Bernon, Jonathan Larmour + * init.c: Add first version of lwip_sanity_check for task #7142 "Sanity check + user-configurable values". + + 2007-08-29 Frédéric Bernon + * igmp.h, igmp.c, tcpip.c, init.c, netif.c: change igmp_init and add igmp_start. + igmp_start is call inside netif_add. Now, igmp initialization is in the same + spirit than the others modules. Modify some IGMP debug traces. + + 2007-08-29 Frédéric Bernon + * Add init.h, init.c, Change opt.h, tcpip.c: Task #7213 "Add a lwip_init function" + Add lwip_init function to regroup all modules initializations, and to provide + a place to add code for task #7142 "Sanity check user-configurable values". + Ports maintainers should remove direct initializations calls from their code, + and add init.c in their makefiles. Note that lwip_init() function is called + inside tcpip_init, but can also be used by raw api users since all calls are + disabled when matching options are disabled. Also note that their is new options + in opt.h, you should configure in your lwipopts.h (they are enabled per default). + + 2007-08-26 Marc Boucher + * api_msg.c: do_close_internal(): Reset the callbacks and arg (conn) to NULL + since they can under certain circumstances be called with an invalid conn + pointer after the connection has been closed (and conn has been freed). + + 2007-08-25 Frédéric Bernon (Artem Migaev's Patch) + * netif.h, netif.c: Integrate "patch #6163 : Function to check if link layer is up". + Add a netif_is_link_up() function if LWIP_NETIF_LINK_CALLBACK option is set. + + 2007-08-22 Frédéric Bernon + * netif.h, netif.c, opt.h: Rename LWIP_NETIF_CALLBACK in LWIP_NETIF_STATUS_CALLBACK + to be coherent with new LWIP_NETIF_LINK_CALLBACK option before next release. + + 2007-08-22 Frédéric Bernon + * tcpip.h, tcpip.c, ethernetif.c, opt.h: remove options ETHARP_TCPIP_INPUT & + ETHARP_TCPIP_ETHINPUT, now, only "ethinput" code is supported, even if the + name is tcpip_input (we keep the name of 1.2.0 function). + + 2007-08-17 Jared Grubb + * memp_std.h, memp.h, memp.c, mem.c, stats.c: (Task #7136) Centralize mempool + settings into new memp_std.h and optional user file lwippools.h. This adds + more dynamic mempools, and allows the user to create an arbitrary number of + mempools for mem_malloc. + + 2007-08-16 Marc Boucher + * api_msg.c: Initialize newconn->state to NETCONN_NONE in accept_function; + otherwise it was left to NETCONN_CLOSE and sent_tcp() could prematurely + close the connection. + + 2007-08-16 Marc Boucher + * sockets.c: lwip_accept(): check netconn_peer() error return. + + 2007-08-16 Marc Boucher + * mem.c, mem.h: Added mem_calloc(). + + 2007-08-16 Marc Boucher + * tcpip.c, tcpip.h memp.c, memp.h: Added distinct memp (MEMP_TCPIP_MSG_INPKT) + for input packets to prevent floods from consuming all of MEMP_TCPIP_MSG + and starving other message types. + Renamed MEMP_TCPIP_MSG to MEMP_TCPIP_MSG_API + + 2007-08-16 Marc Boucher + * pbuf.c, pbuf.h, etharp.c, tcp_in.c, sockets.c: Split pbuf flags in pbuf + type and flgs (later renamed to flags). + Use enum pbuf_flag as pbuf_type. Renumber PBUF_FLAG_*. + Improved lwip_recvfrom(). TCP push now propagated. + + 2007-08-16 Marc Boucher + * ethernetif.c, contrib/ports/various: ethbroadcast now a shared global + provided by etharp. + + 2007-08-16 Marc Boucher + * ppp_oe.c ppp_oe.h, auth.c chap.c fsm.c lcp.c ppp.c ppp.h, + etharp.c ethernetif.c, etharp.h, opt.h tcpip.h, tcpip.c: + Added PPPoE support and various PPP improvements. + + 2007-07-25 Simon Goldschmidt + * api_lib.c, ip_frag.c, pbuf.c, api.h, pbuf.h: Introduced pbuf_copy_partial, + making netbuf_copy_partial use this function. + + 2007-07-25 Simon Goldschmidt + * tcp_in.c: Fix bug #20506: Slow start / initial congestion window starts with + 2 * mss (instead of 1 * mss previously) to comply with some newer RFCs and + other stacks. + + 2007-07-13 Jared Grubb (integrated by Frédéric Bernon) + * opt.h, netif.h, netif.c, ethernetif.c: Add new configuration option to add + a link callback in the netif struct, and functions to handle it. Be carefull + for port maintainers to add the NETIF_FLAG_LINK_UP flag (like in ethernetif.c) + if you want to be sure to be compatible with future changes... + + 2007-06-30 Frédéric Bernon + * sockets.h, sockets.c: Implement MSG_PEEK flag for recv/recvfrom functions. + + 2007-06-21 Simon Goldschmidt + * etharp.h, etharp.c: Combined etharp_request with etharp_raw for both + LWIP_AUTOIP =0 and =1 to remove redundant code. + + 2007-06-21 Simon Goldschmidt + * mem.c, memp.c, mem.h, memp.h, opt.h: task #6863: Introduced the option + MEM_USE_POOLS to use 4 pools with different sized elements instead of a + heap. This both prevents memory fragmentation and gives a higher speed + at the cost of more memory consumption. Turned off by default. + + 2007-06-21 Simon Goldschmidt + * api_lib.c, api_msg.c, api.h, api_msg.h: Converted the length argument of + netconn_write (and therefore also api_msg_msg.msg.w.len) from u16_t into + int to be able to send a bigger buffer than 64K with one time (mainly + used from lwip_send). + + 2007-06-21 Simon Goldschmidt + * tcp.h, api_msg.c: Moved the nagle algorithm from netconn_write/do_write + into a define (tcp_output_nagle) in tcp.h to provide it to raw api users, too. + + 2007-06-21 Simon Goldschmidt + * api.h, api_lib.c, api_msg.c: Fixed bug #20021: Moved sendbuf-processing in + netconn_write from api_lib.c to api_msg.c to also prevent multiple context- + changes on low memory or empty send-buffer. + + 2007-06-18 Simon Goldschmidt + * etharp.c, etharp.h: Changed etharp to use a defined hardware address length + of 6 to avoid loading netif->hwaddr_len every time (since this file is only + used for ethernet and struct eth_addr already had a defined length of 6). + + 2007-06-17 Simon Goldschmidt + * sockets.c, sockets.h: Implemented socket options SO_NO_CHECK for UDP sockets + to disable UDP checksum generation on transmit. + + 2007-06-13 Frédéric Bernon, Simon Goldschmidt + * debug.h, api_msg.c: change LWIP_ERROR to use it to check errors like invalid + pointers or parameters, and let the possibility to redefined it in cc.h. Use + this macro to check "conn" parameter in api_msg.c functions. + + 2007-06-11 Simon Goldschmidt + * sockets.c, sockets.h: Added UDP lite support for sockets + + 2007-06-10 Simon Goldschmidt + * udp.h, opt.h, api_msg.c, ip.c, udp.c: Included switch LWIP_UDPLITE (enabled + by default) to switch off UDP-Lite support if not needed (reduces udp.c code + size) + + 2007-06-09 Dominik Spies (integrated by Frédéric Bernon) + * autoip.h, autoip.c, dhcp.h, dhcp.c, netif.h, netif.c, etharp.h, etharp.c, opt.h: + AutoIP implementation available for IPv4, with new options LWIP_AUTOIP and + LWIP_DHCP_AUTOIP_COOP if you want to cooperate with DHCP. Some tips to adapt + (see TODO mark in the source code). + + 2007-06-09 Simon Goldschmidt + * etharp.h, etharp.c, ethernetif.c: Modified order of parameters for + etharp_output() to match netif->output so etharp_output() can be used + directly as netif->output to save one function call. + + 2007-06-08 Simon Goldschmidt + * netif.h, ethernetif.c, slipif.c, loopif.c: Added define + NETIF_INIT_SNMP(netif, type, speed) to initialize per-netif snmp variables, + added initialization of those to ethernetif, slipif and loopif. + + 2007-05-18 Simon Goldschmidt + * opt.h, ip_frag.c, ip_frag.h, ip.c: Added option IP_FRAG_USES_STATIC_BUF + (defaulting to off for now) that can be set to 0 to send fragmented + packets by passing PBUF_REFs down the stack. + + 2007-05-23 Frédéric Bernon + * api_lib.c: Implement SO_RCVTIMEO for accept and recv on TCP + connections, such present in patch #5959. + + 2007-05-23 Frédéric Bernon + * api.h, api_lib.c, api_msg.c, sockets.c: group the different NETCONN_UDPxxx + code in only one part... + + 2007-05-18 Simon Goldschmidt + * opt.h, memp.h, memp.c: Added option MEMP_OVERFLOW_CHECK to check for memp + elements to overflow. This is achieved by adding some bytes before and after + each pool element (increasing their size, of course), filling them with a + prominent value and checking them on freeing the element. + Set it to 2 to also check every element in every pool each time memp_malloc() + or memp_free() is called (slower but more helpful). + + 2007-05-10 Simon Goldschmidt + * opt.h, memp.h, memp.c, pbuf.c (see task #6831): use a new memp pool for + PBUF_POOL pbufs instead of the old pool implementation in pbuf.c to reduce + code size. + + 2007-05-11 Frédéric Bernon + * sockets.c, api_lib.c, api_msg.h, api_msg.c, netifapi.h, netifapi.c, tcpip.c: + Include a function pointer instead of a table index in the message to reduce + footprint. Disable some part of lwip_send and lwip_sendto if some options are + not set (LWIP_TCP, LWIP_UDP, LWIP_RAW). + + 2007-05-10 Simon Goldschmidt + * *.h (except netif/ppp/*.h): Included patch #5448: include '#ifdef __cplusplus + \ extern "C" {' in all header files. Now you can write your application using + the lwIP stack in C++ and simply #include the core files. Note I have left + out the netif/ppp/*h header files for now, since I don't know which files are + included by applications and which are for internal use only. + + 2007-05-09 Simon Goldschmidt + * opt.h, *.c/*.h: Included patch #5920: Create define to override C-library + memcpy. 2 Defines are created: MEMCPY() for normal memcpy, SMEMCPY() for + situations where some compilers might inline the copy and save a function + call. Also replaced all calls to memcpy() with calls to (S)MEMCPY(). + + 2007-05-08 Simon Goldschmidt + * mem.h: If MEM_LIBC_MALLOC==1, allow the defines (e.g. mem_malloc() -> malloc()) + to be overriden in case the C-library malloc implementation is not protected + against concurrent access. + + 2007-05-04 Simon Goldschmidt (Atte Kojo) + * etharp.c: Introduced fast one-entry-cache to speed up ARP lookup when sending + multiple packets to the same host. + + 2007-05-04 Frédéric Bernon, Jonathan Larmour + * sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c: Fix bug #19162 "lwip_sento: a possible + to corrupt remote addr/port connection state". Reduce problems "not enought memory" with + netbuf (if we receive lot of datagrams). Improve lwip_sendto (only one exchange between + sockets api and api_msg which run in tcpip_thread context). Add netconn_sento function. + Warning, if you directly access to "fromaddr" & "fromport" field from netbuf struct, + these fields are now renamed "addr" & "port". + + 2007-04-11 Jonathan Larmour + * sys.h, api_lib.c: Provide new sys_mbox_tryfetch function. Require ports to provide new + sys_arch_mbox_tryfetch function to get a message if one is there, otherwise return + with SYS_MBOX_EMPTY. sys_arch_mbox_tryfetch can be implemented as a function-like macro + by the port in sys_arch.h if desired. + + 2007-04-06 Frédéric Bernon, Simon Goldschmidt + * opt.h, tcpip.h, tcpip.c, netifapi.h, netifapi.c: New configuration option LWIP_NETIF_API + allow to use thread-safe functions to add/remove netif in list, and to start/stop dhcp + clients, using new functions from netifapi.h. Disable as default (no port change to do). + + 2007-04-05 Frédéric Bernon + * sockets.c: remplace ENOBUFS errors on alloc_socket by ENFILE to be more BSD compliant. + + 2007-04-04 Simon Goldschmidt + * arch.h, api_msg.c, dhcp.c, msg_in.c, sockets.c: Introduced #define LWIP_UNUSED_ARG(x) + use this for and architecture-independent form to tell the compiler you intentionally + are not using this variable. Can be overriden in cc.h. + + 2007-03-28 Frédéric Bernon + * opt.h, netif.h, dhcp.h, dhcp.c: New configuration option LWIP_NETIF_HOSTNAME allow to + define a hostname in netif struct (this is just a pointer, so, you can use a hardcoded + string, point on one of your's ethernetif field, or alloc a string you will free yourself). + It will be used by DHCP to register a client hostname, but can also be use when you call + snmp_set_sysname. + + 2007-03-28 Frédéric Bernon + * netif.h, netif.c: A new NETIF_FLAG_ETHARP flag is defined in netif.h, to allow to + initialize a network interface's flag with. It tell this interface is an ethernet + device, and we can use ARP with it to do a "gratuitous ARP" (RFC 3220 "IP Mobility + Support for IPv4" section 4.6) when interface is "up" with netif_set_up(). + + 2007-03-26 Frédéric Bernon, Jonathan Larmour + * opt.h, tcpip.c: New configuration option LWIP_ARP allow to disable ARP init at build + time if you only use PPP or SLIP. The default is enable. Note we don't have to call + etharp_init in your port's initilization sequence if you use tcpip.c, because this call + is done in tcpip_init function. + + 2007-03-22 Frédéric Bernon + * stats.h, stats.c, msg_in.c: Stats counters can be change to u32_t if necessary with the + new option LWIP_STATS_LARGE. If you need this option, define LWIP_STATS_LARGE to 1 in + your lwipopts.h. More, unused counters are not defined in the stats structs, and not + display by stats_display(). Note that some options (SYS_STATS and RAW_STATS) are defined + but never used. Fix msg_in.c with the correct #if test for a stat display. + + 2007-03-21 Kieran Mansley + * netif.c, netif.h: Apply patch#4197 with some changes (originator: rireland@hmgsl.com). + Provides callback on netif up/down state change. + + 2007-03-11 Frédéric Bernon, Mace Gael, Steve Reynolds + * sockets.h, sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c, igmp.h, igmp.c, + ip.c, netif.h, tcpip.c, opt.h: + New configuration option LWIP_IGMP to enable IGMP processing. Based on only one + filter per all network interfaces. Declare a new function in netif to enable to + control the MAC filter (to reduce lwIP traffic processing). + + 2007-03-11 Frédéric Bernon + * tcp.h, tcp.c, sockets.c, tcp_out.c, tcp_in.c, opt.h: Keepalive values can + be configured at run time with LWIP_TCP_KEEPALIVE, but don't change this + unless you know what you're doing (default are RFC1122 compliant). Note + that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set in seconds. + + 2007-03-08 Frédéric Bernon + * tcp.h: Keepalive values can be configured at compile time, but don't change + this unless you know what you're doing (default are RFC1122 compliant). + + 2007-03-08 Frédéric Bernon + * sockets.c, api.h, api_lib.c, tcpip.c, sys.h, sys.c, err.c, opt.h: + Implement LWIP_SO_RCVTIMEO configuration option to enable/disable SO_RCVTIMEO + on UDP sockets/netconn. + + 2007-03-08 Simon Goldschmidt + * snmp_msg.h, msg_in.c: SNMP UDP ports can be configured at compile time. + + 2007-03-06 Frédéric Bernon + * api.h, api_lib.c, sockets.h, sockets.c, tcpip.c, sys.h, sys.c, err.h: + Implement SO_RCVTIMEO on UDP sockets/netconn. + + 2007-02-28 Kieran Mansley (based on patch from Simon Goldschmidt) + * api_lib.c, tcpip.c, memp.c, memp.h: make API msg structs allocated + on the stack and remove the API msg type from memp + + 2007-02-26 Jonathan Larmour (based on patch from Simon Goldschmidt) + * sockets.h, sockets.c: Move socket initialization to new + lwip_socket_init() function. + NOTE: this changes the API with ports. Ports will have to be + updated to call lwip_socket_init() now. + + 2007-02-26 Jonathan Larmour (based on patch from Simon Goldschmidt) + * api_lib.c: Use memcpy in netbuf_copy_partial. + + + ++ Bug fixes: + + 2008-03-17 Frédéric Bernon, Ed Kerekes + * igmp.h, igmp.c: Fix bug #22613 "IGMP iphdr problem" (could have + some problems to fill the IP header on some targets, use now the + ip.h macros to do it). + + 2008-03-13 Frédéric Bernon + * sockets.c: Fix bug #22435 "lwip_recvfrom with TCP break;". Using + (lwip_)recvfrom with valid "from" and "fromlen" parameters, on a + TCP connection caused a crash. Note that using (lwip_)recvfrom + like this is a bit slow and that using (lwip)getpeername is the + good lwip way to do it (so, using recv is faster on tcp sockets). + + 2008-03-12 Frédéric Bernon, Jonathan Larmour + * api_msg.c, contrib/apps/ping.c: Fix bug #22530 "api_msg.c's + recv_raw() does not consume data", and the ping sample (with + LWIP_SOCKET=1, the code did the wrong supposition that lwip_recvfrom + returned the IP payload, without the IP header). + + 2008-03-04 Jonathan Larmour + * mem.c, stats.c, mem.h: apply patch #6414 to avoid compiler errors + and/or warnings on some systems where mem_size_t and size_t differ. + * pbuf.c, ppp.c: Fix warnings on some systems with mem_malloc. + + 2008-03-04 Kieran Mansley (contributions by others) + * Numerous small compiler error/warning fixes from contributions to + mailing list after 1.3.0 release candidate made. + + 2008-01-25 Cui hengbin (integrated by Frédéric Bernon) + * dns.c: Fix bug #22108 "DNS problem" caused by unaligned structures. + + 2008-01-15 Kieran Mansley + * tcp_out.c: BUG20511. Modify persist timer to start when we are + prevented from sending by a small send window, not just a zero + send window. + + 2008-01-09 Jonathan Larmour + * opt.h, ip.c: Rename IP_OPTIONS define to IP_OPTIONS_ALLOWED to avoid + conflict with Linux system headers. + + 2008-01-06 Jonathan Larmour + * dhcp.c: fix bug #19927: "DHCP NACK problem" by clearing any existing set IP + address entirely on receiving a DHCPNAK, and restarting discovery. + + 2007-12-21 Simon Goldschmidt + * sys.h, api_lib.c, api_msg.c, sockets.c: fix bug #21698: "netconn->recv_avail + is not protected" by using new macros for interlocked access to modify/test + netconn->recv_avail. + + 2007-12-20 Kieran Mansley (based on patch from Oleg Tyshev) + * tcp_in.c: fix bug# 21535 (nrtx not reset correctly in SYN_SENT state) + + 2007-12-20 Kieran Mansley (based on patch from Per-Henrik Lundbolm) + * tcp.c, tcp_in.c, tcp_out.c, tcp.h: fix bug #20199 (better handling + of silly window avoidance and prevent lwIP from shrinking the window) + + 2007-12-04 Simon Goldschmidt + * tcp.c, tcp_in.c: fix bug #21699 (segment leak in ooseq processing when last + data packet was lost): add assert that all segment lists are empty in + tcp_pcb_remove before setting pcb to CLOSED state; don't directly set CLOSED + state from LAST_ACK in tcp_process + + 2007-12-02 Simon Goldschmidt + * sockets.h: fix bug #21654: exclude definition of struct timeval from #ifndef FD_SET + If including for system-struct timeval, LWIP_TIMEVAL_PRIVATE now + has to be set to 0 in lwipopts.h + + 2007-12-02 Simon Goldschmidt + * api_msg.c, api_lib.c: fix bug #21656 (recvmbox problem in netconn API): always + allocate a recvmbox in netconn_new_with_proto_and_callback. For a tcp-listen + netconn, this recvmbox is later freed and a new mbox is allocated for acceptmbox. + This is a fix for thread-safety and allocates all items needed for a netconn + when the netconn is created. + + 2007-11-30 Simon Goldschmidt + * udp.c: first attempt to fix bug #21655 (DHCP doesn't work reliably with multiple + netifs): if LWIP_DHCP is enabled, UDP packets to DHCP_CLIENT_PORT are passed + to netif->dhcp->pcb only (if that exists) and not to any other pcb for the same + port (only solution to let UDP pcbs 'bind' to a netif instead of an IP address) + + 2007-11-27 Simon Goldschmidt + * ip.c: fixed bug #21643 (udp_send/raw_send don't fail if netif is down) by + letting ip_route only use netifs that are up. + + 2007-11-27 Simon Goldschmidt + * err.h, api_lib.c, api_msg.c, sockets.c: Changed error handling: ERR_MEM, ERR_BUF + and ERR_RTE are seen as non-fatal, all other errors are fatal. netconns and + sockets block most operations once they have seen a fatal error. + + 2007-11-27 Simon Goldschmidt + * udp.h, udp.c, dhcp.c: Implemented new function udp_sendto_if which takes the + netif to send as an argument (to be able to send on netifs that are down). + + 2007-11-26 Simon Goldschmidt + * tcp_in.c: Fixed bug #21582: pcb->acked accounting can be wrong when ACKs + arrive out-of-order + + 2007-11-21 Simon Goldschmidt + * tcp.h, tcp_out.c, api_msg.c: Fixed bug #20287: tcp_output_nagle sends too early + Fixed the nagle algorithm; nagle now also works for all raw API applications + and has to be explicitly disabled with 'tcp_pcb->flags |= TF_NODELAY' + + 2007-11-12 Frédéric Bernon + * sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c: Fixed bug #20900. Now, most + of the netconn_peer and netconn_addr processing is done inside tcpip_thread + context in do_getaddr. + + 2007-11-10 Simon Goldschmidt + * etharp.c: Fixed bug: assert fired when MEMP_ARP_QUEUE was empty (which can + happen any time). Now the packet simply isn't enqueued when out of memory. + + 2007-11-01 Simon Goldschmidt + * tcp.c, tcp_in.c: Fixed bug #21494: The send mss (pcb->mss) is set to 536 (or + TCP_MSS if that is smaller) as long as no MSS option is received from the + remote host. + + 2007-11-01 Simon Goldschmidt + * tcp.h, tcp.c, tcp_in.c: Fixed bug #21491: The MSS option sent (with SYN) + is now based on TCP_MSS instead of pcb->mss (on passive open now effectively + sending our configured TCP_MSS instead of the one received). + + 2007-11-01 Simon Goldschmidt + * tcp_in.c: Fixed bug #21181: On active open, the initial congestion window was + calculated based on the configured TCP_MSS, not on the MSS option received + with SYN+ACK. + + 2007-10-09 Simon Goldschmidt + * udp.c, inet.c, inet.h: Fixed UDPLite: send: Checksum was always generated too + short and also was generated wrong if checksum coverage != tot_len; + receive: checksum was calculated wrong if checksum coverage != tot_len + + 2007-10-08 Simon Goldschmidt + * mem.c: lfree was not updated in mem_realloc! + + 2007-10-07 Frédéric Bernon + * sockets.c, api.h, api_lib.c: First step to fix "bug #20900 : Potential + crash error problem with netconn_peer & netconn_addr". VERY IMPORTANT: + this change cause an API breakage for netconn_addr, since a parameter + type change. Any compiler should cause an error without any changes in + yours netconn_peer calls (so, it can't be a "silent change"). It also + reduce a little bit the footprint for socket layer (lwip_getpeername & + lwip_getsockname use now a common lwip_getaddrname function since + netconn_peer & netconn_addr have the same parameters). + + 2007-09-20 Simon Goldschmidt + * tcp.c: Fixed bug #21080 (tcp_bind without check pcbs in TIME_WAIT state) + by checking tcp_tw_pcbs also + + 2007-09-19 Simon Goldschmidt + * icmp.c: Fixed bug #21107 (didn't reset IP TTL in ICMP echo replies) + + 2007-09-15 Mike Kleshov + * mem.c: Fixed bug #21077 (inaccuracy in calculation of lwip_stat.mem.used) + + 2007-09-06 Frédéric Bernon + * several-files: replace some #include "arch/cc.h" by "lwip/arch.h", or simply remove + it as long as "lwip/opt.h" is included before (this one include "lwip/debug.h" which + already include "lwip/arch.h"). Like that, default defines are provided by "lwip/arch.h" + if they are not defined in cc.h, in the same spirit than "lwip/opt.h" for lwipopts.h. + + 2007-08-30 Frédéric Bernon + * igmp.h, igmp.c: Some changes to remove some redundant code, add some traces, + and fix some coding style. + + 2007-08-28 Frédéric Bernon + * tcpip.c: Fix TCPIP_MSG_INPKT processing: now, tcpip_input can be used for any + kind of packets. These packets are considered like Ethernet packets (payload + pointing to ethhdr) if the netif got the NETIF_FLAG_ETHARP flag. Else, packets + are considered like IP packets (payload pointing to iphdr). + + 2007-08-27 Frédéric Bernon + * api.h, api_lib.c, api_msg.c: First fix for "bug #20900 : Potential crash error + problem with netconn_peer & netconn_addr". Introduce NETCONN_LISTEN netconn_state + and remove obsolete ones (NETCONN_RECV & NETCONN_ACCEPT). + + 2007-08-24 Kieran Mansley + * inet.c Modify (acc >> 16) test to ((acc >> 16) != 0) to help buggy + compiler (Paradigm C++) + + 2007-08-09 Frédéric Bernon, Bill Florac + * stats.h, stats.c, igmp.h, igmp.c, opt.h: Fix for bug #20503 : IGMP Improvement. + Introduce IGMP_STATS to centralize statistics management. + + 2007-08-09 Frédéric Bernon, Bill Florac + * udp.c: Fix for bug #20503 : IGMP Improvement. Enable to receive a multicast + packet on a udp pcb binded on an netif's IP address, and not on "any". + + 2007-08-09 Frédéric Bernon, Bill Florac + * igmp.h, igmp.c, ip.c: Fix minor changes from bug #20503 : IGMP Improvement. + This is mainly on using lookup/lookfor, and some coding styles... + + 2007-07-26 Frédéric Bernon (and "thedoctor") + * igmp.c: Fix bug #20595 to accept IGMPv3 "Query" messages. + + 2007-07-25 Simon Goldschmidt + * api_msg.c, tcp.c: Another fix for bug #20021: by not returning an error if + tcp_output fails in tcp_close, the code in do_close_internal gets simpler + (tcp_output is called again later from tcp timers). + + 2007-07-25 Simon Goldschmidt + * ip_frag.c: Fixed bug #20429: use the new pbuf_copy_partial instead of the old + copy_from_pbuf, which illegally modified the given pbuf. + + 2007-07-25 Simon Goldschmidt + * tcp_out.c: tcp_enqueue: pcb->snd_queuelen didn't work for chaine PBUF_RAMs: + changed snd_queuelen++ to snd_queuelen += pbuf_clen(p). + + 2007-07-24 Simon Goldschmidt + * api_msg.c, tcp.c: Fix bug #20480: Check the pcb passed to tcp_listen() for the + correct state (must be CLOSED). + + 2007-07-13 Thomas Taranowski (commited by Jared Grubb) + * memp.c: Fix bug #20478: memp_malloc returned NULL+MEMP_SIZE on failed + allocation. It now returns NULL. + + 2007-07-13 Frédéric Bernon + * api_msg.c: Fix bug #20318: api_msg "recv" callbacks don't call pbuf_free in + all error cases. + + 2007-07-13 Frédéric Bernon + * api_msg.c: Fix bug #20315: possible memory leak problem if tcp_listen failed, + because current code doesn't follow rawapi.txt documentation. + + 2007-07-13 Kieran Mansley + * src/core/tcp_in.c Apply patch#5741 from Oleg Tyshev to fix bug in + out of sequence processing of received packets + + 2007-07-03 Simon Goldschmidt + * nearly-all-files: Added assertions where PBUF_RAM pbufs are used and an + assumption is made that this pbuf is in one piece (i.e. not chained). These + assumptions clash with the possibility of converting to fully pool-based + pbuf implementations, where PBUF_RAM pbufs might be chained. + + 2007-07-03 Simon Goldschmidt + * api.h, api_lib.c, api_msg.c: Final fix for bug #20021 and some other problems + when closing tcp netconns: removed conn->sem, less context switches when + closing, both netconn_close and netconn_delete should safely close tcp + connections. + + 2007-07-02 Simon Goldschmidt + * ipv4/ip.h, ipv6/ip.h, opt.h, netif.h, etharp.h, ipv4/ip.c, netif.c, raw.c, + tcp_out.c, udp.c, etharp.c: Added option LWIP_NETIF_HWADDRHINT (default=off) + to cache ARP table indices with each pcb instead of single-entry cache for + the complete stack. + + 2007-07-02 Simon Goldschmidt + * tcp.h, tcp.c, tcp_in.c, tcp_out.c: Added some ASSERTS and casts to prevent + warnings when assigning to smaller types. + + 2007-06-28 Simon Goldschmidt + * tcp_out.c: Added check to prevent tcp_pcb->snd_queuelen from overflowing. + + 2007-06-28 Simon Goldschmidt + * tcp.h: Fixed bug #20287: Fixed nagle algorithm (sending was done too early if + a segment contained chained pbufs) + + 2007-06-28 Frédéric Bernon + * autoip.c: replace most of rand() calls by a macro LWIP_AUTOIP_RAND which compute + a "pseudo-random" value based on netif's MAC and some autoip fields. It's always + possible to define this macro in your own lwipopts.h to always use C library's + rand(). Note that autoip_create_rand_addr doesn't use this macro. + + 2007-06-28 Frédéric Bernon + * netifapi.h, netifapi.c, tcpip.h, tcpip.c: Update code to handle the option + LWIP_TCPIP_CORE_LOCKING, and do some changes to be coherent with last modifications + in api_lib/api_msg (use pointers and not type with table, etc...) + + 2007-06-26 Simon Goldschmidt + * udp.h: Fixed bug #20259: struct udp_hdr was lacking the packin defines. + + 2007-06-25 Simon Goldschmidt + * udp.c: Fixed bug #20253: icmp_dest_unreach was called with a wrong p->payload + for udp packets with no matching pcb. + + 2007-06-25 Simon Goldschmidt + * udp.c: Fixed bug #20220: UDP PCB search in udp_input(): a non-local match + could get udp input packets if the remote side matched. + + 2007-06-13 Simon Goldschmidt + * netif.c: Fixed bug #20180 (TCP pcbs listening on IP_ADDR_ANY could get + changed in netif_set_ipaddr if previous netif->ip_addr.addr was 0. + + 2007-06-13 Simon Goldschmidt + * api_msg.c: pcb_new sets conn->err if protocol is not implemented + -> netconn_new_..() does not allocate a new connection for unsupported + protocols. + + 2007-06-13 Frédéric Bernon, Simon Goldschmidt + * api_lib.c: change return expression in netconn_addr and netconn_peer, because + conn->err was reset to ERR_OK without any reasons (and error was lost)... + + 2007-06-13 Frédéric Bernon, Matthias Weisser + * opt.h, mem.h, mem.c, memp.c, pbuf.c, ip_frag.c, vj.c: Fix bug #20162. Rename + MEM_ALIGN in LWIP_MEM_ALIGN and MEM_ALIGN_SIZE in LWIP_MEM_ALIGN_SIZE to avoid + some macro names collision with some OS macros. + + 2007-06-11 Simon Goldschmidt + * udp.c: UDP Lite: corrected the use of chksum_len (based on RFC3828: if it's 0, + create checksum over the complete packet. On RX, if it's < 8 (and not 0), + discard the packet. Also removed the duplicate 'udphdr->chksum = 0' for both + UDP & UDP Lite. + + 2007-06-11 Srinivas Gollakota & Oleg Tyshev + * tcp_out.c: Fix for bug #20075 : "A problem with keep-alive timer and TCP flags" + where TCP flags wasn't initialized in tcp_keepalive. + + 2007-06-03 Simon Goldschmidt + * udp.c: udp_input(): Input pbuf was not freed if pcb had no recv function + registered, p->payload was modified without modifying p->len if sending + icmp_dest_unreach() (had no negative effect but was definitively wrong). + + 2007-06-03 Simon Goldschmidt + * icmp.c: Corrected bug #19937: For responding to an icmp echo request, icmp + re-used the input pbuf even if that didn't have enough space to include the + link headers. Now the space is tested and a new pbuf is allocated for the + echo response packet if the echo request pbuf isn't big enough. + + 2007-06-01 Simon Goldschmidt + * sockets.c: Checked in patch #5914: Moved sockopt processing into tcpip_thread. + + 2007-05-23 Frédéric Bernon + * api_lib.c, sockets.c: Fixed bug #5958 for netconn_listen (acceptmbox only + allocated by do_listen if success) and netconn_accept errors handling. In + most of api_lib functions, we replace some errors checkings like "if (conn==NULL)" + by ASSERT, except for netconn_delete. + + 2007-05-23 Frédéric Bernon + * api_lib.c: Fixed bug #5957 "Safe-thread problem inside netconn_recv" to return + an error code if it's impossible to fetch a pbuf on a TCP connection (and not + directly close the recvmbox). + + 2007-05-22 Simon Goldschmidt + * tcp.c: Fixed bug #1895 (tcp_bind not correct) by introducing a list of + bound but unconnected (and non-listening) tcp_pcbs. + + 2007-05-22 Frédéric Bernon + * sys.h, sys.c, api_lib.c, tcpip.c: remove sys_mbox_fetch_timeout() (was only + used for LWIP_SO_RCVTIMEO option) and use sys_arch_mbox_fetch() instead of + sys_mbox_fetch() in api files. Now, users SHOULD NOT use internal lwIP features + like "sys_timeout" in their application threads. + + 2007-05-22 Frédéric Bernon + * api.h, api_lib.c, api_msg.h, api_msg.c: change the struct api_msg_msg to see + which parameters are used by which do_xxx function, and to avoid "misusing" + parameters (patch #5938). + + 2007-05-22 Simon Goldschmidt + * api_lib.c, api_msg.c, raw.c, api.h, api_msg.h, raw.h: Included patch #5938: + changed raw_pcb.protocol from u16_t to u8_t since for IPv4 and IPv6, proto + is only 8 bits wide. This affects the api, as there, the protocol was + u16_t, too. + + 2007-05-18 Simon Goldschmidt + * memp.c: addition to patch #5913: smaller pointer was returned but + memp_memory was the same size -> did not save memory. + + 2007-05-16 Simon Goldschmidt + * loopif.c, slipif.c: Fix bug #19729: free pbuf if netif->input() returns + != ERR_OK. + + 2007-05-16 Simon Goldschmidt + * api_msg.c, udp.c: If a udp_pcb has a local_ip set, check if it is the same + as the one of the netif used for sending to prevent sending from old + addresses after a netif address gets changed (partly fixes bug #3168). + + 2007-05-16 Frédéric Bernon + * tcpip.c, igmp.h, igmp.c: Fixed bug "#19800 : IGMP: igmp_tick() will not work + with NO_SYS=1". Note that igmp_init is always in tcpip_thread (and not in + tcpip_init) because we have to be sure that network interfaces are already + added (mac filter is updated only in igmp_init for the moment). + + 2007-05-16 Simon Goldschmidt + * mem.c, memp.c: Removed semaphores from memp, changed sys_sem_wait calls + into sys_arch_sem_wait calls to prevent timers from running while waiting + for the heap. This fixes bug #19167. + + 2007-05-13 Simon Goldschmidt + * tcp.h, sockets.h, sockets.c: Fixed bug from patch #5865 by moving the defines + for socket options (lwip_set/-getsockopt) used with level IPPROTO_TCP from + tcp.h to sockets.h. + + 2007-05-07 Simon Goldschmidt + * mem.c: Another attempt to fix bug #17922. + + 2007-05-04 Simon Goldschmidt + * pbuf.c, pbuf.h, etharp.c: Further update to ARP queueing: Changed pbuf_copy() + implementation so that it can be reused (don't allocate the target + pbuf inside pbuf_copy()). + + 2007-05-04 Simon Goldschmidt + * memp.c: checked in patch #5913: in memp_malloc() we can return memp as mem + to save a little RAM (next pointer of memp is not used while not in pool). + + 2007-05-03 "maq" + * sockets.c: Fix ioctl FIONREAD when some data remains from last recv. + (patch #3574). + + 2007-04-23 Simon Goldschmidt + * loopif.c, loopif.h, opt.h, src/netif/FILES: fix bug #2595: "loopif results + in NULL reference for incoming TCP packets". Loopif has to be configured + (using LWIP_LOOPIF_MULTITHREADING) to directly call netif->input() + (multithreading environments, e.g. netif->input() = tcpip_input()) or + putting packets on a list that is fed to the stack by calling loopif_poll() + (single-thread / NO_SYS / polling environment where e.g. + netif->input() = ip_input). + + 2007-04-17 Jonathan Larmour + * pbuf.c: Use s32_t in pbuf_realloc(), as an s16_t can't reliably hold + the difference between two u16_t's. + * sockets.h: FD_SETSIZE needs to match number of sockets, which is + MEMP_NUM_NETCONN in sockets.c right now. + + 2007-04-12 Jonathan Larmour + * icmp.c: Reset IP header TTL in ICMP ECHO responses (bug #19580). + + 2007-04-12 Kieran Mansley + * tcp.c, tcp_in.c, tcp_out.c, tcp.h: Modify way the retransmission + timer is reset to fix bug#19434, with help from Oleg Tyshev. + + 2007-04-11 Simon Goldschmidt + * etharp.c, pbuf.c, pbuf.h: 3rd fix for bug #11400 (arp-queuing): More pbufs than + previously thought need to be copied (everything but PBUF_ROM!). Cleaned up + pbuf.c: removed functions no needed any more (by etharp). + + 2007-04-11 Kieran Mansley + * inet.c, ip_addr.h, sockets.h, sys.h, tcp.h: Apply patch #5745: Fix + "Constant is long" warnings with 16bit compilers. Contributed by + avatar@mmlab.cse.yzu.edu.tw + + 2007-04-05 Frédéric Bernon, Jonathan Larmour + * api_msg.c: Fix bug #16830: "err_tcp() posts to connection mailbox when no pend on + the mailbox is active". Now, the post is only done during a connect, and do_send, + do_write and do_join_leave_group don't do anything if a previous error was signaled. + + 2007-04-03 Frédéric Bernon + * ip.c: Don't set the IP_DF ("Don't fragment") flag in the IP header in IP output + packets. See patch #5834. + + 2007-03-30 Frédéric Bernon + * api_msg.c: add a "pcb_new" helper function to avoid redundant code, and to add + missing pcb allocations checking (in do_bind, and for each raw_new). Fix style. + + 2007-03-30 Frédéric Bernon + * most of files: prefix all debug.h define with "LWIP_" to avoid any conflict with + others environment defines (these were too "generic"). + + 2007-03-28 Frédéric Bernon + * api.h, api_lib.c, sockets.c: netbuf_ref doesn't check its internal pbuf_alloc call + result and can cause a crash. lwip_send now check netbuf_ref result. + + 2007-03-28 Simon Goldschmidt + * sockets.c Remove "#include " from sockets.c to avoid multiple + definition of macros (in errno.h and lwip/arch.h) if LWIP_PROVIDE_ERRNO is + defined. This is the way it should have been already (looking at + doc/sys_arch.txt) + + 2007-03-28 Kieran Mansley + * opt.h Change default PBUF_POOL_BUFSIZE (again) to accomodate default MSS + + IP and TCP headers *and* physical link headers + + 2007-03-26 Frédéric Bernon (based on patch from Dmitry Potapov) + * api_lib.c: patch for netconn_write(), fixes a possible race condition which cause + to send some garbage. It is not a definitive solution, but the patch does solve + the problem for most cases. + + 2007-03-22 Frédéric Bernon + * api_msg.h, api_msg.c: Remove obsolete API_MSG_ACCEPT and do_accept (never used). + + 2007-03-22 Frédéric Bernon + * api_lib.c: somes resources couldn't be freed if there was errors during + netconn_new_with_proto_and_callback. + + 2007-03-22 Frédéric Bernon + * ethernetif.c: update netif->input calls to check return value. In older ports, + it's a good idea to upgrade them, even if before, there could be another problem + (access to an uninitialized mailbox). + + 2007-03-21 Simon Goldschmidt + * sockets.c: fixed bug #5067 (essentialy a signed/unsigned warning fixed + by casting to unsigned). + + 2007-03-21 Frédéric Bernon + * api_lib.c, api_msg.c, tcpip.c: integrate sys_mbox_fetch(conn->mbox, NULL) calls from + api_lib.c to tcpip.c's tcpip_apimsg(). Now, use a local variable and not a + dynamic one from memp to send tcpip_msg to tcpip_thread in a synchrone call. + Free tcpip_msg from tcpip_apimsg is not done in tcpip_thread. This give a + faster and more reliable communication between api_lib and tcpip. + + 2007-03-21 Frédéric Bernon + * opt.h: Add LWIP_NETIF_CALLBACK (to avoid compiler warning) and set it to 0. + + 2007-03-21 Frédéric Bernon + * api_msg.c, igmp.c, igmp.h: Fix C++ style comments + + 2007-03-21 Kieran Mansley + * opt.h Change default PBUF_POOL_BUFSIZE to accomodate default MSS + + IP and TCP headers + + 2007-03-21 Kieran Mansley + * Fix all uses of pbuf_header to check the return value. In some + cases just assert if it fails as I'm not sure how to fix them, but + this is no worse than before when they would carry on regardless + of the failure. + + 2007-03-21 Kieran Mansley + * sockets.c, igmp.c, igmp.h, memp.h: Fix C++ style comments and + comment out missing header include in icmp.c + + 2007-03-20 Frédéric Bernon + * memp.h, stats.c: Fix stats_display function where memp_names table wasn't + synchronized with memp.h. + + 2007-03-20 Frédéric Bernon + * tcpip.c: Initialize tcpip's mbox, and verify if initialized in tcpip_input, + tcpip_ethinput, tcpip_callback, tcpip_apimsg, to fix a init problem with + network interfaces. Also fix a compiler warning. + + 2007-03-20 Kieran Mansley + * udp.c: Only try and use pbuf_header() to make space for headers if + not a ROM or REF pbuf. + + 2007-03-19 Frédéric Bernon + * api_msg.h, api_msg.c, tcpip.h, tcpip.c: Add return types to tcpip_apimsg() + and api_msg_post(). + + 2007-03-19 Frédéric Bernon + * Remove unimplemented "memp_realloc" function from memp.h. + + 2007-03-11 Simon Goldschmidt + * pbuf.c: checked in patch #5796: pbuf_alloc: len field claculation caused + memory corruption. + + 2007-03-11 Simon Goldschmidt (based on patch from Dmitry Potapov) + * api_lib.c, sockets.c, api.h, api_msg.h, sockets.h: Fixed bug #19251 + (missing `const' qualifier in socket functions), to get more compatible to + standard POSIX sockets. + + 2007-03-11 Frédéric Bernon (based on patch from Dmitry Potapov) + * sockets.c: Add asserts inside bind, connect and sendto to check input + parameters. Remove excessive set_errno() calls after get_socket(), because + errno is set inside of get_socket(). Move last sock_set_errno() inside + lwip_close. + + 2007-03-09 Simon Goldschmidt + * memp.c: Fixed bug #11400: New etharp queueing introduced bug: memp_memory + was allocated too small. + + 2007-03-06 Simon Goldschmidt + * tcpip.c: Initialize dhcp timers in tcpip_thread (if LWIP_DHCP) to protect + the stack from concurrent access. + + 2007-03-06 Frédéric Bernon, Dmitry Potapov + * tcpip.c, ip_frag.c, ethernetif.c: Fix some build problems, and a redundancy + call to "lwip_stats.link.recv++;" in low_level_input() & ethernetif_input(). + + 2007-03-06 Simon Goldschmidt + * ip_frag.c, ip_frag.h: Reduce code size: don't include code in those files + if IP_FRAG == 0 and IP_REASSEMBLY == 0 + + 2007-03-06 Frédéric Bernon, Simon Goldschmidt + * opt.h, ip_frag.h, tcpip.h, tcpip.c, ethernetif.c: add new configuration + option named ETHARP_TCPIP_ETHINPUT, which enable the new tcpip_ethinput. + Allow to do ARP processing for incoming packets inside tcpip_thread + (protecting ARP layer against concurrent access). You can also disable + old code using tcp_input with new define ETHARP_TCPIP_INPUT set to 0. + Older ports have to use tcpip_ethinput. + + 2007-03-06 Simon Goldschmidt (based on patch from Dmitry Potapov) + * err.h, err.c: fixed compiler warning "initialization dircards qualifiers + from pointer target type" + + 2007-03-05 Frédéric Bernon + * opt.h, sockets.h: add new configuration options (LWIP_POSIX_SOCKETS_IO_NAMES, + ETHARP_TRUST_IP_MAC, review SO_REUSE) + + 2007-03-04 Frédéric Bernon + * api_msg.c: Remove some compiler warnings : parameter "pcb" was never + referenced. + + 2007-03-04 Frédéric Bernon + * api_lib.c: Fix "[patch #5764] api_lib.c cleanup: after patch #5687" (from + Dmitry Potapov). + The api_msg struct stay on the stack (not moved to netconn struct). + + 2007-03-04 Simon Goldschmidt (based on patch from Dmitry Potapov) + * pbuf.c: Fix BUG#19168 - pbuf_free can cause deadlock (if + SYS_LIGHTWEIGHT_PROT=1 & freeing PBUF_RAM when mem_sem is not available) + Also fixed cast warning in pbuf_alloc() + + 2007-03-04 Simon Goldschmidt + * etharp.c, etharp.h, memp.c, memp.h, opt.h: Fix BUG#11400 - don't corrupt + existing pbuf chain when enqueuing multiple pbufs to a pending ARP request + + 2007-03-03 Frédéric Bernon + * udp.c: remove obsolete line "static struct udp_pcb *pcb_cache = NULL;" + It is static, and never used in udp.c except udp_init(). + + 2007-03-02 Simon Goldschmidt + * tcpip.c: Moved call to ip_init(), udp_init() and tcp_init() from + tcpip_thread() to tcpip_init(). This way, raw API connections can be + initialized before tcpip_thread is running (e.g. before OS is started) + + 2007-03-02 Frédéric Bernon + * rawapi.txt: Fix documentation mismatch with etharp.h about etharp_tmr's call + interval. + + 2007-02-28 Kieran Mansley + * pbuf.c: Fix BUG#17645 - ensure pbuf payload pointer is not moved + outside the region of the pbuf by pbuf_header() + + 2007-02-28 Kieran Mansley + * sockets.c: Fix BUG#19161 - ensure milliseconds timeout is non-zero + when supplied timeout is also non-zero + +(STABLE-1.2.0) + + 2006-12-05 Leon Woestenberg + * CHANGELOG: Mention STABLE-1.2.0 release. + + ++ New features: + + 2006-12-01 Christiaan Simons + * mem.h, opt.h: Added MEM_LIBC_MALLOC option. + Note this is a workaround. Currently I have no other options left. + + 2006-10-26 Christiaan Simons (accepted patch by Jonathan Larmour) + * ipv4/ip_frag.c: rename MAX_MTU to IP_FRAG_MAX_MTU and move define + to include/lwip/opt.h. + * ipv4/lwip/ip_frag.h: Remove unused IP_REASS_INTERVAL. + Move IP_REASS_MAXAGE and IP_REASS_BUFSIZE to include/lwip/opt.h. + * opt.h: Add above new options. + + 2006-08-18 Christiaan Simons + * tcp_{in,out}.c: added SNMP counters. + * ipv4/ip.c: added SNMP counters. + * ipv4/ip_frag.c: added SNMP counters. + + 2006-08-08 Christiaan Simons + * etharp.{c,h}: added etharp_find_addr() to read + (stable) ethernet/IP address pair from ARP table + + 2006-07-14 Christiaan Simons + * mib_structs.c: added + * include/lwip/snmp_structs.h: added + * netif.{c,h}, netif/ethernetif.c: added SNMP statistics to netif struct + + 2006-07-06 Christiaan Simons + * snmp/asn1_{enc,dec}.c added + * snmp/mib2.c added + * snmp/msg_{in,out}.c added + * include/lwip/snmp_asn1.h added + * include/lwip/snmp_msg.h added + * doc/snmp_agent.txt added + + 2006-03-29 Christiaan Simons + * inet.c, inet.h: Added platform byteswap support. + Added LWIP_PLATFORM_BYTESWAP define (defaults to 0) and + optional LWIP_PLATFORM_HTONS(), LWIP_PLATFORM_HTONL() macros. + + ++ Bug fixes: + + 2006-11-30 Christiaan Simons + * dhcp.c: Fixed false triggers of request_timeout. + + 2006-11-28 Christiaan Simons + * netif.c: In netif_add() fixed missing clear of ip_addr, netmask, gw and flags. + + 2006-10-11 Christiaan Simons + * api_lib.c etharp.c, ip.c, memp.c, stats.c, sys.{c,h} tcp.h: + Partially accepted patch #5449 for ANSI C compatibility / build fixes. + * ipv4/lwip/ip.h ipv6/lwip/ip.h: Corrected UDP-Lite protocol + identifier from 170 to 136 (bug #17574). + + 2006-10-10 Christiaan Simons + * api_msg.c: Fixed Nagle algorithm as reported by Bob Grice. + + 2006-08-17 Christiaan Simons + * udp.c: Fixed bug #17200, added check for broadcast + destinations for PCBs bound to a unicast address. + + 2006-08-07 Christiaan Simons + * api_msg.c: Flushing TCP output in do_close() (bug #15926). + + 2006-06-27 Christiaan Simons + * api_msg.c: Applied patch for cold case (bug #11135). + In accept_function() ensure newconn->callback is always initialized. + + 2006-06-15 Christiaan Simons + * mem.h: added MEM_SIZE_F alias to fix an ancient cold case (bug #1748), + facilitate printing of mem_size_t and u16_t statistics. + + 2006-06-14 Christiaan Simons + * api_msg.c: Applied patch #5146 to handle allocation failures + in accept() by Kevin Lawson. + + 2006-05-26 Christiaan Simons + * api_lib.c: Removed conn->sem creation and destruction + from netconn_write() and added sys_sem_new to netconn_new_*. + +(STABLE-1_1_1) + + 2006-03-03 Christiaan Simons + * ipv4/ip_frag.c: Added bound-checking assertions on ip_reassbitmap + access and added pbuf_alloc() return value checks. + + 2006-01-01 Leon Woestenberg + * tcp_{in,out}.c, tcp_out.c: Removed 'even sndbuf' fix in TCP, which is + now handled by the checksum routine properly. + + 2006-02-27 Leon Woestenberg + * pbuf.c: Fix alignment; pbuf_init() would not work unless + pbuf_pool_memory[] was properly aligned. (Patch by Curt McDowell.) + + 2005-12-20 Leon Woestenberg + * tcp.c: Remove PCBs which stay in LAST_ACK state too long. Patch + submitted by Mitrani Hiroshi. + + 2005-12-15 Christiaan Simons + * inet.c: Disabled the added summing routine to preserve code space. + + 2005-12-14 Leon Woestenberg + * tcp_in.c: Duplicate FIN ACK race condition fix by Kelvin Lawson. + Added Curt McDowell's optimized checksumming routine for future + inclusion. Need to create test case for unaliged, aligned, odd, + even length combination of cases on various endianess machines. + + 2005-12-09 Christiaan Simons + * inet.c: Rewrote standard checksum routine in proper portable C. + + 2005-11-25 Christiaan Simons + * udp.c tcp.c: Removed SO_REUSE hack. Should reside in socket code only. + * *.c: introduced cc.h LWIP_DEBUG formatters matching the u16_t, s16_t, + u32_t, s32_t typedefs. This solves most debug word-length assumes. + + 2005-07-17 Leon Woestenberg + * inet.c: Fixed unaligned 16-bit access in the standard checksum + routine by Peter Jolasson. + * slipif.c: Fixed implementation assumption of single-pbuf datagrams. + + 2005-02-04 Leon Woestenberg + * tcp_out.c: Fixed uninitialized 'queue' referenced in memerr branch. + * tcp_{out|in}.c: Applied patch fixing unaligned access. + + 2005-01-04 Leon Woestenberg + * pbuf.c: Fixed missing semicolon after LWIP_DEBUG statement. + + 2005-01-03 Leon Woestenberg + * udp.c: UDP pcb->recv() was called even when it was NULL. + +(STABLE-1_1_0) + + 2004-12-28 Leon Woestenberg + * etharp.*: Disabled multiple packets on the ARP queue. + This clashes with TCP queueing. + + 2004-11-28 Leon Woestenberg + * etharp.*: Fixed race condition from ARP request to ARP timeout. + Halved the ARP period, doubled the period counts. + ETHARP_MAX_PENDING now should be at least 2. This prevents + the counter from reaching 0 right away (which would allow + too little time for ARP responses to be received). + + 2004-11-25 Leon Woestenberg + * dhcp.c: Decline messages were not multicast but unicast. + * etharp.c: ETHARP_CREATE is renamed to ETHARP_TRY_HARD. + Do not try hard to insert arbitrary packet's source address, + etharp_ip_input() now calls etharp_update() without ETHARP_TRY_HARD. + etharp_query() now always DOES call ETHARP_TRY_HARD so that users + querying an address will see it appear in the cache (DHCP could + suffer from this when a server invalidly gave an in-use address.) + * ipv4/ip_addr.h: Renamed ip_addr_maskcmp() to _netcmp() as we are + comparing network addresses (identifiers), not the network masks + themselves. + * ipv4/ip_addr.c: ip_addr_isbroadcast() now checks that the given + IP address actually belongs to the network of the given interface. + + 2004-11-24 Kieran Mansley + * tcp.c: Increment pcb->snd_buf when ACK is received in SYN_SENT state. + +(STABLE-1_1_0-RC1) + + 2004-10-16 Kieran Mansley + * tcp.c: Add code to tcp_recved() to send an ACK (window update) immediately, + even if one is already pending, if the rcv_wnd is above a threshold + (currently TCP_WND/2). This avoids waiting for a timer to expire to send a + delayed ACK in order to open the window if the stack is only receiving data. + + 2004-09-12 Kieran Mansley + * tcp*.*: Retransmit time-out handling improvement by Sam Jansen. + + 2004-08-20 Tony Mountifield + * etharp.c: Make sure the first pbuf queued on an ARP entry + is properly ref counted. + + 2004-07-27 Tony Mountifield + * debug.h: Added (int) cast in LWIP_DEBUGF() to avoid compiler + warnings about comparison. + * pbuf.c: Stopped compiler complaining of empty if statement + when LWIP_DEBUGF() empty. Closed an unclosed comment. + * tcp.c: Stopped compiler complaining of empty if statement + when LWIP_DEBUGF() empty. + * ip.h Corrected IPH_TOS() macro: returns a byte, so doesn't need htons(). + * inet.c: Added a couple of casts to quiet the compiler. + No need to test isascii(c) before isdigit(c) or isxdigit(c). + + 2004-07-22 Tony Mountifield + * inet.c: Made data types consistent in inet_ntoa(). + Added casts for return values of checksum routines, to pacify compiler. + * ip_frag.c, tcp_out.c, sockets.c, pbuf.c + Small corrections to some debugging statements, to pacify compiler. + + 2004-07-21 Tony Mountifield + * etharp.c: Removed spurious semicolon and added missing end-of-comment. + * ethernetif.c Updated low_level_output() to match prototype for + netif->linkoutput and changed low_level_input() similarly for consistency. + * api_msg.c: Changed recv_raw() from int to u8_t, to match prototype + of raw_recv() in raw.h and so avoid compiler error. + * sockets.c: Added trivial (int) cast to keep compiler happier. + * ip.c, netif.c Changed debug statements to use the tidier ip4_addrN() macros. + +(STABLE-1_0_0) + + ++ Changes: + + 2004-07-05 Leon Woestenberg + * sockets.*: Restructured LWIP_PRIVATE_TIMEVAL. Make sure + your cc.h file defines this either 1 or 0. If non-defined, + defaults to 1. + * .c: Added and includes where used. + * etharp.c: Made some array indices unsigned. + + 2004-06-27 Leon Woestenberg + * netif.*: Added netif_set_up()/down(). + * dhcp.c: Changes to restart program flow. + + 2004-05-07 Leon Woestenberg + * etharp.c: In find_entry(), instead of a list traversal per candidate, do a + single-pass lookup for different candidates. Should exploit locality. + + 2004-04-29 Leon Woestenberg + * tcp*.c: Cleaned up source comment documentation for Doxygen processing. + * opt.h: ETHARP_ALWAYS_INSERT option removed to comply with ARP RFC. + * etharp.c: update_arp_entry() only adds new ARP entries when adviced to by + the caller. This deprecates the ETHARP_ALWAYS_INSERT overrule option. + + ++ Bug fixes: + + 2004-04-27 Leon Woestenberg + * etharp.c: Applied patch of bug #8708 by Toni Mountifield with a solution + suggested by Timmy Brolin. Fix for 32-bit processors that cannot access + non-aligned 32-bit words, such as soms 32-bit TCP/IP header fields. Fix + is to prefix the 14-bit Ethernet headers with two padding bytes. + + 2004-04-23 Leon Woestenberg + * ip_addr.c: Fix in the ip_addr_isbroadcast() check. + * etharp.c: Fixed the case where the packet that initiates the ARP request + is not queued, and gets lost. Fixed the case where the packets destination + address is already known; we now always queue the packet and perform an ARP + request. + +(STABLE-0_7_0) + + ++ Bug fixes: + + * Fixed TCP bug for SYN_SENT to ESTABLISHED state transition. + * Fixed TCP bug in dequeueing of FIN from out of order segment queue. + * Fixed two possible NULL references in rare cases. + +(STABLE-0_6_6) + + ++ Bug fixes: + + * Fixed DHCP which did not include the IP address in DECLINE messages. + + ++ Changes: + + * etharp.c has been hauled over a bit. + +(STABLE-0_6_5) + + ++ Bug fixes: + + * Fixed TCP bug induced by bad window resizing with unidirectional TCP traffic. + * Packets sent from ARP queue had invalid source hardware address. + + ++ Changes: + + * Pass-by ARP requests do now update the cache. + + ++ New features: + + * No longer dependent on ctype.h. + * New socket options. + * Raw IP pcb support. + +(STABLE-0_6_4) + + ++ Bug fixes: + + * Some debug formatters and casts fixed. + * Numereous fixes in PPP. + + ++ Changes: + + * DEBUGF now is LWIP_DEBUGF + * pbuf_dechain() has been re-enabled. + * Mentioned the changed use of CVS branches in README. + +(STABLE-0_6_3) + + ++ Bug fixes: + + * Fixed pool pbuf memory leak in pbuf_alloc(). + Occured if not enough PBUF_POOL pbufs for a packet pbuf chain. + Reported by Savin Zlobec. + + * PBUF_POOL chains had their tot_len field not set for non-first + pbufs. Fixed in pbuf_alloc(). + + ++ New features: + + * Added PPP stack contributed by Marc Boucher + + ++ Changes: + + * Now drops short packets for ICMP/UDP/TCP protocols. More robust. + + * ARP queueuing now queues the latest packet instead of the first. + This is the RFC recommended behaviour, but can be overridden in + lwipopts.h. + +(0.6.2) + + ++ Bugfixes: + + * TCP has been fixed to deal with the new use of the pbuf->ref + counter. + + * DHCP dhcp_inform() crash bug fixed. + + ++ Changes: + + * Removed pbuf_pool_free_cache and pbuf_pool_alloc_cache. Also removed + pbuf_refresh(). This has sped up pbuf pool operations considerably. + Implemented by David Haas. + +(0.6.1) + + ++ New features: + + * The packet buffer implementation has been enhanced to support + zero-copy and copy-on-demand for packet buffers which have their + payloads in application-managed memory. + Implemented by David Haas. + + Use PBUF_REF to make a pbuf refer to RAM. lwIP will use zero-copy + if an outgoing packet can be directly sent on the link, or perform + a copy-on-demand when necessary. + + The application can safely assume the packet is sent, and the RAM + is available to the application directly after calling udp_send() + or similar function. + + ++ Bugfixes: + + * ARP_QUEUEING should now correctly work for all cases, including + PBUF_REF. + Implemented by Leon Woestenberg. + + ++ Changes: + + * IP_ADDR_ANY is no longer a NULL pointer. Instead, it is a pointer + to a '0.0.0.0' IP address. + + * The packet buffer implementation is changed. The pbuf->ref counter + meaning has changed, and several pbuf functions have been + adapted accordingly. + + * netif drivers have to be changed to set the hardware address length field + that must be initialized correctly by the driver (hint: 6 for Ethernet MAC). + See the contrib/ports/c16x cs8900 driver as a driver example. + + * netif's have a dhcp field that must be initialized to NULL by the driver. + See the contrib/ports/c16x cs8900 driver as a driver example. + +(0.5.x) This file has been unmaintained up to 0.6.1. All changes are + logged in CVS but have not been explained here. + +(0.5.3) Changes since version 0.5.2 + + ++ Bugfixes: + + * memp_malloc(MEMP_API_MSG) could fail with multiple application + threads because it wasn't protected by semaphores. + + ++ Other changes: + + * struct ip_addr now packed. + + * The name of the time variable in arp.c has been changed to ctime + to avoid conflicts with the time() function. + +(0.5.2) Changes since version 0.5.1 + + ++ New features: + + * A new TCP function, tcp_tmr(), now handles both TCP timers. + + ++ Bugfixes: + + * A bug in tcp_parseopt() could cause the stack to hang because of a + malformed TCP option. + + * The address of new connections in the accept() function in the BSD + socket library was not handled correctly. + + * pbuf_dechain() did not update the ->tot_len field of the tail. + + * Aborted TCP connections were not handled correctly in all + situations. + + ++ Other changes: + + * All protocol header structs are now packed. + + * The ->len field in the tcp_seg structure now counts the actual + amount of data, and does not add one for SYN and FIN segments. + +(0.5.1) Changes since version 0.5.0 + + ++ New features: + + * Possible to run as a user process under Linux. + + * Preliminary support for cross platform packed structs. + + * ARP timer now implemented. + + ++ Bugfixes: + + * TCP output queue length was badly initialized when opening + connections. + + * TCP delayed ACKs were not sent correctly. + + * Explicit initialization of BSS segment variables. + + * read() in BSD socket library could drop data. + + * Problems with memory alignment. + + * Situations when all TCP buffers were used could lead to + starvation. + + * TCP MSS option wasn't parsed correctly. + + * Problems with UDP checksum calculation. + + * IP multicast address tests had endianess problems. + + * ARP requests had wrong destination hardware address. + + ++ Other changes: + + * struct eth_addr changed from u16_t[3] array to u8_t[6]. + + * A ->linkoutput() member was added to struct netif. + + * TCP and UDP ->dest_* struct members where changed to ->remote_*. + + * ntoh* macros are now null definitions for big endian CPUs. + +(0.5.0) Changes since version 0.4.2 + + ++ New features: + + * Redesigned operating system emulation layer to make porting easier. + + * Better control over TCP output buffers. + + * Documenation added. + + ++ Bugfixes: + + * Locking issues in buffer management. + + * Bugfixes in the sequential API. + + * IP forwarding could cause memory leakage. This has been fixed. + + ++ Other changes: + + * Directory structure somewhat changed; the core/ tree has been + collapsed. + +(0.4.2) Changes since version 0.4.1 + + ++ New features: + + * Experimental ARP implementation added. + + * Skeleton Ethernet driver added. + + * Experimental BSD socket API library added. + + ++ Bugfixes: + + * In very intense situations, memory leakage could occur. This has + been fixed. + + ++ Other changes: + + * Variables named "data" and "code" have been renamed in order to + avoid name conflicts in certain compilers. + + * Variable++ have in appliciable cases been translated to ++variable + since some compilers generate better code in the latter case. + +(0.4.1) Changes since version 0.4 + + ++ New features: + + * TCP: Connection attempts time out earlier than data + transmissions. Nagle algorithm implemented. Push flag set on the + last segment in a burst. + + * UDP: experimental support for UDP-Lite extensions. + + ++ Bugfixes: + + * TCP: out of order segments were in some cases handled incorrectly, + and this has now been fixed. Delayed acknowledgements was broken + in 0.4, has now been fixed. Binding to an address that is in use + now results in an error. Reset connections sometimes hung an + application; this has been fixed. + + * Checksum calculation sometimes failed for chained pbufs with odd + lengths. This has been fixed. + + * API: a lot of bug fixes in the API. The UDP API has been improved + and tested. Error reporting and handling has been + improved. Logical flaws and race conditions for incoming TCP + connections has been found and removed. + + * Memory manager: alignment issues. Reallocating memory sometimes + failed, this has been fixed. + + * Generic library: bcopy was flawed and has been fixed. + + ++ Other changes: + + * API: all datatypes has been changed from generic ones such as + ints, to specified ones such as u16_t. Functions that return + errors now have the correct type (err_t). + + * General: A lot of code cleaned up and debugging code removed. Many + portability issues have been fixed. + + * The license was changed; the advertising clause was removed. + + * C64 port added. + + * Thanks: Huge thanks go to Dagan Galarneau, Horst Garnetzke, Petri + Kosunen, Mikael Caleres, and Frits Wilmink for reporting and + fixing bugs! + +(0.4) Changes since version 0.3.1 + + * Memory management has been radically changed; instead of + allocating memory from a shared heap, memory for objects that are + rapidly allocated and deallocated is now kept in pools. Allocation + and deallocation from those memory pools is very fast. The shared + heap is still present but is used less frequently. + + * The memory, memory pool, and packet buffer subsystems now support + 4-, 2-, or 1-byte alignment. + + * "Out of memory" situations are handled in a more robust way. + + * Stack usage has been reduced. + + * Easier configuration of lwIP parameters such as memory usage, + TTLs, statistics gathering, etc. All configuration parameters are + now kept in a single header file "lwipopts.h". + + * The directory structure has been changed slightly so that all + architecture specific files are kept under the src/arch + hierarchy. + + * Error propagation has been improved, both in the protocol modules + and in the API. + + * The code for the RTXC architecture has been implemented, tested + and put to use. + + * Bugs have been found and corrected in the TCP, UDP, IP, API, and + the Internet checksum modules. + + * Bugs related to porting between a 32-bit and a 16-bit architecture + have been found and corrected. + + * The license has been changed slightly to conform more with the + original BSD license, including the advertisement clause. + +(0.3.1) Changes since version 0.3 + + * Fix of a fatal bug in the buffer management. Pbufs with allocated + RAM never returned the RAM when the pbuf was deallocated. + + * TCP congestion control, window updates and retransmissions did not + work correctly. This has now been fixed. + + * Bugfixes in the API. + +(0.3) Changes since version 0.2 + + * New and improved directory structure. All include files are now + kept in a dedicated include/ directory. + + * The API now has proper error handling. A new function, + netconn_err(), now returns an error code for the connection in + case of errors. + + * Improvements in the memory management subsystem. The system now + keeps a pointer to the lowest free memory block. A new function, + mem_malloc2() tries to allocate memory once, and if it fails tries + to free some memory and retry the allocation. + + * Much testing has been done with limited memory + configurations. lwIP now does a better job when overloaded. + + * Some bugfixes and improvements to the buffer (pbuf) subsystem. + + * Many bugfixes in the TCP code: + + - Fixed a bug in tcp_close(). + + - The TCP receive window was incorrectly closed when out of + sequence segments was received. This has been fixed. + + - Connections are now timed-out of the FIN-WAIT-2 state. + + - The initial congestion window could in some cases be too + large. This has been fixed. + + - The retransmission queue could in some cases be screwed up. This + has been fixed. + + - TCP RST flag now handled correctly. + + - Out of sequence data was in some cases never delivered to the + application. This has been fixed. + + - Retransmitted segments now contain the correct acknowledgment + number and advertised window. + + - TCP retransmission timeout backoffs are not correctly computed + (ala BSD). After a number of retransmissions, TCP now gives up + the connection. + + * TCP connections now are kept on three lists, one for active + connections, one for listening connections, and one for + connections that are in TIME-WAIT. This greatly speeds up the fast + timeout processing for sending delayed ACKs. + + * TCP now provides proper feedback to the application when a + connection has been successfully set up. + + * More comments have been added to the code. The code has also been + somewhat cleaned up. + +(0.2) Initial public release. diff --git a/component/common/network/lwip/lwip_v1.3.2/COPYING b/component/common/network/lwip/lwip_v1.3.2/COPYING new file mode 100644 index 0000000..e23898b --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/COPYING @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2001, 2002 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + + diff --git a/component/common/network/lwip/lwip_v1.3.2/FILES b/component/common/network/lwip/lwip_v1.3.2/FILES new file mode 100644 index 0000000..6625319 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/FILES @@ -0,0 +1,4 @@ +src/ - The source code for the lwIP TCP/IP stack. +doc/ - The documentation for lwIP. + +See also the FILES file in each subdirectory. diff --git a/component/common/network/lwip/lwip_v1.3.2/README b/component/common/network/lwip/lwip_v1.3.2/README new file mode 100644 index 0000000..a62cc4f --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/README @@ -0,0 +1,89 @@ +INTRODUCTION + +lwIP is a small independent implementation of the TCP/IP protocol +suite that has been developed by Adam Dunkels at the Computer and +Networks Architectures (CNA) lab at the Swedish Institute of Computer +Science (SICS). + +The focus of the lwIP TCP/IP implementation is to reduce the RAM usage +while still having a full scale TCP. This making lwIP suitable for use +in embedded systems with tens of kilobytes of free RAM and room for +around 40 kilobytes of code ROM. + +FEATURES + + * IP (Internet Protocol) including packet forwarding over multiple network + interfaces + * ICMP (Internet Control Message Protocol) for network maintenance and debugging + * IGMP (Internet Group Management Protocol) for multicast traffic management + * UDP (User Datagram Protocol) including experimental UDP-lite extensions + * TCP (Transmission Control Protocol) with congestion control, RTT estimation + and fast recovery/fast retransmit + * Specialized raw/native API for enhanced performance + * Optional Berkeley-like socket API + * DNS (Domain names resolver) + * SNMP (Simple Network Management Protocol) + * DHCP (Dynamic Host Configuration Protocol) + * AUTOIP (for IPv4, conform with RFC 3927) + * PPP (Point-to-Point Protocol) + * ARP (Address Resolution Protocol) for Ethernet + +LICENSE + +lwIP is freely available under a BSD license. + +DEVELOPMENT + +lwIP has grown into an excellent TCP/IP stack for embedded devices, +and developers using the stack often submit bug fixes, improvements, +and additions to the stack to further increase its usefulness. + +Development of lwIP is hosted on Savannah, a central point for +software development, maintenance and distribution. Everyone can +help improve lwIP by use of Savannah's interface, CVS and the +mailing list. A core team of developers will commit changes to the +CVS source tree. + +The lwIP TCP/IP stack is maintained in the 'lwip' CVS module and +contributions (such as platform ports) are in the 'contrib' module. + +See doc/savannah.txt for details on CVS server access for users and +developers. + +Last night's CVS tar ball can be downloaded from: + http://savannah.gnu.org/cvs.backups/lwip.tar.gz [CHANGED - NEEDS FIXING] + +The current CVS trees are web-browsable: + http://savannah.nongnu.org/cgi-bin/viewcvs/lwip/lwip/ + http://savannah.nongnu.org/cgi-bin/viewcvs/lwip/contrib/ + +Submit patches and bugs via the lwIP project page: + http://savannah.nongnu.org/projects/lwip/ + + +DOCUMENTATION + +The original out-dated homepage of lwIP and Adam Dunkels' papers on +lwIP are at the official lwIP home page: + http://www.sics.se/~adam/lwip/ + +Self documentation of the source code is regularly extracted from the +current CVS sources and is available from this web page: + http://www.nongnu.org/lwip/ + +There is now a constantly growin wiki about lwIP at + http://lwip.wikia.com/wiki/LwIP_Wiki + +Also, there are mailing lists you can subscribe at + http://savannah.nongnu.org/mail/?group=lwip +plus searchable archives: + http://lists.nongnu.org/archive/html/lwip-users/ + http://lists.nongnu.org/archive/html/lwip-devel/ + +Reading Adam's papers, the files in docs/, browsing the source code +documentation and browsing the mailing list archives is a good way to +become familiar with the design of lwIP. + +Adam Dunkels +Leon Woestenberg + diff --git a/component/common/network/lwip/lwip_v1.3.2/doc/FILES b/component/common/network/lwip/lwip_v1.3.2/doc/FILES new file mode 100644 index 0000000..05d356f --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/doc/FILES @@ -0,0 +1,6 @@ +savannah.txt - How to obtain the current development source code. +contrib.txt - How to contribute to lwIP as a developer. +rawapi.txt - The documentation for the core API of lwIP. + Also provides an overview about the other APIs and multithreading. +snmp_agent.txt - The documentation for the lwIP SNMP agent. +sys_arch.txt - The documentation for a system abstraction layer of lwIP. diff --git a/component/common/network/lwip/lwip_v1.3.2/doc/contrib.txt b/component/common/network/lwip/lwip_v1.3.2/doc/contrib.txt new file mode 100644 index 0000000..39596fc --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/doc/contrib.txt @@ -0,0 +1,63 @@ +1 Introduction + +This document describes some guidelines for people participating +in lwIP development. + +2 How to contribute to lwIP + +Here is a short list of suggestions to anybody working with lwIP and +trying to contribute bug reports, fixes, enhancements, platform ports etc. +First of all as you may already know lwIP is a volunteer project so feedback +to fixes or questions might often come late. Hopefully the bug and patch tracking +features of Savannah help us not lose users' input. + +2.1 Source code style: + +1. do not use tabs. +2. indentation is two spaces per level (i.e. per tab). +3. end debug messages with a trailing newline (\n). +4. one space between keyword and opening bracket. +5. no space between function and opening bracket. +6. one space and no newline before opening curly braces of a block. +7. closing curly brace on a single line. +8. spaces surrounding assignment and comparisons. +9. don't initialize static and/or global variables to zero, the compiler takes care of that. +10. use current source code style as further reference. + +2.2 Source code documentation style: + +1. JavaDoc compliant and Doxygen compatible. +2. Function documentation above functions in .c files, not .h files. + (This forces you to synchronize documentation and implementation.) +3. Use current documentation style as further reference. + +2.3 Bug reports and patches: + +1. Make sure you are reporting bugs or send patches against the latest + sources. (From the latest release and/or the current CVS sources.) +2. If you think you found a bug make sure it's not already filed in the + bugtracker at Savannah. +3. If you have a fix put the patch on Savannah. If it is a patch that affects + both core and arch specific stuff please separate them so that the core can + be applied separately while leaving the other patch 'open'. The prefered way + is to NOT touch archs you can't test and let maintainers take care of them. + This is a good way to see if they are used at all - the same goes for unix + netifs except tapif. +4. Do not file a bug and post a fix to it to the patch area. Either a bug report + or a patch will be enough. + If you correct an existing bug then attach the patch to the bug rather than creating a new entry in the patch area. +5. Trivial patches (compiler warning, indentation and spelling fixes or anything obvious which takes a line or two) + can go to the lwip-users list. This is still the fastest way of interaction and the list is not so crowded + as to allow for loss of fixes. Putting bugs on Savannah and subsequently closing them is too much an overhead + for reporting a compiler warning fix. +6. Patches should be specific to a single change or to related changes.Do not mix bugfixes with spelling and other + trivial fixes unless the bugfix is trivial too.Do not reorganize code and rename identifiers in the same patch you + change behaviour if not necessary.A patch is easier to read and understand if it's to the point and short than + if it's not to the point and long :) so the chances for it to be applied are greater. + +2.4 Platform porters: + +1. If you have ported lwIP to a platform (an OS, a uC/processor or a combination of these) and + you think it could benefit others[1] you might want discuss this on the mailing list. You + can also ask for CVS access to submit and maintain your port in the contrib CVS module. + \ No newline at end of file diff --git a/component/common/network/lwip/lwip_v1.3.2/doc/rawapi.txt b/component/common/network/lwip/lwip_v1.3.2/doc/rawapi.txt new file mode 100644 index 0000000..8eec6e7 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/doc/rawapi.txt @@ -0,0 +1,478 @@ +Raw TCP/IP interface for lwIP + +Authors: Adam Dunkels, Leon Woestenberg, Christiaan Simons + +lwIP provides three Application Program's Interfaces (APIs) for programs +to use for communication with the TCP/IP code: +* low-level "core" / "callback" or "raw" API. +* higher-level "sequential" API. +* BSD-style socket API. + +The sequential API provides a way for ordinary, sequential, programs +to use the lwIP stack. It is quite similar to the BSD socket API. The +model of execution is based on the blocking open-read-write-close +paradigm. Since the TCP/IP stack is event based by nature, the TCP/IP +code and the application program must reside in different execution +contexts (threads). + +The socket API is a compatibility API for existing applications, +currently it is built on top of the sequential API. It is meant to +provide all functions needed to run socket API applications running +on other platforms (e.g. unix / windows etc.). However, due to limitations +in the specification of this API, there might be incompatibilities +that require small modifications of existing programs. + +** Threading + +lwIP started targeting single-threaded environments. When adding multi- +threading support, instead of making the core thread-safe, another +approach was chosen: there is one main thread running the lwIP core +(also known as the "tcpip_thread"). The raw API may only be used from +this thread! Application threads using the sequential- or socket API +communicate with this main thread through message passing. + + As such, the list of functions that may be called from + other threads or an ISR is very limited! Only functions + from these API header files are thread-safe: + - api.h + - netbuf.h + - netdb.h + - netifapi.h + - sockets.h + - sys.h + + Additionaly, memory (de-)allocation functions may be + called from multiple threads (not ISR!) with NO_SYS=0 + since they are protected by SYS_LIGHTWEIGHT_PROT and/or + semaphores. + + Only since 1.3.0, if SYS_LIGHTWEIGHT_PROT is set to 1 + and LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT is set to 1, + pbuf_free() may also be called from another thread or + an ISR (since only then, mem_free - for PBUF_RAM - may + be called from an ISR: otherwise, the HEAP is only + protected by semaphores). + + +** The remainder of this document discusses the "raw" API. ** + +The raw TCP/IP interface allows the application program to integrate +better with the TCP/IP code. Program execution is event based by +having callback functions being called from within the TCP/IP +code. The TCP/IP code and the application program both run in the same +thread. The sequential API has a much higher overhead and is not very +well suited for small systems since it forces a multithreaded paradigm +on the application. + +The raw TCP/IP interface is not only faster in terms of code execution +time but is also less memory intensive. The drawback is that program +development is somewhat harder and application programs written for +the raw TCP/IP interface are more difficult to understand. Still, this +is the preferred way of writing applications that should be small in +code size and memory usage. + +Both APIs can be used simultaneously by different application +programs. In fact, the sequential API is implemented as an application +program using the raw TCP/IP interface. + +--- Callbacks + +Program execution is driven by callbacks. Each callback is an ordinary +C function that is called from within the TCP/IP code. Every callback +function is passed the current TCP or UDP connection state as an +argument. Also, in order to be able to keep program specific state, +the callback functions are called with a program specified argument +that is independent of the TCP/IP state. + +The function for setting the application connection state is: + +- void tcp_arg(struct tcp_pcb *pcb, void *arg) + + Specifies the program specific state that should be passed to all + other callback functions. The "pcb" argument is the current TCP + connection control block, and the "arg" argument is the argument + that will be passed to the callbacks. + + +--- TCP connection setup + +The functions used for setting up connections is similar to that of +the sequential API and of the BSD socket API. A new TCP connection +identifier (i.e., a protocol control block - PCB) is created with the +tcp_new() function. This PCB can then be either set to listen for new +incoming connections or be explicitly connected to another host. + +- struct tcp_pcb *tcp_new(void) + + Creates a new connection identifier (PCB). If memory is not + available for creating the new pcb, NULL is returned. + +- err_t tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, + u16_t port) + + Binds the pcb to a local IP address and port number. The IP address + can be specified as IP_ADDR_ANY in order to bind the connection to + all local IP addresses. + + If another connection is bound to the same port, the function will + return ERR_USE, otherwise ERR_OK is returned. + +- struct tcp_pcb *tcp_listen(struct tcp_pcb *pcb) + + Commands a pcb to start listening for incoming connections. When an + incoming connection is accepted, the function specified with the + tcp_accept() function will be called. The pcb will have to be bound + to a local port with the tcp_bind() function. + + The tcp_listen() function returns a new connection identifier, and + the one passed as an argument to the function will be + deallocated. The reason for this behavior is that less memory is + needed for a connection that is listening, so tcp_listen() will + reclaim the memory needed for the original connection and allocate a + new smaller memory block for the listening connection. + + tcp_listen() may return NULL if no memory was available for the + listening connection. If so, the memory associated with the pcb + passed as an argument to tcp_listen() will not be deallocated. + +- struct tcp_pcb *tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog) + + Same as tcp_listen, but limits the number of outstanding connections + in the listen queue to the value specified by the backlog argument. + To use it, your need to set TCP_LISTEN_BACKLOG=1 in your lwipopts.h. + +- void tcp_accepted(struct tcp_pcb *pcb) + + Inform lwIP that an incoming connection has been accepted. This would + usually be called from the accept callback. This allows lwIP to perform + housekeeping tasks, such as allowing further incoming connections to be + queued in the listen backlog. + +- void tcp_accept(struct tcp_pcb *pcb, + err_t (* accept)(void *arg, struct tcp_pcb *newpcb, + err_t err)) + + Specified the callback function that should be called when a new + connection arrives on a listening connection. + +- err_t tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, + u16_t port, err_t (* connected)(void *arg, + struct tcp_pcb *tpcb, + err_t err)); + + Sets up the pcb to connect to the remote host and sends the + initial SYN segment which opens the connection. + + The tcp_connect() function returns immediately; it does not wait for + the connection to be properly setup. Instead, it will call the + function specified as the fourth argument (the "connected" argument) + when the connection is established. If the connection could not be + properly established, either because the other host refused the + connection or because the other host didn't answer, the "err" + callback function of this pcb (registered with tcp_err, see below) + will be called. + + The tcp_connect() function can return ERR_MEM if no memory is + available for enqueueing the SYN segment. If the SYN indeed was + enqueued successfully, the tcp_connect() function returns ERR_OK. + + +--- Sending TCP data + +TCP data is sent by enqueueing the data with a call to +tcp_write(). When the data is successfully transmitted to the remote +host, the application will be notified with a call to a specified +callback function. + +- err_t tcp_write(struct tcp_pcb *pcb, void *dataptr, u16_t len, + u8_t copy) + + Enqueues the data pointed to by the argument dataptr. The length of + the data is passed as the len parameter. The copy argument is either + 0 or 1 and indicates whether the new memory should be allocated for + the data to be copied into. If the argument is 0, no new memory + should be allocated and the data should only be referenced by + pointer. + + The tcp_write() function will fail and return ERR_MEM if the length + of the data exceeds the current send buffer size or if the length of + the queue of outgoing segment is larger than the upper limit defined + in lwipopts.h. The number of bytes available in the output queue can + be retrieved with the tcp_sndbuf() function. + + The proper way to use this function is to call the function with at + most tcp_sndbuf() bytes of data. If the function returns ERR_MEM, + the application should wait until some of the currently enqueued + data has been successfully received by the other host and try again. + +- void tcp_sent(struct tcp_pcb *pcb, + err_t (* sent)(void *arg, struct tcp_pcb *tpcb, + u16_t len)) + + Specifies the callback function that should be called when data has + successfully been received (i.e., acknowledged) by the remote + host. The len argument passed to the callback function gives the + amount bytes that was acknowledged by the last acknowledgment. + + +--- Receiving TCP data + +TCP data reception is callback based - an application specified +callback function is called when new data arrives. When the +application has taken the data, it has to call the tcp_recved() +function to indicate that TCP can advertise increase the receive +window. + +- void tcp_recv(struct tcp_pcb *pcb, + err_t (* recv)(void *arg, struct tcp_pcb *tpcb, + struct pbuf *p, err_t err)) + + Sets the callback function that will be called when new data + arrives. The callback function will be passed a NULL pbuf to + indicate that the remote host has closed the connection. If + there are no errors and the callback function is to return + ERR_OK, then it must free the pbuf. Otherwise, it must not + free the pbuf so that lwIP core code can store it. + +- void tcp_recved(struct tcp_pcb *pcb, u16_t len) + + Must be called when the application has received the data. The len + argument indicates the length of the received data. + + +--- Application polling + +When a connection is idle (i.e., no data is either transmitted or +received), lwIP will repeatedly poll the application by calling a +specified callback function. This can be used either as a watchdog +timer for killing connections that have stayed idle for too long, or +as a method of waiting for memory to become available. For instance, +if a call to tcp_write() has failed because memory wasn't available, +the application may use the polling functionality to call tcp_write() +again when the connection has been idle for a while. + +- void tcp_poll(struct tcp_pcb *pcb, u8_t interval, + err_t (* poll)(void *arg, struct tcp_pcb *tpcb)) + + Specifies the polling interval and the callback function that should + be called to poll the application. The interval is specified in + number of TCP coarse grained timer shots, which typically occurs + twice a second. An interval of 10 means that the application would + be polled every 5 seconds. + + +--- Closing and aborting connections + +- err_t tcp_close(struct tcp_pcb *pcb) + + Closes the connection. The function may return ERR_MEM if no memory + was available for closing the connection. If so, the application + should wait and try again either by using the acknowledgment + callback or the polling functionality. If the close succeeds, the + function returns ERR_OK. + + The pcb is deallocated by the TCP code after a call to tcp_close(). + +- void tcp_abort(struct tcp_pcb *pcb) + + Aborts the connection by sending a RST (reset) segment to the remote + host. The pcb is deallocated. This function never fails. + +If a connection is aborted because of an error, the application is +alerted of this event by the err callback. Errors that might abort a +connection are when there is a shortage of memory. The callback +function to be called is set using the tcp_err() function. + +- void tcp_err(struct tcp_pcb *pcb, void (* err)(void *arg, + err_t err)) + + The error callback function does not get the pcb passed to it as a + parameter since the pcb may already have been deallocated. + + +--- Lower layer TCP interface + +TCP provides a simple interface to the lower layers of the +system. During system initialization, the function tcp_init() has +to be called before any other TCP function is called. When the system +is running, the two timer functions tcp_fasttmr() and tcp_slowtmr() +must be called with regular intervals. The tcp_fasttmr() should be +called every TCP_FAST_INTERVAL milliseconds (defined in tcp.h) and +tcp_slowtmr() should be called every TCP_SLOW_INTERVAL milliseconds. + + +--- UDP interface + +The UDP interface is similar to that of TCP, but due to the lower +level of complexity of UDP, the interface is significantly simpler. + +- struct udp_pcb *udp_new(void) + + Creates a new UDP pcb which can be used for UDP communication. The + pcb is not active until it has either been bound to a local address + or connected to a remote address. + +- void udp_remove(struct udp_pcb *pcb) + + Removes and deallocates the pcb. + +- err_t udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, + u16_t port) + + Binds the pcb to a local address. The IP-address argument "ipaddr" + can be IP_ADDR_ANY to indicate that it should listen to any local IP + address. The function currently always return ERR_OK. + +- err_t udp_connect(struct udp_pcb *pcb, struct ip_addr *ipaddr, + u16_t port) + + Sets the remote end of the pcb. This function does not generate any + network traffic, but only set the remote address of the pcb. + +- err_t udp_disconnect(struct udp_pcb *pcb) + + Remove the remote end of the pcb. This function does not generate + any network traffic, but only removes the remote address of the pcb. + +- err_t udp_send(struct udp_pcb *pcb, struct pbuf *p) + + Sends the pbuf p. The pbuf is not deallocated. + +- void udp_recv(struct udp_pcb *pcb, + void (* recv)(void *arg, struct udp_pcb *upcb, + struct pbuf *p, + struct ip_addr *addr, + u16_t port), + void *recv_arg) + + Specifies a callback function that should be called when a UDP + datagram is received. + + +--- System initalization + +A truly complete and generic sequence for initializing the lwip stack +cannot be given because it depends on the build configuration (lwipopts.h) +and additional initializations for your runtime environment (e.g. timers). + +We can give you some idea on how to proceed when using the raw API. +We assume a configuration using a single Ethernet netif and the +UDP and TCP transport layers, IPv4 and the DHCP client. + +Call these functions in the order of appearance: + +- stats_init() + + Clears the structure where runtime statistics are gathered. + +- sys_init() + + Not of much use since we set the NO_SYS 1 option in lwipopts.h, + to be called for easy configuration changes. + +- mem_init() + + Initializes the dynamic memory heap defined by MEM_SIZE. + +- memp_init() + + Initializes the memory pools defined by MEMP_NUM_x. + +- pbuf_init() + + Initializes the pbuf memory pool defined by PBUF_POOL_SIZE. + +- etharp_init() + + Initializes the ARP table and queue. + Note: you must call etharp_tmr at a ARP_TMR_INTERVAL (5 seconds) regular interval + after this initialization. + +- ip_init() + + Doesn't do much, it should be called to handle future changes. + +- udp_init() + + Clears the UDP PCB list. + +- tcp_init() + + Clears the TCP PCB list and clears some internal TCP timers. + Note: you must call tcp_fasttmr() and tcp_slowtmr() at the + predefined regular intervals after this initialization. + +- netif_add(struct netif *netif, struct ip_addr *ipaddr, + struct ip_addr *netmask, struct ip_addr *gw, + void *state, err_t (* init)(struct netif *netif), + err_t (* input)(struct pbuf *p, struct netif *netif)) + + Adds your network interface to the netif_list. Allocate a struct + netif and pass a pointer to this structure as the first argument. + Give pointers to cleared ip_addr structures when using DHCP, + or fill them with sane numbers otherwise. The state pointer may be NULL. + + The init function pointer must point to a initialization function for + your ethernet netif interface. The following code illustrates it's use. + + err_t netif_if_init(struct netif *netif) + { + u8_t i; + + for(i = 0; i < ETHARP_HWADDR_LEN; i++) netif->hwaddr[i] = some_eth_addr[i]; + init_my_eth_device(); + return ERR_OK; + } + + For ethernet drivers, the input function pointer must point to the lwip + function ethernet_input() declared in "netif/etharp.h". Other drivers + must use ip_input() declared in "lwip/ip.h". + +- netif_set_default(struct netif *netif) + + Registers the default network interface. + +- netif_set_up(struct netif *netif) + + When the netif is fully configured this function must be called. + +- dhcp_start(struct netif *netif) + + Creates a new DHCP client for this interface on the first call. + Note: you must call dhcp_fine_tmr() and dhcp_coarse_tmr() at + the predefined regular intervals after starting the client. + + You can peek in the netif->dhcp struct for the actual DHCP status. + + +--- Optimalization hints + +The first thing you want to optimize is the lwip_standard_checksum() +routine from src/core/inet.c. You can override this standard +function with the #define LWIP_CHKSUM . + +There are C examples given in inet.c or you might want to +craft an assembly function for this. RFC1071 is a good +introduction to this subject. + +Other significant improvements can be made by supplying +assembly or inline replacements for htons() and htonl() +if you're using a little-endian architecture. +#define LWIP_PLATFORM_BYTESWAP 1 +#define LWIP_PLATFORM_HTONS(x) +#define LWIP_PLATFORM_HTONL(x) + +Check your network interface driver if it reads at +a higher speed than the maximum wire-speed. If the +hardware isn't serviced frequently and fast enough +buffer overflows are likely to occur. + +E.g. when using the cs8900 driver, call cs8900if_service(ethif) +as frequently as possible. When using an RTOS let the cs8900 interrupt +wake a high priority task that services your driver using a binary +semaphore or event flag. Some drivers might allow additional tuning +to match your application and network. + +For a production release it is recommended to set LWIP_STATS to 0. +Note that speed performance isn't influenced much by simply setting +high values to the memory options. diff --git a/component/common/network/lwip/lwip_v1.3.2/doc/savannah.txt b/component/common/network/lwip/lwip_v1.3.2/doc/savannah.txt new file mode 100644 index 0000000..409905b --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/doc/savannah.txt @@ -0,0 +1,135 @@ +Daily Use Guide for using Savannah for lwIP + +Table of Contents: + +1 - Obtaining lwIP from the CVS repository +2 - Committers/developers CVS access using SSH (to be written) +3 - Merging from DEVEL branch to main trunk (stable branch) +4 - How to release lwIP + + + +1 Obtaining lwIP from the CVS repository +---------------------------------------- + +To perform an anonymous CVS checkout of the main trunk (this is where +bug fixes and incremental enhancements occur), do this: + +cvs -z3 -d:pserver:anonymous@cvs.sv.gnu.org:/sources/lwip checkout lwip + +Or, obtain a stable branch (updated with bug fixes only) as follows: +cvs -z3 -d:pserver:anonymous@cvs.sv.gnu.org:/sources/lwip checkout \ + -r STABLE-0_7 -d lwip-0.7 lwip + +Or, obtain a specific (fixed) release as follows: +cvs -z3 -d:pserver:anonymous@cvs.sv.gnu.org:/sources/lwip checkout \ + -r STABLE-0_7_0 -d lwip-0.7.0 lwip + +3 Committers/developers CVS access using SSH +-------------------------------------------- + +The Savannah server uses SSH (Secure Shell) protocol 2 authentication and encryption. +As such, CVS commits to the server occur through a SSH tunnel for project members. +To create a SSH2 key pair in UNIX-like environments, do this: + +ssh-keygen -t dsa + +Under Windows, a recommended SSH client is "PuTTY", freely available with good +documentation and a graphic user interface. Use its key generator. + +Now paste the id_dsa.pub contents into your Savannah account public key list. Wait +a while so that Savannah can update its configuration (This can take minutes). + +Try to login using SSH: + +ssh -v your_login@cvs.sv.gnu.org + +If it tells you: + +Authenticating with public key "your_key_name"... +Server refused to allocate pty + +then you could login; Savannah refuses to give you a shell - which is OK, as we +are allowed to use SSH for CVS only. Now, you should be able to do this: + +export CVS_RSH=ssh +cvs -z3 -d:ext:your_login@cvs.sv.gnu.org:/sources/lwip co lwip + +after which you can edit your local files with bug fixes or new features and +commit them. Make sure you know what you are doing when using CVS to make +changes on the repository. If in doubt, ask on the lwip-members mailing list. + +(If SSH asks about authenticity of the host, you can check the key + fingerprint against http://savannah.nongnu.org/cvs/?group=lwip) + + +3 Merging from DEVEL branch to main trunk (stable) +-------------------------------------------------- + +Merging is a delicate process in CVS and requires the +following disciplined steps in order to prevent conflicts +in the future. Conflicts can be hard to solve! + +Merging from branch A to branch B requires that the A branch +has a tag indicating the previous merger. This tag is called +'merged_from_A_to_B'. After merging, the tag is moved in the +A branch to remember this merger for future merge actions. + +IMPORTANT: AFTER COMMITTING A SUCCESFUL MERGE IN THE +REPOSITORY, THE TAG MUST BE SET ON THE SOURCE BRANCH OF THE +MERGE ACTION (REPLACING EXISTING TAGS WITH THE SAME NAME). + +Merge all changes in DEVEL since our last merge to main: + +In the working copy of the main trunk: +cvs update -P -jmerged_from_DEVEL_to_main -jDEVEL + +(This will apply the changes between 'merged_from_DEVEL_to_main' +and 'DEVEL' to your work set of files) + +We can now commit the merge result. +cvs commit -R -m "Merged from DEVEL to main." + +If this worked out OK, we now move the tag in the DEVEL branch +to this merge point, so we can use this point for future merges: + +cvs rtag -F -r DEVEL merged_from_DEVEL_to_main lwip + +4 How to release lwIP +--------------------- + +First, checkout a clean copy of the branch to be released. Tag this set with +tag name "STABLE-0_6_3". (I use release number 0.6.3 throughout this example). + +Login CVS using pserver authentication, then export a clean copy of the +tagged tree. Export is similar to a checkout, except that the CVS metadata +is not created locally. + +export CVS_RSH=ssh +cvs -z3 -d:pserver:anonymous@cvs.sv.gnu.org:/sources/lwip checkout \ + -r STABLE-0_6_3 -d lwip-0.6.3 lwip + +Archive this directory using tar, gzip'd, bzip2'd and zip'd. + +tar czvf lwip-0.6.3.tar.gz lwip-0.6.3 +tar cjvf lwip-0.6.3.tar.bz2 lwip-0.6.3 +zip -r lwip-0.6.3.zip lwip-0.6.3 + +Now, sign the archives with a detached GPG binary signature as follows: + +gpg -b lwip-0.6.3.tar.gz +gpg -b lwip-0.6.3.tar.bz2 +gpg -b lwip-0.6.3.zip + +Upload these files using anonymous FTP: +ncftp ftp://savannah.gnu.org/incoming/savannah/lwip + +ncftp>mput *0.6.3.* + +Additionally, you may post a news item on Savannah, like this: + +A new 0.6.3 release is now available here: +http://savannah.nongnu.org/files/?group=lwip&highlight=0.6.3 + +You will have to submit this via the user News interface, then approve +this via the Administrator News interface. \ No newline at end of file diff --git a/component/common/network/lwip/lwip_v1.3.2/doc/snmp_agent.txt b/component/common/network/lwip/lwip_v1.3.2/doc/snmp_agent.txt new file mode 100644 index 0000000..9b58616 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/doc/snmp_agent.txt @@ -0,0 +1,181 @@ +SNMPv1 agent for lwIP + +Author: Christiaan Simons + +This is a brief introduction how to use and configure the SNMP agent. +Note the agent uses the raw-API UDP interface so you may also want to +read rawapi.txt to gain a better understanding of the SNMP message handling. + +0 Agent Capabilities +==================== + +SNMPv1 per RFC1157 + This is an old(er) standard but is still widely supported. + For SNMPv2c and v3 have a greater complexity and need many + more lines of code. IMHO this breaks the idea of "lightweight IP". + + Note the S in SNMP stands for "Simple". Note that "Simple" is + relative. SNMP is simple compared to the complex ISO network + management protocols CMIP (Common Management Information Protocol) + and CMOT (CMip Over Tcp). + +MIB II per RFC1213 + The standard lwIP stack management information base. + This is a required MIB, so this is always enabled. + When builing lwIP without TCP, the mib-2.tcp group is omitted. + The groups EGP, CMOT and transmission are disabled by default. + + Most mib-2 objects are not writable except: + sysName, sysLocation, sysContact, snmpEnableAuthenTraps. + Writing to or changing the ARP and IP address and route + tables is not possible. + + Note lwIP has a very limited notion of IP routing. It currently + doen't have a route table and doesn't have a notion of the U,G,H flags. + Instead lwIP uses the interface list with only one default interface + acting as a single gateway interface (G) for the default route. + + The agent returns a "virtual table" with the default route 0.0.0.0 + for the default interface and network routes (no H) for each + network interface in the netif_list. + All routes are considered to be up (U). + +Loading additional MIBs + MIBs can only be added in compile-time, not in run-time. + There is no MIB compiler thus additional MIBs must be hand coded. + +Large SNMP message support + The packet decoding and encoding routines are designed + to use pbuf-chains. Larger payloads then the minimum + SNMP requirement of 484 octets are supported if the + PBUF_POOL_SIZE and IP_REASS_BUFSIZE are set to match your + local requirement. + +1 Building the Agent +==================== + +First of all you'll need to add the following define +to your local lwipopts.h: + +#define LWIP_SNMP 1 + +and add the source files in lwip/src/core/snmp +and some snmp headers in lwip/src/include/lwip to your makefile. + +Note you'll might need to adapt you network driver to update +the mib2 variables for your interface. + +2 Running the Agent +=================== + +The following function calls must be made in your program to +actually get the SNMP agent running. + +Before starting the agent you should supply pointers +to non-volatile memory for sysContact, sysLocation, +and snmpEnableAuthenTraps. You can do this by calling + +snmp_set_syscontact() +snmp_set_syslocation() +snmp_set_snmpenableauthentraps() + +Additionally you may want to set + +snmp_set_sysdescr() +snmp_set_sysobjid() (if you have a private MIB) +snmp_set_sysname() + +Also before starting the agent you need to setup +one or more trap destinations using these calls: + +snmp_trap_dst_enable(); +snmp_trap_dst_ip_set(); + +In the lwIP initialisation sequence call snmp_init() just after +the call to udp_init(). + +Exactly every 10 msec the SNMP uptime timestamp must be updated with +snmp_inc_sysuptime(). You should call this from a timer interrupt +or a timer signal handler depending on your runtime environment. + +An alternative way to update the SNMP uptime timestamp is to do a call like +snmp_add_sysuptime(100) each 1000ms (which is bigger "step", but call to +a lower frequency). Another one is to not call snmp_inc_sysuptime() or +snmp_add_sysuptime(), and to define the SNMP_GET_SYSUPTIME(sysuptime) macro. +This one is undefined by default in mib2.c. SNMP_GET_SYSUPTIME is called inside +snmp_get_sysuptime(u32_t *value), and enable to change "sysuptime" value only +when it's queried (any function which need "sysuptime" have to call +snmp_get_sysuptime). + + +3 Private MIBs +============== + +If want to extend the agent with your own private MIB you'll need to +add the following define to your local lwipopts.h: + +#define SNMP_PRIVATE_MIB 1 + +You must provide the private_mib.h and associated files yourself. +Note we don't have a "MIB compiler" that generates C source from a MIB, +so you're required to do some serious coding if you enable this! + +Note the lwIP enterprise ID (26381) is assigned to the lwIP project, +ALL OBJECT IDENTIFIERS LIVING UNDER THIS ID ARE ASSIGNED BY THE lwIP +MAINTAINERS! + +If you need to create your own private MIB you'll need +to apply for your own enterprise ID with IANA: http://www.iana.org/numbers.html + +You can set it by passing a struct snmp_obj_id to the agent +using snmp_set_sysobjid(&my_object_id), just before snmp_init(). + +Note the object identifiers for thes MIB-2 and your private MIB +tree must be kept in sorted ascending (lexicographical) order. +This to ensure correct getnext operation. + +An example for a private MIB is part of the "minimal Unix" project: +contrib/ports/unix/proj/minimal/lwip_prvmib.c + +The next chapter gives a more detailed description of the +MIB-2 tree and the optional private MIB. + +4 The Gory Details +================== + +4.0 Object identifiers and the MIB tree. + +We have three distinct parts for all object identifiers: + +The prefix + .iso.org.dod.internet + +the middle part + .mgmt.mib-2.ip.ipNetToMediaTable.ipNetToMediaEntry.ipNetToMediaPhysAddress + +and the index part + .1.192.168.0.1 + +Objects located above the .internet hierarchy aren't supported. +Currently only the .mgmt sub-tree is available and +when the SNMP_PRIVATE_MIB is enabled the .private tree +becomes available too. + +Object identifiers from incoming requests are checked +for a matching prefix, middle part and index part +or are expanded(*) for GetNext requests with short +or inexisting names in the request. +(* we call this "expansion" but this also +resembles the "auto-completion" operation) + +The middle part is usually located in ROM (const) +to preserve precious RAM on small microcontrollers. +However RAM location is possible for an dynamically +changing private tree. + +The index part is handled by functions which in +turn use dynamically allocated index trees from RAM. +These trees are updated by e.g. the etharp code +when new entries are made or removed form the ARP cache. + +/** @todo more gory details */ diff --git a/component/common/network/lwip/lwip_v1.3.2/doc/sys_arch.txt b/component/common/network/lwip/lwip_v1.3.2/doc/sys_arch.txt new file mode 100644 index 0000000..66310a9 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/doc/sys_arch.txt @@ -0,0 +1,228 @@ +sys_arch interface for lwIP 0.6++ + +Author: Adam Dunkels + +The operating system emulation layer provides a common interface +between the lwIP code and the underlying operating system kernel. The +general idea is that porting lwIP to new architectures requires only +small changes to a few header files and a new sys_arch +implementation. It is also possible to do a sys_arch implementation +that does not rely on any underlying operating system. + +The sys_arch provides semaphores and mailboxes to lwIP. For the full +lwIP functionality, multiple threads support can be implemented in the +sys_arch, but this is not required for the basic lwIP +functionality. Previous versions of lwIP required the sys_arch to +implement timer scheduling as well but as of lwIP 0.5 this is +implemented in a higher layer. + +In addition to the source file providing the functionality of sys_arch, +the OS emulation layer must provide several header files defining +macros used throughout lwip. The files required and the macros they +must define are listed below the sys_arch description. + +Semaphores can be either counting or binary - lwIP works with both +kinds. Mailboxes are used for message passing and can be implemented +either as a queue which allows multiple messages to be posted to a +mailbox, or as a rendez-vous point where only one message can be +posted at a time. lwIP works with both kinds, but the former type will +be more efficient. A message in a mailbox is just a pointer, nothing +more. + +Semaphores are represented by the type "sys_sem_t" which is typedef'd +in the sys_arch.h file. Mailboxes are equivalently represented by the +type "sys_mbox_t". lwIP does not place any restrictions on how +sys_sem_t or sys_mbox_t are represented internally. + +The following functions must be implemented by the sys_arch: + +- void sys_init(void) + + Is called to initialize the sys_arch layer. + +- sys_sem_t sys_sem_new(u8_t count) + + Creates and returns a new semaphore. The "count" argument specifies + the initial state of the semaphore. + +- void sys_sem_free(sys_sem_t sem) + + Deallocates a semaphore. + +- void sys_sem_signal(sys_sem_t sem) + + Signals a semaphore. + +- u32_t sys_arch_sem_wait(sys_sem_t sem, u32_t timeout) + + Blocks the thread while waiting for the semaphore to be + signaled. If the "timeout" argument is non-zero, the thread should + only be blocked for the specified time (measured in + milliseconds). If the "timeout" argument is zero, the thread should be + blocked until the semaphore is signalled. + + If the timeout argument is non-zero, the return value is the number of + milliseconds spent waiting for the semaphore to be signaled. If the + semaphore wasn't signaled within the specified time, the return value is + SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore + (i.e., it was already signaled), the function may return zero. + + Notice that lwIP implements a function with a similar name, + sys_sem_wait(), that uses the sys_arch_sem_wait() function. + +- sys_mbox_t sys_mbox_new(int size) + + Creates an empty mailbox for maximum "size" elements. Elements stored + in mailboxes are pointers. You have to define macros "_MBOX_SIZE" + in your lwipopts.h, or ignore this parameter in your implementation + and use a default size. + +- void sys_mbox_free(sys_mbox_t mbox) + + Deallocates a mailbox. If there are messages still present in the + mailbox when the mailbox is deallocated, it is an indication of a + programming error in lwIP and the developer should be notified. + +- void sys_mbox_post(sys_mbox_t mbox, void *msg) + + Posts the "msg" to the mailbox. This function have to block until + the "msg" is really posted. + +- err_t sys_mbox_trypost(sys_mbox_t mbox, void *msg) + + Try to post the "msg" to the mailbox. Returns ERR_MEM if this one + is full, else, ERR_OK if the "msg" is posted. + +- u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout) + + Blocks the thread until a message arrives in the mailbox, but does + not block the thread longer than "timeout" milliseconds (similar to + the sys_arch_sem_wait() function). If "timeout" is 0, the thread should + be blocked until a message arrives. The "msg" argument is a result + parameter that is set by the function (i.e., by doing "*msg = + ptr"). The "msg" parameter maybe NULL to indicate that the message + should be dropped. + + The return values are the same as for the sys_arch_sem_wait() function: + Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a + timeout. + + Note that a function with a similar name, sys_mbox_fetch(), is + implemented by lwIP. + +- u32_t sys_arch_mbox_tryfetch(sys_mbox_t mbox, void **msg) + + This is similar to sys_arch_mbox_fetch, however if a message is not + present in the mailbox, it immediately returns with the code + SYS_MBOX_EMPTY. On success 0 is returned. + + To allow for efficient implementations, this can be defined as a + function-like macro in sys_arch.h instead of a normal function. For + example, a naive implementation could be: + #define sys_arch_mbox_tryfetch(mbox,msg) \ + sys_arch_mbox_fetch(mbox,msg,1) + although this would introduce unnecessary delays. + +- struct sys_timeouts *sys_arch_timeouts(void) + + Returns a pointer to the per-thread sys_timeouts structure. In lwIP, + each thread has a list of timeouts which is repressented as a linked + list of sys_timeout structures. The sys_timeouts structure holds a + pointer to a linked list of timeouts. This function is called by + the lwIP timeout scheduler and must not return a NULL value. + + In a single thread sys_arch implementation, this function will + simply return a pointer to a global sys_timeouts variable stored in + the sys_arch module. + +If threads are supported by the underlying operating system and if +such functionality is needed in lwIP, the following function will have +to be implemented as well: + +- sys_thread_t sys_thread_new(char *name, void (* thread)(void *arg), void *arg, int stacksize, int prio) + + Starts a new thread named "name" with priority "prio" that will begin its + execution in the function "thread()". The "arg" argument will be passed as an + argument to the thread() function. The stack size to used for this thread is + the "stacksize" parameter. The id of the new thread is returned. Both the id + and the priority are system dependent. + +- sys_prot_t sys_arch_protect(void) + + This optional function does a "fast" critical region protection and returns + the previous protection level. This function is only called during very short + critical regions. An embedded system which supports ISR-based drivers might + want to implement this function by disabling interrupts. Task-based systems + might want to implement this by using a mutex or disabling tasking. This + function should support recursive calls from the same task or interrupt. In + other words, sys_arch_protect() could be called while already protected. In + that case the return value indicates that it is already protected. + + sys_arch_protect() is only required if your port is supporting an operating + system. + +- void sys_arch_unprotect(sys_prot_t pval) + + This optional function does a "fast" set of critical region protection to the + value specified by pval. See the documentation for sys_arch_protect() for + more information. This function is only required if your port is supporting + an operating system. + +Note: + +Be carefull with using mem_malloc() in sys_arch. When malloc() refers to +mem_malloc() you can run into a circular function call problem. In mem.c +mem_init() tries to allcate a semaphore using mem_malloc, which of course +can't be performed when sys_arch uses mem_malloc. + +------------------------------------------------------------------------------- +Additional files required for the "OS support" emulation layer: +------------------------------------------------------------------------------- + +cc.h - Architecture environment, some compiler specific, some + environment specific (probably should move env stuff + to sys_arch.h.) + + Typedefs for the types used by lwip - + u8_t, s8_t, u16_t, s16_t, u32_t, s32_t, mem_ptr_t + + Compiler hints for packing lwip's structures - + PACK_STRUCT_FIELD(x) + PACK_STRUCT_STRUCT + PACK_STRUCT_BEGIN + PACK_STRUCT_END + + Platform specific diagnostic output - + LWIP_PLATFORM_DIAG(x) - non-fatal, print a message. + LWIP_PLATFORM_ASSERT(x) - fatal, print message and abandon execution. + Portability defines for printf formatters: + U16_F, S16_F, X16_F, U32_F, S32_F, X32_F, SZT_F + + "lightweight" synchronization mechanisms - + SYS_ARCH_DECL_PROTECT(x) - declare a protection state variable. + SYS_ARCH_PROTECT(x) - enter protection mode. + SYS_ARCH_UNPROTECT(x) - leave protection mode. + + If the compiler does not provide memset() this file must include a + definition of it, or include a file which defines it. + + This file must either include a system-local which defines + the standard *nix error codes, or it should #define LWIP_PROVIDE_ERRNO + to make lwip/arch.h define the codes which are used throughout. + + +perf.h - Architecture specific performance measurement. + Measurement calls made throughout lwip, these can be defined to nothing. + PERF_START - start measuring something. + PERF_STOP(x) - stop measuring something, and record the result. + +sys_arch.h - Tied to sys_arch.c + + Arch dependent types for the following objects: + sys_sem_t, sys_mbox_t, sys_thread_t, + And, optionally: + sys_prot_t + + Defines to set vars of sys_mbox_t and sys_sem_t to NULL. + SYS_MBOX_NULL NULL + SYS_SEM_NULL NULL diff --git a/component/common/network/lwip/lwip_v1.3.2/port/realtek/arch/bpstruct.h b/component/common/network/lwip/lwip_v1.3.2/port/realtek/arch/bpstruct.h new file mode 100644 index 0000000..177758c --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/port/realtek/arch/bpstruct.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#if defined(__IAR_SYSTEMS_ICC__) +#pragma pack(1) +#endif + diff --git a/component/common/network/lwip/lwip_v1.3.2/port/realtek/arch/cc.h b/component/common/network/lwip/lwip_v1.3.2/port/realtek/arch/cc.h new file mode 100644 index 0000000..be882d9 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/port/realtek/arch/cc.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __CC_H__ +#define __CC_H__ + +#include "cpu.h" + +typedef unsigned char u8_t; +typedef signed char s8_t; +typedef unsigned short u16_t; +typedef signed short s16_t; +typedef unsigned int u32_t; +typedef signed long s32_t; +typedef u32_t mem_ptr_t; +typedef int sys_prot_t; + +#define U16_F "d" +#define S16_F "d" +#define X16_F "x" +#define U32_F "d" +#define S32_F "d" +#define X32_F "x" +#define SZT_F "uz" + +/* define compiler specific symbols */ +#if defined (__ICCARM__) +#if !defined (__IARSTDLIB__) +#define _STRING +#ifndef memcmp +#define memcmp(dst, src, sz) _memcmp(dst, src, sz) +#endif +#ifndef memset +#define memset(dst, val, sz) _memset(dst, val, sz) +#endif +#ifndef memcpy +#define memcpy(dst, src, sz) _memcpy(dst, src, sz) +#endif +#endif // __IARSTDLIB__ + +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_STRUCT +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x +#define PACK_STRUCT_USE_INCLUDES + +#elif defined (__CC_ARM) + +#define PACK_STRUCT_BEGIN __packed +#define PACK_STRUCT_STRUCT +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x + +#elif defined (__GNUC__) + +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_STRUCT __attribute__ ((__packed__)) +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x + +#elif defined (__TASKING__) + +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_STRUCT +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x + +#endif + +#define LWIP_PLATFORM_ASSERT(x) //do { if(!(x)) while(1); } while(0) + +#endif /* __CC_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/port/realtek/arch/cpu.h b/component/common/network/lwip/lwip_v1.3.2/port/realtek/arch/cpu.h new file mode 100644 index 0000000..a02f86d --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/port/realtek/arch/cpu.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __CPU_H__ +#define __CPU_H__ + +#define BYTE_ORDER LITTLE_ENDIAN + +#endif /* __CPU_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/port/realtek/arch/epstruct.h b/component/common/network/lwip/lwip_v1.3.2/port/realtek/arch/epstruct.h new file mode 100644 index 0000000..1e1a049 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/port/realtek/arch/epstruct.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#if defined(__IAR_SYSTEMS_ICC__) +#pragma pack() +#endif + diff --git a/component/common/network/lwip/lwip_v1.3.2/port/realtek/arch/init.h b/component/common/network/lwip/lwip_v1.3.2/port/realtek/arch/init.h new file mode 100644 index 0000000..e622c73 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/port/realtek/arch/init.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __ARCH_INIT_H__ +#define __ARCH_INIT_H__ + +#define TCPIP_INIT_DONE(arg) tcpip_init_done(arg) + +void tcpip_init_done(void *); +int wait_for_tcpip_init(void); + +#endif /* __ARCH_INIT_H__ */ + + + + diff --git a/component/common/network/lwip/lwip_v1.3.2/port/realtek/arch/lib.h b/component/common/network/lwip/lwip_v1.3.2/port/realtek/arch/lib.h new file mode 100644 index 0000000..378f25b --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/port/realtek/arch/lib.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LIB_H__ +#define __LIB_H__ + +#include + + +#endif /* __LIB_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/port/realtek/arch/perf.h b/component/common/network/lwip/lwip_v1.3.2/port/realtek/arch/perf.h new file mode 100644 index 0000000..334d42a --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/port/realtek/arch/perf.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __PERF_H__ +#define __PERF_H__ + +#define PERF_START /* null definition */ +#define PERF_STOP(x) /* null definition */ + +#endif /* __PERF_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/port/realtek/arch/sys_arch.h b/component/common/network/lwip/lwip_v1.3.2/port/realtek/arch/sys_arch.h new file mode 100644 index 0000000..83d0c08 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/port/realtek/arch/sys_arch.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __SYS_RTXC_H__ +#define __SYS_RTXC_H__ + +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "semphr.h" + +#define SYS_MBOX_NULL (xQueueHandle)0 +#define SYS_SEM_NULL (xSemaphoreHandle)0 +#define SYS_DEFAULT_THREAD_STACK_DEPTH configMINIMAL_STACK_SIZE + +typedef xSemaphoreHandle sys_sem_t; +typedef xQueueHandle sys_mbox_t; +typedef xTaskHandle sys_thread_t; + +typedef struct _sys_arch_state_t +{ + // Task creation data. + char cTaskName[configMAX_TASK_NAME_LEN]; + unsigned short nStackDepth; + unsigned short nTaskCount; +} sys_arch_state_t; + + + +//extern sys_arch_state_t s_sys_arch_state; + +//void sys_set_default_state(); +//void sys_set_state(signed char *pTaskName, unsigned short nStackSize); + +/* Message queue constants. */ +#define archMESG_QUEUE_LENGTH ( 6 ) +#endif /* __SYS_RTXC_H__ */ + diff --git a/component/common/network/lwip/lwip_v1.3.2/port/realtek/freertos/ethernetif.c b/component/common/network/lwip/lwip_v1.3.2/port/realtek/freertos/ethernetif.c new file mode 100644 index 0000000..a0f38bd --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/port/realtek/freertos/ethernetif.c @@ -0,0 +1,274 @@ +/** + * @file + * Ethernet Interface Skeleton + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/* + * This file is a skeleton for developing Ethernet network interface + * drivers for lwIP. Add code to the low_level functions and do a + * search-and-replace for the word "ethernetif" to replace it with + * something that better describes your network interface. + */ + +#include "lwip/opt.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/sys.h" +#include "lwip/tcpip.h" +#include "netif/etharp.h" +#include "err.h" +#include "ethernetif.h" +#include "queue.h" + +#include +#include + +#define netifMTU (1500) +#define netifINTERFACE_TASK_STACK_SIZE ( 350 ) +#define netifINTERFACE_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) +#define netifGUARD_BLOCK_TIME ( 250 ) +/* The time to block waiting for input. */ +#define emacBLOCK_TIME_WAITING_FOR_INPUT ( ( portTickType ) 100 ) + + +#ifdef CONFIG_CONCURRENT_MODE +#define IF2NAME0 'r' +#define IF2NAME1 '2' +#endif + +static void arp_timer(void *arg); + + +/** + * In this function, the hardware should be initialized. + * Called from ethernetif_init(). + * + * @param netif the already initialized lwip network interface structure + * for this ethernetif + */ + +static void low_level_init(struct netif *netif) +{ + + /* set netif MAC hardware address length */ + netif->hwaddr_len = ETHARP_HWADDR_LEN; + + /* set netif maximum transfer unit */ + netif->mtu = 1500; + + /* Accept broadcast address and ARP traffic */ + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; + + /* Wlan interface is initialized later */ +} + + +/** + * This function should do the actual transmission of the packet. The packet is + * contained in the pbuf that is passed to the function. This pbuf + * might be chained. + * + * @param netif the lwip network interface structure for this ethernetif + * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type) + * @return ERR_OK if the packet could be sent + * an err_t value if the packet couldn't be sent + * + * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to + * strange results. You might consider waiting for space in the DMA queue + * to become availale since the stack doesn't retry to send a packet + * dropped because of memory failure (except for the TCP timers). + */ + +static err_t low_level_output(struct netif *netif, struct pbuf *p) +{ + + + /* Refer to eCos lwip eth_drv_send() */ + struct eth_drv_sg sg_list[MAX_ETH_DRV_SG]; + int sg_len = 0; + struct pbuf *q; + + if(!rltk_wlan_running(netif_get_idx(netif))) + return ERR_IF; + + for (q = p; q != NULL && sg_len < MAX_ETH_DRV_SG; q = q->next) { + sg_list[sg_len].buf = (unsigned int) q->payload; + sg_list[sg_len++].len = q->len; + } + + if (sg_len) + rltk_wlan_send(netif_get_idx(netif), sg_list, sg_len, p->tot_len); + + return ERR_OK; +} + + +/** + * Should allocate a pbuf and transfer the bytes of the incoming + * packet from the interface into the pbuf. + * + * @param netif the lwip network interface structure for this ethernetif + * @return a pbuf filled with the received packet (including MAC header) + * NULL on memory error + */ +//static struct pbuf * low_level_input(struct netif *netif){} + + +/** + * This function is the ethernetif_input task, it is processed when a packet + * is ready to be read from the interface. It uses the function low_level_input() + * that should handle the actual reception of bytes from the network + * interface. Then the type of the received packet is determined and + * the appropriate input function is called. + * + * @param netif the lwip network interface structure for this ethernetif + */ +//void ethernetif_input( void * pvParameters ) + + +/* Refer to eCos eth_drv_recv to do similarly in ethernetif_input */ +void ethernetif_recv(struct netif *netif, int total_len) +{ + struct eth_drv_sg sg_list[MAX_ETH_DRV_SG]; + struct pbuf *p, *q; + int sg_len = 0; + + if(!rltk_wlan_running(netif_get_idx(netif))) + return; + + if ((total_len > MAX_ETH_MSG) || (total_len < 0)) + total_len = MAX_ETH_MSG; + + // Allocate buffer to store received packet + p = pbuf_alloc(PBUF_RAW, total_len, PBUF_POOL); + if (p == NULL) { + printf("\n\rCannot allocate pbuf to receive packet"); + return; + } + + // Create scatter list + for (q = p; q != NULL && sg_len < MAX_ETH_DRV_SG; q = q->next) { + sg_list[sg_len].buf = (unsigned int) q->payload; + sg_list[sg_len++].len = q->len; + } + + // Copy received packet to scatter list from wrapper rx skb + //printf("\n\rwlan:%c: Recv sg_len: %d, tot_len:%d", netif->name[1],sg_len, total_len); + rltk_wlan_recv(netif_get_idx(netif), sg_list, sg_len); + + // Pass received packet to the interface + if (ERR_OK != netif->input(p, netif)) + pbuf_free(p); + +} + +/** + * Should be called at the beginning of the program to set up the + * network interface. It calls the function low_level_init() to do the + * actual setup of the hardware. + * + * This function should be passed as a parameter to netif_add(). + * + * @param netif the lwip network interface structure for this ethernetif + * @return ERR_OK if the loopif is initialized + * ERR_MEM if private data couldn't be allocated + * any other err_t on error + */ +err_t ethernetif_init(struct netif *netif) +{ + LWIP_ASSERT("netif != NULL", (netif != NULL)); + +#if LWIP_NETIF_HOSTNAME + /* Initialize interface hostname */ + if(netif->name[1] == '0') + netif->hostname = "lwip0"; + else if(netif->name[1] == '1') + netif->hostname = "lwip1"; +#endif /* LWIP_NETIF_HOSTNAME */ + + netif->output = etharp_output; + netif->linkoutput = low_level_output; + + /* initialize the hardware */ + low_level_init(netif); + + etharp_init(); + + return ERR_OK; +} + +static void arp_timer(void *arg) +{ + etharp_tmr(); + sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); +} + +/* + * For FreeRTOS tickless + */ +int lwip_tickless_used = 0; + +int arp_timeout_exist(void) +{ + struct sys_timeouts *timeouts; + struct sys_timeo *t; + + timeouts = sys_arch_timeouts(); + + for(t = timeouts->next; t != NULL;t = t->next) + if(t->h == arp_timer) + return 1; + + return 0; +} + +//Called by rltk_wlan_PRE_SLEEP_PROCESSING() +void lwip_PRE_SLEEP_PROCESSING(void) +{ + if(arp_timeout_exist()) { + tcpip_untimeout(arp_timer, NULL); + } + lwip_tickless_used = 1; +} + +//Called in ips_leave() path, support tickless when wifi power wakeup due to ioctl or deinit +void lwip_POST_SLEEP_PROCESSING(void) +{ + if(lwip_tickless_used) { + tcpip_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); + } +} diff --git a/component/common/network/lwip/lwip_v1.3.2/port/realtek/freertos/ethernetif.h b/component/common/network/lwip/lwip_v1.3.2/port/realtek/freertos/ethernetif.h new file mode 100644 index 0000000..93139d1 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/port/realtek/freertos/ethernetif.h @@ -0,0 +1,13 @@ +#ifndef __ETHERNETIF_H__ +#define __ETHERNETIF_H__ + + +#include "lwip/err.h" +#include "lwip/netif.h" + +void ethernetif_recv(struct netif *netif, int total_len); +err_t ethernetif_init(struct netif *netif); +void lwip_PRE_SLEEP_PROCESSING(void); +void lwip_POST_SLEEP_PROCESSING(void); + +#endif diff --git a/component/common/network/lwip/lwip_v1.3.2/port/realtek/freertos/sys_arch.c b/component/common/network/lwip/lwip_v1.3.2/port/realtek/freertos/sys_arch.c new file mode 100644 index 0000000..1793f87 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/port/realtek/freertos/sys_arch.c @@ -0,0 +1,446 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/* lwIP includes. */ +#include "lwip/debug.h" +#include "lwip/def.h" +#include "lwip/sys.h" +#include "lwip/mem.h" +#include "lwip/stats.h" +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +xTaskHandle xTaskGetCurrentTaskHandle( void ) PRIVILEGED_FUNCTION; + +struct timeoutlist +{ + struct sys_timeouts timeouts; + xTaskHandle pid; +}; + +/* This is the number of threads that can be started with sys_thread_new() */ +#define SYS_THREAD_MAX 6 + +static struct timeoutlist s_timeoutlist[SYS_THREAD_MAX]; +static u16_t s_nextthread = 0; + + +/*-----------------------------------------------------------------------------------*/ +// Creates an empty mailbox. +sys_mbox_t sys_mbox_new(int size) +{ + xQueueHandle mbox; + + ( void ) size; + + mbox = xQueueCreate( archMESG_QUEUE_LENGTH, sizeof( void * ) ); + +#if SYS_STATS + ++lwip_stats.sys.mbox.used; + if (lwip_stats.sys.mbox.max < lwip_stats.sys.mbox.used) { + lwip_stats.sys.mbox.max = lwip_stats.sys.mbox.used; + } +#endif /* SYS_STATS */ + + return mbox; +} + +/*-----------------------------------------------------------------------------------*/ +/* + Deallocates a mailbox. If there are messages still present in the + mailbox when the mailbox is deallocated, it is an indication of a + programming error in lwIP and the developer should be notified. +*/ +void sys_mbox_free(sys_mbox_t mbox) +{ + if( uxQueueMessagesWaiting( mbox ) ) + { + /* Line for breakpoint. Should never break here! */ + portNOP(); +#if SYS_STATS + lwip_stats.sys.mbox.err++; +#endif /* SYS_STATS */ + + // TODO notify the user of failure. + } + + vQueueDelete( mbox ); + +#if SYS_STATS + --lwip_stats.sys.mbox.used; +#endif /* SYS_STATS */ +} + +/*-----------------------------------------------------------------------------------*/ +// Posts the "msg" to the mailbox. +void sys_mbox_post(sys_mbox_t mbox, void *data) +{ + while ( xQueueSendToBack(mbox, &data, portMAX_DELAY ) != pdTRUE ){} +} + + +/*-----------------------------------------------------------------------------------*/ +// Try to post the "msg" to the mailbox. +err_t sys_mbox_trypost(sys_mbox_t mbox, void *msg) +{ +err_t result; + + if ( xQueueSend( mbox, &msg, 0 ) == pdPASS ) + { + result = ERR_OK; + } + else { + // could not post, queue must be full + result = ERR_MEM; + +#if SYS_STATS + lwip_stats.sys.mbox.err++; +#endif /* SYS_STATS */ + + } + + return result; +} + +/*-----------------------------------------------------------------------------------*/ +/* + Blocks the thread until a message arrives in the mailbox, but does + not block the thread longer than "timeout" milliseconds (similar to + the sys_arch_sem_wait() function). The "msg" argument is a result + parameter that is set by the function (i.e., by doing "*msg = + ptr"). The "msg" parameter maybe NULL to indicate that the message + should be dropped. + + The return values are the same as for the sys_arch_sem_wait() function: + Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a + timeout. + + Note that a function with a similar name, sys_mbox_fetch(), is + implemented by lwIP. +*/ +u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout) +{ +void *dummyptr; +portTickType StartTime, EndTime, Elapsed; + + StartTime = xTaskGetTickCount(); + + if ( msg == NULL ) + { + msg = &dummyptr; + } + + if ( timeout != 0 ) + { + if ( pdTRUE == xQueueReceive( mbox, &(*msg), timeout / portTICK_RATE_MS ) ) + { + EndTime = xTaskGetTickCount(); + Elapsed = (EndTime - StartTime) * portTICK_RATE_MS; + + return ( Elapsed ); + } + else // timed out blocking for message + { + *msg = NULL; + + return SYS_ARCH_TIMEOUT; + } + } + else // block forever for a message. + { + while( pdTRUE != xQueueReceive( mbox, &(*msg), portMAX_DELAY ) ){} // time is arbitrary + EndTime = xTaskGetTickCount(); + Elapsed = (EndTime - StartTime) * portTICK_RATE_MS; + + return ( Elapsed ); // return time blocked TODO test + } +} + +/*-----------------------------------------------------------------------------------*/ +/* + Similar to sys_arch_mbox_fetch, but if message is not ready immediately, we'll + return with SYS_MBOX_EMPTY. On success, 0 is returned. +*/ +u32_t sys_arch_mbox_tryfetch(sys_mbox_t mbox, void **msg) +{ +void *dummyptr; + + if ( msg == NULL ) + { + msg = &dummyptr; + } + + if ( pdTRUE == xQueueReceive( mbox, &(*msg), 0 ) ) + { + return ERR_OK; + } + else + { + return SYS_MBOX_EMPTY; + } +} + +/*-----------------------------------------------------------------------------------*/ +// Creates and returns a new semaphore. The "count" argument specifies +// the initial state of the semaphore. +sys_sem_t sys_sem_new(u8_t count) +{ + xSemaphoreHandle xSemaphore; + + vSemaphoreCreateBinary( xSemaphore ); + + if( xSemaphore == NULL ) + { + +#if SYS_STATS + ++lwip_stats.sys.sem.err; +#endif /* SYS_STATS */ + + return SYS_SEM_NULL; // TODO need assert + } + + if(count == 0) // Means it can't be taken + { + xSemaphoreTake(xSemaphore,1); + } + +#if SYS_STATS + ++lwip_stats.sys.sem.used; + if (lwip_stats.sys.sem.max < lwip_stats.sys.sem.used) { + lwip_stats.sys.sem.max = lwip_stats.sys.sem.used; + } +#endif /* SYS_STATS */ + + return xSemaphore; +} + +/*-----------------------------------------------------------------------------------*/ +/* + Blocks the thread while waiting for the semaphore to be + signaled. If the "timeout" argument is non-zero, the thread should + only be blocked for the specified time (measured in + milliseconds). + + If the timeout argument is non-zero, the return value is the number of + milliseconds spent waiting for the semaphore to be signaled. If the + semaphore wasn't signaled within the specified time, the return value is + SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore + (i.e., it was already signaled), the function may return zero. + + Notice that lwIP implements a function with a similar name, + sys_sem_wait(), that uses the sys_arch_sem_wait() function. +*/ +u32_t sys_arch_sem_wait(sys_sem_t sem, u32_t timeout) +{ +portTickType StartTime, EndTime, Elapsed; + + StartTime = xTaskGetTickCount(); + + if( timeout != 0) + { + if( xSemaphoreTake( sem, timeout / portTICK_RATE_MS ) == pdTRUE ) + { + EndTime = xTaskGetTickCount(); + Elapsed = (EndTime - StartTime) * portTICK_RATE_MS; + + return (Elapsed); // return time blocked TODO test + } + else + { + return SYS_ARCH_TIMEOUT; + } + } + else // must block without a timeout + { + while( xSemaphoreTake( sem, portMAX_DELAY ) != pdTRUE ){} + EndTime = xTaskGetTickCount(); + Elapsed = (EndTime - StartTime) * portTICK_RATE_MS; + + return ( Elapsed ); // return time blocked + + } +} + +/*-----------------------------------------------------------------------------------*/ +// Signals a semaphore +void sys_sem_signal(sys_sem_t sem) +{ + xSemaphoreGive( sem ); +} + +/*-----------------------------------------------------------------------------------*/ +// Deallocates a semaphore +void sys_sem_free(sys_sem_t sem) +{ +#if SYS_STATS + --lwip_stats.sys.sem.used; +#endif /* SYS_STATS */ + + vQueueDelete( sem ); +} + +/*-----------------------------------------------------------------------------------*/ +// Initialize sys arch +void sys_init(void) +{ + int i; + + // Initialize the the per-thread sys_timeouts structures + // make sure there are no valid pids in the list + for(i = 0; i < SYS_THREAD_MAX; i++) + { + s_timeoutlist[i].pid = 0; + s_timeoutlist[i].timeouts.next = NULL; + } + + // keep track of how many threads have been created + s_nextthread = 0; +} + +/*-----------------------------------------------------------------------------------*/ +/* + Returns a pointer to the per-thread sys_timeouts structure. In lwIP, + each thread has a list of timeouts which is represented as a linked + list of sys_timeout structures. The sys_timeouts structure holds a + pointer to a linked list of timeouts. This function is called by + the lwIP timeout scheduler and must not return a NULL value. + + In a single threaded sys_arch implementation, this function will + simply return a pointer to a global sys_timeouts variable stored in + the sys_arch module. +*/ +struct sys_timeouts *sys_arch_timeouts(void) +{ +int i; +xTaskHandle pid; +struct timeoutlist *tl; + + pid = xTaskGetCurrentTaskHandle(); + + for(i = 0; i < s_nextthread; i++) + { + tl = &(s_timeoutlist[i]); + if(tl->pid == pid) + { + return &(tl->timeouts); + } + } + // Error + return NULL; +} + +/*-----------------------------------------------------------------------------------*/ +/*-----------------------------------------------------------------------------------*/ +// TODO +/*-----------------------------------------------------------------------------------*/ +/* + Starts a new thread with priority "prio" that will begin its execution in the + function "thread()". The "arg" argument will be passed as an argument to the + thread() function. The id of the new thread is returned. Both the id and + the priority are system dependent. +*/ +sys_thread_t sys_thread_new(char *name, void (* thread)(void *arg), void *arg, int stacksize, int prio) +{ +xTaskHandle CreatedTask; +int result; + + if ( s_nextthread < SYS_THREAD_MAX ) + { + vPortEnterCritical(); + result = xTaskCreate( thread, ( const portCHAR * ) name, stacksize, arg, prio, &CreatedTask ); + + // For each task created, store the task handle (pid) in the timers array. + // This scheme doesn't allow for threads to be deleted + s_timeoutlist[s_nextthread++].pid = CreatedTask; + vPortExitCritical(); + + if(result == pdPASS) + { + return CreatedTask; + } + else + { + return NULL; + } + } + else + { + return NULL; + } +} + +/* + This optional function does a "fast" critical region protection and returns + the previous protection level. This function is only called during very short + critical regions. An embedded system which supports ISR-based drivers might + want to implement this function by disabling interrupts. Task-based systems + might want to implement this by using a mutex or disabling tasking. This + function should support recursive calls from the same task or interrupt. In + other words, sys_arch_protect() could be called while already protected. In + that case the return value indicates that it is already protected. + + sys_arch_protect() is only required if your port is supporting an operating + system. +*/ +sys_prot_t sys_arch_protect(void) +{ + vPortEnterCritical(); + return 1; +} + +/* + This optional function does a "fast" set of critical region protection to the + value specified by pval. See the documentation for sys_arch_protect() for + more information. This function is only required if your port is supporting + an operating system. +*/ +void sys_arch_unprotect(sys_prot_t pval) +{ + ( void ) pval; + vPortExitCritical(); +} + +/* + * Prints an assertion messages and aborts execution. + */ +void sys_assert( const char *msg ) +{ + ( void ) msg; + /*FSL:only needed for debugging + printf(msg); + printf("\n\r"); + */ + vPortEnterCritical( ); + for(;;) + ; +} diff --git a/component/common/network/lwip/lwip_v1.3.2/port/realtek/freertos/sys_arch.h b/component/common/network/lwip/lwip_v1.3.2/port/realtek/freertos/sys_arch.h new file mode 100644 index 0000000..83d0c08 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/port/realtek/freertos/sys_arch.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __SYS_RTXC_H__ +#define __SYS_RTXC_H__ + +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "semphr.h" + +#define SYS_MBOX_NULL (xQueueHandle)0 +#define SYS_SEM_NULL (xSemaphoreHandle)0 +#define SYS_DEFAULT_THREAD_STACK_DEPTH configMINIMAL_STACK_SIZE + +typedef xSemaphoreHandle sys_sem_t; +typedef xQueueHandle sys_mbox_t; +typedef xTaskHandle sys_thread_t; + +typedef struct _sys_arch_state_t +{ + // Task creation data. + char cTaskName[configMAX_TASK_NAME_LEN]; + unsigned short nStackDepth; + unsigned short nTaskCount; +} sys_arch_state_t; + + + +//extern sys_arch_state_t s_sys_arch_state; + +//void sys_set_default_state(); +//void sys_set_state(signed char *pTaskName, unsigned short nStackSize); + +/* Message queue constants. */ +#define archMESG_QUEUE_LENGTH ( 6 ) +#endif /* __SYS_RTXC_H__ */ + diff --git a/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/arch/bpstruct.h b/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/arch/bpstruct.h new file mode 100644 index 0000000..177758c --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/arch/bpstruct.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#if defined(__IAR_SYSTEMS_ICC__) +#pragma pack(1) +#endif + diff --git a/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/arch/cc.h b/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/arch/cc.h new file mode 100644 index 0000000..3ca260f --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/arch/cc.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __CC_H__ +#define __CC_H__ + +#include "cpu.h" + +typedef unsigned char u8_t; +typedef signed char s8_t; +typedef unsigned short u16_t; +typedef signed short s16_t; +typedef unsigned long u32_t; +typedef signed long s32_t; +typedef u32_t mem_ptr_t; +typedef int sys_prot_t; + + +#define U16_F "hu" +#define S16_F "d" +#define X16_F "hx" +#define U32_F "u" +#define S32_F "d" +#define X32_F "x" +#define SZT_F "uz" + + + + + +/* define compiler specific symbols */ +#if defined (__ICCARM__) + +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_STRUCT +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x +#define PACK_STRUCT_USE_INCLUDES + +#elif defined (__CC_ARM) + +#define PACK_STRUCT_BEGIN __packed +#define PACK_STRUCT_STRUCT +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x + +#elif defined (__GNUC__) + +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_STRUCT __attribute__ ((__packed__)) +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x + +#elif defined (__TASKING__) + +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_STRUCT +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x + +#endif + +#define LWIP_PLATFORM_ASSERT(x) //do { if(!(x)) while(1); } while(0) + +#endif /* __CC_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/arch/cpu.h b/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/arch/cpu.h new file mode 100644 index 0000000..a02f86d --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/arch/cpu.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __CPU_H__ +#define __CPU_H__ + +#define BYTE_ORDER LITTLE_ENDIAN + +#endif /* __CPU_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/arch/epstruct.h b/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/arch/epstruct.h new file mode 100644 index 0000000..1e1a049 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/arch/epstruct.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#if defined(__IAR_SYSTEMS_ICC__) +#pragma pack() +#endif + diff --git a/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/arch/init.h b/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/arch/init.h new file mode 100644 index 0000000..e622c73 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/arch/init.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __ARCH_INIT_H__ +#define __ARCH_INIT_H__ + +#define TCPIP_INIT_DONE(arg) tcpip_init_done(arg) + +void tcpip_init_done(void *); +int wait_for_tcpip_init(void); + +#endif /* __ARCH_INIT_H__ */ + + + + diff --git a/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/arch/lib.h b/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/arch/lib.h new file mode 100644 index 0000000..378f25b --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/arch/lib.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LIB_H__ +#define __LIB_H__ + +#include + + +#endif /* __LIB_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/arch/perf.h b/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/arch/perf.h new file mode 100644 index 0000000..334d42a --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/arch/perf.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __PERF_H__ +#define __PERF_H__ + +#define PERF_START /* null definition */ +#define PERF_STOP(x) /* null definition */ + +#endif /* __PERF_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/arch/sys_arch.h b/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/arch/sys_arch.h new file mode 100644 index 0000000..83d0c08 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/arch/sys_arch.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __SYS_RTXC_H__ +#define __SYS_RTXC_H__ + +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "semphr.h" + +#define SYS_MBOX_NULL (xQueueHandle)0 +#define SYS_SEM_NULL (xSemaphoreHandle)0 +#define SYS_DEFAULT_THREAD_STACK_DEPTH configMINIMAL_STACK_SIZE + +typedef xSemaphoreHandle sys_sem_t; +typedef xQueueHandle sys_mbox_t; +typedef xTaskHandle sys_thread_t; + +typedef struct _sys_arch_state_t +{ + // Task creation data. + char cTaskName[configMAX_TASK_NAME_LEN]; + unsigned short nStackDepth; + unsigned short nTaskCount; +} sys_arch_state_t; + + + +//extern sys_arch_state_t s_sys_arch_state; + +//void sys_set_default_state(); +//void sys_set_state(signed char *pTaskName, unsigned short nStackSize); + +/* Message queue constants. */ +#define archMESG_QUEUE_LENGTH ( 6 ) +#endif /* __SYS_RTXC_H__ */ + diff --git a/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/freertos/ethernetif.c b/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/freertos/ethernetif.c new file mode 100644 index 0000000..9c6f99c --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/freertos/ethernetif.c @@ -0,0 +1,649 @@ +/** + * @file + * Ethernet Interface Skeleton + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/* + * This file is a skeleton for developing Ethernet network interface + * drivers for lwIP. Add code to the low_level functions and do a + * search-and-replace for the word "ethernetif" to replace it with + * something that better describes your network interface. + */ + +#include "lwip/opt.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/sys.h" +#include "lwip/tcpip.h" +#include "lwip/icmp.h" +#include "netif/etharp.h" +#include "err.h" +#include "ethernetif.h" +#include "queue.h" + +#include "main.h" // for the definition of CONFIG_WLAN + + +#if !CONFIG_WLAN +#include "stm32f2x7_eth.h" +#else +#include +#endif +#include + +#ifdef CONFIG_DONT_CARE_TP +#define netifMTU (576) +#else +#define netifMTU (1500) +#endif +#define netifINTERFACE_TASK_STACK_SIZE ( 350 ) +#define netifINTERFACE_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) +#define netifGUARD_BLOCK_TIME ( 250 ) +/* The time to block waiting for input. */ +#define emacBLOCK_TIME_WAITING_FOR_INPUT ( ( portTickType ) 100 ) +#define FAKE_PING_REPLY 0 + +#if !CONFIG_WLAN +/* Define those to better describe your network interface. */ +#define IFNAME0 's' +#define IFNAME1 't' + +static struct netif *s_pxNetIf = NULL; +xSemaphoreHandle s_xSemaphore = NULL; + + +/* Ethernet Rx & Tx DMA Descriptors */ +extern ETH_DMADESCTypeDef DMARxDscrTab[ETH_RXBUFNB], DMATxDscrTab[ETH_TXBUFNB]; + +/* Ethernet Receive buffers */ +extern uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE]; + +/* Ethernet Transmit buffers */ +extern uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE]; + +/* Global pointers to track current transmit and receive descriptors */ +extern ETH_DMADESCTypeDef *DMATxDescToSet; +extern ETH_DMADESCTypeDef *DMARxDescToGet; + +/* Global pointer for last received frame infos */ +extern ETH_DMA_Rx_Frame_infos *DMA_RX_FRAME_infos; + +static void ethernetif_input( void * pvParameters ); +#endif + +static void arp_timer(void *arg); + + +/** + * In this function, the hardware should be initialized. + * Called from ethernetif_init(). + * + * @param netif the already initialized lwip network interface structure + * for this ethernetif + */ + +static void low_level_init(struct netif *netif) +{ + + /* set netif MAC hardware address length */ + netif->hwaddr_len = ETHARP_HWADDR_LEN; + +#if !CONFIG_WLAN + /* set netif MAC hardware address */ + netif->hwaddr[0] = MAC_ADDR0; + netif->hwaddr[1] = MAC_ADDR1; + netif->hwaddr[2] = MAC_ADDR2; + netif->hwaddr[3] = MAC_ADDR3; + netif->hwaddr[4] = MAC_ADDR4; + netif->hwaddr[5] = MAC_ADDR5; +#endif + + /* set netif maximum transfer unit */ + netif->mtu = netifMTU; + + /* Accept broadcast address and ARP traffic */ + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; + +#if !CONFIG_WLAN + s_pxNetIf =netif; + + /* create binary semaphore used for informing ethernetif of frame reception */ + if (s_xSemaphore == NULL) + { + s_xSemaphore= xSemaphoreCreateCounting(20,0); + } + + /* initialize MAC address in ethernet MAC */ + ETH_MACAddressConfig(ETH_MAC_Address0, netif->hwaddr); + + /* Initialize Tx Descriptors list: Chain Mode */ + ETH_DMATxDescChainInit(DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB); + /* Initialize Rx Descriptors list: Chain Mode */ + ETH_DMARxDescChainInit(DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB); + + /* Enable Ethernet Rx interrrupt */ + { + uint32_t i; + for(i=0; itot_len, PBUF_POOL); + if (p == NULL) { + printf("\n\rCannot allocate pbuf to receive packet"); + return; + } + for (tq = q, tp = p, q_len = tq->len; tp != NULL ; tp = tp->next) + { + p_len = tp->len; + while(p_len) + { + if(q_len > p_len) { + memcpy((char*)tq->payload + (tq->len - q_len), (char*)tp->payload + (tp->len - p_len), p_len); + q_len -= p_len; + p_len = 0; + }else{ + memcpy((char*)tq->payload + (tq->len - q_len), (char*)tp->payload + (tp->len - p_len), q_len); + p_len -= q_len; + tq = tq->next; + q_len = tq->len; + } + } + } + p_eth = (struct eth_hdr *)p->payload; + q_eth = (struct eth_hdr *)q->payload; + p_arp = (struct etharp_hdr *)((char*)(p->payload) + sizeof(struct eth_hdr)); + q_arp = (struct etharp_hdr *)((char*)(q->payload) + sizeof(struct eth_hdr)); + + q_eth->dest = p_eth->src; + q_eth->src = fake_src_mac; + q_arp->opcode = htons(ARP_REPLY); + q_arp->shwaddr = fake_src_mac; + q_arp->sipaddr = p_arp->dipaddr; + q_arp->dhwaddr = p_eth->src; + q_arp->dipaddr = p_arp->sipaddr; + + if(0){ + int i; + char *buf = q->payload; + printf("\n\r"); + for(i=0;itot_len;i++) + printf("0x%02x, ", buf[i]); + printf("\n\r"); + } + if (ERR_OK != netif->input(q, netif)){ + printf("\n\rfake_arp_reply input error"); + pbuf_free(q); + }else + printf("\n\rfake arp reply \n\r"); +} + +void fake_echo_reply(struct netif *netif, struct pbuf *p) +{ + struct pbuf *q, *tq, *tp; + int q_len, p_len; + struct eth_hdr *p_eth, *q_eth; + struct ip_hdr *p_ip, *q_ip; + struct icmp_echo_hdr *p_echo, *q_echo; + + // Allocate buffer to store received packet + q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_POOL); + if (p == NULL) { + printf("\n\rCannot allocate pbuf to receive packet"); + return; + } + for (tq = q, tp = p, q_len = tq->len; tp != NULL ; tp = tp->next) + { + p_len = tp->len; + while(p_len) + { + if(q_len > p_len) { + memcpy((char*)tq->payload + (tq->len - q_len), (char*)tp->payload + (tp->len - p_len), p_len); + q_len -= p_len; + p_len = 0; + }else{ + memcpy((char*)tq->payload + (tq->len - q_len), (char*)tp->payload + (tp->len - p_len), q_len); + p_len -= q_len; + tq = tq->next; + q_len = tq->len; + } + } + } + p_eth = (struct eth_hdr *)p->payload; + q_eth = (struct eth_hdr *)q->payload; + p_ip = (struct ip_hdr *)((char*)(p->payload) + sizeof(struct eth_hdr)); + q_ip = (struct ip_hdr *)((char*)(q->payload) + sizeof(struct eth_hdr)); + p_echo = (struct icmp_echo_hdr *)((char*)(p->payload) + sizeof(struct eth_hdr) + sizeof(struct ip_hdr)); + q_echo = (struct icmp_echo_hdr *)((char*)(q->payload) + sizeof(struct eth_hdr) + sizeof(struct ip_hdr)); + + q_eth->dest = p_eth->src; + q_eth->src = p_eth->dest; + q_ip->src.addr = p_ip->dest.addr; + q_ip->dest.addr = p_ip->src.addr; + q_ip->_chksum = 0; + q_ip->_chksum = inet_chksum(q_ip, sizeof(struct ip_hdr)); + q_echo->type = ICMP_ER; + q_echo->code = 0; + q_echo->chksum = 0; + q_echo->chksum = inet_chksum(q_echo, q->tot_len - sizeof(struct eth_hdr) - sizeof(struct ip_hdr)); + + if(0){ + int i; + char *buf = q->payload; + printf("\n\r"); + for(i=0;itot_len;i++) + printf("0x%02x, ", buf[i]); + printf("\n\r"); + } + if (ERR_OK != netif->input(q, netif)){ + printf("\n\rfake_echo_reply input error"); + pbuf_free(q); + }else + printf("\n\rfake echo reply \n\r"); +} +#endif // #if FAKE_PING_REPLY + +/** + * This function should do the actual transmission of the packet. The packet is + * contained in the pbuf that is passed to the function. This pbuf + * might be chained. + * + * @param netif the lwip network interface structure for this ethernetif + * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type) + * @return ERR_OK if the packet could be sent + * an err_t value if the packet couldn't be sent + * + * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to + * strange results. You might consider waiting for space in the DMA queue + * to become availale since the stack doesn't retry to send a packet + * dropped because of memory failure (except for the TCP timers). + */ + +static err_t low_level_output(struct netif *netif, struct pbuf *p) +{ +#if !CONFIG_WLAN + static xSemaphoreHandle xTxSemaphore = NULL; + struct pbuf *q; + uint32_t l = 0; + u8 *buffer ; + + if (xTxSemaphore == NULL) + { + vSemaphoreCreateBinary (xTxSemaphore); + } + + if (xSemaphoreTake(xTxSemaphore, netifGUARD_BLOCK_TIME)) + { + buffer = (u8 *)(DMATxDescToSet->Buffer1Addr); + for(q = p; q != NULL; q = q->next) + { + memcpy((u8_t*)&buffer[l], q->payload, q->len); + l = l + q->len; + } + ETH_Prepare_Transmit_Descriptors(l); + xSemaphoreGive(xTxSemaphore); + } +#else + /* Refer to eCos lwip eth_drv_send() */ + struct eth_drv_sg sg_list[MAX_ETH_DRV_SG]; + int sg_len = 0; + struct pbuf *q; + + if(!rltk_wlan_running(netif_get_idx(netif))) + return ERR_IF; + + for (q = p; q != NULL && sg_len < MAX_ETH_DRV_SG; q = q->next) { + sg_list[sg_len].buf = (unsigned int) q->payload; + sg_list[sg_len++].len = q->len; + } + +#if FAKE_PING_REPLY + { + char *header = p->payload; + if(header[12] == 0x08 && header[13] == 0x06) + { // arp packet + if(header[21] == 0x01) + { // arp request packet + printf("\n\rfake_ping: arp request packet."); + if(0) + { + int i; + printf("\n\r"); + for (q = p; q != NULL; q = q->next) + { + char *buf = q->payload; + for(i=0;ilen;i++) + printf("0x%02x, ", buf[i]); + } + printf("\n\r"); + } + fake_arp_reply(netif, p); + return ERR_OK; + } + }else if(header[12] == 0x08 && header[13] == 0x00) + { // ip packet + if(header[15] == 0x00 && header[23] == 0x01) + { // icmp packet + printf("\n\rfake_ping: icmp packet."); + if(0){ + int i; + printf("\n\r"); + for (q = p; q != NULL; q = q->next) + { + char *buf = q->payload; + for(i=0;ilen;i++) + printf("0x%02x, ", buf[i]); + } + printf("\n\r"); + } + fake_echo_reply(netif, p); + return ERR_OK; + } + } + } +#endif // #if FAKE_PING_REPLY + if (sg_len) + rltk_wlan_send(netif_get_idx(netif), sg_list, sg_len, p->tot_len); +#endif // #if !CONFIG_WLAN + + return ERR_OK; +} + + +#if !CONFIG_WLAN +/** + * Should allocate a pbuf and transfer the bytes of the incoming + * packet from the interface into the pbuf. + * + * @param netif the lwip network interface structure for this ethernetif + * @return a pbuf filled with the received packet (including MAC header) + * NULL on memory error + */ +static struct pbuf * low_level_input(struct netif *netif) +{ + struct pbuf *p, *q; + u16_t len; + uint32_t l=0,i =0; + FrameTypeDef frame; + u8 *buffer; + __IO ETH_DMADESCTypeDef *DMARxNextDesc; + + p = NULL; + + /* Get received frame */ + frame = ETH_Get_Received_Frame_interrupt(); + + /* check that frame has no error */ + if ((frame.descriptor->Status & ETH_DMARxDesc_ES) == (uint32_t)RESET) + { + + /* Obtain the size of the packet and put it into the "len" variable. */ + len = frame.length; + buffer = (u8 *)frame.buffer; + + /* We allocate a pbuf chain of pbufs from the pool. */ + p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); + + /* Copy received frame from ethernet driver buffer to stack buffer */ + if (p != NULL) + { + for (q = p; q != NULL; q = q->next) + { + memcpy((u8_t*)q->payload, (u8_t*)&buffer[l], q->len); + l = l + q->len; + } + } + } + + /* Release descriptors to DMA */ + /* Check if received frame with multiple DMA buffer segments */ + if (DMA_RX_FRAME_infos->Seg_Count > 1) + { + DMARxNextDesc = DMA_RX_FRAME_infos->FS_Rx_Desc; + } + else + { + DMARxNextDesc = frame.descriptor; + } + + /* Set Own bit in Rx descriptors: gives the buffers back to DMA */ + for (i=0; iSeg_Count; i++) + { + DMARxNextDesc->Status = ETH_DMARxDesc_OWN; + DMARxNextDesc = (ETH_DMADESCTypeDef *)(DMARxNextDesc->Buffer2NextDescAddr); + } + + /* Clear Segment_Count */ + DMA_RX_FRAME_infos->Seg_Count =0; + + + /* When Rx Buffer unavailable flag is set: clear it and resume reception */ + if ((ETH->DMASR & ETH_DMASR_RBUS) != (u32)RESET) + { + /* Clear RBUS ETHERNET DMA flag */ + ETH->DMASR = ETH_DMASR_RBUS; + + /* Resume DMA reception */ + ETH->DMARPDR = 0; + } + return p; +} + + +/** + * This function is the ethernetif_input task, it is processed when a packet + * is ready to be read from the interface. It uses the function low_level_input() + * that should handle the actual reception of bytes from the network + * interface. Then the type of the received packet is determined and + * the appropriate input function is called. + * + * @param netif the lwip network interface structure for this ethernetif + */ +void ethernetif_input( void * pvParameters ) +{ + struct pbuf *p; + + for( ;; ) + { + if (xSemaphoreTake( s_xSemaphore, emacBLOCK_TIME_WAITING_FOR_INPUT)==pdTRUE) + { + p = low_level_input( s_pxNetIf ); + if (ERR_OK != s_pxNetIf->input( p, s_pxNetIf)) + { + pbuf_free(p); + p=NULL; + } + } + } +} +#endif + +/* Refer to eCos eth_drv_recv to do similarly in ethernetif_input */ +void ethernetif_recv(struct netif *netif, int total_len) +{ +#if CONFIG_WLAN + struct eth_drv_sg sg_list[MAX_ETH_DRV_SG]; + struct pbuf *p, *q; + int sg_len = 0; + + if(!rltk_wlan_running(netif_get_idx(netif))) + return; + + if ((total_len > MAX_ETH_MSG) || (total_len < 0)) + total_len = MAX_ETH_MSG; + + // Allocate buffer to store received packet + p = pbuf_alloc(PBUF_RAW, total_len, PBUF_POOL); + if (p == NULL) { + printf("\n\rCannot allocate pbuf to receive packet"); + return; + } + + // Create scatter list + for (q = p; q != NULL && sg_len < MAX_ETH_DRV_SG; q = q->next) { + sg_list[sg_len].buf = (unsigned int) q->payload; + sg_list[sg_len++].len = q->len; + } + + // Copy received packet to scatter list from wrapper rx skb + //printf("\n\rwlan:%c: Recv sg_len: %d, tot_len:%d", netif->name[1],sg_len, total_len); + rltk_wlan_recv(netif_get_idx(netif), sg_list, sg_len); + + // Pass received packet to the interface + if (ERR_OK != netif->input(p, netif)) + pbuf_free(p); +#endif +} + +/** + * Should be called at the beginning of the program to set up the + * network interface. It calls the function low_level_init() to do the + * actual setup of the hardware. + * + * This function should be passed as a parameter to netif_add(). + * + * @param netif the lwip network interface structure for this ethernetif + * @return ERR_OK if the loopif is initialized + * ERR_MEM if private data couldn't be allocated + * any other err_t on error + */ +err_t ethernetif_init(struct netif *netif) +{ + LWIP_ASSERT("netif != NULL", (netif != NULL)); + +#if !CONFIG_WLAN + /* ethernet */ + netif->name[0] = IFNAME0; + netif->name[1] = IFNAME1; +#else + /* wlan interface*/ +#if LWIP_NETIF_HOSTNAME + /* Initialize interface hostname */ + if(netif->name[1] == '0') + netif->hostname = "lwip0"; + else if(netif->name[1] == '1') + netif->hostname = "lwip1"; +#endif /* LWIP_NETIF_HOSTNAME */ + +#endif // WLAN + netif->output = etharp_output; + netif->linkoutput = low_level_output; + + /* initialize the hardware */ + low_level_init(netif); + + etharp_init(); + + return ERR_OK; +} + +static void arp_timer(void *arg) +{ + etharp_tmr(); + sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); +} + +/* + * For FreeRTOS tickless + */ +int lwip_tickless_used = 0; + +int arp_timeout_exist(void) +{ + struct sys_timeouts *timeouts; + struct sys_timeo *t; + + timeouts = sys_arch_timeouts(); + + for(t = timeouts->next; t != NULL;t = t->next) + if(t->h == arp_timer) + return 1; + + return 0; +} + +//Called by rltk_wlan_PRE_SLEEP_PROCESSING() +void lwip_PRE_SLEEP_PROCESSING(void) +{ + if(arp_timeout_exist()) { + tcpip_untimeout(arp_timer, NULL); + } + lwip_tickless_used = 1; +} + +//Called in ips_leave() path, support tickless when wifi power wakeup due to ioctl or deinit +void lwip_POST_SLEEP_PROCESSING(void) +{ + if(lwip_tickless_used) { + tcpip_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); + } +} + diff --git a/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/freertos/ethernetif.h b/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/freertos/ethernetif.h new file mode 100644 index 0000000..93139d1 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/freertos/ethernetif.h @@ -0,0 +1,13 @@ +#ifndef __ETHERNETIF_H__ +#define __ETHERNETIF_H__ + + +#include "lwip/err.h" +#include "lwip/netif.h" + +void ethernetif_recv(struct netif *netif, int total_len); +err_t ethernetif_init(struct netif *netif); +void lwip_PRE_SLEEP_PROCESSING(void); +void lwip_POST_SLEEP_PROCESSING(void); + +#endif diff --git a/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/freertos/sys_arch.c b/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/freertos/sys_arch.c new file mode 100644 index 0000000..c2792a8 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/freertos/sys_arch.c @@ -0,0 +1,446 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/* lwIP includes. */ +#include "lwip/debug.h" +#include "lwip/def.h" +#include "lwip/sys.h" +#include "lwip/mem.h" +#include "lwip/stats.h" +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +xTaskHandle xTaskGetCurrentTaskHandle( void ) PRIVILEGED_FUNCTION; + +struct timeoutlist +{ + struct sys_timeouts timeouts; + xTaskHandle pid; +}; + +/* This is the number of threads that can be started with sys_thread_new() */ +#define SYS_THREAD_MAX 6 + +static struct timeoutlist s_timeoutlist[SYS_THREAD_MAX]; +static u16_t s_nextthread = 0; + + +/*-----------------------------------------------------------------------------------*/ +// Creates an empty mailbox. +sys_mbox_t sys_mbox_new(int size) +{ + xQueueHandle mbox; + + ( void ) size; + + mbox = xQueueCreate( archMESG_QUEUE_LENGTH, sizeof( void * ) ); + +#if SYS_STATS + ++lwip_stats.sys.mbox.used; + if (lwip_stats.sys.mbox.max < lwip_stats.sys.mbox.used) { + lwip_stats.sys.mbox.max = lwip_stats.sys.mbox.used; + } +#endif /* SYS_STATS */ + + return mbox; +} + +/*-----------------------------------------------------------------------------------*/ +/* + Deallocates a mailbox. If there are messages still present in the + mailbox when the mailbox is deallocated, it is an indication of a + programming error in lwIP and the developer should be notified. +*/ +void sys_mbox_free(sys_mbox_t mbox) +{ + if( uxQueueMessagesWaiting( mbox ) ) + { + /* Line for breakpoint. Should never break here! */ + portNOP(); +#if SYS_STATS + lwip_stats.sys.mbox.err++; +#endif /* SYS_STATS */ + + // TODO notify the user of failure. + } + + vQueueDelete( mbox ); + +#if SYS_STATS + --lwip_stats.sys.mbox.used; +#endif /* SYS_STATS */ +} + +/*-----------------------------------------------------------------------------------*/ +// Posts the "msg" to the mailbox. +void sys_mbox_post(sys_mbox_t mbox, void *data) +{ + while ( xQueueSendToBack(mbox, &data, portMAX_DELAY ) != pdTRUE ){} +} + + +/*-----------------------------------------------------------------------------------*/ +// Try to post the "msg" to the mailbox. +err_t sys_mbox_trypost(sys_mbox_t mbox, void *msg) +{ +err_t result; + + if ( xQueueSend( mbox, &msg, 0 ) == pdPASS ) + { + result = ERR_OK; + } + else { + // could not post, queue must be full + result = ERR_MEM; + +#if SYS_STATS + lwip_stats.sys.mbox.err++; +#endif /* SYS_STATS */ + + } + + return result; +} + +/*-----------------------------------------------------------------------------------*/ +/* + Blocks the thread until a message arrives in the mailbox, but does + not block the thread longer than "timeout" milliseconds (similar to + the sys_arch_sem_wait() function). The "msg" argument is a result + parameter that is set by the function (i.e., by doing "*msg = + ptr"). The "msg" parameter maybe NULL to indicate that the message + should be dropped. + + The return values are the same as for the sys_arch_sem_wait() function: + Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a + timeout. + + Note that a function with a similar name, sys_mbox_fetch(), is + implemented by lwIP. +*/ +u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout) +{ +void *dummyptr; +portTickType StartTime, EndTime, Elapsed; + + StartTime = xTaskGetTickCount(); + + if ( msg == NULL ) + { + msg = &dummyptr; + } + + if ( timeout != 0 ) + { + if ( pdTRUE == xQueueReceive( mbox, &(*msg), timeout / portTICK_RATE_MS ) ) + { + EndTime = xTaskGetTickCount(); + Elapsed = (EndTime - StartTime) * portTICK_RATE_MS; + + return ( Elapsed ); + } + else // timed out blocking for message + { + *msg = NULL; + + return SYS_ARCH_TIMEOUT; + } + } + else // block forever for a message. + { + while( pdTRUE != xQueueReceive( mbox, &(*msg), portMAX_DELAY ) ){} // time is arbitrary + EndTime = xTaskGetTickCount(); + Elapsed = (EndTime - StartTime) * portTICK_RATE_MS; + + return ( Elapsed ); // return time blocked TODO test + } +} + +/*-----------------------------------------------------------------------------------*/ +/* + Similar to sys_arch_mbox_fetch, but if message is not ready immediately, we'll + return with SYS_MBOX_EMPTY. On success, 0 is returned. +*/ +u32_t sys_arch_mbox_tryfetch(sys_mbox_t mbox, void **msg) +{ +void *dummyptr; + + if ( msg == NULL ) + { + msg = &dummyptr; + } + + if ( pdTRUE == xQueueReceive( mbox, &(*msg), 0 ) ) + { + return ERR_OK; + } + else + { + return SYS_MBOX_EMPTY; + } +} + +/*-----------------------------------------------------------------------------------*/ +// Creates and returns a new semaphore. The "count" argument specifies +// the initial state of the semaphore. +sys_sem_t sys_sem_new(u8_t count) +{ + xSemaphoreHandle xSemaphore; + + vSemaphoreCreateBinary( xSemaphore ); + + if( xSemaphore == NULL ) + { + +#if SYS_STATS + ++lwip_stats.sys.sem.err; +#endif /* SYS_STATS */ + + return SYS_SEM_NULL; // TODO need assert + } + + if(count == 0) // Means it can't be taken + { + xSemaphoreTake(xSemaphore,1); + } + +#if SYS_STATS + ++lwip_stats.sys.sem.used; + if (lwip_stats.sys.sem.max < lwip_stats.sys.sem.used) { + lwip_stats.sys.sem.max = lwip_stats.sys.sem.used; + } +#endif /* SYS_STATS */ + + return xSemaphore; +} + +/*-----------------------------------------------------------------------------------*/ +/* + Blocks the thread while waiting for the semaphore to be + signaled. If the "timeout" argument is non-zero, the thread should + only be blocked for the specified time (measured in + milliseconds). + + If the timeout argument is non-zero, the return value is the number of + milliseconds spent waiting for the semaphore to be signaled. If the + semaphore wasn't signaled within the specified time, the return value is + SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore + (i.e., it was already signaled), the function may return zero. + + Notice that lwIP implements a function with a similar name, + sys_sem_wait(), that uses the sys_arch_sem_wait() function. +*/ +u32_t sys_arch_sem_wait(sys_sem_t sem, u32_t timeout) +{ +portTickType StartTime, EndTime, Elapsed; + + StartTime = xTaskGetTickCount(); + + if( timeout != 0) + { + if( xSemaphoreTake( sem, timeout / portTICK_RATE_MS ) == pdTRUE ) + { + EndTime = xTaskGetTickCount(); + Elapsed = (EndTime - StartTime) * portTICK_RATE_MS; + + return (Elapsed); // return time blocked TODO test + } + else + { + return SYS_ARCH_TIMEOUT; + } + } + else // must block without a timeout + { + while( xSemaphoreTake( sem, portMAX_DELAY ) != pdTRUE ){} + EndTime = xTaskGetTickCount(); + Elapsed = (EndTime - StartTime) * portTICK_RATE_MS; + + return ( Elapsed ); // return time blocked + + } +} + +/*-----------------------------------------------------------------------------------*/ +// Signals a semaphore +void sys_sem_signal(sys_sem_t sem) +{ + xSemaphoreGive( sem ); +} + +/*-----------------------------------------------------------------------------------*/ +// Deallocates a semaphore +void sys_sem_free(sys_sem_t sem) +{ +#if SYS_STATS + --lwip_stats.sys.sem.used; +#endif /* SYS_STATS */ + + vQueueDelete( sem ); +} + +/*-----------------------------------------------------------------------------------*/ +// Initialize sys arch +void sys_init(void) +{ + int i; + + // Initialize the the per-thread sys_timeouts structures + // make sure there are no valid pids in the list + for(i = 0; i < SYS_THREAD_MAX; i++) + { + s_timeoutlist[i].pid = 0; + s_timeoutlist[i].timeouts.next = NULL; + } + + // keep track of how many threads have been created + s_nextthread = 0; +} + +/*-----------------------------------------------------------------------------------*/ +/* + Returns a pointer to the per-thread sys_timeouts structure. In lwIP, + each thread has a list of timeouts which is represented as a linked + list of sys_timeout structures. The sys_timeouts structure holds a + pointer to a linked list of timeouts. This function is called by + the lwIP timeout scheduler and must not return a NULL value. + + In a single threaded sys_arch implementation, this function will + simply return a pointer to a global sys_timeouts variable stored in + the sys_arch module. +*/ +struct sys_timeouts *sys_arch_timeouts(void) +{ +int i; +xTaskHandle pid; +struct timeoutlist *tl; + + pid = xTaskGetCurrentTaskHandle(); + + for(i = 0; i < s_nextthread; i++) + { + tl = &(s_timeoutlist[i]); + if(tl->pid == pid) + { + return &(tl->timeouts); + } + } + // Error + return NULL; +} + +/*-----------------------------------------------------------------------------------*/ +/*-----------------------------------------------------------------------------------*/ +// TODO +/*-----------------------------------------------------------------------------------*/ +/* + Starts a new thread with priority "prio" that will begin its execution in the + function "thread()". The "arg" argument will be passed as an argument to the + thread() function. The id of the new thread is returned. Both the id and + the priority are system dependent. +*/ +sys_thread_t sys_thread_new(char *name, void (* thread)(void *arg), void *arg, int stacksize, int prio) +{ +xTaskHandle CreatedTask; +int result; + + if ( s_nextthread < SYS_THREAD_MAX ) + { + vPortEnterCritical(); + result = xTaskCreate( thread, ( char const * ) name, stacksize, arg, prio, &CreatedTask ); + + // For each task created, store the task handle (pid) in the timers array. + // This scheme doesn't allow for threads to be deleted + s_timeoutlist[s_nextthread++].pid = CreatedTask; + vPortExitCritical(); + + if(result == pdPASS) + { + return CreatedTask; + } + else + { + return NULL; + } + } + else + { + return NULL; + } +} + +/* + This optional function does a "fast" critical region protection and returns + the previous protection level. This function is only called during very short + critical regions. An embedded system which supports ISR-based drivers might + want to implement this function by disabling interrupts. Task-based systems + might want to implement this by using a mutex or disabling tasking. This + function should support recursive calls from the same task or interrupt. In + other words, sys_arch_protect() could be called while already protected. In + that case the return value indicates that it is already protected. + + sys_arch_protect() is only required if your port is supporting an operating + system. +*/ +sys_prot_t sys_arch_protect(void) +{ + vPortEnterCritical(); + return 1; +} + +/* + This optional function does a "fast" set of critical region protection to the + value specified by pval. See the documentation for sys_arch_protect() for + more information. This function is only required if your port is supporting + an operating system. +*/ +void sys_arch_unprotect(sys_prot_t pval) +{ + ( void ) pval; + vPortExitCritical(); +} + +/* + * Prints an assertion messages and aborts execution. + */ +void sys_assert( const char *msg ) +{ + ( void ) msg; + /*FSL:only needed for debugging + printf(msg); + printf("\n\r"); + */ + vPortEnterCritical( ); + for(;;) + ; +} diff --git a/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/freertos/sys_arch.h b/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/freertos/sys_arch.h new file mode 100644 index 0000000..83d0c08 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/freertos/sys_arch.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __SYS_RTXC_H__ +#define __SYS_RTXC_H__ + +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "semphr.h" + +#define SYS_MBOX_NULL (xQueueHandle)0 +#define SYS_SEM_NULL (xSemaphoreHandle)0 +#define SYS_DEFAULT_THREAD_STACK_DEPTH configMINIMAL_STACK_SIZE + +typedef xSemaphoreHandle sys_sem_t; +typedef xQueueHandle sys_mbox_t; +typedef xTaskHandle sys_thread_t; + +typedef struct _sys_arch_state_t +{ + // Task creation data. + char cTaskName[configMAX_TASK_NAME_LEN]; + unsigned short nStackDepth; + unsigned short nTaskCount; +} sys_arch_state_t; + + + +//extern sys_arch_state_t s_sys_arch_state; + +//void sys_set_default_state(); +//void sys_set_state(signed char *pTaskName, unsigned short nStackSize); + +/* Message queue constants. */ +#define archMESG_QUEUE_LENGTH ( 6 ) +#endif /* __SYS_RTXC_H__ */ + diff --git a/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/standalone/ethernetif.c b/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/standalone/ethernetif.c new file mode 100644 index 0000000..5100fb2 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/standalone/ethernetif.c @@ -0,0 +1,304 @@ +/** + * @file + * Ethernet Interface for standalone applications (without RTOS) - works only for + * ethernet polling mode (polling for ethernet frame reception) + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/mem.h" +#include "netif/etharp.h" +#include "ethernetif.h" +#include "stm32f2x7_eth.h" +#include "main.h" +#include + +/* Network interface name */ +#define IFNAME0 's' +#define IFNAME1 't' + + +/* Ethernet Rx & Tx DMA Descriptors */ +extern ETH_DMADESCTypeDef DMARxDscrTab[ETH_RXBUFNB], DMATxDscrTab[ETH_TXBUFNB]; + +/* Ethernet Driver Receive buffers */ +extern uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE]; + +/* Ethernet Driver Transmit buffers */ +extern uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE]; + +/* Global pointers to track current transmit and receive descriptors */ +extern ETH_DMADESCTypeDef *DMATxDescToSet; +extern ETH_DMADESCTypeDef *DMARxDescToGet; + +/* Global pointer for last received frame infos */ +extern ETH_DMA_Rx_Frame_infos *DMA_RX_FRAME_infos; + + + + +/** + * In this function, the hardware should be initialized. + * Called from ethernetif_init(). + * + * @param netif the already initialized lwip network interface structure + * for this ethernetif + */ +static void low_level_init(struct netif *netif) +{ +#ifdef CHECKSUM_BY_HARDWARE + int i; +#endif + /* set MAC hardware address length */ + netif->hwaddr_len = ETHARP_HWADDR_LEN; + + /* set MAC hardware address */ + netif->hwaddr[0] = MAC_ADDR0; + netif->hwaddr[1] = MAC_ADDR1; + netif->hwaddr[2] = MAC_ADDR2; + netif->hwaddr[3] = MAC_ADDR3; + netif->hwaddr[4] = MAC_ADDR4; + netif->hwaddr[5] = MAC_ADDR5; + + /* initialize MAC address in ethernet MAC */ + ETH_MACAddressConfig(ETH_MAC_Address0, netif->hwaddr); + + /* maximum transfer unit */ + netif->mtu = 1500; + + /* device capabilities */ + /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; + + /* Initialize Tx Descriptors list: Chain Mode */ + ETH_DMATxDescChainInit(DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB); + /* Initialize Rx Descriptors list: Chain Mode */ + ETH_DMARxDescChainInit(DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB); + +#ifdef CHECKSUM_BY_HARDWARE + /* Enable the TCP, UDP and ICMP checksum insertion for the Tx frames */ + for(i=0; iBuffer1Addr); + + /* copy frame from pbufs to driver buffers */ + for(q = p; q != NULL; q = q->next) + { + memcpy((u8_t*)&buffer[framelength], q->payload, q->len); + framelength = framelength + q->len; + } + + /* Note: padding and CRC for transmitted frame + are automatically inserted by DMA */ + + /* Prepare transmit descriptors to give to DMA*/ + ETH_Prepare_Transmit_Descriptors(framelength); + + return ERR_OK; +} + +/** + * Should allocate a pbuf and transfer the bytes of the incoming + * packet from the interface into the pbuf. + * + * @param netif the lwip network interface structure for this ethernetif + * @return a pbuf filled with the received packet (including MAC header) + * NULL on memory error + */ +static struct pbuf * low_level_input(struct netif *netif) +{ + struct pbuf *p, *q; + u16_t len; + int l =0; + FrameTypeDef frame; + u8 *buffer; + uint32_t i=0; + __IO ETH_DMADESCTypeDef *DMARxNextDesc; + + + p = NULL; + + /* get received frame */ + frame = ETH_Get_Received_Frame(); + + /* Obtain the size of the packet and put it into the "len" variable. */ + len = frame.length; + buffer = (u8 *)frame.buffer; + + /* We allocate a pbuf chain of pbufs from the Lwip buffer pool */ + p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); + + /* copy received frame to pbuf chain */ + if (p != NULL) + { + for (q = p; q != NULL; q = q->next) + { + memcpy((u8_t*)q->payload, (u8_t*)&buffer[l], q->len); + l = l + q->len; + } + } + + /* Release descriptors to DMA */ + /* Check if frame with multiple DMA buffer segments */ + if (DMA_RX_FRAME_infos->Seg_Count > 1) + { + DMARxNextDesc = DMA_RX_FRAME_infos->FS_Rx_Desc; + } + else + { + DMARxNextDesc = frame.descriptor; + } + + /* Set Own bit in Rx descriptors: gives the buffers back to DMA */ + for (i=0; iSeg_Count; i++) + { + DMARxNextDesc->Status = ETH_DMARxDesc_OWN; + DMARxNextDesc = (ETH_DMADESCTypeDef *)(DMARxNextDesc->Buffer2NextDescAddr); + } + + /* Clear Segment_Count */ + DMA_RX_FRAME_infos->Seg_Count =0; + + /* When Rx Buffer unavailable flag is set: clear it and resume reception */ + if ((ETH->DMASR & ETH_DMASR_RBUS) != (u32)RESET) + { + /* Clear RBUS ETHERNET DMA flag */ + ETH->DMASR = ETH_DMASR_RBUS; + /* Resume DMA reception */ + ETH->DMARPDR = 0; + } + return p; +} + +/** + * This function should be called when a packet is ready to be read + * from the interface. It uses the function low_level_input() that + * should handle the actual reception of bytes from the network + * interface. Then the type of the received packet is determined and + * the appropriate input function is called. + * + * @param netif the lwip network interface structure for this ethernetif + */ +err_t ethernetif_input(struct netif *netif) +{ + err_t err; + struct pbuf *p; + + /* move received packet into a new pbuf */ + p = low_level_input(netif); + + /* no packet could be read, silently ignore this */ + if (p == NULL) return ERR_MEM; + + /* entry point to the LwIP stack */ + err = netif->input(p, netif); + + if (err != ERR_OK) + { + LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); + pbuf_free(p); + p = NULL; + } + return err; +} + +/** + * Should be called at the beginning of the program to set up the + * network interface. It calls the function low_level_init() to do the + * actual setup of the hardware. + * + * This function should be passed as a parameter to netif_add(). + * + * @param netif the lwip network interface structure for this ethernetif + * @return ERR_OK if the loopif is initialized + * ERR_MEM if private data couldn't be allocated + * any other err_t on error + */ +err_t ethernetif_init(struct netif *netif) +{ + LWIP_ASSERT("netif != NULL", (netif != NULL)); + +#if LWIP_NETIF_HOSTNAME + /* Initialize interface hostname */ + netif->hostname = "lwip"; +#endif /* LWIP_NETIF_HOSTNAME */ + + netif->name[0] = IFNAME0; + netif->name[1] = IFNAME1; + /* We directly use etharp_output() here to save a function call. + * You can instead declare your own function an call etharp_output() + * from it if you have to do some checks before sending (e.g. if link + * is available...) */ + netif->output = etharp_output; + netif->linkoutput = low_level_output; + + /* initialize the hardware */ + low_level_init(netif); + + return ERR_OK; +} + + + diff --git a/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/standalone/ethernetif.h b/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/standalone/ethernetif.h new file mode 100644 index 0000000..9ff1408 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/port/stm32f2x7/standalone/ethernetif.h @@ -0,0 +1,11 @@ +#ifndef __ETHERNETIF_H__ +#define __ETHERNETIF_H__ + + +#include "lwip/err.h" +#include "lwip/netif.h" + +err_t ethernetif_init(struct netif *netif); +err_t ethernetif_input(struct netif *netif); + +#endif diff --git a/component/common/network/lwip/lwip_v1.3.2/src/api/api_lib.c b/component/common/network/lwip/lwip_v1.3.2/src/api/api_lib.c new file mode 100644 index 0000000..8947902 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/api/api_lib.c @@ -0,0 +1,568 @@ +/* + * @file + * Sequential API External module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/* This is the part of the API that is linked with + the application */ + +#include "lwip/opt.h" + +#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/api.h" +#include "lwip/tcpip.h" +#include "lwip/memp.h" + +#include "lwip/ip.h" +#include "lwip/raw.h" +#include "lwip/udp.h" +#include "lwip/tcp.h" + +#include + +/** + * Create a new netconn (of a specific type) that has a callback function. + * The corresponding pcb is also created. + * + * @param t the type of 'connection' to create (@see enum netconn_type) + * @param proto the IP protocol for RAW IP pcbs + * @param callback a function to call on status changes (RX available, TX'ed) + * @return a newly allocated struct netconn or + * NULL on memory error + */ +struct netconn* +netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_callback callback) +{ + struct netconn *conn; + struct api_msg msg; + + conn = netconn_alloc(t, callback); + if (conn != NULL ) { + msg.function = do_newconn; + msg.msg.msg.n.proto = proto; + msg.msg.conn = conn; + TCPIP_APIMSG(&msg); + + if (conn->err != ERR_OK) { + LWIP_ASSERT("freeing conn without freeing pcb", conn->pcb.tcp == NULL); + LWIP_ASSERT("conn has no op_completed", conn->op_completed != SYS_SEM_NULL); + LWIP_ASSERT("conn has no recvmbox", conn->recvmbox != SYS_MBOX_NULL); + LWIP_ASSERT("conn->acceptmbox shouldn't exist", conn->acceptmbox == SYS_MBOX_NULL); + sys_sem_free(conn->op_completed); + sys_mbox_free(conn->recvmbox); + memp_free(MEMP_NETCONN, conn); + return NULL; + } + } + return conn; +} + +/** + * Close a netconn 'connection' and free its resources. + * UDP and RAW connection are completely closed, TCP pcbs might still be in a waitstate + * after this returns. + * + * @param conn the netconn to delete + * @return ERR_OK if the connection was deleted + */ +err_t +netconn_delete(struct netconn *conn) +{ + struct api_msg msg; + + /* No ASSERT here because possible to get a (conn == NULL) if we got an accept error */ + if (conn == NULL) { + return ERR_OK; + } + + msg.function = do_delconn; + msg.msg.conn = conn; + tcpip_apimsg(&msg); + + conn->pcb.tcp = NULL; + netconn_free(conn); + + return ERR_OK; +} + +/** + * Get the local or remote IP address and port of a netconn. + * For RAW netconns, this returns the protocol instead of a port! + * + * @param conn the netconn to query + * @param addr a pointer to which to save the IP address + * @param port a pointer to which to save the port (or protocol for RAW) + * @param local 1 to get the local IP address, 0 to get the remote one + * @return ERR_CONN for invalid connections + * ERR_OK if the information was retrieved + */ +err_t +netconn_getaddr(struct netconn *conn, struct ip_addr *addr, u16_t *port, u8_t local) +{ + struct api_msg msg; + + LWIP_ERROR("netconn_getaddr: invalid conn", (conn != NULL), return ERR_ARG;); + LWIP_ERROR("netconn_getaddr: invalid addr", (addr != NULL), return ERR_ARG;); + LWIP_ERROR("netconn_getaddr: invalid port", (port != NULL), return ERR_ARG;); + + msg.function = do_getaddr; + msg.msg.conn = conn; + msg.msg.msg.ad.ipaddr = addr; + msg.msg.msg.ad.port = port; + msg.msg.msg.ad.local = local; + TCPIP_APIMSG(&msg); + + return conn->err; +} + +/** + * Bind a netconn to a specific local IP address and port. + * Binding one netconn twice might not always be checked correctly! + * + * @param conn the netconn to bind + * @param addr the local IP address to bind the netconn to (use IP_ADDR_ANY + * to bind to all addresses) + * @param port the local port to bind the netconn to (not used for RAW) + * @return ERR_OK if bound, any other err_t on failure + */ +err_t +netconn_bind(struct netconn *conn, struct ip_addr *addr, u16_t port) +{ + struct api_msg msg; + + LWIP_ERROR("netconn_bind: invalid conn", (conn != NULL), return ERR_ARG;); + + msg.function = do_bind; + msg.msg.conn = conn; + msg.msg.msg.bc.ipaddr = addr; + msg.msg.msg.bc.port = port; + TCPIP_APIMSG(&msg); + return conn->err; +} + +/** + * Connect a netconn to a specific remote IP address and port. + * + * @param conn the netconn to connect + * @param addr the remote IP address to connect to + * @param port the remote port to connect to (no used for RAW) + * @return ERR_OK if connected, return value of tcp_/udp_/raw_connect otherwise + */ +err_t +netconn_connect(struct netconn *conn, struct ip_addr *addr, u16_t port) +{ + struct api_msg msg; + + LWIP_ERROR("netconn_connect: invalid conn", (conn != NULL), return ERR_ARG;); + + msg.function = do_connect; + msg.msg.conn = conn; + msg.msg.msg.bc.ipaddr = addr; + msg.msg.msg.bc.port = port; + /* This is the only function which need to not block tcpip_thread */ + tcpip_apimsg(&msg); + return conn->err; +} + +/** + * Disconnect a netconn from its current peer (only valid for UDP netconns). + * + * @param conn the netconn to disconnect + * @return TODO: return value is not set here... + */ +err_t +netconn_disconnect(struct netconn *conn) +{ + struct api_msg msg; + + LWIP_ERROR("netconn_disconnect: invalid conn", (conn != NULL), return ERR_ARG;); + + msg.function = do_disconnect; + msg.msg.conn = conn; + TCPIP_APIMSG(&msg); + return conn->err; +} + +/** + * Set a TCP netconn into listen mode + * + * @param conn the tcp netconn to set to listen mode + * @param backlog the listen backlog, only used if TCP_LISTEN_BACKLOG==1 + * @return ERR_OK if the netconn was set to listen (UDP and RAW netconns + * don't return any error (yet?)) + */ +err_t +netconn_listen_with_backlog(struct netconn *conn, u8_t backlog) +{ + struct api_msg msg; + + /* This does no harm. If TCP_LISTEN_BACKLOG is off, backlog is unused. */ + LWIP_UNUSED_ARG(backlog); + + LWIP_ERROR("netconn_listen: invalid conn", (conn != NULL), return ERR_ARG;); + + msg.function = do_listen; + msg.msg.conn = conn; +#if TCP_LISTEN_BACKLOG + msg.msg.msg.lb.backlog = backlog; +#endif /* TCP_LISTEN_BACKLOG */ + TCPIP_APIMSG(&msg); + return conn->err; +} + +/** + * Accept a new connection on a TCP listening netconn. + * + * @param conn the TCP listen netconn + * @return the newly accepted netconn or NULL on timeout + */ +struct netconn * +netconn_accept(struct netconn *conn) +{ + struct netconn *newconn; + + LWIP_ERROR("netconn_accept: invalid conn", (conn != NULL), return NULL;); + LWIP_ERROR("netconn_accept: invalid acceptmbox", (conn->acceptmbox != SYS_MBOX_NULL), return NULL;); + +#if LWIP_SO_RCVTIMEO + if (sys_arch_mbox_fetch(conn->acceptmbox, (void *)&newconn, conn->recv_timeout) == SYS_ARCH_TIMEOUT) { + newconn = NULL; + } else +#else + sys_arch_mbox_fetch(conn->acceptmbox, (void *)&newconn, 0); +#endif /* LWIP_SO_RCVTIMEO*/ + { + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0); + +#if TCP_LISTEN_BACKLOG + if (newconn != NULL) { + /* Let the stack know that we have accepted the connection. */ + struct api_msg msg; + msg.function = do_recv; + msg.msg.conn = conn; + TCPIP_APIMSG(&msg); + } +#endif /* TCP_LISTEN_BACKLOG */ + } + + return newconn; +} + +/** + * Receive data (in form of a netbuf containing a packet buffer) from a netconn + * + * @param conn the netconn from which to receive data + * @return a new netbuf containing received data or NULL on memory error or timeout + */ +struct netbuf * +netconn_recv(struct netconn *conn) +{ + struct api_msg msg; + struct netbuf *buf = NULL; + struct pbuf *p; + u16_t len; + + LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return NULL;); + + if (conn->recvmbox == SYS_MBOX_NULL) { + /* @todo: should calling netconn_recv on a TCP listen conn be fatal (ERR_CONN)?? */ + /* TCP listen conns don't have a recvmbox! */ + conn->err = ERR_CONN; + return NULL; + } + + if (ERR_IS_FATAL(conn->err)) { + return NULL; + } + + if (conn->type == NETCONN_TCP) { +#if LWIP_TCP + if (conn->state == NETCONN_LISTEN) { + /* @todo: should calling netconn_recv on a TCP listen conn be fatal?? */ + conn->err = ERR_CONN; + return NULL; + } + + buf = memp_malloc(MEMP_NETBUF); + + if (buf == NULL) { + conn->err = ERR_MEM; + return NULL; + } + +#if LWIP_SO_RCVTIMEO + if (sys_arch_mbox_fetch(conn->recvmbox, (void *)&p, conn->recv_timeout)==SYS_ARCH_TIMEOUT) { + memp_free(MEMP_NETBUF, buf); + conn->err = ERR_TIMEOUT; + return NULL; + } +#else + sys_arch_mbox_fetch(conn->recvmbox, (void *)&p, 0); +#endif /* LWIP_SO_RCVTIMEO*/ + + if (p != NULL) { + len = p->tot_len; + SYS_ARCH_DEC(conn->recv_avail, len); + } else { + len = 0; + } + + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVMINUS, len); + + /* If we are closed, we indicate that we no longer wish to use the socket */ + if (p == NULL) { + memp_free(MEMP_NETBUF, buf); + /* Avoid to lose any previous error code */ + if (conn->err == ERR_OK) { + conn->err = ERR_CLSD; + } + return NULL; + } + + buf->p = p; + buf->ptr = p; + buf->port = 0; + buf->addr = NULL; + + /* Let the stack know that we have taken the data. */ + msg.function = do_recv; + msg.msg.conn = conn; + if (buf != NULL) { + msg.msg.msg.r.len = buf->p->tot_len; + } else { + msg.msg.msg.r.len = 1; + } + TCPIP_APIMSG(&msg); +#endif /* LWIP_TCP */ + } else { +#if (LWIP_UDP || LWIP_RAW) +#if LWIP_SO_RCVTIMEO + if (sys_arch_mbox_fetch(conn->recvmbox, (void *)&buf, conn->recv_timeout)==SYS_ARCH_TIMEOUT) { + buf = NULL; + } +#else + sys_arch_mbox_fetch(conn->recvmbox, (void *)&buf, 0); +#endif /* LWIP_SO_RCVTIMEO*/ + if (buf!=NULL) { + SYS_ARCH_DEC(conn->recv_avail, buf->p->tot_len); + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVMINUS, buf->p->tot_len); + } +#endif /* (LWIP_UDP || LWIP_RAW) */ + } + + LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_recv: received %p (err %d)\n", (void *)buf, conn->err)); + + return buf; +} + +/** + * Send data (in form of a netbuf) to a specific remote IP address and port. + * Only to be used for UDP and RAW netconns (not TCP). + * + * @param conn the netconn over which to send data + * @param buf a netbuf containing the data to send + * @param addr the remote IP address to which to send the data + * @param port the remote port to which to send the data + * @return ERR_OK if data was sent, any other err_t on error + */ +err_t +netconn_sendto(struct netconn *conn, struct netbuf *buf, struct ip_addr *addr, u16_t port) +{ + if (buf != NULL) { + buf->addr = addr; + buf->port = port; + return netconn_send(conn, buf); + } + return ERR_VAL; +} + +/** + * Send data over a UDP or RAW netconn (that is already connected). + * + * @param conn the UDP or RAW netconn over which to send data + * @param buf a netbuf containing the data to send + * @return ERR_OK if data was sent, any other err_t on error + */ +err_t +netconn_send(struct netconn *conn, struct netbuf *buf) +{ + struct api_msg msg; + + LWIP_ERROR("netconn_send: invalid conn", (conn != NULL), return ERR_ARG;); + + LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %"U16_F" bytes\n", buf->p->tot_len)); + msg.function = do_send; + msg.msg.conn = conn; + msg.msg.msg.b = buf; + TCPIP_APIMSG(&msg); + return conn->err; +} + +/** + * Send data over a TCP netconn. + * + * @param conn the TCP netconn over which to send data + * @param dataptr pointer to the application buffer that contains the data to send + * @param size size of the application data to send + * @param apiflags combination of following flags : + * - NETCONN_COPY (0x01) data will be copied into memory belonging to the stack + * - NETCONN_MORE (0x02) for TCP connection, PSH flag will be set on last segment sent + * @return ERR_OK if data was sent, any other err_t on error + */ +err_t +netconn_write(struct netconn *conn, const void *dataptr, size_t size, u8_t apiflags) +{ + struct api_msg msg; + + LWIP_ERROR("netconn_write: invalid conn", (conn != NULL), return ERR_ARG;); + LWIP_ERROR("netconn_write: invalid conn->type", (conn->type == NETCONN_TCP), return ERR_VAL;); + + msg.function = do_write; + msg.msg.conn = conn; + msg.msg.msg.w.dataptr = dataptr; + msg.msg.msg.w.apiflags = apiflags; + msg.msg.msg.w.len = size; + /* For locking the core: this _can_ be delayed on low memory/low send buffer, + but if it is, this is done inside api_msg.c:do_write(), so we can use the + non-blocking version here. */ + TCPIP_APIMSG(&msg); + return conn->err; +} + +/** + * Close a TCP netconn (doesn't delete it). + * + * @param conn the TCP netconn to close + * @return ERR_OK if the netconn was closed, any other err_t on error + */ +err_t +netconn_close(struct netconn *conn) +{ + struct api_msg msg; + + LWIP_ERROR("netconn_close: invalid conn", (conn != NULL), return ERR_ARG;); + + msg.function = do_close; + msg.msg.conn = conn; + tcpip_apimsg(&msg); + return conn->err; +} + +#if LWIP_IGMP +/** + * Join multicast groups for UDP netconns. + * + * @param conn the UDP netconn for which to change multicast addresses + * @param multiaddr IP address of the multicast group to join or leave + * @param interface the IP address of the network interface on which to send + * the igmp message + * @param join_or_leave flag whether to send a join- or leave-message + * @return ERR_OK if the action was taken, any err_t on error + */ +err_t +netconn_join_leave_group(struct netconn *conn, + struct ip_addr *multiaddr, + struct ip_addr *interface, + enum netconn_igmp join_or_leave) +{ + struct api_msg msg; + + LWIP_ERROR("netconn_join_leave_group: invalid conn", (conn != NULL), return ERR_ARG;); + + msg.function = do_join_leave_group; + msg.msg.conn = conn; + msg.msg.msg.jl.multiaddr = multiaddr; + msg.msg.msg.jl.interface = interface; + msg.msg.msg.jl.join_or_leave = join_or_leave; + TCPIP_APIMSG(&msg); + return conn->err; +} +#endif /* LWIP_IGMP */ + +#if LWIP_DNS +/** + * Execute a DNS query, only one IP address is returned + * + * @param name a string representation of the DNS host name to query + * @param addr a preallocated struct ip_addr where to store the resolved IP address + * @return ERR_OK: resolving succeeded + * ERR_MEM: memory error, try again later + * ERR_ARG: dns client not initialized or invalid hostname + * ERR_VAL: dns server response was invalid + */ +err_t +netconn_gethostbyname(const char *name, struct ip_addr *addr) +{ + struct dns_api_msg msg; + err_t err; + sys_sem_t sem; + + LWIP_ERROR("netconn_gethostbyname: invalid name", (name != NULL), return ERR_ARG;); + LWIP_ERROR("netconn_gethostbyname: invalid addr", (addr != NULL), return ERR_ARG;); + + sem = sys_sem_new(0); + if (sem == SYS_SEM_NULL) { + return ERR_MEM; + } + + msg.name = name; + msg.addr = addr; + msg.err = &err; + msg.sem = sem; + + tcpip_callback(do_gethostbyname, &msg); + sys_sem_wait(sem); + sys_sem_free(sem); + + return err; +} +#endif /* LWIP_DNS*/ + +err_t netconn_abort(struct netconn *conn) +{ + if (conn->acceptmbox != SYS_MBOX_NULL) { + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); + sys_mbox_post(conn->acceptmbox, NULL); + } + return ERR_OK; +} + +#endif /* LWIP_NETCONN */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/api/api_msg.c b/component/common/network/lwip/lwip_v1.3.2/src/api/api_msg.c new file mode 100644 index 0000000..8920139 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/api/api_msg.c @@ -0,0 +1,1243 @@ +/* + * @file + * Sequential API Internal module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/api_msg.h" + +#include "lwip/ip.h" +#include "lwip/udp.h" +#include "lwip/tcp.h" +#include "lwip/raw.h" + +#include "lwip/memp.h" +#include "lwip/tcpip.h" +#include "lwip/igmp.h" +#include "lwip/dns.h" + +#include + +/* forward declarations */ +#if LWIP_TCP +static err_t do_writemore(struct netconn *conn); +static void do_close_internal(struct netconn *conn); +#endif + +#if LWIP_RAW +/** + * Receive callback function for RAW netconns. + * Doesn't 'eat' the packet, only references it and sends it to + * conn->recvmbox + * + * @see raw.h (struct raw_pcb.recv) for parameters and return value + */ +static u8_t +recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p, + struct ip_addr *addr) +{ + struct pbuf *q; + struct netbuf *buf; + struct netconn *conn; +#if LWIP_SO_RCVBUF + int recv_avail; +#endif /* LWIP_SO_RCVBUF */ + + LWIP_UNUSED_ARG(addr); + conn = arg; + +#if LWIP_SO_RCVBUF + SYS_ARCH_GET(conn->recv_avail, recv_avail); + if ((conn != NULL) && (conn->recvmbox != SYS_MBOX_NULL) && + ((recv_avail + (int)(p->tot_len)) <= conn->recv_bufsize)) { +#else /* LWIP_SO_RCVBUF */ + if ((conn != NULL) && (conn->recvmbox != SYS_MBOX_NULL)) { +#endif /* LWIP_SO_RCVBUF */ + /* copy the whole packet into new pbufs */ + q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); + if(q != NULL) { + if (pbuf_copy(q, p) != ERR_OK) { + pbuf_free(q); + q = NULL; + } + } + + if(q != NULL) { + buf = memp_malloc(MEMP_NETBUF); + if (buf == NULL) { + pbuf_free(q); + return 0; + } + + buf->p = q; + buf->ptr = q; + buf->addr = &(((struct ip_hdr*)(q->payload))->src); + buf->port = pcb->protocol; + + if (sys_mbox_trypost(conn->recvmbox, buf) != ERR_OK) { + netbuf_delete(buf); + return 0; + } else { + SYS_ARCH_INC(conn->recv_avail, q->tot_len); + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, q->tot_len); + } + } + } + + return 0; /* do not eat the packet */ +} +#endif /* LWIP_RAW*/ + +#if LWIP_UDP +/** + * Receive callback function for UDP netconns. + * Posts the packet to conn->recvmbox or deletes it on memory error. + * + * @see udp.h (struct udp_pcb.recv) for parameters + */ +static void +recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p, + struct ip_addr *addr, u16_t port) +{ + struct netbuf *buf; + struct netconn *conn; +#if LWIP_SO_RCVBUF + int recv_avail; +#endif /* LWIP_SO_RCVBUF */ + + LWIP_UNUSED_ARG(pcb); /* only used for asserts... */ + LWIP_ASSERT("recv_udp must have a pcb argument", pcb != NULL); + LWIP_ASSERT("recv_udp must have an argument", arg != NULL); + conn = arg; + LWIP_ASSERT("recv_udp: recv for wrong pcb!", conn->pcb.udp == pcb); + +#if LWIP_SO_RCVBUF + SYS_ARCH_GET(conn->recv_avail, recv_avail); + if ((conn == NULL) || (conn->recvmbox == SYS_MBOX_NULL) || + ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize)) { +#else /* LWIP_SO_RCVBUF */ + if ((conn == NULL) || (conn->recvmbox == SYS_MBOX_NULL)) { +#endif /* LWIP_SO_RCVBUF */ + pbuf_free(p); + return; + } + + buf = memp_malloc(MEMP_NETBUF); + if (buf == NULL) { + pbuf_free(p); + return; + } else { + buf->p = p; + buf->ptr = p; + buf->addr = addr; + buf->port = port; +#if LWIP_NETBUF_RECVINFO + { + const struct ip_hdr* iphdr = ip_current_header(); + /* get the UDP header - always in the first pbuf, ensured by udp_input */ + const struct udp_hdr* udphdr = (void*)(((char*)iphdr) + IPH_LEN(iphdr)); + buf->toaddr = (struct ip_addr*)&iphdr->dest; + buf->toport = udphdr->dest; + } +#endif /* LWIP_NETBUF_RECVINFO */ + } + + if (sys_mbox_trypost(conn->recvmbox, buf) != ERR_OK) { + netbuf_delete(buf); + return; + } else { + SYS_ARCH_INC(conn->recv_avail, p->tot_len); + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, p->tot_len); + } +} +#endif /* LWIP_UDP */ + +#if LWIP_TCP +/** + * Receive callback function for TCP netconns. + * Posts the packet to conn->recvmbox, but doesn't delete it on errors. + * + * @see tcp.h (struct tcp_pcb.recv) for parameters and return value + */ +static err_t +recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) +{ + struct netconn *conn; + u16_t len; + + LWIP_UNUSED_ARG(pcb); + LWIP_ASSERT("recv_tcp must have a pcb argument", pcb != NULL); + LWIP_ASSERT("recv_tcp must have an argument", arg != NULL); + conn = arg; + LWIP_ASSERT("recv_tcp: recv for wrong pcb!", conn->pcb.tcp == pcb); + + if ((conn == NULL) || (conn->recvmbox == SYS_MBOX_NULL)) { + return ERR_VAL; + } + + conn->err = err; + if (p != NULL) { + len = p->tot_len; + SYS_ARCH_INC(conn->recv_avail, len); + } else { + len = 0; + } + + if (sys_mbox_trypost(conn->recvmbox, p) != ERR_OK) { + return ERR_MEM; + } else { + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); + } + + return ERR_OK; +} + +/** + * Poll callback function for TCP netconns. + * Wakes up an application thread that waits for a connection to close + * or data to be sent. The application thread then takes the + * appropriate action to go on. + * + * Signals the conn->sem. + * netconn_close waits for conn->sem if closing failed. + * + * @see tcp.h (struct tcp_pcb.poll) for parameters and return value + */ +static err_t +poll_tcp(void *arg, struct tcp_pcb *pcb) +{ + struct netconn *conn = arg; + + LWIP_UNUSED_ARG(pcb); + LWIP_ASSERT("conn != NULL", (conn != NULL)); + + if (conn->state == NETCONN_WRITE) { + do_writemore(conn); + } else if (conn->state == NETCONN_CLOSE) { + do_close_internal(conn); + } + + return ERR_OK; +} + +/** + * Sent callback function for TCP netconns. + * Signals the conn->sem and calls API_EVENT. + * netconn_write waits for conn->sem if send buffer is low. + * + * @see tcp.h (struct tcp_pcb.sent) for parameters and return value + */ +static err_t +sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len) +{ + struct netconn *conn = arg; + + LWIP_UNUSED_ARG(pcb); + LWIP_ASSERT("conn != NULL", (conn != NULL)); + + if (conn->state == NETCONN_WRITE) { + LWIP_ASSERT("conn->pcb.tcp != NULL", conn->pcb.tcp != NULL); + do_writemore(conn); + } else if (conn->state == NETCONN_CLOSE) { + do_close_internal(conn); + } + + if (conn) { + if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT)) { + API_EVENT(conn, NETCONN_EVT_SENDPLUS, len); + } + } + + return ERR_OK; +} + +/** + * Error callback function for TCP netconns. + * Signals conn->sem, posts to all conn mboxes and calls API_EVENT. + * The application thread has then to decide what to do. + * + * @see tcp.h (struct tcp_pcb.err) for parameters + */ +static void +err_tcp(void *arg, err_t err) +{ + struct netconn *conn; + + conn = arg; + LWIP_ASSERT("conn != NULL", (conn != NULL)); + + conn->pcb.tcp = NULL; + + conn->err = err; + if (conn->recvmbox != SYS_MBOX_NULL) { + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); + sys_mbox_post(conn->recvmbox, NULL); + } + if (conn->op_completed != SYS_SEM_NULL && conn->state == NETCONN_CONNECT) { + conn->state = NETCONN_NONE; + sys_sem_signal(conn->op_completed); + } + if (conn->acceptmbox != SYS_MBOX_NULL) { + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); + sys_mbox_post(conn->acceptmbox, NULL); + } + if ((conn->state == NETCONN_WRITE) || (conn->state == NETCONN_CLOSE)) { + /* calling do_writemore/do_close_internal is not necessary + since the pcb has already been deleted! */ + conn->state = NETCONN_NONE; + /* wake up the waiting task */ + sys_sem_signal(conn->op_completed); + } +} + +/** + * Setup a tcp_pcb with the correct callback function pointers + * and their arguments. + * + * @param conn the TCP netconn to setup + */ +static void +setup_tcp(struct netconn *conn) +{ + struct tcp_pcb *pcb; + + pcb = conn->pcb.tcp; + tcp_arg(pcb, conn); + tcp_recv(pcb, recv_tcp); + tcp_sent(pcb, sent_tcp); + tcp_poll(pcb, poll_tcp, 4); + tcp_err(pcb, err_tcp); +} + +/** + * Accept callback function for TCP netconns. + * Allocates a new netconn and posts that to conn->acceptmbox. + * + * @see tcp.h (struct tcp_pcb_listen.accept) for parameters and return value + */ +static err_t +accept_function(void *arg, struct tcp_pcb *newpcb, err_t err) +{ + struct netconn *newconn; + struct netconn *conn; + +#if API_MSG_DEBUG +#if TCP_DEBUG + tcp_debug_print_state(newpcb->state); +#endif /* TCP_DEBUG */ +#endif /* API_MSG_DEBUG */ + conn = (struct netconn *)arg; + + LWIP_ERROR("accept_function: invalid conn->acceptmbox", + conn->acceptmbox != SYS_MBOX_NULL, return ERR_VAL;); + + /* We have to set the callback here even though + * the new socket is unknown. conn->socket is marked as -1. */ + newconn = netconn_alloc(conn->type, conn->callback); + if (newconn == NULL) { + return ERR_MEM; + } + newconn->pcb.tcp = newpcb; + setup_tcp(newconn); + newconn->err = err; + + if (sys_mbox_trypost(conn->acceptmbox, newconn) != ERR_OK) { + /* When returning != ERR_OK, the connection is aborted in tcp_process(), + so do nothing here! */ + newconn->pcb.tcp = NULL; + netconn_free(newconn); + return ERR_MEM; + } else { + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); + } + + return ERR_OK; +} +#endif /* LWIP_TCP */ + +/** + * Create a new pcb of a specific type. + * Called from do_newconn(). + * + * @param msg the api_msg_msg describing the connection type + * @return msg->conn->err, but the return value is currently ignored + */ +static err_t +pcb_new(struct api_msg_msg *msg) +{ + msg->conn->err = ERR_OK; + + LWIP_ASSERT("pcb_new: pcb already allocated", msg->conn->pcb.tcp == NULL); + + /* Allocate a PCB for this connection */ + switch(NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + msg->conn->pcb.raw = raw_new(msg->msg.n.proto); + if(msg->conn->pcb.raw == NULL) { + msg->conn->err = ERR_MEM; + break; + } + raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn); + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + msg->conn->pcb.udp = udp_new(); + if(msg->conn->pcb.udp == NULL) { + msg->conn->err = ERR_MEM; + break; + } +#if LWIP_UDPLITE + if (msg->conn->type==NETCONN_UDPLITE) { + udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE); + } +#endif /* LWIP_UDPLITE */ + if (msg->conn->type==NETCONN_UDPNOCHKSUM) { + udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM); + } + udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + msg->conn->pcb.tcp = tcp_new(); + if(msg->conn->pcb.tcp == NULL) { + msg->conn->err = ERR_MEM; + break; + } + setup_tcp(msg->conn); + break; +#endif /* LWIP_TCP */ + default: + /* Unsupported netconn type, e.g. protocol disabled */ + msg->conn->err = ERR_VAL; + break; + } + + return msg->conn->err; +} + +/** + * Create a new pcb of a specific type inside a netconn. + * Called from netconn_new_with_proto_and_callback. + * + * @param msg the api_msg_msg describing the connection type + */ +void +do_newconn(struct api_msg_msg *msg) +{ + if(msg->conn->pcb.tcp == NULL) { + pcb_new(msg); + } + /* Else? This "new" connection already has a PCB allocated. */ + /* Is this an error condition? Should it be deleted? */ + /* We currently just are happy and return. */ + + TCPIP_APIMSG_ACK(msg); +} + +/** + * Create a new netconn (of a specific type) that has a callback function. + * The corresponding pcb is NOT created! + * + * @param t the type of 'connection' to create (@see enum netconn_type) + * @param proto the IP protocol for RAW IP pcbs + * @param callback a function to call on status changes (RX available, TX'ed) + * @return a newly allocated struct netconn or + * NULL on memory error + */ +struct netconn* +netconn_alloc(enum netconn_type t, netconn_callback callback) +{ + struct netconn *conn; + int size = 0; + + conn = memp_malloc(MEMP_NETCONN); + if (conn == NULL) { + return NULL; + } + + conn->err = ERR_OK; + conn->type = t; + conn->pcb.tcp = NULL; + +#if (DEFAULT_RAW_RECVMBOX_SIZE == DEFAULT_UDP_RECVMBOX_SIZE) && \ + (DEFAULT_RAW_RECVMBOX_SIZE == DEFAULT_TCP_RECVMBOX_SIZE) + size = DEFAULT_RAW_RECVMBOX_SIZE; +#else + switch(NETCONNTYPE_GROUP(t)) { +#if LWIP_RAW + case NETCONN_RAW: + size = DEFAULT_RAW_RECVMBOX_SIZE; + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + size = DEFAULT_UDP_RECVMBOX_SIZE; + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + size = DEFAULT_TCP_RECVMBOX_SIZE; + break; +#endif /* LWIP_TCP */ + default: + LWIP_ASSERT("netconn_alloc: undefined netconn_type", 0); + break; + } +#endif + + if ((conn->op_completed = sys_sem_new(0)) == SYS_SEM_NULL) { + memp_free(MEMP_NETCONN, conn); + return NULL; + } + if ((conn->recvmbox = sys_mbox_new(size)) == SYS_MBOX_NULL) { + sys_sem_free(conn->op_completed); + memp_free(MEMP_NETCONN, conn); + return NULL; + } + + conn->acceptmbox = SYS_MBOX_NULL; + conn->state = NETCONN_NONE; + /* initialize socket to -1 since 0 is a valid socket */ + conn->socket = -1; + conn->callback = callback; + conn->recv_avail = 0; +#if LWIP_TCP + conn->write_msg = NULL; + conn->write_offset = 0; +#if LWIP_TCPIP_CORE_LOCKING + conn->write_delayed = 0; +#endif /* LWIP_TCPIP_CORE_LOCKING */ +#endif /* LWIP_TCP */ +#if LWIP_SO_RCVTIMEO + conn->recv_timeout = 0; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + conn->recv_bufsize = RECV_BUFSIZE_DEFAULT; +#endif /* LWIP_SO_RCVBUF */ + return conn; +} + +/** + * Delete a netconn and all its resources. + * The pcb is NOT freed (since we might not be in the right thread context do this). + * + * @param conn the netconn to free + */ +void +netconn_free(struct netconn *conn) +{ + void *mem; + LWIP_ASSERT("PCB must be deallocated outside this function", conn->pcb.tcp == NULL); + + /* Drain the recvmbox. */ + if (conn->recvmbox != SYS_MBOX_NULL) { + while (sys_mbox_tryfetch(conn->recvmbox, &mem) != SYS_MBOX_EMPTY) { + if (conn->type == NETCONN_TCP) { + if(mem != NULL) { + pbuf_free((struct pbuf *)mem); + } + } else { + netbuf_delete((struct netbuf *)mem); + } + } + sys_mbox_free(conn->recvmbox); + conn->recvmbox = SYS_MBOX_NULL; + } + + /* Drain the acceptmbox. */ + if (conn->acceptmbox != SYS_MBOX_NULL) { + while (sys_mbox_tryfetch(conn->acceptmbox, &mem) != SYS_MBOX_EMPTY) { + netconn_delete((struct netconn *)mem); + } + sys_mbox_free(conn->acceptmbox); + conn->acceptmbox = SYS_MBOX_NULL; + } + + sys_sem_free(conn->op_completed); + conn->op_completed = SYS_SEM_NULL; + + memp_free(MEMP_NETCONN, conn); +} + +#if LWIP_TCP +/** + * Internal helper function to close a TCP netconn: since this sometimes + * doesn't work at the first attempt, this function is called from multiple + * places. + * + * @param conn the TCP netconn to close + */ +static void +do_close_internal(struct netconn *conn) +{ + err_t err; + + LWIP_ASSERT("invalid conn", (conn != NULL)); + LWIP_ASSERT("this is for tcp netconns only", (conn->type == NETCONN_TCP)); + LWIP_ASSERT("conn must be in state NETCONN_CLOSE", (conn->state == NETCONN_CLOSE)); + LWIP_ASSERT("pcb already closed", (conn->pcb.tcp != NULL)); + + /* Set back some callback pointers */ + tcp_arg(conn->pcb.tcp, NULL); + if (conn->pcb.tcp->state == LISTEN) { + tcp_accept(conn->pcb.tcp, NULL); + } else { + tcp_recv(conn->pcb.tcp, NULL); + tcp_accept(conn->pcb.tcp, NULL); + /* some callbacks have to be reset if tcp_close is not successful */ + tcp_sent(conn->pcb.tcp, NULL); + tcp_poll(conn->pcb.tcp, NULL, 4); + tcp_err(conn->pcb.tcp, NULL); + } + /* Try to close the connection */ + err = tcp_close(conn->pcb.tcp); + if (err == ERR_OK) { + /* Closing succeeded */ + conn->state = NETCONN_NONE; + /* Set back some callback pointers as conn is going away */ + conn->pcb.tcp = NULL; + conn->err = ERR_OK; + /* Trigger select() in socket layer. This send should something else so the + errorfd is set, not the read and write fd! */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); + API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); + /* wake up the application task */ + sys_sem_signal(conn->op_completed); + } else { + /* Closing failed, restore some of the callbacks */ + /* Closing of listen pcb will never fail! */ + LWIP_ASSERT("Closing a listen pcb may not fail!", (conn->pcb.tcp->state != LISTEN)); + tcp_sent(conn->pcb.tcp, sent_tcp); + tcp_poll(conn->pcb.tcp, poll_tcp, 4); + tcp_err(conn->pcb.tcp, err_tcp); + tcp_arg(conn->pcb.tcp, conn); + } + /* If closing didn't succeed, we get called again either + from poll_tcp or from sent_tcp */ +} +#endif /* LWIP_TCP */ + +/** + * Delete the pcb inside a netconn. + * Called from netconn_delete. + * + * @param msg the api_msg_msg pointing to the connection + */ +void +do_delconn(struct api_msg_msg *msg) +{ + if (msg->conn->pcb.tcp != NULL) { + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + raw_remove(msg->conn->pcb.raw); + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + msg->conn->pcb.udp->recv_arg = NULL; + udp_remove(msg->conn->pcb.udp); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + msg->conn->state = NETCONN_CLOSE; + do_close_internal(msg->conn); + /* API_EVENT is called inside do_close_internal, before releasing + the application thread, so we can return at this point! */ + return; +#endif /* LWIP_TCP */ + default: + break; + } + } + /* tcp netconns don't come here! */ + + /* Trigger select() in socket layer. This send should something else so the + errorfd is set, not the read and write fd! */ + API_EVENT(msg->conn, NETCONN_EVT_RCVPLUS, 0); + API_EVENT(msg->conn, NETCONN_EVT_SENDPLUS, 0); + + if (msg->conn->op_completed != SYS_SEM_NULL) { + sys_sem_signal(msg->conn->op_completed); + } +} + +/** + * Bind a pcb contained in a netconn + * Called from netconn_bind. + * + * @param msg the api_msg_msg pointing to the connection and containing + * the IP address and port to bind to + */ +void +do_bind(struct api_msg_msg *msg) +{ + if (!ERR_IS_FATAL(msg->conn->err)) { + if (msg->conn->pcb.tcp != NULL) { + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + msg->conn->err = raw_bind(msg->conn->pcb.raw, msg->msg.bc.ipaddr); + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + msg->conn->err = udp_bind(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + msg->conn->err = tcp_bind(msg->conn->pcb.tcp, msg->msg.bc.ipaddr, msg->msg.bc.port); + break; +#endif /* LWIP_TCP */ + default: + break; + } + } else { + /* msg->conn->pcb is NULL */ + msg->conn->err = ERR_VAL; + } + } + TCPIP_APIMSG_ACK(msg); +} + +#if LWIP_TCP +/** + * TCP callback function if a connection (opened by tcp_connect/do_connect) has + * been established (or reset by the remote host). + * + * @see tcp.h (struct tcp_pcb.connected) for parameters and return values + */ +static err_t +do_connected(void *arg, struct tcp_pcb *pcb, err_t err) +{ + struct netconn *conn; + + LWIP_UNUSED_ARG(pcb); + + conn = arg; + + if (conn == NULL) { + return ERR_VAL; + } + + conn->err = err; + if ((conn->type == NETCONN_TCP) && (err == ERR_OK)) { + setup_tcp(conn); + } + conn->state = NETCONN_NONE; + sys_sem_signal(conn->op_completed); + return ERR_OK; +} +#endif /* LWIP_TCP */ + +/** + * Connect a pcb contained inside a netconn + * Called from netconn_connect. + * + * @param msg the api_msg_msg pointing to the connection and containing + * the IP address and port to connect to + */ +void +do_connect(struct api_msg_msg *msg) +{ + if (msg->conn->pcb.tcp == NULL) { + sys_sem_signal(msg->conn->op_completed); + return; + } + + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + msg->conn->err = raw_connect(msg->conn->pcb.raw, msg->msg.bc.ipaddr); + sys_sem_signal(msg->conn->op_completed); + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + msg->conn->err = udp_connect(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port); + sys_sem_signal(msg->conn->op_completed); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + msg->conn->state = NETCONN_CONNECT; + setup_tcp(msg->conn); + msg->conn->err = tcp_connect(msg->conn->pcb.tcp, msg->msg.bc.ipaddr, msg->msg.bc.port, + do_connected); + /* sys_sem_signal() is called from do_connected (or err_tcp()), + * when the connection is established! */ + break; +#endif /* LWIP_TCP */ + default: + LWIP_ERROR("Invalid netconn type", 0, do{ msg->conn->err = ERR_VAL; + sys_sem_signal(msg->conn->op_completed); }while(0)); + break; + } +} + +/** + * Connect a pcb contained inside a netconn + * Only used for UDP netconns. + * Called from netconn_disconnect. + * + * @param msg the api_msg_msg pointing to the connection to disconnect + */ +void +do_disconnect(struct api_msg_msg *msg) +{ +#if LWIP_UDP + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) { + udp_disconnect(msg->conn->pcb.udp); + } +#endif /* LWIP_UDP */ + TCPIP_APIMSG_ACK(msg); +} + +/** + * Set a TCP pcb contained in a netconn into listen mode + * Called from netconn_listen. + * + * @param msg the api_msg_msg pointing to the connection + */ +void +do_listen(struct api_msg_msg *msg) +{ +#if LWIP_TCP + if (!ERR_IS_FATAL(msg->conn->err)) { + if (msg->conn->pcb.tcp != NULL) { + if (msg->conn->type == NETCONN_TCP) { + if (msg->conn->pcb.tcp->state == CLOSED) { +#if TCP_LISTEN_BACKLOG + struct tcp_pcb* lpcb = tcp_listen_with_backlog(msg->conn->pcb.tcp, msg->msg.lb.backlog); +#else /* TCP_LISTEN_BACKLOG */ + struct tcp_pcb* lpcb = tcp_listen(msg->conn->pcb.tcp); +#endif /* TCP_LISTEN_BACKLOG */ + if (lpcb == NULL) { + msg->conn->err = ERR_MEM; + } else { + /* delete the recvmbox and allocate the acceptmbox */ + if (msg->conn->recvmbox != SYS_MBOX_NULL) { + /** @todo: should we drain the recvmbox here? */ + sys_mbox_free(msg->conn->recvmbox); + msg->conn->recvmbox = SYS_MBOX_NULL; + } + if (msg->conn->acceptmbox == SYS_MBOX_NULL) { + if ((msg->conn->acceptmbox = sys_mbox_new(DEFAULT_ACCEPTMBOX_SIZE)) == SYS_MBOX_NULL) { + msg->conn->err = ERR_MEM; + } + } + if (msg->conn->err == ERR_OK) { + msg->conn->state = NETCONN_LISTEN; + msg->conn->pcb.tcp = lpcb; + tcp_arg(msg->conn->pcb.tcp, msg->conn); + tcp_accept(msg->conn->pcb.tcp, accept_function); + } + } + } else { + msg->conn->err = ERR_CONN; + } + } + } + } +#endif /* LWIP_TCP */ + TCPIP_APIMSG_ACK(msg); +} + +/** + * Send some data on a RAW or UDP pcb contained in a netconn + * Called from netconn_send + * + * @param msg the api_msg_msg pointing to the connection + */ +void +do_send(struct api_msg_msg *msg) +{ + if (!ERR_IS_FATAL(msg->conn->err)) { + if (msg->conn->pcb.tcp != NULL) { + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + if (msg->msg.b->addr == NULL) { + msg->conn->err = raw_send(msg->conn->pcb.raw, msg->msg.b->p); + } else { + msg->conn->err = raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, msg->msg.b->addr); + } + break; +#endif +#if LWIP_UDP + case NETCONN_UDP: + if (msg->msg.b->addr == NULL) { + msg->conn->err = udp_send(msg->conn->pcb.udp, msg->msg.b->p); + } else { + msg->conn->err = udp_sendto(msg->conn->pcb.udp, msg->msg.b->p, msg->msg.b->addr, msg->msg.b->port); + } + break; +#endif /* LWIP_UDP */ + default: + break; + } + } + } + TCPIP_APIMSG_ACK(msg); +} + +/** + * Indicate data has been received from a TCP pcb contained in a netconn + * Called from netconn_recv + * + * @param msg the api_msg_msg pointing to the connection + */ +void +do_recv(struct api_msg_msg *msg) +{ +#if LWIP_TCP + if (!ERR_IS_FATAL(msg->conn->err)) { + if (msg->conn->pcb.tcp != NULL) { + if (msg->conn->type == NETCONN_TCP) { +#if TCP_LISTEN_BACKLOG + if (msg->conn->pcb.tcp->state == LISTEN) { + tcp_accepted(msg->conn->pcb.tcp); + } else +#endif /* TCP_LISTEN_BACKLOG */ + { + tcp_recved(msg->conn->pcb.tcp, msg->msg.r.len); + } + } + } + } +#endif /* LWIP_TCP */ + TCPIP_APIMSG_ACK(msg); +} + +#if LWIP_TCP +/** + * See if more data needs to be written from a previous call to netconn_write. + * Called initially from do_write. If the first call can't send all data + * (because of low memory or empty send-buffer), this function is called again + * from sent_tcp() or poll_tcp() to send more data. If all data is sent, the + * blocking application thread (waiting in netconn_write) is released. + * + * @param conn netconn (that is currently in state NETCONN_WRITE) to process + * @return ERR_OK + * ERR_MEM if LWIP_TCPIP_CORE_LOCKING=1 and sending hasn't yet finished + */ +static err_t +do_writemore(struct netconn *conn) +{ + err_t err; + void *dataptr; + u16_t len, available; + u8_t write_finished = 0; + size_t diff; + + LWIP_ASSERT("conn->state == NETCONN_WRITE", (conn->state == NETCONN_WRITE)); + + dataptr = (u8_t*)conn->write_msg->msg.w.dataptr + conn->write_offset; + diff = conn->write_msg->msg.w.len - conn->write_offset; + if (diff > 0xffffUL) { /* max_u16_t */ + len = 0xffff; +#if LWIP_TCPIP_CORE_LOCKING + conn->write_delayed = 1; +#endif + } else { + len = (u16_t)diff; + } + available = tcp_sndbuf(conn->pcb.tcp); + if (available < len) { + /* don't try to write more than sendbuf */ + len = available; +#if LWIP_TCPIP_CORE_LOCKING + conn->write_delayed = 1; +#endif + } + + err = tcp_write(conn->pcb.tcp, dataptr, len, conn->write_msg->msg.w.apiflags); + LWIP_ASSERT("do_writemore: invalid length!", ((conn->write_offset + len) <= conn->write_msg->msg.w.len)); + if (err == ERR_OK) { + conn->write_offset += len; + if (conn->write_offset == conn->write_msg->msg.w.len) { + /* everything was written */ + write_finished = 1; + conn->write_msg = NULL; + conn->write_offset = 0; + /* API_EVENT might call tcp_tmr, so reset conn->state now */ + conn->state = NETCONN_NONE; + } + err = tcp_output_nagle(conn->pcb.tcp); + conn->err = err; + if ((err == ERR_OK) && (tcp_sndbuf(conn->pcb.tcp) <= TCP_SNDLOWAT)) { + API_EVENT(conn, NETCONN_EVT_SENDMINUS, len); + } + } else if (err == ERR_MEM) { + /* If ERR_MEM, we wait for sent_tcp or poll_tcp to be called + we do NOT return to the application thread, since ERR_MEM is + only a temporary error! */ + + /* tcp_enqueue returned ERR_MEM, try tcp_output anyway */ + err = tcp_output(conn->pcb.tcp); + +#if LWIP_TCPIP_CORE_LOCKING + conn->write_delayed = 1; +#endif + } else { + /* On errors != ERR_MEM, we don't try writing any more but return + the error to the application thread. */ + conn->err = err; + write_finished = 1; + } + + if (write_finished) { + /* everything was written: set back connection state + and back to application task */ + conn->state = NETCONN_NONE; +#if LWIP_TCPIP_CORE_LOCKING + if (conn->write_delayed != 0) +#endif + { + sys_sem_signal(conn->op_completed); + } + } +#if LWIP_TCPIP_CORE_LOCKING + else + return ERR_MEM; +#endif + return ERR_OK; +} +#endif /* LWIP_TCP */ + +/** + * Send some data on a TCP pcb contained in a netconn + * Called from netconn_write + * + * @param msg the api_msg_msg pointing to the connection + */ +void +do_write(struct api_msg_msg *msg) +{ + if (!ERR_IS_FATAL(msg->conn->err)) { + if ((msg->conn->pcb.tcp != NULL) && (msg->conn->type == NETCONN_TCP)) { +#if LWIP_TCP + msg->conn->state = NETCONN_WRITE; + /* set all the variables used by do_writemore */ + LWIP_ASSERT("already writing", msg->conn->write_msg == NULL && + msg->conn->write_offset == 0); + msg->conn->write_msg = msg; + msg->conn->write_offset = 0; +#if LWIP_TCPIP_CORE_LOCKING + msg->conn->write_delayed = 0; + if (do_writemore(msg->conn) != ERR_OK) { + LWIP_ASSERT("state!", msg->conn->state == NETCONN_WRITE); + UNLOCK_TCPIP_CORE(); + sys_arch_sem_wait(msg->conn->op_completed, 0); + LOCK_TCPIP_CORE(); + LWIP_ASSERT("state!", msg->conn->state == NETCONN_NONE); + } +#else + do_writemore(msg->conn); +#endif + /* for both cases: if do_writemore was called, don't ACK the APIMSG! */ + return; +#endif /* LWIP_TCP */ +#if (LWIP_UDP || LWIP_RAW) + } else { + msg->conn->err = ERR_VAL; +#endif /* (LWIP_UDP || LWIP_RAW) */ + } + } + TCPIP_APIMSG_ACK(msg); +} + +/** + * Return a connection's local or remote address + * Called from netconn_getaddr + * + * @param msg the api_msg_msg pointing to the connection + */ +void +do_getaddr(struct api_msg_msg *msg) +{ + if (msg->conn->pcb.ip != NULL) { + *(msg->msg.ad.ipaddr) = (msg->msg.ad.local?msg->conn->pcb.ip->local_ip:msg->conn->pcb.ip->remote_ip); + + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + if (msg->msg.ad.local) { + *(msg->msg.ad.port) = msg->conn->pcb.raw->protocol; + } else { + /* return an error as connecting is only a helper for upper layers */ + msg->conn->err = ERR_CONN; + } + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + if (msg->msg.ad.local) { + *(msg->msg.ad.port) = msg->conn->pcb.udp->local_port; + } else { + if ((msg->conn->pcb.udp->flags & UDP_FLAGS_CONNECTED) == 0) { + msg->conn->err = ERR_CONN; + } else { + *(msg->msg.ad.port) = msg->conn->pcb.udp->remote_port; + } + } + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + *(msg->msg.ad.port) = (msg->msg.ad.local?msg->conn->pcb.tcp->local_port:msg->conn->pcb.tcp->remote_port); + break; +#endif /* LWIP_TCP */ + } + } else { + msg->conn->err = ERR_CONN; + } + TCPIP_APIMSG_ACK(msg); +} + +/** + * Close a TCP pcb contained in a netconn + * Called from netconn_close + * + * @param msg the api_msg_msg pointing to the connection + */ +void +do_close(struct api_msg_msg *msg) +{ +#if LWIP_TCP + if ((msg->conn->pcb.tcp != NULL) && (msg->conn->type == NETCONN_TCP)) { + msg->conn->state = NETCONN_CLOSE; + do_close_internal(msg->conn); + /* for tcp netconns, do_close_internal ACKs the message */ + } else +#endif /* LWIP_TCP */ + { + msg->conn->err = ERR_VAL; + sys_sem_signal(msg->conn->op_completed); + } +} + +#if LWIP_IGMP +/** + * Join multicast groups for UDP netconns. + * Called from netconn_join_leave_group + * + * @param msg the api_msg_msg pointing to the connection + */ +void +do_join_leave_group(struct api_msg_msg *msg) +{ + if (!ERR_IS_FATAL(msg->conn->err)) { + if (msg->conn->pcb.tcp != NULL) { + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) { +#if LWIP_UDP + if (msg->msg.jl.join_or_leave == NETCONN_JOIN) { + msg->conn->err = igmp_joingroup(msg->msg.jl.interface, msg->msg.jl.multiaddr); + } else { + msg->conn->err = igmp_leavegroup(msg->msg.jl.interface, msg->msg.jl.multiaddr); + } +#endif /* LWIP_UDP */ +#if (LWIP_TCP || LWIP_RAW) + } else { + msg->conn->err = ERR_VAL; +#endif /* (LWIP_TCP || LWIP_RAW) */ + } + } + } + TCPIP_APIMSG_ACK(msg); +} +#endif /* LWIP_IGMP */ + +#if LWIP_DNS +/** + * Callback function that is called when DNS name is resolved + * (or on timeout). A waiting application thread is waked up by + * signaling the semaphore. + */ +static void +do_dns_found(const char *name, struct ip_addr *ipaddr, void *arg) +{ + struct dns_api_msg *msg = (struct dns_api_msg*)arg; + + LWIP_ASSERT("DNS response for wrong host name", strcmp(msg->name, name) == 0); + + if (ipaddr == NULL) { + /* timeout or memory error */ + *msg->err = ERR_VAL; + } else { + /* address was resolved */ + *msg->err = ERR_OK; + *msg->addr = *ipaddr; + } + /* wake up the application task waiting in netconn_gethostbyname */ + sys_sem_signal(msg->sem); +} + +/** + * Execute a DNS query + * Called from netconn_gethostbyname + * + * @param arg the dns_api_msg pointing to the query + */ +void +do_gethostbyname(void *arg) +{ + struct dns_api_msg *msg = (struct dns_api_msg*)arg; + + *msg->err = dns_gethostbyname(msg->name, msg->addr, do_dns_found, msg); + if (*msg->err != ERR_INPROGRESS) { + /* on error or immediate success, wake up the application + * task waiting in netconn_gethostbyname */ + sys_sem_signal(msg->sem); + } +} +#endif /* LWIP_DNS */ + +#endif /* LWIP_NETCONN */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/api/err.c b/component/common/network/lwip/lwip_v1.3.2/src/api/err.c new file mode 100644 index 0000000..c8266ab --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/api/err.c @@ -0,0 +1,74 @@ +/* + * @file + * Error Management module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/err.h" + +#ifdef LWIP_DEBUG + +static const char *err_strerr[] = { + "Ok.", /* ERR_OK 0 */ + "Out of memory error.", /* ERR_MEM -1 */ + "Buffer error.", /* ERR_BUF -2 */ + "Timeout.", /* ERR_TIMEOUT -3 */ + "Routing problem.", /* ERR_RTE -4 */ + "Connection aborted.", /* ERR_ABRT -5 */ + "Connection reset.", /* ERR_RST -6 */ + "Connection closed.", /* ERR_CLSD -7 */ + "Not connected.", /* ERR_CONN -8 */ + "Illegal value.", /* ERR_VAL -9 */ + "Illegal argument.", /* ERR_ARG -10 */ + "Address in use.", /* ERR_USE -11 */ + "Low-level netif error.", /* ERR_IF -12 */ + "Already connected.", /* ERR_ISCONN -13 */ + "Operation in progress." /* ERR_INPROGRESS -14 */ +}; + +/** + * Convert an lwip internal error to a string representation. + * + * @param err an lwip internal err_t + * @return a string representation for err + */ +const char * +lwip_strerr(err_t err) +{ + return err_strerr[-err]; + +} + +#endif /* LWIP_DEBUG */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/api/netbuf.c b/component/common/network/lwip/lwip_v1.3.2/src/api/netbuf.c new file mode 100644 index 0000000..5cb24f1 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/api/netbuf.c @@ -0,0 +1,240 @@ +/** + * @file + * Network buffer management + * + **/ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/netbuf.h" +#include "lwip/memp.h" + +#include + +/** + * Create (allocate) and initialize a new netbuf. + * The netbuf doesn't yet contain a packet buffer! + * + * @return a pointer to a new netbuf + * NULL on lack of memory + */ +struct +netbuf *netbuf_new(void) +{ + struct netbuf *buf; + + buf = memp_malloc(MEMP_NETBUF); + if (buf != NULL) { + buf->p = NULL; + buf->ptr = NULL; + buf->addr = NULL; + buf->port = 0; +#if LWIP_NETBUF_RECVINFO + buf->toaddr = NULL; + buf->toport = 0; +#endif /* LWIP_NETBUF_RECVINFO */ + return buf; + } else { + return NULL; + } +} + +/** + * Deallocate a netbuf allocated by netbuf_new(). + * + * @param buf pointer to a netbuf allocated by netbuf_new() + */ +void +netbuf_delete(struct netbuf *buf) +{ + if (buf != NULL) { + if (buf->p != NULL) { + pbuf_free(buf->p); + buf->p = buf->ptr = NULL; + } + memp_free(MEMP_NETBUF, buf); + } +} + +/** + * Allocate memory for a packet buffer for a given netbuf. + * + * @param buf the netbuf for which to allocate a packet buffer + * @param size the size of the packet buffer to allocate + * @return pointer to the allocated memory + * NULL if no memory could be allocated + */ +void * +netbuf_alloc(struct netbuf *buf, u16_t size) +{ + LWIP_ERROR("netbuf_alloc: invalid buf", (buf != NULL), return NULL;); + + /* Deallocate any previously allocated memory. */ + if (buf->p != NULL) { + pbuf_free(buf->p); + } + buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM); + if (buf->p == NULL) { + return NULL; + } + LWIP_ASSERT("check that first pbuf can hold size", + (buf->p->len >= size)); + buf->ptr = buf->p; + return buf->p->payload; +} + +/** + * Free the packet buffer included in a netbuf + * + * @param buf pointer to the netbuf which contains the packet buffer to free + */ +void +netbuf_free(struct netbuf *buf) +{ + LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return;); + if (buf->p != NULL) { + pbuf_free(buf->p); + } + buf->p = buf->ptr = NULL; +} + +/** + * Let a netbuf reference existing (non-volatile) data. + * + * @param buf netbuf which should reference the data + * @param dataptr pointer to the data to reference + * @param size size of the data + * @return ERR_OK if data is referenced + * ERR_MEM if data couldn't be referenced due to lack of memory + */ +err_t +netbuf_ref(struct netbuf *buf, const void *dataptr, u16_t size) +{ + LWIP_ERROR("netbuf_ref: invalid buf", (buf != NULL), return ERR_ARG;); + if (buf->p != NULL) { + pbuf_free(buf->p); + } + buf->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF); + if (buf->p == NULL) { + buf->ptr = NULL; + return ERR_MEM; + } + buf->p->payload = (void*)dataptr; + buf->p->len = buf->p->tot_len = size; + buf->ptr = buf->p; + return ERR_OK; +} + +/** + * Chain one netbuf to another (@see pbuf_chain) + * + * @param head the first netbuf + * @param tail netbuf to chain after head, freed by this function, may not be reference after returning + */ +void +netbuf_chain(struct netbuf *head, struct netbuf *tail) +{ + LWIP_ERROR("netbuf_ref: invalid head", (head != NULL), return;); + LWIP_ERROR("netbuf_chain: invalid tail", (tail != NULL), return;); + pbuf_cat(head->p, tail->p); + head->ptr = head->p; + memp_free(MEMP_NETBUF, tail); +} + +/** + * Get the data pointer and length of the data inside a netbuf. + * + * @param buf netbuf to get the data from + * @param dataptr pointer to a void pointer where to store the data pointer + * @param len pointer to an u16_t where the length of the data is stored + * @return ERR_OK if the information was retreived, + * ERR_BUF on error. + */ +err_t +netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len) +{ + LWIP_ERROR("netbuf_data: invalid buf", (buf != NULL), return ERR_ARG;); + LWIP_ERROR("netbuf_data: invalid dataptr", (dataptr != NULL), return ERR_ARG;); + LWIP_ERROR("netbuf_data: invalid len", (len != NULL), return ERR_ARG;); + + if (buf->ptr == NULL) { + return ERR_BUF; + } + *dataptr = buf->ptr->payload; + *len = buf->ptr->len; + return ERR_OK; +} + +/** + * Move the current data pointer of a packet buffer contained in a netbuf + * to the next part. + * The packet buffer itself is not modified. + * + * @param buf the netbuf to modify + * @return -1 if there is no next part + * 1 if moved to the next part but now there is no next part + * 0 if moved to the next part and there are still more parts + */ +s8_t +netbuf_next(struct netbuf *buf) +{ + LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return -1;); + if (buf->ptr->next == NULL) { + return -1; + } + buf->ptr = buf->ptr->next; + if (buf->ptr->next == NULL) { + return 1; + } + return 0; +} + +/** + * Move the current data pointer of a packet buffer contained in a netbuf + * to the beginning of the packet. + * The packet buffer itself is not modified. + * + * @param buf the netbuf to modify + */ +void +netbuf_first(struct netbuf *buf) +{ + LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return;); + buf->ptr = buf->p; +} + +#endif /* LWIP_NETCONN */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/api/netdb.c b/component/common/network/lwip/lwip_v1.3.2/src/api/netdb.c new file mode 100644 index 0000000..dc91837 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/api/netdb.c @@ -0,0 +1,346 @@ +/** + * @file + * API functions for name resolving + * + **/ + +/* + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Simon Goldschmidt + * + */ + +#include "lwip/netdb.h" + +#if LWIP_DNS && LWIP_SOCKET + +#include "lwip/err.h" +#include "lwip/mem.h" +#include "lwip/ip_addr.h" +#include "lwip/api.h" + +#include +#include + +/** helper struct for gethostbyname_r to access the char* buffer */ +struct gethostbyname_r_helper { + struct ip_addr *addrs; + struct ip_addr addr; + char *aliases; +}; + +/** h_errno is exported in netdb.h for access by applications. */ +#if LWIP_DNS_API_DECLARE_H_ERRNO +int h_errno; +#endif /* LWIP_DNS_API_DECLARE_H_ERRNO */ + +/** define "hostent" variables storage: 0 if we use a static (but unprotected) + * set of variables for lwip_gethostbyname, 1 if we use a local storage */ +#ifndef LWIP_DNS_API_HOSTENT_STORAGE +#define LWIP_DNS_API_HOSTENT_STORAGE 0 +#endif + +/** define "hostent" variables storage */ +#if LWIP_DNS_API_HOSTENT_STORAGE +#define HOSTENT_STORAGE +#else +#define HOSTENT_STORAGE static +#endif /* LWIP_DNS_API_STATIC_HOSTENT */ + +/** + * Returns an entry containing addresses of address family AF_INET + * for the host with name name. + * Due to dns_gethostbyname limitations, only one address is returned. + * + * @param name the hostname to resolve + * @return an entry containing addresses of address family AF_INET + * for the host with name name + */ +struct hostent* +lwip_gethostbyname(const char *name) +{ + err_t err; + struct ip_addr addr; + + /* buffer variables for lwip_gethostbyname() */ + HOSTENT_STORAGE struct hostent s_hostent; + HOSTENT_STORAGE char *s_aliases; + HOSTENT_STORAGE struct ip_addr s_hostent_addr; + HOSTENT_STORAGE struct ip_addr *s_phostent_addr; + + /* query host IP address */ + err = netconn_gethostbyname(name, &addr); + if (err != ERR_OK) { + LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err)); + h_errno = HOST_NOT_FOUND; + return NULL; + } + + /* fill hostent */ + s_hostent_addr = addr; + s_phostent_addr = &s_hostent_addr; + s_hostent.h_name = (char*)name; + s_hostent.h_aliases = &s_aliases; + s_hostent.h_addrtype = AF_INET; + s_hostent.h_length = sizeof(struct ip_addr); + s_hostent.h_addr_list = (char**)&s_phostent_addr; + +#if DNS_DEBUG + /* dump hostent */ + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_name == %s\n", s_hostent.h_name)); + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases == %p\n", s_hostent.h_aliases)); + if (s_hostent.h_aliases != NULL) { + u8_t idx; + for ( idx=0; s_hostent.h_aliases[idx]; idx++) { + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases[%i]-> == %p\n", idx, s_hostent.h_aliases[idx])); + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases[%i]-> == %s\n", idx, s_hostent.h_aliases[idx])); + } + } + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addrtype == %d\n", s_hostent.h_addrtype)); + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_length == %d\n", s_hostent.h_length)); + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list == %p\n", s_hostent.h_addr_list)); + if (s_hostent.h_addr_list != NULL) { + u8_t idx; + for ( idx=0; s_hostent.h_addr_list[idx]; idx++) { + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i] == %p\n", idx, s_hostent.h_addr_list[idx])); + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i]-> == %s\n", idx, ip_ntoa(s_hostent.h_addr_list[idx]))); + } + } +#endif /* DNS_DEBUG */ + +#if LWIP_DNS_API_HOSTENT_STORAGE + /* this function should return the "per-thread" hostent after copy from s_hostent */ + return sys_thread_hostent(&s_hostent); +#else + return &s_hostent; +#endif /* LWIP_DNS_API_HOSTENT_STORAGE */ +} + +/** + * Thread-safe variant of lwip_gethostbyname: instead of using a static + * buffer, this function takes buffer and errno pointers as arguments + * and uses these for the result. + * + * @param name the hostname to resolve + * @param ret pre-allocated struct where to store the result + * @param buf pre-allocated buffer where to store additional data + * @param buflen the size of buf + * @param result pointer to a hostent pointer that is set to ret on success + * and set to zero on error + * @param h_errnop pointer to an int where to store errors (instead of modifying + * the global h_errno) + * @return 0 on success, non-zero on error, additional error information + * is stored in *h_errnop instead of h_errno to be thread-safe + */ +int +lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf, + size_t buflen, struct hostent **result, int *h_errnop) +{ + err_t err; + struct gethostbyname_r_helper *h; + char *hostname; + size_t namelen; + int lh_errno; + + if (h_errnop == NULL) { + /* ensure h_errnop is never NULL */ + h_errnop = &lh_errno; + } + + if (result == NULL) { + /* not all arguments given */ + *h_errnop = EINVAL; + return -1; + } + /* first thing to do: set *result to nothing */ + *result = NULL; + if ((name == NULL) || (ret == NULL) || (buf == 0)) { + /* not all arguments given */ + *h_errnop = EINVAL; + return -1; + } + + namelen = strlen(name); + if (buflen < (sizeof(struct gethostbyname_r_helper) + namelen + 1 + (MEM_ALIGNMENT - 1))) { + /* buf can't hold the data needed + a copy of name */ + *h_errnop = ERANGE; + return -1; + } + + h = (struct gethostbyname_r_helper*)LWIP_MEM_ALIGN(buf); + hostname = ((char*)h) + sizeof(struct gethostbyname_r_helper); + + /* query host IP address */ + err = netconn_gethostbyname(name, &(h->addr)); + if (err != ERR_OK) { + LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err)); + *h_errnop = ENSRNOTFOUND; + return -1; + } + + /* copy the hostname into buf */ + MEMCPY(hostname, name, namelen); + hostname[namelen] = 0; + + /* fill hostent */ + h->addrs = &(h->addr); + h->aliases = NULL; + ret->h_name = (char*)hostname; + ret->h_aliases = &(h->aliases); + ret->h_addrtype = AF_INET; + ret->h_length = sizeof(struct ip_addr); + ret->h_addr_list = (char**)&(h->addrs); + + /* set result != NULL */ + *result = ret; + + /* return success */ + return 0; +} + +/** + * Frees one or more addrinfo structures returned by getaddrinfo(), along with + * any additional storage associated with those structures. If the ai_next field + * of the structure is not null, the entire list of structures is freed. + * + * @param ai struct addrinfo to free + */ +void +lwip_freeaddrinfo(struct addrinfo *ai) +{ + struct addrinfo *next; + + while (ai != NULL) { + next = ai->ai_next; + mem_free(ai); + ai = next; + } +} + +/** + * Translates the name of a service location (for example, a host name) and/or + * a service name and returns a set of socket addresses and associated + * information to be used in creating a socket with which to address the + * specified service. + * Memory for the result is allocated internally and must be freed by calling + * lwip_freeaddrinfo()! + * + * Due to a limitation in dns_gethostbyname, only the first address of a + * host is returned. + * Also, service names are not supported (only port numbers)! + * + * @param nodename descriptive name or address string of the host + * (may be NULL -> local address) + * @param servname port number as string of NULL + * @param hints structure containing input values that set socktype and protocol + * @param res pointer to a pointer where to store the result (set to NULL on failure) + * @return 0 on success, non-zero on failure + */ +int +lwip_getaddrinfo(const char *nodename, const char *servname, + const struct addrinfo *hints, struct addrinfo **res) +{ + err_t err; + struct ip_addr addr; + struct addrinfo *ai; + struct sockaddr_in *sa = NULL; + int port_nr = 0; + size_t total_size; + size_t namelen = 0; + + if (res == NULL) { + return EAI_FAIL; + } + *res = NULL; + if ((nodename == NULL) && (servname == NULL)) { + return EAI_NONAME; + } + + if (servname != NULL) { + /* service name specified: convert to port number + * @todo?: currently, only ASCII integers (port numbers) are supported! */ + port_nr = atoi(servname); + if ((port_nr <= 0) || (port_nr > 0xffff)) { + return EAI_SERVICE; + } + } + + if (nodename != NULL) { + /* service location specified, try to resolve */ + err = netconn_gethostbyname(nodename, &addr); + if (err != ERR_OK) { + return EAI_FAIL; + } + } else { + /* service location specified, use loopback address */ + addr.addr = htonl(INADDR_LOOPBACK); + } + + total_size = sizeof(struct addrinfo) + sizeof(struct sockaddr_in); + if (nodename != NULL) { + namelen = strlen(nodename); + LWIP_ASSERT("namelen is too long", (namelen + 1) <= (mem_size_t)-1); + total_size += namelen + 1; + } + ai = mem_malloc(total_size); + if (ai == NULL) { + goto memerr; + } + memset(ai, 0, total_size); + sa = (struct sockaddr_in*)((u8_t*)ai + sizeof(struct addrinfo)); + /* set up sockaddr */ + sa->sin_addr.s_addr = addr.addr; + sa->sin_family = AF_INET; + sa->sin_len = sizeof(struct sockaddr_in); + sa->sin_port = htons(port_nr); + + /* set up addrinfo */ + ai->ai_family = AF_INET; + if (hints != NULL) { + /* copy socktype & protocol from hints if specified */ + ai->ai_socktype = hints->ai_socktype; + ai->ai_protocol = hints->ai_protocol; + } + if (nodename != NULL) { + /* copy nodename to canonname if specified */ + ai->ai_canonname = ((char*)ai + sizeof(struct addrinfo) + sizeof(struct sockaddr_in)); + MEMCPY(ai->ai_canonname, nodename, namelen); + ai->ai_canonname[namelen] = 0; + } + ai->ai_addrlen = sizeof(struct sockaddr_in); + ai->ai_addr = (struct sockaddr*)sa; + + *res = ai; + + return 0; +memerr: + if (ai != NULL) { + mem_free(ai); + } + return EAI_MEMORY; +} + +#endif /* LWIP_DNS && LWIP_SOCKET */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/api/netifapi.c b/component/common/network/lwip/lwip_v1.3.2/src/api/netifapi.c new file mode 100644 index 0000000..6ee58dc --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/api/netifapi.c @@ -0,0 +1,162 @@ +/** + * @file + * Network Interface Sequential API module + * + **/ + +/* + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/opt.h" + +#if LWIP_NETIF_API /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/netifapi.h" +#include "lwip/tcpip.h" + +/** + * Call netif_add() inside the tcpip_thread context. + */ +void +do_netifapi_netif_add( struct netifapi_msg_msg *msg) +{ + if (!netif_add( msg->netif, + msg->msg.add.ipaddr, + msg->msg.add.netmask, + msg->msg.add.gw, + msg->msg.add.state, + msg->msg.add.init, + msg->msg.add.input)) { + msg->err = ERR_IF; + } else { + msg->err = ERR_OK; + } + TCPIP_NETIFAPI_ACK(msg); +} + +/** + * Call netif_set_addr() inside the tcpip_thread context. + */ +void +do_netifapi_netif_set_addr( struct netifapi_msg_msg *msg) +{ + netif_set_addr( msg->netif, + msg->msg.add.ipaddr, + msg->msg.add.netmask, + msg->msg.add.gw); + msg->err = ERR_OK; + TCPIP_NETIFAPI_ACK(msg); +} + +/** + * Call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) inside the + * tcpip_thread context. + */ +void +do_netifapi_netif_common( struct netifapi_msg_msg *msg) +{ + if (msg->msg.common.errtfunc!=NULL) { + msg->err = + msg->msg.common.errtfunc(msg->netif); + } else { + msg->err = ERR_OK; + msg->msg.common.voidfunc(msg->netif); + } + TCPIP_NETIFAPI_ACK(msg); +} + +/** + * Call netif_add() in a thread-safe way by running that function inside the + * tcpip_thread context. + * + * @note for params @see netif_add() + */ +err_t +netifapi_netif_add(struct netif *netif, + struct ip_addr *ipaddr, + struct ip_addr *netmask, + struct ip_addr *gw, + void *state, + err_t (* init)(struct netif *netif), + err_t (* input)(struct pbuf *p, struct netif *netif)) +{ + struct netifapi_msg msg; + msg.function = do_netifapi_netif_add; + msg.msg.netif = netif; + msg.msg.msg.add.ipaddr = ipaddr; + msg.msg.msg.add.netmask = netmask; + msg.msg.msg.add.gw = gw; + msg.msg.msg.add.state = state; + msg.msg.msg.add.init = init; + msg.msg.msg.add.input = input; + TCPIP_NETIFAPI(&msg); + return msg.msg.err; +} + +/** + * Call netif_set_addr() in a thread-safe way by running that function inside the + * tcpip_thread context. + * + * @note for params @see netif_set_addr() + */ +err_t +netifapi_netif_set_addr(struct netif *netif, + struct ip_addr *ipaddr, + struct ip_addr *netmask, + struct ip_addr *gw) +{ + struct netifapi_msg msg; + msg.function = do_netifapi_netif_set_addr; + msg.msg.netif = netif; + msg.msg.msg.add.ipaddr = ipaddr; + msg.msg.msg.add.netmask = netmask; + msg.msg.msg.add.gw = gw; + TCPIP_NETIFAPI(&msg); + return msg.msg.err; +} + +/** + * call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) in a thread-safe + * way by running that function inside the tcpip_thread context. + * + * @note use only for functions where there is only "netif" parameter. + */ +err_t +netifapi_netif_common( struct netif *netif, + void (* voidfunc)(struct netif *netif), + err_t (* errtfunc)(struct netif *netif) ) +{ + struct netifapi_msg msg; + msg.function = do_netifapi_netif_common; + msg.msg.netif = netif; + msg.msg.msg.common.voidfunc = voidfunc; + msg.msg.msg.common.errtfunc = errtfunc; + TCPIP_NETIFAPI(&msg); + return msg.msg.err; +} + +#endif /* LWIP_NETIF_API */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/api/sockets.c b/component/common/network/lwip/lwip_v1.3.2/src/api/sockets.c new file mode 100644 index 0000000..bf09d46 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/api/sockets.c @@ -0,0 +1,1971 @@ +/** + * @file + * Sockets BSD-Like API module + * + **/ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + * Improved by Marc Boucher and David Haas + * + */ + +#include "lwip/opt.h" + +#if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/sockets.h" +#include "lwip/api.h" +#include "lwip/sys.h" +#include "lwip/igmp.h" +#include "lwip/inet.h" +#include "lwip/tcp.h" +#include "lwip/raw.h" +#include "lwip/udp.h" +#include "lwip/tcpip.h" + +#include + +#define NUM_SOCKETS MEMP_NUM_NETCONN + +/** Contains all internal pointers and states used for a socket */ +struct lwip_socket { + /** sockets currently are built on netconns, each socket has one netconn */ + struct netconn *conn; + /** data that was left from the previous read */ + struct netbuf *lastdata; + /** offset in the data that was left from the previous read */ + u16_t lastoffset; + /** number of times data was received, set by event_callback(), + tested by the receive and select functions */ + s16_t rcvevent; + /** number of times data was received, set by event_callback(), + tested by select */ + u16_t sendevent; + /** socket flags (currently, only used for O_NONBLOCK) */ + u16_t flags; + /** last error that occurred on this socket */ + int err; +}; + +/** Description for a task waiting in select */ +struct lwip_select_cb { + /** Pointer to the next waiting task */ + struct lwip_select_cb *next; + /** readset passed to select */ + fd_set *readset; + /** writeset passed to select */ + fd_set *writeset; + /** unimplemented: exceptset passed to select */ + fd_set *exceptset; + /** don't signal the same semaphore twice: set to 1 when signalled */ + int sem_signalled; + /** semaphore to wake up a task waiting for select */ + sys_sem_t sem; +}; + +/** This struct is used to pass data to the set/getsockopt_internal + * functions running in tcpip_thread context (only a void* is allowed) */ +struct lwip_setgetsockopt_data { + /** socket struct for which to change options */ + struct lwip_socket *sock; + /** socket index for which to change options */ + int s; + /** level of the option to process */ + int level; + /** name of the option to process */ + int optname; + /** set: value to set the option to + * get: value of the option is stored here */ + void *optval; + /** size of *optval */ + socklen_t *optlen; + /** if an error occures, it is temporarily stored here */ + err_t err; +}; + +/** The global array of available sockets */ +static struct lwip_socket sockets[NUM_SOCKETS]; +/** The global list of tasks waiting for select */ +static struct lwip_select_cb *select_cb_list; + +/** Semaphore protecting the sockets array */ +static sys_sem_t socksem; +/** Semaphore protecting select_cb_list */ +static sys_sem_t selectsem; + +/** Table to quickly map an lwIP error (err_t) to a socket error + * by using -err as an index */ +static const int err_to_errno_table[] = { + 0, /* ERR_OK 0 No error, everything OK. */ + ENOMEM, /* ERR_MEM -1 Out of memory error. */ + ENOBUFS, /* ERR_BUF -2 Buffer error. */ + ETIMEDOUT, /* ERR_TIMEOUT -3 Timeout */ + EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */ + ECONNABORTED, /* ERR_ABRT -5 Connection aborted. */ + ECONNRESET, /* ERR_RST -6 Connection reset. */ + ESHUTDOWN, /* ERR_CLSD -7 Connection closed. */ + ENOTCONN, /* ERR_CONN -8 Not connected. */ + EINVAL, /* ERR_VAL -9 Illegal value. */ + EIO, /* ERR_ARG -10 Illegal argument. */ + EADDRINUSE, /* ERR_USE -11 Address in use. */ + -1, /* ERR_IF -12 Low-level netif error */ + -1, /* ERR_ISCONN -13 Already connected. */ + EINPROGRESS /* ERR_INPROGRESS -14 Operation in progress */ +}; + +#define ERR_TO_ERRNO_TABLE_SIZE \ + (sizeof(err_to_errno_table)/sizeof(err_to_errno_table[0])) + +#define err_to_errno(err) \ + ((unsigned)(-(err)) < ERR_TO_ERRNO_TABLE_SIZE ? \ + err_to_errno_table[-(err)] : EIO) + +#ifdef ERRNO +#ifndef set_errno +#define set_errno(err) errno = (err) +#endif +#else +#define set_errno(err) +#endif + +#define sock_set_errno(sk, e) do { \ + sk->err = (e); \ + set_errno(sk->err); \ +} while (0) + +/* Forward delcaration of some functions */ +static void event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len); +static void lwip_getsockopt_internal(void *arg); +static void lwip_setsockopt_internal(void *arg); + +/** + * Initialize this module. This function has to be called before any other + * functions in this module! + */ +void +lwip_socket_init(void) +{ + socksem = sys_sem_new(1); + selectsem = sys_sem_new(1); +} + +/** + * Map a externally used socket index to the internal socket representation. + * + * @param s externally used socket index + * @return struct lwip_socket for the socket or NULL if not found + */ +static struct lwip_socket * +get_socket(int s) +{ + struct lwip_socket *sock; + + if ((s < 0) || (s >= NUM_SOCKETS)) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): invalid\n", s)); + set_errno(EBADF); + return NULL; + } + + sock = &sockets[s]; + + if (!sock->conn) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): not active\n", s)); + set_errno(EBADF); + return NULL; + } + + return sock; +} + +/** + * Allocate a new socket for a given netconn. + * + * @param newconn the netconn for which to allocate a socket + * @return the index of the new socket; -1 on error + */ +static int +alloc_socket(struct netconn *newconn) +{ + int i; + + /* Protect socket array */ + sys_sem_wait(socksem); + + /* allocate a new socket identifier */ + for (i = 0; i < NUM_SOCKETS; ++i) { + if (!sockets[i].conn) { + sockets[i].conn = newconn; + sockets[i].lastdata = NULL; + sockets[i].lastoffset = 0; + sockets[i].rcvevent = 0; + sockets[i].sendevent = 1; /* TCP send buf is empty */ + sockets[i].flags = 0; + sockets[i].err = 0; + sys_sem_signal(socksem); + return i; + } + } + sys_sem_signal(socksem); + return -1; +} + +/* Below this, the well-known socket functions are implemented. + * Use google.com or opengroup.org to get a good description :-) + * + * Exceptions are documented! + */ + +int +lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen) +{ + struct lwip_socket *sock, *nsock; + struct netconn *newconn; + struct ip_addr naddr; + u16_t port; + int newsock; + struct sockaddr_in sin; + err_t err; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s)); + sock = get_socket(s); + if (!sock) + return -1; + + if ((sock->flags & O_NONBLOCK) && (sock->rcvevent <= 0)) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): returning EWOULDBLOCK\n", s)); + sock_set_errno(sock, EWOULDBLOCK); + return -1; + } + + newconn = netconn_accept(sock->conn); + if (!newconn) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) failed, err=%d\n", s, sock->conn->err)); + sock_set_errno(sock, err_to_errno(sock->conn->err)); + return -1; + } + + /* get the IP address and port of the remote host */ + err = netconn_peer(newconn, &naddr, &port); + if (err != ERR_OK) { + netconn_delete(newconn); + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + + /* Note that POSIX only requires us to check addr is non-NULL. addrlen must + * not be NULL if addr is valid. + */ + if (NULL != addr) { + LWIP_ASSERT("addr valid but addrlen NULL", addrlen != NULL); + memset(&sin, 0, sizeof(sin)); + sin.sin_len = sizeof(sin); + sin.sin_family = AF_INET; + sin.sin_port = htons(port); + sin.sin_addr.s_addr = naddr.addr; + + if (*addrlen > sizeof(sin)) + *addrlen = sizeof(sin); + + MEMCPY(addr, &sin, *addrlen); + } + + newsock = alloc_socket(newconn); + if (newsock == -1) { + netconn_delete(newconn); + sock_set_errno(sock, ENFILE); + return -1; + } + LWIP_ASSERT("invalid socket index", (newsock >= 0) && (newsock < NUM_SOCKETS)); + newconn->callback = event_callback; + nsock = &sockets[newsock]; + LWIP_ASSERT("invalid socket pointer", nsock != NULL); + + sys_sem_wait(socksem); + /* See event_callback: If data comes in right away after an accept, even + * though the server task might not have created a new socket yet. + * In that case, newconn->socket is counted down (newconn->socket--), + * so nsock->rcvevent is >= 1 here! + */ + nsock->rcvevent += -1 - newconn->socket; + newconn->socket = newsock; + sys_sem_signal(socksem); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d addr=", s, newsock)); + ip_addr_debug_print(SOCKETS_DEBUG, &naddr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", port)); + + sock_set_errno(sock, 0); + return newsock; +} + +int +lwip_bind(int s, const struct sockaddr *name, socklen_t namelen) +{ + struct lwip_socket *sock; + struct ip_addr local_addr; + u16_t local_port; + err_t err; + + sock = get_socket(s); + if (!sock) + return -1; + + LWIP_ERROR("lwip_bind: invalid address", ((namelen == sizeof(struct sockaddr_in)) && + ((((const struct sockaddr_in *)name)->sin_family) == AF_INET)), + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + + local_addr.addr = ((const struct sockaddr_in *)name)->sin_addr.s_addr; + local_port = ((const struct sockaddr_in *)name)->sin_port; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s)); + ip_addr_debug_print(SOCKETS_DEBUG, &local_addr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", ntohs(local_port))); + + err = netconn_bind(sock->conn, &local_addr, ntohs(local_port)); + + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) failed, err=%d\n", s, err)); + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) succeeded\n", s)); + sock_set_errno(sock, 0); + return 0; +} + +int +lwip_close(int s) +{ + struct lwip_socket *sock; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_close(%d)\n", s)); + + sock = get_socket(s); + if (!sock) { + return -1; + } + + netconn_delete(sock->conn); + + sys_sem_wait(socksem); + if (sock->lastdata) { + netbuf_delete(sock->lastdata); + } + sock->lastdata = NULL; + sock->lastoffset = 0; + sock->conn = NULL; + sock_set_errno(sock, 0); + sys_sem_signal(socksem); + return 0; +} + +int +lwip_connect(int s, const struct sockaddr *name, socklen_t namelen) +{ + struct lwip_socket *sock; + err_t err; + + sock = get_socket(s); + if (!sock) + return -1; + + LWIP_ERROR("lwip_connect: invalid address", ((namelen == sizeof(struct sockaddr_in)) && + ((((const struct sockaddr_in *)name)->sin_family) == AF_INET)), + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + + if (((const struct sockaddr_in *)name)->sin_family == AF_UNSPEC) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, AF_UNSPEC)\n", s)); + err = netconn_disconnect(sock->conn); + } else { + struct ip_addr remote_addr; + u16_t remote_port; + + remote_addr.addr = ((const struct sockaddr_in *)name)->sin_addr.s_addr; + remote_port = ((const struct sockaddr_in *)name)->sin_port; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, addr=", s)); + ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", ntohs(remote_port))); + + err = netconn_connect(sock->conn, &remote_addr, ntohs(remote_port)); + } + + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) failed, err=%d\n", s, err)); + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) succeeded\n", s)); + sock_set_errno(sock, 0); + return 0; +} + +/** + * Set a socket into listen mode. + * The socket may not have been used for another connection previously. + * + * @param s the socket to set to listening mode + * @param backlog (ATTENTION: need TCP_LISTEN_BACKLOG=1) + * @return 0 on success, non-zero on failure + */ +int +lwip_listen(int s, int backlog) +{ + struct lwip_socket *sock; + err_t err; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d, backlog=%d)\n", s, backlog)); + + sock = get_socket(s); + if (!sock) + return -1; + + /* limit the "backlog" parameter to fit in an u8_t */ + if (backlog < 0) { + backlog = 0; + } + if (backlog > 0xff) { + backlog = 0xff; + } + + err = netconn_listen_with_backlog(sock->conn, backlog); + + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d) failed, err=%d\n", s, err)); + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + + sock_set_errno(sock, 0); + return 0; +} + +int +lwip_recvfrom(int s, void *mem, size_t len, int flags, + struct sockaddr *from, socklen_t *fromlen) +{ + struct lwip_socket *sock; + struct netbuf *buf; + u16_t buflen, copylen, off = 0; + struct ip_addr *addr; + u16_t port; + u8_t done = 0; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %"SZT_F", 0x%x, ..)\n", s, mem, len, flags)); + sock = get_socket(s); + if (!sock) + return -1; + + do { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: top while sock->lastdata=%p\n", (void*)sock->lastdata)); + /* Check if there is data left from the last recv operation. */ + if (sock->lastdata) { + buf = sock->lastdata; + } else { + /* If this is non-blocking call, then check first */ + if (((flags & MSG_DONTWAIT) || (sock->flags & O_NONBLOCK)) && + (sock->rcvevent <= 0)) { + if (off > 0) { + /* already received data, return that */ + sock_set_errno(sock, 0); + return off; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s)); + sock_set_errno(sock, EWOULDBLOCK); + return -1; + } + + /* No data was left from the previous operation, so we try to get + some from the network. */ + sock->lastdata = buf = netconn_recv(sock->conn); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: netconn_recv netbuf=%p\n", (void*)buf)); + + if (!buf) { + if (off > 0) { + /* already received data, return that */ + sock_set_errno(sock, 0); + return off; + } + /* We should really do some error checking here. */ + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): buf == NULL!\n", s)); + sock_set_errno(sock, (((sock->conn->pcb.ip != NULL) && (sock->conn->err == ERR_OK)) + ? ETIMEDOUT : err_to_errno(sock->conn->err))); + return 0; + } + } + + buflen = netbuf_len(buf); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: buflen=%"U16_F" len=%"SZT_F" off=%"U16_F" sock->lastoffset=%"U16_F"\n", + buflen, len, off, sock->lastoffset)); + + buflen -= sock->lastoffset; + + if (len > buflen) { + copylen = buflen; + } else { + copylen = (u16_t)len; + } + + /* copy the contents of the received buffer into + the supplied memory pointer mem */ + netbuf_copy_partial(buf, (u8_t*)mem + off, copylen, sock->lastoffset); + + off += copylen; + + if (netconn_type(sock->conn) == NETCONN_TCP) { + LWIP_ASSERT("invalid copylen, len would underflow", len >= copylen); + len -= copylen; + if ( (len <= 0) || + (buf->p->flags & PBUF_FLAG_PUSH) || + (sock->rcvevent <= 0) || + ((flags & MSG_PEEK)!=0)) { + done = 1; + } + } else { + done = 1; + } + + /* Check to see from where the data was.*/ + if (done) { + if (from && fromlen) { + struct sockaddr_in sin; + + if (netconn_type(sock->conn) == NETCONN_TCP) { + addr = (struct ip_addr*)&(sin.sin_addr.s_addr); + netconn_getaddr(sock->conn, addr, &port, 0); + } else { + addr = netbuf_fromaddr(buf); + port = netbuf_fromport(buf); + } + + memset(&sin, 0, sizeof(sin)); + sin.sin_len = sizeof(sin); + sin.sin_family = AF_INET; + sin.sin_port = htons(port); + sin.sin_addr.s_addr = addr->addr; + + if (*fromlen > sizeof(sin)) { + *fromlen = sizeof(sin); + } + + MEMCPY(from, &sin, *fromlen); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s)); + ip_addr_debug_print(SOCKETS_DEBUG, addr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%"U16_F"\n", port, off)); + } else { + #if SOCKETS_DEBUG + struct sockaddr_in sin; + + if (netconn_type(sock->conn) == NETCONN_TCP) { + addr = (struct ip_addr*)&(sin.sin_addr.s_addr); + netconn_getaddr(sock->conn, addr, &port, 0); + } else { + addr = netbuf_fromaddr(buf); + port = netbuf_fromport(buf); + } + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s)); + ip_addr_debug_print(SOCKETS_DEBUG, addr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%"U16_F"\n", port, off)); + #endif /* SOCKETS_DEBUG */ + } + } + + /* If we don't peek the incoming message... */ + if ((flags & MSG_PEEK)==0) { + /* If this is a TCP socket, check if there is data left in the + buffer. If so, it should be saved in the sock structure for next + time around. */ + if ((netconn_type(sock->conn) == NETCONN_TCP) && (buflen - copylen > 0)) { + sock->lastdata = buf; + sock->lastoffset += copylen; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: lastdata now netbuf=%p\n", (void*)buf)); + } else { + sock->lastdata = NULL; + sock->lastoffset = 0; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: deleting netbuf=%p\n", (void*)buf)); + netbuf_delete(buf); + } + } + } while (!done); + + sock_set_errno(sock, 0); + return off; +} + +int +lwip_read(int s, void *mem, size_t len) +{ + return lwip_recvfrom(s, mem, len, 0, NULL, NULL); +} + +int +lwip_recv(int s, void *mem, size_t len, int flags) +{ + return lwip_recvfrom(s, mem, len, flags, NULL, NULL); +} + +int +lwip_send(int s, const void *data, size_t size, int flags) +{ + struct lwip_socket *sock; + err_t err; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d, data=%p, size=%"SZT_F", flags=0x%x)\n", + s, data, size, flags)); + + sock = get_socket(s); + if (!sock) + return -1; + + if (sock->conn->type != NETCONN_TCP) { +#if (LWIP_UDP || LWIP_RAW) + return lwip_sendto(s, data, size, flags, NULL, 0); +#else + sock_set_errno(sock, err_to_errno(ERR_ARG)); + return -1; +#endif /* (LWIP_UDP || LWIP_RAW) */ + } + + err = netconn_write(sock->conn, data, size, NETCONN_COPY | ((flags & MSG_MORE)?NETCONN_MORE:0)); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) err=%d size=%"SZT_F"\n", s, err, size)); + sock_set_errno(sock, err_to_errno(err)); + return (err == ERR_OK ? (int)size : -1); +} + +int +lwip_sendto(int s, const void *data, size_t size, int flags, + const struct sockaddr *to, socklen_t tolen) +{ + struct lwip_socket *sock; + struct ip_addr remote_addr; + err_t err; + u16_t short_size; +#if !LWIP_TCPIP_CORE_LOCKING + struct netbuf buf; + u16_t remote_port; +#endif + + sock = get_socket(s); + if (!sock) + return -1; + + if (sock->conn->type == NETCONN_TCP) { +#if LWIP_TCP + return lwip_send(s, data, size, flags); +#else + sock_set_errno(sock, err_to_errno(ERR_ARG)); + return -1; +#endif /* LWIP_TCP */ + } + + LWIP_ASSERT("lwip_sendto: size must fit in u16_t", size <= 0xffff); + short_size = (u16_t)size; + LWIP_ERROR("lwip_sendto: invalid address", (((to == NULL) && (tolen == 0)) || + ((tolen == sizeof(struct sockaddr_in)) && + ((((const struct sockaddr_in *)to)->sin_family) == AF_INET))), + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + +#if LWIP_TCPIP_CORE_LOCKING + /* Should only be consider like a sample or a simple way to experiment this option (no check of "to" field...) */ + { struct pbuf* p; + + p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF); + if (p == NULL) { + err = ERR_MEM; + } else { + p->payload = (void*)data; + p->len = p->tot_len = short_size; + + remote_addr.addr = ((const struct sockaddr_in *)to)->sin_addr.s_addr; + + LOCK_TCPIP_CORE(); + if (sock->conn->type==NETCONN_RAW) { + err = sock->conn->err = raw_sendto(sock->conn->pcb.raw, p, &remote_addr); + } else { + err = sock->conn->err = udp_sendto(sock->conn->pcb.udp, p, &remote_addr, ntohs(((const struct sockaddr_in *)to)->sin_port)); + } + UNLOCK_TCPIP_CORE(); + + pbuf_free(p); + } + } +#else + /* initialize a buffer */ + buf.p = buf.ptr = NULL; + if (to) { + remote_addr.addr = ((const struct sockaddr_in *)to)->sin_addr.s_addr; + remote_port = ntohs(((const struct sockaddr_in *)to)->sin_port); + buf.addr = &remote_addr; + buf.port = remote_port; + } else { + remote_addr.addr = 0; + remote_port = 0; + buf.addr = NULL; + buf.port = 0; + } + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, short_size=%d"U16_F", flags=0x%x to=", + s, data, short_size, flags)); + ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port)); + + /* make the buffer point to the data that should be sent */ +#if LWIP_NETIF_TX_SINGLE_PBUF + /* Allocate a new netbuf and copy the data into it. */ + if (netbuf_alloc(&buf, short_size) == NULL) { + err = ERR_MEM; + } else { + err = netbuf_take(&buf, data, short_size); + } +#else /* LWIP_NETIF_TX_SINGLE_PBUF */ + err = netbuf_ref(&buf, data, short_size); +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + if (err == ERR_OK) { + /* send the data */ + err = netconn_send(sock->conn, &buf); + } + + /* deallocated the buffer */ + netbuf_free(&buf); +#endif /* LWIP_TCPIP_CORE_LOCKING */ + sock_set_errno(sock, err_to_errno(err)); + return (err == ERR_OK ? short_size : -1); +} + +int +lwip_socket(int domain, int type, int protocol) +{ + struct netconn *conn; + int i; + + LWIP_UNUSED_ARG(domain); + + /* create a netconn */ + switch (type) { + case SOCK_RAW: + conn = netconn_new_with_proto_and_callback(NETCONN_RAW, (u8_t)protocol, event_callback); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ", + domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); + break; + case SOCK_DGRAM: + conn = netconn_new_with_callback( (protocol == IPPROTO_UDPLITE) ? + NETCONN_UDPLITE : NETCONN_UDP, event_callback); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_DGRAM, %d) = ", + domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); + break; + case SOCK_STREAM: + conn = netconn_new_with_callback(NETCONN_TCP, event_callback); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_STREAM, %d) = ", + domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%d, %d/UNKNOWN, %d) = -1\n", + domain, type, protocol)); + set_errno(EINVAL); + return -1; + } + + if (!conn) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("-1 / ENOBUFS (could not create netconn)\n")); + set_errno(ENOBUFS); + return -1; + } + + i = alloc_socket(conn); + + if (i == -1) { + netconn_delete(conn); + set_errno(ENFILE); + return -1; + } + conn->socket = i; + LWIP_DEBUGF(SOCKETS_DEBUG, ("%d\n", i)); + set_errno(0); + return i; +} + +int +lwip_write(int s, const void *data, size_t size) +{ + return lwip_send(s, data, size, 0); +} + +/** + * Go through the readset and writeset lists and see which socket of the sockets + * set in the sets has events. On return, readset, writeset and exceptset have + * the sockets enabled that had events. + * + * exceptset is not used for now!!! + * + * @param maxfdp1 the highest socket index in the sets + * @param readset in: set of sockets to check for read events; + * out: set of sockets that had read events + * @param writeset in: set of sockets to check for write events; + * out: set of sockets that had write events + * @param exceptset not yet implemented + * @return number of sockets that had events (read+write) + */ +static int +lwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset) +{ + int i, nready = 0; + fd_set lreadset, lwriteset, lexceptset; + struct lwip_socket *p_sock; + + FD_ZERO(&lreadset); + FD_ZERO(&lwriteset); + FD_ZERO(&lexceptset); + + /* Go through each socket in each list to count number of sockets which + currently match */ + for(i = 0; i < maxfdp1; i++) { + if (FD_ISSET(i, readset)) { + /* See if netconn of this socket is ready for read */ + p_sock = get_socket(i); + if (p_sock && (p_sock->lastdata || (p_sock->rcvevent > 0))) { + FD_SET(i, &lreadset); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for reading\n", i)); + nready++; + } + } + if (FD_ISSET(i, writeset)) { + /* See if netconn of this socket is ready for write */ + p_sock = get_socket(i); + if (p_sock && p_sock->sendevent) { + FD_SET(i, &lwriteset); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for writing\n", i)); + nready++; + } + } + } + *readset = lreadset; + *writeset = lwriteset; + FD_ZERO(exceptset); + + return nready; +} + + +/** + * Processing exceptset is not yet implemented. + */ +int +lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, + struct timeval *timeout) +{ + int i; + int nready; + fd_set lreadset, lwriteset, lexceptset; + u32_t msectimeout; + struct lwip_select_cb select_cb; + struct lwip_select_cb *p_selcb; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select(%d, %p, %p, %p, tvsec=%ld tvusec=%ld)\n", + maxfdp1, (void *)readset, (void *) writeset, (void *) exceptset, + timeout ? (long)timeout->tv_sec : (long)-1, + timeout ? (long)timeout->tv_usec : (long)-1)); + + select_cb.next = 0; + select_cb.readset = readset; + select_cb.writeset = writeset; + select_cb.exceptset = exceptset; + select_cb.sem_signalled = 0; + + /* Protect ourselves searching through the list */ + sys_sem_wait(selectsem); + + if (readset) + lreadset = *readset; + else + FD_ZERO(&lreadset); + if (writeset) + lwriteset = *writeset; + else + FD_ZERO(&lwriteset); + if (exceptset) + lexceptset = *exceptset; + else + FD_ZERO(&lexceptset); + + /* Go through each socket in each list to count number of sockets which + currently match */ + nready = lwip_selscan(maxfdp1, &lreadset, &lwriteset, &lexceptset); + + /* If we don't have any current events, then suspend if we are supposed to */ + if (!nready) { + if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0) { + sys_sem_signal(selectsem); + if (readset) + FD_ZERO(readset); + if (writeset) + FD_ZERO(writeset); + if (exceptset) + FD_ZERO(exceptset); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: no timeout, returning 0\n")); + set_errno(0); + + return 0; + } + + /* add our semaphore to list */ + /* We don't actually need any dynamic memory. Our entry on the + * list is only valid while we are in this function, so it's ok + * to use local variables */ + + select_cb.sem = sys_sem_new(0); + /* Note that we are still protected */ + /* Put this select_cb on top of list */ + select_cb.next = select_cb_list; + select_cb_list = &select_cb; + + /* Now we can safely unprotect */ + sys_sem_signal(selectsem); + + /* Now just wait to be woken */ + if (timeout == 0) + /* Wait forever */ + msectimeout = 0; + else { + msectimeout = ((timeout->tv_sec * 1000) + ((timeout->tv_usec + 500)/1000)); + if(msectimeout == 0) + msectimeout = 1; + } + + i = sys_sem_wait_timeout(select_cb.sem, msectimeout); + + /* Take us off the list */ + sys_sem_wait(selectsem); + if (select_cb_list == &select_cb) + select_cb_list = select_cb.next; + else + for (p_selcb = select_cb_list; p_selcb; p_selcb = p_selcb->next) { + if (p_selcb->next == &select_cb) { + p_selcb->next = select_cb.next; + break; + } + } + + sys_sem_signal(selectsem); + + sys_sem_free(select_cb.sem); + if (i == 0) { + /* Timeout */ + if (readset) + FD_ZERO(readset); + if (writeset) + FD_ZERO(writeset); + if (exceptset) + FD_ZERO(exceptset); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n")); + set_errno(0); + + return 0; + } + + if (readset) + lreadset = *readset; + else + FD_ZERO(&lreadset); + if (writeset) + lwriteset = *writeset; + else + FD_ZERO(&lwriteset); + if (exceptset) + lexceptset = *exceptset; + else + FD_ZERO(&lexceptset); + + /* See what's set */ + nready = lwip_selscan(maxfdp1, &lreadset, &lwriteset, &lexceptset); + } else + sys_sem_signal(selectsem); + + if (readset) + *readset = lreadset; + if (writeset) + *writeset = lwriteset; + if (exceptset) + *exceptset = lexceptset; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready)); + set_errno(0); + + return nready; +} + +/** + * Callback registered in the netconn layer for each socket-netconn. + * Processes recvevent (data available) and wakes up tasks waiting for select. + */ +static void +event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len) +{ + int s; + struct lwip_socket *sock; + struct lwip_select_cb *scb; + + LWIP_UNUSED_ARG(len); + + /* Get socket */ + if (conn) { + s = conn->socket; + if (s < 0) { + /* Data comes in right away after an accept, even though + * the server task might not have created a new socket yet. + * Just count down (or up) if that's the case and we + * will use the data later. Note that only receive events + * can happen before the new socket is set up. */ + sys_sem_wait(socksem); + if (conn->socket < 0) { + if (evt == NETCONN_EVT_RCVPLUS) { + conn->socket--; + } + sys_sem_signal(socksem); + return; + } + s = conn->socket; + sys_sem_signal(socksem); + } + + sock = get_socket(s); + if (!sock) { + return; + } + } else { + return; + } + + sys_sem_wait(selectsem); + /* Set event as required */ + switch (evt) { + case NETCONN_EVT_RCVPLUS: + sock->rcvevent++; + break; + case NETCONN_EVT_RCVMINUS: + sock->rcvevent--; + break; + case NETCONN_EVT_SENDPLUS: + sock->sendevent = 1; + break; + case NETCONN_EVT_SENDMINUS: + sock->sendevent = 0; + break; + default: + LWIP_ASSERT("unknown event", 0); + break; + } + sys_sem_signal(selectsem); + + /* Now decide if anyone is waiting for this socket */ + /* NOTE: This code is written this way to protect the select link list + but to avoid a deadlock situation by releasing socksem before + signalling for the select. This means we need to go through the list + multiple times ONLY IF a select was actually waiting. We go through + the list the number of waiting select calls + 1. This list is + expected to be small. */ + while (1) { + sys_sem_wait(selectsem); + for (scb = select_cb_list; scb; scb = scb->next) { + if (scb->sem_signalled == 0) { + /* Test this select call for our socket */ + if (scb->readset && FD_ISSET(s, scb->readset)) + if (sock->rcvevent > 0) + break; + if (scb->writeset && FD_ISSET(s, scb->writeset)) + if (sock->sendevent) + break; + } + } + if (scb) { + scb->sem_signalled = 1; + sys_sem_signal(scb->sem); + sys_sem_signal(selectsem); + } else { + sys_sem_signal(selectsem); + break; + } + } +} + +/** + * Unimplemented: Close one end of a full-duplex connection. + * Currently, the full connection is closed. + */ +int +lwip_shutdown(int s, int how) +{ + LWIP_UNUSED_ARG(how); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_shutdown(%d, how=%d)\n", s, how)); + return lwip_close(s); /* XXX temporary hack until proper implementation */ +} + +static int +lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local) +{ + struct lwip_socket *sock; + struct sockaddr_in sin; + struct ip_addr naddr; + + sock = get_socket(s); + if (!sock) + return -1; + + memset(&sin, 0, sizeof(sin)); + sin.sin_len = sizeof(sin); + sin.sin_family = AF_INET; + + /* get the IP address and port */ + netconn_getaddr(sock->conn, &naddr, &sin.sin_port, local); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getaddrname(%d, addr=", s)); + ip_addr_debug_print(SOCKETS_DEBUG, &naddr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", sin.sin_port)); + + sin.sin_port = htons(sin.sin_port); + sin.sin_addr.s_addr = naddr.addr; + + if (*namelen > sizeof(sin)) + *namelen = sizeof(sin); + + MEMCPY(name, &sin, *namelen); + sock_set_errno(sock, 0); + return 0; +} + +int +lwip_getpeername(int s, struct sockaddr *name, socklen_t *namelen) +{ + return lwip_getaddrname(s, name, namelen, 0); +} + +int +lwip_getsockname(int s, struct sockaddr *name, socklen_t *namelen) +{ + return lwip_getaddrname(s, name, namelen, 1); +} + +int +lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) +{ + err_t err = ERR_OK; + struct lwip_socket *sock = get_socket(s); + struct lwip_setgetsockopt_data data; + + if (!sock) + return -1; + + if ((NULL == optval) || (NULL == optlen)) { + sock_set_errno(sock, EFAULT); + return -1; + } + + /* Do length and type checks for the various options first, to keep it readable. */ + switch (level) { + +/* Level: SOL_SOCKET */ + case SOL_SOCKET: + switch (optname) { + + case SO_ACCEPTCONN: + case SO_BROADCAST: + /* UNIMPL case SO_DEBUG: */ + /* UNIMPL case SO_DONTROUTE: */ + case SO_ERROR: + case SO_KEEPALIVE: + /* UNIMPL case SO_CONTIMEO: */ + /* UNIMPL case SO_SNDTIMEO: */ +#if LWIP_SO_RCVTIMEO + case SO_RCVTIMEO: +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + case SO_RCVBUF: +#endif /* LWIP_SO_RCVBUF */ + /* UNIMPL case SO_OOBINLINE: */ + /* UNIMPL case SO_SNDBUF: */ + /* UNIMPL case SO_RCVLOWAT: */ + /* UNIMPL case SO_SNDLOWAT: */ +#if SO_REUSE + case SO_REUSEADDR: + case SO_REUSEPORT: +#endif /* SO_REUSE */ + case SO_TYPE: + /* UNIMPL case SO_USELOOPBACK: */ + if (*optlen < sizeof(int)) { + err = EINVAL; + } + break; + + case SO_NO_CHECK: + if (*optlen < sizeof(int)) { + err = EINVAL; + } +#if LWIP_UDP + if ((sock->conn->type != NETCONN_UDP) || + ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0)) { + /* this flag is only available for UDP, not for UDP lite */ + err = EAFNOSUPPORT; + } +#endif /* LWIP_UDP */ + break; + + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + } /* switch (optname) */ + break; + +/* Level: IPPROTO_IP */ + case IPPROTO_IP: + switch (optname) { + /* UNIMPL case IP_HDRINCL: */ + /* UNIMPL case IP_RCVDSTADDR: */ + /* UNIMPL case IP_RCVIF: */ + case IP_TTL: + case IP_TOS: + if (*optlen < sizeof(int)) { + err = EINVAL; + } + break; +#if LWIP_IGMP + case IP_MULTICAST_TTL: + if (*optlen < sizeof(u8_t)) { + err = EINVAL; + } + break; + case IP_MULTICAST_IF: + if (*optlen < sizeof(struct in_addr)) { + err = EINVAL; + } + break; +#endif /* LWIP_IGMP */ + + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + } /* switch (optname) */ + break; + +#if LWIP_TCP +/* Level: IPPROTO_TCP */ + case IPPROTO_TCP: + if (*optlen < sizeof(int)) { + err = EINVAL; + break; + } + + /* If this is no TCP socket, ignore any options. */ + if (sock->conn->type != NETCONN_TCP) + return 0; + + switch (optname) { + case TCP_NODELAY: + case TCP_KEEPALIVE: +#if LWIP_TCP_KEEPALIVE + case TCP_KEEPIDLE: + case TCP_KEEPINTVL: + case TCP_KEEPCNT: +#endif /* LWIP_TCP_KEEPALIVE */ + break; + + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + } /* switch (optname) */ + break; +#endif /* LWIP_TCP */ +#if LWIP_UDP && LWIP_UDPLITE +/* Level: IPPROTO_UDPLITE */ + case IPPROTO_UDPLITE: + if (*optlen < sizeof(int)) { + err = EINVAL; + break; + } + + /* If this is no UDP lite socket, ignore any options. */ + if (sock->conn->type != NETCONN_UDPLITE) + return 0; + + switch (optname) { + case UDPLITE_SEND_CSCOV: + case UDPLITE_RECV_CSCOV: + break; + + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + } /* switch (optname) */ + break; +#endif /* LWIP_UDP && LWIP_UDPLITE*/ +/* UNDEFINED LEVEL */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", + s, level, optname)); + err = ENOPROTOOPT; + } /* switch */ + + + if (err != ERR_OK) { + sock_set_errno(sock, err); + return -1; + } + + /* Now do the actual option processing */ + data.sock = sock; + data.level = level; + data.optname = optname; + data.optval = optval; + data.optlen = optlen; + data.err = err; + tcpip_callback(lwip_getsockopt_internal, &data); + sys_arch_sem_wait(sock->conn->op_completed, 0); + /* maybe lwip_getsockopt_internal has changed err */ + err = data.err; + + sock_set_errno(sock, err); + return err ? -1 : 0; +} + +static void +lwip_getsockopt_internal(void *arg) +{ + struct lwip_socket *sock; +#ifdef LWIP_DEBUG + int s; +#endif /* LWIP_DEBUG */ + int level, optname; + void *optval; + struct lwip_setgetsockopt_data *data; + + LWIP_ASSERT("arg != NULL", arg != NULL); + + data = (struct lwip_setgetsockopt_data*)arg; + sock = data->sock; +#ifdef LWIP_DEBUG + s = data->s; +#endif /* LWIP_DEBUG */ + level = data->level; + optname = data->optname; + optval = data->optval; + + switch (level) { + +/* Level: SOL_SOCKET */ + case SOL_SOCKET: + switch (optname) { + + /* The option flags */ + case SO_ACCEPTCONN: + case SO_BROADCAST: + /* UNIMPL case SO_DEBUG: */ + /* UNIMPL case SO_DONTROUTE: */ + case SO_KEEPALIVE: + /* UNIMPL case SO_OOBINCLUDE: */ +#if SO_REUSE + case SO_REUSEADDR: + case SO_REUSEPORT: +#endif /* SO_REUSE */ + /*case SO_USELOOPBACK: UNIMPL */ + *(int*)optval = sock->conn->pcb.ip->so_options & optname; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, optname=0x%x, ..) = %s\n", + s, optname, (*(int*)optval?"on":"off"))); + break; + + case SO_TYPE: + switch (NETCONNTYPE_GROUP(sock->conn->type)) { + case NETCONN_RAW: + *(int*)optval = SOCK_RAW; + break; + case NETCONN_TCP: + *(int*)optval = SOCK_STREAM; + break; + case NETCONN_UDP: + *(int*)optval = SOCK_DGRAM; + break; + default: /* unrecognized socket type */ + *(int*)optval = sock->conn->type; + LWIP_DEBUGF(SOCKETS_DEBUG, + ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n", + s, *(int *)optval)); + } /* switch (sock->conn->type) */ + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n", + s, *(int *)optval)); + break; + + case SO_ERROR: + if (sock->err == 0) { + sock_set_errno(sock, err_to_errno(sock->conn->err)); + } + *(int *)optval = sock->err; + sock->err = 0; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n", + s, *(int *)optval)); + break; + +#if LWIP_SO_RCVTIMEO + case SO_RCVTIMEO: + *(int *)optval = sock->conn->recv_timeout; + break; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + case SO_RCVBUF: + *(int *)optval = sock->conn->recv_bufsize; + break; +#endif /* LWIP_SO_RCVBUF */ +#if LWIP_UDP + case SO_NO_CHECK: + *(int*)optval = (udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_NOCHKSUM) ? 1 : 0; + break; +#endif /* LWIP_UDP*/ + } /* switch (optname) */ + break; + +/* Level: IPPROTO_IP */ + case IPPROTO_IP: + switch (optname) { + case IP_TTL: + *(int*)optval = sock->conn->pcb.ip->ttl; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TTL) = %d\n", + s, *(int *)optval)); + break; + case IP_TOS: + *(int*)optval = sock->conn->pcb.ip->tos; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TOS) = %d\n", + s, *(int *)optval)); + break; +#if LWIP_IGMP + case IP_MULTICAST_TTL: + *(u8_t*)optval = sock->conn->pcb.ip->ttl; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_TTL) = %d\n", + s, *(int *)optval)); + break; + case IP_MULTICAST_IF: + ((struct in_addr*) optval)->s_addr = sock->conn->pcb.udp->multicast_ip.addr; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_IF) = 0x%"X32_F"\n", + s, *(u32_t *)optval)); + break; +#endif /* LWIP_IGMP */ + } /* switch (optname) */ + break; + +#if LWIP_TCP +/* Level: IPPROTO_TCP */ + case IPPROTO_TCP: + switch (optname) { + case TCP_NODELAY: + *(int*)optval = tcp_nagle_disabled(sock->conn->pcb.tcp); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n", + s, (*(int*)optval)?"on":"off") ); + break; + case TCP_KEEPALIVE: + *(int*)optval = (int)sock->conn->pcb.tcp->keep_idle; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPALIVE) = %d\n", + s, *(int *)optval)); + break; + +#if LWIP_TCP_KEEPALIVE + case TCP_KEEPIDLE: + *(int*)optval = (int)(sock->conn->pcb.tcp->keep_idle/1000); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPIDLE) = %d\n", + s, *(int *)optval)); + break; + case TCP_KEEPINTVL: + *(int*)optval = (int)(sock->conn->pcb.tcp->keep_intvl/1000); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPINTVL) = %d\n", + s, *(int *)optval)); + break; + case TCP_KEEPCNT: + *(int*)optval = (int)sock->conn->pcb.tcp->keep_cnt; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPCNT) = %d\n", + s, *(int *)optval)); + break; +#endif /* LWIP_TCP_KEEPALIVE */ + + } /* switch (optname) */ + break; +#endif /* LWIP_TCP */ +#if LWIP_UDP && LWIP_UDPLITE + /* Level: IPPROTO_UDPLITE */ + case IPPROTO_UDPLITE: + switch (optname) { + case UDPLITE_SEND_CSCOV: + *(int*)optval = sock->conn->pcb.udp->chksum_len_tx; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) = %d\n", + s, (*(int*)optval)) ); + break; + case UDPLITE_RECV_CSCOV: + *(int*)optval = sock->conn->pcb.udp->chksum_len_rx; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) = %d\n", + s, (*(int*)optval)) ); + break; + } /* switch (optname) */ + break; +#endif /* LWIP_UDP */ + } /* switch (level) */ + sys_sem_signal(sock->conn->op_completed); +} + +int +lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) +{ + struct lwip_socket *sock = get_socket(s); + int err = ERR_OK; + struct lwip_setgetsockopt_data data; + + if (!sock) + return -1; + + if (NULL == optval) { + sock_set_errno(sock, EFAULT); + return -1; + } + + /* Do length and type checks for the various options first, to keep it readable. */ + switch (level) { + +/* Level: SOL_SOCKET */ + case SOL_SOCKET: + switch (optname) { + + case SO_BROADCAST: + /* UNIMPL case SO_DEBUG: */ + /* UNIMPL case SO_DONTROUTE: */ + case SO_KEEPALIVE: + /* UNIMPL case case SO_CONTIMEO: */ + /* UNIMPL case case SO_SNDTIMEO: */ +#if LWIP_SO_RCVTIMEO + case SO_RCVTIMEO: +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + case SO_RCVBUF: +#endif /* LWIP_SO_RCVBUF */ + /* UNIMPL case SO_OOBINLINE: */ + /* UNIMPL case SO_SNDBUF: */ + /* UNIMPL case SO_RCVLOWAT: */ + /* UNIMPL case SO_SNDLOWAT: */ +#if SO_REUSE + case SO_REUSEADDR: + case SO_REUSEPORT: +#endif /* SO_REUSE */ + /* UNIMPL case SO_USELOOPBACK: */ + if (optlen < sizeof(int)) { + err = EINVAL; + } + break; + case SO_NO_CHECK: + if (optlen < sizeof(int)) { + err = EINVAL; + } +#if LWIP_UDP + if ((sock->conn->type != NETCONN_UDP) || + ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0)) { + /* this flag is only available for UDP, not for UDP lite */ + err = EAFNOSUPPORT; + } +#endif /* LWIP_UDP */ + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + } /* switch (optname) */ + break; + +/* Level: IPPROTO_IP */ + case IPPROTO_IP: + switch (optname) { + /* UNIMPL case IP_HDRINCL: */ + /* UNIMPL case IP_RCVDSTADDR: */ + /* UNIMPL case IP_RCVIF: */ + case IP_TTL: + case IP_TOS: + if (optlen < sizeof(int)) { + err = EINVAL; + } + break; +#if LWIP_IGMP + case IP_MULTICAST_TTL: + if (optlen < sizeof(u8_t)) { + err = EINVAL; + } + if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) { + err = EAFNOSUPPORT; + } + break; + case IP_MULTICAST_IF: + if (optlen < sizeof(struct in_addr)) { + err = EINVAL; + } + if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) { + err = EAFNOSUPPORT; + } + break; + case IP_ADD_MEMBERSHIP: + case IP_DROP_MEMBERSHIP: + if (optlen < sizeof(struct ip_mreq)) { + err = EINVAL; + } + if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) { + err = EAFNOSUPPORT; + } + break; +#endif /* LWIP_IGMP */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + } /* switch (optname) */ + break; + +#if LWIP_TCP +/* Level: IPPROTO_TCP */ + case IPPROTO_TCP: + if (optlen < sizeof(int)) { + err = EINVAL; + break; + } + + /* If this is no TCP socket, ignore any options. */ + if (sock->conn->type != NETCONN_TCP) + return 0; + + switch (optname) { + case TCP_NODELAY: + case TCP_KEEPALIVE: +#if LWIP_TCP_KEEPALIVE + case TCP_KEEPIDLE: + case TCP_KEEPINTVL: + case TCP_KEEPCNT: +#endif /* LWIP_TCP_KEEPALIVE */ + break; + + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + } /* switch (optname) */ + break; +#endif /* LWIP_TCP */ +#if LWIP_UDP && LWIP_UDPLITE +/* Level: IPPROTO_UDPLITE */ + case IPPROTO_UDPLITE: + if (optlen < sizeof(int)) { + err = EINVAL; + break; + } + + /* If this is no UDP lite socket, ignore any options. */ + if (sock->conn->type != NETCONN_UDPLITE) + return 0; + + switch (optname) { + case UDPLITE_SEND_CSCOV: + case UDPLITE_RECV_CSCOV: + break; + + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + } /* switch (optname) */ + break; +#endif /* LWIP_UDP && LWIP_UDPLITE */ +/* UNDEFINED LEVEL */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", + s, level, optname)); + err = ENOPROTOOPT; + } /* switch (level) */ + + + if (err != ERR_OK) { + sock_set_errno(sock, err); + return -1; + } + + + /* Now do the actual option processing */ + data.sock = sock; + data.level = level; + data.optname = optname; + data.optval = (void*)optval; + data.optlen = &optlen; + data.err = err; + tcpip_callback(lwip_setsockopt_internal, &data); + sys_arch_sem_wait(sock->conn->op_completed, 0); + /* maybe lwip_setsockopt_internal has changed err */ + err = data.err; + + sock_set_errno(sock, err); + return err ? -1 : 0; +} + +static void +lwip_setsockopt_internal(void *arg) +{ + struct lwip_socket *sock; +#ifdef LWIP_DEBUG + int s; +#endif /* LWIP_DEBUG */ + int level, optname; + const void *optval; + struct lwip_setgetsockopt_data *data; + + LWIP_ASSERT("arg != NULL", arg != NULL); + + data = (struct lwip_setgetsockopt_data*)arg; + sock = data->sock; +#ifdef LWIP_DEBUG + s = data->s; +#endif /* LWIP_DEBUG */ + level = data->level; + optname = data->optname; + optval = data->optval; + + switch (level) { + +/* Level: SOL_SOCKET */ + case SOL_SOCKET: + switch (optname) { + + /* The option flags */ + case SO_BROADCAST: + /* UNIMPL case SO_DEBUG: */ + /* UNIMPL case SO_DONTROUTE: */ + case SO_KEEPALIVE: + /* UNIMPL case SO_OOBINCLUDE: */ +#if SO_REUSE + case SO_REUSEADDR: + case SO_REUSEPORT: +#endif /* SO_REUSE */ + /* UNIMPL case SO_USELOOPBACK: */ + if (*(int*)optval) { + sock->conn->pcb.ip->so_options |= optname; + } else { + sock->conn->pcb.ip->so_options &= ~optname; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n", + s, optname, (*(int*)optval?"on":"off"))); + break; +#if LWIP_SO_RCVTIMEO + case SO_RCVTIMEO: + sock->conn->recv_timeout = ( *(int*)optval ); + break; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + case SO_RCVBUF: + sock->conn->recv_bufsize = ( *(int*)optval ); + break; +#endif /* LWIP_SO_RCVBUF */ +#if LWIP_UDP + case SO_NO_CHECK: + if (*(int*)optval) { + udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_NOCHKSUM); + } else { + udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_NOCHKSUM); + } + break; +#endif /* LWIP_UDP */ + } /* switch (optname) */ + break; + +/* Level: IPPROTO_IP */ + case IPPROTO_IP: + switch (optname) { + case IP_TTL: + sock->conn->pcb.ip->ttl = (u8_t)(*(int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TTL, ..) -> %d\n", + s, sock->conn->pcb.ip->ttl)); + break; + case IP_TOS: + sock->conn->pcb.ip->tos = (u8_t)(*(int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TOS, ..)-> %d\n", + s, sock->conn->pcb.ip->tos)); + break; +#if LWIP_IGMP + case IP_MULTICAST_TTL: + sock->conn->pcb.udp->ttl = (u8_t)(*(u8_t*)optval); + break; + case IP_MULTICAST_IF: + sock->conn->pcb.udp->multicast_ip.addr = ((struct in_addr*) optval)->s_addr; + break; + case IP_ADD_MEMBERSHIP: + case IP_DROP_MEMBERSHIP: + { + /* If this is a TCP or a RAW socket, ignore these options. */ + struct ip_mreq *imr = (struct ip_mreq *)optval; + if(optname == IP_ADD_MEMBERSHIP){ + data->err = igmp_joingroup((struct ip_addr*)&(imr->imr_interface.s_addr), (struct ip_addr*)&(imr->imr_multiaddr.s_addr)); + } else { + data->err = igmp_leavegroup((struct ip_addr*)&(imr->imr_interface.s_addr), (struct ip_addr*)&(imr->imr_multiaddr.s_addr)); + } + if(data->err != ERR_OK) { + data->err = EADDRNOTAVAIL; + } + } + break; +#endif /* LWIP_IGMP */ + } /* switch (optname) */ + break; + +#if LWIP_TCP +/* Level: IPPROTO_TCP */ + case IPPROTO_TCP: + switch (optname) { + case TCP_NODELAY: + if (*(int*)optval) { + tcp_nagle_disable(sock->conn->pcb.tcp); + } else { + tcp_nagle_enable(sock->conn->pcb.tcp); + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n", + s, (*(int *)optval)?"on":"off") ); + break; + case TCP_KEEPALIVE: + sock->conn->pcb.tcp->keep_idle = (u32_t)(*(int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %"U32_F"\n", + s, sock->conn->pcb.tcp->keep_idle)); + break; + +#if LWIP_TCP_KEEPALIVE + case TCP_KEEPIDLE: + sock->conn->pcb.tcp->keep_idle = 1000*(u32_t)(*(int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) -> %"U32_F"\n", + s, sock->conn->pcb.tcp->keep_idle)); + break; + case TCP_KEEPINTVL: + sock->conn->pcb.tcp->keep_intvl = 1000*(u32_t)(*(int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) -> %"U32_F"\n", + s, sock->conn->pcb.tcp->keep_intvl)); + break; + case TCP_KEEPCNT: + sock->conn->pcb.tcp->keep_cnt = (u32_t)(*(int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) -> %"U32_F"\n", + s, sock->conn->pcb.tcp->keep_cnt)); + break; +#endif /* LWIP_TCP_KEEPALIVE */ + + } /* switch (optname) */ + break; +#endif /* LWIP_TCP*/ +#if LWIP_UDP && LWIP_UDPLITE + /* Level: IPPROTO_UDPLITE */ + case IPPROTO_UDPLITE: + switch (optname) { + case UDPLITE_SEND_CSCOV: + if ((*(int*)optval != 0) && (*(int*)optval < 8)) { + /* don't allow illegal values! */ + sock->conn->pcb.udp->chksum_len_tx = 8; + } else { + sock->conn->pcb.udp->chksum_len_tx = *(int*)optval; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) -> %d\n", + s, (*(int*)optval)) ); + break; + case UDPLITE_RECV_CSCOV: + if ((*(int*)optval != 0) && (*(int*)optval < 8)) { + /* don't allow illegal values! */ + sock->conn->pcb.udp->chksum_len_rx = 8; + } else { + sock->conn->pcb.udp->chksum_len_rx = *(int*)optval; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) -> %d\n", + s, (*(int*)optval)) ); + break; + } /* switch (optname) */ + break; +#endif /* LWIP_UDP */ + } /* switch (level) */ + sys_sem_signal(sock->conn->op_completed); +} + +int +lwip_ioctl(int s, long cmd, void *argp) +{ + struct lwip_socket *sock = get_socket(s); + u16_t buflen = 0; + s16_t recv_avail; + + if (!sock) + return -1; + + switch (cmd) { + case FIONREAD: + if (!argp) { + sock_set_errno(sock, EINVAL); + return -1; + } + + SYS_ARCH_GET(sock->conn->recv_avail, recv_avail); + if (recv_avail < 0) + recv_avail = 0; + *((u16_t*)argp) = (u16_t)recv_avail; + + /* Check if there is data left from the last recv operation. /maq 041215 */ + if (sock->lastdata) { + buflen = netbuf_len(sock->lastdata); + buflen -= sock->lastoffset; + + *((u16_t*)argp) += buflen; + } + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %"U16_F"\n", s, argp, *((u16_t*)argp))); + sock_set_errno(sock, 0); + return 0; + + case FIONBIO: + if (argp && *(u32_t*)argp) + sock->flags |= O_NONBLOCK; + else + sock->flags &= ~O_NONBLOCK; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, !!(sock->flags & O_NONBLOCK))); + sock_set_errno(sock, 0); + return 0; + + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s, cmd, argp)); + sock_set_errno(sock, ENOSYS); /* not yet implemented */ + return -1; + } /* switch (cmd) */ +} + +#endif /* LWIP_SOCKET */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/api/tcpip.c b/component/common/network/lwip/lwip_v1.3.2/src/api/tcpip.c new file mode 100644 index 0000000..002df90 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/api/tcpip.c @@ -0,0 +1,596 @@ +/** + * @file + * Sequential API Main thread module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if !NO_SYS /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/sys.h" +#include "lwip/memp.h" +#include "lwip/pbuf.h" +#include "lwip/ip_frag.h" +#include "lwip/tcp.h" +#include "lwip/autoip.h" +#include "lwip/dhcp.h" +#include "lwip/igmp.h" +#include "lwip/dns.h" +#include "lwip/tcpip.h" +#include "lwip/init.h" +#include "netif/etharp.h" +#include "netif/ppp_oe.h" + +/* global variables */ +static void (* tcpip_init_done)(void *arg); +static void *tcpip_init_done_arg; +static sys_mbox_t mbox = SYS_MBOX_NULL; + +#if LWIP_TCPIP_CORE_LOCKING +/** The global semaphore to lock the stack. */ +sys_sem_t lock_tcpip_core; +#endif /* LWIP_TCPIP_CORE_LOCKING */ + +#if LWIP_TCP +/* global variable that shows if the tcp timer is currently scheduled or not */ +static int tcpip_tcp_timer_active; + +/** + * Timer callback function that calls tcp_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +tcpip_tcp_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + + /* call TCP timer handler */ + tcp_tmr(); + /* timer still needed? */ + if (tcp_active_pcbs || tcp_tw_pcbs) { + /* restart timer */ + sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL); + } else { + /* disable timer */ + tcpip_tcp_timer_active = 0; + } +} + +#if !NO_SYS +/** + * Called from TCP_REG when registering a new PCB: + * the reason is to have the TCP timer only running when + * there are active (or time-wait) PCBs. + */ +void +tcp_timer_needed(void) +{ + /* timer is off but needed again? */ + if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) { + /* enable and start timer */ + tcpip_tcp_timer_active = 1; + sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL); + } +} +#endif /* !NO_SYS */ +#endif /* LWIP_TCP */ + +#if IP_REASSEMBLY +/** + * Timer callback function that calls ip_reass_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +ip_reass_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: ip_reass_tmr()\n")); + ip_reass_tmr(); + sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL); +} +#endif /* IP_REASSEMBLY */ + +#if LWIP_ARP +/** + * Timer callback function that calls etharp_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +arp_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: etharp_tmr()\n")); + etharp_tmr(); + sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); +} +#endif /* LWIP_ARP */ + +#if LWIP_DHCP +/** + * Timer callback function that calls dhcp_coarse_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +dhcp_timer_coarse(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: dhcp_coarse_tmr()\n")); + dhcp_coarse_tmr(); + sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL); +} + +/** + * Timer callback function that calls dhcp_fine_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +dhcp_timer_fine(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: dhcp_fine_tmr()\n")); + dhcp_fine_tmr(); + sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL); +} +#endif /* LWIP_DHCP */ + +#if LWIP_AUTOIP +/** + * Timer callback function that calls autoip_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +autoip_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: autoip_tmr()\n")); + autoip_tmr(); + sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL); +} +#endif /* LWIP_AUTOIP */ + +#if LWIP_IGMP +/** + * Timer callback function that calls igmp_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +igmp_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: igmp_tmr()\n")); + igmp_tmr(); + sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL); +} +#endif /* LWIP_IGMP */ + +#if LWIP_DNS +/** + * Timer callback function that calls dns_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +dns_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: dns_tmr()\n")); + dns_tmr(); + sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL); +} +#endif /* LWIP_DNS */ + +/** + * The main lwIP thread. This thread has exclusive access to lwIP core functions + * (unless access to them is not locked). Other threads communicate with this + * thread using message boxes. + * + * It also starts all the timers to make sure they are running in the right + * thread context. + * + * @param arg unused argument + */ +static void +tcpip_thread(void *arg) +{ + struct tcpip_msg *msg; + LWIP_UNUSED_ARG(arg); + +#if IP_REASSEMBLY + sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL); +#endif /* IP_REASSEMBLY */ +#if LWIP_ARP + sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); +#endif /* LWIP_ARP */ +#if LWIP_DHCP + sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL); + sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL); +#endif /* LWIP_DHCP */ +#if LWIP_AUTOIP + sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL); +#endif /* LWIP_AUTOIP */ +#if LWIP_IGMP + sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL); +#endif /* LWIP_IGMP */ +#if LWIP_DNS + sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL); +#endif /* LWIP_DNS */ + + if (tcpip_init_done != NULL) { + tcpip_init_done(tcpip_init_done_arg); + } + + LOCK_TCPIP_CORE(); + while (1) { /* MAIN Loop */ + sys_mbox_fetch(mbox, (void *)&msg); + switch (msg->type) { +#if LWIP_NETCONN + case TCPIP_MSG_API: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg)); + msg->msg.apimsg->function(&(msg->msg.apimsg->msg)); + break; +#endif /* LWIP_NETCONN */ + + case TCPIP_MSG_INPKT: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: PACKET %p\n", (void *)msg)); +#if LWIP_ARP + if (msg->msg.inp.netif->flags & NETIF_FLAG_ETHARP) { + ethernet_input(msg->msg.inp.p, msg->msg.inp.netif); + } else +#endif /* LWIP_ARP */ + { ip_input(msg->msg.inp.p, msg->msg.inp.netif); + } + memp_free(MEMP_TCPIP_MSG_INPKT, msg); + break; + +#if LWIP_NETIF_API + case TCPIP_MSG_NETIFAPI: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: Netif API message %p\n", (void *)msg)); + msg->msg.netifapimsg->function(&(msg->msg.netifapimsg->msg)); + break; +#endif /* LWIP_NETIF_API */ + + case TCPIP_MSG_CALLBACK: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg)); + msg->msg.cb.f(msg->msg.cb.ctx); + memp_free(MEMP_TCPIP_MSG_API, msg); + break; + + case TCPIP_MSG_TIMEOUT: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: TIMEOUT %p\n", (void *)msg)); + sys_timeout(msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg); + memp_free(MEMP_TCPIP_MSG_API, msg); + break; + case TCPIP_MSG_UNTIMEOUT: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: UNTIMEOUT %p\n", (void *)msg)); + sys_untimeout(msg->msg.tmo.h, msg->msg.tmo.arg); + memp_free(MEMP_TCPIP_MSG_API, msg); + break; + + default: + break; + } + } +} + +/** + * Pass a received packet to tcpip_thread for input processing + * + * @param p the received packet, p->payload pointing to the Ethernet header or + * to an IP header (if netif doesn't got NETIF_FLAG_ETHARP flag) + * @param inp the network interface on which the packet was received + */ +err_t +tcpip_input(struct pbuf *p, struct netif *inp) +{ + struct tcpip_msg *msg; + + if (mbox != SYS_MBOX_NULL) { + msg = memp_malloc(MEMP_TCPIP_MSG_INPKT); + if (msg == NULL) { + return ERR_MEM; + } + + msg->type = TCPIP_MSG_INPKT; + msg->msg.inp.p = p; + msg->msg.inp.netif = inp; + if (sys_mbox_trypost(mbox, msg) != ERR_OK) { + memp_free(MEMP_TCPIP_MSG_INPKT, msg); + return ERR_MEM; + } + return ERR_OK; + } + return ERR_VAL; +} + +/** + * Call a specific function in the thread context of + * tcpip_thread for easy access synchronization. + * A function called in that way may access lwIP core code + * without fearing concurrent access. + * + * @param f the function to call + * @param ctx parameter passed to f + * @param block 1 to block until the request is posted, 0 to non-blocking mode + * @return ERR_OK if the function was called, another err_t if not + */ +err_t +tcpip_callback_with_block(void (*f)(void *ctx), void *ctx, u8_t block) +{ + struct tcpip_msg *msg; + + if (mbox != SYS_MBOX_NULL) { + msg = memp_malloc(MEMP_TCPIP_MSG_API); + if (msg == NULL) { + return ERR_MEM; + } + + msg->type = TCPIP_MSG_CALLBACK; + msg->msg.cb.f = f; + msg->msg.cb.ctx = ctx; + if (block) { + sys_mbox_post(mbox, msg); + } else { + if (sys_mbox_trypost(mbox, msg) != ERR_OK) { + memp_free(MEMP_TCPIP_MSG_API, msg); + return ERR_MEM; + } + } + return ERR_OK; + } + return ERR_VAL; +} + +/** + * call sys_timeout in tcpip_thread + * + * @param msec time in miliseconds for timeout + * @param h function to be called on timeout + * @param arg argument to pass to timeout function h + * @return ERR_MEM on memory error, ERR_OK otherwise + */ +err_t +tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg) +{ + struct tcpip_msg *msg; + + if (mbox != SYS_MBOX_NULL) { + msg = memp_malloc(MEMP_TCPIP_MSG_API); + if (msg == NULL) { + return ERR_MEM; + } + + msg->type = TCPIP_MSG_TIMEOUT; + msg->msg.tmo.msecs = msecs; + msg->msg.tmo.h = h; + msg->msg.tmo.arg = arg; + sys_mbox_post(mbox, msg); + return ERR_OK; + } + return ERR_VAL; +} + +/** + * call sys_untimeout in tcpip_thread + * + * @param msec time in miliseconds for timeout + * @param h function to be called on timeout + * @param arg argument to pass to timeout function h + * @return ERR_MEM on memory error, ERR_OK otherwise + */ +err_t +tcpip_untimeout(sys_timeout_handler h, void *arg) +{ + struct tcpip_msg *msg; + + if (mbox != SYS_MBOX_NULL) { + msg = memp_malloc(MEMP_TCPIP_MSG_API); + if (msg == NULL) { + return ERR_MEM; + } + + msg->type = TCPIP_MSG_UNTIMEOUT; + msg->msg.tmo.h = h; + msg->msg.tmo.arg = arg; + sys_mbox_post(mbox, msg); + return ERR_OK; + } + return ERR_VAL; +} + +#if LWIP_NETCONN +/** + * Call the lower part of a netconn_* function + * This function is then running in the thread context + * of tcpip_thread and has exclusive access to lwIP core code. + * + * @param apimsg a struct containing the function to call and its parameters + * @return ERR_OK if the function was called, another err_t if not + */ +err_t +tcpip_apimsg(struct api_msg *apimsg) +{ + struct tcpip_msg msg; + + if (mbox != SYS_MBOX_NULL) { + msg.type = TCPIP_MSG_API; + msg.msg.apimsg = apimsg; + sys_mbox_post(mbox, &msg); + sys_arch_sem_wait(apimsg->msg.conn->op_completed, 0); + return ERR_OK; + } + return ERR_VAL; +} + +#if LWIP_TCPIP_CORE_LOCKING +/** + * Call the lower part of a netconn_* function + * This function has exclusive access to lwIP core code by locking it + * before the function is called. + * + * @param apimsg a struct containing the function to call and its parameters + * @return ERR_OK (only for compatibility fo tcpip_apimsg()) + */ +err_t +tcpip_apimsg_lock(struct api_msg *apimsg) +{ + LOCK_TCPIP_CORE(); + apimsg->function(&(apimsg->msg)); + UNLOCK_TCPIP_CORE(); + return ERR_OK; + +} +#endif /* LWIP_TCPIP_CORE_LOCKING */ +#endif /* LWIP_NETCONN */ + +#if LWIP_NETIF_API +#if !LWIP_TCPIP_CORE_LOCKING +/** + * Much like tcpip_apimsg, but calls the lower part of a netifapi_* + * function. + * + * @param netifapimsg a struct containing the function to call and its parameters + * @return error code given back by the function that was called + */ +err_t +tcpip_netifapi(struct netifapi_msg* netifapimsg) +{ + struct tcpip_msg msg; + + if (mbox != SYS_MBOX_NULL) { + netifapimsg->msg.sem = sys_sem_new(0); + if (netifapimsg->msg.sem == SYS_SEM_NULL) { + netifapimsg->msg.err = ERR_MEM; + return netifapimsg->msg.err; + } + + msg.type = TCPIP_MSG_NETIFAPI; + msg.msg.netifapimsg = netifapimsg; + sys_mbox_post(mbox, &msg); + sys_sem_wait(netifapimsg->msg.sem); + sys_sem_free(netifapimsg->msg.sem); + return netifapimsg->msg.err; + } + return ERR_VAL; +} +#else /* !LWIP_TCPIP_CORE_LOCKING */ +/** + * Call the lower part of a netifapi_* function + * This function has exclusive access to lwIP core code by locking it + * before the function is called. + * + * @param netifapimsg a struct containing the function to call and its parameters + * @return ERR_OK (only for compatibility fo tcpip_netifapi()) + */ +err_t +tcpip_netifapi_lock(struct netifapi_msg* netifapimsg) +{ + LOCK_TCPIP_CORE(); + netifapimsg->function(&(netifapimsg->msg)); + UNLOCK_TCPIP_CORE(); + return netifapimsg->msg.err; +} +#endif /* !LWIP_TCPIP_CORE_LOCKING */ +#endif /* LWIP_NETIF_API */ + +/** + * Initialize this module: + * - initialize all sub modules + * - start the tcpip_thread + * + * @param initfunc a function to call when tcpip_thread is running and finished initializing + * @param arg argument to pass to initfunc + */ +void +tcpip_init(void (* initfunc)(void *), void *arg) +{ + lwip_init(); + + tcpip_init_done = initfunc; + tcpip_init_done_arg = arg; + mbox = sys_mbox_new(TCPIP_MBOX_SIZE); +#if LWIP_TCPIP_CORE_LOCKING + lock_tcpip_core = sys_sem_new(1); +#endif /* LWIP_TCPIP_CORE_LOCKING */ + + sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO); +} + +/** + * Simple callback function used with tcpip_callback to free a pbuf + * (pbuf_free has a wrong signature for tcpip_callback) + * + * @param p The pbuf (chain) to be dereferenced. + */ +static void +pbuf_free_int(void *p) +{ + struct pbuf *q = p; + pbuf_free(q); +} + +/** + * A simple wrapper function that allows you to free a pbuf from interrupt context. + * + * @param p The pbuf (chain) to be dereferenced. + * @return ERR_OK if callback could be enqueued, an err_t if not + */ +err_t +pbuf_free_callback(struct pbuf *p) +{ + return tcpip_callback_with_block(pbuf_free_int, p, 0); +} + +/** + * A simple wrapper function that allows you to free heap memory from + * interrupt context. + * + * @param m the heap memory to free + * @return ERR_OK if callback could be enqueued, an err_t if not + */ +err_t +mem_free_callback(void *m) +{ + return tcpip_callback_with_block(mem_free, m, 0); +} + +#endif /* !NO_SYS */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/core/dhcp.c b/component/common/network/lwip/lwip_v1.3.2/src/core/dhcp.c new file mode 100644 index 0000000..7087107 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/core/dhcp.c @@ -0,0 +1,1778 @@ +/* + * @file + * Dynamic Host Configuration Protocol client + * + */ + +/* + * + * Copyright (c) 2001-2004 Leon Woestenberg + * Copyright (c) 2001-2004 Axon Digital Design B.V., The Netherlands. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is a contribution to the lwIP TCP/IP stack. + * The Swedish Institute of Computer Science and Adam Dunkels + * are specifically granted permission to redistribute this + * source code. + * + * Author: Leon Woestenberg + * + * This is a DHCP client for the lwIP TCP/IP stack. It aims to conform + * with RFC 2131 and RFC 2132. + * + * TODO: + * - Proper parsing of DHCP messages exploiting file/sname field overloading. + * - Add JavaDoc style documentation (API, internals). + * - Support for interfaces other than Ethernet (SLIP, PPP, ...) + * + * Please coordinate changes and requests with Leon Woestenberg + * + * + * Integration with your code: + * + * In lwip/dhcp.h + * #define DHCP_COARSE_TIMER_SECS (recommended 60 which is a minute) + * #define DHCP_FINE_TIMER_MSECS (recommended 500 which equals TCP coarse timer) + * + * Then have your application call dhcp_coarse_tmr() and + * dhcp_fine_tmr() on the defined intervals. + * + * dhcp_start(struct netif *netif); + * starts a DHCP client instance which configures the interface by + * obtaining an IP address lease and maintaining it. + * + * Use dhcp_release(netif) to end the lease and use dhcp_stop(netif) + * to remove the DHCP client. + * + */ + +#include "lwip/opt.h" + +#if LWIP_DHCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/stats.h" +#include "lwip/mem.h" +#include "lwip/udp.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/inet.h" +#include "lwip/sys.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" +#include "lwip/dns.h" +#include "netif/etharp.h" + +#include + +/** Default for DHCP_GLOBAL_XID is 0xABCD0000 + * This can be changed by defining DHCP_GLOBAL_XID and DHCP_GLOBAL_XID_HEADER, e.g. + * #define DHCP_GLOBAL_XID_HEADER "stdlib.h" + * #define DHCP_GLOBAL_XID rand() + */ +#ifdef DHCP_GLOBAL_XID_HEADER +#include DHCP_GLOBAL_XID_HEADER /* include optional starting XID generation prototypes */ +#endif + +/** DHCP_OPTION_MAX_MSG_SIZE is set to the MTU + * MTU is checked to be big enough in dhcp_start */ +#define DHCP_MAX_MSG_LEN(netif) (netif->mtu) +#define DHCP_MAX_MSG_LEN_MIN_REQUIRED 576 +/** Minimum length for reply before packet is parsed */ +#define DHCP_MIN_REPLY_LEN 44 + +#define REBOOT_TRIES 2 + +/* DHCP client state machine functions */ +static void dhcp_handle_ack(struct netif *netif); +static void dhcp_handle_nak(struct netif *netif); +static void dhcp_handle_offer(struct netif *netif); + +static err_t dhcp_discover(struct netif *netif); +static err_t dhcp_select(struct netif *netif); +static void dhcp_bind(struct netif *netif); +#if DHCP_DOES_ARP_CHECK +static void dhcp_check(struct netif *netif); +static err_t dhcp_decline(struct netif *netif); +#endif /* DHCP_DOES_ARP_CHECK */ +static err_t dhcp_rebind(struct netif *netif); +static err_t dhcp_reboot(struct netif *netif); +static void dhcp_set_state(struct dhcp *dhcp, u8_t new_state); + +/* receive, unfold, parse and free incoming messages */ +static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port); +static err_t dhcp_unfold_reply(struct dhcp *dhcp, struct pbuf *p); +static u8_t *dhcp_get_option_ptr(struct dhcp *dhcp, u8_t option_type); +static u8_t dhcp_get_option_byte(u8_t *ptr); +#if 0 +static u16_t dhcp_get_option_short(u8_t *ptr); +#endif +static u32_t dhcp_get_option_long(u8_t *ptr); +static void dhcp_free_reply(struct dhcp *dhcp); + +/* set the DHCP timers */ +static void dhcp_timeout(struct netif *netif); +static void dhcp_t1_timeout(struct netif *netif); +static void dhcp_t2_timeout(struct netif *netif); + +/* build outgoing messages */ +/* create a DHCP request, fill in common headers */ +static err_t dhcp_create_request(struct netif *netif); +/* free a DHCP request */ +static void dhcp_delete_request(struct netif *netif); +/* add a DHCP option (type, then length in bytes) */ +static void dhcp_option(struct dhcp *dhcp, u8_t option_type, u8_t option_len); +/* add option values */ +static void dhcp_option_byte(struct dhcp *dhcp, u8_t value); +static void dhcp_option_short(struct dhcp *dhcp, u16_t value); +static void dhcp_option_long(struct dhcp *dhcp, u32_t value); +/* always add the DHCP options trailer to end and pad */ +static void dhcp_option_trailer(struct dhcp *dhcp); + +/** + * Back-off the DHCP client (because of a received NAK response). + * + * Back-off the DHCP client because of a received NAK. Receiving a + * NAK means the client asked for something non-sensible, for + * example when it tries to renew a lease obtained on another network. + * + * We clear any existing set IP address and restart DHCP negotiation + * afresh (as per RFC2131 3.2.3). + * + * @param netif the netif under DHCP control + */ +static void +dhcp_handle_nak(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_nak(netif=%p) %c%c%"U16_F"\n", + (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); + /* Set the interface down since the address must no longer be used, as per RFC2131 */ + netif_set_down(netif); + /* remove IP address from interface */ + netif_set_ipaddr(netif, IP_ADDR_ANY); + netif_set_gw(netif, IP_ADDR_ANY); + netif_set_netmask(netif, IP_ADDR_ANY); + /* Change to a defined state */ + dhcp_set_state(dhcp, DHCP_BACKING_OFF); + /* We can immediately restart discovery */ + dhcp_discover(netif); +} + +#if DHCP_DOES_ARP_CHECK +/** + * Checks if the offered IP address is already in use. + * + * It does so by sending an ARP request for the offered address and + * entering CHECKING state. If no ARP reply is received within a small + * interval, the address is assumed to be free for use by us. + * + * @param netif the netif under DHCP control + */ +static void +dhcp_check(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result; + u16_t msecs; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_check(netif=%p) %c%c\n", (void *)netif, (s16_t)netif->name[0], + (s16_t)netif->name[1])); + dhcp_set_state(dhcp, DHCP_CHECKING); + /* create an ARP query for the offered IP address, expecting that no host + responds, as the IP address should not be in use. */ + result = etharp_query(netif, &dhcp->offered_ip_addr, NULL); + if (result != ERR_OK) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_check: could not perform ARP query\n")); + } + dhcp->tries++; + msecs = 500; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_check(): set request timeout %"U16_F" msecs\n", msecs)); +} +#endif /* DHCP_DOES_ARP_CHECK */ + +/** + * Remember the configuration offered by a DHCP server. + * + * @param netif the netif under DHCP control + */ +static void +dhcp_handle_offer(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + /* obtain the server address */ + u8_t *option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_SERVER_ID); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_offer(netif=%p) %c%c%"U16_F"\n", + (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); + if (option_ptr != NULL) { + dhcp->server_ip_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2])); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): server 0x%08"X32_F"\n", dhcp->server_ip_addr.addr)); + /* remember offered address */ + ip_addr_set(&dhcp->offered_ip_addr, (struct ip_addr *)&dhcp->msg_in->yiaddr); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): offer for 0x%08"X32_F"\n", dhcp->offered_ip_addr.addr)); + + dhcp_select(netif); + } +} + +/** + * Select a DHCP server offer out of all offers. + * + * Simply select the first offer received. + * + * @param netif the netif under DHCP control + * @return lwIP specific error (see error.h) + */ +static err_t +dhcp_select(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result; + u16_t msecs; +#if LWIP_NETIF_HOSTNAME + const char *p; +#endif /* LWIP_NETIF_HOSTNAME */ + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_select(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); + dhcp_set_state(dhcp, DHCP_REQUESTING); + + /* create and initialize the DHCP message header */ + result = dhcp_create_request(netif); + if (result == ERR_OK) { + dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN); + dhcp_option_byte(dhcp, DHCP_REQUEST); + + dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); + + /* MUST request the offered IP address */ + dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); + dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr)); + + dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4); + dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr)); + + dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 4/*num options*/); + dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK); + dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER); + dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST); + dhcp_option_byte(dhcp, DHCP_OPTION_DNS_SERVER); + +#if LWIP_NETIF_HOSTNAME + p = (const char*)netif->hostname; + if (p != NULL) { + dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, strlen(p)); + while (*p) { + dhcp_option_byte(dhcp, *p++); + } + } +#endif /* LWIP_NETIF_HOSTNAME */ + + dhcp_option_trailer(dhcp); + /* shrink the pbuf to the actual content length */ + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + /* send broadcast to any DHCP server */ + udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); + dhcp_delete_request(netif); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_select: REQUESTING\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_select: could not allocate DHCP request\n")); + } + dhcp->tries++; + msecs = (dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_select(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} + +/** + * The DHCP timer that checks for lease renewal/rebind timeouts. + * + */ +void +dhcp_coarse_tmr() +{ + struct netif *netif = netif_list; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_coarse_tmr()\n")); + /* iterate through all network interfaces */ + while (netif != NULL) { + /* only act on DHCP configured interfaces */ + if (netif->dhcp != NULL) { + /* timer is active (non zero), and triggers (zeroes) now? */ + if (netif->dhcp->t2_timeout-- == 1) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t2 timeout\n")); + /* this clients' rebind timeout triggered */ + dhcp_t2_timeout(netif); + /* timer is active (non zero), and triggers (zeroes) now */ + } else if (netif->dhcp->t1_timeout-- == 1) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t1 timeout\n")); + /* this clients' renewal timeout triggered */ + dhcp_t1_timeout(netif); + } + } + /* proceed to next netif */ + netif = netif->next; + } +} + +/** + * DHCP transaction timeout handling + * + * A DHCP server is expected to respond within a short period of time. + * This timer checks whether an outstanding DHCP request is timed out. + * + */ +void +dhcp_fine_tmr() +{ + struct netif *netif = netif_list; + /* loop through netif's */ + while (netif != NULL) { + /* only act on DHCP configured interfaces */ + if (netif->dhcp != NULL) { + /* timer is active (non zero), and is about to trigger now */ + if (netif->dhcp->request_timeout > 1) { + netif->dhcp->request_timeout--; + } + else if (netif->dhcp->request_timeout == 1) { + netif->dhcp->request_timeout--; + /* { netif->dhcp->request_timeout == 0 } */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_fine_tmr(): request timeout\n")); + /* this clients' request timeout triggered */ + dhcp_timeout(netif); + } + } + /* proceed to next network interface */ + netif = netif->next; + } +} + +/** + * A DHCP negotiation transaction, or ARP request, has timed out. + * + * The timer that was started with the DHCP or ARP request has + * timed out, indicating no response was received in time. + * + * @param netif the netif under DHCP control + */ +static void +dhcp_timeout(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout()\n")); + /* back-off period has passed, or server selection timed out */ + if ((dhcp->state == DHCP_BACKING_OFF) || (dhcp->state == DHCP_SELECTING)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout(): restarting discovery\n")); + dhcp_discover(netif); + /* receiving the requested lease timed out */ + } else if (dhcp->state == DHCP_REQUESTING) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REQUESTING, DHCP request timed out\n")); + if (dhcp->tries <= 5) { + dhcp_select(netif); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REQUESTING, releasing, restarting\n")); + dhcp_release(netif); + dhcp_discover(netif); + } +#if DHCP_DOES_ARP_CHECK + /* received no ARP reply for the offered address (which is good) */ + } else if (dhcp->state == DHCP_CHECKING) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): CHECKING, ARP request timed out\n")); + if (dhcp->tries <= 1) { + dhcp_check(netif); + /* no ARP replies on the offered address, + looks like the IP address is indeed free */ + } else { + /* bind the interface to the offered address */ + dhcp_bind(netif); + } +#endif /* DHCP_DOES_ARP_CHECK */ + } + /* did not get response to renew request? */ + else if (dhcp->state == DHCP_RENEWING) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): RENEWING, DHCP request timed out\n")); + /* just retry renewal */ + /* note that the rebind timer will eventually time-out if renew does not work */ + dhcp_renew(netif); + /* did not get response to rebind request? */ + } else if (dhcp->state == DHCP_REBINDING) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REBINDING, DHCP request timed out\n")); + if (dhcp->tries <= 8) { + dhcp_rebind(netif); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): RELEASING, DISCOVERING\n")); + dhcp_release(netif); + dhcp_discover(netif); + } + } else if (dhcp->state == DHCP_REBOOTING) { + if (dhcp->tries < REBOOT_TRIES) { + dhcp_reboot(netif); + } else { + dhcp_discover(netif); + } + } +} + +/** + * The renewal period has timed out. + * + * @param netif the netif under DHCP control + */ +static void +dhcp_t1_timeout(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_t1_timeout()\n")); + if ((dhcp->state == DHCP_REQUESTING) || (dhcp->state == DHCP_BOUND) || (dhcp->state == DHCP_RENEWING)) { + /* just retry to renew - note that the rebind timer (t2) will + * eventually time-out if renew tries fail. */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_t1_timeout(): must renew\n")); + dhcp_renew(netif); + } +} + +/** + * The rebind period has timed out. + * + * @param netif the netif under DHCP control + */ +static void +dhcp_t2_timeout(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_t2_timeout()\n")); + if ((dhcp->state == DHCP_REQUESTING) || (dhcp->state == DHCP_BOUND) || (dhcp->state == DHCP_RENEWING)) { + /* just retry to rebind */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_t2_timeout(): must rebind\n")); + dhcp_rebind(netif); + } +} + +/** + * Handle a DHCP ACK packet + * + * @param netif the netif under DHCP control + */ +static void +dhcp_handle_ack(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + u8_t *option_ptr; + /* clear options we might not get from the ACK */ + dhcp->offered_sn_mask.addr = 0; + dhcp->offered_gw_addr.addr = 0; + dhcp->offered_bc_addr.addr = 0; + + /* lease time given? */ + option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_LEASE_TIME); + if (option_ptr != NULL) { + /* remember offered lease time */ + dhcp->offered_t0_lease = dhcp_get_option_long(option_ptr + 2); + } + /* renewal period given? */ + option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_T1); + if (option_ptr != NULL) { + /* remember given renewal period */ + dhcp->offered_t1_renew = dhcp_get_option_long(option_ptr + 2); + } else { + /* calculate safe periods for renewal */ + dhcp->offered_t1_renew = dhcp->offered_t0_lease / 2; + } + + /* renewal period given? */ + option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_T2); + if (option_ptr != NULL) { + /* remember given rebind period */ + dhcp->offered_t2_rebind = dhcp_get_option_long(option_ptr + 2); + } else { + /* calculate safe periods for rebinding */ + dhcp->offered_t2_rebind = dhcp->offered_t0_lease; + } + + /* (y)our internet address */ + ip_addr_set(&dhcp->offered_ip_addr, &dhcp->msg_in->yiaddr); + +/** + * Patch #1308 + * TODO: we must check if the file field is not overloaded by DHCP options! + */ +#if 0 + /* boot server address */ + ip_addr_set(&dhcp->offered_si_addr, &dhcp->msg_in->siaddr); + /* boot file name */ + if (dhcp->msg_in->file[0]) { + dhcp->boot_file_name = mem_malloc(strlen(dhcp->msg_in->file) + 1); + strcpy(dhcp->boot_file_name, dhcp->msg_in->file); + } +#endif + + /* subnet mask */ + option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_SUBNET_MASK); + /* subnet mask given? */ + if (option_ptr != NULL) { + dhcp->offered_sn_mask.addr = htonl(dhcp_get_option_long(&option_ptr[2])); + } + + /* gateway router */ + option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_ROUTER); + if (option_ptr != NULL) { + dhcp->offered_gw_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2])); + } + + /* broadcast address */ + option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_BROADCAST); + if (option_ptr != NULL) { + dhcp->offered_bc_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2])); + } + + /* DNS servers */ + option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_DNS_SERVER); + if (option_ptr != NULL) { + u8_t n; + dhcp->dns_count = dhcp_get_option_byte(&option_ptr[1]) / (u32_t)sizeof(struct ip_addr); + /* limit to at most DHCP_MAX_DNS DNS servers */ + if (dhcp->dns_count > DHCP_MAX_DNS) + dhcp->dns_count = DHCP_MAX_DNS; + for (n = 0; n < dhcp->dns_count; n++) { + dhcp->offered_dns_addr[n].addr = htonl(dhcp_get_option_long(&option_ptr[2 + n * 4])); +#if LWIP_DNS + dns_setserver( n, (struct ip_addr *)(&(dhcp->offered_dns_addr[n].addr))); +#endif /* LWIP_DNS */ + } +#if LWIP_DNS + dns_setserver( n, (struct ip_addr *)(&ip_addr_any)); +#endif /* LWIP_DNS */ + } +} + +/** + * Start DHCP negotiation for a network interface. + * + * If no DHCP client instance was attached to this interface, + * a new client is created first. If a DHCP client instance + * was already present, it restarts negotiation. + * + * @param netif The lwIP network interface + * @return lwIP error code + * - ERR_OK - No error + * - ERR_MEM - Out of memory + */ +err_t +dhcp_start(struct netif *netif) +{ + struct dhcp *dhcp; + err_t result = ERR_OK; + + LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG;); + dhcp = netif->dhcp; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); + /* Remove the flag that says this netif is handled by DHCP, + it is set when we succeeded starting. */ + netif->flags &= ~NETIF_FLAG_DHCP; + + /* check MTU of the netif */ + if (netif->mtu < DHCP_MAX_MSG_LEN_MIN_REQUIRED) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): Cannot use this netif with DHCP: MTU is too small\n")); + return ERR_MEM; + } + + /* no DHCP client attached yet? */ + if (dhcp == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting new DHCP client\n")); + dhcp = mem_malloc(sizeof(struct dhcp)); + if (dhcp == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not allocate dhcp\n")); + return ERR_MEM; + } + /* store this dhcp client in the netif */ + netif->dhcp = dhcp; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): allocated dhcp")); + /* already has DHCP client attached */ + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_start(): restarting DHCP configuration\n")); + if (dhcp->pcb != NULL) { + udp_remove(dhcp->pcb); + } + LWIP_ASSERT("pbuf p_out wasn't freed", dhcp->p_out == NULL); + LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL && + dhcp->options_in == NULL && dhcp->options_in_len == 0); + } + + /* clear data structure */ + memset(dhcp, 0, sizeof(struct dhcp)); + /* allocate UDP PCB */ + dhcp->pcb = udp_new(); + if (dhcp->pcb == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not obtain pcb\n")); + mem_free((void *)dhcp); + netif->dhcp = dhcp = NULL; + return ERR_MEM; + } +#if IP_SOF_BROADCAST + dhcp->pcb->so_options|=SOF_BROADCAST; +#endif /* IP_SOF_BROADCAST */ + /* set up local and remote port for the pcb */ + udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT); + udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT); + /* set up the recv callback and argument */ + udp_recv(dhcp->pcb, dhcp_recv, netif); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting DHCP configuration\n")); + /* (re)start the DHCP negotiation */ + result = dhcp_discover(netif); + if (result != ERR_OK) { + /* free resources allocated above */ + dhcp_stop(netif); + return ERR_MEM; + } + /* Set the flag that says this netif is handled by DHCP. */ + netif->flags |= NETIF_FLAG_DHCP; + return result; +} + +/** + * Inform a DHCP server of our manual configuration. + * + * This informs DHCP servers of our fixed IP address configuration + * by sending an INFORM message. It does not involve DHCP address + * configuration, it is just here to be nice to the network. + * + * @param netif The lwIP network interface + */ +void +dhcp_inform(struct netif *netif) +{ + struct dhcp *dhcp, *old_dhcp; + err_t result = ERR_OK; + dhcp = mem_malloc(sizeof(struct dhcp)); + if (dhcp == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform(): could not allocate dhcp\n")); + return; + } + memset(dhcp, 0, sizeof(struct dhcp)); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_inform(): allocated dhcp\n")); + dhcp->pcb = udp_new(); + if (dhcp->pcb == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform(): could not obtain pcb")); + goto free_dhcp_and_return; + } + old_dhcp = netif->dhcp; + netif->dhcp = dhcp; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_inform(): created new udp pcb\n")); + /* create and initialize the DHCP message header */ + result = dhcp_create_request(netif); + if (result == ERR_OK) { + + dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN); + dhcp_option_byte(dhcp, DHCP_INFORM); + + dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); + + dhcp_option_trailer(dhcp); + + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + +#if IP_SOF_BROADCAST + dhcp->pcb->so_options|=SOF_BROADCAST; +#endif /* IP_SOF_BROADCAST */ + udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_inform: INFORMING\n")); + udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); + dhcp_delete_request(netif); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform: could not allocate DHCP request\n")); + } + + udp_remove(dhcp->pcb); + dhcp->pcb = NULL; + netif->dhcp = old_dhcp; +free_dhcp_and_return: + mem_free((void *)dhcp); +} + +/** Handle a possible change in the network configuration. + * + * This enters the REBOOTING state to verify that the currently bound + * address is still valid. + */ +void +dhcp_network_changed(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + if (!dhcp) + return; + switch (dhcp->state) { + case DHCP_REBINDING: + case DHCP_RENEWING: + case DHCP_BOUND: + case DHCP_REBOOTING: + netif_set_down(netif); + dhcp->tries = 0; + dhcp_reboot(netif); + break; + case DHCP_OFF: + /* stay off */ + break; + default: + dhcp->tries = 0; + dhcp_discover(netif); + break; + } +} + +#if DHCP_DOES_ARP_CHECK +/** + * Match an ARP reply with the offered IP address. + * + * @param netif the network interface on which the reply was received + * @param addr The IP address we received a reply from + */ +void dhcp_arp_reply(struct netif *netif, struct ip_addr *addr) +{ + LWIP_ERROR("netif != NULL", (netif != NULL), return;); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_arp_reply()\n")); + /* is a DHCP client doing an ARP check? */ + if ((netif->dhcp != NULL) && (netif->dhcp->state == DHCP_CHECKING)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08"X32_F"\n", addr->addr)); + /* did a host respond with the address we + were offered by the DHCP server? */ + if (ip_addr_cmp(addr, &netif->dhcp->offered_ip_addr)) { + /* we will not accept the offered address */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING, + ("dhcp_arp_reply(): arp reply matched with offered address, declining\n")); + dhcp_decline(netif); + } + } +} + +/** + * Decline an offered lease. + * + * Tell the DHCP server we do not accept the offered address. + * One reason to decline the lease is when we find out the address + * is already in use by another host (through ARP). + * + * @param netif the netif under DHCP control + */ +static err_t +dhcp_decline(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result = ERR_OK; + u16_t msecs; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline()\n")); + dhcp_set_state(dhcp, DHCP_BACKING_OFF); + /* create and initialize the DHCP message header */ + result = dhcp_create_request(netif); + if (result == ERR_OK) { + dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN); + dhcp_option_byte(dhcp, DHCP_DECLINE); + + dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); + dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr)); + + dhcp_option_trailer(dhcp); + /* resize pbuf to reflect true size of options */ + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + /* per section 4.4.4, broadcast DECLINE messages */ + udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); + dhcp_delete_request(netif); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_decline: BACKING OFF\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("dhcp_decline: could not allocate DHCP request\n")); + } + dhcp->tries++; + msecs = 10*1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} +#endif + + +/** + * Start the DHCP process, discover a DHCP server. + * + * @param netif the netif under DHCP control + */ +static err_t +dhcp_discover(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result = ERR_OK; + u16_t msecs; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover()\n")); + ip_addr_set(&dhcp->offered_ip_addr, IP_ADDR_ANY); + dhcp_set_state(dhcp, DHCP_SELECTING); + /* create and initialize the DHCP message header */ + result = dhcp_create_request(netif); + if (result == ERR_OK) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: making request\n")); + dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN); + dhcp_option_byte(dhcp, DHCP_DISCOVER); + + dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); + + dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 4/*num options*/); + dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK); + dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER); + dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST); + dhcp_option_byte(dhcp, DHCP_OPTION_DNS_SERVER); + + dhcp_option_trailer(dhcp); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: realloc()ing\n")); + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, DHCP_SERVER_PORT)\n")); + udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: deleting()ing\n")); + dhcp_delete_request(netif); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover: SELECTING\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_discover: could not allocate DHCP request\n")); + } + dhcp->tries++; +#if LWIP_DHCP_AUTOIP_COOP + if(dhcp->tries >= LWIP_DHCP_AUTOIP_COOP_TRIES && dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_OFF) { + dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_ON; + autoip_start(netif); + } +#endif /* LWIP_DHCP_AUTOIP_COOP */ + msecs = (dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} + + +/** + * Bind the interface to the offered IP address. + * + * @param netif network interface to bind to the offered address + */ +static void +dhcp_bind(struct netif *netif) +{ + u32_t timeout; + struct dhcp *dhcp; + struct ip_addr sn_mask, gw_addr; + LWIP_ERROR("dhcp_bind: netif != NULL", (netif != NULL), return;); + dhcp = netif->dhcp; + LWIP_ERROR("dhcp_bind: dhcp != NULL", (dhcp != NULL), return;); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); + + /* temporary DHCP lease? */ + if (dhcp->offered_t1_renew != 0xffffffffUL) { + /* set renewal period timer */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t1 renewal timer %"U32_F" secs\n", dhcp->offered_t1_renew)); + timeout = (dhcp->offered_t1_renew + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS; + if(timeout > 0xffff) { + timeout = 0xffff; + } + dhcp->t1_timeout = (u16_t)timeout; + if (dhcp->t1_timeout == 0) { + dhcp->t1_timeout = 1; + } + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t1_renew*1000)); + } + /* set renewal period timer */ + if (dhcp->offered_t2_rebind != 0xffffffffUL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t2 rebind timer %"U32_F" secs\n", dhcp->offered_t2_rebind)); + timeout = (dhcp->offered_t2_rebind + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS; + if(timeout > 0xffff) { + timeout = 0xffff; + } + dhcp->t2_timeout = (u16_t)timeout; + if (dhcp->t2_timeout == 0) { + dhcp->t2_timeout = 1; + } + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t2_rebind*1000)); + } + /* copy offered network mask */ + ip_addr_set(&sn_mask, &dhcp->offered_sn_mask); + + /* subnet mask not given? */ + /* TODO: this is not a valid check. what if the network mask is 0? */ + if (sn_mask.addr == 0) { + /* choose a safe subnet mask given the network class */ + u8_t first_octet = ip4_addr1(&sn_mask); + if (first_octet <= 127) { + sn_mask.addr = htonl(0xff000000); + } else if (first_octet >= 192) { + sn_mask.addr = htonl(0xffffff00); + } else { + sn_mask.addr = htonl(0xffff0000); + } + } + + ip_addr_set(&gw_addr, &dhcp->offered_gw_addr); + /* gateway address not given? */ + if (gw_addr.addr == 0) { + /* copy network address */ + gw_addr.addr = (dhcp->offered_ip_addr.addr & sn_mask.addr); + /* use first host address on network as gateway */ + gw_addr.addr |= htonl(0x00000001); + } + +#if LWIP_DHCP_AUTOIP_COOP + if(dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) { + autoip_stop(netif); + dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF; + } +#endif /* LWIP_DHCP_AUTOIP_COOP */ + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): IP: 0x%08"X32_F"\n", dhcp->offered_ip_addr.addr)); + netif_set_ipaddr(netif, &dhcp->offered_ip_addr); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): SN: 0x%08"X32_F"\n", sn_mask.addr)); + netif_set_netmask(netif, &sn_mask); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): GW: 0x%08"X32_F"\n", gw_addr.addr)); + netif_set_gw(netif, &gw_addr); + /* bring the interface up */ + netif_set_up(netif); + /* netif is now bound to DHCP leased address */ + dhcp_set_state(dhcp, DHCP_BOUND); +} + +/** + * Renew an existing DHCP lease at the involved DHCP server. + * + * @param netif network interface which must renew its lease + */ +err_t +dhcp_renew(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result; + u16_t msecs; +#if LWIP_NETIF_HOSTNAME + const char *p; +#endif /* LWIP_NETIF_HOSTNAME */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_renew()\n")); + dhcp_set_state(dhcp, DHCP_RENEWING); + + /* create and initialize the DHCP message header */ + result = dhcp_create_request(netif); + if (result == ERR_OK) { + + dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN); + dhcp_option_byte(dhcp, DHCP_REQUEST); + + dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); + +#if LWIP_NETIF_HOSTNAME + p = (const char*)netif->hostname; + if (p != NULL) { + dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, strlen(p)); + while (*p) { + dhcp_option_byte(dhcp, *p++); + } + } +#endif /* LWIP_NETIF_HOSTNAME */ + +#if 0 + dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); + dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr)); +#endif + +#if 0 + dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4); + dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr)); +#endif + /* append DHCP message trailer */ + dhcp_option_trailer(dhcp); + + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + udp_sendto_if(dhcp->pcb, dhcp->p_out, &dhcp->server_ip_addr, DHCP_SERVER_PORT, netif); + dhcp_delete_request(netif); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew: RENEWING\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_renew: could not allocate DHCP request\n")); + } + dhcp->tries++; + /* back-off on retries, but to a maximum of 20 seconds */ + msecs = dhcp->tries < 10 ? dhcp->tries * 2000 : 20 * 1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} + +/** + * Rebind with a DHCP server for an existing DHCP lease. + * + * @param netif network interface which must rebind with a DHCP server + */ +static err_t +dhcp_rebind(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result; + u16_t msecs; +#if LWIP_NETIF_HOSTNAME + const char *p; +#endif /* LWIP_NETIF_HOSTNAME */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind()\n")); + dhcp_set_state(dhcp, DHCP_REBINDING); + + /* create and initialize the DHCP message header */ + result = dhcp_create_request(netif); + if (result == ERR_OK) { + + dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN); + dhcp_option_byte(dhcp, DHCP_REQUEST); + + dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); + +#if LWIP_NETIF_HOSTNAME + p = (const char*)netif->hostname; + if (p != NULL) { + dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, strlen(p)); + while (*p) { + dhcp_option_byte(dhcp, *p++); + } + } +#endif /* LWIP_NETIF_HOSTNAME */ + +#if 0 + dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); + dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr)); + + dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4); + dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr)); +#endif + + dhcp_option_trailer(dhcp); + + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + /* broadcast to server */ + udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); + dhcp_delete_request(netif); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind: REBINDING\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_rebind: could not allocate DHCP request\n")); + } + dhcp->tries++; + msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} + +/** + * Enter REBOOTING state to verify an existing lease + * + * @param netif network interface which must reboot + */ +static err_t +dhcp_reboot(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result; + u16_t msecs; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot()\n")); + dhcp_set_state(dhcp, DHCP_REBOOTING); + + /* create and initialize the DHCP message header */ + result = dhcp_create_request(netif); + if (result == ERR_OK) { + + dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN); + dhcp_option_byte(dhcp, DHCP_REQUEST); + + dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(dhcp, 576); + + dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); + dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr)); + + dhcp_option_trailer(dhcp); + + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + /* broadcast to server */ + udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); + dhcp_delete_request(netif); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot: REBOOTING\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_reboot: could not allocate DHCP request\n")); + } + dhcp->tries++; + msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} + + +/** + * Release a DHCP lease. + * + * @param netif network interface which must release its lease + */ +err_t +dhcp_release(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result; + u16_t msecs; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_release()\n")); + + /* idle DHCP client */ + dhcp_set_state(dhcp, DHCP_OFF); + /* clean old DHCP offer */ + dhcp->server_ip_addr.addr = 0; + dhcp->offered_ip_addr.addr = dhcp->offered_sn_mask.addr = 0; + dhcp->offered_gw_addr.addr = dhcp->offered_bc_addr.addr = 0; + dhcp->offered_t0_lease = dhcp->offered_t1_renew = dhcp->offered_t2_rebind = 0; + dhcp->dns_count = 0; + + /* create and initialize the DHCP message header */ + result = dhcp_create_request(netif); + if (result == ERR_OK) { + dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN); + dhcp_option_byte(dhcp, DHCP_RELEASE); + + dhcp_option_trailer(dhcp); + + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + udp_sendto_if(dhcp->pcb, dhcp->p_out, &dhcp->server_ip_addr, DHCP_SERVER_PORT, netif); + dhcp_delete_request(netif); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release: RELEASED, DHCP_OFF\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_release: could not allocate DHCP request\n")); + } + dhcp->tries++; + msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release(): set request timeout %"U16_F" msecs\n", msecs)); + /* bring the interface down */ + netif_set_down(netif); + /* remove IP address from interface */ + netif_set_ipaddr(netif, IP_ADDR_ANY); + netif_set_gw(netif, IP_ADDR_ANY); + netif_set_netmask(netif, IP_ADDR_ANY); + + /* TODO: netif_down(netif); */ + return result; +} + +/** + * Release a DHCP lease. + * + * @param netif network interface which must release its lease + */ +err_t +dhcp_release_unicast(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result; + u16_t msecs; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_release()\n")); + + /* idle DHCP client */ + dhcp_set_state(dhcp, DHCP_RELEASING); + /* clean old DHCP offer *//* + dhcp->server_ip_addr.addr = 0; + dhcp->offered_ip_addr.addr = dhcp->offered_sn_mask.addr = 0; + dhcp->offered_gw_addr.addr = dhcp->offered_bc_addr.addr = 0; + dhcp->offered_t0_lease = dhcp->offered_t1_renew = dhcp->offered_t2_rebind = 0; + dhcp->dns_count = 0;*/ + + /* create and initialize the DHCP message header */ + result = dhcp_create_request(netif); + if (result == ERR_OK) { + dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN); + dhcp_option_byte(dhcp, DHCP_RELEASE); + + dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4); + dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr)); + + dhcp_option_trailer(dhcp); + + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + udp_sendto_if(dhcp->pcb, dhcp->p_out, &dhcp->server_ip_addr, DHCP_SERVER_PORT, netif); + dhcp_delete_request(netif); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release: RELEASED, DHCP_OFF\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_release: could not allocate DHCP request\n")); + } + dhcp->tries++; + msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release(): set request timeout %"U16_F" msecs\n", msecs)); + /* bring the interface down */ + netif_set_down(netif); + /* remove IP address from interface */ + netif_set_ipaddr(netif, IP_ADDR_ANY); + netif_set_gw(netif, IP_ADDR_ANY); + netif_set_netmask(netif, IP_ADDR_ANY); + + /* TODO: netif_down(netif); */ + return result; +} + +/** + * Remove the DHCP client from the interface. + * + * @param netif The network interface to stop DHCP on + */ +void +dhcp_stop(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + LWIP_ERROR("dhcp_stop: netif != NULL", (netif != NULL), return;); + /* Remove the flag that says this netif is handled by DHCP. */ + netif->flags &= ~NETIF_FLAG_DHCP; + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_stop()\n")); + /* netif is DHCP configured? */ + if (dhcp != NULL) { +#if LWIP_DHCP_AUTOIP_COOP + if(dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) { + autoip_stop(netif); + dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF; + } +#endif /* LWIP_DHCP_AUTOIP_COOP */ + + if (dhcp->pcb != NULL) { + udp_remove(dhcp->pcb); + dhcp->pcb = NULL; + } + LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL && + dhcp->options_in == NULL && dhcp->options_in_len == 0); + mem_free((void *)dhcp); + netif->dhcp = NULL; + } +} + +/* + * Set the DHCP state of a DHCP client. + * + * If the state changed, reset the number of tries. + * + * TODO: we might also want to reset the timeout here? + */ +static void +dhcp_set_state(struct dhcp *dhcp, u8_t new_state) +{ + if (new_state != dhcp->state) { + dhcp->state = new_state; + dhcp->tries = 0; + } +} + +/* + * Concatenate an option type and length field to the outgoing + * DHCP message. + * + */ +static void +dhcp_option(struct dhcp *dhcp, u8_t option_type, u8_t option_len) +{ + LWIP_ASSERT("dhcp_option: dhcp->options_out_len + 2 + option_len <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 2U + option_len <= DHCP_OPTIONS_LEN); + dhcp->msg_out->options[dhcp->options_out_len++] = option_type; + dhcp->msg_out->options[dhcp->options_out_len++] = option_len; +} +/* + * Concatenate a single byte to the outgoing DHCP message. + * + */ +static void +dhcp_option_byte(struct dhcp *dhcp, u8_t value) +{ + LWIP_ASSERT("dhcp_option_byte: dhcp->options_out_len < DHCP_OPTIONS_LEN", dhcp->options_out_len < DHCP_OPTIONS_LEN); + dhcp->msg_out->options[dhcp->options_out_len++] = value; +} + +static void +dhcp_option_short(struct dhcp *dhcp, u16_t value) +{ + LWIP_ASSERT("dhcp_option_short: dhcp->options_out_len + 2 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 2U <= DHCP_OPTIONS_LEN); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0xff00U) >> 8); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t) (value & 0x00ffU); +} + +static void +dhcp_option_long(struct dhcp *dhcp, u32_t value) +{ + LWIP_ASSERT("dhcp_option_long: dhcp->options_out_len + 4 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 4U <= DHCP_OPTIONS_LEN); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0xff000000UL) >> 24); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x00ff0000UL) >> 16); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x0000ff00UL) >> 8); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x000000ffUL)); +} + +/** + * Extract the DHCP message and the DHCP options. + * + * Extract the DHCP message and the DHCP options, each into a contiguous + * piece of memory. As a DHCP message is variable sized by its options, + * and also allows overriding some fields for options, the easy approach + * is to first unfold the options into a conitguous piece of memory, and + * use that further on. + * + */ +static err_t +dhcp_unfold_reply(struct dhcp *dhcp, struct pbuf *p) +{ + u16_t ret; + LWIP_ERROR("dhcp != NULL", (dhcp != NULL), return ERR_ARG;); + /* free any left-overs from previous unfolds */ + dhcp_free_reply(dhcp); + /* options present? */ + if (p->tot_len > (sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN)) { + dhcp->options_in_len = p->tot_len - (sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN); + dhcp->options_in = mem_malloc(dhcp->options_in_len); + if (dhcp->options_in == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("dhcp_unfold_reply(): could not allocate dhcp->options\n")); + dhcp->options_in_len = 0; + return ERR_MEM; + } + } + dhcp->msg_in = mem_malloc(sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN); + if (dhcp->msg_in == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("dhcp_unfold_reply(): could not allocate dhcp->msg_in\n")); + if (dhcp->options_in != NULL) { + mem_free(dhcp->options_in); + dhcp->options_in = NULL; + dhcp->options_in_len = 0; + } + return ERR_MEM; + } + + /** copy the DHCP message without options */ + ret = pbuf_copy_partial(p, dhcp->msg_in, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN, 0); + LWIP_ASSERT("ret == sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN", ret == sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_unfold_reply(): copied %"U16_F" bytes into dhcp->msg_in[]\n", + sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN)); + + if (dhcp->options_in != NULL) { + /** copy the DHCP options */ + ret = pbuf_copy_partial(p, dhcp->options_in, dhcp->options_in_len, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN); + LWIP_ASSERT("ret == dhcp->options_in_len", ret == dhcp->options_in_len); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_unfold_reply(): copied %"U16_F" bytes to dhcp->options_in[]\n", + dhcp->options_in_len)); + } + LWIP_UNUSED_ARG(ret); + return ERR_OK; +} + +/** + * Free the incoming DHCP message including contiguous copy of + * its DHCP options. + */ +static void dhcp_free_reply(struct dhcp *dhcp) +{ + if (dhcp->msg_in != NULL) { + mem_free((void *)dhcp->msg_in); + dhcp->msg_in = NULL; + } + if (dhcp->options_in) { + mem_free(dhcp->options_in); + dhcp->options_in = NULL; + dhcp->options_in_len = 0; + } + LWIP_DEBUGF(DHCP_DEBUG, ("dhcp_free_reply(): free'd\n")); +} + +/** + * If an incoming DHCP message is in response to us, then trigger the state machine + */ +static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port) +{ + struct netif *netif = (struct netif *)arg; + struct dhcp *dhcp = netif->dhcp; + struct dhcp_msg *reply_msg = (struct dhcp_msg *)p->payload; + u8_t *options_ptr; + u8_t msg_type; + u8_t i; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_recv(pbuf = %p) from DHCP server %"U16_F".%"U16_F".%"U16_F".%"U16_F" port %"U16_F"\n", (void*)p, + (u16_t)(ntohl(addr->addr) >> 24 & 0xff), (u16_t)(ntohl(addr->addr) >> 16 & 0xff), + (u16_t)(ntohl(addr->addr) >> 8 & 0xff), (u16_t)(ntohl(addr->addr) & 0xff), port)); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->len = %"U16_F"\n", p->len)); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->tot_len = %"U16_F"\n", p->tot_len)); + /* prevent warnings about unused arguments */ + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(addr); + LWIP_UNUSED_ARG(port); + + LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL && + dhcp->options_in == NULL && dhcp->options_in_len == 0); + + if (p->len < DHCP_MIN_REPLY_LEN) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP reply message too short\n")); + goto free_pbuf_and_return; + } + + if (reply_msg->op != DHCP_BOOTREPLY) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("not a DHCP reply message, but type %"U16_F"\n", (u16_t)reply_msg->op)); + goto free_pbuf_and_return; + } + /* iterate through hardware address and match against DHCP message */ + for (i = 0; i < netif->hwaddr_len; i++) { + if (netif->hwaddr[i] != reply_msg->chaddr[i]) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("netif->hwaddr[%"U16_F"]==%02"X16_F" != reply_msg->chaddr[%"U16_F"]==%02"X16_F"\n", + (u16_t)i, (u16_t)netif->hwaddr[i], (u16_t)i, (u16_t)reply_msg->chaddr[i])); + goto free_pbuf_and_return; + } + } + /* match transaction ID against what we expected */ + if (ntohl(reply_msg->xid) != dhcp->xid) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("transaction id mismatch reply_msg->xid(%"X32_F")!=dhcp->xid(%"X32_F")\n",ntohl(reply_msg->xid),dhcp->xid)); + goto free_pbuf_and_return; + } + /* option fields could be unfold? */ + if (dhcp_unfold_reply(dhcp, p) != ERR_OK) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("problem unfolding DHCP message - too short on memory?\n")); + goto free_pbuf_and_return; + } + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("searching DHCP_OPTION_MESSAGE_TYPE\n")); + /* obtain pointer to DHCP message type */ + options_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_MESSAGE_TYPE); + if (options_ptr == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP_OPTION_MESSAGE_TYPE option not found\n")); + goto free_pbuf_and_return; + } + + /* read DHCP message type */ + msg_type = dhcp_get_option_byte(options_ptr + 2); + /* message type is DHCP ACK? */ + if (msg_type == DHCP_ACK) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_ACK received\n")); + /* in requesting state? */ + if (dhcp->state == DHCP_REQUESTING) { + dhcp_handle_ack(netif); + dhcp->request_timeout = 0; +#if DHCP_DOES_ARP_CHECK + /* check if the acknowledged lease address is already in use */ + dhcp_check(netif); +#else + /* bind interface to the acknowledged lease address */ + dhcp_bind(netif); +#endif + } + /* already bound to the given lease address? */ + else if ((dhcp->state == DHCP_REBOOTING) || (dhcp->state == DHCP_REBINDING) || (dhcp->state == DHCP_RENEWING)) { + dhcp->request_timeout = 0; + dhcp_bind(netif); + } + } + /* received a DHCP_NAK in appropriate state? */ + else if ((msg_type == DHCP_NAK) && + ((dhcp->state == DHCP_REBOOTING) || (dhcp->state == DHCP_REQUESTING) || + (dhcp->state == DHCP_REBINDING) || (dhcp->state == DHCP_RENEWING ))) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_NAK received\n")); + dhcp->request_timeout = 0; + dhcp_handle_nak(netif); + } + /* received a DHCP_OFFER in DHCP_SELECTING state? */ + else if ((msg_type == DHCP_OFFER) && (dhcp->state == DHCP_SELECTING)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_OFFER received in DHCP_SELECTING state\n")); + dhcp->request_timeout = 0; + /* remember offered lease */ + dhcp_handle_offer(netif); + } +free_pbuf_and_return: + dhcp_free_reply(dhcp); + pbuf_free(p); +} + +/** + * Create a DHCP request, fill in common headers + * + * @param netif the netif under DHCP control + */ +static err_t +dhcp_create_request(struct netif *netif) +{ + struct dhcp *dhcp; + u16_t i; +#ifndef DHCP_GLOBAL_XID + /** default global transaction identifier starting value (easy to match + * with a packet analyser). We simply increment for each new request. + * Predefine DHCP_GLOBAL_XID to a better value or a function call to generate one + * at runtime, any supporting function prototypes can be defined in DHCP_GLOBAL_XID_HEADER */ + static u32_t xid = 0xABCD0000; +#else + static u32_t xid; + static u8_t xid_initialised = 0; + if (!xid_initialised) { + xid = DHCP_GLOBAL_XID; + xid_initialised = !xid_initialised; + } +#endif + LWIP_ERROR("dhcp_create_request: netif != NULL", (netif != NULL), return ERR_ARG;); + dhcp = netif->dhcp; + LWIP_ERROR("dhcp_create_request: dhcp != NULL", (dhcp != NULL), return ERR_VAL;); + LWIP_ASSERT("dhcp_create_request: dhcp->p_out == NULL", dhcp->p_out == NULL); + LWIP_ASSERT("dhcp_create_request: dhcp->msg_out == NULL", dhcp->msg_out == NULL); + dhcp->p_out = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcp_msg), PBUF_RAM); + if (dhcp->p_out == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("dhcp_create_request(): could not allocate pbuf\n")); + return ERR_MEM; + } + LWIP_ASSERT("dhcp_create_request: check that first pbuf can hold struct dhcp_msg", + (dhcp->p_out->len >= sizeof(struct dhcp_msg))); + + /* reuse transaction identifier in retransmissions */ + if (dhcp->tries==0) + xid++; + dhcp->xid = xid; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, + ("transaction id xid(%"X32_F")\n", xid)); + + dhcp->msg_out = (struct dhcp_msg *)dhcp->p_out->payload; + + dhcp->msg_out->op = DHCP_BOOTREQUEST; + /* TODO: make link layer independent */ + dhcp->msg_out->htype = DHCP_HTYPE_ETH; + /* TODO: make link layer independent */ + dhcp->msg_out->hlen = DHCP_HLEN_ETH; + dhcp->msg_out->hops = 0; + dhcp->msg_out->xid = htonl(dhcp->xid); + dhcp->msg_out->secs = 0; + dhcp->msg_out->flags = 0; + dhcp->msg_out->ciaddr.addr = 0; + if (dhcp->state==DHCP_BOUND || dhcp->state==DHCP_RENEWING || dhcp->state==DHCP_REBINDING || dhcp->state == DHCP_RELEASING) { + dhcp->msg_out->ciaddr.addr = netif->ip_addr.addr; + } + dhcp->msg_out->yiaddr.addr = 0; + dhcp->msg_out->siaddr.addr = 0; + dhcp->msg_out->giaddr.addr = 0; + for (i = 0; i < DHCP_CHADDR_LEN; i++) { + /* copy netif hardware address, pad with zeroes */ + dhcp->msg_out->chaddr[i] = (i < netif->hwaddr_len) ? netif->hwaddr[i] : 0/* pad byte*/; + } + for (i = 0; i < DHCP_SNAME_LEN; i++) { + dhcp->msg_out->sname[i] = 0; + } + for (i = 0; i < DHCP_FILE_LEN; i++) { + dhcp->msg_out->file[i] = 0; + } + dhcp->msg_out->cookie = htonl(0x63825363UL); + dhcp->options_out_len = 0; + /* fill options field with an incrementing array (for debugging purposes) */ + for (i = 0; i < DHCP_OPTIONS_LEN; i++) { + dhcp->msg_out->options[i] = (u8_t)i; /* for debugging only, no matter if truncated */ + } + return ERR_OK; +} + +/** + * Free previously allocated memory used to send a DHCP request. + * + * @param netif the netif under DHCP control + */ +static void +dhcp_delete_request(struct netif *netif) +{ + struct dhcp *dhcp; + LWIP_ERROR("dhcp_delete_request: netif != NULL", (netif != NULL), return;); + dhcp = netif->dhcp; + LWIP_ERROR("dhcp_delete_request: dhcp != NULL", (dhcp != NULL), return;); + LWIP_ASSERT("dhcp_delete_request: dhcp->p_out != NULL", dhcp->p_out != NULL); + LWIP_ASSERT("dhcp_delete_request: dhcp->msg_out != NULL", dhcp->msg_out != NULL); + if (dhcp->p_out != NULL) { + pbuf_free(dhcp->p_out); + } + dhcp->p_out = NULL; + dhcp->msg_out = NULL; +} + +/** + * Add a DHCP message trailer + * + * Adds the END option to the DHCP message, and if + * necessary, up to three padding bytes. + * + * @param dhcp DHCP state structure + */ +static void +dhcp_option_trailer(struct dhcp *dhcp) +{ + LWIP_ERROR("dhcp_option_trailer: dhcp != NULL", (dhcp != NULL), return;); + LWIP_ASSERT("dhcp_option_trailer: dhcp->msg_out != NULL\n", dhcp->msg_out != NULL); + LWIP_ASSERT("dhcp_option_trailer: dhcp->options_out_len < DHCP_OPTIONS_LEN\n", dhcp->options_out_len < DHCP_OPTIONS_LEN); + dhcp->msg_out->options[dhcp->options_out_len++] = DHCP_OPTION_END; + /* packet is too small, or not 4 byte aligned? */ + while ((dhcp->options_out_len < DHCP_MIN_OPTIONS_LEN) || (dhcp->options_out_len & 3)) { + /* LWIP_DEBUGF(DHCP_DEBUG,("dhcp_option_trailer:dhcp->options_out_len=%"U16_F", DHCP_OPTIONS_LEN=%"U16_F, dhcp->options_out_len, DHCP_OPTIONS_LEN)); */ + LWIP_ASSERT("dhcp_option_trailer: dhcp->options_out_len < DHCP_OPTIONS_LEN\n", dhcp->options_out_len < DHCP_OPTIONS_LEN); + /* add a fill/padding byte */ + dhcp->msg_out->options[dhcp->options_out_len++] = 0; + } +} + +/** + * Find the offset of a DHCP option inside the DHCP message. + * + * @param dhcp DHCP client + * @param option_type + * + * @return a byte offset into the UDP message where the option was found, or + * zero if the given option was not found. + */ +static u8_t *dhcp_get_option_ptr(struct dhcp *dhcp, u8_t option_type) +{ + u8_t overload = DHCP_OVERLOAD_NONE; + + /* options available? */ + if ((dhcp->options_in != NULL) && (dhcp->options_in_len > 0)) { + /* start with options field */ + u8_t *options = (u8_t *)dhcp->options_in; + u16_t offset = 0; + /* at least 1 byte to read and no end marker, then at least 3 bytes to read? */ + while ((offset < dhcp->options_in_len) && (options[offset] != DHCP_OPTION_END)) { + /* LWIP_DEBUGF(DHCP_DEBUG, ("msg_offset=%"U16_F", q->len=%"U16_F, msg_offset, q->len)); */ + /* are the sname and/or file field overloaded with options? */ + if (options[offset] == DHCP_OPTION_OVERLOAD) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded message detected\n")); + /* skip option type and length */ + offset += 2; + overload = options[offset++]; + } + /* requested option found */ + else if (options[offset] == option_type) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("option found at offset %"U16_F" in options\n", offset)); + return &options[offset]; + /* skip option */ + } else { + LWIP_DEBUGF(DHCP_DEBUG, ("skipping option %"U16_F" in options\n", options[offset])); + /* skip option type */ + offset++; + /* skip option length, and then length bytes */ + offset += 1 + options[offset]; + } + } + /* is this an overloaded message? */ + if (overload != DHCP_OVERLOAD_NONE) { + u16_t field_len; + if (overload == DHCP_OVERLOAD_FILE) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded file field\n")); + options = (u8_t *)&dhcp->msg_in->file; + field_len = DHCP_FILE_LEN; + } else if (overload == DHCP_OVERLOAD_SNAME) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname field\n")); + options = (u8_t *)&dhcp->msg_in->sname; + field_len = DHCP_SNAME_LEN; + /* TODO: check if else if () is necessary */ + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname and file field\n")); + options = (u8_t *)&dhcp->msg_in->sname; + field_len = DHCP_FILE_LEN + DHCP_SNAME_LEN; + } + offset = 0; + + /* at least 1 byte to read and no end marker */ + while ((offset < field_len) && (options[offset] != DHCP_OPTION_END)) { + if (options[offset] == option_type) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("option found at offset=%"U16_F"\n", offset)); + return &options[offset]; + /* skip option */ + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("skipping option %"U16_F"\n", options[offset])); + /* skip option type */ + offset++; + offset += 1 + options[offset]; + } + } + } + } + return NULL; +} + +/** + * Return the byte of DHCP option data. + * + * @param client DHCP client. + * @param ptr pointer obtained by dhcp_get_option_ptr(). + * + * @return byte value at the given address. + */ +static u8_t +dhcp_get_option_byte(u8_t *ptr) +{ + LWIP_DEBUGF(DHCP_DEBUG, ("option byte value=%"U16_F"\n", (u16_t)(*ptr))); + return *ptr; +} + +#if 0 /* currently unused */ +/** + * Return the 16-bit value of DHCP option data. + * + * @param client DHCP client. + * @param ptr pointer obtained by dhcp_get_option_ptr(). + * + * @return byte value at the given address. + */ +static u16_t +dhcp_get_option_short(u8_t *ptr) +{ + u16_t value; + value = *ptr++ << 8; + value |= *ptr; + LWIP_DEBUGF(DHCP_DEBUG, ("option short value=%"U16_F"\n", value)); + return value; +} +#endif + +/** + * Return the 32-bit value of DHCP option data. + * + * @param client DHCP client. + * @param ptr pointer obtained by dhcp_get_option_ptr(). + * + * @return byte value at the given address. + */ +static u32_t dhcp_get_option_long(u8_t *ptr) +{ + u32_t value; + value = (u32_t)(*ptr++) << 24; + value |= (u32_t)(*ptr++) << 16; + value |= (u32_t)(*ptr++) << 8; + value |= (u32_t)(*ptr++); + LWIP_DEBUGF(DHCP_DEBUG, ("option long value=%"U32_F"\n", value)); + return value; +} + +#endif /* LWIP_DHCP */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/core/dns.c b/component/common/network/lwip/lwip_v1.3.2/src/core/dns.c new file mode 100644 index 0000000..b18a360 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/core/dns.c @@ -0,0 +1,980 @@ +/* + * @file + * DNS - host name to IP address resolver. + * + */ + +/** + + * This file implements a DNS host name to IP address resolver. + + * Port to lwIP from uIP + * by Jim Pettinato April 2007 + + * uIP version Copyright (c) 2002-2003, Adam Dunkels. + * 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. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * + * DNS.C + * + * The lwIP DNS resolver functions are used to lookup a host name and + * map it to a numerical IP address. It maintains a list of resolved + * hostnames that can be queried with the dns_lookup() function. + * New hostnames can be resolved using the dns_query() function. + * + * The lwIP version of the resolver also adds a non-blocking version of + * gethostbyname() that will work with a raw API application. This function + * checks for an IP address string first and converts it if it is valid. + * gethostbyname() then does a dns_lookup() to see if the name is + * already in the table. If so, the IP is returned. If not, a query is + * issued and the function returns with a ERR_INPROGRESS status. The app + * using the dns client must then go into a waiting state. + * + * Once a hostname has been resolved (or found to be non-existent), + * the resolver code calls a specified callback function (which + * must be implemented by the module that uses the resolver). + */ + +/*----------------------------------------------------------------------------- + * RFC 1035 - Domain names - implementation and specification + * RFC 2181 - Clarifications to the DNS Specification + *----------------------------------------------------------------------------*/ + +/** @todo: define good default values (rfc compliance) */ +/** @todo: improve answer parsing, more checkings... */ +/** @todo: check RFC1035 - 7.3. Processing responses */ + +/*----------------------------------------------------------------------------- + * Includes + *----------------------------------------------------------------------------*/ + +#include "lwip/opt.h" + +#if LWIP_DNS /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/udp.h" +#include "lwip/mem.h" +#include "lwip/dns.h" + +#include + +/** DNS server IP address */ +#ifndef DNS_SERVER_ADDRESS +#define DNS_SERVER_ADDRESS inet_addr("208.67.222.222") /* resolver1.opendns.com */ +#endif + +/** DNS server port address */ +#ifndef DNS_SERVER_PORT +#define DNS_SERVER_PORT 53 +#endif + +/** DNS maximum number of retries when asking for a name, before "timeout". */ +#ifndef DNS_MAX_RETRIES +#define DNS_MAX_RETRIES 4 +#endif + +/** DNS resource record max. TTL (one week as default) */ +#ifndef DNS_MAX_TTL +#define DNS_MAX_TTL 604800 +#endif + +/* DNS protocol flags */ +#define DNS_FLAG1_RESPONSE 0x80 +#define DNS_FLAG1_OPCODE_STATUS 0x10 +#define DNS_FLAG1_OPCODE_INVERSE 0x08 +#define DNS_FLAG1_OPCODE_STANDARD 0x00 +#define DNS_FLAG1_AUTHORATIVE 0x04 +#define DNS_FLAG1_TRUNC 0x02 +#define DNS_FLAG1_RD 0x01 +#define DNS_FLAG2_RA 0x80 +#define DNS_FLAG2_ERR_MASK 0x0f +#define DNS_FLAG2_ERR_NONE 0x00 +#define DNS_FLAG2_ERR_NAME 0x03 + +/* DNS protocol states */ +#define DNS_STATE_UNUSED 0 +#define DNS_STATE_NEW 1 +#define DNS_STATE_ASKING 2 +#define DNS_STATE_DONE 3 + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** DNS message header */ +struct dns_hdr { + PACK_STRUCT_FIELD(u16_t id); + PACK_STRUCT_FIELD(u8_t flags1); + PACK_STRUCT_FIELD(u8_t flags2); + PACK_STRUCT_FIELD(u16_t numquestions); + PACK_STRUCT_FIELD(u16_t numanswers); + PACK_STRUCT_FIELD(u16_t numauthrr); + PACK_STRUCT_FIELD(u16_t numextrarr); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif +#define SIZEOF_DNS_HDR 12 + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** DNS query message structure */ +struct dns_query { + /* DNS query record starts with either a domain name or a pointer + to a name already present somewhere in the packet. */ + PACK_STRUCT_FIELD(u16_t type); + PACK_STRUCT_FIELD(u16_t class); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif +#define SIZEOF_DNS_QUERY 4 + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** DNS answer message structure */ +struct dns_answer { + /* DNS answer record starts with either a domain name or a pointer + to a name already present somewhere in the packet. */ + PACK_STRUCT_FIELD(u16_t type); + PACK_STRUCT_FIELD(u16_t class); + PACK_STRUCT_FIELD(u32_t ttl); + PACK_STRUCT_FIELD(u16_t len); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif +#define SIZEOF_DNS_ANSWER 10 + +/** DNS table entry */ +struct dns_table_entry { + u8_t state; + u8_t numdns; + u8_t tmr; + u8_t retries; + u8_t seqno; + u8_t err; + u32_t ttl; + char name[DNS_MAX_NAME_LENGTH]; + struct ip_addr ipaddr; + /* pointer to callback on DNS query done */ + dns_found_callback found; + void *arg; +}; + +#if DNS_LOCAL_HOSTLIST +/** struct used for local host-list */ +struct local_hostlist_entry { + /** static hostname */ + const char *name; + /** static host address in network byteorder */ + u32_t addr; + struct local_hostlist_entry *next; +}; + +#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC +/** Local host-list. For hostnames in this list, no + * external name resolution is performed */ +static struct local_hostlist_entry *local_hostlist_dynamic; +#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + +/** Defining this allows the local_hostlist_static to be placed in a different + * linker section (e.g. FLASH) */ +#ifndef DNS_LOCAL_HOSTLIST_STORAGE_PRE +#define DNS_LOCAL_HOSTLIST_STORAGE_PRE static +#endif /* DNS_LOCAL_HOSTLIST_STORAGE_PRE */ +/** Defining this allows the local_hostlist_static to be placed in a different + * linker section (e.g. FLASH) */ +#ifndef DNS_LOCAL_HOSTLIST_STORAGE_POST +#define DNS_LOCAL_HOSTLIST_STORAGE_POST +#endif /* DNS_LOCAL_HOSTLIST_STORAGE_POST */ +DNS_LOCAL_HOSTLIST_STORAGE_PRE struct local_hostlist_entry local_hostlist_static[] + DNS_LOCAL_HOSTLIST_STORAGE_POST = DNS_LOCAL_HOSTLIST_INIT; + +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + +static void dns_init_local(); +#endif /* DNS_LOCAL_HOSTLIST */ + + +/* forward declarations */ +static void dns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port); +static void dns_check_entries(void); + +/*----------------------------------------------------------------------------- + * Globales + *----------------------------------------------------------------------------*/ + +/* DNS variables */ +static struct udp_pcb *dns_pcb; +static u8_t dns_seqno; +static struct dns_table_entry dns_table[DNS_TABLE_SIZE]; +static struct ip_addr dns_servers[DNS_MAX_SERVERS]; + +#if (DNS_USES_STATIC_BUF == 1) +static u8_t dns_payload[DNS_MSG_SIZE]; +#endif /* (DNS_USES_STATIC_BUF == 1) */ + +/** + * Initialize the resolver: set up the UDP pcb and configure the default server + * (DNS_SERVER_ADDRESS). + */ +void +dns_init() +{ + struct ip_addr dnsserver; + + /* initialize default DNS server address */ + dnsserver.addr = DNS_SERVER_ADDRESS; + + LWIP_DEBUGF(DNS_DEBUG, ("dns_init: initializing\n")); + + /* if dns client not yet initialized... */ + if (dns_pcb == NULL) { + dns_pcb = udp_new(); + + if (dns_pcb != NULL) { + /* initialize DNS table not needed (initialized to zero since it is a + * global variable) */ + LWIP_ASSERT("For implicit initialization to work, DNS_STATE_UNUSED needs to be 0", + DNS_STATE_UNUSED == 0); + + /* initialize DNS client */ + udp_bind(dns_pcb, IP_ADDR_ANY, 0); + udp_recv(dns_pcb, dns_recv, NULL); + + /* initialize default DNS primary server */ + dns_setserver(0, &dnsserver); + } + } +#if DNS_LOCAL_HOSTLIST + dns_init_local(); +#endif +} + +/** + * Initialize one of the DNS servers. + * + * @param numdns the index of the DNS server to set must be < DNS_MAX_SERVERS + * @param dnsserver IP address of the DNS server to set + */ +void +dns_setserver(u8_t numdns, struct ip_addr *dnsserver) +{ + if ((numdns < DNS_MAX_SERVERS) && (dns_pcb != NULL) && + (dnsserver != NULL) && (dnsserver->addr !=0 )) { + dns_servers[numdns] = (*dnsserver); + } +} + +/** + * Obtain one of the currently configured DNS server. + * + * @param numdns the index of the DNS server + * @return IP address of the indexed DNS server or "ip_addr_any" if the DNS + * server has not been configured. + */ +struct ip_addr +dns_getserver(u8_t numdns) +{ + if (numdns < DNS_MAX_SERVERS) { + return dns_servers[numdns]; + } else { + return *IP_ADDR_ANY; + } +} + +/** + * The DNS resolver client timer - handle retries and timeouts and should + * be called every DNS_TMR_INTERVAL milliseconds (every second by default). + */ +void +dns_tmr(void) +{ + if (dns_pcb != NULL) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_tmr: dns_check_entries\n")); + dns_check_entries(); + } +} + +#if DNS_LOCAL_HOSTLIST +static void +dns_init_local() +{ +#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT) + int i; + struct local_hostlist_entry *entry; + /* Dynamic: copy entries from DNS_LOCAL_HOSTLIST_INIT to list */ + struct local_hostlist_entry local_hostlist_init[] = DNS_LOCAL_HOSTLIST_INIT; + for (i = 0; i < sizeof(local_hostlist_init) / sizeof(struct local_hostlist_entry); i++) { + entry = mem_malloc(sizeof(struct local_hostlist_entry)); + LWIP_ASSERT("mem-error in dns_init_local", entry != NULL); + if (entry != NULL) { + struct local_hostlist_entry *init_entry = &local_hostlist_init[i]; + entry->name = init_entry->name; + entry->addr = init_entry->addr; + entry->next = local_hostlist_dynamic; + local_hostlist_dynamic = entry; + } + } +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT) */ +} + +/** + * Scans the local host-list for a hostname. + * + * @param hostname Hostname to look for in the local host-list + * @return The first IP address for the hostname in the local host-list or + * INADDR_NONE if not found. + */ +static u32_t +dns_lookup_local(const char *hostname) +{ +#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC + struct local_hostlist_entry *entry = local_hostlist_dynamic; + while(entry != NULL) { + if(strcmp(entry->name, hostname) == 0) { + return entry->addr; + } + entry = entry->next; + } +#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + int i; + for (i = 0; i < sizeof(local_hostlist_static) / sizeof(struct local_hostlist_entry); i++) { + if(strcmp(local_hostlist_static[i].name, hostname) == 0) { + return local_hostlist_static[i].addr; + } + } +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + return INADDR_NONE; +} + +#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC +/** Remove all entries from the local host-list for a specific hostname + * and/or IP addess + * + * @param hostname hostname for which entries shall be removed from the local + * host-list + * @param addr address for which entries shall be removed from the local host-list + * @return the number of removed entries + */ +int +dns_local_removehost(const char *hostname, const struct ip_addr *addr) +{ + int removed = 0; + struct local_hostlist_entry *entry = local_hostlist_dynamic; + struct local_hostlist_entry *last_entry = NULL; + while (entry != NULL) { + if (((hostname == NULL) || !strcmp(entry->name, hostname)) && + ((addr == NULL) || (entry->addr == addr->addr))) { + struct local_hostlist_entry *free_entry; + if (last_entry != NULL) { + last_entry->next = entry->next; + } else { + local_hostlist_dynamic = entry->next; + } + free_entry = entry; + entry = entry->next; + mem_free(free_entry); + removed++; + } else { + last_entry = entry; + entry = entry->next; + } + } + return removed; +} + +/** + * Add a hostname/IP address pair to the local host-list. + * Duplicates are not checked. + * + * @param hostname hostname of the new entry + * @param addr IP address of the new entry + * @return ERR_OK if succeeded or ERR_MEM on memory error + */ +err_t +dns_local_addhost(const char *hostname, const struct ip_addr *addr) +{ + struct local_hostlist_entry *entry; + entry = mem_malloc(sizeof(struct local_hostlist_entry)); + if (entry == NULL) { + return ERR_MEM; + } + entry->name = hostname; + entry->addr = addr->addr; + entry->next = local_hostlist_dynamic; + local_hostlist_dynamic = entry; + return ERR_OK; +} +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC*/ +#endif /* DNS_LOCAL_HOSTLIST */ + +/** + * Look up a hostname in the array of known hostnames. + * + * @note This function only looks in the internal array of known + * hostnames, it does not send out a query for the hostname if none + * was found. The function dns_enqueue() can be used to send a query + * for a hostname. + * + * @param name the hostname to look up + * @return the hostname's IP address, as u32_t (instead of struct ip_addr to + * better check for failure: != INADDR_NONE) or INADDR_NONE if the hostname + * was not found in the cached dns_table. + */ +static u32_t +dns_lookup(const char *name) +{ + u8_t i; +#if DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN) + u32_t addr; +#endif /* DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN) */ +#if DNS_LOCAL_HOSTLIST + if ((addr = dns_lookup_local(name)) != INADDR_NONE) { + return addr; + } +#endif /* DNS_LOCAL_HOSTLIST */ +#ifdef DNS_LOOKUP_LOCAL_EXTERN + if((addr = DNS_LOOKUP_LOCAL_EXTERN(name)) != INADDR_NONE) { + return addr; + } +#endif /* DNS_LOOKUP_LOCAL_EXTERN */ + + /* Walk through name list, return entry if found. If not, return NULL. */ + for (i = 0; i < DNS_TABLE_SIZE; ++i) { + if ((dns_table[i].state == DNS_STATE_DONE) && + (strcmp(name, dns_table[i].name) == 0)) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_lookup: \"%s\": found = ", name)); + ip_addr_debug_print(DNS_DEBUG, &(dns_table[i].ipaddr)); + LWIP_DEBUGF(DNS_DEBUG, ("\n")); + return dns_table[i].ipaddr.addr; + } + } + + return INADDR_NONE; +} + +#if DNS_DOES_NAME_CHECK +/** + * Compare the "dotted" name "query" with the encoded name "response" + * to make sure an answer from the DNS server matches the current dns_table + * entry (otherwise, answers might arrive late for hostname not on the list + * any more). + * + * @param query hostname (not encoded) from the dns_table + * @param response encoded hostname in the DNS response + * @return 0: names equal; 1: names differ + */ +static u8_t +dns_compare_name(unsigned char *query, unsigned char *response) +{ + unsigned char n; + + do { + n = *response++; + /** @see RFC 1035 - 4.1.4. Message compression */ + if ((n & 0xc0) == 0xc0) { + /* Compressed name */ + break; + } else { + /* Not compressed name */ + while (n > 0) { + if ((*query) != (*response)) { + return 1; + } + ++response; + ++query; + --n; + }; + ++query; + } + } while (*response != 0); + + return 0; +} +#endif /* DNS_DOES_NAME_CHECK */ + +/** + * Walk through a compact encoded DNS name and return the end of the name. + * + * @param query encoded DNS name in the DNS server response + * @return end of the name + */ +static unsigned char * +dns_parse_name(unsigned char *query) +{ + unsigned char n; + + do { + n = *query++; + /** @see RFC 1035 - 4.1.4. Message compression */ + if ((n & 0xc0) == 0xc0) { + /* Compressed name */ + break; + } else { + /* Not compressed name */ + while (n > 0) { + ++query; + --n; + }; + } + } while (*query != 0); + + return query + 1; +} + +/** + * Send a DNS query packet. + * + * @param numdns index of the DNS server in the dns_servers table + * @param name hostname to query + * @param id index of the hostname in dns_table, used as transaction ID in the + * DNS query packet + * @return ERR_OK if packet is sent; an err_t indicating the problem otherwise + */ +static err_t +dns_send(u8_t numdns, const char* name, u8_t id) +{ + err_t err; + struct dns_hdr *hdr; + struct dns_query qry; + struct pbuf *p; + char *query, *nptr; + const char *pHostname; + u8_t n; + + LWIP_DEBUGF(DNS_DEBUG, ("dns_send: dns_servers[%"U16_F"] \"%s\": request\n", + (u16_t)(numdns), name)); + LWIP_ASSERT("dns server out of array", numdns < DNS_MAX_SERVERS); + LWIP_ASSERT("dns server has no IP address set", dns_servers[numdns].addr != 0); + + /* if here, we have either a new query or a retry on a previous query to process */ + p = pbuf_alloc(PBUF_TRANSPORT, SIZEOF_DNS_HDR + DNS_MAX_NAME_LENGTH + + SIZEOF_DNS_QUERY, PBUF_RAM); + if (p != NULL) { + LWIP_ASSERT("pbuf must be in one piece", p->next == NULL); + /* fill dns header */ + hdr = (struct dns_hdr*)p->payload; + memset(hdr, 0, SIZEOF_DNS_HDR); + hdr->id = htons(id); + hdr->flags1 = DNS_FLAG1_RD; + hdr->numquestions = htons(1); + query = (char*)hdr + SIZEOF_DNS_HDR; + pHostname = name; + --pHostname; + + /* convert hostname into suitable query format. */ + do { + ++pHostname; + nptr = query; + ++query; + for(n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) { + *query = *pHostname; + ++query; + ++n; + } + *nptr = n; + } while(*pHostname != 0); + *query++='\0'; + + /* fill dns query */ + qry.type = htons(DNS_RRTYPE_A); + qry.class = htons(DNS_RRCLASS_IN); + MEMCPY( query, &qry, SIZEOF_DNS_QUERY); + + /* resize pbuf to the exact dns query */ + pbuf_realloc(p, (query + SIZEOF_DNS_QUERY) - ((char*)(p->payload))); + + /* connect to the server for faster receiving */ + udp_connect(dns_pcb, &dns_servers[numdns], DNS_SERVER_PORT); + /* send dns packet */ + err = udp_sendto(dns_pcb, p, &dns_servers[numdns], DNS_SERVER_PORT); + + /* free pbuf */ + pbuf_free(p); + } else { + err = ERR_MEM; + } + + return err; +} + +/** + * dns_check_entry() - see if pEntry has not yet been queried and, if so, sends out a query. + * Check an entry in the dns_table: + * - send out query for new entries + * - retry old pending entries on timeout (also with different servers) + * - remove completed entries from the table if their TTL has expired + * + * @param i index of the dns_table entry to check + */ +static void +dns_check_entry(u8_t i) +{ + struct dns_table_entry *pEntry = &dns_table[i]; + + LWIP_ASSERT("array index out of bounds", i < DNS_TABLE_SIZE); + + switch(pEntry->state) { + + case DNS_STATE_NEW: { + /* initialize new entry */ + pEntry->state = DNS_STATE_ASKING; + pEntry->numdns = 0; + pEntry->tmr = 1; + pEntry->retries = 0; + + /* send DNS packet for this entry */ + dns_send(pEntry->numdns, pEntry->name, i); + break; + } + + case DNS_STATE_ASKING: { + if (--pEntry->tmr == 0) { + if (++pEntry->retries == DNS_MAX_RETRIES) { + if ((pEntry->numdns+1numdns+1].addr!=0)) { + /* change of server */ + pEntry->numdns++; + pEntry->tmr = 1; + pEntry->retries = 0; + break; + } else { + LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": timeout\n", pEntry->name)); + /* call specified callback function if provided */ + if (pEntry->found) + (*pEntry->found)(pEntry->name, NULL, pEntry->arg); + /* flush this entry */ + pEntry->state = DNS_STATE_UNUSED; + pEntry->found = NULL; + break; + } + } + + /* wait longer for the next retry */ + pEntry->tmr = pEntry->retries; + + /* send DNS packet for this entry */ + dns_send(pEntry->numdns, pEntry->name, i); + } + break; + } + + case DNS_STATE_DONE: { + /* if the time to live is nul */ + if (--pEntry->ttl == 0) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": flush\n", pEntry->name)); + /* flush this entry */ + pEntry->state = DNS_STATE_UNUSED; + pEntry->found = NULL; + } + break; + } + case DNS_STATE_UNUSED: + /* nothing to do */ + break; + default: + LWIP_ASSERT("unknown dns_table entry state:", 0); + break; + } +} + +/** + * Call dns_check_entry for each entry in dns_table - check all entries. + */ +static void +dns_check_entries(void) +{ + u8_t i; + + for (i = 0; i < DNS_TABLE_SIZE; ++i) { + dns_check_entry(i); + } +} + +/** + * Receive input function for DNS response packets arriving for the dns UDP pcb. + * + * @params see udp.h + */ +static void +dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port) +{ + u8_t i; + char *pHostname; + struct dns_hdr *hdr; + struct dns_answer ans; + struct dns_table_entry *pEntry; + u8_t nquestions, nanswers; +#if (DNS_USES_STATIC_BUF == 0) + u8_t dns_payload[DNS_MSG_SIZE]; +#endif /* (DNS_USES_STATIC_BUF == 0) */ +#if (DNS_USES_STATIC_BUF == 2) + u8_t* dns_payload; +#endif /* (DNS_USES_STATIC_BUF == 2) */ + + LWIP_UNUSED_ARG(arg); + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(addr); + LWIP_UNUSED_ARG(port); + + /* is the dns message too big ? */ + if (p->tot_len > DNS_MSG_SIZE) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too big\n")); + /* free pbuf and return */ + goto memerr1; + } + + /* is the dns message big enough ? */ + if (p->tot_len < (SIZEOF_DNS_HDR + SIZEOF_DNS_QUERY + SIZEOF_DNS_ANSWER)) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too small\n")); + /* free pbuf and return */ + goto memerr1; + } + +#if (DNS_USES_STATIC_BUF == 2) + dns_payload = mem_malloc(p->tot_len); + if (dns_payload == NULL) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: mem_malloc error\n")); + /* free pbuf and return */ + goto memerr1; + } +#endif /* (DNS_USES_STATIC_BUF == 2) */ + + /* copy dns payload inside static buffer for processing */ + if (pbuf_copy_partial(p, dns_payload, p->tot_len, 0) == p->tot_len) { + /* The ID in the DNS header should be our entry into the name table. */ + hdr = (struct dns_hdr*)dns_payload; + i = htons(hdr->id); + if (i < DNS_TABLE_SIZE) { + pEntry = &dns_table[i]; + if(pEntry->state == DNS_STATE_ASKING) { + /* This entry is now completed. */ + pEntry->state = DNS_STATE_DONE; + pEntry->err = hdr->flags2 & DNS_FLAG2_ERR_MASK; + + /* We only care about the question(s) and the answers. The authrr + and the extrarr are simply discarded. */ + nquestions = htons(hdr->numquestions); + nanswers = htons(hdr->numanswers); + + /* Check for error. If so, call callback to inform. */ + if (((hdr->flags1 & DNS_FLAG1_RESPONSE) == 0) || (pEntry->err != 0) || (nquestions != 1)) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in flags\n", pEntry->name)); + /* call callback to indicate error, clean up memory and return */ + goto responseerr; + } + +#if DNS_DOES_NAME_CHECK + /* Check if the name in the "question" part match with the name in the entry. */ + if (dns_compare_name((unsigned char *)(pEntry->name), (unsigned char *)dns_payload + SIZEOF_DNS_HDR) != 0) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", pEntry->name)); + /* call callback to indicate error, clean up memory and return */ + goto responseerr; + } +#endif /* DNS_DOES_NAME_CHECK */ + + /* Skip the name in the "question" part */ + pHostname = (char *) dns_parse_name((unsigned char *)dns_payload + SIZEOF_DNS_HDR) + SIZEOF_DNS_QUERY; + + while(nanswers > 0) { + /* skip answer resource record's host name */ + pHostname = (char *) dns_parse_name((unsigned char *)pHostname); + + /* Check for IP address type and Internet class. Others are discarded. */ + MEMCPY(&ans, pHostname, SIZEOF_DNS_ANSWER); + if((ntohs(ans.type) == DNS_RRTYPE_A) && (ntohs(ans.class) == DNS_RRCLASS_IN) && (ntohs(ans.len) == sizeof(struct ip_addr)) ) { + /* read the answer resource record's TTL, and maximize it if needed */ + pEntry->ttl = ntohl(ans.ttl); + if (pEntry->ttl > DNS_MAX_TTL) { + pEntry->ttl = DNS_MAX_TTL; + } + /* read the IP address after answer resource record's header */ + MEMCPY( &(pEntry->ipaddr), (pHostname+SIZEOF_DNS_ANSWER), sizeof(struct ip_addr)); + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response = ", pEntry->name)); + ip_addr_debug_print(DNS_DEBUG, (&(pEntry->ipaddr))); + LWIP_DEBUGF(DNS_DEBUG, ("\n")); + /* call specified callback function if provided */ + if (pEntry->found) { + (*pEntry->found)(pEntry->name, &pEntry->ipaddr, pEntry->arg); + } + /* deallocate memory and return */ + goto memerr2; + } else { + pHostname = pHostname + SIZEOF_DNS_ANSWER + htons(ans.len); + } + --nanswers; + } + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in response\n", pEntry->name)); + /* call callback to indicate error, clean up memory and return */ + goto responseerr; + } + } + } + + /* deallocate memory and return */ + goto memerr2; + +responseerr: + /* ERROR: call specified callback function with NULL as name to indicate an error */ + if (pEntry->found) { + (*pEntry->found)(pEntry->name, NULL, pEntry->arg); + } + /* flush this entry */ + pEntry->state = DNS_STATE_UNUSED; + pEntry->found = NULL; + +memerr2: +#if (DNS_USES_STATIC_BUF == 2) + /* free dns buffer */ + mem_free(dns_payload); +#endif /* (DNS_USES_STATIC_BUF == 2) */ + +memerr1: + /* free pbuf */ + pbuf_free(p); + return; +} + +/** + * Queues a new hostname to resolve and sends out a DNS query for that hostname + * + * @param name the hostname that is to be queried + * @param found a callback founction to be called on success, failure or timeout + * @param callback_arg argument to pass to the callback function + * @return @return a err_t return code. + */ +static err_t +dns_enqueue(const char *name, dns_found_callback found, void *callback_arg) +{ + u8_t i; + u8_t lseq, lseqi; + struct dns_table_entry *pEntry = NULL; + + /* search an unused entry, or the oldest one */ + lseq = lseqi = 0; + for (i = 0; i < DNS_TABLE_SIZE; ++i) { + pEntry = &dns_table[i]; + /* is it an unused entry ? */ + if (pEntry->state == DNS_STATE_UNUSED) + break; + + /* check if this is the oldest completed entry */ + if (pEntry->state == DNS_STATE_DONE) { + if ((dns_seqno - pEntry->seqno) > lseq) { + lseq = dns_seqno - pEntry->seqno; + lseqi = i; + } + } + } + + /* if we don't have found an unused entry, use the oldest completed one */ + if (i == DNS_TABLE_SIZE) { + if ((lseqi >= DNS_TABLE_SIZE) || (dns_table[lseqi].state != DNS_STATE_DONE)) { + /* no entry can't be used now, table is full */ + LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": DNS entries table is full\n", name)); + return ERR_MEM; + } else { + /* use the oldest completed one */ + i = lseqi; + pEntry = &dns_table[i]; + } + } + + /* use this entry */ + LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": use DNS entry %"U16_F"\n", name, (u16_t)(i))); + + /* fill the entry */ + pEntry->state = DNS_STATE_NEW; + pEntry->seqno = dns_seqno++; + pEntry->found = found; + pEntry->arg = callback_arg; + strcpy(pEntry->name, name); + + /* force to send query without waiting timer */ + dns_check_entry(i); + + /* dns query is enqueued */ + return ERR_INPROGRESS; +} + +/** + * Resolve a hostname (string) into an IP address. + * NON-BLOCKING callback version for use with raw API!!! + * + * Returns immediately with one of err_t return codes: + * - ERR_OK if hostname is a valid IP address string or the host + * name is already in the local names table. + * - ERR_INPROGRESS enqueue a request to be sent to the DNS server + * for resolution if no errors are present. + * + * @param hostname the hostname that is to be queried + * @param addr pointer to a struct ip_addr where to store the address if it is already + * cached in the dns_table (only valid if ERR_OK is returned!) + * @param found a callback function to be called on success, failure or timeout (only if + * ERR_INPROGRESS is returned!) + * @param callback_arg argument to pass to the callback function + * @return a err_t return code. + */ +err_t +dns_gethostbyname(const char *hostname, struct ip_addr *addr, dns_found_callback found, + void *callback_arg) +{ + /* not initialized or no valid server yet, or invalid addr pointer + * or invalid hostname or invalid hostname length */ + if ((dns_pcb == NULL) || (addr == NULL) || + (!hostname) || (!hostname[0]) || + (strlen(hostname) >= DNS_MAX_NAME_LENGTH)) { + return ERR_VAL; + } + +#if LWIP_HAVE_LOOPIF + if (strcmp(hostname,"localhost")==0) { + addr->addr = htonl(INADDR_LOOPBACK); + return ERR_OK; + } +#endif /* LWIP_HAVE_LOOPIF */ + + /* host name already in octet notation? set ip addr and return ERR_OK + * already have this address cached? */ + if (((addr->addr = inet_addr(hostname)) != INADDR_NONE) || + ((addr->addr = dns_lookup(hostname)) != INADDR_NONE)) { + return ERR_OK; + } + + /* queue query with specified callback */ + return dns_enqueue(hostname, found, callback_arg); +} + +#endif /* LWIP_DNS */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/core/init.c b/component/common/network/lwip/lwip_v1.3.2/src/core/init.c new file mode 100644 index 0000000..2a76d4c --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/core/init.c @@ -0,0 +1,274 @@ +/** + * @file + * Modules initialization + * + **/ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/init.h" +#include "lwip/stats.h" +#include "lwip/sys.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/sockets.h" +#include "lwip/ip.h" +#include "lwip/raw.h" +#include "lwip/udp.h" +#include "lwip/tcp.h" +#include "lwip/snmp_msg.h" +#include "lwip/autoip.h" +#include "lwip/igmp.h" +#include "lwip/dns.h" +#include "netif/etharp.h" + +/* Compile-time sanity checks for configuration errors. + * These can be done independently of LWIP_DEBUG, without penalty. + */ +#ifndef BYTE_ORDER + #error "BYTE_ORDER is not defined, you have to define it in your cc.h" +#endif +#if (!IP_SOF_BROADCAST && IP_SOF_BROADCAST_RECV) + #error "If you want to use broadcast filter per pcb on recv operations, you have to define IP_SOF_BROADCAST=1 in your lwipopts.h" +#endif +#if (!LWIP_ARP && ARP_QUEUEING) + #error "If you want to use ARP Queueing, you have to define LWIP_ARP=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_UDPLITE) + #error "If you want to use UDP Lite, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_SNMP) + #error "If you want to use SNMP, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_DHCP) + #error "If you want to use DHCP, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_IGMP) + #error "If you want to use IGMP, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_DNS) + #error "If you want to use DNS, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif +#if (LWIP_ARP && (ARP_TABLE_SIZE > 0x7f)) + #error "If you want to use ARP, ARP_TABLE_SIZE must fit in an s8_t, so, you have to reduce it in your lwipopts.h" +#endif +#if (LWIP_ARP && ARP_QUEUEING && (MEMP_NUM_ARP_QUEUE<=0)) + #error "If you want to use ARP Queueing, you have to define MEMP_NUM_ARP_QUEUE>=1 in your lwipopts.h" +#endif +#if (LWIP_RAW && (MEMP_NUM_RAW_PCB<=0)) + #error "If you want to use RAW, you have to define MEMP_NUM_RAW_PCB>=1 in your lwipopts.h" +#endif +#if (LWIP_UDP && (MEMP_NUM_UDP_PCB<=0)) + #error "If you want to use UDP, you have to define MEMP_NUM_UDP_PCB>=1 in your lwipopts.h" +#endif +#if (LWIP_TCP && (MEMP_NUM_TCP_PCB<=0)) + #error "If you want to use TCP, you have to define MEMP_NUM_TCP_PCB>=1 in your lwipopts.h" +#endif +#if (LWIP_TCP && (TCP_WND > 0xffff)) + #error "If you want to use TCP, TCP_WND must fit in an u16_t, so, you have to reduce it in your lwipopts.h" +#endif +#if (LWIP_TCP && (TCP_SND_QUEUELEN > 0xffff)) + #error "If you want to use TCP, TCP_SND_QUEUELEN must fit in an u16_t, so, you have to reduce it in your lwipopts.h" +#endif +#if (LWIP_TCP && ((TCP_MAXRTX > 12) || (TCP_SYNMAXRTX > 12))) + #error "If you want to use TCP, TCP_MAXRTX and TCP_SYNMAXRTX must less or equal to 12 (due to tcp_backoff table), so, you have to reduce them in your lwipopts.h" +#endif +#if (LWIP_TCP && TCP_LISTEN_BACKLOG && (TCP_DEFAULT_LISTEN_BACKLOG < 0) || (TCP_DEFAULT_LISTEN_BACKLOG > 0xff)) + #error "If you want to use TCP backlog, TCP_DEFAULT_LISTEN_BACKLOG must fit into an u8_t" +#endif +#if (LWIP_IGMP && (MEMP_NUM_IGMP_GROUP<=1)) + #error "If you want to use IGMP, you have to define MEMP_NUM_IGMP_GROUP>1 in your lwipopts.h" +#endif +#if (PPP_SUPPORT && (NO_SYS==1)) + #error "If you want to use PPP, you have to define NO_SYS=0 in your lwipopts.h" +#endif +#if (LWIP_NETIF_API && (NO_SYS==1)) + #error "If you want to use NETIF API, you have to define NO_SYS=0 in your lwipopts.h" +#endif +#if ((LWIP_SOCKET || LWIP_NETCONN) && (NO_SYS==1)) + #error "If you want to use Sequential API, you have to define NO_SYS=0 in your lwipopts.h" +#endif +#if ((LWIP_NETCONN || LWIP_SOCKET) && (MEMP_NUM_TCPIP_MSG_API<=0)) + #error "If you want to use Sequential API, you have to define MEMP_NUM_TCPIP_MSG_API>=1 in your lwipopts.h" +#endif +#if (!LWIP_NETCONN && LWIP_SOCKET) + #error "If you want to use Socket API, you have to define LWIP_NETCONN=1 in your lwipopts.h" +#endif +#if (((!LWIP_DHCP) || (!LWIP_AUTOIP)) && LWIP_DHCP_AUTOIP_COOP) + #error "If you want to use DHCP/AUTOIP cooperation mode, you have to define LWIP_DHCP=1 and LWIP_AUTOIP=1 in your lwipopts.h" +#endif +#if (((!LWIP_DHCP) || (!LWIP_ARP)) && DHCP_DOES_ARP_CHECK) + #error "If you want to use DHCP ARP checking, you have to define LWIP_DHCP=1 and LWIP_ARP=1 in your lwipopts.h" +#endif +#if (!LWIP_ARP && LWIP_AUTOIP) + #error "If you want to use AUTOIP, you have to define LWIP_ARP=1 in your lwipopts.h" +#endif +#if (LWIP_SNMP && (SNMP_CONCURRENT_REQUESTS<=0)) + #error "If you want to use SNMP, you have to define SNMP_CONCURRENT_REQUESTS>=1 in your lwipopts.h" +#endif +#if (LWIP_SNMP && (SNMP_TRAP_DESTINATIONS<=0)) + #error "If you want to use SNMP, you have to define SNMP_TRAP_DESTINATIONS>=1 in your lwipopts.h" +#endif +#if (LWIP_TCP && ((LWIP_EVENT_API && LWIP_CALLBACK_API) || (!LWIP_EVENT_API && !LWIP_CALLBACK_API))) + #error "One and exactly one of LWIP_EVENT_API and LWIP_CALLBACK_API has to be enabled in your lwipopts.h" +#endif +/* There must be sufficient timeouts, taking into account requirements of the subsystems. */ +#if ((NO_SYS==0) && (MEMP_NUM_SYS_TIMEOUT < (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + PPP_SUPPORT))) + #error "MEMP_NUM_SYS_TIMEOUT is too low to accomodate all required timeouts" +#endif +#if (IP_REASSEMBLY && (MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS)) + #error "MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS doesn't make sense since each struct ip_reassdata must hold 2 pbufs at least!" +#endif +#if (MEM_LIBC_MALLOC && MEM_USE_POOLS) + #error "MEM_LIBC_MALLOC and MEM_USE_POOLS may not both be simultaneously enabled in your lwipopts.h" +#endif +#if (MEM_USE_POOLS && !MEMP_USE_CUSTOM_POOLS) + #error "MEM_USE_POOLS requires custom pools (MEMP_USE_CUSTOM_POOLS) to be enabled in your lwipopts.h" +#endif +#if (PBUF_POOL_BUFSIZE <= MEM_ALIGNMENT) + #error "PBUF_POOL_BUFSIZE must be greater than MEM_ALIGNMENT or the offset may take the full first pbuf" +#endif +#if (TCP_QUEUE_OOSEQ && !LWIP_TCP) + #error "TCP_QUEUE_OOSEQ requires LWIP_TCP" +#endif +#if (DNS_LOCAL_HOSTLIST && !DNS_LOCAL_HOSTLIST_IS_DYNAMIC && !(defined(DNS_LOCAL_HOSTLIST_INIT))) + #error "you have to define define DNS_LOCAL_HOSTLIST_INIT {{'host1', 0x123}, {'host2', 0x234}} to initialize DNS_LOCAL_HOSTLIST" +#endif +#if PPP_SUPPORT && !PPPOS_SUPPORT & !PPPOE_SUPPORT + #error "PPP_SUPPORT needs either PPPOS_SUPPORT or PPPOE_SUPPORT turned on" +#endif + + +/* Compile-time checks for deprecated options. + */ +#ifdef MEMP_NUM_TCPIP_MSG + #error "MEMP_NUM_TCPIP_MSG option is deprecated. Remove it from your lwipopts.h." +#endif +#ifdef MEMP_NUM_API_MSG + #error "MEMP_NUM_API_MSG option is deprecated. Remove it from your lwipopts.h." +#endif +#ifdef TCP_REXMIT_DEBUG + #error "TCP_REXMIT_DEBUG option is deprecated. Remove it from your lwipopts.h." +#endif +#ifdef RAW_STATS + #error "RAW_STATS option is deprecated. Remove it from your lwipopts.h." +#endif +#ifdef ETHARP_QUEUE_FIRST + #error "ETHARP_QUEUE_FIRST option is deprecated. Remove it from your lwipopts.h." +#endif +#ifdef ETHARP_ALWAYS_INSERT + #error "ETHARP_ALWAYS_INSERT option is deprecated. Remove it from your lwipopts.h." +#endif +#if SO_REUSE +/* I removed the lot since this was an ugly hack. It broke the raw-API. + It also came with many ugly goto's, Christiaan Simons. */ + #error "SO_REUSE currently unavailable, this was a hack" +#endif + +#ifdef LWIP_DEBUG +static void +lwip_sanity_check(void) +{ + /* Warnings */ +#if LWIP_NETCONN + if (MEMP_NUM_NETCONN > (MEMP_NUM_TCP_PCB+MEMP_NUM_TCP_PCB_LISTEN+MEMP_NUM_UDP_PCB+MEMP_NUM_RAW_PCB)) + LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: MEMP_NUM_NETCONN should be less than the sum of MEMP_NUM_{TCP,RAW,UDP}_PCB+MEMP_NUM_TCP_PCB_LISTEN\n")); +#endif /* LWIP_NETCONN */ +#if LWIP_TCP + if (MEMP_NUM_TCP_SEG < TCP_SND_QUEUELEN) + LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: MEMP_NUM_TCP_SEG should be at least as big as TCP_SND_QUEUELEN\n")); + if (TCP_SND_BUF < 2 * TCP_MSS) + LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: TCP_SND_BUF must be at least as much as (2 * TCP_MSS) for things to work smoothly\n")); + if (TCP_SND_QUEUELEN < (2 * (TCP_SND_BUF/TCP_MSS))) + LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: TCP_SND_QUEUELEN must be at least as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work\n")); + if (TCP_SNDLOWAT > TCP_SND_BUF) + LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: TCP_SNDLOWAT must be less than or equal to TCP_SND_BUF.\n")); + if (TCP_WND > (PBUF_POOL_SIZE*PBUF_POOL_BUFSIZE)) + LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: TCP_WND is larger than space provided by PBUF_POOL_SIZE*PBUF_POOL_BUFSIZE\n")); + if (TCP_WND < TCP_MSS) + LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: TCP_WND is smaller than MSS\n")); +#endif /* LWIP_TCP */ +} +#else /* LWIP_DEBUG */ +#define lwip_sanity_check() +#endif /* LWIP_DEBUG */ + +/** + * Perform Sanity check of user-configurable values, and initialize all modules. + */ +void +lwip_init(void) +{ + /* Sanity check user-configurable values */ + lwip_sanity_check(); + + /* Modules initialization */ + stats_init(); + sys_init(); + mem_init(); + memp_init(); + pbuf_init(); + netif_init(); +#if LWIP_SOCKET + lwip_socket_init(); +#endif /* LWIP_SOCKET */ + ip_init(); +#if LWIP_ARP + etharp_init(); +#endif /* LWIP_ARP */ +#if LWIP_RAW + raw_init(); +#endif /* LWIP_RAW */ +#if LWIP_UDP + udp_init(); +#endif /* LWIP_UDP */ +#if LWIP_TCP + tcp_init(); +#endif /* LWIP_TCP */ +#if LWIP_SNMP + snmp_init(); +#endif /* LWIP_SNMP */ +#if LWIP_AUTOIP + autoip_init(); +#endif /* LWIP_AUTOIP */ +#if LWIP_IGMP + igmp_init(); +#endif /* LWIP_IGMP */ +#if LWIP_DNS + dns_init(); +#endif /* LWIP_DNS */ +} diff --git a/component/common/network/lwip/lwip_v1.3.2/src/core/ipv4/autoip.c b/component/common/network/lwip/lwip_v1.3.2/src/core/ipv4/autoip.c new file mode 100644 index 0000000..ff89e44 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/core/ipv4/autoip.c @@ -0,0 +1,497 @@ +/* + * @file + * AutoIP Automatic LinkLocal IP Configuration + * + */ + +/* + * + * Copyright (c) 2007 Dominik Spies + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * Author: Dominik Spies + * + * This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform + * with RFC 3927. + * + * + * Please coordinate changes and requests with Dominik Spies + * + */ + +/******************************************************************************* + * USAGE: + * + * define LWIP_AUTOIP 1 in your lwipopts.h + * + * If you don't use tcpip.c (so, don't call, you don't call tcpip_init): + * - First, call autoip_init(). + * - call autoip_tmr() all AUTOIP_TMR_INTERVAL msces, + * that should be defined in autoip.h. + * I recommend a value of 100. The value must divide 1000 with a remainder almost 0. + * Possible values are 1000, 500, 333, 250, 200, 166, 142, 125, 111, 100 .... + * + * Without DHCP: + * - Call autoip_start() after netif_add(). + * + * With DHCP: + * - define LWIP_DHCP_AUTOIP_COOP 1 in your lwipopts.h. + * - Configure your DHCP Client. + * + */ + +#include "lwip/opt.h" + +#if LWIP_AUTOIP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/mem.h" +#include "lwip/udp.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/autoip.h" +#include "netif/etharp.h" + +#include +#include + +/* 169.254.0.0 */ +#define AUTOIP_NET 0xA9FE0000 +/* 169.254.1.0 */ +#define AUTOIP_RANGE_START (AUTOIP_NET | 0x0100) +/* 169.254.254.255 */ +#define AUTOIP_RANGE_END (AUTOIP_NET | 0xFEFF) + + +/** Pseudo random macro based on netif informations. + * You could use "rand()" from the C Library if you define LWIP_AUTOIP_RAND in lwipopts.h */ +#ifndef LWIP_AUTOIP_RAND +#define LWIP_AUTOIP_RAND(netif) ( (((u32_t)((netif->hwaddr[5]) & 0xff) << 24) | \ + ((u32_t)((netif->hwaddr[3]) & 0xff) << 16) | \ + ((u32_t)((netif->hwaddr[2]) & 0xff) << 8) | \ + ((u32_t)((netif->hwaddr[4]) & 0xff))) + \ + (netif->autoip?netif->autoip->tried_llipaddr:0)) +#endif /* LWIP_AUTOIP_RAND */ + +/** + * Macro that generates the initial IP address to be tried by AUTOIP. + * If you want to override this, define it to something else in lwipopts.h. + */ +#ifndef LWIP_AUTOIP_CREATE_SEED_ADDR +#define LWIP_AUTOIP_CREATE_SEED_ADDR(netif) \ + htonl(AUTOIP_RANGE_START + ((u32_t)(((u8_t)(netif->hwaddr[4])) | \ + ((u32_t)((u8_t)(netif->hwaddr[5]))) << 8))) +#endif /* LWIP_AUTOIP_CREATE_SEED_ADDR */ + +/* static functions */ +static void autoip_handle_arp_conflict(struct netif *netif); + +/* creates a pseudo random LL IP-Address for a network interface */ +static void autoip_create_addr(struct netif *netif, struct ip_addr *ipaddr); + +/* sends an ARP probe */ +static err_t autoip_arp_probe(struct netif *netif); + +/* sends an ARP announce */ +static err_t autoip_arp_announce(struct netif *netif); + +/* configure interface for use with current LL IP-Address */ +static err_t autoip_bind(struct netif *netif); + +/* start sending probes for llipaddr */ +static void autoip_start_probing(struct netif *netif); + +/** + * Initialize this module + */ +void +autoip_init(void) +{ + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_init()\n")); +} + +/** + * Handle a IP address conflict after an ARP conflict detection + */ +static void +autoip_handle_arp_conflict(struct netif *netif) +{ + /* Somehow detect if we are defending or retreating */ + unsigned char defend = 1; /* tbd */ + + if(defend) { + if(netif->autoip->lastconflict > 0) { + /* retreat, there was a conflicting ARP in the last + * DEFEND_INTERVAL seconds + */ + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_handle_arp_conflict(): we are defending, but in DEFEND_INTERVAL, retreating\n")); + + /* TODO: close all TCP sessions */ + autoip_start(netif); + } else { + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_handle_arp_conflict(): we are defend, send ARP Announce\n")); + autoip_arp_announce(netif); + netif->autoip->lastconflict = DEFEND_INTERVAL * AUTOIP_TICKS_PER_SECOND; + } + } else { + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_handle_arp_conflict(): we do not defend, retreating\n")); + /* TODO: close all TCP sessions */ + autoip_start(netif); + } +} + +/** + * Create an IP-Address out of range 169.254.1.0 to 169.254.254.255 + * + * @param netif network interface on which create the IP-Address + * @param ipaddr ip address to initialize + */ +static void +autoip_create_addr(struct netif *netif, struct ip_addr *ipaddr) +{ + /* Here we create an IP-Address out of range 169.254.1.0 to 169.254.254.255 + * compliant to RFC 3927 Section 2.1 + * We have 254 * 256 possibilities */ + + u32_t addr = ntohl(LWIP_AUTOIP_CREATE_SEED_ADDR(netif)); + addr += netif->autoip->tried_llipaddr; + addr = AUTOIP_NET | (addr & 0xffff); + /* Now, 169.254.0.0 <= addr <= 169.254.255.255 */ + + if (addr < AUTOIP_RANGE_START) { + addr += AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1; + } + if (addr > AUTOIP_RANGE_END) { + addr -= AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1; + } + LWIP_ASSERT("AUTOIP address not in range", (addr >= AUTOIP_RANGE_START) && + (addr <= AUTOIP_RANGE_END)); + ipaddr->addr = htonl(addr); + + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_create_addr(): tried_llipaddr=%"U16_F", 0x%08"X32_F"\n", + (u16_t)(netif->autoip->tried_llipaddr), (u32_t)(ipaddr->addr))); +} + +/** + * Sends an ARP probe from a network interface + * + * @param netif network interface used to send the probe + */ +static err_t +autoip_arp_probe(struct netif *netif) +{ + return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, ðbroadcast, + (struct eth_addr *)netif->hwaddr, IP_ADDR_ANY, ðzero, + &netif->autoip->llipaddr, ARP_REQUEST); +} + +/** + * Sends an ARP announce from a network interface + * + * @param netif network interface used to send the announce + */ +static err_t +autoip_arp_announce(struct netif *netif) +{ + return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, ðbroadcast, + (struct eth_addr *)netif->hwaddr, &netif->autoip->llipaddr, ðzero, + &netif->autoip->llipaddr, ARP_REQUEST); +} + +/** + * Configure interface for use with current LL IP-Address + * + * @param netif network interface to configure with current LL IP-Address + */ +static err_t +autoip_bind(struct netif *netif) +{ + struct autoip *autoip = netif->autoip; + struct ip_addr sn_mask, gw_addr; + + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, + ("autoip_bind(netif=%p) %c%c%"U16_F" 0x%08"X32_F"\n", + (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num, autoip->llipaddr.addr)); + + IP4_ADDR(&sn_mask, 255, 255, 0, 0); + IP4_ADDR(&gw_addr, 0, 0, 0, 0); + + netif_set_ipaddr(netif, &autoip->llipaddr); + netif_set_netmask(netif, &sn_mask); + netif_set_gw(netif, &gw_addr); + + /* bring the interface up */ + netif_set_up(netif); + + return ERR_OK; +} + +/** + * Start AutoIP client + * + * @param netif network interface on which start the AutoIP client + */ +err_t +autoip_start(struct netif *netif) +{ + struct autoip *autoip = netif->autoip; + err_t result = ERR_OK; + + if(netif_is_up(netif)) { + netif_set_down(netif); + } + + /* Set IP-Address, Netmask and Gateway to 0 to make sure that + * ARP Packets are formed correctly + */ + netif->ip_addr.addr = 0; + netif->netmask.addr = 0; + netif->gw.addr = 0; + + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], + netif->name[1], (u16_t)netif->num)); + if(autoip == NULL) { + /* no AutoIP client attached yet? */ + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, + ("autoip_start(): starting new AUTOIP client\n")); + autoip = mem_malloc(sizeof(struct autoip)); + if(autoip == NULL) { + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, + ("autoip_start(): could not allocate autoip\n")); + return ERR_MEM; + } + memset( autoip, 0, sizeof(struct autoip)); + /* store this AutoIP client in the netif */ + netif->autoip = autoip; + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_start(): allocated autoip")); + } else { + autoip->state = AUTOIP_STATE_OFF; + autoip->ttw = 0; + autoip->sent_num = 0; + memset(&autoip->llipaddr, 0, sizeof(struct ip_addr)); + autoip->lastconflict = 0; + } + + autoip_create_addr(netif, &(autoip->llipaddr)); + autoip->tried_llipaddr++; + autoip_start_probing(netif); + + return result; +} + +static void +autoip_start_probing(struct netif *netif) +{ + struct autoip *autoip = netif->autoip; + + autoip->state = AUTOIP_STATE_PROBING; + autoip->sent_num = 0; + + /* time to wait to first probe, this is randomly + * choosen out of 0 to PROBE_WAIT seconds. + * compliant to RFC 3927 Section 2.2.1 + */ + autoip->ttw = (u16_t)(LWIP_AUTOIP_RAND(netif) % (PROBE_WAIT * AUTOIP_TICKS_PER_SECOND)); + + /* + * if we tried more then MAX_CONFLICTS we must limit our rate for + * accquiring and probing address + * compliant to RFC 3927 Section 2.2.1 + */ + if(autoip->tried_llipaddr > MAX_CONFLICTS) { + autoip->ttw = RATE_LIMIT_INTERVAL * AUTOIP_TICKS_PER_SECOND; + } +} + +/** + * Handle a possible change in the network configuration. + * + * If there is an AutoIP address configured, take the interface down + * and begin probing with the same address. + */ +void +autoip_network_changed(struct netif *netif) +{ + if (netif->autoip && netif->autoip->state != AUTOIP_STATE_OFF) { + netif_set_down(netif); + autoip_start_probing(netif); + } +} + +/** + * Stop AutoIP client + * + * @param netif network interface on which stop the AutoIP client + */ +err_t +autoip_stop(struct netif *netif) +{ + netif->autoip->state = AUTOIP_STATE_OFF; + netif_set_down(netif); + return ERR_OK; +} + +/** + * Has to be called in loop every AUTOIP_TMR_INTERVAL milliseconds + */ +void +autoip_tmr() +{ + struct netif *netif = netif_list; + /* loop through netif's */ + while (netif != NULL) { + /* only act on AutoIP configured interfaces */ + if (netif->autoip != NULL) { + if(netif->autoip->lastconflict > 0) { + netif->autoip->lastconflict--; + } + + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, + ("autoip_tmr() AutoIP-State: %"U16_F", ttw=%"U16_F"\n", + (u16_t)(netif->autoip->state), netif->autoip->ttw)); + + switch(netif->autoip->state) { + case AUTOIP_STATE_PROBING: + if(netif->autoip->ttw > 0) { + netif->autoip->ttw--; + } else { + if(netif->autoip->sent_num >= PROBE_NUM) { + netif->autoip->state = AUTOIP_STATE_ANNOUNCING; + netif->autoip->sent_num = 0; + netif->autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND; + } else { + autoip_arp_probe(netif); + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, + ("autoip_tmr() PROBING Sent Probe\n")); + netif->autoip->sent_num++; + /* calculate time to wait to next probe */ + netif->autoip->ttw = (u16_t)((LWIP_AUTOIP_RAND(netif) % + ((PROBE_MAX - PROBE_MIN) * AUTOIP_TICKS_PER_SECOND) ) + + PROBE_MIN * AUTOIP_TICKS_PER_SECOND); + } + } + break; + + case AUTOIP_STATE_ANNOUNCING: + if(netif->autoip->ttw > 0) { + netif->autoip->ttw--; + } else { + if(netif->autoip->sent_num == 0) { + /* We are here the first time, so we waited ANNOUNCE_WAIT seconds + * Now we can bind to an IP address and use it. + * + * autoip_bind calls netif_set_up. This triggers a gratuitous ARP + * which counts as an announcement. + */ + autoip_bind(netif); + } else { + autoip_arp_announce(netif); + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, + ("autoip_tmr() ANNOUNCING Sent Announce\n")); + } + netif->autoip->ttw = ANNOUNCE_INTERVAL * AUTOIP_TICKS_PER_SECOND; + netif->autoip->sent_num++; + + if(netif->autoip->sent_num >= ANNOUNCE_NUM) { + netif->autoip->state = AUTOIP_STATE_BOUND; + netif->autoip->sent_num = 0; + netif->autoip->ttw = 0; + } + } + break; + } + } + /* proceed to next network interface */ + netif = netif->next; + } +} + +/** + * Handles every incoming ARP Packet, called by etharp_arp_input. + * + * @param netif network interface to use for autoip processing + * @param hdr Incoming ARP packet + */ +void +autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr) +{ + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_arp_reply()\n")); + if ((netif->autoip != NULL) && (netif->autoip->state != AUTOIP_STATE_OFF)) { + /* when ip.src == llipaddr && hw.src != netif->hwaddr + * + * when probing ip.dst == llipaddr && hw.src != netif->hwaddr + * we have a conflict and must solve it + */ + struct ip_addr sipaddr, dipaddr; + struct eth_addr netifaddr; + netifaddr.addr[0] = netif->hwaddr[0]; + netifaddr.addr[1] = netif->hwaddr[1]; + netifaddr.addr[2] = netif->hwaddr[2]; + netifaddr.addr[3] = netif->hwaddr[3]; + netifaddr.addr[4] = netif->hwaddr[4]; + netifaddr.addr[5] = netif->hwaddr[5]; + + /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without + * structure packing (not using structure copy which breaks strict-aliasing rules). + */ + SMEMCPY(&sipaddr, &hdr->sipaddr, sizeof(sipaddr)); + SMEMCPY(&dipaddr, &hdr->dipaddr, sizeof(dipaddr)); + + if ((netif->autoip->state == AUTOIP_STATE_PROBING) || + ((netif->autoip->state == AUTOIP_STATE_ANNOUNCING) && + (netif->autoip->sent_num == 0))) { + /* RFC 3927 Section 2.2.1: + * from beginning to after ANNOUNCE_WAIT + * seconds we have a conflict if + * ip.src == llipaddr OR + * ip.dst == llipaddr && hw.src != own hwaddr + */ + if ((ip_addr_cmp(&sipaddr, &netif->autoip->llipaddr)) || + (ip_addr_cmp(&dipaddr, &netif->autoip->llipaddr) && + !eth_addr_cmp(&netifaddr, &hdr->shwaddr))) { + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING, + ("autoip_arp_reply(): Probe Conflict detected\n")); + autoip_start(netif); + } + } else { + /* RFC 3927 Section 2.5: + * in any state we have a conflict if + * ip.src == llipaddr && hw.src != own hwaddr + */ + if (ip_addr_cmp(&sipaddr, &netif->autoip->llipaddr) && + !eth_addr_cmp(&netifaddr, &hdr->shwaddr)) { + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING, + ("autoip_arp_reply(): Conflicting ARP-Packet detected\n")); + autoip_handle_arp_conflict(netif); + } + } + } +} + +#endif /* LWIP_AUTOIP */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/core/ipv4/icmp.c b/component/common/network/lwip/lwip_v1.3.2/src/core/ipv4/icmp.c new file mode 100644 index 0000000..7b0a02e --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/core/ipv4/icmp.c @@ -0,0 +1,340 @@ +/** + * @file + * ICMP - Internet Control Message Protocol + * + **/ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/* Some ICMP messages should be passed to the transport protocols. This + is not implemented. */ + +#include "lwip/opt.h" + +#if LWIP_ICMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/icmp.h" +#include "lwip/inet.h" +#include "lwip/inet_chksum.h" +#include "lwip/ip.h" +#include "lwip/def.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" + +#include + +/** Small optimization: set to 0 if incoming PBUF_POOL pbuf always can be + * used to modify and send a response packet (and to 1 if this is not the case, + * e.g. when link header is stripped of when receiving) */ +#ifndef LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN +#define LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN 1 +#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */ + +/* The amount of data from the original packet to return in a dest-unreachable */ +#define ICMP_DEST_UNREACH_DATASIZE 8 + +static void icmp_send_response(struct pbuf *p, u8_t type, u8_t code); + +/** + * Processes ICMP input packets, called from ip_input(). + * + * Currently only processes icmp echo requests and sends + * out the echo response. + * + * @param p the icmp echo request packet, p->payload pointing to the ip header + * @param inp the netif on which this packet was received + */ +void +icmp_input(struct pbuf *p, struct netif *inp) +{ + u8_t type; +#ifdef LWIP_DEBUG + u8_t code; +#endif /* LWIP_DEBUG */ + struct icmp_echo_hdr *iecho; + struct ip_hdr *iphdr; + struct ip_addr tmpaddr; + s16_t hlen; + + ICMP_STATS_INC(icmp.recv); + snmp_inc_icmpinmsgs(); + + + iphdr = p->payload; + hlen = IPH_HL(iphdr) * 4; + if (pbuf_header(p, -hlen) || (p->tot_len < sizeof(u16_t)*2)) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%"U16_F" bytes) received\n", p->tot_len)); + goto lenerr; + } + + type = *((u8_t *)p->payload); +#ifdef LWIP_DEBUG + code = *(((u8_t *)p->payload)+1); +#endif /* LWIP_DEBUG */ + switch (type) { + case ICMP_ECHO: +#if !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING + { + int accepted = 1; +#if !LWIP_MULTICAST_PING + /* multicast destination address? */ + if (ip_addr_ismulticast(&iphdr->dest)) { + accepted = 0; + } +#endif /* LWIP_MULTICAST_PING */ +#if !LWIP_BROADCAST_PING + /* broadcast destination address? */ + if (ip_addr_isbroadcast(&iphdr->dest, inp)) { + accepted = 0; + } +#endif /* LWIP_BROADCAST_PING */ + /* broadcast or multicast destination address not acceptd? */ + if (!accepted) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to multicast or broadcast pings\n")); + ICMP_STATS_INC(icmp.err); + pbuf_free(p); + return; + } + } +#endif /* !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING */ + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ping\n")); + if (p->tot_len < sizeof(struct icmp_echo_hdr)) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n")); + goto lenerr; + } + if (inet_chksum_pbuf(p) != 0) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo\n")); + pbuf_free(p); + ICMP_STATS_INC(icmp.chkerr); + snmp_inc_icmpinerrors(); + return; + } +#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN + if (pbuf_header(p, (PBUF_IP_HLEN + PBUF_LINK_HLEN))) { + /* p is not big enough to contain link headers + * allocate a new one and copy p into it + */ + struct pbuf *r; + /* switch p->payload to ip header */ + if (pbuf_header(p, hlen)) { + LWIP_ASSERT("icmp_input: moving p->payload to ip header failed\n", 0); + goto memerr; + } + /* allocate new packet buffer with space for link headers */ + r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM); + if (r == NULL) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: allocating new pbuf failed\n")); + goto memerr; + } + LWIP_ASSERT("check that first pbuf can hold struct the ICMP header", + (r->len >= hlen + sizeof(struct icmp_echo_hdr))); + /* copy the whole packet including ip header */ + if (pbuf_copy(r, p) != ERR_OK) { + LWIP_ASSERT("icmp_input: copying to new pbuf failed\n", 0); + goto memerr; + } + iphdr = r->payload; + /* switch r->payload back to icmp header */ + if (pbuf_header(r, -hlen)) { + LWIP_ASSERT("icmp_input: restoring original p->payload failed\n", 0); + goto memerr; + } + /* free the original p */ + pbuf_free(p); + /* we now have an identical copy of p that has room for link headers */ + p = r; + } else { + /* restore p->payload to point to icmp header */ + if (pbuf_header(p, -(s16_t)(PBUF_IP_HLEN + PBUF_LINK_HLEN))) { + LWIP_ASSERT("icmp_input: restoring original p->payload failed\n", 0); + goto memerr; + } + } +#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */ + /* At this point, all checks are OK. */ + /* We generate an answer by switching the dest and src ip addresses, + * setting the icmp type to ECHO_RESPONSE and updating the checksum. */ + iecho = p->payload; + tmpaddr.addr = iphdr->src.addr; + iphdr->src.addr = iphdr->dest.addr; + iphdr->dest.addr = tmpaddr.addr; + ICMPH_TYPE_SET(iecho, ICMP_ER); + + +/* This part of code has been modified by ST's MCD Application Team */ +/* To use the Checksum Offload Engine for the putgoing ICMP packets, + the ICMP checksum field should be set to 0, this is required only for Tx ICMP*/ +#ifdef CHECKSUM_BY_HARDWARE + iecho->chksum = 0; +#else + /* adjust the checksum */ + if (iecho->chksum >= htons(0xffff - (ICMP_ECHO << 8))) { + iecho->chksum += htons(ICMP_ECHO << 8) + 1; + } else { + iecho->chksum += htons(ICMP_ECHO << 8); + } +#endif + + /* Set the correct TTL and recalculate the header checksum. */ + IPH_TTL_SET(iphdr, ICMP_TTL); + IPH_CHKSUM_SET(iphdr, 0); +#if CHECKSUM_GEN_IP + IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN)); +#endif /* CHECKSUM_GEN_IP */ + + ICMP_STATS_INC(icmp.xmit); + /* increase number of messages attempted to send */ + snmp_inc_icmpoutmsgs(); + /* increase number of echo replies attempted to send */ + snmp_inc_icmpoutechoreps(); + + if(pbuf_header(p, hlen)) { + LWIP_ASSERT("Can't move over header in packet", 0); + } else { + err_t ret; + ret = ip_output_if(p, &(iphdr->src), IP_HDRINCL, + ICMP_TTL, 0, IP_PROTO_ICMP, inp); + if (ret != ERR_OK) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ip_output_if returned an error: %c.\n", ret)); + } + } + break; + default: + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %"S16_F" code %"S16_F" not supported.\n", + (s16_t)type, (s16_t)code)); + ICMP_STATS_INC(icmp.proterr); + ICMP_STATS_INC(icmp.drop); + } + pbuf_free(p); + return; +lenerr: + pbuf_free(p); + ICMP_STATS_INC(icmp.lenerr); + snmp_inc_icmpinerrors(); + return; +#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN +memerr: + pbuf_free(p); + ICMP_STATS_INC(icmp.err); + snmp_inc_icmpinerrors(); + return; +#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */ +} + +/** + * Send an icmp 'destination unreachable' packet, called from ip_input() if + * the transport layer protocol is unknown and from udp_input() if the local + * port is not bound. + * + * @param p the input packet for which the 'unreachable' should be sent, + * p->payload pointing to the IP header + * @param t type of the 'unreachable' packet + */ +void +icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t) +{ + icmp_send_response(p, ICMP_DUR, t); +} + +#if IP_FORWARD || IP_REASSEMBLY +/** + * Send a 'time exceeded' packet, called from ip_forward() if TTL is 0. + * + * @param p the input packet for which the 'time exceeded' should be sent, + * p->payload pointing to the IP header + * @param t type of the 'time exceeded' packet + */ +void +icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t) +{ + icmp_send_response(p, ICMP_TE, t); +} + +#endif /* IP_FORWARD || IP_REASSEMBLY */ + +/** + * Send an icmp packet in response to an incoming packet. + * + * @param p the input packet for which the 'unreachable' should be sent, + * p->payload pointing to the IP header + * @param type Type of the ICMP header + * @param code Code of the ICMP header + */ +static void +icmp_send_response(struct pbuf *p, u8_t type, u8_t code) +{ + struct pbuf *q; + struct ip_hdr *iphdr; + /* we can use the echo header here */ + struct icmp_echo_hdr *icmphdr; + + /* ICMP header + IP header + 8 bytes of data */ + q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE, + PBUF_RAM); + if (q == NULL) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMP packet.\n")); + return; + } + LWIP_ASSERT("check that first pbuf can hold icmp message", + (q->len >= (sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE))); + + iphdr = p->payload; + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from ")); + ip_addr_debug_print(ICMP_DEBUG, &(iphdr->src)); + LWIP_DEBUGF(ICMP_DEBUG, (" to ")); + ip_addr_debug_print(ICMP_DEBUG, &(iphdr->dest)); + LWIP_DEBUGF(ICMP_DEBUG, ("\n")); + + icmphdr = q->payload; + icmphdr->type = type; + icmphdr->code = code; + icmphdr->id = 0; + icmphdr->seqno = 0; + + /* copy fields from original packet */ + SMEMCPY((u8_t *)q->payload + sizeof(struct icmp_echo_hdr), (u8_t *)p->payload, + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE); + + /* calculate checksum */ + icmphdr->chksum = 0; + icmphdr->chksum = inet_chksum(icmphdr, q->len); + ICMP_STATS_INC(icmp.xmit); + /* increase number of messages attempted to send */ + snmp_inc_icmpoutmsgs(); + /* increase number of destination unreachable messages attempted to send */ + snmp_inc_icmpouttimeexcds(); + ip_output(q, NULL, &(iphdr->src), ICMP_TTL, 0, IP_PROTO_ICMP); + pbuf_free(q); +} + +#endif /* LWIP_ICMP */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/core/ipv4/igmp.c b/component/common/network/lwip/lwip_v1.3.2/src/core/ipv4/igmp.c new file mode 100644 index 0000000..b89a06b --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/core/ipv4/igmp.c @@ -0,0 +1,757 @@ +/** + * @file + * IGMP - Internet Group Management Protocol + * + **/ + +/* + * Copyright (c) 2002 CITEL Technologies Ltd. + * 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 CITEL Technologies Ltd 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 CITEL TECHNOLOGIES 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 CITEL TECHNOLOGIES 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. + * + * This file is a contribution to the lwIP TCP/IP stack. + * The Swedish Institute of Computer Science and Adam Dunkels + * are specifically granted permission to redistribute this + * source code. +*/ + +/*------------------------------------------------------------- +Note 1) +Although the rfc requires V1 AND V2 capability +we will only support v2 since now V1 is very old (August 1989) +V1 can be added if required + +a debug print and statistic have been implemented to +show this up. +------------------------------------------------------------- +------------------------------------------------------------- +Note 2) +A query for a specific group address (as opposed to ALLHOSTS) +has now been implemented as I am unsure if it is required + +a debug print and statistic have been implemented to +show this up. +------------------------------------------------------------- +------------------------------------------------------------- +Note 3) +The router alert rfc 2113 is implemented in outgoing packets +but not checked rigorously incoming +------------------------------------------------------------- +Steve Reynolds +------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------- + * RFC 988 - Host extensions for IP multicasting - V0 + * RFC 1054 - Host extensions for IP multicasting - + * RFC 1112 - Host extensions for IP multicasting - V1 + * RFC 2236 - Internet Group Management Protocol, Version 2 - V2 <- this code is based on this RFC (it's the "de facto" standard) + * RFC 3376 - Internet Group Management Protocol, Version 3 - V3 + * RFC 4604 - Using Internet Group Management Protocol Version 3... - V3+ + * RFC 2113 - IP Router Alert Option - + *----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------- + * Includes + *----------------------------------------------------------------------------*/ + +#include "lwip/opt.h" + +#if LWIP_IGMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/igmp.h" +#include "lwip/debug.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/ip.h" +#include "lwip/inet.h" +#include "lwip/inet_chksum.h" +#include "lwip/netif.h" +#include "lwip/icmp.h" +#include "lwip/udp.h" +#include "lwip/tcp.h" +#include "lwip/stats.h" + +#include "string.h" + +/*----------------------------------------------------------------------------- + * Globales + *----------------------------------------------------------------------------*/ + +static struct igmp_group* igmp_group_list; +static struct ip_addr allsystems; +static struct ip_addr allrouters; + +/** + * Initialize the IGMP module + */ +void +igmp_init(void) +{ + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_init: initializing\n")); + + IP4_ADDR(&allsystems, 224, 0, 0, 1); + IP4_ADDR(&allrouters, 224, 0, 0, 2); +} + +#ifdef LWIP_DEBUG +/** + * Dump global IGMP groups list + */ +void +igmp_dump_group_list() +{ + struct igmp_group *group = igmp_group_list; + + while (group != NULL) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_dump_group_list: [%"U32_F"] ", (u32_t)(group->group_state))); + ip_addr_debug_print(IGMP_DEBUG, &group->group_address); + LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", group->interface)); + group = group->next; + } + LWIP_DEBUGF(IGMP_DEBUG, ("\n")); +} +#else +#define igmp_dump_group_list() +#endif /* LWIP_DEBUG */ + +/** + * Start IGMP processing on interface + * + * @param netif network interface on which start IGMP processing + */ +err_t +igmp_start(struct netif *netif) +{ + struct igmp_group* group; + + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_start: starting IGMP processing on if %p\n", netif)); + + group = igmp_lookup_group(netif, &allsystems); + + if (group != NULL) { + group->group_state = IGMP_GROUP_IDLE_MEMBER; + group->use++; + + /* Allow the igmp messages at the MAC level */ + if (netif->igmp_mac_filter != NULL) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_start: igmp_mac_filter(ADD ")); + ip_addr_debug_print(IGMP_DEBUG, &allsystems); + LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif)); + netif->igmp_mac_filter( netif, &allsystems, IGMP_ADD_MAC_FILTER); + } + + return ERR_OK; + } + + return ERR_MEM; +} + +/** + * Stop IGMP processing on interface + * + * @param netif network interface on which stop IGMP processing + */ +err_t +igmp_stop(struct netif *netif) +{ + struct igmp_group *group = igmp_group_list; + struct igmp_group *prev = NULL; + struct igmp_group *next; + + /* look for groups joined on this interface further down the list */ + while (group != NULL) { + next = group->next; + /* is it a group joined on this interface? */ + if (group->interface == netif) { + /* is it the first group of the list? */ + if (group == igmp_group_list) { + igmp_group_list = next; + } + /* is there a "previous" group defined? */ + if (prev != NULL) { + prev->next = next; + } + /* disable the group at the MAC level */ + if (netif->igmp_mac_filter != NULL) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_stop: igmp_mac_filter(DEL ")); + ip_addr_debug_print(IGMP_DEBUG, &group->group_address); + LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif)); + netif->igmp_mac_filter(netif, &(group->group_address), IGMP_DEL_MAC_FILTER); + } + /* free group */ + memp_free(MEMP_IGMP_GROUP, group); + } else { + /* change the "previous" */ + prev = group; + } + /* move to "next" */ + group = next; + } + return ERR_OK; +} + +/** + * Report IGMP memberships for this interface + * + * @param netif network interface on which report IGMP memberships + */ +void +igmp_report_groups( struct netif *netif) +{ + struct igmp_group *group = igmp_group_list; + + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_report_groups: sending IGMP reports on if %p\n", netif)); + + while (group != NULL) { + if (group->interface == netif) { + igmp_delaying_member( group, IGMP_JOIN_DELAYING_MEMBER_TMR); + } + group = group->next; + } +} + +/** + * Search for a group in the global igmp_group_list + * + * @param ifp the network interface for which to look + * @param addr the group ip address to search for + * @return a struct igmp_group* if the group has been found, + * NULL if the group wasn't found. + */ +struct igmp_group * +igmp_lookfor_group(struct netif *ifp, struct ip_addr *addr) +{ + struct igmp_group *group = igmp_group_list; + + while (group != NULL) { + if ((group->interface == ifp) && (ip_addr_cmp(&(group->group_address), addr))) { + return group; + } + group = group->next; + } + + /* to be clearer, we return NULL here instead of + * 'group' (which is also NULL at this point). + */ + return NULL; +} + +/** + * Search for a specific igmp group and create a new one if not found- + * + * @param ifp the network interface for which to look + * @param addr the group ip address to search + * @return a struct igmp_group*, + * NULL on memory error. + */ +struct igmp_group * +igmp_lookup_group(struct netif *ifp, struct ip_addr *addr) +{ + struct igmp_group *group = igmp_group_list; + + /* Search if the group already exists */ + group = igmp_lookfor_group(ifp, addr); + if (group != NULL) { + /* Group already exists. */ + return group; + } + + /* Group doesn't exist yet, create a new one */ + group = memp_malloc(MEMP_IGMP_GROUP); + if (group != NULL) { + group->interface = ifp; + ip_addr_set(&(group->group_address), addr); + group->timer = 0; /* Not running */ + group->group_state = IGMP_GROUP_NON_MEMBER; + group->last_reporter_flag = 0; + group->use = 0; + group->next = igmp_group_list; + + igmp_group_list = group; + } + + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_lookup_group: %sallocated a new group with address ", (group?"":"impossible to "))); + ip_addr_debug_print(IGMP_DEBUG, addr); + LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", ifp)); + + return group; +} + +/** + * Remove a group in the global igmp_group_list + * + * @param group the group to remove from the global igmp_group_list + * @return ERR_OK if group was removed from the list, an err_t otherwise + */ +err_t +igmp_remove_group(struct igmp_group *group) +{ + err_t err = ERR_OK; + + /* Is it the first group? */ + if (igmp_group_list == group) { + igmp_group_list = group->next; + } else { + /* look for group further down the list */ + struct igmp_group *tmpGroup; + for (tmpGroup = igmp_group_list; tmpGroup != NULL; tmpGroup = tmpGroup->next) { + if (tmpGroup->next == group) { + tmpGroup->next = group->next; + break; + } + } + /* Group not found in the global igmp_group_list */ + if (tmpGroup == NULL) + err = ERR_ARG; + } + /* free group */ + memp_free(MEMP_IGMP_GROUP, group); + + return err; +} + +/** + * Called from ip_input() if a new IGMP packet is received. + * + * @param p received igmp packet, p->payload pointing to the ip header + * @param inp network interface on which the packet was received + * @param dest destination ip address of the igmp packet + */ +void +igmp_input(struct pbuf *p, struct netif *inp, struct ip_addr *dest) +{ + struct ip_hdr * iphdr; + struct igmp_msg* igmp; + struct igmp_group* group; + struct igmp_group* groupref; + + /* Note that the length CAN be greater than 8 but only 8 are used - All are included in the checksum */ + iphdr = p->payload; + if (pbuf_header(p, -(s16_t)(IPH_HL(iphdr) * 4)) || (p->len < IGMP_MINLEN)) { + pbuf_free(p); + IGMP_STATS_INC(igmp.lenerr); + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: length error\n")); + return; + } + + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: message from ")); + ip_addr_debug_print(IGMP_DEBUG, &(iphdr->src)); + LWIP_DEBUGF(IGMP_DEBUG, (" to address ")); + ip_addr_debug_print(IGMP_DEBUG, &(iphdr->dest)); + LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", inp)); + + /* Now calculate and check the checksum */ + igmp = (struct igmp_msg *)p->payload; + if (inet_chksum(igmp, p->len)) { + pbuf_free(p); + IGMP_STATS_INC(igmp.chkerr); + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: checksum error\n")); + return; + } + + /* Packet is ok so find an existing group */ + group = igmp_lookfor_group(inp, dest); /* use the incoming IP address! */ + + /* If group can be found or create... */ + if (!group) { + pbuf_free(p); + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP frame not for us\n")); + return; + } + + /* NOW ACT ON THE INCOMING MESSAGE TYPE... */ + switch (igmp->igmp_msgtype) { + case IGMP_MEMB_QUERY: { + /* IGMP_MEMB_QUERY to the "all systems" address ? */ + if ((ip_addr_cmp(dest, &allsystems)) && (igmp->igmp_group_address.addr == 0)) { + /* THIS IS THE GENERAL QUERY */ + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: General IGMP_MEMB_QUERY on \"ALL SYSTEMS\" address (224.0.0.1) [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp))); + + if (igmp->igmp_maxresp == 0) { + IGMP_STATS_INC(igmp.v1_rxed); + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: got an all hosts query with time== 0 - this is V1 and not implemented - treat as v2\n")); + igmp->igmp_maxresp = IGMP_V1_DELAYING_MEMBER_TMR; + } + + IGMP_STATS_INC(igmp.group_query_rxed); + groupref = igmp_group_list; + while (groupref) { + /* Do not send messages on the all systems group address! */ + if ((groupref->interface == inp) && (!(ip_addr_cmp(&(groupref->group_address), &allsystems)))) { + igmp_delaying_member( groupref, igmp->igmp_maxresp); + } + groupref = groupref->next; + } + } else { + /* IGMP_MEMB_QUERY to a specific group ? */ + if (group->group_address.addr != 0) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP_MEMB_QUERY to a specific group ")); + ip_addr_debug_print(IGMP_DEBUG, &group->group_address); + if (ip_addr_cmp (dest, &allsystems)) { + LWIP_DEBUGF(IGMP_DEBUG, (" using \"ALL SYSTEMS\" address (224.0.0.1) [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp))); + /* we first need to re-lookfor the group since we used dest last time */ + group = igmp_lookfor_group(inp, &igmp->igmp_group_address); + } else { + LWIP_DEBUGF(IGMP_DEBUG, (" with the group address as destination [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp))); + } + + if (group != NULL) { + IGMP_STATS_INC(igmp.unicast_query); + igmp_delaying_member( group, igmp->igmp_maxresp); + } + } + } + break; + } + case IGMP_V2_MEMB_REPORT: { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP_V2_MEMB_REPORT\n")); + + IGMP_STATS_INC(igmp.report_rxed); + if (group->group_state == IGMP_GROUP_DELAYING_MEMBER) { + /* This is on a specific group we have already looked up */ + group->timer = 0; /* stopped */ + group->group_state = IGMP_GROUP_IDLE_MEMBER; + group->last_reporter_flag = 0; + } + break; + } + default: { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: unexpected msg %d in state %d on group %p on if %p\n", + igmp->igmp_msgtype, group->group_state, &group, group->interface)); + break; + } + } + + pbuf_free(p); + return; +} + +/** + * Join a group on one network interface. + * + * @param ifaddr ip address of the network interface which should join a new group + * @param groupaddr the ip address of the group which to join + * @return ERR_OK if group was joined on the netif(s), an err_t otherwise + */ +err_t +igmp_joingroup(struct ip_addr *ifaddr, struct ip_addr *groupaddr) +{ + err_t err = ERR_VAL; /* no matching interface */ + struct igmp_group *group; + struct netif *netif; + + /* make sure it is multicast address */ + LWIP_ERROR("igmp_joingroup: attempt to join non-multicast address", ip_addr_ismulticast(groupaddr), return ERR_VAL;); + LWIP_ERROR("igmp_joingroup: attempt to join allsystems address", (!ip_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;); + + /* loop through netif's */ + netif = netif_list; + while (netif != NULL) { + /* Should we join this interface ? */ + if ((netif->flags & NETIF_FLAG_IGMP) && ((ip_addr_isany(ifaddr) || ip_addr_cmp(&(netif->ip_addr), ifaddr)))) { + /* find group or create a new one if not found */ + group = igmp_lookup_group(netif, groupaddr); + + if (group != NULL) { + /* This should create a new group, check the state to make sure */ + if (group->group_state != IGMP_GROUP_NON_MEMBER) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: join to group not in state IGMP_GROUP_NON_MEMBER\n")); + } else { + /* OK - it was new group */ + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: join to new group: ")); + ip_addr_debug_print(IGMP_DEBUG, groupaddr); + LWIP_DEBUGF(IGMP_DEBUG, ("\n")); + + /* If first use of the group, allow the group at the MAC level */ + if ((group->use==0) && (netif->igmp_mac_filter != NULL)) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: igmp_mac_filter(ADD ")); + ip_addr_debug_print(IGMP_DEBUG, groupaddr); + LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif)); + netif->igmp_mac_filter(netif, groupaddr, IGMP_ADD_MAC_FILTER); + } + + IGMP_STATS_INC(igmp.join_sent); + igmp_send(group, IGMP_V2_MEMB_REPORT); + + igmp_start_timer(group, IGMP_JOIN_DELAYING_MEMBER_TMR); + + /* Need to work out where this timer comes from */ + group->group_state = IGMP_GROUP_DELAYING_MEMBER; + } + /* Increment group use */ + group->use++; + /* Join on this interface */ + err = ERR_OK; + } else { + /* Return an error even if some network interfaces are joined */ + /** @todo undo any other netif already joined */ + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: Not enought memory to join to group\n")); + return ERR_MEM; + } + } + /* proceed to next network interface */ + netif = netif->next; + } + + return err; +} + +/** + * Leave a group on one network interface. + * + * @param ifaddr ip address of the network interface which should leave a group + * @param groupaddr the ip address of the group which to leave + * @return ERR_OK if group was left on the netif(s), an err_t otherwise + */ +err_t +igmp_leavegroup(struct ip_addr *ifaddr, struct ip_addr *groupaddr) +{ + err_t err = ERR_VAL; /* no matching interface */ + struct igmp_group *group; + struct netif *netif; + + /* make sure it is multicast address */ + LWIP_ERROR("igmp_leavegroup: attempt to leave non-multicast address", ip_addr_ismulticast(groupaddr), return ERR_VAL;); + LWIP_ERROR("igmp_leavegroup: attempt to leave allsystems address", (!ip_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;); + + /* loop through netif's */ + netif = netif_list; + while (netif != NULL) { + /* Should we leave this interface ? */ + if ((netif->flags & NETIF_FLAG_IGMP) && ((ip_addr_isany(ifaddr) || ip_addr_cmp(&(netif->ip_addr), ifaddr)))) { + /* find group */ + group = igmp_lookfor_group(netif, groupaddr); + + if (group != NULL) { + /* Only send a leave if the flag is set according to the state diagram */ + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: Leaving group: ")); + ip_addr_debug_print(IGMP_DEBUG, groupaddr); + LWIP_DEBUGF(IGMP_DEBUG, ("\n")); + + /* If there is no other use of the group */ + if (group->use <= 1) { + /* If we are the last reporter for this group */ + if (group->last_reporter_flag) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: sending leaving group\n")); + IGMP_STATS_INC(igmp.leave_sent); + igmp_send(group, IGMP_LEAVE_GROUP); + } + + /* Disable the group at the MAC level */ + if (netif->igmp_mac_filter != NULL) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: igmp_mac_filter(DEL ")); + ip_addr_debug_print(IGMP_DEBUG, groupaddr); + LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif)); + netif->igmp_mac_filter(netif, groupaddr, IGMP_DEL_MAC_FILTER); + } + + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: remove group: ")); + ip_addr_debug_print(IGMP_DEBUG, groupaddr); + LWIP_DEBUGF(IGMP_DEBUG, ("\n")); + + /* Free the group */ + igmp_remove_group(group); + } else { + /* Decrement group use */ + group->use--; + } + /* Leave on this interface */ + err = ERR_OK; + } else { + /* It's not a fatal error on "leavegroup" */ + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: not member of group\n")); + } + } + /* proceed to next network interface */ + netif = netif->next; + } + + return err; +} + +/** + * The igmp timer function (both for NO_SYS=1 and =0) + * Should be called every IGMP_TMR_INTERVAL milliseconds (100 ms is default). + */ +void +igmp_tmr(void) +{ + struct igmp_group *group = igmp_group_list; + + while (group != NULL) { + if (group->timer != 0) { + group->timer -= 1; + if (group->timer == 0) { + igmp_timeout(group); + } + } + group = group->next; + } +} + +/** + * Called if a timeout for one group is reached. + * Sends a report for this group. + * + * @param group an igmp_group for which a timeout is reached + */ +void +igmp_timeout(struct igmp_group *group) +{ + /* If the state is IGMP_GROUP_DELAYING_MEMBER then we send a report for this group */ + if (group->group_state == IGMP_GROUP_DELAYING_MEMBER) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_timeout: report membership for group with address ")); + ip_addr_debug_print(IGMP_DEBUG, &(group->group_address)); + LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", group->interface)); + + igmp_send(group, IGMP_V2_MEMB_REPORT); + } +} + +/** + * Start a timer for an igmp group + * + * @param group the igmp_group for which to start a timer + * @param max_time the time in multiples of IGMP_TMR_INTERVAL (decrease with + * every call to igmp_tmr()) + */ +void +igmp_start_timer(struct igmp_group *group, u8_t max_time) +{ + /** + * @todo Important !! this should be random 0 -> max_time. Find out how to do this + */ + group->timer = max_time; +} + +/** + * Stop a timer for an igmp_group + * + * @param group the igmp_group for which to stop the timer + */ +void +igmp_stop_timer(struct igmp_group *group) +{ + group->timer = 0; +} + +/** + * Delaying membership report for a group if necessary + * + * @param group the igmp_group for which "delaying" membership report + * @param maxresp query delay + */ +void +igmp_delaying_member( struct igmp_group *group, u8_t maxresp) +{ + if ((group->group_state == IGMP_GROUP_IDLE_MEMBER) || + ((group->group_state == IGMP_GROUP_DELAYING_MEMBER) && (maxresp > group->timer))) { + igmp_start_timer(group, (maxresp)/2); + group->group_state = IGMP_GROUP_DELAYING_MEMBER; + } +} + + +/** + * Sends an IP packet on a network interface. This function constructs the IP header + * and calculates the IP header checksum. If the source IP address is NULL, + * the IP address of the outgoing network interface is filled in as source address. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == IP_HDRINCL, p already includes an IP + header and p->payload points to that IP header) + * @param src the source IP address to send from (if src == IP_ADDR_ANY, the + * IP address of the netif used to send is used as source address) + * @param dest the destination IP address to send the packet to + * @param ttl the TTL value to be set in the IP header + * @param proto the PROTOCOL to be set in the IP header + * @param netif the netif on which to send this packet + * @return ERR_OK if the packet was sent OK + * ERR_BUF if p doesn't have enough space for IP/LINK headers + * returns errors returned by netif->output + */ +err_t +igmp_ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, + u8_t ttl, u8_t proto, struct netif *netif) +{ + /* This is the "router alert" option */ + u16_t ra[2]; + ra[0] = htons (ROUTER_ALERT); + ra[1] = 0x0000; /* Router shall examine packet */ + return ip_output_if_opt(p, src, dest, ttl, 0, proto, netif, ra, ROUTER_ALERTLEN); +} + +/** + * Send an igmp packet to a specific group. + * + * @param group the group to which to send the packet + * @param type the type of igmp packet to send + */ +void +igmp_send(struct igmp_group *group, u8_t type) +{ + struct pbuf* p = NULL; + struct igmp_msg* igmp = NULL; + struct ip_addr src = {0}; + struct ip_addr* dest = NULL; + + /* IP header + "router alert" option + IGMP header */ + p = pbuf_alloc(PBUF_TRANSPORT, IGMP_MINLEN, PBUF_RAM); + + if (p) { + igmp = p->payload; + LWIP_ASSERT("igmp_send: check that first pbuf can hold struct igmp_msg", + (p->len >= sizeof(struct igmp_msg))); + ip_addr_set(&src, &((group->interface)->ip_addr)); + + if (type == IGMP_V2_MEMB_REPORT) { + dest = &(group->group_address); + IGMP_STATS_INC(igmp.report_sent); + ip_addr_set(&(igmp->igmp_group_address), &(group->group_address)); + group->last_reporter_flag = 1; /* Remember we were the last to report */ + } else { + if (type == IGMP_LEAVE_GROUP) { + dest = &allrouters; + ip_addr_set(&(igmp->igmp_group_address), &(group->group_address)); + } + } + + if ((type == IGMP_V2_MEMB_REPORT) || (type == IGMP_LEAVE_GROUP)) { + igmp->igmp_msgtype = type; + igmp->igmp_maxresp = 0; + igmp->igmp_checksum = 0; + igmp->igmp_checksum = inet_chksum( igmp, IGMP_MINLEN); + + igmp_ip_output_if(p, &src, dest, IGMP_TTL, IP_PROTO_IGMP, group->interface); + } + + pbuf_free(p); + } else { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_send: not enough memory for igmp_send\n")); + } +} + +#endif /* LWIP_IGMP */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/core/ipv4/inet.c b/component/common/network/lwip/lwip_v1.3.2/src/core/ipv4/inet.c new file mode 100644 index 0000000..5e0a6aa --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/core/ipv4/inet.c @@ -0,0 +1,278 @@ +/** + * @file + * Functions common to all TCP/IPv4 modules, such as the byte order functions. + * + **/ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/inet.h" + +/* Here for now until needed in other places in lwIP */ +#ifndef isprint +#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up) +#define isprint(c) in_range(c, 0x20, 0x7f) +#define isdigit(c) in_range(c, '0', '9') +#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F')) +#define islower(c) in_range(c, 'a', 'z') +#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v') +#endif + +/** + * Ascii internet address interpretation routine. + * The value returned is in network order. + * + * @param cp IP address in ascii represenation (e.g. "127.0.0.1") + * @return ip address in network order + */ +u32_t +inet_addr(const char *cp) +{ + struct in_addr val; + + if (inet_aton(cp, &val)) { + return (val.s_addr); + } + return (INADDR_NONE); +} + +/** + * Check whether "cp" is a valid ascii representation + * of an Internet address and convert to a binary address. + * Returns 1 if the address is valid, 0 if not. + * This replaces inet_addr, the return value from which + * cannot distinguish between failure and a local broadcast address. + * + * @param cp IP address in ascii represenation (e.g. "127.0.0.1") + * @param addr pointer to which to save the ip address in network order + * @return 1 if cp could be converted to addr, 0 on failure + */ +int +inet_aton(const char *cp, struct in_addr *addr) +{ + u32_t val; + u8_t base; + char c; + u32_t parts[4]; + u32_t *pp = parts; + + c = *cp; + for (;;) { + /* + * Collect number up to ``.''. + * Values are specified as for C: + * 0x=hex, 0=octal, 1-9=decimal. + */ + if (!isdigit(c)) + return (0); + val = 0; + base = 10; + if (c == '0') { + c = *++cp; + if (c == 'x' || c == 'X') { + base = 16; + c = *++cp; + } else + base = 8; + } + for (;;) { + if (isdigit(c)) { + val = (val * base) + (int)(c - '0'); + c = *++cp; + } else if (base == 16 && isxdigit(c)) { + val = (val << 4) | (int)(c + 10 - (islower(c) ? 'a' : 'A')); + c = *++cp; + } else + break; + } + if (c == '.') { + /* + * Internet format: + * a.b.c.d + * a.b.c (with c treated as 16 bits) + * a.b (with b treated as 24 bits) + */ + if (pp >= parts + 3) + return (0); + *pp++ = val; + c = *++cp; + } else + break; + } + /* + * Check for trailing characters. + */ + if (c != '\0' && !isspace(c)) + return (0); + /* + * Concoct the address according to + * the number of parts specified. + */ + switch (pp - parts + 1) { + + case 0: + return (0); /* initial nondigit */ + + case 1: /* a -- 32 bits */ + break; + + case 2: /* a.b -- 8.24 bits */ + if (val > 0xffffffUL) + return (0); + val |= parts[0] << 24; + break; + + case 3: /* a.b.c -- 8.8.16 bits */ + if (val > 0xffff) + return (0); + val |= (parts[0] << 24) | (parts[1] << 16); + break; + + case 4: /* a.b.c.d -- 8.8.8.8 bits */ + if (val > 0xff) + return (0); + val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); + break; + } + if (addr) + addr->s_addr = htonl(val); + return (1); +} + +/** + * Convert numeric IP address into decimal dotted ASCII representation. + * returns ptr to static buffer; not reentrant! + * + * @param addr ip address in network order to convert + * @return pointer to a global static (!) buffer that holds the ASCII + * represenation of addr + */ +char * +inet_ntoa(struct in_addr addr) +{ + static char str[16]; + u32_t s_addr = addr.s_addr; + char inv[3]; + char *rp; + u8_t *ap; + u8_t rem; + u8_t n; + u8_t i; + + rp = str; + ap = (u8_t *)&s_addr; + for(n = 0; n < 4; n++) { + i = 0; + do { + rem = *ap % (u8_t)10; + *ap /= (u8_t)10; + inv[i++] = '0' + rem; + } while(*ap); + while(i--) + *rp++ = inv[i]; + *rp++ = '.'; + ap++; + } + *--rp = 0; + return str; +} + +/** + * These are reference implementations of the byte swapping functions. + * Again with the aim of being simple, correct and fully portable. + * Byte swapping is the second thing you would want to optimize. You will + * need to port it to your architecture and in your cc.h: + * + * #define LWIP_PLATFORM_BYTESWAP 1 + * #define LWIP_PLATFORM_HTONS(x) + * #define LWIP_PLATFORM_HTONL(x) + * + * Note ntohs() and ntohl() are merely references to the htonx counterparts. + */ + +#if (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN) + +/** + * Convert an u16_t from host- to network byte order. + * + * @param n u16_t in host byte order + * @return n in network byte order + */ +u16_t +htons(u16_t n) +{ + return ((n & 0xff) << 8) | ((n & 0xff00) >> 8); +} + +/** + * Convert an u16_t from network- to host byte order. + * + * @param n u16_t in network byte order + * @return n in host byte order + */ +u16_t +ntohs(u16_t n) +{ + return htons(n); +} + +/** + * Convert an u32_t from host- to network byte order. + * + * @param n u32_t in host byte order + * @return n in network byte order + */ +u32_t +htonl(u32_t n) +{ + return ((n & 0xff) << 24) | + ((n & 0xff00) << 8) | + ((n & 0xff0000UL) >> 8) | + ((n & 0xff000000UL) >> 24); +} + +/** + * Convert an u32_t from network- to host byte order. + * + * @param n u32_t in network byte order + * @return n in host byte order + */ +u32_t +ntohl(u32_t n) +{ + return htonl(n); +} + +#endif /* (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN) */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/core/ipv4/inet_chksum.c b/component/common/network/lwip/lwip_v1.3.2/src/core/ipv4/inet_chksum.c new file mode 100644 index 0000000..739854a --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/core/ipv4/inet_chksum.c @@ -0,0 +1,438 @@ +/** + * @file + * Incluse internet checksum functions. + * + **/ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/inet_chksum.h" +#include "lwip/inet.h" + +#include + +/* These are some reference implementations of the checksum algorithm, with the + * aim of being simple, correct and fully portable. Checksumming is the + * first thing you would want to optimize for your platform. If you create + * your own version, link it in and in your cc.h put: + * + * #define LWIP_CHKSUM + * + * Or you can select from the implementations below by defining + * LWIP_CHKSUM_ALGORITHM to 1, 2 or 3. + */ + +#ifndef LWIP_CHKSUM +# define LWIP_CHKSUM lwip_standard_chksum +# ifndef LWIP_CHKSUM_ALGORITHM +# define LWIP_CHKSUM_ALGORITHM 1 +# endif +#endif +/* If none set: */ +#ifndef LWIP_CHKSUM_ALGORITHM +# define LWIP_CHKSUM_ALGORITHM 0 +#endif + +/** Like the name says... */ +#if LWIP_PLATFORM_BYTESWAP && (BYTE_ORDER == LITTLE_ENDIAN) +/* little endian and PLATFORM_BYTESWAP defined */ +#define SWAP_BYTES_IN_WORD(w) LWIP_PLATFORM_HTONS(w) +#else +/* can't use htons on big endian (or PLATFORM_BYTESWAP not defined)... */ +#define SWAP_BYTES_IN_WORD(w) ((w & 0xff) << 8) | ((w & 0xff00) >> 8) +#endif + +/** Split an u32_t in two u16_ts and add them up */ +#define FOLD_U32T(u) ((u >> 16) + (u & 0x0000ffffUL)) + +#if (LWIP_CHKSUM_ALGORITHM == 1) /* Version #1 */ +/** + * lwip checksum + * + * @param dataptr points to start of data to be summed at any boundary + * @param len length of data to be summed + * @return host order (!) lwip checksum (non-inverted Internet sum) + * + * @note accumulator size limits summable length to 64k + * @note host endianess is irrelevant (p3 RFC1071) + */ +static u16_t +lwip_standard_chksum(void *dataptr, u16_t len) +{ + u32_t acc; + u16_t src; + u8_t *octetptr; + + acc = 0; + /* dataptr may be at odd or even addresses */ + octetptr = (u8_t*)dataptr; + while (len > 1) { + /* declare first octet as most significant + thus assume network order, ignoring host order */ + src = (*octetptr) << 8; + octetptr++; + /* declare second octet as least significant */ + src |= (*octetptr); + octetptr++; + acc += src; + len -= 2; + } + if (len > 0) { + /* accumulate remaining octet */ + src = (*octetptr) << 8; + acc += src; + } + /* add deferred carry bits */ + acc = (acc >> 16) + (acc & 0x0000ffffUL); + if ((acc & 0xffff0000UL) != 0) { + acc = (acc >> 16) + (acc & 0x0000ffffUL); + } + /* This maybe a little confusing: reorder sum using htons() + instead of ntohs() since it has a little less call overhead. + The caller must invert bits for Internet sum ! */ + return htons((u16_t)acc); +} +#endif + +#if (LWIP_CHKSUM_ALGORITHM == 2) /* Alternative version #2 */ +/* + * Curt McDowell + * Broadcom Corp. + * csm@broadcom.com + * + * IP checksum two bytes at a time with support for + * unaligned buffer. + * Works for len up to and including 0x20000. + * by Curt McDowell, Broadcom Corp. 12/08/2005 + * + * @param dataptr points to start of data to be summed at any boundary + * @param len length of data to be summed + * @return host order (!) lwip checksum (non-inverted Internet sum) + */ + +static u16_t +lwip_standard_chksum(void *dataptr, int len) +{ + u8_t *pb = dataptr; + u16_t *ps, t = 0; + u32_t sum = 0; + int odd = ((u32_t)pb & 1); + + /* Get aligned to u16_t */ + if (odd && len > 0) { + ((u8_t *)&t)[1] = *pb++; + len--; + } + + /* Add the bulk of the data */ + ps = (u16_t *)pb; + while (len > 1) { + sum += *ps++; + len -= 2; + } + + /* Consume left-over byte, if any */ + if (len > 0) { + ((u8_t *)&t)[0] = *(u8_t *)ps;; + } + + /* Add end bytes */ + sum += t; + + /* Fold 32-bit sum to 16 bits + calling this twice is propably faster than if statements... */ + sum = FOLD_U32T(sum); + sum = FOLD_U32T(sum); + + /* Swap if alignment was odd */ + if (odd) { + sum = SWAP_BYTES_IN_WORD(sum); + } + + return sum; +} +#endif + +#if (LWIP_CHKSUM_ALGORITHM == 3) /* Alternative version #3 */ +/** + * An optimized checksum routine. Basically, it uses loop-unrolling on + * the checksum loop, treating the head and tail bytes specially, whereas + * the inner loop acts on 8 bytes at a time. + * + * @arg start of buffer to be checksummed. May be an odd byte address. + * @len number of bytes in the buffer to be checksummed. + * @return host order (!) lwip checksum (non-inverted Internet sum) + * + * by Curt McDowell, Broadcom Corp. December 8th, 2005 + */ + +static u16_t +lwip_standard_chksum(void *dataptr, int len) +{ + u8_t *pb = dataptr; + u16_t *ps, t = 0; + u32_t *pl; + u32_t sum = 0, tmp; + /* starts at odd byte address? */ + int odd = ((u32_t)pb & 1); + + if (odd && len > 0) { + ((u8_t *)&t)[1] = *pb++; + len--; + } + + ps = (u16_t *)pb; + + if (((u32_t)ps & 3) && len > 1) { + sum += *ps++; + len -= 2; + } + + pl = (u32_t *)ps; + + while (len > 7) { + tmp = sum + *pl++; /* ping */ + if (tmp < sum) { + tmp++; /* add back carry */ + } + + sum = tmp + *pl++; /* pong */ + if (sum < tmp) { + sum++; /* add back carry */ + } + + len -= 8; + } + + /* make room in upper bits */ + sum = FOLD_U32T(sum); + + ps = (u16_t *)pl; + + /* 16-bit aligned word remaining? */ + while (len > 1) { + sum += *ps++; + len -= 2; + } + + /* dangling tail byte remaining? */ + if (len > 0) { /* include odd byte */ + ((u8_t *)&t)[0] = *(u8_t *)ps; + } + + sum += t; /* add end bytes */ + + /* Fold 32-bit sum to 16 bits + calling this twice is propably faster than if statements... */ + sum = FOLD_U32T(sum); + sum = FOLD_U32T(sum); + + if (odd) { + sum = SWAP_BYTES_IN_WORD(sum); + } + + return sum; +} +#endif + +/* inet_chksum_pseudo: + * + * Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain. + * IP addresses are expected to be in network byte order. + * + * @param p chain of pbufs over that a checksum should be calculated (ip data part) + * @param src source ip address (used for checksum of pseudo header) + * @param dst destination ip address (used for checksum of pseudo header) + * @param proto ip protocol (used for checksum of pseudo header) + * @param proto_len length of the ip data part (used for checksum of pseudo header) + * @return checksum (as u16_t) to be saved directly in the protocol header + */ +u16_t +inet_chksum_pseudo(struct pbuf *p, + struct ip_addr *src, struct ip_addr *dest, + u8_t proto, u16_t proto_len) +{ + u32_t acc; + struct pbuf *q; + u8_t swapped; + + acc = 0; + swapped = 0; + /* iterate through all pbuf in chain */ + for(q = p; q != NULL; q = q->next) { + LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n", + (void *)q, (void *)q->next)); + acc += LWIP_CHKSUM(q->payload, q->len); + /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/ + /* just executing this next line is probably faster that the if statement needed + to check whether we really need to execute it, and does no harm */ + acc = FOLD_U32T(acc); + if (q->len % 2 != 0) { + swapped = 1 - swapped; + acc = SWAP_BYTES_IN_WORD(acc); + } + /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/ + } + + if (swapped) { + acc = SWAP_BYTES_IN_WORD(acc); + } + acc += (src->addr & 0xffffUL); + acc += ((src->addr >> 16) & 0xffffUL); + acc += (dest->addr & 0xffffUL); + acc += ((dest->addr >> 16) & 0xffffUL); + acc += (u32_t)htons((u16_t)proto); + acc += (u32_t)htons(proto_len); + + /* Fold 32-bit sum to 16 bits + calling this twice is propably faster than if statements... */ + acc = FOLD_U32T(acc); + acc = FOLD_U32T(acc); + LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc)); + return (u16_t)~(acc & 0xffffUL); +} + +/* inet_chksum_pseudo: + * + * Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain. + * IP addresses are expected to be in network byte order. + * + * @param p chain of pbufs over that a checksum should be calculated (ip data part) + * @param src source ip address (used for checksum of pseudo header) + * @param dst destination ip address (used for checksum of pseudo header) + * @param proto ip protocol (used for checksum of pseudo header) + * @param proto_len length of the ip data part (used for checksum of pseudo header) + * @return checksum (as u16_t) to be saved directly in the protocol header + */ +/* Currently only used by UDPLITE, although this could change in the future. */ +#if LWIP_UDPLITE +u16_t +inet_chksum_pseudo_partial(struct pbuf *p, + struct ip_addr *src, struct ip_addr *dest, + u8_t proto, u16_t proto_len, u16_t chksum_len) +{ + u32_t acc; + struct pbuf *q; + u8_t swapped; + u16_t chklen; + + acc = 0; + swapped = 0; + /* iterate through all pbuf in chain */ + for(q = p; (q != NULL) && (chksum_len > 0); q = q->next) { + LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n", + (void *)q, (void *)q->next)); + chklen = q->len; + if (chklen > chksum_len) { + chklen = chksum_len; + } + acc += LWIP_CHKSUM(q->payload, chklen); + chksum_len -= chklen; + LWIP_ASSERT("delete me", chksum_len < 0x7fff); + /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/ + /* fold the upper bit down */ + acc = FOLD_U32T(acc); + if (q->len % 2 != 0) { + swapped = 1 - swapped; + acc = SWAP_BYTES_IN_WORD(acc); + } + /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/ + } + + if (swapped) { + acc = SWAP_BYTES_IN_WORD(acc); + } + acc += (src->addr & 0xffffUL); + acc += ((src->addr >> 16) & 0xffffUL); + acc += (dest->addr & 0xffffUL); + acc += ((dest->addr >> 16) & 0xffffUL); + acc += (u32_t)htons((u16_t)proto); + acc += (u32_t)htons(proto_len); + + /* Fold 32-bit sum to 16 bits + calling this twice is propably faster than if statements... */ + acc = FOLD_U32T(acc); + acc = FOLD_U32T(acc); + LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc)); + return (u16_t)~(acc & 0xffffUL); +} +#endif /* LWIP_UDPLITE */ + +/* inet_chksum: + * + * Calculates the Internet checksum over a portion of memory. Used primarily for IP + * and ICMP. + * + * @param dataptr start of the buffer to calculate the checksum (no alignment needed) + * @param len length of the buffer to calculate the checksum + * @return checksum (as u16_t) to be saved directly in the protocol header + */ + +u16_t +inet_chksum(void *dataptr, u16_t len) +{ + return ~LWIP_CHKSUM(dataptr, len); +} + +/** + * Calculate a checksum over a chain of pbufs (without pseudo-header, much like + * inet_chksum only pbufs are used). + * + * @param p pbuf chain over that the checksum should be calculated + * @return checksum (as u16_t) to be saved directly in the protocol header + */ +u16_t +inet_chksum_pbuf(struct pbuf *p) +{ + u32_t acc; + struct pbuf *q; + u8_t swapped; + + acc = 0; + swapped = 0; + for(q = p; q != NULL; q = q->next) { + acc += LWIP_CHKSUM(q->payload, q->len); + acc = FOLD_U32T(acc); + if (q->len % 2 != 0) { + swapped = 1 - swapped; + acc = SWAP_BYTES_IN_WORD(acc); + } + } + + if (swapped) { + acc = SWAP_BYTES_IN_WORD(acc); + } + return (u16_t)~(acc & 0xffffUL); +} diff --git a/component/common/network/lwip/lwip_v1.3.2/src/core/ipv4/ip.c b/component/common/network/lwip/lwip_v1.3.2/src/core/ipv4/ip.c new file mode 100644 index 0000000..df6946c --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/core/ipv4/ip.c @@ -0,0 +1,768 @@ +/** + * @file + * This is the IPv4 layer implementation for incoming and outgoing IP traffic. + * + * @see ip_frag.c + * + **/ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" +#include "lwip/ip.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/ip_frag.h" +#include "lwip/inet.h" +#include "lwip/inet_chksum.h" +#include "lwip/netif.h" +#include "lwip/icmp.h" +#include "lwip/igmp.h" +#include "lwip/raw.h" +#include "lwip/udp.h" +#include "lwip/tcp.h" +#include "lwip/snmp.h" +#include "lwip/dhcp.h" +#include "lwip/stats.h" +#include "arch/perf.h" + +#include + +/** + * The interface that provided the packet for the current callback + * invocation. + */ +struct netif *current_netif; + +/** + * Header of the input packet currently being processed. + */ +const struct ip_hdr *current_header; + +/** + * Finds the appropriate network interface for a given IP address. It + * searches the list of network interfaces linearly. A match is found + * if the masked IP address of the network interface equals the masked + * IP address given to the function. + * + * @param dest the destination IP address for which to find the route + * @return the netif on which to send to reach dest + */ +struct netif * +ip_route(struct ip_addr *dest) +{ + struct netif *netif; + + /* iterate through netifs */ + for(netif = netif_list; netif != NULL; netif = netif->next) { + /* network mask matches? */ + if (netif_is_up(netif)) { + if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) { + /* return netif on which to forward IP packet */ + return netif; + } + } + } + if ((netif_default == NULL) || (!netif_is_up(netif_default))) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_route: No route to 0x%"X32_F"\n", dest->addr)); + IP_STATS_INC(ip.rterr); + snmp_inc_ipoutnoroutes(); + return NULL; + } + /* no matching netif found, use default netif */ + return netif_default; +} + +#if IP_FORWARD +/** + * Forwards an IP packet. It finds an appropriate route for the + * packet, decrements the TTL value of the packet, adjusts the + * checksum and outputs the packet on the appropriate interface. + * + * @param p the packet to forward (p->payload points to IP header) + * @param iphdr the IP header of the input packet + * @param inp the netif on which this packet was received + * @return the netif on which the packet was sent (NULL if it wasn't sent) + */ +static struct netif * +ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp) +{ + struct netif *netif; + + PERF_START; + /* Find network interface where to forward this IP packet to. */ + netif = ip_route((struct ip_addr *)&(iphdr->dest)); + if (netif == NULL) { + LWIP_DEBUGF(IP_DEBUG, ("ip_forward: no forwarding route for 0x%"X32_F" found\n", + iphdr->dest.addr)); + snmp_inc_ipoutnoroutes(); + return (struct netif *)NULL; + } + /* Do not forward packets onto the same network interface on which + * they arrived. */ +/* Realtek Modified Start */ +#ifdef CONFIG_DONT_CARE_TP + if(netif->flags & NETIF_FLAG_IPSWITCH == 0) { + if (netif == inp) { + LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not bouncing packets back on incoming interface.\n")); + snmp_inc_ipoutnoroutes(); + return (struct netif *)NULL; + } + } +#endif +/* Realtek Modified End */ + + /* decrement TTL */ + IPH_TTL_SET(iphdr, IPH_TTL(iphdr) - 1); + /* send ICMP if TTL == 0 */ + if (IPH_TTL(iphdr) == 0) { + snmp_inc_ipinhdrerrors(); +#if LWIP_ICMP + /* Don't send ICMP messages in response to ICMP messages */ + if (IPH_PROTO(iphdr) != IP_PROTO_ICMP) { + icmp_time_exceeded(p, ICMP_TE_TTL); + } +#endif /* LWIP_ICMP */ + return (struct netif *)NULL; + } + + /* Incrementally update the IP checksum. */ + if (IPH_CHKSUM(iphdr) >= htons(0xffff - 0x100)) { + IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + htons(0x100) + 1); + } else { + IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + htons(0x100)); + } + + LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to 0x%"X32_F"\n", + iphdr->dest.addr)); + + IP_STATS_INC(ip.fw); + IP_STATS_INC(ip.xmit); + snmp_inc_ipforwdatagrams(); + + PERF_STOP("ip_forward"); +/* Realtek Modified Start */ +#ifdef CONFIG_DONT_CARE_TP +#if IP_FRAG + /* don't fragment if interface has mtu set to 0 [loopif] */ + if ((netif->flags & NETIF_FLAG_IPSWITCH) && netif->mtu && (p->tot_len > netif->mtu)) { + ip_frag(p,netif,(struct ip_addr *)&(iphdr->dest)); + return netif; + } +#endif +#endif +/* Realtek Modified End */ + /* transmit pbuf on chosen interface */ + netif->output(netif, p, (struct ip_addr *)&(iphdr->dest)); + return netif; +} +#endif /* IP_FORWARD */ + +/** + * This function is called by the network interface device driver when + * an IP packet is received. The function does the basic checks of the + * IP header such as packet size being at least larger than the header + * size etc. If the packet was not destined for us, the packet is + * forwarded (using ip_forward). The IP checksum is always checked. + * + * Finally, the packet is sent to the upper layer protocol input function. + * + * @param p the received IP packet (p->payload points to IP header) + * @param inp the netif on which this packet was received + * @return ERR_OK if the packet was processed (could return ERR_* if it wasn't + * processed, but currently always returns ERR_OK) + */ +err_t +ip_input(struct pbuf *p, struct netif *inp) +{ + struct ip_hdr *iphdr; + struct netif *netif; + u16_t iphdr_hlen; + u16_t iphdr_len; +#if LWIP_DHCP || LWIP_UPNP + int check_ip_src=1; +#endif /* LWIP_DHCP || LWIP_UPNP */ + + IP_STATS_INC(ip.recv); + snmp_inc_ipinreceives(); + + /* identify the IP header */ + iphdr = p->payload; + if (IPH_V(iphdr) != 4) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_WARNING, ("IP packet dropped due to bad version number %"U16_F"\n", IPH_V(iphdr))); + ip_debug_print(p); + pbuf_free(p); + IP_STATS_INC(ip.err); + IP_STATS_INC(ip.drop); + snmp_inc_ipinhdrerrors(); + return ERR_OK; + } + + /* obtain IP header length in number of 32-bit words */ + iphdr_hlen = IPH_HL(iphdr); + /* calculate IP header length in bytes */ + iphdr_hlen *= 4; + /* obtain ip length in bytes */ + iphdr_len = ntohs(IPH_LEN(iphdr)); + + /* header length exceeds first pbuf length, or ip length exceeds total pbuf length? */ + if ((iphdr_hlen > p->len) || (iphdr_len > p->tot_len)) { + if (iphdr_hlen > p->len) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IP header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n", + iphdr_hlen, p->len)); + } + if (iphdr_len > p->tot_len) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IP (len %"U16_F") is longer than pbuf (len %"U16_F"), IP packet dropped.\n", + iphdr_len, p->tot_len)); + } + /* free (drop) packet pbufs */ + pbuf_free(p); + IP_STATS_INC(ip.lenerr); + IP_STATS_INC(ip.drop); + snmp_inc_ipindiscards(); + return ERR_OK; + } + + /* verify checksum */ +#if CHECKSUM_CHECK_IP + if (inet_chksum(iphdr, iphdr_hlen) != 0) { + + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("Checksum (0x%"X16_F") failed, IP packet dropped.\n", inet_chksum(iphdr, iphdr_hlen))); + ip_debug_print(p); + pbuf_free(p); + IP_STATS_INC(ip.chkerr); + IP_STATS_INC(ip.drop); + snmp_inc_ipinhdrerrors(); + return ERR_OK; + } +#endif + + /* Trim pbuf. This should have been done at the netif layer, + * but we'll do it anyway just to be sure that its done. */ + pbuf_realloc(p, iphdr_len); + + /* match packet against an interface, i.e. is this packet for us? */ +#if LWIP_IGMP + if (ip_addr_ismulticast(&(iphdr->dest))) { + if ((inp->flags & NETIF_FLAG_IGMP) && (igmp_lookfor_group(inp, &(iphdr->dest)))) { + netif = inp; + } else { + netif = NULL; + } + } else +#endif /* LWIP_IGMP */ + { + /* start trying with inp. if that's not acceptable, start walking the + list of configured netifs. + 'first' is used as a boolean to mark whether we started walking the list */ + int first = 1; + netif = inp; + do { + LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest 0x%"X32_F" netif->ip_addr 0x%"X32_F" (0x%"X32_F", 0x%"X32_F", 0x%"X32_F")\n", + iphdr->dest.addr, netif->ip_addr.addr, + iphdr->dest.addr & netif->netmask.addr, + netif->ip_addr.addr & netif->netmask.addr, + iphdr->dest.addr & ~(netif->netmask.addr))); + + /* interface is up and configured? */ + if ((netif_is_up(netif)) && (!ip_addr_isany(&(netif->ip_addr)))) { + /* unicast to this interface address? */ + if (ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr)) || + /* or broadcast on this interface network address? */ + ip_addr_isbroadcast(&(iphdr->dest), netif)) { + LWIP_DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n", + netif->name[0], netif->name[1])); + /* break out of for loop */ + break; + } + } + if (first) { + first = 0; + netif = netif_list; + } else { + netif = netif->next; + } + if (netif == inp) { + netif = netif->next; + } + } while(netif != NULL); + } + +#if LWIP_DHCP + /* Pass DHCP messages regardless of destination address. DHCP traffic is addressed + * using link layer addressing (such as Ethernet MAC) so we must not filter on IP. + * According to RFC 1542 section 3.1.1, referred by RFC 2131). + */ + if (netif == NULL) { + /* remote port is DHCP server? */ + if (IPH_PROTO(iphdr) == IP_PROTO_UDP) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: UDP packet to DHCP client port %"U16_F"\n", + ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen))->dest))); + if (ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen))->dest) == DHCP_CLIENT_PORT) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: DHCP packet accepted.\n")); + netif = inp; + check_ip_src = 0; + } + } + } +#endif /* LWIP_DHCP */ + +/* This part of code has been modified by ST's MCD Application Team */ +/* To use the UPnP responder for device discovery */ +#if LWIP_UPNP + /* Pass UPNP messages regardless of destination address. UPNP traffic is addressed + * using multicast addressing so we must not filter on IP. + */ + if (netif == NULL) { + /* remote port is DHCP server? */ + if (IPH_PROTO(iphdr) == IP_PROTO_UDP) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | 1, ("ip_input: UDP packet to UPNP client port %"U16_F"\n", + ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen))->dest))); + if (ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen))->dest) == 1900) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | 1, ("ip_input: UPNP packet accepted.\n")); + netif = inp; + check_ip_src = 0; + } + } + } +#endif /* LWIP_UPNP */ + + /* broadcast or multicast packet source address? Compliant with RFC 1122: 3.2.1.3 */ +#if LWIP_DHCP || LWIP_UPNP + /* DHCP servers need 0.0.0.0 to be allowed as source address (RFC 1.1.2.2: 3.2.1.3/a) */ + if (check_ip_src && (iphdr->src.addr != 0)) +#endif /* LWIP_DHCP || LWIP_UPNP */ + { if ((ip_addr_isbroadcast(&(iphdr->src), inp)) || + (ip_addr_ismulticast(&(iphdr->src)))) { + /* packet source is not valid */ + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("ip_input: packet source is not valid.\n")); + /* free (drop) packet pbufs */ + pbuf_free(p); + IP_STATS_INC(ip.drop); + snmp_inc_ipinaddrerrors(); + snmp_inc_ipindiscards(); + return ERR_OK; + } + } + + /* packet not for us? */ + if (netif == NULL) { + /* packet not for us, route or discard */ + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: packet not for us.\n")); +#if IP_FORWARD +/* Realtek Modified Start */ +#ifdef CONFIG_DONT_CARE_TP + if(inp->flags & NETIF_FLAG_IPSWITCH) +#else +/* Realtek Modified End */ + if (!ip_addr_isbroadcast(&(iphdr->dest), inp)) +#endif + { + /* try to forward IP packet on (other) interfaces */ + ip_forward(p, iphdr, inp); + } + /* non-broadcast packet? */ + else +#endif /* IP_FORWARD */ + { + snmp_inc_ipinaddrerrors(); + snmp_inc_ipindiscards(); + } + pbuf_free(p); + return ERR_OK; + } + /* packet consists of multiple fragments? */ + if ((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) { +#if IP_REASSEMBLY /* packet fragment reassembly code present? */ + LWIP_DEBUGF(IP_DEBUG, ("IP packet is a fragment (id=0x%04"X16_F" tot_len=%"U16_F" len=%"U16_F" MF=%"U16_F" offset=%"U16_F"), calling ip_reass()\n", + ntohs(IPH_ID(iphdr)), p->tot_len, ntohs(IPH_LEN(iphdr)), !!(IPH_OFFSET(iphdr) & htons(IP_MF)), (ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8)); + /* reassemble the packet*/ + p = ip_reass(p); + /* packet not fully reassembled yet? */ + if (p == NULL) { + return ERR_OK; + } + iphdr = p->payload; +#else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */ + pbuf_free(p); + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since it was fragmented (0x%"X16_F") (while IP_REASSEMBLY == 0).\n", + ntohs(IPH_OFFSET(iphdr)))); + IP_STATS_INC(ip.opterr); + IP_STATS_INC(ip.drop); + /* unsupported protocol feature */ + snmp_inc_ipinunknownprotos(); + return ERR_OK; +#endif /* IP_REASSEMBLY */ + } + +#if IP_OPTIONS_ALLOWED == 0 /* no support for IP options in the IP header? */ + +#if LWIP_IGMP + /* there is an extra "router alert" option in IGMP messages which we allow for but do not police */ + if((iphdr_hlen > IP_HLEN && (IPH_PROTO(iphdr) != IP_PROTO_IGMP)) { +#else + if (iphdr_hlen > IP_HLEN) { +#endif /* LWIP_IGMP */ + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since there were IP options (while IP_OPTIONS_ALLOWED == 0).\n")); + pbuf_free(p); + IP_STATS_INC(ip.opterr); + IP_STATS_INC(ip.drop); + /* unsupported protocol feature */ + snmp_inc_ipinunknownprotos(); + return ERR_OK; + } +#endif /* IP_OPTIONS_ALLOWED == 0 */ + + /* send to upper layers */ + LWIP_DEBUGF(IP_DEBUG, ("ip_input: \n")); + ip_debug_print(p); + LWIP_DEBUGF(IP_DEBUG, ("ip_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len)); + + current_netif = inp; + current_header = iphdr; + +#if LWIP_RAW + /* raw input did not eat the packet? */ + if (raw_input(p, inp) == 0) +#endif /* LWIP_RAW */ + { + + switch (IPH_PROTO(iphdr)) { +#if LWIP_UDP + case IP_PROTO_UDP: +#if LWIP_UDPLITE + case IP_PROTO_UDPLITE: +#endif /* LWIP_UDPLITE */ + snmp_inc_ipindelivers(); + udp_input(p, inp); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case IP_PROTO_TCP: + snmp_inc_ipindelivers(); + tcp_input(p, inp); + break; +#endif /* LWIP_TCP */ +#if LWIP_ICMP + case IP_PROTO_ICMP: + snmp_inc_ipindelivers(); + icmp_input(p, inp); + break; +#endif /* LWIP_ICMP */ +#if LWIP_IGMP + case IP_PROTO_IGMP: + igmp_input(p,inp,&(iphdr->dest)); + break; +#endif /* LWIP_IGMP */ + default: +#if LWIP_ICMP + /* send ICMP destination protocol unreachable unless is was a broadcast */ + if (!ip_addr_isbroadcast(&(iphdr->dest), inp) && + !ip_addr_ismulticast(&(iphdr->dest))) { + p->payload = iphdr; + icmp_dest_unreach(p, ICMP_DUR_PROTO); + } +#endif /* LWIP_ICMP */ + pbuf_free(p); + + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("Unsupported transport protocol %"U16_F"\n", IPH_PROTO(iphdr))); + + IP_STATS_INC(ip.proterr); + IP_STATS_INC(ip.drop); + snmp_inc_ipinunknownprotos(); + } + } + + current_netif = NULL; + current_header = NULL; + + return ERR_OK; +} + +/** + * Sends an IP packet on a network interface. This function constructs + * the IP header and calculates the IP header checksum. If the source + * IP address is NULL, the IP address of the outgoing network + * interface is filled in as source address. + * If the destination IP address is IP_HDRINCL, p is assumed to already + * include an IP header and p->payload points to it instead of the data. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == IP_HDRINCL, p already includes an IP + header and p->payload points to that IP header) + * @param src the source IP address to send from (if src == IP_ADDR_ANY, the + * IP address of the netif used to send is used as source address) + * @param dest the destination IP address to send the packet to + * @param ttl the TTL value to be set in the IP header + * @param tos the TOS value to be set in the IP header + * @param proto the PROTOCOL to be set in the IP header + * @param netif the netif on which to send this packet + * @return ERR_OK if the packet was sent OK + * ERR_BUF if p doesn't have enough space for IP/LINK headers + * returns errors returned by netif->output + * + * @note ip_id: RFC791 "some host may be able to simply use + * unique identifiers independent of destination" + */ +err_t +ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, + u8_t ttl, u8_t tos, + u8_t proto, struct netif *netif) +{ +#if IP_OPTIONS_SEND + return ip_output_if_opt(p, src, dest, ttl, tos, proto, netif, NULL, 0); +} + +/** + * Same as ip_output_if() but with the possibility to include IP options: + * + * @ param ip_options pointer to the IP options, copied into the IP header + * @ param optlen length of ip_options + */ +err_t ip_output_if_opt(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, + u16_t optlen) +{ +#endif /* IP_OPTIONS_SEND */ + struct ip_hdr *iphdr; + static u16_t ip_id = 0; + + snmp_inc_ipoutrequests(); + + /* Should the IP header be generated or is it already included in p? */ + if (dest != IP_HDRINCL) { + u16_t ip_hlen = IP_HLEN; +#if IP_OPTIONS_SEND + u16_t optlen_aligned = 0; + if (optlen != 0) { + /* round up to a multiple of 4 */ + optlen_aligned = ((optlen + 3) & ~3); + ip_hlen += optlen_aligned; + /* First write in the IP options */ + if (pbuf_header(p, optlen_aligned)) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_output_if_opt: not enough room for IP options in pbuf\n")); + IP_STATS_INC(ip.err); + snmp_inc_ipoutdiscards(); + return ERR_BUF; + } + MEMCPY(p->payload, ip_options, optlen); + if (optlen < optlen_aligned) { + /* zero the remaining bytes */ + memset(((char*)p->payload) + optlen, 0, optlen_aligned - optlen); + } + } +#endif /* IP_OPTIONS_SEND */ + /* generate IP header */ + if (pbuf_header(p, IP_HLEN)) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_output: not enough room for IP header in pbuf\n")); + + IP_STATS_INC(ip.err); + snmp_inc_ipoutdiscards(); + return ERR_BUF; + } + + iphdr = p->payload; + LWIP_ASSERT("check that first pbuf can hold struct ip_hdr", + (p->len >= sizeof(struct ip_hdr))); + + IPH_TTL_SET(iphdr, ttl); + IPH_PROTO_SET(iphdr, proto); + + ip_addr_set(&(iphdr->dest), dest); + + IPH_VHLTOS_SET(iphdr, 4, ip_hlen / 4, tos); + IPH_LEN_SET(iphdr, htons(p->tot_len)); + IPH_OFFSET_SET(iphdr, 0); + IPH_ID_SET(iphdr, htons(ip_id)); + ++ip_id; + + if (ip_addr_isany(src)) { + ip_addr_set(&(iphdr->src), &(netif->ip_addr)); + } else { + ip_addr_set(&(iphdr->src), src); + } + + IPH_CHKSUM_SET(iphdr, 0); +#if CHECKSUM_GEN_IP + IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, ip_hlen)); +#endif + } else { + /* IP header already included in p */ + iphdr = p->payload; + dest = &(iphdr->dest); + } + + IP_STATS_INC(ip.xmit); + + LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], netif->num)); + ip_debug_print(p); + +#if ENABLE_LOOPBACK + if (ip_addr_cmp(dest, &netif->ip_addr)) { + /* Packet to self, enqueue it for loopback */ + LWIP_DEBUGF(IP_DEBUG, ("netif_loop_output()")); + return netif_loop_output(netif, p, dest); + } +#endif /* ENABLE_LOOPBACK */ +#if IP_FRAG + /* don't fragment if interface has mtu set to 0 [loopif] */ + if (netif->mtu && (p->tot_len > netif->mtu)) { + return ip_frag(p,netif,dest); + } +#endif + + LWIP_DEBUGF(IP_DEBUG, ("netif->output()")); + return netif->output(netif, p, dest); +} + +/** + * Simple interface to ip_output_if. It finds the outgoing network + * interface and calls upon ip_output_if to do the actual work. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == IP_HDRINCL, p already includes an IP + header and p->payload points to that IP header) + * @param src the source IP address to send from (if src == IP_ADDR_ANY, the + * IP address of the netif used to send is used as source address) + * @param dest the destination IP address to send the packet to + * @param ttl the TTL value to be set in the IP header + * @param tos the TOS value to be set in the IP header + * @param proto the PROTOCOL to be set in the IP header + * + * @return ERR_RTE if no route is found + * see ip_output_if() for more return values + */ +err_t +ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, + u8_t ttl, u8_t tos, u8_t proto) +{ + struct netif *netif; + + if ((netif = ip_route(dest)) == NULL) { + LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to 0x%"X32_F"\n", dest->addr)); + IP_STATS_INC(ip.rterr); + return ERR_RTE; + } + + return ip_output_if(p, src, dest, ttl, tos, proto, netif); +} + +#if LWIP_NETIF_HWADDRHINT +/** Like ip_output, but takes and addr_hint pointer that is passed on to netif->addr_hint + * before calling ip_output_if. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == IP_HDRINCL, p already includes an IP + header and p->payload points to that IP header) + * @param src the source IP address to send from (if src == IP_ADDR_ANY, the + * IP address of the netif used to send is used as source address) + * @param dest the destination IP address to send the packet to + * @param ttl the TTL value to be set in the IP header + * @param tos the TOS value to be set in the IP header + * @param proto the PROTOCOL to be set in the IP header + * @param addr_hint address hint pointer set to netif->addr_hint before + * calling ip_output_if() + * + * @return ERR_RTE if no route is found + * see ip_output_if() for more return values + */ +err_t +ip_output_hinted(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, + u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint) +{ + struct netif *netif; + err_t err; + + if ((netif = ip_route(dest)) == NULL) { + LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to 0x%"X32_F"\n", dest->addr)); + IP_STATS_INC(ip.rterr); + return ERR_RTE; + } + + netif->addr_hint = addr_hint; + err = ip_output_if(p, src, dest, ttl, tos, proto, netif); + netif->addr_hint = NULL; + + return err; +} +#endif /* LWIP_NETIF_HWADDRHINT*/ + +#if IP_DEBUG +/* Print an IP header by using LWIP_DEBUGF + * @param p an IP packet, p->payload pointing to the IP header + */ +void +ip_debug_print(struct pbuf *p) +{ + struct ip_hdr *iphdr = p->payload; + u8_t *payload; + + payload = (u8_t *)iphdr + IP_HLEN; + + LWIP_DEBUGF(IP_DEBUG, ("IP header:\n")); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("|%2"S16_F" |%2"S16_F" | 0x%02"X16_F" | %5"U16_F" | (v, hl, tos, len)\n", + IPH_V(iphdr), + IPH_HL(iphdr), + IPH_TOS(iphdr), + ntohs(IPH_LEN(iphdr)))); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("| %5"U16_F" |%"U16_F"%"U16_F"%"U16_F"| %4"U16_F" | (id, flags, offset)\n", + ntohs(IPH_ID(iphdr)), + ntohs(IPH_OFFSET(iphdr)) >> 15 & 1, + ntohs(IPH_OFFSET(iphdr)) >> 14 & 1, + ntohs(IPH_OFFSET(iphdr)) >> 13 & 1, + ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | 0x%04"X16_F" | (ttl, proto, chksum)\n", + IPH_TTL(iphdr), + IPH_PROTO(iphdr), + ntohs(IPH_CHKSUM(iphdr)))); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (src)\n", + ip4_addr1(&iphdr->src), + ip4_addr2(&iphdr->src), + ip4_addr3(&iphdr->src), + ip4_addr4(&iphdr->src))); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (dest)\n", + ip4_addr1(&iphdr->dest), + ip4_addr2(&iphdr->dest), + ip4_addr3(&iphdr->dest), + ip4_addr4(&iphdr->dest))); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); +} +#endif /* IP_DEBUG */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/core/ipv4/ip_addr.c b/component/common/network/lwip/lwip_v1.3.2/src/core/ipv4/ip_addr.c new file mode 100644 index 0000000..30a165b --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/core/ipv4/ip_addr.c @@ -0,0 +1,84 @@ +/** + * @file + * This is the IPv4 address tools implementation. + * + **/ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" +#include "lwip/ip_addr.h" +#include "lwip/inet.h" +#include "lwip/netif.h" + +#define IP_ADDR_ANY_VALUE 0x00000000UL +#define IP_ADDR_BROADCAST_VALUE 0xffffffffUL + +/* used by IP_ADDR_ANY and IP_ADDR_BROADCAST in ip_addr.h */ +const struct ip_addr ip_addr_any = { IP_ADDR_ANY_VALUE }; +const struct ip_addr ip_addr_broadcast = { IP_ADDR_BROADCAST_VALUE }; + +/** + * Determine if an address is a broadcast address on a network interface + * + * @param addr address to be checked + * @param netif the network interface against which the address is checked + * @return returns non-zero if the address is a broadcast address + */ +u8_t ip_addr_isbroadcast(struct ip_addr *addr, struct netif *netif) +{ + u32_t addr2test; + + addr2test = addr->addr; + /* all ones (broadcast) or all zeroes (old skool broadcast) */ + if ((~addr2test == IP_ADDR_ANY_VALUE) || + (addr2test == IP_ADDR_ANY_VALUE)) + return 1; + /* no broadcast support on this network interface? */ + else if ((netif->flags & NETIF_FLAG_BROADCAST) == 0) + /* the given address cannot be a broadcast address + * nor can we check against any broadcast addresses */ + return 0; + /* address matches network interface address exactly? => no broadcast */ + else if (addr2test == netif->ip_addr.addr) + return 0; + /* on the same (sub) network... */ + else if (ip_addr_netcmp(addr, &(netif->ip_addr), &(netif->netmask)) + /* ...and host identifier bits are all ones? =>... */ + && ((addr2test & ~netif->netmask.addr) == + (IP_ADDR_BROADCAST_VALUE & ~netif->netmask.addr))) + /* => network broadcast address */ + return 1; + else + return 0; +} diff --git a/component/common/network/lwip/lwip_v1.3.2/src/core/ipv4/ip_frag.c b/component/common/network/lwip/lwip_v1.3.2/src/core/ipv4/ip_frag.c new file mode 100644 index 0000000..59afe94 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/core/ipv4/ip_frag.c @@ -0,0 +1,792 @@ +/** + * @file + * This is the IPv4 packet segmentation and reassembly implementation. + * + **/ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Jani Monoses + * Simon Goldschmidt + * original reassembly code by Adam Dunkels + * + */ + +#include "lwip/opt.h" +#include "lwip/ip_frag.h" +#include "lwip/ip.h" +#include "lwip/inet.h" +#include "lwip/inet_chksum.h" +#include "lwip/netif.h" +#include "lwip/snmp.h" +#include "lwip/stats.h" +#include "lwip/icmp.h" + +#include + +#if IP_REASSEMBLY +/** + * The IP reassembly code currently has the following limitations: + * - IP header options are not supported + * - fragments must not overlap (e.g. due to different routes), + * currently, overlapping or duplicate fragments are thrown away + * if IP_REASS_CHECK_OVERLAP=1 (the default)! + * + * @todo: work with IP header options + */ + +/** Setting this to 0, you can turn off checking the fragments for overlapping + * regions. The code gets a little smaller. Only use this if you know that + * overlapping won't occur on your network! */ +#ifndef IP_REASS_CHECK_OVERLAP +#define IP_REASS_CHECK_OVERLAP 1 +#endif /* IP_REASS_CHECK_OVERLAP */ + +/** Set to 0 to prevent freeing the oldest datagram when the reassembly buffer is + * full (IP_REASS_MAX_PBUFS pbufs are enqueued). The code gets a little smaller. + * Datagrams will be freed by timeout only. Especially useful when MEMP_NUM_REASSDATA + * is set to 1, so one datagram can be reassembled at a time, only. */ +#ifndef IP_REASS_FREE_OLDEST +#define IP_REASS_FREE_OLDEST 1 +#endif /* IP_REASS_FREE_OLDEST */ + +#define IP_REASS_FLAG_LASTFRAG 0x01 + +/** This is a helper struct which holds the starting + * offset and the ending offset of this fragment to + * easily chain the fragments. + * It has to be packed since it has to fit inside the IP header. + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip_reass_helper { + PACK_STRUCT_FIELD(struct pbuf *next_pbuf); + PACK_STRUCT_FIELD(u16_t start); + PACK_STRUCT_FIELD(u16_t end); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define IP_ADDRESSES_AND_ID_MATCH(iphdrA, iphdrB) \ + (ip_addr_cmp(&(iphdrA)->src, &(iphdrB)->src) && \ + ip_addr_cmp(&(iphdrA)->dest, &(iphdrB)->dest) && \ + IPH_ID(iphdrA) == IPH_ID(iphdrB)) ? 1 : 0 + +/* global variables */ +static struct ip_reassdata *reassdatagrams; +static u16_t ip_reass_pbufcount; + +/* function prototypes */ +static void ip_reass_dequeue_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev); +static int ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev); + +/** + * Reassembly timer base function + * for both NO_SYS == 0 and 1 (!). + * + * Should be called every 1000 msec (defined by IP_TMR_INTERVAL). + */ +void +ip_reass_tmr(void) +{ + struct ip_reassdata *r, *prev = NULL; + + r = reassdatagrams; + while (r != NULL) { + /* Decrement the timer. Once it reaches 0, + * clean up the incomplete fragment assembly */ + if (r->timer > 0) { + r->timer--; + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass_tmr: timer dec %"U16_F"\n",(u16_t)r->timer)); + prev = r; + r = r->next; + } else { + /* reassembly timed out */ + struct ip_reassdata *tmp; + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass_tmr: timer timed out\n")); + tmp = r; + /* get the next pointer before freeing */ + r = r->next; + /* free the helper struct and all enqueued pbufs */ + ip_reass_free_complete_datagram(tmp, prev); + } + } +} + +/** + * Free a datagram (struct ip_reassdata) and all its pbufs. + * Updates the total count of enqueued pbufs (ip_reass_pbufcount), + * SNMP counters and sends an ICMP time exceeded packet. + * + * @param ipr datagram to free + * @param prev the previous datagram in the linked list + * @return the number of pbufs freed + */ +static int +ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev) +{ + int pbufs_freed = 0; + struct pbuf *p; + struct ip_reass_helper *iprh; + + LWIP_ASSERT("prev != ipr", prev != ipr); + if (prev != NULL) { + LWIP_ASSERT("prev->next == ipr", prev->next == ipr); + } + + snmp_inc_ipreasmfails(); +#if LWIP_ICMP + iprh = (struct ip_reass_helper *)ipr->p->payload; + if (iprh->start == 0) { + /* The first fragment was received, send ICMP time exceeded. */ + /* First, de-queue the first pbuf from r->p. */ + p = ipr->p; + ipr->p = iprh->next_pbuf; + /* Then, copy the original header into it. */ + SMEMCPY(p->payload, &ipr->iphdr, IP_HLEN); + icmp_time_exceeded(p, ICMP_TE_FRAG); + pbufs_freed += pbuf_clen(p); + pbuf_free(p); + } +#endif /* LWIP_ICMP */ + + /* First, free all received pbufs. The individual pbufs need to be released + separately as they have not yet been chained */ + p = ipr->p; + while (p != NULL) { + struct pbuf *pcur; + iprh = (struct ip_reass_helper *)p->payload; + pcur = p; + /* get the next pointer before freeing */ + p = iprh->next_pbuf; + pbufs_freed += pbuf_clen(pcur); + pbuf_free(pcur); + } + /* Then, unchain the struct ip_reassdata from the list and free it. */ + ip_reass_dequeue_datagram(ipr, prev); + LWIP_ASSERT("ip_reass_pbufcount >= clen", ip_reass_pbufcount >= pbufs_freed); + ip_reass_pbufcount -= pbufs_freed; + + return pbufs_freed; +} + +#if IP_REASS_FREE_OLDEST +/** + * Free the oldest datagram to make room for enqueueing new fragments. + * The datagram 'fraghdr' belongs to is not freed! + * + * @param fraghdr IP header of the current fragment + * @param pbufs_needed number of pbufs needed to enqueue + * (used for freeing other datagrams if not enough space) + * @return the number of pbufs freed + */ +static int +ip_reass_remove_oldest_datagram(struct ip_hdr *fraghdr, int pbufs_needed) +{ + /* @todo Can't we simply remove the last datagram in the + * linked list behind reassdatagrams? + */ + struct ip_reassdata *r, *oldest, *prev; + int pbufs_freed = 0, pbufs_freed_current; + int other_datagrams; + + /* Free datagrams until being allowed to enqueue 'pbufs_needed' pbufs, + * but don't free the datagram that 'fraghdr' belongs to! */ + do { + oldest = NULL; + prev = NULL; + other_datagrams = 0; + r = reassdatagrams; + while (r != NULL) { + if (!IP_ADDRESSES_AND_ID_MATCH(&r->iphdr, fraghdr)) { + /* Not the same datagram as fraghdr */ + other_datagrams++; + if (oldest == NULL) { + oldest = r; + } else if (r->timer <= oldest->timer) { + /* older than the previous oldest */ + oldest = r; + } + } + if (r->next != NULL) { + prev = r; + } + r = r->next; + } + if (oldest != NULL) { + pbufs_freed_current = ip_reass_free_complete_datagram(oldest, prev); + pbufs_freed += pbufs_freed_current; + } + } while ((pbufs_freed < pbufs_needed) && (other_datagrams > 1)); + return pbufs_freed; +} +#endif /* IP_REASS_FREE_OLDEST */ + +/** + * Enqueues a new fragment into the fragment queue + * @param fraghdr points to the new fragments IP hdr + * @param clen number of pbufs needed to enqueue (used for freeing other datagrams if not enough space) + * @return A pointer to the queue location into which the fragment was enqueued + */ +static struct ip_reassdata* +ip_reass_enqueue_new_datagram(struct ip_hdr *fraghdr, int clen) +{ + struct ip_reassdata* ipr; + /* No matching previous fragment found, allocate a new reassdata struct */ + ipr = memp_malloc(MEMP_REASSDATA); + if (ipr == NULL) { +#if IP_REASS_FREE_OLDEST + if (ip_reass_remove_oldest_datagram(fraghdr, clen) >= clen) { + ipr = memp_malloc(MEMP_REASSDATA); + } + if (ipr == NULL) +#endif /* IP_REASS_FREE_OLDEST */ + { + IPFRAG_STATS_INC(ip_frag.memerr); + LWIP_DEBUGF(IP_REASS_DEBUG,("Failed to alloc reassdata struct\n")); + return NULL; + } + } + memset(ipr, 0, sizeof(struct ip_reassdata)); + ipr->timer = IP_REASS_MAXAGE; + + /* enqueue the new structure to the front of the list */ + ipr->next = reassdatagrams; + reassdatagrams = ipr; + /* copy the ip header for later tests and input */ + /* @todo: no ip options supported? */ + SMEMCPY(&(ipr->iphdr), fraghdr, IP_HLEN); + return ipr; +} + +/** + * Dequeues a datagram from the datagram queue. Doesn't deallocate the pbufs. + * @param ipr points to the queue entry to dequeue + */ +static void +ip_reass_dequeue_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev) +{ + + /* dequeue the reass struct */ + if (reassdatagrams == ipr) { + /* it was the first in the list */ + reassdatagrams = ipr->next; + } else { + /* it wasn't the first, so it must have a valid 'prev' */ + LWIP_ASSERT("sanity check linked list", prev != NULL); + prev->next = ipr->next; + } + + /* now we can free the ip_reass struct */ + memp_free(MEMP_REASSDATA, ipr); +} + +/** + * Chain a new pbuf into the pbuf list that composes the datagram. The pbuf list + * will grow over time as new pbufs are rx. + * Also checks that the datagram passes basic continuity checks (if the last + * fragment was received at least once). + * @param root_p points to the 'root' pbuf for the current datagram being assembled. + * @param new_p points to the pbuf for the current fragment + * @return 0 if invalid, >0 otherwise + */ +static int +ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct pbuf *new_p) +{ + struct ip_reass_helper *iprh, *iprh_tmp, *iprh_prev=NULL; + struct pbuf *q; + u16_t offset,len; + struct ip_hdr *fraghdr; + int valid = 1; + + /* Extract length and fragment offset from current fragment */ + fraghdr = (struct ip_hdr*)new_p->payload; + len = ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4; + offset = (ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8; + + /* overwrite the fragment's ip header from the pbuf with our helper struct, + * and setup the embedded helper structure. */ + /* make sure the struct ip_reass_helper fits into the IP header */ + LWIP_ASSERT("sizeof(struct ip_reass_helper) <= IP_HLEN", + sizeof(struct ip_reass_helper) <= IP_HLEN); + iprh = (struct ip_reass_helper*)new_p->payload; + iprh->next_pbuf = NULL; + iprh->start = offset; + iprh->end = offset + len; + + /* Iterate through until we either get to the end of the list (append), + * or we find on with a larger offset (insert). */ + for (q = ipr->p; q != NULL;) { + iprh_tmp = (struct ip_reass_helper*)q->payload; + if (iprh->start < iprh_tmp->start) { + /* the new pbuf should be inserted before this */ + iprh->next_pbuf = q; + if (iprh_prev != NULL) { + /* not the fragment with the lowest offset */ +#if IP_REASS_CHECK_OVERLAP + if ((iprh->start < iprh_prev->end) || (iprh->end > iprh_tmp->start)) { + /* fragment overlaps with previous or following, throw away */ + goto freepbuf; + } +#endif /* IP_REASS_CHECK_OVERLAP */ + iprh_prev->next_pbuf = new_p; + } else { + /* fragment with the lowest offset */ + ipr->p = new_p; + } + break; + } else if(iprh->start == iprh_tmp->start) { + /* received the same datagram twice: no need to keep the datagram */ + goto freepbuf; +#if IP_REASS_CHECK_OVERLAP + } else if(iprh->start < iprh_tmp->end) { + /* overlap: no need to keep the new datagram */ + goto freepbuf; +#endif /* IP_REASS_CHECK_OVERLAP */ + } else { + /* Check if the fragments received so far have no wholes. */ + if (iprh_prev != NULL) { + if (iprh_prev->end != iprh_tmp->start) { + /* There is a fragment missing between the current + * and the previous fragment */ + valid = 0; + } + } + } + q = iprh_tmp->next_pbuf; + iprh_prev = iprh_tmp; + } + + /* If q is NULL, then we made it to the end of the list. Determine what to do now */ + if (q == NULL) { + if (iprh_prev != NULL) { + /* this is (for now), the fragment with the highest offset: + * chain it to the last fragment */ +#if IP_REASS_CHECK_OVERLAP + LWIP_ASSERT("check fragments don't overlap", iprh_prev->end <= iprh->start); +#endif /* IP_REASS_CHECK_OVERLAP */ + iprh_prev->next_pbuf = new_p; + if (iprh_prev->end != iprh->start) { + valid = 0; + } + } else { +#if IP_REASS_CHECK_OVERLAP + LWIP_ASSERT("no previous fragment, this must be the first fragment!", + ipr->p == NULL); +#endif /* IP_REASS_CHECK_OVERLAP */ + /* this is the first fragment we ever received for this ip datagram */ + ipr->p = new_p; + } + } + + /* At this point, the validation part begins: */ + /* If we already received the last fragment */ + if ((ipr->flags & IP_REASS_FLAG_LASTFRAG) != 0) { + /* and had no wholes so far */ + if (valid) { + /* then check if the rest of the fragments is here */ + /* Check if the queue starts with the first datagram */ + if (((struct ip_reass_helper*)ipr->p->payload)->start != 0) { + valid = 0; + } else { + /* and check that there are no wholes after this datagram */ + iprh_prev = iprh; + q = iprh->next_pbuf; + while (q != NULL) { + iprh = (struct ip_reass_helper*)q->payload; + if (iprh_prev->end != iprh->start) { + valid = 0; + break; + } + iprh_prev = iprh; + q = iprh->next_pbuf; + } + /* if still valid, all fragments are received + * (because to the MF==0 already arrived */ + if (valid) { + LWIP_ASSERT("sanity check", ipr->p != NULL); + LWIP_ASSERT("sanity check", + ((struct ip_reass_helper*)ipr->p->payload) != iprh); + LWIP_ASSERT("validate_datagram:next_pbuf!=NULL", + iprh->next_pbuf == NULL); + LWIP_ASSERT("validate_datagram:datagram end!=datagram len", + iprh->end == ipr->datagram_len); + } + } + } + /* If valid is 0 here, there are some fragments missing in the middle + * (since MF == 0 has already arrived). Such datagrams simply time out if + * no more fragments are received... */ + return valid; + } + /* If we come here, not all fragments were received, yet! */ + return 0; /* not yet valid! */ +#if IP_REASS_CHECK_OVERLAP +freepbuf: + ip_reass_pbufcount -= pbuf_clen(new_p); + pbuf_free(new_p); + return 0; +#endif /* IP_REASS_CHECK_OVERLAP */ +} + +/** + * Reassembles incoming IP fragments into an IP datagram. + * + * @param p points to a pbuf chain of the fragment + * @return NULL if reassembly is incomplete, ? otherwise + */ +struct pbuf * +ip_reass(struct pbuf *p) +{ + struct pbuf *r; + struct ip_hdr *fraghdr; + struct ip_reassdata *ipr; + struct ip_reass_helper *iprh; + u16_t offset, len; + u8_t clen; + struct ip_reassdata *ipr_prev = NULL; + + IPFRAG_STATS_INC(ip_frag.recv); + snmp_inc_ipreasmreqds(); + + fraghdr = (struct ip_hdr*)p->payload; + + if ((IPH_HL(fraghdr) * 4) != IP_HLEN) { + LWIP_DEBUGF(IP_REASS_DEBUG,("ip_reass: IP options currently not supported!\n")); + IPFRAG_STATS_INC(ip_frag.err); + goto nullreturn; + } + + offset = (ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8; + len = ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4; + + /* Check if we are allowed to enqueue more datagrams. */ + clen = pbuf_clen(p); + if ((ip_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS) { +#if IP_REASS_FREE_OLDEST + if (!ip_reass_remove_oldest_datagram(fraghdr, clen) || + ((ip_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS)) +#endif /* IP_REASS_FREE_OLDEST */ + { + /* No datagram could be freed and still too many pbufs enqueued */ + LWIP_DEBUGF(IP_REASS_DEBUG,("ip_reass: Overflow condition: pbufct=%d, clen=%d, MAX=%d\n", + ip_reass_pbufcount, clen, IP_REASS_MAX_PBUFS)); + IPFRAG_STATS_INC(ip_frag.memerr); + /* @todo: send ICMP time exceeded here? */ + /* drop this pbuf */ + goto nullreturn; + } + } + + /* Look for the datagram the fragment belongs to in the current datagram queue, + * remembering the previous in the queue for later dequeueing. */ + for (ipr = reassdatagrams; ipr != NULL; ipr = ipr->next) { + /* Check if the incoming fragment matches the one currently present + in the reassembly buffer. If so, we proceed with copying the + fragment into the buffer. */ + if (IP_ADDRESSES_AND_ID_MATCH(&ipr->iphdr, fraghdr)) { + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: matching previous fragment ID=%"X16_F"\n", + ntohs(IPH_ID(fraghdr)))); + IPFRAG_STATS_INC(ip_frag.cachehit); + break; + } + ipr_prev = ipr; + } + + if (ipr == NULL) { + /* Enqueue a new datagram into the datagram queue */ + ipr = ip_reass_enqueue_new_datagram(fraghdr, clen); + /* Bail if unable to enqueue */ + if(ipr == NULL) { + goto nullreturn; + } + } else { + if (((ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) == 0) && + ((ntohs(IPH_OFFSET(&ipr->iphdr)) & IP_OFFMASK) != 0)) { + /* ipr->iphdr is not the header from the first fragment, but fraghdr is + * -> copy fraghdr into ipr->iphdr since we want to have the header + * of the first fragment (for ICMP time exceeded and later, for copying + * all options, if supported)*/ + SMEMCPY(&ipr->iphdr, fraghdr, IP_HLEN); + } + } + /* Track the current number of pbufs current 'in-flight', in order to limit + the number of fragments that may be enqueued at any one time */ + ip_reass_pbufcount += clen; + + /* At this point, we have either created a new entry or pointing + * to an existing one */ + + /* check for 'no more fragments', and update queue entry*/ + if ((ntohs(IPH_OFFSET(fraghdr)) & IP_MF) == 0) { + ipr->flags |= IP_REASS_FLAG_LASTFRAG; + ipr->datagram_len = offset + len; + LWIP_DEBUGF(IP_REASS_DEBUG, + ("ip_reass: last fragment seen, total len %"S16_F"\n", + ipr->datagram_len)); + } + /* find the right place to insert this pbuf */ + /* @todo: trim pbufs if fragments are overlapping */ + if (ip_reass_chain_frag_into_datagram_and_validate(ipr, p)) { + /* the totally last fragment (flag more fragments = 0) was received at least + * once AND all fragments are received */ + ipr->datagram_len += IP_HLEN; + + /* save the second pbuf before copying the header over the pointer */ + r = ((struct ip_reass_helper*)ipr->p->payload)->next_pbuf; + + /* copy the original ip header back to the first pbuf */ + fraghdr = (struct ip_hdr*)(ipr->p->payload); + SMEMCPY(fraghdr, &ipr->iphdr, IP_HLEN); + IPH_LEN_SET(fraghdr, htons(ipr->datagram_len)); + IPH_OFFSET_SET(fraghdr, 0); + IPH_CHKSUM_SET(fraghdr, 0); + /* @todo: do we need to set calculate the correct checksum? */ + IPH_CHKSUM_SET(fraghdr, inet_chksum(fraghdr, IP_HLEN)); + + p = ipr->p; + + /* chain together the pbufs contained within the reass_data list. */ + while(r != NULL) { + iprh = (struct ip_reass_helper*)r->payload; + + /* hide the ip header for every succeding fragment */ + pbuf_header(r, -IP_HLEN); + pbuf_cat(p, r); + r = iprh->next_pbuf; + } + /* release the sources allocate for the fragment queue entry */ + ip_reass_dequeue_datagram(ipr, ipr_prev); + + /* and adjust the number of pbufs currently queued for reassembly. */ + ip_reass_pbufcount -= pbuf_clen(p); + + /* Return the pbuf chain */ + return p; + } + /* the datagram is not (yet?) reassembled completely */ + LWIP_DEBUGF(IP_REASS_DEBUG,("ip_reass_pbufcount: %d out\n", ip_reass_pbufcount)); + return NULL; + +nullreturn: + LWIP_DEBUGF(IP_REASS_DEBUG,("ip_reass: nullreturn\n")); + IPFRAG_STATS_INC(ip_frag.drop); + pbuf_free(p); + return NULL; +} +#endif /* IP_REASSEMBLY */ + +#if IP_FRAG +#if IP_FRAG_USES_STATIC_BUF +static u8_t buf[LWIP_MEM_ALIGN_SIZE(IP_FRAG_MAX_MTU + MEM_ALIGNMENT - 1)]; +#endif /* IP_FRAG_USES_STATIC_BUF */ + +/** + * Fragment an IP datagram if too large for the netif. + * + * Chop the datagram in MTU sized chunks and send them in order + * by using a fixed size static memory buffer (PBUF_REF) or + * point PBUF_REFs into p (depending on IP_FRAG_USES_STATIC_BUF). + * + * @param p ip packet to send + * @param netif the netif on which to send + * @param dest destination ip address to which to send + * + * @return ERR_OK if sent successfully, err_t otherwise + */ +err_t +ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest) +{ + struct pbuf *rambuf; +#if IP_FRAG_USES_STATIC_BUF + struct pbuf *header; +#else + struct pbuf *newpbuf; + struct ip_hdr *original_iphdr; +#endif + struct ip_hdr *iphdr; + u16_t nfb; + u16_t left, cop; + u16_t mtu = netif->mtu; + u16_t ofo, omf; + u16_t last; + u16_t poff = IP_HLEN; + u16_t tmp; +#if !IP_FRAG_USES_STATIC_BUF + u16_t newpbuflen = 0; + u16_t left_to_copy; +#endif + + /* Get a RAM based MTU sized pbuf */ +#if IP_FRAG_USES_STATIC_BUF + /* When using a static buffer, we use a PBUF_REF, which we will + * use to reference the packet (without link header). + * Layer and length is irrelevant. + */ + rambuf = pbuf_alloc(PBUF_LINK, 0, PBUF_REF); + if (rambuf == NULL) { + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_frag: pbuf_alloc(PBUF_LINK, 0, PBUF_REF) failed\n")); + return ERR_MEM; + } + rambuf->tot_len = rambuf->len = mtu; + rambuf->payload = LWIP_MEM_ALIGN((void *)buf); + + /* Copy the IP header in it */ + iphdr = rambuf->payload; + SMEMCPY(iphdr, p->payload, IP_HLEN); +#else /* IP_FRAG_USES_STATIC_BUF */ + original_iphdr = p->payload; + iphdr = original_iphdr; +#endif /* IP_FRAG_USES_STATIC_BUF */ + + /* Save original offset */ + tmp = ntohs(IPH_OFFSET(iphdr)); + ofo = tmp & IP_OFFMASK; + omf = tmp & IP_MF; + + left = p->tot_len - IP_HLEN; + + nfb = (mtu - IP_HLEN) / 8; + + while (left) { + last = (left <= mtu - IP_HLEN); + + /* Set new offset and MF flag */ + tmp = omf | (IP_OFFMASK & (ofo)); + if (!last) + tmp = tmp | IP_MF; + + /* Fill this fragment */ + cop = last ? left : nfb * 8; + +#if IP_FRAG_USES_STATIC_BUF + poff += pbuf_copy_partial(p, (u8_t*)iphdr + IP_HLEN, cop, poff); +#else /* IP_FRAG_USES_STATIC_BUF */ + /* When not using a static buffer, create a chain of pbufs. + * The first will be a PBUF_RAM holding the link and IP header. + * The rest will be PBUF_REFs mirroring the pbuf chain to be fragged, + * but limited to the size of an mtu. + */ + rambuf = pbuf_alloc(PBUF_LINK, IP_HLEN, PBUF_RAM); + if (rambuf == NULL) { + return ERR_MEM; + } + LWIP_ASSERT("this needs a pbuf in one piece!", + (p->len >= (IP_HLEN))); + SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN); + iphdr = rambuf->payload; + + /* Can just adjust p directly for needed offset. */ + p->payload = (u8_t *)p->payload + poff; + p->len -= poff; + + left_to_copy = cop; + while (left_to_copy) { + newpbuflen = (left_to_copy < p->len) ? left_to_copy : p->len; + /* Is this pbuf already empty? */ + if (!newpbuflen) { + p = p->next; + continue; + } + newpbuf = pbuf_alloc(PBUF_RAW, 0, PBUF_REF); + if (newpbuf == NULL) { + pbuf_free(rambuf); + return ERR_MEM; + } + /* Mirror this pbuf, although we might not need all of it. */ + newpbuf->payload = p->payload; + newpbuf->len = newpbuf->tot_len = newpbuflen; + /* Add it to end of rambuf's chain, but using pbuf_cat, not pbuf_chain + * so that it is removed when pbuf_dechain is later called on rambuf. + */ + pbuf_cat(rambuf, newpbuf); + left_to_copy -= newpbuflen; + if (left_to_copy) + p = p->next; + } + poff = newpbuflen; +#endif /* IP_FRAG_USES_STATIC_BUF */ + + /* Correct header */ + IPH_OFFSET_SET(iphdr, htons(tmp)); + IPH_LEN_SET(iphdr, htons(cop + IP_HLEN)); + IPH_CHKSUM_SET(iphdr, 0); + IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN)); + +#if IP_FRAG_USES_STATIC_BUF + if (last) + pbuf_realloc(rambuf, left + IP_HLEN); + + /* This part is ugly: we alloc a RAM based pbuf for + * the link level header for each chunk and then + * free it.A PBUF_ROM style pbuf for which pbuf_header + * worked would make things simpler. + */ + header = pbuf_alloc(PBUF_LINK, 0, PBUF_RAM); + if (header != NULL) { + pbuf_chain(header, rambuf); + netif->output(netif, header, dest); + IPFRAG_STATS_INC(ip_frag.xmit); + snmp_inc_ipfragcreates(); + pbuf_free(header); + } else { + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_frag: pbuf_alloc() for header failed\n")); + pbuf_free(rambuf); + return ERR_MEM; + } +#else /* IP_FRAG_USES_STATIC_BUF */ + /* No need for separate header pbuf - we allowed room for it in rambuf + * when allocated. + */ + netif->output(netif, rambuf, dest); + IPFRAG_STATS_INC(ip_frag.xmit); + + /* Unfortunately we can't reuse rambuf - the hardware may still be + * using the buffer. Instead we free it (and the ensuing chain) and + * recreate it next time round the loop. If we're lucky the hardware + * will have already sent the packet, the free will really free, and + * there will be zero memory penalty. + */ + + pbuf_free(rambuf); +#endif /* IP_FRAG_USES_STATIC_BUF */ + left -= cop; + ofo += nfb; + } +#if IP_FRAG_USES_STATIC_BUF + pbuf_free(rambuf); +#endif /* IP_FRAG_USES_STATIC_BUF */ + snmp_inc_ipfragoks(); + return ERR_OK; +} +#endif /* IP_FRAG */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/core/ipv6/README b/component/common/network/lwip/lwip_v1.3.2/src/core/ipv6/README new file mode 100644 index 0000000..3620004 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/core/ipv6/README @@ -0,0 +1 @@ +IPv6 support in lwIP is very experimental. diff --git a/component/common/network/lwip/lwip_v1.3.2/src/core/ipv6/icmp6.c b/component/common/network/lwip/lwip_v1.3.2/src/core/ipv6/icmp6.c new file mode 100644 index 0000000..4fcc895 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/core/ipv6/icmp6.c @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/* Some ICMP messages should be passed to the transport protocols. This + is not implemented. */ + +#include "lwip/opt.h" + +#if LWIP_ICMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/icmp.h" +#include "lwip/inet.h" +#include "lwip/ip.h" +#include "lwip/def.h" +#include "lwip/stats.h" + +void +icmp_input(struct pbuf *p, struct netif *inp) +{ + u8_t type; + struct icmp_echo_hdr *iecho; + struct ip_hdr *iphdr; + struct ip_addr tmpaddr; + + ICMP_STATS_INC(icmp.recv); + + /* TODO: check length before accessing payload! */ + + type = ((u8_t *)p->payload)[0]; + + switch (type) { + case ICMP6_ECHO: + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ping\n")); + + if (p->tot_len < sizeof(struct icmp_echo_hdr)) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n")); + + pbuf_free(p); + ICMP_STATS_INC(icmp.lenerr); + return; + } + iecho = p->payload; + iphdr = (struct ip_hdr *)((u8_t *)p->payload - IP_HLEN); + if (inet_chksum_pbuf(p) != 0) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo (%"X16_F")\n", inet_chksum_pseudo(p, &(iphdr->src), &(iphdr->dest), IP_PROTO_ICMP, p->tot_len))); + ICMP_STATS_INC(icmp.chkerr); + /* return;*/ + } + LWIP_DEBUGF(ICMP_DEBUG, ("icmp: p->len %"S16_F" p->tot_len %"S16_F"\n", p->len, p->tot_len)); + ip_addr_set(&tmpaddr, &(iphdr->src)); + ip_addr_set(&(iphdr->src), &(iphdr->dest)); + ip_addr_set(&(iphdr->dest), &tmpaddr); + iecho->type = ICMP6_ER; + /* adjust the checksum */ + if (iecho->chksum >= htons(0xffff - (ICMP6_ECHO << 8))) { + iecho->chksum += htons(ICMP6_ECHO << 8) + 1; + } else { + iecho->chksum += htons(ICMP6_ECHO << 8); + } + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo (%"X16_F")\n", inet_chksum_pseudo(p, &(iphdr->src), &(iphdr->dest), IP_PROTO_ICMP, p->tot_len))); + ICMP_STATS_INC(icmp.xmit); + + /* LWIP_DEBUGF("icmp: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len);*/ + ip_output_if (p, &(iphdr->src), IP_HDRINCL, + iphdr->hoplim, IP_PROTO_ICMP, inp); + break; + default: + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %"S16_F" not supported.\n", (s16_t)type)); + ICMP_STATS_INC(icmp.proterr); + ICMP_STATS_INC(icmp.drop); + } + + pbuf_free(p); +} + +void +icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t) +{ + struct pbuf *q; + struct ip_hdr *iphdr; + struct icmp_dur_hdr *idur; + + /* @todo: can this be PBUF_LINK instead of PBUF_IP? */ + q = pbuf_alloc(PBUF_IP, 8 + IP_HLEN + 8, PBUF_RAM); + /* ICMP header + IP header + 8 bytes of data */ + if (q == NULL) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_dest_unreach: failed to allocate pbuf for ICMP packet.\n")); + pbuf_free(p); + return; + } + LWIP_ASSERT("check that first pbuf can hold icmp message", + (q->len >= (8 + IP_HLEN + 8))); + + iphdr = p->payload; + + idur = q->payload; + idur->type = (u8_t)ICMP6_DUR; + idur->icode = (u8_t)t; + + SMEMCPY((u8_t *)q->payload + 8, p->payload, IP_HLEN + 8); + + /* calculate checksum */ + idur->chksum = 0; + idur->chksum = inet_chksum(idur, q->len); + ICMP_STATS_INC(icmp.xmit); + + ip_output(q, NULL, + (struct ip_addr *)&(iphdr->src), ICMP_TTL, IP_PROTO_ICMP); + pbuf_free(q); +} + +void +icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t) +{ + struct pbuf *q; + struct ip_hdr *iphdr; + struct icmp_te_hdr *tehdr; + + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded\n")); + + /* @todo: can this be PBUF_LINK instead of PBUF_IP? */ + q = pbuf_alloc(PBUF_IP, 8 + IP_HLEN + 8, PBUF_RAM); + /* ICMP header + IP header + 8 bytes of data */ + if (q == NULL) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_dest_unreach: failed to allocate pbuf for ICMP packet.\n")); + pbuf_free(p); + return; + } + LWIP_ASSERT("check that first pbuf can hold icmp message", + (q->len >= (8 + IP_HLEN + 8))); + + iphdr = p->payload; + + tehdr = q->payload; + tehdr->type = (u8_t)ICMP6_TE; + tehdr->icode = (u8_t)t; + + /* copy fields from original packet */ + SMEMCPY((u8_t *)q->payload + 8, (u8_t *)p->payload, IP_HLEN + 8); + + /* calculate checksum */ + tehdr->chksum = 0; + tehdr->chksum = inet_chksum(tehdr, q->len); + ICMP_STATS_INC(icmp.xmit); + ip_output(q, NULL, + (struct ip_addr *)&(iphdr->src), ICMP_TTL, IP_PROTO_ICMP); + pbuf_free(q); +} + +#endif /* LWIP_ICMP */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/core/ipv6/inet6.c b/component/common/network/lwip/lwip_v1.3.2/src/core/ipv6/inet6.c new file mode 100644 index 0000000..c3de85c --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/core/ipv6/inet6.c @@ -0,0 +1,163 @@ +/** + * @file + * Functions common to all TCP/IPv6 modules, such as the Internet checksum and the + * byte order functions. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/def.h" +#include "lwip/inet.h" + +/* chksum: + * + * Sums up all 16 bit words in a memory portion. Also includes any odd byte. + * This function is used by the other checksum functions. + * + * For now, this is not optimized. Must be optimized for the particular processor + * arcitecture on which it is to run. Preferebly coded in assembler. + */ + +static u32_t +chksum(void *dataptr, u16_t len) +{ + u16_t *sdataptr = dataptr; + u32_t acc; + + + for(acc = 0; len > 1; len -= 2) { + acc += *sdataptr++; + } + + /* add up any odd byte */ + if (len == 1) { + acc += htons((u16_t)(*(u8_t *)dataptr) << 8); + } + + return acc; + +} + +/* inet_chksum_pseudo: + * + * Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain. + */ + +u16_t +inet_chksum_pseudo(struct pbuf *p, + struct ip_addr *src, struct ip_addr *dest, + u8_t proto, u32_t proto_len) +{ + u32_t acc; + struct pbuf *q; + u8_t swapped, i; + + acc = 0; + swapped = 0; + for(q = p; q != NULL; q = q->next) { + acc += chksum(q->payload, q->len); + while (acc >> 16) { + acc = (acc & 0xffff) + (acc >> 16); + } + if (q->len % 2 != 0) { + swapped = 1 - swapped; + acc = ((acc & 0xff) << 8) | ((acc & 0xff00) >> 8); + } + } + + if (swapped) { + acc = ((acc & 0xff) << 8) | ((acc & 0xff00) >> 8); + } + + for(i = 0; i < 8; i++) { + acc += ((u16_t *)src->addr)[i] & 0xffff; + acc += ((u16_t *)dest->addr)[i] & 0xffff; + while (acc >> 16) { + acc = (acc & 0xffff) + (acc >> 16); + } + } + acc += (u16_t)htons((u16_t)proto); + acc += ((u16_t *)&proto_len)[0] & 0xffff; + acc += ((u16_t *)&proto_len)[1] & 0xffff; + + while (acc >> 16) { + acc = (acc & 0xffff) + (acc >> 16); + } + return ~(acc & 0xffff); +} + +/* inet_chksum: + * + * Calculates the Internet checksum over a portion of memory. Used primarely for IP + * and ICMP. + */ + +u16_t +inet_chksum(void *dataptr, u16_t len) +{ + u32_t acc, sum; + + acc = chksum(dataptr, len); + sum = (acc & 0xffff) + (acc >> 16); + sum += (sum >> 16); + return ~(sum & 0xffff); +} + +u16_t +inet_chksum_pbuf(struct pbuf *p) +{ + u32_t acc; + struct pbuf *q; + u8_t swapped; + + acc = 0; + swapped = 0; + for(q = p; q != NULL; q = q->next) { + acc += chksum(q->payload, q->len); + while (acc >> 16) { + acc = (acc & 0xffff) + (acc >> 16); + } + if (q->len % 2 != 0) { + swapped = 1 - swapped; + acc = (acc & 0xff << 8) | (acc & 0xff00 >> 8); + } + } + + if (swapped) { + acc = ((acc & 0xff) << 8) | ((acc & 0xff00) >> 8); + } + return ~(acc & 0xffff); +} diff --git a/component/common/network/lwip/lwip_v1.3.2/src/core/ipv6/ip6.c b/component/common/network/lwip/lwip_v1.3.2/src/core/ipv6/ip6.c new file mode 100644 index 0000000..7e43420 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/core/ipv6/ip6.c @@ -0,0 +1,397 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + + + +/* ip.c + * + * This is the code for the IP layer for IPv6. + * + */ + + +#include "lwip/opt.h" + +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/ip.h" +#include "lwip/inet.h" +#include "lwip/netif.h" +#include "lwip/icmp.h" +#include "lwip/udp.h" +#include "lwip/tcp.h" + +#include "lwip/stats.h" + +#include "arch/perf.h" + +/* ip_init: + * + * Initializes the IP layer. + */ + +void +ip_init(void) +{ +} + +/* ip_route: + * + * Finds the appropriate network interface for a given IP address. It searches the + * list of network interfaces linearly. A match is found if the masked IP address of + * the network interface equals the masked IP address given to the function. + */ + +struct netif * +ip_route(struct ip_addr *dest) +{ + struct netif *netif; + + for(netif = netif_list; netif != NULL; netif = netif->next) { + if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) { + return netif; + } + } + + return netif_default; +} + +/* ip_forward: + * + * Forwards an IP packet. It finds an appropriate route for the packet, decrements + * the TTL value of the packet, adjusts the checksum and outputs the packet on the + * appropriate interface. + */ + +static void +ip_forward(struct pbuf *p, struct ip_hdr *iphdr) +{ + struct netif *netif; + + PERF_START; + + if ((netif = ip_route((struct ip_addr *)&(iphdr->dest))) == NULL) { + + LWIP_DEBUGF(IP_DEBUG, ("ip_input: no forwarding route found for ")); +#if IP_DEBUG + ip_addr_debug_print(IP_DEBUG, ((struct ip_addr *)&(iphdr->dest))); +#endif /* IP_DEBUG */ + LWIP_DEBUGF(IP_DEBUG, ("\n")); + pbuf_free(p); + return; + } + /* Decrement TTL and send ICMP if ttl == 0. */ + if (--iphdr->hoplim == 0) { +#if LWIP_ICMP + /* Don't send ICMP messages in response to ICMP messages */ + if (iphdr->nexthdr != IP_PROTO_ICMP) { + icmp_time_exceeded(p, ICMP_TE_TTL); + } +#endif /* LWIP_ICMP */ + pbuf_free(p); + return; + } + + /* Incremental update of the IP checksum. */ + /* if (iphdr->chksum >= htons(0xffff - 0x100)) { + iphdr->chksum += htons(0x100) + 1; + } else { + iphdr->chksum += htons(0x100); + }*/ + + + LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to ")); +#if IP_DEBUG + ip_addr_debug_print(IP_DEBUG, ((struct ip_addr *)&(iphdr->dest))); +#endif /* IP_DEBUG */ + LWIP_DEBUGF(IP_DEBUG, ("\n")); + + IP_STATS_INC(ip.fw); + IP_STATS_INC(ip.xmit); + + PERF_STOP("ip_forward"); + + netif->output(netif, p, (struct ip_addr *)&(iphdr->dest)); +} + +/* ip_input: + * + * This function is called by the network interface device driver when an IP packet is + * received. The function does the basic checks of the IP header such as packet size + * being at least larger than the header size etc. If the packet was not destined for + * us, the packet is forwarded (using ip_forward). The IP checksum is always checked. + * + * Finally, the packet is sent to the upper layer protocol input function. + */ + +void +ip_input(struct pbuf *p, struct netif *inp) { + struct ip_hdr *iphdr; + struct netif *netif; + + + PERF_START; + +#if IP_DEBUG + ip_debug_print(p); +#endif /* IP_DEBUG */ + + + IP_STATS_INC(ip.recv); + + /* identify the IP header */ + iphdr = p->payload; + + + if (iphdr->v != 6) { + LWIP_DEBUGF(IP_DEBUG, ("IP packet dropped due to bad version number\n")); +#if IP_DEBUG + ip_debug_print(p); +#endif /* IP_DEBUG */ + pbuf_free(p); + IP_STATS_INC(ip.err); + IP_STATS_INC(ip.drop); + return; + } + + /* is this packet for us? */ + for(netif = netif_list; netif != NULL; netif = netif->next) { +#if IP_DEBUG + LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest ")); + ip_addr_debug_print(IP_DEBUG, ((struct ip_addr *)&(iphdr->dest))); + LWIP_DEBUGF(IP_DEBUG, ("netif->ip_addr ")); + ip_addr_debug_print(IP_DEBUG, ((struct ip_addr *)&(iphdr->dest))); + LWIP_DEBUGF(IP_DEBUG, ("\n")); +#endif /* IP_DEBUG */ + if (ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr))) { + break; + } + } + + + if (netif == NULL) { + /* packet not for us, route or discard */ +#if IP_FORWARD + ip_forward(p, iphdr); +#endif + pbuf_free(p); + return; + } + + pbuf_realloc(p, IP_HLEN + ntohs(iphdr->len)); + + /* send to upper layers */ +#if IP_DEBUG + /* LWIP_DEBUGF("ip_input: \n"); + ip_debug_print(p); + LWIP_DEBUGF("ip_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len);*/ +#endif /* IP_DEBUG */ + + if(pbuf_header(p, -IP_HLEN)) { + LWIP_ASSERT("Can't move over header in packet", 0); + return; + } + + switch (iphdr->nexthdr) { + case IP_PROTO_UDP: + udp_input(p, inp); + break; + case IP_PROTO_TCP: + tcp_input(p, inp); + break; +#if LWIP_ICMP + case IP_PROTO_ICMP: + icmp_input(p, inp); + break; +#endif /* LWIP_ICMP */ + default: +#if LWIP_ICMP + /* send ICMP destination protocol unreachable */ + icmp_dest_unreach(p, ICMP_DUR_PROTO); +#endif /* LWIP_ICMP */ + pbuf_free(p); + LWIP_DEBUGF(IP_DEBUG, ("Unsupported transport protocol %"U16_F"\n", + iphdr->nexthdr)); + + IP_STATS_INC(ip.proterr); + IP_STATS_INC(ip.drop); + } + PERF_STOP("ip_input"); +} + + +/* ip_output_if: + * + * Sends an IP packet on a network interface. This function constructs the IP header + * and calculates the IP header checksum. If the source IP address is NULL, + * the IP address of the outgoing network interface is filled in as source address. + */ + +err_t +ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, + u8_t ttl, + u8_t proto, struct netif *netif) +{ + struct ip_hdr *iphdr; + + PERF_START; + + LWIP_DEBUGF(IP_DEBUG, ("len %"U16_F" tot_len %"U16_F"\n", p->len, p->tot_len)); + if (pbuf_header(p, IP_HLEN)) { + LWIP_DEBUGF(IP_DEBUG, ("ip_output: not enough room for IP header in pbuf\n")); + IP_STATS_INC(ip.err); + + return ERR_BUF; + } + LWIP_DEBUGF(IP_DEBUG, ("len %"U16_F" tot_len %"U16_F"\n", p->len, p->tot_len)); + + iphdr = p->payload; + + + if (dest != IP_HDRINCL) { + LWIP_DEBUGF(IP_DEBUG, ("!IP_HDRLINCL\n")); + iphdr->hoplim = ttl; + iphdr->nexthdr = proto; + iphdr->len = htons(p->tot_len - IP_HLEN); + ip_addr_set(&(iphdr->dest), dest); + + iphdr->v = 6; + + if (ip_addr_isany(src)) { + ip_addr_set(&(iphdr->src), &(netif->ip_addr)); + } else { + ip_addr_set(&(iphdr->src), src); + } + + } else { + dest = &(iphdr->dest); + } + + IP_STATS_INC(ip.xmit); + + LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c (len %"U16_F")\n", netif->name[0], netif->name[1], p->tot_len)); +#if IP_DEBUG + ip_debug_print(p); +#endif /* IP_DEBUG */ + + PERF_STOP("ip_output_if"); + return netif->output(netif, p, dest); +} + +/* ip_output: + * + * Simple interface to ip_output_if. It finds the outgoing network interface and + * calls upon ip_output_if to do the actual work. + */ + +err_t +ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, + u8_t ttl, u8_t proto) +{ + struct netif *netif; + if ((netif = ip_route(dest)) == NULL) { + LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to 0x%"X32_F"\n", dest->addr)); + IP_STATS_INC(ip.rterr); + return ERR_RTE; + } + + return ip_output_if (p, src, dest, ttl, proto, netif); +} + +#if LWIP_NETIF_HWADDRHINT +err_t +ip_output_hinted(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, + u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint) +{ + struct netif *netif; + err_t err; + + if ((netif = ip_route(dest)) == NULL) { + LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to 0x%"X32_F"\n", dest->addr)); + IP_STATS_INC(ip.rterr); + return ERR_RTE; + } + + netif->addr_hint = addr_hint; + err = ip_output_if(p, src, dest, ttl, tos, proto, netif); + netif->addr_hint = NULL; + + return err; +} +#endif /* LWIP_NETIF_HWADDRHINT*/ + +#if IP_DEBUG +void +ip_debug_print(struct pbuf *p) +{ + struct ip_hdr *iphdr = p->payload; + + LWIP_DEBUGF(IP_DEBUG, ("IP header:\n")); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("|%2"S16_F" | %"X16_F"%"X16_F" | %"X16_F"%"X16_F" | (v, traffic class, flow label)\n", + iphdr->v, + iphdr->tclass1, iphdr->tclass2, + iphdr->flow1, iphdr->flow2)); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("| %5"U16_F" | %2"U16_F" | %2"U16_F" | (len, nexthdr, hoplim)\n", + ntohs(iphdr->len), + iphdr->nexthdr, + iphdr->hoplim)); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (src)\n", + (ntohl(iphdr->src.addr[0]) >> 16) & 0xffff, + ntohl(iphdr->src.addr[0]) & 0xffff)); + LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (src)\n", + (ntohl(iphdr->src.addr[1]) >> 16) & 0xffff, + ntohl(iphdr->src.addr[1]) & 0xffff)); + LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (src)\n", + (ntohl(iphdr->src.addr[2]) >> 16) & 0xffff, + ntohl(iphdr->src.addr[2]) & 0xffff)); + LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (src)\n", + (ntohl(iphdr->src.addr[3]) >> 16) & 0xffff, + ntohl(iphdr->src.addr[3]) & 0xffff)); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (dest)\n", + (ntohl(iphdr->dest.addr[0]) >> 16) & 0xffff, + ntohl(iphdr->dest.addr[0]) & 0xffff)); + LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (dest)\n", + (ntohl(iphdr->dest.addr[1]) >> 16) & 0xffff, + ntohl(iphdr->dest.addr[1]) & 0xffff)); + LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (dest)\n", + (ntohl(iphdr->dest.addr[2]) >> 16) & 0xffff, + ntohl(iphdr->dest.addr[2]) & 0xffff)); + LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (dest)\n", + (ntohl(iphdr->dest.addr[3]) >> 16) & 0xffff, + ntohl(iphdr->dest.addr[3]) & 0xffff)); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); +} +#endif /* IP_DEBUG */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/core/ipv6/ip6_addr.c b/component/common/network/lwip/lwip_v1.3.2/src/core/ipv6/ip6_addr.c new file mode 100644 index 0000000..2da6cea --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/core/ipv6/ip6_addr.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" +#include "lwip/ip_addr.h" +#include "lwip/inet.h" + +u8_t +ip_addr_netcmp(struct ip_addr *addr1, struct ip_addr *addr2, + struct ip_addr *mask) +{ + return((addr1->addr[0] & mask->addr[0]) == (addr2->addr[0] & mask->addr[0]) && + (addr1->addr[1] & mask->addr[1]) == (addr2->addr[1] & mask->addr[1]) && + (addr1->addr[2] & mask->addr[2]) == (addr2->addr[2] & mask->addr[2]) && + (addr1->addr[3] & mask->addr[3]) == (addr2->addr[3] & mask->addr[3])); + +} + +u8_t +ip_addr_cmp(struct ip_addr *addr1, struct ip_addr *addr2) +{ + return(addr1->addr[0] == addr2->addr[0] && + addr1->addr[1] == addr2->addr[1] && + addr1->addr[2] == addr2->addr[2] && + addr1->addr[3] == addr2->addr[3]); +} + +void +ip_addr_set(struct ip_addr *dest, struct ip_addr *src) +{ + SMEMCPY(dest, src, sizeof(struct ip_addr)); + /* dest->addr[0] = src->addr[0]; + dest->addr[1] = src->addr[1]; + dest->addr[2] = src->addr[2]; + dest->addr[3] = src->addr[3];*/ +} + +u8_t +ip_addr_isany(struct ip_addr *addr) +{ + if (addr == NULL) return 1; + return((addr->addr[0] | addr->addr[1] | addr->addr[2] | addr->addr[3]) == 0); +} diff --git a/component/common/network/lwip/lwip_v1.3.2/src/core/mem.c b/component/common/network/lwip/lwip_v1.3.2/src/core/mem.c new file mode 100644 index 0000000..008c2c9 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/core/mem.c @@ -0,0 +1,633 @@ +/** + * @file + * Dynamic memory manager + * + * This is a lightweight replacement for the standard C library malloc(). + * + * If you want to use the standard C library malloc() instead, define + * MEM_LIBC_MALLOC to 1 in your lwipopts.h + * + * To let mem_malloc() use pools (prevents fragmentation and is much faster than + * a heap but might waste some memory), define MEM_USE_POOLS to 1, define + * MEM_USE_CUSTOM_POOLS to 1 and create a file "lwippools.h" that includes a list + * of pools like this (more pools can be added between _START and _END): + * + * Define three pools with sizes 256, 512, and 1512 bytes + * LWIP_MALLOC_MEMPOOL_START + * LWIP_MALLOC_MEMPOOL(20, 256) + * LWIP_MALLOC_MEMPOOL(10, 512) + * LWIP_MALLOC_MEMPOOL(5, 1512) + * LWIP_MALLOC_MEMPOOL_END + **/ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * Simon Goldschmidt + * + */ + +#include "lwip/opt.h" + +#if !MEM_LIBC_MALLOC /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/sys.h" +#include "lwip/stats.h" + +#include + +#if MEM_USE_POOLS +/* lwIP head implemented with different sized pools */ + +/** + * Allocate memory: determine the smallest pool that is big enough + * to contain an element of 'size' and get an element from that pool. + * + * @param size the size in bytes of the memory needed + * @return a pointer to the allocated memory or NULL if the pool is empty + */ +void * +mem_malloc(mem_size_t size) +{ + struct memp_malloc_helper *element; + memp_t poolnr; + mem_size_t required_size = size + sizeof(struct memp_malloc_helper); + + for (poolnr = MEMP_POOL_FIRST; poolnr <= MEMP_POOL_LAST; poolnr++) { +#if MEM_USE_POOLS_TRY_BIGGER_POOL +again: +#endif /* MEM_USE_POOLS_TRY_BIGGER_POOL */ + /* is this pool big enough to hold an element of the required size + plus a struct memp_malloc_helper that saves the pool this element came from? */ + if (required_size <= memp_sizes[poolnr]) { + break; + } + } + if (poolnr > MEMP_POOL_LAST) { + LWIP_ASSERT("mem_malloc(): no pool is that big!", 0); + return NULL; + } + element = (struct memp_malloc_helper*)memp_malloc(poolnr); + if (element == NULL) { + /* No need to DEBUGF or ASSERT: This error is already + taken care of in memp.c */ +#if MEM_USE_POOLS_TRY_BIGGER_POOL + /** Try a bigger pool if this one is empty! */ + if (poolnr < MEMP_POOL_LAST) { + poolnr++; + goto again; + } +#endif /* MEM_USE_POOLS_TRY_BIGGER_POOL */ + return NULL; + } + + /* save the pool number this element came from */ + element->poolnr = poolnr; + /* and return a pointer to the memory directly after the struct memp_malloc_helper */ + element++; + + return element; +} + +/** + * Free memory previously allocated by mem_malloc. Loads the pool number + * and calls memp_free with that pool number to put the element back into + * its pool + * + * @param rmem the memory element to free + */ +void +mem_free(void *rmem) +{ + struct memp_malloc_helper *hmem = (struct memp_malloc_helper*)rmem; + + LWIP_ASSERT("rmem != NULL", (rmem != NULL)); + LWIP_ASSERT("rmem == MEM_ALIGN(rmem)", (rmem == LWIP_MEM_ALIGN(rmem))); + + /* get the original struct memp_malloc_helper */ + hmem--; + + LWIP_ASSERT("hmem != NULL", (hmem != NULL)); + LWIP_ASSERT("hmem == MEM_ALIGN(hmem)", (hmem == LWIP_MEM_ALIGN(hmem))); + LWIP_ASSERT("hmem->poolnr < MEMP_MAX", (hmem->poolnr < MEMP_MAX)); + + /* and put it in the pool we saved earlier */ + memp_free(hmem->poolnr, hmem); +} + +#else /* MEM_USE_POOLS */ +/* lwIP replacement for your libc malloc() */ + +/** + * The heap is made up as a list of structs of this type. + * This does not have to be aligned since for getting its size, + * we only use the macro SIZEOF_STRUCT_MEM, which automatically alignes. + */ +struct mem { + /** index (-> ram[next]) of the next struct */ + mem_size_t next; + /** index (-> ram[next]) of the next struct */ + mem_size_t prev; + /** 1: this area is used; 0: this area is unused */ + u8_t used; +}; + +/** All allocated blocks will be MIN_SIZE bytes big, at least! + * MIN_SIZE can be overridden to suit your needs. Smaller values save space, + * larger values could prevent too small blocks to fragment the RAM too much. */ +#ifndef MIN_SIZE +#define MIN_SIZE 12 +#endif /* MIN_SIZE */ +/* some alignment macros: we define them here for better source code layout */ +#define MIN_SIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(MIN_SIZE) +#define SIZEOF_STRUCT_MEM LWIP_MEM_ALIGN_SIZE(sizeof(struct mem)) +#define MEM_SIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(MEM_SIZE) + +/** the heap. we need one struct mem at the end and some room for alignment */ +static u8_t ram_heap[MEM_SIZE_ALIGNED + (2*SIZEOF_STRUCT_MEM) + MEM_ALIGNMENT]; +/** pointer to the heap (ram_heap): for alignment, ram is now a pointer instead of an array */ +static u8_t *ram; +/** the last entry, always unused! */ +static struct mem *ram_end; +/** pointer to the lowest free block, this is used for faster search */ +static struct mem *lfree; + +/** concurrent access protection */ +static sys_sem_t mem_sem; + +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + +static volatile u8_t mem_free_count; + +/* Allow mem_free from other (e.g. interrupt) context */ +#define LWIP_MEM_FREE_DECL_PROTECT() SYS_ARCH_DECL_PROTECT(lev_free) +#define LWIP_MEM_FREE_PROTECT() SYS_ARCH_PROTECT(lev_free) +#define LWIP_MEM_FREE_UNPROTECT() SYS_ARCH_UNPROTECT(lev_free) +#define LWIP_MEM_ALLOC_DECL_PROTECT() SYS_ARCH_DECL_PROTECT(lev_alloc) +#define LWIP_MEM_ALLOC_PROTECT() SYS_ARCH_PROTECT(lev_alloc) +#define LWIP_MEM_ALLOC_UNPROTECT() SYS_ARCH_UNPROTECT(lev_alloc) + +#else /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + +/* Protect the heap only by using a semaphore */ +#define LWIP_MEM_FREE_DECL_PROTECT() +#define LWIP_MEM_FREE_PROTECT() sys_arch_sem_wait(mem_sem, 0) +#define LWIP_MEM_FREE_UNPROTECT() sys_sem_signal(mem_sem) +/* mem_malloc is protected using semaphore AND LWIP_MEM_ALLOC_PROTECT */ +#define LWIP_MEM_ALLOC_DECL_PROTECT() +#define LWIP_MEM_ALLOC_PROTECT() +#define LWIP_MEM_ALLOC_UNPROTECT() + +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + + +/** + * "Plug holes" by combining adjacent empty struct mems. + * After this function is through, there should not exist + * one empty struct mem pointing to another empty struct mem. + * + * @param mem this points to a struct mem which just has been freed + * @internal this function is only called by mem_free() and mem_realloc() + * + * This assumes access to the heap is protected by the calling function + * already. + */ +static void +plug_holes(struct mem *mem) +{ + struct mem *nmem; + struct mem *pmem; + + LWIP_ASSERT("plug_holes: mem >= ram", (u8_t *)mem >= ram); + LWIP_ASSERT("plug_holes: mem < ram_end", (u8_t *)mem < (u8_t *)ram_end); + LWIP_ASSERT("plug_holes: mem->used == 0", mem->used == 0); + + /* plug hole forward */ + LWIP_ASSERT("plug_holes: mem->next <= MEM_SIZE_ALIGNED", mem->next <= MEM_SIZE_ALIGNED); + + nmem = (struct mem *)&ram[mem->next]; + if (mem != nmem && nmem->used == 0 && (u8_t *)nmem != (u8_t *)ram_end) { + /* if mem->next is unused and not end of ram, combine mem and mem->next */ + if (lfree == nmem) { + lfree = mem; + } + mem->next = nmem->next; + ((struct mem *)&ram[nmem->next])->prev = (u8_t *)mem - ram; + } + + /* plug hole backward */ + pmem = (struct mem *)&ram[mem->prev]; + if (pmem != mem && pmem->used == 0) { + /* if mem->prev is unused, combine mem and mem->prev */ + if (lfree == mem) { + lfree = pmem; + } + pmem->next = mem->next; + ((struct mem *)&ram[mem->next])->prev = (u8_t *)pmem - ram; + } +} + +/** + * Zero the heap and initialize start, end and lowest-free + */ +void +mem_init(void) +{ + struct mem *mem; + + LWIP_ASSERT("Sanity check alignment", + (SIZEOF_STRUCT_MEM & (MEM_ALIGNMENT-1)) == 0); + + /* align the heap */ + ram = LWIP_MEM_ALIGN(ram_heap); + /* initialize the start of the heap */ + mem = (struct mem *)ram; + mem->next = MEM_SIZE_ALIGNED; + mem->prev = 0; + mem->used = 0; + /* initialize the end of the heap */ + ram_end = (struct mem *)&ram[MEM_SIZE_ALIGNED]; + ram_end->used = 1; + ram_end->next = MEM_SIZE_ALIGNED; + ram_end->prev = MEM_SIZE_ALIGNED; + + mem_sem = sys_sem_new(1); + + /* initialize the lowest-free pointer to the start of the heap */ + lfree = (struct mem *)ram; + + MEM_STATS_AVAIL(avail, MEM_SIZE_ALIGNED); +} + +/** + * Put a struct mem back on the heap + * + * @param rmem is the data portion of a struct mem as returned by a previous + * call to mem_malloc() + */ +void +mem_free(void *rmem) +{ + struct mem *mem; + LWIP_MEM_FREE_DECL_PROTECT(); + + if (rmem == NULL) { + LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("mem_free(p == NULL) was called.\n")); + return; + } + LWIP_ASSERT("mem_free: sanity check alignment", (((mem_ptr_t)rmem) & (MEM_ALIGNMENT-1)) == 0); + + LWIP_ASSERT("mem_free: legal memory", (u8_t *)rmem >= (u8_t *)ram && + (u8_t *)rmem < (u8_t *)ram_end); + + if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) { + SYS_ARCH_DECL_PROTECT(lev); + LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_free: illegal memory\n")); + /* protect mem stats from concurrent access */ + SYS_ARCH_PROTECT(lev); + MEM_STATS_INC(illegal); + SYS_ARCH_UNPROTECT(lev); + return; + } + /* protect the heap from concurrent access */ + LWIP_MEM_FREE_PROTECT(); + /* Get the corresponding struct mem ... */ + mem = (struct mem *)((u8_t *)rmem - SIZEOF_STRUCT_MEM); + /* ... which has to be in a used state ... */ + LWIP_ASSERT("mem_free: mem->used", mem->used); + /* ... and is now unused. */ + mem->used = 0; + + if (mem < lfree) { + /* the newly freed struct is now the lowest */ + lfree = mem; + } + + MEM_STATS_DEC_USED(used, mem->next - ((u8_t *)mem - ram)); + + /* finally, see if prev or next are free also */ + plug_holes(mem); +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + mem_free_count = 1; +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + LWIP_MEM_FREE_UNPROTECT(); +} + +/** + * In contrast to its name, mem_realloc can only shrink memory, not expand it. + * Since the only use (for now) is in pbuf_realloc (which also can only shrink), + * this shouldn't be a problem! + * + * @param rmem pointer to memory allocated by mem_malloc the is to be shrinked + * @param newsize required size after shrinking (needs to be smaller than or + * equal to the previous size) + * @return for compatibility reasons: is always == rmem, at the moment + * or NULL if newsize is > old size, in which case rmem is NOT touched + * or freed! + */ +void * +mem_realloc(void *rmem, mem_size_t newsize) +{ + mem_size_t size; + mem_size_t ptr, ptr2; + struct mem *mem, *mem2; + /* use the FREE_PROTECT here: it protects with sem OR SYS_ARCH_PROTECT */ + LWIP_MEM_FREE_DECL_PROTECT(); + + /* Expand the size of the allocated memory region so that we can + adjust for alignment. */ + newsize = LWIP_MEM_ALIGN_SIZE(newsize); + + if(newsize < MIN_SIZE_ALIGNED) { + /* every data block must be at least MIN_SIZE_ALIGNED long */ + newsize = MIN_SIZE_ALIGNED; + } + + if (newsize > MEM_SIZE_ALIGNED) { + return NULL; + } + + LWIP_ASSERT("mem_realloc: legal memory", (u8_t *)rmem >= (u8_t *)ram && + (u8_t *)rmem < (u8_t *)ram_end); + + if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) { + SYS_ARCH_DECL_PROTECT(lev); + LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_realloc: illegal memory\n")); + /* protect mem stats from concurrent access */ + SYS_ARCH_PROTECT(lev); + MEM_STATS_INC(illegal); + SYS_ARCH_UNPROTECT(lev); + return rmem; + } + /* Get the corresponding struct mem ... */ + mem = (struct mem *)((u8_t *)rmem - SIZEOF_STRUCT_MEM); + /* ... and its offset pointer */ + ptr = (u8_t *)mem - ram; + + size = mem->next - ptr - SIZEOF_STRUCT_MEM; + LWIP_ASSERT("mem_realloc can only shrink memory", newsize <= size); + if (newsize > size) { + /* not supported */ + return NULL; + } + if (newsize == size) { + /* No change in size, simply return */ + return rmem; + } + + /* protect the heap from concurrent access */ + LWIP_MEM_FREE_PROTECT(); + + MEM_STATS_DEC_USED(used, (size - newsize)); + + mem2 = (struct mem *)&ram[mem->next]; + if(mem2->used == 0) { + /* The next struct is unused, we can simply move it at little */ + mem_size_t next; + /* remember the old next pointer */ + next = mem2->next; + /* create new struct mem which is moved directly after the shrinked mem */ + ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize; + if (lfree == mem2) { + lfree = (struct mem *)&ram[ptr2]; + } + mem2 = (struct mem *)&ram[ptr2]; + mem2->used = 0; + /* restore the next pointer */ + mem2->next = next; + /* link it back to mem */ + mem2->prev = ptr; + /* link mem to it */ + mem->next = ptr2; + /* last thing to restore linked list: as we have moved mem2, + * let 'mem2->next->prev' point to mem2 again. but only if mem2->next is not + * the end of the heap */ + if (mem2->next != MEM_SIZE_ALIGNED) { + ((struct mem *)&ram[mem2->next])->prev = ptr2; + } + /* no need to plug holes, we've already done that */ + } else if (newsize + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED <= size) { + /* Next struct is used but there's room for another struct mem with + * at least MIN_SIZE_ALIGNED of data. + * Old size ('size') must be big enough to contain at least 'newsize' plus a struct mem + * ('SIZEOF_STRUCT_MEM') with some data ('MIN_SIZE_ALIGNED'). + * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty + * region that couldn't hold data, but when mem->next gets freed, + * the 2 regions would be combined, resulting in more free memory */ + ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize; + mem2 = (struct mem *)&ram[ptr2]; + if (mem2 < lfree) { + lfree = mem2; + } + mem2->used = 0; + mem2->next = mem->next; + mem2->prev = ptr; + mem->next = ptr2; + if (mem2->next != MEM_SIZE_ALIGNED) { + ((struct mem *)&ram[mem2->next])->prev = ptr2; + } + /* the original mem->next is used, so no need to plug holes! */ + } + /* else { + next struct mem is used but size between mem and mem2 is not big enough + to create another struct mem + -> don't do anyhting. + -> the remaining space stays unused since it is too small + } */ +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + mem_free_count = 1; +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + LWIP_MEM_FREE_UNPROTECT(); + return rmem; +} + +/** + * Adam's mem_malloc() plus solution for bug #17922 + * Allocate a block of memory with a minimum of 'size' bytes. + * + * @param size is the minimum size of the requested block in bytes. + * @return pointer to allocated memory or NULL if no free memory was found. + * + * Note that the returned value will always be aligned (as defined by MEM_ALIGNMENT). + */ +void * +mem_malloc(mem_size_t size) +{ + mem_size_t ptr, ptr2; + struct mem *mem, *mem2; +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + u8_t local_mem_free_count = 0; +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + LWIP_MEM_ALLOC_DECL_PROTECT(); + + if (size == 0) { + return NULL; + } + + /* Expand the size of the allocated memory region so that we can + adjust for alignment. */ + size = LWIP_MEM_ALIGN_SIZE(size); + + if(size < MIN_SIZE_ALIGNED) { + /* every data block must be at least MIN_SIZE_ALIGNED long */ + size = MIN_SIZE_ALIGNED; + } + + if (size > MEM_SIZE_ALIGNED) { + return NULL; + } + + /* protect the heap from concurrent access */ + sys_arch_sem_wait(mem_sem, 0); + LWIP_MEM_ALLOC_PROTECT(); +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + /* run as long as a mem_free disturbed mem_malloc */ + do { + local_mem_free_count = 0; +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + + /* Scan through the heap searching for a free block that is big enough, + * beginning with the lowest free block. + */ + for (ptr = (u8_t *)lfree - ram; ptr < MEM_SIZE_ALIGNED - size; + ptr = ((struct mem *)&ram[ptr])->next) { + mem = (struct mem *)&ram[ptr]; +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + mem_free_count = 0; + LWIP_MEM_ALLOC_UNPROTECT(); + /* allow mem_free to run */ + LWIP_MEM_ALLOC_PROTECT(); + if (mem_free_count != 0) { + local_mem_free_count = mem_free_count; + } + mem_free_count = 0; +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + + if ((!mem->used) && + (mem->next - (ptr + SIZEOF_STRUCT_MEM)) >= size) { + /* mem is not used and at least perfect fit is possible: + * mem->next - (ptr + SIZEOF_STRUCT_MEM) gives us the 'user data size' of mem */ + + if (mem->next - (ptr + SIZEOF_STRUCT_MEM) >= (size + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED)) { + /* (in addition to the above, we test if another struct mem (SIZEOF_STRUCT_MEM) containing + * at least MIN_SIZE_ALIGNED of data also fits in the 'user data space' of 'mem') + * -> split large block, create empty remainder, + * remainder must be large enough to contain MIN_SIZE_ALIGNED data: if + * mem->next - (ptr + (2*SIZEOF_STRUCT_MEM)) == size, + * struct mem would fit in but no data between mem2 and mem2->next + * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty + * region that couldn't hold data, but when mem->next gets freed, + * the 2 regions would be combined, resulting in more free memory + */ + ptr2 = ptr + SIZEOF_STRUCT_MEM + size; + /* create mem2 struct */ + mem2 = (struct mem *)&ram[ptr2]; + mem2->used = 0; + mem2->next = mem->next; + mem2->prev = ptr; + /* and insert it between mem and mem->next */ + mem->next = ptr2; + mem->used = 1; + + if (mem2->next != MEM_SIZE_ALIGNED) { + ((struct mem *)&ram[mem2->next])->prev = ptr2; + } + MEM_STATS_INC_USED(used, (size + SIZEOF_STRUCT_MEM)); + } else { + /* (a mem2 struct does no fit into the user data space of mem and mem->next will always + * be used at this point: if not we have 2 unused structs in a row, plug_holes should have + * take care of this). + * -> near fit or excact fit: do not split, no mem2 creation + * also can't move mem->next directly behind mem, since mem->next + * will always be used at this point! + */ + mem->used = 1; + MEM_STATS_INC_USED(used, mem->next - ((u8_t *)mem - ram)); + } + + if (mem == lfree) { + /* Find next free block after mem and update lowest free pointer */ + while (lfree->used && lfree != ram_end) { + LWIP_MEM_ALLOC_UNPROTECT(); + /* prevent high interrupt latency... */ + LWIP_MEM_ALLOC_PROTECT(); + lfree = (struct mem *)&ram[lfree->next]; + } + LWIP_ASSERT("mem_malloc: !lfree->used", ((lfree == ram_end) || (!lfree->used))); + } + LWIP_MEM_ALLOC_UNPROTECT(); + sys_sem_signal(mem_sem); + LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.", + (mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end); + LWIP_ASSERT("mem_malloc: allocated memory properly aligned.", + ((mem_ptr_t)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0); + LWIP_ASSERT("mem_malloc: sanity check alignment", + (((mem_ptr_t)mem) & (MEM_ALIGNMENT-1)) == 0); + + return (u8_t *)mem + SIZEOF_STRUCT_MEM; + } + } +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + /* if we got interrupted by a mem_free, try again */ + } while(local_mem_free_count != 0); +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("mem_malloc: could not allocate %"S16_F" bytes\n", (s16_t)size)); + MEM_STATS_INC(err); + LWIP_MEM_ALLOC_UNPROTECT(); + sys_sem_signal(mem_sem); + return NULL; +} + +#endif /* MEM_USE_POOLS */ +/** + * Contiguously allocates enough space for count objects that are size bytes + * of memory each and returns a pointer to the allocated memory. + * + * The allocated memory is filled with bytes of value zero. + * + * @param count number of objects to allocate + * @param size size of the objects to allocate + * @return pointer to allocated memory / NULL pointer if there is an error + */ +void *mem_calloc(mem_size_t count, mem_size_t size) +{ + void *p; + + /* allocate 'count' objects of size 'size' */ + p = mem_malloc(count * size); + if (p) { + /* zero the memory */ + memset(p, 0, count * size); + } + return p; +} + +#endif /* !MEM_LIBC_MALLOC */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/core/memp.c b/component/common/network/lwip/lwip_v1.3.2/src/core/memp.c new file mode 100644 index 0000000..8a34c4b --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/core/memp.c @@ -0,0 +1,386 @@ +/** + * @file + * Dynamic pool memory manager + * + * lwIP has dedicated pools for many structures (netconn, protocol control blocks, + * packet buffers, ...). All these pools are managed here. + **/ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/memp.h" +#include "lwip/pbuf.h" +#include "lwip/udp.h" +#include "lwip/raw.h" +#include "lwip/tcp.h" +#include "lwip/igmp.h" +#include "lwip/api.h" +#include "lwip/api_msg.h" +#include "lwip/tcpip.h" +#include "lwip/sys.h" +#include "lwip/stats.h" +#include "netif/etharp.h" +#include "lwip/ip_frag.h" + +#include + +#if !MEMP_MEM_MALLOC /* don't build if not configured for use in lwipopts.h */ + +struct memp { + struct memp *next; +#if MEMP_OVERFLOW_CHECK + const char *file; + int line; +#endif /* MEMP_OVERFLOW_CHECK */ +}; + +#if MEMP_OVERFLOW_CHECK +/* if MEMP_OVERFLOW_CHECK is turned on, we reserve some bytes at the beginning + * and at the end of each element, initialize them as 0xcd and check + * them later. */ +/* If MEMP_OVERFLOW_CHECK is >= 2, on every call to memp_malloc or memp_free, + * every single element in each pool is checked! + * This is VERY SLOW but also very helpful. */ +/* MEMP_SANITY_REGION_BEFORE and MEMP_SANITY_REGION_AFTER can be overridden in + * lwipopts.h to change the amount reserved for checking. */ +#ifndef MEMP_SANITY_REGION_BEFORE +#define MEMP_SANITY_REGION_BEFORE 16 +#endif /* MEMP_SANITY_REGION_BEFORE*/ +#if MEMP_SANITY_REGION_BEFORE > 0 +#define MEMP_SANITY_REGION_BEFORE_ALIGNED LWIP_MEM_ALIGN_SIZE(MEMP_SANITY_REGION_BEFORE) +#else +#define MEMP_SANITY_REGION_BEFORE_ALIGNED 0 +#endif /* MEMP_SANITY_REGION_BEFORE*/ +#ifndef MEMP_SANITY_REGION_AFTER +#define MEMP_SANITY_REGION_AFTER 16 +#endif /* MEMP_SANITY_REGION_AFTER*/ +#if MEMP_SANITY_REGION_AFTER > 0 +#define MEMP_SANITY_REGION_AFTER_ALIGNED LWIP_MEM_ALIGN_SIZE(MEMP_SANITY_REGION_AFTER) +#else +#define MEMP_SANITY_REGION_AFTER_ALIGNED 0 +#endif /* MEMP_SANITY_REGION_AFTER*/ + +/* MEMP_SIZE: save space for struct memp and for sanity check */ +#define MEMP_SIZE (LWIP_MEM_ALIGN_SIZE(sizeof(struct memp)) + MEMP_SANITY_REGION_BEFORE_ALIGNED) +#define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x) + MEMP_SANITY_REGION_AFTER_ALIGNED) + +#else /* MEMP_OVERFLOW_CHECK */ + +/* No sanity checks + * We don't need to preserve the struct memp while not allocated, so we + * can save a little space and set MEMP_SIZE to 0. + */ +#define MEMP_SIZE 0 +#define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x)) + +#endif /* MEMP_OVERFLOW_CHECK */ + +/** This array holds the first free element of each pool. + * Elements form a linked list. */ +static struct memp *memp_tab[MEMP_MAX]; + +#else /* MEMP_MEM_MALLOC */ + +#define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x)) + +#endif /* MEMP_MEM_MALLOC */ + +/** This array holds the element sizes of each pool. */ +#if !MEM_USE_POOLS && !MEMP_MEM_MALLOC +static +#endif +const u16_t memp_sizes[MEMP_MAX] = { +#define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEM_ALIGN_SIZE(size), +#include "lwip/memp_std.h" +}; + +#if !MEMP_MEM_MALLOC /* don't build if not configured for use in lwipopts.h */ + +/** This array holds the number of elements in each pool. */ +static const u16_t memp_num[MEMP_MAX] = { +#define LWIP_MEMPOOL(name,num,size,desc) (num), +#include "lwip/memp_std.h" +}; + +/** This array holds a textual description of each pool. */ +#ifdef LWIP_DEBUG +static const char *memp_desc[MEMP_MAX] = { +#define LWIP_MEMPOOL(name,num,size,desc) (desc), +#include "lwip/memp_std.h" +}; +#endif /* LWIP_DEBUG */ + +/** This is the actual memory used by the pools. */ +static u8_t memp_memory[MEM_ALIGNMENT - 1 +#define LWIP_MEMPOOL(name,num,size,desc) + ( (num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size) ) ) +#include "lwip/memp_std.h" +]; + +#if MEMP_SANITY_CHECK +/** + * Check that memp-lists don't form a circle + */ +static int +memp_sanity(void) +{ + s16_t i, c; + struct memp *m, *n; + + for (i = 0; i < MEMP_MAX; i++) { + for (m = memp_tab[i]; m != NULL; m = m->next) { + c = 1; + for (n = memp_tab[i]; n != NULL; n = n->next) { + if (n == m && --c < 0) { + return 0; + } + } + } + } + return 1; +} +#endif /* MEMP_SANITY_CHECK*/ +#if MEMP_OVERFLOW_CHECK +/** + * Check if a memp element was victim of an overflow + * (e.g. the restricted area after it has been altered) + * + * @param p the memp element to check + * @param memp_size the element size of the pool p comes from + */ +static void +memp_overflow_check_element(struct memp *p, u16_t memp_size) +{ + u16_t k; + u8_t *m; +#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 + m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED; + for (k = 0; k < MEMP_SANITY_REGION_BEFORE_ALIGNED; k++) { + if (m[k] != 0xcd) { + LWIP_ASSERT("detected memp underflow!", 0); + } + } +#endif +#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0 + m = (u8_t*)p + MEMP_SIZE + memp_size; + for (k = 0; k < MEMP_SANITY_REGION_AFTER_ALIGNED; k++) { + if (m[k] != 0xcd) { + LWIP_ASSERT("detected memp overflow!", 0); + } + } +#endif +} + +/** + * Do an overflow check for all elements in every pool. + * + * @see memp_overflow_check_element for a description of the check + */ +static void +memp_overflow_check_all(void) +{ + u16_t i, j; + struct memp *p; + + p = LWIP_MEM_ALIGN(memp_memory); + for (i = 0; i < MEMP_MAX; ++i) { + p = p; + for (j = 0; j < memp_num[i]; ++j) { + memp_overflow_check_element(p, memp_sizes[i]); + p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i] + MEMP_SANITY_REGION_AFTER_ALIGNED); + } + } +} + +/** + * Initialize the restricted areas of all memp elements in every pool. + */ +static void +memp_overflow_init(void) +{ + u16_t i, j; + struct memp *p; + u8_t *m; + + p = LWIP_MEM_ALIGN(memp_memory); + for (i = 0; i < MEMP_MAX; ++i) { + p = p; + for (j = 0; j < memp_num[i]; ++j) { +#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 + m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED; + memset(m, 0xcd, MEMP_SANITY_REGION_BEFORE_ALIGNED); +#endif +#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0 + m = (u8_t*)p + MEMP_SIZE + memp_sizes[i]; + memset(m, 0xcd, MEMP_SANITY_REGION_AFTER_ALIGNED); +#endif + p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i] + MEMP_SANITY_REGION_AFTER_ALIGNED); + } + } +} +#endif /* MEMP_OVERFLOW_CHECK */ + +/** + * Initialize this module. + * + * Carves out memp_memory into linked lists for each pool-type. + */ +void +memp_init(void) +{ + struct memp *memp; + u16_t i, j; + + for (i = 0; i < MEMP_MAX; ++i) { + MEMP_STATS_AVAIL(used, i, 0); + MEMP_STATS_AVAIL(max, i, 0); + MEMP_STATS_AVAIL(err, i, 0); + MEMP_STATS_AVAIL(avail, i, memp_num[i]); + } + + memp = LWIP_MEM_ALIGN(memp_memory); + /* for every pool: */ + for (i = 0; i < MEMP_MAX; ++i) { + memp_tab[i] = NULL; + /* create a linked list of memp elements */ + for (j = 0; j < memp_num[i]; ++j) { + memp->next = memp_tab[i]; + memp_tab[i] = memp; + memp = (struct memp *)((u8_t *)memp + MEMP_SIZE + memp_sizes[i] +#if MEMP_OVERFLOW_CHECK + + MEMP_SANITY_REGION_AFTER_ALIGNED +#endif + ); + } + } +#if MEMP_OVERFLOW_CHECK + memp_overflow_init(); + /* check everything a first time to see if it worked */ + memp_overflow_check_all(); +#endif /* MEMP_OVERFLOW_CHECK */ +} + +/** + * Get an element from a specific pool. + * + * @param type the pool to get an element from + * + * the debug version has two more parameters: + * @param file file name calling this function + * @param line number of line where this function is called + * + * @return a pointer to the allocated memory or a NULL pointer on error + */ +void * +#if !MEMP_OVERFLOW_CHECK +memp_malloc(memp_t type) +#else +memp_malloc_fn(memp_t type, const char* file, const int line) +#endif +{ + struct memp *memp; + SYS_ARCH_DECL_PROTECT(old_level); + + LWIP_ERROR("memp_malloc: type < MEMP_MAX", (type < MEMP_MAX), return NULL;); + + SYS_ARCH_PROTECT(old_level); +#if MEMP_OVERFLOW_CHECK >= 2 + memp_overflow_check_all(); +#endif /* MEMP_OVERFLOW_CHECK >= 2 */ + + memp = memp_tab[type]; + + if (memp != NULL) { + memp_tab[type] = memp->next; +#if MEMP_OVERFLOW_CHECK + memp->next = NULL; + memp->file = file; + memp->line = line; +#endif /* MEMP_OVERFLOW_CHECK */ + MEMP_STATS_INC_USED(used, type); + LWIP_ASSERT("memp_malloc: memp properly aligned", + ((mem_ptr_t)memp % MEM_ALIGNMENT) == 0); + memp = (struct memp*)((u8_t*)memp + MEMP_SIZE); + } else { + LWIP_DEBUGF(MEMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("memp_malloc: out of memory in pool %s\n", memp_desc[type])); + MEMP_STATS_INC(err, type); + } + + SYS_ARCH_UNPROTECT(old_level); + + return memp; +} + +/** + * Put an element back into its pool. + * + * @param type the pool where to put mem + * @param mem the memp element to free + */ +void +memp_free(memp_t type, void *mem) +{ + struct memp *memp; + SYS_ARCH_DECL_PROTECT(old_level); + + if (mem == NULL) { + return; + } + LWIP_ASSERT("memp_free: mem properly aligned", + ((mem_ptr_t)mem % MEM_ALIGNMENT) == 0); + + memp = (struct memp *)((u8_t*)mem - MEMP_SIZE); + + SYS_ARCH_PROTECT(old_level); +#if MEMP_OVERFLOW_CHECK +#if MEMP_OVERFLOW_CHECK >= 2 + memp_overflow_check_all(); +#else + memp_overflow_check_element(memp, memp_sizes[type]); +#endif /* MEMP_OVERFLOW_CHECK >= 2 */ +#endif /* MEMP_OVERFLOW_CHECK */ + + MEMP_STATS_DEC(used, type); + + memp->next = memp_tab[type]; + memp_tab[type] = memp; + +#if MEMP_SANITY_CHECK + LWIP_ASSERT("memp sanity", memp_sanity()); +#endif /* MEMP_SANITY_CHECK */ + + SYS_ARCH_UNPROTECT(old_level); +} + +#endif /* MEMP_MEM_MALLOC */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/core/netif.c b/component/common/network/lwip/lwip_v1.3.2/src/core/netif.c new file mode 100644 index 0000000..6c697e7 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/core/netif.c @@ -0,0 +1,687 @@ +/** + * @file + * lwIP network interface abstraction + * + **/ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/def.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/tcp.h" +#include "lwip/snmp.h" +#include "lwip/igmp.h" +#include "netif/etharp.h" +#if ENABLE_LOOPBACK +#include "lwip/sys.h" +#if LWIP_NETIF_LOOPBACK_MULTITHREADING +#include "lwip/tcpip.h" +#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ +#endif /* ENABLE_LOOPBACK */ + +#if LWIP_AUTOIP +#include "lwip/autoip.h" +#endif /* LWIP_AUTOIP */ +#if LWIP_DHCP +#include "lwip/dhcp.h" +#endif /* LWIP_DHCP */ + +#if LWIP_NETIF_STATUS_CALLBACK +#define NETIF_STATUS_CALLBACK(n) { if (n->status_callback) (n->status_callback)(n); } +#else +#define NETIF_STATUS_CALLBACK(n) { /* NOP */ } +#endif /* LWIP_NETIF_STATUS_CALLBACK */ + +#if LWIP_NETIF_LINK_CALLBACK +#define NETIF_LINK_CALLBACK(n) { if (n->link_callback) (n->link_callback)(n); } +#else +#define NETIF_LINK_CALLBACK(n) { /* NOP */ } +#endif /* LWIP_NETIF_LINK_CALLBACK */ + +struct netif *netif_list; +struct netif *netif_default; + +/** + * Add a network interface to the list of lwIP netifs. + * + * @param netif a pre-allocated netif structure + * @param ipaddr IP address for the new netif + * @param netmask network mask for the new netif + * @param gw default gateway IP address for the new netif + * @param state opaque data passed to the new netif + * @param init callback function that initializes the interface + * @param input callback function that is called to pass + * ingress packets up in the protocol layer stack. + * + * @return netif, or NULL if failed. + */ +struct netif * +netif_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask, + struct ip_addr *gw, + void *state, + err_t (* init)(struct netif *netif), + err_t (* input)(struct pbuf *p, struct netif *netif)) +{ + static u8_t netifnum = 0; + + /* reset new interface configuration state */ + netif->ip_addr.addr = 0; + netif->netmask.addr = 0; + netif->gw.addr = 0; + netif->flags = 0; +#if LWIP_DHCP + /* netif not under DHCP control by default */ + netif->dhcp = NULL; +#endif /* LWIP_DHCP */ +#if LWIP_AUTOIP + /* netif not under AutoIP control by default */ + netif->autoip = NULL; +#endif /* LWIP_AUTOIP */ +#if LWIP_NETIF_STATUS_CALLBACK + netif->status_callback = NULL; +#endif /* LWIP_NETIF_STATUS_CALLBACK */ +#if LWIP_NETIF_LINK_CALLBACK + netif->link_callback = NULL; +#endif /* LWIP_NETIF_LINK_CALLBACK */ +#if LWIP_IGMP + netif->igmp_mac_filter = NULL; +#endif /* LWIP_IGMP */ +#if ENABLE_LOOPBACK + netif->loop_first = NULL; + netif->loop_last = NULL; +#endif /* ENABLE_LOOPBACK */ + + /* remember netif specific state information data */ + netif->state = state; + netif->num = netifnum++; + netif->input = input; +#if LWIP_NETIF_HWADDRHINT + netif->addr_hint = NULL; +#endif /* LWIP_NETIF_HWADDRHINT*/ +#if ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS + netif->loop_cnt_current = 0; +#endif /* ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS */ + + netif_set_addr(netif, ipaddr, netmask, gw); + + /* call user specified initialization function for netif */ + if (init(netif) != ERR_OK) { + return NULL; + } + + /* add this netif to the list */ + netif->next = netif_list; + netif_list = netif; + snmp_inc_iflist(); + +#if LWIP_IGMP + /* start IGMP processing */ + if (netif->flags & NETIF_FLAG_IGMP) { + igmp_start( netif); + } +#endif /* LWIP_IGMP */ + + LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP addr ", + netif->name[0], netif->name[1])); + ip_addr_debug_print(NETIF_DEBUG, ipaddr); + LWIP_DEBUGF(NETIF_DEBUG, (" netmask ")); + ip_addr_debug_print(NETIF_DEBUG, netmask); + LWIP_DEBUGF(NETIF_DEBUG, (" gw ")); + ip_addr_debug_print(NETIF_DEBUG, gw); + LWIP_DEBUGF(NETIF_DEBUG, ("\n")); + return netif; +} + +/** + * Change IP address configuration for a network interface (including netmask + * and default gateway). + * + * @param netif the network interface to change + * @param ipaddr the new IP address + * @param netmask the new netmask + * @param gw the new default gateway + */ +void +netif_set_addr(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask, + struct ip_addr *gw) +{ + netif_set_ipaddr(netif, ipaddr); + netif_set_netmask(netif, netmask); + netif_set_gw(netif, gw); +} + +/** + * Remove a network interface from the list of lwIP netifs. + * + * @param netif the network interface to remove + */ +void netif_remove(struct netif * netif) +{ + if ( netif == NULL ) return; + +#if LWIP_IGMP + /* stop IGMP processing */ + if (netif->flags & NETIF_FLAG_IGMP) { + igmp_stop( netif); + } +#endif /* LWIP_IGMP */ + + snmp_delete_ipaddridx_tree(netif); + + /* is it the first netif? */ + if (netif_list == netif) { + netif_list = netif->next; + snmp_dec_iflist(); + } + else { + /* look for netif further down the list */ + struct netif * tmpNetif; + for (tmpNetif = netif_list; tmpNetif != NULL; tmpNetif = tmpNetif->next) { + if (tmpNetif->next == netif) { + tmpNetif->next = netif->next; + snmp_dec_iflist(); + break; + } + } + if (tmpNetif == NULL) + return; /* we didn't find any netif today */ + } + /* this netif is default? */ + if (netif_default == netif) + /* reset default netif */ + netif_set_default(NULL); + LWIP_DEBUGF( NETIF_DEBUG, ("netif_remove: removed netif\n") ); +} + +/** + * Find a network interface by searching for its name + * + * @param name the name of the netif (like netif->name) plus concatenated number + * in ascii representation (e.g. 'en0') + */ +struct netif * +netif_find(char *name) +{ + struct netif *netif; + u8_t num; + + if (name == NULL) { + return NULL; + } + + num = name[2] - '0'; + + for(netif = netif_list; netif != NULL; netif = netif->next) { + if (num == netif->num && + name[0] == netif->name[0] && + name[1] == netif->name[1]) { + LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %c%c\n", name[0], name[1])); + return netif; + } + } + LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1])); + return NULL; +} + +/** + * Change the IP address of a network interface + * + * @param netif the network interface to change + * @param ipaddr the new IP address + * + * @note call netif_set_addr() if you also want to change netmask and + * default gateway + */ +void +netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr) +{ + /* TODO: Handling of obsolete pcbs */ + /* See: http://mail.gnu.org/archive/html/lwip-users/2003-03/msg00118.html */ +#if LWIP_TCP + struct tcp_pcb *pcb; + struct tcp_pcb_listen *lpcb; + + /* address is actually being changed? */ + if ((ip_addr_cmp(ipaddr, &(netif->ip_addr))) == 0) + { + /* extern struct tcp_pcb *tcp_active_pcbs; defined by tcp.h */ + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: netif address being changed\n")); + pcb = tcp_active_pcbs; + while (pcb != NULL) { + /* PCB bound to current local interface address? */ + if (ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr))) { + /* this connection must be aborted */ + struct tcp_pcb *next = pcb->next; + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: aborting TCP pcb %p\n", (void *)pcb)); + tcp_abort(pcb); + pcb = next; + } else { + pcb = pcb->next; + } + } + for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { + /* PCB bound to current local interface address? */ + if ((!(ip_addr_isany(&(lpcb->local_ip)))) && + (ip_addr_cmp(&(lpcb->local_ip), &(netif->ip_addr)))) { + /* The PCB is listening to the old ipaddr and + * is set to listen to the new one instead */ + ip_addr_set(&(lpcb->local_ip), ipaddr); + } + } + } +#endif + snmp_delete_ipaddridx_tree(netif); + snmp_delete_iprteidx_tree(0,netif); + /* set new IP address to netif */ + ip_addr_set(&(netif->ip_addr), ipaddr); + snmp_insert_ipaddridx_tree(netif); + snmp_insert_iprteidx_tree(0,netif); + + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: IP address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + netif->name[0], netif->name[1], + ip4_addr1(&netif->ip_addr), + ip4_addr2(&netif->ip_addr), + ip4_addr3(&netif->ip_addr), + ip4_addr4(&netif->ip_addr))); +} + +/** + * Change the default gateway for a network interface + * + * @param netif the network interface to change + * @param gw the new default gateway + * + * @note call netif_set_addr() if you also want to change ip address and netmask + */ +void +netif_set_gw(struct netif *netif, struct ip_addr *gw) +{ + ip_addr_set(&(netif->gw), gw); + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: GW address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + netif->name[0], netif->name[1], + ip4_addr1(&netif->gw), + ip4_addr2(&netif->gw), + ip4_addr3(&netif->gw), + ip4_addr4(&netif->gw))); +} + +/** + * Change the netmask of a network interface + * + * @param netif the network interface to change + * @param netmask the new netmask + * + * @note call netif_set_addr() if you also want to change ip address and + * default gateway + */ +void +netif_set_netmask(struct netif *netif, struct ip_addr *netmask) +{ + snmp_delete_iprteidx_tree(0, netif); + /* set new netmask to netif */ + ip_addr_set(&(netif->netmask), netmask); + snmp_insert_iprteidx_tree(0, netif); + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: netmask of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + netif->name[0], netif->name[1], + ip4_addr1(&netif->netmask), + ip4_addr2(&netif->netmask), + ip4_addr3(&netif->netmask), + ip4_addr4(&netif->netmask))); +} + +#if LWIP_NETIF_HOSTNAME +void netif_set_hostname(struct netif *netif, char* hostname){ + netif->hostname = hostname; +} +#endif + +/** + * Set a network interface as the default network interface + * (used to output all packets for which no specific route is found) + * + * @param netif the default network interface + */ +void +netif_set_default(struct netif *netif) +{ + if (netif == NULL) + { + /* remove default route */ + snmp_delete_iprteidx_tree(1, netif); + } + else + { + /* install default route */ + snmp_insert_iprteidx_tree(1, netif); + } + netif_default = netif; + LWIP_DEBUGF(NETIF_DEBUG, ("netif: setting default interface %c%c\n", + netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\'')); +} + +/** + * Bring an interface up, available for processing + * traffic. + * + * @note: Enabling DHCP on a down interface will make it come + * up once configured. + * + * @see dhcp_start() + */ +void netif_set_up(struct netif *netif) +{ + if ( !(netif->flags & NETIF_FLAG_UP )) { + netif->flags |= NETIF_FLAG_UP; + +#if LWIP_SNMP + snmp_get_sysuptime(&netif->ts); +#endif /* LWIP_SNMP */ + + NETIF_LINK_CALLBACK(netif); + NETIF_STATUS_CALLBACK(netif); + +#if LWIP_ARP + /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */ + if (netif->flags & NETIF_FLAG_ETHARP) { + etharp_gratuitous(netif); + } +#endif /* LWIP_ARP */ + +#if LWIP_IGMP + /* resend IGMP memberships */ + if (netif->flags & NETIF_FLAG_IGMP) { + igmp_report_groups( netif); + } +#endif /* LWIP_IGMP */ + } +} + +/** + * Bring an interface down, disabling any traffic processing. + * + * @note: Enabling DHCP on a down interface will make it come + * up once configured. + * + * @see dhcp_start() + */ +void netif_set_down(struct netif *netif) +{ + if ( netif->flags & NETIF_FLAG_UP ) + { + netif->flags &= ~NETIF_FLAG_UP; +#if LWIP_SNMP + snmp_get_sysuptime(&netif->ts); +#endif + + NETIF_LINK_CALLBACK(netif); + NETIF_STATUS_CALLBACK(netif); + } +} + +/** + * Ask if an interface is up + */ +u8_t netif_is_up(struct netif *netif) +{ + return (netif->flags & NETIF_FLAG_UP)?1:0; +} + +#if LWIP_NETIF_STATUS_CALLBACK +/** + * Set callback to be called when interface is brought up/down + */ +void netif_set_status_callback(struct netif *netif, void (* status_callback)(struct netif *netif )) +{ + if ( netif ) + netif->status_callback = status_callback; +} +#endif /* LWIP_NETIF_STATUS_CALLBACK */ + +#if LWIP_NETIF_LINK_CALLBACK +/** + * Called by a driver when its link goes up + */ +void netif_set_link_up(struct netif *netif ) +{ + netif->flags |= NETIF_FLAG_LINK_UP; + +#if LWIP_DHCP + if (netif->dhcp) { + dhcp_network_changed(netif); + } +#endif /* LWIP_DHCP */ + +#if LWIP_AUTOIP + if (netif->autoip) { + autoip_network_changed(netif); + } +#endif /* LWIP_AUTOIP */ + + if (netif->flags & NETIF_FLAG_UP) { +#if LWIP_ARP + /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */ + if (netif->flags & NETIF_FLAG_ETHARP) { + etharp_gratuitous(netif); + } +#endif /* LWIP_ARP */ + +#if LWIP_IGMP + /* resend IGMP memberships */ + if (netif->flags & NETIF_FLAG_IGMP) { + igmp_report_groups( netif); + } +#endif /* LWIP_IGMP */ + } + NETIF_LINK_CALLBACK(netif); +} + +/** + * Called by a driver when its link goes down + */ +void netif_set_link_down(struct netif *netif ) +{ + netif->flags &= ~NETIF_FLAG_LINK_UP; + NETIF_LINK_CALLBACK(netif); +} + +/** + * Ask if a link is up + */ +u8_t netif_is_link_up(struct netif *netif) +{ + return (netif->flags & NETIF_FLAG_LINK_UP) ? 1 : 0; +} + +/** + * Set callback to be called when link is brought up/down + */ +void netif_set_link_callback(struct netif *netif, void (* link_callback)(struct netif *netif )) +{ + if (netif) { + netif->link_callback = link_callback; + } +} +#endif /* LWIP_NETIF_LINK_CALLBACK */ + +#if ENABLE_LOOPBACK +/** + * Send an IP packet to be received on the same netif (loopif-like). + * The pbuf is simply copied and handed back to netif->input. + * In multithreaded mode, this is done directly since netif->input must put + * the packet on a queue. + * In callback mode, the packet is put on an internal queue and is fed to + * netif->input by netif_poll(). + * + * @param netif the lwip network interface structure + * @param p the (IP) packet to 'send' + * @param ipaddr the ip address to send the packet to (not used) + * @return ERR_OK if the packet has been sent + * ERR_MEM if the pbuf used to copy the packet couldn't be allocated + */ +err_t +netif_loop_output(struct netif *netif, struct pbuf *p, + struct ip_addr *ipaddr) +{ + struct pbuf *r; + err_t err; + struct pbuf *last; +#if LWIP_LOOPBACK_MAX_PBUFS + u8_t clen = 0; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ + SYS_ARCH_DECL_PROTECT(lev); + LWIP_UNUSED_ARG(ipaddr); + + /* Allocate a new pbuf */ + r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM); + if (r == NULL) { + return ERR_MEM; + } +#if LWIP_LOOPBACK_MAX_PBUFS + clen = pbuf_clen(r); + /* check for overflow or too many pbuf on queue */ + if(((netif->loop_cnt_current + clen) < netif->loop_cnt_current) || + ((netif->loop_cnt_current + clen) > LWIP_LOOPBACK_MAX_PBUFS)) { + pbuf_free(r); + r = NULL; + return ERR_MEM; + } + netif->loop_cnt_current += clen; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ + + /* Copy the whole pbuf queue p into the single pbuf r */ + if ((err = pbuf_copy(r, p)) != ERR_OK) { + pbuf_free(r); + r = NULL; + return err; + } + + /* Put the packet on a linked list which gets emptied through calling + netif_poll(). */ + + /* let last point to the last pbuf in chain r */ + for (last = r; last->next != NULL; last = last->next); + + SYS_ARCH_PROTECT(lev); + if(netif->loop_first != NULL) { + LWIP_ASSERT("if first != NULL, last must also be != NULL", netif->loop_last != NULL); + netif->loop_last->next = r; + netif->loop_last = last; + } else { + netif->loop_first = r; + netif->loop_last = last; + } + SYS_ARCH_UNPROTECT(lev); + +#if LWIP_NETIF_LOOPBACK_MULTITHREADING + /* For multithreading environment, schedule a call to netif_poll */ + tcpip_callback((void (*)(void *))(netif_poll), netif); +#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ + + return ERR_OK; +} + +/** + * Call netif_poll() in the main loop of your application. This is to prevent + * reentering non-reentrant functions like tcp_input(). Packets passed to + * netif_loop_output() are put on a list that is passed to netif->input() by + * netif_poll(). + */ +void +netif_poll(struct netif *netif) +{ + struct pbuf *in; + SYS_ARCH_DECL_PROTECT(lev); + + do { + /* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */ + SYS_ARCH_PROTECT(lev); + in = netif->loop_first; + if(in != NULL) { + struct pbuf *in_end = in; +#if LWIP_LOOPBACK_MAX_PBUFS + u8_t clen = pbuf_clen(in); + /* adjust the number of pbufs on queue */ + LWIP_ASSERT("netif->loop_cnt_current underflow", + ((netif->loop_cnt_current - clen) < netif->loop_cnt_current)); + netif->loop_cnt_current -= clen; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ + while(in_end->len != in_end->tot_len) { + LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL); + in_end = in_end->next; + } + /* 'in_end' now points to the last pbuf from 'in' */ + if(in_end == netif->loop_last) { + /* this was the last pbuf in the list */ + netif->loop_first = netif->loop_last = NULL; + } else { + /* pop the pbuf off the list */ + netif->loop_first = in_end->next; + LWIP_ASSERT("should not be null since first != last!", netif->loop_first != NULL); + } + /* De-queue the pbuf from its successors on the 'loop_' list. */ + in_end->next = NULL; + } + SYS_ARCH_UNPROTECT(lev); + + if(in != NULL) { + /* loopback packets are always IP packets! */ + if(ip_input(in, netif) != ERR_OK) { + pbuf_free(in); + } + /* Don't reference the packet any more! */ + in = NULL; + } + /* go on while there is a packet on the list */ + } while(netif->loop_first != NULL); +} + +#if !LWIP_NETIF_LOOPBACK_MULTITHREADING +/** + * Calls netif_poll() for every netif on the netif_list. + */ +void +netif_poll_all(void) +{ + struct netif *netif = netif_list; + /* loop through netifs */ + while (netif != NULL) { + netif_poll(netif); + /* proceed to next network interface */ + netif = netif->next; + } +} +#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */ +#endif /* ENABLE_LOOPBACK */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/core/pbuf.c b/component/common/network/lwip/lwip_v1.3.2/src/core/pbuf.c new file mode 100644 index 0000000..59de5bc --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/core/pbuf.c @@ -0,0 +1,929 @@ +/** + * @file + * Packet buffer management + * + * Packets are built from the pbuf data structure. It supports dynamic + * memory allocation for packet contents or can reference externally + * managed packet contents both in RAM and ROM. Quick allocation for + * incoming packets is provided through pools with fixed sized pbufs. + * + * A packet may span over multiple pbufs, chained as a singly linked + * list. This is called a "pbuf chain". + * + * Multiple packets may be queued, also using this singly linked list. + * This is called a "packet queue". + * + * So, a packet queue consists of one or more pbuf chains, each of + * which consist of one or more pbufs. CURRENTLY, PACKET QUEUES ARE + * NOT SUPPORTED!!! Use helper structs to queue multiple packets. + * + * The differences between a pbuf chain and a packet queue are very + * precise but subtle. + * + * The last pbuf of a packet has a ->tot_len field that equals the + * ->len field. It can be found by traversing the list. If the last + * pbuf of a packet has a ->next field other than NULL, more packets + * are on the queue. + * + * Therefore, looping through a pbuf of a single packet, has an + * loop end condition (tot_len == p->len), NOT (next == NULL). + **/ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/stats.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/pbuf.h" +#include "lwip/sys.h" +#include "arch/perf.h" +#if TCP_QUEUE_OOSEQ +#include "lwip/tcp.h" +#endif + +#include + +#define SIZEOF_STRUCT_PBUF LWIP_MEM_ALIGN_SIZE(sizeof(struct pbuf)) +/* Since the pool is created in memp, PBUF_POOL_BUFSIZE will be automatically + aligned there. Therefore, PBUF_POOL_BUFSIZE_ALIGNED can be used here. */ +#define PBUF_POOL_BUFSIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE) + +#if !TCP_QUEUE_OOSEQ || NO_SYS +#define PBUF_POOL_IS_EMPTY() +#else /* !TCP_QUEUE_OOSEQ || NO_SYS */ +/** Define this to 0 to prevent freeing ooseq pbufs when the PBUF_POOL is empty */ +#ifndef PBUF_POOL_FREE_OOSEQ +#define PBUF_POOL_FREE_OOSEQ 1 +#endif /* PBUF_POOL_FREE_OOSEQ */ + +#if PBUF_POOL_FREE_OOSEQ +#include "lwip/tcpip.h" +#define PBUF_POOL_IS_EMPTY() pbuf_pool_is_empty() +static u8_t pbuf_free_ooseq_queued; +/** + * Attempt to reclaim some memory from queued out-of-sequence TCP segments + * if we run out of pool pbufs. It's better to give priority to new packets + * if we're running out. + * + * This must be done in the correct thread context therefore this function + * can only be used with NO_SYS=0 and through tcpip_callback. + */ +static void +pbuf_free_ooseq(void* arg) +{ + struct tcp_pcb* pcb; + SYS_ARCH_DECL_PROTECT(old_level); + LWIP_UNUSED_ARG(arg); + + SYS_ARCH_PROTECT(old_level); + pbuf_free_ooseq_queued = 0; + SYS_ARCH_UNPROTECT(old_level); + + for (pcb = tcp_active_pcbs; NULL != pcb; pcb = pcb->next) { + if (NULL != pcb->ooseq) { + /** Free the ooseq pbufs of one PCB only */ + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free_ooseq: freeing out-of-sequence pbufs\n")); + tcp_segs_free(pcb->ooseq); + pcb->ooseq = NULL; + return; + } + } +} + +/** Queue a call to pbuf_free_ooseq if not already queued. */ +static void +pbuf_pool_is_empty(void) +{ + u8_t queued; + SYS_ARCH_DECL_PROTECT(old_level); + + SYS_ARCH_PROTECT(old_level); + queued = pbuf_free_ooseq_queued; + pbuf_free_ooseq_queued = 1; + SYS_ARCH_UNPROTECT(old_level); + + if(!queued) { + /* queue a call to pbuf_free_ooseq if not already queued */ + if(tcpip_callback_with_block(pbuf_free_ooseq, NULL, 0) != ERR_OK) { + SYS_ARCH_PROTECT(old_level); + pbuf_free_ooseq_queued = 0; + SYS_ARCH_UNPROTECT(old_level); + } + } +} +#endif /* PBUF_POOL_FREE_OOSEQ */ +#endif /* !TCP_QUEUE_OOSEQ || NO_SYS */ + +/** + * Allocates a pbuf of the given type (possibly a chain for PBUF_POOL type). + * + * The actual memory allocated for the pbuf is determined by the + * layer at which the pbuf is allocated and the requested size + * (from the size parameter). + * + * @param layer flag to define header size + * @param length size of the pbuf's payload + * @param type this parameter decides how and where the pbuf + * should be allocated as follows: + * + * - PBUF_RAM: buffer memory for pbuf is allocated as one large + * chunk. This includes protocol headers as well. + * - PBUF_ROM: no buffer memory is allocated for the pbuf, even for + * protocol headers. Additional headers must be prepended + * by allocating another pbuf and chain in to the front of + * the ROM pbuf. It is assumed that the memory used is really + * similar to ROM in that it is immutable and will not be + * changed. Memory which is dynamic should generally not + * be attached to PBUF_ROM pbufs. Use PBUF_REF instead. + * - PBUF_REF: no buffer memory is allocated for the pbuf, even for + * protocol headers. It is assumed that the pbuf is only + * being used in a single thread. If the pbuf gets queued, + * then pbuf_take should be called to copy the buffer. + * - PBUF_POOL: the pbuf is allocated as a pbuf chain, with pbufs from + * the pbuf pool that is allocated during pbuf_init(). + * + * @return the allocated pbuf. If multiple pbufs where allocated, this + * is the first pbuf of a pbuf chain. + */ +struct pbuf * +pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type) +{ + struct pbuf *p, *q, *r; + u16_t offset; + s32_t rem_len; /* remaining length */ + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F")\n", length)); + + /* determine header offset */ + offset = 0; + switch (layer) { + case PBUF_TRANSPORT: + /* add room for transport (often TCP) layer header */ + offset += PBUF_TRANSPORT_HLEN; + /* FALLTHROUGH */ + case PBUF_IP: + /* add room for IP layer header */ + offset += PBUF_IP_HLEN; + /* FALLTHROUGH */ + case PBUF_LINK: + /* add room for link layer header */ + offset += PBUF_LINK_HLEN; + break; + case PBUF_RAW: + break; + default: + LWIP_ASSERT("pbuf_alloc: bad pbuf layer", 0); + return NULL; + } + + switch (type) { + case PBUF_POOL: + /* allocate head of pbuf chain into p */ + p = memp_malloc(MEMP_PBUF_POOL); + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc: allocated pbuf %p\n", (void *)p)); + if (p == NULL) { + PBUF_POOL_IS_EMPTY(); + return NULL; + } + p->type = type; + p->next = NULL; + + /* make the payload pointer point 'offset' bytes into pbuf data memory */ + p->payload = LWIP_MEM_ALIGN((void *)((u8_t *)p + (SIZEOF_STRUCT_PBUF + offset))); + LWIP_ASSERT("pbuf_alloc: pbuf p->payload properly aligned", + ((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0); + /* the total length of the pbuf chain is the requested size */ + p->tot_len = length; + /* set the length of the first pbuf in the chain */ + p->len = LWIP_MIN(length, PBUF_POOL_BUFSIZE_ALIGNED - LWIP_MEM_ALIGN_SIZE(offset)); + LWIP_ASSERT("check p->payload + p->len does not overflow pbuf", + ((u8_t*)p->payload + p->len <= + (u8_t*)p + SIZEOF_STRUCT_PBUF + PBUF_POOL_BUFSIZE_ALIGNED)); + LWIP_ASSERT("PBUF_POOL_BUFSIZE must be bigger than MEM_ALIGNMENT", + (PBUF_POOL_BUFSIZE_ALIGNED - LWIP_MEM_ALIGN_SIZE(offset)) > 0 ); + /* set reference count (needed here in case we fail) */ + p->ref = 1; + + /* now allocate the tail of the pbuf chain */ + + /* remember first pbuf for linkage in next iteration */ + r = p; + /* remaining length to be allocated */ + rem_len = length - p->len; + /* any remaining pbufs to be allocated? */ + while (rem_len > 0) { + q = memp_malloc(MEMP_PBUF_POOL); + if (q == NULL) { + PBUF_POOL_IS_EMPTY(); + /* free chain so far allocated */ + pbuf_free(p); + /* bail out unsuccesfully */ + return NULL; + } + q->type = type; + q->flags = 0; + q->next = NULL; + /* make previous pbuf point to this pbuf */ + r->next = q; + /* set total length of this pbuf and next in chain */ + LWIP_ASSERT("rem_len < max_u16_t", rem_len < 0xffff); + q->tot_len = (u16_t)rem_len; + /* this pbuf length is pool size, unless smaller sized tail */ + q->len = LWIP_MIN((u16_t)rem_len, PBUF_POOL_BUFSIZE_ALIGNED); + q->payload = (void *)((u8_t *)q + SIZEOF_STRUCT_PBUF); + LWIP_ASSERT("pbuf_alloc: pbuf q->payload properly aligned", + ((mem_ptr_t)q->payload % MEM_ALIGNMENT) == 0); + LWIP_ASSERT("check p->payload + p->len does not overflow pbuf", + ((u8_t*)p->payload + p->len <= + (u8_t*)p + SIZEOF_STRUCT_PBUF + PBUF_POOL_BUFSIZE_ALIGNED)); + q->ref = 1; + /* calculate remaining length to be allocated */ + rem_len -= q->len; + /* remember this pbuf for linkage in next iteration */ + r = q; + } + /* end of chain */ + /*r->next = NULL;*/ + + break; + case PBUF_RAM: + /* If pbuf is to be allocated in RAM, allocate memory for it. */ + p = (struct pbuf*)mem_malloc(LWIP_MEM_ALIGN_SIZE(SIZEOF_STRUCT_PBUF + offset) + LWIP_MEM_ALIGN_SIZE(length)); + if (p == NULL) { + return NULL; + } + /* Set up internal structure of the pbuf. */ + p->payload = LWIP_MEM_ALIGN((void *)((u8_t *)p + SIZEOF_STRUCT_PBUF + offset)); + p->len = p->tot_len = length; + p->next = NULL; + p->type = type; + + LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned", + ((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0); + break; + /* pbuf references existing (non-volatile static constant) ROM payload? */ + case PBUF_ROM: + /* pbuf references existing (externally allocated) RAM payload? */ + case PBUF_REF: + /* only allocate memory for the pbuf structure */ + p = memp_malloc(MEMP_PBUF); + if (p == NULL) { + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("pbuf_alloc: Could not allocate MEMP_PBUF for PBUF_%s.\n", + (type == PBUF_ROM) ? "ROM" : "REF")); + return NULL; + } + /* caller must set this field properly, afterwards */ + p->payload = NULL; + p->len = p->tot_len = length; + p->next = NULL; + p->type = type; + break; + default: + LWIP_ASSERT("pbuf_alloc: erroneous type", 0); + return NULL; + } + /* set reference count */ + p->ref = 1; + /* set flags */ + p->flags = 0; + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F") == %p\n", length, (void *)p)); + return p; +} + + +/** + * Shrink a pbuf chain to a desired length. + * + * @param p pbuf to shrink. + * @param new_len desired new length of pbuf chain + * + * Depending on the desired length, the first few pbufs in a chain might + * be skipped and left unchanged. The new last pbuf in the chain will be + * resized, and any remaining pbufs will be freed. + * + * @note If the pbuf is ROM/REF, only the ->tot_len and ->len fields are adjusted. + * @note May not be called on a packet queue. + * + * @note Despite its name, pbuf_realloc cannot grow the size of a pbuf (chain). + */ +void +pbuf_realloc(struct pbuf *p, u16_t new_len) +{ + struct pbuf *q; + u16_t rem_len; /* remaining length */ + s32_t grow; + + LWIP_ASSERT("pbuf_realloc: p != NULL", p != NULL); + LWIP_ASSERT("pbuf_realloc: sane p->type", p->type == PBUF_POOL || + p->type == PBUF_ROM || + p->type == PBUF_RAM || + p->type == PBUF_REF); + + /* desired length larger than current length? */ + if (new_len >= p->tot_len) { + /* enlarging not yet supported */ + return; + } + + /* the pbuf chain grows by (new_len - p->tot_len) bytes + * (which may be negative in case of shrinking) */ + grow = new_len - p->tot_len; + + /* first, step over any pbufs that should remain in the chain */ + rem_len = new_len; + q = p; + /* should this pbuf be kept? */ + while (rem_len > q->len) { + /* decrease remaining length by pbuf length */ + rem_len -= q->len; + /* decrease total length indicator */ + LWIP_ASSERT("grow < max_u16_t", grow < 0xffff); + q->tot_len += (u16_t)grow; + /* proceed to next pbuf in chain */ + q = q->next; + LWIP_ASSERT("pbuf_realloc: q != NULL", q != NULL); + } + /* we have now reached the new last pbuf (in q) */ + /* rem_len == desired length for pbuf q */ + + /* shrink allocated memory for PBUF_RAM */ + /* (other types merely adjust their length fields */ + if ((q->type == PBUF_RAM) && (rem_len != q->len)) { + /* reallocate and adjust the length of the pbuf that will be split */ + q = mem_realloc(q, (u8_t *)q->payload - (u8_t *)q + rem_len); + LWIP_ASSERT("mem_realloc give q == NULL", q != NULL); + } + /* adjust length fields for new last pbuf */ + q->len = rem_len; + q->tot_len = q->len; + + /* any remaining pbufs in chain? */ + if (q->next != NULL) { + /* free remaining pbufs in chain */ + pbuf_free(q->next); + } + /* q is last packet in chain */ + q->next = NULL; + +} + +/** + * Adjusts the payload pointer to hide or reveal headers in the payload. + * + * Adjusts the ->payload pointer so that space for a header + * (dis)appears in the pbuf payload. + * + * The ->payload, ->tot_len and ->len fields are adjusted. + * + * @param p pbuf to change the header size. + * @param header_size_increment Number of bytes to increment header size which + * increases the size of the pbuf. New space is on the front. + * (Using a negative value decreases the header size.) + * If hdr_size_inc is 0, this function does nothing and returns succesful. + * + * PBUF_ROM and PBUF_REF type buffers cannot have their sizes increased, so + * the call will fail. A check is made that the increase in header size does + * not move the payload pointer in front of the start of the buffer. + * @return non-zero on failure, zero on success. + * + */ +u8_t +pbuf_header(struct pbuf *p, s16_t header_size_increment) +{ + u16_t type; + void *payload; + u16_t increment_magnitude; + + LWIP_ASSERT("p != NULL", p != NULL); + if ((header_size_increment == 0) || (p == NULL)) + return 0; + + if (header_size_increment < 0){ + increment_magnitude = -header_size_increment; + /* Check that we aren't going to move off the end of the pbuf */ + LWIP_ERROR("increment_magnitude <= p->len", (increment_magnitude <= p->len), return 1;); + } else { + increment_magnitude = header_size_increment; +#if 0 + /* Can't assert these as some callers speculatively call + pbuf_header() to see if it's OK. Will return 1 below instead. */ + /* Check that we've got the correct type of pbuf to work with */ + LWIP_ASSERT("p->type == PBUF_RAM || p->type == PBUF_POOL", + p->type == PBUF_RAM || p->type == PBUF_POOL); + /* Check that we aren't going to move off the beginning of the pbuf */ + LWIP_ASSERT("p->payload - increment_magnitude >= p + SIZEOF_STRUCT_PBUF", + (u8_t *)p->payload - increment_magnitude >= (u8_t *)p + SIZEOF_STRUCT_PBUF); +#endif + } + + type = p->type; + /* remember current payload pointer */ + payload = p->payload; + + /* pbuf types containing payloads? */ + if (type == PBUF_RAM || type == PBUF_POOL) { + /* set new payload pointer */ + p->payload = (u8_t *)p->payload - header_size_increment; + /* boundary check fails? */ + if ((u8_t *)p->payload < (u8_t *)p + SIZEOF_STRUCT_PBUF) { + LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("pbuf_header: failed as %p < %p (not enough space for new header size)\n", + (void *)p->payload, (void *)(p + 1))); + /* restore old payload pointer */ + p->payload = payload; + /* bail out unsuccesfully */ + return 1; + } + /* pbuf types refering to external payloads? */ + } else if (type == PBUF_REF || type == PBUF_ROM) { + /* hide a header in the payload? */ + if ((header_size_increment < 0) && (increment_magnitude <= p->len)) { + /* increase payload pointer */ + p->payload = (u8_t *)p->payload - header_size_increment; + } else { + /* cannot expand payload to front (yet!) + * bail out unsuccesfully */ + return 1; + } + } + else { + /* Unknown type */ + LWIP_ASSERT("bad pbuf type", 0); + return 1; + } + /* modify pbuf length fields */ + p->len += header_size_increment; + p->tot_len += header_size_increment; + + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_header: old %p new %p (%"S16_F")\n", + (void *)payload, (void *)p->payload, header_size_increment)); + + return 0; +} + +/** + * Dereference a pbuf chain or queue and deallocate any no-longer-used + * pbufs at the head of this chain or queue. + * + * Decrements the pbuf reference count. If it reaches zero, the pbuf is + * deallocated. + * + * For a pbuf chain, this is repeated for each pbuf in the chain, + * up to the first pbuf which has a non-zero reference count after + * decrementing. So, when all reference counts are one, the whole + * chain is free'd. + * + * @param p The pbuf (chain) to be dereferenced. + * + * @return the number of pbufs that were de-allocated + * from the head of the chain. + * + * @note MUST NOT be called on a packet queue (Not verified to work yet). + * @note the reference counter of a pbuf equals the number of pointers + * that refer to the pbuf (or into the pbuf). + * + * @internal examples: + * + * Assuming existing chains a->b->c with the following reference + * counts, calling pbuf_free(a) results in: + * + * 1->2->3 becomes ...1->3 + * 3->3->3 becomes 2->3->3 + * 1->1->2 becomes ......1 + * 2->1->1 becomes 1->1->1 + * 1->1->1 becomes ....... + * + */ +u8_t +pbuf_free(struct pbuf *p) +{ + u16_t type; + struct pbuf *q; + u8_t count; + + if (p == NULL) { + LWIP_ASSERT("p != NULL", p != NULL); + /* if assertions are disabled, proceed with debug output */ + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("pbuf_free(p == NULL) was called.\n")); + return 0; + } + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free(%p)\n", (void *)p)); + + PERF_START; + + LWIP_ASSERT("pbuf_free: sane type", + p->type == PBUF_RAM || p->type == PBUF_ROM || + p->type == PBUF_REF || p->type == PBUF_POOL); + + count = 0; + /* de-allocate all consecutive pbufs from the head of the chain that + * obtain a zero reference count after decrementing*/ + while (p != NULL) { + u16_t ref; + SYS_ARCH_DECL_PROTECT(old_level); + /* Since decrementing ref cannot be guaranteed to be a single machine operation + * we must protect it. We put the new ref into a local variable to prevent + * further protection. */ + SYS_ARCH_PROTECT(old_level); + /* all pbufs in a chain are referenced at least once */ + LWIP_ASSERT("pbuf_free: p->ref > 0", p->ref > 0); + /* decrease reference count (number of pointers to pbuf) */ + ref = --(p->ref); + SYS_ARCH_UNPROTECT(old_level); + /* this pbuf is no longer referenced to? */ + if (ref == 0) { + /* remember next pbuf in chain for next iteration */ + q = p->next; + LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: deallocating %p\n", (void *)p)); + type = p->type; + /* is this a pbuf from the pool? */ + if (type == PBUF_POOL) { + memp_free(MEMP_PBUF_POOL, p); + /* is this a ROM or RAM referencing pbuf? */ + } else if (type == PBUF_ROM || type == PBUF_REF) { + memp_free(MEMP_PBUF, p); + /* type == PBUF_RAM */ + } else { + mem_free(p); + } + count++; + /* proceed to next pbuf */ + p = q; + /* p->ref > 0, this pbuf is still referenced to */ + /* (and so the remaining pbufs in chain as well) */ + } else { + LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: %p has ref %"U16_F", ending here.\n", (void *)p, ref)); + /* stop walking through the chain */ + p = NULL; + } + } + PERF_STOP("pbuf_free"); + /* return number of de-allocated pbufs */ + return count; +} + +/** + * Count number of pbufs in a chain + * + * @param p first pbuf of chain + * @return the number of pbufs in a chain + */ + +u8_t +pbuf_clen(struct pbuf *p) +{ + u8_t len; + + len = 0; + while (p != NULL) { + ++len; + p = p->next; + } + return len; +} + +/** + * Increment the reference count of the pbuf. + * + * @param p pbuf to increase reference counter of + * + */ +void +pbuf_ref(struct pbuf *p) +{ + SYS_ARCH_DECL_PROTECT(old_level); + /* pbuf given? */ + if (p != NULL) { + SYS_ARCH_PROTECT(old_level); + ++(p->ref); + SYS_ARCH_UNPROTECT(old_level); + } +} + +/** + * Concatenate two pbufs (each may be a pbuf chain) and take over + * the caller's reference of the tail pbuf. + * + * @note The caller MAY NOT reference the tail pbuf afterwards. + * Use pbuf_chain() for that purpose. + * + * @see pbuf_chain() + */ + +void +pbuf_cat(struct pbuf *h, struct pbuf *t) +{ + struct pbuf *p; + + LWIP_ERROR("(h != NULL) && (t != NULL) (programmer violates API)", + ((h != NULL) && (t != NULL)), return;); + + /* proceed to last pbuf of chain */ + for (p = h; p->next != NULL; p = p->next) { + /* add total length of second chain to all totals of first chain */ + p->tot_len += t->tot_len; + } + /* { p is last pbuf of first h chain, p->next == NULL } */ + LWIP_ASSERT("p->tot_len == p->len (of last pbuf in chain)", p->tot_len == p->len); + LWIP_ASSERT("p->next == NULL", p->next == NULL); + /* add total length of second chain to last pbuf total of first chain */ + p->tot_len += t->tot_len; + /* chain last pbuf of head (p) with first of tail (t) */ + p->next = t; + /* p->next now references t, but the caller will drop its reference to t, + * so netto there is no change to the reference count of t. + */ +} + +/** + * Chain two pbufs (or pbuf chains) together. + * + * The caller MUST call pbuf_free(t) once it has stopped + * using it. Use pbuf_cat() instead if you no longer use t. + * + * @param h head pbuf (chain) + * @param t tail pbuf (chain) + * @note The pbufs MUST belong to the same packet. + * @note MAY NOT be called on a packet queue. + * + * The ->tot_len fields of all pbufs of the head chain are adjusted. + * The ->next field of the last pbuf of the head chain is adjusted. + * The ->ref field of the first pbuf of the tail chain is adjusted. + * + */ +void +pbuf_chain(struct pbuf *h, struct pbuf *t) +{ + pbuf_cat(h, t); + /* t is now referenced by h */ + pbuf_ref(t); + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_chain: %p references %p\n", (void *)h, (void *)t)); +} + +/** + * Dechains the first pbuf from its succeeding pbufs in the chain. + * + * Makes p->tot_len field equal to p->len. + * @param p pbuf to dechain + * @return remainder of the pbuf chain, or NULL if it was de-allocated. + * @note May not be called on a packet queue. + */ +struct pbuf * +pbuf_dechain(struct pbuf *p) +{ + struct pbuf *q; + u8_t tail_gone = 1; + /* tail */ + q = p->next; + /* pbuf has successor in chain? */ + if (q != NULL) { + /* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */ + LWIP_ASSERT("p->tot_len == p->len + q->tot_len", q->tot_len == p->tot_len - p->len); + /* enforce invariant if assertion is disabled */ + q->tot_len = p->tot_len - p->len; + /* decouple pbuf from remainder */ + p->next = NULL; + /* total length of pbuf p is its own length only */ + p->tot_len = p->len; + /* q is no longer referenced by p, free it */ + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_dechain: unreferencing %p\n", (void *)q)); + tail_gone = pbuf_free(q); + if (tail_gone > 0) { + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, + ("pbuf_dechain: deallocated %p (as it is no longer referenced)\n", (void *)q)); + } + /* return remaining tail or NULL if deallocated */ + } + /* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */ + LWIP_ASSERT("p->tot_len == p->len", p->tot_len == p->len); + return ((tail_gone > 0) ? NULL : q); +} + +/** + * + * Create PBUF_RAM copies of pbufs. + * + * Used to queue packets on behalf of the lwIP stack, such as + * ARP based queueing. + * + * @note You MUST explicitly use p = pbuf_take(p); + * + * @note Only one packet is copied, no packet queue! + * + * @param p_to pbuf destination of the copy + * @param p_from pbuf source of the copy + * + * @return ERR_OK if pbuf was copied + * ERR_ARG if one of the pbufs is NULL or p_to is not big + * enough to hold p_from + */ +err_t +pbuf_copy(struct pbuf *p_to, struct pbuf *p_from) +{ + u16_t offset_to=0, offset_from=0, len; + + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy(%p, %p)\n", + (void*)p_to, (void*)p_from)); + + /* is the target big enough to hold the source? */ + LWIP_ERROR("pbuf_copy: target not big enough to hold source", ((p_to != NULL) && + (p_from != NULL) && (p_to->tot_len >= p_from->tot_len)), return ERR_ARG;); + + /* iterate through pbuf chain */ + do + { + LWIP_ASSERT("p_to != NULL", p_to != NULL); + /* copy one part of the original chain */ + if ((p_to->len - offset_to) >= (p_from->len - offset_from)) { + /* complete current p_from fits into current p_to */ + len = p_from->len - offset_from; + } else { + /* current p_from does not fit into current p_to */ + len = p_to->len - offset_to; + } + MEMCPY((u8_t*)p_to->payload + offset_to, (u8_t*)p_from->payload + offset_from, len); + offset_to += len; + offset_from += len; + LWIP_ASSERT("offset_to <= p_to->len", offset_to <= p_to->len); + if (offset_to == p_to->len) { + /* on to next p_to (if any) */ + offset_to = 0; + p_to = p_to->next; + } + LWIP_ASSERT("offset_from <= p_from->len", offset_from <= p_from->len); + if (offset_from >= p_from->len) { + /* on to next p_from (if any) */ + offset_from = 0; + p_from = p_from->next; + } + + if((p_from != NULL) && (p_from->len == p_from->tot_len)) { + /* don't copy more than one packet! */ + LWIP_ERROR("pbuf_copy() does not allow packet queues!\n", + (p_from->next == NULL), return ERR_VAL;); + } + if((p_to != NULL) && (p_to->len == p_to->tot_len)) { + /* don't copy more than one packet! */ + LWIP_ERROR("pbuf_copy() does not allow packet queues!\n", + (p_to->next == NULL), return ERR_VAL;); + } + } while (p_from); + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy: end of chain reached.\n")); + return ERR_OK; +} + +/** + * Copy (part of) the contents of a packet buffer + * to an application supplied buffer. + * + * @param buf the pbuf from which to copy data + * @param dataptr the application supplied buffer + * @param len length of data to copy (dataptr must be big enough). No more + * than buf->tot_len will be copied, irrespective of len + * @param offset offset into the packet buffer from where to begin copying len bytes + * @return the number of bytes copied, or 0 on failure + */ +u16_t +pbuf_copy_partial(struct pbuf *buf, void *dataptr, u16_t len, u16_t offset) +{ + struct pbuf *p; + u16_t left; + u16_t buf_copy_len; + u16_t copied_total = 0; + + LWIP_ERROR("pbuf_copy_partial: invalid buf", (buf != NULL), return 0;); + LWIP_ERROR("pbuf_copy_partial: invalid dataptr", (dataptr != NULL), return 0;); + + left = 0; + + if((buf == NULL) || (dataptr == NULL)) { + return 0; + } + + /* Note some systems use byte copy if dataptr or one of the pbuf payload pointers are unaligned. */ + for(p = buf; len != 0 && p != NULL; p = p->next) { + if ((offset != 0) && (offset >= p->len)) { + /* don't copy from this buffer -> on to the next */ + offset -= p->len; + } else { + /* copy from this buffer. maybe only partially. */ + buf_copy_len = p->len - offset; + if (buf_copy_len > len) + buf_copy_len = len; + /* copy the necessary parts of the buffer */ + MEMCPY(&((char*)dataptr)[left], &((char*)p->payload)[offset], buf_copy_len); + copied_total += buf_copy_len; + left += buf_copy_len; + len -= buf_copy_len; + offset = 0; + } + } + return copied_total; +} + +/** + * Copy application supplied data into a pbuf. + * This function can only be used to copy the equivalent of buf->tot_len data. + * + * @param buf pbuf to fill with data + * @param dataptr application supplied data buffer + * @param len length of the application supplied data buffer + * + * @return ERR_OK if successful, ERR_MEM if the pbuf is not big enough + */ +err_t +pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len) +{ + struct pbuf *p; + u16_t buf_copy_len; + u16_t total_copy_len = len; + u16_t copied_total = 0; + + LWIP_ERROR("pbuf_take: invalid buf", (buf != NULL), return 0;); + LWIP_ERROR("pbuf_take: invalid dataptr", (dataptr != NULL), return 0;); + + if ((buf == NULL) || (dataptr == NULL) || (buf->tot_len < len)) { + return ERR_ARG; + } + + /* Note some systems use byte copy if dataptr or one of the pbuf payload pointers are unaligned. */ + for(p = buf; total_copy_len != 0; p = p->next) { + LWIP_ASSERT("pbuf_take: invalid pbuf", p != NULL); + buf_copy_len = total_copy_len; + if (buf_copy_len > p->len) { + /* this pbuf cannot hold all remaining data */ + buf_copy_len = p->len; + } + /* copy the necessary parts of the buffer */ + MEMCPY(p->payload, &((char*)dataptr)[copied_total], buf_copy_len); + total_copy_len -= buf_copy_len; + copied_total += buf_copy_len; + } + LWIP_ASSERT("did not copy all data", total_copy_len == 0 && copied_total == len); + return ERR_OK; +} + +/** + * Creates a single pbuf out of a queue of pbufs. + * + * @remark: The source pbuf 'p' is not freed by this function because that can + * be illegal in some places! + * + * @param p the source pbuf + * @param layer pbuf_layer of the new pbuf + * + * @return a new, single pbuf (p->next is NULL) + * or the old pbuf if allocation fails + */ +struct pbuf* +pbuf_coalesce(struct pbuf *p, pbuf_layer layer) +{ + struct pbuf *q; + err_t err; + if (p->next == NULL) { + return p; + } + q = pbuf_alloc(layer, p->tot_len, PBUF_RAM); + if (q == NULL) { + /* @todo: what do we do now? */ + return p; + } + err = pbuf_copy(q, p); + LWIP_ASSERT("pbuf_copy failed", err == ERR_OK); + pbuf_free(p); + return q; +} diff --git a/component/common/network/lwip/lwip_v1.3.2/src/core/raw.c b/component/common/network/lwip/lwip_v1.3.2/src/core/raw.c new file mode 100644 index 0000000..57acd07 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/core/raw.c @@ -0,0 +1,353 @@ +/** + * @file + * Implementation of raw protocol PCBs for low-level handling of + * different types of protocols besides (or overriding) those + * already available in lwIP. + * + **/ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_RAW /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/memp.h" +#include "lwip/inet.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/raw.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "arch/perf.h" + +#include + +/** The list of RAW PCBs */ +static struct raw_pcb *raw_pcbs; + +/** + * Determine if in incoming IP packet is covered by a RAW PCB + * and if so, pass it to a user-provided receive callback function. + * + * Given an incoming IP datagram (as a chain of pbufs) this function + * finds a corresponding RAW PCB and calls the corresponding receive + * callback function. + * + * @param p pbuf to be demultiplexed to a RAW PCB. + * @param inp network interface on which the datagram was received. + * @return - 1 if the packet has been eaten by a RAW PCB receive + * callback function. The caller MAY NOT not reference the + * packet any longer, and MAY NOT call pbuf_free(). + * @return - 0 if packet is not eaten (pbuf is still referenced by the + * caller). + * + */ +u8_t +raw_input(struct pbuf *p, struct netif *inp) +{ + struct raw_pcb *pcb, *prev; + struct ip_hdr *iphdr; + s16_t proto; + u8_t eaten = 0; + + LWIP_UNUSED_ARG(inp); + + iphdr = p->payload; + proto = IPH_PROTO(iphdr); + + prev = NULL; + pcb = raw_pcbs; + /* loop through all raw pcbs until the packet is eaten by one */ + /* this allows multiple pcbs to match against the packet by design */ + while ((eaten == 0) && (pcb != NULL)) { + if (pcb->protocol == proto) { +#if IP_SOF_BROADCAST_RECV + /* broadcast filter? */ + if ((pcb->so_options & SOF_BROADCAST) || !ip_addr_isbroadcast(&(iphdr->dest), inp)) +#endif /* IP_SOF_BROADCAST_RECV */ + { + /* receive callback function available? */ + if (pcb->recv != NULL) { + /* the receive callback function did not eat the packet? */ + if (pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src)) != 0) { + /* receive function ate the packet */ + p = NULL; + eaten = 1; + if (prev != NULL) { + /* move the pcb to the front of raw_pcbs so that is + found faster next time */ + prev->next = pcb->next; + pcb->next = raw_pcbs; + raw_pcbs = pcb; + } + } + } + /* no receive callback function was set for this raw PCB */ + } + /* drop the packet */ + } + prev = pcb; + pcb = pcb->next; + } + return eaten; +} + +/** + * Bind a RAW PCB. + * + * @param pcb RAW PCB to be bound with a local address ipaddr. + * @param ipaddr local IP address to bind with. Use IP_ADDR_ANY to + * bind to all local interfaces. + * + * @return lwIP error code. + * - ERR_OK. Successful. No error occured. + * - ERR_USE. The specified IP address is already bound to by + * another RAW PCB. + * + * @see raw_disconnect() + */ +err_t +raw_bind(struct raw_pcb *pcb, struct ip_addr *ipaddr) +{ + ip_addr_set(&pcb->local_ip, ipaddr); + return ERR_OK; +} + +/** + * Connect an RAW PCB. This function is required by upper layers + * of lwip. Using the raw api you could use raw_sendto() instead + * + * This will associate the RAW PCB with the remote address. + * + * @param pcb RAW PCB to be connected with remote address ipaddr and port. + * @param ipaddr remote IP address to connect with. + * + * @return lwIP error code + * + * @see raw_disconnect() and raw_sendto() + */ +err_t +raw_connect(struct raw_pcb *pcb, struct ip_addr *ipaddr) +{ + ip_addr_set(&pcb->remote_ip, ipaddr); + return ERR_OK; +} + + +/** + * Set the callback function for received packets that match the + * raw PCB's protocol and binding. + * + * The callback function MUST either + * - eat the packet by calling pbuf_free() and returning non-zero. The + * packet will not be passed to other raw PCBs or other protocol layers. + * - not free the packet, and return zero. The packet will be matched + * against further PCBs and/or forwarded to another protocol layers. + * + * @return non-zero if the packet was free()d, zero if the packet remains + * available for others. + */ +void +raw_recv(struct raw_pcb *pcb, + u8_t (* recv)(void *arg, struct raw_pcb *upcb, struct pbuf *p, + struct ip_addr *addr), + void *recv_arg) +{ + /* remember recv() callback and user data */ + pcb->recv = recv; + pcb->recv_arg = recv_arg; +} + +/** + * Send the raw IP packet to the given address. Note that actually you cannot + * modify the IP headers (this is inconsistent with the receive callback where + * you actually get the IP headers), you can only specify the IP payload here. + * It requires some more changes in lwIP. (there will be a raw_send() function + * then.) + * + * @param pcb the raw pcb which to send + * @param p the IP payload to send + * @param ipaddr the destination address of the IP packet + * + */ +err_t +raw_sendto(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr) +{ + err_t err; + struct netif *netif; + struct ip_addr *src_ip; + struct pbuf *q; /* q will be sent down the stack */ + + LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_sendto\n")); + + /* not enough space to add an IP header to first pbuf in given p chain? */ + if (pbuf_header(p, IP_HLEN)) { + /* allocate header in new pbuf */ + q = pbuf_alloc(PBUF_IP, 0, PBUF_RAM); + /* new header pbuf could not be allocated? */ + if (q == NULL) { + LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("raw_sendto: could not allocate header\n")); + return ERR_MEM; + } + /* chain header q in front of given pbuf p */ + pbuf_chain(q, p); + /* { first pbuf q points to header pbuf } */ + LWIP_DEBUGF(RAW_DEBUG, ("raw_sendto: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p)); + } else { + /* first pbuf q equals given pbuf */ + q = p; + if(pbuf_header(q, -IP_HLEN)) { + LWIP_ASSERT("Can't restore header we just removed!", 0); + return ERR_MEM; + } + } + + if ((netif = ip_route(ipaddr)) == NULL) { + LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: No route to 0x%"X32_F"\n", ipaddr->addr)); + /* free any temporary header pbuf allocated by pbuf_header() */ + if (q != p) { + pbuf_free(q); + } + return ERR_RTE; + } + +#if IP_SOF_BROADCAST + /* broadcast filter? */ + if ( ((pcb->so_options & SOF_BROADCAST) == 0) && ip_addr_isbroadcast(ipaddr, netif) ) { + LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb)); + /* free any temporary header pbuf allocated by pbuf_header() */ + if (q != p) { + pbuf_free(q); + } + return ERR_VAL; + } +#endif /* IP_SOF_BROADCAST */ + + if (ip_addr_isany(&pcb->local_ip)) { + /* use outgoing network interface IP address as source address */ + src_ip = &(netif->ip_addr); + } else { + /* use RAW PCB local IP address as source address */ + src_ip = &(pcb->local_ip); + } + +#if LWIP_NETIF_HWADDRHINT + netif->addr_hint = &(pcb->addr_hint); +#endif /* LWIP_NETIF_HWADDRHINT*/ + err = ip_output_if (q, src_ip, ipaddr, pcb->ttl, pcb->tos, pcb->protocol, netif); +#if LWIP_NETIF_HWADDRHINT + netif->addr_hint = NULL; +#endif /* LWIP_NETIF_HWADDRHINT*/ + + /* did we chain a header earlier? */ + if (q != p) { + /* free the header */ + pbuf_free(q); + } + return err; +} + +/** + * Send the raw IP packet to the address given by raw_connect() + * + * @param pcb the raw pcb which to send + * @param p the IP payload to send + * + */ +err_t +raw_send(struct raw_pcb *pcb, struct pbuf *p) +{ + return raw_sendto(pcb, p, &pcb->remote_ip); +} + +/** + * Remove an RAW PCB. + * + * @param pcb RAW PCB to be removed. The PCB is removed from the list of + * RAW PCB's and the data structure is freed from memory. + * + * @see raw_new() + */ +void +raw_remove(struct raw_pcb *pcb) +{ + struct raw_pcb *pcb2; + /* pcb to be removed is first in list? */ + if (raw_pcbs == pcb) { + /* make list start at 2nd pcb */ + raw_pcbs = raw_pcbs->next; + /* pcb not 1st in list */ + } else { + for(pcb2 = raw_pcbs; pcb2 != NULL; pcb2 = pcb2->next) { + /* find pcb in raw_pcbs list */ + if (pcb2->next != NULL && pcb2->next == pcb) { + /* remove pcb from list */ + pcb2->next = pcb->next; + } + } + } + memp_free(MEMP_RAW_PCB, pcb); +} + +/** + * Create a RAW PCB. + * + * @return The RAW PCB which was created. NULL if the PCB data structure + * could not be allocated. + * + * @param proto the protocol number of the IPs payload (e.g. IP_PROTO_ICMP) + * + * @see raw_remove() + */ +struct raw_pcb * +raw_new(u8_t proto) { + struct raw_pcb *pcb; + + LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_new\n")); + + pcb = memp_malloc(MEMP_RAW_PCB); + /* could allocate RAW PCB? */ + if (pcb != NULL) { + /* initialize PCB to all zeroes */ + memset(pcb, 0, sizeof(struct raw_pcb)); + pcb->protocol = proto; + pcb->ttl = RAW_TTL; + pcb->next = raw_pcbs; + raw_pcbs = pcb; + } + return pcb; +} + +#endif /* LWIP_RAW */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/core/snmp/asn1_dec.c b/component/common/network/lwip/lwip_v1.3.2/src/core/snmp/asn1_dec.c new file mode 100644 index 0000000..650fb40 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/core/snmp/asn1_dec.c @@ -0,0 +1,657 @@ +/** + * @file + * Abstract Syntax Notation One (ISO 8824, 8825) decoding + * + * @todo not optimised (yet), favor correctness over speed, favor speed over size + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * Author: Christiaan Simons + */ + +#include "lwip/opt.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/snmp_asn1.h" + +/** + * Retrieves type field from incoming pbuf chain. + * + * @param p points to a pbuf holding an ASN1 coded type field + * @param ofs points to the offset within the pbuf chain of the ASN1 coded type field + * @param type return ASN1 type + * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) decode + */ +err_t +snmp_asn1_dec_type(struct pbuf *p, u16_t ofs, u8_t *type) +{ + u16_t plen, base; + u8_t *msg_ptr; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = p->payload; + msg_ptr += ofs - base; + *type = *msg_ptr; + return ERR_OK; + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +/** + * Decodes length field from incoming pbuf chain into host length. + * + * @param p points to a pbuf holding an ASN1 coded length + * @param ofs points to the offset within the pbuf chain of the ASN1 coded length + * @param octets_used returns number of octets used by the length code + * @param length return host order length, upto 64k + * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) decode + */ +err_t +snmp_asn1_dec_length(struct pbuf *p, u16_t ofs, u8_t *octets_used, u16_t *length) +{ + u16_t plen, base; + u8_t *msg_ptr; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = p->payload; + msg_ptr += ofs - base; + + if (*msg_ptr < 0x80) + { + /* primitive definite length format */ + *octets_used = 1; + *length = *msg_ptr; + return ERR_OK; + } + else if (*msg_ptr == 0x80) + { + /* constructed indefinite length format, termination with two zero octets */ + u8_t zeros; + u8_t i; + + *length = 0; + zeros = 0; + while (zeros != 2) + { + i = 2; + while (i > 0) + { + i--; + (*length) += 1; + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + if (*msg_ptr == 0) + { + zeros++; + if (zeros == 2) + { + /* stop while (i > 0) */ + i = 0; + } + } + else + { + zeros = 0; + } + } + } + *octets_used = 1; + return ERR_OK; + } + else if (*msg_ptr == 0x81) + { + /* constructed definite length format, one octet */ + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = p->payload; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + *length = *msg_ptr; + *octets_used = 2; + return ERR_OK; + } + else if (*msg_ptr == 0x82) + { + u8_t i; + + /* constructed definite length format, two octets */ + i = 2; + while (i > 0) + { + i--; + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + if (i == 0) + { + /* least significant length octet */ + *length |= *msg_ptr; + } + else + { + /* most significant length octet */ + *length = (*msg_ptr) << 8; + } + } + *octets_used = 3; + return ERR_OK; + } + else + { + /* constructed definite length format 3..127 octets, this is too big (>64k) */ + /** @todo: do we need to accept inefficient codings with many leading zero's? */ + *octets_used = 1 + ((*msg_ptr) & 0x7f); + return ERR_ARG; + } + } + p = p->next; + } + + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +/** + * Decodes positive integer (counter, gauge, timeticks) into u32_t. + * + * @param p points to a pbuf holding an ASN1 coded integer + * @param ofs points to the offset within the pbuf chain of the ASN1 coded integer + * @param len length of the coded integer field + * @param value return host order integer + * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) decode + * + * @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded + * as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value + * of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!! + */ +err_t +snmp_asn1_dec_u32t(struct pbuf *p, u16_t ofs, u16_t len, u32_t *value) +{ + u16_t plen, base; + u8_t *msg_ptr; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = p->payload; + msg_ptr += ofs - base; + if ((len > 0) && (len < 6)) + { + /* start from zero */ + *value = 0; + if (*msg_ptr & 0x80) + { + /* negative, expecting zero sign bit! */ + return ERR_ARG; + } + else + { + /* positive */ + if ((len > 1) && (*msg_ptr == 0)) + { + /* skip leading "sign byte" octet 0x00 */ + len--; + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + } + /* OR octets with value */ + while (len > 1) + { + len--; + *value |= *msg_ptr; + *value <<= 8; + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + *value |= *msg_ptr; + return ERR_OK; + } + else + { + return ERR_ARG; + } + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +/** + * Decodes integer into s32_t. + * + * @param p points to a pbuf holding an ASN1 coded integer + * @param ofs points to the offset within the pbuf chain of the ASN1 coded integer + * @param len length of the coded integer field + * @param value return host order integer + * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) decode + * + * @note ASN coded integers are _always_ signed! + */ +err_t +snmp_asn1_dec_s32t(struct pbuf *p, u16_t ofs, u16_t len, s32_t *value) +{ + u16_t plen, base; + u8_t *msg_ptr; +#if BYTE_ORDER == LITTLE_ENDIAN + u8_t *lsb_ptr = (u8_t*)value; +#endif +#if BYTE_ORDER == BIG_ENDIAN + u8_t *lsb_ptr = (u8_t*)value + sizeof(s32_t) - 1; +#endif + u8_t sign; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = p->payload; + msg_ptr += ofs - base; + if ((len > 0) && (len < 5)) + { + if (*msg_ptr & 0x80) + { + /* negative, start from -1 */ + *value = -1; + sign = 1; + } + else + { + /* positive, start from 0 */ + *value = 0; + sign = 0; + } + /* OR/AND octets with value */ + while (len > 1) + { + len--; + if (sign) + { + *lsb_ptr &= *msg_ptr; + *value <<= 8; + *lsb_ptr |= 255; + } + else + { + *lsb_ptr |= *msg_ptr; + *value <<= 8; + } + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + if (sign) + { + *lsb_ptr &= *msg_ptr; + } + else + { + *lsb_ptr |= *msg_ptr; + } + return ERR_OK; + } + else + { + return ERR_ARG; + } + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +/** + * Decodes object identifier from incoming message into array of s32_t. + * + * @param p points to a pbuf holding an ASN1 coded object identifier + * @param ofs points to the offset within the pbuf chain of the ASN1 coded object identifier + * @param len length of the coded object identifier + * @param oid return object identifier struct + * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) decode + */ +err_t +snmp_asn1_dec_oid(struct pbuf *p, u16_t ofs, u16_t len, struct snmp_obj_id *oid) +{ + u16_t plen, base; + u8_t *msg_ptr; + s32_t *oid_ptr; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = p->payload; + msg_ptr += ofs - base; + + oid->len = 0; + oid_ptr = &oid->id[0]; + if (len > 0) + { + /* first compressed octet */ + if (*msg_ptr == 0x2B) + { + /* (most) common case 1.3 (iso.org) */ + *oid_ptr = 1; + oid_ptr++; + *oid_ptr = 3; + oid_ptr++; + } + else if (*msg_ptr < 40) + { + *oid_ptr = 0; + oid_ptr++; + *oid_ptr = *msg_ptr; + oid_ptr++; + } + else if (*msg_ptr < 80) + { + *oid_ptr = 1; + oid_ptr++; + *oid_ptr = (*msg_ptr) - 40; + oid_ptr++; + } + else + { + *oid_ptr = 2; + oid_ptr++; + *oid_ptr = (*msg_ptr) - 80; + oid_ptr++; + } + oid->len = 2; + } + else + { + /* accepting zero length identifiers e.g. for + getnext operation. uncommon but valid */ + return ERR_OK; + } + len--; + if (len > 0) + { + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + while ((len > 0) && (oid->len < LWIP_SNMP_OBJ_ID_LEN)) + { + /* sub-identifier uses multiple octets */ + if (*msg_ptr & 0x80) + { + s32_t sub_id = 0; + + while ((*msg_ptr & 0x80) && (len > 1)) + { + len--; + sub_id = (sub_id << 7) + (*msg_ptr & ~0x80); + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + if (!(*msg_ptr & 0x80) && (len > 0)) + { + /* last octet sub-identifier */ + len--; + sub_id = (sub_id << 7) + *msg_ptr; + *oid_ptr = sub_id; + } + } + else + { + /* !(*msg_ptr & 0x80) sub-identifier uses single octet */ + len--; + *oid_ptr = *msg_ptr; + } + if (len > 0) + { + /* remaining oid bytes available ... */ + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + oid_ptr++; + oid->len++; + } + if (len == 0) + { + /* len == 0, end of oid */ + return ERR_OK; + } + else + { + /* len > 0, oid->len == LWIP_SNMP_OBJ_ID_LEN or malformed encoding */ + return ERR_ARG; + } + + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +/** + * Decodes (copies) raw data (ip-addresses, octet strings, opaque encoding) + * from incoming message into array. + * + * @param p points to a pbuf holding an ASN1 coded raw data + * @param ofs points to the offset within the pbuf chain of the ASN1 coded raw data + * @param len length of the coded raw data (zero is valid, e.g. empty string!) + * @param raw_len length of the raw return value + * @param raw return raw bytes + * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) decode + */ +err_t +snmp_asn1_dec_raw(struct pbuf *p, u16_t ofs, u16_t len, u16_t raw_len, u8_t *raw) +{ + u16_t plen, base; + u8_t *msg_ptr; + + if (len > 0) + { + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = p->payload; + msg_ptr += ofs - base; + if (raw_len >= len) + { + while (len > 1) + { + /* copy len - 1 octets */ + len--; + *raw = *msg_ptr; + raw++; + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + /* copy last octet */ + *raw = *msg_ptr; + return ERR_OK; + } + else + { + /* raw_len < len, not enough dst space */ + return ERR_ARG; + } + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; + } + else + { + /* len == 0, empty string */ + return ERR_OK; + } +} + +#endif /* LWIP_SNMP */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/core/snmp/asn1_enc.c b/component/common/network/lwip/lwip_v1.3.2/src/core/snmp/asn1_enc.c new file mode 100644 index 0000000..77af6b4 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/core/snmp/asn1_enc.c @@ -0,0 +1,611 @@ +/** + * @file + * Abstract Syntax Notation One (ISO 8824, 8825) encoding + * + * @todo not optimised (yet), favor correctness over speed, favor speed over size + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * Author: Christiaan Simons + */ + +#include "lwip/opt.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/snmp_asn1.h" + +/** + * Returns octet count for length. + * + * @param length + * @param octets_needed points to the return value + */ +void +snmp_asn1_enc_length_cnt(u16_t length, u8_t *octets_needed) +{ + if (length < 0x80U) + { + *octets_needed = 1; + } + else if (length < 0x100U) + { + *octets_needed = 2; + } + else + { + *octets_needed = 3; + } +} + +/** + * Returns octet count for an u32_t. + * + * @param value + * @param octets_needed points to the return value + * + * @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded + * as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value + * of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!! + */ +void +snmp_asn1_enc_u32t_cnt(u32_t value, u16_t *octets_needed) +{ + if (value < 0x80UL) + { + *octets_needed = 1; + } + else if (value < 0x8000UL) + { + *octets_needed = 2; + } + else if (value < 0x800000UL) + { + *octets_needed = 3; + } + else if (value < 0x80000000UL) + { + *octets_needed = 4; + } + else + { + *octets_needed = 5; + } +} + +/** + * Returns octet count for an s32_t. + * + * @param value + * @param octets_needed points to the return value + * + * @note ASN coded integers are _always_ signed. + */ +void +snmp_asn1_enc_s32t_cnt(s32_t value, u16_t *octets_needed) +{ + if (value < 0) + { + value = ~value; + } + if (value < 0x80L) + { + *octets_needed = 1; + } + else if (value < 0x8000L) + { + *octets_needed = 2; + } + else if (value < 0x800000L) + { + *octets_needed = 3; + } + else + { + *octets_needed = 4; + } +} + +/** + * Returns octet count for an object identifier. + * + * @param ident_len object identifier array length + * @param ident points to object identifier array + * @param octets_needed points to the return value + */ +void +snmp_asn1_enc_oid_cnt(u8_t ident_len, s32_t *ident, u16_t *octets_needed) +{ + s32_t sub_id; + u8_t cnt; + + cnt = 0; + if (ident_len > 1) + { + /* compressed prefix in one octet */ + cnt++; + ident_len -= 2; + ident += 2; + } + while(ident_len > 0) + { + ident_len--; + sub_id = *ident; + + sub_id >>= 7; + cnt++; + while(sub_id > 0) + { + sub_id >>= 7; + cnt++; + } + ident++; + } + *octets_needed = cnt; +} + +/** + * Encodes ASN type field into a pbuf chained ASN1 msg. + * + * @param p points to output pbuf to encode value into + * @param ofs points to the offset within the pbuf chain + * @param type input ASN1 type + * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) encode + */ +err_t +snmp_asn1_enc_type(struct pbuf *p, u16_t ofs, u8_t type) +{ + u16_t plen, base; + u8_t *msg_ptr; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = p->payload; + msg_ptr += ofs - base; + *msg_ptr = type; + return ERR_OK; + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +/** + * Encodes host order length field into a pbuf chained ASN1 msg. + * + * @param p points to output pbuf to encode length into + * @param ofs points to the offset within the pbuf chain + * @param length is the host order length to be encoded + * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) encode + */ +err_t +snmp_asn1_enc_length(struct pbuf *p, u16_t ofs, u16_t length) +{ + u16_t plen, base; + u8_t *msg_ptr; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = p->payload; + msg_ptr += ofs - base; + + if (length < 0x80) + { + *msg_ptr = length; + return ERR_OK; + } + else if (length < 0x100) + { + *msg_ptr = 0x81; + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = p->payload; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + *msg_ptr = length; + return ERR_OK; + } + else + { + u8_t i; + + /* length >= 0x100 && length <= 0xFFFF */ + *msg_ptr = 0x82; + i = 2; + while (i > 0) + { + i--; + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + if (i == 0) + { + /* least significant length octet */ + *msg_ptr = length; + } + else + { + /* most significant length octet */ + *msg_ptr = length >> 8; + } + } + return ERR_OK; + } + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +/** + * Encodes u32_t (counter, gauge, timeticks) into a pbuf chained ASN1 msg. + * + * @param p points to output pbuf to encode value into + * @param ofs points to the offset within the pbuf chain + * @param octets_needed encoding length (from snmp_asn1_enc_u32t_cnt()) + * @param value is the host order u32_t value to be encoded + * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) encode + * + * @see snmp_asn1_enc_u32t_cnt() + */ +err_t +snmp_asn1_enc_u32t(struct pbuf *p, u16_t ofs, u8_t octets_needed, u32_t value) +{ + u16_t plen, base; + u8_t *msg_ptr; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = p->payload; + msg_ptr += ofs - base; + + if (octets_needed == 5) + { + /* not enough bits in 'value' add leading 0x00 */ + octets_needed--; + *msg_ptr = 0x00; + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + while (octets_needed > 1) + { + octets_needed--; + *msg_ptr = value >> (octets_needed << 3); + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + /* (only) one least significant octet */ + *msg_ptr = value; + return ERR_OK; + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +/** + * Encodes s32_t integer into a pbuf chained ASN1 msg. + * + * @param p points to output pbuf to encode value into + * @param ofs points to the offset within the pbuf chain + * @param octets_needed encoding length (from snmp_asn1_enc_s32t_cnt()) + * @param value is the host order s32_t value to be encoded + * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) encode + * + * @see snmp_asn1_enc_s32t_cnt() + */ +err_t +snmp_asn1_enc_s32t(struct pbuf *p, u16_t ofs, u8_t octets_needed, s32_t value) +{ + u16_t plen, base; + u8_t *msg_ptr; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = p->payload; + msg_ptr += ofs - base; + + while (octets_needed > 1) + { + octets_needed--; + *msg_ptr = value >> (octets_needed << 3); + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + /* (only) one least significant octet */ + *msg_ptr = value; + return ERR_OK; + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +/** + * Encodes object identifier into a pbuf chained ASN1 msg. + * + * @param p points to output pbuf to encode oid into + * @param ofs points to the offset within the pbuf chain + * @param ident_len object identifier array length + * @param ident points to object identifier array + * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) encode + */ +err_t +snmp_asn1_enc_oid(struct pbuf *p, u16_t ofs, u8_t ident_len, s32_t *ident) +{ + u16_t plen, base; + u8_t *msg_ptr; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = p->payload; + msg_ptr += ofs - base; + + if (ident_len > 1) + { + if ((ident[0] == 1) && (ident[1] == 3)) + { + /* compressed (most common) prefix .iso.org */ + *msg_ptr = 0x2b; + } + else + { + /* calculate prefix */ + *msg_ptr = (ident[0] * 40) + ident[1]; + } + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + ident_len -= 2; + ident += 2; + } + else + { +/* @bug: allow empty varbinds for symmetry (we must decode them for getnext), allow partial compression?? */ + /* ident_len <= 1, at least we need zeroDotZero (0.0) (ident_len == 2) */ + return ERR_ARG; + } + while (ident_len > 0) + { + s32_t sub_id; + u8_t shift, tail; + + ident_len--; + sub_id = *ident; + tail = 0; + shift = 28; + while(shift > 0) + { + u8_t code; + + code = sub_id >> shift; + if ((code != 0) || (tail != 0)) + { + tail = 1; + *msg_ptr = code | 0x80; + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + shift -= 7; + } + *msg_ptr = (u8_t)sub_id & 0x7F; + if (ident_len > 0) + { + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + /* proceed to next sub-identifier */ + ident++; + } + return ERR_OK; + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +/** + * Encodes raw data (octet string, opaque) into a pbuf chained ASN1 msg. + * + * @param p points to output pbuf to encode raw data into + * @param ofs points to the offset within the pbuf chain + * @param raw_len raw data length + * @param raw points raw data + * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) encode + */ +err_t +snmp_asn1_enc_raw(struct pbuf *p, u16_t ofs, u8_t raw_len, u8_t *raw) +{ + u16_t plen, base; + u8_t *msg_ptr; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = p->payload; + msg_ptr += ofs - base; + + while (raw_len > 1) + { + /* copy raw_len - 1 octets */ + raw_len--; + *msg_ptr = *raw; + raw++; + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + if (raw_len > 0) + { + /* copy last or single octet */ + *msg_ptr = *raw; + } + return ERR_OK; + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +#endif /* LWIP_SNMP */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/core/snmp/mib2.c b/component/common/network/lwip/lwip_v1.3.2/src/core/snmp/mib2.c new file mode 100644 index 0000000..bc5830d --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/core/snmp/mib2.c @@ -0,0 +1,4128 @@ +/** + * @file + * Management Information Base II (RFC1213) objects and functions. + * + * @note the object identifiers for this MIB-2 and private MIB tree + * must be kept in sorted ascending order. This to ensure correct getnext operation. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * Author: Christiaan Simons + */ + +#include "lwip/opt.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/snmp.h" +#include "lwip/netif.h" +#include "lwip/ip.h" +#include "lwip/ip_frag.h" +#include "lwip/tcp.h" +#include "lwip/udp.h" +#include "lwip/snmp_asn1.h" +#include "lwip/snmp_structs.h" +#include "netif/etharp.h" + +/** + * IANA assigned enterprise ID for lwIP is 26381 + * @see http://www.iana.org/assignments/enterprise-numbers + * + * @note this enterprise ID is assigned to the lwIP project, + * all object identifiers living under this ID are assigned + * by the lwIP maintainers (contact Christiaan Simons)! + * @note don't change this define, use snmp_set_sysobjid() + * + * If you need to create your own private MIB you'll need + * to apply for your own enterprise ID with IANA: + * http://www.iana.org/numbers.html + */ +#define SNMP_ENTERPRISE_ID 26381 +#define SNMP_SYSOBJID_LEN 7 +#define SNMP_SYSOBJID {1, 3, 6, 1, 4, 1, SNMP_ENTERPRISE_ID} + +#ifndef SNMP_SYSSERVICES +#define SNMP_SYSSERVICES ((1 << 6) | (1 << 3) | ((IP_FORWARD) << 2)) +#endif + +#ifndef SNMP_GET_SYSUPTIME +#define SNMP_GET_SYSUPTIME(sysuptime) +#endif + +static void system_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void system_get_value(struct obj_def *od, u16_t len, void *value); +static u8_t system_set_test(struct obj_def *od, u16_t len, void *value); +static void system_set_value(struct obj_def *od, u16_t len, void *value); +static void interfaces_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void interfaces_get_value(struct obj_def *od, u16_t len, void *value); +static void ifentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void ifentry_get_value(struct obj_def *od, u16_t len, void *value); +#if !SNMP_SAFE_REQUESTS +static u8_t ifentry_set_test (struct obj_def *od, u16_t len, void *value); +static void ifentry_set_value (struct obj_def *od, u16_t len, void *value); +#endif /* SNMP_SAFE_REQUESTS */ +static void atentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void atentry_get_value(struct obj_def *od, u16_t len, void *value); +static void ip_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void ip_get_value(struct obj_def *od, u16_t len, void *value); +static u8_t ip_set_test(struct obj_def *od, u16_t len, void *value); +static void ip_addrentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void ip_addrentry_get_value(struct obj_def *od, u16_t len, void *value); +static void ip_rteentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void ip_rteentry_get_value(struct obj_def *od, u16_t len, void *value); +static void ip_ntomentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void ip_ntomentry_get_value(struct obj_def *od, u16_t len, void *value); +static void icmp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void icmp_get_value(struct obj_def *od, u16_t len, void *value); +#if LWIP_TCP +static void tcp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void tcp_get_value(struct obj_def *od, u16_t len, void *value); +#ifdef THIS_SEEMS_UNUSED +static void tcpconnentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void tcpconnentry_get_value(struct obj_def *od, u16_t len, void *value); +#endif +#endif +static void udp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void udp_get_value(struct obj_def *od, u16_t len, void *value); +static void udpentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void udpentry_get_value(struct obj_def *od, u16_t len, void *value); +static void snmp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void snmp_get_value(struct obj_def *od, u16_t len, void *value); +static u8_t snmp_set_test(struct obj_def *od, u16_t len, void *value); +static void snmp_set_value(struct obj_def *od, u16_t len, void *value); + + +/* snmp .1.3.6.1.2.1.11 */ +const mib_scalar_node snmp_scalar = { + &snmp_get_object_def, + &snmp_get_value, + &snmp_set_test, + &snmp_set_value, + MIB_NODE_SC, + 0 +}; +const s32_t snmp_ids[28] = { + 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 24, 25, 26, 27, 28, 29, 30 +}; +struct mib_node* const snmp_nodes[28] = { + (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar, + (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar, + (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar, + (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar, + (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar, + (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar, + (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar, + (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar, + (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar, + (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar, + (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar, + (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar, + (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar, + (struct mib_node* const)&snmp_scalar, (struct mib_node* const)&snmp_scalar +}; +const struct mib_array_node snmp = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 28, + snmp_ids, + snmp_nodes +}; + +/* dot3 and EtherLike MIB not planned. (transmission .1.3.6.1.2.1.10) */ +/* historical (some say hysterical). (cmot .1.3.6.1.2.1.9) */ +/* lwIP has no EGP, thus may not implement it. (egp .1.3.6.1.2.1.8) */ + +/* udp .1.3.6.1.2.1.7 */ +/** index root node for udpTable */ +struct mib_list_rootnode udp_root = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_LR, + 0, + NULL, + NULL, + 0 +}; +const s32_t udpentry_ids[2] = { 1, 2 }; +struct mib_node* const udpentry_nodes[2] = { + (struct mib_node* const)&udp_root, (struct mib_node* const)&udp_root, +}; +const struct mib_array_node udpentry = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 2, + udpentry_ids, + udpentry_nodes +}; + +s32_t udptable_id = 1; +struct mib_node* udptable_node = (struct mib_node* const)&udpentry; +struct mib_ram_array_node udptable = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_RA, + 0, + &udptable_id, + &udptable_node +}; + +const mib_scalar_node udp_scalar = { + &udp_get_object_def, + &udp_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_SC, + 0 +}; +const s32_t udp_ids[5] = { 1, 2, 3, 4, 5 }; +struct mib_node* const udp_nodes[5] = { + (struct mib_node* const)&udp_scalar, (struct mib_node* const)&udp_scalar, + (struct mib_node* const)&udp_scalar, (struct mib_node* const)&udp_scalar, + (struct mib_node* const)&udptable +}; +const struct mib_array_node udp = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 5, + udp_ids, + udp_nodes +}; + +/* tcp .1.3.6.1.2.1.6 */ +#if LWIP_TCP +/* only if the TCP protocol is available may implement this group */ +/** index root node for tcpConnTable */ +struct mib_list_rootnode tcpconntree_root = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_LR, + 0, + NULL, + NULL, + 0 +}; +const s32_t tcpconnentry_ids[5] = { 1, 2, 3, 4, 5 }; +struct mib_node* const tcpconnentry_nodes[5] = { + (struct mib_node* const)&tcpconntree_root, (struct mib_node* const)&tcpconntree_root, + (struct mib_node* const)&tcpconntree_root, (struct mib_node* const)&tcpconntree_root, + (struct mib_node* const)&tcpconntree_root +}; +const struct mib_array_node tcpconnentry = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 5, + tcpconnentry_ids, + tcpconnentry_nodes +}; + +s32_t tcpconntable_id = 1; +struct mib_node* tcpconntable_node = (struct mib_node* const)&tcpconnentry; +struct mib_ram_array_node tcpconntable = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_RA, +/** @todo update maxlength when inserting / deleting from table + 0 when table is empty, 1 when more than one entry */ + 0, + &tcpconntable_id, + &tcpconntable_node +}; + +const mib_scalar_node tcp_scalar = { + &tcp_get_object_def, + &tcp_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_SC, + 0 +}; +const s32_t tcp_ids[15] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; +struct mib_node* const tcp_nodes[15] = { + (struct mib_node* const)&tcp_scalar, (struct mib_node* const)&tcp_scalar, + (struct mib_node* const)&tcp_scalar, (struct mib_node* const)&tcp_scalar, + (struct mib_node* const)&tcp_scalar, (struct mib_node* const)&tcp_scalar, + (struct mib_node* const)&tcp_scalar, (struct mib_node* const)&tcp_scalar, + (struct mib_node* const)&tcp_scalar, (struct mib_node* const)&tcp_scalar, + (struct mib_node* const)&tcp_scalar, (struct mib_node* const)&tcp_scalar, + (struct mib_node* const)&tcpconntable, (struct mib_node* const)&tcp_scalar, + (struct mib_node* const)&tcp_scalar +}; +const struct mib_array_node tcp = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 15, + tcp_ids, + tcp_nodes +}; +#endif + +/* icmp .1.3.6.1.2.1.5 */ +const mib_scalar_node icmp_scalar = { + &icmp_get_object_def, + &icmp_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_SC, + 0 +}; +const s32_t icmp_ids[26] = { 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 }; +struct mib_node* const icmp_nodes[26] = { + (struct mib_node* const)&icmp_scalar, (struct mib_node* const)&icmp_scalar, + (struct mib_node* const)&icmp_scalar, (struct mib_node* const)&icmp_scalar, + (struct mib_node* const)&icmp_scalar, (struct mib_node* const)&icmp_scalar, + (struct mib_node* const)&icmp_scalar, (struct mib_node* const)&icmp_scalar, + (struct mib_node* const)&icmp_scalar, (struct mib_node* const)&icmp_scalar, + (struct mib_node* const)&icmp_scalar, (struct mib_node* const)&icmp_scalar, + (struct mib_node* const)&icmp_scalar, (struct mib_node* const)&icmp_scalar, + (struct mib_node* const)&icmp_scalar, (struct mib_node* const)&icmp_scalar, + (struct mib_node* const)&icmp_scalar, (struct mib_node* const)&icmp_scalar, + (struct mib_node* const)&icmp_scalar, (struct mib_node* const)&icmp_scalar, + (struct mib_node* const)&icmp_scalar, (struct mib_node* const)&icmp_scalar, + (struct mib_node* const)&icmp_scalar, (struct mib_node* const)&icmp_scalar, + (struct mib_node* const)&icmp_scalar, (struct mib_node* const)&icmp_scalar +}; +const struct mib_array_node icmp = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 26, + icmp_ids, + icmp_nodes +}; + +/** index root node for ipNetToMediaTable */ +struct mib_list_rootnode ipntomtree_root = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_LR, + 0, + NULL, + NULL, + 0 +}; +const s32_t ipntomentry_ids[4] = { 1, 2, 3, 4 }; +struct mib_node* const ipntomentry_nodes[4] = { + (struct mib_node* const)&ipntomtree_root, (struct mib_node* const)&ipntomtree_root, + (struct mib_node* const)&ipntomtree_root, (struct mib_node* const)&ipntomtree_root +}; +const struct mib_array_node ipntomentry = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 4, + ipntomentry_ids, + ipntomentry_nodes +}; + +s32_t ipntomtable_id = 1; +struct mib_node* ipntomtable_node = (struct mib_node* const)&ipntomentry; +struct mib_ram_array_node ipntomtable = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_RA, + 0, + &ipntomtable_id, + &ipntomtable_node +}; + +/** index root node for ipRouteTable */ +struct mib_list_rootnode iprtetree_root = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_LR, + 0, + NULL, + NULL, + 0 +}; +const s32_t iprteentry_ids[13] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 }; +struct mib_node* const iprteentry_nodes[13] = { + (struct mib_node* const)&iprtetree_root, (struct mib_node* const)&iprtetree_root, + (struct mib_node* const)&iprtetree_root, (struct mib_node* const)&iprtetree_root, + (struct mib_node* const)&iprtetree_root, (struct mib_node* const)&iprtetree_root, + (struct mib_node* const)&iprtetree_root, (struct mib_node* const)&iprtetree_root, + (struct mib_node* const)&iprtetree_root, (struct mib_node* const)&iprtetree_root, + (struct mib_node* const)&iprtetree_root, (struct mib_node* const)&iprtetree_root, + (struct mib_node* const)&iprtetree_root +}; +const struct mib_array_node iprteentry = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 13, + iprteentry_ids, + iprteentry_nodes +}; + +s32_t iprtetable_id = 1; +struct mib_node* iprtetable_node = (struct mib_node* const)&iprteentry; +struct mib_ram_array_node iprtetable = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_RA, + 0, + &iprtetable_id, + &iprtetable_node +}; + +/** index root node for ipAddrTable */ +struct mib_list_rootnode ipaddrtree_root = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_LR, + 0, + NULL, + NULL, + 0 +}; +const s32_t ipaddrentry_ids[5] = { 1, 2, 3, 4, 5 }; +struct mib_node* const ipaddrentry_nodes[5] = { + (struct mib_node* const)&ipaddrtree_root, + (struct mib_node* const)&ipaddrtree_root, + (struct mib_node* const)&ipaddrtree_root, + (struct mib_node* const)&ipaddrtree_root, + (struct mib_node* const)&ipaddrtree_root +}; +const struct mib_array_node ipaddrentry = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 5, + ipaddrentry_ids, + ipaddrentry_nodes +}; + +s32_t ipaddrtable_id = 1; +struct mib_node* ipaddrtable_node = (struct mib_node* const)&ipaddrentry; +struct mib_ram_array_node ipaddrtable = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_RA, + 0, + &ipaddrtable_id, + &ipaddrtable_node +}; + +/* ip .1.3.6.1.2.1.4 */ +const mib_scalar_node ip_scalar = { + &ip_get_object_def, + &ip_get_value, + &ip_set_test, + &noleafs_set_value, + MIB_NODE_SC, + 0 +}; +const s32_t ip_ids[23] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23 }; +struct mib_node* const ip_nodes[23] = { + (struct mib_node* const)&ip_scalar, (struct mib_node* const)&ip_scalar, + (struct mib_node* const)&ip_scalar, (struct mib_node* const)&ip_scalar, + (struct mib_node* const)&ip_scalar, (struct mib_node* const)&ip_scalar, + (struct mib_node* const)&ip_scalar, (struct mib_node* const)&ip_scalar, + (struct mib_node* const)&ip_scalar, (struct mib_node* const)&ip_scalar, + (struct mib_node* const)&ip_scalar, (struct mib_node* const)&ip_scalar, + (struct mib_node* const)&ip_scalar, (struct mib_node* const)&ip_scalar, + (struct mib_node* const)&ip_scalar, (struct mib_node* const)&ip_scalar, + (struct mib_node* const)&ip_scalar, (struct mib_node* const)&ip_scalar, + (struct mib_node* const)&ip_scalar, (struct mib_node* const)&ipaddrtable, + (struct mib_node* const)&iprtetable, (struct mib_node* const)&ipntomtable, + (struct mib_node* const)&ip_scalar +}; +const struct mib_array_node mib2_ip = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 23, + ip_ids, + ip_nodes +}; + +/** index root node for atTable */ +struct mib_list_rootnode arptree_root = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_LR, + 0, + NULL, + NULL, + 0 +}; +const s32_t atentry_ids[3] = { 1, 2, 3 }; +struct mib_node* const atentry_nodes[3] = { + (struct mib_node* const)&arptree_root, + (struct mib_node* const)&arptree_root, + (struct mib_node* const)&arptree_root +}; +const struct mib_array_node atentry = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 3, + atentry_ids, + atentry_nodes +}; + +const s32_t attable_id = 1; +struct mib_node* const attable_node = (struct mib_node* const)&atentry; +const struct mib_array_node attable = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 1, + &attable_id, + &attable_node +}; + +/* at .1.3.6.1.2.1.3 */ +s32_t at_id = 1; +struct mib_node* mib2_at_node = (struct mib_node* const)&attable; +struct mib_ram_array_node at = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_RA, + 0, + &at_id, + &mib2_at_node +}; + +/** index root node for ifTable */ +struct mib_list_rootnode iflist_root = { + &ifentry_get_object_def, + &ifentry_get_value, +#if SNMP_SAFE_REQUESTS + &noleafs_set_test, + &noleafs_set_value, +#else /* SNMP_SAFE_REQUESTS */ + &ifentry_set_test, + &ifentry_set_value, +#endif /* SNMP_SAFE_REQUESTS */ + MIB_NODE_LR, + 0, + NULL, + NULL, + 0 +}; +const s32_t ifentry_ids[22] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22 }; +struct mib_node* const ifentry_nodes[22] = { + (struct mib_node* const)&iflist_root, (struct mib_node* const)&iflist_root, + (struct mib_node* const)&iflist_root, (struct mib_node* const)&iflist_root, + (struct mib_node* const)&iflist_root, (struct mib_node* const)&iflist_root, + (struct mib_node* const)&iflist_root, (struct mib_node* const)&iflist_root, + (struct mib_node* const)&iflist_root, (struct mib_node* const)&iflist_root, + (struct mib_node* const)&iflist_root, (struct mib_node* const)&iflist_root, + (struct mib_node* const)&iflist_root, (struct mib_node* const)&iflist_root, + (struct mib_node* const)&iflist_root, (struct mib_node* const)&iflist_root, + (struct mib_node* const)&iflist_root, (struct mib_node* const)&iflist_root, + (struct mib_node* const)&iflist_root, (struct mib_node* const)&iflist_root, + (struct mib_node* const)&iflist_root, (struct mib_node* const)&iflist_root +}; +const struct mib_array_node ifentry = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 22, + ifentry_ids, + ifentry_nodes +}; + +s32_t iftable_id = 1; +struct mib_node* iftable_node = (struct mib_node* const)&ifentry; +struct mib_ram_array_node iftable = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_RA, + 0, + &iftable_id, + &iftable_node +}; + +/* interfaces .1.3.6.1.2.1.2 */ +const mib_scalar_node interfaces_scalar = { + &interfaces_get_object_def, + &interfaces_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_SC, + 0 +}; +const s32_t interfaces_ids[2] = { 1, 2 }; +struct mib_node* const interfaces_nodes[2] = { + (struct mib_node* const)&interfaces_scalar, (struct mib_node* const)&iftable +}; +const struct mib_array_node interfaces = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 2, + interfaces_ids, + interfaces_nodes +}; + + +/* 0 1 2 3 4 5 6 */ +/* system .1.3.6.1.2.1.1 */ +const mib_scalar_node sys_tem_scalar = { + &system_get_object_def, + &system_get_value, + &system_set_test, + &system_set_value, + MIB_NODE_SC, + 0 +}; +const s32_t sys_tem_ids[7] = { 1, 2, 3, 4, 5, 6, 7 }; +struct mib_node* const sys_tem_nodes[7] = { + (struct mib_node* const)&sys_tem_scalar, (struct mib_node* const)&sys_tem_scalar, + (struct mib_node* const)&sys_tem_scalar, (struct mib_node* const)&sys_tem_scalar, + (struct mib_node* const)&sys_tem_scalar, (struct mib_node* const)&sys_tem_scalar, + (struct mib_node* const)&sys_tem_scalar +}; +/* work around name issue with 'sys_tem', some compiler(s?) seem to reserve 'system' */ +const struct mib_array_node sys_tem = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 7, + sys_tem_ids, + sys_tem_nodes +}; + +/* mib-2 .1.3.6.1.2.1 */ +#if LWIP_TCP +#define MIB2_GROUPS 8 +#else +#define MIB2_GROUPS 7 +#endif +const s32_t mib2_ids[MIB2_GROUPS] = +{ + 1, + 2, + 3, + 4, + 5, +#if LWIP_TCP + 6, +#endif + 7, + 11 +}; +struct mib_node* const mib2_nodes[MIB2_GROUPS] = { + (struct mib_node* const)&sys_tem, + (struct mib_node* const)&interfaces, + (struct mib_node* const)&at, + (struct mib_node* const)&mib2_ip, + (struct mib_node* const)&icmp, +#if LWIP_TCP + (struct mib_node* const)&tcp, +#endif + (struct mib_node* const)&udp, + (struct mib_node* const)&snmp +}; + +const struct mib_array_node mib2 = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + MIB2_GROUPS, + mib2_ids, + mib2_nodes +}; + +/* mgmt .1.3.6.1.2 */ +const s32_t mgmt_ids[1] = { 1 }; +struct mib_node* const mgmt_nodes[1] = { (struct mib_node* const)&mib2 }; +const struct mib_array_node mgmt = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 1, + mgmt_ids, + mgmt_nodes +}; + +/* internet .1.3.6.1 */ +#if SNMP_PRIVATE_MIB +s32_t internet_ids[2] = { 2, 4 }; +struct mib_node* const internet_nodes[2] = { (struct mib_node* const)&mgmt, (struct mib_node* const)&private }; +const struct mib_array_node internet = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 2, + internet_ids, + internet_nodes +}; +#else +const s32_t internet_ids[1] = { 2 }; +struct mib_node* const internet_nodes[1] = { (struct mib_node* const)&mgmt }; +const struct mib_array_node internet = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 1, + internet_ids, + internet_nodes +}; +#endif + +/** mib-2.system.sysObjectID */ +static struct snmp_obj_id sysobjid = {SNMP_SYSOBJID_LEN, SNMP_SYSOBJID}; +/** enterprise ID for generic TRAPs, .iso.org.dod.internet.mgmt.mib-2.snmp */ +static struct snmp_obj_id snmpgrp_id = {7,{1,3,6,1,2,1,11}}; +/** mib-2.system.sysServices */ +static const s32_t sysservices = SNMP_SYSSERVICES; + +/** mib-2.system.sysDescr */ +static const u8_t sysdescr_len_default = 4; +static const u8_t sysdescr_default[] = "lwIP"; +static u8_t* sysdescr_len_ptr = (u8_t*)&sysdescr_len_default; +static u8_t* sysdescr_ptr = (u8_t*)&sysdescr_default[0]; +/** mib-2.system.sysContact */ +static const u8_t syscontact_len_default = 0; +static const u8_t syscontact_default[] = ""; +static u8_t* syscontact_len_ptr = (u8_t*)&syscontact_len_default; +static u8_t* syscontact_ptr = (u8_t*)&syscontact_default[0]; +/** mib-2.system.sysName */ +static const u8_t sysname_len_default = 8; +static const u8_t sysname_default[] = "FQDN-unk"; +static u8_t* sysname_len_ptr = (u8_t*)&sysname_len_default; +static u8_t* sysname_ptr = (u8_t*)&sysname_default[0]; +/** mib-2.system.sysLocation */ +static const u8_t syslocation_len_default = 0; +static const u8_t syslocation_default[] = ""; +static u8_t* syslocation_len_ptr = (u8_t*)&syslocation_len_default; +static u8_t* syslocation_ptr = (u8_t*)&syslocation_default[0]; +/** mib-2.snmp.snmpEnableAuthenTraps */ +static const u8_t snmpenableauthentraps_default = 2; /* disabled */ +static u8_t* snmpenableauthentraps_ptr = (u8_t*)&snmpenableauthentraps_default; + +/** mib-2.interfaces.ifTable.ifEntry.ifSpecific (zeroDotZero) */ +static const struct snmp_obj_id ifspecific = {2, {0, 0}}; +/** mib-2.ip.ipRouteTable.ipRouteEntry.ipRouteInfo (zeroDotZero) */ +static const struct snmp_obj_id iprouteinfo = {2, {0, 0}}; + + + +/* mib-2.system counter(s) */ +static u32_t sysuptime = 0; + +/* mib-2.ip counter(s) */ +static u32_t ipinreceives = 0, + ipinhdrerrors = 0, + ipinaddrerrors = 0, + ipforwdatagrams = 0, + ipinunknownprotos = 0, + ipindiscards = 0, + ipindelivers = 0, + ipoutrequests = 0, + ipoutdiscards = 0, + ipoutnoroutes = 0, + ipreasmreqds = 0, + ipreasmoks = 0, + ipreasmfails = 0, + ipfragoks = 0, + ipfragfails = 0, + ipfragcreates = 0, + iproutingdiscards = 0; +/* mib-2.icmp counter(s) */ +static u32_t icmpinmsgs = 0, + icmpinerrors = 0, + icmpindestunreachs = 0, + icmpintimeexcds = 0, + icmpinparmprobs = 0, + icmpinsrcquenchs = 0, + icmpinredirects = 0, + icmpinechos = 0, + icmpinechoreps = 0, + icmpintimestamps = 0, + icmpintimestampreps = 0, + icmpinaddrmasks = 0, + icmpinaddrmaskreps = 0, + icmpoutmsgs = 0, + icmpouterrors = 0, + icmpoutdestunreachs = 0, + icmpouttimeexcds = 0, + icmpoutparmprobs = 0, + icmpoutsrcquenchs = 0, + icmpoutredirects = 0, + icmpoutechos = 0, + icmpoutechoreps = 0, + icmpouttimestamps = 0, + icmpouttimestampreps = 0, + icmpoutaddrmasks = 0, + icmpoutaddrmaskreps = 0; +/* mib-2.tcp counter(s) */ +static u32_t tcpactiveopens = 0, + tcppassiveopens = 0, + tcpattemptfails = 0, + tcpestabresets = 0, + tcpinsegs = 0, + tcpoutsegs = 0, + tcpretranssegs = 0, + tcpinerrs = 0, + tcpoutrsts = 0; +/* mib-2.udp counter(s) */ +static u32_t udpindatagrams = 0, + udpnoports = 0, + udpinerrors = 0, + udpoutdatagrams = 0; +/* mib-2.snmp counter(s) */ +static u32_t snmpinpkts = 0, + snmpoutpkts = 0, + snmpinbadversions = 0, + snmpinbadcommunitynames = 0, + snmpinbadcommunityuses = 0, + snmpinasnparseerrs = 0, + snmpintoobigs = 0, + snmpinnosuchnames = 0, + snmpinbadvalues = 0, + snmpinreadonlys = 0, + snmpingenerrs = 0, + snmpintotalreqvars = 0, + snmpintotalsetvars = 0, + snmpingetrequests = 0, + snmpingetnexts = 0, + snmpinsetrequests = 0, + snmpingetresponses = 0, + snmpintraps = 0, + snmpouttoobigs = 0, + snmpoutnosuchnames = 0, + snmpoutbadvalues = 0, + snmpoutgenerrs = 0, + snmpoutgetrequests = 0, + snmpoutgetnexts = 0, + snmpoutsetrequests = 0, + snmpoutgetresponses = 0, + snmpouttraps = 0; + + + +/* prototypes of the following functions are in lwip/src/include/lwip/snmp.h */ +/** + * Copy octet string. + * + * @param dst points to destination + * @param src points to source + * @param n number of octets to copy. + */ +void ocstrncpy(u8_t *dst, u8_t *src, u8_t n) +{ + while (n > 0) + { + n--; + *dst++ = *src++; + } +} + +/** + * Copy object identifier (s32_t) array. + * + * @param dst points to destination + * @param src points to source + * @param n number of sub identifiers to copy. + */ +void objectidncpy(s32_t *dst, s32_t *src, u8_t n) +{ + while(n > 0) + { + n--; + *dst++ = *src++; + } +} + +/** + * Initializes sysDescr pointers. + * + * @param str if non-NULL then copy str pointer + * @param len points to string length, excluding zero terminator + */ +void snmp_set_sysdesr(u8_t *str, u8_t *len) +{ + if (str != NULL) + { + sysdescr_ptr = str; + sysdescr_len_ptr = len; + } +} + +void snmp_get_sysobjid_ptr(struct snmp_obj_id **oid) +{ + *oid = &sysobjid; +} + +/** + * Initializes sysObjectID value. + * + * @param oid points to stuct snmp_obj_id to copy + */ +void snmp_set_sysobjid(struct snmp_obj_id *oid) +{ + sysobjid = *oid; +} + +/** + * Must be called at regular 10 msec interval from a timer interrupt + * or signal handler depending on your runtime environment. + */ +void snmp_inc_sysuptime(void) +{ + sysuptime++; +} + +void snmp_add_sysuptime(u32_t value) +{ + sysuptime+=value; +} + +void snmp_get_sysuptime(u32_t *value) +{ + SNMP_GET_SYSUPTIME(sysuptime); + *value = sysuptime; +} + +/** + * Initializes sysContact pointers, + * e.g. ptrs to non-volatile memory external to lwIP. + * + * @param ocstr if non-NULL then copy str pointer + * @param ocstrlen points to string length, excluding zero terminator + */ +void snmp_set_syscontact(u8_t *ocstr, u8_t *ocstrlen) +{ + if (ocstr != NULL) + { + syscontact_ptr = ocstr; + syscontact_len_ptr = ocstrlen; + } +} + +/** + * Initializes sysName pointers, + * e.g. ptrs to non-volatile memory external to lwIP. + * + * @param ocstr if non-NULL then copy str pointer + * @param ocstrlen points to string length, excluding zero terminator + */ +void snmp_set_sysname(u8_t *ocstr, u8_t *ocstrlen) +{ + if (ocstr != NULL) + { + sysname_ptr = ocstr; + sysname_len_ptr = ocstrlen; + } +} + +/** + * Initializes sysLocation pointers, + * e.g. ptrs to non-volatile memory external to lwIP. + * + * @param ocstr if non-NULL then copy str pointer + * @param ocstrlen points to string length, excluding zero terminator + */ +void snmp_set_syslocation(u8_t *ocstr, u8_t *ocstrlen) +{ + if (ocstr != NULL) + { + syslocation_ptr = ocstr; + syslocation_len_ptr = ocstrlen; + } +} + + +void snmp_add_ifinoctets(struct netif *ni, u32_t value) +{ + ni->ifinoctets += value; +} + +void snmp_inc_ifinucastpkts(struct netif *ni) +{ + (ni->ifinucastpkts)++; +} + +void snmp_inc_ifinnucastpkts(struct netif *ni) +{ + (ni->ifinnucastpkts)++; +} + +void snmp_inc_ifindiscards(struct netif *ni) +{ + (ni->ifindiscards)++; +} + +void snmp_add_ifoutoctets(struct netif *ni, u32_t value) +{ + ni->ifoutoctets += value; +} + +void snmp_inc_ifoutucastpkts(struct netif *ni) +{ + (ni->ifoutucastpkts)++; +} + +void snmp_inc_ifoutnucastpkts(struct netif *ni) +{ + (ni->ifoutnucastpkts)++; +} + +void snmp_inc_ifoutdiscards(struct netif *ni) +{ + (ni->ifoutdiscards)++; +} + +void snmp_inc_iflist(void) +{ + struct mib_list_node *if_node = NULL; + + snmp_mib_node_insert(&iflist_root, iflist_root.count + 1, &if_node); + /* enable getnext traversal on filled table */ + iftable.maxlength = 1; +} + +void snmp_dec_iflist(void) +{ + snmp_mib_node_delete(&iflist_root, iflist_root.tail); + /* disable getnext traversal on empty table */ + if(iflist_root.count == 0) iftable.maxlength = 0; +} + +/** + * Inserts ARP table indexes (.xIfIndex.xNetAddress) + * into arp table index trees (both atTable and ipNetToMediaTable). + */ +void snmp_insert_arpidx_tree(struct netif *ni, struct ip_addr *ip) +{ + struct mib_list_rootnode *at_rn; + struct mib_list_node *at_node; + struct ip_addr hip; + s32_t arpidx[5]; + u8_t level, tree; + + LWIP_ASSERT("ni != NULL", ni != NULL); + snmp_netiftoifindex(ni, &arpidx[0]); + hip.addr = ntohl(ip->addr); + snmp_iptooid(&hip, &arpidx[1]); + + for (tree = 0; tree < 2; tree++) + { + if (tree == 0) + { + at_rn = &arptree_root; + } + else + { + at_rn = &ipntomtree_root; + } + for (level = 0; level < 5; level++) + { + at_node = NULL; + snmp_mib_node_insert(at_rn, arpidx[level], &at_node); + if ((level != 4) && (at_node != NULL)) + { + if (at_node->nptr == NULL) + { + at_rn = snmp_mib_lrn_alloc(); + at_node->nptr = (struct mib_node*)at_rn; + if (at_rn != NULL) + { + if (level == 3) + { + if (tree == 0) + { + at_rn->get_object_def = atentry_get_object_def; + at_rn->get_value = atentry_get_value; + } + else + { + at_rn->get_object_def = ip_ntomentry_get_object_def; + at_rn->get_value = ip_ntomentry_get_value; + } + at_rn->set_test = noleafs_set_test; + at_rn->set_value = noleafs_set_value; + } + } + else + { + /* at_rn == NULL, malloc failure */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_insert_arpidx_tree() insert failed, mem full")); + break; + } + } + else + { + at_rn = (struct mib_list_rootnode*)at_node->nptr; + } + } + } + } + /* enable getnext traversal on filled tables */ + at.maxlength = 1; + ipntomtable.maxlength = 1; +} + +/** + * Removes ARP table indexes (.xIfIndex.xNetAddress) + * from arp table index trees. + */ +void snmp_delete_arpidx_tree(struct netif *ni, struct ip_addr *ip) +{ + struct mib_list_rootnode *at_rn, *next, *del_rn[5]; + struct mib_list_node *at_n, *del_n[5]; + struct ip_addr hip; + s32_t arpidx[5]; + u8_t fc, tree, level, del_cnt; + + snmp_netiftoifindex(ni, &arpidx[0]); + hip.addr = ntohl(ip->addr); + snmp_iptooid(&hip, &arpidx[1]); + + for (tree = 0; tree < 2; tree++) + { + /* mark nodes for deletion */ + if (tree == 0) + { + at_rn = &arptree_root; + } + else + { + at_rn = &ipntomtree_root; + } + level = 0; + del_cnt = 0; + while ((level < 5) && (at_rn != NULL)) + { + fc = snmp_mib_node_find(at_rn, arpidx[level], &at_n); + if (fc == 0) + { + /* arpidx[level] does not exist */ + del_cnt = 0; + at_rn = NULL; + } + else if (fc == 1) + { + del_rn[del_cnt] = at_rn; + del_n[del_cnt] = at_n; + del_cnt++; + at_rn = (struct mib_list_rootnode*)(at_n->nptr); + } + else if (fc == 2) + { + /* reset delete (2 or more childs) */ + del_cnt = 0; + at_rn = (struct mib_list_rootnode*)(at_n->nptr); + } + level++; + } + /* delete marked index nodes */ + while (del_cnt > 0) + { + del_cnt--; + + at_rn = del_rn[del_cnt]; + at_n = del_n[del_cnt]; + + next = snmp_mib_node_delete(at_rn, at_n); + if (next != NULL) + { + LWIP_ASSERT("next_count == 0",next->count == 0); + snmp_mib_lrn_free(next); + } + } + } + /* disable getnext traversal on empty tables */ + if(arptree_root.count == 0) at.maxlength = 0; + if(ipntomtree_root.count == 0) ipntomtable.maxlength = 0; +} + +void snmp_inc_ipinreceives(void) +{ + ipinreceives++; +} + +void snmp_inc_ipinhdrerrors(void) +{ + ipinhdrerrors++; +} + +void snmp_inc_ipinaddrerrors(void) +{ + ipinaddrerrors++; +} + +void snmp_inc_ipforwdatagrams(void) +{ + ipforwdatagrams++; +} + +void snmp_inc_ipinunknownprotos(void) +{ + ipinunknownprotos++; +} + +void snmp_inc_ipindiscards(void) +{ + ipindiscards++; +} + +void snmp_inc_ipindelivers(void) +{ + ipindelivers++; +} + +void snmp_inc_ipoutrequests(void) +{ + ipoutrequests++; +} + +void snmp_inc_ipoutdiscards(void) +{ + ipoutdiscards++; +} + +void snmp_inc_ipoutnoroutes(void) +{ + ipoutnoroutes++; +} + +void snmp_inc_ipreasmreqds(void) +{ + ipreasmreqds++; +} + +void snmp_inc_ipreasmoks(void) +{ + ipreasmoks++; +} + +void snmp_inc_ipreasmfails(void) +{ + ipreasmfails++; +} + +void snmp_inc_ipfragoks(void) +{ + ipfragoks++; +} + +void snmp_inc_ipfragfails(void) +{ + ipfragfails++; +} + +void snmp_inc_ipfragcreates(void) +{ + ipfragcreates++; +} + +void snmp_inc_iproutingdiscards(void) +{ + iproutingdiscards++; +} + +/** + * Inserts ipAddrTable indexes (.ipAdEntAddr) + * into index tree. + */ +void snmp_insert_ipaddridx_tree(struct netif *ni) +{ + struct mib_list_rootnode *ipa_rn; + struct mib_list_node *ipa_node; + struct ip_addr ip; + s32_t ipaddridx[4]; + u8_t level; + + LWIP_ASSERT("ni != NULL", ni != NULL); + ip.addr = ntohl(ni->ip_addr.addr); + snmp_iptooid(&ip, &ipaddridx[0]); + + level = 0; + ipa_rn = &ipaddrtree_root; + while (level < 4) + { + ipa_node = NULL; + snmp_mib_node_insert(ipa_rn, ipaddridx[level], &ipa_node); + if ((level != 3) && (ipa_node != NULL)) + { + if (ipa_node->nptr == NULL) + { + ipa_rn = snmp_mib_lrn_alloc(); + ipa_node->nptr = (struct mib_node*)ipa_rn; + if (ipa_rn != NULL) + { + if (level == 2) + { + ipa_rn->get_object_def = ip_addrentry_get_object_def; + ipa_rn->get_value = ip_addrentry_get_value; + ipa_rn->set_test = noleafs_set_test; + ipa_rn->set_value = noleafs_set_value; + } + } + else + { + /* ipa_rn == NULL, malloc failure */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_insert_ipaddridx_tree() insert failed, mem full")); + break; + } + } + else + { + ipa_rn = (struct mib_list_rootnode*)ipa_node->nptr; + } + } + level++; + } + /* enable getnext traversal on filled table */ + ipaddrtable.maxlength = 1; +} + +/** + * Removes ipAddrTable indexes (.ipAdEntAddr) + * from index tree. + */ +void snmp_delete_ipaddridx_tree(struct netif *ni) +{ + struct mib_list_rootnode *ipa_rn, *next, *del_rn[4]; + struct mib_list_node *ipa_n, *del_n[4]; + struct ip_addr ip; + s32_t ipaddridx[4]; + u8_t fc, level, del_cnt; + + LWIP_ASSERT("ni != NULL", ni != NULL); + ip.addr = ntohl(ni->ip_addr.addr); + snmp_iptooid(&ip, &ipaddridx[0]); + + /* mark nodes for deletion */ + level = 0; + del_cnt = 0; + ipa_rn = &ipaddrtree_root; + while ((level < 4) && (ipa_rn != NULL)) + { + fc = snmp_mib_node_find(ipa_rn, ipaddridx[level], &ipa_n); + if (fc == 0) + { + /* ipaddridx[level] does not exist */ + del_cnt = 0; + ipa_rn = NULL; + } + else if (fc == 1) + { + del_rn[del_cnt] = ipa_rn; + del_n[del_cnt] = ipa_n; + del_cnt++; + ipa_rn = (struct mib_list_rootnode*)(ipa_n->nptr); + } + else if (fc == 2) + { + /* reset delete (2 or more childs) */ + del_cnt = 0; + ipa_rn = (struct mib_list_rootnode*)(ipa_n->nptr); + } + level++; + } + /* delete marked index nodes */ + while (del_cnt > 0) + { + del_cnt--; + + ipa_rn = del_rn[del_cnt]; + ipa_n = del_n[del_cnt]; + + next = snmp_mib_node_delete(ipa_rn, ipa_n); + if (next != NULL) + { + LWIP_ASSERT("next_count == 0",next->count == 0); + snmp_mib_lrn_free(next); + } + } + /* disable getnext traversal on empty table */ + if (ipaddrtree_root.count == 0) ipaddrtable.maxlength = 0; +} + +/** + * Inserts ipRouteTable indexes (.ipRouteDest) + * into index tree. + * + * @param dflt non-zero for the default rte, zero for network rte + * @param ni points to network interface for this rte + * + * @todo record sysuptime for _this_ route when it is installed + * (needed for ipRouteAge) in the netif. + */ +void snmp_insert_iprteidx_tree(u8_t dflt, struct netif *ni) +{ + u8_t insert = 0; + struct ip_addr dst; + + if (dflt != 0) + { + /* the default route 0.0.0.0 */ + dst.addr = 0; + insert = 1; + } + else + { + /* route to the network address */ + dst.addr = ntohl(ni->ip_addr.addr & ni->netmask.addr); + /* exclude 0.0.0.0 network (reserved for default rte) */ + if (dst.addr != 0) insert = 1; + } + if (insert) + { + struct mib_list_rootnode *iprte_rn; + struct mib_list_node *iprte_node; + s32_t iprteidx[4]; + u8_t level; + + snmp_iptooid(&dst, &iprteidx[0]); + level = 0; + iprte_rn = &iprtetree_root; + while (level < 4) + { + iprte_node = NULL; + snmp_mib_node_insert(iprte_rn, iprteidx[level], &iprte_node); + if ((level != 3) && (iprte_node != NULL)) + { + if (iprte_node->nptr == NULL) + { + iprte_rn = snmp_mib_lrn_alloc(); + iprte_node->nptr = (struct mib_node*)iprte_rn; + if (iprte_rn != NULL) + { + if (level == 2) + { + iprte_rn->get_object_def = ip_rteentry_get_object_def; + iprte_rn->get_value = ip_rteentry_get_value; + iprte_rn->set_test = noleafs_set_test; + iprte_rn->set_value = noleafs_set_value; + } + } + else + { + /* iprte_rn == NULL, malloc failure */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_insert_iprteidx_tree() insert failed, mem full")); + break; + } + } + else + { + iprte_rn = (struct mib_list_rootnode*)iprte_node->nptr; + } + } + level++; + } + } + /* enable getnext traversal on filled table */ + iprtetable.maxlength = 1; +} + +/** + * Removes ipRouteTable indexes (.ipRouteDest) + * from index tree. + * + * @param dflt non-zero for the default rte, zero for network rte + * @param ni points to network interface for this rte or NULL + * for default route to be removed. + */ +void snmp_delete_iprteidx_tree(u8_t dflt, struct netif *ni) +{ + u8_t delete = 0; + struct ip_addr dst; + + if (dflt != 0) + { + /* the default route 0.0.0.0 */ + dst.addr = 0; + delete = 1; + } + else + { + /* route to the network address */ + dst.addr = ntohl(ni->ip_addr.addr & ni->netmask.addr); + /* exclude 0.0.0.0 network (reserved for default rte) */ + if (dst.addr != 0) delete = 1; + } + if (delete) + { + struct mib_list_rootnode *iprte_rn, *next, *del_rn[4]; + struct mib_list_node *iprte_n, *del_n[4]; + s32_t iprteidx[4]; + u8_t fc, level, del_cnt; + + snmp_iptooid(&dst, &iprteidx[0]); + /* mark nodes for deletion */ + level = 0; + del_cnt = 0; + iprte_rn = &iprtetree_root; + while ((level < 4) && (iprte_rn != NULL)) + { + fc = snmp_mib_node_find(iprte_rn, iprteidx[level], &iprte_n); + if (fc == 0) + { + /* iprteidx[level] does not exist */ + del_cnt = 0; + iprte_rn = NULL; + } + else if (fc == 1) + { + del_rn[del_cnt] = iprte_rn; + del_n[del_cnt] = iprte_n; + del_cnt++; + iprte_rn = (struct mib_list_rootnode*)(iprte_n->nptr); + } + else if (fc == 2) + { + /* reset delete (2 or more childs) */ + del_cnt = 0; + iprte_rn = (struct mib_list_rootnode*)(iprte_n->nptr); + } + level++; + } + /* delete marked index nodes */ + while (del_cnt > 0) + { + del_cnt--; + + iprte_rn = del_rn[del_cnt]; + iprte_n = del_n[del_cnt]; + + next = snmp_mib_node_delete(iprte_rn, iprte_n); + if (next != NULL) + { + LWIP_ASSERT("next_count == 0",next->count == 0); + snmp_mib_lrn_free(next); + } + } + } + /* disable getnext traversal on empty table */ + if (iprtetree_root.count == 0) iprtetable.maxlength = 0; +} + + +void snmp_inc_icmpinmsgs(void) +{ + icmpinmsgs++; +} + +void snmp_inc_icmpinerrors(void) +{ + icmpinerrors++; +} + +void snmp_inc_icmpindestunreachs(void) +{ + icmpindestunreachs++; +} + +void snmp_inc_icmpintimeexcds(void) +{ + icmpintimeexcds++; +} + +void snmp_inc_icmpinparmprobs(void) +{ + icmpinparmprobs++; +} + +void snmp_inc_icmpinsrcquenchs(void) +{ + icmpinsrcquenchs++; +} + +void snmp_inc_icmpinredirects(void) +{ + icmpinredirects++; +} + +void snmp_inc_icmpinechos(void) +{ + icmpinechos++; +} + +void snmp_inc_icmpinechoreps(void) +{ + icmpinechoreps++; +} + +void snmp_inc_icmpintimestamps(void) +{ + icmpintimestamps++; +} + +void snmp_inc_icmpintimestampreps(void) +{ + icmpintimestampreps++; +} + +void snmp_inc_icmpinaddrmasks(void) +{ + icmpinaddrmasks++; +} + +void snmp_inc_icmpinaddrmaskreps(void) +{ + icmpinaddrmaskreps++; +} + +void snmp_inc_icmpoutmsgs(void) +{ + icmpoutmsgs++; +} + +void snmp_inc_icmpouterrors(void) +{ + icmpouterrors++; +} + +void snmp_inc_icmpoutdestunreachs(void) +{ + icmpoutdestunreachs++; +} + +void snmp_inc_icmpouttimeexcds(void) +{ + icmpouttimeexcds++; +} + +void snmp_inc_icmpoutparmprobs(void) +{ + icmpoutparmprobs++; +} + +void snmp_inc_icmpoutsrcquenchs(void) +{ + icmpoutsrcquenchs++; +} + +void snmp_inc_icmpoutredirects(void) +{ + icmpoutredirects++; +} + +void snmp_inc_icmpoutechos(void) +{ + icmpoutechos++; +} + +void snmp_inc_icmpoutechoreps(void) +{ + icmpoutechoreps++; +} + +void snmp_inc_icmpouttimestamps(void) +{ + icmpouttimestamps++; +} + +void snmp_inc_icmpouttimestampreps(void) +{ + icmpouttimestampreps++; +} + +void snmp_inc_icmpoutaddrmasks(void) +{ + icmpoutaddrmasks++; +} + +void snmp_inc_icmpoutaddrmaskreps(void) +{ + icmpoutaddrmaskreps++; +} + +void snmp_inc_tcpactiveopens(void) +{ + tcpactiveopens++; +} + +void snmp_inc_tcppassiveopens(void) +{ + tcppassiveopens++; +} + +void snmp_inc_tcpattemptfails(void) +{ + tcpattemptfails++; +} + +void snmp_inc_tcpestabresets(void) +{ + tcpestabresets++; +} + +void snmp_inc_tcpinsegs(void) +{ + tcpinsegs++; +} + +void snmp_inc_tcpoutsegs(void) +{ + tcpoutsegs++; +} + +void snmp_inc_tcpretranssegs(void) +{ + tcpretranssegs++; +} + +void snmp_inc_tcpinerrs(void) +{ + tcpinerrs++; +} + +void snmp_inc_tcpoutrsts(void) +{ + tcpoutrsts++; +} + +void snmp_inc_udpindatagrams(void) +{ + udpindatagrams++; +} + +void snmp_inc_udpnoports(void) +{ + udpnoports++; +} + +void snmp_inc_udpinerrors(void) +{ + udpinerrors++; +} + +void snmp_inc_udpoutdatagrams(void) +{ + udpoutdatagrams++; +} + +/** + * Inserts udpTable indexes (.udpLocalAddress.udpLocalPort) + * into index tree. + */ +void snmp_insert_udpidx_tree(struct udp_pcb *pcb) +{ + struct mib_list_rootnode *udp_rn; + struct mib_list_node *udp_node; + struct ip_addr ip; + s32_t udpidx[5]; + u8_t level; + + LWIP_ASSERT("pcb != NULL", pcb != NULL); + ip.addr = ntohl(pcb->local_ip.addr); + snmp_iptooid(&ip, &udpidx[0]); + udpidx[4] = pcb->local_port; + + udp_rn = &udp_root; + for (level = 0; level < 5; level++) + { + udp_node = NULL; + snmp_mib_node_insert(udp_rn, udpidx[level], &udp_node); + if ((level != 4) && (udp_node != NULL)) + { + if (udp_node->nptr == NULL) + { + udp_rn = snmp_mib_lrn_alloc(); + udp_node->nptr = (struct mib_node*)udp_rn; + if (udp_rn != NULL) + { + if (level == 3) + { + udp_rn->get_object_def = udpentry_get_object_def; + udp_rn->get_value = udpentry_get_value; + udp_rn->set_test = noleafs_set_test; + udp_rn->set_value = noleafs_set_value; + } + } + else + { + /* udp_rn == NULL, malloc failure */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_insert_udpidx_tree() insert failed, mem full")); + break; + } + } + else + { + udp_rn = (struct mib_list_rootnode*)udp_node->nptr; + } + } + } + udptable.maxlength = 1; +} + +/** + * Removes udpTable indexes (.udpLocalAddress.udpLocalPort) + * from index tree. + */ +void snmp_delete_udpidx_tree(struct udp_pcb *pcb) +{ + struct mib_list_rootnode *udp_rn, *next, *del_rn[5]; + struct mib_list_node *udp_n, *del_n[5]; + struct ip_addr ip; + s32_t udpidx[5]; + u8_t bindings, fc, level, del_cnt; + + LWIP_ASSERT("pcb != NULL", pcb != NULL); + ip.addr = ntohl(pcb->local_ip.addr); + snmp_iptooid(&ip, &udpidx[0]); + udpidx[4] = pcb->local_port; + + /* count PCBs for a given binding + (e.g. when reusing ports or for temp output PCBs) */ + bindings = 0; + pcb = udp_pcbs; + while ((pcb != NULL)) + { + if ((pcb->local_ip.addr == ip.addr) && + (pcb->local_port == udpidx[4])) + { + bindings++; + } + pcb = pcb->next; + } + if (bindings == 1) + { + /* selectively remove */ + /* mark nodes for deletion */ + level = 0; + del_cnt = 0; + udp_rn = &udp_root; + while ((level < 5) && (udp_rn != NULL)) + { + fc = snmp_mib_node_find(udp_rn, udpidx[level], &udp_n); + if (fc == 0) + { + /* udpidx[level] does not exist */ + del_cnt = 0; + udp_rn = NULL; + } + else if (fc == 1) + { + del_rn[del_cnt] = udp_rn; + del_n[del_cnt] = udp_n; + del_cnt++; + udp_rn = (struct mib_list_rootnode*)(udp_n->nptr); + } + else if (fc == 2) + { + /* reset delete (2 or more childs) */ + del_cnt = 0; + udp_rn = (struct mib_list_rootnode*)(udp_n->nptr); + } + level++; + } + /* delete marked index nodes */ + while (del_cnt > 0) + { + del_cnt--; + + udp_rn = del_rn[del_cnt]; + udp_n = del_n[del_cnt]; + + next = snmp_mib_node_delete(udp_rn, udp_n); + if (next != NULL) + { + LWIP_ASSERT("next_count == 0",next->count == 0); + snmp_mib_lrn_free(next); + } + } + } + /* disable getnext traversal on empty table */ + if (udp_root.count == 0) udptable.maxlength = 0; +} + + +void snmp_inc_snmpinpkts(void) +{ + snmpinpkts++; +} + +void snmp_inc_snmpoutpkts(void) +{ + snmpoutpkts++; +} + +void snmp_inc_snmpinbadversions(void) +{ + snmpinbadversions++; +} + +void snmp_inc_snmpinbadcommunitynames(void) +{ + snmpinbadcommunitynames++; +} + +void snmp_inc_snmpinbadcommunityuses(void) +{ + snmpinbadcommunityuses++; +} + +void snmp_inc_snmpinasnparseerrs(void) +{ + snmpinasnparseerrs++; +} + +void snmp_inc_snmpintoobigs(void) +{ + snmpintoobigs++; +} + +void snmp_inc_snmpinnosuchnames(void) +{ + snmpinnosuchnames++; +} + +void snmp_inc_snmpinbadvalues(void) +{ + snmpinbadvalues++; +} + +void snmp_inc_snmpinreadonlys(void) +{ + snmpinreadonlys++; +} + +void snmp_inc_snmpingenerrs(void) +{ + snmpingenerrs++; +} + +void snmp_add_snmpintotalreqvars(u8_t value) +{ + snmpintotalreqvars += value; +} + +void snmp_add_snmpintotalsetvars(u8_t value) +{ + snmpintotalsetvars += value; +} + +void snmp_inc_snmpingetrequests(void) +{ + snmpingetrequests++; +} + +void snmp_inc_snmpingetnexts(void) +{ + snmpingetnexts++; +} + +void snmp_inc_snmpinsetrequests(void) +{ + snmpinsetrequests++; +} + +void snmp_inc_snmpingetresponses(void) +{ + snmpingetresponses++; +} + +void snmp_inc_snmpintraps(void) +{ + snmpintraps++; +} + +void snmp_inc_snmpouttoobigs(void) +{ + snmpouttoobigs++; +} + +void snmp_inc_snmpoutnosuchnames(void) +{ + snmpoutnosuchnames++; +} + +void snmp_inc_snmpoutbadvalues(void) +{ + snmpoutbadvalues++; +} + +void snmp_inc_snmpoutgenerrs(void) +{ + snmpoutgenerrs++; +} + +void snmp_inc_snmpoutgetrequests(void) +{ + snmpoutgetrequests++; +} + +void snmp_inc_snmpoutgetnexts(void) +{ + snmpoutgetnexts++; +} + +void snmp_inc_snmpoutsetrequests(void) +{ + snmpoutsetrequests++; +} + +void snmp_inc_snmpoutgetresponses(void) +{ + snmpoutgetresponses++; +} + +void snmp_inc_snmpouttraps(void) +{ + snmpouttraps++; +} + +void snmp_get_snmpgrpid_ptr(struct snmp_obj_id **oid) +{ + *oid = &snmpgrp_id; +} + +void snmp_set_snmpenableauthentraps(u8_t *value) +{ + if (value != NULL) + { + snmpenableauthentraps_ptr = value; + } +} + +void snmp_get_snmpenableauthentraps(u8_t *value) +{ + *value = *snmpenableauthentraps_ptr; +} + +void +noleafs_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + LWIP_UNUSED_ARG(ident_len); + LWIP_UNUSED_ARG(ident); + od->instance = MIB_OBJECT_NONE; +} + +void +noleafs_get_value(struct obj_def *od, u16_t len, void *value) +{ + LWIP_UNUSED_ARG(od); + LWIP_UNUSED_ARG(len); + LWIP_UNUSED_ARG(value); +} + +u8_t +noleafs_set_test(struct obj_def *od, u16_t len, void *value) +{ + LWIP_UNUSED_ARG(od); + LWIP_UNUSED_ARG(len); + LWIP_UNUSED_ARG(value); + /* can't set */ + return 0; +} + +void +noleafs_set_value(struct obj_def *od, u16_t len, void *value) +{ + LWIP_UNUSED_ARG(od); + LWIP_UNUSED_ARG(len); + LWIP_UNUSED_ARG(value); +} + + +/** + * Returns systems object definitions. + * + * @param ident_len the address length (2) + * @param ident points to objectname.0 (object id trailer) + * @param od points to object definition. + */ +static void +system_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + u8_t id; + + /* return to object name, adding index depth (1) */ + ident_len += 1; + ident -= 1; + if (ident_len == 2) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + id = ident[0]; + LWIP_DEBUGF(SNMP_MIB_DEBUG,("get_object_def system.%"U16_F".0\n",(u16_t)id)); + switch (id) + { + case 1: /* sysDescr */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); + od->v_len = *sysdescr_len_ptr; + break; + case 2: /* sysObjectID */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID); + od->v_len = sysobjid.len * sizeof(s32_t); + break; + case 3: /* sysUpTime */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS); + od->v_len = sizeof(u32_t); + break; + case 4: /* sysContact */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); + od->v_len = *syscontact_len_ptr; + break; + case 5: /* sysName */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); + od->v_len = *sysname_len_ptr; + break; + case 6: /* sysLocation */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); + od->v_len = *syslocation_len_ptr; + break; + case 7: /* sysServices */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + }; + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +/** + * Returns system object value. + * + * @param ident_len the address length (2) + * @param ident points to objectname.0 (object id trailer) + * @param len return value space (in bytes) + * @param value points to (varbind) space to copy value into. + */ +static void +system_get_value(struct obj_def *od, u16_t len, void *value) +{ + u8_t id; + + id = od->id_inst_ptr[0]; + switch (id) + { + case 1: /* sysDescr */ + ocstrncpy(value,sysdescr_ptr, len); + break; + case 2: /* sysObjectID */ + objectidncpy((s32_t*)value, (s32_t*)sysobjid.id, (u8_t)(len / sizeof(s32_t))); + break; + case 3: /* sysUpTime */ + { + snmp_get_sysuptime(value); + } + break; + case 4: /* sysContact */ + ocstrncpy(value,syscontact_ptr,len); + break; + case 5: /* sysName */ + ocstrncpy(value,sysname_ptr,len); + break; + case 6: /* sysLocation */ + ocstrncpy(value,syslocation_ptr,len); + break; + case 7: /* sysServices */ + { + s32_t *sint_ptr = value; + *sint_ptr = sysservices; + } + break; + }; +} + +static u8_t +system_set_test(struct obj_def *od, u16_t len, void *value) +{ + u8_t id, set_ok; + + LWIP_UNUSED_ARG(value); + set_ok = 0; + id = od->id_inst_ptr[0]; + switch (id) + { + case 4: /* sysContact */ + if ((syscontact_ptr != syscontact_default) && + (len <= 255)) + { + set_ok = 1; + } + break; + case 5: /* sysName */ + if ((sysname_ptr != sysname_default) && + (len <= 255)) + { + set_ok = 1; + } + break; + case 6: /* sysLocation */ + if ((syslocation_ptr != syslocation_default) && + (len <= 255)) + { + set_ok = 1; + } + break; + }; + return set_ok; +} + +static void +system_set_value(struct obj_def *od, u16_t len, void *value) +{ + u8_t id; + + id = od->id_inst_ptr[0]; + switch (id) + { + case 4: /* sysContact */ + ocstrncpy(syscontact_ptr,value,len); + *syscontact_len_ptr = len; + break; + case 5: /* sysName */ + ocstrncpy(sysname_ptr,value,len); + *sysname_len_ptr = len; + break; + case 6: /* sysLocation */ + ocstrncpy(syslocation_ptr,value,len); + *syslocation_len_ptr = len; + break; + }; +} + +/** + * Returns interfaces.ifnumber object definition. + * + * @param ident_len the address length (2) + * @param ident points to objectname.index + * @param od points to object definition. + */ +static void +interfaces_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + /* return to object name, adding index depth (1) */ + ident_len += 1; + ident -= 1; + if (ident_len == 2) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("interfaces_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +/** + * Returns interfaces.ifnumber object value. + * + * @param ident_len the address length (2) + * @param ident points to objectname.0 (object id trailer) + * @param len return value space (in bytes) + * @param value points to (varbind) space to copy value into. + */ +static void +interfaces_get_value(struct obj_def *od, u16_t len, void *value) +{ + LWIP_UNUSED_ARG(len); + if (od->id_inst_ptr[0] == 1) + { + s32_t *sint_ptr = value; + *sint_ptr = iflist_root.count; + } +} + +/** + * Returns ifentry object definitions. + * + * @param ident_len the address length (2) + * @param ident points to objectname.index + * @param od points to object definition. + */ +static void +ifentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + u8_t id; + + /* return to object name, adding index depth (1) */ + ident_len += 1; + ident -= 1; + if (ident_len == 2) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + id = ident[0]; + LWIP_DEBUGF(SNMP_MIB_DEBUG,("get_object_def ifentry.%"U16_F"\n",(u16_t)id)); + switch (id) + { + case 1: /* ifIndex */ + case 3: /* ifType */ + case 4: /* ifMtu */ + case 8: /* ifOperStatus */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + case 2: /* ifDescr */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); + /** @todo this should be some sort of sizeof(struct netif.name) */ + od->v_len = 2; + break; + case 5: /* ifSpeed */ + case 21: /* ifOutQLen */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE); + od->v_len = sizeof(u32_t); + break; + case 6: /* ifPhysAddress */ + { + struct netif *netif; + + snmp_ifindextonetif(ident[1], &netif); + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); + od->v_len = netif->hwaddr_len; + } + break; + case 7: /* ifAdminStatus */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + case 9: /* ifLastChange */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS); + od->v_len = sizeof(u32_t); + break; + case 10: /* ifInOctets */ + case 11: /* ifInUcastPkts */ + case 12: /* ifInNUcastPkts */ + case 13: /* ifInDiscarts */ + case 14: /* ifInErrors */ + case 15: /* ifInUnkownProtos */ + case 16: /* ifOutOctets */ + case 17: /* ifOutUcastPkts */ + case 18: /* ifOutNUcastPkts */ + case 19: /* ifOutDiscarts */ + case 20: /* ifOutErrors */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER); + od->v_len = sizeof(u32_t); + break; + case 22: /* ifSpecific */ + /** @note returning zeroDotZero (0.0) no media specific MIB support */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID); + od->v_len = ifspecific.len * sizeof(s32_t); + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ifentry_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + }; + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ifentry_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +/** + * Returns ifentry object value. + * + * @param ident_len the address length (2) + * @param ident points to objectname.0 (object id trailer) + * @param len return value space (in bytes) + * @param value points to (varbind) space to copy value into. + */ +static void +ifentry_get_value(struct obj_def *od, u16_t len, void *value) +{ + struct netif *netif; + u8_t id; + + snmp_ifindextonetif(od->id_inst_ptr[1], &netif); + id = od->id_inst_ptr[0]; + switch (id) + { + case 1: /* ifIndex */ + { + s32_t *sint_ptr = value; + *sint_ptr = od->id_inst_ptr[1]; + } + break; + case 2: /* ifDescr */ + ocstrncpy(value,(u8_t*)netif->name,len); + break; + case 3: /* ifType */ + { + s32_t *sint_ptr = value; + *sint_ptr = netif->link_type; + } + break; + case 4: /* ifMtu */ + { + s32_t *sint_ptr = value; + *sint_ptr = netif->mtu; + } + break; + case 5: /* ifSpeed */ + { + u32_t *uint_ptr = value; + *uint_ptr = netif->link_speed; + } + break; + case 6: /* ifPhysAddress */ + ocstrncpy(value,netif->hwaddr,len); + break; + case 7: /* ifAdminStatus */ +#if LWIP_NETIF_LINK_CALLBACK + { + s32_t *sint_ptr = value; + if (netif_is_up(netif)) + { + if (netif_is_link_up(netif)) + { + *sint_ptr = 1; /* up */ + } + else + { + *sint_ptr = 7; /* lowerLayerDown */ + } + } + else + { + *sint_ptr = 2; /* down */ + } + } + break; +#endif + case 8: /* ifOperStatus */ + { + s32_t *sint_ptr = value; + if (netif_is_up(netif)) + { + *sint_ptr = 1; + } + else + { + *sint_ptr = 2; + } + } + break; + case 9: /* ifLastChange */ + { + u32_t *uint_ptr = value; + *uint_ptr = netif->ts; + } + break; + case 10: /* ifInOctets */ + { + u32_t *uint_ptr = value; + *uint_ptr = netif->ifinoctets; + } + break; + case 11: /* ifInUcastPkts */ + { + u32_t *uint_ptr = value; + *uint_ptr = netif->ifinucastpkts; + } + break; + case 12: /* ifInNUcastPkts */ + { + u32_t *uint_ptr = value; + *uint_ptr = netif->ifinnucastpkts; + } + break; + case 13: /* ifInDiscarts */ + { + u32_t *uint_ptr = value; + *uint_ptr = netif->ifindiscards; + } + break; + case 14: /* ifInErrors */ + case 15: /* ifInUnkownProtos */ + /** @todo add these counters! */ + { + u32_t *uint_ptr = value; + *uint_ptr = 0; + } + break; + case 16: /* ifOutOctets */ + { + u32_t *uint_ptr = value; + *uint_ptr = netif->ifoutoctets; + } + break; + case 17: /* ifOutUcastPkts */ + { + u32_t *uint_ptr = value; + *uint_ptr = netif->ifoutucastpkts; + } + break; + case 18: /* ifOutNUcastPkts */ + { + u32_t *uint_ptr = value; + *uint_ptr = netif->ifoutnucastpkts; + } + break; + case 19: /* ifOutDiscarts */ + { + u32_t *uint_ptr = value; + *uint_ptr = netif->ifoutdiscards; + } + break; + case 20: /* ifOutErrors */ + /** @todo add this counter! */ + { + u32_t *uint_ptr = value; + *uint_ptr = 0; + } + break; + case 21: /* ifOutQLen */ + /** @todo figure out if this must be 0 (no queue) or 1? */ + { + u32_t *uint_ptr = value; + *uint_ptr = 0; + } + break; + case 22: /* ifSpecific */ + objectidncpy((s32_t*)value, (s32_t*)ifspecific.id, (u8_t)(len / sizeof(s32_t))); + break; + }; +} + +#if !SNMP_SAFE_REQUESTS +static u8_t +ifentry_set_test (struct obj_def *od, u16_t len, void *value) +{ + struct netif *netif; + u8_t id, set_ok; + + set_ok = 0; + snmp_ifindextonetif(od->id_inst_ptr[1], &netif); + id = od->id_inst_ptr[0]; + switch (id) + { + case 7: /* ifAdminStatus */ + { + s32_t *sint_ptr = value; + if (*sint_ptr == 1 || *sint_ptr == 2) + set_ok = 1; + } + break; + } + return set_ok; +} + +static void +ifentry_set_value (struct obj_def *od, u16_t len, void *value) +{ + struct netif *netif; + u8_t id; + + snmp_ifindextonetif(od->id_inst_ptr[1], &netif); + id = od->id_inst_ptr[0]; + switch (id) + { + case 7: /* ifAdminStatus */ + { + s32_t *sint_ptr = value; + if (*sint_ptr == 1) + { + netif_set_up(netif); + } + else if (*sint_ptr == 2) + { + netif_set_down(netif); + } + } + break; + } +} +#endif /* SNMP_SAFE_REQUESTS */ + +/** + * Returns atentry object definitions. + * + * @param ident_len the address length (6) + * @param ident points to objectname.atifindex.atnetaddress + * @param od points to object definition. + */ +static void +atentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + /* return to object name, adding index depth (5) */ + ident_len += 5; + ident -= 5; + + if (ident_len == 6) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + switch (ident[0]) + { + case 1: /* atIfIndex */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + case 2: /* atPhysAddress */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); + od->v_len = 6; /** @todo try to use netif::hwaddr_len */ + break; + case 3: /* atNetAddress */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR); + od->v_len = 4; + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("atentry_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + } + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("atentry_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +atentry_get_value(struct obj_def *od, u16_t len, void *value) +{ +#if LWIP_ARP + u8_t id; + struct eth_addr* ethaddr_ret; + struct ip_addr* ipaddr_ret; +#endif /* LWIP_ARP */ + struct ip_addr ip; + struct netif *netif; + + LWIP_UNUSED_ARG(len); + LWIP_UNUSED_ARG(value);/* if !LWIP_ARP */ + + snmp_ifindextonetif(od->id_inst_ptr[1], &netif); + snmp_oidtoip(&od->id_inst_ptr[2], &ip); + ip.addr = htonl(ip.addr); + +#if LWIP_ARP /** @todo implement a netif_find_addr */ + if (etharp_find_addr(netif, &ip, ðaddr_ret, &ipaddr_ret) > -1) + { + id = od->id_inst_ptr[0]; + switch (id) + { + case 1: /* atIfIndex */ + { + s32_t *sint_ptr = value; + *sint_ptr = od->id_inst_ptr[1]; + } + break; + case 2: /* atPhysAddress */ + { + struct eth_addr *dst = value; + + *dst = *ethaddr_ret; + } + break; + case 3: /* atNetAddress */ + { + struct ip_addr *dst = value; + + *dst = *ipaddr_ret; + } + break; + } + } +#endif /* LWIP_ARP */ +} + +static void +ip_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + u8_t id; + + /* return to object name, adding index depth (1) */ + ident_len += 1; + ident -= 1; + if (ident_len == 2) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + id = ident[0]; + LWIP_DEBUGF(SNMP_MIB_DEBUG,("get_object_def ip.%"U16_F".0\n",(u16_t)id)); + switch (id) + { + case 1: /* ipForwarding */ + case 2: /* ipDefaultTTL */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + case 3: /* ipInReceives */ + case 4: /* ipInHdrErrors */ + case 5: /* ipInAddrErrors */ + case 6: /* ipForwDatagrams */ + case 7: /* ipInUnknownProtos */ + case 8: /* ipInDiscards */ + case 9: /* ipInDelivers */ + case 10: /* ipOutRequests */ + case 11: /* ipOutDiscards */ + case 12: /* ipOutNoRoutes */ + case 14: /* ipReasmReqds */ + case 15: /* ipReasmOKs */ + case 16: /* ipReasmFails */ + case 17: /* ipFragOKs */ + case 18: /* ipFragFails */ + case 19: /* ipFragCreates */ + case 23: /* ipRoutingDiscards */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER); + od->v_len = sizeof(u32_t); + break; + case 13: /* ipReasmTimeout */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + }; + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +ip_get_value(struct obj_def *od, u16_t len, void *value) +{ + u8_t id; + + LWIP_UNUSED_ARG(len); + id = od->id_inst_ptr[0]; + switch (id) + { + case 1: /* ipForwarding */ + { + s32_t *sint_ptr = value; +#if IP_FORWARD + /* forwarding */ + *sint_ptr = 1; +#else + /* not-forwarding */ + *sint_ptr = 2; +#endif + } + break; + case 2: /* ipDefaultTTL */ + { + s32_t *sint_ptr = value; + *sint_ptr = IP_DEFAULT_TTL; + } + break; + case 3: /* ipInReceives */ + { + u32_t *uint_ptr = value; + *uint_ptr = ipinreceives; + } + break; + case 4: /* ipInHdrErrors */ + { + u32_t *uint_ptr = value; + *uint_ptr = ipinhdrerrors; + } + break; + case 5: /* ipInAddrErrors */ + { + u32_t *uint_ptr = value; + *uint_ptr = ipinaddrerrors; + } + break; + case 6: /* ipForwDatagrams */ + { + u32_t *uint_ptr = value; + *uint_ptr = ipforwdatagrams; + } + break; + case 7: /* ipInUnknownProtos */ + { + u32_t *uint_ptr = value; + *uint_ptr = ipinunknownprotos; + } + break; + case 8: /* ipInDiscards */ + { + u32_t *uint_ptr = value; + *uint_ptr = ipindiscards; + } + break; + case 9: /* ipInDelivers */ + { + u32_t *uint_ptr = value; + *uint_ptr = ipindelivers; + } + break; + case 10: /* ipOutRequests */ + { + u32_t *uint_ptr = value; + *uint_ptr = ipoutrequests; + } + break; + case 11: /* ipOutDiscards */ + { + u32_t *uint_ptr = value; + *uint_ptr = ipoutdiscards; + } + break; + case 12: /* ipOutNoRoutes */ + { + u32_t *uint_ptr = value; + *uint_ptr = ipoutnoroutes; + } + break; + case 13: /* ipReasmTimeout */ + { + s32_t *sint_ptr = value; +#if IP_REASSEMBLY + *sint_ptr = IP_REASS_MAXAGE; +#else + *sint_ptr = 0; +#endif + } + break; + case 14: /* ipReasmReqds */ + { + u32_t *uint_ptr = value; + *uint_ptr = ipreasmreqds; + } + break; + case 15: /* ipReasmOKs */ + { + u32_t *uint_ptr = value; + *uint_ptr = ipreasmoks; + } + break; + case 16: /* ipReasmFails */ + { + u32_t *uint_ptr = value; + *uint_ptr = ipreasmfails; + } + break; + case 17: /* ipFragOKs */ + { + u32_t *uint_ptr = value; + *uint_ptr = ipfragoks; + } + break; + case 18: /* ipFragFails */ + { + u32_t *uint_ptr = value; + *uint_ptr = ipfragfails; + } + break; + case 19: /* ipFragCreates */ + { + u32_t *uint_ptr = value; + *uint_ptr = ipfragcreates; + } + break; + case 23: /* ipRoutingDiscards */ + /** @todo can lwIP discard routes at all?? hardwire this to 0?? */ + { + u32_t *uint_ptr = value; + *uint_ptr = iproutingdiscards; + } + break; + }; +} + +/** + * Test ip object value before setting. + * + * @param od is the object definition + * @param len return value space (in bytes) + * @param value points to (varbind) space to copy value from. + * + * @note we allow set if the value matches the hardwired value, + * otherwise return badvalue. + */ +static u8_t +ip_set_test(struct obj_def *od, u16_t len, void *value) +{ + u8_t id, set_ok; + s32_t *sint_ptr = value; + + LWIP_UNUSED_ARG(len); + set_ok = 0; + id = od->id_inst_ptr[0]; + switch (id) + { + case 1: /* ipForwarding */ +#if IP_FORWARD + /* forwarding */ + if (*sint_ptr == 1) +#else + /* not-forwarding */ + if (*sint_ptr == 2) +#endif + { + set_ok = 1; + } + break; + case 2: /* ipDefaultTTL */ + if (*sint_ptr == IP_DEFAULT_TTL) + { + set_ok = 1; + } + break; + }; + return set_ok; +} + +static void +ip_addrentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + /* return to object name, adding index depth (4) */ + ident_len += 4; + ident -= 4; + + if (ident_len == 5) + { + u8_t id; + + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + id = ident[0]; + switch (id) + { + case 1: /* ipAdEntAddr */ + case 3: /* ipAdEntNetMask */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR); + od->v_len = 4; + break; + case 2: /* ipAdEntIfIndex */ + case 4: /* ipAdEntBcastAddr */ + case 5: /* ipAdEntReasmMaxSize */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_addrentry_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + } + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_addrentry_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +ip_addrentry_get_value(struct obj_def *od, u16_t len, void *value) +{ + u8_t id; + u16_t ifidx; + struct ip_addr ip; + struct netif *netif = netif_list; + + LWIP_UNUSED_ARG(len); + snmp_oidtoip(&od->id_inst_ptr[1], &ip); + ip.addr = htonl(ip.addr); + ifidx = 0; + while ((netif != NULL) && !ip_addr_cmp(&ip, &netif->ip_addr)) + { + netif = netif->next; + ifidx++; + } + + if (netif != NULL) + { + id = od->id_inst_ptr[0]; + switch (id) + { + case 1: /* ipAdEntAddr */ + { + struct ip_addr *dst = value; + *dst = netif->ip_addr; + } + break; + case 2: /* ipAdEntIfIndex */ + { + s32_t *sint_ptr = value; + *sint_ptr = ifidx + 1; + } + break; + case 3: /* ipAdEntNetMask */ + { + struct ip_addr *dst = value; + *dst = netif->netmask; + } + break; + case 4: /* ipAdEntBcastAddr */ + { + s32_t *sint_ptr = value; + + /* lwIP oddity, there's no broadcast + address in the netif we can rely on */ + *sint_ptr = ip_addr_broadcast.addr & 1; + } + break; + case 5: /* ipAdEntReasmMaxSize */ + { + s32_t *sint_ptr = value; +#if IP_REASSEMBLY + /* @todo The theoretical maximum is IP_REASS_MAX_PBUFS * size of the pbufs, + * but only if receiving one fragmented packet at a time. + * The current solution is to calculate for 2 simultaneous packets... + */ + *sint_ptr = (IP_HLEN + ((IP_REASS_MAX_PBUFS/2) * + (PBUF_POOL_BUFSIZE - PBUF_LINK_HLEN - IP_HLEN))); +#else + /** @todo returning MTU would be a bad thing and + returning a wild guess like '576' isn't good either */ + *sint_ptr = 0; +#endif + } + break; + } + } +} + +/** + * @note + * lwIP IP routing is currently using the network addresses in netif_list. + * if no suitable network IP is found in netif_list, the default_netif is used. + */ +static void +ip_rteentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + u8_t id; + + /* return to object name, adding index depth (4) */ + ident_len += 4; + ident -= 4; + + if (ident_len == 5) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + id = ident[0]; + switch (id) + { + case 1: /* ipRouteDest */ + case 7: /* ipRouteNextHop */ + case 11: /* ipRouteMask */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR); + od->v_len = 4; + break; + case 2: /* ipRouteIfIndex */ + case 3: /* ipRouteMetric1 */ + case 4: /* ipRouteMetric2 */ + case 5: /* ipRouteMetric3 */ + case 6: /* ipRouteMetric4 */ + case 8: /* ipRouteType */ + case 10: /* ipRouteAge */ + case 12: /* ipRouteMetric5 */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + case 9: /* ipRouteProto */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + case 13: /* ipRouteInfo */ + /** @note returning zeroDotZero (0.0) no routing protocol specific MIB */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID); + od->v_len = iprouteinfo.len * sizeof(s32_t); + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_rteentry_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + } + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_rteentry_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +ip_rteentry_get_value(struct obj_def *od, u16_t len, void *value) +{ + struct netif *netif; + struct ip_addr dest; + s32_t *ident; + u8_t id; + + ident = od->id_inst_ptr; + snmp_oidtoip(&ident[1], &dest); + dest.addr = htonl(dest.addr); + + if (dest.addr == 0) + { + /* ip_route() uses default netif for default route */ + netif = netif_default; + } + else + { + /* not using ip_route(), need exact match! */ + netif = netif_list; + while ((netif != NULL) && + !ip_addr_netcmp(&dest, &(netif->ip_addr), &(netif->netmask)) ) + { + netif = netif->next; + } + } + if (netif != NULL) + { + id = ident[0]; + switch (id) + { + case 1: /* ipRouteDest */ + { + struct ip_addr *dst = value; + + if (dest.addr == 0) + { + /* default rte has 0.0.0.0 dest */ + dst->addr = 0; + } + else + { + /* netifs have netaddress dest */ + dst->addr = netif->ip_addr.addr & netif->netmask.addr; + } + } + break; + case 2: /* ipRouteIfIndex */ + { + s32_t *sint_ptr = value; + + snmp_netiftoifindex(netif, sint_ptr); + } + break; + case 3: /* ipRouteMetric1 */ + { + s32_t *sint_ptr = value; + + if (dest.addr == 0) + { + /* default rte has metric 1 */ + *sint_ptr = 1; + } + else + { + /* other rtes have metric 0 */ + *sint_ptr = 0; + } + } + break; + case 4: /* ipRouteMetric2 */ + case 5: /* ipRouteMetric3 */ + case 6: /* ipRouteMetric4 */ + case 12: /* ipRouteMetric5 */ + { + s32_t *sint_ptr = value; + /* not used */ + *sint_ptr = -1; + } + break; + case 7: /* ipRouteNextHop */ + { + struct ip_addr *dst = value; + + if (dest.addr == 0) + { + /* default rte: gateway */ + *dst = netif->gw; + } + else + { + /* other rtes: netif ip_addr */ + *dst = netif->ip_addr; + } + } + break; + case 8: /* ipRouteType */ + { + s32_t *sint_ptr = value; + + if (dest.addr == 0) + { + /* default rte is indirect */ + *sint_ptr = 4; + } + else + { + /* other rtes are direct */ + *sint_ptr = 3; + } + } + break; + case 9: /* ipRouteProto */ + { + s32_t *sint_ptr = value; + /* locally defined routes */ + *sint_ptr = 2; + } + break; + case 10: /* ipRouteAge */ + { + s32_t *sint_ptr = value; + /** @todo (sysuptime - timestamp last change) / 100 + @see snmp_insert_iprteidx_tree() */ + *sint_ptr = 0; + } + break; + case 11: /* ipRouteMask */ + { + struct ip_addr *dst = value; + + if (dest.addr == 0) + { + /* default rte use 0.0.0.0 mask */ + dst->addr = 0; + } + else + { + /* other rtes use netmask */ + *dst = netif->netmask; + } + } + break; + case 13: /* ipRouteInfo */ + objectidncpy((s32_t*)value, (s32_t*)iprouteinfo.id, (u8_t)(len / sizeof(s32_t))); + break; + } + } +} + +static void +ip_ntomentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + /* return to object name, adding index depth (5) */ + ident_len += 5; + ident -= 5; + + if (ident_len == 6) + { + u8_t id; + + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + id = ident[0]; + switch (id) + { + case 1: /* ipNetToMediaIfIndex */ + case 4: /* ipNetToMediaType */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + case 2: /* ipNetToMediaPhysAddress */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); + od->v_len = 6; /** @todo try to use netif::hwaddr_len */ + break; + case 3: /* ipNetToMediaNetAddress */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR); + od->v_len = 4; + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_ntomentry_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + } + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_ntomentry_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +ip_ntomentry_get_value(struct obj_def *od, u16_t len, void *value) +{ +#if LWIP_ARP + u8_t id; + struct eth_addr* ethaddr_ret; + struct ip_addr* ipaddr_ret; +#endif /* LWIP_ARP */ + struct ip_addr ip; + struct netif *netif; + + LWIP_UNUSED_ARG(len); + LWIP_UNUSED_ARG(value);/* if !LWIP_ARP */ + + snmp_ifindextonetif(od->id_inst_ptr[1], &netif); + snmp_oidtoip(&od->id_inst_ptr[2], &ip); + ip.addr = htonl(ip.addr); + +#if LWIP_ARP /** @todo implement a netif_find_addr */ + if (etharp_find_addr(netif, &ip, ðaddr_ret, &ipaddr_ret) > -1) + { + id = od->id_inst_ptr[0]; + switch (id) + { + case 1: /* ipNetToMediaIfIndex */ + { + s32_t *sint_ptr = value; + *sint_ptr = od->id_inst_ptr[1]; + } + break; + case 2: /* ipNetToMediaPhysAddress */ + { + struct eth_addr *dst = value; + + *dst = *ethaddr_ret; + } + break; + case 3: /* ipNetToMediaNetAddress */ + { + struct ip_addr *dst = value; + + *dst = *ipaddr_ret; + } + break; + case 4: /* ipNetToMediaType */ + { + s32_t *sint_ptr = value; + /* dynamic (?) */ + *sint_ptr = 3; + } + break; + } + } +#endif /* LWIP_ARP */ +} + +static void +icmp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + /* return to object name, adding index depth (1) */ + ident_len += 1; + ident -= 1; + if ((ident_len == 2) && + (ident[0] > 0) && (ident[0] < 27)) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER); + od->v_len = sizeof(u32_t); + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("icmp_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +icmp_get_value(struct obj_def *od, u16_t len, void *value) +{ + u32_t *uint_ptr = value; + u8_t id; + + LWIP_UNUSED_ARG(len); + id = od->id_inst_ptr[0]; + switch (id) + { + case 1: /* icmpInMsgs */ + *uint_ptr = icmpinmsgs; + break; + case 2: /* icmpInErrors */ + *uint_ptr = icmpinerrors; + break; + case 3: /* icmpInDestUnreachs */ + *uint_ptr = icmpindestunreachs; + break; + case 4: /* icmpInTimeExcds */ + *uint_ptr = icmpintimeexcds; + break; + case 5: /* icmpInParmProbs */ + *uint_ptr = icmpinparmprobs; + break; + case 6: /* icmpInSrcQuenchs */ + *uint_ptr = icmpinsrcquenchs; + break; + case 7: /* icmpInRedirects */ + *uint_ptr = icmpinredirects; + break; + case 8: /* icmpInEchos */ + *uint_ptr = icmpinechos; + break; + case 9: /* icmpInEchoReps */ + *uint_ptr = icmpinechoreps; + break; + case 10: /* icmpInTimestamps */ + *uint_ptr = icmpintimestamps; + break; + case 11: /* icmpInTimestampReps */ + *uint_ptr = icmpintimestampreps; + break; + case 12: /* icmpInAddrMasks */ + *uint_ptr = icmpinaddrmasks; + break; + case 13: /* icmpInAddrMaskReps */ + *uint_ptr = icmpinaddrmaskreps; + break; + case 14: /* icmpOutMsgs */ + *uint_ptr = icmpoutmsgs; + break; + case 15: /* icmpOutErrors */ + *uint_ptr = icmpouterrors; + break; + case 16: /* icmpOutDestUnreachs */ + *uint_ptr = icmpoutdestunreachs; + break; + case 17: /* icmpOutTimeExcds */ + *uint_ptr = icmpouttimeexcds; + break; + case 18: /* icmpOutParmProbs */ + *uint_ptr = icmpoutparmprobs; + break; + case 19: /* icmpOutSrcQuenchs */ + *uint_ptr = icmpoutsrcquenchs; + break; + case 20: /* icmpOutRedirects */ + *uint_ptr = icmpoutredirects; + break; + case 21: /* icmpOutEchos */ + *uint_ptr = icmpoutechos; + break; + case 22: /* icmpOutEchoReps */ + *uint_ptr = icmpoutechoreps; + break; + case 23: /* icmpOutTimestamps */ + *uint_ptr = icmpouttimestamps; + break; + case 24: /* icmpOutTimestampReps */ + *uint_ptr = icmpouttimestampreps; + break; + case 25: /* icmpOutAddrMasks */ + *uint_ptr = icmpoutaddrmasks; + break; + case 26: /* icmpOutAddrMaskReps */ + *uint_ptr = icmpoutaddrmaskreps; + break; + } +} + +#if LWIP_TCP +/** @todo tcp grp */ +static void +tcp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + u8_t id; + + /* return to object name, adding index depth (1) */ + ident_len += 1; + ident -= 1; + if (ident_len == 2) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + id = ident[0]; + LWIP_DEBUGF(SNMP_MIB_DEBUG,("get_object_def tcp.%"U16_F".0\n",(u16_t)id)); + + switch (id) + { + case 1: /* tcpRtoAlgorithm */ + case 2: /* tcpRtoMin */ + case 3: /* tcpRtoMax */ + case 4: /* tcpMaxConn */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + case 5: /* tcpActiveOpens */ + case 6: /* tcpPassiveOpens */ + case 7: /* tcpAttemptFails */ + case 8: /* tcpEstabResets */ + case 10: /* tcpInSegs */ + case 11: /* tcpOutSegs */ + case 12: /* tcpRetransSegs */ + case 14: /* tcpInErrs */ + case 15: /* tcpOutRsts */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER); + od->v_len = sizeof(u32_t); + break; + case 9: /* tcpCurrEstab */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE); + od->v_len = sizeof(u32_t); + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("tcp_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + }; + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("tcp_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +tcp_get_value(struct obj_def *od, u16_t len, void *value) +{ + u32_t *uint_ptr = value; + s32_t *sint_ptr = value; + u8_t id; + + LWIP_UNUSED_ARG(len); + id = od->id_inst_ptr[0]; + switch (id) + { + case 1: /* tcpRtoAlgorithm, vanj(4) */ + *sint_ptr = 4; + break; + case 2: /* tcpRtoMin */ + /* @todo not the actual value, a guess, + needs to be calculated */ + *sint_ptr = 1000; + break; + case 3: /* tcpRtoMax */ + /* @todo not the actual value, a guess, + needs to be calculated */ + *sint_ptr = 60000; + break; + case 4: /* tcpMaxConn */ + *sint_ptr = MEMP_NUM_TCP_PCB; + break; + case 5: /* tcpActiveOpens */ + *uint_ptr = tcpactiveopens; + break; + case 6: /* tcpPassiveOpens */ + *uint_ptr = tcppassiveopens; + break; + case 7: /* tcpAttemptFails */ + *uint_ptr = tcpattemptfails; + break; + case 8: /* tcpEstabResets */ + *uint_ptr = tcpestabresets; + break; + case 9: /* tcpCurrEstab */ + { + u16_t tcpcurrestab = 0; + struct tcp_pcb *pcb = tcp_active_pcbs; + while (pcb != NULL) + { + if ((pcb->state == ESTABLISHED) || + (pcb->state == CLOSE_WAIT)) + { + tcpcurrestab++; + } + pcb = pcb->next; + } + *uint_ptr = tcpcurrestab; + } + break; + case 10: /* tcpInSegs */ + *uint_ptr = tcpinsegs; + break; + case 11: /* tcpOutSegs */ + *uint_ptr = tcpoutsegs; + break; + case 12: /* tcpRetransSegs */ + *uint_ptr = tcpretranssegs; + break; + case 14: /* tcpInErrs */ + *uint_ptr = tcpinerrs; + break; + case 15: /* tcpOutRsts */ + *uint_ptr = tcpoutrsts; + break; + } +} +#ifdef THIS_SEEMS_UNUSED +static void +tcpconnentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + /* return to object name, adding index depth (10) */ + ident_len += 10; + ident -= 10; + + if (ident_len == 11) + { + u8_t id; + + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + id = ident[0]; + LWIP_DEBUGF(SNMP_MIB_DEBUG,("get_object_def tcp.%"U16_F".0\n",(u16_t)id)); + + switch (id) + { + case 1: /* tcpConnState */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + case 2: /* tcpConnLocalAddress */ + case 4: /* tcpConnRemAddress */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR); + od->v_len = 4; + break; + case 3: /* tcpConnLocalPort */ + case 5: /* tcpConnRemPort */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("tcpconnentry_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + }; + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("tcpconnentry_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +tcpconnentry_get_value(struct obj_def *od, u16_t len, void *value) +{ + struct ip_addr lip, rip; + u16_t lport, rport; + s32_t *ident; + + ident = od->id_inst_ptr; + snmp_oidtoip(&ident[1], &lip); + lip.addr = htonl(lip.addr); + lport = ident[5]; + snmp_oidtoip(&ident[6], &rip); + rip.addr = htonl(rip.addr); + rport = ident[10]; + + /** @todo find matching PCB */ +} +#endif /* if 0 */ +#endif + +static void +udp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + /* return to object name, adding index depth (1) */ + ident_len += 1; + ident -= 1; + if ((ident_len == 2) && + (ident[0] > 0) && (ident[0] < 6)) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER); + od->v_len = sizeof(u32_t); + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("udp_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +udp_get_value(struct obj_def *od, u16_t len, void *value) +{ + u32_t *uint_ptr = value; + u8_t id; + + LWIP_UNUSED_ARG(len); + id = od->id_inst_ptr[0]; + switch (id) + { + case 1: /* udpInDatagrams */ + *uint_ptr = udpindatagrams; + break; + case 2: /* udpNoPorts */ + *uint_ptr = udpnoports; + break; + case 3: /* udpInErrors */ + *uint_ptr = udpinerrors; + break; + case 4: /* udpOutDatagrams */ + *uint_ptr = udpoutdatagrams; + break; + } +} + +static void +udpentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + /* return to object name, adding index depth (5) */ + ident_len += 5; + ident -= 5; + + if (ident_len == 6) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + switch (ident[0]) + { + case 1: /* udpLocalAddress */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR); + od->v_len = 4; + break; + case 2: /* udpLocalPort */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("udpentry_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + } + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("udpentry_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +udpentry_get_value(struct obj_def *od, u16_t len, void *value) +{ + u8_t id; + struct udp_pcb *pcb; + struct ip_addr ip; + u16_t port; + + LWIP_UNUSED_ARG(len); + snmp_oidtoip(&od->id_inst_ptr[1], &ip); + ip.addr = htonl(ip.addr); + port = od->id_inst_ptr[5]; + + pcb = udp_pcbs; + while ((pcb != NULL) && + !((pcb->local_ip.addr == ip.addr) && + (pcb->local_port == port))) + { + pcb = pcb->next; + } + + if (pcb != NULL) + { + id = od->id_inst_ptr[0]; + switch (id) + { + case 1: /* udpLocalAddress */ + { + struct ip_addr *dst = value; + *dst = pcb->local_ip; + } + break; + case 2: /* udpLocalPort */ + { + s32_t *sint_ptr = value; + *sint_ptr = pcb->local_port; + } + break; + } + } +} + +static void +snmp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + /* return to object name, adding index depth (1) */ + ident_len += 1; + ident -= 1; + if (ident_len == 2) + { + u8_t id; + + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + id = ident[0]; + switch (id) + { + case 1: /* snmpInPkts */ + case 2: /* snmpOutPkts */ + case 3: /* snmpInBadVersions */ + case 4: /* snmpInBadCommunityNames */ + case 5: /* snmpInBadCommunityUses */ + case 6: /* snmpInASNParseErrs */ + case 8: /* snmpInTooBigs */ + case 9: /* snmpInNoSuchNames */ + case 10: /* snmpInBadValues */ + case 11: /* snmpInReadOnlys */ + case 12: /* snmpInGenErrs */ + case 13: /* snmpInTotalReqVars */ + case 14: /* snmpInTotalSetVars */ + case 15: /* snmpInGetRequests */ + case 16: /* snmpInGetNexts */ + case 17: /* snmpInSetRequests */ + case 18: /* snmpInGetResponses */ + case 19: /* snmpInTraps */ + case 20: /* snmpOutTooBigs */ + case 21: /* snmpOutNoSuchNames */ + case 22: /* snmpOutBadValues */ + case 24: /* snmpOutGenErrs */ + case 25: /* snmpOutGetRequests */ + case 26: /* snmpOutGetNexts */ + case 27: /* snmpOutSetRequests */ + case 28: /* snmpOutGetResponses */ + case 29: /* snmpOutTraps */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER); + od->v_len = sizeof(u32_t); + break; + case 30: /* snmpEnableAuthenTraps */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + }; + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +snmp_get_value(struct obj_def *od, u16_t len, void *value) +{ + u32_t *uint_ptr = value; + u8_t id; + + LWIP_UNUSED_ARG(len); + id = od->id_inst_ptr[0]; + switch (id) + { + case 1: /* snmpInPkts */ + *uint_ptr = snmpinpkts; + break; + case 2: /* snmpOutPkts */ + *uint_ptr = snmpoutpkts; + break; + case 3: /* snmpInBadVersions */ + *uint_ptr = snmpinbadversions; + break; + case 4: /* snmpInBadCommunityNames */ + *uint_ptr = snmpinbadcommunitynames; + break; + case 5: /* snmpInBadCommunityUses */ + *uint_ptr = snmpinbadcommunityuses; + break; + case 6: /* snmpInASNParseErrs */ + *uint_ptr = snmpinasnparseerrs; + break; + case 8: /* snmpInTooBigs */ + *uint_ptr = snmpintoobigs; + break; + case 9: /* snmpInNoSuchNames */ + *uint_ptr = snmpinnosuchnames; + break; + case 10: /* snmpInBadValues */ + *uint_ptr = snmpinbadvalues; + break; + case 11: /* snmpInReadOnlys */ + *uint_ptr = snmpinreadonlys; + break; + case 12: /* snmpInGenErrs */ + *uint_ptr = snmpingenerrs; + break; + case 13: /* snmpInTotalReqVars */ + *uint_ptr = snmpintotalreqvars; + break; + case 14: /* snmpInTotalSetVars */ + *uint_ptr = snmpintotalsetvars; + break; + case 15: /* snmpInGetRequests */ + *uint_ptr = snmpingetrequests; + break; + case 16: /* snmpInGetNexts */ + *uint_ptr = snmpingetnexts; + break; + case 17: /* snmpInSetRequests */ + *uint_ptr = snmpinsetrequests; + break; + case 18: /* snmpInGetResponses */ + *uint_ptr = snmpingetresponses; + break; + case 19: /* snmpInTraps */ + *uint_ptr = snmpintraps; + break; + case 20: /* snmpOutTooBigs */ + *uint_ptr = snmpouttoobigs; + break; + case 21: /* snmpOutNoSuchNames */ + *uint_ptr = snmpoutnosuchnames; + break; + case 22: /* snmpOutBadValues */ + *uint_ptr = snmpoutbadvalues; + break; + case 24: /* snmpOutGenErrs */ + *uint_ptr = snmpoutgenerrs; + break; + case 25: /* snmpOutGetRequests */ + *uint_ptr = snmpoutgetrequests; + break; + case 26: /* snmpOutGetNexts */ + *uint_ptr = snmpoutgetnexts; + break; + case 27: /* snmpOutSetRequests */ + *uint_ptr = snmpoutsetrequests; + break; + case 28: /* snmpOutGetResponses */ + *uint_ptr = snmpoutgetresponses; + break; + case 29: /* snmpOutTraps */ + *uint_ptr = snmpouttraps; + break; + case 30: /* snmpEnableAuthenTraps */ + *uint_ptr = *snmpenableauthentraps_ptr; + break; + }; +} + +/** + * Test snmp object value before setting. + * + * @param od is the object definition + * @param len return value space (in bytes) + * @param value points to (varbind) space to copy value from. + */ +static u8_t +snmp_set_test(struct obj_def *od, u16_t len, void *value) +{ + u8_t id, set_ok; + + LWIP_UNUSED_ARG(len); + set_ok = 0; + id = od->id_inst_ptr[0]; + if (id == 30) + { + /* snmpEnableAuthenTraps */ + s32_t *sint_ptr = value; + + if (snmpenableauthentraps_ptr != &snmpenableauthentraps_default) + { + /* we should have writable non-volatile mem here */ + if ((*sint_ptr == 1) || (*sint_ptr == 2)) + { + set_ok = 1; + } + } + else + { + /* const or hardwired value */ + if (*sint_ptr == snmpenableauthentraps_default) + { + set_ok = 1; + } + } + } + return set_ok; +} + +static void +snmp_set_value(struct obj_def *od, u16_t len, void *value) +{ + u8_t id; + + LWIP_UNUSED_ARG(len); + id = od->id_inst_ptr[0]; + if (id == 30) + { + /* snmpEnableAuthenTraps */ + s32_t *sint_ptr = value; + *snmpenableauthentraps_ptr = *sint_ptr; + } +} + +#endif /* LWIP_SNMP */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/core/snmp/mib_structs.c b/component/common/network/lwip/lwip_v1.3.2/src/core/snmp/mib_structs.c new file mode 100644 index 0000000..39a2949 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/core/snmp/mib_structs.c @@ -0,0 +1,1183 @@ +/** + * @file + * MIB tree access/construction functions. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * Author: Christiaan Simons + */ + +#include "lwip/opt.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/snmp_structs.h" +#include "lwip/mem.h" + +/** .iso.org.dod.internet address prefix, @see snmp_iso_*() */ +const s32_t prefix[4] = {1, 3, 6, 1}; + +#define NODE_STACK_SIZE (LWIP_SNMP_OBJ_ID_LEN) +/** node stack entry (old news?) */ +struct nse +{ + /** right child */ + struct mib_node* r_ptr; + /** right child identifier */ + s32_t r_id; + /** right child next level */ + u8_t r_nl; +}; +static u8_t node_stack_cnt; +static struct nse node_stack[NODE_STACK_SIZE]; + +/** + * Pushes nse struct onto stack. + */ +static void +push_node(struct nse* node) +{ + LWIP_ASSERT("node_stack_cnt < NODE_STACK_SIZE",node_stack_cnt < NODE_STACK_SIZE); + LWIP_DEBUGF(SNMP_MIB_DEBUG,("push_node() node=%p id=%"S32_F"\n",(void*)(node->r_ptr),node->r_id)); + if (node_stack_cnt < NODE_STACK_SIZE) + { + node_stack[node_stack_cnt] = *node; + node_stack_cnt++; + } +} + +/** + * Pops nse struct from stack. + */ +static void +pop_node(struct nse* node) +{ + if (node_stack_cnt > 0) + { + node_stack_cnt--; + *node = node_stack[node_stack_cnt]; + } + LWIP_DEBUGF(SNMP_MIB_DEBUG,("pop_node() node=%p id=%"S32_F"\n",(void *)(node->r_ptr),node->r_id)); +} + +/** + * Conversion from ifIndex to lwIP netif + * @param ifindex is a s32_t object sub-identifier + * @param netif points to returned netif struct pointer + */ +void +snmp_ifindextonetif(s32_t ifindex, struct netif **netif) +{ + struct netif *nif = netif_list; + u16_t i, ifidx; + + ifidx = ifindex - 1; + i = 0; + while ((nif != NULL) && (i < ifidx)) + { + nif = nif->next; + i++; + } + *netif = nif; +} + +/** + * Conversion from lwIP netif to ifIndex + * @param netif points to a netif struct + * @param ifidx points to s32_t object sub-identifier + */ +void +snmp_netiftoifindex(struct netif *netif, s32_t *ifidx) +{ + struct netif *nif = netif_list; + u16_t i; + + i = 0; + while ((nif != NULL) && (nif != netif)) + { + nif = nif->next; + i++; + } + *ifidx = i+1; +} + +/** + * Conversion from oid to lwIP ip_addr + * @param ident points to s32_t ident[4] input + * @param ip points to output struct + */ +void +snmp_oidtoip(s32_t *ident, struct ip_addr *ip) +{ + u32_t ipa; + + ipa = ident[0]; + ipa <<= 8; + ipa |= ident[1]; + ipa <<= 8; + ipa |= ident[2]; + ipa <<= 8; + ipa |= ident[3]; + ip->addr = ipa; +} + +/** + * Conversion from lwIP ip_addr to oid + * @param ip points to input struct + * @param ident points to s32_t ident[4] output + */ +void +snmp_iptooid(struct ip_addr *ip, s32_t *ident) +{ + u32_t ipa; + + ipa = ip->addr; + ident[0] = (ipa >> 24) & 0xff; + ident[1] = (ipa >> 16) & 0xff; + ident[2] = (ipa >> 8) & 0xff; + ident[3] = ipa & 0xff; +} + +struct mib_list_node * +snmp_mib_ln_alloc(s32_t id) +{ + struct mib_list_node *ln; + + ln = (struct mib_list_node *)mem_malloc(sizeof(struct mib_list_node)); + if (ln != NULL) + { + ln->prev = NULL; + ln->next = NULL; + ln->objid = id; + ln->nptr = NULL; + } + return ln; +} + +void +snmp_mib_ln_free(struct mib_list_node *ln) +{ + mem_free(ln); +} + +struct mib_list_rootnode * +snmp_mib_lrn_alloc(void) +{ + struct mib_list_rootnode *lrn; + + lrn = (struct mib_list_rootnode*)mem_malloc(sizeof(struct mib_list_rootnode)); + if (lrn != NULL) + { + lrn->get_object_def = noleafs_get_object_def; + lrn->get_value = noleafs_get_value; + lrn->set_test = noleafs_set_test; + lrn->set_value = noleafs_set_value; + lrn->node_type = MIB_NODE_LR; + lrn->maxlength = 0; + lrn->head = NULL; + lrn->tail = NULL; + lrn->count = 0; + } + return lrn; +} + +void +snmp_mib_lrn_free(struct mib_list_rootnode *lrn) +{ + mem_free(lrn); +} + +/** + * Inserts node in idx list in a sorted + * (ascending order) fashion and + * allocates the node if needed. + * + * @param rn points to the root node + * @param objid is the object sub identifier + * @param insn points to a pointer to the inserted node + * used for constructing the tree. + * @return -1 if failed, 1 if inserted, 2 if present. + */ +s8_t +snmp_mib_node_insert(struct mib_list_rootnode *rn, s32_t objid, struct mib_list_node **insn) +{ + struct mib_list_node *nn; + s8_t insert; + + LWIP_ASSERT("rn != NULL",rn != NULL); + + /* -1 = malloc failure, 0 = not inserted, 1 = inserted, 2 = was present */ + insert = 0; + if (rn->head == NULL) + { + /* empty list, add first node */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("alloc empty list objid==%"S32_F"\n",objid)); + nn = snmp_mib_ln_alloc(objid); + if (nn != NULL) + { + rn->head = nn; + rn->tail = nn; + *insn = nn; + insert = 1; + } + else + { + insert = -1; + } + } + else + { + struct mib_list_node *n; + /* at least one node is present */ + n = rn->head; + while ((n != NULL) && (insert == 0)) + { + if (n->objid == objid) + { + /* node is already there */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("node already there objid==%"S32_F"\n",objid)); + *insn = n; + insert = 2; + } + else if (n->objid < objid) + { + if (n->next == NULL) + { + /* alloc and insert at the tail */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("alloc ins tail objid==%"S32_F"\n",objid)); + nn = snmp_mib_ln_alloc(objid); + if (nn != NULL) + { + nn->next = NULL; + nn->prev = n; + n->next = nn; + rn->tail = nn; + *insn = nn; + insert = 1; + } + else + { + /* insertion failure */ + insert = -1; + } + } + else + { + /* there's more to explore: traverse list */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("traverse list\n")); + n = n->next; + } + } + else + { + /* n->objid > objid */ + /* alloc and insert between n->prev and n */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("alloc ins n->prev, objid==%"S32_F", n\n",objid)); + nn = snmp_mib_ln_alloc(objid); + if (nn != NULL) + { + if (n->prev == NULL) + { + /* insert at the head */ + nn->next = n; + nn->prev = NULL; + rn->head = nn; + n->prev = nn; + } + else + { + /* insert in the middle */ + nn->next = n; + nn->prev = n->prev; + n->prev->next = nn; + n->prev = nn; + } + *insn = nn; + insert = 1; + } + else + { + /* insertion failure */ + insert = -1; + } + } + } + } + if (insert == 1) + { + rn->count += 1; + } + LWIP_ASSERT("insert != 0",insert != 0); + return insert; +} + +/** + * Finds node in idx list and returns deletion mark. + * + * @param rn points to the root node + * @param objid is the object sub identifier + * @param fn returns pointer to found node + * @return 0 if not found, 1 if deletable, + * 2 can't delete (2 or more children), 3 not a list_node + */ +s8_t +snmp_mib_node_find(struct mib_list_rootnode *rn, s32_t objid, struct mib_list_node **fn) +{ + s8_t fc; + struct mib_list_node *n; + + LWIP_ASSERT("rn != NULL",rn != NULL); + n = rn->head; + while ((n != NULL) && (n->objid != objid)) + { + n = n->next; + } + if (n == NULL) + { + fc = 0; + } + else if (n->nptr == NULL) + { + /* leaf, can delete node */ + fc = 1; + } + else + { + struct mib_list_rootnode *r; + + if (n->nptr->node_type == MIB_NODE_LR) + { + r = (struct mib_list_rootnode *)n->nptr; + if (r->count > 1) + { + /* can't delete node */ + fc = 2; + } + else + { + /* count <= 1, can delete node */ + fc = 1; + } + } + else + { + /* other node type */ + fc = 3; + } + } + *fn = n; + return fc; +} + +/** + * Removes node from idx list + * if it has a single child left. + * + * @param rn points to the root node + * @param n points to the node to delete + * @return the nptr to be freed by caller + */ +struct mib_list_rootnode * +snmp_mib_node_delete(struct mib_list_rootnode *rn, struct mib_list_node *n) +{ + struct mib_list_rootnode *next; + + LWIP_ASSERT("rn != NULL",rn != NULL); + LWIP_ASSERT("n != NULL",n != NULL); + + /* caller must remove this sub-tree */ + next = (struct mib_list_rootnode*)(n->nptr); + rn->count -= 1; + + if (n == rn->head) + { + rn->head = n->next; + if (n->next != NULL) + { + /* not last node, new list begin */ + n->next->prev = NULL; + } + } + else if (n == rn->tail) + { + rn->tail = n->prev; + if (n->prev != NULL) + { + /* not last node, new list end */ + n->prev->next = NULL; + } + } + else + { + /* node must be in the middle */ + n->prev->next = n->next; + n->next->prev = n->prev; + } + LWIP_DEBUGF(SNMP_MIB_DEBUG,("free list objid==%"S32_F"\n",n->objid)); + snmp_mib_ln_free(n); + if (rn->count == 0) + { + rn->head = NULL; + rn->tail = NULL; + } + return next; +} + + + +/** + * Searches tree for the supplied (scalar?) object identifier. + * + * @param node points to the root of the tree ('.internet') + * @param ident_len the length of the supplied object identifier + * @param ident points to the array of sub identifiers + * @param np points to the found object instance (rerurn) + * @return pointer to the requested parent (!) node if success, NULL otherwise + */ +struct mib_node * +snmp_search_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct snmp_name_ptr *np) +{ + u8_t node_type, ext_level; + + ext_level = 0; + LWIP_DEBUGF(SNMP_MIB_DEBUG,("node==%p *ident==%"S32_F"\n",(void*)node,*ident)); + while (node != NULL) + { + node_type = node->node_type; + if ((node_type == MIB_NODE_AR) || (node_type == MIB_NODE_RA)) + { + struct mib_array_node *an; + u16_t i; + + if (ident_len > 0) + { + /* array node (internal ROM or RAM, fixed length) */ + an = (struct mib_array_node *)node; + i = 0; + while ((i < an->maxlength) && (an->objid[i] != *ident)) + { + i++; + } + if (i < an->maxlength) + { + /* found it, if available proceed to child, otherwise inspect leaf */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("an->objid[%"U16_F"]==%"S32_F" *ident==%"S32_F"\n",i,an->objid[i],*ident)); + if (an->nptr[i] == NULL) + { + /* a scalar leaf OR table, + inspect remaining instance number / table index */ + np->ident_len = ident_len; + np->ident = ident; + return (struct mib_node*)an; + } + else + { + /* follow next child pointer */ + ident++; + ident_len--; + node = an->nptr[i]; + } + } + else + { + /* search failed, identifier mismatch (nosuchname) */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("an search failed *ident==%"S32_F"\n",*ident)); + return NULL; + } + } + else + { + /* search failed, short object identifier (nosuchname) */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("an search failed, short object identifier\n")); + return NULL; + } + } + else if(node_type == MIB_NODE_LR) + { + struct mib_list_rootnode *lrn; + struct mib_list_node *ln; + + if (ident_len > 0) + { + /* list root node (internal 'RAM', variable length) */ + lrn = (struct mib_list_rootnode *)node; + ln = lrn->head; + /* iterate over list, head to tail */ + while ((ln != NULL) && (ln->objid != *ident)) + { + ln = ln->next; + } + if (ln != NULL) + { + /* found it, proceed to child */; + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ln->objid==%"S32_F" *ident==%"S32_F"\n",ln->objid,*ident)); + if (ln->nptr == NULL) + { + np->ident_len = ident_len; + np->ident = ident; + return (struct mib_node*)lrn; + } + else + { + /* follow next child pointer */ + ident_len--; + ident++; + node = ln->nptr; + } + } + else + { + /* search failed */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ln search failed *ident==%"S32_F"\n",*ident)); + return NULL; + } + } + else + { + /* search failed, short object identifier (nosuchname) */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ln search failed, short object identifier\n")); + return NULL; + } + } + else if(node_type == MIB_NODE_EX) + { + struct mib_external_node *en; + u16_t i, len; + + if (ident_len > 0) + { + /* external node (addressing and access via functions) */ + en = (struct mib_external_node *)node; + + i = 0; + len = en->level_length(en->addr_inf,ext_level); + while ((i < len) && (en->ident_cmp(en->addr_inf,ext_level,i,*ident) != 0)) + { + i++; + } + if (i < len) + { + s32_t debug_id; + + en->get_objid(en->addr_inf,ext_level,i,&debug_id); + LWIP_DEBUGF(SNMP_MIB_DEBUG,("en->objid==%"S32_F" *ident==%"S32_F"\n",debug_id,*ident)); + if ((ext_level + 1) == en->tree_levels) + { + np->ident_len = ident_len; + np->ident = ident; + return (struct mib_node*)en; + } + else + { + /* found it, proceed to child */ + ident_len--; + ident++; + ext_level++; + } + } + else + { + /* search failed */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("en search failed *ident==%"S32_F"\n",*ident)); + return NULL; + } + } + else + { + /* search failed, short object identifier (nosuchname) */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("en search failed, short object identifier\n")); + return NULL; + } + } + else if (node_type == MIB_NODE_SC) + { + mib_scalar_node *sn; + + sn = (mib_scalar_node *)node; + if ((ident_len == 1) && (*ident == 0)) + { + np->ident_len = ident_len; + np->ident = ident; + return (struct mib_node*)sn; + } + else + { + /* search failed, short object identifier (nosuchname) */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("search failed, invalid object identifier length\n")); + return NULL; + } + } + else + { + /* unknown node_type */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("search failed node_type %"U16_F" unkown\n",(u16_t)node_type)); + return NULL; + } + } + /* done, found nothing */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("search failed node==%p\n",(void*)node)); + return NULL; +} + +/** + * Test table for presence of at least one table entry. + */ +static u8_t +empty_table(struct mib_node *node) +{ + u8_t node_type; + u8_t empty = 0; + + if (node != NULL) + { + node_type = node->node_type; + if (node_type == MIB_NODE_LR) + { + struct mib_list_rootnode *lrn; + lrn = (struct mib_list_rootnode *)node; + if ((lrn->count == 0) || (lrn->head == NULL)) + { + empty = 1; + } + } + else if ((node_type == MIB_NODE_AR) || (node_type == MIB_NODE_RA)) + { + struct mib_array_node *an; + an = (struct mib_array_node *)node; + if ((an->maxlength == 0) || (an->nptr == NULL)) + { + empty = 1; + } + } + else if (node_type == MIB_NODE_EX) + { + struct mib_external_node *en; + en = (struct mib_external_node *)node; + if (en->tree_levels == 0) + { + empty = 1; + } + } + } + return empty; +} + +/** + * Tree expansion. + */ +struct mib_node * +snmp_expand_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct snmp_obj_id *oidret) +{ + u8_t node_type, ext_level, climb_tree; + + ext_level = 0; + /* reset node stack */ + node_stack_cnt = 0; + while (node != NULL) + { + climb_tree = 0; + node_type = node->node_type; + if ((node_type == MIB_NODE_AR) || (node_type == MIB_NODE_RA)) + { + struct mib_array_node *an; + u16_t i; + + /* array node (internal ROM or RAM, fixed length) */ + an = (struct mib_array_node *)node; + if (ident_len > 0) + { + i = 0; + while ((i < an->maxlength) && (an->objid[i] < *ident)) + { + i++; + } + if (i < an->maxlength) + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("an->objid[%"U16_F"]==%"S32_F" *ident==%"S32_F"\n",i,an->objid[i],*ident)); + /* add identifier to oidret */ + oidret->id[oidret->len] = an->objid[i]; + (oidret->len)++; + + if (an->nptr[i] == NULL) + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("leaf node\n")); + /* leaf node (e.g. in a fixed size table) */ + if (an->objid[i] > *ident) + { + return (struct mib_node*)an; + } + else if ((i + 1) < an->maxlength) + { + /* an->objid[i] == *ident */ + (oidret->len)--; + oidret->id[oidret->len] = an->objid[i + 1]; + (oidret->len)++; + return (struct mib_node*)an; + } + else + { + /* (i + 1) == an->maxlength */ + (oidret->len)--; + climb_tree = 1; + } + } + else + { + u8_t j; + struct nse cur_node; + + LWIP_DEBUGF(SNMP_MIB_DEBUG,("non-leaf node\n")); + /* non-leaf, store right child ptr and id */ + j = i + 1; + while ((j < an->maxlength) && (empty_table(an->nptr[j]))) + { + j++; + } + if (j < an->maxlength) + { + cur_node.r_ptr = an->nptr[j]; + cur_node.r_id = an->objid[j]; + cur_node.r_nl = 0; + } + else + { + cur_node.r_ptr = NULL; + } + push_node(&cur_node); + if (an->objid[i] == *ident) + { + ident_len--; + ident++; + } + else + { + /* an->objid[i] < *ident */ + ident_len = 0; + } + /* follow next child pointer */ + node = an->nptr[i]; + } + } + else + { + /* i == an->maxlength */ + climb_tree = 1; + } + } + else + { + u8_t j; + /* ident_len == 0, complete with leftmost '.thing' */ + j = 0; + while ((j < an->maxlength) && empty_table(an->nptr[j])) + { + j++; + } + if (j < an->maxlength) + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("left an->objid[j]==%"S32_F"\n",an->objid[j])); + oidret->id[oidret->len] = an->objid[j]; + (oidret->len)++; + if (an->nptr[j] == NULL) + { + /* leaf node */ + return (struct mib_node*)an; + } + else + { + /* no leaf, continue */ + node = an->nptr[j]; + } + } + else + { + /* j == an->maxlength */ + climb_tree = 1; + } + } + } + else if(node_type == MIB_NODE_LR) + { + struct mib_list_rootnode *lrn; + struct mib_list_node *ln; + + /* list root node (internal 'RAM', variable length) */ + lrn = (struct mib_list_rootnode *)node; + if (ident_len > 0) + { + ln = lrn->head; + /* iterate over list, head to tail */ + while ((ln != NULL) && (ln->objid < *ident)) + { + ln = ln->next; + } + if (ln != NULL) + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ln->objid==%"S32_F" *ident==%"S32_F"\n",ln->objid,*ident)); + oidret->id[oidret->len] = ln->objid; + (oidret->len)++; + if (ln->nptr == NULL) + { + /* leaf node */ + if (ln->objid > *ident) + { + return (struct mib_node*)lrn; + } + else if (ln->next != NULL) + { + /* ln->objid == *ident */ + (oidret->len)--; + oidret->id[oidret->len] = ln->next->objid; + (oidret->len)++; + return (struct mib_node*)lrn; + } + else + { + /* ln->next == NULL */ + (oidret->len)--; + climb_tree = 1; + } + } + else + { + struct mib_list_node *jn; + struct nse cur_node; + + /* non-leaf, store right child ptr and id */ + jn = ln->next; + while ((jn != NULL) && empty_table(jn->nptr)) + { + jn = jn->next; + } + if (jn != NULL) + { + cur_node.r_ptr = jn->nptr; + cur_node.r_id = jn->objid; + cur_node.r_nl = 0; + } + else + { + cur_node.r_ptr = NULL; + } + push_node(&cur_node); + if (ln->objid == *ident) + { + ident_len--; + ident++; + } + else + { + /* ln->objid < *ident */ + ident_len = 0; + } + /* follow next child pointer */ + node = ln->nptr; + } + + } + else + { + /* ln == NULL */ + climb_tree = 1; + } + } + else + { + struct mib_list_node *jn; + /* ident_len == 0, complete with leftmost '.thing' */ + jn = lrn->head; + while ((jn != NULL) && empty_table(jn->nptr)) + { + jn = jn->next; + } + if (jn != NULL) + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("left jn->objid==%"S32_F"\n",jn->objid)); + oidret->id[oidret->len] = jn->objid; + (oidret->len)++; + if (jn->nptr == NULL) + { + /* leaf node */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("jn->nptr == NULL\n")); + return (struct mib_node*)lrn; + } + else + { + /* no leaf, continue */ + node = jn->nptr; + } + } + else + { + /* jn == NULL */ + climb_tree = 1; + } + } + } + else if(node_type == MIB_NODE_EX) + { + struct mib_external_node *en; + s32_t ex_id; + + /* external node (addressing and access via functions) */ + en = (struct mib_external_node *)node; + if (ident_len > 0) + { + u16_t i, len; + + i = 0; + len = en->level_length(en->addr_inf,ext_level); + while ((i < len) && (en->ident_cmp(en->addr_inf,ext_level,i,*ident) < 0)) + { + i++; + } + if (i < len) + { + /* add identifier to oidret */ + en->get_objid(en->addr_inf,ext_level,i,&ex_id); + LWIP_DEBUGF(SNMP_MIB_DEBUG,("en->objid[%"U16_F"]==%"S32_F" *ident==%"S32_F"\n",i,ex_id,*ident)); + oidret->id[oidret->len] = ex_id; + (oidret->len)++; + + if ((ext_level + 1) == en->tree_levels) + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("leaf node\n")); + /* leaf node */ + if (ex_id > *ident) + { + return (struct mib_node*)en; + } + else if ((i + 1) < len) + { + /* ex_id == *ident */ + en->get_objid(en->addr_inf,ext_level,i + 1,&ex_id); + (oidret->len)--; + oidret->id[oidret->len] = ex_id; + (oidret->len)++; + return (struct mib_node*)en; + } + else + { + /* (i + 1) == len */ + (oidret->len)--; + climb_tree = 1; + } + } + else + { + u8_t j; + struct nse cur_node; + + LWIP_DEBUGF(SNMP_MIB_DEBUG,("non-leaf node\n")); + /* non-leaf, store right child ptr and id */ + j = i + 1; + if (j < len) + { + /* right node is the current external node */ + cur_node.r_ptr = node; + en->get_objid(en->addr_inf,ext_level,j,&cur_node.r_id); + cur_node.r_nl = ext_level + 1; + } + else + { + cur_node.r_ptr = NULL; + } + push_node(&cur_node); + if (en->ident_cmp(en->addr_inf,ext_level,i,*ident) == 0) + { + ident_len--; + ident++; + } + else + { + /* external id < *ident */ + ident_len = 0; + } + /* proceed to child */ + ext_level++; + } + } + else + { + /* i == len (en->level_len()) */ + climb_tree = 1; + } + } + else + { + /* ident_len == 0, complete with leftmost '.thing' */ + en->get_objid(en->addr_inf,ext_level,0,&ex_id); + LWIP_DEBUGF(SNMP_MIB_DEBUG,("left en->objid==%"S32_F"\n",ex_id)); + oidret->id[oidret->len] = ex_id; + (oidret->len)++; + if ((ext_level + 1) == en->tree_levels) + { + /* leaf node */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("(ext_level + 1) == en->tree_levels\n")); + return (struct mib_node*)en; + } + else + { + /* no leaf, proceed to child */ + ext_level++; + } + } + } + else if(node_type == MIB_NODE_SC) + { + mib_scalar_node *sn; + + /* scalar node */ + sn = (mib_scalar_node *)node; + if (ident_len > 0) + { + /* at .0 */ + climb_tree = 1; + } + else + { + /* ident_len == 0, complete object identifier */ + oidret->id[oidret->len] = 0; + (oidret->len)++; + /* leaf node */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("completed scalar leaf\n")); + return (struct mib_node*)sn; + } + } + else + { + /* unknown/unhandled node_type */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("expand failed node_type %"U16_F" unkown\n",(u16_t)node_type)); + return NULL; + } + + if (climb_tree) + { + struct nse child; + + /* find right child ptr */ + child.r_ptr = NULL; + child.r_id = 0; + child.r_nl = 0; + while ((node_stack_cnt > 0) && (child.r_ptr == NULL)) + { + pop_node(&child); + /* trim returned oid */ + (oidret->len)--; + } + if (child.r_ptr != NULL) + { + /* incoming ident is useless beyond this point */ + ident_len = 0; + oidret->id[oidret->len] = child.r_id; + oidret->len++; + node = child.r_ptr; + ext_level = child.r_nl; + } + else + { + /* tree ends here ... */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("expand failed, tree ends here\n")); + return NULL; + } + } + } + /* done, found nothing */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("expand failed node==%p\n",(void*)node)); + return NULL; +} + +/** + * Test object identifier for the iso.org.dod.internet prefix. + * + * @param ident_len the length of the supplied object identifier + * @param ident points to the array of sub identifiers + * @return 1 if it matches, 0 otherwise + */ +u8_t +snmp_iso_prefix_tst(u8_t ident_len, s32_t *ident) +{ + if ((ident_len > 3) && + (ident[0] == 1) && (ident[1] == 3) && + (ident[2] == 6) && (ident[3] == 1)) + { + return 1; + } + else + { + return 0; + } +} + +/** + * Expands object identifier to the iso.org.dod.internet + * prefix for use in getnext operation. + * + * @param ident_len the length of the supplied object identifier + * @param ident points to the array of sub identifiers + * @param oidret points to returned expanded object identifier + * @return 1 if it matches, 0 otherwise + * + * @note ident_len 0 is allowed, expanding to the first known object id!! + */ +u8_t +snmp_iso_prefix_expand(u8_t ident_len, s32_t *ident, struct snmp_obj_id *oidret) +{ + const s32_t *prefix_ptr; + s32_t *ret_ptr; + u8_t i; + + i = 0; + prefix_ptr = &prefix[0]; + ret_ptr = &oidret->id[0]; + ident_len = ((ident_len < 4)?ident_len:4); + while ((i < ident_len) && ((*ident) <= (*prefix_ptr))) + { + *ret_ptr++ = *prefix_ptr++; + ident++; + i++; + } + if (i == ident_len) + { + /* match, complete missing bits */ + while (i < 4) + { + *ret_ptr++ = *prefix_ptr++; + i++; + } + oidret->len = i; + return 1; + } + else + { + /* i != ident_len */ + return 0; + } +} + +#endif /* LWIP_SNMP */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/core/snmp/msg_in.c b/component/common/network/lwip/lwip_v1.3.2/src/core/snmp/msg_in.c new file mode 100644 index 0000000..d0c3c75 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/core/snmp/msg_in.c @@ -0,0 +1,1454 @@ +/** + * @file + * SNMP input message processing (RFC1157). + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * Author: Christiaan Simons + */ + +#include "lwip/opt.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/ip_addr.h" +#include "lwip/mem.h" +#include "lwip/udp.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "lwip/snmp_asn1.h" +#include "lwip/snmp_msg.h" +#include "lwip/snmp_structs.h" + +#include + +/* public (non-static) constants */ +/** SNMP v1 == 0 */ +const s32_t snmp_version = 0; +/** default SNMP community string */ +const char snmp_publiccommunity[7] = "public"; + +/* statically allocated buffers for SNMP_CONCURRENT_REQUESTS */ +struct snmp_msg_pstat msg_input_list[SNMP_CONCURRENT_REQUESTS]; +/* UDP Protocol Control Block */ +struct udp_pcb *snmp1_pcb; + +static void snmp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port); +static err_t snmp_pdu_header_check(struct pbuf *p, u16_t ofs, u16_t pdu_len, u16_t *ofs_ret, struct snmp_msg_pstat *m_stat); +static err_t snmp_pdu_dec_varbindlist(struct pbuf *p, u16_t ofs, u16_t *ofs_ret, struct snmp_msg_pstat *m_stat); + + +/** + * Starts SNMP Agent. + * Allocates UDP pcb and binds it to IP_ADDR_ANY port 161. + */ +void +snmp_init(void) +{ + struct snmp_msg_pstat *msg_ps; + u8_t i; + + snmp1_pcb = udp_new(); + if (snmp1_pcb != NULL) + { + udp_recv(snmp1_pcb, snmp_recv, (void *)SNMP_IN_PORT); + udp_bind(snmp1_pcb, IP_ADDR_ANY, SNMP_IN_PORT); + } + msg_ps = &msg_input_list[0]; + for (i=0; istate = SNMP_MSG_EMPTY; + msg_ps->error_index = 0; + msg_ps->error_status = SNMP_ES_NOERROR; + msg_ps++; + } + trap_msg.pcb = snmp1_pcb; + /* The coldstart trap will only be output + if our outgoing interface is up & configured */ + snmp_coldstart_trap(); +} + +static void +snmp_error_response(struct snmp_msg_pstat *msg_ps, u8_t error) +{ + snmp_varbind_list_free(&msg_ps->outvb); + msg_ps->outvb = msg_ps->invb; + msg_ps->invb.head = NULL; + msg_ps->invb.tail = NULL; + msg_ps->invb.count = 0; + msg_ps->error_status = error; + msg_ps->error_index = 1 + msg_ps->vb_idx; + snmp_send_response(msg_ps); + snmp_varbind_list_free(&msg_ps->outvb); + msg_ps->state = SNMP_MSG_EMPTY; +} + +static void +snmp_ok_response(struct snmp_msg_pstat *msg_ps) +{ + err_t err_ret; + + err_ret = snmp_send_response(msg_ps); + if (err_ret == ERR_MEM) + { + /* serious memory problem, can't return tooBig */ + } + else + { + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event = %"S32_F"\n",msg_ps->error_status)); + } + /* free varbinds (if available) */ + snmp_varbind_list_free(&msg_ps->invb); + snmp_varbind_list_free(&msg_ps->outvb); + msg_ps->state = SNMP_MSG_EMPTY; +} + +/** + * Service an internal or external event for SNMP GET. + * + * @param request_id identifies requests from 0 to (SNMP_CONCURRENT_REQUESTS-1) + * @param msg_ps points to the assosicated message process state + */ +static void +snmp_msg_get_event(u8_t request_id, struct snmp_msg_pstat *msg_ps) +{ + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_get_event: msg_ps->state==%"U16_F"\n",(u16_t)msg_ps->state)); + + if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_OBJDEF) + { + struct mib_external_node *en; + struct snmp_name_ptr np; + + /* get_object_def() answer*/ + en = msg_ps->ext_mib_node; + np = msg_ps->ext_name_ptr; + + /* translate answer into a known lifeform */ + en->get_object_def_a(request_id, np.ident_len, np.ident, &msg_ps->ext_object_def); + if (msg_ps->ext_object_def.instance != MIB_OBJECT_NONE) + { + msg_ps->state = SNMP_MSG_EXTERNAL_GET_VALUE; + en->get_value_q(request_id, &msg_ps->ext_object_def); + } + else + { + en->get_object_def_pc(request_id, np.ident_len, np.ident); + /* search failed, object id points to unknown object (nosuchname) */ + snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME); + } + } + else if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_VALUE) + { + struct mib_external_node *en; + struct snmp_varbind *vb; + + /* get_value() answer */ + en = msg_ps->ext_mib_node; + + /* allocate output varbind */ + vb = (struct snmp_varbind *)mem_malloc(sizeof(struct snmp_varbind)); + LWIP_ASSERT("vb != NULL",vb != NULL); + if (vb != NULL) + { + vb->next = NULL; + vb->prev = NULL; + + /* move name from invb to outvb */ + vb->ident = msg_ps->vb_ptr->ident; + vb->ident_len = msg_ps->vb_ptr->ident_len; + /* ensure this memory is refereced once only */ + msg_ps->vb_ptr->ident = NULL; + msg_ps->vb_ptr->ident_len = 0; + + vb->value_type = msg_ps->ext_object_def.asn_type; + vb->value_len = msg_ps->ext_object_def.v_len; + if (vb->value_len > 0) + { + vb->value = mem_malloc(vb->value_len); + LWIP_ASSERT("vb->value != NULL",vb->value != NULL); + if (vb->value != NULL) + { + en->get_value_a(request_id, &msg_ps->ext_object_def, vb->value_len, vb->value); + snmp_varbind_tail_add(&msg_ps->outvb, vb); + /* search again (if vb_idx < msg_ps->invb.count) */ + msg_ps->state = SNMP_MSG_SEARCH_OBJ; + msg_ps->vb_idx += 1; + } + else + { + en->get_value_pc(request_id, &msg_ps->ext_object_def); + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event: no variable space\n")); + msg_ps->vb_ptr->ident = vb->ident; + msg_ps->vb_ptr->ident_len = vb->ident_len; + mem_free(vb); + snmp_error_response(msg_ps,SNMP_ES_TOOBIG); + } + } + else + { + /* vb->value_len == 0, empty value (e.g. empty string) */ + en->get_value_a(request_id, &msg_ps->ext_object_def, 0, NULL); + vb->value = NULL; + snmp_varbind_tail_add(&msg_ps->outvb, vb); + /* search again (if vb_idx < msg_ps->invb.count) */ + msg_ps->state = SNMP_MSG_SEARCH_OBJ; + msg_ps->vb_idx += 1; + } + } + else + { + en->get_value_pc(request_id, &msg_ps->ext_object_def); + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event: no outvb space\n")); + snmp_error_response(msg_ps,SNMP_ES_TOOBIG); + } + } + + while ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) && + (msg_ps->vb_idx < msg_ps->invb.count)) + { + struct mib_node *mn; + struct snmp_name_ptr np; + + if (msg_ps->vb_idx == 0) + { + msg_ps->vb_ptr = msg_ps->invb.head; + } + else + { + msg_ps->vb_ptr = msg_ps->vb_ptr->next; + } + /** test object identifier for .iso.org.dod.internet prefix */ + if (snmp_iso_prefix_tst(msg_ps->vb_ptr->ident_len, msg_ps->vb_ptr->ident)) + { + mn = snmp_search_tree((struct mib_node*)&internet, msg_ps->vb_ptr->ident_len - 4, + msg_ps->vb_ptr->ident + 4, &np); + if (mn != NULL) + { + if (mn->node_type == MIB_NODE_EX) + { + /* external object */ + struct mib_external_node *en = (struct mib_external_node*)mn; + + msg_ps->state = SNMP_MSG_EXTERNAL_GET_OBJDEF; + /* save en && args in msg_ps!! */ + msg_ps->ext_mib_node = en; + msg_ps->ext_name_ptr = np; + + en->get_object_def_q(en->addr_inf, request_id, np.ident_len, np.ident); + } + else + { + /* internal object */ + struct obj_def object_def; + + msg_ps->state = SNMP_MSG_INTERNAL_GET_OBJDEF; + mn->get_object_def(np.ident_len, np.ident, &object_def); + if (object_def.instance != MIB_OBJECT_NONE) + { + mn = mn; + } + else + { + /* search failed, object id points to unknown object (nosuchname) */ + mn = NULL; + } + if (mn != NULL) + { + struct snmp_varbind *vb; + + msg_ps->state = SNMP_MSG_INTERNAL_GET_VALUE; + /* allocate output varbind */ + vb = (struct snmp_varbind *)mem_malloc(sizeof(struct snmp_varbind)); + LWIP_ASSERT("vb != NULL",vb != NULL); + if (vb != NULL) + { + vb->next = NULL; + vb->prev = NULL; + + /* move name from invb to outvb */ + vb->ident = msg_ps->vb_ptr->ident; + vb->ident_len = msg_ps->vb_ptr->ident_len; + /* ensure this memory is refereced once only */ + msg_ps->vb_ptr->ident = NULL; + msg_ps->vb_ptr->ident_len = 0; + + vb->value_type = object_def.asn_type; + vb->value_len = object_def.v_len; + if (vb->value_len > 0) + { + vb->value = mem_malloc(vb->value_len); + LWIP_ASSERT("vb->value != NULL",vb->value != NULL); + if (vb->value != NULL) + { + mn->get_value(&object_def, vb->value_len, vb->value); + snmp_varbind_tail_add(&msg_ps->outvb, vb); + msg_ps->state = SNMP_MSG_SEARCH_OBJ; + msg_ps->vb_idx += 1; + } + else + { + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event: couldn't allocate variable space\n")); + msg_ps->vb_ptr->ident = vb->ident; + msg_ps->vb_ptr->ident_len = vb->ident_len; + mem_free(vb); + snmp_error_response(msg_ps,SNMP_ES_TOOBIG); + } + } + else + { + /* vb->value_len == 0, empty value (e.g. empty string) */ + vb->value = NULL; + snmp_varbind_tail_add(&msg_ps->outvb, vb); + msg_ps->state = SNMP_MSG_SEARCH_OBJ; + msg_ps->vb_idx += 1; + } + } + else + { + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event: couldn't allocate outvb space\n")); + snmp_error_response(msg_ps,SNMP_ES_TOOBIG); + } + } + } + } + } + else + { + mn = NULL; + } + if (mn == NULL) + { + /* mn == NULL, noSuchName */ + snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME); + } + } + if ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) && + (msg_ps->vb_idx == msg_ps->invb.count)) + { + snmp_ok_response(msg_ps); + } +} + +/** + * Service an internal or external event for SNMP GETNEXT. + * + * @param request_id identifies requests from 0 to (SNMP_CONCURRENT_REQUESTS-1) + * @param msg_ps points to the assosicated message process state + */ +static void +snmp_msg_getnext_event(u8_t request_id, struct snmp_msg_pstat *msg_ps) +{ + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_getnext_event: msg_ps->state==%"U16_F"\n",(u16_t)msg_ps->state)); + + if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_OBJDEF) + { + struct mib_external_node *en; + + /* get_object_def() answer*/ + en = msg_ps->ext_mib_node; + + /* translate answer into a known lifeform */ + en->get_object_def_a(request_id, 1, &msg_ps->ext_oid.id[msg_ps->ext_oid.len - 1], &msg_ps->ext_object_def); + if (msg_ps->ext_object_def.instance != MIB_OBJECT_NONE) + { + msg_ps->state = SNMP_MSG_EXTERNAL_GET_VALUE; + en->get_value_q(request_id, &msg_ps->ext_object_def); + } + else + { + en->get_object_def_pc(request_id, 1, &msg_ps->ext_oid.id[msg_ps->ext_oid.len - 1]); + /* search failed, object id points to unknown object (nosuchname) */ + snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME); + } + } + else if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_VALUE) + { + struct mib_external_node *en; + struct snmp_varbind *vb; + + /* get_value() answer */ + en = msg_ps->ext_mib_node; + + vb = snmp_varbind_alloc(&msg_ps->ext_oid, + msg_ps->ext_object_def.asn_type, + msg_ps->ext_object_def.v_len); + if (vb != NULL) + { + en->get_value_a(request_id, &msg_ps->ext_object_def, vb->value_len, vb->value); + snmp_varbind_tail_add(&msg_ps->outvb, vb); + msg_ps->state = SNMP_MSG_SEARCH_OBJ; + msg_ps->vb_idx += 1; + } + else + { + en->get_value_pc(request_id, &msg_ps->ext_object_def); + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_getnext_event: couldn't allocate outvb space\n")); + snmp_error_response(msg_ps,SNMP_ES_TOOBIG); + } + } + + while ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) && + (msg_ps->vb_idx < msg_ps->invb.count)) + { + struct mib_node *mn; + struct snmp_obj_id oid; + + if (msg_ps->vb_idx == 0) + { + msg_ps->vb_ptr = msg_ps->invb.head; + } + else + { + msg_ps->vb_ptr = msg_ps->vb_ptr->next; + } + if (snmp_iso_prefix_expand(msg_ps->vb_ptr->ident_len, msg_ps->vb_ptr->ident, &oid)) + { + if (msg_ps->vb_ptr->ident_len > 3) + { + /* can offset ident_len and ident */ + mn = snmp_expand_tree((struct mib_node*)&internet, + msg_ps->vb_ptr->ident_len - 4, + msg_ps->vb_ptr->ident + 4, &oid); + } + else + { + /* can't offset ident_len -4, ident + 4 */ + mn = snmp_expand_tree((struct mib_node*)&internet, 0, NULL, &oid); + } + } + else + { + mn = NULL; + } + if (mn != NULL) + { + if (mn->node_type == MIB_NODE_EX) + { + /* external object */ + struct mib_external_node *en = (struct mib_external_node*)mn; + + msg_ps->state = SNMP_MSG_EXTERNAL_GET_OBJDEF; + /* save en && args in msg_ps!! */ + msg_ps->ext_mib_node = en; + msg_ps->ext_oid = oid; + + en->get_object_def_q(en->addr_inf, request_id, 1, &oid.id[oid.len - 1]); + } + else + { + /* internal object */ + struct obj_def object_def; + struct snmp_varbind *vb; + + msg_ps->state = SNMP_MSG_INTERNAL_GET_OBJDEF; + mn->get_object_def(1, &oid.id[oid.len - 1], &object_def); + + vb = snmp_varbind_alloc(&oid, object_def.asn_type, object_def.v_len); + if (vb != NULL) + { + msg_ps->state = SNMP_MSG_INTERNAL_GET_VALUE; + mn->get_value(&object_def, object_def.v_len, vb->value); + snmp_varbind_tail_add(&msg_ps->outvb, vb); + msg_ps->state = SNMP_MSG_SEARCH_OBJ; + msg_ps->vb_idx += 1; + } + else + { + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_recv couldn't allocate outvb space\n")); + snmp_error_response(msg_ps,SNMP_ES_TOOBIG); + } + } + } + if (mn == NULL) + { + /* mn == NULL, noSuchName */ + snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME); + } + } + if ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) && + (msg_ps->vb_idx == msg_ps->invb.count)) + { + snmp_ok_response(msg_ps); + } +} + +/** + * Service an internal or external event for SNMP SET. + * + * @param request_id identifies requests from 0 to (SNMP_CONCURRENT_REQUESTS-1) + * @param msg_ps points to the assosicated message process state + */ +static void +snmp_msg_set_event(u8_t request_id, struct snmp_msg_pstat *msg_ps) +{ + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_set_event: msg_ps->state==%"U16_F"\n",(u16_t)msg_ps->state)); + + if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_OBJDEF) + { + struct mib_external_node *en; + struct snmp_name_ptr np; + + /* get_object_def() answer*/ + en = msg_ps->ext_mib_node; + np = msg_ps->ext_name_ptr; + + /* translate answer into a known lifeform */ + en->get_object_def_a(request_id, np.ident_len, np.ident, &msg_ps->ext_object_def); + if (msg_ps->ext_object_def.instance != MIB_OBJECT_NONE) + { + msg_ps->state = SNMP_MSG_EXTERNAL_SET_TEST; + en->set_test_q(request_id, &msg_ps->ext_object_def); + } + else + { + en->get_object_def_pc(request_id, np.ident_len, np.ident); + /* search failed, object id points to unknown object (nosuchname) */ + snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME); + } + } + else if (msg_ps->state == SNMP_MSG_EXTERNAL_SET_TEST) + { + struct mib_external_node *en; + + /* set_test() answer*/ + en = msg_ps->ext_mib_node; + + if (msg_ps->ext_object_def.access == MIB_OBJECT_READ_WRITE) + { + if ((msg_ps->ext_object_def.asn_type == msg_ps->vb_ptr->value_type) && + (en->set_test_a(request_id,&msg_ps->ext_object_def, + msg_ps->vb_ptr->value_len,msg_ps->vb_ptr->value) != 0)) + { + msg_ps->state = SNMP_MSG_SEARCH_OBJ; + msg_ps->vb_idx += 1; + } + else + { + en->set_test_pc(request_id,&msg_ps->ext_object_def); + /* bad value */ + snmp_error_response(msg_ps,SNMP_ES_BADVALUE); + } + } + else + { + en->set_test_pc(request_id,&msg_ps->ext_object_def); + /* object not available for set */ + snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME); + } + } + else if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_OBJDEF_S) + { + struct mib_external_node *en; + struct snmp_name_ptr np; + + /* get_object_def() answer*/ + en = msg_ps->ext_mib_node; + np = msg_ps->ext_name_ptr; + + /* translate answer into a known lifeform */ + en->get_object_def_a(request_id, np.ident_len, np.ident, &msg_ps->ext_object_def); + if (msg_ps->ext_object_def.instance != MIB_OBJECT_NONE) + { + msg_ps->state = SNMP_MSG_EXTERNAL_SET_VALUE; + en->set_value_q(request_id, &msg_ps->ext_object_def, + msg_ps->vb_ptr->value_len,msg_ps->vb_ptr->value); + } + else + { + en->get_object_def_pc(request_id, np.ident_len, np.ident); + /* set_value failed, object has disappeared for some odd reason?? */ + snmp_error_response(msg_ps,SNMP_ES_GENERROR); + } + } + else if (msg_ps->state == SNMP_MSG_EXTERNAL_SET_VALUE) + { + struct mib_external_node *en; + + /** set_value_a() */ + en = msg_ps->ext_mib_node; + en->set_value_a(request_id, &msg_ps->ext_object_def, + msg_ps->vb_ptr->value_len, msg_ps->vb_ptr->value); + + /** @todo use set_value_pc() if toobig */ + msg_ps->state = SNMP_MSG_INTERNAL_SET_VALUE; + msg_ps->vb_idx += 1; + } + + /* test all values before setting */ + while ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) && + (msg_ps->vb_idx < msg_ps->invb.count)) + { + struct mib_node *mn; + struct snmp_name_ptr np; + + if (msg_ps->vb_idx == 0) + { + msg_ps->vb_ptr = msg_ps->invb.head; + } + else + { + msg_ps->vb_ptr = msg_ps->vb_ptr->next; + } + /** test object identifier for .iso.org.dod.internet prefix */ + if (snmp_iso_prefix_tst(msg_ps->vb_ptr->ident_len, msg_ps->vb_ptr->ident)) + { + mn = snmp_search_tree((struct mib_node*)&internet, msg_ps->vb_ptr->ident_len - 4, + msg_ps->vb_ptr->ident + 4, &np); + if (mn != NULL) + { + if (mn->node_type == MIB_NODE_EX) + { + /* external object */ + struct mib_external_node *en = (struct mib_external_node*)mn; + + msg_ps->state = SNMP_MSG_EXTERNAL_GET_OBJDEF; + /* save en && args in msg_ps!! */ + msg_ps->ext_mib_node = en; + msg_ps->ext_name_ptr = np; + + en->get_object_def_q(en->addr_inf, request_id, np.ident_len, np.ident); + } + else + { + /* internal object */ + struct obj_def object_def; + + msg_ps->state = SNMP_MSG_INTERNAL_GET_OBJDEF; + mn->get_object_def(np.ident_len, np.ident, &object_def); + if (object_def.instance != MIB_OBJECT_NONE) + { + mn = mn; + } + else + { + /* search failed, object id points to unknown object (nosuchname) */ + mn = NULL; + } + if (mn != NULL) + { + msg_ps->state = SNMP_MSG_INTERNAL_SET_TEST; + + if (object_def.access == MIB_OBJECT_READ_WRITE) + { + if ((object_def.asn_type == msg_ps->vb_ptr->value_type) && + (mn->set_test(&object_def,msg_ps->vb_ptr->value_len,msg_ps->vb_ptr->value) != 0)) + { + msg_ps->state = SNMP_MSG_SEARCH_OBJ; + msg_ps->vb_idx += 1; + } + else + { + /* bad value */ + snmp_error_response(msg_ps,SNMP_ES_BADVALUE); + } + } + else + { + /* object not available for set */ + snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME); + } + } + } + } + } + else + { + mn = NULL; + } + if (mn == NULL) + { + /* mn == NULL, noSuchName */ + snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME); + } + } + + if ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) && + (msg_ps->vb_idx == msg_ps->invb.count)) + { + msg_ps->vb_idx = 0; + msg_ps->state = SNMP_MSG_INTERNAL_SET_VALUE; + } + + /* set all values "atomically" (be as "atomic" as possible) */ + while ((msg_ps->state == SNMP_MSG_INTERNAL_SET_VALUE) && + (msg_ps->vb_idx < msg_ps->invb.count)) + { + struct mib_node *mn; + struct snmp_name_ptr np; + + if (msg_ps->vb_idx == 0) + { + msg_ps->vb_ptr = msg_ps->invb.head; + } + else + { + msg_ps->vb_ptr = msg_ps->vb_ptr->next; + } + /* skip iso prefix test, was done previously while settesting() */ + mn = snmp_search_tree((struct mib_node*)&internet, msg_ps->vb_ptr->ident_len - 4, + msg_ps->vb_ptr->ident + 4, &np); + /* check if object is still available + (e.g. external hot-plug thingy present?) */ + if (mn != NULL) + { + if (mn->node_type == MIB_NODE_EX) + { + /* external object */ + struct mib_external_node *en = (struct mib_external_node*)mn; + + msg_ps->state = SNMP_MSG_EXTERNAL_GET_OBJDEF_S; + /* save en && args in msg_ps!! */ + msg_ps->ext_mib_node = en; + msg_ps->ext_name_ptr = np; + + en->get_object_def_q(en->addr_inf, request_id, np.ident_len, np.ident); + } + else + { + /* internal object */ + struct obj_def object_def; + + msg_ps->state = SNMP_MSG_INTERNAL_GET_OBJDEF_S; + mn->get_object_def(np.ident_len, np.ident, &object_def); + msg_ps->state = SNMP_MSG_INTERNAL_SET_VALUE; + mn->set_value(&object_def,msg_ps->vb_ptr->value_len,msg_ps->vb_ptr->value); + msg_ps->vb_idx += 1; + } + } + } + if ((msg_ps->state == SNMP_MSG_INTERNAL_SET_VALUE) && + (msg_ps->vb_idx == msg_ps->invb.count)) + { + /* simply echo the input if we can set it + @todo do we need to return the actual value? + e.g. if value is silently modified or behaves sticky? */ + msg_ps->outvb = msg_ps->invb; + msg_ps->invb.head = NULL; + msg_ps->invb.tail = NULL; + msg_ps->invb.count = 0; + snmp_ok_response(msg_ps); + } +} + + +/** + * Handle one internal or external event. + * Called for one async event. (recv external/private answer) + * + * @param request_id identifies requests from 0 to (SNMP_CONCURRENT_REQUESTS-1) + */ +void +snmp_msg_event(u8_t request_id) +{ + struct snmp_msg_pstat *msg_ps; + + if (request_id < SNMP_CONCURRENT_REQUESTS) + { + msg_ps = &msg_input_list[request_id]; + if (msg_ps->rt == SNMP_ASN1_PDU_GET_NEXT_REQ) + { + snmp_msg_getnext_event(request_id, msg_ps); + } + else if (msg_ps->rt == SNMP_ASN1_PDU_GET_REQ) + { + snmp_msg_get_event(request_id, msg_ps); + } + else if(msg_ps->rt == SNMP_ASN1_PDU_SET_REQ) + { + snmp_msg_set_event(request_id, msg_ps); + } + } +} + + +/* lwIP UDP receive callback function */ +static void +snmp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port) +{ + struct udp_hdr *udphdr; + + /* suppress unused argument warning */ + LWIP_UNUSED_ARG(arg); + /* peek in the UDP header (goto IP payload) */ + if(pbuf_header(p, UDP_HLEN)){ + LWIP_ASSERT("Can't move to UDP header", 0); + pbuf_free(p); + return; + } + udphdr = p->payload; + + /* check if datagram is really directed at us (including broadcast requests) */ + if ((pcb == snmp1_pcb) && (ntohs(udphdr->dest) == SNMP_IN_PORT)) + { + struct snmp_msg_pstat *msg_ps; + u8_t req_idx; + + /* traverse input message process list, look for SNMP_MSG_EMPTY */ + msg_ps = &msg_input_list[0]; + req_idx = 0; + while ((req_idxstate != SNMP_MSG_EMPTY)) + { + req_idx++; + msg_ps++; + } + if (req_idx != SNMP_CONCURRENT_REQUESTS) + { + err_t err_ret; + u16_t payload_len; + u16_t payload_ofs; + u16_t varbind_ofs = 0; + + /* accepting request */ + snmp_inc_snmpinpkts(); + /* record used 'protocol control block' */ + msg_ps->pcb = pcb; + /* source address (network order) */ + msg_ps->sip = *addr; + /* source port (host order (lwIP oddity)) */ + msg_ps->sp = port; + /* read UDP payload length from UDP header */ + payload_len = ntohs(udphdr->len) - UDP_HLEN; + + /* adjust to UDP payload */ + payload_ofs = UDP_HLEN; + + /* check total length, version, community, pdu type */ + err_ret = snmp_pdu_header_check(p, payload_ofs, payload_len, &varbind_ofs, msg_ps); + if (((msg_ps->rt == SNMP_ASN1_PDU_GET_REQ) || + (msg_ps->rt == SNMP_ASN1_PDU_GET_NEXT_REQ) || + (msg_ps->rt == SNMP_ASN1_PDU_SET_REQ)) && + ((msg_ps->error_status == SNMP_ES_NOERROR) && + (msg_ps->error_index == 0)) ) + { + /* Only accept requests and requests without error (be robust) */ + err_ret = err_ret; + } + else + { + /* Reject response and trap headers or error requests as input! */ + err_ret = ERR_ARG; + } + if (err_ret == ERR_OK) + { + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_recv ok, community %s\n", msg_ps->community)); + + /* Builds a list of variable bindings. Copy the varbinds from the pbuf + chain to glue them when these are divided over two or more pbuf's. */ + err_ret = snmp_pdu_dec_varbindlist(p, varbind_ofs, &varbind_ofs, msg_ps); + if ((err_ret == ERR_OK) && (msg_ps->invb.count > 0)) + { + /* we've decoded the incoming message, release input msg now */ + pbuf_free(p); + + msg_ps->error_status = SNMP_ES_NOERROR; + msg_ps->error_index = 0; + /* find object for each variable binding */ + msg_ps->state = SNMP_MSG_SEARCH_OBJ; + /* first variable binding from list to inspect */ + msg_ps->vb_idx = 0; + + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_recv varbind cnt=%"U16_F"\n",(u16_t)msg_ps->invb.count)); + + /* handle input event and as much objects as possible in one go */ + snmp_msg_event(req_idx); + } + else + { + /* varbind-list decode failed, or varbind list empty. + drop request silently, do not return error! + (errors are only returned for a specific varbind failure) */ + pbuf_free(p); + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_pdu_dec_varbindlist() failed\n")); + } + } + else + { + /* header check failed + drop request silently, do not return error! */ + pbuf_free(p); + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_pdu_header_check() failed\n")); + } + } + else + { + /* exceeding number of concurrent requests */ + pbuf_free(p); + } + } + else + { + /* datagram not for us */ + pbuf_free(p); + } +} + +/** + * Checks and decodes incoming SNMP message header, logs header errors. + * + * @param p points to pbuf chain of SNMP message (UDP payload) + * @param ofs points to first octet of SNMP message + * @param pdu_len the length of the UDP payload + * @param ofs_ret returns the ofset of the variable bindings + * @param m_stat points to the current message request state return + * @return + * - ERR_OK SNMP header is sane and accepted + * - ERR_ARG SNMP header is either malformed or rejected + */ +static err_t +snmp_pdu_header_check(struct pbuf *p, u16_t ofs, u16_t pdu_len, u16_t *ofs_ret, struct snmp_msg_pstat *m_stat) +{ + err_t derr; + u16_t len, ofs_base; + u8_t len_octets; + u8_t type; + s32_t version; + + ofs_base = ofs; + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); + if ((derr != ERR_OK) || + (pdu_len != (1 + len_octets + len)) || + (type != (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ))) + { + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + ofs += (1 + len_octets); + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); + if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG))) + { + /* can't decode or no integer (version) */ + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, &version); + if (derr != ERR_OK) + { + /* can't decode */ + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + if (version != 0) + { + /* not version 1 */ + snmp_inc_snmpinbadversions(); + return ERR_ARG; + } + ofs += (1 + len_octets + len); + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); + if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR))) + { + /* can't decode or no octet string (community) */ + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + derr = snmp_asn1_dec_raw(p, ofs + 1 + len_octets, len, SNMP_COMMUNITY_STR_LEN, m_stat->community); + if (derr != ERR_OK) + { + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + /* add zero terminator */ + len = ((len < (SNMP_COMMUNITY_STR_LEN))?(len):(SNMP_COMMUNITY_STR_LEN)); + m_stat->community[len] = 0; + m_stat->com_strlen = len; + if (strncmp(snmp_publiccommunity, (const char*)m_stat->community, SNMP_COMMUNITY_STR_LEN) != 0) + { + /** @todo: move this if we need to check more names */ + snmp_inc_snmpinbadcommunitynames(); + snmp_authfail_trap(); + return ERR_ARG; + } + ofs += (1 + len_octets + len); + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); + if (derr != ERR_OK) + { + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + switch(type) + { + case (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_GET_REQ): + /* GetRequest PDU */ + snmp_inc_snmpingetrequests(); + derr = ERR_OK; + break; + case (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_GET_NEXT_REQ): + /* GetNextRequest PDU */ + snmp_inc_snmpingetnexts(); + derr = ERR_OK; + break; + case (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_GET_RESP): + /* GetResponse PDU */ + snmp_inc_snmpingetresponses(); + derr = ERR_ARG; + break; + case (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_SET_REQ): + /* SetRequest PDU */ + snmp_inc_snmpinsetrequests(); + derr = ERR_OK; + break; + case (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_TRAP): + /* Trap PDU */ + snmp_inc_snmpintraps(); + derr = ERR_ARG; + break; + default: + snmp_inc_snmpinasnparseerrs(); + derr = ERR_ARG; + break; + } + if (derr != ERR_OK) + { + /* unsupported input PDU for this agent (no parse error) */ + return ERR_ARG; + } + m_stat->rt = type & 0x1F; + ofs += (1 + len_octets); + if (len != (pdu_len - (ofs - ofs_base))) + { + /* decoded PDU length does not equal actual payload length */ + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); + if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG))) + { + /* can't decode or no integer (request ID) */ + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, &m_stat->rid); + if (derr != ERR_OK) + { + /* can't decode */ + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + ofs += (1 + len_octets + len); + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); + if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG))) + { + /* can't decode or no integer (error-status) */ + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + /* must be noError (0) for incoming requests. + log errors for mib-2 completeness and for debug purposes */ + derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, &m_stat->error_status); + if (derr != ERR_OK) + { + /* can't decode */ + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + switch (m_stat->error_status) + { + case SNMP_ES_TOOBIG: + snmp_inc_snmpintoobigs(); + break; + case SNMP_ES_NOSUCHNAME: + snmp_inc_snmpinnosuchnames(); + break; + case SNMP_ES_BADVALUE: + snmp_inc_snmpinbadvalues(); + break; + case SNMP_ES_READONLY: + snmp_inc_snmpinreadonlys(); + break; + case SNMP_ES_GENERROR: + snmp_inc_snmpingenerrs(); + break; + } + ofs += (1 + len_octets + len); + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); + if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG))) + { + /* can't decode or no integer (error-index) */ + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + /* must be 0 for incoming requests. + decode anyway to catch bad integers (and dirty tricks) */ + derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, &m_stat->error_index); + if (derr != ERR_OK) + { + /* can't decode */ + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + ofs += (1 + len_octets + len); + *ofs_ret = ofs; + return ERR_OK; +} + +static err_t +snmp_pdu_dec_varbindlist(struct pbuf *p, u16_t ofs, u16_t *ofs_ret, struct snmp_msg_pstat *m_stat) +{ + err_t derr; + u16_t len, vb_len; + u8_t len_octets; + u8_t type; + + /* variable binding list */ + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &vb_len); + if ((derr != ERR_OK) || + (type != (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ))) + { + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + ofs += (1 + len_octets); + + /* start with empty list */ + m_stat->invb.count = 0; + m_stat->invb.head = NULL; + m_stat->invb.tail = NULL; + + while (vb_len > 0) + { + struct snmp_obj_id oid, oid_value; + struct snmp_varbind *vb; + + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); + if ((derr != ERR_OK) || + (type != (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)) || + (len == 0) || (len > vb_len)) + { + snmp_inc_snmpinasnparseerrs(); + /* free varbinds (if available) */ + snmp_varbind_list_free(&m_stat->invb); + return ERR_ARG; + } + ofs += (1 + len_octets); + vb_len -= (1 + len_octets); + + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); + if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID))) + { + /* can't decode object name length */ + snmp_inc_snmpinasnparseerrs(); + /* free varbinds (if available) */ + snmp_varbind_list_free(&m_stat->invb); + return ERR_ARG; + } + derr = snmp_asn1_dec_oid(p, ofs + 1 + len_octets, len, &oid); + if (derr != ERR_OK) + { + /* can't decode object name */ + snmp_inc_snmpinasnparseerrs(); + /* free varbinds (if available) */ + snmp_varbind_list_free(&m_stat->invb); + return ERR_ARG; + } + ofs += (1 + len_octets + len); + vb_len -= (1 + len_octets + len); + + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); + if (derr != ERR_OK) + { + /* can't decode object value length */ + snmp_inc_snmpinasnparseerrs(); + /* free varbinds (if available) */ + snmp_varbind_list_free(&m_stat->invb); + return ERR_ARG; + } + + switch (type) + { + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG): + vb = snmp_varbind_alloc(&oid, type, sizeof(s32_t)); + if (vb != NULL) + { + s32_t *vptr = vb->value; + + derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, vptr); + snmp_varbind_tail_add(&m_stat->invb, vb); + } + else + { + derr = ERR_ARG; + } + break; + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS): + vb = snmp_varbind_alloc(&oid, type, sizeof(u32_t)); + if (vb != NULL) + { + u32_t *vptr = vb->value; + + derr = snmp_asn1_dec_u32t(p, ofs + 1 + len_octets, len, vptr); + snmp_varbind_tail_add(&m_stat->invb, vb); + } + else + { + derr = ERR_ARG; + } + break; + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_OPAQUE): + vb = snmp_varbind_alloc(&oid, type, len); + if (vb != NULL) + { + derr = snmp_asn1_dec_raw(p, ofs + 1 + len_octets, len, vb->value_len, vb->value); + snmp_varbind_tail_add(&m_stat->invb, vb); + } + else + { + derr = ERR_ARG; + } + break; + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_NUL): + vb = snmp_varbind_alloc(&oid, type, 0); + if (vb != NULL) + { + snmp_varbind_tail_add(&m_stat->invb, vb); + derr = ERR_OK; + } + else + { + derr = ERR_ARG; + } + break; + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID): + derr = snmp_asn1_dec_oid(p, ofs + 1 + len_octets, len, &oid_value); + if (derr == ERR_OK) + { + vb = snmp_varbind_alloc(&oid, type, oid_value.len * sizeof(s32_t)); + if (vb != NULL) + { + u8_t i = oid_value.len; + s32_t *vptr = vb->value; + + while(i > 0) + { + i--; + vptr[i] = oid_value.id[i]; + } + snmp_varbind_tail_add(&m_stat->invb, vb); + derr = ERR_OK; + } + else + { + derr = ERR_ARG; + } + } + break; + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR): + if (len == 4) + { + /* must be exactly 4 octets! */ + vb = snmp_varbind_alloc(&oid, type, 4); + if (vb != NULL) + { + derr = snmp_asn1_dec_raw(p, ofs + 1 + len_octets, len, vb->value_len, vb->value); + snmp_varbind_tail_add(&m_stat->invb, vb); + } + else + { + derr = ERR_ARG; + } + } + else + { + derr = ERR_ARG; + } + break; + default: + derr = ERR_ARG; + break; + } + if (derr != ERR_OK) + { + snmp_inc_snmpinasnparseerrs(); + /* free varbinds (if available) */ + snmp_varbind_list_free(&m_stat->invb); + return ERR_ARG; + } + ofs += (1 + len_octets + len); + vb_len -= (1 + len_octets + len); + } + + if (m_stat->rt == SNMP_ASN1_PDU_SET_REQ) + { + snmp_add_snmpintotalsetvars(m_stat->invb.count); + } + else + { + snmp_add_snmpintotalreqvars(m_stat->invb.count); + } + + *ofs_ret = ofs; + return ERR_OK; +} + +struct snmp_varbind* +snmp_varbind_alloc(struct snmp_obj_id *oid, u8_t type, u8_t len) +{ + struct snmp_varbind *vb; + + vb = (struct snmp_varbind *)mem_malloc(sizeof(struct snmp_varbind)); + LWIP_ASSERT("vb != NULL",vb != NULL); + if (vb != NULL) + { + u8_t i; + + vb->next = NULL; + vb->prev = NULL; + i = oid->len; + vb->ident_len = i; + if (i > 0) + { + /* allocate array of s32_t for our object identifier */ + vb->ident = (s32_t*)mem_malloc(sizeof(s32_t) * i); + LWIP_ASSERT("vb->ident != NULL",vb->ident != NULL); + if (vb->ident == NULL) + { + mem_free(vb); + return NULL; + } + while(i > 0) + { + i--; + vb->ident[i] = oid->id[i]; + } + } + else + { + /* i == 0, pass zero length object identifier */ + vb->ident = NULL; + } + vb->value_type = type; + vb->value_len = len; + if (len > 0) + { + /* allocate raw bytes for our object value */ + vb->value = mem_malloc(len); + LWIP_ASSERT("vb->value != NULL",vb->value != NULL); + if (vb->value == NULL) + { + if (vb->ident != NULL) + { + mem_free(vb->ident); + } + mem_free(vb); + return NULL; + } + } + else + { + /* ASN1_NUL type, or zero length ASN1_OC_STR */ + vb->value = NULL; + } + } + return vb; +} + +void +snmp_varbind_free(struct snmp_varbind *vb) +{ + if (vb->value != NULL ) + { + mem_free(vb->value); + } + if (vb->ident != NULL ) + { + mem_free(vb->ident); + } + mem_free(vb); +} + +void +snmp_varbind_list_free(struct snmp_varbind_root *root) +{ + struct snmp_varbind *vb, *prev; + + vb = root->tail; + while ( vb != NULL ) + { + prev = vb->prev; + snmp_varbind_free(vb); + vb = prev; + } + root->count = 0; + root->head = NULL; + root->tail = NULL; +} + +void +snmp_varbind_tail_add(struct snmp_varbind_root *root, struct snmp_varbind *vb) +{ + if (root->count == 0) + { + /* add first varbind to list */ + root->head = vb; + root->tail = vb; + } + else + { + /* add nth varbind to list tail */ + root->tail->next = vb; + vb->prev = root->tail; + root->tail = vb; + } + root->count += 1; +} + +struct snmp_varbind* +snmp_varbind_tail_remove(struct snmp_varbind_root *root) +{ + struct snmp_varbind* vb; + + if (root->count > 0) + { + /* remove tail varbind */ + vb = root->tail; + root->tail = vb->prev; + vb->prev->next = NULL; + root->count -= 1; + } + else + { + /* nothing to remove */ + vb = NULL; + } + return vb; +} + +#endif /* LWIP_SNMP */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/core/snmp/msg_out.c b/component/common/network/lwip/lwip_v1.3.2/src/core/snmp/msg_out.c new file mode 100644 index 0000000..b705aac --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/core/snmp/msg_out.c @@ -0,0 +1,683 @@ +/** + * @file + * SNMP output message processing (RFC1157). + * + * Output responses and traps are build in two passes: + * + * Pass 0: iterate over the output message backwards to determine encoding lengths + * Pass 1: the actual forward encoding of internal form into ASN1 + * + * The single-pass encoding method described by Comer & Stevens + * requires extra buffer space and copying for reversal of the packet. + * The buffer requirement can be prohibitively large for big payloads + * (>= 484) therefore we use the two encoding passes. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * Author: Christiaan Simons + */ + +#include "lwip/opt.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/udp.h" +#include "lwip/netif.h" +#include "lwip/snmp.h" +#include "lwip/snmp_asn1.h" +#include "lwip/snmp_msg.h" + +struct snmp_trap_dst +{ + /* destination IP address in network order */ + struct ip_addr dip; + /* set to 0 when disabled, >0 when enabled */ + u8_t enable; +}; +struct snmp_trap_dst trap_dst[SNMP_TRAP_DESTINATIONS]; + +/** TRAP message structure */ +struct snmp_msg_trap trap_msg; + +static u16_t snmp_resp_header_sum(struct snmp_msg_pstat *m_stat, u16_t vb_len); +static u16_t snmp_trap_header_sum(struct snmp_msg_trap *m_trap, u16_t vb_len); +static u16_t snmp_varbind_list_sum(struct snmp_varbind_root *root); + +static u16_t snmp_resp_header_enc(struct snmp_msg_pstat *m_stat, struct pbuf *p); +static u16_t snmp_trap_header_enc(struct snmp_msg_trap *m_trap, struct pbuf *p); +static u16_t snmp_varbind_list_enc(struct snmp_varbind_root *root, struct pbuf *p, u16_t ofs); + +/** + * Sets enable switch for this trap destination. + * @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1 + * @param enable switch if 0 destination is disabled >0 enabled. + */ +void +snmp_trap_dst_enable(u8_t dst_idx, u8_t enable) +{ + if (dst_idx < SNMP_TRAP_DESTINATIONS) + { + trap_dst[dst_idx].enable = enable; + } +} + +/** + * Sets IPv4 address for this trap destination. + * @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1 + * @param dst IPv4 address in host order. + */ +void +snmp_trap_dst_ip_set(u8_t dst_idx, struct ip_addr *dst) +{ + if (dst_idx < SNMP_TRAP_DESTINATIONS) + { + trap_dst[dst_idx].dip.addr = htonl(dst->addr); + } +} + +/** + * Sends a 'getresponse' message to the request originator. + * + * @param m_stat points to the current message request state source + * @return ERR_OK when success, ERR_MEM if we're out of memory + * + * @note the caller is responsible for filling in outvb in the m_stat + * and provide error-status and index (except for tooBig errors) ... + */ +err_t +snmp_send_response(struct snmp_msg_pstat *m_stat) +{ + struct snmp_varbind_root emptyvb = {NULL, NULL, 0, 0, 0}; + struct pbuf *p; + u16_t tot_len; + err_t err; + + /* pass 0, calculate length fields */ + tot_len = snmp_varbind_list_sum(&m_stat->outvb); + tot_len = snmp_resp_header_sum(m_stat, tot_len); + + /* try allocating pbuf(s) for complete response */ + p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_POOL); + if (p == NULL) + { + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_snd_response() tooBig\n")); + + /* can't construct reply, return error-status tooBig */ + m_stat->error_status = SNMP_ES_TOOBIG; + m_stat->error_index = 0; + /* pass 0, recalculate lengths, for empty varbind-list */ + tot_len = snmp_varbind_list_sum(&emptyvb); + tot_len = snmp_resp_header_sum(m_stat, tot_len); + /* retry allocation once for header and empty varbind-list */ + p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_POOL); + } + if (p != NULL) + { + /* first pbuf alloc try or retry alloc success */ + u16_t ofs; + + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_snd_response() p != NULL\n")); + + /* pass 1, size error, encode packet ino the pbuf(s) */ + ofs = snmp_resp_header_enc(m_stat, p); + if (m_stat->error_status == SNMP_ES_TOOBIG) + { + snmp_varbind_list_enc(&emptyvb, p, ofs); + } + else + { + snmp_varbind_list_enc(&m_stat->outvb, p, ofs); + } + + switch (m_stat->error_status) + { + case SNMP_ES_TOOBIG: + snmp_inc_snmpouttoobigs(); + break; + case SNMP_ES_NOSUCHNAME: + snmp_inc_snmpoutnosuchnames(); + break; + case SNMP_ES_BADVALUE: + snmp_inc_snmpoutbadvalues(); + break; + case SNMP_ES_GENERROR: + snmp_inc_snmpoutgenerrs(); + break; + } + snmp_inc_snmpoutgetresponses(); + snmp_inc_snmpoutpkts(); + + /** @todo do we need separate rx and tx pcbs for threaded case? */ + /** connect to the originating source */ + udp_connect(m_stat->pcb, &m_stat->sip, m_stat->sp); + err = udp_send(m_stat->pcb, p); + if (err == ERR_MEM) + { + /** @todo release some memory, retry and return tooBig? tooMuchHassle? */ + err = ERR_MEM; + } + else + { + err = ERR_OK; + } + /** disassociate remote address and port with this pcb */ + udp_disconnect(m_stat->pcb); + + pbuf_free(p); + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_snd_response() done\n")); + return err; + } + else + { + /* first pbuf alloc try or retry alloc failed + very low on memory, couldn't return tooBig */ + return ERR_MEM; + } +} + + +/** + * Sends an generic or enterprise specific trap message. + * + * @param generic_trap is the trap code + * @param eoid points to enterprise object identifier + * @param specific_trap used for enterprise traps when generic_trap == 6 + * @return ERR_OK when success, ERR_MEM if we're out of memory + * + * @note the caller is responsible for filling in outvb in the trap_msg + * @note the use of the enterpise identifier field + * is per RFC1215. + * Use .iso.org.dod.internet.mgmt.mib-2.snmp for generic traps + * and .iso.org.dod.internet.private.enterprises.yourenterprise + * (sysObjectID) for specific traps. + */ +err_t +snmp_send_trap(s8_t generic_trap, struct snmp_obj_id *eoid, s32_t specific_trap) +{ + struct snmp_trap_dst *td; + struct netif *dst_if; + struct ip_addr dst_ip; + struct pbuf *p; + u16_t i,tot_len; + + for (i=0, td = &trap_dst[0]; ienable != 0) && (td->dip.addr != 0)) + { + /* network order trap destination */ + trap_msg.dip.addr = td->dip.addr; + /* lookup current source address for this dst */ + dst_if = ip_route(&td->dip); + dst_ip.addr = ntohl(dst_if->ip_addr.addr); + trap_msg.sip_raw[0] = dst_ip.addr >> 24; + trap_msg.sip_raw[1] = dst_ip.addr >> 16; + trap_msg.sip_raw[2] = dst_ip.addr >> 8; + trap_msg.sip_raw[3] = dst_ip.addr; + trap_msg.gen_trap = generic_trap; + trap_msg.spc_trap = specific_trap; + if (generic_trap == SNMP_GENTRAP_ENTERPRISESPC) + { + /* enterprise-Specific trap */ + trap_msg.enterprise = eoid; + } + else + { + /* generic (MIB-II) trap */ + snmp_get_snmpgrpid_ptr(&trap_msg.enterprise); + } + snmp_get_sysuptime(&trap_msg.ts); + + /* pass 0, calculate length fields */ + tot_len = snmp_varbind_list_sum(&trap_msg.outvb); + tot_len = snmp_trap_header_sum(&trap_msg, tot_len); + + /* allocate pbuf(s) */ + p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_POOL); + if (p != NULL) + { + u16_t ofs; + + /* pass 1, encode packet ino the pbuf(s) */ + ofs = snmp_trap_header_enc(&trap_msg, p); + snmp_varbind_list_enc(&trap_msg.outvb, p, ofs); + + snmp_inc_snmpouttraps(); + snmp_inc_snmpoutpkts(); + + /** connect to the TRAP destination */ + udp_connect(trap_msg.pcb, &trap_msg.dip, SNMP_TRAP_PORT); + udp_send(trap_msg.pcb, p); + /** disassociate remote address and port with this pcb */ + udp_disconnect(trap_msg.pcb); + + pbuf_free(p); + } + else + { + return ERR_MEM; + } + } + } + return ERR_OK; +} + +void +snmp_coldstart_trap(void) +{ + trap_msg.outvb.head = NULL; + trap_msg.outvb.tail = NULL; + trap_msg.outvb.count = 0; + snmp_send_trap(SNMP_GENTRAP_COLDSTART, NULL, 0); +} + +void +snmp_authfail_trap(void) +{ + u8_t enable; + snmp_get_snmpenableauthentraps(&enable); + if (enable == 1) + { + trap_msg.outvb.head = NULL; + trap_msg.outvb.tail = NULL; + trap_msg.outvb.count = 0; + snmp_send_trap(SNMP_GENTRAP_AUTHFAIL, NULL, 0); + } +} + +/** + * Sums response header field lengths from tail to head and + * returns resp_header_lengths for second encoding pass. + * + * @param vb_len varbind-list length + * @param rhl points to returned header lengths + * @return the required lenght for encoding the response header + */ +static u16_t +snmp_resp_header_sum(struct snmp_msg_pstat *m_stat, u16_t vb_len) +{ + u16_t tot_len; + struct snmp_resp_header_lengths *rhl; + + rhl = &m_stat->rhl; + tot_len = vb_len; + snmp_asn1_enc_s32t_cnt(m_stat->error_index, &rhl->erridxlen); + snmp_asn1_enc_length_cnt(rhl->erridxlen, &rhl->erridxlenlen); + tot_len += 1 + rhl->erridxlenlen + rhl->erridxlen; + + snmp_asn1_enc_s32t_cnt(m_stat->error_status, &rhl->errstatlen); + snmp_asn1_enc_length_cnt(rhl->errstatlen, &rhl->errstatlenlen); + tot_len += 1 + rhl->errstatlenlen + rhl->errstatlen; + + snmp_asn1_enc_s32t_cnt(m_stat->rid, &rhl->ridlen); + snmp_asn1_enc_length_cnt(rhl->ridlen, &rhl->ridlenlen); + tot_len += 1 + rhl->ridlenlen + rhl->ridlen; + + rhl->pdulen = tot_len; + snmp_asn1_enc_length_cnt(rhl->pdulen, &rhl->pdulenlen); + tot_len += 1 + rhl->pdulenlen; + + rhl->comlen = m_stat->com_strlen; + snmp_asn1_enc_length_cnt(rhl->comlen, &rhl->comlenlen); + tot_len += 1 + rhl->comlenlen + rhl->comlen; + + snmp_asn1_enc_s32t_cnt(snmp_version, &rhl->verlen); + snmp_asn1_enc_length_cnt(rhl->verlen, &rhl->verlenlen); + tot_len += 1 + rhl->verlen + rhl->verlenlen; + + rhl->seqlen = tot_len; + snmp_asn1_enc_length_cnt(rhl->seqlen, &rhl->seqlenlen); + tot_len += 1 + rhl->seqlenlen; + + return tot_len; +} + +/** + * Sums trap header field lengths from tail to head and + * returns trap_header_lengths for second encoding pass. + * + * @param vb_len varbind-list length + * @param thl points to returned header lengths + * @return the required lenght for encoding the trap header + */ +static u16_t +snmp_trap_header_sum(struct snmp_msg_trap *m_trap, u16_t vb_len) +{ + u16_t tot_len; + struct snmp_trap_header_lengths *thl; + + thl = &m_trap->thl; + tot_len = vb_len; + + snmp_asn1_enc_u32t_cnt(m_trap->ts, &thl->tslen); + snmp_asn1_enc_length_cnt(thl->tslen, &thl->tslenlen); + tot_len += 1 + thl->tslen + thl->tslenlen; + + snmp_asn1_enc_s32t_cnt(m_trap->spc_trap, &thl->strplen); + snmp_asn1_enc_length_cnt(thl->strplen, &thl->strplenlen); + tot_len += 1 + thl->strplen + thl->strplenlen; + + snmp_asn1_enc_s32t_cnt(m_trap->gen_trap, &thl->gtrplen); + snmp_asn1_enc_length_cnt(thl->gtrplen, &thl->gtrplenlen); + tot_len += 1 + thl->gtrplen + thl->gtrplenlen; + + thl->aaddrlen = 4; + snmp_asn1_enc_length_cnt(thl->aaddrlen, &thl->aaddrlenlen); + tot_len += 1 + thl->aaddrlen + thl->aaddrlenlen; + + snmp_asn1_enc_oid_cnt(m_trap->enterprise->len, &m_trap->enterprise->id[0], &thl->eidlen); + snmp_asn1_enc_length_cnt(thl->eidlen, &thl->eidlenlen); + tot_len += 1 + thl->eidlen + thl->eidlenlen; + + thl->pdulen = tot_len; + snmp_asn1_enc_length_cnt(thl->pdulen, &thl->pdulenlen); + tot_len += 1 + thl->pdulenlen; + + thl->comlen = sizeof(snmp_publiccommunity) - 1; + snmp_asn1_enc_length_cnt(thl->comlen, &thl->comlenlen); + tot_len += 1 + thl->comlenlen + thl->comlen; + + snmp_asn1_enc_s32t_cnt(snmp_version, &thl->verlen); + snmp_asn1_enc_length_cnt(thl->verlen, &thl->verlenlen); + tot_len += 1 + thl->verlen + thl->verlenlen; + + thl->seqlen = tot_len; + snmp_asn1_enc_length_cnt(thl->seqlen, &thl->seqlenlen); + tot_len += 1 + thl->seqlenlen; + + return tot_len; +} + +/** + * Sums varbind lengths from tail to head and + * annotates lengths in varbind for second encoding pass. + * + * @param root points to the root of the variable binding list + * @return the required lenght for encoding the variable bindings + */ +static u16_t +snmp_varbind_list_sum(struct snmp_varbind_root *root) +{ + struct snmp_varbind *vb; + u32_t *uint_ptr; + s32_t *sint_ptr; + u16_t tot_len; + + tot_len = 0; + vb = root->tail; + while ( vb != NULL ) + { + /* encoded value lenght depends on type */ + switch (vb->value_type) + { + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG): + sint_ptr = vb->value; + snmp_asn1_enc_s32t_cnt(*sint_ptr, &vb->vlen); + break; + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS): + uint_ptr = vb->value; + snmp_asn1_enc_u32t_cnt(*uint_ptr, &vb->vlen); + break; + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR): + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_NUL): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_OPAQUE): + vb->vlen = vb->value_len; + break; + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID): + sint_ptr = vb->value; + snmp_asn1_enc_oid_cnt(vb->value_len / sizeof(s32_t), sint_ptr, &vb->vlen); + break; + default: + /* unsupported type */ + vb->vlen = 0; + break; + }; + /* encoding length of value length field */ + snmp_asn1_enc_length_cnt(vb->vlen, &vb->vlenlen); + snmp_asn1_enc_oid_cnt(vb->ident_len, vb->ident, &vb->olen); + snmp_asn1_enc_length_cnt(vb->olen, &vb->olenlen); + + vb->seqlen = 1 + vb->vlenlen + vb->vlen; + vb->seqlen += 1 + vb->olenlen + vb->olen; + snmp_asn1_enc_length_cnt(vb->seqlen, &vb->seqlenlen); + + /* varbind seq */ + tot_len += 1 + vb->seqlenlen + vb->seqlen; + + vb = vb->prev; + } + + /* varbind-list seq */ + root->seqlen = tot_len; + snmp_asn1_enc_length_cnt(root->seqlen, &root->seqlenlen); + tot_len += 1 + root->seqlenlen; + + return tot_len; +} + +/** + * Encodes response header from head to tail. + */ +static u16_t +snmp_resp_header_enc(struct snmp_msg_pstat *m_stat, struct pbuf *p) +{ + u16_t ofs; + + ofs = 0; + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_stat->rhl.seqlen); + ofs += m_stat->rhl.seqlenlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_stat->rhl.verlen); + ofs += m_stat->rhl.verlenlen; + snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.verlen, snmp_version); + ofs += m_stat->rhl.verlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_stat->rhl.comlen); + ofs += m_stat->rhl.comlenlen; + snmp_asn1_enc_raw(p, ofs, m_stat->rhl.comlen, m_stat->community); + ofs += m_stat->rhl.comlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_GET_RESP)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_stat->rhl.pdulen); + ofs += m_stat->rhl.pdulenlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_stat->rhl.ridlen); + ofs += m_stat->rhl.ridlenlen; + snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.ridlen, m_stat->rid); + ofs += m_stat->rhl.ridlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_stat->rhl.errstatlen); + ofs += m_stat->rhl.errstatlenlen; + snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.errstatlen, m_stat->error_status); + ofs += m_stat->rhl.errstatlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_stat->rhl.erridxlen); + ofs += m_stat->rhl.erridxlenlen; + snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.erridxlen, m_stat->error_index); + ofs += m_stat->rhl.erridxlen; + + return ofs; +} + +/** + * Encodes trap header from head to tail. + */ +static u16_t +snmp_trap_header_enc(struct snmp_msg_trap *m_trap, struct pbuf *p) +{ + u16_t ofs; + + ofs = 0; + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_trap->thl.seqlen); + ofs += m_trap->thl.seqlenlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_trap->thl.verlen); + ofs += m_trap->thl.verlenlen; + snmp_asn1_enc_s32t(p, ofs, m_trap->thl.verlen, snmp_version); + ofs += m_trap->thl.verlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_trap->thl.comlen); + ofs += m_trap->thl.comlenlen; + snmp_asn1_enc_raw(p, ofs, m_trap->thl.comlen, (u8_t *)&snmp_publiccommunity[0]); + ofs += m_trap->thl.comlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_TRAP)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_trap->thl.pdulen); + ofs += m_trap->thl.pdulenlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_trap->thl.eidlen); + ofs += m_trap->thl.eidlenlen; + snmp_asn1_enc_oid(p, ofs, m_trap->enterprise->len, &m_trap->enterprise->id[0]); + ofs += m_trap->thl.eidlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_trap->thl.aaddrlen); + ofs += m_trap->thl.aaddrlenlen; + snmp_asn1_enc_raw(p, ofs, m_trap->thl.aaddrlen, &m_trap->sip_raw[0]); + ofs += m_trap->thl.aaddrlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_trap->thl.gtrplen); + ofs += m_trap->thl.gtrplenlen; + snmp_asn1_enc_u32t(p, ofs, m_trap->thl.gtrplen, m_trap->gen_trap); + ofs += m_trap->thl.gtrplen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_trap->thl.strplen); + ofs += m_trap->thl.strplenlen; + snmp_asn1_enc_u32t(p, ofs, m_trap->thl.strplen, m_trap->spc_trap); + ofs += m_trap->thl.strplen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_trap->thl.tslen); + ofs += m_trap->thl.tslenlen; + snmp_asn1_enc_u32t(p, ofs, m_trap->thl.tslen, m_trap->ts); + ofs += m_trap->thl.tslen; + + return ofs; +} + +/** + * Encodes varbind list from head to tail. + */ +static u16_t +snmp_varbind_list_enc(struct snmp_varbind_root *root, struct pbuf *p, u16_t ofs) +{ + struct snmp_varbind *vb; + s32_t *sint_ptr; + u32_t *uint_ptr; + u8_t *raw_ptr; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, root->seqlen); + ofs += root->seqlenlen; + + vb = root->head; + while ( vb != NULL ) + { + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, vb->seqlen); + ofs += vb->seqlenlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, vb->olen); + ofs += vb->olenlen; + snmp_asn1_enc_oid(p, ofs, vb->ident_len, &vb->ident[0]); + ofs += vb->olen; + + snmp_asn1_enc_type(p, ofs, vb->value_type); + ofs += 1; + snmp_asn1_enc_length(p, ofs, vb->vlen); + ofs += vb->vlenlen; + + switch (vb->value_type) + { + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG): + sint_ptr = vb->value; + snmp_asn1_enc_s32t(p, ofs, vb->vlen, *sint_ptr); + break; + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS): + uint_ptr = vb->value; + snmp_asn1_enc_u32t(p, ofs, vb->vlen, *uint_ptr); + break; + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_OPAQUE): + raw_ptr = vb->value; + snmp_asn1_enc_raw(p, ofs, vb->vlen, raw_ptr); + break; + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_NUL): + break; + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID): + sint_ptr = vb->value; + snmp_asn1_enc_oid(p, ofs, vb->value_len / sizeof(s32_t), sint_ptr); + break; + default: + /* unsupported type */ + break; + }; + ofs += vb->vlen; + vb = vb->next; + } + return ofs; +} + +#endif /* LWIP_SNMP */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/core/stats.c b/component/common/network/lwip/lwip_v1.3.2/src/core/stats.c new file mode 100644 index 0000000..2ef179d --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/core/stats.c @@ -0,0 +1,149 @@ +/** + * @file + * Statistics module + * + **/ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_STATS /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/stats.h" +#include "lwip/mem.h" + +#include + +struct stats_ lwip_stats; + +#if LWIP_STATS_DISPLAY +void +stats_display_proto(struct stats_proto *proto, char *name) +{ + LWIP_PLATFORM_DIAG("\n\r%s\n\r\t", name); + LWIP_PLATFORM_DIAG("xmit: %"STAT_COUNTER_F"\n\r\t", proto->xmit); + LWIP_PLATFORM_DIAG("recv: %"STAT_COUNTER_F"\n\r\t", proto->recv); + LWIP_PLATFORM_DIAG("fw: %"STAT_COUNTER_F"\n\r\t", proto->fw); + LWIP_PLATFORM_DIAG("drop: %"STAT_COUNTER_F"\n\r\t", proto->drop); + LWIP_PLATFORM_DIAG("chkerr: %"STAT_COUNTER_F"\n\r\t", proto->chkerr); + LWIP_PLATFORM_DIAG("lenerr: %"STAT_COUNTER_F"\n\r\t", proto->lenerr); + LWIP_PLATFORM_DIAG("memerr: %"STAT_COUNTER_F"\n\r\t", proto->memerr); + LWIP_PLATFORM_DIAG("rterr: %"STAT_COUNTER_F"\n\r\t", proto->rterr); + LWIP_PLATFORM_DIAG("proterr: %"STAT_COUNTER_F"\n\r\t", proto->proterr); + LWIP_PLATFORM_DIAG("opterr: %"STAT_COUNTER_F"\n\r\t", proto->opterr); + LWIP_PLATFORM_DIAG("err: %"STAT_COUNTER_F"\n\r\t", proto->err); + LWIP_PLATFORM_DIAG("cachehit: %"STAT_COUNTER_F"\n\r", proto->cachehit); +} + +#if IGMP_STATS +void +stats_display_igmp(struct stats_igmp *igmp) +{ + LWIP_PLATFORM_DIAG("\n\rIGMP\n\r\t")); + LWIP_PLATFORM_DIAG("lenerr: %"STAT_COUNTER_F"\n\r\t", igmp->lenerr); + LWIP_PLATFORM_DIAG("chkerr: %"STAT_COUNTER_F"\n\r\t", igmp->chkerr); + LWIP_PLATFORM_DIAG("v1_rxed: %"STAT_COUNTER_F"\n\r\t", igmp->v1_rxed); + LWIP_PLATFORM_DIAG("join_sent: %"STAT_COUNTER_F"\n\r\t", igmp->join_sent); + LWIP_PLATFORM_DIAG("leave_sent: %"STAT_COUNTER_F"\n\r\t", igmp->leave_sent); + LWIP_PLATFORM_DIAG("unicast_query: %"STAT_COUNTER_F"\n\r\t", igmp->unicast_query); + LWIP_PLATFORM_DIAG("report_sent: %"STAT_COUNTER_F"\n\r\t", igmp->report_sent); + LWIP_PLATFORM_DIAG("report_rxed: %"STAT_COUNTER_F"\n\r\t", igmp->report_rxed); + LWIP_PLATFORM_DIAG("group_query_rxed: %"STAT_COUNTER_F"\n\r", igmp->group_query_rxed); +} +#endif /* IGMP_STATS */ + +#if MEM_STATS || MEMP_STATS +void +stats_display_mem(struct stats_mem *mem, char *name) +{ + LWIP_PLATFORM_DIAG("\n\rMEM %s\n\r\t", name); + LWIP_PLATFORM_DIAG("avail: %"U32_F"\n\r\t", (u32_t)mem->avail); + LWIP_PLATFORM_DIAG("used: %"U32_F"\n\r\t", (u32_t)mem->used); + LWIP_PLATFORM_DIAG("max: %"U32_F"\n\r\t", (u32_t)mem->max); + LWIP_PLATFORM_DIAG("err: %"U32_F"\n\r", (u32_t)mem->err); +} + +#if MEMP_STATS +void +stats_display_memp(struct stats_mem *mem, int index) +{ + char * memp_names[] = { +#define LWIP_MEMPOOL(name,num,size,desc) desc, +#include "lwip/memp_std.h" + }; + if(index < MEMP_MAX) { + stats_display_mem(mem, memp_names[index]); + } +} +#endif /* MEMP_STATS */ +#endif /* MEM_STATS || MEMP_STATS */ + +#if SYS_STATS +void +stats_display_sys(struct stats_sys *sys) +{ + LWIP_PLATFORM_DIAG("\n\rSYS\n\r\t"); + LWIP_PLATFORM_DIAG("sem.used: %"U32_F"\n\r\t", (u32_t)sys->sem.used); + LWIP_PLATFORM_DIAG("sem.max: %"U32_F"\n\r\t", (u32_t)sys->sem.max); + LWIP_PLATFORM_DIAG("sem.err: %"U32_F"\n\r\t", (u32_t)sys->sem.err); + LWIP_PLATFORM_DIAG("mbox.used: %"U32_F"\n\r\t", (u32_t)sys->mbox.used); + LWIP_PLATFORM_DIAG("mbox.max: %"U32_F"\n\r\t", (u32_t)sys->mbox.max); + LWIP_PLATFORM_DIAG("mbox.err: %"U32_F"\n\r\t", (u32_t)sys->mbox.err); +} +#endif /* SYS_STATS */ + +void +stats_display(void) +{ + s16_t i; + + LINK_STATS_DISPLAY(); + ETHARP_STATS_DISPLAY(); + IPFRAG_STATS_DISPLAY(); + IP_STATS_DISPLAY(); + IGMP_STATS_DISPLAY(); + ICMP_STATS_DISPLAY(); + UDP_STATS_DISPLAY(); + TCP_STATS_DISPLAY(); + MEM_STATS_DISPLAY(); + for (i = 0; i < MEMP_MAX; i++) { + MEMP_STATS_DISPLAY(i); + } + SYS_STATS_DISPLAY(); +} +#endif /* LWIP_STATS_DISPLAY */ + +#endif /* LWIP_STATS */ + diff --git a/component/common/network/lwip/lwip_v1.3.2/src/core/sys.c b/component/common/network/lwip/lwip_v1.3.2/src/core/sys.c new file mode 100644 index 0000000..cb5e86a --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/core/sys.c @@ -0,0 +1,346 @@ +/** + * @file + * lwIP Operating System abstraction + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if (NO_SYS == 0) /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/sys.h" +#include "lwip/def.h" +#include "lwip/memp.h" +#include "lwip/tcpip.h" + +/** + * Struct used for sys_sem_wait_timeout() to tell wether the time + * has run out or the semaphore has really become available. + */ +struct sswt_cb +{ + s16_t timeflag; + sys_sem_t *psem; +}; + +/** + * Wait (forever) for a message to arrive in an mbox. + * While waiting, timeouts (for this thread) are processed. + * + * @param mbox the mbox to fetch the message from + * @param msg the place to store the message + */ +void +sys_mbox_fetch(sys_mbox_t mbox, void **msg) +{ + u32_t time_needed; + struct sys_timeouts *timeouts; + struct sys_timeo *tmptimeout; + sys_timeout_handler h; + void *arg; + + again: + timeouts = sys_arch_timeouts(); + + if (!timeouts || !timeouts->next) { + UNLOCK_TCPIP_CORE(); + time_needed = sys_arch_mbox_fetch(mbox, msg, 0); + LOCK_TCPIP_CORE(); + } else { + if (timeouts->next->time > 0) { + UNLOCK_TCPIP_CORE(); + time_needed = sys_arch_mbox_fetch(mbox, msg, timeouts->next->time); + LOCK_TCPIP_CORE(); + } else { + time_needed = SYS_ARCH_TIMEOUT; + } + + if (time_needed == SYS_ARCH_TIMEOUT) { + /* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message + could be fetched. We should now call the timeout handler and + deallocate the memory allocated for the timeout. */ + tmptimeout = timeouts->next; + timeouts->next = tmptimeout->next; + h = tmptimeout->h; + arg = tmptimeout->arg; + memp_free(MEMP_SYS_TIMEOUT, tmptimeout); + if (h != NULL) { + LWIP_DEBUGF(SYS_DEBUG, ("smf calling h=%p(%p)\n", *(void**)&h, arg)); + h(arg); + } + + /* We try again to fetch a message from the mbox. */ + goto again; + } else { + /* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout + occured. The time variable is set to the number of + milliseconds we waited for the message. */ + if (time_needed < timeouts->next->time) { + timeouts->next->time -= time_needed; + } else { + timeouts->next->time = 0; + } + } + } +} + +/** + * Wait (forever) for a semaphore to become available. + * While waiting, timeouts (for this thread) are processed. + * + * @param sem semaphore to wait for + */ +void +sys_sem_wait(sys_sem_t sem) +{ + u32_t time_needed; + struct sys_timeouts *timeouts; + struct sys_timeo *tmptimeout; + sys_timeout_handler h; + void *arg; + + again: + + timeouts = sys_arch_timeouts(); + + if (!timeouts || !timeouts->next) { + sys_arch_sem_wait(sem, 0); + } else { + if (timeouts->next->time > 0) { + time_needed = sys_arch_sem_wait(sem, timeouts->next->time); + } else { + time_needed = SYS_ARCH_TIMEOUT; + } + + if (time_needed == SYS_ARCH_TIMEOUT) { + /* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message + could be fetched. We should now call the timeout handler and + deallocate the memory allocated for the timeout. */ + tmptimeout = timeouts->next; + timeouts->next = tmptimeout->next; + h = tmptimeout->h; + arg = tmptimeout->arg; + memp_free(MEMP_SYS_TIMEOUT, tmptimeout); + if (h != NULL) { + LWIP_DEBUGF(SYS_DEBUG, ("ssw h=%p(%p)\n", *(void**)&h, (void *)arg)); + h(arg); + } + + /* We try again to fetch a message from the mbox. */ + goto again; + } else { + /* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout + occured. The time variable is set to the number of + milliseconds we waited for the message. */ + if (time_needed < timeouts->next->time) { + timeouts->next->time -= time_needed; + } else { + timeouts->next->time = 0; + } + } + } +} + +/** + * Create a one-shot timer (aka timeout). Timeouts are processed in the + * following cases: + * - while waiting for a message using sys_mbox_fetch() + * - while waiting for a semaphore using sys_sem_wait() or sys_sem_wait_timeout() + * - while sleeping using the inbuilt sys_msleep() + * + * @param msecs time in milliseconds after that the timer should expire + * @param h callback function to call when msecs have elapsed + * @param arg argument to pass to the callback function + */ +void +sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg) +{ + struct sys_timeouts *timeouts; + struct sys_timeo *timeout, *t; + + timeout = memp_malloc(MEMP_SYS_TIMEOUT); + if (timeout == NULL) { + LWIP_ASSERT("sys_timeout: timeout != NULL", timeout != NULL); + return; + } + timeout->next = NULL; + timeout->h = h; + timeout->arg = arg; + timeout->time = msecs; + + timeouts = sys_arch_timeouts(); + + LWIP_DEBUGF(SYS_DEBUG, ("sys_timeout: %p msecs=%"U32_F" h=%p arg=%p\n", + (void *)timeout, msecs, *(void**)&h, (void *)arg)); + + if (timeouts == NULL) { + LWIP_ASSERT("sys_timeout: timeouts != NULL", timeouts != NULL); + return; + } + + if (timeouts->next == NULL) { + timeouts->next = timeout; + return; + } + + if (timeouts->next->time > msecs) { + timeouts->next->time -= msecs; + timeout->next = timeouts->next; + timeouts->next = timeout; + } else { + for(t = timeouts->next; t != NULL; t = t->next) { + timeout->time -= t->time; + if (t->next == NULL || t->next->time > timeout->time) { + if (t->next != NULL) { + t->next->time -= timeout->time; + } + timeout->next = t->next; + t->next = timeout; + break; + } + } + } +} + +/** + * Go through timeout list (for this task only) and remove the first matching + * entry, even though the timeout has not triggered yet. + * + * @note This function only works as expected if there is only one timeout + * calling 'h' in the list of timeouts. + * + * @param h callback function that would be called by the timeout + * @param arg callback argument that would be passed to h +*/ +void +sys_untimeout(sys_timeout_handler h, void *arg) +{ + struct sys_timeouts *timeouts; + struct sys_timeo *prev_t, *t; + + timeouts = sys_arch_timeouts(); + + if (timeouts == NULL) { + LWIP_ASSERT("sys_untimeout: timeouts != NULL", timeouts != NULL); + return; + } + if (timeouts->next == NULL) { + return; + } + + for (t = timeouts->next, prev_t = NULL; t != NULL; prev_t = t, t = t->next) { + if ((t->h == h) && (t->arg == arg)) { + /* We have a match */ + /* Unlink from previous in list */ + if (prev_t == NULL) { + timeouts->next = t->next; + } else { + prev_t->next = t->next; + } + /* If not the last one, add time of this one back to next */ + if (t->next != NULL) { + t->next->time += t->time; + } + memp_free(MEMP_SYS_TIMEOUT, t); + return; + } + } + return; +} + +/** + * Timeout handler function for sys_sem_wait_timeout() + * + * @param arg struct sswt_cb* used to signal a semaphore and end waiting. + */ +static void +sswt_handler(void *arg) +{ + struct sswt_cb *sswt_cb = (struct sswt_cb *) arg; + + /* Timeout. Set flag to TRUE and signal semaphore */ + sswt_cb->timeflag = 1; + sys_sem_signal(*(sswt_cb->psem)); +} + +/** + * Wait for a semaphore with timeout (specified in ms) + * + * @param sem semaphore to wait + * @param timeout timeout in ms (0: wait forever) + * @return 0 on timeout, 1 otherwise + */ +int +sys_sem_wait_timeout(sys_sem_t sem, u32_t timeout) +{ + struct sswt_cb sswt_cb; + + sswt_cb.psem = &sem; + sswt_cb.timeflag = 0; + + /* If timeout is zero, then just wait forever */ + if (timeout > 0) { + /* Create a timer and pass it the address of our flag */ + sys_timeout(timeout, sswt_handler, &sswt_cb); + } + sys_sem_wait(sem); + /* Was it a timeout? */ + if (sswt_cb.timeflag) { + /* timeout */ + return 0; + } else { + /* Not a timeout. Remove timeout entry */ + sys_untimeout(sswt_handler, &sswt_cb); + return 1; + } +} + +/** + * Sleep for some ms. Timeouts are processed while sleeping. + * + * @param ms number of milliseconds to sleep + */ +void +sys_msleep(u32_t ms) +{ + sys_sem_t delaysem = sys_sem_new(0); + + sys_sem_wait_timeout(delaysem, ms); + + sys_sem_free(delaysem); +} + + +#endif /* NO_SYS */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/core/tcp.c b/component/common/network/lwip/lwip_v1.3.2/src/core/tcp.c new file mode 100644 index 0000000..81c4432 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/core/tcp.c @@ -0,0 +1,1461 @@ +/** + * @file + * Transmission Control Protocol for IP + * + * This file contains common functions for the TCP implementation, such as functinos + * for manipulating the data structures and the TCP timer functions. TCP functions + * related to input and output is found in tcp_in.c and tcp_out.c respectively. + * + **/ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/snmp.h" +#include "lwip/tcp.h" +#include "lwip/debug.h" +#include "lwip/stats.h" + +#include + +const char *tcp_state_str[] = { + "CLOSED", + "LISTEN", + "SYN_SENT", + "SYN_RCVD", + "ESTABLISHED", + "FIN_WAIT_1", + "FIN_WAIT_2", + "CLOSE_WAIT", + "CLOSING", + "LAST_ACK", + "TIME_WAIT" +}; + +/* Incremented every coarse grained timer shot (typically every 500 ms). */ +u32_t tcp_ticks; +const u8_t tcp_backoff[13] = + { 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7}; + /* Times per slowtmr hits */ +const u8_t tcp_persist_backoff[7] = { 3, 6, 12, 24, 48, 96, 120 }; + +/* The TCP PCB lists. */ + +/** List of all TCP PCBs bound but not yet (connected || listening) */ +struct tcp_pcb *tcp_bound_pcbs; +/** List of all TCP PCBs in LISTEN state */ +union tcp_listen_pcbs_t tcp_listen_pcbs; +/** List of all TCP PCBs that are in a state in which + * they accept or send data. */ +struct tcp_pcb *tcp_active_pcbs; +/** List of all TCP PCBs in TIME-WAIT state */ +struct tcp_pcb *tcp_tw_pcbs; + +struct tcp_pcb *tcp_tmp_pcb; + +static u8_t tcp_timer; +static u16_t tcp_new_port(void); + +/** + * Called periodically to dispatch TCP timers. + * + */ +void +tcp_tmr(void) +{ + /* Call tcp_fasttmr() every 250 ms */ + tcp_fasttmr(); + + if (++tcp_timer & 1) { + /* Call tcp_tmr() every 500 ms, i.e., every other timer + tcp_tmr() is called. */ + tcp_slowtmr(); + } +} + +/** + * Closes the connection held by the PCB. + * + * Listening pcbs are freed and may not be referenced any more. + * Connection pcbs are freed if not yet connected and may not be referenced + * any more. If a connection is established (at least SYN received or in + * a closing state), the connection is closed, and put in a closing state. + * The pcb is then automatically freed in tcp_slowtmr(). It is therefore + * unsafe to reference it. + * + * @param pcb the tcp_pcb to close + * @return ERR_OK if connection has been closed + * another err_t if closing failed and pcb is not freed + */ +err_t +tcp_close(struct tcp_pcb *pcb) +{ + err_t err; + +#if TCP_DEBUG + LWIP_DEBUGF(TCP_DEBUG, ("tcp_close: closing in ")); + tcp_debug_print_state(pcb->state); +#endif /* TCP_DEBUG */ + + switch (pcb->state) { + case CLOSED: + /* Closing a pcb in the CLOSED state might seem erroneous, + * however, it is in this state once allocated and as yet unused + * and the user needs some way to free it should the need arise. + * Calling tcp_close() with a pcb that has already been closed, (i.e. twice) + * or for a pcb that has been used and then entered the CLOSED state + * is erroneous, but this should never happen as the pcb has in those cases + * been freed, and so any remaining handles are bogus. */ + err = ERR_OK; + TCP_RMV(&tcp_bound_pcbs, pcb); + memp_free(MEMP_TCP_PCB, pcb); + pcb = NULL; + break; + case LISTEN: + err = ERR_OK; + tcp_pcb_remove((struct tcp_pcb **)&tcp_listen_pcbs.pcbs, pcb); + memp_free(MEMP_TCP_PCB_LISTEN, pcb); + pcb = NULL; + break; + case SYN_SENT: + err = ERR_OK; + tcp_pcb_remove(&tcp_active_pcbs, pcb); + memp_free(MEMP_TCP_PCB, pcb); + pcb = NULL; + snmp_inc_tcpattemptfails(); + break; + case SYN_RCVD: + err = tcp_send_ctrl(pcb, TCP_FIN); + if (err == ERR_OK) { + snmp_inc_tcpattemptfails(); + pcb->state = FIN_WAIT_1; + } + break; + case ESTABLISHED: + err = tcp_send_ctrl(pcb, TCP_FIN); + if (err == ERR_OK) { + snmp_inc_tcpestabresets(); + pcb->state = FIN_WAIT_1; + } + break; + case CLOSE_WAIT: + err = tcp_send_ctrl(pcb, TCP_FIN); + if (err == ERR_OK) { + snmp_inc_tcpestabresets(); + pcb->state = LAST_ACK; + } + break; + default: + /* Has already been closed, do nothing. */ + err = ERR_OK; + pcb = NULL; + break; + } + + if (pcb != NULL && err == ERR_OK) { + /* To ensure all data has been sent when tcp_close returns, we have + to make sure tcp_output doesn't fail. + Since we don't really have to ensure all data has been sent when tcp_close + returns (unsent data is sent from tcp timer functions, also), we don't care + for the return value of tcp_output for now. */ + /* @todo: When implementing SO_LINGER, this must be changed somehow: + If SOF_LINGER is set, the data should be sent when tcp_close returns. */ + tcp_output(pcb); + } + return err; +} + +/** + * Abandons a connection and optionally sends a RST to the remote + * host. Deletes the local protocol control block. This is done when + * a connection is killed because of shortage of memory. + * + * @param pcb the tcp_pcb to abort + * @param reset boolean to indicate whether a reset should be sent + */ +void +tcp_abandon(struct tcp_pcb *pcb, int reset) +{ + u32_t seqno, ackno; + u16_t remote_port, local_port; + struct ip_addr remote_ip, local_ip; +#if LWIP_CALLBACK_API + void (* errf)(void *arg, err_t err); +#endif /* LWIP_CALLBACK_API */ + void *errf_arg; + + + /* Figure out on which TCP PCB list we are, and remove us. If we + are in an active state, call the receive function associated with + the PCB with a NULL argument, and send an RST to the remote end. */ + if (pcb->state == TIME_WAIT) { + tcp_pcb_remove(&tcp_tw_pcbs, pcb); + memp_free(MEMP_TCP_PCB, pcb); + } else { + seqno = pcb->snd_nxt; + ackno = pcb->rcv_nxt; + ip_addr_set(&local_ip, &(pcb->local_ip)); + ip_addr_set(&remote_ip, &(pcb->remote_ip)); + local_port = pcb->local_port; + remote_port = pcb->remote_port; +#if LWIP_CALLBACK_API + errf = pcb->errf; +#endif /* LWIP_CALLBACK_API */ + errf_arg = pcb->callback_arg; + tcp_pcb_remove(&tcp_active_pcbs, pcb); + if (pcb->unacked != NULL) { + tcp_segs_free(pcb->unacked); + } + if (pcb->unsent != NULL) { + tcp_segs_free(pcb->unsent); + } +#if TCP_QUEUE_OOSEQ + if (pcb->ooseq != NULL) { + tcp_segs_free(pcb->ooseq); + } +#endif /* TCP_QUEUE_OOSEQ */ + memp_free(MEMP_TCP_PCB, pcb); + TCP_EVENT_ERR(errf, errf_arg, ERR_ABRT); + if (reset) { + LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_abandon: sending RST\n")); + tcp_rst(seqno, ackno, &local_ip, &remote_ip, local_port, remote_port); + } + } +} + +/** + * Binds the connection to a local portnumber and IP address. If the + * IP address is not given (i.e., ipaddr == NULL), the IP address of + * the outgoing network interface is used instead. + * + * @param pcb the tcp_pcb to bind (no check is done whether this pcb is + * already bound!) + * @param ipaddr the local ip address to bind to (use IP_ADDR_ANY to bind + * to any local address + * @param port the local port to bind to + * @return ERR_USE if the port is already in use + * ERR_OK if bound + */ +err_t +tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port) +{ + struct tcp_pcb *cpcb; + + LWIP_ERROR("tcp_bind: can only bind in state CLOSED", pcb->state == CLOSED, return ERR_ISCONN); + + if (port == 0) { + port = tcp_new_port(); + } + /* Check if the address already is in use. */ + /* Check the listen pcbs. */ + for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; + cpcb != NULL; cpcb = cpcb->next) { + if (cpcb->local_port == port) { + if (ip_addr_isany(&(cpcb->local_ip)) || + ip_addr_isany(ipaddr) || + ip_addr_cmp(&(cpcb->local_ip), ipaddr)) { + return ERR_USE; + } + } + } + /* Check the connected pcbs. */ + for(cpcb = tcp_active_pcbs; + cpcb != NULL; cpcb = cpcb->next) { + if (cpcb->local_port == port) { + if (ip_addr_isany(&(cpcb->local_ip)) || + ip_addr_isany(ipaddr) || + ip_addr_cmp(&(cpcb->local_ip), ipaddr)) { + return ERR_USE; + } + } + } + /* Check the bound, not yet connected pcbs. */ + for(cpcb = tcp_bound_pcbs; cpcb != NULL; cpcb = cpcb->next) { + if (cpcb->local_port == port) { + if (ip_addr_isany(&(cpcb->local_ip)) || + ip_addr_isany(ipaddr) || + ip_addr_cmp(&(cpcb->local_ip), ipaddr)) { + return ERR_USE; + } + } + } + /* @todo: until SO_REUSEADDR is implemented (see task #6995 on savannah), + * we have to check the pcbs in TIME-WAIT state, also: */ + for(cpcb = tcp_tw_pcbs; cpcb != NULL; cpcb = cpcb->next) { + if (cpcb->local_port == port) { + if (ip_addr_cmp(&(cpcb->local_ip), ipaddr)) { + return ERR_USE; + } + } + } + + if (!ip_addr_isany(ipaddr)) { + pcb->local_ip = *ipaddr; + } + pcb->local_port = port; + TCP_REG(&tcp_bound_pcbs, pcb); + LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: bind to port %"U16_F"\n", port)); + return ERR_OK; +} +#if LWIP_CALLBACK_API +/** + * Default accept callback if no accept callback is specified by the user. + */ +static err_t +tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err) +{ + LWIP_UNUSED_ARG(arg); + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(err); + + return ERR_ABRT; +} +#endif /* LWIP_CALLBACK_API */ + +/** + * Set the state of the connection to be LISTEN, which means that it + * is able to accept incoming connections. The protocol control block + * is reallocated in order to consume less memory. Setting the + * connection to LISTEN is an irreversible process. + * + * @param pcb the original tcp_pcb + * @param backlog the incoming connections queue limit + * @return tcp_pcb used for listening, consumes less memory. + * + * @note The original tcp_pcb is freed. This function therefore has to be + * called like this: + * tpcb = tcp_listen(tpcb); + */ +struct tcp_pcb * +tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog) +{ + struct tcp_pcb_listen *lpcb; + + LWIP_UNUSED_ARG(backlog); + LWIP_ERROR("tcp_listen: pcb already connected", pcb->state == CLOSED, return NULL); + + /* already listening? */ + if (pcb->state == LISTEN) { + return pcb; + } + lpcb = memp_malloc(MEMP_TCP_PCB_LISTEN); + if (lpcb == NULL) { + return NULL; + } + lpcb->callback_arg = pcb->callback_arg; + lpcb->local_port = pcb->local_port; + lpcb->state = LISTEN; + lpcb->so_options = pcb->so_options; + lpcb->so_options |= SOF_ACCEPTCONN; + lpcb->ttl = pcb->ttl; + lpcb->tos = pcb->tos; + ip_addr_set(&lpcb->local_ip, &pcb->local_ip); + TCP_RMV(&tcp_bound_pcbs, pcb); + memp_free(MEMP_TCP_PCB, pcb); +#if LWIP_CALLBACK_API + lpcb->accept = tcp_accept_null; +#endif /* LWIP_CALLBACK_API */ +#if TCP_LISTEN_BACKLOG + lpcb->accepts_pending = 0; + lpcb->backlog = (backlog ? backlog : 1); +#endif /* TCP_LISTEN_BACKLOG */ + TCP_REG(&tcp_listen_pcbs.listen_pcbs, lpcb); + return (struct tcp_pcb *)lpcb; +} + +/** + * Update the state that tracks the available window space to advertise. + * + * Returns how much extra window would be advertised if we sent an + * update now. + */ +u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb) +{ + u32_t new_right_edge = pcb->rcv_nxt + pcb->rcv_wnd; + + if (TCP_SEQ_GEQ(new_right_edge, pcb->rcv_ann_right_edge + LWIP_MIN((TCP_WND / 2), pcb->mss))) { + /* we can advertise more window */ + pcb->rcv_ann_wnd = pcb->rcv_wnd; + return new_right_edge - pcb->rcv_ann_right_edge; + } else { + if (TCP_SEQ_GT(pcb->rcv_nxt, pcb->rcv_ann_right_edge)) { + /* Can happen due to other end sending out of advertised window, + * but within actual available (but not yet advertised) window */ + pcb->rcv_ann_wnd = 0; + } else { + /* keep the right edge of window constant */ + pcb->rcv_ann_wnd = pcb->rcv_ann_right_edge - pcb->rcv_nxt; + } + return 0; + } +} + +/** + * This function should be called by the application when it has + * processed the data. The purpose is to advertise a larger window + * when the data has been processed. + * + * @param pcb the tcp_pcb for which data is read + * @param len the amount of bytes that have been read by the application + */ +void +tcp_recved(struct tcp_pcb *pcb, u16_t len) +{ + int wnd_inflation; + + LWIP_ASSERT("tcp_recved: len would wrap rcv_wnd\n", + len <= 0xffff - pcb->rcv_wnd ); + + pcb->rcv_wnd += len; + if (pcb->rcv_wnd > TCP_WND) + pcb->rcv_wnd = TCP_WND; + + wnd_inflation = tcp_update_rcv_ann_wnd(pcb); + + /* If the change in the right edge of window is significant (default + * watermark is TCP_WND/2), then send an explicit update now. + * Otherwise wait for a packet to be sent in the normal course of + * events (or more window to be available later) */ + if (wnd_inflation >= TCP_WND_UPDATE_THRESHOLD) + tcp_ack_now(pcb); + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_recved: recveived %"U16_F" bytes, wnd %"U16_F" (%"U16_F").\n", + len, pcb->rcv_wnd, TCP_WND - pcb->rcv_wnd)); +} + +/** + * A nastly hack featuring 'goto' statements that allocates a + * new TCP local port. + * + * @return a new (free) local TCP port number + */ +static u16_t +tcp_new_port(void) +{ + struct tcp_pcb *pcb; +#ifndef TCP_LOCAL_PORT_RANGE_START +#define TCP_LOCAL_PORT_RANGE_START 4096 +#define TCP_LOCAL_PORT_RANGE_END 0x7fff +#endif + static u16_t port = TCP_LOCAL_PORT_RANGE_START; + + again: + if (++port > TCP_LOCAL_PORT_RANGE_END) { + port = TCP_LOCAL_PORT_RANGE_START; + } + + for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + if (pcb->local_port == port) { + goto again; + } + } + for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { + if (pcb->local_port == port) { + goto again; + } + } + for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) { + if (pcb->local_port == port) { + goto again; + } + } + return port; +} + +/** + * Connects to another host. The function given as the "connected" + * argument will be called when the connection has been established. + * + * @param pcb the tcp_pcb used to establish the connection + * @param ipaddr the remote ip address to connect to + * @param port the remote tcp port to connect to + * @param connected callback function to call when connected (or on error) + * @return ERR_VAL if invalid arguments are given + * ERR_OK if connect request has been sent + * other err_t values if connect request couldn't be sent + */ +err_t +tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port, + err_t (* connected)(void *arg, struct tcp_pcb *tpcb, err_t err)) +{ + err_t ret; + u32_t iss; + + LWIP_ERROR("tcp_connect: can only connected from state CLOSED", pcb->state == CLOSED, return ERR_ISCONN); + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %"U16_F"\n", port)); + if (ipaddr != NULL) { + pcb->remote_ip = *ipaddr; + } else { + return ERR_VAL; + } + pcb->remote_port = port; + if (pcb->local_port == 0) { + pcb->local_port = tcp_new_port(); + } + iss = tcp_next_iss(); + pcb->rcv_nxt = 0; + pcb->snd_nxt = iss; + pcb->lastack = iss - 1; + pcb->snd_lbb = iss - 1; + pcb->rcv_wnd = TCP_WND; + pcb->rcv_ann_wnd = TCP_WND; + pcb->rcv_ann_right_edge = pcb->rcv_nxt; + pcb->snd_wnd = TCP_WND; + /* As initial send MSS, we use TCP_MSS but limit it to 536. + The send MSS is updated when an MSS option is received. */ + pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS; +#if TCP_CALCULATE_EFF_SEND_MSS + pcb->mss = tcp_eff_send_mss(pcb->mss, ipaddr); +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + pcb->cwnd = 1; + pcb->ssthresh = pcb->mss * 10; + pcb->state = SYN_SENT; +#if LWIP_CALLBACK_API + pcb->connected = connected; +#endif /* LWIP_CALLBACK_API */ + TCP_RMV(&tcp_bound_pcbs, pcb); + TCP_REG(&tcp_active_pcbs, pcb); + + snmp_inc_tcpactiveopens(); + + ret = tcp_enqueue(pcb, NULL, 0, TCP_SYN, 0, TF_SEG_OPTS_MSS +#if LWIP_TCP_TIMESTAMPS + | TF_SEG_OPTS_TS +#endif + ); + if (ret == ERR_OK) { + tcp_output(pcb); + } + return ret; +} + +/** + * Called every 500 ms and implements the retransmission timer and the timer that + * removes PCBs that have been in TIME-WAIT for enough time. It also increments + * various timers such as the inactivity timer in each PCB. + * + * Automatically called from tcp_tmr(). + */ +void +tcp_slowtmr(void) +{ + struct tcp_pcb *pcb, *pcb2, *prev; + u16_t eff_wnd; + u8_t pcb_remove; /* flag if a PCB should be removed */ + u8_t pcb_reset; /* flag if a RST should be sent when removing */ + err_t err; + + err = ERR_OK; + + ++tcp_ticks; + + /* Steps through all of the active PCBs. */ + prev = NULL; + pcb = tcp_active_pcbs; + if (pcb == NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: no active pcbs\n")); + } + while (pcb != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: processing active pcb\n")); + LWIP_ASSERT("tcp_slowtmr: active pcb->state != CLOSED\n", pcb->state != CLOSED); + LWIP_ASSERT("tcp_slowtmr: active pcb->state != LISTEN\n", pcb->state != LISTEN); + LWIP_ASSERT("tcp_slowtmr: active pcb->state != TIME-WAIT\n", pcb->state != TIME_WAIT); + + pcb_remove = 0; + pcb_reset = 0; + + if (pcb->state == SYN_SENT && pcb->nrtx == TCP_SYNMAXRTX) { + ++pcb_remove; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max SYN retries reached\n")); + } + else if (pcb->nrtx == TCP_MAXRTX) { + ++pcb_remove; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max DATA retries reached\n")); + } else { + if (pcb->persist_backoff > 0) { + /* If snd_wnd is zero, use persist timer to send 1 byte probes + * instead of using the standard retransmission mechanism. */ + pcb->persist_cnt++; + if (pcb->persist_cnt >= tcp_persist_backoff[pcb->persist_backoff-1]) { + pcb->persist_cnt = 0; + if (pcb->persist_backoff < sizeof(tcp_persist_backoff)) { + pcb->persist_backoff++; + } + tcp_zero_window_probe(pcb); + } + } else { + /* Increase the retransmission timer if it is running */ + if(pcb->rtime >= 0) + ++pcb->rtime; + + if (pcb->unacked != NULL && pcb->rtime >= pcb->rto) { + /* Time for a retransmission. */ + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_slowtmr: rtime %"S16_F + " pcb->rto %"S16_F"\n", + pcb->rtime, pcb->rto)); + + /* Double retransmission time-out unless we are trying to + * connect to somebody (i.e., we are in SYN_SENT). */ + if (pcb->state != SYN_SENT) { + pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[pcb->nrtx]; + } + + /* Reset the retransmission timer. */ + pcb->rtime = 0; + + /* Reduce congestion window and ssthresh. */ + eff_wnd = LWIP_MIN(pcb->cwnd, pcb->snd_wnd); + pcb->ssthresh = eff_wnd >> 1; + if (pcb->ssthresh < pcb->mss) { + pcb->ssthresh = pcb->mss * 2; + } + pcb->cwnd = pcb->mss; + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %"U16_F + " ssthresh %"U16_F"\n", + pcb->cwnd, pcb->ssthresh)); + + /* The following needs to be called AFTER cwnd is set to one + mss - STJ */ + tcp_rexmit_rto(pcb); + } + } + } + /* Check if this PCB has stayed too long in FIN-WAIT-2 */ + if (pcb->state == FIN_WAIT_2) { + if ((u32_t)(tcp_ticks - pcb->tmr) > + TCP_FIN_WAIT_TIMEOUT / TCP_SLOW_INTERVAL) { + ++pcb_remove; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in FIN-WAIT-2\n")); + } + } + + /* Check if KEEPALIVE should be sent */ + if((pcb->so_options & SOF_KEEPALIVE) && + ((pcb->state == ESTABLISHED) || + (pcb->state == CLOSE_WAIT))) { +#if LWIP_TCP_KEEPALIVE + if((u32_t)(tcp_ticks - pcb->tmr) > + (pcb->keep_idle + (pcb->keep_cnt*pcb->keep_intvl)) + / TCP_SLOW_INTERVAL) +#else + if((u32_t)(tcp_ticks - pcb->tmr) > + (pcb->keep_idle + TCP_MAXIDLE) / TCP_SLOW_INTERVAL) +#endif /* LWIP_TCP_KEEPALIVE */ + { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to %"U16_F".%"U16_F".%"U16_F".%"U16_F".\n", + ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip), + ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip))); + + ++pcb_remove; + ++pcb_reset; + } +#if LWIP_TCP_KEEPALIVE + else if((u32_t)(tcp_ticks - pcb->tmr) > + (pcb->keep_idle + pcb->keep_cnt_sent * pcb->keep_intvl) + / TCP_SLOW_INTERVAL) +#else + else if((u32_t)(tcp_ticks - pcb->tmr) > + (pcb->keep_idle + pcb->keep_cnt_sent * TCP_KEEPINTVL_DEFAULT) + / TCP_SLOW_INTERVAL) +#endif /* LWIP_TCP_KEEPALIVE */ + { + tcp_keepalive(pcb); + pcb->keep_cnt_sent++; + } + } + + /* If this PCB has queued out of sequence data, but has been + inactive for too long, will drop the data (it will eventually + be retransmitted). */ +#if TCP_QUEUE_OOSEQ + if (pcb->ooseq != NULL && + (u32_t)tcp_ticks - pcb->tmr >= pcb->rto * TCP_OOSEQ_TIMEOUT) { + tcp_segs_free(pcb->ooseq); + pcb->ooseq = NULL; + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: dropping OOSEQ queued data\n")); + } +#endif /* TCP_QUEUE_OOSEQ */ + + /* Check if this PCB has stayed too long in SYN-RCVD */ + if (pcb->state == SYN_RCVD) { + if ((u32_t)(tcp_ticks - pcb->tmr) > + TCP_SYN_RCVD_TIMEOUT / TCP_SLOW_INTERVAL) { + ++pcb_remove; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in SYN-RCVD\n")); + } + } + + /* Check if this PCB has stayed too long in LAST-ACK */ + if (pcb->state == LAST_ACK) { + if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) { + ++pcb_remove; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in LAST-ACK\n")); + } + } + + /* If the PCB should be removed, do it. */ + if (pcb_remove) { + tcp_pcb_purge(pcb); + /* Remove PCB from tcp_active_pcbs list. */ + if (prev != NULL) { + LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_active_pcbs", pcb != tcp_active_pcbs); + prev->next = pcb->next; + } else { + /* This PCB was the first. */ + LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_active_pcbs", tcp_active_pcbs == pcb); + tcp_active_pcbs = pcb->next; + } + + TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_ABRT); + if (pcb_reset) { + tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip, + pcb->local_port, pcb->remote_port); + } + + pcb2 = pcb->next; + memp_free(MEMP_TCP_PCB, pcb); + pcb = pcb2; + } else { + + /* We check if we should poll the connection. */ + ++pcb->polltmr; + if (pcb->polltmr >= pcb->pollinterval) { + pcb->polltmr = 0; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: polling application\n")); + TCP_EVENT_POLL(pcb, err); + if (err == ERR_OK) { + tcp_output(pcb); + } + } + + prev = pcb; + pcb = pcb->next; + } + } + + + /* Steps through all of the TIME-WAIT PCBs. */ + prev = NULL; + pcb = tcp_tw_pcbs; + while (pcb != NULL) { + LWIP_ASSERT("tcp_slowtmr: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); + pcb_remove = 0; + + /* Check if this PCB has stayed long enough in TIME-WAIT */ + if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) { + ++pcb_remove; + } + + + + /* If the PCB should be removed, do it. */ + if (pcb_remove) { + tcp_pcb_purge(pcb); + /* Remove PCB from tcp_tw_pcbs list. */ + if (prev != NULL) { + LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_tw_pcbs", pcb != tcp_tw_pcbs); + prev->next = pcb->next; + } else { + /* This PCB was the first. */ + LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_tw_pcbs", tcp_tw_pcbs == pcb); + tcp_tw_pcbs = pcb->next; + } + pcb2 = pcb->next; + memp_free(MEMP_TCP_PCB, pcb); + pcb = pcb2; + } else { + prev = pcb; + pcb = pcb->next; + } + } +} + +/** + * Is called every TCP_FAST_INTERVAL (250 ms) and process data previously + * "refused" by upper layer (application) and sends delayed ACKs. + * + * Automatically called from tcp_tmr(). + */ +void +tcp_fasttmr(void) +{ + struct tcp_pcb *pcb; + + for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + /* If there is data which was previously "refused" by upper layer */ + if (pcb->refused_data != NULL) { + /* Notify again application with data previously received. */ + err_t err; + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_fasttmr: notify kept packet\n")); + TCP_EVENT_RECV(pcb, pcb->refused_data, ERR_OK, err); + if (err == ERR_OK) { + pcb->refused_data = NULL; + } + } + + /* send delayed ACKs */ + if (pcb->flags & TF_ACK_DELAY) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_fasttmr: delayed ACK\n")); + tcp_ack_now(pcb); + pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); + } + } +} + +/** + * Deallocates a list of TCP segments (tcp_seg structures). + * + * @param seg tcp_seg list of TCP segments to free + * @return the number of pbufs that were deallocated + */ +u8_t +tcp_segs_free(struct tcp_seg *seg) +{ + u8_t count = 0; + struct tcp_seg *next; + while (seg != NULL) { + next = seg->next; + count += tcp_seg_free(seg); + seg = next; + } + return count; +} + +/** + * Frees a TCP segment (tcp_seg structure). + * + * @param seg single tcp_seg to free + * @return the number of pbufs that were deallocated + */ +u8_t +tcp_seg_free(struct tcp_seg *seg) +{ + u8_t count = 0; + + if (seg != NULL) { + if (seg->p != NULL) { + count = pbuf_free(seg->p); +#if TCP_DEBUG + seg->p = NULL; +#endif /* TCP_DEBUG */ + } + memp_free(MEMP_TCP_SEG, seg); + } + return count; +} + +/** + * Sets the priority of a connection. + * + * @param pcb the tcp_pcb to manipulate + * @param prio new priority + */ +void +tcp_setprio(struct tcp_pcb *pcb, u8_t prio) +{ + pcb->prio = prio; +} +#if TCP_QUEUE_OOSEQ + +/** + * Returns a copy of the given TCP segment. + * The pbuf and data are not copied, only the pointers + * + * @param seg the old tcp_seg + * @return a copy of seg + */ +struct tcp_seg * +tcp_seg_copy(struct tcp_seg *seg) +{ + struct tcp_seg *cseg; + + cseg = memp_malloc(MEMP_TCP_SEG); + if (cseg == NULL) { + return NULL; + } + SMEMCPY((u8_t *)cseg, (const u8_t *)seg, sizeof(struct tcp_seg)); + pbuf_ref(cseg->p); + return cseg; +} +#endif + +#if LWIP_CALLBACK_API +/** + * Default receive callback that is called if the user didn't register + * a recv callback for the pcb. + */ +err_t +tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) +{ + LWIP_UNUSED_ARG(arg); + if (p != NULL) { + tcp_recved(pcb, p->tot_len); + pbuf_free(p); + } else if (err == ERR_OK) { + return tcp_close(pcb); + } + return ERR_OK; +} +#endif /* LWIP_CALLBACK_API */ + +/** + * Kills the oldest active connection that has lower priority than prio. + * + * @param prio minimum priority + */ +static void +tcp_kill_prio(u8_t prio) +{ + struct tcp_pcb *pcb, *inactive; + u32_t inactivity; + u8_t mprio; + + + mprio = TCP_PRIO_MAX; + + /* We kill the oldest active connection that has lower priority than prio. */ + inactivity = 0; + inactive = NULL; + for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + if (pcb->prio <= prio && + pcb->prio <= mprio && + (u32_t)(tcp_ticks - pcb->tmr) >= inactivity) { + inactivity = tcp_ticks - pcb->tmr; + inactive = pcb; + mprio = pcb->prio; + } + } + if (inactive != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB %p (%"S32_F")\n", + (void *)inactive, inactivity)); + tcp_abort(inactive); + } +} + +/** + * Kills the oldest connection that is in TIME_WAIT state. + * Called from tcp_alloc() if no more connections are available. + */ +static void +tcp_kill_timewait(void) +{ + struct tcp_pcb *pcb, *inactive; + u32_t inactivity; + + inactivity = 0; + inactive = NULL; + /* Go through the list of TIME_WAIT pcbs and get the oldest pcb. */ + for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { + if ((u32_t)(tcp_ticks - pcb->tmr) >= inactivity) { + inactivity = tcp_ticks - pcb->tmr; + inactive = pcb; + } + } + if (inactive != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_timewait: killing oldest TIME-WAIT PCB %p (%"S32_F")\n", + (void *)inactive, inactivity)); + tcp_abort(inactive); + } +} + +/** + * Allocate a new tcp_pcb structure. + * + * @param prio priority for the new pcb + * @return a new tcp_pcb that initially is in state CLOSED + */ +struct tcp_pcb * +tcp_alloc(u8_t prio) +{ + struct tcp_pcb *pcb; + u32_t iss; + + pcb = memp_malloc(MEMP_TCP_PCB); + if (pcb == NULL) { + /* Try killing oldest connection in TIME-WAIT. */ + LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing off oldest TIME-WAIT connection\n")); + tcp_kill_timewait(); + /* Try to allocate a tcp_pcb again. */ + pcb = memp_malloc(MEMP_TCP_PCB); + if (pcb == NULL) { + /* Try killing active connections with lower priority than the new one. */ + LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing connection with prio lower than %d\n", prio)); + tcp_kill_prio(prio); + /* Try to allocate a tcp_pcb again. */ + pcb = memp_malloc(MEMP_TCP_PCB); + if (pcb != NULL) { + /* adjust err stats: memp_malloc failed twice before */ + MEMP_STATS_DEC(err, MEMP_TCP_PCB); + } + } + if (pcb != NULL) { + /* adjust err stats: timewait PCB was freed above */ + MEMP_STATS_DEC(err, MEMP_TCP_PCB); + } + } + if (pcb != NULL) { + memset(pcb, 0, sizeof(struct tcp_pcb)); + pcb->prio = TCP_PRIO_NORMAL; + pcb->snd_buf = TCP_SND_BUF; + pcb->snd_queuelen = 0; + pcb->rcv_wnd = TCP_WND; + pcb->rcv_ann_wnd = TCP_WND; + pcb->tos = 0; + pcb->ttl = TCP_TTL; + /* As initial send MSS, we use TCP_MSS but limit it to 536. + The send MSS is updated when an MSS option is received. */ + pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS; + pcb->rto = 3000 / TCP_SLOW_INTERVAL; + pcb->sa = 0; + pcb->sv = 3000 / TCP_SLOW_INTERVAL; + pcb->rtime = -1; + pcb->cwnd = 1; + iss = tcp_next_iss(); + pcb->snd_wl2 = iss; + pcb->snd_nxt = iss; + pcb->lastack = iss; + pcb->snd_lbb = iss; + pcb->tmr = tcp_ticks; + + pcb->polltmr = 0; + +#if LWIP_CALLBACK_API + pcb->recv = tcp_recv_null; +#endif /* LWIP_CALLBACK_API */ + + /* Init KEEPALIVE timer */ + pcb->keep_idle = TCP_KEEPIDLE_DEFAULT; + +#if LWIP_TCP_KEEPALIVE + pcb->keep_intvl = TCP_KEEPINTVL_DEFAULT; + pcb->keep_cnt = TCP_KEEPCNT_DEFAULT; +#endif /* LWIP_TCP_KEEPALIVE */ + + pcb->keep_cnt_sent = 0; + } + return pcb; +} + +/** + * Creates a new TCP protocol control block but doesn't place it on + * any of the TCP PCB lists. + * The pcb is not put on any list until binding using tcp_bind(). + * + * @internal: Maybe there should be a idle TCP PCB list where these + * PCBs are put on. Port reservation using tcp_bind() is implemented but + * allocated pcbs that are not bound can't be killed automatically if wanting + * to allocate a pcb with higher prio (@see tcp_kill_prio()) + * + * @return a new tcp_pcb that initially is in state CLOSED + */ +struct tcp_pcb * +tcp_new(void) +{ + return tcp_alloc(TCP_PRIO_NORMAL); +} + +/** + * Used to specify the argument that should be passed callback + * functions. + * + * @param pcb tcp_pcb to set the callback argument + * @param arg void pointer argument to pass to callback functions + */ +void +tcp_arg(struct tcp_pcb *pcb, void *arg) +{ + pcb->callback_arg = arg; +} +#if LWIP_CALLBACK_API + +/** + * Used to specify the function that should be called when a TCP + * connection receives data. + * + * @param pcb tcp_pcb to set the recv callback + * @param recv callback function to call for this pcb when data is received + */ +void +tcp_recv(struct tcp_pcb *pcb, + err_t (* recv)(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)) +{ + pcb->recv = recv; +} + +/** + * Used to specify the function that should be called when TCP data + * has been successfully delivered to the remote host. + * + * @param pcb tcp_pcb to set the sent callback + * @param sent callback function to call for this pcb when data is successfully sent + */ +void +tcp_sent(struct tcp_pcb *pcb, + err_t (* sent)(void *arg, struct tcp_pcb *tpcb, u16_t len)) +{ + pcb->sent = sent; +} + +/** + * Used to specify the function that should be called when a fatal error + * has occured on the connection. + * + * @param pcb tcp_pcb to set the err callback + * @param errf callback function to call for this pcb when a fatal error + * has occured on the connection + */ +void +tcp_err(struct tcp_pcb *pcb, + void (* errf)(void *arg, err_t err)) +{ + pcb->errf = errf; +} + +/** + * Used for specifying the function that should be called when a + * LISTENing connection has been connected to another host. + * + * @param pcb tcp_pcb to set the accept callback + * @param accept callback function to call for this pcb when LISTENing + * connection has been connected to another host + */ +void +tcp_accept(struct tcp_pcb *pcb, + err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err)) +{ + pcb->accept = accept; +} +#endif /* LWIP_CALLBACK_API */ + + +/** + * Used to specify the function that should be called periodically + * from TCP. The interval is specified in terms of the TCP coarse + * timer interval, which is called twice a second. + * + */ +void +tcp_poll(struct tcp_pcb *pcb, + err_t (* poll)(void *arg, struct tcp_pcb *tpcb), u8_t interval) +{ +#if LWIP_CALLBACK_API + pcb->poll = poll; +#endif /* LWIP_CALLBACK_API */ + pcb->pollinterval = interval; +} + +/** + * Purges a TCP PCB. Removes any buffered data and frees the buffer memory + * (pcb->ooseq, pcb->unsent and pcb->unacked are freed). + * + * @param pcb tcp_pcb to purge. The pcb itself is not deallocated! + */ +void +tcp_pcb_purge(struct tcp_pcb *pcb) +{ + if (pcb->state != CLOSED && + pcb->state != TIME_WAIT && + pcb->state != LISTEN) { + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge\n")); + +#if TCP_LISTEN_BACKLOG + if (pcb->state == SYN_RCVD) { + /* Need to find the corresponding listen_pcb and decrease its accepts_pending */ + struct tcp_pcb_listen *lpcb; + LWIP_ASSERT("tcp_pcb_purge: pcb->state == SYN_RCVD but tcp_listen_pcbs is NULL", + tcp_listen_pcbs.listen_pcbs != NULL); + for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { + if ((lpcb->local_port == pcb->local_port) && + (ip_addr_isany(&lpcb->local_ip) || + ip_addr_cmp(&pcb->local_ip, &lpcb->local_ip))) { + /* port and address of the listen pcb match the timed-out pcb */ + LWIP_ASSERT("tcp_pcb_purge: listen pcb does not have accepts pending", + lpcb->accepts_pending > 0); + lpcb->accepts_pending--; + break; + } + } + } +#endif /* TCP_LISTEN_BACKLOG */ + + + if (pcb->refused_data != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->refused_data\n")); + pbuf_free(pcb->refused_data); + pcb->refused_data = NULL; + } + if (pcb->unsent != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: not all data sent\n")); + } + if (pcb->unacked != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->unacked\n")); + } +#if TCP_QUEUE_OOSEQ /* LW */ + if (pcb->ooseq != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->ooseq\n")); + } + + /* Stop the retransmission timer as it will expect data on unacked + queue if it fires */ + pcb->rtime = -1; + + tcp_segs_free(pcb->ooseq); + pcb->ooseq = NULL; +#endif /* TCP_QUEUE_OOSEQ */ + tcp_segs_free(pcb->unsent); + tcp_segs_free(pcb->unacked); + pcb->unacked = pcb->unsent = NULL; + } +} + +/** + * Purges the PCB and removes it from a PCB list. Any delayed ACKs are sent first. + * + * @param pcblist PCB list to purge. + * @param pcb tcp_pcb to purge. The pcb itself is NOT deallocated! + */ +void +tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb) +{ + TCP_RMV(pcblist, pcb); + + tcp_pcb_purge(pcb); + + /* if there is an outstanding delayed ACKs, send it */ + if (pcb->state != TIME_WAIT && + pcb->state != LISTEN && + pcb->flags & TF_ACK_DELAY) { + pcb->flags |= TF_ACK_NOW; + tcp_output(pcb); + } + + if (pcb->state != LISTEN) { + LWIP_ASSERT("unsent segments leaking", pcb->unsent == NULL); + LWIP_ASSERT("unacked segments leaking", pcb->unacked == NULL); +#if TCP_QUEUE_OOSEQ + LWIP_ASSERT("ooseq segments leaking", pcb->ooseq == NULL); +#endif /* TCP_QUEUE_OOSEQ */ + } + + pcb->state = CLOSED; + + LWIP_ASSERT("tcp_pcb_remove: tcp_pcbs_sane()", tcp_pcbs_sane()); +} + +/** + * Calculates a new initial sequence number for new connections. + * + * @return u32_t pseudo random sequence number + */ +u32_t +tcp_next_iss(void) +{ + static u32_t iss = 6510; + + iss += tcp_ticks; /* XXX */ + return iss; +} + +#if TCP_CALCULATE_EFF_SEND_MSS +/** + * Calcluates the effective send mss that can be used for a specific IP address + * by using ip_route to determin the netif used to send to the address and + * calculating the minimum of TCP_MSS and that netif's mtu (if set). + */ +u16_t +tcp_eff_send_mss(u16_t sendmss, struct ip_addr *addr) +{ + u16_t mss_s; + struct netif *outif; + + outif = ip_route(addr); + if ((outif != NULL) && (outif->mtu != 0)) { + mss_s = outif->mtu - IP_HLEN - TCP_HLEN; + /* RFC 1122, chap 4.2.2.6: + * Eff.snd.MSS = min(SendMSS+20, MMS_S) - TCPhdrsize - IPoptionsize + * We correct for TCP options in tcp_enqueue(), and don't support + * IP options + */ + sendmss = LWIP_MIN(sendmss, mss_s); + } + return sendmss; +} +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + +const char* +tcp_debug_state_str(enum tcp_state s) +{ + return tcp_state_str[s]; +} + +#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG +/** + * Print a tcp header for debugging purposes. + * + * @param tcphdr pointer to a struct tcp_hdr + */ +void +tcp_debug_print(struct tcp_hdr *tcphdr) +{ + LWIP_DEBUGF(TCP_DEBUG, ("TCP header:\n")); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(TCP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n", + ntohs(tcphdr->src), ntohs(tcphdr->dest))); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (seq no)\n", + ntohl(tcphdr->seqno))); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (ack no)\n", + ntohl(tcphdr->ackno))); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(TCP_DEBUG, ("| %2"U16_F" | |%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"| %5"U16_F" | (hdrlen, flags (", + TCPH_HDRLEN(tcphdr), + TCPH_FLAGS(tcphdr) >> 5 & 1, + TCPH_FLAGS(tcphdr) >> 4 & 1, + TCPH_FLAGS(tcphdr) >> 3 & 1, + TCPH_FLAGS(tcphdr) >> 2 & 1, + TCPH_FLAGS(tcphdr) >> 1 & 1, + TCPH_FLAGS(tcphdr) & 1, + ntohs(tcphdr->wnd))); + tcp_debug_print_flags(TCPH_FLAGS(tcphdr)); + LWIP_DEBUGF(TCP_DEBUG, ("), win)\n")); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(TCP_DEBUG, ("| 0x%04"X16_F" | %5"U16_F" | (chksum, urgp)\n", + ntohs(tcphdr->chksum), ntohs(tcphdr->urgp))); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); +} + +/** + * Print a tcp state for debugging purposes. + * + * @param s enum tcp_state to print + */ +void +tcp_debug_print_state(enum tcp_state s) +{ + LWIP_DEBUGF(TCP_DEBUG, ("State: %s\n", tcp_state_str[s])); +} + +/** + * Print tcp flags for debugging purposes. + * + * @param flags tcp flags, all active flags are printed + */ +void +tcp_debug_print_flags(u8_t flags) +{ + if (flags & TCP_FIN) { + LWIP_DEBUGF(TCP_DEBUG, ("FIN ")); + } + if (flags & TCP_SYN) { + LWIP_DEBUGF(TCP_DEBUG, ("SYN ")); + } + if (flags & TCP_RST) { + LWIP_DEBUGF(TCP_DEBUG, ("RST ")); + } + if (flags & TCP_PSH) { + LWIP_DEBUGF(TCP_DEBUG, ("PSH ")); + } + if (flags & TCP_ACK) { + LWIP_DEBUGF(TCP_DEBUG, ("ACK ")); + } + if (flags & TCP_URG) { + LWIP_DEBUGF(TCP_DEBUG, ("URG ")); + } + if (flags & TCP_ECE) { + LWIP_DEBUGF(TCP_DEBUG, ("ECE ")); + } + if (flags & TCP_CWR) { + LWIP_DEBUGF(TCP_DEBUG, ("CWR ")); + } + LWIP_DEBUGF(TCP_DEBUG, ("\n")); +} + +/** + * Print all tcp_pcbs in every list for debugging purposes. + */ +void +tcp_debug_print_pcbs(void) +{ + struct tcp_pcb *pcb; + LWIP_DEBUGF(TCP_DEBUG, ("Active PCB states:\n")); + for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", + pcb->local_port, pcb->remote_port, + pcb->snd_nxt, pcb->rcv_nxt)); + tcp_debug_print_state(pcb->state); + } + LWIP_DEBUGF(TCP_DEBUG, ("Listen PCB states:\n")); + for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", + pcb->local_port, pcb->remote_port, + pcb->snd_nxt, pcb->rcv_nxt)); + tcp_debug_print_state(pcb->state); + } + LWIP_DEBUGF(TCP_DEBUG, ("TIME-WAIT PCB states:\n")); + for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", + pcb->local_port, pcb->remote_port, + pcb->snd_nxt, pcb->rcv_nxt)); + tcp_debug_print_state(pcb->state); + } +} + +/** + * Check state consistency of the tcp_pcb lists. + */ +s16_t +tcp_pcbs_sane(void) +{ + struct tcp_pcb *pcb; + for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != CLOSED", pcb->state != CLOSED); + LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != LISTEN", pcb->state != LISTEN); + LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT); + } + for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_ASSERT("tcp_pcbs_sane: tw pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); + } + return 1; +} +#endif /* TCP_DEBUG */ + +#endif /* LWIP_TCP */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/core/tcp_in.c b/component/common/network/lwip/lwip_v1.3.2/src/core/tcp_in.c new file mode 100644 index 0000000..9c79898 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/core/tcp_in.c @@ -0,0 +1,1506 @@ +/** + * @file + * Transmission Control Protocol, incoming traffic + * + * The input processing functions of the TCP layer. + * + * These functions are generally called in the order (ip_input() ->) + * tcp_input() -> * tcp_process() -> tcp_receive() (-> application). + * + **/ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/tcp.h" +#include "lwip/def.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/inet.h" +#include "lwip/inet_chksum.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "arch/perf.h" + +/* These variables are global to all functions involved in the input + processing of TCP segments. They are set by the tcp_input() + function. */ +static struct tcp_seg inseg; +static struct tcp_hdr *tcphdr; +static struct ip_hdr *iphdr; +static u32_t seqno, ackno; +static u8_t flags; +static u16_t tcplen; + +static u8_t recv_flags; +static struct pbuf *recv_data; + +struct tcp_pcb *tcp_input_pcb; + +/* Forward declarations. */ +static err_t tcp_process(struct tcp_pcb *pcb); +static void tcp_receive(struct tcp_pcb *pcb); +static void tcp_parseopt(struct tcp_pcb *pcb); + +static err_t tcp_listen_input(struct tcp_pcb_listen *pcb); +static err_t tcp_timewait_input(struct tcp_pcb *pcb); + +/** + * The initial input processing of TCP. It verifies the TCP header, demultiplexes + * the segment between the PCBs and passes it on to tcp_process(), which implements + * the TCP finite state machine. This function is called by the IP layer (in + * ip_input()). + * + * @param p received TCP segment to process (p->payload pointing to the IP header) + * @param inp network interface on which this segment was received + */ +void +tcp_input(struct pbuf *p, struct netif *inp) +{ + struct tcp_pcb *pcb, *prev; + struct tcp_pcb_listen *lpcb; + u8_t hdrlen; + err_t err; + + PERF_START; + + TCP_STATS_INC(tcp.recv); + snmp_inc_tcpinsegs(); + + iphdr = p->payload; + tcphdr = (struct tcp_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4); + +#if TCP_INPUT_DEBUG + tcp_debug_print(tcphdr); +#endif + + /* remove header from payload */ + if (pbuf_header(p, -((s16_t)(IPH_HL(iphdr) * 4))) || (p->tot_len < sizeof(struct tcp_hdr))) { + /* drop short packets */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%"U16_F" bytes) discarded\n", p->tot_len)); + TCP_STATS_INC(tcp.lenerr); + TCP_STATS_INC(tcp.drop); + snmp_inc_tcpinerrs(); + pbuf_free(p); + return; + } + + /* Don't even process incoming broadcasts/multicasts. */ + if (ip_addr_isbroadcast(&(iphdr->dest), inp) || + ip_addr_ismulticast(&(iphdr->dest))) { + TCP_STATS_INC(tcp.proterr); + TCP_STATS_INC(tcp.drop); + snmp_inc_tcpinerrs(); + pbuf_free(p); + return; + } + +#if CHECKSUM_CHECK_TCP + /* Verify TCP checksum. */ + if (inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src), + (struct ip_addr *)&(iphdr->dest), + IP_PROTO_TCP, p->tot_len) != 0) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04"X16_F"\n", + inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src), (struct ip_addr *)&(iphdr->dest), + IP_PROTO_TCP, p->tot_len))); +#if TCP_DEBUG + tcp_debug_print(tcphdr); +#endif /* TCP_DEBUG */ + TCP_STATS_INC(tcp.chkerr); + TCP_STATS_INC(tcp.drop); + snmp_inc_tcpinerrs(); + pbuf_free(p); + return; + } +#endif + + /* Move the payload pointer in the pbuf so that it points to the + TCP data instead of the TCP header. */ + hdrlen = TCPH_HDRLEN(tcphdr); + if(pbuf_header(p, -(hdrlen * 4))){ + /* drop short packets */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet\n")); + TCP_STATS_INC(tcp.lenerr); + TCP_STATS_INC(tcp.drop); + snmp_inc_tcpinerrs(); + pbuf_free(p); + return; + } + + /* Convert fields in TCP header to host byte order. */ + tcphdr->src = ntohs(tcphdr->src); + tcphdr->dest = ntohs(tcphdr->dest); + seqno = tcphdr->seqno = ntohl(tcphdr->seqno); + ackno = tcphdr->ackno = ntohl(tcphdr->ackno); + tcphdr->wnd = ntohs(tcphdr->wnd); + + flags = TCPH_FLAGS(tcphdr); + tcplen = p->tot_len + ((flags & (TCP_FIN | TCP_SYN)) ? 1 : 0); + + /* Demultiplex an incoming segment. First, we check if it is destined + for an active connection. */ + prev = NULL; + + + for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED); + LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT); + LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN); + if (pcb->remote_port == tcphdr->src && + pcb->local_port == tcphdr->dest && + ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) && + ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) { + + /* Move this PCB to the front of the list so that subsequent + lookups will be faster (we exploit locality in TCP segment + arrivals). */ + LWIP_ASSERT("tcp_input: pcb->next != pcb (before cache)", pcb->next != pcb); + if (prev != NULL) { + prev->next = pcb->next; + pcb->next = tcp_active_pcbs; + tcp_active_pcbs = pcb; + } + LWIP_ASSERT("tcp_input: pcb->next != pcb (after cache)", pcb->next != pcb); + break; + } + prev = pcb; + } + + if (pcb == NULL) { + /* If it did not go to an active connection, we check the connections + in the TIME-WAIT state. */ + for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); + if (pcb->remote_port == tcphdr->src && + pcb->local_port == tcphdr->dest && + ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) && + ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) { + /* We don't really care enough to move this PCB to the front + of the list since we are not very likely to receive that + many segments for connections in TIME-WAIT. */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for TIME_WAITing connection.\n")); + tcp_timewait_input(pcb); + pbuf_free(p); + return; + } + } + + /* Finally, if we still did not get a match, we check all PCBs that + are LISTENing for incoming connections. */ + prev = NULL; + for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { + if ((ip_addr_isany(&(lpcb->local_ip)) || + ip_addr_cmp(&(lpcb->local_ip), &(iphdr->dest))) && + lpcb->local_port == tcphdr->dest) { + /* Move this PCB to the front of the list so that subsequent + lookups will be faster (we exploit locality in TCP segment + arrivals). */ + if (prev != NULL) { + ((struct tcp_pcb_listen *)prev)->next = lpcb->next; + /* our successor is the remainder of the listening list */ + lpcb->next = tcp_listen_pcbs.listen_pcbs; + /* put this listening pcb at the head of the listening list */ + tcp_listen_pcbs.listen_pcbs = lpcb; + } + + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n")); + tcp_listen_input(lpcb); + pbuf_free(p); + return; + } + prev = (struct tcp_pcb *)lpcb; + } + } + +#if TCP_INPUT_DEBUG + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("+-+-+-+-+-+-+-+-+-+-+-+-+-+- tcp_input: flags ")); + tcp_debug_print_flags(TCPH_FLAGS(tcphdr)); + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n")); +#endif /* TCP_INPUT_DEBUG */ + + + if (pcb != NULL) { + /* The incoming segment belongs to a connection. */ +#if TCP_INPUT_DEBUG +#if TCP_DEBUG + tcp_debug_print_state(pcb->state); +#endif /* TCP_DEBUG */ +#endif /* TCP_INPUT_DEBUG */ + + /* Set up a tcp_seg structure. */ + inseg.next = NULL; + inseg.len = p->tot_len; + inseg.dataptr = p->payload; + inseg.p = p; + inseg.tcphdr = tcphdr; + + recv_data = NULL; + recv_flags = 0; + + /* If there is data which was previously "refused" by upper layer */ + if (pcb->refused_data != NULL) { + /* Notify again application with data previously received. */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: notify kept packet\n")); + TCP_EVENT_RECV(pcb, pcb->refused_data, ERR_OK, err); + if (err == ERR_OK) { + pcb->refused_data = NULL; + } else { + /* drop incoming packets, because pcb is "full" */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: drop incoming packets, because pcb is \"full\"\n")); + TCP_STATS_INC(tcp.drop); + snmp_inc_tcpinerrs(); + pbuf_free(p); + return; + } + } + tcp_input_pcb = pcb; + err = tcp_process(pcb); + /* A return value of ERR_ABRT means that tcp_abort() was called + and that the pcb has been freed. If so, we don't do anything. */ + if (err != ERR_ABRT) { + if (recv_flags & TF_RESET) { + /* TF_RESET means that the connection was reset by the other + end. We then call the error callback to inform the + application that the connection is dead before we + deallocate the PCB. */ + TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_RST); + tcp_pcb_remove(&tcp_active_pcbs, pcb); + memp_free(MEMP_TCP_PCB, pcb); + } else if (recv_flags & TF_CLOSED) { + /* The connection has been closed and we will deallocate the + PCB. */ + tcp_pcb_remove(&tcp_active_pcbs, pcb); + memp_free(MEMP_TCP_PCB, pcb); + } else { + err = ERR_OK; + /* If the application has registered a "sent" function to be + called when new send buffer space is available, we call it + now. */ + if (pcb->acked > 0) { + TCP_EVENT_SENT(pcb, pcb->acked, err); + } + + if (recv_data != NULL) { + if(flags & TCP_PSH) { + recv_data->flags |= PBUF_FLAG_PUSH; + } + + /* Notify application that data has been received. */ + TCP_EVENT_RECV(pcb, recv_data, ERR_OK, err); + + /* If the upper layer can't receive this data, store it */ + if (err != ERR_OK) { + pcb->refused_data = recv_data; + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: keep incoming packet, because pcb is \"full\"\n")); + } + } + + /* If a FIN segment was received, we call the callback + function with a NULL buffer to indicate EOF. */ + if (recv_flags & TF_GOT_FIN) { + TCP_EVENT_RECV(pcb, NULL, ERR_OK, err); + } + + tcp_input_pcb = NULL; + /* Try to send something out. */ + tcp_output(pcb); +#if TCP_INPUT_DEBUG +#if TCP_DEBUG + tcp_debug_print_state(pcb->state); +#endif /* TCP_DEBUG */ +#endif /* TCP_INPUT_DEBUG */ + } + } + tcp_input_pcb = NULL; + + + /* give up our reference to inseg.p */ + if (inseg.p != NULL) + { + pbuf_free(inseg.p); + inseg.p = NULL; + } + } else { + + /* If no matching PCB was found, send a TCP RST (reset) to the + sender. */ + LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n")); + if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) { + TCP_STATS_INC(tcp.proterr); + TCP_STATS_INC(tcp.drop); + tcp_rst(ackno, seqno + tcplen, + &(iphdr->dest), &(iphdr->src), + tcphdr->dest, tcphdr->src); + } + pbuf_free(p); + } + + LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane()); + PERF_STOP("tcp_input"); +} + +/** + * Called by tcp_input() when a segment arrives for a listening + * connection (from tcp_input()). + * + * @param pcb the tcp_pcb_listen for which a segment arrived + * @return ERR_OK if the segment was processed + * another err_t on error + * + * @note the return value is not (yet?) used in tcp_input() + * @note the segment which arrived is saved in global variables, therefore only the pcb + * involved is passed as a parameter to this function + */ +static err_t +tcp_listen_input(struct tcp_pcb_listen *pcb) +{ + struct tcp_pcb *npcb; + err_t rc; + + /* In the LISTEN state, we check for incoming SYN segments, + creates a new PCB, and responds with a SYN|ACK. */ + if (flags & TCP_ACK) { + /* For incoming segments with the ACK flag set, respond with a + RST. */ + LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n")); + tcp_rst(ackno + 1, seqno + tcplen, + &(iphdr->dest), &(iphdr->src), + tcphdr->dest, tcphdr->src); + } else if (flags & TCP_SYN) { + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest)); +#if TCP_LISTEN_BACKLOG + if (pcb->accepts_pending >= pcb->backlog) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: listen backlog exceeded for port %"U16_F"\n", tcphdr->dest)); + return ERR_ABRT; + } +#endif /* TCP_LISTEN_BACKLOG */ + npcb = tcp_alloc(pcb->prio); + /* If a new PCB could not be created (probably due to lack of memory), + we don't do anything, but rely on the sender will retransmit the + SYN at a time when we have more memory available. */ + if (npcb == NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n")); + TCP_STATS_INC(tcp.memerr); + return ERR_MEM; + } +#if TCP_LISTEN_BACKLOG + pcb->accepts_pending++; +#endif /* TCP_LISTEN_BACKLOG */ + /* Set up the new PCB. */ + ip_addr_set(&(npcb->local_ip), &(iphdr->dest)); + npcb->local_port = pcb->local_port; + ip_addr_set(&(npcb->remote_ip), &(iphdr->src)); + npcb->remote_port = tcphdr->src; + npcb->state = SYN_RCVD; + npcb->rcv_nxt = seqno + 1; + npcb->rcv_ann_right_edge = npcb->rcv_nxt; + npcb->snd_wnd = tcphdr->wnd; + npcb->ssthresh = npcb->snd_wnd; + npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */ + npcb->callback_arg = pcb->callback_arg; +#if LWIP_CALLBACK_API + npcb->accept = pcb->accept; +#endif /* LWIP_CALLBACK_API */ + /* inherit socket options */ + npcb->so_options = pcb->so_options & (SOF_DEBUG|SOF_DONTROUTE|SOF_KEEPALIVE|SOF_OOBINLINE|SOF_LINGER); + /* Register the new PCB so that we can begin receiving segments + for it. */ + TCP_REG(&tcp_active_pcbs, npcb); + + /* Parse any options in the SYN. */ + tcp_parseopt(npcb); +#if TCP_CALCULATE_EFF_SEND_MSS + npcb->mss = tcp_eff_send_mss(npcb->mss, &(npcb->remote_ip)); +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + + snmp_inc_tcppassiveopens(); + + /* Send a SYN|ACK together with the MSS option. */ + rc = tcp_enqueue(npcb, NULL, 0, TCP_SYN | TCP_ACK, 0, TF_SEG_OPTS_MSS +#if LWIP_TCP_TIMESTAMPS + /* and maybe include the TIMESTAMP option */ + | (npcb->flags & TF_TIMESTAMP ? TF_SEG_OPTS_TS : 0) +#endif + ); + if (rc != ERR_OK) { + tcp_abandon(npcb, 0); + return rc; + } + return tcp_output(npcb); + } + return ERR_OK; +} + +/** + * Called by tcp_input() when a segment arrives for a connection in + * TIME_WAIT. + * + * @param pcb the tcp_pcb for which a segment arrived + * + * @note the segment which arrived is saved in global variables, therefore only the pcb + * involved is passed as a parameter to this function + */ +static err_t +tcp_timewait_input(struct tcp_pcb *pcb) +{ + /* RFC 1337: in TIME_WAIT, ignore RST and ACK FINs + any 'acceptable' segments */ + /* RFC 793 3.9 Event Processing - Segment Arrives: + * - first check sequence number - we skip that one in TIME_WAIT (always + * acceptable since we only send ACKs) + * - second check the RST bit (... return) */ + if (flags & TCP_RST) { + return ERR_OK; + } + /* - fourth, check the SYN bit, */ + if (flags & TCP_SYN) { + /* If an incoming segment is not acceptable, an acknowledgment + should be sent in reply */ + if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt+pcb->rcv_wnd)) { + /* If the SYN is in the window it is an error, send a reset */ + tcp_rst(ackno, seqno + tcplen, &(iphdr->dest), &(iphdr->src), + tcphdr->dest, tcphdr->src); + return ERR_OK; + } + } else if (flags & TCP_FIN) { + /* - eighth, check the FIN bit: Remain in the TIME-WAIT state. + Restart the 2 MSL time-wait timeout.*/ + pcb->tmr = tcp_ticks; + } + + if ((tcplen > 0)) { + /* Acknowledge data, FIN or out-of-window SYN */ + pcb->flags |= TF_ACK_NOW; + return tcp_output(pcb); + } + return ERR_OK; +} + +/** + * Implements the TCP state machine. Called by tcp_input. In some + * states tcp_receive() is called to receive data. The tcp_seg + * argument will be freed by the caller (tcp_input()) unless the + * recv_data pointer in the pcb is set. + * + * @param pcb the tcp_pcb for which a segment arrived + * + * @note the segment which arrived is saved in global variables, therefore only the pcb + * involved is passed as a parameter to this function + */ +static err_t +tcp_process(struct tcp_pcb *pcb) +{ + struct tcp_seg *rseg; + u8_t acceptable = 0; + err_t err; + + err = ERR_OK; + + /* Process incoming RST segments. */ + if (flags & TCP_RST) { + /* First, determine if the reset is acceptable. */ + if (pcb->state == SYN_SENT) { + if (ackno == pcb->snd_nxt) { + acceptable = 1; + } + } else { + if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, + pcb->rcv_nxt+pcb->rcv_wnd)) { + acceptable = 1; + } + } + + if (acceptable) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: Connection RESET\n")); + LWIP_ASSERT("tcp_input: pcb->state != CLOSED", pcb->state != CLOSED); + recv_flags |= TF_RESET; + pcb->flags &= ~TF_ACK_DELAY; + return ERR_RST; + } else { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n", + seqno, pcb->rcv_nxt)); + LWIP_DEBUGF(TCP_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n", + seqno, pcb->rcv_nxt)); + return ERR_OK; + } + } + + if ((flags & TCP_SYN) && (pcb->state != SYN_SENT && pcb->state != SYN_RCVD)) { + /* Cope with new connection attempt after remote end crashed */ + tcp_ack_now(pcb); + return ERR_OK; + } + + /* Update the PCB (in)activity timer. */ + pcb->tmr = tcp_ticks; + pcb->keep_cnt_sent = 0; + + tcp_parseopt(pcb); + + /* Do different things depending on the TCP state. */ + switch (pcb->state) { + case SYN_SENT: + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %"U32_F" pcb->snd_nxt %"U32_F" unacked %"U32_F"\n", ackno, + pcb->snd_nxt, ntohl(pcb->unacked->tcphdr->seqno))); + /* received SYN ACK with expected sequence number? */ + if ((flags & TCP_ACK) && (flags & TCP_SYN) + && ackno == ntohl(pcb->unacked->tcphdr->seqno) + 1) { + pcb->snd_buf++; + pcb->rcv_nxt = seqno + 1; + pcb->rcv_ann_right_edge = pcb->rcv_nxt; + pcb->lastack = ackno; + pcb->snd_wnd = tcphdr->wnd; + pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */ + pcb->state = ESTABLISHED; + +#if TCP_CALCULATE_EFF_SEND_MSS + pcb->mss = tcp_eff_send_mss(pcb->mss, &(pcb->remote_ip)); +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + + /* Set ssthresh again after changing pcb->mss (already set in tcp_connect + * but for the default value of pcb->mss) */ + pcb->ssthresh = pcb->mss * 10; + + pcb->cwnd = ((pcb->cwnd == 1) ? (pcb->mss * 2) : pcb->mss); + LWIP_ASSERT("pcb->snd_queuelen > 0", (pcb->snd_queuelen > 0)); + --pcb->snd_queuelen; + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %"U16_F"\n", (u16_t)pcb->snd_queuelen)); + rseg = pcb->unacked; + pcb->unacked = rseg->next; + + /* If there's nothing left to acknowledge, stop the retransmit + timer, otherwise reset it to start again */ + if(pcb->unacked == NULL) + pcb->rtime = -1; + else { + pcb->rtime = 0; + pcb->nrtx = 0; + } + + tcp_seg_free(rseg); + + /* Call the user specified function to call when sucessfully + * connected. */ + TCP_EVENT_CONNECTED(pcb, ERR_OK, err); + tcp_ack_now(pcb); + } + /* received ACK? possibly a half-open connection */ + else if (flags & TCP_ACK) { + /* send a RST to bring the other side in a non-synchronized state. */ + tcp_rst(ackno, seqno + tcplen, &(iphdr->dest), &(iphdr->src), + tcphdr->dest, tcphdr->src); + } + break; + case SYN_RCVD: + if (flags & TCP_ACK) { + /* expected ACK number? */ + if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) { + u16_t old_cwnd; + pcb->state = ESTABLISHED; + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); +#if LWIP_CALLBACK_API + LWIP_ASSERT("pcb->accept != NULL", pcb->accept != NULL); +#endif + /* Call the accept function. */ + TCP_EVENT_ACCEPT(pcb, ERR_OK, err); + if (err != ERR_OK) { + /* If the accept function returns with an error, we abort + * the connection. */ + tcp_abort(pcb); + return ERR_ABRT; + } + old_cwnd = pcb->cwnd; + /* If there was any data contained within this ACK, + * we'd better pass it on to the application as well. */ + tcp_receive(pcb); + + /* Prevent ACK for SYN to generate a sent event */ + if (pcb->acked != 0) { + pcb->acked--; + } + + pcb->cwnd = ((old_cwnd == 1) ? (pcb->mss * 2) : pcb->mss); + + if (recv_flags & TF_GOT_FIN) { + tcp_ack_now(pcb); + pcb->state = CLOSE_WAIT; + } + } + /* incorrect ACK number */ + else { + /* send RST */ + tcp_rst(ackno, seqno + tcplen, &(iphdr->dest), &(iphdr->src), + tcphdr->dest, tcphdr->src); + } + } else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) { + /* Looks like another copy of the SYN - retransmit our SYN-ACK */ + tcp_rexmit(pcb); + } + break; + case CLOSE_WAIT: + /* FALLTHROUGH */ + case ESTABLISHED: + tcp_receive(pcb); + if (recv_flags & TF_GOT_FIN) { /* passive close */ + tcp_ack_now(pcb); + pcb->state = CLOSE_WAIT; + } + break; + case FIN_WAIT_1: + tcp_receive(pcb); + if (recv_flags & TF_GOT_FIN) { + if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) { + LWIP_DEBUGF(TCP_DEBUG, + ("TCP connection closed: FIN_WAIT_1 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); + tcp_ack_now(pcb); + tcp_pcb_purge(pcb); + TCP_RMV(&tcp_active_pcbs, pcb); + pcb->state = TIME_WAIT; + TCP_REG(&tcp_tw_pcbs, pcb); + } else { + tcp_ack_now(pcb); + pcb->state = CLOSING; + } + } else if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) { + pcb->state = FIN_WAIT_2; + } + break; + case FIN_WAIT_2: + tcp_receive(pcb); + if (recv_flags & TF_GOT_FIN) { + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: FIN_WAIT_2 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); + tcp_ack_now(pcb); + tcp_pcb_purge(pcb); + TCP_RMV(&tcp_active_pcbs, pcb); + pcb->state = TIME_WAIT; + TCP_REG(&tcp_tw_pcbs, pcb); + } + break; + case CLOSING: + tcp_receive(pcb); + if (flags & TCP_ACK && ackno == pcb->snd_nxt) { + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: CLOSING %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); + tcp_pcb_purge(pcb); + TCP_RMV(&tcp_active_pcbs, pcb); + pcb->state = TIME_WAIT; + TCP_REG(&tcp_tw_pcbs, pcb); + } + break; + case LAST_ACK: + tcp_receive(pcb); + if (flags & TCP_ACK && ackno == pcb->snd_nxt) { + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: LAST_ACK %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); + /* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */ + recv_flags |= TF_CLOSED; + } + break; + default: + break; + } + return ERR_OK; +} + +#if TCP_QUEUE_OOSEQ +/** + * Insert segment into the list (segments covered with new one will be deleted) + * + * Called from tcp_receive() + */ +static void +tcp_oos_insert_segment(struct tcp_seg *cseg, struct tcp_seg *next) +{ + struct tcp_seg *old_seg; + + if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) { + /* received segment overlaps all following segments */ + tcp_segs_free(next); + next = NULL; + } + else { + /* delete some following segments + oos queue may have segments with FIN flag */ + while (next && + TCP_SEQ_GEQ((seqno + cseg->len), + (next->tcphdr->seqno + next->len))) { + /* cseg with FIN already processed */ + if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) { + TCPH_FLAGS_SET(cseg->tcphdr, TCPH_FLAGS(cseg->tcphdr) | TCP_FIN); + } + old_seg = next; + next = next->next; + tcp_seg_free(old_seg); + } + if (next && + TCP_SEQ_GT(seqno + cseg->len, next->tcphdr->seqno)) { + /* We need to trim the incoming segment. */ + cseg->len = (u16_t)(next->tcphdr->seqno - seqno); + pbuf_realloc(cseg->p, cseg->len); + } + } + cseg->next = next; +} +#endif + +/** + * Called by tcp_process. Checks if the given segment is an ACK for outstanding + * data, and if so frees the memory of the buffered data. Next, is places the + * segment on any of the receive queues (pcb->recved or pcb->ooseq). If the segment + * is buffered, the pbuf is referenced by pbuf_ref so that it will not be freed until + * i it has been removed from the buffer. + * + * If the incoming segment constitutes an ACK for a segment that was used for RTT + * estimation, the RTT is estimated here as well. + * + * Called from tcp_process(). + */ +static void +tcp_receive(struct tcp_pcb *pcb) +{ + struct tcp_seg *next; +#if TCP_QUEUE_OOSEQ + struct tcp_seg *prev, *cseg; +#endif + struct pbuf *p; + s32_t off; + s16_t m; + u32_t right_wnd_edge; + u16_t new_tot_len; + int found_dupack = 0; + + if (flags & TCP_ACK) { + right_wnd_edge = pcb->snd_wnd + pcb->snd_wl2; + + /* Update window. */ + if (TCP_SEQ_LT(pcb->snd_wl1, seqno) || + (pcb->snd_wl1 == seqno && TCP_SEQ_LT(pcb->snd_wl2, ackno)) || + (pcb->snd_wl2 == ackno && tcphdr->wnd > pcb->snd_wnd)) { + pcb->snd_wnd = tcphdr->wnd; + pcb->snd_wl1 = seqno; + pcb->snd_wl2 = ackno; + if (pcb->snd_wnd > 0 && pcb->persist_backoff > 0) { + pcb->persist_backoff = 0; + } + LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: window update %"U16_F"\n", pcb->snd_wnd)); +#if TCP_WND_DEBUG + } else { + if (pcb->snd_wnd != tcphdr->wnd) { + LWIP_DEBUGF(TCP_WND_DEBUG, + ("tcp_receive: no window update lastack %"U32_F" ackno %" + U32_F" wl1 %"U32_F" seqno %"U32_F" wl2 %"U32_F"\n", + pcb->lastack, ackno, pcb->snd_wl1, seqno, pcb->snd_wl2)); + } +#endif /* TCP_WND_DEBUG */ + } + + /* (From Stevens TCP/IP Illustrated Vol II, p970.) Its only a + * duplicate ack if: + * 1) It doesn't ACK new data + * 2) length of received packet is zero (i.e. no payload) + * 3) the advertised window hasn't changed + * 4) There is outstanding unacknowledged data (retransmission timer running) + * 5) The ACK is == biggest ACK sequence number so far seen (snd_una) + * + * If it passes all five, should process as a dupack: + * a) dupacks < 3: do nothing + * b) dupacks == 3: fast retransmit + * c) dupacks > 3: increase cwnd + * + * If it only passes 1-3, should reset dupack counter (and add to + * stats, which we don't do in lwIP) + * + * If it only passes 1, should reset dupack counter + * + */ + + /* Clause 1 */ + if (TCP_SEQ_LEQ(ackno, pcb->lastack)) { + pcb->acked = 0; + /* Clause 2 */ + if (tcplen == 0) { + /* Clause 3 */ + if (pcb->snd_wl2 + pcb->snd_wnd == right_wnd_edge){ + /* Clause 4 */ + if (pcb->rtime >= 0) { + /* Clause 5 */ + if (pcb->lastack == ackno) { + found_dupack = 1; + if (pcb->dupacks + 1 > pcb->dupacks) + ++pcb->dupacks; + if (pcb->dupacks > 3) { + /* Inflate the congestion window, but not if it means that + the value overflows. */ + if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { + pcb->cwnd += pcb->mss; + } + } else if (pcb->dupacks == 3) { + /* Do fast retransmit */ + tcp_rexmit_fast(pcb); + } + } + } + } + } + /* If Clause (1) or more is true, but not a duplicate ack, reset + * count of consecutive duplicate acks */ + if (!found_dupack) { + pcb->dupacks = 0; + } + } else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)){ + /* We come here when the ACK acknowledges new data. */ + + /* Reset the "IN Fast Retransmit" flag, since we are no longer + in fast retransmit. Also reset the congestion window to the + slow start threshold. */ + if (pcb->flags & TF_INFR) { + pcb->flags &= ~TF_INFR; + pcb->cwnd = pcb->ssthresh; + } + + /* Reset the number of retransmissions. */ + pcb->nrtx = 0; + + /* Reset the retransmission time-out. */ + pcb->rto = (pcb->sa >> 3) + pcb->sv; + + /* Update the send buffer space. Diff between the two can never exceed 64K? */ + pcb->acked = (u16_t)(ackno - pcb->lastack); + + pcb->snd_buf += pcb->acked; + + /* Reset the fast retransmit variables. */ + pcb->dupacks = 0; + pcb->lastack = ackno; + + /* Update the congestion control variables (cwnd and + ssthresh). */ + if (pcb->state >= ESTABLISHED) { + if (pcb->cwnd < pcb->ssthresh) { + if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { + pcb->cwnd += pcb->mss; + } + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: slow start cwnd %"U16_F"\n", pcb->cwnd)); + } else { + u16_t new_cwnd = (pcb->cwnd + pcb->mss * pcb->mss / pcb->cwnd); + if (new_cwnd > pcb->cwnd) { + pcb->cwnd = new_cwnd; + } + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %"U16_F"\n", pcb->cwnd)); + } + } + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %"U32_F", unacked->seqno %"U32_F":%"U32_F"\n", + ackno, + pcb->unacked != NULL? + ntohl(pcb->unacked->tcphdr->seqno): 0, + pcb->unacked != NULL? + ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0)); + + /* Remove segment from the unacknowledged list if the incoming + ACK acknowlegdes them. */ + while (pcb->unacked != NULL && + TCP_SEQ_LEQ(ntohl(pcb->unacked->tcphdr->seqno) + + TCP_TCPLEN(pcb->unacked), ackno)) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unacked\n", + ntohl(pcb->unacked->tcphdr->seqno), + ntohl(pcb->unacked->tcphdr->seqno) + + TCP_TCPLEN(pcb->unacked))); + + next = pcb->unacked; + pcb->unacked = pcb->unacked->next; + + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen)); + LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p))); + /* Prevent ACK for FIN to generate a sent event */ + if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) { + pcb->acked--; + } + + pcb->snd_queuelen -= pbuf_clen(next->p); + tcp_seg_free(next); + + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unacked)\n", (u16_t)pcb->snd_queuelen)); + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL || + pcb->unsent != NULL); + } + } + + /* If there's nothing left to acknowledge, stop the retransmit + timer, otherwise reset it to start again */ + if(pcb->unacked == NULL) + pcb->rtime = -1; + else + pcb->rtime = 0; + + pcb->polltmr = 0; + } else { + /* Fix bug bug #21582: out of sequence ACK, didn't really ack anything */ + pcb->acked = 0; + } + + /* We go through the ->unsent list to see if any of the segments + on the list are acknowledged by the ACK. This may seem + strange since an "unsent" segment shouldn't be acked. The + rationale is that lwIP puts all outstanding segments on the + ->unsent list after a retransmission, so these segments may + in fact have been sent once. */ + while (pcb->unsent != NULL && + TCP_SEQ_BETWEEN(ackno, ntohl(pcb->unsent->tcphdr->seqno) + + TCP_TCPLEN(pcb->unsent), pcb->snd_nxt)) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unsent\n", + ntohl(pcb->unsent->tcphdr->seqno), ntohl(pcb->unsent->tcphdr->seqno) + + TCP_TCPLEN(pcb->unsent))); + + next = pcb->unsent; + pcb->unsent = pcb->unsent->next; + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen)); + LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p))); + /* Prevent ACK for FIN to generate a sent event */ + if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) { + pcb->acked--; + } + pcb->snd_queuelen -= pbuf_clen(next->p); + tcp_seg_free(next); + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unsent)\n", (u16_t)pcb->snd_queuelen)); + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_receive: valid queue length", + pcb->unacked != NULL || pcb->unsent != NULL); + } + } + /* End of ACK for new data processing. */ + + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %"U32_F" rtseq %"U32_F" ackno %"U32_F"\n", + pcb->rttest, pcb->rtseq, ackno)); + + /* RTT estimation calculations. This is done by checking if the + incoming segment acknowledges the segment we use to take a + round-trip time measurement. */ + if (pcb->rttest && TCP_SEQ_LT(pcb->rtseq, ackno)) { + /* diff between this shouldn't exceed 32K since this are tcp timer ticks + and a round-trip shouldn't be that long... */ + m = (s16_t)(tcp_ticks - pcb->rttest); + + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: experienced rtt %"U16_F" ticks (%"U16_F" msec).\n", + m, m * TCP_SLOW_INTERVAL)); + + /* This is taken directly from VJs original code in his paper */ + m = m - (pcb->sa >> 3); + pcb->sa += m; + if (m < 0) { + m = -m; + } + m = m - (pcb->sv >> 2); + pcb->sv += m; + pcb->rto = (pcb->sa >> 3) + pcb->sv; + + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: RTO %"U16_F" (%"U16_F" milliseconds)\n", + pcb->rto, pcb->rto * TCP_SLOW_INTERVAL)); + + pcb->rttest = 0; + } + } + + /* If the incoming segment contains data, we must process it + further. */ + if (tcplen > 0) { + /* This code basically does three things: + + +) If the incoming segment contains data that is the next + in-sequence data, this data is passed to the application. This + might involve trimming the first edge of the data. The rcv_nxt + variable and the advertised window are adjusted. + + +) If the incoming segment has data that is above the next + sequence number expected (->rcv_nxt), the segment is placed on + the ->ooseq queue. This is done by finding the appropriate + place in the ->ooseq queue (which is ordered by sequence + number) and trim the segment in both ends if needed. An + immediate ACK is sent to indicate that we received an + out-of-sequence segment. + + +) Finally, we check if the first segment on the ->ooseq queue + now is in sequence (i.e., if rcv_nxt >= ooseq->seqno). If + rcv_nxt > ooseq->seqno, we must trim the first edge of the + segment on ->ooseq before we adjust rcv_nxt. The data in the + segments that are now on sequence are chained onto the + incoming segment so that we only need to call the application + once. + */ + + /* First, we check if we must trim the first edge. We have to do + this if the sequence number of the incoming segment is less + than rcv_nxt, and the sequence number plus the length of the + segment is larger than rcv_nxt. */ + /* if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){ + if (TCP_SEQ_LT(pcb->rcv_nxt, seqno + tcplen)) {*/ + if (TCP_SEQ_BETWEEN(pcb->rcv_nxt, seqno + 1, seqno + tcplen - 1)){ + /* Trimming the first edge is done by pushing the payload + pointer in the pbuf downwards. This is somewhat tricky since + we do not want to discard the full contents of the pbuf up to + the new starting point of the data since we have to keep the + TCP header which is present in the first pbuf in the chain. + + What is done is really quite a nasty hack: the first pbuf in + the pbuf chain is pointed to by inseg.p. Since we need to be + able to deallocate the whole pbuf, we cannot change this + inseg.p pointer to point to any of the later pbufs in the + chain. Instead, we point the ->payload pointer in the first + pbuf to data in one of the later pbufs. We also set the + inseg.data pointer to point to the right place. This way, the + ->p pointer will still point to the first pbuf, but the + ->p->payload pointer will point to data in another pbuf. + + After we are done with adjusting the pbuf pointers we must + adjust the ->data pointer in the seg and the segment + length.*/ + + off = pcb->rcv_nxt - seqno; + p = inseg.p; + LWIP_ASSERT("inseg.p != NULL", inseg.p); + LWIP_ASSERT("insane offset!", (off < 0x7fff)); + if (inseg.p->len < off) { + LWIP_ASSERT("pbuf too short!", (((s32_t)inseg.p->tot_len) >= off)); + new_tot_len = (u16_t)(inseg.p->tot_len - off); + while (p->len < off) { + off -= p->len; + /* KJM following line changed (with addition of new_tot_len var) + to fix bug #9076 + inseg.p->tot_len -= p->len; */ + p->tot_len = new_tot_len; + p->len = 0; + p = p->next; + } + if(pbuf_header(p, (s16_t)-off)) { + /* Do we need to cope with this failing? Assert for now */ + LWIP_ASSERT("pbuf_header failed", 0); + } + } else { + if(pbuf_header(inseg.p, (s16_t)-off)) { + /* Do we need to cope with this failing? Assert for now */ + LWIP_ASSERT("pbuf_header failed", 0); + } + } + /* KJM following line changed to use p->payload rather than inseg->p->payload + to fix bug #9076 */ + inseg.dataptr = p->payload; + inseg.len -= (u16_t)(pcb->rcv_nxt - seqno); + inseg.tcphdr->seqno = seqno = pcb->rcv_nxt; + } + else { + if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){ + /* the whole segment is < rcv_nxt */ + /* must be a duplicate of a packet that has already been correctly handled */ + + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %"U32_F"\n", seqno)); + tcp_ack_now(pcb); + } + } + + /* The sequence number must be within the window (above rcv_nxt + and below rcv_nxt + rcv_wnd) in order to be further + processed. */ + if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, + pcb->rcv_nxt + pcb->rcv_wnd - 1)){ + if (pcb->rcv_nxt == seqno) { + /* The incoming segment is the next in sequence. We check if + we have to trim the end of the segment and update rcv_nxt + and pass the data to the application. */ + tcplen = TCP_TCPLEN(&inseg); + + if (tcplen > pcb->rcv_wnd) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, + ("tcp_receive: other end overran receive window" + "seqno %"U32_F" len %"U32_F" right edge %"U32_F"\n", + seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd)); + if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { + /* Must remove the FIN from the header as we're trimming + * that byte of sequence-space from the packet */ + TCPH_FLAGS_SET(inseg.tcphdr, TCPH_FLAGS(inseg.tcphdr) &~ TCP_FIN); + } + /* Adjust length of segment to fit in the window. */ + inseg.len = pcb->rcv_wnd; + if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) { + inseg.len -= 1; + } + pbuf_realloc(inseg.p, inseg.len); + tcplen = TCP_TCPLEN(&inseg); + LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n", + (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd)); + } +#if TCP_QUEUE_OOSEQ + if (pcb->ooseq != NULL) { + if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, + ("tcp_receive: received in-order FIN, binning ooseq queue\n")); + /* Received in-order FIN means anything that was received + * out of order must now have been received in-order, so + * bin the ooseq queue + * rcv_nxt + * . |--ooseq--| + * .==seg============|FIN + */ + while (pcb->ooseq != NULL) { + struct tcp_seg *old_ooseq = pcb->ooseq; + pcb->ooseq = pcb->ooseq->next; + tcp_seg_free(old_ooseq); + } + } + else { + struct tcp_seg* next = pcb->ooseq; + struct tcp_seg *old_seg; + /* rcv_nxt + * . |--ooseq--| + * .==seg============| + */ + while (next && + TCP_SEQ_GEQ(seqno + tcplen, + next->tcphdr->seqno + next->len)) { + /* inseg doesn't have FIN (already processed) */ + if (TCPH_FLAGS(next->tcphdr) & TCP_FIN && + (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) == 0) { + TCPH_FLAGS_SET(inseg.tcphdr, + TCPH_FLAGS(inseg.tcphdr) | TCP_FIN); + tcplen = TCP_TCPLEN(&inseg); + } + old_seg = next; + next = next->next; + tcp_seg_free(old_seg); + } + /* rcv_nxt + * . |--ooseq--| + * .==seg============| + */ + if (next && + TCP_SEQ_GT(seqno + tcplen, + next->tcphdr->seqno)) { + /* FIN in inseg already handled by dropping whole ooseq queue */ + inseg.len = (u16_t)(pcb->ooseq->tcphdr->seqno - seqno); + if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) { + inseg.len -= 1; + } + pbuf_realloc(inseg.p, inseg.len); + tcplen = TCP_TCPLEN(&inseg); + LWIP_ASSERT("tcp_receive: segment not trimmed correctly to ooseq queue\n", + (seqno + tcplen) == pcb->ooseq->tcphdr->seqno); + } + pcb->ooseq = next; + } + } +#endif /* TCP_QUEUE_OOSEQ */ + + pcb->rcv_nxt = seqno + tcplen; + + /* Update the receiver's (our) window. */ + LWIP_ASSERT("tcp_receive: tcplen > rcv_wnd\n", pcb->rcv_wnd >= tcplen); + pcb->rcv_wnd -= tcplen; + + tcp_update_rcv_ann_wnd(pcb); + + /* If there is data in the segment, we make preparations to + pass this up to the application. The ->recv_data variable + is used for holding the pbuf that goes to the + application. The code for reassembling out-of-sequence data + chains its data on this pbuf as well. + + If the segment was a FIN, we set the TF_GOT_FIN flag that will + be used to indicate to the application that the remote side has + closed its end of the connection. */ + if (inseg.p->tot_len > 0) { + recv_data = inseg.p; + /* Since this pbuf now is the responsibility of the + application, we delete our reference to it so that we won't + (mistakingly) deallocate it. */ + inseg.p = NULL; + } + if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN.\n")); + recv_flags |= TF_GOT_FIN; + } + +#if TCP_QUEUE_OOSEQ + /* We now check if we have segments on the ->ooseq queue that + is now in sequence. */ + while (pcb->ooseq != NULL && + pcb->ooseq->tcphdr->seqno == pcb->rcv_nxt) { + + cseg = pcb->ooseq; + seqno = pcb->ooseq->tcphdr->seqno; + + pcb->rcv_nxt += TCP_TCPLEN(cseg); + LWIP_ASSERT("tcp_receive: ooseq tcplen > rcv_wnd\n", + pcb->rcv_wnd >= TCP_TCPLEN(cseg)); + pcb->rcv_wnd -= TCP_TCPLEN(cseg); + + tcp_update_rcv_ann_wnd(pcb); + + if (cseg->p->tot_len > 0) { + /* Chain this pbuf onto the pbuf that we will pass to + the application. */ + if (recv_data) { + pbuf_cat(recv_data, cseg->p); + } else { + recv_data = cseg->p; + } + cseg->p = NULL; + } + if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n")); + recv_flags |= TF_GOT_FIN; + if (pcb->state == ESTABLISHED) { /* force passive close or we can move to active close */ + pcb->state = CLOSE_WAIT; + } + } + + pcb->ooseq = cseg->next; + tcp_seg_free(cseg); + } +#endif /* TCP_QUEUE_OOSEQ */ + + + /* Acknowledge the segment(s). */ + tcp_ack(pcb); + + } else { + /* We get here if the incoming segment is out-of-sequence. */ + tcp_send_empty_ack(pcb); +#if TCP_QUEUE_OOSEQ + /* We queue the segment on the ->ooseq queue. */ + if (pcb->ooseq == NULL) { + pcb->ooseq = tcp_seg_copy(&inseg); + } else { + /* If the queue is not empty, we walk through the queue and + try to find a place where the sequence number of the + incoming segment is between the sequence numbers of the + previous and the next segment on the ->ooseq queue. That is + the place where we put the incoming segment. If needed, we + trim the second edges of the previous and the incoming + segment so that it will fit into the sequence. + + If the incoming segment has the same sequence number as a + segment on the ->ooseq queue, we discard the segment that + contains less data. */ + + prev = NULL; + for(next = pcb->ooseq; next != NULL; next = next->next) { + if (seqno == next->tcphdr->seqno) { + /* The sequence number of the incoming segment is the + same as the sequence number of the segment on + ->ooseq. We check the lengths to see which one to + discard. */ + if (inseg.len > next->len) { + /* The incoming segment is larger than the old + segment. We replace some segments with the new + one. */ + cseg = tcp_seg_copy(&inseg); + if (cseg != NULL) { + if (prev != NULL) { + prev->next = cseg; + } else { + pcb->ooseq = cseg; + } + tcp_oos_insert_segment(cseg, next); + } + break; + } else { + /* Either the lenghts are the same or the incoming + segment was smaller than the old one; in either + case, we ditch the incoming segment. */ + break; + } + } else { + if (prev == NULL) { + if (TCP_SEQ_LT(seqno, next->tcphdr->seqno)) { + /* The sequence number of the incoming segment is lower + than the sequence number of the first segment on the + queue. We put the incoming segment first on the + queue. */ + cseg = tcp_seg_copy(&inseg); + if (cseg != NULL) { + pcb->ooseq = cseg; + tcp_oos_insert_segment(cseg, next); + } + break; + } + } else { + /*if (TCP_SEQ_LT(prev->tcphdr->seqno, seqno) && + TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {*/ + if (TCP_SEQ_BETWEEN(seqno, prev->tcphdr->seqno+1, next->tcphdr->seqno-1)) { + /* The sequence number of the incoming segment is in + between the sequence numbers of the previous and + the next segment on ->ooseq. We trim trim the previous + segment, delete next segments that included in received segment + and trim received, if needed. */ + cseg = tcp_seg_copy(&inseg); + if (cseg != NULL) { + if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) { + /* We need to trim the prev segment. */ + prev->len = (u16_t)(seqno - prev->tcphdr->seqno); + pbuf_realloc(prev->p, prev->len); + } + prev->next = cseg; + tcp_oos_insert_segment(cseg, next); + } + break; + } + } + /* If the "next" segment is the last segment on the + ooseq queue, we add the incoming segment to the end + of the list. */ + if (next->next == NULL && + TCP_SEQ_GT(seqno, next->tcphdr->seqno)) { + if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) { + /* segment "next" already contains all data */ + break; + } + next->next = tcp_seg_copy(&inseg); + if (next->next != NULL) { + if (TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) { + /* We need to trim the last segment. */ + next->len = (u16_t)(seqno - next->tcphdr->seqno); + pbuf_realloc(next->p, next->len); + } + } + break; + } + } + prev = next; + } + } +#endif /* TCP_QUEUE_OOSEQ */ + + } + } else { + /* The incoming segment is not withing the window. */ + tcp_send_empty_ack(pcb); + } + } else { + /* Segments with length 0 is taken care of here. Segments that + fall out of the window are ACKed. */ + /*if (TCP_SEQ_GT(pcb->rcv_nxt, seqno) || + TCP_SEQ_GEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/ + if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd-1)){ + tcp_ack_now(pcb); + } + } +} + +/** + * Parses the options contained in the incoming segment. + * + * Called from tcp_listen_input() and tcp_process(). + * Currently, only the MSS option is supported! + * + * @param pcb the tcp_pcb for which a segment arrived + */ +static void +tcp_parseopt(struct tcp_pcb *pcb) +{ + u16_t c, max_c; + u16_t mss; + u8_t *opts, opt; +#if LWIP_TCP_TIMESTAMPS + u32_t tsval; +#endif + + opts = (u8_t *)tcphdr + TCP_HLEN; + + /* Parse the TCP MSS option, if present. */ + if(TCPH_HDRLEN(tcphdr) > 0x5) { + max_c = (TCPH_HDRLEN(tcphdr) - 5) << 2; + for (c = 0; c < max_c; ) { + opt = opts[c]; + switch (opt) { + case 0x00: + /* End of options. */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: EOL\n")); + return; + case 0x01: + /* NOP option. */ + ++c; + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: NOP\n")); + break; + case 0x02: + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: MSS\n")); + if (opts[c + 1] != 0x04 || c + 0x04 > max_c) { + /* Bad length */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); + return; + } + /* An MSS option with the right option length. */ + mss = (opts[c + 2] << 8) | opts[c + 3]; + /* Limit the mss to the configured TCP_MSS and prevent division by zero */ + pcb->mss = ((mss > TCP_MSS) || (mss == 0)) ? TCP_MSS : mss; + /* Advance to next option */ + c += 0x04; + break; +#if LWIP_TCP_TIMESTAMPS + case 0x08: + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: TS\n")); + if (opts[c + 1] != 0x0A || c + 0x0A > max_c) { + /* Bad length */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); + return; + } + /* TCP timestamp option with valid length */ + tsval = (opts[c+2]) | (opts[c+3] << 8) | + (opts[c+4] << 16) | (opts[c+5] << 24); + if (flags & TCP_SYN) { + pcb->ts_recent = ntohl(tsval); + pcb->flags |= TF_TIMESTAMP; + } else if (TCP_SEQ_BETWEEN(pcb->ts_lastacksent, seqno, seqno+tcplen)) { + pcb->ts_recent = ntohl(tsval); + } + /* Advance to next option */ + c += 0x0A; + break; +#endif + default: + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: other\n")); + if (opts[c + 1] == 0) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); + /* If the length field is zero, the options are malformed + and we don't process them further. */ + return; + } + /* All other options have a length field, so that we easily + can skip past them. */ + c += opts[c + 1]; + } + } + } +} + +#endif /* LWIP_TCP */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/core/tcp_out.c b/component/common/network/lwip/lwip_v1.3.2/src/core/tcp_out.c new file mode 100644 index 0000000..ebff525 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/core/tcp_out.c @@ -0,0 +1,1054 @@ +/** + * @file + * Transmission Control Protocol, outgoing traffic + * + * The output functions of TCP. + * + **/ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/tcp.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/sys.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/inet.h" +#include "lwip/inet_chksum.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" + +#include + +/* Forward declarations.*/ +static void tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb); + +static struct tcp_hdr * +tcp_output_set_header(struct tcp_pcb *pcb, struct pbuf *p, int optlen, + u32_t seqno_be /* already in network byte order */) +{ + struct tcp_hdr *tcphdr = p->payload; + tcphdr->src = htons(pcb->local_port); + tcphdr->dest = htons(pcb->remote_port); + tcphdr->seqno = seqno_be; + tcphdr->ackno = htonl(pcb->rcv_nxt); + TCPH_FLAGS_SET(tcphdr, TCP_ACK); + tcphdr->wnd = htons(pcb->rcv_ann_wnd); + tcphdr->urgp = 0; + TCPH_HDRLEN_SET(tcphdr, (5 + optlen / 4)); + tcphdr->chksum = 0; + + /* If we're sending a packet, update the announced right window edge */ + pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd; + + return tcphdr; +} + +/** + * Called by tcp_close() to send a segment including flags but not data. + * + * @param pcb the tcp_pcb over which to send a segment + * @param flags the flags to set in the segment header + * @return ERR_OK if sent, another err_t otherwise + */ +err_t +tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags) +{ + /* no data, no length, flags, copy=1, no optdata */ + return tcp_enqueue(pcb, NULL, 0, flags, TCP_WRITE_FLAG_COPY, 0); +} + +/** + * Write data for sending (but does not send it immediately). + * + * It waits in the expectation of more data being sent soon (as + * it can send them more efficiently by combining them together). + * To prompt the system to send data now, call tcp_output() after + * calling tcp_write(). + * + * @param pcb Protocol control block of the TCP connection to enqueue data for. + * @param data pointer to the data to send + * @param len length (in bytes) of the data to send + * @param apiflags combination of following flags : + * - TCP_WRITE_FLAG_COPY (0x01) data will be copied into memory belonging to the stack + * - TCP_WRITE_FLAG_MORE (0x02) for TCP connection, PSH flag will be set on last segment sent, + * @return ERR_OK if enqueued, another err_t on error + * + * @see tcp_write() + */ +err_t +tcp_write(struct tcp_pcb *pcb, const void *data, u16_t len, u8_t apiflags) +{ + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, data=%p, len=%"U16_F", apiflags=%"U16_F")\n", (void *)pcb, + data, len, (u16_t)apiflags)); + /* connection is in valid state for data transmission? */ + if (pcb->state == ESTABLISHED || + pcb->state == CLOSE_WAIT || + pcb->state == SYN_SENT || + pcb->state == SYN_RCVD) { + if (len > 0) { +#if LWIP_TCP_TIMESTAMPS + return tcp_enqueue(pcb, (void *)data, len, 0, apiflags, + pcb->flags & TF_TIMESTAMP ? TF_SEG_OPTS_TS : 0); +#else + return tcp_enqueue(pcb, (void *)data, len, 0, apiflags, 0); +#endif + } + return ERR_OK; + } else { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_STATE | LWIP_DBG_LEVEL_SEVERE, ("tcp_write() called in invalid state\n")); + return ERR_CONN; + } +} + +/** + * Enqueue data and/or TCP options for transmission + * + * Called by tcp_connect(), tcp_listen_input(), tcp_send_ctrl() and tcp_write(). + * + * @param pcb Protocol control block for the TCP connection to enqueue data for. + * @param arg Pointer to the data to be enqueued for sending. + * @param len Data length in bytes + * @param flags tcp header flags to set in the outgoing segment + * @param apiflags combination of following flags : + * - TCP_WRITE_FLAG_COPY (0x01) data will be copied into memory belonging to the stack + * - TCP_WRITE_FLAG_MORE (0x02) for TCP connection, PSH flag will be set on last segment sent, + * @param optflags options to include in segment later on (see definition of struct tcp_seg) + */ +err_t +tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len, + u8_t flags, u8_t apiflags, u8_t optflags) +{ + struct pbuf *p; + struct tcp_seg *seg, *useg, *queue; + u32_t seqno; + u16_t left, seglen; + void *ptr; + u16_t queuelen; + u8_t optlen; + + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, + ("tcp_enqueue(pcb=%p, arg=%p, len=%"U16_F", flags=%"X16_F", apiflags=%"U16_F")\n", + (void *)pcb, arg, len, (u16_t)flags, (u16_t)apiflags)); + LWIP_ERROR("tcp_enqueue: packet needs payload, options, or SYN/FIN (programmer violates API)", + ((len != 0) || (optflags != 0) || ((flags & (TCP_SYN | TCP_FIN)) != 0)), + return ERR_ARG;); + LWIP_ERROR("tcp_enqueue: len != 0 || arg == NULL (programmer violates API)", + ((len != 0) || (arg == NULL)), return ERR_ARG;); + + /* fail on too much data */ + if (len > pcb->snd_buf) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_WARNING, + ("tcp_enqueue: too much data (len=%"U16_F" > snd_buf=%"U16_F")\n", len, pcb->snd_buf)); + pcb->flags |= TF_NAGLEMEMERR; + return ERR_MEM; + } + left = len; + ptr = arg; + + optlen = LWIP_TCP_OPT_LENGTH(optflags); + + /* seqno will be the sequence number of the first segment enqueued + * by the call to this function. */ + seqno = pcb->snd_lbb; + + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen)); + + /* If total number of pbufs on the unsent/unacked queues exceeds the + * configured maximum, return an error */ + queuelen = pcb->snd_queuelen; + /* check for configured max queuelen and possible overflow */ + if ((queuelen >= TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_WARNING, + ("tcp_enqueue: too long queue %"U16_F" (max %"U16_F")\n", queuelen, TCP_SND_QUEUELEN)); + TCP_STATS_INC(tcp.memerr); + pcb->flags |= TF_NAGLEMEMERR; + return ERR_MEM; + } + if (queuelen != 0) { + LWIP_ASSERT("tcp_enqueue: pbufs on queue => at least one queue non-empty", + pcb->unacked != NULL || pcb->unsent != NULL); + } else { + LWIP_ASSERT("tcp_enqueue: no pbufs on queue => both queues empty", + pcb->unacked == NULL && pcb->unsent == NULL); + } + + /* First, break up the data into segments and tuck them together in + * the local "queue" variable. */ + useg = queue = seg = NULL; + seglen = 0; + while (queue == NULL || left > 0) { + /* The segment length (including options) should be at most the MSS */ + seglen = left > (pcb->mss - optlen) ? (pcb->mss - optlen) : left; + + /* Allocate memory for tcp_seg, and fill in fields. */ + seg = memp_malloc(MEMP_TCP_SEG); + if (seg == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("tcp_enqueue: could not allocate memory for tcp_seg\n")); + goto memerr; + } + seg->next = NULL; + seg->p = NULL; + + /* first segment of to-be-queued data? */ + if (queue == NULL) { + queue = seg; + } + /* subsequent segments of to-be-queued data */ + else { + /* Attach the segment to the end of the queued segments */ + LWIP_ASSERT("useg != NULL", useg != NULL); + useg->next = seg; + } + /* remember last segment of to-be-queued data for next iteration */ + useg = seg; + + /* If copy is set, memory should be allocated + * and data copied into pbuf, otherwise data comes from + * ROM or other static memory, and need not be copied. */ + if (apiflags & TCP_WRITE_FLAG_COPY) { + if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, seglen + optlen, PBUF_RAM)) == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("tcp_enqueue : could not allocate memory for pbuf copy size %"U16_F"\n", seglen)); + goto memerr; + } + LWIP_ASSERT("check that first pbuf can hold the complete seglen", + (seg->p->len >= seglen + optlen)); + queuelen += pbuf_clen(seg->p); + if (arg != NULL) { + MEMCPY((char *)seg->p->payload + optlen, ptr, seglen); + } + seg->dataptr = seg->p->payload; + } + /* do not copy data */ + else { + /* First, allocate a pbuf for the headers. */ + if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("tcp_enqueue: could not allocate memory for header pbuf\n")); + goto memerr; + } + queuelen += pbuf_clen(seg->p); + + /* Second, allocate a pbuf for holding the data. + * since the referenced data is available at least until it is sent out on the + * link (as it has to be ACKed by the remote party) we can safely use PBUF_ROM + * instead of PBUF_REF here. + */ + if (left > 0) { + if ((p = pbuf_alloc(PBUF_RAW, seglen, PBUF_ROM)) == NULL) { + /* If allocation fails, we have to deallocate the header pbuf as well. */ + pbuf_free(seg->p); + seg->p = NULL; + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("tcp_enqueue: could not allocate memory for zero-copy pbuf\n")); + goto memerr; + } + ++queuelen; + /* reference the non-volatile payload data */ + p->payload = ptr; + seg->dataptr = ptr; + + /* Concatenate the headers and data pbufs together. */ + pbuf_cat(seg->p/*header*/, p/*data*/); + p = NULL; + } + } + + /* Now that there are more segments queued, we check again if the + length of the queue exceeds the configured maximum or overflows. */ + if ((queuelen > TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("tcp_enqueue: queue too long %"U16_F" (%"U16_F")\n", queuelen, TCP_SND_QUEUELEN)); + goto memerr; + } + + seg->len = seglen; + + /* build TCP header */ + if (pbuf_header(seg->p, TCP_HLEN)) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_enqueue: no room for TCP header in pbuf.\n")); + TCP_STATS_INC(tcp.err); + goto memerr; + } + seg->tcphdr = seg->p->payload; + seg->tcphdr->src = htons(pcb->local_port); + seg->tcphdr->dest = htons(pcb->remote_port); + seg->tcphdr->seqno = htonl(seqno); + seg->tcphdr->urgp = 0; + TCPH_FLAGS_SET(seg->tcphdr, flags); + /* don't fill in tcphdr->ackno and tcphdr->wnd until later */ + + seg->flags = optflags; + + /* Set the length of the header */ + TCPH_HDRLEN_SET(seg->tcphdr, (5 + optlen / 4)); + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, ("tcp_enqueue: queueing %"U32_F":%"U32_F" (0x%"X16_F")\n", + ntohl(seg->tcphdr->seqno), + ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg), + (u16_t)flags)); + + left -= seglen; + seqno += seglen; + ptr = (void *)((u8_t *)ptr + seglen); + } + + /* Now that the data to be enqueued has been broken up into TCP + segments in the queue variable, we add them to the end of the + pcb->unsent queue. */ + if (pcb->unsent == NULL) { + useg = NULL; + } + else { + for (useg = pcb->unsent; useg->next != NULL; useg = useg->next); + } + /* { useg is last segment on the unsent queue, NULL if list is empty } */ + + /* If there is room in the last pbuf on the unsent queue, + chain the first pbuf on the queue together with that. */ + if (useg != NULL && + TCP_TCPLEN(useg) != 0 && + !(TCPH_FLAGS(useg->tcphdr) & (TCP_SYN | TCP_FIN)) && + (!(flags & (TCP_SYN | TCP_FIN)) || (flags == TCP_FIN)) && + /* fit within max seg size */ + (useg->len + queue->len <= pcb->mss) && + /* only concatenate segments with the same options */ + (useg->flags == queue->flags) && + /* segments are consecutive */ + (ntohl(useg->tcphdr->seqno) + useg->len == ntohl(queue->tcphdr->seqno)) ) { + /* Remove TCP header from first segment of our to-be-queued list */ + if(pbuf_header(queue->p, -(TCP_HLEN + optlen))) { + /* Can we cope with this failing? Just assert for now */ + LWIP_ASSERT("pbuf_header failed\n", 0); + TCP_STATS_INC(tcp.err); + goto memerr; + } + if (queue->p->len == 0) { + /* free the first (header-only) pbuf if it is now empty (contained only headers) */ + struct pbuf *old_q = queue->p; + queue->p = queue->p->next; + old_q->next = NULL; + queuelen--; + pbuf_free(old_q); + } + if (flags & TCP_FIN) { + /* the new segment contains only FIN, no data -> put the FIN into the last segment */ + LWIP_ASSERT("FIN enqueued together with data", queue->p == NULL && queue->len == 0); + TCPH_SET_FLAG(useg->tcphdr, TCP_FIN); + } else { + LWIP_ASSERT("zero-length pbuf", (queue->p != NULL) && (queue->p->len > 0)); + pbuf_cat(useg->p, queue->p); + useg->len += queue->len; + useg->next = queue->next; + } + + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("tcp_enqueue: chaining segments, new len %"U16_F"\n", useg->len)); + if (seg == queue) { + seg = useg; + seglen = useg->len; + } + memp_free(MEMP_TCP_SEG, queue); + } + else { + /* empty list */ + if (useg == NULL) { + /* initialize list with this segment */ + pcb->unsent = queue; + } + /* enqueue segment */ + else { + useg->next = queue; + } + } + if ((flags & TCP_SYN) || (flags & TCP_FIN)) { + ++len; + } + if (flags & TCP_FIN) { + pcb->flags |= TF_FIN; + } + pcb->snd_lbb += len; + + pcb->snd_buf -= len; + + /* update number of segments on the queues */ + pcb->snd_queuelen = queuelen; + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: %"S16_F" (after enqueued)\n", pcb->snd_queuelen)); + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_enqueue: valid queue length", + pcb->unacked != NULL || pcb->unsent != NULL); + } + + /* Set the PSH flag in the last segment that we enqueued, but only + if the segment has data (indicated by seglen > 0). */ + if (seg != NULL && seglen > 0 && seg->tcphdr != NULL && ((apiflags & TCP_WRITE_FLAG_MORE)==0)) { + TCPH_SET_FLAG(seg->tcphdr, TCP_PSH); + } + + return ERR_OK; +memerr: + pcb->flags |= TF_NAGLEMEMERR; + TCP_STATS_INC(tcp.memerr); + + if (queue != NULL) { + tcp_segs_free(queue); + } + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL || + pcb->unsent != NULL); + } + LWIP_DEBUGF(TCP_QLEN_DEBUG | LWIP_DBG_STATE, ("tcp_enqueue: %"S16_F" (with mem err)\n", pcb->snd_queuelen)); + return ERR_MEM; +} + + +#if LWIP_TCP_TIMESTAMPS +/* Build a timestamp option (12 bytes long) at the specified options pointer) + * + * @param pcb tcp_pcb + * @param opts option pointer where to store the timestamp option + */ +static void +tcp_build_timestamp_option(struct tcp_pcb *pcb, u32_t *opts) +{ + /* Pad with two NOP options to make everything nicely aligned */ + opts[0] = htonl(0x0101080A); + opts[1] = htonl(sys_now()); + opts[2] = htonl(pcb->ts_recent); +} +#endif + +/** Send an ACK without data. + * + * @param pcb Protocol control block for the TCP connection to send the ACK + */ +err_t +tcp_send_empty_ack(struct tcp_pcb *pcb) +{ + struct pbuf *p; + struct tcp_hdr *tcphdr; + u8_t optlen = 0; + +#if LWIP_TCP_TIMESTAMPS + if (pcb->flags & TF_TIMESTAMP) { + optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS); + } +#endif + p = pbuf_alloc(PBUF_IP, TCP_HLEN + optlen, PBUF_RAM); + if (p == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n")); + return ERR_BUF; + } + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, + ("tcp_output: sending ACK for %"U32_F"\n", pcb->rcv_nxt)); + /* remove ACK flags from the PCB, as we send an empty ACK now */ + pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); + + tcphdr = tcp_output_set_header(pcb, p, optlen, htonl(pcb->snd_nxt)); + + /* NB. MSS option is only sent on SYNs, so ignore it here */ +#if LWIP_TCP_TIMESTAMPS + pcb->ts_lastacksent = pcb->rcv_nxt; + + if (pcb->flags & TF_TIMESTAMP) { + tcp_build_timestamp_option(pcb, (u32_t *)(tcphdr + 1)); + } +#endif + +#if CHECKSUM_GEN_TCP + tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip), + IP_PROTO_TCP, p->tot_len); +#endif +#if LWIP_NETIF_HWADDRHINT + ip_output_hinted(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos, + IP_PROTO_TCP, &(pcb->addr_hint)); +#else /* LWIP_NETIF_HWADDRHINT*/ + ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos, + IP_PROTO_TCP); +#endif /* LWIP_NETIF_HWADDRHINT*/ + pbuf_free(p); + + return ERR_OK; +} + +/** + * Find out what we can send and send it + * + * @param pcb Protocol control block for the TCP connection to send data + * @return ERR_OK if data has been sent or nothing to send + * another err_t on error + */ +err_t +tcp_output(struct tcp_pcb *pcb) +{ + struct tcp_seg *seg, *useg; + u32_t wnd, snd_nxt; +#if TCP_CWND_DEBUG + s16_t i = 0; +#endif /* TCP_CWND_DEBUG */ + + /* First, check if we are invoked by the TCP input processing + code. If so, we do not output anything. Instead, we rely on the + input processing code to call us when input processing is done + with. */ + if (tcp_input_pcb == pcb) { + return ERR_OK; + } + + wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd); + + seg = pcb->unsent; + + /* If the TF_ACK_NOW flag is set and no data will be sent (either + * because the ->unsent queue is empty or because the window does + * not allow it), construct an empty ACK segment and send it. + * + * If data is to be sent, we will just piggyback the ACK (see below). + */ + if (pcb->flags & TF_ACK_NOW && + (seg == NULL || + ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) { + return tcp_send_empty_ack(pcb); + } + + /* useg should point to last segment on unacked queue */ + useg = pcb->unacked; + if (useg != NULL) { + for (; useg->next != NULL; useg = useg->next); + } + +#if TCP_OUTPUT_DEBUG + if (seg == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n", + (void*)pcb->unsent)); + } +#endif /* TCP_OUTPUT_DEBUG */ +#if TCP_CWND_DEBUG + if (seg == NULL) { + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U16_F + ", cwnd %"U16_F", wnd %"U32_F + ", seg == NULL, ack %"U32_F"\n", + pcb->snd_wnd, pcb->cwnd, wnd, pcb->lastack)); + } else { + LWIP_DEBUGF(TCP_CWND_DEBUG, + ("tcp_output: snd_wnd %"U16_F", cwnd %"U16_F", wnd %"U32_F + ", effwnd %"U32_F", seq %"U32_F", ack %"U32_F"\n", + pcb->snd_wnd, pcb->cwnd, wnd, + ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len, + ntohl(seg->tcphdr->seqno), pcb->lastack)); + } +#endif /* TCP_CWND_DEBUG */ + /* data available and window allows it to be sent? */ + while (seg != NULL && + ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) { + LWIP_ASSERT("RST not expected here!", + (TCPH_FLAGS(seg->tcphdr) & TCP_RST) == 0); + /* Stop sending if the nagle algorithm would prevent it + * Don't stop: + * - if tcp_enqueue had a memory error before (prevent delayed ACK timeout) or + * - if FIN was already enqueued for this PCB (SYN is always alone in a segment - + * either seg->next != NULL or pcb->unacked == NULL; + * RST is no sent using tcp_enqueue/tcp_output. + */ + if((tcp_do_output_nagle(pcb) == 0) && + ((pcb->flags & (TF_NAGLEMEMERR | TF_FIN)) == 0)){ + break; + } +#if TCP_CWND_DEBUG + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U16_F", cwnd %"U16_F", wnd %"U32_F", effwnd %"U32_F", seq %"U32_F", ack %"U32_F", i %"S16_F"\n", + pcb->snd_wnd, pcb->cwnd, wnd, + ntohl(seg->tcphdr->seqno) + seg->len - + pcb->lastack, + ntohl(seg->tcphdr->seqno), pcb->lastack, i)); + ++i; +#endif /* TCP_CWND_DEBUG */ + + pcb->unsent = seg->next; + + if (pcb->state != SYN_SENT) { + TCPH_SET_FLAG(seg->tcphdr, TCP_ACK); + pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); + } + + tcp_output_segment(seg, pcb); + snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg); + if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) { + pcb->snd_nxt = snd_nxt; + } + /* put segment on unacknowledged list if length > 0 */ + if (TCP_TCPLEN(seg) > 0) { + seg->next = NULL; + /* unacked list is empty? */ + if (pcb->unacked == NULL) { + pcb->unacked = seg; + useg = seg; + /* unacked list is not empty? */ + } else { + /* In the case of fast retransmit, the packet should not go to the tail + * of the unacked queue, but rather somewhere before it. We need to check for + * this case. -STJ Jul 27, 2004 */ + if (TCP_SEQ_LT(ntohl(seg->tcphdr->seqno), ntohl(useg->tcphdr->seqno))){ + /* add segment to before tail of unacked list, keeping the list sorted */ + struct tcp_seg **cur_seg = &(pcb->unacked); + while (*cur_seg && + TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) { + cur_seg = &((*cur_seg)->next ); + } + seg->next = (*cur_seg); + (*cur_seg) = seg; + } else { + /* add segment to tail of unacked list */ + useg->next = seg; + useg = useg->next; + } + } + /* do not queue empty segments on the unacked list */ + } else { + tcp_seg_free(seg); + } + seg = pcb->unsent; + } + + if (seg != NULL && pcb->persist_backoff == 0 && + ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > pcb->snd_wnd) { + /* prepare for persist timer */ + pcb->persist_cnt = 0; + pcb->persist_backoff = 1; + } + + pcb->flags &= ~TF_NAGLEMEMERR; + return ERR_OK; +} + +/** + * Called by tcp_output() to actually send a TCP segment over IP. + * + * @param seg the tcp_seg to send + * @param pcb the tcp_pcb for the TCP connection used to send the segment + */ +static void +tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb) +{ + u16_t len; + struct netif *netif; + u32_t *opts; + + /** @bug Exclude retransmitted segments from this count. */ + snmp_inc_tcpoutsegs(); + + /* The TCP header has already been constructed, but the ackno and + wnd fields remain. */ + seg->tcphdr->ackno = htonl(pcb->rcv_nxt); + + /* advertise our receive window size in this TCP segment */ + seg->tcphdr->wnd = htons(pcb->rcv_ann_wnd); + + pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd; + + /* Add any requested options. NB MSS option is only set on SYN + packets, so ignore it here */ + opts = (u32_t *)(seg->tcphdr + 1); + if (seg->flags & TF_SEG_OPTS_MSS) { + TCP_BUILD_MSS_OPTION(*opts); + opts += 1; + } +#if LWIP_TCP_TIMESTAMPS + pcb->ts_lastacksent = pcb->rcv_nxt; + + if (seg->flags & TF_SEG_OPTS_TS) { + tcp_build_timestamp_option(pcb, opts); + opts += 3; + } +#endif + + /* If we don't have a local IP address, we get one by + calling ip_route(). */ + if (ip_addr_isany(&(pcb->local_ip))) { + netif = ip_route(&(pcb->remote_ip)); + if (netif == NULL) { + return; + } + ip_addr_set(&(pcb->local_ip), &(netif->ip_addr)); + } + + /* Set retransmission timer running if it is not currently enabled */ + if(pcb->rtime == -1) + pcb->rtime = 0; + + if (pcb->rttest == 0) { + pcb->rttest = tcp_ticks; + pcb->rtseq = ntohl(seg->tcphdr->seqno); + + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %"U32_F"\n", pcb->rtseq)); + } + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %"U32_F":%"U32_F"\n", + htonl(seg->tcphdr->seqno), htonl(seg->tcphdr->seqno) + + seg->len)); + + len = (u16_t)((u8_t *)seg->tcphdr - (u8_t *)seg->p->payload); + + seg->p->len -= len; + seg->p->tot_len -= len; + + seg->p->payload = seg->tcphdr; + + seg->tcphdr->chksum = 0; +#if CHECKSUM_GEN_TCP + seg->tcphdr->chksum = inet_chksum_pseudo(seg->p, + &(pcb->local_ip), + &(pcb->remote_ip), + IP_PROTO_TCP, seg->p->tot_len); +#endif + TCP_STATS_INC(tcp.xmit); + +#if LWIP_NETIF_HWADDRHINT + ip_output_hinted(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos, + IP_PROTO_TCP, &(pcb->addr_hint)); +#else /* LWIP_NETIF_HWADDRHINT*/ + ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos, + IP_PROTO_TCP); +#endif /* LWIP_NETIF_HWADDRHINT*/ +} + +/** + * Send a TCP RESET packet (empty segment with RST flag set) either to + * abort a connection or to show that there is no matching local connection + * for a received segment. + * + * Called by tcp_abort() (to abort a local connection), tcp_input() (if no + * matching local pcb was found), tcp_listen_input() (if incoming segment + * has ACK flag set) and tcp_process() (received segment in the wrong state) + * + * Since a RST segment is in most cases not sent for an active connection, + * tcp_rst() has a number of arguments that are taken from a tcp_pcb for + * most other segment output functions. + * + * @param seqno the sequence number to use for the outgoing segment + * @param ackno the acknowledge number to use for the outgoing segment + * @param local_ip the local IP address to send the segment from + * @param remote_ip the remote IP address to send the segment to + * @param local_port the local TCP port to send the segment from + * @param remote_port the remote TCP port to send the segment to + */ +void +tcp_rst(u32_t seqno, u32_t ackno, + struct ip_addr *local_ip, struct ip_addr *remote_ip, + u16_t local_port, u16_t remote_port) +{ + struct pbuf *p; + struct tcp_hdr *tcphdr; + p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM); + if (p == NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n")); + return; + } + LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr", + (p->len >= sizeof(struct tcp_hdr))); + + tcphdr = p->payload; + tcphdr->src = htons(local_port); + tcphdr->dest = htons(remote_port); + tcphdr->seqno = htonl(seqno); + tcphdr->ackno = htonl(ackno); + TCPH_FLAGS_SET(tcphdr, TCP_RST | TCP_ACK); + tcphdr->wnd = htons(TCP_WND); + tcphdr->urgp = 0; + TCPH_HDRLEN_SET(tcphdr, 5); + + tcphdr->chksum = 0; +#if CHECKSUM_GEN_TCP + tcphdr->chksum = inet_chksum_pseudo(p, local_ip, remote_ip, + IP_PROTO_TCP, p->tot_len); +#endif + TCP_STATS_INC(tcp.xmit); + snmp_inc_tcpoutrsts(); + /* Send output with hardcoded TTL since we have no access to the pcb */ + ip_output(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP); + pbuf_free(p); + LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %"U32_F" ackno %"U32_F".\n", seqno, ackno)); +} + +/** + * Requeue all unacked segments for retransmission + * + * Called by tcp_slowtmr() for slow retransmission. + * + * @param pcb the tcp_pcb for which to re-enqueue all unacked segments + */ +void +tcp_rexmit_rto(struct tcp_pcb *pcb) +{ + struct tcp_seg *seg; + + if (pcb->unacked == NULL) { + return; + } + + /* Move all unacked segments to the head of the unsent queue */ + for (seg = pcb->unacked; seg->next != NULL; seg = seg->next); + /* concatenate unsent queue after unacked queue */ + seg->next = pcb->unsent; + /* unsent queue is the concatenated queue (of unacked, unsent) */ + pcb->unsent = pcb->unacked; + /* unacked queue is now empty */ + pcb->unacked = NULL; + + /* increment number of retransmissions */ + ++pcb->nrtx; + + /* Don't take any RTT measurements after retransmitting. */ + pcb->rttest = 0; + + /* Do the actual retransmission */ + tcp_output(pcb); +} + +/** + * Requeue the first unacked segment for retransmission + * + * Called by tcp_receive() for fast retramsmit. + * + * @param pcb the tcp_pcb for which to retransmit the first unacked segment + */ +void +tcp_rexmit(struct tcp_pcb *pcb) +{ + struct tcp_seg *seg; + struct tcp_seg **cur_seg; + + if (pcb->unacked == NULL) { + return; + } + + /* Move the first unacked segment to the unsent queue */ + /* Keep the unsent queue sorted. */ + seg = pcb->unacked; + pcb->unacked = seg->next; + + cur_seg = &(pcb->unsent); + while (*cur_seg && + TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) { + cur_seg = &((*cur_seg)->next ); + } + seg->next = *cur_seg; + *cur_seg = seg; + + ++pcb->nrtx; + + /* Don't take any rtt measurements after retransmitting. */ + pcb->rttest = 0; + + /* Do the actual retransmission. */ + snmp_inc_tcpretranssegs(); + /* No need to call tcp_output: we are always called from tcp_input() + and thus tcp_output directly returns. */ +} + + +/** + * Handle retransmission after three dupacks received + * + * @param pcb the tcp_pcb for which to retransmit the first unacked segment + */ +void +tcp_rexmit_fast(struct tcp_pcb *pcb) +{ + if (pcb->unacked != NULL && !(pcb->flags & TF_INFR)) { + /* This is fast retransmit. Retransmit the first unacked segment. */ + LWIP_DEBUGF(TCP_FR_DEBUG, + ("tcp_receive: dupacks %"U16_F" (%"U32_F + "), fast retransmit %"U32_F"\n", + (u16_t)pcb->dupacks, pcb->lastack, + ntohl(pcb->unacked->tcphdr->seqno))); + tcp_rexmit(pcb); + + /* Set ssthresh to half of the minimum of the current + * cwnd and the advertised window */ + if (pcb->cwnd > pcb->snd_wnd) + pcb->ssthresh = pcb->snd_wnd / 2; + else + pcb->ssthresh = pcb->cwnd / 2; + + /* The minimum value for ssthresh should be 2 MSS */ + if (pcb->ssthresh < 2*pcb->mss) { + LWIP_DEBUGF(TCP_FR_DEBUG, + ("tcp_receive: The minimum value for ssthresh %"U16_F + " should be min 2 mss %"U16_F"...\n", + pcb->ssthresh, 2*pcb->mss)); + pcb->ssthresh = 2*pcb->mss; + } + + pcb->cwnd = pcb->ssthresh + 3 * pcb->mss; + pcb->flags |= TF_INFR; + } +} + + +/** + * Send keepalive packets to keep a connection active although + * no data is sent over it. + * + * Called by tcp_slowtmr() + * + * @param pcb the tcp_pcb for which to send a keepalive packet + */ +void +tcp_keepalive(struct tcp_pcb *pcb) +{ + struct pbuf *p; + struct tcp_hdr *tcphdr; + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip), + ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip))); + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F" pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n", + tcp_ticks, pcb->tmr, pcb->keep_cnt_sent)); + + p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM); + + if(p == NULL) { + LWIP_DEBUGF(TCP_DEBUG, + ("tcp_keepalive: could not allocate memory for pbuf\n")); + return; + } + LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr", + (p->len >= sizeof(struct tcp_hdr))); + + tcphdr = tcp_output_set_header(pcb, p, 0, htonl(pcb->snd_nxt - 1)); + +#if CHECKSUM_GEN_TCP + tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip, + IP_PROTO_TCP, p->tot_len); +#endif + TCP_STATS_INC(tcp.xmit); + + /* Send output to IP */ +#if LWIP_NETIF_HWADDRHINT + ip_output_hinted(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP, + &(pcb->addr_hint)); +#else /* LWIP_NETIF_HWADDRHINT*/ + ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP); +#endif /* LWIP_NETIF_HWADDRHINT*/ + + pbuf_free(p); + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: seqno %"U32_F" ackno %"U32_F".\n", + pcb->snd_nxt - 1, pcb->rcv_nxt)); +} + + +/** + * Send persist timer zero-window probes to keep a connection active + * when a window update is lost. + * + * Called by tcp_slowtmr() + * + * @param pcb the tcp_pcb for which to send a zero-window probe packet + */ +void +tcp_zero_window_probe(struct tcp_pcb *pcb) +{ + struct pbuf *p; + struct tcp_hdr *tcphdr; + struct tcp_seg *seg; + u16_t len; + u8_t is_fin; + + LWIP_DEBUGF(TCP_DEBUG, + ("tcp_zero_window_probe: sending ZERO WINDOW probe to %" + U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip), + ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip))); + + LWIP_DEBUGF(TCP_DEBUG, + ("tcp_zero_window_probe: tcp_ticks %"U32_F + " pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n", + tcp_ticks, pcb->tmr, pcb->keep_cnt_sent)); + + seg = pcb->unacked; + + if(seg == NULL) + seg = pcb->unsent; + + if(seg == NULL) + return; + + is_fin = ((TCPH_FLAGS(seg->tcphdr) & TCP_FIN) != 0) && (seg->len == 0); + len = is_fin ? TCP_HLEN : TCP_HLEN + 1; + + p = pbuf_alloc(PBUF_IP, len, PBUF_RAM); + if(p == NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: no memory for pbuf\n")); + return; + } + LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr", + (p->len >= sizeof(struct tcp_hdr))); + + tcphdr = tcp_output_set_header(pcb, p, 0, seg->tcphdr->seqno); + + if (is_fin) { + /* FIN segment, no data */ + TCPH_FLAGS_SET(tcphdr, TCP_ACK | TCP_FIN); + } else { + /* Data segment, copy in one byte from the head of the unacked queue */ + *((char *)p->payload + sizeof(struct tcp_hdr)) = *(char *)seg->dataptr; + } + +#if CHECKSUM_GEN_TCP + tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip, + IP_PROTO_TCP, p->tot_len); +#endif + TCP_STATS_INC(tcp.xmit); + + /* Send output to IP */ +#if LWIP_NETIF_HWADDRHINT + ip_output_hinted(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP, + &(pcb->addr_hint)); +#else /* LWIP_NETIF_HWADDRHINT*/ + ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP); +#endif /* LWIP_NETIF_HWADDRHINT*/ + + pbuf_free(p); + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: seqno %"U32_F + " ackno %"U32_F".\n", + pcb->snd_nxt - 1, pcb->rcv_nxt)); +} +#endif /* LWIP_TCP */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/core/udp.c b/component/common/network/lwip/lwip_v1.3.2/src/core/udp.c new file mode 100644 index 0000000..31bbf8c --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/core/udp.c @@ -0,0 +1,848 @@ +/** + * @file + * User Datagram Protocol module + * + **/ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + + +/* udp.c + * + * The code for the User Datagram Protocol UDP & UDPLite (RFC 3828). + * + */ + +/* @todo Check the use of '(struct udp_pcb).chksum_len_rx'! + */ + +#include "lwip/opt.h" + +#if LWIP_UDP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/udp.h" +#include "lwip/def.h" +#include "lwip/memp.h" +#include "lwip/inet.h" +#include "lwip/inet_chksum.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/icmp.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "arch/perf.h" +#include "lwip/dhcp.h" + +#include + +/* The list of UDP PCBs */ +/* exported in udp.h (was static) */ +struct udp_pcb *udp_pcbs; + +/** + * Process an incoming UDP datagram. + * + * Given an incoming UDP datagram (as a chain of pbufs) this function + * finds a corresponding UDP PCB and hands over the pbuf to the pcbs + * recv function. If no pcb is found or the datagram is incorrect, the + * pbuf is freed. + * + * @param p pbuf to be demultiplexed to a UDP PCB. + * @param inp network interface on which the datagram was received. + * + */ +void +udp_input(struct pbuf *p, struct netif *inp) +{ + struct udp_hdr *udphdr; + struct udp_pcb *pcb, *prev; + struct udp_pcb *uncon_pcb; + struct ip_hdr *iphdr; + u16_t src, dest; + u8_t local_match; + u8_t broadcast; + + PERF_START; + + UDP_STATS_INC(udp.recv); + + iphdr = p->payload; + + /* Check minimum length (IP header + UDP header) + * and move payload pointer to UDP header */ + if (p->tot_len < (IPH_HL(iphdr) * 4 + UDP_HLEN) || pbuf_header(p, -(s16_t)(IPH_HL(iphdr) * 4))) { + /* drop short packets */ + LWIP_DEBUGF(UDP_DEBUG, + ("udp_input: short UDP datagram (%"U16_F" bytes) discarded\n", p->tot_len)); + UDP_STATS_INC(udp.lenerr); + UDP_STATS_INC(udp.drop); + snmp_inc_udpinerrors(); + pbuf_free(p); + goto end; + } + + udphdr = (struct udp_hdr *)p->payload; + + /* is broadcast packet ? */ + broadcast = ip_addr_isbroadcast(&(iphdr->dest), inp); + + LWIP_DEBUGF(UDP_DEBUG, ("udp_input: received datagram of length %"U16_F"\n", p->tot_len)); + + /* convert src and dest ports to host byte order */ + src = ntohs(udphdr->src); + dest = ntohs(udphdr->dest); + + udp_debug_print(udphdr); + + /* print the UDP source and destination */ + LWIP_DEBUGF(UDP_DEBUG, + ("udp (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F") <-- " + "(%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F")\n", + ip4_addr1(&iphdr->dest), ip4_addr2(&iphdr->dest), + ip4_addr3(&iphdr->dest), ip4_addr4(&iphdr->dest), ntohs(udphdr->dest), + ip4_addr1(&iphdr->src), ip4_addr2(&iphdr->src), + ip4_addr3(&iphdr->src), ip4_addr4(&iphdr->src), ntohs(udphdr->src))); + +#if LWIP_DHCP + pcb = NULL; + /* when LWIP_DHCP is active, packets to DHCP_CLIENT_PORT may only be processed by + the dhcp module, no other UDP pcb may use the local UDP port DHCP_CLIENT_PORT */ + if (dest == DHCP_CLIENT_PORT) { + /* all packets for DHCP_CLIENT_PORT not coming from DHCP_SERVER_PORT are dropped! */ + if (src == DHCP_SERVER_PORT) { + if ((inp->dhcp != NULL) && (inp->dhcp->pcb != NULL)) { + /* accept the packe if + (- broadcast or directed to us) -> DHCP is link-layer-addressed, local ip is always ANY! + - inp->dhcp->pcb->remote == ANY or iphdr->src */ + if ((ip_addr_isany(&inp->dhcp->pcb->remote_ip) || + ip_addr_cmp(&(inp->dhcp->pcb->remote_ip), &(iphdr->src)))) { + pcb = inp->dhcp->pcb; + } + } + } + } else +#endif /* LWIP_DHCP */ + { + prev = NULL; + local_match = 0; + uncon_pcb = NULL; + /* Iterate through the UDP pcb list for a matching pcb. + * 'Perfect match' pcbs (connected to the remote port & ip address) are + * preferred. If no perfect match is found, the first unconnected pcb that + * matches the local port and ip address gets the datagram. */ + for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) { + local_match = 0; + /* print the PCB local and remote address */ + LWIP_DEBUGF(UDP_DEBUG, + ("pcb (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F") --- " + "(%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F")\n", + ip4_addr1(&pcb->local_ip), ip4_addr2(&pcb->local_ip), + ip4_addr3(&pcb->local_ip), ip4_addr4(&pcb->local_ip), pcb->local_port, + ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip), + ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip), pcb->remote_port)); + + /* compare PCB local addr+port to UDP destination addr+port */ + if ((pcb->local_port == dest) && + ((!broadcast && ip_addr_isany(&pcb->local_ip)) || + ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)) || +#if LWIP_IGMP + ip_addr_ismulticast(&(iphdr->dest)) || +#endif /* LWIP_IGMP */ +#if IP_SOF_BROADCAST_RECV + (broadcast && (pcb->so_options & SOF_BROADCAST)))) { +#else /* IP_SOF_BROADCAST_RECV */ + (broadcast))) { +#endif /* IP_SOF_BROADCAST_RECV */ + local_match = 1; + if ((uncon_pcb == NULL) && + ((pcb->flags & UDP_FLAGS_CONNECTED) == 0)) { + /* the first unconnected matching PCB */ + uncon_pcb = pcb; + } + } + /* compare PCB remote addr+port to UDP source addr+port */ + if ((local_match != 0) && + (pcb->remote_port == src) && + (ip_addr_isany(&pcb->remote_ip) || + ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)))) { + /* the first fully matching PCB */ + if (prev != NULL) { + /* move the pcb to the front of udp_pcbs so that is + found faster next time */ + prev->next = pcb->next; + pcb->next = udp_pcbs; + udp_pcbs = pcb; + } else { + UDP_STATS_INC(udp.cachehit); + } + break; + } +/* This part of code has been modified by ST's MCD Application Team */ +/* To use the UPnP responder for device discovery */ +#if LWIP_UPNP + if((local_match != 0) && (dest == 1900)) { + break; + } +#endif /* LWIP_UPNP */ + prev = pcb; + } + /* no fully matching pcb found? then look for an unconnected pcb */ + if (pcb == NULL) { + pcb = uncon_pcb; + } + } + + /* Check checksum if this is a match or if it was directed at us. */ + if (pcb != NULL || ip_addr_cmp(&inp->ip_addr, &iphdr->dest)) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: calculating checksum\n")); +#if LWIP_UDPLITE + if (IPH_PROTO(iphdr) == IP_PROTO_UDPLITE) { + /* Do the UDP Lite checksum */ +#if CHECKSUM_CHECK_UDP + u16_t chklen = ntohs(udphdr->len); + if (chklen < sizeof(struct udp_hdr)) { + if (chklen == 0) { + /* For UDP-Lite, checksum length of 0 means checksum + over the complete packet (See RFC 3828 chap. 3.1) */ + chklen = p->tot_len; + } else { + /* At least the UDP-Lite header must be covered by the + checksum! (Again, see RFC 3828 chap. 3.1) */ + UDP_STATS_INC(udp.chkerr); + UDP_STATS_INC(udp.drop); + snmp_inc_udpinerrors(); + pbuf_free(p); + goto end; + } + } + if (inet_chksum_pseudo_partial(p, (struct ip_addr *)&(iphdr->src), + (struct ip_addr *)&(iphdr->dest), + IP_PROTO_UDPLITE, p->tot_len, chklen) != 0) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("udp_input: UDP Lite datagram discarded due to failing checksum\n")); + UDP_STATS_INC(udp.chkerr); + UDP_STATS_INC(udp.drop); + snmp_inc_udpinerrors(); + pbuf_free(p); + goto end; + } +#endif /* CHECKSUM_CHECK_UDP */ + } else +#endif /* LWIP_UDPLITE */ + { +#if CHECKSUM_CHECK_UDP + if (udphdr->chksum != 0) { + if (inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src), + (struct ip_addr *)&(iphdr->dest), + IP_PROTO_UDP, p->tot_len) != 0) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("udp_input: UDP datagram discarded due to failing checksum\n")); + UDP_STATS_INC(udp.chkerr); + UDP_STATS_INC(udp.drop); + snmp_inc_udpinerrors(); + pbuf_free(p); + goto end; + } + } +#endif /* CHECKSUM_CHECK_UDP */ + } + if(pbuf_header(p, -UDP_HLEN)) { + /* Can we cope with this failing? Just assert for now */ + LWIP_ASSERT("pbuf_header failed\n", 0); + UDP_STATS_INC(udp.drop); + snmp_inc_udpinerrors(); + pbuf_free(p); + goto end; + } + if (pcb != NULL) { + snmp_inc_udpindatagrams(); + /* callback */ + if (pcb->recv != NULL) { + /* now the recv function is responsible for freeing p */ + pcb->recv(pcb->recv_arg, pcb, p, &iphdr->src, src); + } else { + /* no recv function registered? then we have to free the pbuf! */ + pbuf_free(p); + goto end; + } + } else { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: not for us.\n")); + +#if LWIP_ICMP + /* No match was found, send ICMP destination port unreachable unless + destination address was broadcast/multicast. */ + if (!broadcast && + !ip_addr_ismulticast(&iphdr->dest)) { + /* move payload pointer back to ip header */ + pbuf_header(p, (IPH_HL(iphdr) * 4) + UDP_HLEN); + LWIP_ASSERT("p->payload == iphdr", (p->payload == iphdr)); + icmp_dest_unreach(p, ICMP_DUR_PORT); + } +#endif /* LWIP_ICMP */ + UDP_STATS_INC(udp.proterr); + UDP_STATS_INC(udp.drop); + snmp_inc_udpnoports(); + pbuf_free(p); + } + } else { + pbuf_free(p); + } +end: + PERF_STOP("udp_input"); +} + +/** + * Send data using UDP. + * + * @param pcb UDP PCB used to send the data. + * @param p chain of pbuf's to be sent. + * + * The datagram will be sent to the current remote_ip & remote_port + * stored in pcb. If the pcb is not bound to a port, it will + * automatically be bound to a random port. + * + * @return lwIP error code. + * - ERR_OK. Successful. No error occured. + * - ERR_MEM. Out of memory. + * - ERR_RTE. Could not find route to destination address. + * - More errors could be returned by lower protocol layers. + * + * @see udp_disconnect() udp_sendto() + */ +err_t +udp_send(struct udp_pcb *pcb, struct pbuf *p) +{ + /* send to the packet using remote ip and port stored in the pcb */ + return udp_sendto(pcb, p, &pcb->remote_ip, pcb->remote_port); +} + +/** + * Send data to a specified address using UDP. + * + * @param pcb UDP PCB used to send the data. + * @param p chain of pbuf's to be sent. + * @param dst_ip Destination IP address. + * @param dst_port Destination UDP port. + * + * dst_ip & dst_port are expected to be in the same byte order as in the pcb. + * + * If the PCB already has a remote address association, it will + * be restored after the data is sent. + * + * @return lwIP error code (@see udp_send for possible error codes) + * + * @see udp_disconnect() udp_send() + */ +err_t +udp_sendto(struct udp_pcb *pcb, struct pbuf *p, + struct ip_addr *dst_ip, u16_t dst_port) +{ + struct netif *netif; + + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send\n")); + + /* find the outgoing network interface for this packet */ +#if LWIP_IGMP + netif = ip_route((ip_addr_ismulticast(dst_ip))?(&(pcb->multicast_ip)):(dst_ip)); +#else + netif = ip_route(dst_ip); +#endif /* LWIP_IGMP */ + + /* no outgoing network interface could be found? */ + if (netif == NULL) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: No route to 0x%"X32_F"\n", dst_ip->addr)); + UDP_STATS_INC(udp.rterr); + return ERR_RTE; + } + return udp_sendto_if(pcb, p, dst_ip, dst_port, netif); +} + +/** + * Send data to a specified address using UDP. + * The netif used for sending can be specified. + * + * This function exists mainly for DHCP, to be able to send UDP packets + * on a netif that is still down. + * + * @param pcb UDP PCB used to send the data. + * @param p chain of pbuf's to be sent. + * @param dst_ip Destination IP address. + * @param dst_port Destination UDP port. + * @param netif the netif used for sending. + * + * dst_ip & dst_port are expected to be in the same byte order as in the pcb. + * + * @return lwIP error code (@see udp_send for possible error codes) + * + * @see udp_disconnect() udp_send() + */ +err_t +udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p, + struct ip_addr *dst_ip, u16_t dst_port, struct netif *netif) +{ + struct udp_hdr *udphdr; + struct ip_addr *src_ip; + err_t err; + struct pbuf *q; /* q will be sent down the stack */ + +#if IP_SOF_BROADCAST + /* broadcast filter? */ + if ( ((pcb->so_options & SOF_BROADCAST) == 0) && ip_addr_isbroadcast(dst_ip, netif) ) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("udp_sendto_if: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb)); + return ERR_VAL; + } +#endif /* IP_SOF_BROADCAST */ + + /* if the PCB is not yet bound to a port, bind it here */ + if (pcb->local_port == 0) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send: not yet bound to a port, binding now\n")); + err = udp_bind(pcb, &pcb->local_ip, pcb->local_port); + if (err != ERR_OK) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: forced port bind failed\n")); + return err; + } + } + + /* not enough space to add an UDP header to first pbuf in given p chain? */ + if (pbuf_header(p, UDP_HLEN)) { + /* allocate header in a separate new pbuf */ + q = pbuf_alloc(PBUF_IP, UDP_HLEN, PBUF_RAM); + /* new header pbuf could not be allocated? */ + if (q == NULL) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: could not allocate header\n")); + return ERR_MEM; + } + /* chain header q in front of given pbuf p */ + pbuf_chain(q, p); + /* first pbuf q points to header pbuf */ + LWIP_DEBUGF(UDP_DEBUG, + ("udp_send: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p)); + } else { + /* adding space for header within p succeeded */ + /* first pbuf q equals given pbuf */ + q = p; + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: added header in given pbuf %p\n", (void *)p)); + } + LWIP_ASSERT("check that first pbuf can hold struct udp_hdr", + (q->len >= sizeof(struct udp_hdr))); + /* q now represents the packet to be sent */ + udphdr = q->payload; + udphdr->src = htons(pcb->local_port); + udphdr->dest = htons(dst_port); + /* in UDP, 0 checksum means 'no checksum' */ + udphdr->chksum = 0x0000; + + /* PCB local address is IP_ANY_ADDR? */ + if (ip_addr_isany(&pcb->local_ip)) { + /* use outgoing network interface IP address as source address */ + src_ip = &(netif->ip_addr); + } else { + /* check if UDP PCB local IP address is correct + * this could be an old address if netif->ip_addr has changed */ + if (!ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr))) { + /* local_ip doesn't match, drop the packet */ + if (q != p) { + /* free the header pbuf */ + pbuf_free(q); + q = NULL; + /* p is still referenced by the caller, and will live on */ + } + return ERR_VAL; + } + /* use UDP PCB local IP address as source address */ + src_ip = &(pcb->local_ip); + } + + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: sending datagram of length %"U16_F"\n", q->tot_len)); + +#if LWIP_UDPLITE + /* UDP Lite protocol? */ + if (pcb->flags & UDP_FLAGS_UDPLITE) { + u16_t chklen, chklen_hdr; + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE packet length %"U16_F"\n", q->tot_len)); + /* set UDP message length in UDP header */ + chklen_hdr = chklen = pcb->chksum_len_tx; + if ((chklen < sizeof(struct udp_hdr)) || (chklen > q->tot_len)) { + if (chklen != 0) { + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE pcb->chksum_len is illegal: %"U16_F"\n", chklen)); + } + /* For UDP-Lite, checksum length of 0 means checksum + over the complete packet. (See RFC 3828 chap. 3.1) + At least the UDP-Lite header must be covered by the + checksum, therefore, if chksum_len has an illegal + value, we generate the checksum over the complete + packet to be safe. */ + chklen_hdr = 0; + chklen = q->tot_len; + } + udphdr->len = htons(chklen_hdr); + /* calculate checksum */ +#if CHECKSUM_GEN_UDP + udphdr->chksum = inet_chksum_pseudo_partial(q, src_ip, dst_ip, + IP_PROTO_UDPLITE, q->tot_len, chklen); + /* chksum zero must become 0xffff, as zero means 'no checksum' */ + if (udphdr->chksum == 0x0000) + udphdr->chksum = 0xffff; +#endif /* CHECKSUM_CHECK_UDP */ + /* output to IP */ + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDPLITE,)\n")); +#if LWIP_NETIF_HWADDRHINT + netif->addr_hint = &(pcb->addr_hint); +#endif /* LWIP_NETIF_HWADDRHINT*/ + err = ip_output_if(q, src_ip, dst_ip, pcb->ttl, pcb->tos, IP_PROTO_UDPLITE, netif); +#if LWIP_NETIF_HWADDRHINT + netif->addr_hint = NULL; +#endif /* LWIP_NETIF_HWADDRHINT*/ + } else +#endif /* LWIP_UDPLITE */ + { /* UDP */ + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %"U16_F"\n", q->tot_len)); + udphdr->len = htons(q->tot_len); + /* calculate checksum */ +#if CHECKSUM_GEN_UDP + if ((pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) { + udphdr->chksum = inet_chksum_pseudo(q, src_ip, dst_ip, IP_PROTO_UDP, q->tot_len); + /* chksum zero must become 0xffff, as zero means 'no checksum' */ + if (udphdr->chksum == 0x0000) udphdr->chksum = 0xffff; + } +#endif /* CHECKSUM_CHECK_UDP */ + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum 0x%04"X16_F"\n", udphdr->chksum)); + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDP,)\n")); + /* output to IP */ +#if LWIP_NETIF_HWADDRHINT + netif->addr_hint = &(pcb->addr_hint); +#endif /* LWIP_NETIF_HWADDRHINT*/ + err = ip_output_if(q, src_ip, dst_ip, pcb->ttl, pcb->tos, IP_PROTO_UDP, netif); +#if LWIP_NETIF_HWADDRHINT + netif->addr_hint = NULL; +#endif /* LWIP_NETIF_HWADDRHINT*/ + } + /* TODO: must this be increased even if error occured? */ + snmp_inc_udpoutdatagrams(); + + /* did we chain a separate header pbuf earlier? */ + if (q != p) { + /* free the header pbuf */ + pbuf_free(q); + q = NULL; + /* p is still referenced by the caller, and will live on */ + } + + UDP_STATS_INC(udp.xmit); + return err; +} + +/** + * Bind an UDP PCB. + * + * @param pcb UDP PCB to be bound with a local address ipaddr and port. + * @param ipaddr local IP address to bind with. Use IP_ADDR_ANY to + * bind to all local interfaces. + * @param port local UDP port to bind with. Use 0 to automatically bind + * to a random port between UDP_LOCAL_PORT_RANGE_START and + * UDP_LOCAL_PORT_RANGE_END. + * + * ipaddr & port are expected to be in the same byte order as in the pcb. + * + * @return lwIP error code. + * - ERR_OK. Successful. No error occured. + * - ERR_USE. The specified ipaddr and port are already bound to by + * another UDP PCB. + * + * @see udp_disconnect() + */ +err_t +udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port) +{ + struct udp_pcb *ipcb; + u8_t rebind; + + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_bind(ipaddr = ")); + ip_addr_debug_print(UDP_DEBUG, ipaddr); + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, (", port = %"U16_F")\n", port)); + + rebind = 0; + /* Check for double bind and rebind of the same pcb */ + for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) { + /* is this UDP PCB already on active list? */ + if (pcb == ipcb) { + /* pcb may occur at most once in active list */ + LWIP_ASSERT("rebind == 0", rebind == 0); + /* pcb already in list, just rebind */ + rebind = 1; + } + + /* this code does not allow upper layer to share a UDP port for + listening to broadcast or multicast traffic (See SO_REUSE_ADDR and + SO_REUSE_PORT under *BSD). TODO: See where it fits instead, OR + combine with implementation of UDP PCB flags. Leon Woestenberg. */ +#ifdef LWIP_UDP_TODO + /* port matches that of PCB in list? */ + else + if ((ipcb->local_port == port) && + /* IP address matches, or one is IP_ADDR_ANY? */ + (ip_addr_isany(&(ipcb->local_ip)) || + ip_addr_isany(ipaddr) || + ip_addr_cmp(&(ipcb->local_ip), ipaddr))) { + /* other PCB already binds to this local IP and port */ + LWIP_DEBUGF(UDP_DEBUG, + ("udp_bind: local port %"U16_F" already bound by another pcb\n", port)); + return ERR_USE; + } +#endif + } + + ip_addr_set(&pcb->local_ip, ipaddr); + + /* no port specified? */ + if (port == 0) { +#ifndef UDP_LOCAL_PORT_RANGE_START +#define UDP_LOCAL_PORT_RANGE_START 4096 +#define UDP_LOCAL_PORT_RANGE_END 0x7fff +#endif + port = UDP_LOCAL_PORT_RANGE_START; + ipcb = udp_pcbs; + while ((ipcb != NULL) && (port != UDP_LOCAL_PORT_RANGE_END)) { + if (ipcb->local_port == port) { + /* port is already used by another udp_pcb */ + port++; + /* restart scanning all udp pcbs */ + ipcb = udp_pcbs; + } else + /* go on with next udp pcb */ + ipcb = ipcb->next; + } + if (ipcb != NULL) { + /* no more ports available in local range */ + LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: out of free UDP ports\n")); + return ERR_USE; + } + } + pcb->local_port = port; + snmp_insert_udpidx_tree(pcb); + /* pcb not active yet? */ + if (rebind == 0) { + /* place the PCB on the active list if not already there */ + pcb->next = udp_pcbs; + udp_pcbs = pcb; + } + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("udp_bind: bound to %"U16_F".%"U16_F".%"U16_F".%"U16_F", port %"U16_F"\n", + (u16_t)((ntohl(pcb->local_ip.addr) >> 24) & 0xff), + (u16_t)((ntohl(pcb->local_ip.addr) >> 16) & 0xff), + (u16_t)((ntohl(pcb->local_ip.addr) >> 8) & 0xff), + (u16_t)(ntohl(pcb->local_ip.addr) & 0xff), pcb->local_port)); + return ERR_OK; +} +/** + * Connect an UDP PCB. + * + * This will associate the UDP PCB with the remote address. + * + * @param pcb UDP PCB to be connected with remote address ipaddr and port. + * @param ipaddr remote IP address to connect with. + * @param port remote UDP port to connect with. + * + * @return lwIP error code + * + * ipaddr & port are expected to be in the same byte order as in the pcb. + * + * The udp pcb is bound to a random local port if not already bound. + * + * @see udp_disconnect() + */ +err_t +udp_connect(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port) +{ + struct udp_pcb *ipcb; + + if (pcb->local_port == 0) { + err_t err = udp_bind(pcb, &pcb->local_ip, pcb->local_port); + if (err != ERR_OK) + return err; + } + + ip_addr_set(&pcb->remote_ip, ipaddr); + pcb->remote_port = port; + pcb->flags |= UDP_FLAGS_CONNECTED; +/** TODO: this functionality belongs in upper layers */ +#ifdef LWIP_UDP_TODO + /* Nail down local IP for netconn_addr()/getsockname() */ + if (ip_addr_isany(&pcb->local_ip) && !ip_addr_isany(&pcb->remote_ip)) { + struct netif *netif; + + if ((netif = ip_route(&(pcb->remote_ip))) == NULL) { + LWIP_DEBUGF(UDP_DEBUG, ("udp_connect: No route to 0x%lx\n", pcb->remote_ip.addr)); + UDP_STATS_INC(udp.rterr); + return ERR_RTE; + } + /** TODO: this will bind the udp pcb locally, to the interface which + is used to route output packets to the remote address. However, we + might want to accept incoming packets on any interface! */ + pcb->local_ip = netif->ip_addr; + } else if (ip_addr_isany(&pcb->remote_ip)) { + pcb->local_ip.addr = 0; + } +#endif + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("udp_connect: connected to %"U16_F".%"U16_F".%"U16_F".%"U16_F",port %"U16_F"\n", + (u16_t)((ntohl(pcb->remote_ip.addr) >> 24) & 0xff), + (u16_t)((ntohl(pcb->remote_ip.addr) >> 16) & 0xff), + (u16_t)((ntohl(pcb->remote_ip.addr) >> 8) & 0xff), + (u16_t)(ntohl(pcb->remote_ip.addr) & 0xff), pcb->remote_port)); + + /* Insert UDP PCB into the list of active UDP PCBs. */ + for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) { + if (pcb == ipcb) { + /* already on the list, just return */ + return ERR_OK; + } + } + /* PCB not yet on the list, add PCB now */ + pcb->next = udp_pcbs; + udp_pcbs = pcb; + return ERR_OK; +} + +/** + * Disconnect a UDP PCB + * + * @param pcb the udp pcb to disconnect. + */ +void +udp_disconnect(struct udp_pcb *pcb) +{ + /* reset remote address association */ + ip_addr_set(&pcb->remote_ip, IP_ADDR_ANY); + pcb->remote_port = 0; + /* mark PCB as unconnected */ + pcb->flags &= ~UDP_FLAGS_CONNECTED; +} + +/** + * Set a receive callback for a UDP PCB + * + * This callback will be called when receiving a datagram for the pcb. + * + * @param pcb the pcb for wich to set the recv callback + * @param recv function pointer of the callback function + * @param recv_arg additional argument to pass to the callback function + */ +void +udp_recv(struct udp_pcb *pcb, + void (* recv)(void *arg, struct udp_pcb *upcb, struct pbuf *p, + struct ip_addr *addr, u16_t port), + void *recv_arg) +{ + /* remember recv() callback and user data */ + pcb->recv = recv; + pcb->recv_arg = recv_arg; +} + +/** + * Remove an UDP PCB. + * + * @param pcb UDP PCB to be removed. The PCB is removed from the list of + * UDP PCB's and the data structure is freed from memory. + * + * @see udp_new() + */ +void +udp_remove(struct udp_pcb *pcb) +{ + struct udp_pcb *pcb2; + + snmp_delete_udpidx_tree(pcb); + /* pcb to be removed is first in list? */ + if (udp_pcbs == pcb) { + /* make list start at 2nd pcb */ + udp_pcbs = udp_pcbs->next; + /* pcb not 1st in list */ + } else + for (pcb2 = udp_pcbs; pcb2 != NULL; pcb2 = pcb2->next) { + /* find pcb in udp_pcbs list */ + if (pcb2->next != NULL && pcb2->next == pcb) { + /* remove pcb from list */ + pcb2->next = pcb->next; + } + } + memp_free(MEMP_UDP_PCB, pcb); +} + +/** + * Create a UDP PCB. + * + * @return The UDP PCB which was created. NULL if the PCB data structure + * could not be allocated. + * + * @see udp_remove() + */ +struct udp_pcb * +udp_new(void) +{ + struct udp_pcb *pcb; + pcb = memp_malloc(MEMP_UDP_PCB); + /* could allocate UDP PCB? */ + if (pcb != NULL) { + /* UDP Lite: by initializing to all zeroes, chksum_len is set to 0 + * which means checksum is generated over the whole datagram per default + * (recommended as default by RFC 3828). */ + /* initialize PCB to all zeroes */ + memset(pcb, 0, sizeof(struct udp_pcb)); + pcb->ttl = UDP_TTL; + } + return pcb; +} + +#if UDP_DEBUG +/** + * Print UDP header information for debug purposes. + * + * @param udphdr pointer to the udp header in memory. + */ +void +udp_debug_print(struct udp_hdr *udphdr) +{ + LWIP_DEBUGF(UDP_DEBUG, ("UDP header:\n")); + LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n", + ntohs(udphdr->src), ntohs(udphdr->dest))); + LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | 0x%04"X16_F" | (len, chksum)\n", + ntohs(udphdr->len), ntohs(udphdr->chksum))); + LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); +} +#endif /* UDP_DEBUG */ + +#endif /* LWIP_UDP */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/ipv4/lwip/autoip.h b/component/common/network/lwip/lwip_v1.3.2/src/include/ipv4/lwip/autoip.h new file mode 100644 index 0000000..f711a61 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/ipv4/lwip/autoip.h @@ -0,0 +1,116 @@ +/** + * @file + * + * AutoIP Automatic LinkLocal IP Configuration + **/ + +/* + * + * Copyright (c) 2007 Dominik Spies + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * Author: Dominik Spies + * + * This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform + * with RFC 3927. + * + * + * Please coordinate changes and requests with Dominik Spies + * + */ + +#ifndef __LWIP_AUTOIP_H__ +#define __LWIP_AUTOIP_H__ + +#include "lwip/opt.h" + +#if LWIP_AUTOIP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/netif.h" +#include "lwip/udp.h" +#include "netif/etharp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* AutoIP Timing */ +#define AUTOIP_TMR_INTERVAL 100 +#define AUTOIP_TICKS_PER_SECOND (1000 / AUTOIP_TMR_INTERVAL) + +/* RFC 3927 Constants */ +#define PROBE_WAIT 1 /* second (initial random delay) */ +#define PROBE_MIN 1 /* second (minimum delay till repeated probe) */ +#define PROBE_MAX 2 /* seconds (maximum delay till repeated probe) */ +#define PROBE_NUM 3 /* (number of probe packets) */ +#define ANNOUNCE_NUM 2 /* (number of announcement packets) */ +#define ANNOUNCE_INTERVAL 2 /* seconds (time between announcement packets) */ +#define ANNOUNCE_WAIT 2 /* seconds (delay before announcing) */ +#define MAX_CONFLICTS 10 /* (max conflicts before rate limiting) */ +#define RATE_LIMIT_INTERVAL 60 /* seconds (delay between successive attempts) */ +#define DEFEND_INTERVAL 10 /* seconds (min. wait between defensive ARPs) */ + +/* AutoIP client states */ +#define AUTOIP_STATE_OFF 0 +#define AUTOIP_STATE_PROBING 1 +#define AUTOIP_STATE_ANNOUNCING 2 +#define AUTOIP_STATE_BOUND 3 + +struct autoip +{ + struct ip_addr llipaddr; /* the currently selected, probed, announced or used LL IP-Address */ + u8_t state; /* current AutoIP state machine state */ + u8_t sent_num; /* sent number of probes or announces, dependent on state */ + u16_t ttw; /* ticks to wait, tick is AUTOIP_TMR_INTERVAL long */ + u8_t lastconflict; /* ticks until a conflict can be solved by defending */ + u8_t tried_llipaddr; /* total number of probed/used Link Local IP-Addresses */ +}; + + +/** Init srand, has to be called before entering mainloop */ +void autoip_init(void); + +/** Start AutoIP client */ +err_t autoip_start(struct netif *netif); + +/** Stop AutoIP client */ +err_t autoip_stop(struct netif *netif); + +/** Handles every incoming ARP Packet, called by etharp_arp_input */ +void autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr); + +/** Has to be called in loop every AUTOIP_TMR_INTERVAL milliseconds */ +void autoip_tmr(void); + +/** Handle a possible change in the network configuration */ +void autoip_network_changed(struct netif *netif); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_AUTOIP */ + +#endif /* __LWIP_AUTOIP_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/ipv4/lwip/icmp.h b/component/common/network/lwip/lwip_v1.3.2/src/include/ipv4/lwip/icmp.h new file mode 100644 index 0000000..9e9faf6 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/ipv4/lwip/icmp.h @@ -0,0 +1,111 @@ +/** + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + **/ +#ifndef __LWIP_ICMP_H__ +#define __LWIP_ICMP_H__ + +#include "lwip/opt.h" +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ICMP_ER 0 /* echo reply */ +#define ICMP_DUR 3 /* destination unreachable */ +#define ICMP_SQ 4 /* source quench */ +#define ICMP_RD 5 /* redirect */ +#define ICMP_ECHO 8 /* echo */ +#define ICMP_TE 11 /* time exceeded */ +#define ICMP_PP 12 /* parameter problem */ +#define ICMP_TS 13 /* timestamp */ +#define ICMP_TSR 14 /* timestamp reply */ +#define ICMP_IRQ 15 /* information request */ +#define ICMP_IR 16 /* information reply */ + +enum icmp_dur_type { + ICMP_DUR_NET = 0, /* net unreachable */ + ICMP_DUR_HOST = 1, /* host unreachable */ + ICMP_DUR_PROTO = 2, /* protocol unreachable */ + ICMP_DUR_PORT = 3, /* port unreachable */ + ICMP_DUR_FRAG = 4, /* fragmentation needed and DF set */ + ICMP_DUR_SR = 5 /* source route failed */ +}; + +enum icmp_te_type { + ICMP_TE_TTL = 0, /* time to live exceeded in transit */ + ICMP_TE_FRAG = 1 /* fragment reassembly time exceeded */ +}; + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +/** This is the standard ICMP header only that the u32_t data + * is splitted to two u16_t like ICMP echo needs it. + * This header is also used for other ICMP types that do not + * use the data part. + */ +PACK_STRUCT_BEGIN +struct icmp_echo_hdr { + PACK_STRUCT_FIELD(u8_t type); + PACK_STRUCT_FIELD(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u16_t id); + PACK_STRUCT_FIELD(u16_t seqno); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define ICMPH_TYPE(hdr) ((hdr)->type) +#define ICMPH_CODE(hdr) ((hdr)->code) + +/** Combines type and code to an u16_t */ +#define ICMPH_TYPE_SET(hdr, t) ((hdr)->type = (t)) +#define ICMPH_CODE_SET(hdr, c) ((hdr)->code = (c)) + + +#if LWIP_ICMP /* don't build if not configured for use in lwipopts.h */ + +void icmp_input(struct pbuf *p, struct netif *inp); +void icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t); +void icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t); + +#endif /* LWIP_ICMP */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_ICMP_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/ipv4/lwip/igmp.h b/component/common/network/lwip/lwip_v1.3.2/src/include/ipv4/lwip/igmp.h new file mode 100644 index 0000000..86108ae --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/ipv4/lwip/igmp.h @@ -0,0 +1,162 @@ +/** + * Copyright (c) 2002 CITEL Technologies Ltd. + * 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 CITEL Technologies Ltd 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 CITEL TECHNOLOGIES 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 CITEL TECHNOLOGIES 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. + * + * This file is a contribution to the lwIP TCP/IP stack. + * The Swedish Institute of Computer Science and Adam Dunkels + * are specifically granted permission to redistribute this + * source code. +**/ + +#ifndef __LWIP_IGMP_H__ +#define __LWIP_IGMP_H__ + +#include "lwip/opt.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/pbuf.h" + +#if LWIP_IGMP /* don't build if not configured for use in lwipopts.h */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * IGMP constants + */ +#define IP_PROTO_IGMP 2 +#define IGMP_TTL 1 +#define IGMP_MINLEN 8 +#define ROUTER_ALERT 0x9404 +#define ROUTER_ALERTLEN 4 + +/* + * IGMP message types, including version number. + */ +#define IGMP_MEMB_QUERY 0x11 /* Membership query */ +#define IGMP_V1_MEMB_REPORT 0x12 /* Ver. 1 membership report */ +#define IGMP_V2_MEMB_REPORT 0x16 /* Ver. 2 membership report */ +#define IGMP_LEAVE_GROUP 0x17 /* Leave-group message */ + +/* IGMP timer */ +#define IGMP_TMR_INTERVAL 100 /* Milliseconds */ +#define IGMP_V1_DELAYING_MEMBER_TMR (1000/IGMP_TMR_INTERVAL) +#define IGMP_JOIN_DELAYING_MEMBER_TMR (500 /IGMP_TMR_INTERVAL) + +/* MAC Filter Actions */ +#define IGMP_DEL_MAC_FILTER 0 +#define IGMP_ADD_MAC_FILTER 1 + +/* Group membership states */ +#define IGMP_GROUP_NON_MEMBER 0 +#define IGMP_GROUP_DELAYING_MEMBER 1 +#define IGMP_GROUP_IDLE_MEMBER 2 + +/* + * IGMP packet format. + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct igmp_msg { + PACK_STRUCT_FIELD(u8_t igmp_msgtype); + PACK_STRUCT_FIELD(u8_t igmp_maxresp); + PACK_STRUCT_FIELD(u16_t igmp_checksum); + PACK_STRUCT_FIELD(struct ip_addr igmp_group_address); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* + * now a group structure - there is + * a list of groups for each interface + * these should really be linked from the interface, but + * if we keep them separate we will not affect the lwip original code + * too much + * + * There will be a group for the all systems group address but this + * will not run the state machine as it is used to kick off reports + * from all the other groups + */ + +struct igmp_group { + struct igmp_group *next; + struct netif *interface; + struct ip_addr group_address; + u8_t last_reporter_flag; /* signifies we were the last person to report */ + u8_t group_state; + u16_t timer; + u8_t use; /* counter of simultaneous uses */ +}; + + +/* Prototypes */ +void igmp_init(void); + +err_t igmp_start( struct netif *netif); + +err_t igmp_stop( struct netif *netif); + +void igmp_report_groups( struct netif *netif); + +struct igmp_group *igmp_lookfor_group( struct netif *ifp, struct ip_addr *addr); + +struct igmp_group *igmp_lookup_group( struct netif *ifp, struct ip_addr *addr); + +err_t igmp_remove_group( struct igmp_group *group); + +void igmp_input( struct pbuf *p, struct netif *inp, struct ip_addr *dest); + +err_t igmp_joingroup( struct ip_addr *ifaddr, struct ip_addr *groupaddr); + +err_t igmp_leavegroup( struct ip_addr *ifaddr, struct ip_addr *groupaddr); + +void igmp_tmr(void); + +void igmp_timeout( struct igmp_group *group); + +void igmp_start_timer( struct igmp_group *group, u8_t max_time); + +void igmp_stop_timer( struct igmp_group *group); + +void igmp_delaying_member( struct igmp_group *group, u8_t maxresp); + +err_t igmp_ip_output_if( struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, u8_t ttl, u8_t proto, struct netif *netif); + +void igmp_send( struct igmp_group *group, u8_t type); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IGMP */ + +#endif /* __LWIP_IGMP_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/ipv4/lwip/inet.h b/component/common/network/lwip/lwip_v1.3.2/src/include/ipv4/lwip/inet.h new file mode 100644 index 0000000..6f259c7 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/ipv4/lwip/inet.h @@ -0,0 +1,103 @@ +/** + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_INET_H__ +#define __LWIP_INET_H__ + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* For compatibility with BSD code */ +struct in_addr { + u32_t s_addr; +}; + +#define INADDR_NONE ((u32_t)0xffffffffUL) /* 255.255.255.255 */ +#define INADDR_LOOPBACK ((u32_t)0x7f000001UL) /* 127.0.0.1 */ +#define INADDR_ANY ((u32_t)0x00000000UL) /* 0.0.0.0 */ +#define INADDR_BROADCAST ((u32_t)0xffffffffUL) /* 255.255.255.255 */ + +u32_t inet_addr(const char *cp); +int inet_aton(const char *cp, struct in_addr *addr); +char *inet_ntoa(struct in_addr addr); /* returns ptr to static buffer; not reentrant! */ + +#ifdef htons +#undef htons +#endif /* htons */ +#ifdef htonl +#undef htonl +#endif /* htonl */ +#ifdef ntohs +#undef ntohs +#endif /* ntohs */ +#ifdef ntohl +#undef ntohl +#endif /* ntohl */ + +#ifndef LWIP_PLATFORM_BYTESWAP +#define LWIP_PLATFORM_BYTESWAP 0 +#endif + +#if BYTE_ORDER == BIG_ENDIAN +#define htons(x) (x) +#define ntohs(x) (x) +#define htonl(x) (x) +#define ntohl(x) (x) +#else /* BYTE_ORDER != BIG_ENDIAN */ +#ifdef LWIP_PREFIX_BYTEORDER_FUNCS +/* workaround for naming collisions on some platforms */ +#define htons lwip_htons +#define ntohs lwip_ntohs +#define htonl lwip_htonl +#define ntohl lwip_ntohl +#endif /* LWIP_PREFIX_BYTEORDER_FUNCS */ +#if LWIP_PLATFORM_BYTESWAP +#define htons(x) LWIP_PLATFORM_HTONS(x) +#define ntohs(x) LWIP_PLATFORM_HTONS(x) +#define htonl(x) LWIP_PLATFORM_HTONL(x) +#define ntohl(x) LWIP_PLATFORM_HTONL(x) +#else /* LWIP_PLATFORM_BYTESWAP */ +u16_t htons(u16_t x); +u16_t ntohs(u16_t x); +u32_t htonl(u32_t x); +u32_t ntohl(u32_t x); +#endif /* LWIP_PLATFORM_BYTESWAP */ + +#endif /* BYTE_ORDER == BIG_ENDIAN */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_INET_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/ipv4/lwip/inet_chksum.h b/component/common/network/lwip/lwip_v1.3.2/src/include/ipv4/lwip/inet_chksum.h new file mode 100644 index 0000000..ba64ce8 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/ipv4/lwip/inet_chksum.h @@ -0,0 +1,60 @@ +/** + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + **/ +#ifndef __LWIP_INET_CHKSUM_H__ +#define __LWIP_INET_CHKSUM_H__ + +#include "lwip/opt.h" + +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +u16_t inet_chksum(void *dataptr, u16_t len); +u16_t inet_chksum_pbuf(struct pbuf *p); +u16_t inet_chksum_pseudo(struct pbuf *p, + struct ip_addr *src, struct ip_addr *dest, + u8_t proto, u16_t proto_len); +#if LWIP_UDPLITE +u16_t inet_chksum_pseudo_partial(struct pbuf *p, + struct ip_addr *src, struct ip_addr *dest, + u8_t proto, u16_t proto_len, u16_t chksum_len); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_INET_H__ */ + diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/ipv4/lwip/ip.h b/component/common/network/lwip/lwip_v1.3.2/src/include/ipv4/lwip/ip.h new file mode 100644 index 0000000..fbf5a22 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/ipv4/lwip/ip.h @@ -0,0 +1,198 @@ +/** + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_IP_H__ +#define __LWIP_IP_H__ + +#include "lwip/opt.h" + +#include "lwip/def.h" +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" +#include "lwip/err.h" +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Currently, the function ip_output_if_opt() is only used with IGMP */ +#define IP_OPTIONS_SEND LWIP_IGMP + +#define IP_HLEN 20 + +#define IP_PROTO_ICMP 1 +#define IP_PROTO_UDP 17 +#define IP_PROTO_UDPLITE 136 +#define IP_PROTO_TCP 6 + +/* This is passed as the destination address to ip_output_if (not + to ip_output), meaning that an IP header already is constructed + in the pbuf. This is used when TCP retransmits. */ +#ifdef IP_HDRINCL +#undef IP_HDRINCL +#endif /* IP_HDRINCL */ +#define IP_HDRINCL NULL + +#if LWIP_NETIF_HWADDRHINT +#define IP_PCB_ADDRHINT ;u8_t addr_hint +#else +#define IP_PCB_ADDRHINT +#endif /* LWIP_NETIF_HWADDRHINT */ + +/* This is the common part of all PCB types. It needs to be at the + beginning of a PCB type definition. It is located here so that + changes to this common part are made in one location instead of + having to change all PCB structs. */ +#define IP_PCB \ + /* ip addresses in network byte order */ \ + struct ip_addr local_ip; \ + struct ip_addr remote_ip; \ + /* Socket options */ \ + u16_t so_options; \ + /* Type Of Service */ \ + u8_t tos; \ + /* Time To Live */ \ + u8_t ttl \ + /* link layer address resolution hint */ \ + IP_PCB_ADDRHINT + +struct ip_pcb { +/* Common members of all PCB types */ + IP_PCB; +}; + +/* + * Option flags per-socket. These are the same like SO_XXX. + */ +#define SOF_DEBUG (u16_t)0x0001U /* turn on debugging info recording */ +#define SOF_ACCEPTCONN (u16_t)0x0002U /* socket has had listen() */ +#define SOF_REUSEADDR (u16_t)0x0004U /* allow local address reuse */ +#define SOF_KEEPALIVE (u16_t)0x0008U /* keep connections alive */ +#define SOF_DONTROUTE (u16_t)0x0010U /* just use interface addresses */ +#define SOF_BROADCAST (u16_t)0x0020U /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */ +#define SOF_USELOOPBACK (u16_t)0x0040U /* bypass hardware when possible */ +#define SOF_LINGER (u16_t)0x0080U /* linger on close if data present */ +#define SOF_OOBINLINE (u16_t)0x0100U /* leave received OOB data in line */ +#define SOF_REUSEPORT (u16_t)0x0200U /* allow local address & port reuse */ + + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip_hdr { + /* version / header length / type of service */ + PACK_STRUCT_FIELD(u16_t _v_hl_tos); + /* total length */ + PACK_STRUCT_FIELD(u16_t _len); + /* identification */ + PACK_STRUCT_FIELD(u16_t _id); + /* fragment offset field */ + PACK_STRUCT_FIELD(u16_t _offset); +#define IP_RF 0x8000 /* reserved fragment flag */ +#define IP_DF 0x4000 /* dont fragment flag */ +#define IP_MF 0x2000 /* more fragments flag */ +#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ + /* time to live / protocol*/ + PACK_STRUCT_FIELD(u16_t _ttl_proto); + /* checksum */ + PACK_STRUCT_FIELD(u16_t _chksum); + /* source and destination IP addresses */ + PACK_STRUCT_FIELD(struct ip_addr src); + PACK_STRUCT_FIELD(struct ip_addr dest); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define IPH_V(hdr) (ntohs((hdr)->_v_hl_tos) >> 12) +#define IPH_HL(hdr) ((ntohs((hdr)->_v_hl_tos) >> 8) & 0x0f) +#define IPH_TOS(hdr) (ntohs((hdr)->_v_hl_tos) & 0xff) +#define IPH_LEN(hdr) ((hdr)->_len) +#define IPH_ID(hdr) ((hdr)->_id) +#define IPH_OFFSET(hdr) ((hdr)->_offset) +#define IPH_TTL(hdr) (ntohs((hdr)->_ttl_proto) >> 8) +#define IPH_PROTO(hdr) (ntohs((hdr)->_ttl_proto) & 0xff) +#define IPH_CHKSUM(hdr) ((hdr)->_chksum) + +#define IPH_VHLTOS_SET(hdr, v, hl, tos) (hdr)->_v_hl_tos = (htons(((v) << 12) | ((hl) << 8) | (tos))) +#define IPH_LEN_SET(hdr, len) (hdr)->_len = (len) +#define IPH_ID_SET(hdr, id) (hdr)->_id = (id) +#define IPH_OFFSET_SET(hdr, off) (hdr)->_offset = (off) +#define IPH_TTL_SET(hdr, ttl) (hdr)->_ttl_proto = (htons(IPH_PROTO(hdr) | ((u16_t)(ttl) << 8))) +#define IPH_PROTO_SET(hdr, proto) (hdr)->_ttl_proto = (htons((proto) | (IPH_TTL(hdr) << 8))) +#define IPH_CHKSUM_SET(hdr, chksum) (hdr)->_chksum = (chksum) + +/** The interface that provided the packet for the current callback invocation. */ +extern struct netif *current_netif; +/** Header of the input packet currently being processed. */ +extern const struct ip_hdr *current_header; + +#define ip_init() /* Compatibility define, not init needed. */ +struct netif *ip_route(struct ip_addr *dest); +err_t ip_input(struct pbuf *p, struct netif *inp); +err_t ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, + u8_t ttl, u8_t tos, u8_t proto); +err_t ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, + u8_t ttl, u8_t tos, u8_t proto, + struct netif *netif); +#if LWIP_NETIF_HWADDRHINT +err_t ip_output_hinted(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, + u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint); +#endif /* LWIP_NETIF_HWADDRHINT */ +#if IP_OPTIONS_SEND +err_t ip_output_if_opt(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, + u16_t optlen); +#endif /* IP_OPTIONS_SEND */ +/** Get the interface that received the current packet. + * This function must only be called from a receive callback (udp_recv, + * raw_recv, tcp_accept). It will return NULL otherwise. */ +#define ip_current_netif() (current_netif) +/** Get the IP header of the current packet. + * This function must only be called from a receive callback (udp_recv, + * raw_recv, tcp_accept). It will return NULL otherwise. */ +#define ip_current_header() (current_header) +#if IP_DEBUG +void ip_debug_print(struct pbuf *p); +#else +#define ip_debug_print(p) +#endif /* IP_DEBUG */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_IP_H__ */ + + diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/ipv4/lwip/ip_addr.h b/component/common/network/lwip/lwip_v1.3.2/src/include/ipv4/lwip/ip_addr.h new file mode 100644 index 0000000..2fcccc2 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/ipv4/lwip/ip_addr.h @@ -0,0 +1,173 @@ +/** + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + **/ +#ifndef __LWIP_IP_ADDR_H__ +#define __LWIP_IP_ADDR_H__ + +#include "lwip/opt.h" + +#include "lwip/inet.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip_addr { + PACK_STRUCT_FIELD(u32_t addr); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* + * struct ipaddr2 is used in the definition of the ARP packet format in + * order to support compilers that don't have structure packing. + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip_addr2 { + PACK_STRUCT_FIELD(u16_t addrw[2]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +struct netif; + +extern const struct ip_addr ip_addr_any; +extern const struct ip_addr ip_addr_broadcast; + +/** IP_ADDR_ can be used as a fixed IP address + * for the wildcard and the broadcast address + */ +#define IP_ADDR_ANY ((struct ip_addr *)&ip_addr_any) +#define IP_ADDR_BROADCAST ((struct ip_addr *)&ip_addr_broadcast) + +/* Definitions of the bits in an Internet address integer. + + On subnets, host and network parts are found according to + the subnet mask, not these masks. */ + +#define IN_CLASSA(a) ((((u32_t)(a)) & 0x80000000UL) == 0) +#define IN_CLASSA_NET 0xff000000 +#define IN_CLASSA_NSHIFT 24 +#define IN_CLASSA_HOST (0xffffffff & ~IN_CLASSA_NET) +#define IN_CLASSA_MAX 128 + +#define IN_CLASSB(a) ((((u32_t)(a)) & 0xc0000000UL) == 0x80000000UL) +#define IN_CLASSB_NET 0xffff0000 +#define IN_CLASSB_NSHIFT 16 +#define IN_CLASSB_HOST (0xffffffff & ~IN_CLASSB_NET) +#define IN_CLASSB_MAX 65536 + +#define IN_CLASSC(a) ((((u32_t)(a)) & 0xe0000000UL) == 0xc0000000UL) +#define IN_CLASSC_NET 0xffffff00 +#define IN_CLASSC_NSHIFT 8 +#define IN_CLASSC_HOST (0xffffffff & ~IN_CLASSC_NET) + +#define IN_CLASSD(a) (((u32_t)(a) & 0xf0000000UL) == 0xe0000000UL) +#define IN_CLASSD_NET 0xf0000000 /* These ones aren't really */ +#define IN_CLASSD_NSHIFT 28 /* net and host fields, but */ +#define IN_CLASSD_HOST 0x0fffffff /* routing needn't know. */ +#define IN_MULTICAST(a) IN_CLASSD(a) + +#define IN_EXPERIMENTAL(a) (((u32_t)(a) & 0xf0000000UL) == 0xf0000000UL) +#define IN_BADCLASS(a) (((u32_t)(a) & 0xf0000000UL) == 0xf0000000UL) + +#define IN_LOOPBACKNET 127 /* official! */ + +#define IP4_ADDR(ipaddr, a,b,c,d) \ + (ipaddr)->addr = htonl(((u32_t)((a) & 0xff) << 24) | \ + ((u32_t)((b) & 0xff) << 16) | \ + ((u32_t)((c) & 0xff) << 8) | \ + (u32_t)((d) & 0xff)) + +#define ip_addr_set(dest, src) (dest)->addr = \ + ((src) == NULL? 0:\ + (src)->addr) +/** + * Determine if two address are on the same network. + * + * @arg addr1 IP address 1 + * @arg addr2 IP address 2 + * @arg mask network identifier mask + * @return !0 if the network identifiers of both address match + */ +#define ip_addr_netcmp(addr1, addr2, mask) (((addr1)->addr & \ + (mask)->addr) == \ + ((addr2)->addr & \ + (mask)->addr)) +#define ip_addr_cmp(addr1, addr2) ((addr1)->addr == (addr2)->addr) + +#define ip_addr_isany(addr1) ((addr1) == NULL || (addr1)->addr == 0) + +u8_t ip_addr_isbroadcast(struct ip_addr *, struct netif *); + +#define ip_addr_ismulticast(addr1) (((addr1)->addr & ntohl(0xf0000000UL)) == ntohl(0xe0000000UL)) + +#define ip_addr_islinklocal(addr1) (((addr1)->addr & ntohl(0xffff0000UL)) == ntohl(0xa9fe0000UL)) + +#define ip_addr_debug_print(debug, ipaddr) \ + LWIP_DEBUGF(debug, ("%"U16_F".%"U16_F".%"U16_F".%"U16_F, \ + ipaddr != NULL ? \ + (u16_t)(ntohl((ipaddr)->addr) >> 24) & 0xff : 0, \ + ipaddr != NULL ? \ + (u16_t)(ntohl((ipaddr)->addr) >> 16) & 0xff : 0, \ + ipaddr != NULL ? \ + (u16_t)(ntohl((ipaddr)->addr) >> 8) & 0xff : 0, \ + ipaddr != NULL ? \ + (u16_t)ntohl((ipaddr)->addr) & 0xff : 0)) + +/* These are cast to u16_t, with the intent that they are often arguments + * to printf using the U16_F format from cc.h. */ +#define ip4_addr1(ipaddr) ((u16_t)(ntohl((ipaddr)->addr) >> 24) & 0xff) +#define ip4_addr2(ipaddr) ((u16_t)(ntohl((ipaddr)->addr) >> 16) & 0xff) +#define ip4_addr3(ipaddr) ((u16_t)(ntohl((ipaddr)->addr) >> 8) & 0xff) +#define ip4_addr4(ipaddr) ((u16_t)(ntohl((ipaddr)->addr)) & 0xff) + +/** + * Same as inet_ntoa() but takes a struct ip_addr* + */ +#define ip_ntoa(addr) ((addr != NULL) ? inet_ntoa(*((struct in_addr*)(addr))) : "NULL") + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_IP_ADDR_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/ipv4/lwip/ip_frag.h b/component/common/network/lwip/lwip_v1.3.2/src/include/ipv4/lwip/ip_frag.h new file mode 100644 index 0000000..ee18728 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/ipv4/lwip/ip_frag.h @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Jani Monoses + * + **/ + +#ifndef __LWIP_IP_FRAG_H__ +#define __LWIP_IP_FRAG_H__ + +#include "lwip/opt.h" +#include "lwip/err.h" +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/ip_addr.h" +#include "lwip/ip.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if IP_REASSEMBLY +/* The IP reassembly timer interval in milliseconds. */ +#define IP_TMR_INTERVAL 1000 + +/* IP reassembly helper struct. + * This is exported because memp needs to know the size. + */ +struct ip_reassdata { + struct ip_reassdata *next; + struct pbuf *p; + struct ip_hdr iphdr; + u16_t datagram_len; + u8_t flags; + u8_t timer; +}; + +void ip_reass_init(void); +void ip_reass_tmr(void); +struct pbuf * ip_reass(struct pbuf *p); +#endif /* IP_REASSEMBLY */ + +#if IP_FRAG +err_t ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest); +#endif /* IP_FRAG */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_IP_FRAG_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/ipv6/lwip/icmp.h b/component/common/network/lwip/lwip_v1.3.2/src/include/ipv6/lwip/icmp.h new file mode 100644 index 0000000..87e9ffd --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/ipv6/lwip/icmp.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_ICMP_H__ +#define __LWIP_ICMP_H__ + +#include "lwip/opt.h" + +#if LWIP_ICMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ICMP6_DUR 1 +#define ICMP6_TE 3 +#define ICMP6_ECHO 128 /* echo */ +#define ICMP6_ER 129 /* echo reply */ + + +enum icmp_dur_type { + ICMP_DUR_NET = 0, /* net unreachable */ + ICMP_DUR_HOST = 1, /* host unreachable */ + ICMP_DUR_PROTO = 2, /* protocol unreachable */ + ICMP_DUR_PORT = 3, /* port unreachable */ + ICMP_DUR_FRAG = 4, /* fragmentation needed and DF set */ + ICMP_DUR_SR = 5 /* source route failed */ +}; + +enum icmp_te_type { + ICMP_TE_TTL = 0, /* time to live exceeded in transit */ + ICMP_TE_FRAG = 1 /* fragment reassembly time exceeded */ +}; + +void icmp_input(struct pbuf *p, struct netif *inp); + +void icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t); +void icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t); + +struct icmp_echo_hdr { + u8_t type; + u8_t icode; + u16_t chksum; + u16_t id; + u16_t seqno; +}; + +struct icmp_dur_hdr { + u8_t type; + u8_t icode; + u16_t chksum; + u32_t unused; +}; + +struct icmp_te_hdr { + u8_t type; + u8_t icode; + u16_t chksum; + u32_t unused; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_ICMP */ + +#endif /* __LWIP_ICMP_H__ */ + diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/ipv6/lwip/inet.h b/component/common/network/lwip/lwip_v1.3.2/src/include/ipv6/lwip/inet.h new file mode 100644 index 0000000..de1a0b6 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/ipv6/lwip/inet.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_INET_H__ +#define __LWIP_INET_H__ + +#include "lwip/opt.h" +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +u16_t inet_chksum(void *data, u16_t len); +u16_t inet_chksum_pbuf(struct pbuf *p); +u16_t inet_chksum_pseudo(struct pbuf *p, + struct ip_addr *src, struct ip_addr *dest, + u8_t proto, u32_t proto_len); + +u32_t inet_addr(const char *cp); +s8_t inet_aton(const char *cp, struct in_addr *addr); + +#ifndef _MACHINE_ENDIAN_H_ +#ifndef _NETINET_IN_H +#ifndef _LINUX_BYTEORDER_GENERIC_H +u16_t htons(u16_t n); +u16_t ntohs(u16_t n); +u32_t htonl(u32_t n); +u32_t ntohl(u32_t n); +#endif /* _LINUX_BYTEORDER_GENERIC_H */ +#endif /* _NETINET_IN_H */ +#endif /* _MACHINE_ENDIAN_H_ */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_INET_H__ */ + diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/ipv6/lwip/ip.h b/component/common/network/lwip/lwip_v1.3.2/src/include/ipv6/lwip/ip.h new file mode 100644 index 0000000..a01cfc6 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/ipv6/lwip/ip.h @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_IP_H__ +#define __LWIP_IP_H__ + +#include "lwip/opt.h" +#include "lwip/def.h" +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" + +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define IP_HLEN 40 + +#define IP_PROTO_ICMP 58 +#define IP_PROTO_UDP 17 +#define IP_PROTO_UDPLITE 136 +#define IP_PROTO_TCP 6 + +/* This is passed as the destination address to ip_output_if (not + to ip_output), meaning that an IP header already is constructed + in the pbuf. This is used when TCP retransmits. */ +#ifdef IP_HDRINCL +#undef IP_HDRINCL +#endif /* IP_HDRINCL */ +#define IP_HDRINCL NULL + +#if LWIP_NETIF_HWADDRHINT +#define IP_PCB_ADDRHINT ;u8_t addr_hint +#else +#define IP_PCB_ADDRHINT +#endif /* LWIP_NETIF_HWADDRHINT */ + +/* This is the common part of all PCB types. It needs to be at the + beginning of a PCB type definition. It is located here so that + changes to this common part are made in one location instead of + having to change all PCB structs. */ +#define IP_PCB struct ip_addr local_ip; \ + struct ip_addr remote_ip; \ + /* Socket options */ \ + u16_t so_options; \ + /* Type Of Service */ \ + u8_t tos; \ + /* Time To Live */ \ + u8_t ttl; \ + /* link layer address resolution hint */ \ + IP_PCB_ADDRHINT + + +/* The IPv6 header. */ +struct ip_hdr { +#if BYTE_ORDER == LITTLE_ENDIAN + u8_t tclass1:4, v:4; + u8_t flow1:4, tclass2:4; +#else + u8_t v:4, tclass1:4; + u8_t tclass2:8, flow1:4; +#endif + u16_t flow2; + u16_t len; /* payload length */ + u8_t nexthdr; /* next header */ + u8_t hoplim; /* hop limit (TTL) */ + struct ip_addr src, dest; /* source and destination IP addresses */ +}; + +#define IPH_PROTO(hdr) (iphdr->nexthdr) + +void ip_init(void); + +#include "lwip/netif.h" + +struct netif *ip_route(struct ip_addr *dest); + +void ip_input(struct pbuf *p, struct netif *inp); + +/* source and destination addresses in network byte order, please */ +err_t ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, + u8_t ttl, u8_t proto); + +err_t ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, + u8_t ttl, u8_t proto, + struct netif *netif); + +#define ip_current_netif() NULL +#define ip_current_header() NULL + +#if IP_DEBUG +void ip_debug_print(struct pbuf *p); +#endif /* IP_DEBUG */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_IP_H__ */ + + diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/ipv6/lwip/ip_addr.h b/component/common/network/lwip/lwip_v1.3.2/src/include/ipv6/lwip/ip_addr.h new file mode 100644 index 0000000..b2d8ae5 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/ipv6/lwip/ip_addr.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_IP_ADDR_H__ +#define __LWIP_IP_ADDR_H__ + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define IP_ADDR_ANY 0 + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN + struct ip_addr { + PACK_STRUCT_FIELD(u32_t addr[4]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* + * struct ipaddr2 is used in the definition of the ARP packet format in + * order to support compilers that don't have structure packing. + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip_addr2 { + PACK_STRUCT_FIELD(u16_t addrw[2]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define IP6_ADDR(ipaddr, a,b,c,d,e,f,g,h) do { (ipaddr)->addr[0] = htonl((u32_t)((a & 0xffff) << 16) | (b & 0xffff)); \ + (ipaddr)->addr[1] = htonl(((c & 0xffff) << 16) | (d & 0xffff)); \ + (ipaddr)->addr[2] = htonl(((e & 0xffff) << 16) | (f & 0xffff)); \ + (ipaddr)->addr[3] = htonl(((g & 0xffff) << 16) | (h & 0xffff)); } while(0) + +u8_t ip_addr_netcmp(struct ip_addr *addr1, struct ip_addr *addr2, + struct ip_addr *mask); +u8_t ip_addr_cmp(struct ip_addr *addr1, struct ip_addr *addr2); +void ip_addr_set(struct ip_addr *dest, struct ip_addr *src); +u8_t ip_addr_isany(struct ip_addr *addr); + +#define ip_addr_debug_print(debug, ipaddr) \ + LWIP_DEBUGF(debug, ("%"X32_F":%"X32_F":%"X32_F":%"X32_F":%"X32_F":%"X32_F":%"X32_F":%"X32_F"\n", \ + (ntohl(ipaddr->addr[0]) >> 16) & 0xffff, \ + ntohl(ipaddr->addr[0]) & 0xffff, \ + (ntohl(ipaddr->addr[1]) >> 16) & 0xffff, \ + ntohl(ipaddr->addr[1]) & 0xffff, \ + (ntohl(ipaddr->addr[2]) >> 16) & 0xffff, \ + ntohl(ipaddr->addr[2]) & 0xffff, \ + (ntohl(ipaddr->addr[3]) >> 16) & 0xffff, \ + ntohl(ipaddr->addr[3]) & 0xffff)); + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_IP_ADDR_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/api.h b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/api.h new file mode 100644 index 0000000..eec83bd --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/api.h @@ -0,0 +1,229 @@ +/** + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + **/ +#ifndef __LWIP_API_H__ +#define __LWIP_API_H__ + +#include "lwip/opt.h" + +#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ + +#include /* for size_t */ + +#include "lwip/netbuf.h" +#include "lwip/sys.h" +#include "lwip/ip_addr.h" +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Evan add for port netconn api +#define port_netconn_recv(conn , buf, ret) do{buf = netconn_recv(conn);}while(0); +#define port_netconn_accept(conn , newconn, ret) do{newconn = netconn_accept(conn);}while(0); +// Evan add end + +/* Throughout this file, IP addresses and port numbers are expected to be in + * the same byte order as in the corresponding pcb. + */ + +/* Flags for netconn_write */ +#define NETCONN_NOFLAG 0x00 +#define NETCONN_NOCOPY 0x00 /* Only for source code compatibility */ +#define NETCONN_COPY 0x01 +#define NETCONN_MORE 0x02 + +/* Helpers to process several netconn_types by the same code */ +#define NETCONNTYPE_GROUP(t) (t&0xF0) +#define NETCONNTYPE_DATAGRAM(t) (t&0xE0) + +enum netconn_type { + NETCONN_INVALID = 0, + /* NETCONN_TCP Group */ + NETCONN_TCP = 0x10, + /* NETCONN_UDP Group */ + NETCONN_UDP = 0x20, + NETCONN_UDPLITE = 0x21, + NETCONN_UDPNOCHKSUM= 0x22, + /* NETCONN_RAW Group */ + NETCONN_RAW = 0x40 +}; + +enum netconn_state { + NETCONN_NONE, + NETCONN_WRITE, + NETCONN_LISTEN, + NETCONN_CONNECT, + NETCONN_CLOSE +}; + +enum netconn_evt { + NETCONN_EVT_RCVPLUS, + NETCONN_EVT_RCVMINUS, + NETCONN_EVT_SENDPLUS, + NETCONN_EVT_SENDMINUS +}; + +#if LWIP_IGMP +enum netconn_igmp { + NETCONN_JOIN, + NETCONN_LEAVE +}; +#endif /* LWIP_IGMP */ + +/* forward-declare some structs to avoid to include their headers */ +struct ip_pcb; +struct tcp_pcb; +struct udp_pcb; +struct raw_pcb; +struct netconn; + +/** A callback prototype to inform about events for a netconn */ +typedef void (* netconn_callback)(struct netconn *, enum netconn_evt, u16_t len); + +/** A netconn descriptor */ +struct netconn { + /** type of the netconn (TCP, UDP or RAW) */ + enum netconn_type type; + /** current state of the netconn */ + enum netconn_state state; + /** the lwIP internal protocol control block */ + union { + struct ip_pcb *ip; + struct tcp_pcb *tcp; + struct udp_pcb *udp; + struct raw_pcb *raw; + } pcb; + /** the last error this netconn had */ + err_t err; + /** sem that is used to synchroneously execute functions in the core context */ + sys_sem_t op_completed; + /** mbox where received packets are stored until they are fetched + by the netconn application thread (can grow quite big) */ + sys_mbox_t recvmbox; + /** mbox where new connections are stored until processed + by the application thread */ + sys_mbox_t acceptmbox; + /** only used for socket layer */ + int socket; +#if LWIP_SO_RCVTIMEO + /** timeout to wait for new data to be received + (or connections to arrive for listening netconns) */ + int recv_timeout; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + /** maximum amount of bytes queued in recvmbox */ + int recv_bufsize; +#endif /* LWIP_SO_RCVBUF */ + s16_t recv_avail; +#if LWIP_TCP + /** TCP: when data passed to netconn_write doesn't fit into the send buffer, + this temporarily stores the message. */ + struct api_msg_msg *write_msg; + /** TCP: when data passed to netconn_write doesn't fit into the send buffer, + this temporarily stores how much is already sent. */ + size_t write_offset; +#if LWIP_TCPIP_CORE_LOCKING + /** TCP: when data passed to netconn_write doesn't fit into the send buffer, + this temporarily stores whether to wake up the original application task + if data couldn't be sent in the first try. */ + u8_t write_delayed; +#endif /* LWIP_TCPIP_CORE_LOCKING */ +#endif /* LWIP_TCP */ + /** A callback function that is informed about events for this netconn */ + netconn_callback callback; +}; + +/* Register an Network connection event */ +#define API_EVENT(c,e,l) if (c->callback) { \ + (*c->callback)(c, e, l); \ + } + +/* Network connection functions: */ +#define netconn_new(t) netconn_new_with_proto_and_callback(t, 0, NULL) +#define netconn_new_with_callback(t, c) netconn_new_with_proto_and_callback(t, 0, c) +struct +netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, + netconn_callback callback); +err_t netconn_delete (struct netconn *conn); +/** Get the type of a netconn (as enum netconn_type). */ +#define netconn_type(conn) (conn->type) + +err_t netconn_getaddr (struct netconn *conn, + struct ip_addr *addr, + u16_t *port, + u8_t local); +#define netconn_peer(c,i,p) netconn_getaddr(c,i,p,0) +#define netconn_addr(c,i,p) netconn_getaddr(c,i,p,1) + +err_t netconn_bind (struct netconn *conn, + struct ip_addr *addr, + u16_t port); +err_t netconn_connect (struct netconn *conn, + struct ip_addr *addr, + u16_t port); +err_t netconn_disconnect (struct netconn *conn); +err_t netconn_listen_with_backlog(struct netconn *conn, u8_t backlog); +#define netconn_listen(conn) netconn_listen_with_backlog(conn, TCP_DEFAULT_LISTEN_BACKLOG) +struct netconn * netconn_accept (struct netconn *conn); +struct netbuf * netconn_recv (struct netconn *conn); +err_t netconn_sendto (struct netconn *conn, + struct netbuf *buf, struct ip_addr *addr, u16_t port); +err_t netconn_send (struct netconn *conn, + struct netbuf *buf); +err_t netconn_write (struct netconn *conn, + const void *dataptr, size_t size, + u8_t apiflags); +err_t netconn_close (struct netconn *conn); + +err_t netconn_abort(struct netconn *conn); + +#if LWIP_IGMP +err_t netconn_join_leave_group (struct netconn *conn, + struct ip_addr *multiaddr, + struct ip_addr *interface, + enum netconn_igmp join_or_leave); +#endif /* LWIP_IGMP */ +#if LWIP_DNS +err_t netconn_gethostbyname(const char *name, struct ip_addr *addr); +#endif /* LWIP_DNS */ + +#define netconn_err(conn) ((conn)->err) +#define netconn_recv_bufsize(conn) ((conn)->recv_bufsize) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_NETCONN */ + +#endif /* __LWIP_API_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/api_msg.h b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/api_msg.h new file mode 100644 index 0000000..a1e1924 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/api_msg.h @@ -0,0 +1,162 @@ +/** + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + **/ +#ifndef __LWIP_API_MSG_H__ +#define __LWIP_API_MSG_H__ + +#include "lwip/opt.h" + +#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ + +#include /* for size_t */ + +#include "lwip/ip_addr.h" +#include "lwip/err.h" +#include "lwip/sys.h" +#include "lwip/igmp.h" +#include "lwip/api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* IP addresses and port numbers are expected to be in + * the same byte order as in the corresponding pcb. + */ +/** This struct includes everything that is necessary to execute a function + for a netconn in another thread context (mainly used to process netconns + in the tcpip_thread context to be thread safe). */ +struct api_msg_msg { + /** The netconn which to process - always needed: it includes the semaphore + which is used to block the application thread until the function finished. */ + struct netconn *conn; + /** Depending on the executed function, one of these union members is used */ + union { + /** used for do_send */ + struct netbuf *b; + /** used for do_newconn */ + struct { + u8_t proto; + } n; + /** used for do_bind and do_connect */ + struct { + struct ip_addr *ipaddr; + u16_t port; + } bc; + /** used for do_getaddr */ + struct { + struct ip_addr *ipaddr; + u16_t *port; + u8_t local; + } ad; + /** used for do_write */ + struct { + const void *dataptr; + size_t len; + u8_t apiflags; + } w; + /** used for do_recv */ + struct { + u16_t len; + } r; +#if LWIP_IGMP + /** used for do_join_leave_group */ + struct { + struct ip_addr *multiaddr; + struct ip_addr *interface; + enum netconn_igmp join_or_leave; + } jl; +#endif /* LWIP_IGMP */ +#if TCP_LISTEN_BACKLOG + struct { + u8_t backlog; + } lb; +#endif /* TCP_LISTEN_BACKLOG */ + } msg; +}; + +/** This struct contains a function to execute in another thread context and + a struct api_msg_msg that serves as an argument for this function. + This is passed to tcpip_apimsg to execute functions in tcpip_thread context. */ +struct api_msg { + /** function to execute in tcpip_thread context */ + void (* function)(struct api_msg_msg *msg); + /** arguments for this function */ + struct api_msg_msg msg; +}; + +#if LWIP_DNS +/** As do_gethostbyname requires more arguments but doesn't require a netconn, + it has its own struct (to avoid struct api_msg getting bigger than necessary). + do_gethostbyname must be called using tcpip_callback instead of tcpip_apimsg + (see netconn_gethostbyname). */ +struct dns_api_msg { + /** Hostname to query or dotted IP address string */ + const char *name; + /** Rhe resolved address is stored here */ + struct ip_addr *addr; + /** This semaphore is posted when the name is resolved, the application thread + should wait on it. */ + sys_sem_t sem; + /** Errors are given back here */ + err_t *err; +}; +#endif /* LWIP_DNS */ + +void do_newconn ( struct api_msg_msg *msg); +void do_delconn ( struct api_msg_msg *msg); +void do_bind ( struct api_msg_msg *msg); +void do_connect ( struct api_msg_msg *msg); +void do_disconnect ( struct api_msg_msg *msg); +void do_listen ( struct api_msg_msg *msg); +void do_send ( struct api_msg_msg *msg); +void do_recv ( struct api_msg_msg *msg); +void do_write ( struct api_msg_msg *msg); +void do_getaddr ( struct api_msg_msg *msg); +void do_close ( struct api_msg_msg *msg); +#if LWIP_IGMP +void do_join_leave_group( struct api_msg_msg *msg); +#endif /* LWIP_IGMP */ + +#if LWIP_DNS +void do_gethostbyname(void *arg); +#endif /* LWIP_DNS */ + +struct netconn* netconn_alloc(enum netconn_type t, netconn_callback callback); +void netconn_free(struct netconn *conn); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_NETCONN */ + +#endif /* __LWIP_API_MSG_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/arch.h b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/arch.h new file mode 100644 index 0000000..19d5734 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/arch.h @@ -0,0 +1,233 @@ +/** + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_ARCH_H__ +#define __LWIP_ARCH_H__ + +#ifndef LITTLE_ENDIAN +#define LITTLE_ENDIAN 1234 +#endif + +#ifndef BIG_ENDIAN +#define BIG_ENDIAN 4321 +#endif + +#include "arch/cc.h" + +/** Temporary: define format string for size_t if not defined in cc.h */ +#ifndef SZT_F +#define SZT_F U32_F +#endif /* SZT_F */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef PACK_STRUCT_BEGIN +#define PACK_STRUCT_BEGIN +#endif /* PACK_STRUCT_BEGIN */ + +#ifndef PACK_STRUCT_END +#define PACK_STRUCT_END +#endif /* PACK_STRUCT_END */ + +#ifndef PACK_STRUCT_FIELD +#define PACK_STRUCT_FIELD(x) x +#endif /* PACK_STRUCT_FIELD */ + + +#ifndef LWIP_UNUSED_ARG +#define LWIP_UNUSED_ARG(x) (void)x +#endif /* LWIP_UNUSED_ARG */ + + +#ifdef LWIP_PROVIDE_ERRNO + +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#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 child processes */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device or resource 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 ETXTBSY 26 /* Text file busy */ +#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 EDOM 33 /* Math argument out of domain of func */ +#define ERANGE 34 /* Math result not representable */ +#define EDEADLK 35 /* Resource deadlock would occur */ +#define ENAMETOOLONG 36 /* File name too long */ +#define ENOLCK 37 /* No record locks available */ +#define ENOSYS 38 /* Function not implemented */ +#define ENOTEMPTY 39 /* Directory not empty */ +#define ELOOP 40 /* Too many symbolic links encountered */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define ENOMSG 42 /* No message of desired type */ +#define EIDRM 43 /* Identifier removed */ +#define ECHRNG 44 /* Channel number out of range */ +#define EL2NSYNC 45 /* Level 2 not synchronized */ +#define EL3HLT 46 /* Level 3 halted */ +#define EL3RST 47 /* Level 3 reset */ +#define ELNRNG 48 /* Link number out of range */ +#define EUNATCH 49 /* Protocol driver not attached */ +#define ENOCSI 50 /* No CSI structure available */ +#define EL2HLT 51 /* Level 2 halted */ +#define EBADE 52 /* Invalid exchange */ +#define EBADR 53 /* Invalid request descriptor */ +#define EXFULL 54 /* Exchange full */ +#define ENOANO 55 /* No anode */ +#define EBADRQC 56 /* Invalid request code */ +#define EBADSLT 57 /* Invalid slot */ + +#define EDEADLOCK EDEADLK + +#define EBFONT 59 /* Bad font file format */ +#define ENOSTR 60 /* Device not a stream */ +#define ENODATA 61 /* No data available */ +#define ETIME 62 /* Timer expired */ +#define ENOSR 63 /* Out of streams resources */ +#define ENONET 64 /* Machine is not on the network */ +#define ENOPKG 65 /* Package not installed */ +#define EREMOTE 66 /* Object is remote */ +#define ENOLINK 67 /* Link has been severed */ +#define EADV 68 /* Advertise error */ +#define ESRMNT 69 /* Srmount error */ +#define ECOMM 70 /* Communication error on send */ +#define EPROTO 71 /* Protocol error */ +#define EMULTIHOP 72 /* Multihop attempted */ +#define EDOTDOT 73 /* RFS specific error */ +#define EBADMSG 74 /* Not a data message */ +#define EOVERFLOW 75 /* Value too large for defined data type */ +#define ENOTUNIQ 76 /* Name not unique on network */ +#define EBADFD 77 /* File descriptor in bad state */ +#define EREMCHG 78 /* Remote address changed */ +#define ELIBACC 79 /* Can not access a needed shared library */ +#define ELIBBAD 80 /* Accessing a corrupted shared library */ +#define ELIBSCN 81 /* .lib section in a.out corrupted */ +#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ +#define ELIBEXEC 83 /* Cannot exec a shared library directly */ +#define EILSEQ 84 /* Illegal byte sequence */ +#define ERESTART 85 /* Interrupted system call should be restarted */ +#define ESTRPIPE 86 /* Streams pipe error */ +#define EUSERS 87 /* Too many users */ +#define ENOTSOCK 88 /* Socket operation on non-socket */ +#define EDESTADDRREQ 89 /* Destination address required */ +#define EMSGSIZE 90 /* Message too long */ +#define EPROTOTYPE 91 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 92 /* Protocol not available */ +#define EPROTONOSUPPORT 93 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ +#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ +#define EADDRINUSE 98 /* Address already in use */ +#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ +#define ENETDOWN 100 /* Network is down */ +#define ENETUNREACH 101 /* Network is unreachable */ +#define ENETRESET 102 /* Network dropped connection because of reset */ +#define ECONNABORTED 103 /* Software caused connection abort */ +#define ECONNRESET 104 /* Connection reset by peer */ +#define ENOBUFS 105 /* No buffer space available */ +#define EISCONN 106 /* Transport endpoint is already connected */ +#define ENOTCONN 107 /* Transport endpoint is not connected */ +#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ +#define ETOOMANYREFS 109 /* Too many references: cannot splice */ +#define ETIMEDOUT 110 /* Connection timed out */ +#define ECONNREFUSED 111 /* Connection refused */ +#define EHOSTDOWN 112 /* Host is down */ +#define EHOSTUNREACH 113 /* No route to host */ +#define EALREADY 114 /* Operation already in progress */ +#define EINPROGRESS 115 /* Operation now in progress */ +#define ESTALE 116 /* Stale NFS file handle */ +#define EUCLEAN 117 /* Structure needs cleaning */ +#define ENOTNAM 118 /* Not a XENIX named type file */ +#define ENAVAIL 119 /* No XENIX semaphores available */ +#define EISNAM 120 /* Is a named type file */ +#define EREMOTEIO 121 /* Remote I/O error */ +#define EDQUOT 122 /* Quota exceeded */ + +#define ENOMEDIUM 123 /* No medium found */ +#define EMEDIUMTYPE 124 /* Wrong medium type */ + + +#define ENSROK 0 /* DNS server returned answer with no data */ +#define ENSRNODATA 160 /* DNS server returned answer with no data */ +#define ENSRFORMERR 161 /* DNS server claims query was misformatted */ +#define ENSRSERVFAIL 162 /* DNS server returned general failure */ +#define ENSRNOTFOUND 163 /* Domain name not found */ +#define ENSRNOTIMP 164 /* DNS server does not implement requested operation */ +#define ENSRREFUSED 165 /* DNS server refused query */ +#define ENSRBADQUERY 166 /* Misformatted DNS query */ +#define ENSRBADNAME 167 /* Misformatted domain name */ +#define ENSRBADFAMILY 168 /* Unsupported address family */ +#define ENSRBADRESP 169 /* Misformatted DNS reply */ +#define ENSRCONNREFUSED 170 /* Could not contact DNS servers */ +#define ENSRTIMEOUT 171 /* Timeout while contacting DNS servers */ +#define ENSROF 172 /* End of file */ +#define ENSRFILE 173 /* Error reading file */ +#define ENSRNOMEM 174 /* Out of memory */ +#define ENSRDESTRUCTION 175 /* Application terminated lookup */ +#define ENSRQUERYDOMAINTOOLONG 176 /* Domain name is too long */ +#define ENSRCNAMELOOP 177 /* Domain name is too long */ + +#ifndef errno +extern int errno; +#endif + +#endif /* LWIP_PROVIDE_ERRNO */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_ARCH_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/debug.h b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/debug.h new file mode 100644 index 0000000..f9eff83 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/debug.h @@ -0,0 +1,102 @@ +/** + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_DEBUG_H__ +#define __LWIP_DEBUG_H__ + +#include "lwip/arch.h" +#include + +/** lower two bits indicate debug level + * - 0 all + * - 1 warning + * - 2 serious + * - 3 severe + */ +#define LWIP_DBG_LEVEL_ALL 0x00 +#define LWIP_DBG_LEVEL_OFF LWIP_DBG_LEVEL_ALL /* compatibility define only */ +#define LWIP_DBG_LEVEL_WARNING 0x01 /* bad checksums, dropped packets, ... */ +#define LWIP_DBG_LEVEL_SERIOUS 0x02 /* memory allocation failures, ... */ +#define LWIP_DBG_LEVEL_SEVERE 0x03 +#define LWIP_DBG_MASK_LEVEL 0x03 + +/** flag for LWIP_DEBUGF to enable that debug message */ +#define LWIP_DBG_ON 0x80U +/** flag for LWIP_DEBUGF to disable that debug message */ +#define LWIP_DBG_OFF 0x00U + +/** flag for LWIP_DEBUGF indicating a tracing message (to follow program flow) */ +#define LWIP_DBG_TRACE 0x40U +/** flag for LWIP_DEBUGF indicating a state debug message (to follow module states) */ +#define LWIP_DBG_STATE 0x20U +/** flag for LWIP_DEBUGF indicating newly added code, not thoroughly tested yet */ +#define LWIP_DBG_FRESH 0x10U +/** flag for LWIP_DEBUGF to halt after printing this debug message */ +#define LWIP_DBG_HALT 0x08U + +#ifndef LWIP_NOASSERT +#define LWIP_ASSERT(message, assertion) do { if(!(assertion)) \ + LWIP_PLATFORM_ASSERT(message); } while(0) +#else /* LWIP_NOASSERT */ +#define LWIP_ASSERT(message, assertion) +#endif /* LWIP_NOASSERT */ + +/** if "expression" isn't true, then print "message" and execute "handler" expression */ +#ifndef LWIP_ERROR +#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \ + LWIP_PLATFORM_ASSERT(message); handler;}} while(0) +#endif /* LWIP_ERROR */ + +#ifdef LWIP_DEBUG +/** print debug message only if debug message type is enabled... + * AND is of correct type AND is at least LWIP_DBG_LEVEL + */ + + +#define LWIP_PLATFORM_DIAG printf +#define LWIP_DEBUGF(debug, message) do { \ + if ( \ + ((debug) & LWIP_DBG_ON) && \ + ((debug) & LWIP_DBG_TYPES_ON) && \ + ((s16_t)((debug) & LWIP_DBG_MASK_LEVEL) >= LWIP_DBG_MIN_LEVEL)) { \ + LWIP_PLATFORM_DIAG message; \ + if ((debug) & LWIP_DBG_HALT) { \ + while(1); \ + } \ + } \ + } while(0) + +#else /* LWIP_DEBUG */ +#define LWIP_DEBUGF(debug, message) +#endif /* LWIP_DEBUG */ + +#endif /* __LWIP_DEBUG_H__ */ + diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/def.h b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/def.h new file mode 100644 index 0000000..0e84852 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/def.h @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_DEF_H__ +#define __LWIP_DEF_H__ + +/* this might define NULL already */ +#include "lwip/arch.h" + +#define LWIP_MAX(x , y) (((x) > (y)) ? (x) : (y)) +#define LWIP_MIN(x , y) (((x) < (y)) ? (x) : (y)) + +#ifndef NULL +#define NULL ((void *)0) +#endif + + +#endif /* __LWIP_DEF_H__ */ + diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/dhcp.h b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/dhcp.h new file mode 100644 index 0000000..f93fcd0 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/dhcp.h @@ -0,0 +1,247 @@ +/** @file + **/ + +#ifndef __LWIP_DHCP_H__ +#define __LWIP_DHCP_H__ + +#include "lwip/opt.h" + +#if LWIP_DHCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/netif.h" +#include "lwip/udp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** period (in seconds) of the application calling dhcp_coarse_tmr() */ +#define DHCP_COARSE_TIMER_SECS 60 +/** period (in milliseconds) of the application calling dhcp_coarse_tmr() */ +#define DHCP_COARSE_TIMER_MSECS (DHCP_COARSE_TIMER_SECS * 1000UL) +/** period (in milliseconds) of the application calling dhcp_fine_tmr() */ +#define DHCP_FINE_TIMER_MSECS 500 + +struct dhcp +{ + /** transaction identifier of last sent request */ + u32_t xid; + /** our connection to the DHCP server */ + struct udp_pcb *pcb; + /** incoming msg */ + struct dhcp_msg *msg_in; + /** incoming msg options */ + void *options_in; + /** ingoing msg options length */ + u16_t options_in_len; + /** current DHCP state machine state */ + u8_t state; + /** retries of current request */ + u8_t tries; + + struct pbuf *p_out; /* pbuf of outcoming msg */ + struct dhcp_msg *msg_out; /* outgoing msg */ + u16_t options_out_len; /* outgoing msg options length */ + u16_t request_timeout; /* #ticks with period DHCP_FINE_TIMER_SECS for request timeout */ + u16_t t1_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for renewal time */ + u16_t t2_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for rebind time */ + struct ip_addr server_ip_addr; /* dhcp server address that offered this lease */ + struct ip_addr offered_ip_addr; + struct ip_addr offered_sn_mask; + struct ip_addr offered_gw_addr; + struct ip_addr offered_bc_addr; +#define DHCP_MAX_DNS 2 + u32_t dns_count; /* actual number of DNS servers obtained */ + struct ip_addr offered_dns_addr[DHCP_MAX_DNS]; /* DNS server addresses */ + + u32_t offered_t0_lease; /* lease period (in seconds) */ + u32_t offered_t1_renew; /* recommended renew time (usually 50% of lease period) */ + u32_t offered_t2_rebind; /* recommended rebind time (usually 66% of lease period) */ +#if LWIP_DHCP_AUTOIP_COOP + u8_t autoip_coop_state; +#endif +/** Patch #1308 + * TODO: See dhcp.c "TODO"s + */ +#if 0 + struct ip_addr offered_si_addr; + u8_t *boot_file_name; +#endif +}; + +/* MUST be compiled with "pack structs" or equivalent! */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** minimum set of fields of any DHCP message */ +struct dhcp_msg +{ + PACK_STRUCT_FIELD(u8_t op); + PACK_STRUCT_FIELD(u8_t htype); + PACK_STRUCT_FIELD(u8_t hlen); + PACK_STRUCT_FIELD(u8_t hops); + PACK_STRUCT_FIELD(u32_t xid); + PACK_STRUCT_FIELD(u16_t secs); + PACK_STRUCT_FIELD(u16_t flags); + PACK_STRUCT_FIELD(struct ip_addr ciaddr); + PACK_STRUCT_FIELD(struct ip_addr yiaddr); + PACK_STRUCT_FIELD(struct ip_addr siaddr); + PACK_STRUCT_FIELD(struct ip_addr giaddr); +#define DHCP_CHADDR_LEN 16U + PACK_STRUCT_FIELD(u8_t chaddr[DHCP_CHADDR_LEN]); +#define DHCP_SNAME_LEN 64U + PACK_STRUCT_FIELD(u8_t sname[DHCP_SNAME_LEN]); +#define DHCP_FILE_LEN 128U + PACK_STRUCT_FIELD(u8_t file[DHCP_FILE_LEN]); + PACK_STRUCT_FIELD(u32_t cookie); +#define DHCP_MIN_OPTIONS_LEN 68U +/** make sure user does not configure this too small */ +#if ((defined(DHCP_OPTIONS_LEN)) && (DHCP_OPTIONS_LEN < DHCP_MIN_OPTIONS_LEN)) +# undef DHCP_OPTIONS_LEN +#endif +/** allow this to be configured in lwipopts.h, but not too small */ +#if (!defined(DHCP_OPTIONS_LEN)) +/** set this to be sufficient for your options in outgoing DHCP msgs */ +# define DHCP_OPTIONS_LEN DHCP_MIN_OPTIONS_LEN +#endif + PACK_STRUCT_FIELD(u8_t options[DHCP_OPTIONS_LEN]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** start DHCP configuration */ +err_t dhcp_start(struct netif *netif); +/** enforce early lease renewal (not needed normally)*/ +err_t dhcp_renew(struct netif *netif); +/** release the DHCP lease, usually called before dhcp_stop()*/ +err_t dhcp_release(struct netif *netif); +err_t dhcp_release_unicast(struct netif *netif); +/** stop DHCP configuration */ +void dhcp_stop(struct netif *netif); +/** inform server of our manual IP address */ +void dhcp_inform(struct netif *netif); +/** Handle a possible change in the network configuration */ +void dhcp_network_changed(struct netif *netif); + +/** if enabled, check whether the offered IP address is not in use, using ARP */ +#if DHCP_DOES_ARP_CHECK +void dhcp_arp_reply(struct netif *netif, struct ip_addr *addr); +#endif + +/** to be called every minute */ +void dhcp_coarse_tmr(void); +/** to be called every half second */ +void dhcp_fine_tmr(void); + +/** DHCP message item offsets and length */ +#define DHCP_MSG_OFS (UDP_DATA_OFS) + #define DHCP_OP_OFS (DHCP_MSG_OFS + 0) + #define DHCP_HTYPE_OFS (DHCP_MSG_OFS + 1) + #define DHCP_HLEN_OFS (DHCP_MSG_OFS + 2) + #define DHCP_HOPS_OFS (DHCP_MSG_OFS + 3) + #define DHCP_XID_OFS (DHCP_MSG_OFS + 4) + #define DHCP_SECS_OFS (DHCP_MSG_OFS + 8) + #define DHCP_FLAGS_OFS (DHCP_MSG_OFS + 10) + #define DHCP_CIADDR_OFS (DHCP_MSG_OFS + 12) + #define DHCP_YIADDR_OFS (DHCP_MSG_OFS + 16) + #define DHCP_SIADDR_OFS (DHCP_MSG_OFS + 20) + #define DHCP_GIADDR_OFS (DHCP_MSG_OFS + 24) + #define DHCP_CHADDR_OFS (DHCP_MSG_OFS + 28) + #define DHCP_SNAME_OFS (DHCP_MSG_OFS + 44) + #define DHCP_FILE_OFS (DHCP_MSG_OFS + 108) +#define DHCP_MSG_LEN 236 + +#define DHCP_COOKIE_OFS (DHCP_MSG_OFS + DHCP_MSG_LEN) +#define DHCP_OPTIONS_OFS (DHCP_MSG_OFS + DHCP_MSG_LEN + 4) + +#define DHCP_CLIENT_PORT 68 +#define DHCP_SERVER_PORT 67 + +/** DHCP client states */ +#define DHCP_REQUESTING 1 +#define DHCP_INIT 2 +#define DHCP_REBOOTING 3 +#define DHCP_REBINDING 4 +#define DHCP_RENEWING 5 +#define DHCP_SELECTING 6 +#define DHCP_INFORMING 7 +#define DHCP_CHECKING 8 +#define DHCP_PERMANENT 9 +#define DHCP_BOUND 10 +#define DHCP_RELEASING 11 +#define DHCP_BACKING_OFF 12 +#define DHCP_OFF 13 + +/** AUTOIP cooperatation flags */ +#define DHCP_AUTOIP_COOP_STATE_OFF 0 +#define DHCP_AUTOIP_COOP_STATE_ON 1 + +#define DHCP_BOOTREQUEST 1 +#define DHCP_BOOTREPLY 2 + +#define DHCP_DISCOVER 1 +#define DHCP_OFFER 2 +#define DHCP_REQUEST 3 +#define DHCP_DECLINE 4 +#define DHCP_ACK 5 +#define DHCP_NAK 6 +#define DHCP_RELEASE 7 +#define DHCP_INFORM 8 + +#define DHCP_HTYPE_ETH 1 + +#define DHCP_HLEN_ETH 6 + +#define DHCP_BROADCAST_FLAG 15 +#define DHCP_BROADCAST_MASK (1 << DHCP_FLAG_BROADCAST) + +/** BootP options */ +#define DHCP_OPTION_PAD 0 +#define DHCP_OPTION_SUBNET_MASK 1 /* RFC 2132 3.3 */ +#define DHCP_OPTION_ROUTER 3 +#define DHCP_OPTION_DNS_SERVER 6 +#define DHCP_OPTION_HOSTNAME 12 +#define DHCP_OPTION_IP_TTL 23 +#define DHCP_OPTION_MTU 26 +#define DHCP_OPTION_BROADCAST 28 +#define DHCP_OPTION_TCP_TTL 37 +#define DHCP_OPTION_END 255 + +/** DHCP options */ +#define DHCP_OPTION_REQUESTED_IP 50 /* RFC 2132 9.1, requested IP address */ +#define DHCP_OPTION_LEASE_TIME 51 /* RFC 2132 9.2, time in seconds, in 4 bytes */ +#define DHCP_OPTION_OVERLOAD 52 /* RFC2132 9.3, use file and/or sname field for options */ + +#define DHCP_OPTION_MESSAGE_TYPE 53 /* RFC 2132 9.6, important for DHCP */ +#define DHCP_OPTION_MESSAGE_TYPE_LEN 1 + + +#define DHCP_OPTION_SERVER_ID 54 /* RFC 2132 9.7, server IP address */ +#define DHCP_OPTION_PARAMETER_REQUEST_LIST 55 /* RFC 2132 9.8, requested option types */ + +#define DHCP_OPTION_MAX_MSG_SIZE 57 /* RFC 2132 9.10, message size accepted >= 576 */ +#define DHCP_OPTION_MAX_MSG_SIZE_LEN 2 + +#define DHCP_OPTION_T1 58 /* T1 renewal time */ +#define DHCP_OPTION_T2 59 /* T2 rebinding time */ +#define DHCP_OPTION_US 60 +#define DHCP_OPTION_CLIENT_ID 61 +#define DHCP_OPTION_TFTP_SERVERNAME 66 +#define DHCP_OPTION_BOOTFILE 67 + +/** possible combinations of overloading the file and sname fields with options */ +#define DHCP_OVERLOAD_NONE 0 +#define DHCP_OVERLOAD_FILE 1 +#define DHCP_OVERLOAD_SNAME 2 +#define DHCP_OVERLOAD_SNAME_FILE 3 + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_DHCP */ + +#endif /*__LWIP_DHCP_H__*/ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/dns.h b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/dns.h new file mode 100644 index 0000000..be91d49 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/dns.h @@ -0,0 +1,97 @@ +/** + * lwip DNS resolver header file. + + * Author: Jim Pettinato + * April 2007 + + * ported from uIP resolv.c Copyright (c) 2002-2003, Adam Dunkels. + * + * 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. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 __LWIP_DNS_H__ +#define __LWIP_DNS_H__ + +#include "lwip/opt.h" + +#if LWIP_DNS /* don't build if not configured for use in lwipopts.h */ + +/** DNS timer period */ +#define DNS_TMR_INTERVAL 1000 + +/** DNS field TYPE used for "Resource Records" */ +#define DNS_RRTYPE_A 1 /* a host address */ +#define DNS_RRTYPE_NS 2 /* an authoritative name server */ +#define DNS_RRTYPE_MD 3 /* a mail destination (Obsolete - use MX) */ +#define DNS_RRTYPE_MF 4 /* a mail forwarder (Obsolete - use MX) */ +#define DNS_RRTYPE_CNAME 5 /* the canonical name for an alias */ +#define DNS_RRTYPE_SOA 6 /* marks the start of a zone of authority */ +#define DNS_RRTYPE_MB 7 /* a mailbox domain name (EXPERIMENTAL) */ +#define DNS_RRTYPE_MG 8 /* a mail group member (EXPERIMENTAL) */ +#define DNS_RRTYPE_MR 9 /* a mail rename domain name (EXPERIMENTAL) */ +#define DNS_RRTYPE_NULL 10 /* a null RR (EXPERIMENTAL) */ +#define DNS_RRTYPE_WKS 11 /* a well known service description */ +#define DNS_RRTYPE_PTR 12 /* a domain name pointer */ +#define DNS_RRTYPE_HINFO 13 /* host information */ +#define DNS_RRTYPE_MINFO 14 /* mailbox or mail list information */ +#define DNS_RRTYPE_MX 15 /* mail exchange */ +#define DNS_RRTYPE_TXT 16 /* text strings */ + +/** DNS field CLASS used for "Resource Records" */ +#define DNS_RRCLASS_IN 1 /* the Internet */ +#define DNS_RRCLASS_CS 2 /* the CSNET class (Obsolete - used only for examples in some obsolete RFCs) */ +#define DNS_RRCLASS_CH 3 /* the CHAOS class */ +#define DNS_RRCLASS_HS 4 /* Hesiod [Dyer 87] */ +#define DNS_RRCLASS_FLUSH 0x800 /* Flush bit */ + +/** Callback which is invoked when a hostname is found. + * A function of this type must be implemented by the application using the DNS resolver. + * @param name pointer to the name that was looked up. + * @param ipaddr pointer to a struct ip_addr containing the IP address of the hostname, + * or NULL if the name could not be found (or on any other error). + * @param callback_arg a user-specified callback argument passed to dns_gethostbyname +*/ +typedef void (*dns_found_callback)(const char *name, struct ip_addr *ipaddr, void *callback_arg); + + +void dns_init(void); + +void dns_tmr(void); + +void dns_setserver(u8_t numdns, struct ip_addr *dnsserver); + +struct ip_addr dns_getserver(u8_t numdns); + +err_t dns_gethostbyname(const char *hostname, struct ip_addr *addr, + dns_found_callback found, void *callback_arg); + +#if DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC +int dns_local_removehost(const char *hostname, const struct ip_addr *addr); +err_t dns_local_addhost(const char *hostname, const struct ip_addr *addr); +#endif /* DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + +#endif /* LWIP_DNS */ + +#endif /* __LWIP_DNS_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/err.h b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/err.h new file mode 100644 index 0000000..2cd5819 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/err.h @@ -0,0 +1,87 @@ +/** + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_ERR_H__ +#define __LWIP_ERR_H__ + +#include "lwip/opt.h" +#include "lwip/arch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Define LWIP_ERR_T in cc.h if you want to use + * a different type for your platform (must be signed). */ +#ifdef LWIP_ERR_T +typedef LWIP_ERR_T err_t; +#else /* LWIP_ERR_T */ + typedef s8_t err_t; +#endif /* LWIP_ERR_T*/ + +/* Definitions for error constants. */ + +#define ERR_OK 0 /* No error, everything OK. */ +#define ERR_MEM -1 /* Out of memory error. */ +#define ERR_BUF -2 /* Buffer error. */ +#define ERR_TIMEOUT -3 /* Timeout. */ +#define ERR_RTE -4 /* Routing problem. */ + +#define ERR_IS_FATAL(e) ((e) < ERR_RTE) + +#define ERR_ABRT -5 /* Connection aborted. */ +#define ERR_RST -6 /* Connection reset. */ +#define ERR_CLSD -7 /* Connection closed. */ +#define ERR_CONN -8 /* Not connected. */ + +#define ERR_VAL -9 /* Illegal value. */ + +#define ERR_ARG -10 /* Illegal argument. */ + +#define ERR_USE -11 /* Address in use. */ + +#define ERR_IF -12 /* Low-level netif error */ +#define ERR_ISCONN -13 /* Already connected. */ + +#define ERR_INPROGRESS -14 /* Operation in progress */ + + +#ifdef LWIP_DEBUG +extern const char *lwip_strerr(err_t err); +#else +#define lwip_strerr(x) "" +#endif /* LWIP_DEBUG */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_ERR_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/init.h b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/init.h new file mode 100644 index 0000000..86be6da --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/init.h @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + **/ +#ifndef __LWIP_INIT_H__ +#define __LWIP_INIT_H__ + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** X.x.x: Major version of the stack */ +#define LWIP_VERSION_MAJOR 1U +/** x.X.x: Minor version of the stack */ +#define LWIP_VERSION_MINOR 3U +/** x.x.X: Revision of the stack */ +#define LWIP_VERSION_REVISION 2U +/** For release candidates, this is set to 1..254 + * For official releases, this is set to 255 (LWIP_RC_RELEASE) + * For development versions (CVS), this is set to 0 (LWIP_RC_DEVELOPMENT) */ +#define LWIP_VERSION_RC 255U + +/** LWIP_VERSION_RC is set to LWIP_RC_RELEASE for official releases */ +#define LWIP_RC_RELEASE 255U +/** LWIP_VERSION_RC is set to LWIP_RC_DEVELOPMENT for CVS versions */ +#define LWIP_RC_DEVELOPMENT 0U + +#define LWIP_VERSION_IS_RELEASE (LWIP_VERSION_RC == LWIP_RC_RELEASE) +#define LWIP_VERSION_IS_DEVELOPMENT (LWIP_VERSION_RC == LWIP_RC_DEVELOPMENT) +#define LWIP_VERSION_IS_RC ((LWIP_VERSION_RC != LWIP_RC_RELEASE) && (LWIP_VERSION_RC != LWIP_RC_DEVELOPMENT)) + +/** Provides the version of the stack */ +#define LWIP_VERSION (LWIP_VERSION_MAJOR << 24 | LWIP_VERSION_MINOR << 16 | \ + LWIP_VERSION_REVISION << 8 | LWIP_VERSION_RC) + +/* Modules initialization */ +void lwip_init(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_INIT_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/mem.h b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/mem.h new file mode 100644 index 0000000..7976462 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/mem.h @@ -0,0 +1,107 @@ +/** + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_MEM_H__ +#define __LWIP_MEM_H__ + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if MEM_LIBC_MALLOC + +#include /* for size_t */ + +typedef size_t mem_size_t; + +/* aliases for C library malloc() */ +#define mem_init() +/* in case C library malloc() needs extra protection, + * allow these defines to be overridden. + */ +#ifndef mem_free +#define mem_free free +#endif +#ifndef mem_malloc +#define mem_malloc malloc +#endif +#ifndef mem_calloc +#define mem_calloc calloc +#endif +#ifndef mem_realloc +static void *mem_realloc(void *mem, mem_size_t size) +{ + LWIP_UNUSED_ARG(size); + return mem; +} +#endif +#else /* MEM_LIBC_MALLOC */ + +/* MEM_SIZE would have to be aligned, but using 64000 here instead of + * 65535 leaves some room for alignment... + */ +#if MEM_SIZE > 64000l +typedef u32_t mem_size_t; +#else +typedef u16_t mem_size_t; +#endif /* MEM_SIZE > 64000 */ + +#if MEM_USE_POOLS +/** mem_init is not used when using pools instead of a heap */ +#define mem_init() +/** mem_realloc is not used when using pools instead of a heap: + we can't free part of a pool element and don't want to copy the rest */ +#define mem_realloc(mem, size) (mem) +#else /* MEM_USE_POOLS */ +/* lwIP alternative malloc */ +void mem_init(void); +void *mem_realloc(void *mem, mem_size_t size); +#endif /* MEM_USE_POOLS */ +void *mem_malloc(mem_size_t size); +void *mem_calloc(mem_size_t count, mem_size_t size); +void mem_free(void *mem); +#endif /* MEM_LIBC_MALLOC */ + +#ifndef LWIP_MEM_ALIGN_SIZE +#define LWIP_MEM_ALIGN_SIZE(size) (((size) + MEM_ALIGNMENT - 1) & ~(MEM_ALIGNMENT-1)) +#endif + +#ifndef LWIP_MEM_ALIGN +#define LWIP_MEM_ALIGN(addr) ((void *)(((mem_ptr_t)(addr) + MEM_ALIGNMENT - 1) & ~(mem_ptr_t)(MEM_ALIGNMENT-1))) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_MEM_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/memp.h b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/memp.h new file mode 100644 index 0000000..33046db --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/memp.h @@ -0,0 +1,116 @@ +/** + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#ifndef __LWIP_MEMP_H__ +#define __LWIP_MEMP_H__ + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Create the list of all memory pools managed by memp. MEMP_MAX represents a NULL pool at the end */ +typedef enum { +#define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name, +#include "lwip/memp_std.h" + MEMP_MAX +} memp_t; + +#if MEM_USE_POOLS +/* Use a helper type to get the start and end of the user "memory pools" for mem_malloc */ +typedef enum { + /* Get the first (via: + MEMP_POOL_HELPER_START = ((u8_t) 1*MEMP_POOL_A + 0*MEMP_POOL_B + 0*MEMP_POOL_C + 0)*/ + MEMP_POOL_HELPER_FIRST = ((u8_t) +#define LWIP_MEMPOOL(name,num,size,desc) +#define LWIP_MALLOC_MEMPOOL_START 1 +#define LWIP_MALLOC_MEMPOOL(num, size) * MEMP_POOL_##size + 0 +#define LWIP_MALLOC_MEMPOOL_END +#include "lwip/memp_std.h" + ) , + /* Get the last (via: + MEMP_POOL_HELPER_END = ((u8_t) 0 + MEMP_POOL_A*0 + MEMP_POOL_B*0 + MEMP_POOL_C*1) */ + MEMP_POOL_HELPER_LAST = ((u8_t) +#define LWIP_MEMPOOL(name,num,size,desc) +#define LWIP_MALLOC_MEMPOOL_START +#define LWIP_MALLOC_MEMPOOL(num, size) 0 + MEMP_POOL_##size * +#define LWIP_MALLOC_MEMPOOL_END 1 +#include "lwip/memp_std.h" + ) +} memp_pool_helper_t; + +/* The actual start and stop values are here (cast them over) + We use this helper type and these defines so we can avoid using const memp_t values */ +#define MEMP_POOL_FIRST ((memp_t) MEMP_POOL_HELPER_FIRST) +#define MEMP_POOL_LAST ((memp_t) MEMP_POOL_HELPER_LAST) +#endif /* MEM_USE_POOLS */ + +#if MEMP_MEM_MALLOC || MEM_USE_POOLS +extern const u16_t memp_sizes[MEMP_MAX]; +#endif /* MEMP_MEM_MALLOC || MEM_USE_POOLS */ + +#if MEMP_MEM_MALLOC + +#include "mem.h" + +#define memp_init() +#define memp_malloc(type) mem_malloc(memp_sizes[type]) +#define memp_free(type, mem) mem_free(mem) + +#else /* MEMP_MEM_MALLOC */ + +#if MEM_USE_POOLS +/** This structure is used to save the pool one element came from. */ +struct memp_malloc_helper +{ + memp_t poolnr; +}; +#endif /* MEM_USE_POOLS */ + +void memp_init(void); + +#if MEMP_OVERFLOW_CHECK +void *memp_malloc_fn(memp_t type, const char* file, const int line); +#define memp_malloc(t) memp_malloc_fn((t), __FILE__, __LINE__) +#else +void *memp_malloc(memp_t type); +#endif +void memp_free(memp_t type, void *mem); + +#endif /* MEMP_MEM_MALLOC */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_MEMP_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/memp_std.h b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/memp_std.h new file mode 100644 index 0000000..0d25696 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/memp_std.h @@ -0,0 +1,102 @@ +/** + * SETUP: Make sure we define everything we will need. + * + * We have create three types of pools: + * 1) MEMPOOL - standard pools + * 2) MALLOC_MEMPOOL - to be used by mem_malloc in mem.c + * 3) PBUF_MEMPOOL - a mempool of pbuf's, so include space for the pbuf struct + * + * If the include'r doesn't require any special treatment of each of the types + * above, then will declare #2 & #3 to be just standard mempools. + */ +#ifndef LWIP_MALLOC_MEMPOOL +/* This treats "malloc pools" just like any other pool. + The pools are a little bigger to provide 'size' as the amount of user data. */ +#define LWIP_MALLOC_MEMPOOL(num, size) LWIP_MEMPOOL(POOL_##size, num, (size + sizeof(struct memp_malloc_helper)), "MALLOC_"#size) +#define LWIP_MALLOC_MEMPOOL_START +#define LWIP_MALLOC_MEMPOOL_END +#endif /* LWIP_MALLOC_MEMPOOL */ + +#ifndef LWIP_PBUF_MEMPOOL +/* This treats "pbuf pools" just like any other pool. + * Allocates buffers for a pbuf struct AND a payload size */ +#define LWIP_PBUF_MEMPOOL(name, num, payload, desc) LWIP_MEMPOOL(name, num, (MEMP_ALIGN_SIZE(sizeof(struct pbuf)) + MEMP_ALIGN_SIZE(payload)), desc) +#endif /* LWIP_PBUF_MEMPOOL */ + + +/* + * A list of internal pools used by LWIP. + * + * LWIP_MEMPOOL(pool_name, number_elements, element_size, pool_description) + * creates a pool name MEMP_pool_name. description is used in stats.c + */ +#if LWIP_RAW +LWIP_MEMPOOL(RAW_PCB, MEMP_NUM_RAW_PCB, sizeof(struct raw_pcb), "RAW_PCB") +#endif /* LWIP_RAW */ + +#if LWIP_UDP +LWIP_MEMPOOL(UDP_PCB, MEMP_NUM_UDP_PCB, sizeof(struct udp_pcb), "UDP_PCB") +#endif /* LWIP_UDP */ + +#if LWIP_TCP +LWIP_MEMPOOL(TCP_PCB, MEMP_NUM_TCP_PCB, sizeof(struct tcp_pcb), "TCP_PCB") +LWIP_MEMPOOL(TCP_PCB_LISTEN, MEMP_NUM_TCP_PCB_LISTEN, sizeof(struct tcp_pcb_listen), "TCP_PCB_LISTEN") +LWIP_MEMPOOL(TCP_SEG, MEMP_NUM_TCP_SEG, sizeof(struct tcp_seg), "TCP_SEG") +#endif /* LWIP_TCP */ + +#if IP_REASSEMBLY +LWIP_MEMPOOL(REASSDATA, MEMP_NUM_REASSDATA, sizeof(struct ip_reassdata), "REASSDATA") +#endif /* IP_REASSEMBLY */ + +#if LWIP_NETCONN +LWIP_MEMPOOL(NETBUF, MEMP_NUM_NETBUF, sizeof(struct netbuf), "NETBUF") +LWIP_MEMPOOL(NETCONN, MEMP_NUM_NETCONN, sizeof(struct netconn), "NETCONN") +#endif /* LWIP_NETCONN */ + +#if NO_SYS==0 +LWIP_MEMPOOL(TCPIP_MSG_API, MEMP_NUM_TCPIP_MSG_API, sizeof(struct tcpip_msg), "TCPIP_MSG_API") +LWIP_MEMPOOL(TCPIP_MSG_INPKT,MEMP_NUM_TCPIP_MSG_INPKT, sizeof(struct tcpip_msg), "TCPIP_MSG_INPKT") +#endif /* NO_SYS==0 */ + +#if ARP_QUEUEING +LWIP_MEMPOOL(ARP_QUEUE, MEMP_NUM_ARP_QUEUE, sizeof(struct etharp_q_entry), "ARP_QUEUE") +#endif /* ARP_QUEUEING */ + +#if LWIP_IGMP +LWIP_MEMPOOL(IGMP_GROUP, MEMP_NUM_IGMP_GROUP, sizeof(struct igmp_group), "IGMP_GROUP") +#endif /* LWIP_IGMP */ + +#if NO_SYS==0 +LWIP_MEMPOOL(SYS_TIMEOUT, MEMP_NUM_SYS_TIMEOUT, sizeof(struct sys_timeo), "SYS_TIMEOUT") +#endif /* NO_SYS==0 */ + + +/* + * A list of pools of pbuf's used by LWIP. + * + * LWIP_PBUF_MEMPOOL(pool_name, number_elements, pbuf_payload_size, pool_description) + * creates a pool name MEMP_pool_name. description is used in stats.c + * This allocates enough space for the pbuf struct and a payload. + * (Example: pbuf_payload_size=0 allocates only size for the struct) + */ +LWIP_PBUF_MEMPOOL(PBUF, MEMP_NUM_PBUF, 0, "PBUF_REF/ROM") +LWIP_PBUF_MEMPOOL(PBUF_POOL, PBUF_POOL_SIZE, PBUF_POOL_BUFSIZE, "PBUF_POOL") + + +/* + * Allow for user-defined pools; this must be explicitly set in lwipopts.h + * since the default is to NOT look for lwippools.h + */ +#if MEMP_USE_CUSTOM_POOLS +#include "lwippools.h" +#endif /* MEMP_USE_CUSTOM_POOLS */ + +/* + * REQUIRED CLEANUP: Clear up so we don't get "multiply defined" error later + * (#undef is ignored for something that is not defined) + */ +#undef LWIP_MEMPOOL +#undef LWIP_MALLOC_MEMPOOL +#undef LWIP_MALLOC_MEMPOOL_START +#undef LWIP_MALLOC_MEMPOOL_END +#undef LWIP_PBUF_MEMPOOL diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/netbuf.h b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/netbuf.h new file mode 100644 index 0000000..0dfb367 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/netbuf.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_NETBUF_H__ +#define __LWIP_NETBUF_H__ + +#include "lwip/opt.h" +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct netbuf { + struct pbuf *p, *ptr; + struct ip_addr *addr; + u16_t port; +#if LWIP_NETBUF_RECVINFO + struct ip_addr *toaddr; + u16_t toport; +#endif /* LWIP_NETBUF_RECVINFO */ +}; + +/* Network buffer functions: */ +struct netbuf * netbuf_new (void); +void netbuf_delete (struct netbuf *buf); +void * netbuf_alloc (struct netbuf *buf, u16_t size); +void netbuf_free (struct netbuf *buf); +err_t netbuf_ref (struct netbuf *buf, + const void *dataptr, u16_t size); +void netbuf_chain (struct netbuf *head, + struct netbuf *tail); + +u16_t netbuf_len (struct netbuf *buf); +err_t netbuf_data (struct netbuf *buf, + void **dataptr, u16_t *len); +s8_t netbuf_next (struct netbuf *buf); +void netbuf_first (struct netbuf *buf); + + +#define netbuf_copy_partial(buf, dataptr, len, offset) \ + pbuf_copy_partial((buf)->p, (dataptr), (len), (offset)) +#define netbuf_copy(buf,dataptr,len) netbuf_copy_partial(buf, dataptr, len, 0) +#define netbuf_take(buf, dataptr, len) pbuf_take((buf)->p, dataptr, len) +#define netbuf_len(buf) ((buf)->p->tot_len) +#define netbuf_fromaddr(buf) ((buf)->addr) +#define netbuf_fromport(buf) ((buf)->port) +#if LWIP_NETBUF_RECVINFO +#define netbuf_destaddr(buf) ((buf)->toaddr) +#define netbuf_destport(buf) ((buf)->toport) +#endif /* LWIP_NETBUF_RECVINFO */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_NETBUF_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/netdb.h b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/netdb.h new file mode 100644 index 0000000..00cc172 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/netdb.h @@ -0,0 +1,111 @@ +/** + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Simon Goldschmidt + * + **/ + +#include "lwip/opt.h" + +#if LWIP_DNS && LWIP_SOCKET + +#include /* for size_t */ + +#include "lwip/sockets.h" + +/* some rarely used options */ +#ifndef LWIP_DNS_API_DECLARE_H_ERRNO +#define LWIP_DNS_API_DECLARE_H_ERRNO 1 +#endif + +#ifndef LWIP_DNS_API_DEFINE_ERRORS +#define LWIP_DNS_API_DEFINE_ERRORS 1 +#endif + +#ifndef LWIP_DNS_API_DECLARE_STRUCTS +#define LWIP_DNS_API_DECLARE_STRUCTS 1 +#endif + +#if LWIP_DNS_API_DEFINE_ERRORS +/** Errors used by the DNS API functions, h_errno can be one of them */ +#define EAI_NONAME 200 +#define EAI_SERVICE 201 +#define EAI_FAIL 202 +#define EAI_MEMORY 203 + +#define HOST_NOT_FOUND 210 +#define NO_DATA 211 +#define NO_RECOVERY 212 +#define TRY_AGAIN 213 +#endif /* LWIP_DNS_API_DEFINE_ERRORS */ + +#if LWIP_DNS_API_DECLARE_STRUCTS +struct hostent { + char *h_name; /* Official name of the host. */ + char **h_aliases; /* A pointer to an array of pointers to alternative host names, + terminated by a null pointer. */ + int h_addrtype; /* Address type. */ + int h_length; /* The length, in bytes, of the address. */ + char **h_addr_list; /* A pointer to an array of pointers to network addresses (in + network byte order) for the host, terminated by a null pointer. */ +#define h_addr h_addr_list[0] /* for backward compatibility */ +}; + +struct addrinfo { + int ai_flags; /* Input flags. */ + int ai_family; /* Address family of socket. */ + int ai_socktype; /* Socket type. */ + int ai_protocol; /* Protocol of socket. */ + socklen_t ai_addrlen; /* Length of socket address. */ + struct sockaddr *ai_addr; /* Socket address of socket. */ + char *ai_canonname; /* Canonical name of service location. */ + struct addrinfo *ai_next; /* Pointer to next in list. */ +}; +#endif /* LWIP_DNS_API_DECLARE_STRUCTS */ + +#if LWIP_DNS_API_DECLARE_H_ERRNO +/* application accessable error code set by the DNS API functions */ +extern int h_errno; +#endif /* LWIP_DNS_API_DECLARE_H_ERRNO*/ + +struct hostent *lwip_gethostbyname(const char *name); +int lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf, + size_t buflen, struct hostent **result, int *h_errnop); +void lwip_freeaddrinfo(struct addrinfo *ai); +int lwip_getaddrinfo(const char *nodename, + const char *servname, + const struct addrinfo *hints, + struct addrinfo **res); + +#if LWIP_COMPAT_SOCKETS +#define gethostbyname(name) lwip_gethostbyname(name) +#define gethostbyname_r(name, ret, buf, buflen, result, h_errnop) \ + lwip_gethostbyname_r(name, ret, buf, buflen, result, h_errnop) +#define freeaddrinfo(addrinfo) lwip_freeaddrinfo(addrinfo) +#define getaddrinfo(nodname, servname, hints, res) \ + lwip_getaddrinfo(nodname, servname, hints, res) +#endif /* LWIP_COMPAT_SOCKETS */ + +#endif /* LWIP_DNS && LWIP_SOCKET */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/netif.h b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/netif.h new file mode 100644 index 0000000..59869ac --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/netif.h @@ -0,0 +1,269 @@ +/** + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_NETIF_H__ +#define __LWIP_NETIF_H__ + +#include "lwip/opt.h" + +#define ENABLE_LOOPBACK (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF) + +#include "lwip/err.h" + +#include "lwip/ip_addr.h" + +#include "lwip/inet.h" +#include "lwip/pbuf.h" +#if LWIP_DHCP +struct dhcp; +#endif +#if LWIP_AUTOIP +struct autoip; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Throughout this file, IP addresses are expected to be in + * the same byte order as in IP_PCB. */ + +/** must be the maximum of all used hardware address lengths + across all types of interfaces in use */ +#define NETIF_MAX_HWADDR_LEN 6U + +/** TODO: define the use (where, when, whom) of netif flags */ + +/** whether the network interface is 'up'. this is + * a software flag used to control whether this network + * interface is enabled and processes traffic. + */ +#define NETIF_FLAG_UP 0x01U +/** if set, the netif has broadcast capability */ +#define NETIF_FLAG_BROADCAST 0x02U +/** if set, the netif is one end of a point-to-point connection */ +#define NETIF_FLAG_POINTTOPOINT 0x04U +/** if set, the interface is configured using DHCP */ +#define NETIF_FLAG_DHCP 0x08U +/** if set, the interface has an active link + * (set by the network interface driver) */ +#define NETIF_FLAG_LINK_UP 0x10U +/** if set, the netif is an device using ARP */ +#define NETIF_FLAG_ETHARP 0x20U +/** if set, the netif has IGMP capability */ +#define NETIF_FLAG_IGMP 0x40U +/** if set, the netif has IP layer switch capability */ +/* Realtek Modified Start */ +#ifdef CONFIG_DONT_CARE_TP +#define NETIF_FLAG_IPSWITCH 0x80U +#endif +/* Realtek Modified End */ + +/** Generic data structure used for all lwIP network interfaces. + * The following fields should be filled in by the initialization + * function for the device driver: hwaddr_len, hwaddr[], mtu, flags */ + +struct netif { + /** pointer to next in linked list */ + struct netif *next; + + /** IP address configuration in network byte order */ + struct ip_addr ip_addr; + struct ip_addr netmask; + struct ip_addr gw; + + /** This function is called by the network device driver + * to pass a packet up the TCP/IP stack. */ + err_t (* input)(struct pbuf *p, struct netif *inp); + /** This function is called by the IP module when it wants + * to send a packet on the interface. This function typically + * first resolves the hardware address, then sends the packet. */ + err_t (* output)(struct netif *netif, struct pbuf *p, + struct ip_addr *ipaddr); + /** This function is called by the ARP module when it wants + * to send a packet on the interface. This function outputs + * the pbuf as-is on the link medium. */ + err_t (* linkoutput)(struct netif *netif, struct pbuf *p); +#if LWIP_NETIF_STATUS_CALLBACK + /** This function is called when the netif state is set to up or down + */ + void (* status_callback)(struct netif *netif); +#endif /* LWIP_NETIF_STATUS_CALLBACK */ +#if LWIP_NETIF_LINK_CALLBACK + /** This function is called when the netif link is set to up or down + */ + void (* link_callback)(struct netif *netif); +#endif /* LWIP_NETIF_LINK_CALLBACK */ + /** This field can be set by the device driver and could point + * to state information for the device. */ + void *state; +#if LWIP_DHCP + /** the DHCP client state information for this netif */ + struct dhcp *dhcp; +#endif /* LWIP_DHCP */ +#if LWIP_AUTOIP + /** the AutoIP client state information for this netif */ + struct autoip *autoip; +#endif +#if LWIP_NETIF_HOSTNAME + /* the hostname for this netif, NULL is a valid value */ + char* hostname; +#endif /* LWIP_NETIF_HOSTNAME */ + /** maximum transfer unit (in bytes) */ + u16_t mtu; + /** number of bytes used in hwaddr */ + u8_t hwaddr_len; + /** link level hardware address of this interface */ + u8_t hwaddr[NETIF_MAX_HWADDR_LEN]; + /** flags (see NETIF_FLAG_ above) */ + u8_t flags; + /** descriptive abbreviation */ + char name[2]; + /** number of this interface */ + u8_t num; +#if LWIP_SNMP + /** link type (from "snmp_ifType" enum from snmp.h) */ + u8_t link_type; + /** (estimate) link speed */ + u32_t link_speed; + /** timestamp at last change made (up/down) */ + u32_t ts; + /** counters */ + u32_t ifinoctets; + u32_t ifinucastpkts; + u32_t ifinnucastpkts; + u32_t ifindiscards; + u32_t ifoutoctets; + u32_t ifoutucastpkts; + u32_t ifoutnucastpkts; + u32_t ifoutdiscards; +#endif /* LWIP_SNMP */ +#if LWIP_IGMP + /* This function could be called to add or delete a entry in the multicast filter table of the ethernet MAC.*/ + err_t (*igmp_mac_filter)( struct netif *netif, struct ip_addr *group, u8_t action); +#endif /* LWIP_IGMP */ +#if LWIP_NETIF_HWADDRHINT + u8_t *addr_hint; +#endif /* LWIP_NETIF_HWADDRHINT */ +#if ENABLE_LOOPBACK + /* List of packets to be queued for ourselves. */ + struct pbuf *loop_first; + struct pbuf *loop_last; +#if LWIP_LOOPBACK_MAX_PBUFS + u16_t loop_cnt_current; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ +#endif /* ENABLE_LOOPBACK */ +}; + +#if LWIP_SNMP +#define NETIF_INIT_SNMP(netif, type, speed) \ + /* use "snmp_ifType" enum from snmp.h for "type", snmp_ifType_ethernet_csmacd by example */ \ + netif->link_type = type; \ + /* your link speed here (units: bits per second) */ \ + netif->link_speed = speed; \ + netif->ts = 0; \ + netif->ifinoctets = 0; \ + netif->ifinucastpkts = 0; \ + netif->ifinnucastpkts = 0; \ + netif->ifindiscards = 0; \ + netif->ifoutoctets = 0; \ + netif->ifoutucastpkts = 0; \ + netif->ifoutnucastpkts = 0; \ + netif->ifoutdiscards = 0 +#else /* LWIP_SNMP */ +#define NETIF_INIT_SNMP(netif, type, speed) +#endif /* LWIP_SNMP */ + + +/** The list of network interfaces. */ +extern struct netif *netif_list; +/** The default network interface. */ +extern struct netif *netif_default; + +#define netif_init() /* Compatibility define, not init needed. */ + +struct netif *netif_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask, + struct ip_addr *gw, + void *state, + err_t (* init)(struct netif *netif), + err_t (* input)(struct pbuf *p, struct netif *netif)); + +void +netif_set_addr(struct netif *netif,struct ip_addr *ipaddr, struct ip_addr *netmask, + struct ip_addr *gw); +void netif_remove(struct netif * netif); + +/* Returns a network interface given its name. The name is of the form + "et0", where the first two letters are the "name" field in the + netif structure, and the digit is in the num field in the same + structure. */ +struct netif *netif_find(char *name); + +void netif_set_default(struct netif *netif); + +void netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr); +void netif_set_netmask(struct netif *netif, struct ip_addr *netmask); +void netif_set_gw(struct netif *netif, struct ip_addr *gw); + +void netif_set_up(struct netif *netif); +void netif_set_down(struct netif *netif); +u8_t netif_is_up(struct netif *netif); + +#if LWIP_NETIF_STATUS_CALLBACK +/* + * Set callback to be called when interface is brought up/down + */ +void netif_set_status_callback(struct netif *netif, void (* status_callback)(struct netif *netif)); +#endif /* LWIP_NETIF_STATUS_CALLBACK */ + +#if LWIP_NETIF_LINK_CALLBACK +void netif_set_link_up(struct netif *netif); +void netif_set_link_down(struct netif *netif); +u8_t netif_is_link_up(struct netif *netif); +/* + * Set callback to be called when link is brought up/down + */ +void netif_set_link_callback(struct netif *netif, void (* link_callback)(struct netif *netif)); +#endif /* LWIP_NETIF_LINK_CALLBACK */ + +#ifdef __cplusplus +} +#endif + +#if ENABLE_LOOPBACK +err_t netif_loop_output(struct netif *netif, struct pbuf *p, struct ip_addr *dest_ip); +void netif_poll(struct netif *netif); +#if !LWIP_NETIF_LOOPBACK_MULTITHREADING +void netif_poll_all(void); +#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */ +#endif /* ENABLE_LOOPBACK */ + +#endif /* __LWIP_NETIF_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/netifapi.h b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/netifapi.h new file mode 100644 index 0000000..4145dd7 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/netifapi.h @@ -0,0 +1,105 @@ +/* + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#ifndef __LWIP_NETIFAPI_H__ +#define __LWIP_NETIFAPI_H__ + +#include "lwip/opt.h" + +#if LWIP_NETIF_API /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/sys.h" +#include "lwip/netif.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct netifapi_msg_msg { +#if !LWIP_TCPIP_CORE_LOCKING + sys_sem_t sem; +#endif /* !LWIP_TCPIP_CORE_LOCKING */ + err_t err; + struct netif *netif; + union { + struct { + struct ip_addr *ipaddr; + struct ip_addr *netmask; + struct ip_addr *gw; + void *state; + err_t (* init) (struct netif *netif); + err_t (* input)(struct pbuf *p, struct netif *netif); + } add; + struct { + void (* voidfunc)(struct netif *netif); + err_t (* errtfunc)(struct netif *netif); + } common; + } msg; +}; + +struct netifapi_msg { + void (* function)(struct netifapi_msg_msg *msg); + struct netifapi_msg_msg msg; +}; + + +/* API for application */ +err_t netifapi_netif_add ( struct netif *netif, + struct ip_addr *ipaddr, + struct ip_addr *netmask, + struct ip_addr *gw, + void *state, + err_t (* init)(struct netif *netif), + err_t (* input)(struct pbuf *p, struct netif *netif) ); + +err_t netifapi_netif_set_addr ( struct netif *netif, + struct ip_addr *ipaddr, + struct ip_addr *netmask, + struct ip_addr *gw ); + +err_t netifapi_netif_common ( struct netif *netif, + void (* voidfunc)(struct netif *netif), + err_t (* errtfunc)(struct netif *netif) ); + +#define netifapi_netif_remove(n) netifapi_netif_common(n, netif_remove, NULL) +#define netifapi_netif_set_up(n) netifapi_netif_common(n, netif_set_up, NULL) +#define netifapi_netif_set_down(n) netifapi_netif_common(n, netif_set_down, NULL) +#define netifapi_netif_set_default(n) netifapi_netif_common(n, netif_set_default, NULL) +#define netifapi_dhcp_start(n) netifapi_netif_common(n, NULL, dhcp_start) +#define netifapi_dhcp_stop(n) netifapi_netif_common(n, dhcp_stop, NULL) +#define netifapi_autoip_start(n) netifapi_netif_common(n, NULL, autoip_start) +#define netifapi_autoip_stop(n) netifapi_netif_common(n, NULL, autoip_stop) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_NETIF_API */ + +#endif /* __LWIP_NETIFAPI_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/opt.h b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/opt.h new file mode 100644 index 0000000..69162cf --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/opt.h @@ -0,0 +1,1841 @@ +/* + * @file + * + * lwIP Options Configuration + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_OPT_H__ +#define __LWIP_OPT_H__ + +/* + * Include user defined options first. Anything not defined in these files + * will be set to standard values. Override anything you dont like! + */ +#include "lwipopts.h" +#include "lwip/debug.h" + +/* + ----------------------------------------------- + ---------- Platform specific locking ---------- + ----------------------------------------------- +*/ + +/** + * SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain + * critical regions during buffer allocation, deallocation and memory + * allocation and deallocation. + */ +#ifndef SYS_LIGHTWEIGHT_PROT +#define SYS_LIGHTWEIGHT_PROT 0 +#endif + +/** + * NO_SYS==1: Provides VERY minimal functionality. Otherwise, + * use lwIP facilities. + */ +#ifndef NO_SYS +#define NO_SYS 0 +#endif + +/** + * MEMCPY: override this if you have a faster implementation at hand than the + * one included in your C library + */ +#ifndef MEMCPY +#define MEMCPY(dst,src,len) memcpy(dst,src,len) +#endif + +/** + * SMEMCPY: override this with care! Some compilers (e.g. gcc) can inline a + * call to memcpy() if the length is known at compile time and is small. + */ +#ifndef SMEMCPY +#define SMEMCPY(dst,src,len) memcpy(dst,src,len) +#endif + +/* + ------------------------------------ + ---------- Memory options ---------- + ------------------------------------ +*/ +/** + * MEM_LIBC_MALLOC==1: Use malloc/free/realloc provided by your C-library + * instead of the lwip internal allocator. Can save code size if you + * already use it. + */ +#ifndef MEM_LIBC_MALLOC +#define MEM_LIBC_MALLOC 0 +#endif + +/** +* MEMP_MEM_MALLOC==1: Use mem_malloc/mem_free instead of the lwip pool allocator. +* Especially useful with MEM_LIBC_MALLOC but handle with care regarding execution +* speed and usage from interrupts! +*/ +#ifndef MEMP_MEM_MALLOC +#define MEMP_MEM_MALLOC 0 +#endif + +/** + * MEM_ALIGNMENT: should be set to the alignment of the CPU + * 4 byte alignment -> #define MEM_ALIGNMENT 4 + * 2 byte alignment -> #define MEM_ALIGNMENT 2 + */ +#ifndef MEM_ALIGNMENT +#define MEM_ALIGNMENT 1 +#endif + +/** + * MEM_SIZE: the size of the heap memory. If the application will send + * a lot of data that needs to be copied, this should be set high. + */ +#ifndef MEM_SIZE +#define MEM_SIZE 1600 +#endif + +/** + * MEMP_OVERFLOW_CHECK: memp overflow protection reserves a configurable + * amount of bytes before and after each memp element in every pool and fills + * it with a prominent default value. + * MEMP_OVERFLOW_CHECK == 0 no checking + * MEMP_OVERFLOW_CHECK == 1 checks each element when it is freed + * MEMP_OVERFLOW_CHECK >= 2 checks each element in every pool every time + * memp_malloc() or memp_free() is called (useful but slow!) + */ +#ifndef MEMP_OVERFLOW_CHECK +#define MEMP_OVERFLOW_CHECK 0 +#endif + +/** + * MEMP_SANITY_CHECK==1: run a sanity check after each memp_free() to make + * sure that there are no cycles in the linked lists. + */ +#ifndef MEMP_SANITY_CHECK +#define MEMP_SANITY_CHECK 0 +#endif + +/** + * MEM_USE_POOLS==1: Use an alternative to malloc() by allocating from a set + * of memory pools of various sizes. When mem_malloc is called, an element of + * the smallest pool that can provide the length needed is returned. + * To use this, MEMP_USE_CUSTOM_POOLS also has to be enabled. + */ +#ifndef MEM_USE_POOLS +#define MEM_USE_POOLS 0 +#endif + +/** + * MEM_USE_POOLS_TRY_BIGGER_POOL==1: if one malloc-pool is empty, try the next + * bigger pool - WARNING: THIS MIGHT WASTE MEMORY but it can make a system more + * reliable. */ +#ifndef MEM_USE_POOLS_TRY_BIGGER_POOL +#define MEM_USE_POOLS_TRY_BIGGER_POOL 0 +#endif + +/** + * MEMP_USE_CUSTOM_POOLS==1: whether to include a user file lwippools.h + * that defines additional pools beyond the "standard" ones required + * by lwIP. If you set this to 1, you must have lwippools.h in your + * inlude path somewhere. + */ +#ifndef MEMP_USE_CUSTOM_POOLS +#define MEMP_USE_CUSTOM_POOLS 0 +#endif + +/** + * Set this to 1 if you want to free PBUF_RAM pbufs (or call mem_free()) from + * interrupt context (or another context that doesn't allow waiting for a + * semaphore). + * If set to 1, mem_malloc will be protected by a semaphore and SYS_ARCH_PROTECT, + * while mem_free will only use SYS_ARCH_PROTECT. mem_malloc SYS_ARCH_UNPROTECTs + * with each loop so that mem_free can run. + * + * ATTENTION: As you can see from the above description, this leads to dis-/ + * enabling interrupts often, which can be slow! Also, on low memory, mem_malloc + * can need longer. + * + * If you don't want that, at least for NO_SYS=0, you can still use the following + * functions to enqueue a deallocation call which then runs in the tcpip_thread + * context: + * - pbuf_free_callback(p); + * - mem_free_callback(m); + */ +#ifndef LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT +#define LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT 0 +#endif + +/* + ------------------------------------------------ + ---------- Internal Memory Pool Sizes ---------- + ------------------------------------------------ +*/ +/** + * MEMP_NUM_PBUF: the number of memp struct pbufs (used for PBUF_ROM and PBUF_REF). + * If the application sends a lot of data out of ROM (or other static memory), + * this should be set high. + */ +#ifndef MEMP_NUM_PBUF +#define MEMP_NUM_PBUF 16 +#endif + +/** + * MEMP_NUM_RAW_PCB: Number of raw connection PCBs + * (requires the LWIP_RAW option) + */ +#ifndef MEMP_NUM_RAW_PCB +#define MEMP_NUM_RAW_PCB 4 +#endif + +/** + * MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One + * per active UDP "connection". + * (requires the LWIP_UDP option) + */ +#ifndef MEMP_NUM_UDP_PCB +#define MEMP_NUM_UDP_PCB 4 +#endif + +/** + * MEMP_NUM_TCP_PCB: the number of simulatenously active TCP connections. + * (requires the LWIP_TCP option) + */ +#ifndef MEMP_NUM_TCP_PCB +#define MEMP_NUM_TCP_PCB 5 +#endif + +/** + * MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP connections. + * (requires the LWIP_TCP option) + */ +#ifndef MEMP_NUM_TCP_PCB_LISTEN +#define MEMP_NUM_TCP_PCB_LISTEN 8 +#endif + +/** + * MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP segments. + * (requires the LWIP_TCP option) + */ +#ifndef MEMP_NUM_TCP_SEG +#define MEMP_NUM_TCP_SEG 16 +#endif + +/** + * MEMP_NUM_REASSDATA: the number of simultaneously IP packets queued for + * reassembly (whole packets, not fragments!) + */ +#ifndef MEMP_NUM_REASSDATA +#define MEMP_NUM_REASSDATA 5 +#endif + +/** + * MEMP_NUM_ARP_QUEUE: the number of simulateously queued outgoing + * packets (pbufs) that are waiting for an ARP request (to resolve + * their destination address) to finish. + * (requires the ARP_QUEUEING option) + */ +#ifndef MEMP_NUM_ARP_QUEUE +#define MEMP_NUM_ARP_QUEUE 30 +#endif + +/** + * MEMP_NUM_IGMP_GROUP: The number of multicast groups whose network interfaces + * can be members et the same time (one per netif - allsystems group -, plus one + * per netif membership). + * (requires the LWIP_IGMP option) + */ +#ifndef MEMP_NUM_IGMP_GROUP +#define MEMP_NUM_IGMP_GROUP 8 +#endif + +/** + * MEMP_NUM_SYS_TIMEOUT: the number of simulateously active timeouts. + * (requires NO_SYS==0) + */ +#ifndef MEMP_NUM_SYS_TIMEOUT +#define MEMP_NUM_SYS_TIMEOUT 3 +#endif + +/** + * MEMP_NUM_NETBUF: the number of struct netbufs. + * (only needed if you use the sequential API, like api_lib.c) + */ +#ifndef MEMP_NUM_NETBUF +#define MEMP_NUM_NETBUF 2 +#endif + +/** + * MEMP_NUM_NETCONN: the number of struct netconns. + * (only needed if you use the sequential API, like api_lib.c) + */ +#ifndef MEMP_NUM_NETCONN +#define MEMP_NUM_NETCONN 4 +#endif + +/** + * MEMP_NUM_TCPIP_MSG_API: the number of struct tcpip_msg, which are used + * for callback/timeout API communication. + * (only needed if you use tcpip.c) + */ +#ifndef MEMP_NUM_TCPIP_MSG_API +#define MEMP_NUM_TCPIP_MSG_API 8 +#endif + +/** + * MEMP_NUM_TCPIP_MSG_INPKT: the number of struct tcpip_msg, which are used + * for incoming packets. + * (only needed if you use tcpip.c) + */ +#ifndef MEMP_NUM_TCPIP_MSG_INPKT +#define MEMP_NUM_TCPIP_MSG_INPKT 8 +#endif + +/** + * PBUF_POOL_SIZE: the number of buffers in the pbuf pool. + */ +#ifndef PBUF_POOL_SIZE +#define PBUF_POOL_SIZE 16 +#endif + +/* + --------------------------------- + ---------- ARP options ---------- + --------------------------------- +*/ +/** + * LWIP_ARP==1: Enable ARP functionality. + */ +#ifndef LWIP_ARP +#define LWIP_ARP 1 +#endif + +/** + * ARP_TABLE_SIZE: Number of active MAC-IP address pairs cached. + */ +#ifndef ARP_TABLE_SIZE +#define ARP_TABLE_SIZE 10 +#endif + +/** + * ARP_QUEUEING==1: Outgoing packets are queued during hardware address + * resolution. + */ +#ifndef ARP_QUEUEING +#define ARP_QUEUEING 1 +#endif + +/** + * ETHARP_TRUST_IP_MAC==1: Incoming IP packets cause the ARP table to be + * updated with the source MAC and IP addresses supplied in the packet. + * You may want to disable this if you do not trust LAN peers to have the + * correct addresses, or as a limited approach to attempt to handle + * spoofing. If disabled, lwIP will need to make a new ARP request if + * the peer is not already in the ARP table, adding a little latency. + */ +#ifndef ETHARP_TRUST_IP_MAC +#define ETHARP_TRUST_IP_MAC 1 +#endif + +/** + * ETHARP_SUPPORT_VLAN==1: support receiving ethernet packets with VLAN header. + * Additionally, you can define ETHARP_VLAN_CHECK to an u16_t VLAN ID to check. + * If ETHARP_VLAN_CHECK is defined, only VLAN-traffic for this VLAN is accepted. + * If ETHARP_VLAN_CHECK is not defined, all traffic is accepted. + */ +#ifndef ETHARP_SUPPORT_VLAN +#define ETHARP_SUPPORT_VLAN 0 +#endif + +/* + -------------------------------- + ---------- IP options ---------- + -------------------------------- +*/ +/** + * IP_FORWARD==1: Enables the ability to forward IP packets across network + * interfaces. If you are going to run lwIP on a device with only one network + * interface, define this to 0. + */ +#ifndef IP_FORWARD +#define IP_FORWARD 0 +#endif + +/** + * IP_OPTIONS_ALLOWED: Defines the behavior for IP options. + * IP_OPTIONS_ALLOWED==0: All packets with IP options are dropped. + * IP_OPTIONS_ALLOWED==1: IP options are allowed (but not parsed). + */ +#ifndef IP_OPTIONS_ALLOWED +#define IP_OPTIONS_ALLOWED 1 +#endif + +/** + * IP_REASSEMBLY==1: Reassemble incoming fragmented IP packets. Note that + * this option does not affect outgoing packet sizes, which can be controlled + * via IP_FRAG. + */ +#ifndef IP_REASSEMBLY +#define IP_REASSEMBLY 1 +#endif + +/** + * IP_FRAG==1: Fragment outgoing IP packets if their size exceeds MTU. Note + * that this option does not affect incoming packet sizes, which can be + * controlled via IP_REASSEMBLY. + */ +#ifndef IP_FRAG +#define IP_FRAG 1 +#endif + +/** + * IP_REASS_MAXAGE: Maximum time (in multiples of IP_TMR_INTERVAL - so seconds, normally) + * a fragmented IP packet waits for all fragments to arrive. If not all fragments arrived + * in this time, the whole packet is discarded. + */ +#ifndef IP_REASS_MAXAGE +#define IP_REASS_MAXAGE 3 +#endif + +/** + * IP_REASS_MAX_PBUFS: Total maximum amount of pbufs waiting to be reassembled. + * Since the received pbufs are enqueued, be sure to configure + * PBUF_POOL_SIZE > IP_REASS_MAX_PBUFS so that the stack is still able to receive + * packets even if the maximum amount of fragments is enqueued for reassembly! + */ +#ifndef IP_REASS_MAX_PBUFS +#define IP_REASS_MAX_PBUFS 10 +#endif + +/** + * IP_FRAG_USES_STATIC_BUF==1: Use a static MTU-sized buffer for IP + * fragmentation. Otherwise pbufs are allocated and reference the original + * packet data to be fragmented. + */ +#ifndef IP_FRAG_USES_STATIC_BUF +#define IP_FRAG_USES_STATIC_BUF 1 +#endif + +/** + * IP_FRAG_MAX_MTU: Assumed max MTU on any interface for IP frag buffer + * (requires IP_FRAG_USES_STATIC_BUF==1) + */ +#if IP_FRAG_USES_STATIC_BUF && !defined(IP_FRAG_MAX_MTU) +#define IP_FRAG_MAX_MTU 1500 +#endif + +/** + * IP_DEFAULT_TTL: Default value for Time-To-Live used by transport layers. + */ +#ifndef IP_DEFAULT_TTL +#define IP_DEFAULT_TTL 255 +#endif + +/** + * IP_SOF_BROADCAST=1: Use the SOF_BROADCAST field to enable broadcast + * filter per pcb on udp and raw send operations. To enable broadcast filter + * on recv operations, you also have to set IP_SOF_BROADCAST_RECV=1. + */ +#ifndef IP_SOF_BROADCAST +#define IP_SOF_BROADCAST 0 +#endif + +/** + * IP_SOF_BROADCAST_RECV (requires IP_SOF_BROADCAST=1) enable the broadcast + * filter on recv operations. + */ +#ifndef IP_SOF_BROADCAST_RECV +#define IP_SOF_BROADCAST_RECV 0 +#endif + +/* + ---------------------------------- + ---------- ICMP options ---------- + ---------------------------------- +*/ +/** + * LWIP_ICMP==1: Enable ICMP module inside the IP stack. + * Be careful, disable that make your product non-compliant to RFC1122 + */ +#ifndef LWIP_ICMP +#define LWIP_ICMP 1 +#endif + +/** + * ICMP_TTL: Default value for Time-To-Live used by ICMP packets. + */ +#ifndef ICMP_TTL +#define ICMP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * LWIP_BROADCAST_PING==1: respond to broadcast pings (default is unicast only) + */ +#ifndef LWIP_BROADCAST_PING +#define LWIP_BROADCAST_PING 0 +#endif + +/** + * LWIP_MULTICAST_PING==1: respond to multicast pings (default is unicast only) + */ +#ifndef LWIP_MULTICAST_PING +#define LWIP_MULTICAST_PING 0 +#endif + +/* + --------------------------------- + ---------- RAW options ---------- + --------------------------------- +*/ +/** + * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. + */ +#ifndef LWIP_RAW +#define LWIP_RAW 1 +#endif + +/** + * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. + */ +#ifndef RAW_TTL +#define RAW_TTL (IP_DEFAULT_TTL) +#endif + +/* + ---------------------------------- + ---------- DHCP options ---------- + ---------------------------------- +*/ +/** + * LWIP_DHCP==1: Enable DHCP module. + */ +#ifndef LWIP_DHCP +#define LWIP_DHCP 0 +#endif + +/** + * DHCP_DOES_ARP_CHECK==1: Do an ARP check on the offered address. + */ +#ifndef DHCP_DOES_ARP_CHECK +#define DHCP_DOES_ARP_CHECK ((LWIP_DHCP) && (LWIP_ARP)) +#endif + +/* + ------------------------------------ + ---------- AUTOIP options ---------- + ------------------------------------ +*/ +/** + * LWIP_AUTOIP==1: Enable AUTOIP module. + */ +#ifndef LWIP_AUTOIP +#define LWIP_AUTOIP 1 +#endif + +/** + * LWIP_DHCP_AUTOIP_COOP==1: Allow DHCP and AUTOIP to be both enabled on + * the same interface at the same time. + */ +#ifndef LWIP_DHCP_AUTOIP_COOP +#define LWIP_DHCP_AUTOIP_COOP 0 +#endif + +/** + * LWIP_DHCP_AUTOIP_COOP_TRIES: Set to the number of DHCP DISCOVER probes + * that should be sent before falling back on AUTOIP. This can be set + * as low as 1 to get an AutoIP address very quickly, but you should + * be prepared to handle a changing IP address when DHCP overrides + * AutoIP. + */ +#ifndef LWIP_DHCP_AUTOIP_COOP_TRIES +#define LWIP_DHCP_AUTOIP_COOP_TRIES 9 +#endif + +/* + ---------------------------------- + ---------- SNMP options ---------- + ---------------------------------- +*/ +/** + * LWIP_SNMP==1: Turn on SNMP module. UDP must be available for SNMP + * transport. + */ +#ifndef LWIP_SNMP +#define LWIP_SNMP 0 +#endif + +/** + * SNMP_CONCURRENT_REQUESTS: Number of concurrent requests the module will + * allow. At least one request buffer is required. + */ +#ifndef SNMP_CONCURRENT_REQUESTS +#define SNMP_CONCURRENT_REQUESTS 1 +#endif + +/** + * SNMP_TRAP_DESTINATIONS: Number of trap destinations. At least one trap + * destination is required + */ +#ifndef SNMP_TRAP_DESTINATIONS +#define SNMP_TRAP_DESTINATIONS 1 +#endif + +/** + * SNMP_PRIVATE_MIB: + */ +#ifndef SNMP_PRIVATE_MIB +#define SNMP_PRIVATE_MIB 0 +#endif + +/** + * Only allow SNMP write actions that are 'safe' (e.g. disabeling netifs is not + * a safe action and disabled when SNMP_SAFE_REQUESTS = 1). + * Unsafe requests are disabled by default! + */ +#ifndef SNMP_SAFE_REQUESTS +#define SNMP_SAFE_REQUESTS 1 +#endif + +/* + ---------------------------------- + ---------- IGMP options ---------- + ---------------------------------- +*/ +/** + * LWIP_IGMP==1: Turn on IGMP module. + */ +#ifndef LWIP_IGMP +#define LWIP_IGMP 0 +#endif + +/* + ---------------------------------- + ---------- DNS options ----------- + ---------------------------------- +*/ +/** + * LWIP_DNS==1: Turn on DNS module. UDP must be available for DNS + * transport. + */ +#ifndef LWIP_DNS +#define LWIP_DNS 1 +#endif + +/** DNS maximum number of entries to maintain locally. */ +#ifndef DNS_TABLE_SIZE +#define DNS_TABLE_SIZE 4 +#endif + +/** DNS maximum host name length supported in the name table. */ +#ifndef DNS_MAX_NAME_LENGTH +#define DNS_MAX_NAME_LENGTH 256 +#endif + +/** The maximum of DNS servers */ +#ifndef DNS_MAX_SERVERS +#define DNS_MAX_SERVERS 2 +#endif + +/** DNS do a name checking between the query and the response. */ +#ifndef DNS_DOES_NAME_CHECK +#define DNS_DOES_NAME_CHECK 1 +#endif + +/** DNS use a local buffer if DNS_USES_STATIC_BUF=0, a static one if + DNS_USES_STATIC_BUF=1, or a dynamic one if DNS_USES_STATIC_BUF=2. + The buffer will be of size DNS_MSG_SIZE */ +#ifndef DNS_USES_STATIC_BUF +#define DNS_USES_STATIC_BUF 1 +#endif + +/** DNS message max. size. Default value is RFC compliant. */ +#ifndef DNS_MSG_SIZE +#define DNS_MSG_SIZE 512 +#endif + +/** DNS_LOCAL_HOSTLIST: Implements a local host-to-address list. If enabled, + * you have to define + * #define DNS_LOCAL_HOSTLIST_INIT {{"host1", 0x123}, {"host2", 0x234}} + * (an array of structs name/address, where address is an u32_t in network + * byte order). + * + * Instead, you can also use an external function: + * #define DNS_LOOKUP_LOCAL_EXTERN(x) extern u32_t my_lookup_function(const char *name) + * that returns the IP address or INADDR_NONE if not found. + */ +#ifndef DNS_LOCAL_HOSTLIST +#define DNS_LOCAL_HOSTLIST 0 +#endif /* DNS_LOCAL_HOSTLIST */ + +/** If this is turned on, the local host-list can be dynamically changed + * at runtime. */ +#ifndef DNS_LOCAL_HOSTLIST_IS_DYNAMIC +#define DNS_LOCAL_HOSTLIST_IS_DYNAMIC 0 +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + +/* + --------------------------------- + ---------- UDP options ---------- + --------------------------------- +*/ +/** + * LWIP_UDP==1: Turn on UDP. + */ +#ifndef LWIP_UDP +#define LWIP_UDP 1 +#endif + +/** + * LWIP_UDPLITE==1: Turn on UDP-Lite. (Requires LWIP_UDP) + */ +#ifndef LWIP_UDPLITE +#define LWIP_UDPLITE 0 +#endif + +/** + * UDP_TTL: Default Time-To-Live value. + */ +#ifndef UDP_TTL +#define UDP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * LWIP_NETBUF_RECVINFO==1: append destination addr and port to every netbuf. + */ +#ifndef LWIP_NETBUF_RECVINFO +#define LWIP_NETBUF_RECVINFO 0 +#endif + +/* + --------------------------------- + ---------- TCP options ---------- + --------------------------------- +*/ +/** + * LWIP_TCP==1: Turn on TCP. + */ +#ifndef LWIP_TCP +#define LWIP_TCP 1 +#endif + +/** + * TCP_TTL: Default Time-To-Live value. + */ +#ifndef TCP_TTL +#define TCP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * TCP_WND: The size of a TCP window. This must be at least + * (2 * TCP_MSS) for things to work well + */ +#ifndef TCP_WND +#define TCP_WND (4 * TCP_MSS) +#endif + +/** + * TCP_MAXRTX: Maximum number of retransmissions of data segments. + */ +#ifndef TCP_MAXRTX +#define TCP_MAXRTX 12 +#endif + +/** + * TCP_SYNMAXRTX: Maximum number of retransmissions of SYN segments. + */ +#ifndef TCP_SYNMAXRTX +#define TCP_SYNMAXRTX 6 +#endif + +/** + * TCP_QUEUE_OOSEQ==1: TCP will queue segments that arrive out of order. + * Define to 0 if your device is low on memory. + */ +#ifndef TCP_QUEUE_OOSEQ +#define TCP_QUEUE_OOSEQ (LWIP_TCP) +#endif + +/** + * TCP_MSS: TCP Maximum segment size. (default is 536, a conservative default, + * you might want to increase this.) + * For the receive side, this MSS is advertised to the remote side + * when opening a connection. For the transmit size, this MSS sets + * an upper limit on the MSS advertised by the remote host. + */ +#ifndef TCP_MSS +#define TCP_MSS 536 +#endif + +/** + * TCP_CALCULATE_EFF_SEND_MSS: "The maximum size of a segment that TCP really + * sends, the 'effective send MSS,' MUST be the smaller of the send MSS (which + * reflects the available reassembly buffer size at the remote host) and the + * largest size permitted by the IP layer" (RFC 1122) + * Setting this to 1 enables code that checks TCP_MSS against the MTU of the + * netif used for a connection and limits the MSS if it would be too big otherwise. + */ +#ifndef TCP_CALCULATE_EFF_SEND_MSS +#define TCP_CALCULATE_EFF_SEND_MSS 1 +#endif + + +/** + * TCP_SND_BUF: TCP sender buffer space (bytes). + */ +#ifndef TCP_SND_BUF +#define TCP_SND_BUF 256 +#endif + +/** + * TCP_SND_QUEUELEN: TCP sender buffer space (pbufs). This must be at least + * as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. + */ +#ifndef TCP_SND_QUEUELEN +#define TCP_SND_QUEUELEN (4 * (TCP_SND_BUF)/(TCP_MSS)) +#endif + +/** + * TCP_SNDLOWAT: TCP writable space (bytes). This must be less than or equal + * to TCP_SND_BUF. It is the amount of space which must be available in the + * TCP snd_buf for select to return writable. + */ +#ifndef TCP_SNDLOWAT +#define TCP_SNDLOWAT ((TCP_SND_BUF)/2) +#endif + +/** + * TCP_LISTEN_BACKLOG: Enable the backlog option for tcp listen pcb. + */ +#ifndef TCP_LISTEN_BACKLOG +#define TCP_LISTEN_BACKLOG 0 +#endif + +/** + * The maximum allowed backlog for TCP listen netconns. + * This backlog is used unless another is explicitly specified. + * 0xff is the maximum (u8_t). + */ +#ifndef TCP_DEFAULT_LISTEN_BACKLOG +#define TCP_DEFAULT_LISTEN_BACKLOG 0xff +#endif + +/** + * LWIP_TCP_TIMESTAMPS==1: support the TCP timestamp option. + */ +#ifndef LWIP_TCP_TIMESTAMPS +#define LWIP_TCP_TIMESTAMPS 0 +#endif + +/** + * TCP_WND_UPDATE_THRESHOLD: difference in window to trigger an + * explicit window update + */ +#ifndef TCP_WND_UPDATE_THRESHOLD +#define TCP_WND_UPDATE_THRESHOLD (TCP_WND / 4) +#endif + +/** + * LWIP_EVENT_API and LWIP_CALLBACK_API: Only one of these should be set to 1. + * LWIP_EVENT_API==1: The user defines lwip_tcp_event() to receive all + * events (accept, sent, etc) that happen in the system. + * LWIP_CALLBACK_API==1: The PCB callback function is called directly + * for the event. + */ +#ifndef LWIP_EVENT_API +#define LWIP_EVENT_API 0 +#define LWIP_CALLBACK_API 1 +#else +#define LWIP_EVENT_API 1 +#define LWIP_CALLBACK_API 0 +#endif + + +/* + ---------------------------------- + ---------- Pbuf options ---------- + ---------------------------------- +*/ +/** + * PBUF_LINK_HLEN: the number of bytes that should be allocated for a + * link level header. The default is 14, the standard value for + * Ethernet. + */ +#ifndef PBUF_LINK_HLEN +#define PBUF_LINK_HLEN 14 +#endif + +/** + * PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. The default is + * designed to accomodate single full size TCP frame in one pbuf, including + * TCP_MSS, IP header, and link header. + */ +#ifndef PBUF_POOL_BUFSIZE +#define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS+40+PBUF_LINK_HLEN) +#endif + +/* + ------------------------------------------------ + ---------- Network Interfaces options ---------- + ------------------------------------------------ +*/ +/** + * LWIP_NETIF_HOSTNAME==1: use DHCP_OPTION_HOSTNAME with netif's hostname + * field. + */ +#ifndef LWIP_NETIF_HOSTNAME +#define LWIP_NETIF_HOSTNAME 1 +#endif + +/** + * LWIP_NETIF_API==1: Support netif api (in netifapi.c) + */ +#ifndef LWIP_NETIF_API +#define LWIP_NETIF_API 0 +#endif + +/** + * LWIP_NETIF_STATUS_CALLBACK==1: Support a callback function whenever an interface + * changes its up/down status (i.e., due to DHCP IP acquistion) + */ +#ifndef LWIP_NETIF_STATUS_CALLBACK +#define LWIP_NETIF_STATUS_CALLBACK 0 +#endif + +/** + * LWIP_NETIF_LINK_CALLBACK==1: Support a callback function from an interface + * whenever the link changes (i.e., link down) + */ +#ifndef LWIP_NETIF_LINK_CALLBACK +#define LWIP_NETIF_LINK_CALLBACK 0 +#endif + +/** + * LWIP_NETIF_HWADDRHINT==1: Cache link-layer-address hints (e.g. table + * indices) in struct netif. TCP and UDP can make use of this to prevent + * scanning the ARP table for every sent packet. While this is faster for big + * ARP tables or many concurrent connections, it might be counterproductive + * if you have a tiny ARP table or if there never are concurrent connections. + */ +#ifndef LWIP_NETIF_HWADDRHINT +#define LWIP_NETIF_HWADDRHINT 0 +#endif + +/** + * LWIP_NETIF_LOOPBACK==1: Support sending packets with a destination IP + * address equal to the netif IP address, looping them back up the stack. + */ +#ifndef LWIP_NETIF_LOOPBACK +#define LWIP_NETIF_LOOPBACK 0 +#endif + +/** + * LWIP_LOOPBACK_MAX_PBUFS: Maximum number of pbufs on queue for loopback + * sending for each netif (0 = disabled) + */ +#ifndef LWIP_LOOPBACK_MAX_PBUFS +#define LWIP_LOOPBACK_MAX_PBUFS 0 +#endif + +/** + * LWIP_NETIF_LOOPBACK_MULTITHREADING: Indicates whether threading is enabled in + * the system, as netifs must change how they behave depending on this setting + * for the LWIP_NETIF_LOOPBACK option to work. + * Setting this is needed to avoid reentering non-reentrant functions like + * tcp_input(). + * LWIP_NETIF_LOOPBACK_MULTITHREADING==1: Indicates that the user is using a + * multithreaded environment like tcpip.c. In this case, netif->input() + * is called directly. + * LWIP_NETIF_LOOPBACK_MULTITHREADING==0: Indicates a polling (or NO_SYS) setup. + * The packets are put on a list and netif_poll() must be called in + * the main application loop. + */ +#ifndef LWIP_NETIF_LOOPBACK_MULTITHREADING +#define LWIP_NETIF_LOOPBACK_MULTITHREADING (!NO_SYS) +#endif + +/** + * LWIP_NETIF_TX_SINGLE_PBUF: if this is set to 1, lwIP tries to put all data + * to be sent into one single pbuf. This is for compatibility with DMA-enabled + * MACs that do not support scatter-gather. + * Beware that this might involve CPU-memcpy before transmitting that would not + * be needed without this flag! Use this only if you need to! + * + * @todo: TCP and IP-frag do not work with this, yet: + */ +#ifndef LWIP_NETIF_TX_SINGLE_PBUF +#define LWIP_NETIF_TX_SINGLE_PBUF 0 +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + +/* + ------------------------------------ + ---------- LOOPIF options ---------- + ------------------------------------ +*/ +/** + * LWIP_HAVE_LOOPIF==1: Support loop interface (127.0.0.1) and loopif.c + */ +#ifndef LWIP_HAVE_LOOPIF +#define LWIP_HAVE_LOOPIF 0 +#endif + +/* + ------------------------------------ + ---------- SLIPIF options ---------- + ------------------------------------ +*/ +/** + * LWIP_HAVE_SLIPIF==1: Support slip interface and slipif.c + */ +#ifndef LWIP_HAVE_SLIPIF +#define LWIP_HAVE_SLIPIF 0 +#endif + +/* + ------------------------------------ + ---------- Thread options ---------- + ------------------------------------ +*/ +/** + * TCPIP_THREAD_NAME: The name assigned to the main tcpip thread. + */ +#ifndef TCPIP_THREAD_NAME +#define TCPIP_THREAD_NAME "TCP_IP" +#endif + +/** + * TCPIP_THREAD_STACKSIZE: The stack size used by the main tcpip thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef TCPIP_THREAD_STACKSIZE +#define TCPIP_THREAD_STACKSIZE 0 +#endif + +/** + * TCPIP_THREAD_PRIO: The priority assigned to the main tcpip thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef TCPIP_THREAD_PRIO +#define TCPIP_THREAD_PRIO 1 +#endif + +/** + * TCPIP_MBOX_SIZE: The mailbox size for the tcpip thread messages + * The queue size value itself is platform-dependent, but is passed to + * sys_mbox_new() when tcpip_init is called. + */ +#ifndef TCPIP_MBOX_SIZE +#define TCPIP_MBOX_SIZE 0 +#endif + +/** + * SLIPIF_THREAD_NAME: The name assigned to the slipif_loop thread. + */ +#ifndef SLIPIF_THREAD_NAME +#define SLIPIF_THREAD_NAME "slipif_loop" +#endif + +/** + * SLIP_THREAD_STACKSIZE: The stack size used by the slipif_loop thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef SLIPIF_THREAD_STACKSIZE +#define SLIPIF_THREAD_STACKSIZE 0 +#endif + +/** + * SLIPIF_THREAD_PRIO: The priority assigned to the slipif_loop thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef SLIPIF_THREAD_PRIO +#define SLIPIF_THREAD_PRIO 1 +#endif + +/** + * PPP_THREAD_NAME: The name assigned to the pppMain thread. + */ +#ifndef PPP_THREAD_NAME +#define PPP_THREAD_NAME "pppMain" +#endif + +/** + * PPP_THREAD_STACKSIZE: The stack size used by the pppMain thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef PPP_THREAD_STACKSIZE +#define PPP_THREAD_STACKSIZE 0 +#endif + +/** + * PPP_THREAD_PRIO: The priority assigned to the pppMain thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef PPP_THREAD_PRIO +#define PPP_THREAD_PRIO 1 +#endif + +/** + * DEFAULT_THREAD_NAME: The name assigned to any other lwIP thread. + */ +#ifndef DEFAULT_THREAD_NAME +#define DEFAULT_THREAD_NAME "lwIP" +#endif + +/** + * DEFAULT_THREAD_STACKSIZE: The stack size used by any other lwIP thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef DEFAULT_THREAD_STACKSIZE +#define DEFAULT_THREAD_STACKSIZE 0 +#endif + +/** + * DEFAULT_THREAD_PRIO: The priority assigned to any other lwIP thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef DEFAULT_THREAD_PRIO +#define DEFAULT_THREAD_PRIO 1 +#endif + +/** + * DEFAULT_RAW_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_RAW. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#ifndef DEFAULT_RAW_RECVMBOX_SIZE +#define DEFAULT_RAW_RECVMBOX_SIZE 0 +#endif + +/** + * DEFAULT_UDP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_UDP. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#ifndef DEFAULT_UDP_RECVMBOX_SIZE +#define DEFAULT_UDP_RECVMBOX_SIZE 0 +#endif + +/** + * DEFAULT_TCP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_TCP. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#ifndef DEFAULT_TCP_RECVMBOX_SIZE +#define DEFAULT_TCP_RECVMBOX_SIZE 0 +#endif + +/** + * DEFAULT_ACCEPTMBOX_SIZE: The mailbox size for the incoming connections. + * The queue size value itself is platform-dependent, but is passed to + * sys_mbox_new() when the acceptmbox is created. + */ +#ifndef DEFAULT_ACCEPTMBOX_SIZE +#define DEFAULT_ACCEPTMBOX_SIZE 0 +#endif + +/* + ---------------------------------------------- + ---------- Sequential layer options ---------- + ---------------------------------------------- +*/ +/** + * LWIP_TCPIP_CORE_LOCKING: (EXPERIMENTAL!) + * Don't use it if you're not an active lwIP project member + */ +#ifndef LWIP_TCPIP_CORE_LOCKING +#define LWIP_TCPIP_CORE_LOCKING 0 +#endif + +/** + * LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c) + */ +#ifndef LWIP_NETCONN +#define LWIP_NETCONN 1 +#endif + +/* + ------------------------------------ + ---------- Socket options ---------- + ------------------------------------ +*/ +/** + * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c) + */ +#ifndef LWIP_SOCKET +#define LWIP_SOCKET 1 +#endif + +/** + * LWIP_COMPAT_SOCKETS==1: Enable BSD-style sockets functions names. + * (only used if you use sockets.c) + */ +#ifndef LWIP_COMPAT_SOCKETS +#define LWIP_COMPAT_SOCKETS 1 +#endif + +/** + * LWIP_POSIX_SOCKETS_IO_NAMES==1: Enable POSIX-style sockets functions names. + * Disable this option if you use a POSIX operating system that uses the same + * names (read, write & close). (only used if you use sockets.c) + */ +#ifndef LWIP_POSIX_SOCKETS_IO_NAMES +#define LWIP_POSIX_SOCKETS_IO_NAMES 1 +#endif + +/** + * LWIP_TCP_KEEPALIVE==1: Enable TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT + * options processing. Note that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set + * in seconds. (does not require sockets.c, and will affect tcp.c) + */ +#ifndef LWIP_TCP_KEEPALIVE +#define LWIP_TCP_KEEPALIVE 0 +#endif + +/** + * LWIP_SO_RCVTIMEO==1: Enable SO_RCVTIMEO processing. + */ +#ifndef LWIP_SO_RCVTIMEO +#define LWIP_SO_RCVTIMEO 1 +#endif + +/** + * LWIP_SO_RCVBUF==1: Enable SO_RCVBUF processing. + */ +#ifndef LWIP_SO_RCVBUF +#define LWIP_SO_RCVBUF 0 +#endif + +/** + * If LWIP_SO_RCVBUF is used, this is the default value for recv_bufsize. + */ +#ifndef RECV_BUFSIZE_DEFAULT +#define RECV_BUFSIZE_DEFAULT INT_MAX +#endif + +/** + * SO_REUSE==1: Enable SO_REUSEADDR and SO_REUSEPORT options. DO NOT USE! + */ +#ifndef SO_REUSE +#define SO_REUSE 0 +#endif + +/* + ---------------------------------------- + ---------- Statistics options ---------- + ---------------------------------------- +*/ +/** + * LWIP_STATS==1: Enable statistics collection in lwip_stats. + */ +#ifndef LWIP_STATS +#define LWIP_STATS 1 +#endif + +#if LWIP_STATS + +/** + * LWIP_STATS_DISPLAY==1: Compile in the statistics output functions. + */ +#ifndef LWIP_STATS_DISPLAY +#define LWIP_STATS_DISPLAY 0 +#endif + +/** + * LINK_STATS==1: Enable link stats. + */ +#ifndef LINK_STATS +#define LINK_STATS 1 +#endif + +/** + * ETHARP_STATS==1: Enable etharp stats. + */ +#ifndef ETHARP_STATS +#define ETHARP_STATS (LWIP_ARP) +#endif + +/** + * IP_STATS==1: Enable IP stats. + */ +#ifndef IP_STATS +#define IP_STATS 1 +#endif + +/** + * IPFRAG_STATS==1: Enable IP fragmentation stats. Default is + * on if using either frag or reass. + */ +#ifndef IPFRAG_STATS +#define IPFRAG_STATS (IP_REASSEMBLY || IP_FRAG) +#endif + +/** + * ICMP_STATS==1: Enable ICMP stats. + */ +#ifndef ICMP_STATS +#define ICMP_STATS 1 +#endif + +/** + * IGMP_STATS==1: Enable IGMP stats. + */ +#ifndef IGMP_STATS +#define IGMP_STATS (LWIP_IGMP) +#endif + +/** + * UDP_STATS==1: Enable UDP stats. Default is on if + * UDP enabled, otherwise off. + */ +#ifndef UDP_STATS +#define UDP_STATS (LWIP_UDP) +#endif + +/** + * TCP_STATS==1: Enable TCP stats. Default is on if TCP + * enabled, otherwise off. + */ +#ifndef TCP_STATS +#define TCP_STATS (LWIP_TCP) +#endif + +/** + * MEM_STATS==1: Enable mem.c stats. + */ +#ifndef MEM_STATS +#define MEM_STATS ((MEM_LIBC_MALLOC == 0) && (MEM_USE_POOLS == 0)) +#endif + +/** + * MEMP_STATS==1: Enable memp.c pool stats. + */ +#ifndef MEMP_STATS +#define MEMP_STATS (MEMP_MEM_MALLOC == 0) +#endif + +/** + * SYS_STATS==1: Enable system stats (sem and mbox counts, etc). + */ +#ifndef SYS_STATS +#define SYS_STATS (NO_SYS == 0) +#endif + +#else + +#define LINK_STATS 0 +#define IP_STATS 0 +#define IPFRAG_STATS 0 +#define ICMP_STATS 0 +#define IGMP_STATS 0 +#define UDP_STATS 0 +#define TCP_STATS 0 +#define MEM_STATS 0 +#define MEMP_STATS 0 +#define SYS_STATS 0 +#define LWIP_STATS_DISPLAY 0 +#define ETHARP_STATS 0 + +#endif /* LWIP_STATS */ + +/* + --------------------------------- + ---------- PPP options ---------- + --------------------------------- +*/ +/** + * PPP_SUPPORT==1: Enable PPP. + */ +#ifndef PPP_SUPPORT +#define PPP_SUPPORT 0 +#endif + +/** + * PPPOE_SUPPORT==1: Enable PPP Over Ethernet + */ +#ifndef PPPOE_SUPPORT +#define PPPOE_SUPPORT 0 +#endif + +/** + * PPPOS_SUPPORT==1: Enable PPP Over Serial + */ +#ifndef PPPOS_SUPPORT +#define PPPOS_SUPPORT PPP_SUPPORT +#endif + +#if PPP_SUPPORT + +/** + * NUM_PPP: Max PPP sessions. + */ +#ifndef NUM_PPP +#define NUM_PPP 1 +#endif + +/** + * PAP_SUPPORT==1: Support PAP. + */ +#ifndef PAP_SUPPORT +#define PAP_SUPPORT 0 +#endif + +/** + * CHAP_SUPPORT==1: Support CHAP. + */ +#ifndef CHAP_SUPPORT +#define CHAP_SUPPORT 0 +#endif + +/** + * MSCHAP_SUPPORT==1: Support MSCHAP. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef MSCHAP_SUPPORT +#define MSCHAP_SUPPORT 0 +#endif + +/** + * CBCP_SUPPORT==1: Support CBCP. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef CBCP_SUPPORT +#define CBCP_SUPPORT 0 +#endif + +/** + * CCP_SUPPORT==1: Support CCP. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef CCP_SUPPORT +#define CCP_SUPPORT 0 +#endif + +/** + * VJ_SUPPORT==1: Support VJ header compression. + */ +#ifndef VJ_SUPPORT +#define VJ_SUPPORT 0 +#endif + +/** + * MD5_SUPPORT==1: Support MD5 (see also CHAP). + */ +#ifndef MD5_SUPPORT +#define MD5_SUPPORT 0 +#endif + +/* + * Timeouts + */ +#ifndef FSM_DEFTIMEOUT +#define FSM_DEFTIMEOUT 6 /* Timeout time in seconds */ +#endif + +#ifndef FSM_DEFMAXTERMREQS +#define FSM_DEFMAXTERMREQS 2 /* Maximum Terminate-Request transmissions */ +#endif + +#ifndef FSM_DEFMAXCONFREQS +#define FSM_DEFMAXCONFREQS 10 /* Maximum Configure-Request transmissions */ +#endif + +#ifndef FSM_DEFMAXNAKLOOPS +#define FSM_DEFMAXNAKLOOPS 5 /* Maximum number of nak loops */ +#endif + +#ifndef UPAP_DEFTIMEOUT +#define UPAP_DEFTIMEOUT 6 /* Timeout (seconds) for retransmitting req */ +#endif + +#ifndef UPAP_DEFREQTIME +#define UPAP_DEFREQTIME 30 /* Time to wait for auth-req from peer */ +#endif + +#ifndef CHAP_DEFTIMEOUT +#define CHAP_DEFTIMEOUT 6 /* Timeout time in seconds */ +#endif + +#ifndef CHAP_DEFTRANSMITS +#define CHAP_DEFTRANSMITS 10 /* max # times to send challenge */ +#endif + +/* Interval in seconds between keepalive echo requests, 0 to disable. */ +#ifndef LCP_ECHOINTERVAL +#define LCP_ECHOINTERVAL 0 +#endif + +/* Number of unanswered echo requests before failure. */ +#ifndef LCP_MAXECHOFAILS +#define LCP_MAXECHOFAILS 3 +#endif + +/* Max Xmit idle time (in jiffies) before resend flag char. */ +#ifndef PPP_MAXIDLEFLAG +#define PPP_MAXIDLEFLAG 100 +#endif + +/* + * Packet sizes + * + * Note - lcp shouldn't be allowed to negotiate stuff outside these + * limits. See lcp.h in the pppd directory. + * (XXX - these constants should simply be shared by lcp.c instead + * of living in lcp.h) + */ +#define PPP_MTU 1500 /* Default MTU (size of Info field) */ +#ifndef PPP_MAXMTU +/* #define PPP_MAXMTU 65535 - (PPP_HDRLEN + PPP_FCSLEN) */ +#define PPP_MAXMTU 1500 /* Largest MTU we allow */ +#endif +#define PPP_MINMTU 64 +#define PPP_MRU 1500 /* default MRU = max length of info field */ +#define PPP_MAXMRU 1500 /* Largest MRU we allow */ +#ifndef PPP_DEFMRU +#define PPP_DEFMRU 296 /* Try for this */ +#endif +#define PPP_MINMRU 128 /* No MRUs below this */ + +#ifndef MAXNAMELEN +#define MAXNAMELEN 256 /* max length of hostname or name for auth */ +#endif +#ifndef MAXSECRETLEN +#define MAXSECRETLEN 256 /* max length of password or secret */ +#endif + +#endif /* PPP_SUPPORT */ + +/* + -------------------------------------- + ---------- Checksum options ---------- + -------------------------------------- +*/ +/** + * CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets. + */ +#ifndef CHECKSUM_GEN_IP +#define CHECKSUM_GEN_IP 1 +#endif + +/** + * CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets. + */ +#ifndef CHECKSUM_GEN_UDP +#define CHECKSUM_GEN_UDP 1 +#endif + +/** + * CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets. + */ +#ifndef CHECKSUM_GEN_TCP +#define CHECKSUM_GEN_TCP 1 +#endif + +/** + * CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets. + */ +#ifndef CHECKSUM_CHECK_IP +#define CHECKSUM_CHECK_IP 1 +#endif + +/** + * CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets. + */ +#ifndef CHECKSUM_CHECK_UDP +#define CHECKSUM_CHECK_UDP 1 +#endif + +/** + * CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets. + */ +#ifndef CHECKSUM_CHECK_TCP +#define CHECKSUM_CHECK_TCP 1 +#endif + +/* + --------------------------------------- + ---------- Debugging options ---------- + --------------------------------------- +*/ +/** + * LWIP_DBG_MIN_LEVEL: After masking, the value of the debug is + * compared against this value. If it is smaller, then debugging + * messages are written. + */ +#ifndef LWIP_DBG_MIN_LEVEL +#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL +#endif + +/** + * LWIP_DBG_TYPES_ON: A mask that can be used to globally enable/disable + * debug messages of certain types. + */ +#ifndef LWIP_DBG_TYPES_ON +#define LWIP_DBG_TYPES_ON LWIP_DBG_ON +#endif + +/** + * ETHARP_DEBUG: Enable debugging in etharp.c. + */ +#ifndef ETHARP_DEBUG +#define ETHARP_DEBUG LWIP_DBG_OFF +#endif + +/** + * NETIF_DEBUG: Enable debugging in netif.c. + */ +#ifndef NETIF_DEBUG +#define NETIF_DEBUG LWIP_DBG_OFF +#endif + +/** + * PBUF_DEBUG: Enable debugging in pbuf.c. + */ +#ifndef PBUF_DEBUG +#define PBUF_DEBUG LWIP_DBG_OFF +#endif + +/** + * API_LIB_DEBUG: Enable debugging in api_lib.c. + */ +#ifndef API_LIB_DEBUG +#define API_LIB_DEBUG LWIP_DBG_OFF +#endif + +/** + * API_MSG_DEBUG: Enable debugging in api_msg.c. + */ +#ifndef API_MSG_DEBUG +#define API_MSG_DEBUG LWIP_DBG_OFF +#endif + +/** + * SOCKETS_DEBUG: Enable debugging in sockets.c. + */ +#ifndef SOCKETS_DEBUG +#define SOCKETS_DEBUG LWIP_DBG_OFF +#endif + +/** + * ICMP_DEBUG: Enable debugging in icmp.c. + */ +#ifndef ICMP_DEBUG +#define ICMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * IGMP_DEBUG: Enable debugging in igmp.c. + */ +#ifndef IGMP_DEBUG +#define IGMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * INET_DEBUG: Enable debugging in inet.c. + */ +#ifndef INET_DEBUG +#define INET_DEBUG LWIP_DBG_OFF +#endif + +/** + * IP_DEBUG: Enable debugging for IP. + */ +#ifndef IP_DEBUG +#define IP_DEBUG LWIP_DBG_OFF +#endif + +/** + * IP_REASS_DEBUG: Enable debugging in ip_frag.c for both frag & reass. + */ +#ifndef IP_REASS_DEBUG +#define IP_REASS_DEBUG LWIP_DBG_OFF +#endif + +/** + * RAW_DEBUG: Enable debugging in raw.c. + */ +#ifndef RAW_DEBUG +#define RAW_DEBUG LWIP_DBG_OFF +#endif + +/** + * MEM_DEBUG: Enable debugging in mem.c. + */ +#ifndef MEM_DEBUG +#define MEM_DEBUG LWIP_DBG_OFF +#endif + +/** + * MEMP_DEBUG: Enable debugging in memp.c. + */ +#ifndef MEMP_DEBUG +#define MEMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * SYS_DEBUG: Enable debugging in sys.c. + */ +#ifndef SYS_DEBUG +#define SYS_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_DEBUG: Enable debugging for TCP. + */ +#ifndef TCP_DEBUG +#define TCP_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_INPUT_DEBUG: Enable debugging in tcp_in.c for incoming debug. + */ +#ifndef TCP_INPUT_DEBUG +#define TCP_INPUT_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_FR_DEBUG: Enable debugging in tcp_in.c for fast retransmit. + */ +#ifndef TCP_FR_DEBUG +#define TCP_FR_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_RTO_DEBUG: Enable debugging in TCP for retransmit + * timeout. + */ +#ifndef TCP_RTO_DEBUG +#define TCP_RTO_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_CWND_DEBUG: Enable debugging for TCP congestion window. + */ +#ifndef TCP_CWND_DEBUG +#define TCP_CWND_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_WND_DEBUG: Enable debugging in tcp_in.c for window updating. + */ +#ifndef TCP_WND_DEBUG +#define TCP_WND_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_OUTPUT_DEBUG: Enable debugging in tcp_out.c output functions. + */ +#ifndef TCP_OUTPUT_DEBUG +#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_RST_DEBUG: Enable debugging for TCP with the RST message. + */ +#ifndef TCP_RST_DEBUG +#define TCP_RST_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_QLEN_DEBUG: Enable debugging for TCP queue lengths. + */ +#ifndef TCP_QLEN_DEBUG +#define TCP_QLEN_DEBUG LWIP_DBG_OFF +#endif + +/** + * UDP_DEBUG: Enable debugging in UDP. + */ +#ifndef UDP_DEBUG +#define UDP_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCPIP_DEBUG: Enable debugging in tcpip.c. + */ +#ifndef TCPIP_DEBUG +#define TCPIP_DEBUG LWIP_DBG_OFF +#endif + +/** + * PPP_DEBUG: Enable debugging for PPP. + */ +#ifndef PPP_DEBUG +#define PPP_DEBUG LWIP_DBG_OFF +#endif + +/** + * SLIP_DEBUG: Enable debugging in slipif.c. + */ +#ifndef SLIP_DEBUG +#define SLIP_DEBUG LWIP_DBG_OFF +#endif + +/** + * DHCP_DEBUG: Enable debugging in dhcp.c. + */ +#ifndef DHCP_DEBUG +#define DHCP_DEBUG LWIP_DBG_OFF +#endif + +/** + * AUTOIP_DEBUG: Enable debugging in autoip.c. + */ +#ifndef AUTOIP_DEBUG +#define AUTOIP_DEBUG LWIP_DBG_OFF +#endif + +/** + * SNMP_MSG_DEBUG: Enable debugging for SNMP messages. + */ +#ifndef SNMP_MSG_DEBUG +#define SNMP_MSG_DEBUG LWIP_DBG_OFF +#endif + +/** + * SNMP_MIB_DEBUG: Enable debugging for SNMP MIBs. + */ +#ifndef SNMP_MIB_DEBUG +#define SNMP_MIB_DEBUG LWIP_DBG_OFF +#endif + +/** + * DNS_DEBUG: Enable debugging for DNS. + */ +#ifndef DNS_DEBUG +#define DNS_DEBUG LWIP_DBG_OFF +#endif + +#endif /* __LWIP_OPT_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/pbuf.h b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/pbuf.h new file mode 100644 index 0000000..4156c36 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/pbuf.h @@ -0,0 +1,120 @@ +/** + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#ifndef __LWIP_PBUF_H__ +#define __LWIP_PBUF_H__ + +#include "lwip/opt.h" +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define PBUF_TRANSPORT_HLEN 20 +#define PBUF_IP_HLEN 20 + +typedef enum { + PBUF_TRANSPORT, + PBUF_IP, + PBUF_LINK, + PBUF_RAW +} pbuf_layer; + +typedef enum { + PBUF_RAM, /* pbuf data is stored in RAM */ + PBUF_ROM, /* pbuf data is stored in ROM */ + PBUF_REF, /* pbuf comes from the pbuf pool */ + PBUF_POOL /* pbuf payload refers to RAM */ +} pbuf_type; + + +/** indicates this packet's data should be immediately passed to the application */ +#define PBUF_FLAG_PUSH 0x01U + +struct pbuf { + /** next pbuf in singly linked pbuf chain */ + struct pbuf *next; + + /** pointer to the actual data in the buffer */ + void *payload; + + /** + * total length of this buffer and all next buffers in chain + * belonging to the same packet. + * + * For non-queue packet chains this is the invariant: + * p->tot_len == p->len + (p->next? p->next->tot_len: 0) + */ + u16_t tot_len; + + /** length of this buffer */ + u16_t len; + + /** pbuf_type as u8_t instead of enum to save space */ + u8_t /*pbuf_type*/ type; + + /** misc flags */ + u8_t flags; + + /** + * the reference count always equals the number of pointers + * that refer to this pbuf. This can be pointers from an application, + * the stack itself, or pbuf->next pointers from a chain. + */ + u16_t ref; + +}; + +/* Initializes the pbuf module. This call is empty for now, but may not be in future. */ +#define pbuf_init() + +struct pbuf *pbuf_alloc(pbuf_layer l, u16_t size, pbuf_type type); +void pbuf_realloc(struct pbuf *p, u16_t size); +u8_t pbuf_header(struct pbuf *p, s16_t header_size); +void pbuf_ref(struct pbuf *p); +void pbuf_ref_chain(struct pbuf *p); +u8_t pbuf_free(struct pbuf *p); +u8_t pbuf_clen(struct pbuf *p); +void pbuf_cat(struct pbuf *head, struct pbuf *tail); +void pbuf_chain(struct pbuf *head, struct pbuf *tail); +struct pbuf *pbuf_dechain(struct pbuf *p); +err_t pbuf_copy(struct pbuf *p_to, struct pbuf *p_from); +u16_t pbuf_copy_partial(struct pbuf *p, void *dataptr, u16_t len, u16_t offset); +err_t pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len); +struct pbuf *pbuf_coalesce(struct pbuf *p, pbuf_layer layer); + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_PBUF_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/raw.h b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/raw.h new file mode 100644 index 0000000..659ad9d --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/raw.h @@ -0,0 +1,97 @@ +/** + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + **/ +#ifndef __LWIP_RAW_H__ +#define __LWIP_RAW_H__ + +#include "lwip/opt.h" + +#if LWIP_RAW /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/inet.h" +#include "lwip/ip.h" +#include "lwip/ip_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct raw_pcb { +/* Common members of all PCB types */ + IP_PCB; + + struct raw_pcb *next; + + u8_t protocol; + + /* receive callback function + * @param arg user supplied argument (raw_pcb.recv_arg) + * @param pcb the raw_pcb which received data + * @param p the packet buffer that was received + * @param addr the remote IP address from which the packet was received + * @return 1 if the packet was 'eaten' (aka. deleted), + * 0 if the packet lives on + * If returning 1, the callback is responsible for freeing the pbuf + * if it's not used any more. + */ + u8_t (* recv)(void *arg, struct raw_pcb *pcb, struct pbuf *p, + struct ip_addr *addr); + /* user-supplied argument for the recv callback */ + void *recv_arg; +}; + +/* The following functions is the application layer interface to the + RAW code. */ +struct raw_pcb * raw_new (u8_t proto); +void raw_remove (struct raw_pcb *pcb); +err_t raw_bind (struct raw_pcb *pcb, struct ip_addr *ipaddr); +err_t raw_connect (struct raw_pcb *pcb, struct ip_addr *ipaddr); + +void raw_recv (struct raw_pcb *pcb, + u8_t (* recv)(void *arg, struct raw_pcb *pcb, + struct pbuf *p, + struct ip_addr *addr), + void *recv_arg); +err_t raw_sendto (struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr); +err_t raw_send (struct raw_pcb *pcb, struct pbuf *p); + +/* The following functions are the lower layer interface to RAW. */ +u8_t raw_input (struct pbuf *p, struct netif *inp); +#define raw_init() /* Compatibility define, not init needed. */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_RAW */ + +#endif /* __LWIP_RAW_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/sio.h b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/sio.h new file mode 100644 index 0000000..28ae2f2 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/sio.h @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + */ + +/* + * This is the interface to the platform specific serial IO module + * It needs to be implemented by those platforms which need SLIP or PPP + */ + +#ifndef __SIO_H__ +#define __SIO_H__ + +#include "lwip/arch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* If you want to define sio_fd_t elsewhere or differently, + define this in your cc.h file. */ +#ifndef __sio_fd_t_defined +typedef void * sio_fd_t; +#endif + +/* The following functions can be defined to something else in your cc.h file + or be implemented in your custom sio.c file. */ + +#ifndef sio_open +/** + * Opens a serial device for communication. + * + * @param devnum device number + * @return handle to serial device if successful, NULL otherwise + */ +sio_fd_t sio_open(u8_t devnum); +#endif + +#ifndef sio_send +/** + * Sends a single character to the serial device. + * + * @param c character to send + * @param fd serial device handle + * + * @note This function will block until the character can be sent. + */ +void sio_send(u8_t c, sio_fd_t fd); +#endif + +#ifndef sio_recv +/** + * Receives a single character from the serial device. + * + * @param fd serial device handle + * + * @note This function will block until a character is received. + */ +u8_t sio_recv(sio_fd_t fd); +#endif + +#ifndef sio_read +/** + * Reads from the serial device. + * + * @param fd serial device handle + * @param data pointer to data buffer for receiving + * @param len maximum length (in bytes) of data to receive + * @return number of bytes actually received - may be 0 if aborted by sio_read_abort + * + * @note This function will block until data can be received. The blocking + * can be cancelled by calling sio_read_abort(). + */ +u32_t sio_read(sio_fd_t fd, u8_t *data, u32_t len); +#endif + +#ifndef sio_tryread +/** + * Tries to read from the serial device. Same as sio_read but returns + * immediately if no data is available and never blocks. + * + * @param fd serial device handle + * @param data pointer to data buffer for receiving + * @param len maximum length (in bytes) of data to receive + * @return number of bytes actually received + */ +u32_t sio_tryread(sio_fd_t fd, u8_t *data, u32_t len); +#endif + +#ifndef sio_write +/** + * Writes to the serial device. + * + * @param fd serial device handle + * @param data pointer to data to send + * @param len length (in bytes) of data to send + * @return number of bytes actually sent + * + * @note This function will block until all data can be sent. + */ +u32_t sio_write(sio_fd_t fd, u8_t *data, u32_t len); +#endif + +#ifndef sio_read_abort +/** + * Aborts a blocking sio_read() call. + * + * @param fd serial device handle + */ +void sio_read_abort(sio_fd_t fd); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __SIO_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/snmp.h b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/snmp.h new file mode 100644 index 0000000..20bbce5 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/snmp.h @@ -0,0 +1,364 @@ +/** + * Copyright (c) 2001, 2002 Leon Woestenberg + * Copyright (c) 2001, 2002 Axon Digital Design B.V., The Netherlands. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Leon Woestenberg + * + **/ +#ifndef __LWIP_SNMP_H__ +#define __LWIP_SNMP_H__ + +#include "lwip/opt.h" +#include "lwip/netif.h" +#include "lwip/udp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @see RFC1213, "MIB-II, 6. Definitions" + */ +enum snmp_ifType { + snmp_ifType_other=1, /* none of the following */ + snmp_ifType_regular1822, + snmp_ifType_hdh1822, + snmp_ifType_ddn_x25, + snmp_ifType_rfc877_x25, + snmp_ifType_ethernet_csmacd, + snmp_ifType_iso88023_csmacd, + snmp_ifType_iso88024_tokenBus, + snmp_ifType_iso88025_tokenRing, + snmp_ifType_iso88026_man, + snmp_ifType_starLan, + snmp_ifType_proteon_10Mbit, + snmp_ifType_proteon_80Mbit, + snmp_ifType_hyperchannel, + snmp_ifType_fddi, + snmp_ifType_lapb, + snmp_ifType_sdlc, + snmp_ifType_ds1, /* T-1 */ + snmp_ifType_e1, /* european equiv. of T-1 */ + snmp_ifType_basicISDN, + snmp_ifType_primaryISDN, /* proprietary serial */ + snmp_ifType_propPointToPointSerial, + snmp_ifType_ppp, + snmp_ifType_softwareLoopback, + snmp_ifType_eon, /* CLNP over IP [11] */ + snmp_ifType_ethernet_3Mbit, + snmp_ifType_nsip, /* XNS over IP */ + snmp_ifType_slip, /* generic SLIP */ + snmp_ifType_ultra, /* ULTRA technologies */ + snmp_ifType_ds3, /* T-3 */ + snmp_ifType_sip, /* SMDS */ + snmp_ifType_frame_relay +}; + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +/** SNMP "sysuptime" Interval */ +#define SNMP_SYSUPTIME_INTERVAL 10 + +/** fixed maximum length for object identifier type */ +#define LWIP_SNMP_OBJ_ID_LEN 32 + +/** internal object identifier representation */ +struct snmp_obj_id +{ + u8_t len; + s32_t id[LWIP_SNMP_OBJ_ID_LEN]; +}; + +/* system */ +void snmp_set_sysdesr(u8_t* str, u8_t* len); +void snmp_set_sysobjid(struct snmp_obj_id *oid); +void snmp_get_sysobjid_ptr(struct snmp_obj_id **oid); +void snmp_inc_sysuptime(void); +void snmp_add_sysuptime(u32_t value); +void snmp_get_sysuptime(u32_t *value); +void snmp_set_syscontact(u8_t *ocstr, u8_t *ocstrlen); +void snmp_set_sysname(u8_t *ocstr, u8_t *ocstrlen); +void snmp_set_syslocation(u8_t *ocstr, u8_t *ocstrlen); + +/* network interface */ +void snmp_add_ifinoctets(struct netif *ni, u32_t value); +void snmp_inc_ifinucastpkts(struct netif *ni); +void snmp_inc_ifinnucastpkts(struct netif *ni); +void snmp_inc_ifindiscards(struct netif *ni); +void snmp_add_ifoutoctets(struct netif *ni, u32_t value); +void snmp_inc_ifoutucastpkts(struct netif *ni); +void snmp_inc_ifoutnucastpkts(struct netif *ni); +void snmp_inc_ifoutdiscards(struct netif *ni); +void snmp_inc_iflist(void); +void snmp_dec_iflist(void); + +/* ARP (for atTable and ipNetToMediaTable) */ +void snmp_insert_arpidx_tree(struct netif *ni, struct ip_addr *ip); +void snmp_delete_arpidx_tree(struct netif *ni, struct ip_addr *ip); + +/* IP */ +void snmp_inc_ipinreceives(void); +void snmp_inc_ipinhdrerrors(void); +void snmp_inc_ipinaddrerrors(void); +void snmp_inc_ipforwdatagrams(void); +void snmp_inc_ipinunknownprotos(void); +void snmp_inc_ipindiscards(void); +void snmp_inc_ipindelivers(void); +void snmp_inc_ipoutrequests(void); +void snmp_inc_ipoutdiscards(void); +void snmp_inc_ipoutnoroutes(void); +void snmp_inc_ipreasmreqds(void); +void snmp_inc_ipreasmoks(void); +void snmp_inc_ipreasmfails(void); +void snmp_inc_ipfragoks(void); +void snmp_inc_ipfragfails(void); +void snmp_inc_ipfragcreates(void); +void snmp_inc_iproutingdiscards(void); +void snmp_insert_ipaddridx_tree(struct netif *ni); +void snmp_delete_ipaddridx_tree(struct netif *ni); +void snmp_insert_iprteidx_tree(u8_t dflt, struct netif *ni); +void snmp_delete_iprteidx_tree(u8_t dflt, struct netif *ni); + +/* ICMP */ +void snmp_inc_icmpinmsgs(void); +void snmp_inc_icmpinerrors(void); +void snmp_inc_icmpindestunreachs(void); +void snmp_inc_icmpintimeexcds(void); +void snmp_inc_icmpinparmprobs(void); +void snmp_inc_icmpinsrcquenchs(void); +void snmp_inc_icmpinredirects(void); +void snmp_inc_icmpinechos(void); +void snmp_inc_icmpinechoreps(void); +void snmp_inc_icmpintimestamps(void); +void snmp_inc_icmpintimestampreps(void); +void snmp_inc_icmpinaddrmasks(void); +void snmp_inc_icmpinaddrmaskreps(void); +void snmp_inc_icmpoutmsgs(void); +void snmp_inc_icmpouterrors(void); +void snmp_inc_icmpoutdestunreachs(void); +void snmp_inc_icmpouttimeexcds(void); +void snmp_inc_icmpoutparmprobs(void); +void snmp_inc_icmpoutsrcquenchs(void); +void snmp_inc_icmpoutredirects(void); +void snmp_inc_icmpoutechos(void); +void snmp_inc_icmpoutechoreps(void); +void snmp_inc_icmpouttimestamps(void); +void snmp_inc_icmpouttimestampreps(void); +void snmp_inc_icmpoutaddrmasks(void); +void snmp_inc_icmpoutaddrmaskreps(void); + +/* TCP */ +void snmp_inc_tcpactiveopens(void); +void snmp_inc_tcppassiveopens(void); +void snmp_inc_tcpattemptfails(void); +void snmp_inc_tcpestabresets(void); +void snmp_inc_tcpinsegs(void); +void snmp_inc_tcpoutsegs(void); +void snmp_inc_tcpretranssegs(void); +void snmp_inc_tcpinerrs(void); +void snmp_inc_tcpoutrsts(void); + +/* UDP */ +void snmp_inc_udpindatagrams(void); +void snmp_inc_udpnoports(void); +void snmp_inc_udpinerrors(void); +void snmp_inc_udpoutdatagrams(void); +void snmp_insert_udpidx_tree(struct udp_pcb *pcb); +void snmp_delete_udpidx_tree(struct udp_pcb *pcb); + +/* SNMP */ +void snmp_inc_snmpinpkts(void); +void snmp_inc_snmpoutpkts(void); +void snmp_inc_snmpinbadversions(void); +void snmp_inc_snmpinbadcommunitynames(void); +void snmp_inc_snmpinbadcommunityuses(void); +void snmp_inc_snmpinasnparseerrs(void); +void snmp_inc_snmpintoobigs(void); +void snmp_inc_snmpinnosuchnames(void); +void snmp_inc_snmpinbadvalues(void); +void snmp_inc_snmpinreadonlys(void); +void snmp_inc_snmpingenerrs(void); +void snmp_add_snmpintotalreqvars(u8_t value); +void snmp_add_snmpintotalsetvars(u8_t value); +void snmp_inc_snmpingetrequests(void); +void snmp_inc_snmpingetnexts(void); +void snmp_inc_snmpinsetrequests(void); +void snmp_inc_snmpingetresponses(void); +void snmp_inc_snmpintraps(void); +void snmp_inc_snmpouttoobigs(void); +void snmp_inc_snmpoutnosuchnames(void); +void snmp_inc_snmpoutbadvalues(void); +void snmp_inc_snmpoutgenerrs(void); +void snmp_inc_snmpoutgetrequests(void); +void snmp_inc_snmpoutgetnexts(void); +void snmp_inc_snmpoutsetrequests(void); +void snmp_inc_snmpoutgetresponses(void); +void snmp_inc_snmpouttraps(void); +void snmp_get_snmpgrpid_ptr(struct snmp_obj_id **oid); +void snmp_set_snmpenableauthentraps(u8_t *value); +void snmp_get_snmpenableauthentraps(u8_t *value); + +/* LWIP_SNMP support not available */ +/* define everything to be empty */ +#else + +/* system */ +#define snmp_set_sysdesr(str, len) +#define snmp_set_sysobjid(oid); +#define snmp_get_sysobjid_ptr(oid) +#define snmp_inc_sysuptime() +#define snmp_add_sysuptime(value) +#define snmp_get_sysuptime(value) +#define snmp_set_syscontact(ocstr, ocstrlen); +#define snmp_set_sysname(ocstr, ocstrlen); +#define snmp_set_syslocation(ocstr, ocstrlen); + +/* network interface */ +#define snmp_add_ifinoctets(ni,value) +#define snmp_inc_ifinucastpkts(ni) +#define snmp_inc_ifinnucastpkts(ni) +#define snmp_inc_ifindiscards(ni) +#define snmp_add_ifoutoctets(ni,value) +#define snmp_inc_ifoutucastpkts(ni) +#define snmp_inc_ifoutnucastpkts(ni) +#define snmp_inc_ifoutdiscards(ni) +#define snmp_inc_iflist() +#define snmp_dec_iflist() + +/* ARP */ +#define snmp_insert_arpidx_tree(ni,ip) +#define snmp_delete_arpidx_tree(ni,ip) + +/* IP */ +#define snmp_inc_ipinreceives() +#define snmp_inc_ipinhdrerrors() +#define snmp_inc_ipinaddrerrors() +#define snmp_inc_ipforwdatagrams() +#define snmp_inc_ipinunknownprotos() +#define snmp_inc_ipindiscards() +#define snmp_inc_ipindelivers() +#define snmp_inc_ipoutrequests() +#define snmp_inc_ipoutdiscards() +#define snmp_inc_ipoutnoroutes() +#define snmp_inc_ipreasmreqds() +#define snmp_inc_ipreasmoks() +#define snmp_inc_ipreasmfails() +#define snmp_inc_ipfragoks() +#define snmp_inc_ipfragfails() +#define snmp_inc_ipfragcreates() +#define snmp_inc_iproutingdiscards() +#define snmp_insert_ipaddridx_tree(ni) +#define snmp_delete_ipaddridx_tree(ni) +#define snmp_insert_iprteidx_tree(dflt, ni) +#define snmp_delete_iprteidx_tree(dflt, ni) + +/* ICMP */ +#define snmp_inc_icmpinmsgs() +#define snmp_inc_icmpinerrors() +#define snmp_inc_icmpindestunreachs() +#define snmp_inc_icmpintimeexcds() +#define snmp_inc_icmpinparmprobs() +#define snmp_inc_icmpinsrcquenchs() +#define snmp_inc_icmpinredirects() +#define snmp_inc_icmpinechos() +#define snmp_inc_icmpinechoreps() +#define snmp_inc_icmpintimestamps() +#define snmp_inc_icmpintimestampreps() +#define snmp_inc_icmpinaddrmasks() +#define snmp_inc_icmpinaddrmaskreps() +#define snmp_inc_icmpoutmsgs() +#define snmp_inc_icmpouterrors() +#define snmp_inc_icmpoutdestunreachs() +#define snmp_inc_icmpouttimeexcds() +#define snmp_inc_icmpoutparmprobs() +#define snmp_inc_icmpoutsrcquenchs() +#define snmp_inc_icmpoutredirects() +#define snmp_inc_icmpoutechos() +#define snmp_inc_icmpoutechoreps() +#define snmp_inc_icmpouttimestamps() +#define snmp_inc_icmpouttimestampreps() +#define snmp_inc_icmpoutaddrmasks() +#define snmp_inc_icmpoutaddrmaskreps() +/* TCP */ +#define snmp_inc_tcpactiveopens() +#define snmp_inc_tcppassiveopens() +#define snmp_inc_tcpattemptfails() +#define snmp_inc_tcpestabresets() +#define snmp_inc_tcpinsegs() +#define snmp_inc_tcpoutsegs() +#define snmp_inc_tcpretranssegs() +#define snmp_inc_tcpinerrs() +#define snmp_inc_tcpoutrsts() + +/* UDP */ +#define snmp_inc_udpindatagrams() +#define snmp_inc_udpnoports() +#define snmp_inc_udpinerrors() +#define snmp_inc_udpoutdatagrams() +#define snmp_insert_udpidx_tree(pcb) +#define snmp_delete_udpidx_tree(pcb) + +/* SNMP */ +#define snmp_inc_snmpinpkts() +#define snmp_inc_snmpoutpkts() +#define snmp_inc_snmpinbadversions() +#define snmp_inc_snmpinbadcommunitynames() +#define snmp_inc_snmpinbadcommunityuses() +#define snmp_inc_snmpinasnparseerrs() +#define snmp_inc_snmpintoobigs() +#define snmp_inc_snmpinnosuchnames() +#define snmp_inc_snmpinbadvalues() +#define snmp_inc_snmpinreadonlys() +#define snmp_inc_snmpingenerrs() +#define snmp_add_snmpintotalreqvars(value) +#define snmp_add_snmpintotalsetvars(value) +#define snmp_inc_snmpingetrequests() +#define snmp_inc_snmpingetnexts() +#define snmp_inc_snmpinsetrequests() +#define snmp_inc_snmpingetresponses() +#define snmp_inc_snmpintraps() +#define snmp_inc_snmpouttoobigs() +#define snmp_inc_snmpoutnosuchnames() +#define snmp_inc_snmpoutbadvalues() +#define snmp_inc_snmpoutgenerrs() +#define snmp_inc_snmpoutgetrequests() +#define snmp_inc_snmpoutgetnexts() +#define snmp_inc_snmpoutsetrequests() +#define snmp_inc_snmpoutgetresponses() +#define snmp_inc_snmpouttraps() +#define snmp_get_snmpgrpid_ptr(oid) +#define snmp_set_snmpenableauthentraps(value) +#define snmp_get_snmpenableauthentraps(value) + +#endif /* LWIP_SNMP */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_SNMP_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/snmp_asn1.h b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/snmp_asn1.h new file mode 100644 index 0000000..8a60288 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/snmp_asn1.h @@ -0,0 +1,101 @@ +/** + * @file + * Abstract Syntax Notation One (ISO 8824, 8825) codec. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * Author: Christiaan Simons + */ + +#ifndef __LWIP_SNMP_ASN1_H__ +#define __LWIP_SNMP_ASN1_H__ + +#include "lwip/opt.h" +#include "lwip/err.h" +#include "lwip/pbuf.h" +#include "lwip/snmp.h" + +#if LWIP_SNMP + +#ifdef __cplusplus +extern "C" { +#endif + +#define SNMP_ASN1_UNIV (!0x80 | !0x40) +#define SNMP_ASN1_APPLIC (!0x80 | 0x40) +#define SNMP_ASN1_CONTXT ( 0x80 | !0x40) + +#define SNMP_ASN1_CONSTR (0x20) +#define SNMP_ASN1_PRIMIT (!0x20) + +/* universal tags */ +#define SNMP_ASN1_INTEG 2 +#define SNMP_ASN1_OC_STR 4 +#define SNMP_ASN1_NUL 5 +#define SNMP_ASN1_OBJ_ID 6 +#define SNMP_ASN1_SEQ 16 + +/* application specific (SNMP) tags */ +#define SNMP_ASN1_IPADDR 0 /* octet string size(4) */ +#define SNMP_ASN1_COUNTER 1 /* u32_t */ +#define SNMP_ASN1_GAUGE 2 /* u32_t */ +#define SNMP_ASN1_TIMETICKS 3 /* u32_t */ +#define SNMP_ASN1_OPAQUE 4 /* octet string */ + +/* context specific (SNMP) tags */ +#define SNMP_ASN1_PDU_GET_REQ 0 +#define SNMP_ASN1_PDU_GET_NEXT_REQ 1 +#define SNMP_ASN1_PDU_GET_RESP 2 +#define SNMP_ASN1_PDU_SET_REQ 3 +#define SNMP_ASN1_PDU_TRAP 4 + +err_t snmp_asn1_dec_type(struct pbuf *p, u16_t ofs, u8_t *type); +err_t snmp_asn1_dec_length(struct pbuf *p, u16_t ofs, u8_t *octets_used, u16_t *length); +err_t snmp_asn1_dec_u32t(struct pbuf *p, u16_t ofs, u16_t len, u32_t *value); +err_t snmp_asn1_dec_s32t(struct pbuf *p, u16_t ofs, u16_t len, s32_t *value); +err_t snmp_asn1_dec_oid(struct pbuf *p, u16_t ofs, u16_t len, struct snmp_obj_id *oid); +err_t snmp_asn1_dec_raw(struct pbuf *p, u16_t ofs, u16_t len, u16_t raw_len, u8_t *raw); + +void snmp_asn1_enc_length_cnt(u16_t length, u8_t *octets_needed); +void snmp_asn1_enc_u32t_cnt(u32_t value, u16_t *octets_needed); +void snmp_asn1_enc_s32t_cnt(s32_t value, u16_t *octets_needed); +void snmp_asn1_enc_oid_cnt(u8_t ident_len, s32_t *ident, u16_t *octets_needed); +err_t snmp_asn1_enc_type(struct pbuf *p, u16_t ofs, u8_t type); +err_t snmp_asn1_enc_length(struct pbuf *p, u16_t ofs, u16_t length); +err_t snmp_asn1_enc_u32t(struct pbuf *p, u16_t ofs, u8_t octets_needed, u32_t value); +err_t snmp_asn1_enc_s32t(struct pbuf *p, u16_t ofs, u8_t octets_needed, s32_t value); +err_t snmp_asn1_enc_oid(struct pbuf *p, u16_t ofs, u8_t ident_len, s32_t *ident); +err_t snmp_asn1_enc_raw(struct pbuf *p, u16_t ofs, u8_t raw_len, u8_t *raw); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SNMP */ + +#endif /* __LWIP_SNMP_ASN1_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/snmp_msg.h b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/snmp_msg.h new file mode 100644 index 0000000..32ba8fb --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/snmp_msg.h @@ -0,0 +1,311 @@ +/** + * @file + * SNMP Agent message handling structures. + **/ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * Author: Christiaan Simons + */ + +#ifndef __LWIP_SNMP_MSG_H__ +#define __LWIP_SNMP_MSG_H__ + +#include "lwip/opt.h" +#include "lwip/snmp.h" +#include "lwip/snmp_structs.h" + +#if LWIP_SNMP + +#if SNMP_PRIVATE_MIB +#include "private_mib.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* The listen port of the SNMP agent. Clients have to make their requests to + this port. Most standard clients won't work if you change this! */ +#ifndef SNMP_IN_PORT +#define SNMP_IN_PORT 161 +#endif +/* The remote port the SNMP agent sends traps to. Most standard trap sinks won't + work if you change this! */ +#ifndef SNMP_TRAP_PORT +#define SNMP_TRAP_PORT 162 +#endif + +#define SNMP_ES_NOERROR 0 +#define SNMP_ES_TOOBIG 1 +#define SNMP_ES_NOSUCHNAME 2 +#define SNMP_ES_BADVALUE 3 +#define SNMP_ES_READONLY 4 +#define SNMP_ES_GENERROR 5 + +#define SNMP_GENTRAP_COLDSTART 0 +#define SNMP_GENTRAP_WARMSTART 1 +#define SNMP_GENTRAP_AUTHFAIL 4 +#define SNMP_GENTRAP_ENTERPRISESPC 6 + +struct snmp_varbind +{ + /* next pointer, NULL for last in list */ + struct snmp_varbind *next; + /* previous pointer, NULL for first in list */ + struct snmp_varbind *prev; + + /* object identifier length (in s32_t) */ + u8_t ident_len; + /* object identifier array */ + s32_t *ident; + + /* object value ASN1 type */ + u8_t value_type; + /* object value length (in u8_t) */ + u8_t value_len; + /* object value */ + void *value; + + /* encoding varbind seq length length */ + u8_t seqlenlen; + /* encoding object identifier length length */ + u8_t olenlen; + /* encoding object value length length */ + u8_t vlenlen; + /* encoding varbind seq length */ + u16_t seqlen; + /* encoding object identifier length */ + u16_t olen; + /* encoding object value length */ + u16_t vlen; +}; + +struct snmp_varbind_root +{ + struct snmp_varbind *head; + struct snmp_varbind *tail; + /* number of variable bindings in list */ + u8_t count; + /* encoding varbind-list seq length length */ + u8_t seqlenlen; + /* encoding varbind-list seq length */ + u16_t seqlen; +}; + +/** output response message header length fields */ +struct snmp_resp_header_lengths +{ + /* encoding error-index length length */ + u8_t erridxlenlen; + /* encoding error-status length length */ + u8_t errstatlenlen; + /* encoding request id length length */ + u8_t ridlenlen; + /* encoding pdu length length */ + u8_t pdulenlen; + /* encoding community length length */ + u8_t comlenlen; + /* encoding version length length */ + u8_t verlenlen; + /* encoding sequence length length */ + u8_t seqlenlen; + + /* encoding error-index length */ + u16_t erridxlen; + /* encoding error-status length */ + u16_t errstatlen; + /* encoding request id length */ + u16_t ridlen; + /* encoding pdu length */ + u16_t pdulen; + /* encoding community length */ + u16_t comlen; + /* encoding version length */ + u16_t verlen; + /* encoding sequence length */ + u16_t seqlen; +}; + +/** output response message header length fields */ +struct snmp_trap_header_lengths +{ + /* encoding timestamp length length */ + u8_t tslenlen; + /* encoding specific-trap length length */ + u8_t strplenlen; + /* encoding generic-trap length length */ + u8_t gtrplenlen; + /* encoding agent-addr length length */ + u8_t aaddrlenlen; + /* encoding enterprise-id length length */ + u8_t eidlenlen; + /* encoding pdu length length */ + u8_t pdulenlen; + /* encoding community length length */ + u8_t comlenlen; + /* encoding version length length */ + u8_t verlenlen; + /* encoding sequence length length */ + u8_t seqlenlen; + + /* encoding timestamp length */ + u16_t tslen; + /* encoding specific-trap length */ + u16_t strplen; + /* encoding generic-trap length */ + u16_t gtrplen; + /* encoding agent-addr length */ + u16_t aaddrlen; + /* encoding enterprise-id length */ + u16_t eidlen; + /* encoding pdu length */ + u16_t pdulen; + /* encoding community length */ + u16_t comlen; + /* encoding version length */ + u16_t verlen; + /* encoding sequence length */ + u16_t seqlen; +}; + +/* Accepting new SNMP messages. */ +#define SNMP_MSG_EMPTY 0 +/* Search for matching object for variable binding. */ +#define SNMP_MSG_SEARCH_OBJ 1 +/* Perform SNMP operation on in-memory object. + Pass-through states, for symmetry only. */ +#define SNMP_MSG_INTERNAL_GET_OBJDEF 2 +#define SNMP_MSG_INTERNAL_GET_VALUE 3 +#define SNMP_MSG_INTERNAL_SET_TEST 4 +#define SNMP_MSG_INTERNAL_GET_OBJDEF_S 5 +#define SNMP_MSG_INTERNAL_SET_VALUE 6 +/* Perform SNMP operation on object located externally. + In theory this could be used for building a proxy agent. + Practical use is for an enterprise spc. app. gateway. */ +#define SNMP_MSG_EXTERNAL_GET_OBJDEF 7 +#define SNMP_MSG_EXTERNAL_GET_VALUE 8 +#define SNMP_MSG_EXTERNAL_SET_TEST 9 +#define SNMP_MSG_EXTERNAL_GET_OBJDEF_S 10 +#define SNMP_MSG_EXTERNAL_SET_VALUE 11 + +#define SNMP_COMMUNITY_STR_LEN 64 +struct snmp_msg_pstat +{ + /* lwIP local port (161) binding */ + struct udp_pcb *pcb; + /* source IP address */ + struct ip_addr sip; + /* source UDP port */ + u16_t sp; + /* request type */ + u8_t rt; + /* request ID */ + s32_t rid; + /* error status */ + s32_t error_status; + /* error index */ + s32_t error_index; + /* community name (zero terminated) */ + u8_t community[SNMP_COMMUNITY_STR_LEN + 1]; + /* community string length (exclusive zero term) */ + u8_t com_strlen; + /* one out of MSG_EMPTY, MSG_DEMUX, MSG_INTERNAL, MSG_EXTERNAL_x */ + u8_t state; + /* saved arguments for MSG_EXTERNAL_x */ + struct mib_external_node *ext_mib_node; + struct snmp_name_ptr ext_name_ptr; + struct obj_def ext_object_def; + struct snmp_obj_id ext_oid; + /* index into input variable binding list */ + u8_t vb_idx; + /* ptr into input variable binding list */ + struct snmp_varbind *vb_ptr; + /* list of variable bindings from input */ + struct snmp_varbind_root invb; + /* list of variable bindings to output */ + struct snmp_varbind_root outvb; + /* output response lengths used in ASN encoding */ + struct snmp_resp_header_lengths rhl; +}; + +struct snmp_msg_trap +{ + /* lwIP local port (161) binding */ + struct udp_pcb *pcb; + /* destination IP address in network order */ + struct ip_addr dip; + + /* source enterprise ID (sysObjectID) */ + struct snmp_obj_id *enterprise; + /* source IP address, raw network order format */ + u8_t sip_raw[4]; + /* generic trap code */ + u32_t gen_trap; + /* specific trap code */ + u32_t spc_trap; + /* timestamp */ + u32_t ts; + /* list of variable bindings to output */ + struct snmp_varbind_root outvb; + /* output trap lengths used in ASN encoding */ + struct snmp_trap_header_lengths thl; +}; + +/** Agent Version constant, 0 = v1 oddity */ +extern const s32_t snmp_version; +/** Agent default "public" community string */ +extern const char snmp_publiccommunity[7]; + +extern struct snmp_msg_trap trap_msg; + +/** Agent setup, start listening to port 161. */ +void snmp_init(void); +void snmp_trap_dst_enable(u8_t dst_idx, u8_t enable); +void snmp_trap_dst_ip_set(u8_t dst_idx, struct ip_addr *dst); + +/** Varbind-list functions. */ +struct snmp_varbind* snmp_varbind_alloc(struct snmp_obj_id *oid, u8_t type, u8_t len); +void snmp_varbind_free(struct snmp_varbind *vb); +void snmp_varbind_list_free(struct snmp_varbind_root *root); +void snmp_varbind_tail_add(struct snmp_varbind_root *root, struct snmp_varbind *vb); +struct snmp_varbind* snmp_varbind_tail_remove(struct snmp_varbind_root *root); + +/** Handle an internal (recv) or external (private response) event. */ +void snmp_msg_event(u8_t request_id); +err_t snmp_send_response(struct snmp_msg_pstat *m_stat); +err_t snmp_send_trap(s8_t generic_trap, struct snmp_obj_id *eoid, s32_t specific_trap); +void snmp_coldstart_trap(void); +void snmp_authfail_trap(void); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SNMP */ + +#endif /* __LWIP_SNMP_MSG_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/snmp_structs.h b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/snmp_structs.h new file mode 100644 index 0000000..aa3f02e --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/snmp_structs.h @@ -0,0 +1,262 @@ +/** + * @file + * Generic MIB tree structures. + * + * @todo namespace prefixes + **/ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * Author: Christiaan Simons + */ + +#ifndef __LWIP_SNMP_STRUCTS_H__ +#define __LWIP_SNMP_STRUCTS_H__ + +#include "lwip/opt.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/snmp.h" + +#if SNMP_PRIVATE_MIB +#include "private_mib.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* MIB object instance */ +#define MIB_OBJECT_NONE 0 +#define MIB_OBJECT_SCALAR 1 +#define MIB_OBJECT_TAB 2 + +/* MIB object access */ +#define MIB_OBJECT_READ_ONLY 0 +#define MIB_OBJECT_READ_WRITE 1 +#define MIB_OBJECT_WRITE_ONLY 2 +#define MIB_OBJECT_NOT_ACCESSIBLE 3 + +/** object definition returned by (get_object_def)() */ +struct obj_def +{ + /* MIB_OBJECT_NONE (0), MIB_OBJECT_SCALAR (1), MIB_OBJECT_TAB (2) */ + u8_t instance; + /* 0 read-only, 1 read-write, 2 write-only, 3 not-accessible */ + u8_t access; + /* ASN type for this object */ + u8_t asn_type; + /* value length (host length) */ + u16_t v_len; + /* length of instance part of supplied object identifier */ + u8_t id_inst_len; + /* instance part of supplied object identifier */ + s32_t *id_inst_ptr; +}; + +struct snmp_name_ptr +{ + u8_t ident_len; + s32_t *ident; +}; + +/** MIB const scalar (.0) node */ +#define MIB_NODE_SC 0x01 +/** MIB const array node */ +#define MIB_NODE_AR 0x02 +/** MIB array node (mem_malloced from RAM) */ +#define MIB_NODE_RA 0x03 +/** MIB list root node (mem_malloced from RAM) */ +#define MIB_NODE_LR 0x04 +/** MIB node for external objects */ +#define MIB_NODE_EX 0x05 + +/** node "base class" layout, the mandatory fields for a node */ +struct mib_node +{ + /** returns struct obj_def for the given object identifier */ + void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od); + /** returns object value for the given object identifier, + @note the caller must allocate at least len bytes for the value */ + void (*get_value)(struct obj_def *od, u16_t len, void *value); + /** tests length and/or range BEFORE setting */ + u8_t (*set_test)(struct obj_def *od, u16_t len, void *value); + /** sets object value, only to be called when set_test() */ + void (*set_value)(struct obj_def *od, u16_t len, void *value); + /** One out of MIB_NODE_AR, MIB_NODE_LR or MIB_NODE_EX */ + const u8_t node_type; + /* array or max list length */ + const u16_t maxlength; +}; + +/** derived node for scalars .0 index */ +typedef struct mib_node mib_scalar_node; + +/** derived node, points to a fixed size const array + of sub-identifiers plus a 'child' pointer */ +struct mib_array_node +{ + /* inherited "base class" members */ + void (* const get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od); + void (* const get_value)(struct obj_def *od, u16_t len, void *value); + u8_t (*set_test)(struct obj_def *od, u16_t len, void *value); + void (*set_value)(struct obj_def *od, u16_t len, void *value); + + const u8_t node_type; + const u16_t maxlength; + + /* aditional struct members */ + const s32_t *objid; + struct mib_node* const *nptr; +}; + +/** derived node, points to a fixed size mem_malloced array + of sub-identifiers plus a 'child' pointer */ +struct mib_ram_array_node +{ + /* inherited "base class" members */ + void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od); + void (*get_value)(struct obj_def *od, u16_t len, void *value); + u8_t (*set_test)(struct obj_def *od, u16_t len, void *value); + void (*set_value)(struct obj_def *od, u16_t len, void *value); + + u8_t node_type; + u16_t maxlength; + + /* aditional struct members */ + s32_t *objid; + struct mib_node **nptr; +}; + +struct mib_list_node +{ + struct mib_list_node *prev; + struct mib_list_node *next; + s32_t objid; + struct mib_node *nptr; +}; + +/** derived node, points to a doubly linked list + of sub-identifiers plus a 'child' pointer */ +struct mib_list_rootnode +{ + /* inherited "base class" members */ + void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od); + void (*get_value)(struct obj_def *od, u16_t len, void *value); + u8_t (*set_test)(struct obj_def *od, u16_t len, void *value); + void (*set_value)(struct obj_def *od, u16_t len, void *value); + + u8_t node_type; + u16_t maxlength; + + /* aditional struct members */ + struct mib_list_node *head; + struct mib_list_node *tail; + /* counts list nodes in list */ + u16_t count; +}; + +/** derived node, has access functions for mib object in external memory or device + using 'tree_level' and 'idx', with a range 0 .. (level_length() - 1) */ +struct mib_external_node +{ + /* inherited "base class" members */ + void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od); + void (*get_value)(struct obj_def *od, u16_t len, void *value); + u8_t (*set_test)(struct obj_def *od, u16_t len, void *value); + void (*set_value)(struct obj_def *od, u16_t len, void *value); + + u8_t node_type; + u16_t maxlength; + + /* aditional struct members */ + /** points to an extenal (in memory) record of some sort of addressing + information, passed to and interpreted by the funtions below */ + void* addr_inf; + /** tree levels under this node */ + u8_t tree_levels; + /** number of objects at this level */ + u16_t (*level_length)(void* addr_inf, u8_t level); + /** compares object sub identifier with external id + return zero when equal, nonzero when unequal */ + s32_t (*ident_cmp)(void* addr_inf, u8_t level, u16_t idx, s32_t sub_id); + void (*get_objid)(void* addr_inf, u8_t level, u16_t idx, s32_t *sub_id); + + /** async Questions */ + void (*get_object_def_q)(void* addr_inf, u8_t rid, u8_t ident_len, s32_t *ident); + void (*get_value_q)(u8_t rid, struct obj_def *od); + void (*set_test_q)(u8_t rid, struct obj_def *od); + void (*set_value_q)(u8_t rid, struct obj_def *od, u16_t len, void *value); + /** async Answers */ + void (*get_object_def_a)(u8_t rid, u8_t ident_len, s32_t *ident, struct obj_def *od); + void (*get_value_a)(u8_t rid, struct obj_def *od, u16_t len, void *value); + u8_t (*set_test_a)(u8_t rid, struct obj_def *od, u16_t len, void *value); + void (*set_value_a)(u8_t rid, struct obj_def *od, u16_t len, void *value); + /** async Panic Close (agent returns error reply, + e.g. used for external transaction cleanup) */ + void (*get_object_def_pc)(u8_t rid, u8_t ident_len, s32_t *ident); + void (*get_value_pc)(u8_t rid, struct obj_def *od); + void (*set_test_pc)(u8_t rid, struct obj_def *od); + void (*set_value_pc)(u8_t rid, struct obj_def *od); +}; + +/** export MIB tree from mib2.c */ +extern const struct mib_array_node internet; + +/** dummy function pointers for non-leaf MIB nodes from mib2.c */ +void noleafs_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +void noleafs_get_value(struct obj_def *od, u16_t len, void *value); +u8_t noleafs_set_test(struct obj_def *od, u16_t len, void *value); +void noleafs_set_value(struct obj_def *od, u16_t len, void *value); + +void snmp_oidtoip(s32_t *ident, struct ip_addr *ip); +void snmp_iptooid(struct ip_addr *ip, s32_t *ident); +void snmp_ifindextonetif(s32_t ifindex, struct netif **netif); +void snmp_netiftoifindex(struct netif *netif, s32_t *ifidx); + +struct mib_list_node* snmp_mib_ln_alloc(s32_t id); +void snmp_mib_ln_free(struct mib_list_node *ln); +struct mib_list_rootnode* snmp_mib_lrn_alloc(void); +void snmp_mib_lrn_free(struct mib_list_rootnode *lrn); + +s8_t snmp_mib_node_insert(struct mib_list_rootnode *rn, s32_t objid, struct mib_list_node **insn); +s8_t snmp_mib_node_find(struct mib_list_rootnode *rn, s32_t objid, struct mib_list_node **fn); +struct mib_list_rootnode *snmp_mib_node_delete(struct mib_list_rootnode *rn, struct mib_list_node *n); + +struct mib_node* snmp_search_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct snmp_name_ptr *np); +struct mib_node* snmp_expand_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct snmp_obj_id *oidret); +u8_t snmp_iso_prefix_tst(u8_t ident_len, s32_t *ident); +u8_t snmp_iso_prefix_expand(u8_t ident_len, s32_t *ident, struct snmp_obj_id *oidret); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SNMP */ + +#endif /* __LWIP_SNMP_STRUCTS_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/sockets.h b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/sockets.h new file mode 100644 index 0000000..44a18e6 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/sockets.h @@ -0,0 +1,357 @@ +/** + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + **/ + + +#ifndef __LWIP_SOCKETS_H__ +#define __LWIP_SOCKETS_H__ + +#include "lwip/opt.h" + +#if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ + +#include /* for size_t */ + +#include "lwip/ip_addr.h" +#include "lwip/inet.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* members are in network byte order */ +struct sockaddr_in { + u8_t sin_len; + u8_t sin_family; + u16_t sin_port; + struct in_addr sin_addr; + char sin_zero[8]; +}; + +struct sockaddr { + u8_t sa_len; + u8_t sa_family; + char sa_data[14]; +}; + +#ifndef socklen_t +# define socklen_t u32_t +#endif + +/* Socket protocol types (TCP/UDP/RAW) */ +#define SOCK_STREAM 1 +#define SOCK_DGRAM 2 +#define SOCK_RAW 3 + +/* + * Option flags per-socket. These must match the SOF_ flags in ip.h! + */ +#define SO_DEBUG 0x0001 /* Unimplemented: turn on debugging info recording */ +#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */ +#define SO_REUSEADDR 0x0004 /* Unimplemented: allow local address reuse */ +#define SO_KEEPALIVE 0x0008 /* keep connections alive */ +#define SO_DONTROUTE 0x0010 /* Unimplemented: just use interface addresses */ +#define SO_BROADCAST 0x0020 /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */ +#define SO_USELOOPBACK 0x0040 /* Unimplemented: bypass hardware when possible */ +#define SO_LINGER 0x0080 /* linger on close if data present */ +#define SO_OOBINLINE 0x0100 /* Unimplemented: leave received OOB data in line */ +#define SO_REUSEPORT 0x0200 /* Unimplemented: allow local address & port reuse */ + +#define SO_DONTLINGER ((int)(~SO_LINGER)) + +/* + * Additional options, not kept in so_options. + */ +#define SO_SNDBUF 0x1001 /* Unimplemented: send buffer size */ +#define SO_RCVBUF 0x1002 /* receive buffer size */ +#define SO_SNDLOWAT 0x1003 /* Unimplemented: send low-water mark */ +#define SO_RCVLOWAT 0x1004 /* Unimplemented: receive low-water mark */ +#define SO_SNDTIMEO 0x1005 /* Unimplemented: send timeout */ +#define SO_RCVTIMEO 0x1006 /* receive timeout */ +#define SO_ERROR 0x1007 /* get error status and clear */ +#define SO_TYPE 0x1008 /* get socket type */ +#define SO_CONTIMEO 0x1009 /* Unimplemented: connect timeout */ +#define SO_NO_CHECK 0x100a /* don't create UDP checksum */ + + +/* + * Structure used for manipulating linger option. + */ +struct linger { + int l_onoff; /* option on/off */ + int l_linger; /* linger time */ +}; + +/* + * Level number for (get/set)sockopt() to apply to socket itself. + */ +#define SOL_SOCKET 0xfff /* options for socket level */ + + +#define AF_UNSPEC 0 +#define AF_INET 2 +#define PF_INET AF_INET +#define PF_UNSPEC AF_UNSPEC + +#define IPPROTO_IP 0 +#define IPPROTO_TCP 6 +#define IPPROTO_UDP 17 +#define IPPROTO_UDPLITE 136 + +/* Flags we can use with send and recv. */ +#define MSG_PEEK 0x01 /* Peeks at an incoming message */ +#define MSG_WAITALL 0x02 /* Unimplemented: Requests that the function block until the full amount of data requested can be returned */ +#define MSG_OOB 0x04 /* Unimplemented: Requests out-of-band data. The significance and semantics of out-of-band data are protocol-specific */ +#define MSG_DONTWAIT 0x08 /* Nonblocking i/o for this operation only */ +#define MSG_MORE 0x10 /* Sender will send more */ + + +/* + * Options for level IPPROTO_IP + */ +#define IP_TOS 1 +#define IP_TTL 2 + +#if LWIP_TCP +/* + * Options for level IPPROTO_TCP + */ +#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */ +#define TCP_KEEPALIVE 0x02 /* send KEEPALIVE probes when idle for pcb->keep_idle milliseconds */ +#define TCP_KEEPIDLE 0x03 /* set pcb->keep_idle - Same as TCP_KEEPALIVE, but use seconds for get/setsockopt */ +#define TCP_KEEPINTVL 0x04 /* set pcb->keep_intvl - Use seconds for get/setsockopt */ +#define TCP_KEEPCNT 0x05 /* set pcb->keep_cnt - Use number of probes sent for get/setsockopt */ +#endif /* LWIP_TCP */ + +#if LWIP_UDP && LWIP_UDPLITE +/* + * Options for level IPPROTO_UDPLITE + */ +#define UDPLITE_SEND_CSCOV 0x01 /* sender checksum coverage */ +#define UDPLITE_RECV_CSCOV 0x02 /* minimal receiver checksum coverage */ +#endif /* LWIP_UDP && LWIP_UDPLITE*/ + + +#if LWIP_IGMP +/* + * Options and types for UDP multicast traffic handling + */ +#define IP_ADD_MEMBERSHIP 3 +#define IP_DROP_MEMBERSHIP 4 +#define IP_MULTICAST_TTL 5 +#define IP_MULTICAST_IF 6 +#define IP_MULTICAST_LOOP 7 + +typedef struct ip_mreq { + struct in_addr imr_multiaddr; /* IP multicast address of group */ + struct in_addr imr_interface; /* local IP address of interface */ +} ip_mreq; +#endif /* LWIP_IGMP */ + +/* + * The Type of Service provides an indication of the abstract + * parameters of the quality of service desired. These parameters are + * to be used to guide the selection of the actual service parameters + * when transmitting a datagram through a particular network. Several + * networks offer service precedence, which somehow treats high + * precedence traffic as more important than other traffic (generally + * by accepting only traffic above a certain precedence at time of high + * load). The major choice is a three way tradeoff between low-delay, + * high-reliability, and high-throughput. + * The use of the Delay, Throughput, and Reliability indications may + * increase the cost (in some sense) of the service. In many networks + * better performance for one of these parameters is coupled with worse + * performance on another. Except for very unusual cases at most two + * of these three indications should be set. + */ +#define IPTOS_TOS_MASK 0x1E +#define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK) +#define IPTOS_LOWDELAY 0x10 +#define IPTOS_THROUGHPUT 0x08 +#define IPTOS_RELIABILITY 0x04 +#define IPTOS_LOWCOST 0x02 +#define IPTOS_MINCOST IPTOS_LOWCOST + +/* + * The Network Control precedence designation is intended to be used + * within a network only. The actual use and control of that + * designation is up to each network. The Internetwork Control + * designation is intended for use by gateway control originators only. + * If the actual use of these precedence designations is of concern to + * a particular network, it is the responsibility of that network to + * control the access to, and use of, those precedence designations. + */ +#define IPTOS_PREC_MASK 0xe0 +#define IPTOS_PREC(tos) ((tos) & IPTOS_PREC_MASK) +#define IPTOS_PREC_NETCONTROL 0xe0 +#define IPTOS_PREC_INTERNETCONTROL 0xc0 +#define IPTOS_PREC_CRITIC_ECP 0xa0 +#define IPTOS_PREC_FLASHOVERRIDE 0x80 +#define IPTOS_PREC_FLASH 0x60 +#define IPTOS_PREC_IMMEDIATE 0x40 +#define IPTOS_PREC_PRIORITY 0x20 +#define IPTOS_PREC_ROUTINE 0x00 + + +/* + * Commands for ioctlsocket(), taken from the BSD file fcntl.h. + * lwip_ioctl only supports FIONREAD and FIONBIO, for now + * + * Ioctl's have the command encoded in the lower word, + * and the size of any in or out parameters in the upper + * word. The high 2 bits of the upper word are used + * to encode the in/out status of the parameter; for now + * we restrict parameters to at most 128 bytes. + */ +#if !defined(FIONREAD) || !defined(FIONBIO) +#define IOCPARM_MASK 0x7fU /* parameters must be < 128 bytes */ +#define IOC_VOID 0x20000000UL /* no parameters */ +#define IOC_OUT 0x40000000UL /* copy out parameters */ +#define IOC_IN 0x80000000UL /* copy in parameters */ +#define IOC_INOUT (IOC_IN|IOC_OUT) + /* 0x20000000 distinguishes new & + old ioctl's */ +#define _IO(x,y) (IOC_VOID|((x)<<8)|(y)) + +#define _IOR(x,y,t) (IOC_OUT|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) + +#define _IOW(x,y,t) (IOC_IN|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) +#endif /* !defined(FIONREAD) || !defined(FIONBIO) */ + +#ifndef FIONREAD +#define FIONREAD _IOR('f', 127, unsigned long) /* get # bytes to read */ +#endif +#ifndef FIONBIO +#define FIONBIO _IOW('f', 126, unsigned long) /* set/clear non-blocking i/o */ +#endif + +/* Socket I/O Controls: unimplemented */ +#ifndef SIOCSHIWAT +#define SIOCSHIWAT _IOW('s', 0, unsigned long) /* set high watermark */ +#define SIOCGHIWAT _IOR('s', 1, unsigned long) /* get high watermark */ +#define SIOCSLOWAT _IOW('s', 2, unsigned long) /* set low watermark */ +#define SIOCGLOWAT _IOR('s', 3, unsigned long) /* get low watermark */ +#define SIOCATMARK _IOR('s', 7, unsigned long) /* at oob mark? */ +#endif + +/* Socket flags: */ +#ifndef O_NONBLOCK +#define O_NONBLOCK 04000U +#endif + +/* FD_SET used for lwip_select */ +#ifndef FD_SET + #undef FD_SETSIZE + /* Make FD_SETSIZE match NUM_SOCKETS in socket.c */ + #define FD_SETSIZE MEMP_NUM_NETCONN + #define FD_SET(n, p) ((p)->fd_bits[(n)/8] |= (1 << ((n) & 7))) + #define FD_CLR(n, p) ((p)->fd_bits[(n)/8] &= ~(1 << ((n) & 7))) + #define FD_ISSET(n,p) ((p)->fd_bits[(n)/8] & (1 << ((n) & 7))) + #define FD_ZERO(p) memset((void*)(p),0,sizeof(*(p))) + + typedef struct fd_set { + unsigned char fd_bits [(FD_SETSIZE+7)/8]; + } fd_set; + +#endif /* FD_SET */ + +/** LWIP_TIMEVAL_PRIVATE: if you want to use the struct timeval provided + * by your system, set this to 0 and include in cc.h */ +#ifndef LWIP_TIMEVAL_PRIVATE +#define LWIP_TIMEVAL_PRIVATE 1 +#endif + +#if LWIP_TIMEVAL_PRIVATE +struct timeval { + long tv_sec; /* seconds */ + long tv_usec; /* and microseconds */ +}; +#endif /* LWIP_TIMEVAL_PRIVATE */ + +void lwip_socket_init(void); + +int lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen); +int lwip_bind(int s, const struct sockaddr *name, socklen_t namelen); +int lwip_shutdown(int s, int how); +int lwip_getpeername (int s, struct sockaddr *name, socklen_t *namelen); +int lwip_getsockname (int s, struct sockaddr *name, socklen_t *namelen); +int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *optlen); +int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_t optlen); +int lwip_close(int s); +int lwip_connect(int s, const struct sockaddr *name, socklen_t namelen); +int lwip_listen(int s, int backlog); +int lwip_recv(int s, void *mem, size_t len, int flags); +int lwip_read(int s, void *mem, size_t len); +int lwip_recvfrom(int s, void *mem, size_t len, int flags, + struct sockaddr *from, socklen_t *fromlen); +int lwip_send(int s, const void *dataptr, size_t size, int flags); +int lwip_sendto(int s, const void *dataptr, size_t size, int flags, + const struct sockaddr *to, socklen_t tolen); +int lwip_socket(int domain, int type, int protocol); +int lwip_write(int s, const void *dataptr, size_t size); +int lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, + struct timeval *timeout); +int lwip_ioctl(int s, long cmd, void *argp); + +#if LWIP_COMPAT_SOCKETS +#define accept(a,b,c) lwip_accept(a,b,c) +#define bind(a,b,c) lwip_bind(a,b,c) +#define shutdown(a,b) lwip_shutdown(a,b) +#define closesocket(s) lwip_close(s) +#define connect(a,b,c) lwip_connect(a,b,c) +#define getsockname(a,b,c) lwip_getsockname(a,b,c) +#define getpeername(a,b,c) lwip_getpeername(a,b,c) +#define setsockopt(a,b,c,d,e) lwip_setsockopt(a,b,c,d,e) +#define getsockopt(a,b,c,d,e) lwip_getsockopt(a,b,c,d,e) +#define listen(a,b) lwip_listen(a,b) +#define recv(a,b,c,d) lwip_recv(a,b,c,d) +#define recvfrom(a,b,c,d,e,f) lwip_recvfrom(a,b,c,d,e,f) +#define send(a,b,c,d) lwip_send(a,b,c,d) +#define sendto(a,b,c,d,e,f) lwip_sendto(a,b,c,d,e,f) +#define socket(a,b,c) lwip_socket(a,b,c) +#define select(a,b,c,d,e) lwip_select(a,b,c,d,e) +#define ioctlsocket(a,b,c) lwip_ioctl(a,b,c) + +#if LWIP_POSIX_SOCKETS_IO_NAMES +#define read(a,b,c) lwip_read(a,b,c) +#define write(a,b,c) lwip_write(a,b,c) +#define close(s) lwip_close(s) +#endif /* LWIP_POSIX_SOCKETS_IO_NAMES */ + +#endif /* LWIP_COMPAT_SOCKETS */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SOCKET */ + +#endif /* __LWIP_SOCKETS_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/stats.h b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/stats.h new file mode 100644 index 0000000..99878dc --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/stats.h @@ -0,0 +1,283 @@ +/** + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_STATS_H__ +#define __LWIP_STATS_H__ + +#include "lwip/opt.h" + +#include "lwip/mem.h" +#include "lwip/memp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_STATS + +#ifndef LWIP_STATS_LARGE +#define LWIP_STATS_LARGE 0 +#endif + +#if LWIP_STATS_LARGE +#define STAT_COUNTER u32_t +#define STAT_COUNTER_F U32_F +#else +#define STAT_COUNTER u16_t +#define STAT_COUNTER_F U16_F +#endif + +struct stats_proto { + STAT_COUNTER xmit; /* Transmitted packets. */ + STAT_COUNTER recv; /* Received packets. */ + STAT_COUNTER fw; /* Forwarded packets. */ + STAT_COUNTER drop; /* Dropped packets. */ + STAT_COUNTER chkerr; /* Checksum error. */ + STAT_COUNTER lenerr; /* Invalid length error. */ + STAT_COUNTER memerr; /* Out of memory error. */ + STAT_COUNTER rterr; /* Routing error. */ + STAT_COUNTER proterr; /* Protocol error. */ + STAT_COUNTER opterr; /* Error in options. */ + STAT_COUNTER err; /* Misc error. */ + STAT_COUNTER cachehit; +}; + +struct stats_igmp { + STAT_COUNTER lenerr; /* Invalid length error. */ + STAT_COUNTER chkerr; /* Checksum error. */ + STAT_COUNTER v1_rxed; /* */ + STAT_COUNTER join_sent; /* */ + STAT_COUNTER leave_sent; /* */ + STAT_COUNTER unicast_query; /* */ + STAT_COUNTER report_sent; /* */ + STAT_COUNTER report_rxed; /* */ + STAT_COUNTER group_query_rxed; /* */ +}; + +struct stats_mem { + mem_size_t avail; + mem_size_t used; + mem_size_t max; + STAT_COUNTER err; + STAT_COUNTER illegal; +}; + +struct stats_syselem { + STAT_COUNTER used; + STAT_COUNTER max; + STAT_COUNTER err; +}; + +struct stats_sys { + struct stats_syselem sem; + struct stats_syselem mbox; +}; + +struct stats_ { +#if LINK_STATS + struct stats_proto link; +#endif +#if ETHARP_STATS + struct stats_proto etharp; +#endif +#if IPFRAG_STATS + struct stats_proto ip_frag; +#endif +#if IP_STATS + struct stats_proto ip; +#endif +#if ICMP_STATS + struct stats_proto icmp; +#endif +#if IGMP_STATS + struct stats_igmp igmp; +#endif +#if UDP_STATS + struct stats_proto udp; +#endif +#if TCP_STATS + struct stats_proto tcp; +#endif +#if MEM_STATS + struct stats_mem mem; +#endif +#if MEMP_STATS + struct stats_mem memp[MEMP_MAX]; +#endif +#if SYS_STATS + struct stats_sys sys; +#endif +}; + +extern struct stats_ lwip_stats; + +#define stats_init() /* Compatibility define, not init needed. */ + +#define STATS_INC(x) ++lwip_stats.x +#define STATS_DEC(x) --lwip_stats.x +#else +#define stats_init() +#define STATS_INC(x) +#define STATS_DEC(x) +#endif /* LWIP_STATS */ + +#if TCP_STATS +#define TCP_STATS_INC(x) STATS_INC(x) +#define TCP_STATS_DISPLAY() stats_display_proto(&lwip_stats.tcp, "TCP") +#else +#define TCP_STATS_INC(x) +#define TCP_STATS_DISPLAY() +#endif + +#if UDP_STATS +#define UDP_STATS_INC(x) STATS_INC(x) +#define UDP_STATS_DISPLAY() stats_display_proto(&lwip_stats.udp, "UDP") +#else +#define UDP_STATS_INC(x) +#define UDP_STATS_DISPLAY() +#endif + +#if ICMP_STATS +#define ICMP_STATS_INC(x) STATS_INC(x) +#define ICMP_STATS_DISPLAY() stats_display_proto(&lwip_stats.icmp, "ICMP") +#else +#define ICMP_STATS_INC(x) +#define ICMP_STATS_DISPLAY() +#endif + +#if IGMP_STATS +#define IGMP_STATS_INC(x) STATS_INC(x) +#define IGMP_STATS_DISPLAY() stats_display_igmp(&lwip_stats.igmp) +#else +#define IGMP_STATS_INC(x) +#define IGMP_STATS_DISPLAY() +#endif + +#if IP_STATS +#define IP_STATS_INC(x) STATS_INC(x) +#define IP_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip, "IP") +#else +#define IP_STATS_INC(x) +#define IP_STATS_DISPLAY() +#endif + +#if IPFRAG_STATS +#define IPFRAG_STATS_INC(x) STATS_INC(x) +#define IPFRAG_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip_frag, "IP_FRAG") +#else +#define IPFRAG_STATS_INC(x) +#define IPFRAG_STATS_DISPLAY() +#endif + +#if ETHARP_STATS +#define ETHARP_STATS_INC(x) STATS_INC(x) +#define ETHARP_STATS_DISPLAY() stats_display_proto(&lwip_stats.etharp, "ETHARP") +#else +#define ETHARP_STATS_INC(x) +#define ETHARP_STATS_DISPLAY() +#endif + +#if LINK_STATS +#define LINK_STATS_INC(x) STATS_INC(x) +#define LINK_STATS_DISPLAY() stats_display_proto(&lwip_stats.link, "LINK") +#else +#define LINK_STATS_INC(x) +#define LINK_STATS_DISPLAY() +#endif + +#if MEM_STATS +#define MEM_STATS_AVAIL(x, y) lwip_stats.mem.x = y +#define MEM_STATS_INC(x) STATS_INC(mem.x) +#define MEM_STATS_INC_USED(x, y) do { lwip_stats.mem.used += y; \ + if (lwip_stats.mem.max < lwip_stats.mem.used) { \ + lwip_stats.mem.max = lwip_stats.mem.used; \ + } \ + } while(0) +#define MEM_STATS_DEC_USED(x, y) lwip_stats.mem.x -= y +#define MEM_STATS_DISPLAY() stats_display_mem(&lwip_stats.mem, "HEAP") +#else +#define MEM_STATS_AVAIL(x, y) +#define MEM_STATS_INC(x) +#define MEM_STATS_INC_USED(x, y) +#define MEM_STATS_DEC_USED(x, y) +#define MEM_STATS_DISPLAY() +#endif + +#if MEMP_STATS +#define MEMP_STATS_AVAIL(x, i, y) lwip_stats.memp[i].x = y +#define MEMP_STATS_INC(x, i) STATS_INC(memp[i].x) +#define MEMP_STATS_DEC(x, i) STATS_DEC(memp[i].x) +#define MEMP_STATS_INC_USED(x, i) do { ++lwip_stats.memp[i].used; \ + if (lwip_stats.memp[i].max < lwip_stats.memp[i].used) { \ + lwip_stats.memp[i].max = lwip_stats.memp[i].used; \ + } \ + } while(0) +#define MEMP_STATS_DISPLAY(i) stats_display_memp(&lwip_stats.memp[i], i) +#else +#define MEMP_STATS_AVAIL(x, i, y) +#define MEMP_STATS_INC(x, i) +#define MEMP_STATS_DEC(x, i) +#define MEMP_STATS_INC_USED(x, i) +#define MEMP_STATS_DISPLAY(i) +#endif + +#if SYS_STATS +#define SYS_STATS_INC(x) STATS_INC(sys.x) +#define SYS_STATS_DEC(x) STATS_DEC(sys.x) +#define SYS_STATS_DISPLAY() stats_display_sys(&lwip_stats.sys) +#else +#define SYS_STATS_INC(x) +#define SYS_STATS_DEC(x) +#define SYS_STATS_DISPLAY() +#endif + +/* Display of statistics */ +#if LWIP_STATS_DISPLAY +void stats_display(void); +void stats_display_proto(struct stats_proto *proto, char *name); +void stats_display_igmp(struct stats_igmp *igmp); +void stats_display_mem(struct stats_mem *mem, char *name); +void stats_display_memp(struct stats_mem *mem, int index); +void stats_display_sys(struct stats_sys *sys); +#else +#define stats_display() +#define stats_display_proto(proto, name) +#define stats_display_igmp(igmp) +#define stats_display_mem(mem, name) +#define stats_display_memp(mem, index) +#define stats_display_sys(sys) +#endif /* LWIP_STATS_DISPLAY */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_STATS_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/sys.h b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/sys.h new file mode 100644 index 0000000..b9a85ee --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/sys.h @@ -0,0 +1,243 @@ +/** + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + **/ +#ifndef __LWIP_SYS_H__ +#define __LWIP_SYS_H__ + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if NO_SYS + +/* For a totally minimal and standalone system, we provide null + definitions of the sys_ functions. */ +typedef u8_t sys_sem_t; +typedef u8_t sys_mbox_t; +struct sys_timeo {u8_t dummy;}; + +#define sys_init() +#define sys_timeout(m,h,a) +#define sys_untimeout(m,a) +#define sys_sem_new(c) c +#define sys_sem_signal(s) +#define sys_sem_wait(s) +#define sys_sem_wait_timeout(s,t) +#define sys_arch_sem_wait(s,t) +#define sys_sem_free(s) +#define sys_mbox_new(s) 0 +#define sys_mbox_fetch(m,d) +#define sys_mbox_tryfetch(m,d) +#define sys_mbox_post(m,d) +#define sys_mbox_trypost(m,d) +#define sys_mbox_free(m) + +#define sys_thread_new(n,t,a,s,p) + +#else /* NO_SYS */ + +/** Return code for timeouts from sys_arch_mbox_fetch and sys_arch_sem_wait */ +#define SYS_ARCH_TIMEOUT 0xffffffffUL + +/* sys_mbox_tryfetch returns SYS_MBOX_EMPTY if appropriate. + * For now we use the same magic value, but we allow this to change in future. + */ +#define SYS_MBOX_EMPTY SYS_ARCH_TIMEOUT + +#include "lwip/err.h" +#include "arch/sys_arch.h" + +typedef void (* sys_timeout_handler)(void *arg); + +struct sys_timeo { + struct sys_timeo *next; + u32_t time; + sys_timeout_handler h; + void *arg; +}; + +struct sys_timeouts { + struct sys_timeo *next; +}; + +/* sys_init() must be called before anthing else. */ +void sys_init(void); + +/* + * sys_timeout(): + * + * Schedule a timeout a specified amount of milliseconds in the + * future. When the timeout occurs, the specified timeout handler will + * be called. The handler will be passed the "arg" argument when + * called. + * + */ +void sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg); +void sys_untimeout(sys_timeout_handler h, void *arg); +struct sys_timeouts *sys_arch_timeouts(void); + +/* Semaphore functions. */ +sys_sem_t sys_sem_new(u8_t count); +void sys_sem_signal(sys_sem_t sem); +u32_t sys_arch_sem_wait(sys_sem_t sem, u32_t timeout); +void sys_sem_free(sys_sem_t sem); +void sys_sem_wait(sys_sem_t sem); +int sys_sem_wait_timeout(sys_sem_t sem, u32_t timeout); + +/* Time functions. */ +#ifndef sys_msleep +void sys_msleep(u32_t ms); /* only has a (close to) 1 jiffy resolution. */ +#endif +#ifndef sys_jiffies +u32_t sys_jiffies(void); /* since power up. */ +#endif + +/* Mailbox functions. */ +sys_mbox_t sys_mbox_new(int size); +void sys_mbox_post(sys_mbox_t mbox, void *msg); +err_t sys_mbox_trypost(sys_mbox_t mbox, void *msg); +u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout); +#ifndef sys_arch_mbox_tryfetch /* Allow port to override with a macro */ +u32_t sys_arch_mbox_tryfetch(sys_mbox_t mbox, void **msg); +#endif +/* For now, we map straight to sys_arch implementation. */ +#define sys_mbox_tryfetch(mbox, msg) sys_arch_mbox_tryfetch(mbox, msg) +void sys_mbox_free(sys_mbox_t mbox); +void sys_mbox_fetch(sys_mbox_t mbox, void **msg); + +/* Thread functions. */ +sys_thread_t sys_thread_new(char *name, void (* thread)(void *arg), void *arg, int stacksize, int prio); + +#endif /* NO_SYS */ + +/** Returns the current time in milliseconds. */ +u32_t sys_now(void); + +/* Critical Region Protection */ +/* These functions must be implemented in the sys_arch.c file. + In some implementations they can provide a more light-weight protection + mechanism than using semaphores. Otherwise semaphores can be used for + implementation */ +#ifndef SYS_ARCH_PROTECT +/** SYS_LIGHTWEIGHT_PROT + * define SYS_LIGHTWEIGHT_PROT in lwipopts.h if you want inter-task protection + * for certain critical regions during buffer allocation, deallocation and memory + * allocation and deallocation. + */ +#if SYS_LIGHTWEIGHT_PROT + +/** SYS_ARCH_DECL_PROTECT + * declare a protection variable. This macro will default to defining a variable of + * type sys_prot_t. If a particular port needs a different implementation, then + * this macro may be defined in sys_arch.h. + */ +#define SYS_ARCH_DECL_PROTECT(lev) sys_prot_t lev +/** SYS_ARCH_PROTECT + * Perform a "fast" protect. This could be implemented by + * disabling interrupts for an embedded system or by using a semaphore or + * mutex. The implementation should allow calling SYS_ARCH_PROTECT when + * already protected. The old protection level is returned in the variable + * "lev". This macro will default to calling the sys_arch_protect() function + * which should be implemented in sys_arch.c. If a particular port needs a + * different implementation, then this macro may be defined in sys_arch.h + */ +#define SYS_ARCH_PROTECT(lev) lev = sys_arch_protect() +/** SYS_ARCH_UNPROTECT + * Perform a "fast" set of the protection level to "lev". This could be + * implemented by setting the interrupt level to "lev" within the MACRO or by + * using a semaphore or mutex. This macro will default to calling the + * sys_arch_unprotect() function which should be implemented in + * sys_arch.c. If a particular port needs a different implementation, then + * this macro may be defined in sys_arch.h + */ +#define SYS_ARCH_UNPROTECT(lev) sys_arch_unprotect(lev) +sys_prot_t sys_arch_protect(void); +void sys_arch_unprotect(sys_prot_t pval); + +#else + +#define SYS_ARCH_DECL_PROTECT(lev) +#define SYS_ARCH_PROTECT(lev) +#define SYS_ARCH_UNPROTECT(lev) + +#endif /* SYS_LIGHTWEIGHT_PROT */ + +#endif /* SYS_ARCH_PROTECT */ + +/* + * Macros to set/get and increase/decrease variables in a thread-safe way. + * Use these for accessing variable that are used from more than one thread. + */ + +#ifndef SYS_ARCH_INC +#define SYS_ARCH_INC(var, val) do { \ + SYS_ARCH_DECL_PROTECT(old_level); \ + SYS_ARCH_PROTECT(old_level); \ + var += val; \ + SYS_ARCH_UNPROTECT(old_level); \ + } while(0) +#endif /* SYS_ARCH_INC */ + +#ifndef SYS_ARCH_DEC +#define SYS_ARCH_DEC(var, val) do { \ + SYS_ARCH_DECL_PROTECT(old_level); \ + SYS_ARCH_PROTECT(old_level); \ + var -= val; \ + SYS_ARCH_UNPROTECT(old_level); \ + } while(0) +#endif /* SYS_ARCH_DEC */ + +#ifndef SYS_ARCH_GET +#define SYS_ARCH_GET(var, ret) do { \ + SYS_ARCH_DECL_PROTECT(old_level); \ + SYS_ARCH_PROTECT(old_level); \ + ret = var; \ + SYS_ARCH_UNPROTECT(old_level); \ + } while(0) +#endif /* SYS_ARCH_GET */ + +#ifndef SYS_ARCH_SET +#define SYS_ARCH_SET(var, val) do { \ + SYS_ARCH_DECL_PROTECT(old_level); \ + SYS_ARCH_PROTECT(old_level); \ + var = val; \ + SYS_ARCH_UNPROTECT(old_level); \ + } while(0) +#endif /* SYS_ARCH_SET */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_SYS_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/tcp.h b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/tcp.h new file mode 100644 index 0000000..43004de --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/tcp.h @@ -0,0 +1,707 @@ +/** + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_TCP_H__ +#define __LWIP_TCP_H__ + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/sys.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/ip.h" +#include "lwip/icmp.h" +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct tcp_pcb; + +/* Functions for interfacing with TCP: */ + +/* Lower layer interface to TCP: */ +#define tcp_init() /* Compatibility define, not init needed. */ +void tcp_tmr (void); /* Must be called every + TCP_TMR_INTERVAL + ms. (Typically 250 ms). */ +/* Application program's interface: */ +struct tcp_pcb * tcp_new (void); +struct tcp_pcb * tcp_alloc (u8_t prio); + +void tcp_arg (struct tcp_pcb *pcb, void *arg); +void tcp_accept (struct tcp_pcb *pcb, + err_t (* accept)(void *arg, struct tcp_pcb *newpcb, + err_t err)); +void tcp_recv (struct tcp_pcb *pcb, + err_t (* recv)(void *arg, struct tcp_pcb *tpcb, + struct pbuf *p, err_t err)); +void tcp_sent (struct tcp_pcb *pcb, + err_t (* sent)(void *arg, struct tcp_pcb *tpcb, + u16_t len)); +void tcp_poll (struct tcp_pcb *pcb, + err_t (* poll)(void *arg, struct tcp_pcb *tpcb), + u8_t interval); +void tcp_err (struct tcp_pcb *pcb, + void (* err)(void *arg, err_t err)); + +#define tcp_mss(pcb) ((pcb)->mss) +#define tcp_sndbuf(pcb) ((pcb)->snd_buf) +#define tcp_nagle_disable(pcb) ((pcb)->flags |= TF_NODELAY) +#define tcp_nagle_enable(pcb) ((pcb)->flags &= ~TF_NODELAY) +#define tcp_nagle_disabled(pcb) (((pcb)->flags & TF_NODELAY) != 0) + +#if TCP_LISTEN_BACKLOG +#define tcp_accepted(pcb) (((struct tcp_pcb_listen *)(pcb))->accepts_pending--) +#else /* TCP_LISTEN_BACKLOG */ +#define tcp_accepted(pcb) +#endif /* TCP_LISTEN_BACKLOG */ + +void tcp_recved (struct tcp_pcb *pcb, u16_t len); +err_t tcp_bind (struct tcp_pcb *pcb, struct ip_addr *ipaddr, + u16_t port); +err_t tcp_connect (struct tcp_pcb *pcb, struct ip_addr *ipaddr, + u16_t port, err_t (* connected)(void *arg, + struct tcp_pcb *tpcb, + err_t err)); + +struct tcp_pcb * tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog); +#define tcp_listen(pcb) tcp_listen_with_backlog(pcb, TCP_DEFAULT_LISTEN_BACKLOG) + +void tcp_abandon (struct tcp_pcb *pcb, int reset); +#define tcp_abort(pcb) tcp_abandon((pcb), 1) +err_t tcp_close (struct tcp_pcb *pcb); + +/* Flags for "apiflags" parameter in tcp_write and tcp_enqueue */ +#define TCP_WRITE_FLAG_COPY 0x01 +#define TCP_WRITE_FLAG_MORE 0x02 + +err_t tcp_write (struct tcp_pcb *pcb, const void *dataptr, u16_t len, + u8_t apiflags); + +void tcp_setprio (struct tcp_pcb *pcb, u8_t prio); + +#define TCP_PRIO_MIN 1 +#define TCP_PRIO_NORMAL 64 +#define TCP_PRIO_MAX 127 + +/* It is also possible to call these two functions at the right + intervals (instead of calling tcp_tmr()). */ +void tcp_slowtmr (void); +void tcp_fasttmr (void); + + +/* Only used by IP to pass a TCP segment to TCP: */ +void tcp_input (struct pbuf *p, struct netif *inp); +/* Used within the TCP code only: */ +err_t tcp_send_empty_ack(struct tcp_pcb *pcb); +err_t tcp_output (struct tcp_pcb *pcb); +void tcp_rexmit (struct tcp_pcb *pcb); +void tcp_rexmit_rto (struct tcp_pcb *pcb); +void tcp_rexmit_fast (struct tcp_pcb *pcb); +u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb); + +/** + * This is the Nagle algorithm: try to combine user data to send as few TCP + * segments as possible. Only send if + * - no previously transmitted data on the connection remains unacknowledged or + * - the TF_NODELAY flag is set (nagle algorithm turned off for this pcb) or + * - the only unsent segment is at least pcb->mss bytes long (or there is more + * than one unsent segment - with lwIP, this can happen although unsent->len < mss) + * - or if we are in fast-retransmit (TF_INFR) + */ +#define tcp_do_output_nagle(tpcb) ((((tpcb)->unacked == NULL) || \ + ((tpcb)->flags & (TF_NODELAY | TF_INFR)) || \ + (((tpcb)->unsent != NULL) && (((tpcb)->unsent->next != NULL) || \ + ((tpcb)->unsent->len >= (tpcb)->mss))) \ + ) ? 1 : 0) +#define tcp_output_nagle(tpcb) (tcp_do_output_nagle(tpcb) ? tcp_output(tpcb) : ERR_OK) + + +#define TCP_SEQ_LT(a,b) ((s32_t)((a)-(b)) < 0) +#define TCP_SEQ_LEQ(a,b) ((s32_t)((a)-(b)) <= 0) +#define TCP_SEQ_GT(a,b) ((s32_t)((a)-(b)) > 0) +#define TCP_SEQ_GEQ(a,b) ((s32_t)((a)-(b)) >= 0) +/* is b<=a<=c? */ +#if 0 /* see bug #10548 */ +#define TCP_SEQ_BETWEEN(a,b,c) ((c)-(b) >= (a)-(b)) +#endif +#define TCP_SEQ_BETWEEN(a,b,c) (TCP_SEQ_GEQ(a,b) && TCP_SEQ_LEQ(a,c)) +#define TCP_FIN 0x01U +#define TCP_SYN 0x02U +#define TCP_RST 0x04U +#define TCP_PSH 0x08U +#define TCP_ACK 0x10U +#define TCP_URG 0x20U +#define TCP_ECE 0x40U +#define TCP_CWR 0x80U + +#define TCP_FLAGS 0x3fU + +/* Length of the TCP header, excluding options. */ +#define TCP_HLEN 20 + +#ifndef TCP_TMR_INTERVAL +#define TCP_TMR_INTERVAL 250 /* The TCP timer interval in milliseconds. */ +#endif /* TCP_TMR_INTERVAL */ + +#ifndef TCP_FAST_INTERVAL +#define TCP_FAST_INTERVAL TCP_TMR_INTERVAL /* the fine grained timeout in milliseconds */ +#endif /* TCP_FAST_INTERVAL */ + +#ifndef TCP_SLOW_INTERVAL +#define TCP_SLOW_INTERVAL (2*TCP_TMR_INTERVAL) /* the coarse grained timeout in milliseconds */ +#endif /* TCP_SLOW_INTERVAL */ + +#define TCP_FIN_WAIT_TIMEOUT 20000 /* milliseconds */ +#define TCP_SYN_RCVD_TIMEOUT 20000 /* milliseconds */ + +#define TCP_OOSEQ_TIMEOUT 6U /* x RTO */ + +#ifndef TCP_MSL +#define TCP_MSL 60000UL /* The maximum segment lifetime in milliseconds */ +#endif + +/* Keepalive values, compliant with RFC 1122. Don't change this unless you know what you're doing */ +#ifndef TCP_KEEPIDLE_DEFAULT +#define TCP_KEEPIDLE_DEFAULT 7200000UL /* Default KEEPALIVE timer in milliseconds */ +#endif + +#ifndef TCP_KEEPINTVL_DEFAULT +#define TCP_KEEPINTVL_DEFAULT 75000UL /* Default Time between KEEPALIVE probes in milliseconds */ +#endif + +#ifndef TCP_KEEPCNT_DEFAULT +#define TCP_KEEPCNT_DEFAULT 9U /* Default Counter for KEEPALIVE probes */ +#endif + +#define TCP_MAXIDLE TCP_KEEPCNT_DEFAULT * TCP_KEEPINTVL_DEFAULT /* Maximum KEEPALIVE probe time */ + +/* Fields are (of course) in network byte order. + * Some fields are converted to host byte order in tcp_input(). + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct tcp_hdr { + PACK_STRUCT_FIELD(u16_t src); + PACK_STRUCT_FIELD(u16_t dest); + PACK_STRUCT_FIELD(u32_t seqno); + PACK_STRUCT_FIELD(u32_t ackno); + PACK_STRUCT_FIELD(u16_t _hdrlen_rsvd_flags); + PACK_STRUCT_FIELD(u16_t wnd); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u16_t urgp); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define TCPH_OFFSET(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 8) +#define TCPH_HDRLEN(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 12) +#define TCPH_FLAGS(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) & TCP_FLAGS) + +#define TCPH_OFFSET_SET(phdr, offset) (phdr)->_hdrlen_rsvd_flags = htons(((offset) << 8) | TCPH_FLAGS(phdr)) +#define TCPH_HDRLEN_SET(phdr, len) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | TCPH_FLAGS(phdr)) +#define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = (((phdr)->_hdrlen_rsvd_flags & htons((u16_t)(~(u16_t)(TCP_FLAGS)))) | htons(flags)) +#define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags | htons(flags)) +#define TCPH_UNSET_FLAG(phdr, flags) (phdr)->_hdrlen_rsvd_flags = htons(ntohs((phdr)->_hdrlen_rsvd_flags) | (TCPH_FLAGS(phdr) & ~(flags)) ) + +#define TCP_TCPLEN(seg) ((seg)->len + ((TCPH_FLAGS((seg)->tcphdr) & (TCP_FIN | TCP_SYN)) != 0)) + +enum tcp_state { + CLOSED = 0, + LISTEN = 1, + SYN_SENT = 2, + SYN_RCVD = 3, + ESTABLISHED = 4, + FIN_WAIT_1 = 5, + FIN_WAIT_2 = 6, + CLOSE_WAIT = 7, + CLOSING = 8, + LAST_ACK = 9, + TIME_WAIT = 10 +}; + +/** Flags used on input processing, not on pcb->flags +*/ +#define TF_RESET (u8_t)0x08U /* Connection was reset. */ +#define TF_CLOSED (u8_t)0x10U /* Connection was sucessfully closed. */ +#define TF_GOT_FIN (u8_t)0x20U /* Connection was closed by the remote end. */ + + +#if LWIP_CALLBACK_API + /* Function to call when a listener has been connected. + * @param arg user-supplied argument (tcp_pcb.callback_arg) + * @param pcb a new tcp_pcb that now is connected + * @param err an error argument (TODO: that is current always ERR_OK?) + * @return ERR_OK: accept the new connection, + * any other err_t abortsthe new connection + */ +#define DEF_ACCEPT_CALLBACK err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err) +#else /* LWIP_CALLBACK_API */ +#define DEF_ACCEPT_CALLBACK +#endif /* LWIP_CALLBACK_API */ + +/** + * members common to struct tcp_pcb and struct tcp_listen_pcb + */ +#define TCP_PCB_COMMON(type) \ + type *next; /* for the linked list */ \ + enum tcp_state state; /* TCP state */ \ + u8_t prio; \ + void *callback_arg; \ + /* ports are in host byte order */ \ + u16_t local_port; \ + /* the accept callback for listen- and normal pcbs, if LWIP_CALLBACK_API */ \ + DEF_ACCEPT_CALLBACK + + +/* the TCP protocol control block */ +struct tcp_pcb { +/** common PCB members */ + IP_PCB; +/** protocol specific PCB members */ + TCP_PCB_COMMON(struct tcp_pcb); + + /* ports are in host byte order */ + u16_t remote_port; + + u8_t flags; +#define TF_ACK_DELAY ((u8_t)0x01U) /* Delayed ACK. */ +#define TF_ACK_NOW ((u8_t)0x02U) /* Immediate ACK. */ +#define TF_INFR ((u8_t)0x04U) /* In fast recovery. */ +#define TF_TIMESTAMP ((u8_t)0x08U) /* Timestamp option enabled */ +#define TF_FIN ((u8_t)0x20U) /* Connection was closed locally (FIN segment enqueued). */ +#define TF_NODELAY ((u8_t)0x40U) /* Disable Nagle algorithm */ +#define TF_NAGLEMEMERR ((u8_t)0x80U) /* nagle enabled, memerr, try to output to prevent delayed ACK to happen */ + + /* the rest of the fields are in host byte order + as we have to do some math with them */ + /* receiver variables */ + u32_t rcv_nxt; /* next seqno expected */ + u16_t rcv_wnd; /* receiver window available */ + u16_t rcv_ann_wnd; /* receiver window to announce */ + u32_t rcv_ann_right_edge; /* announced right edge of window */ + + /* Timers */ + u32_t tmr; + u8_t polltmr, pollinterval; + + /* Retransmission timer. */ + s16_t rtime; + + u16_t mss; /* maximum segment size */ + + /* RTT (round trip time) estimation variables */ + u32_t rttest; /* RTT estimate in 500ms ticks */ + u32_t rtseq; /* sequence number being timed */ + s16_t sa, sv; /* @todo document this */ + + s16_t rto; /* retransmission time-out */ + u8_t nrtx; /* number of retransmissions */ + + /* fast retransmit/recovery */ + u32_t lastack; /* Highest acknowledged seqno. */ + u8_t dupacks; + + /* congestion avoidance/control variables */ + u16_t cwnd; + u16_t ssthresh; + + /* sender variables */ + u32_t snd_nxt; /* next new seqno to be sent */ + u16_t snd_wnd; /* sender window */ + u32_t snd_wl1, snd_wl2; /* Sequence and acknowledgement numbers of last + window update. */ + u32_t snd_lbb; /* Sequence number of next byte to be buffered. */ + + u16_t acked; + + u16_t snd_buf; /* Available buffer space for sending (in bytes). */ +#define TCP_SNDQUEUELEN_OVERFLOW (0xffff-3) + u16_t snd_queuelen; /* Available buffer space for sending (in tcp_segs). */ + + + /* These are ordered by sequence number: */ + struct tcp_seg *unsent; /* Unsent (queued) segments. */ + struct tcp_seg *unacked; /* Sent but unacknowledged segments. */ +#if TCP_QUEUE_OOSEQ + struct tcp_seg *ooseq; /* Received out of sequence segments. */ +#endif /* TCP_QUEUE_OOSEQ */ + + struct pbuf *refused_data; /* Data previously received but not yet taken by upper layer */ + +#if LWIP_CALLBACK_API + /* Function to be called when more send buffer space is available. + * @param arg user-supplied argument (tcp_pcb.callback_arg) + * @param pcb the tcp_pcb which has send buffer space available + * @param space the amount of bytes available + * @return ERR_OK: try to send some data by calling tcp_output + */ + err_t (* sent)(void *arg, struct tcp_pcb *pcb, u16_t space); + + /* Function to be called when (in-sequence) data has arrived. + * @param arg user-supplied argument (tcp_pcb.callback_arg) + * @param pcb the tcp_pcb for which data has arrived + * @param p the packet buffer which arrived + * @param err an error argument (TODO: that is current always ERR_OK?) + * @return ERR_OK: try to send some data by calling tcp_output + */ + err_t (* recv)(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err); + + /* Function to be called when a connection has been set up. + * @param arg user-supplied argument (tcp_pcb.callback_arg) + * @param pcb the tcp_pcb that now is connected + * @param err an error argument (TODO: that is current always ERR_OK?) + * @return value is currently ignored + */ + err_t (* connected)(void *arg, struct tcp_pcb *pcb, err_t err); + + /* Function which is called periodically. + * The period can be adjusted in multiples of the TCP slow timer interval + * by changing tcp_pcb.polltmr. + * @param arg user-supplied argument (tcp_pcb.callback_arg) + * @param pcb the tcp_pcb to poll for + * @return ERR_OK: try to send some data by calling tcp_output + */ + err_t (* poll)(void *arg, struct tcp_pcb *pcb); + + /* Function to be called whenever a fatal error occurs. + * There is no pcb parameter since most of the times, the pcb is + * already deallocated (or there is no pcb) when this function is called. + * @param arg user-supplied argument (tcp_pcb.callback_arg) + * @param err an indication why the error callback is called: + * ERR_ABRT: aborted through tcp_abort or by a TCP timer + * ERR_RST: the connection was reset by the remote host + */ + void (* errf)(void *arg, err_t err); +#endif /* LWIP_CALLBACK_API */ + +#if LWIP_TCP_TIMESTAMPS + u32_t ts_lastacksent; + u32_t ts_recent; +#endif /* LWIP_TCP_TIMESTAMPS */ + + /* idle time before KEEPALIVE is sent */ + u32_t keep_idle; +#if LWIP_TCP_KEEPALIVE + u32_t keep_intvl; + u32_t keep_cnt; +#endif /* LWIP_TCP_KEEPALIVE */ + + /* Persist timer counter */ + u32_t persist_cnt; + /* Persist timer back-off */ + u8_t persist_backoff; + + /* KEEPALIVE counter */ + u8_t keep_cnt_sent; +}; + +struct tcp_pcb_listen { +/* Common members of all PCB types */ + IP_PCB; +/* Protocol specific PCB members */ + TCP_PCB_COMMON(struct tcp_pcb_listen); + +#if TCP_LISTEN_BACKLOG + u8_t backlog; + u8_t accepts_pending; +#endif /* TCP_LISTEN_BACKLOG */ +}; + +#if LWIP_EVENT_API + +enum lwip_event { + LWIP_EVENT_ACCEPT, + LWIP_EVENT_SENT, + LWIP_EVENT_RECV, + LWIP_EVENT_CONNECTED, + LWIP_EVENT_POLL, + LWIP_EVENT_ERR +}; + +err_t lwip_tcp_event(void *arg, struct tcp_pcb *pcb, + enum lwip_event, + struct pbuf *p, + u16_t size, + err_t err); + +#define TCP_EVENT_ACCEPT(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_ACCEPT, NULL, 0, err) +#define TCP_EVENT_SENT(pcb,space,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_SENT, NULL, space, ERR_OK) +#define TCP_EVENT_RECV(pcb,p,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_RECV, (p), 0, (err)) +#define TCP_EVENT_CONNECTED(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_CONNECTED, NULL, 0, (err)) +#define TCP_EVENT_POLL(pcb,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_POLL, NULL, 0, ERR_OK) +#define TCP_EVENT_ERR(errf,arg,err) lwip_tcp_event((arg), NULL, \ + LWIP_EVENT_ERR, NULL, 0, (err)) +#else /* LWIP_EVENT_API */ + +#define TCP_EVENT_ACCEPT(pcb,err,ret) \ + do { \ + if((pcb)->accept != NULL) \ + (ret) = (pcb)->accept((pcb)->callback_arg,(pcb),(err)); \ + else (ret) = ERR_OK; \ + } while (0) + +#define TCP_EVENT_SENT(pcb,space,ret) \ + do { \ + if((pcb)->sent != NULL) \ + (ret) = (pcb)->sent((pcb)->callback_arg,(pcb),(space)); \ + else (ret) = ERR_OK; \ + } while (0) + +#define TCP_EVENT_RECV(pcb,p,err,ret) \ + do { \ + if((pcb)->recv != NULL) { \ + (ret) = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err)); \ + } else { \ + (ret) = tcp_recv_null(NULL, (pcb), (p), (err)); \ + } \ + } while (0) + +#define TCP_EVENT_CONNECTED(pcb,err,ret) \ + do { \ + if((pcb)->connected != NULL) \ + (ret) = (pcb)->connected((pcb)->callback_arg,(pcb),(err)); \ + else (ret) = ERR_OK; \ + } while (0) + +#define TCP_EVENT_POLL(pcb,ret) \ + do { \ + if((pcb)->poll != NULL) \ + (ret) = (pcb)->poll((pcb)->callback_arg,(pcb)); \ + else (ret) = ERR_OK; \ + } while (0) + +#define TCP_EVENT_ERR(errf,arg,err) \ + do { \ + if((errf) != NULL) \ + (errf)((arg),(err)); \ + } while (0) + +#endif /* LWIP_EVENT_API */ + +/* This structure represents a TCP segment on the unsent and unacked queues */ +struct tcp_seg { + struct tcp_seg *next; /* used when putting segements on a queue */ + struct pbuf *p; /* buffer containing data + TCP header */ + void *dataptr; /* pointer to the TCP data in the pbuf */ + u16_t len; /* the TCP length of this segment */ + u8_t flags; +#define TF_SEG_OPTS_MSS (u8_t)0x01U /* Include MSS option. */ +#define TF_SEG_OPTS_TS (u8_t)0x02U /* Include timestamp option. */ + struct tcp_hdr *tcphdr; /* the TCP header */ +}; + +#define LWIP_TCP_OPT_LENGTH(flags) \ + (flags & TF_SEG_OPTS_MSS ? 4 : 0) + \ + (flags & TF_SEG_OPTS_TS ? 12 : 0) + +/** This returns a TCP header option for MSS in an u32_t */ +#define TCP_BUILD_MSS_OPTION(x) (x) = htonl(((u32_t)2 << 24) | \ + ((u32_t)4 << 16) | \ + (((u32_t)TCP_MSS / 256) << 8) | \ + (TCP_MSS & 255)) + +/* Internal functions and global variables: */ +struct tcp_pcb *tcp_pcb_copy(struct tcp_pcb *pcb); +void tcp_pcb_purge(struct tcp_pcb *pcb); +void tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb); + +u8_t tcp_segs_free(struct tcp_seg *seg); +u8_t tcp_seg_free(struct tcp_seg *seg); +struct tcp_seg *tcp_seg_copy(struct tcp_seg *seg); + +#define tcp_ack(pcb) \ + do { \ + if((pcb)->flags & TF_ACK_DELAY) { \ + (pcb)->flags &= ~TF_ACK_DELAY; \ + (pcb)->flags |= TF_ACK_NOW; \ + tcp_output(pcb); \ + } \ + else { \ + (pcb)->flags |= TF_ACK_DELAY; \ + } \ + } while (0) + +#define tcp_ack_now(pcb) \ + do { \ + (pcb)->flags |= TF_ACK_NOW; \ + tcp_output(pcb); \ + } while (0) + +err_t tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags); +err_t tcp_enqueue(struct tcp_pcb *pcb, void *dataptr, u16_t len, + u8_t flags, u8_t apiflags, u8_t optflags); + +void tcp_rexmit_seg(struct tcp_pcb *pcb, struct tcp_seg *seg); + +void tcp_rst(u32_t seqno, u32_t ackno, + struct ip_addr *local_ip, struct ip_addr *remote_ip, + u16_t local_port, u16_t remote_port); + +u32_t tcp_next_iss(void); + +void tcp_keepalive(struct tcp_pcb *pcb); +void tcp_zero_window_probe(struct tcp_pcb *pcb); + +#if TCP_CALCULATE_EFF_SEND_MSS +u16_t tcp_eff_send_mss(u16_t sendmss, struct ip_addr *addr); +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + +#if LWIP_CALLBACK_API +err_t tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err); +#endif /* LWIP_CALLBACK_API */ + +extern struct tcp_pcb *tcp_input_pcb; +extern u32_t tcp_ticks; + +const char* tcp_debug_state_str(enum tcp_state s); +#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG +void tcp_debug_print(struct tcp_hdr *tcphdr); +void tcp_debug_print_flags(u8_t flags); +void tcp_debug_print_state(enum tcp_state s); +void tcp_debug_print_pcbs(void); +s16_t tcp_pcbs_sane(void); +#else +# define tcp_debug_print(tcphdr) +# define tcp_debug_print_flags(flags) +# define tcp_debug_print_state(s) +# define tcp_debug_print_pcbs() +# define tcp_pcbs_sane() 1 +#endif /* TCP_DEBUG */ + +#if NO_SYS +#define tcp_timer_needed() +#else +void tcp_timer_needed(void); +#endif + +/* The TCP PCB lists. */ +union tcp_listen_pcbs_t { /* List of all TCP PCBs in LISTEN state. */ + struct tcp_pcb_listen *listen_pcbs; + struct tcp_pcb *pcbs; +}; +extern union tcp_listen_pcbs_t tcp_listen_pcbs; +extern struct tcp_pcb *tcp_active_pcbs; /* List of all TCP PCBs that are in a + state in which they accept or send + data. */ +extern struct tcp_pcb *tcp_tw_pcbs; /* List of all TCP PCBs in TIME-WAIT. */ + +extern struct tcp_pcb *tcp_tmp_pcb; /* Only used for temporary storage. */ + +/* Axioms about the above lists: + 1) Every TCP PCB that is not CLOSED is in one of the lists. + 2) A PCB is only in one of the lists. + 3) All PCBs in the tcp_listen_pcbs list is in LISTEN state. + 4) All PCBs in the tcp_tw_pcbs list is in TIME-WAIT state. +*/ + +/* Define two macros, TCP_REG and TCP_RMV that registers a TCP PCB + with a PCB list or removes a PCB from a list, respectively. */ +#if 0 +#define TCP_REG(pcbs, npcb) do {\ + LWIP_DEBUGF(TCP_DEBUG, ("TCP_REG %p local port %d\n", npcb, npcb->local_port)); \ + for(tcp_tmp_pcb = *pcbs; \ + tcp_tmp_pcb != NULL; \ + tcp_tmp_pcb = tcp_tmp_pcb->next) { \ + LWIP_ASSERT("TCP_REG: already registered\n", tcp_tmp_pcb != npcb); \ + } \ + LWIP_ASSERT("TCP_REG: pcb->state != CLOSED", npcb->state != CLOSED); \ + npcb->next = *pcbs; \ + LWIP_ASSERT("TCP_REG: npcb->next != npcb", npcb->next != npcb); \ + *(pcbs) = npcb; \ + LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \ + tcp_timer_needed(); \ + } while(0) +#define TCP_RMV(pcbs, npcb) do { \ + LWIP_ASSERT("TCP_RMV: pcbs != NULL", *pcbs != NULL); \ + LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removing %p from %p\n", npcb, *pcbs)); \ + if(*pcbs == npcb) { \ + *pcbs = (*pcbs)->next; \ + } else for(tcp_tmp_pcb = *pcbs; tcp_tmp_pcb != NULL; tcp_tmp_pcb = tcp_tmp_pcb->next) { \ + if(tcp_tmp_pcb->next == npcb) { \ + tcp_tmp_pcb->next = npcb->next; \ + break; \ + } \ + } \ + npcb->next = NULL; \ + LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \ + LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removed %p from %p\n", npcb, *pcbs)); \ + } while(0) + +#else /* LWIP_DEBUG */ + +#define TCP_REG(pcbs, npcb) \ + do { \ + npcb->next = *pcbs; \ + *(pcbs) = npcb; \ + tcp_timer_needed(); \ + } while (0) + +#define TCP_RMV(pcbs, npcb) \ + do { \ + if(*(pcbs) == npcb) { \ + (*(pcbs)) = (*pcbs)->next; \ + } \ + else { \ + for(tcp_tmp_pcb = *pcbs; \ + tcp_tmp_pcb != NULL; \ + tcp_tmp_pcb = tcp_tmp_pcb->next) { \ + if(tcp_tmp_pcb->next == npcb) { \ + tcp_tmp_pcb->next = npcb->next; \ + break; \ + } \ + } \ + } \ + npcb->next = NULL; \ + } while(0) + +#endif /* LWIP_DEBUG */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_TCP */ + +#endif /* __LWIP_TCP_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/tcpip.h b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/tcpip.h new file mode 100644 index 0000000..8bfbaf7 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/tcpip.h @@ -0,0 +1,141 @@ +/** + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + **/ +#ifndef __LWIP_TCPIP_H__ +#define __LWIP_TCPIP_H__ + +#include "lwip/opt.h" + +#if !NO_SYS /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/api_msg.h" +#include "lwip/netifapi.h" +#include "lwip/pbuf.h" +#include "lwip/api.h" +#include "lwip/sys.h" +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_TCPIP_CORE_LOCKING +/** The global semaphore to lock the stack. */ +extern sys_sem_t lock_tcpip_core; +#define LOCK_TCPIP_CORE() sys_sem_wait(lock_tcpip_core) +#define UNLOCK_TCPIP_CORE() sys_sem_signal(lock_tcpip_core) +#define TCPIP_APIMSG(m) tcpip_apimsg_lock(m) +#define TCPIP_APIMSG_ACK(m) +#define TCPIP_NETIFAPI(m) tcpip_netifapi_lock(m) +#define TCPIP_NETIFAPI_ACK(m) +#else +#define LOCK_TCPIP_CORE() +#define UNLOCK_TCPIP_CORE() +#define TCPIP_APIMSG(m) tcpip_apimsg(m) +#define TCPIP_APIMSG_ACK(m) sys_sem_signal(m->conn->op_completed) +#define TCPIP_NETIFAPI(m) tcpip_netifapi(m) +#define TCPIP_NETIFAPI_ACK(m) sys_sem_signal(m->sem) +#endif /* LWIP_TCPIP_CORE_LOCKING */ + +void tcpip_init(void (* tcpip_init_done)(void *), void *arg); + +#if LWIP_NETCONN +err_t tcpip_apimsg(struct api_msg *apimsg); +#if LWIP_TCPIP_CORE_LOCKING +err_t tcpip_apimsg_lock(struct api_msg *apimsg); +#endif /* LWIP_TCPIP_CORE_LOCKING */ +#endif /* LWIP_NETCONN */ + +err_t tcpip_input(struct pbuf *p, struct netif *inp); + +#if LWIP_NETIF_API +err_t tcpip_netifapi(struct netifapi_msg *netifapimsg); +#if LWIP_TCPIP_CORE_LOCKING +err_t tcpip_netifapi_lock(struct netifapi_msg *netifapimsg); +#endif /* LWIP_TCPIP_CORE_LOCKING */ +#endif /* LWIP_NETIF_API */ + +err_t tcpip_callback_with_block(void (*f)(void *ctx), void *ctx, u8_t block); +#define tcpip_callback(f, ctx) tcpip_callback_with_block(f, ctx, 1) + +/* free pbufs or heap memory from another context without blocking */ +err_t pbuf_free_callback(struct pbuf *p); +err_t mem_free_callback(void *m); + +err_t tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg); +err_t tcpip_untimeout(sys_timeout_handler h, void *arg); + +enum tcpip_msg_type { +#if LWIP_NETCONN + TCPIP_MSG_API, +#endif /* LWIP_NETCONN */ + TCPIP_MSG_INPKT, +#if LWIP_NETIF_API + TCPIP_MSG_NETIFAPI, +#endif /* LWIP_NETIF_API */ + TCPIP_MSG_CALLBACK, + TCPIP_MSG_TIMEOUT, + TCPIP_MSG_UNTIMEOUT +}; + +struct tcpip_msg { + enum tcpip_msg_type type; + sys_sem_t *sem; + union { +#if LWIP_NETCONN + struct api_msg *apimsg; +#endif /* LWIP_NETCONN */ +#if LWIP_NETIF_API + struct netifapi_msg *netifapimsg; +#endif /* LWIP_NETIF_API */ + struct { + struct pbuf *p; + struct netif *netif; + } inp; + struct { + void (*f)(void *ctx); + void *ctx; + } cb; + struct { + u32_t msecs; + sys_timeout_handler h; + void *arg; + } tmo; + } msg; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* !NO_SYS */ + +#endif /* __LWIP_TCPIP_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/udp.h b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/udp.h new file mode 100644 index 0000000..e441dac --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/lwip/udp.h @@ -0,0 +1,153 @@ +/** + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_UDP_H__ +#define __LWIP_UDP_H__ + +#include "lwip/opt.h" + +#if LWIP_UDP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/ip_addr.h" +#include "lwip/ip.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define UDP_HLEN 8 + +/* Fields are (of course) in network byte order. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct udp_hdr { + PACK_STRUCT_FIELD(u16_t src); + PACK_STRUCT_FIELD(u16_t dest); /* src/dest UDP ports */ + PACK_STRUCT_FIELD(u16_t len); + PACK_STRUCT_FIELD(u16_t chksum); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define UDP_FLAGS_NOCHKSUM 0x01U +#define UDP_FLAGS_UDPLITE 0x02U +#define UDP_FLAGS_CONNECTED 0x04U + +struct udp_pcb { +/* Common members of all PCB types */ + IP_PCB; + +/* Protocol specific PCB members */ + + struct udp_pcb *next; + + u8_t flags; + /* ports are in host byte order */ + u16_t local_port, remote_port; + +#if LWIP_IGMP + /* outgoing network interface for multicast packets */ + struct ip_addr multicast_ip; +#endif /* LWIP_IGMP */ + +#if LWIP_UDPLITE + /* used for UDP_LITE only */ + u16_t chksum_len_rx, chksum_len_tx; +#endif /* LWIP_UDPLITE */ + + /* receive callback function + * addr and port are in same byte order as in the pcb + * The callback is responsible for freeing the pbuf + * if it's not used any more. + * + * ATTENTION: Be aware that 'addr' points into the pbuf 'p' so freeing this pbuf + * makes 'addr' invalid, too. + * + * @param arg user supplied argument (udp_pcb.recv_arg) + * @param pcb the udp_pcb which received data + * @param p the packet buffer that was received + * @param addr the remote IP address from which the packet was received + * @param port the remote port from which the packet was received + */ + void (* recv)(void *arg, struct udp_pcb *pcb, struct pbuf *p, + struct ip_addr *addr, u16_t port); + /* user-supplied argument for the recv callback */ + void *recv_arg; +}; +/* udp_pcbs export for exernal reference (e.g. SNMP agent) */ +extern struct udp_pcb *udp_pcbs; + +/* The following functions is the application layer interface to the + UDP code. */ +struct udp_pcb * udp_new (void); +void udp_remove (struct udp_pcb *pcb); +err_t udp_bind (struct udp_pcb *pcb, struct ip_addr *ipaddr, + u16_t port); +err_t udp_connect (struct udp_pcb *pcb, struct ip_addr *ipaddr, + u16_t port); +void udp_disconnect (struct udp_pcb *pcb); +void udp_recv (struct udp_pcb *pcb, + void (* recv)(void *arg, struct udp_pcb *upcb, + struct pbuf *p, + struct ip_addr *addr, + u16_t port), + void *recv_arg); +err_t udp_sendto_if (struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *dst_ip, u16_t dst_port, struct netif *netif); +err_t udp_sendto (struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *dst_ip, u16_t dst_port); +err_t udp_send (struct udp_pcb *pcb, struct pbuf *p); + +#define udp_flags(pcb) ((pcb)->flags) +#define udp_setflags(pcb, f) ((pcb)->flags = (f)) + +/* The following functions are the lower layer interface to UDP. */ +void udp_input (struct pbuf *p, struct netif *inp); + +#define udp_init() /* Compatibility define, not init needed. */ + +#if UDP_DEBUG +void udp_debug_print(struct udp_hdr *udphdr); +#else +#define udp_debug_print(udphdr) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_UDP */ + +#endif /* __LWIP_UDP_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/netif/etharp.h b/component/common/network/lwip/lwip_v1.3.2/src/include/netif/etharp.h new file mode 100644 index 0000000..847f605 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/netif/etharp.h @@ -0,0 +1,192 @@ +/** + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * Copyright (c) 2003-2004 Leon Woestenberg + * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + **/ + +#ifndef __NETIF_ETHARP_H__ +#define __NETIF_ETHARP_H__ + +#include "lwip/opt.h" + +#if LWIP_ARP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/ip.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef ETH_PAD_SIZE +#define ETH_PAD_SIZE 0 +#endif + +#ifndef ETHARP_HWADDR_LEN +#define ETHARP_HWADDR_LEN 6 +#endif + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct eth_addr { + PACK_STRUCT_FIELD(u8_t addr[ETHARP_HWADDR_LEN]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct eth_hdr { +#if ETH_PAD_SIZE + PACK_STRUCT_FIELD(u8_t padding[ETH_PAD_SIZE]); +#endif + PACK_STRUCT_FIELD(struct eth_addr dest); + PACK_STRUCT_FIELD(struct eth_addr src); + PACK_STRUCT_FIELD(u16_t type); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define SIZEOF_ETH_HDR (14 + ETH_PAD_SIZE) + +#if ETHARP_SUPPORT_VLAN + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct eth_vlan_hdr { + PACK_STRUCT_FIELD(u16_t tpid); + PACK_STRUCT_FIELD(u16_t prio_vid); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define SIZEOF_VLAN_HDR 4 +#define VLAN_ID(vlan_hdr) (htons((vlan_hdr)->prio_vid) & 0xFFF) + +#endif /* ETHARP_SUPPORT_VLAN */ + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** the ARP message */ +struct etharp_hdr { + PACK_STRUCT_FIELD(u16_t hwtype); + PACK_STRUCT_FIELD(u16_t proto); + PACK_STRUCT_FIELD(u16_t _hwlen_protolen); + PACK_STRUCT_FIELD(u16_t opcode); + PACK_STRUCT_FIELD(struct eth_addr shwaddr); + PACK_STRUCT_FIELD(struct ip_addr2 sipaddr); + PACK_STRUCT_FIELD(struct eth_addr dhwaddr); + PACK_STRUCT_FIELD(struct ip_addr2 dipaddr); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define SIZEOF_ETHARP_HDR 28 +#define SIZEOF_ETHARP_PACKET (SIZEOF_ETH_HDR + SIZEOF_ETHARP_HDR) + +/** 5 seconds period */ +#define ARP_TMR_INTERVAL 1000 + +#define ETHTYPE_ARP 0x0806 +#define ETHTYPE_IP 0x0800 +#define ETHTYPE_VLAN 0x8100 +#define ETHTYPE_PPPOEDISC 0x8863 /* PPP Over Ethernet Discovery Stage */ +#define ETHTYPE_PPPOE 0x8864 /* PPP Over Ethernet Session Stage */ + +/** ARP message types (opcodes) */ +#define ARP_REQUEST 1 +#define ARP_REPLY 2 + +#if ARP_QUEUEING +/** struct for queueing outgoing packets for unknown address + * defined here to be accessed by memp.h + */ +struct etharp_q_entry { + struct etharp_q_entry *next; + struct pbuf *p; +}; +#endif /* ARP_QUEUEING */ + +#define etharp_init() /* Compatibility define, not init needed. */ +void etharp_tmr(void); +s8_t etharp_find_addr(struct netif *netif, struct ip_addr *ipaddr, + struct eth_addr **eth_ret, struct ip_addr **ip_ret); +void etharp_ip_input(struct netif *netif, struct pbuf *p); +void etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, + struct pbuf *p); +err_t etharp_output(struct netif *netif, struct pbuf *q, struct ip_addr *ipaddr); +err_t etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q); +err_t etharp_request(struct netif *netif, struct ip_addr *ipaddr); +/** For Ethernet network interfaces, we might want to send "gratuitous ARP"; + * this is an ARP packet sent by a node in order to spontaneously cause other + * nodes to update an entry in their ARP cache. + * From RFC 3220 "IP Mobility Support for IPv4" section 4.6. */ +#define etharp_gratuitous(netif) etharp_request((netif), &(netif)->ip_addr) + +err_t ethernet_input(struct pbuf *p, struct netif *netif); + +#if LWIP_AUTOIP +err_t etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr, + const struct eth_addr *ethdst_addr, + const struct eth_addr *hwsrc_addr, const struct ip_addr *ipsrc_addr, + const struct eth_addr *hwdst_addr, const struct ip_addr *ipdst_addr, + const u16_t opcode); +#endif /* LWIP_AUTOIP */ + +#define eth_addr_cmp(addr1, addr2) (memcmp((addr1)->addr, (addr2)->addr, ETHARP_HWADDR_LEN) == 0) + +extern const struct eth_addr ethbroadcast, ethzero; + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_ARP */ + +#endif /* __NETIF_ARP_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/netif/loopif.h b/component/common/network/lwip/lwip_v1.3.2/src/include/netif/loopif.h new file mode 100644 index 0000000..304af4b --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/netif/loopif.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __NETIF_LOOPIF_H__ +#define __NETIF_LOOPIF_H__ + +#include "lwip/opt.h" +#include "lwip/netif.h" +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if !LWIP_NETIF_LOOPBACK_MULTITHREADING +#define loopif_poll netif_poll +#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */ + +err_t loopif_init(struct netif *netif); + +#ifdef __cplusplus +} +#endif + +#endif /* __NETIF_LOOPIF_H__ */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/netif/ppp_oe.h b/component/common/network/lwip/lwip_v1.3.2/src/include/netif/ppp_oe.h new file mode 100644 index 0000000..ee9408a --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/netif/ppp_oe.h @@ -0,0 +1,161 @@ +/** +* ppp_oe.h - PPP Over Ethernet implementation for lwIP. +* +* Copyright (c) 2006 by Marc Boucher, Services Informatiques (MBSI) inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 06-01-01 Marc Boucher +* Ported to lwIP. +**/ + + + +/* based on NetBSD: if_pppoe.c,v 1.64 2006/01/31 23:50:15 martin Exp */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Martin Husemann . + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 PPP_OE_H +#define PPP_OE_H + +#include "lwip/opt.h" + +#if PPPOE_SUPPORT > 0 + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct pppoehdr { + PACK_STRUCT_FIELD(u8_t vertype); + PACK_STRUCT_FIELD(u8_t code); + PACK_STRUCT_FIELD(u16_t session); + PACK_STRUCT_FIELD(u16_t plen); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct pppoetag { + PACK_STRUCT_FIELD(u16_t tag); + PACK_STRUCT_FIELD(u16_t len); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + + +#define PPPOE_STATE_INITIAL 0 +#define PPPOE_STATE_PADI_SENT 1 +#define PPPOE_STATE_PADR_SENT 2 +#define PPPOE_STATE_SESSION 3 +#define PPPOE_STATE_CLOSING 4 +/* passive */ +#define PPPOE_STATE_PADO_SENT 1 + +#define PPPOE_HEADERLEN sizeof(struct pppoehdr) +#define PPPOE_VERTYPE 0x11 /* VER=1, TYPE = 1 */ + +#define PPPOE_TAG_EOL 0x0000 /* end of list */ +#define PPPOE_TAG_SNAME 0x0101 /* service name */ +#define PPPOE_TAG_ACNAME 0x0102 /* access concentrator name */ +#define PPPOE_TAG_HUNIQUE 0x0103 /* host unique */ +#define PPPOE_TAG_ACCOOKIE 0x0104 /* AC cookie */ +#define PPPOE_TAG_VENDOR 0x0105 /* vendor specific */ +#define PPPOE_TAG_RELAYSID 0x0110 /* relay session id */ +#define PPPOE_TAG_SNAME_ERR 0x0201 /* service name error */ +#define PPPOE_TAG_ACSYS_ERR 0x0202 /* AC system error */ +#define PPPOE_TAG_GENERIC_ERR 0x0203 /* gerneric error */ + +#define PPPOE_CODE_PADI 0x09 /* Active Discovery Initiation */ +#define PPPOE_CODE_PADO 0x07 /* Active Discovery Offer */ +#define PPPOE_CODE_PADR 0x19 /* Active Discovery Request */ +#define PPPOE_CODE_PADS 0x65 /* Active Discovery Session confirmation */ +#define PPPOE_CODE_PADT 0xA7 /* Active Discovery Terminate */ + +#ifndef ETHERMTU +#define ETHERMTU 1500 +#endif + +/* two byte PPP protocol discriminator, then IP data */ +#define PPPOE_MAXMTU (ETHERMTU-PPPOE_HEADERLEN-2) + +struct pppoe_softc; + + +void pppoe_init(void); + +err_t pppoe_create(struct netif *ethif, int pd, void (*linkStatusCB)(int pd, int up), struct pppoe_softc **scptr); +err_t pppoe_destroy(struct netif *ifp); + +int pppoe_connect(struct pppoe_softc *sc); +void pppoe_disconnect(struct pppoe_softc *sc); + +void pppoe_disc_input(struct netif *netif, struct pbuf *p); +void pppoe_data_input(struct netif *netif, struct pbuf *p); + +err_t pppoe_xmit(struct pppoe_softc *sc, struct pbuf *pb); + +extern int pppoe_hdrlen; + +#endif /* PPPOE_SUPPORT */ + +#endif /* PPP_OE_H */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/include/netif/slipif.h b/component/common/network/lwip/lwip_v1.3.2/src/include/netif/slipif.h new file mode 100644 index 0000000..ccd03c8 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/include/netif/slipif.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2001, Swedish Institute of Computer Science. + * 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 Institute 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 INSTITUTE 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 INSTITUTE 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __NETIF_SLIPIF_H__ +#define __NETIF_SLIPIF_H__ + +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + +err_t slipif_init(struct netif * netif); +void slipif_poll(struct netif *netif); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/network/lwip/lwip_v1.3.2/src/netif/FILES b/component/common/network/lwip/lwip_v1.3.2/src/netif/FILES new file mode 100644 index 0000000..099dbf3 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/netif/FILES @@ -0,0 +1,29 @@ +This directory contains generic network interface device drivers that +do not contain any hardware or architecture specific code. The files +are: + +etharp.c + Implements the ARP (Address Resolution Protocol) over + Ethernet. The code in this file should be used together with + Ethernet device drivers. Note that this module has been + largely made Ethernet independent so you should be able to + adapt this for other link layers (such as Firewire). + +ethernetif.c + An example of how an Ethernet device driver could look. This + file can be used as a "skeleton" for developing new Ethernet + network device drivers. It uses the etharp.c ARP code. + +loopif.c + A "loopback" network interface driver. It requires configuration + through the define LWIP_LOOPIF_MULTITHREADING (see opt.h). + +slipif.c + A generic implementation of the SLIP (Serial Line IP) + protocol. It requires a sio (serial I/O) module to work. + +ppp/ Point-to-Point Protocol stack + The PPP stack has been ported from ucip (http://ucip.sourceforge.net). + It matches quite well to pppd 2.3.1 (http://ppp.samba.org), although + compared to that, it has some modifications for embedded systems and + the source code has been reordered a bit. \ No newline at end of file diff --git a/component/common/network/lwip/lwip_v1.3.2/src/netif/etharp.c b/component/common/network/lwip/lwip_v1.3.2/src/netif/etharp.c new file mode 100644 index 0000000..28b2111 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/netif/etharp.c @@ -0,0 +1,1235 @@ +/* + * @file + * Address Resolution Protocol module for IP over Ethernet + * + * Functionally, ARP is divided into two parts. The first maps an IP address + * to a physical address when sending a packet, and the second part answers + * requests from other machines for our physical address. + * + * This implementation complies with RFC 826 (Ethernet ARP). It supports + * Gratuitious ARP from RFC3220 (IP Mobility Support for IPv4) section 4.6 + * if an interface calls etharp_gratuitous(our_netif) upon address change. + */ + +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * Copyright (c) 2003-2004 Leon Woestenberg + * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/opt.h" + +#if LWIP_ARP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/inet.h" +#include "lwip/ip.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" +#include "netif/etharp.h" + +#if PPPOE_SUPPORT +#include "netif/ppp_oe.h" +#endif /* PPPOE_SUPPORT */ + +#include + +/** the time an ARP entry stays valid after its last update, + * for ARP_TMR_INTERVAL = 5000, this is + * (240 * 5) seconds = 20 minutes. + */ +#define ARP_MAXAGE 240 +/** the time an ARP entry stays pending after first request, + * for ARP_TMR_INTERVAL = 5000, this is + * (2 * 5) seconds = 10 seconds. + * + * @internal Keep this number at least 2, otherwise it might + * run out instantly if the timeout occurs directly after a request. + */ +#define ARP_MAXPENDING 2 + +#define HWTYPE_ETHERNET 1 + +#define ARPH_HWLEN(hdr) (ntohs((hdr)->_hwlen_protolen) >> 8) +#define ARPH_PROTOLEN(hdr) (ntohs((hdr)->_hwlen_protolen) & 0xff) + +#define ARPH_HWLEN_SET(hdr, len) (hdr)->_hwlen_protolen = htons(ARPH_PROTOLEN(hdr) | ((len) << 8)) +#define ARPH_PROTOLEN_SET(hdr, len) (hdr)->_hwlen_protolen = htons((len) | (ARPH_HWLEN(hdr) << 8)) + +enum etharp_state { + ETHARP_STATE_EMPTY = 0, + ETHARP_STATE_PENDING, + ETHARP_STATE_STABLE +}; + +struct etharp_entry { +#if ARP_QUEUEING + /** + * Pointer to queue of pending outgoing packets on this ARP entry. + */ + struct etharp_q_entry *q; +#endif + struct ip_addr ipaddr; + struct eth_addr ethaddr; + enum etharp_state state; + u8_t ctime; + struct netif *netif; +}; + +const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}}; +const struct eth_addr ethzero = {{0,0,0,0,0,0}}; +static struct etharp_entry arp_table[ARP_TABLE_SIZE]; +#if !LWIP_NETIF_HWADDRHINT +static u8_t etharp_cached_entry; +#endif + +/** + * Try hard to create a new entry - we want the IP address to appear in + * the cache (even if this means removing an active entry or so). */ +#define ETHARP_TRY_HARD 1 +#define ETHARP_FIND_ONLY 2 + +#if LWIP_NETIF_HWADDRHINT +#define NETIF_SET_HINT(netif, hint) if (((netif) != NULL) && ((netif)->addr_hint != NULL)) \ + *((netif)->addr_hint) = (hint); +static s8_t find_entry(struct ip_addr *ipaddr, u8_t flags, struct netif *netif); +#else /* LWIP_NETIF_HWADDRHINT */ +static s8_t find_entry(struct ip_addr *ipaddr, u8_t flags); +#endif /* LWIP_NETIF_HWADDRHINT */ + +static err_t update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags); + + +/* Some checks, instead of etharp_init(): */ +#if (LWIP_ARP && (ARP_TABLE_SIZE > 0x7f)) + #error "If you want to use ARP, ARP_TABLE_SIZE must fit in an s8_t, so, you have to reduce it in your lwipopts.h" +#endif + + +#if ARP_QUEUEING +/** + * Free a complete queue of etharp entries + * + * @param q a qeueue of etharp_q_entry's to free + */ +static void +free_etharp_q(struct etharp_q_entry *q) +{ + struct etharp_q_entry *r; + LWIP_ASSERT("q != NULL", q != NULL); + LWIP_ASSERT("q->p != NULL", q->p != NULL); + while (q) { + r = q; + q = q->next; + LWIP_ASSERT("r->p != NULL", (r->p != NULL)); + pbuf_free(r->p); + memp_free(MEMP_ARP_QUEUE, r); + } +} +#endif + +/** + * Clears expired entries in the ARP table. + * + * This function should be called every ETHARP_TMR_INTERVAL microseconds (5 seconds), + * in order to expire entries in the ARP table. + */ +void +etharp_tmr(void) +{ + u8_t i; + + LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer\n")); + /* remove expired entries from the ARP table */ + for (i = 0; i < ARP_TABLE_SIZE; ++i) { + arp_table[i].ctime++; + if (((arp_table[i].state == ETHARP_STATE_STABLE) && + (arp_table[i].ctime >= ARP_MAXAGE)) || + ((arp_table[i].state == ETHARP_STATE_PENDING) && + (arp_table[i].ctime >= ARP_MAXPENDING))) { + /* pending or stable entry has become old! */ + LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired %s entry %"U16_F".\n", + arp_table[i].state == ETHARP_STATE_STABLE ? "stable" : "pending", (u16_t)i)); + /* clean up entries that have just been expired */ + /* remove from SNMP ARP index tree */ + snmp_delete_arpidx_tree(arp_table[i].netif, &arp_table[i].ipaddr); +#if ARP_QUEUEING + /* and empty packet queue */ + if (arp_table[i].q != NULL) { + /* remove all queued packets */ + LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: freeing entry %"U16_F", packet queue %p.\n", (u16_t)i, (void *)(arp_table[i].q))); + free_etharp_q(arp_table[i].q); + arp_table[i].q = NULL; + } +#endif + /* recycle entry for re-use */ + arp_table[i].state = ETHARP_STATE_EMPTY; + } +#if ARP_QUEUEING + /* still pending entry? (not expired) */ + if (arp_table[i].state == ETHARP_STATE_PENDING) { + /* resend an ARP query here? */ + } +#endif + } +} + +/** + * Search the ARP table for a matching or new entry. + * + * If an IP address is given, return a pending or stable ARP entry that matches + * the address. If no match is found, create a new entry with this address set, + * but in state ETHARP_EMPTY. The caller must check and possibly change the + * state of the returned entry. + * + * If ipaddr is NULL, return a initialized new entry in state ETHARP_EMPTY. + * + * In all cases, attempt to create new entries from an empty entry. If no + * empty entries are available and ETHARP_TRY_HARD flag is set, recycle + * old entries. Heuristic choose the least important entry for recycling. + * + * @param ipaddr IP address to find in ARP cache, or to add if not found. + * @param flags + * - ETHARP_TRY_HARD: Try hard to create a entry by allowing recycling of + * active (stable or pending) entries. + * + * @return The ARP entry index that matched or is created, ERR_MEM if no + * entry is found or could be recycled. + */ +static s8_t +#if LWIP_NETIF_HWADDRHINT +find_entry(struct ip_addr *ipaddr, u8_t flags, struct netif *netif) +#else /* LWIP_NETIF_HWADDRHINT */ +find_entry(struct ip_addr *ipaddr, u8_t flags) +#endif /* LWIP_NETIF_HWADDRHINT */ +{ + s8_t old_pending = ARP_TABLE_SIZE, old_stable = ARP_TABLE_SIZE; + s8_t empty = ARP_TABLE_SIZE; + u8_t i = 0, age_pending = 0, age_stable = 0; +#if ARP_QUEUEING + /* oldest entry with packets on queue */ + s8_t old_queue = ARP_TABLE_SIZE; + /* its age */ + u8_t age_queue = 0; +#endif + + /* First, test if the last call to this function asked for the + * same address. If so, we're really fast! */ + if (ipaddr) { + /* ipaddr to search for was given */ +#if LWIP_NETIF_HWADDRHINT + if ((netif != NULL) && (netif->addr_hint != NULL)) { + /* per-pcb cached entry was given */ + u8_t per_pcb_cache = *(netif->addr_hint); + if ((per_pcb_cache < ARP_TABLE_SIZE) && arp_table[per_pcb_cache].state == ETHARP_STATE_STABLE) { + /* the per-pcb-cached entry is stable */ + if (ip_addr_cmp(ipaddr, &arp_table[per_pcb_cache].ipaddr)) { + /* per-pcb cached entry was the right one! */ + ETHARP_STATS_INC(etharp.cachehit); + return per_pcb_cache; + } + } + } +#else /* #if LWIP_NETIF_HWADDRHINT */ + if (arp_table[etharp_cached_entry].state == ETHARP_STATE_STABLE) { + /* the cached entry is stable */ + if (ip_addr_cmp(ipaddr, &arp_table[etharp_cached_entry].ipaddr)) { + /* cached entry was the right one! */ + ETHARP_STATS_INC(etharp.cachehit); + return etharp_cached_entry; + } + } +#endif /* #if LWIP_NETIF_HWADDRHINT */ + } + + /** + * a) do a search through the cache, remember candidates + * b) select candidate entry + * c) create new entry + */ + + /* a) in a single search sweep, do all of this + * 1) remember the first empty entry (if any) + * 2) remember the oldest stable entry (if any) + * 3) remember the oldest pending entry without queued packets (if any) + * 4) remember the oldest pending entry with queued packets (if any) + * 5) search for a matching IP entry, either pending or stable + * until 5 matches, or all entries are searched for. + */ + + for (i = 0; i < ARP_TABLE_SIZE; ++i) { + /* no empty entry found yet and now we do find one? */ + if ((empty == ARP_TABLE_SIZE) && (arp_table[i].state == ETHARP_STATE_EMPTY)) { + LWIP_DEBUGF(ETHARP_DEBUG, ("find_entry: found empty entry %"U16_F"\n", (u16_t)i)); + /* remember first empty entry */ + empty = i; + } + /* pending entry? */ + else if (arp_table[i].state == ETHARP_STATE_PENDING) { + /* if given, does IP address match IP address in ARP entry? */ + if (ipaddr && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: found matching pending entry %"U16_F"\n", (u16_t)i)); + /* found exact IP address match, simply bail out */ +#if LWIP_NETIF_HWADDRHINT + NETIF_SET_HINT(netif, i); +#else /* #if LWIP_NETIF_HWADDRHINT */ + etharp_cached_entry = i; +#endif /* #if LWIP_NETIF_HWADDRHINT */ + return i; +#if ARP_QUEUEING + /* pending with queued packets? */ + } else if (arp_table[i].q != NULL) { + if (arp_table[i].ctime >= age_queue) { + old_queue = i; + age_queue = arp_table[i].ctime; + } +#endif + /* pending without queued packets? */ + } else { + if (arp_table[i].ctime >= age_pending) { + old_pending = i; + age_pending = arp_table[i].ctime; + } + } + } + /* stable entry? */ + else if (arp_table[i].state == ETHARP_STATE_STABLE) { + /* if given, does IP address match IP address in ARP entry? */ + if (ipaddr && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: found matching stable entry %"U16_F"\n", (u16_t)i)); + /* found exact IP address match, simply bail out */ +#if LWIP_NETIF_HWADDRHINT + NETIF_SET_HINT(netif, i); +#else /* #if LWIP_NETIF_HWADDRHINT */ + etharp_cached_entry = i; +#endif /* #if LWIP_NETIF_HWADDRHINT */ + return i; + /* remember entry with oldest stable entry in oldest, its age in maxtime */ + } else if (arp_table[i].ctime >= age_stable) { + old_stable = i; + age_stable = arp_table[i].ctime; + } + } + } + /* { we have no match } => try to create a new entry */ + + /* no empty entry found and not allowed to recycle? */ + if (((empty == ARP_TABLE_SIZE) && ((flags & ETHARP_TRY_HARD) == 0)) + /* or don't create new entry, only search? */ + || ((flags & ETHARP_FIND_ONLY) != 0)) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: no empty entry found and not allowed to recycle\n")); + return (s8_t)ERR_MEM; + } + + /* b) choose the least destructive entry to recycle: + * 1) empty entry + * 2) oldest stable entry + * 3) oldest pending entry without queued packets + * 4) oldest pending entry with queued packets + * + * { ETHARP_TRY_HARD is set at this point } + */ + + /* 1) empty entry available? */ + if (empty < ARP_TABLE_SIZE) { + i = empty; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting empty entry %"U16_F"\n", (u16_t)i)); + } + /* 2) found recyclable stable entry? */ + else if (old_stable < ARP_TABLE_SIZE) { + /* recycle oldest stable*/ + i = old_stable; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest stable entry %"U16_F"\n", (u16_t)i)); +#if ARP_QUEUEING + /* no queued packets should exist on stable entries */ + LWIP_ASSERT("arp_table[i].q == NULL", arp_table[i].q == NULL); +#endif + /* 3) found recyclable pending entry without queued packets? */ + } else if (old_pending < ARP_TABLE_SIZE) { + /* recycle oldest pending */ + i = old_pending; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F" (without queue)\n", (u16_t)i)); +#if ARP_QUEUEING + /* 4) found recyclable pending entry with queued packets? */ + } else if (old_queue < ARP_TABLE_SIZE) { + /* recycle oldest pending */ + i = old_queue; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F", freeing packet queue %p\n", (u16_t)i, (void *)(arp_table[i].q))); + free_etharp_q(arp_table[i].q); + arp_table[i].q = NULL; +#endif + /* no empty or recyclable entries found */ + } else { + return (s8_t)ERR_MEM; + } + + /* { empty or recyclable entry found } */ + LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE); + + if (arp_table[i].state != ETHARP_STATE_EMPTY) + { + snmp_delete_arpidx_tree(arp_table[i].netif, &arp_table[i].ipaddr); + } + /* recycle entry (no-op for an already empty entry) */ + arp_table[i].state = ETHARP_STATE_EMPTY; + + /* IP address given? */ + if (ipaddr != NULL) { + /* set IP address */ + ip_addr_set(&arp_table[i].ipaddr, ipaddr); + } + arp_table[i].ctime = 0; +#if LWIP_NETIF_HWADDRHINT + NETIF_SET_HINT(netif, i); +#else /* #if LWIP_NETIF_HWADDRHINT */ + etharp_cached_entry = i; +#endif /* #if LWIP_NETIF_HWADDRHINT */ + return (err_t)i; +} + +/** + * Send an IP packet on the network using netif->linkoutput + * The ethernet header is filled in before sending. + * + * @params netif the lwIP network interface on which to send the packet + * @params p the packet to send, p->payload pointing to the (uninitialized) ethernet header + * @params src the source MAC address to be copied into the ethernet header + * @params dst the destination MAC address to be copied into the ethernet header + * @return ERR_OK if the packet was sent, any other err_t on failure + */ +static err_t +etharp_send_ip(struct netif *netif, struct pbuf *p, struct eth_addr *src, struct eth_addr *dst) +{ + struct eth_hdr *ethhdr = p->payload; + u8_t k; + + LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!", + (netif->hwaddr_len == ETHARP_HWADDR_LEN)); + k = ETHARP_HWADDR_LEN; + while(k > 0) { + k--; + ethhdr->dest.addr[k] = dst->addr[k]; + ethhdr->src.addr[k] = src->addr[k]; + } + ethhdr->type = htons(ETHTYPE_IP); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_send_ip: sending packet %p\n", (void *)p)); + /* send the packet */ + return netif->linkoutput(netif, p); +} + +/** + * Update (or insert) a IP/MAC address pair in the ARP cache. + * + * If a pending entry is resolved, any queued packets will be sent + * at this point. + * + * @param ipaddr IP address of the inserted ARP entry. + * @param ethaddr Ethernet address of the inserted ARP entry. + * @param flags Defines behaviour: + * - ETHARP_TRY_HARD Allows ARP to insert this as a new item. If not specified, + * only existing ARP entries will be updated. + * + * @return + * - ERR_OK Succesfully updated ARP cache. + * - ERR_MEM If we could not add a new ARP entry when ETHARP_TRY_HARD was set. + * - ERR_ARG Non-unicast address given, those will not appear in ARP cache. + * + * @see pbuf_free() + */ +static err_t +update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags) +{ + s8_t i; + u8_t k; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("update_arp_entry()\n")); + LWIP_ASSERT("netif->hwaddr_len == ETHARP_HWADDR_LEN", netif->hwaddr_len == ETHARP_HWADDR_LEN); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("update_arp_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n", + ip4_addr1(ipaddr), ip4_addr2(ipaddr), ip4_addr3(ipaddr), ip4_addr4(ipaddr), + ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2], + ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5])); + /* non-unicast address? */ + if (ip_addr_isany(ipaddr) || + ip_addr_isbroadcast(ipaddr, netif) || + ip_addr_ismulticast(ipaddr)) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("update_arp_entry: will not add non-unicast IP address to ARP cache\n")); + return ERR_ARG; + } + /* find or create ARP entry */ +#if LWIP_NETIF_HWADDRHINT + i = find_entry(ipaddr, flags, netif); +#else /* LWIP_NETIF_HWADDRHINT */ + i = find_entry(ipaddr, flags); +#endif /* LWIP_NETIF_HWADDRHINT */ + /* bail out if no entry could be found */ + if (i < 0) + return (err_t)i; + + /* mark it stable */ + arp_table[i].state = ETHARP_STATE_STABLE; + /* record network interface */ + arp_table[i].netif = netif; + + /* insert in SNMP ARP index tree */ + snmp_insert_arpidx_tree(netif, &arp_table[i].ipaddr); + + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("update_arp_entry: updating stable entry %"S16_F"\n", (s16_t)i)); + /* update address */ + k = ETHARP_HWADDR_LEN; + while (k > 0) { + k--; + arp_table[i].ethaddr.addr[k] = ethaddr->addr[k]; + } + /* reset time stamp */ + arp_table[i].ctime = 0; +#if ARP_QUEUEING + /* this is where we will send out queued packets! */ + while (arp_table[i].q != NULL) { + struct pbuf *p; + /* remember remainder of queue */ + struct etharp_q_entry *q = arp_table[i].q; + /* pop first item off the queue */ + arp_table[i].q = q->next; + /* get the packet pointer */ + p = q->p; + /* now queue entry can be freed */ + memp_free(MEMP_ARP_QUEUE, q); + /* send the queued IP packet */ + etharp_send_ip(netif, p, (struct eth_addr*)(netif->hwaddr), ethaddr); + /* free the queued IP packet */ + pbuf_free(p); + } +#endif + return ERR_OK; +} + +/** + * Finds (stable) ethernet/IP address pair from ARP table + * using interface and IP address index. + * @note the addresses in the ARP table are in network order! + * + * @param netif points to interface index + * @param ipaddr points to the (network order) IP address index + * @param eth_ret points to return pointer + * @param ip_ret points to return pointer + * @return table index if found, -1 otherwise + */ +s8_t +etharp_find_addr(struct netif *netif, struct ip_addr *ipaddr, + struct eth_addr **eth_ret, struct ip_addr **ip_ret) +{ + s8_t i; + + LWIP_UNUSED_ARG(netif); + +#if LWIP_NETIF_HWADDRHINT + i = find_entry(ipaddr, ETHARP_FIND_ONLY, NULL); +#else /* LWIP_NETIF_HWADDRHINT */ + i = find_entry(ipaddr, ETHARP_FIND_ONLY); +#endif /* LWIP_NETIF_HWADDRHINT */ + if((i >= 0) && arp_table[i].state == ETHARP_STATE_STABLE) { + *eth_ret = &arp_table[i].ethaddr; + *ip_ret = &arp_table[i].ipaddr; + return i; + } + return -1; +} + +/** + * Updates the ARP table using the given IP packet. + * + * Uses the incoming IP packet's source address to update the + * ARP cache for the local network. The function does not alter + * or free the packet. This function must be called before the + * packet p is passed to the IP layer. + * + * @param netif The lwIP network interface on which the IP packet pbuf arrived. + * @param p The IP packet that arrived on netif. + * + * @return NULL + * + * @see pbuf_free() + */ +void +etharp_ip_input(struct netif *netif, struct pbuf *p) +{ + struct eth_hdr *ethhdr; + struct ip_hdr *iphdr; + LWIP_ERROR("netif != NULL", (netif != NULL), return;); + /* Only insert an entry if the source IP address of the + incoming IP packet comes from a host on the local network. */ + ethhdr = p->payload; + iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR); +#if ETHARP_SUPPORT_VLAN + if (ethhdr->type == ETHTYPE_VLAN) { + iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR); + } +#endif /* ETHARP_SUPPORT_VLAN */ + + /* source is not on the local network? */ + if (!ip_addr_netcmp(&(iphdr->src), &(netif->ip_addr), &(netif->netmask))) { + /* do nothing */ + return; + } + + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_ip_input: updating ETHARP table.\n")); + /* update ARP table */ + /* @todo We could use ETHARP_TRY_HARD if we think we are going to talk + * back soon (for example, if the destination IP address is ours. */ + update_arp_entry(netif, &(iphdr->src), &(ethhdr->src), 0); +} + + +/** + * Responds to ARP requests to us. Upon ARP replies to us, add entry to cache + * send out queued IP packets. Updates cache with snooped address pairs. + * + * Should be called for incoming ARP packets. The pbuf in the argument + * is freed by this function. + * + * @param netif The lwIP network interface on which the ARP packet pbuf arrived. + * @param ethaddr Ethernet address of netif. + * @param p The ARP packet that arrived on netif. Is freed by this function. + * + * @return NULL + * + * @see pbuf_free() + */ +void +etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p) +{ + struct etharp_hdr *hdr; + struct eth_hdr *ethhdr; + /* these are aligned properly, whereas the ARP header fields might not be */ + struct ip_addr sipaddr, dipaddr; + u8_t i; + u8_t for_us; +#if LWIP_AUTOIP + const u8_t * ethdst_hwaddr; +#endif /* LWIP_AUTOIP */ + + LWIP_ERROR("netif != NULL", (netif != NULL), return;); + + /* drop short ARP packets: we have to check for p->len instead of p->tot_len here + since a struct etharp_hdr is pointed to p->payload, so it musn't be chained! */ + if (p->len < SIZEOF_ETHARP_PACKET) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("etharp_arp_input: packet dropped, too short (%"S16_F"/%"S16_F")\n", p->tot_len, + (s16_t)SIZEOF_ETHARP_PACKET)); + ETHARP_STATS_INC(etharp.lenerr); + ETHARP_STATS_INC(etharp.drop); + pbuf_free(p); + return; + } + + ethhdr = p->payload; + hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR); +#if ETHARP_SUPPORT_VLAN + if (ethhdr->type == ETHTYPE_VLAN) { + hdr = (struct etharp_hdr *)(((u8_t*)ethhdr) + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR); + } +#endif /* ETHARP_SUPPORT_VLAN */ + + /* RFC 826 "Packet Reception": */ + if ((hdr->hwtype != htons(HWTYPE_ETHERNET)) || + (hdr->_hwlen_protolen != htons((ETHARP_HWADDR_LEN << 8) | sizeof(struct ip_addr))) || + (hdr->proto != htons(ETHTYPE_IP)) || + (ethhdr->type != htons(ETHTYPE_ARP))) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("etharp_arp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n", + hdr->hwtype, ARPH_HWLEN(hdr), hdr->proto, ARPH_PROTOLEN(hdr), ethhdr->type)); + ETHARP_STATS_INC(etharp.proterr); + ETHARP_STATS_INC(etharp.drop); + pbuf_free(p); + return; + } + ETHARP_STATS_INC(etharp.recv); + +#if LWIP_AUTOIP + /* We have to check if a host already has configured our random + * created link local address and continously check if there is + * a host with this IP-address so we can detect collisions */ + autoip_arp_reply(netif, hdr); +#endif /* LWIP_AUTOIP */ + + /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without + * structure packing (not using structure copy which breaks strict-aliasing rules). */ + SMEMCPY(&sipaddr, &hdr->sipaddr, sizeof(sipaddr)); + SMEMCPY(&dipaddr, &hdr->dipaddr, sizeof(dipaddr)); + + /* this interface is not configured? */ + if (netif->ip_addr.addr == 0) { + for_us = 0; + } else { + /* ARP packet directed to us? */ + for_us = ip_addr_cmp(&dipaddr, &(netif->ip_addr)); + } + + /* ARP message directed to us? */ + if (for_us) { + /* add IP address in ARP cache; assume requester wants to talk to us. + * can result in directly sending the queued packets for this host. */ + update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), ETHARP_TRY_HARD); + /* ARP message not directed to us? */ + } else { + /* update the source IP address in the cache, if present */ + update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), 0); + } + + /* now act on the message itself */ + switch (htons(hdr->opcode)) { + /* ARP request? */ + case ARP_REQUEST: + /* ARP request. If it asked for our address, we send out a + * reply. In any case, we time-stamp any existing ARP entry, + * and possiby send out an IP packet that was queued on it. */ + + LWIP_DEBUGF (ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: incoming ARP request\n")); + /* ARP request for our address? */ + if (for_us) { + + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: replying to ARP request for our IP address\n")); + /* Re-use pbuf to send ARP reply. + Since we are re-using an existing pbuf, we can't call etharp_raw since + that would allocate a new pbuf. */ + hdr->opcode = htons(ARP_REPLY); + + hdr->dipaddr = hdr->sipaddr; + SMEMCPY(&hdr->sipaddr, &netif->ip_addr, sizeof(hdr->sipaddr)); + + LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!", + (netif->hwaddr_len == ETHARP_HWADDR_LEN)); + i = ETHARP_HWADDR_LEN; +#if LWIP_AUTOIP + /* If we are using Link-Local, ARP packets must be broadcast on the + * link layer. (See RFC3927 Section 2.5) */ + ethdst_hwaddr = ((netif->autoip != NULL) && (netif->autoip->state != AUTOIP_STATE_OFF)) ? (u8_t*)(ethbroadcast.addr) : hdr->shwaddr.addr; +#endif /* LWIP_AUTOIP */ + + while(i > 0) { + i--; + hdr->dhwaddr.addr[i] = hdr->shwaddr.addr[i]; +#if LWIP_AUTOIP + ethhdr->dest.addr[i] = ethdst_hwaddr[i]; +#else /* LWIP_AUTOIP */ + ethhdr->dest.addr[i] = hdr->shwaddr.addr[i]; +#endif /* LWIP_AUTOIP */ + hdr->shwaddr.addr[i] = ethaddr->addr[i]; + ethhdr->src.addr[i] = ethaddr->addr[i]; + } + + /* hwtype, hwaddr_len, proto, protolen and the type in the ethernet header + are already correct, we tested that before */ + + /* return ARP reply */ + netif->linkoutput(netif, p); + /* we are not configured? */ + } else if (netif->ip_addr.addr == 0) { + /* { for_us == 0 and netif->ip_addr.addr == 0 } */ + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: we are unconfigured, ARP request ignored.\n")); + /* request was not directed to us */ + } else { + /* { for_us == 0 and netif->ip_addr.addr != 0 } */ +/* Realtek Modified Start */ +#ifdef CONFIG_DONT_CARE_TP + if(netif->flags & NETIF_FLAG_IPSWITCH) + netif->linkoutput(netif, p); + else +#endif +/* Realtek Modified End */ + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: ARP request was not for us.\n")); + } + break; + case ARP_REPLY: + /* ARP reply. We already updated the ARP cache earlier. */ + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: incoming ARP reply\n")); +#if (LWIP_DHCP && DHCP_DOES_ARP_CHECK) + /* DHCP wants to know about ARP replies from any host with an + * IP address also offered to us by the DHCP server. We do not + * want to take a duplicate IP address on a single network. + * @todo How should we handle redundant (fail-over) interfaces? */ + dhcp_arp_reply(netif, &sipaddr); +#endif +/* Realtek Modified Start */ +#ifdef CONFIG_DONT_CARE_TP + if(netif->flags & NETIF_FLAG_IPSWITCH) + netif->linkoutput(netif, p); +#endif +/* Realtek Modified End */ + break; + default: + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: ARP unknown opcode type %"S16_F"\n", htons(hdr->opcode))); + ETHARP_STATS_INC(etharp.err); + break; + } + /* free ARP packet */ + pbuf_free(p); +} + +/** + * Resolve and fill-in Ethernet address header for outgoing IP packet. + * + * For IP multicast and broadcast, corresponding Ethernet addresses + * are selected and the packet is transmitted on the link. + * + * For unicast addresses, the packet is submitted to etharp_query(). In + * case the IP address is outside the local network, the IP address of + * the gateway is used. + * + * @param netif The lwIP network interface which the IP packet will be sent on. + * @param q The pbuf(s) containing the IP packet to be sent. + * @param ipaddr The IP address of the packet destination. + * + * @return + * - ERR_RTE No route to destination (no gateway to external networks), + * or the return type of either etharp_query() or etharp_send_ip(). + */ +err_t +etharp_output(struct netif *netif, struct pbuf *q, struct ip_addr *ipaddr) +{ + struct eth_addr *dest, mcastaddr; + + /* make room for Ethernet header - should not fail */ + if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) { + /* bail out */ + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("etharp_output: could not allocate room for header.\n")); + LINK_STATS_INC(link.lenerr); + return ERR_BUF; + } + + /* assume unresolved Ethernet address */ + dest = NULL; + /* Determine on destination hardware address. Broadcasts and multicasts + * are special, other IP addresses are looked up in the ARP table. */ + + /* broadcast destination IP address? */ + if (ip_addr_isbroadcast(ipaddr, netif)) { + /* broadcast on Ethernet also */ + dest = (struct eth_addr *)ðbroadcast; + /* multicast destination IP address? */ + } else if (ip_addr_ismulticast(ipaddr)) { + /* Hash IP multicast address to MAC address.*/ + mcastaddr.addr[0] = 0x01; + mcastaddr.addr[1] = 0x00; + mcastaddr.addr[2] = 0x5e; + mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f; + mcastaddr.addr[4] = ip4_addr3(ipaddr); + mcastaddr.addr[5] = ip4_addr4(ipaddr); + /* destination Ethernet address is multicast */ + dest = &mcastaddr; + /* unicast destination IP address? */ + } else { + /* outside local network? */ + if (!ip_addr_netcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) { + /* interface has default gateway? */ + if (netif->gw.addr != 0) { + /* send to hardware address of default gateway IP address */ + ipaddr = &(netif->gw); + /* no default gateway available */ + } else { + /* no route to destination error (default gateway missing) */ + return ERR_RTE; + } + } + /* queue on destination Ethernet address belonging to ipaddr */ + return etharp_query(netif, ipaddr, q); + } + + /* continuation for multicast/broadcast destinations */ + /* obtain source Ethernet address of the given interface */ + /* send packet directly on the link */ + return etharp_send_ip(netif, q, (struct eth_addr*)(netif->hwaddr), dest); +} + +/** + * Send an ARP request for the given IP address and/or queue a packet. + * + * If the IP address was not yet in the cache, a pending ARP cache entry + * is added and an ARP request is sent for the given address. The packet + * is queued on this entry. + * + * If the IP address was already pending in the cache, a new ARP request + * is sent for the given address. The packet is queued on this entry. + * + * If the IP address was already stable in the cache, and a packet is + * given, it is directly sent and no ARP request is sent out. + * + * If the IP address was already stable in the cache, and no packet is + * given, an ARP request is sent out. + * + * @param netif The lwIP network interface on which ipaddr + * must be queried for. + * @param ipaddr The IP address to be resolved. + * @param q If non-NULL, a pbuf that must be delivered to the IP address. + * q is not freed by this function. + * + * @note q must only be ONE packet, not a packet queue! + * + * @return + * - ERR_BUF Could not make room for Ethernet header. + * - ERR_MEM Hardware address unknown, and no more ARP entries available + * to query for address or queue the packet. + * - ERR_MEM Could not queue packet due to memory shortage. + * - ERR_RTE No route to destination (no gateway to external networks). + * - ERR_ARG Non-unicast address given, those will not appear in ARP cache. + * + */ +err_t +etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q) +{ + struct eth_addr * srcaddr = (struct eth_addr *)netif->hwaddr; + err_t result = ERR_MEM; + s8_t i; /* ARP entry index */ + + /* non-unicast address? */ + if (ip_addr_isbroadcast(ipaddr, netif) || + ip_addr_ismulticast(ipaddr) || + ip_addr_isany(ipaddr)) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: will not add non-unicast IP address to ARP cache\n")); + return ERR_ARG; + } + + /* find entry in ARP cache, ask to create entry if queueing packet */ +#if LWIP_NETIF_HWADDRHINT + i = find_entry(ipaddr, ETHARP_TRY_HARD, netif); +#else /* LWIP_NETIF_HWADDRHINT */ + i = find_entry(ipaddr, ETHARP_TRY_HARD); +#endif /* LWIP_NETIF_HWADDRHINT */ + + /* could not find or create entry? */ + if (i < 0) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not create ARP entry\n")); + if (q) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: packet dropped\n")); + ETHARP_STATS_INC(etharp.memerr); + } + return (err_t)i; + } + + /* mark a fresh entry as pending (we just sent a request) */ + if (arp_table[i].state == ETHARP_STATE_EMPTY) { + arp_table[i].state = ETHARP_STATE_PENDING; + } + + /* { i is either a STABLE or (new or existing) PENDING entry } */ + LWIP_ASSERT("arp_table[i].state == PENDING or STABLE", + ((arp_table[i].state == ETHARP_STATE_PENDING) || + (arp_table[i].state == ETHARP_STATE_STABLE))); + + /* do we have a pending entry? or an implicit query request? */ + if ((arp_table[i].state == ETHARP_STATE_PENDING) || (q == NULL)) { + /* try to resolve it; send out ARP request */ + result = etharp_request(netif, ipaddr); + if (result != ERR_OK) { + /* ARP request couldn't be sent */ + /* We don't re-send arp request in etharp_tmr, but we still queue packets, + since this failure could be temporary, and the next packet calling + etharp_query again could lead to sending the queued packets. */ + } + } + + /* packet given? */ + if (q != NULL) { + /* stable entry? */ + if (arp_table[i].state == ETHARP_STATE_STABLE) { + /* we have a valid IP->Ethernet address mapping */ + /* send the packet */ + result = etharp_send_ip(netif, q, srcaddr, &(arp_table[i].ethaddr)); + /* pending entry? (either just created or already pending */ + } else if (arp_table[i].state == ETHARP_STATE_PENDING) { +#if ARP_QUEUEING /* queue the given q packet */ + struct pbuf *p; + int copy_needed = 0; + /* IF q includes a PBUF_REF, PBUF_POOL or PBUF_RAM, we have no choice but + * to copy the whole queue into a new PBUF_RAM (see bug #11400) + * PBUF_ROMs can be left as they are, since ROM must not get changed. */ + p = q; + while (p) { + LWIP_ASSERT("no packet queues allowed!", (p->len != p->tot_len) || (p->next == 0)); + if(p->type != PBUF_ROM) { + copy_needed = 1; + break; + } + p = p->next; + } + if(copy_needed) { + /* copy the whole packet into new pbufs */ + p = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); + if(p != NULL) { + if (pbuf_copy(p, q) != ERR_OK) { + pbuf_free(p); + p = NULL; + } + } + } else { + /* referencing the old pbuf is enough */ + p = q; + pbuf_ref(p); + } + /* packet could be taken over? */ + if (p != NULL) { + /* queue packet ... */ + struct etharp_q_entry *new_entry; + /* allocate a new arp queue entry */ + new_entry = memp_malloc(MEMP_ARP_QUEUE); + if (new_entry != NULL) { + new_entry->next = 0; + new_entry->p = p; + if(arp_table[i].q != NULL) { + /* queue was already existent, append the new entry to the end */ + struct etharp_q_entry *r; + r = arp_table[i].q; + while (r->next != NULL) { + r = r->next; + } + r->next = new_entry; + } else { + /* queue did not exist, first item in queue */ + arp_table[i].q = new_entry; + } + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i)); + result = ERR_OK; + } else { + /* the pool MEMP_ARP_QUEUE is empty */ + pbuf_free(p); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q)); + /* { result == ERR_MEM } through initialization */ + } + } else { + ETHARP_STATS_INC(etharp.memerr); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q)); + /* { result == ERR_MEM } through initialization */ + } +#else /* ARP_QUEUEING == 0 */ + /* q && state == PENDING && ARP_QUEUEING == 0 => result = ERR_MEM */ + /* { result == ERR_MEM } through initialization */ + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: Ethernet destination address unknown, queueing disabled, packet %p dropped\n", (void *)q)); +#endif + } + } + return result; +} + +/** + * Send a raw ARP packet (opcode and all addresses can be modified) + * + * @param netif the lwip network interface on which to send the ARP packet + * @param ethsrc_addr the source MAC address for the ethernet header + * @param ethdst_addr the destination MAC address for the ethernet header + * @param hwsrc_addr the source MAC address for the ARP protocol header + * @param ipsrc_addr the source IP address for the ARP protocol header + * @param hwdst_addr the destination MAC address for the ARP protocol header + * @param ipdst_addr the destination IP address for the ARP protocol header + * @param opcode the type of the ARP packet + * @return ERR_OK if the ARP packet has been sent + * ERR_MEM if the ARP packet couldn't be allocated + * any other err_t on failure + */ +#if !LWIP_AUTOIP +static +#endif /* LWIP_AUTOIP */ +err_t +etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr, + const struct eth_addr *ethdst_addr, + const struct eth_addr *hwsrc_addr, const struct ip_addr *ipsrc_addr, + const struct eth_addr *hwdst_addr, const struct ip_addr *ipdst_addr, + const u16_t opcode) +{ + struct pbuf *p; + err_t result = ERR_OK; + u8_t k; /* ARP entry index */ + struct eth_hdr *ethhdr; + struct etharp_hdr *hdr; +#if LWIP_AUTOIP + const u8_t * ethdst_hwaddr; +#endif /* LWIP_AUTOIP */ + + /* allocate a pbuf for the outgoing ARP request packet */ + p = pbuf_alloc(PBUF_RAW, SIZEOF_ETHARP_PACKET, PBUF_RAM); + /* could allocate a pbuf for an ARP request? */ + if (p == NULL) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("etharp_raw: could not allocate pbuf for ARP request.\n")); + ETHARP_STATS_INC(etharp.memerr); + return ERR_MEM; + } + LWIP_ASSERT("check that first pbuf can hold struct etharp_hdr", + (p->len >= SIZEOF_ETHARP_PACKET)); + + ethhdr = p->payload; + hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_raw: sending raw ARP packet.\n")); + hdr->opcode = htons(opcode); + + LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!", + (netif->hwaddr_len == ETHARP_HWADDR_LEN)); + k = ETHARP_HWADDR_LEN; +#if LWIP_AUTOIP + /* If we are using Link-Local, ARP packets must be broadcast on the + * link layer. (See RFC3927 Section 2.5) */ + ethdst_hwaddr = ((netif->autoip != NULL) && (netif->autoip->state != AUTOIP_STATE_OFF)) ? (u8_t*)(ethbroadcast.addr) : ethdst_addr->addr; +#endif /* LWIP_AUTOIP */ + /* Write MAC-Addresses (combined loop for both headers) */ + while(k > 0) { + k--; + /* Write the ARP MAC-Addresses */ + hdr->shwaddr.addr[k] = hwsrc_addr->addr[k]; + hdr->dhwaddr.addr[k] = hwdst_addr->addr[k]; + /* Write the Ethernet MAC-Addresses */ +#if LWIP_AUTOIP + ethhdr->dest.addr[k] = ethdst_hwaddr[k]; +#else /* LWIP_AUTOIP */ + ethhdr->dest.addr[k] = ethdst_addr->addr[k]; +#endif /* LWIP_AUTOIP */ + ethhdr->src.addr[k] = ethsrc_addr->addr[k]; + } + hdr->sipaddr = *(struct ip_addr2 *)ipsrc_addr; + hdr->dipaddr = *(struct ip_addr2 *)ipdst_addr; + + hdr->hwtype = htons(HWTYPE_ETHERNET); + hdr->proto = htons(ETHTYPE_IP); + /* set hwlen and protolen together */ + hdr->_hwlen_protolen = htons((ETHARP_HWADDR_LEN << 8) | sizeof(struct ip_addr)); + + ethhdr->type = htons(ETHTYPE_ARP); + /* send ARP query */ + result = netif->linkoutput(netif, p); + ETHARP_STATS_INC(etharp.xmit); + /* free ARP query packet */ + pbuf_free(p); + p = NULL; + /* could not allocate pbuf for ARP request */ + + return result; +} + +/** + * Send an ARP request packet asking for ipaddr. + * + * @param netif the lwip network interface on which to send the request + * @param ipaddr the IP address for which to ask + * @return ERR_OK if the request has been sent + * ERR_MEM if the ARP packet couldn't be allocated + * any other err_t on failure + */ +err_t +etharp_request(struct netif *netif, struct ip_addr *ipaddr) +{ + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_request: sending ARP request.\n")); + return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, ðbroadcast, + (struct eth_addr *)netif->hwaddr, &netif->ip_addr, ðzero, + ipaddr, ARP_REQUEST); +} + +/** + * Process received ethernet frames. Using this function instead of directly + * calling ip_input and passing ARP frames through etharp in ethernetif_input, + * the ARP cache is protected from concurrent access. + * + * @param p the recevied packet, p->payload pointing to the ethernet header + * @param netif the network interface on which the packet was received + */ +err_t +ethernet_input(struct pbuf *p, struct netif *netif) +{ + struct eth_hdr* ethhdr; + u16_t type; + + /* points to packet payload, which starts with an Ethernet header */ + ethhdr = p->payload; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, + ("ethernet_input: dest:%02x:%02x:%02x:%02x:%02x:%02x, src:%02x:%02x:%02x:%02x:%02x:%02x, type:%2hx\n", + (unsigned)ethhdr->dest.addr[0], (unsigned)ethhdr->dest.addr[1], (unsigned)ethhdr->dest.addr[2], + (unsigned)ethhdr->dest.addr[3], (unsigned)ethhdr->dest.addr[4], (unsigned)ethhdr->dest.addr[5], + (unsigned)ethhdr->src.addr[0], (unsigned)ethhdr->src.addr[1], (unsigned)ethhdr->src.addr[2], + (unsigned)ethhdr->src.addr[3], (unsigned)ethhdr->src.addr[4], (unsigned)ethhdr->src.addr[5], + (unsigned)htons(ethhdr->type))); + + type = htons(ethhdr->type); +#if ETHARP_SUPPORT_VLAN + if (type == ETHTYPE_VLAN) { + struct eth_vlan_hdr *vlan = (struct eth_vlan_hdr*)(((char*)ethhdr) + SIZEOF_ETH_HDR); +#ifdef ETHARP_VLAN_CHECK /* if not, allow all VLANs */ + if (VLAN_ID(vlan) != ETHARP_VLAN_CHECK) { + /* silently ignore this packet: not for our VLAN */ + pbuf_free(p); + return ERR_OK; + } +#endif /* ETHARP_VLAN_CHECK */ + type = htons(vlan->tpid); + } +#endif /* ETHARP_SUPPORT_VLAN */ + + switch (type) { + /* IP packet? */ + case ETHTYPE_IP: +#if ETHARP_TRUST_IP_MAC + /* update ARP table */ + etharp_ip_input(netif, p); +#endif /* ETHARP_TRUST_IP_MAC */ + /* skip Ethernet header */ + if(pbuf_header(p, -(s16_t)SIZEOF_ETH_HDR)) { + LWIP_ASSERT("Can't move over header in packet", 0); + pbuf_free(p); + p = NULL; + } else { + /* pass to IP layer */ + ip_input(p, netif); + } + break; + + case ETHTYPE_ARP: + /* pass p to ARP module */ + etharp_arp_input(netif, (struct eth_addr*)(netif->hwaddr), p); + break; + +#if PPPOE_SUPPORT + case ETHTYPE_PPPOEDISC: /* PPP Over Ethernet Discovery Stage */ + pppoe_disc_input(netif, p); + break; + + case ETHTYPE_PPPOE: /* PPP Over Ethernet Session Stage */ + pppoe_data_input(netif, p); + break; +#endif /* PPPOE_SUPPORT */ + + default: + ETHARP_STATS_INC(etharp.proterr); + ETHARP_STATS_INC(etharp.drop); + pbuf_free(p); + p = NULL; + break; + } + + /* This means the pbuf is freed or consumed, + so the caller doesn't have to free it again */ + return ERR_OK; +} +#endif /* LWIP_ARP */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/netif/loopif.c b/component/common/network/lwip/lwip_v1.3.2/src/netif/loopif.c new file mode 100644 index 0000000..cbcda78 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/netif/loopif.c @@ -0,0 +1,66 @@ +/** + * @file + * Loop Interface + * + **/ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#include "lwip/opt.h" + +#if LWIP_HAVE_LOOPIF + +#include "netif/loopif.h" +#include "lwip/snmp.h" + +/** + * Initialize a lwip network interface structure for a loopback interface + * + * @param netif the lwip network interface structure for this loopif + * @return ERR_OK if the loopif is initialized + * ERR_MEM if private data couldn't be allocated + */ +err_t +loopif_init(struct netif *netif) +{ + /* initialize the snmp variables and counters inside the struct netif + * ifSpeed: no assumption can be made! + */ + NETIF_INIT_SNMP(netif, snmp_ifType_softwareLoopback, 0); + + netif->name[0] = 'l'; + netif->name[1] = 'o'; + netif->output = netif_loop_output; + return ERR_OK; +} + +#endif /* LWIP_HAVE_LOOPIF */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/auth.c b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/auth.c new file mode 100644 index 0000000..cbd3eb2 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/auth.c @@ -0,0 +1,990 @@ +/***************************************************************************** +* auth.c - Network Authentication and Phase Control program file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* Copyright (c) 1997 by Global Election Systems Inc. All rights reserved. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-12-08 Guy Lancaster , Global Election Systems Inc. +* Ported from public pppd code. +*****************************************************************************/ +/* + * auth.c - PPP authentication and phase control. + * + * Copyright (c) 1993 The Australian National University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the Australian National University. The name of the University + * may not be used to endorse or promote products derived from this + * software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "lwip/opt.h" + +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "ppp.h" +#include "pppdebug.h" + +#include "fsm.h" +#include "lcp.h" +#include "pap.h" +#include "chap.h" +#include "auth.h" +#include "ipcp.h" + +#if CBCP_SUPPORT +#include "cbcp.h" +#endif /* CBCP_SUPPORT */ + +#include + +/*************************/ +/*** LOCAL DEFINITIONS ***/ +/*************************/ + +/* Bits in auth_pending[] */ +#define PAP_WITHPEER 1 +#define PAP_PEER 2 +#define CHAP_WITHPEER 4 +#define CHAP_PEER 8 + + +/************************/ +/*** LOCAL DATA TYPES ***/ +/************************/ +/* Used for storing a sequence of words. Usually malloced. */ +struct wordlist { + struct wordlist *next; + char word[1]; +}; + + +/***********************************/ +/*** LOCAL FUNCTION DECLARATIONS ***/ +/***********************************/ +extern char *crypt (const char *, const char *); + +/* Prototypes for procedures local to this file. */ + +static void network_phase (int); +static void check_idle (void *); +static void connect_time_expired (void *); +#if 0 +static int login (char *, char *, char **, int *); +#endif +static void logout (void); +static int null_login (int); +static int get_pap_passwd (int, char *, char *); +static int have_pap_secret (void); +static int have_chap_secret (char *, char *, u32_t); +static int ip_addr_check (u32_t, struct wordlist *); +#if 0 /* PAP_SUPPORT || CHAP_SUPPORT */ +static void set_allowed_addrs(int unit, struct wordlist *addrs); +static void free_wordlist (struct wordlist *); +#endif /* 0 */ /* PAP_SUPPORT || CHAP_SUPPORT */ +#if CBCP_SUPPORT +static void callback_phase (int); +#endif /* CBCP_SUPPORT */ + + +/******************************/ +/*** PUBLIC DATA STRUCTURES ***/ +/******************************/ + + +/*****************************/ +/*** LOCAL DATA STRUCTURES ***/ +/*****************************/ +#if PAP_SUPPORT || CHAP_SUPPORT +/* The name by which the peer authenticated itself to us. */ +static char peer_authname[MAXNAMELEN]; +#endif /* PAP_SUPPORT || CHAP_SUPPORT */ + +/* Records which authentication operations haven't completed yet. */ +static int auth_pending[NUM_PPP]; + +/* Set if we have successfully called login() */ +static int logged_in; + +/* Set if we have run the /etc/ppp/auth-up script. */ +static int did_authup; + +/* List of addresses which the peer may use. */ +static struct wordlist *addresses[NUM_PPP]; + +/* Number of network protocols which we have opened. */ +static int num_np_open; + +/* Number of network protocols which have come up. */ +static int num_np_up; + +#if PAP_SUPPORT || CHAP_SUPPORT +/* Set if we got the contents of passwd[] from the pap-secrets file. */ +static int passwd_from_file; +#endif /* PAP_SUPPORT || CHAP_SUPPORT */ + + +/***********************************/ +/*** PUBLIC FUNCTION DEFINITIONS ***/ +/***********************************/ +/* + * An Open on LCP has requested a change from Dead to Establish phase. + * Do what's necessary to bring the physical layer up. + */ +void +link_required(int unit) +{ + LWIP_UNUSED_ARG(unit); + + AUTHDEBUG((LOG_INFO, "link_required: %d\n", unit)); +} + +/* + * LCP has terminated the link; go to the Dead phase and take the + * physical layer down. + */ +void +link_terminated(int unit) +{ + AUTHDEBUG((LOG_INFO, "link_terminated: %d\n", unit)); + if (lcp_phase[unit] == PHASE_DEAD) { + return; + } + if (logged_in) { + logout(); + } + lcp_phase[unit] = PHASE_DEAD; + AUTHDEBUG((LOG_NOTICE, "Connection terminated.\n")); + pppLinkTerminated(unit); +} + +/* + * LCP has gone down; it will either die or try to re-establish. + */ +void +link_down(int unit) +{ + int i; + struct protent *protp; + + AUTHDEBUG((LOG_INFO, "link_down: %d\n", unit)); + if (did_authup) { + /* XXX Do link down processing. */ + did_authup = 0; + } + for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) { + if (!protp->enabled_flag) { + continue; + } + if (protp->protocol != PPP_LCP && protp->lowerdown != NULL) { + (*protp->lowerdown)(unit); + } + if (protp->protocol < 0xC000 && protp->close != NULL) { + (*protp->close)(unit, "LCP down"); + } + } + num_np_open = 0; + num_np_up = 0; + if (lcp_phase[unit] != PHASE_DEAD) { + lcp_phase[unit] = PHASE_TERMINATE; + } + pppLinkDown(unit); +} + +/* + * The link is established. + * Proceed to the Dead, Authenticate or Network phase as appropriate. + */ +void +link_established(int unit) +{ + int auth; + int i; + struct protent *protp; + lcp_options *wo = &lcp_wantoptions[unit]; + lcp_options *go = &lcp_gotoptions[unit]; +#if PAP_SUPPORT || CHAP_SUPPORT + lcp_options *ho = &lcp_hisoptions[unit]; +#endif /* PAP_SUPPORT || CHAP_SUPPORT */ + + AUTHDEBUG((LOG_INFO, "link_established: %d\n", unit)); + /* + * Tell higher-level protocols that LCP is up. + */ + for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) { + if (protp->protocol != PPP_LCP && protp->enabled_flag && protp->lowerup != NULL) { + (*protp->lowerup)(unit); + } + } + if (ppp_settings.auth_required && !(go->neg_chap || go->neg_upap)) { + /* + * We wanted the peer to authenticate itself, and it refused: + * treat it as though it authenticated with PAP using a username + * of "" and a password of "". If that's not OK, boot it out. + */ + if (!wo->neg_upap || !null_login(unit)) { + AUTHDEBUG((LOG_WARNING, "peer refused to authenticate\n")); + lcp_close(unit, "peer refused to authenticate"); + return; + } + } + + lcp_phase[unit] = PHASE_AUTHENTICATE; + auth = 0; +#if CHAP_SUPPORT + if (go->neg_chap) { + ChapAuthPeer(unit, ppp_settings.our_name, go->chap_mdtype); + auth |= CHAP_PEER; + } +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT && CHAP_SUPPORT + else +#endif /* PAP_SUPPORT && CHAP_SUPPORT */ +#if PAP_SUPPORT + if (go->neg_upap) { + upap_authpeer(unit); + auth |= PAP_PEER; + } +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + if (ho->neg_chap) { + ChapAuthWithPeer(unit, ppp_settings.user, ho->chap_mdtype); + auth |= CHAP_WITHPEER; + } +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT && CHAP_SUPPORT + else +#endif /* PAP_SUPPORT && CHAP_SUPPORT */ +#if PAP_SUPPORT + if (ho->neg_upap) { + if (ppp_settings.passwd[0] == 0) { + passwd_from_file = 1; + if (!get_pap_passwd(unit, ppp_settings.user, ppp_settings.passwd)) { + AUTHDEBUG((LOG_ERR, "No secret found for PAP login\n")); + } + } + upap_authwithpeer(unit, ppp_settings.user, ppp_settings.passwd); + auth |= PAP_WITHPEER; + } +#endif /* PAP_SUPPORT */ + auth_pending[unit] = auth; + + if (!auth) { + network_phase(unit); + } +} + +/* + * The peer has failed to authenticate himself using `protocol'. + */ +void +auth_peer_fail(int unit, u16_t protocol) +{ + LWIP_UNUSED_ARG(protocol); + + AUTHDEBUG((LOG_INFO, "auth_peer_fail: %d proto=%X\n", unit, protocol)); + /* + * Authentication failure: take the link down + */ + lcp_close(unit, "Authentication failed"); +} + + +#if PAP_SUPPORT || CHAP_SUPPORT +/* + * The peer has been successfully authenticated using `protocol'. + */ +void +auth_peer_success(int unit, u16_t protocol, char *name, int namelen) +{ + int pbit; + + AUTHDEBUG((LOG_INFO, "auth_peer_success: %d proto=%X\n", unit, protocol)); + switch (protocol) { + case PPP_CHAP: + pbit = CHAP_PEER; + break; + case PPP_PAP: + pbit = PAP_PEER; + break; + default: + AUTHDEBUG((LOG_WARNING, "auth_peer_success: unknown protocol %x\n", protocol)); + return; + } + + /* + * Save the authenticated name of the peer for later. + */ + if (namelen > sizeof(peer_authname) - 1) { + namelen = sizeof(peer_authname) - 1; + } + BCOPY(name, peer_authname, namelen); + peer_authname[namelen] = 0; + + /* + * If there is no more authentication still to be done, + * proceed to the network (or callback) phase. + */ + if ((auth_pending[unit] &= ~pbit) == 0) { + network_phase(unit); + } +} + +/* + * We have failed to authenticate ourselves to the peer using `protocol'. + */ +void +auth_withpeer_fail(int unit, u16_t protocol) +{ + int errCode = PPPERR_AUTHFAIL; + + LWIP_UNUSED_ARG(protocol); + + AUTHDEBUG((LOG_INFO, "auth_withpeer_fail: %d proto=%X\n", unit, protocol)); + if (passwd_from_file) { + BZERO(ppp_settings.passwd, MAXSECRETLEN); + } + /* + * XXX Warning: the unit number indicates the interface which is + * not necessarily the PPP connection. It works here as long + * as we are only supporting PPP interfaces. + */ + pppIOCtl(unit, PPPCTLS_ERRCODE, &errCode); + + /* + * We've failed to authenticate ourselves to our peer. + * He'll probably take the link down, and there's not much + * we can do except wait for that. + */ +} + +/* + * We have successfully authenticated ourselves with the peer using `protocol'. + */ +void +auth_withpeer_success(int unit, u16_t protocol) +{ + int pbit; + + AUTHDEBUG((LOG_INFO, "auth_withpeer_success: %d proto=%X\n", unit, protocol)); + switch (protocol) { + case PPP_CHAP: + pbit = CHAP_WITHPEER; + break; + case PPP_PAP: + if (passwd_from_file) { + BZERO(ppp_settings.passwd, MAXSECRETLEN); + } + pbit = PAP_WITHPEER; + break; + default: + AUTHDEBUG((LOG_WARNING, "auth_peer_success: unknown protocol %x\n", protocol)); + pbit = 0; + } + + /* + * If there is no more authentication still being done, + * proceed to the network (or callback) phase. + */ + if ((auth_pending[unit] &= ~pbit) == 0) { + network_phase(unit); + } +} +#endif /* PAP_SUPPORT || CHAP_SUPPORT */ + + +/* + * np_up - a network protocol has come up. + */ +void +np_up(int unit, u16_t proto) +{ + LWIP_UNUSED_ARG(unit); + LWIP_UNUSED_ARG(proto); + + AUTHDEBUG((LOG_INFO, "np_up: %d proto=%X\n", unit, proto)); + if (num_np_up == 0) { + AUTHDEBUG((LOG_INFO, "np_up: maxconnect=%d idle_time_limit=%d\n",ppp_settings.maxconnect,ppp_settings.idle_time_limit)); + /* + * At this point we consider that the link has come up successfully. + */ + if (ppp_settings.idle_time_limit > 0) { + TIMEOUT(check_idle, NULL, ppp_settings.idle_time_limit); + } + + /* + * Set a timeout to close the connection once the maximum + * connect time has expired. + */ + if (ppp_settings.maxconnect > 0) { + TIMEOUT(connect_time_expired, 0, ppp_settings.maxconnect); + } + } + ++num_np_up; +} + +/* + * np_down - a network protocol has gone down. + */ +void +np_down(int unit, u16_t proto) +{ + LWIP_UNUSED_ARG(unit); + LWIP_UNUSED_ARG(proto); + + AUTHDEBUG((LOG_INFO, "np_down: %d proto=%X\n", unit, proto)); + if (--num_np_up == 0 && ppp_settings.idle_time_limit > 0) { + UNTIMEOUT(check_idle, NULL); + } +} + +/* + * np_finished - a network protocol has finished using the link. + */ +void +np_finished(int unit, u16_t proto) +{ + LWIP_UNUSED_ARG(unit); + LWIP_UNUSED_ARG(proto); + + AUTHDEBUG((LOG_INFO, "np_finished: %d proto=%X\n", unit, proto)); + if (--num_np_open <= 0) { + /* no further use for the link: shut up shop. */ + lcp_close(0, "No network protocols running"); + } +} + +/* + * auth_reset - called when LCP is starting negotiations to recheck + * authentication options, i.e. whether we have appropriate secrets + * to use for authenticating ourselves and/or the peer. + */ +void +auth_reset(int unit) +{ + lcp_options *go = &lcp_gotoptions[unit]; + lcp_options *ao = &lcp_allowoptions[0]; + ipcp_options *ipwo = &ipcp_wantoptions[0]; + u32_t remote; + + AUTHDEBUG((LOG_INFO, "auth_reset: %d\n", unit)); + ao->neg_upap = !ppp_settings.refuse_pap && (ppp_settings.passwd[0] != 0 || get_pap_passwd(unit, NULL, NULL)); + ao->neg_chap = !ppp_settings.refuse_chap && ppp_settings.passwd[0] != 0 /*have_chap_secret(ppp_settings.user, ppp_settings.remote_name, (u32_t)0)*/; + + if (go->neg_upap && !have_pap_secret()) { + go->neg_upap = 0; + } + if (go->neg_chap) { + remote = ipwo->accept_remote? 0: ipwo->hisaddr; + if (!have_chap_secret(ppp_settings.remote_name, ppp_settings.our_name, remote)) { + go->neg_chap = 0; + } + } +} + +#if PAP_SUPPORT +/* + * check_passwd - Check the user name and passwd against the PAP secrets + * file. If requested, also check against the system password database, + * and login the user if OK. + * + * returns: + * UPAP_AUTHNAK: Authentication failed. + * UPAP_AUTHACK: Authentication succeeded. + * In either case, msg points to an appropriate message. + */ +int +check_passwd( int unit, char *auser, int userlen, char *apasswd, int passwdlen, char **msg, int *msglen) +{ +#if 1 + LWIP_UNUSED_ARG(unit); + LWIP_UNUSED_ARG(auser); + LWIP_UNUSED_ARG(userlen); + LWIP_UNUSED_ARG(apasswd); + LWIP_UNUSED_ARG(passwdlen); + LWIP_UNUSED_ARG(msglen); + *msg = (char *) 0; + return UPAP_AUTHACK; /* XXX Assume all entries OK. */ +#else + int ret = 0; + struct wordlist *addrs = NULL; + char passwd[256], user[256]; + char secret[MAXWORDLEN]; + static u_short attempts = 0; + + /* + * Make copies of apasswd and auser, then null-terminate them. + */ + BCOPY(apasswd, passwd, passwdlen); + passwd[passwdlen] = '\0'; + BCOPY(auser, user, userlen); + user[userlen] = '\0'; + *msg = (char *) 0; + + /* XXX Validate user name and password. */ + ret = UPAP_AUTHACK; /* XXX Assume all entries OK. */ + + if (ret == UPAP_AUTHNAK) { + if (*msg == (char *) 0) { + *msg = "Login incorrect"; + } + *msglen = strlen(*msg); + /* + * Frustrate passwd stealer programs. + * Allow 10 tries, but start backing off after 3 (stolen from login). + * On 10'th, drop the connection. + */ + if (attempts++ >= 10) { + AUTHDEBUG((LOG_WARNING, "%d LOGIN FAILURES BY %s\n", attempts, user)); + /*ppp_panic("Excess Bad Logins");*/ + } + if (attempts > 3) { + sys_msleep((attempts - 3) * 5); + } + if (addrs != NULL) { + free_wordlist(addrs); + } + } else { + attempts = 0; /* Reset count */ + if (*msg == (char *) 0) { + *msg = "Login ok"; + } + *msglen = strlen(*msg); + set_allowed_addrs(unit, addrs); + } + + BZERO(passwd, sizeof(passwd)); + BZERO(secret, sizeof(secret)); + + return ret; +#endif +} +#endif /* PAP_SUPPORT */ + + +/* + * auth_ip_addr - check whether the peer is authorized to use + * a given IP address. Returns 1 if authorized, 0 otherwise. + */ +int +auth_ip_addr(int unit, u32_t addr) +{ + return ip_addr_check(addr, addresses[unit]); +} + +/* + * bad_ip_adrs - return 1 if the IP address is one we don't want + * to use, such as an address in the loopback net or a multicast address. + * addr is in network byte order. + */ +int +bad_ip_adrs(u32_t addr) +{ + addr = ntohl(addr); + return (addr >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET + || IN_MULTICAST(addr) || IN_BADCLASS(addr); +} + + +#if CHAP_SUPPORT +/* + * get_secret - open the CHAP secret file and return the secret + * for authenticating the given client on the given server. + * (We could be either client or server). + */ +int get_secret( int unit, char *client, char *server, char *secret, int *secret_len, int save_addrs) +{ +#if 1 + int len; + struct wordlist *addrs; + + LWIP_UNUSED_ARG(unit); + LWIP_UNUSED_ARG(server); + LWIP_UNUSED_ARG(save_addrs); + + addrs = NULL; + + if(!client || !client[0] || strcmp(client, ppp_settings.user)) { + return 0; + } + + len = strlen(ppp_settings.passwd); + if (len > MAXSECRETLEN) { + AUTHDEBUG((LOG_ERR, "Secret for %s on %s is too long\n", client, server)); + len = MAXSECRETLEN; + } + + BCOPY(ppp_settings.passwd, secret, len); + *secret_len = len; + + return 1; +#else + int ret = 0, len; + struct wordlist *addrs; + char secbuf[MAXWORDLEN]; + + addrs = NULL; + secbuf[0] = 0; + + /* XXX Find secret. */ + if (ret < 0) { + return 0; + } + + if (save_addrs) { + set_allowed_addrs(unit, addrs); + } + + len = strlen(secbuf); + if (len > MAXSECRETLEN) { + AUTHDEBUG((LOG_ERR, "Secret for %s on %s is too long\n", client, server)); + len = MAXSECRETLEN; + } + + BCOPY(secbuf, secret, len); + BZERO(secbuf, sizeof(secbuf)); + *secret_len = len; + + return 1; +#endif +} +#endif /* CHAP_SUPPORT */ + + +#if 0 /* UNUSED */ +/* + * auth_check_options - called to check authentication options. + */ +void +auth_check_options(void) +{ + lcp_options *wo = &lcp_wantoptions[0]; + int can_auth; + ipcp_options *ipwo = &ipcp_wantoptions[0]; + u32_t remote; + + /* Default our_name to hostname, and user to our_name */ + if (ppp_settings.our_name[0] == 0 || ppp_settings.usehostname) { + strcpy(ppp_settings.our_name, ppp_settings.hostname); + } + + if (ppp_settings.user[0] == 0) { + strcpy(ppp_settings.user, ppp_settings.our_name); + } + + /* If authentication is required, ask peer for CHAP or PAP. */ + if (ppp_settings.auth_required && !wo->neg_chap && !wo->neg_upap) { + wo->neg_chap = 1; + wo->neg_upap = 1; + } + + /* + * Check whether we have appropriate secrets to use + * to authenticate the peer. + */ + can_auth = wo->neg_upap && have_pap_secret(); + if (!can_auth && wo->neg_chap) { + remote = ipwo->accept_remote? 0: ipwo->hisaddr; + can_auth = have_chap_secret(ppp_settings.remote_name, ppp_settings.our_name, remote); + } + + if (ppp_settings.auth_required && !can_auth) { + ppp_panic("No auth secret"); + } +} +#endif + + +/**********************************/ +/*** LOCAL FUNCTION DEFINITIONS ***/ +/**********************************/ +/* + * Proceed to the network phase. + */ +static void +network_phase(int unit) +{ + int i; + struct protent *protp; + lcp_options *go = &lcp_gotoptions[unit]; + + /* + * If the peer had to authenticate, run the auth-up script now. + */ + if ((go->neg_chap || go->neg_upap) && !did_authup) { + /* XXX Do setup for peer authentication. */ + did_authup = 1; + } + +#if CBCP_SUPPORT + /* + * If we negotiated callback, do it now. + */ + if (go->neg_cbcp) { + lcp_phase[unit] = PHASE_CALLBACK; + (*cbcp_protent.open)(unit); + return; + } +#endif /* CBCP_SUPPORT */ + + lcp_phase[unit] = PHASE_NETWORK; + for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) { + if (protp->protocol < 0xC000 && protp->enabled_flag && protp->open != NULL) { + (*protp->open)(unit); + if (protp->protocol != PPP_CCP) { + ++num_np_open; + } + } + } + + if (num_np_open == 0) { + /* nothing to do */ + lcp_close(0, "No network protocols running"); + } +} + +/* + * check_idle - check whether the link has been idle for long + * enough that we can shut it down. + */ +static void +check_idle(void *arg) +{ + struct ppp_idle idle; + u_short itime; + + LWIP_UNUSED_ARG(arg); + if (!get_idle_time(0, &idle)) { + return; + } + itime = LWIP_MIN(idle.xmit_idle, idle.recv_idle); + if (itime >= ppp_settings.idle_time_limit) { + /* link is idle: shut it down. */ + AUTHDEBUG((LOG_INFO, "Terminating connection due to lack of activity.\n")); + lcp_close(0, "Link inactive"); + } else { + TIMEOUT(check_idle, NULL, ppp_settings.idle_time_limit - itime); + } +} + +/* + * connect_time_expired - log a message and close the connection. + */ +static void +connect_time_expired(void *arg) +{ + LWIP_UNUSED_ARG(arg); + + AUTHDEBUG((LOG_INFO, "Connect time expired\n")); + lcp_close(0, "Connect time expired"); /* Close connection */ +} + +#if 0 +/* + * login - Check the user name and password against the system + * password database, and login the user if OK. + * + * returns: + * UPAP_AUTHNAK: Login failed. + * UPAP_AUTHACK: Login succeeded. + * In either case, msg points to an appropriate message. + */ +static int +login(char *user, char *passwd, char **msg, int *msglen) +{ + /* XXX Fail until we decide that we want to support logins. */ + return (UPAP_AUTHNAK); +} +#endif + +/* + * logout - Logout the user. + */ +static void +logout(void) +{ + logged_in = 0; +} + +/* + * null_login - Check if a username of "" and a password of "" are + * acceptable, and iff so, set the list of acceptable IP addresses + * and return 1. + */ +static int +null_login(int unit) +{ + LWIP_UNUSED_ARG(unit); + /* XXX Fail until we decide that we want to support logins. */ + return 0; +} + +/* + * get_pap_passwd - get a password for authenticating ourselves with + * our peer using PAP. Returns 1 on success, 0 if no suitable password + * could be found. + */ +static int +get_pap_passwd(int unit, char *user, char *passwd) +{ + LWIP_UNUSED_ARG(unit); +/* normally we would reject PAP if no password is provided, + but this causes problems with some providers (like CHT in Taiwan) + who incorrectly request PAP and expect a bogus/empty password, so + always provide a default user/passwd of "none"/"none" +*/ + if(user) { + strcpy(user, "none"); + } + if(passwd) { + strcpy(passwd, "none"); + } + return 1; +} + +/* + * have_pap_secret - check whether we have a PAP file with any + * secrets that we could possibly use for authenticating the peer. + */ +static int +have_pap_secret(void) +{ + /* XXX Fail until we set up our passwords. */ + return 0; +} + +/* + * have_chap_secret - check whether we have a CHAP file with a + * secret that we could possibly use for authenticating `client' + * on `server'. Either can be the null string, meaning we don't + * know the identity yet. + */ +static int +have_chap_secret(char *client, char *server, u32_t remote) +{ + LWIP_UNUSED_ARG(client); + LWIP_UNUSED_ARG(server); + LWIP_UNUSED_ARG(remote); + /* XXX Fail until we set up our passwords. */ + return 0; +} + +#if 0 /* PAP_SUPPORT || CHAP_SUPPORT */ +/* + * set_allowed_addrs() - set the list of allowed addresses. + */ +static void +set_allowed_addrs(int unit, struct wordlist *addrs) +{ + if (addresses[unit] != NULL) { + free_wordlist(addresses[unit]); + } + addresses[unit] = addrs; + +#if 0 + /* + * If there's only one authorized address we might as well + * ask our peer for that one right away + */ + if (addrs != NULL && addrs->next == NULL) { + char *p = addrs->word; + struct ipcp_options *wo = &ipcp_wantoptions[unit]; + u32_t a; + struct hostent *hp; + + if (wo->hisaddr == 0 && *p != '!' && *p != '-' && strchr(p, '/') == NULL) { + hp = gethostbyname(p); + if (hp != NULL && hp->h_addrtype == AF_INET) { + a = *(u32_t *)hp->h_addr; + } else { + a = inet_addr(p); + } + if (a != (u32_t) -1) { + wo->hisaddr = a; + } + } + } +#endif +} +#endif /* 0 */ /* PAP_SUPPORT || CHAP_SUPPORT */ + +static int +ip_addr_check(u32_t addr, struct wordlist *addrs) +{ + /* don't allow loopback or multicast address */ + if (bad_ip_adrs(addr)) { + return 0; + } + + if (addrs == NULL) { + return !ppp_settings.auth_required; /* no addresses authorized */ + } + + /* XXX All other addresses allowed. */ + return 1; +} + +#if 0 /* PAP_SUPPORT || CHAP_SUPPORT */ +/* + * free_wordlist - release memory allocated for a wordlist. + */ +static void +free_wordlist(struct wordlist *wp) +{ + struct wordlist *next; + + while (wp != NULL) { + next = wp->next; + free(wp); + wp = next; + } +} +#endif /* 0 */ /* PAP_SUPPORT || CHAP_SUPPORT */ + +#endif /* PPP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/auth.h b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/auth.h new file mode 100644 index 0000000..86ff049 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/auth.h @@ -0,0 +1,111 @@ +/***************************************************************************** +* auth.h - PPP Authentication and phase control header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1998 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-12-04 Guy Lancaster , Global Election Systems Inc. +* Original derived from BSD pppd.h. +*****************************************************************************/ +/* + * pppd.h - PPP daemon global declarations. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#ifndef AUTH_H +#define AUTH_H + +/*********************** +*** PUBLIC FUNCTIONS *** +***********************/ + +/* we are starting to use the link */ +void link_required (int); + +/* we are finished with the link */ +void link_terminated (int); + +/* the LCP layer has left the Opened state */ +void link_down (int); + +/* the link is up; authenticate now */ +void link_established (int); + +/* a network protocol has come up */ +void np_up (int, u16_t); + +/* a network protocol has gone down */ +void np_down (int, u16_t); + +/* a network protocol no longer needs link */ +void np_finished (int, u16_t); + +/* peer failed to authenticate itself */ +void auth_peer_fail (int, u16_t); + +/* peer successfully authenticated itself */ +void auth_peer_success (int, u16_t, char *, int); + +/* we failed to authenticate ourselves */ +void auth_withpeer_fail (int, u16_t); + +/* we successfully authenticated ourselves */ +void auth_withpeer_success (int, u16_t); + +/* check authentication options supplied */ +void auth_check_options (void); + +/* check what secrets we have */ +void auth_reset (int); + +/* Check peer-supplied username/password */ +int check_passwd (int, char *, int, char *, int, char **, int *); + +/* get "secret" for chap */ +int get_secret (int, char *, char *, char *, int *, int); + +/* check if IP address is authorized */ +int auth_ip_addr (int, u32_t); + +/* check if IP address is unreasonable */ +int bad_ip_adrs (u32_t); + +#endif /* AUTH_H */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/chap.c b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/chap.c new file mode 100644 index 0000000..b3ea6b2 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/chap.c @@ -0,0 +1,903 @@ +/*** WARNING - THIS HAS NEVER BEEN FINISHED ***/ +/***************************************************************************** +* chap.c - Network Challenge Handshake Authentication Protocol program file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 by Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-12-04 Guy Lancaster , Global Election Systems Inc. +* Original based on BSD chap.c. +*****************************************************************************/ +/* + * chap.c - Challenge Handshake Authentication Protocol. + * + * Copyright (c) 1993 The Australian National University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the Australian National University. The name of the University + * may not be used to endorse or promote products derived from this + * software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Copyright (c) 1991 Gregory M. Christy. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Gregory M. Christy. The name of the author may not be used to + * endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "lwip/opt.h" + +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#if CHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "ppp.h" +#include "pppdebug.h" + +#include "magic.h" +#include "randm.h" +#include "auth.h" +#include "md5.h" +#include "chap.h" +#include "chpms.h" + +#include + +/*************************/ +/*** LOCAL DEFINITIONS ***/ +/*************************/ + + +/************************/ +/*** LOCAL DATA TYPES ***/ +/************************/ + + +/***********************************/ +/*** LOCAL FUNCTION DECLARATIONS ***/ +/***********************************/ +/* + * Protocol entry points. + */ +static void ChapInit (int); +static void ChapLowerUp (int); +static void ChapLowerDown (int); +static void ChapInput (int, u_char *, int); +static void ChapProtocolReject (int); +#if 0 +static int ChapPrintPkt (u_char *, int, void (*) (void *, char *, ...), void *); +#endif + +static void ChapChallengeTimeout (void *); +static void ChapResponseTimeout (void *); +static void ChapReceiveChallenge (chap_state *, u_char *, int, int); +static void ChapRechallenge (void *); +static void ChapReceiveResponse (chap_state *, u_char *, int, int); +static void ChapReceiveSuccess(chap_state *cstate, u_char *inp, u_char id, int len); +static void ChapReceiveFailure(chap_state *cstate, u_char *inp, u_char id, int len); +static void ChapSendStatus (chap_state *, int); +static void ChapSendChallenge (chap_state *); +static void ChapSendResponse (chap_state *); +static void ChapGenChallenge (chap_state *); + + +/******************************/ +/*** PUBLIC DATA STRUCTURES ***/ +/******************************/ +chap_state chap[NUM_PPP]; /* CHAP state; one for each unit */ + +struct protent chap_protent = { + PPP_CHAP, + ChapInit, + ChapInput, + ChapProtocolReject, + ChapLowerUp, + ChapLowerDown, + NULL, + NULL, +#if 0 + ChapPrintPkt, + NULL, +#endif + 1, + "CHAP", +#if 0 + NULL, + NULL, + NULL +#endif +}; + + +/***********************************/ +/*** PUBLIC FUNCTION DEFINITIONS ***/ +/***********************************/ +/* + * ChapAuthWithPeer - Authenticate us with our peer (start client). + * + */ +void +ChapAuthWithPeer(int unit, char *our_name, int digest) +{ + chap_state *cstate = &chap[unit]; + + cstate->resp_name = our_name; + cstate->resp_type = digest; + + if (cstate->clientstate == CHAPCS_INITIAL || + cstate->clientstate == CHAPCS_PENDING) { + /* lower layer isn't up - wait until later */ + cstate->clientstate = CHAPCS_PENDING; + return; + } + + /* + * We get here as a result of LCP coming up. + * So even if CHAP was open before, we will + * have to re-authenticate ourselves. + */ + cstate->clientstate = CHAPCS_LISTEN; +} + + +/* + * ChapAuthPeer - Authenticate our peer (start server). + */ +void +ChapAuthPeer(int unit, char *our_name, int digest) +{ + chap_state *cstate = &chap[unit]; + + cstate->chal_name = our_name; + cstate->chal_type = digest; + + if (cstate->serverstate == CHAPSS_INITIAL || + cstate->serverstate == CHAPSS_PENDING) { + /* lower layer isn't up - wait until later */ + cstate->serverstate = CHAPSS_PENDING; + return; + } + + ChapGenChallenge(cstate); + ChapSendChallenge(cstate); /* crank it up dude! */ + cstate->serverstate = CHAPSS_INITIAL_CHAL; +} + + +/**********************************/ +/*** LOCAL FUNCTION DEFINITIONS ***/ +/**********************************/ +/* + * ChapInit - Initialize a CHAP unit. + */ +static void +ChapInit(int unit) +{ + chap_state *cstate = &chap[unit]; + + BZERO(cstate, sizeof(*cstate)); + cstate->unit = unit; + cstate->clientstate = CHAPCS_INITIAL; + cstate->serverstate = CHAPSS_INITIAL; + cstate->timeouttime = CHAP_DEFTIMEOUT; + cstate->max_transmits = CHAP_DEFTRANSMITS; + /* random number generator is initialized in magic_init */ +} + + +/* + * ChapChallengeTimeout - Timeout expired on sending challenge. + */ +static void +ChapChallengeTimeout(void *arg) +{ + chap_state *cstate = (chap_state *) arg; + + /* if we aren't sending challenges, don't worry. then again we */ + /* probably shouldn't be here either */ + if (cstate->serverstate != CHAPSS_INITIAL_CHAL && + cstate->serverstate != CHAPSS_RECHALLENGE) { + return; + } + + if (cstate->chal_transmits >= cstate->max_transmits) { + /* give up on peer */ + CHAPDEBUG((LOG_ERR, "Peer failed to respond to CHAP challenge\n")); + cstate->serverstate = CHAPSS_BADAUTH; + auth_peer_fail(cstate->unit, PPP_CHAP); + return; + } + + ChapSendChallenge(cstate); /* Re-send challenge */ +} + + +/* + * ChapResponseTimeout - Timeout expired on sending response. + */ +static void +ChapResponseTimeout(void *arg) +{ + chap_state *cstate = (chap_state *) arg; + + /* if we aren't sending a response, don't worry. */ + if (cstate->clientstate != CHAPCS_RESPONSE) { + return; + } + + ChapSendResponse(cstate); /* re-send response */ +} + + +/* + * ChapRechallenge - Time to challenge the peer again. + */ +static void +ChapRechallenge(void *arg) +{ + chap_state *cstate = (chap_state *) arg; + + /* if we aren't sending a response, don't worry. */ + if (cstate->serverstate != CHAPSS_OPEN) { + return; + } + + ChapGenChallenge(cstate); + ChapSendChallenge(cstate); + cstate->serverstate = CHAPSS_RECHALLENGE; +} + + +/* + * ChapLowerUp - The lower layer is up. + * + * Start up if we have pending requests. + */ +static void +ChapLowerUp(int unit) +{ + chap_state *cstate = &chap[unit]; + + if (cstate->clientstate == CHAPCS_INITIAL) { + cstate->clientstate = CHAPCS_CLOSED; + } else if (cstate->clientstate == CHAPCS_PENDING) { + cstate->clientstate = CHAPCS_LISTEN; + } + + if (cstate->serverstate == CHAPSS_INITIAL) { + cstate->serverstate = CHAPSS_CLOSED; + } else if (cstate->serverstate == CHAPSS_PENDING) { + ChapGenChallenge(cstate); + ChapSendChallenge(cstate); + cstate->serverstate = CHAPSS_INITIAL_CHAL; + } +} + + +/* + * ChapLowerDown - The lower layer is down. + * + * Cancel all timeouts. + */ +static void +ChapLowerDown(int unit) +{ + chap_state *cstate = &chap[unit]; + + /* Timeout(s) pending? Cancel if so. */ + if (cstate->serverstate == CHAPSS_INITIAL_CHAL || + cstate->serverstate == CHAPSS_RECHALLENGE) { + UNTIMEOUT(ChapChallengeTimeout, cstate); + } else if (cstate->serverstate == CHAPSS_OPEN + && cstate->chal_interval != 0) { + UNTIMEOUT(ChapRechallenge, cstate); + } + if (cstate->clientstate == CHAPCS_RESPONSE) { + UNTIMEOUT(ChapResponseTimeout, cstate); + } + cstate->clientstate = CHAPCS_INITIAL; + cstate->serverstate = CHAPSS_INITIAL; +} + + +/* + * ChapProtocolReject - Peer doesn't grok CHAP. + */ +static void +ChapProtocolReject(int unit) +{ + chap_state *cstate = &chap[unit]; + + if (cstate->serverstate != CHAPSS_INITIAL && + cstate->serverstate != CHAPSS_CLOSED) { + auth_peer_fail(unit, PPP_CHAP); + } + if (cstate->clientstate != CHAPCS_INITIAL && + cstate->clientstate != CHAPCS_CLOSED) { + auth_withpeer_fail(unit, PPP_CHAP); + } + ChapLowerDown(unit); /* shutdown chap */ +} + + +/* + * ChapInput - Input CHAP packet. + */ +static void +ChapInput(int unit, u_char *inpacket, int packet_len) +{ + chap_state *cstate = &chap[unit]; + u_char *inp; + u_char code, id; + int len; + + /* + * Parse header (code, id and length). + * If packet too short, drop it. + */ + inp = inpacket; + if (packet_len < CHAP_HEADERLEN) { + CHAPDEBUG((LOG_INFO, "ChapInput: rcvd short header.\n")); + return; + } + GETCHAR(code, inp); + GETCHAR(id, inp); + GETSHORT(len, inp); + if (len < CHAP_HEADERLEN) { + CHAPDEBUG((LOG_INFO, "ChapInput: rcvd illegal length.\n")); + return; + } + if (len > packet_len) { + CHAPDEBUG((LOG_INFO, "ChapInput: rcvd short packet.\n")); + return; + } + len -= CHAP_HEADERLEN; + + /* + * Action depends on code (as in fact it usually does :-). + */ + switch (code) { + case CHAP_CHALLENGE: + ChapReceiveChallenge(cstate, inp, id, len); + break; + + case CHAP_RESPONSE: + ChapReceiveResponse(cstate, inp, id, len); + break; + + case CHAP_FAILURE: + ChapReceiveFailure(cstate, inp, id, len); + break; + + case CHAP_SUCCESS: + ChapReceiveSuccess(cstate, inp, id, len); + break; + + default: /* Need code reject? */ + CHAPDEBUG((LOG_WARNING, "Unknown CHAP code (%d) received.\n", code)); + break; + } +} + + +/* + * ChapReceiveChallenge - Receive Challenge and send Response. + */ +static void +ChapReceiveChallenge(chap_state *cstate, u_char *inp, int id, int len) +{ + int rchallenge_len; + u_char *rchallenge; + int secret_len; + char secret[MAXSECRETLEN]; + char rhostname[256]; + MD5_CTX mdContext; + u_char hash[MD5_SIGNATURE_SIZE]; + + CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: Rcvd id %d.\n", id)); + if (cstate->clientstate == CHAPCS_CLOSED || + cstate->clientstate == CHAPCS_PENDING) { + CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: in state %d\n", + cstate->clientstate)); + return; + } + + if (len < 2) { + CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: rcvd short packet.\n")); + return; + } + + GETCHAR(rchallenge_len, inp); + len -= sizeof (u_char) + rchallenge_len; /* now name field length */ + if (len < 0) { + CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: rcvd short packet.\n")); + return; + } + rchallenge = inp; + INCPTR(rchallenge_len, inp); + + if (len >= sizeof(rhostname)) { + len = sizeof(rhostname) - 1; + } + BCOPY(inp, rhostname, len); + rhostname[len] = '\000'; + + CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: received name field '%s'\n", rhostname)); + + /* Microsoft doesn't send their name back in the PPP packet */ + if (ppp_settings.remote_name[0] != 0 && (ppp_settings.explicit_remote || rhostname[0] == 0)) { + strncpy(rhostname, ppp_settings.remote_name, sizeof(rhostname)); + rhostname[sizeof(rhostname) - 1] = 0; + CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: using '%s' as remote name\n", rhostname)); + } + + /* get secret for authenticating ourselves with the specified host */ + if (!get_secret(cstate->unit, cstate->resp_name, rhostname, secret, &secret_len, 0)) { + secret_len = 0; /* assume null secret if can't find one */ + CHAPDEBUG((LOG_WARNING, "No CHAP secret found for authenticating us to %s\n", rhostname)); + } + + /* cancel response send timeout if necessary */ + if (cstate->clientstate == CHAPCS_RESPONSE) { + UNTIMEOUT(ChapResponseTimeout, cstate); + } + + cstate->resp_id = id; + cstate->resp_transmits = 0; + + /* generate MD based on negotiated type */ + switch (cstate->resp_type) { + + case CHAP_DIGEST_MD5: + MD5Init(&mdContext); + MD5Update(&mdContext, &cstate->resp_id, 1); + MD5Update(&mdContext, (u_char*)secret, secret_len); + MD5Update(&mdContext, rchallenge, rchallenge_len); + MD5Final(hash, &mdContext); + BCOPY(hash, cstate->response, MD5_SIGNATURE_SIZE); + cstate->resp_length = MD5_SIGNATURE_SIZE; + break; + +#ifdef CHAPMS + case CHAP_MICROSOFT: + ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len); + break; +#endif + + default: + CHAPDEBUG((LOG_INFO, "unknown digest type %d\n", cstate->resp_type)); + return; + } + + BZERO(secret, sizeof(secret)); + ChapSendResponse(cstate); +} + + +/* + * ChapReceiveResponse - Receive and process response. + */ +static void +ChapReceiveResponse(chap_state *cstate, u_char *inp, int id, int len) +{ + u_char *remmd, remmd_len; + int secret_len, old_state; + int code; + char rhostname[256]; + MD5_CTX mdContext; + char secret[MAXSECRETLEN]; + u_char hash[MD5_SIGNATURE_SIZE]; + + CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: Rcvd id %d.\n", id)); + + if (cstate->serverstate == CHAPSS_CLOSED || + cstate->serverstate == CHAPSS_PENDING) { + CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: in state %d\n", + cstate->serverstate)); + return; + } + + if (id != cstate->chal_id) { + return; /* doesn't match ID of last challenge */ + } + + /* + * If we have received a duplicate or bogus Response, + * we have to send the same answer (Success/Failure) + * as we did for the first Response we saw. + */ + if (cstate->serverstate == CHAPSS_OPEN) { + ChapSendStatus(cstate, CHAP_SUCCESS); + return; + } + if (cstate->serverstate == CHAPSS_BADAUTH) { + ChapSendStatus(cstate, CHAP_FAILURE); + return; + } + + if (len < 2) { + CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: rcvd short packet.\n")); + return; + } + GETCHAR(remmd_len, inp); /* get length of MD */ + remmd = inp; /* get pointer to MD */ + INCPTR(remmd_len, inp); + + len -= sizeof (u_char) + remmd_len; + if (len < 0) { + CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: rcvd short packet.\n")); + return; + } + + UNTIMEOUT(ChapChallengeTimeout, cstate); + + if (len >= sizeof(rhostname)) { + len = sizeof(rhostname) - 1; + } + BCOPY(inp, rhostname, len); + rhostname[len] = '\000'; + + CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: received name field: %s\n", rhostname)); + + /* + * Get secret for authenticating them with us, + * do the hash ourselves, and compare the result. + */ + code = CHAP_FAILURE; + if (!get_secret(cstate->unit, rhostname, cstate->chal_name, secret, &secret_len, 1)) { + /* CHAPDEBUG((LOG_WARNING, TL_CHAP, "No CHAP secret found for authenticating %s\n", rhostname)); */ + CHAPDEBUG((LOG_WARNING, "No CHAP secret found for authenticating %s\n", + rhostname)); + } else { + /* generate MD based on negotiated type */ + switch (cstate->chal_type) { + + case CHAP_DIGEST_MD5: /* only MD5 is defined for now */ + if (remmd_len != MD5_SIGNATURE_SIZE) { + break; /* it's not even the right length */ + } + MD5Init(&mdContext); + MD5Update(&mdContext, &cstate->chal_id, 1); + MD5Update(&mdContext, (u_char*)secret, secret_len); + MD5Update(&mdContext, cstate->challenge, cstate->chal_len); + MD5Final(hash, &mdContext); + + /* compare local and remote MDs and send the appropriate status */ + if (memcmp (hash, remmd, MD5_SIGNATURE_SIZE) == 0) { + code = CHAP_SUCCESS; /* they are the same! */ + } + break; + + default: + CHAPDEBUG((LOG_INFO, "unknown digest type %d\n", cstate->chal_type)); + } + } + + BZERO(secret, sizeof(secret)); + ChapSendStatus(cstate, code); + + if (code == CHAP_SUCCESS) { + old_state = cstate->serverstate; + cstate->serverstate = CHAPSS_OPEN; + if (old_state == CHAPSS_INITIAL_CHAL) { + auth_peer_success(cstate->unit, PPP_CHAP, rhostname, len); + } + if (cstate->chal_interval != 0) { + TIMEOUT(ChapRechallenge, cstate, cstate->chal_interval); + } + } else { + CHAPDEBUG((LOG_ERR, "CHAP peer authentication failed\n")); + cstate->serverstate = CHAPSS_BADAUTH; + auth_peer_fail(cstate->unit, PPP_CHAP); + } +} + +/* + * ChapReceiveSuccess - Receive Success + */ +static void +ChapReceiveSuccess(chap_state *cstate, u_char *inp, u_char id, int len) +{ + LWIP_UNUSED_ARG(id); + LWIP_UNUSED_ARG(inp); + + CHAPDEBUG((LOG_INFO, "ChapReceiveSuccess: Rcvd id %d.\n", id)); + + if (cstate->clientstate == CHAPCS_OPEN) { + /* presumably an answer to a duplicate response */ + return; + } + + if (cstate->clientstate != CHAPCS_RESPONSE) { + /* don't know what this is */ + CHAPDEBUG((LOG_INFO, "ChapReceiveSuccess: in state %d\n", cstate->clientstate)); + return; + } + + UNTIMEOUT(ChapResponseTimeout, cstate); + + /* + * Print message. + */ + if (len > 0) { + PRINTMSG(inp, len); + } + + cstate->clientstate = CHAPCS_OPEN; + + auth_withpeer_success(cstate->unit, PPP_CHAP); +} + + +/* + * ChapReceiveFailure - Receive failure. + */ +static void +ChapReceiveFailure(chap_state *cstate, u_char *inp, u_char id, int len) +{ + LWIP_UNUSED_ARG(id); + LWIP_UNUSED_ARG(inp); + + CHAPDEBUG((LOG_INFO, "ChapReceiveFailure: Rcvd id %d.\n", id)); + + if (cstate->clientstate != CHAPCS_RESPONSE) { + /* don't know what this is */ + CHAPDEBUG((LOG_INFO, "ChapReceiveFailure: in state %d\n", cstate->clientstate)); + return; + } + + UNTIMEOUT(ChapResponseTimeout, cstate); + + /* + * Print message. + */ + if (len > 0) { + PRINTMSG(inp, len); + } + + CHAPDEBUG((LOG_ERR, "CHAP authentication failed\n")); + auth_withpeer_fail(cstate->unit, PPP_CHAP); +} + + +/* + * ChapSendChallenge - Send an Authenticate challenge. + */ +static void +ChapSendChallenge(chap_state *cstate) +{ + u_char *outp; + int chal_len, name_len; + int outlen; + + chal_len = cstate->chal_len; + name_len = strlen(cstate->chal_name); + outlen = CHAP_HEADERLEN + sizeof (u_char) + chal_len + name_len; + outp = outpacket_buf[cstate->unit]; + + MAKEHEADER(outp, PPP_CHAP); /* paste in a CHAP header */ + + PUTCHAR(CHAP_CHALLENGE, outp); + PUTCHAR(cstate->chal_id, outp); + PUTSHORT(outlen, outp); + + PUTCHAR(chal_len, outp); /* put length of challenge */ + BCOPY(cstate->challenge, outp, chal_len); + INCPTR(chal_len, outp); + + BCOPY(cstate->chal_name, outp, name_len); /* append hostname */ + + pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN); + + CHAPDEBUG((LOG_INFO, "ChapSendChallenge: Sent id %d.\n", cstate->chal_id)); + + TIMEOUT(ChapChallengeTimeout, cstate, cstate->timeouttime); + ++cstate->chal_transmits; +} + + +/* + * ChapSendStatus - Send a status response (ack or nak). + */ +static void +ChapSendStatus(chap_state *cstate, int code) +{ + u_char *outp; + int outlen, msglen; + char msg[256]; + + if (code == CHAP_SUCCESS) { + strcpy(msg, "Welcome!"); + } else { + strcpy(msg, "I don't like you. Go 'way."); + } + msglen = strlen(msg); + + outlen = CHAP_HEADERLEN + msglen; + outp = outpacket_buf[cstate->unit]; + + MAKEHEADER(outp, PPP_CHAP); /* paste in a header */ + + PUTCHAR(code, outp); + PUTCHAR(cstate->chal_id, outp); + PUTSHORT(outlen, outp); + BCOPY(msg, outp, msglen); + pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN); + + CHAPDEBUG((LOG_INFO, "ChapSendStatus: Sent code %d, id %d.\n", code, cstate->chal_id)); +} + +/* + * ChapGenChallenge is used to generate a pseudo-random challenge string of + * a pseudo-random length between min_len and max_len. The challenge + * string and its length are stored in *cstate, and various other fields of + * *cstate are initialized. + */ + +static void +ChapGenChallenge(chap_state *cstate) +{ + int chal_len; + u_char *ptr = cstate->challenge; + int i; + + /* pick a random challenge length between MIN_CHALLENGE_LENGTH and + MAX_CHALLENGE_LENGTH */ + chal_len = (unsigned) + ((((magic() >> 16) * + (MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH)) >> 16) + + MIN_CHALLENGE_LENGTH); + cstate->chal_len = chal_len; + cstate->chal_id = ++cstate->id; + cstate->chal_transmits = 0; + + /* generate a random string */ + for (i = 0; i < chal_len; i++ ) { + *ptr++ = (char) (magic() & 0xff); + } +} + +/* + * ChapSendResponse - send a response packet with values as specified + * in *cstate. + */ +/* ARGSUSED */ +static void +ChapSendResponse(chap_state *cstate) +{ + u_char *outp; + int outlen, md_len, name_len; + + md_len = cstate->resp_length; + name_len = strlen(cstate->resp_name); + outlen = CHAP_HEADERLEN + sizeof (u_char) + md_len + name_len; + outp = outpacket_buf[cstate->unit]; + + MAKEHEADER(outp, PPP_CHAP); + + PUTCHAR(CHAP_RESPONSE, outp); /* we are a response */ + PUTCHAR(cstate->resp_id, outp); /* copy id from challenge packet */ + PUTSHORT(outlen, outp); /* packet length */ + + PUTCHAR(md_len, outp); /* length of MD */ + BCOPY(cstate->response, outp, md_len); /* copy MD to buffer */ + INCPTR(md_len, outp); + + BCOPY(cstate->resp_name, outp, name_len); /* append our name */ + + /* send the packet */ + pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN); + + cstate->clientstate = CHAPCS_RESPONSE; + TIMEOUT(ChapResponseTimeout, cstate, cstate->timeouttime); + ++cstate->resp_transmits; +} + +#if 0 +static char *ChapCodenames[] = { + "Challenge", "Response", "Success", "Failure" +}; +/* + * ChapPrintPkt - print the contents of a CHAP packet. + */ +static int +ChapPrintPkt( u_char *p, int plen, void (*printer) (void *, char *, ...), void *arg) +{ + int code, id, len; + int clen, nlen; + u_char x; + + if (plen < CHAP_HEADERLEN) { + return 0; + } + GETCHAR(code, p); + GETCHAR(id, p); + GETSHORT(len, p); + if (len < CHAP_HEADERLEN || len > plen) { + return 0; + } + if (code >= 1 && code <= sizeof(ChapCodenames) / sizeof(char *)) { + printer(arg, " %s", ChapCodenames[code-1]); + } else { + printer(arg, " code=0x%x", code); + } + printer(arg, " id=0x%x", id); + len -= CHAP_HEADERLEN; + switch (code) { + case CHAP_CHALLENGE: + case CHAP_RESPONSE: + if (len < 1) { + break; + } + clen = p[0]; + if (len < clen + 1) { + break; + } + ++p; + nlen = len - clen - 1; + printer(arg, " <"); + for (; clen > 0; --clen) { + GETCHAR(x, p); + printer(arg, "%.2x", x); + } + printer(arg, ">, name = %.*Z", nlen, p); + break; + case CHAP_FAILURE: + case CHAP_SUCCESS: + printer(arg, " %.*Z", len, p); + break; + default: + for (clen = len; clen > 0; --clen) { + GETCHAR(x, p); + printer(arg, " %.2x", x); + } + } + + return len + CHAP_HEADERLEN; +} +#endif + +#endif /* CHAP_SUPPORT */ + +#endif /* PPP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/chap.h b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/chap.h new file mode 100644 index 0000000..83dafd7 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/chap.h @@ -0,0 +1,166 @@ +/***************************************************************************** +* chap.h - Network Challenge Handshake Authentication Protocol header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1998 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-12-03 Guy Lancaster , Global Election Systems Inc. +* Original built from BSD network code. +******************************************************************************/ +/* + * chap.h - Challenge Handshake Authentication Protocol definitions. + * + * Copyright (c) 1993 The Australian National University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the Australian National University. The name of the University + * may not be used to endorse or promote products derived from this + * software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Copyright (c) 1991 Gregory M. Christy + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the author. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * $Id: chap.h,v 1.4 2007/12/19 20:47:22 fbernon Exp $ + */ + +#ifndef CHAP_H +#define CHAP_H + +/************************* +*** PUBLIC DEFINITIONS *** +*************************/ + +/* Code + ID + length */ +#define CHAP_HEADERLEN 4 + +/* + * CHAP codes. + */ + +#define CHAP_DIGEST_MD5 5 /* use MD5 algorithm */ +#define MD5_SIGNATURE_SIZE 16 /* 16 bytes in a MD5 message digest */ +#define CHAP_MICROSOFT 0x80 /* use Microsoft-compatible alg. */ +#define MS_CHAP_RESPONSE_LEN 49 /* Response length for MS-CHAP */ + +#define CHAP_CHALLENGE 1 +#define CHAP_RESPONSE 2 +#define CHAP_SUCCESS 3 +#define CHAP_FAILURE 4 + +/* + * Challenge lengths (for challenges we send) and other limits. + */ +#define MIN_CHALLENGE_LENGTH 32 +#define MAX_CHALLENGE_LENGTH 64 +#define MAX_RESPONSE_LENGTH 64 /* sufficient for MD5 or MS-CHAP */ + +/* + * Client (peer) states. + */ +#define CHAPCS_INITIAL 0 /* Lower layer down, not opened */ +#define CHAPCS_CLOSED 1 /* Lower layer up, not opened */ +#define CHAPCS_PENDING 2 /* Auth us to peer when lower up */ +#define CHAPCS_LISTEN 3 /* Listening for a challenge */ +#define CHAPCS_RESPONSE 4 /* Sent response, waiting for status */ +#define CHAPCS_OPEN 5 /* We've received Success */ + +/* + * Server (authenticator) states. + */ +#define CHAPSS_INITIAL 0 /* Lower layer down, not opened */ +#define CHAPSS_CLOSED 1 /* Lower layer up, not opened */ +#define CHAPSS_PENDING 2 /* Auth peer when lower up */ +#define CHAPSS_INITIAL_CHAL 3 /* We've sent the first challenge */ +#define CHAPSS_OPEN 4 /* We've sent a Success msg */ +#define CHAPSS_RECHALLENGE 5 /* We've sent another challenge */ +#define CHAPSS_BADAUTH 6 /* We've sent a Failure msg */ + +/************************ +*** PUBLIC DATA TYPES *** +************************/ + +/* + * Each interface is described by a chap structure. + */ + +typedef struct chap_state { + int unit; /* Interface unit number */ + int clientstate; /* Client state */ + int serverstate; /* Server state */ + u_char challenge[MAX_CHALLENGE_LENGTH]; /* last challenge string sent */ + u_char chal_len; /* challenge length */ + u_char chal_id; /* ID of last challenge */ + u_char chal_type; /* hash algorithm for challenges */ + u_char id; /* Current id */ + char *chal_name; /* Our name to use with challenge */ + int chal_interval; /* Time until we challenge peer again */ + int timeouttime; /* Timeout time in seconds */ + int max_transmits; /* Maximum # of challenge transmissions */ + int chal_transmits; /* Number of transmissions of challenge */ + int resp_transmits; /* Number of transmissions of response */ + u_char response[MAX_RESPONSE_LENGTH]; /* Response to send */ + u_char resp_length; /* length of response */ + u_char resp_id; /* ID for response messages */ + u_char resp_type; /* hash algorithm for responses */ + char *resp_name; /* Our name to send with response */ +} chap_state; + + +/****************** +*** PUBLIC DATA *** +******************/ +extern chap_state chap[]; + +extern struct protent chap_protent; + + +/*********************** +*** PUBLIC FUNCTIONS *** +***********************/ + +void ChapAuthWithPeer (int, char *, int); +void ChapAuthPeer (int, char *, int); + +#endif /* CHAP_H */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/chpms.c b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/chpms.c new file mode 100644 index 0000000..582cfd2 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/chpms.c @@ -0,0 +1,399 @@ +/*** WARNING - THIS CODE HAS NOT BEEN FINISHED! ***/ +/*** The original PPPD code is written in a way to require either the UNIX DES + encryption functions encrypt(3) and setkey(3) or the DES library libdes. + Since both is not included in lwIP, MSCHAP currently does not work! */ +/***************************************************************************** +* chpms.c - Network MicroSoft Challenge Handshake Authentication Protocol program file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* Copyright (c) 1997 by Global Election Systems Inc. All rights reserved. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-12-08 Guy Lancaster , Global Election Systems Inc. +* Original based on BSD chap_ms.c. +*****************************************************************************/ +/* + * chap_ms.c - Microsoft MS-CHAP compatible implementation. + * + * Copyright (c) 1995 Eric Rosenquist, Strata Software Limited. + * http://www.strataware.com/ + * + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Eric Rosenquist. The name of the author may not be used to + * endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* + * Modifications by Lauri Pesonen / lpesonen@clinet.fi, april 1997 + * + * Implemented LANManager type password response to MS-CHAP challenges. + * Now pppd provides both NT style and LANMan style blocks, and the + * prefered is set by option "ms-lanman". Default is to use NT. + * The hash text (StdText) was taken from Win95 RASAPI32.DLL. + * + * You should also use DOMAIN\\USERNAME as described in README.MSCHAP80 + */ + +#define USE_CRYPT + +#include "lwip/opt.h" + +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#if MSCHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "ppp.h" +#include "pppdebug.h" + +#include "md4.h" +#ifndef USE_CRYPT +#include "des.h" +#endif +#include "chap.h" +#include "chpms.h" + + +/*************************/ +/*** LOCAL DEFINITIONS ***/ +/*************************/ + + +/************************/ +/*** LOCAL DATA TYPES ***/ +/************************/ +typedef struct { + u_char LANManResp[24]; + u_char NTResp[24]; + u_char UseNT; /* If 1, ignore the LANMan response field */ +} MS_ChapResponse; +/* We use MS_CHAP_RESPONSE_LEN, rather than sizeof(MS_ChapResponse), + in case this struct gets padded. */ + + + +/***********************************/ +/*** LOCAL FUNCTION DECLARATIONS ***/ +/***********************************/ + +/* XXX Don't know what to do with these. */ +extern void setkey(const char *); +extern void encrypt(char *, int); + +static void DesEncrypt (u_char *, u_char *, u_char *); +static void MakeKey (u_char *, u_char *); + +#ifdef USE_CRYPT +static void Expand (u_char *, u_char *); +static void Collapse (u_char *, u_char *); +#endif + +static void ChallengeResponse( + u_char *challenge, /* IN 8 octets */ + u_char *pwHash, /* IN 16 octets */ + u_char *response /* OUT 24 octets */ +); +static void ChapMS_NT( + char *rchallenge, + int rchallenge_len, + char *secret, + int secret_len, + MS_ChapResponse *response +); +static u_char Get7Bits( + u_char *input, + int startBit +); + + +/***********************************/ +/*** PUBLIC FUNCTION DEFINITIONS ***/ +/***********************************/ +void +ChapMS( chap_state *cstate, char *rchallenge, int rchallenge_len, char *secret, int secret_len) +{ + MS_ChapResponse response; +#ifdef MSLANMAN + extern int ms_lanman; +#endif + +#if 0 + CHAPDEBUG((LOG_INFO, "ChapMS: secret is '%.*s'\n", secret_len, secret)); +#endif + BZERO(&response, sizeof(response)); + + /* Calculate both always */ + ChapMS_NT(rchallenge, rchallenge_len, secret, secret_len, &response); + +#ifdef MSLANMAN + ChapMS_LANMan(rchallenge, rchallenge_len, secret, secret_len, &response); + + /* prefered method is set by option */ + response.UseNT = !ms_lanman; +#else + response.UseNT = 1; +#endif + + BCOPY(&response, cstate->response, MS_CHAP_RESPONSE_LEN); + cstate->resp_length = MS_CHAP_RESPONSE_LEN; +} + + +/**********************************/ +/*** LOCAL FUNCTION DEFINITIONS ***/ +/**********************************/ +static void +ChallengeResponse( u_char *challenge, /* IN 8 octets */ + u_char *pwHash, /* IN 16 octets */ + u_char *response /* OUT 24 octets */) +{ + char ZPasswordHash[21]; + + BZERO(ZPasswordHash, sizeof(ZPasswordHash)); + BCOPY(pwHash, ZPasswordHash, 16); + +#if 0 + log_packet(ZPasswordHash, sizeof(ZPasswordHash), "ChallengeResponse - ZPasswordHash", LOG_DEBUG); +#endif + + DesEncrypt(challenge, ZPasswordHash + 0, response + 0); + DesEncrypt(challenge, ZPasswordHash + 7, response + 8); + DesEncrypt(challenge, ZPasswordHash + 14, response + 16); + +#if 0 + log_packet(response, 24, "ChallengeResponse - response", LOG_DEBUG); +#endif +} + + +#ifdef USE_CRYPT +static void +DesEncrypt( u_char *clear, /* IN 8 octets */ + u_char *key, /* IN 7 octets */ + u_char *cipher /* OUT 8 octets */) +{ + u_char des_key[8]; + u_char crypt_key[66]; + u_char des_input[66]; + + MakeKey(key, des_key); + + Expand(des_key, crypt_key); + setkey(crypt_key); + +#if 0 + CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet input : %02X%02X%02X%02X%02X%02X%02X%02X\n", + clear[0], clear[1], clear[2], clear[3], clear[4], clear[5], clear[6], clear[7])); +#endif + + Expand(clear, des_input); + encrypt(des_input, 0); + Collapse(des_input, cipher); + +#if 0 + CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %02X%02X%02X%02X%02X%02X%02X%02X\n", + cipher[0], cipher[1], cipher[2], cipher[3], cipher[4], cipher[5], cipher[6], cipher[7])); +#endif +} + +#else /* USE_CRYPT */ + +static void +DesEncrypt( u_char *clear, /* IN 8 octets */ + u_char *key, /* IN 7 octets */ + u_char *cipher /* OUT 8 octets */) +{ + des_cblock des_key; + des_key_schedule key_schedule; + + MakeKey(key, des_key); + + des_set_key(&des_key, key_schedule); + +#if 0 + CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet input : %02X%02X%02X%02X%02X%02X%02X%02X\n", + clear[0], clear[1], clear[2], clear[3], clear[4], clear[5], clear[6], clear[7])); +#endif + + des_ecb_encrypt((des_cblock *)clear, (des_cblock *)cipher, key_schedule, 1); + +#if 0 + CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %02X%02X%02X%02X%02X%02X%02X%02X\n", + cipher[0], cipher[1], cipher[2], cipher[3], cipher[4], cipher[5], cipher[6], cipher[7])); +#endif +} + +#endif /* USE_CRYPT */ + + +static u_char +Get7Bits( u_char *input, int startBit) +{ + register unsigned int word; + + word = (unsigned)input[startBit / 8] << 8; + word |= (unsigned)input[startBit / 8 + 1]; + + word >>= 15 - (startBit % 8 + 7); + + return word & 0xFE; +} + +#ifdef USE_CRYPT + +/* in == 8-byte string (expanded version of the 56-bit key) + * out == 64-byte string where each byte is either 1 or 0 + * Note that the low-order "bit" is always ignored by by setkey() + */ +static void +Expand(u_char *in, u_char *out) +{ + int j, c; + int i; + + for(i = 0; i < 64; in++){ + c = *in; + for(j = 7; j >= 0; j--) { + *out++ = (c >> j) & 01; + } + i += 8; + } +} + +/* The inverse of Expand + */ +static void +Collapse(u_char *in, u_char *out) +{ + int j; + int i; + unsigned int c; + + for (i = 0; i < 64; i += 8, out++) { + c = 0; + for (j = 7; j >= 0; j--, in++) { + c |= *in << j; + } + *out = c & 0xff; + } +} +#endif + +static void +MakeKey( u_char *key, /* IN 56 bit DES key missing parity bits */ + u_char *des_key /* OUT 64 bit DES key with parity bits added */) +{ + des_key[0] = Get7Bits(key, 0); + des_key[1] = Get7Bits(key, 7); + des_key[2] = Get7Bits(key, 14); + des_key[3] = Get7Bits(key, 21); + des_key[4] = Get7Bits(key, 28); + des_key[5] = Get7Bits(key, 35); + des_key[6] = Get7Bits(key, 42); + des_key[7] = Get7Bits(key, 49); + +#ifndef USE_CRYPT + des_set_odd_parity((des_cblock *)des_key); +#endif + +#if 0 + CHAPDEBUG((LOG_INFO, "MakeKey: 56-bit input : %02X%02X%02X%02X%02X%02X%02X\n", + key[0], key[1], key[2], key[3], key[4], key[5], key[6])); + CHAPDEBUG((LOG_INFO, "MakeKey: 64-bit output: %02X%02X%02X%02X%02X%02X%02X%02X\n", + des_key[0], des_key[1], des_key[2], des_key[3], des_key[4], des_key[5], des_key[6], des_key[7])); +#endif +} + +static void +ChapMS_NT( char *rchallenge, + int rchallenge_len, + char *secret, + int secret_len, + MS_ChapResponse *response) +{ + int i; + MDstruct md4Context; + u_char unicodePassword[MAX_NT_PASSWORD * 2]; + static int low_byte_first = -1; + + /* Initialize the Unicode version of the secret (== password). */ + /* This implicitly supports 8-bit ISO8859/1 characters. */ + BZERO(unicodePassword, sizeof(unicodePassword)); + for (i = 0; i < secret_len; i++) { + unicodePassword[i * 2] = (u_char)secret[i]; + } + MDbegin(&md4Context); + MDupdate(&md4Context, unicodePassword, secret_len * 2 * 8); /* Unicode is 2 bytes/char, *8 for bit count */ + + if (low_byte_first == -1) { + low_byte_first = (htons((unsigned short int)1) != 1); + } + if (low_byte_first == 0) { + MDreverse((u_long *)&md4Context); /* sfb 961105 */ + } + + MDupdate(&md4Context, NULL, 0); /* Tell MD4 we're done */ + + ChallengeResponse(rchallenge, (char *)md4Context.buffer, response->NTResp); +} + +#ifdef MSLANMAN +static u_char *StdText = (u_char *)"KGS!@#$%"; /* key from rasapi32.dll */ + +static void +ChapMS_LANMan( char *rchallenge, + int rchallenge_len, + char *secret, + int secret_len, + MS_ChapResponse *response) +{ + int i; + u_char UcasePassword[MAX_NT_PASSWORD]; /* max is actually 14 */ + u_char PasswordHash[16]; + + /* LANMan password is case insensitive */ + BZERO(UcasePassword, sizeof(UcasePassword)); + for (i = 0; i < secret_len; i++) { + UcasePassword[i] = (u_char)toupper(secret[i]); + } + DesEncrypt( StdText, UcasePassword + 0, PasswordHash + 0 ); + DesEncrypt( StdText, UcasePassword + 7, PasswordHash + 8 ); + ChallengeResponse(rchallenge, PasswordHash, response->LANManResp); +} +#endif + +#endif /* MSCHAP_SUPPORT */ + +#endif /* PPP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/chpms.h b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/chpms.h new file mode 100644 index 0000000..df070fb --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/chpms.h @@ -0,0 +1,64 @@ +/***************************************************************************** +* chpms.h - Network Microsoft Challenge Handshake Protocol header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1998 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 98-01-30 Guy Lancaster , Global Election Systems Inc. +* Original built from BSD network code. +******************************************************************************/ +/* + * chap.h - Challenge Handshake Authentication Protocol definitions. + * + * Copyright (c) 1995 Eric Rosenquist, Strata Software Limited. + * http://www.strataware.com/ + * + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Eric Rosenquist. The name of the author may not be used to + * endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * $Id: chpms.h,v 1.5 2007/12/19 20:47:23 fbernon Exp $ + */ + +#ifndef CHPMS_H +#define CHPMS_H + +#define MAX_NT_PASSWORD 256 /* Maximum number of (Unicode) chars in an NT password */ + +void ChapMS (chap_state *, char *, int, char *, int); + +#endif /* CHPMS_H */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/fsm.c b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/fsm.c new file mode 100644 index 0000000..ee549f2 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/fsm.c @@ -0,0 +1,908 @@ +/***************************************************************************** +* fsm.c - Network Control Protocol Finite State Machine program file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 by Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-12-01 Guy Lancaster , Global Election Systems Inc. +* Original based on BSD fsm.c. +*****************************************************************************/ +/* + * fsm.c - {Link, IP} Control Protocol Finite State Machine. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* + * TODO: + * Randomize fsm id on link/init. + * Deal with variable outgoing MTU. + */ + +#include "lwip/opt.h" + +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "ppp.h" +#include "pppdebug.h" + +#include "fsm.h" + +#include + + +/*************************/ +/*** LOCAL DEFINITIONS ***/ +/*************************/ + +#if PPP_DEBUG + +static const char *ppperr_strerr[] = { + "LS_INITIAL", /* LS_INITIAL 0 */ + "LS_STARTING", /* LS_STARTING 1 */ + "LS_CLOSED", /* LS_CLOSED 2 */ + "LS_STOPPED", /* LS_STOPPED 3 */ + "LS_CLOSING", /* LS_CLOSING 4 */ + "LS_STOPPING", /* LS_STOPPING 5 */ + "LS_REQSENT", /* LS_REQSENT 6 */ + "LS_ACKRCVD", /* LS_ACKRCVD 7 */ + "LS_ACKSENT", /* LS_ACKSENT 8 */ + "LS_OPENED" /* LS_OPENED 9 */ +}; + +#endif /* PPP_DEBUG */ + +/************************/ +/*** LOCAL DATA TYPES ***/ +/************************/ + + +/***********************************/ +/*** LOCAL FUNCTION DECLARATIONS ***/ +/***********************************/ +static void fsm_timeout (void *); +static void fsm_rconfreq (fsm *, u_char, u_char *, int); +static void fsm_rconfack (fsm *, int, u_char *, int); +static void fsm_rconfnakrej (fsm *, int, int, u_char *, int); +static void fsm_rtermreq (fsm *, int, u_char *, int); +static void fsm_rtermack (fsm *); +static void fsm_rcoderej (fsm *, u_char *, int); +static void fsm_sconfreq (fsm *, int); + +#define PROTO_NAME(f) ((f)->callbacks->proto_name) + + +/******************************/ +/*** PUBLIC DATA STRUCTURES ***/ +/******************************/ + + +/*****************************/ +/*** LOCAL DATA STRUCTURES ***/ +/*****************************/ +int peer_mru[NUM_PPP]; + + +/***********************************/ +/*** PUBLIC FUNCTION DEFINITIONS ***/ +/***********************************/ + +/* + * fsm_init - Initialize fsm. + * + * Initialize fsm state. + */ +void +fsm_init(fsm *f) +{ + f->state = LS_INITIAL; + f->flags = 0; + f->id = 0; /* XXX Start with random id? */ + f->timeouttime = FSM_DEFTIMEOUT; + f->maxconfreqtransmits = FSM_DEFMAXCONFREQS; + f->maxtermtransmits = FSM_DEFMAXTERMREQS; + f->maxnakloops = FSM_DEFMAXNAKLOOPS; + f->term_reason_len = 0; +} + + +/* + * fsm_lowerup - The lower layer is up. + */ +void +fsm_lowerup(fsm *f) +{ + int oldState = f->state; + + LWIP_UNUSED_ARG(oldState); + + switch( f->state ) { + case LS_INITIAL: + f->state = LS_CLOSED; + break; + + case LS_STARTING: + if( f->flags & OPT_SILENT ) { + f->state = LS_STOPPED; + } else { + /* Send an initial configure-request */ + fsm_sconfreq(f, 0); + f->state = LS_REQSENT; + } + break; + + default: + FSMDEBUG((LOG_INFO, "%s: Up event in state %d (%s)!\n", + PROTO_NAME(f), f->state, ppperr_strerr[f->state])); + } + + FSMDEBUG((LOG_INFO, "%s: lowerup state %d (%s) -> %d (%s)\n", + PROTO_NAME(f), oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state])); +} + + +/* + * fsm_lowerdown - The lower layer is down. + * + * Cancel all timeouts and inform upper layers. + */ +void +fsm_lowerdown(fsm *f) +{ + int oldState = f->state; + + LWIP_UNUSED_ARG(oldState); + + switch( f->state ) { + case LS_CLOSED: + f->state = LS_INITIAL; + break; + + case LS_STOPPED: + f->state = LS_STARTING; + if( f->callbacks->starting ) { + (*f->callbacks->starting)(f); + } + break; + + case LS_CLOSING: + f->state = LS_INITIAL; + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + break; + + case LS_STOPPING: + case LS_REQSENT: + case LS_ACKRCVD: + case LS_ACKSENT: + f->state = LS_STARTING; + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + break; + + case LS_OPENED: + if( f->callbacks->down ) { + (*f->callbacks->down)(f); + } + f->state = LS_STARTING; + break; + + default: + FSMDEBUG((LOG_INFO, "%s: Down event in state %d (%s)!\n", + PROTO_NAME(f), f->state, ppperr_strerr[f->state])); + } + + FSMDEBUG((LOG_INFO, "%s: lowerdown state %d (%s) -> %d (%s)\n", + PROTO_NAME(f), oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state])); +} + + +/* + * fsm_open - Link is allowed to come up. + */ +void +fsm_open(fsm *f) +{ + int oldState = f->state; + + LWIP_UNUSED_ARG(oldState); + + switch( f->state ) { + case LS_INITIAL: + f->state = LS_STARTING; + if( f->callbacks->starting ) { + (*f->callbacks->starting)(f); + } + break; + + case LS_CLOSED: + if( f->flags & OPT_SILENT ) { + f->state = LS_STOPPED; + } else { + /* Send an initial configure-request */ + fsm_sconfreq(f, 0); + f->state = LS_REQSENT; + } + break; + + case LS_CLOSING: + f->state = LS_STOPPING; + /* fall through */ + case LS_STOPPED: + case LS_OPENED: + if( f->flags & OPT_RESTART ) { + fsm_lowerdown(f); + fsm_lowerup(f); + } + break; + } + + FSMDEBUG((LOG_INFO, "%s: open state %d (%s) -> %d (%s)\n", + PROTO_NAME(f), oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state])); +} + + +/* + * fsm_close - Start closing connection. + * + * Cancel timeouts and either initiate close or possibly go directly to + * the LS_CLOSED state. + */ +void +fsm_close(fsm *f, char *reason) +{ + int oldState = f->state; + + LWIP_UNUSED_ARG(oldState); + + f->term_reason = reason; + f->term_reason_len = (reason == NULL? 0: strlen(reason)); + switch( f->state ) { + case LS_STARTING: + f->state = LS_INITIAL; + break; + case LS_STOPPED: + f->state = LS_CLOSED; + break; + case LS_STOPPING: + f->state = LS_CLOSING; + break; + + case LS_REQSENT: + case LS_ACKRCVD: + case LS_ACKSENT: + case LS_OPENED: + if( f->state != LS_OPENED ) { + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + } else if( f->callbacks->down ) { + (*f->callbacks->down)(f); /* Inform upper layers we're down */ + } + /* Init restart counter, send Terminate-Request */ + f->retransmits = f->maxtermtransmits; + fsm_sdata(f, TERMREQ, f->reqid = ++f->id, + (u_char *) f->term_reason, f->term_reason_len); + TIMEOUT(fsm_timeout, f, f->timeouttime); + --f->retransmits; + + f->state = LS_CLOSING; + break; + } + + FSMDEBUG((LOG_INFO, "%s: close reason=%s state %d (%s) -> %d (%s)\n", + PROTO_NAME(f), reason, oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state])); +} + + +/* + * fsm_sdata - Send some data. + * + * Used for all packets sent to our peer by this module. + */ +void +fsm_sdata( fsm *f, u_char code, u_char id, u_char *data, int datalen) +{ + u_char *outp; + int outlen; + + /* Adjust length to be smaller than MTU */ + outp = outpacket_buf[f->unit]; + if (datalen > peer_mru[f->unit] - (int)HEADERLEN) { + datalen = peer_mru[f->unit] - HEADERLEN; + } + if (datalen && data != outp + PPP_HDRLEN + HEADERLEN) { + BCOPY(data, outp + PPP_HDRLEN + HEADERLEN, datalen); + } + outlen = datalen + HEADERLEN; + MAKEHEADER(outp, f->protocol); + PUTCHAR(code, outp); + PUTCHAR(id, outp); + PUTSHORT(outlen, outp); + pppWrite(f->unit, outpacket_buf[f->unit], outlen + PPP_HDRLEN); + FSMDEBUG((LOG_INFO, "fsm_sdata(%s): Sent code %d,%d,%d.\n", + PROTO_NAME(f), code, id, outlen)); +} + + +/* + * fsm_input - Input packet. + */ +void +fsm_input(fsm *f, u_char *inpacket, int l) +{ + u_char *inp = inpacket; + u_char code, id; + int len; + + /* + * Parse header (code, id and length). + * If packet too short, drop it. + */ + if (l < HEADERLEN) { + FSMDEBUG((LOG_WARNING, "fsm_input(%x): Rcvd short header.\n", + f->protocol)); + return; + } + GETCHAR(code, inp); + GETCHAR(id, inp); + GETSHORT(len, inp); + if (len < HEADERLEN) { + FSMDEBUG((LOG_INFO, "fsm_input(%x): Rcvd illegal length.\n", + f->protocol)); + return; + } + if (len > l) { + FSMDEBUG((LOG_INFO, "fsm_input(%x): Rcvd short packet.\n", + f->protocol)); + return; + } + len -= HEADERLEN; /* subtract header length */ + + if( f->state == LS_INITIAL || f->state == LS_STARTING ) { + FSMDEBUG((LOG_INFO, "fsm_input(%x): Rcvd packet in state %d (%s).\n", + f->protocol, f->state, ppperr_strerr[f->state])); + return; + } + FSMDEBUG((LOG_INFO, "fsm_input(%s):%d,%d,%d\n", PROTO_NAME(f), code, id, l)); + /* + * Action depends on code. + */ + switch (code) { + case CONFREQ: + fsm_rconfreq(f, id, inp, len); + break; + + case CONFACK: + fsm_rconfack(f, id, inp, len); + break; + + case CONFNAK: + case CONFREJ: + fsm_rconfnakrej(f, code, id, inp, len); + break; + + case TERMREQ: + fsm_rtermreq(f, id, inp, len); + break; + + case TERMACK: + fsm_rtermack(f); + break; + + case CODEREJ: + fsm_rcoderej(f, inp, len); + break; + + default: + if( !f->callbacks->extcode || + !(*f->callbacks->extcode)(f, code, id, inp, len) ) { + fsm_sdata(f, CODEREJ, ++f->id, inpacket, len + HEADERLEN); + } + break; + } +} + + +/* + * fsm_protreject - Peer doesn't speak this protocol. + * + * Treat this as a catastrophic error (RXJ-). + */ +void +fsm_protreject(fsm *f) +{ + switch( f->state ) { + case LS_CLOSING: + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + /* fall through */ + case LS_CLOSED: + f->state = LS_CLOSED; + if( f->callbacks->finished ) { + (*f->callbacks->finished)(f); + } + break; + + case LS_STOPPING: + case LS_REQSENT: + case LS_ACKRCVD: + case LS_ACKSENT: + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + /* fall through */ + case LS_STOPPED: + f->state = LS_STOPPED; + if( f->callbacks->finished ) { + (*f->callbacks->finished)(f); + } + break; + + case LS_OPENED: + if( f->callbacks->down ) { + (*f->callbacks->down)(f); + } + /* Init restart counter, send Terminate-Request */ + f->retransmits = f->maxtermtransmits; + fsm_sdata(f, TERMREQ, f->reqid = ++f->id, + (u_char *) f->term_reason, f->term_reason_len); + TIMEOUT(fsm_timeout, f, f->timeouttime); + --f->retransmits; + + f->state = LS_STOPPING; + break; + + default: + FSMDEBUG((LOG_INFO, "%s: Protocol-reject event in state %d (%s)!\n", + PROTO_NAME(f), f->state, ppperr_strerr[f->state])); + } +} + + + + + +/**********************************/ +/*** LOCAL FUNCTION DEFINITIONS ***/ +/**********************************/ + +/* + * fsm_timeout - Timeout expired. + */ +static void +fsm_timeout(void *arg) +{ + fsm *f = (fsm *) arg; + + switch (f->state) { + case LS_CLOSING: + case LS_STOPPING: + if( f->retransmits <= 0 ) { + FSMDEBUG((LOG_WARNING, "%s: timeout sending Terminate-Request state=%d (%s)\n", + PROTO_NAME(f), f->state, ppperr_strerr[f->state])); + /* + * We've waited for an ack long enough. Peer probably heard us. + */ + f->state = (f->state == LS_CLOSING)? LS_CLOSED: LS_STOPPED; + if( f->callbacks->finished ) { + (*f->callbacks->finished)(f); + } + } else { + FSMDEBUG((LOG_WARNING, "%s: timeout resending Terminate-Requests state=%d (%s)\n", + PROTO_NAME(f), f->state, ppperr_strerr[f->state])); + /* Send Terminate-Request */ + fsm_sdata(f, TERMREQ, f->reqid = ++f->id, + (u_char *) f->term_reason, f->term_reason_len); + TIMEOUT(fsm_timeout, f, f->timeouttime); + --f->retransmits; + } + break; + + case LS_REQSENT: + case LS_ACKRCVD: + case LS_ACKSENT: + if (f->retransmits <= 0) { + FSMDEBUG((LOG_WARNING, "%s: timeout sending Config-Requests state=%d (%s)\n", + PROTO_NAME(f), f->state, ppperr_strerr[f->state])); + f->state = LS_STOPPED; + if( (f->flags & OPT_PASSIVE) == 0 && f->callbacks->finished ) { + (*f->callbacks->finished)(f); + } + } else { + FSMDEBUG((LOG_WARNING, "%s: timeout resending Config-Request state=%d (%s)\n", + PROTO_NAME(f), f->state, ppperr_strerr[f->state])); + /* Retransmit the configure-request */ + if (f->callbacks->retransmit) { + (*f->callbacks->retransmit)(f); + } + fsm_sconfreq(f, 1); /* Re-send Configure-Request */ + if( f->state == LS_ACKRCVD ) { + f->state = LS_REQSENT; + } + } + break; + + default: + FSMDEBUG((LOG_INFO, "%s: UNHANDLED timeout event in state %d (%s)!\n", + PROTO_NAME(f), f->state, ppperr_strerr[f->state])); + } +} + + +/* + * fsm_rconfreq - Receive Configure-Request. + */ +static void +fsm_rconfreq(fsm *f, u_char id, u_char *inp, int len) +{ + int code, reject_if_disagree; + + FSMDEBUG((LOG_INFO, "fsm_rconfreq(%s): Rcvd id %d state=%d (%s)\n", + PROTO_NAME(f), id, f->state, ppperr_strerr[f->state])); + switch( f->state ) { + case LS_CLOSED: + /* Go away, we're closed */ + fsm_sdata(f, TERMACK, id, NULL, 0); + return; + case LS_CLOSING: + case LS_STOPPING: + return; + + case LS_OPENED: + /* Go down and restart negotiation */ + if( f->callbacks->down ) { + (*f->callbacks->down)(f); /* Inform upper layers */ + } + fsm_sconfreq(f, 0); /* Send initial Configure-Request */ + break; + + case LS_STOPPED: + /* Negotiation started by our peer */ + fsm_sconfreq(f, 0); /* Send initial Configure-Request */ + f->state = LS_REQSENT; + break; + } + + /* + * Pass the requested configuration options + * to protocol-specific code for checking. + */ + if (f->callbacks->reqci) { /* Check CI */ + reject_if_disagree = (f->nakloops >= f->maxnakloops); + code = (*f->callbacks->reqci)(f, inp, &len, reject_if_disagree); + } else if (len) { + code = CONFREJ; /* Reject all CI */ + } else { + code = CONFACK; + } + + /* send the Ack, Nak or Rej to the peer */ + fsm_sdata(f, (u_char)code, id, inp, len); + + if (code == CONFACK) { + if (f->state == LS_ACKRCVD) { + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + f->state = LS_OPENED; + if (f->callbacks->up) { + (*f->callbacks->up)(f); /* Inform upper layers */ + } + } else { + f->state = LS_ACKSENT; + } + f->nakloops = 0; + } else { + /* we sent CONFACK or CONFREJ */ + if (f->state != LS_ACKRCVD) { + f->state = LS_REQSENT; + } + if( code == CONFNAK ) { + ++f->nakloops; + } + } +} + + +/* + * fsm_rconfack - Receive Configure-Ack. + */ +static void +fsm_rconfack(fsm *f, int id, u_char *inp, int len) +{ + FSMDEBUG((LOG_INFO, "fsm_rconfack(%s): Rcvd id %d state=%d (%s)\n", + PROTO_NAME(f), id, f->state, ppperr_strerr[f->state])); + + if (id != f->reqid || f->seen_ack) { /* Expected id? */ + return; /* Nope, toss... */ + } + if( !(f->callbacks->ackci? (*f->callbacks->ackci)(f, inp, len): (len == 0)) ) { + /* Ack is bad - ignore it */ + FSMDEBUG((LOG_INFO, "%s: received bad Ack (length %d)\n", + PROTO_NAME(f), len)); + return; + } + f->seen_ack = 1; + + switch (f->state) { + case LS_CLOSED: + case LS_STOPPED: + fsm_sdata(f, TERMACK, (u_char)id, NULL, 0); + break; + + case LS_REQSENT: + f->state = LS_ACKRCVD; + f->retransmits = f->maxconfreqtransmits; + break; + + case LS_ACKRCVD: + /* Huh? an extra valid Ack? oh well... */ + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + fsm_sconfreq(f, 0); + f->state = LS_REQSENT; + break; + + case LS_ACKSENT: + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + f->state = LS_OPENED; + f->retransmits = f->maxconfreqtransmits; + if (f->callbacks->up) { + (*f->callbacks->up)(f); /* Inform upper layers */ + } + break; + + case LS_OPENED: + /* Go down and restart negotiation */ + if (f->callbacks->down) { + (*f->callbacks->down)(f); /* Inform upper layers */ + } + fsm_sconfreq(f, 0); /* Send initial Configure-Request */ + f->state = LS_REQSENT; + break; + } +} + + +/* + * fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject. + */ +static void +fsm_rconfnakrej(fsm *f, int code, int id, u_char *inp, int len) +{ + int (*proc) (fsm *, u_char *, int); + int ret; + + FSMDEBUG((LOG_INFO, "fsm_rconfnakrej(%s): Rcvd id %d state=%d (%s)\n", + PROTO_NAME(f), id, f->state, ppperr_strerr[f->state])); + + if (id != f->reqid || f->seen_ack) { /* Expected id? */ + return; /* Nope, toss... */ + } + proc = (code == CONFNAK)? f->callbacks->nakci: f->callbacks->rejci; + if (!proc || !((ret = proc(f, inp, len)))) { + /* Nak/reject is bad - ignore it */ + FSMDEBUG((LOG_INFO, "%s: received bad %s (length %d)\n", + PROTO_NAME(f), (code==CONFNAK? "Nak": "reject"), len)); + return; + } + f->seen_ack = 1; + + switch (f->state) { + case LS_CLOSED: + case LS_STOPPED: + fsm_sdata(f, TERMACK, (u_char)id, NULL, 0); + break; + + case LS_REQSENT: + case LS_ACKSENT: + /* They didn't agree to what we wanted - try another request */ + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + if (ret < 0) { + f->state = LS_STOPPED; /* kludge for stopping CCP */ + } else { + fsm_sconfreq(f, 0); /* Send Configure-Request */ + } + break; + + case LS_ACKRCVD: + /* Got a Nak/reject when we had already had an Ack?? oh well... */ + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + fsm_sconfreq(f, 0); + f->state = LS_REQSENT; + break; + + case LS_OPENED: + /* Go down and restart negotiation */ + if (f->callbacks->down) { + (*f->callbacks->down)(f); /* Inform upper layers */ + } + fsm_sconfreq(f, 0); /* Send initial Configure-Request */ + f->state = LS_REQSENT; + break; + } +} + + +/* + * fsm_rtermreq - Receive Terminate-Req. + */ +static void +fsm_rtermreq(fsm *f, int id, u_char *p, int len) +{ + LWIP_UNUSED_ARG(p); + + FSMDEBUG((LOG_INFO, "fsm_rtermreq(%s): Rcvd id %d state=%d (%s)\n", + PROTO_NAME(f), id, f->state, ppperr_strerr[f->state])); + + switch (f->state) { + case LS_ACKRCVD: + case LS_ACKSENT: + f->state = LS_REQSENT; /* Start over but keep trying */ + break; + + case LS_OPENED: + if (len > 0) { + FSMDEBUG((LOG_INFO, "%s terminated by peer (%x)\n", PROTO_NAME(f), p)); + } else { + FSMDEBUG((LOG_INFO, "%s terminated by peer\n", PROTO_NAME(f))); + } + if (f->callbacks->down) { + (*f->callbacks->down)(f); /* Inform upper layers */ + } + f->retransmits = 0; + f->state = LS_STOPPING; + TIMEOUT(fsm_timeout, f, f->timeouttime); + break; + } + + fsm_sdata(f, TERMACK, (u_char)id, NULL, 0); +} + + +/* + * fsm_rtermack - Receive Terminate-Ack. + */ +static void +fsm_rtermack(fsm *f) +{ + FSMDEBUG((LOG_INFO, "fsm_rtermack(%s): state=%d (%s)\n", + PROTO_NAME(f), f->state, ppperr_strerr[f->state])); + + switch (f->state) { + case LS_CLOSING: + UNTIMEOUT(fsm_timeout, f); + f->state = LS_CLOSED; + if( f->callbacks->finished ) { + (*f->callbacks->finished)(f); + } + break; + + case LS_STOPPING: + UNTIMEOUT(fsm_timeout, f); + f->state = LS_STOPPED; + if( f->callbacks->finished ) { + (*f->callbacks->finished)(f); + } + break; + + case LS_ACKRCVD: + f->state = LS_REQSENT; + break; + + case LS_OPENED: + if (f->callbacks->down) { + (*f->callbacks->down)(f); /* Inform upper layers */ + } + fsm_sconfreq(f, 0); + break; + } +} + + +/* + * fsm_rcoderej - Receive an Code-Reject. + */ +static void +fsm_rcoderej(fsm *f, u_char *inp, int len) +{ + u_char code, id; + + FSMDEBUG((LOG_INFO, "fsm_rcoderej(%s): state=%d (%s)\n", + PROTO_NAME(f), f->state, ppperr_strerr[f->state])); + + if (len < HEADERLEN) { + FSMDEBUG((LOG_INFO, "fsm_rcoderej: Rcvd short Code-Reject packet!\n")); + return; + } + GETCHAR(code, inp); + GETCHAR(id, inp); + FSMDEBUG((LOG_WARNING, "%s: Rcvd Code-Reject for code %d, id %d\n", + PROTO_NAME(f), code, id)); + + if( f->state == LS_ACKRCVD ) { + f->state = LS_REQSENT; + } +} + + +/* + * fsm_sconfreq - Send a Configure-Request. + */ +static void +fsm_sconfreq(fsm *f, int retransmit) +{ + u_char *outp; + int cilen; + + if( f->state != LS_REQSENT && f->state != LS_ACKRCVD && f->state != LS_ACKSENT ) { + /* Not currently negotiating - reset options */ + if( f->callbacks->resetci ) { + (*f->callbacks->resetci)(f); + } + f->nakloops = 0; + } + + if( !retransmit ) { + /* New request - reset retransmission counter, use new ID */ + f->retransmits = f->maxconfreqtransmits; + f->reqid = ++f->id; + } + + f->seen_ack = 0; + + /* + * Make up the request packet + */ + outp = outpacket_buf[f->unit] + PPP_HDRLEN + HEADERLEN; + if( f->callbacks->cilen && f->callbacks->addci ) { + cilen = (*f->callbacks->cilen)(f); + if( cilen > peer_mru[f->unit] - (int)HEADERLEN ) { + cilen = peer_mru[f->unit] - HEADERLEN; + } + if (f->callbacks->addci) { + (*f->callbacks->addci)(f, outp, &cilen); + } + } else { + cilen = 0; + } + + /* send the request to our peer */ + fsm_sdata(f, CONFREQ, f->reqid, outp, cilen); + + /* start the retransmit timer */ + --f->retransmits; + TIMEOUT(fsm_timeout, f, f->timeouttime); + + FSMDEBUG((LOG_INFO, "%s: sending Configure-Request, id %d\n", + PROTO_NAME(f), f->reqid)); +} + +#endif /* PPP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/fsm.h b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/fsm.h new file mode 100644 index 0000000..14034ec --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/fsm.h @@ -0,0 +1,169 @@ +/***************************************************************************** +* fsm.h - Network Control Protocol Finite State Machine header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* Copyright (c) 1997 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-11-05 Guy Lancaster , Global Election Systems Inc. +* Original based on BSD code. +*****************************************************************************/ +/* + * fsm.h - {Link, IP} Control Protocol Finite State Machine definitions. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * $Id: fsm.h,v 1.4 2007/12/19 20:47:23 fbernon Exp $ + */ + +#ifndef FSM_H +#define FSM_H + +/***************************************************************************** +************************* PUBLIC DEFINITIONS ********************************* +*****************************************************************************/ +/* + * LCP Packet header = Code, id, length. + */ +#define HEADERLEN (sizeof (u_char) + sizeof (u_char) + sizeof (u_short)) + + +/* + * CP (LCP, IPCP, etc.) codes. + */ +#define CONFREQ 1 /* Configuration Request */ +#define CONFACK 2 /* Configuration Ack */ +#define CONFNAK 3 /* Configuration Nak */ +#define CONFREJ 4 /* Configuration Reject */ +#define TERMREQ 5 /* Termination Request */ +#define TERMACK 6 /* Termination Ack */ +#define CODEREJ 7 /* Code Reject */ + +/* + * Link states. + */ +#define LS_INITIAL 0 /* Down, hasn't been opened */ +#define LS_STARTING 1 /* Down, been opened */ +#define LS_CLOSED 2 /* Up, hasn't been opened */ +#define LS_STOPPED 3 /* Open, waiting for down event */ +#define LS_CLOSING 4 /* Terminating the connection, not open */ +#define LS_STOPPING 5 /* Terminating, but open */ +#define LS_REQSENT 6 /* We've sent a Config Request */ +#define LS_ACKRCVD 7 /* We've received a Config Ack */ +#define LS_ACKSENT 8 /* We've sent a Config Ack */ +#define LS_OPENED 9 /* Connection available */ + +/* + * Flags - indicate options controlling FSM operation + */ +#define OPT_PASSIVE 1 /* Don't die if we don't get a response */ +#define OPT_RESTART 2 /* Treat 2nd OPEN as DOWN, UP */ +#define OPT_SILENT 4 /* Wait for peer to speak first */ + + +/***************************************************************************** +************************* PUBLIC DATA TYPES ********************************** +*****************************************************************************/ +/* + * Each FSM is described by an fsm structure and fsm callbacks. + */ +typedef struct fsm { + int unit; /* Interface unit number */ + u_short protocol; /* Data Link Layer Protocol field value */ + int state; /* State */ + int flags; /* Contains option bits */ + u_char id; /* Current id */ + u_char reqid; /* Current request id */ + u_char seen_ack; /* Have received valid Ack/Nak/Rej to Req */ + int timeouttime; /* Timeout time in milliseconds */ + int maxconfreqtransmits; /* Maximum Configure-Request transmissions */ + int retransmits; /* Number of retransmissions left */ + int maxtermtransmits; /* Maximum Terminate-Request transmissions */ + int nakloops; /* Number of nak loops since last ack */ + int maxnakloops; /* Maximum number of nak loops tolerated */ + struct fsm_callbacks* callbacks; /* Callback routines */ + char* term_reason; /* Reason for closing protocol */ + int term_reason_len; /* Length of term_reason */ +} fsm; + + +typedef struct fsm_callbacks { + void (*resetci)(fsm*); /* Reset our Configuration Information */ + int (*cilen)(fsm*); /* Length of our Configuration Information */ + void (*addci)(fsm*, u_char*, int*); /* Add our Configuration Information */ + int (*ackci)(fsm*, u_char*, int); /* ACK our Configuration Information */ + int (*nakci)(fsm*, u_char*, int); /* NAK our Configuration Information */ + int (*rejci)(fsm*, u_char*, int); /* Reject our Configuration Information */ + int (*reqci)(fsm*, u_char*, int*, int); /* Request peer's Configuration Information */ + void (*up)(fsm*); /* Called when fsm reaches LS_OPENED state */ + void (*down)(fsm*); /* Called when fsm leaves LS_OPENED state */ + void (*starting)(fsm*); /* Called when we want the lower layer */ + void (*finished)(fsm*); /* Called when we don't want the lower layer */ + void (*protreject)(int); /* Called when Protocol-Reject received */ + void (*retransmit)(fsm*); /* Retransmission is necessary */ + int (*extcode)(fsm*, int, u_char, u_char*, int); /* Called when unknown code received */ + char *proto_name; /* String name for protocol (for messages) */ +} fsm_callbacks; + + +/***************************************************************************** +*********************** PUBLIC DATA STRUCTURES ******************************* +*****************************************************************************/ +/* + * Variables + */ +extern int peer_mru[]; /* currently negotiated peer MRU (per unit) */ + + +/***************************************************************************** +************************** PUBLIC FUNCTIONS ********************************** +*****************************************************************************/ + +/* + * Prototypes + */ +void fsm_init (fsm*); +void fsm_lowerup (fsm*); +void fsm_lowerdown (fsm*); +void fsm_open (fsm*); +void fsm_close (fsm*, char*); +void fsm_input (fsm*, u_char*, int); +void fsm_protreject (fsm*); +void fsm_sdata (fsm*, u_char, u_char, u_char*, int); + +#endif /* FSM_H */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/ipcp.c b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/ipcp.c new file mode 100644 index 0000000..0ff4ce3 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/ipcp.c @@ -0,0 +1,1427 @@ +/***************************************************************************** +* ipcp.c - Network PPP IP Control Protocol program file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 by Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-12-08 Guy Lancaster , Global Election Systems Inc. +* Original. +*****************************************************************************/ +/* + * ipcp.c - PPP IP Control Protocol. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "lwip/opt.h" + +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "ppp.h" +#include "pppdebug.h" + +#include "auth.h" +#include "fsm.h" +#include "vj.h" +#include "ipcp.h" + +#include + +/*************************/ +/*** LOCAL DEFINITIONS ***/ +/*************************/ +/* #define OLD_CI_ADDRS 1 */ /* Support deprecated address negotiation. */ + +/* + * Lengths of configuration options. + */ +#define CILEN_VOID 2 +#define CILEN_COMPRESS 4 /* min length for compression protocol opt. */ +#define CILEN_VJ 6 /* length for RFC1332 Van-Jacobson opt. */ +#define CILEN_ADDR 6 /* new-style single address option */ +#define CILEN_ADDRS 10 /* old-style dual address option */ + + + +/***********************************/ +/*** LOCAL FUNCTION DECLARATIONS ***/ +/***********************************/ +/* + * Callbacks for fsm code. (CI = Configuration Information) + */ +static void ipcp_resetci (fsm *); /* Reset our CI */ +static int ipcp_cilen (fsm *); /* Return length of our CI */ +static void ipcp_addci (fsm *, u_char *, int *); /* Add our CI */ +static int ipcp_ackci (fsm *, u_char *, int); /* Peer ack'd our CI */ +static int ipcp_nakci (fsm *, u_char *, int); /* Peer nak'd our CI */ +static int ipcp_rejci (fsm *, u_char *, int); /* Peer rej'd our CI */ +static int ipcp_reqci (fsm *, u_char *, int *, int); /* Rcv CI */ +static void ipcp_up (fsm *); /* We're UP */ +static void ipcp_down (fsm *); /* We're DOWN */ +#if 0 +static void ipcp_script (fsm *, char *); /* Run an up/down script */ +#endif +static void ipcp_finished (fsm *); /* Don't need lower layer */ + +/* + * Protocol entry points from main code. + */ +static void ipcp_init (int); +static void ipcp_open (int); +static void ipcp_close (int, char *); +static void ipcp_lowerup (int); +static void ipcp_lowerdown (int); +static void ipcp_input (int, u_char *, int); +static void ipcp_protrej (int); + +static void ipcp_clear_addrs (int); + +#define CODENAME(x) ((x) == CONFACK ? "ACK" : \ + (x) == CONFNAK ? "NAK" : "REJ") + + + +/******************************/ +/*** PUBLIC DATA STRUCTURES ***/ +/******************************/ +/* global vars */ +ipcp_options ipcp_wantoptions[NUM_PPP]; /* Options that we want to request */ +ipcp_options ipcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */ +ipcp_options ipcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */ +ipcp_options ipcp_hisoptions[NUM_PPP]; /* Options that we ack'd */ + +fsm ipcp_fsm[NUM_PPP]; /* IPCP fsm structure */ + +struct protent ipcp_protent = { + PPP_IPCP, + ipcp_init, + ipcp_input, + ipcp_protrej, + ipcp_lowerup, + ipcp_lowerdown, + ipcp_open, + ipcp_close, +#if 0 + ipcp_printpkt, + NULL, +#endif + 1, + "IPCP", +#if 0 + ip_check_options, + NULL, + ip_active_pkt +#endif +}; + + + +/*****************************/ +/*** LOCAL DATA STRUCTURES ***/ +/*****************************/ +/* local vars */ +static int cis_received[NUM_PPP]; /* # Conf-Reqs received */ +static int default_route_set[NUM_PPP]; /* Have set up a default route */ + +static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */ + ipcp_resetci, /* Reset our Configuration Information */ + ipcp_cilen, /* Length of our Configuration Information */ + ipcp_addci, /* Add our Configuration Information */ + ipcp_ackci, /* ACK our Configuration Information */ + ipcp_nakci, /* NAK our Configuration Information */ + ipcp_rejci, /* Reject our Configuration Information */ + ipcp_reqci, /* Request peer's Configuration Information */ + ipcp_up, /* Called when fsm reaches LS_OPENED state */ + ipcp_down, /* Called when fsm leaves LS_OPENED state */ + NULL, /* Called when we want the lower layer up */ + ipcp_finished, /* Called when we want the lower layer down */ + NULL, /* Called when Protocol-Reject received */ + NULL, /* Retransmission is necessary */ + NULL, /* Called to handle protocol-specific codes */ + "IPCP" /* String name of protocol */ +}; + + + +/**********************************/ +/*** LOCAL FUNCTION DEFINITIONS ***/ +/**********************************/ + +#define inet_ntoa(addr) ip_ntoa(((struct ip_addr*)&(addr))) + +/* + * ipcp_init - Initialize IPCP. + */ +static void +ipcp_init(int unit) +{ + fsm *f = &ipcp_fsm[unit]; + ipcp_options *wo = &ipcp_wantoptions[unit]; + ipcp_options *ao = &ipcp_allowoptions[unit]; + + f->unit = unit; + f->protocol = PPP_IPCP; + f->callbacks = &ipcp_callbacks; + fsm_init(&ipcp_fsm[unit]); + + memset(wo, 0, sizeof(*wo)); + memset(ao, 0, sizeof(*ao)); + + wo->neg_addr = 1; + wo->ouraddr = 0; +#if VJ_SUPPORT + wo->neg_vj = 1; +#else /* VJ_SUPPORT */ + wo->neg_vj = 0; +#endif /* VJ_SUPPORT */ + wo->vj_protocol = IPCP_VJ_COMP; + wo->maxslotindex = MAX_SLOTS - 1; + wo->cflag = 0; + wo->default_route = 1; + + ao->neg_addr = 1; +#if VJ_SUPPORT + ao->neg_vj = 1; +#else /* VJ_SUPPORT */ + ao->neg_vj = 0; +#endif /* VJ_SUPPORT */ + ao->maxslotindex = MAX_SLOTS - 1; + ao->cflag = 1; + ao->default_route = 1; +} + + +/* + * ipcp_open - IPCP is allowed to come up. + */ +static void +ipcp_open(int unit) +{ + fsm_open(&ipcp_fsm[unit]); +} + + +/* + * ipcp_close - Take IPCP down. + */ +static void +ipcp_close(int unit, char *reason) +{ + fsm_close(&ipcp_fsm[unit], reason); +} + + +/* + * ipcp_lowerup - The lower layer is up. + */ +static void +ipcp_lowerup(int unit) +{ + fsm_lowerup(&ipcp_fsm[unit]); +} + + +/* + * ipcp_lowerdown - The lower layer is down. + */ +static void +ipcp_lowerdown(int unit) +{ + fsm_lowerdown(&ipcp_fsm[unit]); +} + + +/* + * ipcp_input - Input IPCP packet. + */ +static void +ipcp_input(int unit, u_char *p, int len) +{ + fsm_input(&ipcp_fsm[unit], p, len); +} + + +/* + * ipcp_protrej - A Protocol-Reject was received for IPCP. + * + * Pretend the lower layer went down, so we shut up. + */ +static void +ipcp_protrej(int unit) +{ + fsm_lowerdown(&ipcp_fsm[unit]); +} + + +/* + * ipcp_resetci - Reset our CI. + */ +static void +ipcp_resetci(fsm *f) +{ + ipcp_options *wo = &ipcp_wantoptions[f->unit]; + + wo->req_addr = wo->neg_addr && ipcp_allowoptions[f->unit].neg_addr; + if (wo->ouraddr == 0) { + wo->accept_local = 1; + } + if (wo->hisaddr == 0) { + wo->accept_remote = 1; + } + /* Request DNS addresses from the peer */ + wo->req_dns1 = ppp_settings.usepeerdns; + wo->req_dns2 = ppp_settings.usepeerdns; + ipcp_gotoptions[f->unit] = *wo; + cis_received[f->unit] = 0; +} + + +/* + * ipcp_cilen - Return length of our CI. + */ +static int +ipcp_cilen(fsm *f) +{ + ipcp_options *go = &ipcp_gotoptions[f->unit]; + ipcp_options *wo = &ipcp_wantoptions[f->unit]; + ipcp_options *ho = &ipcp_hisoptions[f->unit]; + +#define LENCIVJ(neg, old) (neg ? (old? CILEN_COMPRESS : CILEN_VJ) : 0) +#define LENCIADDR(neg, old) (neg ? (old? CILEN_ADDRS : CILEN_ADDR) : 0) +#define LENCIDNS(neg) (neg ? (CILEN_ADDR) : 0) + + /* + * First see if we want to change our options to the old + * forms because we have received old forms from the peer. + */ + if (wo->neg_addr && !go->neg_addr && !go->old_addrs) { + /* use the old style of address negotiation */ + go->neg_addr = 1; + go->old_addrs = 1; + } + if (wo->neg_vj && !go->neg_vj && !go->old_vj) { + /* try an older style of VJ negotiation */ + if (cis_received[f->unit] == 0) { + /* keep trying the new style until we see some CI from the peer */ + go->neg_vj = 1; + } else { + /* use the old style only if the peer did */ + if (ho->neg_vj && ho->old_vj) { + go->neg_vj = 1; + go->old_vj = 1; + go->vj_protocol = ho->vj_protocol; + } + } + } + + return (LENCIADDR(go->neg_addr, go->old_addrs) + + LENCIVJ(go->neg_vj, go->old_vj) + + LENCIDNS(go->req_dns1) + + LENCIDNS(go->req_dns2)); +} + + +/* + * ipcp_addci - Add our desired CIs to a packet. + */ +static void +ipcp_addci(fsm *f, u_char *ucp, int *lenp) +{ + ipcp_options *go = &ipcp_gotoptions[f->unit]; + int len = *lenp; + +#define ADDCIVJ(opt, neg, val, old, maxslotindex, cflag) \ + if (neg) { \ + int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \ + if (len >= vjlen) { \ + PUTCHAR(opt, ucp); \ + PUTCHAR(vjlen, ucp); \ + PUTSHORT(val, ucp); \ + if (!old) { \ + PUTCHAR(maxslotindex, ucp); \ + PUTCHAR(cflag, ucp); \ + } \ + len -= vjlen; \ + } else { \ + neg = 0; \ + } \ + } + +#define ADDCIADDR(opt, neg, old, val1, val2) \ + if (neg) { \ + int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \ + if (len >= addrlen) { \ + u32_t l; \ + PUTCHAR(opt, ucp); \ + PUTCHAR(addrlen, ucp); \ + l = ntohl(val1); \ + PUTLONG(l, ucp); \ + if (old) { \ + l = ntohl(val2); \ + PUTLONG(l, ucp); \ + } \ + len -= addrlen; \ + } else { \ + neg = 0; \ + } \ + } + +#define ADDCIDNS(opt, neg, addr) \ + if (neg) { \ + if (len >= CILEN_ADDR) { \ + u32_t l; \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_ADDR, ucp); \ + l = ntohl(addr); \ + PUTLONG(l, ucp); \ + len -= CILEN_ADDR; \ + } else { \ + neg = 0; \ + } \ + } + + ADDCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr, + go->old_addrs, go->ouraddr, go->hisaddr); + + ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj, + go->maxslotindex, go->cflag); + + ADDCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]); + + ADDCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]); + + *lenp -= len; +} + + +/* + * ipcp_ackci - Ack our CIs. + * + * Returns: + * 0 - Ack was bad. + * 1 - Ack was good. + */ +static int +ipcp_ackci(fsm *f, u_char *p, int len) +{ + ipcp_options *go = &ipcp_gotoptions[f->unit]; + u_short cilen, citype, cishort; + u32_t cilong; + u_char cimaxslotindex, cicflag; + + /* + * CIs must be in exactly the same order that we sent... + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ + +#define ACKCIVJ(opt, neg, val, old, maxslotindex, cflag) \ + if (neg) { \ + int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \ + if ((len -= vjlen) < 0) { \ + goto bad; \ + } \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != vjlen || \ + citype != opt) { \ + goto bad; \ + } \ + GETSHORT(cishort, p); \ + if (cishort != val) { \ + goto bad; \ + } \ + if (!old) { \ + GETCHAR(cimaxslotindex, p); \ + if (cimaxslotindex != maxslotindex) { \ + goto bad; \ + } \ + GETCHAR(cicflag, p); \ + if (cicflag != cflag) { \ + goto bad; \ + } \ + } \ + } + +#define ACKCIADDR(opt, neg, old, val1, val2) \ + if (neg) { \ + int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \ + u32_t l; \ + if ((len -= addrlen) < 0) { \ + goto bad; \ + } \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != addrlen || \ + citype != opt) { \ + goto bad; \ + } \ + GETLONG(l, p); \ + cilong = htonl(l); \ + if (val1 != cilong) { \ + goto bad; \ + } \ + if (old) { \ + GETLONG(l, p); \ + cilong = htonl(l); \ + if (val2 != cilong) { \ + goto bad; \ + } \ + } \ + } + +#define ACKCIDNS(opt, neg, addr) \ + if (neg) { \ + u32_t l; \ + if ((len -= CILEN_ADDR) < 0) { \ + goto bad; \ + } \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_ADDR || \ + citype != opt) { \ + goto bad; \ + } \ + GETLONG(l, p); \ + cilong = htonl(l); \ + if (addr != cilong) { \ + goto bad; \ + } \ + } + + ACKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr, + go->old_addrs, go->ouraddr, go->hisaddr); + + ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj, + go->maxslotindex, go->cflag); + + ACKCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]); + + ACKCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]); + + /* + * If there are any remaining CIs, then this packet is bad. + */ + if (len != 0) { + goto bad; + } + return (1); + +bad: + IPCPDEBUG((LOG_INFO, "ipcp_ackci: received bad Ack!\n")); + return (0); +} + +/* + * ipcp_nakci - Peer has sent a NAK for some of our CIs. + * This should not modify any state if the Nak is bad + * or if IPCP is in the LS_OPENED state. + * + * Returns: + * 0 - Nak was bad. + * 1 - Nak was good. + */ +static int +ipcp_nakci(fsm *f, u_char *p, int len) +{ + ipcp_options *go = &ipcp_gotoptions[f->unit]; + u_char cimaxslotindex, cicflag; + u_char citype, cilen, *next; + u_short cishort; + u32_t ciaddr1, ciaddr2, l, cidnsaddr; + ipcp_options no; /* options we've seen Naks for */ + ipcp_options try; /* options to request next time */ + + BZERO(&no, sizeof(no)); + try = *go; + + /* + * Any Nak'd CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define NAKCIADDR(opt, neg, old, code) \ + if (go->neg && \ + len >= (cilen = (old? CILEN_ADDRS: CILEN_ADDR)) && \ + p[1] == cilen && \ + p[0] == opt) { \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + ciaddr1 = htonl(l); \ + if (old) { \ + GETLONG(l, p); \ + ciaddr2 = htonl(l); \ + no.old_addrs = 1; \ + } else { \ + ciaddr2 = 0; \ + } \ + no.neg = 1; \ + code \ + } + +#define NAKCIVJ(opt, neg, code) \ + if (go->neg && \ + ((cilen = p[1]) == CILEN_COMPRESS || cilen == CILEN_VJ) && \ + len >= cilen && \ + p[0] == opt) { \ + len -= cilen; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + no.neg = 1; \ + code \ + } + +#define NAKCIDNS(opt, neg, code) \ + if (go->neg && \ + ((cilen = p[1]) == CILEN_ADDR) && \ + len >= cilen && \ + p[0] == opt) { \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + cidnsaddr = htonl(l); \ + no.neg = 1; \ + code \ + } + + /* + * Accept the peer's idea of {our,his} address, if different + * from our idea, only if the accept_{local,remote} flag is set. + */ + NAKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr, go->old_addrs, + if (go->accept_local && ciaddr1) { /* Do we know our address? */ + try.ouraddr = ciaddr1; + IPCPDEBUG((LOG_INFO, "local IP address %s\n", + inet_ntoa(ciaddr1))); + } + if (go->accept_remote && ciaddr2) { /* Does he know his? */ + try.hisaddr = ciaddr2; + IPCPDEBUG((LOG_INFO, "remote IP address %s\n", + inet_ntoa(ciaddr2))); + } + ); + + /* + * Accept the peer's value of maxslotindex provided that it + * is less than what we asked for. Turn off slot-ID compression + * if the peer wants. Send old-style compress-type option if + * the peer wants. + */ + NAKCIVJ(CI_COMPRESSTYPE, neg_vj, + if (cilen == CILEN_VJ) { + GETCHAR(cimaxslotindex, p); + GETCHAR(cicflag, p); + if (cishort == IPCP_VJ_COMP) { + try.old_vj = 0; + if (cimaxslotindex < go->maxslotindex) { + try.maxslotindex = cimaxslotindex; + } + if (!cicflag) { + try.cflag = 0; + } + } else { + try.neg_vj = 0; + } + } else { + if (cishort == IPCP_VJ_COMP || cishort == IPCP_VJ_COMP_OLD) { + try.old_vj = 1; + try.vj_protocol = cishort; + } else { + try.neg_vj = 0; + } + } + ); + + NAKCIDNS(CI_MS_DNS1, req_dns1, + try.dnsaddr[0] = cidnsaddr; + IPCPDEBUG((LOG_INFO, "primary DNS address %s\n", inet_ntoa(cidnsaddr))); + ); + + NAKCIDNS(CI_MS_DNS2, req_dns2, + try.dnsaddr[1] = cidnsaddr; + IPCPDEBUG((LOG_INFO, "secondary DNS address %s\n", inet_ntoa(cidnsaddr))); + ); + + /* + * There may be remaining CIs, if the peer is requesting negotiation + * on an option that we didn't include in our request packet. + * If they want to negotiate about IP addresses, we comply. + * If they want us to ask for compression, we refuse. + */ + while (len > CILEN_VOID) { + GETCHAR(citype, p); + GETCHAR(cilen, p); + if( (len -= cilen) < 0 ) { + goto bad; + } + next = p + cilen - 2; + + switch (citype) { + case CI_COMPRESSTYPE: + if (go->neg_vj || no.neg_vj || + (cilen != CILEN_VJ && cilen != CILEN_COMPRESS)) { + goto bad; + } + no.neg_vj = 1; + break; + case CI_ADDRS: + if ((go->neg_addr && go->old_addrs) || no.old_addrs + || cilen != CILEN_ADDRS) { + goto bad; + } + try.neg_addr = 1; + try.old_addrs = 1; + GETLONG(l, p); + ciaddr1 = htonl(l); + if (ciaddr1 && go->accept_local) { + try.ouraddr = ciaddr1; + } + GETLONG(l, p); + ciaddr2 = htonl(l); + if (ciaddr2 && go->accept_remote) { + try.hisaddr = ciaddr2; + } + no.old_addrs = 1; + break; + case CI_ADDR: + if (go->neg_addr || no.neg_addr || cilen != CILEN_ADDR) { + goto bad; + } + try.old_addrs = 0; + GETLONG(l, p); + ciaddr1 = htonl(l); + if (ciaddr1 && go->accept_local) { + try.ouraddr = ciaddr1; + } + if (try.ouraddr != 0) { + try.neg_addr = 1; + } + no.neg_addr = 1; + break; + } + p = next; + } + + /* If there is still anything left, this packet is bad. */ + if (len != 0) { + goto bad; + } + + /* + * OK, the Nak is good. Now we can update state. + */ + if (f->state != LS_OPENED) { + *go = try; + } + + return 1; + +bad: + IPCPDEBUG((LOG_INFO, "ipcp_nakci: received bad Nak!\n")); + return 0; +} + + +/* + * ipcp_rejci - Reject some of our CIs. + */ +static int +ipcp_rejci(fsm *f, u_char *p, int len) +{ + ipcp_options *go = &ipcp_gotoptions[f->unit]; + u_char cimaxslotindex, ciflag, cilen; + u_short cishort; + u32_t cilong; + ipcp_options try; /* options to request next time */ + + try = *go; + /* + * Any Rejected CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define REJCIADDR(opt, neg, old, val1, val2) \ + if (go->neg && \ + len >= (cilen = old? CILEN_ADDRS: CILEN_ADDR) && \ + p[1] == cilen && \ + p[0] == opt) { \ + u32_t l; \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + cilong = htonl(l); \ + /* Check rejected value. */ \ + if (cilong != val1) { \ + goto bad; \ + } \ + if (old) { \ + GETLONG(l, p); \ + cilong = htonl(l); \ + /* Check rejected value. */ \ + if (cilong != val2) { \ + goto bad; \ + } \ + } \ + try.neg = 0; \ + } + +#define REJCIVJ(opt, neg, val, old, maxslot, cflag) \ + if (go->neg && \ + p[1] == (old? CILEN_COMPRESS : CILEN_VJ) && \ + len >= p[1] && \ + p[0] == opt) { \ + len -= p[1]; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + /* Check rejected value. */ \ + if (cishort != val) { \ + goto bad; \ + } \ + if (!old) { \ + GETCHAR(cimaxslotindex, p); \ + if (cimaxslotindex != maxslot) { \ + goto bad; \ + } \ + GETCHAR(ciflag, p); \ + if (ciflag != cflag) { \ + goto bad; \ + } \ + } \ + try.neg = 0; \ + } + +#define REJCIDNS(opt, neg, dnsaddr) \ + if (go->neg && \ + ((cilen = p[1]) == CILEN_ADDR) && \ + len >= cilen && \ + p[0] == opt) { \ + u32_t l; \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + cilong = htonl(l); \ + /* Check rejected value. */ \ + if (cilong != dnsaddr) { \ + goto bad; \ + } \ + try.neg = 0; \ + } + + REJCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr, + go->old_addrs, go->ouraddr, go->hisaddr); + + REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol, go->old_vj, + go->maxslotindex, go->cflag); + + REJCIDNS(CI_MS_DNS1, req_dns1, go->dnsaddr[0]); + + REJCIDNS(CI_MS_DNS2, req_dns2, go->dnsaddr[1]); + + /* + * If there are any remaining CIs, then this packet is bad. + */ + if (len != 0) { + goto bad; + } + /* + * Now we can update state. + */ + if (f->state != LS_OPENED) { + *go = try; + } + return 1; + +bad: + IPCPDEBUG((LOG_INFO, "ipcp_rejci: received bad Reject!\n")); + return 0; +} + + +/* + * ipcp_reqci - Check the peer's requested CIs and send appropriate response. + * + * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified + * appropriately. If reject_if_disagree is non-zero, doesn't return + * CONFNAK; returns CONFREJ if it can't return CONFACK. + */ +static int +ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested CIs */,int reject_if_disagree) +{ + ipcp_options *wo = &ipcp_wantoptions[f->unit]; + ipcp_options *ho = &ipcp_hisoptions[f->unit]; + ipcp_options *ao = &ipcp_allowoptions[f->unit]; +#ifdef OLD_CI_ADDRS + ipcp_options *go = &ipcp_gotoptions[f->unit]; +#endif + u_char *cip, *next; /* Pointer to current and next CIs */ + u_short cilen, citype; /* Parsed len, type */ + u_short cishort; /* Parsed short value */ + u32_t tl, ciaddr1; /* Parsed address values */ +#ifdef OLD_CI_ADDRS + u32_t ciaddr2; /* Parsed address values */ +#endif + int rc = CONFACK; /* Final packet return code */ + int orc; /* Individual option return code */ + u_char *p; /* Pointer to next char to parse */ + u_char *ucp = inp; /* Pointer to current output char */ + int l = *len; /* Length left */ + u_char maxslotindex, cflag; + int d; + + cis_received[f->unit] = 1; + + /* + * Reset all his options. + */ + BZERO(ho, sizeof(*ho)); + + /* + * Process all his options. + */ + next = inp; + while (l) { + orc = CONFACK; /* Assume success */ + cip = p = next; /* Remember begining of CI */ + if (l < 2 || /* Not enough data for CI header or */ + p[1] < 2 || /* CI length too small or */ + p[1] > l) { /* CI length too big? */ + IPCPDEBUG((LOG_INFO, "ipcp_reqci: bad CI length!\n")); + orc = CONFREJ; /* Reject bad CI */ + cilen = l; /* Reject till end of packet */ + l = 0; /* Don't loop again */ + goto endswitch; + } + GETCHAR(citype, p); /* Parse CI type */ + GETCHAR(cilen, p); /* Parse CI length */ + l -= cilen; /* Adjust remaining length */ + next += cilen; /* Step to next CI */ + + switch (citype) { /* Check CI type */ +#ifdef OLD_CI_ADDRS /* Need to save space... */ + case CI_ADDRS: + IPCPDEBUG((LOG_INFO, "ipcp_reqci: received ADDRS\n")); + if (!ao->neg_addr || + cilen != CILEN_ADDRS) { /* Check CI length */ + orc = CONFREJ; /* Reject CI */ + break; + } + + /* + * If he has no address, or if we both have his address but + * disagree about it, then NAK it with our idea. + * In particular, if we don't know his address, but he does, + * then accept it. + */ + GETLONG(tl, p); /* Parse source address (his) */ + ciaddr1 = htonl(tl); + IPCPDEBUG((LOG_INFO, "his addr %s\n", inet_ntoa(ciaddr1))); + if (ciaddr1 != wo->hisaddr + && (ciaddr1 == 0 || !wo->accept_remote)) { + orc = CONFNAK; + if (!reject_if_disagree) { + DECPTR(sizeof(u32_t), p); + tl = ntohl(wo->hisaddr); + PUTLONG(tl, p); + } + } else if (ciaddr1 == 0 && wo->hisaddr == 0) { + /* + * If neither we nor he knows his address, reject the option. + */ + orc = CONFREJ; + wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */ + break; + } + + /* + * If he doesn't know our address, or if we both have our address + * but disagree about it, then NAK it with our idea. + */ + GETLONG(tl, p); /* Parse desination address (ours) */ + ciaddr2 = htonl(tl); + IPCPDEBUG((LOG_INFO, "our addr %s\n", inet_ntoa(ciaddr2))); + if (ciaddr2 != wo->ouraddr) { + if (ciaddr2 == 0 || !wo->accept_local) { + orc = CONFNAK; + if (!reject_if_disagree) { + DECPTR(sizeof(u32_t), p); + tl = ntohl(wo->ouraddr); + PUTLONG(tl, p); + } + } else { + go->ouraddr = ciaddr2; /* accept peer's idea */ + } + } + + ho->neg_addr = 1; + ho->old_addrs = 1; + ho->hisaddr = ciaddr1; + ho->ouraddr = ciaddr2; + break; +#endif + + case CI_ADDR: + if (!ao->neg_addr) { + IPCPDEBUG((LOG_INFO, "ipcp_reqci: Reject ADDR not allowed\n")); + orc = CONFREJ; /* Reject CI */ + break; + } else if (cilen != CILEN_ADDR) { /* Check CI length */ + IPCPDEBUG((LOG_INFO, "ipcp_reqci: Reject ADDR bad len\n")); + orc = CONFREJ; /* Reject CI */ + break; + } + + /* + * If he has no address, or if we both have his address but + * disagree about it, then NAK it with our idea. + * In particular, if we don't know his address, but he does, + * then accept it. + */ + GETLONG(tl, p); /* Parse source address (his) */ + ciaddr1 = htonl(tl); + if (ciaddr1 != wo->hisaddr + && (ciaddr1 == 0 || !wo->accept_remote)) { + orc = CONFNAK; + if (!reject_if_disagree) { + DECPTR(sizeof(u32_t), p); + tl = ntohl(wo->hisaddr); + PUTLONG(tl, p); + } + IPCPDEBUG((LOG_INFO, "ipcp_reqci: Nak ADDR %s\n", inet_ntoa(ciaddr1))); + } else if (ciaddr1 == 0 && wo->hisaddr == 0) { + /* + * Don't ACK an address of 0.0.0.0 - reject it instead. + */ + IPCPDEBUG((LOG_INFO, "ipcp_reqci: Reject ADDR %s\n", inet_ntoa(ciaddr1))); + orc = CONFREJ; + wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */ + break; + } + + ho->neg_addr = 1; + ho->hisaddr = ciaddr1; + IPCPDEBUG((LOG_INFO, "ipcp_reqci: ADDR %s\n", inet_ntoa(ciaddr1))); + break; + + case CI_MS_DNS1: + case CI_MS_DNS2: + /* Microsoft primary or secondary DNS request */ + d = citype == CI_MS_DNS2; + + /* If we do not have a DNS address then we cannot send it */ + if (ao->dnsaddr[d] == 0 || + cilen != CILEN_ADDR) { /* Check CI length */ + IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting DNS%d Request\n", d+1)); + orc = CONFREJ; /* Reject CI */ + break; + } + GETLONG(tl, p); + if (htonl(tl) != ao->dnsaddr[d]) { + IPCPDEBUG((LOG_INFO, "ipcp_reqci: Naking DNS%d Request %d\n", + d+1, inet_ntoa(tl))); + DECPTR(sizeof(u32_t), p); + tl = ntohl(ao->dnsaddr[d]); + PUTLONG(tl, p); + orc = CONFNAK; + } + IPCPDEBUG((LOG_INFO, "ipcp_reqci: received DNS%d Request\n", d+1)); + break; + + case CI_MS_WINS1: + case CI_MS_WINS2: + /* Microsoft primary or secondary WINS request */ + d = citype == CI_MS_WINS2; + IPCPDEBUG((LOG_INFO, "ipcp_reqci: received WINS%d Request\n", d+1)); + + /* If we do not have a DNS address then we cannot send it */ + if (ao->winsaddr[d] == 0 || + cilen != CILEN_ADDR) { /* Check CI length */ + orc = CONFREJ; /* Reject CI */ + break; + } + GETLONG(tl, p); + if (htonl(tl) != ao->winsaddr[d]) { + DECPTR(sizeof(u32_t), p); + tl = ntohl(ao->winsaddr[d]); + PUTLONG(tl, p); + orc = CONFNAK; + } + break; + + case CI_COMPRESSTYPE: + if (!ao->neg_vj) { + IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting COMPRESSTYPE not allowed\n")); + orc = CONFREJ; + break; + } else if (cilen != CILEN_VJ && cilen != CILEN_COMPRESS) { + IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting COMPRESSTYPE len=%d\n", cilen)); + orc = CONFREJ; + break; + } + GETSHORT(cishort, p); + + if (!(cishort == IPCP_VJ_COMP || + (cishort == IPCP_VJ_COMP_OLD && cilen == CILEN_COMPRESS))) { + IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting COMPRESSTYPE %d\n", cishort)); + orc = CONFREJ; + break; + } + + ho->neg_vj = 1; + ho->vj_protocol = cishort; + if (cilen == CILEN_VJ) { + GETCHAR(maxslotindex, p); + if (maxslotindex > ao->maxslotindex) { + IPCPDEBUG((LOG_INFO, "ipcp_reqci: Naking VJ max slot %d\n", maxslotindex)); + orc = CONFNAK; + if (!reject_if_disagree) { + DECPTR(1, p); + PUTCHAR(ao->maxslotindex, p); + } + } + GETCHAR(cflag, p); + if (cflag && !ao->cflag) { + IPCPDEBUG((LOG_INFO, "ipcp_reqci: Naking VJ cflag %d\n", cflag)); + orc = CONFNAK; + if (!reject_if_disagree) { + DECPTR(1, p); + PUTCHAR(wo->cflag, p); + } + } + ho->maxslotindex = maxslotindex; + ho->cflag = cflag; + } else { + ho->old_vj = 1; + ho->maxslotindex = MAX_SLOTS - 1; + ho->cflag = 1; + } + IPCPDEBUG((LOG_INFO, + "ipcp_reqci: received COMPRESSTYPE p=%d old=%d maxslot=%d cflag=%d\n", + ho->vj_protocol, ho->old_vj, ho->maxslotindex, ho->cflag)); + break; + + default: + IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting unknown CI type %d\n", citype)); + orc = CONFREJ; + break; + } + +endswitch: + if (orc == CONFACK && /* Good CI */ + rc != CONFACK) { /* but prior CI wasnt? */ + continue; /* Don't send this one */ + } + + if (orc == CONFNAK) { /* Nak this CI? */ + if (reject_if_disagree) { /* Getting fed up with sending NAKs? */ + IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting too many naks\n")); + orc = CONFREJ; /* Get tough if so */ + } else { + if (rc == CONFREJ) { /* Rejecting prior CI? */ + continue; /* Don't send this one */ + } + if (rc == CONFACK) { /* Ack'd all prior CIs? */ + rc = CONFNAK; /* Not anymore... */ + ucp = inp; /* Backup */ + } + } + } + + if (orc == CONFREJ && /* Reject this CI */ + rc != CONFREJ) { /* but no prior ones? */ + rc = CONFREJ; + ucp = inp; /* Backup */ + } + + /* Need to move CI? */ + if (ucp != cip) { + BCOPY(cip, ucp, cilen); /* Move it */ + } + + /* Update output pointer */ + INCPTR(cilen, ucp); + } + + /* + * If we aren't rejecting this packet, and we want to negotiate + * their address, and they didn't send their address, then we + * send a NAK with a CI_ADDR option appended. We assume the + * input buffer is long enough that we can append the extra + * option safely. + */ + if (rc != CONFREJ && !ho->neg_addr && + wo->req_addr && !reject_if_disagree) { + IPCPDEBUG((LOG_INFO, "ipcp_reqci: Requesting peer address\n")); + if (rc == CONFACK) { + rc = CONFNAK; + ucp = inp; /* reset pointer */ + wo->req_addr = 0; /* don't ask again */ + } + PUTCHAR(CI_ADDR, ucp); + PUTCHAR(CILEN_ADDR, ucp); + tl = ntohl(wo->hisaddr); + PUTLONG(tl, ucp); + } + + *len = (int)(ucp - inp); /* Compute output length */ + IPCPDEBUG((LOG_INFO, "ipcp_reqci: returning Configure-%s\n", CODENAME(rc))); + return (rc); /* Return final code */ +} + + +#if 0 +/* + * ip_check_options - check that any IP-related options are OK, + * and assign appropriate defaults. + */ +static void +ip_check_options(u_long localAddr) +{ + ipcp_options *wo = &ipcp_wantoptions[0]; + + /* + * Load our default IP address but allow the remote host to give us + * a new address. + */ + if (wo->ouraddr == 0 && !ppp_settings.disable_defaultip) { + wo->accept_local = 1; /* don't insist on this default value */ + wo->ouraddr = htonl(localAddr); + } +} +#endif + + +/* + * ipcp_up - IPCP has come UP. + * + * Configure the IP network interface appropriately and bring it up. + */ +static void +ipcp_up(fsm *f) +{ + u32_t mask; + ipcp_options *ho = &ipcp_hisoptions[f->unit]; + ipcp_options *go = &ipcp_gotoptions[f->unit]; + ipcp_options *wo = &ipcp_wantoptions[f->unit]; + + np_up(f->unit, PPP_IP); + IPCPDEBUG((LOG_INFO, "ipcp: up\n")); + + /* + * We must have a non-zero IP address for both ends of the link. + */ + if (!ho->neg_addr) { + ho->hisaddr = wo->hisaddr; + } + + if (ho->hisaddr == 0) { + IPCPDEBUG((LOG_ERR, "Could not determine remote IP address\n")); + ipcp_close(f->unit, "Could not determine remote IP address"); + return; + } + if (go->ouraddr == 0) { + IPCPDEBUG((LOG_ERR, "Could not determine local IP address\n")); + ipcp_close(f->unit, "Could not determine local IP address"); + return; + } + + if (ppp_settings.usepeerdns && (go->dnsaddr[0] || go->dnsaddr[1])) { + /*pppGotDNSAddrs(go->dnsaddr[0], go->dnsaddr[1]);*/ + } + + /* + * Check that the peer is allowed to use the IP address it wants. + */ + if (!auth_ip_addr(f->unit, ho->hisaddr)) { + IPCPDEBUG((LOG_ERR, "Peer is not authorized to use remote address %s\n", + inet_ntoa(ho->hisaddr))); + ipcp_close(f->unit, "Unauthorized remote IP address"); + return; + } + + /* set tcp compression */ + sifvjcomp(f->unit, ho->neg_vj, ho->cflag, ho->maxslotindex); + + /* + * Set IP addresses and (if specified) netmask. + */ + mask = GetMask(go->ouraddr); + + if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask, go->dnsaddr[0], go->dnsaddr[1])) { + IPCPDEBUG((LOG_WARNING, "sifaddr failed\n")); + ipcp_close(f->unit, "Interface configuration failed"); + return; + } + + /* bring the interface up for IP */ + if (!sifup(f->unit)) { + IPCPDEBUG((LOG_WARNING, "sifup failed\n")); + ipcp_close(f->unit, "Interface configuration failed"); + return; + } + + sifnpmode(f->unit, PPP_IP, NPMODE_PASS); + + /* assign a default route through the interface if required */ + if (ipcp_wantoptions[f->unit].default_route) { + if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr)) { + default_route_set[f->unit] = 1; + } + } + + IPCPDEBUG((LOG_NOTICE, "local IP address %s\n", inet_ntoa(go->ouraddr))); + IPCPDEBUG((LOG_NOTICE, "remote IP address %s\n", inet_ntoa(ho->hisaddr))); + if (go->dnsaddr[0]) { + IPCPDEBUG((LOG_NOTICE, "primary DNS address %s\n", inet_ntoa(go->dnsaddr[0]))); + } + if (go->dnsaddr[1]) { + IPCPDEBUG((LOG_NOTICE, "secondary DNS address %s\n", inet_ntoa(go->dnsaddr[1]))); + } +} + + +/* + * ipcp_down - IPCP has gone DOWN. + * + * Take the IP network interface down, clear its addresses + * and delete routes through it. + */ +static void +ipcp_down(fsm *f) +{ + IPCPDEBUG((LOG_INFO, "ipcp: down\n")); + np_down(f->unit, PPP_IP); + sifvjcomp(f->unit, 0, 0, 0); + + sifdown(f->unit); + ipcp_clear_addrs(f->unit); +} + + +/* + * ipcp_clear_addrs() - clear the interface addresses, routes, etc. + */ +static void +ipcp_clear_addrs(int unit) +{ + u32_t ouraddr, hisaddr; + + ouraddr = ipcp_gotoptions[unit].ouraddr; + hisaddr = ipcp_hisoptions[unit].hisaddr; + if (default_route_set[unit]) { + cifdefaultroute(unit, ouraddr, hisaddr); + default_route_set[unit] = 0; + } + cifaddr(unit, ouraddr, hisaddr); +} + + +/* + * ipcp_finished - possibly shut down the lower layers. + */ +static void +ipcp_finished(fsm *f) +{ + np_finished(f->unit, PPP_IP); +} + +#if 0 +static int +ipcp_printpkt(u_char *p, int plen, void (*printer) (void *, char *, ...), void *arg) +{ + LWIP_UNUSED_ARG(p); + LWIP_UNUSED_ARG(plen); + LWIP_UNUSED_ARG(printer); + LWIP_UNUSED_ARG(arg); + return 0; +} + +/* + * ip_active_pkt - see if this IP packet is worth bringing the link up for. + * We don't bring the link up for IP fragments or for TCP FIN packets + * with no data. + */ +#define IP_HDRLEN 20 /* bytes */ +#define IP_OFFMASK 0x1fff +#define IPPROTO_TCP 6 +#define TCP_HDRLEN 20 +#define TH_FIN 0x01 + +/* + * We use these macros because the IP header may be at an odd address, + * and some compilers might use word loads to get th_off or ip_hl. + */ + +#define net_short(x) (((x)[0] << 8) + (x)[1]) +#define get_iphl(x) (((unsigned char *)(x))[0] & 0xF) +#define get_ipoff(x) net_short((unsigned char *)(x) + 6) +#define get_ipproto(x) (((unsigned char *)(x))[9]) +#define get_tcpoff(x) (((unsigned char *)(x))[12] >> 4) +#define get_tcpflags(x) (((unsigned char *)(x))[13]) + +static int +ip_active_pkt(u_char *pkt, int len) +{ + u_char *tcp; + int hlen; + + len -= PPP_HDRLEN; + pkt += PPP_HDRLEN; + if (len < IP_HDRLEN) { + return 0; + } + if ((get_ipoff(pkt) & IP_OFFMASK) != 0) { + return 0; + } + if (get_ipproto(pkt) != IPPROTO_TCP) { + return 1; + } + hlen = get_iphl(pkt) * 4; + if (len < hlen + TCP_HDRLEN) { + return 0; + } + tcp = pkt + hlen; + if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == hlen + get_tcpoff(tcp) * 4) { + return 0; + } + return 1; +} +#endif + +#endif /* PPP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/ipcp.h b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/ipcp.h new file mode 100644 index 0000000..dfcf4fb --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/ipcp.h @@ -0,0 +1,124 @@ +/***************************************************************************** +* ipcp.h - PPP IP NCP: Internet Protocol Network Control Protocol header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-12-04 Guy Lancaster , Global Election Systems Inc. +* Original derived from BSD codes. +*****************************************************************************/ +/* + * ipcp.h - IP Control Protocol definitions. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * $Id: ipcp.h,v 1.3 2007/12/19 20:47:23 fbernon Exp $ + */ + +#ifndef IPCP_H +#define IPCP_H + +/************************* +*** PUBLIC DEFINITIONS *** +*************************/ +/* + * Options. + */ +#define CI_ADDRS 1 /* IP Addresses */ +#define CI_COMPRESSTYPE 2 /* Compression Type */ +#define CI_ADDR 3 + +#define CI_MS_WINS1 128 /* Primary WINS value */ +#define CI_MS_DNS1 129 /* Primary DNS value */ +#define CI_MS_WINS2 130 /* Secondary WINS value */ +#define CI_MS_DNS2 131 /* Secondary DNS value */ + +#define IPCP_VJMODE_OLD 1 /* "old" mode (option # = 0x0037) */ +#define IPCP_VJMODE_RFC1172 2 /* "old-rfc"mode (option # = 0x002d) */ +#define IPCP_VJMODE_RFC1332 3 /* "new-rfc"mode (option # = 0x002d, */ + /* maxslot and slot number compression) */ + +#define IPCP_VJ_COMP 0x002d /* current value for VJ compression option */ +#define IPCP_VJ_COMP_OLD 0x0037 /* "old" (i.e, broken) value for VJ */ + /* compression option */ + + +/************************ +*** PUBLIC DATA TYPES *** +************************/ + +typedef struct ipcp_options { + u_int neg_addr : 1; /* Negotiate IP Address? */ + u_int old_addrs : 1; /* Use old (IP-Addresses) option? */ + u_int req_addr : 1; /* Ask peer to send IP address? */ + u_int default_route : 1; /* Assign default route through interface? */ + u_int proxy_arp : 1; /* Make proxy ARP entry for peer? */ + u_int neg_vj : 1; /* Van Jacobson Compression? */ + u_int old_vj : 1; /* use old (short) form of VJ option? */ + u_int accept_local : 1; /* accept peer's value for ouraddr */ + u_int accept_remote : 1; /* accept peer's value for hisaddr */ + u_int req_dns1 : 1; /* Ask peer to send primary DNS address? */ + u_int req_dns2 : 1; /* Ask peer to send secondary DNS address? */ + u_short vj_protocol; /* protocol value to use in VJ option */ + u_char maxslotindex; /* VJ slots - 1. */ + u_char cflag; /* VJ slot compression flag. */ + u32_t ouraddr, hisaddr; /* Addresses in NETWORK BYTE ORDER */ + u32_t dnsaddr[2]; /* Primary and secondary MS DNS entries */ + u32_t winsaddr[2]; /* Primary and secondary MS WINS entries */ +} ipcp_options; + + +/***************************** +*** PUBLIC DATA STRUCTURES *** +*****************************/ + +extern fsm ipcp_fsm[]; +extern ipcp_options ipcp_wantoptions[]; +extern ipcp_options ipcp_gotoptions[]; +extern ipcp_options ipcp_allowoptions[]; +extern ipcp_options ipcp_hisoptions[]; + +extern struct protent ipcp_protent; + + +/*********************** +*** PUBLIC FUNCTIONS *** +***********************/ + +#endif /* IPCP_H */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/lcp.c b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/lcp.c new file mode 100644 index 0000000..85a0add --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/lcp.c @@ -0,0 +1,2035 @@ +/***************************************************************************** +* lcp.c - Network Link Control Protocol program file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 by Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-12-01 Guy Lancaster , Global Election Systems Inc. +* Original. +*****************************************************************************/ + +/* + * lcp.c - PPP Link Control Protocol. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + + +#include "lwip/opt.h" + +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "ppp.h" +#include "pppdebug.h" + +#include "fsm.h" +#include "chap.h" +#include "magic.h" +#include "auth.h" +#include "lcp.h" + +#include + +#if PPPOE_SUPPORT +#include "netif/ppp_oe.h" +#else +#define PPPOE_MAXMTU PPP_MAXMRU +#endif + + +/*************************/ +/*** LOCAL DEFINITIONS ***/ +/*************************/ +/* + * Length of each type of configuration option (in octets) + */ +#define CILEN_VOID 2 +#define CILEN_CHAR 3 +#define CILEN_SHORT 4 /* CILEN_VOID + sizeof(short) */ +#define CILEN_CHAP 5 /* CILEN_VOID + sizeof(short) + 1 */ +#define CILEN_LONG 6 /* CILEN_VOID + sizeof(long) */ +#define CILEN_LQR 8 /* CILEN_VOID + sizeof(short) + sizeof(long) */ +#define CILEN_CBCP 3 + + +/***********************************/ +/*** LOCAL FUNCTION DECLARATIONS ***/ +/***********************************/ +/* + * Callbacks for fsm code. (CI = Configuration Information) + */ +static void lcp_resetci (fsm*); /* Reset our CI */ +static int lcp_cilen (fsm*); /* Return length of our CI */ +static void lcp_addci (fsm*, u_char*, int*); /* Add our CI to pkt */ +static int lcp_ackci (fsm*, u_char*, int); /* Peer ack'd our CI */ +static int lcp_nakci (fsm*, u_char*, int); /* Peer nak'd our CI */ +static int lcp_rejci (fsm*, u_char*, int); /* Peer rej'd our CI */ +static int lcp_reqci (fsm*, u_char*, int*, int); /* Rcv peer CI */ +static void lcp_up (fsm*); /* We're UP */ +static void lcp_down (fsm*); /* We're DOWN */ +static void lcp_starting (fsm*); /* We need lower layer up */ +static void lcp_finished (fsm*); /* We need lower layer down */ +static int lcp_extcode (fsm*, int, u_char, u_char*, int); + +static void lcp_rprotrej (fsm*, u_char*, int); + +/* + * routines to send LCP echos to peer + */ +static void lcp_echo_lowerup (int); +static void lcp_echo_lowerdown (int); +static void LcpEchoTimeout (void*); +static void lcp_received_echo_reply (fsm*, int, u_char*, int); +static void LcpSendEchoRequest (fsm*); +static void LcpLinkFailure (fsm*); +static void LcpEchoCheck (fsm*); + +/* + * Protocol entry points. + * Some of these are called directly. + */ +static void lcp_input (int, u_char *, int); +static void lcp_protrej (int); + +#define CODENAME(x) ((x) == CONFACK ? "ACK" : (x) == CONFNAK ? "NAK" : "REJ") + + +/******************************/ +/*** PUBLIC DATA STRUCTURES ***/ +/******************************/ +/* global vars */ +LinkPhase lcp_phase[NUM_PPP]; /* Phase of link session (RFC 1661) */ +lcp_options lcp_wantoptions[NUM_PPP]; /* Options that we want to request */ +lcp_options lcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */ +lcp_options lcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */ +lcp_options lcp_hisoptions[NUM_PPP]; /* Options that we ack'd */ +ext_accm xmit_accm[NUM_PPP]; /* extended transmit ACCM */ + + + +/*****************************/ +/*** LOCAL DATA STRUCTURES ***/ +/*****************************/ +static fsm lcp_fsm[NUM_PPP]; /* LCP fsm structure (global)*/ +static u_int lcp_echo_interval = LCP_ECHOINTERVAL; /* Interval between LCP echo-requests */ +static u_int lcp_echo_fails = LCP_MAXECHOFAILS; /* Tolerance to unanswered echo-requests */ +static u32_t lcp_echos_pending = 0; /* Number of outstanding echo msgs */ +static u32_t lcp_echo_number = 0; /* ID number of next echo frame */ +static u32_t lcp_echo_timer_running = 0; /* TRUE if a timer is running */ + +static u_char nak_buffer[PPP_MRU]; /* where we construct a nak packet */ + +static fsm_callbacks lcp_callbacks = { /* LCP callback routines */ + lcp_resetci, /* Reset our Configuration Information */ + lcp_cilen, /* Length of our Configuration Information */ + lcp_addci, /* Add our Configuration Information */ + lcp_ackci, /* ACK our Configuration Information */ + lcp_nakci, /* NAK our Configuration Information */ + lcp_rejci, /* Reject our Configuration Information */ + lcp_reqci, /* Request peer's Configuration Information */ + lcp_up, /* Called when fsm reaches LS_OPENED state */ + lcp_down, /* Called when fsm leaves LS_OPENED state */ + lcp_starting, /* Called when we want the lower layer up */ + lcp_finished, /* Called when we want the lower layer down */ + NULL, /* Called when Protocol-Reject received */ + NULL, /* Retransmission is necessary */ + lcp_extcode, /* Called to handle LCP-specific codes */ + "LCP" /* String name of protocol */ +}; + +struct protent lcp_protent = { + PPP_LCP, + lcp_init, + lcp_input, + lcp_protrej, + lcp_lowerup, + lcp_lowerdown, + lcp_open, + lcp_close, +#if 0 + lcp_printpkt, + NULL, +#endif + 1, + "LCP", +#if 0 + NULL, + NULL, + NULL +#endif +}; + +int lcp_loopbackfail = DEFLOOPBACKFAIL; + + + +/***********************************/ +/*** PUBLIC FUNCTION DEFINITIONS ***/ +/***********************************/ +/* + * lcp_init - Initialize LCP. + */ +void +lcp_init(int unit) +{ + fsm *f = &lcp_fsm[unit]; + lcp_options *wo = &lcp_wantoptions[unit]; + lcp_options *ao = &lcp_allowoptions[unit]; + + f->unit = unit; + f->protocol = PPP_LCP; + f->callbacks = &lcp_callbacks; + + fsm_init(f); + + wo->passive = 0; + wo->silent = 0; + wo->restart = 0; /* Set to 1 in kernels or multi-line implementations */ + wo->neg_mru = 1; + wo->mru = PPP_DEFMRU; + wo->neg_asyncmap = 1; + wo->asyncmap = 0x00000000l; /* Assume don't need to escape any ctl chars. */ + wo->neg_chap = 0; /* Set to 1 on server */ + wo->neg_upap = 0; /* Set to 1 on server */ + wo->chap_mdtype = CHAP_DIGEST_MD5; + wo->neg_magicnumber = 1; + wo->neg_pcompression = 1; + wo->neg_accompression = 1; + wo->neg_lqr = 0; /* no LQR implementation yet */ + wo->neg_cbcp = 0; + + ao->neg_mru = 1; + ao->mru = PPP_MAXMRU; + ao->neg_asyncmap = 1; + ao->asyncmap = 0x00000000l; /* Assume don't need to escape any ctl chars. */ + ao->neg_chap = (CHAP_SUPPORT != 0); + ao->chap_mdtype = CHAP_DIGEST_MD5; + ao->neg_upap = (PAP_SUPPORT != 0); + ao->neg_magicnumber = 1; + ao->neg_pcompression = 1; + ao->neg_accompression = 1; + ao->neg_lqr = 0; /* no LQR implementation yet */ + ao->neg_cbcp = (CBCP_SUPPORT != 0); + + /* + * Set transmit escape for the flag and escape characters plus anything + * set for the allowable options. + */ + memset(xmit_accm[unit], 0, sizeof(xmit_accm[0])); + xmit_accm[unit][15] = 0x60; + xmit_accm[unit][0] = (u_char)((ao->asyncmap & 0xFF)); + xmit_accm[unit][1] = (u_char)((ao->asyncmap >> 8) & 0xFF); + xmit_accm[unit][2] = (u_char)((ao->asyncmap >> 16) & 0xFF); + xmit_accm[unit][3] = (u_char)((ao->asyncmap >> 24) & 0xFF); + LCPDEBUG((LOG_INFO, "lcp_init: xmit_accm=%X %X %X %X\n", + xmit_accm[unit][0], + xmit_accm[unit][1], + xmit_accm[unit][2], + xmit_accm[unit][3])); + + lcp_phase[unit] = PHASE_INITIALIZE; +} + + +/* + * lcp_open - LCP is allowed to come up. + */ +void +lcp_open(int unit) +{ + fsm *f = &lcp_fsm[unit]; + lcp_options *wo = &lcp_wantoptions[unit]; + + f->flags = 0; + if (wo->passive) { + f->flags |= OPT_PASSIVE; + } + if (wo->silent) { + f->flags |= OPT_SILENT; + } + fsm_open(f); + + lcp_phase[unit] = PHASE_ESTABLISH; +} + + +/* + * lcp_close - Take LCP down. + */ +void +lcp_close(int unit, char *reason) +{ + fsm *f = &lcp_fsm[unit]; + + if (lcp_phase[unit] != PHASE_DEAD) { + lcp_phase[unit] = PHASE_TERMINATE; + } + if (f->state == LS_STOPPED && f->flags & (OPT_PASSIVE|OPT_SILENT)) { + /* + * This action is not strictly according to the FSM in RFC1548, + * but it does mean that the program terminates if you do an + * lcp_close() in passive/silent mode when a connection hasn't + * been established. + */ + f->state = LS_CLOSED; + lcp_finished(f); + } else { + fsm_close(&lcp_fsm[unit], reason); + } +} + + +/* + * lcp_lowerup - The lower layer is up. + */ +void +lcp_lowerup(int unit) +{ + lcp_options *wo = &lcp_wantoptions[unit]; + + /* + * Don't use A/C or protocol compression on transmission, + * but accept A/C and protocol compressed packets + * if we are going to ask for A/C and protocol compression. + */ + ppp_set_xaccm(unit, &xmit_accm[unit]); + ppp_send_config(unit, PPP_MRU, 0xffffffffl, 0, 0); + ppp_recv_config(unit, PPP_MRU, 0x00000000l, + wo->neg_pcompression, wo->neg_accompression); + peer_mru[unit] = PPP_MRU; + lcp_allowoptions[unit].asyncmap = (u_long)xmit_accm[unit][0] + | ((u_long)xmit_accm[unit][1] << 8) + | ((u_long)xmit_accm[unit][2] << 16) + | ((u_long)xmit_accm[unit][3] << 24); + LCPDEBUG((LOG_INFO, "lcp_lowerup: asyncmap=%X %X %X %X\n", + xmit_accm[unit][3], + xmit_accm[unit][2], + xmit_accm[unit][1], + xmit_accm[unit][0])); + + fsm_lowerup(&lcp_fsm[unit]); +} + + +/* + * lcp_lowerdown - The lower layer is down. + */ +void +lcp_lowerdown(int unit) +{ + fsm_lowerdown(&lcp_fsm[unit]); +} + +/* + * lcp_sprotrej - Send a Protocol-Reject for some protocol. + */ +void +lcp_sprotrej(int unit, u_char *p, int len) +{ + /* + * Send back the protocol and the information field of the + * rejected packet. We only get here if LCP is in the LS_OPENED state. + */ + + fsm_sdata(&lcp_fsm[unit], PROTREJ, ++lcp_fsm[unit].id, p, len); +} + + + +/**********************************/ +/*** LOCAL FUNCTION DEFINITIONS ***/ +/**********************************/ +/* + * lcp_input - Input LCP packet. + */ +static void +lcp_input(int unit, u_char *p, int len) +{ + fsm *f = &lcp_fsm[unit]; + + fsm_input(f, p, len); +} + + +/* + * lcp_extcode - Handle a LCP-specific code. + */ +static int +lcp_extcode(fsm *f, int code, u_char id, u_char *inp, int len) +{ + u_char *magp; + + switch( code ){ + case PROTREJ: + lcp_rprotrej(f, inp, len); + break; + + case ECHOREQ: + if (f->state != LS_OPENED) { + break; + } + LCPDEBUG((LOG_INFO, "lcp: Echo-Request, Rcvd id %d\n", id)); + magp = inp; + PUTLONG(lcp_gotoptions[f->unit].magicnumber, magp); + fsm_sdata(f, ECHOREP, id, inp, len); + break; + + case ECHOREP: + lcp_received_echo_reply(f, id, inp, len); + break; + + case DISCREQ: + break; + + default: + return 0; + } + return 1; +} + + +/* + * lcp_rprotrej - Receive an Protocol-Reject. + * + * Figure out which protocol is rejected and inform it. + */ +static void +lcp_rprotrej(fsm *f, u_char *inp, int len) +{ + int i; + struct protent *protp; + u_short prot; + + if (len < sizeof (u_short)) { + LCPDEBUG((LOG_INFO, "lcp_rprotrej: Rcvd short Protocol-Reject packet!\n")); + return; + } + + GETSHORT(prot, inp); + + LCPDEBUG((LOG_INFO, "lcp_rprotrej: Rcvd Protocol-Reject packet for %x!\n", prot)); + + /* + * Protocol-Reject packets received in any state other than the LCP + * LS_OPENED state SHOULD be silently discarded. + */ + if( f->state != LS_OPENED ) { + LCPDEBUG((LOG_INFO, "Protocol-Reject discarded: LCP in state %d\n", f->state)); + return; + } + + /* + * Upcall the proper Protocol-Reject routine. + */ + for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) { + if (protp->protocol == prot && protp->enabled_flag) { + (*protp->protrej)(f->unit); + return; + } + } + + LCPDEBUG((LOG_WARNING, "Protocol-Reject for unsupported protocol 0x%x\n", prot)); +} + + +/* + * lcp_protrej - A Protocol-Reject was received. + */ +static void +lcp_protrej(int unit) +{ + LWIP_UNUSED_ARG(unit); + /* + * Can't reject LCP! + */ + LCPDEBUG((LOG_WARNING, "lcp_protrej: Received Protocol-Reject for LCP!\n")); + fsm_protreject(&lcp_fsm[unit]); +} + + +/* + * lcp_resetci - Reset our CI. + */ +static void +lcp_resetci(fsm *f) +{ + lcp_wantoptions[f->unit].magicnumber = magic(); + lcp_wantoptions[f->unit].numloops = 0; + lcp_gotoptions[f->unit] = lcp_wantoptions[f->unit]; + peer_mru[f->unit] = PPP_MRU; + auth_reset(f->unit); +} + + +/* + * lcp_cilen - Return length of our CI. + */ +static int lcp_cilen(fsm *f) +{ + lcp_options *go = &lcp_gotoptions[f->unit]; + +#define LENCIVOID(neg) ((neg) ? CILEN_VOID : 0) +#define LENCICHAP(neg) ((neg) ? CILEN_CHAP : 0) +#define LENCISHORT(neg) ((neg) ? CILEN_SHORT : 0) +#define LENCILONG(neg) ((neg) ? CILEN_LONG : 0) +#define LENCILQR(neg) ((neg) ? CILEN_LQR: 0) +#define LENCICBCP(neg) ((neg) ? CILEN_CBCP: 0) + /* + * NB: we only ask for one of CHAP and UPAP, even if we will + * accept either. + */ + return (LENCISHORT(go->neg_mru && go->mru != PPP_DEFMRU) + + LENCILONG(go->neg_asyncmap && go->asyncmap != 0xFFFFFFFFl) + + LENCICHAP(go->neg_chap) + + LENCISHORT(!go->neg_chap && go->neg_upap) + + LENCILQR(go->neg_lqr) + + LENCICBCP(go->neg_cbcp) + + LENCILONG(go->neg_magicnumber) + + LENCIVOID(go->neg_pcompression) + + LENCIVOID(go->neg_accompression)); +} + + +/* + * lcp_addci - Add our desired CIs to a packet. + */ +static void +lcp_addci(fsm *f, u_char *ucp, int *lenp) +{ + lcp_options *go = &lcp_gotoptions[f->unit]; + u_char *start_ucp = ucp; + +#define ADDCIVOID(opt, neg) \ + if (neg) { \ + LCPDEBUG((LOG_INFO, "lcp_addci: opt=%d\n", opt)); \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_VOID, ucp); \ + } +#define ADDCISHORT(opt, neg, val) \ + if (neg) { \ + LCPDEBUG((LOG_INFO, "lcp_addci: INT opt=%d %X\n", opt, val)); \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_SHORT, ucp); \ + PUTSHORT(val, ucp); \ + } +#define ADDCICHAP(opt, neg, val, digest) \ + if (neg) { \ + LCPDEBUG((LOG_INFO, "lcp_addci: CHAP opt=%d %X\n", opt, val)); \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_CHAP, ucp); \ + PUTSHORT(val, ucp); \ + PUTCHAR(digest, ucp); \ + } +#define ADDCILONG(opt, neg, val) \ + if (neg) { \ + LCPDEBUG((LOG_INFO, "lcp_addci: L opt=%d %lX\n", opt, val)); \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_LONG, ucp); \ + PUTLONG(val, ucp); \ + } +#define ADDCILQR(opt, neg, val) \ + if (neg) { \ + LCPDEBUG((LOG_INFO, "lcp_addci: LQR opt=%d %lX\n", opt, val)); \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_LQR, ucp); \ + PUTSHORT(PPP_LQR, ucp); \ + PUTLONG(val, ucp); \ + } +#define ADDCICHAR(opt, neg, val) \ + if (neg) { \ + LCPDEBUG((LOG_INFO, "lcp_addci: CHAR opt=%d %X '%z'\n", opt, val, val)); \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_CHAR, ucp); \ + PUTCHAR(val, ucp); \ + } + + ADDCISHORT(CI_MRU, go->neg_mru && go->mru != PPP_DEFMRU, go->mru); + ADDCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFFl, go->asyncmap); + ADDCICHAP(CI_AUTHTYPE, go->neg_chap, PPP_CHAP, go->chap_mdtype); + ADDCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP); + ADDCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period); + ADDCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT); + ADDCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber); + ADDCIVOID(CI_PCOMPRESSION, go->neg_pcompression); + ADDCIVOID(CI_ACCOMPRESSION, go->neg_accompression); + + if (ucp - start_ucp != *lenp) { + /* this should never happen, because peer_mtu should be 1500 */ + LCPDEBUG((LOG_ERR, "Bug in lcp_addci: wrong length\n")); + } +} + + +/* + * lcp_ackci - Ack our CIs. + * This should not modify any state if the Ack is bad. + * + * Returns: + * 0 - Ack was bad. + * 1 - Ack was good. + */ +static int +lcp_ackci(fsm *f, u_char *p, int len) +{ + lcp_options *go = &lcp_gotoptions[f->unit]; + u_char cilen, citype, cichar; + u_short cishort; + u32_t cilong; + + /* + * CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define ACKCIVOID(opt, neg) \ + if (neg) { \ + if ((len -= CILEN_VOID) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_VOID || citype != opt) \ + goto bad; \ + } +#define ACKCISHORT(opt, neg, val) \ + if (neg) { \ + if ((len -= CILEN_SHORT) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_SHORT || citype != opt) \ + goto bad; \ + GETSHORT(cishort, p); \ + if (cishort != val) \ + goto bad; \ + } +#define ACKCICHAR(opt, neg, val) \ + if (neg) { \ + if ((len -= CILEN_CHAR) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_CHAR || citype != opt) \ + goto bad; \ + GETCHAR(cichar, p); \ + if (cichar != val) \ + goto bad; \ + } +#define ACKCICHAP(opt, neg, val, digest) \ + if (neg) { \ + if ((len -= CILEN_CHAP) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_CHAP || citype != opt) \ + goto bad; \ + GETSHORT(cishort, p); \ + if (cishort != val) \ + goto bad; \ + GETCHAR(cichar, p); \ + if (cichar != digest) \ + goto bad; \ + } +#define ACKCILONG(opt, neg, val) \ + if (neg) { \ + if ((len -= CILEN_LONG) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_LONG || citype != opt) \ + goto bad; \ + GETLONG(cilong, p); \ + if (cilong != val) \ + goto bad; \ + } +#define ACKCILQR(opt, neg, val) \ + if (neg) { \ + if ((len -= CILEN_LQR) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_LQR || citype != opt) \ + goto bad; \ + GETSHORT(cishort, p); \ + if (cishort != PPP_LQR) \ + goto bad; \ + GETLONG(cilong, p); \ + if (cilong != val) \ + goto bad; \ + } + + ACKCISHORT(CI_MRU, go->neg_mru && go->mru != PPP_DEFMRU, go->mru); + ACKCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFFl, go->asyncmap); + ACKCICHAP(CI_AUTHTYPE, go->neg_chap, PPP_CHAP, go->chap_mdtype); + ACKCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP); + ACKCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period); + ACKCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT); + ACKCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber); + ACKCIVOID(CI_PCOMPRESSION, go->neg_pcompression); + ACKCIVOID(CI_ACCOMPRESSION, go->neg_accompression); + + /* + * If there are any remaining CIs, then this packet is bad. + */ + if (len != 0) { + goto bad; + } + LCPDEBUG((LOG_INFO, "lcp_acki: Ack\n")); + return (1); +bad: + LCPDEBUG((LOG_WARNING, "lcp_acki: received bad Ack!\n")); + return (0); +} + + +/* + * lcp_nakci - Peer has sent a NAK for some of our CIs. + * This should not modify any state if the Nak is bad + * or if LCP is in the LS_OPENED state. + * + * Returns: + * 0 - Nak was bad. + * 1 - Nak was good. + */ +static int +lcp_nakci(fsm *f, u_char *p, int len) +{ + lcp_options *go = &lcp_gotoptions[f->unit]; + lcp_options *wo = &lcp_wantoptions[f->unit]; + u_char citype, cichar, *next; + u_short cishort; + u32_t cilong; + lcp_options no; /* options we've seen Naks for */ + lcp_options try; /* options to request next time */ + int looped_back = 0; + int cilen; + + BZERO(&no, sizeof(no)); + try = *go; + + /* + * Any Nak'd CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define NAKCIVOID(opt, neg, code) \ + if (go->neg && \ + len >= CILEN_VOID && \ + p[1] == CILEN_VOID && \ + p[0] == opt) { \ + len -= CILEN_VOID; \ + INCPTR(CILEN_VOID, p); \ + no.neg = 1; \ + code \ + } +#define NAKCICHAP(opt, neg, code) \ + if (go->neg && \ + len >= CILEN_CHAP && \ + p[1] == CILEN_CHAP && \ + p[0] == opt) { \ + len -= CILEN_CHAP; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETCHAR(cichar, p); \ + no.neg = 1; \ + code \ + } +#define NAKCICHAR(opt, neg, code) \ + if (go->neg && \ + len >= CILEN_CHAR && \ + p[1] == CILEN_CHAR && \ + p[0] == opt) { \ + len -= CILEN_CHAR; \ + INCPTR(2, p); \ + GETCHAR(cichar, p); \ + no.neg = 1; \ + code \ + } +#define NAKCISHORT(opt, neg, code) \ + if (go->neg && \ + len >= CILEN_SHORT && \ + p[1] == CILEN_SHORT && \ + p[0] == opt) { \ + len -= CILEN_SHORT; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + no.neg = 1; \ + code \ + } +#define NAKCILONG(opt, neg, code) \ + if (go->neg && \ + len >= CILEN_LONG && \ + p[1] == CILEN_LONG && \ + p[0] == opt) { \ + len -= CILEN_LONG; \ + INCPTR(2, p); \ + GETLONG(cilong, p); \ + no.neg = 1; \ + code \ + } +#define NAKCILQR(opt, neg, code) \ + if (go->neg && \ + len >= CILEN_LQR && \ + p[1] == CILEN_LQR && \ + p[0] == opt) { \ + len -= CILEN_LQR; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETLONG(cilong, p); \ + no.neg = 1; \ + code \ + } + + /* + * We don't care if they want to send us smaller packets than + * we want. Therefore, accept any MRU less than what we asked for, + * but then ignore the new value when setting the MRU in the kernel. + * If they send us a bigger MRU than what we asked, accept it, up to + * the limit of the default MRU we'd get if we didn't negotiate. + */ + if (go->neg_mru && go->mru != PPP_DEFMRU) { + NAKCISHORT(CI_MRU, neg_mru, + if (cishort <= wo->mru || cishort < PPP_DEFMRU) { + try.mru = cishort; + } + ); + } + + /* + * Add any characters they want to our (receive-side) asyncmap. + */ + if (go->neg_asyncmap && go->asyncmap != 0xFFFFFFFFl) { + NAKCILONG(CI_ASYNCMAP, neg_asyncmap, + try.asyncmap = go->asyncmap | cilong; + ); + } + + /* + * If they've nak'd our authentication-protocol, check whether + * they are proposing a different protocol, or a different + * hash algorithm for CHAP. + */ + if ((go->neg_chap || go->neg_upap) + && len >= CILEN_SHORT + && p[0] == CI_AUTHTYPE && p[1] >= CILEN_SHORT && p[1] <= len) { + cilen = p[1]; + len -= cilen; + no.neg_chap = go->neg_chap; + no.neg_upap = go->neg_upap; + INCPTR(2, p); + GETSHORT(cishort, p); + if (cishort == PPP_PAP && cilen == CILEN_SHORT) { + /* + * If we were asking for CHAP, they obviously don't want to do it. + * If we weren't asking for CHAP, then we were asking for PAP, + * in which case this Nak is bad. + */ + if (!go->neg_chap) { + goto bad; + } + try.neg_chap = 0; + + } else if (cishort == PPP_CHAP && cilen == CILEN_CHAP) { + GETCHAR(cichar, p); + if (go->neg_chap) { + /* + * We were asking for CHAP/MD5; they must want a different + * algorithm. If they can't do MD5, we'll have to stop + * asking for CHAP. + */ + if (cichar != go->chap_mdtype) { + try.neg_chap = 0; + } + } else { + /* + * Stop asking for PAP if we were asking for it. + */ + try.neg_upap = 0; + } + + } else { + /* + * We don't recognize what they're suggesting. + * Stop asking for what we were asking for. + */ + if (go->neg_chap) { + try.neg_chap = 0; + } else { + try.neg_upap = 0; + } + p += cilen - CILEN_SHORT; + } + } + + /* + * If they can't cope with our link quality protocol, we'll have + * to stop asking for LQR. We haven't got any other protocol. + * If they Nak the reporting period, take their value XXX ? + */ + NAKCILQR(CI_QUALITY, neg_lqr, + if (cishort != PPP_LQR) { + try.neg_lqr = 0; + } else { + try.lqr_period = cilong; + } + ); + + /* + * Only implementing CBCP...not the rest of the callback options + */ + NAKCICHAR(CI_CALLBACK, neg_cbcp, + try.neg_cbcp = 0; + ); + + /* + * Check for a looped-back line. + */ + NAKCILONG(CI_MAGICNUMBER, neg_magicnumber, + try.magicnumber = magic(); + looped_back = 1; + ); + + /* + * Peer shouldn't send Nak for protocol compression or + * address/control compression requests; they should send + * a Reject instead. If they send a Nak, treat it as a Reject. + */ + NAKCIVOID(CI_PCOMPRESSION, neg_pcompression, + try.neg_pcompression = 0; + ); + NAKCIVOID(CI_ACCOMPRESSION, neg_accompression, + try.neg_accompression = 0; + ); + + /* + * There may be remaining CIs, if the peer is requesting negotiation + * on an option that we didn't include in our request packet. + * If we see an option that we requested, or one we've already seen + * in this packet, then this packet is bad. + * If we wanted to respond by starting to negotiate on the requested + * option(s), we could, but we don't, because except for the + * authentication type and quality protocol, if we are not negotiating + * an option, it is because we were told not to. + * For the authentication type, the Nak from the peer means + * `let me authenticate myself with you' which is a bit pointless. + * For the quality protocol, the Nak means `ask me to send you quality + * reports', but if we didn't ask for them, we don't want them. + * An option we don't recognize represents the peer asking to + * negotiate some option we don't support, so ignore it. + */ + while (len > CILEN_VOID) { + GETCHAR(citype, p); + GETCHAR(cilen, p); + if (cilen < CILEN_VOID || (len -= cilen) < 0) { + goto bad; + } + next = p + cilen - 2; + + switch (citype) { + case CI_MRU: + if ((go->neg_mru && go->mru != PPP_DEFMRU) + || no.neg_mru || cilen != CILEN_SHORT) { + goto bad; + } + GETSHORT(cishort, p); + if (cishort < PPP_DEFMRU) { + try.mru = cishort; + } + break; + case CI_ASYNCMAP: + if ((go->neg_asyncmap && go->asyncmap != 0xFFFFFFFFl) + || no.neg_asyncmap || cilen != CILEN_LONG) { + goto bad; + } + break; + case CI_AUTHTYPE: + if (go->neg_chap || no.neg_chap || go->neg_upap || no.neg_upap) { + goto bad; + } + break; + case CI_MAGICNUMBER: + if (go->neg_magicnumber || no.neg_magicnumber || + cilen != CILEN_LONG) { + goto bad; + } + break; + case CI_PCOMPRESSION: + if (go->neg_pcompression || no.neg_pcompression + || cilen != CILEN_VOID) { + goto bad; + } + break; + case CI_ACCOMPRESSION: + if (go->neg_accompression || no.neg_accompression + || cilen != CILEN_VOID) { + goto bad; + } + break; + case CI_QUALITY: + if (go->neg_lqr || no.neg_lqr || cilen != CILEN_LQR) { + goto bad; + } + break; + } + p = next; + } + + /* If there is still anything left, this packet is bad. */ + if (len != 0) { + goto bad; + } + + /* + * OK, the Nak is good. Now we can update state. + */ + if (f->state != LS_OPENED) { + if (looped_back) { + if (++try.numloops >= lcp_loopbackfail) { + LCPDEBUG((LOG_NOTICE, "Serial line is looped back.\n")); + lcp_close(f->unit, "Loopback detected"); + } + } else { + try.numloops = 0; + } + *go = try; + } + + return 1; + +bad: + LCPDEBUG((LOG_WARNING, "lcp_nakci: received bad Nak!\n")); + return 0; +} + + +/* + * lcp_rejci - Peer has Rejected some of our CIs. + * This should not modify any state if the Reject is bad + * or if LCP is in the LS_OPENED state. + * + * Returns: + * 0 - Reject was bad. + * 1 - Reject was good. + */ +static int +lcp_rejci(fsm *f, u_char *p, int len) +{ + lcp_options *go = &lcp_gotoptions[f->unit]; + u_char cichar; + u_short cishort; + u32_t cilong; + lcp_options try; /* options to request next time */ + + try = *go; + + /* + * Any Rejected CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define REJCIVOID(opt, neg) \ + if (go->neg && \ + len >= CILEN_VOID && \ + p[1] == CILEN_VOID && \ + p[0] == opt) { \ + len -= CILEN_VOID; \ + INCPTR(CILEN_VOID, p); \ + try.neg = 0; \ + LCPDEBUG((LOG_INFO, "lcp_rejci: void opt %d rejected\n", opt)); \ + } +#define REJCISHORT(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_SHORT && \ + p[1] == CILEN_SHORT && \ + p[0] == opt) { \ + len -= CILEN_SHORT; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + /* Check rejected value. */ \ + if (cishort != val) { \ + goto bad; \ + } \ + try.neg = 0; \ + LCPDEBUG((LOG_INFO,"lcp_rejci: short opt %d rejected\n", opt)); \ + } +#define REJCICHAP(opt, neg, val, digest) \ + if (go->neg && \ + len >= CILEN_CHAP && \ + p[1] == CILEN_CHAP && \ + p[0] == opt) { \ + len -= CILEN_CHAP; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETCHAR(cichar, p); \ + /* Check rejected value. */ \ + if (cishort != val || cichar != digest) { \ + goto bad; \ + } \ + try.neg = 0; \ + try.neg_upap = 0; \ + LCPDEBUG((LOG_INFO,"lcp_rejci: chap opt %d rejected\n", opt)); \ + } +#define REJCILONG(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_LONG && \ + p[1] == CILEN_LONG && \ + p[0] == opt) { \ + len -= CILEN_LONG; \ + INCPTR(2, p); \ + GETLONG(cilong, p); \ + /* Check rejected value. */ \ + if (cilong != val) { \ + goto bad; \ + } \ + try.neg = 0; \ + LCPDEBUG((LOG_INFO,"lcp_rejci: long opt %d rejected\n", opt)); \ + } +#define REJCILQR(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_LQR && \ + p[1] == CILEN_LQR && \ + p[0] == opt) { \ + len -= CILEN_LQR; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETLONG(cilong, p); \ + /* Check rejected value. */ \ + if (cishort != PPP_LQR || cilong != val) { \ + goto bad; \ + } \ + try.neg = 0; \ + LCPDEBUG((LOG_INFO,"lcp_rejci: LQR opt %d rejected\n", opt)); \ + } +#define REJCICBCP(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_CBCP && \ + p[1] == CILEN_CBCP && \ + p[0] == opt) { \ + len -= CILEN_CBCP; \ + INCPTR(2, p); \ + GETCHAR(cichar, p); \ + /* Check rejected value. */ \ + if (cichar != val) { \ + goto bad; \ + } \ + try.neg = 0; \ + LCPDEBUG((LOG_INFO,"lcp_rejci: Callback opt %d rejected\n", opt)); \ + } + + REJCISHORT(CI_MRU, neg_mru, go->mru); + REJCILONG(CI_ASYNCMAP, neg_asyncmap, go->asyncmap); + REJCICHAP(CI_AUTHTYPE, neg_chap, PPP_CHAP, go->chap_mdtype); + if (!go->neg_chap) { + REJCISHORT(CI_AUTHTYPE, neg_upap, PPP_PAP); + } + REJCILQR(CI_QUALITY, neg_lqr, go->lqr_period); + REJCICBCP(CI_CALLBACK, neg_cbcp, CBCP_OPT); + REJCILONG(CI_MAGICNUMBER, neg_magicnumber, go->magicnumber); + REJCIVOID(CI_PCOMPRESSION, neg_pcompression); + REJCIVOID(CI_ACCOMPRESSION, neg_accompression); + + /* + * If there are any remaining CIs, then this packet is bad. + */ + if (len != 0) { + goto bad; + } + /* + * Now we can update state. + */ + if (f->state != LS_OPENED) { + *go = try; + } + return 1; + +bad: + LCPDEBUG((LOG_WARNING, "lcp_rejci: received bad Reject!\n")); + return 0; +} + + +/* + * lcp_reqci - Check the peer's requested CIs and send appropriate response. + * + * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified + * appropriately. If reject_if_disagree is non-zero, doesn't return + * CONFNAK; returns CONFREJ if it can't return CONFACK. + */ +static int +lcp_reqci(fsm *f, + u_char *inp, /* Requested CIs */ + int *lenp, /* Length of requested CIs */ + int reject_if_disagree) +{ + lcp_options *go = &lcp_gotoptions[f->unit]; + lcp_options *ho = &lcp_hisoptions[f->unit]; + lcp_options *ao = &lcp_allowoptions[f->unit]; + u_char *cip, *next; /* Pointer to current and next CIs */ + int cilen, citype, cichar; /* Parsed len, type, char value */ + u_short cishort; /* Parsed short value */ + u32_t cilong; /* Parse long value */ + int rc = CONFACK; /* Final packet return code */ + int orc; /* Individual option return code */ + u_char *p; /* Pointer to next char to parse */ + u_char *rejp; /* Pointer to next char in reject frame */ + u_char *nakp; /* Pointer to next char in Nak frame */ + int l = *lenp; /* Length left */ +#if TRACELCP > 0 + char traceBuf[80]; + int traceNdx = 0; +#endif + + /* + * Reset all his options. + */ + BZERO(ho, sizeof(*ho)); + + /* + * Process all his options. + */ + next = inp; + nakp = nak_buffer; + rejp = inp; + while (l) { + orc = CONFACK; /* Assume success */ + cip = p = next; /* Remember begining of CI */ + if (l < 2 || /* Not enough data for CI header or */ + p[1] < 2 || /* CI length too small or */ + p[1] > l) { /* CI length too big? */ + LCPDEBUG((LOG_WARNING, "lcp_reqci: bad CI length!\n")); + orc = CONFREJ; /* Reject bad CI */ + cilen = l; /* Reject till end of packet */ + l = 0; /* Don't loop again */ + citype = 0; + goto endswitch; + } + GETCHAR(citype, p); /* Parse CI type */ + GETCHAR(cilen, p); /* Parse CI length */ + l -= cilen; /* Adjust remaining length */ + next += cilen; /* Step to next CI */ + + switch (citype) { /* Check CI type */ + case CI_MRU: + if (!ao->neg_mru) { /* Allow option? */ + LCPDEBUG((LOG_INFO, "lcp_reqci: Reject MRU - not allowed\n")); + orc = CONFREJ; /* Reject CI */ + break; + } else if (cilen != CILEN_SHORT) { /* Check CI length */ + LCPDEBUG((LOG_INFO, "lcp_reqci: Reject MRU - bad length\n")); + orc = CONFREJ; /* Reject CI */ + break; + } + GETSHORT(cishort, p); /* Parse MRU */ + + /* + * He must be able to receive at least our minimum. + * No need to check a maximum. If he sends a large number, + * we'll just ignore it. + */ + if (cishort < PPP_MINMRU) { + LCPDEBUG((LOG_INFO, "lcp_reqci: Nak - MRU too small\n")); + orc = CONFNAK; /* Nak CI */ + PUTCHAR(CI_MRU, nakp); + PUTCHAR(CILEN_SHORT, nakp); + PUTSHORT(PPP_MINMRU, nakp); /* Give him a hint */ + break; + } + ho->neg_mru = 1; /* Remember he sent MRU */ + ho->mru = cishort; /* And remember value */ +#if TRACELCP > 0 + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " MRU %d", cishort); + traceNdx = strlen(traceBuf); +#endif + break; + + case CI_ASYNCMAP: + if (!ao->neg_asyncmap) { + LCPDEBUG((LOG_INFO, "lcp_reqci: Reject ASYNCMAP not allowed\n")); + orc = CONFREJ; + break; + } else if (cilen != CILEN_LONG) { + LCPDEBUG((LOG_INFO, "lcp_reqci: Reject ASYNCMAP bad length\n")); + orc = CONFREJ; + break; + } + GETLONG(cilong, p); + + /* + * Asyncmap must have set at least the bits + * which are set in lcp_allowoptions[unit].asyncmap. + */ + if ((ao->asyncmap & ~cilong) != 0) { + LCPDEBUG((LOG_INFO, "lcp_reqci: Nak ASYNCMAP %lX missing %lX\n", + cilong, ao->asyncmap)); + orc = CONFNAK; + PUTCHAR(CI_ASYNCMAP, nakp); + PUTCHAR(CILEN_LONG, nakp); + PUTLONG(ao->asyncmap | cilong, nakp); + break; + } + ho->neg_asyncmap = 1; + ho->asyncmap = cilong; +#if TRACELCP > 0 + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " ASYNCMAP=%lX", cilong); + traceNdx = strlen(traceBuf); +#endif + break; + + case CI_AUTHTYPE: + if (cilen < CILEN_SHORT) { + LCPDEBUG((LOG_INFO, "lcp_reqci: Reject AUTHTYPE missing arg\n")); + orc = CONFREJ; + break; + } else if (!(ao->neg_upap || ao->neg_chap)) { + /* + * Reject the option if we're not willing to authenticate. + */ + LCPDEBUG((LOG_INFO, "lcp_reqci: Reject AUTHTYPE not allowed\n")); + orc = CONFREJ; + break; + } + GETSHORT(cishort, p); + + /* + * Authtype must be UPAP or CHAP. + * + * Note: if both ao->neg_upap and ao->neg_chap are set, + * and the peer sends a Configure-Request with two + * authenticate-protocol requests, one for CHAP and one + * for UPAP, then we will reject the second request. + * Whether we end up doing CHAP or UPAP depends then on + * the ordering of the CIs in the peer's Configure-Request. + */ + + if (cishort == PPP_PAP) { + if (ho->neg_chap) { /* we've already accepted CHAP */ + LCPDEBUG((LOG_WARNING, "lcp_reqci: Reject AUTHTYPE PAP already accepted\n")); + orc = CONFREJ; + break; + } else if (cilen != CILEN_SHORT) { + LCPDEBUG((LOG_WARNING, "lcp_reqci: Reject AUTHTYPE PAP bad len\n")); + orc = CONFREJ; + break; + } + if (!ao->neg_upap) { /* we don't want to do PAP */ + LCPDEBUG((LOG_WARNING, "lcp_reqci: Nak AUTHTYPE PAP not allowed\n")); + orc = CONFNAK; /* NAK it and suggest CHAP */ + PUTCHAR(CI_AUTHTYPE, nakp); + PUTCHAR(CILEN_CHAP, nakp); + PUTSHORT(PPP_CHAP, nakp); + PUTCHAR(ao->chap_mdtype, nakp); + break; + } + ho->neg_upap = 1; +#if TRACELCP > 0 + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " PAP (%X)", cishort); + traceNdx = strlen(traceBuf); +#endif + break; + } + if (cishort == PPP_CHAP) { + if (ho->neg_upap) { /* we've already accepted PAP */ + LCPDEBUG((LOG_WARNING, "lcp_reqci: Reject AUTHTYPE CHAP accepted PAP\n")); + orc = CONFREJ; + break; + } else if (cilen != CILEN_CHAP) { + LCPDEBUG((LOG_WARNING, "lcp_reqci: Reject AUTHTYPE CHAP bad len\n")); + orc = CONFREJ; + break; + } + if (!ao->neg_chap) { /* we don't want to do CHAP */ + LCPDEBUG((LOG_WARNING, "lcp_reqci: Nak AUTHTYPE CHAP not allowed\n")); + orc = CONFNAK; /* NAK it and suggest PAP */ + PUTCHAR(CI_AUTHTYPE, nakp); + PUTCHAR(CILEN_SHORT, nakp); + PUTSHORT(PPP_PAP, nakp); + break; + } + GETCHAR(cichar, p); /* get digest type*/ + if (cichar != CHAP_DIGEST_MD5 +#ifdef CHAPMS + && cichar != CHAP_MICROSOFT +#endif + ) { + LCPDEBUG((LOG_WARNING, "lcp_reqci: Nak AUTHTYPE CHAP digest=%d\n", cichar)); + orc = CONFNAK; + PUTCHAR(CI_AUTHTYPE, nakp); + PUTCHAR(CILEN_CHAP, nakp); + PUTSHORT(PPP_CHAP, nakp); + PUTCHAR(ao->chap_mdtype, nakp); + break; + } +#if TRACELCP > 0 + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CHAP %X,%d", cishort, cichar); + traceNdx = strlen(traceBuf); +#endif + ho->chap_mdtype = cichar; /* save md type */ + ho->neg_chap = 1; + break; + } + + /* + * We don't recognize the protocol they're asking for. + * Nak it with something we're willing to do. + * (At this point we know ao->neg_upap || ao->neg_chap.) + */ + orc = CONFNAK; + PUTCHAR(CI_AUTHTYPE, nakp); + if (ao->neg_chap) { + LCPDEBUG((LOG_WARNING, "lcp_reqci: Nak AUTHTYPE %d req CHAP\n", cishort)); + PUTCHAR(CILEN_CHAP, nakp); + PUTSHORT(PPP_CHAP, nakp); + PUTCHAR(ao->chap_mdtype, nakp); + } else { + LCPDEBUG((LOG_WARNING, "lcp_reqci: Nak AUTHTYPE %d req PAP\n", cishort)); + PUTCHAR(CILEN_SHORT, nakp); + PUTSHORT(PPP_PAP, nakp); + } + break; + + case CI_QUALITY: + GETSHORT(cishort, p); + GETLONG(cilong, p); +#if TRACELCP > 0 + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " QUALITY (%x %x)", cishort, (unsigned int) cilong); + traceNdx = strlen(traceBuf); +#endif + + if (!ao->neg_lqr || + cilen != CILEN_LQR) { + orc = CONFREJ; + break; + } + + /* + * Check the protocol and the reporting period. + * XXX When should we Nak this, and what with? + */ + if (cishort != PPP_LQR) { + orc = CONFNAK; + PUTCHAR(CI_QUALITY, nakp); + PUTCHAR(CILEN_LQR, nakp); + PUTSHORT(PPP_LQR, nakp); + PUTLONG(ao->lqr_period, nakp); + break; + } + break; + + case CI_MAGICNUMBER: + if (!(ao->neg_magicnumber || go->neg_magicnumber) || + cilen != CILEN_LONG) { + orc = CONFREJ; + break; + } + GETLONG(cilong, p); +#if TRACELCP > 0 + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " MAGICNUMBER (%lX)", cilong); + traceNdx = strlen(traceBuf); +#endif + + /* + * He must have a different magic number. + */ + if (go->neg_magicnumber && + cilong == go->magicnumber) { + cilong = magic(); /* Don't put magic() inside macro! */ + orc = CONFNAK; + PUTCHAR(CI_MAGICNUMBER, nakp); + PUTCHAR(CILEN_LONG, nakp); + PUTLONG(cilong, nakp); + break; + } + ho->neg_magicnumber = 1; + ho->magicnumber = cilong; + break; + + + case CI_PCOMPRESSION: +#if TRACELCP > 0 + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " PCOMPRESSION"); + traceNdx = strlen(traceBuf); +#endif + if (!ao->neg_pcompression || + cilen != CILEN_VOID) { + orc = CONFREJ; + break; + } + ho->neg_pcompression = 1; + break; + + case CI_ACCOMPRESSION: +#if TRACELCP > 0 + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " ACCOMPRESSION"); + traceNdx = strlen(traceBuf); +#endif + if (!ao->neg_accompression || + cilen != CILEN_VOID) { + orc = CONFREJ; + break; + } + ho->neg_accompression = 1; + break; + + case CI_MRRU: +#if TRACELCP > 0 + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CI_MRRU"); + traceNdx = strlen(traceBuf); +#endif + orc = CONFREJ; + break; + + case CI_SSNHF: +#if TRACELCP > 0 + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CI_SSNHF"); + traceNdx = strlen(traceBuf); +#endif + orc = CONFREJ; + break; + + case CI_EPDISC: +#if TRACELCP > 0 + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CI_EPDISC"); + traceNdx = strlen(traceBuf); +#endif + orc = CONFREJ; + break; + + default: +#if TRACELCP + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " unknown %d", citype); + traceNdx = strlen(traceBuf); +#endif + orc = CONFREJ; + break; + } + + endswitch: +#if TRACELCP + if (traceNdx >= 80 - 32) { + LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd%s\n", traceBuf)); + traceNdx = 0; + } +#endif + if (orc == CONFACK && /* Good CI */ + rc != CONFACK) { /* but prior CI wasnt? */ + continue; /* Don't send this one */ + } + + if (orc == CONFNAK) { /* Nak this CI? */ + if (reject_if_disagree /* Getting fed up with sending NAKs? */ + && citype != CI_MAGICNUMBER) { + orc = CONFREJ; /* Get tough if so */ + } else { + if (rc == CONFREJ) { /* Rejecting prior CI? */ + continue; /* Don't send this one */ + } + rc = CONFNAK; + } + } + if (orc == CONFREJ) { /* Reject this CI */ + rc = CONFREJ; + if (cip != rejp) { /* Need to move rejected CI? */ + BCOPY(cip, rejp, cilen); /* Move it */ + } + INCPTR(cilen, rejp); /* Update output pointer */ + } + } + + /* + * If we wanted to send additional NAKs (for unsent CIs), the + * code would go here. The extra NAKs would go at *nakp. + * At present there are no cases where we want to ask the + * peer to negotiate an option. + */ + + switch (rc) { + case CONFACK: + *lenp = (int)(next - inp); + break; + case CONFNAK: + /* + * Copy the Nak'd options from the nak_buffer to the caller's buffer. + */ + *lenp = (int)(nakp - nak_buffer); + BCOPY(nak_buffer, inp, *lenp); + break; + case CONFREJ: + *lenp = (int)(rejp - inp); + break; + } + +#if TRACELCP > 0 + if (traceNdx > 0) { + LCPDEBUG((LOG_INFO, "lcp_reqci: %s\n", traceBuf)); + } +#endif + LCPDEBUG((LOG_INFO, "lcp_reqci: returning CONF%s.\n", CODENAME(rc))); + return (rc); /* Return final code */ +} + + +/* + * lcp_up - LCP has come UP. + */ +static void +lcp_up(fsm *f) +{ + lcp_options *wo = &lcp_wantoptions[f->unit]; + lcp_options *ho = &lcp_hisoptions[f->unit]; + lcp_options *go = &lcp_gotoptions[f->unit]; + lcp_options *ao = &lcp_allowoptions[f->unit]; + + if (!go->neg_magicnumber) { + go->magicnumber = 0; + } + if (!ho->neg_magicnumber) { + ho->magicnumber = 0; + } + + /* + * Set our MTU to the smaller of the MTU we wanted and + * the MRU our peer wanted. If we negotiated an MRU, + * set our MRU to the larger of value we wanted and + * the value we got in the negotiation. + */ + ppp_send_config(f->unit, LWIP_MIN(ao->mru, (ho->neg_mru? ho->mru: PPP_MRU)), + (ho->neg_asyncmap? ho->asyncmap: 0xffffffffl), + ho->neg_pcompression, ho->neg_accompression); + /* + * If the asyncmap hasn't been negotiated, we really should + * set the receive asyncmap to ffffffff, but we set it to 0 + * for backwards contemptibility. + */ + ppp_recv_config(f->unit, (go->neg_mru? LWIP_MAX(wo->mru, go->mru): PPP_MRU), + (go->neg_asyncmap? go->asyncmap: 0x00000000), + go->neg_pcompression, go->neg_accompression); + + if (ho->neg_mru) { + peer_mru[f->unit] = ho->mru; + } + + lcp_echo_lowerup(f->unit); /* Enable echo messages */ + + link_established(f->unit); +} + + +/* + * lcp_down - LCP has gone DOWN. + * + * Alert other protocols. + */ +static void +lcp_down(fsm *f) +{ + lcp_options *go = &lcp_gotoptions[f->unit]; + + lcp_echo_lowerdown(f->unit); + + link_down(f->unit); + + ppp_send_config(f->unit, PPP_MRU, 0xffffffffl, 0, 0); + ppp_recv_config(f->unit, PPP_MRU, + (go->neg_asyncmap? go->asyncmap: 0x00000000), + go->neg_pcompression, go->neg_accompression); + peer_mru[f->unit] = PPP_MRU; +} + + +/* + * lcp_starting - LCP needs the lower layer up. + */ +static void +lcp_starting(fsm *f) +{ + link_required(f->unit); +} + + +/* + * lcp_finished - LCP has finished with the lower layer. + */ +static void +lcp_finished(fsm *f) +{ + link_terminated(f->unit); +} + + +#if 0 +/* + * print_string - print a readable representation of a string using + * printer. + */ +static void +print_string( char *p, int len, void (*printer) (void *, char *, ...), void *arg) +{ + int c; + + printer(arg, "\""); + for (; len > 0; --len) { + c = *p++; + if (' ' <= c && c <= '~') { + if (c == '\\' || c == '"') { + printer(arg, "\\"); + } + printer(arg, "%c", c); + } else { + switch (c) { + case '\n': + printer(arg, "\\n"); + break; + case '\r': + printer(arg, "\\r"); + break; + case '\t': + printer(arg, "\\t"); + break; + default: + printer(arg, "\\%.3o", c); + } + } + } + printer(arg, "\""); +} + + +/* + * lcp_printpkt - print the contents of an LCP packet. + */ +static char *lcp_codenames[] = { + "ConfReq", "ConfAck", "ConfNak", "ConfRej", + "TermReq", "TermAck", "CodeRej", "ProtRej", + "EchoReq", "EchoRep", "DiscReq" +}; + +static int +lcp_printpkt( u_char *p, int plen, void (*printer) (void *, char *, ...), void *arg) +{ + int code, id, len, olen; + u_char *pstart, *optend; + u_short cishort; + u32_t cilong; + + if (plen < HEADERLEN) { + return 0; + } + pstart = p; + GETCHAR(code, p); + GETCHAR(id, p); + GETSHORT(len, p); + if (len < HEADERLEN || len > plen) { + return 0; + } + + if (code >= 1 && code <= sizeof(lcp_codenames) / sizeof(char *)) { + printer(arg, " %s", lcp_codenames[code-1]); + } else { + printer(arg, " code=0x%x", code); + } + printer(arg, " id=0x%x", id); + len -= HEADERLEN; + switch (code) { + case CONFREQ: + case CONFACK: + case CONFNAK: + case CONFREJ: + /* print option list */ + while (len >= 2) { + GETCHAR(code, p); + GETCHAR(olen, p); + p -= 2; + if (olen < 2 || olen > len) { + break; + } + printer(arg, " <"); + len -= olen; + optend = p + olen; + switch (code) { + case CI_MRU: + if (olen == CILEN_SHORT) { + p += 2; + GETSHORT(cishort, p); + printer(arg, "mru %d", cishort); + } + break; + case CI_ASYNCMAP: + if (olen == CILEN_LONG) { + p += 2; + GETLONG(cilong, p); + printer(arg, "asyncmap 0x%lx", cilong); + } + break; + case CI_AUTHTYPE: + if (olen >= CILEN_SHORT) { + p += 2; + printer(arg, "auth "); + GETSHORT(cishort, p); + switch (cishort) { + case PPP_PAP: + printer(arg, "pap"); + break; + case PPP_CHAP: + printer(arg, "chap"); + break; + default: + printer(arg, "0x%x", cishort); + } + } + break; + case CI_QUALITY: + if (olen >= CILEN_SHORT) { + p += 2; + printer(arg, "quality "); + GETSHORT(cishort, p); + switch (cishort) { + case PPP_LQR: + printer(arg, "lqr"); + break; + default: + printer(arg, "0x%x", cishort); + } + } + break; + case CI_CALLBACK: + if (olen >= CILEN_CHAR) { + p += 2; + printer(arg, "callback "); + GETSHORT(cishort, p); + switch (cishort) { + case CBCP_OPT: + printer(arg, "CBCP"); + break; + default: + printer(arg, "0x%x", cishort); + } + } + break; + case CI_MAGICNUMBER: + if (olen == CILEN_LONG) { + p += 2; + GETLONG(cilong, p); + printer(arg, "magic 0x%x", cilong); + } + break; + case CI_PCOMPRESSION: + if (olen == CILEN_VOID) { + p += 2; + printer(arg, "pcomp"); + } + break; + case CI_ACCOMPRESSION: + if (olen == CILEN_VOID) { + p += 2; + printer(arg, "accomp"); + } + break; + } + while (p < optend) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + printer(arg, ">"); + } + break; + + case TERMACK: + case TERMREQ: + if (len > 0 && *p >= ' ' && *p < 0x7f) { + printer(arg, " "); + print_string((char*)p, len, printer, arg); + p += len; + len = 0; + } + break; + + case ECHOREQ: + case ECHOREP: + case DISCREQ: + if (len >= 4) { + GETLONG(cilong, p); + printer(arg, " magic=0x%x", cilong); + p += 4; + len -= 4; + } + break; + } + + /* print the rest of the bytes in the packet */ + for (; len > 0; --len) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + + return (int)(p - pstart); +} +#endif + +/* + * Time to shut down the link because there is nothing out there. + */ +static void +LcpLinkFailure (fsm *f) +{ + if (f->state == LS_OPENED) { + LCPDEBUG((LOG_INFO, "No response to %d echo-requests\n", lcp_echos_pending)); + LCPDEBUG((LOG_NOTICE, "Serial link appears to be disconnected.\n")); + lcp_close(f->unit, "Peer not responding"); + } +} + +/* + * Timer expired for the LCP echo requests from this process. + */ +static void +LcpEchoCheck (fsm *f) +{ + LcpSendEchoRequest (f); + + /* + * Start the timer for the next interval. + */ + LWIP_ASSERT("lcp_echo_timer_running == 0", lcp_echo_timer_running == 0); + + TIMEOUT (LcpEchoTimeout, f, lcp_echo_interval); + lcp_echo_timer_running = 1; +} + +/* + * LcpEchoTimeout - Timer expired on the LCP echo + */ +static void +LcpEchoTimeout (void *arg) +{ + if (lcp_echo_timer_running != 0) { + lcp_echo_timer_running = 0; + LcpEchoCheck ((fsm *) arg); + } +} + +/* + * LcpEchoReply - LCP has received a reply to the echo + */ +static void +lcp_received_echo_reply (fsm *f, int id, u_char *inp, int len) +{ + u32_t magic; + + LWIP_UNUSED_ARG(id); + + /* Check the magic number - don't count replies from ourselves. */ + if (len < 4) { + LCPDEBUG((LOG_WARNING, "lcp: received short Echo-Reply, length %d\n", len)); + return; + } + GETLONG(magic, inp); + if (lcp_gotoptions[f->unit].neg_magicnumber && magic == lcp_gotoptions[f->unit].magicnumber) { + LCPDEBUG((LOG_WARNING, "appear to have received our own echo-reply!\n")); + return; + } + + /* Reset the number of outstanding echo frames */ + lcp_echos_pending = 0; +} + +/* + * LcpSendEchoRequest - Send an echo request frame to the peer + */ +static void +LcpSendEchoRequest (fsm *f) +{ + u32_t lcp_magic; + u_char pkt[4], *pktp; + + /* + * Detect the failure of the peer at this point. + */ + if (lcp_echo_fails != 0) { + if (lcp_echos_pending++ >= lcp_echo_fails) { + LcpLinkFailure(f); + lcp_echos_pending = 0; + } + } + + /* + * Make and send the echo request frame. + */ + if (f->state == LS_OPENED) { + lcp_magic = lcp_gotoptions[f->unit].magicnumber; + pktp = pkt; + PUTLONG(lcp_magic, pktp); + fsm_sdata(f, ECHOREQ, (u_char)(lcp_echo_number++ & 0xFF), pkt, (int)(pktp - pkt)); + } +} + +/* + * lcp_echo_lowerup - Start the timer for the LCP frame + */ + +static void +lcp_echo_lowerup (int unit) +{ + fsm *f = &lcp_fsm[unit]; + + /* Clear the parameters for generating echo frames */ + lcp_echos_pending = 0; + lcp_echo_number = 0; + lcp_echo_timer_running = 0; + + /* If a timeout interval is specified then start the timer */ + if (lcp_echo_interval != 0) { + LcpEchoCheck (f); + } +} + +/* + * lcp_echo_lowerdown - Stop the timer for the LCP frame + */ + +static void +lcp_echo_lowerdown (int unit) +{ + fsm *f = &lcp_fsm[unit]; + + if (lcp_echo_timer_running != 0) { + UNTIMEOUT (LcpEchoTimeout, f); + lcp_echo_timer_running = 0; + } +} + +#endif /* PPP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/lcp.h b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/lcp.h new file mode 100644 index 0000000..1a5e5a4 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/lcp.h @@ -0,0 +1,167 @@ +/***************************************************************************** +* lcp.h - Network Link Control Protocol header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-11-05 Guy Lancaster , Global Election Systems Inc. +* Original derived from BSD codes. +*****************************************************************************/ +/* + * lcp.h - Link Control Protocol definitions. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * $Id: lcp.h,v 1.3 2007/12/19 20:47:23 fbernon Exp $ + */ + +#ifndef LCP_H +#define LCP_H + +/************************* +*** PUBLIC DEFINITIONS *** +*************************/ +/* + * Options. + */ +#define CI_MRU 1 /* Maximum Receive Unit */ +#define CI_ASYNCMAP 2 /* Async Control Character Map */ +#define CI_AUTHTYPE 3 /* Authentication Type */ +#define CI_QUALITY 4 /* Quality Protocol */ +#define CI_MAGICNUMBER 5 /* Magic Number */ +#define CI_PCOMPRESSION 7 /* Protocol Field Compression */ +#define CI_ACCOMPRESSION 8 /* Address/Control Field Compression */ +#define CI_CALLBACK 13 /* callback */ +#define CI_MRRU 17 /* max reconstructed receive unit; multilink */ +#define CI_SSNHF 18 /* short sequence numbers for multilink */ +#define CI_EPDISC 19 /* endpoint discriminator */ + +/* + * LCP-specific packet types. + */ +#define PROTREJ 8 /* Protocol Reject */ +#define ECHOREQ 9 /* Echo Request */ +#define ECHOREP 10 /* Echo Reply */ +#define DISCREQ 11 /* Discard Request */ +#define CBCP_OPT 6 /* Use callback control protocol */ + + +/************************ +*** PUBLIC DATA TYPES *** +************************/ + +/* + * The state of options is described by an lcp_options structure. + */ +typedef struct lcp_options { + u_int passive : 1; /* Don't die if we don't get a response */ + u_int silent : 1; /* Wait for the other end to start first */ + u_int restart : 1; /* Restart vs. exit after close */ + u_int neg_mru : 1; /* Negotiate the MRU? */ + u_int neg_asyncmap : 1; /* Negotiate the async map? */ + u_int neg_upap : 1; /* Ask for UPAP authentication? */ + u_int neg_chap : 1; /* Ask for CHAP authentication? */ + u_int neg_magicnumber : 1; /* Ask for magic number? */ + u_int neg_pcompression : 1; /* HDLC Protocol Field Compression? */ + u_int neg_accompression : 1; /* HDLC Address/Control Field Compression? */ + u_int neg_lqr : 1; /* Negotiate use of Link Quality Reports */ + u_int neg_cbcp : 1; /* Negotiate use of CBCP */ +#ifdef PPP_MULTILINK + u_int neg_mrru : 1; /* Negotiate multilink MRRU */ + u_int neg_ssnhf : 1; /* Negotiate short sequence numbers */ + u_int neg_endpoint : 1; /* Negotiate endpoint discriminator */ +#endif + u_short mru; /* Value of MRU */ +#ifdef PPP_MULTILINK + u_short mrru; /* Value of MRRU, and multilink enable */ +#endif + u_char chap_mdtype; /* which MD type (hashing algorithm) */ + u32_t asyncmap; /* Value of async map */ + u32_t magicnumber; + int numloops; /* Number of loops during magic number neg. */ + u32_t lqr_period; /* Reporting period for LQR 1/100ths second */ +#ifdef PPP_MULTILINK + struct epdisc endpoint; /* endpoint discriminator */ +#endif +} lcp_options; + +/* + * Values for phase from BSD pppd.h based on RFC 1661. + */ +typedef enum { + PHASE_DEAD = 0, + PHASE_INITIALIZE, + PHASE_ESTABLISH, + PHASE_AUTHENTICATE, + PHASE_CALLBACK, + PHASE_NETWORK, + PHASE_TERMINATE +} LinkPhase; + + +/***************************** +*** PUBLIC DATA STRUCTURES *** +*****************************/ + +extern LinkPhase lcp_phase[NUM_PPP]; /* Phase of link session (RFC 1661) */ +extern lcp_options lcp_wantoptions[]; +extern lcp_options lcp_gotoptions[]; +extern lcp_options lcp_allowoptions[]; +extern lcp_options lcp_hisoptions[]; +extern ext_accm xmit_accm[]; + + +/*********************** +*** PUBLIC FUNCTIONS *** +***********************/ + +void lcp_init (int); +void lcp_open (int); +void lcp_close (int, char *); +void lcp_lowerup (int); +void lcp_lowerdown(int); +void lcp_sprotrej (int, u_char *, int); /* send protocol reject */ + +extern struct protent lcp_protent; + +/* Default number of times we receive our magic number from the peer + before deciding the link is looped-back. */ +#define DEFLOOPBACKFAIL 10 + +#endif /* LCP_H */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/magic.c b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/magic.c new file mode 100644 index 0000000..d3922bb --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/magic.c @@ -0,0 +1,82 @@ +/***************************************************************************** +* magic.c - Network Random Number Generator program file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 by Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-12-04 Guy Lancaster , Global Election Systems Inc. +* Original based on BSD magic.c. +*****************************************************************************/ +/* + * magic.c - PPP Magic Number routines. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "lwip/opt.h" + +#if PPP_SUPPORT + +#include "ppp.h" +#include "randm.h" +#include "magic.h" + +/***********************************/ +/*** PUBLIC FUNCTION DEFINITIONS ***/ +/***********************************/ +/* + * magicInit - Initialize the magic number generator. + * + * Since we use another random number generator that has its own + * initialization, we do nothing here. + */ +void magicInit() +{ + return; +} + +/* + * magic - Returns the next magic number. + */ +u32_t magic() +{ + return avRandom(); +} + +#endif /* PPP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/magic.h b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/magic.h new file mode 100644 index 0000000..bc51749 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/magic.h @@ -0,0 +1,67 @@ +/***************************************************************************** +* magic.h - Network Random Number Generator header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-12-04 Guy Lancaster , Global Election Systems Inc. +* Original derived from BSD codes. +*****************************************************************************/ +/* + * magic.h - PPP Magic Number definitions. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * $Id: magic.h,v 1.2 2007/12/02 22:35:55 fbernon Exp $ + */ + +#ifndef MAGIC_H +#define MAGIC_H + +/***************************************************************************** +************************** PUBLIC FUNCTIONS ********************************** +*****************************************************************************/ + +/* Initialize the magic number generator */ +void magicInit(void); + +/* Returns the next magic number */ +u32_t magic(void); + +#endif /* MAGIC_H */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/md5.c b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/md5.c new file mode 100644 index 0000000..7a60d78 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/md5.c @@ -0,0 +1,320 @@ +/* + *********************************************************************** + ** md5.c -- the source code for MD5 routines ** + ** RSA Data Security, Inc. MD5 Message-Digest Algorithm ** + ** Created: 2/17/90 RLR ** + ** Revised: 1/91 SRD,AJ,BSK,JT Reference C ver., 7/10 constant corr. ** + *********************************************************************** + */ + +/* + *********************************************************************** + ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. ** + ** ** + ** License to copy and use this software is granted provided that ** + ** it is identified as the "RSA Data Security, Inc. MD5 Message- ** + ** Digest Algorithm" in all material mentioning or referencing this ** + ** software or this function. ** + ** ** + ** License is also granted to make and use derivative works ** + ** provided that such works are identified as "derived from the RSA ** + ** Data Security, Inc. MD5 Message-Digest Algorithm" in all ** + ** material mentioning or referencing the derived work. ** + ** ** + ** RSA Data Security, Inc. makes no representations concerning ** + ** either the merchantability of this software or the suitability ** + ** of this software for any particular purpose. It is provided "as ** + ** is" without express or implied warranty of any kind. ** + ** ** + ** These notices must be retained in any copies of any part of this ** + ** documentation and/or software. ** + *********************************************************************** + */ + +#include "lwip/opt.h" + +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#if CHAP_SUPPORT || MD5_SUPPORT + +#include "ppp.h" +#include "pppdebug.h" + +#include "md5.h" + +#include + +/* + *********************************************************************** + ** Message-digest routines: ** + ** To form the message digest for a message M ** + ** (1) Initialize a context buffer mdContext using MD5Init ** + ** (2) Call MD5Update on mdContext and M ** + ** (3) Call MD5Final on mdContext ** + ** The message digest is now in mdContext->digest[0...15] ** + *********************************************************************** + */ + +/* forward declaration */ +static void Transform (u32_t *buf, u32_t *in); + +static unsigned char PADDING[64] = { + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/* F, G, H and I are basic MD5 functions */ +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) + +/* ROTATE_LEFT rotates x left n bits */ +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */ +/* Rotation is separate from addition to prevent recomputation */ +#define FF(a, b, c, d, x, s, ac) \ + {(a) += F ((b), (c), (d)) + (x) + (u32_t)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define GG(a, b, c, d, x, s, ac) \ + {(a) += G ((b), (c), (d)) + (x) + (u32_t)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define HH(a, b, c, d, x, s, ac) \ + {(a) += H ((b), (c), (d)) + (x) + (u32_t)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define II(a, b, c, d, x, s, ac) \ + {(a) += I ((b), (c), (d)) + (x) + (u32_t)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } + +#ifdef __STDC__ +#define UL(x) x##UL +#else +#ifdef WIN32 +#define UL(x) x##UL +#else +#define UL(x) x +#endif +#endif + +/* The routine MD5Init initializes the message-digest context + mdContext. All fields are set to zero. + */ +void +MD5Init (MD5_CTX *mdContext) +{ + mdContext->i[0] = mdContext->i[1] = (u32_t)0; + + /* Load magic initialization constants. */ + mdContext->buf[0] = (u32_t)0x67452301UL; + mdContext->buf[1] = (u32_t)0xefcdab89UL; + mdContext->buf[2] = (u32_t)0x98badcfeUL; + mdContext->buf[3] = (u32_t)0x10325476UL; +} + +/* The routine MD5Update updates the message-digest context to + account for the presence of each of the characters inBuf[0..inLen-1] + in the message whose digest is being computed. + */ +void +MD5Update(MD5_CTX *mdContext, unsigned char *inBuf, unsigned int inLen) +{ + u32_t in[16]; + int mdi; + unsigned int i, ii; + +#if 0 + ppp_trace(LOG_INFO, "MD5Update: %u:%.*H\n", inLen, MIN(inLen, 20) * 2, inBuf); + ppp_trace(LOG_INFO, "MD5Update: %u:%s\n", inLen, inBuf); +#endif + + /* compute number of bytes mod 64 */ + mdi = (int)((mdContext->i[0] >> 3) & 0x3F); + + /* update number of bits */ + if ((mdContext->i[0] + ((u32_t)inLen << 3)) < mdContext->i[0]) { + mdContext->i[1]++; + } + mdContext->i[0] += ((u32_t)inLen << 3); + mdContext->i[1] += ((u32_t)inLen >> 29); + + while (inLen--) { + /* add new character to buffer, increment mdi */ + mdContext->in[mdi++] = *inBuf++; + + /* transform if necessary */ + if (mdi == 0x40) { + for (i = 0, ii = 0; i < 16; i++, ii += 4) { + in[i] = (((u32_t)mdContext->in[ii+3]) << 24) | + (((u32_t)mdContext->in[ii+2]) << 16) | + (((u32_t)mdContext->in[ii+1]) << 8) | + ((u32_t)mdContext->in[ii]); + } + Transform (mdContext->buf, in); + mdi = 0; + } + } +} + +/* The routine MD5Final terminates the message-digest computation and + ends with the desired message digest in mdContext->digest[0...15]. + */ +void +MD5Final (unsigned char hash[], MD5_CTX *mdContext) +{ + u32_t in[16]; + int mdi; + unsigned int i, ii; + unsigned int padLen; + + /* save number of bits */ + in[14] = mdContext->i[0]; + in[15] = mdContext->i[1]; + + /* compute number of bytes mod 64 */ + mdi = (int)((mdContext->i[0] >> 3) & 0x3F); + + /* pad out to 56 mod 64 */ + padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi); + MD5Update (mdContext, PADDING, padLen); + + /* append length in bits and transform */ + for (i = 0, ii = 0; i < 14; i++, ii += 4) { + in[i] = (((u32_t)mdContext->in[ii+3]) << 24) | + (((u32_t)mdContext->in[ii+2]) << 16) | + (((u32_t)mdContext->in[ii+1]) << 8) | + ((u32_t)mdContext->in[ii]); + } + Transform (mdContext->buf, in); + + /* store buffer in digest */ + for (i = 0, ii = 0; i < 4; i++, ii += 4) { + mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF); + mdContext->digest[ii+1] = + (unsigned char)((mdContext->buf[i] >> 8) & 0xFF); + mdContext->digest[ii+2] = + (unsigned char)((mdContext->buf[i] >> 16) & 0xFF); + mdContext->digest[ii+3] = + (unsigned char)((mdContext->buf[i] >> 24) & 0xFF); + } + SMEMCPY(hash, mdContext->digest, 16); +} + +/* Basic MD5 step. Transforms buf based on in. + */ +static void +Transform (u32_t *buf, u32_t *in) +{ + u32_t a = buf[0], b = buf[1], c = buf[2], d = buf[3]; + + /* Round 1 */ +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 + FF ( a, b, c, d, in[ 0], S11, UL(3614090360)); /* 1 */ + FF ( d, a, b, c, in[ 1], S12, UL(3905402710)); /* 2 */ + FF ( c, d, a, b, in[ 2], S13, UL( 606105819)); /* 3 */ + FF ( b, c, d, a, in[ 3], S14, UL(3250441966)); /* 4 */ + FF ( a, b, c, d, in[ 4], S11, UL(4118548399)); /* 5 */ + FF ( d, a, b, c, in[ 5], S12, UL(1200080426)); /* 6 */ + FF ( c, d, a, b, in[ 6], S13, UL(2821735955)); /* 7 */ + FF ( b, c, d, a, in[ 7], S14, UL(4249261313)); /* 8 */ + FF ( a, b, c, d, in[ 8], S11, UL(1770035416)); /* 9 */ + FF ( d, a, b, c, in[ 9], S12, UL(2336552879)); /* 10 */ + FF ( c, d, a, b, in[10], S13, UL(4294925233)); /* 11 */ + FF ( b, c, d, a, in[11], S14, UL(2304563134)); /* 12 */ + FF ( a, b, c, d, in[12], S11, UL(1804603682)); /* 13 */ + FF ( d, a, b, c, in[13], S12, UL(4254626195)); /* 14 */ + FF ( c, d, a, b, in[14], S13, UL(2792965006)); /* 15 */ + FF ( b, c, d, a, in[15], S14, UL(1236535329)); /* 16 */ + + /* Round 2 */ +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 + GG ( a, b, c, d, in[ 1], S21, UL(4129170786)); /* 17 */ + GG ( d, a, b, c, in[ 6], S22, UL(3225465664)); /* 18 */ + GG ( c, d, a, b, in[11], S23, UL( 643717713)); /* 19 */ + GG ( b, c, d, a, in[ 0], S24, UL(3921069994)); /* 20 */ + GG ( a, b, c, d, in[ 5], S21, UL(3593408605)); /* 21 */ + GG ( d, a, b, c, in[10], S22, UL( 38016083)); /* 22 */ + GG ( c, d, a, b, in[15], S23, UL(3634488961)); /* 23 */ + GG ( b, c, d, a, in[ 4], S24, UL(3889429448)); /* 24 */ + GG ( a, b, c, d, in[ 9], S21, UL( 568446438)); /* 25 */ + GG ( d, a, b, c, in[14], S22, UL(3275163606)); /* 26 */ + GG ( c, d, a, b, in[ 3], S23, UL(4107603335)); /* 27 */ + GG ( b, c, d, a, in[ 8], S24, UL(1163531501)); /* 28 */ + GG ( a, b, c, d, in[13], S21, UL(2850285829)); /* 29 */ + GG ( d, a, b, c, in[ 2], S22, UL(4243563512)); /* 30 */ + GG ( c, d, a, b, in[ 7], S23, UL(1735328473)); /* 31 */ + GG ( b, c, d, a, in[12], S24, UL(2368359562)); /* 32 */ + + /* Round 3 */ +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 + HH ( a, b, c, d, in[ 5], S31, UL(4294588738)); /* 33 */ + HH ( d, a, b, c, in[ 8], S32, UL(2272392833)); /* 34 */ + HH ( c, d, a, b, in[11], S33, UL(1839030562)); /* 35 */ + HH ( b, c, d, a, in[14], S34, UL(4259657740)); /* 36 */ + HH ( a, b, c, d, in[ 1], S31, UL(2763975236)); /* 37 */ + HH ( d, a, b, c, in[ 4], S32, UL(1272893353)); /* 38 */ + HH ( c, d, a, b, in[ 7], S33, UL(4139469664)); /* 39 */ + HH ( b, c, d, a, in[10], S34, UL(3200236656)); /* 40 */ + HH ( a, b, c, d, in[13], S31, UL( 681279174)); /* 41 */ + HH ( d, a, b, c, in[ 0], S32, UL(3936430074)); /* 42 */ + HH ( c, d, a, b, in[ 3], S33, UL(3572445317)); /* 43 */ + HH ( b, c, d, a, in[ 6], S34, UL( 76029189)); /* 44 */ + HH ( a, b, c, d, in[ 9], S31, UL(3654602809)); /* 45 */ + HH ( d, a, b, c, in[12], S32, UL(3873151461)); /* 46 */ + HH ( c, d, a, b, in[15], S33, UL( 530742520)); /* 47 */ + HH ( b, c, d, a, in[ 2], S34, UL(3299628645)); /* 48 */ + + /* Round 4 */ +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + II ( a, b, c, d, in[ 0], S41, UL(4096336452)); /* 49 */ + II ( d, a, b, c, in[ 7], S42, UL(1126891415)); /* 50 */ + II ( c, d, a, b, in[14], S43, UL(2878612391)); /* 51 */ + II ( b, c, d, a, in[ 5], S44, UL(4237533241)); /* 52 */ + II ( a, b, c, d, in[12], S41, UL(1700485571)); /* 53 */ + II ( d, a, b, c, in[ 3], S42, UL(2399980690)); /* 54 */ + II ( c, d, a, b, in[10], S43, UL(4293915773)); /* 55 */ + II ( b, c, d, a, in[ 1], S44, UL(2240044497)); /* 56 */ + II ( a, b, c, d, in[ 8], S41, UL(1873313359)); /* 57 */ + II ( d, a, b, c, in[15], S42, UL(4264355552)); /* 58 */ + II ( c, d, a, b, in[ 6], S43, UL(2734768916)); /* 59 */ + II ( b, c, d, a, in[13], S44, UL(1309151649)); /* 60 */ + II ( a, b, c, d, in[ 4], S41, UL(4149444226)); /* 61 */ + II ( d, a, b, c, in[11], S42, UL(3174756917)); /* 62 */ + II ( c, d, a, b, in[ 2], S43, UL( 718787259)); /* 63 */ + II ( b, c, d, a, in[ 9], S44, UL(3951481745)); /* 64 */ + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +#endif /* CHAP_SUPPORT || MD5_SUPPORT */ + +#endif /* PPP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/md5.h b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/md5.h new file mode 100644 index 0000000..e129533 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/md5.h @@ -0,0 +1,55 @@ +/* + *********************************************************************** + ** md5.h -- header file for implementation of MD5 ** + ** RSA Data Security, Inc. MD5 Message-Digest Algorithm ** + ** Created: 2/17/90 RLR ** + ** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version ** + ** Revised (for MD5): RLR 4/27/91 ** + ** -- G modified to have y&~z instead of y&z ** + ** -- FF, GG, HH modified to add in last register done ** + ** -- Access pattern: round 2 works mod 5, round 3 works mod 3 ** + ** -- distinct additive constant for each step ** + ** -- round 4 added, working mod 7 ** + *********************************************************************** + */ + +/* + *********************************************************************** + ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. ** + ** ** + ** License to copy and use this software is granted provided that ** + ** it is identified as the "RSA Data Security, Inc. MD5 Message- ** + ** Digest Algorithm" in all material mentioning or referencing this ** + ** software or this function. ** + ** ** + ** License is also granted to make and use derivative works ** + ** provided that such works are identified as "derived from the RSA ** + ** Data Security, Inc. MD5 Message-Digest Algorithm" in all ** + ** material mentioning or referencing the derived work. ** + ** ** + ** RSA Data Security, Inc. makes no representations concerning ** + ** either the merchantability of this software or the suitability ** + ** of this software for any particular purpose. It is provided "as ** + ** is" without express or implied warranty of any kind. ** + ** ** + ** These notices must be retained in any copies of any part of this ** + ** documentation and/or software. ** + *********************************************************************** + */ + +#ifndef MD5_H +#define MD5_H + +/* Data structure for MD5 (Message-Digest) computation */ +typedef struct { + u32_t i[2]; /* number of _bits_ handled mod 2^64 */ + u32_t buf[4]; /* scratch buffer */ + unsigned char in[64]; /* input buffer */ + unsigned char digest[16]; /* actual digest after MD5Final call */ +} MD5_CTX; + +void MD5Init ( MD5_CTX *mdContext); +void MD5Update( MD5_CTX *mdContext, unsigned char *inBuf, unsigned int inLen); +void MD5Final ( unsigned char hash[], MD5_CTX *mdContext); + +#endif /* MD5_H */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/pap.c b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/pap.c new file mode 100644 index 0000000..e8c45df --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/pap.c @@ -0,0 +1,622 @@ +/***************************************************************************** +* pap.c - Network Password Authentication Protocol program file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 by Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-12-12 Guy Lancaster , Global Election Systems Inc. +* Original. +*****************************************************************************/ +/* + * upap.c - User/Password Authentication Protocol. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "lwip/opt.h" + +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#if PAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "ppp.h" +#include "pppdebug.h" + +#include "auth.h" +#include "pap.h" + +#include + +/***********************************/ +/*** LOCAL FUNCTION DECLARATIONS ***/ +/***********************************/ +/* + * Protocol entry points. + */ +static void upap_init (int); +static void upap_lowerup (int); +static void upap_lowerdown (int); +static void upap_input (int, u_char *, int); +static void upap_protrej (int); + +static void upap_timeout (void *); +static void upap_reqtimeout(void *); +static void upap_rauthreq (upap_state *, u_char *, int, int); +static void upap_rauthack (upap_state *, u_char *, int, int); +static void upap_rauthnak (upap_state *, u_char *, int, int); +static void upap_sauthreq (upap_state *); +static void upap_sresp (upap_state *, u_char, u_char, char *, int); + + +/******************************/ +/*** PUBLIC DATA STRUCTURES ***/ +/******************************/ +struct protent pap_protent = { + PPP_PAP, + upap_init, + upap_input, + upap_protrej, + upap_lowerup, + upap_lowerdown, + NULL, + NULL, +#if 0 + upap_printpkt, + NULL, +#endif + 1, + "PAP", +#if 0 + NULL, + NULL, + NULL +#endif +}; + +upap_state upap[NUM_PPP]; /* UPAP state; one for each unit */ + + + +/***********************************/ +/*** PUBLIC FUNCTION DEFINITIONS ***/ +/***********************************/ +/* + * Set the default login name and password for the pap sessions + */ +void +upap_setloginpasswd(int unit, const char *luser, const char *lpassword) +{ + upap_state *u = &upap[unit]; + + /* Save the username and password we're given */ + u->us_user = luser; + u->us_userlen = strlen(luser); + u->us_passwd = lpassword; + u->us_passwdlen = strlen(lpassword); +} + + +/* + * upap_authwithpeer - Authenticate us with our peer (start client). + * + * Set new state and send authenticate's. + */ +void +upap_authwithpeer(int unit, char *user, char *password) +{ + upap_state *u = &upap[unit]; + + UPAPDEBUG((LOG_INFO, "upap_authwithpeer: %d user=%s password=%s s=%d\n", + unit, user, password, u->us_clientstate)); + + upap_setloginpasswd(unit, user, password); + + u->us_transmits = 0; + + /* Lower layer up yet? */ + if (u->us_clientstate == UPAPCS_INITIAL || + u->us_clientstate == UPAPCS_PENDING) { + u->us_clientstate = UPAPCS_PENDING; + return; + } + + upap_sauthreq(u); /* Start protocol */ +} + + +/* + * upap_authpeer - Authenticate our peer (start server). + * + * Set new state. + */ +void +upap_authpeer(int unit) +{ + upap_state *u = &upap[unit]; + + /* Lower layer up yet? */ + if (u->us_serverstate == UPAPSS_INITIAL || + u->us_serverstate == UPAPSS_PENDING) { + u->us_serverstate = UPAPSS_PENDING; + return; + } + + u->us_serverstate = UPAPSS_LISTEN; + if (u->us_reqtimeout > 0) { + TIMEOUT(upap_reqtimeout, u, u->us_reqtimeout); + } +} + + + +/**********************************/ +/*** LOCAL FUNCTION DEFINITIONS ***/ +/**********************************/ +/* + * upap_init - Initialize a UPAP unit. + */ +static void +upap_init(int unit) +{ + upap_state *u = &upap[unit]; + + UPAPDEBUG((LOG_INFO, "upap_init: %d\n", unit)); + u->us_unit = unit; + u->us_user = NULL; + u->us_userlen = 0; + u->us_passwd = NULL; + u->us_passwdlen = 0; + u->us_clientstate = UPAPCS_INITIAL; + u->us_serverstate = UPAPSS_INITIAL; + u->us_id = 0; + u->us_timeouttime = UPAP_DEFTIMEOUT; + u->us_maxtransmits = 10; + u->us_reqtimeout = UPAP_DEFREQTIME; +} + +/* + * upap_timeout - Retransmission timer for sending auth-reqs expired. + */ +static void +upap_timeout(void *arg) +{ + upap_state *u = (upap_state *) arg; + + UPAPDEBUG((LOG_INFO, "upap_timeout: %d timeout %d expired s=%d\n", + u->us_unit, u->us_timeouttime, u->us_clientstate)); + + if (u->us_clientstate != UPAPCS_AUTHREQ) { + return; + } + + if (u->us_transmits >= u->us_maxtransmits) { + /* give up in disgust */ + UPAPDEBUG((LOG_ERR, "No response to PAP authenticate-requests\n")); + u->us_clientstate = UPAPCS_BADAUTH; + auth_withpeer_fail(u->us_unit, PPP_PAP); + return; + } + + upap_sauthreq(u); /* Send Authenticate-Request */ +} + + +/* + * upap_reqtimeout - Give up waiting for the peer to send an auth-req. + */ +static void +upap_reqtimeout(void *arg) +{ + upap_state *u = (upap_state *) arg; + + if (u->us_serverstate != UPAPSS_LISTEN) { + return; /* huh?? */ + } + + auth_peer_fail(u->us_unit, PPP_PAP); + u->us_serverstate = UPAPSS_BADAUTH; +} + + +/* + * upap_lowerup - The lower layer is up. + * + * Start authenticating if pending. + */ +static void +upap_lowerup(int unit) +{ + upap_state *u = &upap[unit]; + + UPAPDEBUG((LOG_INFO, "upap_lowerup: %d s=%d\n", unit, u->us_clientstate)); + + if (u->us_clientstate == UPAPCS_INITIAL) { + u->us_clientstate = UPAPCS_CLOSED; + } else if (u->us_clientstate == UPAPCS_PENDING) { + upap_sauthreq(u); /* send an auth-request */ + } + + if (u->us_serverstate == UPAPSS_INITIAL) { + u->us_serverstate = UPAPSS_CLOSED; + } else if (u->us_serverstate == UPAPSS_PENDING) { + u->us_serverstate = UPAPSS_LISTEN; + if (u->us_reqtimeout > 0) { + TIMEOUT(upap_reqtimeout, u, u->us_reqtimeout); + } + } +} + + +/* + * upap_lowerdown - The lower layer is down. + * + * Cancel all timeouts. + */ +static void +upap_lowerdown(int unit) +{ + upap_state *u = &upap[unit]; + + UPAPDEBUG((LOG_INFO, "upap_lowerdown: %d s=%d\n", unit, u->us_clientstate)); + + if (u->us_clientstate == UPAPCS_AUTHREQ) { /* Timeout pending? */ + UNTIMEOUT(upap_timeout, u); /* Cancel timeout */ + } + if (u->us_serverstate == UPAPSS_LISTEN && u->us_reqtimeout > 0) { + UNTIMEOUT(upap_reqtimeout, u); + } + + u->us_clientstate = UPAPCS_INITIAL; + u->us_serverstate = UPAPSS_INITIAL; +} + + +/* + * upap_protrej - Peer doesn't speak this protocol. + * + * This shouldn't happen. In any case, pretend lower layer went down. + */ +static void +upap_protrej(int unit) +{ + upap_state *u = &upap[unit]; + + if (u->us_clientstate == UPAPCS_AUTHREQ) { + UPAPDEBUG((LOG_ERR, "PAP authentication failed due to protocol-reject\n")); + auth_withpeer_fail(unit, PPP_PAP); + } + if (u->us_serverstate == UPAPSS_LISTEN) { + UPAPDEBUG((LOG_ERR, "PAP authentication of peer failed (protocol-reject)\n")); + auth_peer_fail(unit, PPP_PAP); + } + upap_lowerdown(unit); +} + + +/* + * upap_input - Input UPAP packet. + */ +static void +upap_input(int unit, u_char *inpacket, int l) +{ + upap_state *u = &upap[unit]; + u_char *inp; + u_char code, id; + int len; + + /* + * Parse header (code, id and length). + * If packet too short, drop it. + */ + inp = inpacket; + if (l < UPAP_HEADERLEN) { + UPAPDEBUG((LOG_INFO, "pap_input: rcvd short header.\n")); + return; + } + GETCHAR(code, inp); + GETCHAR(id, inp); + GETSHORT(len, inp); + if (len < UPAP_HEADERLEN) { + UPAPDEBUG((LOG_INFO, "pap_input: rcvd illegal length.\n")); + return; + } + if (len > l) { + UPAPDEBUG((LOG_INFO, "pap_input: rcvd short packet.\n")); + return; + } + len -= UPAP_HEADERLEN; + + /* + * Action depends on code. + */ + switch (code) { + case UPAP_AUTHREQ: + upap_rauthreq(u, inp, id, len); + break; + + case UPAP_AUTHACK: + upap_rauthack(u, inp, id, len); + break; + + case UPAP_AUTHNAK: + upap_rauthnak(u, inp, id, len); + break; + + default: /* XXX Need code reject */ + break; + } +} + + +/* + * upap_rauth - Receive Authenticate. + */ +static void +upap_rauthreq(upap_state *u, u_char *inp, int id, int len) +{ + u_char ruserlen, rpasswdlen; + char *ruser, *rpasswd; + int retcode; + char *msg; + int msglen; + + UPAPDEBUG((LOG_INFO, "pap_rauth: Rcvd id %d.\n", id)); + + if (u->us_serverstate < UPAPSS_LISTEN) { + return; + } + + /* + * If we receive a duplicate authenticate-request, we are + * supposed to return the same status as for the first request. + */ + if (u->us_serverstate == UPAPSS_OPEN) { + upap_sresp(u, UPAP_AUTHACK, id, "", 0); /* return auth-ack */ + return; + } + if (u->us_serverstate == UPAPSS_BADAUTH) { + upap_sresp(u, UPAP_AUTHNAK, id, "", 0); /* return auth-nak */ + return; + } + + /* + * Parse user/passwd. + */ + if (len < sizeof (u_char)) { + UPAPDEBUG((LOG_INFO, "pap_rauth: rcvd short packet.\n")); + return; + } + GETCHAR(ruserlen, inp); + len -= sizeof (u_char) + ruserlen + sizeof (u_char); + if (len < 0) { + UPAPDEBUG((LOG_INFO, "pap_rauth: rcvd short packet.\n")); + return; + } + ruser = (char *) inp; + INCPTR(ruserlen, inp); + GETCHAR(rpasswdlen, inp); + if (len < rpasswdlen) { + UPAPDEBUG((LOG_INFO, "pap_rauth: rcvd short packet.\n")); + return; + } + rpasswd = (char *) inp; + + /* + * Check the username and password given. + */ + retcode = check_passwd(u->us_unit, ruser, ruserlen, rpasswd, rpasswdlen, &msg, &msglen); + BZERO(rpasswd, rpasswdlen); + + upap_sresp(u, retcode, id, msg, msglen); + + if (retcode == UPAP_AUTHACK) { + u->us_serverstate = UPAPSS_OPEN; + auth_peer_success(u->us_unit, PPP_PAP, ruser, ruserlen); + } else { + u->us_serverstate = UPAPSS_BADAUTH; + auth_peer_fail(u->us_unit, PPP_PAP); + } + + if (u->us_reqtimeout > 0) { + UNTIMEOUT(upap_reqtimeout, u); + } +} + + +/* + * upap_rauthack - Receive Authenticate-Ack. + */ +static void +upap_rauthack(upap_state *u, u_char *inp, int id, int len) +{ + u_char msglen; + char *msg; + + LWIP_UNUSED_ARG(id); + + UPAPDEBUG((LOG_INFO, "pap_rauthack: Rcvd id %d s=%d\n", id, u->us_clientstate)); + + if (u->us_clientstate != UPAPCS_AUTHREQ) { /* XXX */ + return; + } + + /* + * Parse message. + */ + if (len < sizeof (u_char)) { + UPAPDEBUG((LOG_INFO, "pap_rauthack: rcvd short packet.\n")); + return; + } + GETCHAR(msglen, inp); + len -= sizeof (u_char); + if (len < msglen) { + UPAPDEBUG((LOG_INFO, "pap_rauthack: rcvd short packet.\n")); + return; + } + msg = (char *) inp; + PRINTMSG(msg, msglen); + + UNTIMEOUT(upap_timeout, u); /* Cancel timeout */ + u->us_clientstate = UPAPCS_OPEN; + + auth_withpeer_success(u->us_unit, PPP_PAP); +} + + +/* + * upap_rauthnak - Receive Authenticate-Nakk. + */ +static void +upap_rauthnak(upap_state *u, u_char *inp, int id, int len) +{ + u_char msglen; + char *msg; + + LWIP_UNUSED_ARG(id); + + UPAPDEBUG((LOG_INFO, "pap_rauthnak: Rcvd id %d s=%d\n", id, u->us_clientstate)); + + if (u->us_clientstate != UPAPCS_AUTHREQ) { /* XXX */ + return; + } + + /* + * Parse message. + */ + if (len < sizeof (u_char)) { + UPAPDEBUG((LOG_INFO, "pap_rauthnak: rcvd short packet.\n")); + } else { + GETCHAR(msglen, inp); + if(msglen > 0) { + len -= sizeof (u_char); + if (len < msglen) { + UPAPDEBUG((LOG_INFO, "pap_rauthnak: rcvd short packet.\n")); + return; + } + msg = (char *) inp; + PRINTMSG(msg, msglen); + } + } + + u->us_clientstate = UPAPCS_BADAUTH; + + UPAPDEBUG((LOG_ERR, "PAP authentication failed\n")); + auth_withpeer_fail(u->us_unit, PPP_PAP); +} + + +/* + * upap_sauthreq - Send an Authenticate-Request. + */ +static void +upap_sauthreq(upap_state *u) +{ + u_char *outp; + int outlen; + + outlen = UPAP_HEADERLEN + 2 * sizeof (u_char) + + u->us_userlen + u->us_passwdlen; + outp = outpacket_buf[u->us_unit]; + + MAKEHEADER(outp, PPP_PAP); + + PUTCHAR(UPAP_AUTHREQ, outp); + PUTCHAR(++u->us_id, outp); + PUTSHORT(outlen, outp); + PUTCHAR(u->us_userlen, outp); + BCOPY(u->us_user, outp, u->us_userlen); + INCPTR(u->us_userlen, outp); + PUTCHAR(u->us_passwdlen, outp); + BCOPY(u->us_passwd, outp, u->us_passwdlen); + + pppWrite(u->us_unit, outpacket_buf[u->us_unit], outlen + PPP_HDRLEN); + + UPAPDEBUG((LOG_INFO, "pap_sauth: Sent id %d\n", u->us_id)); + + TIMEOUT(upap_timeout, u, u->us_timeouttime); + ++u->us_transmits; + u->us_clientstate = UPAPCS_AUTHREQ; +} + + +/* + * upap_sresp - Send a response (ack or nak). + */ +static void +upap_sresp(upap_state *u, u_char code, u_char id, char *msg, int msglen) +{ + u_char *outp; + int outlen; + + outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen; + outp = outpacket_buf[u->us_unit]; + MAKEHEADER(outp, PPP_PAP); + + PUTCHAR(code, outp); + PUTCHAR(id, outp); + PUTSHORT(outlen, outp); + PUTCHAR(msglen, outp); + BCOPY(msg, outp, msglen); + pppWrite(u->us_unit, outpacket_buf[u->us_unit], outlen + PPP_HDRLEN); + + UPAPDEBUG((LOG_INFO, "pap_sresp: Sent code %d, id %d s=%d\n", code, id, u->us_clientstate)); +} + +#if 0 +/* + * upap_printpkt - print the contents of a PAP packet. + */ +static int upap_printpkt( + u_char *p, + int plen, + void (*printer) (void *, char *, ...), + void *arg +) +{ + LWIP_UNUSED_ARG(p); + LWIP_UNUSED_ARG(plen); + LWIP_UNUSED_ARG(printer); + LWIP_UNUSED_ARG(arg); + return 0; +} +#endif /* 0 */ + +#endif /* PAP_SUPPORT */ + +#endif /* PPP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/pap.h b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/pap.h new file mode 100644 index 0000000..0a09fc8 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/pap.h @@ -0,0 +1,131 @@ +/***************************************************************************** +* pap.h - PPP Password Authentication Protocol header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-12-04 Guy Lancaster , Global Election Systems Inc. +* Original derived from BSD codes. +*****************************************************************************/ +/* + * upap.h - User/Password Authentication Protocol definitions. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef PAP_H +#define PAP_H + +#if PAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +/************************* +*** PUBLIC DEFINITIONS *** +*************************/ +/* + * Packet header = Code, id, length. + */ +#define UPAP_HEADERLEN (sizeof (u_char) + sizeof (u_char) + sizeof (u_short)) + + +/* + * UPAP codes. + */ +#define UPAP_AUTHREQ 1 /* Authenticate-Request */ +#define UPAP_AUTHACK 2 /* Authenticate-Ack */ +#define UPAP_AUTHNAK 3 /* Authenticate-Nak */ + +/* + * Client states. + */ +#define UPAPCS_INITIAL 0 /* Connection down */ +#define UPAPCS_CLOSED 1 /* Connection up, haven't requested auth */ +#define UPAPCS_PENDING 2 /* Connection down, have requested auth */ +#define UPAPCS_AUTHREQ 3 /* We've sent an Authenticate-Request */ +#define UPAPCS_OPEN 4 /* We've received an Ack */ +#define UPAPCS_BADAUTH 5 /* We've received a Nak */ + +/* + * Server states. + */ +#define UPAPSS_INITIAL 0 /* Connection down */ +#define UPAPSS_CLOSED 1 /* Connection up, haven't requested auth */ +#define UPAPSS_PENDING 2 /* Connection down, have requested auth */ +#define UPAPSS_LISTEN 3 /* Listening for an Authenticate */ +#define UPAPSS_OPEN 4 /* We've sent an Ack */ +#define UPAPSS_BADAUTH 5 /* We've sent a Nak */ + + +/************************ +*** PUBLIC DATA TYPES *** +************************/ + +/* + * Each interface is described by upap structure. + */ +typedef struct upap_state { + int us_unit; /* Interface unit number */ + const char *us_user; /* User */ + int us_userlen; /* User length */ + const char *us_passwd; /* Password */ + int us_passwdlen; /* Password length */ + int us_clientstate; /* Client state */ + int us_serverstate; /* Server state */ + u_char us_id; /* Current id */ + int us_timeouttime; /* Timeout (seconds) for auth-req retrans. */ + int us_transmits; /* Number of auth-reqs sent */ + int us_maxtransmits; /* Maximum number of auth-reqs to send */ + int us_reqtimeout; /* Time to wait for auth-req from peer */ +} upap_state; + + +/*********************** +*** PUBLIC FUNCTIONS *** +***********************/ + +extern upap_state upap[]; + +void upap_setloginpasswd(int unit, const char *luser, const char *lpassword); +void upap_authwithpeer (int, char *, char *); +void upap_authpeer (int); + +extern struct protent pap_protent; + +#endif /* PAP_SUPPORT */ + +#endif /* PAP_H */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/ppp.c b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/ppp.c new file mode 100644 index 0000000..13fa5ed --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/ppp.c @@ -0,0 +1,1989 @@ +/***************************************************************************** +* ppp.c - Network Point to Point Protocol program file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 by Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-11-05 Guy Lancaster , Global Election Systems Inc. +* Original. +*****************************************************************************/ + +/* + * ppp_defs.h - PPP definitions. + * + * if_pppvar.h - private structures and declarations for PPP. + * + * Copyright (c) 1994 The Australian National University. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, provided that the above copyright + * notice appears in all copies. This software is provided without any + * warranty, express or implied. The Australian National University + * makes no representations about the suitability of this software for + * any purpose. + * + * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY + * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO + * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, + * OR MODIFICATIONS. + */ + +/* + * if_ppp.h - Point-to-Point Protocol definitions. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "lwip/opt.h" + +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/ip.h" /* for ip_input() */ + +#include "ppp.h" +#include "pppdebug.h" + +#include "randm.h" +#include "fsm.h" +#if PAP_SUPPORT +#include "pap.h" +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT +#include "chap.h" +#endif /* CHAP_SUPPORT */ +#include "ipcp.h" +#include "lcp.h" +#include "magic.h" +#include "auth.h" +#if VJ_SUPPORT +#include "vj.h" +#endif /* VJ_SUPPORT */ +#if PPPOE_SUPPORT +#include "netif/ppp_oe.h" +#endif /* PPPOE_SUPPORT */ + +#include + +/*************************/ +/*** LOCAL DEFINITIONS ***/ +/*************************/ + +/* + * The basic PPP frame. + */ +#define PPP_ADDRESS(p) (((u_char *)(p))[0]) +#define PPP_CONTROL(p) (((u_char *)(p))[1]) +#define PPP_PROTOCOL(p) ((((u_char *)(p))[2] << 8) + ((u_char *)(p))[3]) + +/* PPP packet parser states. Current state indicates operation yet to be + * completed. */ +typedef enum { + PDIDLE = 0, /* Idle state - waiting. */ + PDSTART, /* Process start flag. */ + PDADDRESS, /* Process address field. */ + PDCONTROL, /* Process control field. */ + PDPROTOCOL1, /* Process protocol field 1. */ + PDPROTOCOL2, /* Process protocol field 2. */ + PDDATA /* Process data byte. */ +} PPPDevStates; + +#define ESCAPE_P(accm, c) ((accm)[(c) >> 3] & pppACCMMask[c & 0x07]) + +/************************/ +/*** LOCAL DATA TYPES ***/ +/************************/ +/* + * PPP interface control block. + */ +typedef struct PPPControl_s { + char openFlag; /* True when in use. */ +#if PPPOE_SUPPORT + struct netif *ethif; + struct pppoe_softc *pppoe_sc; +#endif /* PPPOE_SUPPORT */ + int if_up; /* True when the interface is up. */ + int errCode; /* Code indicating why interface is down. */ +#if PPPOS_SUPPORT + sio_fd_t fd; /* File device ID of port. */ + int kill_link; /* Shut the link down. */ + int sig_hup; /* Carrier lost. */ + struct pbuf *inHead, *inTail; /* The input packet. */ + PPPDevStates inState; /* The input process state. */ + char inEscaped; /* Escape next character. */ + u16_t inProtocol; /* The input protocol code. */ + u16_t inFCS; /* Input Frame Check Sequence value. */ +#endif /* PPPOS_SUPPORT */ + int mtu; /* Peer's mru */ + int pcomp; /* Does peer accept protocol compression? */ + int accomp; /* Does peer accept addr/ctl compression? */ + u_long lastXMit; /* Time of last transmission. */ + ext_accm inACCM; /* Async-Ctl-Char-Map for input. */ + ext_accm outACCM; /* Async-Ctl-Char-Map for output. */ +#if PPPOS_SUPPORT && VJ_SUPPORT + int vjEnabled; /* Flag indicating VJ compression enabled. */ + struct vjcompress vjComp; /* Van Jacobson compression header. */ +#endif /* PPPOS_SUPPORT && VJ_SUPPORT */ + + struct netif netif; + + struct ppp_addrs addrs; + + void (*linkStatusCB)(void *ctx, int errCode, void *arg); + void *linkStatusCtx; + +} PPPControl; + + +/* + * Ioctl definitions. + */ + +struct npioctl { + int protocol; /* PPP procotol, e.g. PPP_IP */ + enum NPmode mode; +}; + + + +/***********************************/ +/*** LOCAL FUNCTION DECLARATIONS ***/ +/***********************************/ +#if PPPOS_SUPPORT +static void pppMain(void *pd); +static void pppDrop(PPPControl *pc); +static void pppInProc(int pd, u_char *s, int l); +#endif /* PPPOS_SUPPORT */ + + +/******************************/ +/*** PUBLIC DATA STRUCTURES ***/ +/******************************/ +u_long subnetMask; + +static PPPControl pppControl[NUM_PPP]; /* The PPP interface control blocks. */ + +/* + * PPP Data Link Layer "protocol" table. + * One entry per supported protocol. + * The last entry must be NULL. + */ +struct protent *ppp_protocols[] = { + &lcp_protent, +#if PAP_SUPPORT + &pap_protent, +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + &chap_protent, +#endif /* CHAP_SUPPORT */ +#if CBCP_SUPPORT + &cbcp_protent, +#endif /* CBCP_SUPPORT */ + &ipcp_protent, +#if CCP_SUPPORT + &ccp_protent, +#endif /* CCP_SUPPORT */ + NULL +}; + + +/* + * Buffers for outgoing packets. This must be accessed only from the appropriate + * PPP task so that it doesn't need to be protected to avoid collisions. + */ +u_char outpacket_buf[NUM_PPP][PPP_MRU+PPP_HDRLEN]; + + +/*****************************/ +/*** LOCAL DATA STRUCTURES ***/ +/*****************************/ + +#if PPPOS_SUPPORT +/* + * FCS lookup table as calculated by genfcstab. + */ +static const u_short fcstab[256] = { + 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, + 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, + 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, + 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, + 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, + 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, + 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, + 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, + 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, + 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, + 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, + 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, + 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, + 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, + 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, + 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, + 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, + 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, + 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, + 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, + 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, + 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, + 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, + 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, + 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, + 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, + 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, + 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, + 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, + 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, + 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 +}; + +/* PPP's Asynchronous-Control-Character-Map. The mask array is used + * to select the specific bit for a character. */ +static u_char pppACCMMask[] = { + 0x01, + 0x02, + 0x04, + 0x08, + 0x10, + 0x20, + 0x40, + 0x80 +}; + + +void +pppMainWakeup(int pd) +{ + PPPDEBUG((LOG_DEBUG, "pppMainWakeup: unit %d\n", pd)); + sio_read_abort(pppControl[pd].fd); +} +#endif /* PPPOS_SUPPORT */ + +void +pppLinkTerminated(int pd) +{ + PPPDEBUG((LOG_DEBUG, "pppLinkTerminated: unit %d\n", pd)); + +#if PPPOE_SUPPORT + if(pppControl[pd].ethif) { + pppoe_disconnect(pppControl[pd].pppoe_sc); + } else +#endif /* PPPOE_SUPPORT */ + { +#if PPPOS_SUPPORT + pppMainWakeup(pd); +#endif /* PPPOS_SUPPORT */ + } +} + +void +pppLinkDown(int pd) +{ + PPPDEBUG((LOG_DEBUG, "pppLinkDown: unit %d\n", pd)); + +#if PPPOE_SUPPORT + if(pppControl[pd].ethif) { + pppoe_disconnect(pppControl[pd].pppoe_sc); + } else +#endif /* PPPOE_SUPPORT */ + { +#if PPPOS_SUPPORT + pppMainWakeup(pd); +#endif /* PPPOS_SUPPORT */ + } +} + +/* these callbacks are necessary because lcp_* functions + must be called in the same context as pppInput(), + namely the tcpip_thread(), essentially because + they manipulate timeouts which are thread-private +*/ + +static void +pppStartCB(void *arg) +{ + int pd = (int)arg; + + PPPDEBUG((LOG_DEBUG, "pppStartCB: unit %d\n", pd)); + lcp_lowerup(pd); + lcp_open(pd); /* Start protocol */ +} + +static void +pppStopCB(void *arg) +{ + int pd = (int)arg; + + PPPDEBUG((LOG_DEBUG, "pppStopCB: unit %d\n", pd)); + lcp_close(pd, "User request"); +} + +static void +pppHupCB(void *arg) +{ + int pd = (int)arg; + + PPPDEBUG((LOG_DEBUG, "pppHupCB: unit %d\n", pd)); + lcp_lowerdown(pd); + link_terminated(pd); +} + +/***********************************/ +/*** PUBLIC FUNCTION DEFINITIONS ***/ +/***********************************/ +/* Initialize the PPP subsystem. */ + +struct ppp_settings ppp_settings; + +void +pppInit(void) +{ + struct protent *protp; + int i, j; + + memset(&ppp_settings, 0, sizeof(ppp_settings)); + ppp_settings.usepeerdns = 1; + pppSetAuth(PPPAUTHTYPE_NONE, NULL, NULL); + + magicInit(); + + subnetMask = htonl(0xffffff00); + + for (i = 0; i < NUM_PPP; i++) { + pppControl[i].openFlag = 0; + + /* + * Initialize to the standard option set. + */ + for (j = 0; (protp = ppp_protocols[j]) != NULL; ++j) { + (*protp->init)(i); + } + } + +#if PPPOE_SUPPORT + pppoe_init(); +#endif /* PPPOE_SUPPORT */ +} + +void +pppSetAuth(enum pppAuthType authType, const char *user, const char *passwd) +{ + switch(authType) { + case PPPAUTHTYPE_NONE: + default: +#ifdef LWIP_PPP_STRICT_PAP_REJECT + ppp_settings.refuse_pap = 1; +#else /* LWIP_PPP_STRICT_PAP_REJECT */ + /* some providers request pap and accept an empty login/pw */ + ppp_settings.refuse_pap = 0; +#endif /* LWIP_PPP_STRICT_PAP_REJECT */ + ppp_settings.refuse_chap = 1; + break; + + case PPPAUTHTYPE_ANY: + /* Warning: Using PPPAUTHTYPE_ANY might have security consequences. + * RFC 1994 says: + * + * In practice, within or associated with each PPP server, there is a + * database which associates "user" names with authentication + * information ("secrets"). It is not anticipated that a particular + * named user would be authenticated by multiple methods. This would + * make the user vulnerable to attacks which negotiate the least secure + * method from among a set (such as PAP rather than CHAP). If the same + * secret was used, PAP would reveal the secret to be used later with + * CHAP. + * + * Instead, for each user name there should be an indication of exactly + * one method used to authenticate that user name. If a user needs to + * make use of different authentication methods under different + * circumstances, then distinct user names SHOULD be employed, each of + * which identifies exactly one authentication method. + * + */ + ppp_settings.refuse_pap = 0; + ppp_settings.refuse_chap = 0; + break; + + case PPPAUTHTYPE_PAP: + ppp_settings.refuse_pap = 0; + ppp_settings.refuse_chap = 1; + break; + + case PPPAUTHTYPE_CHAP: + ppp_settings.refuse_pap = 1; + ppp_settings.refuse_chap = 0; + break; + } + + if(user) { + strncpy(ppp_settings.user, user, sizeof(ppp_settings.user)-1); + ppp_settings.user[sizeof(ppp_settings.user)-1] = '\0'; + } else { + ppp_settings.user[0] = '\0'; + } + + if(passwd) { + strncpy(ppp_settings.passwd, passwd, sizeof(ppp_settings.passwd)-1); + ppp_settings.passwd[sizeof(ppp_settings.passwd)-1] = '\0'; + } else { + ppp_settings.passwd[0] = '\0'; + } +} + +#if PPPOS_SUPPORT +/* Open a new PPP connection using the given I/O device. + * This initializes the PPP control block but does not + * attempt to negotiate the LCP session. If this port + * connects to a modem, the modem connection must be + * established before calling this. + * Return a new PPP connection descriptor on success or + * an error code (negative) on failure. */ +int +pppOverSerialOpen(sio_fd_t fd, void (*linkStatusCB)(void *ctx, int errCode, void *arg), void *linkStatusCtx) +{ + PPPControl *pc; + int pd; + + /* Find a free PPP session descriptor. Critical region? */ + for (pd = 0; pd < NUM_PPP && pppControl[pd].openFlag != 0; pd++); + + if (pd >= NUM_PPP) { + pd = PPPERR_OPEN; + } else { + pppControl[pd].openFlag = !0; + } + + /* Launch a deamon thread. */ + if (pd >= 0) { + pppControl[pd].openFlag = 1; + + lcp_init(pd); + pc = &pppControl[pd]; + pc->fd = fd; +#if PPPOE_SUPPORT + pc->ethif= NULL; +#endif /* PPPOE_SUPPORT */ + pc->kill_link = 0; + pc->sig_hup = 0; + pc->if_up = 0; + pc->errCode = 0; + pc->inState = PDIDLE; + pc->inHead = NULL; + pc->inTail = NULL; + pc->inEscaped = 0; + pc->lastXMit = 0; + +#if VJ_SUPPORT + pc->vjEnabled = 0; + vj_compress_init(&pc->vjComp); +#endif /* VJ_SUPPORT */ + + /* + * Default the in and out accm so that escape and flag characters + * are always escaped. + */ + memset(pc->inACCM, 0, sizeof(ext_accm)); + pc->inACCM[15] = 0x60; + memset(pc->outACCM, 0, sizeof(ext_accm)); + pc->outACCM[15] = 0x60; + + pc->linkStatusCB = linkStatusCB; + pc->linkStatusCtx = linkStatusCtx; + + sys_thread_new(PPP_THREAD_NAME, pppMain, (void*)pd, PPP_THREAD_STACKSIZE, PPP_THREAD_PRIO); + if(!linkStatusCB) { + while(pd >= 0 && !pc->if_up) { + sys_msleep(500); + if (lcp_phase[pd] == PHASE_DEAD) { + pppClose(pd); + if (pc->errCode) { + pd = pc->errCode; + } else { + pd = PPPERR_CONNECT; + } + } + } + } + } + + return pd; +} +#endif /* PPPOS_SUPPORT */ + +#if PPPOE_SUPPORT +static void pppOverEthernetLinkStatusCB(int pd, int up); + +void +pppOverEthernetClose(int pd) +{ + PPPControl* pc = &pppControl[pd]; + + /* *TJL* There's no lcp_deinit */ + lcp_close(pd, NULL); + + pppoe_destroy(&pc->netif); +} + +int pppOverEthernetOpen(struct netif *ethif, const char *service_name, const char *concentrator_name, void (*linkStatusCB)(void *ctx, int errCode, void *arg), void *linkStatusCtx) +{ + PPPControl *pc; + int pd; + + LWIP_UNUSED_ARG(service_name); + LWIP_UNUSED_ARG(concentrator_name); + + /* Find a free PPP session descriptor. Critical region? */ + for (pd = 0; pd < NUM_PPP && pppControl[pd].openFlag != 0; pd++); + if (pd >= NUM_PPP) { + pd = PPPERR_OPEN; + } else { + pppControl[pd].openFlag = !0; + } + + /* PPP session descriptor found, start PPPoE */ + if (pd >= 0) { + + pppControl[pd].openFlag = 1; + + lcp_init(pd); + + lcp_wantoptions[pd].mru = PPPOE_MAXMTU; + lcp_wantoptions[pd].neg_asyncmap = 0; + lcp_wantoptions[pd].neg_pcompression = 0; + lcp_wantoptions[pd].neg_accompression = 0; + + lcp_allowoptions[pd].mru = PPPOE_MAXMTU; + lcp_allowoptions[pd].neg_asyncmap = 0; + lcp_allowoptions[pd].neg_pcompression = 0; + lcp_allowoptions[pd].neg_accompression = 0; + + pc = &pppControl[pd]; + pc->if_up = 0; + pc->errCode = 0; + pc->lastXMit = 0; +#if PPPOS_SUPPORT + pc->kill_link = 0; + pc->sig_hup = 0; + pc->inState = PDIDLE; + pc->inHead = NULL; + pc->inTail = NULL; + pc->inEscaped = 0; +#if VJ_SUPPORT + pc->vjEnabled = 0; +#endif /* VJ_SUPPORT */ +#endif /* PPPOS_SUPPORT */ + pc->ethif= ethif; + + memset(pc->inACCM, 0, sizeof(ext_accm)); + memset(pc->outACCM, 0, sizeof(ext_accm)); + + pc->linkStatusCB = linkStatusCB; + pc->linkStatusCtx = linkStatusCtx; + + if(pppoe_create(ethif, pd, pppOverEthernetLinkStatusCB, &pc->pppoe_sc) != ERR_OK) { + pc->openFlag = 0; + return PPPERR_OPEN; + } + + pppoe_connect(pc->pppoe_sc); + + if(!linkStatusCB) { + while(pd >= 0 && !pc->if_up) { + sys_msleep(500); + if (lcp_phase[pd] == PHASE_DEAD) { + pppClose(pd); + if (pc->errCode) { + pd = pc->errCode; + } else { + pd = PPPERR_CONNECT; + } + } + } + } + } + + return pd; +} +#endif /* PPPOE_SUPPORT */ + + +/* Close a PPP connection and release the descriptor. + * Any outstanding packets in the queues are dropped. + * Return 0 on success, an error code on failure. */ +int +pppClose(int pd) +{ + PPPControl *pc = &pppControl[pd]; + int st = 0; + + /* Disconnect */ +#if PPPOE_SUPPORT + if(pc->ethif) { + PPPDEBUG((LOG_DEBUG, "pppClose: unit %d kill_link -> pppStopCB\n", pd)); + pc->errCode = PPPERR_USER; + /* This will leave us at PHASE_DEAD. */ + tcpip_callback(pppStopCB, (void*)pd); + } else +#endif /* PPPOE_SUPPORT */ + { +#if PPPOS_SUPPORT + pc->kill_link = !0; + pppMainWakeup(pd); +#endif /* PPPOS_SUPPORT */ + } + + if(!pc->linkStatusCB) { + while(st >= 0 && lcp_phase[pd] != PHASE_DEAD) { + sys_msleep(500); + break; + } + } + + return st; +} + +/* This function is called when carrier is lost on the PPP channel. */ +void +pppSigHUP(int pd) +{ + PPPControl *pc = &pppControl[pd]; + +#if PPPOE_SUPPORT + if(pc->ethif) { + PPPDEBUG((LOG_DEBUG, "pppSigHUP: unit %d sig_hup -> pppHupCB\n", pd)); + tcpip_callback(pppHupCB, (void*)pd); + } else +#endif /* PPPOE_SUPPORT */ + { +#if PPPOS_SUPPORT + pc->sig_hup = 1; + pppMainWakeup(pd); +#endif /* PPPOS_SUPPORT */ + } +} + +#if PPPOS_SUPPORT +static void +nPut(PPPControl *pc, struct pbuf *nb) +{ + struct pbuf *b; + int c; + + for(b = nb; b != NULL; b = b->next) { + if((c = sio_write(pc->fd, b->payload, b->len)) != b->len) { + PPPDEBUG((LOG_WARNING, + "PPP nPut: incomplete sio_write(%d,, %u) = %d\n", pc->fd, b->len, c)); + LINK_STATS_INC(link.err); + pc->lastXMit = 0; /* prepend PPP_FLAG to next packet */ + break; + } + } + + pbuf_free(nb); + LINK_STATS_INC(link.xmit); +} + +/* + * pppAppend - append given character to end of given pbuf. If outACCM + * is not NULL and the character needs to be escaped, do so. + * If pbuf is full, append another. + * Return the current pbuf. + */ +static struct pbuf * +pppAppend(u_char c, struct pbuf *nb, ext_accm *outACCM) +{ + struct pbuf *tb = nb; + + /* Make sure there is room for the character and an escape code. + * Sure we don't quite fill the buffer if the character doesn't + * get escaped but is one character worth complicating this? */ + /* Note: We assume no packet header. */ + if (nb && (PBUF_POOL_BUFSIZE - nb->len) < 2) { + tb = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); + if (tb) { + nb->next = tb; + } else { + LINK_STATS_INC(link.memerr); + } + nb = tb; + } + + if (nb) { + if (outACCM && ESCAPE_P(*outACCM, c)) { + *((u_char*)nb->payload + nb->len++) = PPP_ESCAPE; + *((u_char*)nb->payload + nb->len++) = c ^ PPP_TRANS; + } else { + *((u_char*)nb->payload + nb->len++) = c; + } + } + + return tb; +} +#endif /* PPPOS_SUPPORT */ + +#if PPPOE_SUPPORT +static err_t +pppifOutputOverEthernet(int pd, struct pbuf *p) +{ + PPPControl *pc = &pppControl[pd]; + struct pbuf *pb; + u_short protocol = PPP_IP; + int i=0; + + pb = pbuf_alloc(PBUF_LINK, pppoe_hdrlen + sizeof(protocol), PBUF_RAM); + if(!pb) { + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.proterr); + return ERR_MEM; + } + + pbuf_header(pb, -pppoe_hdrlen); + + pc->lastXMit = sys_jiffies(); + + if (!pc->pcomp || protocol > 0xFF) { + *((u_char*)pb->payload + i++) = (protocol >> 8) & 0xFF; + } + *((u_char*)pb->payload + i) = protocol & 0xFF; + + pbuf_chain(pb, p); + + if(pppoe_xmit(pc->pppoe_sc, pb) != ERR_OK) { + LINK_STATS_INC(link.err); + return PPPERR_DEVICE; + } + + LINK_STATS_INC(link.xmit); + return ERR_OK; +} +#endif /* PPPOE_SUPPORT */ + +/* Send a packet on the given connection. */ +static err_t +pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *ipaddr) +{ + int pd = (int)netif->state; + PPPControl *pc = &pppControl[pd]; +#if PPPOS_SUPPORT + u_short protocol = PPP_IP; + u_int fcsOut = PPP_INITFCS; + struct pbuf *headMB = NULL, *tailMB = NULL, *p; + u_char c; +#endif /* PPPOS_SUPPORT */ + + LWIP_UNUSED_ARG(ipaddr); + + /* Validate parameters. */ + /* We let any protocol value go through - it can't hurt us + * and the peer will just drop it if it's not accepting it. */ + if (pd < 0 || pd >= NUM_PPP || !pc->openFlag || !pb) { + PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: bad parms prot=%d pb=%p\n", + pd, PPP_IP, pb)); + LINK_STATS_INC(link.opterr); + LINK_STATS_INC(link.drop); + return ERR_ARG; + } + + /* Check that the link is up. */ + if (lcp_phase[pd] == PHASE_DEAD) { + PPPDEBUG((LOG_ERR, "pppifOutput[%d]: link not up\n", pd)); + LINK_STATS_INC(link.rterr); + LINK_STATS_INC(link.drop); + return ERR_RTE; + } + +#if PPPOE_SUPPORT + if(pc->ethif) { + return pppifOutputOverEthernet(pd, pb); + } +#endif /* PPPOE_SUPPORT */ + +#if PPPOS_SUPPORT + /* Grab an output buffer. */ + headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); + if (headMB == NULL) { + PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: first alloc fail\n", pd)); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + return ERR_MEM; + } + +#if VJ_SUPPORT + /* + * Attempt Van Jacobson header compression if VJ is configured and + * this is an IP packet. + */ + if (protocol == PPP_IP && pc->vjEnabled) { + switch (vj_compress_tcp(&pc->vjComp, pb)) { + case TYPE_IP: + /* No change... + protocol = PPP_IP_PROTOCOL; */ + break; + case TYPE_COMPRESSED_TCP: + protocol = PPP_VJC_COMP; + break; + case TYPE_UNCOMPRESSED_TCP: + protocol = PPP_VJC_UNCOMP; + break; + default: + PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: bad IP packet\n", pd)); + LINK_STATS_INC(link.proterr); + LINK_STATS_INC(link.drop); + pbuf_free(headMB); + return ERR_VAL; + } + } +#endif /* VJ_SUPPORT */ + + tailMB = headMB; + + /* Build the PPP header. */ + if ((sys_jiffies() - pc->lastXMit) >= PPP_MAXIDLEFLAG) { + tailMB = pppAppend(PPP_FLAG, tailMB, NULL); + } + + pc->lastXMit = sys_jiffies(); + if (!pc->accomp) { + fcsOut = PPP_FCS(fcsOut, PPP_ALLSTATIONS); + tailMB = pppAppend(PPP_ALLSTATIONS, tailMB, &pc->outACCM); + fcsOut = PPP_FCS(fcsOut, PPP_UI); + tailMB = pppAppend(PPP_UI, tailMB, &pc->outACCM); + } + if (!pc->pcomp || protocol > 0xFF) { + c = (protocol >> 8) & 0xFF; + fcsOut = PPP_FCS(fcsOut, c); + tailMB = pppAppend(c, tailMB, &pc->outACCM); + } + c = protocol & 0xFF; + fcsOut = PPP_FCS(fcsOut, c); + tailMB = pppAppend(c, tailMB, &pc->outACCM); + + /* Load packet. */ + for(p = pb; p; p = p->next) { + int n; + u_char *sPtr; + + sPtr = (u_char*)p->payload; + n = p->len; + while (n-- > 0) { + c = *sPtr++; + + /* Update FCS before checking for special characters. */ + fcsOut = PPP_FCS(fcsOut, c); + + /* Copy to output buffer escaping special characters. */ + tailMB = pppAppend(c, tailMB, &pc->outACCM); + } + } + + /* Add FCS and trailing flag. */ + c = ~fcsOut & 0xFF; + tailMB = pppAppend(c, tailMB, &pc->outACCM); + c = (~fcsOut >> 8) & 0xFF; + tailMB = pppAppend(c, tailMB, &pc->outACCM); + tailMB = pppAppend(PPP_FLAG, tailMB, NULL); + + /* If we failed to complete the packet, throw it away. */ + if (!tailMB) { + PPPDEBUG((LOG_WARNING, + "pppifOutput[%d]: Alloc err - dropping proto=%d\n", + pd, protocol)); + pbuf_free(headMB); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + return ERR_MEM; + } + + /* Send it. */ + PPPDEBUG((LOG_INFO, "pppifOutput[%d]: proto=0x%04X\n", pd, protocol)); + + nPut(pc, headMB); +#endif /* PPPOS_SUPPORT */ + + return ERR_OK; +} + +/* Get and set parameters for the given connection. + * Return 0 on success, an error code on failure. */ +int +pppIOCtl(int pd, int cmd, void *arg) +{ + PPPControl *pc = &pppControl[pd]; + int st = 0; + + if (pd < 0 || pd >= NUM_PPP) { + st = PPPERR_PARAM; + } else { + switch(cmd) { + case PPPCTLG_UPSTATUS: /* Get the PPP up status. */ + if (arg) { + *(int *)arg = (int)(pc->if_up); + } else { + st = PPPERR_PARAM; + } + break; + case PPPCTLS_ERRCODE: /* Set the PPP error code. */ + if (arg) { + pc->errCode = *(int *)arg; + } else { + st = PPPERR_PARAM; + } + break; + case PPPCTLG_ERRCODE: /* Get the PPP error code. */ + if (arg) { + *(int *)arg = (int)(pc->errCode); + } else { + st = PPPERR_PARAM; + } + break; +#if PPPOS_SUPPORT + case PPPCTLG_FD: + if (arg) { + *(sio_fd_t *)arg = pc->fd; + } else { + st = PPPERR_PARAM; + } + break; +#endif /* PPPOS_SUPPORT */ + default: + st = PPPERR_PARAM; + break; + } + } + + return st; +} + +/* + * Return the Maximum Transmission Unit for the given PPP connection. + */ +u_int +pppMTU(int pd) +{ + PPPControl *pc = &pppControl[pd]; + u_int st; + + /* Validate parameters. */ + if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { + st = 0; + } else { + st = pc->mtu; + } + + return st; +} + +#if PPPOE_SUPPORT +int +pppWriteOverEthernet(int pd, const u_char *s, int n) +{ + PPPControl *pc = &pppControl[pd]; + struct pbuf *pb; + + /* skip address & flags */ + s += 2; + n -= 2; + + pb = pbuf_alloc(PBUF_LINK, pppoe_hdrlen + n, PBUF_RAM); + if(!pb) { + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.proterr); + return PPPERR_ALLOC; + } + + pbuf_header(pb, -pppoe_hdrlen); + + pc->lastXMit = sys_jiffies(); + + MEMCPY(pb->payload, s, n); + + if(pppoe_xmit(pc->pppoe_sc, pb) != ERR_OK) { + LINK_STATS_INC(link.err); + return PPPERR_DEVICE; + } + + LINK_STATS_INC(link.xmit); + return PPPERR_NONE; +} +#endif /* PPPOE_SUPPORT */ + +/* + * Write n characters to a ppp link. + * RETURN: >= 0 Number of characters written + * -1 Failed to write to device + */ +int +pppWrite(int pd, const u_char *s, int n) +{ + PPPControl *pc = &pppControl[pd]; +#if PPPOS_SUPPORT + u_char c; + u_int fcsOut; + struct pbuf *headMB, *tailMB; +#endif /* PPPOS_SUPPORT */ + +#if PPPOE_SUPPORT + if(pc->ethif) { + return pppWriteOverEthernet(pd, s, n); + } +#endif /* PPPOE_SUPPORT */ + +#if PPPOS_SUPPORT + headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); + if (headMB == NULL) { + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.proterr); + return PPPERR_ALLOC; + } + + tailMB = headMB; + + /* If the link has been idle, we'll send a fresh flag character to + * flush any noise. */ + if ((sys_jiffies() - pc->lastXMit) >= PPP_MAXIDLEFLAG) { + tailMB = pppAppend(PPP_FLAG, tailMB, NULL); + } + pc->lastXMit = sys_jiffies(); + + fcsOut = PPP_INITFCS; + /* Load output buffer. */ + while (n-- > 0) { + c = *s++; + + /* Update FCS before checking for special characters. */ + fcsOut = PPP_FCS(fcsOut, c); + + /* Copy to output buffer escaping special characters. */ + tailMB = pppAppend(c, tailMB, &pc->outACCM); + } + + /* Add FCS and trailing flag. */ + c = ~fcsOut & 0xFF; + tailMB = pppAppend(c, tailMB, &pc->outACCM); + c = (~fcsOut >> 8) & 0xFF; + tailMB = pppAppend(c, tailMB, &pc->outACCM); + tailMB = pppAppend(PPP_FLAG, tailMB, NULL); + + /* If we failed to complete the packet, throw it away. + * Otherwise send it. */ + if (!tailMB) { + PPPDEBUG((LOG_WARNING, + "pppWrite[%d]: Alloc err - dropping pbuf len=%d\n", pd, headMB->len)); + /*"pppWrite[%d]: Alloc err - dropping %d:%.*H", pd, headMB->len, LWIP_MIN(headMB->len * 2, 40), headMB->payload)); */ + pbuf_free(headMB); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.proterr); + return PPPERR_ALLOC; + } + + PPPDEBUG((LOG_INFO, "pppWrite[%d]: len=%d\n", pd, headMB->len)); + /* "pppWrite[%d]: %d:%.*H", pd, headMB->len, LWIP_MIN(headMB->len * 2, 40), headMB->payload)); */ + nPut(pc, headMB); +#endif /* PPPOS_SUPPORT */ + + return PPPERR_NONE; +} + +/* + * ppp_send_config - configure the transmit characteristics of + * the ppp interface. + */ +void +ppp_send_config( int unit, int mtu, u32_t asyncmap, int pcomp, int accomp) +{ + PPPControl *pc = &pppControl[unit]; + int i; + + pc->mtu = mtu; + pc->pcomp = pcomp; + pc->accomp = accomp; + + /* Load the ACCM bits for the 32 control codes. */ + for (i = 0; i < 32/8; i++) { + pc->outACCM[i] = (u_char)((asyncmap >> (8 * i)) & 0xFF); + } + PPPDEBUG((LOG_INFO, "ppp_send_config[%d]: outACCM=%X %X %X %X\n", + unit, + pc->outACCM[0], pc->outACCM[1], pc->outACCM[2], pc->outACCM[3])); +} + + +/* + * ppp_set_xaccm - set the extended transmit ACCM for the interface. + */ +void +ppp_set_xaccm(int unit, ext_accm *accm) +{ + SMEMCPY(pppControl[unit].outACCM, accm, sizeof(ext_accm)); + PPPDEBUG((LOG_INFO, "ppp_set_xaccm[%d]: outACCM=%X %X %X %X\n", + unit, + pppControl[unit].outACCM[0], + pppControl[unit].outACCM[1], + pppControl[unit].outACCM[2], + pppControl[unit].outACCM[3])); +} + + +/* + * ppp_recv_config - configure the receive-side characteristics of + * the ppp interface. + */ +void +ppp_recv_config( int unit, int mru, u32_t asyncmap, int pcomp, int accomp) +{ + PPPControl *pc = &pppControl[unit]; + int i; + + LWIP_UNUSED_ARG(accomp); + LWIP_UNUSED_ARG(pcomp); + LWIP_UNUSED_ARG(mru); + + /* Load the ACCM bits for the 32 control codes. */ + for (i = 0; i < 32 / 8; i++) { + pc->inACCM[i] = (u_char)(asyncmap >> (i * 8)); + } + PPPDEBUG((LOG_INFO, "ppp_recv_config[%d]: inACCM=%X %X %X %X\n", + unit, + pc->inACCM[0], pc->inACCM[1], pc->inACCM[2], pc->inACCM[3])); +} + +#if 0 +/* + * ccp_test - ask kernel whether a given compression method + * is acceptable for use. Returns 1 if the method and parameters + * are OK, 0 if the method is known but the parameters are not OK + * (e.g. code size should be reduced), or -1 if the method is unknown. + */ +int +ccp_test( int unit, int opt_len, int for_transmit, u_char *opt_ptr) +{ + return 0; /* XXX Currently no compression. */ +} + +/* + * ccp_flags_set - inform kernel about the current state of CCP. + */ +void +ccp_flags_set(int unit, int isopen, int isup) +{ + /* XXX */ +} + +/* + * ccp_fatal_error - returns 1 if decompression was disabled as a + * result of an error detected after decompression of a packet, + * 0 otherwise. This is necessary because of patent nonsense. + */ +int +ccp_fatal_error(int unit) +{ + /* XXX */ + return 0; +} +#endif + +/* + * get_idle_time - return how long the link has been idle. + */ +int +get_idle_time(int u, struct ppp_idle *ip) +{ + /* XXX */ + LWIP_UNUSED_ARG(u); + LWIP_UNUSED_ARG(ip); + + return 0; +} + + +/* + * Return user specified netmask, modified by any mask we might determine + * for address `addr' (in network byte order). + * Here we scan through the system's list of interfaces, looking for + * any non-point-to-point interfaces which might appear to be on the same + * network as `addr'. If we find any, we OR in their netmask to the + * user-specified netmask. + */ +u32_t +GetMask(u32_t addr) +{ + u32_t mask, nmask; + + htonl(addr); + if (IN_CLASSA(addr)) { /* determine network mask for address class */ + nmask = IN_CLASSA_NET; + } else if (IN_CLASSB(addr)) { + nmask = IN_CLASSB_NET; + } else { + nmask = IN_CLASSC_NET; + } + + /* class D nets are disallowed by bad_ip_adrs */ + mask = subnetMask | htonl(nmask); + + /* XXX + * Scan through the system's network interfaces. + * Get each netmask and OR them into our mask. + */ + + return mask; +} + +/* + * sifvjcomp - config tcp header compression + */ +int +sifvjcomp(int pd, int vjcomp, int cidcomp, int maxcid) +{ +#if PPPOS_SUPPORT && VJ_SUPPORT + PPPControl *pc = &pppControl[pd]; + + pc->vjEnabled = vjcomp; + pc->vjComp.compressSlot = cidcomp; + pc->vjComp.maxSlotIndex = maxcid; + PPPDEBUG((LOG_INFO, "sifvjcomp: VJ compress enable=%d slot=%d max slot=%d\n", + vjcomp, cidcomp, maxcid)); +#else /* PPPOS_SUPPORT && VJ_SUPPORT */ + LWIP_UNUSED_ARG(pd); + LWIP_UNUSED_ARG(vjcomp); + LWIP_UNUSED_ARG(cidcomp); + LWIP_UNUSED_ARG(maxcid); +#endif /* PPPOS_SUPPORT && VJ_SUPPORT */ + + return 0; +} + +/* + * pppifNetifInit - netif init callback + */ +static err_t +pppifNetifInit(struct netif *netif) +{ + netif->name[0] = 'p'; + netif->name[1] = 'p'; + netif->output = pppifOutput; + netif->mtu = pppMTU((int)netif->state); + return ERR_OK; +} + + +/* + * sifup - Config the interface up and enable IP packets to pass. + */ +int +sifup(int pd) +{ + PPPControl *pc = &pppControl[pd]; + int st = 1; + + if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { + st = 0; + PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd)); + } else { + netif_remove(&pc->netif); + if (netif_add(&pc->netif, &pc->addrs.our_ipaddr, &pc->addrs.netmask, &pc->addrs.his_ipaddr, (void *)pd, pppifNetifInit, ip_input)) { + netif_set_up(&pc->netif); + pc->if_up = 1; + pc->errCode = PPPERR_NONE; + + PPPDEBUG((LOG_DEBUG, "sifup: unit %d: linkStatusCB=%lx errCode=%d\n", pd, pc->linkStatusCB, pc->errCode)); + if(pc->linkStatusCB) { + pc->linkStatusCB(pc->linkStatusCtx, pc->errCode, &pc->addrs); + } + } else { + st = 0; + PPPDEBUG((LOG_ERR, "sifup[%d]: netif_add failed\n", pd)); + } + } + + return st; +} + +/* + * sifnpmode - Set the mode for handling packets for a given NP. + */ +int +sifnpmode(int u, int proto, enum NPmode mode) +{ + LWIP_UNUSED_ARG(u); + LWIP_UNUSED_ARG(proto); + LWIP_UNUSED_ARG(mode); + return 0; +} + +/* + * sifdown - Config the interface down and disable IP. + */ +int +sifdown(int pd) +{ + PPPControl *pc = &pppControl[pd]; + int st = 1; + + if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { + st = 0; + PPPDEBUG((LOG_WARNING, "sifdown[%d]: bad parms\n", pd)); + } else { + pc->if_up = 0; + /* make sure the netif status callback is called */ + netif_set_down(&pc->netif); + netif_remove(&pc->netif); + PPPDEBUG((LOG_DEBUG, "sifdown: unit %d: linkStatusCB=%lx errCode=%d\n", pd, pc->linkStatusCB, pc->errCode)); + if(pc->linkStatusCB) { + pc->linkStatusCB(pc->linkStatusCtx, PPPERR_CONNECT, NULL); + } + } + return st; +} + +/** + * sifaddr - Config the interface IP addresses and netmask. + * @param pd Interface unit ??? + * @param o Our IP address ??? + * @param h His IP address ??? + * @param m IP subnet mask ??? + * @param ns1 Primary DNS + * @param ns2 Secondary DNS + */ +int +sifaddr( int pd, u32_t o, u32_t h, u32_t m, u32_t ns1, u32_t ns2) +{ + PPPControl *pc = &pppControl[pd]; + int st = 1; + + if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { + st = 0; + PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd)); + } else { + SMEMCPY(&pc->addrs.our_ipaddr, &o, sizeof(o)); + SMEMCPY(&pc->addrs.his_ipaddr, &h, sizeof(h)); + SMEMCPY(&pc->addrs.netmask, &m, sizeof(m)); + SMEMCPY(&pc->addrs.dns1, &ns1, sizeof(ns1)); + SMEMCPY(&pc->addrs.dns2, &ns2, sizeof(ns2)); + } + return st; +} + +/** + * cifaddr - Clear the interface IP addresses, and delete routes + * through the interface if possible. + * @param pd Interface unit ??? + * @param o Our IP address ??? + * @param h IP broadcast address ??? + */ +int +cifaddr( int pd, u32_t o, u32_t h) +{ + PPPControl *pc = &pppControl[pd]; + int st = 1; + + LWIP_UNUSED_ARG(o); + LWIP_UNUSED_ARG(h); + if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { + st = 0; + PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd)); + } else { + IP4_ADDR(&pc->addrs.our_ipaddr, 0,0,0,0); + IP4_ADDR(&pc->addrs.his_ipaddr, 0,0,0,0); + IP4_ADDR(&pc->addrs.netmask, 255,255,255,0); + IP4_ADDR(&pc->addrs.dns1, 0,0,0,0); + IP4_ADDR(&pc->addrs.dns2, 0,0,0,0); + } + return st; +} + +/* + * sifdefaultroute - assign a default route through the address given. + */ +int +sifdefaultroute(int pd, u32_t l, u32_t g) +{ + PPPControl *pc = &pppControl[pd]; + int st = 1; + + LWIP_UNUSED_ARG(l); + LWIP_UNUSED_ARG(g); + + if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { + st = 0; + PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd)); + } else { + netif_set_default(&pc->netif); + } + + /* TODO: check how PPP handled the netMask, previously not set by ipSetDefault */ + + return st; +} + +/* + * cifdefaultroute - delete a default route through the address given. + */ +int +cifdefaultroute(int pd, u32_t l, u32_t g) +{ + PPPControl *pc = &pppControl[pd]; + int st = 1; + + LWIP_UNUSED_ARG(l); + LWIP_UNUSED_ARG(g); + + if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { + st = 0; + PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd)); + } else { + netif_set_default(NULL); + } + + return st; +} + +/**********************************/ +/*** LOCAL FUNCTION DEFINITIONS ***/ +/**********************************/ + +#if PPPOS_SUPPORT +/* The main PPP process function. This implements the state machine according + * to section 4 of RFC 1661: The Point-To-Point Protocol. */ +static void +pppMain(void *arg) +{ + int pd = (int)arg; + struct pbuf *p; + PPPControl* pc; + int c; + + pc = &pppControl[pd]; + + p = pbuf_alloc(PBUF_RAW, PPP_MRU+PPP_HDRLEN, PBUF_RAM); + if (!p) { + LWIP_ASSERT("p != NULL", p); + pc->errCode = PPPERR_ALLOC; + goto out; + } + + /* + * Start the connection and handle incoming events (packet or timeout). + */ + PPPDEBUG((LOG_INFO, "pppMain: unit %d: Connecting\n", pd)); + tcpip_callback(pppStartCB, arg); + while (lcp_phase[pd] != PHASE_DEAD) { + if (pc->kill_link) { + PPPDEBUG((LOG_DEBUG, "pppMain: unit %d kill_link -> pppStopCB\n", pd)); + pc->errCode = PPPERR_USER; + /* This will leave us at PHASE_DEAD. */ + tcpip_callback(pppStopCB, arg); + pc->kill_link = 0; + } else if (pc->sig_hup) { + PPPDEBUG((LOG_DEBUG, "pppMain: unit %d sig_hup -> pppHupCB\n", pd)); + pc->sig_hup = 0; + tcpip_callback(pppHupCB, arg); + } else { + c = sio_read(pc->fd, p->payload, p->len); + if(c > 0) { + pppInProc(pd, p->payload, c); + } else { + /* nothing received, give other tasks a chance to run */ + sys_msleep(1); + } + } + } + PPPDEBUG((LOG_INFO, "pppMain: unit %d: PHASE_DEAD\n", pd)); + pppDrop(pc); /* bug fix #17726 */ + pbuf_free(p); + +out: + PPPDEBUG((LOG_DEBUG, "pppMain: unit %d: linkStatusCB=%lx errCode=%d\n", pd, pc->linkStatusCB, pc->errCode)); + if(pc->linkStatusCB) { + pc->linkStatusCB(pc->linkStatusCtx, pc->errCode ? pc->errCode : PPPERR_PROTOCOL, NULL); + } + + pc->openFlag = 0; +} +#endif /* PPPOS_SUPPORT */ + +#if PPPOE_SUPPORT + +void +pppOverEthernetInitFailed(void* arg) +{ + PPPControl* pc; + int pd = (int)arg; + + pppHupCB(arg); + pppStopCB(arg); + + pc = &pppControl[pd]; + pppoe_destroy(&pc->netif); + pc->openFlag = 0; + + if(pc->linkStatusCB) { + pc->linkStatusCB(pc->linkStatusCtx, pc->errCode ? pc->errCode : PPPERR_PROTOCOL, NULL); + } +} + +static void +pppOverEthernetLinkStatusCB(int pd, int up) +{ + if(up) { + PPPDEBUG((LOG_INFO, "pppMain: unit %d: Connecting\n", pd)); + tcpip_callback(pppStartCB, (void*)pd); + } else { + PPPControl* pc; + pc = &pppControl[pd]; + tcpip_callback(pppOverEthernetInitFailed, (void*)pd); + } +} +#endif /* PPPOE_SUPPORT */ + +struct pbuf * +pppSingleBuf(struct pbuf *p) +{ + struct pbuf *q, *b; + u_char *pl; + + if(p->tot_len == p->len) { + return p; + } + + q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); + if(!q) { + PPPDEBUG((LOG_ERR, + "pppSingleBuf: unable to alloc new buf (%d)\n", p->tot_len)); + return p; /* live dangerously */ + } + + for(b = p, pl = q->payload; b != NULL; b = b->next) { + MEMCPY(pl, b->payload, b->len); + pl += b->len; + } + + pbuf_free(p); + + return q; +} + +struct pppInputHeader { + int unit; + u16_t proto; +}; + +/* + * Pass the processed input packet to the appropriate handler. + * This function and all handlers run in the context of the tcpip_thread + */ +static void +pppInput(void *arg) +{ + struct pbuf *nb = (struct pbuf *)arg; + u16_t protocol; + int pd; + + pd = ((struct pppInputHeader *)nb->payload)->unit; + protocol = ((struct pppInputHeader *)nb->payload)->proto; + + if(pbuf_header(nb, -(int)sizeof(struct pppInputHeader))) { + LWIP_ASSERT("pbuf_header failed\n", 0); + goto drop; + } + + LINK_STATS_INC(link.recv); + + /* + * Toss all non-LCP packets unless LCP is OPEN. + * Until we get past the authentication phase, toss all packets + * except LCP, LQR and authentication packets. + */ + if((lcp_phase[pd] <= PHASE_AUTHENTICATE) && (protocol != PPP_LCP)) { + if(!((protocol == PPP_LQR) || (protocol == PPP_PAP) || (protocol == PPP_CHAP)) || + (lcp_phase[pd] != PHASE_AUTHENTICATE)) { + PPPDEBUG((LOG_INFO, "pppInput: discarding proto 0x%04X in phase %d\n", protocol, lcp_phase[pd])); + goto drop; + } + } + + switch(protocol) { + case PPP_VJC_COMP: /* VJ compressed TCP */ +#if PPPOS_SUPPORT && VJ_SUPPORT + PPPDEBUG((LOG_INFO, "pppInput[%d]: vj_comp in pbuf len=%d\n", pd, nb->len)); + /* + * Clip off the VJ header and prepend the rebuilt TCP/IP header and + * pass the result to IP. + */ + if ((vj_uncompress_tcp(&nb, &pppControl[pd].vjComp) >= 0) && (pppControl[pd].netif.input)) { + pppControl[pd].netif.input(nb, &pppControl[pd].netif); + return; + } + /* Something's wrong so drop it. */ + PPPDEBUG((LOG_WARNING, "pppInput[%d]: Dropping VJ compressed\n", pd)); +#else /* PPPOS_SUPPORT && VJ_SUPPORT */ + /* No handler for this protocol so drop the packet. */ + PPPDEBUG((LOG_INFO, "pppInput[%d]: drop VJ Comp in %d:%s\n", pd, nb->len, nb->payload)); +#endif /* PPPOS_SUPPORT && VJ_SUPPORT */ + break; + + case PPP_VJC_UNCOMP: /* VJ uncompressed TCP */ +#if PPPOS_SUPPORT && VJ_SUPPORT + PPPDEBUG((LOG_INFO, "pppInput[%d]: vj_un in pbuf len=%d\n", pd, nb->len)); + /* + * Process the TCP/IP header for VJ header compression and then pass + * the packet to IP. + */ + if ((vj_uncompress_uncomp(nb, &pppControl[pd].vjComp) >= 0) && pppControl[pd].netif.input) { + pppControl[pd].netif.input(nb, &pppControl[pd].netif); + return; + } + /* Something's wrong so drop it. */ + PPPDEBUG((LOG_WARNING, "pppInput[%d]: Dropping VJ uncompressed\n", pd)); +#else /* PPPOS_SUPPORT && VJ_SUPPORT */ + /* No handler for this protocol so drop the packet. */ + PPPDEBUG((LOG_INFO, + "pppInput[%d]: drop VJ UnComp in %d:.*H\n", + pd, nb->len, LWIP_MIN(nb->len * 2, 40), nb->payload)); +#endif /* PPPOS_SUPPORT && VJ_SUPPORT */ + break; + + case PPP_IP: /* Internet Protocol */ + PPPDEBUG((LOG_INFO, "pppInput[%d]: ip in pbuf len=%d\n", pd, nb->len)); + if (pppControl[pd].netif.input) { + pppControl[pd].netif.input(nb, &pppControl[pd].netif); + return; + } + break; + + default: { + struct protent *protp; + int i; + + /* + * Upcall the proper protocol input routine. + */ + for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) { + if (protp->protocol == protocol && protp->enabled_flag) { + PPPDEBUG((LOG_INFO, "pppInput[%d]: %s len=%d\n", pd, protp->name, nb->len)); + nb = pppSingleBuf(nb); + (*protp->input)(pd, nb->payload, nb->len); + goto out; + } + } + + /* No handler for this protocol so reject the packet. */ + PPPDEBUG((LOG_INFO, "pppInput[%d]: rejecting unsupported proto 0x%04X len=%d\n", pd, protocol, nb->len)); + if (pbuf_header(nb, sizeof(protocol))) { + LWIP_ASSERT("pbuf_header failed\n", 0); + goto drop; + } +#if BYTE_ORDER == LITTLE_ENDIAN + protocol = htons(protocol); + SMEMCPY(nb->payload, &protocol, sizeof(protocol)); +#endif /* BYTE_ORDER == LITTLE_ENDIAN */ + lcp_sprotrej(pd, nb->payload, nb->len); + } + break; + } + +drop: + LINK_STATS_INC(link.drop); + +out: + pbuf_free(nb); + return; +} + +#if PPPOS_SUPPORT +/* + * Drop the input packet. + */ +static void +pppDrop(PPPControl *pc) +{ + if (pc->inHead != NULL) { +#if 0 + PPPDEBUG((LOG_INFO, "pppDrop: %d:%.*H\n", pc->inHead->len, min(60, pc->inHead->len * 2), pc->inHead->payload)); +#endif + PPPDEBUG((LOG_INFO, "pppDrop: pbuf len=%d\n", pc->inHead->len)); + if (pc->inTail && (pc->inTail != pc->inHead)) { + pbuf_free(pc->inTail); + } + pbuf_free(pc->inHead); + pc->inHead = NULL; + pc->inTail = NULL; + } +#if VJ_SUPPORT + vj_uncompress_err(&pc->vjComp); +#endif /* VJ_SUPPORT */ + + LINK_STATS_INC(link.drop); +} + +/** + * Process a received octet string. + */ +static void +pppInProc(int pd, u_char *s, int l) +{ + PPPControl *pc = &pppControl[pd]; + struct pbuf *nextNBuf; + u_char curChar; + + PPPDEBUG((LOG_DEBUG, "pppInProc[%d]: got %d bytes\n", pd, l)); + while (l-- > 0) { + curChar = *s++; + + /* Handle special characters. */ + if (ESCAPE_P(pc->inACCM, curChar)) { + /* Check for escape sequences. */ + /* XXX Note that this does not handle an escaped 0x5d character which + * would appear as an escape character. Since this is an ASCII ']' + * and there is no reason that I know of to escape it, I won't complicate + * the code to handle this case. GLL */ + if (curChar == PPP_ESCAPE) { + pc->inEscaped = 1; + /* Check for the flag character. */ + } else if (curChar == PPP_FLAG) { + /* If this is just an extra flag character, ignore it. */ + if (pc->inState <= PDADDRESS) { + /* ignore it */; + /* If we haven't received the packet header, drop what has come in. */ + } else if (pc->inState < PDDATA) { + PPPDEBUG((LOG_WARNING, + "pppInProc[%d]: Dropping incomplete packet %d\n", + pd, pc->inState)); + LINK_STATS_INC(link.lenerr); + pppDrop(pc); + /* If the fcs is invalid, drop the packet. */ + } else if (pc->inFCS != PPP_GOODFCS) { + PPPDEBUG((LOG_INFO, + "pppInProc[%d]: Dropping bad fcs 0x%04X proto=0x%04X\n", + pd, pc->inFCS, pc->inProtocol)); + LINK_STATS_INC(link.chkerr); + pppDrop(pc); + /* Otherwise it's a good packet so pass it on. */ + } else { + /* Trim off the checksum. */ + if(pc->inTail->len >= 2) { + pc->inTail->len -= 2; + + pc->inTail->tot_len = pc->inTail->len; + if (pc->inTail != pc->inHead) { + pbuf_cat(pc->inHead, pc->inTail); + } + } else { + pc->inTail->tot_len = pc->inTail->len; + if (pc->inTail != pc->inHead) { + pbuf_cat(pc->inHead, pc->inTail); + } + + pbuf_realloc(pc->inHead, pc->inHead->tot_len - 2); + } + + /* Dispatch the packet thereby consuming it. */ + if(tcpip_callback(pppInput, pc->inHead) != ERR_OK) { + PPPDEBUG((LOG_ERR, "pppInProc[%d]: tcpip_callback() failed, dropping packet\n", pd)); + pbuf_free(pc->inHead); + LINK_STATS_INC(link.drop); + } + pc->inHead = NULL; + pc->inTail = NULL; + } + + /* Prepare for a new packet. */ + pc->inFCS = PPP_INITFCS; + pc->inState = PDADDRESS; + pc->inEscaped = 0; + /* Other characters are usually control characters that may have + * been inserted by the physical layer so here we just drop them. */ + } else { + PPPDEBUG((LOG_WARNING, + "pppInProc[%d]: Dropping ACCM char <%d>\n", pd, curChar)); + } + /* Process other characters. */ + } else { + /* Unencode escaped characters. */ + if (pc->inEscaped) { + pc->inEscaped = 0; + curChar ^= PPP_TRANS; + } + + /* Process character relative to current state. */ + switch(pc->inState) { + case PDIDLE: /* Idle state - waiting. */ + /* Drop the character if it's not 0xff + * we would have processed a flag character above. */ + if (curChar != PPP_ALLSTATIONS) { + break; + } + + /* Fall through */ + case PDSTART: /* Process start flag. */ + /* Prepare for a new packet. */ + pc->inFCS = PPP_INITFCS; + + /* Fall through */ + case PDADDRESS: /* Process address field. */ + if (curChar == PPP_ALLSTATIONS) { + pc->inState = PDCONTROL; + break; + } + /* Else assume compressed address and control fields so + * fall through to get the protocol... */ + case PDCONTROL: /* Process control field. */ + /* If we don't get a valid control code, restart. */ + if (curChar == PPP_UI) { + pc->inState = PDPROTOCOL1; + break; + } +#if 0 + else { + PPPDEBUG((LOG_WARNING, + "pppInProc[%d]: Invalid control <%d>\n", pd, curChar)); + pc->inState = PDSTART; + } +#endif + case PDPROTOCOL1: /* Process protocol field 1. */ + /* If the lower bit is set, this is the end of the protocol + * field. */ + if (curChar & 1) { + pc->inProtocol = curChar; + pc->inState = PDDATA; + } else { + pc->inProtocol = (u_int)curChar << 8; + pc->inState = PDPROTOCOL2; + } + break; + case PDPROTOCOL2: /* Process protocol field 2. */ + pc->inProtocol |= curChar; + pc->inState = PDDATA; + break; + case PDDATA: /* Process data byte. */ + /* Make space to receive processed data. */ + if (pc->inTail == NULL || pc->inTail->len == PBUF_POOL_BUFSIZE) { + if(pc->inTail) { + pc->inTail->tot_len = pc->inTail->len; + if (pc->inTail != pc->inHead) { + pbuf_cat(pc->inHead, pc->inTail); + } + } + /* If we haven't started a packet, we need a packet header. */ + nextNBuf = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); + if (nextNBuf == NULL) { + /* No free buffers. Drop the input packet and let the + * higher layers deal with it. Continue processing + * the received pbuf chain in case a new packet starts. */ + PPPDEBUG((LOG_ERR, "pppInProc[%d]: NO FREE MBUFS!\n", pd)); + LINK_STATS_INC(link.memerr); + pppDrop(pc); + pc->inState = PDSTART; /* Wait for flag sequence. */ + break; + } + if (pc->inHead == NULL) { + struct pppInputHeader *pih = nextNBuf->payload; + + pih->unit = pd; + pih->proto = pc->inProtocol; + + nextNBuf->len += sizeof(*pih); + + pc->inHead = nextNBuf; + } + pc->inTail = nextNBuf; + } + /* Load character into buffer. */ + ((u_char*)pc->inTail->payload)[pc->inTail->len++] = curChar; + break; + } + + /* update the frame check sequence number. */ + pc->inFCS = PPP_FCS(pc->inFCS, curChar); + } + } + + avRandomize(); +} +#endif /* PPPOS_SUPPORT */ + +#if PPPOE_SUPPORT +void +pppInProcOverEthernet(int pd, struct pbuf *pb) +{ + struct pppInputHeader *pih; + u16_t inProtocol; + + if(pb->len < sizeof(inProtocol)) { + PPPDEBUG((LOG_ERR, "pppInProcOverEthernet: too small for protocol field\n")); + goto drop; + } + + inProtocol = (((u8_t *)pb->payload)[0] << 8) | ((u8_t*)pb->payload)[1]; + + /* make room for pppInputHeader - should not fail */ + if (pbuf_header(pb, sizeof(*pih) - sizeof(inProtocol)) != 0) { + PPPDEBUG((LOG_ERR, "pppInProcOverEthernet: could not allocate room for header\n")); + goto drop; + } + + pih = pb->payload; + + pih->unit = pd; + pih->proto = inProtocol; + + /* Dispatch the packet thereby consuming it. */ + if(tcpip_callback(pppInput, pb) != ERR_OK) { + PPPDEBUG((LOG_ERR, "pppInProcOverEthernet[%d]: tcpip_callback() failed, dropping packet\n", pd)); + goto drop; + } + + return; + +drop: + LINK_STATS_INC(link.drop); + pbuf_free(pb); + return; +} +#endif /* PPPOE_SUPPORT */ + +#endif /* PPP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/ppp.h b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/ppp.h new file mode 100644 index 0000000..ebc733b --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/ppp.h @@ -0,0 +1,465 @@ +/***************************************************************************** +* ppp.h - Network Point to Point Protocol header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-11-05 Guy Lancaster , Global Election Systems Inc. +* Original derived from BSD codes. +*****************************************************************************/ + +#ifndef PPP_H +#define PPP_H + +#include "lwip/opt.h" + +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/sio.h" +#include "lwip/api.h" +#include "lwip/sockets.h" +#include "lwip/stats.h" +#include "lwip/mem.h" +#include "lwip/tcpip.h" +#include "lwip/netif.h" + +/* + * pppd.h - PPP daemon global declarations. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + */ +/* + * ppp_defs.h - PPP definitions. + * + * Copyright (c) 1994 The Australian National University. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, provided that the above copyright + * notice appears in all copies. This software is provided without any + * warranty, express or implied. The Australian National University + * makes no representations about the suitability of this software for + * any purpose. + * + * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY + * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO + * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, + * OR MODIFICATIONS. + */ + +#define TIMEOUT(f, a, t) sys_untimeout((f), (a)), sys_timeout((t)*1000, (f), (a)) +#define UNTIMEOUT(f, a) sys_untimeout((f), (a)) + + +#ifndef __u_char_defined + +/* Type definitions for BSD code. */ +typedef unsigned long u_long; +typedef unsigned int u_int; +typedef unsigned short u_short; +typedef unsigned char u_char; + +#endif + +/* + * Constants and structures defined by the internet system, + * Per RFC 790, September 1981, and numerous additions. + */ + +/* + * The basic PPP frame. + */ +#define PPP_HDRLEN 4 /* octets for standard ppp header */ +#define PPP_FCSLEN 2 /* octets for FCS */ + + +/* + * Significant octet values. + */ +#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */ +#define PPP_UI 0x03 /* Unnumbered Information */ +#define PPP_FLAG 0x7e /* Flag Sequence */ +#define PPP_ESCAPE 0x7d /* Asynchronous Control Escape */ +#define PPP_TRANS 0x20 /* Asynchronous transparency modifier */ + +/* + * Protocol field values. + */ +#define PPP_IP 0x21 /* Internet Protocol */ +#define PPP_AT 0x29 /* AppleTalk Protocol */ +#define PPP_VJC_COMP 0x2d /* VJ compressed TCP */ +#define PPP_VJC_UNCOMP 0x2f /* VJ uncompressed TCP */ +#define PPP_COMP 0xfd /* compressed packet */ +#define PPP_IPCP 0x8021 /* IP Control Protocol */ +#define PPP_ATCP 0x8029 /* AppleTalk Control Protocol */ +#define PPP_CCP 0x80fd /* Compression Control Protocol */ +#define PPP_LCP 0xc021 /* Link Control Protocol */ +#define PPP_PAP 0xc023 /* Password Authentication Protocol */ +#define PPP_LQR 0xc025 /* Link Quality Report protocol */ +#define PPP_CHAP 0xc223 /* Cryptographic Handshake Auth. Protocol */ +#define PPP_CBCP 0xc029 /* Callback Control Protocol */ + +/* + * Values for FCS calculations. + */ +#define PPP_INITFCS 0xffff /* Initial FCS value */ +#define PPP_GOODFCS 0xf0b8 /* Good final FCS value */ +#define PPP_FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff]) + +/* + * Extended asyncmap - allows any character to be escaped. + */ +typedef u_char ext_accm[32]; + +/* + * What to do with network protocol (NP) packets. + */ +enum NPmode { + NPMODE_PASS, /* pass the packet through */ + NPMODE_DROP, /* silently drop the packet */ + NPMODE_ERROR, /* return an error */ + NPMODE_QUEUE /* save it up for later. */ +}; + +/* + * Inline versions of get/put char/short/long. + * Pointer is advanced; we assume that both arguments + * are lvalues and will already be in registers. + * cp MUST be u_char *. + */ +#define GETCHAR(c, cp) { \ + (c) = *(cp)++; \ +} +#define PUTCHAR(c, cp) { \ + *(cp)++ = (u_char) (c); \ +} + + +#define GETSHORT(s, cp) { \ + (s) = *(cp); (cp)++; (s) <<= 8; \ + (s) |= *(cp); (cp)++; \ +} +#define PUTSHORT(s, cp) { \ + *(cp)++ = (u_char) ((s) >> 8); \ + *(cp)++ = (u_char) (s & 0xff); \ +} + +#define GETLONG(l, cp) { \ + (l) = *(cp); (cp)++; (l) <<= 8; \ + (l) |= *(cp); (cp)++; (l) <<= 8; \ + (l) |= *(cp); (cp)++; (l) <<= 8; \ + (l) |= *(cp); (cp)++; \ +} +#define PUTLONG(l, cp) { \ + *(cp)++ = (u_char) ((l) >> 24); \ + *(cp)++ = (u_char) ((l) >> 16); \ + *(cp)++ = (u_char) ((l) >> 8); \ + *(cp)++ = (u_char) (l); \ +} + + +#define INCPTR(n, cp) ((cp) += (n)) +#define DECPTR(n, cp) ((cp) -= (n)) + +#define BCMP(s0, s1, l) memcmp((u_char *)(s0), (u_char *)(s1), (l)) +#define BCOPY(s, d, l) MEMCPY((d), (s), (l)) +#define BZERO(s, n) memset(s, 0, n) + +#if PPP_DEBUG +#define PRINTMSG(m, l) { m[l] = '\0'; ppp_trace(LOG_INFO, "Remote message: %s\n", m); } +#else /* PPP_DEBUG */ +#define PRINTMSG(m, l) +#endif /* PPP_DEBUG */ + +/* + * MAKEHEADER - Add PPP Header fields to a packet. + */ +#define MAKEHEADER(p, t) { \ + PUTCHAR(PPP_ALLSTATIONS, p); \ + PUTCHAR(PPP_UI, p); \ + PUTSHORT(t, p); } + +/************************* +*** PUBLIC DEFINITIONS *** +*************************/ + +/* Error codes. */ +#define PPPERR_NONE 0 /* No error. */ +#define PPPERR_PARAM -1 /* Invalid parameter. */ +#define PPPERR_OPEN -2 /* Unable to open PPP session. */ +#define PPPERR_DEVICE -3 /* Invalid I/O device for PPP. */ +#define PPPERR_ALLOC -4 /* Unable to allocate resources. */ +#define PPPERR_USER -5 /* User interrupt. */ +#define PPPERR_CONNECT -6 /* Connection lost. */ +#define PPPERR_AUTHFAIL -7 /* Failed authentication challenge. */ +#define PPPERR_PROTOCOL -8 /* Failed to meet protocol. */ + +/* + * PPP IOCTL commands. + */ +/* + * Get the up status - 0 for down, non-zero for up. The argument must + * point to an int. + */ +#define PPPCTLG_UPSTATUS 100 /* Get the up status - 0 down else up */ +#define PPPCTLS_ERRCODE 101 /* Set the error code */ +#define PPPCTLG_ERRCODE 102 /* Get the error code */ +#define PPPCTLG_FD 103 /* Get the fd associated with the ppp */ + +/************************ +*** PUBLIC DATA TYPES *** +************************/ + +/* + * The following struct gives the addresses of procedures to call + * for a particular protocol. + */ +struct protent { + u_short protocol; /* PPP protocol number */ + /* Initialization procedure */ + void (*init) (int unit); + /* Process a received packet */ + void (*input) (int unit, u_char *pkt, int len); + /* Process a received protocol-reject */ + void (*protrej) (int unit); + /* Lower layer has come up */ + void (*lowerup) (int unit); + /* Lower layer has gone down */ + void (*lowerdown) (int unit); + /* Open the protocol */ + void (*open) (int unit); + /* Close the protocol */ + void (*close) (int unit, char *reason); +#if 0 + /* Print a packet in readable form */ + int (*printpkt) (u_char *pkt, int len, + void (*printer) (void *, char *, ...), + void *arg); + /* Process a received data packet */ + void (*datainput) (int unit, u_char *pkt, int len); +#endif + int enabled_flag; /* 0 iff protocol is disabled */ + char *name; /* Text name of protocol */ +#if 0 + /* Check requested options, assign defaults */ + void (*check_options) (u_long); + /* Configure interface for demand-dial */ + int (*demand_conf) (int unit); + /* Say whether to bring up link for this pkt */ + int (*active_pkt) (u_char *pkt, int len); +#endif +}; + +/* + * The following structure records the time in seconds since + * the last NP packet was sent or received. + */ +struct ppp_idle { + u_short xmit_idle; /* seconds since last NP packet sent */ + u_short recv_idle; /* seconds since last NP packet received */ +}; + +struct ppp_settings { + + u_int disable_defaultip : 1; /* Don't use hostname for default IP addrs */ + u_int auth_required : 1; /* Peer is required to authenticate */ + u_int explicit_remote : 1; /* remote_name specified with remotename opt */ + u_int refuse_pap : 1; /* Don't wanna auth. ourselves with PAP */ + u_int refuse_chap : 1; /* Don't wanna auth. ourselves with CHAP */ + u_int usehostname : 1; /* Use hostname for our_name */ + u_int usepeerdns : 1; /* Ask peer for DNS adds */ + + u_short idle_time_limit; /* Shut down link if idle for this long */ + int maxconnect; /* Maximum connect time (seconds) */ + + char user [MAXNAMELEN + 1]; /* Username for PAP */ + char passwd [MAXSECRETLEN + 1]; /* Password for PAP, secret for CHAP */ + char our_name [MAXNAMELEN + 1]; /* Our name for authentication purposes */ + char remote_name[MAXNAMELEN + 1]; /* Peer's name for authentication */ +}; + +struct ppp_addrs { + struct ip_addr our_ipaddr, his_ipaddr, netmask, dns1, dns2; +}; + +/***************************** +*** PUBLIC DATA STRUCTURES *** +*****************************/ + +/* Buffers for outgoing packets. */ +extern u_char outpacket_buf[NUM_PPP][PPP_MRU+PPP_HDRLEN]; + +extern struct ppp_settings ppp_settings; + +extern struct protent *ppp_protocols[]; /* Table of pointers to supported protocols */ + + +/*********************** +*** PUBLIC FUNCTIONS *** +***********************/ + +/* Initialize the PPP subsystem. */ +void pppInit(void); + +/* Warning: Using PPPAUTHTYPE_ANY might have security consequences. + * RFC 1994 says: + * + * In practice, within or associated with each PPP server, there is a + * database which associates "user" names with authentication + * information ("secrets"). It is not anticipated that a particular + * named user would be authenticated by multiple methods. This would + * make the user vulnerable to attacks which negotiate the least secure + * method from among a set (such as PAP rather than CHAP). If the same + * secret was used, PAP would reveal the secret to be used later with + * CHAP. + * + * Instead, for each user name there should be an indication of exactly + * one method used to authenticate that user name. If a user needs to + * make use of different authentication methods under different + * circumstances, then distinct user names SHOULD be employed, each of + * which identifies exactly one authentication method. + * + */ +enum pppAuthType { + PPPAUTHTYPE_NONE, + PPPAUTHTYPE_ANY, + PPPAUTHTYPE_PAP, + PPPAUTHTYPE_CHAP +}; + +void pppSetAuth(enum pppAuthType authType, const char *user, const char *passwd); + +/* + * Open a new PPP connection using the given serial I/O device. + * This initializes the PPP control block but does not + * attempt to negotiate the LCP session. + * Return a new PPP connection descriptor on success or + * an error code (negative) on failure. + */ +int pppOverSerialOpen(sio_fd_t fd, void (*linkStatusCB)(void *ctx, int errCode, void *arg), void *linkStatusCtx); + +/* + * Open a new PPP Over Ethernet (PPPOE) connection. + */ +int pppOverEthernetOpen(struct netif *ethif, const char *service_name, const char *concentrator_name, void (*linkStatusCB)(void *ctx, int errCode, void *arg), void *linkStatusCtx); + +/* for source code compatibility */ +#define pppOpen(fd,cb,ls) pppOverSerialOpen(fd,cb,ls) + +/* + * Close a PPP connection and release the descriptor. + * Any outstanding packets in the queues are dropped. + * Return 0 on success, an error code on failure. + */ +int pppClose(int pd); + +/* + * Indicate to the PPP process that the line has disconnected. + */ +void pppSigHUP(int pd); + +/* + * Get and set parameters for the given connection. + * Return 0 on success, an error code on failure. + */ +int pppIOCtl(int pd, int cmd, void *arg); + +/* + * Return the Maximum Transmission Unit for the given PPP connection. + */ +u_int pppMTU(int pd); + +/* + * Write n characters to a ppp link. + * RETURN: >= 0 Number of characters written, -1 Failed to write to device. + */ +int pppWrite(int pd, const u_char *s, int n); + +void pppInProcOverEthernet(int pd, struct pbuf *pb); + +struct pbuf *pppSingleBuf(struct pbuf *p); + +void pppLinkTerminated(int pd); + +void pppLinkDown(int pd); + +void pppMainWakeup(int pd); + +/* Configure i/f transmit parameters */ +void ppp_send_config (int, int, u32_t, int, int); +/* Set extended transmit ACCM */ +void ppp_set_xaccm (int, ext_accm *); +/* Configure i/f receive parameters */ +void ppp_recv_config (int, int, u32_t, int, int); +/* Find out how long link has been idle */ +int get_idle_time (int, struct ppp_idle *); + +/* Configure VJ TCP header compression */ +int sifvjcomp (int, int, int, int); +/* Configure i/f down (for IP) */ +int sifup (int); +/* Set mode for handling packets for proto */ +int sifnpmode (int u, int proto, enum NPmode mode); +/* Configure i/f down (for IP) */ +int sifdown (int); +/* Configure IP addresses for i/f */ +int sifaddr (int, u32_t, u32_t, u32_t, u32_t, u32_t); +/* Reset i/f IP addresses */ +int cifaddr (int, u32_t, u32_t); +/* Create default route through i/f */ +int sifdefaultroute (int, u32_t, u32_t); +/* Delete default route through i/f */ +int cifdefaultroute (int, u32_t, u32_t); + +/* Get appropriate netmask for address */ +u32_t GetMask (u32_t); + +#endif /* PPP_SUPPORT */ + +#endif /* PPP_H */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/ppp_oe.c b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/ppp_oe.c new file mode 100644 index 0000000..5a8a45c --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/ppp_oe.c @@ -0,0 +1,1227 @@ +/***************************************************************************** +* ppp_oe.c - PPP Over Ethernet implementation for lwIP. +* +* Copyright (c) 2006 by Marc Boucher, Services Informatiques (MBSI) inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 06-01-01 Marc Boucher +* Ported to lwIP. +*****************************************************************************/ + + + +/* based on NetBSD: if_pppoe.c,v 1.64 2006/01/31 23:50:15 martin Exp */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Martin Husemann . + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +#include "lwip/opt.h" + +#if PPPOE_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "ppp.h" +#include "pppdebug.h" + +#include "lwip/sys.h" + +#include "netif/ppp_oe.h" +#include "netif/etharp.h" + +#include +#include + +/** @todo Replace this part with a simple list like other lwIP lists */ +#ifndef _SYS_QUEUE_H_ +#define _SYS_QUEUE_H_ + +/* + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before + * or after an existing element or at the head of the list. A list + * may only be traversed in the forward direction. + * + * For details on the use of these macros, see the queue(3) manual page. + */ + +/* + * List declarations. + */ +#define LIST_HEAD(name, type) \ +struct name { \ + struct type *lh_first; /* first element */ \ +} + +#define LIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define LIST_ENTRY(type) \ +struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ +} + +/* + * List functions. + */ + +#define LIST_EMPTY(head) ((head)->lh_first == NULL) + +#define LIST_FIRST(head) ((head)->lh_first) + +#define LIST_FOREACH(var, head, field) \ + for ((var) = LIST_FIRST((head)); \ + (var); \ + (var) = LIST_NEXT((var), field)) + +#define LIST_INIT(head) do { \ + LIST_FIRST((head)) = NULL; \ +} while (0) + +#define LIST_INSERT_AFTER(listelm, elm, field) do { \ + if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL) \ + LIST_NEXT((listelm), field)->field.le_prev = \ + &LIST_NEXT((elm), field); \ + LIST_NEXT((listelm), field) = (elm); \ + (elm)->field.le_prev = &LIST_NEXT((listelm), field); \ +} while (0) + +#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.le_prev = (listelm)->field.le_prev; \ + LIST_NEXT((elm), field) = (listelm); \ + *(listelm)->field.le_prev = (elm); \ + (listelm)->field.le_prev = &LIST_NEXT((elm), field); \ +} while (0) + +#define LIST_INSERT_HEAD(head, elm, field) do { \ + if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \ + LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field); \ + LIST_FIRST((head)) = (elm); \ + (elm)->field.le_prev = &LIST_FIRST((head)); \ +} while (0) + +#define LIST_NEXT(elm, field) ((elm)->field.le_next) + +#define LIST_REMOVE(elm, field) do { \ + if (LIST_NEXT((elm), field) != NULL) \ + LIST_NEXT((elm), field)->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = LIST_NEXT((elm), field); \ +} while (0) + +#endif /* !_SYS_QUEUE_H_ */ + + +/* Add a 16 bit unsigned value to a buffer pointed to by PTR */ +#define PPPOE_ADD_16(PTR, VAL) \ + *(PTR)++ = (VAL) / 256; \ + *(PTR)++ = (VAL) % 256 + +/* Add a complete PPPoE header to the buffer pointed to by PTR */ +#define PPPOE_ADD_HEADER(PTR, CODE, SESS, LEN) \ + *(PTR)++ = PPPOE_VERTYPE; \ + *(PTR)++ = (CODE); \ + PPPOE_ADD_16(PTR, SESS); \ + PPPOE_ADD_16(PTR, LEN) + +#define PPPOE_DISC_TIMEOUT (5*1000) /* base for quick timeout calculation */ +#define PPPOE_SLOW_RETRY (60*1000) /* persistent retry interval */ +#define PPPOE_DISC_MAXPADI 4 /* retry PADI four times (quickly) */ +#define PPPOE_DISC_MAXPADR 2 /* retry PADR twice */ + +#ifdef PPPOE_SERVER +/* from if_spppsubr.c */ +#define IFF_PASSIVE IFF_LINK0 /* wait passively for connection */ +#endif + +struct pppoe_softc { + LIST_ENTRY(pppoe_softc) sc_list; + struct netif *sc_ethif; /* ethernet interface we are using */ + int sc_pd; /* ppp unit number */ + void (*sc_linkStatusCB)(int pd, int up); + + int sc_state; /* discovery phase or session connected */ + struct eth_addr sc_dest; /* hardware address of concentrator */ + u16_t sc_session; /* PPPoE session id */ + + char *sc_service_name; /* if != NULL: requested name of service */ + char *sc_concentrator_name; /* if != NULL: requested concentrator id */ + u8_t *sc_ac_cookie; /* content of AC cookie we must echo back */ + size_t sc_ac_cookie_len; /* length of cookie data */ +#ifdef PPPOE_SERVER + u8_t *sc_hunique; /* content of host unique we must echo back */ + size_t sc_hunique_len; /* length of host unique */ +#endif + int sc_padi_retried; /* number of PADI retries already done */ + int sc_padr_retried; /* number of PADR retries already done */ +}; + +/* input routines */ +static void pppoe_dispatch_disc_pkt(struct netif *, struct pbuf *); + +/* management routines */ +static int pppoe_do_disconnect(struct pppoe_softc *); +static void pppoe_abort_connect(struct pppoe_softc *); +static void pppoe_clear_softc(struct pppoe_softc *, const char *); + +/* internal timeout handling */ +static void pppoe_timeout(void *); + +/* sending actual protocol controll packets */ +static err_t pppoe_send_padi(struct pppoe_softc *); +static err_t pppoe_send_padr(struct pppoe_softc *); +#ifdef PPPOE_SERVER +static err_t pppoe_send_pado(struct pppoe_softc *); +static err_t pppoe_send_pads(struct pppoe_softc *); +#endif +static err_t pppoe_send_padt(struct netif *, u_int, const u8_t *); + +/* internal helper functions */ +static struct pppoe_softc * pppoe_find_softc_by_session(u_int, struct netif *); +static struct pppoe_softc * pppoe_find_softc_by_hunique(u8_t *, size_t, struct netif *); + +static LIST_HEAD(pppoe_softc_head, pppoe_softc) pppoe_softc_list; + +int pppoe_hdrlen; + +void +pppoe_init(void) +{ + pppoe_hdrlen = sizeof(struct eth_hdr) + PPPOE_HEADERLEN; + LIST_INIT(&pppoe_softc_list); +} + +err_t +pppoe_create(struct netif *ethif, int pd, void (*linkStatusCB)(int pd, int up), struct pppoe_softc **scptr) +{ + struct pppoe_softc *sc; + + sc = mem_malloc(sizeof(struct pppoe_softc)); + if(!sc) { + *scptr = NULL; + return ERR_MEM; + } + memset(sc, 0, sizeof(struct pppoe_softc)); + + /* changed to real address later */ + MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); + + sc->sc_pd = pd; + sc->sc_linkStatusCB = linkStatusCB; + sc->sc_ethif = ethif; + + LIST_INSERT_HEAD(&pppoe_softc_list, sc, sc_list); + + *scptr = sc; + + return ERR_OK; +} + +err_t +pppoe_destroy(struct netif *ifp) +{ + struct pppoe_softc * sc; + + LIST_FOREACH(sc, &pppoe_softc_list, sc_list) { + if (sc->sc_ethif == ifp) { + break; + } + } + + if(!(sc && (sc->sc_ethif == ifp))) { + return ERR_IF; + } + + tcpip_untimeout(pppoe_timeout, sc); + LIST_REMOVE(sc, sc_list); + + if (sc->sc_concentrator_name) { + mem_free(sc->sc_concentrator_name); + } + if (sc->sc_service_name) { + mem_free(sc->sc_service_name); + } + if (sc->sc_ac_cookie) { + mem_free(sc->sc_ac_cookie); + } + mem_free(sc); + + return ERR_OK; +} + +/* + * Find the interface handling the specified session. + * Note: O(number of sessions open), this is a client-side only, mean + * and lean implementation, so number of open sessions typically should + * be 1. + */ +static struct pppoe_softc * +pppoe_find_softc_by_session(u_int session, struct netif *rcvif) +{ + struct pppoe_softc *sc; + + if (session == 0) { + return NULL; + } + + LIST_FOREACH(sc, &pppoe_softc_list, sc_list) { + if (sc->sc_state == PPPOE_STATE_SESSION + && sc->sc_session == session) { + if (sc->sc_ethif == rcvif) { + return sc; + } else { + return NULL; + } + } + } + return NULL; +} + +/* Check host unique token passed and return appropriate softc pointer, + * or NULL if token is bogus. */ +static struct pppoe_softc * +pppoe_find_softc_by_hunique(u8_t *token, size_t len, struct netif *rcvif) +{ + struct pppoe_softc *sc, *t; + + if (LIST_EMPTY(&pppoe_softc_list)) { + return NULL; + } + + if (len != sizeof sc) { + return NULL; + } + MEMCPY(&t, token, len); + + LIST_FOREACH(sc, &pppoe_softc_list, sc_list) { + if (sc == t) { + break; + } + } + + if (sc == NULL) { + PPPDEBUG((LOG_DEBUG, "pppoe: alien host unique tag, no session found\n")); + return NULL; + } + + /* should be safe to access *sc now */ + if (sc->sc_state < PPPOE_STATE_PADI_SENT || sc->sc_state >= PPPOE_STATE_SESSION) { + printf("%c%c%"U16_F": host unique tag found, but it belongs to a connection in state %d\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, sc->sc_state); + return NULL; + } + if (sc->sc_ethif != rcvif) { + printf("%c%c%"U16_F": wrong interface, not accepting host unique\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num); + return NULL; + } + return sc; +} + +static void +pppoe_linkstatus_up(void *arg) +{ + struct pppoe_softc *sc = (struct pppoe_softc*)arg; + + sc->sc_linkStatusCB(sc->sc_pd, 1); +} + +/* analyze and handle a single received packet while not in session state */ +static void +pppoe_dispatch_disc_pkt(struct netif *netif, struct pbuf *pb) +{ + u16_t tag, len; + u16_t session, plen; + struct pppoe_softc *sc; + const char *err_msg; + char devname[6]; + char *error; + u8_t *ac_cookie; + size_t ac_cookie_len; +#ifdef PPPOE_SERVER + u8_t *hunique; + size_t hunique_len; +#endif + struct pppoehdr *ph; + struct pppoetag pt; + int off, err, errortag; + struct eth_hdr *ethhdr; + + pb = pppSingleBuf(pb); + + strcpy(devname, "pppoe"); /* as long as we don't know which instance */ + err_msg = NULL; + errortag = 0; + if (pb->len < sizeof(*ethhdr)) { + goto done; + } + ethhdr = (struct eth_hdr *)pb->payload; + off = sizeof(*ethhdr); + + ac_cookie = NULL; + ac_cookie_len = 0; +#ifdef PPPOE_SERVER + hunique = NULL; + hunique_len = 0; +#endif + session = 0; + if (pb->len - off < PPPOE_HEADERLEN) { + printf("pppoe: packet too short: %d\n", pb->len); + goto done; + } + + ph = (struct pppoehdr *) (ethhdr + 1); + if (ph->vertype != PPPOE_VERTYPE) { + printf("pppoe: unknown version/type packet: 0x%x\n", ph->vertype); + goto done; + } + session = ntohs(ph->session); + plen = ntohs(ph->plen); + off += sizeof(*ph); + + if (plen + off > pb->len) { + printf("pppoe: packet content does not fit: data available = %d, packet size = %u\n", + pb->len - off, plen); + goto done; + } + if(pb->tot_len == pb->len) { + pb->tot_len = pb->len = off + plen; /* ignore trailing garbage */ + } + tag = 0; + len = 0; + sc = NULL; + while (off + sizeof(pt) <= pb->len) { + MEMCPY(&pt, (u8_t*)pb->payload + off, sizeof(pt)); + tag = ntohs(pt.tag); + len = ntohs(pt.len); + if (off + sizeof(pt) + len > pb->len) { + printf("pppoe: tag 0x%x len 0x%x is too long\n", tag, len); + goto done; + } + switch (tag) { + case PPPOE_TAG_EOL: + goto breakbreak; + case PPPOE_TAG_SNAME: + break; /* ignored */ + case PPPOE_TAG_ACNAME: + break; /* ignored */ + case PPPOE_TAG_HUNIQUE: + if (sc != NULL) { + break; + } +#ifdef PPPOE_SERVER + hunique = (u8_t*)pb->payload + off + sizeof(pt); + hunique_len = len; +#endif + sc = pppoe_find_softc_by_hunique((u8_t*)pb->payload + off + sizeof(pt), len, netif); + if (sc != NULL) { + snprintf(devname, sizeof(devname), "%c%c%"U16_F, sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num); + } + break; + case PPPOE_TAG_ACCOOKIE: + if (ac_cookie == NULL) { + ac_cookie = (u8_t*)pb->payload + off + sizeof(pt); + ac_cookie_len = len; + } + break; + case PPPOE_TAG_SNAME_ERR: + err_msg = "SERVICE NAME ERROR"; + errortag = 1; + break; + case PPPOE_TAG_ACSYS_ERR: + err_msg = "AC SYSTEM ERROR"; + errortag = 1; + break; + case PPPOE_TAG_GENERIC_ERR: + err_msg = "GENERIC ERROR"; + errortag = 1; + break; + } + if (err_msg) { + error = NULL; + if (errortag && len) { + error = mem_malloc(len+1); + if (error) { + strncpy(error, (char*)pb->payload + off + sizeof(pt), len); + error[len-1] = '\0'; + } + } + if (error) { + printf("%s: %s: %s\n", devname, err_msg, error); + mem_free(error); + } else { + printf("%s: %s\n", devname, err_msg); + } + if (errortag) { + goto done; + } + } + off += sizeof(pt) + len; + } + +breakbreak:; + switch (ph->code) { + case PPPOE_CODE_PADI: +#ifdef PPPOE_SERVER + /* + * got service name, concentrator name, and/or host unique. + * ignore if we have no interfaces with IFF_PASSIVE|IFF_UP. + */ + if (LIST_EMPTY(&pppoe_softc_list)) { + goto done; + } + LIST_FOREACH(sc, &pppoe_softc_list, sc_list) { + if (!(sc->sc_sppp.pp_if.if_flags & IFF_UP)) { + continue; + } + if (!(sc->sc_sppp.pp_if.if_flags & IFF_PASSIVE)) { + continue; + } + if (sc->sc_state == PPPOE_STATE_INITIAL) { + break; + } + } + if (sc == NULL) { + /* printf("pppoe: free passive interface is not found\n"); */ + goto done; + } + if (hunique) { + if (sc->sc_hunique) { + mem_free(sc->sc_hunique); + } + sc->sc_hunique = mem_malloc(hunique_len); + if (sc->sc_hunique == NULL) { + goto done; + } + sc->sc_hunique_len = hunique_len; + MEMCPY(sc->sc_hunique, hunique, hunique_len); + } + MEMCPY(&sc->sc_dest, eh->ether_shost, sizeof sc->sc_dest); + sc->sc_state = PPPOE_STATE_PADO_SENT; + pppoe_send_pado(sc); + break; + #endif /* PPPOE_SERVER */ + case PPPOE_CODE_PADR: + #ifdef PPPOE_SERVER + /* + * get sc from ac_cookie if IFF_PASSIVE + */ + if (ac_cookie == NULL) { + /* be quiet if there is not a single pppoe instance */ + printf("pppoe: received PADR but not includes ac_cookie\n"); + goto done; + } + sc = pppoe_find_softc_by_hunique(ac_cookie, ac_cookie_len, netif); + if (sc == NULL) { + /* be quiet if there is not a single pppoe instance */ + if (!LIST_EMPTY(&pppoe_softc_list)) { + printf("pppoe: received PADR but could not find request for it\n"); + } + goto done; + } + if (sc->sc_state != PPPOE_STATE_PADO_SENT) { + printf("%c%c%"U16_F": received unexpected PADR\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num); + goto done; + } + if (hunique) { + if (sc->sc_hunique) { + mem_free(sc->sc_hunique); + } + sc->sc_hunique = mem_malloc(hunique_len); + if (sc->sc_hunique == NULL) { + goto done; + } + sc->sc_hunique_len = hunique_len; + MEMCPY(sc->sc_hunique, hunique, hunique_len); + } + pppoe_send_pads(sc); + sc->sc_state = PPPOE_STATE_SESSION; + tcpip_timeout (100, pppoe_linkstatus_up, sc); /* notify upper layers */ + break; + #else + /* ignore, we are no access concentrator */ + goto done; + #endif /* PPPOE_SERVER */ + case PPPOE_CODE_PADO: + if (sc == NULL) { + /* be quiet if there is not a single pppoe instance */ + if (!LIST_EMPTY(&pppoe_softc_list)) { + printf("pppoe: received PADO but could not find request for it\n"); + } + goto done; + } + if (sc->sc_state != PPPOE_STATE_PADI_SENT) { + printf("%c%c%"U16_F": received unexpected PADO\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num); + goto done; + } + if (ac_cookie) { + if (sc->sc_ac_cookie) { + mem_free(sc->sc_ac_cookie); + } + sc->sc_ac_cookie = mem_malloc(ac_cookie_len); + if (sc->sc_ac_cookie == NULL) { + goto done; + } + sc->sc_ac_cookie_len = ac_cookie_len; + MEMCPY(sc->sc_ac_cookie, ac_cookie, ac_cookie_len); + } + MEMCPY(&sc->sc_dest, ethhdr->src.addr, sizeof(sc->sc_dest.addr)); + tcpip_untimeout(pppoe_timeout, sc); + sc->sc_padr_retried = 0; + sc->sc_state = PPPOE_STATE_PADR_SENT; + if ((err = pppoe_send_padr(sc)) != 0) { + PPPDEBUG((LOG_DEBUG, "pppoe: %c%c%"U16_F": failed to send PADR, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); + } + tcpip_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padr_retried), pppoe_timeout, sc); + break; + case PPPOE_CODE_PADS: + if (sc == NULL) { + goto done; + } + sc->sc_session = session; + tcpip_untimeout(pppoe_timeout, sc); + PPPDEBUG((LOG_DEBUG, "pppoe: %c%c%"U16_F": session 0x%x connected\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, session)); + sc->sc_state = PPPOE_STATE_SESSION; + tcpip_timeout (100, pppoe_linkstatus_up, sc); /* notify upper layers */ + break; + case PPPOE_CODE_PADT: + if (sc == NULL) { + goto done; + } + pppoe_clear_softc(sc, "received PADT"); + break; + default: + if(sc) { + printf("%c%c%"U16_F": unknown code (0x%04x) session = 0x%04x\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, + ph->code, session); + } else { + printf("pppoe: unknown code (0x%04x) session = 0x%04x\n", ph->code, session); + } + break; + } + +done: + pbuf_free(pb); + return; +} + +void +pppoe_disc_input(struct netif *netif, struct pbuf *p) +{ + /* avoid error messages if there is not a single pppoe instance */ + if (!LIST_EMPTY(&pppoe_softc_list)) { + pppoe_dispatch_disc_pkt(netif, p); + } else { + pbuf_free(p); + } +} + +void +pppoe_data_input(struct netif *netif, struct pbuf *pb) +{ + u16_t session, plen; + struct pppoe_softc *sc; + struct pppoehdr *ph; +#ifdef PPPOE_TERM_UNKNOWN_SESSIONS + u8_t shost[ETHER_ADDR_LEN]; +#endif + +#ifdef PPPOE_TERM_UNKNOWN_SESSIONS + MEMCPY(shost, ((struct eth_hdr *)pb->payload)->src.addr, sizeof(shost)); +#endif + if (pbuf_header(pb, -(int)sizeof(struct eth_hdr)) != 0) { + /* bail out */ + PPPDEBUG((LOG_ERR, "pppoe_data_input: pbuf_header failed\n")); + LINK_STATS_INC(link.lenerr); + goto drop; + } + + pb = pppSingleBuf (pb); + + if (pb->len <= PPPOE_HEADERLEN) { + printf("pppoe (data): dropping too short packet: %d bytes\n", pb->len); + goto drop; + } + + if (pb->len < sizeof(*ph)) { + printf("pppoe_data_input: could not get PPPoE header\n"); + goto drop; + } + ph = (struct pppoehdr *)pb->payload; + + if (ph->vertype != PPPOE_VERTYPE) { + printf("pppoe (data): unknown version/type packet: 0x%x\n", ph->vertype); + goto drop; + } + if (ph->code != 0) { + goto drop; + } + + session = ntohs(ph->session); + sc = pppoe_find_softc_by_session(session, netif); + if (sc == NULL) { +#ifdef PPPOE_TERM_UNKNOWN_SESSIONS + printf("pppoe: input for unknown session 0x%x, sending PADT\n", session); + pppoe_send_padt(netif, session, shost); +#endif + goto drop; + } + + plen = ntohs(ph->plen); + + if (pbuf_header(pb, -(int)(PPPOE_HEADERLEN)) != 0) { + /* bail out */ + PPPDEBUG((LOG_ERR, "pppoe_data_input: pbuf_header PPPOE_HEADERLEN failed\n")); + LINK_STATS_INC(link.lenerr); + goto drop; + } + + PPPDEBUG((LOG_DEBUG, "pppoe_data_input: %c%c%"U16_F": pkthdr.len=%d, pppoe.len=%d\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, + pb->len, plen)); + + if (pb->len < plen) { + goto drop; + } + + pppInProcOverEthernet(sc->sc_pd, pb); + + return; + +drop: + pbuf_free(pb); +} + +static err_t +pppoe_output(struct pppoe_softc *sc, struct pbuf *pb) +{ + struct eth_hdr *ethhdr; + u16_t etype; + err_t res; + + if (!sc->sc_ethif) { + pbuf_free(pb); + return ERR_IF; + } + + ethhdr = (struct eth_hdr *)pb->payload; + etype = sc->sc_state == PPPOE_STATE_SESSION ? ETHTYPE_PPPOE : ETHTYPE_PPPOEDISC; + ethhdr->type = htons(etype); + MEMCPY(ethhdr->dest.addr, sc->sc_dest.addr, sizeof(ethhdr->dest.addr)); + MEMCPY(ethhdr->src.addr, ((struct eth_addr *)sc->sc_ethif->hwaddr)->addr, sizeof(ethhdr->src.addr)); + + PPPDEBUG((LOG_DEBUG, "pppoe: %c%c%"U16_F" (%x) state=%d, session=0x%x output -> %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F", len=%d\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, etype, + sc->sc_state, sc->sc_session, + sc->sc_dest.addr[0], sc->sc_dest.addr[1], sc->sc_dest.addr[2], sc->sc_dest.addr[3], sc->sc_dest.addr[4], sc->sc_dest.addr[5], + pb->tot_len)); + + res = sc->sc_ethif->linkoutput(sc->sc_ethif, pb); + + pbuf_free(pb); + + return res; +} + +static err_t +pppoe_send_padi(struct pppoe_softc *sc) +{ + struct pbuf *pb; + u8_t *p; + int len, l1 = 0, l2 = 0; /* XXX: gcc */ + + if (sc->sc_state >PPPOE_STATE_PADI_SENT) { + PPPDEBUG((LOG_ERR, "ERROR: pppoe_send_padi in state %d", sc->sc_state)); + } + + /* calculate length of frame (excluding ethernet header + pppoe header) */ + len = 2 + 2 + 2 + 2 + sizeof sc; /* service name tag is required, host unique is send too */ + if (sc->sc_service_name != NULL) { + l1 = strlen(sc->sc_service_name); + len += l1; + } + if (sc->sc_concentrator_name != NULL) { + l2 = strlen(sc->sc_concentrator_name); + len += 2 + 2 + l2; + } + + /* allocate a buffer */ + pb = pbuf_alloc(PBUF_LINK, sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len, PBUF_RAM); + if (!pb) { + return ERR_MEM; + } + + p = (u8_t*)pb->payload + sizeof (struct eth_hdr); + /* fill in pkt */ + PPPOE_ADD_HEADER(p, PPPOE_CODE_PADI, 0, len); + PPPOE_ADD_16(p, PPPOE_TAG_SNAME); + if (sc->sc_service_name != NULL) { + PPPOE_ADD_16(p, l1); + MEMCPY(p, sc->sc_service_name, l1); + p += l1; + } else { + PPPOE_ADD_16(p, 0); + } + if (sc->sc_concentrator_name != NULL) { + PPPOE_ADD_16(p, PPPOE_TAG_ACNAME); + PPPOE_ADD_16(p, l2); + MEMCPY(p, sc->sc_concentrator_name, l2); + p += l2; + } + PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); + PPPOE_ADD_16(p, sizeof(sc)); + MEMCPY(p, &sc, sizeof sc); + + /* send pkt */ + return pppoe_output(sc, pb); +} + +static void +pppoe_timeout(void *arg) +{ + int retry_wait, err; + struct pppoe_softc *sc = (struct pppoe_softc*)arg; + + PPPDEBUG((LOG_DEBUG, "pppoe: %c%c%"U16_F": timeout\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + + switch (sc->sc_state) { + case PPPOE_STATE_PADI_SENT: + /* + * We have two basic ways of retrying: + * - Quick retry mode: try a few times in short sequence + * - Slow retry mode: we already had a connection successfully + * established and will try infinitely (without user + * intervention) + * We only enter slow retry mode if IFF_LINK1 (aka autodial) + * is not set. + */ + + /* initialize for quick retry mode */ + retry_wait = PPPOE_DISC_TIMEOUT * (1 + sc->sc_padi_retried); + + sc->sc_padi_retried++; + if (sc->sc_padi_retried >= PPPOE_DISC_MAXPADI) { +#if 0 + if ((sc->sc_sppp.pp_if.if_flags & IFF_LINK1) == 0) { + /* slow retry mode */ + retry_wait = PPPOE_SLOW_RETRY; + } else +#endif + { + pppoe_abort_connect(sc); + return; + } + } + if ((err = pppoe_send_padi(sc)) != 0) { + sc->sc_padi_retried--; + PPPDEBUG((LOG_DEBUG, "pppoe: %c%c%"U16_F": failed to transmit PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); + } + tcpip_timeout(retry_wait, pppoe_timeout, sc); + break; + + case PPPOE_STATE_PADR_SENT: + sc->sc_padr_retried++; + if (sc->sc_padr_retried >= PPPOE_DISC_MAXPADR) { + MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); + sc->sc_state = PPPOE_STATE_PADI_SENT; + sc->sc_padr_retried = 0; + if ((err = pppoe_send_padi(sc)) != 0) { + PPPDEBUG((LOG_DEBUG, "pppoe: %c%c%"U16_F": failed to send PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); + } + tcpip_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padi_retried), pppoe_timeout, sc); + return; + } + if ((err = pppoe_send_padr(sc)) != 0) { + sc->sc_padr_retried--; + PPPDEBUG((LOG_DEBUG, "pppoe: %c%c%"U16_F": failed to send PADR, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); + } + tcpip_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padr_retried), pppoe_timeout, sc); + break; + case PPPOE_STATE_CLOSING: + pppoe_do_disconnect(sc); + break; + default: + return; /* all done, work in peace */ + } +} + +/* Start a connection (i.e. initiate discovery phase) */ +int +pppoe_connect(struct pppoe_softc *sc) +{ + int err; + + if (sc->sc_state != PPPOE_STATE_INITIAL) { + return EBUSY; + } + +#ifdef PPPOE_SERVER + /* wait PADI if IFF_PASSIVE */ + if ((sc->sc_sppp.pp_if.if_flags & IFF_PASSIVE)) { + return 0; + } +#endif + /* save state, in case we fail to send PADI */ + sc->sc_state = PPPOE_STATE_PADI_SENT; + sc->sc_padr_retried = 0; + err = pppoe_send_padi(sc); + PPPDEBUG((LOG_DEBUG, "pppoe: %c%c%"U16_F": failed to send PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); + tcpip_timeout(PPPOE_DISC_TIMEOUT, pppoe_timeout, sc); + return err; +} + +/* disconnect */ +void +pppoe_disconnect(struct pppoe_softc *sc) +{ + if (sc->sc_state < PPPOE_STATE_SESSION) { + return; + } + /* + * Do not call pppoe_disconnect here, the upper layer state + * machine gets confused by this. We must return from this + * function and defer disconnecting to the timeout handler. + */ + sc->sc_state = PPPOE_STATE_CLOSING; + tcpip_timeout(20, pppoe_timeout, sc); +} + +static int +pppoe_do_disconnect(struct pppoe_softc *sc) +{ + int err; + + if (sc->sc_state < PPPOE_STATE_SESSION) { + err = EBUSY; + } else { + PPPDEBUG((LOG_DEBUG, "pppoe: %c%c%"U16_F": disconnecting\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + err = pppoe_send_padt(sc->sc_ethif, sc->sc_session, (const u8_t *)&sc->sc_dest); + } + + /* cleanup softc */ + sc->sc_state = PPPOE_STATE_INITIAL; + MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); + if (sc->sc_ac_cookie) { + mem_free(sc->sc_ac_cookie); + sc->sc_ac_cookie = NULL; + } + sc->sc_ac_cookie_len = 0; +#ifdef PPPOE_SERVER + if (sc->sc_hunique) { + mem_free(sc->sc_hunique); + sc->sc_hunique = NULL; + } + sc->sc_hunique_len = 0; +#endif + sc->sc_session = 0; + + sc->sc_linkStatusCB(sc->sc_pd, 0); /* notify upper layers */ + + return err; +} + +/* Connection attempt aborted */ +static void +pppoe_abort_connect(struct pppoe_softc *sc) +{ + printf("%c%c%"U16_F": could not establish connection\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num); + sc->sc_state = PPPOE_STATE_CLOSING; + + sc->sc_linkStatusCB(sc->sc_pd, 0); /* notify upper layers */ + + /* clear connection state */ + MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); + sc->sc_state = PPPOE_STATE_INITIAL; +} + +/* Send a PADR packet */ +static err_t +pppoe_send_padr(struct pppoe_softc *sc) +{ + struct pbuf *pb; + u8_t *p; + size_t len, l1 = 0; /* XXX: gcc */ + + if (sc->sc_state != PPPOE_STATE_PADR_SENT) { + return ERR_CONN; + } + + len = 2 + 2 + 2 + 2 + sizeof(sc); /* service name, host unique */ + if (sc->sc_service_name != NULL) { /* service name tag maybe empty */ + l1 = strlen(sc->sc_service_name); + len += l1; + } + if (sc->sc_ac_cookie_len > 0) { + len += 2 + 2 + sc->sc_ac_cookie_len; /* AC cookie */ + } + pb = pbuf_alloc(PBUF_LINK, sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len, PBUF_RAM); + if (!pb) { + return ERR_MEM; + } + p = (u8_t*)pb->payload + sizeof (struct eth_hdr); + PPPOE_ADD_HEADER(p, PPPOE_CODE_PADR, 0, len); + PPPOE_ADD_16(p, PPPOE_TAG_SNAME); + if (sc->sc_service_name != NULL) { + PPPOE_ADD_16(p, l1); + MEMCPY(p, sc->sc_service_name, l1); + p += l1; + } else { + PPPOE_ADD_16(p, 0); + } + if (sc->sc_ac_cookie_len > 0) { + PPPOE_ADD_16(p, PPPOE_TAG_ACCOOKIE); + PPPOE_ADD_16(p, sc->sc_ac_cookie_len); + MEMCPY(p, sc->sc_ac_cookie, sc->sc_ac_cookie_len); + p += sc->sc_ac_cookie_len; + } + PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); + PPPOE_ADD_16(p, sizeof(sc)); + MEMCPY(p, &sc, sizeof sc); + + return pppoe_output(sc, pb); +} + +/* send a PADT packet */ +static err_t +pppoe_send_padt(struct netif *outgoing_if, u_int session, const u8_t *dest) +{ + struct pbuf *pb; + struct eth_hdr *ethhdr; + err_t res; + u8_t *p; + + pb = pbuf_alloc(PBUF_LINK, sizeof(struct eth_hdr) + PPPOE_HEADERLEN, PBUF_RAM); + if (!pb) { + return ERR_MEM; + } + + ethhdr = (struct eth_hdr *)pb->payload; + ethhdr->type = htons(ETHTYPE_PPPOEDISC); + MEMCPY(ethhdr->dest.addr, dest, sizeof(ethhdr->dest.addr)); + MEMCPY(ethhdr->src.addr, ((struct eth_addr *)outgoing_if->hwaddr)->addr, sizeof(ethhdr->src.addr)); + + p = (u8_t*)(ethhdr + 1); + PPPOE_ADD_HEADER(p, PPPOE_CODE_PADT, session, 0); + + res = outgoing_if->linkoutput(outgoing_if, pb); + + pbuf_free(pb); + + return res; +} + +#ifdef PPPOE_SERVER +static err_t +pppoe_send_pado(struct pppoe_softc *sc) +{ + struct pbuf *pb; + u8_t *p; + size_t len; + + if (sc->sc_state != PPPOE_STATE_PADO_SENT) { + return ERR_CONN; + } + + /* calc length */ + len = 0; + /* include ac_cookie */ + len += 2 + 2 + sizeof(sc); + /* include hunique */ + len += 2 + 2 + sc->sc_hunique_len; + pb = pbuf_alloc(PBUF_LINK, sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len, PBUF_RAM); + if (!pb) { + return ERR_MEM; + } + p = (u8_t*)pb->payload + sizeof (struct eth_hdr); + PPPOE_ADD_HEADER(p, PPPOE_CODE_PADO, 0, len); + PPPOE_ADD_16(p, PPPOE_TAG_ACCOOKIE); + PPPOE_ADD_16(p, sizeof(sc)); + MEMCPY(p, &sc, sizeof(sc)); + p += sizeof(sc); + PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); + PPPOE_ADD_16(p, sc->sc_hunique_len); + MEMCPY(p, sc->sc_hunique, sc->sc_hunique_len); + return pppoe_output(sc, pb); +} + +static err_t +pppoe_send_pads(struct pppoe_softc *sc) +{ + struct pbuf *pb; + u8_t *p; + size_t len, l1 = 0; /* XXX: gcc */ + + if (sc->sc_state != PPPOE_STATE_PADO_SENT) { + return ERR_CONN; + } + + sc->sc_session = mono_time.tv_sec % 0xff + 1; + /* calc length */ + len = 0; + /* include hunique */ + len += 2 + 2 + 2 + 2 + sc->sc_hunique_len; /* service name, host unique*/ + if (sc->sc_service_name != NULL) { /* service name tag maybe empty */ + l1 = strlen(sc->sc_service_name); + len += l1; + } + pb = pbuf_alloc(PBUF_LINK, sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len, PBUF_RAM); + if (!pb) { + return ERR_MEM; + } + p = (u8_t*)pb->payload + sizeof (struct eth_hdr); + PPPOE_ADD_HEADER(p, PPPOE_CODE_PADS, sc->sc_session, len); + PPPOE_ADD_16(p, PPPOE_TAG_SNAME); + if (sc->sc_service_name != NULL) { + PPPOE_ADD_16(p, l1); + MEMCPY(p, sc->sc_service_name, l1); + p += l1; + } else { + PPPOE_ADD_16(p, 0); + } + PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); + PPPOE_ADD_16(p, sc->sc_hunique_len); + MEMCPY(p, sc->sc_hunique, sc->sc_hunique_len); + return pppoe_output(sc, pb); +} +#endif + +err_t +pppoe_xmit(struct pppoe_softc *sc, struct pbuf *pb) +{ + u8_t *p; + size_t len; + + /* are we ready to process data yet? */ + if (sc->sc_state < PPPOE_STATE_SESSION) { + /*sppp_flush(&sc->sc_sppp.pp_if);*/ + pbuf_free(pb); + return ERR_CONN; + } + + len = pb->tot_len; + + /* make room for Ethernet header - should not fail */ + if (pbuf_header(pb, sizeof(struct eth_hdr) + PPPOE_HEADERLEN) != 0) { + /* bail out */ + PPPDEBUG((LOG_ERR, "pppoe: %c%c%"U16_F": pppoe_xmit: could not allocate room for header\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + LINK_STATS_INC(link.lenerr); + pbuf_free(pb); + return ERR_BUF; + } + + p = (u8_t*)pb->payload + sizeof(struct eth_hdr); + PPPOE_ADD_HEADER(p, 0, sc->sc_session, len); + + return pppoe_output(sc, pb); +} + +#if 0 /*def PFIL_HOOKS*/ +static int +pppoe_ifattach_hook(void *arg, struct pbuf **mp, struct netif *ifp, int dir) +{ + struct pppoe_softc *sc; + int s; + + if (mp != (struct pbuf **)PFIL_IFNET_DETACH) { + return 0; + } + + LIST_FOREACH(sc, &pppoe_softc_list, sc_list) { + if (sc->sc_ethif != ifp) { + continue; + } + if (sc->sc_sppp.pp_if.if_flags & IFF_UP) { + sc->sc_sppp.pp_if.if_flags &= ~(IFF_UP|IFF_RUNNING); + printf("%c%c%"U16_F": ethernet interface detached, going down\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num); + } + sc->sc_ethif = NULL; + pppoe_clear_softc(sc, "ethernet interface detached"); + } + + return 0; +} +#endif + +static void +pppoe_clear_softc(struct pppoe_softc *sc, const char *message) +{ + LWIP_UNUSED_ARG(message); + + /* stop timer */ + tcpip_untimeout(pppoe_timeout, sc); + PPPDEBUG((LOG_DEBUG, "pppoe: %c%c%"U16_F": session 0x%x terminated, %s\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, sc->sc_session, message)); + + /* fix our state */ + sc->sc_state = PPPOE_STATE_INITIAL; + + /* notify upper layers */ + sc->sc_linkStatusCB(sc->sc_pd, 0); + + /* clean up softc */ + MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); + if (sc->sc_ac_cookie) { + mem_free(sc->sc_ac_cookie); + sc->sc_ac_cookie = NULL; + } + sc->sc_ac_cookie_len = 0; + sc->sc_session = 0; +} + +#endif /* PPPOE_SUPPORT */ + diff --git a/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/pppdebug.h b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/pppdebug.h new file mode 100644 index 0000000..6253863 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/pppdebug.h @@ -0,0 +1,86 @@ +/***************************************************************************** +* pppdebug.h - System debugging utilities. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1998 Global Election Systems Inc. +* portions Copyright (c) 2001 by Cognizant Pty Ltd. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY (please don't use tabs!) +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 98-07-29 Guy Lancaster , Global Election Systems Inc. +* Original. +* +***************************************************************************** +*/ +#ifndef PPPDEBUG_H +#define PPPDEBUG_H + +/************************ +*** PUBLIC DATA TYPES *** +************************/ +/* Trace levels. */ +typedef enum { +LOG_CRITICAL = 0, +LOG_ERR = 1, +LOG_NOTICE = 2, +LOG_WARNING = 3, +LOG_INFO = 5, +LOG_DETAIL = 6, +LOG_DEBUG = 7 +} LogCodes; + + +/*********************** +*** PUBLIC FUNCTIONS *** +***********************/ +/* + * ppp_trace - a form of printf to send tracing information to stderr + */ +void ppp_trace(int level, const char *format,...); + +#define TRACELCP PPP_DEBUG + +#if PPP_DEBUG + +#define AUTHDEBUG(a) ppp_trace a +#define IPCPDEBUG(a) ppp_trace a +#define UPAPDEBUG(a) ppp_trace a +#define LCPDEBUG(a) ppp_trace a +#define FSMDEBUG(a) ppp_trace a +#define CHAPDEBUG(a) ppp_trace a +#define PPPDEBUG(a) ppp_trace a + +#else /* PPP_DEBUG */ + +#define AUTHDEBUG(a) +#define IPCPDEBUG(a) +#define UPAPDEBUG(a) +#define LCPDEBUG(a) +#define FSMDEBUG(a) +#define CHAPDEBUG(a) +#define PPPDEBUG(a) + +#endif /* PPP_DEBUG */ + +#endif /* PPPDEBUG_H */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/randm.c b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/randm.c new file mode 100644 index 0000000..83c4174 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/randm.c @@ -0,0 +1,249 @@ +/***************************************************************************** +* randm.c - Random number generator program file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* Copyright (c) 1998 by Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 98-06-03 Guy Lancaster , Global Election Systems Inc. +* Extracted from avos. +*****************************************************************************/ + +#include "lwip/opt.h" + +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "md5.h" +#include "randm.h" + +#include "ppp.h" +#include "pppdebug.h" + +#include + +#if MD5_SUPPORT /* this module depends on MD5 */ +#define RANDPOOLSZ 16 /* Bytes stored in the pool of randomness. */ + +/*****************************/ +/*** LOCAL DATA STRUCTURES ***/ +/*****************************/ +static char randPool[RANDPOOLSZ]; /* Pool of randomness. */ +static long randCount = 0; /* Pseudo-random incrementer */ + + +/***********************************/ +/*** PUBLIC FUNCTION DEFINITIONS ***/ +/***********************************/ +/* + * Initialize the random number generator. + * + * Since this is to be called on power up, we don't have much + * system randomess to work with. Here all we use is the + * real-time clock. We'll accumulate more randomness as soon + * as things start happening. + */ +void +avRandomInit() +{ + avChurnRand(NULL, 0); +} + +/* + * Churn the randomness pool on a random event. Call this early and often + * on random and semi-random system events to build randomness in time for + * usage. For randomly timed events, pass a null pointer and a zero length + * and this will use the system timer and other sources to add randomness. + * If new random data is available, pass a pointer to that and it will be + * included. + * + * Ref: Applied Cryptography 2nd Ed. by Bruce Schneier p. 427 + */ +void +avChurnRand(char *randData, u32_t randLen) +{ + MD5_CTX md5; + + /* ppp_trace(LOG_INFO, "churnRand: %u@%P\n", randLen, randData); */ + MD5Init(&md5); + MD5Update(&md5, (u_char *)randPool, sizeof(randPool)); + if (randData) { + MD5Update(&md5, (u_char *)randData, randLen); + } else { + struct { + /* INCLUDE fields for any system sources of randomness */ + char foobar; + } sysData; + + /* Load sysData fields here. */ + MD5Update(&md5, (u_char *)&sysData, sizeof(sysData)); + } + MD5Final((u_char *)randPool, &md5); +/* ppp_trace(LOG_INFO, "churnRand: -> 0\n"); */ +} + +/* + * Use the random pool to generate random data. This degrades to pseudo + * random when used faster than randomness is supplied using churnRand(). + * Note: It's important that there be sufficient randomness in randPool + * before this is called for otherwise the range of the result may be + * narrow enough to make a search feasible. + * + * Ref: Applied Cryptography 2nd Ed. by Bruce Schneier p. 427 + * + * XXX Why does he not just call churnRand() for each block? Probably + * so that you don't ever publish the seed which could possibly help + * predict future values. + * XXX Why don't we preserve md5 between blocks and just update it with + * randCount each time? Probably there is a weakness but I wish that + * it was documented. + */ +void +avGenRand(char *buf, u32_t bufLen) +{ + MD5_CTX md5; + u_char tmp[16]; + u32_t n; + + while (bufLen > 0) { + n = LWIP_MIN(bufLen, RANDPOOLSZ); + MD5Init(&md5); + MD5Update(&md5, (u_char *)randPool, sizeof(randPool)); + MD5Update(&md5, (u_char *)&randCount, sizeof(randCount)); + MD5Final(tmp, &md5); + randCount++; + MEMCPY(buf, tmp, n); + buf += n; + bufLen -= n; + } +} + +/* + * Return a new random number. + */ +u32_t +avRandom() +{ + u32_t newRand; + + avGenRand((char *)&newRand, sizeof(newRand)); + + return newRand; +} + +#else /* MD5_SUPPORT */ + +/*****************************/ +/*** LOCAL DATA STRUCTURES ***/ +/*****************************/ +static int avRandomized = 0; /* Set when truely randomized. */ +static u32_t avRandomSeed = 0; /* Seed used for random number generation. */ + + +/***********************************/ +/*** PUBLIC FUNCTION DEFINITIONS ***/ +/***********************************/ +/* + * Initialize the random number generator. + * + * Here we attempt to compute a random number seed but even if + * it isn't random, we'll randomize it later. + * + * The current method uses the fields from the real time clock, + * the idle process counter, the millisecond counter, and the + * hardware timer tick counter. When this is invoked + * in startup(), then the idle counter and timer values may + * repeat after each boot and the real time clock may not be + * operational. Thus we call it again on the first random + * event. + */ +void +avRandomInit() +{ +#if 0 + /* Get a pointer into the last 4 bytes of clockBuf. */ + u32_t *lptr1 = (u32_t *)((char *)&clockBuf[3]); + + /* + * Initialize our seed using the real-time clock, the idle + * counter, the millisecond timer, and the hardware timer + * tick counter. The real-time clock and the hardware + * tick counter are the best sources of randomness but + * since the tick counter is only 16 bit (and truncated + * at that), the idle counter and millisecond timer + * (which may be small values) are added to help + * randomize the lower 16 bits of the seed. + */ + readClk(); + avRandomSeed += *(u32_t *)clockBuf + *lptr1 + OSIdleCtr + + ppp_mtime() + ((u32_t)TM1 << 16) + TM1; +#else + avRandomSeed += sys_jiffies(); /* XXX */ +#endif + + /* Initialize the Borland random number generator. */ + srand((unsigned)avRandomSeed); +} + +/* + * Randomize our random seed value. Here we use the fact that + * this function is called at *truely random* times by the polling + * and network functions. Here we only get 16 bits of new random + * value but we use the previous value to randomize the other 16 + * bits. + */ +void +avRandomize(void) +{ + static u32_t last_jiffies; + + if (!avRandomized) { + avRandomized = !0; + avRandomInit(); + /* The initialization function also updates the seed. */ + } else { + /* avRandomSeed += (avRandomSeed << 16) + TM1; */ + avRandomSeed += (sys_jiffies() - last_jiffies); /* XXX */ + } + last_jiffies = sys_jiffies(); +} + +/* + * Return a new random number. + * Here we use the Borland rand() function to supply a pseudo random + * number which we make truely random by combining it with our own + * seed which is randomized by truely random events. + * Thus the numbers will be truely random unless there have been no + * operator or network events in which case it will be pseudo random + * seeded by the real time clock. + */ +u32_t +avRandom() +{ + return ((((u32_t)rand() << 16) + rand()) + avRandomSeed); +} + +#endif /* MD5_SUPPORT */ + +#endif /* PPP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/randm.h b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/randm.h new file mode 100644 index 0000000..a0984b0 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/randm.h @@ -0,0 +1,81 @@ +/***************************************************************************** +* randm.h - Random number generator header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* Copyright (c) 1998 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 98-05-29 Guy Lancaster , Global Election Systems Inc. +* Extracted from avos. +*****************************************************************************/ + +#ifndef RANDM_H +#define RANDM_H + +/*********************** +*** PUBLIC FUNCTIONS *** +***********************/ +/* + * Initialize the random number generator. + */ +void avRandomInit(void); + +/* + * Churn the randomness pool on a random event. Call this early and often + * on random and semi-random system events to build randomness in time for + * usage. For randomly timed events, pass a null pointer and a zero length + * and this will use the system timer and other sources to add randomness. + * If new random data is available, pass a pointer to that and it will be + * included. + */ +void avChurnRand(char *randData, u32_t randLen); + +/* + * Randomize our random seed value. To be called for truely random events + * such as user operations and network traffic. + */ +#if MD5_SUPPORT +#define avRandomize() avChurnRand(NULL, 0) +#else /* MD5_SUPPORT */ +void avRandomize(void); +#endif /* MD5_SUPPORT */ + +/* + * Use the random pool to generate random data. This degrades to pseudo + * random when used faster than randomness is supplied using churnRand(). + * Thus it's important to make sure that the results of this are not + * published directly because one could predict the next result to at + * least some degree. Also, it's important to get a good seed before + * the first use. + */ +void avGenRand(char *buf, u32_t bufLen); + +/* + * Return a new random number. + */ +u32_t avRandom(void); + + +#endif /* RANDM_H */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/vj.c b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/vj.c new file mode 100644 index 0000000..694b702 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/vj.c @@ -0,0 +1,660 @@ +/* + * Routines to compress and uncompess tcp packets (for transmission + * over low speed serial lines. + * + * Copyright (c) 1989 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989: + * Initial distribution. + * + * Modified June 1993 by Paul Mackerras, paulus@cs.anu.edu.au, + * so that the entire packet being decompressed doesn't have + * to be in contiguous memory (just the compressed header). + * + * Modified March 1998 by Guy Lancaster, glanca@gesn.com, + * for a 16 bit processor. + */ + +#include "lwip/opt.h" + +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "ppp.h" +#include "pppdebug.h" + +#include "vj.h" + +#include + +#if VJ_SUPPORT + +#if LINK_STATS +#define INCR(counter) ++comp->stats.counter +#else +#define INCR(counter) +#endif + +#if defined(NO_CHAR_BITFIELDS) +#define getip_hl(base) ((base).ip_hl_v&0xf) +#define getth_off(base) (((base).th_x2_off&0xf0)>>4) +#else +#define getip_hl(base) ((base).ip_hl) +#define getth_off(base) ((base).th_off) +#endif + +void +vj_compress_init(struct vjcompress *comp) +{ + register u_int i; + register struct cstate *tstate = comp->tstate; + +#if MAX_SLOTS == 0 + memset((char *)comp, 0, sizeof(*comp)); +#endif + comp->maxSlotIndex = MAX_SLOTS - 1; + comp->compressSlot = 0; /* Disable slot ID compression by default. */ + for (i = MAX_SLOTS - 1; i > 0; --i) { + tstate[i].cs_id = i; + tstate[i].cs_next = &tstate[i - 1]; + } + tstate[0].cs_next = &tstate[MAX_SLOTS - 1]; + tstate[0].cs_id = 0; + comp->last_cs = &tstate[0]; + comp->last_recv = 255; + comp->last_xmit = 255; + comp->flags = VJF_TOSS; +} + + +/* ENCODE encodes a number that is known to be non-zero. ENCODEZ + * checks for zero (since zero has to be encoded in the long, 3 byte + * form). + */ +#define ENCODE(n) { \ + if ((u_short)(n) >= 256) { \ + *cp++ = 0; \ + cp[1] = (n); \ + cp[0] = (n) >> 8; \ + cp += 2; \ + } else { \ + *cp++ = (n); \ + } \ +} +#define ENCODEZ(n) { \ + if ((u_short)(n) >= 256 || (u_short)(n) == 0) { \ + *cp++ = 0; \ + cp[1] = (n); \ + cp[0] = (n) >> 8; \ + cp += 2; \ + } else { \ + *cp++ = (n); \ + } \ +} + +#define DECODEL(f) { \ + if (*cp == 0) {\ + u32_t tmp = ntohl(f) + ((cp[1] << 8) | cp[2]); \ + (f) = htonl(tmp); \ + cp += 3; \ + } else { \ + u32_t tmp = ntohl(f) + (u32_t)*cp++; \ + (f) = htonl(tmp); \ + } \ +} + +#define DECODES(f) { \ + if (*cp == 0) {\ + u_short tmp = ntohs(f) + (((u_short)cp[1] << 8) | cp[2]); \ + (f) = htons(tmp); \ + cp += 3; \ + } else { \ + u_short tmp = ntohs(f) + (u_short)*cp++; \ + (f) = htons(tmp); \ + } \ +} + +#define DECODEU(f) { \ + if (*cp == 0) {\ + (f) = htons(((u_short)cp[1] << 8) | cp[2]); \ + cp += 3; \ + } else { \ + (f) = htons((u_short)*cp++); \ + } \ +} + +/* + * vj_compress_tcp - Attempt to do Van Jacobson header compression on a + * packet. This assumes that nb and comp are not null and that the first + * buffer of the chain contains a valid IP header. + * Return the VJ type code indicating whether or not the packet was + * compressed. + */ +u_int +vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb) +{ + register struct ip *ip = (struct ip *)pb->payload; + register struct cstate *cs = comp->last_cs->cs_next; + register u_short hlen = getip_hl(*ip); + register struct tcphdr *oth; + register struct tcphdr *th; + register u_short deltaS, deltaA; + register u_long deltaL; + register u_int changes = 0; + u_char new_seq[16]; + register u_char *cp = new_seq; + + /* + * Check that the packet is IP proto TCP. + */ + if (ip->ip_p != IPPROTO_TCP) { + return (TYPE_IP); + } + + /* + * Bail if this is an IP fragment or if the TCP packet isn't + * `compressible' (i.e., ACK isn't set or some other control bit is + * set). + */ + if ((ip->ip_off & htons(0x3fff)) || pb->tot_len < 40) { + return (TYPE_IP); + } + th = (struct tcphdr *)&((long *)ip)[hlen]; + if ((th->th_flags & (TCP_SYN|TCP_FIN|TCP_RST|TCP_ACK)) != TCP_ACK) { + return (TYPE_IP); + } + /* + * Packet is compressible -- we're going to send either a + * COMPRESSED_TCP or UNCOMPRESSED_TCP packet. Either way we need + * to locate (or create) the connection state. Special case the + * most recently used connection since it's most likely to be used + * again & we don't have to do any reordering if it's used. + */ + INCR(vjs_packets); + if (ip->ip_src.s_addr != cs->cs_ip.ip_src.s_addr + || ip->ip_dst.s_addr != cs->cs_ip.ip_dst.s_addr + || *(long *)th != ((long *)&cs->cs_ip)[getip_hl(cs->cs_ip)]) { + /* + * Wasn't the first -- search for it. + * + * States are kept in a circularly linked list with + * last_cs pointing to the end of the list. The + * list is kept in lru order by moving a state to the + * head of the list whenever it is referenced. Since + * the list is short and, empirically, the connection + * we want is almost always near the front, we locate + * states via linear search. If we don't find a state + * for the datagram, the oldest state is (re-)used. + */ + register struct cstate *lcs; + register struct cstate *lastcs = comp->last_cs; + + do { + lcs = cs; cs = cs->cs_next; + INCR(vjs_searches); + if (ip->ip_src.s_addr == cs->cs_ip.ip_src.s_addr + && ip->ip_dst.s_addr == cs->cs_ip.ip_dst.s_addr + && *(long *)th == ((long *)&cs->cs_ip)[getip_hl(cs->cs_ip)]) { + goto found; + } + } while (cs != lastcs); + + /* + * Didn't find it -- re-use oldest cstate. Send an + * uncompressed packet that tells the other side what + * connection number we're using for this conversation. + * Note that since the state list is circular, the oldest + * state points to the newest and we only need to set + * last_cs to update the lru linkage. + */ + INCR(vjs_misses); + comp->last_cs = lcs; + hlen += getth_off(*th); + hlen <<= 2; + /* Check that the IP/TCP headers are contained in the first buffer. */ + if (hlen > pb->len) { + return (TYPE_IP); + } + goto uncompressed; + + found: + /* + * Found it -- move to the front on the connection list. + */ + if (cs == lastcs) { + comp->last_cs = lcs; + } else { + lcs->cs_next = cs->cs_next; + cs->cs_next = lastcs->cs_next; + lastcs->cs_next = cs; + } + } + + oth = (struct tcphdr *)&((long *)&cs->cs_ip)[hlen]; + deltaS = hlen; + hlen += getth_off(*th); + hlen <<= 2; + /* Check that the IP/TCP headers are contained in the first buffer. */ + if (hlen > pb->len) { + PPPDEBUG((LOG_INFO, "vj_compress_tcp: header len %d spans buffers\n", hlen)); + return (TYPE_IP); + } + + /* + * Make sure that only what we expect to change changed. The first + * line of the `if' checks the IP protocol version, header length & + * type of service. The 2nd line checks the "Don't fragment" bit. + * The 3rd line checks the time-to-live and protocol (the protocol + * check is unnecessary but costless). The 4th line checks the TCP + * header length. The 5th line checks IP options, if any. The 6th + * line checks TCP options, if any. If any of these things are + * different between the previous & current datagram, we send the + * current datagram `uncompressed'. + */ + if (((u_short *)ip)[0] != ((u_short *)&cs->cs_ip)[0] + || ((u_short *)ip)[3] != ((u_short *)&cs->cs_ip)[3] + || ((u_short *)ip)[4] != ((u_short *)&cs->cs_ip)[4] + || getth_off(*th) != getth_off(*oth) + || (deltaS > 5 && BCMP(ip + 1, &cs->cs_ip + 1, (deltaS - 5) << 2)) + || (getth_off(*th) > 5 && BCMP(th + 1, oth + 1, (getth_off(*th) - 5) << 2))) { + goto uncompressed; + } + + /* + * Figure out which of the changing fields changed. The + * receiver expects changes in the order: urgent, window, + * ack, seq (the order minimizes the number of temporaries + * needed in this section of code). + */ + if (th->th_flags & TCP_URG) { + deltaS = ntohs(th->th_urp); + ENCODEZ(deltaS); + changes |= NEW_U; + } else if (th->th_urp != oth->th_urp) { + /* argh! URG not set but urp changed -- a sensible + * implementation should never do this but RFC793 + * doesn't prohibit the change so we have to deal + * with it. */ + goto uncompressed; + } + + if ((deltaS = (u_short)(ntohs(th->th_win) - ntohs(oth->th_win))) != 0) { + ENCODE(deltaS); + changes |= NEW_W; + } + + if ((deltaL = ntohl(th->th_ack) - ntohl(oth->th_ack)) != 0) { + if (deltaL > 0xffff) { + goto uncompressed; + } + deltaA = (u_short)deltaL; + ENCODE(deltaA); + changes |= NEW_A; + } + + if ((deltaL = ntohl(th->th_seq) - ntohl(oth->th_seq)) != 0) { + if (deltaL > 0xffff) { + goto uncompressed; + } + deltaS = (u_short)deltaL; + ENCODE(deltaS); + changes |= NEW_S; + } + + switch(changes) { + case 0: + /* + * Nothing changed. If this packet contains data and the + * last one didn't, this is probably a data packet following + * an ack (normal on an interactive connection) and we send + * it compressed. Otherwise it's probably a retransmit, + * retransmitted ack or window probe. Send it uncompressed + * in case the other side missed the compressed version. + */ + if (ip->ip_len != cs->cs_ip.ip_len && + ntohs(cs->cs_ip.ip_len) == hlen) { + break; + } + + /* (fall through) */ + + case SPECIAL_I: + case SPECIAL_D: + /* + * actual changes match one of our special case encodings -- + * send packet uncompressed. + */ + goto uncompressed; + + case NEW_S|NEW_A: + if (deltaS == deltaA && deltaS == ntohs(cs->cs_ip.ip_len) - hlen) { + /* special case for echoed terminal traffic */ + changes = SPECIAL_I; + cp = new_seq; + } + break; + + case NEW_S: + if (deltaS == ntohs(cs->cs_ip.ip_len) - hlen) { + /* special case for data xfer */ + changes = SPECIAL_D; + cp = new_seq; + } + break; + } + + deltaS = (u_short)(ntohs(ip->ip_id) - ntohs(cs->cs_ip.ip_id)); + if (deltaS != 1) { + ENCODEZ(deltaS); + changes |= NEW_I; + } + if (th->th_flags & TCP_PSH) { + changes |= TCP_PUSH_BIT; + } + /* + * Grab the cksum before we overwrite it below. Then update our + * state with this packet's header. + */ + deltaA = ntohs(th->th_sum); + BCOPY(ip, &cs->cs_ip, hlen); + + /* + * We want to use the original packet as our compressed packet. + * (cp - new_seq) is the number of bytes we need for compressed + * sequence numbers. In addition we need one byte for the change + * mask, one for the connection id and two for the tcp checksum. + * So, (cp - new_seq) + 4 bytes of header are needed. hlen is how + * many bytes of the original packet to toss so subtract the two to + * get the new packet size. + */ + deltaS = (u_short)(cp - new_seq); + if (!comp->compressSlot || comp->last_xmit != cs->cs_id) { + comp->last_xmit = cs->cs_id; + hlen -= deltaS + 4; + if(pbuf_header(pb, -hlen)){ + /* Can we cope with this failing? Just assert for now */ + LWIP_ASSERT("pbuf_header failed\n", 0); + } + cp = (u_char *)pb->payload; + *cp++ = changes | NEW_C; + *cp++ = cs->cs_id; + } else { + hlen -= deltaS + 3; + if(pbuf_header(pb, -hlen)) { + /* Can we cope with this failing? Just assert for now */ + LWIP_ASSERT("pbuf_header failed\n", 0); + } + cp = (u_char *)pb->payload; + *cp++ = changes; + } + *cp++ = deltaA >> 8; + *cp++ = deltaA; + BCOPY(new_seq, cp, deltaS); + INCR(vjs_compressed); + return (TYPE_COMPRESSED_TCP); + + /* + * Update connection state cs & send uncompressed packet (that is, + * a regular ip/tcp packet but with the 'conversation id' we hope + * to use on future compressed packets in the protocol field). + */ +uncompressed: + BCOPY(ip, &cs->cs_ip, hlen); + ip->ip_p = cs->cs_id; + comp->last_xmit = cs->cs_id; + return (TYPE_UNCOMPRESSED_TCP); +} + +/* + * Called when we may have missed a packet. + */ +void +vj_uncompress_err(struct vjcompress *comp) +{ + comp->flags |= VJF_TOSS; + INCR(vjs_errorin); +} + +/* + * "Uncompress" a packet of type TYPE_UNCOMPRESSED_TCP. + * Return 0 on success, -1 on failure. + */ +int +vj_uncompress_uncomp(struct pbuf *nb, struct vjcompress *comp) +{ + register u_int hlen; + register struct cstate *cs; + register struct ip *ip; + + ip = (struct ip *)nb->payload; + hlen = getip_hl(*ip) << 2; + if (ip->ip_p >= MAX_SLOTS + || hlen + sizeof(struct tcphdr) > nb->len + || (hlen += getth_off(*((struct tcphdr *)&((char *)ip)[hlen])) << 2) + > nb->len + || hlen > MAX_HDR) { + PPPDEBUG((LOG_INFO, "vj_uncompress_uncomp: bad cid=%d, hlen=%d buflen=%d\n", + ip->ip_p, hlen, nb->len)); + comp->flags |= VJF_TOSS; + INCR(vjs_errorin); + return -1; + } + cs = &comp->rstate[comp->last_recv = ip->ip_p]; + comp->flags &=~ VJF_TOSS; + ip->ip_p = IPPROTO_TCP; + BCOPY(ip, &cs->cs_ip, hlen); + cs->cs_hlen = hlen; + INCR(vjs_uncompressedin); + return 0; +} + +/* + * Uncompress a packet of type TYPE_COMPRESSED_TCP. + * The packet is composed of a buffer chain and the first buffer + * must contain an accurate chain length. + * The first buffer must include the entire compressed TCP/IP header. + * This procedure replaces the compressed header with the uncompressed + * header and returns the length of the VJ header. + */ +int +vj_uncompress_tcp(struct pbuf **nb, struct vjcompress *comp) +{ + u_char *cp; + struct tcphdr *th; + struct cstate *cs; + u_short *bp; + struct pbuf *n0 = *nb; + u32_t tmp; + u_int vjlen, hlen, changes; + + INCR(vjs_compressedin); + cp = (u_char *)n0->payload; + changes = *cp++; + if (changes & NEW_C) { + /* + * Make sure the state index is in range, then grab the state. + * If we have a good state index, clear the 'discard' flag. + */ + if (*cp >= MAX_SLOTS) { + PPPDEBUG((LOG_INFO, "vj_uncompress_tcp: bad cid=%d\n", *cp)); + goto bad; + } + + comp->flags &=~ VJF_TOSS; + comp->last_recv = *cp++; + } else { + /* + * this packet has an implicit state index. If we've + * had a line error since the last time we got an + * explicit state index, we have to toss the packet. + */ + if (comp->flags & VJF_TOSS) { + PPPDEBUG((LOG_INFO, "vj_uncompress_tcp: tossing\n")); + INCR(vjs_tossed); + return (-1); + } + } + cs = &comp->rstate[comp->last_recv]; + hlen = getip_hl(cs->cs_ip) << 2; + th = (struct tcphdr *)&((u_char *)&cs->cs_ip)[hlen]; + th->th_sum = htons((*cp << 8) | cp[1]); + cp += 2; + if (changes & TCP_PUSH_BIT) { + th->th_flags |= TCP_PSH; + } else { + th->th_flags &=~ TCP_PSH; + } + + switch (changes & SPECIALS_MASK) { + case SPECIAL_I: + { + register u32_t i = ntohs(cs->cs_ip.ip_len) - cs->cs_hlen; + /* some compilers can't nest inline assembler.. */ + tmp = ntohl(th->th_ack) + i; + th->th_ack = htonl(tmp); + tmp = ntohl(th->th_seq) + i; + th->th_seq = htonl(tmp); + } + break; + + case SPECIAL_D: + /* some compilers can't nest inline assembler.. */ + tmp = ntohl(th->th_seq) + ntohs(cs->cs_ip.ip_len) - cs->cs_hlen; + th->th_seq = htonl(tmp); + break; + + default: + if (changes & NEW_U) { + th->th_flags |= TCP_URG; + DECODEU(th->th_urp); + } else { + th->th_flags &=~ TCP_URG; + } + if (changes & NEW_W) { + DECODES(th->th_win); + } + if (changes & NEW_A) { + DECODEL(th->th_ack); + } + if (changes & NEW_S) { + DECODEL(th->th_seq); + } + break; + } + if (changes & NEW_I) { + DECODES(cs->cs_ip.ip_id); + } else { + cs->cs_ip.ip_id = ntohs(cs->cs_ip.ip_id) + 1; + cs->cs_ip.ip_id = htons(cs->cs_ip.ip_id); + } + + /* + * At this point, cp points to the first byte of data in the + * packet. Fill in the IP total length and update the IP + * header checksum. + */ + vjlen = (u_short)(cp - (u_char*)n0->payload); + if (n0->len < vjlen) { + /* + * We must have dropped some characters (crc should detect + * this but the old slip framing won't) + */ + PPPDEBUG((LOG_INFO, "vj_uncompress_tcp: head buffer %d too short %d\n", + n0->len, vjlen)); + goto bad; + } + +#if BYTE_ORDER == LITTLE_ENDIAN + tmp = n0->tot_len - vjlen + cs->cs_hlen; + cs->cs_ip.ip_len = htons(tmp); +#else + cs->cs_ip.ip_len = htons(n0->tot_len - vjlen + cs->cs_hlen); +#endif + + /* recompute the ip header checksum */ + bp = (u_short *) &cs->cs_ip; + cs->cs_ip.ip_sum = 0; + for (tmp = 0; hlen > 0; hlen -= 2) { + tmp += *bp++; + } + tmp = (tmp & 0xffff) + (tmp >> 16); + tmp = (tmp & 0xffff) + (tmp >> 16); + cs->cs_ip.ip_sum = (u_short)(~tmp); + + /* Remove the compressed header and prepend the uncompressed header. */ + if(pbuf_header(n0, -((s16_t)(vjlen)))) { + /* Can we cope with this failing? Just assert for now */ + LWIP_ASSERT("pbuf_header failed\n", 0); + goto bad; + } + + if(LWIP_MEM_ALIGN(n0->payload) != n0->payload) { + struct pbuf *np, *q; + u8_t *bufptr; + + np = pbuf_alloc(PBUF_RAW, n0->len + cs->cs_hlen, PBUF_POOL); + if(!np) { + PPPDEBUG((LOG_WARNING, "vj_uncompress_tcp: realign failed\n")); + goto bad; + } + + if(pbuf_header(np, -cs->cs_hlen)) { + /* Can we cope with this failing? Just assert for now */ + LWIP_ASSERT("pbuf_header failed\n", 0); + goto bad; + } + + bufptr = n0->payload; + for(q = np; q != NULL; q = q->next) { + MEMCPY(q->payload, bufptr, q->len); + bufptr += q->len; + } + + if(n0->next) { + pbuf_chain(np, n0->next); + pbuf_dechain(n0); + } + pbuf_free(n0); + n0 = np; + } + + if(pbuf_header(n0, cs->cs_hlen)) { + struct pbuf *np; + + LWIP_ASSERT("vj_uncompress_tcp: cs->cs_hlen <= PBUF_POOL_BUFSIZE", cs->cs_hlen <= PBUF_POOL_BUFSIZE); + np = pbuf_alloc(PBUF_RAW, cs->cs_hlen, PBUF_POOL); + if(!np) { + PPPDEBUG((LOG_WARNING, "vj_uncompress_tcp: prepend failed\n")); + goto bad; + } + pbuf_cat(np, n0); + n0 = np; + } + LWIP_ASSERT("n0->len >= cs->cs_hlen", n0->len >= cs->cs_hlen); + MEMCPY(n0->payload, &cs->cs_ip, cs->cs_hlen); + + *nb = n0; + + return vjlen; + +bad: + comp->flags |= VJF_TOSS; + INCR(vjs_errorin); + return (-1); +} + +#endif /* VJ_SUPPORT */ + +#endif /* PPP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/vj.h b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/vj.h new file mode 100644 index 0000000..b9617da --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/vj.h @@ -0,0 +1,155 @@ +/* + * Definitions for tcp compression routines. + * + * $Id: vj.h,v 1.5 2007/12/19 20:47:23 fbernon Exp $ + * + * Copyright (c) 1989 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989: + * - Initial distribution. + */ + +#ifndef VJ_H +#define VJ_H + +#include "vjbsdhdr.h" + +#define MAX_SLOTS 16 /* must be > 2 and < 256 */ +#define MAX_HDR 128 + +/* + * Compressed packet format: + * + * The first octet contains the packet type (top 3 bits), TCP + * 'push' bit, and flags that indicate which of the 4 TCP sequence + * numbers have changed (bottom 5 bits). The next octet is a + * conversation number that associates a saved IP/TCP header with + * the compressed packet. The next two octets are the TCP checksum + * from the original datagram. The next 0 to 15 octets are + * sequence number changes, one change per bit set in the header + * (there may be no changes and there are two special cases where + * the receiver implicitly knows what changed -- see below). + * + * There are 5 numbers which can change (they are always inserted + * in the following order): TCP urgent pointer, window, + * acknowlegement, sequence number and IP ID. (The urgent pointer + * is different from the others in that its value is sent, not the + * change in value.) Since typical use of SLIP links is biased + * toward small packets (see comments on MTU/MSS below), changes + * use a variable length coding with one octet for numbers in the + * range 1 - 255 and 3 octets (0, MSB, LSB) for numbers in the + * range 256 - 65535 or 0. (If the change in sequence number or + * ack is more than 65535, an uncompressed packet is sent.) + */ + +/* + * Packet types (must not conflict with IP protocol version) + * + * The top nibble of the first octet is the packet type. There are + * three possible types: IP (not proto TCP or tcp with one of the + * control flags set); uncompressed TCP (a normal IP/TCP packet but + * with the 8-bit protocol field replaced by an 8-bit connection id -- + * this type of packet syncs the sender & receiver); and compressed + * TCP (described above). + * + * LSB of 4-bit field is TCP "PUSH" bit (a worthless anachronism) and + * is logically part of the 4-bit "changes" field that follows. Top + * three bits are actual packet type. For backward compatibility + * and in the interest of conserving bits, numbers are chosen so the + * IP protocol version number (4) which normally appears in this nibble + * means "IP packet". + */ + +/* packet types */ +#define TYPE_IP 0x40 +#define TYPE_UNCOMPRESSED_TCP 0x70 +#define TYPE_COMPRESSED_TCP 0x80 +#define TYPE_ERROR 0x00 + +/* Bits in first octet of compressed packet */ +#define NEW_C 0x40 /* flag bits for what changed in a packet */ +#define NEW_I 0x20 +#define NEW_S 0x08 +#define NEW_A 0x04 +#define NEW_W 0x02 +#define NEW_U 0x01 + +/* reserved, special-case values of above */ +#define SPECIAL_I (NEW_S|NEW_W|NEW_U) /* echoed interactive traffic */ +#define SPECIAL_D (NEW_S|NEW_A|NEW_W|NEW_U) /* unidirectional data */ +#define SPECIALS_MASK (NEW_S|NEW_A|NEW_W|NEW_U) + +#define TCP_PUSH_BIT 0x10 + + +/* + * "state" data for each active tcp conversation on the wire. This is + * basically a copy of the entire IP/TCP header from the last packet + * we saw from the conversation together with a small identifier + * the transmit & receive ends of the line use to locate saved header. + */ +struct cstate { + struct cstate *cs_next; /* next most recently used state (xmit only) */ + u_short cs_hlen; /* size of hdr (receive only) */ + u_char cs_id; /* connection # associated with this state */ + u_char cs_filler; + union { + char csu_hdr[MAX_HDR]; + struct ip csu_ip; /* ip/tcp hdr from most recent packet */ + } vjcs_u; +}; +#define cs_ip vjcs_u.csu_ip +#define cs_hdr vjcs_u.csu_hdr + + +struct vjstat { + unsigned long vjs_packets; /* outbound packets */ + unsigned long vjs_compressed; /* outbound compressed packets */ + unsigned long vjs_searches; /* searches for connection state */ + unsigned long vjs_misses; /* times couldn't find conn. state */ + unsigned long vjs_uncompressedin; /* inbound uncompressed packets */ + unsigned long vjs_compressedin; /* inbound compressed packets */ + unsigned long vjs_errorin; /* inbound unknown type packets */ + unsigned long vjs_tossed; /* inbound packets tossed because of error */ +}; + +/* + * all the state data for one serial line (we need one of these per line). + */ +struct vjcompress { + struct cstate *last_cs; /* most recently used tstate */ + u_char last_recv; /* last rcvd conn. id */ + u_char last_xmit; /* last sent conn. id */ + u_short flags; + u_char maxSlotIndex; + u_char compressSlot; /* Flag indicating OK to compress slot ID. */ +#if LINK_STATS + struct vjstat stats; +#endif + struct cstate tstate[MAX_SLOTS]; /* xmit connection states */ + struct cstate rstate[MAX_SLOTS]; /* receive connection states */ +}; + +/* flag values */ +#define VJF_TOSS 1U /* tossing rcvd frames because of input err */ + +extern void vj_compress_init (struct vjcompress *comp); +extern u_int vj_compress_tcp (struct vjcompress *comp, struct pbuf *pb); +extern void vj_uncompress_err (struct vjcompress *comp); +extern int vj_uncompress_uncomp(struct pbuf *nb, struct vjcompress *comp); +extern int vj_uncompress_tcp (struct pbuf **nb, struct vjcompress *comp); + +#endif /* VJ_H */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/vjbsdhdr.h b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/vjbsdhdr.h new file mode 100644 index 0000000..f462676 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/netif/ppp/vjbsdhdr.h @@ -0,0 +1,75 @@ +#ifndef VJBSDHDR_H +#define VJBSDHDR_H + +#include "lwip/tcp.h" + +/* + * Structure of an internet header, naked of options. + * + * We declare ip_len and ip_off to be short, rather than u_short + * pragmatically since otherwise unsigned comparisons can result + * against negative integers quite easily, and fail in subtle ways. + */ +PACK_STRUCT_BEGIN +struct ip +{ +#if defined(NO_CHAR_BITFIELDS) + u_char ip_hl_v; /* bug in GCC for mips means the bitfield stuff will sometimes break - so we use a char for both and get round it with macro's instead... */ +#else +#if BYTE_ORDER == LITTLE_ENDIAN + unsigned ip_hl:4, /* header length */ + ip_v :4; /* version */ +#elif BYTE_ORDER == BIG_ENDIAN + unsigned ip_v :4, /* version */ + ip_hl:4; /* header length */ +#else + COMPLAIN - NO BYTE ORDER SELECTED! +#endif +#endif + u_char ip_tos; /* type of service */ + u_short ip_len; /* total length */ + u_short ip_id; /* identification */ + u_short ip_off; /* fragment offset field */ +#define IP_DF 0x4000 /* dont fragment flag */ +#define IP_MF 0x2000 /* more fragments flag */ +#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ + u_char ip_ttl; /* time to live */ + u_char ip_p; /* protocol */ + u_short ip_sum; /* checksum */ + struct in_addr ip_src,ip_dst; /* source and dest address */ +}; +PACK_STRUCT_END + +typedef u32_t tcp_seq; + +/* + * TCP header. + * Per RFC 793, September, 1981. + */ +PACK_STRUCT_BEGIN +struct tcphdr +{ + u_short th_sport; /* source port */ + u_short th_dport; /* destination port */ + tcp_seq th_seq; /* sequence number */ + tcp_seq th_ack; /* acknowledgement number */ +#if defined(NO_CHAR_BITFIELDS) + u_char th_x2_off; +#else +#if BYTE_ORDER == LITTLE_ENDIAN + unsigned th_x2 :4, /* (unused) */ + th_off:4; /* data offset */ +#endif +#if BYTE_ORDER == BIG_ENDIAN + unsigned th_off:4, /* data offset */ + th_x2 :4; /* (unused) */ +#endif +#endif + u_char th_flags; + u_short th_win; /* window */ + u_short th_sum; /* checksum */ + u_short th_urp; /* urgent pointer */ +}; +PACK_STRUCT_END + +#endif /* VJBSDHDR_H */ diff --git a/component/common/network/lwip/lwip_v1.3.2/src/netif/slipif.c b/component/common/network/lwip/lwip_v1.3.2/src/netif/slipif.c new file mode 100644 index 0000000..089d2d3 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.3.2/src/netif/slipif.c @@ -0,0 +1,367 @@ +/** + * @file + * SLIP Interface + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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 Institute 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 INSTITUTE 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 INSTITUTE 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. + * + * This file is built upon the file: src/arch/rtxc/netif/sioslip.c + * + * Author: Magnus Ivarsson + */ + +/* + * This is an arch independent SLIP netif. The specific serial hooks must be + * provided by another file. They are sio_open, sio_read/sio_tryread and sio_send + */ + +#include "netif/slipif.h" +#include "lwip/opt.h" + +#if LWIP_HAVE_SLIPIF + +#include "lwip/def.h" +#include "lwip/pbuf.h" +#include "lwip/sys.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "lwip/sio.h" + +#define SLIP_BLOCK 1 +#define SLIP_DONTBLOCK 0 + +#define SLIP_END 0300 /* 0xC0 */ +#define SLIP_ESC 0333 /* 0xDB */ +#define SLIP_ESC_END 0334 /* 0xDC */ +#define SLIP_ESC_ESC 0335 /* 0xDD */ + +#define SLIP_MAX_SIZE 1500 + +enum slipif_recv_state { + SLIP_RECV_NORMAL, + SLIP_RECV_ESCAPE, +}; + +struct slipif_priv { + sio_fd_t sd; + /* q is the whole pbuf chain for a packet, p is the current pbuf in the chain */ + struct pbuf *p, *q; + enum slipif_recv_state state; + u16_t i, recved; +}; + +/** + * Send a pbuf doing the necessary SLIP encapsulation + * + * Uses the serial layer's sio_send() + * + * @param netif the lwip network interface structure for this slipif + * @param p the pbuf chaing packet to send + * @param ipaddr the ip address to send the packet to (not used for slipif) + * @return always returns ERR_OK since the serial layer does not provide return values + */ +err_t +slipif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr) +{ + struct slipif_priv *priv; + struct pbuf *q; + u16_t i; + u8_t c; + + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + LWIP_ASSERT("p != NULL", (p != NULL)); + + LWIP_UNUSED_ARG(ipaddr); + + priv = netif->state; + + /* Send pbuf out on the serial I/O device. */ + sio_send(SLIP_END, priv->sd); + + for (q = p; q != NULL; q = q->next) { + for (i = 0; i < q->len; i++) { + c = ((u8_t *)q->payload)[i]; + switch (c) { + case SLIP_END: + sio_send(SLIP_ESC, priv->sd); + sio_send(SLIP_ESC_END, priv->sd); + break; + case SLIP_ESC: + sio_send(SLIP_ESC, priv->sd); + sio_send(SLIP_ESC_ESC, priv->sd); + break; + default: + sio_send(c, priv->sd); + break; + } + } + } + sio_send(SLIP_END, priv->sd); + return ERR_OK; +} + +/** + * Static function for easy use of blockig or non-blocking + * sio_read + * + * @param fd serial device handle + * @param data pointer to data buffer for receiving + * @param len maximum length (in bytes) of data to receive + * @param block if 1, call sio_read; if 0, call sio_tryread + * @return return value of sio_read of sio_tryread + */ +static u32_t +slip_sio_read(sio_fd_t fd, u8_t* data, u32_t len, u8_t block) +{ + if (block) { + return sio_read(fd, data, len); + } else { + return sio_tryread(fd, data, len); + } +} + +/** + * Handle the incoming SLIP stream character by character + * + * Poll the serial layer by calling sio_read() or sio_tryread(). + * + * @param netif the lwip network interface structure for this slipif + * @param block if 1, block until data is received; if 0, return when all data + * from the buffer is received (multiple calls to this function will + * return a complete packet, NULL is returned before - used for polling) + * @return The IP packet when SLIP_END is received + */ +static struct pbuf * +slipif_input(struct netif *netif, u8_t block) +{ + struct slipif_priv *priv; + u8_t c; + struct pbuf *t; + + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + + priv = netif->state; + + while (slip_sio_read(priv->sd, &c, 1, block) > 0) { + switch (priv->state) { + case SLIP_RECV_NORMAL: + switch (c) { + case SLIP_END: + if (priv->recved > 0) { + /* Received whole packet. */ + /* Trim the pbuf to the size of the received packet. */ + pbuf_realloc(priv->q, priv->recved); + + LINK_STATS_INC(link.recv); + + LWIP_DEBUGF(SLIP_DEBUG, ("slipif: Got packet\n")); + t = priv->q; + priv->p = priv->q = NULL; + priv->i = priv->recved = 0; + return t; + } + continue; + case SLIP_ESC: + priv->state = SLIP_RECV_ESCAPE; + continue; + } + break; + case SLIP_RECV_ESCAPE: + switch (c) { + case SLIP_ESC_END: + c = SLIP_END; + break; + case SLIP_ESC_ESC: + c = SLIP_ESC; + break; + } + priv->state = SLIP_RECV_NORMAL; + /* FALLTHROUGH */ + } + + /* byte received, packet not yet completely received */ + if (priv->p == NULL) { + /* allocate a new pbuf */ + LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: alloc\n")); + priv->p = pbuf_alloc(PBUF_LINK, (PBUF_POOL_BUFSIZE - PBUF_LINK_HLEN), PBUF_POOL); + + if (priv->p == NULL) { + LINK_STATS_INC(link.drop); + LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: no new pbuf! (DROP)\n")); + /* don't process any further since we got no pbuf to receive to */ + break; + } + + if (priv->q != NULL) { + /* 'chain' the pbuf to the existing chain */ + pbuf_cat(priv->q, priv->p); + } else { + /* p is the first pbuf in the chain */ + priv->q = priv->p; + } + } + + /* this automatically drops bytes if > SLIP_MAX_SIZE */ + if ((priv->p != NULL) && (priv->recved <= SLIP_MAX_SIZE)) { + ((u8_t *)priv->p->payload)[priv->i] = c; + priv->recved++; + priv->i++; + if (priv->i >= priv->p->len) { + /* on to the next pbuf */ + priv->i = 0; + if (priv->p->next != NULL && priv->p->next->len > 0) { + /* p is a chain, on to the next in the chain */ + priv->p = priv->p->next; + } else { + /* p is a single pbuf, set it to NULL so next time a new + * pbuf is allocated */ + priv->p = NULL; + } + } + } + } + + return NULL; +} + +#if !NO_SYS +/** + * The SLIP input thread. + * + * Feed the IP layer with incoming packets + * + * @param nf the lwip network interface structure for this slipif + */ +static void +slipif_loop_thread(void *nf) +{ + struct pbuf *p; + struct netif *netif = (struct netif *)nf; + + while (1) { + p = slipif_input(netif, SLIP_BLOCK); + if (p != NULL) { + if (netif->input(p, netif) != ERR_OK) { + pbuf_free(p); + p = NULL; + } + } + } +} +#endif /* !NO_SYS */ + +/** + * SLIP netif initialization + * + * Call the arch specific sio_open and remember + * the opened device in the state field of the netif. + * + * @param netif the lwip network interface structure for this slipif + * @return ERR_OK if serial line could be opened, + * ERR_MEM if no memory could be allocated, + * ERR_IF is serial line couldn't be opened + * + * @note netif->num must contain the number of the serial port to open + * (0 by default) + */ +err_t +slipif_init(struct netif *netif) +{ + struct slipif_priv *priv; + + LWIP_DEBUGF(SLIP_DEBUG, ("slipif_init: netif->num=%"U16_F"\n", (u16_t)netif->num)); + + /* Allocate private data */ + priv = mem_malloc(sizeof(struct slipif_priv)); + if (!priv) { + return ERR_MEM; + } + + netif->name[0] = 's'; + netif->name[1] = 'l'; + netif->output = slipif_output; + netif->mtu = SLIP_MAX_SIZE; + netif->flags |= NETIF_FLAG_POINTTOPOINT; + + /* Try to open the serial port (netif->num contains the port number). */ + priv->sd = sio_open(netif->num); + if (!priv->sd) { + /* Opening the serial port failed. */ + mem_free(priv); + return ERR_IF; + } + + /* Initialize private data */ + priv->p = NULL; + priv->q = NULL; + priv->state = SLIP_RECV_NORMAL; + priv->i = 0; + priv->recved = 0; + + netif->state = priv; + + /* initialize the snmp variables and counters inside the struct netif + * ifSpeed: no assumption can be made without knowing more about the + * serial line! + */ + NETIF_INIT_SNMP(netif, snmp_ifType_slip, 0); + + /* Create a thread to poll the serial line. */ + sys_thread_new(SLIPIF_THREAD_NAME, slipif_loop_thread, netif, + SLIPIF_THREAD_STACKSIZE, SLIPIF_THREAD_PRIO); + return ERR_OK; +} + +/** + * Polls the serial device and feeds the IP layer with incoming packets. + * + * @param netif The lwip network interface structure for this slipif + */ +void +slipif_poll(struct netif *netif) +{ + struct pbuf *p; + struct slipif_priv *priv; + + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + + priv = netif->state; + + while ((p = slipif_input(netif, SLIP_DONTBLOCK)) != NULL) { + if (netif->input(p, netif) != ERR_OK) { + pbuf_free(p); + } + } +} + +#endif /* LWIP_HAVE_SLIPIF */ diff --git a/component/common/network/lwip/lwip_v1.4.1/CHANGELOG b/component/common/network/lwip/lwip_v1.4.1/CHANGELOG new file mode 100644 index 0000000..af68299 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/CHANGELOG @@ -0,0 +1,3349 @@ +HISTORY + +(CVS HEAD) + + * [Enter new changes just after this line - do not remove this line] + + ++ New features: + + + ++ Bugfixes: + + + + +(STABLE-1.4.1) + + ++ New features: + + 2012-03-25: Simon Goldschmidt (idea by Mason) + * posix/*: added posix-compatibility include files posix/netdb.h and posix/sys/socket.h + which are a simple wrapper to the correct lwIP include files. + + 2012-01-16: Simon Goldschmidt + * opt.h, icmp.c: Added option CHECKSUM_GEN_ICMP + + 2011-12-17: Simon Goldschmidt + * ip.h: implemented API functions to access so_options of IP pcbs (UDP, TCP, RAW) + (fixes bug #35061) + + 2011-09-27: Simon Goldschmidt + * opt.h, tcp.c, tcp_in.c: Implemented limiting data on ooseq queue (task #9989) + (define TCP_OOSEQ_MAX_BYTES / TCP_OOSEQ_MAX_PBUFS in lwipopts.h) + + 2011-09-21: Simon Goldschmidt + * opt.h, api.h, api_lib.c, api_msg.h/.c, sockets.c: Implemented timeout on + send (TCP only, bug #33820) + + 2011-09-21: Simon Goldschmidt + * init.c: Converted runtime-sanity-checks into compile-time checks that can + be disabled (since runtime checks can often not be seen on embedded targets) + + 2011-09-11: Simon Goldschmidt + * ppp.h, ppp_impl.h: splitted ppp.h to an internal and external header file + to get a clear separation of which functions an application or port may use + (task #11281) + + 2011-09-11: Simon Goldschmidt + * opt.h, tcp_impl.h, tcp.c, udp.h/.c: Added a config option to randomize + initial local TCP/UDP ports (so that different port ranges are used after + a reboot; bug #33818; this one added tcp_init/udp_init functions again) + + 2011-09-03: Simon Goldschmidt + * dhcp.c: DHCP uses LWIP_RAND() for xid's (bug #30302) + + 2011-08-24: Simon Goldschmidt + * opt.h, netif.h/.c: added netif remove callback (bug #32397) + + 2011-07-26: Simon Goldschmidt + * etharp.c: ETHARP_SUPPORT_VLAN: add support for an external VLAN filter + function instead of only checking for one VLAN (define ETHARP_VLAN_CHECK_FN) + + 2011-07-21: Simon Goldschmidt (patch by hanhui) + * ip4.c, etharp.c, pbuf.h: bug #33634 ip_forward() have a faulty behaviour: + Added pbuf flags to mark incoming packets as link-layer broadcast/multicast. + Also added code to allow ip_forward() to forward non-broadcast packets to + the input netif (set IP_FORWARD_ALLOW_TX_ON_RX_NETIF==1). + + 2011-06-26: Simon Goldschmidt (patch by Cameron Gutman) + * tcp.c, tcp_out.c: bug #33604: added some more asserts to check that + pcb->state != LISTEN + + 2011-05-14: Simon Goldschmidt (patch by Stéphane Lesage) + * tcpip.c/.h: patch #7449 allow tcpip callback from interrupt with static + memory message + + + ++ Bugfixes: + + 2012-09-26: Simon Goldschmidt + * api_msg.c: fixed bug #37405 'err_tcp()' uses already freed 'netconn' object + + 2012-09-26: patch by Henrik Persson + * dhcp.c: patch #7843 Fix corner case with dhcp timeouts + + 2012-09-26: patch by Henrik Persson + * dhcp.c: patch #7840 Segfault in dhcp_parse_reply if no end marker in dhcp packet + + 2012-08-22: Simon Goldschmidt + * memp.c: fixed bug #37166: memp_sanity check loops itself + + 2012-05-08: Simon Goldschmidt + * tcp_out.c: fixed bug: #36380 unsent_oversize mismatch in 1.4.1RC1 (this was + a debug-check issue only) + + 2012-03-27: Simon Goldschmidt + * vj.c: fixed bug #35756 header length calculation problem in ppp/vj.c + + 2012-03-27: Simon Goldschmidt (patch by Mason) + * tcp_out.c: fixed bug #35945: SYN packet should provide the recv MSS not the + send MSS + + 2012-03-22: Simon Goldschmidt + * ip4.c: fixed bug #35927: missing refragmentaion in ip_forward + + 2012-03-20: Simon Goldschmidt (patch by Mason) + * netdb.c: fixed bug #35907: lwip_gethostbyname_r returns an invalid h_addr_list + + 2012-03-12: Simon Goldschmidt (patch by Bostjan Meglic) + * ppp.c: fixed bug #35809: PPP GetMask(): Compiler warning on big endian, + possible bug on little endian system + + 2012-02-23: Simon Goldschmidt + * etharp.c: fixed bug #35595: Impossible to send broadcast without a gateway + (introduced when fixing bug# 33551) + + 2012-02-16: Simon Goldschmidt + * ppp.c: fixed pbuf leak when PPP session is aborted through pppSigHUP() + (bug #35541: PPP Memory Leak) + + 2012-02-16: Simon Goldschmidt + * etharp.c: fixed bug #35531: Impossible to send multicast without a gateway + (introduced when fixing bug# 33551) + + 2012-02-16: Simon Goldschmidt (patch by Stéphane Lesage) + * msg_in.c, msg_out.c: fixed bug #35536 SNMP: error too big response is malformed + + 2012-02-15: Simon Goldschmidt + * init.c: fixed bug #35537: MEMP_NUM_* sanity checks should be disabled with + MEMP_MEM_MALLOC==1 + + 2012-02-12: Simon Goldschmidt + * tcp.h, tcp_in.c, tcp_out.c: partly fixed bug #25882: TCP hangs on + MSS > pcb->snd_wnd (by not creating segments bigger than half the window) + + 2012-02-11: Simon Goldschmidt + * tcp.c: fixed bug #35435: No pcb state check before adding it to time-wait + queue while closing + + 2012-01-22: Simon Goldschmidt + * tcp.c, tcp_in.c: fixed bug #35305: pcb may be freed too early on shutdown(WR) + + 2012-01-21: Simon Goldschmidt + * tcp.c: fixed bug #34636: FIN_WAIT_2 - Incorrect shutdown of TCP pcb + + 2012-01-20: Simon Goldschmidt + * dhcp.c: fixed bug #35151: DHCP asserts on incoming option lengths + + 2012-01-20: Simon Goldschmidt + * pbuf.c: fixed bug #35291: NULL pointer in pbuf_copy + + 2011-11-25: Simon Goldschmidt + * tcp.h/.c, tcp_impl.h, tcp_in.c: fixed bug #31177: tcp timers can corrupt + tcp_active_pcbs in some cases + + 2011-11-23: Simon Goldschmidt + * sys.c: fixed bug #34884: sys_msleep() body needs to be surrounded with + '#ifndef sys_msleep' + + 2011-11-22: Simon Goldschmidt + * netif.c, etharp.h/.c: fixed bug #34684: Clear the arp table cache when + netif is brought down + + 2011-10-28: Simon Goldschmidt + * tcp_in.c: fixed bug #34638: Dead code in tcp_receive - pcb->dupacks + + 2011-10-23: Simon Goldschmidt + * mem.c: fixed bug #34429: possible memory corruption with + LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT set to 1 + + 2011-10-18: Simon Goldschmidt + * arch.h, netdb.c: fixed bug #34592: lwip_gethostbyname_r uses nonstandard + error value + + 2011-10-18: Simon Goldschmidt + * opt.h: fixed default values of TCP_SNDLOWAT and TCP_SNDQUEUELOWAT for small + windows (bug #34176 select after non-blocking send times out) + + 2011-10-18: Simon Goldschmidt + * tcp_impl.h, tcp_out.c: fixed bug #34587: TCP_BUILD_MSS_OPTION doesn't + consider netif->mtu, causes slow network + + 2011-10-18: Simon Goldschmidt + * sockets.c: fixed bug #34581 missing parentheses in udplite sockets code + + 2011-10-18: Simon Goldschmidt + * sockets.h: fixed bug #34580 fcntl() is missing in LWIP_COMPAT_SOCKETS + + 2011-10-17: Simon Goldschmidt + * api_msg.c: fixed bug #34569: shutdown(SHUT_WR) crashes netconn/socket api + + 2011-10-13: Simon Goldschmidt + * tcp_in.c, tcp_out.c: fixed bug #34517 (persist timer is started although no + zero window is received) by starting the persist timer when a zero window is + received, not when we have more data queued for sending than fits into the + window + + 2011-10-13: Simon Goldschmidt + * def.h, timers.c: fixed bug #34541: LWIP_U32_DIFF is unnecessarily complex + + 2011-10-13: Simon Goldschmidt + * sockets.c, api_lib.c: fixed bug #34540: compiler error when CORE_LOCKING is + used and not all protocols are enabled + + 2011-10-12: Simon Goldschmidt + * pbuf.c: fixed bug #34534: Error in sending fragmented IP if MEM_ALIGNMENT > 4 + + 2011-10-09: Simon Goldschmidt + * tcp_out.c: fixed bug #34426: tcp_zero_window_probe() transmits incorrect + byte value when pcb->unacked != NULL + + 2011-10-09: Simon Goldschmidt + * ip4.c: fixed bug #34447 LWIP_IP_ACCEPT_UDP_PORT(dst_port) wrong + + 2011-09-27: Simon Goldschmidt + * tcp_in.c, tcp_out.c: Reset pcb->unsent_oversize in 2 more places... + + 2011-09-27: Simon Goldschmidt + * tcp_in.c: fixed bug #28288: Data after FIN in oos queue + + 2011-09-27: Simon Goldschmidt + * dhcp.c: fixed bug #34406 dhcp_option_hostname() can overflow the pbuf + + 2011-09-24: Simon Goldschmidt + * mem.h: fixed bug #34377 MEM_SIZE_F is not defined if MEM_LIBC_MALLOC==1 + + 2011-09-23: Simon Goldschmidt + * pbuf.h, tcp.c, tcp_in.c: fixed bug #33871: rejecting TCP_EVENT_RECV() for + the last packet including FIN can lose data + + 2011-09-22: Simon Goldschmidt + * tcp_impl.h: fixed bug #34355: nagle does not take snd_buf/snd_queuelen into + account + + 2011-09-21: Simon Goldschmidt + * opt.h: fixed default value of TCP_SND_BUF to not violate the sanity checks + in init.c + + 2011-09-20: Simon Goldschmidt + * timers.c: fixed bug #34337 (possible NULL pointer in sys_check_timeouts) + + 2011-09-11: Simon Goldschmidt + * tcp_out.c: use pcb->mss instead of TCP_MSS for preallocate mss-sized pbufs + (bug #34019) + + 2011-09-09: Simon Goldschmidt + * udp.c: fixed bug #34072: UDP broadcast is received from wrong UDP pcb if + udp port matches + + 2011-09-03: Simon Goldschmidt + * tcp_in.c: fixed bug #33952 PUSH flag in incoming packet is lost when packet + is aggregated and sent to application + + 2011-09-01: Simon Goldschmidt + * opt.h: fixed bug #31809 LWIP_EVENT_API in opts.h is inconsistent compared + to other options + + 2011-09-01: Simon Goldschmidt + * tcp_in.c: fixed bug #34111 RST for ACK to listening pcb has wrong seqno + + 2011-08-24: Simon Goldschmidt + * api_msg.c, sockets.c: fixed bug #33956 Wrong error returned when calling + accept() on UDP connections + + 2011-08-24: Simon Goldschmidt + * sockets.h: fixed bug #34057 socklen_t should be a typedef + + 2011-08-24: Simon Goldschmidt + * pbuf.c: fixed bug #34112 Odd check in pbuf_alloced_custom (typo) + + 2011-08-24: Simon Goldschmidt + * dhcp.c: fixed bug #34122 dhcp: hostname can overflow + + 2011-08-24: Simon Goldschmidt + * netif.c: fixed bug #34121 netif_add/netif_set_ipaddr fail on NULL ipaddr + + 2011-08-22: Simon Goldschmidt + * tcp_out.c: fixed bug #33962 TF_FIN not always set after FIN is sent. (This + merely prevents nagle from not transmitting fast after closing.) + + 2011-07-22: Simon Goldschmidt + * api_lib.c, api_msg.c, sockets.c, api.h: fixed bug #31084 (socket API returns + always EMSGSIZE on non-blocking sockets if data size > send buffers) -> now + lwip_send() sends as much as possible for non-blocking sockets + + 2011-07-22: Simon Goldschmidt + * pbuf.c/.h, timers.c: freeing ooseq pbufs when the pbuf pool is empty implemented + for NO_SYS==1: when not using sys_check_timeouts(), call PBUF_CHECK_FREE_OOSEQ() + at regular intervals from main level. + + 2011-07-21: Simon Goldschmidt + * etharp.c: fixed bug #33551 (ARP entries may time out although in use) by + sending an ARP request when an ARP entry is used in the last minute before + it would time out. + + 2011-07-04: Simon Goldschmidt + * sys_arch.txt: Fixed documentation after changing sys arch prototypes for 1.4.0. + + 2011-06-26: Simon Goldschmidt + * tcp.c: fixed bug #31723 (tcp_kill_prio() kills pcbs with the same prio) by + updating its documentation only. + + 2011-06-26: Simon Goldschmidt + * mem.c: fixed bug #33545: With MEM_USE_POOLS==1, mem_malloc can return an + unaligned pointer. + + 2011-06-26: Simon Goldschmidt + * mem.c: fixed bug #33544 "warning in mem.c in lwip 1.4.0 with NO_SYS=1" + + 2011-05-25: Simon Goldschmidt + * tcp.c: fixed bug #33398 (pointless conversion when checking TCP port range) + + + +(STABLE-1.4.0) + + ++ New features: + + 2011-03-27: Simon Goldschmidt + * tcp_impl.h, tcp_in.c, tcp_out.c: Removed 'dataptr' from 'struct tcp_seg' and + calculate it in tcp_zero_window_probe (the only place where it was used). + + 2010-11-21: Simon Goldschmidt + * dhcp.c/.h: Added a function to deallocate the struct dhcp from a netif + (fixes bug #31525). + + 2010-07-12: Simon Goldschmidt (patch by Stephane Lesage) + * ip.c, udp.c/.h, pbuf.h, sockets.c: task #10495: Added support for + IP_MULTICAST_LOOP at socket- and raw-API level. + + 2010-06-16: Simon Goldschmidt + * ip.c: Added an optional define (LWIP_IP_ACCEPT_UDP_PORT) that can allow + link-layer-addressed UDP traffic to be received while a netif is down (just + like DHCP during configuration) + + 2010-05-22: Simon Goldschmidt + * many many files: bug #27352: removed packing from ip_addr_t, the packed + version is now only used in protocol headers. Added global storage for + current src/dest IP address while in input functions. + + 2010-05-16: Simon Goldschmidt + * def.h: task #10391: Add preprocessor-macros for compile-time htonl + calculation (and use them throughout the stack where applicable) + + 2010-05-16: Simon Goldschmidt + * opt.h, memp_std.h, memp.c, ppp_oe.h/.c: PPPoE now uses its own MEMP pool + instead of the heap (moved struct pppoe_softc from ppp_oe.c to ppp_oe.h) + + 2010-05-16: Simon Goldschmidt + * opt.h, memp_std.h, dns.h/.c: DNS_LOCAL_HOSTLIST_IS_DYNAMIC uses its own + MEMP pool instead of the heap + + 2010-05-13: Simon Goldschmidt + * tcp.c, udp.c: task #6995: Implement SO_REUSEADDR (correctly), added + new option SO_REUSE_RXTOALL to pass received UDP broadcast/multicast + packets to more than one pcb. + + 2010-05-02: Simon Goldschmidt + * netbuf.h/.c, sockets.c, api_msg.c: use checksum-on-copy for sending + UDP data for LWIP_NETIF_TX_SINGLE_PBUF==1 + + 2010-04-30: Simon Goldschmidt + * udp.h/.c, pbuf.h/.c: task #6849: added udp_send(_to/_if) functions that + take a precalculated checksum, added pbuf_fill_chksum() to copy data + into a pbuf and at the same time calculating the checksum for that data + + 2010-04-29: Simon Goldschmidt + * ip_addr.h, etharp.h/.c, autoip.c: Create overridable macros for copying + 2-byte-aligned IP addresses and MAC addresses + + 2010-04-28: Patch by Bill Auerbach + * ip.c: Inline generating IP checksum to save a function call + + 2010-04-14: Simon Goldschmidt + * tcpip.h/.c, timers.c: Added an overridable define to get informed when the + tcpip_thread processes messages or timeouts to implement a watchdog. + + 2010-03-28: Simon Goldschmidt + * ip_frag.c: create a new (contiguous) PBUF_RAM for every outgoing + fragment if LWIP_NETIF_TX_SINGLE_PBUF==1 + + 2010-03-27: Simon Goldschmidt + * etharp.c: Speedup TX by moving code from find_entry to etharp_output/ + etharp_query to prevent unnecessary function calls (inspired by + patch #7135). + + 2010-03-20: Simon Goldschmidt + * opt.h, tcpip.c/.h: Added an option to disable tcpip_(un)timeout code + since the linker cannot do this automatically to save space. + + 2010-03-20: Simon Goldschmidt + * opt.h, etharp.c/.h: Added support for static ARP table entries + + 2010-03-14: Simon Goldschmidt + * tcp_impl.h, tcp_out.c, inet_chksum.h/.c: task #6849: Calculate checksum + when creating TCP segments, not when (re-)transmitting them. + + 2010-03-07: Simon Goldschmidt + * sockets.c: bug #28775 (select/event_callback: only check select_cb_list + on change) plus use SYS_LIGHTWEIGHT_PROT to protect the select code. + This should speed up receiving data on sockets as the select code in + event_callback is only executed when select is waiting. + + 2010-03-06: Simon Goldschmidt + * tcp_out.c: task #7013 (Create option to have all packets delivered to + netif->output in one piece): Always copy to try to create single pbufs + in tcp_write. + + 2010-03-06: Simon Goldschmidt + * api.h, api_lib.c, sockets.c: task #10167 (sockets: speed up TCP recv + by not allocating a netbuf): added function netconn_recv_tcp_pbuf() + for tcp netconns to receive pbufs, not netbufs; use that function + for tcp sockets. + + 2010-03-05: Jakob Ole Stoklundsen / Simon Goldschmidt + * opt.h, tcp.h, tcp_impl.h, tcp.c, tcp_in.c, tcp_out.c: task #7040: + Work on tcp_enqueue: Don't waste memory when chaining segments, + added option TCP_OVERSIZE to prevent creating many small pbufs when + calling tcp_write with many small blocks of data. Instead, pbufs are + allocated larger than needed and the space is used for later calls to + tcp_write. + + 2010-02-21: Simon Goldschmidt + * stats.c/.h: Added const char* name to mem- and memp-stats for easier + debugging. + + 2010-02-21: Simon Goldschmidt + * tcp.h (and usages), added tcp_impl.h: Splitted API and internal + implementation of tcp to make API usage cleare to application programmers + + 2010-02-14: Simon Goldschmidt/Stephane Lesage + * ip_addr.h: Improved some defines working on ip addresses, added faster + macro to copy addresses that cannot be NULL + + 2010-02-13: Simon Goldschmidt + * api.h, api_lib.c, api_msg.c, sockets.c: task #7865 (implement non- + blocking send operation) + + 2010-02-12: Simon Goldschmidt + * sockets.c/.h: Added a minimal version of posix fctl() to have a + standardised way to set O_NONBLOCK for nonblocking sockets. + + 2010-02-12: Simon Goldschmidt + * dhcp.c/.h, autoip.c/.h: task #10139 (Prefer statically allocated + memory): added autoip_set_struct() and dhcp_set_struct() to let autoip + and dhcp work with user-allocated structs instead of callin mem_malloc + + 2010-02-12: Simon Goldschmidt/Jeff Barber + * tcp.c/h: patch #6865 (SO_REUSEADDR for TCP): if pcb.so_options has + SOF_REUSEADDR set, allow binding to endpoint in TIME_WAIT + + 2010-02-12: Simon Goldschmidt + * sys layer: task #10139 (Prefer statically allocated memory): converted + mbox and semaphore functions to take pointers to sys_mbox_t/sys_sem_t; + converted sys_mbox_new/sys_sem_new to take pointers and return err_t; + task #7212: Add Mutex concept in sys_arch (define LWIP_COMPAT_MUTEX + to let sys.h use binary semaphores instead of mutexes - as before) + + 2010-02-09: Simon Goldschmidt (Simon Kallweit) + * timers.c/.h: Added function sys_restart_timeouts() from patch #7085 + (Restart system timeout handling) + + 2010-02-09: Simon Goldschmidt + * netif.c/.h, removed loopif.c/.h: task #10153 (Integrate loopif into + netif.c) - loopif does not have to be created by the port any more, + just define LWIP_HAVE_LOOPIF to 1. + + 2010-02-08: Simon Goldschmidt + * inet.h, ip_addr.c/.h: Added reentrant versions of inet_ntoa/ipaddr_ntoa + inet_ntoa_r/ipaddr_ntoa_r + + 2010-02-08: Simon Goldschmidt + * netif.h: Added netif_s/get_igmp_mac_filter() macros + + 2010-02-05: Simon Goldschmidt + * netif.h: Added function-like macros to get/set the hostname on a netif + + 2010-02-04: Simon Goldschmidt + * nearly every file: Replaced struct ip_addr by typedef ip_addr_t to + make changing the actual implementation behind the typedef easier. + + 2010-02-01: Simon Goldschmidt + * opt.h, memp_std.h, dns.h, netdb.c, memp.c: Let netdb use a memp pool + for allocating memory when getaddrinfo() is called. + + 2010-01-31: Simon Goldschmidt + * dhcp.h, dhcp.c: Reworked the code that parses DHCP options: parse + them once instead of parsing for every option. This also removes + the need for mem_malloc from dhcp_recv and makes it possible to + correctly retrieve the BOOTP file. + + 2010-01-30: simon Goldschmidt + * sockets.c: Use SYS_LIGHTWEIGHT_PROT instead of a semaphore to protect + the sockets array. + + 2010-01-29: Simon Goldschmidt (patch by Laura Garrett) + * api.h, api_msg.c, sockets.c: Added except set support in select + (patch #6860) + + 2010-01-29: Simon Goldschmidt (patch by Laura Garrett) + * api.h, sockets.h, err.h, api_lib.c, api_msg.c, sockets.c, err.c: + Add non-blocking support for connect (partly from patch #6860), + plus many cleanups in socket & netconn API. + + 2010-01-27: Simon Goldschmidt + * opt.h, tcp.h, init.c, api_msg.c: Added TCP_SNDQUEUELOWAT corresponding + to TCP_SNDLOWAT and added tcp_sndqueuelen() - this fixes bug #28605 + + 2010-01-26: Simon Goldschmidt + * snmp: Use memp pools for snmp instead of the heap; added 4 new pools. + + 2010-01-14: Simon Goldschmidt + * ppp.c/.h: Fixed bug #27856: PPP: Set netif link- and status-callback + by adding ppp_set_netif_statuscallback()/ppp_set_netif_linkcallback() + + 2010-01-13: Simon Goldschmidt + * mem.c: The heap now may be moved to user-defined memory by defining + LWIP_RAM_HEAP_POINTER as a void pointer to that memory's address + (patch #6966 and bug #26133) + + 2010-01-10: Simon Goldschmidt (Bill Auerbach) + * opt.h, memp.c: patch #6822 (Add option to place memory pools in + separate arrays) + + 2010-01-10: Simon Goldschmidt + * init.c, igmp.c: patch #6463 (IGMP - Adding Random Delay): added define + LWIP_RAND() for lwip-wide randomization (to be defined in cc.h) + + 2009-12-31: Simon Goldschmidt + * tcpip.c, init.c, memp.c, sys.c, memp_std.h, sys.h, tcpip.h + added timers.c/.h: Separated timer implementation from semaphore/mbox + implementation, moved timer implementation to timers.c/.h, timers are + now only called from tcpip_thread or by explicitly checking them. + (TASK#7235) + + 2009-12-27: Simon Goldschmidt + * opt.h, etharp.h/.c, init.c, tcpip.c: Added an additional option + LWIP_ETHERNET to support ethernet without ARP (necessary for pure PPPoE) + + + ++ Bugfixes: + + 2011-04-20: Simon Goldschmidt + * sys_arch.txt: sys_arch_timeouts() is not needed any more. + + 2011-04-13: Simon Goldschmidt + * tcp.c, udp.c: Fixed bug #33048 (Bad range for IP source port numbers) by + using ports in the IANA private/dynamic range (49152 through 65535). + + 2011-03-29: Simon Goldschmidt, patch by Emil Lhungdahl: + * etharp.h/.c: Fixed broken VLAN support. + + 2011-03-27: Simon Goldschmidt + * tcp.c: Fixed bug #32926 (TCP_RMV(&tcp_bound_pcbs) is called on unbound tcp + pcbs) by checking if the pcb was bound (local_port != 0). + + 2011-03-27: Simon Goldschmidt + * ppp.c: Fixed bug #32280 (ppp: a pbuf is freed twice) + + 2011-03-27: Simon Goldschmidt + * sockets.c: Fixed bug #32906: lwip_connect+lwip_send did not work for udp and + raw pcbs with LWIP_TCPIP_CORE_LOCKING==1. + + 2011-03-27: Simon Goldschmidt + * tcp_out.c: Fixed bug #32820 (Outgoing TCP connections created before route + is present never times out) by starting retransmission timer before checking + route. + + 2011-03-22: Simon Goldschmidt + * ppp.c: Fixed bug #32648 (PPP code crashes when terminating a link) by only + calling sio_read_abort() if the file descriptor is valid. + + 2011-03-14: Simon Goldschmidt + * err.h/.c, sockets.c, api_msg.c: fixed bug #31748 (Calling non-blocking connect + more than once can render a socket useless) since it mainly involves changing + "FATAL" classification of error codes: ERR_USE and ERR_ISCONN just aren't fatal. + + 2011-03-13: Simon Goldschmidt + * sockets.c: fixed bug #32769 (ESHUTDOWN is linux-specific) by fixing + err_to_errno_table (ERR_CLSD: ENOTCONN instead of ESHUTDOWN), ERR_ISCONN: + use EALRADY instead of -1 + + 2011-03-13: Simon Goldschmidt + * api_lib.c: netconn_accept: return ERR_ABRT instead of ERR_CLSD if the + connection has been aborted by err_tcp (since this is not a normal closing + procedure). + + 2011-03-13: Simon Goldschmidt + * tcp.c: tcp_bind: return ERR_VAL instead of ERR_ISCONN when trying to bind + with pcb->state != CLOSED + + 2011-02-17: Simon Goldschmidt + * rawapi.txt: Fixed bug #32561 tcp_poll argument definition out-of-order in + documentation + + 2011-02-17: Simon Goldschmidt + * many files: Added missing U/UL modifiers to fix 16-bit-arch portability. + + 2011-01-24: Simon Goldschmidt + * sockets.c: Fixed bug #31741: lwip_select seems to have threading problems + + 2010-12-02: Simon Goldschmidt + * err.h: Fixed ERR_IS_FATAL so that ERR_WOULDBLOCK is not fatal. + + 2010-11-23: Simon Goldschmidt + * api.h, api_lib.c, api_msg.c, sockets.c: netconn.recv_avail is only used for + LWIP_SO_RCVBUF and ioctl/FIONREAD. + + 2010-11-23: Simon Goldschmidt + * etharp.c: Fixed bug #31720: ARP-queueing: RFC 1122 recommends to queue at + least 1 packet -> ARP_QUEUEING==0 now queues the most recent packet. + + 2010-11-23: Simon Goldschmidt + * tcp_in.c: Fixed bug #30577: tcp_input: don't discard ACK-only packets after + refusing 'refused_data' again. + + 2010-11-22: Simon Goldschmidt + * sockets.c: Fixed bug #31590: getsockopt(... SO_ERROR ...) gives EINPROGRESS + after a successful nonblocking connection. + + 2010-11-22: Simon Goldschmidt + * etharp.c: Fixed bug #31722: IP packets sent with an AutoIP source addr + must be sent link-local + + 2010-11-22: Simon Goldschmidt + * timers.c: patch #7329: tcp_timer_needed prototype was ifdef'ed out for + LWIP_TIMERS==0 + + 2010-11-20: Simon Goldschmidt + * sockets.c: Fixed bug #31170: lwip_setsockopt() does not set socket number + + 2010-11-20: Simon Goldschmidt + * sockets.h: Fixed bug #31304: Changed SHUT_RD, SHUT_WR and SHUT_RDWR to + resemble other stacks. + + 2010-11-20: Simon Goldschmidt + * dns.c: Fixed bug #31535: TCP_SND_QUEUELEN must be at least 2 or else + no-copy TCP writes will never succeed. + + 2010-11-20: Simon Goldschmidt + * dns.c: Fixed bug #31701: Error return value from dns_gethostbyname() does + not match documentation: return ERR_ARG instead of ERR_VAL if not + initialized or wrong argument. + + 2010-10-20: Simon Goldschmidt + * sockets.h: Fixed bug #31385: sizeof(struct sockaddr) is 30 but should be 16 + + 2010-10-05: Simon Goldschmidt + * dhcp.c: Once again fixed #30038: DHCP/AutoIP cooperation failed when + replugging the network cable after an AutoIP address was assigned. + + 2010-08-10: Simon Goldschmidt + * tcp.c: Fixed bug #30728: tcp_new_port() did not check listen pcbs + + 2010-08-03: Simon Goldschmidt + * udp.c, raw.c: Don't chain empty pbufs when sending them (fixes bug #30625) + + 2010-08-01: Simon Goldschmidt (patch by Greg Renda) + * ppp.c: Applied patch #7264 (PPP protocols are rejected incorrectly on big + endian architectures) + + 2010-07-28: Simon Goldschmidt + * api_lib.c, api_msg.c, sockets.c, mib2.c: Fixed compilation with TCP or UDP + disabled. + + 2010-07-27: Simon Goldschmidt + * tcp.c: Fixed bug #30565 (tcp_connect() check bound list): that check did no + harm but never did anything + + 2010-07-21: Simon Goldschmidt + * ip.c: Fixed invalid fix for bug #30402 (CHECKSUM_GEN_IP_INLINE does not + add IP options) + + 2010-07-16: Kieran Mansley + * msg_in.c: Fixed SNMP ASN constant defines to not use ! operator + + 2010-07-10: Simon Goldschmidt + * ip.c: Fixed bug #30402: CHECKSUM_GEN_IP_INLINE does not add IP options + + 2010-06-30: Simon Goldschmidt + * api_msg.c: fixed bug #30300 (shutdown parameter was not initialized in + netconn_delete) + + 2010-06-28: Kieran Mansley + * timers.c remove unportable printing of C function pointers + + 2010-06-24: Simon Goldschmidt + * init.c, timers.c/.h, opt.h, memp_std.h: From patch #7221: added flag + NO_SYS_NO_TIMERS to drop timer support for NO_SYS==1 for easier upgrading + + 2010-06-24: Simon Goldschmidt + * api(_lib).c/.h, api_msg.c/.h, sockets.c/.h: Fixed bug #10088: Correctly + implemented shutdown at socket level. + + 2010-06-21: Simon Goldschmidt + * pbuf.c/.h, ip_frag.c/.h, opt.h, memp_std.h: Fixed bug #29361 (ip_frag has + problems with zero-copy DMA MACs) by adding custom pbufs and implementing + custom pbufs that reference other (original) pbufs. Additionally set + IP_FRAG_USES_STATIC_BUF=0 as default to be on the safe side. + + 2010-06-15: Simon Goldschmidt + * dhcp.c: Fixed bug #29970: DHCP endian issue parsing option responses + + 2010-06-14: Simon Goldschmidt + * autoip.c: Fixed bug #30039: AutoIP does not reuse previous addresses + + 2010-06-12: Simon Goldschmidt + * dhcp.c: Fixed bug #30038: dhcp_network_changed doesn't reset AUTOIP coop + state + + 2010-05-17: Simon Goldschmidt + * netdb.c: Correctly NULL-terminate h_addr_list + + 2010-05-16: Simon Goldschmidt + * def.h/.c: changed the semantics of LWIP_PREFIX_BYTEORDER_FUNCS to prevent + "symbol already defined" i.e. when linking to winsock + + 2010-05-05: Simon Goldschmidt + * def.h, timers.c: Fixed bug #29769 (sys_check_timeouts: sys_now() may + overflow) + + 2010-04-21: Simon Goldschmidt + * api_msg.c: Fixed bug #29617 (sometime cause stall on delete listening + connection) + + 2010-03-28: Luca Ceresoli + * ip_addr.c/.h: patch #7143: Add a few missing const qualifiers + + 2010-03-27: Luca Ceresoli + * mib2.c: patch #7130: remove meaningless const qualifiers + + 2010-03-26: Simon Goldschmidt + * tcp_out.c: Make LWIP_NETIF_TX_SINGLE_PBUF work for TCP, too + + 2010-03-26: Simon Goldschmidt + * various files: Fixed compiling with different options disabled (TCP/UDP), + triggered by bug #29345; don't allocate acceptmbox if LWIP_TCP is disabled + + 2010-03-25: Simon Goldschmidt + * sockets.c: Fixed bug #29332: lwip_select() processes readset incorrectly + + 2010-03-25: Simon Goldschmidt + * tcp_in.c, test_tcp_oos.c: Fixed bug #29080: Correctly handle remote side + overrunning our rcv_wnd in ooseq case. + + 2010-03-22: Simon Goldschmidt + * tcp.c: tcp_listen() did not copy the pcb's prio. + + 2010-03-19: Simon Goldschmidt + * snmp_msg.c: Fixed bug #29256: SNMP Trap address was not correctly set + + 2010-03-14: Simon Goldschmidt + * opt.h, etharp.h: Fixed bug #29148 (Incorrect PBUF_POOL_BUFSIZE for ports + where ETH_PAD_SIZE > 0) by moving definition of ETH_PAD_SIZE to opt.h + and basing PBUF_LINK_HLEN on it. + + 2010-03-08: Simon Goldschmidt + * netif.c, ipv4/ip.c: task #10241 (AutoIP: don't break existing connections + when assiging routable address): when checking incoming packets and + aborting existing connection on address change, filter out link-local + addresses. + + 2010-03-06: Simon Goldschmidt + * sockets.c: Fixed LWIP_NETIF_TX_SINGLE_PBUF for LWIP_TCPIP_CORE_LOCKING + + 2010-03-06: Simon Goldschmidt + * ipv4/ip.c: Don't try to forward link-local addresses + + 2010-03-06: Simon Goldschmidt + * etharp.c: Fixed bug #29087: etharp: don't send packets for LinkLocal- + addresses to gw + + 2010-03-05: Simon Goldschmidt + * dhcp.c: Fixed bug #29072: Correctly set ciaddr based on message-type + and state. + + 2010-03-05: Simon Goldschmidt + * api_msg.c: Correctly set TCP_WRITE_FLAG_MORE when netconn_write is split + into multiple calls to tcp_write. + + 2010-02-21: Simon Goldschmidt + * opt.h, mem.h, dns.c: task #10140: Remove DNS_USES_STATIC_BUF (keep + the implementation of DNS_USES_STATIC_BUF==1) + + 2010-02-20: Simon Goldschmidt + * tcp.h, tcp.c, tcp_in.c, tcp_out.c: Task #10088: Correctly implement + close() vs. shutdown(). Now the application does not get any more + recv callbacks after calling tcp_close(). Added tcp_shutdown(). + + 2010-02-19: Simon Goldschmidt + * mem.c/.h, pbuf.c: Renamed mem_realloc() to mem_trim() to prevent + confusion with realloc() + + 2010-02-15: Simon Goldschmidt/Stephane Lesage + * netif.c/.h: Link status does not depend on LWIP_NETIF_LINK_CALLBACK + (fixes bug #28899) + + 2010-02-14: Simon Goldschmidt + * netif.c: Fixed bug #28877 (Duplicate ARP gratuitous packet with + LWIP_NETIF_LINK_CALLBACK set on) by only sending if both link- and + admin-status of a netif are up + + 2010-02-14: Simon Goldschmidt + * opt.h: Disable ETHARP_TRUST_IP_MAC by default since it slows down packet + reception and is not really necessary + + 2010-02-14: Simon Goldschmidt + * etharp.c/.h: Fixed ARP input processing: only add a new entry if a + request was directed as us (RFC 826, Packet Reception), otherwise + only update existing entries; internalized some functions + + 2010-02-14: Simon Goldschmidt + * netif.h, etharp.c, tcpip.c: Fixed bug #28183 (ARP and TCP/IP cannot be + disabled on netif used for PPPoE) by adding a new netif flag + (NETIF_FLAG_ETHERNET) that tells the stack the device is an ethernet + device but prevents usage of ARP (so that ethernet_input can be used + for PPPoE). + + 2010-02-12: Simon Goldschmidt + * netif.c: netif_set_link_up/down: only do something if the link state + actually changes + + 2010-02-12: Simon Goldschmidt/Stephane Lesage + * api_msg.c: Fixed bug #28865 (Cannot close socket/netconn in non-blocking + connect) + + 2010-02-12: Simon Goldschmidt + * mem.h: Fixed bug #28866 (mem_realloc function defined in mem.h) + + 2010-02-09: Simon Goldschmidt + * api_lib.c, api_msg.c, sockets.c, api.h, api_msg.h: Fixed bug #22110 + (recv() makes receive window update for data that wasn't received by + application) + + 2010-02-09: Simon Goldschmidt/Stephane Lesage + * sockets.c: Fixed bug #28853 (lwip_recvfrom() returns 0 on receive time-out + or any netconn_recv() error) + + 2010-02-09: Simon Goldschmidt + * ppp.c: task #10154 (PPP: Update snmp in/out counters for tx/rx packets) + + 2010-02-09: Simon Goldschmidt + * netif.c: For loopback packets, adjust the stats- and snmp-counters + for the loopback netif. + + 2010-02-08: Simon Goldschmidt + * igmp.c/.h, ip.h: Moved most defines from igmp.h to igmp.c for clarity + since they are not used anywhere else. + + 2010-02-08: Simon Goldschmidt (Stéphane Lesage) + * igmp.c, igmp.h, stats.c, stats.h: Improved IGMP stats + (patch from bug #28798) + + 2010-02-08: Simon Goldschmidt (Stéphane Lesage) + * igmp.c: Fixed bug #28798 (Error in "Max Response Time" processing) and + another bug when LWIP_RAND() returns zero. + + 2010-02-04: Simon Goldschmidt + * nearly every file: Use macros defined in ip_addr.h (some of them new) + to work with IP addresses (preparation for bug #27352 - Change ip_addr + from struct to typedef (u32_t) - and better code). + + 2010-01-31: Simon Goldschmidt + * netif.c: Don't call the link-callback from netif_set_up/down() since + this invalidly retriggers DHCP. + + 2010-01-29: Simon Goldschmidt + * ip_addr.h, inet.h, def.h, inet.c, def.c, more: Cleanly separate the + portability file inet.h and its contents from the stack: moved htonX- + functions to def.h (and the new def.c - they are not ipv4 dependent), + let inet.h depend on ip_addr.h and not the other way round. + This fixes bug #28732. + + 2010-01-28: Kieran Mansley + * tcp.c: Ensure ssthresh >= 2*MSS + + 2010-01-27: Simon Goldschmidt + * tcp.h, tcp.c, tcp_in.c: Fixed bug #27871: Calling tcp_abort() in recv + callback can lead to accessing unallocated memory. As a consequence, + ERR_ABRT means the application has called tcp_abort()! + + 2010-01-25: Simon Goldschmidt + * snmp_structs.h, msg_in.c: Partly fixed bug #22070 (MIB_OBJECT_WRITE_ONLY + not implemented in SNMP): write-only or not-accessible are still + returned by getnext (though not by get) + + 2010-01-24: Simon Goldschmidt + * snmp: Renamed the private mib node from 'private' to 'mib_private' to + not use reserved C/C++ keywords + + 2010-01-23: Simon Goldschmidt + * sockets.c: Fixed bug #28716: select() returns 0 after waiting for less + than 1 ms + + 2010-01-21: Simon Goldschmidt + * tcp.c, api_msg.c: Fixed bug #28651 (tcp_connect: no callbacks called + if tcp_enqueue fails) both in raw- and netconn-API + + 2010-01-19: Simon Goldschmidt + * api_msg.c: Fixed bug #27316: netconn: Possible deadlock in err_tcp + + 2010-01-18: Iordan Neshev/Simon Goldschmidt + * src/netif/ppp: reorganised PPP sourcecode to 2.3.11 including some + bugfix backports from 2.4.x. + + 2010-01-18: Simon Goldschmidt + * mem.c: Fixed bug #28679: mem_realloc calculates mem_stats wrong + + 2010-01-17: Simon Goldschmidt + * api_lib.c, api_msg.c, (api_msg.h, api.h, sockets.c, tcpip.c): + task #10102: "netconn: clean up conn->err threading issues" by adding + error return value to struct api_msg_msg + + 2010-01-17: Simon Goldschmidt + * api.h, api_lib.c, sockets.c: Changed netconn_recv() and netconn_accept() + to return err_t (bugs #27709 and #28087) + + 2010-01-14: Simon Goldschmidt + * ...: Use typedef for function prototypes throughout the stack. + + 2010-01-13: Simon Goldschmidt + * api_msg.h/.c, api_lib.c: Fixed bug #26672 (close connection when receive + window = 0) by correctly draining recvmbox/acceptmbox + + 2010-01-11: Simon Goldschmidt + * pap.c: Fixed bug #13315 (PPP PAP authentication can result in + erroneous callbacks) by copying the code from recent pppd + + 2010-01-10: Simon Goldschmidt + * raw.c: Fixed bug #28506 (raw_bind should filter received packets) + + 2010-01-10: Simon Goldschmidt + * tcp.h/.c: bug #28127 (remove call to tcp_output() from tcp_ack(_now)()) + + 2010-01-08: Simon Goldschmidt + * sockets.c: Fixed bug #28519 (lwip_recvfrom bug with len > 65535) + + 2010-01-08: Simon Goldschmidt + * dns.c: Copy hostname for DNS_LOCAL_HOSTLIST_IS_DYNAMIC==1 since string + passed to dns_local_addhost() might be volatile + + 2010-01-07: Simon Goldschmidt + * timers.c, tcp.h: Call tcp_timer_needed() with NO_SYS==1, too + + 2010-01-06: Simon Goldschmidt + * netdb.h: Fixed bug #28496: missing include guards in netdb.h + + 2009-12-31: Simon Goldschmidt + * many ppp files: Reorganised PPP source code from ucip structure to pppd + structure to easily compare our code against the pppd code (around v2.3.1) + + 2009-12-27: Simon Goldschmidt + * tcp_in.c: Another fix for bug #28241 (ooseq processing) and adapted + unit test + + +(STABLE-1.3.2) + + ++ New features: + + 2009-10-27 Simon Goldschmidt/Stephan Lesage + * netifapi.c/.h: Added netifapi_netif_set_addr() + + 2009-10-07 Simon Goldschmidt/Fabian Koch + * api_msg.c, netbuf.c/.h, opt.h: patch #6888: Patch for UDP Netbufs to + support dest-addr and dest-port (optional: LWIP_NETBUF_RECVINFO) + + 2009-08-26 Simon Goldschmidt/Simon Kallweit + * slipif.c/.h: bug #26397: SLIP polling support + + 2009-08-25 Simon Goldschmidt + * opt.h, etharp.h/.c: task #9033: Support IEEE 802.1q tagged frame (VLAN), + New configuration options ETHARP_SUPPORT_VLAN and ETHARP_VLAN_CHECK. + + 2009-08-25 Simon Goldschmidt + * ip_addr.h, netdb.c: patch #6900: added define ip_ntoa(struct ip_addr*) + + 2009-08-24 Jakob Stoklund Olesen + * autoip.c, dhcp.c, netif.c: patch #6725: Teach AutoIP and DHCP to respond + to netif_set_link_up(). + + 2009-08-23 Simon Goldschmidt + * tcp.h/.c: Added function tcp_debug_state_str() to convert a tcp state + to a human-readable string. + + ++ Bugfixes: + + 2009-12-24: Kieran Mansley + * tcp_in.c Apply patches from Oleg Tyshev to improve OOS processing + (BUG#28241) + + 2009-12-06: Simon Goldschmidt + * ppp.h/.c: Fixed bug #27079 (Yet another leak in PPP): outpacket_buf can + be statically allocated (like in ucip) + + 2009-12-04: Simon Goldschmidt (patch by Ioardan Neshev) + * pap.c: patch #6969: PPP: missing PAP authentication UNTIMEOUT + + 2009-12-03: Simon Goldschmidt + * tcp.h, tcp_in.c, tcp_out.c: Fixed bug #28106: dup ack for fast retransmit + could have non-zero length + + 2009-12-02: Simon Goldschmidt + * tcp_in.c: Fixed bug #27904: TCP sends too many ACKs: delay resetting + tcp_input_pcb until after calling the pcb's callbacks + + 2009-11-29: Simon Goldschmidt + * tcp_in.c: Fixed bug #28054: Two segments with FIN flag on the out-of- + sequence queue, also fixed PBUF_POOL leak in the out-of-sequence code + + 2009-11-29: Simon Goldschmidt + * pbuf.c: Fixed bug #28064: pbuf_alloc(PBUF_POOL) is not thread-safe by + queueing a call into tcpip_thread to free ooseq-bufs if the pool is empty + + 2009-11-26: Simon Goldschmidt + * tcp.h: Fixed bug #28098: Nagle can prevent fast retransmit from sending + segment + + 2009-11-26: Simon Goldschmidt + * tcp.h, sockets.c: Fixed bug #28099: API required to disable Nagle + algorithm at PCB level + + 2009-11-22: Simon Goldschmidt + * tcp_out.c: Fixed bug #27905: FIN isn't combined with data on unsent + + 2009-11-22: Simon Goldschmidt (suggested by Bill Auerbach) + * tcp.c: tcp_alloc: prevent increasing stats.err for MEMP_TCP_PCB when + reusing time-wait pcb + + 2009-11-20: Simon Goldschmidt (patch by Albert Bartel) + * sockets.c: Fixed bug #28062: Data received directly after accepting + does not wake up select + + 2009-11-11: Simon Goldschmidt + * netdb.h: Fixed bug #27994: incorrect define for freeaddrinfo(addrinfo) + + 2009-10-30: Simon Goldschmidt + * opt.h: Increased default value for TCP_MSS to 536, updated default + value for TCP_WND to 4*TCP_MSS to keep delayed ACK working. + + 2009-10-28: Kieran Mansley + * tcp_in.c, tcp_out.c, tcp.h: re-work the fast retransmission code + to follow algorithm from TCP/IP Illustrated + + 2009-10-27: Kieran Mansley + * tcp_in.c: fix BUG#27445: grow cwnd with every duplicate ACK + + 2009-10-25: Simon Goldschmidt + * tcp.h: bug-fix in the TCP_EVENT_RECV macro (has to call tcp_recved if + pcb->recv is NULL to keep rcv_wnd correct) + + 2009-10-25: Simon Goldschmidt + * tcp_in.c: Fixed bug #26251: RST process in TIME_WAIT TCP state + + 2009-10-23: Simon Goldschmidt (David Empson) + * tcp.c: Fixed bug #27783: Silly window avoidance for small window sizes + + 2009-10-21: Simon Goldschmidt + * tcp_in.c: Fixed bug #27215: TCP sent() callback gives leading and + trailing 1 byte len (SYN/FIN) + + 2009-10-21: Simon Goldschmidt + * tcp_out.c: Fixed bug #27315: zero window probe and FIN + + 2009-10-19: Simon Goldschmidt + * dhcp.c/.h: Minor code simplification (don't store received pbuf, change + conditional code to assert where applicable), check pbuf length before + testing for valid reply + + 2009-10-19: Simon Goldschmidt + * dhcp.c: Removed most calls to udp_connect since they aren't necessary + when using udp_sendto_if() - always stay connected to IP_ADDR_ANY. + + 2009-10-16: Simon Goldschmidt + * ip.c: Fixed bug #27390: Source IP check in ip_input() causes it to drop + valid DHCP packets -> allow 0.0.0.0 as source address when LWIP_DHCP is + enabled + + 2009-10-15: Simon Goldschmidt (Oleg Tyshev) + * tcp_in.c: Fixed bug #27329: dupacks by unidirectional data transmit + + 2009-10-15: Simon Goldschmidt + * api_lib.c: Fixed bug #27709: conn->err race condition on netconn_recv() + timeout + + 2009-10-15: Simon Goldschmidt + * autoip.c: Fixed bug #27704: autoip starts with wrong address + LWIP_AUTOIP_CREATE_SEED_ADDR() returned address in host byte order instead + of network byte order + + 2009-10-11 Simon Goldschmidt (Jörg Kesten) + * tcp_out.c: Fixed bug #27504: tcp_enqueue wrongly concatenates segments + which are not consecutive when retransmitting unacked segments + + 2009-10-09 Simon Goldschmidt + * opt.h: Fixed default values of some stats to only be enabled if used + Fixes bug #27338: sys_stats is defined when NO_SYS = 1 + + 2009-08-30 Simon Goldschmidt + * ip.c: Fixed bug bug #27345: "ip_frag() does not use the LWIP_NETIF_LOOPBACK + function" by checking for loopback before calling ip_frag + + 2009-08-25 Simon Goldschmidt + * dhcp.c: fixed invalid dependency to etharp_query if DHCP_DOES_ARP_CHECK==0 + + 2009-08-23 Simon Goldschmidt + * ppp.c: bug #27078: Possible memory leak in pppInit() + + 2009-08-23 Simon Goldschmidt + * netdb.c, dns.c: bug #26657: DNS, if host name is "localhost", result + is error. + + 2009-08-23 Simon Goldschmidt + * opt.h, init.c: bug #26649: TCP fails when TCP_MSS > TCP_SND_BUF + Fixed wrong parenthesis, added check in init.c + + 2009-08-23 Simon Goldschmidt + * ppp.c: bug #27266: wait-state debug message in pppMain occurs every ms + + 2009-08-23 Simon Goldschmidt + * many ppp files: bug #27267: Added include to string.h where needed + + 2009-08-23 Simon Goldschmidt + * tcp.h: patch #6843: tcp.h macro optimization patch (for little endian) + + +(STABLE-1.3.1) + + ++ New features: + + 2009-05-10 Simon Goldschmidt + * opt.h, sockets.c, pbuf.c, netbuf.h, pbuf.h: task #7013: Added option + LWIP_NETIF_TX_SINGLE_PBUF to try to create transmit packets from only + one pbuf to help MACs that don't support scatter-gather DMA. + + 2009-05-09 Simon Goldschmidt + * icmp.h, icmp.c: Shrinked ICMP code, added option to NOT check icoming + ECHO pbuf for size (just use it): LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN + + 2009-05-05 Simon Goldschmidt, Jakob Stoklund Olesen + * ip.h, ip.c: Added ip_current_netif() & ip_current_header() to receive + extended info about the currently received packet. + + 2009-04-27 Simon Goldschmidt + * sys.h: Made SYS_LIGHTWEIGHT_PROT and sys_now() work with NO_SYS=1 + + 2009-04-25 Simon Goldschmidt + * mem.c, opt.h: Added option MEM_USE_POOLS_TRY_BIGGER_POOL to try the next + bigger malloc pool if one is empty (only usable with MEM_USE_POOLS). + + 2009-04-21 Simon Goldschmidt + * dns.c, init.c, dns.h, opt.h: task #7507, patch #6786: DNS supports static + hosts table. New configuration options DNS_LOCAL_HOSTLIST and + DNS_LOCAL_HOSTLIST_IS_DYNAMIC. Also, DNS_LOOKUP_LOCAL_EXTERN() can be defined + as an external function for lookup. + + 2009-04-15 Simon Goldschmidt + * dhcp.c: patch #6763: Global DHCP XID can be redefined to something more unique + + 2009-03-31 Kieran Mansley + * tcp.c, tcp_out.c, tcp_in.c, sys.h, tcp.h, opts.h: add support for + TCP timestamp options, off by default. Rework tcp_enqueue() to + take option flags rather than specified option data + + 2009-02-18 Simon Goldschmidt + * cc.h: Added printf formatter for size_t: SZT_F + + 2009-02-16 Simon Goldschmidt (patch by Rishi Khan) + * icmp.c, opt.h: patch #6539: (configurable) response to broadcast- and multicast + pings + + 2009-02-12 Simon Goldschmidt + * init.h: Added LWIP_VERSION to get the current version of the stack + + 2009-02-11 Simon Goldschmidt (suggested by Gottfried Spitaler) + * opt.h, memp.h/.c: added MEMP_MEM_MALLOC to use mem_malloc/mem_free instead + of the pool allocator (can save code size with MEM_LIBC_MALLOC if libc-malloc + is otherwise used) + + 2009-01-28 Jonathan Larmour (suggested by Bill Bauerbach) + * ipv4/inet_chksum.c, ipv4/lwip/inet_chksum.h: inet_chksum_pseudo_partial() + is only used by UDPLITE at present, so conditionalise it. + + 2008-12-03 Simon Goldschmidt (base on patch from Luca Ceresoli) + * autoip.c: checked in (slightly modified) patch #6683: Customizable AUTOIP + "seed" address. This should reduce AUTOIP conflicts if + LWIP_AUTOIP_CREATE_SEED_ADDR is overridden. + + 2008-10-02 Jonathan Larmour and Rishi Khan + * sockets.c (lwip_accept): Return EWOULDBLOCK if would block on non-blocking + socket. + + 2008-06-30 Simon Goldschmidt + * mem.c, opt.h, stats.h: fixed bug #21433: Calling mem_free/pbuf_free from + interrupt context isn't safe: LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT allows + mem_free to run between mem_malloc iterations. Added illegal counter for + mem stats. + + 2008-06-27 Simon Goldschmidt + * stats.h/.c, some other files: patch #6483: stats module improvement: + Added defines to display each module's statistic individually, added stats + defines for MEM, MEMP and SYS modules, removed (unused) rexmit counter. + + 2008-06-17 Simon Goldschmidt + * err.h: patch #6459: Made err_t overridable to use a more efficient type + (define LWIP_ERR_T in cc.h) + + 2008-06-17 Simon Goldschmidt + * slipif.c: patch #6480: Added a configuration option for slipif for symmetry + to loopif + + 2008-06-17 Simon Goldschmidt (patch by Luca Ceresoli) + * netif.c, loopif.c, ip.c, netif.h, loopif.h, opt.h: Checked in slightly + modified version of patch # 6370: Moved loopif code to netif.c so that + loopback traffic is supported on all netifs (all local IPs). + Added option to limit loopback packets for each netifs. + + + ++ Bugfixes: + 2009-08-12 Kieran Mansley + * tcp_in.c, tcp.c: Fix bug #27209: handle trimming of segments when + out of window or out of order properly + + 2009-08-12 Kieran Mansley + * tcp_in.c: Fix bug #27199: use snd_wl2 instead of snd_wl1 + + 2009-07-28 Simon Goldschmidt + * mem.h: Fixed bug #27105: "realloc() cannot replace mem_realloc()"s + + 2009-07-27 Kieran Mansley + * api.h api_msg.h netdb.h sockets.h: add missing #include directives + + 2009-07-09 Kieran Mansley + * api_msg.c, sockets.c, api.h: BUG23240 use signed counters for + recv_avail and don't increment counters until message successfully + sent to mbox + + 2009-06-25 Kieran Mansley + * api_msg.c api.h: BUG26722: initialise netconn write variables + in netconn_alloc + + 2009-06-25 Kieran Mansley + * tcp.h: BUG26879: set ret value in TCP_EVENT macros when function is not set + + 2009-06-25 Kieran Mansley + * tcp.c, tcp_in.c, tcp_out.c, tcp.h: BUG26301 and BUG26267: correct + simultaneous close behaviour, and make snd_nxt have the same meaning + as in the RFCs. + + 2009-05-12 Simon Goldschmidt + * etharp.h, etharp.c, netif.c: fixed bug #26507: "Gratuitous ARP depends on + arp_table / uses etharp_query" by adding etharp_gratuitous() + + 2009-05-12 Simon Goldschmidt + * ip.h, ip.c, igmp.c: bug #26487: Added ip_output_if_opt that can add IP options + to the IP header (used by igmp_ip_output_if) + + 2009-05-06 Simon Goldschmidt + * inet_chksum.c: On little endian architectures, use LWIP_PLATFORM_HTONS (if + defined) for SWAP_BYTES_IN_WORD to speed up checksumming. + + 2009-05-05 Simon Goldschmidt + * sockets.c: bug #26405: Prematurely released semaphore causes lwip_select() + to crash + + 2009-05-04 Simon Goldschmidt + * init.c: snmp was not initialized in lwip_init() + + 2009-05-04 Frédéric Bernon + * dhcp.c, netbios.c: Changes if IP_SOF_BROADCAST is enabled. + + 2009-05-03 Simon Goldschmidt + * tcp.h: bug #26349: Nagle algorithm doesn't send although segment is full + (and unsent->next == NULL) + + 2009-05-02 Simon Goldschmidt + * tcpip.h, tcpip.c: fixed tcpip_untimeout (does not need the time, broken after + 1.3.0 in CVS only) - fixes compilation of ppp_oe.c + + 2009-05-02 Simon Goldschmidt + * msg_in.c: fixed bug #25636: SNMPSET value is ignored for integer fields + + 2009-05-01 Simon Goldschmidt + * pap.c: bug #21680: PPP upap_rauthnak() drops legal NAK packets + + 2009-05-01 Simon Goldschmidt + * ppp.c: bug #24228: Memory corruption with PPP and DHCP + + 2009-04-29 Frédéric Bernon + * raw.c, udp.c, init.c, opt.h, ip.h, sockets.h: bug #26309: Implement the + SO(F)_BROADCAST filter for all API layers. Avoid the unindented reception + of broadcast packets even when this option wasn't set. Port maintainers + which want to enable this filter have to set IP_SOF_BROADCAST=1 in opt.h. + If you want this option also filter broadcast on recv operations, you also + have to set IP_SOF_BROADCAST_RECV=1 in opt.h. + + 2009-04-28 Simon Goldschmidt, Jakob Stoklund Olesen + * dhcp.c: patch #6721, bugs #25575, #25576: Some small fixes to DHCP and + DHCP/AUTOIP cooperation + + 2009-04-25 Simon Goldschmidt, Oleg Tyshev + * tcp_out.c: bug #24212: Deadlocked tcp_retransmit due to exceeded pcb->cwnd + Fixed by sorting the unsent and unacked queues (segments are inserted at the + right place in tcp_output and tcp_rexmit). + + 2009-04-25 Simon Goldschmidt + * memp.c, mem.c, memp.h, mem_std.h: bug #26213 "Problem with memory allocation + when debugging": memp_sizes contained the wrong sizes (including sanity + regions); memp pools for MEM_USE_POOLS were too small + + 2009-04-24 Simon Goldschmidt, Frédéric Bernon + * inet.c: patch #6765: Fix a small problem with the last changes (incorrect + behavior, with with ip address string not ended by a '\0', a space or a + end of line) + + 2009-04-19 Simon Goldschmidt + * rawapi.txt: Fixed bug #26069: Corrected documentation: if tcp_connect fails, + pcb->err is called, not pcb->connected (with an error code). + + 2009-04-19 Simon Goldschmidt + * tcp_out.c: Fixed bug #26236: "TCP options (timestamp) don't work with + no-copy-tcpwrite": deallocate option data, only concat segments with same flags + + 2009-04-19 Simon Goldschmidt + * tcp_out.c: Fixed bug #25094: "Zero-length pbuf" (options are now allocated + in the header pbuf, not the data pbuf) + + 2009-04-18 Simon Goldschmidt + * api_msg.c: fixed bug #25695: Segmentation fault in do_writemore() + + 2009-04-15 Simon Goldschmidt + * sockets.c: tried to fix bug #23559: lwip_recvfrom problem with tcp + + 2009-04-15 Simon Goldschmidt + * dhcp.c: task #9192: mem_free of dhcp->options_in and dhcp->msg_in + + 2009-04-15 Simon Goldschmidt + * ip.c, ip6.c, tcp_out.c, ip.h: patch #6808: Add a utility function + ip_hinted_output() (for smaller code mainly) + + 2009-04-15 Simon Goldschmidt + * inet.c: patch #6765: Supporting new line characters in inet_aton() + + 2009-04-15 Simon Goldschmidt + * dhcp.c: patch #6764: DHCP rebind and renew did not send hostnam option; + Converted constant OPTION_MAX_MSG_SIZE to netif->mtu, check if netif->mtu + is big enough in dhcp_start + + 2009-04-15 Simon Goldschmidt + * netbuf.c: bug #26027: netbuf_chain resulted in pbuf memory leak + + 2009-04-15 Simon Goldschmidt + * sockets.c, ppp.c: bug #25763: corrected 4 occurrences of SMEMCPY to MEMCPY + + 2009-04-15 Simon Goldschmidt + * sockets.c: bug #26121: set_errno can be overridden + + 2009-04-09 Kieran Mansley (patch from Luca Ceresoli ) + * init.c, opt.h: Patch#6774 TCP_QUEUE_OOSEQ breaks compilation when + LWIP_TCP==0 + + 2009-04-09 Kieran Mansley (patch from Roy Lee ) + * tcp.h: Patch#6802 Add do-while-clauses to those function like + macros in tcp.h + + 2009-03-31 Kieran Mansley + * tcp.c, tcp_in.c, tcp_out.c, tcp.h, opt.h: Rework the way window + updates are calculated and sent (BUG20515) + + * tcp_in.c: cope with SYN packets received during established states, + and retransmission of initial SYN. + + * tcp_out.c: set push bit correctly when tcp segments are merged + + 2009-03-27 Kieran Mansley + * tcp_out.c set window correctly on probes (correcting change made + yesterday) + + 2009-03-26 Kieran Mansley + * tcp.c, tcp_in.c, tcp.h: add tcp_abandon() to cope with dropping + connections where no reset required (bug #25622) + + * tcp_out.c: set TCP_ACK flag on keepalive and zero window probes + (bug #20779) + + 2009-02-18 Simon Goldschmidt (Jonathan Larmour and Bill Auerbach) + * ip_frag.c: patch #6528: the buffer used for IP_FRAG_USES_STATIC_BUF could be + too small depending on MEM_ALIGNMENT + + 2009-02-16 Simon Goldschmidt + * sockets.h/.c, api_*.h/.c: fixed arguments of socket functions to match the standard; + converted size argument of netconn_write to 'size_t' + + 2009-02-16 Simon Goldschmidt + * tcp.h, tcp.c: fixed bug #24440: TCP connection close problem on 64-bit host + by moving accept callback function pointer to TCP_PCB_COMMON + + 2009-02-12 Simon Goldschmidt + * dhcp.c: fixed bug #25345 (DHCPDECLINE is sent with "Maximum message size" + option) + + 2009-02-11 Simon Goldschmidt + * dhcp.c: fixed bug #24480 (releasing old udp_pdb and pbuf in dhcp_start) + + 2009-02-11 Simon Goldschmidt + * opt.h, api_msg.c: added configurable default valud for netconn->recv_bufsize: + RECV_BUFSIZE_DEFAULT (fixes bug #23726: pbuf pool exhaustion on slow recv()) + + 2009-02-10 Simon Goldschmidt + * tcp.c: fixed bug #25467: Listen backlog is not reset on timeout in SYN_RCVD: + Accepts_pending is decrease on a corresponding listen pcb when a connection + in state SYN_RCVD is close. + + 2009-01-28 Jonathan Larmour + * pbuf.c: reclaim pbufs from TCP out-of-sequence segments if we run + out of pool pbufs. + + 2008-12-19 Simon Goldschmidt + * many files: patch #6699: fixed some warnings on platform where sizeof(int) == 2 + + 2008-12-10 Tamas Somogyi, Frédéric Bernon + * sockets.c: fixed bug #25051: lwip_recvfrom problem with udp: fromaddr and + port uses deleted netbuf. + + 2008-10-18 Simon Goldschmidt + * tcp_in.c: fixed bug ##24596: Vulnerability on faulty TCP options length + in tcp_parseopt + + 2008-10-15 Simon Goldschmidt + * ip_frag.c: fixed bug #24517: IP reassembly crashes on unaligned IP headers + by packing the struct ip_reass_helper. + + 2008-10-03 David Woodhouse, Jonathan Larmour + * etharp.c (etharp_arp_input): Fix type aliasing problem copying ip address. + + 2008-10-02 Jonathan Larmour + * dns.c: Hard-code structure sizes, to avoid issues on some compilers where + padding is included. + + 2008-09-30 Jonathan Larmour + * sockets.c (lwip_accept): check addr isn't NULL. If it's valid, do an + assertion check that addrlen isn't NULL. + + 2008-09-30 Jonathan Larmour + * tcp.c: Fix bug #24227, wrong error message in tcp_bind. + + 2008-08-26 Simon Goldschmidt + * inet.h, ip_addr.h: fixed bug #24132: Cross-dependency between ip_addr.h and + inet.h -> moved declaration of struct in_addr from ip_addr.h to inet.h + + 2008-08-14 Simon Goldschmidt + * api_msg.c: fixed bug #23847: do_close_internal references freed memory (when + tcp_close returns != ERR_OK) + + 2008-07-08 Frédéric Bernon + * stats.h: Fix some build bugs introduced with patch #6483 (missing some parameters + in macros, mainly if MEM_STATS=0 and MEMP_STATS=0). + + 2008-06-24 Jonathan Larmour + * tcp_in.c: Fix for bug #23693 as suggested by Art R. Ensure cseg is unused + if tcp_seg_copy fails. + + 2008-06-17 Simon Goldschmidt + * inet_chksum.c: Checked in some ideas of patch #6460 (loop optimizations) + and created defines for swapping bytes and folding u32 to u16. + + 2008-05-30 Kieran Mansley + * tcp_in.c Remove redundant "if" statement, and use real rcv_wnd + rather than rcv_ann_wnd when deciding if packets are in-window. + Contributed by + + 2008-05-30 Kieran Mansley + * mem.h: Fix BUG#23254. Change macro definition of mem_* to allow + passing as function pointers when MEM_LIBC_MALLOC is defined. + + 2008-05-09 Jonathan Larmour + * err.h, err.c, sockets.c: Fix bug #23119: Reorder timeout error code to + stop it being treated as a fatal error. + + 2008-04-15 Simon Goldschmidt + * dhcp.c: fixed bug #22804: dhcp_stop doesn't clear NETIF_FLAG_DHCP + (flag now cleared) + + 2008-03-27 Simon Goldschmidt + * mem.c, tcpip.c, tcpip.h, opt.h: fixed bug #21433 (Calling mem_free/pbuf_free + from interrupt context isn't safe): set LWIP_USE_HEAP_FROM_INTERRUPT to 1 + in lwipopts.h or use pbuf_free_callback(p)/mem_free_callback(m) to free pbufs + or heap memory from interrupt context + + 2008-03-26 Simon Goldschmidt + * tcp_in.c, tcp.c: fixed bug #22249: division by zero could occur if a remote + host sent a zero mss as TCP option. + + +(STABLE-1.3.0) + + ++ New features: + + 2008-03-10 Jonathan Larmour + * inet_chksum.c: Allow choice of one of the sample algorithms to be + made from lwipopts.h. Fix comment on how to override LWIP_CHKSUM. + + 2008-01-22 Frédéric Bernon + * tcp.c, tcp_in.c, tcp.h, opt.h: Rename LWIP_CALCULATE_EFF_SEND_MSS in + TCP_CALCULATE_EFF_SEND_MSS to have coherent TCP options names. + + 2008-01-14 Frédéric Bernon + * rawapi.txt, api_msg.c, tcp.c, tcp_in.c, tcp.h: changes for task #7675 "Enable + to refuse data on a TCP_EVENT_RECV call". Important, behavior changes for the + tcp_recv callback (see rawapi.txt). + + 2008-01-14 Frédéric Bernon, Marc Chaland + * ip.c: Integrate patch #6369" ip_input : checking before realloc". + + 2008-01-12 Frédéric Bernon + * tcpip.h, tcpip.c, api.h, api_lib.c, api_msg.c, sockets.c: replace the field + netconn::sem per netconn::op_completed like suggested for the task #7490 + "Add return value to sys_mbox_post". + + 2008-01-12 Frédéric Bernon + * api_msg.c, opt.h: replace DEFAULT_RECVMBOX_SIZE per DEFAULT_TCP_RECVMBOX_SIZE, + DEFAULT_UDP_RECVMBOX_SIZE and DEFAULT_RAW_RECVMBOX_SIZE (to optimize queues + sizes), like suggested for the task #7490 "Add return value to sys_mbox_post". + + 2008-01-10 Frédéric Bernon + * tcpip.h, tcpip.c: add tcpip_callback_with_block function for the task #7490 + "Add return value to sys_mbox_post". tcpip_callback is always defined as + "blocking" ("block" parameter = 1). + + 2008-01-10 Frédéric Bernon + * tcpip.h, tcpip.c, api.h, api_lib.c, api_msg.c, sockets.c: replace the field + netconn::mbox (sys_mbox_t) per netconn::sem (sys_sem_t) for the task #7490 + "Add return value to sys_mbox_post". + + 2008-01-05 Frédéric Bernon + * sys_arch.txt, api.h, api_lib.c, api_msg.h, api_msg.c, tcpip.c, sys.h, opt.h: + Introduce changes for task #7490 "Add return value to sys_mbox_post" with some + modifications in the sys_mbox api: sys_mbox_new take a "size" parameters which + indicate the number of pointers query by the mailbox. There is three defines + in opt.h to indicate sizes for tcpip::mbox, netconn::recvmbox, and for the + netconn::acceptmbox. Port maintainers, you can decide to just add this new + parameter in your implementation, but to ignore it to keep the previous behavior. + The new sys_mbox_trypost function return a value to know if the mailbox is + full or if the message is posted. Take a look to sys_arch.txt for more details. + This new function is used in tcpip_input (so, can be called in an interrupt + context since the function is not blocking), and in recv_udp and recv_raw. + + 2008-01-04 Frédéric Bernon, Simon Goldschmidt, Jonathan Larmour + * rawapi.txt, api.h, api_lib.c, api_msg.h, api_msg.c, sockets.c, tcp.h, tcp.c, + tcp_in.c, init.c, opt.h: rename backlog options with TCP_ prefix, limit the + "backlog" parameter in an u8_t, 0 is interpreted as "smallest queue", add + documentation in the rawapi.txt file. + + 2007-12-31 Kieran Mansley (based on patch from Per-Henrik Lundbolm) + * tcp.c, tcp_in.c, tcp_out.c, tcp.h: Add TCP persist timer + + 2007-12-31 Frédéric Bernon, Luca Ceresoli + * autoip.c, etharp.c: ip_addr.h: Integrate patch #6348: "Broadcast ARP packets + in autoip". The change in etharp_raw could be removed, since all calls to + etharp_raw use ethbroadcast for the "ethdst_addr" parameter. But it could be + wrong in the future. + + 2007-12-30 Frédéric Bernon, Tom Evans + * ip.c: Fix bug #21846 "LwIP doesn't appear to perform any IP Source Address + Filtering" reported by Tom Evans. + + 2007-12-21 Frédéric Bernon, Simon Goldschmidt, Jonathan Larmour + * tcp.h, opt.h, api.h, api_msg.h, tcp.c, tcp_in.c, api_lib.c, api_msg.c, + sockets.c, init.c: task #7252: Implement TCP listen backlog: Warning: raw API + applications have to call 'tcp_accepted(pcb)' in their accept callback to + keep accepting new connections. + + 2007-12-13 Frédéric Bernon + * api_msg.c, err.h, err.c, sockets.c, dns.c, dns.h: replace "enum dns_result" + by err_t type. Add a new err_t code "ERR_INPROGRESS". + + 2007-12-12 Frédéric Bernon + * dns.h, dns.c, opt.h: move DNS options to the "right" place. Most visibles + are the one which have ram usage. + + 2007-12-05 Frédéric Bernon + * netdb.c: add a LWIP_DNS_API_HOSTENT_STORAGE option to decide to use a static + set of variables (=0) or a local one (=1). In this last case, your port should + provide a function "struct hostent* sys_thread_hostent( struct hostent* h)" + which have to do a copy of "h" and return a pointer ont the "per-thread" copy. + + 2007-12-03 Simon Goldschmidt + * ip.c: ip_input: check if a packet is for inp first before checking all other + netifs on netif_list (speeds up packet receiving in most cases) + + 2007-11-30 Simon Goldschmidt + * udp.c, raw.c: task #7497: Sort lists (pcb, netif, ...) for faster access + UDP: move a (connected) pcb selected for input to the front of the list of + pcbs so that it is found faster next time. Same for RAW pcbs that have eaten + a packet. + + 2007-11-28 Simon Goldschmidt + * etharp.c, stats.c, stats.h, opt.h: Introduced ETHARP_STATS + + 2007-11-25 Simon Goldschmidt + * dhcp.c: dhcp_unfold_reply() uses pbuf_copy_partial instead of its own copy + algorithm. + + 2007-11-24 Simon Goldschmidt + * netdb.h, netdb.c, sockets.h/.c: Moved lwip_gethostbyname from sockets.c + to the new file netdb.c; included lwip_getaddrinfo. + + 2007-11-21 Simon Goldschmidt + * tcp.h, opt.h, tcp.c, tcp_in.c: implemented calculating the effective send-mss + based on the MTU of the netif used to send. Enabled by default. Disable by + setting LWIP_CALCULATE_EFF_SEND_MSS to 0. This fixes bug #21492. + + 2007-11-19 Frédéric Bernon + * api_msg.c, dns.h, dns.c: Implement DNS_DOES_NAME_CHECK option (check if name + received match the name query), implement DNS_USES_STATIC_BUF (the place where + copy dns payload to parse the response), return an error if there is no place + for a new query, and fix some minor problems. + + 2007-11-16 Simon Goldschmidt + * new files: ipv4/inet.c, ipv4/inet_chksum.c, ipv6/inet6.c + removed files: core/inet.c, core/inet6.c + Moved inet files into ipv4/ipv6 directory; splitted inet.c/inet.h into + inet and chksum part; changed includes in all lwIP files as appropriate + + 2007-11-16 Simon Goldschmidt + * api.h, api_msg.h, api_lib.c, api_msg.c, socket.h, socket.c: Added sequential + dns resolver function for netconn api (netconn_gethostbyname) and socket api + (gethostbyname/gethostbyname_r). + + 2007-11-15 Jim Pettinato, Frédéric Bernon + * opt.h, init.c, tcpip.c, dhcp.c, dns.h, dns.c: add DNS client for simple name + requests with RAW api interface. Initialization is done in lwip_init() with + build time options. DNS timer is added in tcpip_thread context. DHCP can set + DNS server ip addresses when options are received. You need to set LWIP_DNS=1 + in your lwipopts.h file (LWIP_DNS=0 in opt.h). DNS_DEBUG can be set to get + some traces with LWIP_DEBUGF. Sanity check have been added. There is a "todo" + list with points to improve. + + 2007-11-06 Simon Goldschmidt + * opt.h, mib2.c: Patch #6215: added ifAdminStatus write support (if explicitly + enabled by defining SNMP_SAFE_REQUESTS to 0); added code to check link status + for ifOperStatus if LWIP_NETIF_LINK_CALLBACK is defined. + + 2007-11-06 Simon Goldschmidt + * api.h, api_msg.h and dependent files: Task #7410: Removed the need to include + core header files in api.h (ip/tcp/udp/raw.h) to hide the internal + implementation from netconn api applications. + + 2007-11-03 Frédéric Bernon + * api.h, api_lib.c, api_msg.c, sockets.c, opt.h: add SO_RCVBUF option for UDP & + RAW netconn. You need to set LWIP_SO_RCVBUF=1 in your lwipopts.h (it's disabled + by default). Netconn API users can use the netconn_recv_bufsize macro to access + it. This is a first release which have to be improve for TCP. Note it used the + netconn::recv_avail which need to be more "thread-safe" (note there is already + the problem for FIONREAD with lwip_ioctl/ioctlsocket). + + 2007-11-01 Frédéric Bernon, Marc Chaland + * sockets.h, sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c, tcp.h, tcp_out.c: + Integrate "patch #6250 : MSG_MORE flag for send". MSG_MORE is used at socket api + layer, NETCONN_MORE at netconn api layer, and TCP_WRITE_FLAG_MORE at raw api + layer. This option enable to delayed TCP PUSH flag on multiple "write" calls. + Note that previous "copy" parameter for "write" APIs is now called "apiflags". + + 2007-10-24 Frédéric Bernon + * api.h, api_lib.c, api_msg.c: Add macro API_EVENT in the same spirit than + TCP_EVENT_xxx macros to get a code more readable. It could also help to remove + some code (like we have talk in "patch #5919 : Create compile switch to remove + select code"), but it could be done later. + + 2007-10-08 Simon Goldschmidt + * many files: Changed initialization: many init functions are not needed any + more since we now rely on the compiler initializing global and static + variables to zero! + + 2007-10-06 Simon Goldschmidt + * ip_frag.c, memp.c, mib2.c, ip_frag.h, memp_std.h, opt.h: Changed IP_REASSEMBLY + to enqueue the received pbufs so that multiple packets can be reassembled + simultaneously and no static reassembly buffer is needed. + + 2007-10-05 Simon Goldschmidt + * tcpip.c, etharp.h, etharp.c: moved ethernet_input from tcpip.c to etharp.c so + all netifs (or ports) can use it. + + 2007-10-05 Frédéric Bernon + * netifapi.h, netifapi.c: add function netifapi_netif_set_default. Change the + common function to reduce a little bit the footprint (for all functions using + only the "netif" parameter). + + 2007-10-03 Frédéric Bernon + * netifapi.h, netifapi.c: add functions netifapi_netif_set_up, netifapi_netif_set_down, + netifapi_autoip_start and netifapi_autoip_stop. Use a common function to reduce + a little bit the footprint (for all functions using only the "netif" parameter). + + 2007-09-15 Frédéric Bernon + * udp.h, udp.c, sockets.c: Changes for "#20503 IGMP Improvement". Add IP_MULTICAST_IF + option in socket API, and a new field "multicast_ip" in "struct udp_pcb" (for + netconn and raw API users), only if LWIP_IGMP=1. Add getsockopt processing for + IP_MULTICAST_TTL and IP_MULTICAST_IF. + + 2007-09-10 Frédéric Bernon + * snmp.h, mib2.c: enable to remove SNMP timer (which consumne several cycles + even when it's not necessary). snmp_agent.txt tell to call snmp_inc_sysuptime() + each 10ms (but, it's intrusive if you use sys_timeout feature). Now, you can + decide to call snmp_add_sysuptime(100) each 1000ms (which is bigger "step", but + call to a lower frequency). Or, you can decide to not call snmp_inc_sysuptime() + or snmp_add_sysuptime(), and to define the SNMP_GET_SYSUPTIME(sysuptime) macro. + This one is undefined by default in mib2.c. SNMP_GET_SYSUPTIME is called inside + snmp_get_sysuptime(u32_t *value), and enable to change "sysuptime" value only + when it's queried (any direct call to "sysuptime" is changed by a call to + snmp_get_sysuptime). + + 2007-09-09 Frédéric Bernon, Bill Florac + * igmp.h, igmp.c, netif.h, netif.c, ip.c: To enable to have interfaces with IGMP, + and others without it, there is a new NETIF_FLAG_IGMP flag to set in netif->flags + if you want IGMP on an interface. igmp_stop() is now called inside netif_remove(). + igmp_report_groups() is now called inside netif_set_link_up() (need to have + LWIP_NETIF_LINK_CALLBACK=1) to resend reports once the link is up (avoid to wait + the next query message to receive the matching multicast streams). + + 2007-09-08 Frédéric Bernon + * sockets.c, ip.h, api.h, tcp.h: declare a "struct ip_pcb" which only contains + IP_PCB. Add in the netconn's "pcb" union a "struct ip_pcb *ip;" (no size change). + Use this new field to access to common pcb fields (ttl, tos, so_options, etc...). + Enable to access to these fields with LWIP_TCP=0. + + 2007-09-05 Frédéric Bernon + * udp.c, ipv4/icmp.c, ipv4/ip.c, ipv6/icmp.c, ipv6/ip6.c, ipv4/icmp.h, + ipv6/icmp.h, opt.h: Integrate "task #7272 : LWIP_ICMP option". The new option + LWIP_ICMP enable/disable ICMP module inside the IP stack (enable per default). + Be careful, disabling ICMP make your product non-compliant to RFC1122, but + help to reduce footprint, and to reduce "visibility" on the Internet. + + 2007-09-05 Frédéric Bernon, Bill Florac + * opt.h, sys.h, tcpip.c, slipif.c, ppp.c, sys_arch.txt: Change parameters list + for sys_thread_new (see "task #7252 : Create sys_thread_new_ex()"). Two new + parameters have to be provided: a task name, and a task stack size. For this + one, since it's platform dependant, you could define the best one for you in + your lwipopts.h. For port maintainers, you can just add these new parameters + in your sys_arch.c file, and but it's not mandatory, use them in your OS + specific functions. + + 2007-09-05 Frédéric Bernon + * inet.c, autoip.c, msg_in.c, msg_out.c, init.c: Move some build time checkings + inside init.c for task #7142 "Sanity check user-configurable values". + + 2007-09-04 Frédéric Bernon, Bill Florac + * igmp.h, igmp.c, memp_std.h, memp.c, init.c, opt.h: Replace mem_malloc call by + memp_malloc, and use a new MEMP_NUM_IGMP_GROUP option (see opt.h to define the + value). It will avoid potential fragmentation problems, use a counter to know + how many times a group is used on an netif, and free it when all applications + leave it. MEMP_NUM_IGMP_GROUP got 8 as default value (and init.c got a sanity + check if LWIP_IGMP!=0). + + 2007-09-03 Frédéric Bernon + * igmp.h, igmp.c, sockets.c, api_msg.c: Changes for "#20503 IGMP Improvement". + Initialize igmp_mac_filter to NULL in netif_add (this field should be set in + the netif's "init" function). Use the "imr_interface" field (for socket layer) + and/or the "interface" field (for netconn layer), for join/leave operations. + The igmp_join/leavegroup first parameter change from a netif to an ipaddr. + This field could be a netif's ipaddr, or "any" (same meaning than ip_addr_isany). + + 2007-08-30 Frédéric Bernon + * Add netbuf.h, netbuf.c, Change api.h, api_lib.c: #7249 "Split netbuf functions + from api/api_lib". Now netbuf API is independant of netconn, and can be used + with other API (application based on raw API, or future "socket2" API). Ports + maintainers just have to add src/api/netbuf.c in their makefile/projects. + + 2007-08-30 Frédéric Bernon, Jonathan Larmour + * init.c: Add first version of lwip_sanity_check for task #7142 "Sanity check + user-configurable values". + + 2007-08-29 Frédéric Bernon + * igmp.h, igmp.c, tcpip.c, init.c, netif.c: change igmp_init and add igmp_start. + igmp_start is call inside netif_add. Now, igmp initialization is in the same + spirit than the others modules. Modify some IGMP debug traces. + + 2007-08-29 Frédéric Bernon + * Add init.h, init.c, Change opt.h, tcpip.c: Task #7213 "Add a lwip_init function" + Add lwip_init function to regroup all modules initializations, and to provide + a place to add code for task #7142 "Sanity check user-configurable values". + Ports maintainers should remove direct initializations calls from their code, + and add init.c in their makefiles. Note that lwip_init() function is called + inside tcpip_init, but can also be used by raw api users since all calls are + disabled when matching options are disabled. Also note that their is new options + in opt.h, you should configure in your lwipopts.h (they are enabled per default). + + 2007-08-26 Marc Boucher + * api_msg.c: do_close_internal(): Reset the callbacks and arg (conn) to NULL + since they can under certain circumstances be called with an invalid conn + pointer after the connection has been closed (and conn has been freed). + + 2007-08-25 Frédéric Bernon (Artem Migaev's Patch) + * netif.h, netif.c: Integrate "patch #6163 : Function to check if link layer is up". + Add a netif_is_link_up() function if LWIP_NETIF_LINK_CALLBACK option is set. + + 2007-08-22 Frédéric Bernon + * netif.h, netif.c, opt.h: Rename LWIP_NETIF_CALLBACK in LWIP_NETIF_STATUS_CALLBACK + to be coherent with new LWIP_NETIF_LINK_CALLBACK option before next release. + + 2007-08-22 Frédéric Bernon + * tcpip.h, tcpip.c, ethernetif.c, opt.h: remove options ETHARP_TCPIP_INPUT & + ETHARP_TCPIP_ETHINPUT, now, only "ethinput" code is supported, even if the + name is tcpip_input (we keep the name of 1.2.0 function). + + 2007-08-17 Jared Grubb + * memp_std.h, memp.h, memp.c, mem.c, stats.c: (Task #7136) Centralize mempool + settings into new memp_std.h and optional user file lwippools.h. This adds + more dynamic mempools, and allows the user to create an arbitrary number of + mempools for mem_malloc. + + 2007-08-16 Marc Boucher + * api_msg.c: Initialize newconn->state to NETCONN_NONE in accept_function; + otherwise it was left to NETCONN_CLOSE and sent_tcp() could prematurely + close the connection. + + 2007-08-16 Marc Boucher + * sockets.c: lwip_accept(): check netconn_peer() error return. + + 2007-08-16 Marc Boucher + * mem.c, mem.h: Added mem_calloc(). + + 2007-08-16 Marc Boucher + * tcpip.c, tcpip.h memp.c, memp.h: Added distinct memp (MEMP_TCPIP_MSG_INPKT) + for input packets to prevent floods from consuming all of MEMP_TCPIP_MSG + and starving other message types. + Renamed MEMP_TCPIP_MSG to MEMP_TCPIP_MSG_API + + 2007-08-16 Marc Boucher + * pbuf.c, pbuf.h, etharp.c, tcp_in.c, sockets.c: Split pbuf flags in pbuf + type and flgs (later renamed to flags). + Use enum pbuf_flag as pbuf_type. Renumber PBUF_FLAG_*. + Improved lwip_recvfrom(). TCP push now propagated. + + 2007-08-16 Marc Boucher + * ethernetif.c, contrib/ports/various: ethbroadcast now a shared global + provided by etharp. + + 2007-08-16 Marc Boucher + * ppp_oe.c ppp_oe.h, auth.c chap.c fsm.c lcp.c ppp.c ppp.h, + etharp.c ethernetif.c, etharp.h, opt.h tcpip.h, tcpip.c: + Added PPPoE support and various PPP improvements. + + 2007-07-25 Simon Goldschmidt + * api_lib.c, ip_frag.c, pbuf.c, api.h, pbuf.h: Introduced pbuf_copy_partial, + making netbuf_copy_partial use this function. + + 2007-07-25 Simon Goldschmidt + * tcp_in.c: Fix bug #20506: Slow start / initial congestion window starts with + 2 * mss (instead of 1 * mss previously) to comply with some newer RFCs and + other stacks. + + 2007-07-13 Jared Grubb (integrated by Frédéric Bernon) + * opt.h, netif.h, netif.c, ethernetif.c: Add new configuration option to add + a link callback in the netif struct, and functions to handle it. Be carefull + for port maintainers to add the NETIF_FLAG_LINK_UP flag (like in ethernetif.c) + if you want to be sure to be compatible with future changes... + + 2007-06-30 Frédéric Bernon + * sockets.h, sockets.c: Implement MSG_PEEK flag for recv/recvfrom functions. + + 2007-06-21 Simon Goldschmidt + * etharp.h, etharp.c: Combined etharp_request with etharp_raw for both + LWIP_AUTOIP =0 and =1 to remove redundant code. + + 2007-06-21 Simon Goldschmidt + * mem.c, memp.c, mem.h, memp.h, opt.h: task #6863: Introduced the option + MEM_USE_POOLS to use 4 pools with different sized elements instead of a + heap. This both prevents memory fragmentation and gives a higher speed + at the cost of more memory consumption. Turned off by default. + + 2007-06-21 Simon Goldschmidt + * api_lib.c, api_msg.c, api.h, api_msg.h: Converted the length argument of + netconn_write (and therefore also api_msg_msg.msg.w.len) from u16_t into + int to be able to send a bigger buffer than 64K with one time (mainly + used from lwip_send). + + 2007-06-21 Simon Goldschmidt + * tcp.h, api_msg.c: Moved the nagle algorithm from netconn_write/do_write + into a define (tcp_output_nagle) in tcp.h to provide it to raw api users, too. + + 2007-06-21 Simon Goldschmidt + * api.h, api_lib.c, api_msg.c: Fixed bug #20021: Moved sendbuf-processing in + netconn_write from api_lib.c to api_msg.c to also prevent multiple context- + changes on low memory or empty send-buffer. + + 2007-06-18 Simon Goldschmidt + * etharp.c, etharp.h: Changed etharp to use a defined hardware address length + of 6 to avoid loading netif->hwaddr_len every time (since this file is only + used for ethernet and struct eth_addr already had a defined length of 6). + + 2007-06-17 Simon Goldschmidt + * sockets.c, sockets.h: Implemented socket options SO_NO_CHECK for UDP sockets + to disable UDP checksum generation on transmit. + + 2007-06-13 Frédéric Bernon, Simon Goldschmidt + * debug.h, api_msg.c: change LWIP_ERROR to use it to check errors like invalid + pointers or parameters, and let the possibility to redefined it in cc.h. Use + this macro to check "conn" parameter in api_msg.c functions. + + 2007-06-11 Simon Goldschmidt + * sockets.c, sockets.h: Added UDP lite support for sockets + + 2007-06-10 Simon Goldschmidt + * udp.h, opt.h, api_msg.c, ip.c, udp.c: Included switch LWIP_UDPLITE (enabled + by default) to switch off UDP-Lite support if not needed (reduces udp.c code + size) + + 2007-06-09 Dominik Spies (integrated by Frédéric Bernon) + * autoip.h, autoip.c, dhcp.h, dhcp.c, netif.h, netif.c, etharp.h, etharp.c, opt.h: + AutoIP implementation available for IPv4, with new options LWIP_AUTOIP and + LWIP_DHCP_AUTOIP_COOP if you want to cooperate with DHCP. Some tips to adapt + (see TODO mark in the source code). + + 2007-06-09 Simon Goldschmidt + * etharp.h, etharp.c, ethernetif.c: Modified order of parameters for + etharp_output() to match netif->output so etharp_output() can be used + directly as netif->output to save one function call. + + 2007-06-08 Simon Goldschmidt + * netif.h, ethernetif.c, slipif.c, loopif.c: Added define + NETIF_INIT_SNMP(netif, type, speed) to initialize per-netif snmp variables, + added initialization of those to ethernetif, slipif and loopif. + + 2007-05-18 Simon Goldschmidt + * opt.h, ip_frag.c, ip_frag.h, ip.c: Added option IP_FRAG_USES_STATIC_BUF + (defaulting to off for now) that can be set to 0 to send fragmented + packets by passing PBUF_REFs down the stack. + + 2007-05-23 Frédéric Bernon + * api_lib.c: Implement SO_RCVTIMEO for accept and recv on TCP + connections, such present in patch #5959. + + 2007-05-23 Frédéric Bernon + * api.h, api_lib.c, api_msg.c, sockets.c: group the different NETCONN_UDPxxx + code in only one part... + + 2007-05-18 Simon Goldschmidt + * opt.h, memp.h, memp.c: Added option MEMP_OVERFLOW_CHECK to check for memp + elements to overflow. This is achieved by adding some bytes before and after + each pool element (increasing their size, of course), filling them with a + prominent value and checking them on freeing the element. + Set it to 2 to also check every element in every pool each time memp_malloc() + or memp_free() is called (slower but more helpful). + + 2007-05-10 Simon Goldschmidt + * opt.h, memp.h, memp.c, pbuf.c (see task #6831): use a new memp pool for + PBUF_POOL pbufs instead of the old pool implementation in pbuf.c to reduce + code size. + + 2007-05-11 Frédéric Bernon + * sockets.c, api_lib.c, api_msg.h, api_msg.c, netifapi.h, netifapi.c, tcpip.c: + Include a function pointer instead of a table index in the message to reduce + footprint. Disable some part of lwip_send and lwip_sendto if some options are + not set (LWIP_TCP, LWIP_UDP, LWIP_RAW). + + 2007-05-10 Simon Goldschmidt + * *.h (except netif/ppp/*.h): Included patch #5448: include '#ifdef __cplusplus + \ extern "C" {' in all header files. Now you can write your application using + the lwIP stack in C++ and simply #include the core files. Note I have left + out the netif/ppp/*h header files for now, since I don't know which files are + included by applications and which are for internal use only. + + 2007-05-09 Simon Goldschmidt + * opt.h, *.c/*.h: Included patch #5920: Create define to override C-library + memcpy. 2 Defines are created: MEMCPY() for normal memcpy, SMEMCPY() for + situations where some compilers might inline the copy and save a function + call. Also replaced all calls to memcpy() with calls to (S)MEMCPY(). + + 2007-05-08 Simon Goldschmidt + * mem.h: If MEM_LIBC_MALLOC==1, allow the defines (e.g. mem_malloc() -> malloc()) + to be overriden in case the C-library malloc implementation is not protected + against concurrent access. + + 2007-05-04 Simon Goldschmidt (Atte Kojo) + * etharp.c: Introduced fast one-entry-cache to speed up ARP lookup when sending + multiple packets to the same host. + + 2007-05-04 Frédéric Bernon, Jonathan Larmour + * sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c: Fix bug #19162 "lwip_sento: a possible + to corrupt remote addr/port connection state". Reduce problems "not enought memory" with + netbuf (if we receive lot of datagrams). Improve lwip_sendto (only one exchange between + sockets api and api_msg which run in tcpip_thread context). Add netconn_sento function. + Warning, if you directly access to "fromaddr" & "fromport" field from netbuf struct, + these fields are now renamed "addr" & "port". + + 2007-04-11 Jonathan Larmour + * sys.h, api_lib.c: Provide new sys_mbox_tryfetch function. Require ports to provide new + sys_arch_mbox_tryfetch function to get a message if one is there, otherwise return + with SYS_MBOX_EMPTY. sys_arch_mbox_tryfetch can be implemented as a function-like macro + by the port in sys_arch.h if desired. + + 2007-04-06 Frédéric Bernon, Simon Goldschmidt + * opt.h, tcpip.h, tcpip.c, netifapi.h, netifapi.c: New configuration option LWIP_NETIF_API + allow to use thread-safe functions to add/remove netif in list, and to start/stop dhcp + clients, using new functions from netifapi.h. Disable as default (no port change to do). + + 2007-04-05 Frédéric Bernon + * sockets.c: remplace ENOBUFS errors on alloc_socket by ENFILE to be more BSD compliant. + + 2007-04-04 Simon Goldschmidt + * arch.h, api_msg.c, dhcp.c, msg_in.c, sockets.c: Introduced #define LWIP_UNUSED_ARG(x) + use this for and architecture-independent form to tell the compiler you intentionally + are not using this variable. Can be overriden in cc.h. + + 2007-03-28 Frédéric Bernon + * opt.h, netif.h, dhcp.h, dhcp.c: New configuration option LWIP_NETIF_HOSTNAME allow to + define a hostname in netif struct (this is just a pointer, so, you can use a hardcoded + string, point on one of your's ethernetif field, or alloc a string you will free yourself). + It will be used by DHCP to register a client hostname, but can also be use when you call + snmp_set_sysname. + + 2007-03-28 Frédéric Bernon + * netif.h, netif.c: A new NETIF_FLAG_ETHARP flag is defined in netif.h, to allow to + initialize a network interface's flag with. It tell this interface is an ethernet + device, and we can use ARP with it to do a "gratuitous ARP" (RFC 3220 "IP Mobility + Support for IPv4" section 4.6) when interface is "up" with netif_set_up(). + + 2007-03-26 Frédéric Bernon, Jonathan Larmour + * opt.h, tcpip.c: New configuration option LWIP_ARP allow to disable ARP init at build + time if you only use PPP or SLIP. The default is enable. Note we don't have to call + etharp_init in your port's initilization sequence if you use tcpip.c, because this call + is done in tcpip_init function. + + 2007-03-22 Frédéric Bernon + * stats.h, stats.c, msg_in.c: Stats counters can be change to u32_t if necessary with the + new option LWIP_STATS_LARGE. If you need this option, define LWIP_STATS_LARGE to 1 in + your lwipopts.h. More, unused counters are not defined in the stats structs, and not + display by stats_display(). Note that some options (SYS_STATS and RAW_STATS) are defined + but never used. Fix msg_in.c with the correct #if test for a stat display. + + 2007-03-21 Kieran Mansley + * netif.c, netif.h: Apply patch#4197 with some changes (originator: rireland@hmgsl.com). + Provides callback on netif up/down state change. + + 2007-03-11 Frédéric Bernon, Mace Gael, Steve Reynolds + * sockets.h, sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c, igmp.h, igmp.c, + ip.c, netif.h, tcpip.c, opt.h: + New configuration option LWIP_IGMP to enable IGMP processing. Based on only one + filter per all network interfaces. Declare a new function in netif to enable to + control the MAC filter (to reduce lwIP traffic processing). + + 2007-03-11 Frédéric Bernon + * tcp.h, tcp.c, sockets.c, tcp_out.c, tcp_in.c, opt.h: Keepalive values can + be configured at run time with LWIP_TCP_KEEPALIVE, but don't change this + unless you know what you're doing (default are RFC1122 compliant). Note + that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set in seconds. + + 2007-03-08 Frédéric Bernon + * tcp.h: Keepalive values can be configured at compile time, but don't change + this unless you know what you're doing (default are RFC1122 compliant). + + 2007-03-08 Frédéric Bernon + * sockets.c, api.h, api_lib.c, tcpip.c, sys.h, sys.c, err.c, opt.h: + Implement LWIP_SO_RCVTIMEO configuration option to enable/disable SO_RCVTIMEO + on UDP sockets/netconn. + + 2007-03-08 Simon Goldschmidt + * snmp_msg.h, msg_in.c: SNMP UDP ports can be configured at compile time. + + 2007-03-06 Frédéric Bernon + * api.h, api_lib.c, sockets.h, sockets.c, tcpip.c, sys.h, sys.c, err.h: + Implement SO_RCVTIMEO on UDP sockets/netconn. + + 2007-02-28 Kieran Mansley (based on patch from Simon Goldschmidt) + * api_lib.c, tcpip.c, memp.c, memp.h: make API msg structs allocated + on the stack and remove the API msg type from memp + + 2007-02-26 Jonathan Larmour (based on patch from Simon Goldschmidt) + * sockets.h, sockets.c: Move socket initialization to new + lwip_socket_init() function. + NOTE: this changes the API with ports. Ports will have to be + updated to call lwip_socket_init() now. + + 2007-02-26 Jonathan Larmour (based on patch from Simon Goldschmidt) + * api_lib.c: Use memcpy in netbuf_copy_partial. + + + ++ Bug fixes: + + 2008-03-17 Frédéric Bernon, Ed Kerekes + * igmp.h, igmp.c: Fix bug #22613 "IGMP iphdr problem" (could have + some problems to fill the IP header on some targets, use now the + ip.h macros to do it). + + 2008-03-13 Frédéric Bernon + * sockets.c: Fix bug #22435 "lwip_recvfrom with TCP break;". Using + (lwip_)recvfrom with valid "from" and "fromlen" parameters, on a + TCP connection caused a crash. Note that using (lwip_)recvfrom + like this is a bit slow and that using (lwip)getpeername is the + good lwip way to do it (so, using recv is faster on tcp sockets). + + 2008-03-12 Frédéric Bernon, Jonathan Larmour + * api_msg.c, contrib/apps/ping.c: Fix bug #22530 "api_msg.c's + recv_raw() does not consume data", and the ping sample (with + LWIP_SOCKET=1, the code did the wrong supposition that lwip_recvfrom + returned the IP payload, without the IP header). + + 2008-03-04 Jonathan Larmour + * mem.c, stats.c, mem.h: apply patch #6414 to avoid compiler errors + and/or warnings on some systems where mem_size_t and size_t differ. + * pbuf.c, ppp.c: Fix warnings on some systems with mem_malloc. + + 2008-03-04 Kieran Mansley (contributions by others) + * Numerous small compiler error/warning fixes from contributions to + mailing list after 1.3.0 release candidate made. + + 2008-01-25 Cui hengbin (integrated by Frédéric Bernon) + * dns.c: Fix bug #22108 "DNS problem" caused by unaligned structures. + + 2008-01-15 Kieran Mansley + * tcp_out.c: BUG20511. Modify persist timer to start when we are + prevented from sending by a small send window, not just a zero + send window. + + 2008-01-09 Jonathan Larmour + * opt.h, ip.c: Rename IP_OPTIONS define to IP_OPTIONS_ALLOWED to avoid + conflict with Linux system headers. + + 2008-01-06 Jonathan Larmour + * dhcp.c: fix bug #19927: "DHCP NACK problem" by clearing any existing set IP + address entirely on receiving a DHCPNAK, and restarting discovery. + + 2007-12-21 Simon Goldschmidt + * sys.h, api_lib.c, api_msg.c, sockets.c: fix bug #21698: "netconn->recv_avail + is not protected" by using new macros for interlocked access to modify/test + netconn->recv_avail. + + 2007-12-20 Kieran Mansley (based on patch from Oleg Tyshev) + * tcp_in.c: fix bug# 21535 (nrtx not reset correctly in SYN_SENT state) + + 2007-12-20 Kieran Mansley (based on patch from Per-Henrik Lundbolm) + * tcp.c, tcp_in.c, tcp_out.c, tcp.h: fix bug #20199 (better handling + of silly window avoidance and prevent lwIP from shrinking the window) + + 2007-12-04 Simon Goldschmidt + * tcp.c, tcp_in.c: fix bug #21699 (segment leak in ooseq processing when last + data packet was lost): add assert that all segment lists are empty in + tcp_pcb_remove before setting pcb to CLOSED state; don't directly set CLOSED + state from LAST_ACK in tcp_process + + 2007-12-02 Simon Goldschmidt + * sockets.h: fix bug #21654: exclude definition of struct timeval from #ifndef FD_SET + If including for system-struct timeval, LWIP_TIMEVAL_PRIVATE now + has to be set to 0 in lwipopts.h + + 2007-12-02 Simon Goldschmidt + * api_msg.c, api_lib.c: fix bug #21656 (recvmbox problem in netconn API): always + allocate a recvmbox in netconn_new_with_proto_and_callback. For a tcp-listen + netconn, this recvmbox is later freed and a new mbox is allocated for acceptmbox. + This is a fix for thread-safety and allocates all items needed for a netconn + when the netconn is created. + + 2007-11-30 Simon Goldschmidt + * udp.c: first attempt to fix bug #21655 (DHCP doesn't work reliably with multiple + netifs): if LWIP_DHCP is enabled, UDP packets to DHCP_CLIENT_PORT are passed + to netif->dhcp->pcb only (if that exists) and not to any other pcb for the same + port (only solution to let UDP pcbs 'bind' to a netif instead of an IP address) + + 2007-11-27 Simon Goldschmidt + * ip.c: fixed bug #21643 (udp_send/raw_send don't fail if netif is down) by + letting ip_route only use netifs that are up. + + 2007-11-27 Simon Goldschmidt + * err.h, api_lib.c, api_msg.c, sockets.c: Changed error handling: ERR_MEM, ERR_BUF + and ERR_RTE are seen as non-fatal, all other errors are fatal. netconns and + sockets block most operations once they have seen a fatal error. + + 2007-11-27 Simon Goldschmidt + * udp.h, udp.c, dhcp.c: Implemented new function udp_sendto_if which takes the + netif to send as an argument (to be able to send on netifs that are down). + + 2007-11-26 Simon Goldschmidt + * tcp_in.c: Fixed bug #21582: pcb->acked accounting can be wrong when ACKs + arrive out-of-order + + 2007-11-21 Simon Goldschmidt + * tcp.h, tcp_out.c, api_msg.c: Fixed bug #20287: tcp_output_nagle sends too early + Fixed the nagle algorithm; nagle now also works for all raw API applications + and has to be explicitly disabled with 'tcp_pcb->flags |= TF_NODELAY' + + 2007-11-12 Frédéric Bernon + * sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c: Fixed bug #20900. Now, most + of the netconn_peer and netconn_addr processing is done inside tcpip_thread + context in do_getaddr. + + 2007-11-10 Simon Goldschmidt + * etharp.c: Fixed bug: assert fired when MEMP_ARP_QUEUE was empty (which can + happen any time). Now the packet simply isn't enqueued when out of memory. + + 2007-11-01 Simon Goldschmidt + * tcp.c, tcp_in.c: Fixed bug #21494: The send mss (pcb->mss) is set to 536 (or + TCP_MSS if that is smaller) as long as no MSS option is received from the + remote host. + + 2007-11-01 Simon Goldschmidt + * tcp.h, tcp.c, tcp_in.c: Fixed bug #21491: The MSS option sent (with SYN) + is now based on TCP_MSS instead of pcb->mss (on passive open now effectively + sending our configured TCP_MSS instead of the one received). + + 2007-11-01 Simon Goldschmidt + * tcp_in.c: Fixed bug #21181: On active open, the initial congestion window was + calculated based on the configured TCP_MSS, not on the MSS option received + with SYN+ACK. + + 2007-10-09 Simon Goldschmidt + * udp.c, inet.c, inet.h: Fixed UDPLite: send: Checksum was always generated too + short and also was generated wrong if checksum coverage != tot_len; + receive: checksum was calculated wrong if checksum coverage != tot_len + + 2007-10-08 Simon Goldschmidt + * mem.c: lfree was not updated in mem_realloc! + + 2007-10-07 Frédéric Bernon + * sockets.c, api.h, api_lib.c: First step to fix "bug #20900 : Potential + crash error problem with netconn_peer & netconn_addr". VERY IMPORTANT: + this change cause an API breakage for netconn_addr, since a parameter + type change. Any compiler should cause an error without any changes in + yours netconn_peer calls (so, it can't be a "silent change"). It also + reduce a little bit the footprint for socket layer (lwip_getpeername & + lwip_getsockname use now a common lwip_getaddrname function since + netconn_peer & netconn_addr have the same parameters). + + 2007-09-20 Simon Goldschmidt + * tcp.c: Fixed bug #21080 (tcp_bind without check pcbs in TIME_WAIT state) + by checking tcp_tw_pcbs also + + 2007-09-19 Simon Goldschmidt + * icmp.c: Fixed bug #21107 (didn't reset IP TTL in ICMP echo replies) + + 2007-09-15 Mike Kleshov + * mem.c: Fixed bug #21077 (inaccuracy in calculation of lwip_stat.mem.used) + + 2007-09-06 Frédéric Bernon + * several-files: replace some #include "arch/cc.h" by "lwip/arch.h", or simply remove + it as long as "lwip/opt.h" is included before (this one include "lwip/debug.h" which + already include "lwip/arch.h"). Like that, default defines are provided by "lwip/arch.h" + if they are not defined in cc.h, in the same spirit than "lwip/opt.h" for lwipopts.h. + + 2007-08-30 Frédéric Bernon + * igmp.h, igmp.c: Some changes to remove some redundant code, add some traces, + and fix some coding style. + + 2007-08-28 Frédéric Bernon + * tcpip.c: Fix TCPIP_MSG_INPKT processing: now, tcpip_input can be used for any + kind of packets. These packets are considered like Ethernet packets (payload + pointing to ethhdr) if the netif got the NETIF_FLAG_ETHARP flag. Else, packets + are considered like IP packets (payload pointing to iphdr). + + 2007-08-27 Frédéric Bernon + * api.h, api_lib.c, api_msg.c: First fix for "bug #20900 : Potential crash error + problem with netconn_peer & netconn_addr". Introduce NETCONN_LISTEN netconn_state + and remove obsolete ones (NETCONN_RECV & NETCONN_ACCEPT). + + 2007-08-24 Kieran Mansley + * inet.c Modify (acc >> 16) test to ((acc >> 16) != 0) to help buggy + compiler (Paradigm C++) + + 2007-08-09 Frédéric Bernon, Bill Florac + * stats.h, stats.c, igmp.h, igmp.c, opt.h: Fix for bug #20503 : IGMP Improvement. + Introduce IGMP_STATS to centralize statistics management. + + 2007-08-09 Frédéric Bernon, Bill Florac + * udp.c: Fix for bug #20503 : IGMP Improvement. Enable to receive a multicast + packet on a udp pcb binded on an netif's IP address, and not on "any". + + 2007-08-09 Frédéric Bernon, Bill Florac + * igmp.h, igmp.c, ip.c: Fix minor changes from bug #20503 : IGMP Improvement. + This is mainly on using lookup/lookfor, and some coding styles... + + 2007-07-26 Frédéric Bernon (and "thedoctor") + * igmp.c: Fix bug #20595 to accept IGMPv3 "Query" messages. + + 2007-07-25 Simon Goldschmidt + * api_msg.c, tcp.c: Another fix for bug #20021: by not returning an error if + tcp_output fails in tcp_close, the code in do_close_internal gets simpler + (tcp_output is called again later from tcp timers). + + 2007-07-25 Simon Goldschmidt + * ip_frag.c: Fixed bug #20429: use the new pbuf_copy_partial instead of the old + copy_from_pbuf, which illegally modified the given pbuf. + + 2007-07-25 Simon Goldschmidt + * tcp_out.c: tcp_enqueue: pcb->snd_queuelen didn't work for chaine PBUF_RAMs: + changed snd_queuelen++ to snd_queuelen += pbuf_clen(p). + + 2007-07-24 Simon Goldschmidt + * api_msg.c, tcp.c: Fix bug #20480: Check the pcb passed to tcp_listen() for the + correct state (must be CLOSED). + + 2007-07-13 Thomas Taranowski (commited by Jared Grubb) + * memp.c: Fix bug #20478: memp_malloc returned NULL+MEMP_SIZE on failed + allocation. It now returns NULL. + + 2007-07-13 Frédéric Bernon + * api_msg.c: Fix bug #20318: api_msg "recv" callbacks don't call pbuf_free in + all error cases. + + 2007-07-13 Frédéric Bernon + * api_msg.c: Fix bug #20315: possible memory leak problem if tcp_listen failed, + because current code doesn't follow rawapi.txt documentation. + + 2007-07-13 Kieran Mansley + * src/core/tcp_in.c Apply patch#5741 from Oleg Tyshev to fix bug in + out of sequence processing of received packets + + 2007-07-03 Simon Goldschmidt + * nearly-all-files: Added assertions where PBUF_RAM pbufs are used and an + assumption is made that this pbuf is in one piece (i.e. not chained). These + assumptions clash with the possibility of converting to fully pool-based + pbuf implementations, where PBUF_RAM pbufs might be chained. + + 2007-07-03 Simon Goldschmidt + * api.h, api_lib.c, api_msg.c: Final fix for bug #20021 and some other problems + when closing tcp netconns: removed conn->sem, less context switches when + closing, both netconn_close and netconn_delete should safely close tcp + connections. + + 2007-07-02 Simon Goldschmidt + * ipv4/ip.h, ipv6/ip.h, opt.h, netif.h, etharp.h, ipv4/ip.c, netif.c, raw.c, + tcp_out.c, udp.c, etharp.c: Added option LWIP_NETIF_HWADDRHINT (default=off) + to cache ARP table indices with each pcb instead of single-entry cache for + the complete stack. + + 2007-07-02 Simon Goldschmidt + * tcp.h, tcp.c, tcp_in.c, tcp_out.c: Added some ASSERTS and casts to prevent + warnings when assigning to smaller types. + + 2007-06-28 Simon Goldschmidt + * tcp_out.c: Added check to prevent tcp_pcb->snd_queuelen from overflowing. + + 2007-06-28 Simon Goldschmidt + * tcp.h: Fixed bug #20287: Fixed nagle algorithm (sending was done too early if + a segment contained chained pbufs) + + 2007-06-28 Frédéric Bernon + * autoip.c: replace most of rand() calls by a macro LWIP_AUTOIP_RAND which compute + a "pseudo-random" value based on netif's MAC and some autoip fields. It's always + possible to define this macro in your own lwipopts.h to always use C library's + rand(). Note that autoip_create_rand_addr doesn't use this macro. + + 2007-06-28 Frédéric Bernon + * netifapi.h, netifapi.c, tcpip.h, tcpip.c: Update code to handle the option + LWIP_TCPIP_CORE_LOCKING, and do some changes to be coherent with last modifications + in api_lib/api_msg (use pointers and not type with table, etc...) + + 2007-06-26 Simon Goldschmidt + * udp.h: Fixed bug #20259: struct udp_hdr was lacking the packin defines. + + 2007-06-25 Simon Goldschmidt + * udp.c: Fixed bug #20253: icmp_dest_unreach was called with a wrong p->payload + for udp packets with no matching pcb. + + 2007-06-25 Simon Goldschmidt + * udp.c: Fixed bug #20220: UDP PCB search in udp_input(): a non-local match + could get udp input packets if the remote side matched. + + 2007-06-13 Simon Goldschmidt + * netif.c: Fixed bug #20180 (TCP pcbs listening on IP_ADDR_ANY could get + changed in netif_set_ipaddr if previous netif->ip_addr.addr was 0. + + 2007-06-13 Simon Goldschmidt + * api_msg.c: pcb_new sets conn->err if protocol is not implemented + -> netconn_new_..() does not allocate a new connection for unsupported + protocols. + + 2007-06-13 Frédéric Bernon, Simon Goldschmidt + * api_lib.c: change return expression in netconn_addr and netconn_peer, because + conn->err was reset to ERR_OK without any reasons (and error was lost)... + + 2007-06-13 Frédéric Bernon, Matthias Weisser + * opt.h, mem.h, mem.c, memp.c, pbuf.c, ip_frag.c, vj.c: Fix bug #20162. Rename + MEM_ALIGN in LWIP_MEM_ALIGN and MEM_ALIGN_SIZE in LWIP_MEM_ALIGN_SIZE to avoid + some macro names collision with some OS macros. + + 2007-06-11 Simon Goldschmidt + * udp.c: UDP Lite: corrected the use of chksum_len (based on RFC3828: if it's 0, + create checksum over the complete packet. On RX, if it's < 8 (and not 0), + discard the packet. Also removed the duplicate 'udphdr->chksum = 0' for both + UDP & UDP Lite. + + 2007-06-11 Srinivas Gollakota & Oleg Tyshev + * tcp_out.c: Fix for bug #20075 : "A problem with keep-alive timer and TCP flags" + where TCP flags wasn't initialized in tcp_keepalive. + + 2007-06-03 Simon Goldschmidt + * udp.c: udp_input(): Input pbuf was not freed if pcb had no recv function + registered, p->payload was modified without modifying p->len if sending + icmp_dest_unreach() (had no negative effect but was definitively wrong). + + 2007-06-03 Simon Goldschmidt + * icmp.c: Corrected bug #19937: For responding to an icmp echo request, icmp + re-used the input pbuf even if that didn't have enough space to include the + link headers. Now the space is tested and a new pbuf is allocated for the + echo response packet if the echo request pbuf isn't big enough. + + 2007-06-01 Simon Goldschmidt + * sockets.c: Checked in patch #5914: Moved sockopt processing into tcpip_thread. + + 2007-05-23 Frédéric Bernon + * api_lib.c, sockets.c: Fixed bug #5958 for netconn_listen (acceptmbox only + allocated by do_listen if success) and netconn_accept errors handling. In + most of api_lib functions, we replace some errors checkings like "if (conn==NULL)" + by ASSERT, except for netconn_delete. + + 2007-05-23 Frédéric Bernon + * api_lib.c: Fixed bug #5957 "Safe-thread problem inside netconn_recv" to return + an error code if it's impossible to fetch a pbuf on a TCP connection (and not + directly close the recvmbox). + + 2007-05-22 Simon Goldschmidt + * tcp.c: Fixed bug #1895 (tcp_bind not correct) by introducing a list of + bound but unconnected (and non-listening) tcp_pcbs. + + 2007-05-22 Frédéric Bernon + * sys.h, sys.c, api_lib.c, tcpip.c: remove sys_mbox_fetch_timeout() (was only + used for LWIP_SO_RCVTIMEO option) and use sys_arch_mbox_fetch() instead of + sys_mbox_fetch() in api files. Now, users SHOULD NOT use internal lwIP features + like "sys_timeout" in their application threads. + + 2007-05-22 Frédéric Bernon + * api.h, api_lib.c, api_msg.h, api_msg.c: change the struct api_msg_msg to see + which parameters are used by which do_xxx function, and to avoid "misusing" + parameters (patch #5938). + + 2007-05-22 Simon Goldschmidt + * api_lib.c, api_msg.c, raw.c, api.h, api_msg.h, raw.h: Included patch #5938: + changed raw_pcb.protocol from u16_t to u8_t since for IPv4 and IPv6, proto + is only 8 bits wide. This affects the api, as there, the protocol was + u16_t, too. + + 2007-05-18 Simon Goldschmidt + * memp.c: addition to patch #5913: smaller pointer was returned but + memp_memory was the same size -> did not save memory. + + 2007-05-16 Simon Goldschmidt + * loopif.c, slipif.c: Fix bug #19729: free pbuf if netif->input() returns + != ERR_OK. + + 2007-05-16 Simon Goldschmidt + * api_msg.c, udp.c: If a udp_pcb has a local_ip set, check if it is the same + as the one of the netif used for sending to prevent sending from old + addresses after a netif address gets changed (partly fixes bug #3168). + + 2007-05-16 Frédéric Bernon + * tcpip.c, igmp.h, igmp.c: Fixed bug "#19800 : IGMP: igmp_tick() will not work + with NO_SYS=1". Note that igmp_init is always in tcpip_thread (and not in + tcpip_init) because we have to be sure that network interfaces are already + added (mac filter is updated only in igmp_init for the moment). + + 2007-05-16 Simon Goldschmidt + * mem.c, memp.c: Removed semaphores from memp, changed sys_sem_wait calls + into sys_arch_sem_wait calls to prevent timers from running while waiting + for the heap. This fixes bug #19167. + + 2007-05-13 Simon Goldschmidt + * tcp.h, sockets.h, sockets.c: Fixed bug from patch #5865 by moving the defines + for socket options (lwip_set/-getsockopt) used with level IPPROTO_TCP from + tcp.h to sockets.h. + + 2007-05-07 Simon Goldschmidt + * mem.c: Another attempt to fix bug #17922. + + 2007-05-04 Simon Goldschmidt + * pbuf.c, pbuf.h, etharp.c: Further update to ARP queueing: Changed pbuf_copy() + implementation so that it can be reused (don't allocate the target + pbuf inside pbuf_copy()). + + 2007-05-04 Simon Goldschmidt + * memp.c: checked in patch #5913: in memp_malloc() we can return memp as mem + to save a little RAM (next pointer of memp is not used while not in pool). + + 2007-05-03 "maq" + * sockets.c: Fix ioctl FIONREAD when some data remains from last recv. + (patch #3574). + + 2007-04-23 Simon Goldschmidt + * loopif.c, loopif.h, opt.h, src/netif/FILES: fix bug #2595: "loopif results + in NULL reference for incoming TCP packets". Loopif has to be configured + (using LWIP_LOOPIF_MULTITHREADING) to directly call netif->input() + (multithreading environments, e.g. netif->input() = tcpip_input()) or + putting packets on a list that is fed to the stack by calling loopif_poll() + (single-thread / NO_SYS / polling environment where e.g. + netif->input() = ip_input). + + 2007-04-17 Jonathan Larmour + * pbuf.c: Use s32_t in pbuf_realloc(), as an s16_t can't reliably hold + the difference between two u16_t's. + * sockets.h: FD_SETSIZE needs to match number of sockets, which is + MEMP_NUM_NETCONN in sockets.c right now. + + 2007-04-12 Jonathan Larmour + * icmp.c: Reset IP header TTL in ICMP ECHO responses (bug #19580). + + 2007-04-12 Kieran Mansley + * tcp.c, tcp_in.c, tcp_out.c, tcp.h: Modify way the retransmission + timer is reset to fix bug#19434, with help from Oleg Tyshev. + + 2007-04-11 Simon Goldschmidt + * etharp.c, pbuf.c, pbuf.h: 3rd fix for bug #11400 (arp-queuing): More pbufs than + previously thought need to be copied (everything but PBUF_ROM!). Cleaned up + pbuf.c: removed functions no needed any more (by etharp). + + 2007-04-11 Kieran Mansley + * inet.c, ip_addr.h, sockets.h, sys.h, tcp.h: Apply patch #5745: Fix + "Constant is long" warnings with 16bit compilers. Contributed by + avatar@mmlab.cse.yzu.edu.tw + + 2007-04-05 Frédéric Bernon, Jonathan Larmour + * api_msg.c: Fix bug #16830: "err_tcp() posts to connection mailbox when no pend on + the mailbox is active". Now, the post is only done during a connect, and do_send, + do_write and do_join_leave_group don't do anything if a previous error was signaled. + + 2007-04-03 Frédéric Bernon + * ip.c: Don't set the IP_DF ("Don't fragment") flag in the IP header in IP output + packets. See patch #5834. + + 2007-03-30 Frédéric Bernon + * api_msg.c: add a "pcb_new" helper function to avoid redundant code, and to add + missing pcb allocations checking (in do_bind, and for each raw_new). Fix style. + + 2007-03-30 Frédéric Bernon + * most of files: prefix all debug.h define with "LWIP_" to avoid any conflict with + others environment defines (these were too "generic"). + + 2007-03-28 Frédéric Bernon + * api.h, api_lib.c, sockets.c: netbuf_ref doesn't check its internal pbuf_alloc call + result and can cause a crash. lwip_send now check netbuf_ref result. + + 2007-03-28 Simon Goldschmidt + * sockets.c Remove "#include " from sockets.c to avoid multiple + definition of macros (in errno.h and lwip/arch.h) if LWIP_PROVIDE_ERRNO is + defined. This is the way it should have been already (looking at + doc/sys_arch.txt) + + 2007-03-28 Kieran Mansley + * opt.h Change default PBUF_POOL_BUFSIZE (again) to accomodate default MSS + + IP and TCP headers *and* physical link headers + + 2007-03-26 Frédéric Bernon (based on patch from Dmitry Potapov) + * api_lib.c: patch for netconn_write(), fixes a possible race condition which cause + to send some garbage. It is not a definitive solution, but the patch does solve + the problem for most cases. + + 2007-03-22 Frédéric Bernon + * api_msg.h, api_msg.c: Remove obsolete API_MSG_ACCEPT and do_accept (never used). + + 2007-03-22 Frédéric Bernon + * api_lib.c: somes resources couldn't be freed if there was errors during + netconn_new_with_proto_and_callback. + + 2007-03-22 Frédéric Bernon + * ethernetif.c: update netif->input calls to check return value. In older ports, + it's a good idea to upgrade them, even if before, there could be another problem + (access to an uninitialized mailbox). + + 2007-03-21 Simon Goldschmidt + * sockets.c: fixed bug #5067 (essentialy a signed/unsigned warning fixed + by casting to unsigned). + + 2007-03-21 Frédéric Bernon + * api_lib.c, api_msg.c, tcpip.c: integrate sys_mbox_fetch(conn->mbox, NULL) calls from + api_lib.c to tcpip.c's tcpip_apimsg(). Now, use a local variable and not a + dynamic one from memp to send tcpip_msg to tcpip_thread in a synchrone call. + Free tcpip_msg from tcpip_apimsg is not done in tcpip_thread. This give a + faster and more reliable communication between api_lib and tcpip. + + 2007-03-21 Frédéric Bernon + * opt.h: Add LWIP_NETIF_CALLBACK (to avoid compiler warning) and set it to 0. + + 2007-03-21 Frédéric Bernon + * api_msg.c, igmp.c, igmp.h: Fix C++ style comments + + 2007-03-21 Kieran Mansley + * opt.h Change default PBUF_POOL_BUFSIZE to accomodate default MSS + + IP and TCP headers + + 2007-03-21 Kieran Mansley + * Fix all uses of pbuf_header to check the return value. In some + cases just assert if it fails as I'm not sure how to fix them, but + this is no worse than before when they would carry on regardless + of the failure. + + 2007-03-21 Kieran Mansley + * sockets.c, igmp.c, igmp.h, memp.h: Fix C++ style comments and + comment out missing header include in icmp.c + + 2007-03-20 Frédéric Bernon + * memp.h, stats.c: Fix stats_display function where memp_names table wasn't + synchronized with memp.h. + + 2007-03-20 Frédéric Bernon + * tcpip.c: Initialize tcpip's mbox, and verify if initialized in tcpip_input, + tcpip_ethinput, tcpip_callback, tcpip_apimsg, to fix a init problem with + network interfaces. Also fix a compiler warning. + + 2007-03-20 Kieran Mansley + * udp.c: Only try and use pbuf_header() to make space for headers if + not a ROM or REF pbuf. + + 2007-03-19 Frédéric Bernon + * api_msg.h, api_msg.c, tcpip.h, tcpip.c: Add return types to tcpip_apimsg() + and api_msg_post(). + + 2007-03-19 Frédéric Bernon + * Remove unimplemented "memp_realloc" function from memp.h. + + 2007-03-11 Simon Goldschmidt + * pbuf.c: checked in patch #5796: pbuf_alloc: len field claculation caused + memory corruption. + + 2007-03-11 Simon Goldschmidt (based on patch from Dmitry Potapov) + * api_lib.c, sockets.c, api.h, api_msg.h, sockets.h: Fixed bug #19251 + (missing `const' qualifier in socket functions), to get more compatible to + standard POSIX sockets. + + 2007-03-11 Frédéric Bernon (based on patch from Dmitry Potapov) + * sockets.c: Add asserts inside bind, connect and sendto to check input + parameters. Remove excessive set_errno() calls after get_socket(), because + errno is set inside of get_socket(). Move last sock_set_errno() inside + lwip_close. + + 2007-03-09 Simon Goldschmidt + * memp.c: Fixed bug #11400: New etharp queueing introduced bug: memp_memory + was allocated too small. + + 2007-03-06 Simon Goldschmidt + * tcpip.c: Initialize dhcp timers in tcpip_thread (if LWIP_DHCP) to protect + the stack from concurrent access. + + 2007-03-06 Frédéric Bernon, Dmitry Potapov + * tcpip.c, ip_frag.c, ethernetif.c: Fix some build problems, and a redundancy + call to "lwip_stats.link.recv++;" in low_level_input() & ethernetif_input(). + + 2007-03-06 Simon Goldschmidt + * ip_frag.c, ip_frag.h: Reduce code size: don't include code in those files + if IP_FRAG == 0 and IP_REASSEMBLY == 0 + + 2007-03-06 Frédéric Bernon, Simon Goldschmidt + * opt.h, ip_frag.h, tcpip.h, tcpip.c, ethernetif.c: add new configuration + option named ETHARP_TCPIP_ETHINPUT, which enable the new tcpip_ethinput. + Allow to do ARP processing for incoming packets inside tcpip_thread + (protecting ARP layer against concurrent access). You can also disable + old code using tcp_input with new define ETHARP_TCPIP_INPUT set to 0. + Older ports have to use tcpip_ethinput. + + 2007-03-06 Simon Goldschmidt (based on patch from Dmitry Potapov) + * err.h, err.c: fixed compiler warning "initialization dircards qualifiers + from pointer target type" + + 2007-03-05 Frédéric Bernon + * opt.h, sockets.h: add new configuration options (LWIP_POSIX_SOCKETS_IO_NAMES, + ETHARP_TRUST_IP_MAC, review SO_REUSE) + + 2007-03-04 Frédéric Bernon + * api_msg.c: Remove some compiler warnings : parameter "pcb" was never + referenced. + + 2007-03-04 Frédéric Bernon + * api_lib.c: Fix "[patch #5764] api_lib.c cleanup: after patch #5687" (from + Dmitry Potapov). + The api_msg struct stay on the stack (not moved to netconn struct). + + 2007-03-04 Simon Goldschmidt (based on patch from Dmitry Potapov) + * pbuf.c: Fix BUG#19168 - pbuf_free can cause deadlock (if + SYS_LIGHTWEIGHT_PROT=1 & freeing PBUF_RAM when mem_sem is not available) + Also fixed cast warning in pbuf_alloc() + + 2007-03-04 Simon Goldschmidt + * etharp.c, etharp.h, memp.c, memp.h, opt.h: Fix BUG#11400 - don't corrupt + existing pbuf chain when enqueuing multiple pbufs to a pending ARP request + + 2007-03-03 Frédéric Bernon + * udp.c: remove obsolete line "static struct udp_pcb *pcb_cache = NULL;" + It is static, and never used in udp.c except udp_init(). + + 2007-03-02 Simon Goldschmidt + * tcpip.c: Moved call to ip_init(), udp_init() and tcp_init() from + tcpip_thread() to tcpip_init(). This way, raw API connections can be + initialized before tcpip_thread is running (e.g. before OS is started) + + 2007-03-02 Frédéric Bernon + * rawapi.txt: Fix documentation mismatch with etharp.h about etharp_tmr's call + interval. + + 2007-02-28 Kieran Mansley + * pbuf.c: Fix BUG#17645 - ensure pbuf payload pointer is not moved + outside the region of the pbuf by pbuf_header() + + 2007-02-28 Kieran Mansley + * sockets.c: Fix BUG#19161 - ensure milliseconds timeout is non-zero + when supplied timeout is also non-zero + +(STABLE-1.2.0) + + 2006-12-05 Leon Woestenberg + * CHANGELOG: Mention STABLE-1.2.0 release. + + ++ New features: + + 2006-12-01 Christiaan Simons + * mem.h, opt.h: Added MEM_LIBC_MALLOC option. + Note this is a workaround. Currently I have no other options left. + + 2006-10-26 Christiaan Simons (accepted patch by Jonathan Larmour) + * ipv4/ip_frag.c: rename MAX_MTU to IP_FRAG_MAX_MTU and move define + to include/lwip/opt.h. + * ipv4/lwip/ip_frag.h: Remove unused IP_REASS_INTERVAL. + Move IP_REASS_MAXAGE and IP_REASS_BUFSIZE to include/lwip/opt.h. + * opt.h: Add above new options. + + 2006-08-18 Christiaan Simons + * tcp_{in,out}.c: added SNMP counters. + * ipv4/ip.c: added SNMP counters. + * ipv4/ip_frag.c: added SNMP counters. + + 2006-08-08 Christiaan Simons + * etharp.{c,h}: added etharp_find_addr() to read + (stable) ethernet/IP address pair from ARP table + + 2006-07-14 Christiaan Simons + * mib_structs.c: added + * include/lwip/snmp_structs.h: added + * netif.{c,h}, netif/ethernetif.c: added SNMP statistics to netif struct + + 2006-07-06 Christiaan Simons + * snmp/asn1_{enc,dec}.c added + * snmp/mib2.c added + * snmp/msg_{in,out}.c added + * include/lwip/snmp_asn1.h added + * include/lwip/snmp_msg.h added + * doc/snmp_agent.txt added + + 2006-03-29 Christiaan Simons + * inet.c, inet.h: Added platform byteswap support. + Added LWIP_PLATFORM_BYTESWAP define (defaults to 0) and + optional LWIP_PLATFORM_HTONS(), LWIP_PLATFORM_HTONL() macros. + + ++ Bug fixes: + + 2006-11-30 Christiaan Simons + * dhcp.c: Fixed false triggers of request_timeout. + + 2006-11-28 Christiaan Simons + * netif.c: In netif_add() fixed missing clear of ip_addr, netmask, gw and flags. + + 2006-10-11 Christiaan Simons + * api_lib.c etharp.c, ip.c, memp.c, stats.c, sys.{c,h} tcp.h: + Partially accepted patch #5449 for ANSI C compatibility / build fixes. + * ipv4/lwip/ip.h ipv6/lwip/ip.h: Corrected UDP-Lite protocol + identifier from 170 to 136 (bug #17574). + + 2006-10-10 Christiaan Simons + * api_msg.c: Fixed Nagle algorithm as reported by Bob Grice. + + 2006-08-17 Christiaan Simons + * udp.c: Fixed bug #17200, added check for broadcast + destinations for PCBs bound to a unicast address. + + 2006-08-07 Christiaan Simons + * api_msg.c: Flushing TCP output in do_close() (bug #15926). + + 2006-06-27 Christiaan Simons + * api_msg.c: Applied patch for cold case (bug #11135). + In accept_function() ensure newconn->callback is always initialized. + + 2006-06-15 Christiaan Simons + * mem.h: added MEM_SIZE_F alias to fix an ancient cold case (bug #1748), + facilitate printing of mem_size_t and u16_t statistics. + + 2006-06-14 Christiaan Simons + * api_msg.c: Applied patch #5146 to handle allocation failures + in accept() by Kevin Lawson. + + 2006-05-26 Christiaan Simons + * api_lib.c: Removed conn->sem creation and destruction + from netconn_write() and added sys_sem_new to netconn_new_*. + +(STABLE-1_1_1) + + 2006-03-03 Christiaan Simons + * ipv4/ip_frag.c: Added bound-checking assertions on ip_reassbitmap + access and added pbuf_alloc() return value checks. + + 2006-01-01 Leon Woestenberg + * tcp_{in,out}.c, tcp_out.c: Removed 'even sndbuf' fix in TCP, which is + now handled by the checksum routine properly. + + 2006-02-27 Leon Woestenberg + * pbuf.c: Fix alignment; pbuf_init() would not work unless + pbuf_pool_memory[] was properly aligned. (Patch by Curt McDowell.) + + 2005-12-20 Leon Woestenberg + * tcp.c: Remove PCBs which stay in LAST_ACK state too long. Patch + submitted by Mitrani Hiroshi. + + 2005-12-15 Christiaan Simons + * inet.c: Disabled the added summing routine to preserve code space. + + 2005-12-14 Leon Woestenberg + * tcp_in.c: Duplicate FIN ACK race condition fix by Kelvin Lawson. + Added Curt McDowell's optimized checksumming routine for future + inclusion. Need to create test case for unaliged, aligned, odd, + even length combination of cases on various endianess machines. + + 2005-12-09 Christiaan Simons + * inet.c: Rewrote standard checksum routine in proper portable C. + + 2005-11-25 Christiaan Simons + * udp.c tcp.c: Removed SO_REUSE hack. Should reside in socket code only. + * *.c: introduced cc.h LWIP_DEBUG formatters matching the u16_t, s16_t, + u32_t, s32_t typedefs. This solves most debug word-length assumes. + + 2005-07-17 Leon Woestenberg + * inet.c: Fixed unaligned 16-bit access in the standard checksum + routine by Peter Jolasson. + * slipif.c: Fixed implementation assumption of single-pbuf datagrams. + + 2005-02-04 Leon Woestenberg + * tcp_out.c: Fixed uninitialized 'queue' referenced in memerr branch. + * tcp_{out|in}.c: Applied patch fixing unaligned access. + + 2005-01-04 Leon Woestenberg + * pbuf.c: Fixed missing semicolon after LWIP_DEBUG statement. + + 2005-01-03 Leon Woestenberg + * udp.c: UDP pcb->recv() was called even when it was NULL. + +(STABLE-1_1_0) + + 2004-12-28 Leon Woestenberg + * etharp.*: Disabled multiple packets on the ARP queue. + This clashes with TCP queueing. + + 2004-11-28 Leon Woestenberg + * etharp.*: Fixed race condition from ARP request to ARP timeout. + Halved the ARP period, doubled the period counts. + ETHARP_MAX_PENDING now should be at least 2. This prevents + the counter from reaching 0 right away (which would allow + too little time for ARP responses to be received). + + 2004-11-25 Leon Woestenberg + * dhcp.c: Decline messages were not multicast but unicast. + * etharp.c: ETHARP_CREATE is renamed to ETHARP_TRY_HARD. + Do not try hard to insert arbitrary packet's source address, + etharp_ip_input() now calls etharp_update() without ETHARP_TRY_HARD. + etharp_query() now always DOES call ETHARP_TRY_HARD so that users + querying an address will see it appear in the cache (DHCP could + suffer from this when a server invalidly gave an in-use address.) + * ipv4/ip_addr.h: Renamed ip_addr_maskcmp() to _netcmp() as we are + comparing network addresses (identifiers), not the network masks + themselves. + * ipv4/ip_addr.c: ip_addr_isbroadcast() now checks that the given + IP address actually belongs to the network of the given interface. + + 2004-11-24 Kieran Mansley + * tcp.c: Increment pcb->snd_buf when ACK is received in SYN_SENT state. + +(STABLE-1_1_0-RC1) + + 2004-10-16 Kieran Mansley + * tcp.c: Add code to tcp_recved() to send an ACK (window update) immediately, + even if one is already pending, if the rcv_wnd is above a threshold + (currently TCP_WND/2). This avoids waiting for a timer to expire to send a + delayed ACK in order to open the window if the stack is only receiving data. + + 2004-09-12 Kieran Mansley + * tcp*.*: Retransmit time-out handling improvement by Sam Jansen. + + 2004-08-20 Tony Mountifield + * etharp.c: Make sure the first pbuf queued on an ARP entry + is properly ref counted. + + 2004-07-27 Tony Mountifield + * debug.h: Added (int) cast in LWIP_DEBUGF() to avoid compiler + warnings about comparison. + * pbuf.c: Stopped compiler complaining of empty if statement + when LWIP_DEBUGF() empty. Closed an unclosed comment. + * tcp.c: Stopped compiler complaining of empty if statement + when LWIP_DEBUGF() empty. + * ip.h Corrected IPH_TOS() macro: returns a byte, so doesn't need htons(). + * inet.c: Added a couple of casts to quiet the compiler. + No need to test isascii(c) before isdigit(c) or isxdigit(c). + + 2004-07-22 Tony Mountifield + * inet.c: Made data types consistent in inet_ntoa(). + Added casts for return values of checksum routines, to pacify compiler. + * ip_frag.c, tcp_out.c, sockets.c, pbuf.c + Small corrections to some debugging statements, to pacify compiler. + + 2004-07-21 Tony Mountifield + * etharp.c: Removed spurious semicolon and added missing end-of-comment. + * ethernetif.c Updated low_level_output() to match prototype for + netif->linkoutput and changed low_level_input() similarly for consistency. + * api_msg.c: Changed recv_raw() from int to u8_t, to match prototype + of raw_recv() in raw.h and so avoid compiler error. + * sockets.c: Added trivial (int) cast to keep compiler happier. + * ip.c, netif.c Changed debug statements to use the tidier ip4_addrN() macros. + +(STABLE-1_0_0) + + ++ Changes: + + 2004-07-05 Leon Woestenberg + * sockets.*: Restructured LWIP_PRIVATE_TIMEVAL. Make sure + your cc.h file defines this either 1 or 0. If non-defined, + defaults to 1. + * .c: Added and includes where used. + * etharp.c: Made some array indices unsigned. + + 2004-06-27 Leon Woestenberg + * netif.*: Added netif_set_up()/down(). + * dhcp.c: Changes to restart program flow. + + 2004-05-07 Leon Woestenberg + * etharp.c: In find_entry(), instead of a list traversal per candidate, do a + single-pass lookup for different candidates. Should exploit locality. + + 2004-04-29 Leon Woestenberg + * tcp*.c: Cleaned up source comment documentation for Doxygen processing. + * opt.h: ETHARP_ALWAYS_INSERT option removed to comply with ARP RFC. + * etharp.c: update_arp_entry() only adds new ARP entries when adviced to by + the caller. This deprecates the ETHARP_ALWAYS_INSERT overrule option. + + ++ Bug fixes: + + 2004-04-27 Leon Woestenberg + * etharp.c: Applied patch of bug #8708 by Toni Mountifield with a solution + suggested by Timmy Brolin. Fix for 32-bit processors that cannot access + non-aligned 32-bit words, such as soms 32-bit TCP/IP header fields. Fix + is to prefix the 14-bit Ethernet headers with two padding bytes. + + 2004-04-23 Leon Woestenberg + * ip_addr.c: Fix in the ip_addr_isbroadcast() check. + * etharp.c: Fixed the case where the packet that initiates the ARP request + is not queued, and gets lost. Fixed the case where the packets destination + address is already known; we now always queue the packet and perform an ARP + request. + +(STABLE-0_7_0) + + ++ Bug fixes: + + * Fixed TCP bug for SYN_SENT to ESTABLISHED state transition. + * Fixed TCP bug in dequeueing of FIN from out of order segment queue. + * Fixed two possible NULL references in rare cases. + +(STABLE-0_6_6) + + ++ Bug fixes: + + * Fixed DHCP which did not include the IP address in DECLINE messages. + + ++ Changes: + + * etharp.c has been hauled over a bit. + +(STABLE-0_6_5) + + ++ Bug fixes: + + * Fixed TCP bug induced by bad window resizing with unidirectional TCP traffic. + * Packets sent from ARP queue had invalid source hardware address. + + ++ Changes: + + * Pass-by ARP requests do now update the cache. + + ++ New features: + + * No longer dependent on ctype.h. + * New socket options. + * Raw IP pcb support. + +(STABLE-0_6_4) + + ++ Bug fixes: + + * Some debug formatters and casts fixed. + * Numereous fixes in PPP. + + ++ Changes: + + * DEBUGF now is LWIP_DEBUGF + * pbuf_dechain() has been re-enabled. + * Mentioned the changed use of CVS branches in README. + +(STABLE-0_6_3) + + ++ Bug fixes: + + * Fixed pool pbuf memory leak in pbuf_alloc(). + Occured if not enough PBUF_POOL pbufs for a packet pbuf chain. + Reported by Savin Zlobec. + + * PBUF_POOL chains had their tot_len field not set for non-first + pbufs. Fixed in pbuf_alloc(). + + ++ New features: + + * Added PPP stack contributed by Marc Boucher + + ++ Changes: + + * Now drops short packets for ICMP/UDP/TCP protocols. More robust. + + * ARP queueuing now queues the latest packet instead of the first. + This is the RFC recommended behaviour, but can be overridden in + lwipopts.h. + +(0.6.2) + + ++ Bugfixes: + + * TCP has been fixed to deal with the new use of the pbuf->ref + counter. + + * DHCP dhcp_inform() crash bug fixed. + + ++ Changes: + + * Removed pbuf_pool_free_cache and pbuf_pool_alloc_cache. Also removed + pbuf_refresh(). This has sped up pbuf pool operations considerably. + Implemented by David Haas. + +(0.6.1) + + ++ New features: + + * The packet buffer implementation has been enhanced to support + zero-copy and copy-on-demand for packet buffers which have their + payloads in application-managed memory. + Implemented by David Haas. + + Use PBUF_REF to make a pbuf refer to RAM. lwIP will use zero-copy + if an outgoing packet can be directly sent on the link, or perform + a copy-on-demand when necessary. + + The application can safely assume the packet is sent, and the RAM + is available to the application directly after calling udp_send() + or similar function. + + ++ Bugfixes: + + * ARP_QUEUEING should now correctly work for all cases, including + PBUF_REF. + Implemented by Leon Woestenberg. + + ++ Changes: + + * IP_ADDR_ANY is no longer a NULL pointer. Instead, it is a pointer + to a '0.0.0.0' IP address. + + * The packet buffer implementation is changed. The pbuf->ref counter + meaning has changed, and several pbuf functions have been + adapted accordingly. + + * netif drivers have to be changed to set the hardware address length field + that must be initialized correctly by the driver (hint: 6 for Ethernet MAC). + See the contrib/ports/c16x cs8900 driver as a driver example. + + * netif's have a dhcp field that must be initialized to NULL by the driver. + See the contrib/ports/c16x cs8900 driver as a driver example. + +(0.5.x) This file has been unmaintained up to 0.6.1. All changes are + logged in CVS but have not been explained here. + +(0.5.3) Changes since version 0.5.2 + + ++ Bugfixes: + + * memp_malloc(MEMP_API_MSG) could fail with multiple application + threads because it wasn't protected by semaphores. + + ++ Other changes: + + * struct ip_addr now packed. + + * The name of the time variable in arp.c has been changed to ctime + to avoid conflicts with the time() function. + +(0.5.2) Changes since version 0.5.1 + + ++ New features: + + * A new TCP function, tcp_tmr(), now handles both TCP timers. + + ++ Bugfixes: + + * A bug in tcp_parseopt() could cause the stack to hang because of a + malformed TCP option. + + * The address of new connections in the accept() function in the BSD + socket library was not handled correctly. + + * pbuf_dechain() did not update the ->tot_len field of the tail. + + * Aborted TCP connections were not handled correctly in all + situations. + + ++ Other changes: + + * All protocol header structs are now packed. + + * The ->len field in the tcp_seg structure now counts the actual + amount of data, and does not add one for SYN and FIN segments. + +(0.5.1) Changes since version 0.5.0 + + ++ New features: + + * Possible to run as a user process under Linux. + + * Preliminary support for cross platform packed structs. + + * ARP timer now implemented. + + ++ Bugfixes: + + * TCP output queue length was badly initialized when opening + connections. + + * TCP delayed ACKs were not sent correctly. + + * Explicit initialization of BSS segment variables. + + * read() in BSD socket library could drop data. + + * Problems with memory alignment. + + * Situations when all TCP buffers were used could lead to + starvation. + + * TCP MSS option wasn't parsed correctly. + + * Problems with UDP checksum calculation. + + * IP multicast address tests had endianess problems. + + * ARP requests had wrong destination hardware address. + + ++ Other changes: + + * struct eth_addr changed from u16_t[3] array to u8_t[6]. + + * A ->linkoutput() member was added to struct netif. + + * TCP and UDP ->dest_* struct members where changed to ->remote_*. + + * ntoh* macros are now null definitions for big endian CPUs. + +(0.5.0) Changes since version 0.4.2 + + ++ New features: + + * Redesigned operating system emulation layer to make porting easier. + + * Better control over TCP output buffers. + + * Documenation added. + + ++ Bugfixes: + + * Locking issues in buffer management. + + * Bugfixes in the sequential API. + + * IP forwarding could cause memory leakage. This has been fixed. + + ++ Other changes: + + * Directory structure somewhat changed; the core/ tree has been + collapsed. + +(0.4.2) Changes since version 0.4.1 + + ++ New features: + + * Experimental ARP implementation added. + + * Skeleton Ethernet driver added. + + * Experimental BSD socket API library added. + + ++ Bugfixes: + + * In very intense situations, memory leakage could occur. This has + been fixed. + + ++ Other changes: + + * Variables named "data" and "code" have been renamed in order to + avoid name conflicts in certain compilers. + + * Variable++ have in appliciable cases been translated to ++variable + since some compilers generate better code in the latter case. + +(0.4.1) Changes since version 0.4 + + ++ New features: + + * TCP: Connection attempts time out earlier than data + transmissions. Nagle algorithm implemented. Push flag set on the + last segment in a burst. + + * UDP: experimental support for UDP-Lite extensions. + + ++ Bugfixes: + + * TCP: out of order segments were in some cases handled incorrectly, + and this has now been fixed. Delayed acknowledgements was broken + in 0.4, has now been fixed. Binding to an address that is in use + now results in an error. Reset connections sometimes hung an + application; this has been fixed. + + * Checksum calculation sometimes failed for chained pbufs with odd + lengths. This has been fixed. + + * API: a lot of bug fixes in the API. The UDP API has been improved + and tested. Error reporting and handling has been + improved. Logical flaws and race conditions for incoming TCP + connections has been found and removed. + + * Memory manager: alignment issues. Reallocating memory sometimes + failed, this has been fixed. + + * Generic library: bcopy was flawed and has been fixed. + + ++ Other changes: + + * API: all datatypes has been changed from generic ones such as + ints, to specified ones such as u16_t. Functions that return + errors now have the correct type (err_t). + + * General: A lot of code cleaned up and debugging code removed. Many + portability issues have been fixed. + + * The license was changed; the advertising clause was removed. + + * C64 port added. + + * Thanks: Huge thanks go to Dagan Galarneau, Horst Garnetzke, Petri + Kosunen, Mikael Caleres, and Frits Wilmink for reporting and + fixing bugs! + +(0.4) Changes since version 0.3.1 + + * Memory management has been radically changed; instead of + allocating memory from a shared heap, memory for objects that are + rapidly allocated and deallocated is now kept in pools. Allocation + and deallocation from those memory pools is very fast. The shared + heap is still present but is used less frequently. + + * The memory, memory pool, and packet buffer subsystems now support + 4-, 2-, or 1-byte alignment. + + * "Out of memory" situations are handled in a more robust way. + + * Stack usage has been reduced. + + * Easier configuration of lwIP parameters such as memory usage, + TTLs, statistics gathering, etc. All configuration parameters are + now kept in a single header file "lwipopts.h". + + * The directory structure has been changed slightly so that all + architecture specific files are kept under the src/arch + hierarchy. + + * Error propagation has been improved, both in the protocol modules + and in the API. + + * The code for the RTXC architecture has been implemented, tested + and put to use. + + * Bugs have been found and corrected in the TCP, UDP, IP, API, and + the Internet checksum modules. + + * Bugs related to porting between a 32-bit and a 16-bit architecture + have been found and corrected. + + * The license has been changed slightly to conform more with the + original BSD license, including the advertisement clause. + +(0.3.1) Changes since version 0.3 + + * Fix of a fatal bug in the buffer management. Pbufs with allocated + RAM never returned the RAM when the pbuf was deallocated. + + * TCP congestion control, window updates and retransmissions did not + work correctly. This has now been fixed. + + * Bugfixes in the API. + +(0.3) Changes since version 0.2 + + * New and improved directory structure. All include files are now + kept in a dedicated include/ directory. + + * The API now has proper error handling. A new function, + netconn_err(), now returns an error code for the connection in + case of errors. + + * Improvements in the memory management subsystem. The system now + keeps a pointer to the lowest free memory block. A new function, + mem_malloc2() tries to allocate memory once, and if it fails tries + to free some memory and retry the allocation. + + * Much testing has been done with limited memory + configurations. lwIP now does a better job when overloaded. + + * Some bugfixes and improvements to the buffer (pbuf) subsystem. + + * Many bugfixes in the TCP code: + + - Fixed a bug in tcp_close(). + + - The TCP receive window was incorrectly closed when out of + sequence segments was received. This has been fixed. + + - Connections are now timed-out of the FIN-WAIT-2 state. + + - The initial congestion window could in some cases be too + large. This has been fixed. + + - The retransmission queue could in some cases be screwed up. This + has been fixed. + + - TCP RST flag now handled correctly. + + - Out of sequence data was in some cases never delivered to the + application. This has been fixed. + + - Retransmitted segments now contain the correct acknowledgment + number and advertised window. + + - TCP retransmission timeout backoffs are not correctly computed + (ala BSD). After a number of retransmissions, TCP now gives up + the connection. + + * TCP connections now are kept on three lists, one for active + connections, one for listening connections, and one for + connections that are in TIME-WAIT. This greatly speeds up the fast + timeout processing for sending delayed ACKs. + + * TCP now provides proper feedback to the application when a + connection has been successfully set up. + + * More comments have been added to the code. The code has also been + somewhat cleaned up. + +(0.2) Initial public release. diff --git a/component/common/network/lwip/lwip_v1.4.1/COPYING b/component/common/network/lwip/lwip_v1.4.1/COPYING new file mode 100644 index 0000000..e23898b --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/COPYING @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2001, 2002 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + + diff --git a/component/common/network/lwip/lwip_v1.4.1/FILES b/component/common/network/lwip/lwip_v1.4.1/FILES new file mode 100644 index 0000000..6625319 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/FILES @@ -0,0 +1,4 @@ +src/ - The source code for the lwIP TCP/IP stack. +doc/ - The documentation for lwIP. + +See also the FILES file in each subdirectory. diff --git a/component/common/network/lwip/lwip_v1.4.1/README b/component/common/network/lwip/lwip_v1.4.1/README new file mode 100644 index 0000000..a62cc4f --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/README @@ -0,0 +1,89 @@ +INTRODUCTION + +lwIP is a small independent implementation of the TCP/IP protocol +suite that has been developed by Adam Dunkels at the Computer and +Networks Architectures (CNA) lab at the Swedish Institute of Computer +Science (SICS). + +The focus of the lwIP TCP/IP implementation is to reduce the RAM usage +while still having a full scale TCP. This making lwIP suitable for use +in embedded systems with tens of kilobytes of free RAM and room for +around 40 kilobytes of code ROM. + +FEATURES + + * IP (Internet Protocol) including packet forwarding over multiple network + interfaces + * ICMP (Internet Control Message Protocol) for network maintenance and debugging + * IGMP (Internet Group Management Protocol) for multicast traffic management + * UDP (User Datagram Protocol) including experimental UDP-lite extensions + * TCP (Transmission Control Protocol) with congestion control, RTT estimation + and fast recovery/fast retransmit + * Specialized raw/native API for enhanced performance + * Optional Berkeley-like socket API + * DNS (Domain names resolver) + * SNMP (Simple Network Management Protocol) + * DHCP (Dynamic Host Configuration Protocol) + * AUTOIP (for IPv4, conform with RFC 3927) + * PPP (Point-to-Point Protocol) + * ARP (Address Resolution Protocol) for Ethernet + +LICENSE + +lwIP is freely available under a BSD license. + +DEVELOPMENT + +lwIP has grown into an excellent TCP/IP stack for embedded devices, +and developers using the stack often submit bug fixes, improvements, +and additions to the stack to further increase its usefulness. + +Development of lwIP is hosted on Savannah, a central point for +software development, maintenance and distribution. Everyone can +help improve lwIP by use of Savannah's interface, CVS and the +mailing list. A core team of developers will commit changes to the +CVS source tree. + +The lwIP TCP/IP stack is maintained in the 'lwip' CVS module and +contributions (such as platform ports) are in the 'contrib' module. + +See doc/savannah.txt for details on CVS server access for users and +developers. + +Last night's CVS tar ball can be downloaded from: + http://savannah.gnu.org/cvs.backups/lwip.tar.gz [CHANGED - NEEDS FIXING] + +The current CVS trees are web-browsable: + http://savannah.nongnu.org/cgi-bin/viewcvs/lwip/lwip/ + http://savannah.nongnu.org/cgi-bin/viewcvs/lwip/contrib/ + +Submit patches and bugs via the lwIP project page: + http://savannah.nongnu.org/projects/lwip/ + + +DOCUMENTATION + +The original out-dated homepage of lwIP and Adam Dunkels' papers on +lwIP are at the official lwIP home page: + http://www.sics.se/~adam/lwip/ + +Self documentation of the source code is regularly extracted from the +current CVS sources and is available from this web page: + http://www.nongnu.org/lwip/ + +There is now a constantly growin wiki about lwIP at + http://lwip.wikia.com/wiki/LwIP_Wiki + +Also, there are mailing lists you can subscribe at + http://savannah.nongnu.org/mail/?group=lwip +plus searchable archives: + http://lists.nongnu.org/archive/html/lwip-users/ + http://lists.nongnu.org/archive/html/lwip-devel/ + +Reading Adam's papers, the files in docs/, browsing the source code +documentation and browsing the mailing list archives is a good way to +become familiar with the design of lwIP. + +Adam Dunkels +Leon Woestenberg + diff --git a/component/common/network/lwip/lwip_v1.4.1/UPGRADING b/component/common/network/lwip/lwip_v1.4.1/UPGRADING new file mode 100644 index 0000000..6501107 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/UPGRADING @@ -0,0 +1,144 @@ +This file lists major changes between release versions that require +ports or applications to be changed. Use it to update a port or an +application written for an older version of lwIP to correctly work +with newer versions. + + +(CVS HEAD) + + * [Enter new changes just after this line - do not remove this line] + + ++ Application changes: + + * Replaced struct ip_addr by typedef ip_addr_t (struct ip_addr is kept for + compatibility to old applications, but will be removed in the future). + + * Renamed mem_realloc() to mem_trim() to prevent confusion with realloc() + + +++ Raw API: + * Changed the semantics of tcp_close() (since it was rather a + shutdown before): Now the application does *NOT* get any calls to the recv + callback (aside from NULL/closed) after calling tcp_close() + + * When calling tcp_abort() from a raw API TCP callback function, + make sure you return ERR_ABRT to prevent accessing unallocated memory. + (ERR_ABRT now means the applicaiton has called tcp_abort!) + + +++ Netconn API: + * Changed netconn_receive() and netconn_accept() to return + err_t, not a pointer to new data/netconn. + + +++ Socket API: + * LWIP_SO_RCVTIMEO: when accept() or recv() time out, they + now set errno to EWOULDBLOCK/EAGAIN, not ETIMEDOUT. + + * Added a minimal version of posix fctl() to have a + standardised way to set O_NONBLOCK for nonblocking sockets. + + +++ all APIs: + * correctly implemented SO(F)_REUSEADDR + + ++ Port changes + + +++ new files: + + * Added 4 new files: def.c, timers.c, timers.h, tcp_impl.h: + + * Moved stack-internal parts of tcp.h to tcp_impl.h, tcp.h now only contains + the actual application programmer's API + + * Separated timer implementation from sys.h/.c, moved to timers.h/.c; + Added timer implementation for NO_SYS==1, set NO_SYS_NO_TIMERS==1 if you + still want to use your own timer implementation for NO_SYS==0 (as before). + + +++ sys layer: + + * Converted mbox- and semaphore-functions to take pointers to sys_mbox_t/ + sys_sem_t; + + * Converted sys_mbox_new/sys_sem_new to take pointers and return err_t; + + * Added Mutex concept in sys_arch (define LWIP_COMPAT_MUTEX to let sys.h use + binary semaphores instead of mutexes - as before) + + +++ new options: + + * Don't waste memory when chaining segments, added option TCP_OVERSIZE to + prevent creating many small pbufs when calling tcp_write with many small + blocks of data. Instead, pbufs are allocated larger than needed and the + space is used for later calls to tcp_write. + + * Added LWIP_NETIF_TX_SINGLE_PBUF to always copy to try to create single pbufs + in tcp_write/udp_send. + + * Added an additional option LWIP_ETHERNET to support ethernet without ARP + (necessary for pure PPPoE) + + * Add MEMP_SEPARATE_POOLS to place memory pools in separate arrays. This may + be used to place these pools into user-defined memory by using external + declaration. + + * Added TCP_SNDQUEUELOWAT corresponding to TCP_SNDLOWAT + + +++ new pools: + + * Netdb uses a memp pool for allocating memory when getaddrinfo() is called, + so MEMP_NUM_NETDB has to be set accordingly. + + * DNS_LOCAL_HOSTLIST_IS_DYNAMIC uses a memp pool instead of the heap, so + MEMP_NUM_LOCALHOSTLIST has to be set accordingly. + + * Snmp-agent uses a memp pools instead of the heap, so MEMP_NUM_SNMP_* have + to be set accordingly. + + * PPPoE uses a MEMP pool instead of the heap, so MEMP_NUM_PPPOE_INTERFACES + has to be set accordingly + + * Integrated loopif into netif.c - loopif does not have to be created by the + port any more, just define LWIP_HAVE_LOOPIF to 1. + + * Added define LWIP_RAND() for lwip-wide randomization (needs to be defined + in cc.h, e.g. used by igmp) + + * Added printf-formatter X8_F to printf u8_t as hex + + * The heap now may be moved to user-defined memory by defining + LWIP_RAM_HEAP_POINTER as a void pointer to that memory's address + + * added autoip_set_struct() and dhcp_set_struct() to let autoip and dhcp work + with user-allocated structs instead of calling mem_malloc + + * Added const char* name to mem- and memp-stats for easier debugging. + + * Calculate the TCP/UDP checksum while copying to only fetch data once: + Define LWIP_CHKSUM_COPY to a memcpy-like function that returns the checksum + + * Added SO_REUSE_RXTOALL to pass received UDP broadcast/multicast packets to + more than one pcb. + + * Changed the semantics of ARP_QUEUEING==0: ARP_QUEUEING now cannot be turned + off any more, if this is set to 0, only one packet (the most recent one) is + queued (like demanded by RFC 1122). + + + ++ Major bugfixes/improvements + + * Implemented tcp_shutdown() to only shut down one end of a connection + * Implemented shutdown() at socket- and netconn-level + * Added errorset support to select() + improved select speed overhead + * Merged pppd to v2.3.11 (including some backported bugfixes from 2.4.x) + * Added timer implementation for NO_SYS==1 (may be disabled with NO_SYS_NO_TIMERS==1 + * Use macros defined in ip_addr.h to work with IP addresses + * Implemented many nonblocking socket/netconn functions + * Fixed ARP input processing: only add a new entry if a request was directed as us + * mem_realloc() to mem_trim() to prevent confusion with realloc() + * Some improvements for AutoIP (don't route/forward link-local addresses, don't break + existing connections when assigning a routable address) + * Correctly handle remote side overrunning our rcv_wnd in ooseq case + * Removed packing from ip_addr_t, the packed version is now only used in protocol headers + * Corrected PBUF_POOL_BUFSIZE for ports where ETH_PAD_SIZE > 0 + * Added support for static ARP table entries + +(STABLE-1.3.2) + + * initial version of this file diff --git a/component/common/network/lwip/lwip_v1.4.1/doc/FILES b/component/common/network/lwip/lwip_v1.4.1/doc/FILES new file mode 100644 index 0000000..05d356f --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/doc/FILES @@ -0,0 +1,6 @@ +savannah.txt - How to obtain the current development source code. +contrib.txt - How to contribute to lwIP as a developer. +rawapi.txt - The documentation for the core API of lwIP. + Also provides an overview about the other APIs and multithreading. +snmp_agent.txt - The documentation for the lwIP SNMP agent. +sys_arch.txt - The documentation for a system abstraction layer of lwIP. diff --git a/component/common/network/lwip/lwip_v1.4.1/doc/contrib.txt b/component/common/network/lwip/lwip_v1.4.1/doc/contrib.txt new file mode 100644 index 0000000..39596fc --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/doc/contrib.txt @@ -0,0 +1,63 @@ +1 Introduction + +This document describes some guidelines for people participating +in lwIP development. + +2 How to contribute to lwIP + +Here is a short list of suggestions to anybody working with lwIP and +trying to contribute bug reports, fixes, enhancements, platform ports etc. +First of all as you may already know lwIP is a volunteer project so feedback +to fixes or questions might often come late. Hopefully the bug and patch tracking +features of Savannah help us not lose users' input. + +2.1 Source code style: + +1. do not use tabs. +2. indentation is two spaces per level (i.e. per tab). +3. end debug messages with a trailing newline (\n). +4. one space between keyword and opening bracket. +5. no space between function and opening bracket. +6. one space and no newline before opening curly braces of a block. +7. closing curly brace on a single line. +8. spaces surrounding assignment and comparisons. +9. don't initialize static and/or global variables to zero, the compiler takes care of that. +10. use current source code style as further reference. + +2.2 Source code documentation style: + +1. JavaDoc compliant and Doxygen compatible. +2. Function documentation above functions in .c files, not .h files. + (This forces you to synchronize documentation and implementation.) +3. Use current documentation style as further reference. + +2.3 Bug reports and patches: + +1. Make sure you are reporting bugs or send patches against the latest + sources. (From the latest release and/or the current CVS sources.) +2. If you think you found a bug make sure it's not already filed in the + bugtracker at Savannah. +3. If you have a fix put the patch on Savannah. If it is a patch that affects + both core and arch specific stuff please separate them so that the core can + be applied separately while leaving the other patch 'open'. The prefered way + is to NOT touch archs you can't test and let maintainers take care of them. + This is a good way to see if they are used at all - the same goes for unix + netifs except tapif. +4. Do not file a bug and post a fix to it to the patch area. Either a bug report + or a patch will be enough. + If you correct an existing bug then attach the patch to the bug rather than creating a new entry in the patch area. +5. Trivial patches (compiler warning, indentation and spelling fixes or anything obvious which takes a line or two) + can go to the lwip-users list. This is still the fastest way of interaction and the list is not so crowded + as to allow for loss of fixes. Putting bugs on Savannah and subsequently closing them is too much an overhead + for reporting a compiler warning fix. +6. Patches should be specific to a single change or to related changes.Do not mix bugfixes with spelling and other + trivial fixes unless the bugfix is trivial too.Do not reorganize code and rename identifiers in the same patch you + change behaviour if not necessary.A patch is easier to read and understand if it's to the point and short than + if it's not to the point and long :) so the chances for it to be applied are greater. + +2.4 Platform porters: + +1. If you have ported lwIP to a platform (an OS, a uC/processor or a combination of these) and + you think it could benefit others[1] you might want discuss this on the mailing list. You + can also ask for CVS access to submit and maintain your port in the contrib CVS module. + \ No newline at end of file diff --git a/component/common/network/lwip/lwip_v1.4.1/doc/rawapi.txt b/component/common/network/lwip/lwip_v1.4.1/doc/rawapi.txt new file mode 100644 index 0000000..8c19030 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/doc/rawapi.txt @@ -0,0 +1,511 @@ +Raw TCP/IP interface for lwIP + +Authors: Adam Dunkels, Leon Woestenberg, Christiaan Simons + +lwIP provides three Application Program's Interfaces (APIs) for programs +to use for communication with the TCP/IP code: +* low-level "core" / "callback" or "raw" API. +* higher-level "sequential" API. +* BSD-style socket API. + +The sequential API provides a way for ordinary, sequential, programs +to use the lwIP stack. It is quite similar to the BSD socket API. The +model of execution is based on the blocking open-read-write-close +paradigm. Since the TCP/IP stack is event based by nature, the TCP/IP +code and the application program must reside in different execution +contexts (threads). + +The socket API is a compatibility API for existing applications, +currently it is built on top of the sequential API. It is meant to +provide all functions needed to run socket API applications running +on other platforms (e.g. unix / windows etc.). However, due to limitations +in the specification of this API, there might be incompatibilities +that require small modifications of existing programs. + +** Threading + +lwIP started targeting single-threaded environments. When adding multi- +threading support, instead of making the core thread-safe, another +approach was chosen: there is one main thread running the lwIP core +(also known as the "tcpip_thread"). The raw API may only be used from +this thread! Application threads using the sequential- or socket API +communicate with this main thread through message passing. + + As such, the list of functions that may be called from + other threads or an ISR is very limited! Only functions + from these API header files are thread-safe: + - api.h + - netbuf.h + - netdb.h + - netifapi.h + - sockets.h + - sys.h + + Additionaly, memory (de-)allocation functions may be + called from multiple threads (not ISR!) with NO_SYS=0 + since they are protected by SYS_LIGHTWEIGHT_PROT and/or + semaphores. + + Only since 1.3.0, if SYS_LIGHTWEIGHT_PROT is set to 1 + and LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT is set to 1, + pbuf_free() may also be called from another thread or + an ISR (since only then, mem_free - for PBUF_RAM - may + be called from an ISR: otherwise, the HEAP is only + protected by semaphores). + + +** The remainder of this document discusses the "raw" API. ** + +The raw TCP/IP interface allows the application program to integrate +better with the TCP/IP code. Program execution is event based by +having callback functions being called from within the TCP/IP +code. The TCP/IP code and the application program both run in the same +thread. The sequential API has a much higher overhead and is not very +well suited for small systems since it forces a multithreaded paradigm +on the application. + +The raw TCP/IP interface is not only faster in terms of code execution +time but is also less memory intensive. The drawback is that program +development is somewhat harder and application programs written for +the raw TCP/IP interface are more difficult to understand. Still, this +is the preferred way of writing applications that should be small in +code size and memory usage. + +Both APIs can be used simultaneously by different application +programs. In fact, the sequential API is implemented as an application +program using the raw TCP/IP interface. + +--- Callbacks + +Program execution is driven by callbacks. Each callback is an ordinary +C function that is called from within the TCP/IP code. Every callback +function is passed the current TCP or UDP connection state as an +argument. Also, in order to be able to keep program specific state, +the callback functions are called with a program specified argument +that is independent of the TCP/IP state. + +The function for setting the application connection state is: + +- void tcp_arg(struct tcp_pcb *pcb, void *arg) + + Specifies the program specific state that should be passed to all + other callback functions. The "pcb" argument is the current TCP + connection control block, and the "arg" argument is the argument + that will be passed to the callbacks. + + +--- TCP connection setup + +The functions used for setting up connections is similar to that of +the sequential API and of the BSD socket API. A new TCP connection +identifier (i.e., a protocol control block - PCB) is created with the +tcp_new() function. This PCB can then be either set to listen for new +incoming connections or be explicitly connected to another host. + +- struct tcp_pcb *tcp_new(void) + + Creates a new connection identifier (PCB). If memory is not + available for creating the new pcb, NULL is returned. + +- err_t tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr, + u16_t port) + + Binds the pcb to a local IP address and port number. The IP address + can be specified as IP_ADDR_ANY in order to bind the connection to + all local IP addresses. + + If another connection is bound to the same port, the function will + return ERR_USE, otherwise ERR_OK is returned. + +- struct tcp_pcb *tcp_listen(struct tcp_pcb *pcb) + + Commands a pcb to start listening for incoming connections. When an + incoming connection is accepted, the function specified with the + tcp_accept() function will be called. The pcb will have to be bound + to a local port with the tcp_bind() function. + + The tcp_listen() function returns a new connection identifier, and + the one passed as an argument to the function will be + deallocated. The reason for this behavior is that less memory is + needed for a connection that is listening, so tcp_listen() will + reclaim the memory needed for the original connection and allocate a + new smaller memory block for the listening connection. + + tcp_listen() may return NULL if no memory was available for the + listening connection. If so, the memory associated with the pcb + passed as an argument to tcp_listen() will not be deallocated. + +- struct tcp_pcb *tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog) + + Same as tcp_listen, but limits the number of outstanding connections + in the listen queue to the value specified by the backlog argument. + To use it, your need to set TCP_LISTEN_BACKLOG=1 in your lwipopts.h. + +- void tcp_accepted(struct tcp_pcb *pcb) + + Inform lwIP that an incoming connection has been accepted. This would + usually be called from the accept callback. This allows lwIP to perform + housekeeping tasks, such as allowing further incoming connections to be + queued in the listen backlog. + ATTENTION: the PCB passed in must be the listening pcb, not the pcb passed + into the accept callback! + +- void tcp_accept(struct tcp_pcb *pcb, + err_t (* accept)(void *arg, struct tcp_pcb *newpcb, + err_t err)) + + Specified the callback function that should be called when a new + connection arrives on a listening connection. + +- err_t tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, + u16_t port, err_t (* connected)(void *arg, + struct tcp_pcb *tpcb, + err_t err)); + + Sets up the pcb to connect to the remote host and sends the + initial SYN segment which opens the connection. + + The tcp_connect() function returns immediately; it does not wait for + the connection to be properly setup. Instead, it will call the + function specified as the fourth argument (the "connected" argument) + when the connection is established. If the connection could not be + properly established, either because the other host refused the + connection or because the other host didn't answer, the "err" + callback function of this pcb (registered with tcp_err, see below) + will be called. + + The tcp_connect() function can return ERR_MEM if no memory is + available for enqueueing the SYN segment. If the SYN indeed was + enqueued successfully, the tcp_connect() function returns ERR_OK. + + +--- Sending TCP data + +TCP data is sent by enqueueing the data with a call to +tcp_write(). When the data is successfully transmitted to the remote +host, the application will be notified with a call to a specified +callback function. + +- err_t tcp_write(struct tcp_pcb *pcb, const void *dataptr, u16_t len, + u8_t apiflags) + + Enqueues the data pointed to by the argument dataptr. The length of + the data is passed as the len parameter. The apiflags can be one or more of: + - TCP_WRITE_FLAG_COPY: indicates whether the new memory should be allocated + for the data to be copied into. If this flag is not given, no new memory + should be allocated and the data should only be referenced by pointer. This + also means that the memory behind dataptr must not change until the data is + ACKed by the remote host + - TCP_WRITE_FLAG_MORE: indicates that more data follows. If this is given, + the PSH flag is set in the last segment created by this call to tcp_write. + If this flag is given, the PSH flag is not set. + + The tcp_write() function will fail and return ERR_MEM if the length + of the data exceeds the current send buffer size or if the length of + the queue of outgoing segment is larger than the upper limit defined + in lwipopts.h. The number of bytes available in the output queue can + be retrieved with the tcp_sndbuf() function. + + The proper way to use this function is to call the function with at + most tcp_sndbuf() bytes of data. If the function returns ERR_MEM, + the application should wait until some of the currently enqueued + data has been successfully received by the other host and try again. + +- void tcp_sent(struct tcp_pcb *pcb, + err_t (* sent)(void *arg, struct tcp_pcb *tpcb, + u16_t len)) + + Specifies the callback function that should be called when data has + successfully been received (i.e., acknowledged) by the remote + host. The len argument passed to the callback function gives the + amount bytes that was acknowledged by the last acknowledgment. + + +--- Receiving TCP data + +TCP data reception is callback based - an application specified +callback function is called when new data arrives. When the +application has taken the data, it has to call the tcp_recved() +function to indicate that TCP can advertise increase the receive +window. + +- void tcp_recv(struct tcp_pcb *pcb, + err_t (* recv)(void *arg, struct tcp_pcb *tpcb, + struct pbuf *p, err_t err)) + + Sets the callback function that will be called when new data + arrives. The callback function will be passed a NULL pbuf to + indicate that the remote host has closed the connection. If + there are no errors and the callback function is to return + ERR_OK, then it must free the pbuf. Otherwise, it must not + free the pbuf so that lwIP core code can store it. + +- void tcp_recved(struct tcp_pcb *pcb, u16_t len) + + Must be called when the application has received the data. The len + argument indicates the length of the received data. + + +--- Application polling + +When a connection is idle (i.e., no data is either transmitted or +received), lwIP will repeatedly poll the application by calling a +specified callback function. This can be used either as a watchdog +timer for killing connections that have stayed idle for too long, or +as a method of waiting for memory to become available. For instance, +if a call to tcp_write() has failed because memory wasn't available, +the application may use the polling functionality to call tcp_write() +again when the connection has been idle for a while. + +- void tcp_poll(struct tcp_pcb *pcb, + err_t (* poll)(void *arg, struct tcp_pcb *tpcb), + u8_t interval) + + Specifies the polling interval and the callback function that should + be called to poll the application. The interval is specified in + number of TCP coarse grained timer shots, which typically occurs + twice a second. An interval of 10 means that the application would + be polled every 5 seconds. + + +--- Closing and aborting connections + +- err_t tcp_close(struct tcp_pcb *pcb) + + Closes the connection. The function may return ERR_MEM if no memory + was available for closing the connection. If so, the application + should wait and try again either by using the acknowledgment + callback or the polling functionality. If the close succeeds, the + function returns ERR_OK. + + The pcb is deallocated by the TCP code after a call to tcp_close(). + +- void tcp_abort(struct tcp_pcb *pcb) + + Aborts the connection by sending a RST (reset) segment to the remote + host. The pcb is deallocated. This function never fails. + + ATTENTION: When calling this from one of the TCP callbacks, make + sure you always return ERR_ABRT (and never return ERR_ABRT otherwise + or you will risk accessing deallocated memory or memory leaks! + + +If a connection is aborted because of an error, the application is +alerted of this event by the err callback. Errors that might abort a +connection are when there is a shortage of memory. The callback +function to be called is set using the tcp_err() function. + +- void tcp_err(struct tcp_pcb *pcb, void (* err)(void *arg, + err_t err)) + + The error callback function does not get the pcb passed to it as a + parameter since the pcb may already have been deallocated. + + +--- Lower layer TCP interface + +TCP provides a simple interface to the lower layers of the +system. During system initialization, the function tcp_init() has +to be called before any other TCP function is called. When the system +is running, the two timer functions tcp_fasttmr() and tcp_slowtmr() +must be called with regular intervals. The tcp_fasttmr() should be +called every TCP_FAST_INTERVAL milliseconds (defined in tcp.h) and +tcp_slowtmr() should be called every TCP_SLOW_INTERVAL milliseconds. + + +--- UDP interface + +The UDP interface is similar to that of TCP, but due to the lower +level of complexity of UDP, the interface is significantly simpler. + +- struct udp_pcb *udp_new(void) + + Creates a new UDP pcb which can be used for UDP communication. The + pcb is not active until it has either been bound to a local address + or connected to a remote address. + +- void udp_remove(struct udp_pcb *pcb) + + Removes and deallocates the pcb. + +- err_t udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, + u16_t port) + + Binds the pcb to a local address. The IP-address argument "ipaddr" + can be IP_ADDR_ANY to indicate that it should listen to any local IP + address. The function currently always return ERR_OK. + +- err_t udp_connect(struct udp_pcb *pcb, ip_addr_t *ipaddr, + u16_t port) + + Sets the remote end of the pcb. This function does not generate any + network traffic, but only set the remote address of the pcb. + +- err_t udp_disconnect(struct udp_pcb *pcb) + + Remove the remote end of the pcb. This function does not generate + any network traffic, but only removes the remote address of the pcb. + +- err_t udp_send(struct udp_pcb *pcb, struct pbuf *p) + + Sends the pbuf p. The pbuf is not deallocated. + +- void udp_recv(struct udp_pcb *pcb, + void (* recv)(void *arg, struct udp_pcb *upcb, + struct pbuf *p, + ip_addr_t *addr, + u16_t port), + void *recv_arg) + + Specifies a callback function that should be called when a UDP + datagram is received. + + +--- System initalization + +A truly complete and generic sequence for initializing the lwip stack +cannot be given because it depends on the build configuration (lwipopts.h) +and additional initializations for your runtime environment (e.g. timers). + +We can give you some idea on how to proceed when using the raw API. +We assume a configuration using a single Ethernet netif and the +UDP and TCP transport layers, IPv4 and the DHCP client. + +Call these functions in the order of appearance: + +- stats_init() + + Clears the structure where runtime statistics are gathered. + +- sys_init() + + Not of much use since we set the NO_SYS 1 option in lwipopts.h, + to be called for easy configuration changes. + +- mem_init() + + Initializes the dynamic memory heap defined by MEM_SIZE. + +- memp_init() + + Initializes the memory pools defined by MEMP_NUM_x. + +- pbuf_init() + + Initializes the pbuf memory pool defined by PBUF_POOL_SIZE. + +- etharp_init() + + Initializes the ARP table and queue. + Note: you must call etharp_tmr at a ARP_TMR_INTERVAL (5 seconds) regular interval + after this initialization. + +- ip_init() + + Doesn't do much, it should be called to handle future changes. + +- udp_init() + + Clears the UDP PCB list. + +- tcp_init() + + Clears the TCP PCB list and clears some internal TCP timers. + Note: you must call tcp_fasttmr() and tcp_slowtmr() at the + predefined regular intervals after this initialization. + +- netif_add(struct netif *netif, ip_addr_t *ipaddr, + ip_addr_t *netmask, ip_addr_t *gw, + void *state, err_t (* init)(struct netif *netif), + err_t (* input)(struct pbuf *p, struct netif *netif)) + + Adds your network interface to the netif_list. Allocate a struct + netif and pass a pointer to this structure as the first argument. + Give pointers to cleared ip_addr structures when using DHCP, + or fill them with sane numbers otherwise. The state pointer may be NULL. + + The init function pointer must point to a initialization function for + your ethernet netif interface. The following code illustrates it's use. + + err_t netif_if_init(struct netif *netif) + { + u8_t i; + + for(i = 0; i < ETHARP_HWADDR_LEN; i++) netif->hwaddr[i] = some_eth_addr[i]; + init_my_eth_device(); + return ERR_OK; + } + + For ethernet drivers, the input function pointer must point to the lwip + function ethernet_input() declared in "netif/etharp.h". Other drivers + must use ip_input() declared in "lwip/ip.h". + +- netif_set_default(struct netif *netif) + + Registers the default network interface. + +- netif_set_up(struct netif *netif) + + When the netif is fully configured this function must be called. + +- dhcp_start(struct netif *netif) + + Creates a new DHCP client for this interface on the first call. + Note: you must call dhcp_fine_tmr() and dhcp_coarse_tmr() at + the predefined regular intervals after starting the client. + + You can peek in the netif->dhcp struct for the actual DHCP status. + + +--- Optimalization hints + +The first thing you want to optimize is the lwip_standard_checksum() +routine from src/core/inet.c. You can override this standard +function with the #define LWIP_CHKSUM . + +There are C examples given in inet.c or you might want to +craft an assembly function for this. RFC1071 is a good +introduction to this subject. + +Other significant improvements can be made by supplying +assembly or inline replacements for htons() and htonl() +if you're using a little-endian architecture. +#define LWIP_PLATFORM_BYTESWAP 1 +#define LWIP_PLATFORM_HTONS(x) +#define LWIP_PLATFORM_HTONL(x) + +Check your network interface driver if it reads at +a higher speed than the maximum wire-speed. If the +hardware isn't serviced frequently and fast enough +buffer overflows are likely to occur. + +E.g. when using the cs8900 driver, call cs8900if_service(ethif) +as frequently as possible. When using an RTOS let the cs8900 interrupt +wake a high priority task that services your driver using a binary +semaphore or event flag. Some drivers might allow additional tuning +to match your application and network. + +For a production release it is recommended to set LWIP_STATS to 0. +Note that speed performance isn't influenced much by simply setting +high values to the memory options. + +For more optimization hints take a look at the lwIP wiki. + +--- Zero-copy MACs + +To achieve zero-copy on transmit, the data passed to the raw API must +remain unchanged until sent. Because the send- (or write-)functions return +when the packets have been enqueued for sending, data must be kept stable +after that, too. + +This implies that PBUF_RAM/PBUF_POOL pbufs passed to raw-API send functions +must *not* be reused by the application unless their ref-count is 1. + +For no-copy pbufs (PBUF_ROM/PBUF_REF), data must be kept unchanged, too, +but the stack/driver will/must copy PBUF_REF'ed data when enqueueing, while +PBUF_ROM-pbufs are just enqueued (as ROM-data is expected to never change). + +Also, data passed to tcp_write without the copy-flag must not be changed! + +Therefore, be careful which type of PBUF you use and if you copy TCP data +or not! diff --git a/component/common/network/lwip/lwip_v1.4.1/doc/savannah.txt b/component/common/network/lwip/lwip_v1.4.1/doc/savannah.txt new file mode 100644 index 0000000..409905b --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/doc/savannah.txt @@ -0,0 +1,135 @@ +Daily Use Guide for using Savannah for lwIP + +Table of Contents: + +1 - Obtaining lwIP from the CVS repository +2 - Committers/developers CVS access using SSH (to be written) +3 - Merging from DEVEL branch to main trunk (stable branch) +4 - How to release lwIP + + + +1 Obtaining lwIP from the CVS repository +---------------------------------------- + +To perform an anonymous CVS checkout of the main trunk (this is where +bug fixes and incremental enhancements occur), do this: + +cvs -z3 -d:pserver:anonymous@cvs.sv.gnu.org:/sources/lwip checkout lwip + +Or, obtain a stable branch (updated with bug fixes only) as follows: +cvs -z3 -d:pserver:anonymous@cvs.sv.gnu.org:/sources/lwip checkout \ + -r STABLE-0_7 -d lwip-0.7 lwip + +Or, obtain a specific (fixed) release as follows: +cvs -z3 -d:pserver:anonymous@cvs.sv.gnu.org:/sources/lwip checkout \ + -r STABLE-0_7_0 -d lwip-0.7.0 lwip + +3 Committers/developers CVS access using SSH +-------------------------------------------- + +The Savannah server uses SSH (Secure Shell) protocol 2 authentication and encryption. +As such, CVS commits to the server occur through a SSH tunnel for project members. +To create a SSH2 key pair in UNIX-like environments, do this: + +ssh-keygen -t dsa + +Under Windows, a recommended SSH client is "PuTTY", freely available with good +documentation and a graphic user interface. Use its key generator. + +Now paste the id_dsa.pub contents into your Savannah account public key list. Wait +a while so that Savannah can update its configuration (This can take minutes). + +Try to login using SSH: + +ssh -v your_login@cvs.sv.gnu.org + +If it tells you: + +Authenticating with public key "your_key_name"... +Server refused to allocate pty + +then you could login; Savannah refuses to give you a shell - which is OK, as we +are allowed to use SSH for CVS only. Now, you should be able to do this: + +export CVS_RSH=ssh +cvs -z3 -d:ext:your_login@cvs.sv.gnu.org:/sources/lwip co lwip + +after which you can edit your local files with bug fixes or new features and +commit them. Make sure you know what you are doing when using CVS to make +changes on the repository. If in doubt, ask on the lwip-members mailing list. + +(If SSH asks about authenticity of the host, you can check the key + fingerprint against http://savannah.nongnu.org/cvs/?group=lwip) + + +3 Merging from DEVEL branch to main trunk (stable) +-------------------------------------------------- + +Merging is a delicate process in CVS and requires the +following disciplined steps in order to prevent conflicts +in the future. Conflicts can be hard to solve! + +Merging from branch A to branch B requires that the A branch +has a tag indicating the previous merger. This tag is called +'merged_from_A_to_B'. After merging, the tag is moved in the +A branch to remember this merger for future merge actions. + +IMPORTANT: AFTER COMMITTING A SUCCESFUL MERGE IN THE +REPOSITORY, THE TAG MUST BE SET ON THE SOURCE BRANCH OF THE +MERGE ACTION (REPLACING EXISTING TAGS WITH THE SAME NAME). + +Merge all changes in DEVEL since our last merge to main: + +In the working copy of the main trunk: +cvs update -P -jmerged_from_DEVEL_to_main -jDEVEL + +(This will apply the changes between 'merged_from_DEVEL_to_main' +and 'DEVEL' to your work set of files) + +We can now commit the merge result. +cvs commit -R -m "Merged from DEVEL to main." + +If this worked out OK, we now move the tag in the DEVEL branch +to this merge point, so we can use this point for future merges: + +cvs rtag -F -r DEVEL merged_from_DEVEL_to_main lwip + +4 How to release lwIP +--------------------- + +First, checkout a clean copy of the branch to be released. Tag this set with +tag name "STABLE-0_6_3". (I use release number 0.6.3 throughout this example). + +Login CVS using pserver authentication, then export a clean copy of the +tagged tree. Export is similar to a checkout, except that the CVS metadata +is not created locally. + +export CVS_RSH=ssh +cvs -z3 -d:pserver:anonymous@cvs.sv.gnu.org:/sources/lwip checkout \ + -r STABLE-0_6_3 -d lwip-0.6.3 lwip + +Archive this directory using tar, gzip'd, bzip2'd and zip'd. + +tar czvf lwip-0.6.3.tar.gz lwip-0.6.3 +tar cjvf lwip-0.6.3.tar.bz2 lwip-0.6.3 +zip -r lwip-0.6.3.zip lwip-0.6.3 + +Now, sign the archives with a detached GPG binary signature as follows: + +gpg -b lwip-0.6.3.tar.gz +gpg -b lwip-0.6.3.tar.bz2 +gpg -b lwip-0.6.3.zip + +Upload these files using anonymous FTP: +ncftp ftp://savannah.gnu.org/incoming/savannah/lwip + +ncftp>mput *0.6.3.* + +Additionally, you may post a news item on Savannah, like this: + +A new 0.6.3 release is now available here: +http://savannah.nongnu.org/files/?group=lwip&highlight=0.6.3 + +You will have to submit this via the user News interface, then approve +this via the Administrator News interface. \ No newline at end of file diff --git a/component/common/network/lwip/lwip_v1.4.1/doc/snmp_agent.txt b/component/common/network/lwip/lwip_v1.4.1/doc/snmp_agent.txt new file mode 100644 index 0000000..2653230 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/doc/snmp_agent.txt @@ -0,0 +1,181 @@ +SNMPv1 agent for lwIP + +Author: Christiaan Simons + +This is a brief introduction how to use and configure the SNMP agent. +Note the agent uses the raw-API UDP interface so you may also want to +read rawapi.txt to gain a better understanding of the SNMP message handling. + +0 Agent Capabilities +==================== + +SNMPv1 per RFC1157 + This is an old(er) standard but is still widely supported. + For SNMPv2c and v3 have a greater complexity and need many + more lines of code. IMHO this breaks the idea of "lightweight IP". + + Note the S in SNMP stands for "Simple". Note that "Simple" is + relative. SNMP is simple compared to the complex ISO network + management protocols CMIP (Common Management Information Protocol) + and CMOT (CMip Over Tcp). + +MIB II per RFC1213 + The standard lwIP stack management information base. + This is a required MIB, so this is always enabled. + When builing lwIP without TCP, the mib-2.tcp group is omitted. + The groups EGP, CMOT and transmission are disabled by default. + + Most mib-2 objects are not writable except: + sysName, sysLocation, sysContact, snmpEnableAuthenTraps. + Writing to or changing the ARP and IP address and route + tables is not possible. + + Note lwIP has a very limited notion of IP routing. It currently + doen't have a route table and doesn't have a notion of the U,G,H flags. + Instead lwIP uses the interface list with only one default interface + acting as a single gateway interface (G) for the default route. + + The agent returns a "virtual table" with the default route 0.0.0.0 + for the default interface and network routes (no H) for each + network interface in the netif_list. + All routes are considered to be up (U). + +Loading additional MIBs + MIBs can only be added in compile-time, not in run-time. + There is no MIB compiler thus additional MIBs must be hand coded. + +Large SNMP message support + The packet decoding and encoding routines are designed + to use pbuf-chains. Larger payloads than the minimum + SNMP requirement of 484 octets are supported if the + PBUF_POOL_SIZE and IP_REASS_BUFSIZE are set to match your + local requirement. + +1 Building the Agent +==================== + +First of all you'll need to add the following define +to your local lwipopts.h: + +#define LWIP_SNMP 1 + +and add the source files in lwip/src/core/snmp +and some snmp headers in lwip/src/include/lwip to your makefile. + +Note you'll might need to adapt you network driver to update +the mib2 variables for your interface. + +2 Running the Agent +=================== + +The following function calls must be made in your program to +actually get the SNMP agent running. + +Before starting the agent you should supply pointers +to non-volatile memory for sysContact, sysLocation, +and snmpEnableAuthenTraps. You can do this by calling + +snmp_set_syscontact() +snmp_set_syslocation() +snmp_set_snmpenableauthentraps() + +Additionally you may want to set + +snmp_set_sysdescr() +snmp_set_sysobjid() (if you have a private MIB) +snmp_set_sysname() + +Also before starting the agent you need to setup +one or more trap destinations using these calls: + +snmp_trap_dst_enable(); +snmp_trap_dst_ip_set(); + +In the lwIP initialisation sequence call snmp_init() just after +the call to udp_init(). + +Exactly every 10 msec the SNMP uptime timestamp must be updated with +snmp_inc_sysuptime(). You should call this from a timer interrupt +or a timer signal handler depending on your runtime environment. + +An alternative way to update the SNMP uptime timestamp is to do a call like +snmp_add_sysuptime(100) each 1000ms (which is bigger "step", but call to +a lower frequency). Another one is to not call snmp_inc_sysuptime() or +snmp_add_sysuptime(), and to define the SNMP_GET_SYSUPTIME(sysuptime) macro. +This one is undefined by default in mib2.c. SNMP_GET_SYSUPTIME is called inside +snmp_get_sysuptime(u32_t *value), and enable to change "sysuptime" value only +when it's queried (any function which need "sysuptime" have to call +snmp_get_sysuptime). + + +3 Private MIBs +============== + +If want to extend the agent with your own private MIB you'll need to +add the following define to your local lwipopts.h: + +#define SNMP_PRIVATE_MIB 1 + +You must provide the private_mib.h and associated files yourself. +Note we don't have a "MIB compiler" that generates C source from a MIB, +so you're required to do some serious coding if you enable this! + +Note the lwIP enterprise ID (26381) is assigned to the lwIP project, +ALL OBJECT IDENTIFIERS LIVING UNDER THIS ID ARE ASSIGNED BY THE lwIP +MAINTAINERS! + +If you need to create your own private MIB you'll need +to apply for your own enterprise ID with IANA: http://www.iana.org/numbers.html + +You can set it by passing a struct snmp_obj_id to the agent +using snmp_set_sysobjid(&my_object_id), just before snmp_init(). + +Note the object identifiers for thes MIB-2 and your private MIB +tree must be kept in sorted ascending (lexicographical) order. +This to ensure correct getnext operation. + +An example for a private MIB is part of the "minimal Unix" project: +contrib/ports/unix/proj/minimal/lwip_prvmib.c + +The next chapter gives a more detailed description of the +MIB-2 tree and the optional private MIB. + +4 The Gory Details +================== + +4.0 Object identifiers and the MIB tree. + +We have three distinct parts for all object identifiers: + +The prefix + .iso.org.dod.internet + +the middle part + .mgmt.mib-2.ip.ipNetToMediaTable.ipNetToMediaEntry.ipNetToMediaPhysAddress + +and the index part + .1.192.168.0.1 + +Objects located above the .internet hierarchy aren't supported. +Currently only the .mgmt sub-tree is available and +when the SNMP_PRIVATE_MIB is enabled the .private tree +becomes available too. + +Object identifiers from incoming requests are checked +for a matching prefix, middle part and index part +or are expanded(*) for GetNext requests with short +or inexisting names in the request. +(* we call this "expansion" but this also +resembles the "auto-completion" operation) + +The middle part is usually located in ROM (const) +to preserve precious RAM on small microcontrollers. +However RAM location is possible for a dynamically +changing private tree. + +The index part is handled by functions which in +turn use dynamically allocated index trees from RAM. +These trees are updated by e.g. the etharp code +when new entries are made or removed form the ARP cache. + +/** @todo more gory details */ diff --git a/component/common/network/lwip/lwip_v1.4.1/doc/sys_arch.txt b/component/common/network/lwip/lwip_v1.4.1/doc/sys_arch.txt new file mode 100644 index 0000000..847cd77 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/doc/sys_arch.txt @@ -0,0 +1,267 @@ +sys_arch interface for lwIP 0.6++ + +Author: Adam Dunkels + +The operating system emulation layer provides a common interface +between the lwIP code and the underlying operating system kernel. The +general idea is that porting lwIP to new architectures requires only +small changes to a few header files and a new sys_arch +implementation. It is also possible to do a sys_arch implementation +that does not rely on any underlying operating system. + +The sys_arch provides semaphores and mailboxes to lwIP. For the full +lwIP functionality, multiple threads support can be implemented in the +sys_arch, but this is not required for the basic lwIP +functionality. Previous versions of lwIP required the sys_arch to +implement timer scheduling as well but as of lwIP 0.5 this is +implemented in a higher layer. + +In addition to the source file providing the functionality of sys_arch, +the OS emulation layer must provide several header files defining +macros used throughout lwip. The files required and the macros they +must define are listed below the sys_arch description. + +Semaphores can be either counting or binary - lwIP works with both +kinds. Mailboxes are used for message passing and can be implemented +either as a queue which allows multiple messages to be posted to a +mailbox, or as a rendez-vous point where only one message can be +posted at a time. lwIP works with both kinds, but the former type will +be more efficient. A message in a mailbox is just a pointer, nothing +more. + +Semaphores are represented by the type "sys_sem_t" which is typedef'd +in the sys_arch.h file. Mailboxes are equivalently represented by the +type "sys_mbox_t". lwIP does not place any restrictions on how +sys_sem_t or sys_mbox_t are represented internally. + +Since lwIP 1.4.0, semaphore and mailbox functions are prototyped in a way that +allows both using pointers or actual OS structures to be used. This way, memory +required for such types can be either allocated in place (globally or on the +stack) or on the heap (allocated internally in the "*_new()" functions). + +The following functions must be implemented by the sys_arch: + +- void sys_init(void) + + Is called to initialize the sys_arch layer. + +- err_t sys_sem_new(sys_sem_t *sem, u8_t count) + + Creates a new semaphore. The semaphore is allocated to the memory that 'sem' + points to (which can be both a pointer or the actual OS structure). + The "count" argument specifies the initial state of the semaphore (which is + either 0 or 1). + If the semaphore has been created, ERR_OK should be returned. Returning any + other error will provide a hint what went wrong, but except for assertions, + no real error handling is implemented. + +- void sys_sem_free(sys_sem_t *sem) + + Deallocates a semaphore. + +- void sys_sem_signal(sys_sem_t *sem) + + Signals a semaphore. + +- u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) + + Blocks the thread while waiting for the semaphore to be + signaled. If the "timeout" argument is non-zero, the thread should + only be blocked for the specified time (measured in + milliseconds). If the "timeout" argument is zero, the thread should be + blocked until the semaphore is signalled. + + If the timeout argument is non-zero, the return value is the number of + milliseconds spent waiting for the semaphore to be signaled. If the + semaphore wasn't signaled within the specified time, the return value is + SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore + (i.e., it was already signaled), the function may return zero. + + Notice that lwIP implements a function with a similar name, + sys_sem_wait(), that uses the sys_arch_sem_wait() function. + +- int sys_sem_valid(sys_sem_t *sem) + + Returns 1 if the semaphore is valid, 0 if it is not valid. + When using pointers, a simple way is to check the pointer for != NULL. + When directly using OS structures, implementing this may be more complex. + This may also be a define, in which case the function is not prototyped. + +- void sys_sem_set_invalid(sys_sem_t *sem) + + Invalidate a semaphore so that sys_sem_valid() returns 0. + ATTENTION: This does NOT mean that the semaphore shall be deallocated: + sys_sem_free() is always called before calling this function! + This may also be a define, in which case the function is not prototyped. + +- err_t sys_mbox_new(sys_mbox_t *mbox, int size) + + Creates an empty mailbox for maximum "size" elements. Elements stored + in mailboxes are pointers. You have to define macros "_MBOX_SIZE" + in your lwipopts.h, or ignore this parameter in your implementation + and use a default size. + If the mailbox has been created, ERR_OK should be returned. Returning any + other error will provide a hint what went wrong, but except for assertions, + no real error handling is implemented. + +- void sys_mbox_free(sys_mbox_t *mbox) + + Deallocates a mailbox. If there are messages still present in the + mailbox when the mailbox is deallocated, it is an indication of a + programming error in lwIP and the developer should be notified. + +- void sys_mbox_post(sys_mbox_t *mbox, void *msg) + + Posts the "msg" to the mailbox. This function have to block until + the "msg" is really posted. + +- err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) + + Try to post the "msg" to the mailbox. Returns ERR_MEM if this one + is full, else, ERR_OK if the "msg" is posted. + +- u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout) + + Blocks the thread until a message arrives in the mailbox, but does + not block the thread longer than "timeout" milliseconds (similar to + the sys_arch_sem_wait() function). If "timeout" is 0, the thread should + be blocked until a message arrives. The "msg" argument is a result + parameter that is set by the function (i.e., by doing "*msg = + ptr"). The "msg" parameter maybe NULL to indicate that the message + should be dropped. + + The return values are the same as for the sys_arch_sem_wait() function: + Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a + timeout. + + Note that a function with a similar name, sys_mbox_fetch(), is + implemented by lwIP. + +- u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg) + + This is similar to sys_arch_mbox_fetch, however if a message is not + present in the mailbox, it immediately returns with the code + SYS_MBOX_EMPTY. On success 0 is returned. + + To allow for efficient implementations, this can be defined as a + function-like macro in sys_arch.h instead of a normal function. For + example, a naive implementation could be: + #define sys_arch_mbox_tryfetch(mbox,msg) \ + sys_arch_mbox_fetch(mbox,msg,1) + although this would introduce unnecessary delays. + +- int sys_mbox_valid(sys_mbox_t *mbox) + + Returns 1 if the mailbox is valid, 0 if it is not valid. + When using pointers, a simple way is to check the pointer for != NULL. + When directly using OS structures, implementing this may be more complex. + This may also be a define, in which case the function is not prototyped. + +- void sys_mbox_set_invalid(sys_mbox_t *mbox) + + Invalidate a mailbox so that sys_mbox_valid() returns 0. + ATTENTION: This does NOT mean that the mailbox shall be deallocated: + sys_mbox_free() is always called before calling this function! + This may also be a define, in which case the function is not prototyped. + +If threads are supported by the underlying operating system and if +such functionality is needed in lwIP, the following function will have +to be implemented as well: + +- sys_thread_t sys_thread_new(char *name, void (* thread)(void *arg), void *arg, int stacksize, int prio) + + Starts a new thread named "name" with priority "prio" that will begin its + execution in the function "thread()". The "arg" argument will be passed as an + argument to the thread() function. The stack size to used for this thread is + the "stacksize" parameter. The id of the new thread is returned. Both the id + and the priority are system dependent. + +- sys_prot_t sys_arch_protect(void) + + This optional function does a "fast" critical region protection and returns + the previous protection level. This function is only called during very short + critical regions. An embedded system which supports ISR-based drivers might + want to implement this function by disabling interrupts. Task-based systems + might want to implement this by using a mutex or disabling tasking. This + function should support recursive calls from the same task or interrupt. In + other words, sys_arch_protect() could be called while already protected. In + that case the return value indicates that it is already protected. + + sys_arch_protect() is only required if your port is supporting an operating + system. + +- void sys_arch_unprotect(sys_prot_t pval) + + This optional function does a "fast" set of critical region protection to the + value specified by pval. See the documentation for sys_arch_protect() for + more information. This function is only required if your port is supporting + an operating system. + +For some configurations, you also need: + +- u32_t sys_now(void) + + This optional function returns the current time in milliseconds (don't care + for wraparound, this is only used for time diffs). + Not implementing this function means you cannot use some modules (e.g. TCP + timestamps, internal timeouts for NO_SYS==1). + + +Note: + +Be carefull with using mem_malloc() in sys_arch. When malloc() refers to +mem_malloc() you can run into a circular function call problem. In mem.c +mem_init() tries to allcate a semaphore using mem_malloc, which of course +can't be performed when sys_arch uses mem_malloc. + +------------------------------------------------------------------------------- +Additional files required for the "OS support" emulation layer: +------------------------------------------------------------------------------- + +cc.h - Architecture environment, some compiler specific, some + environment specific (probably should move env stuff + to sys_arch.h.) + + Typedefs for the types used by lwip - + u8_t, s8_t, u16_t, s16_t, u32_t, s32_t, mem_ptr_t + + Compiler hints for packing lwip's structures - + PACK_STRUCT_FIELD(x) + PACK_STRUCT_STRUCT + PACK_STRUCT_BEGIN + PACK_STRUCT_END + + Platform specific diagnostic output - + LWIP_PLATFORM_DIAG(x) - non-fatal, print a message. + LWIP_PLATFORM_ASSERT(x) - fatal, print message and abandon execution. + Portability defines for printf formatters: + U16_F, S16_F, X16_F, U32_F, S32_F, X32_F, SZT_F + + "lightweight" synchronization mechanisms - + SYS_ARCH_DECL_PROTECT(x) - declare a protection state variable. + SYS_ARCH_PROTECT(x) - enter protection mode. + SYS_ARCH_UNPROTECT(x) - leave protection mode. + + If the compiler does not provide memset() this file must include a + definition of it, or include a file which defines it. + + This file must either include a system-local which defines + the standard *nix error codes, or it should #define LWIP_PROVIDE_ERRNO + to make lwip/arch.h define the codes which are used throughout. + + +perf.h - Architecture specific performance measurement. + Measurement calls made throughout lwip, these can be defined to nothing. + PERF_START - start measuring something. + PERF_STOP(x) - stop measuring something, and record the result. + +sys_arch.h - Tied to sys_arch.c + + Arch dependent types for the following objects: + sys_sem_t, sys_mbox_t, sys_thread_t, + And, optionally: + sys_prot_t + + Defines to set vars of sys_mbox_t and sys_sem_t to NULL. + SYS_MBOX_NULL NULL + SYS_SEM_NULL NULL diff --git a/component/common/network/lwip/lwip_v1.4.1/port/realtek/arch/bpstruct.h b/component/common/network/lwip/lwip_v1.4.1/port/realtek/arch/bpstruct.h new file mode 100644 index 0000000..177758c --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/port/realtek/arch/bpstruct.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#if defined(__IAR_SYSTEMS_ICC__) +#pragma pack(1) +#endif + diff --git a/component/common/network/lwip/lwip_v1.4.1/port/realtek/arch/cc.h b/component/common/network/lwip/lwip_v1.4.1/port/realtek/arch/cc.h new file mode 100644 index 0000000..be882d9 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/port/realtek/arch/cc.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __CC_H__ +#define __CC_H__ + +#include "cpu.h" + +typedef unsigned char u8_t; +typedef signed char s8_t; +typedef unsigned short u16_t; +typedef signed short s16_t; +typedef unsigned int u32_t; +typedef signed long s32_t; +typedef u32_t mem_ptr_t; +typedef int sys_prot_t; + +#define U16_F "d" +#define S16_F "d" +#define X16_F "x" +#define U32_F "d" +#define S32_F "d" +#define X32_F "x" +#define SZT_F "uz" + +/* define compiler specific symbols */ +#if defined (__ICCARM__) +#if !defined (__IARSTDLIB__) +#define _STRING +#ifndef memcmp +#define memcmp(dst, src, sz) _memcmp(dst, src, sz) +#endif +#ifndef memset +#define memset(dst, val, sz) _memset(dst, val, sz) +#endif +#ifndef memcpy +#define memcpy(dst, src, sz) _memcpy(dst, src, sz) +#endif +#endif // __IARSTDLIB__ + +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_STRUCT +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x +#define PACK_STRUCT_USE_INCLUDES + +#elif defined (__CC_ARM) + +#define PACK_STRUCT_BEGIN __packed +#define PACK_STRUCT_STRUCT +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x + +#elif defined (__GNUC__) + +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_STRUCT __attribute__ ((__packed__)) +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x + +#elif defined (__TASKING__) + +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_STRUCT +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x + +#endif + +#define LWIP_PLATFORM_ASSERT(x) //do { if(!(x)) while(1); } while(0) + +#endif /* __CC_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/port/realtek/arch/cpu.h b/component/common/network/lwip/lwip_v1.4.1/port/realtek/arch/cpu.h new file mode 100644 index 0000000..a02f86d --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/port/realtek/arch/cpu.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __CPU_H__ +#define __CPU_H__ + +#define BYTE_ORDER LITTLE_ENDIAN + +#endif /* __CPU_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/port/realtek/arch/epstruct.h b/component/common/network/lwip/lwip_v1.4.1/port/realtek/arch/epstruct.h new file mode 100644 index 0000000..1e1a049 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/port/realtek/arch/epstruct.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#if defined(__IAR_SYSTEMS_ICC__) +#pragma pack() +#endif + diff --git a/component/common/network/lwip/lwip_v1.4.1/port/realtek/arch/init.h b/component/common/network/lwip/lwip_v1.4.1/port/realtek/arch/init.h new file mode 100644 index 0000000..e622c73 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/port/realtek/arch/init.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __ARCH_INIT_H__ +#define __ARCH_INIT_H__ + +#define TCPIP_INIT_DONE(arg) tcpip_init_done(arg) + +void tcpip_init_done(void *); +int wait_for_tcpip_init(void); + +#endif /* __ARCH_INIT_H__ */ + + + + diff --git a/component/common/network/lwip/lwip_v1.4.1/port/realtek/arch/lib.h b/component/common/network/lwip/lwip_v1.4.1/port/realtek/arch/lib.h new file mode 100644 index 0000000..378f25b --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/port/realtek/arch/lib.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LIB_H__ +#define __LIB_H__ + +#include + + +#endif /* __LIB_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/port/realtek/arch/perf.h b/component/common/network/lwip/lwip_v1.4.1/port/realtek/arch/perf.h new file mode 100644 index 0000000..334d42a --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/port/realtek/arch/perf.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __PERF_H__ +#define __PERF_H__ + +#define PERF_START /* null definition */ +#define PERF_STOP(x) /* null definition */ + +#endif /* __PERF_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/port/realtek/arch/sys_arch.h b/component/common/network/lwip/lwip_v1.4.1/port/realtek/arch/sys_arch.h new file mode 100644 index 0000000..2e841bd --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/port/realtek/arch/sys_arch.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __SYS_RTXC_H__ +#define __SYS_RTXC_H__ + +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "semphr.h" + +#define SYS_MBOX_NULL (xQueueHandle)0 +#define SYS_SEM_NULL (xSemaphoreHandle)0 +#define SYS_DEFAULT_THREAD_STACK_DEPTH configMINIMAL_STACK_SIZE + +typedef xSemaphoreHandle sys_sem_t; +typedef xSemaphoreHandle sys_mutex_t; +typedef xQueueHandle sys_mbox_t; +typedef xTaskHandle sys_thread_t; + +typedef struct _sys_arch_state_t +{ + // Task creation data. + char cTaskName[configMAX_TASK_NAME_LEN]; + unsigned short nStackDepth; + unsigned short nTaskCount; +} sys_arch_state_t; + + + +//extern sys_arch_state_t s_sys_arch_state; + +//void sys_set_default_state(); +//void sys_set_state(signed char *pTaskName, unsigned short nStackSize); + +/* Message queue constants. */ +#define archMESG_QUEUE_LENGTH ( 6 ) +#endif /* __SYS_RTXC_H__ */ + diff --git a/component/common/network/lwip/lwip_v1.4.1/port/realtek/freertos/ethernetif.c b/component/common/network/lwip/lwip_v1.4.1/port/realtek/freertos/ethernetif.c new file mode 100644 index 0000000..ff87e04 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/port/realtek/freertos/ethernetif.c @@ -0,0 +1,284 @@ +/** + * @file + * Ethernet Interface Skeleton + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/* + * This file is a skeleton for developing Ethernet network interface + * drivers for lwIP. Add code to the low_level functions and do a + * search-and-replace for the word "ethernetif" to replace it with + * something that better describes your network interface. + */ + +#include "lwip/opt.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/sys.h" +#include "lwip/tcpip.h" +#include "lwip/icmp.h" +#include "lwip/lwip_timers.h" +#include "netif/etharp.h" +#include "err.h" +#include "ethernetif.h" +#include "queue.h" + +//#include "lwip/ethip6.h" //Evan add for ipv6 +#include +#include + +#define netifMTU (1500) +#define netifINTERFACE_TASK_STACK_SIZE ( 350 ) +#define netifINTERFACE_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) +#define netifGUARD_BLOCK_TIME ( 250 ) +/* The time to block waiting for input. */ +#define emacBLOCK_TIME_WAITING_FOR_INPUT ( ( portTickType ) 100 ) + + +#ifdef CONFIG_CONCURRENT_MODE +#define IF2NAME0 'r' +#define IF2NAME1 '2' +#endif + +static void arp_timer(void *arg); + + +/** + * In this function, the hardware should be initialized. + * Called from ethernetif_init(). + * + * @param netif the already initialized lwip network interface structure + * for this ethernetif + */ + +static void low_level_init(struct netif *netif) +{ + + /* set netif MAC hardware address length */ + netif->hwaddr_len = ETHARP_HWADDR_LEN; + + /* set netif maximum transfer unit */ + netif->mtu = 1500; + + /* Accept broadcast address and ARP traffic */ + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; + + /* Wlan interface is initialized later */ +} + + +/** + * This function should do the actual transmission of the packet. The packet is + * contained in the pbuf that is passed to the function. This pbuf + * might be chained. + * + * @param netif the lwip network interface structure for this ethernetif + * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type) + * @return ERR_OK if the packet could be sent + * an err_t value if the packet couldn't be sent + * + * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to + * strange results. You might consider waiting for space in the DMA queue + * to become availale since the stack doesn't retry to send a packet + * dropped because of memory failure (except for the TCP timers). + */ + +static err_t low_level_output(struct netif *netif, struct pbuf *p) +{ + + + /* Refer to eCos lwip eth_drv_send() */ + struct eth_drv_sg sg_list[MAX_ETH_DRV_SG]; + int sg_len = 0; + struct pbuf *q; + + if(!rltk_wlan_running(netif_get_idx(netif))) + return ERR_IF; + + for (q = p; q != NULL && sg_len < MAX_ETH_DRV_SG; q = q->next) { + sg_list[sg_len].buf = (unsigned int) q->payload; + sg_list[sg_len++].len = q->len; + } + + if (sg_len) { + if (rltk_wlan_send(netif_get_idx(netif), sg_list, sg_len, p->tot_len) == 0) + return ERR_OK; + else + return ERR_BUF; // return a non-fatal error + } + + return ERR_OK; +} + + +/** + * Should allocate a pbuf and transfer the bytes of the incoming + * packet from the interface into the pbuf. + * + * @param netif the lwip network interface structure for this ethernetif + * @return a pbuf filled with the received packet (including MAC header) + * NULL on memory error + */ +//static struct pbuf * low_level_input(struct netif *netif){} + + +/** + * This function is the ethernetif_input task, it is processed when a packet + * is ready to be read from the interface. It uses the function low_level_input() + * that should handle the actual reception of bytes from the network + * interface. Then the type of the received packet is determined and + * the appropriate input function is called. + * + * @param netif the lwip network interface structure for this ethernetif + */ +//void ethernetif_input( void * pvParameters ) + + +/* Refer to eCos eth_drv_recv to do similarly in ethernetif_input */ +void ethernetif_recv(struct netif *netif, int total_len) +{ + struct eth_drv_sg sg_list[MAX_ETH_DRV_SG]; + struct pbuf *p, *q; + int sg_len = 0; + + if(!rltk_wlan_running(netif_get_idx(netif))) + return; + + if ((total_len > MAX_ETH_MSG) || (total_len < 0)) + total_len = MAX_ETH_MSG; + + // Allocate buffer to store received packet + p = pbuf_alloc(PBUF_RAW, total_len, PBUF_POOL); + if (p == NULL) { + printf("\n\rCannot allocate pbuf to receive packet"); + return; + } + + // Create scatter list + for (q = p; q != NULL && sg_len < MAX_ETH_DRV_SG; q = q->next) { + sg_list[sg_len].buf = (unsigned int) q->payload; + sg_list[sg_len++].len = q->len; + } + + // Copy received packet to scatter list from wrapper rx skb + //printf("\n\rwlan:%c: Recv sg_len: %d, tot_len:%d", netif->name[1],sg_len, total_len); + rltk_wlan_recv(netif_get_idx(netif), sg_list, sg_len); + + // Pass received packet to the interface + if (ERR_OK != netif->input(p, netif)) + pbuf_free(p); + +} + +/** + * Should be called at the beginning of the program to set up the + * network interface. It calls the function low_level_init() to do the + * actual setup of the hardware. + * + * This function should be passed as a parameter to netif_add(). + * + * @param netif the lwip network interface structure for this ethernetif + * @return ERR_OK if the loopif is initialized + * ERR_MEM if private data couldn't be allocated + * any other err_t on error + */ +err_t ethernetif_init(struct netif *netif) +{ + LWIP_ASSERT("netif != NULL", (netif != NULL)); + +#if LWIP_NETIF_HOSTNAME + /* Initialize interface hostname */ + if(netif->name[1] == '0') + netif->hostname = "lwip0"; + else if(netif->name[1] == '1') + netif->hostname = "lwip1"; +#endif /* LWIP_NETIF_HOSTNAME */ + + netif->output = etharp_output; +//#if LWIP_IPV6 +// netif->output_ip6 = ethip6_output; +//#endif + netif->linkoutput = low_level_output; + + /* initialize the hardware */ + low_level_init(netif); + + etharp_init(); + + return ERR_OK; +} + +static void arp_timer(void *arg) +{ + etharp_tmr(); + sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); +} + +/* + * For FreeRTOS tickless + */ +int lwip_tickless_used = 0; + +int arp_timeout_exist(void) +{ + struct sys_timeouts *timeouts; + struct sys_timeo *t; + + timeouts = sys_arch_timeouts(); + + for(t = timeouts->next; t != NULL;t = t->next) + if(t->h == arp_timer) + return 1; + + return 0; +} + +//Called by rltk_wlan_PRE_SLEEP_PROCESSING() +void lwip_PRE_SLEEP_PROCESSING(void) +{ + if(arp_timeout_exist()) { + tcpip_untimeout(arp_timer, NULL); + } + lwip_tickless_used = 1; +} + +//Called in ips_leave() path, support tickless when wifi power wakeup due to ioctl or deinit +void lwip_POST_SLEEP_PROCESSING(void) +{ + if(lwip_tickless_used) { + tcpip_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); + } +} diff --git a/component/common/network/lwip/lwip_v1.4.1/port/realtek/freertos/ethernetif.h b/component/common/network/lwip/lwip_v1.4.1/port/realtek/freertos/ethernetif.h new file mode 100644 index 0000000..93139d1 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/port/realtek/freertos/ethernetif.h @@ -0,0 +1,13 @@ +#ifndef __ETHERNETIF_H__ +#define __ETHERNETIF_H__ + + +#include "lwip/err.h" +#include "lwip/netif.h" + +void ethernetif_recv(struct netif *netif, int total_len); +err_t ethernetif_init(struct netif *netif); +void lwip_PRE_SLEEP_PROCESSING(void); +void lwip_POST_SLEEP_PROCESSING(void); + +#endif diff --git a/component/common/network/lwip/lwip_v1.4.1/port/realtek/freertos/sys_arch.c b/component/common/network/lwip/lwip_v1.4.1/port/realtek/freertos/sys_arch.c new file mode 100644 index 0000000..c496791 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/port/realtek/freertos/sys_arch.c @@ -0,0 +1,563 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/* lwIP includes. */ +#include "lwip/debug.h" +#include "lwip/def.h" +#include "lwip/sys.h" +#include "lwip/mem.h" +#include "lwip/stats.h" +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "lwip/lwip_timers.h" + +xTaskHandle xTaskGetCurrentTaskHandle( void ) PRIVILEGED_FUNCTION; +extern void * vTaskGetCurrentTCB( void ); +struct timeoutlist +{ + struct sys_timeouts timeouts; + xTaskHandle pid; +}; + +/* This is the number of threads that can be started with sys_thread_new() */ +#define SYS_THREAD_MAX 6 + +static struct timeoutlist s_timeoutlist[SYS_THREAD_MAX]; +static u16_t s_nextthread = 0; + + +/*-----------------------------------------------------------------------------------*/ +// Creates an empty mailbox. +err_t sys_mbox_new(sys_mbox_t *mbox, int size) +{ + (void ) size; + + *mbox = xQueueCreate( archMESG_QUEUE_LENGTH, sizeof( void * ) ); + +#if SYS_STATS + ++lwip_stats.sys.mbox.used; + if (lwip_stats.sys.mbox.max < lwip_stats.sys.mbox.used) { + lwip_stats.sys.mbox.max = lwip_stats.sys.mbox.used; + } +#endif /* SYS_STATS */ + if (*mbox == NULL) + return ERR_MEM; + + return ERR_OK; +} + +/*-----------------------------------------------------------------------------------*/ +/* + Deallocates a mailbox. If there are messages still present in the + mailbox when the mailbox is deallocated, it is an indication of a + programming error in lwIP and the developer should be notified. +*/ +void sys_mbox_free(sys_mbox_t *mbox) +{ + if( uxQueueMessagesWaiting( *mbox ) ) + { + /* Line for breakpoint. Should never break here! */ + portNOP(); +#if SYS_STATS + lwip_stats.sys.mbox.err++; +#endif /* SYS_STATS */ + + // TODO notify the user of failure. + } + + vQueueDelete( *mbox ); + +#if SYS_STATS + --lwip_stats.sys.mbox.used; +#endif /* SYS_STATS */ +} + +/*-----------------------------------------------------------------------------------*/ +// Posts the "msg" to the mailbox. +void sys_mbox_post(sys_mbox_t *mbox, void *data) +{ + while ( xQueueSendToBack(*mbox, &data, portMAX_DELAY ) != pdTRUE ){} +} + + +/*-----------------------------------------------------------------------------------*/ +// Try to post the "msg" to the mailbox. +err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) +{ +err_t result; + + if ( xQueueSend( *mbox, &msg, 0 ) == pdPASS ) + { + result = ERR_OK; + } + else { + // could not post, queue must be full + result = ERR_MEM; + +#if SYS_STATS + lwip_stats.sys.mbox.err++; +#endif /* SYS_STATS */ + + } + + return result; +} + +/*-----------------------------------------------------------------------------------*/ +/* + Blocks the thread until a message arrives in the mailbox, but does + not block the thread longer than "timeout" milliseconds (similar to + the sys_arch_sem_wait() function). The "msg" argument is a result + parameter that is set by the function (i.e., by doing "*msg = + ptr"). The "msg" parameter maybe NULL to indicate that the message + should be dropped. + + The return values are the same as for the sys_arch_sem_wait() function: + Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a + timeout. + + Note that a function with a similar name, sys_mbox_fetch(), is + implemented by lwIP. +*/ +u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout) +{ +void *dummyptr; +portTickType StartTime, EndTime, Elapsed; + + StartTime = xTaskGetTickCount(); + + if ( msg == NULL ) + { + msg = &dummyptr; + } + + if ( timeout != 0 ) + { + if ( pdTRUE == xQueueReceive( *mbox, &(*msg), timeout / portTICK_RATE_MS ) ) + { + EndTime = xTaskGetTickCount(); + Elapsed = (EndTime - StartTime) * portTICK_RATE_MS; + + return ( Elapsed ); + } + else // timed out blocking for message + { + *msg = NULL; + + return SYS_ARCH_TIMEOUT; + } + } + else // block forever for a message. + { + while( pdTRUE != xQueueReceive( *mbox, &(*msg), portMAX_DELAY ) ){} // time is arbitrary + EndTime = xTaskGetTickCount(); + Elapsed = (EndTime - StartTime) * portTICK_RATE_MS; + + return ( Elapsed ); // return time blocked TODO test + } +} + +/*-----------------------------------------------------------------------------------*/ +/* + Similar to sys_arch_mbox_fetch, but if message is not ready immediately, we'll + return with SYS_MBOX_EMPTY. On success, 0 is returned. +*/ +u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg) +{ +void *dummyptr; + + if ( msg == NULL ) + { + msg = &dummyptr; + } + + if ( pdTRUE == xQueueReceive( *mbox, &(*msg), 0 ) ) + { + return ERR_OK; + } + else + { + return SYS_MBOX_EMPTY; + } +} +/*----------------------------------------------------------------------------------*/ +int sys_mbox_valid(sys_mbox_t *mbox) +{ + if (*mbox == SYS_MBOX_NULL) + return 0; + else + return 1; +} +/*-----------------------------------------------------------------------------------*/ +void sys_mbox_set_invalid(sys_mbox_t *mbox) +{ + *mbox = SYS_MBOX_NULL; +} + +/*-----------------------------------------------------------------------------------*/ +// Creates a new semaphore. The "count" argument specifies +// the initial state of the semaphore. +err_t sys_sem_new(sys_sem_t *sem, u8_t count) +{ + vSemaphoreCreateBinary(*sem ); + if(*sem == NULL) + { + +#if SYS_STATS + ++lwip_stats.sys.sem.err; +#endif /* SYS_STATS */ + return ERR_MEM; + } + + if(count == 0) // Means it can't be taken + { + xSemaphoreTake(*sem,1); + } + +#if SYS_STATS + ++lwip_stats.sys.sem.used; + if (lwip_stats.sys.sem.max < lwip_stats.sys.sem.used) { + lwip_stats.sys.sem.max = lwip_stats.sys.sem.used; + } +#endif /* SYS_STATS */ + + return ERR_OK; +} + +/*-----------------------------------------------------------------------------------*/ +/* + Blocks the thread while waiting for the semaphore to be + signaled. If the "timeout" argument is non-zero, the thread should + only be blocked for the specified time (measured in + milliseconds). + + If the timeout argument is non-zero, the return value is the number of + milliseconds spent waiting for the semaphore to be signaled. If the + semaphore wasn't signaled within the specified time, the return value is + SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore + (i.e., it was already signaled), the function may return zero. + + Notice that lwIP implements a function with a similar name, + sys_sem_wait(), that uses the sys_arch_sem_wait() function. +*/ +u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) +{ +portTickType StartTime, EndTime, Elapsed; + + StartTime = xTaskGetTickCount(); + + if( timeout != 0) + { + if( xSemaphoreTake( *sem, timeout / portTICK_RATE_MS ) == pdTRUE ) + { + EndTime = xTaskGetTickCount(); + Elapsed = (EndTime - StartTime) * portTICK_RATE_MS; + + return (Elapsed); // return time blocked TODO test + } + else + { + return SYS_ARCH_TIMEOUT; + } + } + else // must block without a timeout + { + while( xSemaphoreTake(*sem, portMAX_DELAY) != pdTRUE){} + EndTime = xTaskGetTickCount(); + Elapsed = (EndTime - StartTime) * portTICK_RATE_MS; + + return ( Elapsed ); // return time blocked + + } +} + +/*-----------------------------------------------------------------------------------*/ +// Signals a semaphore +void sys_sem_signal(sys_sem_t *sem) +{ + xSemaphoreGive(*sem); +} + +/*-----------------------------------------------------------------------------------*/ +// Deallocates a semaphore +void sys_sem_free(sys_sem_t *sem) +{ +#if SYS_STATS + --lwip_stats.sys.sem.used; +#endif /* SYS_STATS */ + + vQueueDelete(*sem); +} +/*-----------------------------------------------------------------------------------*/ +int sys_sem_valid(sys_sem_t *sem) +{ + if (*sem == SYS_SEM_NULL) + return 0; + else + return 1; +} + +/*-----------------------------------------------------------------------------------*/ +void sys_sem_set_invalid(sys_sem_t *sem) +{ + *sem = SYS_SEM_NULL; +} + +/*-----------------------------------------------------------------------------------*/ +// Initialize sys arch +void sys_init(void) +{ + int i; + + // Initialize the the per-thread sys_timeouts structures + // make sure there are no valid pids in the list + for(i = 0; i < SYS_THREAD_MAX; i++) + { + s_timeoutlist[i].pid = 0; + s_timeoutlist[i].timeouts.next = NULL; + } + + // keep track of how many threads have been created + s_nextthread = 0; +} + +/*-----------------------------------------------------------------------------------*/ +/* + Returns a pointer to the per-thread sys_timeouts structure. In lwIP, + each thread has a list of timeouts which is represented as a linked + list of sys_timeout structures. The sys_timeouts structure holds a + pointer to a linked list of timeouts. This function is called by + the lwIP timeout scheduler and must not return a NULL value. + + In a single threaded sys_arch implementation, this function will + simply return a pointer to a global sys_timeouts variable stored in + the sys_arch module. +*/ +struct sys_timeouts *sys_arch_timeouts(void) +{ +int i; +xTaskHandle pid; +struct timeoutlist *tl; + + pid = xTaskGetCurrentTaskHandle(); + + for(i = 0; i < s_nextthread; i++) + { + tl = &(s_timeoutlist[i]); + if(tl->pid == pid) + { + return &(tl->timeouts); + } + } + // Error + return NULL; +} +/*-----------------------------------------------------------------------------------*/ + /* Mutexes*/ +/*-----------------------------------------------------------------------------------*/ +/*-----------------------------------------------------------------------------------*/ +#if LWIP_COMPAT_MUTEX == 0 +/* Create a new mutex*/ +err_t sys_mutex_new(sys_mutex_t *mutex) { + + *mutex = xSemaphoreCreateMutex(); + if(*mutex == NULL) + { +#if SYS_STATS + ++lwip_stats.sys.mutex.err; +#endif /* SYS_STATS */ + return ERR_MEM; + } + +#if SYS_STATS + ++lwip_stats.sys.mutex.used; + if (lwip_stats.sys.mutex.max < lwip_stats.sys.mutex.used) { + lwip_stats.sys.mutex.max = lwip_stats.sys.mutex.used; + } +#endif /* SYS_STATS */ + return ERR_OK; +} +/*-----------------------------------------------------------------------------------*/ +/* Deallocate a mutex*/ +void sys_mutex_free(sys_mutex_t *mutex) +{ +#if SYS_STATS + --lwip_stats.sys.mutex.used; +#endif /* SYS_STATS */ + + vQueueDelete(*mutex); +} +/*-----------------------------------------------------------------------------------*/ +/* Lock a mutex*/ +void sys_mutex_lock(sys_mutex_t *mutex) +{ + sys_arch_sem_wait(*mutex, 0); +} + +/*-----------------------------------------------------------------------------------*/ +/* Unlock a mutex*/ +void sys_mutex_unlock(sys_mutex_t *mutex) +{ + xSemaphoreGive(*mutex); +} +#endif /*LWIP_COMPAT_MUTEX*/ +/*-----------------------------------------------------------------------------------*/ +// TODO +/*-----------------------------------------------------------------------------------*/ +/* + Starts a new thread with priority "prio" that will begin its execution in the + function "thread()". The "arg" argument will be passed as an argument to the + thread() function. The id of the new thread is returned. Both the id and + the priority are system dependent. +*/ +sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread , void *arg, int stacksize, int prio) +{ +xTaskHandle CreatedTask; +int result; + + if ( s_nextthread < SYS_THREAD_MAX ) + { + vPortEnterCritical(); + result = xTaskCreate( thread, ( signed portCHAR * ) name, stacksize, arg, prio, &CreatedTask ); + + // For each task created, store the task handle (pid) in the timers array. + // This scheme doesn't allow for threads to be deleted + s_timeoutlist[s_nextthread++].pid = CreatedTask; + vPortExitCritical(); + + if(result == pdPASS) + { + return CreatedTask; + } + else + { + return NULL; + } + } + else + { + return NULL; + } +} + +int sys_thread_delete(xTaskHandle pid) +{ + int i, isFind = 0; + struct timeoutlist *tl, *tend = NULL; + + pid = (( pid == NULL)?(xTaskHandle) vTaskGetCurrentTCB() : pid); + + if (s_nextthread) + { + vPortEnterCritical(); + + tend = &(s_timeoutlist[s_nextthread-1]);//the last one + for(i = 0; i < s_nextthread; i++) + { + tl = &(s_timeoutlist[i]); + if(tl->pid == pid) + {//find the task, exchange with the last one + memcpy(tl, tend, sizeof(struct timeoutlist)); + memset(tend, 0, sizeof(struct timeoutlist)); + s_nextthread --; + isFind = 1; + break; + } + } + + if (isFind) { + vTaskDelete( pid); + } + + vPortExitCritical(); + + if (isFind) + { + return pdPASS; + } + else + { + return pdFAIL; + } + } + else + { + return pdFAIL; + } +} + +/* + This optional function does a "fast" critical region protection and returns + the previous protection level. This function is only called during very short + critical regions. An embedded system which supports ISR-based drivers might + want to implement this function by disabling interrupts. Task-based systems + might want to implement this by using a mutex or disabling tasking. This + function should support recursive calls from the same task or interrupt. In + other words, sys_arch_protect() could be called while already protected. In + that case the return value indicates that it is already protected. + + sys_arch_protect() is only required if your port is supporting an operating + system. +*/ +sys_prot_t sys_arch_protect(void) +{ + vPortEnterCritical(); + return 1; +} + +/* + This optional function does a "fast" set of critical region protection to the + value specified by pval. See the documentation for sys_arch_protect() for + more information. This function is only required if your port is supporting + an operating system. +*/ +void sys_arch_unprotect(sys_prot_t pval) +{ + ( void ) pval; + vPortExitCritical(); +} + +/* + * Prints an assertion messages and aborts execution. + */ +void sys_assert( const char *msg ) +{ + ( void ) msg; + /*FSL:only needed for debugging + printf(msg); + printf("\n\r"); + */ + vPortEnterCritical( ); + for(;;) + ; +} diff --git a/component/common/network/lwip/lwip_v1.4.1/port/realtek/freertos/sys_arch.h b/component/common/network/lwip/lwip_v1.4.1/port/realtek/freertos/sys_arch.h new file mode 100644 index 0000000..83d0c08 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/port/realtek/freertos/sys_arch.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __SYS_RTXC_H__ +#define __SYS_RTXC_H__ + +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "semphr.h" + +#define SYS_MBOX_NULL (xQueueHandle)0 +#define SYS_SEM_NULL (xSemaphoreHandle)0 +#define SYS_DEFAULT_THREAD_STACK_DEPTH configMINIMAL_STACK_SIZE + +typedef xSemaphoreHandle sys_sem_t; +typedef xQueueHandle sys_mbox_t; +typedef xTaskHandle sys_thread_t; + +typedef struct _sys_arch_state_t +{ + // Task creation data. + char cTaskName[configMAX_TASK_NAME_LEN]; + unsigned short nStackDepth; + unsigned short nTaskCount; +} sys_arch_state_t; + + + +//extern sys_arch_state_t s_sys_arch_state; + +//void sys_set_default_state(); +//void sys_set_state(signed char *pTaskName, unsigned short nStackSize); + +/* Message queue constants. */ +#define archMESG_QUEUE_LENGTH ( 6 ) +#endif /* __SYS_RTXC_H__ */ + diff --git a/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/arch/bpstruct.h b/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/arch/bpstruct.h new file mode 100644 index 0000000..177758c --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/arch/bpstruct.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#if defined(__IAR_SYSTEMS_ICC__) +#pragma pack(1) +#endif + diff --git a/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/arch/cc.h b/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/arch/cc.h new file mode 100644 index 0000000..3ca260f --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/arch/cc.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __CC_H__ +#define __CC_H__ + +#include "cpu.h" + +typedef unsigned char u8_t; +typedef signed char s8_t; +typedef unsigned short u16_t; +typedef signed short s16_t; +typedef unsigned long u32_t; +typedef signed long s32_t; +typedef u32_t mem_ptr_t; +typedef int sys_prot_t; + + +#define U16_F "hu" +#define S16_F "d" +#define X16_F "hx" +#define U32_F "u" +#define S32_F "d" +#define X32_F "x" +#define SZT_F "uz" + + + + + +/* define compiler specific symbols */ +#if defined (__ICCARM__) + +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_STRUCT +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x +#define PACK_STRUCT_USE_INCLUDES + +#elif defined (__CC_ARM) + +#define PACK_STRUCT_BEGIN __packed +#define PACK_STRUCT_STRUCT +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x + +#elif defined (__GNUC__) + +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_STRUCT __attribute__ ((__packed__)) +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x + +#elif defined (__TASKING__) + +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_STRUCT +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x + +#endif + +#define LWIP_PLATFORM_ASSERT(x) //do { if(!(x)) while(1); } while(0) + +#endif /* __CC_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/arch/cpu.h b/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/arch/cpu.h new file mode 100644 index 0000000..a02f86d --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/arch/cpu.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __CPU_H__ +#define __CPU_H__ + +#define BYTE_ORDER LITTLE_ENDIAN + +#endif /* __CPU_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/arch/epstruct.h b/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/arch/epstruct.h new file mode 100644 index 0000000..1e1a049 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/arch/epstruct.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#if defined(__IAR_SYSTEMS_ICC__) +#pragma pack() +#endif + diff --git a/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/arch/init.h b/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/arch/init.h new file mode 100644 index 0000000..e622c73 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/arch/init.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __ARCH_INIT_H__ +#define __ARCH_INIT_H__ + +#define TCPIP_INIT_DONE(arg) tcpip_init_done(arg) + +void tcpip_init_done(void *); +int wait_for_tcpip_init(void); + +#endif /* __ARCH_INIT_H__ */ + + + + diff --git a/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/arch/lib.h b/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/arch/lib.h new file mode 100644 index 0000000..378f25b --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/arch/lib.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LIB_H__ +#define __LIB_H__ + +#include + + +#endif /* __LIB_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/arch/perf.h b/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/arch/perf.h new file mode 100644 index 0000000..334d42a --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/arch/perf.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __PERF_H__ +#define __PERF_H__ + +#define PERF_START /* null definition */ +#define PERF_STOP(x) /* null definition */ + +#endif /* __PERF_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/arch/sys_arch.h b/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/arch/sys_arch.h new file mode 100644 index 0000000..2e841bd --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/arch/sys_arch.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __SYS_RTXC_H__ +#define __SYS_RTXC_H__ + +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "semphr.h" + +#define SYS_MBOX_NULL (xQueueHandle)0 +#define SYS_SEM_NULL (xSemaphoreHandle)0 +#define SYS_DEFAULT_THREAD_STACK_DEPTH configMINIMAL_STACK_SIZE + +typedef xSemaphoreHandle sys_sem_t; +typedef xSemaphoreHandle sys_mutex_t; +typedef xQueueHandle sys_mbox_t; +typedef xTaskHandle sys_thread_t; + +typedef struct _sys_arch_state_t +{ + // Task creation data. + char cTaskName[configMAX_TASK_NAME_LEN]; + unsigned short nStackDepth; + unsigned short nTaskCount; +} sys_arch_state_t; + + + +//extern sys_arch_state_t s_sys_arch_state; + +//void sys_set_default_state(); +//void sys_set_state(signed char *pTaskName, unsigned short nStackSize); + +/* Message queue constants. */ +#define archMESG_QUEUE_LENGTH ( 6 ) +#endif /* __SYS_RTXC_H__ */ + diff --git a/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/freertos/MFC6A0B.tmp b/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/freertos/MFC6A0B.tmp new file mode 100644 index 0000000..5097f29 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/freertos/MFC6A0B.tmp @@ -0,0 +1,489 @@ +/** +* @file +* Ethernet Interface Skeleton +* +*/ + +/* +* Copyright (c) 2001-2004 Swedish Institute of Computer Science. +* 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. The name of the author may not be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. +* +* This file is part of the lwIP TCP/IP stack. +* +* Author: Adam Dunkels +* +*/ + +/* +* This file is a skeleton for developing Ethernet network interface +* drivers for lwIP. Add code to the low_level functions and do a +* search-and-replace for the word "ethernetif" to replace it with +* something that better describes your network interface. +*/ + +#include "lwip/opt.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +//#include "lwip/sys.h" +//#include "lwip/tcpip.h" +//#include "lwip/icmp.h" +#include "lwip/lwip_timers.h" +#include "netif/etharp.h" +#include "err.h" +#include "ethernetif.h" +//#include "queue.h" + +#include "main.h" // for the definition of CONFIG_WLAN + +#if !CONFIG_WLAN +#include "stm32f2x7_eth.h" +#else +#include +#endif +#include + +#include + + +#define netifMTU (1500) +#define netifINTERFACE_TASK_STACK_SIZE ( 350 ) +#define netifINTERFACE_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) +#define netifGUARD_BLOCK_TIME ( 250 ) +/* The time to block waiting for input. */ +#define emacBLOCK_TIME_WAITING_FOR_INPUT ( ( portTickType ) 100 ) + +#if !CONFIG_WLAN +/* Define those to better describe your network interface. */ +#define IFNAME0 's' +#define IFNAME1 't' + +static struct netif *s_pxNetIf = NULL; +xSemaphoreHandle s_xSemaphore = NULL; + + +/* Ethernet Rx & Tx DMA Descriptors */ +extern ETH_DMADESCTypeDef DMARxDscrTab[ETH_RXBUFNB], DMATxDscrTab[ETH_TXBUFNB]; + +/* Ethernet Receive buffers */ +extern uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE]; + +/* Ethernet Transmit buffers */ +extern uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE]; + +/* Global pointers to track current transmit and receive descriptors */ +extern ETH_DMADESCTypeDef *DMATxDescToSet; +extern ETH_DMADESCTypeDef *DMARxDescToGet; + +/* Global pointer for last received frame infos */ +extern ETH_DMA_Rx_Frame_infos *DMA_RX_FRAME_infos; + + +static void ethernetif_input( void * pvParameters ); +#endif + +static void arp_timer(void *arg); + + +/** +* In this function, the hardware should be initialized. +* Called from ethernetif_init(). +* +* @param netif the already initialized lwip network interface structure +* for this ethernetif +*/ +static void low_level_init(struct netif *netif) +{ + uint32_t i; + + /* set netif MAC hardware address length */ + netif->hwaddr_len = ETHARP_HWADDR_LEN; + +#if !CONFIG_WLAN + /* set netif MAC hardware address */ + netif->hwaddr[0] = MAC_ADDR0; + netif->hwaddr[1] = MAC_ADDR1; + netif->hwaddr[2] = MAC_ADDR2; + netif->hwaddr[3] = MAC_ADDR3; + netif->hwaddr[4] = MAC_ADDR4; + netif->hwaddr[5] = MAC_ADDR5; +#endif + + /* set netif maximum transfer unit */ + netif->mtu = 1500; + + /* Accept broadcast address and ARP traffic */ + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; + +#if !CONFIG_WLAN + s_pxNetIf =netif; + + /* create binary semaphore used for informing ethernetif of frame reception */ + if (s_xSemaphore == NULL) + { + vSemaphoreCreateBinary(s_xSemaphore); + xSemaphoreTake( s_xSemaphore, 0); + } + + /* initialize MAC address in ethernet MAC */ + ETH_MACAddressConfig(ETH_MAC_Address0, netif->hwaddr); + + /* Initialize Tx Descriptors list: Chain Mode */ + ETH_DMATxDescChainInit(DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB); + /* Initialize Rx Descriptors list: Chain Mode */ + ETH_DMARxDescChainInit(DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB); + + /* Enable Ethernet Rx interrrupt */ + { + for(i=0; iBuffer1Addr); + bufferoffset = 0; + + for(q = p; q != NULL; q = q->next) + { + if((DmaTxDesc->Status & ETH_DMATxDesc_OWN) != (u32)RESET) + { + goto error; + } + + /* Get bytes in current lwIP buffer */ + byteslefttocopy = q->len; + payloadoffset = 0; + + /* Check if the length of data to copy is bigger than Tx buffer size*/ + while( (byteslefttocopy + bufferoffset) > ETH_TX_BUF_SIZE ) + { + /* Copy data to Tx buffer*/ + memcpy( (u8_t*)((u8_t*)buffer + bufferoffset), (u8_t*)((u8_t*)q->payload + payloadoffset), (ETH_TX_BUF_SIZE - bufferoffset) ); + + /* Point to next descriptor */ + DmaTxDesc = (ETH_DMADESCTypeDef *)(DmaTxDesc->Buffer2NextDescAddr); + + /* Check if the buffer is available */ + if((DmaTxDesc->Status & ETH_DMATxDesc_OWN) != (u32)RESET) + { + goto error; + } + + buffer = (u8 *)(DmaTxDesc->Buffer1Addr); + + byteslefttocopy = byteslefttocopy - (ETH_TX_BUF_SIZE - bufferoffset); + payloadoffset = payloadoffset + (ETH_TX_BUF_SIZE - bufferoffset); + framelength = framelength + (ETH_TX_BUF_SIZE - bufferoffset); + bufferoffset = 0; + } + + /* Copy the remaining bytes */ + memcpy( (u8_t*)((u8_t*)buffer + bufferoffset), (u8_t*)((u8_t*)q->payload + payloadoffset), byteslefttocopy ); + bufferoffset = bufferoffset + byteslefttocopy; + framelength = framelength + byteslefttocopy; + } + + /* Prepare transmit descriptors to give to DMA*/ + ETH_Prepare_Transmit_Descriptors(framelength); + + /* Give semaphore and exit */ + error: + + xSemaphoreGive(xTxSemaphore); + } +#endif // #if !CONFIG_WLAN + + return ERR_OK; +} + + +#if !CONFIG_WLAN +/** +* Should allocate a pbuf and transfer the bytes of the incoming +* packet from the interface into the pbuf. +* +* @param netif the lwip network interface structure for this ethernetif +* @return a pbuf filled with the received packet (including MAC header) +* NULL on memory error +*/ +static struct pbuf * low_level_input(struct netif *netif) +{ + struct pbuf *p= NULL, *q; + u32_t len; + FrameTypeDef frame; + u8 *buffer; + __IO ETH_DMADESCTypeDef *DMARxDesc; + uint32_t bufferoffset = 0; + uint32_t payloadoffset = 0; + uint32_t byteslefttocopy = 0; + uint32_t i=0; + + /* get received frame */ + frame = ETH_Get_Received_Frame_interrupt(); + + /* Obtain the size of the packet and put it into the "len" variable. */ + len = frame.length; + buffer = (u8 *)frame.buffer; + + if (len > 0) + { + /* We allocate a pbuf chain of pbufs from the Lwip buffer pool */ + p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); + } + + if (p != NULL) + { + DMARxDesc = frame.descriptor; + bufferoffset = 0; + for(q = p; q != NULL; q = q->next) + { + byteslefttocopy = q->len; + payloadoffset = 0; + + /* Check if the length of bytes to copy in current pbuf is bigger than Rx buffer size*/ + while( (byteslefttocopy + bufferoffset) > ETH_RX_BUF_SIZE ) + { + /* Copy data to pbuf*/ + memcpy( (u8_t*)((u8_t*)q->payload + payloadoffset), (u8_t*)((u8_t*)buffer + bufferoffset), (ETH_RX_BUF_SIZE - bufferoffset)); + + /* Point to next descriptor */ + DMARxDesc = (ETH_DMADESCTypeDef *)(DMARxDesc->Buffer2NextDescAddr); + buffer = (unsigned char *)(DMARxDesc->Buffer1Addr); + + byteslefttocopy = byteslefttocopy - (ETH_RX_BUF_SIZE - bufferoffset); + payloadoffset = payloadoffset + (ETH_RX_BUF_SIZE - bufferoffset); + bufferoffset = 0; + } + + /* Copy remaining data in pbuf */ + memcpy( (u8_t*)((u8_t*)q->payload + payloadoffset), (u8_t*)((u8_t*)buffer + bufferoffset), byteslefttocopy); + bufferoffset = bufferoffset + byteslefttocopy; + } + + /* Release descriptors to DMA */ + DMARxDesc =frame.descriptor; + + /* Set Own bit in Rx descriptors: gives the buffers back to DMA */ + for (i=0; iSeg_Count; i++) + { + DMARxDesc->Status = ETH_DMARxDesc_OWN; + DMARxDesc = (ETH_DMADESCTypeDef *)(DMARxDesc->Buffer2NextDescAddr); + } + + /* Clear Segment_Count */ + DMA_RX_FRAME_infos->Seg_Count =0; + /* added for test*/ + } + + /* When Rx Buffer unavailable flag is set: clear it and resume reception */ + if ((ETH->DMASR & ETH_DMASR_RBUS) != (u32)RESET) + { + /* Clear RBUS ETHERNET DMA flag */ + ETH->DMASR = ETH_DMASR_RBUS; + /* Resume DMA reception */ + ETH->DMARPDR = 0; + } + return p; +} + + +/** +* This function is the ethernetif_input task, it is processed when a packet +* is ready to be read from the interface. It uses the function low_level_input() +* that should handle the actual reception of bytes from the network +* interface. Then the type of the received packet is determined and +* the appropriate input function is called. +* +* @param netif the lwip network interface structure for this ethernetif +*/ +void ethernetif_input( void * pvParameters ) +{ + struct pbuf *p; + + for( ;; ) + { + if (xSemaphoreTake( s_xSemaphore, emacBLOCK_TIME_WAITING_FOR_INPUT)==pdTRUE) + { +TRY_GET_NEXT_FRAME: + p = low_level_input( s_pxNetIf ); + if (p != NULL) + { + if (ERR_OK != s_pxNetIf->input( p, s_pxNetIf)) + { + pbuf_free(p); + } + else + { + goto TRY_GET_NEXT_FRAME; + } + } + + } + } +} +#endif +/** +* Should be called at the beginning of the program to set up the +* network interface. It calls the function low_level_init() to do the +* actual setup of the hardware. +* +* This function should be passed as a parameter to netif_add(). +* +* @param netif the lwip network interface structure for this ethernetif +* @return ERR_OK if the loopif is initialized +* ERR_MEM if private data couldn't be allocated +* any other err_t on error +*/ +err_t ethernetif_init(struct netif *netif) +{ + LWIP_ASSERT("netif != NULL", (netif != NULL)); + +#if !CONFIG_WLAN + /* ethernet */ + netif->name[0] = IFNAME0; + netif->name[1] = IFNAME1; +#else + /* wlan interface*/ +#if LWIP_NETIF_HOSTNAME + /* Initialize interface hostname */ + netif->hostname = "lwip"; +#endif /* LWIP_NETIF_HOSTNAME */ +#endif // WLAN + + netif->output = etharp_output; + netif->linkoutput = low_level_output; + + /* initialize the hardware */ + low_level_init(netif); + + etharp_init(); + sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); + + return ERR_OK; +} + + +static void arp_timer(void *arg) +{ + etharp_tmr(); + sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); +} + +/* + * For FreeRTOS tickless + */ +int lwip_tickless_used = 0; + +/* +int arp_timeout_exist(void) +{ + struct sys_timeouts *timeouts; + struct sys_timeo *t; + + timeouts = sys_arch_timeouts(); + + for(t = timeouts->next; t != NULL;t = t->next) + if(t->h == arp_timer) + return 1; + + return 0; +} +*/ +//Called by rltk_wlan_PRE_SLEEP_PROCESSING() +void lwip_PRE_SLEEP_PROCESSING(void) +{ + if(arp_timeout_exist()) { + tcpip_untimeout(arp_timer, NULL); + } + lwip_tickless_used = 1; +} + +//Called in ips_leave() path, support tickless when wifi power wakeup due to ioctl or deinit +void lwip_POST_SLEEP_PROCESSING(void) +{ + if(lwip_tickless_used) { + tcpip_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); + } +} + diff --git a/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/freertos/ethernetif.c b/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/freertos/ethernetif.c new file mode 100644 index 0000000..0f67357 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/freertos/ethernetif.c @@ -0,0 +1,653 @@ +/** +* @file +* Ethernet Interface Skeleton +* +*/ + +/* +* Copyright (c) 2001-2004 Swedish Institute of Computer Science. +* 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. The name of the author may not be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. +* +* This file is part of the lwIP TCP/IP stack. +* +* Author: Adam Dunkels +* +*/ + +/* +* This file is a skeleton for developing Ethernet network interface +* drivers for lwIP. Add code to the low_level functions and do a +* search-and-replace for the word "ethernetif" to replace it with +* something that better describes your network interface. +*/ + +#include "lwip/opt.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/sys.h" +#include "lwip/tcpip.h" +#include "lwip/icmp.h" +#include "lwip/lwip_timers.h" +#include "netif/etharp.h" +#include "err.h" +#include "ethernetif.h" +#include "queue.h" + +#include "main.h" // for the definition of CONFIG_WLAN + + +#if !CONFIG_WLAN +#include "stm32f2x7_eth.h" +#else +#include +#endif +#include + +#include + +#ifdef CONFIG_DONT_CARE_TP +#define netifMTU (576) +#else +#define netifMTU (1500) +#endif +#define netifINTERFACE_TASK_STACK_SIZE ( 350 ) +#define netifINTERFACE_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) +#define netifGUARD_BLOCK_TIME ( 250 ) +/* The time to block waiting for input. */ +#define emacBLOCK_TIME_WAITING_FOR_INPUT ( ( portTickType ) 100 ) +#define FAKE_PING_REPLY 0 + +#if !CONFIG_WLAN +/* Define those to better describe your network interface. */ +#define IFNAME0 's' +#define IFNAME1 't' + +static struct netif *s_pxNetIf = NULL; +xSemaphoreHandle s_xSemaphore = NULL; + + +/* Ethernet Rx & Tx DMA Descriptors */ +extern ETH_DMADESCTypeDef DMARxDscrTab[ETH_RXBUFNB], DMATxDscrTab[ETH_TXBUFNB]; + +/* Ethernet Receive buffers */ +extern uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE]; + +/* Ethernet Transmit buffers */ +extern uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE]; + +/* Global pointers to track current transmit and receive descriptors */ +extern ETH_DMADESCTypeDef *DMATxDescToSet; +extern ETH_DMADESCTypeDef *DMARxDescToGet; + +/* Global pointer for last received frame infos */ +extern ETH_DMA_Rx_Frame_infos *DMA_RX_FRAME_infos; + +static void ethernetif_input( void * pvParameters ); +#endif + +static void arp_timer(void *arg); + + +/** +* In this function, the hardware should be initialized. +* Called from ethernetif_init(). +* +* @param netif the already initialized lwip network interface structure +* for this ethernetif +*/ +static void low_level_init(struct netif *netif) +{ + uint32_t i; + + /* set netif MAC hardware address length */ + netif->hwaddr_len = ETHARP_HWADDR_LEN; + +#if !CONFIG_WLAN + /* set netif MAC hardware address */ + netif->hwaddr[0] = MAC_ADDR0; + netif->hwaddr[1] = MAC_ADDR1; + netif->hwaddr[2] = MAC_ADDR2; + netif->hwaddr[3] = MAC_ADDR3; + netif->hwaddr[4] = MAC_ADDR4; + netif->hwaddr[5] = MAC_ADDR5; +#endif + + /* set netif maximum transfer unit */ + netif->mtu = netifMTU; + + /* Accept broadcast address and ARP traffic */ + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; + +#if !CONFIG_WLAN + s_pxNetIf =netif; + + /* create binary semaphore used for informing ethernetif of frame reception */ + if (s_xSemaphore == NULL) + { + s_xSemaphore= xSemaphoreCreateCounting(20,0); + } + + /* initialize MAC address in ethernet MAC */ + ETH_MACAddressConfig(ETH_MAC_Address0, netif->hwaddr); + + /* Initialize Tx Descriptors list: Chain Mode */ + ETH_DMATxDescChainInit(DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB); + /* Initialize Rx Descriptors list: Chain Mode */ + ETH_DMARxDescChainInit(DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB); + + /* Enable Ethernet Rx interrrupt */ + { + for(i=0; itot_len, PBUF_POOL); + if (p == NULL) { + printf("\n\rCannot allocate pbuf to receive packet"); + return; + } + for (tq = q, tp = p, q_len = tq->len; tp != NULL ; tp = tp->next) + { + p_len = tp->len; + while(p_len) + { + if(q_len > p_len) { + memcpy((char*)tq->payload + (tq->len - q_len), (char*)tp->payload + (tp->len - p_len), p_len); + q_len -= p_len; + p_len = 0; + }else{ + memcpy((char*)tq->payload + (tq->len - q_len), (char*)tp->payload + (tp->len - p_len), q_len); + p_len -= q_len; + tq = tq->next; + q_len = tq->len; + } + } + } + p_eth = (struct eth_hdr *)p->payload; + q_eth = (struct eth_hdr *)q->payload; + p_arp = (struct etharp_hdr *)((char*)(p->payload) + sizeof(struct eth_hdr)); + q_arp = (struct etharp_hdr *)((char*)(q->payload) + sizeof(struct eth_hdr)); + + q_eth->dest = p_eth->src; + q_eth->src = fake_src_mac; + q_arp->opcode = htons(ARP_REPLY); + q_arp->shwaddr = fake_src_mac; + q_arp->sipaddr = p_arp->dipaddr; + q_arp->dhwaddr = p_eth->src; + q_arp->dipaddr = p_arp->sipaddr; + + if(0){ + int i; + char *buf = q->payload; + printf("\n\r"); + for(i=0;itot_len;i++) + printf("0x%02x, ", buf[i]); + printf("\n\r"); + } + if (ERR_OK != netif->input(q, netif)){ + printf("\n\rfake_arp_reply input error"); + pbuf_free(q); + }else + printf("\n\rfake arp reply \n\r"); +} + +void fake_echo_reply(struct netif *netif, struct pbuf *p) +{ + struct pbuf *q, *tq, *tp; + int q_len, p_len; + struct eth_hdr *p_eth, *q_eth; + struct ip_hdr *p_ip, *q_ip; + struct icmp_echo_hdr *p_echo, *q_echo; + + // Allocate buffer to store received packet + q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_POOL); + if (p == NULL) { + printf("\n\rCannot allocate pbuf to receive packet"); + return; + } + for (tq = q, tp = p, q_len = tq->len; tp != NULL ; tp = tp->next) + { + p_len = tp->len; + while(p_len) + { + if(q_len > p_len) { + memcpy((char*)tq->payload + (tq->len - q_len), (char*)tp->payload + (tp->len - p_len), p_len); + q_len -= p_len; + p_len = 0; + }else{ + memcpy((char*)tq->payload + (tq->len - q_len), (char*)tp->payload + (tp->len - p_len), q_len); + p_len -= q_len; + tq = tq->next; + q_len = tq->len; + } + } + } + p_eth = (struct eth_hdr *)p->payload; + q_eth = (struct eth_hdr *)q->payload; + p_ip = (struct ip_hdr *)((char*)(p->payload) + sizeof(struct eth_hdr)); + q_ip = (struct ip_hdr *)((char*)(q->payload) + sizeof(struct eth_hdr)); + p_echo = (struct icmp_echo_hdr *)((char*)(p->payload) + sizeof(struct eth_hdr) + sizeof(struct ip_hdr)); + q_echo = (struct icmp_echo_hdr *)((char*)(q->payload) + sizeof(struct eth_hdr) + sizeof(struct ip_hdr)); + + q_eth->dest = p_eth->src; + q_eth->src = p_eth->dest; + q_ip->src.addr = p_ip->dest.addr; + q_ip->dest.addr = p_ip->src.addr; + q_ip->_chksum = 0; + q_ip->_chksum = inet_chksum(q_ip, sizeof(struct ip_hdr)); + q_echo->type = ICMP_ER; + q_echo->code = 0; + q_echo->chksum = 0; + q_echo->chksum = inet_chksum(q_echo, q->tot_len - sizeof(struct eth_hdr) - sizeof(struct ip_hdr)); + + if(0){ + int i; + char *buf = q->payload; + printf("\n\r"); + for(i=0;itot_len;i++) + printf("0x%02x, ", buf[i]); + printf("\n\r"); + } + if (ERR_OK != netif->input(q, netif)){ + printf("\n\rfake_echo_reply input error"); + pbuf_free(q); + }else + printf("\n\rfake echo reply \n\r"); +} +#endif // #if FAKE_PING_REPLY + +/** +* This function should do the actual transmission of the packet. The packet is +* contained in the pbuf that is passed to the function. This pbuf +* might be chained. +* +* @param netif the lwip network interface structure for this ethernetif +* @param p the MAC packet to send (e.g. IP packet including MAC addresses and type) +* @return ERR_OK if the packet could be sent +* an err_t value if the packet couldn't be sent +* +* @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to +* strange results. You might consider waiting for space in the DMA queue +* to become availale since the stack doesn't retry to send a packet +* dropped because of memory failure (except for the TCP timers). +*/ + +static err_t low_level_output(struct netif *netif, struct pbuf *p) +{ +#if !CONFIG_WLAN + static xSemaphoreHandle xTxSemaphore = NULL; + struct pbuf *q; + uint32_t l = 0; + u8 *buffer ; + + if (xTxSemaphore == NULL) + { + vSemaphoreCreateBinary (xTxSemaphore); + } + + if (xSemaphoreTake(xTxSemaphore, netifGUARD_BLOCK_TIME)) + { + buffer = (u8 *)(DMATxDescToSet->Buffer1Addr); + for(q = p; q != NULL; q = q->next) + { + memcpy((u8_t*)&buffer[l], q->payload, q->len); + l = l + q->len; + } + ETH_Prepare_Transmit_Descriptors(l); + xSemaphoreGive(xTxSemaphore); + } +#else + /* Refer to eCos lwip eth_drv_send() */ + struct eth_drv_sg sg_list[MAX_ETH_DRV_SG]; + int sg_len = 0; + struct pbuf *q; + + if(!rltk_wlan_running(netif_get_idx(netif))) + return ERR_IF; + + for (q = p; q != NULL && sg_len < MAX_ETH_DRV_SG; q = q->next) { + sg_list[sg_len].buf = (unsigned int) q->payload; + sg_list[sg_len++].len = q->len; + } + +#if FAKE_PING_REPLY + { + char *header = p->payload; + if(header[12] == 0x08 && header[13] == 0x06) + { // arp packet + if(header[21] == 0x01) + { // arp request packet + printf("\n\rfake_ping: arp request packet."); + if(0) + { + int i; + printf("\n\r"); + for (q = p; q != NULL; q = q->next) + { + char *buf = q->payload; + for(i=0;ilen;i++) + printf("0x%02x, ", buf[i]); + } + printf("\n\r"); + } + fake_arp_reply(netif, p); + return ERR_OK; + } + }else if(header[12] == 0x08 && header[13] == 0x00) + { // ip packet + if(header[15] == 0x00 && header[23] == 0x01) + { // icmp packet + printf("\n\rfake_ping: icmp packet."); + if(0){ + int i; + printf("\n\r"); + for (q = p; q != NULL; q = q->next) + { + char *buf = q->payload; + for(i=0;ilen;i++) + printf("0x%02x, ", buf[i]); + } + printf("\n\r"); + } + fake_echo_reply(netif, p); + return ERR_OK; + } + } + } +#endif // #if FAKE_PING_REPLY + if (sg_len) + rltk_wlan_send(netif_get_idx(netif), sg_list, sg_len, p->tot_len); +#endif // #if !CONFIG_WLAN + + return ERR_OK; +} + + +#if !CONFIG_WLAN +/** +* Should allocate a pbuf and transfer the bytes of the incoming +* packet from the interface into the pbuf. +* +* @param netif the lwip network interface structure for this ethernetif +* @return a pbuf filled with the received packet (including MAC header) +* NULL on memory error +*/ +static struct pbuf * low_level_input(struct netif *netif) +{ + struct pbuf *p, *q; + u16_t len; + uint32_t l=0,i =0; + FrameTypeDef frame; + u8 *buffer; + __IO ETH_DMADESCTypeDef *DMARxNextDesc; + + p = NULL; + + /* Get received frame */ + frame = ETH_Get_Received_Frame_interrupt(); + + /* check that frame has no error */ + if ((frame.descriptor->Status & ETH_DMARxDesc_ES) == (uint32_t)RESET) + { + + /* Obtain the size of the packet and put it into the "len" variable. */ + len = frame.length; + buffer = (u8 *)frame.buffer; + + /* We allocate a pbuf chain of pbufs from the pool. */ + p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); + + /* Copy received frame from ethernet driver buffer to stack buffer */ + if (p != NULL) + { + for (q = p; q != NULL; q = q->next) + { + memcpy((u8_t*)q->payload, (u8_t*)&buffer[l], q->len); + l = l + q->len; + } + } + } + + /* Release descriptors to DMA */ + /* Check if received frame with multiple DMA buffer segments */ + if (DMA_RX_FRAME_infos->Seg_Count > 1) + { + DMARxNextDesc = DMA_RX_FRAME_infos->FS_Rx_Desc; + } + else + { + DMARxNextDesc = frame.descriptor; + } + + /* Set Own bit in Rx descriptors: gives the buffers back to DMA */ + for (i=0; iSeg_Count; i++) + { + DMARxNextDesc->Status = ETH_DMARxDesc_OWN; + DMARxNextDesc = (ETH_DMADESCTypeDef *)(DMARxNextDesc->Buffer2NextDescAddr); + } + + /* Clear Segment_Count */ + DMA_RX_FRAME_infos->Seg_Count =0; + + + /* When Rx Buffer unavailable flag is set: clear it and resume reception */ + if ((ETH->DMASR & ETH_DMASR_RBUS) != (u32)RESET) + { + /* Clear RBUS ETHERNET DMA flag */ + ETH->DMASR = ETH_DMASR_RBUS; + + /* Resume DMA reception */ + ETH->DMARPDR = 0; + } + return p; +} + + +/** +* This function is the ethernetif_input task, it is processed when a packet +* is ready to be read from the interface. It uses the function low_level_input() +* that should handle the actual reception of bytes from the network +* interface. Then the type of the received packet is determined and +* the appropriate input function is called. +* +* @param netif the lwip network interface structure for this ethernetif +*/ +void ethernetif_input( void * pvParameters ) +{ + struct pbuf *p; + + for( ;; ) + { + if (xSemaphoreTake( s_xSemaphore, emacBLOCK_TIME_WAITING_FOR_INPUT)==pdTRUE) + { + p = low_level_input( s_pxNetIf ); + if (ERR_OK != s_pxNetIf->input( p, s_pxNetIf)) + { + pbuf_free(p); + p=NULL; + } + } + } +} +#endif + +/* Refer to eCos eth_drv_recv to do similarly in ethernetif_input */ +void ethernetif_recv(struct netif *netif, int total_len) +{ +#if CONFIG_WLAN + struct eth_drv_sg sg_list[MAX_ETH_DRV_SG]; + struct pbuf *p, *q; + int sg_len = 0; + + if(!rltk_wlan_running(netif_get_idx(netif))) + return; + + if ((total_len > MAX_ETH_MSG) || (total_len < 0)) + total_len = MAX_ETH_MSG; + + // Allocate buffer to store received packet + p = pbuf_alloc(PBUF_RAW, total_len, PBUF_POOL); + if (p == NULL) { + printf("\n\rCannot allocate pbuf to receive packet"); + return; + } + + // Create scatter list + for (q = p; q != NULL && sg_len < MAX_ETH_DRV_SG; q = q->next) { + sg_list[sg_len].buf = (unsigned int) q->payload; + sg_list[sg_len++].len = q->len; + } + + // Copy received packet to scatter list from wrapper rx skb + //printf("\n\rwlan:%c: Recv sg_len: %d, tot_len:%d", netif->name[1],sg_len, total_len); + rltk_wlan_recv(netif_get_idx(netif), sg_list, sg_len); + + // Pass received packet to the interface + if (ERR_OK != netif->input(p, netif)) + pbuf_free(p); +#endif +} + +/** +* Should be called at the beginning of the program to set up the +* network interface. It calls the function low_level_init() to do the +* actual setup of the hardware. +* +* This function should be passed as a parameter to netif_add(). +* +* @param netif the lwip network interface structure for this ethernetif +* @return ERR_OK if the loopif is initialized +* ERR_MEM if private data couldn't be allocated +* any other err_t on error +*/ +err_t ethernetif_init(struct netif *netif) +{ + LWIP_ASSERT("netif != NULL", (netif != NULL)); + +#if !CONFIG_WLAN + /* ethernet */ + netif->name[0] = IFNAME0; + netif->name[1] = IFNAME1; +#else + /* wlan interface*/ +#if LWIP_NETIF_HOSTNAME + /* Initialize interface hostname */ + if(netif->name[1] == '0') + netif->hostname = "lwip0"; + else if(netif->name[1] == '1') + netif->hostname = "lwip1"; +#endif /* LWIP_NETIF_HOSTNAME */ + +#endif // WLAN + + netif->output = etharp_output; + netif->linkoutput = low_level_output; + + /* initialize the hardware */ + low_level_init(netif); + + etharp_init(); + sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); + + return ERR_OK; +} + + +static void arp_timer(void *arg) +{ + etharp_tmr(); + sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); +} + +/* + * For FreeRTOS tickless + */ +int lwip_tickless_used = 0; + + +int arp_timeout_exist(void) +{ + struct sys_timeouts *timeouts; + struct sys_timeo *t; + + timeouts = sys_arch_timeouts(); + + for(t = timeouts->next; t != NULL;t = t->next) + if(t->h == arp_timer) + return 1; + + return 0; +} + +//Called by rltk_wlan_PRE_SLEEP_PROCESSING() +void lwip_PRE_SLEEP_PROCESSING(void) +{ + if(arp_timeout_exist()) { + tcpip_untimeout(arp_timer, NULL); + } + lwip_tickless_used = 1; +} + +//Called in ips_leave() path, support tickless when wifi power wakeup due to ioctl or deinit +void lwip_POST_SLEEP_PROCESSING(void) +{ + if(lwip_tickless_used) { + tcpip_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); + } +} diff --git a/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/freertos/ethernetif.h b/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/freertos/ethernetif.h new file mode 100644 index 0000000..93139d1 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/freertos/ethernetif.h @@ -0,0 +1,13 @@ +#ifndef __ETHERNETIF_H__ +#define __ETHERNETIF_H__ + + +#include "lwip/err.h" +#include "lwip/netif.h" + +void ethernetif_recv(struct netif *netif, int total_len); +err_t ethernetif_init(struct netif *netif); +void lwip_PRE_SLEEP_PROCESSING(void); +void lwip_POST_SLEEP_PROCESSING(void); + +#endif diff --git a/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/freertos/sys_arch.c b/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/freertos/sys_arch.c new file mode 100644 index 0000000..3d111c6 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/freertos/sys_arch.c @@ -0,0 +1,515 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/* lwIP includes. */ +#include "lwip/debug.h" +#include "lwip/def.h" +#include "lwip/sys.h" +#include "lwip/mem.h" +#include "lwip/stats.h" +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "lwip/lwip_timers.h" + +xTaskHandle xTaskGetCurrentTaskHandle( void ) PRIVILEGED_FUNCTION; + +struct timeoutlist +{ + struct sys_timeouts timeouts; + xTaskHandle pid; +}; + +/* This is the number of threads that can be started with sys_thread_new() */ +#define SYS_THREAD_MAX 6 + +static struct timeoutlist s_timeoutlist[SYS_THREAD_MAX]; +static u16_t s_nextthread = 0; + + +/*-----------------------------------------------------------------------------------*/ +// Creates an empty mailbox. +err_t sys_mbox_new(sys_mbox_t *mbox, int size) +{ + (void ) size; + + *mbox = xQueueCreate( archMESG_QUEUE_LENGTH, sizeof( void * ) ); + +#if SYS_STATS + ++lwip_stats.sys.mbox.used; + if (lwip_stats.sys.mbox.max < lwip_stats.sys.mbox.used) { + lwip_stats.sys.mbox.max = lwip_stats.sys.mbox.used; + } +#endif /* SYS_STATS */ + if (*mbox == NULL) + return ERR_MEM; + + return ERR_OK; +} + +/*-----------------------------------------------------------------------------------*/ +/* + Deallocates a mailbox. If there are messages still present in the + mailbox when the mailbox is deallocated, it is an indication of a + programming error in lwIP and the developer should be notified. +*/ +void sys_mbox_free(sys_mbox_t *mbox) +{ + if( uxQueueMessagesWaiting( *mbox ) ) + { + /* Line for breakpoint. Should never break here! */ + portNOP(); +#if SYS_STATS + lwip_stats.sys.mbox.err++; +#endif /* SYS_STATS */ + + // TODO notify the user of failure. + } + + vQueueDelete( *mbox ); + +#if SYS_STATS + --lwip_stats.sys.mbox.used; +#endif /* SYS_STATS */ +} + +/*-----------------------------------------------------------------------------------*/ +// Posts the "msg" to the mailbox. +void sys_mbox_post(sys_mbox_t *mbox, void *data) +{ + while ( xQueueSendToBack(*mbox, &data, portMAX_DELAY ) != pdTRUE ){} +} + + +/*-----------------------------------------------------------------------------------*/ +// Try to post the "msg" to the mailbox. +err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) +{ +err_t result; + + if ( xQueueSend( *mbox, &msg, 0 ) == pdPASS ) + { + result = ERR_OK; + } + else { + // could not post, queue must be full + result = ERR_MEM; + +#if SYS_STATS + lwip_stats.sys.mbox.err++; +#endif /* SYS_STATS */ + + } + + return result; +} + +/*-----------------------------------------------------------------------------------*/ +/* + Blocks the thread until a message arrives in the mailbox, but does + not block the thread longer than "timeout" milliseconds (similar to + the sys_arch_sem_wait() function). The "msg" argument is a result + parameter that is set by the function (i.e., by doing "*msg = + ptr"). The "msg" parameter maybe NULL to indicate that the message + should be dropped. + + The return values are the same as for the sys_arch_sem_wait() function: + Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a + timeout. + + Note that a function with a similar name, sys_mbox_fetch(), is + implemented by lwIP. +*/ +u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout) +{ +void *dummyptr; +portTickType StartTime, EndTime, Elapsed; + + StartTime = xTaskGetTickCount(); + + if ( msg == NULL ) + { + msg = &dummyptr; + } + + if ( timeout != 0 ) + { + if ( pdTRUE == xQueueReceive( *mbox, &(*msg), timeout / portTICK_RATE_MS ) ) + { + EndTime = xTaskGetTickCount(); + Elapsed = (EndTime - StartTime) * portTICK_RATE_MS; + + return ( Elapsed ); + } + else // timed out blocking for message + { + *msg = NULL; + + return SYS_ARCH_TIMEOUT; + } + } + else // block forever for a message. + { + while( pdTRUE != xQueueReceive( *mbox, &(*msg), portMAX_DELAY ) ){} // time is arbitrary + EndTime = xTaskGetTickCount(); + Elapsed = (EndTime - StartTime) * portTICK_RATE_MS; + + return ( Elapsed ); // return time blocked TODO test + } +} + +/*-----------------------------------------------------------------------------------*/ +/* + Similar to sys_arch_mbox_fetch, but if message is not ready immediately, we'll + return with SYS_MBOX_EMPTY. On success, 0 is returned. +*/ +u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg) +{ +void *dummyptr; + + if ( msg == NULL ) + { + msg = &dummyptr; + } + + if ( pdTRUE == xQueueReceive( *mbox, &(*msg), 0 ) ) + { + return ERR_OK; + } + else + { + return SYS_MBOX_EMPTY; + } +} +/*----------------------------------------------------------------------------------*/ +int sys_mbox_valid(sys_mbox_t *mbox) +{ + if (*mbox == SYS_MBOX_NULL) + return 0; + else + return 1; +} +/*-----------------------------------------------------------------------------------*/ +void sys_mbox_set_invalid(sys_mbox_t *mbox) +{ + *mbox = SYS_MBOX_NULL; +} + +/*-----------------------------------------------------------------------------------*/ +// Creates a new semaphore. The "count" argument specifies +// the initial state of the semaphore. +err_t sys_sem_new(sys_sem_t *sem, u8_t count) +{ + vSemaphoreCreateBinary(*sem ); + if(*sem == NULL) + { +#if SYS_STATS + ++lwip_stats.sys.sem.err; +#endif /* SYS_STATS */ + return ERR_MEM; + } + + if(count == 0) // Means it can't be taken + { + xSemaphoreTake(*sem,1); + } + +#if SYS_STATS + ++lwip_stats.sys.sem.used; + if (lwip_stats.sys.sem.max < lwip_stats.sys.sem.used) { + lwip_stats.sys.sem.max = lwip_stats.sys.sem.used; + } +#endif /* SYS_STATS */ + + return ERR_OK; +} + +/*-----------------------------------------------------------------------------------*/ +/* + Blocks the thread while waiting for the semaphore to be + signaled. If the "timeout" argument is non-zero, the thread should + only be blocked for the specified time (measured in + milliseconds). + + If the timeout argument is non-zero, the return value is the number of + milliseconds spent waiting for the semaphore to be signaled. If the + semaphore wasn't signaled within the specified time, the return value is + SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore + (i.e., it was already signaled), the function may return zero. + + Notice that lwIP implements a function with a similar name, + sys_sem_wait(), that uses the sys_arch_sem_wait() function. +*/ +u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) +{ +portTickType StartTime, EndTime, Elapsed; + + StartTime = xTaskGetTickCount(); + + if( timeout != 0) + { + if( xSemaphoreTake( *sem, timeout / portTICK_RATE_MS ) == pdTRUE ) + { + EndTime = xTaskGetTickCount(); + Elapsed = (EndTime - StartTime) * portTICK_RATE_MS; + + return (Elapsed); // return time blocked TODO test + } + else + { + return SYS_ARCH_TIMEOUT; + } + } + else // must block without a timeout + { + while( xSemaphoreTake(*sem, portMAX_DELAY) != pdTRUE){} + EndTime = xTaskGetTickCount(); + Elapsed = (EndTime - StartTime) * portTICK_RATE_MS; + + return ( Elapsed ); // return time blocked + + } +} + +/*-----------------------------------------------------------------------------------*/ +// Signals a semaphore +void sys_sem_signal(sys_sem_t *sem) +{ + xSemaphoreGive(*sem); +} + +/*-----------------------------------------------------------------------------------*/ +// Deallocates a semaphore +void sys_sem_free(sys_sem_t *sem) +{ +#if SYS_STATS + --lwip_stats.sys.sem.used; +#endif /* SYS_STATS */ + + vQueueDelete(*sem); +} +/*-----------------------------------------------------------------------------------*/ +int sys_sem_valid(sys_sem_t *sem) +{ + if (*sem == SYS_SEM_NULL) + return 0; + else + return 1; +} + +/*-----------------------------------------------------------------------------------*/ +void sys_sem_set_invalid(sys_sem_t *sem) +{ + *sem = SYS_SEM_NULL; +} + +/*-----------------------------------------------------------------------------------*/ +// Initialize sys arch +void sys_init(void) +{ + int i; + + // Initialize the the per-thread sys_timeouts structures + // make sure there are no valid pids in the list + for(i = 0; i < SYS_THREAD_MAX; i++) + { + s_timeoutlist[i].pid = 0; + s_timeoutlist[i].timeouts.next = NULL; + } + + // keep track of how many threads have been created + s_nextthread = 0; +} + +/* + Returns a pointer to the per-thread sys_timeouts structure. In lwIP, + each thread has a list of timeouts which is represented as a linked + list of sys_timeout structures. The sys_timeouts structure holds a + pointer to a linked list of timeouts. This function is called by + the lwIP timeout scheduler and must not return a NULL value. + + In a single threaded sys_arch implementation, this function will + simply return a pointer to a global sys_timeouts variable stored in + the sys_arch module. +*/ +struct sys_timeouts* sys_arch_timeouts(void) +{ +int i; +xTaskHandle pid; +struct timeoutlist *tl; + + pid = xTaskGetCurrentTaskHandle(); + + for(i = 0; i < s_nextthread; i++) + { + tl = &(s_timeoutlist[i]); + if(tl->pid == pid) + { + return &(tl->timeouts); + } + } + // Error + return NULL; +} +/*-----------------------------------------------------------------------------------*/ + /* Mutexes*/ +/*-----------------------------------------------------------------------------------*/ +/*-----------------------------------------------------------------------------------*/ +#if LWIP_COMPAT_MUTEX == 0 +/* Create a new mutex*/ +err_t sys_mutex_new(sys_mutex_t *mutex) { + + *mutex = xSemaphoreCreateMutex(); + if(*mutex == NULL) + { +#if SYS_STATS + ++lwip_stats.sys.mutex.err; +#endif /* SYS_STATS */ + return ERR_MEM; + } + +#if SYS_STATS + ++lwip_stats.sys.mutex.used; + if (lwip_stats.sys.mutex.max < lwip_stats.sys.mutex.used) { + lwip_stats.sys.mutex.max = lwip_stats.sys.mutex.used; + } +#endif /* SYS_STATS */ + return ERR_OK; +} +/*-----------------------------------------------------------------------------------*/ +/* Deallocate a mutex*/ +void sys_mutex_free(sys_mutex_t *mutex) +{ +#if SYS_STATS + --lwip_stats.sys.mutex.used; +#endif /* SYS_STATS */ + + vQueueDelete(*mutex); +} +/*-----------------------------------------------------------------------------------*/ +/* Lock a mutex*/ +void sys_mutex_lock(sys_mutex_t *mutex) +{ + sys_arch_sem_wait(*mutex, 0); +} + +/*-----------------------------------------------------------------------------------*/ +/* Unlock a mutex*/ +void sys_mutex_unlock(sys_mutex_t *mutex) +{ + xSemaphoreGive(*mutex); +} +#endif /*LWIP_COMPAT_MUTEX*/ +/*-----------------------------------------------------------------------------------*/ +// TODO +/*-----------------------------------------------------------------------------------*/ +/* + Starts a new thread with priority "prio" that will begin its execution in the + function "thread()". The "arg" argument will be passed as an argument to the + thread() function. The id of the new thread is returned. Both the id and + the priority are system dependent. +*/ +sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread , void *arg, int stacksize, int prio) +{ +xTaskHandle CreatedTask; +int result; + + if ( s_nextthread < SYS_THREAD_MAX ) + { + vPortEnterCritical(); + result = xTaskCreate( thread, ( signed portCHAR * ) name, stacksize, arg, prio, &CreatedTask ); + + // For each task created, store the task handle (pid) in the timers array. + // This scheme doesn't allow for threads to be deleted + s_timeoutlist[s_nextthread++].pid = CreatedTask; + vPortExitCritical(); + + if(result == pdPASS) + { + return CreatedTask; + } + else + { + return NULL; + } + } + else + { + return NULL; + } +} + +/* + This optional function does a "fast" critical region protection and returns + the previous protection level. This function is only called during very short + critical regions. An embedded system which supports ISR-based drivers might + want to implement this function by disabling interrupts. Task-based systems + might want to implement this by using a mutex or disabling tasking. This + function should support recursive calls from the same task or interrupt. In + other words, sys_arch_protect() could be called while already protected. In + that case the return value indicates that it is already protected. + + sys_arch_protect() is only required if your port is supporting an operating + system. +*/ +sys_prot_t sys_arch_protect(void) +{ + vPortEnterCritical(); + return 1; +} + +/* + This optional function does a "fast" set of critical region protection to the + value specified by pval. See the documentation for sys_arch_protect() for + more information. This function is only required if your port is supporting + an operating system. +*/ +void sys_arch_unprotect(sys_prot_t pval) +{ + ( void ) pval; + vPortExitCritical(); +} + +/* + * Prints an assertion messages and aborts execution. + */ +void sys_assert( const char *msg ) +{ + ( void ) msg; + /*FSL:only needed for debugging + printf(msg); + printf("\n\r"); + */ + vPortEnterCritical( ); + for(;;) + ; +} diff --git a/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/freertos/sys_arch.h b/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/freertos/sys_arch.h new file mode 100644 index 0000000..83d0c08 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/freertos/sys_arch.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __SYS_RTXC_H__ +#define __SYS_RTXC_H__ + +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "semphr.h" + +#define SYS_MBOX_NULL (xQueueHandle)0 +#define SYS_SEM_NULL (xSemaphoreHandle)0 +#define SYS_DEFAULT_THREAD_STACK_DEPTH configMINIMAL_STACK_SIZE + +typedef xSemaphoreHandle sys_sem_t; +typedef xQueueHandle sys_mbox_t; +typedef xTaskHandle sys_thread_t; + +typedef struct _sys_arch_state_t +{ + // Task creation data. + char cTaskName[configMAX_TASK_NAME_LEN]; + unsigned short nStackDepth; + unsigned short nTaskCount; +} sys_arch_state_t; + + + +//extern sys_arch_state_t s_sys_arch_state; + +//void sys_set_default_state(); +//void sys_set_state(signed char *pTaskName, unsigned short nStackSize); + +/* Message queue constants. */ +#define archMESG_QUEUE_LENGTH ( 6 ) +#endif /* __SYS_RTXC_H__ */ + diff --git a/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/standalone/ethernetif.c b/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/standalone/ethernetif.c new file mode 100644 index 0000000..f3b74ee --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/standalone/ethernetif.c @@ -0,0 +1,366 @@ +/** + * @file + * Ethernet Interface for standalone applications (without RTOS) - works only for + * ethernet polling mode (polling for ethernet frame reception) + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" +#include "lwip/mem.h" +#include "netif/etharp.h" +#include "ethernetif.h" +#include "stm32f2x7_eth.h" +#include "main.h" +#include + +/* Network interface name */ +#define IFNAME0 's' +#define IFNAME1 't' + + +/* Ethernet Rx & Tx DMA Descriptors */ +extern ETH_DMADESCTypeDef DMARxDscrTab[ETH_RXBUFNB], DMATxDscrTab[ETH_TXBUFNB]; + +/* Ethernet Driver Receive buffers */ +extern uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE]; + +/* Ethernet Driver Transmit buffers */ +extern uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE]; + +/* Global pointers to track current transmit and receive descriptors */ +extern ETH_DMADESCTypeDef *DMATxDescToSet; +extern ETH_DMADESCTypeDef *DMARxDescToGet; + +/* Global pointer for last received frame infos */ +extern ETH_DMA_Rx_Frame_infos *DMA_RX_FRAME_infos; + +/** + * In this function, the hardware should be initialized. + * Called from ethernetif_init(). + * + * @param netif the already initialized lwip network interface structure + * for this ethernetif + */ +static void low_level_init(struct netif *netif) +{ +#ifdef CHECKSUM_BY_HARDWARE + int i; +#endif + /* set MAC hardware address length */ + netif->hwaddr_len = ETHARP_HWADDR_LEN; + + /* set MAC hardware address */ + netif->hwaddr[0] = MAC_ADDR0; + netif->hwaddr[1] = MAC_ADDR1; + netif->hwaddr[2] = MAC_ADDR2; + netif->hwaddr[3] = MAC_ADDR3; + netif->hwaddr[4] = MAC_ADDR4; + netif->hwaddr[5] = MAC_ADDR5; + + /* initialize MAC address in ethernet MAC */ + ETH_MACAddressConfig(ETH_MAC_Address0, netif->hwaddr); + + /* maximum transfer unit */ + netif->mtu = 1500; + + /* device capabilities */ + /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; + + /* Initialize Tx Descriptors list: Chain Mode */ + ETH_DMATxDescChainInit(DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB); + /* Initialize Rx Descriptors list: Chain Mode */ + ETH_DMARxDescChainInit(DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB); + +#ifdef CHECKSUM_BY_HARDWARE + /* Enable the TCP, UDP and ICMP checksum insertion for the Tx frames */ + for(i=0; iBuffer1Addr); + __IO ETH_DMADESCTypeDef *DmaTxDesc; + uint16_t framelength = 0; + uint32_t bufferoffset = 0; + uint32_t byteslefttocopy = 0; + uint32_t payloadoffset = 0; + + DmaTxDesc = DMATxDescToSet; + bufferoffset = 0; + + /* copy frame from pbufs to driver buffers */ + for(q = p; q != NULL; q = q->next) + { + /* Is this buffer available? If not, goto error */ + if((DmaTxDesc->Status & ETH_DMATxDesc_OWN) != (u32)RESET) + { + errval = ERR_BUF; + goto error; + } + + /* Get bytes in current lwIP buffer */ + byteslefttocopy = q->len; + payloadoffset = 0; + + /* Check if the length of data to copy is bigger than Tx buffer size*/ + while( (byteslefttocopy + bufferoffset) > ETH_TX_BUF_SIZE ) + { + /* Copy data to Tx buffer*/ + memcpy( (u8_t*)((u8_t*)buffer + bufferoffset), (u8_t*)((u8_t*)q->payload + payloadoffset), (ETH_TX_BUF_SIZE - bufferoffset) ); + + /* Point to next descriptor */ + DmaTxDesc = (ETH_DMADESCTypeDef *)(DmaTxDesc->Buffer2NextDescAddr); + + /* Check if the buffer is available */ + if((DmaTxDesc->Status & ETH_DMATxDesc_OWN) != (u32)RESET) + { + errval = ERR_USE; + goto error; + } + + buffer = (u8 *)(DmaTxDesc->Buffer1Addr); + + byteslefttocopy = byteslefttocopy - (ETH_TX_BUF_SIZE - bufferoffset); + payloadoffset = payloadoffset + (ETH_TX_BUF_SIZE - bufferoffset); + framelength = framelength + (ETH_TX_BUF_SIZE - bufferoffset); + bufferoffset = 0; + } + + /* Copy the remaining bytes */ + memcpy( (u8_t*)((u8_t*)buffer + bufferoffset), (u8_t*)((u8_t*)q->payload + payloadoffset), byteslefttocopy ); + bufferoffset = bufferoffset + byteslefttocopy; + framelength = framelength + byteslefttocopy; + } + + /* Note: padding and CRC for transmitted frame + are automatically inserted by DMA */ + + /* Prepare transmit descriptors to give to DMA*/ + ETH_Prepare_Transmit_Descriptors(framelength); + + errval = ERR_OK; + +error: + + /* When Transmit Underflow flag is set, clear it and issue a Transmit Poll Demand to resume transmission */ + if ((ETH->DMASR & ETH_DMASR_TUS) != (uint32_t)RESET) + { + /* Clear TUS ETHERNET DMA flag */ + ETH->DMASR = ETH_DMASR_TUS; + + /* Resume DMA transmission*/ + ETH->DMATPDR = 0; + } + return errval; +} + +/** + * Should allocate a pbuf and transfer the bytes of the incoming + * packet from the interface into the pbuf. + * + * @param netif the lwip network interface structure for this ethernetif + * @return a pbuf filled with the received packet (including MAC header) + * NULL on memory error + */ +static struct pbuf * low_level_input(struct netif *netif) +{ + struct pbuf *p, *q; + uint32_t len; + FrameTypeDef frame; + u8 *buffer; + __IO ETH_DMADESCTypeDef *DMARxDesc; + uint32_t bufferoffset = 0; + uint32_t payloadoffset = 0; + uint32_t byteslefttocopy = 0; + uint32_t i=0; + + /* get received frame */ + frame = ETH_Get_Received_Frame(); + + /* Obtain the size of the packet and put it into the "len" variable. */ + len = frame.length; + buffer = (u8 *)frame.buffer; + + /* We allocate a pbuf chain of pbufs from the Lwip buffer pool */ + p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); + + if (p != NULL) + { + DMARxDesc = frame.descriptor; + bufferoffset = 0; + for(q = p; q != NULL; q = q->next) + { + byteslefttocopy = q->len; + payloadoffset = 0; + + /* Check if the length of bytes to copy in current pbuf is bigger than Rx buffer size*/ + while( (byteslefttocopy + bufferoffset) > ETH_RX_BUF_SIZE ) + { + /* Copy data to pbuf*/ + memcpy( (u8_t*)((u8_t*)q->payload + payloadoffset), (u8_t*)((u8_t*)buffer + bufferoffset), (ETH_RX_BUF_SIZE - bufferoffset)); + + /* Point to next descriptor */ + DMARxDesc = (ETH_DMADESCTypeDef *)(DMARxDesc->Buffer2NextDescAddr); + buffer = (unsigned char *)(DMARxDesc->Buffer1Addr); + + byteslefttocopy = byteslefttocopy - (ETH_RX_BUF_SIZE - bufferoffset); + payloadoffset = payloadoffset + (ETH_RX_BUF_SIZE - bufferoffset); + bufferoffset = 0; + } + /* Copy remaining data in pbuf */ + memcpy( (u8_t*)((u8_t*)q->payload + payloadoffset), (u8_t*)((u8_t*)buffer + bufferoffset), byteslefttocopy); + bufferoffset = bufferoffset + byteslefttocopy; + } + } + + /* Release descriptors to DMA */ + DMARxDesc =frame.descriptor; + + /* Set Own bit in Rx descriptors: gives the buffers back to DMA */ + for (i=0; iSeg_Count; i++) + { + DMARxDesc->Status = ETH_DMARxDesc_OWN; + DMARxDesc = (ETH_DMADESCTypeDef *)(DMARxDesc->Buffer2NextDescAddr); + } + + /* Clear Segment_Count */ + DMA_RX_FRAME_infos->Seg_Count =0; + + /* When Rx Buffer unavailable flag is set: clear it and resume reception */ + if ((ETH->DMASR & ETH_DMASR_RBUS) != (u32)RESET) + { + /* Clear RBUS ETHERNET DMA flag */ + ETH->DMASR = ETH_DMASR_RBUS; + /* Resume DMA reception */ + ETH->DMARPDR = 0; + } + return p; +} + +/** + * This function should be called when a packet is ready to be read + * from the interface. It uses the function low_level_input() that + * should handle the actual reception of bytes from the network + * interface. Then the type of the received packet is determined and + * the appropriate input function is called. + * + * @param netif the lwip network interface structure for this ethernetif + */ +err_t ethernetif_input(struct netif *netif) +{ + err_t err; + struct pbuf *p; + + /* move received packet into a new pbuf */ + p = low_level_input(netif); + + /* no packet could be read, silently ignore this */ + if (p == NULL) return ERR_MEM; + + /* entry point to the LwIP stack */ + err = netif->input(p, netif); + + if (err != ERR_OK) + { + LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); + pbuf_free(p); + } + return err; +} + +/** + * Should be called at the beginning of the program to set up the + * network interface. It calls the function low_level_init() to do the + * actual setup of the hardware. + * + * This function should be passed as a parameter to netif_add(). + * + * @param netif the lwip network interface structure for this ethernetif + * @return ERR_OK if the loopif is initialized + * ERR_MEM if private data couldn't be allocated + * any other err_t on error + */ +err_t ethernetif_init(struct netif *netif) +{ + LWIP_ASSERT("netif != NULL", (netif != NULL)); + +#if LWIP_NETIF_HOSTNAME + /* Initialize interface hostname */ + netif->hostname = "lwip"; +#endif /* LWIP_NETIF_HOSTNAME */ + + netif->name[0] = IFNAME0; + netif->name[1] = IFNAME1; + /* We directly use etharp_output() here to save a function call. + * You can instead declare your own function an call etharp_output() + * from it if you have to do some checks before sending (e.g. if link + * is available...) */ + netif->output = etharp_output; + netif->linkoutput = low_level_output; + + /* initialize the hardware */ + low_level_init(netif); + + return ERR_OK; +} \ No newline at end of file diff --git a/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/standalone/ethernetif.h b/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/standalone/ethernetif.h new file mode 100644 index 0000000..9ff1408 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/port/stm32f2x7/standalone/ethernetif.h @@ -0,0 +1,11 @@ +#ifndef __ETHERNETIF_H__ +#define __ETHERNETIF_H__ + + +#include "lwip/err.h" +#include "lwip/netif.h" + +err_t ethernetif_init(struct netif *netif); +err_t ethernetif_input(struct netif *netif); + +#endif diff --git a/component/common/network/lwip/lwip_v1.4.1/src/FILES b/component/common/network/lwip/lwip_v1.4.1/src/FILES new file mode 100644 index 0000000..952aeab --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/FILES @@ -0,0 +1,13 @@ +api/ - The code for the high-level wrapper API. Not needed if + you use the lowel-level call-back/raw API. + +core/ - The core of the TPC/IP stack; protocol implementations, + memory and buffer management, and the low-level raw API. + +include/ - lwIP include files. + +netif/ - Generic network interface device drivers are kept here, + as well as the ARP module. + +For more information on the various subdirectories, check the FILES +file in each directory. diff --git a/component/common/network/lwip/lwip_v1.4.1/src/api/api_lib.c b/component/common/network/lwip/lwip_v1.4.1/src/api/api_lib.c new file mode 100644 index 0000000..38e49a4 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/api/api_lib.c @@ -0,0 +1,792 @@ +/** + * @file + * Sequential API External module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/* This is the part of the API that is linked with + the application */ + +#include "lwip/opt.h" + +#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/api.h" +#include "lwip/tcpip.h" +#include "lwip/memp.h" + +#include "lwip/ip.h" +#include "lwip/raw.h" +#include "lwip/udp.h" +#include "lwip/tcp.h" + +#include + +/** + * Create a new netconn (of a specific type) that has a callback function. + * The corresponding pcb is also created. + * + * @param t the type of 'connection' to create (@see enum netconn_type) + * @param proto the IP protocol for RAW IP pcbs + * @param callback a function to call on status changes (RX available, TX'ed) + * @return a newly allocated struct netconn or + * NULL on memory error + */ +struct netconn* +netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_callback callback) +{ + struct netconn *conn; + struct api_msg msg; + + conn = netconn_alloc(t, callback); + if (conn != NULL) { + msg.function = do_newconn; + msg.msg.msg.n.proto = proto; + msg.msg.conn = conn; + if (TCPIP_APIMSG(&msg) != ERR_OK) { + LWIP_ASSERT("freeing conn without freeing pcb", conn->pcb.tcp == NULL); + LWIP_ASSERT("conn has no op_completed", sys_sem_valid(&conn->op_completed)); + LWIP_ASSERT("conn has no recvmbox", sys_mbox_valid(&conn->recvmbox)); +#if LWIP_TCP + LWIP_ASSERT("conn->acceptmbox shouldn't exist", !sys_mbox_valid(&conn->acceptmbox)); +#endif /* LWIP_TCP */ + sys_sem_free(&conn->op_completed); + sys_mbox_free(&conn->recvmbox); + memp_free(MEMP_NETCONN, conn); + return NULL; + } + } + return conn; +} + +/** + * Close a netconn 'connection' and free its resources. + * UDP and RAW connection are completely closed, TCP pcbs might still be in a waitstate + * after this returns. + * + * @param conn the netconn to delete + * @return ERR_OK if the connection was deleted + */ +err_t +netconn_delete(struct netconn *conn) +{ + struct api_msg msg; + + /* No ASSERT here because possible to get a (conn == NULL) if we got an accept error */ + if (conn == NULL) { + return ERR_OK; + } + + msg.function = do_delconn; + msg.msg.conn = conn; + tcpip_apimsg(&msg); + + netconn_free(conn); + + /* don't care for return value of do_delconn since it only calls void functions */ + + return ERR_OK; +} + +/** + * Get the local or remote IP address and port of a netconn. + * For RAW netconns, this returns the protocol instead of a port! + * + * @param conn the netconn to query + * @param addr a pointer to which to save the IP address + * @param port a pointer to which to save the port (or protocol for RAW) + * @param local 1 to get the local IP address, 0 to get the remote one + * @return ERR_CONN for invalid connections + * ERR_OK if the information was retrieved + */ +err_t +netconn_getaddr(struct netconn *conn, ip_addr_t *addr, u16_t *port, u8_t local) +{ + struct api_msg msg; + err_t err; + + LWIP_ERROR("netconn_getaddr: invalid conn", (conn != NULL), return ERR_ARG;); + LWIP_ERROR("netconn_getaddr: invalid addr", (addr != NULL), return ERR_ARG;); + LWIP_ERROR("netconn_getaddr: invalid port", (port != NULL), return ERR_ARG;); + + msg.function = do_getaddr; + msg.msg.conn = conn; + msg.msg.msg.ad.ipaddr = addr; + msg.msg.msg.ad.port = port; + msg.msg.msg.ad.local = local; + err = TCPIP_APIMSG(&msg); + + NETCONN_SET_SAFE_ERR(conn, err); + return err; +} + +/** + * Bind a netconn to a specific local IP address and port. + * Binding one netconn twice might not always be checked correctly! + * + * @param conn the netconn to bind + * @param addr the local IP address to bind the netconn to (use IP_ADDR_ANY + * to bind to all addresses) + * @param port the local port to bind the netconn to (not used for RAW) + * @return ERR_OK if bound, any other err_t on failure + */ +err_t +netconn_bind(struct netconn *conn, ip_addr_t *addr, u16_t port) +{ + struct api_msg msg; + err_t err; + + LWIP_ERROR("netconn_bind: invalid conn", (conn != NULL), return ERR_ARG;); + + msg.function = do_bind; + msg.msg.conn = conn; + msg.msg.msg.bc.ipaddr = addr; + msg.msg.msg.bc.port = port; + err = TCPIP_APIMSG(&msg); + + NETCONN_SET_SAFE_ERR(conn, err); + return err; +} + +/** + * Connect a netconn to a specific remote IP address and port. + * + * @param conn the netconn to connect + * @param addr the remote IP address to connect to + * @param port the remote port to connect to (no used for RAW) + * @return ERR_OK if connected, return value of tcp_/udp_/raw_connect otherwise + */ +err_t +netconn_connect(struct netconn *conn, ip_addr_t *addr, u16_t port) +{ + struct api_msg msg; + err_t err; + + LWIP_ERROR("netconn_connect: invalid conn", (conn != NULL), return ERR_ARG;); + + msg.function = do_connect; + msg.msg.conn = conn; + msg.msg.msg.bc.ipaddr = addr; + msg.msg.msg.bc.port = port; + /* This is the only function which need to not block tcpip_thread */ + err = tcpip_apimsg(&msg); + + NETCONN_SET_SAFE_ERR(conn, err); + return err; +} + +/** + * Disconnect a netconn from its current peer (only valid for UDP netconns). + * + * @param conn the netconn to disconnect + * @return TODO: return value is not set here... + */ +err_t +netconn_disconnect(struct netconn *conn) +{ + struct api_msg msg; + err_t err; + + LWIP_ERROR("netconn_disconnect: invalid conn", (conn != NULL), return ERR_ARG;); + + msg.function = do_disconnect; + msg.msg.conn = conn; + err = TCPIP_APIMSG(&msg); + + NETCONN_SET_SAFE_ERR(conn, err); + return err; +} + +/** + * Set a TCP netconn into listen mode + * + * @param conn the tcp netconn to set to listen mode + * @param backlog the listen backlog, only used if TCP_LISTEN_BACKLOG==1 + * @return ERR_OK if the netconn was set to listen (UDP and RAW netconns + * don't return any error (yet?)) + */ +err_t +netconn_listen_with_backlog(struct netconn *conn, u8_t backlog) +{ +#if LWIP_TCP + struct api_msg msg; + err_t err; + + /* This does no harm. If TCP_LISTEN_BACKLOG is off, backlog is unused. */ + LWIP_UNUSED_ARG(backlog); + + LWIP_ERROR("netconn_listen: invalid conn", (conn != NULL), return ERR_ARG;); + + msg.function = do_listen; + msg.msg.conn = conn; +#if TCP_LISTEN_BACKLOG + msg.msg.msg.lb.backlog = backlog; +#endif /* TCP_LISTEN_BACKLOG */ + err = TCPIP_APIMSG(&msg); + + NETCONN_SET_SAFE_ERR(conn, err); + return err; +#else /* LWIP_TCP */ + LWIP_UNUSED_ARG(conn); + LWIP_UNUSED_ARG(backlog); + return ERR_ARG; +#endif /* LWIP_TCP */ +} + +/** + * Accept a new connection on a TCP listening netconn. + * + * @param conn the TCP listen netconn + * @param new_conn pointer where the new connection is stored + * @return ERR_OK if a new connection has been received or an error + * code otherwise + */ +err_t +netconn_accept(struct netconn *conn, struct netconn **new_conn) +{ +#if LWIP_TCP + struct netconn *newconn; + err_t err; +#if TCP_LISTEN_BACKLOG + struct api_msg msg; +#endif /* TCP_LISTEN_BACKLOG */ + + LWIP_ERROR("netconn_accept: invalid pointer", (new_conn != NULL), return ERR_ARG;); + *new_conn = NULL; + LWIP_ERROR("netconn_accept: invalid conn", (conn != NULL), return ERR_ARG;); + LWIP_ERROR("netconn_accept: invalid acceptmbox", sys_mbox_valid(&conn->acceptmbox), return ERR_ARG;); + + err = conn->last_err; + if (ERR_IS_FATAL(err)) { + /* don't recv on fatal errors: this might block the application task + waiting on acceptmbox forever! */ + return err; + } + +#if LWIP_SO_RCVTIMEO + if (sys_arch_mbox_fetch(&conn->acceptmbox, (void **)&newconn, conn->recv_timeout) == SYS_ARCH_TIMEOUT) { + NETCONN_SET_SAFE_ERR(conn, ERR_TIMEOUT); + return ERR_TIMEOUT; + } +#else + sys_arch_mbox_fetch(&conn->acceptmbox, (void **)&newconn, 0); +#endif /* LWIP_SO_RCVTIMEO*/ + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0); + + if (newconn == NULL) { + /* connection has been aborted */ + NETCONN_SET_SAFE_ERR(conn, ERR_ABRT); + return ERR_ABRT; + } +#if TCP_LISTEN_BACKLOG + /* Let the stack know that we have accepted the connection. */ + msg.function = do_recv; + msg.msg.conn = conn; + /* don't care for the return value of do_recv */ + TCPIP_APIMSG(&msg); +#endif /* TCP_LISTEN_BACKLOG */ + + *new_conn = newconn; + /* don't set conn->last_err: it's only ERR_OK, anyway */ + return ERR_OK; +#else /* LWIP_TCP */ + LWIP_UNUSED_ARG(conn); + LWIP_UNUSED_ARG(new_conn); + return ERR_ARG; +#endif /* LWIP_TCP */ +} + +/** + * Receive data: actual implementation that doesn't care whether pbuf or netbuf + * is received + * + * @param conn the netconn from which to receive data + * @param new_buf pointer where a new pbuf/netbuf is stored when received data + * @return ERR_OK if data has been received, an error code otherwise (timeout, + * memory error or another error) + */ +static err_t +netconn_recv_data(struct netconn *conn, void **new_buf) +{ + void *buf = NULL; + u16_t len; + err_t err; +#if LWIP_TCP + struct api_msg msg; +#endif /* LWIP_TCP */ + + LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;); + *new_buf = NULL; + LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;); + LWIP_ERROR("netconn_accept: invalid recvmbox", sys_mbox_valid(&conn->recvmbox), return ERR_CONN;); + + err = conn->last_err; + if (ERR_IS_FATAL(err)) { + /* don't recv on fatal errors: this might block the application task + waiting on recvmbox forever! */ + /* @todo: this does not allow us to fetch data that has been put into recvmbox + before the fatal error occurred - is that a problem? */ + return err; + } + +#if LWIP_SO_RCVTIMEO + if (sys_arch_mbox_fetch(&conn->recvmbox, &buf, conn->recv_timeout) == SYS_ARCH_TIMEOUT) { + NETCONN_SET_SAFE_ERR(conn, ERR_TIMEOUT); + return ERR_TIMEOUT; + } +#else + sys_arch_mbox_fetch(&conn->recvmbox, &buf, 0); +#endif /* LWIP_SO_RCVTIMEO*/ + +#if LWIP_TCP +#if (LWIP_UDP || LWIP_RAW) + if (conn->type == NETCONN_TCP) +#endif /* (LWIP_UDP || LWIP_RAW) */ + { + if (!netconn_get_noautorecved(conn) || (buf == NULL)) { + /* Let the stack know that we have taken the data. */ + /* TODO: Speedup: Don't block and wait for the answer here + (to prevent multiple thread-switches). */ + msg.function = do_recv; + msg.msg.conn = conn; + if (buf != NULL) { + msg.msg.msg.r.len = ((struct pbuf *)buf)->tot_len; + } else { + msg.msg.msg.r.len = 1; + } + /* don't care for the return value of do_recv */ + TCPIP_APIMSG(&msg); + } + + /* If we are closed, we indicate that we no longer wish to use the socket */ + if (buf == NULL) { + API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0); + /* Avoid to lose any previous error code */ + NETCONN_SET_SAFE_ERR(conn, ERR_CLSD); + return ERR_CLSD; + } + len = ((struct pbuf *)buf)->tot_len; + } +#endif /* LWIP_TCP */ +#if LWIP_TCP && (LWIP_UDP || LWIP_RAW) + else +#endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */ +#if (LWIP_UDP || LWIP_RAW) + { + LWIP_ASSERT("buf != NULL", buf != NULL); + len = netbuf_len((struct netbuf *)buf); + } +#endif /* (LWIP_UDP || LWIP_RAW) */ + +#if LWIP_SO_RCVBUF + SYS_ARCH_DEC(conn->recv_avail, len); +#endif /* LWIP_SO_RCVBUF */ + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVMINUS, len); + + LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_recv_data: received %p, len=%"U16_F"\n", buf, len)); + + *new_buf = buf; + /* don't set conn->last_err: it's only ERR_OK, anyway */ + return ERR_OK; +} + +/** + * Receive data (in form of a pbuf) from a TCP netconn + * + * @param conn the netconn from which to receive data + * @param new_buf pointer where a new pbuf is stored when received data + * @return ERR_OK if data has been received, an error code otherwise (timeout, + * memory error or another error) + * ERR_ARG if conn is not a TCP netconn + */ +err_t +netconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf) +{ + LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL) && + netconn_type(conn) == NETCONN_TCP, return ERR_ARG;); + + return netconn_recv_data(conn, (void **)new_buf); +} + +/** + * Receive data (in form of a netbuf containing a packet buffer) from a netconn + * + * @param conn the netconn from which to receive data + * @param new_buf pointer where a new netbuf is stored when received data + * @return ERR_OK if data has been received, an error code otherwise (timeout, + * memory error or another error) + */ +err_t +netconn_recv(struct netconn *conn, struct netbuf **new_buf) +{ +#if LWIP_TCP + struct netbuf *buf = NULL; + err_t err; +#endif /* LWIP_TCP */ + + LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;); + *new_buf = NULL; + LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;); + LWIP_ERROR("netconn_accept: invalid recvmbox", sys_mbox_valid(&conn->recvmbox), return ERR_CONN;); + +#if LWIP_TCP +#if (LWIP_UDP || LWIP_RAW) + if (conn->type == NETCONN_TCP) +#endif /* (LWIP_UDP || LWIP_RAW) */ + { + struct pbuf *p = NULL; + /* This is not a listening netconn, since recvmbox is set */ + + buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); + if (buf == NULL) { + NETCONN_SET_SAFE_ERR(conn, ERR_MEM); + return ERR_MEM; + } + + err = netconn_recv_data(conn, (void **)&p); + if (err != ERR_OK) { + memp_free(MEMP_NETBUF, buf); + return err; + } + LWIP_ASSERT("p != NULL", p != NULL); + + buf->p = p; + buf->ptr = p; + buf->port = 0; + ip_addr_set_any(&buf->addr); + *new_buf = buf; + /* don't set conn->last_err: it's only ERR_OK, anyway */ + return ERR_OK; + } +#endif /* LWIP_TCP */ +#if LWIP_TCP && (LWIP_UDP || LWIP_RAW) + else +#endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */ + { +#if (LWIP_UDP || LWIP_RAW) + return netconn_recv_data(conn, (void **)new_buf); +#endif /* (LWIP_UDP || LWIP_RAW) */ + } +} + +/** + * TCP: update the receive window: by calling this, the application + * tells the stack that it has processed data and is able to accept + * new data. + * ATTENTION: use with care, this is mainly used for sockets! + * Can only be used when calling netconn_set_noautorecved(conn, 1) before. + * + * @param conn the netconn for which to update the receive window + * @param length amount of data processed (ATTENTION: this must be accurate!) + */ +void +netconn_recved(struct netconn *conn, u32_t length) +{ +#if LWIP_TCP + if ((conn != NULL) && (conn->type == NETCONN_TCP) && + (netconn_get_noautorecved(conn))) { + struct api_msg msg; + /* Let the stack know that we have taken the data. */ + /* TODO: Speedup: Don't block and wait for the answer here + (to prevent multiple thread-switches). */ + msg.function = do_recv; + msg.msg.conn = conn; + msg.msg.msg.r.len = length; + /* don't care for the return value of do_recv */ + TCPIP_APIMSG(&msg); + } +#else /* LWIP_TCP */ + LWIP_UNUSED_ARG(conn); + LWIP_UNUSED_ARG(length); +#endif /* LWIP_TCP */ +} + +/** + * Send data (in form of a netbuf) to a specific remote IP address and port. + * Only to be used for UDP and RAW netconns (not TCP). + * + * @param conn the netconn over which to send data + * @param buf a netbuf containing the data to send + * @param addr the remote IP address to which to send the data + * @param port the remote port to which to send the data + * @return ERR_OK if data was sent, any other err_t on error + */ +err_t +netconn_sendto(struct netconn *conn, struct netbuf *buf, ip_addr_t *addr, u16_t port) +{ + if (buf != NULL) { + ip_addr_set(&buf->addr, addr); + buf->port = port; + return netconn_send(conn, buf); + } + return ERR_VAL; +} + +/** + * Send data over a UDP or RAW netconn (that is already connected). + * + * @param conn the UDP or RAW netconn over which to send data + * @param buf a netbuf containing the data to send + * @return ERR_OK if data was sent, any other err_t on error + */ +err_t +netconn_send(struct netconn *conn, struct netbuf *buf) +{ + struct api_msg msg; + err_t err; + + LWIP_ERROR("netconn_send: invalid conn", (conn != NULL), return ERR_ARG;); + + LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %"U16_F" bytes\n", buf->p->tot_len)); + msg.function = do_send; + msg.msg.conn = conn; + msg.msg.msg.b = buf; + err = TCPIP_APIMSG(&msg); + + NETCONN_SET_SAFE_ERR(conn, err); + return err; +} + +/** + * Send data over a TCP netconn. + * + * @param conn the TCP netconn over which to send data + * @param dataptr pointer to the application buffer that contains the data to send + * @param size size of the application data to send + * @param apiflags combination of following flags : + * - NETCONN_COPY: data will be copied into memory belonging to the stack + * - NETCONN_MORE: for TCP connection, PSH flag will be set on last segment sent + * - NETCONN_DONTBLOCK: only write the data if all dat can be written at once + * @param bytes_written pointer to a location that receives the number of written bytes + * @return ERR_OK if data was sent, any other err_t on error + */ +err_t +netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size, + u8_t apiflags, size_t *bytes_written) +{ + struct api_msg msg; + err_t err; + u8_t dontblock; + + LWIP_ERROR("netconn_write: invalid conn", (conn != NULL), return ERR_ARG;); + LWIP_ERROR("netconn_write: invalid conn->type", (conn->type == NETCONN_TCP), return ERR_VAL;); + if (size == 0) { + return ERR_OK; + } + dontblock = netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK); + if (dontblock && !bytes_written) { + /* This implies netconn_write() cannot be used for non-blocking send, since + it has no way to return the number of bytes written. */ + return ERR_VAL; + } + + /* non-blocking write sends as much */ + msg.function = do_write; + msg.msg.conn = conn; + msg.msg.msg.w.dataptr = dataptr; + msg.msg.msg.w.apiflags = apiflags; + msg.msg.msg.w.len = size; +#if LWIP_SO_SNDTIMEO + if (conn->send_timeout != 0) { + /* get the time we started, which is later compared to + sys_now() + conn->send_timeout */ + msg.msg.msg.w.time_started = sys_now(); + } else { + msg.msg.msg.w.time_started = 0; + } +#endif /* LWIP_SO_SNDTIMEO */ + + /* For locking the core: this _can_ be delayed on low memory/low send buffer, + but if it is, this is done inside api_msg.c:do_write(), so we can use the + non-blocking version here. */ + err = TCPIP_APIMSG(&msg); + if ((err == ERR_OK) && (bytes_written != NULL)) { + if (dontblock +#if LWIP_SO_SNDTIMEO + || (conn->send_timeout != 0) +#endif /* LWIP_SO_SNDTIMEO */ + ) { + /* nonblocking write: maybe the data has been sent partly */ + *bytes_written = msg.msg.msg.w.len; + } else { + /* blocking call succeeded: all data has been sent if it */ + *bytes_written = size; + } + } + + NETCONN_SET_SAFE_ERR(conn, err); + return err; +} + +/** + * Close ot shutdown a TCP netconn (doesn't delete it). + * + * @param conn the TCP netconn to close or shutdown + * @param how fully close or only shutdown one side? + * @return ERR_OK if the netconn was closed, any other err_t on error + */ +static err_t +netconn_close_shutdown(struct netconn *conn, u8_t how) +{ + struct api_msg msg; + err_t err; + + LWIP_ERROR("netconn_close: invalid conn", (conn != NULL), return ERR_ARG;); + + msg.function = do_close; + msg.msg.conn = conn; + /* shutting down both ends is the same as closing */ + msg.msg.msg.sd.shut = how; + /* because of the LWIP_TCPIP_CORE_LOCKING implementation of do_close, + don't use TCPIP_APIMSG here */ + err = tcpip_apimsg(&msg); + + NETCONN_SET_SAFE_ERR(conn, err); + return err; +} + +/** + * Close a TCP netconn (doesn't delete it). + * + * @param conn the TCP netconn to close + * @return ERR_OK if the netconn was closed, any other err_t on error + */ +err_t +netconn_close(struct netconn *conn) +{ + /* shutting down both ends is the same as closing */ + return netconn_close_shutdown(conn, NETCONN_SHUT_RDWR); +} + +/** + * Shut down one or both sides of a TCP netconn (doesn't delete it). + * + * @param conn the TCP netconn to shut down + * @return ERR_OK if the netconn was closed, any other err_t on error + */ +err_t +netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx) +{ + return netconn_close_shutdown(conn, (shut_rx ? NETCONN_SHUT_RD : 0) | (shut_tx ? NETCONN_SHUT_WR : 0)); +} + +#if LWIP_IGMP +/** + * Join multicast groups for UDP netconns. + * + * @param conn the UDP netconn for which to change multicast addresses + * @param multiaddr IP address of the multicast group to join or leave + * @param netif_addr the IP address of the network interface on which to send + * the igmp message + * @param join_or_leave flag whether to send a join- or leave-message + * @return ERR_OK if the action was taken, any err_t on error + */ +err_t +netconn_join_leave_group(struct netconn *conn, + ip_addr_t *multiaddr, + ip_addr_t *netif_addr, + enum netconn_igmp join_or_leave) +{ + struct api_msg msg; + err_t err; + + LWIP_ERROR("netconn_join_leave_group: invalid conn", (conn != NULL), return ERR_ARG;); + + msg.function = do_join_leave_group; + msg.msg.conn = conn; + msg.msg.msg.jl.multiaddr = multiaddr; + msg.msg.msg.jl.netif_addr = netif_addr; + msg.msg.msg.jl.join_or_leave = join_or_leave; + err = TCPIP_APIMSG(&msg); + + NETCONN_SET_SAFE_ERR(conn, err); + return err; +} +#endif /* LWIP_IGMP */ + +#if LWIP_DNS +/** + * Execute a DNS query, only one IP address is returned + * + * @param name a string representation of the DNS host name to query + * @param addr a preallocated ip_addr_t where to store the resolved IP address + * @return ERR_OK: resolving succeeded + * ERR_MEM: memory error, try again later + * ERR_ARG: dns client not initialized or invalid hostname + * ERR_VAL: dns server response was invalid + */ +err_t +netconn_gethostbyname(const char *name, ip_addr_t *addr) +{ + struct dns_api_msg msg; + err_t err; + sys_sem_t sem; + + LWIP_ERROR("netconn_gethostbyname: invalid name", (name != NULL), return ERR_ARG;); + LWIP_ERROR("netconn_gethostbyname: invalid addr", (addr != NULL), return ERR_ARG;); + + err = sys_sem_new(&sem, 0); + if (err != ERR_OK) { + return err; + } + + msg.name = name; + msg.addr = addr; + msg.err = &err; + msg.sem = &sem; + + tcpip_callback(do_gethostbyname, &msg); + sys_sem_wait(&sem); + sys_sem_free(&sem); + + return err; +} +#endif /* LWIP_DNS*/ + +//Realtek add +err_t netconn_abort(struct netconn *conn) +{ + if (conn->acceptmbox != SYS_MBOX_NULL) { + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); + sys_mbox_post(conn->acceptmbox, NULL); + } + return ERR_OK; +} +//Realtek add end + +#endif /* LWIP_NETCONN */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/api/api_msg.c b/component/common/network/lwip/lwip_v1.4.1/src/api/api_msg.c new file mode 100644 index 0000000..ffcdc43 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/api/api_msg.c @@ -0,0 +1,1565 @@ +/** + * @file + * Sequential API Internal module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/api_msg.h" + +#include "lwip/ip.h" +#include "lwip/udp.h" +#include "lwip/tcp.h" +#include "lwip/raw.h" + +#include "lwip/memp.h" +#include "lwip/tcpip.h" +#include "lwip/igmp.h" +#include "lwip/dns.h" + +#include + +#define SET_NONBLOCKING_CONNECT(conn, val) do { if(val) { \ + (conn)->flags |= NETCONN_FLAG_IN_NONBLOCKING_CONNECT; \ +} else { \ + (conn)->flags &= ~ NETCONN_FLAG_IN_NONBLOCKING_CONNECT; }} while(0) +#define IN_NONBLOCKING_CONNECT(conn) (((conn)->flags & NETCONN_FLAG_IN_NONBLOCKING_CONNECT) != 0) + +/* forward declarations */ +#if LWIP_TCP +static err_t do_writemore(struct netconn *conn); +static void do_close_internal(struct netconn *conn); +#endif + +#if LWIP_RAW +/** + * Receive callback function for RAW netconns. + * Doesn't 'eat' the packet, only references it and sends it to + * conn->recvmbox + * + * @see raw.h (struct raw_pcb.recv) for parameters and return value + */ +static u8_t +recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p, + ip_addr_t *addr) +{ + struct pbuf *q; + struct netbuf *buf; + struct netconn *conn; + + LWIP_UNUSED_ARG(addr); + conn = (struct netconn *)arg; + + if ((conn != NULL) && sys_mbox_valid(&conn->recvmbox)) { +#if LWIP_SO_RCVBUF + int recv_avail; + SYS_ARCH_GET(conn->recv_avail, recv_avail); + if ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize) { + return 0; + } +#endif /* LWIP_SO_RCVBUF */ + /* copy the whole packet into new pbufs */ + q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); + if(q != NULL) { + if (pbuf_copy(q, p) != ERR_OK) { + pbuf_free(q); + q = NULL; + } + } + + if (q != NULL) { + u16_t len; + buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); + if (buf == NULL) { + pbuf_free(q); + return 0; + } + + buf->p = q; + buf->ptr = q; + ip_addr_copy(buf->addr, *ip_current_src_addr()); + buf->port = pcb->protocol; + + len = q->tot_len; + if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) { + netbuf_delete(buf); + return 0; + } else { +#if LWIP_SO_RCVBUF + SYS_ARCH_INC(conn->recv_avail, len); +#endif /* LWIP_SO_RCVBUF */ + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); + } + } + } + + return 0; /* do not eat the packet */ +} +#endif /* LWIP_RAW*/ + +#if LWIP_UDP +/** + * Receive callback function for UDP netconns. + * Posts the packet to conn->recvmbox or deletes it on memory error. + * + * @see udp.h (struct udp_pcb.recv) for parameters + */ +static void +recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *addr, u16_t port) +{ + struct netbuf *buf; + struct netconn *conn; + u16_t len; +#if LWIP_SO_RCVBUF + int recv_avail; +#endif /* LWIP_SO_RCVBUF */ + + LWIP_UNUSED_ARG(pcb); /* only used for asserts... */ + LWIP_ASSERT("recv_udp must have a pcb argument", pcb != NULL); + LWIP_ASSERT("recv_udp must have an argument", arg != NULL); + conn = (struct netconn *)arg; + LWIP_ASSERT("recv_udp: recv for wrong pcb!", conn->pcb.udp == pcb); + +#if LWIP_SO_RCVBUF + SYS_ARCH_GET(conn->recv_avail, recv_avail); + if ((conn == NULL) || !sys_mbox_valid(&conn->recvmbox) || + ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize)) { +#else /* LWIP_SO_RCVBUF */ + if ((conn == NULL) || !sys_mbox_valid(&conn->recvmbox)) { +#endif /* LWIP_SO_RCVBUF */ + pbuf_free(p); + return; + } + + buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); + if (buf == NULL) { + pbuf_free(p); + return; + } else { + buf->p = p; + buf->ptr = p; + ip_addr_set(&buf->addr, addr); + buf->port = port; +#if LWIP_NETBUF_RECVINFO + { + const struct ip_hdr* iphdr = ip_current_header(); + /* get the UDP header - always in the first pbuf, ensured by udp_input */ + const struct udp_hdr* udphdr = (void*)(((char*)iphdr) + IPH_LEN(iphdr)); +#if LWIP_CHECKSUM_ON_COPY + buf->flags = NETBUF_FLAG_DESTADDR; +#endif /* LWIP_CHECKSUM_ON_COPY */ + ip_addr_set(&buf->toaddr, ip_current_dest_addr()); + buf->toport_chksum = udphdr->dest; + } +#endif /* LWIP_NETBUF_RECVINFO */ + } + + len = p->tot_len; + if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) { + netbuf_delete(buf); + return; + } else { +#if LWIP_SO_RCVBUF + SYS_ARCH_INC(conn->recv_avail, len); +#endif /* LWIP_SO_RCVBUF */ + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); + } +} +#endif /* LWIP_UDP */ + +#if LWIP_TCP +/** + * Receive callback function for TCP netconns. + * Posts the packet to conn->recvmbox, but doesn't delete it on errors. + * + * @see tcp.h (struct tcp_pcb.recv) for parameters and return value + */ +static err_t +recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) +{ + struct netconn *conn; + u16_t len; + + LWIP_UNUSED_ARG(pcb); + LWIP_ASSERT("recv_tcp must have a pcb argument", pcb != NULL); + LWIP_ASSERT("recv_tcp must have an argument", arg != NULL); + conn = (struct netconn *)arg; + LWIP_ASSERT("recv_tcp: recv for wrong pcb!", conn->pcb.tcp == pcb); + + if (conn == NULL) { + return ERR_VAL; + } + if (!sys_mbox_valid(&conn->recvmbox)) { + /* recvmbox already deleted */ + if (p != NULL) { + tcp_recved(pcb, p->tot_len); + pbuf_free(p); + } + return ERR_OK; + } + /* Unlike for UDP or RAW pcbs, don't check for available space + using recv_avail since that could break the connection + (data is already ACKed) */ + + /* don't overwrite fatal errors! */ + NETCONN_SET_SAFE_ERR(conn, err); + + if (p != NULL) { + len = p->tot_len; + } else { + len = 0; + } + + if (sys_mbox_trypost(&conn->recvmbox, p) != ERR_OK) { + /* don't deallocate p: it is presented to us later again from tcp_fasttmr! */ + return ERR_MEM; + } else { +#if LWIP_SO_RCVBUF + SYS_ARCH_INC(conn->recv_avail, len); +#endif /* LWIP_SO_RCVBUF */ + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); + } + + return ERR_OK; +} + +/** + * Poll callback function for TCP netconns. + * Wakes up an application thread that waits for a connection to close + * or data to be sent. The application thread then takes the + * appropriate action to go on. + * + * Signals the conn->sem. + * netconn_close waits for conn->sem if closing failed. + * + * @see tcp.h (struct tcp_pcb.poll) for parameters and return value + */ +static err_t +poll_tcp(void *arg, struct tcp_pcb *pcb) +{ + struct netconn *conn = (struct netconn *)arg; + + LWIP_UNUSED_ARG(pcb); + LWIP_ASSERT("conn != NULL", (conn != NULL)); + + if (conn->state == NETCONN_WRITE) { + do_writemore(conn); + } else if (conn->state == NETCONN_CLOSE) { + do_close_internal(conn); + } + /* @todo: implement connect timeout here? */ + + /* Did a nonblocking write fail before? Then check available write-space. */ + if (conn->flags & NETCONN_FLAG_CHECK_WRITESPACE) { + /* If the queued byte- or pbuf-count drops below the configured low-water limit, + let select mark this pcb as writable again. */ + if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT) && + (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT)) { + conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE; + API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); + } + } + + return ERR_OK; +} + +/** + * Sent callback function for TCP netconns. + * Signals the conn->sem and calls API_EVENT. + * netconn_write waits for conn->sem if send buffer is low. + * + * @see tcp.h (struct tcp_pcb.sent) for parameters and return value + */ +static err_t +sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len) +{ + struct netconn *conn = (struct netconn *)arg; + + LWIP_UNUSED_ARG(pcb); + LWIP_ASSERT("conn != NULL", (conn != NULL)); + + if (conn->state == NETCONN_WRITE) { + do_writemore(conn); + } else if (conn->state == NETCONN_CLOSE) { + do_close_internal(conn); + } + + if (conn) { + /* If the queued byte- or pbuf-count drops below the configured low-water limit, + let select mark this pcb as writable again. */ + if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT) && + (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT)) { + conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE; + API_EVENT(conn, NETCONN_EVT_SENDPLUS, len); + } + } + + return ERR_OK; +} + +/** + * Error callback function for TCP netconns. + * Signals conn->sem, posts to all conn mboxes and calls API_EVENT. + * The application thread has then to decide what to do. + * + * @see tcp.h (struct tcp_pcb.err) for parameters + */ +static void +err_tcp(void *arg, err_t err) +{ + struct netconn *conn; + enum netconn_state old_state; + SYS_ARCH_DECL_PROTECT(lev); + + conn = (struct netconn *)arg; + LWIP_ASSERT("conn != NULL", (conn != NULL)); + + conn->pcb.tcp = NULL; + + /* no check since this is always fatal! */ + SYS_ARCH_PROTECT(lev); + conn->last_err = err; + SYS_ARCH_UNPROTECT(lev); + + /* reset conn->state now before waking up other threads */ + old_state = conn->state; + conn->state = NETCONN_NONE; + + /* Notify the user layer about a connection error. Used to signal + select. */ + API_EVENT(conn, NETCONN_EVT_ERROR, 0); + /* Try to release selects pending on 'read' or 'write', too. + They will get an error if they actually try to read or write. */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); + API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); + + /* pass NULL-message to recvmbox to wake up pending recv */ + if (sys_mbox_valid(&conn->recvmbox)) { + /* use trypost to prevent deadlock */ + sys_mbox_trypost(&conn->recvmbox, NULL); + } + /* pass NULL-message to acceptmbox to wake up pending accept */ + if (sys_mbox_valid(&conn->acceptmbox)) { + /* use trypost to preven deadlock */ + sys_mbox_trypost(&conn->acceptmbox, NULL); + } + + if ((old_state == NETCONN_WRITE) || (old_state == NETCONN_CLOSE) || + (old_state == NETCONN_CONNECT)) { + /* calling do_writemore/do_close_internal is not necessary + since the pcb has already been deleted! */ + int was_nonblocking_connect = IN_NONBLOCKING_CONNECT(conn); + SET_NONBLOCKING_CONNECT(conn, 0); + + if (!was_nonblocking_connect) { + /* set error return code */ + LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL); + conn->current_msg->err = err; + conn->current_msg = NULL; + /* wake up the waiting task */ + sys_sem_signal(&conn->op_completed); + } + } else { + LWIP_ASSERT("conn->current_msg == NULL", conn->current_msg == NULL); + } +} + +/** + * Setup a tcp_pcb with the correct callback function pointers + * and their arguments. + * + * @param conn the TCP netconn to setup + */ +static void +setup_tcp(struct netconn *conn) +{ + struct tcp_pcb *pcb; + + pcb = conn->pcb.tcp; + tcp_arg(pcb, conn); + tcp_recv(pcb, recv_tcp); + tcp_sent(pcb, sent_tcp); + tcp_poll(pcb, poll_tcp, 4); + tcp_err(pcb, err_tcp); +} + +/** + * Accept callback function for TCP netconns. + * Allocates a new netconn and posts that to conn->acceptmbox. + * + * @see tcp.h (struct tcp_pcb_listen.accept) for parameters and return value + */ +static err_t +accept_function(void *arg, struct tcp_pcb *newpcb, err_t err) +{ + struct netconn *newconn; + struct netconn *conn = (struct netconn *)arg; + + LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: newpcb->tate: %s\n", tcp_debug_state_str(newpcb->state))); + + if (!sys_mbox_valid(&conn->acceptmbox)) { + LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: acceptmbox already deleted\n")); + return ERR_VAL; + } + + /* We have to set the callback here even though + * the new socket is unknown. conn->socket is marked as -1. */ + newconn = netconn_alloc(conn->type, conn->callback); + if (newconn == NULL) { + return ERR_MEM; + } + newconn->pcb.tcp = newpcb; + setup_tcp(newconn); + /* no protection: when creating the pcb, the netconn is not yet known + to the application thread */ + newconn->last_err = err; + + if (sys_mbox_trypost(&conn->acceptmbox, newconn) != ERR_OK) { + /* When returning != ERR_OK, the pcb is aborted in tcp_process(), + so do nothing here! */ + /* remove all references to this netconn from the pcb */ + struct tcp_pcb* pcb = newconn->pcb.tcp; + tcp_arg(pcb, NULL); + tcp_recv(pcb, NULL); + tcp_sent(pcb, NULL); + tcp_poll(pcb, NULL, 4); + tcp_err(pcb, NULL); + /* remove reference from to the pcb from this netconn */ + newconn->pcb.tcp = NULL; + /* no need to drain since we know the recvmbox is empty. */ + sys_mbox_free(&newconn->recvmbox); + sys_mbox_set_invalid(&newconn->recvmbox); + netconn_free(newconn); + return ERR_MEM; + } else { + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); + } + + return ERR_OK; +} +#endif /* LWIP_TCP */ + +/** + * Create a new pcb of a specific type. + * Called from do_newconn(). + * + * @param msg the api_msg_msg describing the connection type + * @return msg->conn->err, but the return value is currently ignored + */ +static void +pcb_new(struct api_msg_msg *msg) +{ + LWIP_ASSERT("pcb_new: pcb already allocated", msg->conn->pcb.tcp == NULL); + + /* Allocate a PCB for this connection */ + switch(NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + msg->conn->pcb.raw = raw_new(msg->msg.n.proto); + if(msg->conn->pcb.raw == NULL) { + msg->err = ERR_MEM; + break; + } + raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn); + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + msg->conn->pcb.udp = udp_new(); + if(msg->conn->pcb.udp == NULL) { + msg->err = ERR_MEM; + break; + } +#if LWIP_UDPLITE + if (msg->conn->type==NETCONN_UDPLITE) { + udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE); + } +#endif /* LWIP_UDPLITE */ + if (msg->conn->type==NETCONN_UDPNOCHKSUM) { + udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM); + } + udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + msg->conn->pcb.tcp = tcp_new(); + if(msg->conn->pcb.tcp == NULL) { + msg->err = ERR_MEM; + break; + } + setup_tcp(msg->conn); + break; +#endif /* LWIP_TCP */ + default: + /* Unsupported netconn type, e.g. protocol disabled */ + msg->err = ERR_VAL; + break; + } +} + +/** + * Create a new pcb of a specific type inside a netconn. + * Called from netconn_new_with_proto_and_callback. + * + * @param msg the api_msg_msg describing the connection type + */ +void +do_newconn(struct api_msg_msg *msg) +{ + msg->err = ERR_OK; + if(msg->conn->pcb.tcp == NULL) { + pcb_new(msg); + } + /* Else? This "new" connection already has a PCB allocated. */ + /* Is this an error condition? Should it be deleted? */ + /* We currently just are happy and return. */ + + TCPIP_APIMSG_ACK(msg); +} + +/** + * Create a new netconn (of a specific type) that has a callback function. + * The corresponding pcb is NOT created! + * + * @param t the type of 'connection' to create (@see enum netconn_type) + * @param proto the IP protocol for RAW IP pcbs + * @param callback a function to call on status changes (RX available, TX'ed) + * @return a newly allocated struct netconn or + * NULL on memory error + */ +struct netconn* +netconn_alloc(enum netconn_type t, netconn_callback callback) +{ + struct netconn *conn; + int size = 0; + + conn = (struct netconn *)memp_malloc(MEMP_NETCONN); + if (conn == NULL) { + return NULL; + } + + conn->last_err = ERR_OK; + conn->type = t; + conn->pcb.tcp = NULL; + +#if (DEFAULT_RAW_RECVMBOX_SIZE == DEFAULT_UDP_RECVMBOX_SIZE) && \ + (DEFAULT_RAW_RECVMBOX_SIZE == DEFAULT_TCP_RECVMBOX_SIZE) + size = DEFAULT_RAW_RECVMBOX_SIZE; +#else + switch(NETCONNTYPE_GROUP(t)) { +#if LWIP_RAW + case NETCONN_RAW: + size = DEFAULT_RAW_RECVMBOX_SIZE; + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + size = DEFAULT_UDP_RECVMBOX_SIZE; + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + size = DEFAULT_TCP_RECVMBOX_SIZE; + break; +#endif /* LWIP_TCP */ + default: + LWIP_ASSERT("netconn_alloc: undefined netconn_type", 0); + goto free_and_return; + } +#endif + + if (sys_sem_new(&conn->op_completed, 0) != ERR_OK) { + goto free_and_return; + } + if (sys_mbox_new(&conn->recvmbox, size) != ERR_OK) { + sys_sem_free(&conn->op_completed); + goto free_and_return; + } + +#if LWIP_TCP + sys_mbox_set_invalid(&conn->acceptmbox); +#endif + conn->state = NETCONN_NONE; +#if LWIP_SOCKET + /* initialize socket to -1 since 0 is a valid socket */ + conn->socket = -1; +#endif /* LWIP_SOCKET */ + conn->callback = callback; +#if LWIP_TCP + conn->current_msg = NULL; + conn->write_offset = 0; +#endif /* LWIP_TCP */ +#if LWIP_SO_SNDTIMEO + conn->send_timeout = 0; +#endif /* LWIP_SO_SNDTIMEO */ +#if LWIP_SO_RCVTIMEO + conn->recv_timeout = 0; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + conn->recv_bufsize = RECV_BUFSIZE_DEFAULT; + conn->recv_avail = 0; +#endif /* LWIP_SO_RCVBUF */ + conn->flags = 0; + return conn; +free_and_return: + memp_free(MEMP_NETCONN, conn); + return NULL; +} + +/** + * Delete a netconn and all its resources. + * The pcb is NOT freed (since we might not be in the right thread context do this). + * + * @param conn the netconn to free + */ +void +netconn_free(struct netconn *conn) +{ + LWIP_ASSERT("PCB must be deallocated outside this function", conn->pcb.tcp == NULL); + LWIP_ASSERT("recvmbox must be deallocated before calling this function", + !sys_mbox_valid(&conn->recvmbox)); +#if LWIP_TCP + LWIP_ASSERT("acceptmbox must be deallocated before calling this function", + !sys_mbox_valid(&conn->acceptmbox)); +#endif /* LWIP_TCP */ + + sys_sem_free(&conn->op_completed); + sys_sem_set_invalid(&conn->op_completed); + + memp_free(MEMP_NETCONN, conn); +} + +/** + * Delete rcvmbox and acceptmbox of a netconn and free the left-over data in + * these mboxes + * + * @param conn the netconn to free + * @bytes_drained bytes drained from recvmbox + * @accepts_drained pending connections drained from acceptmbox + */ +static void +netconn_drain(struct netconn *conn) +{ + void *mem; +#if LWIP_TCP + struct pbuf *p; +#endif /* LWIP_TCP */ + + /* This runs in tcpip_thread, so we don't need to lock against rx packets */ + + /* Delete and drain the recvmbox. */ + if (sys_mbox_valid(&conn->recvmbox)) { + while (sys_mbox_tryfetch(&conn->recvmbox, &mem) != SYS_MBOX_EMPTY) { +#if LWIP_TCP + if (conn->type == NETCONN_TCP) { + if(mem != NULL) { + p = (struct pbuf*)mem; + /* pcb might be set to NULL already by err_tcp() */ + if (conn->pcb.tcp != NULL) { + tcp_recved(conn->pcb.tcp, p->tot_len); + } + pbuf_free(p); + } + } else +#endif /* LWIP_TCP */ + { + netbuf_delete((struct netbuf *)mem); + } + } + sys_mbox_free(&conn->recvmbox); + sys_mbox_set_invalid(&conn->recvmbox); + } + + /* Delete and drain the acceptmbox. */ +#if LWIP_TCP + if (sys_mbox_valid(&conn->acceptmbox)) { + while (sys_mbox_tryfetch(&conn->acceptmbox, &mem) != SYS_MBOX_EMPTY) { + struct netconn *newconn = (struct netconn *)mem; + /* Only tcp pcbs have an acceptmbox, so no need to check conn->type */ + /* pcb might be set to NULL already by err_tcp() */ + if (conn->pcb.tcp != NULL) { + tcp_accepted(conn->pcb.tcp); + } + /* drain recvmbox */ + netconn_drain(newconn); + if (newconn->pcb.tcp != NULL) { + tcp_abort(newconn->pcb.tcp); + newconn->pcb.tcp = NULL; + } + netconn_free(newconn); + } + sys_mbox_free(&conn->acceptmbox); + sys_mbox_set_invalid(&conn->acceptmbox); + } +#endif /* LWIP_TCP */ +} + +#if LWIP_TCP +/** + * Internal helper function to close a TCP netconn: since this sometimes + * doesn't work at the first attempt, this function is called from multiple + * places. + * + * @param conn the TCP netconn to close + */ +static void +do_close_internal(struct netconn *conn) +{ + err_t err; + u8_t shut, shut_rx, shut_tx, close; + + LWIP_ASSERT("invalid conn", (conn != NULL)); + LWIP_ASSERT("this is for tcp netconns only", (conn->type == NETCONN_TCP)); + LWIP_ASSERT("conn must be in state NETCONN_CLOSE", (conn->state == NETCONN_CLOSE)); + LWIP_ASSERT("pcb already closed", (conn->pcb.tcp != NULL)); + LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL); + + shut = conn->current_msg->msg.sd.shut; + shut_rx = shut & NETCONN_SHUT_RD; + shut_tx = shut & NETCONN_SHUT_WR; + /* shutting down both ends is the same as closing */ + close = shut == NETCONN_SHUT_RDWR; + + /* Set back some callback pointers */ + if (close) { + tcp_arg(conn->pcb.tcp, NULL); + } + if (conn->pcb.tcp->state == LISTEN) { + tcp_accept(conn->pcb.tcp, NULL); + } else { + /* some callbacks have to be reset if tcp_close is not successful */ + if (shut_rx) { + tcp_recv(conn->pcb.tcp, NULL); + tcp_accept(conn->pcb.tcp, NULL); + } + if (shut_tx) { + tcp_sent(conn->pcb.tcp, NULL); + } + if (close) { + tcp_poll(conn->pcb.tcp, NULL, 4); + tcp_err(conn->pcb.tcp, NULL); + } + } + /* Try to close the connection */ + if (close) { + err = tcp_close(conn->pcb.tcp); + } else { + err = tcp_shutdown(conn->pcb.tcp, shut_rx, shut_tx); + } + if (err == ERR_OK) { + /* Closing succeeded */ + conn->current_msg->err = ERR_OK; + conn->current_msg = NULL; + conn->state = NETCONN_NONE; + if (close) { + /* Set back some callback pointers as conn is going away */ + conn->pcb.tcp = NULL; + /* Trigger select() in socket layer. Make sure everybody notices activity + on the connection, error first! */ + API_EVENT(conn, NETCONN_EVT_ERROR, 0); + } + if (shut_rx) { + API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); + } + if (shut_tx) { + API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); + } + /* wake up the application task */ + sys_sem_signal(&conn->op_completed); + } else { + /* Closing failed, restore some of the callbacks */ + /* Closing of listen pcb will never fail! */ + LWIP_ASSERT("Closing a listen pcb may not fail!", (conn->pcb.tcp->state != LISTEN)); + tcp_sent(conn->pcb.tcp, sent_tcp); + tcp_poll(conn->pcb.tcp, poll_tcp, 4); + tcp_err(conn->pcb.tcp, err_tcp); + tcp_arg(conn->pcb.tcp, conn); + /* don't restore recv callback: we don't want to receive any more data */ + } + /* If closing didn't succeed, we get called again either + from poll_tcp or from sent_tcp */ +} +#endif /* LWIP_TCP */ + +/** + * Delete the pcb inside a netconn. + * Called from netconn_delete. + * + * @param msg the api_msg_msg pointing to the connection + */ +void +do_delconn(struct api_msg_msg *msg) +{ + /* @todo TCP: abort running write/connect? */ + if ((msg->conn->state != NETCONN_NONE) && + (msg->conn->state != NETCONN_LISTEN) && + (msg->conn->state != NETCONN_CONNECT)) { + /* this only happens for TCP netconns */ + LWIP_ASSERT("msg->conn->type == NETCONN_TCP", msg->conn->type == NETCONN_TCP); + msg->err = ERR_INPROGRESS; + } else { + LWIP_ASSERT("blocking connect in progress", + (msg->conn->state != NETCONN_CONNECT) || IN_NONBLOCKING_CONNECT(msg->conn)); + /* Drain and delete mboxes */ + netconn_drain(msg->conn); + + if (msg->conn->pcb.tcp != NULL) { + + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + raw_remove(msg->conn->pcb.raw); + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + msg->conn->pcb.udp->recv_arg = NULL; + udp_remove(msg->conn->pcb.udp); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL && + msg->conn->write_offset == 0); + msg->conn->state = NETCONN_CLOSE; + msg->msg.sd.shut = NETCONN_SHUT_RDWR; + msg->conn->current_msg = msg; + do_close_internal(msg->conn); + /* API_EVENT is called inside do_close_internal, before releasing + the application thread, so we can return at this point! */ + return; +#endif /* LWIP_TCP */ + default: + break; + } + msg->conn->pcb.tcp = NULL; + } + /* tcp netconns don't come here! */ + + /* @todo: this lets select make the socket readable and writable, + which is wrong! errfd instead? */ + API_EVENT(msg->conn, NETCONN_EVT_RCVPLUS, 0); + API_EVENT(msg->conn, NETCONN_EVT_SENDPLUS, 0); + } + if (sys_sem_valid(&msg->conn->op_completed)) { + sys_sem_signal(&msg->conn->op_completed); + } +} + +/** + * Bind a pcb contained in a netconn + * Called from netconn_bind. + * + * @param msg the api_msg_msg pointing to the connection and containing + * the IP address and port to bind to + */ +void +do_bind(struct api_msg_msg *msg) +{ + if (ERR_IS_FATAL(msg->conn->last_err)) { + msg->err = msg->conn->last_err; + } else { + msg->err = ERR_VAL; + if (msg->conn->pcb.tcp != NULL) { + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + msg->err = raw_bind(msg->conn->pcb.raw, msg->msg.bc.ipaddr); + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + msg->err = udp_bind(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + msg->err = tcp_bind(msg->conn->pcb.tcp, msg->msg.bc.ipaddr, msg->msg.bc.port); + break; +#endif /* LWIP_TCP */ + default: + break; + } + } + } + TCPIP_APIMSG_ACK(msg); +} + +#if LWIP_TCP +/** + * TCP callback function if a connection (opened by tcp_connect/do_connect) has + * been established (or reset by the remote host). + * + * @see tcp.h (struct tcp_pcb.connected) for parameters and return values + */ +static err_t +do_connected(void *arg, struct tcp_pcb *pcb, err_t err) +{ + struct netconn *conn; + int was_blocking; + + LWIP_UNUSED_ARG(pcb); + + conn = (struct netconn *)arg; + + if (conn == NULL) { + return ERR_VAL; + } + + LWIP_ASSERT("conn->state == NETCONN_CONNECT", conn->state == NETCONN_CONNECT); + LWIP_ASSERT("(conn->current_msg != NULL) || conn->in_non_blocking_connect", + (conn->current_msg != NULL) || IN_NONBLOCKING_CONNECT(conn)); + + if (conn->current_msg != NULL) { + conn->current_msg->err = err; + } + if ((conn->type == NETCONN_TCP) && (err == ERR_OK)) { + setup_tcp(conn); + } + was_blocking = !IN_NONBLOCKING_CONNECT(conn); + SET_NONBLOCKING_CONNECT(conn, 0); + conn->current_msg = NULL; + conn->state = NETCONN_NONE; + if (!was_blocking) { + NETCONN_SET_SAFE_ERR(conn, ERR_OK); + } + API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); + + if (was_blocking) { + sys_sem_signal(&conn->op_completed); + } + return ERR_OK; +} +#endif /* LWIP_TCP */ + +/** + * Connect a pcb contained inside a netconn + * Called from netconn_connect. + * + * @param msg the api_msg_msg pointing to the connection and containing + * the IP address and port to connect to + */ +void +do_connect(struct api_msg_msg *msg) +{ + if (msg->conn->pcb.tcp == NULL) { + /* This may happen when calling netconn_connect() a second time */ + msg->err = ERR_CLSD; + } else { + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + msg->err = raw_connect(msg->conn->pcb.raw, msg->msg.bc.ipaddr); + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + msg->err = udp_connect(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + /* Prevent connect while doing any other action. */ + if (msg->conn->state != NETCONN_NONE) { + msg->err = ERR_ISCONN; + } else { + setup_tcp(msg->conn); + msg->err = tcp_connect(msg->conn->pcb.tcp, msg->msg.bc.ipaddr, + msg->msg.bc.port, do_connected); + if (msg->err == ERR_OK) { + u8_t non_blocking = netconn_is_nonblocking(msg->conn); + msg->conn->state = NETCONN_CONNECT; + SET_NONBLOCKING_CONNECT(msg->conn, non_blocking); + if (non_blocking) { + msg->err = ERR_INPROGRESS; + } else { + msg->conn->current_msg = msg; + /* sys_sem_signal() is called from do_connected (or err_tcp()), + * when the connection is established! */ + return; + } + } + } + break; +#endif /* LWIP_TCP */ + default: + LWIP_ERROR("Invalid netconn type", 0, do{ msg->err = ERR_VAL; }while(0)); + break; + } + } + sys_sem_signal(&msg->conn->op_completed); +} + +/** + * Connect a pcb contained inside a netconn + * Only used for UDP netconns. + * Called from netconn_disconnect. + * + * @param msg the api_msg_msg pointing to the connection to disconnect + */ +void +do_disconnect(struct api_msg_msg *msg) +{ +#if LWIP_UDP + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) { + udp_disconnect(msg->conn->pcb.udp); + msg->err = ERR_OK; + } else +#endif /* LWIP_UDP */ + { + msg->err = ERR_VAL; + } + TCPIP_APIMSG_ACK(msg); +} + +#if LWIP_TCP +/** + * Set a TCP pcb contained in a netconn into listen mode + * Called from netconn_listen. + * + * @param msg the api_msg_msg pointing to the connection + */ +void +do_listen(struct api_msg_msg *msg) +{ + if (ERR_IS_FATAL(msg->conn->last_err)) { + msg->err = msg->conn->last_err; + } else { + msg->err = ERR_CONN; + if (msg->conn->pcb.tcp != NULL) { + if (msg->conn->type == NETCONN_TCP) { + if (msg->conn->state == NETCONN_NONE) { +#if TCP_LISTEN_BACKLOG + struct tcp_pcb* lpcb = tcp_listen_with_backlog(msg->conn->pcb.tcp, msg->msg.lb.backlog); +#else /* TCP_LISTEN_BACKLOG */ + struct tcp_pcb* lpcb = tcp_listen(msg->conn->pcb.tcp); +#endif /* TCP_LISTEN_BACKLOG */ + if (lpcb == NULL) { + /* in this case, the old pcb is still allocated */ + msg->err = ERR_MEM; + } else { + /* delete the recvmbox and allocate the acceptmbox */ + if (sys_mbox_valid(&msg->conn->recvmbox)) { + /** @todo: should we drain the recvmbox here? */ + sys_mbox_free(&msg->conn->recvmbox); + sys_mbox_set_invalid(&msg->conn->recvmbox); + } + msg->err = ERR_OK; + if (!sys_mbox_valid(&msg->conn->acceptmbox)) { + msg->err = sys_mbox_new(&msg->conn->acceptmbox, DEFAULT_ACCEPTMBOX_SIZE); + } + if (msg->err == ERR_OK) { + msg->conn->state = NETCONN_LISTEN; + msg->conn->pcb.tcp = lpcb; + tcp_arg(msg->conn->pcb.tcp, msg->conn); + tcp_accept(msg->conn->pcb.tcp, accept_function); + } else { + /* since the old pcb is already deallocated, free lpcb now */ + tcp_close(lpcb); + msg->conn->pcb.tcp = NULL; + } + } + } + } else { + msg->err = ERR_ARG; + } + } + } + TCPIP_APIMSG_ACK(msg); +} +#endif /* LWIP_TCP */ + +/** + * Send some data on a RAW or UDP pcb contained in a netconn + * Called from netconn_send + * + * @param msg the api_msg_msg pointing to the connection + */ +void +do_send(struct api_msg_msg *msg) +{ + if (ERR_IS_FATAL(msg->conn->last_err)) { + msg->err = msg->conn->last_err; + } else { + msg->err = ERR_CONN; + if (msg->conn->pcb.tcp != NULL) { + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + if (ip_addr_isany(&msg->msg.b->addr)) { + msg->err = raw_send(msg->conn->pcb.raw, msg->msg.b->p); + } else { + msg->err = raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, &msg->msg.b->addr); + } + break; +#endif +#if LWIP_UDP + case NETCONN_UDP: +#if LWIP_CHECKSUM_ON_COPY + if (ip_addr_isany(&msg->msg.b->addr)) { + msg->err = udp_send_chksum(msg->conn->pcb.udp, msg->msg.b->p, + msg->msg.b->flags & NETBUF_FLAG_CHKSUM, msg->msg.b->toport_chksum); + } else { + msg->err = udp_sendto_chksum(msg->conn->pcb.udp, msg->msg.b->p, + &msg->msg.b->addr, msg->msg.b->port, + msg->msg.b->flags & NETBUF_FLAG_CHKSUM, msg->msg.b->toport_chksum); + } +#else /* LWIP_CHECKSUM_ON_COPY */ + if (ip_addr_isany(&msg->msg.b->addr)) { + msg->err = udp_send(msg->conn->pcb.udp, msg->msg.b->p); + } else { + msg->err = udp_sendto(msg->conn->pcb.udp, msg->msg.b->p, &msg->msg.b->addr, msg->msg.b->port); + } +#endif /* LWIP_CHECKSUM_ON_COPY */ + break; +#endif /* LWIP_UDP */ + default: + break; + } + } + } + TCPIP_APIMSG_ACK(msg); +} + +#if LWIP_TCP +/** + * Indicate data has been received from a TCP pcb contained in a netconn + * Called from netconn_recv + * + * @param msg the api_msg_msg pointing to the connection + */ +void +do_recv(struct api_msg_msg *msg) +{ + msg->err = ERR_OK; + if (msg->conn->pcb.tcp != NULL) { + if (msg->conn->type == NETCONN_TCP) { +#if TCP_LISTEN_BACKLOG + if (msg->conn->pcb.tcp->state == LISTEN) { + tcp_accepted(msg->conn->pcb.tcp); + } else +#endif /* TCP_LISTEN_BACKLOG */ + { + u32_t remaining = msg->msg.r.len; + do { + u16_t recved = (remaining > 0xffff) ? 0xffff : (u16_t)remaining; + tcp_recved(msg->conn->pcb.tcp, recved); + remaining -= recved; + }while(remaining != 0); + } + } + } + TCPIP_APIMSG_ACK(msg); +} + +/** + * See if more data needs to be written from a previous call to netconn_write. + * Called initially from do_write. If the first call can't send all data + * (because of low memory or empty send-buffer), this function is called again + * from sent_tcp() or poll_tcp() to send more data. If all data is sent, the + * blocking application thread (waiting in netconn_write) is released. + * + * @param conn netconn (that is currently in state NETCONN_WRITE) to process + * @return ERR_OK + * ERR_MEM if LWIP_TCPIP_CORE_LOCKING=1 and sending hasn't yet finished + */ +static err_t +do_writemore(struct netconn *conn) +{ + err_t err; + void *dataptr; + u16_t len, available; + u8_t write_finished = 0; + size_t diff; + u8_t dontblock = netconn_is_nonblocking(conn) || + (conn->current_msg->msg.w.apiflags & NETCONN_DONTBLOCK); + u8_t apiflags = conn->current_msg->msg.w.apiflags; + + LWIP_ASSERT("conn != NULL", conn != NULL); + LWIP_ASSERT("conn->state == NETCONN_WRITE", (conn->state == NETCONN_WRITE)); + LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL); + LWIP_ASSERT("conn->pcb.tcp != NULL", conn->pcb.tcp != NULL); + LWIP_ASSERT("conn->write_offset < conn->current_msg->msg.w.len", + conn->write_offset < conn->current_msg->msg.w.len); + +#if LWIP_SO_SNDTIMEO + if ((conn->send_timeout != 0) && + ((s32_t)(sys_now() - conn->current_msg->msg.w.time_started) >= conn->send_timeout)) { + write_finished = 1; + if (conn->write_offset == 0) { + /* nothing has been written */ + err = ERR_WOULDBLOCK; + conn->current_msg->msg.w.len = 0; + } else { + /* partial write */ + err = ERR_OK; + conn->current_msg->msg.w.len = conn->write_offset; + } + } else +#endif /* LWIP_SO_SNDTIMEO */ + { + dataptr = (u8_t*)conn->current_msg->msg.w.dataptr + conn->write_offset; + diff = conn->current_msg->msg.w.len - conn->write_offset; + if (diff > 0xffffUL) { /* max_u16_t */ + len = 0xffff; +#if LWIP_TCPIP_CORE_LOCKING + conn->flags |= NETCONN_FLAG_WRITE_DELAYED; +#endif + apiflags |= TCP_WRITE_FLAG_MORE; + } else { + len = (u16_t)diff; + } + available = tcp_sndbuf(conn->pcb.tcp); + if (available < len) { + /* don't try to write more than sendbuf */ + len = available; + if (dontblock){ + if (!len) { + err = ERR_WOULDBLOCK; + goto err_mem; + } + } else { +#if LWIP_TCPIP_CORE_LOCKING + conn->flags |= NETCONN_FLAG_WRITE_DELAYED; +#endif + apiflags |= TCP_WRITE_FLAG_MORE; + } + } + LWIP_ASSERT("do_writemore: invalid length!", ((conn->write_offset + len) <= conn->current_msg->msg.w.len)); + err = tcp_write(conn->pcb.tcp, dataptr, len, apiflags); + /* if OK or memory error, check available space */ + if ((err == ERR_OK) || (err == ERR_MEM)) { +err_mem: + if (dontblock && (len < conn->current_msg->msg.w.len)) { + /* non-blocking write did not write everything: mark the pcb non-writable + and let poll_tcp check writable space to mark the pcb writable again */ + API_EVENT(conn, NETCONN_EVT_SENDMINUS, len); + conn->flags |= NETCONN_FLAG_CHECK_WRITESPACE; + } else if ((tcp_sndbuf(conn->pcb.tcp) <= TCP_SNDLOWAT) || + (tcp_sndqueuelen(conn->pcb.tcp) >= TCP_SNDQUEUELOWAT)) { + /* The queued byte- or pbuf-count exceeds the configured low-water limit, + let select mark this pcb as non-writable. */ + API_EVENT(conn, NETCONN_EVT_SENDMINUS, len); + } + } + + if (err == ERR_OK) { + conn->write_offset += len; + if ((conn->write_offset == conn->current_msg->msg.w.len) || dontblock) { + /* return sent length */ + conn->current_msg->msg.w.len = conn->write_offset; + /* everything was written */ + write_finished = 1; + conn->write_offset = 0; + } + tcp_output(conn->pcb.tcp); + } else if ((err == ERR_MEM) && !dontblock) { + /* If ERR_MEM, we wait for sent_tcp or poll_tcp to be called + we do NOT return to the application thread, since ERR_MEM is + only a temporary error! */ + + /* tcp_write returned ERR_MEM, try tcp_output anyway */ + tcp_output(conn->pcb.tcp); + +#if LWIP_TCPIP_CORE_LOCKING + conn->flags |= NETCONN_FLAG_WRITE_DELAYED; +#endif + } else { + /* On errors != ERR_MEM, we don't try writing any more but return + the error to the application thread. */ + write_finished = 1; + conn->current_msg->msg.w.len = 0; + } + } + if (write_finished) { + /* everything was written: set back connection state + and back to application task */ + conn->current_msg->err = err; + conn->current_msg = NULL; + conn->state = NETCONN_NONE; +#if LWIP_TCPIP_CORE_LOCKING + if ((conn->flags & NETCONN_FLAG_WRITE_DELAYED) != 0) +#endif + { + sys_sem_signal(&conn->op_completed); + } + } +#if LWIP_TCPIP_CORE_LOCKING + else + return ERR_MEM; +#endif + return ERR_OK; +} +#endif /* LWIP_TCP */ + +/** + * Send some data on a TCP pcb contained in a netconn + * Called from netconn_write + * + * @param msg the api_msg_msg pointing to the connection + */ +void +do_write(struct api_msg_msg *msg) +{ + if (ERR_IS_FATAL(msg->conn->last_err)) { + msg->err = msg->conn->last_err; + } else { + if (msg->conn->type == NETCONN_TCP) { +#if LWIP_TCP + if (msg->conn->state != NETCONN_NONE) { + /* netconn is connecting, closing or in blocking write */ + msg->err = ERR_INPROGRESS; + } else if (msg->conn->pcb.tcp != NULL) { + msg->conn->state = NETCONN_WRITE; + /* set all the variables used by do_writemore */ + LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL && + msg->conn->write_offset == 0); + LWIP_ASSERT("msg->msg.w.len != 0", msg->msg.w.len != 0); + msg->conn->current_msg = msg; + msg->conn->write_offset = 0; +#if LWIP_TCPIP_CORE_LOCKING + msg->conn->flags &= ~NETCONN_FLAG_WRITE_DELAYED; + if (do_writemore(msg->conn) != ERR_OK) { + LWIP_ASSERT("state!", msg->conn->state == NETCONN_WRITE); + UNLOCK_TCPIP_CORE(); + sys_arch_sem_wait(&msg->conn->op_completed, 0); + LOCK_TCPIP_CORE(); + LWIP_ASSERT("state!", msg->conn->state == NETCONN_NONE); + } +#else /* LWIP_TCPIP_CORE_LOCKING */ + do_writemore(msg->conn); +#endif /* LWIP_TCPIP_CORE_LOCKING */ + /* for both cases: if do_writemore was called, don't ACK the APIMSG + since do_writemore ACKs it! */ + return; + } else { + msg->err = ERR_CONN; + } +#else /* LWIP_TCP */ + msg->err = ERR_VAL; +#endif /* LWIP_TCP */ +#if (LWIP_UDP || LWIP_RAW) + } else { + msg->err = ERR_VAL; +#endif /* (LWIP_UDP || LWIP_RAW) */ + } + } + TCPIP_APIMSG_ACK(msg); +} + +/** + * Return a connection's local or remote address + * Called from netconn_getaddr + * + * @param msg the api_msg_msg pointing to the connection + */ +void +do_getaddr(struct api_msg_msg *msg) +{ + if (msg->conn->pcb.ip != NULL) { + *(msg->msg.ad.ipaddr) = (msg->msg.ad.local ? msg->conn->pcb.ip->local_ip : + msg->conn->pcb.ip->remote_ip); + + msg->err = ERR_OK; + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + if (msg->msg.ad.local) { + *(msg->msg.ad.port) = msg->conn->pcb.raw->protocol; + } else { + /* return an error as connecting is only a helper for upper layers */ + msg->err = ERR_CONN; + } + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + if (msg->msg.ad.local) { + *(msg->msg.ad.port) = msg->conn->pcb.udp->local_port; + } else { + if ((msg->conn->pcb.udp->flags & UDP_FLAGS_CONNECTED) == 0) { + msg->err = ERR_CONN; + } else { + *(msg->msg.ad.port) = msg->conn->pcb.udp->remote_port; + } + } + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + *(msg->msg.ad.port) = (msg->msg.ad.local?msg->conn->pcb.tcp->local_port:msg->conn->pcb.tcp->remote_port); + break; +#endif /* LWIP_TCP */ + default: + LWIP_ASSERT("invalid netconn_type", 0); + break; + } + } else { + msg->err = ERR_CONN; + } + TCPIP_APIMSG_ACK(msg); +} + +/** + * Close a TCP pcb contained in a netconn + * Called from netconn_close + * + * @param msg the api_msg_msg pointing to the connection + */ +void +do_close(struct api_msg_msg *msg) +{ +#if LWIP_TCP + /* @todo: abort running write/connect? */ + if ((msg->conn->state != NETCONN_NONE) && (msg->conn->state != NETCONN_LISTEN)) { + /* this only happens for TCP netconns */ + LWIP_ASSERT("msg->conn->type == NETCONN_TCP", msg->conn->type == NETCONN_TCP); + msg->err = ERR_INPROGRESS; + } else if ((msg->conn->pcb.tcp != NULL) && (msg->conn->type == NETCONN_TCP)) { + if ((msg->msg.sd.shut != NETCONN_SHUT_RDWR) && (msg->conn->state == NETCONN_LISTEN)) { + /* LISTEN doesn't support half shutdown */ + msg->err = ERR_CONN; + } else { + if (msg->msg.sd.shut & NETCONN_SHUT_RD) { + /* Drain and delete mboxes */ + netconn_drain(msg->conn); + } + LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL && + msg->conn->write_offset == 0); + msg->conn->state = NETCONN_CLOSE; + msg->conn->current_msg = msg; + do_close_internal(msg->conn); + /* for tcp netconns, do_close_internal ACKs the message */ + return; + } + } else +#endif /* LWIP_TCP */ + { + msg->err = ERR_VAL; + } + sys_sem_signal(&msg->conn->op_completed); +} + +#if LWIP_IGMP +/** + * Join multicast groups for UDP netconns. + * Called from netconn_join_leave_group + * + * @param msg the api_msg_msg pointing to the connection + */ +void +do_join_leave_group(struct api_msg_msg *msg) +{ + if (ERR_IS_FATAL(msg->conn->last_err)) { + msg->err = msg->conn->last_err; + } else { + if (msg->conn->pcb.tcp != NULL) { + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) { +#if LWIP_UDP + if (msg->msg.jl.join_or_leave == NETCONN_JOIN) { + msg->err = igmp_joingroup(msg->msg.jl.netif_addr, msg->msg.jl.multiaddr); + } else { + msg->err = igmp_leavegroup(msg->msg.jl.netif_addr, msg->msg.jl.multiaddr); + } +#endif /* LWIP_UDP */ +#if (LWIP_TCP || LWIP_RAW) + } else { + msg->err = ERR_VAL; +#endif /* (LWIP_TCP || LWIP_RAW) */ + } + } else { + msg->err = ERR_CONN; + } + } + TCPIP_APIMSG_ACK(msg); +} +#endif /* LWIP_IGMP */ + +#if LWIP_DNS +/** + * Callback function that is called when DNS name is resolved + * (or on timeout). A waiting application thread is waked up by + * signaling the semaphore. + */ +static void +do_dns_found(const char *name, ip_addr_t *ipaddr, void *arg) +{ + struct dns_api_msg *msg = (struct dns_api_msg*)arg; + + LWIP_ASSERT("DNS response for wrong host name", strcmp(msg->name, name) == 0); + LWIP_UNUSED_ARG(name); + + if (ipaddr == NULL) { + /* timeout or memory error */ + *msg->err = ERR_VAL; + } else { + /* address was resolved */ + *msg->err = ERR_OK; + *msg->addr = *ipaddr; + } + /* wake up the application task waiting in netconn_gethostbyname */ + sys_sem_signal(msg->sem); +} + +/** + * Execute a DNS query + * Called from netconn_gethostbyname + * + * @param arg the dns_api_msg pointing to the query + */ +void +do_gethostbyname(void *arg) +{ + struct dns_api_msg *msg = (struct dns_api_msg*)arg; + + *msg->err = dns_gethostbyname(msg->name, msg->addr, do_dns_found, msg); + if (*msg->err != ERR_INPROGRESS) { + /* on error or immediate success, wake up the application + * task waiting in netconn_gethostbyname */ + sys_sem_signal(msg->sem); + } +} +#endif /* LWIP_DNS */ + +#endif /* LWIP_NETCONN */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/api/err.c b/component/common/network/lwip/lwip_v1.4.1/src/api/err.c new file mode 100644 index 0000000..92fa8b7 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/api/err.c @@ -0,0 +1,75 @@ +/** + * @file + * Error Management module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/err.h" + +#ifdef LWIP_DEBUG + +static const char *err_strerr[] = { + "Ok.", /* ERR_OK 0 */ + "Out of memory error.", /* ERR_MEM -1 */ + "Buffer error.", /* ERR_BUF -2 */ + "Timeout.", /* ERR_TIMEOUT -3 */ + "Routing problem.", /* ERR_RTE -4 */ + "Operation in progress.", /* ERR_INPROGRESS -5 */ + "Illegal value.", /* ERR_VAL -6 */ + "Operation would block.", /* ERR_WOULDBLOCK -7 */ + "Address in use.", /* ERR_USE -8 */ + "Already connected.", /* ERR_ISCONN -9 */ + "Connection aborted.", /* ERR_ABRT -10 */ + "Connection reset.", /* ERR_RST -11 */ + "Connection closed.", /* ERR_CLSD -12 */ + "Not connected.", /* ERR_CONN -13 */ + "Illegal argument.", /* ERR_ARG -14 */ + "Low-level netif error.", /* ERR_IF -15 */ +}; + +/** + * Convert an lwip internal error to a string representation. + * + * @param err an lwip internal err_t + * @return a string representation for err + */ +const char * +lwip_strerr(err_t err) +{ + return err_strerr[-err]; + +} + +#endif /* LWIP_DEBUG */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/api/netbuf.c b/component/common/network/lwip/lwip_v1.4.1/src/api/netbuf.c new file mode 100644 index 0000000..9390c9e --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/api/netbuf.c @@ -0,0 +1,245 @@ +/** + * @file + * Network buffer management + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/netbuf.h" +#include "lwip/memp.h" + +#include + +/** + * Create (allocate) and initialize a new netbuf. + * The netbuf doesn't yet contain a packet buffer! + * + * @return a pointer to a new netbuf + * NULL on lack of memory + */ +struct +netbuf *netbuf_new(void) +{ + struct netbuf *buf; + + buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); + if (buf != NULL) { + buf->p = NULL; + buf->ptr = NULL; + ip_addr_set_any(&buf->addr); + buf->port = 0; +#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY +#if LWIP_CHECKSUM_ON_COPY + buf->flags = 0; +#endif /* LWIP_CHECKSUM_ON_COPY */ + buf->toport_chksum = 0; +#if LWIP_NETBUF_RECVINFO + ip_addr_set_any(&buf->toaddr); +#endif /* LWIP_NETBUF_RECVINFO */ +#endif /* LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY */ + return buf; + } else { + return NULL; + } +} + +/** + * Deallocate a netbuf allocated by netbuf_new(). + * + * @param buf pointer to a netbuf allocated by netbuf_new() + */ +void +netbuf_delete(struct netbuf *buf) +{ + if (buf != NULL) { + if (buf->p != NULL) { + pbuf_free(buf->p); + buf->p = buf->ptr = NULL; + } + memp_free(MEMP_NETBUF, buf); + } +} + +/** + * Allocate memory for a packet buffer for a given netbuf. + * + * @param buf the netbuf for which to allocate a packet buffer + * @param size the size of the packet buffer to allocate + * @return pointer to the allocated memory + * NULL if no memory could be allocated + */ +void * +netbuf_alloc(struct netbuf *buf, u16_t size) +{ + LWIP_ERROR("netbuf_alloc: invalid buf", (buf != NULL), return NULL;); + + /* Deallocate any previously allocated memory. */ + if (buf->p != NULL) { + pbuf_free(buf->p); + } + buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM); + if (buf->p == NULL) { + return NULL; + } + LWIP_ASSERT("check that first pbuf can hold size", + (buf->p->len >= size)); + buf->ptr = buf->p; + return buf->p->payload; +} + +/** + * Free the packet buffer included in a netbuf + * + * @param buf pointer to the netbuf which contains the packet buffer to free + */ +void +netbuf_free(struct netbuf *buf) +{ + LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return;); + if (buf->p != NULL) { + pbuf_free(buf->p); + } + buf->p = buf->ptr = NULL; +} + +/** + * Let a netbuf reference existing (non-volatile) data. + * + * @param buf netbuf which should reference the data + * @param dataptr pointer to the data to reference + * @param size size of the data + * @return ERR_OK if data is referenced + * ERR_MEM if data couldn't be referenced due to lack of memory + */ +err_t +netbuf_ref(struct netbuf *buf, const void *dataptr, u16_t size) +{ + LWIP_ERROR("netbuf_ref: invalid buf", (buf != NULL), return ERR_ARG;); + if (buf->p != NULL) { + pbuf_free(buf->p); + } + buf->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF); + if (buf->p == NULL) { + buf->ptr = NULL; + return ERR_MEM; + } + buf->p->payload = (void*)dataptr; + buf->p->len = buf->p->tot_len = size; + buf->ptr = buf->p; + return ERR_OK; +} + +/** + * Chain one netbuf to another (@see pbuf_chain) + * + * @param head the first netbuf + * @param tail netbuf to chain after head, freed by this function, may not be reference after returning + */ +void +netbuf_chain(struct netbuf *head, struct netbuf *tail) +{ + LWIP_ERROR("netbuf_ref: invalid head", (head != NULL), return;); + LWIP_ERROR("netbuf_chain: invalid tail", (tail != NULL), return;); + pbuf_cat(head->p, tail->p); + head->ptr = head->p; + memp_free(MEMP_NETBUF, tail); +} + +/** + * Get the data pointer and length of the data inside a netbuf. + * + * @param buf netbuf to get the data from + * @param dataptr pointer to a void pointer where to store the data pointer + * @param len pointer to an u16_t where the length of the data is stored + * @return ERR_OK if the information was retreived, + * ERR_BUF on error. + */ +err_t +netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len) +{ + LWIP_ERROR("netbuf_data: invalid buf", (buf != NULL), return ERR_ARG;); + LWIP_ERROR("netbuf_data: invalid dataptr", (dataptr != NULL), return ERR_ARG;); + LWIP_ERROR("netbuf_data: invalid len", (len != NULL), return ERR_ARG;); + + if (buf->ptr == NULL) { + return ERR_BUF; + } + *dataptr = buf->ptr->payload; + *len = buf->ptr->len; + return ERR_OK; +} + +/** + * Move the current data pointer of a packet buffer contained in a netbuf + * to the next part. + * The packet buffer itself is not modified. + * + * @param buf the netbuf to modify + * @return -1 if there is no next part + * 1 if moved to the next part but now there is no next part + * 0 if moved to the next part and there are still more parts + */ +s8_t +netbuf_next(struct netbuf *buf) +{ + LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return -1;); + if (buf->ptr->next == NULL) { + return -1; + } + buf->ptr = buf->ptr->next; + if (buf->ptr->next == NULL) { + return 1; + } + return 0; +} + +/** + * Move the current data pointer of a packet buffer contained in a netbuf + * to the beginning of the packet. + * The packet buffer itself is not modified. + * + * @param buf the netbuf to modify + */ +void +netbuf_first(struct netbuf *buf) +{ + LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return;); + buf->ptr = buf->p; +} + +#endif /* LWIP_NETCONN */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/api/netdb.c b/component/common/network/lwip/lwip_v1.4.1/src/api/netdb.c new file mode 100644 index 0000000..6a4bac5 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/api/netdb.c @@ -0,0 +1,353 @@ +/** + * @file + * API functions for name resolving + * + */ + +/* + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Simon Goldschmidt + * + */ + +#include "lwip/netdb.h" + +#if LWIP_DNS && LWIP_SOCKET + +#include "lwip/err.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/ip_addr.h" +#include "lwip/api.h" +#include "lwip/dns.h" + +#include +#include + +/** helper struct for gethostbyname_r to access the char* buffer */ +struct gethostbyname_r_helper { + ip_addr_t *addr_list[2]; + ip_addr_t addr; + char *aliases; +}; + +/** h_errno is exported in netdb.h for access by applications. */ +#if LWIP_DNS_API_DECLARE_H_ERRNO +int h_errno; +#endif /* LWIP_DNS_API_DECLARE_H_ERRNO */ + +/** define "hostent" variables storage: 0 if we use a static (but unprotected) + * set of variables for lwip_gethostbyname, 1 if we use a local storage */ +#ifndef LWIP_DNS_API_HOSTENT_STORAGE +#define LWIP_DNS_API_HOSTENT_STORAGE 0 +#endif + +/** define "hostent" variables storage */ +#if LWIP_DNS_API_HOSTENT_STORAGE +#define HOSTENT_STORAGE +#else +#define HOSTENT_STORAGE static +#endif /* LWIP_DNS_API_STATIC_HOSTENT */ + +/** + * Returns an entry containing addresses of address family AF_INET + * for the host with name name. + * Due to dns_gethostbyname limitations, only one address is returned. + * + * @param name the hostname to resolve + * @return an entry containing addresses of address family AF_INET + * for the host with name name + */ +struct hostent* +lwip_gethostbyname(const char *name) +{ + err_t err; + ip_addr_t addr; + + /* buffer variables for lwip_gethostbyname() */ + HOSTENT_STORAGE struct hostent s_hostent; + HOSTENT_STORAGE char *s_aliases; + HOSTENT_STORAGE ip_addr_t s_hostent_addr; + HOSTENT_STORAGE ip_addr_t *s_phostent_addr[2]; + + /* query host IP address */ + err = netconn_gethostbyname(name, &addr); + if (err != ERR_OK) { + LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err)); + h_errno = HOST_NOT_FOUND; + return NULL; + } + + /* fill hostent */ + s_hostent_addr = addr; + s_phostent_addr[0] = &s_hostent_addr; + s_phostent_addr[1] = NULL; + s_hostent.h_name = (char*)name; + s_hostent.h_aliases = &s_aliases; + s_hostent.h_addrtype = AF_INET; + s_hostent.h_length = sizeof(ip_addr_t); + s_hostent.h_addr_list = (char**)&s_phostent_addr; + +#if DNS_DEBUG + /* dump hostent */ + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_name == %s\n", s_hostent.h_name)); + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases == %p\n", s_hostent.h_aliases)); + if (s_hostent.h_aliases != NULL) { + u8_t idx; + for ( idx=0; s_hostent.h_aliases[idx]; idx++) { + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases[%i]-> == %p\n", idx, s_hostent.h_aliases[idx])); + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases[%i]-> == %s\n", idx, s_hostent.h_aliases[idx])); + } + } + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addrtype == %d\n", s_hostent.h_addrtype)); + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_length == %d\n", s_hostent.h_length)); + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list == %p\n", s_hostent.h_addr_list)); + if (s_hostent.h_addr_list != NULL) { + u8_t idx; + for ( idx=0; s_hostent.h_addr_list[idx]; idx++) { + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i] == %p\n", idx, s_hostent.h_addr_list[idx])); + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i]-> == %s\n", idx, ip_ntoa((ip_addr_t*)s_hostent.h_addr_list[idx]))); + } + } +#endif /* DNS_DEBUG */ + +#if LWIP_DNS_API_HOSTENT_STORAGE + /* this function should return the "per-thread" hostent after copy from s_hostent */ + return sys_thread_hostent(&s_hostent); +#else + return &s_hostent; +#endif /* LWIP_DNS_API_HOSTENT_STORAGE */ +} + +/** + * Thread-safe variant of lwip_gethostbyname: instead of using a static + * buffer, this function takes buffer and errno pointers as arguments + * and uses these for the result. + * + * @param name the hostname to resolve + * @param ret pre-allocated struct where to store the result + * @param buf pre-allocated buffer where to store additional data + * @param buflen the size of buf + * @param result pointer to a hostent pointer that is set to ret on success + * and set to zero on error + * @param h_errnop pointer to an int where to store errors (instead of modifying + * the global h_errno) + * @return 0 on success, non-zero on error, additional error information + * is stored in *h_errnop instead of h_errno to be thread-safe + */ +int +lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf, + size_t buflen, struct hostent **result, int *h_errnop) +{ + err_t err; + struct gethostbyname_r_helper *h; + char *hostname; + size_t namelen; + int lh_errno; + + if (h_errnop == NULL) { + /* ensure h_errnop is never NULL */ + h_errnop = &lh_errno; + } + + if (result == NULL) { + /* not all arguments given */ + *h_errnop = EINVAL; + return -1; + } + /* first thing to do: set *result to nothing */ + *result = NULL; + if ((name == NULL) || (ret == NULL) || (buf == NULL)) { + /* not all arguments given */ + *h_errnop = EINVAL; + return -1; + } + + namelen = strlen(name); + if (buflen < (sizeof(struct gethostbyname_r_helper) + namelen + 1 + (MEM_ALIGNMENT - 1))) { + /* buf can't hold the data needed + a copy of name */ + *h_errnop = ERANGE; + return -1; + } + + h = (struct gethostbyname_r_helper*)LWIP_MEM_ALIGN(buf); + hostname = ((char*)h) + sizeof(struct gethostbyname_r_helper); + + /* query host IP address */ + err = netconn_gethostbyname(name, &h->addr); + if (err != ERR_OK) { + LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err)); + *h_errnop = HOST_NOT_FOUND; + return -1; + } + + /* copy the hostname into buf */ + MEMCPY(hostname, name, namelen); + hostname[namelen] = 0; + + /* fill hostent */ + h->addr_list[0] = &h->addr; + h->addr_list[1] = NULL; + h->aliases = NULL; + ret->h_name = hostname; + ret->h_aliases = &h->aliases; + ret->h_addrtype = AF_INET; + ret->h_length = sizeof(ip_addr_t); + ret->h_addr_list = (char**)&h->addr_list; + + /* set result != NULL */ + *result = ret; + + /* return success */ + return 0; +} + +/** + * Frees one or more addrinfo structures returned by getaddrinfo(), along with + * any additional storage associated with those structures. If the ai_next field + * of the structure is not null, the entire list of structures is freed. + * + * @param ai struct addrinfo to free + */ +void +lwip_freeaddrinfo(struct addrinfo *ai) +{ + struct addrinfo *next; + + while (ai != NULL) { + next = ai->ai_next; + memp_free(MEMP_NETDB, ai); + ai = next; + } +} + +/** + * Translates the name of a service location (for example, a host name) and/or + * a service name and returns a set of socket addresses and associated + * information to be used in creating a socket with which to address the + * specified service. + * Memory for the result is allocated internally and must be freed by calling + * lwip_freeaddrinfo()! + * + * Due to a limitation in dns_gethostbyname, only the first address of a + * host is returned. + * Also, service names are not supported (only port numbers)! + * + * @param nodename descriptive name or address string of the host + * (may be NULL -> local address) + * @param servname port number as string of NULL + * @param hints structure containing input values that set socktype and protocol + * @param res pointer to a pointer where to store the result (set to NULL on failure) + * @return 0 on success, non-zero on failure + */ +int +lwip_getaddrinfo(const char *nodename, const char *servname, + const struct addrinfo *hints, struct addrinfo **res) +{ + err_t err; + ip_addr_t addr; + struct addrinfo *ai; + struct sockaddr_in *sa = NULL; + int port_nr = 0; + size_t total_size; + size_t namelen = 0; + + if (res == NULL) { + return EAI_FAIL; + } + *res = NULL; + if ((nodename == NULL) && (servname == NULL)) { + return EAI_NONAME; + } + + if (servname != NULL) { + /* service name specified: convert to port number + * @todo?: currently, only ASCII integers (port numbers) are supported! */ + port_nr = atoi(servname); + if ((port_nr <= 0) || (port_nr > 0xffff)) { + return EAI_SERVICE; + } + } + + if (nodename != NULL) { + /* service location specified, try to resolve */ + err = netconn_gethostbyname(nodename, &addr); + if (err != ERR_OK) { + return EAI_FAIL; + } + } else { + /* service location specified, use loopback address */ + ip_addr_set_loopback(&addr); + } + + total_size = sizeof(struct addrinfo) + sizeof(struct sockaddr_in); + if (nodename != NULL) { + namelen = strlen(nodename); + LWIP_ASSERT("namelen is too long", (namelen + 1) <= (mem_size_t)-1); + total_size += namelen + 1; + } + /* If this fails, please report to lwip-devel! :-) */ + LWIP_ASSERT("total_size <= NETDB_ELEM_SIZE: please report this!", + total_size <= NETDB_ELEM_SIZE); + ai = (struct addrinfo *)memp_malloc(MEMP_NETDB); + if (ai == NULL) { + goto memerr; + } + memset(ai, 0, total_size); + sa = (struct sockaddr_in*)((u8_t*)ai + sizeof(struct addrinfo)); + /* set up sockaddr */ + inet_addr_from_ipaddr(&sa->sin_addr, &addr); + sa->sin_family = AF_INET; + sa->sin_len = sizeof(struct sockaddr_in); + sa->sin_port = htons((u16_t)port_nr); + + /* set up addrinfo */ + ai->ai_family = AF_INET; + if (hints != NULL) { + /* copy socktype & protocol from hints if specified */ + ai->ai_socktype = hints->ai_socktype; + ai->ai_protocol = hints->ai_protocol; + } + if (nodename != NULL) { + /* copy nodename to canonname if specified */ + ai->ai_canonname = ((char*)ai + sizeof(struct addrinfo) + sizeof(struct sockaddr_in)); + MEMCPY(ai->ai_canonname, nodename, namelen); + ai->ai_canonname[namelen] = 0; + } + ai->ai_addrlen = sizeof(struct sockaddr_in); + ai->ai_addr = (struct sockaddr*)sa; + + *res = ai; + + return 0; +memerr: + if (ai != NULL) { + memp_free(MEMP_NETDB, ai); + } + return EAI_MEMORY; +} + +#endif /* LWIP_DNS && LWIP_SOCKET */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/api/netifapi.c b/component/common/network/lwip/lwip_v1.4.1/src/api/netifapi.c new file mode 100644 index 0000000..43e4720 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/api/netifapi.c @@ -0,0 +1,160 @@ +/** + * @file + * Network Interface Sequential API module + * + */ + +/* + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/opt.h" + +#if LWIP_NETIF_API /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/netifapi.h" +#include "lwip/tcpip.h" + +/** + * Call netif_add() inside the tcpip_thread context. + */ +void +do_netifapi_netif_add(struct netifapi_msg_msg *msg) +{ + if (!netif_add( msg->netif, + msg->msg.add.ipaddr, + msg->msg.add.netmask, + msg->msg.add.gw, + msg->msg.add.state, + msg->msg.add.init, + msg->msg.add.input)) { + msg->err = ERR_IF; + } else { + msg->err = ERR_OK; + } + TCPIP_NETIFAPI_ACK(msg); +} + +/** + * Call netif_set_addr() inside the tcpip_thread context. + */ +void +do_netifapi_netif_set_addr(struct netifapi_msg_msg *msg) +{ + netif_set_addr( msg->netif, + msg->msg.add.ipaddr, + msg->msg.add.netmask, + msg->msg.add.gw); + msg->err = ERR_OK; + TCPIP_NETIFAPI_ACK(msg); +} + +/** + * Call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) inside the + * tcpip_thread context. + */ +void +do_netifapi_netif_common(struct netifapi_msg_msg *msg) +{ + if (msg->msg.common.errtfunc != NULL) { + msg->err = msg->msg.common.errtfunc(msg->netif); + } else { + msg->err = ERR_OK; + msg->msg.common.voidfunc(msg->netif); + } + TCPIP_NETIFAPI_ACK(msg); +} + +/** + * Call netif_add() in a thread-safe way by running that function inside the + * tcpip_thread context. + * + * @note for params @see netif_add() + */ +err_t +netifapi_netif_add(struct netif *netif, + ip_addr_t *ipaddr, + ip_addr_t *netmask, + ip_addr_t *gw, + void *state, + netif_init_fn init, + netif_input_fn input) +{ + struct netifapi_msg msg; + msg.function = do_netifapi_netif_add; + msg.msg.netif = netif; + msg.msg.msg.add.ipaddr = ipaddr; + msg.msg.msg.add.netmask = netmask; + msg.msg.msg.add.gw = gw; + msg.msg.msg.add.state = state; + msg.msg.msg.add.init = init; + msg.msg.msg.add.input = input; + TCPIP_NETIFAPI(&msg); + return msg.msg.err; +} + +/** + * Call netif_set_addr() in a thread-safe way by running that function inside the + * tcpip_thread context. + * + * @note for params @see netif_set_addr() + */ +err_t +netifapi_netif_set_addr(struct netif *netif, + ip_addr_t *ipaddr, + ip_addr_t *netmask, + ip_addr_t *gw) +{ + struct netifapi_msg msg; + msg.function = do_netifapi_netif_set_addr; + msg.msg.netif = netif; + msg.msg.msg.add.ipaddr = ipaddr; + msg.msg.msg.add.netmask = netmask; + msg.msg.msg.add.gw = gw; + TCPIP_NETIFAPI(&msg); + return msg.msg.err; +} + +/** + * call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) in a thread-safe + * way by running that function inside the tcpip_thread context. + * + * @note use only for functions where there is only "netif" parameter. + */ +err_t +netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc, + netifapi_errt_fn errtfunc) +{ + struct netifapi_msg msg; + msg.function = do_netifapi_netif_common; + msg.msg.netif = netif; + msg.msg.msg.common.voidfunc = voidfunc; + msg.msg.msg.common.errtfunc = errtfunc; + TCPIP_NETIFAPI(&msg); + return msg.msg.err; +} + +#endif /* LWIP_NETIF_API */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/api/sockets.c b/component/common/network/lwip/lwip_v1.4.1/src/api/sockets.c new file mode 100644 index 0000000..2f8765b --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/api/sockets.c @@ -0,0 +1,2444 @@ +/** + * @file + * Sockets BSD-Like API module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + * Improved by Marc Boucher and David Haas + * + */ + +#include "lwip/opt.h" + +#if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/sockets.h" +#include "lwip/api.h" +#include "lwip/sys.h" +#include "lwip/igmp.h" +#include "lwip/inet.h" +#include "lwip/tcp.h" +#include "lwip/raw.h" +#include "lwip/udp.h" +#include "lwip/tcpip.h" +#include "lwip/pbuf.h" +#if LWIP_CHECKSUM_ON_COPY +#include "lwip/inet_chksum.h" +#endif + +#include + +#define NUM_SOCKETS MEMP_NUM_NETCONN + +/** Contains all internal pointers and states used for a socket */ +struct lwip_sock { + /** sockets currently are built on netconns, each socket has one netconn */ + struct netconn *conn; + /** data that was left from the previous read */ + void *lastdata; + /** offset in the data that was left from the previous read */ + u16_t lastoffset; + /** number of times data was received, set by event_callback(), + tested by the receive and select functions */ + s16_t rcvevent; + /** number of times data was ACKed (free send buffer), set by event_callback(), + tested by select */ + u16_t sendevent; + /** error happened for this socket, set by event_callback(), tested by select */ + u16_t errevent; + /** last error that occurred on this socket */ + int err; + /** counter of how many threads are waiting for this socket using select */ + int select_waiting; +}; + +/** Description for a task waiting in select */ +struct lwip_select_cb { + /** Pointer to the next waiting task */ + struct lwip_select_cb *next; + /** Pointer to the previous waiting task */ + struct lwip_select_cb *prev; + /** readset passed to select */ + fd_set *readset; + /** writeset passed to select */ + fd_set *writeset; + /** unimplemented: exceptset passed to select */ + fd_set *exceptset; + /** don't signal the same semaphore twice: set to 1 when signalled */ + int sem_signalled; + /** semaphore to wake up a task waiting for select */ + sys_sem_t sem; +}; + +/** This struct is used to pass data to the set/getsockopt_internal + * functions running in tcpip_thread context (only a void* is allowed) */ +struct lwip_setgetsockopt_data { + /** socket struct for which to change options */ + struct lwip_sock *sock; +#ifdef LWIP_DEBUG + /** socket index for which to change options */ + int s; +#endif /* LWIP_DEBUG */ + /** level of the option to process */ + int level; + /** name of the option to process */ + int optname; + /** set: value to set the option to + * get: value of the option is stored here */ + void *optval; + /** size of *optval */ + socklen_t *optlen; + /** if an error occures, it is temporarily stored here */ + err_t err; +}; + +/** The global array of available sockets */ +static struct lwip_sock sockets[NUM_SOCKETS]; +/** The global list of tasks waiting for select */ +static struct lwip_select_cb *select_cb_list; +/** This counter is increased from lwip_select when the list is chagned + and checked in event_callback to see if it has changed. */ +static volatile int select_cb_ctr; + +/** Table to quickly map an lwIP error (err_t) to a socket error + * by using -err as an index */ +static const int err_to_errno_table[] = { + 0, /* ERR_OK 0 No error, everything OK. */ + ENOMEM, /* ERR_MEM -1 Out of memory error. */ + ENOBUFS, /* ERR_BUF -2 Buffer error. */ + EWOULDBLOCK, /* ERR_TIMEOUT -3 Timeout */ + EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */ + EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */ + EINVAL, /* ERR_VAL -6 Illegal value. */ + EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */ + EADDRINUSE, /* ERR_USE -8 Address in use. */ + EALREADY, /* ERR_ISCONN -9 Already connected. */ + ECONNABORTED, /* ERR_ABRT -10 Connection aborted. */ + ECONNRESET, /* ERR_RST -11 Connection reset. */ + ENOTCONN, /* ERR_CLSD -12 Connection closed. */ + ENOTCONN, /* ERR_CONN -13 Not connected. */ + EIO, /* ERR_ARG -14 Illegal argument. */ + -1, /* ERR_IF -15 Low-level netif error */ +}; + +#define ERR_TO_ERRNO_TABLE_SIZE \ + (sizeof(err_to_errno_table)/sizeof(err_to_errno_table[0])) + +#define err_to_errno(err) \ + ((unsigned)(-(err)) < ERR_TO_ERRNO_TABLE_SIZE ? \ + err_to_errno_table[-(err)] : EIO) + +#ifdef ERRNO +#ifndef set_errno +#define set_errno(err) errno = (err) +#endif +#else /* ERRNO */ +#define set_errno(err) +#endif /* ERRNO */ + +#define sock_set_errno(sk, e) do { \ + sk->err = (e); \ + set_errno(sk->err); \ +} while (0) + +/* Forward delcaration of some functions */ +static void event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len); +static void lwip_getsockopt_internal(void *arg); +static void lwip_setsockopt_internal(void *arg); + +/** + * Initialize this module. This function has to be called before any other + * functions in this module! + */ +void +lwip_socket_init(void) +{ +} + +/** + * Map a externally used socket index to the internal socket representation. + * + * @param s externally used socket index + * @return struct lwip_sock for the socket or NULL if not found + */ +static struct lwip_sock * +get_socket(int s) +{ + struct lwip_sock *sock; + + if ((s < 0) || (s >= NUM_SOCKETS)) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): invalid\n", s)); + set_errno(EBADF); + return NULL; + } + + sock = &sockets[s]; + + if (!sock->conn) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): not active\n", s)); + set_errno(EBADF); + return NULL; + } + + return sock; +} + +/** + * Same as get_socket but doesn't set errno + * + * @param s externally used socket index + * @return struct lwip_sock for the socket or NULL if not found + */ +static struct lwip_sock * +tryget_socket(int s) +{ + if ((s < 0) || (s >= NUM_SOCKETS)) { + return NULL; + } + if (!sockets[s].conn) { + return NULL; + } + return &sockets[s]; +} + +/** + * Allocate a new socket for a given netconn. + * + * @param newconn the netconn for which to allocate a socket + * @param accepted 1 if socket has been created by accept(), + * 0 if socket has been created by socket() + * @return the index of the new socket; -1 on error + */ +static int +alloc_socket(struct netconn *newconn, int accepted) +{ + int i; + SYS_ARCH_DECL_PROTECT(lev); + + /* allocate a new socket identifier */ + for (i = 0; i < NUM_SOCKETS; ++i) { + /* Protect socket array */ + SYS_ARCH_PROTECT(lev); + if (!sockets[i].conn) { + sockets[i].conn = newconn; + /* The socket is not yet known to anyone, so no need to protect + after having marked it as used. */ + SYS_ARCH_UNPROTECT(lev); + sockets[i].lastdata = NULL; + sockets[i].lastoffset = 0; + sockets[i].rcvevent = 0; + /* TCP sendbuf is empty, but the socket is not yet writable until connected + * (unless it has been created by accept()). */ + sockets[i].sendevent = (newconn->type == NETCONN_TCP ? (accepted != 0) : 1); + sockets[i].errevent = 0; + sockets[i].err = 0; + sockets[i].select_waiting = 0; + return i; + } + SYS_ARCH_UNPROTECT(lev); + } + return -1; +} + +/** Free a socket. The socket's netconn must have been + * delete before! + * + * @param sock the socket to free + * @param is_tcp != 0 for TCP sockets, used to free lastdata + */ +static void +free_socket(struct lwip_sock *sock, int is_tcp) +{ + void *lastdata; + SYS_ARCH_DECL_PROTECT(lev); + + lastdata = sock->lastdata; + sock->lastdata = NULL; + sock->lastoffset = 0; + sock->err = 0; + + /* Protect socket array */ + SYS_ARCH_PROTECT(lev); + sock->conn = NULL; + SYS_ARCH_UNPROTECT(lev); + /* don't use 'sock' after this line, as another task might have allocated it */ + + if (lastdata != NULL) { + if (is_tcp) { + pbuf_free((struct pbuf *)lastdata); + } else { + netbuf_delete((struct netbuf *)lastdata); + } + } +} + +/* Below this, the well-known socket functions are implemented. + * Use google.com or opengroup.org to get a good description :-) + * + * Exceptions are documented! + */ + +int +lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen) +{ + struct lwip_sock *sock, *nsock; + struct netconn *newconn; + ip_addr_t naddr; + u16_t port; + int newsock; + struct sockaddr_in sin; + err_t err; + SYS_ARCH_DECL_PROTECT(lev); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s)); + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (netconn_is_nonblocking(sock->conn) && (sock->rcvevent <= 0)) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): returning EWOULDBLOCK\n", s)); + sock_set_errno(sock, EWOULDBLOCK); + return -1; + } + + /* wait for a new connection */ + err = netconn_accept(sock->conn, &newconn); + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_acept failed, err=%d\n", s, err)); + if (netconn_type(sock->conn) != NETCONN_TCP) { + sock_set_errno(sock, EOPNOTSUPP); + return EOPNOTSUPP; + } + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + LWIP_ASSERT("newconn != NULL", newconn != NULL); + /* Prevent automatic window updates, we do this on our own! */ + netconn_set_noautorecved(newconn, 1); + + /* get the IP address and port of the remote host */ + err = netconn_peer(newconn, &naddr, &port); + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_peer failed, err=%d\n", s, err)); + netconn_delete(newconn); + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + + /* Note that POSIX only requires us to check addr is non-NULL. addrlen must + * not be NULL if addr is valid. + */ + if (NULL != addr) { + LWIP_ASSERT("addr valid but addrlen NULL", addrlen != NULL); + memset(&sin, 0, sizeof(sin)); + sin.sin_len = sizeof(sin); + sin.sin_family = AF_INET; + sin.sin_port = htons(port); + inet_addr_from_ipaddr(&sin.sin_addr, &naddr); + + if (*addrlen > sizeof(sin)) + *addrlen = sizeof(sin); + + MEMCPY(addr, &sin, *addrlen); + } + + newsock = alloc_socket(newconn, 1); + if (newsock == -1) { + netconn_delete(newconn); + sock_set_errno(sock, ENFILE); + return -1; + } + LWIP_ASSERT("invalid socket index", (newsock >= 0) && (newsock < NUM_SOCKETS)); + LWIP_ASSERT("newconn->callback == event_callback", newconn->callback == event_callback); + nsock = &sockets[newsock]; + + /* See event_callback: If data comes in right away after an accept, even + * though the server task might not have created a new socket yet. + * In that case, newconn->socket is counted down (newconn->socket--), + * so nsock->rcvevent is >= 1 here! + */ + SYS_ARCH_PROTECT(lev); + nsock->rcvevent += (s16_t)(-1 - newconn->socket); + newconn->socket = newsock; + SYS_ARCH_UNPROTECT(lev); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d addr=", s, newsock)); + ip_addr_debug_print(SOCKETS_DEBUG, &naddr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", port)); + + sock_set_errno(sock, 0); + return newsock; +} + +int +lwip_bind(int s, const struct sockaddr *name, socklen_t namelen) +{ + struct lwip_sock *sock; + ip_addr_t local_addr; + u16_t local_port; + err_t err; + const struct sockaddr_in *name_in; + + sock = get_socket(s); + if (!sock) { + return -1; + } + + /* check size, familiy and alignment of 'name' */ + LWIP_ERROR("lwip_bind: invalid address", ((namelen == sizeof(struct sockaddr_in)) && + ((name->sa_family) == AF_INET) && ((((mem_ptr_t)name) % 4) == 0)), + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + name_in = (const struct sockaddr_in *)(void*)name; + + inet_addr_to_ipaddr(&local_addr, &name_in->sin_addr); + local_port = name_in->sin_port; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s)); + ip_addr_debug_print(SOCKETS_DEBUG, &local_addr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", ntohs(local_port))); + + err = netconn_bind(sock->conn, &local_addr, ntohs(local_port)); + + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) failed, err=%d\n", s, err)); + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) succeeded\n", s)); + sock_set_errno(sock, 0); + return 0; +} + +int +lwip_close(int s) +{ + struct lwip_sock *sock; + int is_tcp = 0; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_close(%d)\n", s)); + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if(sock->conn != NULL) { + is_tcp = netconn_type(sock->conn) == NETCONN_TCP; + } else { + LWIP_ASSERT("sock->lastdata == NULL", sock->lastdata == NULL); + } + + netconn_delete(sock->conn); + + free_socket(sock, is_tcp); + set_errno(0); + return 0; +} + +int +lwip_connect(int s, const struct sockaddr *name, socklen_t namelen) +{ + struct lwip_sock *sock; + err_t err; + const struct sockaddr_in *name_in; + + sock = get_socket(s); + if (!sock) { + return -1; + } + + /* check size, familiy and alignment of 'name' */ + LWIP_ERROR("lwip_connect: invalid address", ((namelen == sizeof(struct sockaddr_in)) && + ((name->sa_family) == AF_INET) && ((((mem_ptr_t)name) % 4) == 0)), + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + name_in = (const struct sockaddr_in *)(void*)name; + + if (name_in->sin_family == AF_UNSPEC) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, AF_UNSPEC)\n", s)); + err = netconn_disconnect(sock->conn); + } else { + ip_addr_t remote_addr; + u16_t remote_port; + + inet_addr_to_ipaddr(&remote_addr, &name_in->sin_addr); + remote_port = name_in->sin_port; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, addr=", s)); + ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", ntohs(remote_port))); + + err = netconn_connect(sock->conn, &remote_addr, ntohs(remote_port)); + } + + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) failed, err=%d\n", s, err)); + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) succeeded\n", s)); + sock_set_errno(sock, 0); + return 0; +} + +/** + * Set a socket into listen mode. + * The socket may not have been used for another connection previously. + * + * @param s the socket to set to listening mode + * @param backlog (ATTENTION: needs TCP_LISTEN_BACKLOG=1) + * @return 0 on success, non-zero on failure + */ +int +lwip_listen(int s, int backlog) +{ + struct lwip_sock *sock; + err_t err; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d, backlog=%d)\n", s, backlog)); + + sock = get_socket(s); + if (!sock) { + return -1; + } + + /* limit the "backlog" parameter to fit in an u8_t */ + backlog = LWIP_MIN(LWIP_MAX(backlog, 0), 0xff); + + err = netconn_listen_with_backlog(sock->conn, (u8_t)backlog); + + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d) failed, err=%d\n", s, err)); + if (netconn_type(sock->conn) != NETCONN_TCP) { + sock_set_errno(sock, EOPNOTSUPP); + return EOPNOTSUPP; + } + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + + sock_set_errno(sock, 0); + return 0; +} + +int +lwip_recvfrom(int s, void *mem, size_t len, int flags, + struct sockaddr *from, socklen_t *fromlen) +{ + struct lwip_sock *sock; + void *buf = NULL; + struct pbuf *p; + u16_t buflen, copylen; + int off = 0; + ip_addr_t *addr; + u16_t port; + u8_t done = 0; + err_t err; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %"SZT_F", 0x%x, ..)\n", s, mem, len, flags)); + sock = get_socket(s); + if (!sock) { + return -1; + } + + do { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: top while sock->lastdata=%p\n", sock->lastdata)); + /* Check if there is data left from the last recv operation. */ + if (sock->lastdata) { + buf = sock->lastdata; + } else { + /* If this is non-blocking call, then check first */ + if (((flags & MSG_DONTWAIT) || netconn_is_nonblocking(sock->conn)) && + (sock->rcvevent <= 0)) { + if (off > 0) { + /* update receive window */ + netconn_recved(sock->conn, (u32_t)off); + /* already received data, return that */ + sock_set_errno(sock, 0); + return off; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s)); + sock_set_errno(sock, EWOULDBLOCK); + return -1; + } + + /* No data was left from the previous operation, so we try to get + some from the network. */ + if (netconn_type(sock->conn) == NETCONN_TCP) { + err = netconn_recv_tcp_pbuf(sock->conn, (struct pbuf **)&buf); + } else { + err = netconn_recv(sock->conn, (struct netbuf **)&buf); + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: netconn_recv err=%d, netbuf=%p\n", + err, buf)); + + if (err != ERR_OK) { + if (off > 0) { + /* update receive window */ + netconn_recved(sock->conn, (u32_t)off); + /* already received data, return that */ + sock_set_errno(sock, 0); + return off; + } + /* We should really do some error checking here. */ + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): buf == NULL, error is \"%s\"!\n", + s, lwip_strerr(err))); + sock_set_errno(sock, err_to_errno(err)); + if (err == ERR_CLSD) { + return 0; + } else { + return -1; + } + } + LWIP_ASSERT("buf != NULL", buf != NULL); + sock->lastdata = buf; + } + + if (netconn_type(sock->conn) == NETCONN_TCP) { + p = (struct pbuf *)buf; + } else { + p = ((struct netbuf *)buf)->p; + } + buflen = p->tot_len; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: buflen=%"U16_F" len=%"SZT_F" off=%d sock->lastoffset=%"U16_F"\n", + buflen, len, off, sock->lastoffset)); + + buflen -= sock->lastoffset; + + if (len > buflen) { + copylen = buflen; + } else { + copylen = (u16_t)len; + } + + /* copy the contents of the received buffer into + the supplied memory pointer mem */ + pbuf_copy_partial(p, (u8_t*)mem + off, copylen, sock->lastoffset); + + off += copylen; + + if (netconn_type(sock->conn) == NETCONN_TCP) { + LWIP_ASSERT("invalid copylen, len would underflow", len >= copylen); + len -= copylen; + if ( (len <= 0) || + (p->flags & PBUF_FLAG_PUSH) || + (sock->rcvevent <= 0) || + ((flags & MSG_PEEK)!=0)) { + done = 1; + } + } else { + done = 1; + } + + /* Check to see from where the data was.*/ + if (done) { + ip_addr_t fromaddr; + if (from && fromlen) { + struct sockaddr_in sin; + + if (netconn_type(sock->conn) == NETCONN_TCP) { + addr = &fromaddr; + netconn_getaddr(sock->conn, addr, &port, 0); + } else { + addr = netbuf_fromaddr((struct netbuf *)buf); + port = netbuf_fromport((struct netbuf *)buf); + } + + memset(&sin, 0, sizeof(sin)); + sin.sin_len = sizeof(sin); + sin.sin_family = AF_INET; + sin.sin_port = htons(port); + inet_addr_from_ipaddr(&sin.sin_addr, addr); + + if (*fromlen > sizeof(sin)) { + *fromlen = sizeof(sin); + } + + MEMCPY(from, &sin, *fromlen); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s)); + ip_addr_debug_print(SOCKETS_DEBUG, addr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%d\n", port, off)); + } else { +#if SOCKETS_DEBUG + if (netconn_type(sock->conn) == NETCONN_TCP) { + addr = &fromaddr; + netconn_getaddr(sock->conn, addr, &port, 0); + } else { + addr = netbuf_fromaddr((struct netbuf *)buf); + port = netbuf_fromport((struct netbuf *)buf); + } + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s)); + ip_addr_debug_print(SOCKETS_DEBUG, addr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%d\n", port, off)); +#endif /* SOCKETS_DEBUG */ + } + } + + /* If we don't peek the incoming message... */ + if ((flags & MSG_PEEK) == 0) { + /* If this is a TCP socket, check if there is data left in the + buffer. If so, it should be saved in the sock structure for next + time around. */ + if ((netconn_type(sock->conn) == NETCONN_TCP) && (buflen - copylen > 0)) { + sock->lastdata = buf; + sock->lastoffset += copylen; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: lastdata now netbuf=%p\n", buf)); + } else { + sock->lastdata = NULL; + sock->lastoffset = 0; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: deleting netbuf=%p\n", buf)); + if (netconn_type(sock->conn) == NETCONN_TCP) { + pbuf_free((struct pbuf *)buf); + } else { + netbuf_delete((struct netbuf *)buf); + } + } + } + } while (!done); + + if (off > 0) { + /* update receive window */ + netconn_recved(sock->conn, (u32_t)off); + } + sock_set_errno(sock, 0); + return off; +} + +int +lwip_read(int s, void *mem, size_t len) +{ + return lwip_recvfrom(s, mem, len, 0, NULL, NULL); +} + +int +lwip_recv(int s, void *mem, size_t len, int flags) +{ + return lwip_recvfrom(s, mem, len, flags, NULL, NULL); +} + +int +lwip_send(int s, const void *data, size_t size, int flags) +{ + struct lwip_sock *sock; + err_t err; + u8_t write_flags; + size_t written; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d, data=%p, size=%"SZT_F", flags=0x%x)\n", + s, data, size, flags)); + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (sock->conn->type != NETCONN_TCP) { +#if (LWIP_UDP || LWIP_RAW) + return lwip_sendto(s, data, size, flags, NULL, 0); +#else /* (LWIP_UDP || LWIP_RAW) */ + sock_set_errno(sock, err_to_errno(ERR_ARG)); + return -1; +#endif /* (LWIP_UDP || LWIP_RAW) */ + } + + write_flags = NETCONN_COPY | + ((flags & MSG_MORE) ? NETCONN_MORE : 0) | + ((flags & MSG_DONTWAIT) ? NETCONN_DONTBLOCK : 0); + written = 0; + err = netconn_write_partly(sock->conn, data, size, write_flags, &written); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) err=%d written=%"SZT_F"\n", s, err, written)); + sock_set_errno(sock, err_to_errno(err)); + return (err == ERR_OK ? (int)written : -1); +} + +int +lwip_sendto(int s, const void *data, size_t size, int flags, + const struct sockaddr *to, socklen_t tolen) +{ + struct lwip_sock *sock; + err_t err; + u16_t short_size; + const struct sockaddr_in *to_in; + u16_t remote_port; +#if !LWIP_TCPIP_CORE_LOCKING + struct netbuf buf; +#endif + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (sock->conn->type == NETCONN_TCP) { +#if LWIP_TCP + return lwip_send(s, data, size, flags); +#else /* LWIP_TCP */ + LWIP_UNUSED_ARG(flags); + sock_set_errno(sock, err_to_errno(ERR_ARG)); + return -1; +#endif /* LWIP_TCP */ + } + + /* @todo: split into multiple sendto's? */ + LWIP_ASSERT("lwip_sendto: size must fit in u16_t", size <= 0xffff); + short_size = (u16_t)size; + LWIP_ERROR("lwip_sendto: invalid address", (((to == NULL) && (tolen == 0)) || + ((tolen == sizeof(struct sockaddr_in)) && + ((to->sa_family) == AF_INET) && ((((mem_ptr_t)to) % 4) == 0))), + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + to_in = (const struct sockaddr_in *)(void*)to; + +#if LWIP_TCPIP_CORE_LOCKING + /* Should only be consider like a sample or a simple way to experiment this option (no check of "to" field...) */ + { + struct pbuf* p; + ip_addr_t *remote_addr; + +#if LWIP_NETIF_TX_SINGLE_PBUF + p = pbuf_alloc(PBUF_TRANSPORT, short_size, PBUF_RAM); + if (p != NULL) { +#if LWIP_CHECKSUM_ON_COPY + u16_t chksum = 0; + if (sock->conn->type != NETCONN_RAW) { + chksum = LWIP_CHKSUM_COPY(p->payload, data, short_size); + } else +#endif /* LWIP_CHECKSUM_ON_COPY */ + MEMCPY(p->payload, data, size); +#else /* LWIP_NETIF_TX_SINGLE_PBUF */ + p = pbuf_alloc(PBUF_TRANSPORT, short_size, PBUF_REF); + if (p != NULL) { + p->payload = (void*)data; +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + + if (to_in != NULL) { + inet_addr_to_ipaddr_p(remote_addr, &to_in->sin_addr); + remote_port = ntohs(to_in->sin_port); + } else { + remote_addr = &sock->conn->pcb.ip->remote_ip; +#if LWIP_UDP + if (NETCONNTYPE_GROUP(sock->conn->type) == NETCONN_UDP) { + remote_port = sock->conn->pcb.udp->remote_port; + } else +#endif /* LWIP_UDP */ + { + remote_port = 0; + } + } + + LOCK_TCPIP_CORE(); + if (netconn_type(sock->conn) == NETCONN_RAW) { +#if LWIP_RAW + err = sock->conn->last_err = raw_sendto(sock->conn->pcb.raw, p, remote_addr); +#else /* LWIP_RAW */ + err = ERR_ARG; +#endif /* LWIP_RAW */ + } +#if LWIP_UDP && LWIP_RAW + else +#endif /* LWIP_UDP && LWIP_RAW */ + { +#if LWIP_UDP +#if LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF + err = sock->conn->last_err = udp_sendto_chksum(sock->conn->pcb.udp, p, + remote_addr, remote_port, 1, chksum); +#else /* LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF */ + err = sock->conn->last_err = udp_sendto(sock->conn->pcb.udp, p, + remote_addr, remote_port); +#endif /* LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF */ +#else /* LWIP_UDP */ + err = ERR_ARG; +#endif /* LWIP_UDP */ + } + UNLOCK_TCPIP_CORE(); + + pbuf_free(p); + } else { + err = ERR_MEM; + } + } +#else /* LWIP_TCPIP_CORE_LOCKING */ + /* initialize a buffer */ + buf.p = buf.ptr = NULL; +#if LWIP_CHECKSUM_ON_COPY + buf.flags = 0; +#endif /* LWIP_CHECKSUM_ON_COPY */ + if (to) { + inet_addr_to_ipaddr(&buf.addr, &to_in->sin_addr); + remote_port = ntohs(to_in->sin_port); + netbuf_fromport(&buf) = remote_port; + } else { + remote_port = 0; + ip_addr_set_any(&buf.addr); + netbuf_fromport(&buf) = 0; + } + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, short_size=%"U16_F", flags=0x%x to=", + s, data, short_size, flags)); + ip_addr_debug_print(SOCKETS_DEBUG, &buf.addr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port)); + + /* make the buffer point to the data that should be sent */ +#if LWIP_NETIF_TX_SINGLE_PBUF + /* Allocate a new netbuf and copy the data into it. */ + if (netbuf_alloc(&buf, short_size) == NULL) { + err = ERR_MEM; + } else { +#if LWIP_CHECKSUM_ON_COPY + if (sock->conn->type != NETCONN_RAW) { + u16_t chksum = LWIP_CHKSUM_COPY(buf.p->payload, data, short_size); + netbuf_set_chksum(&buf, chksum); + err = ERR_OK; + } else +#endif /* LWIP_CHECKSUM_ON_COPY */ + { + err = netbuf_take(&buf, data, short_size); + } + } +#else /* LWIP_NETIF_TX_SINGLE_PBUF */ + err = netbuf_ref(&buf, data, short_size); +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + if (err == ERR_OK) { + /* send the data */ + err = netconn_send(sock->conn, &buf); + } + + /* deallocated the buffer */ + netbuf_free(&buf); +#endif /* LWIP_TCPIP_CORE_LOCKING */ + sock_set_errno(sock, err_to_errno(err)); + return (err == ERR_OK ? short_size : -1); +} + +int +lwip_socket(int domain, int type, int protocol) +{ + struct netconn *conn; + int i; + + LWIP_UNUSED_ARG(domain); + + /* create a netconn */ + switch (type) { + case SOCK_RAW: + conn = netconn_new_with_proto_and_callback(NETCONN_RAW, (u8_t)protocol, event_callback); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ", + domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); + break; + case SOCK_DGRAM: + conn = netconn_new_with_callback( (protocol == IPPROTO_UDPLITE) ? + NETCONN_UDPLITE : NETCONN_UDP, event_callback); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_DGRAM, %d) = ", + domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); + break; + case SOCK_STREAM: + conn = netconn_new_with_callback(NETCONN_TCP, event_callback); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_STREAM, %d) = ", + domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); + if (conn != NULL) { + /* Prevent automatic window updates, we do this on our own! */ + netconn_set_noautorecved(conn, 1); + } + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%d, %d/UNKNOWN, %d) = -1\n", + domain, type, protocol)); + set_errno(EINVAL); + return -1; + } + + if (!conn) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("-1 / ENOBUFS (could not create netconn)\n")); + set_errno(ENOBUFS); + return -1; + } + + i = alloc_socket(conn, 0); + + if (i == -1) { + netconn_delete(conn); + set_errno(ENFILE); + return -1; + } + conn->socket = i; + LWIP_DEBUGF(SOCKETS_DEBUG, ("%d\n", i)); + set_errno(0); + return i; +} + +int +lwip_write(int s, const void *data, size_t size) +{ + return lwip_send(s, data, size, 0); +} + +/** + * Go through the readset and writeset lists and see which socket of the sockets + * set in the sets has events. On return, readset, writeset and exceptset have + * the sockets enabled that had events. + * + * exceptset is not used for now!!! + * + * @param maxfdp1 the highest socket index in the sets + * @param readset_in: set of sockets to check for read events + * @param writeset_in: set of sockets to check for write events + * @param exceptset_in: set of sockets to check for error events + * @param readset_out: set of sockets that had read events + * @param writeset_out: set of sockets that had write events + * @param exceptset_out: set os sockets that had error events + * @return number of sockets that had events (read/write/exception) (>= 0) + */ +static int +lwip_selscan(int maxfdp1, fd_set *readset_in, fd_set *writeset_in, fd_set *exceptset_in, + fd_set *readset_out, fd_set *writeset_out, fd_set *exceptset_out) +{ + int i, nready = 0; + fd_set lreadset, lwriteset, lexceptset; + struct lwip_sock *sock; + SYS_ARCH_DECL_PROTECT(lev); + + FD_ZERO(&lreadset); + FD_ZERO(&lwriteset); + FD_ZERO(&lexceptset); + + /* Go through each socket in each list to count number of sockets which + currently match */ + for(i = 0; i < maxfdp1; i++) { + void* lastdata = NULL; + s16_t rcvevent = 0; + u16_t sendevent = 0; + u16_t errevent = 0; + /* First get the socket's status (protected)... */ + SYS_ARCH_PROTECT(lev); + sock = tryget_socket(i); + if (sock != NULL) { + lastdata = sock->lastdata; + rcvevent = sock->rcvevent; + sendevent = sock->sendevent; + errevent = sock->errevent; + } + SYS_ARCH_UNPROTECT(lev); + /* ... then examine it: */ + /* See if netconn of this socket is ready for read */ + if (readset_in && FD_ISSET(i, readset_in) && ((lastdata != NULL) || (rcvevent > 0))) { + FD_SET(i, &lreadset); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for reading\n", i)); + nready++; + } + /* See if netconn of this socket is ready for write */ + if (writeset_in && FD_ISSET(i, writeset_in) && (sendevent != 0)) { + FD_SET(i, &lwriteset); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for writing\n", i)); + nready++; + } + /* See if netconn of this socket had an error */ + if (exceptset_in && FD_ISSET(i, exceptset_in) && (errevent != 0)) { + FD_SET(i, &lexceptset); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for exception\n", i)); + nready++; + } + } + /* copy local sets to the ones provided as arguments */ + *readset_out = lreadset; + *writeset_out = lwriteset; + *exceptset_out = lexceptset; + + LWIP_ASSERT("nready >= 0", nready >= 0); + return nready; +} + +/** + * Processing exceptset is not yet implemented. + */ +int +lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, + struct timeval *timeout) +{ + u32_t waitres = 0; + int nready; + fd_set lreadset, lwriteset, lexceptset; + u32_t msectimeout; + struct lwip_select_cb select_cb; + err_t err; + int i; + SYS_ARCH_DECL_PROTECT(lev); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select(%d, %p, %p, %p, tvsec=%"S32_F" tvusec=%"S32_F")\n", + maxfdp1, (void *)readset, (void *) writeset, (void *) exceptset, + timeout ? (s32_t)timeout->tv_sec : (s32_t)-1, + timeout ? (s32_t)timeout->tv_usec : (s32_t)-1)); + + /* Go through each socket in each list to count number of sockets which + currently match */ + nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset); + + /* If we don't have any current events, then suspend if we are supposed to */ + if (!nready) { + if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: no timeout, returning 0\n")); + /* This is OK as the local fdsets are empty and nready is zero, + or we would have returned earlier. */ + goto return_copy_fdsets; + } + + /* None ready: add our semaphore to list: + We don't actually need any dynamic memory. Our entry on the + list is only valid while we are in this function, so it's ok + to use local variables. */ + + select_cb.next = NULL; + select_cb.prev = NULL; + select_cb.readset = readset; + select_cb.writeset = writeset; + select_cb.exceptset = exceptset; + select_cb.sem_signalled = 0; + err = sys_sem_new(&select_cb.sem, 0); + if (err != ERR_OK) { + /* failed to create semaphore */ + set_errno(ENOMEM); + return -1; + } + + /* Protect the select_cb_list */ + SYS_ARCH_PROTECT(lev); + + /* Put this select_cb on top of list */ + select_cb.next = select_cb_list; + if (select_cb_list != NULL) { + select_cb_list->prev = &select_cb; + } + select_cb_list = &select_cb; + /* Increasing this counter tells even_callback that the list has changed. */ + select_cb_ctr++; + + /* Now we can safely unprotect */ + SYS_ARCH_UNPROTECT(lev); + + /* Increase select_waiting for each socket we are interested in */ + for(i = 0; i < maxfdp1; i++) { + if ((readset && FD_ISSET(i, readset)) || + (writeset && FD_ISSET(i, writeset)) || + (exceptset && FD_ISSET(i, exceptset))) { + struct lwip_sock *sock = tryget_socket(i); + LWIP_ASSERT("sock != NULL", sock != NULL); + SYS_ARCH_PROTECT(lev); + sock->select_waiting++; + LWIP_ASSERT("sock->select_waiting > 0", sock->select_waiting > 0); + SYS_ARCH_UNPROTECT(lev); + } + } + + /* Call lwip_selscan again: there could have been events between + the last scan (whithout us on the list) and putting us on the list! */ + nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset); + if (!nready) { + /* Still none ready, just wait to be woken */ + if (timeout == 0) { + /* Wait forever */ + msectimeout = 0; + } else { + msectimeout = ((timeout->tv_sec * 1000) + ((timeout->tv_usec + 500)/1000)); + if (msectimeout == 0) { + /* Wait 1ms at least (0 means wait forever) */ + msectimeout = 1; + } + } + + waitres = sys_arch_sem_wait(&select_cb.sem, msectimeout); + } + /* Increase select_waiting for each socket we are interested in */ + for(i = 0; i < maxfdp1; i++) { + if ((readset && FD_ISSET(i, readset)) || + (writeset && FD_ISSET(i, writeset)) || + (exceptset && FD_ISSET(i, exceptset))) { + struct lwip_sock *sock = tryget_socket(i); + LWIP_ASSERT("sock != NULL", sock != NULL); + SYS_ARCH_PROTECT(lev); + sock->select_waiting--; + LWIP_ASSERT("sock->select_waiting >= 0", sock->select_waiting >= 0); + SYS_ARCH_UNPROTECT(lev); + } + } + /* Take us off the list */ + SYS_ARCH_PROTECT(lev); + if (select_cb.next != NULL) { + select_cb.next->prev = select_cb.prev; + } + if (select_cb_list == &select_cb) { + LWIP_ASSERT("select_cb.prev == NULL", select_cb.prev == NULL); + select_cb_list = select_cb.next; + } else { + LWIP_ASSERT("select_cb.prev != NULL", select_cb.prev != NULL); + select_cb.prev->next = select_cb.next; + } + /* Increasing this counter tells even_callback that the list has changed. */ + select_cb_ctr++; + SYS_ARCH_UNPROTECT(lev); + + sys_sem_free(&select_cb.sem); + if (waitres == SYS_ARCH_TIMEOUT) { + /* Timeout */ + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n")); + /* This is OK as the local fdsets are empty and nready is zero, + or we would have returned earlier. */ + goto return_copy_fdsets; + } + + /* See what's set */ + nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset); + } + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready)); +return_copy_fdsets: + set_errno(0); + if (readset) { + *readset = lreadset; + } + if (writeset) { + *writeset = lwriteset; + } + if (exceptset) { + *exceptset = lexceptset; + } + + + return nready; +} + +/** + * Callback registered in the netconn layer for each socket-netconn. + * Processes recvevent (data available) and wakes up tasks waiting for select. + */ +static void +event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len) +{ + int s; + struct lwip_sock *sock; + struct lwip_select_cb *scb; + int last_select_cb_ctr; + SYS_ARCH_DECL_PROTECT(lev); + + LWIP_UNUSED_ARG(len); + + /* Get socket */ + if (conn) { + s = conn->socket; + if (s < 0) { + /* Data comes in right away after an accept, even though + * the server task might not have created a new socket yet. + * Just count down (or up) if that's the case and we + * will use the data later. Note that only receive events + * can happen before the new socket is set up. */ + SYS_ARCH_PROTECT(lev); + if (conn->socket < 0) { + if (evt == NETCONN_EVT_RCVPLUS) { + conn->socket--; + } + SYS_ARCH_UNPROTECT(lev); + return; + } + s = conn->socket; + SYS_ARCH_UNPROTECT(lev); + } + + sock = get_socket(s); + if (!sock) { + return; + } + } else { + return; + } + + SYS_ARCH_PROTECT(lev); + /* Set event as required */ + switch (evt) { + case NETCONN_EVT_RCVPLUS: + sock->rcvevent++; + break; + case NETCONN_EVT_RCVMINUS: + sock->rcvevent--; + break; + case NETCONN_EVT_SENDPLUS: + sock->sendevent = 1; + break; + case NETCONN_EVT_SENDMINUS: + sock->sendevent = 0; + break; + case NETCONN_EVT_ERROR: + sock->errevent = 1; + break; + default: + LWIP_ASSERT("unknown event", 0); + break; + } + + if (sock->select_waiting == 0) { + /* noone is waiting for this socket, no need to check select_cb_list */ + SYS_ARCH_UNPROTECT(lev); + return; + } + + /* Now decide if anyone is waiting for this socket */ + /* NOTE: This code goes through the select_cb_list list multiple times + ONLY IF a select was actually waiting. We go through the list the number + of waiting select calls + 1. This list is expected to be small. */ + + /* At this point, SYS_ARCH is still protected! */ +again: + for (scb = select_cb_list; scb != NULL; scb = scb->next) { + if (scb->sem_signalled == 0) { + /* semaphore not signalled yet */ + int do_signal = 0; + /* Test this select call for our socket */ + if (sock->rcvevent > 0) { + if (scb->readset && FD_ISSET(s, scb->readset)) { + do_signal = 1; + } + } + if (sock->sendevent != 0) { + if (!do_signal && scb->writeset && FD_ISSET(s, scb->writeset)) { + do_signal = 1; + } + } + if (sock->errevent != 0) { + if (!do_signal && scb->exceptset && FD_ISSET(s, scb->exceptset)) { + do_signal = 1; + } + } + if (do_signal) { + scb->sem_signalled = 1; + /* Don't call SYS_ARCH_UNPROTECT() before signaling the semaphore, as this might + lead to the select thread taking itself off the list, invalidagin the semaphore. */ + sys_sem_signal(&scb->sem); + } + } + /* unlock interrupts with each step */ + last_select_cb_ctr = select_cb_ctr; + SYS_ARCH_UNPROTECT(lev); + /* this makes sure interrupt protection time is short */ + SYS_ARCH_PROTECT(lev); + if (last_select_cb_ctr != select_cb_ctr) { + /* someone has changed select_cb_list, restart at the beginning */ + goto again; + } + } + SYS_ARCH_UNPROTECT(lev); +} + +/** + * Unimplemented: Close one end of a full-duplex connection. + * Currently, the full connection is closed. + */ +int +lwip_shutdown(int s, int how) +{ + struct lwip_sock *sock; + err_t err; + u8_t shut_rx = 0, shut_tx = 0; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_shutdown(%d, how=%d)\n", s, how)); + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (sock->conn != NULL) { + if (netconn_type(sock->conn) != NETCONN_TCP) { + sock_set_errno(sock, EOPNOTSUPP); + return EOPNOTSUPP; + } + } else { + sock_set_errno(sock, ENOTCONN); + return ENOTCONN; + } + + if (how == SHUT_RD) { + shut_rx = 1; + } else if (how == SHUT_WR) { + shut_tx = 1; + } else if(how == SHUT_RDWR) { + shut_rx = 1; + shut_tx = 1; + } else { + sock_set_errno(sock, EINVAL); + return EINVAL; + } + err = netconn_shutdown(sock->conn, shut_rx, shut_tx); + + sock_set_errno(sock, err_to_errno(err)); + return (err == ERR_OK ? 0 : -1); +} + +static int +lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local) +{ + struct lwip_sock *sock; + struct sockaddr_in sin; + ip_addr_t naddr; + + sock = get_socket(s); + if (!sock) { + return -1; + } + + memset(&sin, 0, sizeof(sin)); + sin.sin_len = sizeof(sin); + sin.sin_family = AF_INET; + + /* get the IP address and port */ + netconn_getaddr(sock->conn, &naddr, &sin.sin_port, local); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getaddrname(%d, addr=", s)); + ip_addr_debug_print(SOCKETS_DEBUG, &naddr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", sin.sin_port)); + + sin.sin_port = htons(sin.sin_port); + inet_addr_from_ipaddr(&sin.sin_addr, &naddr); + + if (*namelen > sizeof(sin)) { + *namelen = sizeof(sin); + } + + MEMCPY(name, &sin, *namelen); + sock_set_errno(sock, 0); + return 0; +} + +int +lwip_getpeername(int s, struct sockaddr *name, socklen_t *namelen) +{ + return lwip_getaddrname(s, name, namelen, 0); +} + +int +lwip_getsockname(int s, struct sockaddr *name, socklen_t *namelen) +{ + return lwip_getaddrname(s, name, namelen, 1); +} + +int +lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) +{ + err_t err = ERR_OK; + struct lwip_sock *sock = get_socket(s); + struct lwip_setgetsockopt_data data; + + if (!sock) { + return -1; + } + + if ((NULL == optval) || (NULL == optlen)) { + sock_set_errno(sock, EFAULT); + return -1; + } + + /* Do length and type checks for the various options first, to keep it readable. */ + switch (level) { + +/* Level: SOL_SOCKET */ + case SOL_SOCKET: + switch (optname) { + + case SO_ACCEPTCONN: + case SO_BROADCAST: + /* UNIMPL case SO_DEBUG: */ + /* UNIMPL case SO_DONTROUTE: */ + case SO_ERROR: + case SO_KEEPALIVE: + /* UNIMPL case SO_CONTIMEO: */ +#if LWIP_SO_SNDTIMEO + case SO_SNDTIMEO: +#endif /* LWIP_SO_SNDTIMEO */ +#if LWIP_SO_RCVTIMEO + case SO_RCVTIMEO: +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + case SO_RCVBUF: +#endif /* LWIP_SO_RCVBUF */ + /* UNIMPL case SO_OOBINLINE: */ + /* UNIMPL case SO_SNDBUF: */ + /* UNIMPL case SO_RCVLOWAT: */ + /* UNIMPL case SO_SNDLOWAT: */ +#if SO_REUSE + case SO_REUSEADDR: + case SO_REUSEPORT: +#endif /* SO_REUSE */ + case SO_TYPE: + /* UNIMPL case SO_USELOOPBACK: */ + if (*optlen < sizeof(int)) { + err = EINVAL; + } + break; + + case SO_NO_CHECK: + if (*optlen < sizeof(int)) { + err = EINVAL; + } +#if LWIP_UDP + if ((sock->conn->type != NETCONN_UDP) || + ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0)) { + /* this flag is only available for UDP, not for UDP lite */ + err = EAFNOSUPPORT; + } +#endif /* LWIP_UDP */ + break; + + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + } /* switch (optname) */ + break; + +/* Level: IPPROTO_IP */ + case IPPROTO_IP: + switch (optname) { + /* UNIMPL case IP_HDRINCL: */ + /* UNIMPL case IP_RCVDSTADDR: */ + /* UNIMPL case IP_RCVIF: */ + case IP_TTL: + case IP_TOS: + if (*optlen < sizeof(int)) { + err = EINVAL; + } + break; +#if LWIP_IGMP + case IP_MULTICAST_TTL: + if (*optlen < sizeof(u8_t)) { + err = EINVAL; + } + break; + case IP_MULTICAST_IF: + if (*optlen < sizeof(struct in_addr)) { + err = EINVAL; + } + break; + case IP_MULTICAST_LOOP: + if (*optlen < sizeof(u8_t)) { + err = EINVAL; + } + if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) { + err = EAFNOSUPPORT; + } + break; +#endif /* LWIP_IGMP */ + + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + } /* switch (optname) */ + break; + +#if LWIP_TCP +/* Level: IPPROTO_TCP */ + case IPPROTO_TCP: + if (*optlen < sizeof(int)) { + err = EINVAL; + break; + } + + /* If this is no TCP socket, ignore any options. */ + if (sock->conn->type != NETCONN_TCP) + return 0; + + switch (optname) { + case TCP_NODELAY: + case TCP_KEEPALIVE: +#if LWIP_TCP_KEEPALIVE + case TCP_KEEPIDLE: + case TCP_KEEPINTVL: + case TCP_KEEPCNT: +#endif /* LWIP_TCP_KEEPALIVE */ + break; + + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + } /* switch (optname) */ + break; +#endif /* LWIP_TCP */ +#if LWIP_UDP && LWIP_UDPLITE +/* Level: IPPROTO_UDPLITE */ + case IPPROTO_UDPLITE: + if (*optlen < sizeof(int)) { + err = EINVAL; + break; + } + + /* If this is no UDP lite socket, ignore any options. */ + if (sock->conn->type != NETCONN_UDPLITE) { + return 0; + } + + switch (optname) { + case UDPLITE_SEND_CSCOV: + case UDPLITE_RECV_CSCOV: + break; + + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + } /* switch (optname) */ + break; +#endif /* LWIP_UDP && LWIP_UDPLITE*/ +/* UNDEFINED LEVEL */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", + s, level, optname)); + err = ENOPROTOOPT; + } /* switch */ + + + if (err != ERR_OK) { + sock_set_errno(sock, err); + return -1; + } + + /* Now do the actual option processing */ + data.sock = sock; +#ifdef LWIP_DEBUG + data.s = s; +#endif /* LWIP_DEBUG */ + data.level = level; + data.optname = optname; + data.optval = optval; + data.optlen = optlen; + data.err = err; + tcpip_callback(lwip_getsockopt_internal, &data); + sys_arch_sem_wait(&sock->conn->op_completed, 0); + /* maybe lwip_getsockopt_internal has changed err */ + err = data.err; + + sock_set_errno(sock, err); + return err ? -1 : 0; +} + +static void +lwip_getsockopt_internal(void *arg) +{ + struct lwip_sock *sock; +#ifdef LWIP_DEBUG + int s; +#endif /* LWIP_DEBUG */ + int level, optname; + void *optval; + struct lwip_setgetsockopt_data *data; + + LWIP_ASSERT("arg != NULL", arg != NULL); + + data = (struct lwip_setgetsockopt_data*)arg; + sock = data->sock; +#ifdef LWIP_DEBUG + s = data->s; +#endif /* LWIP_DEBUG */ + level = data->level; + optname = data->optname; + optval = data->optval; + + switch (level) { + +/* Level: SOL_SOCKET */ + case SOL_SOCKET: + switch (optname) { + + /* The option flags */ + case SO_ACCEPTCONN: + case SO_BROADCAST: + /* UNIMPL case SO_DEBUG: */ + /* UNIMPL case SO_DONTROUTE: */ + case SO_KEEPALIVE: + /* UNIMPL case SO_OOBINCLUDE: */ +#if SO_REUSE + case SO_REUSEADDR: + case SO_REUSEPORT: +#endif /* SO_REUSE */ + /*case SO_USELOOPBACK: UNIMPL */ + *(int*)optval = ip_get_option(sock->conn->pcb.ip, optname); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, optname=0x%x, ..) = %s\n", + s, optname, (*(int*)optval?"on":"off"))); + break; + + case SO_TYPE: + switch (NETCONNTYPE_GROUP(sock->conn->type)) { + case NETCONN_RAW: + *(int*)optval = SOCK_RAW; + break; + case NETCONN_TCP: + *(int*)optval = SOCK_STREAM; + break; + case NETCONN_UDP: + *(int*)optval = SOCK_DGRAM; + break; + default: /* unrecognized socket type */ + *(int*)optval = sock->conn->type; + LWIP_DEBUGF(SOCKETS_DEBUG, + ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n", + s, *(int *)optval)); + } /* switch (sock->conn->type) */ + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n", + s, *(int *)optval)); + break; + + case SO_ERROR: + /* only overwrite ERR_OK or tempoary errors */ + if ((sock->err == 0) || (sock->err == EINPROGRESS)) { + sock_set_errno(sock, err_to_errno(sock->conn->last_err)); + } + *(int *)optval = sock->err; + sock->err = 0; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n", + s, *(int *)optval)); + break; + +#if LWIP_SO_SNDTIMEO + case SO_SNDTIMEO: + *(int *)optval = netconn_get_sendtimeout(sock->conn); + break; +#endif /* LWIP_SO_SNDTIMEO */ +#if LWIP_SO_RCVTIMEO + case SO_RCVTIMEO: + *(int *)optval = netconn_get_recvtimeout(sock->conn); + break; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + case SO_RCVBUF: + *(int *)optval = netconn_get_recvbufsize(sock->conn); + break; +#endif /* LWIP_SO_RCVBUF */ +#if LWIP_UDP + case SO_NO_CHECK: + *(int*)optval = (udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_NOCHKSUM) ? 1 : 0; + break; +#endif /* LWIP_UDP*/ + default: + LWIP_ASSERT("unhandled optname", 0); + break; + } /* switch (optname) */ + break; + +/* Level: IPPROTO_IP */ + case IPPROTO_IP: + switch (optname) { + case IP_TTL: + *(int*)optval = sock->conn->pcb.ip->ttl; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TTL) = %d\n", + s, *(int *)optval)); + break; + case IP_TOS: + *(int*)optval = sock->conn->pcb.ip->tos; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TOS) = %d\n", + s, *(int *)optval)); + break; +#if LWIP_IGMP + case IP_MULTICAST_TTL: + *(u8_t*)optval = sock->conn->pcb.ip->ttl; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_TTL) = %d\n", + s, *(int *)optval)); + break; + case IP_MULTICAST_IF: + inet_addr_from_ipaddr((struct in_addr*)optval, &sock->conn->pcb.udp->multicast_ip); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_IF) = 0x%"X32_F"\n", + s, *(u32_t *)optval)); + break; + case IP_MULTICAST_LOOP: + if ((sock->conn->pcb.udp->flags & UDP_FLAGS_MULTICAST_LOOP) != 0) { + *(u8_t*)optval = 1; + } else { + *(u8_t*)optval = 0; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_LOOP) = %d\n", + s, *(int *)optval)); + break; +#endif /* LWIP_IGMP */ + default: + LWIP_ASSERT("unhandled optname", 0); + break; + } /* switch (optname) */ + break; + +#if LWIP_TCP +/* Level: IPPROTO_TCP */ + case IPPROTO_TCP: + switch (optname) { + case TCP_NODELAY: + *(int*)optval = tcp_nagle_disabled(sock->conn->pcb.tcp); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n", + s, (*(int*)optval)?"on":"off") ); + break; + case TCP_KEEPALIVE: + *(int*)optval = (int)sock->conn->pcb.tcp->keep_idle; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPALIVE) = %d\n", + s, *(int *)optval)); + break; + +#if LWIP_TCP_KEEPALIVE + case TCP_KEEPIDLE: + *(int*)optval = (int)(sock->conn->pcb.tcp->keep_idle/1000); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPIDLE) = %d\n", + s, *(int *)optval)); + break; + case TCP_KEEPINTVL: + *(int*)optval = (int)(sock->conn->pcb.tcp->keep_intvl/1000); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPINTVL) = %d\n", + s, *(int *)optval)); + break; + case TCP_KEEPCNT: + *(int*)optval = (int)sock->conn->pcb.tcp->keep_cnt; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPCNT) = %d\n", + s, *(int *)optval)); + break; +#endif /* LWIP_TCP_KEEPALIVE */ + default: + LWIP_ASSERT("unhandled optname", 0); + break; + } /* switch (optname) */ + break; +#endif /* LWIP_TCP */ +#if LWIP_UDP && LWIP_UDPLITE + /* Level: IPPROTO_UDPLITE */ + case IPPROTO_UDPLITE: + switch (optname) { + case UDPLITE_SEND_CSCOV: + *(int*)optval = sock->conn->pcb.udp->chksum_len_tx; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) = %d\n", + s, (*(int*)optval)) ); + break; + case UDPLITE_RECV_CSCOV: + *(int*)optval = sock->conn->pcb.udp->chksum_len_rx; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) = %d\n", + s, (*(int*)optval)) ); + break; + default: + LWIP_ASSERT("unhandled optname", 0); + break; + } /* switch (optname) */ + break; +#endif /* LWIP_UDP */ + default: + LWIP_ASSERT("unhandled level", 0); + break; + } /* switch (level) */ + sys_sem_signal(&sock->conn->op_completed); +} + +int +lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) +{ + struct lwip_sock *sock = get_socket(s); + err_t err = ERR_OK; + struct lwip_setgetsockopt_data data; + + if (!sock) { + return -1; + } + + if (NULL == optval) { + sock_set_errno(sock, EFAULT); + return -1; + } + + /* Do length and type checks for the various options first, to keep it readable. */ + switch (level) { + +/* Level: SOL_SOCKET */ + case SOL_SOCKET: + switch (optname) { + + case SO_BROADCAST: + /* UNIMPL case SO_DEBUG: */ + /* UNIMPL case SO_DONTROUTE: */ + case SO_KEEPALIVE: + /* UNIMPL case case SO_CONTIMEO: */ +#if LWIP_SO_SNDTIMEO + case SO_SNDTIMEO: +#endif /* LWIP_SO_SNDTIMEO */ +#if LWIP_SO_RCVTIMEO + case SO_RCVTIMEO: +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + case SO_RCVBUF: +#endif /* LWIP_SO_RCVBUF */ + /* UNIMPL case SO_OOBINLINE: */ + /* UNIMPL case SO_SNDBUF: */ + /* UNIMPL case SO_RCVLOWAT: */ + /* UNIMPL case SO_SNDLOWAT: */ +#if SO_REUSE + case SO_REUSEADDR: + case SO_REUSEPORT: +#endif /* SO_REUSE */ + /* UNIMPL case SO_USELOOPBACK: */ + if (optlen < sizeof(int)) { + err = EINVAL; + } + break; + case SO_NO_CHECK: + if (optlen < sizeof(int)) { + err = EINVAL; + } +#if LWIP_UDP + if ((sock->conn->type != NETCONN_UDP) || + ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0)) { + /* this flag is only available for UDP, not for UDP lite */ + err = EAFNOSUPPORT; + } +#endif /* LWIP_UDP */ + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + } /* switch (optname) */ + break; + +/* Level: IPPROTO_IP */ + case IPPROTO_IP: + switch (optname) { + /* UNIMPL case IP_HDRINCL: */ + /* UNIMPL case IP_RCVDSTADDR: */ + /* UNIMPL case IP_RCVIF: */ + case IP_TTL: + case IP_TOS: + if (optlen < sizeof(int)) { + err = EINVAL; + } + break; +#if LWIP_IGMP + case IP_MULTICAST_TTL: + if (optlen < sizeof(u8_t)) { + err = EINVAL; + } + if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) { + err = EAFNOSUPPORT; + } + break; + case IP_MULTICAST_IF: + if (optlen < sizeof(struct in_addr)) { + err = EINVAL; + } + if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) { + err = EAFNOSUPPORT; + } + break; + case IP_MULTICAST_LOOP: + if (optlen < sizeof(u8_t)) { + err = EINVAL; + } + if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) { + err = EAFNOSUPPORT; + } + break; + case IP_ADD_MEMBERSHIP: + case IP_DROP_MEMBERSHIP: + if (optlen < sizeof(struct ip_mreq)) { + err = EINVAL; + } + if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) { + err = EAFNOSUPPORT; + } + break; +#endif /* LWIP_IGMP */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + } /* switch (optname) */ + break; + +#if LWIP_TCP +/* Level: IPPROTO_TCP */ + case IPPROTO_TCP: + if (optlen < sizeof(int)) { + err = EINVAL; + break; + } + + /* If this is no TCP socket, ignore any options. */ + if (sock->conn->type != NETCONN_TCP) + return 0; + + switch (optname) { + case TCP_NODELAY: + case TCP_KEEPALIVE: +#if LWIP_TCP_KEEPALIVE + case TCP_KEEPIDLE: + case TCP_KEEPINTVL: + case TCP_KEEPCNT: +#endif /* LWIP_TCP_KEEPALIVE */ + break; + + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + } /* switch (optname) */ + break; +#endif /* LWIP_TCP */ +#if LWIP_UDP && LWIP_UDPLITE +/* Level: IPPROTO_UDPLITE */ + case IPPROTO_UDPLITE: + if (optlen < sizeof(int)) { + err = EINVAL; + break; + } + + /* If this is no UDP lite socket, ignore any options. */ + if (sock->conn->type != NETCONN_UDPLITE) + return 0; + + switch (optname) { + case UDPLITE_SEND_CSCOV: + case UDPLITE_RECV_CSCOV: + break; + + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + } /* switch (optname) */ + break; +#endif /* LWIP_UDP && LWIP_UDPLITE */ +/* UNDEFINED LEVEL */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", + s, level, optname)); + err = ENOPROTOOPT; + } /* switch (level) */ + + + if (err != ERR_OK) { + sock_set_errno(sock, err); + return -1; + } + + + /* Now do the actual option processing */ + data.sock = sock; +#ifdef LWIP_DEBUG + data.s = s; +#endif /* LWIP_DEBUG */ + data.level = level; + data.optname = optname; + data.optval = (void*)optval; + data.optlen = &optlen; + data.err = err; + tcpip_callback(lwip_setsockopt_internal, &data); + sys_arch_sem_wait(&sock->conn->op_completed, 0); + /* maybe lwip_setsockopt_internal has changed err */ + err = data.err; + sock_set_errno(sock, err); + return err ? -1 : 0; +} + +static void +lwip_setsockopt_internal(void *arg) +{ + struct lwip_sock *sock; +#ifdef LWIP_DEBUG + int s; +#endif /* LWIP_DEBUG */ + int level, optname; + const void *optval; + struct lwip_setgetsockopt_data *data; + + LWIP_ASSERT("arg != NULL", arg != NULL); + + data = (struct lwip_setgetsockopt_data*)arg; + sock = data->sock; +#ifdef LWIP_DEBUG + s = data->s; +#endif /* LWIP_DEBUG */ + level = data->level; + optname = data->optname; + optval = data->optval; + + switch (level) { + +/* Level: SOL_SOCKET */ + case SOL_SOCKET: + switch (optname) { + + /* The option flags */ + case SO_BROADCAST: + /* UNIMPL case SO_DEBUG: */ + /* UNIMPL case SO_DONTROUTE: */ + case SO_KEEPALIVE: + /* UNIMPL case SO_OOBINCLUDE: */ +#if SO_REUSE + case SO_REUSEADDR: + case SO_REUSEPORT: +#endif /* SO_REUSE */ + /* UNIMPL case SO_USELOOPBACK: */ + if (*(int*)optval) { + ip_set_option(sock->conn->pcb.ip, optname); + } else { + ip_reset_option(sock->conn->pcb.ip, optname); + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n", + s, optname, (*(int*)optval?"on":"off"))); + break; +#if LWIP_SO_SNDTIMEO + case SO_SNDTIMEO: + netconn_set_sendtimeout(sock->conn, (s32_t)*(int*)optval); + break; +#endif /* LWIP_SO_SNDTIMEO */ +#if LWIP_SO_RCVTIMEO + case SO_RCVTIMEO: + netconn_set_recvtimeout(sock->conn, *(int*)optval); + break; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + case SO_RCVBUF: + netconn_set_recvbufsize(sock->conn, *(int*)optval); + break; +#endif /* LWIP_SO_RCVBUF */ +#if LWIP_UDP + case SO_NO_CHECK: + if (*(int*)optval) { + udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_NOCHKSUM); + } else { + udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_NOCHKSUM); + } + break; +#endif /* LWIP_UDP */ + default: + LWIP_ASSERT("unhandled optname", 0); + break; + } /* switch (optname) */ + break; + +/* Level: IPPROTO_IP */ + case IPPROTO_IP: + switch (optname) { + case IP_TTL: + sock->conn->pcb.ip->ttl = (u8_t)(*(int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TTL, ..) -> %d\n", + s, sock->conn->pcb.ip->ttl)); + break; + case IP_TOS: + sock->conn->pcb.ip->tos = (u8_t)(*(int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TOS, ..)-> %d\n", + s, sock->conn->pcb.ip->tos)); + break; +#if LWIP_IGMP + case IP_MULTICAST_TTL: + sock->conn->pcb.udp->ttl = (u8_t)(*(u8_t*)optval); + break; + case IP_MULTICAST_IF: + inet_addr_to_ipaddr(&sock->conn->pcb.udp->multicast_ip, (struct in_addr*)optval); + break; + case IP_MULTICAST_LOOP: + if (*(u8_t*)optval) { + udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_MULTICAST_LOOP); + } else { + udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_MULTICAST_LOOP); + } + break; + case IP_ADD_MEMBERSHIP: + case IP_DROP_MEMBERSHIP: + { + /* If this is a TCP or a RAW socket, ignore these options. */ + struct ip_mreq *imr = (struct ip_mreq *)optval; + ip_addr_t if_addr; + ip_addr_t multi_addr; + inet_addr_to_ipaddr(&if_addr, &imr->imr_interface); + inet_addr_to_ipaddr(&multi_addr, &imr->imr_multiaddr); + if(optname == IP_ADD_MEMBERSHIP){ + data->err = igmp_joingroup(&if_addr, &multi_addr); + } else { + data->err = igmp_leavegroup(&if_addr, &multi_addr); + } + if(data->err != ERR_OK) { + data->err = EADDRNOTAVAIL; + } + } + break; +#endif /* LWIP_IGMP */ + default: + LWIP_ASSERT("unhandled optname", 0); + break; + } /* switch (optname) */ + break; + +#if LWIP_TCP +/* Level: IPPROTO_TCP */ + case IPPROTO_TCP: + switch (optname) { + case TCP_NODELAY: + if (*(int*)optval) { + tcp_nagle_disable(sock->conn->pcb.tcp); + } else { + tcp_nagle_enable(sock->conn->pcb.tcp); + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n", + s, (*(int *)optval)?"on":"off") ); + break; + case TCP_KEEPALIVE: + sock->conn->pcb.tcp->keep_idle = (u32_t)(*(int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %"U32_F"\n", + s, sock->conn->pcb.tcp->keep_idle)); + break; + +#if LWIP_TCP_KEEPALIVE + case TCP_KEEPIDLE: + sock->conn->pcb.tcp->keep_idle = 1000*(u32_t)(*(int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) -> %"U32_F"\n", + s, sock->conn->pcb.tcp->keep_idle)); + break; + case TCP_KEEPINTVL: + sock->conn->pcb.tcp->keep_intvl = 1000*(u32_t)(*(int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) -> %"U32_F"\n", + s, sock->conn->pcb.tcp->keep_intvl)); + break; + case TCP_KEEPCNT: + sock->conn->pcb.tcp->keep_cnt = (u32_t)(*(int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) -> %"U32_F"\n", + s, sock->conn->pcb.tcp->keep_cnt)); + break; +#endif /* LWIP_TCP_KEEPALIVE */ + default: + LWIP_ASSERT("unhandled optname", 0); + break; + } /* switch (optname) */ + break; +#endif /* LWIP_TCP*/ +#if LWIP_UDP && LWIP_UDPLITE + /* Level: IPPROTO_UDPLITE */ + case IPPROTO_UDPLITE: + switch (optname) { + case UDPLITE_SEND_CSCOV: + if ((*(int*)optval != 0) && ((*(int*)optval < 8) || (*(int*)optval > 0xffff))) { + /* don't allow illegal values! */ + sock->conn->pcb.udp->chksum_len_tx = 8; + } else { + sock->conn->pcb.udp->chksum_len_tx = (u16_t)*(int*)optval; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) -> %d\n", + s, (*(int*)optval)) ); + break; + case UDPLITE_RECV_CSCOV: + if ((*(int*)optval != 0) && ((*(int*)optval < 8) || (*(int*)optval > 0xffff))) { + /* don't allow illegal values! */ + sock->conn->pcb.udp->chksum_len_rx = 8; + } else { + sock->conn->pcb.udp->chksum_len_rx = (u16_t)*(int*)optval; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) -> %d\n", + s, (*(int*)optval)) ); + break; + default: + LWIP_ASSERT("unhandled optname", 0); + break; + } /* switch (optname) */ + break; +#endif /* LWIP_UDP */ + default: + LWIP_ASSERT("unhandled level", 0); + break; + } /* switch (level) */ + sys_sem_signal(&sock->conn->op_completed); +} + +int +lwip_ioctl(int s, long cmd, void *argp) +{ + struct lwip_sock *sock = get_socket(s); + u8_t val; +#if LWIP_SO_RCVBUF + u16_t buflen = 0; + s16_t recv_avail; +#endif /* LWIP_SO_RCVBUF */ + + if (!sock) { + return -1; + } + + switch (cmd) { +#if LWIP_SO_RCVBUF + case FIONREAD: + if (!argp) { + sock_set_errno(sock, EINVAL); + return -1; + } + + SYS_ARCH_GET(sock->conn->recv_avail, recv_avail); + if (recv_avail < 0) { + recv_avail = 0; + } + *((u16_t*)argp) = (u16_t)recv_avail; + + /* Check if there is data left from the last recv operation. /maq 041215 */ + if (sock->lastdata) { + struct pbuf *p = (struct pbuf *)sock->lastdata; + if (netconn_type(sock->conn) != NETCONN_TCP) { + p = ((struct netbuf *)p)->p; + } + buflen = p->tot_len; + buflen -= sock->lastoffset; + + *((u16_t*)argp) += buflen; + } + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %"U16_F"\n", s, argp, *((u16_t*)argp))); + sock_set_errno(sock, 0); + return 0; +#endif /* LWIP_SO_RCVBUF */ + + case FIONBIO: + val = 0; + if (argp && *(u32_t*)argp) { + val = 1; + } + netconn_set_nonblocking(sock->conn, val); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, val)); + sock_set_errno(sock, 0); + return 0; + + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s, cmd, argp)); + sock_set_errno(sock, ENOSYS); /* not yet implemented */ + return -1; + } /* switch (cmd) */ +} + +/** A minimal implementation of fcntl. + * Currently only the commands F_GETFL and F_SETFL are implemented. + * Only the flag O_NONBLOCK is implemented. + */ +int +lwip_fcntl(int s, int cmd, int val) +{ + struct lwip_sock *sock = get_socket(s); + int ret = -1; + + if (!sock || !sock->conn) { + return -1; + } + + switch (cmd) { + case F_GETFL: + ret = netconn_is_nonblocking(sock->conn) ? O_NONBLOCK : 0; + break; + case F_SETFL: + if ((val & ~O_NONBLOCK) == 0) { + /* only O_NONBLOCK, all other bits are zero */ + netconn_set_nonblocking(sock->conn, val & O_NONBLOCK); + ret = 0; + } + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_fcntl(%d, UNIMPL: %d, %d)\n", s, cmd, val)); + break; + } + return ret; +} + +/************************************************************** +* Added by Realtek Begin * +**************************************************************/ +int lwip_allocsocketsd() +{ + struct netconn *conn; + int i; + + /*new a netconn due to avoid some socket->conn check*/ + conn = netconn_new_with_proto_and_callback(NETCONN_RAW, 0, NULL); + if (!conn) { + printf("\r\n could not create netconn"); + return -1; + } + + /*alloc a socket*/ + i = alloc_socket(conn, 1); + if (i == -1) { + netconn_delete(conn); + printf("\r\n alloc socket fail!"); + return -1; + } + + conn->socket = i; + return i; +} +void lwip_setsockrcvevent(int fd, int rcvevent) +{ + struct lwip_sock *sock = get_socket(fd); + + if(sock){ + if(rcvevent) + sock->rcvevent = 1; + else + sock->rcvevent = 0; + } +} +void lwip_selectevindicate(int fd) +{ + struct lwip_select_cb *scb; + struct lwip_sock *sock; + + sock = get_socket(fd); + SYS_ARCH_DECL_PROTECT(lev); + while (1) { + SYS_ARCH_PROTECT(lev); + for (scb = select_cb_list; scb; scb = scb->next) { + if (scb->sem_signalled == 0) { + /* Test this select call for our socket */ + if (scb->readset && FD_ISSET(fd, scb->readset)) + if (sock->rcvevent > 0) + break; + if (scb->writeset && FD_ISSET(fd, scb->writeset)) + if (sock->sendevent) + break; + } + } + if (scb) { + scb->sem_signalled = 1; + sys_sem_signal(&scb->sem); + SYS_ARCH_UNPROTECT(lev); + } else { + SYS_ARCH_UNPROTECT(lev); + break; + } + } +} +/************************************************************** +* Added by Realtek end * +**************************************************************/ + +#endif /* LWIP_SOCKET */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/api/tcpip.c b/component/common/network/lwip/lwip_v1.4.1/src/api/tcpip.c new file mode 100644 index 0000000..18d5f67 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/api/tcpip.c @@ -0,0 +1,511 @@ +/** + * @file + * Sequential API Main thread module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if !NO_SYS /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/sys.h" +#include "lwip/memp.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/tcpip.h" +#include "lwip/init.h" +#include "netif/etharp.h" +#include "netif/ppp_oe.h" + +/* global variables */ +static tcpip_init_done_fn tcpip_init_done; +static void *tcpip_init_done_arg; +static sys_mbox_t mbox; + +#if LWIP_TCPIP_CORE_LOCKING +/** The global semaphore to lock the stack. */ +sys_mutex_t lock_tcpip_core; +#endif /* LWIP_TCPIP_CORE_LOCKING */ + + +/** + * The main lwIP thread. This thread has exclusive access to lwIP core functions + * (unless access to them is not locked). Other threads communicate with this + * thread using message boxes. + * + * It also starts all the timers to make sure they are running in the right + * thread context. + * + * @param arg unused argument + */ +static void +tcpip_thread(void *arg) +{ + struct tcpip_msg *msg; + LWIP_UNUSED_ARG(arg); + + if (tcpip_init_done != NULL) { + tcpip_init_done(tcpip_init_done_arg); + } + + LOCK_TCPIP_CORE(); + while (1) { /* MAIN Loop */ + UNLOCK_TCPIP_CORE(); + LWIP_TCPIP_THREAD_ALIVE(); + /* wait for a message, timeouts are processed while waiting */ + sys_timeouts_mbox_fetch(&mbox, (void **)&msg); + LOCK_TCPIP_CORE(); + switch (msg->type) { +#if LWIP_NETCONN + case TCPIP_MSG_API: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg)); + msg->msg.apimsg->function(&(msg->msg.apimsg->msg)); + break; +#endif /* LWIP_NETCONN */ + +#if !LWIP_TCPIP_CORE_LOCKING_INPUT + case TCPIP_MSG_INPKT: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: PACKET %p\n", (void *)msg)); +#if LWIP_ETHERNET + if (msg->msg.inp.netif->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) { + ethernet_input(msg->msg.inp.p, msg->msg.inp.netif); + } else +#endif /* LWIP_ETHERNET */ + { + ip_input(msg->msg.inp.p, msg->msg.inp.netif); + } + memp_free(MEMP_TCPIP_MSG_INPKT, msg); + break; +#endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */ + +#if LWIP_NETIF_API + case TCPIP_MSG_NETIFAPI: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: Netif API message %p\n", (void *)msg)); + msg->msg.netifapimsg->function(&(msg->msg.netifapimsg->msg)); + break; +#endif /* LWIP_NETIF_API */ + +#if LWIP_TCPIP_TIMEOUT + case TCPIP_MSG_TIMEOUT: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: TIMEOUT %p\n", (void *)msg)); + sys_timeout(msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg); + memp_free(MEMP_TCPIP_MSG_API, msg); + break; + case TCPIP_MSG_UNTIMEOUT: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: UNTIMEOUT %p\n", (void *)msg)); + sys_untimeout(msg->msg.tmo.h, msg->msg.tmo.arg); + memp_free(MEMP_TCPIP_MSG_API, msg); + break; +#endif /* LWIP_TCPIP_TIMEOUT */ + + case TCPIP_MSG_CALLBACK: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg)); + msg->msg.cb.function(msg->msg.cb.ctx); + memp_free(MEMP_TCPIP_MSG_API, msg); + break; + + case TCPIP_MSG_CALLBACK_STATIC: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK_STATIC %p\n", (void *)msg)); + msg->msg.cb.function(msg->msg.cb.ctx); + break; + + default: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: %d\n", msg->type)); + LWIP_ASSERT("tcpip_thread: invalid message", 0); + break; + } + } +} + +/** + * Pass a received packet to tcpip_thread for input processing + * + * @param p the received packet, p->payload pointing to the Ethernet header or + * to an IP header (if inp doesn't have NETIF_FLAG_ETHARP or + * NETIF_FLAG_ETHERNET flags) + * @param inp the network interface on which the packet was received + */ +err_t +tcpip_input(struct pbuf *p, struct netif *inp) +{ +#if LWIP_TCPIP_CORE_LOCKING_INPUT + err_t ret; + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_input: PACKET %p/%p\n", (void *)p, (void *)inp)); + LOCK_TCPIP_CORE(); +#if LWIP_ETHERNET + if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) { + ret = ethernet_input(p, inp); + } else +#endif /* LWIP_ETHERNET */ + { + ret = ip_input(p, inp); + } + UNLOCK_TCPIP_CORE(); + return ret; +#else /* LWIP_TCPIP_CORE_LOCKING_INPUT */ + struct tcpip_msg *msg; + + if (!sys_mbox_valid(&mbox)) { + return ERR_VAL; + } + msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_INPKT); + if (msg == NULL) { + return ERR_MEM; + } + + msg->type = TCPIP_MSG_INPKT; + msg->msg.inp.p = p; + msg->msg.inp.netif = inp; + if (sys_mbox_trypost(&mbox, msg) != ERR_OK) { + memp_free(MEMP_TCPIP_MSG_INPKT, msg); + return ERR_MEM; + } + return ERR_OK; +#endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */ +} + +/** + * Call a specific function in the thread context of + * tcpip_thread for easy access synchronization. + * A function called in that way may access lwIP core code + * without fearing concurrent access. + * + * @param f the function to call + * @param ctx parameter passed to f + * @param block 1 to block until the request is posted, 0 to non-blocking mode + * @return ERR_OK if the function was called, another err_t if not + */ +err_t +tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block) +{ + struct tcpip_msg *msg; + + if (sys_mbox_valid(&mbox)) { + msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); + if (msg == NULL) { + return ERR_MEM; + } + + msg->type = TCPIP_MSG_CALLBACK; + msg->msg.cb.function = function; + msg->msg.cb.ctx = ctx; + if (block) { + sys_mbox_post(&mbox, msg); + } else { + if (sys_mbox_trypost(&mbox, msg) != ERR_OK) { + memp_free(MEMP_TCPIP_MSG_API, msg); + return ERR_MEM; + } + } + return ERR_OK; + } + return ERR_VAL; +} + +#if LWIP_TCPIP_TIMEOUT +/** + * call sys_timeout in tcpip_thread + * + * @param msec time in milliseconds for timeout + * @param h function to be called on timeout + * @param arg argument to pass to timeout function h + * @return ERR_MEM on memory error, ERR_OK otherwise + */ +err_t +tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg) +{ + struct tcpip_msg *msg; + + if (sys_mbox_valid(&mbox)) { + msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); + if (msg == NULL) { + return ERR_MEM; + } + + msg->type = TCPIP_MSG_TIMEOUT; + msg->msg.tmo.msecs = msecs; + msg->msg.tmo.h = h; + msg->msg.tmo.arg = arg; + sys_mbox_post(&mbox, msg); + return ERR_OK; + } + return ERR_VAL; +} + +/** + * call sys_untimeout in tcpip_thread + * + * @param msec time in milliseconds for timeout + * @param h function to be called on timeout + * @param arg argument to pass to timeout function h + * @return ERR_MEM on memory error, ERR_OK otherwise + */ +err_t +tcpip_untimeout(sys_timeout_handler h, void *arg) +{ + struct tcpip_msg *msg; + + if (sys_mbox_valid(&mbox)) { + msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); + if (msg == NULL) { + return ERR_MEM; + } + + msg->type = TCPIP_MSG_UNTIMEOUT; + msg->msg.tmo.h = h; + msg->msg.tmo.arg = arg; + sys_mbox_post(&mbox, msg); + return ERR_OK; + } + return ERR_VAL; +} +#endif /* LWIP_TCPIP_TIMEOUT */ + +#if LWIP_NETCONN +/** + * Call the lower part of a netconn_* function + * This function is then running in the thread context + * of tcpip_thread and has exclusive access to lwIP core code. + * + * @param apimsg a struct containing the function to call and its parameters + * @return ERR_OK if the function was called, another err_t if not + */ +err_t +tcpip_apimsg(struct api_msg *apimsg) +{ + struct tcpip_msg msg; +#ifdef LWIP_DEBUG + /* catch functions that don't set err */ + apimsg->msg.err = ERR_VAL; +#endif + + if (sys_mbox_valid(&mbox)) { + msg.type = TCPIP_MSG_API; + msg.msg.apimsg = apimsg; + sys_mbox_post(&mbox, &msg); + sys_arch_sem_wait(&apimsg->msg.conn->op_completed, 0); + return apimsg->msg.err; + } + return ERR_VAL; +} + +#if LWIP_TCPIP_CORE_LOCKING +/** + * Call the lower part of a netconn_* function + * This function has exclusive access to lwIP core code by locking it + * before the function is called. + * + * @param apimsg a struct containing the function to call and its parameters + * @return ERR_OK (only for compatibility fo tcpip_apimsg()) + */ +err_t +tcpip_apimsg_lock(struct api_msg *apimsg) +{ +#ifdef LWIP_DEBUG + /* catch functions that don't set err */ + apimsg->msg.err = ERR_VAL; +#endif + + LOCK_TCPIP_CORE(); + apimsg->function(&(apimsg->msg)); + UNLOCK_TCPIP_CORE(); + return apimsg->msg.err; + +} +#endif /* LWIP_TCPIP_CORE_LOCKING */ +#endif /* LWIP_NETCONN */ + +#if LWIP_NETIF_API +#if !LWIP_TCPIP_CORE_LOCKING +/** + * Much like tcpip_apimsg, but calls the lower part of a netifapi_* + * function. + * + * @param netifapimsg a struct containing the function to call and its parameters + * @return error code given back by the function that was called + */ +err_t +tcpip_netifapi(struct netifapi_msg* netifapimsg) +{ + struct tcpip_msg msg; + + if (sys_mbox_valid(&mbox)) { + err_t err = sys_sem_new(&netifapimsg->msg.sem, 0); + if (err != ERR_OK) { + netifapimsg->msg.err = err; + return err; + } + + msg.type = TCPIP_MSG_NETIFAPI; + msg.msg.netifapimsg = netifapimsg; + sys_mbox_post(&mbox, &msg); + sys_sem_wait(&netifapimsg->msg.sem); + sys_sem_free(&netifapimsg->msg.sem); + return netifapimsg->msg.err; + } + return ERR_VAL; +} +#else /* !LWIP_TCPIP_CORE_LOCKING */ +/** + * Call the lower part of a netifapi_* function + * This function has exclusive access to lwIP core code by locking it + * before the function is called. + * + * @param netifapimsg a struct containing the function to call and its parameters + * @return ERR_OK (only for compatibility fo tcpip_netifapi()) + */ +err_t +tcpip_netifapi_lock(struct netifapi_msg* netifapimsg) +{ + LOCK_TCPIP_CORE(); + netifapimsg->function(&(netifapimsg->msg)); + UNLOCK_TCPIP_CORE(); + return netifapimsg->msg.err; +} +#endif /* !LWIP_TCPIP_CORE_LOCKING */ +#endif /* LWIP_NETIF_API */ + +/** + * Allocate a structure for a static callback message and initialize it. + * This is intended to be used to send "static" messages from interrupt context. + * + * @param function the function to call + * @param ctx parameter passed to function + * @return a struct pointer to pass to tcpip_trycallback(). + */ +struct tcpip_callback_msg* tcpip_callbackmsg_new(tcpip_callback_fn function, void *ctx) +{ + struct tcpip_msg *msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); + if (msg == NULL) { + return NULL; + } + msg->type = TCPIP_MSG_CALLBACK_STATIC; + msg->msg.cb.function = function; + msg->msg.cb.ctx = ctx; + return (struct tcpip_callback_msg*)msg; +} + +/** + * Free a callback message allocated by tcpip_callbackmsg_new(). + * + * @param msg the message to free + */ +void tcpip_callbackmsg_delete(struct tcpip_callback_msg* msg) +{ + memp_free(MEMP_TCPIP_MSG_API, msg); +} + +/** + * Try to post a callback-message to the tcpip_thread mbox + * This is intended to be used to send "static" messages from interrupt context. + * + * @param msg pointer to the message to post + * @return sys_mbox_trypost() return code + */ +err_t +tcpip_trycallback(struct tcpip_callback_msg* msg) +{ + if (!sys_mbox_valid(&mbox)) { + return ERR_VAL; + } + return sys_mbox_trypost(&mbox, msg); +} + +/** + * Initialize this module: + * - initialize all sub modules + * - start the tcpip_thread + * + * @param initfunc a function to call when tcpip_thread is running and finished initializing + * @param arg argument to pass to initfunc + */ +void +tcpip_init(tcpip_init_done_fn initfunc, void *arg) +{ + lwip_init(); + + tcpip_init_done = initfunc; + tcpip_init_done_arg = arg; + if(sys_mbox_new(&mbox, TCPIP_MBOX_SIZE) != ERR_OK) { + LWIP_ASSERT("failed to create tcpip_thread mbox", 0); + } +#if LWIP_TCPIP_CORE_LOCKING + if(sys_mutex_new(&lock_tcpip_core) != ERR_OK) { + LWIP_ASSERT("failed to create lock_tcpip_core", 0); + } +#endif /* LWIP_TCPIP_CORE_LOCKING */ + + sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO); +} + +/** + * Simple callback function used with tcpip_callback to free a pbuf + * (pbuf_free has a wrong signature for tcpip_callback) + * + * @param p The pbuf (chain) to be dereferenced. + */ +static void +pbuf_free_int(void *p) +{ + struct pbuf *q = (struct pbuf *)p; + pbuf_free(q); +} + +/** + * A simple wrapper function that allows you to free a pbuf from interrupt context. + * + * @param p The pbuf (chain) to be dereferenced. + * @return ERR_OK if callback could be enqueued, an err_t if not + */ +err_t +pbuf_free_callback(struct pbuf *p) +{ + return tcpip_callback_with_block(pbuf_free_int, p, 0); +} + +/** + * A simple wrapper function that allows you to free heap memory from + * interrupt context. + * + * @param m the heap memory to free + * @return ERR_OK if callback could be enqueued, an err_t if not + */ +err_t +mem_free_callback(void *m) +{ + return tcpip_callback_with_block(mem_free, m, 0); +} + +#endif /* !NO_SYS */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/core/def.c b/component/common/network/lwip/lwip_v1.4.1/src/core/def.c new file mode 100644 index 0000000..352b552 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/core/def.c @@ -0,0 +1,108 @@ +/** + * @file + * Common functions used throughout the stack. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Simon Goldschmidt + * + */ + +#include "lwip/opt.h" +#include "lwip/def.h" + +/** + * These are reference implementations of the byte swapping functions. + * Again with the aim of being simple, correct and fully portable. + * Byte swapping is the second thing you would want to optimize. You will + * need to port it to your architecture and in your cc.h: + * + * #define LWIP_PLATFORM_BYTESWAP 1 + * #define LWIP_PLATFORM_HTONS(x) + * #define LWIP_PLATFORM_HTONL(x) + * + * Note ntohs() and ntohl() are merely references to the htonx counterparts. + */ + +#if (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN) + +/** + * Convert an u16_t from host- to network byte order. + * + * @param n u16_t in host byte order + * @return n in network byte order + */ +u16_t +lwip_htons(u16_t n) +{ + return ((n & 0xff) << 8) | ((n & 0xff00) >> 8); +} + +/** + * Convert an u16_t from network- to host byte order. + * + * @param n u16_t in network byte order + * @return n in host byte order + */ +u16_t +lwip_ntohs(u16_t n) +{ + return lwip_htons(n); +} + +/** + * Convert an u32_t from host- to network byte order. + * + * @param n u32_t in host byte order + * @return n in network byte order + */ +u32_t +lwip_htonl(u32_t n) +{ + return ((n & 0xff) << 24) | + ((n & 0xff00) << 8) | + ((n & 0xff0000UL) >> 8) | + ((n & 0xff000000UL) >> 24); +} + +/** + * Convert an u32_t from network- to host byte order. + * + * @param n u32_t in network byte order + * @return n in host byte order + */ +u32_t +lwip_ntohl(u32_t n) +{ + return lwip_htonl(n); +} + +#endif /* (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN) */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/core/dhcp.c b/component/common/network/lwip/lwip_v1.4.1/src/core/dhcp.c new file mode 100644 index 0000000..d51bd03 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/core/dhcp.c @@ -0,0 +1,1827 @@ +/** + * @file + * Dynamic Host Configuration Protocol client + * + */ + +/* + * + * Copyright (c) 2001-2004 Leon Woestenberg + * Copyright (c) 2001-2004 Axon Digital Design B.V., The Netherlands. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is a contribution to the lwIP TCP/IP stack. + * The Swedish Institute of Computer Science and Adam Dunkels + * are specifically granted permission to redistribute this + * source code. + * + * Author: Leon Woestenberg + * + * This is a DHCP client for the lwIP TCP/IP stack. It aims to conform + * with RFC 2131 and RFC 2132. + * + * TODO: + * - Support for interfaces other than Ethernet (SLIP, PPP, ...) + * + * Please coordinate changes and requests with Leon Woestenberg + * + * + * Integration with your code: + * + * In lwip/dhcp.h + * #define DHCP_COARSE_TIMER_SECS (recommended 60 which is a minute) + * #define DHCP_FINE_TIMER_MSECS (recommended 500 which equals TCP coarse timer) + * + * Then have your application call dhcp_coarse_tmr() and + * dhcp_fine_tmr() on the defined intervals. + * + * dhcp_start(struct netif *netif); + * starts a DHCP client instance which configures the interface by + * obtaining an IP address lease and maintaining it. + * + * Use dhcp_release(netif) to end the lease and use dhcp_stop(netif) + * to remove the DHCP client. + * + */ + +#include "lwip/opt.h" + +#if LWIP_DHCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/stats.h" +#include "lwip/mem.h" +#include "lwip/udp.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/def.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" +#include "lwip/dns.h" +#include "netif/etharp.h" + +#include + +/** DHCP_CREATE_RAND_XID: if this is set to 1, the xid is created using + * LWIP_RAND() (this overrides DHCP_GLOBAL_XID) + */ +#ifndef DHCP_CREATE_RAND_XID +#define DHCP_CREATE_RAND_XID 1 +#endif + +/** Default for DHCP_GLOBAL_XID is 0xABCD0000 + * This can be changed by defining DHCP_GLOBAL_XID and DHCP_GLOBAL_XID_HEADER, e.g. + * #define DHCP_GLOBAL_XID_HEADER "stdlib.h" + * #define DHCP_GLOBAL_XID rand() + */ +#ifdef DHCP_GLOBAL_XID_HEADER +#include DHCP_GLOBAL_XID_HEADER /* include optional starting XID generation prototypes */ +#endif + +/** DHCP_OPTION_MAX_MSG_SIZE is set to the MTU + * MTU is checked to be big enough in dhcp_start */ +#define DHCP_MAX_MSG_LEN(netif) (netif->mtu) +#define DHCP_MAX_MSG_LEN_MIN_REQUIRED 576 +/** Minimum length for reply before packet is parsed */ +#define DHCP_MIN_REPLY_LEN 44 + +#define REBOOT_TRIES 2 + +/** Option handling: options are parsed in dhcp_parse_reply + * and saved in an array where other functions can load them from. + * This might be moved into the struct dhcp (not necessarily since + * lwIP is single-threaded and the array is only used while in recv + * callback). */ +#define DHCP_OPTION_IDX_OVERLOAD 0 +#define DHCP_OPTION_IDX_MSG_TYPE 1 +#define DHCP_OPTION_IDX_SERVER_ID 2 +#define DHCP_OPTION_IDX_LEASE_TIME 3 +#define DHCP_OPTION_IDX_T1 4 +#define DHCP_OPTION_IDX_T2 5 +#define DHCP_OPTION_IDX_SUBNET_MASK 6 +#define DHCP_OPTION_IDX_ROUTER 7 +#define DHCP_OPTION_IDX_DNS_SERVER 8 +#define DHCP_OPTION_IDX_MAX (DHCP_OPTION_IDX_DNS_SERVER + DNS_MAX_SERVERS) + +/** Holds the decoded option values, only valid while in dhcp_recv. + @todo: move this into struct dhcp? */ +u32_t dhcp_rx_options_val[DHCP_OPTION_IDX_MAX]; +/** Holds a flag which option was received and is contained in dhcp_rx_options_val, + only valid while in dhcp_recv. + @todo: move this into struct dhcp? */ +u8_t dhcp_rx_options_given[DHCP_OPTION_IDX_MAX]; + +#ifdef DHCP_GLOBAL_XID +static u32_t xid; +static u8_t xid_initialised; +#endif /* DHCP_GLOBAL_XID */ + +#define dhcp_option_given(dhcp, idx) (dhcp_rx_options_given[idx] != 0) +#define dhcp_got_option(dhcp, idx) (dhcp_rx_options_given[idx] = 1) +#define dhcp_clear_option(dhcp, idx) (dhcp_rx_options_given[idx] = 0) +#define dhcp_clear_all_options(dhcp) (memset(dhcp_rx_options_given, 0, sizeof(dhcp_rx_options_given))) +#define dhcp_get_option_value(dhcp, idx) (dhcp_rx_options_val[idx]) +#define dhcp_set_option_value(dhcp, idx, val) (dhcp_rx_options_val[idx] = (val)) + + +/* DHCP client state machine functions */ +static err_t dhcp_discover(struct netif *netif); +static err_t dhcp_select(struct netif *netif); +static void dhcp_bind(struct netif *netif); +#if DHCP_DOES_ARP_CHECK +static err_t dhcp_decline(struct netif *netif); +#endif /* DHCP_DOES_ARP_CHECK */ +static err_t dhcp_rebind(struct netif *netif); +static err_t dhcp_reboot(struct netif *netif); +static void dhcp_set_state(struct dhcp *dhcp, u8_t new_state); + +/* receive, unfold, parse and free incoming messages */ +static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port); + +/* set the DHCP timers */ +static void dhcp_timeout(struct netif *netif); +static void dhcp_t1_timeout(struct netif *netif); +static void dhcp_t2_timeout(struct netif *netif); + +/* build outgoing messages */ +/* create a DHCP message, fill in common headers */ +static err_t dhcp_create_msg(struct netif *netif, struct dhcp *dhcp, u8_t message_type); +/* free a DHCP request */ +static void dhcp_delete_msg(struct dhcp *dhcp); +/* add a DHCP option (type, then length in bytes) */ +static void dhcp_option(struct dhcp *dhcp, u8_t option_type, u8_t option_len); +/* add option values */ +static void dhcp_option_byte(struct dhcp *dhcp, u8_t value); +static void dhcp_option_short(struct dhcp *dhcp, u16_t value); +static void dhcp_option_long(struct dhcp *dhcp, u32_t value); +#if LWIP_NETIF_HOSTNAME +static void dhcp_option_hostname(struct dhcp *dhcp, struct netif *netif); +#endif /* LWIP_NETIF_HOSTNAME */ +/* always add the DHCP options trailer to end and pad */ +static void dhcp_option_trailer(struct dhcp *dhcp); + +/** + * Back-off the DHCP client (because of a received NAK response). + * + * Back-off the DHCP client because of a received NAK. Receiving a + * NAK means the client asked for something non-sensible, for + * example when it tries to renew a lease obtained on another network. + * + * We clear any existing set IP address and restart DHCP negotiation + * afresh (as per RFC2131 3.2.3). + * + * @param netif the netif under DHCP control + */ +static void +dhcp_handle_nak(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_nak(netif=%p) %c%c%"U16_F"\n", + (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); + /* Set the interface down since the address must no longer be used, as per RFC2131 */ + netif_set_down(netif); + /* remove IP address from interface */ + netif_set_ipaddr(netif, IP_ADDR_ANY); + netif_set_gw(netif, IP_ADDR_ANY); + netif_set_netmask(netif, IP_ADDR_ANY); + /* Change to a defined state */ + dhcp_set_state(dhcp, DHCP_BACKING_OFF); + /* We can immediately restart discovery */ + dhcp_discover(netif); +} + +#if DHCP_DOES_ARP_CHECK +/** + * Checks if the offered IP address is already in use. + * + * It does so by sending an ARP request for the offered address and + * entering CHECKING state. If no ARP reply is received within a small + * interval, the address is assumed to be free for use by us. + * + * @param netif the netif under DHCP control + */ +static void +dhcp_check(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result; + u16_t msecs; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_check(netif=%p) %c%c\n", (void *)netif, (s16_t)netif->name[0], + (s16_t)netif->name[1])); + dhcp_set_state(dhcp, DHCP_CHECKING); + /* create an ARP query for the offered IP address, expecting that no host + responds, as the IP address should not be in use. */ + result = etharp_query(netif, &dhcp->offered_ip_addr, NULL); + if (result != ERR_OK) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_check: could not perform ARP query\n")); + } + dhcp->tries++; + msecs = 500; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_check(): set request timeout %"U16_F" msecs\n", msecs)); +} +#endif /* DHCP_DOES_ARP_CHECK */ + +/** + * Remember the configuration offered by a DHCP server. + * + * @param netif the netif under DHCP control + */ +static void +dhcp_handle_offer(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_offer(netif=%p) %c%c%"U16_F"\n", + (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); + /* obtain the server address */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_SERVER_ID)) { + ip4_addr_set_u32(&dhcp->server_ip_addr, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SERVER_ID))); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): server 0x%08"X32_F"\n", + ip4_addr_get_u32(&dhcp->server_ip_addr))); + /* remember offered address */ + ip_addr_copy(dhcp->offered_ip_addr, dhcp->msg_in->yiaddr); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): offer for 0x%08"X32_F"\n", + ip4_addr_get_u32(&dhcp->offered_ip_addr))); + + dhcp_select(netif); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("dhcp_handle_offer(netif=%p) did not get server ID!\n", (void*)netif)); + } +} + +/** + * Select a DHCP server offer out of all offers. + * + * Simply select the first offer received. + * + * @param netif the netif under DHCP control + * @return lwIP specific error (see error.h) + */ +static err_t +dhcp_select(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result; + u16_t msecs; + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_select(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); + dhcp_set_state(dhcp, DHCP_REQUESTING); + + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); + if (result == ERR_OK) { + dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); + + /* MUST request the offered IP address */ + dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); + dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr))); + + dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4); + dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->server_ip_addr))); + + dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 4/*num options*/); + dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK); + dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER); + dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST); + dhcp_option_byte(dhcp, DHCP_OPTION_DNS_SERVER); + +#if LWIP_NETIF_HOSTNAME + dhcp_option_hostname(dhcp, netif); +#endif /* LWIP_NETIF_HOSTNAME */ + + dhcp_option_trailer(dhcp); + /* shrink the pbuf to the actual content length */ + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + /* send broadcast to any DHCP server */ + udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); + dhcp_delete_msg(dhcp); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_select: REQUESTING\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_select: could not allocate DHCP request\n")); + } + dhcp->tries++; + msecs = (dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_select(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} + +/** + * The DHCP timer that checks for lease renewal/rebind timeouts. + */ +void +dhcp_coarse_tmr() +{ + struct netif *netif = netif_list; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_coarse_tmr()\n")); + /* iterate through all network interfaces */ + while (netif != NULL) { + /* only act on DHCP configured interfaces */ + if (netif->dhcp != NULL) { + /* timer is active (non zero), and triggers (zeroes) now? */ + if (netif->dhcp->t2_timeout-- == 1) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t2 timeout\n")); + /* this clients' rebind timeout triggered */ + dhcp_t2_timeout(netif); + /* timer is active (non zero), and triggers (zeroes) now */ + } else if (netif->dhcp->t1_timeout-- == 1) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t1 timeout\n")); + /* this clients' renewal timeout triggered */ + dhcp_t1_timeout(netif); + } + } + /* proceed to next netif */ + netif = netif->next; + } +} + +/** + * DHCP transaction timeout handling + * + * A DHCP server is expected to respond within a short period of time. + * This timer checks whether an outstanding DHCP request is timed out. + */ +void +dhcp_fine_tmr() +{ + struct netif *netif = netif_list; + /* loop through netif's */ + while (netif != NULL) { + /* only act on DHCP configured interfaces */ + if (netif->dhcp != NULL) { + /* timer is active (non zero), and is about to trigger now */ + if (netif->dhcp->request_timeout > 1) { + netif->dhcp->request_timeout--; + } + else if (netif->dhcp->request_timeout == 1) { + netif->dhcp->request_timeout--; + /* { netif->dhcp->request_timeout == 0 } */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_fine_tmr(): request timeout\n")); + /* this client's request timeout triggered */ + dhcp_timeout(netif); + } + } + /* proceed to next network interface */ + netif = netif->next; + } +} + +/** + * A DHCP negotiation transaction, or ARP request, has timed out. + * + * The timer that was started with the DHCP or ARP request has + * timed out, indicating no response was received in time. + * + * @param netif the netif under DHCP control + */ +static void +dhcp_timeout(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout()\n")); + /* back-off period has passed, or server selection timed out */ + if ((dhcp->state == DHCP_BACKING_OFF) || (dhcp->state == DHCP_SELECTING)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout(): restarting discovery\n")); + dhcp_discover(netif); + /* receiving the requested lease timed out */ + } else if (dhcp->state == DHCP_REQUESTING) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REQUESTING, DHCP request timed out\n")); + if (dhcp->tries <= 5) { + dhcp_select(netif); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REQUESTING, releasing, restarting\n")); + dhcp_release(netif); + dhcp_discover(netif); + } +#if DHCP_DOES_ARP_CHECK + /* received no ARP reply for the offered address (which is good) */ + } else if (dhcp->state == DHCP_CHECKING) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): CHECKING, ARP request timed out\n")); + if (dhcp->tries <= 1) { + dhcp_check(netif); + /* no ARP replies on the offered address, + looks like the IP address is indeed free */ + } else { + /* bind the interface to the offered address */ + dhcp_bind(netif); + } +#endif /* DHCP_DOES_ARP_CHECK */ + } + /* did not get response to renew request? */ + else if (dhcp->state == DHCP_RENEWING) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): RENEWING, DHCP request timed out\n")); + /* just retry renewal */ + /* note that the rebind timer will eventually time-out if renew does not work */ + dhcp_renew(netif); + /* did not get response to rebind request? */ + } else if (dhcp->state == DHCP_REBINDING) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REBINDING, DHCP request timed out\n")); + if (dhcp->tries <= 8) { + dhcp_rebind(netif); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): RELEASING, DISCOVERING\n")); + dhcp_release(netif); + dhcp_discover(netif); + } + } else if (dhcp->state == DHCP_REBOOTING) { + if (dhcp->tries < REBOOT_TRIES) { + dhcp_reboot(netif); + } else { + dhcp_discover(netif); + } + } +} + +/** + * The renewal period has timed out. + * + * @param netif the netif under DHCP control + */ +static void +dhcp_t1_timeout(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_t1_timeout()\n")); + if ((dhcp->state == DHCP_REQUESTING) || (dhcp->state == DHCP_BOUND) || + (dhcp->state == DHCP_RENEWING)) { + /* just retry to renew - note that the rebind timer (t2) will + * eventually time-out if renew tries fail. */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("dhcp_t1_timeout(): must renew\n")); + /* This slightly different to RFC2131: DHCPREQUEST will be sent from state + DHCP_RENEWING, not DHCP_BOUND */ + dhcp_renew(netif); + } +} + +/** + * The rebind period has timed out. + * + * @param netif the netif under DHCP control + */ +static void +dhcp_t2_timeout(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_t2_timeout()\n")); + if ((dhcp->state == DHCP_REQUESTING) || (dhcp->state == DHCP_BOUND) || + (dhcp->state == DHCP_RENEWING)) { + /* just retry to rebind */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("dhcp_t2_timeout(): must rebind\n")); + /* This slightly different to RFC2131: DHCPREQUEST will be sent from state + DHCP_REBINDING, not DHCP_BOUND */ + dhcp_rebind(netif); + } +} + +/** + * Handle a DHCP ACK packet + * + * @param netif the netif under DHCP control + */ +static void +dhcp_handle_ack(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; +#if LWIP_DNS + u8_t n; +#endif /* LWIP_DNS */ + + /* clear options we might not get from the ACK */ + ip_addr_set_zero(&dhcp->offered_sn_mask); + ip_addr_set_zero(&dhcp->offered_gw_addr); +#if LWIP_DHCP_BOOTP_FILE + ip_addr_set_zero(&dhcp->offered_si_addr); +#endif /* LWIP_DHCP_BOOTP_FILE */ + + /* lease time given? */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_LEASE_TIME)) { + /* remember offered lease time */ + dhcp->offered_t0_lease = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_LEASE_TIME); + } + /* renewal period given? */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_T1)) { + /* remember given renewal period */ + dhcp->offered_t1_renew = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_T1); + } else { + /* calculate safe periods for renewal */ + dhcp->offered_t1_renew = dhcp->offered_t0_lease / 2; + } + + /* renewal period given? */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_T2)) { + /* remember given rebind period */ + dhcp->offered_t2_rebind = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_T2); + } else { + /* calculate safe periods for rebinding */ + dhcp->offered_t2_rebind = dhcp->offered_t0_lease; + } + + /* (y)our internet address */ + ip_addr_copy(dhcp->offered_ip_addr, dhcp->msg_in->yiaddr); + +#if LWIP_DHCP_BOOTP_FILE + /* copy boot server address, + boot file name copied in dhcp_parse_reply if not overloaded */ + ip_addr_copy(dhcp->offered_si_addr, dhcp->msg_in->siaddr); +#endif /* LWIP_DHCP_BOOTP_FILE */ + + /* subnet mask given? */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_SUBNET_MASK)) { + /* remember given subnet mask */ + ip4_addr_set_u32(&dhcp->offered_sn_mask, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SUBNET_MASK))); + dhcp->subnet_mask_given = 1; + } else { + dhcp->subnet_mask_given = 0; + } + + /* gateway router */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_ROUTER)) { + ip4_addr_set_u32(&dhcp->offered_gw_addr, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_ROUTER))); + } + +#if LWIP_DNS + /* DNS servers */ + n = 0; + while(dhcp_option_given(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n) && (n < DNS_MAX_SERVERS)) { + ip_addr_t dns_addr; + ip4_addr_set_u32(&dns_addr, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n))); + dns_setserver(n, &dns_addr); + n++; + } +#endif /* LWIP_DNS */ +} + +/** Set a statically allocated struct dhcp to work with. + * Using this prevents dhcp_start to allocate it using mem_malloc. + * + * @param netif the netif for which to set the struct dhcp + * @param dhcp (uninitialised) dhcp struct allocated by the application + */ +void +dhcp_set_struct(struct netif *netif, struct dhcp *dhcp) +{ + LWIP_ASSERT("netif != NULL", netif != NULL); + LWIP_ASSERT("dhcp != NULL", dhcp != NULL); + LWIP_ASSERT("netif already has a struct dhcp set", netif->dhcp == NULL); + + /* clear data structure */ + memset(dhcp, 0, sizeof(struct dhcp)); + /* dhcp_set_state(&dhcp, DHCP_OFF); */ + netif->dhcp = dhcp; +} + +/** Removes a struct dhcp from a netif. + * + * ATTENTION: Only use this when not using dhcp_set_struct() to allocate the + * struct dhcp since the memory is passed back to the heap. + * + * @param netif the netif from which to remove the struct dhcp + */ +void dhcp_cleanup(struct netif *netif) +{ + LWIP_ASSERT("netif != NULL", netif != NULL); + + if (netif->dhcp != NULL) { + mem_free(netif->dhcp); + netif->dhcp = NULL; + } +} + +/** + * Start DHCP negotiation for a network interface. + * + * If no DHCP client instance was attached to this interface, + * a new client is created first. If a DHCP client instance + * was already present, it restarts negotiation. + * + * @param netif The lwIP network interface + * @return lwIP error code + * - ERR_OK - No error + * - ERR_MEM - Out of memory + */ +err_t +dhcp_start(struct netif *netif) +{ + struct dhcp *dhcp; + err_t result = ERR_OK; + + LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG;); + dhcp = netif->dhcp; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); + /* Remove the flag that says this netif is handled by DHCP, + it is set when we succeeded starting. */ + netif->flags &= ~NETIF_FLAG_DHCP; + + /* check hwtype of the netif */ + if ((netif->flags & NETIF_FLAG_ETHARP) == 0) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): No ETHARP netif\n")); + return ERR_ARG; + } + + /* check MTU of the netif */ + if (netif->mtu < DHCP_MAX_MSG_LEN_MIN_REQUIRED) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): Cannot use this netif with DHCP: MTU is too small\n")); + return ERR_MEM; + } + + /* no DHCP client attached yet? */ + if (dhcp == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting new DHCP client\n")); + dhcp = (struct dhcp *)mem_malloc(sizeof(struct dhcp)); + if (dhcp == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not allocate dhcp\n")); + return ERR_MEM; + } + /* store this dhcp client in the netif */ + netif->dhcp = dhcp; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): allocated dhcp")); + /* already has DHCP client attached */ + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_start(): restarting DHCP configuration\n")); + if (dhcp->pcb != NULL) { + udp_remove(dhcp->pcb); + } + LWIP_ASSERT("pbuf p_out wasn't freed", dhcp->p_out == NULL); + LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL ); + } + + /* clear data structure */ + memset(dhcp, 0, sizeof(struct dhcp)); + /* dhcp_set_state(&dhcp, DHCP_OFF); */ + /* allocate UDP PCB */ + dhcp->pcb = udp_new(); + if (dhcp->pcb == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not obtain pcb\n")); + return ERR_MEM; + } + ip_set_option(dhcp->pcb, SOF_BROADCAST); + /* set up local and remote port for the pcb */ + udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT); + udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT); + /* set up the recv callback and argument */ + udp_recv(dhcp->pcb, dhcp_recv, netif); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting DHCP configuration\n")); + /* (re)start the DHCP negotiation */ + result = dhcp_discover(netif); + if (result != ERR_OK) { + /* free resources allocated above */ + dhcp_stop(netif); + return ERR_MEM; + } + /* Set the flag that says this netif is handled by DHCP. */ + netif->flags |= NETIF_FLAG_DHCP; + return result; +} + +/** + * Inform a DHCP server of our manual configuration. + * + * This informs DHCP servers of our fixed IP address configuration + * by sending an INFORM message. It does not involve DHCP address + * configuration, it is just here to be nice to the network. + * + * @param netif The lwIP network interface + */ +void +dhcp_inform(struct netif *netif) +{ + struct dhcp dhcp; + err_t result = ERR_OK; + struct udp_pcb *pcb; + + LWIP_ERROR("netif != NULL", (netif != NULL), return;); + + memset(&dhcp, 0, sizeof(struct dhcp)); + dhcp_set_state(&dhcp, DHCP_INFORM); + + if ((netif->dhcp != NULL) && (netif->dhcp->pcb != NULL)) { + /* re-use existing pcb */ + pcb = netif->dhcp->pcb; + } else { + pcb = udp_new(); + if (pcb == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform(): could not obtain pcb")); + return; + } + dhcp.pcb = pcb; + ip_set_option(dhcp.pcb, SOF_BROADCAST); + udp_bind(dhcp.pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_inform(): created new udp pcb\n")); + } + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, &dhcp, DHCP_INFORM); + if (result == ERR_OK) { + dhcp_option(&dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(&dhcp, DHCP_MAX_MSG_LEN(netif)); + + dhcp_option_trailer(&dhcp); + + pbuf_realloc(dhcp.p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp.options_out_len); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_inform: INFORMING\n")); + udp_sendto_if(pcb, dhcp.p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); + dhcp_delete_msg(&dhcp); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform: could not allocate DHCP request\n")); + } + + if (dhcp.pcb != NULL) { + /* otherwise, the existing pcb was used */ + udp_remove(dhcp.pcb); + } +} + +/** Handle a possible change in the network configuration. + * + * This enters the REBOOTING state to verify that the currently bound + * address is still valid. + */ +void +dhcp_network_changed(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + if (!dhcp) + return; + switch (dhcp->state) { + case DHCP_REBINDING: + case DHCP_RENEWING: + case DHCP_BOUND: + case DHCP_REBOOTING: + netif_set_down(netif); + dhcp->tries = 0; + dhcp_reboot(netif); + break; + case DHCP_OFF: + /* stay off */ + break; + default: + dhcp->tries = 0; +#if LWIP_DHCP_AUTOIP_COOP + if(dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) { + autoip_stop(netif); + dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF; + } +#endif /* LWIP_DHCP_AUTOIP_COOP */ + dhcp_discover(netif); + break; + } +} + +#if DHCP_DOES_ARP_CHECK +/** + * Match an ARP reply with the offered IP address. + * + * @param netif the network interface on which the reply was received + * @param addr The IP address we received a reply from + */ +void dhcp_arp_reply(struct netif *netif, ip_addr_t *addr) +{ + LWIP_ERROR("netif != NULL", (netif != NULL), return;); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_arp_reply()\n")); + /* is a DHCP client doing an ARP check? */ + if ((netif->dhcp != NULL) && (netif->dhcp->state == DHCP_CHECKING)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08"X32_F"\n", + ip4_addr_get_u32(addr))); + /* did a host respond with the address we + were offered by the DHCP server? */ + if (ip_addr_cmp(addr, &netif->dhcp->offered_ip_addr)) { + /* we will not accept the offered address */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING, + ("dhcp_arp_reply(): arp reply matched with offered address, declining\n")); + dhcp_decline(netif); + } + } +} + +/** + * Decline an offered lease. + * + * Tell the DHCP server we do not accept the offered address. + * One reason to decline the lease is when we find out the address + * is already in use by another host (through ARP). + * + * @param netif the netif under DHCP control + */ +static err_t +dhcp_decline(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result = ERR_OK; + u16_t msecs; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline()\n")); + dhcp_set_state(dhcp, DHCP_BACKING_OFF); + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_DECLINE); + if (result == ERR_OK) { + dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); + dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr))); + + dhcp_option_trailer(dhcp); + /* resize pbuf to reflect true size of options */ + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + /* per section 4.4.4, broadcast DECLINE messages */ + udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); + dhcp_delete_msg(dhcp); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_decline: BACKING OFF\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("dhcp_decline: could not allocate DHCP request\n")); + } + dhcp->tries++; + msecs = 10*1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} +#endif /* DHCP_DOES_ARP_CHECK */ + + +/** + * Start the DHCP process, discover a DHCP server. + * + * @param netif the netif under DHCP control + */ +static err_t +dhcp_discover(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result = ERR_OK; + u16_t msecs; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover()\n")); + ip_addr_set_any(&dhcp->offered_ip_addr); + dhcp_set_state(dhcp, DHCP_SELECTING); + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_DISCOVER); + if (result == ERR_OK) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: making request\n")); + + dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); + + dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 4/*num options*/); + dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK); + dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER); + dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST); + dhcp_option_byte(dhcp, DHCP_OPTION_DNS_SERVER); + + dhcp_option_trailer(dhcp); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: realloc()ing\n")); + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, DHCP_SERVER_PORT)\n")); + udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: deleting()ing\n")); + dhcp_delete_msg(dhcp); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover: SELECTING\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_discover: could not allocate DHCP request\n")); + } + dhcp->tries++; +#if LWIP_DHCP_AUTOIP_COOP + if(dhcp->tries >= LWIP_DHCP_AUTOIP_COOP_TRIES && dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_OFF) { + dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_ON; + autoip_start(netif); + } +#endif /* LWIP_DHCP_AUTOIP_COOP */ + msecs = (dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} + + +/** + * Bind the interface to the offered IP address. + * + * @param netif network interface to bind to the offered address + */ +static void +dhcp_bind(struct netif *netif) +{ + u32_t timeout; + struct dhcp *dhcp; + ip_addr_t sn_mask, gw_addr; + LWIP_ERROR("dhcp_bind: netif != NULL", (netif != NULL), return;); + dhcp = netif->dhcp; + LWIP_ERROR("dhcp_bind: dhcp != NULL", (dhcp != NULL), return;); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); + + /* temporary DHCP lease? */ + if (dhcp->offered_t1_renew != 0xffffffffUL) { + /* set renewal period timer */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t1 renewal timer %"U32_F" secs\n", dhcp->offered_t1_renew)); + timeout = (dhcp->offered_t1_renew + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS; + if(timeout > 0xffff) { + timeout = 0xffff; + } + dhcp->t1_timeout = (u16_t)timeout; + if (dhcp->t1_timeout == 0) { + dhcp->t1_timeout = 1; + } + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t1_renew*1000)); + } + /* set renewal period timer */ + if (dhcp->offered_t2_rebind != 0xffffffffUL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t2 rebind timer %"U32_F" secs\n", dhcp->offered_t2_rebind)); + timeout = (dhcp->offered_t2_rebind + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS; + if(timeout > 0xffff) { + timeout = 0xffff; + } + dhcp->t2_timeout = (u16_t)timeout; + if (dhcp->t2_timeout == 0) { + dhcp->t2_timeout = 1; + } + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t2_rebind*1000)); + } + + /* If we have sub 1 minute lease, t2 and t1 will kick in at the same time. */ + if ((dhcp->t1_timeout >= dhcp->t2_timeout) && (dhcp->t2_timeout > 0)) { + dhcp->t1_timeout = 0; + } + + if (dhcp->subnet_mask_given) { + /* copy offered network mask */ + ip_addr_copy(sn_mask, dhcp->offered_sn_mask); + } else { + /* subnet mask not given, choose a safe subnet mask given the network class */ + u8_t first_octet = ip4_addr1(&dhcp->offered_ip_addr); + if (first_octet <= 127) { + ip4_addr_set_u32(&sn_mask, PP_HTONL(0xff000000UL)); + } else if (first_octet >= 192) { + ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffffff00UL)); + } else { + ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffff0000UL)); + } + } + + ip_addr_copy(gw_addr, dhcp->offered_gw_addr); + /* gateway address not given? */ + if (ip_addr_isany(&gw_addr)) { + /* copy network address */ + ip_addr_get_network(&gw_addr, &dhcp->offered_ip_addr, &sn_mask); + /* use first host address on network as gateway */ + ip4_addr_set_u32(&gw_addr, ip4_addr_get_u32(&gw_addr) | PP_HTONL(0x00000001UL)); + } + +#if LWIP_DHCP_AUTOIP_COOP + if(dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) { + autoip_stop(netif); + dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF; + } +#endif /* LWIP_DHCP_AUTOIP_COOP */ + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): IP: 0x%08"X32_F"\n", + ip4_addr_get_u32(&dhcp->offered_ip_addr))); + netif_set_ipaddr(netif, &dhcp->offered_ip_addr); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): SN: 0x%08"X32_F"\n", + ip4_addr_get_u32(&sn_mask))); + netif_set_netmask(netif, &sn_mask); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): GW: 0x%08"X32_F"\n", + ip4_addr_get_u32(&gw_addr))); + netif_set_gw(netif, &gw_addr); + /* bring the interface up */ + netif_set_up(netif); + /* netif is now bound to DHCP leased address */ + dhcp_set_state(dhcp, DHCP_BOUND); +} + +/** + * Renew an existing DHCP lease at the involved DHCP server. + * + * @param netif network interface which must renew its lease + */ +err_t +dhcp_renew(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result; + u16_t msecs; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_renew()\n")); + dhcp_set_state(dhcp, DHCP_RENEWING); + + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); + if (result == ERR_OK) { + dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); + +#if 0 + dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); + dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr)); +#endif + +#if 0 + dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4); + dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr)); +#endif + +#if LWIP_NETIF_HOSTNAME + dhcp_option_hostname(dhcp, netif); +#endif /* LWIP_NETIF_HOSTNAME */ + + /* append DHCP message trailer */ + dhcp_option_trailer(dhcp); + + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + udp_sendto_if(dhcp->pcb, dhcp->p_out, &dhcp->server_ip_addr, DHCP_SERVER_PORT, netif); + dhcp_delete_msg(dhcp); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew: RENEWING\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_renew: could not allocate DHCP request\n")); + } + dhcp->tries++; + /* back-off on retries, but to a maximum of 20 seconds */ + msecs = dhcp->tries < 10 ? dhcp->tries * 2000 : 20 * 1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} + +/** + * Rebind with a DHCP server for an existing DHCP lease. + * + * @param netif network interface which must rebind with a DHCP server + */ +static err_t +dhcp_rebind(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result; + u16_t msecs; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind()\n")); + dhcp_set_state(dhcp, DHCP_REBINDING); + + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); + if (result == ERR_OK) { + dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); + +#if LWIP_NETIF_HOSTNAME + dhcp_option_hostname(dhcp, netif); +#endif /* LWIP_NETIF_HOSTNAME */ + +#if 0 + dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); + dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr)); + + dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4); + dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr)); +#endif + + dhcp_option_trailer(dhcp); + + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + /* broadcast to server */ + udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); + dhcp_delete_msg(dhcp); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind: REBINDING\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_rebind: could not allocate DHCP request\n")); + } + dhcp->tries++; + msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} + +/** + * Enter REBOOTING state to verify an existing lease + * + * @param netif network interface which must reboot + */ +static err_t +dhcp_reboot(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result; + u16_t msecs; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot()\n")); + dhcp_set_state(dhcp, DHCP_REBOOTING); + + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); + if (result == ERR_OK) { + dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(dhcp, 576); + + dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); + dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr))); + + dhcp_option_trailer(dhcp); + + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + /* broadcast to server */ + udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); + dhcp_delete_msg(dhcp); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot: REBOOTING\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_reboot: could not allocate DHCP request\n")); + } + dhcp->tries++; + msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} + + +/** + * Release a DHCP lease. + * + * @param netif network interface which must release its lease + */ +err_t +dhcp_release(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result; + u16_t msecs; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_release()\n")); + + /* idle DHCP client */ + dhcp_set_state(dhcp, DHCP_OFF); + /* clean old DHCP offer */ + ip_addr_set_zero(&dhcp->server_ip_addr); + ip_addr_set_zero(&dhcp->offered_ip_addr); + ip_addr_set_zero(&dhcp->offered_sn_mask); + ip_addr_set_zero(&dhcp->offered_gw_addr); +#if LWIP_DHCP_BOOTP_FILE + ip_addr_set_zero(&dhcp->offered_si_addr); +#endif /* LWIP_DHCP_BOOTP_FILE */ + dhcp->offered_t0_lease = dhcp->offered_t1_renew = dhcp->offered_t2_rebind = 0; + + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_RELEASE); + if (result == ERR_OK) { + dhcp_option_trailer(dhcp); + + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + udp_sendto_if(dhcp->pcb, dhcp->p_out, &dhcp->server_ip_addr, DHCP_SERVER_PORT, netif); + dhcp_delete_msg(dhcp); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release: RELEASED, DHCP_OFF\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_release: could not allocate DHCP request\n")); + } + dhcp->tries++; + msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release(): set request timeout %"U16_F" msecs\n", msecs)); + /* bring the interface down */ + netif_set_down(netif); + /* remove IP address from interface */ + netif_set_ipaddr(netif, IP_ADDR_ANY); + netif_set_gw(netif, IP_ADDR_ANY); + netif_set_netmask(netif, IP_ADDR_ANY); + + /* TODO: netif_down(netif); */ + return result; +} + +/** + * Release a DHCP lease. + * + * @param netif network interface which must release its lease + */ +err_t +dhcp_release_unicast(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result; + u16_t msecs; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_release()\n")); + + /* idle DHCP client */ + dhcp_set_state(dhcp, DHCP_RELEASING); + /* clean old DHCP offer *//* + dhcp->server_ip_addr.addr = 0; + dhcp->offered_ip_addr.addr = dhcp->offered_sn_mask.addr = 0; + dhcp->offered_gw_addr.addr = dhcp->offered_bc_addr.addr = 0; + dhcp->offered_t0_lease = dhcp->offered_t1_renew = dhcp->offered_t2_rebind = 0; + dhcp->dns_count = 0;*/ + + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif,netif->dhcp,DHCP_REQUEST); //Evan modified + if (result == ERR_OK) { + dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN); + dhcp_option_byte(dhcp, DHCP_RELEASE); + + dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4); + dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr)); + + dhcp_option_trailer(dhcp); + + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + udp_sendto_if(dhcp->pcb, dhcp->p_out, &dhcp->server_ip_addr, DHCP_SERVER_PORT, netif); + dhcp_delete_msg(netif->dhcp);//Evan modified + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release: RELEASED, DHCP_OFF\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_release: could not allocate DHCP request\n")); + } + dhcp->tries++; + msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release(): set request timeout %"U16_F" msecs\n", msecs)); + /* bring the interface down */ + netif_set_down(netif); + /* remove IP address from interface */ + netif_set_ipaddr(netif, IP_ADDR_ANY); + netif_set_gw(netif, IP_ADDR_ANY); + netif_set_netmask(netif, IP_ADDR_ANY); + + /* TODO: netif_down(netif); */ + return result; +} + +/** + * Remove the DHCP client from the interface. + * + * @param netif The network interface to stop DHCP on + */ +void +dhcp_stop(struct netif *netif) +{ + struct dhcp *dhcp; + LWIP_ERROR("dhcp_stop: netif != NULL", (netif != NULL), return;); + dhcp = netif->dhcp; + /* Remove the flag that says this netif is handled by DHCP. */ + netif->flags &= ~NETIF_FLAG_DHCP; + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_stop()\n")); + /* netif is DHCP configured? */ + if (dhcp != NULL) { +#if LWIP_DHCP_AUTOIP_COOP + if(dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) { + autoip_stop(netif); + dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF; + } +#endif /* LWIP_DHCP_AUTOIP_COOP */ + + if (dhcp->pcb != NULL) { + udp_remove(dhcp->pcb); + dhcp->pcb = NULL; + } + LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL); + dhcp_set_state(dhcp, DHCP_OFF); + } +} + +/* + * Set the DHCP state of a DHCP client. + * + * If the state changed, reset the number of tries. + */ +static void +dhcp_set_state(struct dhcp *dhcp, u8_t new_state) +{ + if (new_state != dhcp->state) { + dhcp->state = new_state; + dhcp->tries = 0; + dhcp->request_timeout = 0; + } +} + +/* + * Concatenate an option type and length field to the outgoing + * DHCP message. + * + */ +static void +dhcp_option(struct dhcp *dhcp, u8_t option_type, u8_t option_len) +{ + LWIP_ASSERT("dhcp_option: dhcp->options_out_len + 2 + option_len <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 2U + option_len <= DHCP_OPTIONS_LEN); + dhcp->msg_out->options[dhcp->options_out_len++] = option_type; + dhcp->msg_out->options[dhcp->options_out_len++] = option_len; +} +/* + * Concatenate a single byte to the outgoing DHCP message. + * + */ +static void +dhcp_option_byte(struct dhcp *dhcp, u8_t value) +{ + LWIP_ASSERT("dhcp_option_byte: dhcp->options_out_len < DHCP_OPTIONS_LEN", dhcp->options_out_len < DHCP_OPTIONS_LEN); + dhcp->msg_out->options[dhcp->options_out_len++] = value; +} + +static void +dhcp_option_short(struct dhcp *dhcp, u16_t value) +{ + LWIP_ASSERT("dhcp_option_short: dhcp->options_out_len + 2 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 2U <= DHCP_OPTIONS_LEN); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0xff00U) >> 8); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t) (value & 0x00ffU); +} + +static void +dhcp_option_long(struct dhcp *dhcp, u32_t value) +{ + LWIP_ASSERT("dhcp_option_long: dhcp->options_out_len + 4 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 4U <= DHCP_OPTIONS_LEN); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0xff000000UL) >> 24); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x00ff0000UL) >> 16); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x0000ff00UL) >> 8); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x000000ffUL)); +} + +#if LWIP_NETIF_HOSTNAME +static void +dhcp_option_hostname(struct dhcp *dhcp, struct netif *netif) +{ + if (netif->hostname != NULL) { + size_t namelen = strlen(netif->hostname); + if (namelen > 0) { + u8_t len; + const char *p = netif->hostname; + /* Shrink len to available bytes (need 2 bytes for OPTION_HOSTNAME + and 1 byte for trailer) */ + size_t available = DHCP_OPTIONS_LEN - dhcp->options_out_len - 3; + LWIP_ASSERT("DHCP: hostname is too long!", namelen <= available); + len = LWIP_MIN(namelen, available); + dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, len); + while (len--) { + dhcp_option_byte(dhcp, *p++); + } + } + } +} +#endif /* LWIP_NETIF_HOSTNAME */ + +/** + * Extract the DHCP message and the DHCP options. + * + * Extract the DHCP message and the DHCP options, each into a contiguous + * piece of memory. As a DHCP message is variable sized by its options, + * and also allows overriding some fields for options, the easy approach + * is to first unfold the options into a conitguous piece of memory, and + * use that further on. + * + */ +static err_t +dhcp_parse_reply(struct dhcp *dhcp, struct pbuf *p) +{ + u8_t *options; + u16_t offset; + u16_t offset_max; + u16_t options_idx; + u16_t options_idx_max; + struct pbuf *q; + int parse_file_as_options = 0; + int parse_sname_as_options = 0; + + /* clear received options */ + dhcp_clear_all_options(dhcp); + /* check that beginning of dhcp_msg (up to and including chaddr) is in first pbuf */ + if (p->len < DHCP_SNAME_OFS) { + return ERR_BUF; + } + dhcp->msg_in = (struct dhcp_msg *)p->payload; +#if LWIP_DHCP_BOOTP_FILE + /* clear boot file name */ + dhcp->boot_file_name[0] = 0; +#endif /* LWIP_DHCP_BOOTP_FILE */ + + /* parse options */ + + /* start with options field */ + options_idx = DHCP_OPTIONS_OFS; + /* parse options to the end of the received packet */ + options_idx_max = p->tot_len; +again: + q = p; + while((q != NULL) && (options_idx >= q->len)) { + options_idx -= q->len; + options_idx_max -= q->len; + q = q->next; + } + if (q == NULL) { + return ERR_BUF; + } + offset = options_idx; + offset_max = options_idx_max; + options = (u8_t*)q->payload; + /* at least 1 byte to read and no end marker, then at least 3 bytes to read? */ + while((q != NULL) && (options[offset] != DHCP_OPTION_END) && (offset < offset_max)) { + u8_t op = options[offset]; + u8_t len; + u8_t decode_len = 0; + int decode_idx = -1; + u16_t val_offset = offset + 2; + /* len byte might be in the next pbuf */ + if (offset + 1 < q->len) { + len = options[offset + 1]; + } else { + len = (q->next != NULL ? ((u8_t*)q->next->payload)[0] : 0); + } + /* LWIP_DEBUGF(DHCP_DEBUG, ("msg_offset=%"U16_F", q->len=%"U16_F, msg_offset, q->len)); */ + decode_len = len; + switch(op) { + /* case(DHCP_OPTION_END): handled above */ + case(DHCP_OPTION_PAD): + /* special option: no len encoded */ + decode_len = len = 0; + /* will be increased below */ + offset--; + break; + case(DHCP_OPTION_SUBNET_MASK): + LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_SUBNET_MASK; + break; + case(DHCP_OPTION_ROUTER): + decode_len = 4; /* only copy the first given router */ + LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_ROUTER; + break; + case(DHCP_OPTION_DNS_SERVER): + /* special case: there might be more than one server */ + LWIP_ERROR("len % 4 == 0", len % 4 == 0, return ERR_VAL;); + /* limit number of DNS servers */ + decode_len = LWIP_MIN(len, 4 * DNS_MAX_SERVERS); + LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_DNS_SERVER; + break; + case(DHCP_OPTION_LEASE_TIME): + LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_LEASE_TIME; + break; + case(DHCP_OPTION_OVERLOAD): + LWIP_ERROR("len == 1", len == 1, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_OVERLOAD; + break; + case(DHCP_OPTION_MESSAGE_TYPE): + LWIP_ERROR("len == 1", len == 1, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_MSG_TYPE; + break; + case(DHCP_OPTION_SERVER_ID): + LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_SERVER_ID; + break; + case(DHCP_OPTION_T1): + LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_T1; + break; + case(DHCP_OPTION_T2): + LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_T2; + break; + default: + decode_len = 0; + LWIP_DEBUGF(DHCP_DEBUG, ("skipping option %"U16_F" in options\n", op)); + break; + } + offset += len + 2; + if (decode_len > 0) { + u32_t value = 0; + u16_t copy_len; +decode_next: + LWIP_ASSERT("check decode_idx", decode_idx >= 0 && decode_idx < DHCP_OPTION_IDX_MAX); + if (!dhcp_option_given(dhcp, decode_idx)) { + copy_len = LWIP_MIN(decode_len, 4); + pbuf_copy_partial(q, &value, copy_len, val_offset); + if (decode_len > 4) { + /* decode more than one u32_t */ + LWIP_ERROR("decode_len % 4 == 0", decode_len % 4 == 0, return ERR_VAL;); + dhcp_got_option(dhcp, decode_idx); + dhcp_set_option_value(dhcp, decode_idx, htonl(value)); + decode_len -= 4; + val_offset += 4; + decode_idx++; + goto decode_next; + } else if (decode_len == 4) { + value = ntohl(value); + } else { + LWIP_ERROR("invalid decode_len", decode_len == 1, return ERR_VAL;); + value = ((u8_t*)&value)[0]; + } + dhcp_got_option(dhcp, decode_idx); + dhcp_set_option_value(dhcp, decode_idx, value); + } + } + if (offset >= q->len) { + offset -= q->len; + offset_max -= q->len; + if ((offset < offset_max) && offset_max) { + q = q->next; + LWIP_ASSERT("next pbuf was null", q); + options = (u8_t*)q->payload; + } else { + // We've run out of bytes, probably no end marker. Don't proceed. + break; + } + } + } + /* is this an overloaded message? */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_OVERLOAD)) { + u32_t overload = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_OVERLOAD); + dhcp_clear_option(dhcp, DHCP_OPTION_IDX_OVERLOAD); + if (overload == DHCP_OVERLOAD_FILE) { + parse_file_as_options = 1; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded file field\n")); + } else if (overload == DHCP_OVERLOAD_SNAME) { + parse_sname_as_options = 1; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname field\n")); + } else if (overload == DHCP_OVERLOAD_SNAME_FILE) { + parse_sname_as_options = 1; + parse_file_as_options = 1; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname and file field\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("invalid overload option: %d\n", (int)overload)); + } +#if LWIP_DHCP_BOOTP_FILE + if (!parse_file_as_options) { + /* only do this for ACK messages */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE) && + (dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_MSG_TYPE) == DHCP_ACK)) + /* copy bootp file name, don't care for sname (server hostname) */ + pbuf_copy_partial(p, dhcp->boot_file_name, DHCP_FILE_LEN-1, DHCP_FILE_OFS); + /* make sure the string is really NULL-terminated */ + dhcp->boot_file_name[DHCP_FILE_LEN-1] = 0; + } +#endif /* LWIP_DHCP_BOOTP_FILE */ + } + if (parse_file_as_options) { + /* if both are overloaded, parse file first and then sname (RFC 2131 ch. 4.1) */ + parse_file_as_options = 0; + options_idx = DHCP_FILE_OFS; + options_idx_max = DHCP_FILE_OFS + DHCP_FILE_LEN; + goto again; + } else if (parse_sname_as_options) { + parse_sname_as_options = 0; + options_idx = DHCP_SNAME_OFS; + options_idx_max = DHCP_SNAME_OFS + DHCP_SNAME_LEN; + goto again; + } + return ERR_OK; +} + +/** + * If an incoming DHCP message is in response to us, then trigger the state machine + */ +static void +dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port) +{ + struct netif *netif = (struct netif *)arg; + struct dhcp *dhcp = netif->dhcp; + struct dhcp_msg *reply_msg = (struct dhcp_msg *)p->payload; + u8_t msg_type; + u8_t i; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_recv(pbuf = %p) from DHCP server %"U16_F".%"U16_F".%"U16_F".%"U16_F" port %"U16_F"\n", (void*)p, + ip4_addr1_16(addr), ip4_addr2_16(addr), ip4_addr3_16(addr), ip4_addr4_16(addr), port)); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->len = %"U16_F"\n", p->len)); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->tot_len = %"U16_F"\n", p->tot_len)); + /* prevent warnings about unused arguments */ + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(addr); + LWIP_UNUSED_ARG(port); + + LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL); + + if (p->len < DHCP_MIN_REPLY_LEN) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP reply message or pbuf too short\n")); + goto free_pbuf_and_return; + } + + if (reply_msg->op != DHCP_BOOTREPLY) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("not a DHCP reply message, but type %"U16_F"\n", (u16_t)reply_msg->op)); + goto free_pbuf_and_return; + } + /* iterate through hardware address and match against DHCP message */ + for (i = 0; i < netif->hwaddr_len; i++) { + if (netif->hwaddr[i] != reply_msg->chaddr[i]) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("netif->hwaddr[%"U16_F"]==%02"X16_F" != reply_msg->chaddr[%"U16_F"]==%02"X16_F"\n", + (u16_t)i, (u16_t)netif->hwaddr[i], (u16_t)i, (u16_t)reply_msg->chaddr[i])); + goto free_pbuf_and_return; + } + } + /* match transaction ID against what we expected */ + if (ntohl(reply_msg->xid) != dhcp->xid) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("transaction id mismatch reply_msg->xid(%"X32_F")!=dhcp->xid(%"X32_F")\n",ntohl(reply_msg->xid),dhcp->xid)); + goto free_pbuf_and_return; + } + /* option fields could be unfold? */ + if (dhcp_parse_reply(dhcp, p) != ERR_OK) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("problem unfolding DHCP message - too short on memory?\n")); + goto free_pbuf_and_return; + } + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("searching DHCP_OPTION_MESSAGE_TYPE\n")); + /* obtain pointer to DHCP message type */ + if (!dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP_OPTION_MESSAGE_TYPE option not found\n")); + goto free_pbuf_and_return; + } + + /* read DHCP message type */ + msg_type = (u8_t)dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_MSG_TYPE); + /* message type is DHCP ACK? */ + if (msg_type == DHCP_ACK) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_ACK received\n")); + /* in requesting state? */ + if (dhcp->state == DHCP_REQUESTING) { + dhcp_handle_ack(netif); +#if DHCP_DOES_ARP_CHECK + /* check if the acknowledged lease address is already in use */ + dhcp_check(netif); +#else + /* bind interface to the acknowledged lease address */ + dhcp_bind(netif); +#endif + } + /* already bound to the given lease address? */ + else if ((dhcp->state == DHCP_REBOOTING) || (dhcp->state == DHCP_REBINDING) || (dhcp->state == DHCP_RENEWING)) { + dhcp_bind(netif); + } + } + /* received a DHCP_NAK in appropriate state? */ + else if ((msg_type == DHCP_NAK) && + ((dhcp->state == DHCP_REBOOTING) || (dhcp->state == DHCP_REQUESTING) || + (dhcp->state == DHCP_REBINDING) || (dhcp->state == DHCP_RENEWING ))) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_NAK received\n")); + dhcp_handle_nak(netif); + } + /* received a DHCP_OFFER in DHCP_SELECTING state? */ + else if ((msg_type == DHCP_OFFER) && (dhcp->state == DHCP_SELECTING)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_OFFER received in DHCP_SELECTING state\n")); + dhcp->request_timeout = 0; + /* remember offered lease */ + dhcp_handle_offer(netif); + } +free_pbuf_and_return: + dhcp->msg_in = NULL; + pbuf_free(p); +} + +/** + * Create a DHCP request, fill in common headers + * + * @param netif the netif under DHCP control + * @param dhcp dhcp control struct + * @param message_type message type of the request + */ +static err_t +dhcp_create_msg(struct netif *netif, struct dhcp *dhcp, u8_t message_type) +{ + u16_t i; +#ifndef DHCP_GLOBAL_XID + /** default global transaction identifier starting value (easy to match + * with a packet analyser). We simply increment for each new request. + * Predefine DHCP_GLOBAL_XID to a better value or a function call to generate one + * at runtime, any supporting function prototypes can be defined in DHCP_GLOBAL_XID_HEADER */ +#if DHCP_CREATE_RAND_XID && defined(LWIP_RAND) + static u32_t xid; +#else /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */ + static u32_t xid = 0xABCD0000; +#endif /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */ +#else + if (!xid_initialised) { + xid = DHCP_GLOBAL_XID; + xid_initialised = !xid_initialised; + } +#endif + LWIP_ERROR("dhcp_create_msg: netif != NULL", (netif != NULL), return ERR_ARG;); + LWIP_ERROR("dhcp_create_msg: dhcp != NULL", (dhcp != NULL), return ERR_VAL;); + LWIP_ASSERT("dhcp_create_msg: dhcp->p_out == NULL", dhcp->p_out == NULL); + LWIP_ASSERT("dhcp_create_msg: dhcp->msg_out == NULL", dhcp->msg_out == NULL); + dhcp->p_out = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcp_msg), PBUF_RAM); + if (dhcp->p_out == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("dhcp_create_msg(): could not allocate pbuf\n")); + return ERR_MEM; + } + LWIP_ASSERT("dhcp_create_msg: check that first pbuf can hold struct dhcp_msg", + (dhcp->p_out->len >= sizeof(struct dhcp_msg))); + + /* reuse transaction identifier in retransmissions */ + if (dhcp->tries == 0) { +#if DHCP_CREATE_RAND_XID && defined(LWIP_RAND) + xid = LWIP_RAND(); +#else /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */ + xid++; +#endif /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */ + } + dhcp->xid = xid; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, + ("transaction id xid(%"X32_F")\n", xid)); + + dhcp->msg_out = (struct dhcp_msg *)dhcp->p_out->payload; + + dhcp->msg_out->op = DHCP_BOOTREQUEST; + /* TODO: make link layer independent */ + dhcp->msg_out->htype = DHCP_HTYPE_ETH; + dhcp->msg_out->hlen = netif->hwaddr_len; + dhcp->msg_out->hops = 0; + dhcp->msg_out->xid = htonl(dhcp->xid); + dhcp->msg_out->secs = 0; + /* we don't need the broadcast flag since we can receive unicast traffic + before being fully configured! */ + dhcp->msg_out->flags = 0; + ip_addr_set_zero(&dhcp->msg_out->ciaddr); + /* set ciaddr to netif->ip_addr based on message_type and state */ + if ((message_type == DHCP_INFORM) || (message_type == DHCP_DECLINE) || + ((message_type == DHCP_REQUEST) && /* DHCP_BOUND not used for sending! */ + ((dhcp->state==DHCP_RENEWING) || dhcp->state==DHCP_REBINDING))) { + ip_addr_copy(dhcp->msg_out->ciaddr, netif->ip_addr); + } + ip_addr_set_zero(&dhcp->msg_out->yiaddr); + ip_addr_set_zero(&dhcp->msg_out->siaddr); + ip_addr_set_zero(&dhcp->msg_out->giaddr); + for (i = 0; i < DHCP_CHADDR_LEN; i++) { + /* copy netif hardware address, pad with zeroes */ + dhcp->msg_out->chaddr[i] = (i < netif->hwaddr_len) ? netif->hwaddr[i] : 0/* pad byte*/; + } + for (i = 0; i < DHCP_SNAME_LEN; i++) { + dhcp->msg_out->sname[i] = 0; + } + for (i = 0; i < DHCP_FILE_LEN; i++) { + dhcp->msg_out->file[i] = 0; + } + dhcp->msg_out->cookie = PP_HTONL(DHCP_MAGIC_COOKIE); + dhcp->options_out_len = 0; + /* fill options field with an incrementing array (for debugging purposes) */ + for (i = 0; i < DHCP_OPTIONS_LEN; i++) { + dhcp->msg_out->options[i] = (u8_t)i; /* for debugging only, no matter if truncated */ + } + /* Add option MESSAGE_TYPE */ + dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN); + dhcp_option_byte(dhcp, message_type); + return ERR_OK; +} + +/** + * Free previously allocated memory used to send a DHCP request. + * + * @param dhcp the dhcp struct to free the request from + */ +static void +dhcp_delete_msg(struct dhcp *dhcp) +{ + LWIP_ERROR("dhcp_delete_msg: dhcp != NULL", (dhcp != NULL), return;); + LWIP_ASSERT("dhcp_delete_msg: dhcp->p_out != NULL", dhcp->p_out != NULL); + LWIP_ASSERT("dhcp_delete_msg: dhcp->msg_out != NULL", dhcp->msg_out != NULL); + if (dhcp->p_out != NULL) { + pbuf_free(dhcp->p_out); + } + dhcp->p_out = NULL; + dhcp->msg_out = NULL; +} + +/** + * Add a DHCP message trailer + * + * Adds the END option to the DHCP message, and if + * necessary, up to three padding bytes. + * + * @param dhcp DHCP state structure + */ +static void +dhcp_option_trailer(struct dhcp *dhcp) +{ + LWIP_ERROR("dhcp_option_trailer: dhcp != NULL", (dhcp != NULL), return;); + LWIP_ASSERT("dhcp_option_trailer: dhcp->msg_out != NULL\n", dhcp->msg_out != NULL); + LWIP_ASSERT("dhcp_option_trailer: dhcp->options_out_len < DHCP_OPTIONS_LEN\n", dhcp->options_out_len < DHCP_OPTIONS_LEN); + dhcp->msg_out->options[dhcp->options_out_len++] = DHCP_OPTION_END; + /* packet is too small, or not 4 byte aligned? */ + while (((dhcp->options_out_len < DHCP_MIN_OPTIONS_LEN) || (dhcp->options_out_len & 3)) && + (dhcp->options_out_len < DHCP_OPTIONS_LEN)) { + /* add a fill/padding byte */ + dhcp->msg_out->options[dhcp->options_out_len++] = 0; + } +} + +#endif /* LWIP_DHCP */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/core/dns.c b/component/common/network/lwip/lwip_v1.4.1/src/core/dns.c new file mode 100644 index 0000000..d633612 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/core/dns.c @@ -0,0 +1,970 @@ +/** + * @file + * DNS - host name to IP address resolver. + * + */ + +/** + + * This file implements a DNS host name to IP address resolver. + + * Port to lwIP from uIP + * by Jim Pettinato April 2007 + + * uIP version Copyright (c) 2002-2003, Adam Dunkels. + * 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. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * + * DNS.C + * + * The lwIP DNS resolver functions are used to lookup a host name and + * map it to a numerical IP address. It maintains a list of resolved + * hostnames that can be queried with the dns_lookup() function. + * New hostnames can be resolved using the dns_query() function. + * + * The lwIP version of the resolver also adds a non-blocking version of + * gethostbyname() that will work with a raw API application. This function + * checks for an IP address string first and converts it if it is valid. + * gethostbyname() then does a dns_lookup() to see if the name is + * already in the table. If so, the IP is returned. If not, a query is + * issued and the function returns with a ERR_INPROGRESS status. The app + * using the dns client must then go into a waiting state. + * + * Once a hostname has been resolved (or found to be non-existent), + * the resolver code calls a specified callback function (which + * must be implemented by the module that uses the resolver). + */ + +/*----------------------------------------------------------------------------- + * RFC 1035 - Domain names - implementation and specification + * RFC 2181 - Clarifications to the DNS Specification + *----------------------------------------------------------------------------*/ + +/** @todo: define good default values (rfc compliance) */ +/** @todo: improve answer parsing, more checkings... */ +/** @todo: check RFC1035 - 7.3. Processing responses */ + +/*----------------------------------------------------------------------------- + * Includes + *----------------------------------------------------------------------------*/ + +#include "lwip/opt.h" + +#if LWIP_DNS /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/udp.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/dns.h" + +#include + +/** DNS server IP address */ +#ifndef DNS_SERVER_ADDRESS +#define DNS_SERVER_ADDRESS(ipaddr) (ip4_addr_set_u32(ipaddr, ipaddr_addr("208.67.222.222"))) /* resolver1.opendns.com */ +#endif + +/** DNS server port address */ +#ifndef DNS_SERVER_PORT +#define DNS_SERVER_PORT 53 +#endif + +/** DNS maximum number of retries when asking for a name, before "timeout". */ +#ifndef DNS_MAX_RETRIES +#define DNS_MAX_RETRIES 4 +#endif + +/** DNS resource record max. TTL (one week as default) */ +#ifndef DNS_MAX_TTL +#define DNS_MAX_TTL 604800 +#endif + +/* DNS protocol flags */ +#define DNS_FLAG1_RESPONSE 0x80 +#define DNS_FLAG1_OPCODE_STATUS 0x10 +#define DNS_FLAG1_OPCODE_INVERSE 0x08 +#define DNS_FLAG1_OPCODE_STANDARD 0x00 +#define DNS_FLAG1_AUTHORATIVE 0x04 +#define DNS_FLAG1_TRUNC 0x02 +#define DNS_FLAG1_RD 0x01 +#define DNS_FLAG2_RA 0x80 +#define DNS_FLAG2_ERR_MASK 0x0f +#define DNS_FLAG2_ERR_NONE 0x00 +#define DNS_FLAG2_ERR_NAME 0x03 + +/* DNS protocol states */ +#define DNS_STATE_UNUSED 0 +#define DNS_STATE_NEW 1 +#define DNS_STATE_ASKING 2 +#define DNS_STATE_DONE 3 + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** DNS message header */ +struct dns_hdr { + PACK_STRUCT_FIELD(u16_t id); + PACK_STRUCT_FIELD(u8_t flags1); + PACK_STRUCT_FIELD(u8_t flags2); + PACK_STRUCT_FIELD(u16_t numquestions); + PACK_STRUCT_FIELD(u16_t numanswers); + PACK_STRUCT_FIELD(u16_t numauthrr); + PACK_STRUCT_FIELD(u16_t numextrarr); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif +#define SIZEOF_DNS_HDR 12 + +/** DNS query message structure. + No packing needed: only used locally on the stack. */ +struct dns_query { + /* DNS query record starts with either a domain name or a pointer + to a name already present somewhere in the packet. */ + u16_t type; + u16_t cls; +}; +#define SIZEOF_DNS_QUERY 4 + +/** DNS answer message structure. + No packing needed: only used locally on the stack. */ +struct dns_answer { + /* DNS answer record starts with either a domain name or a pointer + to a name already present somewhere in the packet. */ + u16_t type; + u16_t cls; + u32_t ttl; + u16_t len; +}; +#define SIZEOF_DNS_ANSWER 10 + +/** DNS table entry */ +struct dns_table_entry { + u8_t state; + u8_t numdns; + u8_t tmr; + u8_t retries; + u8_t seqno; + u8_t err; + u32_t ttl; + char name[DNS_MAX_NAME_LENGTH]; + ip_addr_t ipaddr; + /* pointer to callback on DNS query done */ + dns_found_callback found; + void *arg; +}; + +#if DNS_LOCAL_HOSTLIST + +#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC +/** Local host-list. For hostnames in this list, no + * external name resolution is performed */ +static struct local_hostlist_entry *local_hostlist_dynamic; +#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + +/** Defining this allows the local_hostlist_static to be placed in a different + * linker section (e.g. FLASH) */ +#ifndef DNS_LOCAL_HOSTLIST_STORAGE_PRE +#define DNS_LOCAL_HOSTLIST_STORAGE_PRE static +#endif /* DNS_LOCAL_HOSTLIST_STORAGE_PRE */ +/** Defining this allows the local_hostlist_static to be placed in a different + * linker section (e.g. FLASH) */ +#ifndef DNS_LOCAL_HOSTLIST_STORAGE_POST +#define DNS_LOCAL_HOSTLIST_STORAGE_POST +#endif /* DNS_LOCAL_HOSTLIST_STORAGE_POST */ +DNS_LOCAL_HOSTLIST_STORAGE_PRE struct local_hostlist_entry local_hostlist_static[] + DNS_LOCAL_HOSTLIST_STORAGE_POST = DNS_LOCAL_HOSTLIST_INIT; + +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + +static void dns_init_local(); +#endif /* DNS_LOCAL_HOSTLIST */ + + +/* forward declarations */ +static void dns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port); +static void dns_check_entries(void); + +/*----------------------------------------------------------------------------- + * Globales + *----------------------------------------------------------------------------*/ + +/* DNS variables */ +static struct udp_pcb *dns_pcb; +static u8_t dns_seqno; +static struct dns_table_entry dns_table[DNS_TABLE_SIZE]; +static ip_addr_t dns_servers[DNS_MAX_SERVERS]; +/** Contiguous buffer for processing responses */ +static u8_t dns_payload_buffer[LWIP_MEM_ALIGN_BUFFER(DNS_MSG_SIZE)]; +static u8_t* dns_payload; + +/** + * Initialize the resolver: set up the UDP pcb and configure the default server + * (DNS_SERVER_ADDRESS). + */ +void +dns_init() +{ + ip_addr_t dnsserver; + + dns_payload = (u8_t *)LWIP_MEM_ALIGN(dns_payload_buffer); + + /* initialize default DNS server address */ + DNS_SERVER_ADDRESS(&dnsserver); + + LWIP_DEBUGF(DNS_DEBUG, ("dns_init: initializing\n")); + + /* if dns client not yet initialized... */ + if (dns_pcb == NULL) { + dns_pcb = udp_new(); + + if (dns_pcb != NULL) { + /* initialize DNS table not needed (initialized to zero since it is a + * global variable) */ + LWIP_ASSERT("For implicit initialization to work, DNS_STATE_UNUSED needs to be 0", + DNS_STATE_UNUSED == 0); + + /* initialize DNS client */ + udp_bind(dns_pcb, IP_ADDR_ANY, 0); + udp_recv(dns_pcb, dns_recv, NULL); + + /* initialize default DNS primary server */ + dns_setserver(0, &dnsserver); + } + } +#if DNS_LOCAL_HOSTLIST + dns_init_local(); +#endif +} + +/** + * Initialize one of the DNS servers. + * + * @param numdns the index of the DNS server to set must be < DNS_MAX_SERVERS + * @param dnsserver IP address of the DNS server to set + */ +void +dns_setserver(u8_t numdns, ip_addr_t *dnsserver) +{ + if ((numdns < DNS_MAX_SERVERS) && (dns_pcb != NULL) && + (dnsserver != NULL) && !ip_addr_isany(dnsserver)) { + dns_servers[numdns] = (*dnsserver); + } +} + +/** + * Obtain one of the currently configured DNS server. + * + * @param numdns the index of the DNS server + * @return IP address of the indexed DNS server or "ip_addr_any" if the DNS + * server has not been configured. + */ +ip_addr_t +dns_getserver(u8_t numdns) +{ + if (numdns < DNS_MAX_SERVERS) { + return dns_servers[numdns]; + } else { + return *IP_ADDR_ANY; + } +} + +/** + * The DNS resolver client timer - handle retries and timeouts and should + * be called every DNS_TMR_INTERVAL milliseconds (every second by default). + */ +void +dns_tmr(void) +{ + if (dns_pcb != NULL) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_tmr: dns_check_entries\n")); + dns_check_entries(); + } +} + +#if DNS_LOCAL_HOSTLIST +static void +dns_init_local() +{ +#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT) + int i; + struct local_hostlist_entry *entry; + /* Dynamic: copy entries from DNS_LOCAL_HOSTLIST_INIT to list */ + struct local_hostlist_entry local_hostlist_init[] = DNS_LOCAL_HOSTLIST_INIT; + size_t namelen; + for (i = 0; i < sizeof(local_hostlist_init) / sizeof(struct local_hostlist_entry); i++) { + struct local_hostlist_entry *init_entry = &local_hostlist_init[i]; + LWIP_ASSERT("invalid host name (NULL)", init_entry->name != NULL); + namelen = strlen(init_entry->name); + LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN); + entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST); + LWIP_ASSERT("mem-error in dns_init_local", entry != NULL); + if (entry != NULL) { + entry->name = (char*)entry + sizeof(struct local_hostlist_entry); + MEMCPY((char*)entry->name, init_entry->name, namelen); + ((char*)entry->name)[namelen] = 0; + entry->addr = init_entry->addr; + entry->next = local_hostlist_dynamic; + local_hostlist_dynamic = entry; + } + } +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT) */ +} + +/** + * Scans the local host-list for a hostname. + * + * @param hostname Hostname to look for in the local host-list + * @return The first IP address for the hostname in the local host-list or + * IPADDR_NONE if not found. + */ +static u32_t +dns_lookup_local(const char *hostname) +{ +#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC + struct local_hostlist_entry *entry = local_hostlist_dynamic; + while(entry != NULL) { + if(strcmp(entry->name, hostname) == 0) { + return ip4_addr_get_u32(&entry->addr); + } + entry = entry->next; + } +#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + int i; + for (i = 0; i < sizeof(local_hostlist_static) / sizeof(struct local_hostlist_entry); i++) { + if(strcmp(local_hostlist_static[i].name, hostname) == 0) { + return ip4_addr_get_u32(&local_hostlist_static[i].addr); + } + } +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + return IPADDR_NONE; +} + +#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC +/** Remove all entries from the local host-list for a specific hostname + * and/or IP addess + * + * @param hostname hostname for which entries shall be removed from the local + * host-list + * @param addr address for which entries shall be removed from the local host-list + * @return the number of removed entries + */ +int +dns_local_removehost(const char *hostname, const ip_addr_t *addr) +{ + int removed = 0; + struct local_hostlist_entry *entry = local_hostlist_dynamic; + struct local_hostlist_entry *last_entry = NULL; + while (entry != NULL) { + if (((hostname == NULL) || !strcmp(entry->name, hostname)) && + ((addr == NULL) || ip_addr_cmp(&entry->addr, addr))) { + struct local_hostlist_entry *free_entry; + if (last_entry != NULL) { + last_entry->next = entry->next; + } else { + local_hostlist_dynamic = entry->next; + } + free_entry = entry; + entry = entry->next; + memp_free(MEMP_LOCALHOSTLIST, free_entry); + removed++; + } else { + last_entry = entry; + entry = entry->next; + } + } + return removed; +} + +/** + * Add a hostname/IP address pair to the local host-list. + * Duplicates are not checked. + * + * @param hostname hostname of the new entry + * @param addr IP address of the new entry + * @return ERR_OK if succeeded or ERR_MEM on memory error + */ +err_t +dns_local_addhost(const char *hostname, const ip_addr_t *addr) +{ + struct local_hostlist_entry *entry; + size_t namelen; + LWIP_ASSERT("invalid host name (NULL)", hostname != NULL); + namelen = strlen(hostname); + LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN); + entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST); + if (entry == NULL) { + return ERR_MEM; + } + entry->name = (char*)entry + sizeof(struct local_hostlist_entry); + MEMCPY((char*)entry->name, hostname, namelen); + ((char*)entry->name)[namelen] = 0; + ip_addr_copy(entry->addr, *addr); + entry->next = local_hostlist_dynamic; + local_hostlist_dynamic = entry; + return ERR_OK; +} +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC*/ +#endif /* DNS_LOCAL_HOSTLIST */ + +/** + * Look up a hostname in the array of known hostnames. + * + * @note This function only looks in the internal array of known + * hostnames, it does not send out a query for the hostname if none + * was found. The function dns_enqueue() can be used to send a query + * for a hostname. + * + * @param name the hostname to look up + * @return the hostname's IP address, as u32_t (instead of ip_addr_t to + * better check for failure: != IPADDR_NONE) or IPADDR_NONE if the hostname + * was not found in the cached dns_table. + */ +static u32_t +dns_lookup(const char *name) +{ + u8_t i; +#if DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN) + u32_t addr; +#endif /* DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN) */ +#if DNS_LOCAL_HOSTLIST + if ((addr = dns_lookup_local(name)) != IPADDR_NONE) { + return addr; + } +#endif /* DNS_LOCAL_HOSTLIST */ +#ifdef DNS_LOOKUP_LOCAL_EXTERN + if((addr = DNS_LOOKUP_LOCAL_EXTERN(name)) != IPADDR_NONE) { + return addr; + } +#endif /* DNS_LOOKUP_LOCAL_EXTERN */ + + /* Walk through name list, return entry if found. If not, return NULL. */ + for (i = 0; i < DNS_TABLE_SIZE; ++i) { + if ((dns_table[i].state == DNS_STATE_DONE) && + (strcmp(name, dns_table[i].name) == 0)) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_lookup: \"%s\": found = ", name)); + ip_addr_debug_print(DNS_DEBUG, &(dns_table[i].ipaddr)); + LWIP_DEBUGF(DNS_DEBUG, ("\n")); + return ip4_addr_get_u32(&dns_table[i].ipaddr); + } + } + + return IPADDR_NONE; +} + +#if DNS_DOES_NAME_CHECK +/** + * Compare the "dotted" name "query" with the encoded name "response" + * to make sure an answer from the DNS server matches the current dns_table + * entry (otherwise, answers might arrive late for hostname not on the list + * any more). + * + * @param query hostname (not encoded) from the dns_table + * @param response encoded hostname in the DNS response + * @return 0: names equal; 1: names differ + */ +static u8_t +dns_compare_name(unsigned char *query, unsigned char *response) +{ + unsigned char n; + + do { + n = *response++; + /** @see RFC 1035 - 4.1.4. Message compression */ + if ((n & 0xc0) == 0xc0) { + /* Compressed name */ + break; + } else { + /* Not compressed name */ + while (n > 0) { + if ((*query) != (*response)) { + return 1; + } + ++response; + ++query; + --n; + }; + ++query; + } + } while (*response != 0); + + return 0; +} +#endif /* DNS_DOES_NAME_CHECK */ + +/** + * Walk through a compact encoded DNS name and return the end of the name. + * + * @param query encoded DNS name in the DNS server response + * @return end of the name + */ +static unsigned char * +dns_parse_name(unsigned char *query) +{ + unsigned char n; + + do { + n = *query++; + /** @see RFC 1035 - 4.1.4. Message compression */ + if ((n & 0xc0) == 0xc0) { + /* Compressed name */ + break; + } else { + /* Not compressed name */ + while (n > 0) { + ++query; + --n; + }; + } + } while (*query != 0); + + return query + 1; +} + +/** + * Send a DNS query packet. + * + * @param numdns index of the DNS server in the dns_servers table + * @param name hostname to query + * @param id index of the hostname in dns_table, used as transaction ID in the + * DNS query packet + * @return ERR_OK if packet is sent; an err_t indicating the problem otherwise + */ +static err_t +dns_send(u8_t numdns, const char* name, u8_t id) +{ + err_t err; + struct dns_hdr *hdr; + struct dns_query qry; + struct pbuf *p; + char *query, *nptr; + const char *pHostname; + u8_t n; + + LWIP_DEBUGF(DNS_DEBUG, ("dns_send: dns_servers[%"U16_F"] \"%s\": request\n", + (u16_t)(numdns), name)); + LWIP_ASSERT("dns server out of array", numdns < DNS_MAX_SERVERS); + LWIP_ASSERT("dns server has no IP address set", !ip_addr_isany(&dns_servers[numdns])); + + /* if here, we have either a new query or a retry on a previous query to process */ + p = pbuf_alloc(PBUF_TRANSPORT, SIZEOF_DNS_HDR + DNS_MAX_NAME_LENGTH + + SIZEOF_DNS_QUERY, PBUF_RAM); + if (p != NULL) { + LWIP_ASSERT("pbuf must be in one piece", p->next == NULL); + /* fill dns header */ + hdr = (struct dns_hdr*)p->payload; + memset(hdr, 0, SIZEOF_DNS_HDR); + hdr->id = htons(id); + hdr->flags1 = DNS_FLAG1_RD; + hdr->numquestions = PP_HTONS(1); + query = (char*)hdr + SIZEOF_DNS_HDR; + pHostname = name; + --pHostname; + + /* convert hostname into suitable query format. */ + do { + ++pHostname; + nptr = query; + ++query; + for(n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) { + *query = *pHostname; + ++query; + ++n; + } + *nptr = n; + } while(*pHostname != 0); + *query++='\0'; + + /* fill dns query */ + qry.type = PP_HTONS(DNS_RRTYPE_A); + qry.cls = PP_HTONS(DNS_RRCLASS_IN); + SMEMCPY(query, &qry, SIZEOF_DNS_QUERY); + + /* resize pbuf to the exact dns query */ + pbuf_realloc(p, (u16_t)((query + SIZEOF_DNS_QUERY) - ((char*)(p->payload)))); + + /* connect to the server for faster receiving */ + udp_connect(dns_pcb, &dns_servers[numdns], DNS_SERVER_PORT); + /* send dns packet */ + err = udp_sendto(dns_pcb, p, &dns_servers[numdns], DNS_SERVER_PORT); + + /* free pbuf */ + pbuf_free(p); + } else { + err = ERR_MEM; + } + + return err; +} + +/** + * dns_check_entry() - see if pEntry has not yet been queried and, if so, sends out a query. + * Check an entry in the dns_table: + * - send out query for new entries + * - retry old pending entries on timeout (also with different servers) + * - remove completed entries from the table if their TTL has expired + * + * @param i index of the dns_table entry to check + */ +static void +dns_check_entry(u8_t i) +{ + err_t err; + struct dns_table_entry *pEntry = &dns_table[i]; + + LWIP_ASSERT("array index out of bounds", i < DNS_TABLE_SIZE); + + switch(pEntry->state) { + + case DNS_STATE_NEW: { + /* initialize new entry */ + pEntry->state = DNS_STATE_ASKING; + pEntry->numdns = 0; + pEntry->tmr = 1; + pEntry->retries = 0; + + /* send DNS packet for this entry */ + err = dns_send(pEntry->numdns, pEntry->name, i); + if (err != ERR_OK) { + LWIP_DEBUGF(DNS_DEBUG | LWIP_DBG_LEVEL_WARNING, + ("dns_send returned error: %s\n", lwip_strerr(err))); + } + break; + } + + case DNS_STATE_ASKING: { + if (--pEntry->tmr == 0) { + if (++pEntry->retries == DNS_MAX_RETRIES) { + if ((pEntry->numdns+1numdns+1])) { + /* change of server */ + pEntry->numdns++; + pEntry->tmr = 1; + pEntry->retries = 0; + break; + } else { + LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": timeout\n", pEntry->name)); + /* call specified callback function if provided */ + if (pEntry->found) + (*pEntry->found)(pEntry->name, NULL, pEntry->arg); + /* flush this entry */ + pEntry->state = DNS_STATE_UNUSED; + pEntry->found = NULL; + break; + } + } + + /* wait longer for the next retry */ + pEntry->tmr = pEntry->retries; + + /* send DNS packet for this entry */ + err = dns_send(pEntry->numdns, pEntry->name, i); + if (err != ERR_OK) { + LWIP_DEBUGF(DNS_DEBUG | LWIP_DBG_LEVEL_WARNING, + ("dns_send returned error: %s\n", lwip_strerr(err))); + } + } + break; + } + + case DNS_STATE_DONE: { + /* if the time to live is nul */ + if (--pEntry->ttl == 0) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": flush\n", pEntry->name)); + /* flush this entry */ + pEntry->state = DNS_STATE_UNUSED; + pEntry->found = NULL; + } + break; + } + case DNS_STATE_UNUSED: + /* nothing to do */ + break; + default: + LWIP_ASSERT("unknown dns_table entry state:", 0); + break; + } +} + +/** + * Call dns_check_entry for each entry in dns_table - check all entries. + */ +static void +dns_check_entries(void) +{ + u8_t i; + + for (i = 0; i < DNS_TABLE_SIZE; ++i) { + dns_check_entry(i); + } +} + +/** + * Receive input function for DNS response packets arriving for the dns UDP pcb. + * + * @params see udp.h + */ +static void +dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port) +{ + u16_t i; + char *pHostname; + struct dns_hdr *hdr; + struct dns_answer ans; + struct dns_table_entry *pEntry; + u16_t nquestions, nanswers; + + LWIP_UNUSED_ARG(arg); + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(addr); + LWIP_UNUSED_ARG(port); + + /* is the dns message too big ? */ + if (p->tot_len > DNS_MSG_SIZE) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too big\n")); + /* free pbuf and return */ + goto memerr; + } + + /* is the dns message big enough ? */ + if (p->tot_len < (SIZEOF_DNS_HDR + SIZEOF_DNS_QUERY + SIZEOF_DNS_ANSWER)) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too small\n")); + /* free pbuf and return */ + goto memerr; + } + + /* copy dns payload inside static buffer for processing */ + if (pbuf_copy_partial(p, dns_payload, p->tot_len, 0) == p->tot_len) { + /* The ID in the DNS header should be our entry into the name table. */ + hdr = (struct dns_hdr*)dns_payload; + i = htons(hdr->id); + if (i < DNS_TABLE_SIZE) { + pEntry = &dns_table[i]; + if(pEntry->state == DNS_STATE_ASKING) { + /* This entry is now completed. */ + pEntry->state = DNS_STATE_DONE; + pEntry->err = hdr->flags2 & DNS_FLAG2_ERR_MASK; + + /* We only care about the question(s) and the answers. The authrr + and the extrarr are simply discarded. */ + nquestions = htons(hdr->numquestions); + nanswers = htons(hdr->numanswers); + + /* Check for error. If so, call callback to inform. */ + if (((hdr->flags1 & DNS_FLAG1_RESPONSE) == 0) || (pEntry->err != 0) || (nquestions != 1)) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in flags\n", pEntry->name)); + /* call callback to indicate error, clean up memory and return */ + goto responseerr; + } + +#if DNS_DOES_NAME_CHECK + /* Check if the name in the "question" part match with the name in the entry. */ + if (dns_compare_name((unsigned char *)(pEntry->name), (unsigned char *)dns_payload + SIZEOF_DNS_HDR) != 0) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", pEntry->name)); + /* call callback to indicate error, clean up memory and return */ + goto responseerr; + } +#endif /* DNS_DOES_NAME_CHECK */ + + /* Skip the name in the "question" part */ + pHostname = (char *) dns_parse_name((unsigned char *)dns_payload + SIZEOF_DNS_HDR) + SIZEOF_DNS_QUERY; + + while (nanswers > 0) { + /* skip answer resource record's host name */ + pHostname = (char *) dns_parse_name((unsigned char *)pHostname); + + /* Check for IP address type and Internet class. Others are discarded. */ + SMEMCPY(&ans, pHostname, SIZEOF_DNS_ANSWER); + if((ans.type == PP_HTONS(DNS_RRTYPE_A)) && (ans.cls == PP_HTONS(DNS_RRCLASS_IN)) && + (ans.len == PP_HTONS(sizeof(ip_addr_t))) ) { + /* read the answer resource record's TTL, and maximize it if needed */ + pEntry->ttl = ntohl(ans.ttl); + if (pEntry->ttl > DNS_MAX_TTL) { + pEntry->ttl = DNS_MAX_TTL; + } + /* read the IP address after answer resource record's header */ + SMEMCPY(&(pEntry->ipaddr), (pHostname+SIZEOF_DNS_ANSWER), sizeof(ip_addr_t)); + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response = ", pEntry->name)); + ip_addr_debug_print(DNS_DEBUG, (&(pEntry->ipaddr))); + LWIP_DEBUGF(DNS_DEBUG, ("\n")); + /* call specified callback function if provided */ + if (pEntry->found) { + (*pEntry->found)(pEntry->name, &pEntry->ipaddr, pEntry->arg); + } + /* deallocate memory and return */ + goto memerr; + } else { + pHostname = pHostname + SIZEOF_DNS_ANSWER + htons(ans.len); + } + --nanswers; + } + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in response\n", pEntry->name)); + /* call callback to indicate error, clean up memory and return */ + goto responseerr; + } + } + } + + /* deallocate memory and return */ + goto memerr; + +responseerr: + /* ERROR: call specified callback function with NULL as name to indicate an error */ + if (pEntry->found) { + (*pEntry->found)(pEntry->name, NULL, pEntry->arg); + } + /* flush this entry */ + pEntry->state = DNS_STATE_UNUSED; + pEntry->found = NULL; + +memerr: + /* free pbuf */ + pbuf_free(p); + return; +} + +/** + * Queues a new hostname to resolve and sends out a DNS query for that hostname + * + * @param name the hostname that is to be queried + * @param found a callback founction to be called on success, failure or timeout + * @param callback_arg argument to pass to the callback function + * @return @return a err_t return code. + */ +static err_t +dns_enqueue(const char *name, dns_found_callback found, void *callback_arg) +{ + u8_t i; + u8_t lseq, lseqi; + struct dns_table_entry *pEntry = NULL; + size_t namelen; + + /* search an unused entry, or the oldest one */ + lseq = lseqi = 0; + for (i = 0; i < DNS_TABLE_SIZE; ++i) { + pEntry = &dns_table[i]; + /* is it an unused entry ? */ + if (pEntry->state == DNS_STATE_UNUSED) + break; + + /* check if this is the oldest completed entry */ + if (pEntry->state == DNS_STATE_DONE) { + if ((dns_seqno - pEntry->seqno) > lseq) { + lseq = dns_seqno - pEntry->seqno; + lseqi = i; + } + } + } + + /* if we don't have found an unused entry, use the oldest completed one */ + if (i == DNS_TABLE_SIZE) { + if ((lseqi >= DNS_TABLE_SIZE) || (dns_table[lseqi].state != DNS_STATE_DONE)) { + /* no entry can't be used now, table is full */ + LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": DNS entries table is full\n", name)); + return ERR_MEM; + } else { + /* use the oldest completed one */ + i = lseqi; + pEntry = &dns_table[i]; + } + } + + /* use this entry */ + LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": use DNS entry %"U16_F"\n", name, (u16_t)(i))); + + /* fill the entry */ + pEntry->state = DNS_STATE_NEW; + pEntry->seqno = dns_seqno++; + pEntry->found = found; + pEntry->arg = callback_arg; + namelen = LWIP_MIN(strlen(name), DNS_MAX_NAME_LENGTH-1); + MEMCPY(pEntry->name, name, namelen); + pEntry->name[namelen] = 0; + + /* force to send query without waiting timer */ + dns_check_entry(i); + + /* dns query is enqueued */ + return ERR_INPROGRESS; +} + +/** + * Resolve a hostname (string) into an IP address. + * NON-BLOCKING callback version for use with raw API!!! + * + * Returns immediately with one of err_t return codes: + * - ERR_OK if hostname is a valid IP address string or the host + * name is already in the local names table. + * - ERR_INPROGRESS enqueue a request to be sent to the DNS server + * for resolution if no errors are present. + * - ERR_ARG: dns client not initialized or invalid hostname + * + * @param hostname the hostname that is to be queried + * @param addr pointer to a ip_addr_t where to store the address if it is already + * cached in the dns_table (only valid if ERR_OK is returned!) + * @param found a callback function to be called on success, failure or timeout (only if + * ERR_INPROGRESS is returned!) + * @param callback_arg argument to pass to the callback function + * @return a err_t return code. + */ +err_t +dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback found, + void *callback_arg) +{ + u32_t ipaddr; + /* not initialized or no valid server yet, or invalid addr pointer + * or invalid hostname or invalid hostname length */ + if ((dns_pcb == NULL) || (addr == NULL) || + (!hostname) || (!hostname[0]) || + (strlen(hostname) >= DNS_MAX_NAME_LENGTH)) { + return ERR_ARG; + } + +#if LWIP_HAVE_LOOPIF + if (strcmp(hostname, "localhost")==0) { + ip_addr_set_loopback(addr); + return ERR_OK; + } +#endif /* LWIP_HAVE_LOOPIF */ + + /* host name already in octet notation? set ip addr and return ERR_OK */ + ipaddr = ipaddr_addr(hostname); + if (ipaddr == IPADDR_NONE) { + /* already have this address cached? */ + ipaddr = dns_lookup(hostname); + } + if (ipaddr != IPADDR_NONE) { + ip4_addr_set_u32(addr, ipaddr); + return ERR_OK; + } + + /* queue query with specified callback */ + return dns_enqueue(hostname, found, callback_arg); +} + +#endif /* LWIP_DNS */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/core/init.c b/component/common/network/lwip/lwip_v1.4.1/src/core/init.c new file mode 100644 index 0000000..8aea49d --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/core/init.c @@ -0,0 +1,332 @@ +/** + * @file + * Modules initialization + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/init.h" +#include "lwip/stats.h" +#include "lwip/sys.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/sockets.h" +#include "lwip/ip.h" +#include "lwip/raw.h" +#include "lwip/udp.h" +#include "lwip/tcp_impl.h" +#include "lwip/snmp_msg.h" +#include "lwip/autoip.h" +#include "lwip/igmp.h" +#include "lwip/dns.h" +#include "lwip/lwip_timers.h" +#include "netif/etharp.h" +#include "lwip/api.h" + +/* Compile-time sanity checks for configuration errors. + * These can be done independently of LWIP_DEBUG, without penalty. + */ +#ifndef BYTE_ORDER + #error "BYTE_ORDER is not defined, you have to define it in your cc.h" +#endif +#if (!IP_SOF_BROADCAST && IP_SOF_BROADCAST_RECV) + #error "If you want to use broadcast filter per pcb on recv operations, you have to define IP_SOF_BROADCAST=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_UDPLITE) + #error "If you want to use UDP Lite, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_SNMP) + #error "If you want to use SNMP, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_DHCP) + #error "If you want to use DHCP, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_IGMP) + #error "If you want to use IGMP, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_SNMP) + #error "If you want to use SNMP, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_DNS) + #error "If you want to use DNS, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif +#if !MEMP_MEM_MALLOC /* MEMP_NUM_* checks are disabled when not using the pool allocator */ +#if (LWIP_ARP && ARP_QUEUEING && (MEMP_NUM_ARP_QUEUE<=0)) + #error "If you want to use ARP Queueing, you have to define MEMP_NUM_ARP_QUEUE>=1 in your lwipopts.h" +#endif +#if (LWIP_RAW && (MEMP_NUM_RAW_PCB<=0)) + #error "If you want to use RAW, you have to define MEMP_NUM_RAW_PCB>=1 in your lwipopts.h" +#endif +#if (LWIP_UDP && (MEMP_NUM_UDP_PCB<=0)) + #error "If you want to use UDP, you have to define MEMP_NUM_UDP_PCB>=1 in your lwipopts.h" +#endif +#if (LWIP_TCP && (MEMP_NUM_TCP_PCB<=0)) + #error "If you want to use TCP, you have to define MEMP_NUM_TCP_PCB>=1 in your lwipopts.h" +#endif +#if (LWIP_IGMP && (MEMP_NUM_IGMP_GROUP<=1)) + #error "If you want to use IGMP, you have to define MEMP_NUM_IGMP_GROUP>1 in your lwipopts.h" +#endif +#if ((LWIP_NETCONN || LWIP_SOCKET) && (MEMP_NUM_TCPIP_MSG_API<=0)) + #error "If you want to use Sequential API, you have to define MEMP_NUM_TCPIP_MSG_API>=1 in your lwipopts.h" +#endif +/* There must be sufficient timeouts, taking into account requirements of the subsystems. */ +#if LWIP_TIMERS && (MEMP_NUM_SYS_TIMEOUT < (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + PPP_SUPPORT)) + #error "MEMP_NUM_SYS_TIMEOUT is too low to accomodate all required timeouts" +#endif +#if (IP_REASSEMBLY && (MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS)) + #error "MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS doesn't make sense since each struct ip_reassdata must hold 2 pbufs at least!" +#endif +#endif /* !MEMP_MEM_MALLOC */ +#if (LWIP_TCP && (TCP_WND > 0xffff)) + #error "If you want to use TCP, TCP_WND must fit in an u16_t, so, you have to reduce it in your lwipopts.h" +#endif +#if (LWIP_TCP && (TCP_SND_QUEUELEN > 0xffff)) + #error "If you want to use TCP, TCP_SND_QUEUELEN must fit in an u16_t, so, you have to reduce it in your lwipopts.h" +#endif +#if (LWIP_TCP && (TCP_SND_QUEUELEN < 2)) + #error "TCP_SND_QUEUELEN must be at least 2 for no-copy TCP writes to work" +#endif +#if (LWIP_TCP && ((TCP_MAXRTX > 12) || (TCP_SYNMAXRTX > 12))) + #error "If you want to use TCP, TCP_MAXRTX and TCP_SYNMAXRTX must less or equal to 12 (due to tcp_backoff table), so, you have to reduce them in your lwipopts.h" +#endif +#if (LWIP_TCP && TCP_LISTEN_BACKLOG && (TCP_DEFAULT_LISTEN_BACKLOG < 0) || (TCP_DEFAULT_LISTEN_BACKLOG > 0xff)) + #error "If you want to use TCP backlog, TCP_DEFAULT_LISTEN_BACKLOG must fit into an u8_t" +#endif +#if (LWIP_NETIF_API && (NO_SYS==1)) + #error "If you want to use NETIF API, you have to define NO_SYS=0 in your lwipopts.h" +#endif +#if ((LWIP_SOCKET || LWIP_NETCONN) && (NO_SYS==1)) + #error "If you want to use Sequential API, you have to define NO_SYS=0 in your lwipopts.h" +#endif +#if (!LWIP_NETCONN && LWIP_SOCKET) + #error "If you want to use Socket API, you have to define LWIP_NETCONN=1 in your lwipopts.h" +#endif +#if (((!LWIP_DHCP) || (!LWIP_AUTOIP)) && LWIP_DHCP_AUTOIP_COOP) + #error "If you want to use DHCP/AUTOIP cooperation mode, you have to define LWIP_DHCP=1 and LWIP_AUTOIP=1 in your lwipopts.h" +#endif +#if (((!LWIP_DHCP) || (!LWIP_ARP)) && DHCP_DOES_ARP_CHECK) + #error "If you want to use DHCP ARP checking, you have to define LWIP_DHCP=1 and LWIP_ARP=1 in your lwipopts.h" +#endif +#if (!LWIP_ARP && LWIP_AUTOIP) + #error "If you want to use AUTOIP, you have to define LWIP_ARP=1 in your lwipopts.h" +#endif +#if (LWIP_SNMP && (SNMP_CONCURRENT_REQUESTS<=0)) + #error "If you want to use SNMP, you have to define SNMP_CONCURRENT_REQUESTS>=1 in your lwipopts.h" +#endif +#if (LWIP_SNMP && (SNMP_TRAP_DESTINATIONS<=0)) + #error "If you want to use SNMP, you have to define SNMP_TRAP_DESTINATIONS>=1 in your lwipopts.h" +#endif +#if (LWIP_TCP && ((LWIP_EVENT_API && LWIP_CALLBACK_API) || (!LWIP_EVENT_API && !LWIP_CALLBACK_API))) + #error "One and exactly one of LWIP_EVENT_API and LWIP_CALLBACK_API has to be enabled in your lwipopts.h" +#endif +#if (MEM_LIBC_MALLOC && MEM_USE_POOLS) + #error "MEM_LIBC_MALLOC and MEM_USE_POOLS may not both be simultaneously enabled in your lwipopts.h" +#endif +#if (MEM_USE_POOLS && !MEMP_USE_CUSTOM_POOLS) + #error "MEM_USE_POOLS requires custom pools (MEMP_USE_CUSTOM_POOLS) to be enabled in your lwipopts.h" +#endif +#if (PBUF_POOL_BUFSIZE <= MEM_ALIGNMENT) + #error "PBUF_POOL_BUFSIZE must be greater than MEM_ALIGNMENT or the offset may take the full first pbuf" +#endif +#if (DNS_LOCAL_HOSTLIST && !DNS_LOCAL_HOSTLIST_IS_DYNAMIC && !(defined(DNS_LOCAL_HOSTLIST_INIT))) + #error "you have to define define DNS_LOCAL_HOSTLIST_INIT {{'host1', 0x123}, {'host2', 0x234}} to initialize DNS_LOCAL_HOSTLIST" +#endif +#if PPP_SUPPORT && !PPPOS_SUPPORT & !PPPOE_SUPPORT + #error "PPP_SUPPORT needs either PPPOS_SUPPORT or PPPOE_SUPPORT turned on" +#endif +#if !LWIP_ETHERNET && (LWIP_ARP || PPPOE_SUPPORT) + #error "LWIP_ETHERNET needs to be turned on for LWIP_ARP or PPPOE_SUPPORT" +#endif +#if LWIP_IGMP && !defined(LWIP_RAND) + #error "When using IGMP, LWIP_RAND() needs to be defined to a random-function returning an u32_t random value" +#endif +#if LWIP_TCPIP_CORE_LOCKING_INPUT && !LWIP_TCPIP_CORE_LOCKING + #error "When using LWIP_TCPIP_CORE_LOCKING_INPUT, LWIP_TCPIP_CORE_LOCKING must be enabled, too" +#endif +#if LWIP_TCP && LWIP_NETIF_TX_SINGLE_PBUF && !TCP_OVERSIZE + #error "LWIP_NETIF_TX_SINGLE_PBUF needs TCP_OVERSIZE enabled to create single-pbuf TCP packets" +#endif +#if IP_FRAG && IP_FRAG_USES_STATIC_BUF && LWIP_NETIF_TX_SINGLE_PBUF + #error "LWIP_NETIF_TX_SINGLE_PBUF does not work with IP_FRAG_USES_STATIC_BUF==1 as that creates pbuf queues" +#endif +#if LWIP_NETCONN && LWIP_TCP +#if NETCONN_COPY != TCP_WRITE_FLAG_COPY + #error "NETCONN_COPY != TCP_WRITE_FLAG_COPY" +#endif +#if NETCONN_MORE != TCP_WRITE_FLAG_MORE + #error "NETCONN_MORE != TCP_WRITE_FLAG_MORE" +#endif +#endif /* LWIP_NETCONN && LWIP_TCP */ +#if LWIP_SOCKET +/* Check that the SO_* socket options and SOF_* lwIP-internal flags match */ +#if SO_ACCEPTCONN != SOF_ACCEPTCONN + #error "SO_ACCEPTCONN != SOF_ACCEPTCONN" +#endif +#if SO_REUSEADDR != SOF_REUSEADDR + #error "WARNING: SO_REUSEADDR != SOF_REUSEADDR" +#endif +#if SO_KEEPALIVE != SOF_KEEPALIVE + #error "WARNING: SO_KEEPALIVE != SOF_KEEPALIVE" +#endif +#if SO_BROADCAST != SOF_BROADCAST + #error "WARNING: SO_BROADCAST != SOF_BROADCAST" +#endif +#if SO_LINGER != SOF_LINGER + #error "WARNING: SO_LINGER != SOF_LINGER" +#endif +#endif /* LWIP_SOCKET */ + + +/* Compile-time checks for deprecated options. + */ +#ifdef MEMP_NUM_TCPIP_MSG + #error "MEMP_NUM_TCPIP_MSG option is deprecated. Remove it from your lwipopts.h." +#endif +#ifdef MEMP_NUM_API_MSG + #error "MEMP_NUM_API_MSG option is deprecated. Remove it from your lwipopts.h." +#endif +#ifdef TCP_REXMIT_DEBUG + #error "TCP_REXMIT_DEBUG option is deprecated. Remove it from your lwipopts.h." +#endif +#ifdef RAW_STATS + #error "RAW_STATS option is deprecated. Remove it from your lwipopts.h." +#endif +#ifdef ETHARP_QUEUE_FIRST + #error "ETHARP_QUEUE_FIRST option is deprecated. Remove it from your lwipopts.h." +#endif +#ifdef ETHARP_ALWAYS_INSERT + #error "ETHARP_ALWAYS_INSERT option is deprecated. Remove it from your lwipopts.h." +#endif + +#ifndef LWIP_DISABLE_TCP_SANITY_CHECKS +#define LWIP_DISABLE_TCP_SANITY_CHECKS 0 +#endif +#ifndef LWIP_DISABLE_MEMP_SANITY_CHECKS +#define LWIP_DISABLE_MEMP_SANITY_CHECKS 0 +#endif + +/* MEMP sanity checks */ +#if !LWIP_DISABLE_MEMP_SANITY_CHECKS +#if LWIP_NETCONN +#if MEMP_MEM_MALLOC +#if !MEMP_NUM_NETCONN && LWIP_SOCKET +#error "lwip_sanity_check: WARNING: MEMP_NUM_NETCONN cannot be 0 when using sockets!" +#endif +#else /* MEMP_MEM_MALLOC */ +#if MEMP_NUM_NETCONN > (MEMP_NUM_TCP_PCB+MEMP_NUM_TCP_PCB_LISTEN+MEMP_NUM_UDP_PCB+MEMP_NUM_RAW_PCB) +#error "lwip_sanity_check: WARNING: MEMP_NUM_NETCONN should be less than the sum of MEMP_NUM_{TCP,RAW,UDP}_PCB+MEMP_NUM_TCP_PCB_LISTEN. If you know what you are doing, define LWIP_DISABLE_MEMP_SANITY_CHECKS to 1 to disable this error." +#endif +#endif /* MEMP_MEM_MALLOC */ +#endif /* LWIP_NETCONN */ +#endif /* !LWIP_DISABLE_MEMP_SANITY_CHECKS */ + +/* TCP sanity checks */ +#if !LWIP_DISABLE_TCP_SANITY_CHECKS +#if LWIP_TCP +#if !MEMP_MEM_MALLOC && (MEMP_NUM_TCP_SEG < TCP_SND_QUEUELEN) + #error "lwip_sanity_check: WARNING: MEMP_NUM_TCP_SEG should be at least as big as TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if TCP_SND_BUF < (2 * TCP_MSS) + #error "lwip_sanity_check: WARNING: TCP_SND_BUF must be at least as much as (2 * TCP_MSS) for things to work smoothly. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if TCP_SND_QUEUELEN < (2 * (TCP_SND_BUF / TCP_MSS)) + #error "lwip_sanity_check: WARNING: TCP_SND_QUEUELEN must be at least as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if TCP_SNDLOWAT >= TCP_SND_BUF + #error "lwip_sanity_check: WARNING: TCP_SNDLOWAT must be less than TCP_SND_BUF. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if TCP_SNDQUEUELOWAT >= TCP_SND_QUEUELEN + #error "lwip_sanity_check: WARNING: TCP_SNDQUEUELOWAT must be less than TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if !MEMP_MEM_MALLOC && (TCP_WND > (PBUF_POOL_SIZE * (PBUF_POOL_BUFSIZE - (PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)))) + #error "lwip_sanity_check: WARNING: TCP_WND is larger than space provided by PBUF_POOL_SIZE * (PBUF_POOL_BUFSIZE - protocol headers). If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if TCP_WND < TCP_MSS + #error "lwip_sanity_check: WARNING: TCP_WND is smaller than MSS. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#endif /* LWIP_TCP */ +#endif /* !LWIP_DISABLE_TCP_SANITY_CHECKS */ + +/** + * Perform Sanity check of user-configurable values, and initialize all modules. + */ +void +lwip_init(void) +{ + /* Modules initialization */ + stats_init(); +#if !NO_SYS + sys_init(); +#endif /* !NO_SYS */ + mem_init(); + memp_init(); + pbuf_init(); + netif_init(); +#if LWIP_SOCKET + lwip_socket_init(); +#endif /* LWIP_SOCKET */ + ip_init(); +#if LWIP_ARP + etharp_init(); +#endif /* LWIP_ARP */ +#if LWIP_RAW + raw_init(); +#endif /* LWIP_RAW */ +#if LWIP_UDP + udp_init(); +#endif /* LWIP_UDP */ +#if LWIP_TCP + tcp_init(); +#endif /* LWIP_TCP */ +#if LWIP_SNMP + snmp_init(); +#endif /* LWIP_SNMP */ +#if LWIP_AUTOIP + autoip_init(); +#endif /* LWIP_AUTOIP */ +#if LWIP_IGMP + igmp_init(); +#endif /* LWIP_IGMP */ +#if LWIP_DNS + dns_init(); +#endif /* LWIP_DNS */ + +#if LWIP_TIMERS + sys_timeouts_init(); +#endif /* LWIP_TIMERS */ +} diff --git a/component/common/network/lwip/lwip_v1.4.1/src/core/ipv4/autoip.c b/component/common/network/lwip/lwip_v1.4.1/src/core/ipv4/autoip.c new file mode 100644 index 0000000..b122da2 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/core/ipv4/autoip.c @@ -0,0 +1,528 @@ +/** + * @file + * AutoIP Automatic LinkLocal IP Configuration + * + */ + +/* + * + * Copyright (c) 2007 Dominik Spies + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * Author: Dominik Spies + * + * This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform + * with RFC 3927. + * + * + * Please coordinate changes and requests with Dominik Spies + * + */ + +/******************************************************************************* + * USAGE: + * + * define LWIP_AUTOIP 1 in your lwipopts.h + * + * If you don't use tcpip.c (so, don't call, you don't call tcpip_init): + * - First, call autoip_init(). + * - call autoip_tmr() all AUTOIP_TMR_INTERVAL msces, + * that should be defined in autoip.h. + * I recommend a value of 100. The value must divide 1000 with a remainder almost 0. + * Possible values are 1000, 500, 333, 250, 200, 166, 142, 125, 111, 100 .... + * + * Without DHCP: + * - Call autoip_start() after netif_add(). + * + * With DHCP: + * - define LWIP_DHCP_AUTOIP_COOP 1 in your lwipopts.h. + * - Configure your DHCP Client. + * + */ + +#include "lwip/opt.h" + +#if LWIP_AUTOIP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/mem.h" +#include "lwip/udp.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/autoip.h" +#include "netif/etharp.h" + +#include +#include + +/* 169.254.0.0 */ +#define AUTOIP_NET 0xA9FE0000 +/* 169.254.1.0 */ +#define AUTOIP_RANGE_START (AUTOIP_NET | 0x0100) +/* 169.254.254.255 */ +#define AUTOIP_RANGE_END (AUTOIP_NET | 0xFEFF) + + +/** Pseudo random macro based on netif informations. + * You could use "rand()" from the C Library if you define LWIP_AUTOIP_RAND in lwipopts.h */ +#ifndef LWIP_AUTOIP_RAND +#define LWIP_AUTOIP_RAND(netif) ( (((u32_t)((netif->hwaddr[5]) & 0xff) << 24) | \ + ((u32_t)((netif->hwaddr[3]) & 0xff) << 16) | \ + ((u32_t)((netif->hwaddr[2]) & 0xff) << 8) | \ + ((u32_t)((netif->hwaddr[4]) & 0xff))) + \ + (netif->autoip?netif->autoip->tried_llipaddr:0)) +#endif /* LWIP_AUTOIP_RAND */ + +/** + * Macro that generates the initial IP address to be tried by AUTOIP. + * If you want to override this, define it to something else in lwipopts.h. + */ +#ifndef LWIP_AUTOIP_CREATE_SEED_ADDR +#define LWIP_AUTOIP_CREATE_SEED_ADDR(netif) \ + htonl(AUTOIP_RANGE_START + ((u32_t)(((u8_t)(netif->hwaddr[4])) | \ + ((u32_t)((u8_t)(netif->hwaddr[5]))) << 8))) +#endif /* LWIP_AUTOIP_CREATE_SEED_ADDR */ + +/* static functions */ +static void autoip_handle_arp_conflict(struct netif *netif); + +/* creates a pseudo random LL IP-Address for a network interface */ +static void autoip_create_addr(struct netif *netif, ip_addr_t *ipaddr); + +/* sends an ARP probe */ +static err_t autoip_arp_probe(struct netif *netif); + +/* sends an ARP announce */ +static err_t autoip_arp_announce(struct netif *netif); + +/* configure interface for use with current LL IP-Address */ +static err_t autoip_bind(struct netif *netif); + +/* start sending probes for llipaddr */ +static void autoip_start_probing(struct netif *netif); + + +/** Set a statically allocated struct autoip to work with. + * Using this prevents autoip_start to allocate it using mem_malloc. + * + * @param netif the netif for which to set the struct autoip + * @param dhcp (uninitialised) dhcp struct allocated by the application + */ +void +autoip_set_struct(struct netif *netif, struct autoip *autoip) +{ + LWIP_ASSERT("netif != NULL", netif != NULL); + LWIP_ASSERT("autoip != NULL", autoip != NULL); + LWIP_ASSERT("netif already has a struct autoip set", netif->autoip == NULL); + + /* clear data structure */ + memset(autoip, 0, sizeof(struct autoip)); + /* autoip->state = AUTOIP_STATE_OFF; */ + netif->autoip = autoip; +} + +/** Restart AutoIP client and check the next address (conflict detected) + * + * @param netif The netif under AutoIP control + */ +static void +autoip_restart(struct netif *netif) +{ + netif->autoip->tried_llipaddr++; + autoip_start(netif); +} + +/** + * Handle a IP address conflict after an ARP conflict detection + */ +static void +autoip_handle_arp_conflict(struct netif *netif) +{ + /* Somehow detect if we are defending or retreating */ + unsigned char defend = 1; /* tbd */ + + if (defend) { + if (netif->autoip->lastconflict > 0) { + /* retreat, there was a conflicting ARP in the last + * DEFEND_INTERVAL seconds + */ + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_handle_arp_conflict(): we are defending, but in DEFEND_INTERVAL, retreating\n")); + + /* TODO: close all TCP sessions */ + autoip_restart(netif); + } else { + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_handle_arp_conflict(): we are defend, send ARP Announce\n")); + autoip_arp_announce(netif); + netif->autoip->lastconflict = DEFEND_INTERVAL * AUTOIP_TICKS_PER_SECOND; + } + } else { + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_handle_arp_conflict(): we do not defend, retreating\n")); + /* TODO: close all TCP sessions */ + autoip_restart(netif); + } +} + +/** + * Create an IP-Address out of range 169.254.1.0 to 169.254.254.255 + * + * @param netif network interface on which create the IP-Address + * @param ipaddr ip address to initialize + */ +static void +autoip_create_addr(struct netif *netif, ip_addr_t *ipaddr) +{ + /* Here we create an IP-Address out of range 169.254.1.0 to 169.254.254.255 + * compliant to RFC 3927 Section 2.1 + * We have 254 * 256 possibilities */ + + u32_t addr = ntohl(LWIP_AUTOIP_CREATE_SEED_ADDR(netif)); + addr += netif->autoip->tried_llipaddr; + addr = AUTOIP_NET | (addr & 0xffff); + /* Now, 169.254.0.0 <= addr <= 169.254.255.255 */ + + if (addr < AUTOIP_RANGE_START) { + addr += AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1; + } + if (addr > AUTOIP_RANGE_END) { + addr -= AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1; + } + LWIP_ASSERT("AUTOIP address not in range", (addr >= AUTOIP_RANGE_START) && + (addr <= AUTOIP_RANGE_END)); + ip4_addr_set_u32(ipaddr, htonl(addr)); + + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_create_addr(): tried_llipaddr=%"U16_F", %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + (u16_t)(netif->autoip->tried_llipaddr), ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), + ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr))); +} + +/** + * Sends an ARP probe from a network interface + * + * @param netif network interface used to send the probe + */ +static err_t +autoip_arp_probe(struct netif *netif) +{ + return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, ðbroadcast, + (struct eth_addr *)netif->hwaddr, IP_ADDR_ANY, ðzero, + &netif->autoip->llipaddr, ARP_REQUEST); +} + +/** + * Sends an ARP announce from a network interface + * + * @param netif network interface used to send the announce + */ +static err_t +autoip_arp_announce(struct netif *netif) +{ + return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, ðbroadcast, + (struct eth_addr *)netif->hwaddr, &netif->autoip->llipaddr, ðzero, + &netif->autoip->llipaddr, ARP_REQUEST); +} + +/** + * Configure interface for use with current LL IP-Address + * + * @param netif network interface to configure with current LL IP-Address + */ +static err_t +autoip_bind(struct netif *netif) +{ + struct autoip *autoip = netif->autoip; + ip_addr_t sn_mask, gw_addr; + + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, + ("autoip_bind(netif=%p) %c%c%"U16_F" %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num, + ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr), + ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr))); + + IP4_ADDR(&sn_mask, 255, 255, 0, 0); + IP4_ADDR(&gw_addr, 0, 0, 0, 0); + + netif_set_ipaddr(netif, &autoip->llipaddr); + netif_set_netmask(netif, &sn_mask); + netif_set_gw(netif, &gw_addr); + + /* bring the interface up */ + netif_set_up(netif); + + return ERR_OK; +} + +/** + * Start AutoIP client + * + * @param netif network interface on which start the AutoIP client + */ +err_t +autoip_start(struct netif *netif) +{ + struct autoip *autoip = netif->autoip; + err_t result = ERR_OK; + + if (netif_is_up(netif)) { + netif_set_down(netif); + } + + /* Set IP-Address, Netmask and Gateway to 0 to make sure that + * ARP Packets are formed correctly + */ + ip_addr_set_zero(&netif->ip_addr); + ip_addr_set_zero(&netif->netmask); + ip_addr_set_zero(&netif->gw); + + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], + netif->name[1], (u16_t)netif->num)); + if (autoip == NULL) { + /* no AutoIP client attached yet? */ + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, + ("autoip_start(): starting new AUTOIP client\n")); + autoip = (struct autoip *)mem_malloc(sizeof(struct autoip)); + if (autoip == NULL) { + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, + ("autoip_start(): could not allocate autoip\n")); + return ERR_MEM; + } + memset(autoip, 0, sizeof(struct autoip)); + /* store this AutoIP client in the netif */ + netif->autoip = autoip; + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_start(): allocated autoip")); + } else { + autoip->state = AUTOIP_STATE_OFF; + autoip->ttw = 0; + autoip->sent_num = 0; + ip_addr_set_zero(&autoip->llipaddr); + autoip->lastconflict = 0; + } + + autoip_create_addr(netif, &(autoip->llipaddr)); + autoip_start_probing(netif); + + return result; +} + +static void +autoip_start_probing(struct netif *netif) +{ + struct autoip *autoip = netif->autoip; + + autoip->state = AUTOIP_STATE_PROBING; + autoip->sent_num = 0; + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_start_probing(): changing state to PROBING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(&netif->autoip->llipaddr), ip4_addr2_16(&netif->autoip->llipaddr), + ip4_addr3_16(&netif->autoip->llipaddr), ip4_addr4_16(&netif->autoip->llipaddr))); + + /* time to wait to first probe, this is randomly + * choosen out of 0 to PROBE_WAIT seconds. + * compliant to RFC 3927 Section 2.2.1 + */ + autoip->ttw = (u16_t)(LWIP_AUTOIP_RAND(netif) % (PROBE_WAIT * AUTOIP_TICKS_PER_SECOND)); + + /* + * if we tried more then MAX_CONFLICTS we must limit our rate for + * accquiring and probing address + * compliant to RFC 3927 Section 2.2.1 + */ + if (autoip->tried_llipaddr > MAX_CONFLICTS) { + autoip->ttw = RATE_LIMIT_INTERVAL * AUTOIP_TICKS_PER_SECOND; + } +} + +/** + * Handle a possible change in the network configuration. + * + * If there is an AutoIP address configured, take the interface down + * and begin probing with the same address. + */ +void +autoip_network_changed(struct netif *netif) +{ + if (netif->autoip && netif->autoip->state != AUTOIP_STATE_OFF) { + netif_set_down(netif); + autoip_start_probing(netif); + } +} + +/** + * Stop AutoIP client + * + * @param netif network interface on which stop the AutoIP client + */ +err_t +autoip_stop(struct netif *netif) +{ + netif->autoip->state = AUTOIP_STATE_OFF; + netif_set_down(netif); + return ERR_OK; +} + +/** + * Has to be called in loop every AUTOIP_TMR_INTERVAL milliseconds + */ +void +autoip_tmr() +{ + struct netif *netif = netif_list; + /* loop through netif's */ + while (netif != NULL) { + /* only act on AutoIP configured interfaces */ + if (netif->autoip != NULL) { + if (netif->autoip->lastconflict > 0) { + netif->autoip->lastconflict--; + } + + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, + ("autoip_tmr() AutoIP-State: %"U16_F", ttw=%"U16_F"\n", + (u16_t)(netif->autoip->state), netif->autoip->ttw)); + + switch(netif->autoip->state) { + case AUTOIP_STATE_PROBING: + if (netif->autoip->ttw > 0) { + netif->autoip->ttw--; + } else { + if (netif->autoip->sent_num >= PROBE_NUM) { + netif->autoip->state = AUTOIP_STATE_ANNOUNCING; + netif->autoip->sent_num = 0; + netif->autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND; + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_tmr(): changing state to ANNOUNCING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(&netif->autoip->llipaddr), ip4_addr2_16(&netif->autoip->llipaddr), + ip4_addr3_16(&netif->autoip->llipaddr), ip4_addr4_16(&netif->autoip->llipaddr))); + } else { + autoip_arp_probe(netif); + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, + ("autoip_tmr() PROBING Sent Probe\n")); + netif->autoip->sent_num++; + /* calculate time to wait to next probe */ + netif->autoip->ttw = (u16_t)((LWIP_AUTOIP_RAND(netif) % + ((PROBE_MAX - PROBE_MIN) * AUTOIP_TICKS_PER_SECOND) ) + + PROBE_MIN * AUTOIP_TICKS_PER_SECOND); + } + } + break; + + case AUTOIP_STATE_ANNOUNCING: + if (netif->autoip->ttw > 0) { + netif->autoip->ttw--; + } else { + if (netif->autoip->sent_num == 0) { + /* We are here the first time, so we waited ANNOUNCE_WAIT seconds + * Now we can bind to an IP address and use it. + * + * autoip_bind calls netif_set_up. This triggers a gratuitous ARP + * which counts as an announcement. + */ + autoip_bind(netif); + } else { + autoip_arp_announce(netif); + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, + ("autoip_tmr() ANNOUNCING Sent Announce\n")); + } + netif->autoip->ttw = ANNOUNCE_INTERVAL * AUTOIP_TICKS_PER_SECOND; + netif->autoip->sent_num++; + + if (netif->autoip->sent_num >= ANNOUNCE_NUM) { + netif->autoip->state = AUTOIP_STATE_BOUND; + netif->autoip->sent_num = 0; + netif->autoip->ttw = 0; + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_tmr(): changing state to BOUND: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(&netif->autoip->llipaddr), ip4_addr2_16(&netif->autoip->llipaddr), + ip4_addr3_16(&netif->autoip->llipaddr), ip4_addr4_16(&netif->autoip->llipaddr))); + } + } + break; + } + } + /* proceed to next network interface */ + netif = netif->next; + } +} + +/** + * Handles every incoming ARP Packet, called by etharp_arp_input. + * + * @param netif network interface to use for autoip processing + * @param hdr Incoming ARP packet + */ +void +autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr) +{ + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_arp_reply()\n")); + if ((netif->autoip != NULL) && (netif->autoip->state != AUTOIP_STATE_OFF)) { + /* when ip.src == llipaddr && hw.src != netif->hwaddr + * + * when probing ip.dst == llipaddr && hw.src != netif->hwaddr + * we have a conflict and must solve it + */ + ip_addr_t sipaddr, dipaddr; + struct eth_addr netifaddr; + ETHADDR16_COPY(netifaddr.addr, netif->hwaddr); + + /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without + * structure packing (not using structure copy which breaks strict-aliasing rules). + */ + IPADDR2_COPY(&sipaddr, &hdr->sipaddr); + IPADDR2_COPY(&dipaddr, &hdr->dipaddr); + + if ((netif->autoip->state == AUTOIP_STATE_PROBING) || + ((netif->autoip->state == AUTOIP_STATE_ANNOUNCING) && + (netif->autoip->sent_num == 0))) { + /* RFC 3927 Section 2.2.1: + * from beginning to after ANNOUNCE_WAIT + * seconds we have a conflict if + * ip.src == llipaddr OR + * ip.dst == llipaddr && hw.src != own hwaddr + */ + if ((ip_addr_cmp(&sipaddr, &netif->autoip->llipaddr)) || + (ip_addr_cmp(&dipaddr, &netif->autoip->llipaddr) && + !eth_addr_cmp(&netifaddr, &hdr->shwaddr))) { + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING, + ("autoip_arp_reply(): Probe Conflict detected\n")); + autoip_restart(netif); + } + } else { + /* RFC 3927 Section 2.5: + * in any state we have a conflict if + * ip.src == llipaddr && hw.src != own hwaddr + */ + if (ip_addr_cmp(&sipaddr, &netif->autoip->llipaddr) && + !eth_addr_cmp(&netifaddr, &hdr->shwaddr)) { + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING, + ("autoip_arp_reply(): Conflicting ARP-Packet detected\n")); + autoip_handle_arp_conflict(netif); + } + } + } +} + +#endif /* LWIP_AUTOIP */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/core/ipv4/icmp.c b/component/common/network/lwip/lwip_v1.4.1/src/core/ipv4/icmp.c new file mode 100644 index 0000000..47ba857 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/core/ipv4/icmp.c @@ -0,0 +1,339 @@ +/** + * @file + * ICMP - Internet Control Message Protocol + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/* Some ICMP messages should be passed to the transport protocols. This + is not implemented. */ + +#include "lwip/opt.h" + +#if LWIP_ICMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/icmp.h" +#include "lwip/inet_chksum.h" +#include "lwip/ip.h" +#include "lwip/def.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" + +#include + +/** Small optimization: set to 0 if incoming PBUF_POOL pbuf always can be + * used to modify and send a response packet (and to 1 if this is not the case, + * e.g. when link header is stripped of when receiving) */ +#ifndef LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN +#define LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN 1 +#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */ + +/* The amount of data from the original packet to return in a dest-unreachable */ +#define ICMP_DEST_UNREACH_DATASIZE 8 + +static void icmp_send_response(struct pbuf *p, u8_t type, u8_t code); + +/** + * Processes ICMP input packets, called from ip_input(). + * + * Currently only processes icmp echo requests and sends + * out the echo response. + * + * @param p the icmp echo request packet, p->payload pointing to the ip header + * @param inp the netif on which this packet was received + */ +void +icmp_input(struct pbuf *p, struct netif *inp) +{ + u8_t type; +#ifdef LWIP_DEBUG + u8_t code; +#endif /* LWIP_DEBUG */ + struct icmp_echo_hdr *iecho; + struct ip_hdr *iphdr; + s16_t hlen; + + ICMP_STATS_INC(icmp.recv); + snmp_inc_icmpinmsgs(); + + + iphdr = (struct ip_hdr *)p->payload; + hlen = IPH_HL(iphdr) * 4; + if (pbuf_header(p, -hlen) || (p->tot_len < sizeof(u16_t)*2)) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%"U16_F" bytes) received\n", p->tot_len)); + goto lenerr; + } + + type = *((u8_t *)p->payload); +#ifdef LWIP_DEBUG + code = *(((u8_t *)p->payload)+1); +#endif /* LWIP_DEBUG */ + switch (type) { + case ICMP_ER: + /* This is OK, echo reply might have been parsed by a raw PCB + (as obviously, an echo request has been sent, too). */ + break; + case ICMP_ECHO: +#if !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING + { + int accepted = 1; +#if !LWIP_MULTICAST_PING + /* multicast destination address? */ + if (ip_addr_ismulticast(¤t_iphdr_dest)) { + accepted = 0; + } +#endif /* LWIP_MULTICAST_PING */ +#if !LWIP_BROADCAST_PING + /* broadcast destination address? */ + if (ip_addr_isbroadcast(¤t_iphdr_dest, inp)) { + accepted = 0; + } +#endif /* LWIP_BROADCAST_PING */ + /* broadcast or multicast destination address not acceptd? */ + if (!accepted) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to multicast or broadcast pings\n")); + ICMP_STATS_INC(icmp.err); + pbuf_free(p); + return; + } + } +#endif /* !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING */ + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ping\n")); + if (p->tot_len < sizeof(struct icmp_echo_hdr)) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n")); + goto lenerr; + } + if (inet_chksum_pbuf(p) != 0) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo\n")); + pbuf_free(p); + ICMP_STATS_INC(icmp.chkerr); + snmp_inc_icmpinerrors(); + return; + } +#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN + if (pbuf_header(p, (PBUF_IP_HLEN + PBUF_LINK_HLEN))) { + /* p is not big enough to contain link headers + * allocate a new one and copy p into it + */ + struct pbuf *r; + /* switch p->payload to ip header */ + if (pbuf_header(p, hlen)) { + LWIP_ASSERT("icmp_input: moving p->payload to ip header failed\n", 0); + goto memerr; + } + /* allocate new packet buffer with space for link headers */ + r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM); + if (r == NULL) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: allocating new pbuf failed\n")); + goto memerr; + } + LWIP_ASSERT("check that first pbuf can hold struct the ICMP header", + (r->len >= hlen + sizeof(struct icmp_echo_hdr))); + /* copy the whole packet including ip header */ + if (pbuf_copy(r, p) != ERR_OK) { + LWIP_ASSERT("icmp_input: copying to new pbuf failed\n", 0); + goto memerr; + } + iphdr = (struct ip_hdr *)r->payload; + /* switch r->payload back to icmp header */ + if (pbuf_header(r, -hlen)) { + LWIP_ASSERT("icmp_input: restoring original p->payload failed\n", 0); + goto memerr; + } + /* free the original p */ + pbuf_free(p); + /* we now have an identical copy of p that has room for link headers */ + p = r; + } else { + /* restore p->payload to point to icmp header */ + if (pbuf_header(p, -(s16_t)(PBUF_IP_HLEN + PBUF_LINK_HLEN))) { + LWIP_ASSERT("icmp_input: restoring original p->payload failed\n", 0); + goto memerr; + } + } +#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */ + /* At this point, all checks are OK. */ + /* We generate an answer by switching the dest and src ip addresses, + * setting the icmp type to ECHO_RESPONSE and updating the checksum. */ + iecho = (struct icmp_echo_hdr *)p->payload; + ip_addr_copy(iphdr->src, *ip_current_dest_addr()); + ip_addr_copy(iphdr->dest, *ip_current_src_addr()); + ICMPH_TYPE_SET(iecho, ICMP_ER); +#if CHECKSUM_GEN_ICMP + /* adjust the checksum */ + if (iecho->chksum >= PP_HTONS(0xffffU - (ICMP_ECHO << 8))) { + iecho->chksum += PP_HTONS(ICMP_ECHO << 8) + 1; + } else { + iecho->chksum += PP_HTONS(ICMP_ECHO << 8); + } +#else /* CHECKSUM_GEN_ICMP */ + iecho->chksum = 0; +#endif /* CHECKSUM_GEN_ICMP */ + + /* Set the correct TTL and recalculate the header checksum. */ + IPH_TTL_SET(iphdr, ICMP_TTL); + IPH_CHKSUM_SET(iphdr, 0); +#if CHECKSUM_GEN_IP + IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN)); +#endif /* CHECKSUM_GEN_IP */ + + ICMP_STATS_INC(icmp.xmit); + /* increase number of messages attempted to send */ + snmp_inc_icmpoutmsgs(); + /* increase number of echo replies attempted to send */ + snmp_inc_icmpoutechoreps(); + + if(pbuf_header(p, hlen)) { + LWIP_ASSERT("Can't move over header in packet", 0); + } else { + err_t ret; + /* send an ICMP packet, src addr is the dest addr of the curren packet */ + ret = ip_output_if(p, ip_current_dest_addr(), IP_HDRINCL, + ICMP_TTL, 0, IP_PROTO_ICMP, inp); + if (ret != ERR_OK) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ip_output_if returned an error: %c.\n", ret)); + } + } + break; + default: + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %"S16_F" code %"S16_F" not supported.\n", + (s16_t)type, (s16_t)code)); + ICMP_STATS_INC(icmp.proterr); + ICMP_STATS_INC(icmp.drop); + } + pbuf_free(p); + return; +lenerr: + pbuf_free(p); + ICMP_STATS_INC(icmp.lenerr); + snmp_inc_icmpinerrors(); + return; +#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN +memerr: + pbuf_free(p); + ICMP_STATS_INC(icmp.err); + snmp_inc_icmpinerrors(); + return; +#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */ +} + +/** + * Send an icmp 'destination unreachable' packet, called from ip_input() if + * the transport layer protocol is unknown and from udp_input() if the local + * port is not bound. + * + * @param p the input packet for which the 'unreachable' should be sent, + * p->payload pointing to the IP header + * @param t type of the 'unreachable' packet + */ +void +icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t) +{ + icmp_send_response(p, ICMP_DUR, t); +} + +#if IP_FORWARD || IP_REASSEMBLY +/** + * Send a 'time exceeded' packet, called from ip_forward() if TTL is 0. + * + * @param p the input packet for which the 'time exceeded' should be sent, + * p->payload pointing to the IP header + * @param t type of the 'time exceeded' packet + */ +void +icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t) +{ + icmp_send_response(p, ICMP_TE, t); +} + +#endif /* IP_FORWARD || IP_REASSEMBLY */ + +/** + * Send an icmp packet in response to an incoming packet. + * + * @param p the input packet for which the 'unreachable' should be sent, + * p->payload pointing to the IP header + * @param type Type of the ICMP header + * @param code Code of the ICMP header + */ +static void +icmp_send_response(struct pbuf *p, u8_t type, u8_t code) +{ + struct pbuf *q; + struct ip_hdr *iphdr; + /* we can use the echo header here */ + struct icmp_echo_hdr *icmphdr; + ip_addr_t iphdr_src; + + /* ICMP header + IP header + 8 bytes of data */ + q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE, + PBUF_RAM); + if (q == NULL) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMP packet.\n")); + return; + } + LWIP_ASSERT("check that first pbuf can hold icmp message", + (q->len >= (sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE))); + + iphdr = (struct ip_hdr *)p->payload; + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from ")); + ip_addr_debug_print(ICMP_DEBUG, &(iphdr->src)); + LWIP_DEBUGF(ICMP_DEBUG, (" to ")); + ip_addr_debug_print(ICMP_DEBUG, &(iphdr->dest)); + LWIP_DEBUGF(ICMP_DEBUG, ("\n")); + + icmphdr = (struct icmp_echo_hdr *)q->payload; + icmphdr->type = type; + icmphdr->code = code; + icmphdr->id = 0; + icmphdr->seqno = 0; + + /* copy fields from original packet */ + SMEMCPY((u8_t *)q->payload + sizeof(struct icmp_echo_hdr), (u8_t *)p->payload, + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE); + + /* calculate checksum */ + icmphdr->chksum = 0; + icmphdr->chksum = inet_chksum(icmphdr, q->len); + ICMP_STATS_INC(icmp.xmit); + /* increase number of messages attempted to send */ + snmp_inc_icmpoutmsgs(); + /* increase number of destination unreachable messages attempted to send */ + snmp_inc_icmpouttimeexcds(); + ip_addr_copy(iphdr_src, iphdr->src); + ip_output(q, NULL, &iphdr_src, ICMP_TTL, 0, IP_PROTO_ICMP); + pbuf_free(q); +} + +#endif /* LWIP_ICMP */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/core/ipv4/igmp.c b/component/common/network/lwip/lwip_v1.4.1/src/core/ipv4/igmp.c new file mode 100644 index 0000000..45bb5d9 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/core/ipv4/igmp.c @@ -0,0 +1,805 @@ +/** + * @file + * IGMP - Internet Group Management Protocol + * + */ + +/* + * Copyright (c) 2002 CITEL Technologies Ltd. + * 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 CITEL Technologies Ltd 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 CITEL TECHNOLOGIES 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 CITEL TECHNOLOGIES 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. + * + * This file is a contribution to the lwIP TCP/IP stack. + * The Swedish Institute of Computer Science and Adam Dunkels + * are specifically granted permission to redistribute this + * source code. +*/ + +/*------------------------------------------------------------- +Note 1) +Although the rfc requires V1 AND V2 capability +we will only support v2 since now V1 is very old (August 1989) +V1 can be added if required + +a debug print and statistic have been implemented to +show this up. +------------------------------------------------------------- +------------------------------------------------------------- +Note 2) +A query for a specific group address (as opposed to ALLHOSTS) +has now been implemented as I am unsure if it is required + +a debug print and statistic have been implemented to +show this up. +------------------------------------------------------------- +------------------------------------------------------------- +Note 3) +The router alert rfc 2113 is implemented in outgoing packets +but not checked rigorously incoming +------------------------------------------------------------- +Steve Reynolds +------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------- + * RFC 988 - Host extensions for IP multicasting - V0 + * RFC 1054 - Host extensions for IP multicasting - + * RFC 1112 - Host extensions for IP multicasting - V1 + * RFC 2236 - Internet Group Management Protocol, Version 2 - V2 <- this code is based on this RFC (it's the "de facto" standard) + * RFC 3376 - Internet Group Management Protocol, Version 3 - V3 + * RFC 4604 - Using Internet Group Management Protocol Version 3... - V3+ + * RFC 2113 - IP Router Alert Option - + *----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------- + * Includes + *----------------------------------------------------------------------------*/ + +#include "lwip/opt.h" + +#if LWIP_IGMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/igmp.h" +#include "lwip/debug.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/ip.h" +#include "lwip/inet_chksum.h" +#include "lwip/netif.h" +#include "lwip/icmp.h" +#include "lwip/udp.h" +#include "lwip/tcp.h" +#include "lwip/stats.h" + +#include "string.h" + +/* + * IGMP constants + */ +#define IGMP_TTL 1 +#define IGMP_MINLEN 8 +#define ROUTER_ALERT 0x9404U +#define ROUTER_ALERTLEN 4 + +/* + * IGMP message types, including version number. + */ +#define IGMP_MEMB_QUERY 0x11 /* Membership query */ +#define IGMP_V1_MEMB_REPORT 0x12 /* Ver. 1 membership report */ +#define IGMP_V2_MEMB_REPORT 0x16 /* Ver. 2 membership report */ +#define IGMP_LEAVE_GROUP 0x17 /* Leave-group message */ + +/* Group membership states */ +#define IGMP_GROUP_NON_MEMBER 0 +#define IGMP_GROUP_DELAYING_MEMBER 1 +#define IGMP_GROUP_IDLE_MEMBER 2 + +/** + * IGMP packet format. + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct igmp_msg { + PACK_STRUCT_FIELD(u8_t igmp_msgtype); + PACK_STRUCT_FIELD(u8_t igmp_maxresp); + PACK_STRUCT_FIELD(u16_t igmp_checksum); + PACK_STRUCT_FIELD(ip_addr_p_t igmp_group_address); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + + +static struct igmp_group *igmp_lookup_group(struct netif *ifp, ip_addr_t *addr); +static err_t igmp_remove_group(struct igmp_group *group); +static void igmp_timeout( struct igmp_group *group); +static void igmp_start_timer(struct igmp_group *group, u8_t max_time); +static void igmp_delaying_member(struct igmp_group *group, u8_t maxresp); +static err_t igmp_ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, struct netif *netif); +static void igmp_send(struct igmp_group *group, u8_t type); + + +static struct igmp_group* igmp_group_list; +static ip_addr_t allsystems; +static ip_addr_t allrouters; + + +/** + * Initialize the IGMP module + */ +void +igmp_init(void) +{ + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_init: initializing\n")); + + IP4_ADDR(&allsystems, 224, 0, 0, 1); + IP4_ADDR(&allrouters, 224, 0, 0, 2); +} + +#ifdef LWIP_DEBUG +/** + * Dump global IGMP groups list + */ +void +igmp_dump_group_list() +{ + struct igmp_group *group = igmp_group_list; + + while (group != NULL) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_dump_group_list: [%"U32_F"] ", (u32_t)(group->group_state))); + ip_addr_debug_print(IGMP_DEBUG, &group->group_address); + LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", group->netif)); + group = group->next; + } + LWIP_DEBUGF(IGMP_DEBUG, ("\n")); +} +#else +#define igmp_dump_group_list() +#endif /* LWIP_DEBUG */ + +/** + * Start IGMP processing on interface + * + * @param netif network interface on which start IGMP processing + */ +err_t +igmp_start(struct netif *netif) +{ + struct igmp_group* group; + + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_start: starting IGMP processing on if %p\n", netif)); + + group = igmp_lookup_group(netif, &allsystems); + + if (group != NULL) { + group->group_state = IGMP_GROUP_IDLE_MEMBER; + group->use++; + + /* Allow the igmp messages at the MAC level */ + if (netif->igmp_mac_filter != NULL) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_start: igmp_mac_filter(ADD ")); + ip_addr_debug_print(IGMP_DEBUG, &allsystems); + LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif)); + netif->igmp_mac_filter(netif, &allsystems, IGMP_ADD_MAC_FILTER); + } + + return ERR_OK; + } + + return ERR_MEM; +} + +/** + * Stop IGMP processing on interface + * + * @param netif network interface on which stop IGMP processing + */ +err_t +igmp_stop(struct netif *netif) +{ + struct igmp_group *group = igmp_group_list; + struct igmp_group *prev = NULL; + struct igmp_group *next; + + /* look for groups joined on this interface further down the list */ + while (group != NULL) { + next = group->next; + /* is it a group joined on this interface? */ + if (group->netif == netif) { + /* is it the first group of the list? */ + if (group == igmp_group_list) { + igmp_group_list = next; + } + /* is there a "previous" group defined? */ + if (prev != NULL) { + prev->next = next; + } + /* disable the group at the MAC level */ + if (netif->igmp_mac_filter != NULL) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_stop: igmp_mac_filter(DEL ")); + ip_addr_debug_print(IGMP_DEBUG, &group->group_address); + LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif)); + netif->igmp_mac_filter(netif, &(group->group_address), IGMP_DEL_MAC_FILTER); + } + /* free group */ + memp_free(MEMP_IGMP_GROUP, group); + } else { + /* change the "previous" */ + prev = group; + } + /* move to "next" */ + group = next; + } + return ERR_OK; +} + +/** + * Report IGMP memberships for this interface + * + * @param netif network interface on which report IGMP memberships + */ +void +igmp_report_groups(struct netif *netif) +{ + struct igmp_group *group = igmp_group_list; + + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_report_groups: sending IGMP reports on if %p\n", netif)); + + while (group != NULL) { + if (group->netif == netif) { + igmp_delaying_member(group, IGMP_JOIN_DELAYING_MEMBER_TMR); + } + group = group->next; + } +} + +/** + * Search for a group in the global igmp_group_list + * + * @param ifp the network interface for which to look + * @param addr the group ip address to search for + * @return a struct igmp_group* if the group has been found, + * NULL if the group wasn't found. + */ +struct igmp_group * +igmp_lookfor_group(struct netif *ifp, ip_addr_t *addr) +{ + struct igmp_group *group = igmp_group_list; + + while (group != NULL) { + if ((group->netif == ifp) && (ip_addr_cmp(&(group->group_address), addr))) { + return group; + } + group = group->next; + } + + /* to be clearer, we return NULL here instead of + * 'group' (which is also NULL at this point). + */ + return NULL; +} + +/** + * Search for a specific igmp group and create a new one if not found- + * + * @param ifp the network interface for which to look + * @param addr the group ip address to search + * @return a struct igmp_group*, + * NULL on memory error. + */ +struct igmp_group * +igmp_lookup_group(struct netif *ifp, ip_addr_t *addr) +{ + struct igmp_group *group = igmp_group_list; + + /* Search if the group already exists */ + group = igmp_lookfor_group(ifp, addr); + if (group != NULL) { + /* Group already exists. */ + return group; + } + + /* Group doesn't exist yet, create a new one */ + group = (struct igmp_group *)memp_malloc(MEMP_IGMP_GROUP); + if (group != NULL) { + group->netif = ifp; + ip_addr_set(&(group->group_address), addr); + group->timer = 0; /* Not running */ + group->group_state = IGMP_GROUP_NON_MEMBER; + group->last_reporter_flag = 0; + group->use = 0; + group->next = igmp_group_list; + + igmp_group_list = group; + } + + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_lookup_group: %sallocated a new group with address ", (group?"":"impossible to "))); + ip_addr_debug_print(IGMP_DEBUG, addr); + LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", ifp)); + + return group; +} + +/** + * Remove a group in the global igmp_group_list + * + * @param group the group to remove from the global igmp_group_list + * @return ERR_OK if group was removed from the list, an err_t otherwise + */ +static err_t +igmp_remove_group(struct igmp_group *group) +{ + err_t err = ERR_OK; + + /* Is it the first group? */ + if (igmp_group_list == group) { + igmp_group_list = group->next; + } else { + /* look for group further down the list */ + struct igmp_group *tmpGroup; + for (tmpGroup = igmp_group_list; tmpGroup != NULL; tmpGroup = tmpGroup->next) { + if (tmpGroup->next == group) { + tmpGroup->next = group->next; + break; + } + } + /* Group not found in the global igmp_group_list */ + if (tmpGroup == NULL) + err = ERR_ARG; + } + /* free group */ + memp_free(MEMP_IGMP_GROUP, group); + + return err; +} + +/** + * Called from ip_input() if a new IGMP packet is received. + * + * @param p received igmp packet, p->payload pointing to the ip header + * @param inp network interface on which the packet was received + * @param dest destination ip address of the igmp packet + */ +void +igmp_input(struct pbuf *p, struct netif *inp, ip_addr_t *dest) +{ + struct ip_hdr * iphdr; + struct igmp_msg* igmp; + struct igmp_group* group; + struct igmp_group* groupref; + + IGMP_STATS_INC(igmp.recv); + + /* Note that the length CAN be greater than 8 but only 8 are used - All are included in the checksum */ + iphdr = (struct ip_hdr *)p->payload; + if (pbuf_header(p, -(s16_t)(IPH_HL(iphdr) * 4)) || (p->len < IGMP_MINLEN)) { + pbuf_free(p); + IGMP_STATS_INC(igmp.lenerr); + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: length error\n")); + return; + } + + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: message from ")); + ip_addr_debug_print(IGMP_DEBUG, &(iphdr->src)); + LWIP_DEBUGF(IGMP_DEBUG, (" to address ")); + ip_addr_debug_print(IGMP_DEBUG, &(iphdr->dest)); + LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", inp)); + + /* Now calculate and check the checksum */ + igmp = (struct igmp_msg *)p->payload; + if (inet_chksum(igmp, p->len)) { + pbuf_free(p); + IGMP_STATS_INC(igmp.chkerr); + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: checksum error\n")); + return; + } + + /* Packet is ok so find an existing group */ + group = igmp_lookfor_group(inp, dest); /* use the destination IP address of incoming packet */ + + /* If group can be found or create... */ + if (!group) { + pbuf_free(p); + IGMP_STATS_INC(igmp.drop); + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP frame not for us\n")); + return; + } + + /* NOW ACT ON THE INCOMING MESSAGE TYPE... */ + switch (igmp->igmp_msgtype) { + case IGMP_MEMB_QUERY: { + /* IGMP_MEMB_QUERY to the "all systems" address ? */ + if ((ip_addr_cmp(dest, &allsystems)) && ip_addr_isany(&igmp->igmp_group_address)) { + /* THIS IS THE GENERAL QUERY */ + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: General IGMP_MEMB_QUERY on \"ALL SYSTEMS\" address (224.0.0.1) [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp))); + + if (igmp->igmp_maxresp == 0) { + IGMP_STATS_INC(igmp.rx_v1); + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: got an all hosts query with time== 0 - this is V1 and not implemented - treat as v2\n")); + igmp->igmp_maxresp = IGMP_V1_DELAYING_MEMBER_TMR; + } else { + IGMP_STATS_INC(igmp.rx_general); + } + + groupref = igmp_group_list; + while (groupref) { + /* Do not send messages on the all systems group address! */ + if ((groupref->netif == inp) && (!(ip_addr_cmp(&(groupref->group_address), &allsystems)))) { + igmp_delaying_member(groupref, igmp->igmp_maxresp); + } + groupref = groupref->next; + } + } else { + /* IGMP_MEMB_QUERY to a specific group ? */ + if (!ip_addr_isany(&igmp->igmp_group_address)) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP_MEMB_QUERY to a specific group ")); + ip_addr_debug_print(IGMP_DEBUG, &igmp->igmp_group_address); + if (ip_addr_cmp(dest, &allsystems)) { + ip_addr_t groupaddr; + LWIP_DEBUGF(IGMP_DEBUG, (" using \"ALL SYSTEMS\" address (224.0.0.1) [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp))); + /* we first need to re-look for the group since we used dest last time */ + ip_addr_copy(groupaddr, igmp->igmp_group_address); + group = igmp_lookfor_group(inp, &groupaddr); + } else { + LWIP_DEBUGF(IGMP_DEBUG, (" with the group address as destination [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp))); + } + + if (group != NULL) { + IGMP_STATS_INC(igmp.rx_group); + igmp_delaying_member(group, igmp->igmp_maxresp); + } else { + IGMP_STATS_INC(igmp.drop); + } + } else { + IGMP_STATS_INC(igmp.proterr); + } + } + break; + } + case IGMP_V2_MEMB_REPORT: { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP_V2_MEMB_REPORT\n")); + IGMP_STATS_INC(igmp.rx_report); + if (group->group_state == IGMP_GROUP_DELAYING_MEMBER) { + /* This is on a specific group we have already looked up */ + group->timer = 0; /* stopped */ + group->group_state = IGMP_GROUP_IDLE_MEMBER; + group->last_reporter_flag = 0; + } + break; + } + default: { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: unexpected msg %d in state %d on group %p on if %p\n", + igmp->igmp_msgtype, group->group_state, &group, group->netif)); + IGMP_STATS_INC(igmp.proterr); + break; + } + } + + pbuf_free(p); + return; +} + +/** + * Join a group on one network interface. + * + * @param ifaddr ip address of the network interface which should join a new group + * @param groupaddr the ip address of the group which to join + * @return ERR_OK if group was joined on the netif(s), an err_t otherwise + */ +err_t +igmp_joingroup(ip_addr_t *ifaddr, ip_addr_t *groupaddr) +{ + err_t err = ERR_VAL; /* no matching interface */ + struct igmp_group *group; + struct netif *netif; + + /* make sure it is multicast address */ + LWIP_ERROR("igmp_joingroup: attempt to join non-multicast address", ip_addr_ismulticast(groupaddr), return ERR_VAL;); + LWIP_ERROR("igmp_joingroup: attempt to join allsystems address", (!ip_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;); + + /* loop through netif's */ + netif = netif_list; + while (netif != NULL) { + /* Should we join this interface ? */ + if ((netif->flags & NETIF_FLAG_IGMP) && ((ip_addr_isany(ifaddr) || ip_addr_cmp(&(netif->ip_addr), ifaddr)))) { + /* find group or create a new one if not found */ + group = igmp_lookup_group(netif, groupaddr); + + if (group != NULL) { + /* This should create a new group, check the state to make sure */ + if (group->group_state != IGMP_GROUP_NON_MEMBER) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: join to group not in state IGMP_GROUP_NON_MEMBER\n")); + } else { + /* OK - it was new group */ + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: join to new group: ")); + ip_addr_debug_print(IGMP_DEBUG, groupaddr); + LWIP_DEBUGF(IGMP_DEBUG, ("\n")); + + /* If first use of the group, allow the group at the MAC level */ + if ((group->use==0) && (netif->igmp_mac_filter != NULL)) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: igmp_mac_filter(ADD ")); + ip_addr_debug_print(IGMP_DEBUG, groupaddr); + LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif)); + netif->igmp_mac_filter(netif, groupaddr, IGMP_ADD_MAC_FILTER); + } + + IGMP_STATS_INC(igmp.tx_join); + igmp_send(group, IGMP_V2_MEMB_REPORT); + + igmp_start_timer(group, IGMP_JOIN_DELAYING_MEMBER_TMR); + + /* Need to work out where this timer comes from */ + group->group_state = IGMP_GROUP_DELAYING_MEMBER; + } + /* Increment group use */ + group->use++; + /* Join on this interface */ + err = ERR_OK; + } else { + /* Return an error even if some network interfaces are joined */ + /** @todo undo any other netif already joined */ + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: Not enought memory to join to group\n")); + return ERR_MEM; + } + } + /* proceed to next network interface */ + netif = netif->next; + } + + return err; +} + +/** + * Leave a group on one network interface. + * + * @param ifaddr ip address of the network interface which should leave a group + * @param groupaddr the ip address of the group which to leave + * @return ERR_OK if group was left on the netif(s), an err_t otherwise + */ +err_t +igmp_leavegroup(ip_addr_t *ifaddr, ip_addr_t *groupaddr) +{ + err_t err = ERR_VAL; /* no matching interface */ + struct igmp_group *group; + struct netif *netif; + + /* make sure it is multicast address */ + LWIP_ERROR("igmp_leavegroup: attempt to leave non-multicast address", ip_addr_ismulticast(groupaddr), return ERR_VAL;); + LWIP_ERROR("igmp_leavegroup: attempt to leave allsystems address", (!ip_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;); + + /* loop through netif's */ + netif = netif_list; + while (netif != NULL) { + /* Should we leave this interface ? */ + if ((netif->flags & NETIF_FLAG_IGMP) && ((ip_addr_isany(ifaddr) || ip_addr_cmp(&(netif->ip_addr), ifaddr)))) { + /* find group */ + group = igmp_lookfor_group(netif, groupaddr); + + if (group != NULL) { + /* Only send a leave if the flag is set according to the state diagram */ + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: Leaving group: ")); + ip_addr_debug_print(IGMP_DEBUG, groupaddr); + LWIP_DEBUGF(IGMP_DEBUG, ("\n")); + + /* If there is no other use of the group */ + if (group->use <= 1) { + /* If we are the last reporter for this group */ + if (group->last_reporter_flag) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: sending leaving group\n")); + IGMP_STATS_INC(igmp.tx_leave); + igmp_send(group, IGMP_LEAVE_GROUP); + } + + /* Disable the group at the MAC level */ + if (netif->igmp_mac_filter != NULL) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: igmp_mac_filter(DEL ")); + ip_addr_debug_print(IGMP_DEBUG, groupaddr); + LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif)); + netif->igmp_mac_filter(netif, groupaddr, IGMP_DEL_MAC_FILTER); + } + + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: remove group: ")); + ip_addr_debug_print(IGMP_DEBUG, groupaddr); + LWIP_DEBUGF(IGMP_DEBUG, ("\n")); + + /* Free the group */ + igmp_remove_group(group); + } else { + /* Decrement group use */ + group->use--; + } + /* Leave on this interface */ + err = ERR_OK; + } else { + /* It's not a fatal error on "leavegroup" */ + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: not member of group\n")); + } + } + /* proceed to next network interface */ + netif = netif->next; + } + + return err; +} + +/** + * The igmp timer function (both for NO_SYS=1 and =0) + * Should be called every IGMP_TMR_INTERVAL milliseconds (100 ms is default). + */ +void +igmp_tmr(void) +{ + struct igmp_group *group = igmp_group_list; + + while (group != NULL) { + if (group->timer > 0) { + group->timer--; + if (group->timer == 0) { + igmp_timeout(group); + } + } + group = group->next; + } +} + +/** + * Called if a timeout for one group is reached. + * Sends a report for this group. + * + * @param group an igmp_group for which a timeout is reached + */ +static void +igmp_timeout(struct igmp_group *group) +{ + /* If the state is IGMP_GROUP_DELAYING_MEMBER then we send a report for this group */ + if (group->group_state == IGMP_GROUP_DELAYING_MEMBER) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_timeout: report membership for group with address ")); + ip_addr_debug_print(IGMP_DEBUG, &(group->group_address)); + LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", group->netif)); + + IGMP_STATS_INC(igmp.tx_report); + igmp_send(group, IGMP_V2_MEMB_REPORT); + } +} + +/** + * Start a timer for an igmp group + * + * @param group the igmp_group for which to start a timer + * @param max_time the time in multiples of IGMP_TMR_INTERVAL (decrease with + * every call to igmp_tmr()) + */ +static void +igmp_start_timer(struct igmp_group *group, u8_t max_time) +{ + /* ensure the input value is > 0 */ + if (max_time == 0) { + max_time = 1; + } + /* ensure the random value is > 0 */ + group->timer = (LWIP_RAND() % (max_time - 1)) + 1; +} + +/** + * Delaying membership report for a group if necessary + * + * @param group the igmp_group for which "delaying" membership report + * @param maxresp query delay + */ +static void +igmp_delaying_member(struct igmp_group *group, u8_t maxresp) +{ + if ((group->group_state == IGMP_GROUP_IDLE_MEMBER) || + ((group->group_state == IGMP_GROUP_DELAYING_MEMBER) && + ((group->timer == 0) || (maxresp < group->timer)))) { + igmp_start_timer(group, maxresp); + group->group_state = IGMP_GROUP_DELAYING_MEMBER; + } +} + + +/** + * Sends an IP packet on a network interface. This function constructs the IP header + * and calculates the IP header checksum. If the source IP address is NULL, + * the IP address of the outgoing network interface is filled in as source address. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == IP_HDRINCL, p already includes an IP + header and p->payload points to that IP header) + * @param src the source IP address to send from (if src == IP_ADDR_ANY, the + * IP address of the netif used to send is used as source address) + * @param dest the destination IP address to send the packet to + * @param ttl the TTL value to be set in the IP header + * @param proto the PROTOCOL to be set in the IP header + * @param netif the netif on which to send this packet + * @return ERR_OK if the packet was sent OK + * ERR_BUF if p doesn't have enough space for IP/LINK headers + * returns errors returned by netif->output + */ +static err_t +igmp_ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, struct netif *netif) +{ + /* This is the "router alert" option */ + u16_t ra[2]; + ra[0] = PP_HTONS(ROUTER_ALERT); + ra[1] = 0x0000; /* Router shall examine packet */ + IGMP_STATS_INC(igmp.xmit); + return ip_output_if_opt(p, src, dest, IGMP_TTL, 0, IP_PROTO_IGMP, netif, ra, ROUTER_ALERTLEN); +} + +/** + * Send an igmp packet to a specific group. + * + * @param group the group to which to send the packet + * @param type the type of igmp packet to send + */ +static void +igmp_send(struct igmp_group *group, u8_t type) +{ + struct pbuf* p = NULL; + struct igmp_msg* igmp = NULL; + ip_addr_t src = *IP_ADDR_ANY; + ip_addr_t* dest = NULL; + + /* IP header + "router alert" option + IGMP header */ + p = pbuf_alloc(PBUF_TRANSPORT, IGMP_MINLEN, PBUF_RAM); + + if (p) { + igmp = (struct igmp_msg *)p->payload; + LWIP_ASSERT("igmp_send: check that first pbuf can hold struct igmp_msg", + (p->len >= sizeof(struct igmp_msg))); + ip_addr_copy(src, group->netif->ip_addr); + + if (type == IGMP_V2_MEMB_REPORT) { + dest = &(group->group_address); + ip_addr_copy(igmp->igmp_group_address, group->group_address); + group->last_reporter_flag = 1; /* Remember we were the last to report */ + } else { + if (type == IGMP_LEAVE_GROUP) { + dest = &allrouters; + ip_addr_copy(igmp->igmp_group_address, group->group_address); + } + } + + if ((type == IGMP_V2_MEMB_REPORT) || (type == IGMP_LEAVE_GROUP)) { + igmp->igmp_msgtype = type; + igmp->igmp_maxresp = 0; + igmp->igmp_checksum = 0; + igmp->igmp_checksum = inet_chksum(igmp, IGMP_MINLEN); + + igmp_ip_output_if(p, &src, dest, group->netif); + } + + pbuf_free(p); + } else { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_send: not enough memory for igmp_send\n")); + IGMP_STATS_INC(igmp.memerr); + } +} + +#endif /* LWIP_IGMP */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/core/ipv4/inet.c b/component/common/network/lwip/lwip_v1.4.1/src/core/ipv4/inet.c new file mode 100644 index 0000000..e283a57 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/core/ipv4/inet.c @@ -0,0 +1,42 @@ +/** + * @file + * Functions common to all TCP/IPv4 modules, such as the byte order functions. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/inet.h" + diff --git a/component/common/network/lwip/lwip_v1.4.1/src/core/ipv4/inet_chksum.c b/component/common/network/lwip/lwip_v1.4.1/src/core/ipv4/inet_chksum.c new file mode 100644 index 0000000..960252f --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/core/ipv4/inet_chksum.c @@ -0,0 +1,450 @@ +/** + * @file + * Incluse internet checksum functions. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/inet_chksum.h" +#include "lwip/def.h" + +#include +#include + +/* These are some reference implementations of the checksum algorithm, with the + * aim of being simple, correct and fully portable. Checksumming is the + * first thing you would want to optimize for your platform. If you create + * your own version, link it in and in your cc.h put: + * + * #define LWIP_CHKSUM + * + * Or you can select from the implementations below by defining + * LWIP_CHKSUM_ALGORITHM to 1, 2 or 3. + */ + +#ifndef LWIP_CHKSUM +# define LWIP_CHKSUM lwip_standard_chksum +# ifndef LWIP_CHKSUM_ALGORITHM +# define LWIP_CHKSUM_ALGORITHM 2 +# endif +#endif +/* If none set: */ +#ifndef LWIP_CHKSUM_ALGORITHM +# define LWIP_CHKSUM_ALGORITHM 0 +#endif + +#if (LWIP_CHKSUM_ALGORITHM == 1) /* Version #1 */ +/** + * lwip checksum + * + * @param dataptr points to start of data to be summed at any boundary + * @param len length of data to be summed + * @return host order (!) lwip checksum (non-inverted Internet sum) + * + * @note accumulator size limits summable length to 64k + * @note host endianess is irrelevant (p3 RFC1071) + */ +static u16_t +lwip_standard_chksum(void *dataptr, u16_t len) +{ + u32_t acc; + u16_t src; + u8_t *octetptr; + + acc = 0; + /* dataptr may be at odd or even addresses */ + octetptr = (u8_t*)dataptr; + while (len > 1) { + /* declare first octet as most significant + thus assume network order, ignoring host order */ + src = (*octetptr) << 8; + octetptr++; + /* declare second octet as least significant */ + src |= (*octetptr); + octetptr++; + acc += src; + len -= 2; + } + if (len > 0) { + /* accumulate remaining octet */ + src = (*octetptr) << 8; + acc += src; + } + /* add deferred carry bits */ + acc = (acc >> 16) + (acc & 0x0000ffffUL); + if ((acc & 0xffff0000UL) != 0) { + acc = (acc >> 16) + (acc & 0x0000ffffUL); + } + /* This maybe a little confusing: reorder sum using htons() + instead of ntohs() since it has a little less call overhead. + The caller must invert bits for Internet sum ! */ + return htons((u16_t)acc); +} +#endif + +#if (LWIP_CHKSUM_ALGORITHM == 2) /* Alternative version #2 */ +/* + * Curt McDowell + * Broadcom Corp. + * csm@broadcom.com + * + * IP checksum two bytes at a time with support for + * unaligned buffer. + * Works for len up to and including 0x20000. + * by Curt McDowell, Broadcom Corp. 12/08/2005 + * + * @param dataptr points to start of data to be summed at any boundary + * @param len length of data to be summed + * @return host order (!) lwip checksum (non-inverted Internet sum) + */ + +static u16_t +lwip_standard_chksum(void *dataptr, int len) +{ + u8_t *pb = (u8_t *)dataptr; + u16_t *ps, t = 0; + u32_t sum = 0; + int odd = ((mem_ptr_t)pb & 1); + + /* Get aligned to u16_t */ + if (odd && len > 0) { + ((u8_t *)&t)[1] = *pb++; + len--; + } + + /* Add the bulk of the data */ + ps = (u16_t *)(void *)pb; + while (len > 1) { + sum += *ps++; + len -= 2; + } + + /* Consume left-over byte, if any */ + if (len > 0) { + ((u8_t *)&t)[0] = *(u8_t *)ps; + } + + /* Add end bytes */ + sum += t; + + /* Fold 32-bit sum to 16 bits + calling this twice is propably faster than if statements... */ + sum = FOLD_U32T(sum); + sum = FOLD_U32T(sum); + + /* Swap if alignment was odd */ + if (odd) { + sum = SWAP_BYTES_IN_WORD(sum); + } + + return (u16_t)sum; +} +#endif + +#if (LWIP_CHKSUM_ALGORITHM == 3) /* Alternative version #3 */ +/** + * An optimized checksum routine. Basically, it uses loop-unrolling on + * the checksum loop, treating the head and tail bytes specially, whereas + * the inner loop acts on 8 bytes at a time. + * + * @arg start of buffer to be checksummed. May be an odd byte address. + * @len number of bytes in the buffer to be checksummed. + * @return host order (!) lwip checksum (non-inverted Internet sum) + * + * by Curt McDowell, Broadcom Corp. December 8th, 2005 + */ + +static u16_t +lwip_standard_chksum(void *dataptr, int len) +{ + u8_t *pb = (u8_t *)dataptr; + u16_t *ps, t = 0; + u32_t *pl; + u32_t sum = 0, tmp; + /* starts at odd byte address? */ + int odd = ((mem_ptr_t)pb & 1); + + if (odd && len > 0) { + ((u8_t *)&t)[1] = *pb++; + len--; + } + + ps = (u16_t *)pb; + + if (((mem_ptr_t)ps & 3) && len > 1) { + sum += *ps++; + len -= 2; + } + + pl = (u32_t *)ps; + + while (len > 7) { + tmp = sum + *pl++; /* ping */ + if (tmp < sum) { + tmp++; /* add back carry */ + } + + sum = tmp + *pl++; /* pong */ + if (sum < tmp) { + sum++; /* add back carry */ + } + + len -= 8; + } + + /* make room in upper bits */ + sum = FOLD_U32T(sum); + + ps = (u16_t *)pl; + + /* 16-bit aligned word remaining? */ + while (len > 1) { + sum += *ps++; + len -= 2; + } + + /* dangling tail byte remaining? */ + if (len > 0) { /* include odd byte */ + ((u8_t *)&t)[0] = *(u8_t *)ps; + } + + sum += t; /* add end bytes */ + + /* Fold 32-bit sum to 16 bits + calling this twice is propably faster than if statements... */ + sum = FOLD_U32T(sum); + sum = FOLD_U32T(sum); + + if (odd) { + sum = SWAP_BYTES_IN_WORD(sum); + } + + return (u16_t)sum; +} +#endif + +/* inet_chksum_pseudo: + * + * Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain. + * IP addresses are expected to be in network byte order. + * + * @param p chain of pbufs over that a checksum should be calculated (ip data part) + * @param src source ip address (used for checksum of pseudo header) + * @param dst destination ip address (used for checksum of pseudo header) + * @param proto ip protocol (used for checksum of pseudo header) + * @param proto_len length of the ip data part (used for checksum of pseudo header) + * @return checksum (as u16_t) to be saved directly in the protocol header + */ +u16_t +inet_chksum_pseudo(struct pbuf *p, + ip_addr_t *src, ip_addr_t *dest, + u8_t proto, u16_t proto_len) +{ + u32_t acc; + u32_t addr; + struct pbuf *q; + u8_t swapped; + + acc = 0; + swapped = 0; + /* iterate through all pbuf in chain */ + for(q = p; q != NULL; q = q->next) { + LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n", + (void *)q, (void *)q->next)); + acc += LWIP_CHKSUM(q->payload, q->len); + /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/ + /* just executing this next line is probably faster that the if statement needed + to check whether we really need to execute it, and does no harm */ + acc = FOLD_U32T(acc); + if (q->len % 2 != 0) { + swapped = 1 - swapped; + acc = SWAP_BYTES_IN_WORD(acc); + } + /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/ + } + + if (swapped) { + acc = SWAP_BYTES_IN_WORD(acc); + } + addr = ip4_addr_get_u32(src); + acc += (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + addr = ip4_addr_get_u32(dest); + acc += (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + acc += (u32_t)htons((u16_t)proto); + acc += (u32_t)htons(proto_len); + + /* Fold 32-bit sum to 16 bits + calling this twice is propably faster than if statements... */ + acc = FOLD_U32T(acc); + acc = FOLD_U32T(acc); + LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc)); + return (u16_t)~(acc & 0xffffUL); +} + +/* inet_chksum_pseudo: + * + * Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain. + * IP addresses are expected to be in network byte order. + * + * @param p chain of pbufs over that a checksum should be calculated (ip data part) + * @param src source ip address (used for checksum of pseudo header) + * @param dst destination ip address (used for checksum of pseudo header) + * @param proto ip protocol (used for checksum of pseudo header) + * @param proto_len length of the ip data part (used for checksum of pseudo header) + * @return checksum (as u16_t) to be saved directly in the protocol header + */ +u16_t +inet_chksum_pseudo_partial(struct pbuf *p, + ip_addr_t *src, ip_addr_t *dest, + u8_t proto, u16_t proto_len, u16_t chksum_len) +{ + u32_t acc; + u32_t addr; + struct pbuf *q; + u8_t swapped; + u16_t chklen; + + acc = 0; + swapped = 0; + /* iterate through all pbuf in chain */ + for(q = p; (q != NULL) && (chksum_len > 0); q = q->next) { + LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n", + (void *)q, (void *)q->next)); + chklen = q->len; + if (chklen > chksum_len) { + chklen = chksum_len; + } + acc += LWIP_CHKSUM(q->payload, chklen); + chksum_len -= chklen; + LWIP_ASSERT("delete me", chksum_len < 0x7fff); + /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/ + /* fold the upper bit down */ + acc = FOLD_U32T(acc); + if (q->len % 2 != 0) { + swapped = 1 - swapped; + acc = SWAP_BYTES_IN_WORD(acc); + } + /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/ + } + + if (swapped) { + acc = SWAP_BYTES_IN_WORD(acc); + } + addr = ip4_addr_get_u32(src); + acc += (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + addr = ip4_addr_get_u32(dest); + acc += (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + acc += (u32_t)htons((u16_t)proto); + acc += (u32_t)htons(proto_len); + + /* Fold 32-bit sum to 16 bits + calling this twice is propably faster than if statements... */ + acc = FOLD_U32T(acc); + acc = FOLD_U32T(acc); + LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc)); + return (u16_t)~(acc & 0xffffUL); +} + +/* inet_chksum: + * + * Calculates the Internet checksum over a portion of memory. Used primarily for IP + * and ICMP. + * + * @param dataptr start of the buffer to calculate the checksum (no alignment needed) + * @param len length of the buffer to calculate the checksum + * @return checksum (as u16_t) to be saved directly in the protocol header + */ + +u16_t +inet_chksum(void *dataptr, u16_t len) +{ + return ~LWIP_CHKSUM(dataptr, len); +} + +/** + * Calculate a checksum over a chain of pbufs (without pseudo-header, much like + * inet_chksum only pbufs are used). + * + * @param p pbuf chain over that the checksum should be calculated + * @return checksum (as u16_t) to be saved directly in the protocol header + */ +u16_t +inet_chksum_pbuf(struct pbuf *p) +{ + u32_t acc; + struct pbuf *q; + u8_t swapped; + + acc = 0; + swapped = 0; + for(q = p; q != NULL; q = q->next) { + acc += LWIP_CHKSUM(q->payload, q->len); + acc = FOLD_U32T(acc); + if (q->len % 2 != 0) { + swapped = 1 - swapped; + acc = SWAP_BYTES_IN_WORD(acc); + } + } + + if (swapped) { + acc = SWAP_BYTES_IN_WORD(acc); + } + return (u16_t)~(acc & 0xffffUL); +} + +/* These are some implementations for LWIP_CHKSUM_COPY, which copies data + * like MEMCPY but generates a checksum at the same time. Since this is a + * performance-sensitive function, you might want to create your own version + * in assembly targeted at your hardware by defining it in lwipopts.h: + * #define LWIP_CHKSUM_COPY(dst, src, len) your_chksum_copy(dst, src, len) + */ + +#if (LWIP_CHKSUM_COPY_ALGORITHM == 1) /* Version #1 */ +/** Safe but slow: first call MEMCPY, then call LWIP_CHKSUM. + * For architectures with big caches, data might still be in cache when + * generating the checksum after copying. + */ +u16_t +lwip_chksum_copy(void *dst, const void *src, u16_t len) +{ + MEMCPY(dst, src, len); + return LWIP_CHKSUM(dst, len); +} +#endif /* (LWIP_CHKSUM_COPY_ALGORITHM == 1) */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/core/ipv4/ip.c b/component/common/network/lwip/lwip_v1.4.1/src/core/ipv4/ip.c new file mode 100644 index 0000000..95d2db4 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/core/ipv4/ip.c @@ -0,0 +1,924 @@ +/** + * @file + * This is the IPv4 layer implementation for incoming and outgoing IP traffic. + * + * @see ip_frag.c + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" +#include "lwip/ip.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/ip_frag.h" +#include "lwip/inet_chksum.h" +#include "lwip/netif.h" +#include "lwip/icmp.h" +#include "lwip/igmp.h" +#include "lwip/raw.h" +#include "lwip/udp.h" +#include "lwip/tcp_impl.h" +#include "lwip/snmp.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" +#include "lwip/stats.h" +#include "arch/perf.h" + +#include + +/** Set this to 0 in the rare case of wanting to call an extra function to + * generate the IP checksum (in contrast to calculating it on-the-fly). */ +#ifndef LWIP_INLINE_IP_CHKSUM +#define LWIP_INLINE_IP_CHKSUM 1 +#endif +#if LWIP_INLINE_IP_CHKSUM && CHECKSUM_GEN_IP +#define CHECKSUM_GEN_IP_INLINE 1 +#else +#define CHECKSUM_GEN_IP_INLINE 0 +#endif + +#if LWIP_DHCP || defined(LWIP_IP_ACCEPT_UDP_PORT) +#define IP_ACCEPT_LINK_LAYER_ADDRESSING 1 + +/** Some defines for DHCP to let link-layer-addressed packets through while the + * netif is down. + * To use this in your own application/protocol, define LWIP_IP_ACCEPT_UDP_PORT + * to return 1 if the port is accepted and 0 if the port is not accepted. + */ +#if LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) +/* accept DHCP client port and custom port */ +#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) (((port) == PP_NTOHS(DHCP_CLIENT_PORT)) \ + || (LWIP_IP_ACCEPT_UDP_PORT(port))) +#elif defined(LWIP_IP_ACCEPT_UDP_PORT) /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */ +/* accept custom port only */ +#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) (LWIP_IP_ACCEPT_UDP_PORT(port)) +#else /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */ +/* accept DHCP client port only */ +#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) ((port) == PP_NTOHS(DHCP_CLIENT_PORT)) +#endif /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */ + +#else /* LWIP_DHCP */ +#define IP_ACCEPT_LINK_LAYER_ADDRESSING 0 +#endif /* LWIP_DHCP */ + +/** + * The interface that provided the packet for the current callback + * invocation. + */ +struct netif *current_netif; + +/** + * Header of the input packet currently being processed. + */ +const struct ip_hdr *current_header; +/** Source IP address of current_header */ +ip_addr_t current_iphdr_src; +/** Destination IP address of current_header */ +ip_addr_t current_iphdr_dest; + +/** The IP header ID of the next outgoing IP packet */ +static u16_t ip_id; + +/** + * Finds the appropriate network interface for a given IP address. It + * searches the list of network interfaces linearly. A match is found + * if the masked IP address of the network interface equals the masked + * IP address given to the function. + * + * @param dest the destination IP address for which to find the route + * @return the netif on which to send to reach dest + */ +struct netif * +ip_route(ip_addr_t *dest) +{ + struct netif *netif; + +#ifdef LWIP_HOOK_IP4_ROUTE + netif = LWIP_HOOK_IP4_ROUTE(dest); + if (netif != NULL) { + return netif; + } +#endif + + /* iterate through netifs */ + for (netif = netif_list; netif != NULL; netif = netif->next) { + /* network mask matches? */ + if (netif_is_up(netif)) { + if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) { + /* return netif on which to forward IP packet */ + return netif; + } + } + } + if ((netif_default == NULL) || (!netif_is_up(netif_default))) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_route: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest))); + IP_STATS_INC(ip.rterr); + snmp_inc_ipoutnoroutes(); + return NULL; + } + /* no matching netif found, use default netif */ + return netif_default; +} + +#if IP_FORWARD +/** + * Determine whether an IP address is in a reserved set of addresses + * that may not be forwarded, or whether datagrams to that destination + * may be forwarded. + * @param p the packet to forward + * @param dest the destination IP address + * @return 1: can forward 0: discard + */ +static int +ip_canforward(struct pbuf *p) +{ + u32_t addr = ip4_addr_get_u32(ip_current_dest_addr()); + + if (p->flags & PBUF_FLAG_LLBCAST) { + /* don't route link-layer broadcasts */ + return 0; + } + if ((p->flags & PBUF_FLAG_LLMCAST) && !IP_MULTICAST(addr)) { + /* don't route link-layer multicasts unless the destination address is an IP + multicast address */ + return 0; + } + if (IP_EXPERIMENTAL(addr)) { + return 0; + } + if (IP_CLASSA(addr)) { + u32_t net = addr & IP_CLASSA_NET; + if ((net == 0) || (net == (IP_LOOPBACKNET << IP_CLASSA_NSHIFT))) { + /* don't route loopback packets */ + return 0; + } + } + return 1; +} + +/** + * Forwards an IP packet. It finds an appropriate route for the + * packet, decrements the TTL value of the packet, adjusts the + * checksum and outputs the packet on the appropriate interface. + * + * @param p the packet to forward (p->payload points to IP header) + * @param iphdr the IP header of the input packet + * @param inp the netif on which this packet was received + */ +static void +ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp) +{ + struct netif *netif; + + PERF_START; + + if (!ip_canforward(p)) { + goto return_noroute; + } + + /* RFC3927 2.7: do not forward link-local addresses */ + if (ip_addr_islinklocal(¤t_iphdr_dest)) { + LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not forwarding LLA %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(¤t_iphdr_dest), ip4_addr2_16(¤t_iphdr_dest), + ip4_addr3_16(¤t_iphdr_dest), ip4_addr4_16(¤t_iphdr_dest))); + goto return_noroute; + } + + /* Find network interface where to forward this IP packet to. */ + netif = ip_route(¤t_iphdr_dest); + if (netif == NULL) { + LWIP_DEBUGF(IP_DEBUG, ("ip_forward: no forwarding route for %"U16_F".%"U16_F".%"U16_F".%"U16_F" found\n", + ip4_addr1_16(¤t_iphdr_dest), ip4_addr2_16(¤t_iphdr_dest), + ip4_addr3_16(¤t_iphdr_dest), ip4_addr4_16(¤t_iphdr_dest))); + /* @todo: send ICMP_DUR_NET? */ + goto return_noroute; + } +#if !IP_FORWARD_ALLOW_TX_ON_RX_NETIF + /* Do not forward packets onto the same network interface on which + * they arrived. */ + if (netif == inp) { + LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not bouncing packets back on incoming interface.\n")); + goto return_noroute; + } +#endif /* IP_FORWARD_ALLOW_TX_ON_RX_NETIF */ + + /* decrement TTL */ + IPH_TTL_SET(iphdr, IPH_TTL(iphdr) - 1); + /* send ICMP if TTL == 0 */ + if (IPH_TTL(iphdr) == 0) { + snmp_inc_ipinhdrerrors(); +#if LWIP_ICMP + /* Don't send ICMP messages in response to ICMP messages */ + if (IPH_PROTO(iphdr) != IP_PROTO_ICMP) { + icmp_time_exceeded(p, ICMP_TE_TTL); + } +#endif /* LWIP_ICMP */ + return; + } + + /* Incrementally update the IP checksum. */ + if (IPH_CHKSUM(iphdr) >= PP_HTONS(0xffffU - 0x100)) { + IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100) + 1); + } else { + IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100)); + } + + LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(¤t_iphdr_dest), ip4_addr2_16(¤t_iphdr_dest), + ip4_addr3_16(¤t_iphdr_dest), ip4_addr4_16(¤t_iphdr_dest))); + + IP_STATS_INC(ip.fw); + IP_STATS_INC(ip.xmit); + snmp_inc_ipforwdatagrams(); + + PERF_STOP("ip_forward"); + /* don't fragment if interface has mtu set to 0 [loopif] */ + if (netif->mtu && (p->tot_len > netif->mtu)) { + if ((IPH_OFFSET(iphdr) & PP_NTOHS(IP_DF)) == 0) { +#if IP_FRAG + ip_frag(p, netif, ip_current_dest_addr()); +#else /* IP_FRAG */ + /* @todo: send ICMP Destination Unreacheable code 13 "Communication administratively prohibited"? */ +#endif /* IP_FRAG */ + } else { + /* send ICMP Destination Unreacheable code 4: "Fragmentation Needed and DF Set" */ + icmp_dest_unreach(p, ICMP_DUR_FRAG); + } + return; + } + /* transmit pbuf on chosen interface */ + netif->output(netif, p, ¤t_iphdr_dest); + return; +return_noroute: + snmp_inc_ipoutnoroutes(); +} +#endif /* IP_FORWARD */ + +/** + * This function is called by the network interface device driver when + * an IP packet is received. The function does the basic checks of the + * IP header such as packet size being at least larger than the header + * size etc. If the packet was not destined for us, the packet is + * forwarded (using ip_forward). The IP checksum is always checked. + * + * Finally, the packet is sent to the upper layer protocol input function. + * + * @param p the received IP packet (p->payload points to IP header) + * @param inp the netif on which this packet was received + * @return ERR_OK if the packet was processed (could return ERR_* if it wasn't + * processed, but currently always returns ERR_OK) + */ +err_t +ip_input(struct pbuf *p, struct netif *inp) +{ + struct ip_hdr *iphdr; + struct netif *netif; + u16_t iphdr_hlen; + u16_t iphdr_len; +#if IP_ACCEPT_LINK_LAYER_ADDRESSING + int check_ip_src=1; +#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */ + + IP_STATS_INC(ip.recv); + snmp_inc_ipinreceives(); + + /* identify the IP header */ + iphdr = (struct ip_hdr *)p->payload; + if (IPH_V(iphdr) != 4) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_WARNING, ("IP packet dropped due to bad version number %"U16_F"\n", IPH_V(iphdr))); + ip_debug_print(p); + pbuf_free(p); + IP_STATS_INC(ip.err); + IP_STATS_INC(ip.drop); + snmp_inc_ipinhdrerrors(); + return ERR_OK; + } + +#ifdef LWIP_HOOK_IP4_INPUT + if (LWIP_HOOK_IP4_INPUT(p, inp)) { + /* the packet has been eaten */ + return ERR_OK; + } +#endif + + /* obtain IP header length in number of 32-bit words */ + iphdr_hlen = IPH_HL(iphdr); + /* calculate IP header length in bytes */ + iphdr_hlen *= 4; + /* obtain ip length in bytes */ + iphdr_len = ntohs(IPH_LEN(iphdr)); + + /* header length exceeds first pbuf length, or ip length exceeds total pbuf length? */ + if ((iphdr_hlen > p->len) || (iphdr_len > p->tot_len)) { + if (iphdr_hlen > p->len) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IP header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n", + iphdr_hlen, p->len)); + } + if (iphdr_len > p->tot_len) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IP (len %"U16_F") is longer than pbuf (len %"U16_F"), IP packet dropped.\n", + iphdr_len, p->tot_len)); + } + /* free (drop) packet pbufs */ + pbuf_free(p); + IP_STATS_INC(ip.lenerr); + IP_STATS_INC(ip.drop); + snmp_inc_ipindiscards(); + return ERR_OK; + } + + /* verify checksum */ +#if CHECKSUM_CHECK_IP + if (inet_chksum(iphdr, iphdr_hlen) != 0) { + + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("Checksum (0x%"X16_F") failed, IP packet dropped.\n", inet_chksum(iphdr, iphdr_hlen))); + ip_debug_print(p); + pbuf_free(p); + IP_STATS_INC(ip.chkerr); + IP_STATS_INC(ip.drop); + snmp_inc_ipinhdrerrors(); + return ERR_OK; + } +#endif + + /* Trim pbuf. This should have been done at the netif layer, + * but we'll do it anyway just to be sure that its done. */ + pbuf_realloc(p, iphdr_len); + + /* copy IP addresses to aligned ip_addr_t */ + ip_addr_copy(current_iphdr_dest, iphdr->dest); + ip_addr_copy(current_iphdr_src, iphdr->src); + + /* match packet against an interface, i.e. is this packet for us? */ +#if LWIP_IGMP + if (ip_addr_ismulticast(¤t_iphdr_dest)) { + if ((inp->flags & NETIF_FLAG_IGMP) && (igmp_lookfor_group(inp, ¤t_iphdr_dest))) { + netif = inp; + } else { + netif = NULL; + } + } else +#endif /* LWIP_IGMP */ + { + /* start trying with inp. if that's not acceptable, start walking the + list of configured netifs. + 'first' is used as a boolean to mark whether we started walking the list */ + int first = 1; + netif = inp; + do { + LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest 0x%"X32_F" netif->ip_addr 0x%"X32_F" (0x%"X32_F", 0x%"X32_F", 0x%"X32_F")\n", + ip4_addr_get_u32(&iphdr->dest), ip4_addr_get_u32(&netif->ip_addr), + ip4_addr_get_u32(&iphdr->dest) & ip4_addr_get_u32(&netif->netmask), + ip4_addr_get_u32(&netif->ip_addr) & ip4_addr_get_u32(&netif->netmask), + ip4_addr_get_u32(&iphdr->dest) & ~ip4_addr_get_u32(&netif->netmask))); + + /* interface is up and configured? */ + if ((netif_is_up(netif)) && (!ip_addr_isany(&(netif->ip_addr)))) { + /* unicast to this interface address? */ + if (ip_addr_cmp(¤t_iphdr_dest, &(netif->ip_addr)) || + /* or broadcast on this interface network address? */ + ip_addr_isbroadcast(¤t_iphdr_dest, netif)) { + LWIP_DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n", + netif->name[0], netif->name[1])); + /* break out of for loop */ + break; + } +#if LWIP_AUTOIP + /* connections to link-local addresses must persist after changing + the netif's address (RFC3927 ch. 1.9) */ + if ((netif->autoip != NULL) && + ip_addr_cmp(¤t_iphdr_dest, &(netif->autoip->llipaddr))) { + LWIP_DEBUGF(IP_DEBUG, ("ip_input: LLA packet accepted on interface %c%c\n", + netif->name[0], netif->name[1])); + /* break out of for loop */ + break; + } +#endif /* LWIP_AUTOIP */ + } + if (first) { + first = 0; + netif = netif_list; + } else { + netif = netif->next; + } + if (netif == inp) { + netif = netif->next; + } + } while(netif != NULL); + } + +#if IP_ACCEPT_LINK_LAYER_ADDRESSING + /* Pass DHCP messages regardless of destination address. DHCP traffic is addressed + * using link layer addressing (such as Ethernet MAC) so we must not filter on IP. + * According to RFC 1542 section 3.1.1, referred by RFC 2131). + * + * If you want to accept private broadcast communication while a netif is down, + * define LWIP_IP_ACCEPT_UDP_PORT(dst_port), e.g.: + * + * #define LWIP_IP_ACCEPT_UDP_PORT(dst_port) ((dst_port) == PP_NTOHS(12345)) + */ + if (netif == NULL) { + /* remote port is DHCP server? */ + if (IPH_PROTO(iphdr) == IP_PROTO_UDP) { + struct udp_hdr *udphdr = (struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen); + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: UDP packet to DHCP client port %"U16_F"\n", + ntohs(udphdr->dest))); + if (IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(udphdr->dest)) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: DHCP packet accepted.\n")); + netif = inp; + check_ip_src = 0; + } + } + } +#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */ + + /* broadcast or multicast packet source address? Compliant with RFC 1122: 3.2.1.3 */ +#if IP_ACCEPT_LINK_LAYER_ADDRESSING + /* DHCP servers need 0.0.0.0 to be allowed as source address (RFC 1.1.2.2: 3.2.1.3/a) */ + if (check_ip_src && !ip_addr_isany(¤t_iphdr_src)) +#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */ + { if ((ip_addr_isbroadcast(¤t_iphdr_src, inp)) || + (ip_addr_ismulticast(¤t_iphdr_src))) { + /* packet source is not valid */ + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("ip_input: packet source is not valid.\n")); + /* free (drop) packet pbufs */ + pbuf_free(p); + IP_STATS_INC(ip.drop); + snmp_inc_ipinaddrerrors(); + snmp_inc_ipindiscards(); + return ERR_OK; + } + } + + /* packet not for us? */ + if (netif == NULL) { + /* packet not for us, route or discard */ + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: packet not for us.\n")); +#if IP_FORWARD + /* non-broadcast packet? */ + if (!ip_addr_isbroadcast(¤t_iphdr_dest, inp)) { + /* try to forward IP packet on (other) interfaces */ + ip_forward(p, iphdr, inp); + } else +#endif /* IP_FORWARD */ + { + snmp_inc_ipinaddrerrors(); + snmp_inc_ipindiscards(); + } + pbuf_free(p); + return ERR_OK; + } + /* packet consists of multiple fragments? */ + if ((IPH_OFFSET(iphdr) & PP_HTONS(IP_OFFMASK | IP_MF)) != 0) { +#if IP_REASSEMBLY /* packet fragment reassembly code present? */ + LWIP_DEBUGF(IP_DEBUG, ("IP packet is a fragment (id=0x%04"X16_F" tot_len=%"U16_F" len=%"U16_F" MF=%"U16_F" offset=%"U16_F"), calling ip_reass()\n", + ntohs(IPH_ID(iphdr)), p->tot_len, ntohs(IPH_LEN(iphdr)), !!(IPH_OFFSET(iphdr) & PP_HTONS(IP_MF)), (ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8)); + /* reassemble the packet*/ + p = ip_reass(p); + /* packet not fully reassembled yet? */ + if (p == NULL) { + return ERR_OK; + } + iphdr = (struct ip_hdr *)p->payload; +#else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */ + pbuf_free(p); + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since it was fragmented (0x%"X16_F") (while IP_REASSEMBLY == 0).\n", + ntohs(IPH_OFFSET(iphdr)))); + IP_STATS_INC(ip.opterr); + IP_STATS_INC(ip.drop); + /* unsupported protocol feature */ + snmp_inc_ipinunknownprotos(); + return ERR_OK; +#endif /* IP_REASSEMBLY */ + } + +#if IP_OPTIONS_ALLOWED == 0 /* no support for IP options in the IP header? */ + +#if LWIP_IGMP + /* there is an extra "router alert" option in IGMP messages which we allow for but do not police */ + if((iphdr_hlen > IP_HLEN) && (IPH_PROTO(iphdr) != IP_PROTO_IGMP)) { +#else + if (iphdr_hlen > IP_HLEN) { +#endif /* LWIP_IGMP */ + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since there were IP options (while IP_OPTIONS_ALLOWED == 0).\n")); + pbuf_free(p); + IP_STATS_INC(ip.opterr); + IP_STATS_INC(ip.drop); + /* unsupported protocol feature */ + snmp_inc_ipinunknownprotos(); + return ERR_OK; + } +#endif /* IP_OPTIONS_ALLOWED == 0 */ + + /* send to upper layers */ + LWIP_DEBUGF(IP_DEBUG, ("ip_input: \n")); + ip_debug_print(p); + LWIP_DEBUGF(IP_DEBUG, ("ip_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len)); + + current_netif = inp; + current_header = iphdr; + +#if LWIP_RAW + /* raw input did not eat the packet? */ + if (raw_input(p, inp) == 0) +#endif /* LWIP_RAW */ + { + switch (IPH_PROTO(iphdr)) { +#if LWIP_UDP + case IP_PROTO_UDP: +#if LWIP_UDPLITE + case IP_PROTO_UDPLITE: +#endif /* LWIP_UDPLITE */ + snmp_inc_ipindelivers(); + udp_input(p, inp); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case IP_PROTO_TCP: + snmp_inc_ipindelivers(); + tcp_input(p, inp); + break; +#endif /* LWIP_TCP */ +#if LWIP_ICMP + case IP_PROTO_ICMP: + snmp_inc_ipindelivers(); + icmp_input(p, inp); + break; +#endif /* LWIP_ICMP */ +#if LWIP_IGMP + case IP_PROTO_IGMP: + igmp_input(p, inp, ¤t_iphdr_dest); + break; +#endif /* LWIP_IGMP */ + default: +#if LWIP_ICMP + /* send ICMP destination protocol unreachable unless is was a broadcast */ + if (!ip_addr_isbroadcast(¤t_iphdr_dest, inp) && + !ip_addr_ismulticast(¤t_iphdr_dest)) { + p->payload = iphdr; + icmp_dest_unreach(p, ICMP_DUR_PROTO); + } +#endif /* LWIP_ICMP */ + pbuf_free(p); + + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("Unsupported transport protocol %"U16_F"\n", IPH_PROTO(iphdr))); + + IP_STATS_INC(ip.proterr); + IP_STATS_INC(ip.drop); + snmp_inc_ipinunknownprotos(); + } + } + + current_netif = NULL; + current_header = NULL; + ip_addr_set_any(¤t_iphdr_src); + ip_addr_set_any(¤t_iphdr_dest); + + return ERR_OK; +} + +/** + * Sends an IP packet on a network interface. This function constructs + * the IP header and calculates the IP header checksum. If the source + * IP address is NULL, the IP address of the outgoing network + * interface is filled in as source address. + * If the destination IP address is IP_HDRINCL, p is assumed to already + * include an IP header and p->payload points to it instead of the data. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == IP_HDRINCL, p already includes an IP + header and p->payload points to that IP header) + * @param src the source IP address to send from (if src == IP_ADDR_ANY, the + * IP address of the netif used to send is used as source address) + * @param dest the destination IP address to send the packet to + * @param ttl the TTL value to be set in the IP header + * @param tos the TOS value to be set in the IP header + * @param proto the PROTOCOL to be set in the IP header + * @param netif the netif on which to send this packet + * @return ERR_OK if the packet was sent OK + * ERR_BUF if p doesn't have enough space for IP/LINK headers + * returns errors returned by netif->output + * + * @note ip_id: RFC791 "some host may be able to simply use + * unique identifiers independent of destination" + */ +err_t +ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, + u8_t proto, struct netif *netif) +{ +#if IP_OPTIONS_SEND + return ip_output_if_opt(p, src, dest, ttl, tos, proto, netif, NULL, 0); +} + +/** + * Same as ip_output_if() but with the possibility to include IP options: + * + * @ param ip_options pointer to the IP options, copied into the IP header + * @ param optlen length of ip_options + */ +err_t ip_output_if_opt(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, + u16_t optlen) +{ +#endif /* IP_OPTIONS_SEND */ + struct ip_hdr *iphdr; + ip_addr_t dest_addr; +#if CHECKSUM_GEN_IP_INLINE + u32_t chk_sum = 0; +#endif /* CHECKSUM_GEN_IP_INLINE */ + + /* pbufs passed to IP must have a ref-count of 1 as their payload pointer + gets altered as the packet is passed down the stack */ + LWIP_ASSERT("p->ref == 1", p->ref == 1); + + snmp_inc_ipoutrequests(); + + /* Should the IP header be generated or is it already included in p? */ + if (dest != IP_HDRINCL) { + u16_t ip_hlen = IP_HLEN; +#if IP_OPTIONS_SEND + u16_t optlen_aligned = 0; + if (optlen != 0) { +#if CHECKSUM_GEN_IP_INLINE + int i; +#endif /* CHECKSUM_GEN_IP_INLINE */ + /* round up to a multiple of 4 */ + optlen_aligned = ((optlen + 3) & ~3); + ip_hlen += optlen_aligned; + /* First write in the IP options */ + if (pbuf_header(p, optlen_aligned)) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_output_if_opt: not enough room for IP options in pbuf\n")); + IP_STATS_INC(ip.err); + snmp_inc_ipoutdiscards(); + return ERR_BUF; + } + MEMCPY(p->payload, ip_options, optlen); + if (optlen < optlen_aligned) { + /* zero the remaining bytes */ + memset(((char*)p->payload) + optlen, 0, optlen_aligned - optlen); + } +#if CHECKSUM_GEN_IP_INLINE + for (i = 0; i < optlen_aligned/2; i++) { + chk_sum += ((u16_t*)p->payload)[i]; + } +#endif /* CHECKSUM_GEN_IP_INLINE */ + } +#endif /* IP_OPTIONS_SEND */ + /* generate IP header */ + if (pbuf_header(p, IP_HLEN)) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_output: not enough room for IP header in pbuf\n")); + + IP_STATS_INC(ip.err); + snmp_inc_ipoutdiscards(); + return ERR_BUF; + } + + iphdr = (struct ip_hdr *)p->payload; + LWIP_ASSERT("check that first pbuf can hold struct ip_hdr", + (p->len >= sizeof(struct ip_hdr))); + + IPH_TTL_SET(iphdr, ttl); + IPH_PROTO_SET(iphdr, proto); +#if CHECKSUM_GEN_IP_INLINE + chk_sum += LWIP_MAKE_U16(proto, ttl); +#endif /* CHECKSUM_GEN_IP_INLINE */ + + /* dest cannot be NULL here */ + ip_addr_copy(iphdr->dest, *dest); +#if CHECKSUM_GEN_IP_INLINE + chk_sum += ip4_addr_get_u32(&iphdr->dest) & 0xFFFF; + chk_sum += ip4_addr_get_u32(&iphdr->dest) >> 16; +#endif /* CHECKSUM_GEN_IP_INLINE */ + + IPH_VHL_SET(iphdr, 4, ip_hlen / 4); + IPH_TOS_SET(iphdr, tos); +#if CHECKSUM_GEN_IP_INLINE + chk_sum += LWIP_MAKE_U16(tos, iphdr->_v_hl); +#endif /* CHECKSUM_GEN_IP_INLINE */ + IPH_LEN_SET(iphdr, htons(p->tot_len)); +#if CHECKSUM_GEN_IP_INLINE + chk_sum += iphdr->_len; +#endif /* CHECKSUM_GEN_IP_INLINE */ + IPH_OFFSET_SET(iphdr, 0); + IPH_ID_SET(iphdr, htons(ip_id)); +#if CHECKSUM_GEN_IP_INLINE + chk_sum += iphdr->_id; +#endif /* CHECKSUM_GEN_IP_INLINE */ + ++ip_id; + + if (ip_addr_isany(src)) { + ip_addr_copy(iphdr->src, netif->ip_addr); + } else { + /* src cannot be NULL here */ + ip_addr_copy(iphdr->src, *src); + } + +#if CHECKSUM_GEN_IP_INLINE + chk_sum += ip4_addr_get_u32(&iphdr->src) & 0xFFFF; + chk_sum += ip4_addr_get_u32(&iphdr->src) >> 16; + chk_sum = (chk_sum >> 16) + (chk_sum & 0xFFFF); + chk_sum = (chk_sum >> 16) + chk_sum; + chk_sum = ~chk_sum; + iphdr->_chksum = chk_sum; /* network order */ +#else /* CHECKSUM_GEN_IP_INLINE */ + IPH_CHKSUM_SET(iphdr, 0); +#if CHECKSUM_GEN_IP + IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, ip_hlen)); +#endif +#endif /* CHECKSUM_GEN_IP_INLINE */ + } else { + /* IP header already included in p */ + iphdr = (struct ip_hdr *)p->payload; + ip_addr_copy(dest_addr, iphdr->dest); + dest = &dest_addr; + } + + IP_STATS_INC(ip.xmit); + + LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], netif->num)); + ip_debug_print(p); + +#if ENABLE_LOOPBACK + if (ip_addr_cmp(dest, &netif->ip_addr)) { + /* Packet to self, enqueue it for loopback */ + LWIP_DEBUGF(IP_DEBUG, ("netif_loop_output()")); + return netif_loop_output(netif, p, dest); + } +#if LWIP_IGMP + if ((p->flags & PBUF_FLAG_MCASTLOOP) != 0) { + netif_loop_output(netif, p, dest); + } +#endif /* LWIP_IGMP */ +#endif /* ENABLE_LOOPBACK */ +#if IP_FRAG + /* don't fragment if interface has mtu set to 0 [loopif] */ + if (netif->mtu && (p->tot_len > netif->mtu)) { + return ip_frag(p, netif, dest); + } +#endif /* IP_FRAG */ + + LWIP_DEBUGF(IP_DEBUG, ("netif->output()")); + return netif->output(netif, p, dest); +} + +/** + * Simple interface to ip_output_if. It finds the outgoing network + * interface and calls upon ip_output_if to do the actual work. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == IP_HDRINCL, p already includes an IP + header and p->payload points to that IP header) + * @param src the source IP address to send from (if src == IP_ADDR_ANY, the + * IP address of the netif used to send is used as source address) + * @param dest the destination IP address to send the packet to + * @param ttl the TTL value to be set in the IP header + * @param tos the TOS value to be set in the IP header + * @param proto the PROTOCOL to be set in the IP header + * + * @return ERR_RTE if no route is found + * see ip_output_if() for more return values + */ +err_t +ip_output(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto) +{ + struct netif *netif; + + /* pbufs passed to IP must have a ref-count of 1 as their payload pointer + gets altered as the packet is passed down the stack */ + LWIP_ASSERT("p->ref == 1", p->ref == 1); + + if ((netif = ip_route(dest)) == NULL) { + LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest))); + IP_STATS_INC(ip.rterr); + return ERR_RTE; + } + + return ip_output_if(p, src, dest, ttl, tos, proto, netif); +} + +#if LWIP_NETIF_HWADDRHINT +/** Like ip_output, but takes and addr_hint pointer that is passed on to netif->addr_hint + * before calling ip_output_if. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == IP_HDRINCL, p already includes an IP + header and p->payload points to that IP header) + * @param src the source IP address to send from (if src == IP_ADDR_ANY, the + * IP address of the netif used to send is used as source address) + * @param dest the destination IP address to send the packet to + * @param ttl the TTL value to be set in the IP header + * @param tos the TOS value to be set in the IP header + * @param proto the PROTOCOL to be set in the IP header + * @param addr_hint address hint pointer set to netif->addr_hint before + * calling ip_output_if() + * + * @return ERR_RTE if no route is found + * see ip_output_if() for more return values + */ +err_t +ip_output_hinted(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint) +{ + struct netif *netif; + err_t err; + + /* pbufs passed to IP must have a ref-count of 1 as their payload pointer + gets altered as the packet is passed down the stack */ + LWIP_ASSERT("p->ref == 1", p->ref == 1); + + if ((netif = ip_route(dest)) == NULL) { + LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest))); + IP_STATS_INC(ip.rterr); + return ERR_RTE; + } + + NETIF_SET_HWADDRHINT(netif, addr_hint); + err = ip_output_if(p, src, dest, ttl, tos, proto, netif); + NETIF_SET_HWADDRHINT(netif, NULL); + + return err; +} +#endif /* LWIP_NETIF_HWADDRHINT*/ + +#if IP_DEBUG +/* Print an IP header by using LWIP_DEBUGF + * @param p an IP packet, p->payload pointing to the IP header + */ +void +ip_debug_print(struct pbuf *p) +{ + struct ip_hdr *iphdr = (struct ip_hdr *)p->payload; + + LWIP_DEBUGF(IP_DEBUG, ("IP header:\n")); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("|%2"S16_F" |%2"S16_F" | 0x%02"X16_F" | %5"U16_F" | (v, hl, tos, len)\n", + IPH_V(iphdr), + IPH_HL(iphdr), + IPH_TOS(iphdr), + ntohs(IPH_LEN(iphdr)))); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("| %5"U16_F" |%"U16_F"%"U16_F"%"U16_F"| %4"U16_F" | (id, flags, offset)\n", + ntohs(IPH_ID(iphdr)), + ntohs(IPH_OFFSET(iphdr)) >> 15 & 1, + ntohs(IPH_OFFSET(iphdr)) >> 14 & 1, + ntohs(IPH_OFFSET(iphdr)) >> 13 & 1, + ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | 0x%04"X16_F" | (ttl, proto, chksum)\n", + IPH_TTL(iphdr), + IPH_PROTO(iphdr), + ntohs(IPH_CHKSUM(iphdr)))); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (src)\n", + ip4_addr1_16(&iphdr->src), + ip4_addr2_16(&iphdr->src), + ip4_addr3_16(&iphdr->src), + ip4_addr4_16(&iphdr->src))); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (dest)\n", + ip4_addr1_16(&iphdr->dest), + ip4_addr2_16(&iphdr->dest), + ip4_addr3_16(&iphdr->dest), + ip4_addr4_16(&iphdr->dest))); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); +} +#endif /* IP_DEBUG */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/core/ipv4/ip_addr.c b/component/common/network/lwip/lwip_v1.4.1/src/core/ipv4/ip_addr.c new file mode 100644 index 0000000..8f633ff --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/core/ipv4/ip_addr.c @@ -0,0 +1,312 @@ +/** + * @file + * This is the IPv4 address tools implementation. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" + +/* used by IP_ADDR_ANY and IP_ADDR_BROADCAST in ip_addr.h */ +const ip_addr_t ip_addr_any = { IPADDR_ANY }; +const ip_addr_t ip_addr_broadcast = { IPADDR_BROADCAST }; + +/** + * Determine if an address is a broadcast address on a network interface + * + * @param addr address to be checked + * @param netif the network interface against which the address is checked + * @return returns non-zero if the address is a broadcast address + */ +u8_t +ip4_addr_isbroadcast(u32_t addr, const struct netif *netif) +{ + ip_addr_t ipaddr; + ip4_addr_set_u32(&ipaddr, addr); + + /* all ones (broadcast) or all zeroes (old skool broadcast) */ + if ((~addr == IPADDR_ANY) || + (addr == IPADDR_ANY)) { + return 1; + /* no broadcast support on this network interface? */ + } else if ((netif->flags & NETIF_FLAG_BROADCAST) == 0) { + /* the given address cannot be a broadcast address + * nor can we check against any broadcast addresses */ + return 0; + /* address matches network interface address exactly? => no broadcast */ + } else if (addr == ip4_addr_get_u32(&netif->ip_addr)) { + return 0; + /* on the same (sub) network... */ + } else if (ip_addr_netcmp(&ipaddr, &(netif->ip_addr), &(netif->netmask)) + /* ...and host identifier bits are all ones? =>... */ + && ((addr & ~ip4_addr_get_u32(&netif->netmask)) == + (IPADDR_BROADCAST & ~ip4_addr_get_u32(&netif->netmask)))) { + /* => network broadcast address */ + return 1; + } else { + return 0; + } +} + +/** Checks if a netmask is valid (starting with ones, then only zeros) + * + * @param netmask the IPv4 netmask to check (in network byte order!) + * @return 1 if the netmask is valid, 0 if it is not + */ +u8_t +ip4_addr_netmask_valid(u32_t netmask) +{ + u32_t mask; + u32_t nm_hostorder = lwip_htonl(netmask); + + /* first, check for the first zero */ + for (mask = 1UL << 31 ; mask != 0; mask >>= 1) { + if ((nm_hostorder & mask) == 0) { + break; + } + } + /* then check that there is no one */ + for (; mask != 0; mask >>= 1) { + if ((nm_hostorder & mask) != 0) { + /* there is a one after the first zero -> invalid */ + return 0; + } + } + /* no one after the first zero -> valid */ + return 1; +} + +/* Here for now until needed in other places in lwIP */ +#ifndef isprint +#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up) +#define isprint(c) in_range(c, 0x20, 0x7f) +#define isdigit(c) in_range(c, '0', '9') +#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F')) +#define islower(c) in_range(c, 'a', 'z') +#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v') +#endif + +/** + * Ascii internet address interpretation routine. + * The value returned is in network order. + * + * @param cp IP address in ascii represenation (e.g. "127.0.0.1") + * @return ip address in network order + */ +u32_t +ipaddr_addr(const char *cp) +{ + ip_addr_t val; + + if (ipaddr_aton(cp, &val)) { + return ip4_addr_get_u32(&val); + } + return (IPADDR_NONE); +} + +/** + * Check whether "cp" is a valid ascii representation + * of an Internet address and convert to a binary address. + * Returns 1 if the address is valid, 0 if not. + * This replaces inet_addr, the return value from which + * cannot distinguish between failure and a local broadcast address. + * + * @param cp IP address in ascii represenation (e.g. "127.0.0.1") + * @param addr pointer to which to save the ip address in network order + * @return 1 if cp could be converted to addr, 0 on failure + */ +int +ipaddr_aton(const char *cp, ip_addr_t *addr) +{ + u32_t val; + u8_t base; + char c; + u32_t parts[4]; + u32_t *pp = parts; + + c = *cp; + for (;;) { + /* + * Collect number up to ``.''. + * Values are specified as for C: + * 0x=hex, 0=octal, 1-9=decimal. + */ + if (!isdigit(c)) + return (0); + val = 0; + base = 10; + if (c == '0') { + c = *++cp; + if (c == 'x' || c == 'X') { + base = 16; + c = *++cp; + } else + base = 8; + } + for (;;) { + if (isdigit(c)) { + val = (val * base) + (int)(c - '0'); + c = *++cp; + } else if (base == 16 && isxdigit(c)) { + val = (val << 4) | (int)(c + 10 - (islower(c) ? 'a' : 'A')); + c = *++cp; + } else + break; + } + if (c == '.') { + /* + * Internet format: + * a.b.c.d + * a.b.c (with c treated as 16 bits) + * a.b (with b treated as 24 bits) + */ + if (pp >= parts + 3) { + return (0); + } + *pp++ = val; + c = *++cp; + } else + break; + } + /* + * Check for trailing characters. + */ + if (c != '\0' && !isspace(c)) { + return (0); + } + /* + * Concoct the address according to + * the number of parts specified. + */ + switch (pp - parts + 1) { + + case 0: + return (0); /* initial nondigit */ + + case 1: /* a -- 32 bits */ + break; + + case 2: /* a.b -- 8.24 bits */ + if (val > 0xffffffUL) { + return (0); + } + val |= parts[0] << 24; + break; + + case 3: /* a.b.c -- 8.8.16 bits */ + if (val > 0xffff) { + return (0); + } + val |= (parts[0] << 24) | (parts[1] << 16); + break; + + case 4: /* a.b.c.d -- 8.8.8.8 bits */ + if (val > 0xff) { + return (0); + } + val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); + break; + default: + LWIP_ASSERT("unhandled", 0); + break; + } + if (addr) { + ip4_addr_set_u32(addr, htonl(val)); + } + return (1); +} + +/** + * Convert numeric IP address into decimal dotted ASCII representation. + * returns ptr to static buffer; not reentrant! + * + * @param addr ip address in network order to convert + * @return pointer to a global static (!) buffer that holds the ASCII + * represenation of addr + */ +char * +ipaddr_ntoa(const ip_addr_t *addr) +{ + static char str[16]; + return ipaddr_ntoa_r(addr, str, 16); +} + +/** + * Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used. + * + * @param addr ip address in network order to convert + * @param buf target buffer where the string is stored + * @param buflen length of buf + * @return either pointer to buf which now holds the ASCII + * representation of addr or NULL if buf was too small + */ +char *ipaddr_ntoa_r(const ip_addr_t *addr, char *buf, int buflen) +{ + u32_t s_addr; + char inv[3]; + char *rp; + u8_t *ap; + u8_t rem; + u8_t n; + u8_t i; + int len = 0; + + s_addr = ip4_addr_get_u32(addr); + + rp = buf; + ap = (u8_t *)&s_addr; + for(n = 0; n < 4; n++) { + i = 0; + do { + rem = *ap % (u8_t)10; + *ap /= (u8_t)10; + inv[i++] = '0' + rem; + } while(*ap); + while(i--) { + if (len++ >= buflen) { + return NULL; + } + *rp++ = inv[i]; + } + if (len++ >= buflen) { + return NULL; + } + *rp++ = '.'; + ap++; + } + *--rp = 0; + return buf; +} diff --git a/component/common/network/lwip/lwip_v1.4.1/src/core/ipv4/ip_frag.c b/component/common/network/lwip/lwip_v1.4.1/src/core/ipv4/ip_frag.c new file mode 100644 index 0000000..8d18434 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/core/ipv4/ip_frag.c @@ -0,0 +1,863 @@ +/** + * @file + * This is the IPv4 packet segmentation and reassembly implementation. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Jani Monoses + * Simon Goldschmidt + * original reassembly code by Adam Dunkels + * + */ + +#include "lwip/opt.h" +#include "lwip/ip_frag.h" +#include "lwip/def.h" +#include "lwip/inet_chksum.h" +#include "lwip/netif.h" +#include "lwip/snmp.h" +#include "lwip/stats.h" +#include "lwip/icmp.h" + +#include + +#if IP_REASSEMBLY +/** + * The IP reassembly code currently has the following limitations: + * - IP header options are not supported + * - fragments must not overlap (e.g. due to different routes), + * currently, overlapping or duplicate fragments are thrown away + * if IP_REASS_CHECK_OVERLAP=1 (the default)! + * + * @todo: work with IP header options + */ + +/** Setting this to 0, you can turn off checking the fragments for overlapping + * regions. The code gets a little smaller. Only use this if you know that + * overlapping won't occur on your network! */ +#ifndef IP_REASS_CHECK_OVERLAP +#define IP_REASS_CHECK_OVERLAP 1 +#endif /* IP_REASS_CHECK_OVERLAP */ + +/** Set to 0 to prevent freeing the oldest datagram when the reassembly buffer is + * full (IP_REASS_MAX_PBUFS pbufs are enqueued). The code gets a little smaller. + * Datagrams will be freed by timeout only. Especially useful when MEMP_NUM_REASSDATA + * is set to 1, so one datagram can be reassembled at a time, only. */ +#ifndef IP_REASS_FREE_OLDEST +#define IP_REASS_FREE_OLDEST 1 +#endif /* IP_REASS_FREE_OLDEST */ + +#define IP_REASS_FLAG_LASTFRAG 0x01 + +/** This is a helper struct which holds the starting + * offset and the ending offset of this fragment to + * easily chain the fragments. + * It has the same packing requirements as the IP header, since it replaces + * the IP header in memory in incoming fragments (after copying it) to keep + * track of the various fragments. (-> If the IP header doesn't need packing, + * this struct doesn't need packing, too.) + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip_reass_helper { + PACK_STRUCT_FIELD(struct pbuf *next_pbuf); + PACK_STRUCT_FIELD(u16_t start); + PACK_STRUCT_FIELD(u16_t end); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define IP_ADDRESSES_AND_ID_MATCH(iphdrA, iphdrB) \ + (ip_addr_cmp(&(iphdrA)->src, &(iphdrB)->src) && \ + ip_addr_cmp(&(iphdrA)->dest, &(iphdrB)->dest) && \ + IPH_ID(iphdrA) == IPH_ID(iphdrB)) ? 1 : 0 + +/* global variables */ +static struct ip_reassdata *reassdatagrams; +static u16_t ip_reass_pbufcount; + +/* function prototypes */ +static void ip_reass_dequeue_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev); +static int ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev); + +/** + * Reassembly timer base function + * for both NO_SYS == 0 and 1 (!). + * + * Should be called every 1000 msec (defined by IP_TMR_INTERVAL). + */ +void +ip_reass_tmr(void) +{ + struct ip_reassdata *r, *prev = NULL; + + r = reassdatagrams; + while (r != NULL) { + /* Decrement the timer. Once it reaches 0, + * clean up the incomplete fragment assembly */ + if (r->timer > 0) { + r->timer--; + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass_tmr: timer dec %"U16_F"\n",(u16_t)r->timer)); + prev = r; + r = r->next; + } else { + /* reassembly timed out */ + struct ip_reassdata *tmp; + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass_tmr: timer timed out\n")); + tmp = r; + /* get the next pointer before freeing */ + r = r->next; + /* free the helper struct and all enqueued pbufs */ + ip_reass_free_complete_datagram(tmp, prev); + } + } +} + +/** + * Free a datagram (struct ip_reassdata) and all its pbufs. + * Updates the total count of enqueued pbufs (ip_reass_pbufcount), + * SNMP counters and sends an ICMP time exceeded packet. + * + * @param ipr datagram to free + * @param prev the previous datagram in the linked list + * @return the number of pbufs freed + */ +static int +ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev) +{ + u16_t pbufs_freed = 0; + u8_t clen; + struct pbuf *p; + struct ip_reass_helper *iprh; + + LWIP_ASSERT("prev != ipr", prev != ipr); + if (prev != NULL) { + LWIP_ASSERT("prev->next == ipr", prev->next == ipr); + } + + snmp_inc_ipreasmfails(); +#if LWIP_ICMP + iprh = (struct ip_reass_helper *)ipr->p->payload; + if (iprh->start == 0) { + /* The first fragment was received, send ICMP time exceeded. */ + /* First, de-queue the first pbuf from r->p. */ + p = ipr->p; + ipr->p = iprh->next_pbuf; + /* Then, copy the original header into it. */ + SMEMCPY(p->payload, &ipr->iphdr, IP_HLEN); + icmp_time_exceeded(p, ICMP_TE_FRAG); + clen = pbuf_clen(p); + LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); + pbufs_freed += clen; + pbuf_free(p); + } +#endif /* LWIP_ICMP */ + + /* First, free all received pbufs. The individual pbufs need to be released + separately as they have not yet been chained */ + p = ipr->p; + while (p != NULL) { + struct pbuf *pcur; + iprh = (struct ip_reass_helper *)p->payload; + pcur = p; + /* get the next pointer before freeing */ + p = iprh->next_pbuf; + clen = pbuf_clen(pcur); + LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); + pbufs_freed += clen; + pbuf_free(pcur); + } + /* Then, unchain the struct ip_reassdata from the list and free it. */ + ip_reass_dequeue_datagram(ipr, prev); + LWIP_ASSERT("ip_reass_pbufcount >= clen", ip_reass_pbufcount >= pbufs_freed); + ip_reass_pbufcount -= pbufs_freed; + + return pbufs_freed; +} + +#if IP_REASS_FREE_OLDEST +/** + * Free the oldest datagram to make room for enqueueing new fragments. + * The datagram 'fraghdr' belongs to is not freed! + * + * @param fraghdr IP header of the current fragment + * @param pbufs_needed number of pbufs needed to enqueue + * (used for freeing other datagrams if not enough space) + * @return the number of pbufs freed + */ +static int +ip_reass_remove_oldest_datagram(struct ip_hdr *fraghdr, int pbufs_needed) +{ + /* @todo Can't we simply remove the last datagram in the + * linked list behind reassdatagrams? + */ + struct ip_reassdata *r, *oldest, *prev; + int pbufs_freed = 0, pbufs_freed_current; + int other_datagrams; + + /* Free datagrams until being allowed to enqueue 'pbufs_needed' pbufs, + * but don't free the datagram that 'fraghdr' belongs to! */ + do { + oldest = NULL; + prev = NULL; + other_datagrams = 0; + r = reassdatagrams; + while (r != NULL) { + if (!IP_ADDRESSES_AND_ID_MATCH(&r->iphdr, fraghdr)) { + /* Not the same datagram as fraghdr */ + other_datagrams++; + if (oldest == NULL) { + oldest = r; + } else if (r->timer <= oldest->timer) { + /* older than the previous oldest */ + oldest = r; + } + } + if (r->next != NULL) { + prev = r; + } + r = r->next; + } + if (oldest != NULL) { + pbufs_freed_current = ip_reass_free_complete_datagram(oldest, prev); + pbufs_freed += pbufs_freed_current; + } + } while ((pbufs_freed < pbufs_needed) && (other_datagrams > 1)); + return pbufs_freed; +} +#endif /* IP_REASS_FREE_OLDEST */ + +/** + * Enqueues a new fragment into the fragment queue + * @param fraghdr points to the new fragments IP hdr + * @param clen number of pbufs needed to enqueue (used for freeing other datagrams if not enough space) + * @return A pointer to the queue location into which the fragment was enqueued + */ +static struct ip_reassdata* +ip_reass_enqueue_new_datagram(struct ip_hdr *fraghdr, int clen) +{ + struct ip_reassdata* ipr; + /* No matching previous fragment found, allocate a new reassdata struct */ + ipr = (struct ip_reassdata *)memp_malloc(MEMP_REASSDATA); + if (ipr == NULL) { +#if IP_REASS_FREE_OLDEST + if (ip_reass_remove_oldest_datagram(fraghdr, clen) >= clen) { + ipr = (struct ip_reassdata *)memp_malloc(MEMP_REASSDATA); + } + if (ipr == NULL) +#endif /* IP_REASS_FREE_OLDEST */ + { + IPFRAG_STATS_INC(ip_frag.memerr); + LWIP_DEBUGF(IP_REASS_DEBUG,("Failed to alloc reassdata struct\n")); + return NULL; + } + } + memset(ipr, 0, sizeof(struct ip_reassdata)); + ipr->timer = IP_REASS_MAXAGE; + + /* enqueue the new structure to the front of the list */ + ipr->next = reassdatagrams; + reassdatagrams = ipr; + /* copy the ip header for later tests and input */ + /* @todo: no ip options supported? */ + SMEMCPY(&(ipr->iphdr), fraghdr, IP_HLEN); + return ipr; +} + +/** + * Dequeues a datagram from the datagram queue. Doesn't deallocate the pbufs. + * @param ipr points to the queue entry to dequeue + */ +static void +ip_reass_dequeue_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev) +{ + + /* dequeue the reass struct */ + if (reassdatagrams == ipr) { + /* it was the first in the list */ + reassdatagrams = ipr->next; + } else { + /* it wasn't the first, so it must have a valid 'prev' */ + LWIP_ASSERT("sanity check linked list", prev != NULL); + prev->next = ipr->next; + } + + /* now we can free the ip_reass struct */ + memp_free(MEMP_REASSDATA, ipr); +} + +/** + * Chain a new pbuf into the pbuf list that composes the datagram. The pbuf list + * will grow over time as new pbufs are rx. + * Also checks that the datagram passes basic continuity checks (if the last + * fragment was received at least once). + * @param root_p points to the 'root' pbuf for the current datagram being assembled. + * @param new_p points to the pbuf for the current fragment + * @return 0 if invalid, >0 otherwise + */ +static int +ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct pbuf *new_p) +{ + struct ip_reass_helper *iprh, *iprh_tmp, *iprh_prev=NULL; + struct pbuf *q; + u16_t offset,len; + struct ip_hdr *fraghdr; + int valid = 1; + + /* Extract length and fragment offset from current fragment */ + fraghdr = (struct ip_hdr*)new_p->payload; + len = ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4; + offset = (ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8; + + /* overwrite the fragment's ip header from the pbuf with our helper struct, + * and setup the embedded helper structure. */ + /* make sure the struct ip_reass_helper fits into the IP header */ + LWIP_ASSERT("sizeof(struct ip_reass_helper) <= IP_HLEN", + sizeof(struct ip_reass_helper) <= IP_HLEN); + iprh = (struct ip_reass_helper*)new_p->payload; + iprh->next_pbuf = NULL; + iprh->start = offset; + iprh->end = offset + len; + + /* Iterate through until we either get to the end of the list (append), + * or we find on with a larger offset (insert). */ + for (q = ipr->p; q != NULL;) { + iprh_tmp = (struct ip_reass_helper*)q->payload; + if (iprh->start < iprh_tmp->start) { + /* the new pbuf should be inserted before this */ + iprh->next_pbuf = q; + if (iprh_prev != NULL) { + /* not the fragment with the lowest offset */ +#if IP_REASS_CHECK_OVERLAP + if ((iprh->start < iprh_prev->end) || (iprh->end > iprh_tmp->start)) { + /* fragment overlaps with previous or following, throw away */ + goto freepbuf; + } +#endif /* IP_REASS_CHECK_OVERLAP */ + iprh_prev->next_pbuf = new_p; + } else { + /* fragment with the lowest offset */ + ipr->p = new_p; + } + break; + } else if(iprh->start == iprh_tmp->start) { + /* received the same datagram twice: no need to keep the datagram */ + goto freepbuf; +#if IP_REASS_CHECK_OVERLAP + } else if(iprh->start < iprh_tmp->end) { + /* overlap: no need to keep the new datagram */ + goto freepbuf; +#endif /* IP_REASS_CHECK_OVERLAP */ + } else { + /* Check if the fragments received so far have no wholes. */ + if (iprh_prev != NULL) { + if (iprh_prev->end != iprh_tmp->start) { + /* There is a fragment missing between the current + * and the previous fragment */ + valid = 0; + } + } + } + q = iprh_tmp->next_pbuf; + iprh_prev = iprh_tmp; + } + + /* If q is NULL, then we made it to the end of the list. Determine what to do now */ + if (q == NULL) { + if (iprh_prev != NULL) { + /* this is (for now), the fragment with the highest offset: + * chain it to the last fragment */ +#if IP_REASS_CHECK_OVERLAP + LWIP_ASSERT("check fragments don't overlap", iprh_prev->end <= iprh->start); +#endif /* IP_REASS_CHECK_OVERLAP */ + iprh_prev->next_pbuf = new_p; + if (iprh_prev->end != iprh->start) { + valid = 0; + } + } else { +#if IP_REASS_CHECK_OVERLAP + LWIP_ASSERT("no previous fragment, this must be the first fragment!", + ipr->p == NULL); +#endif /* IP_REASS_CHECK_OVERLAP */ + /* this is the first fragment we ever received for this ip datagram */ + ipr->p = new_p; + } + } + + /* At this point, the validation part begins: */ + /* If we already received the last fragment */ + if ((ipr->flags & IP_REASS_FLAG_LASTFRAG) != 0) { + /* and had no wholes so far */ + if (valid) { + /* then check if the rest of the fragments is here */ + /* Check if the queue starts with the first datagram */ + if (((struct ip_reass_helper*)ipr->p->payload)->start != 0) { + valid = 0; + } else { + /* and check that there are no wholes after this datagram */ + iprh_prev = iprh; + q = iprh->next_pbuf; + while (q != NULL) { + iprh = (struct ip_reass_helper*)q->payload; + if (iprh_prev->end != iprh->start) { + valid = 0; + break; + } + iprh_prev = iprh; + q = iprh->next_pbuf; + } + /* if still valid, all fragments are received + * (because to the MF==0 already arrived */ + if (valid) { + LWIP_ASSERT("sanity check", ipr->p != NULL); + LWIP_ASSERT("sanity check", + ((struct ip_reass_helper*)ipr->p->payload) != iprh); + LWIP_ASSERT("validate_datagram:next_pbuf!=NULL", + iprh->next_pbuf == NULL); + LWIP_ASSERT("validate_datagram:datagram end!=datagram len", + iprh->end == ipr->datagram_len); + } + } + } + /* If valid is 0 here, there are some fragments missing in the middle + * (since MF == 0 has already arrived). Such datagrams simply time out if + * no more fragments are received... */ + return valid; + } + /* If we come here, not all fragments were received, yet! */ + return 0; /* not yet valid! */ +#if IP_REASS_CHECK_OVERLAP +freepbuf: + ip_reass_pbufcount -= pbuf_clen(new_p); + pbuf_free(new_p); + return 0; +#endif /* IP_REASS_CHECK_OVERLAP */ +} + +/** + * Reassembles incoming IP fragments into an IP datagram. + * + * @param p points to a pbuf chain of the fragment + * @return NULL if reassembly is incomplete, ? otherwise + */ +struct pbuf * +ip_reass(struct pbuf *p) +{ + struct pbuf *r; + struct ip_hdr *fraghdr; + struct ip_reassdata *ipr; + struct ip_reass_helper *iprh; + u16_t offset, len; + u8_t clen; + struct ip_reassdata *ipr_prev = NULL; + + IPFRAG_STATS_INC(ip_frag.recv); + snmp_inc_ipreasmreqds(); + + fraghdr = (struct ip_hdr*)p->payload; + + if ((IPH_HL(fraghdr) * 4) != IP_HLEN) { + LWIP_DEBUGF(IP_REASS_DEBUG,("ip_reass: IP options currently not supported!\n")); + IPFRAG_STATS_INC(ip_frag.err); + goto nullreturn; + } + + offset = (ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8; + len = ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4; + + /* Check if we are allowed to enqueue more datagrams. */ + clen = pbuf_clen(p); + if ((ip_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS) { +#if IP_REASS_FREE_OLDEST + if (!ip_reass_remove_oldest_datagram(fraghdr, clen) || + ((ip_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS)) +#endif /* IP_REASS_FREE_OLDEST */ + { + /* No datagram could be freed and still too many pbufs enqueued */ + LWIP_DEBUGF(IP_REASS_DEBUG,("ip_reass: Overflow condition: pbufct=%d, clen=%d, MAX=%d\n", + ip_reass_pbufcount, clen, IP_REASS_MAX_PBUFS)); + IPFRAG_STATS_INC(ip_frag.memerr); + /* @todo: send ICMP time exceeded here? */ + /* drop this pbuf */ + goto nullreturn; + } + } + + /* Look for the datagram the fragment belongs to in the current datagram queue, + * remembering the previous in the queue for later dequeueing. */ + for (ipr = reassdatagrams; ipr != NULL; ipr = ipr->next) { + /* Check if the incoming fragment matches the one currently present + in the reassembly buffer. If so, we proceed with copying the + fragment into the buffer. */ + if (IP_ADDRESSES_AND_ID_MATCH(&ipr->iphdr, fraghdr)) { + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: matching previous fragment ID=%"X16_F"\n", + ntohs(IPH_ID(fraghdr)))); + IPFRAG_STATS_INC(ip_frag.cachehit); + break; + } + ipr_prev = ipr; + } + + if (ipr == NULL) { + /* Enqueue a new datagram into the datagram queue */ + ipr = ip_reass_enqueue_new_datagram(fraghdr, clen); + /* Bail if unable to enqueue */ + if(ipr == NULL) { + goto nullreturn; + } + } else { + if (((ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) == 0) && + ((ntohs(IPH_OFFSET(&ipr->iphdr)) & IP_OFFMASK) != 0)) { + /* ipr->iphdr is not the header from the first fragment, but fraghdr is + * -> copy fraghdr into ipr->iphdr since we want to have the header + * of the first fragment (for ICMP time exceeded and later, for copying + * all options, if supported)*/ + SMEMCPY(&ipr->iphdr, fraghdr, IP_HLEN); + } + } + /* Track the current number of pbufs current 'in-flight', in order to limit + the number of fragments that may be enqueued at any one time */ + ip_reass_pbufcount += clen; + + /* At this point, we have either created a new entry or pointing + * to an existing one */ + + /* check for 'no more fragments', and update queue entry*/ + if ((IPH_OFFSET(fraghdr) & PP_NTOHS(IP_MF)) == 0) { + ipr->flags |= IP_REASS_FLAG_LASTFRAG; + ipr->datagram_len = offset + len; + LWIP_DEBUGF(IP_REASS_DEBUG, + ("ip_reass: last fragment seen, total len %"S16_F"\n", + ipr->datagram_len)); + } + /* find the right place to insert this pbuf */ + /* @todo: trim pbufs if fragments are overlapping */ + if (ip_reass_chain_frag_into_datagram_and_validate(ipr, p)) { + /* the totally last fragment (flag more fragments = 0) was received at least + * once AND all fragments are received */ + ipr->datagram_len += IP_HLEN; + + /* save the second pbuf before copying the header over the pointer */ + r = ((struct ip_reass_helper*)ipr->p->payload)->next_pbuf; + + /* copy the original ip header back to the first pbuf */ + fraghdr = (struct ip_hdr*)(ipr->p->payload); + SMEMCPY(fraghdr, &ipr->iphdr, IP_HLEN); + IPH_LEN_SET(fraghdr, htons(ipr->datagram_len)); + IPH_OFFSET_SET(fraghdr, 0); + IPH_CHKSUM_SET(fraghdr, 0); + /* @todo: do we need to set calculate the correct checksum? */ + IPH_CHKSUM_SET(fraghdr, inet_chksum(fraghdr, IP_HLEN)); + + p = ipr->p; + + /* chain together the pbufs contained within the reass_data list. */ + while(r != NULL) { + iprh = (struct ip_reass_helper*)r->payload; + + /* hide the ip header for every succeding fragment */ + pbuf_header(r, -IP_HLEN); + pbuf_cat(p, r); + r = iprh->next_pbuf; + } + /* release the sources allocate for the fragment queue entry */ + ip_reass_dequeue_datagram(ipr, ipr_prev); + + /* and adjust the number of pbufs currently queued for reassembly. */ + ip_reass_pbufcount -= pbuf_clen(p); + + /* Return the pbuf chain */ + return p; + } + /* the datagram is not (yet?) reassembled completely */ + LWIP_DEBUGF(IP_REASS_DEBUG,("ip_reass_pbufcount: %d out\n", ip_reass_pbufcount)); + return NULL; + +nullreturn: + LWIP_DEBUGF(IP_REASS_DEBUG,("ip_reass: nullreturn\n")); + IPFRAG_STATS_INC(ip_frag.drop); + pbuf_free(p); + return NULL; +} +#endif /* IP_REASSEMBLY */ + +#if IP_FRAG +#if IP_FRAG_USES_STATIC_BUF +static u8_t buf[LWIP_MEM_ALIGN_SIZE(IP_FRAG_MAX_MTU + MEM_ALIGNMENT - 1)]; +#else /* IP_FRAG_USES_STATIC_BUF */ + +#if !LWIP_NETIF_TX_SINGLE_PBUF +/** Allocate a new struct pbuf_custom_ref */ +static struct pbuf_custom_ref* +ip_frag_alloc_pbuf_custom_ref(void) +{ + return (struct pbuf_custom_ref*)memp_malloc(MEMP_FRAG_PBUF); +} + +/** Free a struct pbuf_custom_ref */ +static void +ip_frag_free_pbuf_custom_ref(struct pbuf_custom_ref* p) +{ + LWIP_ASSERT("p != NULL", p != NULL); + memp_free(MEMP_FRAG_PBUF, p); +} + +/** Free-callback function to free a 'struct pbuf_custom_ref', called by + * pbuf_free. */ +static void +ipfrag_free_pbuf_custom(struct pbuf *p) +{ + struct pbuf_custom_ref *pcr = (struct pbuf_custom_ref*)p; + LWIP_ASSERT("pcr != NULL", pcr != NULL); + LWIP_ASSERT("pcr == p", (void*)pcr == (void*)p); + if (pcr->original != NULL) { + pbuf_free(pcr->original); + } + ip_frag_free_pbuf_custom_ref(pcr); +} +#endif /* !LWIP_NETIF_TX_SINGLE_PBUF */ +#endif /* IP_FRAG_USES_STATIC_BUF */ + +/** + * Fragment an IP datagram if too large for the netif. + * + * Chop the datagram in MTU sized chunks and send them in order + * by using a fixed size static memory buffer (PBUF_REF) or + * point PBUF_REFs into p (depending on IP_FRAG_USES_STATIC_BUF). + * + * @param p ip packet to send + * @param netif the netif on which to send + * @param dest destination ip address to which to send + * + * @return ERR_OK if sent successfully, err_t otherwise + */ +err_t +ip_frag(struct pbuf *p, struct netif *netif, ip_addr_t *dest) +{ + struct pbuf *rambuf; +#if IP_FRAG_USES_STATIC_BUF + struct pbuf *header; +#else +#if !LWIP_NETIF_TX_SINGLE_PBUF + struct pbuf *newpbuf; +#endif + struct ip_hdr *original_iphdr; +#endif + struct ip_hdr *iphdr; + u16_t nfb; + u16_t left, cop; + u16_t mtu = netif->mtu; + u16_t ofo, omf; + u16_t last; + u16_t poff = IP_HLEN; + u16_t tmp; +#if !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF + u16_t newpbuflen = 0; + u16_t left_to_copy; +#endif + + /* Get a RAM based MTU sized pbuf */ +#if IP_FRAG_USES_STATIC_BUF + /* When using a static buffer, we use a PBUF_REF, which we will + * use to reference the packet (without link header). + * Layer and length is irrelevant. + */ + rambuf = pbuf_alloc(PBUF_LINK, 0, PBUF_REF); + if (rambuf == NULL) { + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_frag: pbuf_alloc(PBUF_LINK, 0, PBUF_REF) failed\n")); + return ERR_MEM; + } + rambuf->tot_len = rambuf->len = mtu; + rambuf->payload = LWIP_MEM_ALIGN((void *)buf); + + /* Copy the IP header in it */ + iphdr = (struct ip_hdr *)rambuf->payload; + SMEMCPY(iphdr, p->payload, IP_HLEN); +#else /* IP_FRAG_USES_STATIC_BUF */ + original_iphdr = (struct ip_hdr *)p->payload; + iphdr = original_iphdr; +#endif /* IP_FRAG_USES_STATIC_BUF */ + + /* Save original offset */ + tmp = ntohs(IPH_OFFSET(iphdr)); + ofo = tmp & IP_OFFMASK; + omf = tmp & IP_MF; + + left = p->tot_len - IP_HLEN; + + nfb = (mtu - IP_HLEN) / 8; + + while (left) { + last = (left <= mtu - IP_HLEN); + + /* Set new offset and MF flag */ + tmp = omf | (IP_OFFMASK & (ofo)); + if (!last) { + tmp = tmp | IP_MF; + } + + /* Fill this fragment */ + cop = last ? left : nfb * 8; + +#if IP_FRAG_USES_STATIC_BUF + poff += pbuf_copy_partial(p, (u8_t*)iphdr + IP_HLEN, cop, poff); +#else /* IP_FRAG_USES_STATIC_BUF */ +#if LWIP_NETIF_TX_SINGLE_PBUF + rambuf = pbuf_alloc(PBUF_IP, cop, PBUF_RAM); + if (rambuf == NULL) { + return ERR_MEM; + } + LWIP_ASSERT("this needs a pbuf in one piece!", + (rambuf->len == rambuf->tot_len) && (rambuf->next == NULL)); + poff += pbuf_copy_partial(p, rambuf->payload, cop, poff); + /* make room for the IP header */ + if(pbuf_header(rambuf, IP_HLEN)) { + pbuf_free(rambuf); + return ERR_MEM; + } + /* fill in the IP header */ + SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN); + iphdr = rambuf->payload; +#else /* LWIP_NETIF_TX_SINGLE_PBUF */ + /* When not using a static buffer, create a chain of pbufs. + * The first will be a PBUF_RAM holding the link and IP header. + * The rest will be PBUF_REFs mirroring the pbuf chain to be fragged, + * but limited to the size of an mtu. + */ + rambuf = pbuf_alloc(PBUF_LINK, IP_HLEN, PBUF_RAM); + if (rambuf == NULL) { + return ERR_MEM; + } + LWIP_ASSERT("this needs a pbuf in one piece!", + (p->len >= (IP_HLEN))); + SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN); + iphdr = (struct ip_hdr *)rambuf->payload; + + /* Can just adjust p directly for needed offset. */ + p->payload = (u8_t *)p->payload + poff; + p->len -= poff; + + left_to_copy = cop; + while (left_to_copy) { + struct pbuf_custom_ref *pcr; + newpbuflen = (left_to_copy < p->len) ? left_to_copy : p->len; + /* Is this pbuf already empty? */ + if (!newpbuflen) { + p = p->next; + continue; + } + pcr = ip_frag_alloc_pbuf_custom_ref(); + if (pcr == NULL) { + pbuf_free(rambuf); + return ERR_MEM; + } + /* Mirror this pbuf, although we might not need all of it. */ + newpbuf = pbuf_alloced_custom(PBUF_RAW, newpbuflen, PBUF_REF, &pcr->pc, p->payload, newpbuflen); + if (newpbuf == NULL) { + ip_frag_free_pbuf_custom_ref(pcr); + pbuf_free(rambuf); + return ERR_MEM; + } + pbuf_ref(p); + pcr->original = p; + pcr->pc.custom_free_function = ipfrag_free_pbuf_custom; + + /* Add it to end of rambuf's chain, but using pbuf_cat, not pbuf_chain + * so that it is removed when pbuf_dechain is later called on rambuf. + */ + pbuf_cat(rambuf, newpbuf); + left_to_copy -= newpbuflen; + if (left_to_copy) { + p = p->next; + } + } + poff = newpbuflen; +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ +#endif /* IP_FRAG_USES_STATIC_BUF */ + + /* Correct header */ + IPH_OFFSET_SET(iphdr, htons(tmp)); + IPH_LEN_SET(iphdr, htons(cop + IP_HLEN)); + IPH_CHKSUM_SET(iphdr, 0); + IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN)); + +#if IP_FRAG_USES_STATIC_BUF + if (last) { + pbuf_realloc(rambuf, left + IP_HLEN); + } + + /* This part is ugly: we alloc a RAM based pbuf for + * the link level header for each chunk and then + * free it.A PBUF_ROM style pbuf for which pbuf_header + * worked would make things simpler. + */ + header = pbuf_alloc(PBUF_LINK, 0, PBUF_RAM); + if (header != NULL) { + pbuf_chain(header, rambuf); + netif->output(netif, header, dest); + IPFRAG_STATS_INC(ip_frag.xmit); + snmp_inc_ipfragcreates(); + pbuf_free(header); + } else { + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_frag: pbuf_alloc() for header failed\n")); + pbuf_free(rambuf); + return ERR_MEM; + } +#else /* IP_FRAG_USES_STATIC_BUF */ + /* No need for separate header pbuf - we allowed room for it in rambuf + * when allocated. + */ + netif->output(netif, rambuf, dest); + IPFRAG_STATS_INC(ip_frag.xmit); + + /* Unfortunately we can't reuse rambuf - the hardware may still be + * using the buffer. Instead we free it (and the ensuing chain) and + * recreate it next time round the loop. If we're lucky the hardware + * will have already sent the packet, the free will really free, and + * there will be zero memory penalty. + */ + + pbuf_free(rambuf); +#endif /* IP_FRAG_USES_STATIC_BUF */ + left -= cop; + ofo += nfb; + } +#if IP_FRAG_USES_STATIC_BUF + pbuf_free(rambuf); +#endif /* IP_FRAG_USES_STATIC_BUF */ + snmp_inc_ipfragoks(); + return ERR_OK; +} +#endif /* IP_FRAG */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/core/ipv6/README b/component/common/network/lwip/lwip_v1.4.1/src/core/ipv6/README new file mode 100644 index 0000000..3620004 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/core/ipv6/README @@ -0,0 +1 @@ +IPv6 support in lwIP is very experimental. diff --git a/component/common/network/lwip/lwip_v1.4.1/src/core/ipv6/icmp6.c b/component/common/network/lwip/lwip_v1.4.1/src/core/ipv6/icmp6.c new file mode 100644 index 0000000..4fcc895 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/core/ipv6/icmp6.c @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/* Some ICMP messages should be passed to the transport protocols. This + is not implemented. */ + +#include "lwip/opt.h" + +#if LWIP_ICMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/icmp.h" +#include "lwip/inet.h" +#include "lwip/ip.h" +#include "lwip/def.h" +#include "lwip/stats.h" + +void +icmp_input(struct pbuf *p, struct netif *inp) +{ + u8_t type; + struct icmp_echo_hdr *iecho; + struct ip_hdr *iphdr; + struct ip_addr tmpaddr; + + ICMP_STATS_INC(icmp.recv); + + /* TODO: check length before accessing payload! */ + + type = ((u8_t *)p->payload)[0]; + + switch (type) { + case ICMP6_ECHO: + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ping\n")); + + if (p->tot_len < sizeof(struct icmp_echo_hdr)) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n")); + + pbuf_free(p); + ICMP_STATS_INC(icmp.lenerr); + return; + } + iecho = p->payload; + iphdr = (struct ip_hdr *)((u8_t *)p->payload - IP_HLEN); + if (inet_chksum_pbuf(p) != 0) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo (%"X16_F")\n", inet_chksum_pseudo(p, &(iphdr->src), &(iphdr->dest), IP_PROTO_ICMP, p->tot_len))); + ICMP_STATS_INC(icmp.chkerr); + /* return;*/ + } + LWIP_DEBUGF(ICMP_DEBUG, ("icmp: p->len %"S16_F" p->tot_len %"S16_F"\n", p->len, p->tot_len)); + ip_addr_set(&tmpaddr, &(iphdr->src)); + ip_addr_set(&(iphdr->src), &(iphdr->dest)); + ip_addr_set(&(iphdr->dest), &tmpaddr); + iecho->type = ICMP6_ER; + /* adjust the checksum */ + if (iecho->chksum >= htons(0xffff - (ICMP6_ECHO << 8))) { + iecho->chksum += htons(ICMP6_ECHO << 8) + 1; + } else { + iecho->chksum += htons(ICMP6_ECHO << 8); + } + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo (%"X16_F")\n", inet_chksum_pseudo(p, &(iphdr->src), &(iphdr->dest), IP_PROTO_ICMP, p->tot_len))); + ICMP_STATS_INC(icmp.xmit); + + /* LWIP_DEBUGF("icmp: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len);*/ + ip_output_if (p, &(iphdr->src), IP_HDRINCL, + iphdr->hoplim, IP_PROTO_ICMP, inp); + break; + default: + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %"S16_F" not supported.\n", (s16_t)type)); + ICMP_STATS_INC(icmp.proterr); + ICMP_STATS_INC(icmp.drop); + } + + pbuf_free(p); +} + +void +icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t) +{ + struct pbuf *q; + struct ip_hdr *iphdr; + struct icmp_dur_hdr *idur; + + /* @todo: can this be PBUF_LINK instead of PBUF_IP? */ + q = pbuf_alloc(PBUF_IP, 8 + IP_HLEN + 8, PBUF_RAM); + /* ICMP header + IP header + 8 bytes of data */ + if (q == NULL) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_dest_unreach: failed to allocate pbuf for ICMP packet.\n")); + pbuf_free(p); + return; + } + LWIP_ASSERT("check that first pbuf can hold icmp message", + (q->len >= (8 + IP_HLEN + 8))); + + iphdr = p->payload; + + idur = q->payload; + idur->type = (u8_t)ICMP6_DUR; + idur->icode = (u8_t)t; + + SMEMCPY((u8_t *)q->payload + 8, p->payload, IP_HLEN + 8); + + /* calculate checksum */ + idur->chksum = 0; + idur->chksum = inet_chksum(idur, q->len); + ICMP_STATS_INC(icmp.xmit); + + ip_output(q, NULL, + (struct ip_addr *)&(iphdr->src), ICMP_TTL, IP_PROTO_ICMP); + pbuf_free(q); +} + +void +icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t) +{ + struct pbuf *q; + struct ip_hdr *iphdr; + struct icmp_te_hdr *tehdr; + + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded\n")); + + /* @todo: can this be PBUF_LINK instead of PBUF_IP? */ + q = pbuf_alloc(PBUF_IP, 8 + IP_HLEN + 8, PBUF_RAM); + /* ICMP header + IP header + 8 bytes of data */ + if (q == NULL) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_dest_unreach: failed to allocate pbuf for ICMP packet.\n")); + pbuf_free(p); + return; + } + LWIP_ASSERT("check that first pbuf can hold icmp message", + (q->len >= (8 + IP_HLEN + 8))); + + iphdr = p->payload; + + tehdr = q->payload; + tehdr->type = (u8_t)ICMP6_TE; + tehdr->icode = (u8_t)t; + + /* copy fields from original packet */ + SMEMCPY((u8_t *)q->payload + 8, (u8_t *)p->payload, IP_HLEN + 8); + + /* calculate checksum */ + tehdr->chksum = 0; + tehdr->chksum = inet_chksum(tehdr, q->len); + ICMP_STATS_INC(icmp.xmit); + ip_output(q, NULL, + (struct ip_addr *)&(iphdr->src), ICMP_TTL, IP_PROTO_ICMP); + pbuf_free(q); +} + +#endif /* LWIP_ICMP */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/core/ipv6/inet6.c b/component/common/network/lwip/lwip_v1.4.1/src/core/ipv6/inet6.c new file mode 100644 index 0000000..c3de85c --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/core/ipv6/inet6.c @@ -0,0 +1,163 @@ +/** + * @file + * Functions common to all TCP/IPv6 modules, such as the Internet checksum and the + * byte order functions. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/def.h" +#include "lwip/inet.h" + +/* chksum: + * + * Sums up all 16 bit words in a memory portion. Also includes any odd byte. + * This function is used by the other checksum functions. + * + * For now, this is not optimized. Must be optimized for the particular processor + * arcitecture on which it is to run. Preferebly coded in assembler. + */ + +static u32_t +chksum(void *dataptr, u16_t len) +{ + u16_t *sdataptr = dataptr; + u32_t acc; + + + for(acc = 0; len > 1; len -= 2) { + acc += *sdataptr++; + } + + /* add up any odd byte */ + if (len == 1) { + acc += htons((u16_t)(*(u8_t *)dataptr) << 8); + } + + return acc; + +} + +/* inet_chksum_pseudo: + * + * Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain. + */ + +u16_t +inet_chksum_pseudo(struct pbuf *p, + struct ip_addr *src, struct ip_addr *dest, + u8_t proto, u32_t proto_len) +{ + u32_t acc; + struct pbuf *q; + u8_t swapped, i; + + acc = 0; + swapped = 0; + for(q = p; q != NULL; q = q->next) { + acc += chksum(q->payload, q->len); + while (acc >> 16) { + acc = (acc & 0xffff) + (acc >> 16); + } + if (q->len % 2 != 0) { + swapped = 1 - swapped; + acc = ((acc & 0xff) << 8) | ((acc & 0xff00) >> 8); + } + } + + if (swapped) { + acc = ((acc & 0xff) << 8) | ((acc & 0xff00) >> 8); + } + + for(i = 0; i < 8; i++) { + acc += ((u16_t *)src->addr)[i] & 0xffff; + acc += ((u16_t *)dest->addr)[i] & 0xffff; + while (acc >> 16) { + acc = (acc & 0xffff) + (acc >> 16); + } + } + acc += (u16_t)htons((u16_t)proto); + acc += ((u16_t *)&proto_len)[0] & 0xffff; + acc += ((u16_t *)&proto_len)[1] & 0xffff; + + while (acc >> 16) { + acc = (acc & 0xffff) + (acc >> 16); + } + return ~(acc & 0xffff); +} + +/* inet_chksum: + * + * Calculates the Internet checksum over a portion of memory. Used primarely for IP + * and ICMP. + */ + +u16_t +inet_chksum(void *dataptr, u16_t len) +{ + u32_t acc, sum; + + acc = chksum(dataptr, len); + sum = (acc & 0xffff) + (acc >> 16); + sum += (sum >> 16); + return ~(sum & 0xffff); +} + +u16_t +inet_chksum_pbuf(struct pbuf *p) +{ + u32_t acc; + struct pbuf *q; + u8_t swapped; + + acc = 0; + swapped = 0; + for(q = p; q != NULL; q = q->next) { + acc += chksum(q->payload, q->len); + while (acc >> 16) { + acc = (acc & 0xffff) + (acc >> 16); + } + if (q->len % 2 != 0) { + swapped = 1 - swapped; + acc = (acc & 0xff << 8) | (acc & 0xff00 >> 8); + } + } + + if (swapped) { + acc = ((acc & 0xff) << 8) | ((acc & 0xff00) >> 8); + } + return ~(acc & 0xffff); +} diff --git a/component/common/network/lwip/lwip_v1.4.1/src/core/ipv6/ip6.c b/component/common/network/lwip/lwip_v1.4.1/src/core/ipv6/ip6.c new file mode 100644 index 0000000..ad59b72 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/core/ipv6/ip6.c @@ -0,0 +1,397 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + + + +/* ip.c + * + * This is the code for the IP layer for IPv6. + * + */ + + +#include "lwip/opt.h" + +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/ip.h" +#include "lwip/inet.h" +#include "lwip/netif.h" +#include "lwip/icmp.h" +#include "lwip/udp.h" +#include "lwip/tcp_impl.h" + +#include "lwip/stats.h" + +#include "arch/perf.h" + +/* ip_init: + * + * Initializes the IP layer. + */ + +void +ip_init(void) +{ +} + +/* ip_route: + * + * Finds the appropriate network interface for a given IP address. It searches the + * list of network interfaces linearly. A match is found if the masked IP address of + * the network interface equals the masked IP address given to the function. + */ + +struct netif * +ip_route(struct ip_addr *dest) +{ + struct netif *netif; + + for(netif = netif_list; netif != NULL; netif = netif->next) { + if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) { + return netif; + } + } + + return netif_default; +} + +/* ip_forward: + * + * Forwards an IP packet. It finds an appropriate route for the packet, decrements + * the TTL value of the packet, adjusts the checksum and outputs the packet on the + * appropriate interface. + */ + +static void +ip_forward(struct pbuf *p, struct ip_hdr *iphdr) +{ + struct netif *netif; + + PERF_START; + + if ((netif = ip_route((struct ip_addr *)&(iphdr->dest))) == NULL) { + + LWIP_DEBUGF(IP_DEBUG, ("ip_input: no forwarding route found for ")); +#if IP_DEBUG + ip_addr_debug_print(IP_DEBUG, ((struct ip_addr *)&(iphdr->dest))); +#endif /* IP_DEBUG */ + LWIP_DEBUGF(IP_DEBUG, ("\n")); + pbuf_free(p); + return; + } + /* Decrement TTL and send ICMP if ttl == 0. */ + if (--iphdr->hoplim == 0) { +#if LWIP_ICMP + /* Don't send ICMP messages in response to ICMP messages */ + if (iphdr->nexthdr != IP_PROTO_ICMP) { + icmp_time_exceeded(p, ICMP_TE_TTL); + } +#endif /* LWIP_ICMP */ + pbuf_free(p); + return; + } + + /* Incremental update of the IP checksum. */ + /* if (iphdr->chksum >= htons(0xffff - 0x100)) { + iphdr->chksum += htons(0x100) + 1; + } else { + iphdr->chksum += htons(0x100); + }*/ + + + LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to ")); +#if IP_DEBUG + ip_addr_debug_print(IP_DEBUG, ((struct ip_addr *)&(iphdr->dest))); +#endif /* IP_DEBUG */ + LWIP_DEBUGF(IP_DEBUG, ("\n")); + + IP_STATS_INC(ip.fw); + IP_STATS_INC(ip.xmit); + + PERF_STOP("ip_forward"); + + netif->output(netif, p, (struct ip_addr *)&(iphdr->dest)); +} + +/* ip_input: + * + * This function is called by the network interface device driver when an IP packet is + * received. The function does the basic checks of the IP header such as packet size + * being at least larger than the header size etc. If the packet was not destined for + * us, the packet is forwarded (using ip_forward). The IP checksum is always checked. + * + * Finally, the packet is sent to the upper layer protocol input function. + */ + +void +ip_input(struct pbuf *p, struct netif *inp) { + struct ip_hdr *iphdr; + struct netif *netif; + + + PERF_START; + +#if IP_DEBUG + ip_debug_print(p); +#endif /* IP_DEBUG */ + + + IP_STATS_INC(ip.recv); + + /* identify the IP header */ + iphdr = p->payload; + + + if (iphdr->v != 6) { + LWIP_DEBUGF(IP_DEBUG, ("IP packet dropped due to bad version number\n")); +#if IP_DEBUG + ip_debug_print(p); +#endif /* IP_DEBUG */ + pbuf_free(p); + IP_STATS_INC(ip.err); + IP_STATS_INC(ip.drop); + return; + } + + /* is this packet for us? */ + for(netif = netif_list; netif != NULL; netif = netif->next) { +#if IP_DEBUG + LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest ")); + ip_addr_debug_print(IP_DEBUG, ((struct ip_addr *)&(iphdr->dest))); + LWIP_DEBUGF(IP_DEBUG, ("netif->ip_addr ")); + ip_addr_debug_print(IP_DEBUG, ((struct ip_addr *)&(iphdr->dest))); + LWIP_DEBUGF(IP_DEBUG, ("\n")); +#endif /* IP_DEBUG */ + if (ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr))) { + break; + } + } + + + if (netif == NULL) { + /* packet not for us, route or discard */ +#if IP_FORWARD + ip_forward(p, iphdr); +#endif + pbuf_free(p); + return; + } + + pbuf_realloc(p, IP_HLEN + ntohs(iphdr->len)); + + /* send to upper layers */ +#if IP_DEBUG + /* LWIP_DEBUGF("ip_input: \n"); + ip_debug_print(p); + LWIP_DEBUGF("ip_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len);*/ +#endif /* IP_DEBUG */ + + if(pbuf_header(p, -IP_HLEN)) { + LWIP_ASSERT("Can't move over header in packet", 0); + return; + } + + switch (iphdr->nexthdr) { + case IP_PROTO_UDP: + udp_input(p, inp); + break; + case IP_PROTO_TCP: + tcp_input(p, inp); + break; +#if LWIP_ICMP + case IP_PROTO_ICMP: + icmp_input(p, inp); + break; +#endif /* LWIP_ICMP */ + default: +#if LWIP_ICMP + /* send ICMP destination protocol unreachable */ + icmp_dest_unreach(p, ICMP_DUR_PROTO); +#endif /* LWIP_ICMP */ + pbuf_free(p); + LWIP_DEBUGF(IP_DEBUG, ("Unsupported transport protocol %"U16_F"\n", + iphdr->nexthdr)); + + IP_STATS_INC(ip.proterr); + IP_STATS_INC(ip.drop); + } + PERF_STOP("ip_input"); +} + + +/* ip_output_if: + * + * Sends an IP packet on a network interface. This function constructs the IP header + * and calculates the IP header checksum. If the source IP address is NULL, + * the IP address of the outgoing network interface is filled in as source address. + */ + +err_t +ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, + u8_t ttl, + u8_t proto, struct netif *netif) +{ + struct ip_hdr *iphdr; + + PERF_START; + + LWIP_DEBUGF(IP_DEBUG, ("len %"U16_F" tot_len %"U16_F"\n", p->len, p->tot_len)); + if (pbuf_header(p, IP_HLEN)) { + LWIP_DEBUGF(IP_DEBUG, ("ip_output: not enough room for IP header in pbuf\n")); + IP_STATS_INC(ip.err); + + return ERR_BUF; + } + LWIP_DEBUGF(IP_DEBUG, ("len %"U16_F" tot_len %"U16_F"\n", p->len, p->tot_len)); + + iphdr = p->payload; + + + if (dest != IP_HDRINCL) { + LWIP_DEBUGF(IP_DEBUG, ("!IP_HDRLINCL\n")); + iphdr->hoplim = ttl; + iphdr->nexthdr = proto; + iphdr->len = htons(p->tot_len - IP_HLEN); + ip_addr_set(&(iphdr->dest), dest); + + iphdr->v = 6; + + if (ip_addr_isany(src)) { + ip_addr_set(&(iphdr->src), &(netif->ip_addr)); + } else { + ip_addr_set(&(iphdr->src), src); + } + + } else { + dest = &(iphdr->dest); + } + + IP_STATS_INC(ip.xmit); + + LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c (len %"U16_F")\n", netif->name[0], netif->name[1], p->tot_len)); +#if IP_DEBUG + ip_debug_print(p); +#endif /* IP_DEBUG */ + + PERF_STOP("ip_output_if"); + return netif->output(netif, p, dest); +} + +/* ip_output: + * + * Simple interface to ip_output_if. It finds the outgoing network interface and + * calls upon ip_output_if to do the actual work. + */ + +err_t +ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, + u8_t ttl, u8_t proto) +{ + struct netif *netif; + if ((netif = ip_route(dest)) == NULL) { + LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to 0x%"X32_F"\n", dest->addr)); + IP_STATS_INC(ip.rterr); + return ERR_RTE; + } + + return ip_output_if (p, src, dest, ttl, proto, netif); +} + +#if LWIP_NETIF_HWADDRHINT +err_t +ip_output_hinted(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, + u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint) +{ + struct netif *netif; + err_t err; + + if ((netif = ip_route(dest)) == NULL) { + LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to 0x%"X32_F"\n", dest->addr)); + IP_STATS_INC(ip.rterr); + return ERR_RTE; + } + + LWIP_NETIF_HWADDRHINT(netif, addr_hint); + err = ip_output_if(p, src, dest, ttl, tos, proto, netif); + LWIP_NETIF_HWADDRHINT(netif, NULL); + + return err; +} +#endif /* LWIP_NETIF_HWADDRHINT*/ + +#if IP_DEBUG +void +ip_debug_print(struct pbuf *p) +{ + struct ip_hdr *iphdr = p->payload; + + LWIP_DEBUGF(IP_DEBUG, ("IP header:\n")); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("|%2"S16_F" | %"X16_F"%"X16_F" | %"X16_F"%"X16_F" | (v, traffic class, flow label)\n", + iphdr->v, + iphdr->tclass1, iphdr->tclass2, + iphdr->flow1, iphdr->flow2)); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("| %5"U16_F" | %2"U16_F" | %2"U16_F" | (len, nexthdr, hoplim)\n", + ntohs(iphdr->len), + iphdr->nexthdr, + iphdr->hoplim)); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (src)\n", + (ntohl(iphdr->src.addr[0]) >> 16) & 0xffff, + ntohl(iphdr->src.addr[0]) & 0xffff)); + LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (src)\n", + (ntohl(iphdr->src.addr[1]) >> 16) & 0xffff, + ntohl(iphdr->src.addr[1]) & 0xffff)); + LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (src)\n", + (ntohl(iphdr->src.addr[2]) >> 16) & 0xffff, + ntohl(iphdr->src.addr[2]) & 0xffff)); + LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (src)\n", + (ntohl(iphdr->src.addr[3]) >> 16) & 0xffff, + ntohl(iphdr->src.addr[3]) & 0xffff)); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (dest)\n", + (ntohl(iphdr->dest.addr[0]) >> 16) & 0xffff, + ntohl(iphdr->dest.addr[0]) & 0xffff)); + LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (dest)\n", + (ntohl(iphdr->dest.addr[1]) >> 16) & 0xffff, + ntohl(iphdr->dest.addr[1]) & 0xffff)); + LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (dest)\n", + (ntohl(iphdr->dest.addr[2]) >> 16) & 0xffff, + ntohl(iphdr->dest.addr[2]) & 0xffff)); + LWIP_DEBUGF(IP_DEBUG, ("| %4"X32_F" | %4"X32_F" | (dest)\n", + (ntohl(iphdr->dest.addr[3]) >> 16) & 0xffff, + ntohl(iphdr->dest.addr[3]) & 0xffff)); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); +} +#endif /* IP_DEBUG */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/core/ipv6/ip6_addr.c b/component/common/network/lwip/lwip_v1.4.1/src/core/ipv6/ip6_addr.c new file mode 100644 index 0000000..2da6cea --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/core/ipv6/ip6_addr.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" +#include "lwip/ip_addr.h" +#include "lwip/inet.h" + +u8_t +ip_addr_netcmp(struct ip_addr *addr1, struct ip_addr *addr2, + struct ip_addr *mask) +{ + return((addr1->addr[0] & mask->addr[0]) == (addr2->addr[0] & mask->addr[0]) && + (addr1->addr[1] & mask->addr[1]) == (addr2->addr[1] & mask->addr[1]) && + (addr1->addr[2] & mask->addr[2]) == (addr2->addr[2] & mask->addr[2]) && + (addr1->addr[3] & mask->addr[3]) == (addr2->addr[3] & mask->addr[3])); + +} + +u8_t +ip_addr_cmp(struct ip_addr *addr1, struct ip_addr *addr2) +{ + return(addr1->addr[0] == addr2->addr[0] && + addr1->addr[1] == addr2->addr[1] && + addr1->addr[2] == addr2->addr[2] && + addr1->addr[3] == addr2->addr[3]); +} + +void +ip_addr_set(struct ip_addr *dest, struct ip_addr *src) +{ + SMEMCPY(dest, src, sizeof(struct ip_addr)); + /* dest->addr[0] = src->addr[0]; + dest->addr[1] = src->addr[1]; + dest->addr[2] = src->addr[2]; + dest->addr[3] = src->addr[3];*/ +} + +u8_t +ip_addr_isany(struct ip_addr *addr) +{ + if (addr == NULL) return 1; + return((addr->addr[0] | addr->addr[1] | addr->addr[2] | addr->addr[3]) == 0); +} diff --git a/component/common/network/lwip/lwip_v1.4.1/src/core/lwip_timers.c b/component/common/network/lwip/lwip_v1.4.1/src/core/lwip_timers.c new file mode 100644 index 0000000..cf7cb03 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/core/lwip_timers.c @@ -0,0 +1,487 @@ +/** + * @file + * Stack-internal timers implementation. + * This file includes timer callbacks for stack-internal timers as well as + * functions to set up or stop timers and check for expired timers. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * Simon Goldschmidt + * + */ + +#include "lwip/opt.h" + +#include "lwip/lwip_timers.h" +#include "lwip/tcp_impl.h" + +#if LWIP_TIMERS + +#include "lwip/def.h" +#include "lwip/memp.h" +#include "lwip/tcpip.h" + +#include "lwip/ip_frag.h" +#include "netif/etharp.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" +#include "lwip/igmp.h" +#include "lwip/dns.h" +#include "lwip/sys.h" +#include "lwip/pbuf.h" + + +/** The one and only timeout list */ +static struct sys_timeo *next_timeout; +#if NO_SYS +static u32_t timeouts_last_time; +#endif /* NO_SYS */ + +#if LWIP_TCP +/** global variable that shows if the tcp timer is currently scheduled or not */ +static int tcpip_tcp_timer_active; + +/** + * Timer callback function that calls tcp_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +tcpip_tcp_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + + /* call TCP timer handler */ + tcp_tmr(); + /* timer still needed? */ + if (tcp_active_pcbs || tcp_tw_pcbs) { + /* restart timer */ + sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL); + } else { + /* disable timer */ + tcpip_tcp_timer_active = 0; + } +} + +/** + * Called from TCP_REG when registering a new PCB: + * the reason is to have the TCP timer only running when + * there are active (or time-wait) PCBs. + */ +void +tcp_timer_needed(void) +{ + /* timer is off but needed again? */ + if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) { + /* enable and start timer */ + tcpip_tcp_timer_active = 1; + sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL); + } +} +#endif /* LWIP_TCP */ + +#if IP_REASSEMBLY +/** + * Timer callback function that calls ip_reass_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +ip_reass_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: ip_reass_tmr()\n")); + ip_reass_tmr(); + sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL); +} +#endif /* IP_REASSEMBLY */ + +#if LWIP_ARP +/** + * Timer callback function that calls etharp_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +arp_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: etharp_tmr()\n")); + etharp_tmr(); + sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); +} +#endif /* LWIP_ARP */ + +#if LWIP_DHCP +/** + * Timer callback function that calls dhcp_coarse_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +dhcp_timer_coarse(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dhcp_coarse_tmr()\n")); + dhcp_coarse_tmr(); + sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL); +} + +/** + * Timer callback function that calls dhcp_fine_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +dhcp_timer_fine(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dhcp_fine_tmr()\n")); + dhcp_fine_tmr(); + sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL); +} +#endif /* LWIP_DHCP */ + +#if LWIP_AUTOIP +/** + * Timer callback function that calls autoip_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +autoip_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: autoip_tmr()\n")); + autoip_tmr(); + sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL); +} +#endif /* LWIP_AUTOIP */ + +#if LWIP_IGMP +/** + * Timer callback function that calls igmp_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +igmp_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: igmp_tmr()\n")); + igmp_tmr(); + sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL); +} +#endif /* LWIP_IGMP */ + +#if LWIP_DNS +/** + * Timer callback function that calls dns_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +dns_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dns_tmr()\n")); + dns_tmr(); + sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL); +} +#endif /* LWIP_DNS */ + +/** Initialize this module */ +void sys_timeouts_init(void) +{ +#if IP_REASSEMBLY + sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL); +#endif /* IP_REASSEMBLY */ +#if LWIP_ARP + sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); +#endif /* LWIP_ARP */ +#if LWIP_DHCP + sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL); + sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL); +#endif /* LWIP_DHCP */ +#if LWIP_AUTOIP + sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL); +#endif /* LWIP_AUTOIP */ +#if LWIP_IGMP + sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL); +#endif /* LWIP_IGMP */ +#if LWIP_DNS + sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL); +#endif /* LWIP_DNS */ + +#if NO_SYS + /* Initialise timestamp for sys_check_timeouts */ + timeouts_last_time = sys_now(); +#endif +} + +/** + * Create a one-shot timer (aka timeout). Timeouts are processed in the + * following cases: + * - while waiting for a message using sys_timeouts_mbox_fetch() + * - by calling sys_check_timeouts() (NO_SYS==1 only) + * + * @param msecs time in milliseconds after that the timer should expire + * @param handler callback function to call when msecs have elapsed + * @param arg argument to pass to the callback function + */ +#if LWIP_DEBUG_TIMERNAMES +void +sys_timeout_debug(u32_t msecs, sys_timeout_handler handler, void *arg, const char* handler_name) +#else /* LWIP_DEBUG_TIMERNAMES */ +void +sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg) +#endif /* LWIP_DEBUG_TIMERNAMES */ +{ + struct sys_timeo *timeout, *t; + + timeout = (struct sys_timeo *)memp_malloc(MEMP_SYS_TIMEOUT); + if (timeout == NULL) { + LWIP_ASSERT("sys_timeout: timeout != NULL, pool MEMP_SYS_TIMEOUT is empty", timeout != NULL); + return; + } + timeout->next = NULL; + timeout->h = handler; + timeout->arg = arg; + timeout->time = msecs; +#if LWIP_DEBUG_TIMERNAMES + timeout->handler_name = handler_name; + LWIP_DEBUGF(TIMERS_DEBUG, ("sys_timeout: %p msecs=%"U32_F" handler=%s arg=%p\n", + (void *)timeout, msecs, handler_name, (void *)arg)); +#endif /* LWIP_DEBUG_TIMERNAMES */ + + if (next_timeout == NULL) { + next_timeout = timeout; + return; + } + + if (next_timeout->time > msecs) { + next_timeout->time -= msecs; + timeout->next = next_timeout; + next_timeout = timeout; + } else { + for(t = next_timeout; t != NULL; t = t->next) { + timeout->time -= t->time; + if (t->next == NULL || t->next->time > timeout->time) { + if (t->next != NULL) { + t->next->time -= timeout->time; + } + timeout->next = t->next; + t->next = timeout; + break; + } + } + } +} + +/** + * Go through timeout list (for this task only) and remove the first matching + * entry, even though the timeout has not triggered yet. + * + * @note This function only works as expected if there is only one timeout + * calling 'handler' in the list of timeouts. + * + * @param handler callback function that would be called by the timeout + * @param arg callback argument that would be passed to handler +*/ +void +sys_untimeout(sys_timeout_handler handler, void *arg) +{ + struct sys_timeo *prev_t, *t; + + if (next_timeout == NULL) { + return; + } + + for (t = next_timeout, prev_t = NULL; t != NULL; prev_t = t, t = t->next) { + if ((t->h == handler) && (t->arg == arg)) { + /* We have a match */ + /* Unlink from previous in list */ + if (prev_t == NULL) { + next_timeout = t->next; + } else { + prev_t->next = t->next; + } + /* If not the last one, add time of this one back to next */ + if (t->next != NULL) { + t->next->time += t->time; + } + memp_free(MEMP_SYS_TIMEOUT, t); + return; + } + } + return; +} + +#if NO_SYS + +/** Handle timeouts for NO_SYS==1 (i.e. without using + * tcpip_thread/sys_timeouts_mbox_fetch(). Uses sys_now() to call timeout + * handler functions when timeouts expire. + * + * Must be called periodically from your main loop. + */ +void +sys_check_timeouts(void) +{ + if (next_timeout) { + struct sys_timeo *tmptimeout; + u32_t diff; + sys_timeout_handler handler; + void *arg; + u8_t had_one; + u32_t now; + + now = sys_now(); + /* this cares for wraparounds */ + diff = now - timeouts_last_time; + do + { +#if PBUF_POOL_FREE_OOSEQ + PBUF_CHECK_FREE_OOSEQ(); +#endif /* PBUF_POOL_FREE_OOSEQ */ + had_one = 0; + tmptimeout = next_timeout; + if (tmptimeout && (tmptimeout->time <= diff)) { + /* timeout has expired */ + had_one = 1; + timeouts_last_time = now; + diff -= tmptimeout->time; + next_timeout = tmptimeout->next; + handler = tmptimeout->h; + arg = tmptimeout->arg; +#if LWIP_DEBUG_TIMERNAMES + if (handler != NULL) { + LWIP_DEBUGF(TIMERS_DEBUG, ("sct calling h=%s arg=%p\n", + tmptimeout->handler_name, arg)); + } +#endif /* LWIP_DEBUG_TIMERNAMES */ + memp_free(MEMP_SYS_TIMEOUT, tmptimeout); + if (handler != NULL) { + handler(arg); + } + } + /* repeat until all expired timers have been called */ + }while(had_one); + } +} + +/** Set back the timestamp of the last call to sys_check_timeouts() + * This is necessary if sys_check_timeouts() hasn't been called for a long + * time (e.g. while saving energy) to prevent all timer functions of that + * period being called. + */ +void +sys_restart_timeouts(void) +{ + timeouts_last_time = sys_now(); +} + +#else /* NO_SYS */ + +/** + * Wait (forever) for a message to arrive in an mbox. + * While waiting, timeouts are processed. + * + * @param mbox the mbox to fetch the message from + * @param msg the place to store the message + */ +void +sys_timeouts_mbox_fetch(sys_mbox_t *mbox, void **msg) +{ + u32_t time_needed; + struct sys_timeo *tmptimeout; + sys_timeout_handler handler; + void *arg; + + again: + if (!next_timeout) { + time_needed = sys_arch_mbox_fetch(mbox, msg, 0); + } else { + if (next_timeout->time > 0) { + time_needed = sys_arch_mbox_fetch(mbox, msg, next_timeout->time); + } else { + time_needed = SYS_ARCH_TIMEOUT; + } + + if (time_needed == SYS_ARCH_TIMEOUT) { + /* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message + could be fetched. We should now call the timeout handler and + deallocate the memory allocated for the timeout. */ + tmptimeout = next_timeout; + next_timeout = tmptimeout->next; + handler = tmptimeout->h; + arg = tmptimeout->arg; +#if LWIP_DEBUG_TIMERNAMES + if (handler != NULL) { + LWIP_DEBUGF(TIMERS_DEBUG, ("stmf calling h=%s arg=%p\n", + tmptimeout->handler_name, arg)); + } +#endif /* LWIP_DEBUG_TIMERNAMES */ + memp_free(MEMP_SYS_TIMEOUT, tmptimeout); + if (handler != NULL) { + /* For LWIP_TCPIP_CORE_LOCKING, lock the core before calling the + timeout handler function. */ + LOCK_TCPIP_CORE(); + handler(arg); + UNLOCK_TCPIP_CORE(); + } + LWIP_TCPIP_THREAD_ALIVE(); + + /* We try again to fetch a message from the mbox. */ + goto again; + } else { + /* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout + occured. The time variable is set to the number of + milliseconds we waited for the message. */ + if (time_needed < next_timeout->time) { + next_timeout->time -= time_needed; + } else { + next_timeout->time = 0; + } + } + } +} + +#endif /* NO_SYS */ + +#else /* LWIP_TIMERS */ +/* Satisfy the TCP code which calls this function */ +void +tcp_timer_needed(void) +{ +} +#endif /* LWIP_TIMERS */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/core/mem.c b/component/common/network/lwip/lwip_v1.4.1/src/core/mem.c new file mode 100644 index 0000000..1659a2c --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/core/mem.c @@ -0,0 +1,659 @@ +/** + * @file + * Dynamic memory manager + * + * This is a lightweight replacement for the standard C library malloc(). + * + * If you want to use the standard C library malloc() instead, define + * MEM_LIBC_MALLOC to 1 in your lwipopts.h + * + * To let mem_malloc() use pools (prevents fragmentation and is much faster than + * a heap but might waste some memory), define MEM_USE_POOLS to 1, define + * MEM_USE_CUSTOM_POOLS to 1 and create a file "lwippools.h" that includes a list + * of pools like this (more pools can be added between _START and _END): + * + * Define three pools with sizes 256, 512, and 1512 bytes + * LWIP_MALLOC_MEMPOOL_START + * LWIP_MALLOC_MEMPOOL(20, 256) + * LWIP_MALLOC_MEMPOOL(10, 512) + * LWIP_MALLOC_MEMPOOL(5, 1512) + * LWIP_MALLOC_MEMPOOL_END + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * Simon Goldschmidt + * + */ + +#include "lwip/opt.h" + +#if !MEM_LIBC_MALLOC /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/sys.h" +#include "lwip/stats.h" +#include "lwip/err.h" + +#include + +#if MEM_USE_POOLS +/* lwIP head implemented with different sized pools */ + +/** + * Allocate memory: determine the smallest pool that is big enough + * to contain an element of 'size' and get an element from that pool. + * + * @param size the size in bytes of the memory needed + * @return a pointer to the allocated memory or NULL if the pool is empty + */ +void * +mem_malloc(mem_size_t size) +{ + void *ret; + struct memp_malloc_helper *element; + memp_t poolnr; + mem_size_t required_size = size + LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper)); + + for (poolnr = MEMP_POOL_FIRST; poolnr <= MEMP_POOL_LAST; poolnr = (memp_t)(poolnr + 1)) { +#if MEM_USE_POOLS_TRY_BIGGER_POOL +again: +#endif /* MEM_USE_POOLS_TRY_BIGGER_POOL */ + /* is this pool big enough to hold an element of the required size + plus a struct memp_malloc_helper that saves the pool this element came from? */ + if (required_size <= memp_sizes[poolnr]) { + break; + } + } + if (poolnr > MEMP_POOL_LAST) { + LWIP_ASSERT("mem_malloc(): no pool is that big!", 0); + return NULL; + } + element = (struct memp_malloc_helper*)memp_malloc(poolnr); + if (element == NULL) { + /* No need to DEBUGF or ASSERT: This error is already + taken care of in memp.c */ +#if MEM_USE_POOLS_TRY_BIGGER_POOL + /** Try a bigger pool if this one is empty! */ + if (poolnr < MEMP_POOL_LAST) { + poolnr++; + goto again; + } +#endif /* MEM_USE_POOLS_TRY_BIGGER_POOL */ + return NULL; + } + + /* save the pool number this element came from */ + element->poolnr = poolnr; + /* and return a pointer to the memory directly after the struct memp_malloc_helper */ + ret = (u8_t*)element + LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper)); + + return ret; +} + +/** + * Free memory previously allocated by mem_malloc. Loads the pool number + * and calls memp_free with that pool number to put the element back into + * its pool + * + * @param rmem the memory element to free + */ +void +mem_free(void *rmem) +{ + struct memp_malloc_helper *hmem; + + LWIP_ASSERT("rmem != NULL", (rmem != NULL)); + LWIP_ASSERT("rmem == MEM_ALIGN(rmem)", (rmem == LWIP_MEM_ALIGN(rmem))); + + /* get the original struct memp_malloc_helper */ + hmem = (struct memp_malloc_helper*)(void*)((u8_t*)rmem - LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper))); + + LWIP_ASSERT("hmem != NULL", (hmem != NULL)); + LWIP_ASSERT("hmem == MEM_ALIGN(hmem)", (hmem == LWIP_MEM_ALIGN(hmem))); + LWIP_ASSERT("hmem->poolnr < MEMP_MAX", (hmem->poolnr < MEMP_MAX)); + + /* and put it in the pool we saved earlier */ + memp_free(hmem->poolnr, hmem); +} + +#else /* MEM_USE_POOLS */ +/* lwIP replacement for your libc malloc() */ + +/** + * The heap is made up as a list of structs of this type. + * This does not have to be aligned since for getting its size, + * we only use the macro SIZEOF_STRUCT_MEM, which automatically alignes. + */ +struct mem { + /** index (-> ram[next]) of the next struct */ + mem_size_t next; + /** index (-> ram[prev]) of the previous struct */ + mem_size_t prev; + /** 1: this area is used; 0: this area is unused */ + u8_t used; +}; + +/** All allocated blocks will be MIN_SIZE bytes big, at least! + * MIN_SIZE can be overridden to suit your needs. Smaller values save space, + * larger values could prevent too small blocks to fragment the RAM too much. */ +#ifndef MIN_SIZE +#define MIN_SIZE 12 +#endif /* MIN_SIZE */ +/* some alignment macros: we define them here for better source code layout */ +#define MIN_SIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(MIN_SIZE) +#define SIZEOF_STRUCT_MEM LWIP_MEM_ALIGN_SIZE(sizeof(struct mem)) +#define MEM_SIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(MEM_SIZE) + +/** If you want to relocate the heap to external memory, simply define + * LWIP_RAM_HEAP_POINTER as a void-pointer to that location. + * If so, make sure the memory at that location is big enough (see below on + * how that space is calculated). */ +#ifndef LWIP_RAM_HEAP_POINTER +/** the heap. we need one struct mem at the end and some room for alignment */ +u8_t ram_heap[MEM_SIZE_ALIGNED + (2*SIZEOF_STRUCT_MEM) + MEM_ALIGNMENT]; +#define LWIP_RAM_HEAP_POINTER ram_heap +#endif /* LWIP_RAM_HEAP_POINTER */ + +/** pointer to the heap (ram_heap): for alignment, ram is now a pointer instead of an array */ +static u8_t *ram; +/** the last entry, always unused! */ +static struct mem *ram_end; +/** pointer to the lowest free block, this is used for faster search */ +static struct mem *lfree; + +/** concurrent access protection */ +#if !NO_SYS +static sys_mutex_t mem_mutex; +#endif + +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + +static volatile u8_t mem_free_count; + +/* Allow mem_free from other (e.g. interrupt) context */ +#define LWIP_MEM_FREE_DECL_PROTECT() SYS_ARCH_DECL_PROTECT(lev_free) +#define LWIP_MEM_FREE_PROTECT() SYS_ARCH_PROTECT(lev_free) +#define LWIP_MEM_FREE_UNPROTECT() SYS_ARCH_UNPROTECT(lev_free) +#define LWIP_MEM_ALLOC_DECL_PROTECT() SYS_ARCH_DECL_PROTECT(lev_alloc) +#define LWIP_MEM_ALLOC_PROTECT() SYS_ARCH_PROTECT(lev_alloc) +#define LWIP_MEM_ALLOC_UNPROTECT() SYS_ARCH_UNPROTECT(lev_alloc) + +#else /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + +/* Protect the heap only by using a semaphore */ +#define LWIP_MEM_FREE_DECL_PROTECT() +#define LWIP_MEM_FREE_PROTECT() sys_mutex_lock(&mem_mutex) +#define LWIP_MEM_FREE_UNPROTECT() sys_mutex_unlock(&mem_mutex) +/* mem_malloc is protected using semaphore AND LWIP_MEM_ALLOC_PROTECT */ +#define LWIP_MEM_ALLOC_DECL_PROTECT() +#define LWIP_MEM_ALLOC_PROTECT() +#define LWIP_MEM_ALLOC_UNPROTECT() + +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + + +/** + * "Plug holes" by combining adjacent empty struct mems. + * After this function is through, there should not exist + * one empty struct mem pointing to another empty struct mem. + * + * @param mem this points to a struct mem which just has been freed + * @internal this function is only called by mem_free() and mem_trim() + * + * This assumes access to the heap is protected by the calling function + * already. + */ +static void +plug_holes(struct mem *mem) +{ + struct mem *nmem; + struct mem *pmem; + + LWIP_ASSERT("plug_holes: mem >= ram", (u8_t *)mem >= ram); + LWIP_ASSERT("plug_holes: mem < ram_end", (u8_t *)mem < (u8_t *)ram_end); + LWIP_ASSERT("plug_holes: mem->used == 0", mem->used == 0); + + /* plug hole forward */ + LWIP_ASSERT("plug_holes: mem->next <= MEM_SIZE_ALIGNED", mem->next <= MEM_SIZE_ALIGNED); + + nmem = (struct mem *)(void *)&ram[mem->next]; + if (mem != nmem && nmem->used == 0 && (u8_t *)nmem != (u8_t *)ram_end) { + /* if mem->next is unused and not end of ram, combine mem and mem->next */ + if (lfree == nmem) { + lfree = mem; + } + mem->next = nmem->next; + ((struct mem *)(void *)&ram[nmem->next])->prev = (mem_size_t)((u8_t *)mem - ram); + } + + /* plug hole backward */ + pmem = (struct mem *)(void *)&ram[mem->prev]; + if (pmem != mem && pmem->used == 0) { + /* if mem->prev is unused, combine mem and mem->prev */ + if (lfree == mem) { + lfree = pmem; + } + pmem->next = mem->next; + ((struct mem *)(void *)&ram[mem->next])->prev = (mem_size_t)((u8_t *)pmem - ram); + } +} + +/** + * Zero the heap and initialize start, end and lowest-free + */ +void +mem_init(void) +{ + struct mem *mem; + + LWIP_ASSERT("Sanity check alignment", + (SIZEOF_STRUCT_MEM & (MEM_ALIGNMENT-1)) == 0); + + /* align the heap */ + ram = (u8_t *)LWIP_MEM_ALIGN(LWIP_RAM_HEAP_POINTER); + /* initialize the start of the heap */ + mem = (struct mem *)(void *)ram; + mem->next = MEM_SIZE_ALIGNED; + mem->prev = 0; + mem->used = 0; + /* initialize the end of the heap */ + ram_end = (struct mem *)(void *)&ram[MEM_SIZE_ALIGNED]; + ram_end->used = 1; + ram_end->next = MEM_SIZE_ALIGNED; + ram_end->prev = MEM_SIZE_ALIGNED; + + /* initialize the lowest-free pointer to the start of the heap */ + lfree = (struct mem *)(void *)ram; + + MEM_STATS_AVAIL(avail, MEM_SIZE_ALIGNED); + + if(sys_mutex_new(&mem_mutex) != ERR_OK) { + LWIP_ASSERT("failed to create mem_mutex", 0); + } +} + +/** + * Put a struct mem back on the heap + * + * @param rmem is the data portion of a struct mem as returned by a previous + * call to mem_malloc() + */ +void +mem_free(void *rmem) +{ + struct mem *mem; + LWIP_MEM_FREE_DECL_PROTECT(); + + if (rmem == NULL) { + LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("mem_free(p == NULL) was called.\n")); + return; + } + LWIP_ASSERT("mem_free: sanity check alignment", (((mem_ptr_t)rmem) & (MEM_ALIGNMENT-1)) == 0); + + LWIP_ASSERT("mem_free: legal memory", (u8_t *)rmem >= (u8_t *)ram && + (u8_t *)rmem < (u8_t *)ram_end); + + if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) { + SYS_ARCH_DECL_PROTECT(lev); + LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_free: illegal memory\n")); + /* protect mem stats from concurrent access */ + SYS_ARCH_PROTECT(lev); + MEM_STATS_INC(illegal); + SYS_ARCH_UNPROTECT(lev); + return; + } + /* protect the heap from concurrent access */ + LWIP_MEM_FREE_PROTECT(); + /* Get the corresponding struct mem ... */ + mem = (struct mem *)(void *)((u8_t *)rmem - SIZEOF_STRUCT_MEM); + /* ... which has to be in a used state ... */ + LWIP_ASSERT("mem_free: mem->used", mem->used); + /* ... and is now unused. */ + mem->used = 0; + + if (mem < lfree) { + /* the newly freed struct is now the lowest */ + lfree = mem; + } + + MEM_STATS_DEC_USED(used, mem->next - (mem_size_t)(((u8_t *)mem - ram))); + + /* finally, see if prev or next are free also */ + plug_holes(mem); +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + mem_free_count = 1; +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + LWIP_MEM_FREE_UNPROTECT(); +} + +/** + * Shrink memory returned by mem_malloc(). + * + * @param rmem pointer to memory allocated by mem_malloc the is to be shrinked + * @param newsize required size after shrinking (needs to be smaller than or + * equal to the previous size) + * @return for compatibility reasons: is always == rmem, at the moment + * or NULL if newsize is > old size, in which case rmem is NOT touched + * or freed! + */ +void * +mem_trim(void *rmem, mem_size_t newsize) +{ + mem_size_t size; + mem_size_t ptr, ptr2; + struct mem *mem, *mem2; + /* use the FREE_PROTECT here: it protects with sem OR SYS_ARCH_PROTECT */ + LWIP_MEM_FREE_DECL_PROTECT(); + + /* Expand the size of the allocated memory region so that we can + adjust for alignment. */ + newsize = LWIP_MEM_ALIGN_SIZE(newsize); + + if(newsize < MIN_SIZE_ALIGNED) { + /* every data block must be at least MIN_SIZE_ALIGNED long */ + newsize = MIN_SIZE_ALIGNED; + } + + if (newsize > MEM_SIZE_ALIGNED) { + return NULL; + } + + LWIP_ASSERT("mem_trim: legal memory", (u8_t *)rmem >= (u8_t *)ram && + (u8_t *)rmem < (u8_t *)ram_end); + + if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) { + SYS_ARCH_DECL_PROTECT(lev); + LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_trim: illegal memory\n")); + /* protect mem stats from concurrent access */ + SYS_ARCH_PROTECT(lev); + MEM_STATS_INC(illegal); + SYS_ARCH_UNPROTECT(lev); + return rmem; + } + /* Get the corresponding struct mem ... */ + mem = (struct mem *)(void *)((u8_t *)rmem - SIZEOF_STRUCT_MEM); + /* ... and its offset pointer */ + ptr = (mem_size_t)((u8_t *)mem - ram); + + size = mem->next - ptr - SIZEOF_STRUCT_MEM; + LWIP_ASSERT("mem_trim can only shrink memory", newsize <= size); + if (newsize > size) { + /* not supported */ + return NULL; + } + if (newsize == size) { + /* No change in size, simply return */ + return rmem; + } + + /* protect the heap from concurrent access */ + LWIP_MEM_FREE_PROTECT(); + + mem2 = (struct mem *)(void *)&ram[mem->next]; + if(mem2->used == 0) { + /* The next struct is unused, we can simply move it at little */ + mem_size_t next; + /* remember the old next pointer */ + next = mem2->next; + /* create new struct mem which is moved directly after the shrinked mem */ + ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize; + if (lfree == mem2) { + lfree = (struct mem *)(void *)&ram[ptr2]; + } + mem2 = (struct mem *)(void *)&ram[ptr2]; + mem2->used = 0; + /* restore the next pointer */ + mem2->next = next; + /* link it back to mem */ + mem2->prev = ptr; + /* link mem to it */ + mem->next = ptr2; + /* last thing to restore linked list: as we have moved mem2, + * let 'mem2->next->prev' point to mem2 again. but only if mem2->next is not + * the end of the heap */ + if (mem2->next != MEM_SIZE_ALIGNED) { + ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2; + } + MEM_STATS_DEC_USED(used, (size - newsize)); + /* no need to plug holes, we've already done that */ + } else if (newsize + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED <= size) { + /* Next struct is used but there's room for another struct mem with + * at least MIN_SIZE_ALIGNED of data. + * Old size ('size') must be big enough to contain at least 'newsize' plus a struct mem + * ('SIZEOF_STRUCT_MEM') with some data ('MIN_SIZE_ALIGNED'). + * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty + * region that couldn't hold data, but when mem->next gets freed, + * the 2 regions would be combined, resulting in more free memory */ + ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize; + mem2 = (struct mem *)(void *)&ram[ptr2]; + if (mem2 < lfree) { + lfree = mem2; + } + mem2->used = 0; + mem2->next = mem->next; + mem2->prev = ptr; + mem->next = ptr2; + if (mem2->next != MEM_SIZE_ALIGNED) { + ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2; + } + MEM_STATS_DEC_USED(used, (size - newsize)); + /* the original mem->next is used, so no need to plug holes! */ + } + /* else { + next struct mem is used but size between mem and mem2 is not big enough + to create another struct mem + -> don't do anyhting. + -> the remaining space stays unused since it is too small + } */ +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + mem_free_count = 1; +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + LWIP_MEM_FREE_UNPROTECT(); + return rmem; +} + +/** + * Adam's mem_malloc() plus solution for bug #17922 + * Allocate a block of memory with a minimum of 'size' bytes. + * + * @param size is the minimum size of the requested block in bytes. + * @return pointer to allocated memory or NULL if no free memory was found. + * + * Note that the returned value will always be aligned (as defined by MEM_ALIGNMENT). + */ +void * +mem_malloc(mem_size_t size) +{ + mem_size_t ptr, ptr2; + struct mem *mem, *mem2; +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + u8_t local_mem_free_count = 0; +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + LWIP_MEM_ALLOC_DECL_PROTECT(); + + if (size == 0) { + return NULL; + } + + /* Expand the size of the allocated memory region so that we can + adjust for alignment. */ + size = LWIP_MEM_ALIGN_SIZE(size); + + if(size < MIN_SIZE_ALIGNED) { + /* every data block must be at least MIN_SIZE_ALIGNED long */ + size = MIN_SIZE_ALIGNED; + } + + if (size > MEM_SIZE_ALIGNED) { + return NULL; + } + + /* protect the heap from concurrent access */ + sys_mutex_lock(&mem_mutex); + LWIP_MEM_ALLOC_PROTECT(); +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + /* run as long as a mem_free disturbed mem_malloc or mem_trim */ + do { + local_mem_free_count = 0; +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + + /* Scan through the heap searching for a free block that is big enough, + * beginning with the lowest free block. + */ + for (ptr = (mem_size_t)((u8_t *)lfree - ram); ptr < MEM_SIZE_ALIGNED - size; + ptr = ((struct mem *)(void *)&ram[ptr])->next) { + mem = (struct mem *)(void *)&ram[ptr]; +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + mem_free_count = 0; + LWIP_MEM_ALLOC_UNPROTECT(); + /* allow mem_free or mem_trim to run */ + LWIP_MEM_ALLOC_PROTECT(); + if (mem_free_count != 0) { + /* If mem_free or mem_trim have run, we have to restart since they + could have altered our current struct mem. */ + local_mem_free_count = 1; + break; + } +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + + if ((!mem->used) && + (mem->next - (ptr + SIZEOF_STRUCT_MEM)) >= size) { + /* mem is not used and at least perfect fit is possible: + * mem->next - (ptr + SIZEOF_STRUCT_MEM) gives us the 'user data size' of mem */ + + if (mem->next - (ptr + SIZEOF_STRUCT_MEM) >= (size + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED)) { + /* (in addition to the above, we test if another struct mem (SIZEOF_STRUCT_MEM) containing + * at least MIN_SIZE_ALIGNED of data also fits in the 'user data space' of 'mem') + * -> split large block, create empty remainder, + * remainder must be large enough to contain MIN_SIZE_ALIGNED data: if + * mem->next - (ptr + (2*SIZEOF_STRUCT_MEM)) == size, + * struct mem would fit in but no data between mem2 and mem2->next + * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty + * region that couldn't hold data, but when mem->next gets freed, + * the 2 regions would be combined, resulting in more free memory + */ + ptr2 = ptr + SIZEOF_STRUCT_MEM + size; + /* create mem2 struct */ + mem2 = (struct mem *)(void *)&ram[ptr2]; + mem2->used = 0; + mem2->next = mem->next; + mem2->prev = ptr; + /* and insert it between mem and mem->next */ + mem->next = ptr2; + mem->used = 1; + + if (mem2->next != MEM_SIZE_ALIGNED) { + ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2; + } + MEM_STATS_INC_USED(used, (size + SIZEOF_STRUCT_MEM)); + } else { + /* (a mem2 struct does no fit into the user data space of mem and mem->next will always + * be used at this point: if not we have 2 unused structs in a row, plug_holes should have + * take care of this). + * -> near fit or excact fit: do not split, no mem2 creation + * also can't move mem->next directly behind mem, since mem->next + * will always be used at this point! + */ + mem->used = 1; + MEM_STATS_INC_USED(used, mem->next - (mem_size_t)((u8_t *)mem - ram)); + } +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT +mem_malloc_adjust_lfree: +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + if (mem == lfree) { + struct mem *cur = lfree; + /* Find next free block after mem and update lowest free pointer */ + while (cur->used && cur != ram_end) { +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + mem_free_count = 0; + LWIP_MEM_ALLOC_UNPROTECT(); + /* prevent high interrupt latency... */ + LWIP_MEM_ALLOC_PROTECT(); + if (mem_free_count != 0) { + /* If mem_free or mem_trim have run, we have to restart since they + could have altered our current struct mem or lfree. */ + goto mem_malloc_adjust_lfree; + } +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + cur = (struct mem *)(void *)&ram[cur->next]; + } + lfree = cur; + LWIP_ASSERT("mem_malloc: !lfree->used", ((lfree == ram_end) || (!lfree->used))); + } + LWIP_MEM_ALLOC_UNPROTECT(); + sys_mutex_unlock(&mem_mutex); + LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.", + (mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end); + LWIP_ASSERT("mem_malloc: allocated memory properly aligned.", + ((mem_ptr_t)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0); + LWIP_ASSERT("mem_malloc: sanity check alignment", + (((mem_ptr_t)mem) & (MEM_ALIGNMENT-1)) == 0); + + return (u8_t *)mem + SIZEOF_STRUCT_MEM; + } + } +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + /* if we got interrupted by a mem_free, try again */ + } while(local_mem_free_count != 0); +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("mem_malloc: could not allocate %"S16_F" bytes\n", (s16_t)size)); + MEM_STATS_INC(err); + LWIP_MEM_ALLOC_UNPROTECT(); + sys_mutex_unlock(&mem_mutex); + return NULL; +} + +#endif /* MEM_USE_POOLS */ +/** + * Contiguously allocates enough space for count objects that are size bytes + * of memory each and returns a pointer to the allocated memory. + * + * The allocated memory is filled with bytes of value zero. + * + * @param count number of objects to allocate + * @param size size of the objects to allocate + * @return pointer to allocated memory / NULL pointer if there is an error + */ +void *mem_calloc(mem_size_t count, mem_size_t size) +{ + void *p; + + /* allocate 'count' objects of size 'size' */ + p = mem_malloc(count * size); + if (p) { + /* zero the memory */ + memset(p, 0, count * size); + } + return p; +} + +#endif /* !MEM_LIBC_MALLOC */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/core/memp.c b/component/common/network/lwip/lwip_v1.4.1/src/core/memp.c new file mode 100644 index 0000000..24a12b1 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/core/memp.c @@ -0,0 +1,470 @@ +/** + * @file + * Dynamic pool memory manager + * + * lwIP has dedicated pools for many structures (netconn, protocol control blocks, + * packet buffers, ...). All these pools are managed here. + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/memp.h" +#include "lwip/pbuf.h" +#include "lwip/udp.h" +#include "lwip/raw.h" +#include "lwip/tcp_impl.h" +#include "lwip/igmp.h" +#include "lwip/api.h" +#include "lwip/api_msg.h" +#include "lwip/tcpip.h" +#include "lwip/sys.h" +#include "lwip/lwip_timers.h" +#include "lwip/stats.h" +#include "netif/etharp.h" +#include "lwip/ip_frag.h" +#include "lwip/snmp_structs.h" +#include "lwip/snmp_msg.h" +#include "lwip/dns.h" +#include "netif/ppp_oe.h" + +#include + +#if !MEMP_MEM_MALLOC /* don't build if not configured for use in lwipopts.h */ + +struct memp { + struct memp *next; +#if MEMP_OVERFLOW_CHECK + const char *file; + int line; +#endif /* MEMP_OVERFLOW_CHECK */ +}; + +#if MEMP_OVERFLOW_CHECK +/* if MEMP_OVERFLOW_CHECK is turned on, we reserve some bytes at the beginning + * and at the end of each element, initialize them as 0xcd and check + * them later. */ +/* If MEMP_OVERFLOW_CHECK is >= 2, on every call to memp_malloc or memp_free, + * every single element in each pool is checked! + * This is VERY SLOW but also very helpful. */ +/* MEMP_SANITY_REGION_BEFORE and MEMP_SANITY_REGION_AFTER can be overridden in + * lwipopts.h to change the amount reserved for checking. */ +#ifndef MEMP_SANITY_REGION_BEFORE +#define MEMP_SANITY_REGION_BEFORE 16 +#endif /* MEMP_SANITY_REGION_BEFORE*/ +#if MEMP_SANITY_REGION_BEFORE > 0 +#define MEMP_SANITY_REGION_BEFORE_ALIGNED LWIP_MEM_ALIGN_SIZE(MEMP_SANITY_REGION_BEFORE) +#else +#define MEMP_SANITY_REGION_BEFORE_ALIGNED 0 +#endif /* MEMP_SANITY_REGION_BEFORE*/ +#ifndef MEMP_SANITY_REGION_AFTER +#define MEMP_SANITY_REGION_AFTER 16 +#endif /* MEMP_SANITY_REGION_AFTER*/ +#if MEMP_SANITY_REGION_AFTER > 0 +#define MEMP_SANITY_REGION_AFTER_ALIGNED LWIP_MEM_ALIGN_SIZE(MEMP_SANITY_REGION_AFTER) +#else +#define MEMP_SANITY_REGION_AFTER_ALIGNED 0 +#endif /* MEMP_SANITY_REGION_AFTER*/ + +/* MEMP_SIZE: save space for struct memp and for sanity check */ +#define MEMP_SIZE (LWIP_MEM_ALIGN_SIZE(sizeof(struct memp)) + MEMP_SANITY_REGION_BEFORE_ALIGNED) +#define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x) + MEMP_SANITY_REGION_AFTER_ALIGNED) + +#else /* MEMP_OVERFLOW_CHECK */ + +/* No sanity checks + * We don't need to preserve the struct memp while not allocated, so we + * can save a little space and set MEMP_SIZE to 0. + */ +#define MEMP_SIZE 0 +#define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x)) + +#endif /* MEMP_OVERFLOW_CHECK */ + +/** This array holds the first free element of each pool. + * Elements form a linked list. */ +static struct memp *memp_tab[MEMP_MAX]; + +#else /* MEMP_MEM_MALLOC */ + +#define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x)) + +#endif /* MEMP_MEM_MALLOC */ + +/** This array holds the element sizes of each pool. */ +#if !MEM_USE_POOLS && !MEMP_MEM_MALLOC +static +#endif +const u16_t memp_sizes[MEMP_MAX] = { +#define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEM_ALIGN_SIZE(size), +#include "lwip/memp_std.h" +}; + +#if !MEMP_MEM_MALLOC /* don't build if not configured for use in lwipopts.h */ + +/** This array holds the number of elements in each pool. */ +static const u16_t memp_num[MEMP_MAX] = { +#define LWIP_MEMPOOL(name,num,size,desc) (num), +#include "lwip/memp_std.h" +}; + +/** This array holds a textual description of each pool. */ +#ifdef LWIP_DEBUG +static const char *memp_desc[MEMP_MAX] = { +#define LWIP_MEMPOOL(name,num,size,desc) (desc), +#include "lwip/memp_std.h" +}; +#endif /* LWIP_DEBUG */ + +#if MEMP_SEPARATE_POOLS + +/** This creates each memory pool. These are named memp_memory_XXX_base (where + * XXX is the name of the pool defined in memp_std.h). + * To relocate a pool, declare it as extern in cc.h. Example for GCC: + * extern u8_t __attribute__((section(".onchip_mem"))) memp_memory_UDP_PCB_base[]; + */ +#define LWIP_MEMPOOL(name,num,size,desc) u8_t memp_memory_ ## name ## _base \ + [((num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size)))]; +#include "lwip/memp_std.h" + +/** This array holds the base of each memory pool. */ +static u8_t *const memp_bases[] = { +#define LWIP_MEMPOOL(name,num,size,desc) memp_memory_ ## name ## _base, +#include "lwip/memp_std.h" +}; + +#else /* MEMP_SEPARATE_POOLS */ + +/** This is the actual memory used by the pools (all pools in one big block). */ +static u8_t memp_memory[MEM_ALIGNMENT - 1 +#define LWIP_MEMPOOL(name,num,size,desc) + ( (num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size) ) ) +#include "lwip/memp_std.h" +]; + +#endif /* MEMP_SEPARATE_POOLS */ + +#if MEMP_SANITY_CHECK +/** + * Check that memp-lists don't form a circle, using "Floyd's cycle-finding algorithm". + */ +static int +memp_sanity(void) +{ + s16_t i; + struct memp *t, *h; + + for (i = 0; i < MEMP_MAX; i++) { + t = memp_tab[i]; + if(t != NULL) { + for (h = t->next; (t != NULL) && (h != NULL); t = t->next, + h = (((h->next != NULL) && (h->next->next != NULL)) ? h->next->next : NULL)) { + if (t == h) { + return 0; + } + } + } + } + return 1; +} +#endif /* MEMP_SANITY_CHECK*/ +#if MEMP_OVERFLOW_CHECK +#if defined(LWIP_DEBUG) && MEMP_STATS +static const char * memp_overflow_names[] = { +#define LWIP_MEMPOOL(name,num,size,desc) "/"desc, +#include "lwip/memp_std.h" + }; +#endif + +/** + * Check if a memp element was victim of an overflow + * (e.g. the restricted area after it has been altered) + * + * @param p the memp element to check + * @param memp_type the pool p comes from + */ +static void +memp_overflow_check_element_overflow(struct memp *p, u16_t memp_type) +{ + u16_t k; + u8_t *m; +#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0 + m = (u8_t*)p + MEMP_SIZE + memp_sizes[memp_type]; + for (k = 0; k < MEMP_SANITY_REGION_AFTER_ALIGNED; k++) { + if (m[k] != 0xcd) { + char errstr[128] = "detected memp overflow in pool "; + char digit[] = "0"; + if(memp_type >= 10) { + digit[0] = '0' + (memp_type/10); + strcat(errstr, digit); + } + digit[0] = '0' + (memp_type%10); + strcat(errstr, digit); +#if defined(LWIP_DEBUG) && MEMP_STATS + strcat(errstr, memp_overflow_names[memp_type]); +#endif + LWIP_ASSERT(errstr, 0); + } + } +#endif +} + +/** + * Check if a memp element was victim of an underflow + * (e.g. the restricted area before it has been altered) + * + * @param p the memp element to check + * @param memp_type the pool p comes from + */ +static void +memp_overflow_check_element_underflow(struct memp *p, u16_t memp_type) +{ + u16_t k; + u8_t *m; +#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 + m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED; + for (k = 0; k < MEMP_SANITY_REGION_BEFORE_ALIGNED; k++) { + if (m[k] != 0xcd) { + char errstr[128] = "detected memp underflow in pool "; + char digit[] = "0"; + if(memp_type >= 10) { + digit[0] = '0' + (memp_type/10); + strcat(errstr, digit); + } + digit[0] = '0' + (memp_type%10); + strcat(errstr, digit); +#if defined(LWIP_DEBUG) && MEMP_STATS + strcat(errstr, memp_overflow_names[memp_type]); +#endif + LWIP_ASSERT(errstr, 0); + } + } +#endif +} + +/** + * Do an overflow check for all elements in every pool. + * + * @see memp_overflow_check_element for a description of the check + */ +static void +memp_overflow_check_all(void) +{ + u16_t i, j; + struct memp *p; + + p = (struct memp *)LWIP_MEM_ALIGN(memp_memory); + for (i = 0; i < MEMP_MAX; ++i) { + p = p; + for (j = 0; j < memp_num[i]; ++j) { + memp_overflow_check_element_overflow(p, i); + p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i] + MEMP_SANITY_REGION_AFTER_ALIGNED); + } + } + p = (struct memp *)LWIP_MEM_ALIGN(memp_memory); + for (i = 0; i < MEMP_MAX; ++i) { + p = p; + for (j = 0; j < memp_num[i]; ++j) { + memp_overflow_check_element_underflow(p, i); + p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i] + MEMP_SANITY_REGION_AFTER_ALIGNED); + } + } +} + +/** + * Initialize the restricted areas of all memp elements in every pool. + */ +static void +memp_overflow_init(void) +{ + u16_t i, j; + struct memp *p; + u8_t *m; + + p = (struct memp *)LWIP_MEM_ALIGN(memp_memory); + for (i = 0; i < MEMP_MAX; ++i) { + p = p; + for (j = 0; j < memp_num[i]; ++j) { +#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 + m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED; + memset(m, 0xcd, MEMP_SANITY_REGION_BEFORE_ALIGNED); +#endif +#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0 + m = (u8_t*)p + MEMP_SIZE + memp_sizes[i]; + memset(m, 0xcd, MEMP_SANITY_REGION_AFTER_ALIGNED); +#endif + p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i] + MEMP_SANITY_REGION_AFTER_ALIGNED); + } + } +} +#endif /* MEMP_OVERFLOW_CHECK */ + +/** + * Initialize this module. + * + * Carves out memp_memory into linked lists for each pool-type. + */ +void +memp_init(void) +{ + struct memp *memp; + u16_t i, j; + + for (i = 0; i < MEMP_MAX; ++i) { + MEMP_STATS_AVAIL(used, i, 0); + MEMP_STATS_AVAIL(max, i, 0); + MEMP_STATS_AVAIL(err, i, 0); + MEMP_STATS_AVAIL(avail, i, memp_num[i]); + } + +#if !MEMP_SEPARATE_POOLS + memp = (struct memp *)LWIP_MEM_ALIGN(memp_memory); +#endif /* !MEMP_SEPARATE_POOLS */ + /* for every pool: */ + for (i = 0; i < MEMP_MAX; ++i) { + memp_tab[i] = NULL; +#if MEMP_SEPARATE_POOLS + memp = (struct memp*)memp_bases[i]; +#endif /* MEMP_SEPARATE_POOLS */ + /* create a linked list of memp elements */ + for (j = 0; j < memp_num[i]; ++j) { + memp->next = memp_tab[i]; + memp_tab[i] = memp; + memp = (struct memp *)(void *)((u8_t *)memp + MEMP_SIZE + memp_sizes[i] +#if MEMP_OVERFLOW_CHECK + + MEMP_SANITY_REGION_AFTER_ALIGNED +#endif + ); + } + } +#if MEMP_OVERFLOW_CHECK + memp_overflow_init(); + /* check everything a first time to see if it worked */ + memp_overflow_check_all(); +#endif /* MEMP_OVERFLOW_CHECK */ +} + +/** + * Get an element from a specific pool. + * + * @param type the pool to get an element from + * + * the debug version has two more parameters: + * @param file file name calling this function + * @param line number of line where this function is called + * + * @return a pointer to the allocated memory or a NULL pointer on error + */ +void * +#if !MEMP_OVERFLOW_CHECK +memp_malloc(memp_t type) +#else +memp_malloc_fn(memp_t type, const char* file, const int line) +#endif +{ + struct memp *memp; + SYS_ARCH_DECL_PROTECT(old_level); + + LWIP_ERROR("memp_malloc: type < MEMP_MAX", (type < MEMP_MAX), return NULL;); + + SYS_ARCH_PROTECT(old_level); +#if MEMP_OVERFLOW_CHECK >= 2 + memp_overflow_check_all(); +#endif /* MEMP_OVERFLOW_CHECK >= 2 */ + + memp = memp_tab[type]; + + if (memp != NULL) { + memp_tab[type] = memp->next; +#if MEMP_OVERFLOW_CHECK + memp->next = NULL; + memp->file = file; + memp->line = line; +#endif /* MEMP_OVERFLOW_CHECK */ + MEMP_STATS_INC_USED(used, type); + LWIP_ASSERT("memp_malloc: memp properly aligned", + ((mem_ptr_t)memp % MEM_ALIGNMENT) == 0); + memp = (struct memp*)(void *)((u8_t*)memp + MEMP_SIZE); + } else { + LWIP_DEBUGF(MEMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("memp_malloc: out of memory in pool %s\n", memp_desc[type])); + MEMP_STATS_INC(err, type); + } + + SYS_ARCH_UNPROTECT(old_level); + + return memp; +} + +/** + * Put an element back into its pool. + * + * @param type the pool where to put mem + * @param mem the memp element to free + */ +void +memp_free(memp_t type, void *mem) +{ + struct memp *memp; + SYS_ARCH_DECL_PROTECT(old_level); + + if (mem == NULL) { + return; + } + LWIP_ASSERT("memp_free: mem properly aligned", + ((mem_ptr_t)mem % MEM_ALIGNMENT) == 0); + + memp = (struct memp *)(void *)((u8_t*)mem - MEMP_SIZE); + + SYS_ARCH_PROTECT(old_level); +#if MEMP_OVERFLOW_CHECK +#if MEMP_OVERFLOW_CHECK >= 2 + memp_overflow_check_all(); +#else + memp_overflow_check_element_overflow(memp, type); + memp_overflow_check_element_underflow(memp, type); +#endif /* MEMP_OVERFLOW_CHECK >= 2 */ +#endif /* MEMP_OVERFLOW_CHECK */ + + MEMP_STATS_DEC(used, type); + + memp->next = memp_tab[type]; + memp_tab[type] = memp; + +#if MEMP_SANITY_CHECK + LWIP_ASSERT("memp sanity", memp_sanity()); +#endif /* MEMP_SANITY_CHECK */ + + SYS_ARCH_UNPROTECT(old_level); +} + +#endif /* MEMP_MEM_MALLOC */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/core/netif.c b/component/common/network/lwip/lwip_v1.4.1/src/core/netif.c new file mode 100644 index 0000000..4a02e77 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/core/netif.c @@ -0,0 +1,774 @@ +/** + * @file + * lwIP network interface abstraction + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/def.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/tcp_impl.h" +#include "lwip/snmp.h" +#include "lwip/igmp.h" +#include "netif/etharp.h" +#include "lwip/stats.h" +#if ENABLE_LOOPBACK +#include "lwip/sys.h" +#if LWIP_NETIF_LOOPBACK_MULTITHREADING +#include "lwip/tcpip.h" +#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ +#endif /* ENABLE_LOOPBACK */ + +#if LWIP_AUTOIP +#include "lwip/autoip.h" +#endif /* LWIP_AUTOIP */ +#if LWIP_DHCP +#include "lwip/dhcp.h" +#endif /* LWIP_DHCP */ + +#if LWIP_NETIF_STATUS_CALLBACK +#define NETIF_STATUS_CALLBACK(n) do{ if (n->status_callback) { (n->status_callback)(n); }}while(0) +#else +#define NETIF_STATUS_CALLBACK(n) +#endif /* LWIP_NETIF_STATUS_CALLBACK */ + +#if LWIP_NETIF_LINK_CALLBACK +#define NETIF_LINK_CALLBACK(n) do{ if (n->link_callback) { (n->link_callback)(n); }}while(0) +#else +#define NETIF_LINK_CALLBACK(n) +#endif /* LWIP_NETIF_LINK_CALLBACK */ + +struct netif *netif_list; +struct netif *netif_default; + +static u8_t netif_num; + +#if LWIP_HAVE_LOOPIF +static struct netif loop_netif; + +/** + * Initialize a lwip network interface structure for a loopback interface + * + * @param netif the lwip network interface structure for this loopif + * @return ERR_OK if the loopif is initialized + * ERR_MEM if private data couldn't be allocated + */ +static err_t +netif_loopif_init(struct netif *netif) +{ + /* initialize the snmp variables and counters inside the struct netif + * ifSpeed: no assumption can be made! + */ + NETIF_INIT_SNMP(netif, snmp_ifType_softwareLoopback, 0); + + netif->name[0] = 'l'; + netif->name[1] = 'o'; + netif->output = netif_loop_output; + return ERR_OK; +} +#endif /* LWIP_HAVE_LOOPIF */ + +void +netif_init(void) +{ +#if LWIP_HAVE_LOOPIF + ip_addr_t loop_ipaddr, loop_netmask, loop_gw; + IP4_ADDR(&loop_gw, 127,0,0,1); + IP4_ADDR(&loop_ipaddr, 127,0,0,1); + IP4_ADDR(&loop_netmask, 255,0,0,0); + +#if NO_SYS + netif_add(&loop_netif, &loop_ipaddr, &loop_netmask, &loop_gw, NULL, netif_loopif_init, ip_input); +#else /* NO_SYS */ + netif_add(&loop_netif, &loop_ipaddr, &loop_netmask, &loop_gw, NULL, netif_loopif_init, tcpip_input); +#endif /* NO_SYS */ + netif_set_up(&loop_netif); + +#endif /* LWIP_HAVE_LOOPIF */ +} + +/** + * Add a network interface to the list of lwIP netifs. + * + * @param netif a pre-allocated netif structure + * @param ipaddr IP address for the new netif + * @param netmask network mask for the new netif + * @param gw default gateway IP address for the new netif + * @param state opaque data passed to the new netif + * @param init callback function that initializes the interface + * @param input callback function that is called to pass + * ingress packets up in the protocol layer stack. + * + * @return netif, or NULL if failed. + */ +struct netif * +netif_add(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask, + ip_addr_t *gw, void *state, netif_init_fn init, netif_input_fn input) +{ + + LWIP_ASSERT("No init function given", init != NULL); + + /* reset new interface configuration state */ + ip_addr_set_zero(&netif->ip_addr); + ip_addr_set_zero(&netif->netmask); + ip_addr_set_zero(&netif->gw); + netif->flags = 0; +#if LWIP_DHCP + /* netif not under DHCP control by default */ + netif->dhcp = NULL; +#endif /* LWIP_DHCP */ +#if LWIP_AUTOIP + /* netif not under AutoIP control by default */ + netif->autoip = NULL; +#endif /* LWIP_AUTOIP */ +#if LWIP_NETIF_STATUS_CALLBACK + netif->status_callback = NULL; +#endif /* LWIP_NETIF_STATUS_CALLBACK */ +#if LWIP_NETIF_LINK_CALLBACK + netif->link_callback = NULL; +#endif /* LWIP_NETIF_LINK_CALLBACK */ +#if LWIP_IGMP + netif->igmp_mac_filter = NULL; +#endif /* LWIP_IGMP */ +#if ENABLE_LOOPBACK + netif->loop_first = NULL; + netif->loop_last = NULL; +#endif /* ENABLE_LOOPBACK */ + + /* remember netif specific state information data */ + netif->state = state; + netif->num = netif_num++; + netif->input = input; + NETIF_SET_HWADDRHINT(netif, NULL); +#if ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS + netif->loop_cnt_current = 0; +#endif /* ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS */ + + netif_set_addr(netif, ipaddr, netmask, gw); + + /* call user specified initialization function for netif */ + if (init(netif) != ERR_OK) { + return NULL; + } + + /* add this netif to the list */ + netif->next = netif_list; + netif_list = netif; + snmp_inc_iflist(); + +#if LWIP_IGMP + /* start IGMP processing */ + if (netif->flags & NETIF_FLAG_IGMP) { + igmp_start(netif); + } +#endif /* LWIP_IGMP */ + + LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP addr ", + netif->name[0], netif->name[1])); + ip_addr_debug_print(NETIF_DEBUG, ipaddr); + LWIP_DEBUGF(NETIF_DEBUG, (" netmask ")); + ip_addr_debug_print(NETIF_DEBUG, netmask); + LWIP_DEBUGF(NETIF_DEBUG, (" gw ")); + ip_addr_debug_print(NETIF_DEBUG, gw); + LWIP_DEBUGF(NETIF_DEBUG, ("\n")); + return netif; +} + +/** + * Change IP address configuration for a network interface (including netmask + * and default gateway). + * + * @param netif the network interface to change + * @param ipaddr the new IP address + * @param netmask the new netmask + * @param gw the new default gateway + */ +void +netif_set_addr(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask, + ip_addr_t *gw) +{ + netif_set_ipaddr(netif, ipaddr); + netif_set_netmask(netif, netmask); + netif_set_gw(netif, gw); +} + +/** + * Remove a network interface from the list of lwIP netifs. + * + * @param netif the network interface to remove + */ +void +netif_remove(struct netif *netif) +{ + if (netif == NULL) { + return; + } + +#if LWIP_IGMP + /* stop IGMP processing */ + if (netif->flags & NETIF_FLAG_IGMP) { + igmp_stop(netif); + } +#endif /* LWIP_IGMP */ + if (netif_is_up(netif)) { + /* set netif down before removing (call callback function) */ + netif_set_down(netif); + } + + snmp_delete_ipaddridx_tree(netif); + + /* is it the first netif? */ + if (netif_list == netif) { + netif_list = netif->next; + } else { + /* look for netif further down the list */ + struct netif * tmpNetif; + for (tmpNetif = netif_list; tmpNetif != NULL; tmpNetif = tmpNetif->next) { + if (tmpNetif->next == netif) { + tmpNetif->next = netif->next; + break; + } + } + if (tmpNetif == NULL) + return; /* we didn't find any netif today */ + } + snmp_dec_iflist(); + /* this netif is default? */ + if (netif_default == netif) { + /* reset default netif */ + netif_set_default(NULL); + } +#if LWIP_NETIF_REMOVE_CALLBACK + if (netif->remove_callback) { + netif->remove_callback(netif); + } +#endif /* LWIP_NETIF_REMOVE_CALLBACK */ + LWIP_DEBUGF( NETIF_DEBUG, ("netif_remove: removed netif\n") ); +} + +/** + * Find a network interface by searching for its name + * + * @param name the name of the netif (like netif->name) plus concatenated number + * in ascii representation (e.g. 'en0') + */ +struct netif * +netif_find(char *name) +{ + struct netif *netif; + u8_t num; + + if (name == NULL) { + return NULL; + } + + num = name[2] - '0'; + + for(netif = netif_list; netif != NULL; netif = netif->next) { + if (num == netif->num && + name[0] == netif->name[0] && + name[1] == netif->name[1]) { + LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %c%c\n", name[0], name[1])); + return netif; + } + } + LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1])); + return NULL; +} + +/** + * Change the IP address of a network interface + * + * @param netif the network interface to change + * @param ipaddr the new IP address + * + * @note call netif_set_addr() if you also want to change netmask and + * default gateway + */ +void +netif_set_ipaddr(struct netif *netif, ip_addr_t *ipaddr) +{ + /* TODO: Handling of obsolete pcbs */ + /* See: http://mail.gnu.org/archive/html/lwip-users/2003-03/msg00118.html */ +#if LWIP_TCP + struct tcp_pcb *pcb; + struct tcp_pcb_listen *lpcb; + + /* address is actually being changed? */ + if (ipaddr && (ip_addr_cmp(ipaddr, &(netif->ip_addr))) == 0) { + /* extern struct tcp_pcb *tcp_active_pcbs; defined by tcp.h */ + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: netif address being changed\n")); + pcb = tcp_active_pcbs; + while (pcb != NULL) { + /* PCB bound to current local interface address? */ + if (ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr)) +#if LWIP_AUTOIP + /* connections to link-local addresses must persist (RFC3927 ch. 1.9) */ + && !ip_addr_islinklocal(&(pcb->local_ip)) +#endif /* LWIP_AUTOIP */ + ) { + /* this connection must be aborted */ + struct tcp_pcb *next = pcb->next; + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: aborting TCP pcb %p\n", (void *)pcb)); + tcp_abort(pcb); + pcb = next; + } else { + pcb = pcb->next; + } + } + for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { + /* PCB bound to current local interface address? */ + if ((!(ip_addr_isany(&(lpcb->local_ip)))) && + (ip_addr_cmp(&(lpcb->local_ip), &(netif->ip_addr)))) { + /* The PCB is listening to the old ipaddr and + * is set to listen to the new one instead */ + ip_addr_set(&(lpcb->local_ip), ipaddr); + } + } + } +#endif + snmp_delete_ipaddridx_tree(netif); + snmp_delete_iprteidx_tree(0,netif); + /* set new IP address to netif */ + ip_addr_set(&(netif->ip_addr), ipaddr); + snmp_insert_ipaddridx_tree(netif); + snmp_insert_iprteidx_tree(0,netif); + + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: IP address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + netif->name[0], netif->name[1], + ip4_addr1_16(&netif->ip_addr), + ip4_addr2_16(&netif->ip_addr), + ip4_addr3_16(&netif->ip_addr), + ip4_addr4_16(&netif->ip_addr))); +} + +/** + * Change the default gateway for a network interface + * + * @param netif the network interface to change + * @param gw the new default gateway + * + * @note call netif_set_addr() if you also want to change ip address and netmask + */ +void +netif_set_gw(struct netif *netif, ip_addr_t *gw) +{ + ip_addr_set(&(netif->gw), gw); + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: GW address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + netif->name[0], netif->name[1], + ip4_addr1_16(&netif->gw), + ip4_addr2_16(&netif->gw), + ip4_addr3_16(&netif->gw), + ip4_addr4_16(&netif->gw))); +} + +/** + * Change the netmask of a network interface + * + * @param netif the network interface to change + * @param netmask the new netmask + * + * @note call netif_set_addr() if you also want to change ip address and + * default gateway + */ +void +netif_set_netmask(struct netif *netif, ip_addr_t *netmask) +{ + snmp_delete_iprteidx_tree(0, netif); + /* set new netmask to netif */ + ip_addr_set(&(netif->netmask), netmask); + snmp_insert_iprteidx_tree(0, netif); + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: netmask of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + netif->name[0], netif->name[1], + ip4_addr1_16(&netif->netmask), + ip4_addr2_16(&netif->netmask), + ip4_addr3_16(&netif->netmask), + ip4_addr4_16(&netif->netmask))); +} + +/** + * Set a network interface as the default network interface + * (used to output all packets for which no specific route is found) + * + * @param netif the default network interface + */ +void +netif_set_default(struct netif *netif) +{ + if (netif == NULL) { + /* remove default route */ + snmp_delete_iprteidx_tree(1, netif); + } else { + /* install default route */ + snmp_insert_iprteidx_tree(1, netif); + } + netif_default = netif; + LWIP_DEBUGF(NETIF_DEBUG, ("netif: setting default interface %c%c\n", + netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\'')); +} + +/** + * Bring an interface up, available for processing + * traffic. + * + * @note: Enabling DHCP on a down interface will make it come + * up once configured. + * + * @see dhcp_start() + */ +void netif_set_up(struct netif *netif) +{ + if (!(netif->flags & NETIF_FLAG_UP)) { + netif->flags |= NETIF_FLAG_UP; + +#if LWIP_SNMP + snmp_get_sysuptime(&netif->ts); +#endif /* LWIP_SNMP */ + + NETIF_STATUS_CALLBACK(netif); + + if (netif->flags & NETIF_FLAG_LINK_UP) { +#if LWIP_ARP + /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */ + if (netif->flags & (NETIF_FLAG_ETHARP)) { + etharp_gratuitous(netif); + } +#endif /* LWIP_ARP */ + +#if LWIP_IGMP + /* resend IGMP memberships */ + if (netif->flags & NETIF_FLAG_IGMP) { + igmp_report_groups( netif); + } +#endif /* LWIP_IGMP */ + } + } +} + +/** + * Bring an interface down, disabling any traffic processing. + * + * @note: Enabling DHCP on a down interface will make it come + * up once configured. + * + * @see dhcp_start() + */ +void netif_set_down(struct netif *netif) +{ + if (netif->flags & NETIF_FLAG_UP) { + netif->flags &= ~NETIF_FLAG_UP; +#if LWIP_SNMP + snmp_get_sysuptime(&netif->ts); +#endif + +#if LWIP_ARP + if (netif->flags & NETIF_FLAG_ETHARP) { + etharp_cleanup_netif(netif); + } +#endif /* LWIP_ARP */ + NETIF_STATUS_CALLBACK(netif); + } +} + +#if LWIP_NETIF_STATUS_CALLBACK +/** + * Set callback to be called when interface is brought up/down + */ +void netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback) +{ + if (netif) { + netif->status_callback = status_callback; + } +} +#endif /* LWIP_NETIF_STATUS_CALLBACK */ + +#if LWIP_NETIF_REMOVE_CALLBACK +/** + * Set callback to be called when the interface has been removed + */ +void +netif_set_remove_callback(struct netif *netif, netif_status_callback_fn remove_callback) +{ + if (netif) { + netif->remove_callback = remove_callback; + } +} +#endif /* LWIP_NETIF_REMOVE_CALLBACK */ + +/** + * Called by a driver when its link goes up + */ +void netif_set_link_up(struct netif *netif ) +{ + if (!(netif->flags & NETIF_FLAG_LINK_UP)) { + netif->flags |= NETIF_FLAG_LINK_UP; + +#if LWIP_DHCP + if (netif->dhcp) { + dhcp_network_changed(netif); + } +#endif /* LWIP_DHCP */ + +#if LWIP_AUTOIP + if (netif->autoip) { + autoip_network_changed(netif); + } +#endif /* LWIP_AUTOIP */ + + if (netif->flags & NETIF_FLAG_UP) { +#if LWIP_ARP + /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */ + if (netif->flags & NETIF_FLAG_ETHARP) { + etharp_gratuitous(netif); + } +#endif /* LWIP_ARP */ + +#if LWIP_IGMP + /* resend IGMP memberships */ + if (netif->flags & NETIF_FLAG_IGMP) { + igmp_report_groups( netif); + } +#endif /* LWIP_IGMP */ + } + NETIF_LINK_CALLBACK(netif); + } +} + +/** + * Called by a driver when its link goes down + */ +void netif_set_link_down(struct netif *netif ) +{ + if (netif->flags & NETIF_FLAG_LINK_UP) { + netif->flags &= ~NETIF_FLAG_LINK_UP; + NETIF_LINK_CALLBACK(netif); + } +} + +#if LWIP_NETIF_LINK_CALLBACK +/** + * Set callback to be called when link is brought up/down + */ +void netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback) +{ + if (netif) { + netif->link_callback = link_callback; + } +} +#endif /* LWIP_NETIF_LINK_CALLBACK */ + +#if ENABLE_LOOPBACK +/** + * Send an IP packet to be received on the same netif (loopif-like). + * The pbuf is simply copied and handed back to netif->input. + * In multithreaded mode, this is done directly since netif->input must put + * the packet on a queue. + * In callback mode, the packet is put on an internal queue and is fed to + * netif->input by netif_poll(). + * + * @param netif the lwip network interface structure + * @param p the (IP) packet to 'send' + * @param ipaddr the ip address to send the packet to (not used) + * @return ERR_OK if the packet has been sent + * ERR_MEM if the pbuf used to copy the packet couldn't be allocated + */ +err_t +netif_loop_output(struct netif *netif, struct pbuf *p, + ip_addr_t *ipaddr) +{ + struct pbuf *r; + err_t err; + struct pbuf *last; +#if LWIP_LOOPBACK_MAX_PBUFS + u8_t clen = 0; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ + /* If we have a loopif, SNMP counters are adjusted for it, + * if not they are adjusted for 'netif'. */ +#if LWIP_SNMP +#if LWIP_HAVE_LOOPIF + struct netif *stats_if = &loop_netif; +#else /* LWIP_HAVE_LOOPIF */ + struct netif *stats_if = netif; +#endif /* LWIP_HAVE_LOOPIF */ +#endif /* LWIP_SNMP */ + SYS_ARCH_DECL_PROTECT(lev); + LWIP_UNUSED_ARG(ipaddr); + + /* Allocate a new pbuf */ + r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM); + if (r == NULL) { + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + snmp_inc_ifoutdiscards(stats_if); + return ERR_MEM; + } +#if LWIP_LOOPBACK_MAX_PBUFS + clen = pbuf_clen(r); + /* check for overflow or too many pbuf on queue */ + if(((netif->loop_cnt_current + clen) < netif->loop_cnt_current) || + ((netif->loop_cnt_current + clen) > LWIP_LOOPBACK_MAX_PBUFS)) { + pbuf_free(r); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + snmp_inc_ifoutdiscards(stats_if); + return ERR_MEM; + } + netif->loop_cnt_current += clen; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ + + /* Copy the whole pbuf queue p into the single pbuf r */ + if ((err = pbuf_copy(r, p)) != ERR_OK) { + pbuf_free(r); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + snmp_inc_ifoutdiscards(stats_if); + return err; + } + + /* Put the packet on a linked list which gets emptied through calling + netif_poll(). */ + + /* let last point to the last pbuf in chain r */ + for (last = r; last->next != NULL; last = last->next); + + SYS_ARCH_PROTECT(lev); + if(netif->loop_first != NULL) { + LWIP_ASSERT("if first != NULL, last must also be != NULL", netif->loop_last != NULL); + netif->loop_last->next = r; + netif->loop_last = last; + } else { + netif->loop_first = r; + netif->loop_last = last; + } + SYS_ARCH_UNPROTECT(lev); + + LINK_STATS_INC(link.xmit); + snmp_add_ifoutoctets(stats_if, p->tot_len); + snmp_inc_ifoutucastpkts(stats_if); + +#if LWIP_NETIF_LOOPBACK_MULTITHREADING + /* For multithreading environment, schedule a call to netif_poll */ + tcpip_callback((tcpip_callback_fn)netif_poll, netif); +#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ + + return ERR_OK; +} + +/** + * Call netif_poll() in the main loop of your application. This is to prevent + * reentering non-reentrant functions like tcp_input(). Packets passed to + * netif_loop_output() are put on a list that is passed to netif->input() by + * netif_poll(). + */ +void +netif_poll(struct netif *netif) +{ + struct pbuf *in; + /* If we have a loopif, SNMP counters are adjusted for it, + * if not they are adjusted for 'netif'. */ +#if LWIP_SNMP +#if LWIP_HAVE_LOOPIF + struct netif *stats_if = &loop_netif; +#else /* LWIP_HAVE_LOOPIF */ + struct netif *stats_if = netif; +#endif /* LWIP_HAVE_LOOPIF */ +#endif /* LWIP_SNMP */ + SYS_ARCH_DECL_PROTECT(lev); + + do { + /* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */ + SYS_ARCH_PROTECT(lev); + in = netif->loop_first; + if (in != NULL) { + struct pbuf *in_end = in; +#if LWIP_LOOPBACK_MAX_PBUFS + u8_t clen = pbuf_clen(in); + /* adjust the number of pbufs on queue */ + LWIP_ASSERT("netif->loop_cnt_current underflow", + ((netif->loop_cnt_current - clen) < netif->loop_cnt_current)); + netif->loop_cnt_current -= clen; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ + while (in_end->len != in_end->tot_len) { + LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL); + in_end = in_end->next; + } + /* 'in_end' now points to the last pbuf from 'in' */ + if (in_end == netif->loop_last) { + /* this was the last pbuf in the list */ + netif->loop_first = netif->loop_last = NULL; + } else { + /* pop the pbuf off the list */ + netif->loop_first = in_end->next; + LWIP_ASSERT("should not be null since first != last!", netif->loop_first != NULL); + } + /* De-queue the pbuf from its successors on the 'loop_' list. */ + in_end->next = NULL; + } + SYS_ARCH_UNPROTECT(lev); + + if (in != NULL) { + LINK_STATS_INC(link.recv); + snmp_add_ifinoctets(stats_if, in->tot_len); + snmp_inc_ifinucastpkts(stats_if); + /* loopback packets are always IP packets! */ + if (ip_input(in, netif) != ERR_OK) { + pbuf_free(in); + } + /* Don't reference the packet any more! */ + in = NULL; + } + /* go on while there is a packet on the list */ + } while (netif->loop_first != NULL); +} + +#if !LWIP_NETIF_LOOPBACK_MULTITHREADING +/** + * Calls netif_poll() for every netif on the netif_list. + */ +void +netif_poll_all(void) +{ + struct netif *netif = netif_list; + /* loop through netifs */ + while (netif != NULL) { + netif_poll(netif); + /* proceed to next network interface */ + netif = netif->next; + } +} +#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */ +#endif /* ENABLE_LOOPBACK */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/core/pbuf.c b/component/common/network/lwip/lwip_v1.4.1/src/core/pbuf.c new file mode 100644 index 0000000..1e5e53b --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/core/pbuf.c @@ -0,0 +1,1179 @@ +/** + * @file + * Packet buffer management + * + * Packets are built from the pbuf data structure. It supports dynamic + * memory allocation for packet contents or can reference externally + * managed packet contents both in RAM and ROM. Quick allocation for + * incoming packets is provided through pools with fixed sized pbufs. + * + * A packet may span over multiple pbufs, chained as a singly linked + * list. This is called a "pbuf chain". + * + * Multiple packets may be queued, also using this singly linked list. + * This is called a "packet queue". + * + * So, a packet queue consists of one or more pbuf chains, each of + * which consist of one or more pbufs. CURRENTLY, PACKET QUEUES ARE + * NOT SUPPORTED!!! Use helper structs to queue multiple packets. + * + * The differences between a pbuf chain and a packet queue are very + * precise but subtle. + * + * The last pbuf of a packet has a ->tot_len field that equals the + * ->len field. It can be found by traversing the list. If the last + * pbuf of a packet has a ->next field other than NULL, more packets + * are on the queue. + * + * Therefore, looping through a pbuf of a single packet, has an + * loop end condition (tot_len == p->len), NOT (next == NULL). + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/stats.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/pbuf.h" +#include "lwip/sys.h" +#include "arch/perf.h" +#if LWIP_TCP && TCP_QUEUE_OOSEQ +#include "lwip/tcp_impl.h" +#endif +#if LWIP_CHECKSUM_ON_COPY +#include "lwip/inet_chksum.h" +#endif + +#include + +#define SIZEOF_STRUCT_PBUF LWIP_MEM_ALIGN_SIZE(sizeof(struct pbuf)) +/* Since the pool is created in memp, PBUF_POOL_BUFSIZE will be automatically + aligned there. Therefore, PBUF_POOL_BUFSIZE_ALIGNED can be used here. */ +#define PBUF_POOL_BUFSIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE) + +#if !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ +#define PBUF_POOL_IS_EMPTY() +#else /* !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ */ + +#if !NO_SYS +#ifndef PBUF_POOL_FREE_OOSEQ_QUEUE_CALL +#include "lwip/tcpip.h" +#define PBUF_POOL_FREE_OOSEQ_QUEUE_CALL() do { \ + if(tcpip_callback_with_block(pbuf_free_ooseq_callback, NULL, 0) != ERR_OK) { \ + SYS_ARCH_PROTECT(old_level); \ + pbuf_free_ooseq_pending = 0; \ + SYS_ARCH_UNPROTECT(old_level); \ + } } while(0) +#endif /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */ +#endif /* !NO_SYS */ + +volatile u8_t pbuf_free_ooseq_pending; +#define PBUF_POOL_IS_EMPTY() pbuf_pool_is_empty() + +/** + * Attempt to reclaim some memory from queued out-of-sequence TCP segments + * if we run out of pool pbufs. It's better to give priority to new packets + * if we're running out. + * + * This must be done in the correct thread context therefore this function + * can only be used with NO_SYS=0 and through tcpip_callback. + */ +#if !NO_SYS +static +#endif /* !NO_SYS */ +void +pbuf_free_ooseq(void) +{ + struct tcp_pcb* pcb; + SYS_ARCH_DECL_PROTECT(old_level); + + SYS_ARCH_PROTECT(old_level); + pbuf_free_ooseq_pending = 0; + SYS_ARCH_UNPROTECT(old_level); + + for (pcb = tcp_active_pcbs; NULL != pcb; pcb = pcb->next) { + if (NULL != pcb->ooseq) { + /** Free the ooseq pbufs of one PCB only */ + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free_ooseq: freeing out-of-sequence pbufs\n")); + tcp_segs_free(pcb->ooseq); + pcb->ooseq = NULL; + return; + } + } +} + +#if !NO_SYS +/** + * Just a callback function for tcpip_timeout() that calls pbuf_free_ooseq(). + */ +static void +pbuf_free_ooseq_callback(void *arg) +{ + LWIP_UNUSED_ARG(arg); + pbuf_free_ooseq(); +} +#endif /* !NO_SYS */ + +/** Queue a call to pbuf_free_ooseq if not already queued. */ +static void +pbuf_pool_is_empty(void) +{ +#ifndef PBUF_POOL_FREE_OOSEQ_QUEUE_CALL + SYS_ARCH_DECL_PROTECT(old_level); + SYS_ARCH_PROTECT(old_level); + pbuf_free_ooseq_pending = 1; + SYS_ARCH_UNPROTECT(old_level); +#else /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */ + u8_t queued; + SYS_ARCH_DECL_PROTECT(old_level); + SYS_ARCH_PROTECT(old_level); + queued = pbuf_free_ooseq_pending; + pbuf_free_ooseq_pending = 1; + SYS_ARCH_UNPROTECT(old_level); + + if(!queued) { + /* queue a call to pbuf_free_ooseq if not already queued */ + PBUF_POOL_FREE_OOSEQ_QUEUE_CALL(); + } +#endif /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */ +} +#endif /* !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ */ + +/** + * Allocates a pbuf of the given type (possibly a chain for PBUF_POOL type). + * + * The actual memory allocated for the pbuf is determined by the + * layer at which the pbuf is allocated and the requested size + * (from the size parameter). + * + * @param layer flag to define header size + * @param length size of the pbuf's payload + * @param type this parameter decides how and where the pbuf + * should be allocated as follows: + * + * - PBUF_RAM: buffer memory for pbuf is allocated as one large + * chunk. This includes protocol headers as well. + * - PBUF_ROM: no buffer memory is allocated for the pbuf, even for + * protocol headers. Additional headers must be prepended + * by allocating another pbuf and chain in to the front of + * the ROM pbuf. It is assumed that the memory used is really + * similar to ROM in that it is immutable and will not be + * changed. Memory which is dynamic should generally not + * be attached to PBUF_ROM pbufs. Use PBUF_REF instead. + * - PBUF_REF: no buffer memory is allocated for the pbuf, even for + * protocol headers. It is assumed that the pbuf is only + * being used in a single thread. If the pbuf gets queued, + * then pbuf_take should be called to copy the buffer. + * - PBUF_POOL: the pbuf is allocated as a pbuf chain, with pbufs from + * the pbuf pool that is allocated during pbuf_init(). + * + * @return the allocated pbuf. If multiple pbufs where allocated, this + * is the first pbuf of a pbuf chain. + */ +struct pbuf * +pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type) +{ + struct pbuf *p, *q, *r; + u16_t offset; + s32_t rem_len; /* remaining length */ + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F")\n", length)); + + /* determine header offset */ + switch (layer) { + case PBUF_TRANSPORT: + /* add room for transport (often TCP) layer header */ + offset = PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN; + break; + case PBUF_IP: + /* add room for IP layer header */ + offset = PBUF_LINK_HLEN + PBUF_IP_HLEN; + break; + case PBUF_LINK: + /* add room for link layer header */ + offset = PBUF_LINK_HLEN; + break; + case PBUF_RAW: + offset = 0; + break; + default: + LWIP_ASSERT("pbuf_alloc: bad pbuf layer", 0); + return NULL; + } + + switch (type) { + case PBUF_POOL: + /* allocate head of pbuf chain into p */ + p = (struct pbuf *)memp_malloc(MEMP_PBUF_POOL); + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc: allocated pbuf %p\n", (void *)p)); + if (p == NULL) { + PBUF_POOL_IS_EMPTY(); + return NULL; + } + p->type = type; + p->next = NULL; + + /* make the payload pointer point 'offset' bytes into pbuf data memory */ + p->payload = LWIP_MEM_ALIGN((void *)((u8_t *)p + (SIZEOF_STRUCT_PBUF + offset))); + LWIP_ASSERT("pbuf_alloc: pbuf p->payload properly aligned", + ((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0); + /* the total length of the pbuf chain is the requested size */ + p->tot_len = length; + /* set the length of the first pbuf in the chain */ + p->len = LWIP_MIN(length, PBUF_POOL_BUFSIZE_ALIGNED - LWIP_MEM_ALIGN_SIZE(offset)); + LWIP_ASSERT("check p->payload + p->len does not overflow pbuf", + ((u8_t*)p->payload + p->len <= + (u8_t*)p + SIZEOF_STRUCT_PBUF + PBUF_POOL_BUFSIZE_ALIGNED)); + LWIP_ASSERT("PBUF_POOL_BUFSIZE must be bigger than MEM_ALIGNMENT", + (PBUF_POOL_BUFSIZE_ALIGNED - LWIP_MEM_ALIGN_SIZE(offset)) > 0 ); + /* set reference count (needed here in case we fail) */ + p->ref = 1; + + /* now allocate the tail of the pbuf chain */ + + /* remember first pbuf for linkage in next iteration */ + r = p; + /* remaining length to be allocated */ + rem_len = length - p->len; + /* any remaining pbufs to be allocated? */ + while (rem_len > 0) { + q = (struct pbuf *)memp_malloc(MEMP_PBUF_POOL); + if (q == NULL) { + PBUF_POOL_IS_EMPTY(); + /* free chain so far allocated */ + pbuf_free(p); + /* bail out unsuccesfully */ + return NULL; + } + q->type = type; + q->flags = 0; + q->next = NULL; + /* make previous pbuf point to this pbuf */ + r->next = q; + /* set total length of this pbuf and next in chain */ + LWIP_ASSERT("rem_len < max_u16_t", rem_len < 0xffff); + q->tot_len = (u16_t)rem_len; + /* this pbuf length is pool size, unless smaller sized tail */ + q->len = LWIP_MIN((u16_t)rem_len, PBUF_POOL_BUFSIZE_ALIGNED); + q->payload = (void *)((u8_t *)q + SIZEOF_STRUCT_PBUF); + LWIP_ASSERT("pbuf_alloc: pbuf q->payload properly aligned", + ((mem_ptr_t)q->payload % MEM_ALIGNMENT) == 0); + LWIP_ASSERT("check p->payload + p->len does not overflow pbuf", + ((u8_t*)p->payload + p->len <= + (u8_t*)p + SIZEOF_STRUCT_PBUF + PBUF_POOL_BUFSIZE_ALIGNED)); + q->ref = 1; + /* calculate remaining length to be allocated */ + rem_len -= q->len; + /* remember this pbuf for linkage in next iteration */ + r = q; + } + /* end of chain */ + /*r->next = NULL;*/ + + break; + case PBUF_RAM: + /* If pbuf is to be allocated in RAM, allocate memory for it. */ + p = (struct pbuf*)mem_malloc(LWIP_MEM_ALIGN_SIZE(SIZEOF_STRUCT_PBUF + offset) + LWIP_MEM_ALIGN_SIZE(length)); + if (p == NULL) { + return NULL; + } + /* Set up internal structure of the pbuf. */ + p->payload = LWIP_MEM_ALIGN((void *)((u8_t *)p + SIZEOF_STRUCT_PBUF + offset)); + p->len = p->tot_len = length; + p->next = NULL; + p->type = type; + + LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned", + ((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0); + break; + /* pbuf references existing (non-volatile static constant) ROM payload? */ + case PBUF_ROM: + /* pbuf references existing (externally allocated) RAM payload? */ + case PBUF_REF: + /* only allocate memory for the pbuf structure */ + p = (struct pbuf *)memp_malloc(MEMP_PBUF); + if (p == NULL) { + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("pbuf_alloc: Could not allocate MEMP_PBUF for PBUF_%s.\n", + (type == PBUF_ROM) ? "ROM" : "REF")); + return NULL; + } + /* caller must set this field properly, afterwards */ + p->payload = NULL; + p->len = p->tot_len = length; + p->next = NULL; + p->type = type; + break; + default: + LWIP_ASSERT("pbuf_alloc: erroneous type", 0); + return NULL; + } + /* set reference count */ + p->ref = 1; + /* set flags */ + p->flags = 0; + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F") == %p\n", length, (void *)p)); + return p; +} + +#if LWIP_SUPPORT_CUSTOM_PBUF +/** Initialize a custom pbuf (already allocated). + * + * @param layer flag to define header size + * @param length size of the pbuf's payload + * @param type type of the pbuf (only used to treat the pbuf accordingly, as + * this function allocates no memory) + * @param p pointer to the custom pbuf to initialize (already allocated) + * @param payload_mem pointer to the buffer that is used for payload and headers, + * must be at least big enough to hold 'length' plus the header size, + * may be NULL if set later. + * ATTENTION: The caller is responsible for correct alignment of this buffer!! + * @param payload_mem_len the size of the 'payload_mem' buffer, must be at least + * big enough to hold 'length' plus the header size + */ +struct pbuf* +pbuf_alloced_custom(pbuf_layer l, u16_t length, pbuf_type type, struct pbuf_custom *p, + void *payload_mem, u16_t payload_mem_len) +{ + u16_t offset; + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloced_custom(length=%"U16_F")\n", length)); + + /* determine header offset */ + switch (l) { + case PBUF_TRANSPORT: + /* add room for transport (often TCP) layer header */ + offset = PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN; + break; + case PBUF_IP: + /* add room for IP layer header */ + offset = PBUF_LINK_HLEN + PBUF_IP_HLEN; + break; + case PBUF_LINK: + /* add room for link layer header */ + offset = PBUF_LINK_HLEN; + break; + case PBUF_RAW: + offset = 0; + break; + default: + LWIP_ASSERT("pbuf_alloced_custom: bad pbuf layer", 0); + return NULL; + } + + if (LWIP_MEM_ALIGN_SIZE(offset) + length > payload_mem_len) { + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_WARNING, ("pbuf_alloced_custom(length=%"U16_F") buffer too short\n", length)); + return NULL; + } + + p->pbuf.next = NULL; + if (payload_mem != NULL) { + p->pbuf.payload = (u8_t *)payload_mem + LWIP_MEM_ALIGN_SIZE(offset); + } else { + p->pbuf.payload = NULL; + } + p->pbuf.flags = PBUF_FLAG_IS_CUSTOM; + p->pbuf.len = p->pbuf.tot_len = length; + p->pbuf.type = type; + p->pbuf.ref = 1; + return &p->pbuf; +} +#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ + +/** + * Shrink a pbuf chain to a desired length. + * + * @param p pbuf to shrink. + * @param new_len desired new length of pbuf chain + * + * Depending on the desired length, the first few pbufs in a chain might + * be skipped and left unchanged. The new last pbuf in the chain will be + * resized, and any remaining pbufs will be freed. + * + * @note If the pbuf is ROM/REF, only the ->tot_len and ->len fields are adjusted. + * @note May not be called on a packet queue. + * + * @note Despite its name, pbuf_realloc cannot grow the size of a pbuf (chain). + */ +void +pbuf_realloc(struct pbuf *p, u16_t new_len) +{ + struct pbuf *q; + u16_t rem_len; /* remaining length */ + s32_t grow; + + LWIP_ASSERT("pbuf_realloc: p != NULL", p != NULL); + LWIP_ASSERT("pbuf_realloc: sane p->type", p->type == PBUF_POOL || + p->type == PBUF_ROM || + p->type == PBUF_RAM || + p->type == PBUF_REF); + + /* desired length larger than current length? */ + if (new_len >= p->tot_len) { + /* enlarging not yet supported */ + return; + } + + /* the pbuf chain grows by (new_len - p->tot_len) bytes + * (which may be negative in case of shrinking) */ + grow = new_len - p->tot_len; + + /* first, step over any pbufs that should remain in the chain */ + rem_len = new_len; + q = p; + /* should this pbuf be kept? */ + while (rem_len > q->len) { + /* decrease remaining length by pbuf length */ + rem_len -= q->len; + /* decrease total length indicator */ + LWIP_ASSERT("grow < max_u16_t", grow < 0xffff); + q->tot_len += (u16_t)grow; + /* proceed to next pbuf in chain */ + q = q->next; + LWIP_ASSERT("pbuf_realloc: q != NULL", q != NULL); + } + /* we have now reached the new last pbuf (in q) */ + /* rem_len == desired length for pbuf q */ + + /* shrink allocated memory for PBUF_RAM */ + /* (other types merely adjust their length fields */ + if ((q->type == PBUF_RAM) && (rem_len != q->len)) { + /* reallocate and adjust the length of the pbuf that will be split */ + q = (struct pbuf *)mem_trim(q, (u16_t)((u8_t *)q->payload - (u8_t *)q) + rem_len); + LWIP_ASSERT("mem_trim returned q == NULL", q != NULL); + } + /* adjust length fields for new last pbuf */ + q->len = rem_len; + q->tot_len = q->len; + + /* any remaining pbufs in chain? */ + if (q->next != NULL) { + /* free remaining pbufs in chain */ + pbuf_free(q->next); + } + /* q is last packet in chain */ + q->next = NULL; + +} + +/** + * Adjusts the payload pointer to hide or reveal headers in the payload. + * + * Adjusts the ->payload pointer so that space for a header + * (dis)appears in the pbuf payload. + * + * The ->payload, ->tot_len and ->len fields are adjusted. + * + * @param p pbuf to change the header size. + * @param header_size_increment Number of bytes to increment header size which + * increases the size of the pbuf. New space is on the front. + * (Using a negative value decreases the header size.) + * If hdr_size_inc is 0, this function does nothing and returns succesful. + * + * PBUF_ROM and PBUF_REF type buffers cannot have their sizes increased, so + * the call will fail. A check is made that the increase in header size does + * not move the payload pointer in front of the start of the buffer. + * @return non-zero on failure, zero on success. + * + */ +u8_t +pbuf_header(struct pbuf *p, s16_t header_size_increment) +{ + u16_t type; + void *payload; + u16_t increment_magnitude; + + LWIP_ASSERT("p != NULL", p != NULL); + if ((header_size_increment == 0) || (p == NULL)) { + return 0; + } + + if (header_size_increment < 0){ + increment_magnitude = -header_size_increment; + /* Check that we aren't going to move off the end of the pbuf */ + LWIP_ERROR("increment_magnitude <= p->len", (increment_magnitude <= p->len), return 1;); + } else { + increment_magnitude = header_size_increment; +#if 0 + /* Can't assert these as some callers speculatively call + pbuf_header() to see if it's OK. Will return 1 below instead. */ + /* Check that we've got the correct type of pbuf to work with */ + LWIP_ASSERT("p->type == PBUF_RAM || p->type == PBUF_POOL", + p->type == PBUF_RAM || p->type == PBUF_POOL); + /* Check that we aren't going to move off the beginning of the pbuf */ + LWIP_ASSERT("p->payload - increment_magnitude >= p + SIZEOF_STRUCT_PBUF", + (u8_t *)p->payload - increment_magnitude >= (u8_t *)p + SIZEOF_STRUCT_PBUF); +#endif + } + + type = p->type; + /* remember current payload pointer */ + payload = p->payload; + + /* pbuf types containing payloads? */ + if (type == PBUF_RAM || type == PBUF_POOL) { + /* set new payload pointer */ + p->payload = (u8_t *)p->payload - header_size_increment; + /* boundary check fails? */ + if ((u8_t *)p->payload < (u8_t *)p + SIZEOF_STRUCT_PBUF) { + LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("pbuf_header: failed as %p < %p (not enough space for new header size)\n", + (void *)p->payload, (void *)(p + 1))); + /* restore old payload pointer */ + p->payload = payload; + /* bail out unsuccesfully */ + return 1; + } + /* pbuf types refering to external payloads? */ + } else if (type == PBUF_REF || type == PBUF_ROM) { + /* hide a header in the payload? */ + if ((header_size_increment < 0) && (increment_magnitude <= p->len)) { + /* increase payload pointer */ + p->payload = (u8_t *)p->payload - header_size_increment; + } else { + /* cannot expand payload to front (yet!) + * bail out unsuccesfully */ + return 1; + } + } else { + /* Unknown type */ + LWIP_ASSERT("bad pbuf type", 0); + return 1; + } + /* modify pbuf length fields */ + p->len += header_size_increment; + p->tot_len += header_size_increment; + + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_header: old %p new %p (%"S16_F")\n", + (void *)payload, (void *)p->payload, header_size_increment)); + + return 0; +} + +/** + * Dereference a pbuf chain or queue and deallocate any no-longer-used + * pbufs at the head of this chain or queue. + * + * Decrements the pbuf reference count. If it reaches zero, the pbuf is + * deallocated. + * + * For a pbuf chain, this is repeated for each pbuf in the chain, + * up to the first pbuf which has a non-zero reference count after + * decrementing. So, when all reference counts are one, the whole + * chain is free'd. + * + * @param p The pbuf (chain) to be dereferenced. + * + * @return the number of pbufs that were de-allocated + * from the head of the chain. + * + * @note MUST NOT be called on a packet queue (Not verified to work yet). + * @note the reference counter of a pbuf equals the number of pointers + * that refer to the pbuf (or into the pbuf). + * + * @internal examples: + * + * Assuming existing chains a->b->c with the following reference + * counts, calling pbuf_free(a) results in: + * + * 1->2->3 becomes ...1->3 + * 3->3->3 becomes 2->3->3 + * 1->1->2 becomes ......1 + * 2->1->1 becomes 1->1->1 + * 1->1->1 becomes ....... + * + */ +u8_t +pbuf_free(struct pbuf *p) +{ + u16_t type; + struct pbuf *q; + u8_t count; + + if (p == NULL) { + LWIP_ASSERT("p != NULL", p != NULL); + /* if assertions are disabled, proceed with debug output */ + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("pbuf_free(p == NULL) was called.\n")); + return 0; + } + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free(%p)\n", (void *)p)); + + PERF_START; + + LWIP_ASSERT("pbuf_free: sane type", + p->type == PBUF_RAM || p->type == PBUF_ROM || + p->type == PBUF_REF || p->type == PBUF_POOL); + + count = 0; + /* de-allocate all consecutive pbufs from the head of the chain that + * obtain a zero reference count after decrementing*/ + while (p != NULL) { + u16_t ref; + SYS_ARCH_DECL_PROTECT(old_level); + /* Since decrementing ref cannot be guaranteed to be a single machine operation + * we must protect it. We put the new ref into a local variable to prevent + * further protection. */ + SYS_ARCH_PROTECT(old_level); + /* all pbufs in a chain are referenced at least once */ + LWIP_ASSERT("pbuf_free: p->ref > 0", p->ref > 0); + /* decrease reference count (number of pointers to pbuf) */ + ref = --(p->ref); + SYS_ARCH_UNPROTECT(old_level); + /* this pbuf is no longer referenced to? */ + if (ref == 0) { + /* remember next pbuf in chain for next iteration */ + q = p->next; + LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: deallocating %p\n", (void *)p)); + type = p->type; +#if LWIP_SUPPORT_CUSTOM_PBUF + /* is this a custom pbuf? */ + if ((p->flags & PBUF_FLAG_IS_CUSTOM) != 0) { + struct pbuf_custom *pc = (struct pbuf_custom*)p; + LWIP_ASSERT("pc->custom_free_function != NULL", pc->custom_free_function != NULL); + pc->custom_free_function(p); + } else +#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ + { + /* is this a pbuf from the pool? */ + if (type == PBUF_POOL) { + memp_free(MEMP_PBUF_POOL, p); + /* is this a ROM or RAM referencing pbuf? */ + } else if (type == PBUF_ROM || type == PBUF_REF) { + memp_free(MEMP_PBUF, p); + /* type == PBUF_RAM */ + } else { + mem_free(p); + } + } + count++; + /* proceed to next pbuf */ + p = q; + /* p->ref > 0, this pbuf is still referenced to */ + /* (and so the remaining pbufs in chain as well) */ + } else { + LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: %p has ref %"U16_F", ending here.\n", (void *)p, ref)); + /* stop walking through the chain */ + p = NULL; + } + } + PERF_STOP("pbuf_free"); + /* return number of de-allocated pbufs */ + return count; +} + +/** + * Count number of pbufs in a chain + * + * @param p first pbuf of chain + * @return the number of pbufs in a chain + */ + +u8_t +pbuf_clen(struct pbuf *p) +{ + u8_t len; + + len = 0; + while (p != NULL) { + ++len; + p = p->next; + } + return len; +} + +/** + * Increment the reference count of the pbuf. + * + * @param p pbuf to increase reference counter of + * + */ +void +pbuf_ref(struct pbuf *p) +{ + SYS_ARCH_DECL_PROTECT(old_level); + /* pbuf given? */ + if (p != NULL) { + SYS_ARCH_PROTECT(old_level); + ++(p->ref); + SYS_ARCH_UNPROTECT(old_level); + } +} + +/** + * Concatenate two pbufs (each may be a pbuf chain) and take over + * the caller's reference of the tail pbuf. + * + * @note The caller MAY NOT reference the tail pbuf afterwards. + * Use pbuf_chain() for that purpose. + * + * @see pbuf_chain() + */ + +void +pbuf_cat(struct pbuf *h, struct pbuf *t) +{ + struct pbuf *p; + + LWIP_ERROR("(h != NULL) && (t != NULL) (programmer violates API)", + ((h != NULL) && (t != NULL)), return;); + + /* proceed to last pbuf of chain */ + for (p = h; p->next != NULL; p = p->next) { + /* add total length of second chain to all totals of first chain */ + p->tot_len += t->tot_len; + } + /* { p is last pbuf of first h chain, p->next == NULL } */ + LWIP_ASSERT("p->tot_len == p->len (of last pbuf in chain)", p->tot_len == p->len); + LWIP_ASSERT("p->next == NULL", p->next == NULL); + /* add total length of second chain to last pbuf total of first chain */ + p->tot_len += t->tot_len; + /* chain last pbuf of head (p) with first of tail (t) */ + p->next = t; + /* p->next now references t, but the caller will drop its reference to t, + * so netto there is no change to the reference count of t. + */ +} + +/** + * Chain two pbufs (or pbuf chains) together. + * + * The caller MUST call pbuf_free(t) once it has stopped + * using it. Use pbuf_cat() instead if you no longer use t. + * + * @param h head pbuf (chain) + * @param t tail pbuf (chain) + * @note The pbufs MUST belong to the same packet. + * @note MAY NOT be called on a packet queue. + * + * The ->tot_len fields of all pbufs of the head chain are adjusted. + * The ->next field of the last pbuf of the head chain is adjusted. + * The ->ref field of the first pbuf of the tail chain is adjusted. + * + */ +void +pbuf_chain(struct pbuf *h, struct pbuf *t) +{ + pbuf_cat(h, t); + /* t is now referenced by h */ + pbuf_ref(t); + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_chain: %p references %p\n", (void *)h, (void *)t)); +} + +/** + * Dechains the first pbuf from its succeeding pbufs in the chain. + * + * Makes p->tot_len field equal to p->len. + * @param p pbuf to dechain + * @return remainder of the pbuf chain, or NULL if it was de-allocated. + * @note May not be called on a packet queue. + */ +struct pbuf * +pbuf_dechain(struct pbuf *p) +{ + struct pbuf *q; + u8_t tail_gone = 1; + /* tail */ + q = p->next; + /* pbuf has successor in chain? */ + if (q != NULL) { + /* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */ + LWIP_ASSERT("p->tot_len == p->len + q->tot_len", q->tot_len == p->tot_len - p->len); + /* enforce invariant if assertion is disabled */ + q->tot_len = p->tot_len - p->len; + /* decouple pbuf from remainder */ + p->next = NULL; + /* total length of pbuf p is its own length only */ + p->tot_len = p->len; + /* q is no longer referenced by p, free it */ + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_dechain: unreferencing %p\n", (void *)q)); + tail_gone = pbuf_free(q); + if (tail_gone > 0) { + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, + ("pbuf_dechain: deallocated %p (as it is no longer referenced)\n", (void *)q)); + } + /* return remaining tail or NULL if deallocated */ + } + /* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */ + LWIP_ASSERT("p->tot_len == p->len", p->tot_len == p->len); + return ((tail_gone > 0) ? NULL : q); +} + +/** + * + * Create PBUF_RAM copies of pbufs. + * + * Used to queue packets on behalf of the lwIP stack, such as + * ARP based queueing. + * + * @note You MUST explicitly use p = pbuf_take(p); + * + * @note Only one packet is copied, no packet queue! + * + * @param p_to pbuf destination of the copy + * @param p_from pbuf source of the copy + * + * @return ERR_OK if pbuf was copied + * ERR_ARG if one of the pbufs is NULL or p_to is not big + * enough to hold p_from + */ +err_t +pbuf_copy(struct pbuf *p_to, struct pbuf *p_from) +{ + u16_t offset_to=0, offset_from=0, len; + + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy(%p, %p)\n", + (void*)p_to, (void*)p_from)); + + /* is the target big enough to hold the source? */ + LWIP_ERROR("pbuf_copy: target not big enough to hold source", ((p_to != NULL) && + (p_from != NULL) && (p_to->tot_len >= p_from->tot_len)), return ERR_ARG;); + + /* iterate through pbuf chain */ + do + { + /* copy one part of the original chain */ + if ((p_to->len - offset_to) >= (p_from->len - offset_from)) { + /* complete current p_from fits into current p_to */ + len = p_from->len - offset_from; + } else { + /* current p_from does not fit into current p_to */ + len = p_to->len - offset_to; + } + MEMCPY((u8_t*)p_to->payload + offset_to, (u8_t*)p_from->payload + offset_from, len); + offset_to += len; + offset_from += len; + LWIP_ASSERT("offset_to <= p_to->len", offset_to <= p_to->len); + LWIP_ASSERT("offset_from <= p_from->len", offset_from <= p_from->len); + if (offset_from >= p_from->len) { + /* on to next p_from (if any) */ + offset_from = 0; + p_from = p_from->next; + } + if (offset_to == p_to->len) { + /* on to next p_to (if any) */ + offset_to = 0; + p_to = p_to->next; + LWIP_ERROR("p_to != NULL", (p_to != NULL) || (p_from == NULL) , return ERR_ARG;); + } + + if((p_from != NULL) && (p_from->len == p_from->tot_len)) { + /* don't copy more than one packet! */ + LWIP_ERROR("pbuf_copy() does not allow packet queues!\n", + (p_from->next == NULL), return ERR_VAL;); + } + if((p_to != NULL) && (p_to->len == p_to->tot_len)) { + /* don't copy more than one packet! */ + LWIP_ERROR("pbuf_copy() does not allow packet queues!\n", + (p_to->next == NULL), return ERR_VAL;); + } + } while (p_from); + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy: end of chain reached.\n")); + return ERR_OK; +} + +/** + * Copy (part of) the contents of a packet buffer + * to an application supplied buffer. + * + * @param buf the pbuf from which to copy data + * @param dataptr the application supplied buffer + * @param len length of data to copy (dataptr must be big enough). No more + * than buf->tot_len will be copied, irrespective of len + * @param offset offset into the packet buffer from where to begin copying len bytes + * @return the number of bytes copied, or 0 on failure + */ +u16_t +pbuf_copy_partial(struct pbuf *buf, void *dataptr, u16_t len, u16_t offset) +{ + struct pbuf *p; + u16_t left; + u16_t buf_copy_len; + u16_t copied_total = 0; + + LWIP_ERROR("pbuf_copy_partial: invalid buf", (buf != NULL), return 0;); + LWIP_ERROR("pbuf_copy_partial: invalid dataptr", (dataptr != NULL), return 0;); + + left = 0; + + if((buf == NULL) || (dataptr == NULL)) { + return 0; + } + + /* Note some systems use byte copy if dataptr or one of the pbuf payload pointers are unaligned. */ + for(p = buf; len != 0 && p != NULL; p = p->next) { + if ((offset != 0) && (offset >= p->len)) { + /* don't copy from this buffer -> on to the next */ + offset -= p->len; + } else { + /* copy from this buffer. maybe only partially. */ + buf_copy_len = p->len - offset; + if (buf_copy_len > len) + buf_copy_len = len; + /* copy the necessary parts of the buffer */ + MEMCPY(&((char*)dataptr)[left], &((char*)p->payload)[offset], buf_copy_len); + copied_total += buf_copy_len; + left += buf_copy_len; + len -= buf_copy_len; + offset = 0; + } + } + return copied_total; +} + +/** + * Copy application supplied data into a pbuf. + * This function can only be used to copy the equivalent of buf->tot_len data. + * + * @param buf pbuf to fill with data + * @param dataptr application supplied data buffer + * @param len length of the application supplied data buffer + * + * @return ERR_OK if successful, ERR_MEM if the pbuf is not big enough + */ +err_t +pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len) +{ + struct pbuf *p; + u16_t buf_copy_len; + u16_t total_copy_len = len; + u16_t copied_total = 0; + + LWIP_ERROR("pbuf_take: invalid buf", (buf != NULL), return 0;); + LWIP_ERROR("pbuf_take: invalid dataptr", (dataptr != NULL), return 0;); + + if ((buf == NULL) || (dataptr == NULL) || (buf->tot_len < len)) { + return ERR_ARG; + } + + /* Note some systems use byte copy if dataptr or one of the pbuf payload pointers are unaligned. */ + for(p = buf; total_copy_len != 0; p = p->next) { + LWIP_ASSERT("pbuf_take: invalid pbuf", p != NULL); + buf_copy_len = total_copy_len; + if (buf_copy_len > p->len) { + /* this pbuf cannot hold all remaining data */ + buf_copy_len = p->len; + } + /* copy the necessary parts of the buffer */ + MEMCPY(p->payload, &((char*)dataptr)[copied_total], buf_copy_len); + total_copy_len -= buf_copy_len; + copied_total += buf_copy_len; + } + LWIP_ASSERT("did not copy all data", total_copy_len == 0 && copied_total == len); + return ERR_OK; +} + +/** + * Creates a single pbuf out of a queue of pbufs. + * + * @remark: Either the source pbuf 'p' is freed by this function or the original + * pbuf 'p' is returned, therefore the caller has to check the result! + * + * @param p the source pbuf + * @param layer pbuf_layer of the new pbuf + * + * @return a new, single pbuf (p->next is NULL) + * or the old pbuf if allocation fails + */ +struct pbuf* +pbuf_coalesce(struct pbuf *p, pbuf_layer layer) +{ + struct pbuf *q; + err_t err; + if (p->next == NULL) { + return p; + } + q = pbuf_alloc(layer, p->tot_len, PBUF_RAM); + if (q == NULL) { + /* @todo: what do we do now? */ + return p; + } + err = pbuf_copy(q, p); + LWIP_ASSERT("pbuf_copy failed", err == ERR_OK); + pbuf_free(p); + return q; +} + +#if LWIP_CHECKSUM_ON_COPY +/** + * Copies data into a single pbuf (*not* into a pbuf queue!) and updates + * the checksum while copying + * + * @param p the pbuf to copy data into + * @param start_offset offset of p->payload where to copy the data to + * @param dataptr data to copy into the pbuf + * @param len length of data to copy into the pbuf + * @param chksum pointer to the checksum which is updated + * @return ERR_OK if successful, another error if the data does not fit + * within the (first) pbuf (no pbuf queues!) + */ +err_t +pbuf_fill_chksum(struct pbuf *p, u16_t start_offset, const void *dataptr, + u16_t len, u16_t *chksum) +{ + u32_t acc; + u16_t copy_chksum; + char *dst_ptr; + LWIP_ASSERT("p != NULL", p != NULL); + LWIP_ASSERT("dataptr != NULL", dataptr != NULL); + LWIP_ASSERT("chksum != NULL", chksum != NULL); + LWIP_ASSERT("len != 0", len != 0); + + if ((start_offset >= p->len) || (start_offset + len > p->len)) { + return ERR_ARG; + } + + dst_ptr = ((char*)p->payload) + start_offset; + copy_chksum = LWIP_CHKSUM_COPY(dst_ptr, dataptr, len); + if ((start_offset & 1) != 0) { + copy_chksum = SWAP_BYTES_IN_WORD(copy_chksum); + } + acc = *chksum; + acc += copy_chksum; + *chksum = FOLD_U32T(acc); + return ERR_OK; +} +#endif /* LWIP_CHECKSUM_ON_COPY */ + + /** Get one byte from the specified position in a pbuf + * WARNING: returns zero for offset >= p->tot_len + * + * @param p pbuf to parse + * @param offset offset into p of the byte to return + * @return byte at an offset into p OR ZERO IF 'offset' >= p->tot_len + */ +u8_t +pbuf_get_at(struct pbuf* p, u16_t offset) +{ + u16_t copy_from = offset; + struct pbuf* q = p; + + /* get the correct pbuf */ + while ((q != NULL) && (q->len <= copy_from)) { + copy_from -= q->len; + q = q->next; + } + /* return requested data if pbuf is OK */ + if ((q != NULL) && (q->len > copy_from)) { + return ((u8_t*)q->payload)[copy_from]; + } + return 0; +} + +/** Compare pbuf contents at specified offset with memory s2, both of length n + * + * @param p pbuf to compare + * @param offset offset into p at wich to start comparing + * @param s2 buffer to compare + * @param n length of buffer to compare + * @return zero if equal, nonzero otherwise + * (0xffff if p is too short, diffoffset+1 otherwise) + */ +u16_t +pbuf_memcmp(struct pbuf* p, u16_t offset, const void* s2, u16_t n) +{ + u16_t start = offset; + struct pbuf* q = p; + + /* get the correct pbuf */ + while ((q != NULL) && (q->len <= start)) { + start -= q->len; + q = q->next; + } + /* return requested data if pbuf is OK */ + if ((q != NULL) && (q->len > start)) { + u16_t i; + for(i = 0; i < n; i++) { + u8_t a = pbuf_get_at(q, start + i); + u8_t b = ((u8_t*)s2)[i]; + if (a != b) { + return i+1; + } + } + return 0; + } + return 0xffff; +} + +/** Find occurrence of mem (with length mem_len) in pbuf p, starting at offset + * start_offset. + * + * @param p pbuf to search, maximum length is 0xFFFE since 0xFFFF is used as + * return value 'not found' + * @param mem search for the contents of this buffer + * @param mem_len length of 'mem' + * @param start_offset offset into p at which to start searching + * @return 0xFFFF if substr was not found in p or the index where it was found + */ +u16_t +pbuf_memfind(struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset) +{ + u16_t i; + u16_t max = p->tot_len - mem_len; + if (p->tot_len >= mem_len + start_offset) { + for(i = start_offset; i <= max; ) { + u16_t plus = pbuf_memcmp(p, i, mem, mem_len); + if (plus == 0) { + return i; + } else { + i += plus; + } + } + } + return 0xFFFF; +} + +/** Find occurrence of substr with length substr_len in pbuf p, start at offset + * start_offset + * WARNING: in contrast to strstr(), this one does not stop at the first \0 in + * the pbuf/source string! + * + * @param p pbuf to search, maximum length is 0xFFFE since 0xFFFF is used as + * return value 'not found' + * @param substr string to search for in p, maximum length is 0xFFFE + * @return 0xFFFF if substr was not found in p or the index where it was found + */ +u16_t +pbuf_strstr(struct pbuf* p, const char* substr) +{ + size_t substr_len; + if ((substr == NULL) || (substr[0] == 0) || (p->tot_len == 0xFFFF)) { + return 0xFFFF; + } + substr_len = strlen(substr); + if (substr_len >= 0xFFFF) { + return 0xFFFF; + } + return pbuf_memfind(p, substr, (u16_t)substr_len, 0); +} diff --git a/component/common/network/lwip/lwip_v1.4.1/src/core/raw.c b/component/common/network/lwip/lwip_v1.4.1/src/core/raw.c new file mode 100644 index 0000000..7160c0f --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/core/raw.c @@ -0,0 +1,350 @@ +/** + * @file + * Implementation of raw protocol PCBs for low-level handling of + * different types of protocols besides (or overriding) those + * already available in lwIP. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_RAW /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/memp.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/raw.h" +#include "lwip/stats.h" +#include "arch/perf.h" + +#include + +/** The list of RAW PCBs */ +static struct raw_pcb *raw_pcbs; + +/** + * Determine if in incoming IP packet is covered by a RAW PCB + * and if so, pass it to a user-provided receive callback function. + * + * Given an incoming IP datagram (as a chain of pbufs) this function + * finds a corresponding RAW PCB and calls the corresponding receive + * callback function. + * + * @param p pbuf to be demultiplexed to a RAW PCB. + * @param inp network interface on which the datagram was received. + * @return - 1 if the packet has been eaten by a RAW PCB receive + * callback function. The caller MAY NOT not reference the + * packet any longer, and MAY NOT call pbuf_free(). + * @return - 0 if packet is not eaten (pbuf is still referenced by the + * caller). + * + */ +u8_t +raw_input(struct pbuf *p, struct netif *inp) +{ + struct raw_pcb *pcb, *prev; + struct ip_hdr *iphdr; + s16_t proto; + u8_t eaten = 0; + + LWIP_UNUSED_ARG(inp); + + iphdr = (struct ip_hdr *)p->payload; + proto = IPH_PROTO(iphdr); + + prev = NULL; + pcb = raw_pcbs; + /* loop through all raw pcbs until the packet is eaten by one */ + /* this allows multiple pcbs to match against the packet by design */ + while ((eaten == 0) && (pcb != NULL)) { + if ((pcb->protocol == proto) && + (ip_addr_isany(&pcb->local_ip) || + ip_addr_cmp(&(pcb->local_ip), ¤t_iphdr_dest))) { +#if IP_SOF_BROADCAST_RECV + /* broadcast filter? */ + if (ip_get_option(pcb, SOF_BROADCAST) || !ip_addr_isbroadcast(¤t_iphdr_dest, inp)) +#endif /* IP_SOF_BROADCAST_RECV */ + { + /* receive callback function available? */ + if (pcb->recv != NULL) { + /* the receive callback function did not eat the packet? */ + if (pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr()) != 0) { + /* receive function ate the packet */ + p = NULL; + eaten = 1; + if (prev != NULL) { + /* move the pcb to the front of raw_pcbs so that is + found faster next time */ + prev->next = pcb->next; + pcb->next = raw_pcbs; + raw_pcbs = pcb; + } + } + } + /* no receive callback function was set for this raw PCB */ + } + /* drop the packet */ + } + prev = pcb; + pcb = pcb->next; + } + return eaten; +} + +/** + * Bind a RAW PCB. + * + * @param pcb RAW PCB to be bound with a local address ipaddr. + * @param ipaddr local IP address to bind with. Use IP_ADDR_ANY to + * bind to all local interfaces. + * + * @return lwIP error code. + * - ERR_OK. Successful. No error occured. + * - ERR_USE. The specified IP address is already bound to by + * another RAW PCB. + * + * @see raw_disconnect() + */ +err_t +raw_bind(struct raw_pcb *pcb, ip_addr_t *ipaddr) +{ + ip_addr_set(&pcb->local_ip, ipaddr); + return ERR_OK; +} + +/** + * Connect an RAW PCB. This function is required by upper layers + * of lwip. Using the raw api you could use raw_sendto() instead + * + * This will associate the RAW PCB with the remote address. + * + * @param pcb RAW PCB to be connected with remote address ipaddr and port. + * @param ipaddr remote IP address to connect with. + * + * @return lwIP error code + * + * @see raw_disconnect() and raw_sendto() + */ +err_t +raw_connect(struct raw_pcb *pcb, ip_addr_t *ipaddr) +{ + ip_addr_set(&pcb->remote_ip, ipaddr); + return ERR_OK; +} + + +/** + * Set the callback function for received packets that match the + * raw PCB's protocol and binding. + * + * The callback function MUST either + * - eat the packet by calling pbuf_free() and returning non-zero. The + * packet will not be passed to other raw PCBs or other protocol layers. + * - not free the packet, and return zero. The packet will be matched + * against further PCBs and/or forwarded to another protocol layers. + * + * @return non-zero if the packet was free()d, zero if the packet remains + * available for others. + */ +void +raw_recv(struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg) +{ + /* remember recv() callback and user data */ + pcb->recv = recv; + pcb->recv_arg = recv_arg; +} + +/** + * Send the raw IP packet to the given address. Note that actually you cannot + * modify the IP headers (this is inconsistent with the receive callback where + * you actually get the IP headers), you can only specify the IP payload here. + * It requires some more changes in lwIP. (there will be a raw_send() function + * then.) + * + * @param pcb the raw pcb which to send + * @param p the IP payload to send + * @param ipaddr the destination address of the IP packet + * + */ +err_t +raw_sendto(struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr) +{ + err_t err; + struct netif *netif; + ip_addr_t *src_ip; + struct pbuf *q; /* q will be sent down the stack */ + + LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_sendto\n")); + + /* not enough space to add an IP header to first pbuf in given p chain? */ + if (pbuf_header(p, IP_HLEN)) { + /* allocate header in new pbuf */ + q = pbuf_alloc(PBUF_IP, 0, PBUF_RAM); + /* new header pbuf could not be allocated? */ + if (q == NULL) { + LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("raw_sendto: could not allocate header\n")); + return ERR_MEM; + } + if (p->tot_len != 0) { + /* chain header q in front of given pbuf p */ + pbuf_chain(q, p); + } + /* { first pbuf q points to header pbuf } */ + LWIP_DEBUGF(RAW_DEBUG, ("raw_sendto: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p)); + } else { + /* first pbuf q equals given pbuf */ + q = p; + if(pbuf_header(q, -IP_HLEN)) { + LWIP_ASSERT("Can't restore header we just removed!", 0); + return ERR_MEM; + } + } + + if ((netif = ip_route(ipaddr)) == NULL) { + LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr))); + /* free any temporary header pbuf allocated by pbuf_header() */ + if (q != p) { + pbuf_free(q); + } + return ERR_RTE; + } + +#if IP_SOF_BROADCAST + /* broadcast filter? */ + if (!ip_get_option(pcb, SOF_BROADCAST) && ip_addr_isbroadcast(ipaddr, netif)) { + LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb)); + /* free any temporary header pbuf allocated by pbuf_header() */ + if (q != p) { + pbuf_free(q); + } + return ERR_VAL; + } +#endif /* IP_SOF_BROADCAST */ + + if (ip_addr_isany(&pcb->local_ip)) { + /* use outgoing network interface IP address as source address */ + src_ip = &(netif->ip_addr); + } else { + /* use RAW PCB local IP address as source address */ + src_ip = &(pcb->local_ip); + } + + NETIF_SET_HWADDRHINT(netif, &pcb->addr_hint); + err = ip_output_if (q, src_ip, ipaddr, pcb->ttl, pcb->tos, pcb->protocol, netif); + NETIF_SET_HWADDRHINT(netif, NULL); + + /* did we chain a header earlier? */ + if (q != p) { + /* free the header */ + pbuf_free(q); + } + return err; +} + +/** + * Send the raw IP packet to the address given by raw_connect() + * + * @param pcb the raw pcb which to send + * @param p the IP payload to send + * + */ +err_t +raw_send(struct raw_pcb *pcb, struct pbuf *p) +{ + return raw_sendto(pcb, p, &pcb->remote_ip); +} + +/** + * Remove an RAW PCB. + * + * @param pcb RAW PCB to be removed. The PCB is removed from the list of + * RAW PCB's and the data structure is freed from memory. + * + * @see raw_new() + */ +void +raw_remove(struct raw_pcb *pcb) +{ + struct raw_pcb *pcb2; + /* pcb to be removed is first in list? */ + if (raw_pcbs == pcb) { + /* make list start at 2nd pcb */ + raw_pcbs = raw_pcbs->next; + /* pcb not 1st in list */ + } else { + for(pcb2 = raw_pcbs; pcb2 != NULL; pcb2 = pcb2->next) { + /* find pcb in raw_pcbs list */ + if (pcb2->next != NULL && pcb2->next == pcb) { + /* remove pcb from list */ + pcb2->next = pcb->next; + } + } + } + memp_free(MEMP_RAW_PCB, pcb); +} + +/** + * Create a RAW PCB. + * + * @return The RAW PCB which was created. NULL if the PCB data structure + * could not be allocated. + * + * @param proto the protocol number of the IPs payload (e.g. IP_PROTO_ICMP) + * + * @see raw_remove() + */ +struct raw_pcb * +raw_new(u8_t proto) +{ + struct raw_pcb *pcb; + + LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_new\n")); + + pcb = (struct raw_pcb *)memp_malloc(MEMP_RAW_PCB); + /* could allocate RAW PCB? */ + if (pcb != NULL) { + /* initialize PCB to all zeroes */ + memset(pcb, 0, sizeof(struct raw_pcb)); + pcb->protocol = proto; + pcb->ttl = RAW_TTL; + pcb->next = raw_pcbs; + raw_pcbs = pcb; + } + return pcb; +} + +#endif /* LWIP_RAW */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/core/snmp/asn1_dec.c b/component/common/network/lwip/lwip_v1.4.1/src/core/snmp/asn1_dec.c new file mode 100644 index 0000000..1d56582 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/core/snmp/asn1_dec.c @@ -0,0 +1,657 @@ +/** + * @file + * Abstract Syntax Notation One (ISO 8824, 8825) decoding + * + * @todo not optimised (yet), favor correctness over speed, favor speed over size + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * Author: Christiaan Simons + */ + +#include "lwip/opt.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/snmp_asn1.h" + +/** + * Retrieves type field from incoming pbuf chain. + * + * @param p points to a pbuf holding an ASN1 coded type field + * @param ofs points to the offset within the pbuf chain of the ASN1 coded type field + * @param type return ASN1 type + * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) decode + */ +err_t +snmp_asn1_dec_type(struct pbuf *p, u16_t ofs, u8_t *type) +{ + u16_t plen, base; + u8_t *msg_ptr; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = (u8_t*)p->payload; + msg_ptr += ofs - base; + *type = *msg_ptr; + return ERR_OK; + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +/** + * Decodes length field from incoming pbuf chain into host length. + * + * @param p points to a pbuf holding an ASN1 coded length + * @param ofs points to the offset within the pbuf chain of the ASN1 coded length + * @param octets_used returns number of octets used by the length code + * @param length return host order length, upto 64k + * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) decode + */ +err_t +snmp_asn1_dec_length(struct pbuf *p, u16_t ofs, u8_t *octets_used, u16_t *length) +{ + u16_t plen, base; + u8_t *msg_ptr; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = (u8_t*)p->payload; + msg_ptr += ofs - base; + + if (*msg_ptr < 0x80) + { + /* primitive definite length format */ + *octets_used = 1; + *length = *msg_ptr; + return ERR_OK; + } + else if (*msg_ptr == 0x80) + { + /* constructed indefinite length format, termination with two zero octets */ + u8_t zeros; + u8_t i; + + *length = 0; + zeros = 0; + while (zeros != 2) + { + i = 2; + while (i > 0) + { + i--; + (*length) += 1; + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + if (*msg_ptr == 0) + { + zeros++; + if (zeros == 2) + { + /* stop while (i > 0) */ + i = 0; + } + } + else + { + zeros = 0; + } + } + } + *octets_used = 1; + return ERR_OK; + } + else if (*msg_ptr == 0x81) + { + /* constructed definite length format, one octet */ + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + *length = *msg_ptr; + *octets_used = 2; + return ERR_OK; + } + else if (*msg_ptr == 0x82) + { + u8_t i; + + /* constructed definite length format, two octets */ + i = 2; + while (i > 0) + { + i--; + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + if (i == 0) + { + /* least significant length octet */ + *length |= *msg_ptr; + } + else + { + /* most significant length octet */ + *length = (*msg_ptr) << 8; + } + } + *octets_used = 3; + return ERR_OK; + } + else + { + /* constructed definite length format 3..127 octets, this is too big (>64k) */ + /** @todo: do we need to accept inefficient codings with many leading zero's? */ + *octets_used = 1 + ((*msg_ptr) & 0x7f); + return ERR_ARG; + } + } + p = p->next; + } + + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +/** + * Decodes positive integer (counter, gauge, timeticks) into u32_t. + * + * @param p points to a pbuf holding an ASN1 coded integer + * @param ofs points to the offset within the pbuf chain of the ASN1 coded integer + * @param len length of the coded integer field + * @param value return host order integer + * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) decode + * + * @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded + * as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value + * of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!! + */ +err_t +snmp_asn1_dec_u32t(struct pbuf *p, u16_t ofs, u16_t len, u32_t *value) +{ + u16_t plen, base; + u8_t *msg_ptr; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = (u8_t*)p->payload; + msg_ptr += ofs - base; + if ((len > 0) && (len < 6)) + { + /* start from zero */ + *value = 0; + if (*msg_ptr & 0x80) + { + /* negative, expecting zero sign bit! */ + return ERR_ARG; + } + else + { + /* positive */ + if ((len > 1) && (*msg_ptr == 0)) + { + /* skip leading "sign byte" octet 0x00 */ + len--; + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + } + /* OR octets with value */ + while (len > 1) + { + len--; + *value |= *msg_ptr; + *value <<= 8; + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + *value |= *msg_ptr; + return ERR_OK; + } + else + { + return ERR_ARG; + } + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +/** + * Decodes integer into s32_t. + * + * @param p points to a pbuf holding an ASN1 coded integer + * @param ofs points to the offset within the pbuf chain of the ASN1 coded integer + * @param len length of the coded integer field + * @param value return host order integer + * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) decode + * + * @note ASN coded integers are _always_ signed! + */ +err_t +snmp_asn1_dec_s32t(struct pbuf *p, u16_t ofs, u16_t len, s32_t *value) +{ + u16_t plen, base; + u8_t *msg_ptr; +#if BYTE_ORDER == LITTLE_ENDIAN + u8_t *lsb_ptr = (u8_t*)value; +#endif +#if BYTE_ORDER == BIG_ENDIAN + u8_t *lsb_ptr = (u8_t*)value + sizeof(s32_t) - 1; +#endif + u8_t sign; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = (u8_t*)p->payload; + msg_ptr += ofs - base; + if ((len > 0) && (len < 5)) + { + if (*msg_ptr & 0x80) + { + /* negative, start from -1 */ + *value = -1; + sign = 1; + } + else + { + /* positive, start from 0 */ + *value = 0; + sign = 0; + } + /* OR/AND octets with value */ + while (len > 1) + { + len--; + if (sign) + { + *lsb_ptr &= *msg_ptr; + *value <<= 8; + *lsb_ptr |= 255; + } + else + { + *lsb_ptr |= *msg_ptr; + *value <<= 8; + } + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + if (sign) + { + *lsb_ptr &= *msg_ptr; + } + else + { + *lsb_ptr |= *msg_ptr; + } + return ERR_OK; + } + else + { + return ERR_ARG; + } + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +/** + * Decodes object identifier from incoming message into array of s32_t. + * + * @param p points to a pbuf holding an ASN1 coded object identifier + * @param ofs points to the offset within the pbuf chain of the ASN1 coded object identifier + * @param len length of the coded object identifier + * @param oid return object identifier struct + * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) decode + */ +err_t +snmp_asn1_dec_oid(struct pbuf *p, u16_t ofs, u16_t len, struct snmp_obj_id *oid) +{ + u16_t plen, base; + u8_t *msg_ptr; + s32_t *oid_ptr; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = (u8_t*)p->payload; + msg_ptr += ofs - base; + + oid->len = 0; + oid_ptr = &oid->id[0]; + if (len > 0) + { + /* first compressed octet */ + if (*msg_ptr == 0x2B) + { + /* (most) common case 1.3 (iso.org) */ + *oid_ptr = 1; + oid_ptr++; + *oid_ptr = 3; + oid_ptr++; + } + else if (*msg_ptr < 40) + { + *oid_ptr = 0; + oid_ptr++; + *oid_ptr = *msg_ptr; + oid_ptr++; + } + else if (*msg_ptr < 80) + { + *oid_ptr = 1; + oid_ptr++; + *oid_ptr = (*msg_ptr) - 40; + oid_ptr++; + } + else + { + *oid_ptr = 2; + oid_ptr++; + *oid_ptr = (*msg_ptr) - 80; + oid_ptr++; + } + oid->len = 2; + } + else + { + /* accepting zero length identifiers e.g. for + getnext operation. uncommon but valid */ + return ERR_OK; + } + len--; + if (len > 0) + { + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + while ((len > 0) && (oid->len < LWIP_SNMP_OBJ_ID_LEN)) + { + /* sub-identifier uses multiple octets */ + if (*msg_ptr & 0x80) + { + s32_t sub_id = 0; + + while ((*msg_ptr & 0x80) && (len > 1)) + { + len--; + sub_id = (sub_id << 7) + (*msg_ptr & ~0x80); + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + if (!(*msg_ptr & 0x80) && (len > 0)) + { + /* last octet sub-identifier */ + len--; + sub_id = (sub_id << 7) + *msg_ptr; + *oid_ptr = sub_id; + } + } + else + { + /* !(*msg_ptr & 0x80) sub-identifier uses single octet */ + len--; + *oid_ptr = *msg_ptr; + } + if (len > 0) + { + /* remaining oid bytes available ... */ + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + oid_ptr++; + oid->len++; + } + if (len == 0) + { + /* len == 0, end of oid */ + return ERR_OK; + } + else + { + /* len > 0, oid->len == LWIP_SNMP_OBJ_ID_LEN or malformed encoding */ + return ERR_ARG; + } + + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +/** + * Decodes (copies) raw data (ip-addresses, octet strings, opaque encoding) + * from incoming message into array. + * + * @param p points to a pbuf holding an ASN1 coded raw data + * @param ofs points to the offset within the pbuf chain of the ASN1 coded raw data + * @param len length of the coded raw data (zero is valid, e.g. empty string!) + * @param raw_len length of the raw return value + * @param raw return raw bytes + * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) decode + */ +err_t +snmp_asn1_dec_raw(struct pbuf *p, u16_t ofs, u16_t len, u16_t raw_len, u8_t *raw) +{ + u16_t plen, base; + u8_t *msg_ptr; + + if (len > 0) + { + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = (u8_t*)p->payload; + msg_ptr += ofs - base; + if (raw_len >= len) + { + while (len > 1) + { + /* copy len - 1 octets */ + len--; + *raw = *msg_ptr; + raw++; + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + /* copy last octet */ + *raw = *msg_ptr; + return ERR_OK; + } + else + { + /* raw_len < len, not enough dst space */ + return ERR_ARG; + } + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; + } + else + { + /* len == 0, empty string */ + return ERR_OK; + } +} + +#endif /* LWIP_SNMP */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/core/snmp/asn1_enc.c b/component/common/network/lwip/lwip_v1.4.1/src/core/snmp/asn1_enc.c new file mode 100644 index 0000000..64dfc5f --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/core/snmp/asn1_enc.c @@ -0,0 +1,611 @@ +/** + * @file + * Abstract Syntax Notation One (ISO 8824, 8825) encoding + * + * @todo not optimised (yet), favor correctness over speed, favor speed over size + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * Author: Christiaan Simons + */ + +#include "lwip/opt.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/snmp_asn1.h" + +/** + * Returns octet count for length. + * + * @param length + * @param octets_needed points to the return value + */ +void +snmp_asn1_enc_length_cnt(u16_t length, u8_t *octets_needed) +{ + if (length < 0x80U) + { + *octets_needed = 1; + } + else if (length < 0x100U) + { + *octets_needed = 2; + } + else + { + *octets_needed = 3; + } +} + +/** + * Returns octet count for an u32_t. + * + * @param value + * @param octets_needed points to the return value + * + * @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded + * as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value + * of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!! + */ +void +snmp_asn1_enc_u32t_cnt(u32_t value, u16_t *octets_needed) +{ + if (value < 0x80UL) + { + *octets_needed = 1; + } + else if (value < 0x8000UL) + { + *octets_needed = 2; + } + else if (value < 0x800000UL) + { + *octets_needed = 3; + } + else if (value < 0x80000000UL) + { + *octets_needed = 4; + } + else + { + *octets_needed = 5; + } +} + +/** + * Returns octet count for an s32_t. + * + * @param value + * @param octets_needed points to the return value + * + * @note ASN coded integers are _always_ signed. + */ +void +snmp_asn1_enc_s32t_cnt(s32_t value, u16_t *octets_needed) +{ + if (value < 0) + { + value = ~value; + } + if (value < 0x80L) + { + *octets_needed = 1; + } + else if (value < 0x8000L) + { + *octets_needed = 2; + } + else if (value < 0x800000L) + { + *octets_needed = 3; + } + else + { + *octets_needed = 4; + } +} + +/** + * Returns octet count for an object identifier. + * + * @param ident_len object identifier array length + * @param ident points to object identifier array + * @param octets_needed points to the return value + */ +void +snmp_asn1_enc_oid_cnt(u8_t ident_len, s32_t *ident, u16_t *octets_needed) +{ + s32_t sub_id; + u8_t cnt; + + cnt = 0; + if (ident_len > 1) + { + /* compressed prefix in one octet */ + cnt++; + ident_len -= 2; + ident += 2; + } + while(ident_len > 0) + { + ident_len--; + sub_id = *ident; + + sub_id >>= 7; + cnt++; + while(sub_id > 0) + { + sub_id >>= 7; + cnt++; + } + ident++; + } + *octets_needed = cnt; +} + +/** + * Encodes ASN type field into a pbuf chained ASN1 msg. + * + * @param p points to output pbuf to encode value into + * @param ofs points to the offset within the pbuf chain + * @param type input ASN1 type + * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) encode + */ +err_t +snmp_asn1_enc_type(struct pbuf *p, u16_t ofs, u8_t type) +{ + u16_t plen, base; + u8_t *msg_ptr; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = (u8_t*)p->payload; + msg_ptr += ofs - base; + *msg_ptr = type; + return ERR_OK; + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +/** + * Encodes host order length field into a pbuf chained ASN1 msg. + * + * @param p points to output pbuf to encode length into + * @param ofs points to the offset within the pbuf chain + * @param length is the host order length to be encoded + * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) encode + */ +err_t +snmp_asn1_enc_length(struct pbuf *p, u16_t ofs, u16_t length) +{ + u16_t plen, base; + u8_t *msg_ptr; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = (u8_t*)p->payload; + msg_ptr += ofs - base; + + if (length < 0x80) + { + *msg_ptr = (u8_t)length; + return ERR_OK; + } + else if (length < 0x100) + { + *msg_ptr = 0x81; + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + *msg_ptr = (u8_t)length; + return ERR_OK; + } + else + { + u8_t i; + + /* length >= 0x100 && length <= 0xFFFF */ + *msg_ptr = 0x82; + i = 2; + while (i > 0) + { + i--; + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + if (i == 0) + { + /* least significant length octet */ + *msg_ptr = (u8_t)length; + } + else + { + /* most significant length octet */ + *msg_ptr = (u8_t)(length >> 8); + } + } + return ERR_OK; + } + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +/** + * Encodes u32_t (counter, gauge, timeticks) into a pbuf chained ASN1 msg. + * + * @param p points to output pbuf to encode value into + * @param ofs points to the offset within the pbuf chain + * @param octets_needed encoding length (from snmp_asn1_enc_u32t_cnt()) + * @param value is the host order u32_t value to be encoded + * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) encode + * + * @see snmp_asn1_enc_u32t_cnt() + */ +err_t +snmp_asn1_enc_u32t(struct pbuf *p, u16_t ofs, u16_t octets_needed, u32_t value) +{ + u16_t plen, base; + u8_t *msg_ptr; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = (u8_t*)p->payload; + msg_ptr += ofs - base; + + if (octets_needed == 5) + { + /* not enough bits in 'value' add leading 0x00 */ + octets_needed--; + *msg_ptr = 0x00; + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + while (octets_needed > 1) + { + octets_needed--; + *msg_ptr = (u8_t)(value >> (octets_needed << 3)); + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + /* (only) one least significant octet */ + *msg_ptr = (u8_t)value; + return ERR_OK; + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +/** + * Encodes s32_t integer into a pbuf chained ASN1 msg. + * + * @param p points to output pbuf to encode value into + * @param ofs points to the offset within the pbuf chain + * @param octets_needed encoding length (from snmp_asn1_enc_s32t_cnt()) + * @param value is the host order s32_t value to be encoded + * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) encode + * + * @see snmp_asn1_enc_s32t_cnt() + */ +err_t +snmp_asn1_enc_s32t(struct pbuf *p, u16_t ofs, u16_t octets_needed, s32_t value) +{ + u16_t plen, base; + u8_t *msg_ptr; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = (u8_t*)p->payload; + msg_ptr += ofs - base; + + while (octets_needed > 1) + { + octets_needed--; + *msg_ptr = (u8_t)(value >> (octets_needed << 3)); + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + /* (only) one least significant octet */ + *msg_ptr = (u8_t)value; + return ERR_OK; + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +/** + * Encodes object identifier into a pbuf chained ASN1 msg. + * + * @param p points to output pbuf to encode oid into + * @param ofs points to the offset within the pbuf chain + * @param ident_len object identifier array length + * @param ident points to object identifier array + * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) encode + */ +err_t +snmp_asn1_enc_oid(struct pbuf *p, u16_t ofs, u8_t ident_len, s32_t *ident) +{ + u16_t plen, base; + u8_t *msg_ptr; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = (u8_t*)p->payload; + msg_ptr += ofs - base; + + if (ident_len > 1) + { + if ((ident[0] == 1) && (ident[1] == 3)) + { + /* compressed (most common) prefix .iso.org */ + *msg_ptr = 0x2b; + } + else + { + /* calculate prefix */ + *msg_ptr = (u8_t)((ident[0] * 40) + ident[1]); + } + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + ident_len -= 2; + ident += 2; + } + else + { +/* @bug: allow empty varbinds for symmetry (we must decode them for getnext), allow partial compression?? */ + /* ident_len <= 1, at least we need zeroDotZero (0.0) (ident_len == 2) */ + return ERR_ARG; + } + while (ident_len > 0) + { + s32_t sub_id; + u8_t shift, tail; + + ident_len--; + sub_id = *ident; + tail = 0; + shift = 28; + while(shift > 0) + { + u8_t code; + + code = (u8_t)(sub_id >> shift); + if ((code != 0) || (tail != 0)) + { + tail = 1; + *msg_ptr = code | 0x80; + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + shift -= 7; + } + *msg_ptr = (u8_t)sub_id & 0x7F; + if (ident_len > 0) + { + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + /* proceed to next sub-identifier */ + ident++; + } + return ERR_OK; + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +/** + * Encodes raw data (octet string, opaque) into a pbuf chained ASN1 msg. + * + * @param p points to output pbuf to encode raw data into + * @param ofs points to the offset within the pbuf chain + * @param raw_len raw data length + * @param raw points raw data + * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) encode + */ +err_t +snmp_asn1_enc_raw(struct pbuf *p, u16_t ofs, u16_t raw_len, u8_t *raw) +{ + u16_t plen, base; + u8_t *msg_ptr; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = (u8_t*)p->payload; + msg_ptr += ofs - base; + + while (raw_len > 1) + { + /* copy raw_len - 1 octets */ + raw_len--; + *msg_ptr = *raw; + raw++; + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + if (raw_len > 0) + { + /* copy last or single octet */ + *msg_ptr = *raw; + } + return ERR_OK; + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +#endif /* LWIP_SNMP */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/core/snmp/mib2.c b/component/common/network/lwip/lwip_v1.4.1/src/core/snmp/mib2.c new file mode 100644 index 0000000..4775ba9 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/core/snmp/mib2.c @@ -0,0 +1,4146 @@ +/** + * @file + * Management Information Base II (RFC1213) objects and functions. + * + * @note the object identifiers for this MIB-2 and private MIB tree + * must be kept in sorted ascending order. This to ensure correct getnext operation. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * Author: Christiaan Simons + */ + +#include "lwip/opt.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/snmp.h" +#include "lwip/netif.h" +#include "lwip/ip.h" +#include "lwip/ip_frag.h" +#include "lwip/mem.h" +#include "lwip/tcp_impl.h" +#include "lwip/udp.h" +#include "lwip/snmp_asn1.h" +#include "lwip/snmp_structs.h" +#include "lwip/sys.h" +#include "netif/etharp.h" + +/** + * IANA assigned enterprise ID for lwIP is 26381 + * @see http://www.iana.org/assignments/enterprise-numbers + * + * @note this enterprise ID is assigned to the lwIP project, + * all object identifiers living under this ID are assigned + * by the lwIP maintainers (contact Christiaan Simons)! + * @note don't change this define, use snmp_set_sysobjid() + * + * If you need to create your own private MIB you'll need + * to apply for your own enterprise ID with IANA: + * http://www.iana.org/numbers.html + */ +#define SNMP_ENTERPRISE_ID 26381 +#define SNMP_SYSOBJID_LEN 7 +#define SNMP_SYSOBJID {1, 3, 6, 1, 4, 1, SNMP_ENTERPRISE_ID} + +#ifndef SNMP_SYSSERVICES +#define SNMP_SYSSERVICES ((1 << 6) | (1 << 3) | ((IP_FORWARD) << 2)) +#endif + +#ifndef SNMP_GET_SYSUPTIME +#define SNMP_GET_SYSUPTIME(sysuptime) (sysuptime = (sys_now() / 10)) +#endif + +static void system_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void system_get_value(struct obj_def *od, u16_t len, void *value); +static u8_t system_set_test(struct obj_def *od, u16_t len, void *value); +static void system_set_value(struct obj_def *od, u16_t len, void *value); +static void interfaces_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void interfaces_get_value(struct obj_def *od, u16_t len, void *value); +static void ifentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void ifentry_get_value(struct obj_def *od, u16_t len, void *value); +#if !SNMP_SAFE_REQUESTS +static u8_t ifentry_set_test (struct obj_def *od, u16_t len, void *value); +static void ifentry_set_value (struct obj_def *od, u16_t len, void *value); +#endif /* SNMP_SAFE_REQUESTS */ +static void atentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void atentry_get_value(struct obj_def *od, u16_t len, void *value); +static void ip_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void ip_get_value(struct obj_def *od, u16_t len, void *value); +static u8_t ip_set_test(struct obj_def *od, u16_t len, void *value); +static void ip_addrentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void ip_addrentry_get_value(struct obj_def *od, u16_t len, void *value); +static void ip_rteentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void ip_rteentry_get_value(struct obj_def *od, u16_t len, void *value); +static void ip_ntomentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void ip_ntomentry_get_value(struct obj_def *od, u16_t len, void *value); +static void icmp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void icmp_get_value(struct obj_def *od, u16_t len, void *value); +#if LWIP_TCP +static void tcp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void tcp_get_value(struct obj_def *od, u16_t len, void *value); +#ifdef THIS_SEEMS_UNUSED +static void tcpconnentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void tcpconnentry_get_value(struct obj_def *od, u16_t len, void *value); +#endif +#endif +static void udp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void udp_get_value(struct obj_def *od, u16_t len, void *value); +static void udpentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void udpentry_get_value(struct obj_def *od, u16_t len, void *value); +static void snmp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void snmp_get_value(struct obj_def *od, u16_t len, void *value); +static u8_t snmp_set_test(struct obj_def *od, u16_t len, void *value); +static void snmp_set_value(struct obj_def *od, u16_t len, void *value); + + +/* snmp .1.3.6.1.2.1.11 */ +const mib_scalar_node snmp_scalar = { + &snmp_get_object_def, + &snmp_get_value, + &snmp_set_test, + &snmp_set_value, + MIB_NODE_SC, + 0 +}; +const s32_t snmp_ids[28] = { + 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 24, 25, 26, 27, 28, 29, 30 +}; +struct mib_node* const snmp_nodes[28] = { + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar +}; +const struct mib_array_node snmp = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 28, + snmp_ids, + snmp_nodes +}; + +/* dot3 and EtherLike MIB not planned. (transmission .1.3.6.1.2.1.10) */ +/* historical (some say hysterical). (cmot .1.3.6.1.2.1.9) */ +/* lwIP has no EGP, thus may not implement it. (egp .1.3.6.1.2.1.8) */ + +/* udp .1.3.6.1.2.1.7 */ +/** index root node for udpTable */ +struct mib_list_rootnode udp_root = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_LR, + 0, + NULL, + NULL, + 0 +}; +const s32_t udpentry_ids[2] = { 1, 2 }; +struct mib_node* const udpentry_nodes[2] = { + (struct mib_node*)&udp_root, (struct mib_node*)&udp_root, +}; +const struct mib_array_node udpentry = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 2, + udpentry_ids, + udpentry_nodes +}; + +s32_t udptable_id = 1; +struct mib_node* udptable_node = (struct mib_node*)&udpentry; +struct mib_ram_array_node udptable = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_RA, + 0, + &udptable_id, + &udptable_node +}; + +const mib_scalar_node udp_scalar = { + &udp_get_object_def, + &udp_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_SC, + 0 +}; +const s32_t udp_ids[5] = { 1, 2, 3, 4, 5 }; +struct mib_node* const udp_nodes[5] = { + (struct mib_node*)&udp_scalar, (struct mib_node*)&udp_scalar, + (struct mib_node*)&udp_scalar, (struct mib_node*)&udp_scalar, + (struct mib_node*)&udptable +}; +const struct mib_array_node udp = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 5, + udp_ids, + udp_nodes +}; + +/* tcp .1.3.6.1.2.1.6 */ +#if LWIP_TCP +/* only if the TCP protocol is available may implement this group */ +/** index root node for tcpConnTable */ +struct mib_list_rootnode tcpconntree_root = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_LR, + 0, + NULL, + NULL, + 0 +}; +const s32_t tcpconnentry_ids[5] = { 1, 2, 3, 4, 5 }; +struct mib_node* const tcpconnentry_nodes[5] = { + (struct mib_node*)&tcpconntree_root, (struct mib_node*)&tcpconntree_root, + (struct mib_node*)&tcpconntree_root, (struct mib_node*)&tcpconntree_root, + (struct mib_node*)&tcpconntree_root +}; +const struct mib_array_node tcpconnentry = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 5, + tcpconnentry_ids, + tcpconnentry_nodes +}; + +s32_t tcpconntable_id = 1; +struct mib_node* tcpconntable_node = (struct mib_node*)&tcpconnentry; +struct mib_ram_array_node tcpconntable = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_RA, +/** @todo update maxlength when inserting / deleting from table + 0 when table is empty, 1 when more than one entry */ + 0, + &tcpconntable_id, + &tcpconntable_node +}; + +const mib_scalar_node tcp_scalar = { + &tcp_get_object_def, + &tcp_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_SC, + 0 +}; +const s32_t tcp_ids[15] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; +struct mib_node* const tcp_nodes[15] = { + (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar, + (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar, + (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar, + (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar, + (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar, + (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar, + (struct mib_node*)&tcpconntable, (struct mib_node*)&tcp_scalar, + (struct mib_node*)&tcp_scalar +}; +const struct mib_array_node tcp = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 15, + tcp_ids, + tcp_nodes +}; +#endif + +/* icmp .1.3.6.1.2.1.5 */ +const mib_scalar_node icmp_scalar = { + &icmp_get_object_def, + &icmp_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_SC, + 0 +}; +const s32_t icmp_ids[26] = { 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 }; +struct mib_node* const icmp_nodes[26] = { + (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, + (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, + (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, + (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, + (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, + (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, + (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, + (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, + (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, + (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, + (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, + (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, + (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar +}; +const struct mib_array_node icmp = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 26, + icmp_ids, + icmp_nodes +}; + +/** index root node for ipNetToMediaTable */ +struct mib_list_rootnode ipntomtree_root = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_LR, + 0, + NULL, + NULL, + 0 +}; +const s32_t ipntomentry_ids[4] = { 1, 2, 3, 4 }; +struct mib_node* const ipntomentry_nodes[4] = { + (struct mib_node*)&ipntomtree_root, (struct mib_node*)&ipntomtree_root, + (struct mib_node*)&ipntomtree_root, (struct mib_node*)&ipntomtree_root +}; +const struct mib_array_node ipntomentry = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 4, + ipntomentry_ids, + ipntomentry_nodes +}; + +s32_t ipntomtable_id = 1; +struct mib_node* ipntomtable_node = (struct mib_node*)&ipntomentry; +struct mib_ram_array_node ipntomtable = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_RA, + 0, + &ipntomtable_id, + &ipntomtable_node +}; + +/** index root node for ipRouteTable */ +struct mib_list_rootnode iprtetree_root = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_LR, + 0, + NULL, + NULL, + 0 +}; +const s32_t iprteentry_ids[13] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 }; +struct mib_node* const iprteentry_nodes[13] = { + (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root, + (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root, + (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root, + (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root, + (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root, + (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root, + (struct mib_node*)&iprtetree_root +}; +const struct mib_array_node iprteentry = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 13, + iprteentry_ids, + iprteentry_nodes +}; + +s32_t iprtetable_id = 1; +struct mib_node* iprtetable_node = (struct mib_node*)&iprteentry; +struct mib_ram_array_node iprtetable = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_RA, + 0, + &iprtetable_id, + &iprtetable_node +}; + +/** index root node for ipAddrTable */ +struct mib_list_rootnode ipaddrtree_root = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_LR, + 0, + NULL, + NULL, + 0 +}; +const s32_t ipaddrentry_ids[5] = { 1, 2, 3, 4, 5 }; +struct mib_node* const ipaddrentry_nodes[5] = { + (struct mib_node*)&ipaddrtree_root, + (struct mib_node*)&ipaddrtree_root, + (struct mib_node*)&ipaddrtree_root, + (struct mib_node*)&ipaddrtree_root, + (struct mib_node*)&ipaddrtree_root +}; +const struct mib_array_node ipaddrentry = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 5, + ipaddrentry_ids, + ipaddrentry_nodes +}; + +s32_t ipaddrtable_id = 1; +struct mib_node* ipaddrtable_node = (struct mib_node*)&ipaddrentry; +struct mib_ram_array_node ipaddrtable = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_RA, + 0, + &ipaddrtable_id, + &ipaddrtable_node +}; + +/* ip .1.3.6.1.2.1.4 */ +const mib_scalar_node ip_scalar = { + &ip_get_object_def, + &ip_get_value, + &ip_set_test, + &noleafs_set_value, + MIB_NODE_SC, + 0 +}; +const s32_t ip_ids[23] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23 }; +struct mib_node* const ip_nodes[23] = { + (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar, + (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar, + (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar, + (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar, + (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar, + (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar, + (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar, + (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar, + (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar, + (struct mib_node*)&ip_scalar, (struct mib_node*)&ipaddrtable, + (struct mib_node*)&iprtetable, (struct mib_node*)&ipntomtable, + (struct mib_node*)&ip_scalar +}; +const struct mib_array_node mib2_ip = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 23, + ip_ids, + ip_nodes +}; + +/** index root node for atTable */ +struct mib_list_rootnode arptree_root = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_LR, + 0, + NULL, + NULL, + 0 +}; +const s32_t atentry_ids[3] = { 1, 2, 3 }; +struct mib_node* const atentry_nodes[3] = { + (struct mib_node*)&arptree_root, + (struct mib_node*)&arptree_root, + (struct mib_node*)&arptree_root +}; +const struct mib_array_node atentry = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 3, + atentry_ids, + atentry_nodes +}; + +const s32_t attable_id = 1; +struct mib_node* const attable_node = (struct mib_node*)&atentry; +const struct mib_array_node attable = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 1, + &attable_id, + &attable_node +}; + +/* at .1.3.6.1.2.1.3 */ +s32_t at_id = 1; +struct mib_node* mib2_at_node = (struct mib_node*)&attable; +struct mib_ram_array_node at = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_RA, + 0, + &at_id, + &mib2_at_node +}; + +/** index root node for ifTable */ +struct mib_list_rootnode iflist_root = { + &ifentry_get_object_def, + &ifentry_get_value, +#if SNMP_SAFE_REQUESTS + &noleafs_set_test, + &noleafs_set_value, +#else /* SNMP_SAFE_REQUESTS */ + &ifentry_set_test, + &ifentry_set_value, +#endif /* SNMP_SAFE_REQUESTS */ + MIB_NODE_LR, + 0, + NULL, + NULL, + 0 +}; +const s32_t ifentry_ids[22] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22 }; +struct mib_node* const ifentry_nodes[22] = { + (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root, + (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root, + (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root, + (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root, + (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root, + (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root, + (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root, + (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root, + (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root, + (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root, + (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root +}; +const struct mib_array_node ifentry = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 22, + ifentry_ids, + ifentry_nodes +}; + +s32_t iftable_id = 1; +struct mib_node* iftable_node = (struct mib_node*)&ifentry; +struct mib_ram_array_node iftable = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_RA, + 0, + &iftable_id, + &iftable_node +}; + +/* interfaces .1.3.6.1.2.1.2 */ +const mib_scalar_node interfaces_scalar = { + &interfaces_get_object_def, + &interfaces_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_SC, + 0 +}; +const s32_t interfaces_ids[2] = { 1, 2 }; +struct mib_node* const interfaces_nodes[2] = { + (struct mib_node*)&interfaces_scalar, (struct mib_node*)&iftable +}; +const struct mib_array_node interfaces = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 2, + interfaces_ids, + interfaces_nodes +}; + + +/* 0 1 2 3 4 5 6 */ +/* system .1.3.6.1.2.1.1 */ +const mib_scalar_node sys_tem_scalar = { + &system_get_object_def, + &system_get_value, + &system_set_test, + &system_set_value, + MIB_NODE_SC, + 0 +}; +const s32_t sys_tem_ids[7] = { 1, 2, 3, 4, 5, 6, 7 }; +struct mib_node* const sys_tem_nodes[7] = { + (struct mib_node*)&sys_tem_scalar, (struct mib_node*)&sys_tem_scalar, + (struct mib_node*)&sys_tem_scalar, (struct mib_node*)&sys_tem_scalar, + (struct mib_node*)&sys_tem_scalar, (struct mib_node*)&sys_tem_scalar, + (struct mib_node*)&sys_tem_scalar +}; +/* work around name issue with 'sys_tem', some compiler(s?) seem to reserve 'system' */ +const struct mib_array_node sys_tem = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 7, + sys_tem_ids, + sys_tem_nodes +}; + +/* mib-2 .1.3.6.1.2.1 */ +#if LWIP_TCP +#define MIB2_GROUPS 8 +#else +#define MIB2_GROUPS 7 +#endif +const s32_t mib2_ids[MIB2_GROUPS] = +{ + 1, + 2, + 3, + 4, + 5, +#if LWIP_TCP + 6, +#endif + 7, + 11 +}; +struct mib_node* const mib2_nodes[MIB2_GROUPS] = { + (struct mib_node*)&sys_tem, + (struct mib_node*)&interfaces, + (struct mib_node*)&at, + (struct mib_node*)&mib2_ip, + (struct mib_node*)&icmp, +#if LWIP_TCP + (struct mib_node*)&tcp, +#endif + (struct mib_node*)&udp, + (struct mib_node*)&snmp +}; + +const struct mib_array_node mib2 = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + MIB2_GROUPS, + mib2_ids, + mib2_nodes +}; + +/* mgmt .1.3.6.1.2 */ +const s32_t mgmt_ids[1] = { 1 }; +struct mib_node* const mgmt_nodes[1] = { (struct mib_node*)&mib2 }; +const struct mib_array_node mgmt = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 1, + mgmt_ids, + mgmt_nodes +}; + +/* internet .1.3.6.1 */ +#if SNMP_PRIVATE_MIB +/* When using a private MIB, you have to create a file 'private_mib.h' that contains + * a 'struct mib_array_node mib_private' which contains your MIB. */ +s32_t internet_ids[2] = { 2, 4 }; +struct mib_node* const internet_nodes[2] = { (struct mib_node*)&mgmt, (struct mib_node*)&mib_private }; +const struct mib_array_node internet = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 2, + internet_ids, + internet_nodes +}; +#else +const s32_t internet_ids[1] = { 2 }; +struct mib_node* const internet_nodes[1] = { (struct mib_node*)&mgmt }; +const struct mib_array_node internet = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 1, + internet_ids, + internet_nodes +}; +#endif + +/** mib-2.system.sysObjectID */ +static struct snmp_obj_id sysobjid = {SNMP_SYSOBJID_LEN, SNMP_SYSOBJID}; +/** enterprise ID for generic TRAPs, .iso.org.dod.internet.mgmt.mib-2.snmp */ +static struct snmp_obj_id snmpgrp_id = {7,{1,3,6,1,2,1,11}}; +/** mib-2.system.sysServices */ +static const s32_t sysservices = SNMP_SYSSERVICES; + +/** mib-2.system.sysDescr */ +static const u8_t sysdescr_len_default = 4; +static const u8_t sysdescr_default[] = "lwIP"; +static u8_t* sysdescr_len_ptr = (u8_t*)&sysdescr_len_default; +static u8_t* sysdescr_ptr = (u8_t*)&sysdescr_default[0]; +/** mib-2.system.sysContact */ +static const u8_t syscontact_len_default = 0; +static const u8_t syscontact_default[] = ""; +static u8_t* syscontact_len_ptr = (u8_t*)&syscontact_len_default; +static u8_t* syscontact_ptr = (u8_t*)&syscontact_default[0]; +/** mib-2.system.sysName */ +static const u8_t sysname_len_default = 8; +static const u8_t sysname_default[] = "FQDN-unk"; +static u8_t* sysname_len_ptr = (u8_t*)&sysname_len_default; +static u8_t* sysname_ptr = (u8_t*)&sysname_default[0]; +/** mib-2.system.sysLocation */ +static const u8_t syslocation_len_default = 0; +static const u8_t syslocation_default[] = ""; +static u8_t* syslocation_len_ptr = (u8_t*)&syslocation_len_default; +static u8_t* syslocation_ptr = (u8_t*)&syslocation_default[0]; +/** mib-2.snmp.snmpEnableAuthenTraps */ +static const u8_t snmpenableauthentraps_default = 2; /* disabled */ +static u8_t* snmpenableauthentraps_ptr = (u8_t*)&snmpenableauthentraps_default; + +/** mib-2.interfaces.ifTable.ifEntry.ifSpecific (zeroDotZero) */ +static const struct snmp_obj_id ifspecific = {2, {0, 0}}; +/** mib-2.ip.ipRouteTable.ipRouteEntry.ipRouteInfo (zeroDotZero) */ +static const struct snmp_obj_id iprouteinfo = {2, {0, 0}}; + + + +/* mib-2.system counter(s) */ +static u32_t sysuptime = 0; + +/* mib-2.ip counter(s) */ +static u32_t ipinreceives = 0, + ipinhdrerrors = 0, + ipinaddrerrors = 0, + ipforwdatagrams = 0, + ipinunknownprotos = 0, + ipindiscards = 0, + ipindelivers = 0, + ipoutrequests = 0, + ipoutdiscards = 0, + ipoutnoroutes = 0, + ipreasmreqds = 0, + ipreasmoks = 0, + ipreasmfails = 0, + ipfragoks = 0, + ipfragfails = 0, + ipfragcreates = 0, + iproutingdiscards = 0; +/* mib-2.icmp counter(s) */ +static u32_t icmpinmsgs = 0, + icmpinerrors = 0, + icmpindestunreachs = 0, + icmpintimeexcds = 0, + icmpinparmprobs = 0, + icmpinsrcquenchs = 0, + icmpinredirects = 0, + icmpinechos = 0, + icmpinechoreps = 0, + icmpintimestamps = 0, + icmpintimestampreps = 0, + icmpinaddrmasks = 0, + icmpinaddrmaskreps = 0, + icmpoutmsgs = 0, + icmpouterrors = 0, + icmpoutdestunreachs = 0, + icmpouttimeexcds = 0, + icmpoutparmprobs = 0, + icmpoutsrcquenchs = 0, + icmpoutredirects = 0, + icmpoutechos = 0, + icmpoutechoreps = 0, + icmpouttimestamps = 0, + icmpouttimestampreps = 0, + icmpoutaddrmasks = 0, + icmpoutaddrmaskreps = 0; +/* mib-2.tcp counter(s) */ +static u32_t tcpactiveopens = 0, + tcppassiveopens = 0, + tcpattemptfails = 0, + tcpestabresets = 0, + tcpinsegs = 0, + tcpoutsegs = 0, + tcpretranssegs = 0, + tcpinerrs = 0, + tcpoutrsts = 0; +/* mib-2.udp counter(s) */ +static u32_t udpindatagrams = 0, + udpnoports = 0, + udpinerrors = 0, + udpoutdatagrams = 0; +/* mib-2.snmp counter(s) */ +static u32_t snmpinpkts = 0, + snmpoutpkts = 0, + snmpinbadversions = 0, + snmpinbadcommunitynames = 0, + snmpinbadcommunityuses = 0, + snmpinasnparseerrs = 0, + snmpintoobigs = 0, + snmpinnosuchnames = 0, + snmpinbadvalues = 0, + snmpinreadonlys = 0, + snmpingenerrs = 0, + snmpintotalreqvars = 0, + snmpintotalsetvars = 0, + snmpingetrequests = 0, + snmpingetnexts = 0, + snmpinsetrequests = 0, + snmpingetresponses = 0, + snmpintraps = 0, + snmpouttoobigs = 0, + snmpoutnosuchnames = 0, + snmpoutbadvalues = 0, + snmpoutgenerrs = 0, + snmpoutgetrequests = 0, + snmpoutgetnexts = 0, + snmpoutsetrequests = 0, + snmpoutgetresponses = 0, + snmpouttraps = 0; + + + +/* prototypes of the following functions are in lwip/src/include/lwip/snmp.h */ +/** + * Copy octet string. + * + * @param dst points to destination + * @param src points to source + * @param n number of octets to copy. + */ +static void ocstrncpy(u8_t *dst, u8_t *src, u16_t n) +{ + u16_t i = n; + while (i > 0) { + i--; + *dst++ = *src++; + } +} + +/** + * Copy object identifier (s32_t) array. + * + * @param dst points to destination + * @param src points to source + * @param n number of sub identifiers to copy. + */ +void objectidncpy(s32_t *dst, s32_t *src, u8_t n) +{ + u8_t i = n; + while(i > 0) { + i--; + *dst++ = *src++; + } +} + +/** + * Initializes sysDescr pointers. + * + * @param str if non-NULL then copy str pointer + * @param len points to string length, excluding zero terminator + */ +void snmp_set_sysdesr(u8_t *str, u8_t *len) +{ + if (str != NULL) + { + sysdescr_ptr = str; + sysdescr_len_ptr = len; + } +} + +void snmp_get_sysobjid_ptr(struct snmp_obj_id **oid) +{ + *oid = &sysobjid; +} + +/** + * Initializes sysObjectID value. + * + * @param oid points to stuct snmp_obj_id to copy + */ +void snmp_set_sysobjid(struct snmp_obj_id *oid) +{ + sysobjid = *oid; +} + +/** + * Must be called at regular 10 msec interval from a timer interrupt + * or signal handler depending on your runtime environment. + */ +void snmp_inc_sysuptime(void) +{ + sysuptime++; +} + +void snmp_add_sysuptime(u32_t value) +{ + sysuptime+=value; +} + +void snmp_get_sysuptime(u32_t *value) +{ + SNMP_GET_SYSUPTIME(sysuptime); + *value = sysuptime; +} + +/** + * Initializes sysContact pointers, + * e.g. ptrs to non-volatile memory external to lwIP. + * + * @param ocstr if non-NULL then copy str pointer + * @param ocstrlen points to string length, excluding zero terminator + */ +void snmp_set_syscontact(u8_t *ocstr, u8_t *ocstrlen) +{ + if (ocstr != NULL) + { + syscontact_ptr = ocstr; + syscontact_len_ptr = ocstrlen; + } +} + +/** + * Initializes sysName pointers, + * e.g. ptrs to non-volatile memory external to lwIP. + * + * @param ocstr if non-NULL then copy str pointer + * @param ocstrlen points to string length, excluding zero terminator + */ +void snmp_set_sysname(u8_t *ocstr, u8_t *ocstrlen) +{ + if (ocstr != NULL) + { + sysname_ptr = ocstr; + sysname_len_ptr = ocstrlen; + } +} + +/** + * Initializes sysLocation pointers, + * e.g. ptrs to non-volatile memory external to lwIP. + * + * @param ocstr if non-NULL then copy str pointer + * @param ocstrlen points to string length, excluding zero terminator + */ +void snmp_set_syslocation(u8_t *ocstr, u8_t *ocstrlen) +{ + if (ocstr != NULL) + { + syslocation_ptr = ocstr; + syslocation_len_ptr = ocstrlen; + } +} + + +void snmp_add_ifinoctets(struct netif *ni, u32_t value) +{ + ni->ifinoctets += value; +} + +void snmp_inc_ifinucastpkts(struct netif *ni) +{ + (ni->ifinucastpkts)++; +} + +void snmp_inc_ifinnucastpkts(struct netif *ni) +{ + (ni->ifinnucastpkts)++; +} + +void snmp_inc_ifindiscards(struct netif *ni) +{ + (ni->ifindiscards)++; +} + +void snmp_add_ifoutoctets(struct netif *ni, u32_t value) +{ + ni->ifoutoctets += value; +} + +void snmp_inc_ifoutucastpkts(struct netif *ni) +{ + (ni->ifoutucastpkts)++; +} + +void snmp_inc_ifoutnucastpkts(struct netif *ni) +{ + (ni->ifoutnucastpkts)++; +} + +void snmp_inc_ifoutdiscards(struct netif *ni) +{ + (ni->ifoutdiscards)++; +} + +void snmp_inc_iflist(void) +{ + struct mib_list_node *if_node = NULL; + + snmp_mib_node_insert(&iflist_root, iflist_root.count + 1, &if_node); + /* enable getnext traversal on filled table */ + iftable.maxlength = 1; +} + +void snmp_dec_iflist(void) +{ + snmp_mib_node_delete(&iflist_root, iflist_root.tail); + /* disable getnext traversal on empty table */ + if(iflist_root.count == 0) iftable.maxlength = 0; +} + +/** + * Inserts ARP table indexes (.xIfIndex.xNetAddress) + * into arp table index trees (both atTable and ipNetToMediaTable). + */ +void snmp_insert_arpidx_tree(struct netif *ni, ip_addr_t *ip) +{ + struct mib_list_rootnode *at_rn; + struct mib_list_node *at_node; + s32_t arpidx[5]; + u8_t level, tree; + + LWIP_ASSERT("ni != NULL", ni != NULL); + snmp_netiftoifindex(ni, &arpidx[0]); + snmp_iptooid(ip, &arpidx[1]); + + for (tree = 0; tree < 2; tree++) + { + if (tree == 0) + { + at_rn = &arptree_root; + } + else + { + at_rn = &ipntomtree_root; + } + for (level = 0; level < 5; level++) + { + at_node = NULL; + snmp_mib_node_insert(at_rn, arpidx[level], &at_node); + if ((level != 4) && (at_node != NULL)) + { + if (at_node->nptr == NULL) + { + at_rn = snmp_mib_lrn_alloc(); + at_node->nptr = (struct mib_node*)at_rn; + if (at_rn != NULL) + { + if (level == 3) + { + if (tree == 0) + { + at_rn->get_object_def = atentry_get_object_def; + at_rn->get_value = atentry_get_value; + } + else + { + at_rn->get_object_def = ip_ntomentry_get_object_def; + at_rn->get_value = ip_ntomentry_get_value; + } + at_rn->set_test = noleafs_set_test; + at_rn->set_value = noleafs_set_value; + } + } + else + { + /* at_rn == NULL, malloc failure */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_insert_arpidx_tree() insert failed, mem full")); + break; + } + } + else + { + at_rn = (struct mib_list_rootnode*)at_node->nptr; + } + } + } + } + /* enable getnext traversal on filled tables */ + at.maxlength = 1; + ipntomtable.maxlength = 1; +} + +/** + * Removes ARP table indexes (.xIfIndex.xNetAddress) + * from arp table index trees. + */ +void snmp_delete_arpidx_tree(struct netif *ni, ip_addr_t *ip) +{ + struct mib_list_rootnode *at_rn, *next, *del_rn[5]; + struct mib_list_node *at_n, *del_n[5]; + s32_t arpidx[5]; + u8_t fc, tree, level, del_cnt; + + snmp_netiftoifindex(ni, &arpidx[0]); + snmp_iptooid(ip, &arpidx[1]); + + for (tree = 0; tree < 2; tree++) + { + /* mark nodes for deletion */ + if (tree == 0) + { + at_rn = &arptree_root; + } + else + { + at_rn = &ipntomtree_root; + } + level = 0; + del_cnt = 0; + while ((level < 5) && (at_rn != NULL)) + { + fc = snmp_mib_node_find(at_rn, arpidx[level], &at_n); + if (fc == 0) + { + /* arpidx[level] does not exist */ + del_cnt = 0; + at_rn = NULL; + } + else if (fc == 1) + { + del_rn[del_cnt] = at_rn; + del_n[del_cnt] = at_n; + del_cnt++; + at_rn = (struct mib_list_rootnode*)(at_n->nptr); + } + else if (fc == 2) + { + /* reset delete (2 or more childs) */ + del_cnt = 0; + at_rn = (struct mib_list_rootnode*)(at_n->nptr); + } + level++; + } + /* delete marked index nodes */ + while (del_cnt > 0) + { + del_cnt--; + + at_rn = del_rn[del_cnt]; + at_n = del_n[del_cnt]; + + next = snmp_mib_node_delete(at_rn, at_n); + if (next != NULL) + { + LWIP_ASSERT("next_count == 0",next->count == 0); + snmp_mib_lrn_free(next); + } + } + } + /* disable getnext traversal on empty tables */ + if(arptree_root.count == 0) at.maxlength = 0; + if(ipntomtree_root.count == 0) ipntomtable.maxlength = 0; +} + +void snmp_inc_ipinreceives(void) +{ + ipinreceives++; +} + +void snmp_inc_ipinhdrerrors(void) +{ + ipinhdrerrors++; +} + +void snmp_inc_ipinaddrerrors(void) +{ + ipinaddrerrors++; +} + +void snmp_inc_ipforwdatagrams(void) +{ + ipforwdatagrams++; +} + +void snmp_inc_ipinunknownprotos(void) +{ + ipinunknownprotos++; +} + +void snmp_inc_ipindiscards(void) +{ + ipindiscards++; +} + +void snmp_inc_ipindelivers(void) +{ + ipindelivers++; +} + +void snmp_inc_ipoutrequests(void) +{ + ipoutrequests++; +} + +void snmp_inc_ipoutdiscards(void) +{ + ipoutdiscards++; +} + +void snmp_inc_ipoutnoroutes(void) +{ + ipoutnoroutes++; +} + +void snmp_inc_ipreasmreqds(void) +{ + ipreasmreqds++; +} + +void snmp_inc_ipreasmoks(void) +{ + ipreasmoks++; +} + +void snmp_inc_ipreasmfails(void) +{ + ipreasmfails++; +} + +void snmp_inc_ipfragoks(void) +{ + ipfragoks++; +} + +void snmp_inc_ipfragfails(void) +{ + ipfragfails++; +} + +void snmp_inc_ipfragcreates(void) +{ + ipfragcreates++; +} + +void snmp_inc_iproutingdiscards(void) +{ + iproutingdiscards++; +} + +/** + * Inserts ipAddrTable indexes (.ipAdEntAddr) + * into index tree. + */ +void snmp_insert_ipaddridx_tree(struct netif *ni) +{ + struct mib_list_rootnode *ipa_rn; + struct mib_list_node *ipa_node; + s32_t ipaddridx[4]; + u8_t level; + + LWIP_ASSERT("ni != NULL", ni != NULL); + snmp_iptooid(&ni->ip_addr, &ipaddridx[0]); + + level = 0; + ipa_rn = &ipaddrtree_root; + while (level < 4) + { + ipa_node = NULL; + snmp_mib_node_insert(ipa_rn, ipaddridx[level], &ipa_node); + if ((level != 3) && (ipa_node != NULL)) + { + if (ipa_node->nptr == NULL) + { + ipa_rn = snmp_mib_lrn_alloc(); + ipa_node->nptr = (struct mib_node*)ipa_rn; + if (ipa_rn != NULL) + { + if (level == 2) + { + ipa_rn->get_object_def = ip_addrentry_get_object_def; + ipa_rn->get_value = ip_addrentry_get_value; + ipa_rn->set_test = noleafs_set_test; + ipa_rn->set_value = noleafs_set_value; + } + } + else + { + /* ipa_rn == NULL, malloc failure */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_insert_ipaddridx_tree() insert failed, mem full")); + break; + } + } + else + { + ipa_rn = (struct mib_list_rootnode*)ipa_node->nptr; + } + } + level++; + } + /* enable getnext traversal on filled table */ + ipaddrtable.maxlength = 1; +} + +/** + * Removes ipAddrTable indexes (.ipAdEntAddr) + * from index tree. + */ +void snmp_delete_ipaddridx_tree(struct netif *ni) +{ + struct mib_list_rootnode *ipa_rn, *next, *del_rn[4]; + struct mib_list_node *ipa_n, *del_n[4]; + s32_t ipaddridx[4]; + u8_t fc, level, del_cnt; + + LWIP_ASSERT("ni != NULL", ni != NULL); + snmp_iptooid(&ni->ip_addr, &ipaddridx[0]); + + /* mark nodes for deletion */ + level = 0; + del_cnt = 0; + ipa_rn = &ipaddrtree_root; + while ((level < 4) && (ipa_rn != NULL)) + { + fc = snmp_mib_node_find(ipa_rn, ipaddridx[level], &ipa_n); + if (fc == 0) + { + /* ipaddridx[level] does not exist */ + del_cnt = 0; + ipa_rn = NULL; + } + else if (fc == 1) + { + del_rn[del_cnt] = ipa_rn; + del_n[del_cnt] = ipa_n; + del_cnt++; + ipa_rn = (struct mib_list_rootnode*)(ipa_n->nptr); + } + else if (fc == 2) + { + /* reset delete (2 or more childs) */ + del_cnt = 0; + ipa_rn = (struct mib_list_rootnode*)(ipa_n->nptr); + } + level++; + } + /* delete marked index nodes */ + while (del_cnt > 0) + { + del_cnt--; + + ipa_rn = del_rn[del_cnt]; + ipa_n = del_n[del_cnt]; + + next = snmp_mib_node_delete(ipa_rn, ipa_n); + if (next != NULL) + { + LWIP_ASSERT("next_count == 0",next->count == 0); + snmp_mib_lrn_free(next); + } + } + /* disable getnext traversal on empty table */ + if (ipaddrtree_root.count == 0) ipaddrtable.maxlength = 0; +} + +/** + * Inserts ipRouteTable indexes (.ipRouteDest) + * into index tree. + * + * @param dflt non-zero for the default rte, zero for network rte + * @param ni points to network interface for this rte + * + * @todo record sysuptime for _this_ route when it is installed + * (needed for ipRouteAge) in the netif. + */ +void snmp_insert_iprteidx_tree(u8_t dflt, struct netif *ni) +{ + u8_t insert = 0; + ip_addr_t dst; + + if (dflt != 0) + { + /* the default route 0.0.0.0 */ + ip_addr_set_any(&dst); + insert = 1; + } + else + { + /* route to the network address */ + ip_addr_get_network(&dst, &ni->ip_addr, &ni->netmask); + /* exclude 0.0.0.0 network (reserved for default rte) */ + if (!ip_addr_isany(&dst)) { + insert = 1; + } + } + if (insert) + { + struct mib_list_rootnode *iprte_rn; + struct mib_list_node *iprte_node; + s32_t iprteidx[4]; + u8_t level; + + snmp_iptooid(&dst, &iprteidx[0]); + level = 0; + iprte_rn = &iprtetree_root; + while (level < 4) + { + iprte_node = NULL; + snmp_mib_node_insert(iprte_rn, iprteidx[level], &iprte_node); + if ((level != 3) && (iprte_node != NULL)) + { + if (iprte_node->nptr == NULL) + { + iprte_rn = snmp_mib_lrn_alloc(); + iprte_node->nptr = (struct mib_node*)iprte_rn; + if (iprte_rn != NULL) + { + if (level == 2) + { + iprte_rn->get_object_def = ip_rteentry_get_object_def; + iprte_rn->get_value = ip_rteentry_get_value; + iprte_rn->set_test = noleafs_set_test; + iprte_rn->set_value = noleafs_set_value; + } + } + else + { + /* iprte_rn == NULL, malloc failure */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_insert_iprteidx_tree() insert failed, mem full")); + break; + } + } + else + { + iprte_rn = (struct mib_list_rootnode*)iprte_node->nptr; + } + } + level++; + } + } + /* enable getnext traversal on filled table */ + iprtetable.maxlength = 1; +} + +/** + * Removes ipRouteTable indexes (.ipRouteDest) + * from index tree. + * + * @param dflt non-zero for the default rte, zero for network rte + * @param ni points to network interface for this rte or NULL + * for default route to be removed. + */ +void snmp_delete_iprteidx_tree(u8_t dflt, struct netif *ni) +{ + u8_t del = 0; + ip_addr_t dst; + + if (dflt != 0) + { + /* the default route 0.0.0.0 */ + ip_addr_set_any(&dst); + del = 1; + } + else + { + /* route to the network address */ + ip_addr_get_network(&dst, &ni->ip_addr, &ni->netmask); + /* exclude 0.0.0.0 network (reserved for default rte) */ + if (!ip_addr_isany(&dst)) { + del = 1; + } + } + if (del) + { + struct mib_list_rootnode *iprte_rn, *next, *del_rn[4]; + struct mib_list_node *iprte_n, *del_n[4]; + s32_t iprteidx[4]; + u8_t fc, level, del_cnt; + + snmp_iptooid(&dst, &iprteidx[0]); + /* mark nodes for deletion */ + level = 0; + del_cnt = 0; + iprte_rn = &iprtetree_root; + while ((level < 4) && (iprte_rn != NULL)) + { + fc = snmp_mib_node_find(iprte_rn, iprteidx[level], &iprte_n); + if (fc == 0) + { + /* iprteidx[level] does not exist */ + del_cnt = 0; + iprte_rn = NULL; + } + else if (fc == 1) + { + del_rn[del_cnt] = iprte_rn; + del_n[del_cnt] = iprte_n; + del_cnt++; + iprte_rn = (struct mib_list_rootnode*)(iprte_n->nptr); + } + else if (fc == 2) + { + /* reset delete (2 or more childs) */ + del_cnt = 0; + iprte_rn = (struct mib_list_rootnode*)(iprte_n->nptr); + } + level++; + } + /* delete marked index nodes */ + while (del_cnt > 0) + { + del_cnt--; + + iprte_rn = del_rn[del_cnt]; + iprte_n = del_n[del_cnt]; + + next = snmp_mib_node_delete(iprte_rn, iprte_n); + if (next != NULL) + { + LWIP_ASSERT("next_count == 0",next->count == 0); + snmp_mib_lrn_free(next); + } + } + } + /* disable getnext traversal on empty table */ + if (iprtetree_root.count == 0) iprtetable.maxlength = 0; +} + + +void snmp_inc_icmpinmsgs(void) +{ + icmpinmsgs++; +} + +void snmp_inc_icmpinerrors(void) +{ + icmpinerrors++; +} + +void snmp_inc_icmpindestunreachs(void) +{ + icmpindestunreachs++; +} + +void snmp_inc_icmpintimeexcds(void) +{ + icmpintimeexcds++; +} + +void snmp_inc_icmpinparmprobs(void) +{ + icmpinparmprobs++; +} + +void snmp_inc_icmpinsrcquenchs(void) +{ + icmpinsrcquenchs++; +} + +void snmp_inc_icmpinredirects(void) +{ + icmpinredirects++; +} + +void snmp_inc_icmpinechos(void) +{ + icmpinechos++; +} + +void snmp_inc_icmpinechoreps(void) +{ + icmpinechoreps++; +} + +void snmp_inc_icmpintimestamps(void) +{ + icmpintimestamps++; +} + +void snmp_inc_icmpintimestampreps(void) +{ + icmpintimestampreps++; +} + +void snmp_inc_icmpinaddrmasks(void) +{ + icmpinaddrmasks++; +} + +void snmp_inc_icmpinaddrmaskreps(void) +{ + icmpinaddrmaskreps++; +} + +void snmp_inc_icmpoutmsgs(void) +{ + icmpoutmsgs++; +} + +void snmp_inc_icmpouterrors(void) +{ + icmpouterrors++; +} + +void snmp_inc_icmpoutdestunreachs(void) +{ + icmpoutdestunreachs++; +} + +void snmp_inc_icmpouttimeexcds(void) +{ + icmpouttimeexcds++; +} + +void snmp_inc_icmpoutparmprobs(void) +{ + icmpoutparmprobs++; +} + +void snmp_inc_icmpoutsrcquenchs(void) +{ + icmpoutsrcquenchs++; +} + +void snmp_inc_icmpoutredirects(void) +{ + icmpoutredirects++; +} + +void snmp_inc_icmpoutechos(void) +{ + icmpoutechos++; +} + +void snmp_inc_icmpoutechoreps(void) +{ + icmpoutechoreps++; +} + +void snmp_inc_icmpouttimestamps(void) +{ + icmpouttimestamps++; +} + +void snmp_inc_icmpouttimestampreps(void) +{ + icmpouttimestampreps++; +} + +void snmp_inc_icmpoutaddrmasks(void) +{ + icmpoutaddrmasks++; +} + +void snmp_inc_icmpoutaddrmaskreps(void) +{ + icmpoutaddrmaskreps++; +} + +void snmp_inc_tcpactiveopens(void) +{ + tcpactiveopens++; +} + +void snmp_inc_tcppassiveopens(void) +{ + tcppassiveopens++; +} + +void snmp_inc_tcpattemptfails(void) +{ + tcpattemptfails++; +} + +void snmp_inc_tcpestabresets(void) +{ + tcpestabresets++; +} + +void snmp_inc_tcpinsegs(void) +{ + tcpinsegs++; +} + +void snmp_inc_tcpoutsegs(void) +{ + tcpoutsegs++; +} + +void snmp_inc_tcpretranssegs(void) +{ + tcpretranssegs++; +} + +void snmp_inc_tcpinerrs(void) +{ + tcpinerrs++; +} + +void snmp_inc_tcpoutrsts(void) +{ + tcpoutrsts++; +} + +void snmp_inc_udpindatagrams(void) +{ + udpindatagrams++; +} + +void snmp_inc_udpnoports(void) +{ + udpnoports++; +} + +void snmp_inc_udpinerrors(void) +{ + udpinerrors++; +} + +void snmp_inc_udpoutdatagrams(void) +{ + udpoutdatagrams++; +} + +/** + * Inserts udpTable indexes (.udpLocalAddress.udpLocalPort) + * into index tree. + */ +void snmp_insert_udpidx_tree(struct udp_pcb *pcb) +{ + struct mib_list_rootnode *udp_rn; + struct mib_list_node *udp_node; + s32_t udpidx[5]; + u8_t level; + + LWIP_ASSERT("pcb != NULL", pcb != NULL); + snmp_iptooid(&pcb->local_ip, &udpidx[0]); + udpidx[4] = pcb->local_port; + + udp_rn = &udp_root; + for (level = 0; level < 5; level++) + { + udp_node = NULL; + snmp_mib_node_insert(udp_rn, udpidx[level], &udp_node); + if ((level != 4) && (udp_node != NULL)) + { + if (udp_node->nptr == NULL) + { + udp_rn = snmp_mib_lrn_alloc(); + udp_node->nptr = (struct mib_node*)udp_rn; + if (udp_rn != NULL) + { + if (level == 3) + { + udp_rn->get_object_def = udpentry_get_object_def; + udp_rn->get_value = udpentry_get_value; + udp_rn->set_test = noleafs_set_test; + udp_rn->set_value = noleafs_set_value; + } + } + else + { + /* udp_rn == NULL, malloc failure */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_insert_udpidx_tree() insert failed, mem full")); + break; + } + } + else + { + udp_rn = (struct mib_list_rootnode*)udp_node->nptr; + } + } + } + udptable.maxlength = 1; +} + +/** + * Removes udpTable indexes (.udpLocalAddress.udpLocalPort) + * from index tree. + */ +void snmp_delete_udpidx_tree(struct udp_pcb *pcb) +{ + struct udp_pcb *npcb; + struct mib_list_rootnode *udp_rn, *next, *del_rn[5]; + struct mib_list_node *udp_n, *del_n[5]; + s32_t udpidx[5]; + u8_t bindings, fc, level, del_cnt; + + LWIP_ASSERT("pcb != NULL", pcb != NULL); + snmp_iptooid(&pcb->local_ip, &udpidx[0]); + udpidx[4] = pcb->local_port; + + /* count PCBs for a given binding + (e.g. when reusing ports or for temp output PCBs) */ + bindings = 0; + npcb = udp_pcbs; + while ((npcb != NULL)) + { + if (ip_addr_cmp(&npcb->local_ip, &pcb->local_ip) && + (npcb->local_port == udpidx[4])) + { + bindings++; + } + npcb = npcb->next; + } + if (bindings == 1) + { + /* selectively remove */ + /* mark nodes for deletion */ + level = 0; + del_cnt = 0; + udp_rn = &udp_root; + while ((level < 5) && (udp_rn != NULL)) + { + fc = snmp_mib_node_find(udp_rn, udpidx[level], &udp_n); + if (fc == 0) + { + /* udpidx[level] does not exist */ + del_cnt = 0; + udp_rn = NULL; + } + else if (fc == 1) + { + del_rn[del_cnt] = udp_rn; + del_n[del_cnt] = udp_n; + del_cnt++; + udp_rn = (struct mib_list_rootnode*)(udp_n->nptr); + } + else if (fc == 2) + { + /* reset delete (2 or more childs) */ + del_cnt = 0; + udp_rn = (struct mib_list_rootnode*)(udp_n->nptr); + } + level++; + } + /* delete marked index nodes */ + while (del_cnt > 0) + { + del_cnt--; + + udp_rn = del_rn[del_cnt]; + udp_n = del_n[del_cnt]; + + next = snmp_mib_node_delete(udp_rn, udp_n); + if (next != NULL) + { + LWIP_ASSERT("next_count == 0",next->count == 0); + snmp_mib_lrn_free(next); + } + } + } + /* disable getnext traversal on empty table */ + if (udp_root.count == 0) udptable.maxlength = 0; +} + + +void snmp_inc_snmpinpkts(void) +{ + snmpinpkts++; +} + +void snmp_inc_snmpoutpkts(void) +{ + snmpoutpkts++; +} + +void snmp_inc_snmpinbadversions(void) +{ + snmpinbadversions++; +} + +void snmp_inc_snmpinbadcommunitynames(void) +{ + snmpinbadcommunitynames++; +} + +void snmp_inc_snmpinbadcommunityuses(void) +{ + snmpinbadcommunityuses++; +} + +void snmp_inc_snmpinasnparseerrs(void) +{ + snmpinasnparseerrs++; +} + +void snmp_inc_snmpintoobigs(void) +{ + snmpintoobigs++; +} + +void snmp_inc_snmpinnosuchnames(void) +{ + snmpinnosuchnames++; +} + +void snmp_inc_snmpinbadvalues(void) +{ + snmpinbadvalues++; +} + +void snmp_inc_snmpinreadonlys(void) +{ + snmpinreadonlys++; +} + +void snmp_inc_snmpingenerrs(void) +{ + snmpingenerrs++; +} + +void snmp_add_snmpintotalreqvars(u8_t value) +{ + snmpintotalreqvars += value; +} + +void snmp_add_snmpintotalsetvars(u8_t value) +{ + snmpintotalsetvars += value; +} + +void snmp_inc_snmpingetrequests(void) +{ + snmpingetrequests++; +} + +void snmp_inc_snmpingetnexts(void) +{ + snmpingetnexts++; +} + +void snmp_inc_snmpinsetrequests(void) +{ + snmpinsetrequests++; +} + +void snmp_inc_snmpingetresponses(void) +{ + snmpingetresponses++; +} + +void snmp_inc_snmpintraps(void) +{ + snmpintraps++; +} + +void snmp_inc_snmpouttoobigs(void) +{ + snmpouttoobigs++; +} + +void snmp_inc_snmpoutnosuchnames(void) +{ + snmpoutnosuchnames++; +} + +void snmp_inc_snmpoutbadvalues(void) +{ + snmpoutbadvalues++; +} + +void snmp_inc_snmpoutgenerrs(void) +{ + snmpoutgenerrs++; +} + +void snmp_inc_snmpoutgetrequests(void) +{ + snmpoutgetrequests++; +} + +void snmp_inc_snmpoutgetnexts(void) +{ + snmpoutgetnexts++; +} + +void snmp_inc_snmpoutsetrequests(void) +{ + snmpoutsetrequests++; +} + +void snmp_inc_snmpoutgetresponses(void) +{ + snmpoutgetresponses++; +} + +void snmp_inc_snmpouttraps(void) +{ + snmpouttraps++; +} + +void snmp_get_snmpgrpid_ptr(struct snmp_obj_id **oid) +{ + *oid = &snmpgrp_id; +} + +void snmp_set_snmpenableauthentraps(u8_t *value) +{ + if (value != NULL) + { + snmpenableauthentraps_ptr = value; + } +} + +void snmp_get_snmpenableauthentraps(u8_t *value) +{ + *value = *snmpenableauthentraps_ptr; +} + +void +noleafs_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + LWIP_UNUSED_ARG(ident_len); + LWIP_UNUSED_ARG(ident); + od->instance = MIB_OBJECT_NONE; +} + +void +noleafs_get_value(struct obj_def *od, u16_t len, void *value) +{ + LWIP_UNUSED_ARG(od); + LWIP_UNUSED_ARG(len); + LWIP_UNUSED_ARG(value); +} + +u8_t +noleafs_set_test(struct obj_def *od, u16_t len, void *value) +{ + LWIP_UNUSED_ARG(od); + LWIP_UNUSED_ARG(len); + LWIP_UNUSED_ARG(value); + /* can't set */ + return 0; +} + +void +noleafs_set_value(struct obj_def *od, u16_t len, void *value) +{ + LWIP_UNUSED_ARG(od); + LWIP_UNUSED_ARG(len); + LWIP_UNUSED_ARG(value); +} + + +/** + * Returns systems object definitions. + * + * @param ident_len the address length (2) + * @param ident points to objectname.0 (object id trailer) + * @param od points to object definition. + */ +static void +system_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + u8_t id; + + /* return to object name, adding index depth (1) */ + ident_len += 1; + ident -= 1; + if (ident_len == 2) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff)); + id = (u8_t)ident[0]; + LWIP_DEBUGF(SNMP_MIB_DEBUG,("get_object_def system.%"U16_F".0\n",(u16_t)id)); + switch (id) + { + case 1: /* sysDescr */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); + od->v_len = *sysdescr_len_ptr; + break; + case 2: /* sysObjectID */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID); + od->v_len = sysobjid.len * sizeof(s32_t); + break; + case 3: /* sysUpTime */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS); + od->v_len = sizeof(u32_t); + break; + case 4: /* sysContact */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); + od->v_len = *syscontact_len_ptr; + break; + case 5: /* sysName */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); + od->v_len = *sysname_len_ptr; + break; + case 6: /* sysLocation */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); + od->v_len = *syslocation_len_ptr; + break; + case 7: /* sysServices */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + }; + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +/** + * Returns system object value. + * + * @param ident_len the address length (2) + * @param ident points to objectname.0 (object id trailer) + * @param len return value space (in bytes) + * @param value points to (varbind) space to copy value into. + */ +static void +system_get_value(struct obj_def *od, u16_t len, void *value) +{ + u8_t id; + + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 1: /* sysDescr */ + ocstrncpy((u8_t*)value, sysdescr_ptr, len); + break; + case 2: /* sysObjectID */ + objectidncpy((s32_t*)value, (s32_t*)sysobjid.id, (u8_t)(len / sizeof(s32_t))); + break; + case 3: /* sysUpTime */ + { + snmp_get_sysuptime((u32_t*)value); + } + break; + case 4: /* sysContact */ + ocstrncpy((u8_t*)value, syscontact_ptr, len); + break; + case 5: /* sysName */ + ocstrncpy((u8_t*)value, sysname_ptr, len); + break; + case 6: /* sysLocation */ + ocstrncpy((u8_t*)value, syslocation_ptr, len); + break; + case 7: /* sysServices */ + { + s32_t *sint_ptr = (s32_t*)value; + *sint_ptr = sysservices; + } + break; + }; +} + +static u8_t +system_set_test(struct obj_def *od, u16_t len, void *value) +{ + u8_t id, set_ok; + + LWIP_UNUSED_ARG(value); + set_ok = 0; + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 4: /* sysContact */ + if ((syscontact_ptr != syscontact_default) && + (len <= 255)) + { + set_ok = 1; + } + break; + case 5: /* sysName */ + if ((sysname_ptr != sysname_default) && + (len <= 255)) + { + set_ok = 1; + } + break; + case 6: /* sysLocation */ + if ((syslocation_ptr != syslocation_default) && + (len <= 255)) + { + set_ok = 1; + } + break; + }; + return set_ok; +} + +static void +system_set_value(struct obj_def *od, u16_t len, void *value) +{ + u8_t id; + + LWIP_ASSERT("invalid len", len <= 0xff); + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 4: /* sysContact */ + ocstrncpy(syscontact_ptr, (u8_t*)value, len); + *syscontact_len_ptr = (u8_t)len; + break; + case 5: /* sysName */ + ocstrncpy(sysname_ptr, (u8_t*)value, len); + *sysname_len_ptr = (u8_t)len; + break; + case 6: /* sysLocation */ + ocstrncpy(syslocation_ptr, (u8_t*)value, len); + *syslocation_len_ptr = (u8_t)len; + break; + }; +} + +/** + * Returns interfaces.ifnumber object definition. + * + * @param ident_len the address length (2) + * @param ident points to objectname.index + * @param od points to object definition. + */ +static void +interfaces_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + /* return to object name, adding index depth (1) */ + ident_len += 1; + ident -= 1; + if (ident_len == 2) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("interfaces_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +/** + * Returns interfaces.ifnumber object value. + * + * @param ident_len the address length (2) + * @param ident points to objectname.0 (object id trailer) + * @param len return value space (in bytes) + * @param value points to (varbind) space to copy value into. + */ +static void +interfaces_get_value(struct obj_def *od, u16_t len, void *value) +{ + LWIP_UNUSED_ARG(len); + if (od->id_inst_ptr[0] == 1) + { + s32_t *sint_ptr = (s32_t*)value; + *sint_ptr = iflist_root.count; + } +} + +/** + * Returns ifentry object definitions. + * + * @param ident_len the address length (2) + * @param ident points to objectname.index + * @param od points to object definition. + */ +static void +ifentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + u8_t id; + + /* return to object name, adding index depth (1) */ + ident_len += 1; + ident -= 1; + if (ident_len == 2) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff)); + id = (u8_t)ident[0]; + LWIP_DEBUGF(SNMP_MIB_DEBUG,("get_object_def ifentry.%"U16_F"\n",(u16_t)id)); + switch (id) + { + case 1: /* ifIndex */ + case 3: /* ifType */ + case 4: /* ifMtu */ + case 8: /* ifOperStatus */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + case 2: /* ifDescr */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); + /** @todo this should be some sort of sizeof(struct netif.name) */ + od->v_len = 2; + break; + case 5: /* ifSpeed */ + case 21: /* ifOutQLen */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE); + od->v_len = sizeof(u32_t); + break; + case 6: /* ifPhysAddress */ + { + struct netif *netif; + + snmp_ifindextonetif(ident[1], &netif); + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); + od->v_len = netif->hwaddr_len; + } + break; + case 7: /* ifAdminStatus */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + case 9: /* ifLastChange */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS); + od->v_len = sizeof(u32_t); + break; + case 10: /* ifInOctets */ + case 11: /* ifInUcastPkts */ + case 12: /* ifInNUcastPkts */ + case 13: /* ifInDiscarts */ + case 14: /* ifInErrors */ + case 15: /* ifInUnkownProtos */ + case 16: /* ifOutOctets */ + case 17: /* ifOutUcastPkts */ + case 18: /* ifOutNUcastPkts */ + case 19: /* ifOutDiscarts */ + case 20: /* ifOutErrors */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER); + od->v_len = sizeof(u32_t); + break; + case 22: /* ifSpecific */ + /** @note returning zeroDotZero (0.0) no media specific MIB support */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID); + od->v_len = ifspecific.len * sizeof(s32_t); + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ifentry_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + }; + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ifentry_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +/** + * Returns ifentry object value. + * + * @param ident_len the address length (2) + * @param ident points to objectname.0 (object id trailer) + * @param len return value space (in bytes) + * @param value points to (varbind) space to copy value into. + */ +static void +ifentry_get_value(struct obj_def *od, u16_t len, void *value) +{ + struct netif *netif; + u8_t id; + + snmp_ifindextonetif(od->id_inst_ptr[1], &netif); + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 1: /* ifIndex */ + { + s32_t *sint_ptr = (s32_t*)value; + *sint_ptr = od->id_inst_ptr[1]; + } + break; + case 2: /* ifDescr */ + ocstrncpy((u8_t*)value, (u8_t*)netif->name, len); + break; + case 3: /* ifType */ + { + s32_t *sint_ptr = (s32_t*)value; + *sint_ptr = netif->link_type; + } + break; + case 4: /* ifMtu */ + { + s32_t *sint_ptr = (s32_t*)value; + *sint_ptr = netif->mtu; + } + break; + case 5: /* ifSpeed */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = netif->link_speed; + } + break; + case 6: /* ifPhysAddress */ + ocstrncpy((u8_t*)value, netif->hwaddr, len); + break; + case 7: /* ifAdminStatus */ + { + s32_t *sint_ptr = (s32_t*)value; + if (netif_is_up(netif)) + { + if (netif_is_link_up(netif)) + { + *sint_ptr = 1; /* up */ + } + else + { + *sint_ptr = 7; /* lowerLayerDown */ + } + } + else + { + *sint_ptr = 2; /* down */ + } + } + break; + case 8: /* ifOperStatus */ + { + s32_t *sint_ptr = (s32_t*)value; + if (netif_is_up(netif)) + { + *sint_ptr = 1; + } + else + { + *sint_ptr = 2; + } + } + break; + case 9: /* ifLastChange */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = netif->ts; + } + break; + case 10: /* ifInOctets */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = netif->ifinoctets; + } + break; + case 11: /* ifInUcastPkts */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = netif->ifinucastpkts; + } + break; + case 12: /* ifInNUcastPkts */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = netif->ifinnucastpkts; + } + break; + case 13: /* ifInDiscarts */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = netif->ifindiscards; + } + break; + case 14: /* ifInErrors */ + case 15: /* ifInUnkownProtos */ + /** @todo add these counters! */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = 0; + } + break; + case 16: /* ifOutOctets */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = netif->ifoutoctets; + } + break; + case 17: /* ifOutUcastPkts */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = netif->ifoutucastpkts; + } + break; + case 18: /* ifOutNUcastPkts */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = netif->ifoutnucastpkts; + } + break; + case 19: /* ifOutDiscarts */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = netif->ifoutdiscards; + } + break; + case 20: /* ifOutErrors */ + /** @todo add this counter! */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = 0; + } + break; + case 21: /* ifOutQLen */ + /** @todo figure out if this must be 0 (no queue) or 1? */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = 0; + } + break; + case 22: /* ifSpecific */ + objectidncpy((s32_t*)value, (s32_t*)ifspecific.id, (u8_t)(len / sizeof(s32_t))); + break; + }; +} + +#if !SNMP_SAFE_REQUESTS +static u8_t +ifentry_set_test(struct obj_def *od, u16_t len, void *value) +{ + struct netif *netif; + u8_t id, set_ok; + LWIP_UNUSED_ARG(len); + + set_ok = 0; + snmp_ifindextonetif(od->id_inst_ptr[1], &netif); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 7: /* ifAdminStatus */ + { + s32_t *sint_ptr = (s32_t*)value; + if (*sint_ptr == 1 || *sint_ptr == 2) + set_ok = 1; + } + break; + } + return set_ok; +} + +static void +ifentry_set_value(struct obj_def *od, u16_t len, void *value) +{ + struct netif *netif; + u8_t id; + LWIP_UNUSED_ARG(len); + + snmp_ifindextonetif(od->id_inst_ptr[1], &netif); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 7: /* ifAdminStatus */ + { + s32_t *sint_ptr = (s32_t*)value; + if (*sint_ptr == 1) + { + netif_set_up(netif); + } + else if (*sint_ptr == 2) + { + netif_set_down(netif); + } + } + break; + } +} +#endif /* SNMP_SAFE_REQUESTS */ + +/** + * Returns atentry object definitions. + * + * @param ident_len the address length (6) + * @param ident points to objectname.atifindex.atnetaddress + * @param od points to object definition. + */ +static void +atentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + /* return to object name, adding index depth (5) */ + ident_len += 5; + ident -= 5; + + if (ident_len == 6) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + switch (ident[0]) + { + case 1: /* atIfIndex */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + case 2: /* atPhysAddress */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); + od->v_len = 6; /** @todo try to use netif::hwaddr_len */ + break; + case 3: /* atNetAddress */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR); + od->v_len = 4; + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("atentry_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + } + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("atentry_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +atentry_get_value(struct obj_def *od, u16_t len, void *value) +{ +#if LWIP_ARP + u8_t id; + struct eth_addr* ethaddr_ret; + ip_addr_t* ipaddr_ret; +#endif /* LWIP_ARP */ + ip_addr_t ip; + struct netif *netif; + + LWIP_UNUSED_ARG(len); + LWIP_UNUSED_ARG(value);/* if !LWIP_ARP */ + + snmp_ifindextonetif(od->id_inst_ptr[1], &netif); + snmp_oidtoip(&od->id_inst_ptr[2], &ip); + +#if LWIP_ARP /** @todo implement a netif_find_addr */ + if (etharp_find_addr(netif, &ip, ðaddr_ret, &ipaddr_ret) > -1) + { + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 1: /* atIfIndex */ + { + s32_t *sint_ptr = (s32_t*)value; + *sint_ptr = od->id_inst_ptr[1]; + } + break; + case 2: /* atPhysAddress */ + { + struct eth_addr *dst = (struct eth_addr*)value; + + *dst = *ethaddr_ret; + } + break; + case 3: /* atNetAddress */ + { + ip_addr_t *dst = (ip_addr_t*)value; + + *dst = *ipaddr_ret; + } + break; + } + } +#endif /* LWIP_ARP */ +} + +static void +ip_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + u8_t id; + + /* return to object name, adding index depth (1) */ + ident_len += 1; + ident -= 1; + if (ident_len == 2) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff)); + id = (u8_t)ident[0]; + LWIP_DEBUGF(SNMP_MIB_DEBUG,("get_object_def ip.%"U16_F".0\n",(u16_t)id)); + switch (id) + { + case 1: /* ipForwarding */ + case 2: /* ipDefaultTTL */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + case 3: /* ipInReceives */ + case 4: /* ipInHdrErrors */ + case 5: /* ipInAddrErrors */ + case 6: /* ipForwDatagrams */ + case 7: /* ipInUnknownProtos */ + case 8: /* ipInDiscards */ + case 9: /* ipInDelivers */ + case 10: /* ipOutRequests */ + case 11: /* ipOutDiscards */ + case 12: /* ipOutNoRoutes */ + case 14: /* ipReasmReqds */ + case 15: /* ipReasmOKs */ + case 16: /* ipReasmFails */ + case 17: /* ipFragOKs */ + case 18: /* ipFragFails */ + case 19: /* ipFragCreates */ + case 23: /* ipRoutingDiscards */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER); + od->v_len = sizeof(u32_t); + break; + case 13: /* ipReasmTimeout */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + }; + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +ip_get_value(struct obj_def *od, u16_t len, void *value) +{ + u8_t id; + + LWIP_UNUSED_ARG(len); + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 1: /* ipForwarding */ + { + s32_t *sint_ptr = (s32_t*)value; +#if IP_FORWARD + /* forwarding */ + *sint_ptr = 1; +#else + /* not-forwarding */ + *sint_ptr = 2; +#endif + } + break; + case 2: /* ipDefaultTTL */ + { + s32_t *sint_ptr = (s32_t*)value; + *sint_ptr = IP_DEFAULT_TTL; + } + break; + case 3: /* ipInReceives */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipinreceives; + } + break; + case 4: /* ipInHdrErrors */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipinhdrerrors; + } + break; + case 5: /* ipInAddrErrors */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipinaddrerrors; + } + break; + case 6: /* ipForwDatagrams */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipforwdatagrams; + } + break; + case 7: /* ipInUnknownProtos */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipinunknownprotos; + } + break; + case 8: /* ipInDiscards */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipindiscards; + } + break; + case 9: /* ipInDelivers */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipindelivers; + } + break; + case 10: /* ipOutRequests */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipoutrequests; + } + break; + case 11: /* ipOutDiscards */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipoutdiscards; + } + break; + case 12: /* ipOutNoRoutes */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipoutnoroutes; + } + break; + case 13: /* ipReasmTimeout */ + { + s32_t *sint_ptr = (s32_t*)value; +#if IP_REASSEMBLY + *sint_ptr = IP_REASS_MAXAGE; +#else + *sint_ptr = 0; +#endif + } + break; + case 14: /* ipReasmReqds */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipreasmreqds; + } + break; + case 15: /* ipReasmOKs */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipreasmoks; + } + break; + case 16: /* ipReasmFails */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipreasmfails; + } + break; + case 17: /* ipFragOKs */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipfragoks; + } + break; + case 18: /* ipFragFails */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipfragfails; + } + break; + case 19: /* ipFragCreates */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipfragcreates; + } + break; + case 23: /* ipRoutingDiscards */ + /** @todo can lwIP discard routes at all?? hardwire this to 0?? */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = iproutingdiscards; + } + break; + }; +} + +/** + * Test ip object value before setting. + * + * @param od is the object definition + * @param len return value space (in bytes) + * @param value points to (varbind) space to copy value from. + * + * @note we allow set if the value matches the hardwired value, + * otherwise return badvalue. + */ +static u8_t +ip_set_test(struct obj_def *od, u16_t len, void *value) +{ + u8_t id, set_ok; + s32_t *sint_ptr = (s32_t*)value; + + LWIP_UNUSED_ARG(len); + set_ok = 0; + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 1: /* ipForwarding */ +#if IP_FORWARD + /* forwarding */ + if (*sint_ptr == 1) +#else + /* not-forwarding */ + if (*sint_ptr == 2) +#endif + { + set_ok = 1; + } + break; + case 2: /* ipDefaultTTL */ + if (*sint_ptr == IP_DEFAULT_TTL) + { + set_ok = 1; + } + break; + }; + return set_ok; +} + +static void +ip_addrentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + /* return to object name, adding index depth (4) */ + ident_len += 4; + ident -= 4; + + if (ident_len == 5) + { + u8_t id; + + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff)); + id = (u8_t)ident[0]; + switch (id) + { + case 1: /* ipAdEntAddr */ + case 3: /* ipAdEntNetMask */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR); + od->v_len = 4; + break; + case 2: /* ipAdEntIfIndex */ + case 4: /* ipAdEntBcastAddr */ + case 5: /* ipAdEntReasmMaxSize */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_addrentry_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + } + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_addrentry_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +ip_addrentry_get_value(struct obj_def *od, u16_t len, void *value) +{ + u8_t id; + u16_t ifidx; + ip_addr_t ip; + struct netif *netif = netif_list; + + LWIP_UNUSED_ARG(len); + snmp_oidtoip(&od->id_inst_ptr[1], &ip); + ifidx = 0; + while ((netif != NULL) && !ip_addr_cmp(&ip, &netif->ip_addr)) + { + netif = netif->next; + ifidx++; + } + + if (netif != NULL) + { + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 1: /* ipAdEntAddr */ + { + ip_addr_t *dst = (ip_addr_t*)value; + *dst = netif->ip_addr; + } + break; + case 2: /* ipAdEntIfIndex */ + { + s32_t *sint_ptr = (s32_t*)value; + *sint_ptr = ifidx + 1; + } + break; + case 3: /* ipAdEntNetMask */ + { + ip_addr_t *dst = (ip_addr_t*)value; + *dst = netif->netmask; + } + break; + case 4: /* ipAdEntBcastAddr */ + { + s32_t *sint_ptr = (s32_t*)value; + + /* lwIP oddity, there's no broadcast + address in the netif we can rely on */ + *sint_ptr = IPADDR_BROADCAST & 1; + } + break; + case 5: /* ipAdEntReasmMaxSize */ + { + s32_t *sint_ptr = (s32_t*)value; +#if IP_REASSEMBLY + /* @todo The theoretical maximum is IP_REASS_MAX_PBUFS * size of the pbufs, + * but only if receiving one fragmented packet at a time. + * The current solution is to calculate for 2 simultaneous packets... + */ + *sint_ptr = (IP_HLEN + ((IP_REASS_MAX_PBUFS/2) * + (PBUF_POOL_BUFSIZE - PBUF_LINK_HLEN - IP_HLEN))); +#else + /** @todo returning MTU would be a bad thing and + returning a wild guess like '576' isn't good either */ + *sint_ptr = 0; +#endif + } + break; + } + } +} + +/** + * @note + * lwIP IP routing is currently using the network addresses in netif_list. + * if no suitable network IP is found in netif_list, the default_netif is used. + */ +static void +ip_rteentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + u8_t id; + + /* return to object name, adding index depth (4) */ + ident_len += 4; + ident -= 4; + + if (ident_len == 5) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff)); + id = (u8_t)ident[0]; + switch (id) + { + case 1: /* ipRouteDest */ + case 7: /* ipRouteNextHop */ + case 11: /* ipRouteMask */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR); + od->v_len = 4; + break; + case 2: /* ipRouteIfIndex */ + case 3: /* ipRouteMetric1 */ + case 4: /* ipRouteMetric2 */ + case 5: /* ipRouteMetric3 */ + case 6: /* ipRouteMetric4 */ + case 8: /* ipRouteType */ + case 10: /* ipRouteAge */ + case 12: /* ipRouteMetric5 */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + case 9: /* ipRouteProto */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + case 13: /* ipRouteInfo */ + /** @note returning zeroDotZero (0.0) no routing protocol specific MIB */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID); + od->v_len = iprouteinfo.len * sizeof(s32_t); + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_rteentry_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + } + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_rteentry_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +ip_rteentry_get_value(struct obj_def *od, u16_t len, void *value) +{ + struct netif *netif; + ip_addr_t dest; + s32_t *ident; + u8_t id; + + ident = od->id_inst_ptr; + snmp_oidtoip(&ident[1], &dest); + + if (ip_addr_isany(&dest)) + { + /* ip_route() uses default netif for default route */ + netif = netif_default; + } + else + { + /* not using ip_route(), need exact match! */ + netif = netif_list; + while ((netif != NULL) && + !ip_addr_netcmp(&dest, &(netif->ip_addr), &(netif->netmask)) ) + { + netif = netif->next; + } + } + if (netif != NULL) + { + LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff)); + id = (u8_t)ident[0]; + switch (id) + { + case 1: /* ipRouteDest */ + { + ip_addr_t *dst = (ip_addr_t*)value; + + if (ip_addr_isany(&dest)) + { + /* default rte has 0.0.0.0 dest */ + ip_addr_set_zero(dst); + } + else + { + /* netifs have netaddress dest */ + ip_addr_get_network(dst, &netif->ip_addr, &netif->netmask); + } + } + break; + case 2: /* ipRouteIfIndex */ + { + s32_t *sint_ptr = (s32_t*)value; + + snmp_netiftoifindex(netif, sint_ptr); + } + break; + case 3: /* ipRouteMetric1 */ + { + s32_t *sint_ptr = (s32_t*)value; + + if (ip_addr_isany(&dest)) + { + /* default rte has metric 1 */ + *sint_ptr = 1; + } + else + { + /* other rtes have metric 0 */ + *sint_ptr = 0; + } + } + break; + case 4: /* ipRouteMetric2 */ + case 5: /* ipRouteMetric3 */ + case 6: /* ipRouteMetric4 */ + case 12: /* ipRouteMetric5 */ + { + s32_t *sint_ptr = (s32_t*)value; + /* not used */ + *sint_ptr = -1; + } + break; + case 7: /* ipRouteNextHop */ + { + ip_addr_t *dst = (ip_addr_t*)value; + + if (ip_addr_isany(&dest)) + { + /* default rte: gateway */ + *dst = netif->gw; + } + else + { + /* other rtes: netif ip_addr */ + *dst = netif->ip_addr; + } + } + break; + case 8: /* ipRouteType */ + { + s32_t *sint_ptr = (s32_t*)value; + + if (ip_addr_isany(&dest)) + { + /* default rte is indirect */ + *sint_ptr = 4; + } + else + { + /* other rtes are direct */ + *sint_ptr = 3; + } + } + break; + case 9: /* ipRouteProto */ + { + s32_t *sint_ptr = (s32_t*)value; + /* locally defined routes */ + *sint_ptr = 2; + } + break; + case 10: /* ipRouteAge */ + { + s32_t *sint_ptr = (s32_t*)value; + /** @todo (sysuptime - timestamp last change) / 100 + @see snmp_insert_iprteidx_tree() */ + *sint_ptr = 0; + } + break; + case 11: /* ipRouteMask */ + { + ip_addr_t *dst = (ip_addr_t*)value; + + if (ip_addr_isany(&dest)) + { + /* default rte use 0.0.0.0 mask */ + ip_addr_set_zero(dst); + } + else + { + /* other rtes use netmask */ + *dst = netif->netmask; + } + } + break; + case 13: /* ipRouteInfo */ + objectidncpy((s32_t*)value, (s32_t*)iprouteinfo.id, (u8_t)(len / sizeof(s32_t))); + break; + } + } +} + +static void +ip_ntomentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + /* return to object name, adding index depth (5) */ + ident_len += 5; + ident -= 5; + + if (ident_len == 6) + { + u8_t id; + + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff)); + id = (u8_t)ident[0]; + switch (id) + { + case 1: /* ipNetToMediaIfIndex */ + case 4: /* ipNetToMediaType */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + case 2: /* ipNetToMediaPhysAddress */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); + od->v_len = 6; /** @todo try to use netif::hwaddr_len */ + break; + case 3: /* ipNetToMediaNetAddress */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR); + od->v_len = 4; + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_ntomentry_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + } + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_ntomentry_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +ip_ntomentry_get_value(struct obj_def *od, u16_t len, void *value) +{ +#if LWIP_ARP + u8_t id; + struct eth_addr* ethaddr_ret; + ip_addr_t* ipaddr_ret; +#endif /* LWIP_ARP */ + ip_addr_t ip; + struct netif *netif; + + LWIP_UNUSED_ARG(len); + LWIP_UNUSED_ARG(value);/* if !LWIP_ARP */ + + snmp_ifindextonetif(od->id_inst_ptr[1], &netif); + snmp_oidtoip(&od->id_inst_ptr[2], &ip); + +#if LWIP_ARP /** @todo implement a netif_find_addr */ + if (etharp_find_addr(netif, &ip, ðaddr_ret, &ipaddr_ret) > -1) + { + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 1: /* ipNetToMediaIfIndex */ + { + s32_t *sint_ptr = (s32_t*)value; + *sint_ptr = od->id_inst_ptr[1]; + } + break; + case 2: /* ipNetToMediaPhysAddress */ + { + struct eth_addr *dst = (struct eth_addr*)value; + + *dst = *ethaddr_ret; + } + break; + case 3: /* ipNetToMediaNetAddress */ + { + ip_addr_t *dst = (ip_addr_t*)value; + + *dst = *ipaddr_ret; + } + break; + case 4: /* ipNetToMediaType */ + { + s32_t *sint_ptr = (s32_t*)value; + /* dynamic (?) */ + *sint_ptr = 3; + } + break; + } + } +#endif /* LWIP_ARP */ +} + +static void +icmp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + /* return to object name, adding index depth (1) */ + ident_len += 1; + ident -= 1; + if ((ident_len == 2) && + (ident[0] > 0) && (ident[0] < 27)) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER); + od->v_len = sizeof(u32_t); + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("icmp_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +icmp_get_value(struct obj_def *od, u16_t len, void *value) +{ + u32_t *uint_ptr = (u32_t*)value; + u8_t id; + + LWIP_UNUSED_ARG(len); + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 1: /* icmpInMsgs */ + *uint_ptr = icmpinmsgs; + break; + case 2: /* icmpInErrors */ + *uint_ptr = icmpinerrors; + break; + case 3: /* icmpInDestUnreachs */ + *uint_ptr = icmpindestunreachs; + break; + case 4: /* icmpInTimeExcds */ + *uint_ptr = icmpintimeexcds; + break; + case 5: /* icmpInParmProbs */ + *uint_ptr = icmpinparmprobs; + break; + case 6: /* icmpInSrcQuenchs */ + *uint_ptr = icmpinsrcquenchs; + break; + case 7: /* icmpInRedirects */ + *uint_ptr = icmpinredirects; + break; + case 8: /* icmpInEchos */ + *uint_ptr = icmpinechos; + break; + case 9: /* icmpInEchoReps */ + *uint_ptr = icmpinechoreps; + break; + case 10: /* icmpInTimestamps */ + *uint_ptr = icmpintimestamps; + break; + case 11: /* icmpInTimestampReps */ + *uint_ptr = icmpintimestampreps; + break; + case 12: /* icmpInAddrMasks */ + *uint_ptr = icmpinaddrmasks; + break; + case 13: /* icmpInAddrMaskReps */ + *uint_ptr = icmpinaddrmaskreps; + break; + case 14: /* icmpOutMsgs */ + *uint_ptr = icmpoutmsgs; + break; + case 15: /* icmpOutErrors */ + *uint_ptr = icmpouterrors; + break; + case 16: /* icmpOutDestUnreachs */ + *uint_ptr = icmpoutdestunreachs; + break; + case 17: /* icmpOutTimeExcds */ + *uint_ptr = icmpouttimeexcds; + break; + case 18: /* icmpOutParmProbs */ + *uint_ptr = icmpoutparmprobs; + break; + case 19: /* icmpOutSrcQuenchs */ + *uint_ptr = icmpoutsrcquenchs; + break; + case 20: /* icmpOutRedirects */ + *uint_ptr = icmpoutredirects; + break; + case 21: /* icmpOutEchos */ + *uint_ptr = icmpoutechos; + break; + case 22: /* icmpOutEchoReps */ + *uint_ptr = icmpoutechoreps; + break; + case 23: /* icmpOutTimestamps */ + *uint_ptr = icmpouttimestamps; + break; + case 24: /* icmpOutTimestampReps */ + *uint_ptr = icmpouttimestampreps; + break; + case 25: /* icmpOutAddrMasks */ + *uint_ptr = icmpoutaddrmasks; + break; + case 26: /* icmpOutAddrMaskReps */ + *uint_ptr = icmpoutaddrmaskreps; + break; + } +} + +#if LWIP_TCP +/** @todo tcp grp */ +static void +tcp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + u8_t id; + + /* return to object name, adding index depth (1) */ + ident_len += 1; + ident -= 1; + if (ident_len == 2) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff)); + id = (u8_t)ident[0]; + LWIP_DEBUGF(SNMP_MIB_DEBUG,("get_object_def tcp.%"U16_F".0\n",(u16_t)id)); + + switch (id) + { + case 1: /* tcpRtoAlgorithm */ + case 2: /* tcpRtoMin */ + case 3: /* tcpRtoMax */ + case 4: /* tcpMaxConn */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + case 5: /* tcpActiveOpens */ + case 6: /* tcpPassiveOpens */ + case 7: /* tcpAttemptFails */ + case 8: /* tcpEstabResets */ + case 10: /* tcpInSegs */ + case 11: /* tcpOutSegs */ + case 12: /* tcpRetransSegs */ + case 14: /* tcpInErrs */ + case 15: /* tcpOutRsts */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER); + od->v_len = sizeof(u32_t); + break; + case 9: /* tcpCurrEstab */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE); + od->v_len = sizeof(u32_t); + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("tcp_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + }; + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("tcp_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +tcp_get_value(struct obj_def *od, u16_t len, void *value) +{ + u32_t *uint_ptr = (u32_t*)value; + s32_t *sint_ptr = (s32_t*)value; + u8_t id; + + LWIP_UNUSED_ARG(len); + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 1: /* tcpRtoAlgorithm, vanj(4) */ + *sint_ptr = 4; + break; + case 2: /* tcpRtoMin */ + /* @todo not the actual value, a guess, + needs to be calculated */ + *sint_ptr = 1000; + break; + case 3: /* tcpRtoMax */ + /* @todo not the actual value, a guess, + needs to be calculated */ + *sint_ptr = 60000; + break; + case 4: /* tcpMaxConn */ + *sint_ptr = MEMP_NUM_TCP_PCB; + break; + case 5: /* tcpActiveOpens */ + *uint_ptr = tcpactiveopens; + break; + case 6: /* tcpPassiveOpens */ + *uint_ptr = tcppassiveopens; + break; + case 7: /* tcpAttemptFails */ + *uint_ptr = tcpattemptfails; + break; + case 8: /* tcpEstabResets */ + *uint_ptr = tcpestabresets; + break; + case 9: /* tcpCurrEstab */ + { + u16_t tcpcurrestab = 0; + struct tcp_pcb *pcb = tcp_active_pcbs; + while (pcb != NULL) + { + if ((pcb->state == ESTABLISHED) || + (pcb->state == CLOSE_WAIT)) + { + tcpcurrestab++; + } + pcb = pcb->next; + } + *uint_ptr = tcpcurrestab; + } + break; + case 10: /* tcpInSegs */ + *uint_ptr = tcpinsegs; + break; + case 11: /* tcpOutSegs */ + *uint_ptr = tcpoutsegs; + break; + case 12: /* tcpRetransSegs */ + *uint_ptr = tcpretranssegs; + break; + case 14: /* tcpInErrs */ + *uint_ptr = tcpinerrs; + break; + case 15: /* tcpOutRsts */ + *uint_ptr = tcpoutrsts; + break; + } +} +#ifdef THIS_SEEMS_UNUSED +static void +tcpconnentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + /* return to object name, adding index depth (10) */ + ident_len += 10; + ident -= 10; + + if (ident_len == 11) + { + u8_t id; + + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + id = ident[0]; + LWIP_DEBUGF(SNMP_MIB_DEBUG,("get_object_def tcp.%"U16_F".0\n",(u16_t)id)); + + switch (id) + { + case 1: /* tcpConnState */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + case 2: /* tcpConnLocalAddress */ + case 4: /* tcpConnRemAddress */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR); + od->v_len = 4; + break; + case 3: /* tcpConnLocalPort */ + case 5: /* tcpConnRemPort */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("tcpconnentry_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + }; + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("tcpconnentry_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +tcpconnentry_get_value(struct obj_def *od, u16_t len, void *value) +{ + ip_addr_t lip, rip; + u16_t lport, rport; + s32_t *ident; + + ident = od->id_inst_ptr; + snmp_oidtoip(&ident[1], &lip); + lport = ident[5]; + snmp_oidtoip(&ident[6], &rip); + rport = ident[10]; + + /** @todo find matching PCB */ +} +#endif /* if 0 */ +#endif + +static void +udp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + /* return to object name, adding index depth (1) */ + ident_len += 1; + ident -= 1; + if ((ident_len == 2) && + (ident[0] > 0) && (ident[0] < 6)) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER); + od->v_len = sizeof(u32_t); + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("udp_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +udp_get_value(struct obj_def *od, u16_t len, void *value) +{ + u32_t *uint_ptr = (u32_t*)value; + u8_t id; + + LWIP_UNUSED_ARG(len); + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 1: /* udpInDatagrams */ + *uint_ptr = udpindatagrams; + break; + case 2: /* udpNoPorts */ + *uint_ptr = udpnoports; + break; + case 3: /* udpInErrors */ + *uint_ptr = udpinerrors; + break; + case 4: /* udpOutDatagrams */ + *uint_ptr = udpoutdatagrams; + break; + } +} + +static void +udpentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + /* return to object name, adding index depth (5) */ + ident_len += 5; + ident -= 5; + + if (ident_len == 6) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + switch (ident[0]) + { + case 1: /* udpLocalAddress */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR); + od->v_len = 4; + break; + case 2: /* udpLocalPort */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("udpentry_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + } + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("udpentry_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +udpentry_get_value(struct obj_def *od, u16_t len, void *value) +{ + u8_t id; + struct udp_pcb *pcb; + ip_addr_t ip; + u16_t port; + + LWIP_UNUSED_ARG(len); + snmp_oidtoip(&od->id_inst_ptr[1], &ip); + LWIP_ASSERT("invalid port", (od->id_inst_ptr[5] >= 0) && (od->id_inst_ptr[5] <= 0xffff)); + port = (u16_t)od->id_inst_ptr[5]; + + pcb = udp_pcbs; + while ((pcb != NULL) && + !(ip_addr_cmp(&pcb->local_ip, &ip) && + (pcb->local_port == port))) + { + pcb = pcb->next; + } + + if (pcb != NULL) + { + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 1: /* udpLocalAddress */ + { + ip_addr_t *dst = (ip_addr_t*)value; + *dst = pcb->local_ip; + } + break; + case 2: /* udpLocalPort */ + { + s32_t *sint_ptr = (s32_t*)value; + *sint_ptr = pcb->local_port; + } + break; + } + } +} + +static void +snmp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + /* return to object name, adding index depth (1) */ + ident_len += 1; + ident -= 1; + if (ident_len == 2) + { + u8_t id; + + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff)); + id = (u8_t)ident[0]; + switch (id) + { + case 1: /* snmpInPkts */ + case 2: /* snmpOutPkts */ + case 3: /* snmpInBadVersions */ + case 4: /* snmpInBadCommunityNames */ + case 5: /* snmpInBadCommunityUses */ + case 6: /* snmpInASNParseErrs */ + case 8: /* snmpInTooBigs */ + case 9: /* snmpInNoSuchNames */ + case 10: /* snmpInBadValues */ + case 11: /* snmpInReadOnlys */ + case 12: /* snmpInGenErrs */ + case 13: /* snmpInTotalReqVars */ + case 14: /* snmpInTotalSetVars */ + case 15: /* snmpInGetRequests */ + case 16: /* snmpInGetNexts */ + case 17: /* snmpInSetRequests */ + case 18: /* snmpInGetResponses */ + case 19: /* snmpInTraps */ + case 20: /* snmpOutTooBigs */ + case 21: /* snmpOutNoSuchNames */ + case 22: /* snmpOutBadValues */ + case 24: /* snmpOutGenErrs */ + case 25: /* snmpOutGetRequests */ + case 26: /* snmpOutGetNexts */ + case 27: /* snmpOutSetRequests */ + case 28: /* snmpOutGetResponses */ + case 29: /* snmpOutTraps */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER); + od->v_len = sizeof(u32_t); + break; + case 30: /* snmpEnableAuthenTraps */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + }; + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +snmp_get_value(struct obj_def *od, u16_t len, void *value) +{ + u32_t *uint_ptr = (u32_t*)value; + u8_t id; + + LWIP_UNUSED_ARG(len); + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 1: /* snmpInPkts */ + *uint_ptr = snmpinpkts; + break; + case 2: /* snmpOutPkts */ + *uint_ptr = snmpoutpkts; + break; + case 3: /* snmpInBadVersions */ + *uint_ptr = snmpinbadversions; + break; + case 4: /* snmpInBadCommunityNames */ + *uint_ptr = snmpinbadcommunitynames; + break; + case 5: /* snmpInBadCommunityUses */ + *uint_ptr = snmpinbadcommunityuses; + break; + case 6: /* snmpInASNParseErrs */ + *uint_ptr = snmpinasnparseerrs; + break; + case 8: /* snmpInTooBigs */ + *uint_ptr = snmpintoobigs; + break; + case 9: /* snmpInNoSuchNames */ + *uint_ptr = snmpinnosuchnames; + break; + case 10: /* snmpInBadValues */ + *uint_ptr = snmpinbadvalues; + break; + case 11: /* snmpInReadOnlys */ + *uint_ptr = snmpinreadonlys; + break; + case 12: /* snmpInGenErrs */ + *uint_ptr = snmpingenerrs; + break; + case 13: /* snmpInTotalReqVars */ + *uint_ptr = snmpintotalreqvars; + break; + case 14: /* snmpInTotalSetVars */ + *uint_ptr = snmpintotalsetvars; + break; + case 15: /* snmpInGetRequests */ + *uint_ptr = snmpingetrequests; + break; + case 16: /* snmpInGetNexts */ + *uint_ptr = snmpingetnexts; + break; + case 17: /* snmpInSetRequests */ + *uint_ptr = snmpinsetrequests; + break; + case 18: /* snmpInGetResponses */ + *uint_ptr = snmpingetresponses; + break; + case 19: /* snmpInTraps */ + *uint_ptr = snmpintraps; + break; + case 20: /* snmpOutTooBigs */ + *uint_ptr = snmpouttoobigs; + break; + case 21: /* snmpOutNoSuchNames */ + *uint_ptr = snmpoutnosuchnames; + break; + case 22: /* snmpOutBadValues */ + *uint_ptr = snmpoutbadvalues; + break; + case 24: /* snmpOutGenErrs */ + *uint_ptr = snmpoutgenerrs; + break; + case 25: /* snmpOutGetRequests */ + *uint_ptr = snmpoutgetrequests; + break; + case 26: /* snmpOutGetNexts */ + *uint_ptr = snmpoutgetnexts; + break; + case 27: /* snmpOutSetRequests */ + *uint_ptr = snmpoutsetrequests; + break; + case 28: /* snmpOutGetResponses */ + *uint_ptr = snmpoutgetresponses; + break; + case 29: /* snmpOutTraps */ + *uint_ptr = snmpouttraps; + break; + case 30: /* snmpEnableAuthenTraps */ + *uint_ptr = *snmpenableauthentraps_ptr; + break; + }; +} + +/** + * Test snmp object value before setting. + * + * @param od is the object definition + * @param len return value space (in bytes) + * @param value points to (varbind) space to copy value from. + */ +static u8_t +snmp_set_test(struct obj_def *od, u16_t len, void *value) +{ + u8_t id, set_ok; + + LWIP_UNUSED_ARG(len); + set_ok = 0; + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + if (id == 30) + { + /* snmpEnableAuthenTraps */ + s32_t *sint_ptr = (s32_t*)value; + + if (snmpenableauthentraps_ptr != &snmpenableauthentraps_default) + { + /* we should have writable non-volatile mem here */ + if ((*sint_ptr == 1) || (*sint_ptr == 2)) + { + set_ok = 1; + } + } + else + { + /* const or hardwired value */ + if (*sint_ptr == snmpenableauthentraps_default) + { + set_ok = 1; + } + } + } + return set_ok; +} + +static void +snmp_set_value(struct obj_def *od, u16_t len, void *value) +{ + u8_t id; + + LWIP_UNUSED_ARG(len); + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + if (id == 30) + { + /* snmpEnableAuthenTraps */ + /* @todo @fixme: which kind of pointer is 'value'? s32_t or u8_t??? */ + u8_t *ptr = (u8_t*)value; + *snmpenableauthentraps_ptr = *ptr; + } +} + +#endif /* LWIP_SNMP */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/core/snmp/mib_structs.c b/component/common/network/lwip/lwip_v1.4.1/src/core/snmp/mib_structs.c new file mode 100644 index 0000000..2f185cb --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/core/snmp/mib_structs.c @@ -0,0 +1,1174 @@ +/** + * @file + * MIB tree access/construction functions. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * Author: Christiaan Simons + */ + +#include "lwip/opt.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/snmp_structs.h" +#include "lwip/memp.h" +#include "lwip/netif.h" + +/** .iso.org.dod.internet address prefix, @see snmp_iso_*() */ +const s32_t prefix[4] = {1, 3, 6, 1}; + +#define NODE_STACK_SIZE (LWIP_SNMP_OBJ_ID_LEN) +/** node stack entry (old news?) */ +struct nse +{ + /** right child */ + struct mib_node* r_ptr; + /** right child identifier */ + s32_t r_id; + /** right child next level */ + u8_t r_nl; +}; +static u8_t node_stack_cnt; +static struct nse node_stack[NODE_STACK_SIZE]; + +/** + * Pushes nse struct onto stack. + */ +static void +push_node(struct nse* node) +{ + LWIP_ASSERT("node_stack_cnt < NODE_STACK_SIZE",node_stack_cnt < NODE_STACK_SIZE); + LWIP_DEBUGF(SNMP_MIB_DEBUG,("push_node() node=%p id=%"S32_F"\n",(void*)(node->r_ptr),node->r_id)); + if (node_stack_cnt < NODE_STACK_SIZE) + { + node_stack[node_stack_cnt] = *node; + node_stack_cnt++; + } +} + +/** + * Pops nse struct from stack. + */ +static void +pop_node(struct nse* node) +{ + if (node_stack_cnt > 0) + { + node_stack_cnt--; + *node = node_stack[node_stack_cnt]; + } + LWIP_DEBUGF(SNMP_MIB_DEBUG,("pop_node() node=%p id=%"S32_F"\n",(void *)(node->r_ptr),node->r_id)); +} + +/** + * Conversion from ifIndex to lwIP netif + * @param ifindex is a s32_t object sub-identifier + * @param netif points to returned netif struct pointer + */ +void +snmp_ifindextonetif(s32_t ifindex, struct netif **netif) +{ + struct netif *nif = netif_list; + s32_t i, ifidx; + + ifidx = ifindex - 1; + i = 0; + while ((nif != NULL) && (i < ifidx)) + { + nif = nif->next; + i++; + } + *netif = nif; +} + +/** + * Conversion from lwIP netif to ifIndex + * @param netif points to a netif struct + * @param ifidx points to s32_t object sub-identifier + */ +void +snmp_netiftoifindex(struct netif *netif, s32_t *ifidx) +{ + struct netif *nif = netif_list; + u16_t i; + + i = 0; + while ((nif != NULL) && (nif != netif)) + { + nif = nif->next; + i++; + } + *ifidx = i+1; +} + +/** + * Conversion from oid to lwIP ip_addr + * @param ident points to s32_t ident[4] input + * @param ip points to output struct + */ +void +snmp_oidtoip(s32_t *ident, ip_addr_t *ip) +{ + IP4_ADDR(ip, ident[0], ident[1], ident[2], ident[3]); +} + +/** + * Conversion from lwIP ip_addr to oid + * @param ip points to input struct + * @param ident points to s32_t ident[4] output + */ +void +snmp_iptooid(ip_addr_t *ip, s32_t *ident) +{ + ident[0] = ip4_addr1(ip); + ident[1] = ip4_addr2(ip); + ident[2] = ip4_addr3(ip); + ident[3] = ip4_addr4(ip); +} + +struct mib_list_node * +snmp_mib_ln_alloc(s32_t id) +{ + struct mib_list_node *ln; + + ln = (struct mib_list_node *)memp_malloc(MEMP_SNMP_NODE); + if (ln != NULL) + { + ln->prev = NULL; + ln->next = NULL; + ln->objid = id; + ln->nptr = NULL; + } + return ln; +} + +void +snmp_mib_ln_free(struct mib_list_node *ln) +{ + memp_free(MEMP_SNMP_NODE, ln); +} + +struct mib_list_rootnode * +snmp_mib_lrn_alloc(void) +{ + struct mib_list_rootnode *lrn; + + lrn = (struct mib_list_rootnode*)memp_malloc(MEMP_SNMP_ROOTNODE); + if (lrn != NULL) + { + lrn->get_object_def = noleafs_get_object_def; + lrn->get_value = noleafs_get_value; + lrn->set_test = noleafs_set_test; + lrn->set_value = noleafs_set_value; + lrn->node_type = MIB_NODE_LR; + lrn->maxlength = 0; + lrn->head = NULL; + lrn->tail = NULL; + lrn->count = 0; + } + return lrn; +} + +void +snmp_mib_lrn_free(struct mib_list_rootnode *lrn) +{ + memp_free(MEMP_SNMP_ROOTNODE, lrn); +} + +/** + * Inserts node in idx list in a sorted + * (ascending order) fashion and + * allocates the node if needed. + * + * @param rn points to the root node + * @param objid is the object sub identifier + * @param insn points to a pointer to the inserted node + * used for constructing the tree. + * @return -1 if failed, 1 if inserted, 2 if present. + */ +s8_t +snmp_mib_node_insert(struct mib_list_rootnode *rn, s32_t objid, struct mib_list_node **insn) +{ + struct mib_list_node *nn; + s8_t insert; + + LWIP_ASSERT("rn != NULL",rn != NULL); + + /* -1 = malloc failure, 0 = not inserted, 1 = inserted, 2 = was present */ + insert = 0; + if (rn->head == NULL) + { + /* empty list, add first node */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("alloc empty list objid==%"S32_F"\n",objid)); + nn = snmp_mib_ln_alloc(objid); + if (nn != NULL) + { + rn->head = nn; + rn->tail = nn; + *insn = nn; + insert = 1; + } + else + { + insert = -1; + } + } + else + { + struct mib_list_node *n; + /* at least one node is present */ + n = rn->head; + while ((n != NULL) && (insert == 0)) + { + if (n->objid == objid) + { + /* node is already there */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("node already there objid==%"S32_F"\n",objid)); + *insn = n; + insert = 2; + } + else if (n->objid < objid) + { + if (n->next == NULL) + { + /* alloc and insert at the tail */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("alloc ins tail objid==%"S32_F"\n",objid)); + nn = snmp_mib_ln_alloc(objid); + if (nn != NULL) + { + nn->next = NULL; + nn->prev = n; + n->next = nn; + rn->tail = nn; + *insn = nn; + insert = 1; + } + else + { + /* insertion failure */ + insert = -1; + } + } + else + { + /* there's more to explore: traverse list */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("traverse list\n")); + n = n->next; + } + } + else + { + /* n->objid > objid */ + /* alloc and insert between n->prev and n */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("alloc ins n->prev, objid==%"S32_F", n\n",objid)); + nn = snmp_mib_ln_alloc(objid); + if (nn != NULL) + { + if (n->prev == NULL) + { + /* insert at the head */ + nn->next = n; + nn->prev = NULL; + rn->head = nn; + n->prev = nn; + } + else + { + /* insert in the middle */ + nn->next = n; + nn->prev = n->prev; + n->prev->next = nn; + n->prev = nn; + } + *insn = nn; + insert = 1; + } + else + { + /* insertion failure */ + insert = -1; + } + } + } + } + if (insert == 1) + { + rn->count += 1; + } + LWIP_ASSERT("insert != 0",insert != 0); + return insert; +} + +/** + * Finds node in idx list and returns deletion mark. + * + * @param rn points to the root node + * @param objid is the object sub identifier + * @param fn returns pointer to found node + * @return 0 if not found, 1 if deletable, + * 2 can't delete (2 or more children), 3 not a list_node + */ +s8_t +snmp_mib_node_find(struct mib_list_rootnode *rn, s32_t objid, struct mib_list_node **fn) +{ + s8_t fc; + struct mib_list_node *n; + + LWIP_ASSERT("rn != NULL",rn != NULL); + n = rn->head; + while ((n != NULL) && (n->objid != objid)) + { + n = n->next; + } + if (n == NULL) + { + fc = 0; + } + else if (n->nptr == NULL) + { + /* leaf, can delete node */ + fc = 1; + } + else + { + struct mib_list_rootnode *r; + + if (n->nptr->node_type == MIB_NODE_LR) + { + r = (struct mib_list_rootnode *)n->nptr; + if (r->count > 1) + { + /* can't delete node */ + fc = 2; + } + else + { + /* count <= 1, can delete node */ + fc = 1; + } + } + else + { + /* other node type */ + fc = 3; + } + } + *fn = n; + return fc; +} + +/** + * Removes node from idx list + * if it has a single child left. + * + * @param rn points to the root node + * @param n points to the node to delete + * @return the nptr to be freed by caller + */ +struct mib_list_rootnode * +snmp_mib_node_delete(struct mib_list_rootnode *rn, struct mib_list_node *n) +{ + struct mib_list_rootnode *next; + + LWIP_ASSERT("rn != NULL",rn != NULL); + LWIP_ASSERT("n != NULL",n != NULL); + + /* caller must remove this sub-tree */ + next = (struct mib_list_rootnode*)(n->nptr); + rn->count -= 1; + + if (n == rn->head) + { + rn->head = n->next; + if (n->next != NULL) + { + /* not last node, new list begin */ + n->next->prev = NULL; + } + } + else if (n == rn->tail) + { + rn->tail = n->prev; + if (n->prev != NULL) + { + /* not last node, new list end */ + n->prev->next = NULL; + } + } + else + { + /* node must be in the middle */ + n->prev->next = n->next; + n->next->prev = n->prev; + } + LWIP_DEBUGF(SNMP_MIB_DEBUG,("free list objid==%"S32_F"\n",n->objid)); + snmp_mib_ln_free(n); + if (rn->count == 0) + { + rn->head = NULL; + rn->tail = NULL; + } + return next; +} + + + +/** + * Searches tree for the supplied (scalar?) object identifier. + * + * @param node points to the root of the tree ('.internet') + * @param ident_len the length of the supplied object identifier + * @param ident points to the array of sub identifiers + * @param np points to the found object instance (return) + * @return pointer to the requested parent (!) node if success, NULL otherwise + */ +struct mib_node * +snmp_search_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct snmp_name_ptr *np) +{ + u8_t node_type, ext_level; + + ext_level = 0; + LWIP_DEBUGF(SNMP_MIB_DEBUG,("node==%p *ident==%"S32_F"\n",(void*)node,*ident)); + while (node != NULL) + { + node_type = node->node_type; + if ((node_type == MIB_NODE_AR) || (node_type == MIB_NODE_RA)) + { + struct mib_array_node *an; + u16_t i; + + if (ident_len > 0) + { + /* array node (internal ROM or RAM, fixed length) */ + an = (struct mib_array_node *)node; + i = 0; + while ((i < an->maxlength) && (an->objid[i] != *ident)) + { + i++; + } + if (i < an->maxlength) + { + /* found it, if available proceed to child, otherwise inspect leaf */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("an->objid[%"U16_F"]==%"S32_F" *ident==%"S32_F"\n",i,an->objid[i],*ident)); + if (an->nptr[i] == NULL) + { + /* a scalar leaf OR table, + inspect remaining instance number / table index */ + np->ident_len = ident_len; + np->ident = ident; + return (struct mib_node*)an; + } + else + { + /* follow next child pointer */ + ident++; + ident_len--; + node = an->nptr[i]; + } + } + else + { + /* search failed, identifier mismatch (nosuchname) */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("an search failed *ident==%"S32_F"\n",*ident)); + return NULL; + } + } + else + { + /* search failed, short object identifier (nosuchname) */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("an search failed, short object identifier\n")); + return NULL; + } + } + else if(node_type == MIB_NODE_LR) + { + struct mib_list_rootnode *lrn; + struct mib_list_node *ln; + + if (ident_len > 0) + { + /* list root node (internal 'RAM', variable length) */ + lrn = (struct mib_list_rootnode *)node; + ln = lrn->head; + /* iterate over list, head to tail */ + while ((ln != NULL) && (ln->objid != *ident)) + { + ln = ln->next; + } + if (ln != NULL) + { + /* found it, proceed to child */; + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ln->objid==%"S32_F" *ident==%"S32_F"\n",ln->objid,*ident)); + if (ln->nptr == NULL) + { + np->ident_len = ident_len; + np->ident = ident; + return (struct mib_node*)lrn; + } + else + { + /* follow next child pointer */ + ident_len--; + ident++; + node = ln->nptr; + } + } + else + { + /* search failed */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ln search failed *ident==%"S32_F"\n",*ident)); + return NULL; + } + } + else + { + /* search failed, short object identifier (nosuchname) */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ln search failed, short object identifier\n")); + return NULL; + } + } + else if(node_type == MIB_NODE_EX) + { + struct mib_external_node *en; + u16_t i, len; + + if (ident_len > 0) + { + /* external node (addressing and access via functions) */ + en = (struct mib_external_node *)node; + + i = 0; + len = en->level_length(en->addr_inf,ext_level); + while ((i < len) && (en->ident_cmp(en->addr_inf,ext_level,i,*ident) != 0)) + { + i++; + } + if (i < len) + { + s32_t debug_id; + + en->get_objid(en->addr_inf,ext_level,i,&debug_id); + LWIP_DEBUGF(SNMP_MIB_DEBUG,("en->objid==%"S32_F" *ident==%"S32_F"\n",debug_id,*ident)); + if ((ext_level + 1) == en->tree_levels) + { + np->ident_len = ident_len; + np->ident = ident; + return (struct mib_node*)en; + } + else + { + /* found it, proceed to child */ + ident_len--; + ident++; + ext_level++; + } + } + else + { + /* search failed */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("en search failed *ident==%"S32_F"\n",*ident)); + return NULL; + } + } + else + { + /* search failed, short object identifier (nosuchname) */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("en search failed, short object identifier\n")); + return NULL; + } + } + else if (node_type == MIB_NODE_SC) + { + mib_scalar_node *sn; + + sn = (mib_scalar_node *)node; + if ((ident_len == 1) && (*ident == 0)) + { + np->ident_len = ident_len; + np->ident = ident; + return (struct mib_node*)sn; + } + else + { + /* search failed, short object identifier (nosuchname) */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("search failed, invalid object identifier length\n")); + return NULL; + } + } + else + { + /* unknown node_type */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("search failed node_type %"U16_F" unkown\n",(u16_t)node_type)); + return NULL; + } + } + /* done, found nothing */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("search failed node==%p\n",(void*)node)); + return NULL; +} + +/** + * Test table for presence of at least one table entry. + */ +static u8_t +empty_table(struct mib_node *node) +{ + u8_t node_type; + u8_t empty = 0; + + if (node != NULL) + { + node_type = node->node_type; + if (node_type == MIB_NODE_LR) + { + struct mib_list_rootnode *lrn; + lrn = (struct mib_list_rootnode *)node; + if ((lrn->count == 0) || (lrn->head == NULL)) + { + empty = 1; + } + } + else if ((node_type == MIB_NODE_AR) || (node_type == MIB_NODE_RA)) + { + struct mib_array_node *an; + an = (struct mib_array_node *)node; + if ((an->maxlength == 0) || (an->nptr == NULL)) + { + empty = 1; + } + } + else if (node_type == MIB_NODE_EX) + { + struct mib_external_node *en; + en = (struct mib_external_node *)node; + if (en->tree_levels == 0) + { + empty = 1; + } + } + } + return empty; +} + +/** + * Tree expansion. + */ +struct mib_node * +snmp_expand_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct snmp_obj_id *oidret) +{ + u8_t node_type, ext_level, climb_tree; + + ext_level = 0; + /* reset node stack */ + node_stack_cnt = 0; + while (node != NULL) + { + climb_tree = 0; + node_type = node->node_type; + if ((node_type == MIB_NODE_AR) || (node_type == MIB_NODE_RA)) + { + struct mib_array_node *an; + u16_t i; + + /* array node (internal ROM or RAM, fixed length) */ + an = (struct mib_array_node *)node; + if (ident_len > 0) + { + i = 0; + while ((i < an->maxlength) && (an->objid[i] < *ident)) + { + i++; + } + if (i < an->maxlength) + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("an->objid[%"U16_F"]==%"S32_F" *ident==%"S32_F"\n",i,an->objid[i],*ident)); + /* add identifier to oidret */ + oidret->id[oidret->len] = an->objid[i]; + (oidret->len)++; + + if (an->nptr[i] == NULL) + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("leaf node\n")); + /* leaf node (e.g. in a fixed size table) */ + if (an->objid[i] > *ident) + { + return (struct mib_node*)an; + } + else if ((i + 1) < an->maxlength) + { + /* an->objid[i] == *ident */ + (oidret->len)--; + oidret->id[oidret->len] = an->objid[i + 1]; + (oidret->len)++; + return (struct mib_node*)an; + } + else + { + /* (i + 1) == an->maxlength */ + (oidret->len)--; + climb_tree = 1; + } + } + else + { + u8_t j; + struct nse cur_node; + + LWIP_DEBUGF(SNMP_MIB_DEBUG,("non-leaf node\n")); + /* non-leaf, store right child ptr and id */ + LWIP_ASSERT("i < 0xff", i < 0xff); + j = (u8_t)i + 1; + while ((j < an->maxlength) && (empty_table(an->nptr[j]))) + { + j++; + } + if (j < an->maxlength) + { + cur_node.r_ptr = an->nptr[j]; + cur_node.r_id = an->objid[j]; + cur_node.r_nl = 0; + } + else + { + cur_node.r_ptr = NULL; + } + push_node(&cur_node); + if (an->objid[i] == *ident) + { + ident_len--; + ident++; + } + else + { + /* an->objid[i] < *ident */ + ident_len = 0; + } + /* follow next child pointer */ + node = an->nptr[i]; + } + } + else + { + /* i == an->maxlength */ + climb_tree = 1; + } + } + else + { + u8_t j; + /* ident_len == 0, complete with leftmost '.thing' */ + j = 0; + while ((j < an->maxlength) && empty_table(an->nptr[j])) + { + j++; + } + if (j < an->maxlength) + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("left an->objid[j]==%"S32_F"\n",an->objid[j])); + oidret->id[oidret->len] = an->objid[j]; + (oidret->len)++; + if (an->nptr[j] == NULL) + { + /* leaf node */ + return (struct mib_node*)an; + } + else + { + /* no leaf, continue */ + node = an->nptr[j]; + } + } + else + { + /* j == an->maxlength */ + climb_tree = 1; + } + } + } + else if(node_type == MIB_NODE_LR) + { + struct mib_list_rootnode *lrn; + struct mib_list_node *ln; + + /* list root node (internal 'RAM', variable length) */ + lrn = (struct mib_list_rootnode *)node; + if (ident_len > 0) + { + ln = lrn->head; + /* iterate over list, head to tail */ + while ((ln != NULL) && (ln->objid < *ident)) + { + ln = ln->next; + } + if (ln != NULL) + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ln->objid==%"S32_F" *ident==%"S32_F"\n",ln->objid,*ident)); + oidret->id[oidret->len] = ln->objid; + (oidret->len)++; + if (ln->nptr == NULL) + { + /* leaf node */ + if (ln->objid > *ident) + { + return (struct mib_node*)lrn; + } + else if (ln->next != NULL) + { + /* ln->objid == *ident */ + (oidret->len)--; + oidret->id[oidret->len] = ln->next->objid; + (oidret->len)++; + return (struct mib_node*)lrn; + } + else + { + /* ln->next == NULL */ + (oidret->len)--; + climb_tree = 1; + } + } + else + { + struct mib_list_node *jn; + struct nse cur_node; + + /* non-leaf, store right child ptr and id */ + jn = ln->next; + while ((jn != NULL) && empty_table(jn->nptr)) + { + jn = jn->next; + } + if (jn != NULL) + { + cur_node.r_ptr = jn->nptr; + cur_node.r_id = jn->objid; + cur_node.r_nl = 0; + } + else + { + cur_node.r_ptr = NULL; + } + push_node(&cur_node); + if (ln->objid == *ident) + { + ident_len--; + ident++; + } + else + { + /* ln->objid < *ident */ + ident_len = 0; + } + /* follow next child pointer */ + node = ln->nptr; + } + + } + else + { + /* ln == NULL */ + climb_tree = 1; + } + } + else + { + struct mib_list_node *jn; + /* ident_len == 0, complete with leftmost '.thing' */ + jn = lrn->head; + while ((jn != NULL) && empty_table(jn->nptr)) + { + jn = jn->next; + } + if (jn != NULL) + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("left jn->objid==%"S32_F"\n",jn->objid)); + oidret->id[oidret->len] = jn->objid; + (oidret->len)++; + if (jn->nptr == NULL) + { + /* leaf node */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("jn->nptr == NULL\n")); + return (struct mib_node*)lrn; + } + else + { + /* no leaf, continue */ + node = jn->nptr; + } + } + else + { + /* jn == NULL */ + climb_tree = 1; + } + } + } + else if(node_type == MIB_NODE_EX) + { + struct mib_external_node *en; + s32_t ex_id; + + /* external node (addressing and access via functions) */ + en = (struct mib_external_node *)node; + if (ident_len > 0) + { + u16_t i, len; + + i = 0; + len = en->level_length(en->addr_inf,ext_level); + while ((i < len) && (en->ident_cmp(en->addr_inf,ext_level,i,*ident) < 0)) + { + i++; + } + if (i < len) + { + /* add identifier to oidret */ + en->get_objid(en->addr_inf,ext_level,i,&ex_id); + LWIP_DEBUGF(SNMP_MIB_DEBUG,("en->objid[%"U16_F"]==%"S32_F" *ident==%"S32_F"\n",i,ex_id,*ident)); + oidret->id[oidret->len] = ex_id; + (oidret->len)++; + + if ((ext_level + 1) == en->tree_levels) + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("leaf node\n")); + /* leaf node */ + if (ex_id > *ident) + { + return (struct mib_node*)en; + } + else if ((i + 1) < len) + { + /* ex_id == *ident */ + en->get_objid(en->addr_inf,ext_level,i + 1,&ex_id); + (oidret->len)--; + oidret->id[oidret->len] = ex_id; + (oidret->len)++; + return (struct mib_node*)en; + } + else + { + /* (i + 1) == len */ + (oidret->len)--; + climb_tree = 1; + } + } + else + { + u8_t j; + struct nse cur_node; + + LWIP_DEBUGF(SNMP_MIB_DEBUG,("non-leaf node\n")); + /* non-leaf, store right child ptr and id */ + LWIP_ASSERT("i < 0xff", i < 0xff); + j = (u8_t)i + 1; + if (j < len) + { + /* right node is the current external node */ + cur_node.r_ptr = node; + en->get_objid(en->addr_inf,ext_level,j,&cur_node.r_id); + cur_node.r_nl = ext_level + 1; + } + else + { + cur_node.r_ptr = NULL; + } + push_node(&cur_node); + if (en->ident_cmp(en->addr_inf,ext_level,i,*ident) == 0) + { + ident_len--; + ident++; + } + else + { + /* external id < *ident */ + ident_len = 0; + } + /* proceed to child */ + ext_level++; + } + } + else + { + /* i == len (en->level_len()) */ + climb_tree = 1; + } + } + else + { + /* ident_len == 0, complete with leftmost '.thing' */ + en->get_objid(en->addr_inf,ext_level,0,&ex_id); + LWIP_DEBUGF(SNMP_MIB_DEBUG,("left en->objid==%"S32_F"\n",ex_id)); + oidret->id[oidret->len] = ex_id; + (oidret->len)++; + if ((ext_level + 1) == en->tree_levels) + { + /* leaf node */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("(ext_level + 1) == en->tree_levels\n")); + return (struct mib_node*)en; + } + else + { + /* no leaf, proceed to child */ + ext_level++; + } + } + } + else if(node_type == MIB_NODE_SC) + { + mib_scalar_node *sn; + + /* scalar node */ + sn = (mib_scalar_node *)node; + if (ident_len > 0) + { + /* at .0 */ + climb_tree = 1; + } + else + { + /* ident_len == 0, complete object identifier */ + oidret->id[oidret->len] = 0; + (oidret->len)++; + /* leaf node */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("completed scalar leaf\n")); + return (struct mib_node*)sn; + } + } + else + { + /* unknown/unhandled node_type */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("expand failed node_type %"U16_F" unkown\n",(u16_t)node_type)); + return NULL; + } + + if (climb_tree) + { + struct nse child; + + /* find right child ptr */ + child.r_ptr = NULL; + child.r_id = 0; + child.r_nl = 0; + while ((node_stack_cnt > 0) && (child.r_ptr == NULL)) + { + pop_node(&child); + /* trim returned oid */ + (oidret->len)--; + } + if (child.r_ptr != NULL) + { + /* incoming ident is useless beyond this point */ + ident_len = 0; + oidret->id[oidret->len] = child.r_id; + oidret->len++; + node = child.r_ptr; + ext_level = child.r_nl; + } + else + { + /* tree ends here ... */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("expand failed, tree ends here\n")); + return NULL; + } + } + } + /* done, found nothing */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("expand failed node==%p\n",(void*)node)); + return NULL; +} + +/** + * Test object identifier for the iso.org.dod.internet prefix. + * + * @param ident_len the length of the supplied object identifier + * @param ident points to the array of sub identifiers + * @return 1 if it matches, 0 otherwise + */ +u8_t +snmp_iso_prefix_tst(u8_t ident_len, s32_t *ident) +{ + if ((ident_len > 3) && + (ident[0] == 1) && (ident[1] == 3) && + (ident[2] == 6) && (ident[3] == 1)) + { + return 1; + } + else + { + return 0; + } +} + +/** + * Expands object identifier to the iso.org.dod.internet + * prefix for use in getnext operation. + * + * @param ident_len the length of the supplied object identifier + * @param ident points to the array of sub identifiers + * @param oidret points to returned expanded object identifier + * @return 1 if it matches, 0 otherwise + * + * @note ident_len 0 is allowed, expanding to the first known object id!! + */ +u8_t +snmp_iso_prefix_expand(u8_t ident_len, s32_t *ident, struct snmp_obj_id *oidret) +{ + const s32_t *prefix_ptr; + s32_t *ret_ptr; + u8_t i; + + i = 0; + prefix_ptr = &prefix[0]; + ret_ptr = &oidret->id[0]; + ident_len = ((ident_len < 4)?ident_len:4); + while ((i < ident_len) && ((*ident) <= (*prefix_ptr))) + { + *ret_ptr++ = *prefix_ptr++; + ident++; + i++; + } + if (i == ident_len) + { + /* match, complete missing bits */ + while (i < 4) + { + *ret_ptr++ = *prefix_ptr++; + i++; + } + oidret->len = i; + return 1; + } + else + { + /* i != ident_len */ + return 0; + } +} + +#endif /* LWIP_SNMP */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/core/snmp/msg_in.c b/component/common/network/lwip/lwip_v1.4.1/src/core/snmp/msg_in.c new file mode 100644 index 0000000..be940c6 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/core/snmp/msg_in.c @@ -0,0 +1,1453 @@ +/** + * @file + * SNMP input message processing (RFC1157). + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * Author: Christiaan Simons + */ + +#include "lwip/opt.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/snmp.h" +#include "lwip/snmp_asn1.h" +#include "lwip/snmp_msg.h" +#include "lwip/snmp_structs.h" +#include "lwip/ip_addr.h" +#include "lwip/memp.h" +#include "lwip/udp.h" +#include "lwip/stats.h" + +#include + +/* public (non-static) constants */ +/** SNMP v1 == 0 */ +const s32_t snmp_version = 0; +/** default SNMP community string */ +const char snmp_publiccommunity[7] = "public"; + +/* statically allocated buffers for SNMP_CONCURRENT_REQUESTS */ +struct snmp_msg_pstat msg_input_list[SNMP_CONCURRENT_REQUESTS]; +/* UDP Protocol Control Block */ +struct udp_pcb *snmp1_pcb; + +static void snmp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port); +static err_t snmp_pdu_header_check(struct pbuf *p, u16_t ofs, u16_t pdu_len, u16_t *ofs_ret, struct snmp_msg_pstat *m_stat); +static err_t snmp_pdu_dec_varbindlist(struct pbuf *p, u16_t ofs, u16_t *ofs_ret, struct snmp_msg_pstat *m_stat); + + +/** + * Starts SNMP Agent. + * Allocates UDP pcb and binds it to IP_ADDR_ANY port 161. + */ +void +snmp_init(void) +{ + struct snmp_msg_pstat *msg_ps; + u8_t i; + + snmp1_pcb = udp_new(); + if (snmp1_pcb != NULL) + { + udp_recv(snmp1_pcb, snmp_recv, (void *)SNMP_IN_PORT); + udp_bind(snmp1_pcb, IP_ADDR_ANY, SNMP_IN_PORT); + } + msg_ps = &msg_input_list[0]; + for (i=0; istate = SNMP_MSG_EMPTY; + msg_ps->error_index = 0; + msg_ps->error_status = SNMP_ES_NOERROR; + msg_ps++; + } + trap_msg.pcb = snmp1_pcb; + +#ifdef SNMP_PRIVATE_MIB_INIT + /* If defined, this must be a function-like define to initialize the + * private MIB after the stack has been initialized. + * The private MIB can also be initialized in tcpip_callback (or after + * the stack is initialized), this define is only for convenience. */ + SNMP_PRIVATE_MIB_INIT(); +#endif /* SNMP_PRIVATE_MIB_INIT */ + + /* The coldstart trap will only be output + if our outgoing interface is up & configured */ + snmp_coldstart_trap(); +} + +static void +snmp_error_response(struct snmp_msg_pstat *msg_ps, u8_t error) +{ + /* move names back from outvb to invb */ + int v; + struct snmp_varbind *vbi = msg_ps->invb.head; + struct snmp_varbind *vbo = msg_ps->outvb.head; + for (v=0; vvb_idx; v++) { + vbi->ident_len = vbo->ident_len; + vbo->ident_len = 0; + vbi->ident = vbo->ident; + vbo->ident = NULL; + vbi = vbi->next; + vbo = vbo->next; + } + /* free outvb */ + snmp_varbind_list_free(&msg_ps->outvb); + /* we send invb back */ + msg_ps->outvb = msg_ps->invb; + msg_ps->invb.head = NULL; + msg_ps->invb.tail = NULL; + msg_ps->invb.count = 0; + msg_ps->error_status = error; + /* error index must be 0 for error too big */ + msg_ps->error_index = (error != SNMP_ES_TOOBIG) ? (1 + msg_ps->vb_idx) : 0; + snmp_send_response(msg_ps); + snmp_varbind_list_free(&msg_ps->outvb); + msg_ps->state = SNMP_MSG_EMPTY; +} + +static void +snmp_ok_response(struct snmp_msg_pstat *msg_ps) +{ + err_t err_ret; + + err_ret = snmp_send_response(msg_ps); + if (err_ret == ERR_MEM) + { + /* serious memory problem, can't return tooBig */ + } + else + { + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event = %"S32_F"\n",msg_ps->error_status)); + } + /* free varbinds (if available) */ + snmp_varbind_list_free(&msg_ps->invb); + snmp_varbind_list_free(&msg_ps->outvb); + msg_ps->state = SNMP_MSG_EMPTY; +} + +/** + * Service an internal or external event for SNMP GET. + * + * @param request_id identifies requests from 0 to (SNMP_CONCURRENT_REQUESTS-1) + * @param msg_ps points to the assosicated message process state + */ +static void +snmp_msg_get_event(u8_t request_id, struct snmp_msg_pstat *msg_ps) +{ + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_get_event: msg_ps->state==%"U16_F"\n",(u16_t)msg_ps->state)); + + if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_OBJDEF) + { + struct mib_external_node *en; + struct snmp_name_ptr np; + + /* get_object_def() answer*/ + en = msg_ps->ext_mib_node; + np = msg_ps->ext_name_ptr; + + /* translate answer into a known lifeform */ + en->get_object_def_a(request_id, np.ident_len, np.ident, &msg_ps->ext_object_def); + if ((msg_ps->ext_object_def.instance != MIB_OBJECT_NONE) && + (msg_ps->ext_object_def.access & MIB_ACCESS_READ)) + { + msg_ps->state = SNMP_MSG_EXTERNAL_GET_VALUE; + en->get_value_q(request_id, &msg_ps->ext_object_def); + } + else + { + en->get_object_def_pc(request_id, np.ident_len, np.ident); + /* search failed, object id points to unknown object (nosuchname) */ + snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME); + } + } + else if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_VALUE) + { + struct mib_external_node *en; + struct snmp_varbind *vb; + + /* get_value() answer */ + en = msg_ps->ext_mib_node; + + /* allocate output varbind */ + vb = (struct snmp_varbind *)memp_malloc(MEMP_SNMP_VARBIND); + if (vb != NULL) + { + vb->next = NULL; + vb->prev = NULL; + + /* move name from invb to outvb */ + vb->ident = msg_ps->vb_ptr->ident; + vb->ident_len = msg_ps->vb_ptr->ident_len; + /* ensure this memory is refereced once only */ + msg_ps->vb_ptr->ident = NULL; + msg_ps->vb_ptr->ident_len = 0; + + vb->value_type = msg_ps->ext_object_def.asn_type; + LWIP_ASSERT("invalid length", msg_ps->ext_object_def.v_len <= 0xff); + vb->value_len = (u8_t)msg_ps->ext_object_def.v_len; + if (vb->value_len > 0) + { + LWIP_ASSERT("SNMP_MAX_OCTET_STRING_LEN is configured too low", vb->value_len <= SNMP_MAX_VALUE_SIZE); + vb->value = memp_malloc(MEMP_SNMP_VALUE); + if (vb->value != NULL) + { + en->get_value_a(request_id, &msg_ps->ext_object_def, vb->value_len, vb->value); + snmp_varbind_tail_add(&msg_ps->outvb, vb); + /* search again (if vb_idx < msg_ps->invb.count) */ + msg_ps->state = SNMP_MSG_SEARCH_OBJ; + msg_ps->vb_idx += 1; + } + else + { + en->get_value_pc(request_id, &msg_ps->ext_object_def); + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event: no variable space\n")); + msg_ps->vb_ptr->ident = vb->ident; + msg_ps->vb_ptr->ident_len = vb->ident_len; + memp_free(MEMP_SNMP_VARBIND, vb); + snmp_error_response(msg_ps,SNMP_ES_TOOBIG); + } + } + else + { + /* vb->value_len == 0, empty value (e.g. empty string) */ + en->get_value_a(request_id, &msg_ps->ext_object_def, 0, NULL); + vb->value = NULL; + snmp_varbind_tail_add(&msg_ps->outvb, vb); + /* search again (if vb_idx < msg_ps->invb.count) */ + msg_ps->state = SNMP_MSG_SEARCH_OBJ; + msg_ps->vb_idx += 1; + } + } + else + { + en->get_value_pc(request_id, &msg_ps->ext_object_def); + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event: no outvb space\n")); + snmp_error_response(msg_ps,SNMP_ES_TOOBIG); + } + } + + while ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) && + (msg_ps->vb_idx < msg_ps->invb.count)) + { + struct mib_node *mn; + struct snmp_name_ptr np; + + if (msg_ps->vb_idx == 0) + { + msg_ps->vb_ptr = msg_ps->invb.head; + } + else + { + msg_ps->vb_ptr = msg_ps->vb_ptr->next; + } + /** test object identifier for .iso.org.dod.internet prefix */ + if (snmp_iso_prefix_tst(msg_ps->vb_ptr->ident_len, msg_ps->vb_ptr->ident)) + { + mn = snmp_search_tree((struct mib_node*)&internet, msg_ps->vb_ptr->ident_len - 4, + msg_ps->vb_ptr->ident + 4, &np); + if (mn != NULL) + { + if (mn->node_type == MIB_NODE_EX) + { + /* external object */ + struct mib_external_node *en = (struct mib_external_node*)mn; + + msg_ps->state = SNMP_MSG_EXTERNAL_GET_OBJDEF; + /* save en && args in msg_ps!! */ + msg_ps->ext_mib_node = en; + msg_ps->ext_name_ptr = np; + + en->get_object_def_q(en->addr_inf, request_id, np.ident_len, np.ident); + } + else + { + /* internal object */ + struct obj_def object_def; + + msg_ps->state = SNMP_MSG_INTERNAL_GET_OBJDEF; + mn->get_object_def(np.ident_len, np.ident, &object_def); + if ((object_def.instance != MIB_OBJECT_NONE) && + (object_def.access & MIB_ACCESS_READ)) + { + mn = mn; + } + else + { + /* search failed, object id points to unknown object (nosuchname) */ + mn = NULL; + } + if (mn != NULL) + { + struct snmp_varbind *vb; + + msg_ps->state = SNMP_MSG_INTERNAL_GET_VALUE; + /* allocate output varbind */ + vb = (struct snmp_varbind *)memp_malloc(MEMP_SNMP_VARBIND); + if (vb != NULL) + { + vb->next = NULL; + vb->prev = NULL; + + /* move name from invb to outvb */ + vb->ident = msg_ps->vb_ptr->ident; + vb->ident_len = msg_ps->vb_ptr->ident_len; + /* ensure this memory is refereced once only */ + msg_ps->vb_ptr->ident = NULL; + msg_ps->vb_ptr->ident_len = 0; + + vb->value_type = object_def.asn_type; + LWIP_ASSERT("invalid length", object_def.v_len <= 0xff); + vb->value_len = (u8_t)object_def.v_len; + if (vb->value_len > 0) + { + LWIP_ASSERT("SNMP_MAX_OCTET_STRING_LEN is configured too low", + vb->value_len <= SNMP_MAX_VALUE_SIZE); + vb->value = memp_malloc(MEMP_SNMP_VALUE); + if (vb->value != NULL) + { + mn->get_value(&object_def, vb->value_len, vb->value); + snmp_varbind_tail_add(&msg_ps->outvb, vb); + msg_ps->state = SNMP_MSG_SEARCH_OBJ; + msg_ps->vb_idx += 1; + } + else + { + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event: couldn't allocate variable space\n")); + msg_ps->vb_ptr->ident = vb->ident; + msg_ps->vb_ptr->ident_len = vb->ident_len; + vb->ident = NULL; + vb->ident_len = 0; + memp_free(MEMP_SNMP_VARBIND, vb); + snmp_error_response(msg_ps,SNMP_ES_TOOBIG); + } + } + else + { + /* vb->value_len == 0, empty value (e.g. empty string) */ + vb->value = NULL; + snmp_varbind_tail_add(&msg_ps->outvb, vb); + msg_ps->state = SNMP_MSG_SEARCH_OBJ; + msg_ps->vb_idx += 1; + } + } + else + { + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event: couldn't allocate outvb space\n")); + snmp_error_response(msg_ps,SNMP_ES_TOOBIG); + } + } + } + } + } + else + { + mn = NULL; + } + if (mn == NULL) + { + /* mn == NULL, noSuchName */ + snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME); + } + } + if ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) && + (msg_ps->vb_idx == msg_ps->invb.count)) + { + snmp_ok_response(msg_ps); + } +} + +/** + * Service an internal or external event for SNMP GETNEXT. + * + * @param request_id identifies requests from 0 to (SNMP_CONCURRENT_REQUESTS-1) + * @param msg_ps points to the assosicated message process state + */ +static void +snmp_msg_getnext_event(u8_t request_id, struct snmp_msg_pstat *msg_ps) +{ + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_getnext_event: msg_ps->state==%"U16_F"\n",(u16_t)msg_ps->state)); + + if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_OBJDEF) + { + struct mib_external_node *en; + + /* get_object_def() answer*/ + en = msg_ps->ext_mib_node; + + /* translate answer into a known lifeform */ + en->get_object_def_a(request_id, 1, &msg_ps->ext_oid.id[msg_ps->ext_oid.len - 1], &msg_ps->ext_object_def); + if (msg_ps->ext_object_def.instance != MIB_OBJECT_NONE) + { + msg_ps->state = SNMP_MSG_EXTERNAL_GET_VALUE; + en->get_value_q(request_id, &msg_ps->ext_object_def); + } + else + { + en->get_object_def_pc(request_id, 1, &msg_ps->ext_oid.id[msg_ps->ext_oid.len - 1]); + /* search failed, object id points to unknown object (nosuchname) */ + snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME); + } + } + else if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_VALUE) + { + struct mib_external_node *en; + struct snmp_varbind *vb; + + /* get_value() answer */ + en = msg_ps->ext_mib_node; + + LWIP_ASSERT("invalid length", msg_ps->ext_object_def.v_len <= 0xff); + vb = snmp_varbind_alloc(&msg_ps->ext_oid, + msg_ps->ext_object_def.asn_type, + (u8_t)msg_ps->ext_object_def.v_len); + if (vb != NULL) + { + en->get_value_a(request_id, &msg_ps->ext_object_def, vb->value_len, vb->value); + snmp_varbind_tail_add(&msg_ps->outvb, vb); + msg_ps->state = SNMP_MSG_SEARCH_OBJ; + msg_ps->vb_idx += 1; + } + else + { + en->get_value_pc(request_id, &msg_ps->ext_object_def); + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_getnext_event: couldn't allocate outvb space\n")); + snmp_error_response(msg_ps,SNMP_ES_TOOBIG); + } + } + + while ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) && + (msg_ps->vb_idx < msg_ps->invb.count)) + { + struct mib_node *mn; + struct snmp_obj_id oid; + + if (msg_ps->vb_idx == 0) + { + msg_ps->vb_ptr = msg_ps->invb.head; + } + else + { + msg_ps->vb_ptr = msg_ps->vb_ptr->next; + } + if (snmp_iso_prefix_expand(msg_ps->vb_ptr->ident_len, msg_ps->vb_ptr->ident, &oid)) + { + if (msg_ps->vb_ptr->ident_len > 3) + { + /* can offset ident_len and ident */ + mn = snmp_expand_tree((struct mib_node*)&internet, + msg_ps->vb_ptr->ident_len - 4, + msg_ps->vb_ptr->ident + 4, &oid); + } + else + { + /* can't offset ident_len -4, ident + 4 */ + mn = snmp_expand_tree((struct mib_node*)&internet, 0, NULL, &oid); + } + } + else + { + mn = NULL; + } + if (mn != NULL) + { + if (mn->node_type == MIB_NODE_EX) + { + /* external object */ + struct mib_external_node *en = (struct mib_external_node*)mn; + + msg_ps->state = SNMP_MSG_EXTERNAL_GET_OBJDEF; + /* save en && args in msg_ps!! */ + msg_ps->ext_mib_node = en; + msg_ps->ext_oid = oid; + + en->get_object_def_q(en->addr_inf, request_id, 1, &oid.id[oid.len - 1]); + } + else + { + /* internal object */ + struct obj_def object_def; + struct snmp_varbind *vb; + + msg_ps->state = SNMP_MSG_INTERNAL_GET_OBJDEF; + mn->get_object_def(1, &oid.id[oid.len - 1], &object_def); + + LWIP_ASSERT("invalid length", object_def.v_len <= 0xff); + vb = snmp_varbind_alloc(&oid, object_def.asn_type, (u8_t)object_def.v_len); + if (vb != NULL) + { + msg_ps->state = SNMP_MSG_INTERNAL_GET_VALUE; + mn->get_value(&object_def, object_def.v_len, vb->value); + snmp_varbind_tail_add(&msg_ps->outvb, vb); + msg_ps->state = SNMP_MSG_SEARCH_OBJ; + msg_ps->vb_idx += 1; + } + else + { + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_recv couldn't allocate outvb space\n")); + snmp_error_response(msg_ps,SNMP_ES_TOOBIG); + } + } + } + if (mn == NULL) + { + /* mn == NULL, noSuchName */ + snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME); + } + } + if ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) && + (msg_ps->vb_idx == msg_ps->invb.count)) + { + snmp_ok_response(msg_ps); + } +} + +/** + * Service an internal or external event for SNMP SET. + * + * @param request_id identifies requests from 0 to (SNMP_CONCURRENT_REQUESTS-1) + * @param msg_ps points to the assosicated message process state + */ +static void +snmp_msg_set_event(u8_t request_id, struct snmp_msg_pstat *msg_ps) +{ + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_set_event: msg_ps->state==%"U16_F"\n",(u16_t)msg_ps->state)); + + if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_OBJDEF) + { + struct mib_external_node *en; + struct snmp_name_ptr np; + + /* get_object_def() answer*/ + en = msg_ps->ext_mib_node; + np = msg_ps->ext_name_ptr; + + /* translate answer into a known lifeform */ + en->get_object_def_a(request_id, np.ident_len, np.ident, &msg_ps->ext_object_def); + if (msg_ps->ext_object_def.instance != MIB_OBJECT_NONE) + { + msg_ps->state = SNMP_MSG_EXTERNAL_SET_TEST; + en->set_test_q(request_id, &msg_ps->ext_object_def); + } + else + { + en->get_object_def_pc(request_id, np.ident_len, np.ident); + /* search failed, object id points to unknown object (nosuchname) */ + snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME); + } + } + else if (msg_ps->state == SNMP_MSG_EXTERNAL_SET_TEST) + { + struct mib_external_node *en; + + /* set_test() answer*/ + en = msg_ps->ext_mib_node; + + if (msg_ps->ext_object_def.access & MIB_ACCESS_WRITE) + { + if ((msg_ps->ext_object_def.asn_type == msg_ps->vb_ptr->value_type) && + (en->set_test_a(request_id,&msg_ps->ext_object_def, + msg_ps->vb_ptr->value_len,msg_ps->vb_ptr->value) != 0)) + { + msg_ps->state = SNMP_MSG_SEARCH_OBJ; + msg_ps->vb_idx += 1; + } + else + { + en->set_test_pc(request_id,&msg_ps->ext_object_def); + /* bad value */ + snmp_error_response(msg_ps,SNMP_ES_BADVALUE); + } + } + else + { + en->set_test_pc(request_id,&msg_ps->ext_object_def); + /* object not available for set */ + snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME); + } + } + else if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_OBJDEF_S) + { + struct mib_external_node *en; + struct snmp_name_ptr np; + + /* get_object_def() answer*/ + en = msg_ps->ext_mib_node; + np = msg_ps->ext_name_ptr; + + /* translate answer into a known lifeform */ + en->get_object_def_a(request_id, np.ident_len, np.ident, &msg_ps->ext_object_def); + if (msg_ps->ext_object_def.instance != MIB_OBJECT_NONE) + { + msg_ps->state = SNMP_MSG_EXTERNAL_SET_VALUE; + en->set_value_q(request_id, &msg_ps->ext_object_def, + msg_ps->vb_ptr->value_len,msg_ps->vb_ptr->value); + } + else + { + en->get_object_def_pc(request_id, np.ident_len, np.ident); + /* set_value failed, object has disappeared for some odd reason?? */ + snmp_error_response(msg_ps,SNMP_ES_GENERROR); + } + } + else if (msg_ps->state == SNMP_MSG_EXTERNAL_SET_VALUE) + { + struct mib_external_node *en; + + /** set_value_a() */ + en = msg_ps->ext_mib_node; + en->set_value_a(request_id, &msg_ps->ext_object_def, + msg_ps->vb_ptr->value_len, msg_ps->vb_ptr->value); + + /** @todo use set_value_pc() if toobig */ + msg_ps->state = SNMP_MSG_INTERNAL_SET_VALUE; + msg_ps->vb_idx += 1; + } + + /* test all values before setting */ + while ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) && + (msg_ps->vb_idx < msg_ps->invb.count)) + { + struct mib_node *mn; + struct snmp_name_ptr np; + + if (msg_ps->vb_idx == 0) + { + msg_ps->vb_ptr = msg_ps->invb.head; + } + else + { + msg_ps->vb_ptr = msg_ps->vb_ptr->next; + } + /** test object identifier for .iso.org.dod.internet prefix */ + if (snmp_iso_prefix_tst(msg_ps->vb_ptr->ident_len, msg_ps->vb_ptr->ident)) + { + mn = snmp_search_tree((struct mib_node*)&internet, msg_ps->vb_ptr->ident_len - 4, + msg_ps->vb_ptr->ident + 4, &np); + if (mn != NULL) + { + if (mn->node_type == MIB_NODE_EX) + { + /* external object */ + struct mib_external_node *en = (struct mib_external_node*)mn; + + msg_ps->state = SNMP_MSG_EXTERNAL_GET_OBJDEF; + /* save en && args in msg_ps!! */ + msg_ps->ext_mib_node = en; + msg_ps->ext_name_ptr = np; + + en->get_object_def_q(en->addr_inf, request_id, np.ident_len, np.ident); + } + else + { + /* internal object */ + struct obj_def object_def; + + msg_ps->state = SNMP_MSG_INTERNAL_GET_OBJDEF; + mn->get_object_def(np.ident_len, np.ident, &object_def); + if (object_def.instance != MIB_OBJECT_NONE) + { + mn = mn; + } + else + { + /* search failed, object id points to unknown object (nosuchname) */ + mn = NULL; + } + if (mn != NULL) + { + msg_ps->state = SNMP_MSG_INTERNAL_SET_TEST; + + if (object_def.access & MIB_ACCESS_WRITE) + { + if ((object_def.asn_type == msg_ps->vb_ptr->value_type) && + (mn->set_test(&object_def,msg_ps->vb_ptr->value_len,msg_ps->vb_ptr->value) != 0)) + { + msg_ps->state = SNMP_MSG_SEARCH_OBJ; + msg_ps->vb_idx += 1; + } + else + { + /* bad value */ + snmp_error_response(msg_ps,SNMP_ES_BADVALUE); + } + } + else + { + /* object not available for set */ + snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME); + } + } + } + } + } + else + { + mn = NULL; + } + if (mn == NULL) + { + /* mn == NULL, noSuchName */ + snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME); + } + } + + if ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) && + (msg_ps->vb_idx == msg_ps->invb.count)) + { + msg_ps->vb_idx = 0; + msg_ps->state = SNMP_MSG_INTERNAL_SET_VALUE; + } + + /* set all values "atomically" (be as "atomic" as possible) */ + while ((msg_ps->state == SNMP_MSG_INTERNAL_SET_VALUE) && + (msg_ps->vb_idx < msg_ps->invb.count)) + { + struct mib_node *mn; + struct snmp_name_ptr np; + + if (msg_ps->vb_idx == 0) + { + msg_ps->vb_ptr = msg_ps->invb.head; + } + else + { + msg_ps->vb_ptr = msg_ps->vb_ptr->next; + } + /* skip iso prefix test, was done previously while settesting() */ + mn = snmp_search_tree((struct mib_node*)&internet, msg_ps->vb_ptr->ident_len - 4, + msg_ps->vb_ptr->ident + 4, &np); + /* check if object is still available + (e.g. external hot-plug thingy present?) */ + if (mn != NULL) + { + if (mn->node_type == MIB_NODE_EX) + { + /* external object */ + struct mib_external_node *en = (struct mib_external_node*)mn; + + msg_ps->state = SNMP_MSG_EXTERNAL_GET_OBJDEF_S; + /* save en && args in msg_ps!! */ + msg_ps->ext_mib_node = en; + msg_ps->ext_name_ptr = np; + + en->get_object_def_q(en->addr_inf, request_id, np.ident_len, np.ident); + } + else + { + /* internal object */ + struct obj_def object_def; + + msg_ps->state = SNMP_MSG_INTERNAL_GET_OBJDEF_S; + mn->get_object_def(np.ident_len, np.ident, &object_def); + msg_ps->state = SNMP_MSG_INTERNAL_SET_VALUE; + mn->set_value(&object_def,msg_ps->vb_ptr->value_len,msg_ps->vb_ptr->value); + msg_ps->vb_idx += 1; + } + } + } + if ((msg_ps->state == SNMP_MSG_INTERNAL_SET_VALUE) && + (msg_ps->vb_idx == msg_ps->invb.count)) + { + /* simply echo the input if we can set it + @todo do we need to return the actual value? + e.g. if value is silently modified or behaves sticky? */ + msg_ps->outvb = msg_ps->invb; + msg_ps->invb.head = NULL; + msg_ps->invb.tail = NULL; + msg_ps->invb.count = 0; + snmp_ok_response(msg_ps); + } +} + + +/** + * Handle one internal or external event. + * Called for one async event. (recv external/private answer) + * + * @param request_id identifies requests from 0 to (SNMP_CONCURRENT_REQUESTS-1) + */ +void +snmp_msg_event(u8_t request_id) +{ + struct snmp_msg_pstat *msg_ps; + + if (request_id < SNMP_CONCURRENT_REQUESTS) + { + msg_ps = &msg_input_list[request_id]; + if (msg_ps->rt == SNMP_ASN1_PDU_GET_NEXT_REQ) + { + snmp_msg_getnext_event(request_id, msg_ps); + } + else if (msg_ps->rt == SNMP_ASN1_PDU_GET_REQ) + { + snmp_msg_get_event(request_id, msg_ps); + } + else if(msg_ps->rt == SNMP_ASN1_PDU_SET_REQ) + { + snmp_msg_set_event(request_id, msg_ps); + } + } +} + + +/* lwIP UDP receive callback function */ +static void +snmp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port) +{ + struct snmp_msg_pstat *msg_ps; + u8_t req_idx; + err_t err_ret; + u16_t payload_len = p->tot_len; + u16_t payload_ofs = 0; + u16_t varbind_ofs = 0; + + /* suppress unused argument warning */ + LWIP_UNUSED_ARG(arg); + + /* traverse input message process list, look for SNMP_MSG_EMPTY */ + msg_ps = &msg_input_list[0]; + req_idx = 0; + while ((req_idx < SNMP_CONCURRENT_REQUESTS) && (msg_ps->state != SNMP_MSG_EMPTY)) + { + req_idx++; + msg_ps++; + } + if (req_idx == SNMP_CONCURRENT_REQUESTS) + { + /* exceeding number of concurrent requests */ + pbuf_free(p); + return; + } + + /* accepting request */ + snmp_inc_snmpinpkts(); + /* record used 'protocol control block' */ + msg_ps->pcb = pcb; + /* source address (network order) */ + msg_ps->sip = *addr; + /* source port (host order (lwIP oddity)) */ + msg_ps->sp = port; + + /* check total length, version, community, pdu type */ + err_ret = snmp_pdu_header_check(p, payload_ofs, payload_len, &varbind_ofs, msg_ps); + /* Only accept requests and requests without error (be robust) */ + /* Reject response and trap headers or error requests as input! */ + if ((err_ret != ERR_OK) || + ((msg_ps->rt != SNMP_ASN1_PDU_GET_REQ) && + (msg_ps->rt != SNMP_ASN1_PDU_GET_NEXT_REQ) && + (msg_ps->rt != SNMP_ASN1_PDU_SET_REQ)) || + ((msg_ps->error_status != SNMP_ES_NOERROR) || + (msg_ps->error_index != 0)) ) + { + /* header check failed drop request silently, do not return error! */ + pbuf_free(p); + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_pdu_header_check() failed\n")); + return; + } + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_recv ok, community %s\n", msg_ps->community)); + + /* Builds a list of variable bindings. Copy the varbinds from the pbuf + chain to glue them when these are divided over two or more pbuf's. */ + err_ret = snmp_pdu_dec_varbindlist(p, varbind_ofs, &varbind_ofs, msg_ps); + /* we've decoded the incoming message, release input msg now */ + pbuf_free(p); + if ((err_ret != ERR_OK) || (msg_ps->invb.count == 0)) + { + /* varbind-list decode failed, or varbind list empty. + drop request silently, do not return error! + (errors are only returned for a specific varbind failure) */ + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_pdu_dec_varbindlist() failed\n")); + return; + } + + msg_ps->error_status = SNMP_ES_NOERROR; + msg_ps->error_index = 0; + /* find object for each variable binding */ + msg_ps->state = SNMP_MSG_SEARCH_OBJ; + /* first variable binding from list to inspect */ + msg_ps->vb_idx = 0; + + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_recv varbind cnt=%"U16_F"\n",(u16_t)msg_ps->invb.count)); + + /* handle input event and as much objects as possible in one go */ + snmp_msg_event(req_idx); +} + +/** + * Checks and decodes incoming SNMP message header, logs header errors. + * + * @param p points to pbuf chain of SNMP message (UDP payload) + * @param ofs points to first octet of SNMP message + * @param pdu_len the length of the UDP payload + * @param ofs_ret returns the ofset of the variable bindings + * @param m_stat points to the current message request state return + * @return + * - ERR_OK SNMP header is sane and accepted + * - ERR_ARG SNMP header is either malformed or rejected + */ +static err_t +snmp_pdu_header_check(struct pbuf *p, u16_t ofs, u16_t pdu_len, u16_t *ofs_ret, struct snmp_msg_pstat *m_stat) +{ + err_t derr; + u16_t len, ofs_base; + u8_t len_octets; + u8_t type; + s32_t version; + + ofs_base = ofs; + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); + if ((derr != ERR_OK) || + (pdu_len != (1 + len_octets + len)) || + (type != (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ))) + { + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + ofs += (1 + len_octets); + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); + if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG))) + { + /* can't decode or no integer (version) */ + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, &version); + if (derr != ERR_OK) + { + /* can't decode */ + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + if (version != 0) + { + /* not version 1 */ + snmp_inc_snmpinbadversions(); + return ERR_ARG; + } + ofs += (1 + len_octets + len); + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); + if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR))) + { + /* can't decode or no octet string (community) */ + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + derr = snmp_asn1_dec_raw(p, ofs + 1 + len_octets, len, SNMP_COMMUNITY_STR_LEN, m_stat->community); + if (derr != ERR_OK) + { + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + /* add zero terminator */ + len = ((len < (SNMP_COMMUNITY_STR_LEN))?(len):(SNMP_COMMUNITY_STR_LEN)); + m_stat->community[len] = 0; + m_stat->com_strlen = (u8_t)len; + if (strncmp(snmp_publiccommunity, (const char*)m_stat->community, SNMP_COMMUNITY_STR_LEN) != 0) + { + /** @todo: move this if we need to check more names */ + snmp_inc_snmpinbadcommunitynames(); + snmp_authfail_trap(); + return ERR_ARG; + } + ofs += (1 + len_octets + len); + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); + if (derr != ERR_OK) + { + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + switch(type) + { + case (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_GET_REQ): + /* GetRequest PDU */ + snmp_inc_snmpingetrequests(); + derr = ERR_OK; + break; + case (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_GET_NEXT_REQ): + /* GetNextRequest PDU */ + snmp_inc_snmpingetnexts(); + derr = ERR_OK; + break; + case (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_GET_RESP): + /* GetResponse PDU */ + snmp_inc_snmpingetresponses(); + derr = ERR_ARG; + break; + case (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_SET_REQ): + /* SetRequest PDU */ + snmp_inc_snmpinsetrequests(); + derr = ERR_OK; + break; + case (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_TRAP): + /* Trap PDU */ + snmp_inc_snmpintraps(); + derr = ERR_ARG; + break; + default: + snmp_inc_snmpinasnparseerrs(); + derr = ERR_ARG; + break; + } + if (derr != ERR_OK) + { + /* unsupported input PDU for this agent (no parse error) */ + return ERR_ARG; + } + m_stat->rt = type & 0x1F; + ofs += (1 + len_octets); + if (len != (pdu_len - (ofs - ofs_base))) + { + /* decoded PDU length does not equal actual payload length */ + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); + if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG))) + { + /* can't decode or no integer (request ID) */ + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, &m_stat->rid); + if (derr != ERR_OK) + { + /* can't decode */ + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + ofs += (1 + len_octets + len); + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); + if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG))) + { + /* can't decode or no integer (error-status) */ + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + /* must be noError (0) for incoming requests. + log errors for mib-2 completeness and for debug purposes */ + derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, &m_stat->error_status); + if (derr != ERR_OK) + { + /* can't decode */ + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + switch (m_stat->error_status) + { + case SNMP_ES_TOOBIG: + snmp_inc_snmpintoobigs(); + break; + case SNMP_ES_NOSUCHNAME: + snmp_inc_snmpinnosuchnames(); + break; + case SNMP_ES_BADVALUE: + snmp_inc_snmpinbadvalues(); + break; + case SNMP_ES_READONLY: + snmp_inc_snmpinreadonlys(); + break; + case SNMP_ES_GENERROR: + snmp_inc_snmpingenerrs(); + break; + } + ofs += (1 + len_octets + len); + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); + if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG))) + { + /* can't decode or no integer (error-index) */ + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + /* must be 0 for incoming requests. + decode anyway to catch bad integers (and dirty tricks) */ + derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, &m_stat->error_index); + if (derr != ERR_OK) + { + /* can't decode */ + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + ofs += (1 + len_octets + len); + *ofs_ret = ofs; + return ERR_OK; +} + +static err_t +snmp_pdu_dec_varbindlist(struct pbuf *p, u16_t ofs, u16_t *ofs_ret, struct snmp_msg_pstat *m_stat) +{ + err_t derr; + u16_t len, vb_len; + u8_t len_octets; + u8_t type; + + /* variable binding list */ + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &vb_len); + if ((derr != ERR_OK) || + (type != (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ))) + { + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + ofs += (1 + len_octets); + + /* start with empty list */ + m_stat->invb.count = 0; + m_stat->invb.head = NULL; + m_stat->invb.tail = NULL; + + while (vb_len > 0) + { + struct snmp_obj_id oid, oid_value; + struct snmp_varbind *vb; + + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); + if ((derr != ERR_OK) || + (type != (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)) || + (len == 0) || (len > vb_len)) + { + snmp_inc_snmpinasnparseerrs(); + /* free varbinds (if available) */ + snmp_varbind_list_free(&m_stat->invb); + return ERR_ARG; + } + ofs += (1 + len_octets); + vb_len -= (1 + len_octets); + + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); + if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID))) + { + /* can't decode object name length */ + snmp_inc_snmpinasnparseerrs(); + /* free varbinds (if available) */ + snmp_varbind_list_free(&m_stat->invb); + return ERR_ARG; + } + derr = snmp_asn1_dec_oid(p, ofs + 1 + len_octets, len, &oid); + if (derr != ERR_OK) + { + /* can't decode object name */ + snmp_inc_snmpinasnparseerrs(); + /* free varbinds (if available) */ + snmp_varbind_list_free(&m_stat->invb); + return ERR_ARG; + } + ofs += (1 + len_octets + len); + vb_len -= (1 + len_octets + len); + + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); + if (derr != ERR_OK) + { + /* can't decode object value length */ + snmp_inc_snmpinasnparseerrs(); + /* free varbinds (if available) */ + snmp_varbind_list_free(&m_stat->invb); + return ERR_ARG; + } + + switch (type) + { + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG): + vb = snmp_varbind_alloc(&oid, type, sizeof(s32_t)); + if (vb != NULL) + { + s32_t *vptr = (s32_t*)vb->value; + + derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, vptr); + snmp_varbind_tail_add(&m_stat->invb, vb); + } + else + { + derr = ERR_ARG; + } + break; + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS): + vb = snmp_varbind_alloc(&oid, type, sizeof(u32_t)); + if (vb != NULL) + { + u32_t *vptr = (u32_t*)vb->value; + + derr = snmp_asn1_dec_u32t(p, ofs + 1 + len_octets, len, vptr); + snmp_varbind_tail_add(&m_stat->invb, vb); + } + else + { + derr = ERR_ARG; + } + break; + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_OPAQUE): + LWIP_ASSERT("invalid length", len <= 0xff); + vb = snmp_varbind_alloc(&oid, type, (u8_t)len); + if (vb != NULL) + { + derr = snmp_asn1_dec_raw(p, ofs + 1 + len_octets, len, vb->value_len, (u8_t*)vb->value); + snmp_varbind_tail_add(&m_stat->invb, vb); + } + else + { + derr = ERR_ARG; + } + break; + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_NUL): + vb = snmp_varbind_alloc(&oid, type, 0); + if (vb != NULL) + { + snmp_varbind_tail_add(&m_stat->invb, vb); + derr = ERR_OK; + } + else + { + derr = ERR_ARG; + } + break; + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID): + derr = snmp_asn1_dec_oid(p, ofs + 1 + len_octets, len, &oid_value); + if (derr == ERR_OK) + { + vb = snmp_varbind_alloc(&oid, type, oid_value.len * sizeof(s32_t)); + if (vb != NULL) + { + u8_t i = oid_value.len; + s32_t *vptr = (s32_t*)vb->value; + + while(i > 0) + { + i--; + vptr[i] = oid_value.id[i]; + } + snmp_varbind_tail_add(&m_stat->invb, vb); + derr = ERR_OK; + } + else + { + derr = ERR_ARG; + } + } + break; + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR): + if (len == 4) + { + /* must be exactly 4 octets! */ + vb = snmp_varbind_alloc(&oid, type, 4); + if (vb != NULL) + { + derr = snmp_asn1_dec_raw(p, ofs + 1 + len_octets, len, vb->value_len, (u8_t*)vb->value); + snmp_varbind_tail_add(&m_stat->invb, vb); + } + else + { + derr = ERR_ARG; + } + } + else + { + derr = ERR_ARG; + } + break; + default: + derr = ERR_ARG; + break; + } + if (derr != ERR_OK) + { + snmp_inc_snmpinasnparseerrs(); + /* free varbinds (if available) */ + snmp_varbind_list_free(&m_stat->invb); + return ERR_ARG; + } + ofs += (1 + len_octets + len); + vb_len -= (1 + len_octets + len); + } + + if (m_stat->rt == SNMP_ASN1_PDU_SET_REQ) + { + snmp_add_snmpintotalsetvars(m_stat->invb.count); + } + else + { + snmp_add_snmpintotalreqvars(m_stat->invb.count); + } + + *ofs_ret = ofs; + return ERR_OK; +} + +struct snmp_varbind* +snmp_varbind_alloc(struct snmp_obj_id *oid, u8_t type, u8_t len) +{ + struct snmp_varbind *vb; + + vb = (struct snmp_varbind *)memp_malloc(MEMP_SNMP_VARBIND); + if (vb != NULL) + { + u8_t i; + + vb->next = NULL; + vb->prev = NULL; + i = oid->len; + vb->ident_len = i; + if (i > 0) + { + LWIP_ASSERT("SNMP_MAX_TREE_DEPTH is configured too low", i <= SNMP_MAX_TREE_DEPTH); + /* allocate array of s32_t for our object identifier */ + vb->ident = (s32_t*)memp_malloc(MEMP_SNMP_VALUE); + if (vb->ident == NULL) + { + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_varbind_alloc: couldn't allocate ident value space\n")); + memp_free(MEMP_SNMP_VARBIND, vb); + return NULL; + } + while(i > 0) + { + i--; + vb->ident[i] = oid->id[i]; + } + } + else + { + /* i == 0, pass zero length object identifier */ + vb->ident = NULL; + } + vb->value_type = type; + vb->value_len = len; + if (len > 0) + { + LWIP_ASSERT("SNMP_MAX_OCTET_STRING_LEN is configured too low", vb->value_len <= SNMP_MAX_VALUE_SIZE); + /* allocate raw bytes for our object value */ + vb->value = memp_malloc(MEMP_SNMP_VALUE); + if (vb->value == NULL) + { + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_varbind_alloc: couldn't allocate value space\n")); + if (vb->ident != NULL) + { + memp_free(MEMP_SNMP_VALUE, vb->ident); + } + memp_free(MEMP_SNMP_VARBIND, vb); + return NULL; + } + } + else + { + /* ASN1_NUL type, or zero length ASN1_OC_STR */ + vb->value = NULL; + } + } + else + { + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_varbind_alloc: couldn't allocate varbind space\n")); + } + return vb; +} + +void +snmp_varbind_free(struct snmp_varbind *vb) +{ + if (vb->value != NULL ) + { + memp_free(MEMP_SNMP_VALUE, vb->value); + } + if (vb->ident != NULL ) + { + memp_free(MEMP_SNMP_VALUE, vb->ident); + } + memp_free(MEMP_SNMP_VARBIND, vb); +} + +void +snmp_varbind_list_free(struct snmp_varbind_root *root) +{ + struct snmp_varbind *vb, *prev; + + vb = root->tail; + while ( vb != NULL ) + { + prev = vb->prev; + snmp_varbind_free(vb); + vb = prev; + } + root->count = 0; + root->head = NULL; + root->tail = NULL; +} + +void +snmp_varbind_tail_add(struct snmp_varbind_root *root, struct snmp_varbind *vb) +{ + if (root->count == 0) + { + /* add first varbind to list */ + root->head = vb; + root->tail = vb; + } + else + { + /* add nth varbind to list tail */ + root->tail->next = vb; + vb->prev = root->tail; + root->tail = vb; + } + root->count += 1; +} + +struct snmp_varbind* +snmp_varbind_tail_remove(struct snmp_varbind_root *root) +{ + struct snmp_varbind* vb; + + if (root->count > 0) + { + /* remove tail varbind */ + vb = root->tail; + root->tail = vb->prev; + vb->prev->next = NULL; + root->count -= 1; + } + else + { + /* nothing to remove */ + vb = NULL; + } + return vb; +} + +#endif /* LWIP_SNMP */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/core/snmp/msg_out.c b/component/common/network/lwip/lwip_v1.4.1/src/core/snmp/msg_out.c new file mode 100644 index 0000000..485f076 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/core/snmp/msg_out.c @@ -0,0 +1,674 @@ +/** + * @file + * SNMP output message processing (RFC1157). + * + * Output responses and traps are build in two passes: + * + * Pass 0: iterate over the output message backwards to determine encoding lengths + * Pass 1: the actual forward encoding of internal form into ASN1 + * + * The single-pass encoding method described by Comer & Stevens + * requires extra buffer space and copying for reversal of the packet. + * The buffer requirement can be prohibitively large for big payloads + * (>= 484) therefore we use the two encoding passes. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * Author: Christiaan Simons + */ + +#include "lwip/opt.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/udp.h" +#include "lwip/netif.h" +#include "lwip/snmp.h" +#include "lwip/snmp_asn1.h" +#include "lwip/snmp_msg.h" + +struct snmp_trap_dst +{ + /* destination IP address in network order */ + ip_addr_t dip; + /* set to 0 when disabled, >0 when enabled */ + u8_t enable; +}; +struct snmp_trap_dst trap_dst[SNMP_TRAP_DESTINATIONS]; + +/** TRAP message structure */ +struct snmp_msg_trap trap_msg; + +static u16_t snmp_resp_header_sum(struct snmp_msg_pstat *m_stat, u16_t vb_len); +static u16_t snmp_trap_header_sum(struct snmp_msg_trap *m_trap, u16_t vb_len); +static u16_t snmp_varbind_list_sum(struct snmp_varbind_root *root); + +static u16_t snmp_resp_header_enc(struct snmp_msg_pstat *m_stat, struct pbuf *p); +static u16_t snmp_trap_header_enc(struct snmp_msg_trap *m_trap, struct pbuf *p); +static u16_t snmp_varbind_list_enc(struct snmp_varbind_root *root, struct pbuf *p, u16_t ofs); + +/** + * Sets enable switch for this trap destination. + * @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1 + * @param enable switch if 0 destination is disabled >0 enabled. + */ +void +snmp_trap_dst_enable(u8_t dst_idx, u8_t enable) +{ + if (dst_idx < SNMP_TRAP_DESTINATIONS) + { + trap_dst[dst_idx].enable = enable; + } +} + +/** + * Sets IPv4 address for this trap destination. + * @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1 + * @param dst IPv4 address in host order. + */ +void +snmp_trap_dst_ip_set(u8_t dst_idx, ip_addr_t *dst) +{ + if (dst_idx < SNMP_TRAP_DESTINATIONS) + { + ip_addr_set(&trap_dst[dst_idx].dip, dst); + } +} + +/** + * Sends a 'getresponse' message to the request originator. + * + * @param m_stat points to the current message request state source + * @return ERR_OK when success, ERR_MEM if we're out of memory + * + * @note the caller is responsible for filling in outvb in the m_stat + * and provide error-status and index (except for tooBig errors) ... + */ +err_t +snmp_send_response(struct snmp_msg_pstat *m_stat) +{ + struct snmp_varbind_root emptyvb = {NULL, NULL, 0, 0, 0}; + struct pbuf *p; + u16_t tot_len; + err_t err; + + /* pass 0, calculate length fields */ + tot_len = snmp_varbind_list_sum(&m_stat->outvb); + tot_len = snmp_resp_header_sum(m_stat, tot_len); + + /* try allocating pbuf(s) for complete response */ + p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_POOL); + if (p == NULL) + { + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_snd_response() tooBig\n")); + + /* can't construct reply, return error-status tooBig */ + m_stat->error_status = SNMP_ES_TOOBIG; + m_stat->error_index = 0; + /* pass 0, recalculate lengths, for empty varbind-list */ + tot_len = snmp_varbind_list_sum(&emptyvb); + tot_len = snmp_resp_header_sum(m_stat, tot_len); + /* retry allocation once for header and empty varbind-list */ + p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_POOL); + } + if (p != NULL) + { + /* first pbuf alloc try or retry alloc success */ + u16_t ofs; + + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_snd_response() p != NULL\n")); + + /* pass 1, size error, encode packet ino the pbuf(s) */ + ofs = snmp_resp_header_enc(m_stat, p); + snmp_varbind_list_enc(&m_stat->outvb, p, ofs); + + switch (m_stat->error_status) + { + case SNMP_ES_TOOBIG: + snmp_inc_snmpouttoobigs(); + break; + case SNMP_ES_NOSUCHNAME: + snmp_inc_snmpoutnosuchnames(); + break; + case SNMP_ES_BADVALUE: + snmp_inc_snmpoutbadvalues(); + break; + case SNMP_ES_GENERROR: + snmp_inc_snmpoutgenerrs(); + break; + } + snmp_inc_snmpoutgetresponses(); + snmp_inc_snmpoutpkts(); + + /** @todo do we need separate rx and tx pcbs for threaded case? */ + /** connect to the originating source */ + udp_connect(m_stat->pcb, &m_stat->sip, m_stat->sp); + err = udp_send(m_stat->pcb, p); + if (err == ERR_MEM) + { + /** @todo release some memory, retry and return tooBig? tooMuchHassle? */ + err = ERR_MEM; + } + else + { + err = ERR_OK; + } + /** disassociate remote address and port with this pcb */ + udp_disconnect(m_stat->pcb); + + pbuf_free(p); + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_snd_response() done\n")); + return err; + } + else + { + /* first pbuf alloc try or retry alloc failed + very low on memory, couldn't return tooBig */ + return ERR_MEM; + } +} + + +/** + * Sends an generic or enterprise specific trap message. + * + * @param generic_trap is the trap code + * @param eoid points to enterprise object identifier + * @param specific_trap used for enterprise traps when generic_trap == 6 + * @return ERR_OK when success, ERR_MEM if we're out of memory + * + * @note the caller is responsible for filling in outvb in the trap_msg + * @note the use of the enterpise identifier field + * is per RFC1215. + * Use .iso.org.dod.internet.mgmt.mib-2.snmp for generic traps + * and .iso.org.dod.internet.private.enterprises.yourenterprise + * (sysObjectID) for specific traps. + */ +err_t +snmp_send_trap(s8_t generic_trap, struct snmp_obj_id *eoid, s32_t specific_trap) +{ + struct snmp_trap_dst *td; + struct netif *dst_if; + ip_addr_t dst_ip; + struct pbuf *p; + u16_t i,tot_len; + + for (i=0, td = &trap_dst[0]; ienable != 0) && !ip_addr_isany(&td->dip)) + { + /* network order trap destination */ + ip_addr_copy(trap_msg.dip, td->dip); + /* lookup current source address for this dst */ + dst_if = ip_route(&td->dip); + ip_addr_copy(dst_ip, dst_if->ip_addr); + /* @todo: what about IPv6? */ + trap_msg.sip_raw[0] = ip4_addr1(&dst_ip); + trap_msg.sip_raw[1] = ip4_addr2(&dst_ip); + trap_msg.sip_raw[2] = ip4_addr3(&dst_ip); + trap_msg.sip_raw[3] = ip4_addr4(&dst_ip); + trap_msg.gen_trap = generic_trap; + trap_msg.spc_trap = specific_trap; + if (generic_trap == SNMP_GENTRAP_ENTERPRISESPC) + { + /* enterprise-Specific trap */ + trap_msg.enterprise = eoid; + } + else + { + /* generic (MIB-II) trap */ + snmp_get_snmpgrpid_ptr(&trap_msg.enterprise); + } + snmp_get_sysuptime(&trap_msg.ts); + + /* pass 0, calculate length fields */ + tot_len = snmp_varbind_list_sum(&trap_msg.outvb); + tot_len = snmp_trap_header_sum(&trap_msg, tot_len); + + /* allocate pbuf(s) */ + p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_POOL); + if (p != NULL) + { + u16_t ofs; + + /* pass 1, encode packet ino the pbuf(s) */ + ofs = snmp_trap_header_enc(&trap_msg, p); + snmp_varbind_list_enc(&trap_msg.outvb, p, ofs); + + snmp_inc_snmpouttraps(); + snmp_inc_snmpoutpkts(); + + /** send to the TRAP destination */ + udp_sendto(trap_msg.pcb, p, &trap_msg.dip, SNMP_TRAP_PORT); + + pbuf_free(p); + } + else + { + return ERR_MEM; + } + } + } + return ERR_OK; +} + +void +snmp_coldstart_trap(void) +{ + trap_msg.outvb.head = NULL; + trap_msg.outvb.tail = NULL; + trap_msg.outvb.count = 0; + snmp_send_trap(SNMP_GENTRAP_COLDSTART, NULL, 0); +} + +void +snmp_authfail_trap(void) +{ + u8_t enable; + snmp_get_snmpenableauthentraps(&enable); + if (enable == 1) + { + trap_msg.outvb.head = NULL; + trap_msg.outvb.tail = NULL; + trap_msg.outvb.count = 0; + snmp_send_trap(SNMP_GENTRAP_AUTHFAIL, NULL, 0); + } +} + +/** + * Sums response header field lengths from tail to head and + * returns resp_header_lengths for second encoding pass. + * + * @param vb_len varbind-list length + * @param rhl points to returned header lengths + * @return the required lenght for encoding the response header + */ +static u16_t +snmp_resp_header_sum(struct snmp_msg_pstat *m_stat, u16_t vb_len) +{ + u16_t tot_len; + struct snmp_resp_header_lengths *rhl; + + rhl = &m_stat->rhl; + tot_len = vb_len; + snmp_asn1_enc_s32t_cnt(m_stat->error_index, &rhl->erridxlen); + snmp_asn1_enc_length_cnt(rhl->erridxlen, &rhl->erridxlenlen); + tot_len += 1 + rhl->erridxlenlen + rhl->erridxlen; + + snmp_asn1_enc_s32t_cnt(m_stat->error_status, &rhl->errstatlen); + snmp_asn1_enc_length_cnt(rhl->errstatlen, &rhl->errstatlenlen); + tot_len += 1 + rhl->errstatlenlen + rhl->errstatlen; + + snmp_asn1_enc_s32t_cnt(m_stat->rid, &rhl->ridlen); + snmp_asn1_enc_length_cnt(rhl->ridlen, &rhl->ridlenlen); + tot_len += 1 + rhl->ridlenlen + rhl->ridlen; + + rhl->pdulen = tot_len; + snmp_asn1_enc_length_cnt(rhl->pdulen, &rhl->pdulenlen); + tot_len += 1 + rhl->pdulenlen; + + rhl->comlen = m_stat->com_strlen; + snmp_asn1_enc_length_cnt(rhl->comlen, &rhl->comlenlen); + tot_len += 1 + rhl->comlenlen + rhl->comlen; + + snmp_asn1_enc_s32t_cnt(snmp_version, &rhl->verlen); + snmp_asn1_enc_length_cnt(rhl->verlen, &rhl->verlenlen); + tot_len += 1 + rhl->verlen + rhl->verlenlen; + + rhl->seqlen = tot_len; + snmp_asn1_enc_length_cnt(rhl->seqlen, &rhl->seqlenlen); + tot_len += 1 + rhl->seqlenlen; + + return tot_len; +} + +/** + * Sums trap header field lengths from tail to head and + * returns trap_header_lengths for second encoding pass. + * + * @param vb_len varbind-list length + * @param thl points to returned header lengths + * @return the required lenght for encoding the trap header + */ +static u16_t +snmp_trap_header_sum(struct snmp_msg_trap *m_trap, u16_t vb_len) +{ + u16_t tot_len; + struct snmp_trap_header_lengths *thl; + + thl = &m_trap->thl; + tot_len = vb_len; + + snmp_asn1_enc_u32t_cnt(m_trap->ts, &thl->tslen); + snmp_asn1_enc_length_cnt(thl->tslen, &thl->tslenlen); + tot_len += 1 + thl->tslen + thl->tslenlen; + + snmp_asn1_enc_s32t_cnt(m_trap->spc_trap, &thl->strplen); + snmp_asn1_enc_length_cnt(thl->strplen, &thl->strplenlen); + tot_len += 1 + thl->strplen + thl->strplenlen; + + snmp_asn1_enc_s32t_cnt(m_trap->gen_trap, &thl->gtrplen); + snmp_asn1_enc_length_cnt(thl->gtrplen, &thl->gtrplenlen); + tot_len += 1 + thl->gtrplen + thl->gtrplenlen; + + thl->aaddrlen = 4; + snmp_asn1_enc_length_cnt(thl->aaddrlen, &thl->aaddrlenlen); + tot_len += 1 + thl->aaddrlen + thl->aaddrlenlen; + + snmp_asn1_enc_oid_cnt(m_trap->enterprise->len, &m_trap->enterprise->id[0], &thl->eidlen); + snmp_asn1_enc_length_cnt(thl->eidlen, &thl->eidlenlen); + tot_len += 1 + thl->eidlen + thl->eidlenlen; + + thl->pdulen = tot_len; + snmp_asn1_enc_length_cnt(thl->pdulen, &thl->pdulenlen); + tot_len += 1 + thl->pdulenlen; + + thl->comlen = sizeof(snmp_publiccommunity) - 1; + snmp_asn1_enc_length_cnt(thl->comlen, &thl->comlenlen); + tot_len += 1 + thl->comlenlen + thl->comlen; + + snmp_asn1_enc_s32t_cnt(snmp_version, &thl->verlen); + snmp_asn1_enc_length_cnt(thl->verlen, &thl->verlenlen); + tot_len += 1 + thl->verlen + thl->verlenlen; + + thl->seqlen = tot_len; + snmp_asn1_enc_length_cnt(thl->seqlen, &thl->seqlenlen); + tot_len += 1 + thl->seqlenlen; + + return tot_len; +} + +/** + * Sums varbind lengths from tail to head and + * annotates lengths in varbind for second encoding pass. + * + * @param root points to the root of the variable binding list + * @return the required lenght for encoding the variable bindings + */ +static u16_t +snmp_varbind_list_sum(struct snmp_varbind_root *root) +{ + struct snmp_varbind *vb; + u32_t *uint_ptr; + s32_t *sint_ptr; + u16_t tot_len; + + tot_len = 0; + vb = root->tail; + while ( vb != NULL ) + { + /* encoded value lenght depends on type */ + switch (vb->value_type) + { + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG): + sint_ptr = (s32_t*)vb->value; + snmp_asn1_enc_s32t_cnt(*sint_ptr, &vb->vlen); + break; + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS): + uint_ptr = (u32_t*)vb->value; + snmp_asn1_enc_u32t_cnt(*uint_ptr, &vb->vlen); + break; + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR): + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_NUL): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_OPAQUE): + vb->vlen = vb->value_len; + break; + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID): + sint_ptr = (s32_t*)vb->value; + snmp_asn1_enc_oid_cnt(vb->value_len / sizeof(s32_t), sint_ptr, &vb->vlen); + break; + default: + /* unsupported type */ + vb->vlen = 0; + break; + }; + /* encoding length of value length field */ + snmp_asn1_enc_length_cnt(vb->vlen, &vb->vlenlen); + snmp_asn1_enc_oid_cnt(vb->ident_len, vb->ident, &vb->olen); + snmp_asn1_enc_length_cnt(vb->olen, &vb->olenlen); + + vb->seqlen = 1 + vb->vlenlen + vb->vlen; + vb->seqlen += 1 + vb->olenlen + vb->olen; + snmp_asn1_enc_length_cnt(vb->seqlen, &vb->seqlenlen); + + /* varbind seq */ + tot_len += 1 + vb->seqlenlen + vb->seqlen; + + vb = vb->prev; + } + + /* varbind-list seq */ + root->seqlen = tot_len; + snmp_asn1_enc_length_cnt(root->seqlen, &root->seqlenlen); + tot_len += 1 + root->seqlenlen; + + return tot_len; +} + +/** + * Encodes response header from head to tail. + */ +static u16_t +snmp_resp_header_enc(struct snmp_msg_pstat *m_stat, struct pbuf *p) +{ + u16_t ofs; + + ofs = 0; + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_stat->rhl.seqlen); + ofs += m_stat->rhl.seqlenlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_stat->rhl.verlen); + ofs += m_stat->rhl.verlenlen; + snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.verlen, snmp_version); + ofs += m_stat->rhl.verlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_stat->rhl.comlen); + ofs += m_stat->rhl.comlenlen; + snmp_asn1_enc_raw(p, ofs, m_stat->rhl.comlen, m_stat->community); + ofs += m_stat->rhl.comlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_GET_RESP)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_stat->rhl.pdulen); + ofs += m_stat->rhl.pdulenlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_stat->rhl.ridlen); + ofs += m_stat->rhl.ridlenlen; + snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.ridlen, m_stat->rid); + ofs += m_stat->rhl.ridlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_stat->rhl.errstatlen); + ofs += m_stat->rhl.errstatlenlen; + snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.errstatlen, m_stat->error_status); + ofs += m_stat->rhl.errstatlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_stat->rhl.erridxlen); + ofs += m_stat->rhl.erridxlenlen; + snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.erridxlen, m_stat->error_index); + ofs += m_stat->rhl.erridxlen; + + return ofs; +} + +/** + * Encodes trap header from head to tail. + */ +static u16_t +snmp_trap_header_enc(struct snmp_msg_trap *m_trap, struct pbuf *p) +{ + u16_t ofs; + + ofs = 0; + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_trap->thl.seqlen); + ofs += m_trap->thl.seqlenlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_trap->thl.verlen); + ofs += m_trap->thl.verlenlen; + snmp_asn1_enc_s32t(p, ofs, m_trap->thl.verlen, snmp_version); + ofs += m_trap->thl.verlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_trap->thl.comlen); + ofs += m_trap->thl.comlenlen; + snmp_asn1_enc_raw(p, ofs, m_trap->thl.comlen, (u8_t *)&snmp_publiccommunity[0]); + ofs += m_trap->thl.comlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_TRAP)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_trap->thl.pdulen); + ofs += m_trap->thl.pdulenlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_trap->thl.eidlen); + ofs += m_trap->thl.eidlenlen; + snmp_asn1_enc_oid(p, ofs, m_trap->enterprise->len, &m_trap->enterprise->id[0]); + ofs += m_trap->thl.eidlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_trap->thl.aaddrlen); + ofs += m_trap->thl.aaddrlenlen; + snmp_asn1_enc_raw(p, ofs, m_trap->thl.aaddrlen, &m_trap->sip_raw[0]); + ofs += m_trap->thl.aaddrlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_trap->thl.gtrplen); + ofs += m_trap->thl.gtrplenlen; + snmp_asn1_enc_u32t(p, ofs, m_trap->thl.gtrplen, m_trap->gen_trap); + ofs += m_trap->thl.gtrplen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_trap->thl.strplen); + ofs += m_trap->thl.strplenlen; + snmp_asn1_enc_u32t(p, ofs, m_trap->thl.strplen, m_trap->spc_trap); + ofs += m_trap->thl.strplen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_trap->thl.tslen); + ofs += m_trap->thl.tslenlen; + snmp_asn1_enc_u32t(p, ofs, m_trap->thl.tslen, m_trap->ts); + ofs += m_trap->thl.tslen; + + return ofs; +} + +/** + * Encodes varbind list from head to tail. + */ +static u16_t +snmp_varbind_list_enc(struct snmp_varbind_root *root, struct pbuf *p, u16_t ofs) +{ + struct snmp_varbind *vb; + s32_t *sint_ptr; + u32_t *uint_ptr; + u8_t *raw_ptr; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, root->seqlen); + ofs += root->seqlenlen; + + vb = root->head; + while ( vb != NULL ) + { + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, vb->seqlen); + ofs += vb->seqlenlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, vb->olen); + ofs += vb->olenlen; + snmp_asn1_enc_oid(p, ofs, vb->ident_len, &vb->ident[0]); + ofs += vb->olen; + + snmp_asn1_enc_type(p, ofs, vb->value_type); + ofs += 1; + snmp_asn1_enc_length(p, ofs, vb->vlen); + ofs += vb->vlenlen; + + switch (vb->value_type) + { + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG): + sint_ptr = (s32_t*)vb->value; + snmp_asn1_enc_s32t(p, ofs, vb->vlen, *sint_ptr); + break; + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS): + uint_ptr = (u32_t*)vb->value; + snmp_asn1_enc_u32t(p, ofs, vb->vlen, *uint_ptr); + break; + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_OPAQUE): + raw_ptr = (u8_t*)vb->value; + snmp_asn1_enc_raw(p, ofs, vb->vlen, raw_ptr); + break; + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_NUL): + break; + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID): + sint_ptr = (s32_t*)vb->value; + snmp_asn1_enc_oid(p, ofs, vb->value_len / sizeof(s32_t), sint_ptr); + break; + default: + /* unsupported type */ + break; + }; + ofs += vb->vlen; + vb = vb->next; + } + return ofs; +} + +#endif /* LWIP_SNMP */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/core/stats.c b/component/common/network/lwip/lwip_v1.4.1/src/core/stats.c new file mode 100644 index 0000000..8ea8249 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/core/stats.c @@ -0,0 +1,176 @@ +/** + * @file + * Statistics module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_STATS /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/stats.h" +#include "lwip/mem.h" + +#include + +struct stats_ lwip_stats; + +void stats_init(void) +{ +#ifdef LWIP_DEBUG +#if MEMP_STATS + const char * memp_names[] = { +#define LWIP_MEMPOOL(name,num,size,desc) desc, +#include "lwip/memp_std.h" + }; + int i; + for (i = 0; i < MEMP_MAX; i++) { + lwip_stats.memp[i].name = memp_names[i]; + } +#endif /* MEMP_STATS */ +#if MEM_STATS + lwip_stats.mem.name = "MEM"; +#endif /* MEM_STATS */ +#endif /* LWIP_DEBUG */ +} + +#if LWIP_STATS_DISPLAY +void +stats_display_proto(struct stats_proto *proto, const char *name) +{ + LWIP_PLATFORM_DIAG(("\n%s\n\t", name)); + LWIP_PLATFORM_DIAG(("xmit: %"STAT_COUNTER_F"\n\t", proto->xmit)); + LWIP_PLATFORM_DIAG(("recv: %"STAT_COUNTER_F"\n\t", proto->recv)); + LWIP_PLATFORM_DIAG(("fw: %"STAT_COUNTER_F"\n\t", proto->fw)); + LWIP_PLATFORM_DIAG(("drop: %"STAT_COUNTER_F"\n\t", proto->drop)); + LWIP_PLATFORM_DIAG(("chkerr: %"STAT_COUNTER_F"\n\t", proto->chkerr)); + LWIP_PLATFORM_DIAG(("lenerr: %"STAT_COUNTER_F"\n\t", proto->lenerr)); + LWIP_PLATFORM_DIAG(("memerr: %"STAT_COUNTER_F"\n\t", proto->memerr)); + LWIP_PLATFORM_DIAG(("rterr: %"STAT_COUNTER_F"\n\t", proto->rterr)); + LWIP_PLATFORM_DIAG(("proterr: %"STAT_COUNTER_F"\n\t", proto->proterr)); + LWIP_PLATFORM_DIAG(("opterr: %"STAT_COUNTER_F"\n\t", proto->opterr)); + LWIP_PLATFORM_DIAG(("err: %"STAT_COUNTER_F"\n\t", proto->err)); + LWIP_PLATFORM_DIAG(("cachehit: %"STAT_COUNTER_F"\n", proto->cachehit)); +} + +#if IGMP_STATS +void +stats_display_igmp(struct stats_igmp *igmp) +{ + LWIP_PLATFORM_DIAG(("\nIGMP\n\t")); + LWIP_PLATFORM_DIAG(("xmit: %"STAT_COUNTER_F"\n\t", igmp->xmit)); + LWIP_PLATFORM_DIAG(("recv: %"STAT_COUNTER_F"\n\t", igmp->recv)); + LWIP_PLATFORM_DIAG(("drop: %"STAT_COUNTER_F"\n\t", igmp->drop)); + LWIP_PLATFORM_DIAG(("chkerr: %"STAT_COUNTER_F"\n\t", igmp->chkerr)); + LWIP_PLATFORM_DIAG(("lenerr: %"STAT_COUNTER_F"\n\t", igmp->lenerr)); + LWIP_PLATFORM_DIAG(("memerr: %"STAT_COUNTER_F"\n\t", igmp->memerr)); + LWIP_PLATFORM_DIAG(("proterr: %"STAT_COUNTER_F"\n\t", igmp->proterr)); + LWIP_PLATFORM_DIAG(("rx_v1: %"STAT_COUNTER_F"\n\t", igmp->rx_v1)); + LWIP_PLATFORM_DIAG(("rx_group: %"STAT_COUNTER_F"\n", igmp->rx_group)); + LWIP_PLATFORM_DIAG(("rx_general: %"STAT_COUNTER_F"\n", igmp->rx_general)); + LWIP_PLATFORM_DIAG(("rx_report: %"STAT_COUNTER_F"\n\t", igmp->rx_report)); + LWIP_PLATFORM_DIAG(("tx_join: %"STAT_COUNTER_F"\n\t", igmp->tx_join)); + LWIP_PLATFORM_DIAG(("tx_leave: %"STAT_COUNTER_F"\n\t", igmp->tx_leave)); + LWIP_PLATFORM_DIAG(("tx_report: %"STAT_COUNTER_F"\n\t", igmp->tx_report)); +} +#endif /* IGMP_STATS */ + +#if MEM_STATS || MEMP_STATS +void +stats_display_mem(struct stats_mem *mem, const char *name) +{ + LWIP_PLATFORM_DIAG(("\nMEM %s\n\t", name)); + LWIP_PLATFORM_DIAG(("avail: %"U32_F"\n\t", (u32_t)mem->avail)); + LWIP_PLATFORM_DIAG(("used: %"U32_F"\n\t", (u32_t)mem->used)); + LWIP_PLATFORM_DIAG(("max: %"U32_F"\n\t", (u32_t)mem->max)); + LWIP_PLATFORM_DIAG(("err: %"U32_F"\n", (u32_t)mem->err)); +} + +#if MEMP_STATS +void +stats_display_memp(struct stats_mem *mem, int index) +{ + char * memp_names[] = { +#define LWIP_MEMPOOL(name,num,size,desc) desc, +#include "lwip/memp_std.h" + }; + if(index < MEMP_MAX) { + stats_display_mem(mem, memp_names[index]); + } +} +#endif /* MEMP_STATS */ +#endif /* MEM_STATS || MEMP_STATS */ + +#if SYS_STATS +void +stats_display_sys(struct stats_sys *sys) +{ + LWIP_PLATFORM_DIAG(("\nSYS\n\t")); + LWIP_PLATFORM_DIAG(("sem.used: %"U32_F"\n\t", (u32_t)sys->sem.used)); + LWIP_PLATFORM_DIAG(("sem.max: %"U32_F"\n\t", (u32_t)sys->sem.max)); + LWIP_PLATFORM_DIAG(("sem.err: %"U32_F"\n\t", (u32_t)sys->sem.err)); + LWIP_PLATFORM_DIAG(("mutex.used: %"U32_F"\n\t", (u32_t)sys->mutex.used)); + LWIP_PLATFORM_DIAG(("mutex.max: %"U32_F"\n\t", (u32_t)sys->mutex.max)); + LWIP_PLATFORM_DIAG(("mutex.err: %"U32_F"\n\t", (u32_t)sys->mutex.err)); + LWIP_PLATFORM_DIAG(("mbox.used: %"U32_F"\n\t", (u32_t)sys->mbox.used)); + LWIP_PLATFORM_DIAG(("mbox.max: %"U32_F"\n\t", (u32_t)sys->mbox.max)); + LWIP_PLATFORM_DIAG(("mbox.err: %"U32_F"\n\t", (u32_t)sys->mbox.err)); +} +#endif /* SYS_STATS */ + +void +stats_display(void) +{ + s16_t i; + + LINK_STATS_DISPLAY(); + ETHARP_STATS_DISPLAY(); + IPFRAG_STATS_DISPLAY(); + IP_STATS_DISPLAY(); + IGMP_STATS_DISPLAY(); + ICMP_STATS_DISPLAY(); + UDP_STATS_DISPLAY(); + TCP_STATS_DISPLAY(); + MEM_STATS_DISPLAY(); + for (i = 0; i < MEMP_MAX; i++) { + MEMP_STATS_DISPLAY(i); + } + SYS_STATS_DISPLAY(); +} +#endif /* LWIP_STATS_DISPLAY */ + +#endif /* LWIP_STATS */ + diff --git a/component/common/network/lwip/lwip_v1.4.1/src/core/sys.c b/component/common/network/lwip/lwip_v1.4.1/src/core/sys.c new file mode 100644 index 0000000..f177737 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/core/sys.c @@ -0,0 +1,68 @@ +/** + * @file + * lwIP Operating System abstraction + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/sys.h" + +/* Most of the functions defined in sys.h must be implemented in the + * architecture-dependent file sys_arch.c */ + +#if !NO_SYS + +#ifndef sys_msleep +/** + * Sleep for some ms. Timeouts are NOT processed while sleeping. + * + * @param ms number of milliseconds to sleep + */ +void +sys_msleep(u32_t ms) +{ + if (ms > 0) { + sys_sem_t delaysem; + err_t err = sys_sem_new(&delaysem, 0); + if (err == ERR_OK) { + sys_arch_sem_wait(&delaysem, ms); + sys_sem_free(&delaysem); + } + } +} +#endif /* sys_msleep */ + +#endif /* !NO_SYS */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/core/tcp.c b/component/common/network/lwip/lwip_v1.4.1/src/core/tcp.c new file mode 100644 index 0000000..b710d2e --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/core/tcp.c @@ -0,0 +1,1742 @@ +/** + * @file + * Transmission Control Protocol for IP + * + * This file contains common functions for the TCP implementation, such as functinos + * for manipulating the data structures and the TCP timer functions. TCP functions + * related to input and output is found in tcp_in.c and tcp_out.c respectively. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/snmp.h" +#include "lwip/tcp.h" +#include "lwip/tcp_impl.h" +#include "lwip/debug.h" +#include "lwip/stats.h" + +#include + +#ifndef TCP_LOCAL_PORT_RANGE_START +/* From http://www.iana.org/assignments/port-numbers: + "The Dynamic and/or Private Ports are those from 49152 through 65535" */ +#define TCP_LOCAL_PORT_RANGE_START 0xc000 +#define TCP_LOCAL_PORT_RANGE_END 0xffff +#define TCP_ENSURE_LOCAL_PORT_RANGE(port) (((port) & ~TCP_LOCAL_PORT_RANGE_START) + TCP_LOCAL_PORT_RANGE_START) +#endif + +#if LWIP_TCP_KEEPALIVE +#define TCP_KEEP_DUR(pcb) ((pcb)->keep_cnt * (pcb)->keep_intvl) +#define TCP_KEEP_INTVL(pcb) ((pcb)->keep_intvl) +#else /* LWIP_TCP_KEEPALIVE */ +#define TCP_KEEP_DUR(pcb) TCP_MAXIDLE +#define TCP_KEEP_INTVL(pcb) TCP_KEEPINTVL_DEFAULT +#endif /* LWIP_TCP_KEEPALIVE */ + +const char * const tcp_state_str[] = { + "CLOSED", + "LISTEN", + "SYN_SENT", + "SYN_RCVD", + "ESTABLISHED", + "FIN_WAIT_1", + "FIN_WAIT_2", + "CLOSE_WAIT", + "CLOSING", + "LAST_ACK", + "TIME_WAIT" +}; + +/* last local TCP port */ +static u16_t tcp_port = TCP_LOCAL_PORT_RANGE_START; + +/* Incremented every coarse grained timer shot (typically every 500 ms). */ +u32_t tcp_ticks; +const u8_t tcp_backoff[13] = + { 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7}; + /* Times per slowtmr hits */ +const u8_t tcp_persist_backoff[7] = { 3, 6, 12, 24, 48, 96, 120 }; + +/* The TCP PCB lists. */ + +/** List of all TCP PCBs bound but not yet (connected || listening) */ +struct tcp_pcb *tcp_bound_pcbs; +/** List of all TCP PCBs in LISTEN state */ +union tcp_listen_pcbs_t tcp_listen_pcbs; +/** List of all TCP PCBs that are in a state in which + * they accept or send data. */ +struct tcp_pcb *tcp_active_pcbs; +/** List of all TCP PCBs in TIME-WAIT state */ +struct tcp_pcb *tcp_tw_pcbs; + +#define NUM_TCP_PCB_LISTS 4 +#define NUM_TCP_PCB_LISTS_NO_TIME_WAIT 3 +/** An array with all (non-temporary) PCB lists, mainly used for smaller code size */ +struct tcp_pcb ** const tcp_pcb_lists[] = {&tcp_listen_pcbs.pcbs, &tcp_bound_pcbs, + &tcp_active_pcbs, &tcp_tw_pcbs}; + +/** Only used for temporary storage. */ +struct tcp_pcb *tcp_tmp_pcb; + +u8_t tcp_active_pcbs_changed; + +/** Timer counter to handle calling slow-timer from tcp_tmr() */ +static u8_t tcp_timer; +static u8_t tcp_timer_ctr; +static u16_t tcp_new_port(void); + +/** + * Initialize this module. + */ +void +tcp_init(void) +{ +#if LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) + tcp_port = TCP_ENSURE_LOCAL_PORT_RANGE(LWIP_RAND()); +#endif /* LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) */ +} + +/** + * Called periodically to dispatch TCP timers. + */ +void +tcp_tmr(void) +{ + /* Call tcp_fasttmr() every 250 ms */ + tcp_fasttmr(); + + if (++tcp_timer & 1) { + /* Call tcp_tmr() every 500 ms, i.e., every other timer + tcp_tmr() is called. */ + tcp_slowtmr(); + } +} + +/** + * Closes the TX side of a connection held by the PCB. + * For tcp_close(), a RST is sent if the application didn't receive all data + * (tcp_recved() not called for all data passed to recv callback). + * + * Listening pcbs are freed and may not be referenced any more. + * Connection pcbs are freed if not yet connected and may not be referenced + * any more. If a connection is established (at least SYN received or in + * a closing state), the connection is closed, and put in a closing state. + * The pcb is then automatically freed in tcp_slowtmr(). It is therefore + * unsafe to reference it. + * + * @param pcb the tcp_pcb to close + * @return ERR_OK if connection has been closed + * another err_t if closing failed and pcb is not freed + */ +static err_t +tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data) +{ + err_t err; + + if (rst_on_unacked_data && ((pcb->state == ESTABLISHED) || (pcb->state == CLOSE_WAIT))) { + if ((pcb->refused_data != NULL) || (pcb->rcv_wnd != TCP_WND)) { + /* Not all data received by application, send RST to tell the remote + side about this. */ + LWIP_ASSERT("pcb->flags & TF_RXCLOSED", pcb->flags & TF_RXCLOSED); + + /* don't call tcp_abort here: we must not deallocate the pcb since + that might not be expected when calling tcp_close */ + tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip, + pcb->local_port, pcb->remote_port); + + tcp_pcb_purge(pcb); + TCP_RMV_ACTIVE(pcb); + if (pcb->state == ESTABLISHED) { + /* move to TIME_WAIT since we close actively */ + pcb->state = TIME_WAIT; + TCP_REG(&tcp_tw_pcbs, pcb); + } else { + /* CLOSE_WAIT: deallocate the pcb since we already sent a RST for it */ + memp_free(MEMP_TCP_PCB, pcb); + } + return ERR_OK; + } + } + + switch (pcb->state) { + case CLOSED: + /* Closing a pcb in the CLOSED state might seem erroneous, + * however, it is in this state once allocated and as yet unused + * and the user needs some way to free it should the need arise. + * Calling tcp_close() with a pcb that has already been closed, (i.e. twice) + * or for a pcb that has been used and then entered the CLOSED state + * is erroneous, but this should never happen as the pcb has in those cases + * been freed, and so any remaining handles are bogus. */ + err = ERR_OK; + if (pcb->local_port != 0) { + TCP_RMV(&tcp_bound_pcbs, pcb); + } + memp_free(MEMP_TCP_PCB, pcb); + pcb = NULL; + break; + case LISTEN: + err = ERR_OK; + tcp_pcb_remove(&tcp_listen_pcbs.pcbs, pcb); + memp_free(MEMP_TCP_PCB_LISTEN, pcb); + pcb = NULL; + break; + case SYN_SENT: + err = ERR_OK; + TCP_PCB_REMOVE_ACTIVE(pcb); + memp_free(MEMP_TCP_PCB, pcb); + pcb = NULL; + snmp_inc_tcpattemptfails(); + break; + case SYN_RCVD: + err = tcp_send_fin(pcb); + if (err == ERR_OK) { + snmp_inc_tcpattemptfails(); + pcb->state = FIN_WAIT_1; + } + break; + case ESTABLISHED: + err = tcp_send_fin(pcb); + if (err == ERR_OK) { + snmp_inc_tcpestabresets(); + pcb->state = FIN_WAIT_1; + } + break; + case CLOSE_WAIT: + err = tcp_send_fin(pcb); + if (err == ERR_OK) { + snmp_inc_tcpestabresets(); + pcb->state = LAST_ACK; + } + break; + default: + /* Has already been closed, do nothing. */ + err = ERR_OK; + pcb = NULL; + break; + } + + if (pcb != NULL && err == ERR_OK) { + /* To ensure all data has been sent when tcp_close returns, we have + to make sure tcp_output doesn't fail. + Since we don't really have to ensure all data has been sent when tcp_close + returns (unsent data is sent from tcp timer functions, also), we don't care + for the return value of tcp_output for now. */ + /* @todo: When implementing SO_LINGER, this must be changed somehow: + If SOF_LINGER is set, the data should be sent and acked before close returns. + This can only be valid for sequential APIs, not for the raw API. */ + tcp_output(pcb); + } + return err; +} + +/** + * Closes the connection held by the PCB. + * + * Listening pcbs are freed and may not be referenced any more. + * Connection pcbs are freed if not yet connected and may not be referenced + * any more. If a connection is established (at least SYN received or in + * a closing state), the connection is closed, and put in a closing state. + * The pcb is then automatically freed in tcp_slowtmr(). It is therefore + * unsafe to reference it (unless an error is returned). + * + * @param pcb the tcp_pcb to close + * @return ERR_OK if connection has been closed + * another err_t if closing failed and pcb is not freed + */ +err_t +tcp_close(struct tcp_pcb *pcb) +{ +#if TCP_DEBUG + LWIP_DEBUGF(TCP_DEBUG, ("tcp_close: closing in ")); + tcp_debug_print_state(pcb->state); +#endif /* TCP_DEBUG */ + + if (pcb->state != LISTEN) { + /* Set a flag not to receive any more data... */ + pcb->flags |= TF_RXCLOSED; + } + /* ... and close */ + return tcp_close_shutdown(pcb, 1); +} + +/** + * Causes all or part of a full-duplex connection of this PCB to be shut down. + * This doesn't deallocate the PCB unless shutting down both sides! + * Shutting down both sides is the same as calling tcp_close, so if it succeds, + * the PCB should not be referenced any more. + * + * @param pcb PCB to shutdown + * @param shut_rx shut down receive side if this is != 0 + * @param shut_tx shut down send side if this is != 0 + * @return ERR_OK if shutdown succeeded (or the PCB has already been shut down) + * another err_t on error. + */ +err_t +tcp_shutdown(struct tcp_pcb *pcb, int shut_rx, int shut_tx) +{ + if (pcb->state == LISTEN) { + return ERR_CONN; + } + if (shut_rx) { + /* shut down the receive side: set a flag not to receive any more data... */ + pcb->flags |= TF_RXCLOSED; + if (shut_tx) { + /* shutting down the tx AND rx side is the same as closing for the raw API */ + return tcp_close_shutdown(pcb, 1); + } + /* ... and free buffered data */ + if (pcb->refused_data != NULL) { + pbuf_free(pcb->refused_data); + pcb->refused_data = NULL; + } + } + if (shut_tx) { + /* This can't happen twice since if it succeeds, the pcb's state is changed. + Only close in these states as the others directly deallocate the PCB */ + switch (pcb->state) { + case SYN_RCVD: + case ESTABLISHED: + case CLOSE_WAIT: + return tcp_close_shutdown(pcb, shut_rx); + default: + /* Not (yet?) connected, cannot shutdown the TX side as that would bring us + into CLOSED state, where the PCB is deallocated. */ + return ERR_CONN; + } + } + return ERR_OK; +} + +/** + * Abandons a connection and optionally sends a RST to the remote + * host. Deletes the local protocol control block. This is done when + * a connection is killed because of shortage of memory. + * + * @param pcb the tcp_pcb to abort + * @param reset boolean to indicate whether a reset should be sent + */ +void +tcp_abandon(struct tcp_pcb *pcb, int reset) +{ + u32_t seqno, ackno; +#if LWIP_CALLBACK_API + tcp_err_fn errf; +#endif /* LWIP_CALLBACK_API */ + void *errf_arg; + + /* pcb->state LISTEN not allowed here */ + LWIP_ASSERT("don't call tcp_abort/tcp_abandon for listen-pcbs", + pcb->state != LISTEN); + /* Figure out on which TCP PCB list we are, and remove us. If we + are in an active state, call the receive function associated with + the PCB with a NULL argument, and send an RST to the remote end. */ + if (pcb->state == TIME_WAIT) { + tcp_pcb_remove(&tcp_tw_pcbs, pcb); + memp_free(MEMP_TCP_PCB, pcb); + } else { + seqno = pcb->snd_nxt; + ackno = pcb->rcv_nxt; +#if LWIP_CALLBACK_API + errf = pcb->errf; +#endif /* LWIP_CALLBACK_API */ + errf_arg = pcb->callback_arg; + TCP_PCB_REMOVE_ACTIVE(pcb); + if (pcb->unacked != NULL) { + tcp_segs_free(pcb->unacked); + } + if (pcb->unsent != NULL) { + tcp_segs_free(pcb->unsent); + } +#if TCP_QUEUE_OOSEQ + if (pcb->ooseq != NULL) { + tcp_segs_free(pcb->ooseq); + } +#endif /* TCP_QUEUE_OOSEQ */ + if (reset) { + LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_abandon: sending RST\n")); + tcp_rst(seqno, ackno, &pcb->local_ip, &pcb->remote_ip, pcb->local_port, pcb->remote_port); + } + memp_free(MEMP_TCP_PCB, pcb); + TCP_EVENT_ERR(errf, errf_arg, ERR_ABRT); + } +} + +/** + * Aborts the connection by sending a RST (reset) segment to the remote + * host. The pcb is deallocated. This function never fails. + * + * ATTENTION: When calling this from one of the TCP callbacks, make + * sure you always return ERR_ABRT (and never return ERR_ABRT otherwise + * or you will risk accessing deallocated memory or memory leaks! + * + * @param pcb the tcp pcb to abort + */ +void +tcp_abort(struct tcp_pcb *pcb) +{ + tcp_abandon(pcb, 1); +} + +/** + * Binds the connection to a local portnumber and IP address. If the + * IP address is not given (i.e., ipaddr == NULL), the IP address of + * the outgoing network interface is used instead. + * + * @param pcb the tcp_pcb to bind (no check is done whether this pcb is + * already bound!) + * @param ipaddr the local ip address to bind to (use IP_ADDR_ANY to bind + * to any local address + * @param port the local port to bind to + * @return ERR_USE if the port is already in use + * ERR_VAL if bind failed because the PCB is not in a valid state + * ERR_OK if bound + */ +err_t +tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port) +{ + int i; + int max_pcb_list = NUM_TCP_PCB_LISTS; + struct tcp_pcb *cpcb; + + LWIP_ERROR("tcp_bind: can only bind in state CLOSED", pcb->state == CLOSED, return ERR_VAL); + +#if SO_REUSE + /* Unless the REUSEADDR flag is set, + we have to check the pcbs in TIME-WAIT state, also. + We do not dump TIME_WAIT pcb's; they can still be matched by incoming + packets using both local and remote IP addresses and ports to distinguish. + */ + if (ip_get_option(pcb, SOF_REUSEADDR)) { + max_pcb_list = NUM_TCP_PCB_LISTS_NO_TIME_WAIT; + } +#endif /* SO_REUSE */ + + if (port == 0) { + port = tcp_new_port(); + if (port == 0) { + return ERR_BUF; + } + } + + /* Check if the address already is in use (on all lists) */ + for (i = 0; i < max_pcb_list; i++) { + for(cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) { + if (cpcb->local_port == port) { +#if SO_REUSE + /* Omit checking for the same port if both pcbs have REUSEADDR set. + For SO_REUSEADDR, the duplicate-check for a 5-tuple is done in + tcp_connect. */ + if (!ip_get_option(pcb, SOF_REUSEADDR) || + !ip_get_option(cpcb, SOF_REUSEADDR)) +#endif /* SO_REUSE */ + { + if (ip_addr_isany(&(cpcb->local_ip)) || + ip_addr_isany(ipaddr) || + ip_addr_cmp(&(cpcb->local_ip), ipaddr)) { + return ERR_USE; + } + } + } + } + } + + if (!ip_addr_isany(ipaddr)) { + pcb->local_ip = *ipaddr; + } + pcb->local_port = port; + TCP_REG(&tcp_bound_pcbs, pcb); + LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: bind to port %"U16_F"\n", port)); + return ERR_OK; +} +#if LWIP_CALLBACK_API +/** + * Default accept callback if no accept callback is specified by the user. + */ +static err_t +tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err) +{ + LWIP_UNUSED_ARG(arg); + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(err); + + return ERR_ABRT; +} +#endif /* LWIP_CALLBACK_API */ + +/** + * Set the state of the connection to be LISTEN, which means that it + * is able to accept incoming connections. The protocol control block + * is reallocated in order to consume less memory. Setting the + * connection to LISTEN is an irreversible process. + * + * @param pcb the original tcp_pcb + * @param backlog the incoming connections queue limit + * @return tcp_pcb used for listening, consumes less memory. + * + * @note The original tcp_pcb is freed. This function therefore has to be + * called like this: + * tpcb = tcp_listen(tpcb); + */ +struct tcp_pcb * +tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog) +{ + struct tcp_pcb_listen *lpcb; + + LWIP_UNUSED_ARG(backlog); + LWIP_ERROR("tcp_listen: pcb already connected", pcb->state == CLOSED, return NULL); + + /* already listening? */ + if (pcb->state == LISTEN) { + return pcb; + } +#if SO_REUSE + if (ip_get_option(pcb, SOF_REUSEADDR)) { + /* Since SOF_REUSEADDR allows reusing a local address before the pcb's usage + is declared (listen-/connection-pcb), we have to make sure now that + this port is only used once for every local IP. */ + for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { + if (lpcb->local_port == pcb->local_port) { + if (ip_addr_cmp(&lpcb->local_ip, &pcb->local_ip)) { + /* this address/port is already used */ + return NULL; + } + } + } + } +#endif /* SO_REUSE */ + lpcb = (struct tcp_pcb_listen *)memp_malloc(MEMP_TCP_PCB_LISTEN); + if (lpcb == NULL) { + return NULL; + } + lpcb->callback_arg = pcb->callback_arg; + lpcb->local_port = pcb->local_port; + lpcb->state = LISTEN; + lpcb->prio = pcb->prio; + lpcb->so_options = pcb->so_options; + ip_set_option(lpcb, SOF_ACCEPTCONN); + lpcb->ttl = pcb->ttl; + lpcb->tos = pcb->tos; + ip_addr_copy(lpcb->local_ip, pcb->local_ip); + if (pcb->local_port != 0) { + TCP_RMV(&tcp_bound_pcbs, pcb); + } + memp_free(MEMP_TCP_PCB, pcb); +#if LWIP_CALLBACK_API + lpcb->accept = tcp_accept_null; +#endif /* LWIP_CALLBACK_API */ +#if TCP_LISTEN_BACKLOG + lpcb->accepts_pending = 0; + lpcb->backlog = (backlog ? backlog : 1); +#endif /* TCP_LISTEN_BACKLOG */ + TCP_REG(&tcp_listen_pcbs.pcbs, (struct tcp_pcb *)lpcb); + return (struct tcp_pcb *)lpcb; +} + +/** + * Update the state that tracks the available window space to advertise. + * + * Returns how much extra window would be advertised if we sent an + * update now. + */ +u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb) +{ + u32_t new_right_edge = pcb->rcv_nxt + pcb->rcv_wnd; + + if (TCP_SEQ_GEQ(new_right_edge, pcb->rcv_ann_right_edge + LWIP_MIN((TCP_WND / 2), pcb->mss))) { + /* we can advertise more window */ + pcb->rcv_ann_wnd = pcb->rcv_wnd; + return new_right_edge - pcb->rcv_ann_right_edge; + } else { + if (TCP_SEQ_GT(pcb->rcv_nxt, pcb->rcv_ann_right_edge)) { + /* Can happen due to other end sending out of advertised window, + * but within actual available (but not yet advertised) window */ + pcb->rcv_ann_wnd = 0; + } else { + /* keep the right edge of window constant */ + u32_t new_rcv_ann_wnd = pcb->rcv_ann_right_edge - pcb->rcv_nxt; + LWIP_ASSERT("new_rcv_ann_wnd <= 0xffff", new_rcv_ann_wnd <= 0xffff); + pcb->rcv_ann_wnd = (u16_t)new_rcv_ann_wnd; + } + return 0; + } +} + +/** + * This function should be called by the application when it has + * processed the data. The purpose is to advertise a larger window + * when the data has been processed. + * + * @param pcb the tcp_pcb for which data is read + * @param len the amount of bytes that have been read by the application + */ +void +tcp_recved(struct tcp_pcb *pcb, u16_t len) +{ + int wnd_inflation; + + /* pcb->state LISTEN not allowed here */ + LWIP_ASSERT("don't call tcp_recved for listen-pcbs", + pcb->state != LISTEN); + LWIP_ASSERT("tcp_recved: len would wrap rcv_wnd\n", + len <= 0xffff - pcb->rcv_wnd ); + + pcb->rcv_wnd += len; + if (pcb->rcv_wnd > TCP_WND) { + pcb->rcv_wnd = TCP_WND; + } + + wnd_inflation = tcp_update_rcv_ann_wnd(pcb); + + /* If the change in the right edge of window is significant (default + * watermark is TCP_WND/4), then send an explicit update now. + * Otherwise wait for a packet to be sent in the normal course of + * events (or more window to be available later) */ + if (wnd_inflation >= TCP_WND_UPDATE_THRESHOLD) { + tcp_ack_now(pcb); + tcp_output(pcb); + } + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_recved: recveived %"U16_F" bytes, wnd %"U16_F" (%"U16_F").\n", + len, pcb->rcv_wnd, TCP_WND - pcb->rcv_wnd)); +} + +/** + * Allocate a new local TCP port. + * + * @return a new (free) local TCP port number + */ +static u16_t +tcp_new_port(void) +{ + u8_t i; + u16_t n = 0; + struct tcp_pcb *pcb; + +again: + if (tcp_port++ == TCP_LOCAL_PORT_RANGE_END) { + tcp_port = TCP_LOCAL_PORT_RANGE_START; + } + /* Check all PCB lists. */ + for (i = 0; i < NUM_TCP_PCB_LISTS; i++) { + for(pcb = *tcp_pcb_lists[i]; pcb != NULL; pcb = pcb->next) { + if (pcb->local_port == tcp_port) { + if (++n > (TCP_LOCAL_PORT_RANGE_END - TCP_LOCAL_PORT_RANGE_START)) { + return 0; + } + goto again; + } + } + } + return tcp_port; +} + +/** + * Connects to another host. The function given as the "connected" + * argument will be called when the connection has been established. + * + * @param pcb the tcp_pcb used to establish the connection + * @param ipaddr the remote ip address to connect to + * @param port the remote tcp port to connect to + * @param connected callback function to call when connected (or on error) + * @return ERR_VAL if invalid arguments are given + * ERR_OK if connect request has been sent + * other err_t values if connect request couldn't be sent + */ +err_t +tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port, + tcp_connected_fn connected) +{ + err_t ret; + u32_t iss; + u16_t old_local_port; + + LWIP_ERROR("tcp_connect: can only connect from state CLOSED", pcb->state == CLOSED, return ERR_ISCONN); + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %"U16_F"\n", port)); + if (ipaddr != NULL) { + pcb->remote_ip = *ipaddr; + } else { + return ERR_VAL; + } + pcb->remote_port = port; + + /* check if we have a route to the remote host */ + if (ip_addr_isany(&(pcb->local_ip))) { + /* no local IP address set, yet. */ + struct netif *netif = ip_route(&(pcb->remote_ip)); + if (netif == NULL) { + /* Don't even try to send a SYN packet if we have no route + since that will fail. */ + return ERR_RTE; + } + /* Use the netif's IP address as local address. */ + ip_addr_copy(pcb->local_ip, netif->ip_addr); + } + + old_local_port = pcb->local_port; + if (pcb->local_port == 0) { + pcb->local_port = tcp_new_port(); + if (pcb->local_port == 0) { + return ERR_BUF; + } + } +#if SO_REUSE + if (ip_get_option(pcb, SOF_REUSEADDR)) { + /* Since SOF_REUSEADDR allows reusing a local address, we have to make sure + now that the 5-tuple is unique. */ + struct tcp_pcb *cpcb; + int i; + /* Don't check listen- and bound-PCBs, check active- and TIME-WAIT PCBs. */ + for (i = 2; i < NUM_TCP_PCB_LISTS; i++) { + for(cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) { + if ((cpcb->local_port == pcb->local_port) && + (cpcb->remote_port == port) && + ip_addr_cmp(&cpcb->local_ip, &pcb->local_ip) && + ip_addr_cmp(&cpcb->remote_ip, ipaddr)) { + /* linux returns EISCONN here, but ERR_USE should be OK for us */ + return ERR_USE; + } + } + } + } +#endif /* SO_REUSE */ + iss = tcp_next_iss(); + pcb->rcv_nxt = 0; + pcb->snd_nxt = iss; + pcb->lastack = iss - 1; + pcb->snd_lbb = iss - 1; + pcb->rcv_wnd = TCP_WND; + pcb->rcv_ann_wnd = TCP_WND; + pcb->rcv_ann_right_edge = pcb->rcv_nxt; + pcb->snd_wnd = TCP_WND; + /* As initial send MSS, we use TCP_MSS but limit it to 536. + The send MSS is updated when an MSS option is received. */ + pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS; +#if TCP_CALCULATE_EFF_SEND_MSS + pcb->mss = tcp_eff_send_mss(pcb->mss, ipaddr); +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + pcb->cwnd = 1; + pcb->ssthresh = pcb->mss * 10; +#if LWIP_CALLBACK_API + pcb->connected = connected; +#else /* LWIP_CALLBACK_API */ + LWIP_UNUSED_ARG(connected); +#endif /* LWIP_CALLBACK_API */ + + /* Send a SYN together with the MSS option. */ + ret = tcp_enqueue_flags(pcb, TCP_SYN); + if (ret == ERR_OK) { + /* SYN segment was enqueued, changed the pcbs state now */ + pcb->state = SYN_SENT; + if (old_local_port != 0) { + TCP_RMV(&tcp_bound_pcbs, pcb); + } + TCP_REG_ACTIVE(pcb); + snmp_inc_tcpactiveopens(); + + tcp_output(pcb); + } + return ret; +} + +/** + * Called every 500 ms and implements the retransmission timer and the timer that + * removes PCBs that have been in TIME-WAIT for enough time. It also increments + * various timers such as the inactivity timer in each PCB. + * + * Automatically called from tcp_tmr(). + */ +void +tcp_slowtmr(void) +{ + struct tcp_pcb *pcb, *prev; + u16_t eff_wnd; + u8_t pcb_remove; /* flag if a PCB should be removed */ + u8_t pcb_reset; /* flag if a RST should be sent when removing */ + err_t err; + + err = ERR_OK; + + ++tcp_ticks; + ++tcp_timer_ctr; + +tcp_slowtmr_start: + /* Steps through all of the active PCBs. */ + prev = NULL; + pcb = tcp_active_pcbs; + if (pcb == NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: no active pcbs\n")); + } + while (pcb != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: processing active pcb\n")); + LWIP_ASSERT("tcp_slowtmr: active pcb->state != CLOSED\n", pcb->state != CLOSED); + LWIP_ASSERT("tcp_slowtmr: active pcb->state != LISTEN\n", pcb->state != LISTEN); + LWIP_ASSERT("tcp_slowtmr: active pcb->state != TIME-WAIT\n", pcb->state != TIME_WAIT); + if (pcb->last_timer == tcp_timer_ctr) { + /* skip this pcb, we have already processed it */ + pcb = pcb->next; + continue; + } + pcb->last_timer = tcp_timer_ctr; + + pcb_remove = 0; + pcb_reset = 0; + + if (pcb->state == SYN_SENT && pcb->nrtx == TCP_SYNMAXRTX) { + ++pcb_remove; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max SYN retries reached\n")); + } + else if (pcb->nrtx == TCP_MAXRTX) { + ++pcb_remove; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max DATA retries reached\n")); + } else { + if (pcb->persist_backoff > 0) { + /* If snd_wnd is zero, use persist timer to send 1 byte probes + * instead of using the standard retransmission mechanism. */ + pcb->persist_cnt++; + if (pcb->persist_cnt >= tcp_persist_backoff[pcb->persist_backoff-1]) { + pcb->persist_cnt = 0; + if (pcb->persist_backoff < sizeof(tcp_persist_backoff)) { + pcb->persist_backoff++; + } + tcp_zero_window_probe(pcb); + } + } else { + /* Increase the retransmission timer if it is running */ + if(pcb->rtime >= 0) { + ++pcb->rtime; + } + + if (pcb->unacked != NULL && pcb->rtime >= pcb->rto) { + /* Time for a retransmission. */ + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_slowtmr: rtime %"S16_F + " pcb->rto %"S16_F"\n", + pcb->rtime, pcb->rto)); + + /* Double retransmission time-out unless we are trying to + * connect to somebody (i.e., we are in SYN_SENT). */ + if (pcb->state != SYN_SENT) { + pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[pcb->nrtx]; + } + + /* Reset the retransmission timer. */ + pcb->rtime = 0; + + /* Reduce congestion window and ssthresh. */ + eff_wnd = LWIP_MIN(pcb->cwnd, pcb->snd_wnd); + pcb->ssthresh = eff_wnd >> 1; + if (pcb->ssthresh < (pcb->mss << 1)) { + pcb->ssthresh = (pcb->mss << 1); + } + pcb->cwnd = pcb->mss; + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %"U16_F + " ssthresh %"U16_F"\n", + pcb->cwnd, pcb->ssthresh)); + + /* The following needs to be called AFTER cwnd is set to one + mss - STJ */ + tcp_rexmit_rto(pcb); + } + } + } + /* Check if this PCB has stayed too long in FIN-WAIT-2 */ + if (pcb->state == FIN_WAIT_2) { + /* If this PCB is in FIN_WAIT_2 because of SHUT_WR don't let it time out. */ + if (pcb->flags & TF_RXCLOSED) { + /* PCB was fully closed (either through close() or SHUT_RDWR): + normal FIN-WAIT timeout handling. */ + if ((u32_t)(tcp_ticks - pcb->tmr) > + TCP_FIN_WAIT_TIMEOUT / TCP_SLOW_INTERVAL) { + ++pcb_remove; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in FIN-WAIT-2\n")); + } + } + } + + /* Check if KEEPALIVE should be sent */ + if(ip_get_option(pcb, SOF_KEEPALIVE) && + ((pcb->state == ESTABLISHED) || + (pcb->state == CLOSE_WAIT))) { + if((u32_t)(tcp_ticks - pcb->tmr) > + (pcb->keep_idle + TCP_KEEP_DUR(pcb)) / TCP_SLOW_INTERVAL) + { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to %"U16_F".%"U16_F".%"U16_F".%"U16_F".\n", + ip4_addr1_16(&pcb->remote_ip), ip4_addr2_16(&pcb->remote_ip), + ip4_addr3_16(&pcb->remote_ip), ip4_addr4_16(&pcb->remote_ip))); + + ++pcb_remove; + ++pcb_reset; + } + else if((u32_t)(tcp_ticks - pcb->tmr) > + (pcb->keep_idle + pcb->keep_cnt_sent * TCP_KEEP_INTVL(pcb)) + / TCP_SLOW_INTERVAL) + { + tcp_keepalive(pcb); + pcb->keep_cnt_sent++; + } + } + + /* If this PCB has queued out of sequence data, but has been + inactive for too long, will drop the data (it will eventually + be retransmitted). */ +#if TCP_QUEUE_OOSEQ + if (pcb->ooseq != NULL && + (u32_t)tcp_ticks - pcb->tmr >= pcb->rto * TCP_OOSEQ_TIMEOUT) { + tcp_segs_free(pcb->ooseq); + pcb->ooseq = NULL; + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: dropping OOSEQ queued data\n")); + } +#endif /* TCP_QUEUE_OOSEQ */ + + /* Check if this PCB has stayed too long in SYN-RCVD */ + if (pcb->state == SYN_RCVD) { + if ((u32_t)(tcp_ticks - pcb->tmr) > + TCP_SYN_RCVD_TIMEOUT / TCP_SLOW_INTERVAL) { + ++pcb_remove; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in SYN-RCVD\n")); + } + } + + /* Check if this PCB has stayed too long in LAST-ACK */ + if (pcb->state == LAST_ACK) { + if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) { + ++pcb_remove; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in LAST-ACK\n")); + } + } + + /* If the PCB should be removed, do it. */ + if (pcb_remove) { + struct tcp_pcb *pcb2; + tcp_err_fn err_fn; + void *err_arg; + tcp_pcb_purge(pcb); + /* Remove PCB from tcp_active_pcbs list. */ + if (prev != NULL) { + LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_active_pcbs", pcb != tcp_active_pcbs); + prev->next = pcb->next; + } else { + /* This PCB was the first. */ + LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_active_pcbs", tcp_active_pcbs == pcb); + tcp_active_pcbs = pcb->next; + } + + if (pcb_reset) { + tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip, + pcb->local_port, pcb->remote_port); + } + + err_fn = pcb->errf; + err_arg = pcb->callback_arg; + pcb2 = pcb; + pcb = pcb->next; + memp_free(MEMP_TCP_PCB, pcb2); + + tcp_active_pcbs_changed = 0; + TCP_EVENT_ERR(err_fn, err_arg, ERR_ABRT); + if (tcp_active_pcbs_changed) { + goto tcp_slowtmr_start; + } + } else { + /* get the 'next' element now and work with 'prev' below (in case of abort) */ + prev = pcb; + pcb = pcb->next; + + /* We check if we should poll the connection. */ + ++prev->polltmr; + if (prev->polltmr >= prev->pollinterval) { + prev->polltmr = 0; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: polling application\n")); + tcp_active_pcbs_changed = 0; + TCP_EVENT_POLL(prev, err); + if (tcp_active_pcbs_changed) { + goto tcp_slowtmr_start; + } + /* if err == ERR_ABRT, 'prev' is already deallocated */ + if (err == ERR_OK) { + tcp_output(prev); + } + } + } + } + + + /* Steps through all of the TIME-WAIT PCBs. */ + prev = NULL; + pcb = tcp_tw_pcbs; + while (pcb != NULL) { + LWIP_ASSERT("tcp_slowtmr: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); + pcb_remove = 0; + + /* Check if this PCB has stayed long enough in TIME-WAIT */ + if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) { + ++pcb_remove; + } + + + + /* If the PCB should be removed, do it. */ + if (pcb_remove) { + struct tcp_pcb *pcb2; + tcp_pcb_purge(pcb); + /* Remove PCB from tcp_tw_pcbs list. */ + if (prev != NULL) { + LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_tw_pcbs", pcb != tcp_tw_pcbs); + prev->next = pcb->next; + } else { + /* This PCB was the first. */ + LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_tw_pcbs", tcp_tw_pcbs == pcb); + tcp_tw_pcbs = pcb->next; + } + pcb2 = pcb; + pcb = pcb->next; + memp_free(MEMP_TCP_PCB, pcb2); + } else { + prev = pcb; + pcb = pcb->next; + } + } +} + +/** + * Is called every TCP_FAST_INTERVAL (250 ms) and process data previously + * "refused" by upper layer (application) and sends delayed ACKs. + * + * Automatically called from tcp_tmr(). + */ +void +tcp_fasttmr(void) +{ + struct tcp_pcb *pcb; + + ++tcp_timer_ctr; + +tcp_fasttmr_start: + pcb = tcp_active_pcbs; + + while(pcb != NULL) { + if (pcb->last_timer != tcp_timer_ctr) { + struct tcp_pcb *next; + pcb->last_timer = tcp_timer_ctr; + /* send delayed ACKs */ + if (pcb->flags & TF_ACK_DELAY) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_fasttmr: delayed ACK\n")); + tcp_ack_now(pcb); + tcp_output(pcb); + pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); + } + + next = pcb->next; + + /* If there is data which was previously "refused" by upper layer */ + if (pcb->refused_data != NULL) { + tcp_active_pcbs_changed = 0; + tcp_process_refused_data(pcb); + if (tcp_active_pcbs_changed) { + /* application callback has changed the pcb list: restart the loop */ + goto tcp_fasttmr_start; + } + } + pcb = next; + } + } +} + +/** Pass pcb->refused_data to the recv callback */ +err_t +tcp_process_refused_data(struct tcp_pcb *pcb) +{ + err_t err; + u8_t refused_flags = pcb->refused_data->flags; + /* set pcb->refused_data to NULL in case the callback frees it and then + closes the pcb */ + struct pbuf *refused_data = pcb->refused_data; + pcb->refused_data = NULL; + /* Notify again application with data previously received. */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: notify kept packet\n")); + TCP_EVENT_RECV(pcb, refused_data, ERR_OK, err); + if (err == ERR_OK) { + /* did refused_data include a FIN? */ + if (refused_flags & PBUF_FLAG_TCP_FIN) { + /* correct rcv_wnd as the application won't call tcp_recved() + for the FIN's seqno */ + if (pcb->rcv_wnd != TCP_WND) { + pcb->rcv_wnd++; + } + TCP_EVENT_CLOSED(pcb, err); + if (err == ERR_ABRT) { + return ERR_ABRT; + } + } + } else if (err == ERR_ABRT) { + /* if err == ERR_ABRT, 'pcb' is already deallocated */ + /* Drop incoming packets because pcb is "full" (only if the incoming + segment contains data). */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: drop incoming packets, because pcb is \"full\"\n")); + return ERR_ABRT; + } else { + /* data is still refused, pbuf is still valid (go on for ACK-only packets) */ + pcb->refused_data = refused_data; + } + return ERR_OK; +} + +/** + * Deallocates a list of TCP segments (tcp_seg structures). + * + * @param seg tcp_seg list of TCP segments to free + */ +void +tcp_segs_free(struct tcp_seg *seg) +{ + while (seg != NULL) { + struct tcp_seg *next = seg->next; + tcp_seg_free(seg); + seg = next; + } +} + +/** + * Frees a TCP segment (tcp_seg structure). + * + * @param seg single tcp_seg to free + */ +void +tcp_seg_free(struct tcp_seg *seg) +{ + if (seg != NULL) { + if (seg->p != NULL) { + pbuf_free(seg->p); +#if TCP_DEBUG + seg->p = NULL; +#endif /* TCP_DEBUG */ + } + memp_free(MEMP_TCP_SEG, seg); + } +} + +/** + * Sets the priority of a connection. + * + * @param pcb the tcp_pcb to manipulate + * @param prio new priority + */ +void +tcp_setprio(struct tcp_pcb *pcb, u8_t prio) +{ + pcb->prio = prio; +} + +#if TCP_QUEUE_OOSEQ +/** + * Returns a copy of the given TCP segment. + * The pbuf and data are not copied, only the pointers + * + * @param seg the old tcp_seg + * @return a copy of seg + */ +struct tcp_seg * +tcp_seg_copy(struct tcp_seg *seg) +{ + struct tcp_seg *cseg; + + cseg = (struct tcp_seg *)memp_malloc(MEMP_TCP_SEG); + if (cseg == NULL) { + return NULL; + } + SMEMCPY((u8_t *)cseg, (const u8_t *)seg, sizeof(struct tcp_seg)); + pbuf_ref(cseg->p); + return cseg; +} +#endif /* TCP_QUEUE_OOSEQ */ + +#if LWIP_CALLBACK_API +/** + * Default receive callback that is called if the user didn't register + * a recv callback for the pcb. + */ +err_t +tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) +{ + LWIP_UNUSED_ARG(arg); + if (p != NULL) { + tcp_recved(pcb, p->tot_len); + pbuf_free(p); + } else if (err == ERR_OK) { + return tcp_close(pcb); + } + return ERR_OK; +} +#endif /* LWIP_CALLBACK_API */ + +/** + * Kills the oldest active connection that has the same or lower priority than + * 'prio'. + * + * @param prio minimum priority + */ +static void +tcp_kill_prio(u8_t prio) +{ + struct tcp_pcb *pcb, *inactive; + u32_t inactivity; + u8_t mprio; + + + mprio = TCP_PRIO_MAX; + + /* We kill the oldest active connection that has lower priority than prio. */ + inactivity = 0; + inactive = NULL; + for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + if (pcb->prio <= prio && + pcb->prio <= mprio && + (u32_t)(tcp_ticks - pcb->tmr) >= inactivity) { + inactivity = tcp_ticks - pcb->tmr; + inactive = pcb; + mprio = pcb->prio; + } + } + if (inactive != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB %p (%"S32_F")\n", + (void *)inactive, inactivity)); + tcp_abort(inactive); + } +} + +/** + * Kills the oldest connection that is in TIME_WAIT state. + * Called from tcp_alloc() if no more connections are available. + */ +static void +tcp_kill_timewait(void) +{ + struct tcp_pcb *pcb, *inactive; + u32_t inactivity; + + inactivity = 0; + inactive = NULL; + /* Go through the list of TIME_WAIT pcbs and get the oldest pcb. */ + for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { + if ((u32_t)(tcp_ticks - pcb->tmr) >= inactivity) { + inactivity = tcp_ticks - pcb->tmr; + inactive = pcb; + } + } + if (inactive != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_timewait: killing oldest TIME-WAIT PCB %p (%"S32_F")\n", + (void *)inactive, inactivity)); + tcp_abort(inactive); + } +} + +/** + * Allocate a new tcp_pcb structure. + * + * @param prio priority for the new pcb + * @return a new tcp_pcb that initially is in state CLOSED + */ +struct tcp_pcb * +tcp_alloc(u8_t prio) +{ + struct tcp_pcb *pcb; + u32_t iss; + + pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); + if (pcb == NULL) { + /* Try killing oldest connection in TIME-WAIT. */ + LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing off oldest TIME-WAIT connection\n")); + tcp_kill_timewait(); + /* Try to allocate a tcp_pcb again. */ + pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); + if (pcb == NULL) { + /* Try killing active connections with lower priority than the new one. */ + LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing connection with prio lower than %d\n", prio)); + tcp_kill_prio(prio); + /* Try to allocate a tcp_pcb again. */ + pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); + if (pcb != NULL) { + /* adjust err stats: memp_malloc failed twice before */ + MEMP_STATS_DEC(err, MEMP_TCP_PCB); + } + } + if (pcb != NULL) { + /* adjust err stats: timewait PCB was freed above */ + MEMP_STATS_DEC(err, MEMP_TCP_PCB); + } + } + if (pcb != NULL) { + memset(pcb, 0, sizeof(struct tcp_pcb)); + pcb->prio = prio; + pcb->snd_buf = TCP_SND_BUF; + pcb->snd_queuelen = 0; + pcb->rcv_wnd = TCP_WND; + pcb->rcv_ann_wnd = TCP_WND; + pcb->tos = 0; + pcb->ttl = TCP_TTL; + /* As initial send MSS, we use TCP_MSS but limit it to 536. + The send MSS is updated when an MSS option is received. */ + pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS; + pcb->rto = 3000 / TCP_SLOW_INTERVAL; + pcb->sa = 0; + pcb->sv = 3000 / TCP_SLOW_INTERVAL; + pcb->rtime = -1; + pcb->cwnd = 1; + iss = tcp_next_iss(); + pcb->snd_wl2 = iss; + pcb->snd_nxt = iss; + pcb->lastack = iss; + pcb->snd_lbb = iss; + pcb->tmr = tcp_ticks; + pcb->last_timer = tcp_timer_ctr; + + pcb->polltmr = 0; + +#if LWIP_CALLBACK_API + pcb->recv = tcp_recv_null; +#endif /* LWIP_CALLBACK_API */ + + /* Init KEEPALIVE timer */ + pcb->keep_idle = TCP_KEEPIDLE_DEFAULT; + +#if LWIP_TCP_KEEPALIVE + pcb->keep_intvl = TCP_KEEPINTVL_DEFAULT; + pcb->keep_cnt = TCP_KEEPCNT_DEFAULT; +#endif /* LWIP_TCP_KEEPALIVE */ + + pcb->keep_cnt_sent = 0; + } + return pcb; +} + +/** + * Creates a new TCP protocol control block but doesn't place it on + * any of the TCP PCB lists. + * The pcb is not put on any list until binding using tcp_bind(). + * + * @internal: Maybe there should be a idle TCP PCB list where these + * PCBs are put on. Port reservation using tcp_bind() is implemented but + * allocated pcbs that are not bound can't be killed automatically if wanting + * to allocate a pcb with higher prio (@see tcp_kill_prio()) + * + * @return a new tcp_pcb that initially is in state CLOSED + */ +struct tcp_pcb * +tcp_new(void) +{ + return tcp_alloc(TCP_PRIO_NORMAL); +} + +/** + * Used to specify the argument that should be passed callback + * functions. + * + * @param pcb tcp_pcb to set the callback argument + * @param arg void pointer argument to pass to callback functions + */ +void +tcp_arg(struct tcp_pcb *pcb, void *arg) +{ + /* This function is allowed to be called for both listen pcbs and + connection pcbs. */ + pcb->callback_arg = arg; +} +#if LWIP_CALLBACK_API + +/** + * Used to specify the function that should be called when a TCP + * connection receives data. + * + * @param pcb tcp_pcb to set the recv callback + * @param recv callback function to call for this pcb when data is received + */ +void +tcp_recv(struct tcp_pcb *pcb, tcp_recv_fn recv) +{ + LWIP_ASSERT("invalid socket state for recv callback", pcb->state != LISTEN); + pcb->recv = recv; +} + +/** + * Used to specify the function that should be called when TCP data + * has been successfully delivered to the remote host. + * + * @param pcb tcp_pcb to set the sent callback + * @param sent callback function to call for this pcb when data is successfully sent + */ +void +tcp_sent(struct tcp_pcb *pcb, tcp_sent_fn sent) +{ + LWIP_ASSERT("invalid socket state for sent callback", pcb->state != LISTEN); + pcb->sent = sent; +} + +/** + * Used to specify the function that should be called when a fatal error + * has occured on the connection. + * + * @param pcb tcp_pcb to set the err callback + * @param err callback function to call for this pcb when a fatal error + * has occured on the connection + */ +void +tcp_err(struct tcp_pcb *pcb, tcp_err_fn err) +{ + LWIP_ASSERT("invalid socket state for err callback", pcb->state != LISTEN); + pcb->errf = err; +} + +/** + * Used for specifying the function that should be called when a + * LISTENing connection has been connected to another host. + * + * @param pcb tcp_pcb to set the accept callback + * @param accept callback function to call for this pcb when LISTENing + * connection has been connected to another host + */ +void +tcp_accept(struct tcp_pcb *pcb, tcp_accept_fn accept) +{ + /* This function is allowed to be called for both listen pcbs and + connection pcbs. */ + pcb->accept = accept; +} +#endif /* LWIP_CALLBACK_API */ + + +/** + * Used to specify the function that should be called periodically + * from TCP. The interval is specified in terms of the TCP coarse + * timer interval, which is called twice a second. + * + */ +void +tcp_poll(struct tcp_pcb *pcb, tcp_poll_fn poll, u8_t interval) +{ + LWIP_ASSERT("invalid socket state for poll", pcb->state != LISTEN); +#if LWIP_CALLBACK_API + pcb->poll = poll; +#else /* LWIP_CALLBACK_API */ + LWIP_UNUSED_ARG(poll); +#endif /* LWIP_CALLBACK_API */ + pcb->pollinterval = interval; +} + +/** + * Purges a TCP PCB. Removes any buffered data and frees the buffer memory + * (pcb->ooseq, pcb->unsent and pcb->unacked are freed). + * + * @param pcb tcp_pcb to purge. The pcb itself is not deallocated! + */ +void +tcp_pcb_purge(struct tcp_pcb *pcb) +{ + if (pcb->state != CLOSED && + pcb->state != TIME_WAIT && + pcb->state != LISTEN) { + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge\n")); + +#if TCP_LISTEN_BACKLOG + if (pcb->state == SYN_RCVD) { + /* Need to find the corresponding listen_pcb and decrease its accepts_pending */ + struct tcp_pcb_listen *lpcb; + LWIP_ASSERT("tcp_pcb_purge: pcb->state == SYN_RCVD but tcp_listen_pcbs is NULL", + tcp_listen_pcbs.listen_pcbs != NULL); + for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { + if ((lpcb->local_port == pcb->local_port) && + (ip_addr_isany(&lpcb->local_ip) || + ip_addr_cmp(&pcb->local_ip, &lpcb->local_ip))) { + /* port and address of the listen pcb match the timed-out pcb */ + LWIP_ASSERT("tcp_pcb_purge: listen pcb does not have accepts pending", + lpcb->accepts_pending > 0); + lpcb->accepts_pending--; + break; + } + } + } +#endif /* TCP_LISTEN_BACKLOG */ + + + if (pcb->refused_data != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->refused_data\n")); + pbuf_free(pcb->refused_data); + pcb->refused_data = NULL; + } + if (pcb->unsent != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: not all data sent\n")); + } + if (pcb->unacked != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->unacked\n")); + } +#if TCP_QUEUE_OOSEQ + if (pcb->ooseq != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->ooseq\n")); + } + tcp_segs_free(pcb->ooseq); + pcb->ooseq = NULL; +#endif /* TCP_QUEUE_OOSEQ */ + + /* Stop the retransmission timer as it will expect data on unacked + queue if it fires */ + pcb->rtime = -1; + + tcp_segs_free(pcb->unsent); + tcp_segs_free(pcb->unacked); + pcb->unacked = pcb->unsent = NULL; +#if TCP_OVERSIZE + pcb->unsent_oversize = 0; +#endif /* TCP_OVERSIZE */ + } +} + +/** + * Purges the PCB and removes it from a PCB list. Any delayed ACKs are sent first. + * + * @param pcblist PCB list to purge. + * @param pcb tcp_pcb to purge. The pcb itself is NOT deallocated! + */ +void +tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb) +{ + TCP_RMV(pcblist, pcb); + + tcp_pcb_purge(pcb); + + /* if there is an outstanding delayed ACKs, send it */ + if (pcb->state != TIME_WAIT && + pcb->state != LISTEN && + pcb->flags & TF_ACK_DELAY) { + pcb->flags |= TF_ACK_NOW; + tcp_output(pcb); + } + + if (pcb->state != LISTEN) { + LWIP_ASSERT("unsent segments leaking", pcb->unsent == NULL); + LWIP_ASSERT("unacked segments leaking", pcb->unacked == NULL); +#if TCP_QUEUE_OOSEQ + LWIP_ASSERT("ooseq segments leaking", pcb->ooseq == NULL); +#endif /* TCP_QUEUE_OOSEQ */ + } + + pcb->state = CLOSED; + + LWIP_ASSERT("tcp_pcb_remove: tcp_pcbs_sane()", tcp_pcbs_sane()); +} + +/** + * Calculates a new initial sequence number for new connections. + * + * @return u32_t pseudo random sequence number + */ +u32_t +tcp_next_iss(void) +{ + static u32_t iss = 6510; + + iss += tcp_ticks; /* XXX */ + return iss; +} + +#if TCP_CALCULATE_EFF_SEND_MSS +/** + * Calcluates the effective send mss that can be used for a specific IP address + * by using ip_route to determin the netif used to send to the address and + * calculating the minimum of TCP_MSS and that netif's mtu (if set). + */ +u16_t +tcp_eff_send_mss(u16_t sendmss, ip_addr_t *addr) +{ + u16_t mss_s; + struct netif *outif; + + outif = ip_route(addr); + if ((outif != NULL) && (outif->mtu != 0)) { + mss_s = outif->mtu - IP_HLEN - TCP_HLEN; + /* RFC 1122, chap 4.2.2.6: + * Eff.snd.MSS = min(SendMSS+20, MMS_S) - TCPhdrsize - IPoptionsize + * We correct for TCP options in tcp_write(), and don't support IP options. + */ + sendmss = LWIP_MIN(sendmss, mss_s); + } + return sendmss; +} +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + +const char* +tcp_debug_state_str(enum tcp_state s) +{ + return tcp_state_str[s]; +} + +#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG +/** + * Print a tcp header for debugging purposes. + * + * @param tcphdr pointer to a struct tcp_hdr + */ +void +tcp_debug_print(struct tcp_hdr *tcphdr) +{ + LWIP_DEBUGF(TCP_DEBUG, ("TCP header:\n")); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(TCP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n", + ntohs(tcphdr->src), ntohs(tcphdr->dest))); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (seq no)\n", + ntohl(tcphdr->seqno))); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (ack no)\n", + ntohl(tcphdr->ackno))); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(TCP_DEBUG, ("| %2"U16_F" | |%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"| %5"U16_F" | (hdrlen, flags (", + TCPH_HDRLEN(tcphdr), + TCPH_FLAGS(tcphdr) >> 5 & 1, + TCPH_FLAGS(tcphdr) >> 4 & 1, + TCPH_FLAGS(tcphdr) >> 3 & 1, + TCPH_FLAGS(tcphdr) >> 2 & 1, + TCPH_FLAGS(tcphdr) >> 1 & 1, + TCPH_FLAGS(tcphdr) & 1, + ntohs(tcphdr->wnd))); + tcp_debug_print_flags(TCPH_FLAGS(tcphdr)); + LWIP_DEBUGF(TCP_DEBUG, ("), win)\n")); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(TCP_DEBUG, ("| 0x%04"X16_F" | %5"U16_F" | (chksum, urgp)\n", + ntohs(tcphdr->chksum), ntohs(tcphdr->urgp))); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); +} + +/** + * Print a tcp state for debugging purposes. + * + * @param s enum tcp_state to print + */ +void +tcp_debug_print_state(enum tcp_state s) +{ + LWIP_DEBUGF(TCP_DEBUG, ("State: %s\n", tcp_state_str[s])); +} + +/** + * Print tcp flags for debugging purposes. + * + * @param flags tcp flags, all active flags are printed + */ +void +tcp_debug_print_flags(u8_t flags) +{ + if (flags & TCP_FIN) { + LWIP_DEBUGF(TCP_DEBUG, ("FIN ")); + } + if (flags & TCP_SYN) { + LWIP_DEBUGF(TCP_DEBUG, ("SYN ")); + } + if (flags & TCP_RST) { + LWIP_DEBUGF(TCP_DEBUG, ("RST ")); + } + if (flags & TCP_PSH) { + LWIP_DEBUGF(TCP_DEBUG, ("PSH ")); + } + if (flags & TCP_ACK) { + LWIP_DEBUGF(TCP_DEBUG, ("ACK ")); + } + if (flags & TCP_URG) { + LWIP_DEBUGF(TCP_DEBUG, ("URG ")); + } + if (flags & TCP_ECE) { + LWIP_DEBUGF(TCP_DEBUG, ("ECE ")); + } + if (flags & TCP_CWR) { + LWIP_DEBUGF(TCP_DEBUG, ("CWR ")); + } + LWIP_DEBUGF(TCP_DEBUG, ("\n")); +} + +/** + * Print all tcp_pcbs in every list for debugging purposes. + */ +void +tcp_debug_print_pcbs(void) +{ + struct tcp_pcb *pcb; + LWIP_DEBUGF(TCP_DEBUG, ("Active PCB states:\n")); + for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", + pcb->local_port, pcb->remote_port, + pcb->snd_nxt, pcb->rcv_nxt)); + tcp_debug_print_state(pcb->state); + } + LWIP_DEBUGF(TCP_DEBUG, ("Listen PCB states:\n")); + for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", + pcb->local_port, pcb->remote_port, + pcb->snd_nxt, pcb->rcv_nxt)); + tcp_debug_print_state(pcb->state); + } + LWIP_DEBUGF(TCP_DEBUG, ("TIME-WAIT PCB states:\n")); + for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", + pcb->local_port, pcb->remote_port, + pcb->snd_nxt, pcb->rcv_nxt)); + tcp_debug_print_state(pcb->state); + } +} + +/** + * Check state consistency of the tcp_pcb lists. + */ +s16_t +tcp_pcbs_sane(void) +{ + struct tcp_pcb *pcb; + for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != CLOSED", pcb->state != CLOSED); + LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != LISTEN", pcb->state != LISTEN); + LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT); + } + for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_ASSERT("tcp_pcbs_sane: tw pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); + } + return 1; +} +#endif /* TCP_DEBUG */ + +#endif /* LWIP_TCP */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/core/tcp_in.c b/component/common/network/lwip/lwip_v1.4.1/src/core/tcp_in.c new file mode 100644 index 0000000..4ec971a --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/core/tcp_in.c @@ -0,0 +1,1619 @@ +/** + * @file + * Transmission Control Protocol, incoming traffic + * + * The input processing functions of the TCP layer. + * + * These functions are generally called in the order (ip_input() ->) + * tcp_input() -> * tcp_process() -> tcp_receive() (-> application). + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/tcp_impl.h" +#include "lwip/def.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/inet_chksum.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "arch/perf.h" + +/* These variables are global to all functions involved in the input + processing of TCP segments. They are set by the tcp_input() + function. */ +static struct tcp_seg inseg; +static struct tcp_hdr *tcphdr; +static struct ip_hdr *iphdr; +static u32_t seqno, ackno; +static u8_t flags; +static u16_t tcplen; + +static u8_t recv_flags; +static struct pbuf *recv_data; + +struct tcp_pcb *tcp_input_pcb; + +/* Forward declarations. */ +static err_t tcp_process(struct tcp_pcb *pcb); +static void tcp_receive(struct tcp_pcb *pcb); +static void tcp_parseopt(struct tcp_pcb *pcb); + +static err_t tcp_listen_input(struct tcp_pcb_listen *pcb); +static err_t tcp_timewait_input(struct tcp_pcb *pcb); + +/** + * The initial input processing of TCP. It verifies the TCP header, demultiplexes + * the segment between the PCBs and passes it on to tcp_process(), which implements + * the TCP finite state machine. This function is called by the IP layer (in + * ip_input()). + * + * @param p received TCP segment to process (p->payload pointing to the IP header) + * @param inp network interface on which this segment was received + */ +void +tcp_input(struct pbuf *p, struct netif *inp) +{ + struct tcp_pcb *pcb, *prev; + struct tcp_pcb_listen *lpcb; +#if SO_REUSE + struct tcp_pcb *lpcb_prev = NULL; + struct tcp_pcb_listen *lpcb_any = NULL; +#endif /* SO_REUSE */ + u8_t hdrlen; + err_t err; + + PERF_START; + + TCP_STATS_INC(tcp.recv); + snmp_inc_tcpinsegs(); + + iphdr = (struct ip_hdr *)p->payload; + tcphdr = (struct tcp_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4); + +#if TCP_INPUT_DEBUG + tcp_debug_print(tcphdr); +#endif + + /* remove header from payload */ + if (pbuf_header(p, -((s16_t)(IPH_HL(iphdr) * 4))) || (p->tot_len < sizeof(struct tcp_hdr))) { + /* drop short packets */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%"U16_F" bytes) discarded\n", p->tot_len)); + TCP_STATS_INC(tcp.lenerr); + goto dropped; + } + + /* Don't even process incoming broadcasts/multicasts. */ + if (ip_addr_isbroadcast(¤t_iphdr_dest, inp) || + ip_addr_ismulticast(¤t_iphdr_dest)) { + TCP_STATS_INC(tcp.proterr); + goto dropped; + } + +#if CHECKSUM_CHECK_TCP + /* Verify TCP checksum. */ + if (inet_chksum_pseudo(p, ip_current_src_addr(), ip_current_dest_addr(), + IP_PROTO_TCP, p->tot_len) != 0) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04"X16_F"\n", + inet_chksum_pseudo(p, ip_current_src_addr(), ip_current_dest_addr(), + IP_PROTO_TCP, p->tot_len))); +#if TCP_DEBUG + tcp_debug_print(tcphdr); +#endif /* TCP_DEBUG */ + TCP_STATS_INC(tcp.chkerr); + goto dropped; + } +#endif + + /* Move the payload pointer in the pbuf so that it points to the + TCP data instead of the TCP header. */ + hdrlen = TCPH_HDRLEN(tcphdr); + if(pbuf_header(p, -(hdrlen * 4))){ + /* drop short packets */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet\n")); + TCP_STATS_INC(tcp.lenerr); + goto dropped; + } + + /* Convert fields in TCP header to host byte order. */ + tcphdr->src = ntohs(tcphdr->src); + tcphdr->dest = ntohs(tcphdr->dest); + seqno = tcphdr->seqno = ntohl(tcphdr->seqno); + ackno = tcphdr->ackno = ntohl(tcphdr->ackno); + tcphdr->wnd = ntohs(tcphdr->wnd); + + flags = TCPH_FLAGS(tcphdr); + tcplen = p->tot_len + ((flags & (TCP_FIN | TCP_SYN)) ? 1 : 0); + + /* Demultiplex an incoming segment. First, we check if it is destined + for an active connection. */ + prev = NULL; + + + for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED); + LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT); + LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN); + if (pcb->remote_port == tcphdr->src && + pcb->local_port == tcphdr->dest && + ip_addr_cmp(&(pcb->remote_ip), ¤t_iphdr_src) && + ip_addr_cmp(&(pcb->local_ip), ¤t_iphdr_dest)) { + + /* Move this PCB to the front of the list so that subsequent + lookups will be faster (we exploit locality in TCP segment + arrivals). */ + LWIP_ASSERT("tcp_input: pcb->next != pcb (before cache)", pcb->next != pcb); + if (prev != NULL) { + prev->next = pcb->next; + pcb->next = tcp_active_pcbs; + tcp_active_pcbs = pcb; + } + LWIP_ASSERT("tcp_input: pcb->next != pcb (after cache)", pcb->next != pcb); + break; + } + prev = pcb; + } + + if (pcb == NULL) { + /* If it did not go to an active connection, we check the connections + in the TIME-WAIT state. */ + for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); + if (pcb->remote_port == tcphdr->src && + pcb->local_port == tcphdr->dest && + ip_addr_cmp(&(pcb->remote_ip), ¤t_iphdr_src) && + ip_addr_cmp(&(pcb->local_ip), ¤t_iphdr_dest)) { + /* We don't really care enough to move this PCB to the front + of the list since we are not very likely to receive that + many segments for connections in TIME-WAIT. */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for TIME_WAITing connection.\n")); + tcp_timewait_input(pcb); + pbuf_free(p); + return; + } + } + + /* Finally, if we still did not get a match, we check all PCBs that + are LISTENing for incoming connections. */ + prev = NULL; + for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { + if (lpcb->local_port == tcphdr->dest) { +#if SO_REUSE + if (ip_addr_cmp(&(lpcb->local_ip), ¤t_iphdr_dest)) { + /* found an exact match */ + break; + } else if(ip_addr_isany(&(lpcb->local_ip))) { + /* found an ANY-match */ + lpcb_any = lpcb; + lpcb_prev = prev; + } +#else /* SO_REUSE */ + if (ip_addr_cmp(&(lpcb->local_ip), ¤t_iphdr_dest) || + ip_addr_isany(&(lpcb->local_ip))) { + /* found a match */ + break; + } +#endif /* SO_REUSE */ + } + prev = (struct tcp_pcb *)lpcb; + } +#if SO_REUSE + /* first try specific local IP */ + if (lpcb == NULL) { + /* only pass to ANY if no specific local IP has been found */ + lpcb = lpcb_any; + prev = lpcb_prev; + } +#endif /* SO_REUSE */ + if (lpcb != NULL) { + /* Move this PCB to the front of the list so that subsequent + lookups will be faster (we exploit locality in TCP segment + arrivals). */ + if (prev != NULL) { + ((struct tcp_pcb_listen *)prev)->next = lpcb->next; + /* our successor is the remainder of the listening list */ + lpcb->next = tcp_listen_pcbs.listen_pcbs; + /* put this listening pcb at the head of the listening list */ + tcp_listen_pcbs.listen_pcbs = lpcb; + } + + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n")); + tcp_listen_input(lpcb); + pbuf_free(p); + return; + } + } + +#if TCP_INPUT_DEBUG + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("+-+-+-+-+-+-+-+-+-+-+-+-+-+- tcp_input: flags ")); + tcp_debug_print_flags(TCPH_FLAGS(tcphdr)); + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n")); +#endif /* TCP_INPUT_DEBUG */ + + + if (pcb != NULL) { + /* The incoming segment belongs to a connection. */ +#if TCP_INPUT_DEBUG +#if TCP_DEBUG + tcp_debug_print_state(pcb->state); +#endif /* TCP_DEBUG */ +#endif /* TCP_INPUT_DEBUG */ + + /* Set up a tcp_seg structure. */ + inseg.next = NULL; + inseg.len = p->tot_len; + inseg.p = p; + inseg.tcphdr = tcphdr; + + recv_data = NULL; + recv_flags = 0; + + if (flags & TCP_PSH) { + p->flags |= PBUF_FLAG_PUSH; + } + + /* If there is data which was previously "refused" by upper layer */ + if (pcb->refused_data != NULL) { + if ((tcp_process_refused_data(pcb) == ERR_ABRT) || + ((pcb->refused_data != NULL) && (tcplen > 0))) { + /* pcb has been aborted or refused data is still refused and the new + segment contains data */ + TCP_STATS_INC(tcp.drop); + snmp_inc_tcpinerrs(); + goto aborted; + } + } + tcp_input_pcb = pcb; + err = tcp_process(pcb); + /* A return value of ERR_ABRT means that tcp_abort() was called + and that the pcb has been freed. If so, we don't do anything. */ + if (err != ERR_ABRT) { + if (recv_flags & TF_RESET) { + /* TF_RESET means that the connection was reset by the other + end. We then call the error callback to inform the + application that the connection is dead before we + deallocate the PCB. */ + TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_RST); + tcp_pcb_remove(&tcp_active_pcbs, pcb); + memp_free(MEMP_TCP_PCB, pcb); + } else if (recv_flags & TF_CLOSED) { + /* The connection has been closed and we will deallocate the + PCB. */ + if (!(pcb->flags & TF_RXCLOSED)) { + /* Connection closed although the application has only shut down the + tx side: call the PCB's err callback and indicate the closure to + ensure the application doesn't continue using the PCB. */ + TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_CLSD); + } + tcp_pcb_remove(&tcp_active_pcbs, pcb); + memp_free(MEMP_TCP_PCB, pcb); + } else { + err = ERR_OK; + /* If the application has registered a "sent" function to be + called when new send buffer space is available, we call it + now. */ + if (pcb->acked > 0) { + TCP_EVENT_SENT(pcb, pcb->acked, err); + if (err == ERR_ABRT) { + goto aborted; + } + } + + if (recv_data != NULL) { + LWIP_ASSERT("pcb->refused_data == NULL", pcb->refused_data == NULL); + if (pcb->flags & TF_RXCLOSED) { + /* received data although already closed -> abort (send RST) to + notify the remote host that not all data has been processed */ + pbuf_free(recv_data); + tcp_abort(pcb); + goto aborted; + } + + /* Notify application that data has been received. */ + TCP_EVENT_RECV(pcb, recv_data, ERR_OK, err); + if (err == ERR_ABRT) { + goto aborted; + } + + /* If the upper layer can't receive this data, store it */ + if (err != ERR_OK) { + pcb->refused_data = recv_data; + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: keep incoming packet, because pcb is \"full\"\n")); + } + } + + /* If a FIN segment was received, we call the callback + function with a NULL buffer to indicate EOF. */ + if (recv_flags & TF_GOT_FIN) { + if (pcb->refused_data != NULL) { + /* Delay this if we have refused data. */ + pcb->refused_data->flags |= PBUF_FLAG_TCP_FIN; + } else { + /* correct rcv_wnd as the application won't call tcp_recved() + for the FIN's seqno */ + if (pcb->rcv_wnd != TCP_WND) { + pcb->rcv_wnd++; + } + TCP_EVENT_CLOSED(pcb, err); + if (err == ERR_ABRT) { + goto aborted; + } + } + } + + tcp_input_pcb = NULL; + /* Try to send something out. */ + tcp_output(pcb); +#if TCP_INPUT_DEBUG +#if TCP_DEBUG + tcp_debug_print_state(pcb->state); +#endif /* TCP_DEBUG */ +#endif /* TCP_INPUT_DEBUG */ + } + } + /* Jump target if pcb has been aborted in a callback (by calling tcp_abort()). + Below this line, 'pcb' may not be dereferenced! */ +aborted: + tcp_input_pcb = NULL; + recv_data = NULL; + + /* give up our reference to inseg.p */ + if (inseg.p != NULL) + { + pbuf_free(inseg.p); + inseg.p = NULL; + } + } else { + + /* If no matching PCB was found, send a TCP RST (reset) to the + sender. */ + LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n")); + if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) { + TCP_STATS_INC(tcp.proterr); + TCP_STATS_INC(tcp.drop); + tcp_rst(ackno, seqno + tcplen, + ip_current_dest_addr(), ip_current_src_addr(), + tcphdr->dest, tcphdr->src); + } + pbuf_free(p); + } + + LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane()); + PERF_STOP("tcp_input"); + return; +dropped: + TCP_STATS_INC(tcp.drop); + snmp_inc_tcpinerrs(); + pbuf_free(p); +} + +/** + * Called by tcp_input() when a segment arrives for a listening + * connection (from tcp_input()). + * + * @param pcb the tcp_pcb_listen for which a segment arrived + * @return ERR_OK if the segment was processed + * another err_t on error + * + * @note the return value is not (yet?) used in tcp_input() + * @note the segment which arrived is saved in global variables, therefore only the pcb + * involved is passed as a parameter to this function + */ +static err_t +tcp_listen_input(struct tcp_pcb_listen *pcb) +{ + struct tcp_pcb *npcb; + err_t rc; + + if (flags & TCP_RST) { + /* An incoming RST should be ignored. Return. */ + return ERR_OK; + } + + /* In the LISTEN state, we check for incoming SYN segments, + creates a new PCB, and responds with a SYN|ACK. */ + if (flags & TCP_ACK) { + /* For incoming segments with the ACK flag set, respond with a + RST. */ + LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n")); + tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), + ip_current_src_addr(), tcphdr->dest, tcphdr->src); + } else if (flags & TCP_SYN) { + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest)); +#if TCP_LISTEN_BACKLOG + if (pcb->accepts_pending >= pcb->backlog) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: listen backlog exceeded for port %"U16_F"\n", tcphdr->dest)); + return ERR_ABRT; + } +#endif /* TCP_LISTEN_BACKLOG */ + npcb = tcp_alloc(pcb->prio); + /* If a new PCB could not be created (probably due to lack of memory), + we don't do anything, but rely on the sender will retransmit the + SYN at a time when we have more memory available. */ + if (npcb == NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n")); + TCP_STATS_INC(tcp.memerr); + return ERR_MEM; + } +#if TCP_LISTEN_BACKLOG + pcb->accepts_pending++; +#endif /* TCP_LISTEN_BACKLOG */ + /* Set up the new PCB. */ + ip_addr_copy(npcb->local_ip, current_iphdr_dest); + npcb->local_port = pcb->local_port; + ip_addr_copy(npcb->remote_ip, current_iphdr_src); + npcb->remote_port = tcphdr->src; + npcb->state = SYN_RCVD; + npcb->rcv_nxt = seqno + 1; + npcb->rcv_ann_right_edge = npcb->rcv_nxt; + npcb->snd_wnd = tcphdr->wnd; + npcb->snd_wnd_max = tcphdr->wnd; + npcb->ssthresh = npcb->snd_wnd; + npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */ + npcb->callback_arg = pcb->callback_arg; +#if LWIP_CALLBACK_API + npcb->accept = pcb->accept; +#endif /* LWIP_CALLBACK_API */ + /* inherit socket options */ + npcb->so_options = pcb->so_options & SOF_INHERITED; + /* Register the new PCB so that we can begin receiving segments + for it. */ + TCP_REG_ACTIVE(npcb); + + /* Parse any options in the SYN. */ + tcp_parseopt(npcb); +#if TCP_CALCULATE_EFF_SEND_MSS + npcb->mss = tcp_eff_send_mss(npcb->mss, &(npcb->remote_ip)); +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + + snmp_inc_tcppassiveopens(); + + /* Send a SYN|ACK together with the MSS option. */ + rc = tcp_enqueue_flags(npcb, TCP_SYN | TCP_ACK); + if (rc != ERR_OK) { + tcp_abandon(npcb, 0); + return rc; + } + return tcp_output(npcb); + } + return ERR_OK; +} + +/** + * Called by tcp_input() when a segment arrives for a connection in + * TIME_WAIT. + * + * @param pcb the tcp_pcb for which a segment arrived + * + * @note the segment which arrived is saved in global variables, therefore only the pcb + * involved is passed as a parameter to this function + */ +static err_t +tcp_timewait_input(struct tcp_pcb *pcb) +{ + /* RFC 1337: in TIME_WAIT, ignore RST and ACK FINs + any 'acceptable' segments */ + /* RFC 793 3.9 Event Processing - Segment Arrives: + * - first check sequence number - we skip that one in TIME_WAIT (always + * acceptable since we only send ACKs) + * - second check the RST bit (... return) */ + if (flags & TCP_RST) { + return ERR_OK; + } + /* - fourth, check the SYN bit, */ + if (flags & TCP_SYN) { + /* If an incoming segment is not acceptable, an acknowledgment + should be sent in reply */ + if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt+pcb->rcv_wnd)) { + /* If the SYN is in the window it is an error, send a reset */ + tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(), + tcphdr->dest, tcphdr->src); + return ERR_OK; + } + } else if (flags & TCP_FIN) { + /* - eighth, check the FIN bit: Remain in the TIME-WAIT state. + Restart the 2 MSL time-wait timeout.*/ + pcb->tmr = tcp_ticks; + } + + if ((tcplen > 0)) { + /* Acknowledge data, FIN or out-of-window SYN */ + pcb->flags |= TF_ACK_NOW; + return tcp_output(pcb); + } + return ERR_OK; +} + +/** + * Implements the TCP state machine. Called by tcp_input. In some + * states tcp_receive() is called to receive data. The tcp_seg + * argument will be freed by the caller (tcp_input()) unless the + * recv_data pointer in the pcb is set. + * + * @param pcb the tcp_pcb for which a segment arrived + * + * @note the segment which arrived is saved in global variables, therefore only the pcb + * involved is passed as a parameter to this function + */ +static err_t +tcp_process(struct tcp_pcb *pcb) +{ + struct tcp_seg *rseg; + u8_t acceptable = 0; + err_t err; + + err = ERR_OK; + + /* Process incoming RST segments. */ + if (flags & TCP_RST) { + /* First, determine if the reset is acceptable. */ + if (pcb->state == SYN_SENT) { + if (ackno == pcb->snd_nxt) { + acceptable = 1; + } + } else { + if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, + pcb->rcv_nxt+pcb->rcv_wnd)) { + acceptable = 1; + } + } + + if (acceptable) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: Connection RESET\n")); + LWIP_ASSERT("tcp_input: pcb->state != CLOSED", pcb->state != CLOSED); + recv_flags |= TF_RESET; + pcb->flags &= ~TF_ACK_DELAY; + return ERR_RST; + } else { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n", + seqno, pcb->rcv_nxt)); + LWIP_DEBUGF(TCP_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n", + seqno, pcb->rcv_nxt)); + return ERR_OK; + } + } + + if ((flags & TCP_SYN) && (pcb->state != SYN_SENT && pcb->state != SYN_RCVD)) { + /* Cope with new connection attempt after remote end crashed */ + tcp_ack_now(pcb); + return ERR_OK; + } + + if ((pcb->flags & TF_RXCLOSED) == 0) { + /* Update the PCB (in)activity timer unless rx is closed (see tcp_shutdown) */ + pcb->tmr = tcp_ticks; + } + pcb->keep_cnt_sent = 0; + + tcp_parseopt(pcb); + + /* Do different things depending on the TCP state. */ + switch (pcb->state) { + case SYN_SENT: + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %"U32_F" pcb->snd_nxt %"U32_F" unacked %"U32_F"\n", ackno, + pcb->snd_nxt, ntohl(pcb->unacked->tcphdr->seqno))); + /* received SYN ACK with expected sequence number? */ + if ((flags & TCP_ACK) && (flags & TCP_SYN) + && ackno == ntohl(pcb->unacked->tcphdr->seqno) + 1) { + pcb->snd_buf++; + pcb->rcv_nxt = seqno + 1; + pcb->rcv_ann_right_edge = pcb->rcv_nxt; + pcb->lastack = ackno; + pcb->snd_wnd = tcphdr->wnd; + pcb->snd_wnd_max = tcphdr->wnd; + pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */ + pcb->state = ESTABLISHED; + +#if TCP_CALCULATE_EFF_SEND_MSS + pcb->mss = tcp_eff_send_mss(pcb->mss, &(pcb->remote_ip)); +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + + /* Set ssthresh again after changing pcb->mss (already set in tcp_connect + * but for the default value of pcb->mss) */ + pcb->ssthresh = pcb->mss * 10; + + pcb->cwnd = ((pcb->cwnd == 1) ? (pcb->mss * 2) : pcb->mss); + LWIP_ASSERT("pcb->snd_queuelen > 0", (pcb->snd_queuelen > 0)); + --pcb->snd_queuelen; + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %"U16_F"\n", (u16_t)pcb->snd_queuelen)); + rseg = pcb->unacked; + pcb->unacked = rseg->next; + tcp_seg_free(rseg); + + /* If there's nothing left to acknowledge, stop the retransmit + timer, otherwise reset it to start again */ + if(pcb->unacked == NULL) + pcb->rtime = -1; + else { + pcb->rtime = 0; + pcb->nrtx = 0; + } + + /* Call the user specified function to call when sucessfully + * connected. */ + TCP_EVENT_CONNECTED(pcb, ERR_OK, err); + if (err == ERR_ABRT) { + return ERR_ABRT; + } + tcp_ack_now(pcb); + } + /* received ACK? possibly a half-open connection */ + else if (flags & TCP_ACK) { + /* send a RST to bring the other side in a non-synchronized state. */ + tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(), + tcphdr->dest, tcphdr->src); + } + break; + case SYN_RCVD: + if (flags & TCP_ACK) { + /* expected ACK number? */ + if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) { + u16_t old_cwnd; + pcb->state = ESTABLISHED; + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); +#if LWIP_CALLBACK_API + LWIP_ASSERT("pcb->accept != NULL", pcb->accept != NULL); +#endif + /* Call the accept function. */ + TCP_EVENT_ACCEPT(pcb, ERR_OK, err); + if (err != ERR_OK) { + /* If the accept function returns with an error, we abort + * the connection. */ + /* Already aborted? */ + if (err != ERR_ABRT) { + tcp_abort(pcb); + } + return ERR_ABRT; + } + old_cwnd = pcb->cwnd; + /* If there was any data contained within this ACK, + * we'd better pass it on to the application as well. */ + tcp_receive(pcb); + + /* Prevent ACK for SYN to generate a sent event */ + if (pcb->acked != 0) { + pcb->acked--; + } + + pcb->cwnd = ((old_cwnd == 1) ? (pcb->mss * 2) : pcb->mss); + + if (recv_flags & TF_GOT_FIN) { + tcp_ack_now(pcb); + pcb->state = CLOSE_WAIT; + } + } else { + /* incorrect ACK number, send RST */ + tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(), + tcphdr->dest, tcphdr->src); + } + } else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) { + /* Looks like another copy of the SYN - retransmit our SYN-ACK */ + tcp_rexmit(pcb); + } + break; + case CLOSE_WAIT: + /* FALLTHROUGH */ + case ESTABLISHED: + tcp_receive(pcb); + if (recv_flags & TF_GOT_FIN) { /* passive close */ + tcp_ack_now(pcb); + pcb->state = CLOSE_WAIT; + } + break; + case FIN_WAIT_1: + tcp_receive(pcb); + if (recv_flags & TF_GOT_FIN) { + if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) { + LWIP_DEBUGF(TCP_DEBUG, + ("TCP connection closed: FIN_WAIT_1 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); + tcp_ack_now(pcb); + tcp_pcb_purge(pcb); + TCP_RMV_ACTIVE(pcb); + pcb->state = TIME_WAIT; + TCP_REG(&tcp_tw_pcbs, pcb); + } else { + tcp_ack_now(pcb); + pcb->state = CLOSING; + } + } else if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) { + pcb->state = FIN_WAIT_2; + } + break; + case FIN_WAIT_2: + tcp_receive(pcb); + if (recv_flags & TF_GOT_FIN) { + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: FIN_WAIT_2 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); + tcp_ack_now(pcb); + tcp_pcb_purge(pcb); + TCP_RMV_ACTIVE(pcb); + pcb->state = TIME_WAIT; + TCP_REG(&tcp_tw_pcbs, pcb); + } + break; + case CLOSING: + tcp_receive(pcb); + if (flags & TCP_ACK && ackno == pcb->snd_nxt) { + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: CLOSING %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); + tcp_pcb_purge(pcb); + TCP_RMV_ACTIVE(pcb); + pcb->state = TIME_WAIT; + TCP_REG(&tcp_tw_pcbs, pcb); + } + break; + case LAST_ACK: + tcp_receive(pcb); + if (flags & TCP_ACK && ackno == pcb->snd_nxt) { + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: LAST_ACK %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); + /* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */ + recv_flags |= TF_CLOSED; + } + break; + default: + break; + } + return ERR_OK; +} + +#if TCP_QUEUE_OOSEQ +/** + * Insert segment into the list (segments covered with new one will be deleted) + * + * Called from tcp_receive() + */ +static void +tcp_oos_insert_segment(struct tcp_seg *cseg, struct tcp_seg *next) +{ + struct tcp_seg *old_seg; + + if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) { + /* received segment overlaps all following segments */ + tcp_segs_free(next); + next = NULL; + } + else { + /* delete some following segments + oos queue may have segments with FIN flag */ + while (next && + TCP_SEQ_GEQ((seqno + cseg->len), + (next->tcphdr->seqno + next->len))) { + /* cseg with FIN already processed */ + if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) { + TCPH_SET_FLAG(cseg->tcphdr, TCP_FIN); + } + old_seg = next; + next = next->next; + tcp_seg_free(old_seg); + } + if (next && + TCP_SEQ_GT(seqno + cseg->len, next->tcphdr->seqno)) { + /* We need to trim the incoming segment. */ + cseg->len = (u16_t)(next->tcphdr->seqno - seqno); + pbuf_realloc(cseg->p, cseg->len); + } + } + cseg->next = next; +} +#endif /* TCP_QUEUE_OOSEQ */ + +/** + * Called by tcp_process. Checks if the given segment is an ACK for outstanding + * data, and if so frees the memory of the buffered data. Next, is places the + * segment on any of the receive queues (pcb->recved or pcb->ooseq). If the segment + * is buffered, the pbuf is referenced by pbuf_ref so that it will not be freed until + * it has been removed from the buffer. + * + * If the incoming segment constitutes an ACK for a segment that was used for RTT + * estimation, the RTT is estimated here as well. + * + * Called from tcp_process(). + */ +static void +tcp_receive(struct tcp_pcb *pcb) +{ + struct tcp_seg *next; +#if TCP_QUEUE_OOSEQ + struct tcp_seg *prev, *cseg; +#endif /* TCP_QUEUE_OOSEQ */ + struct pbuf *p; + s32_t off; + s16_t m; + u32_t right_wnd_edge; + u16_t new_tot_len; + int found_dupack = 0; +#if TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS + u32_t ooseq_blen; + u16_t ooseq_qlen; +#endif /* TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS */ + + LWIP_ASSERT("tcp_receive: wrong state", pcb->state >= ESTABLISHED); + + if (flags & TCP_ACK) { + right_wnd_edge = pcb->snd_wnd + pcb->snd_wl2; + + /* Update window. */ + if (TCP_SEQ_LT(pcb->snd_wl1, seqno) || + (pcb->snd_wl1 == seqno && TCP_SEQ_LT(pcb->snd_wl2, ackno)) || + (pcb->snd_wl2 == ackno && tcphdr->wnd > pcb->snd_wnd)) { + pcb->snd_wnd = tcphdr->wnd; + /* keep track of the biggest window announced by the remote host to calculate + the maximum segment size */ + if (pcb->snd_wnd_max < tcphdr->wnd) { + pcb->snd_wnd_max = tcphdr->wnd; + } + pcb->snd_wl1 = seqno; + pcb->snd_wl2 = ackno; + if (pcb->snd_wnd == 0) { + if (pcb->persist_backoff == 0) { + /* start persist timer */ + pcb->persist_cnt = 0; + pcb->persist_backoff = 1; + } + } else if (pcb->persist_backoff > 0) { + /* stop persist timer */ + pcb->persist_backoff = 0; + } + LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: window update %"U16_F"\n", pcb->snd_wnd)); +#if TCP_WND_DEBUG + } else { + if (pcb->snd_wnd != tcphdr->wnd) { + LWIP_DEBUGF(TCP_WND_DEBUG, + ("tcp_receive: no window update lastack %"U32_F" ackno %" + U32_F" wl1 %"U32_F" seqno %"U32_F" wl2 %"U32_F"\n", + pcb->lastack, ackno, pcb->snd_wl1, seqno, pcb->snd_wl2)); + } +#endif /* TCP_WND_DEBUG */ + } + + /* (From Stevens TCP/IP Illustrated Vol II, p970.) Its only a + * duplicate ack if: + * 1) It doesn't ACK new data + * 2) length of received packet is zero (i.e. no payload) + * 3) the advertised window hasn't changed + * 4) There is outstanding unacknowledged data (retransmission timer running) + * 5) The ACK is == biggest ACK sequence number so far seen (snd_una) + * + * If it passes all five, should process as a dupack: + * a) dupacks < 3: do nothing + * b) dupacks == 3: fast retransmit + * c) dupacks > 3: increase cwnd + * + * If it only passes 1-3, should reset dupack counter (and add to + * stats, which we don't do in lwIP) + * + * If it only passes 1, should reset dupack counter + * + */ + + /* Clause 1 */ + if (TCP_SEQ_LEQ(ackno, pcb->lastack)) { + pcb->acked = 0; + /* Clause 2 */ + if (tcplen == 0) { + /* Clause 3 */ + if (pcb->snd_wl2 + pcb->snd_wnd == right_wnd_edge){ + /* Clause 4 */ + if (pcb->rtime >= 0) { + /* Clause 5 */ + if (pcb->lastack == ackno) { + found_dupack = 1; + if ((u8_t)(pcb->dupacks + 1) > pcb->dupacks) { + ++pcb->dupacks; + } + if (pcb->dupacks > 3) { + /* Inflate the congestion window, but not if it means that + the value overflows. */ + if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { + pcb->cwnd += pcb->mss; + } + } else if (pcb->dupacks == 3) { + /* Do fast retransmit */ + tcp_rexmit_fast(pcb); + } + } + } + } + } + /* If Clause (1) or more is true, but not a duplicate ack, reset + * count of consecutive duplicate acks */ + if (!found_dupack) { + pcb->dupacks = 0; + } + } else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)){ + /* We come here when the ACK acknowledges new data. */ + + /* Reset the "IN Fast Retransmit" flag, since we are no longer + in fast retransmit. Also reset the congestion window to the + slow start threshold. */ + if (pcb->flags & TF_INFR) { + pcb->flags &= ~TF_INFR; + pcb->cwnd = pcb->ssthresh; + } + + /* Reset the number of retransmissions. */ + pcb->nrtx = 0; + + /* Reset the retransmission time-out. */ + pcb->rto = (pcb->sa >> 3) + pcb->sv; + + /* Update the send buffer space. Diff between the two can never exceed 64K? */ + pcb->acked = (u16_t)(ackno - pcb->lastack); + + pcb->snd_buf += pcb->acked; + + /* Reset the fast retransmit variables. */ + pcb->dupacks = 0; + pcb->lastack = ackno; + + /* Update the congestion control variables (cwnd and + ssthresh). */ + if (pcb->state >= ESTABLISHED) { + if (pcb->cwnd < pcb->ssthresh) { + if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { + pcb->cwnd += pcb->mss; + } + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: slow start cwnd %"U16_F"\n", pcb->cwnd)); + } else { + u16_t new_cwnd = (pcb->cwnd + pcb->mss * pcb->mss / pcb->cwnd); + if (new_cwnd > pcb->cwnd) { + pcb->cwnd = new_cwnd; + } + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %"U16_F"\n", pcb->cwnd)); + } + } + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %"U32_F", unacked->seqno %"U32_F":%"U32_F"\n", + ackno, + pcb->unacked != NULL? + ntohl(pcb->unacked->tcphdr->seqno): 0, + pcb->unacked != NULL? + ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0)); + + /* Remove segment from the unacknowledged list if the incoming + ACK acknowlegdes them. */ + while (pcb->unacked != NULL && + TCP_SEQ_LEQ(ntohl(pcb->unacked->tcphdr->seqno) + + TCP_TCPLEN(pcb->unacked), ackno)) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unacked\n", + ntohl(pcb->unacked->tcphdr->seqno), + ntohl(pcb->unacked->tcphdr->seqno) + + TCP_TCPLEN(pcb->unacked))); + + next = pcb->unacked; + pcb->unacked = pcb->unacked->next; + + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen)); + LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p))); + /* Prevent ACK for FIN to generate a sent event */ + if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) { + pcb->acked--; + } + + pcb->snd_queuelen -= pbuf_clen(next->p); + tcp_seg_free(next); + + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unacked)\n", (u16_t)pcb->snd_queuelen)); + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL || + pcb->unsent != NULL); + } + } + + /* If there's nothing left to acknowledge, stop the retransmit + timer, otherwise reset it to start again */ + if(pcb->unacked == NULL) + pcb->rtime = -1; + else + pcb->rtime = 0; + + pcb->polltmr = 0; + } else { + /* Fix bug bug #21582: out of sequence ACK, didn't really ack anything */ + pcb->acked = 0; + } + + /* We go through the ->unsent list to see if any of the segments + on the list are acknowledged by the ACK. This may seem + strange since an "unsent" segment shouldn't be acked. The + rationale is that lwIP puts all outstanding segments on the + ->unsent list after a retransmission, so these segments may + in fact have been sent once. */ + while (pcb->unsent != NULL && + TCP_SEQ_BETWEEN(ackno, ntohl(pcb->unsent->tcphdr->seqno) + + TCP_TCPLEN(pcb->unsent), pcb->snd_nxt)) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unsent\n", + ntohl(pcb->unsent->tcphdr->seqno), ntohl(pcb->unsent->tcphdr->seqno) + + TCP_TCPLEN(pcb->unsent))); + + next = pcb->unsent; + pcb->unsent = pcb->unsent->next; +#if TCP_OVERSIZE + if (pcb->unsent == NULL) { + pcb->unsent_oversize = 0; + } +#endif /* TCP_OVERSIZE */ + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen)); + LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p))); + /* Prevent ACK for FIN to generate a sent event */ + if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) { + pcb->acked--; + } + pcb->snd_queuelen -= pbuf_clen(next->p); + tcp_seg_free(next); + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unsent)\n", (u16_t)pcb->snd_queuelen)); + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_receive: valid queue length", + pcb->unacked != NULL || pcb->unsent != NULL); + } + } + /* End of ACK for new data processing. */ + + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %"U32_F" rtseq %"U32_F" ackno %"U32_F"\n", + pcb->rttest, pcb->rtseq, ackno)); + + /* RTT estimation calculations. This is done by checking if the + incoming segment acknowledges the segment we use to take a + round-trip time measurement. */ + if (pcb->rttest && TCP_SEQ_LT(pcb->rtseq, ackno)) { + /* diff between this shouldn't exceed 32K since this are tcp timer ticks + and a round-trip shouldn't be that long... */ + m = (s16_t)(tcp_ticks - pcb->rttest); + + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: experienced rtt %"U16_F" ticks (%"U16_F" msec).\n", + m, m * TCP_SLOW_INTERVAL)); + + /* This is taken directly from VJs original code in his paper */ + m = m - (pcb->sa >> 3); + pcb->sa += m; + if (m < 0) { + m = -m; + } + m = m - (pcb->sv >> 2); + pcb->sv += m; + pcb->rto = (pcb->sa >> 3) + pcb->sv; + + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: RTO %"U16_F" (%"U16_F" milliseconds)\n", + pcb->rto, pcb->rto * TCP_SLOW_INTERVAL)); + + pcb->rttest = 0; + } + } + + /* If the incoming segment contains data, we must process it + further unless the pcb already received a FIN. + (RFC 793, chapeter 3.9, "SEGMENT ARRIVES" in states CLOSE-WAIT, CLOSING, + LAST-ACK and TIME-WAIT: "Ignore the segment text.") */ + if ((tcplen > 0) && (pcb->state < CLOSE_WAIT)) { + /* This code basically does three things: + + +) If the incoming segment contains data that is the next + in-sequence data, this data is passed to the application. This + might involve trimming the first edge of the data. The rcv_nxt + variable and the advertised window are adjusted. + + +) If the incoming segment has data that is above the next + sequence number expected (->rcv_nxt), the segment is placed on + the ->ooseq queue. This is done by finding the appropriate + place in the ->ooseq queue (which is ordered by sequence + number) and trim the segment in both ends if needed. An + immediate ACK is sent to indicate that we received an + out-of-sequence segment. + + +) Finally, we check if the first segment on the ->ooseq queue + now is in sequence (i.e., if rcv_nxt >= ooseq->seqno). If + rcv_nxt > ooseq->seqno, we must trim the first edge of the + segment on ->ooseq before we adjust rcv_nxt. The data in the + segments that are now on sequence are chained onto the + incoming segment so that we only need to call the application + once. + */ + + /* First, we check if we must trim the first edge. We have to do + this if the sequence number of the incoming segment is less + than rcv_nxt, and the sequence number plus the length of the + segment is larger than rcv_nxt. */ + /* if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){ + if (TCP_SEQ_LT(pcb->rcv_nxt, seqno + tcplen)) {*/ + if (TCP_SEQ_BETWEEN(pcb->rcv_nxt, seqno + 1, seqno + tcplen - 1)){ + /* Trimming the first edge is done by pushing the payload + pointer in the pbuf downwards. This is somewhat tricky since + we do not want to discard the full contents of the pbuf up to + the new starting point of the data since we have to keep the + TCP header which is present in the first pbuf in the chain. + + What is done is really quite a nasty hack: the first pbuf in + the pbuf chain is pointed to by inseg.p. Since we need to be + able to deallocate the whole pbuf, we cannot change this + inseg.p pointer to point to any of the later pbufs in the + chain. Instead, we point the ->payload pointer in the first + pbuf to data in one of the later pbufs. We also set the + inseg.data pointer to point to the right place. This way, the + ->p pointer will still point to the first pbuf, but the + ->p->payload pointer will point to data in another pbuf. + + After we are done with adjusting the pbuf pointers we must + adjust the ->data pointer in the seg and the segment + length.*/ + + off = pcb->rcv_nxt - seqno; + p = inseg.p; + LWIP_ASSERT("inseg.p != NULL", inseg.p); + LWIP_ASSERT("insane offset!", (off < 0x7fff)); + if (inseg.p->len < off) { + LWIP_ASSERT("pbuf too short!", (((s32_t)inseg.p->tot_len) >= off)); + new_tot_len = (u16_t)(inseg.p->tot_len - off); + while (p->len < off) { + off -= p->len; + /* KJM following line changed (with addition of new_tot_len var) + to fix bug #9076 + inseg.p->tot_len -= p->len; */ + p->tot_len = new_tot_len; + p->len = 0; + p = p->next; + } + if(pbuf_header(p, (s16_t)-off)) { + /* Do we need to cope with this failing? Assert for now */ + LWIP_ASSERT("pbuf_header failed", 0); + } + } else { + if(pbuf_header(inseg.p, (s16_t)-off)) { + /* Do we need to cope with this failing? Assert for now */ + LWIP_ASSERT("pbuf_header failed", 0); + } + } + inseg.len -= (u16_t)(pcb->rcv_nxt - seqno); + inseg.tcphdr->seqno = seqno = pcb->rcv_nxt; + } + else { + if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){ + /* the whole segment is < rcv_nxt */ + /* must be a duplicate of a packet that has already been correctly handled */ + + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %"U32_F"\n", seqno)); + tcp_ack_now(pcb); + } + } + + /* The sequence number must be within the window (above rcv_nxt + and below rcv_nxt + rcv_wnd) in order to be further + processed. */ + if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, + pcb->rcv_nxt + pcb->rcv_wnd - 1)){ + if (pcb->rcv_nxt == seqno) { + /* The incoming segment is the next in sequence. We check if + we have to trim the end of the segment and update rcv_nxt + and pass the data to the application. */ + tcplen = TCP_TCPLEN(&inseg); + + if (tcplen > pcb->rcv_wnd) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, + ("tcp_receive: other end overran receive window" + "seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n", + seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd)); + if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { + /* Must remove the FIN from the header as we're trimming + * that byte of sequence-space from the packet */ + TCPH_FLAGS_SET(inseg.tcphdr, TCPH_FLAGS(inseg.tcphdr) &~ TCP_FIN); + } + /* Adjust length of segment to fit in the window. */ + inseg.len = pcb->rcv_wnd; + if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) { + inseg.len -= 1; + } + pbuf_realloc(inseg.p, inseg.len); + tcplen = TCP_TCPLEN(&inseg); + LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n", + (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd)); + } +#if TCP_QUEUE_OOSEQ + /* Received in-sequence data, adjust ooseq data if: + - FIN has been received or + - inseq overlaps with ooseq */ + if (pcb->ooseq != NULL) { + if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, + ("tcp_receive: received in-order FIN, binning ooseq queue\n")); + /* Received in-order FIN means anything that was received + * out of order must now have been received in-order, so + * bin the ooseq queue */ + while (pcb->ooseq != NULL) { + struct tcp_seg *old_ooseq = pcb->ooseq; + pcb->ooseq = pcb->ooseq->next; + tcp_seg_free(old_ooseq); + } + } else { + next = pcb->ooseq; + /* Remove all segments on ooseq that are covered by inseg already. + * FIN is copied from ooseq to inseg if present. */ + while (next && + TCP_SEQ_GEQ(seqno + tcplen, + next->tcphdr->seqno + next->len)) { + /* inseg cannot have FIN here (already processed above) */ + if (TCPH_FLAGS(next->tcphdr) & TCP_FIN && + (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) == 0) { + TCPH_SET_FLAG(inseg.tcphdr, TCP_FIN); + tcplen = TCP_TCPLEN(&inseg); + } + prev = next; + next = next->next; + tcp_seg_free(prev); + } + /* Now trim right side of inseg if it overlaps with the first + * segment on ooseq */ + if (next && + TCP_SEQ_GT(seqno + tcplen, + next->tcphdr->seqno)) { + /* inseg cannot have FIN here (already processed above) */ + inseg.len = (u16_t)(next->tcphdr->seqno - seqno); + if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) { + inseg.len -= 1; + } + pbuf_realloc(inseg.p, inseg.len); + tcplen = TCP_TCPLEN(&inseg); + LWIP_ASSERT("tcp_receive: segment not trimmed correctly to ooseq queue\n", + (seqno + tcplen) == next->tcphdr->seqno); + } + pcb->ooseq = next; + } + } +#endif /* TCP_QUEUE_OOSEQ */ + + pcb->rcv_nxt = seqno + tcplen; + + /* Update the receiver's (our) window. */ + LWIP_ASSERT("tcp_receive: tcplen > rcv_wnd\n", pcb->rcv_wnd >= tcplen); + pcb->rcv_wnd -= tcplen; + + tcp_update_rcv_ann_wnd(pcb); + + /* If there is data in the segment, we make preparations to + pass this up to the application. The ->recv_data variable + is used for holding the pbuf that goes to the + application. The code for reassembling out-of-sequence data + chains its data on this pbuf as well. + + If the segment was a FIN, we set the TF_GOT_FIN flag that will + be used to indicate to the application that the remote side has + closed its end of the connection. */ + if (inseg.p->tot_len > 0) { + recv_data = inseg.p; + /* Since this pbuf now is the responsibility of the + application, we delete our reference to it so that we won't + (mistakingly) deallocate it. */ + inseg.p = NULL; + } + if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN.\n")); + recv_flags |= TF_GOT_FIN; + } + +#if TCP_QUEUE_OOSEQ + /* We now check if we have segments on the ->ooseq queue that + are now in sequence. */ + while (pcb->ooseq != NULL && + pcb->ooseq->tcphdr->seqno == pcb->rcv_nxt) { + + cseg = pcb->ooseq; + seqno = pcb->ooseq->tcphdr->seqno; + + pcb->rcv_nxt += TCP_TCPLEN(cseg); + LWIP_ASSERT("tcp_receive: ooseq tcplen > rcv_wnd\n", + pcb->rcv_wnd >= TCP_TCPLEN(cseg)); + pcb->rcv_wnd -= TCP_TCPLEN(cseg); + + tcp_update_rcv_ann_wnd(pcb); + + if (cseg->p->tot_len > 0) { + /* Chain this pbuf onto the pbuf that we will pass to + the application. */ + if (recv_data) { + pbuf_cat(recv_data, cseg->p); + } else { + recv_data = cseg->p; + } + cseg->p = NULL; + } + if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n")); + recv_flags |= TF_GOT_FIN; + if (pcb->state == ESTABLISHED) { /* force passive close or we can move to active close */ + pcb->state = CLOSE_WAIT; + } + } + + pcb->ooseq = cseg->next; + tcp_seg_free(cseg); + } +#endif /* TCP_QUEUE_OOSEQ */ + + + /* Acknowledge the segment(s). */ + tcp_ack(pcb); + + } else { + /* We get here if the incoming segment is out-of-sequence. */ + tcp_send_empty_ack(pcb); +#if TCP_QUEUE_OOSEQ + /* We queue the segment on the ->ooseq queue. */ + if (pcb->ooseq == NULL) { + pcb->ooseq = tcp_seg_copy(&inseg); + } else { + /* If the queue is not empty, we walk through the queue and + try to find a place where the sequence number of the + incoming segment is between the sequence numbers of the + previous and the next segment on the ->ooseq queue. That is + the place where we put the incoming segment. If needed, we + trim the second edges of the previous and the incoming + segment so that it will fit into the sequence. + + If the incoming segment has the same sequence number as a + segment on the ->ooseq queue, we discard the segment that + contains less data. */ + + prev = NULL; + for(next = pcb->ooseq; next != NULL; next = next->next) { + if (seqno == next->tcphdr->seqno) { + /* The sequence number of the incoming segment is the + same as the sequence number of the segment on + ->ooseq. We check the lengths to see which one to + discard. */ + if (inseg.len > next->len) { + /* The incoming segment is larger than the old + segment. We replace some segments with the new + one. */ + cseg = tcp_seg_copy(&inseg); + if (cseg != NULL) { + if (prev != NULL) { + prev->next = cseg; + } else { + pcb->ooseq = cseg; + } + tcp_oos_insert_segment(cseg, next); + } + break; + } else { + /* Either the lenghts are the same or the incoming + segment was smaller than the old one; in either + case, we ditch the incoming segment. */ + break; + } + } else { + if (prev == NULL) { + if (TCP_SEQ_LT(seqno, next->tcphdr->seqno)) { + /* The sequence number of the incoming segment is lower + than the sequence number of the first segment on the + queue. We put the incoming segment first on the + queue. */ + cseg = tcp_seg_copy(&inseg); + if (cseg != NULL) { + pcb->ooseq = cseg; + tcp_oos_insert_segment(cseg, next); + } + break; + } + } else { + /*if (TCP_SEQ_LT(prev->tcphdr->seqno, seqno) && + TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {*/ + if (TCP_SEQ_BETWEEN(seqno, prev->tcphdr->seqno+1, next->tcphdr->seqno-1)) { + /* The sequence number of the incoming segment is in + between the sequence numbers of the previous and + the next segment on ->ooseq. We trim trim the previous + segment, delete next segments that included in received segment + and trim received, if needed. */ + cseg = tcp_seg_copy(&inseg); + if (cseg != NULL) { + if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) { + /* We need to trim the prev segment. */ + prev->len = (u16_t)(seqno - prev->tcphdr->seqno); + pbuf_realloc(prev->p, prev->len); + } + prev->next = cseg; + tcp_oos_insert_segment(cseg, next); + } + break; + } + } + /* If the "next" segment is the last segment on the + ooseq queue, we add the incoming segment to the end + of the list. */ + if (next->next == NULL && + TCP_SEQ_GT(seqno, next->tcphdr->seqno)) { + if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) { + /* segment "next" already contains all data */ + break; + } + next->next = tcp_seg_copy(&inseg); + if (next->next != NULL) { + if (TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) { + /* We need to trim the last segment. */ + next->len = (u16_t)(seqno - next->tcphdr->seqno); + pbuf_realloc(next->p, next->len); + } + /* check if the remote side overruns our receive window */ + if ((u32_t)tcplen + seqno > pcb->rcv_nxt + (u32_t)pcb->rcv_wnd) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, + ("tcp_receive: other end overran receive window" + "seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n", + seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd)); + if (TCPH_FLAGS(next->next->tcphdr) & TCP_FIN) { + /* Must remove the FIN from the header as we're trimming + * that byte of sequence-space from the packet */ + TCPH_FLAGS_SET(next->next->tcphdr, TCPH_FLAGS(next->next->tcphdr) &~ TCP_FIN); + } + /* Adjust length of segment to fit in the window. */ + next->next->len = pcb->rcv_nxt + pcb->rcv_wnd - seqno; + pbuf_realloc(next->next->p, next->next->len); + tcplen = TCP_TCPLEN(next->next); + LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n", + (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd)); + } + } + break; + } + } + prev = next; + } + } +#if TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS + /* Check that the data on ooseq doesn't exceed one of the limits + and throw away everything above that limit. */ + ooseq_blen = 0; + ooseq_qlen = 0; + prev = NULL; + for(next = pcb->ooseq; next != NULL; prev = next, next = next->next) { + struct pbuf *p = next->p; + ooseq_blen += p->tot_len; + ooseq_qlen += pbuf_clen(p); + if ((ooseq_blen > TCP_OOSEQ_MAX_BYTES) || + (ooseq_qlen > TCP_OOSEQ_MAX_PBUFS)) { + /* too much ooseq data, dump this and everything after it */ + tcp_segs_free(next); + if (prev == NULL) { + /* first ooseq segment is too much, dump the whole queue */ + pcb->ooseq = NULL; + } else { + /* just dump 'next' and everything after it */ + prev->next = NULL; + } + break; + } + } +#endif /* TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS */ +#endif /* TCP_QUEUE_OOSEQ */ + } + } else { + /* The incoming segment is not withing the window. */ + tcp_send_empty_ack(pcb); + } + } else { + /* Segments with length 0 is taken care of here. Segments that + fall out of the window are ACKed. */ + /*if (TCP_SEQ_GT(pcb->rcv_nxt, seqno) || + TCP_SEQ_GEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/ + if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd-1)){ + tcp_ack_now(pcb); + } + } +} + +/** + * Parses the options contained in the incoming segment. + * + * Called from tcp_listen_input() and tcp_process(). + * Currently, only the MSS option is supported! + * + * @param pcb the tcp_pcb for which a segment arrived + */ +static void +tcp_parseopt(struct tcp_pcb *pcb) +{ + u16_t c, max_c; + u16_t mss; + u8_t *opts, opt; +#if LWIP_TCP_TIMESTAMPS + u32_t tsval; +#endif + + opts = (u8_t *)tcphdr + TCP_HLEN; + + /* Parse the TCP MSS option, if present. */ + if(TCPH_HDRLEN(tcphdr) > 0x5) { + max_c = (TCPH_HDRLEN(tcphdr) - 5) << 2; + for (c = 0; c < max_c; ) { + opt = opts[c]; + switch (opt) { + case 0x00: + /* End of options. */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: EOL\n")); + return; + case 0x01: + /* NOP option. */ + ++c; + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: NOP\n")); + break; + case 0x02: + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: MSS\n")); + if (opts[c + 1] != 0x04 || c + 0x04 > max_c) { + /* Bad length */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); + return; + } + /* An MSS option with the right option length. */ + mss = (opts[c + 2] << 8) | opts[c + 3]; + /* Limit the mss to the configured TCP_MSS and prevent division by zero */ + pcb->mss = ((mss > TCP_MSS) || (mss == 0)) ? TCP_MSS : mss; + /* Advance to next option */ + c += 0x04; + break; +#if LWIP_TCP_TIMESTAMPS + case 0x08: + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: TS\n")); + if (opts[c + 1] != 0x0A || c + 0x0A > max_c) { + /* Bad length */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); + return; + } + /* TCP timestamp option with valid length */ + tsval = (opts[c+2]) | (opts[c+3] << 8) | + (opts[c+4] << 16) | (opts[c+5] << 24); + if (flags & TCP_SYN) { + pcb->ts_recent = ntohl(tsval); + pcb->flags |= TF_TIMESTAMP; + } else if (TCP_SEQ_BETWEEN(pcb->ts_lastacksent, seqno, seqno+tcplen)) { + pcb->ts_recent = ntohl(tsval); + } + /* Advance to next option */ + c += 0x0A; + break; +#endif + default: + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: other\n")); + if (opts[c + 1] == 0) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); + /* If the length field is zero, the options are malformed + and we don't process them further. */ + return; + } + /* All other options have a length field, so that we easily + can skip past them. */ + c += opts[c + 1]; + } + } + } +} + +#endif /* LWIP_TCP */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/core/tcp_out.c b/component/common/network/lwip/lwip_v1.4.1/src/core/tcp_out.c new file mode 100644 index 0000000..ee19fe0 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/core/tcp_out.c @@ -0,0 +1,1485 @@ +/** + * @file + * Transmission Control Protocol, outgoing traffic + * + * The output functions of TCP. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/tcp_impl.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/inet_chksum.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#if LWIP_TCP_TIMESTAMPS +#include "lwip/sys.h" +#endif + +#include + +/* Define some copy-macros for checksum-on-copy so that the code looks + nicer by preventing too many ifdef's. */ +#if TCP_CHECKSUM_ON_COPY +#define TCP_DATA_COPY(dst, src, len, seg) do { \ + tcp_seg_add_chksum(LWIP_CHKSUM_COPY(dst, src, len), \ + len, &seg->chksum, &seg->chksum_swapped); \ + seg->flags |= TF_SEG_DATA_CHECKSUMMED; } while(0) +#define TCP_DATA_COPY2(dst, src, len, chksum, chksum_swapped) \ + tcp_seg_add_chksum(LWIP_CHKSUM_COPY(dst, src, len), len, chksum, chksum_swapped); +#else /* TCP_CHECKSUM_ON_COPY*/ +#define TCP_DATA_COPY(dst, src, len, seg) MEMCPY(dst, src, len) +#define TCP_DATA_COPY2(dst, src, len, chksum, chksum_swapped) MEMCPY(dst, src, len) +#endif /* TCP_CHECKSUM_ON_COPY*/ + +/** Define this to 1 for an extra check that the output checksum is valid + * (usefule when the checksum is generated by the application, not the stack) */ +#ifndef TCP_CHECKSUM_ON_COPY_SANITY_CHECK +#define TCP_CHECKSUM_ON_COPY_SANITY_CHECK 0 +#endif + +/* Forward declarations.*/ +static void tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb); + +/** Allocate a pbuf and create a tcphdr at p->payload, used for output + * functions other than the default tcp_output -> tcp_output_segment + * (e.g. tcp_send_empty_ack, etc.) + * + * @param pcb tcp pcb for which to send a packet (used to initialize tcp_hdr) + * @param optlen length of header-options + * @param datalen length of tcp data to reserve in pbuf + * @param seqno_be seqno in network byte order (big-endian) + * @return pbuf with p->payload being the tcp_hdr + */ +static struct pbuf * +tcp_output_alloc_header(struct tcp_pcb *pcb, u16_t optlen, u16_t datalen, + u32_t seqno_be /* already in network byte order */) +{ + struct tcp_hdr *tcphdr; + struct pbuf *p = pbuf_alloc(PBUF_IP, TCP_HLEN + optlen + datalen, PBUF_RAM); + if (p != NULL) { + LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr", + (p->len >= TCP_HLEN + optlen)); + tcphdr = (struct tcp_hdr *)p->payload; + tcphdr->src = htons(pcb->local_port); + tcphdr->dest = htons(pcb->remote_port); + tcphdr->seqno = seqno_be; + tcphdr->ackno = htonl(pcb->rcv_nxt); + TCPH_HDRLEN_FLAGS_SET(tcphdr, (5 + optlen / 4), TCP_ACK); + tcphdr->wnd = htons(pcb->rcv_ann_wnd); + tcphdr->chksum = 0; + tcphdr->urgp = 0; + + /* If we're sending a packet, update the announced right window edge */ + pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd; + } + return p; +} + +/** + * Called by tcp_close() to send a segment including FIN flag but not data. + * + * @param pcb the tcp_pcb over which to send a segment + * @return ERR_OK if sent, another err_t otherwise + */ +err_t +tcp_send_fin(struct tcp_pcb *pcb) +{ + /* first, try to add the fin to the last unsent segment */ + if (pcb->unsent != NULL) { + struct tcp_seg *last_unsent; + for (last_unsent = pcb->unsent; last_unsent->next != NULL; + last_unsent = last_unsent->next); + + if ((TCPH_FLAGS(last_unsent->tcphdr) & (TCP_SYN | TCP_FIN | TCP_RST)) == 0) { + /* no SYN/FIN/RST flag in the header, we can add the FIN flag */ + TCPH_SET_FLAG(last_unsent->tcphdr, TCP_FIN); + pcb->flags |= TF_FIN; + return ERR_OK; + } + } + /* no data, no length, flags, copy=1, no optdata */ + return tcp_enqueue_flags(pcb, TCP_FIN); +} + +/** + * Create a TCP segment with prefilled header. + * + * Called by tcp_write and tcp_enqueue_flags. + * + * @param pcb Protocol control block for the TCP connection. + * @param p pbuf that is used to hold the TCP header. + * @param flags TCP flags for header. + * @param seqno TCP sequence number of this packet + * @param optflags options to include in TCP header + * @return a new tcp_seg pointing to p, or NULL. + * The TCP header is filled in except ackno and wnd. + * p is freed on failure. + */ +static struct tcp_seg * +tcp_create_segment(struct tcp_pcb *pcb, struct pbuf *p, u8_t flags, u32_t seqno, u8_t optflags) +{ + struct tcp_seg *seg; + u8_t optlen = LWIP_TCP_OPT_LENGTH(optflags); + + if ((seg = (struct tcp_seg *)memp_malloc(MEMP_TCP_SEG)) == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_create_segment: no memory.\n")); + pbuf_free(p); + return NULL; + } + seg->flags = optflags; + seg->next = NULL; + seg->p = p; + seg->len = p->tot_len - optlen; +#if TCP_OVERSIZE_DBGCHECK + seg->oversize_left = 0; +#endif /* TCP_OVERSIZE_DBGCHECK */ +#if TCP_CHECKSUM_ON_COPY + seg->chksum = 0; + seg->chksum_swapped = 0; + /* check optflags */ + LWIP_ASSERT("invalid optflags passed: TF_SEG_DATA_CHECKSUMMED", + (optflags & TF_SEG_DATA_CHECKSUMMED) == 0); +#endif /* TCP_CHECKSUM_ON_COPY */ + + /* build TCP header */ + if (pbuf_header(p, TCP_HLEN)) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_create_segment: no room for TCP header in pbuf.\n")); + TCP_STATS_INC(tcp.err); + tcp_seg_free(seg); + return NULL; + } + seg->tcphdr = (struct tcp_hdr *)seg->p->payload; + seg->tcphdr->src = htons(pcb->local_port); + seg->tcphdr->dest = htons(pcb->remote_port); + seg->tcphdr->seqno = htonl(seqno); + /* ackno is set in tcp_output */ + TCPH_HDRLEN_FLAGS_SET(seg->tcphdr, (5 + optlen / 4), flags); + /* wnd and chksum are set in tcp_output */ + seg->tcphdr->urgp = 0; + return seg; +} + +/** + * Allocate a PBUF_RAM pbuf, perhaps with extra space at the end. + * + * This function is like pbuf_alloc(layer, length, PBUF_RAM) except + * there may be extra bytes available at the end. + * + * @param layer flag to define header size. + * @param length size of the pbuf's payload. + * @param max_length maximum usable size of payload+oversize. + * @param oversize pointer to a u16_t that will receive the number of usable tail bytes. + * @param pcb The TCP connection that willo enqueue the pbuf. + * @param apiflags API flags given to tcp_write. + * @param first_seg true when this pbuf will be used in the first enqueued segment. + * @param + */ +#if TCP_OVERSIZE +static struct pbuf * +tcp_pbuf_prealloc(pbuf_layer layer, u16_t length, u16_t max_length, + u16_t *oversize, struct tcp_pcb *pcb, u8_t apiflags, + u8_t first_seg) +{ + struct pbuf *p; + u16_t alloc = length; + +#if LWIP_NETIF_TX_SINGLE_PBUF + LWIP_UNUSED_ARG(max_length); + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(apiflags); + LWIP_UNUSED_ARG(first_seg); + /* always create MSS-sized pbufs */ + alloc = max_length; +#else /* LWIP_NETIF_TX_SINGLE_PBUF */ + if (length < max_length) { + /* Should we allocate an oversized pbuf, or just the minimum + * length required? If tcp_write is going to be called again + * before this segment is transmitted, we want the oversized + * buffer. If the segment will be transmitted immediately, we can + * save memory by allocating only length. We use a simple + * heuristic based on the following information: + * + * Did the user set TCP_WRITE_FLAG_MORE? + * + * Will the Nagle algorithm defer transmission of this segment? + */ + if ((apiflags & TCP_WRITE_FLAG_MORE) || + (!(pcb->flags & TF_NODELAY) && + (!first_seg || + pcb->unsent != NULL || + pcb->unacked != NULL))) { + alloc = LWIP_MIN(max_length, LWIP_MEM_ALIGN_SIZE(length + TCP_OVERSIZE)); + } + } +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + p = pbuf_alloc(layer, alloc, PBUF_RAM); + if (p == NULL) { + return NULL; + } + LWIP_ASSERT("need unchained pbuf", p->next == NULL); + *oversize = p->len - length; + /* trim p->len to the currently used size */ + p->len = p->tot_len = length; + return p; +} +#else /* TCP_OVERSIZE */ +#define tcp_pbuf_prealloc(layer, length, mx, os, pcb, api, fst) pbuf_alloc((layer), (length), PBUF_RAM) +#endif /* TCP_OVERSIZE */ + +#if TCP_CHECKSUM_ON_COPY +/** Add a checksum of newly added data to the segment */ +static void +tcp_seg_add_chksum(u16_t chksum, u16_t len, u16_t *seg_chksum, + u8_t *seg_chksum_swapped) +{ + u32_t helper; + /* add chksum to old chksum and fold to u16_t */ + helper = chksum + *seg_chksum; + chksum = FOLD_U32T(helper); + if ((len & 1) != 0) { + *seg_chksum_swapped = 1 - *seg_chksum_swapped; + chksum = SWAP_BYTES_IN_WORD(chksum); + } + *seg_chksum = chksum; +} +#endif /* TCP_CHECKSUM_ON_COPY */ + +/** Checks if tcp_write is allowed or not (checks state, snd_buf and snd_queuelen). + * + * @param pcb the tcp pcb to check for + * @param len length of data to send (checked agains snd_buf) + * @return ERR_OK if tcp_write is allowed to proceed, another err_t otherwise + */ +static err_t +tcp_write_checks(struct tcp_pcb *pcb, u16_t len) +{ + /* connection is in invalid state for data transmission? */ + if ((pcb->state != ESTABLISHED) && + (pcb->state != CLOSE_WAIT) && + (pcb->state != SYN_SENT) && + (pcb->state != SYN_RCVD)) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_STATE | LWIP_DBG_LEVEL_SEVERE, ("tcp_write() called in invalid state\n")); + return ERR_CONN; + } else if (len == 0) { + return ERR_OK; + } + + /* fail on too much data */ + if (len > pcb->snd_buf) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_write: too much data (len=%"U16_F" > snd_buf=%"U16_F")\n", + len, pcb->snd_buf)); + pcb->flags |= TF_NAGLEMEMERR; + return ERR_MEM; + } + + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_write: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen)); + + /* If total number of pbufs on the unsent/unacked queues exceeds the + * configured maximum, return an error */ + /* check for configured max queuelen and possible overflow */ + if ((pcb->snd_queuelen >= TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_write: too long queue %"U16_F" (max %"U16_F")\n", + pcb->snd_queuelen, TCP_SND_QUEUELEN)); + TCP_STATS_INC(tcp.memerr); + pcb->flags |= TF_NAGLEMEMERR; + return ERR_MEM; + } + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_write: pbufs on queue => at least one queue non-empty", + pcb->unacked != NULL || pcb->unsent != NULL); + } else { + LWIP_ASSERT("tcp_write: no pbufs on queue => both queues empty", + pcb->unacked == NULL && pcb->unsent == NULL); + } + return ERR_OK; +} + +/** + * Write data for sending (but does not send it immediately). + * + * It waits in the expectation of more data being sent soon (as + * it can send them more efficiently by combining them together). + * To prompt the system to send data now, call tcp_output() after + * calling tcp_write(). + * + * @param pcb Protocol control block for the TCP connection to enqueue data for. + * @param arg Pointer to the data to be enqueued for sending. + * @param len Data length in bytes + * @param apiflags combination of following flags : + * - TCP_WRITE_FLAG_COPY (0x01) data will be copied into memory belonging to the stack + * - TCP_WRITE_FLAG_MORE (0x02) for TCP connection, PSH flag will be set on last segment sent, + * @return ERR_OK if enqueued, another err_t on error + */ +err_t +tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags) +{ + struct pbuf *concat_p = NULL; + struct tcp_seg *last_unsent = NULL, *seg = NULL, *prev_seg = NULL, *queue = NULL; + u16_t pos = 0; /* position in 'arg' data */ + u16_t queuelen; + u8_t optlen = 0; + u8_t optflags = 0; +#if TCP_OVERSIZE + u16_t oversize = 0; + u16_t oversize_used = 0; +#endif /* TCP_OVERSIZE */ +#if TCP_CHECKSUM_ON_COPY + u16_t concat_chksum = 0; + u8_t concat_chksum_swapped = 0; + u16_t concat_chksummed = 0; +#endif /* TCP_CHECKSUM_ON_COPY */ + err_t err; + /* don't allocate segments bigger than half the maximum window we ever received */ + u16_t mss_local = LWIP_MIN(pcb->mss, pcb->snd_wnd_max/2); + +#if LWIP_NETIF_TX_SINGLE_PBUF + /* Always copy to try to create single pbufs for TX */ + apiflags |= TCP_WRITE_FLAG_COPY; +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, data=%p, len=%"U16_F", apiflags=%"U16_F")\n", + (void *)pcb, arg, len, (u16_t)apiflags)); + LWIP_ERROR("tcp_write: arg == NULL (programmer violates API)", + arg != NULL, return ERR_ARG;); + + err = tcp_write_checks(pcb, len); + if (err != ERR_OK) { + return err; + } + queuelen = pcb->snd_queuelen; + +#if LWIP_TCP_TIMESTAMPS + if ((pcb->flags & TF_TIMESTAMP)) { + optflags = TF_SEG_OPTS_TS; + optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS); + } +#endif /* LWIP_TCP_TIMESTAMPS */ + + + /* + * TCP segmentation is done in three phases with increasing complexity: + * + * 1. Copy data directly into an oversized pbuf. + * 2. Chain a new pbuf to the end of pcb->unsent. + * 3. Create new segments. + * + * We may run out of memory at any point. In that case we must + * return ERR_MEM and not change anything in pcb. Therefore, all + * changes are recorded in local variables and committed at the end + * of the function. Some pcb fields are maintained in local copies: + * + * queuelen = pcb->snd_queuelen + * oversize = pcb->unsent_oversize + * + * These variables are set consistently by the phases: + * + * seg points to the last segment tampered with. + * + * pos records progress as data is segmented. + */ + + /* Find the tail of the unsent queue. */ + if (pcb->unsent != NULL) { + u16_t space; + u16_t unsent_optlen; + + /* @todo: this could be sped up by keeping last_unsent in the pcb */ + for (last_unsent = pcb->unsent; last_unsent->next != NULL; + last_unsent = last_unsent->next); + + /* Usable space at the end of the last unsent segment */ + unsent_optlen = LWIP_TCP_OPT_LENGTH(last_unsent->flags); + space = mss_local - (last_unsent->len + unsent_optlen); + + /* + * Phase 1: Copy data directly into an oversized pbuf. + * + * The number of bytes copied is recorded in the oversize_used + * variable. The actual copying is done at the bottom of the + * function. + */ +#if TCP_OVERSIZE +#if TCP_OVERSIZE_DBGCHECK + /* check that pcb->unsent_oversize matches last_unsent->unsent_oversize */ + LWIP_ASSERT("unsent_oversize mismatch (pcb vs. last_unsent)", + pcb->unsent_oversize == last_unsent->oversize_left); +#endif /* TCP_OVERSIZE_DBGCHECK */ + oversize = pcb->unsent_oversize; + if (oversize > 0) { + LWIP_ASSERT("inconsistent oversize vs. space", oversize_used <= space); + seg = last_unsent; + oversize_used = oversize < len ? oversize : len; + pos += oversize_used; + oversize -= oversize_used; + space -= oversize_used; + } + /* now we are either finished or oversize is zero */ + LWIP_ASSERT("inconsistend oversize vs. len", (oversize == 0) || (pos == len)); +#endif /* TCP_OVERSIZE */ + + /* + * Phase 2: Chain a new pbuf to the end of pcb->unsent. + * + * We don't extend segments containing SYN/FIN flags or options + * (len==0). The new pbuf is kept in concat_p and pbuf_cat'ed at + * the end. + */ + if ((pos < len) && (space > 0) && (last_unsent->len > 0)) { + u16_t seglen = space < len - pos ? space : len - pos; + seg = last_unsent; + + /* Create a pbuf with a copy or reference to seglen bytes. We + * can use PBUF_RAW here since the data appears in the middle of + * a segment. A header will never be prepended. */ + if (apiflags & TCP_WRITE_FLAG_COPY) { + /* Data is copied */ + if ((concat_p = tcp_pbuf_prealloc(PBUF_RAW, seglen, space, &oversize, pcb, apiflags, 1)) == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, + ("tcp_write : could not allocate memory for pbuf copy size %"U16_F"\n", + seglen)); + goto memerr; + } +#if TCP_OVERSIZE_DBGCHECK + last_unsent->oversize_left += oversize; +#endif /* TCP_OVERSIZE_DBGCHECK */ + TCP_DATA_COPY2(concat_p->payload, (u8_t*)arg + pos, seglen, &concat_chksum, &concat_chksum_swapped); +#if TCP_CHECKSUM_ON_COPY + concat_chksummed += seglen; +#endif /* TCP_CHECKSUM_ON_COPY */ + } else { + /* Data is not copied */ + if ((concat_p = pbuf_alloc(PBUF_RAW, seglen, PBUF_ROM)) == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, + ("tcp_write: could not allocate memory for zero-copy pbuf\n")); + goto memerr; + } +#if TCP_CHECKSUM_ON_COPY + /* calculate the checksum of nocopy-data */ + tcp_seg_add_chksum(~inet_chksum((u8_t*)arg + pos, seglen), seglen, + &concat_chksum, &concat_chksum_swapped); + concat_chksummed += seglen; +#endif /* TCP_CHECKSUM_ON_COPY */ + /* reference the non-volatile payload data */ + concat_p->payload = (u8_t*)arg + pos; + } + + pos += seglen; + queuelen += pbuf_clen(concat_p); + } + } else { +#if TCP_OVERSIZE + LWIP_ASSERT("unsent_oversize mismatch (pcb->unsent is NULL)", + pcb->unsent_oversize == 0); +#endif /* TCP_OVERSIZE */ + } + + /* + * Phase 3: Create new segments. + * + * The new segments are chained together in the local 'queue' + * variable, ready to be appended to pcb->unsent. + */ + while (pos < len) { + struct pbuf *p; + u16_t left = len - pos; + u16_t max_len = mss_local - optlen; + u16_t seglen = left > max_len ? max_len : left; +#if TCP_CHECKSUM_ON_COPY + u16_t chksum = 0; + u8_t chksum_swapped = 0; +#endif /* TCP_CHECKSUM_ON_COPY */ + + if (apiflags & TCP_WRITE_FLAG_COPY) { + /* If copy is set, memory should be allocated and data copied + * into pbuf */ + if ((p = tcp_pbuf_prealloc(PBUF_TRANSPORT, seglen + optlen, mss_local, &oversize, pcb, apiflags, queue == NULL)) == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_write : could not allocate memory for pbuf copy size %"U16_F"\n", seglen)); + goto memerr; + } + LWIP_ASSERT("tcp_write: check that first pbuf can hold the complete seglen", + (p->len >= seglen)); + TCP_DATA_COPY2((char *)p->payload + optlen, (u8_t*)arg + pos, seglen, &chksum, &chksum_swapped); + } else { + /* Copy is not set: First allocate a pbuf for holding the data. + * Since the referenced data is available at least until it is + * sent out on the link (as it has to be ACKed by the remote + * party) we can safely use PBUF_ROM instead of PBUF_REF here. + */ + struct pbuf *p2; +#if TCP_OVERSIZE + LWIP_ASSERT("oversize == 0", oversize == 0); +#endif /* TCP_OVERSIZE */ + if ((p2 = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_ROM)) == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_write: could not allocate memory for zero-copy pbuf\n")); + goto memerr; + } +#if TCP_CHECKSUM_ON_COPY + /* calculate the checksum of nocopy-data */ + chksum = ~inet_chksum((u8_t*)arg + pos, seglen); +#endif /* TCP_CHECKSUM_ON_COPY */ + /* reference the non-volatile payload data */ + p2->payload = (u8_t*)arg + pos; + + /* Second, allocate a pbuf for the headers. */ + if ((p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) { + /* If allocation fails, we have to deallocate the data pbuf as + * well. */ + pbuf_free(p2); + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_write: could not allocate memory for header pbuf\n")); + goto memerr; + } + /* Concatenate the headers and data pbufs together. */ + pbuf_cat(p/*header*/, p2/*data*/); + } + + queuelen += pbuf_clen(p); + + /* Now that there are more segments queued, we check again if the + * length of the queue exceeds the configured maximum or + * overflows. */ + if ((queuelen > TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_write: queue too long %"U16_F" (%"U16_F")\n", queuelen, TCP_SND_QUEUELEN)); + pbuf_free(p); + goto memerr; + } + + if ((seg = tcp_create_segment(pcb, p, 0, pcb->snd_lbb + pos, optflags)) == NULL) { + goto memerr; + } +#if TCP_OVERSIZE_DBGCHECK + seg->oversize_left = oversize; +#endif /* TCP_OVERSIZE_DBGCHECK */ +#if TCP_CHECKSUM_ON_COPY + seg->chksum = chksum; + seg->chksum_swapped = chksum_swapped; + seg->flags |= TF_SEG_DATA_CHECKSUMMED; +#endif /* TCP_CHECKSUM_ON_COPY */ + + /* first segment of to-be-queued data? */ + if (queue == NULL) { + queue = seg; + } else { + /* Attach the segment to the end of the queued segments */ + LWIP_ASSERT("prev_seg != NULL", prev_seg != NULL); + prev_seg->next = seg; + } + /* remember last segment of to-be-queued data for next iteration */ + prev_seg = seg; + + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, ("tcp_write: queueing %"U32_F":%"U32_F"\n", + ntohl(seg->tcphdr->seqno), + ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg))); + + pos += seglen; + } + + /* + * All three segmentation phases were successful. We can commit the + * transaction. + */ + + /* + * Phase 1: If data has been added to the preallocated tail of + * last_unsent, we update the length fields of the pbuf chain. + */ +#if TCP_OVERSIZE + if (oversize_used > 0) { + struct pbuf *p; + /* Bump tot_len of whole chain, len of tail */ + for (p = last_unsent->p; p; p = p->next) { + p->tot_len += oversize_used; + if (p->next == NULL) { + TCP_DATA_COPY((char *)p->payload + p->len, arg, oversize_used, last_unsent); + p->len += oversize_used; + } + } + last_unsent->len += oversize_used; +#if TCP_OVERSIZE_DBGCHECK + LWIP_ASSERT("last_unsent->oversize_left >= oversize_used", + last_unsent->oversize_left >= oversize_used); + last_unsent->oversize_left -= oversize_used; +#endif /* TCP_OVERSIZE_DBGCHECK */ + } + pcb->unsent_oversize = oversize; +#endif /* TCP_OVERSIZE */ + + /* + * Phase 2: concat_p can be concatenated onto last_unsent->p + */ + if (concat_p != NULL) { + LWIP_ASSERT("tcp_write: cannot concatenate when pcb->unsent is empty", + (last_unsent != NULL)); + pbuf_cat(last_unsent->p, concat_p); + last_unsent->len += concat_p->tot_len; +#if TCP_CHECKSUM_ON_COPY + if (concat_chksummed) { + tcp_seg_add_chksum(concat_chksum, concat_chksummed, &last_unsent->chksum, + &last_unsent->chksum_swapped); + last_unsent->flags |= TF_SEG_DATA_CHECKSUMMED; + } +#endif /* TCP_CHECKSUM_ON_COPY */ + } + + /* + * Phase 3: Append queue to pcb->unsent. Queue may be NULL, but that + * is harmless + */ + if (last_unsent == NULL) { + pcb->unsent = queue; + } else { + last_unsent->next = queue; + } + + /* + * Finally update the pcb state. + */ + pcb->snd_lbb += len; + pcb->snd_buf -= len; + pcb->snd_queuelen = queuelen; + + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_write: %"S16_F" (after enqueued)\n", + pcb->snd_queuelen)); + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_write: valid queue length", + pcb->unacked != NULL || pcb->unsent != NULL); + } + + /* Set the PSH flag in the last segment that we enqueued. */ + if (seg != NULL && seg->tcphdr != NULL && ((apiflags & TCP_WRITE_FLAG_MORE)==0)) { + TCPH_SET_FLAG(seg->tcphdr, TCP_PSH); + } + + return ERR_OK; +memerr: + pcb->flags |= TF_NAGLEMEMERR; + TCP_STATS_INC(tcp.memerr); + + if (concat_p != NULL) { + pbuf_free(concat_p); + } + if (queue != NULL) { + tcp_segs_free(queue); + } + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_write: valid queue length", pcb->unacked != NULL || + pcb->unsent != NULL); + } + LWIP_DEBUGF(TCP_QLEN_DEBUG | LWIP_DBG_STATE, ("tcp_write: %"S16_F" (with mem err)\n", pcb->snd_queuelen)); + return ERR_MEM; +} + +/** + * Enqueue TCP options for transmission. + * + * Called by tcp_connect(), tcp_listen_input(), and tcp_send_ctrl(). + * + * @param pcb Protocol control block for the TCP connection. + * @param flags TCP header flags to set in the outgoing segment. + * @param optdata pointer to TCP options, or NULL. + * @param optlen length of TCP options in bytes. + */ +err_t +tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags) +{ + struct pbuf *p; + struct tcp_seg *seg; + u8_t optflags = 0; + u8_t optlen = 0; + + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue_flags: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen)); + + LWIP_ASSERT("tcp_enqueue_flags: need either TCP_SYN or TCP_FIN in flags (programmer violates API)", + (flags & (TCP_SYN | TCP_FIN)) != 0); + + /* check for configured max queuelen and possible overflow */ + if ((pcb->snd_queuelen >= TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue_flags: too long queue %"U16_F" (max %"U16_F")\n", + pcb->snd_queuelen, TCP_SND_QUEUELEN)); + TCP_STATS_INC(tcp.memerr); + pcb->flags |= TF_NAGLEMEMERR; + return ERR_MEM; + } + + if (flags & TCP_SYN) { + optflags = TF_SEG_OPTS_MSS; + } +#if LWIP_TCP_TIMESTAMPS + if ((pcb->flags & TF_TIMESTAMP)) { + optflags |= TF_SEG_OPTS_TS; + } +#endif /* LWIP_TCP_TIMESTAMPS */ + optlen = LWIP_TCP_OPT_LENGTH(optflags); + + /* tcp_enqueue_flags is always called with either SYN or FIN in flags. + * We need one available snd_buf byte to do that. + * This means we can't send FIN while snd_buf==0. A better fix would be to + * not include SYN and FIN sequence numbers in the snd_buf count. */ + if (pcb->snd_buf == 0) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue_flags: no send buffer available\n")); + TCP_STATS_INC(tcp.memerr); + return ERR_MEM; + } + + /* Allocate pbuf with room for TCP header + options */ + if ((p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) { + pcb->flags |= TF_NAGLEMEMERR; + TCP_STATS_INC(tcp.memerr); + return ERR_MEM; + } + LWIP_ASSERT("tcp_enqueue_flags: check that first pbuf can hold optlen", + (p->len >= optlen)); + + /* Allocate memory for tcp_seg, and fill in fields. */ + if ((seg = tcp_create_segment(pcb, p, flags, pcb->snd_lbb, optflags)) == NULL) { + pcb->flags |= TF_NAGLEMEMERR; + TCP_STATS_INC(tcp.memerr); + return ERR_MEM; + } + LWIP_ASSERT("seg->tcphdr not aligned", ((mem_ptr_t)seg->tcphdr % MEM_ALIGNMENT) == 0); + LWIP_ASSERT("tcp_enqueue_flags: invalid segment length", seg->len == 0); + + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, + ("tcp_enqueue_flags: queueing %"U32_F":%"U32_F" (0x%"X16_F")\n", + ntohl(seg->tcphdr->seqno), + ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg), + (u16_t)flags)); + + /* Now append seg to pcb->unsent queue */ + if (pcb->unsent == NULL) { + pcb->unsent = seg; + } else { + struct tcp_seg *useg; + for (useg = pcb->unsent; useg->next != NULL; useg = useg->next); + useg->next = seg; + } +#if TCP_OVERSIZE + /* The new unsent tail has no space */ + pcb->unsent_oversize = 0; +#endif /* TCP_OVERSIZE */ + + /* SYN and FIN bump the sequence number */ + if ((flags & TCP_SYN) || (flags & TCP_FIN)) { + pcb->snd_lbb++; + /* optlen does not influence snd_buf */ + pcb->snd_buf--; + } + if (flags & TCP_FIN) { + pcb->flags |= TF_FIN; + } + + /* update number of segments on the queues */ + pcb->snd_queuelen += pbuf_clen(seg->p); + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue_flags: %"S16_F" (after enqueued)\n", pcb->snd_queuelen)); + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_enqueue_flags: invalid queue length", + pcb->unacked != NULL || pcb->unsent != NULL); + } + + return ERR_OK; +} + +#if LWIP_TCP_TIMESTAMPS +/* Build a timestamp option (12 bytes long) at the specified options pointer) + * + * @param pcb tcp_pcb + * @param opts option pointer where to store the timestamp option + */ +static void +tcp_build_timestamp_option(struct tcp_pcb *pcb, u32_t *opts) +{ + /* Pad with two NOP options to make everything nicely aligned */ + opts[0] = PP_HTONL(0x0101080A); + opts[1] = htonl(sys_now()); + opts[2] = htonl(pcb->ts_recent); +} +#endif + +/** Send an ACK without data. + * + * @param pcb Protocol control block for the TCP connection to send the ACK + */ +err_t +tcp_send_empty_ack(struct tcp_pcb *pcb) +{ + struct pbuf *p; + struct tcp_hdr *tcphdr; + u8_t optlen = 0; + +#if LWIP_TCP_TIMESTAMPS + if (pcb->flags & TF_TIMESTAMP) { + optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS); + } +#endif + + p = tcp_output_alloc_header(pcb, optlen, 0, htonl(pcb->snd_nxt)); + if (p == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n")); + return ERR_BUF; + } + tcphdr = (struct tcp_hdr *)p->payload; + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, + ("tcp_output: sending ACK for %"U32_F"\n", pcb->rcv_nxt)); + /* remove ACK flags from the PCB, as we send an empty ACK now */ + pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); + + /* NB. MSS option is only sent on SYNs, so ignore it here */ +#if LWIP_TCP_TIMESTAMPS + pcb->ts_lastacksent = pcb->rcv_nxt; + + if (pcb->flags & TF_TIMESTAMP) { + tcp_build_timestamp_option(pcb, (u32_t *)(tcphdr + 1)); + } +#endif + +#if CHECKSUM_GEN_TCP + tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip), + IP_PROTO_TCP, p->tot_len); +#endif +#if LWIP_NETIF_HWADDRHINT + ip_output_hinted(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos, + IP_PROTO_TCP, &(pcb->addr_hint)); +#else /* LWIP_NETIF_HWADDRHINT*/ + ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos, + IP_PROTO_TCP); +#endif /* LWIP_NETIF_HWADDRHINT*/ + pbuf_free(p); + + return ERR_OK; +} + +/** + * Find out what we can send and send it + * + * @param pcb Protocol control block for the TCP connection to send data + * @return ERR_OK if data has been sent or nothing to send + * another err_t on error + */ +err_t +tcp_output(struct tcp_pcb *pcb) +{ + struct tcp_seg *seg, *useg; + u32_t wnd, snd_nxt; +#if TCP_CWND_DEBUG + s16_t i = 0; +#endif /* TCP_CWND_DEBUG */ + + /* pcb->state LISTEN not allowed here */ + LWIP_ASSERT("don't call tcp_output for listen-pcbs", + pcb->state != LISTEN); + + /* First, check if we are invoked by the TCP input processing + code. If so, we do not output anything. Instead, we rely on the + input processing code to call us when input processing is done + with. */ + if (tcp_input_pcb == pcb) { + return ERR_OK; + } + + wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd); + + seg = pcb->unsent; + + /* If the TF_ACK_NOW flag is set and no data will be sent (either + * because the ->unsent queue is empty or because the window does + * not allow it), construct an empty ACK segment and send it. + * + * If data is to be sent, we will just piggyback the ACK (see below). + */ + if (pcb->flags & TF_ACK_NOW && + (seg == NULL || + ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) { + return tcp_send_empty_ack(pcb); + } + + /* useg should point to last segment on unacked queue */ + useg = pcb->unacked; + if (useg != NULL) { + for (; useg->next != NULL; useg = useg->next); + } + +#if TCP_OUTPUT_DEBUG + if (seg == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n", + (void*)pcb->unsent)); + } +#endif /* TCP_OUTPUT_DEBUG */ +#if TCP_CWND_DEBUG + if (seg == NULL) { + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U16_F + ", cwnd %"U16_F", wnd %"U32_F + ", seg == NULL, ack %"U32_F"\n", + pcb->snd_wnd, pcb->cwnd, wnd, pcb->lastack)); + } else { + LWIP_DEBUGF(TCP_CWND_DEBUG, + ("tcp_output: snd_wnd %"U16_F", cwnd %"U16_F", wnd %"U32_F + ", effwnd %"U32_F", seq %"U32_F", ack %"U32_F"\n", + pcb->snd_wnd, pcb->cwnd, wnd, + ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len, + ntohl(seg->tcphdr->seqno), pcb->lastack)); + } +#endif /* TCP_CWND_DEBUG */ + /* data available and window allows it to be sent? */ + while (seg != NULL && + ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) { + LWIP_ASSERT("RST not expected here!", + (TCPH_FLAGS(seg->tcphdr) & TCP_RST) == 0); + /* Stop sending if the nagle algorithm would prevent it + * Don't stop: + * - if tcp_write had a memory error before (prevent delayed ACK timeout) or + * - if FIN was already enqueued for this PCB (SYN is always alone in a segment - + * either seg->next != NULL or pcb->unacked == NULL; + * RST is no sent using tcp_write/tcp_output. + */ + if((tcp_do_output_nagle(pcb) == 0) && + ((pcb->flags & (TF_NAGLEMEMERR | TF_FIN)) == 0)){ + break; + } +#if TCP_CWND_DEBUG + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U16_F", cwnd %"U16_F", wnd %"U32_F", effwnd %"U32_F", seq %"U32_F", ack %"U32_F", i %"S16_F"\n", + pcb->snd_wnd, pcb->cwnd, wnd, + ntohl(seg->tcphdr->seqno) + seg->len - + pcb->lastack, + ntohl(seg->tcphdr->seqno), pcb->lastack, i)); + ++i; +#endif /* TCP_CWND_DEBUG */ + + pcb->unsent = seg->next; + + if (pcb->state != SYN_SENT) { + TCPH_SET_FLAG(seg->tcphdr, TCP_ACK); + pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); + } + + tcp_output_segment(seg, pcb); + snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg); + if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) { + pcb->snd_nxt = snd_nxt; + } + /* put segment on unacknowledged list if length > 0 */ + if (TCP_TCPLEN(seg) > 0) { + seg->next = NULL; + /* unacked list is empty? */ + if (pcb->unacked == NULL) { + pcb->unacked = seg; + useg = seg; + /* unacked list is not empty? */ + } else { + /* In the case of fast retransmit, the packet should not go to the tail + * of the unacked queue, but rather somewhere before it. We need to check for + * this case. -STJ Jul 27, 2004 */ + if (TCP_SEQ_LT(ntohl(seg->tcphdr->seqno), ntohl(useg->tcphdr->seqno))) { + /* add segment to before tail of unacked list, keeping the list sorted */ + struct tcp_seg **cur_seg = &(pcb->unacked); + while (*cur_seg && + TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) { + cur_seg = &((*cur_seg)->next ); + } + seg->next = (*cur_seg); + (*cur_seg) = seg; + } else { + /* add segment to tail of unacked list */ + useg->next = seg; + useg = useg->next; + } + } + /* do not queue empty segments on the unacked list */ + } else { + tcp_seg_free(seg); + } + seg = pcb->unsent; + } +#if TCP_OVERSIZE + if (pcb->unsent == NULL) { + /* last unsent has been removed, reset unsent_oversize */ + pcb->unsent_oversize = 0; + } +#endif /* TCP_OVERSIZE */ + + pcb->flags &= ~TF_NAGLEMEMERR; + return ERR_OK; +} + +/** + * Called by tcp_output() to actually send a TCP segment over IP. + * + * @param seg the tcp_seg to send + * @param pcb the tcp_pcb for the TCP connection used to send the segment + */ +static void +tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb) +{ + u16_t len; + struct netif *netif; + u32_t *opts; + + /** @bug Exclude retransmitted segments from this count. */ + snmp_inc_tcpoutsegs(); + + /* The TCP header has already been constructed, but the ackno and + wnd fields remain. */ + seg->tcphdr->ackno = htonl(pcb->rcv_nxt); + + /* advertise our receive window size in this TCP segment */ + seg->tcphdr->wnd = htons(pcb->rcv_ann_wnd); + + pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd; + + /* Add any requested options. NB MSS option is only set on SYN + packets, so ignore it here */ + opts = (u32_t *)(void *)(seg->tcphdr + 1); + if (seg->flags & TF_SEG_OPTS_MSS) { + u16_t mss; +#if TCP_CALCULATE_EFF_SEND_MSS + mss = tcp_eff_send_mss(TCP_MSS, &pcb->remote_ip); +#else /* TCP_CALCULATE_EFF_SEND_MSS */ + mss = TCP_MSS; +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + *opts = TCP_BUILD_MSS_OPTION(mss); + opts += 1; + } +#if LWIP_TCP_TIMESTAMPS + pcb->ts_lastacksent = pcb->rcv_nxt; + + if (seg->flags & TF_SEG_OPTS_TS) { + tcp_build_timestamp_option(pcb, opts); + opts += 3; + } +#endif + + /* Set retransmission timer running if it is not currently enabled + This must be set before checking the route. */ + if (pcb->rtime == -1) { + pcb->rtime = 0; + } + + /* If we don't have a local IP address, we get one by + calling ip_route(). */ + if (ip_addr_isany(&(pcb->local_ip))) { + netif = ip_route(&(pcb->remote_ip)); + if (netif == NULL) { + return; + } + ip_addr_copy(pcb->local_ip, netif->ip_addr); + } + + if (pcb->rttest == 0) { + pcb->rttest = tcp_ticks; + pcb->rtseq = ntohl(seg->tcphdr->seqno); + + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %"U32_F"\n", pcb->rtseq)); + } + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %"U32_F":%"U32_F"\n", + htonl(seg->tcphdr->seqno), htonl(seg->tcphdr->seqno) + + seg->len)); + + len = (u16_t)((u8_t *)seg->tcphdr - (u8_t *)seg->p->payload); + + seg->p->len -= len; + seg->p->tot_len -= len; + + seg->p->payload = seg->tcphdr; + + seg->tcphdr->chksum = 0; +#if CHECKSUM_GEN_TCP +#if TCP_CHECKSUM_ON_COPY + { + u32_t acc; +#if TCP_CHECKSUM_ON_COPY_SANITY_CHECK + u16_t chksum_slow = inet_chksum_pseudo(seg->p, &(pcb->local_ip), + &(pcb->remote_ip), + IP_PROTO_TCP, seg->p->tot_len); +#endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */ + if ((seg->flags & TF_SEG_DATA_CHECKSUMMED) == 0) { + LWIP_ASSERT("data included but not checksummed", + seg->p->tot_len == (TCPH_HDRLEN(seg->tcphdr) * 4)); + } + + /* rebuild TCP header checksum (TCP header changes for retransmissions!) */ + acc = inet_chksum_pseudo_partial(seg->p, &(pcb->local_ip), + &(pcb->remote_ip), + IP_PROTO_TCP, seg->p->tot_len, TCPH_HDRLEN(seg->tcphdr) * 4); + /* add payload checksum */ + if (seg->chksum_swapped) { + seg->chksum = SWAP_BYTES_IN_WORD(seg->chksum); + seg->chksum_swapped = 0; + } + acc += (u16_t)~(seg->chksum); + seg->tcphdr->chksum = FOLD_U32T(acc); +#if TCP_CHECKSUM_ON_COPY_SANITY_CHECK + if (chksum_slow != seg->tcphdr->chksum) { + LWIP_DEBUGF(TCP_DEBUG | LWIP_DBG_LEVEL_WARNING, + ("tcp_output_segment: calculated checksum is %"X16_F" instead of %"X16_F"\n", + seg->tcphdr->chksum, chksum_slow)); + seg->tcphdr->chksum = chksum_slow; + } +#endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */ + } +#else /* TCP_CHECKSUM_ON_COPY */ + seg->tcphdr->chksum = inet_chksum_pseudo(seg->p, &(pcb->local_ip), + &(pcb->remote_ip), + IP_PROTO_TCP, seg->p->tot_len); +#endif /* TCP_CHECKSUM_ON_COPY */ +#endif /* CHECKSUM_GEN_TCP */ + TCP_STATS_INC(tcp.xmit); + +#if LWIP_NETIF_HWADDRHINT + ip_output_hinted(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos, + IP_PROTO_TCP, &(pcb->addr_hint)); +#else /* LWIP_NETIF_HWADDRHINT*/ + ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos, + IP_PROTO_TCP); +#endif /* LWIP_NETIF_HWADDRHINT*/ +} + +/** + * Send a TCP RESET packet (empty segment with RST flag set) either to + * abort a connection or to show that there is no matching local connection + * for a received segment. + * + * Called by tcp_abort() (to abort a local connection), tcp_input() (if no + * matching local pcb was found), tcp_listen_input() (if incoming segment + * has ACK flag set) and tcp_process() (received segment in the wrong state) + * + * Since a RST segment is in most cases not sent for an active connection, + * tcp_rst() has a number of arguments that are taken from a tcp_pcb for + * most other segment output functions. + * + * @param seqno the sequence number to use for the outgoing segment + * @param ackno the acknowledge number to use for the outgoing segment + * @param local_ip the local IP address to send the segment from + * @param remote_ip the remote IP address to send the segment to + * @param local_port the local TCP port to send the segment from + * @param remote_port the remote TCP port to send the segment to + */ +void +tcp_rst(u32_t seqno, u32_t ackno, + ip_addr_t *local_ip, ip_addr_t *remote_ip, + u16_t local_port, u16_t remote_port) +{ + struct pbuf *p; + struct tcp_hdr *tcphdr; + p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM); + if (p == NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n")); + return; + } + LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr", + (p->len >= sizeof(struct tcp_hdr))); + + tcphdr = (struct tcp_hdr *)p->payload; + tcphdr->src = htons(local_port); + tcphdr->dest = htons(remote_port); + tcphdr->seqno = htonl(seqno); + tcphdr->ackno = htonl(ackno); + TCPH_HDRLEN_FLAGS_SET(tcphdr, TCP_HLEN/4, TCP_RST | TCP_ACK); + tcphdr->wnd = PP_HTONS(TCP_WND); + tcphdr->chksum = 0; + tcphdr->urgp = 0; + +#if CHECKSUM_GEN_TCP + tcphdr->chksum = inet_chksum_pseudo(p, local_ip, remote_ip, + IP_PROTO_TCP, p->tot_len); +#endif + TCP_STATS_INC(tcp.xmit); + snmp_inc_tcpoutrsts(); + /* Send output with hardcoded TTL since we have no access to the pcb */ + ip_output(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP); + pbuf_free(p); + LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %"U32_F" ackno %"U32_F".\n", seqno, ackno)); +} + +/** + * Requeue all unacked segments for retransmission + * + * Called by tcp_slowtmr() for slow retransmission. + * + * @param pcb the tcp_pcb for which to re-enqueue all unacked segments + */ +void +tcp_rexmit_rto(struct tcp_pcb *pcb) +{ + struct tcp_seg *seg; + + if (pcb->unacked == NULL) { + return; + } + + /* Move all unacked segments to the head of the unsent queue */ + for (seg = pcb->unacked; seg->next != NULL; seg = seg->next); + /* concatenate unsent queue after unacked queue */ + seg->next = pcb->unsent; + /* unsent queue is the concatenated queue (of unacked, unsent) */ + pcb->unsent = pcb->unacked; + /* unacked queue is now empty */ + pcb->unacked = NULL; + /* last unsent hasn't changed, no need to reset unsent_oversize */ + + /* increment number of retransmissions */ + ++pcb->nrtx; + + /* Don't take any RTT measurements after retransmitting. */ + pcb->rttest = 0; + + /* Do the actual retransmission */ + tcp_output(pcb); +} + +/** + * Requeue the first unacked segment for retransmission + * + * Called by tcp_receive() for fast retramsmit. + * + * @param pcb the tcp_pcb for which to retransmit the first unacked segment + */ +void +tcp_rexmit(struct tcp_pcb *pcb) +{ + struct tcp_seg *seg; + struct tcp_seg **cur_seg; + + if (pcb->unacked == NULL) { + return; + } + + /* Move the first unacked segment to the unsent queue */ + /* Keep the unsent queue sorted. */ + seg = pcb->unacked; + pcb->unacked = seg->next; + + cur_seg = &(pcb->unsent); + while (*cur_seg && + TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) { + cur_seg = &((*cur_seg)->next ); + } + seg->next = *cur_seg; + *cur_seg = seg; +#if TCP_OVERSIZE + if (seg->next == NULL) { + /* the retransmitted segment is last in unsent, so reset unsent_oversize */ + pcb->unsent_oversize = 0; + } +#endif /* TCP_OVERSIZE */ + + ++pcb->nrtx; + + /* Don't take any rtt measurements after retransmitting. */ + pcb->rttest = 0; + + /* Do the actual retransmission. */ + snmp_inc_tcpretranssegs(); + /* No need to call tcp_output: we are always called from tcp_input() + and thus tcp_output directly returns. */ +} + + +/** + * Handle retransmission after three dupacks received + * + * @param pcb the tcp_pcb for which to retransmit the first unacked segment + */ +void +tcp_rexmit_fast(struct tcp_pcb *pcb) +{ + if (pcb->unacked != NULL && !(pcb->flags & TF_INFR)) { + /* This is fast retransmit. Retransmit the first unacked segment. */ + LWIP_DEBUGF(TCP_FR_DEBUG, + ("tcp_receive: dupacks %"U16_F" (%"U32_F + "), fast retransmit %"U32_F"\n", + (u16_t)pcb->dupacks, pcb->lastack, + ntohl(pcb->unacked->tcphdr->seqno))); + tcp_rexmit(pcb); + + /* Set ssthresh to half of the minimum of the current + * cwnd and the advertised window */ + if (pcb->cwnd > pcb->snd_wnd) { + pcb->ssthresh = pcb->snd_wnd / 2; + } else { + pcb->ssthresh = pcb->cwnd / 2; + } + + /* The minimum value for ssthresh should be 2 MSS */ + if (pcb->ssthresh < 2*pcb->mss) { + LWIP_DEBUGF(TCP_FR_DEBUG, + ("tcp_receive: The minimum value for ssthresh %"U16_F + " should be min 2 mss %"U16_F"...\n", + pcb->ssthresh, 2*pcb->mss)); + pcb->ssthresh = 2*pcb->mss; + } + + pcb->cwnd = pcb->ssthresh + 3 * pcb->mss; + pcb->flags |= TF_INFR; + } +} + + +/** + * Send keepalive packets to keep a connection active although + * no data is sent over it. + * + * Called by tcp_slowtmr() + * + * @param pcb the tcp_pcb for which to send a keepalive packet + */ +void +tcp_keepalive(struct tcp_pcb *pcb) +{ + struct pbuf *p; + struct tcp_hdr *tcphdr; + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(&pcb->remote_ip), ip4_addr2_16(&pcb->remote_ip), + ip4_addr3_16(&pcb->remote_ip), ip4_addr4_16(&pcb->remote_ip))); + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F" pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n", + tcp_ticks, pcb->tmr, pcb->keep_cnt_sent)); + + p = tcp_output_alloc_header(pcb, 0, 0, htonl(pcb->snd_nxt - 1)); + if(p == NULL) { + LWIP_DEBUGF(TCP_DEBUG, + ("tcp_keepalive: could not allocate memory for pbuf\n")); + return; + } + tcphdr = (struct tcp_hdr *)p->payload; + +#if CHECKSUM_GEN_TCP + tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip, + IP_PROTO_TCP, p->tot_len); +#endif + TCP_STATS_INC(tcp.xmit); + + /* Send output to IP */ +#if LWIP_NETIF_HWADDRHINT + ip_output_hinted(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP, + &(pcb->addr_hint)); +#else /* LWIP_NETIF_HWADDRHINT*/ + ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP); +#endif /* LWIP_NETIF_HWADDRHINT*/ + + pbuf_free(p); + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: seqno %"U32_F" ackno %"U32_F".\n", + pcb->snd_nxt - 1, pcb->rcv_nxt)); +} + + +/** + * Send persist timer zero-window probes to keep a connection active + * when a window update is lost. + * + * Called by tcp_slowtmr() + * + * @param pcb the tcp_pcb for which to send a zero-window probe packet + */ +void +tcp_zero_window_probe(struct tcp_pcb *pcb) +{ + struct pbuf *p; + struct tcp_hdr *tcphdr; + struct tcp_seg *seg; + u16_t len; + u8_t is_fin; + + LWIP_DEBUGF(TCP_DEBUG, + ("tcp_zero_window_probe: sending ZERO WINDOW probe to %" + U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(&pcb->remote_ip), ip4_addr2_16(&pcb->remote_ip), + ip4_addr3_16(&pcb->remote_ip), ip4_addr4_16(&pcb->remote_ip))); + + LWIP_DEBUGF(TCP_DEBUG, + ("tcp_zero_window_probe: tcp_ticks %"U32_F + " pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n", + tcp_ticks, pcb->tmr, pcb->keep_cnt_sent)); + + seg = pcb->unacked; + + if(seg == NULL) { + seg = pcb->unsent; + } + if(seg == NULL) { + return; + } + + is_fin = ((TCPH_FLAGS(seg->tcphdr) & TCP_FIN) != 0) && (seg->len == 0); + /* we want to send one seqno: either FIN or data (no options) */ + len = is_fin ? 0 : 1; + + p = tcp_output_alloc_header(pcb, 0, len, seg->tcphdr->seqno); + if(p == NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: no memory for pbuf\n")); + return; + } + tcphdr = (struct tcp_hdr *)p->payload; + + if (is_fin) { + /* FIN segment, no data */ + TCPH_FLAGS_SET(tcphdr, TCP_ACK | TCP_FIN); + } else { + /* Data segment, copy in one byte from the head of the unacked queue */ + char *d = ((char *)p->payload + TCP_HLEN); + /* Depending on whether the segment has already been sent (unacked) or not + (unsent), seg->p->payload points to the IP header or TCP header. + Ensure we copy the first TCP data byte: */ + pbuf_copy_partial(seg->p, d, 1, seg->p->tot_len - seg->len); + } + +#if CHECKSUM_GEN_TCP + tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip, + IP_PROTO_TCP, p->tot_len); +#endif + TCP_STATS_INC(tcp.xmit); + + /* Send output to IP */ +#if LWIP_NETIF_HWADDRHINT + ip_output_hinted(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP, + &(pcb->addr_hint)); +#else /* LWIP_NETIF_HWADDRHINT*/ + ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP); +#endif /* LWIP_NETIF_HWADDRHINT*/ + + pbuf_free(p); + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: seqno %"U32_F + " ackno %"U32_F".\n", + pcb->snd_nxt - 1, pcb->rcv_nxt)); +} +#endif /* LWIP_TCP */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/core/udp.c b/component/common/network/lwip/lwip_v1.4.1/src/core/udp.c new file mode 100644 index 0000000..32c7d38 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/core/udp.c @@ -0,0 +1,1013 @@ +/** + * @file + * User Datagram Protocol module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + + +/* udp.c + * + * The code for the User Datagram Protocol UDP & UDPLite (RFC 3828). + * + */ + +/* @todo Check the use of '(struct udp_pcb).chksum_len_rx'! + */ + +#include "lwip/opt.h" + +#if LWIP_UDP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/udp.h" +#include "lwip/def.h" +#include "lwip/memp.h" +#include "lwip/inet_chksum.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/icmp.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "arch/perf.h" +#include "lwip/dhcp.h" + +#include + +#ifndef UDP_LOCAL_PORT_RANGE_START +/* From http://www.iana.org/assignments/port-numbers: + "The Dynamic and/or Private Ports are those from 49152 through 65535" */ +#define UDP_LOCAL_PORT_RANGE_START 0xc000 +#define UDP_LOCAL_PORT_RANGE_END 0xffff +#define UDP_ENSURE_LOCAL_PORT_RANGE(port) (((port) & ~UDP_LOCAL_PORT_RANGE_START) + UDP_LOCAL_PORT_RANGE_START) +#endif + +/* last local UDP port */ +static u16_t udp_port = UDP_LOCAL_PORT_RANGE_START; + +/* The list of UDP PCBs */ +/* exported in udp.h (was static) */ +struct udp_pcb *udp_pcbs; + +/** + * Initialize this module. + */ +void +udp_init(void) +{ +#if LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) + udp_port = UDP_ENSURE_LOCAL_PORT_RANGE(LWIP_RAND()); +#endif /* LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) */ +} + +/** + * Allocate a new local UDP port. + * + * @return a new (free) local UDP port number + */ +static u16_t +udp_new_port(void) +{ + u16_t n = 0; + struct udp_pcb *pcb; + +again: + if (udp_port++ == UDP_LOCAL_PORT_RANGE_END) { + udp_port = UDP_LOCAL_PORT_RANGE_START; + } + /* Check all PCBs. */ + for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) { + if (pcb->local_port == udp_port) { + if (++n > (UDP_LOCAL_PORT_RANGE_END - UDP_LOCAL_PORT_RANGE_START)) { + return 0; + } + goto again; + } + } + return udp_port; +#if 0 + struct udp_pcb *ipcb = udp_pcbs; + while ((ipcb != NULL) && (udp_port != UDP_LOCAL_PORT_RANGE_END)) { + if (ipcb->local_port == udp_port) { + /* port is already used by another udp_pcb */ + udp_port++; + /* restart scanning all udp pcbs */ + ipcb = udp_pcbs; + } else { + /* go on with next udp pcb */ + ipcb = ipcb->next; + } + } + if (ipcb != NULL) { + return 0; + } + return udp_port; +#endif +} + +/** + * Process an incoming UDP datagram. + * + * Given an incoming UDP datagram (as a chain of pbufs) this function + * finds a corresponding UDP PCB and hands over the pbuf to the pcbs + * recv function. If no pcb is found or the datagram is incorrect, the + * pbuf is freed. + * + * @param p pbuf to be demultiplexed to a UDP PCB. + * @param inp network interface on which the datagram was received. + * + */ +void +udp_input(struct pbuf *p, struct netif *inp) +{ + struct udp_hdr *udphdr; + struct udp_pcb *pcb, *prev; + struct udp_pcb *uncon_pcb; + struct ip_hdr *iphdr; + u16_t src, dest; + u8_t local_match; + u8_t broadcast; + + PERF_START; + + UDP_STATS_INC(udp.recv); + + iphdr = (struct ip_hdr *)p->payload; + + /* Check minimum length (IP header + UDP header) + * and move payload pointer to UDP header */ + if (p->tot_len < (IPH_HL(iphdr) * 4 + UDP_HLEN) || pbuf_header(p, -(s16_t)(IPH_HL(iphdr) * 4))) { + /* drop short packets */ + LWIP_DEBUGF(UDP_DEBUG, + ("udp_input: short UDP datagram (%"U16_F" bytes) discarded\n", p->tot_len)); + UDP_STATS_INC(udp.lenerr); + UDP_STATS_INC(udp.drop); + snmp_inc_udpinerrors(); + pbuf_free(p); + goto end; + } + + udphdr = (struct udp_hdr *)p->payload; + + /* is broadcast packet ? */ + broadcast = ip_addr_isbroadcast(¤t_iphdr_dest, inp); + + LWIP_DEBUGF(UDP_DEBUG, ("udp_input: received datagram of length %"U16_F"\n", p->tot_len)); + + /* convert src and dest ports to host byte order */ + src = ntohs(udphdr->src); + dest = ntohs(udphdr->dest); + + udp_debug_print(udphdr); + + /* print the UDP source and destination */ + LWIP_DEBUGF(UDP_DEBUG, + ("udp (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F") <-- " + "(%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F")\n", + ip4_addr1_16(&iphdr->dest), ip4_addr2_16(&iphdr->dest), + ip4_addr3_16(&iphdr->dest), ip4_addr4_16(&iphdr->dest), ntohs(udphdr->dest), + ip4_addr1_16(&iphdr->src), ip4_addr2_16(&iphdr->src), + ip4_addr3_16(&iphdr->src), ip4_addr4_16(&iphdr->src), ntohs(udphdr->src))); + +#if LWIP_DHCP + pcb = NULL; + /* when LWIP_DHCP is active, packets to DHCP_CLIENT_PORT may only be processed by + the dhcp module, no other UDP pcb may use the local UDP port DHCP_CLIENT_PORT */ + if (dest == DHCP_CLIENT_PORT) { + /* all packets for DHCP_CLIENT_PORT not coming from DHCP_SERVER_PORT are dropped! */ + if (src == DHCP_SERVER_PORT) { + if ((inp->dhcp != NULL) && (inp->dhcp->pcb != NULL)) { + /* accept the packe if + (- broadcast or directed to us) -> DHCP is link-layer-addressed, local ip is always ANY! + - inp->dhcp->pcb->remote == ANY or iphdr->src */ + if ((ip_addr_isany(&inp->dhcp->pcb->remote_ip) || + ip_addr_cmp(&(inp->dhcp->pcb->remote_ip), ¤t_iphdr_src))) { + pcb = inp->dhcp->pcb; + } + } + } + } else +#endif /* LWIP_DHCP */ + { + prev = NULL; + local_match = 0; + uncon_pcb = NULL; + /* Iterate through the UDP pcb list for a matching pcb. + * 'Perfect match' pcbs (connected to the remote port & ip address) are + * preferred. If no perfect match is found, the first unconnected pcb that + * matches the local port and ip address gets the datagram. */ + for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) { + local_match = 0; + /* print the PCB local and remote address */ + LWIP_DEBUGF(UDP_DEBUG, + ("pcb (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F") --- " + "(%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F")\n", + ip4_addr1_16(&pcb->local_ip), ip4_addr2_16(&pcb->local_ip), + ip4_addr3_16(&pcb->local_ip), ip4_addr4_16(&pcb->local_ip), pcb->local_port, + ip4_addr1_16(&pcb->remote_ip), ip4_addr2_16(&pcb->remote_ip), + ip4_addr3_16(&pcb->remote_ip), ip4_addr4_16(&pcb->remote_ip), pcb->remote_port)); + + /* compare PCB local addr+port to UDP destination addr+port */ + if (pcb->local_port == dest) { + if ( + (!broadcast && ip_addr_isany(&pcb->local_ip)) || + ip_addr_cmp(&(pcb->local_ip), ¤t_iphdr_dest) || +#if LWIP_IGMP + ip_addr_ismulticast(¤t_iphdr_dest) || +#endif /* LWIP_IGMP */ +#if IP_SOF_BROADCAST_RECV + (broadcast && ip_get_option(pcb, SOF_BROADCAST) && + (ip_addr_isany(&pcb->local_ip) || + ip_addr_netcmp(&pcb->local_ip, ip_current_dest_addr(), &inp->netmask)))) { +#else /* IP_SOF_BROADCAST_RECV */ + (broadcast && + (ip_addr_isany(&pcb->local_ip) || + ip_addr_netcmp(&pcb->local_ip, ip_current_dest_addr(), &inp->netmask)))) { +#endif /* IP_SOF_BROADCAST_RECV */ + local_match = 1; + if ((uncon_pcb == NULL) && + ((pcb->flags & UDP_FLAGS_CONNECTED) == 0)) { + /* the first unconnected matching PCB */ + uncon_pcb = pcb; + } + } + } + /* compare PCB remote addr+port to UDP source addr+port */ + if ((local_match != 0) && + (pcb->remote_port == src) && + (ip_addr_isany(&pcb->remote_ip) || + ip_addr_cmp(&(pcb->remote_ip), ¤t_iphdr_src))) { + /* the first fully matching PCB */ + if (prev != NULL) { + /* move the pcb to the front of udp_pcbs so that is + found faster next time */ + prev->next = pcb->next; + pcb->next = udp_pcbs; + udp_pcbs = pcb; + } else { + UDP_STATS_INC(udp.cachehit); + } + break; + } + prev = pcb; + } + /* no fully matching pcb found? then look for an unconnected pcb */ + if (pcb == NULL) { + pcb = uncon_pcb; + } + } + + /* Check checksum if this is a match or if it was directed at us. */ + if (pcb != NULL || ip_addr_cmp(&inp->ip_addr, ¤t_iphdr_dest)) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: calculating checksum\n")); +#if LWIP_UDPLITE + if (IPH_PROTO(iphdr) == IP_PROTO_UDPLITE) { + /* Do the UDP Lite checksum */ +#if CHECKSUM_CHECK_UDP + u16_t chklen = ntohs(udphdr->len); + if (chklen < sizeof(struct udp_hdr)) { + if (chklen == 0) { + /* For UDP-Lite, checksum length of 0 means checksum + over the complete packet (See RFC 3828 chap. 3.1) */ + chklen = p->tot_len; + } else { + /* At least the UDP-Lite header must be covered by the + checksum! (Again, see RFC 3828 chap. 3.1) */ + UDP_STATS_INC(udp.chkerr); + UDP_STATS_INC(udp.drop); + snmp_inc_udpinerrors(); + pbuf_free(p); + goto end; + } + } + if (inet_chksum_pseudo_partial(p, ¤t_iphdr_src, ¤t_iphdr_dest, + IP_PROTO_UDPLITE, p->tot_len, chklen) != 0) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("udp_input: UDP Lite datagram discarded due to failing checksum\n")); + UDP_STATS_INC(udp.chkerr); + UDP_STATS_INC(udp.drop); + snmp_inc_udpinerrors(); + pbuf_free(p); + goto end; + } +#endif /* CHECKSUM_CHECK_UDP */ + } else +#endif /* LWIP_UDPLITE */ + { +#if CHECKSUM_CHECK_UDP + if (udphdr->chksum != 0) { + if (inet_chksum_pseudo(p, ip_current_src_addr(), ip_current_dest_addr(), + IP_PROTO_UDP, p->tot_len) != 0) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("udp_input: UDP datagram discarded due to failing checksum\n")); + UDP_STATS_INC(udp.chkerr); + UDP_STATS_INC(udp.drop); + snmp_inc_udpinerrors(); + pbuf_free(p); + goto end; + } + } +#endif /* CHECKSUM_CHECK_UDP */ + } + if(pbuf_header(p, -UDP_HLEN)) { + /* Can we cope with this failing? Just assert for now */ + LWIP_ASSERT("pbuf_header failed\n", 0); + UDP_STATS_INC(udp.drop); + snmp_inc_udpinerrors(); + pbuf_free(p); + goto end; + } + if (pcb != NULL) { + snmp_inc_udpindatagrams(); +#if SO_REUSE && SO_REUSE_RXTOALL + if ((broadcast || ip_addr_ismulticast(¤t_iphdr_dest)) && + ip_get_option(pcb, SOF_REUSEADDR)) { + /* pass broadcast- or multicast packets to all multicast pcbs + if SOF_REUSEADDR is set on the first match */ + struct udp_pcb *mpcb; + u8_t p_header_changed = 0; + for (mpcb = udp_pcbs; mpcb != NULL; mpcb = mpcb->next) { + if (mpcb != pcb) { + /* compare PCB local addr+port to UDP destination addr+port */ + if ((mpcb->local_port == dest) && + ((!broadcast && ip_addr_isany(&mpcb->local_ip)) || + ip_addr_cmp(&(mpcb->local_ip), ¤t_iphdr_dest) || +#if LWIP_IGMP + ip_addr_ismulticast(¤t_iphdr_dest) || +#endif /* LWIP_IGMP */ +#if IP_SOF_BROADCAST_RECV + (broadcast && ip_get_option(mpcb, SOF_BROADCAST)))) { +#else /* IP_SOF_BROADCAST_RECV */ + (broadcast))) { +#endif /* IP_SOF_BROADCAST_RECV */ + /* pass a copy of the packet to all local matches */ + if (mpcb->recv != NULL) { + struct pbuf *q; + /* for that, move payload to IP header again */ + if (p_header_changed == 0) { + pbuf_header(p, (s16_t)((IPH_HL(iphdr) * 4) + UDP_HLEN)); + p_header_changed = 1; + } + q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); + if (q != NULL) { + err_t err = pbuf_copy(q, p); + if (err == ERR_OK) { + /* move payload to UDP data */ + pbuf_header(q, -(s16_t)((IPH_HL(iphdr) * 4) + UDP_HLEN)); + mpcb->recv(mpcb->recv_arg, mpcb, q, ip_current_src_addr(), src); + } + } + } + } + } + } + if (p_header_changed) { + /* and move payload to UDP data again */ + pbuf_header(p, -(s16_t)((IPH_HL(iphdr) * 4) + UDP_HLEN)); + } + } +#endif /* SO_REUSE && SO_REUSE_RXTOALL */ + /* callback */ + if (pcb->recv != NULL) { + /* now the recv function is responsible for freeing p */ + pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr(), src); + } else { + /* no recv function registered? then we have to free the pbuf! */ + pbuf_free(p); + goto end; + } + } else { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: not for us.\n")); + +#if LWIP_ICMP + /* No match was found, send ICMP destination port unreachable unless + destination address was broadcast/multicast. */ + if (!broadcast && + !ip_addr_ismulticast(¤t_iphdr_dest)) { + /* move payload pointer back to ip header */ + pbuf_header(p, (IPH_HL(iphdr) * 4) + UDP_HLEN); + LWIP_ASSERT("p->payload == iphdr", (p->payload == iphdr)); + icmp_dest_unreach(p, ICMP_DUR_PORT); + } +#endif /* LWIP_ICMP */ + UDP_STATS_INC(udp.proterr); + UDP_STATS_INC(udp.drop); + snmp_inc_udpnoports(); + pbuf_free(p); + } + } else { + pbuf_free(p); + } +end: + PERF_STOP("udp_input"); +} + +/** + * Send data using UDP. + * + * @param pcb UDP PCB used to send the data. + * @param p chain of pbuf's to be sent. + * + * The datagram will be sent to the current remote_ip & remote_port + * stored in pcb. If the pcb is not bound to a port, it will + * automatically be bound to a random port. + * + * @return lwIP error code. + * - ERR_OK. Successful. No error occured. + * - ERR_MEM. Out of memory. + * - ERR_RTE. Could not find route to destination address. + * - More errors could be returned by lower protocol layers. + * + * @see udp_disconnect() udp_sendto() + */ +err_t +udp_send(struct udp_pcb *pcb, struct pbuf *p) +{ + /* send to the packet using remote ip and port stored in the pcb */ + return udp_sendto(pcb, p, &pcb->remote_ip, pcb->remote_port); +} + +#if LWIP_CHECKSUM_ON_COPY +/** Same as udp_send() but with checksum + */ +err_t +udp_send_chksum(struct udp_pcb *pcb, struct pbuf *p, + u8_t have_chksum, u16_t chksum) +{ + /* send to the packet using remote ip and port stored in the pcb */ + return udp_sendto_chksum(pcb, p, &pcb->remote_ip, pcb->remote_port, + have_chksum, chksum); +} +#endif /* LWIP_CHECKSUM_ON_COPY */ + +/** + * Send data to a specified address using UDP. + * + * @param pcb UDP PCB used to send the data. + * @param p chain of pbuf's to be sent. + * @param dst_ip Destination IP address. + * @param dst_port Destination UDP port. + * + * dst_ip & dst_port are expected to be in the same byte order as in the pcb. + * + * If the PCB already has a remote address association, it will + * be restored after the data is sent. + * + * @return lwIP error code (@see udp_send for possible error codes) + * + * @see udp_disconnect() udp_send() + */ +err_t +udp_sendto(struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *dst_ip, u16_t dst_port) +{ +#if LWIP_CHECKSUM_ON_COPY + return udp_sendto_chksum(pcb, p, dst_ip, dst_port, 0, 0); +} + +/** Same as udp_sendto(), but with checksum */ +err_t +udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip, + u16_t dst_port, u8_t have_chksum, u16_t chksum) +{ +#endif /* LWIP_CHECKSUM_ON_COPY */ + struct netif *netif; + + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send\n")); + + /* find the outgoing network interface for this packet */ +#if LWIP_IGMP + netif = ip_route((ip_addr_ismulticast(dst_ip))?(&(pcb->multicast_ip)):(dst_ip)); +#else + netif = ip_route(dst_ip); +#endif /* LWIP_IGMP */ + + /* no outgoing network interface could be found? */ + if (netif == NULL) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(dst_ip), ip4_addr2_16(dst_ip), ip4_addr3_16(dst_ip), ip4_addr4_16(dst_ip))); + UDP_STATS_INC(udp.rterr); + return ERR_RTE; + } +#if LWIP_CHECKSUM_ON_COPY + return udp_sendto_if_chksum(pcb, p, dst_ip, dst_port, netif, have_chksum, chksum); +#else /* LWIP_CHECKSUM_ON_COPY */ + return udp_sendto_if(pcb, p, dst_ip, dst_port, netif); +#endif /* LWIP_CHECKSUM_ON_COPY */ +} + +/** + * Send data to a specified address using UDP. + * The netif used for sending can be specified. + * + * This function exists mainly for DHCP, to be able to send UDP packets + * on a netif that is still down. + * + * @param pcb UDP PCB used to send the data. + * @param p chain of pbuf's to be sent. + * @param dst_ip Destination IP address. + * @param dst_port Destination UDP port. + * @param netif the netif used for sending. + * + * dst_ip & dst_port are expected to be in the same byte order as in the pcb. + * + * @return lwIP error code (@see udp_send for possible error codes) + * + * @see udp_disconnect() udp_send() + */ +err_t +udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif) +{ +#if LWIP_CHECKSUM_ON_COPY + return udp_sendto_if_chksum(pcb, p, dst_ip, dst_port, netif, 0, 0); +} + +/** Same as udp_sendto_if(), but with checksum */ +err_t +udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip, + u16_t dst_port, struct netif *netif, u8_t have_chksum, + u16_t chksum) +{ +#endif /* LWIP_CHECKSUM_ON_COPY */ + struct udp_hdr *udphdr; + ip_addr_t *src_ip; + err_t err; + struct pbuf *q; /* q will be sent down the stack */ + +#if IP_SOF_BROADCAST + /* broadcast filter? */ + if (!ip_get_option(pcb, SOF_BROADCAST) && ip_addr_isbroadcast(dst_ip, netif)) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("udp_sendto_if: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb)); + return ERR_VAL; + } +#endif /* IP_SOF_BROADCAST */ + + /* if the PCB is not yet bound to a port, bind it here */ + if (pcb->local_port == 0) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send: not yet bound to a port, binding now\n")); + err = udp_bind(pcb, &pcb->local_ip, pcb->local_port); + if (err != ERR_OK) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: forced port bind failed\n")); + return err; + } + } + + /* not enough space to add an UDP header to first pbuf in given p chain? */ + if (pbuf_header(p, UDP_HLEN)) { + /* allocate header in a separate new pbuf */ + q = pbuf_alloc(PBUF_IP, UDP_HLEN, PBUF_RAM); + /* new header pbuf could not be allocated? */ + if (q == NULL) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: could not allocate header\n")); + return ERR_MEM; + } + if (p->tot_len != 0) { + /* chain header q in front of given pbuf p (only if p contains data) */ + pbuf_chain(q, p); + } + /* first pbuf q points to header pbuf */ + LWIP_DEBUGF(UDP_DEBUG, + ("udp_send: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p)); + } else { + /* adding space for header within p succeeded */ + /* first pbuf q equals given pbuf */ + q = p; + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: added header in given pbuf %p\n", (void *)p)); + } + LWIP_ASSERT("check that first pbuf can hold struct udp_hdr", + (q->len >= sizeof(struct udp_hdr))); + /* q now represents the packet to be sent */ + udphdr = (struct udp_hdr *)q->payload; + udphdr->src = htons(pcb->local_port); + udphdr->dest = htons(dst_port); + /* in UDP, 0 checksum means 'no checksum' */ + udphdr->chksum = 0x0000; + + /* Multicast Loop? */ +#if LWIP_IGMP + if (ip_addr_ismulticast(dst_ip) && ((pcb->flags & UDP_FLAGS_MULTICAST_LOOP) != 0)) { + q->flags |= PBUF_FLAG_MCASTLOOP; + } +#endif /* LWIP_IGMP */ + + + /* PCB local address is IP_ANY_ADDR? */ + if (ip_addr_isany(&pcb->local_ip)) { + /* use outgoing network interface IP address as source address */ + src_ip = &(netif->ip_addr); + } else { + /* check if UDP PCB local IP address is correct + * this could be an old address if netif->ip_addr has changed */ + if (!ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr))) { + /* local_ip doesn't match, drop the packet */ + if (q != p) { + /* free the header pbuf */ + pbuf_free(q); + q = NULL; + /* p is still referenced by the caller, and will live on */ + } + return ERR_VAL; + } + /* use UDP PCB local IP address as source address */ + src_ip = &(pcb->local_ip); + } + + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: sending datagram of length %"U16_F"\n", q->tot_len)); + +#if LWIP_UDPLITE + /* UDP Lite protocol? */ + if (pcb->flags & UDP_FLAGS_UDPLITE) { + u16_t chklen, chklen_hdr; + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE packet length %"U16_F"\n", q->tot_len)); + /* set UDP message length in UDP header */ + chklen_hdr = chklen = pcb->chksum_len_tx; + if ((chklen < sizeof(struct udp_hdr)) || (chklen > q->tot_len)) { + if (chklen != 0) { + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE pcb->chksum_len is illegal: %"U16_F"\n", chklen)); + } + /* For UDP-Lite, checksum length of 0 means checksum + over the complete packet. (See RFC 3828 chap. 3.1) + At least the UDP-Lite header must be covered by the + checksum, therefore, if chksum_len has an illegal + value, we generate the checksum over the complete + packet to be safe. */ + chklen_hdr = 0; + chklen = q->tot_len; + } + udphdr->len = htons(chklen_hdr); + /* calculate checksum */ +#if CHECKSUM_GEN_UDP + udphdr->chksum = inet_chksum_pseudo_partial(q, src_ip, dst_ip, + IP_PROTO_UDPLITE, q->tot_len, +#if !LWIP_CHECKSUM_ON_COPY + chklen); +#else /* !LWIP_CHECKSUM_ON_COPY */ + (have_chksum ? UDP_HLEN : chklen)); + if (have_chksum) { + u32_t acc; + acc = udphdr->chksum + (u16_t)~(chksum); + udphdr->chksum = FOLD_U32T(acc); + } +#endif /* !LWIP_CHECKSUM_ON_COPY */ + + /* chksum zero must become 0xffff, as zero means 'no checksum' */ + if (udphdr->chksum == 0x0000) { + udphdr->chksum = 0xffff; + } +#endif /* CHECKSUM_GEN_UDP */ + /* output to IP */ + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDPLITE,)\n")); + NETIF_SET_HWADDRHINT(netif, &pcb->addr_hint); + err = ip_output_if(q, src_ip, dst_ip, pcb->ttl, pcb->tos, IP_PROTO_UDPLITE, netif); + NETIF_SET_HWADDRHINT(netif, NULL); + } else +#endif /* LWIP_UDPLITE */ + { /* UDP */ + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %"U16_F"\n", q->tot_len)); + udphdr->len = htons(q->tot_len); + /* calculate checksum */ +#if CHECKSUM_GEN_UDP + if ((pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) { + u16_t udpchksum; +#if LWIP_CHECKSUM_ON_COPY + if (have_chksum) { + u32_t acc; + udpchksum = inet_chksum_pseudo_partial(q, src_ip, dst_ip, IP_PROTO_UDP, + q->tot_len, UDP_HLEN); + acc = udpchksum + (u16_t)~(chksum); + udpchksum = FOLD_U32T(acc); + } else +#endif /* LWIP_CHECKSUM_ON_COPY */ + { + udpchksum = inet_chksum_pseudo(q, src_ip, dst_ip, IP_PROTO_UDP, q->tot_len); + } + + /* chksum zero must become 0xffff, as zero means 'no checksum' */ + if (udpchksum == 0x0000) { + udpchksum = 0xffff; + } + udphdr->chksum = udpchksum; + } +#endif /* CHECKSUM_GEN_UDP */ + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum 0x%04"X16_F"\n", udphdr->chksum)); + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDP,)\n")); + /* output to IP */ + NETIF_SET_HWADDRHINT(netif, &pcb->addr_hint); + err = ip_output_if(q, src_ip, dst_ip, pcb->ttl, pcb->tos, IP_PROTO_UDP, netif); + NETIF_SET_HWADDRHINT(netif, NULL); + } + /* TODO: must this be increased even if error occured? */ + snmp_inc_udpoutdatagrams(); + + /* did we chain a separate header pbuf earlier? */ + if (q != p) { + /* free the header pbuf */ + pbuf_free(q); + q = NULL; + /* p is still referenced by the caller, and will live on */ + } + + UDP_STATS_INC(udp.xmit); + return err; +} + +/** + * Bind an UDP PCB. + * + * @param pcb UDP PCB to be bound with a local address ipaddr and port. + * @param ipaddr local IP address to bind with. Use IP_ADDR_ANY to + * bind to all local interfaces. + * @param port local UDP port to bind with. Use 0 to automatically bind + * to a random port between UDP_LOCAL_PORT_RANGE_START and + * UDP_LOCAL_PORT_RANGE_END. + * + * ipaddr & port are expected to be in the same byte order as in the pcb. + * + * @return lwIP error code. + * - ERR_OK. Successful. No error occured. + * - ERR_USE. The specified ipaddr and port are already bound to by + * another UDP PCB. + * + * @see udp_disconnect() + */ +err_t +udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port) +{ + struct udp_pcb *ipcb; + u8_t rebind; + + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_bind(ipaddr = ")); + ip_addr_debug_print(UDP_DEBUG, ipaddr); + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, (", port = %"U16_F")\n", port)); + + rebind = 0; + /* Check for double bind and rebind of the same pcb */ + for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) { + /* is this UDP PCB already on active list? */ + if (pcb == ipcb) { + /* pcb may occur at most once in active list */ + LWIP_ASSERT("rebind == 0", rebind == 0); + /* pcb already in list, just rebind */ + rebind = 1; + } + + /* By default, we don't allow to bind to a port that any other udp + PCB is alread bound to, unless *all* PCBs with that port have tha + REUSEADDR flag set. */ +#if SO_REUSE + else if (!ip_get_option(pcb, SOF_REUSEADDR) && + !ip_get_option(ipcb, SOF_REUSEADDR)) { +#else /* SO_REUSE */ + /* port matches that of PCB in list and REUSEADDR not set -> reject */ + else { +#endif /* SO_REUSE */ + if ((ipcb->local_port == port) && + /* IP address matches, or one is IP_ADDR_ANY? */ + (ip_addr_isany(&(ipcb->local_ip)) || + ip_addr_isany(ipaddr) || + ip_addr_cmp(&(ipcb->local_ip), ipaddr))) { + /* other PCB already binds to this local IP and port */ + LWIP_DEBUGF(UDP_DEBUG, + ("udp_bind: local port %"U16_F" already bound by another pcb\n", port)); + return ERR_USE; + } + } + } + + ip_addr_set(&pcb->local_ip, ipaddr); + + /* no port specified? */ + if (port == 0) { + port = udp_new_port(); + if (port == 0) { + /* no more ports available in local range */ + LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: out of free UDP ports\n")); + return ERR_USE; + } + } + pcb->local_port = port; + snmp_insert_udpidx_tree(pcb); + /* pcb not active yet? */ + if (rebind == 0) { + /* place the PCB on the active list if not already there */ + pcb->next = udp_pcbs; + udp_pcbs = pcb; + } + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("udp_bind: bound to %"U16_F".%"U16_F".%"U16_F".%"U16_F", port %"U16_F"\n", + ip4_addr1_16(&pcb->local_ip), ip4_addr2_16(&pcb->local_ip), + ip4_addr3_16(&pcb->local_ip), ip4_addr4_16(&pcb->local_ip), + pcb->local_port)); + return ERR_OK; +} +/** + * Connect an UDP PCB. + * + * This will associate the UDP PCB with the remote address. + * + * @param pcb UDP PCB to be connected with remote address ipaddr and port. + * @param ipaddr remote IP address to connect with. + * @param port remote UDP port to connect with. + * + * @return lwIP error code + * + * ipaddr & port are expected to be in the same byte order as in the pcb. + * + * The udp pcb is bound to a random local port if not already bound. + * + * @see udp_disconnect() + */ +err_t +udp_connect(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port) +{ + struct udp_pcb *ipcb; + + if (pcb->local_port == 0) { + err_t err = udp_bind(pcb, &pcb->local_ip, pcb->local_port); + if (err != ERR_OK) { + return err; + } + } + + ip_addr_set(&pcb->remote_ip, ipaddr); + pcb->remote_port = port; + pcb->flags |= UDP_FLAGS_CONNECTED; +/** TODO: this functionality belongs in upper layers */ +#ifdef LWIP_UDP_TODO + /* Nail down local IP for netconn_addr()/getsockname() */ + if (ip_addr_isany(&pcb->local_ip) && !ip_addr_isany(&pcb->remote_ip)) { + struct netif *netif; + + if ((netif = ip_route(&(pcb->remote_ip))) == NULL) { + LWIP_DEBUGF(UDP_DEBUG, ("udp_connect: No route to 0x%lx\n", pcb->remote_ip.addr)); + UDP_STATS_INC(udp.rterr); + return ERR_RTE; + } + /** TODO: this will bind the udp pcb locally, to the interface which + is used to route output packets to the remote address. However, we + might want to accept incoming packets on any interface! */ + pcb->local_ip = netif->ip_addr; + } else if (ip_addr_isany(&pcb->remote_ip)) { + pcb->local_ip.addr = 0; + } +#endif + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("udp_connect: connected to %"U16_F".%"U16_F".%"U16_F".%"U16_F",port %"U16_F"\n", + ip4_addr1_16(&pcb->local_ip), ip4_addr2_16(&pcb->local_ip), + ip4_addr3_16(&pcb->local_ip), ip4_addr4_16(&pcb->local_ip), + pcb->local_port)); + + /* Insert UDP PCB into the list of active UDP PCBs. */ + for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) { + if (pcb == ipcb) { + /* already on the list, just return */ + return ERR_OK; + } + } + /* PCB not yet on the list, add PCB now */ + pcb->next = udp_pcbs; + udp_pcbs = pcb; + return ERR_OK; +} + +/** + * Disconnect a UDP PCB + * + * @param pcb the udp pcb to disconnect. + */ +void +udp_disconnect(struct udp_pcb *pcb) +{ + /* reset remote address association */ + ip_addr_set_any(&pcb->remote_ip); + pcb->remote_port = 0; + /* mark PCB as unconnected */ + pcb->flags &= ~UDP_FLAGS_CONNECTED; +} + +/** + * Set a receive callback for a UDP PCB + * + * This callback will be called when receiving a datagram for the pcb. + * + * @param pcb the pcb for wich to set the recv callback + * @param recv function pointer of the callback function + * @param recv_arg additional argument to pass to the callback function + */ +void +udp_recv(struct udp_pcb *pcb, udp_recv_fn recv, void *recv_arg) +{ + /* remember recv() callback and user data */ + pcb->recv = recv; + pcb->recv_arg = recv_arg; +} + +/** + * Remove an UDP PCB. + * + * @param pcb UDP PCB to be removed. The PCB is removed from the list of + * UDP PCB's and the data structure is freed from memory. + * + * @see udp_new() + */ +void +udp_remove(struct udp_pcb *pcb) +{ + struct udp_pcb *pcb2; + + snmp_delete_udpidx_tree(pcb); + /* pcb to be removed is first in list? */ + if (udp_pcbs == pcb) { + /* make list start at 2nd pcb */ + udp_pcbs = udp_pcbs->next; + /* pcb not 1st in list */ + } else { + for (pcb2 = udp_pcbs; pcb2 != NULL; pcb2 = pcb2->next) { + /* find pcb in udp_pcbs list */ + if (pcb2->next != NULL && pcb2->next == pcb) { + /* remove pcb from list */ + pcb2->next = pcb->next; + } + } + } + memp_free(MEMP_UDP_PCB, pcb); +} + +/** + * Create a UDP PCB. + * + * @return The UDP PCB which was created. NULL if the PCB data structure + * could not be allocated. + * + * @see udp_remove() + */ +struct udp_pcb * +udp_new(void) +{ + struct udp_pcb *pcb; + pcb = (struct udp_pcb *)memp_malloc(MEMP_UDP_PCB); + /* could allocate UDP PCB? */ + if (pcb != NULL) { + /* UDP Lite: by initializing to all zeroes, chksum_len is set to 0 + * which means checksum is generated over the whole datagram per default + * (recommended as default by RFC 3828). */ + /* initialize PCB to all zeroes */ + memset(pcb, 0, sizeof(struct udp_pcb)); + pcb->ttl = UDP_TTL; + } + return pcb; +} + +#if UDP_DEBUG +/** + * Print UDP header information for debug purposes. + * + * @param udphdr pointer to the udp header in memory. + */ +void +udp_debug_print(struct udp_hdr *udphdr) +{ + LWIP_DEBUGF(UDP_DEBUG, ("UDP header:\n")); + LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n", + ntohs(udphdr->src), ntohs(udphdr->dest))); + LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | 0x%04"X16_F" | (len, chksum)\n", + ntohs(udphdr->len), ntohs(udphdr->chksum))); + LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); +} +#endif /* UDP_DEBUG */ + +#endif /* LWIP_UDP */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/ipv4/lwip/autoip.h b/component/common/network/lwip/lwip_v1.4.1/src/include/ipv4/lwip/autoip.h new file mode 100644 index 0000000..e62b72e --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/ipv4/lwip/autoip.h @@ -0,0 +1,118 @@ +/** + * @file + * + * AutoIP Automatic LinkLocal IP Configuration + */ + +/* + * + * Copyright (c) 2007 Dominik Spies + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * Author: Dominik Spies + * + * This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform + * with RFC 3927. + * + * + * Please coordinate changes and requests with Dominik Spies + * + */ + +#ifndef __LWIP_AUTOIP_H__ +#define __LWIP_AUTOIP_H__ + +#include "lwip/opt.h" + +#if LWIP_AUTOIP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/netif.h" +#include "lwip/udp.h" +#include "netif/etharp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* AutoIP Timing */ +#define AUTOIP_TMR_INTERVAL 100 +#define AUTOIP_TICKS_PER_SECOND (1000 / AUTOIP_TMR_INTERVAL) + +/* RFC 3927 Constants */ +#define PROBE_WAIT 1 /* second (initial random delay) */ +#define PROBE_MIN 1 /* second (minimum delay till repeated probe) */ +#define PROBE_MAX 2 /* seconds (maximum delay till repeated probe) */ +#define PROBE_NUM 3 /* (number of probe packets) */ +#define ANNOUNCE_NUM 2 /* (number of announcement packets) */ +#define ANNOUNCE_INTERVAL 2 /* seconds (time between announcement packets) */ +#define ANNOUNCE_WAIT 2 /* seconds (delay before announcing) */ +#define MAX_CONFLICTS 10 /* (max conflicts before rate limiting) */ +#define RATE_LIMIT_INTERVAL 60 /* seconds (delay between successive attempts) */ +#define DEFEND_INTERVAL 10 /* seconds (min. wait between defensive ARPs) */ + +/* AutoIP client states */ +#define AUTOIP_STATE_OFF 0 +#define AUTOIP_STATE_PROBING 1 +#define AUTOIP_STATE_ANNOUNCING 2 +#define AUTOIP_STATE_BOUND 3 + +struct autoip +{ + ip_addr_t llipaddr; /* the currently selected, probed, announced or used LL IP-Address */ + u8_t state; /* current AutoIP state machine state */ + u8_t sent_num; /* sent number of probes or announces, dependent on state */ + u16_t ttw; /* ticks to wait, tick is AUTOIP_TMR_INTERVAL long */ + u8_t lastconflict; /* ticks until a conflict can be solved by defending */ + u8_t tried_llipaddr; /* total number of probed/used Link Local IP-Addresses */ +}; + + +#define autoip_init() /* Compatibility define, no init needed. */ + +/** Set a struct autoip allocated by the application to work with */ +void autoip_set_struct(struct netif *netif, struct autoip *autoip); + +/** Start AutoIP client */ +err_t autoip_start(struct netif *netif); + +/** Stop AutoIP client */ +err_t autoip_stop(struct netif *netif); + +/** Handles every incoming ARP Packet, called by etharp_arp_input */ +void autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr); + +/** Has to be called in loop every AUTOIP_TMR_INTERVAL milliseconds */ +void autoip_tmr(void); + +/** Handle a possible change in the network configuration */ +void autoip_network_changed(struct netif *netif); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_AUTOIP */ + +#endif /* __LWIP_AUTOIP_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/ipv4/lwip/icmp.h b/component/common/network/lwip/lwip_v1.4.1/src/include/ipv4/lwip/icmp.h new file mode 100644 index 0000000..d47a7d8 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/ipv4/lwip/icmp.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_ICMP_H__ +#define __LWIP_ICMP_H__ + +#include "lwip/opt.h" +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ICMP_ER 0 /* echo reply */ +#define ICMP_DUR 3 /* destination unreachable */ +#define ICMP_SQ 4 /* source quench */ +#define ICMP_RD 5 /* redirect */ +#define ICMP_ECHO 8 /* echo */ +#define ICMP_TE 11 /* time exceeded */ +#define ICMP_PP 12 /* parameter problem */ +#define ICMP_TS 13 /* timestamp */ +#define ICMP_TSR 14 /* timestamp reply */ +#define ICMP_IRQ 15 /* information request */ +#define ICMP_IR 16 /* information reply */ + +enum icmp_dur_type { + ICMP_DUR_NET = 0, /* net unreachable */ + ICMP_DUR_HOST = 1, /* host unreachable */ + ICMP_DUR_PROTO = 2, /* protocol unreachable */ + ICMP_DUR_PORT = 3, /* port unreachable */ + ICMP_DUR_FRAG = 4, /* fragmentation needed and DF set */ + ICMP_DUR_SR = 5 /* source route failed */ +}; + +enum icmp_te_type { + ICMP_TE_TTL = 0, /* time to live exceeded in transit */ + ICMP_TE_FRAG = 1 /* fragment reassembly time exceeded */ +}; + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +/** This is the standard ICMP header only that the u32_t data + * is splitted to two u16_t like ICMP echo needs it. + * This header is also used for other ICMP types that do not + * use the data part. + */ +PACK_STRUCT_BEGIN +struct icmp_echo_hdr { + PACK_STRUCT_FIELD(u8_t type); + PACK_STRUCT_FIELD(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u16_t id); + PACK_STRUCT_FIELD(u16_t seqno); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define ICMPH_TYPE(hdr) ((hdr)->type) +#define ICMPH_CODE(hdr) ((hdr)->code) + +/** Combines type and code to an u16_t */ +#define ICMPH_TYPE_SET(hdr, t) ((hdr)->type = (t)) +#define ICMPH_CODE_SET(hdr, c) ((hdr)->code = (c)) + + +#if LWIP_ICMP /* don't build if not configured for use in lwipopts.h */ + +void icmp_input(struct pbuf *p, struct netif *inp); +void icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t); +void icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t); + +#endif /* LWIP_ICMP */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_ICMP_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/ipv4/lwip/igmp.h b/component/common/network/lwip/lwip_v1.4.1/src/include/ipv4/lwip/igmp.h new file mode 100644 index 0000000..8aabac2 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/ipv4/lwip/igmp.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2002 CITEL Technologies Ltd. + * 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 CITEL Technologies Ltd 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 CITEL TECHNOLOGIES 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 CITEL TECHNOLOGIES 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. + * + * This file is a contribution to the lwIP TCP/IP stack. + * The Swedish Institute of Computer Science and Adam Dunkels + * are specifically granted permission to redistribute this + * source code. +*/ + +#ifndef __LWIP_IGMP_H__ +#define __LWIP_IGMP_H__ + +#include "lwip/opt.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/pbuf.h" + +#if LWIP_IGMP /* don't build if not configured for use in lwipopts.h */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/* IGMP timer */ +#define IGMP_TMR_INTERVAL 100 /* Milliseconds */ +#define IGMP_V1_DELAYING_MEMBER_TMR (1000/IGMP_TMR_INTERVAL) +#define IGMP_JOIN_DELAYING_MEMBER_TMR (500 /IGMP_TMR_INTERVAL) + +/* MAC Filter Actions, these are passed to a netif's + * igmp_mac_filter callback function. */ +#define IGMP_DEL_MAC_FILTER 0 +#define IGMP_ADD_MAC_FILTER 1 + + +/** + * igmp group structure - there is + * a list of groups for each interface + * these should really be linked from the interface, but + * if we keep them separate we will not affect the lwip original code + * too much + * + * There will be a group for the all systems group address but this + * will not run the state machine as it is used to kick off reports + * from all the other groups + */ +struct igmp_group { + /** next link */ + struct igmp_group *next; + /** interface on which the group is active */ + struct netif *netif; + /** multicast address */ + ip_addr_t group_address; + /** signifies we were the last person to report */ + u8_t last_reporter_flag; + /** current state of the group */ + u8_t group_state; + /** timer for reporting, negative is OFF */ + u16_t timer; + /** counter of simultaneous uses */ + u8_t use; +}; + +/* Prototypes */ +void igmp_init(void); +err_t igmp_start(struct netif *netif); +err_t igmp_stop(struct netif *netif); +void igmp_report_groups(struct netif *netif); +struct igmp_group *igmp_lookfor_group(struct netif *ifp, ip_addr_t *addr); +void igmp_input(struct pbuf *p, struct netif *inp, ip_addr_t *dest); +err_t igmp_joingroup(ip_addr_t *ifaddr, ip_addr_t *groupaddr); +err_t igmp_leavegroup(ip_addr_t *ifaddr, ip_addr_t *groupaddr); +void igmp_tmr(void); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IGMP */ + +#endif /* __LWIP_IGMP_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/ipv4/lwip/inet.h b/component/common/network/lwip/lwip_v1.4.1/src/include/ipv4/lwip/inet.h new file mode 100644 index 0000000..7bff49b --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/ipv4/lwip/inet.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_INET_H__ +#define __LWIP_INET_H__ + +#include "lwip/opt.h" +#include "lwip/def.h" +#include "lwip/ip_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** For compatibility with BSD code */ +struct in_addr { + u32_t s_addr; +}; + +/** 255.255.255.255 */ +#define INADDR_NONE IPADDR_NONE +/** 127.0.0.1 */ +#define INADDR_LOOPBACK IPADDR_LOOPBACK +/** 0.0.0.0 */ +#define INADDR_ANY IPADDR_ANY +/** 255.255.255.255 */ +#define INADDR_BROADCAST IPADDR_BROADCAST + +/* Definitions of the bits in an Internet address integer. + + On subnets, host and network parts are found according to + the subnet mask, not these masks. */ +#define IN_CLASSA(a) IP_CLASSA(a) +#define IN_CLASSA_NET IP_CLASSA_NET +#define IN_CLASSA_NSHIFT IP_CLASSA_NSHIFT +#define IN_CLASSA_HOST IP_CLASSA_HOST +#define IN_CLASSA_MAX IP_CLASSA_MAX + +#define IN_CLASSB(b) IP_CLASSB(b) +#define IN_CLASSB_NET IP_CLASSB_NET +#define IN_CLASSB_NSHIFT IP_CLASSB_NSHIFT +#define IN_CLASSB_HOST IP_CLASSB_HOST +#define IN_CLASSB_MAX IP_CLASSB_MAX + +#define IN_CLASSC(c) IP_CLASSC(c) +#define IN_CLASSC_NET IP_CLASSC_NET +#define IN_CLASSC_NSHIFT IP_CLASSC_NSHIFT +#define IN_CLASSC_HOST IP_CLASSC_HOST +#define IN_CLASSC_MAX IP_CLASSC_MAX + +#define IN_CLASSD(d) IP_CLASSD(d) +#define IN_CLASSD_NET IP_CLASSD_NET /* These ones aren't really */ +#define IN_CLASSD_NSHIFT IP_CLASSD_NSHIFT /* net and host fields, but */ +#define IN_CLASSD_HOST IP_CLASSD_HOST /* routing needn't know. */ +#define IN_CLASSD_MAX IP_CLASSD_MAX + +#define IN_MULTICAST(a) IP_MULTICAST(a) + +#define IN_EXPERIMENTAL(a) IP_EXPERIMENTAL(a) +#define IN_BADCLASS(a) IP_BADCLASS(a) + +#define IN_LOOPBACKNET IP_LOOPBACKNET + +#define inet_addr_from_ipaddr(target_inaddr, source_ipaddr) ((target_inaddr)->s_addr = ip4_addr_get_u32(source_ipaddr)) +#define inet_addr_to_ipaddr(target_ipaddr, source_inaddr) (ip4_addr_set_u32(target_ipaddr, (source_inaddr)->s_addr)) +/* ATTENTION: the next define only works because both s_addr and ip_addr_t are an u32_t effectively! */ +#define inet_addr_to_ipaddr_p(target_ipaddr_p, source_inaddr) ((target_ipaddr_p) = (ip_addr_t*)&((source_inaddr)->s_addr)) + +/* directly map this to the lwip internal functions */ +#define inet_addr(cp) ipaddr_addr(cp) +#define inet_aton(cp, addr) ipaddr_aton(cp, (ip_addr_t*)addr) +#define inet_ntoa(addr) ipaddr_ntoa((ip_addr_t*)&(addr)) +#define inet_ntoa_r(addr, buf, buflen) ipaddr_ntoa_r((ip_addr_t*)&(addr), buf, buflen) + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_INET_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/ipv4/lwip/inet_chksum.h b/component/common/network/lwip/lwip_v1.4.1/src/include/ipv4/lwip/inet_chksum.h new file mode 100644 index 0000000..79a2d90 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/ipv4/lwip/inet_chksum.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_INET_CHKSUM_H__ +#define __LWIP_INET_CHKSUM_H__ + +#include "lwip/opt.h" + +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" + +/** Swap the bytes in an u16_t: much like htons() for little-endian */ +#ifndef SWAP_BYTES_IN_WORD +#if LWIP_PLATFORM_BYTESWAP && (BYTE_ORDER == LITTLE_ENDIAN) +/* little endian and PLATFORM_BYTESWAP defined */ +#define SWAP_BYTES_IN_WORD(w) LWIP_PLATFORM_HTONS(w) +#else /* LWIP_PLATFORM_BYTESWAP && (BYTE_ORDER == LITTLE_ENDIAN) */ +/* can't use htons on big endian (or PLATFORM_BYTESWAP not defined)... */ +#define SWAP_BYTES_IN_WORD(w) (((w) & 0xff) << 8) | (((w) & 0xff00) >> 8) +#endif /* LWIP_PLATFORM_BYTESWAP && (BYTE_ORDER == LITTLE_ENDIAN)*/ +#endif /* SWAP_BYTES_IN_WORD */ + +/** Split an u32_t in two u16_ts and add them up */ +#ifndef FOLD_U32T +#define FOLD_U32T(u) (((u) >> 16) + ((u) & 0x0000ffffUL)) +#endif + +#if LWIP_CHECKSUM_ON_COPY +/** Function-like macro: same as MEMCPY but returns the checksum of copied data + as u16_t */ +#ifndef LWIP_CHKSUM_COPY +#define LWIP_CHKSUM_COPY(dst, src, len) lwip_chksum_copy(dst, src, len) +#ifndef LWIP_CHKSUM_COPY_ALGORITHM +#define LWIP_CHKSUM_COPY_ALGORITHM 1 +#endif /* LWIP_CHKSUM_COPY_ALGORITHM */ +#endif /* LWIP_CHKSUM_COPY */ +#else /* LWIP_CHECKSUM_ON_COPY */ +#define LWIP_CHKSUM_COPY_ALGORITHM 0 +#endif /* LWIP_CHECKSUM_ON_COPY */ + +#ifdef __cplusplus +extern "C" { +#endif + +u16_t inet_chksum(void *dataptr, u16_t len); +u16_t inet_chksum_pbuf(struct pbuf *p); +u16_t inet_chksum_pseudo(struct pbuf *p, + ip_addr_t *src, ip_addr_t *dest, + u8_t proto, u16_t proto_len); +u16_t inet_chksum_pseudo_partial(struct pbuf *p, + ip_addr_t *src, ip_addr_t *dest, + u8_t proto, u16_t proto_len, u16_t chksum_len); +#if LWIP_CHKSUM_COPY_ALGORITHM +u16_t lwip_chksum_copy(void *dst, const void *src, u16_t len); +#endif /* LWIP_CHKSUM_COPY_ALGORITHM */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_INET_H__ */ + diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/ipv4/lwip/ip.h b/component/common/network/lwip/lwip_v1.4.1/src/include/ipv4/lwip/ip.h new file mode 100644 index 0000000..00c83a0 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/ipv4/lwip/ip.h @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_IP_H__ +#define __LWIP_IP_H__ + +#include "lwip/opt.h" + +#include "lwip/def.h" +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" +#include "lwip/err.h" +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Currently, the function ip_output_if_opt() is only used with IGMP */ +#define IP_OPTIONS_SEND LWIP_IGMP + +#define IP_HLEN 20 + +#define IP_PROTO_ICMP 1 +#define IP_PROTO_IGMP 2 +#define IP_PROTO_UDP 17 +#define IP_PROTO_UDPLITE 136 +#define IP_PROTO_TCP 6 + +/* This is passed as the destination address to ip_output_if (not + to ip_output), meaning that an IP header already is constructed + in the pbuf. This is used when TCP retransmits. */ +#ifdef IP_HDRINCL +#undef IP_HDRINCL +#endif /* IP_HDRINCL */ +#define IP_HDRINCL NULL + +#if LWIP_NETIF_HWADDRHINT +#define IP_PCB_ADDRHINT ;u8_t addr_hint +#else +#define IP_PCB_ADDRHINT +#endif /* LWIP_NETIF_HWADDRHINT */ + +/* This is the common part of all PCB types. It needs to be at the + beginning of a PCB type definition. It is located here so that + changes to this common part are made in one location instead of + having to change all PCB structs. */ +#define IP_PCB \ + /* ip addresses in network byte order */ \ + ip_addr_t local_ip; \ + ip_addr_t remote_ip; \ + /* Socket options */ \ + u8_t so_options; \ + /* Type Of Service */ \ + u8_t tos; \ + /* Time To Live */ \ + u8_t ttl \ + /* link layer address resolution hint */ \ + IP_PCB_ADDRHINT + +struct ip_pcb { +/* Common members of all PCB types */ + IP_PCB; +}; + +/* + * Option flags per-socket. These are the same like SO_XXX. + */ +/*#define SOF_DEBUG 0x01U Unimplemented: turn on debugging info recording */ +#define SOF_ACCEPTCONN 0x02U /* socket has had listen() */ +#define SOF_REUSEADDR 0x04U /* allow local address reuse */ +#define SOF_KEEPALIVE 0x08U /* keep connections alive */ +/*#define SOF_DONTROUTE 0x10U Unimplemented: just use interface addresses */ +#define SOF_BROADCAST 0x20U /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */ +/*#define SOF_USELOOPBACK 0x40U Unimplemented: bypass hardware when possible */ +#define SOF_LINGER 0x80U /* linger on close if data present */ +/*#define SOF_OOBINLINE 0x0100U Unimplemented: leave received OOB data in line */ +/*#define SOF_REUSEPORT 0x0200U Unimplemented: allow local address & port reuse */ + +/* These flags are inherited (e.g. from a listen-pcb to a connection-pcb): */ +#define SOF_INHERITED (SOF_REUSEADDR|SOF_KEEPALIVE|SOF_LINGER/*|SOF_DEBUG|SOF_DONTROUTE|SOF_OOBINLINE*/) + + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip_hdr { + /* version / header length */ + PACK_STRUCT_FIELD(u8_t _v_hl); + /* type of service */ + PACK_STRUCT_FIELD(u8_t _tos); + /* total length */ + PACK_STRUCT_FIELD(u16_t _len); + /* identification */ + PACK_STRUCT_FIELD(u16_t _id); + /* fragment offset field */ + PACK_STRUCT_FIELD(u16_t _offset); +#define IP_RF 0x8000U /* reserved fragment flag */ +#define IP_DF 0x4000U /* dont fragment flag */ +#define IP_MF 0x2000U /* more fragments flag */ +#define IP_OFFMASK 0x1fffU /* mask for fragmenting bits */ + /* time to live */ + PACK_STRUCT_FIELD(u8_t _ttl); + /* protocol*/ + PACK_STRUCT_FIELD(u8_t _proto); + /* checksum */ + PACK_STRUCT_FIELD(u16_t _chksum); + /* source and destination IP addresses */ + PACK_STRUCT_FIELD(ip_addr_p_t src); + PACK_STRUCT_FIELD(ip_addr_p_t dest); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define IPH_V(hdr) ((hdr)->_v_hl >> 4) +#define IPH_HL(hdr) ((hdr)->_v_hl & 0x0f) +#define IPH_TOS(hdr) ((hdr)->_tos) +#define IPH_LEN(hdr) ((hdr)->_len) +#define IPH_ID(hdr) ((hdr)->_id) +#define IPH_OFFSET(hdr) ((hdr)->_offset) +#define IPH_TTL(hdr) ((hdr)->_ttl) +#define IPH_PROTO(hdr) ((hdr)->_proto) +#define IPH_CHKSUM(hdr) ((hdr)->_chksum) + +#define IPH_VHL_SET(hdr, v, hl) (hdr)->_v_hl = (((v) << 4) | (hl)) +#define IPH_TOS_SET(hdr, tos) (hdr)->_tos = (tos) +#define IPH_LEN_SET(hdr, len) (hdr)->_len = (len) +#define IPH_ID_SET(hdr, id) (hdr)->_id = (id) +#define IPH_OFFSET_SET(hdr, off) (hdr)->_offset = (off) +#define IPH_TTL_SET(hdr, ttl) (hdr)->_ttl = (u8_t)(ttl) +#define IPH_PROTO_SET(hdr, proto) (hdr)->_proto = (u8_t)(proto) +#define IPH_CHKSUM_SET(hdr, chksum) (hdr)->_chksum = (chksum) + +/** The interface that provided the packet for the current callback invocation. */ +extern struct netif *current_netif; +/** Header of the input packet currently being processed. */ +extern const struct ip_hdr *current_header; +/** Source IP address of current_header */ +extern ip_addr_t current_iphdr_src; +/** Destination IP address of current_header */ +extern ip_addr_t current_iphdr_dest; + +#define ip_init() /* Compatibility define, not init needed. */ +struct netif *ip_route(ip_addr_t *dest); +err_t ip_input(struct pbuf *p, struct netif *inp); +err_t ip_output(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto); +err_t ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, + struct netif *netif); +#if LWIP_NETIF_HWADDRHINT +err_t ip_output_hinted(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint); +#endif /* LWIP_NETIF_HWADDRHINT */ +#if IP_OPTIONS_SEND +err_t ip_output_if_opt(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, + u16_t optlen); +#endif /* IP_OPTIONS_SEND */ +/** Get the interface that received the current packet. + * This function must only be called from a receive callback (udp_recv, + * raw_recv, tcp_accept). It will return NULL otherwise. */ +#define ip_current_netif() (current_netif) +/** Get the IP header of the current packet. + * This function must only be called from a receive callback (udp_recv, + * raw_recv, tcp_accept). It will return NULL otherwise. */ +#define ip_current_header() (current_header) +/** Source IP address of current_header */ +#define ip_current_src_addr() (¤t_iphdr_src) +/** Destination IP address of current_header */ +#define ip_current_dest_addr() (¤t_iphdr_dest) + +/** Gets an IP pcb option (SOF_* flags) */ +#define ip_get_option(pcb, opt) ((pcb)->so_options & (opt)) +/** Sets an IP pcb option (SOF_* flags) */ +#define ip_set_option(pcb, opt) ((pcb)->so_options |= (opt)) +/** Resets an IP pcb option (SOF_* flags) */ +#define ip_reset_option(pcb, opt) ((pcb)->so_options &= ~(opt)) + +#if IP_DEBUG +void ip_debug_print(struct pbuf *p); +#else +#define ip_debug_print(p) +#endif /* IP_DEBUG */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_IP_H__ */ + + diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/ipv4/lwip/ip_addr.h b/component/common/network/lwip/lwip_v1.4.1/src/include/ipv4/lwip/ip_addr.h new file mode 100644 index 0000000..77f84e0 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/ipv4/lwip/ip_addr.h @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_IP_ADDR_H__ +#define __LWIP_IP_ADDR_H__ + +#include "lwip/opt.h" +#include "lwip/def.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* This is the aligned version of ip_addr_t, + used as local variable, on the stack, etc. */ +struct ip_addr { + u32_t addr; +}; + +/* This is the packed version of ip_addr_t, + used in network headers that are itself packed */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip_addr_packed { + PACK_STRUCT_FIELD(u32_t addr); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** ip_addr_t uses a struct for convenience only, so that the same defines can + * operate both on ip_addr_t as well as on ip_addr_p_t. */ +typedef struct ip_addr ip_addr_t; +typedef struct ip_addr_packed ip_addr_p_t; + +/* + * struct ipaddr2 is used in the definition of the ARP packet format in + * order to support compilers that don't have structure packing. + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip_addr2 { + PACK_STRUCT_FIELD(u16_t addrw[2]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* Forward declaration to not include netif.h */ +struct netif; + +extern const ip_addr_t ip_addr_any; +extern const ip_addr_t ip_addr_broadcast; + +/** IP_ADDR_ can be used as a fixed IP address + * for the wildcard and the broadcast address + */ +#define IP_ADDR_ANY ((ip_addr_t *)&ip_addr_any) +#define IP_ADDR_BROADCAST ((ip_addr_t *)&ip_addr_broadcast) + +/** 255.255.255.255 */ +#define IPADDR_NONE ((u32_t)0xffffffffUL) +/** 127.0.0.1 */ +#define IPADDR_LOOPBACK ((u32_t)0x7f000001UL) +/** 0.0.0.0 */ +#define IPADDR_ANY ((u32_t)0x00000000UL) +/** 255.255.255.255 */ +#define IPADDR_BROADCAST ((u32_t)0xffffffffUL) + +/* Definitions of the bits in an Internet address integer. + + On subnets, host and network parts are found according to + the subnet mask, not these masks. */ +#define IP_CLASSA(a) ((((u32_t)(a)) & 0x80000000UL) == 0) +#define IP_CLASSA_NET 0xff000000 +#define IP_CLASSA_NSHIFT 24 +#define IP_CLASSA_HOST (0xffffffff & ~IP_CLASSA_NET) +#define IP_CLASSA_MAX 128 + +#define IP_CLASSB(a) ((((u32_t)(a)) & 0xc0000000UL) == 0x80000000UL) +#define IP_CLASSB_NET 0xffff0000 +#define IP_CLASSB_NSHIFT 16 +#define IP_CLASSB_HOST (0xffffffff & ~IP_CLASSB_NET) +#define IP_CLASSB_MAX 65536 + +#define IP_CLASSC(a) ((((u32_t)(a)) & 0xe0000000UL) == 0xc0000000UL) +#define IP_CLASSC_NET 0xffffff00 +#define IP_CLASSC_NSHIFT 8 +#define IP_CLASSC_HOST (0xffffffff & ~IP_CLASSC_NET) + +#define IP_CLASSD(a) (((u32_t)(a) & 0xf0000000UL) == 0xe0000000UL) +#define IP_CLASSD_NET 0xf0000000 /* These ones aren't really */ +#define IP_CLASSD_NSHIFT 28 /* net and host fields, but */ +#define IP_CLASSD_HOST 0x0fffffff /* routing needn't know. */ +#define IP_MULTICAST(a) IP_CLASSD(a) + +#define IP_EXPERIMENTAL(a) (((u32_t)(a) & 0xf0000000UL) == 0xf0000000UL) +#define IP_BADCLASS(a) (((u32_t)(a) & 0xf0000000UL) == 0xf0000000UL) + +#define IP_LOOPBACKNET 127 /* official! */ + + +#if BYTE_ORDER == BIG_ENDIAN +/** Set an IP address given by the four byte-parts */ +#define IP4_ADDR(ipaddr, a,b,c,d) \ + (ipaddr)->addr = ((u32_t)((a) & 0xff) << 24) | \ + ((u32_t)((b) & 0xff) << 16) | \ + ((u32_t)((c) & 0xff) << 8) | \ + (u32_t)((d) & 0xff) +#else +/** Set an IP address given by the four byte-parts. + Little-endian version that prevents the use of htonl. */ +#define IP4_ADDR(ipaddr, a,b,c,d) \ + (ipaddr)->addr = ((u32_t)((d) & 0xff) << 24) | \ + ((u32_t)((c) & 0xff) << 16) | \ + ((u32_t)((b) & 0xff) << 8) | \ + (u32_t)((a) & 0xff) +#endif + +/** MEMCPY-like copying of IP addresses where addresses are known to be + * 16-bit-aligned if the port is correctly configured (so a port could define + * this to copying 2 u16_t's) - no NULL-pointer-checking needed. */ +#ifndef IPADDR2_COPY +#define IPADDR2_COPY(dest, src) SMEMCPY(dest, src, sizeof(ip_addr_t)) +#endif + +/** Copy IP address - faster than ip_addr_set: no NULL check */ +#define ip_addr_copy(dest, src) ((dest).addr = (src).addr) +/** Safely copy one IP address to another (src may be NULL) */ +#define ip_addr_set(dest, src) ((dest)->addr = \ + ((src) == NULL ? 0 : \ + (src)->addr)) +/** Set complete address to zero */ +#define ip_addr_set_zero(ipaddr) ((ipaddr)->addr = 0) +/** Set address to IPADDR_ANY (no need for htonl()) */ +#define ip_addr_set_any(ipaddr) ((ipaddr)->addr = IPADDR_ANY) +/** Set address to loopback address */ +#define ip_addr_set_loopback(ipaddr) ((ipaddr)->addr = PP_HTONL(IPADDR_LOOPBACK)) +/** Safely copy one IP address to another and change byte order + * from host- to network-order. */ +#define ip_addr_set_hton(dest, src) ((dest)->addr = \ + ((src) == NULL ? 0:\ + htonl((src)->addr))) +/** IPv4 only: set the IP address given as an u32_t */ +#define ip4_addr_set_u32(dest_ipaddr, src_u32) ((dest_ipaddr)->addr = (src_u32)) +/** IPv4 only: get the IP address as an u32_t */ +#define ip4_addr_get_u32(src_ipaddr) ((src_ipaddr)->addr) + +/** Get the network address by combining host address with netmask */ +#define ip_addr_get_network(target, host, netmask) ((target)->addr = ((host)->addr) & ((netmask)->addr)) + +/** + * Determine if two address are on the same network. + * + * @arg addr1 IP address 1 + * @arg addr2 IP address 2 + * @arg mask network identifier mask + * @return !0 if the network identifiers of both address match + */ +#define ip_addr_netcmp(addr1, addr2, mask) (((addr1)->addr & \ + (mask)->addr) == \ + ((addr2)->addr & \ + (mask)->addr)) +#define ip_addr_cmp(addr1, addr2) ((addr1)->addr == (addr2)->addr) + +#define ip_addr_isany(addr1) ((addr1) == NULL || (addr1)->addr == IPADDR_ANY) + +#define ip_addr_isbroadcast(ipaddr, netif) ip4_addr_isbroadcast((ipaddr)->addr, (netif)) +u8_t ip4_addr_isbroadcast(u32_t addr, const struct netif *netif); + +#define ip_addr_netmask_valid(netmask) ip4_addr_netmask_valid((netmask)->addr) +u8_t ip4_addr_netmask_valid(u32_t netmask); + +#define ip_addr_ismulticast(addr1) (((addr1)->addr & PP_HTONL(0xf0000000UL)) == PP_HTONL(0xe0000000UL)) + +#define ip_addr_islinklocal(addr1) (((addr1)->addr & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xa9fe0000UL)) + +#define ip_addr_debug_print(debug, ipaddr) \ + LWIP_DEBUGF(debug, ("%"U16_F".%"U16_F".%"U16_F".%"U16_F, \ + ipaddr != NULL ? ip4_addr1_16(ipaddr) : 0, \ + ipaddr != NULL ? ip4_addr2_16(ipaddr) : 0, \ + ipaddr != NULL ? ip4_addr3_16(ipaddr) : 0, \ + ipaddr != NULL ? ip4_addr4_16(ipaddr) : 0)) + +/* Get one byte from the 4-byte address */ +#define ip4_addr1(ipaddr) (((u8_t*)(ipaddr))[0]) +#define ip4_addr2(ipaddr) (((u8_t*)(ipaddr))[1]) +#define ip4_addr3(ipaddr) (((u8_t*)(ipaddr))[2]) +#define ip4_addr4(ipaddr) (((u8_t*)(ipaddr))[3]) +/* These are cast to u16_t, with the intent that they are often arguments + * to printf using the U16_F format from cc.h. */ +#define ip4_addr1_16(ipaddr) ((u16_t)ip4_addr1(ipaddr)) +#define ip4_addr2_16(ipaddr) ((u16_t)ip4_addr2(ipaddr)) +#define ip4_addr3_16(ipaddr) ((u16_t)ip4_addr3(ipaddr)) +#define ip4_addr4_16(ipaddr) ((u16_t)ip4_addr4(ipaddr)) + +/** For backwards compatibility */ +#define ip_ntoa(ipaddr) ipaddr_ntoa(ipaddr) + +u32_t ipaddr_addr(const char *cp); +int ipaddr_aton(const char *cp, ip_addr_t *addr); +/** returns ptr to static buffer; not reentrant! */ +char *ipaddr_ntoa(const ip_addr_t *addr); +char *ipaddr_ntoa_r(const ip_addr_t *addr, char *buf, int buflen); + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_IP_ADDR_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/ipv4/lwip/ip_frag.h b/component/common/network/lwip/lwip_v1.4.1/src/include/ipv4/lwip/ip_frag.h new file mode 100644 index 0000000..77b5eb1 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/ipv4/lwip/ip_frag.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Jani Monoses + * + */ + +#ifndef __LWIP_IP_FRAG_H__ +#define __LWIP_IP_FRAG_H__ + +#include "lwip/opt.h" +#include "lwip/err.h" +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/ip_addr.h" +#include "lwip/ip.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if IP_REASSEMBLY +/* The IP reassembly timer interval in milliseconds. */ +#define IP_TMR_INTERVAL 1000 + +/* IP reassembly helper struct. + * This is exported because memp needs to know the size. + */ +struct ip_reassdata { + struct ip_reassdata *next; + struct pbuf *p; + struct ip_hdr iphdr; + u16_t datagram_len; + u8_t flags; + u8_t timer; +}; + +void ip_reass_init(void); +void ip_reass_tmr(void); +struct pbuf * ip_reass(struct pbuf *p); +#endif /* IP_REASSEMBLY */ + +#if IP_FRAG +#if !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF +/** A custom pbuf that holds a reference to another pbuf, which is freed + * when this custom pbuf is freed. This is used to create a custom PBUF_REF + * that points into the original pbuf. */ +struct pbuf_custom_ref { + /** 'base class' */ + struct pbuf_custom pc; + /** pointer to the original pbuf that is referenced */ + struct pbuf *original; +}; +#endif /* !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF */ + +err_t ip_frag(struct pbuf *p, struct netif *netif, ip_addr_t *dest); +#endif /* IP_FRAG */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_IP_FRAG_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/ipv6/lwip/icmp.h b/component/common/network/lwip/lwip_v1.4.1/src/include/ipv6/lwip/icmp.h new file mode 100644 index 0000000..87e9ffd --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/ipv6/lwip/icmp.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_ICMP_H__ +#define __LWIP_ICMP_H__ + +#include "lwip/opt.h" + +#if LWIP_ICMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ICMP6_DUR 1 +#define ICMP6_TE 3 +#define ICMP6_ECHO 128 /* echo */ +#define ICMP6_ER 129 /* echo reply */ + + +enum icmp_dur_type { + ICMP_DUR_NET = 0, /* net unreachable */ + ICMP_DUR_HOST = 1, /* host unreachable */ + ICMP_DUR_PROTO = 2, /* protocol unreachable */ + ICMP_DUR_PORT = 3, /* port unreachable */ + ICMP_DUR_FRAG = 4, /* fragmentation needed and DF set */ + ICMP_DUR_SR = 5 /* source route failed */ +}; + +enum icmp_te_type { + ICMP_TE_TTL = 0, /* time to live exceeded in transit */ + ICMP_TE_FRAG = 1 /* fragment reassembly time exceeded */ +}; + +void icmp_input(struct pbuf *p, struct netif *inp); + +void icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t); +void icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t); + +struct icmp_echo_hdr { + u8_t type; + u8_t icode; + u16_t chksum; + u16_t id; + u16_t seqno; +}; + +struct icmp_dur_hdr { + u8_t type; + u8_t icode; + u16_t chksum; + u32_t unused; +}; + +struct icmp_te_hdr { + u8_t type; + u8_t icode; + u16_t chksum; + u32_t unused; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_ICMP */ + +#endif /* __LWIP_ICMP_H__ */ + diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/ipv6/lwip/inet.h b/component/common/network/lwip/lwip_v1.4.1/src/include/ipv6/lwip/inet.h new file mode 100644 index 0000000..de1a0b6 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/ipv6/lwip/inet.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_INET_H__ +#define __LWIP_INET_H__ + +#include "lwip/opt.h" +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +u16_t inet_chksum(void *data, u16_t len); +u16_t inet_chksum_pbuf(struct pbuf *p); +u16_t inet_chksum_pseudo(struct pbuf *p, + struct ip_addr *src, struct ip_addr *dest, + u8_t proto, u32_t proto_len); + +u32_t inet_addr(const char *cp); +s8_t inet_aton(const char *cp, struct in_addr *addr); + +#ifndef _MACHINE_ENDIAN_H_ +#ifndef _NETINET_IN_H +#ifndef _LINUX_BYTEORDER_GENERIC_H +u16_t htons(u16_t n); +u16_t ntohs(u16_t n); +u32_t htonl(u32_t n); +u32_t ntohl(u32_t n); +#endif /* _LINUX_BYTEORDER_GENERIC_H */ +#endif /* _NETINET_IN_H */ +#endif /* _MACHINE_ENDIAN_H_ */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_INET_H__ */ + diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/ipv6/lwip/ip.h b/component/common/network/lwip/lwip_v1.4.1/src/include/ipv6/lwip/ip.h new file mode 100644 index 0000000..a01cfc6 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/ipv6/lwip/ip.h @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_IP_H__ +#define __LWIP_IP_H__ + +#include "lwip/opt.h" +#include "lwip/def.h" +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" + +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define IP_HLEN 40 + +#define IP_PROTO_ICMP 58 +#define IP_PROTO_UDP 17 +#define IP_PROTO_UDPLITE 136 +#define IP_PROTO_TCP 6 + +/* This is passed as the destination address to ip_output_if (not + to ip_output), meaning that an IP header already is constructed + in the pbuf. This is used when TCP retransmits. */ +#ifdef IP_HDRINCL +#undef IP_HDRINCL +#endif /* IP_HDRINCL */ +#define IP_HDRINCL NULL + +#if LWIP_NETIF_HWADDRHINT +#define IP_PCB_ADDRHINT ;u8_t addr_hint +#else +#define IP_PCB_ADDRHINT +#endif /* LWIP_NETIF_HWADDRHINT */ + +/* This is the common part of all PCB types. It needs to be at the + beginning of a PCB type definition. It is located here so that + changes to this common part are made in one location instead of + having to change all PCB structs. */ +#define IP_PCB struct ip_addr local_ip; \ + struct ip_addr remote_ip; \ + /* Socket options */ \ + u16_t so_options; \ + /* Type Of Service */ \ + u8_t tos; \ + /* Time To Live */ \ + u8_t ttl; \ + /* link layer address resolution hint */ \ + IP_PCB_ADDRHINT + + +/* The IPv6 header. */ +struct ip_hdr { +#if BYTE_ORDER == LITTLE_ENDIAN + u8_t tclass1:4, v:4; + u8_t flow1:4, tclass2:4; +#else + u8_t v:4, tclass1:4; + u8_t tclass2:8, flow1:4; +#endif + u16_t flow2; + u16_t len; /* payload length */ + u8_t nexthdr; /* next header */ + u8_t hoplim; /* hop limit (TTL) */ + struct ip_addr src, dest; /* source and destination IP addresses */ +}; + +#define IPH_PROTO(hdr) (iphdr->nexthdr) + +void ip_init(void); + +#include "lwip/netif.h" + +struct netif *ip_route(struct ip_addr *dest); + +void ip_input(struct pbuf *p, struct netif *inp); + +/* source and destination addresses in network byte order, please */ +err_t ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, + u8_t ttl, u8_t proto); + +err_t ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, + u8_t ttl, u8_t proto, + struct netif *netif); + +#define ip_current_netif() NULL +#define ip_current_header() NULL + +#if IP_DEBUG +void ip_debug_print(struct pbuf *p); +#endif /* IP_DEBUG */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_IP_H__ */ + + diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/ipv6/lwip/ip_addr.h b/component/common/network/lwip/lwip_v1.4.1/src/include/ipv6/lwip/ip_addr.h new file mode 100644 index 0000000..b2d8ae5 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/ipv6/lwip/ip_addr.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_IP_ADDR_H__ +#define __LWIP_IP_ADDR_H__ + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define IP_ADDR_ANY 0 + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN + struct ip_addr { + PACK_STRUCT_FIELD(u32_t addr[4]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* + * struct ipaddr2 is used in the definition of the ARP packet format in + * order to support compilers that don't have structure packing. + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip_addr2 { + PACK_STRUCT_FIELD(u16_t addrw[2]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define IP6_ADDR(ipaddr, a,b,c,d,e,f,g,h) do { (ipaddr)->addr[0] = htonl((u32_t)((a & 0xffff) << 16) | (b & 0xffff)); \ + (ipaddr)->addr[1] = htonl(((c & 0xffff) << 16) | (d & 0xffff)); \ + (ipaddr)->addr[2] = htonl(((e & 0xffff) << 16) | (f & 0xffff)); \ + (ipaddr)->addr[3] = htonl(((g & 0xffff) << 16) | (h & 0xffff)); } while(0) + +u8_t ip_addr_netcmp(struct ip_addr *addr1, struct ip_addr *addr2, + struct ip_addr *mask); +u8_t ip_addr_cmp(struct ip_addr *addr1, struct ip_addr *addr2); +void ip_addr_set(struct ip_addr *dest, struct ip_addr *src); +u8_t ip_addr_isany(struct ip_addr *addr); + +#define ip_addr_debug_print(debug, ipaddr) \ + LWIP_DEBUGF(debug, ("%"X32_F":%"X32_F":%"X32_F":%"X32_F":%"X32_F":%"X32_F":%"X32_F":%"X32_F"\n", \ + (ntohl(ipaddr->addr[0]) >> 16) & 0xffff, \ + ntohl(ipaddr->addr[0]) & 0xffff, \ + (ntohl(ipaddr->addr[1]) >> 16) & 0xffff, \ + ntohl(ipaddr->addr[1]) & 0xffff, \ + (ntohl(ipaddr->addr[2]) >> 16) & 0xffff, \ + ntohl(ipaddr->addr[2]) & 0xffff, \ + (ntohl(ipaddr->addr[3]) >> 16) & 0xffff, \ + ntohl(ipaddr->addr[3]) & 0xffff)); + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_IP_ADDR_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/api.h b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/api.h new file mode 100644 index 0000000..5cfcfb1 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/api.h @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_API_H__ +#define __LWIP_API_H__ + +#include "lwip/opt.h" + +#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ + +#include /* for size_t */ + +#include "lwip/netbuf.h" +#include "lwip/sys.h" +#include "lwip/ip_addr.h" +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Evan add for port netconn api +#define port_netconn_recv(conn , buf, ret) do{ret = netconn_recv(conn, &buf);}while(0); +#define port_netconn_accept(conn , newconn, ret) do{ret = netconn_accept(conn, &newconn);}while(0); +// Evan add end + +/* Throughout this file, IP addresses and port numbers are expected to be in + * the same byte order as in the corresponding pcb. + */ + +/* Flags for netconn_write (u8_t) */ +#define NETCONN_NOFLAG 0x00 +#define NETCONN_NOCOPY 0x00 /* Only for source code compatibility */ +#define NETCONN_COPY 0x01 +#define NETCONN_MORE 0x02 +#define NETCONN_DONTBLOCK 0x04 + +/* Flags for struct netconn.flags (u8_t) */ +/** TCP: when data passed to netconn_write doesn't fit into the send buffer, + this temporarily stores whether to wake up the original application task + if data couldn't be sent in the first try. */ +#define NETCONN_FLAG_WRITE_DELAYED 0x01 +/** Should this netconn avoid blocking? */ +#define NETCONN_FLAG_NON_BLOCKING 0x02 +/** Was the last connect action a non-blocking one? */ +#define NETCONN_FLAG_IN_NONBLOCKING_CONNECT 0x04 +/** If this is set, a TCP netconn must call netconn_recved() to update + the TCP receive window (done automatically if not set). */ +#define NETCONN_FLAG_NO_AUTO_RECVED 0x08 +/** If a nonblocking write has been rejected before, poll_tcp needs to + check if the netconn is writable again */ +#define NETCONN_FLAG_CHECK_WRITESPACE 0x10 + + +/* Helpers to process several netconn_types by the same code */ +#define NETCONNTYPE_GROUP(t) (t&0xF0) +#define NETCONNTYPE_DATAGRAM(t) (t&0xE0) + +/** Protocol family and type of the netconn */ +enum netconn_type { + NETCONN_INVALID = 0, + /* NETCONN_TCP Group */ + NETCONN_TCP = 0x10, + /* NETCONN_UDP Group */ + NETCONN_UDP = 0x20, + NETCONN_UDPLITE = 0x21, + NETCONN_UDPNOCHKSUM= 0x22, + /* NETCONN_RAW Group */ + NETCONN_RAW = 0x40 +}; + +/** Current state of the netconn. Non-TCP netconns are always + * in state NETCONN_NONE! */ +enum netconn_state { + NETCONN_NONE, + NETCONN_WRITE, + NETCONN_LISTEN, + NETCONN_CONNECT, + NETCONN_CLOSE +}; + +/** Use to inform the callback function about changes */ +enum netconn_evt { + NETCONN_EVT_RCVPLUS, + NETCONN_EVT_RCVMINUS, + NETCONN_EVT_SENDPLUS, + NETCONN_EVT_SENDMINUS, + NETCONN_EVT_ERROR +}; + +#if LWIP_IGMP +/** Used for netconn_join_leave_group() */ +enum netconn_igmp { + NETCONN_JOIN, + NETCONN_LEAVE +}; +#endif /* LWIP_IGMP */ + +/* forward-declare some structs to avoid to include their headers */ +struct ip_pcb; +struct tcp_pcb; +struct udp_pcb; +struct raw_pcb; +struct netconn; +struct api_msg_msg; + +/** A callback prototype to inform about events for a netconn */ +typedef void (* netconn_callback)(struct netconn *, enum netconn_evt, u16_t len); + +/** A netconn descriptor */ +struct netconn { + /** type of the netconn (TCP, UDP or RAW) */ + enum netconn_type type; + /** current state of the netconn */ + enum netconn_state state; + /** the lwIP internal protocol control block */ + union { + struct ip_pcb *ip; + struct tcp_pcb *tcp; + struct udp_pcb *udp; + struct raw_pcb *raw; + } pcb; + /** the last error this netconn had */ + err_t last_err; + /** sem that is used to synchroneously execute functions in the core context */ + sys_sem_t op_completed; + /** mbox where received packets are stored until they are fetched + by the netconn application thread (can grow quite big) */ + sys_mbox_t recvmbox; +#if LWIP_TCP + /** mbox where new connections are stored until processed + by the application thread */ + sys_mbox_t acceptmbox; +#endif /* LWIP_TCP */ + /** only used for socket layer */ +#if LWIP_SOCKET + int socket; +#endif /* LWIP_SOCKET */ +#if LWIP_SO_SNDTIMEO + /** timeout to wait for sending data (which means enqueueing data for sending + in internal buffers) */ + s32_t send_timeout; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVTIMEO + /** timeout to wait for new data to be received + (or connections to arrive for listening netconns) */ + int recv_timeout; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + /** maximum amount of bytes queued in recvmbox + not used for TCP: adjust TCP_WND instead! */ + int recv_bufsize; + /** number of bytes currently in recvmbox to be received, + tested against recv_bufsize to limit bytes on recvmbox + for UDP and RAW, used for FIONREAD */ + s16_t recv_avail; +#endif /* LWIP_SO_RCVBUF */ + /** flags holding more netconn-internal state, see NETCONN_FLAG_* defines */ + u8_t flags; +#if LWIP_TCP + /** TCP: when data passed to netconn_write doesn't fit into the send buffer, + this temporarily stores how much is already sent. */ + size_t write_offset; + /** TCP: when data passed to netconn_write doesn't fit into the send buffer, + this temporarily stores the message. + Also used during connect and close. */ + struct api_msg_msg *current_msg; +#endif /* LWIP_TCP */ + /** A callback function that is informed about events for this netconn */ + netconn_callback callback; +}; + +/** Register an Network connection event */ +#define API_EVENT(c,e,l) if (c->callback) { \ + (*c->callback)(c, e, l); \ + } + +/** Set conn->last_err to err but don't overwrite fatal errors */ +#define NETCONN_SET_SAFE_ERR(conn, err) do { \ + SYS_ARCH_DECL_PROTECT(lev); \ + SYS_ARCH_PROTECT(lev); \ + if (!ERR_IS_FATAL((conn)->last_err)) { \ + (conn)->last_err = err; \ + } \ + SYS_ARCH_UNPROTECT(lev); \ +} while(0); + + +/* Network connection functions: */ +#define netconn_new(t) netconn_new_with_proto_and_callback(t, 0, NULL) +#define netconn_new_with_callback(t, c) netconn_new_with_proto_and_callback(t, 0, c) +struct +netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, + netconn_callback callback); +err_t netconn_delete(struct netconn *conn); +/** Get the type of a netconn (as enum netconn_type). */ +#define netconn_type(conn) (conn->type) + +err_t netconn_getaddr(struct netconn *conn, ip_addr_t *addr, + u16_t *port, u8_t local); +#define netconn_peer(c,i,p) netconn_getaddr(c,i,p,0) +#define netconn_addr(c,i,p) netconn_getaddr(c,i,p,1) + +err_t netconn_bind(struct netconn *conn, ip_addr_t *addr, u16_t port); +err_t netconn_connect(struct netconn *conn, ip_addr_t *addr, u16_t port); +err_t netconn_disconnect (struct netconn *conn); +err_t netconn_listen_with_backlog(struct netconn *conn, u8_t backlog); +#define netconn_listen(conn) netconn_listen_with_backlog(conn, TCP_DEFAULT_LISTEN_BACKLOG) +err_t netconn_accept(struct netconn *conn, struct netconn **new_conn); +err_t netconn_recv(struct netconn *conn, struct netbuf **new_buf); +err_t netconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf); +void netconn_recved(struct netconn *conn, u32_t length); +err_t netconn_sendto(struct netconn *conn, struct netbuf *buf, + ip_addr_t *addr, u16_t port); +err_t netconn_send(struct netconn *conn, struct netbuf *buf); +err_t netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size, + u8_t apiflags, size_t *bytes_written); +#define netconn_write(conn, dataptr, size, apiflags) \ + netconn_write_partly(conn, dataptr, size, apiflags, NULL) +err_t netconn_close(struct netconn *conn); +err_t netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx); + +err_t netconn_abort(struct netconn *conn);//Realtek add + +#if LWIP_IGMP +err_t netconn_join_leave_group(struct netconn *conn, ip_addr_t *multiaddr, + ip_addr_t *netif_addr, enum netconn_igmp join_or_leave); +#endif /* LWIP_IGMP */ +#if LWIP_DNS +err_t netconn_gethostbyname(const char *name, ip_addr_t *addr); +#endif /* LWIP_DNS */ + +#define netconn_err(conn) ((conn)->last_err) +#define netconn_recv_bufsize(conn) ((conn)->recv_bufsize) + +/** Set the blocking status of netconn calls (@todo: write/send is missing) */ +#define netconn_set_nonblocking(conn, val) do { if(val) { \ + (conn)->flags |= NETCONN_FLAG_NON_BLOCKING; \ +} else { \ + (conn)->flags &= ~ NETCONN_FLAG_NON_BLOCKING; }} while(0) +/** Get the blocking status of netconn calls (@todo: write/send is missing) */ +#define netconn_is_nonblocking(conn) (((conn)->flags & NETCONN_FLAG_NON_BLOCKING) != 0) + +/** TCP: Set the no-auto-recved status of netconn calls (see NETCONN_FLAG_NO_AUTO_RECVED) */ +#define netconn_set_noautorecved(conn, val) do { if(val) { \ + (conn)->flags |= NETCONN_FLAG_NO_AUTO_RECVED; \ +} else { \ + (conn)->flags &= ~ NETCONN_FLAG_NO_AUTO_RECVED; }} while(0) +/** TCP: Get the no-auto-recved status of netconn calls (see NETCONN_FLAG_NO_AUTO_RECVED) */ +#define netconn_get_noautorecved(conn) (((conn)->flags & NETCONN_FLAG_NO_AUTO_RECVED) != 0) + +#if LWIP_SO_SNDTIMEO +/** Set the send timeout in milliseconds */ +#define netconn_set_sendtimeout(conn, timeout) ((conn)->send_timeout = (timeout)) +/** Get the send timeout in milliseconds */ +#define netconn_get_sendtimeout(conn) ((conn)->send_timeout) +#endif /* LWIP_SO_SNDTIMEO */ +#if LWIP_SO_RCVTIMEO +/** Set the receive timeout in milliseconds */ +#define netconn_set_recvtimeout(conn, timeout) ((conn)->recv_timeout = (timeout)) +/** Get the receive timeout in milliseconds */ +#define netconn_get_recvtimeout(conn) ((conn)->recv_timeout) +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF +/** Set the receive buffer in bytes */ +#define netconn_set_recvbufsize(conn, recvbufsize) ((conn)->recv_bufsize = (recvbufsize)) +/** Get the receive buffer in bytes */ +#define netconn_get_recvbufsize(conn) ((conn)->recv_bufsize) +#endif /* LWIP_SO_RCVBUF*/ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_NETCONN */ + +#endif /* __LWIP_API_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/api_msg.h b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/api_msg.h new file mode 100644 index 0000000..f9e1c7d --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/api_msg.h @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_API_MSG_H__ +#define __LWIP_API_MSG_H__ + +#include "lwip/opt.h" + +#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ + +#include /* for size_t */ + +#include "lwip/ip_addr.h" +#include "lwip/err.h" +#include "lwip/sys.h" +#include "lwip/igmp.h" +#include "lwip/api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* For the netconn API, these values are use as a bitmask! */ +#define NETCONN_SHUT_RD 1 +#define NETCONN_SHUT_WR 2 +#define NETCONN_SHUT_RDWR (NETCONN_SHUT_RD | NETCONN_SHUT_WR) + +/* IP addresses and port numbers are expected to be in + * the same byte order as in the corresponding pcb. + */ +/** This struct includes everything that is necessary to execute a function + for a netconn in another thread context (mainly used to process netconns + in the tcpip_thread context to be thread safe). */ +struct api_msg_msg { + /** The netconn which to process - always needed: it includes the semaphore + which is used to block the application thread until the function finished. */ + struct netconn *conn; + /** The return value of the function executed in tcpip_thread. */ + err_t err; + /** Depending on the executed function, one of these union members is used */ + union { + /** used for do_send */ + struct netbuf *b; + /** used for do_newconn */ + struct { + u8_t proto; + } n; + /** used for do_bind and do_connect */ + struct { + ip_addr_t *ipaddr; + u16_t port; + } bc; + /** used for do_getaddr */ + struct { + ip_addr_t *ipaddr; + u16_t *port; + u8_t local; + } ad; + /** used for do_write */ + struct { + const void *dataptr; + size_t len; + u8_t apiflags; +#if LWIP_SO_SNDTIMEO + u32_t time_started; +#endif /* LWIP_SO_SNDTIMEO */ + } w; + /** used for do_recv */ + struct { + u32_t len; + } r; + /** used for do_close (/shutdown) */ + struct { + u8_t shut; + } sd; +#if LWIP_IGMP + /** used for do_join_leave_group */ + struct { + ip_addr_t *multiaddr; + ip_addr_t *netif_addr; + enum netconn_igmp join_or_leave; + } jl; +#endif /* LWIP_IGMP */ +#if TCP_LISTEN_BACKLOG + struct { + u8_t backlog; + } lb; +#endif /* TCP_LISTEN_BACKLOG */ + } msg; +}; + +/** This struct contains a function to execute in another thread context and + a struct api_msg_msg that serves as an argument for this function. + This is passed to tcpip_apimsg to execute functions in tcpip_thread context. */ +struct api_msg { + /** function to execute in tcpip_thread context */ + void (* function)(struct api_msg_msg *msg); + /** arguments for this function */ + struct api_msg_msg msg; +}; + +#if LWIP_DNS +/** As do_gethostbyname requires more arguments but doesn't require a netconn, + it has its own struct (to avoid struct api_msg getting bigger than necessary). + do_gethostbyname must be called using tcpip_callback instead of tcpip_apimsg + (see netconn_gethostbyname). */ +struct dns_api_msg { + /** Hostname to query or dotted IP address string */ + const char *name; + /** Rhe resolved address is stored here */ + ip_addr_t *addr; + /** This semaphore is posted when the name is resolved, the application thread + should wait on it. */ + sys_sem_t *sem; + /** Errors are given back here */ + err_t *err; +}; +#endif /* LWIP_DNS */ + +void do_newconn ( struct api_msg_msg *msg); +void do_delconn ( struct api_msg_msg *msg); +void do_bind ( struct api_msg_msg *msg); +void do_connect ( struct api_msg_msg *msg); +void do_disconnect ( struct api_msg_msg *msg); +void do_listen ( struct api_msg_msg *msg); +void do_send ( struct api_msg_msg *msg); +void do_recv ( struct api_msg_msg *msg); +void do_write ( struct api_msg_msg *msg); +void do_getaddr ( struct api_msg_msg *msg); +void do_close ( struct api_msg_msg *msg); +void do_shutdown ( struct api_msg_msg *msg); +#if LWIP_IGMP +void do_join_leave_group( struct api_msg_msg *msg); +#endif /* LWIP_IGMP */ + +#if LWIP_DNS +void do_gethostbyname(void *arg); +#endif /* LWIP_DNS */ + +struct netconn* netconn_alloc(enum netconn_type t, netconn_callback callback); +void netconn_free(struct netconn *conn); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_NETCONN */ + +#endif /* __LWIP_API_MSG_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/arch.h b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/arch.h new file mode 100644 index 0000000..4d6df77 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/arch.h @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_ARCH_H__ +#define __LWIP_ARCH_H__ + +#ifndef LITTLE_ENDIAN +#define LITTLE_ENDIAN 1234 +#endif + +#ifndef BIG_ENDIAN +#define BIG_ENDIAN 4321 +#endif + +#include "arch/cc.h" + +/** Temporary: define format string for size_t if not defined in cc.h */ +#ifndef SZT_F +#define SZT_F U32_F +#endif /* SZT_F */ +/** Temporary upgrade helper: define format string for u8_t as hex if not + defined in cc.h */ +#ifndef X8_F +#define X8_F "02x" +#endif /* X8_F */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef PACK_STRUCT_BEGIN +#define PACK_STRUCT_BEGIN +#endif /* PACK_STRUCT_BEGIN */ + +#ifndef PACK_STRUCT_END +#define PACK_STRUCT_END +#endif /* PACK_STRUCT_END */ + +#ifndef PACK_STRUCT_FIELD +#define PACK_STRUCT_FIELD(x) x +#endif /* PACK_STRUCT_FIELD */ + + +#ifndef LWIP_UNUSED_ARG +#define LWIP_UNUSED_ARG(x) (void)x +#endif /* LWIP_UNUSED_ARG */ + + +#ifdef LWIP_PROVIDE_ERRNO + +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#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 child processes */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device or resource 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 ETXTBSY 26 /* Text file busy */ +#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 EDOM 33 /* Math argument out of domain of func */ +#define ERANGE 34 /* Math result not representable */ +#define EDEADLK 35 /* Resource deadlock would occur */ +#define ENAMETOOLONG 36 /* File name too long */ +#define ENOLCK 37 /* No record locks available */ +#define ENOSYS 38 /* Function not implemented */ +#define ENOTEMPTY 39 /* Directory not empty */ +#define ELOOP 40 /* Too many symbolic links encountered */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define ENOMSG 42 /* No message of desired type */ +#define EIDRM 43 /* Identifier removed */ +#define ECHRNG 44 /* Channel number out of range */ +#define EL2NSYNC 45 /* Level 2 not synchronized */ +#define EL3HLT 46 /* Level 3 halted */ +#define EL3RST 47 /* Level 3 reset */ +#define ELNRNG 48 /* Link number out of range */ +#define EUNATCH 49 /* Protocol driver not attached */ +#define ENOCSI 50 /* No CSI structure available */ +#define EL2HLT 51 /* Level 2 halted */ +#define EBADE 52 /* Invalid exchange */ +#define EBADR 53 /* Invalid request descriptor */ +#define EXFULL 54 /* Exchange full */ +#define ENOANO 55 /* No anode */ +#define EBADRQC 56 /* Invalid request code */ +#define EBADSLT 57 /* Invalid slot */ + +#define EDEADLOCK EDEADLK + +#define EBFONT 59 /* Bad font file format */ +#define ENOSTR 60 /* Device not a stream */ +#define ENODATA 61 /* No data available */ +#define ETIME 62 /* Timer expired */ +#define ENOSR 63 /* Out of streams resources */ +#define ENONET 64 /* Machine is not on the network */ +#define ENOPKG 65 /* Package not installed */ +#define EREMOTE 66 /* Object is remote */ +#define ENOLINK 67 /* Link has been severed */ +#define EADV 68 /* Advertise error */ +#define ESRMNT 69 /* Srmount error */ +#define ECOMM 70 /* Communication error on send */ +#define EPROTO 71 /* Protocol error */ +#define EMULTIHOP 72 /* Multihop attempted */ +#define EDOTDOT 73 /* RFS specific error */ +#define EBADMSG 74 /* Not a data message */ +#define EOVERFLOW 75 /* Value too large for defined data type */ +#define ENOTUNIQ 76 /* Name not unique on network */ +#define EBADFD 77 /* File descriptor in bad state */ +#define EREMCHG 78 /* Remote address changed */ +#define ELIBACC 79 /* Can not access a needed shared library */ +#define ELIBBAD 80 /* Accessing a corrupted shared library */ +#define ELIBSCN 81 /* .lib section in a.out corrupted */ +#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ +#define ELIBEXEC 83 /* Cannot exec a shared library directly */ +#define EILSEQ 84 /* Illegal byte sequence */ +#define ERESTART 85 /* Interrupted system call should be restarted */ +#define ESTRPIPE 86 /* Streams pipe error */ +#define EUSERS 87 /* Too many users */ +#define ENOTSOCK 88 /* Socket operation on non-socket */ +#define EDESTADDRREQ 89 /* Destination address required */ +#define EMSGSIZE 90 /* Message too long */ +#define EPROTOTYPE 91 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 92 /* Protocol not available */ +#define EPROTONOSUPPORT 93 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ +#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ +#define EADDRINUSE 98 /* Address already in use */ +#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ +#define ENETDOWN 100 /* Network is down */ +#define ENETUNREACH 101 /* Network is unreachable */ +#define ENETRESET 102 /* Network dropped connection because of reset */ +#define ECONNABORTED 103 /* Software caused connection abort */ +#define ECONNRESET 104 /* Connection reset by peer */ +#define ENOBUFS 105 /* No buffer space available */ +#define EISCONN 106 /* Transport endpoint is already connected */ +#define ENOTCONN 107 /* Transport endpoint is not connected */ +#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ +#define ETOOMANYREFS 109 /* Too many references: cannot splice */ +#define ETIMEDOUT 110 /* Connection timed out */ +#define ECONNREFUSED 111 /* Connection refused */ +#define EHOSTDOWN 112 /* Host is down */ +#define EHOSTUNREACH 113 /* No route to host */ +#define EALREADY 114 /* Operation already in progress */ +#define EINPROGRESS 115 /* Operation now in progress */ +#define ESTALE 116 /* Stale NFS file handle */ +#define EUCLEAN 117 /* Structure needs cleaning */ +#define ENOTNAM 118 /* Not a XENIX named type file */ +#define ENAVAIL 119 /* No XENIX semaphores available */ +#define EISNAM 120 /* Is a named type file */ +#define EREMOTEIO 121 /* Remote I/O error */ +#define EDQUOT 122 /* Quota exceeded */ + +#define ENOMEDIUM 123 /* No medium found */ +#define EMEDIUMTYPE 124 /* Wrong medium type */ + +#ifndef errno +extern int errno; +#endif + +#endif /* LWIP_PROVIDE_ERRNO */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_ARCH_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/debug.h b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/debug.h new file mode 100644 index 0000000..5a0e042 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/debug.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_DEBUG_H__ +#define __LWIP_DEBUG_H__ + +#include "lwip/arch.h" +#include "lwip/opt.h" +#include //Realtek add +/** lower two bits indicate debug level + * - 0 all + * - 1 warning + * - 2 serious + * - 3 severe + */ +#define LWIP_DBG_LEVEL_ALL 0x00 +#define LWIP_DBG_LEVEL_OFF LWIP_DBG_LEVEL_ALL /* compatibility define only */ +#define LWIP_DBG_LEVEL_WARNING 0x01 /* bad checksums, dropped packets, ... */ +#define LWIP_DBG_LEVEL_SERIOUS 0x02 /* memory allocation failures, ... */ +#define LWIP_DBG_LEVEL_SEVERE 0x03 +#define LWIP_DBG_MASK_LEVEL 0x03 + +/** flag for LWIP_DEBUGF to enable that debug message */ +#define LWIP_DBG_ON 0x80U +/** flag for LWIP_DEBUGF to disable that debug message */ +#define LWIP_DBG_OFF 0x00U + +/** flag for LWIP_DEBUGF indicating a tracing message (to follow program flow) */ +#define LWIP_DBG_TRACE 0x40U +/** flag for LWIP_DEBUGF indicating a state debug message (to follow module states) */ +#define LWIP_DBG_STATE 0x20U +/** flag for LWIP_DEBUGF indicating newly added code, not thoroughly tested yet */ +#define LWIP_DBG_FRESH 0x10U +/** flag for LWIP_DEBUGF to halt after printing this debug message */ +#define LWIP_DBG_HALT 0x08U + +#ifndef LWIP_NOASSERT +#define LWIP_ASSERT(message, assertion) do { if(!(assertion)) \ + LWIP_PLATFORM_ASSERT(message); } while(0) +#else /* LWIP_NOASSERT */ +#define LWIP_ASSERT(message, assertion) +#endif /* LWIP_NOASSERT */ + +/** if "expression" isn't true, then print "message" and execute "handler" expression */ +#ifndef LWIP_ERROR +#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \ + LWIP_PLATFORM_ASSERT(message); handler;}} while(0) +#endif /* LWIP_ERROR */ + +#ifdef LWIP_DEBUG +/** print debug message only if debug message type is enabled... + * AND is of correct type AND is at least LWIP_DBG_LEVEL + */ + + +#define LWIP_PLATFORM_DIAG printf //Realtek add +#define LWIP_DEBUGF(debug, message) do { \ + if ( \ + ((debug) & LWIP_DBG_ON) && \ + ((debug) & LWIP_DBG_TYPES_ON) && \ + ((s16_t)((debug) & LWIP_DBG_MASK_LEVEL) >= LWIP_DBG_MIN_LEVEL)) { \ + LWIP_PLATFORM_DIAG message; \ + if ((debug) & LWIP_DBG_HALT) { \ + while(1); \ + } \ + } \ + } while(0) + +#else /* LWIP_DEBUG */ +#define LWIP_DEBUGF(debug, message) +#endif /* LWIP_DEBUG */ + +#endif /* __LWIP_DEBUG_H__ */ + diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/def.h b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/def.h new file mode 100644 index 0000000..73a1b56 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/def.h @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_DEF_H__ +#define __LWIP_DEF_H__ + +/* arch.h might define NULL already */ +#include "lwip/arch.h" +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define LWIP_MAX(x , y) (((x) > (y)) ? (x) : (y)) +#define LWIP_MIN(x , y) (((x) < (y)) ? (x) : (y)) + +#ifndef NULL +#define NULL ((void *)0) +#endif + +/* Endianess-optimized shifting of two u8_t to create one u16_t */ +#if BYTE_ORDER == LITTLE_ENDIAN +#define LWIP_MAKE_U16(a, b) ((a << 8) | b) +#else +#define LWIP_MAKE_U16(a, b) ((b << 8) | a) +#endif + +#ifndef LWIP_PLATFORM_BYTESWAP +#define LWIP_PLATFORM_BYTESWAP 0 +#endif + +#ifndef LWIP_PREFIX_BYTEORDER_FUNCS +/* workaround for naming collisions on some platforms */ + +#ifdef htons +#undef htons +#endif /* htons */ +#ifdef htonl +#undef htonl +#endif /* htonl */ +#ifdef ntohs +#undef ntohs +#endif /* ntohs */ +#ifdef ntohl +#undef ntohl +#endif /* ntohl */ + +#define htons(x) lwip_htons(x) +#define ntohs(x) lwip_ntohs(x) +#define htonl(x) lwip_htonl(x) +#define ntohl(x) lwip_ntohl(x) +#endif /* LWIP_PREFIX_BYTEORDER_FUNCS */ + +#if BYTE_ORDER == BIG_ENDIAN +#define lwip_htons(x) (x) +#define lwip_ntohs(x) (x) +#define lwip_htonl(x) (x) +#define lwip_ntohl(x) (x) +#define PP_HTONS(x) (x) +#define PP_NTOHS(x) (x) +#define PP_HTONL(x) (x) +#define PP_NTOHL(x) (x) +#else /* BYTE_ORDER != BIG_ENDIAN */ +#if LWIP_PLATFORM_BYTESWAP +#define lwip_htons(x) LWIP_PLATFORM_HTONS(x) +#define lwip_ntohs(x) LWIP_PLATFORM_HTONS(x) +#define lwip_htonl(x) LWIP_PLATFORM_HTONL(x) +#define lwip_ntohl(x) LWIP_PLATFORM_HTONL(x) +#else /* LWIP_PLATFORM_BYTESWAP */ +u16_t lwip_htons(u16_t x); +u16_t lwip_ntohs(u16_t x); +u32_t lwip_htonl(u32_t x); +u32_t lwip_ntohl(u32_t x); +#endif /* LWIP_PLATFORM_BYTESWAP */ + +/* These macros should be calculated by the preprocessor and are used + with compile-time constants only (so that there is no little-endian + overhead at runtime). */ +#define PP_HTONS(x) ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8)) +#define PP_NTOHS(x) PP_HTONS(x) +#define PP_HTONL(x) ((((x) & 0xff) << 24) | \ + (((x) & 0xff00) << 8) | \ + (((x) & 0xff0000UL) >> 8) | \ + (((x) & 0xff000000UL) >> 24)) +#define PP_NTOHL(x) PP_HTONL(x) + +#endif /* BYTE_ORDER == BIG_ENDIAN */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_DEF_H__ */ + diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/dhcp.h b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/dhcp.h new file mode 100644 index 0000000..296f520 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/dhcp.h @@ -0,0 +1,243 @@ +/** @file + */ + +#ifndef __LWIP_DHCP_H__ +#define __LWIP_DHCP_H__ + +#include "lwip/opt.h" + +#if LWIP_DHCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/netif.h" +#include "lwip/udp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** period (in seconds) of the application calling dhcp_coarse_tmr() */ +#define DHCP_COARSE_TIMER_SECS 60 +/** period (in milliseconds) of the application calling dhcp_coarse_tmr() */ +#define DHCP_COARSE_TIMER_MSECS (DHCP_COARSE_TIMER_SECS * 1000UL) +/** period (in milliseconds) of the application calling dhcp_fine_tmr() */ +#define DHCP_FINE_TIMER_MSECS 500 + +#define DHCP_CHADDR_LEN 16U +#define DHCP_SNAME_LEN 64U +#define DHCP_FILE_LEN 128U + +struct dhcp +{ + /** transaction identifier of last sent request */ + u32_t xid; + /** our connection to the DHCP server */ + struct udp_pcb *pcb; + /** incoming msg */ + struct dhcp_msg *msg_in; + /** current DHCP state machine state */ + u8_t state; + /** retries of current request */ + u8_t tries; +#if LWIP_DHCP_AUTOIP_COOP + u8_t autoip_coop_state; +#endif + u8_t subnet_mask_given; + + struct pbuf *p_out; /* pbuf of outcoming msg */ + struct dhcp_msg *msg_out; /* outgoing msg */ + u16_t options_out_len; /* outgoing msg options length */ + u16_t request_timeout; /* #ticks with period DHCP_FINE_TIMER_SECS for request timeout */ + u16_t t1_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for renewal time */ + u16_t t2_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for rebind time */ + ip_addr_t server_ip_addr; /* dhcp server address that offered this lease */ + ip_addr_t offered_ip_addr; + ip_addr_t offered_sn_mask; + ip_addr_t offered_gw_addr; + ip_addr_t offered_bc_addr;//Evan add for used old version lwip api in lwip_netconf.c + + u32_t offered_t0_lease; /* lease period (in seconds) */ + u32_t offered_t1_renew; /* recommended renew time (usually 50% of lease period) */ + u32_t offered_t2_rebind; /* recommended rebind time (usually 66% of lease period) */ + /* @todo: LWIP_DHCP_BOOTP_FILE configuration option? + integrate with possible TFTP-client for booting? */ +#if LWIP_DHCP_BOOTP_FILE + ip_addr_t offered_si_addr; + char boot_file_name[DHCP_FILE_LEN]; +#endif /* LWIP_DHCP_BOOTPFILE */ +}; + +/* MUST be compiled with "pack structs" or equivalent! */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** minimum set of fields of any DHCP message */ +struct dhcp_msg +{ + PACK_STRUCT_FIELD(u8_t op); + PACK_STRUCT_FIELD(u8_t htype); + PACK_STRUCT_FIELD(u8_t hlen); + PACK_STRUCT_FIELD(u8_t hops); + PACK_STRUCT_FIELD(u32_t xid); + PACK_STRUCT_FIELD(u16_t secs); + PACK_STRUCT_FIELD(u16_t flags); + PACK_STRUCT_FIELD(ip_addr_p_t ciaddr); + PACK_STRUCT_FIELD(ip_addr_p_t yiaddr); + PACK_STRUCT_FIELD(ip_addr_p_t siaddr); + PACK_STRUCT_FIELD(ip_addr_p_t giaddr); + PACK_STRUCT_FIELD(u8_t chaddr[DHCP_CHADDR_LEN]); + PACK_STRUCT_FIELD(u8_t sname[DHCP_SNAME_LEN]); + PACK_STRUCT_FIELD(u8_t file[DHCP_FILE_LEN]); + PACK_STRUCT_FIELD(u32_t cookie); +#define DHCP_MIN_OPTIONS_LEN 68U +/** make sure user does not configure this too small */ +#if ((defined(DHCP_OPTIONS_LEN)) && (DHCP_OPTIONS_LEN < DHCP_MIN_OPTIONS_LEN)) +# undef DHCP_OPTIONS_LEN +#endif +/** allow this to be configured in lwipopts.h, but not too small */ +#if (!defined(DHCP_OPTIONS_LEN)) +/** set this to be sufficient for your options in outgoing DHCP msgs */ +# define DHCP_OPTIONS_LEN DHCP_MIN_OPTIONS_LEN +#endif + PACK_STRUCT_FIELD(u8_t options[DHCP_OPTIONS_LEN]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +void dhcp_set_struct(struct netif *netif, struct dhcp *dhcp); +/** Remove a struct dhcp previously set to the netif using dhcp_set_struct() */ +#define dhcp_remove_struct(netif) do { (netif)->dhcp = NULL; } while(0) +void dhcp_cleanup(struct netif *netif); +/** start DHCP configuration */ +err_t dhcp_start(struct netif *netif); +/** enforce early lease renewal (not needed normally)*/ +err_t dhcp_renew(struct netif *netif); +/** release the DHCP lease, usually called before dhcp_stop()*/ +err_t dhcp_release(struct netif *netif); +/** stop DHCP configuration */ +void dhcp_stop(struct netif *netif); +/** inform server of our manual IP address */ +void dhcp_inform(struct netif *netif); +/** Handle a possible change in the network configuration */ +void dhcp_network_changed(struct netif *netif); + +/** if enabled, check whether the offered IP address is not in use, using ARP */ +#if DHCP_DOES_ARP_CHECK +void dhcp_arp_reply(struct netif *netif, ip_addr_t *addr); +#endif + +/** to be called every minute */ +void dhcp_coarse_tmr(void); +/** to be called every half second */ +void dhcp_fine_tmr(void); + +/** DHCP message item offsets and length */ +#define DHCP_OP_OFS 0 +#define DHCP_HTYPE_OFS 1 +#define DHCP_HLEN_OFS 2 +#define DHCP_HOPS_OFS 3 +#define DHCP_XID_OFS 4 +#define DHCP_SECS_OFS 8 +#define DHCP_FLAGS_OFS 10 +#define DHCP_CIADDR_OFS 12 +#define DHCP_YIADDR_OFS 16 +#define DHCP_SIADDR_OFS 20 +#define DHCP_GIADDR_OFS 24 +#define DHCP_CHADDR_OFS 28 +#define DHCP_SNAME_OFS 44 +#define DHCP_FILE_OFS 108 +#define DHCP_MSG_LEN 236 + +#define DHCP_COOKIE_OFS DHCP_MSG_LEN +#define DHCP_OPTIONS_OFS (DHCP_MSG_LEN + 4) + +#define DHCP_CLIENT_PORT 68 +#define DHCP_SERVER_PORT 67 + +/** DHCP client states */ +#define DHCP_OFF 0 +#define DHCP_REQUESTING 1 +#define DHCP_INIT 2 +#define DHCP_REBOOTING 3 +#define DHCP_REBINDING 4 +#define DHCP_RENEWING 5 +#define DHCP_SELECTING 6 +#define DHCP_INFORMING 7 +#define DHCP_CHECKING 8 +#define DHCP_PERMANENT 9 +#define DHCP_BOUND 10 +#define DHCP_RELEASING 11 //Realtek modified +#define DHCP_BACKING_OFF 12 + +/** AUTOIP cooperatation flags */ +#define DHCP_AUTOIP_COOP_STATE_OFF 0 +#define DHCP_AUTOIP_COOP_STATE_ON 1 + +#define DHCP_BOOTREQUEST 1 +#define DHCP_BOOTREPLY 2 + +/** DHCP message types */ +#define DHCP_DISCOVER 1 +#define DHCP_OFFER 2 +#define DHCP_REQUEST 3 +#define DHCP_DECLINE 4 +#define DHCP_ACK 5 +#define DHCP_NAK 6 +#define DHCP_RELEASE 7 +#define DHCP_INFORM 8 + +/** DHCP hardware type, currently only ethernet is supported */ +#define DHCP_HTYPE_ETH 1 + +#define DHCP_MAGIC_COOKIE 0x63825363UL + +/* This is a list of options for BOOTP and DHCP, see RFC 2132 for descriptions */ + +/** BootP options */ +#define DHCP_OPTION_PAD 0 +#define DHCP_OPTION_SUBNET_MASK 1 /* RFC 2132 3.3 */ +#define DHCP_OPTION_ROUTER 3 +#define DHCP_OPTION_DNS_SERVER 6 +#define DHCP_OPTION_HOSTNAME 12 +#define DHCP_OPTION_IP_TTL 23 +#define DHCP_OPTION_MTU 26 +#define DHCP_OPTION_BROADCAST 28 +#define DHCP_OPTION_TCP_TTL 37 +#define DHCP_OPTION_END 255 + +/** DHCP options */ +#define DHCP_OPTION_REQUESTED_IP 50 /* RFC 2132 9.1, requested IP address */ +#define DHCP_OPTION_LEASE_TIME 51 /* RFC 2132 9.2, time in seconds, in 4 bytes */ +#define DHCP_OPTION_OVERLOAD 52 /* RFC2132 9.3, use file and/or sname field for options */ + +#define DHCP_OPTION_MESSAGE_TYPE 53 /* RFC 2132 9.6, important for DHCP */ +#define DHCP_OPTION_MESSAGE_TYPE_LEN 1 + +#define DHCP_OPTION_SERVER_ID 54 /* RFC 2132 9.7, server IP address */ +#define DHCP_OPTION_PARAMETER_REQUEST_LIST 55 /* RFC 2132 9.8, requested option types */ + +#define DHCP_OPTION_MAX_MSG_SIZE 57 /* RFC 2132 9.10, message size accepted >= 576 */ +#define DHCP_OPTION_MAX_MSG_SIZE_LEN 2 + +#define DHCP_OPTION_T1 58 /* T1 renewal time */ +#define DHCP_OPTION_T2 59 /* T2 rebinding time */ +#define DHCP_OPTION_US 60 +#define DHCP_OPTION_CLIENT_ID 61 +#define DHCP_OPTION_TFTP_SERVERNAME 66 +#define DHCP_OPTION_BOOTFILE 67 + +/** possible combinations of overloading the file and sname fields with options */ +#define DHCP_OVERLOAD_NONE 0 +#define DHCP_OVERLOAD_FILE 1 +#define DHCP_OVERLOAD_SNAME 2 +#define DHCP_OVERLOAD_SNAME_FILE 3 + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_DHCP */ + +#endif /*__LWIP_DHCP_H__*/ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/dns.h b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/dns.h new file mode 100644 index 0000000..6c7d9b0 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/dns.h @@ -0,0 +1,124 @@ +/** + * lwip DNS resolver header file. + + * Author: Jim Pettinato + * April 2007 + + * ported from uIP resolv.c Copyright (c) 2002-2003, Adam Dunkels. + * + * 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. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 __LWIP_DNS_H__ +#define __LWIP_DNS_H__ + +#include "lwip/opt.h" + +#if LWIP_DNS /* don't build if not configured for use in lwipopts.h */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** DNS timer period */ +#define DNS_TMR_INTERVAL 1000 + +/** DNS field TYPE used for "Resource Records" */ +#define DNS_RRTYPE_A 1 /* a host address */ +#define DNS_RRTYPE_NS 2 /* an authoritative name server */ +#define DNS_RRTYPE_MD 3 /* a mail destination (Obsolete - use MX) */ +#define DNS_RRTYPE_MF 4 /* a mail forwarder (Obsolete - use MX) */ +#define DNS_RRTYPE_CNAME 5 /* the canonical name for an alias */ +#define DNS_RRTYPE_SOA 6 /* marks the start of a zone of authority */ +#define DNS_RRTYPE_MB 7 /* a mailbox domain name (EXPERIMENTAL) */ +#define DNS_RRTYPE_MG 8 /* a mail group member (EXPERIMENTAL) */ +#define DNS_RRTYPE_MR 9 /* a mail rename domain name (EXPERIMENTAL) */ +#define DNS_RRTYPE_NULL 10 /* a null RR (EXPERIMENTAL) */ +#define DNS_RRTYPE_WKS 11 /* a well known service description */ +#define DNS_RRTYPE_PTR 12 /* a domain name pointer */ +#define DNS_RRTYPE_HINFO 13 /* host information */ +#define DNS_RRTYPE_MINFO 14 /* mailbox or mail list information */ +#define DNS_RRTYPE_MX 15 /* mail exchange */ +#define DNS_RRTYPE_TXT 16 /* text strings */ + +/** DNS field CLASS used for "Resource Records" */ +#define DNS_RRCLASS_IN 1 /* the Internet */ +#define DNS_RRCLASS_CS 2 /* the CSNET class (Obsolete - used only for examples in some obsolete RFCs) */ +#define DNS_RRCLASS_CH 3 /* the CHAOS class */ +#define DNS_RRCLASS_HS 4 /* Hesiod [Dyer 87] */ +#define DNS_RRCLASS_FLUSH 0x800 /* Flush bit */ + +/* The size used for the next line is rather a hack, but it prevents including socket.h in all files + that include memp.h, and that would possibly break portability (since socket.h defines some types + and constants possibly already define by the OS). + Calculation rule: + sizeof(struct addrinfo) + sizeof(struct sockaddr_in) + DNS_MAX_NAME_LENGTH + 1 byte zero-termination */ +#define NETDB_ELEM_SIZE (32 + 16 + DNS_MAX_NAME_LENGTH + 1) + +#if DNS_LOCAL_HOSTLIST +/** struct used for local host-list */ +struct local_hostlist_entry { + /** static hostname */ + const char *name; + /** static host address in network byteorder */ + ip_addr_t addr; + struct local_hostlist_entry *next; +}; +#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC +#ifndef DNS_LOCAL_HOSTLIST_MAX_NAMELEN +#define DNS_LOCAL_HOSTLIST_MAX_NAMELEN DNS_MAX_NAME_LENGTH +#endif +#define LOCALHOSTLIST_ELEM_SIZE ((sizeof(struct local_hostlist_entry) + DNS_LOCAL_HOSTLIST_MAX_NAMELEN + 1)) +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ +#endif /* DNS_LOCAL_HOSTLIST */ + +/** Callback which is invoked when a hostname is found. + * A function of this type must be implemented by the application using the DNS resolver. + * @param name pointer to the name that was looked up. + * @param ipaddr pointer to an ip_addr_t containing the IP address of the hostname, + * or NULL if the name could not be found (or on any other error). + * @param callback_arg a user-specified callback argument passed to dns_gethostbyname +*/ +typedef void (*dns_found_callback)(const char *name, ip_addr_t *ipaddr, void *callback_arg); + +void dns_init(void); +void dns_tmr(void); +void dns_setserver(u8_t numdns, ip_addr_t *dnsserver); +ip_addr_t dns_getserver(u8_t numdns); +err_t dns_gethostbyname(const char *hostname, ip_addr_t *addr, + dns_found_callback found, void *callback_arg); + +#if DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC +int dns_local_removehost(const char *hostname, const ip_addr_t *addr); +err_t dns_local_addhost(const char *hostname, const ip_addr_t *addr); +#endif /* DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_DNS */ + +#endif /* __LWIP_DNS_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/err.h b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/err.h new file mode 100644 index 0000000..ac90772 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/err.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_ERR_H__ +#define __LWIP_ERR_H__ + +#include "lwip/opt.h" +#include "lwip/arch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Define LWIP_ERR_T in cc.h if you want to use + * a different type for your platform (must be signed). */ +#ifdef LWIP_ERR_T +typedef LWIP_ERR_T err_t; +#else /* LWIP_ERR_T */ +typedef s8_t err_t; +#endif /* LWIP_ERR_T*/ + +/* Definitions for error constants. */ + +#define ERR_OK 0 /* No error, everything OK. */ +#define ERR_MEM -1 /* Out of memory error. */ +#define ERR_BUF -2 /* Buffer error. */ +#define ERR_TIMEOUT -3 /* Timeout. */ +#define ERR_RTE -4 /* Routing problem. */ +#define ERR_INPROGRESS -5 /* Operation in progress */ +#define ERR_VAL -6 /* Illegal value. */ +#define ERR_WOULDBLOCK -7 /* Operation would block. */ +#define ERR_USE -8 /* Address in use. */ +#define ERR_ISCONN -9 /* Already connected. */ + +#define ERR_IS_FATAL(e) ((e) < ERR_ISCONN) + +#define ERR_ABRT -10 /* Connection aborted. */ +#define ERR_RST -11 /* Connection reset. */ +#define ERR_CLSD -12 /* Connection closed. */ +#define ERR_CONN -13 /* Not connected. */ + +#define ERR_ARG -14 /* Illegal argument. */ + +#define ERR_IF -15 /* Low-level netif error */ + + +#ifdef LWIP_DEBUG +extern const char *lwip_strerr(err_t err); +#else +#define lwip_strerr(x) "" +#endif /* LWIP_DEBUG */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_ERR_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/init.h b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/init.h new file mode 100644 index 0000000..3238534 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/init.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_INIT_H__ +#define __LWIP_INIT_H__ + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** X.x.x: Major version of the stack */ +#define LWIP_VERSION_MAJOR 1U +/** x.X.x: Minor version of the stack */ +#define LWIP_VERSION_MINOR 4U +/** x.x.X: Revision of the stack */ +#define LWIP_VERSION_REVISION 1U +/** For release candidates, this is set to 1..254 + * For official releases, this is set to 255 (LWIP_RC_RELEASE) + * For development versions (CVS), this is set to 0 (LWIP_RC_DEVELOPMENT) */ +#define LWIP_VERSION_RC 255U + +/** LWIP_VERSION_RC is set to LWIP_RC_RELEASE for official releases */ +#define LWIP_RC_RELEASE 255U +/** LWIP_VERSION_RC is set to LWIP_RC_DEVELOPMENT for CVS versions */ +#define LWIP_RC_DEVELOPMENT 0U + +#define LWIP_VERSION_IS_RELEASE (LWIP_VERSION_RC == LWIP_RC_RELEASE) +#define LWIP_VERSION_IS_DEVELOPMENT (LWIP_VERSION_RC == LWIP_RC_DEVELOPMENT) +#define LWIP_VERSION_IS_RC ((LWIP_VERSION_RC != LWIP_RC_RELEASE) && (LWIP_VERSION_RC != LWIP_RC_DEVELOPMENT)) + +/** Provides the version of the stack */ +#define LWIP_VERSION (LWIP_VERSION_MAJOR << 24 | LWIP_VERSION_MINOR << 16 | \ + LWIP_VERSION_REVISION << 8 | LWIP_VERSION_RC) + +/* Modules initialization */ +void lwip_init(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_INIT_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/lwip_timers.h b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/lwip_timers.h new file mode 100644 index 0000000..dbb9dbc --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/lwip_timers.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * Simon Goldschmidt + * + */ +#ifndef __LWIP_TIMERS_H__ +#define __LWIP_TIMERS_H__ + +#include "lwip/opt.h" + +/* Timers are not supported when NO_SYS==1 and NO_SYS_NO_TIMERS==1 */ +#define LWIP_TIMERS (!NO_SYS || (NO_SYS && !NO_SYS_NO_TIMERS)) + +#if LWIP_TIMERS + +#include "lwip/err.h" +#if !NO_SYS +#include "lwip/sys.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef LWIP_DEBUG_TIMERNAMES +#ifdef LWIP_DEBUG +#define LWIP_DEBUG_TIMERNAMES SYS_DEBUG +#else /* LWIP_DEBUG */ +#define LWIP_DEBUG_TIMERNAMES 0 +#endif /* LWIP_DEBUG*/ +#endif + +/** Function prototype for a timeout callback function. Register such a function + * using sys_timeout(). + * + * @param arg Additional argument to pass to the function - set up by sys_timeout() + */ +typedef void (* sys_timeout_handler)(void *arg); + +struct sys_timeo { + struct sys_timeo *next; + u32_t time; + sys_timeout_handler h; + void *arg; +#if LWIP_DEBUG_TIMERNAMES + const char* handler_name; +#endif /* LWIP_DEBUG_TIMERNAMES */ +}; + +void sys_timeouts_init(void); + +//Realtek add +struct sys_timeouts { + struct sys_timeo *next; +}; + +struct sys_timeouts *sys_arch_timeouts(void); +//Realtek add end + +#if LWIP_DEBUG_TIMERNAMES +void sys_timeout_debug(u32_t msecs, sys_timeout_handler handler, void *arg, const char* handler_name); +#define sys_timeout(msecs, handler, arg) sys_timeout_debug(msecs, handler, arg, #handler) +#else /* LWIP_DEBUG_TIMERNAMES */ +void sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg); +#endif /* LWIP_DEBUG_TIMERNAMES */ + +void sys_untimeout(sys_timeout_handler handler, void *arg); +#if NO_SYS +void sys_check_timeouts(void); +void sys_restart_timeouts(void); +#else /* NO_SYS */ +void sys_timeouts_mbox_fetch(sys_mbox_t *mbox, void **msg); +#endif /* NO_SYS */ + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_TIMERS */ +#endif /* __LWIP_TIMERS_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/mem.h b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/mem.h new file mode 100644 index 0000000..5bb906b --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/mem.h @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_MEM_H__ +#define __LWIP_MEM_H__ + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if MEM_LIBC_MALLOC + +#include /* for size_t */ + +typedef size_t mem_size_t; +#define MEM_SIZE_F SZT_F + +/* aliases for C library malloc() */ +#define mem_init() +/* in case C library malloc() needs extra protection, + * allow these defines to be overridden. + */ +#ifndef mem_free +#define mem_free free +#endif +#ifndef mem_malloc +#define mem_malloc malloc +#endif +#ifndef mem_calloc +#define mem_calloc calloc +#endif +/* Since there is no C library allocation function to shrink memory without + moving it, define this to nothing. */ +#ifndef mem_trim +#define mem_trim(mem, size) (mem) +#endif +#else /* MEM_LIBC_MALLOC */ + +/* MEM_SIZE would have to be aligned, but using 64000 here instead of + * 65535 leaves some room for alignment... + */ +#if MEM_SIZE > 64000L +typedef u32_t mem_size_t; +#define MEM_SIZE_F U32_F +#else +typedef u16_t mem_size_t; +#define MEM_SIZE_F U16_F +#endif /* MEM_SIZE > 64000 */ + +#if MEM_USE_POOLS +/** mem_init is not used when using pools instead of a heap */ +#define mem_init() +/** mem_trim is not used when using pools instead of a heap: + we can't free part of a pool element and don't want to copy the rest */ +#define mem_trim(mem, size) (mem) +#else /* MEM_USE_POOLS */ +/* lwIP alternative malloc */ +void mem_init(void); +void *mem_trim(void *mem, mem_size_t size); +#endif /* MEM_USE_POOLS */ +void *mem_malloc(mem_size_t size); +void *mem_calloc(mem_size_t count, mem_size_t size); +void mem_free(void *mem); +#endif /* MEM_LIBC_MALLOC */ + +/** Calculate memory size for an aligned buffer - returns the next highest + * multiple of MEM_ALIGNMENT (e.g. LWIP_MEM_ALIGN_SIZE(3) and + * LWIP_MEM_ALIGN_SIZE(4) will both yield 4 for MEM_ALIGNMENT == 4). + */ +#ifndef LWIP_MEM_ALIGN_SIZE +#define LWIP_MEM_ALIGN_SIZE(size) (((size) + MEM_ALIGNMENT - 1) & ~(MEM_ALIGNMENT-1)) +#endif + +/** Calculate safe memory size for an aligned buffer when using an unaligned + * type as storage. This includes a safety-margin on (MEM_ALIGNMENT - 1) at the + * start (e.g. if buffer is u8_t[] and actual data will be u32_t*) + */ +#ifndef LWIP_MEM_ALIGN_BUFFER +#define LWIP_MEM_ALIGN_BUFFER(size) (((size) + MEM_ALIGNMENT - 1)) +#endif + +/** Align a memory pointer to the alignment defined by MEM_ALIGNMENT + * so that ADDR % MEM_ALIGNMENT == 0 + */ +#ifndef LWIP_MEM_ALIGN +#define LWIP_MEM_ALIGN(addr) ((void *)(((mem_ptr_t)(addr) + MEM_ALIGNMENT - 1) & ~(mem_ptr_t)(MEM_ALIGNMENT-1))) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_MEM_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/memp.h b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/memp.h new file mode 100644 index 0000000..f0d0739 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/memp.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#ifndef __LWIP_MEMP_H__ +#define __LWIP_MEMP_H__ + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Create the list of all memory pools managed by memp. MEMP_MAX represents a NULL pool at the end */ +typedef enum { +#define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name, +#include "lwip/memp_std.h" + MEMP_MAX +} memp_t; + +#if MEM_USE_POOLS +/* Use a helper type to get the start and end of the user "memory pools" for mem_malloc */ +typedef enum { + /* Get the first (via: + MEMP_POOL_HELPER_START = ((u8_t) 1*MEMP_POOL_A + 0*MEMP_POOL_B + 0*MEMP_POOL_C + 0)*/ + MEMP_POOL_HELPER_FIRST = ((u8_t) +#define LWIP_MEMPOOL(name,num,size,desc) +#define LWIP_MALLOC_MEMPOOL_START 1 +#define LWIP_MALLOC_MEMPOOL(num, size) * MEMP_POOL_##size + 0 +#define LWIP_MALLOC_MEMPOOL_END +#include "lwip/memp_std.h" + ) , + /* Get the last (via: + MEMP_POOL_HELPER_END = ((u8_t) 0 + MEMP_POOL_A*0 + MEMP_POOL_B*0 + MEMP_POOL_C*1) */ + MEMP_POOL_HELPER_LAST = ((u8_t) +#define LWIP_MEMPOOL(name,num,size,desc) +#define LWIP_MALLOC_MEMPOOL_START +#define LWIP_MALLOC_MEMPOOL(num, size) 0 + MEMP_POOL_##size * +#define LWIP_MALLOC_MEMPOOL_END 1 +#include "lwip/memp_std.h" + ) +} memp_pool_helper_t; + +/* The actual start and stop values are here (cast them over) + We use this helper type and these defines so we can avoid using const memp_t values */ +#define MEMP_POOL_FIRST ((memp_t) MEMP_POOL_HELPER_FIRST) +#define MEMP_POOL_LAST ((memp_t) MEMP_POOL_HELPER_LAST) +#endif /* MEM_USE_POOLS */ + +#if MEMP_MEM_MALLOC || MEM_USE_POOLS +extern const u16_t memp_sizes[MEMP_MAX]; +#endif /* MEMP_MEM_MALLOC || MEM_USE_POOLS */ + +#if MEMP_MEM_MALLOC + +#include "mem.h" + +#define memp_init() +#define memp_malloc(type) mem_malloc(memp_sizes[type]) +#define memp_free(type, mem) mem_free(mem) + +#else /* MEMP_MEM_MALLOC */ + +#if MEM_USE_POOLS +/** This structure is used to save the pool one element came from. */ +struct memp_malloc_helper +{ + memp_t poolnr; +}; +#endif /* MEM_USE_POOLS */ + +void memp_init(void); + +#if MEMP_OVERFLOW_CHECK +void *memp_malloc_fn(memp_t type, const char* file, const int line); +#define memp_malloc(t) memp_malloc_fn((t), __FILE__, __LINE__) +#else +void *memp_malloc(memp_t type); +#endif +void memp_free(memp_t type, void *mem); + +#endif /* MEMP_MEM_MALLOC */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_MEMP_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/memp_std.h b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/memp_std.h new file mode 100644 index 0000000..461ed1a --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/memp_std.h @@ -0,0 +1,122 @@ +/* + * SETUP: Make sure we define everything we will need. + * + * We have create three types of pools: + * 1) MEMPOOL - standard pools + * 2) MALLOC_MEMPOOL - to be used by mem_malloc in mem.c + * 3) PBUF_MEMPOOL - a mempool of pbuf's, so include space for the pbuf struct + * + * If the include'r doesn't require any special treatment of each of the types + * above, then will declare #2 & #3 to be just standard mempools. + */ +#ifndef LWIP_MALLOC_MEMPOOL +/* This treats "malloc pools" just like any other pool. + The pools are a little bigger to provide 'size' as the amount of user data. */ +#define LWIP_MALLOC_MEMPOOL(num, size) LWIP_MEMPOOL(POOL_##size, num, (size + sizeof(struct memp_malloc_helper)), "MALLOC_"#size) +#define LWIP_MALLOC_MEMPOOL_START +#define LWIP_MALLOC_MEMPOOL_END +#endif /* LWIP_MALLOC_MEMPOOL */ + +#ifndef LWIP_PBUF_MEMPOOL +/* This treats "pbuf pools" just like any other pool. + * Allocates buffers for a pbuf struct AND a payload size */ +#define LWIP_PBUF_MEMPOOL(name, num, payload, desc) LWIP_MEMPOOL(name, num, (MEMP_ALIGN_SIZE(sizeof(struct pbuf)) + MEMP_ALIGN_SIZE(payload)), desc) +#endif /* LWIP_PBUF_MEMPOOL */ + + +/* + * A list of internal pools used by LWIP. + * + * LWIP_MEMPOOL(pool_name, number_elements, element_size, pool_description) + * creates a pool name MEMP_pool_name. description is used in stats.c + */ +#if LWIP_RAW +LWIP_MEMPOOL(RAW_PCB, MEMP_NUM_RAW_PCB, sizeof(struct raw_pcb), "RAW_PCB") +#endif /* LWIP_RAW */ + +#if LWIP_UDP +LWIP_MEMPOOL(UDP_PCB, MEMP_NUM_UDP_PCB, sizeof(struct udp_pcb), "UDP_PCB") +#endif /* LWIP_UDP */ + +#if LWIP_TCP +LWIP_MEMPOOL(TCP_PCB, MEMP_NUM_TCP_PCB, sizeof(struct tcp_pcb), "TCP_PCB") +LWIP_MEMPOOL(TCP_PCB_LISTEN, MEMP_NUM_TCP_PCB_LISTEN, sizeof(struct tcp_pcb_listen), "TCP_PCB_LISTEN") +LWIP_MEMPOOL(TCP_SEG, MEMP_NUM_TCP_SEG, sizeof(struct tcp_seg), "TCP_SEG") +#endif /* LWIP_TCP */ + +#if IP_REASSEMBLY +LWIP_MEMPOOL(REASSDATA, MEMP_NUM_REASSDATA, sizeof(struct ip_reassdata), "REASSDATA") +#endif /* IP_REASSEMBLY */ +#if IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF +LWIP_MEMPOOL(FRAG_PBUF, MEMP_NUM_FRAG_PBUF, sizeof(struct pbuf_custom_ref),"FRAG_PBUF") +#endif /* IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF */ + +#if LWIP_NETCONN +LWIP_MEMPOOL(NETBUF, MEMP_NUM_NETBUF, sizeof(struct netbuf), "NETBUF") +LWIP_MEMPOOL(NETCONN, MEMP_NUM_NETCONN, sizeof(struct netconn), "NETCONN") +#endif /* LWIP_NETCONN */ + +#if NO_SYS==0 +LWIP_MEMPOOL(TCPIP_MSG_API, MEMP_NUM_TCPIP_MSG_API, sizeof(struct tcpip_msg), "TCPIP_MSG_API") +#if !LWIP_TCPIP_CORE_LOCKING_INPUT +LWIP_MEMPOOL(TCPIP_MSG_INPKT,MEMP_NUM_TCPIP_MSG_INPKT, sizeof(struct tcpip_msg), "TCPIP_MSG_INPKT") +#endif /* !LWIP_TCPIP_CORE_LOCKING_INPUT */ +#endif /* NO_SYS==0 */ + +#if LWIP_ARP && ARP_QUEUEING +LWIP_MEMPOOL(ARP_QUEUE, MEMP_NUM_ARP_QUEUE, sizeof(struct etharp_q_entry), "ARP_QUEUE") +#endif /* LWIP_ARP && ARP_QUEUEING */ + +#if LWIP_IGMP +LWIP_MEMPOOL(IGMP_GROUP, MEMP_NUM_IGMP_GROUP, sizeof(struct igmp_group), "IGMP_GROUP") +#endif /* LWIP_IGMP */ + +#if (!NO_SYS || (NO_SYS && !NO_SYS_NO_TIMERS)) /* LWIP_TIMERS */ +LWIP_MEMPOOL(SYS_TIMEOUT, MEMP_NUM_SYS_TIMEOUT, sizeof(struct sys_timeo), "SYS_TIMEOUT") +#endif /* LWIP_TIMERS */ + +#if LWIP_SNMP +LWIP_MEMPOOL(SNMP_ROOTNODE, MEMP_NUM_SNMP_ROOTNODE, sizeof(struct mib_list_rootnode), "SNMP_ROOTNODE") +LWIP_MEMPOOL(SNMP_NODE, MEMP_NUM_SNMP_NODE, sizeof(struct mib_list_node), "SNMP_NODE") +LWIP_MEMPOOL(SNMP_VARBIND, MEMP_NUM_SNMP_VARBIND, sizeof(struct snmp_varbind), "SNMP_VARBIND") +LWIP_MEMPOOL(SNMP_VALUE, MEMP_NUM_SNMP_VALUE, SNMP_MAX_VALUE_SIZE, "SNMP_VALUE") +#endif /* LWIP_SNMP */ +#if LWIP_DNS && LWIP_SOCKET +LWIP_MEMPOOL(NETDB, MEMP_NUM_NETDB, NETDB_ELEM_SIZE, "NETDB") +#endif /* LWIP_DNS && LWIP_SOCKET */ +#if LWIP_DNS && DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC +LWIP_MEMPOOL(LOCALHOSTLIST, MEMP_NUM_LOCALHOSTLIST, LOCALHOSTLIST_ELEM_SIZE, "LOCALHOSTLIST") +#endif /* LWIP_DNS && DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ +#if PPP_SUPPORT && PPPOE_SUPPORT +LWIP_MEMPOOL(PPPOE_IF, MEMP_NUM_PPPOE_INTERFACES, sizeof(struct pppoe_softc), "PPPOE_IF") +#endif /* PPP_SUPPORT && PPPOE_SUPPORT */ + +/* + * A list of pools of pbuf's used by LWIP. + * + * LWIP_PBUF_MEMPOOL(pool_name, number_elements, pbuf_payload_size, pool_description) + * creates a pool name MEMP_pool_name. description is used in stats.c + * This allocates enough space for the pbuf struct and a payload. + * (Example: pbuf_payload_size=0 allocates only size for the struct) + */ +LWIP_PBUF_MEMPOOL(PBUF, MEMP_NUM_PBUF, 0, "PBUF_REF/ROM") +LWIP_PBUF_MEMPOOL(PBUF_POOL, PBUF_POOL_SIZE, PBUF_POOL_BUFSIZE, "PBUF_POOL") + + +/* + * Allow for user-defined pools; this must be explicitly set in lwipopts.h + * since the default is to NOT look for lwippools.h + */ +#if MEMP_USE_CUSTOM_POOLS +#include "lwippools.h" +#endif /* MEMP_USE_CUSTOM_POOLS */ + +/* + * REQUIRED CLEANUP: Clear up so we don't get "multiply defined" error later + * (#undef is ignored for something that is not defined) + */ +#undef LWIP_MEMPOOL +#undef LWIP_MALLOC_MEMPOOL +#undef LWIP_MALLOC_MEMPOOL_START +#undef LWIP_MALLOC_MEMPOOL_END +#undef LWIP_PBUF_MEMPOOL diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/netbuf.h b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/netbuf.h new file mode 100644 index 0000000..7d247d7 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/netbuf.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_NETBUF_H__ +#define __LWIP_NETBUF_H__ + +#include "lwip/opt.h" +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** This netbuf has dest-addr/port set */ +#define NETBUF_FLAG_DESTADDR 0x01 +/** This netbuf includes a checksum */ +#define NETBUF_FLAG_CHKSUM 0x02 + +struct netbuf { + struct pbuf *p, *ptr; + ip_addr_t addr; + u16_t port; +#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY +#if LWIP_CHECKSUM_ON_COPY + u8_t flags; +#endif /* LWIP_CHECKSUM_ON_COPY */ + u16_t toport_chksum; +#if LWIP_NETBUF_RECVINFO + ip_addr_t toaddr; +#endif /* LWIP_NETBUF_RECVINFO */ +#endif /* LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY */ +}; + +/* Network buffer functions: */ +struct netbuf * netbuf_new (void); +void netbuf_delete (struct netbuf *buf); +void * netbuf_alloc (struct netbuf *buf, u16_t size); +void netbuf_free (struct netbuf *buf); +err_t netbuf_ref (struct netbuf *buf, + const void *dataptr, u16_t size); +void netbuf_chain (struct netbuf *head, + struct netbuf *tail); + +err_t netbuf_data (struct netbuf *buf, + void **dataptr, u16_t *len); +s8_t netbuf_next (struct netbuf *buf); +void netbuf_first (struct netbuf *buf); + + +#define netbuf_copy_partial(buf, dataptr, len, offset) \ + pbuf_copy_partial((buf)->p, (dataptr), (len), (offset)) +#define netbuf_copy(buf,dataptr,len) netbuf_copy_partial(buf, dataptr, len, 0) +#define netbuf_take(buf, dataptr, len) pbuf_take((buf)->p, dataptr, len) +#define netbuf_len(buf) ((buf)->p->tot_len) +#define netbuf_fromaddr(buf) (&((buf)->addr)) +#define netbuf_set_fromaddr(buf, fromaddr) ip_addr_set((&(buf)->addr), fromaddr) +#define netbuf_fromport(buf) ((buf)->port) +#if LWIP_NETBUF_RECVINFO +#define netbuf_destaddr(buf) (&((buf)->toaddr)) +#define netbuf_set_destaddr(buf, destaddr) ip_addr_set((&(buf)->addr), destaddr) +#define netbuf_destport(buf) (((buf)->flags & NETBUF_FLAG_DESTADDR) ? (buf)->toport_chksum : 0) +#endif /* LWIP_NETBUF_RECVINFO */ +#if LWIP_CHECKSUM_ON_COPY +#define netbuf_set_chksum(buf, chksum) do { (buf)->flags = NETBUF_FLAG_CHKSUM; \ + (buf)->toport_chksum = chksum; } while(0) +#endif /* LWIP_CHECKSUM_ON_COPY */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_NETBUF_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/netdb.h b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/netdb.h new file mode 100644 index 0000000..7587e2f --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/netdb.h @@ -0,0 +1,124 @@ +/* + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Simon Goldschmidt + * + */ +#ifndef __LWIP_NETDB_H__ +#define __LWIP_NETDB_H__ + +#include "lwip/opt.h" + +#if LWIP_DNS && LWIP_SOCKET + +#include /* for size_t */ + +#include "lwip/inet.h" +#include "lwip/sockets.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* some rarely used options */ +#ifndef LWIP_DNS_API_DECLARE_H_ERRNO +#define LWIP_DNS_API_DECLARE_H_ERRNO 1 +#endif + +#ifndef LWIP_DNS_API_DEFINE_ERRORS +#define LWIP_DNS_API_DEFINE_ERRORS 1 +#endif + +#ifndef LWIP_DNS_API_DECLARE_STRUCTS +#define LWIP_DNS_API_DECLARE_STRUCTS 1 +#endif + +#if LWIP_DNS_API_DEFINE_ERRORS +/** Errors used by the DNS API functions, h_errno can be one of them */ +#define EAI_NONAME 200 +#define EAI_SERVICE 201 +#define EAI_FAIL 202 +#define EAI_MEMORY 203 + +#define HOST_NOT_FOUND 210 +#define NO_DATA 211 +#define NO_RECOVERY 212 +#define TRY_AGAIN 213 +#endif /* LWIP_DNS_API_DEFINE_ERRORS */ + +#if LWIP_DNS_API_DECLARE_STRUCTS +struct hostent { + char *h_name; /* Official name of the host. */ + char **h_aliases; /* A pointer to an array of pointers to alternative host names, + terminated by a null pointer. */ + int h_addrtype; /* Address type. */ + int h_length; /* The length, in bytes, of the address. */ + char **h_addr_list; /* A pointer to an array of pointers to network addresses (in + network byte order) for the host, terminated by a null pointer. */ +#define h_addr h_addr_list[0] /* for backward compatibility */ +}; + +struct addrinfo { + int ai_flags; /* Input flags. */ + int ai_family; /* Address family of socket. */ + int ai_socktype; /* Socket type. */ + int ai_protocol; /* Protocol of socket. */ + socklen_t ai_addrlen; /* Length of socket address. */ + struct sockaddr *ai_addr; /* Socket address of socket. */ + char *ai_canonname; /* Canonical name of service location. */ + struct addrinfo *ai_next; /* Pointer to next in list. */ +}; +#endif /* LWIP_DNS_API_DECLARE_STRUCTS */ + +#if LWIP_DNS_API_DECLARE_H_ERRNO +/* application accessable error code set by the DNS API functions */ +extern int h_errno; +#endif /* LWIP_DNS_API_DECLARE_H_ERRNO*/ + +struct hostent *lwip_gethostbyname(const char *name); +int lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf, + size_t buflen, struct hostent **result, int *h_errnop); +void lwip_freeaddrinfo(struct addrinfo *ai); +int lwip_getaddrinfo(const char *nodename, + const char *servname, + const struct addrinfo *hints, + struct addrinfo **res); + +#if LWIP_COMPAT_SOCKETS +#define gethostbyname(name) lwip_gethostbyname(name) +#define gethostbyname_r(name, ret, buf, buflen, result, h_errnop) \ + lwip_gethostbyname_r(name, ret, buf, buflen, result, h_errnop) +#define freeaddrinfo(addrinfo) lwip_freeaddrinfo(addrinfo) +#define getaddrinfo(nodname, servname, hints, res) \ + lwip_getaddrinfo(nodname, servname, hints, res) +#endif /* LWIP_COMPAT_SOCKETS */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_DNS && LWIP_SOCKET */ + +#endif /* __LWIP_NETDB_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/netif.h b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/netif.h new file mode 100644 index 0000000..f7e4937 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/netif.h @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_NETIF_H__ +#define __LWIP_NETIF_H__ + +#include "lwip/opt.h" + +#define ENABLE_LOOPBACK (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF) + +#include "lwip/err.h" + +#include "lwip/ip_addr.h" + +#include "lwip/def.h" +#include "lwip/pbuf.h" +#if LWIP_DHCP +struct dhcp; +#endif +#if LWIP_AUTOIP +struct autoip; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Throughout this file, IP addresses are expected to be in + * the same byte order as in IP_PCB. */ + +/** must be the maximum of all used hardware address lengths + across all types of interfaces in use */ +#define NETIF_MAX_HWADDR_LEN 6U + +/** Whether the network interface is 'up'. This is + * a software flag used to control whether this network + * interface is enabled and processes traffic. + * It is set by the startup code (for static IP configuration) or + * by dhcp/autoip when an address has been assigned. + */ +#define NETIF_FLAG_UP 0x01U +/** If set, the netif has broadcast capability. + * Set by the netif driver in its init function. */ +#define NETIF_FLAG_BROADCAST 0x02U +/** If set, the netif is one end of a point-to-point connection. + * Set by the netif driver in its init function. */ +#define NETIF_FLAG_POINTTOPOINT 0x04U +/** If set, the interface is configured using DHCP. + * Set by the DHCP code when starting or stopping DHCP. */ +#define NETIF_FLAG_DHCP 0x08U +/** If set, the interface has an active link + * (set by the network interface driver). + * Either set by the netif driver in its init function (if the link + * is up at that time) or at a later point once the link comes up + * (if link detection is supported by the hardware). */ +#define NETIF_FLAG_LINK_UP 0x10U +/** If set, the netif is an ethernet device using ARP. + * Set by the netif driver in its init function. + * Used to check input packet types and use of DHCP. */ +#define NETIF_FLAG_ETHARP 0x20U +/** If set, the netif is an ethernet device. It might not use + * ARP or TCP/IP if it is used for PPPoE only. + */ +#define NETIF_FLAG_ETHERNET 0x40U +/** If set, the netif has IGMP capability. + * Set by the netif driver in its init function. */ +#define NETIF_FLAG_IGMP 0x80U + +/** Function prototype for netif init functions. Set up flags and output/linkoutput + * callback functions in this function. + * + * @param netif The netif to initialize + */ +typedef err_t (*netif_init_fn)(struct netif *netif); +/** Function prototype for netif->input functions. This function is saved as 'input' + * callback function in the netif struct. Call it when a packet has been received. + * + * @param p The received packet, copied into a pbuf + * @param inp The netif which received the packet + */ +typedef err_t (*netif_input_fn)(struct pbuf *p, struct netif *inp); +/** Function prototype for netif->output functions. Called by lwIP when a packet + * shall be sent. For ethernet netif, set this to 'etharp_output' and set + * 'linkoutput'. + * + * @param netif The netif which shall send a packet + * @param p The packet to send (p->payload points to IP header) + * @param ipaddr The IP address to which the packet shall be sent + */ +typedef err_t (*netif_output_fn)(struct netif *netif, struct pbuf *p, + ip_addr_t *ipaddr); +/** Function prototype for netif->linkoutput functions. Only used for ethernet + * netifs. This function is called by ARP when a packet shall be sent. + * + * @param netif The netif which shall send a packet + * @param p The packet to send (raw ethernet packet) + */ +typedef err_t (*netif_linkoutput_fn)(struct netif *netif, struct pbuf *p); +/** Function prototype for netif status- or link-callback functions. */ +typedef void (*netif_status_callback_fn)(struct netif *netif); +/** Function prototype for netif igmp_mac_filter functions */ +typedef err_t (*netif_igmp_mac_filter_fn)(struct netif *netif, + ip_addr_t *group, u8_t action); + +/** Generic data structure used for all lwIP network interfaces. + * The following fields should be filled in by the initialization + * function for the device driver: hwaddr_len, hwaddr[], mtu, flags */ +struct netif { + /** pointer to next in linked list */ + struct netif *next; + + /** IP address configuration in network byte order */ + ip_addr_t ip_addr; + ip_addr_t netmask; + ip_addr_t gw; + + /** This function is called by the network device driver + * to pass a packet up the TCP/IP stack. */ + netif_input_fn input; + /** This function is called by the IP module when it wants + * to send a packet on the interface. This function typically + * first resolves the hardware address, then sends the packet. */ + netif_output_fn output; + /** This function is called by the ARP module when it wants + * to send a packet on the interface. This function outputs + * the pbuf as-is on the link medium. */ + netif_linkoutput_fn linkoutput; +#if LWIP_NETIF_STATUS_CALLBACK + /** This function is called when the netif state is set to up or down + */ + netif_status_callback_fn status_callback; +#endif /* LWIP_NETIF_STATUS_CALLBACK */ +#if LWIP_NETIF_LINK_CALLBACK + /** This function is called when the netif link is set to up or down + */ + netif_status_callback_fn link_callback; +#endif /* LWIP_NETIF_LINK_CALLBACK */ +#if LWIP_NETIF_REMOVE_CALLBACK + /** This function is called when the netif has been removed */ + netif_status_callback_fn remove_callback; +#endif /* LWIP_NETIF_REMOVE_CALLBACK */ + /** This field can be set by the device driver and could point + * to state information for the device. */ + void *state; +#if LWIP_DHCP + /** the DHCP client state information for this netif */ + struct dhcp *dhcp; +#endif /* LWIP_DHCP */ +#if LWIP_AUTOIP + /** the AutoIP client state information for this netif */ + struct autoip *autoip; +#endif +#if LWIP_NETIF_HOSTNAME + /* the hostname for this netif, NULL is a valid value */ + char* hostname; +#endif /* LWIP_NETIF_HOSTNAME */ + /** maximum transfer unit (in bytes) */ + u16_t mtu; + /** number of bytes used in hwaddr */ + u8_t hwaddr_len; + /** link level hardware address of this interface */ + u8_t hwaddr[NETIF_MAX_HWADDR_LEN]; + /** flags (see NETIF_FLAG_ above) */ + u8_t flags; + /** descriptive abbreviation */ + char name[2]; + /** number of this interface */ + u8_t num; +#if LWIP_SNMP + /** link type (from "snmp_ifType" enum from snmp.h) */ + u8_t link_type; + /** (estimate) link speed */ + u32_t link_speed; + /** timestamp at last change made (up/down) */ + u32_t ts; + /** counters */ + u32_t ifinoctets; + u32_t ifinucastpkts; + u32_t ifinnucastpkts; + u32_t ifindiscards; + u32_t ifoutoctets; + u32_t ifoutucastpkts; + u32_t ifoutnucastpkts; + u32_t ifoutdiscards; +#endif /* LWIP_SNMP */ +#if LWIP_IGMP + /** This function could be called to add or delete a entry in the multicast + filter table of the ethernet MAC.*/ + netif_igmp_mac_filter_fn igmp_mac_filter; +#endif /* LWIP_IGMP */ +#if LWIP_NETIF_HWADDRHINT + u8_t *addr_hint; +#endif /* LWIP_NETIF_HWADDRHINT */ +#if ENABLE_LOOPBACK + /* List of packets to be queued for ourselves. */ + struct pbuf *loop_first; + struct pbuf *loop_last; +#if LWIP_LOOPBACK_MAX_PBUFS + u16_t loop_cnt_current; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ +#endif /* ENABLE_LOOPBACK */ +}; + +#if LWIP_SNMP +#define NETIF_INIT_SNMP(netif, type, speed) \ + /* use "snmp_ifType" enum from snmp.h for "type", snmp_ifType_ethernet_csmacd by example */ \ + (netif)->link_type = (type); \ + /* your link speed here (units: bits per second) */ \ + (netif)->link_speed = (speed); \ + (netif)->ts = 0; \ + (netif)->ifinoctets = 0; \ + (netif)->ifinucastpkts = 0; \ + (netif)->ifinnucastpkts = 0; \ + (netif)->ifindiscards = 0; \ + (netif)->ifoutoctets = 0; \ + (netif)->ifoutucastpkts = 0; \ + (netif)->ifoutnucastpkts = 0; \ + (netif)->ifoutdiscards = 0 +#else /* LWIP_SNMP */ +#define NETIF_INIT_SNMP(netif, type, speed) +#endif /* LWIP_SNMP */ + + +/** The list of network interfaces. */ +extern struct netif *netif_list; +/** The default network interface. */ +extern struct netif *netif_default; + +void netif_init(void); + +struct netif *netif_add(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask, + ip_addr_t *gw, void *state, netif_init_fn init, netif_input_fn input); + +void +netif_set_addr(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask, + ip_addr_t *gw); +void netif_remove(struct netif * netif); + +/* Returns a network interface given its name. The name is of the form + "et0", where the first two letters are the "name" field in the + netif structure, and the digit is in the num field in the same + structure. */ +struct netif *netif_find(char *name); + +void netif_set_default(struct netif *netif); + +void netif_set_ipaddr(struct netif *netif, ip_addr_t *ipaddr); +void netif_set_netmask(struct netif *netif, ip_addr_t *netmask); +void netif_set_gw(struct netif *netif, ip_addr_t *gw); + +void netif_set_up(struct netif *netif); +void netif_set_down(struct netif *netif); +/** Ask if an interface is up */ +#define netif_is_up(netif) (((netif)->flags & NETIF_FLAG_UP) ? (u8_t)1 : (u8_t)0) + +#if LWIP_NETIF_STATUS_CALLBACK +void netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback); +#endif /* LWIP_NETIF_STATUS_CALLBACK */ +#if LWIP_NETIF_REMOVE_CALLBACK +void netif_set_remove_callback(struct netif *netif, netif_status_callback_fn remove_callback); +#endif /* LWIP_NETIF_REMOVE_CALLBACK */ + +void netif_set_link_up(struct netif *netif); +void netif_set_link_down(struct netif *netif); +/** Ask if a link is up */ +#define netif_is_link_up(netif) (((netif)->flags & NETIF_FLAG_LINK_UP) ? (u8_t)1 : (u8_t)0) + +#if LWIP_NETIF_LINK_CALLBACK +void netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback); +#endif /* LWIP_NETIF_LINK_CALLBACK */ + +#if LWIP_NETIF_HOSTNAME +#define netif_set_hostname(netif, name) do { if((netif) != NULL) { (netif)->hostname = name; }}while(0) +#define netif_get_hostname(netif) (((netif) != NULL) ? ((netif)->hostname) : NULL) +#endif /* LWIP_NETIF_HOSTNAME */ + +#if LWIP_IGMP +#define netif_set_igmp_mac_filter(netif, function) do { if((netif) != NULL) { (netif)->igmp_mac_filter = function; }}while(0) +#define netif_get_igmp_mac_filter(netif) (((netif) != NULL) ? ((netif)->igmp_mac_filter) : NULL) +#endif /* LWIP_IGMP */ + +#if ENABLE_LOOPBACK +err_t netif_loop_output(struct netif *netif, struct pbuf *p, ip_addr_t *dest_ip); +void netif_poll(struct netif *netif); +#if !LWIP_NETIF_LOOPBACK_MULTITHREADING +void netif_poll_all(void); +#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */ +#endif /* ENABLE_LOOPBACK */ + +#if LWIP_NETIF_HWADDRHINT +#define NETIF_SET_HWADDRHINT(netif, hint) ((netif)->addr_hint = (hint)) +#else /* LWIP_NETIF_HWADDRHINT */ +#define NETIF_SET_HWADDRHINT(netif, hint) +#endif /* LWIP_NETIF_HWADDRHINT */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_NETIF_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/netifapi.h b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/netifapi.h new file mode 100644 index 0000000..33318ef --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/netifapi.h @@ -0,0 +1,108 @@ +/* + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#ifndef __LWIP_NETIFAPI_H__ +#define __LWIP_NETIFAPI_H__ + +#include "lwip/opt.h" + +#if LWIP_NETIF_API /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/sys.h" +#include "lwip/netif.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*netifapi_void_fn)(struct netif *netif); +typedef err_t (*netifapi_errt_fn)(struct netif *netif); + +struct netifapi_msg_msg { +#if !LWIP_TCPIP_CORE_LOCKING + sys_sem_t sem; +#endif /* !LWIP_TCPIP_CORE_LOCKING */ + err_t err; + struct netif *netif; + union { + struct { + ip_addr_t *ipaddr; + ip_addr_t *netmask; + ip_addr_t *gw; + void *state; + netif_init_fn init; + netif_input_fn input; + } add; + struct { + netifapi_void_fn voidfunc; + netifapi_errt_fn errtfunc; + } common; + } msg; +}; + +struct netifapi_msg { + void (* function)(struct netifapi_msg_msg *msg); + struct netifapi_msg_msg msg; +}; + + +/* API for application */ +err_t netifapi_netif_add ( struct netif *netif, + ip_addr_t *ipaddr, + ip_addr_t *netmask, + ip_addr_t *gw, + void *state, + netif_init_fn init, + netif_input_fn input); + +err_t netifapi_netif_set_addr ( struct netif *netif, + ip_addr_t *ipaddr, + ip_addr_t *netmask, + ip_addr_t *gw ); + +err_t netifapi_netif_common ( struct netif *netif, + netifapi_void_fn voidfunc, + netifapi_errt_fn errtfunc); + +#define netifapi_netif_remove(n) netifapi_netif_common(n, netif_remove, NULL) +#define netifapi_netif_set_up(n) netifapi_netif_common(n, netif_set_up, NULL) +#define netifapi_netif_set_down(n) netifapi_netif_common(n, netif_set_down, NULL) +#define netifapi_netif_set_default(n) netifapi_netif_common(n, netif_set_default, NULL) +#define netifapi_dhcp_start(n) netifapi_netif_common(n, NULL, dhcp_start) +#define netifapi_dhcp_stop(n) netifapi_netif_common(n, dhcp_stop, NULL) +#define netifapi_autoip_start(n) netifapi_netif_common(n, NULL, autoip_start) +#define netifapi_autoip_stop(n) netifapi_netif_common(n, NULL, autoip_stop) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_NETIF_API */ + +#endif /* __LWIP_NETIFAPI_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/opt.h b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/opt.h new file mode 100644 index 0000000..e387f31 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/opt.h @@ -0,0 +1,2134 @@ +/** + * @file + * + * lwIP Options Configuration + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_OPT_H__ +#define __LWIP_OPT_H__ + +/* + * Include user defined options first. Anything not defined in these files + * will be set to standard values. Override anything you dont like! + */ +#include "lwipopts.h" +#include "lwip/debug.h" + +/* + ----------------------------------------------- + ---------- Platform specific locking ---------- + ----------------------------------------------- +*/ + +/** + * SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain + * critical regions during buffer allocation, deallocation and memory + * allocation and deallocation. + */ +#ifndef SYS_LIGHTWEIGHT_PROT +#define SYS_LIGHTWEIGHT_PROT 0 +#endif + +/** + * NO_SYS==1: Provides VERY minimal functionality. Otherwise, + * use lwIP facilities. + */ +#ifndef NO_SYS +#define NO_SYS 0 +#endif + +/** + * NO_SYS_NO_TIMERS==1: Drop support for sys_timeout when NO_SYS==1 + * Mainly for compatibility to old versions. + */ +#ifndef NO_SYS_NO_TIMERS +#define NO_SYS_NO_TIMERS 0 +#endif + +/** + * MEMCPY: override this if you have a faster implementation at hand than the + * one included in your C library + */ +#ifndef MEMCPY +#define MEMCPY(dst,src,len) memcpy(dst,src,len) +#endif + +/** + * SMEMCPY: override this with care! Some compilers (e.g. gcc) can inline a + * call to memcpy() if the length is known at compile time and is small. + */ +#ifndef SMEMCPY +#define SMEMCPY(dst,src,len) memcpy(dst,src,len) +#endif + +/* + ------------------------------------ + ---------- Memory options ---------- + ------------------------------------ +*/ +/** + * MEM_LIBC_MALLOC==1: Use malloc/free/realloc provided by your C-library + * instead of the lwip internal allocator. Can save code size if you + * already use it. + */ +#ifndef MEM_LIBC_MALLOC +#define MEM_LIBC_MALLOC 0 +#endif + +/** +* MEMP_MEM_MALLOC==1: Use mem_malloc/mem_free instead of the lwip pool allocator. +* Especially useful with MEM_LIBC_MALLOC but handle with care regarding execution +* speed and usage from interrupts! +*/ +#ifndef MEMP_MEM_MALLOC +#define MEMP_MEM_MALLOC 0 +#endif + +/** + * MEM_ALIGNMENT: should be set to the alignment of the CPU + * 4 byte alignment -> #define MEM_ALIGNMENT 4 + * 2 byte alignment -> #define MEM_ALIGNMENT 2 + */ +#ifndef MEM_ALIGNMENT +#define MEM_ALIGNMENT 1 +#endif + +/** + * MEM_SIZE: the size of the heap memory. If the application will send + * a lot of data that needs to be copied, this should be set high. + */ +#ifndef MEM_SIZE +#define MEM_SIZE 1600 +#endif + +/** + * MEMP_SEPARATE_POOLS: if defined to 1, each pool is placed in its own array. + * This can be used to individually change the location of each pool. + * Default is one big array for all pools + */ +#ifndef MEMP_SEPARATE_POOLS +#define MEMP_SEPARATE_POOLS 0 +#endif + +/** + * MEMP_OVERFLOW_CHECK: memp overflow protection reserves a configurable + * amount of bytes before and after each memp element in every pool and fills + * it with a prominent default value. + * MEMP_OVERFLOW_CHECK == 0 no checking + * MEMP_OVERFLOW_CHECK == 1 checks each element when it is freed + * MEMP_OVERFLOW_CHECK >= 2 checks each element in every pool every time + * memp_malloc() or memp_free() is called (useful but slow!) + */ +#ifndef MEMP_OVERFLOW_CHECK +#define MEMP_OVERFLOW_CHECK 0 +#endif + +/** + * MEMP_SANITY_CHECK==1: run a sanity check after each memp_free() to make + * sure that there are no cycles in the linked lists. + */ +#ifndef MEMP_SANITY_CHECK +#define MEMP_SANITY_CHECK 0 +#endif + +/** + * MEM_USE_POOLS==1: Use an alternative to malloc() by allocating from a set + * of memory pools of various sizes. When mem_malloc is called, an element of + * the smallest pool that can provide the length needed is returned. + * To use this, MEMP_USE_CUSTOM_POOLS also has to be enabled. + */ +#ifndef MEM_USE_POOLS +#define MEM_USE_POOLS 0 +#endif + +/** + * MEM_USE_POOLS_TRY_BIGGER_POOL==1: if one malloc-pool is empty, try the next + * bigger pool - WARNING: THIS MIGHT WASTE MEMORY but it can make a system more + * reliable. */ +#ifndef MEM_USE_POOLS_TRY_BIGGER_POOL +#define MEM_USE_POOLS_TRY_BIGGER_POOL 0 +#endif + +/** + * MEMP_USE_CUSTOM_POOLS==1: whether to include a user file lwippools.h + * that defines additional pools beyond the "standard" ones required + * by lwIP. If you set this to 1, you must have lwippools.h in your + * inlude path somewhere. + */ +#ifndef MEMP_USE_CUSTOM_POOLS +#define MEMP_USE_CUSTOM_POOLS 0 +#endif + +/** + * Set this to 1 if you want to free PBUF_RAM pbufs (or call mem_free()) from + * interrupt context (or another context that doesn't allow waiting for a + * semaphore). + * If set to 1, mem_malloc will be protected by a semaphore and SYS_ARCH_PROTECT, + * while mem_free will only use SYS_ARCH_PROTECT. mem_malloc SYS_ARCH_UNPROTECTs + * with each loop so that mem_free can run. + * + * ATTENTION: As you can see from the above description, this leads to dis-/ + * enabling interrupts often, which can be slow! Also, on low memory, mem_malloc + * can need longer. + * + * If you don't want that, at least for NO_SYS=0, you can still use the following + * functions to enqueue a deallocation call which then runs in the tcpip_thread + * context: + * - pbuf_free_callback(p); + * - mem_free_callback(m); + */ +#ifndef LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT +#define LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT 0 +#endif + +/* + ------------------------------------------------ + ---------- Internal Memory Pool Sizes ---------- + ------------------------------------------------ +*/ +/** + * MEMP_NUM_PBUF: the number of memp struct pbufs (used for PBUF_ROM and PBUF_REF). + * If the application sends a lot of data out of ROM (or other static memory), + * this should be set high. + */ +#ifndef MEMP_NUM_PBUF +#define MEMP_NUM_PBUF 16 +#endif + +/** + * MEMP_NUM_RAW_PCB: Number of raw connection PCBs + * (requires the LWIP_RAW option) + */ +#ifndef MEMP_NUM_RAW_PCB +#define MEMP_NUM_RAW_PCB 4 +#endif + +/** + * MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One + * per active UDP "connection". + * (requires the LWIP_UDP option) + */ +#ifndef MEMP_NUM_UDP_PCB +#define MEMP_NUM_UDP_PCB 4 +#endif + +/** + * MEMP_NUM_TCP_PCB: the number of simulatenously active TCP connections. + * (requires the LWIP_TCP option) + */ +#ifndef MEMP_NUM_TCP_PCB +#define MEMP_NUM_TCP_PCB 5 +#endif + +/** + * MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP connections. + * (requires the LWIP_TCP option) + */ +#ifndef MEMP_NUM_TCP_PCB_LISTEN +#define MEMP_NUM_TCP_PCB_LISTEN 8 +#endif + +/** + * MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP segments. + * (requires the LWIP_TCP option) + */ +#ifndef MEMP_NUM_TCP_SEG +#define MEMP_NUM_TCP_SEG 16 +#endif + +/** + * MEMP_NUM_REASSDATA: the number of IP packets simultaneously queued for + * reassembly (whole packets, not fragments!) + */ +#ifndef MEMP_NUM_REASSDATA +#define MEMP_NUM_REASSDATA 5 +#endif + +/** + * MEMP_NUM_FRAG_PBUF: the number of IP fragments simultaneously sent + * (fragments, not whole packets!). + * This is only used with IP_FRAG_USES_STATIC_BUF==0 and + * LWIP_NETIF_TX_SINGLE_PBUF==0 and only has to be > 1 with DMA-enabled MACs + * where the packet is not yet sent when netif->output returns. + */ +#ifndef MEMP_NUM_FRAG_PBUF +#define MEMP_NUM_FRAG_PBUF 15 +#endif + +/** + * MEMP_NUM_ARP_QUEUE: the number of simulateously queued outgoing + * packets (pbufs) that are waiting for an ARP request (to resolve + * their destination address) to finish. + * (requires the ARP_QUEUEING option) + */ +#ifndef MEMP_NUM_ARP_QUEUE +#define MEMP_NUM_ARP_QUEUE 30 +#endif + +/** + * MEMP_NUM_IGMP_GROUP: The number of multicast groups whose network interfaces + * can be members et the same time (one per netif - allsystems group -, plus one + * per netif membership). + * (requires the LWIP_IGMP option) + */ +#ifndef MEMP_NUM_IGMP_GROUP +#define MEMP_NUM_IGMP_GROUP 8 +#endif + +/** + * MEMP_NUM_SYS_TIMEOUT: the number of simulateously active timeouts. + * (requires NO_SYS==0) + * The default number of timeouts is calculated here for all enabled modules. + * The formula expects settings to be either '0' or '1'. + */ +#ifndef MEMP_NUM_SYS_TIMEOUT +#define MEMP_NUM_SYS_TIMEOUT (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + PPP_SUPPORT) +#endif + +/** + * MEMP_NUM_NETBUF: the number of struct netbufs. + * (only needed if you use the sequential API, like api_lib.c) + */ +#ifndef MEMP_NUM_NETBUF +#define MEMP_NUM_NETBUF 2 +#endif + +/** + * MEMP_NUM_NETCONN: the number of struct netconns. + * (only needed if you use the sequential API, like api_lib.c) + */ +#ifndef MEMP_NUM_NETCONN +#define MEMP_NUM_NETCONN 8 +#endif + +/** + * MEMP_NUM_TCPIP_MSG_API: the number of struct tcpip_msg, which are used + * for callback/timeout API communication. + * (only needed if you use tcpip.c) + */ +#ifndef MEMP_NUM_TCPIP_MSG_API +#define MEMP_NUM_TCPIP_MSG_API 8 +#endif + +/** + * MEMP_NUM_TCPIP_MSG_INPKT: the number of struct tcpip_msg, which are used + * for incoming packets. + * (only needed if you use tcpip.c) + */ +#ifndef MEMP_NUM_TCPIP_MSG_INPKT +#define MEMP_NUM_TCPIP_MSG_INPKT 8 +#endif + +/** + * MEMP_NUM_SNMP_NODE: the number of leafs in the SNMP tree. + */ +#ifndef MEMP_NUM_SNMP_NODE +#define MEMP_NUM_SNMP_NODE 50 +#endif + +/** + * MEMP_NUM_SNMP_ROOTNODE: the number of branches in the SNMP tree. + * Every branch has one leaf (MEMP_NUM_SNMP_NODE) at least! + */ +#ifndef MEMP_NUM_SNMP_ROOTNODE +#define MEMP_NUM_SNMP_ROOTNODE 30 +#endif + +/** + * MEMP_NUM_SNMP_VARBIND: the number of concurrent requests (does not have to + * be changed normally) - 2 of these are used per request (1 for input, + * 1 for output) + */ +#ifndef MEMP_NUM_SNMP_VARBIND +#define MEMP_NUM_SNMP_VARBIND 2 +#endif + +/** + * MEMP_NUM_SNMP_VALUE: the number of OID or values concurrently used + * (does not have to be changed normally) - 3 of these are used per request + * (1 for the value read and 2 for OIDs - input and output) + */ +#ifndef MEMP_NUM_SNMP_VALUE +#define MEMP_NUM_SNMP_VALUE 3 +#endif + +/** + * MEMP_NUM_NETDB: the number of concurrently running lwip_addrinfo() calls + * (before freeing the corresponding memory using lwip_freeaddrinfo()). + */ +#ifndef MEMP_NUM_NETDB +#define MEMP_NUM_NETDB 1 +#endif + +/** + * MEMP_NUM_LOCALHOSTLIST: the number of host entries in the local host list + * if DNS_LOCAL_HOSTLIST_IS_DYNAMIC==1. + */ +#ifndef MEMP_NUM_LOCALHOSTLIST +#define MEMP_NUM_LOCALHOSTLIST 1 +#endif + +/** + * MEMP_NUM_PPPOE_INTERFACES: the number of concurrently active PPPoE + * interfaces (only used with PPPOE_SUPPORT==1) + */ +#ifndef MEMP_NUM_PPPOE_INTERFACES +#define MEMP_NUM_PPPOE_INTERFACES 1 +#endif + +/** + * PBUF_POOL_SIZE: the number of buffers in the pbuf pool. + */ +#ifndef PBUF_POOL_SIZE +#define PBUF_POOL_SIZE 16 +#endif + +/* + --------------------------------- + ---------- ARP options ---------- + --------------------------------- +*/ +/** + * LWIP_ARP==1: Enable ARP functionality. + */ +#ifndef LWIP_ARP +#define LWIP_ARP 1 +#endif + +/** + * ARP_TABLE_SIZE: Number of active MAC-IP address pairs cached. + */ +#ifndef ARP_TABLE_SIZE +#define ARP_TABLE_SIZE 10 +#endif + +/** + * ARP_QUEUEING==1: Multiple outgoing packets are queued during hardware address + * resolution. By default, only the most recent packet is queued per IP address. + * This is sufficient for most protocols and mainly reduces TCP connection + * startup time. Set this to 1 if you know your application sends more than one + * packet in a row to an IP address that is not in the ARP cache. + */ +#ifndef ARP_QUEUEING +#define ARP_QUEUEING 0 +#endif + +/** + * ETHARP_TRUST_IP_MAC==1: Incoming IP packets cause the ARP table to be + * updated with the source MAC and IP addresses supplied in the packet. + * You may want to disable this if you do not trust LAN peers to have the + * correct addresses, or as a limited approach to attempt to handle + * spoofing. If disabled, lwIP will need to make a new ARP request if + * the peer is not already in the ARP table, adding a little latency. + * The peer *is* in the ARP table if it requested our address before. + * Also notice that this slows down input processing of every IP packet! + */ +#ifndef ETHARP_TRUST_IP_MAC +#define ETHARP_TRUST_IP_MAC 0 +#endif + +/** + * ETHARP_SUPPORT_VLAN==1: support receiving ethernet packets with VLAN header. + * Additionally, you can define ETHARP_VLAN_CHECK to an u16_t VLAN ID to check. + * If ETHARP_VLAN_CHECK is defined, only VLAN-traffic for this VLAN is accepted. + * If ETHARP_VLAN_CHECK is not defined, all traffic is accepted. + * Alternatively, define a function/define ETHARP_VLAN_CHECK_FN(eth_hdr, vlan) + * that returns 1 to accept a packet or 0 to drop a packet. + */ +#ifndef ETHARP_SUPPORT_VLAN +#define ETHARP_SUPPORT_VLAN 0 +#endif + +/** LWIP_ETHERNET==1: enable ethernet support for PPPoE even though ARP + * might be disabled + */ +#ifndef LWIP_ETHERNET +#define LWIP_ETHERNET (LWIP_ARP || PPPOE_SUPPORT) +#endif + +/** ETH_PAD_SIZE: number of bytes added before the ethernet header to ensure + * alignment of payload after that header. Since the header is 14 bytes long, + * without this padding e.g. addresses in the IP header will not be aligned + * on a 32-bit boundary, so setting this to 2 can speed up 32-bit-platforms. + */ +#ifndef ETH_PAD_SIZE +#define ETH_PAD_SIZE 0 +#endif + +/** ETHARP_SUPPORT_STATIC_ENTRIES==1: enable code to support static ARP table + * entries (using etharp_add_static_entry/etharp_remove_static_entry). + */ +#ifndef ETHARP_SUPPORT_STATIC_ENTRIES +#define ETHARP_SUPPORT_STATIC_ENTRIES 0 +#endif + + +/* + -------------------------------- + ---------- IP options ---------- + -------------------------------- +*/ +/** + * IP_FORWARD==1: Enables the ability to forward IP packets across network + * interfaces. If you are going to run lwIP on a device with only one network + * interface, define this to 0. + */ +#ifndef IP_FORWARD +#define IP_FORWARD 0 +#endif + +/** + * IP_OPTIONS_ALLOWED: Defines the behavior for IP options. + * IP_OPTIONS_ALLOWED==0: All packets with IP options are dropped. + * IP_OPTIONS_ALLOWED==1: IP options are allowed (but not parsed). + */ +#ifndef IP_OPTIONS_ALLOWED +#define IP_OPTIONS_ALLOWED 1 +#endif + +/** + * IP_REASSEMBLY==1: Reassemble incoming fragmented IP packets. Note that + * this option does not affect outgoing packet sizes, which can be controlled + * via IP_FRAG. + */ +#ifndef IP_REASSEMBLY +#define IP_REASSEMBLY 1 +#endif + +/** + * IP_FRAG==1: Fragment outgoing IP packets if their size exceeds MTU. Note + * that this option does not affect incoming packet sizes, which can be + * controlled via IP_REASSEMBLY. + */ +#ifndef IP_FRAG +#define IP_FRAG 1 +#endif + +/** + * IP_REASS_MAXAGE: Maximum time (in multiples of IP_TMR_INTERVAL - so seconds, normally) + * a fragmented IP packet waits for all fragments to arrive. If not all fragments arrived + * in this time, the whole packet is discarded. + */ +#ifndef IP_REASS_MAXAGE +#define IP_REASS_MAXAGE 3 +#endif + +/** + * IP_REASS_MAX_PBUFS: Total maximum amount of pbufs waiting to be reassembled. + * Since the received pbufs are enqueued, be sure to configure + * PBUF_POOL_SIZE > IP_REASS_MAX_PBUFS so that the stack is still able to receive + * packets even if the maximum amount of fragments is enqueued for reassembly! + */ +#ifndef IP_REASS_MAX_PBUFS +#define IP_REASS_MAX_PBUFS 10 +#endif + +/** + * IP_FRAG_USES_STATIC_BUF==1: Use a static MTU-sized buffer for IP + * fragmentation. Otherwise pbufs are allocated and reference the original + * packet data to be fragmented (or with LWIP_NETIF_TX_SINGLE_PBUF==1, + * new PBUF_RAM pbufs are used for fragments). + * ATTENTION: IP_FRAG_USES_STATIC_BUF==1 may not be used for DMA-enabled MACs! + */ +#ifndef IP_FRAG_USES_STATIC_BUF +#define IP_FRAG_USES_STATIC_BUF 0 +#endif + +/** + * IP_FRAG_MAX_MTU: Assumed max MTU on any interface for IP frag buffer + * (requires IP_FRAG_USES_STATIC_BUF==1) + */ +#if IP_FRAG_USES_STATIC_BUF && !defined(IP_FRAG_MAX_MTU) +#define IP_FRAG_MAX_MTU 1500 +#endif + +/** + * IP_DEFAULT_TTL: Default value for Time-To-Live used by transport layers. + */ +#ifndef IP_DEFAULT_TTL +#define IP_DEFAULT_TTL 255 +#endif + +/** + * IP_SOF_BROADCAST=1: Use the SOF_BROADCAST field to enable broadcast + * filter per pcb on udp and raw send operations. To enable broadcast filter + * on recv operations, you also have to set IP_SOF_BROADCAST_RECV=1. + */ +#ifndef IP_SOF_BROADCAST +#define IP_SOF_BROADCAST 0 +#endif + +/** + * IP_SOF_BROADCAST_RECV (requires IP_SOF_BROADCAST=1) enable the broadcast + * filter on recv operations. + */ +#ifndef IP_SOF_BROADCAST_RECV +#define IP_SOF_BROADCAST_RECV 0 +#endif + +/** + * IP_FORWARD_ALLOW_TX_ON_RX_NETIF==1: allow ip_forward() to send packets back + * out on the netif where it was received. This should only be used for + * wireless networks. + * ATTENTION: When this is 1, make sure your netif driver correctly marks incoming + * link-layer-broadcast/multicast packets as such using the corresponding pbuf flags! + */ +#ifndef IP_FORWARD_ALLOW_TX_ON_RX_NETIF +#define IP_FORWARD_ALLOW_TX_ON_RX_NETIF 0 +#endif + +/** + * LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS==1: randomize the local port for the first + * local TCP/UDP pcb (default==0). This can prevent creating predictable port + * numbers after booting a device. + */ +#ifndef LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS +#define LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS 0 +#endif + +/* + ---------------------------------- + ---------- ICMP options ---------- + ---------------------------------- +*/ +/** + * LWIP_ICMP==1: Enable ICMP module inside the IP stack. + * Be careful, disable that make your product non-compliant to RFC1122 + */ +#ifndef LWIP_ICMP +#define LWIP_ICMP 1 +#endif + +/** + * ICMP_TTL: Default value for Time-To-Live used by ICMP packets. + */ +#ifndef ICMP_TTL +#define ICMP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * LWIP_BROADCAST_PING==1: respond to broadcast pings (default is unicast only) + */ +#ifndef LWIP_BROADCAST_PING +#define LWIP_BROADCAST_PING 0 +#endif + +/** + * LWIP_MULTICAST_PING==1: respond to multicast pings (default is unicast only) + */ +#ifndef LWIP_MULTICAST_PING +#define LWIP_MULTICAST_PING 0 +#endif + +/* + --------------------------------- + ---------- RAW options ---------- + --------------------------------- +*/ +/** + * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. + */ +#ifndef LWIP_RAW +#define LWIP_RAW 1 +#endif + +/** + * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. + */ +#ifndef RAW_TTL +#define RAW_TTL (IP_DEFAULT_TTL) +#endif + +/* + ---------------------------------- + ---------- DHCP options ---------- + ---------------------------------- +*/ +/** + * LWIP_DHCP==1: Enable DHCP module. + */ +#ifndef LWIP_DHCP +#define LWIP_DHCP 0 +#endif + +/** + * DHCP_DOES_ARP_CHECK==1: Do an ARP check on the offered address. + */ +#ifndef DHCP_DOES_ARP_CHECK +#define DHCP_DOES_ARP_CHECK ((LWIP_DHCP) && (LWIP_ARP)) +#endif + +/* + ------------------------------------ + ---------- AUTOIP options ---------- + ------------------------------------ +*/ +/** + * LWIP_AUTOIP==1: Enable AUTOIP module. + */ +#ifndef LWIP_AUTOIP +#define LWIP_AUTOIP 1 //Realtek modified (0->1) +#endif + +/** + * LWIP_DHCP_AUTOIP_COOP==1: Allow DHCP and AUTOIP to be both enabled on + * the same interface at the same time. + */ +#ifndef LWIP_DHCP_AUTOIP_COOP +#define LWIP_DHCP_AUTOIP_COOP 0 +#endif + +/** + * LWIP_DHCP_AUTOIP_COOP_TRIES: Set to the number of DHCP DISCOVER probes + * that should be sent before falling back on AUTOIP. This can be set + * as low as 1 to get an AutoIP address very quickly, but you should + * be prepared to handle a changing IP address when DHCP overrides + * AutoIP. + */ +#ifndef LWIP_DHCP_AUTOIP_COOP_TRIES +#define LWIP_DHCP_AUTOIP_COOP_TRIES 9 +#endif + +/* + ---------------------------------- + ---------- SNMP options ---------- + ---------------------------------- +*/ +/** + * LWIP_SNMP==1: Turn on SNMP module. UDP must be available for SNMP + * transport. + */ +#ifndef LWIP_SNMP +#define LWIP_SNMP 0 +#endif + +/** + * SNMP_CONCURRENT_REQUESTS: Number of concurrent requests the module will + * allow. At least one request buffer is required. + * Does not have to be changed unless external MIBs answer request asynchronously + */ +#ifndef SNMP_CONCURRENT_REQUESTS +#define SNMP_CONCURRENT_REQUESTS 1 +#endif + +/** + * SNMP_TRAP_DESTINATIONS: Number of trap destinations. At least one trap + * destination is required + */ +#ifndef SNMP_TRAP_DESTINATIONS +#define SNMP_TRAP_DESTINATIONS 1 +#endif + +/** + * SNMP_PRIVATE_MIB: + * When using a private MIB, you have to create a file 'private_mib.h' that contains + * a 'struct mib_array_node mib_private' which contains your MIB. + */ +#ifndef SNMP_PRIVATE_MIB +#define SNMP_PRIVATE_MIB 0 +#endif + +/** + * Only allow SNMP write actions that are 'safe' (e.g. disabeling netifs is not + * a safe action and disabled when SNMP_SAFE_REQUESTS = 1). + * Unsafe requests are disabled by default! + */ +#ifndef SNMP_SAFE_REQUESTS +#define SNMP_SAFE_REQUESTS 1 +#endif + +/** + * The maximum length of strings used. This affects the size of + * MEMP_SNMP_VALUE elements. + */ +#ifndef SNMP_MAX_OCTET_STRING_LEN +#define SNMP_MAX_OCTET_STRING_LEN 127 +#endif + +/** + * The maximum depth of the SNMP tree. + * With private MIBs enabled, this depends on your MIB! + * This affects the size of MEMP_SNMP_VALUE elements. + */ +#ifndef SNMP_MAX_TREE_DEPTH +#define SNMP_MAX_TREE_DEPTH 15 +#endif + +/** + * The size of the MEMP_SNMP_VALUE elements, normally calculated from + * SNMP_MAX_OCTET_STRING_LEN and SNMP_MAX_TREE_DEPTH. + */ +#ifndef SNMP_MAX_VALUE_SIZE +#define SNMP_MAX_VALUE_SIZE LWIP_MAX((SNMP_MAX_OCTET_STRING_LEN)+1, sizeof(s32_t)*(SNMP_MAX_TREE_DEPTH)) +#endif + +/* + ---------------------------------- + ---------- IGMP options ---------- + ---------------------------------- +*/ +/** + * LWIP_IGMP==1: Turn on IGMP module. + */ +#ifndef LWIP_IGMP +#define LWIP_IGMP 0 +#endif + +/* + ---------------------------------- + ---------- DNS options ----------- + ---------------------------------- +*/ +/** + * LWIP_DNS==1: Turn on DNS module. UDP must be available for DNS + * transport. + */ +#ifndef LWIP_DNS +#define LWIP_DNS 0 +#endif + +/** DNS maximum number of entries to maintain locally. */ +#ifndef DNS_TABLE_SIZE +#define DNS_TABLE_SIZE 4 +#endif + +/** DNS maximum host name length supported in the name table. */ +#ifndef DNS_MAX_NAME_LENGTH +#define DNS_MAX_NAME_LENGTH 256 +#endif + +/** The maximum of DNS servers */ +#ifndef DNS_MAX_SERVERS +#define DNS_MAX_SERVERS 2 +#endif + +/** DNS do a name checking between the query and the response. */ +#ifndef DNS_DOES_NAME_CHECK +#define DNS_DOES_NAME_CHECK 1 +#endif + +/** DNS message max. size. Default value is RFC compliant. */ +#ifndef DNS_MSG_SIZE +#define DNS_MSG_SIZE 512 +#endif + +/** DNS_LOCAL_HOSTLIST: Implements a local host-to-address list. If enabled, + * you have to define + * #define DNS_LOCAL_HOSTLIST_INIT {{"host1", 0x123}, {"host2", 0x234}} + * (an array of structs name/address, where address is an u32_t in network + * byte order). + * + * Instead, you can also use an external function: + * #define DNS_LOOKUP_LOCAL_EXTERN(x) extern u32_t my_lookup_function(const char *name) + * that returns the IP address or INADDR_NONE if not found. + */ +#ifndef DNS_LOCAL_HOSTLIST +#define DNS_LOCAL_HOSTLIST 0 +#endif /* DNS_LOCAL_HOSTLIST */ + +/** If this is turned on, the local host-list can be dynamically changed + * at runtime. */ +#ifndef DNS_LOCAL_HOSTLIST_IS_DYNAMIC +#define DNS_LOCAL_HOSTLIST_IS_DYNAMIC 0 +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + +/* + --------------------------------- + ---------- UDP options ---------- + --------------------------------- +*/ +/** + * LWIP_UDP==1: Turn on UDP. + */ +#ifndef LWIP_UDP +#define LWIP_UDP 1 +#endif + +/** + * LWIP_UDPLITE==1: Turn on UDP-Lite. (Requires LWIP_UDP) + */ +#ifndef LWIP_UDPLITE +#define LWIP_UDPLITE 0 +#endif + +/** + * UDP_TTL: Default Time-To-Live value. + */ +#ifndef UDP_TTL +#define UDP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * LWIP_NETBUF_RECVINFO==1: append destination addr and port to every netbuf. + */ +#ifndef LWIP_NETBUF_RECVINFO +#define LWIP_NETBUF_RECVINFO 0 +#endif + +/* + --------------------------------- + ---------- TCP options ---------- + --------------------------------- +*/ +/** + * LWIP_TCP==1: Turn on TCP. + */ +#ifndef LWIP_TCP +#define LWIP_TCP 1 +#endif + +/** + * TCP_TTL: Default Time-To-Live value. + */ +#ifndef TCP_TTL +#define TCP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * TCP_WND: The size of a TCP window. This must be at least + * (2 * TCP_MSS) for things to work well + */ +#ifndef TCP_WND +#define TCP_WND (4 * TCP_MSS) +#endif + +/** + * TCP_MAXRTX: Maximum number of retransmissions of data segments. + */ +#ifndef TCP_MAXRTX +#define TCP_MAXRTX 12 +#endif + +/** + * TCP_SYNMAXRTX: Maximum number of retransmissions of SYN segments. + */ +#ifndef TCP_SYNMAXRTX +#define TCP_SYNMAXRTX 6 +#endif + +/** + * TCP_QUEUE_OOSEQ==1: TCP will queue segments that arrive out of order. + * Define to 0 if your device is low on memory. + */ +#ifndef TCP_QUEUE_OOSEQ +#define TCP_QUEUE_OOSEQ (LWIP_TCP) +#endif + +/** + * TCP_MSS: TCP Maximum segment size. (default is 536, a conservative default, + * you might want to increase this.) + * For the receive side, this MSS is advertised to the remote side + * when opening a connection. For the transmit size, this MSS sets + * an upper limit on the MSS advertised by the remote host. + */ +#ifndef TCP_MSS +#define TCP_MSS 536 +#endif + +/** + * TCP_CALCULATE_EFF_SEND_MSS: "The maximum size of a segment that TCP really + * sends, the 'effective send MSS,' MUST be the smaller of the send MSS (which + * reflects the available reassembly buffer size at the remote host) and the + * largest size permitted by the IP layer" (RFC 1122) + * Setting this to 1 enables code that checks TCP_MSS against the MTU of the + * netif used for a connection and limits the MSS if it would be too big otherwise. + */ +#ifndef TCP_CALCULATE_EFF_SEND_MSS +#define TCP_CALCULATE_EFF_SEND_MSS 1 +#endif + + +/** + * TCP_SND_BUF: TCP sender buffer space (bytes). + * To achieve good performance, this should be at least 2 * TCP_MSS. + */ +#ifndef TCP_SND_BUF +#define TCP_SND_BUF (2 * TCP_MSS) +#endif + +/** + * TCP_SND_QUEUELEN: TCP sender buffer space (pbufs). This must be at least + * as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. + */ +#ifndef TCP_SND_QUEUELEN +#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1))/(TCP_MSS)) +#endif + +/** + * TCP_SNDLOWAT: TCP writable space (bytes). This must be less than + * TCP_SND_BUF. It is the amount of space which must be available in the + * TCP snd_buf for select to return writable (combined with TCP_SNDQUEUELOWAT). + */ +#ifndef TCP_SNDLOWAT +#define TCP_SNDLOWAT LWIP_MIN(LWIP_MAX(((TCP_SND_BUF)/2), (2 * TCP_MSS) + 1), (TCP_SND_BUF) - 1) +#endif + +/** + * TCP_SNDQUEUELOWAT: TCP writable bufs (pbuf count). This must be less + * than TCP_SND_QUEUELEN. If the number of pbufs queued on a pcb drops below + * this number, select returns writable (combined with TCP_SNDLOWAT). + */ +#ifndef TCP_SNDQUEUELOWAT +#define TCP_SNDQUEUELOWAT LWIP_MAX(((TCP_SND_QUEUELEN)/2), 5) +#endif + +/** + * TCP_OOSEQ_MAX_BYTES: The maximum number of bytes queued on ooseq per pcb. + * Default is 0 (no limit). Only valid for TCP_QUEUE_OOSEQ==0. + */ +#ifndef TCP_OOSEQ_MAX_BYTES +#define TCP_OOSEQ_MAX_BYTES 0 +#endif + +/** + * TCP_OOSEQ_MAX_PBUFS: The maximum number of pbufs queued on ooseq per pcb. + * Default is 0 (no limit). Only valid for TCP_QUEUE_OOSEQ==0. + */ +#ifndef TCP_OOSEQ_MAX_PBUFS +#define TCP_OOSEQ_MAX_PBUFS 0 +#endif + +/** + * TCP_LISTEN_BACKLOG: Enable the backlog option for tcp listen pcb. + */ +#ifndef TCP_LISTEN_BACKLOG +#define TCP_LISTEN_BACKLOG 0 +#endif + +/** + * The maximum allowed backlog for TCP listen netconns. + * This backlog is used unless another is explicitly specified. + * 0xff is the maximum (u8_t). + */ +#ifndef TCP_DEFAULT_LISTEN_BACKLOG +#define TCP_DEFAULT_LISTEN_BACKLOG 0xff +#endif + +/** + * TCP_OVERSIZE: The maximum number of bytes that tcp_write may + * allocate ahead of time in an attempt to create shorter pbuf chains + * for transmission. The meaningful range is 0 to TCP_MSS. Some + * suggested values are: + * + * 0: Disable oversized allocation. Each tcp_write() allocates a new + pbuf (old behaviour). + * 1: Allocate size-aligned pbufs with minimal excess. Use this if your + * scatter-gather DMA requires aligned fragments. + * 128: Limit the pbuf/memory overhead to 20%. + * TCP_MSS: Try to create unfragmented TCP packets. + * TCP_MSS/4: Try to create 4 fragments or less per TCP packet. + */ +#ifndef TCP_OVERSIZE +#define TCP_OVERSIZE TCP_MSS +#endif + +/** + * LWIP_TCP_TIMESTAMPS==1: support the TCP timestamp option. + */ +#ifndef LWIP_TCP_TIMESTAMPS +#define LWIP_TCP_TIMESTAMPS 0 +#endif + +/** + * TCP_WND_UPDATE_THRESHOLD: difference in window to trigger an + * explicit window update + */ +#ifndef TCP_WND_UPDATE_THRESHOLD +#define TCP_WND_UPDATE_THRESHOLD (TCP_WND / 4) +#endif + +/** + * LWIP_EVENT_API and LWIP_CALLBACK_API: Only one of these should be set to 1. + * LWIP_EVENT_API==1: The user defines lwip_tcp_event() to receive all + * events (accept, sent, etc) that happen in the system. + * LWIP_CALLBACK_API==1: The PCB callback function is called directly + * for the event. This is the default. + */ +#if !defined(LWIP_EVENT_API) && !defined(LWIP_CALLBACK_API) +#define LWIP_EVENT_API 0 +#define LWIP_CALLBACK_API 1 +#endif + + +/* + ---------------------------------- + ---------- Pbuf options ---------- + ---------------------------------- +*/ +/** + * PBUF_LINK_HLEN: the number of bytes that should be allocated for a + * link level header. The default is 14, the standard value for + * Ethernet. + */ +#ifndef PBUF_LINK_HLEN +#define PBUF_LINK_HLEN (14 + ETH_PAD_SIZE) +#endif + +/** + * PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. The default is + * designed to accomodate single full size TCP frame in one pbuf, including + * TCP_MSS, IP header, and link header. + */ +#ifndef PBUF_POOL_BUFSIZE +#define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS+40+PBUF_LINK_HLEN) +#endif + +/* + ------------------------------------------------ + ---------- Network Interfaces options ---------- + ------------------------------------------------ +*/ +/** + * LWIP_NETIF_HOSTNAME==1: use DHCP_OPTION_HOSTNAME with netif's hostname + * field. + */ +#ifndef LWIP_NETIF_HOSTNAME +#define LWIP_NETIF_HOSTNAME 0 +#endif + +/** + * LWIP_NETIF_API==1: Support netif api (in netifapi.c) + */ +#ifndef LWIP_NETIF_API +#define LWIP_NETIF_API 0 +#endif + +/** + * LWIP_NETIF_STATUS_CALLBACK==1: Support a callback function whenever an interface + * changes its up/down status (i.e., due to DHCP IP acquistion) + */ +#ifndef LWIP_NETIF_STATUS_CALLBACK +#define LWIP_NETIF_STATUS_CALLBACK 0 +#endif + +/** + * LWIP_NETIF_LINK_CALLBACK==1: Support a callback function from an interface + * whenever the link changes (i.e., link down) + */ +#ifndef LWIP_NETIF_LINK_CALLBACK +#define LWIP_NETIF_LINK_CALLBACK 0 +#endif + +/** + * LWIP_NETIF_REMOVE_CALLBACK==1: Support a callback function that is called + * when a netif has been removed + */ +#ifndef LWIP_NETIF_REMOVE_CALLBACK +#define LWIP_NETIF_REMOVE_CALLBACK 0 +#endif + +/** + * LWIP_NETIF_HWADDRHINT==1: Cache link-layer-address hints (e.g. table + * indices) in struct netif. TCP and UDP can make use of this to prevent + * scanning the ARP table for every sent packet. While this is faster for big + * ARP tables or many concurrent connections, it might be counterproductive + * if you have a tiny ARP table or if there never are concurrent connections. + */ +#ifndef LWIP_NETIF_HWADDRHINT +#define LWIP_NETIF_HWADDRHINT 0 +#endif + +/** + * LWIP_NETIF_LOOPBACK==1: Support sending packets with a destination IP + * address equal to the netif IP address, looping them back up the stack. + */ +#ifndef LWIP_NETIF_LOOPBACK +#define LWIP_NETIF_LOOPBACK 0 +#endif + +/** + * LWIP_LOOPBACK_MAX_PBUFS: Maximum number of pbufs on queue for loopback + * sending for each netif (0 = disabled) + */ +#ifndef LWIP_LOOPBACK_MAX_PBUFS +#define LWIP_LOOPBACK_MAX_PBUFS 0 +#endif + +/** + * LWIP_NETIF_LOOPBACK_MULTITHREADING: Indicates whether threading is enabled in + * the system, as netifs must change how they behave depending on this setting + * for the LWIP_NETIF_LOOPBACK option to work. + * Setting this is needed to avoid reentering non-reentrant functions like + * tcp_input(). + * LWIP_NETIF_LOOPBACK_MULTITHREADING==1: Indicates that the user is using a + * multithreaded environment like tcpip.c. In this case, netif->input() + * is called directly. + * LWIP_NETIF_LOOPBACK_MULTITHREADING==0: Indicates a polling (or NO_SYS) setup. + * The packets are put on a list and netif_poll() must be called in + * the main application loop. + */ +#ifndef LWIP_NETIF_LOOPBACK_MULTITHREADING +#define LWIP_NETIF_LOOPBACK_MULTITHREADING (!NO_SYS) +#endif + +/** + * LWIP_NETIF_TX_SINGLE_PBUF: if this is set to 1, lwIP tries to put all data + * to be sent into one single pbuf. This is for compatibility with DMA-enabled + * MACs that do not support scatter-gather. + * Beware that this might involve CPU-memcpy before transmitting that would not + * be needed without this flag! Use this only if you need to! + * + * @todo: TCP and IP-frag do not work with this, yet: + */ +#ifndef LWIP_NETIF_TX_SINGLE_PBUF +#define LWIP_NETIF_TX_SINGLE_PBUF 0 +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + +/* + ------------------------------------ + ---------- LOOPIF options ---------- + ------------------------------------ +*/ +/** + * LWIP_HAVE_LOOPIF==1: Support loop interface (127.0.0.1) and loopif.c + */ +#ifndef LWIP_HAVE_LOOPIF +#define LWIP_HAVE_LOOPIF 0 +#endif + +/* + ------------------------------------ + ---------- SLIPIF options ---------- + ------------------------------------ +*/ +/** + * LWIP_HAVE_SLIPIF==1: Support slip interface and slipif.c + */ +#ifndef LWIP_HAVE_SLIPIF +#define LWIP_HAVE_SLIPIF 0 +#endif + +/* + ------------------------------------ + ---------- Thread options ---------- + ------------------------------------ +*/ +/** + * TCPIP_THREAD_NAME: The name assigned to the main tcpip thread. + */ +#ifndef TCPIP_THREAD_NAME +#define TCPIP_THREAD_NAME "TCP_IP" //Realtek modified ("tcpip_thread"->"TCP_IP") +#endif + +/** + * TCPIP_THREAD_STACKSIZE: The stack size used by the main tcpip thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef TCPIP_THREAD_STACKSIZE +#define TCPIP_THREAD_STACKSIZE 0 +#endif + +/** + * TCPIP_THREAD_PRIO: The priority assigned to the main tcpip thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef TCPIP_THREAD_PRIO +#define TCPIP_THREAD_PRIO 1 +#endif + +/** + * TCPIP_MBOX_SIZE: The mailbox size for the tcpip thread messages + * The queue size value itself is platform-dependent, but is passed to + * sys_mbox_new() when tcpip_init is called. + */ +#ifndef TCPIP_MBOX_SIZE +#define TCPIP_MBOX_SIZE 0 +#endif + +/** + * SLIPIF_THREAD_NAME: The name assigned to the slipif_loop thread. + */ +#ifndef SLIPIF_THREAD_NAME +#define SLIPIF_THREAD_NAME "slipif_loop" +#endif + +/** + * SLIP_THREAD_STACKSIZE: The stack size used by the slipif_loop thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef SLIPIF_THREAD_STACKSIZE +#define SLIPIF_THREAD_STACKSIZE 0 +#endif + +/** + * SLIPIF_THREAD_PRIO: The priority assigned to the slipif_loop thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef SLIPIF_THREAD_PRIO +#define SLIPIF_THREAD_PRIO 1 +#endif + +/** + * PPP_THREAD_NAME: The name assigned to the pppInputThread. + */ +#ifndef PPP_THREAD_NAME +#define PPP_THREAD_NAME "pppInputThread" +#endif + +/** + * PPP_THREAD_STACKSIZE: The stack size used by the pppInputThread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef PPP_THREAD_STACKSIZE +#define PPP_THREAD_STACKSIZE 0 +#endif + +/** + * PPP_THREAD_PRIO: The priority assigned to the pppInputThread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef PPP_THREAD_PRIO +#define PPP_THREAD_PRIO 1 +#endif + +/** + * DEFAULT_THREAD_NAME: The name assigned to any other lwIP thread. + */ +#ifndef DEFAULT_THREAD_NAME +#define DEFAULT_THREAD_NAME "lwIP" +#endif + +/** + * DEFAULT_THREAD_STACKSIZE: The stack size used by any other lwIP thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef DEFAULT_THREAD_STACKSIZE +#define DEFAULT_THREAD_STACKSIZE 0 +#endif + +/** + * DEFAULT_THREAD_PRIO: The priority assigned to any other lwIP thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef DEFAULT_THREAD_PRIO +#define DEFAULT_THREAD_PRIO 1 +#endif + +/** + * DEFAULT_RAW_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_RAW. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#ifndef DEFAULT_RAW_RECVMBOX_SIZE +#define DEFAULT_RAW_RECVMBOX_SIZE 0 +#endif + +/** + * DEFAULT_UDP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_UDP. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#ifndef DEFAULT_UDP_RECVMBOX_SIZE +#define DEFAULT_UDP_RECVMBOX_SIZE 0 +#endif + +/** + * DEFAULT_TCP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_TCP. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#ifndef DEFAULT_TCP_RECVMBOX_SIZE +#define DEFAULT_TCP_RECVMBOX_SIZE 0 +#endif + +/** + * DEFAULT_ACCEPTMBOX_SIZE: The mailbox size for the incoming connections. + * The queue size value itself is platform-dependent, but is passed to + * sys_mbox_new() when the acceptmbox is created. + */ +#ifndef DEFAULT_ACCEPTMBOX_SIZE +#define DEFAULT_ACCEPTMBOX_SIZE 0 +#endif + +/* + ---------------------------------------------- + ---------- Sequential layer options ---------- + ---------------------------------------------- +*/ +/** + * LWIP_TCPIP_CORE_LOCKING: (EXPERIMENTAL!) + * Don't use it if you're not an active lwIP project member + */ +#ifndef LWIP_TCPIP_CORE_LOCKING +#define LWIP_TCPIP_CORE_LOCKING 0 +#endif + +/** + * LWIP_TCPIP_CORE_LOCKING_INPUT: (EXPERIMENTAL!) + * Don't use it if you're not an active lwIP project member + */ +#ifndef LWIP_TCPIP_CORE_LOCKING_INPUT +#define LWIP_TCPIP_CORE_LOCKING_INPUT 0 +#endif + +/** + * LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c) + */ +#ifndef LWIP_NETCONN +#define LWIP_NETCONN 1 +#endif + +/** LWIP_TCPIP_TIMEOUT==1: Enable tcpip_timeout/tcpip_untimeout tod create + * timers running in tcpip_thread from another thread. + */ +#ifndef LWIP_TCPIP_TIMEOUT +#define LWIP_TCPIP_TIMEOUT 1 +#endif + +/* + ------------------------------------ + ---------- Socket options ---------- + ------------------------------------ +*/ +/** + * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c) + */ +#ifndef LWIP_SOCKET +#define LWIP_SOCKET 1 +#endif + +/** + * LWIP_COMPAT_SOCKETS==1: Enable BSD-style sockets functions names. + * (only used if you use sockets.c) + */ +#ifndef LWIP_COMPAT_SOCKETS +#define LWIP_COMPAT_SOCKETS 1 +#endif + +/** + * LWIP_POSIX_SOCKETS_IO_NAMES==1: Enable POSIX-style sockets functions names. + * Disable this option if you use a POSIX operating system that uses the same + * names (read, write & close). (only used if you use sockets.c) + */ +#ifndef LWIP_POSIX_SOCKETS_IO_NAMES +#define LWIP_POSIX_SOCKETS_IO_NAMES 1 +#endif + +/** + * LWIP_TCP_KEEPALIVE==1: Enable TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT + * options processing. Note that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set + * in seconds. (does not require sockets.c, and will affect tcp.c) + */ +#ifndef LWIP_TCP_KEEPALIVE +#define LWIP_TCP_KEEPALIVE 0 +#endif + +/** + * LWIP_SO_SNDTIMEO==1: Enable send timeout for sockets/netconns and + * SO_SNDTIMEO processing. + */ +#ifndef LWIP_SO_SNDTIMEO +#define LWIP_SO_SNDTIMEO 0 +#endif + +/** + * LWIP_SO_RCVTIMEO==1: Enable receive timeout for sockets/netconns and + * SO_RCVTIMEO processing. + */ +#ifndef LWIP_SO_RCVTIMEO +#define LWIP_SO_RCVTIMEO 1 //Realtek modified(0->1) +#endif + +/** + * LWIP_SO_RCVBUF==1: Enable SO_RCVBUF processing. + */ +#ifndef LWIP_SO_RCVBUF +#define LWIP_SO_RCVBUF 0 +#endif + +/** + * If LWIP_SO_RCVBUF is used, this is the default value for recv_bufsize. + */ +#ifndef RECV_BUFSIZE_DEFAULT +#define RECV_BUFSIZE_DEFAULT INT_MAX +#endif + +/** + * SO_REUSE==1: Enable SO_REUSEADDR option. + */ +#ifndef SO_REUSE +#define SO_REUSE 0 +#endif + +/** + * SO_REUSE_RXTOALL==1: Pass a copy of incoming broadcast/multicast packets + * to all local matches if SO_REUSEADDR is turned on. + * WARNING: Adds a memcpy for every packet if passing to more than one pcb! + */ +#ifndef SO_REUSE_RXTOALL +#define SO_REUSE_RXTOALL 0 +#endif + +/* + ---------------------------------------- + ---------- Statistics options ---------- + ---------------------------------------- +*/ +/** + * LWIP_STATS==1: Enable statistics collection in lwip_stats. + */ +#ifndef LWIP_STATS +#define LWIP_STATS 1 +#endif + +#if LWIP_STATS + +/** + * LWIP_STATS_DISPLAY==1: Compile in the statistics output functions. + */ +#ifndef LWIP_STATS_DISPLAY +#define LWIP_STATS_DISPLAY 0 +#endif + +/** + * LINK_STATS==1: Enable link stats. + */ +#ifndef LINK_STATS +#define LINK_STATS 1 +#endif + +/** + * ETHARP_STATS==1: Enable etharp stats. + */ +#ifndef ETHARP_STATS +#define ETHARP_STATS (LWIP_ARP) +#endif + +/** + * IP_STATS==1: Enable IP stats. + */ +#ifndef IP_STATS +#define IP_STATS 1 +#endif + +/** + * IPFRAG_STATS==1: Enable IP fragmentation stats. Default is + * on if using either frag or reass. + */ +#ifndef IPFRAG_STATS +#define IPFRAG_STATS (IP_REASSEMBLY || IP_FRAG) +#endif + +/** + * ICMP_STATS==1: Enable ICMP stats. + */ +#ifndef ICMP_STATS +#define ICMP_STATS 1 +#endif + +/** + * IGMP_STATS==1: Enable IGMP stats. + */ +#ifndef IGMP_STATS +#define IGMP_STATS (LWIP_IGMP) +#endif + +/** + * UDP_STATS==1: Enable UDP stats. Default is on if + * UDP enabled, otherwise off. + */ +#ifndef UDP_STATS +#define UDP_STATS (LWIP_UDP) +#endif + +/** + * TCP_STATS==1: Enable TCP stats. Default is on if TCP + * enabled, otherwise off. + */ +#ifndef TCP_STATS +#define TCP_STATS (LWIP_TCP) +#endif + +/** + * MEM_STATS==1: Enable mem.c stats. + */ +#ifndef MEM_STATS +#define MEM_STATS ((MEM_LIBC_MALLOC == 0) && (MEM_USE_POOLS == 0)) +#endif + +/** + * MEMP_STATS==1: Enable memp.c pool stats. + */ +#ifndef MEMP_STATS +#define MEMP_STATS (MEMP_MEM_MALLOC == 0) +#endif + +/** + * SYS_STATS==1: Enable system stats (sem and mbox counts, etc). + */ +#ifndef SYS_STATS +#define SYS_STATS (NO_SYS == 0) +#endif + +#else + +#define LINK_STATS 0 +#define IP_STATS 0 +#define IPFRAG_STATS 0 +#define ICMP_STATS 0 +#define IGMP_STATS 0 +#define UDP_STATS 0 +#define TCP_STATS 0 +#define MEM_STATS 0 +#define MEMP_STATS 0 +#define SYS_STATS 0 +#define LWIP_STATS_DISPLAY 0 +#define ETHARP_STATS 0 //Realtek add + +#endif /* LWIP_STATS */ + +/* + --------------------------------- + ---------- PPP options ---------- + --------------------------------- +*/ +/** + * PPP_SUPPORT==1: Enable PPP. + */ +#ifndef PPP_SUPPORT +#define PPP_SUPPORT 0 +#endif + +/** + * PPPOE_SUPPORT==1: Enable PPP Over Ethernet + */ +#ifndef PPPOE_SUPPORT +#define PPPOE_SUPPORT 0 +#endif + +/** + * PPPOS_SUPPORT==1: Enable PPP Over Serial + */ +#ifndef PPPOS_SUPPORT +#define PPPOS_SUPPORT PPP_SUPPORT +#endif + +#if PPP_SUPPORT + +/** + * NUM_PPP: Max PPP sessions. + */ +#ifndef NUM_PPP +#define NUM_PPP 1 +#endif + +/** + * PAP_SUPPORT==1: Support PAP. + */ +#ifndef PAP_SUPPORT +#define PAP_SUPPORT 0 +#endif + +/** + * CHAP_SUPPORT==1: Support CHAP. + */ +#ifndef CHAP_SUPPORT +#define CHAP_SUPPORT 0 +#endif + +/** + * MSCHAP_SUPPORT==1: Support MSCHAP. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef MSCHAP_SUPPORT +#define MSCHAP_SUPPORT 0 +#endif + +/** + * CBCP_SUPPORT==1: Support CBCP. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef CBCP_SUPPORT +#define CBCP_SUPPORT 0 +#endif + +/** + * CCP_SUPPORT==1: Support CCP. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef CCP_SUPPORT +#define CCP_SUPPORT 0 +#endif + +/** + * VJ_SUPPORT==1: Support VJ header compression. + */ +#ifndef VJ_SUPPORT +#define VJ_SUPPORT 0 +#endif + +/** + * MD5_SUPPORT==1: Support MD5 (see also CHAP). + */ +#ifndef MD5_SUPPORT +#define MD5_SUPPORT 0 +#endif + +/* + * Timeouts + */ +#ifndef FSM_DEFTIMEOUT +#define FSM_DEFTIMEOUT 6 /* Timeout time in seconds */ +#endif + +#ifndef FSM_DEFMAXTERMREQS +#define FSM_DEFMAXTERMREQS 2 /* Maximum Terminate-Request transmissions */ +#endif + +#ifndef FSM_DEFMAXCONFREQS +#define FSM_DEFMAXCONFREQS 10 /* Maximum Configure-Request transmissions */ +#endif + +#ifndef FSM_DEFMAXNAKLOOPS +#define FSM_DEFMAXNAKLOOPS 5 /* Maximum number of nak loops */ +#endif + +#ifndef UPAP_DEFTIMEOUT +#define UPAP_DEFTIMEOUT 6 /* Timeout (seconds) for retransmitting req */ +#endif + +#ifndef UPAP_DEFREQTIME +#define UPAP_DEFREQTIME 30 /* Time to wait for auth-req from peer */ +#endif + +#ifndef CHAP_DEFTIMEOUT +#define CHAP_DEFTIMEOUT 6 /* Timeout time in seconds */ +#endif + +#ifndef CHAP_DEFTRANSMITS +#define CHAP_DEFTRANSMITS 10 /* max # times to send challenge */ +#endif + +/* Interval in seconds between keepalive echo requests, 0 to disable. */ +#ifndef LCP_ECHOINTERVAL +#define LCP_ECHOINTERVAL 0 +#endif + +/* Number of unanswered echo requests before failure. */ +#ifndef LCP_MAXECHOFAILS +#define LCP_MAXECHOFAILS 3 +#endif + +/* Max Xmit idle time (in jiffies) before resend flag char. */ +#ifndef PPP_MAXIDLEFLAG +#define PPP_MAXIDLEFLAG 100 +#endif + +/* + * Packet sizes + * + * Note - lcp shouldn't be allowed to negotiate stuff outside these + * limits. See lcp.h in the pppd directory. + * (XXX - these constants should simply be shared by lcp.c instead + * of living in lcp.h) + */ +#define PPP_MTU 1500 /* Default MTU (size of Info field) */ +#ifndef PPP_MAXMTU +/* #define PPP_MAXMTU 65535 - (PPP_HDRLEN + PPP_FCSLEN) */ +#define PPP_MAXMTU 1500 /* Largest MTU we allow */ +#endif +#define PPP_MINMTU 64 +#define PPP_MRU 1500 /* default MRU = max length of info field */ +#define PPP_MAXMRU 1500 /* Largest MRU we allow */ +#ifndef PPP_DEFMRU +#define PPP_DEFMRU 296 /* Try for this */ +#endif +#define PPP_MINMRU 128 /* No MRUs below this */ + +#ifndef MAXNAMELEN +#define MAXNAMELEN 256 /* max length of hostname or name for auth */ +#endif +#ifndef MAXSECRETLEN +#define MAXSECRETLEN 256 /* max length of password or secret */ +#endif + +#endif /* PPP_SUPPORT */ + +/* + -------------------------------------- + ---------- Checksum options ---------- + -------------------------------------- +*/ +/** + * CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets. + */ +#ifndef CHECKSUM_GEN_IP +#define CHECKSUM_GEN_IP 1 +#endif + +/** + * CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets. + */ +#ifndef CHECKSUM_GEN_UDP +#define CHECKSUM_GEN_UDP 1 +#endif + +/** + * CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets. + */ +#ifndef CHECKSUM_GEN_TCP +#define CHECKSUM_GEN_TCP 1 +#endif + +/** + * CHECKSUM_GEN_ICMP==1: Generate checksums in software for outgoing ICMP packets. + */ +#ifndef CHECKSUM_GEN_ICMP +#define CHECKSUM_GEN_ICMP 1 +#endif + +/** + * CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets. + */ +#ifndef CHECKSUM_CHECK_IP +#define CHECKSUM_CHECK_IP 1 +#endif + +/** + * CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets. + */ +#ifndef CHECKSUM_CHECK_UDP +#define CHECKSUM_CHECK_UDP 1 +#endif + +/** + * CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets. + */ +#ifndef CHECKSUM_CHECK_TCP +#define CHECKSUM_CHECK_TCP 1 +#endif + +/** + * LWIP_CHECKSUM_ON_COPY==1: Calculate checksum when copying data from + * application buffers to pbufs. + */ +#ifndef LWIP_CHECKSUM_ON_COPY +#define LWIP_CHECKSUM_ON_COPY 0 +#endif + +/* + --------------------------------------- + ---------- Hook options --------------- + --------------------------------------- +*/ + +/* Hooks are undefined by default, define them to a function if you need them. */ + +/** + * LWIP_HOOK_IP4_INPUT(pbuf, input_netif): + * - called from ip_input() (IPv4) + * - pbuf: received struct pbuf passed to ip_input() + * - input_netif: struct netif on which the packet has been received + * Return values: + * - 0: Hook has not consumed the packet, packet is processed as normal + * - != 0: Hook has consumed the packet. + * If the hook consumed the packet, 'pbuf' is in the responsibility of the hook + * (i.e. free it when done). + */ + +/** + * LWIP_HOOK_IP4_ROUTE(dest): + * - called from ip_route() (IPv4) + * - dest: destination IPv4 address + * Returns the destination netif or NULL if no destination netif is found. In + * that case, ip_route() continues as normal. + */ + +/* + --------------------------------------- + ---------- Debugging options ---------- + --------------------------------------- +*/ +/** + * LWIP_DBG_MIN_LEVEL: After masking, the value of the debug is + * compared against this value. If it is smaller, then debugging + * messages are written. + */ +#ifndef LWIP_DBG_MIN_LEVEL +#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL +#endif + +/** + * LWIP_DBG_TYPES_ON: A mask that can be used to globally enable/disable + * debug messages of certain types. + */ +#ifndef LWIP_DBG_TYPES_ON +#define LWIP_DBG_TYPES_ON LWIP_DBG_ON +#endif + +/** + * ETHARP_DEBUG: Enable debugging in etharp.c. + */ +#ifndef ETHARP_DEBUG +#define ETHARP_DEBUG LWIP_DBG_OFF +#endif + +/** + * NETIF_DEBUG: Enable debugging in netif.c. + */ +#ifndef NETIF_DEBUG +#define NETIF_DEBUG LWIP_DBG_OFF +#endif + +/** + * PBUF_DEBUG: Enable debugging in pbuf.c. + */ +#ifndef PBUF_DEBUG +#define PBUF_DEBUG LWIP_DBG_OFF +#endif + +/** + * API_LIB_DEBUG: Enable debugging in api_lib.c. + */ +#ifndef API_LIB_DEBUG +#define API_LIB_DEBUG LWIP_DBG_OFF +#endif + +/** + * API_MSG_DEBUG: Enable debugging in api_msg.c. + */ +#ifndef API_MSG_DEBUG +#define API_MSG_DEBUG LWIP_DBG_OFF +#endif + +/** + * SOCKETS_DEBUG: Enable debugging in sockets.c. + */ +#ifndef SOCKETS_DEBUG +#define SOCKETS_DEBUG LWIP_DBG_OFF +#endif + +/** + * ICMP_DEBUG: Enable debugging in icmp.c. + */ +#ifndef ICMP_DEBUG +#define ICMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * IGMP_DEBUG: Enable debugging in igmp.c. + */ +#ifndef IGMP_DEBUG +#define IGMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * INET_DEBUG: Enable debugging in inet.c. + */ +#ifndef INET_DEBUG +#define INET_DEBUG LWIP_DBG_OFF +#endif + +/** + * IP_DEBUG: Enable debugging for IP. + */ +#ifndef IP_DEBUG +#define IP_DEBUG LWIP_DBG_OFF +#endif + +/** + * IP_REASS_DEBUG: Enable debugging in ip_frag.c for both frag & reass. + */ +#ifndef IP_REASS_DEBUG +#define IP_REASS_DEBUG LWIP_DBG_OFF +#endif + +/** + * RAW_DEBUG: Enable debugging in raw.c. + */ +#ifndef RAW_DEBUG +#define RAW_DEBUG LWIP_DBG_OFF +#endif + +/** + * MEM_DEBUG: Enable debugging in mem.c. + */ +#ifndef MEM_DEBUG +#define MEM_DEBUG LWIP_DBG_OFF +#endif + +/** + * MEMP_DEBUG: Enable debugging in memp.c. + */ +#ifndef MEMP_DEBUG +#define MEMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * SYS_DEBUG: Enable debugging in sys.c. + */ +#ifndef SYS_DEBUG +#define SYS_DEBUG LWIP_DBG_OFF +#endif + +/** + * TIMERS_DEBUG: Enable debugging in timers.c. + */ +#ifndef TIMERS_DEBUG +#define TIMERS_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_DEBUG: Enable debugging for TCP. + */ +#ifndef TCP_DEBUG +#define TCP_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_INPUT_DEBUG: Enable debugging in tcp_in.c for incoming debug. + */ +#ifndef TCP_INPUT_DEBUG +#define TCP_INPUT_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_FR_DEBUG: Enable debugging in tcp_in.c for fast retransmit. + */ +#ifndef TCP_FR_DEBUG +#define TCP_FR_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_RTO_DEBUG: Enable debugging in TCP for retransmit + * timeout. + */ +#ifndef TCP_RTO_DEBUG +#define TCP_RTO_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_CWND_DEBUG: Enable debugging for TCP congestion window. + */ +#ifndef TCP_CWND_DEBUG +#define TCP_CWND_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_WND_DEBUG: Enable debugging in tcp_in.c for window updating. + */ +#ifndef TCP_WND_DEBUG +#define TCP_WND_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_OUTPUT_DEBUG: Enable debugging in tcp_out.c output functions. + */ +#ifndef TCP_OUTPUT_DEBUG +#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_RST_DEBUG: Enable debugging for TCP with the RST message. + */ +#ifndef TCP_RST_DEBUG +#define TCP_RST_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_QLEN_DEBUG: Enable debugging for TCP queue lengths. + */ +#ifndef TCP_QLEN_DEBUG +#define TCP_QLEN_DEBUG LWIP_DBG_OFF +#endif + +/** + * UDP_DEBUG: Enable debugging in UDP. + */ +#ifndef UDP_DEBUG +#define UDP_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCPIP_DEBUG: Enable debugging in tcpip.c. + */ +#ifndef TCPIP_DEBUG +#define TCPIP_DEBUG LWIP_DBG_OFF +#endif + +/** + * PPP_DEBUG: Enable debugging for PPP. + */ +#ifndef PPP_DEBUG +#define PPP_DEBUG LWIP_DBG_OFF +#endif + +/** + * SLIP_DEBUG: Enable debugging in slipif.c. + */ +#ifndef SLIP_DEBUG +#define SLIP_DEBUG LWIP_DBG_OFF +#endif + +/** + * DHCP_DEBUG: Enable debugging in dhcp.c. + */ +#ifndef DHCP_DEBUG +#define DHCP_DEBUG LWIP_DBG_OFF +#endif + +/** + * AUTOIP_DEBUG: Enable debugging in autoip.c. + */ +#ifndef AUTOIP_DEBUG +#define AUTOIP_DEBUG LWIP_DBG_OFF +#endif + +/** + * SNMP_MSG_DEBUG: Enable debugging for SNMP messages. + */ +#ifndef SNMP_MSG_DEBUG +#define SNMP_MSG_DEBUG LWIP_DBG_OFF +#endif + +/** + * SNMP_MIB_DEBUG: Enable debugging for SNMP MIBs. + */ +#ifndef SNMP_MIB_DEBUG +#define SNMP_MIB_DEBUG LWIP_DBG_OFF +#endif + +/** + * DNS_DEBUG: Enable debugging for DNS. + */ +#ifndef DNS_DEBUG +#define DNS_DEBUG LWIP_DBG_OFF +#endif + +#endif /* __LWIP_OPT_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/pbuf.h b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/pbuf.h new file mode 100644 index 0000000..99d5443 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/pbuf.h @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#ifndef __LWIP_PBUF_H__ +#define __LWIP_PBUF_H__ + +#include "lwip/opt.h" +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Currently, the pbuf_custom code is only needed for one specific configuration + * of IP_FRAG */ +#define LWIP_SUPPORT_CUSTOM_PBUF (IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF) + +#define PBUF_TRANSPORT_HLEN 20 +#define PBUF_IP_HLEN 20 + +typedef enum { + PBUF_TRANSPORT, + PBUF_IP, + PBUF_LINK, + PBUF_RAW +} pbuf_layer; + +typedef enum { + PBUF_RAM, /* pbuf data is stored in RAM */ + PBUF_ROM, /* pbuf data is stored in ROM */ + PBUF_REF, /* pbuf comes from the pbuf pool */ + PBUF_POOL /* pbuf payload refers to RAM */ +} pbuf_type; + + +/** indicates this packet's data should be immediately passed to the application */ +#define PBUF_FLAG_PUSH 0x01U +/** indicates this is a custom pbuf: pbuf_free and pbuf_header handle such a + a pbuf differently */ +#define PBUF_FLAG_IS_CUSTOM 0x02U +/** indicates this pbuf is UDP multicast to be looped back */ +#define PBUF_FLAG_MCASTLOOP 0x04U +/** indicates this pbuf was received as link-level broadcast */ +#define PBUF_FLAG_LLBCAST 0x08U +/** indicates this pbuf was received as link-level multicast */ +#define PBUF_FLAG_LLMCAST 0x10U +/** indicates this pbuf includes a TCP FIN flag */ +#define PBUF_FLAG_TCP_FIN 0x20U + +struct pbuf { + /** next pbuf in singly linked pbuf chain */ + struct pbuf *next; + + /** pointer to the actual data in the buffer */ + void *payload; + + /** + * total length of this buffer and all next buffers in chain + * belonging to the same packet. + * + * For non-queue packet chains this is the invariant: + * p->tot_len == p->len + (p->next? p->next->tot_len: 0) + */ + u16_t tot_len; + + /** length of this buffer */ + u16_t len; + + /** pbuf_type as u8_t instead of enum to save space */ + u8_t /*pbuf_type*/ type; + + /** misc flags */ + u8_t flags; + + /** + * the reference count always equals the number of pointers + * that refer to this pbuf. This can be pointers from an application, + * the stack itself, or pbuf->next pointers from a chain. + */ + u16_t ref; +}; + +#if LWIP_SUPPORT_CUSTOM_PBUF +/** Prototype for a function to free a custom pbuf */ +typedef void (*pbuf_free_custom_fn)(struct pbuf *p); + +/** A custom pbuf: like a pbuf, but following a function pointer to free it. */ +struct pbuf_custom { + /** The actual pbuf */ + struct pbuf pbuf; + /** This function is called when pbuf_free deallocates this pbuf(_custom) */ + pbuf_free_custom_fn custom_free_function; +}; +#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ + +#if LWIP_TCP && TCP_QUEUE_OOSEQ +/** Define this to 0 to prevent freeing ooseq pbufs when the PBUF_POOL is empty */ +#ifndef PBUF_POOL_FREE_OOSEQ +#define PBUF_POOL_FREE_OOSEQ 1 +#endif /* PBUF_POOL_FREE_OOSEQ */ +#if NO_SYS && PBUF_POOL_FREE_OOSEQ +extern volatile u8_t pbuf_free_ooseq_pending; +void pbuf_free_ooseq(); +/** When not using sys_check_timeouts(), call PBUF_CHECK_FREE_OOSEQ() + at regular intervals from main level to check if ooseq pbufs need to be + freed! */ +#define PBUF_CHECK_FREE_OOSEQ() do { if(pbuf_free_ooseq_pending) { \ + /* pbuf_alloc() reported PBUF_POOL to be empty -> try to free some \ + ooseq queued pbufs now */ \ + pbuf_free_ooseq(); }}while(0) +#endif /* NO_SYS && PBUF_POOL_FREE_OOSEQ*/ +#endif /* LWIP_TCP && TCP_QUEUE_OOSEQ */ + +/* Initializes the pbuf module. This call is empty for now, but may not be in future. */ +#define pbuf_init() + +struct pbuf *pbuf_alloc(pbuf_layer l, u16_t length, pbuf_type type); +#if LWIP_SUPPORT_CUSTOM_PBUF +struct pbuf *pbuf_alloced_custom(pbuf_layer l, u16_t length, pbuf_type type, + struct pbuf_custom *p, void *payload_mem, + u16_t payload_mem_len); +#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ +void pbuf_realloc(struct pbuf *p, u16_t size); +u8_t pbuf_header(struct pbuf *p, s16_t header_size); +void pbuf_ref(struct pbuf *p); +u8_t pbuf_free(struct pbuf *p); +u8_t pbuf_clen(struct pbuf *p); +void pbuf_cat(struct pbuf *head, struct pbuf *tail); +void pbuf_chain(struct pbuf *head, struct pbuf *tail); +struct pbuf *pbuf_dechain(struct pbuf *p); +err_t pbuf_copy(struct pbuf *p_to, struct pbuf *p_from); +u16_t pbuf_copy_partial(struct pbuf *p, void *dataptr, u16_t len, u16_t offset); +err_t pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len); +struct pbuf *pbuf_coalesce(struct pbuf *p, pbuf_layer layer); +#if LWIP_CHECKSUM_ON_COPY +err_t pbuf_fill_chksum(struct pbuf *p, u16_t start_offset, const void *dataptr, + u16_t len, u16_t *chksum); +#endif /* LWIP_CHECKSUM_ON_COPY */ + +u8_t pbuf_get_at(struct pbuf* p, u16_t offset); +u16_t pbuf_memcmp(struct pbuf* p, u16_t offset, const void* s2, u16_t n); +u16_t pbuf_memfind(struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset); +u16_t pbuf_strstr(struct pbuf* p, const char* substr); + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_PBUF_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/raw.h b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/raw.h new file mode 100644 index 0000000..17d0a1c --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/raw.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_RAW_H__ +#define __LWIP_RAW_H__ + +#include "lwip/opt.h" + +#if LWIP_RAW /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/def.h" +#include "lwip/ip.h" +#include "lwip/ip_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct raw_pcb; + +/** Function prototype for raw pcb receive callback functions. + * @param arg user supplied argument (raw_pcb.recv_arg) + * @param pcb the raw_pcb which received data + * @param p the packet buffer that was received + * @param addr the remote IP address from which the packet was received + * @return 1 if the packet was 'eaten' (aka. deleted), + * 0 if the packet lives on + * If returning 1, the callback is responsible for freeing the pbuf + * if it's not used any more. + */ +typedef u8_t (*raw_recv_fn)(void *arg, struct raw_pcb *pcb, struct pbuf *p, + ip_addr_t *addr); + +struct raw_pcb { + /* Common members of all PCB types */ + IP_PCB; + + struct raw_pcb *next; + + u8_t protocol; + + /** receive callback function */ + raw_recv_fn recv; + /* user-supplied argument for the recv callback */ + void *recv_arg; +}; + +/* The following functions is the application layer interface to the + RAW code. */ +struct raw_pcb * raw_new (u8_t proto); +void raw_remove (struct raw_pcb *pcb); +err_t raw_bind (struct raw_pcb *pcb, ip_addr_t *ipaddr); +err_t raw_connect (struct raw_pcb *pcb, ip_addr_t *ipaddr); + +void raw_recv (struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg); +err_t raw_sendto (struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr); +err_t raw_send (struct raw_pcb *pcb, struct pbuf *p); + +/* The following functions are the lower layer interface to RAW. */ +u8_t raw_input (struct pbuf *p, struct netif *inp); +#define raw_init() /* Compatibility define, not init needed. */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_RAW */ + +#endif /* __LWIP_RAW_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/sio.h b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/sio.h new file mode 100644 index 0000000..28ae2f2 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/sio.h @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + */ + +/* + * This is the interface to the platform specific serial IO module + * It needs to be implemented by those platforms which need SLIP or PPP + */ + +#ifndef __SIO_H__ +#define __SIO_H__ + +#include "lwip/arch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* If you want to define sio_fd_t elsewhere or differently, + define this in your cc.h file. */ +#ifndef __sio_fd_t_defined +typedef void * sio_fd_t; +#endif + +/* The following functions can be defined to something else in your cc.h file + or be implemented in your custom sio.c file. */ + +#ifndef sio_open +/** + * Opens a serial device for communication. + * + * @param devnum device number + * @return handle to serial device if successful, NULL otherwise + */ +sio_fd_t sio_open(u8_t devnum); +#endif + +#ifndef sio_send +/** + * Sends a single character to the serial device. + * + * @param c character to send + * @param fd serial device handle + * + * @note This function will block until the character can be sent. + */ +void sio_send(u8_t c, sio_fd_t fd); +#endif + +#ifndef sio_recv +/** + * Receives a single character from the serial device. + * + * @param fd serial device handle + * + * @note This function will block until a character is received. + */ +u8_t sio_recv(sio_fd_t fd); +#endif + +#ifndef sio_read +/** + * Reads from the serial device. + * + * @param fd serial device handle + * @param data pointer to data buffer for receiving + * @param len maximum length (in bytes) of data to receive + * @return number of bytes actually received - may be 0 if aborted by sio_read_abort + * + * @note This function will block until data can be received. The blocking + * can be cancelled by calling sio_read_abort(). + */ +u32_t sio_read(sio_fd_t fd, u8_t *data, u32_t len); +#endif + +#ifndef sio_tryread +/** + * Tries to read from the serial device. Same as sio_read but returns + * immediately if no data is available and never blocks. + * + * @param fd serial device handle + * @param data pointer to data buffer for receiving + * @param len maximum length (in bytes) of data to receive + * @return number of bytes actually received + */ +u32_t sio_tryread(sio_fd_t fd, u8_t *data, u32_t len); +#endif + +#ifndef sio_write +/** + * Writes to the serial device. + * + * @param fd serial device handle + * @param data pointer to data to send + * @param len length (in bytes) of data to send + * @return number of bytes actually sent + * + * @note This function will block until all data can be sent. + */ +u32_t sio_write(sio_fd_t fd, u8_t *data, u32_t len); +#endif + +#ifndef sio_read_abort +/** + * Aborts a blocking sio_read() call. + * + * @param fd serial device handle + */ +void sio_read_abort(sio_fd_t fd); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __SIO_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/snmp.h b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/snmp.h new file mode 100644 index 0000000..2ed043d --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/snmp.h @@ -0,0 +1,367 @@ +/* + * Copyright (c) 2001, 2002 Leon Woestenberg + * Copyright (c) 2001, 2002 Axon Digital Design B.V., The Netherlands. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Leon Woestenberg + * + */ +#ifndef __LWIP_SNMP_H__ +#define __LWIP_SNMP_H__ + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include "lwip/ip_addr.h" + +struct udp_pcb; +struct netif; + +/** + * @see RFC1213, "MIB-II, 6. Definitions" + */ +enum snmp_ifType { + snmp_ifType_other=1, /* none of the following */ + snmp_ifType_regular1822, + snmp_ifType_hdh1822, + snmp_ifType_ddn_x25, + snmp_ifType_rfc877_x25, + snmp_ifType_ethernet_csmacd, + snmp_ifType_iso88023_csmacd, + snmp_ifType_iso88024_tokenBus, + snmp_ifType_iso88025_tokenRing, + snmp_ifType_iso88026_man, + snmp_ifType_starLan, + snmp_ifType_proteon_10Mbit, + snmp_ifType_proteon_80Mbit, + snmp_ifType_hyperchannel, + snmp_ifType_fddi, + snmp_ifType_lapb, + snmp_ifType_sdlc, + snmp_ifType_ds1, /* T-1 */ + snmp_ifType_e1, /* european equiv. of T-1 */ + snmp_ifType_basicISDN, + snmp_ifType_primaryISDN, /* proprietary serial */ + snmp_ifType_propPointToPointSerial, + snmp_ifType_ppp, + snmp_ifType_softwareLoopback, + snmp_ifType_eon, /* CLNP over IP [11] */ + snmp_ifType_ethernet_3Mbit, + snmp_ifType_nsip, /* XNS over IP */ + snmp_ifType_slip, /* generic SLIP */ + snmp_ifType_ultra, /* ULTRA technologies */ + snmp_ifType_ds3, /* T-3 */ + snmp_ifType_sip, /* SMDS */ + snmp_ifType_frame_relay +}; + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +/** SNMP "sysuptime" Interval */ +#define SNMP_SYSUPTIME_INTERVAL 10 + +/** fixed maximum length for object identifier type */ +#define LWIP_SNMP_OBJ_ID_LEN 32 + +/** internal object identifier representation */ +struct snmp_obj_id +{ + u8_t len; + s32_t id[LWIP_SNMP_OBJ_ID_LEN]; +}; + +/* system */ +void snmp_set_sysdesr(u8_t* str, u8_t* len); +void snmp_set_sysobjid(struct snmp_obj_id *oid); +void snmp_get_sysobjid_ptr(struct snmp_obj_id **oid); +void snmp_inc_sysuptime(void); +void snmp_add_sysuptime(u32_t value); +void snmp_get_sysuptime(u32_t *value); +void snmp_set_syscontact(u8_t *ocstr, u8_t *ocstrlen); +void snmp_set_sysname(u8_t *ocstr, u8_t *ocstrlen); +void snmp_set_syslocation(u8_t *ocstr, u8_t *ocstrlen); + +/* network interface */ +void snmp_add_ifinoctets(struct netif *ni, u32_t value); +void snmp_inc_ifinucastpkts(struct netif *ni); +void snmp_inc_ifinnucastpkts(struct netif *ni); +void snmp_inc_ifindiscards(struct netif *ni); +void snmp_add_ifoutoctets(struct netif *ni, u32_t value); +void snmp_inc_ifoutucastpkts(struct netif *ni); +void snmp_inc_ifoutnucastpkts(struct netif *ni); +void snmp_inc_ifoutdiscards(struct netif *ni); +void snmp_inc_iflist(void); +void snmp_dec_iflist(void); + +/* ARP (for atTable and ipNetToMediaTable) */ +void snmp_insert_arpidx_tree(struct netif *ni, ip_addr_t *ip); +void snmp_delete_arpidx_tree(struct netif *ni, ip_addr_t *ip); + +/* IP */ +void snmp_inc_ipinreceives(void); +void snmp_inc_ipinhdrerrors(void); +void snmp_inc_ipinaddrerrors(void); +void snmp_inc_ipforwdatagrams(void); +void snmp_inc_ipinunknownprotos(void); +void snmp_inc_ipindiscards(void); +void snmp_inc_ipindelivers(void); +void snmp_inc_ipoutrequests(void); +void snmp_inc_ipoutdiscards(void); +void snmp_inc_ipoutnoroutes(void); +void snmp_inc_ipreasmreqds(void); +void snmp_inc_ipreasmoks(void); +void snmp_inc_ipreasmfails(void); +void snmp_inc_ipfragoks(void); +void snmp_inc_ipfragfails(void); +void snmp_inc_ipfragcreates(void); +void snmp_inc_iproutingdiscards(void); +void snmp_insert_ipaddridx_tree(struct netif *ni); +void snmp_delete_ipaddridx_tree(struct netif *ni); +void snmp_insert_iprteidx_tree(u8_t dflt, struct netif *ni); +void snmp_delete_iprteidx_tree(u8_t dflt, struct netif *ni); + +/* ICMP */ +void snmp_inc_icmpinmsgs(void); +void snmp_inc_icmpinerrors(void); +void snmp_inc_icmpindestunreachs(void); +void snmp_inc_icmpintimeexcds(void); +void snmp_inc_icmpinparmprobs(void); +void snmp_inc_icmpinsrcquenchs(void); +void snmp_inc_icmpinredirects(void); +void snmp_inc_icmpinechos(void); +void snmp_inc_icmpinechoreps(void); +void snmp_inc_icmpintimestamps(void); +void snmp_inc_icmpintimestampreps(void); +void snmp_inc_icmpinaddrmasks(void); +void snmp_inc_icmpinaddrmaskreps(void); +void snmp_inc_icmpoutmsgs(void); +void snmp_inc_icmpouterrors(void); +void snmp_inc_icmpoutdestunreachs(void); +void snmp_inc_icmpouttimeexcds(void); +void snmp_inc_icmpoutparmprobs(void); +void snmp_inc_icmpoutsrcquenchs(void); +void snmp_inc_icmpoutredirects(void); +void snmp_inc_icmpoutechos(void); +void snmp_inc_icmpoutechoreps(void); +void snmp_inc_icmpouttimestamps(void); +void snmp_inc_icmpouttimestampreps(void); +void snmp_inc_icmpoutaddrmasks(void); +void snmp_inc_icmpoutaddrmaskreps(void); + +/* TCP */ +void snmp_inc_tcpactiveopens(void); +void snmp_inc_tcppassiveopens(void); +void snmp_inc_tcpattemptfails(void); +void snmp_inc_tcpestabresets(void); +void snmp_inc_tcpinsegs(void); +void snmp_inc_tcpoutsegs(void); +void snmp_inc_tcpretranssegs(void); +void snmp_inc_tcpinerrs(void); +void snmp_inc_tcpoutrsts(void); + +/* UDP */ +void snmp_inc_udpindatagrams(void); +void snmp_inc_udpnoports(void); +void snmp_inc_udpinerrors(void); +void snmp_inc_udpoutdatagrams(void); +void snmp_insert_udpidx_tree(struct udp_pcb *pcb); +void snmp_delete_udpidx_tree(struct udp_pcb *pcb); + +/* SNMP */ +void snmp_inc_snmpinpkts(void); +void snmp_inc_snmpoutpkts(void); +void snmp_inc_snmpinbadversions(void); +void snmp_inc_snmpinbadcommunitynames(void); +void snmp_inc_snmpinbadcommunityuses(void); +void snmp_inc_snmpinasnparseerrs(void); +void snmp_inc_snmpintoobigs(void); +void snmp_inc_snmpinnosuchnames(void); +void snmp_inc_snmpinbadvalues(void); +void snmp_inc_snmpinreadonlys(void); +void snmp_inc_snmpingenerrs(void); +void snmp_add_snmpintotalreqvars(u8_t value); +void snmp_add_snmpintotalsetvars(u8_t value); +void snmp_inc_snmpingetrequests(void); +void snmp_inc_snmpingetnexts(void); +void snmp_inc_snmpinsetrequests(void); +void snmp_inc_snmpingetresponses(void); +void snmp_inc_snmpintraps(void); +void snmp_inc_snmpouttoobigs(void); +void snmp_inc_snmpoutnosuchnames(void); +void snmp_inc_snmpoutbadvalues(void); +void snmp_inc_snmpoutgenerrs(void); +void snmp_inc_snmpoutgetrequests(void); +void snmp_inc_snmpoutgetnexts(void); +void snmp_inc_snmpoutsetrequests(void); +void snmp_inc_snmpoutgetresponses(void); +void snmp_inc_snmpouttraps(void); +void snmp_get_snmpgrpid_ptr(struct snmp_obj_id **oid); +void snmp_set_snmpenableauthentraps(u8_t *value); +void snmp_get_snmpenableauthentraps(u8_t *value); + +/* LWIP_SNMP support not available */ +/* define everything to be empty */ +#else + +/* system */ +#define snmp_set_sysdesr(str, len) +#define snmp_set_sysobjid(oid); +#define snmp_get_sysobjid_ptr(oid) +#define snmp_inc_sysuptime() +#define snmp_add_sysuptime(value) +#define snmp_get_sysuptime(value) +#define snmp_set_syscontact(ocstr, ocstrlen); +#define snmp_set_sysname(ocstr, ocstrlen); +#define snmp_set_syslocation(ocstr, ocstrlen); + +/* network interface */ +#define snmp_add_ifinoctets(ni,value) +#define snmp_inc_ifinucastpkts(ni) +#define snmp_inc_ifinnucastpkts(ni) +#define snmp_inc_ifindiscards(ni) +#define snmp_add_ifoutoctets(ni,value) +#define snmp_inc_ifoutucastpkts(ni) +#define snmp_inc_ifoutnucastpkts(ni) +#define snmp_inc_ifoutdiscards(ni) +#define snmp_inc_iflist() +#define snmp_dec_iflist() + +/* ARP */ +#define snmp_insert_arpidx_tree(ni,ip) +#define snmp_delete_arpidx_tree(ni,ip) + +/* IP */ +#define snmp_inc_ipinreceives() +#define snmp_inc_ipinhdrerrors() +#define snmp_inc_ipinaddrerrors() +#define snmp_inc_ipforwdatagrams() +#define snmp_inc_ipinunknownprotos() +#define snmp_inc_ipindiscards() +#define snmp_inc_ipindelivers() +#define snmp_inc_ipoutrequests() +#define snmp_inc_ipoutdiscards() +#define snmp_inc_ipoutnoroutes() +#define snmp_inc_ipreasmreqds() +#define snmp_inc_ipreasmoks() +#define snmp_inc_ipreasmfails() +#define snmp_inc_ipfragoks() +#define snmp_inc_ipfragfails() +#define snmp_inc_ipfragcreates() +#define snmp_inc_iproutingdiscards() +#define snmp_insert_ipaddridx_tree(ni) +#define snmp_delete_ipaddridx_tree(ni) +#define snmp_insert_iprteidx_tree(dflt, ni) +#define snmp_delete_iprteidx_tree(dflt, ni) + +/* ICMP */ +#define snmp_inc_icmpinmsgs() +#define snmp_inc_icmpinerrors() +#define snmp_inc_icmpindestunreachs() +#define snmp_inc_icmpintimeexcds() +#define snmp_inc_icmpinparmprobs() +#define snmp_inc_icmpinsrcquenchs() +#define snmp_inc_icmpinredirects() +#define snmp_inc_icmpinechos() +#define snmp_inc_icmpinechoreps() +#define snmp_inc_icmpintimestamps() +#define snmp_inc_icmpintimestampreps() +#define snmp_inc_icmpinaddrmasks() +#define snmp_inc_icmpinaddrmaskreps() +#define snmp_inc_icmpoutmsgs() +#define snmp_inc_icmpouterrors() +#define snmp_inc_icmpoutdestunreachs() +#define snmp_inc_icmpouttimeexcds() +#define snmp_inc_icmpoutparmprobs() +#define snmp_inc_icmpoutsrcquenchs() +#define snmp_inc_icmpoutredirects() +#define snmp_inc_icmpoutechos() +#define snmp_inc_icmpoutechoreps() +#define snmp_inc_icmpouttimestamps() +#define snmp_inc_icmpouttimestampreps() +#define snmp_inc_icmpoutaddrmasks() +#define snmp_inc_icmpoutaddrmaskreps() +/* TCP */ +#define snmp_inc_tcpactiveopens() +#define snmp_inc_tcppassiveopens() +#define snmp_inc_tcpattemptfails() +#define snmp_inc_tcpestabresets() +#define snmp_inc_tcpinsegs() +#define snmp_inc_tcpoutsegs() +#define snmp_inc_tcpretranssegs() +#define snmp_inc_tcpinerrs() +#define snmp_inc_tcpoutrsts() + +/* UDP */ +#define snmp_inc_udpindatagrams() +#define snmp_inc_udpnoports() +#define snmp_inc_udpinerrors() +#define snmp_inc_udpoutdatagrams() +#define snmp_insert_udpidx_tree(pcb) +#define snmp_delete_udpidx_tree(pcb) + +/* SNMP */ +#define snmp_inc_snmpinpkts() +#define snmp_inc_snmpoutpkts() +#define snmp_inc_snmpinbadversions() +#define snmp_inc_snmpinbadcommunitynames() +#define snmp_inc_snmpinbadcommunityuses() +#define snmp_inc_snmpinasnparseerrs() +#define snmp_inc_snmpintoobigs() +#define snmp_inc_snmpinnosuchnames() +#define snmp_inc_snmpinbadvalues() +#define snmp_inc_snmpinreadonlys() +#define snmp_inc_snmpingenerrs() +#define snmp_add_snmpintotalreqvars(value) +#define snmp_add_snmpintotalsetvars(value) +#define snmp_inc_snmpingetrequests() +#define snmp_inc_snmpingetnexts() +#define snmp_inc_snmpinsetrequests() +#define snmp_inc_snmpingetresponses() +#define snmp_inc_snmpintraps() +#define snmp_inc_snmpouttoobigs() +#define snmp_inc_snmpoutnosuchnames() +#define snmp_inc_snmpoutbadvalues() +#define snmp_inc_snmpoutgenerrs() +#define snmp_inc_snmpoutgetrequests() +#define snmp_inc_snmpoutgetnexts() +#define snmp_inc_snmpoutsetrequests() +#define snmp_inc_snmpoutgetresponses() +#define snmp_inc_snmpouttraps() +#define snmp_get_snmpgrpid_ptr(oid) +#define snmp_set_snmpenableauthentraps(value) +#define snmp_get_snmpenableauthentraps(value) + +#endif /* LWIP_SNMP */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_SNMP_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/snmp_asn1.h b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/snmp_asn1.h new file mode 100644 index 0000000..605fa3f --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/snmp_asn1.h @@ -0,0 +1,101 @@ +/** + * @file + * Abstract Syntax Notation One (ISO 8824, 8825) codec. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * Author: Christiaan Simons + */ + +#ifndef __LWIP_SNMP_ASN1_H__ +#define __LWIP_SNMP_ASN1_H__ + +#include "lwip/opt.h" +#include "lwip/err.h" +#include "lwip/pbuf.h" +#include "lwip/snmp.h" + +#if LWIP_SNMP + +#ifdef __cplusplus +extern "C" { +#endif + +#define SNMP_ASN1_UNIV (0) /* (!0x80 | !0x40) */ +#define SNMP_ASN1_APPLIC (0x40) /* (!0x80 | 0x40) */ +#define SNMP_ASN1_CONTXT (0x80) /* ( 0x80 | !0x40) */ + +#define SNMP_ASN1_CONSTR (0x20) /* ( 0x20) */ +#define SNMP_ASN1_PRIMIT (0) /* (!0x20) */ + +/* universal tags */ +#define SNMP_ASN1_INTEG 2 +#define SNMP_ASN1_OC_STR 4 +#define SNMP_ASN1_NUL 5 +#define SNMP_ASN1_OBJ_ID 6 +#define SNMP_ASN1_SEQ 16 + +/* application specific (SNMP) tags */ +#define SNMP_ASN1_IPADDR 0 /* octet string size(4) */ +#define SNMP_ASN1_COUNTER 1 /* u32_t */ +#define SNMP_ASN1_GAUGE 2 /* u32_t */ +#define SNMP_ASN1_TIMETICKS 3 /* u32_t */ +#define SNMP_ASN1_OPAQUE 4 /* octet string */ + +/* context specific (SNMP) tags */ +#define SNMP_ASN1_PDU_GET_REQ 0 +#define SNMP_ASN1_PDU_GET_NEXT_REQ 1 +#define SNMP_ASN1_PDU_GET_RESP 2 +#define SNMP_ASN1_PDU_SET_REQ 3 +#define SNMP_ASN1_PDU_TRAP 4 + +err_t snmp_asn1_dec_type(struct pbuf *p, u16_t ofs, u8_t *type); +err_t snmp_asn1_dec_length(struct pbuf *p, u16_t ofs, u8_t *octets_used, u16_t *length); +err_t snmp_asn1_dec_u32t(struct pbuf *p, u16_t ofs, u16_t len, u32_t *value); +err_t snmp_asn1_dec_s32t(struct pbuf *p, u16_t ofs, u16_t len, s32_t *value); +err_t snmp_asn1_dec_oid(struct pbuf *p, u16_t ofs, u16_t len, struct snmp_obj_id *oid); +err_t snmp_asn1_dec_raw(struct pbuf *p, u16_t ofs, u16_t len, u16_t raw_len, u8_t *raw); + +void snmp_asn1_enc_length_cnt(u16_t length, u8_t *octets_needed); +void snmp_asn1_enc_u32t_cnt(u32_t value, u16_t *octets_needed); +void snmp_asn1_enc_s32t_cnt(s32_t value, u16_t *octets_needed); +void snmp_asn1_enc_oid_cnt(u8_t ident_len, s32_t *ident, u16_t *octets_needed); +err_t snmp_asn1_enc_type(struct pbuf *p, u16_t ofs, u8_t type); +err_t snmp_asn1_enc_length(struct pbuf *p, u16_t ofs, u16_t length); +err_t snmp_asn1_enc_u32t(struct pbuf *p, u16_t ofs, u16_t octets_needed, u32_t value); +err_t snmp_asn1_enc_s32t(struct pbuf *p, u16_t ofs, u16_t octets_needed, s32_t value); +err_t snmp_asn1_enc_oid(struct pbuf *p, u16_t ofs, u8_t ident_len, s32_t *ident); +err_t snmp_asn1_enc_raw(struct pbuf *p, u16_t ofs, u16_t raw_len, u8_t *raw); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SNMP */ + +#endif /* __LWIP_SNMP_ASN1_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/snmp_msg.h b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/snmp_msg.h new file mode 100644 index 0000000..1183e3a --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/snmp_msg.h @@ -0,0 +1,315 @@ +/** + * @file + * SNMP Agent message handling structures. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * Author: Christiaan Simons + */ + +#ifndef __LWIP_SNMP_MSG_H__ +#define __LWIP_SNMP_MSG_H__ + +#include "lwip/opt.h" +#include "lwip/snmp.h" +#include "lwip/snmp_structs.h" +#include "lwip/ip_addr.h" +#include "lwip/err.h" + +#if LWIP_SNMP + +#if SNMP_PRIVATE_MIB +/* When using a private MIB, you have to create a file 'private_mib.h' that contains + * a 'struct mib_array_node mib_private' which contains your MIB. */ +#include "private_mib.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* The listen port of the SNMP agent. Clients have to make their requests to + this port. Most standard clients won't work if you change this! */ +#ifndef SNMP_IN_PORT +#define SNMP_IN_PORT 161 +#endif +/* The remote port the SNMP agent sends traps to. Most standard trap sinks won't + work if you change this! */ +#ifndef SNMP_TRAP_PORT +#define SNMP_TRAP_PORT 162 +#endif + +#define SNMP_ES_NOERROR 0 +#define SNMP_ES_TOOBIG 1 +#define SNMP_ES_NOSUCHNAME 2 +#define SNMP_ES_BADVALUE 3 +#define SNMP_ES_READONLY 4 +#define SNMP_ES_GENERROR 5 + +#define SNMP_GENTRAP_COLDSTART 0 +#define SNMP_GENTRAP_WARMSTART 1 +#define SNMP_GENTRAP_AUTHFAIL 4 +#define SNMP_GENTRAP_ENTERPRISESPC 6 + +struct snmp_varbind +{ + /* next pointer, NULL for last in list */ + struct snmp_varbind *next; + /* previous pointer, NULL for first in list */ + struct snmp_varbind *prev; + + /* object identifier length (in s32_t) */ + u8_t ident_len; + /* object identifier array */ + s32_t *ident; + + /* object value ASN1 type */ + u8_t value_type; + /* object value length (in u8_t) */ + u8_t value_len; + /* object value */ + void *value; + + /* encoding varbind seq length length */ + u8_t seqlenlen; + /* encoding object identifier length length */ + u8_t olenlen; + /* encoding object value length length */ + u8_t vlenlen; + /* encoding varbind seq length */ + u16_t seqlen; + /* encoding object identifier length */ + u16_t olen; + /* encoding object value length */ + u16_t vlen; +}; + +struct snmp_varbind_root +{ + struct snmp_varbind *head; + struct snmp_varbind *tail; + /* number of variable bindings in list */ + u8_t count; + /* encoding varbind-list seq length length */ + u8_t seqlenlen; + /* encoding varbind-list seq length */ + u16_t seqlen; +}; + +/** output response message header length fields */ +struct snmp_resp_header_lengths +{ + /* encoding error-index length length */ + u8_t erridxlenlen; + /* encoding error-status length length */ + u8_t errstatlenlen; + /* encoding request id length length */ + u8_t ridlenlen; + /* encoding pdu length length */ + u8_t pdulenlen; + /* encoding community length length */ + u8_t comlenlen; + /* encoding version length length */ + u8_t verlenlen; + /* encoding sequence length length */ + u8_t seqlenlen; + + /* encoding error-index length */ + u16_t erridxlen; + /* encoding error-status length */ + u16_t errstatlen; + /* encoding request id length */ + u16_t ridlen; + /* encoding pdu length */ + u16_t pdulen; + /* encoding community length */ + u16_t comlen; + /* encoding version length */ + u16_t verlen; + /* encoding sequence length */ + u16_t seqlen; +}; + +/** output response message header length fields */ +struct snmp_trap_header_lengths +{ + /* encoding timestamp length length */ + u8_t tslenlen; + /* encoding specific-trap length length */ + u8_t strplenlen; + /* encoding generic-trap length length */ + u8_t gtrplenlen; + /* encoding agent-addr length length */ + u8_t aaddrlenlen; + /* encoding enterprise-id length length */ + u8_t eidlenlen; + /* encoding pdu length length */ + u8_t pdulenlen; + /* encoding community length length */ + u8_t comlenlen; + /* encoding version length length */ + u8_t verlenlen; + /* encoding sequence length length */ + u8_t seqlenlen; + + /* encoding timestamp length */ + u16_t tslen; + /* encoding specific-trap length */ + u16_t strplen; + /* encoding generic-trap length */ + u16_t gtrplen; + /* encoding agent-addr length */ + u16_t aaddrlen; + /* encoding enterprise-id length */ + u16_t eidlen; + /* encoding pdu length */ + u16_t pdulen; + /* encoding community length */ + u16_t comlen; + /* encoding version length */ + u16_t verlen; + /* encoding sequence length */ + u16_t seqlen; +}; + +/* Accepting new SNMP messages. */ +#define SNMP_MSG_EMPTY 0 +/* Search for matching object for variable binding. */ +#define SNMP_MSG_SEARCH_OBJ 1 +/* Perform SNMP operation on in-memory object. + Pass-through states, for symmetry only. */ +#define SNMP_MSG_INTERNAL_GET_OBJDEF 2 +#define SNMP_MSG_INTERNAL_GET_VALUE 3 +#define SNMP_MSG_INTERNAL_SET_TEST 4 +#define SNMP_MSG_INTERNAL_GET_OBJDEF_S 5 +#define SNMP_MSG_INTERNAL_SET_VALUE 6 +/* Perform SNMP operation on object located externally. + In theory this could be used for building a proxy agent. + Practical use is for an enterprise spc. app. gateway. */ +#define SNMP_MSG_EXTERNAL_GET_OBJDEF 7 +#define SNMP_MSG_EXTERNAL_GET_VALUE 8 +#define SNMP_MSG_EXTERNAL_SET_TEST 9 +#define SNMP_MSG_EXTERNAL_GET_OBJDEF_S 10 +#define SNMP_MSG_EXTERNAL_SET_VALUE 11 + +#define SNMP_COMMUNITY_STR_LEN 64 +struct snmp_msg_pstat +{ + /* lwIP local port (161) binding */ + struct udp_pcb *pcb; + /* source IP address */ + ip_addr_t sip; + /* source UDP port */ + u16_t sp; + /* request type */ + u8_t rt; + /* request ID */ + s32_t rid; + /* error status */ + s32_t error_status; + /* error index */ + s32_t error_index; + /* community name (zero terminated) */ + u8_t community[SNMP_COMMUNITY_STR_LEN + 1]; + /* community string length (exclusive zero term) */ + u8_t com_strlen; + /* one out of MSG_EMPTY, MSG_DEMUX, MSG_INTERNAL, MSG_EXTERNAL_x */ + u8_t state; + /* saved arguments for MSG_EXTERNAL_x */ + struct mib_external_node *ext_mib_node; + struct snmp_name_ptr ext_name_ptr; + struct obj_def ext_object_def; + struct snmp_obj_id ext_oid; + /* index into input variable binding list */ + u8_t vb_idx; + /* ptr into input variable binding list */ + struct snmp_varbind *vb_ptr; + /* list of variable bindings from input */ + struct snmp_varbind_root invb; + /* list of variable bindings to output */ + struct snmp_varbind_root outvb; + /* output response lengths used in ASN encoding */ + struct snmp_resp_header_lengths rhl; +}; + +struct snmp_msg_trap +{ + /* lwIP local port (161) binding */ + struct udp_pcb *pcb; + /* destination IP address in network order */ + ip_addr_t dip; + + /* source enterprise ID (sysObjectID) */ + struct snmp_obj_id *enterprise; + /* source IP address, raw network order format */ + u8_t sip_raw[4]; + /* generic trap code */ + u32_t gen_trap; + /* specific trap code */ + u32_t spc_trap; + /* timestamp */ + u32_t ts; + /* list of variable bindings to output */ + struct snmp_varbind_root outvb; + /* output trap lengths used in ASN encoding */ + struct snmp_trap_header_lengths thl; +}; + +/** Agent Version constant, 0 = v1 oddity */ +extern const s32_t snmp_version; +/** Agent default "public" community string */ +extern const char snmp_publiccommunity[7]; + +extern struct snmp_msg_trap trap_msg; + +/** Agent setup, start listening to port 161. */ +void snmp_init(void); +void snmp_trap_dst_enable(u8_t dst_idx, u8_t enable); +void snmp_trap_dst_ip_set(u8_t dst_idx, ip_addr_t *dst); + +/** Varbind-list functions. */ +struct snmp_varbind* snmp_varbind_alloc(struct snmp_obj_id *oid, u8_t type, u8_t len); +void snmp_varbind_free(struct snmp_varbind *vb); +void snmp_varbind_list_free(struct snmp_varbind_root *root); +void snmp_varbind_tail_add(struct snmp_varbind_root *root, struct snmp_varbind *vb); +struct snmp_varbind* snmp_varbind_tail_remove(struct snmp_varbind_root *root); + +/** Handle an internal (recv) or external (private response) event. */ +void snmp_msg_event(u8_t request_id); +err_t snmp_send_response(struct snmp_msg_pstat *m_stat); +err_t snmp_send_trap(s8_t generic_trap, struct snmp_obj_id *eoid, s32_t specific_trap); +void snmp_coldstart_trap(void); +void snmp_authfail_trap(void); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SNMP */ + +#endif /* __LWIP_SNMP_MSG_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/snmp_structs.h b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/snmp_structs.h new file mode 100644 index 0000000..0d3b46a --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/snmp_structs.h @@ -0,0 +1,268 @@ +/** + * @file + * Generic MIB tree structures. + * + * @todo namespace prefixes + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * Author: Christiaan Simons + */ + +#ifndef __LWIP_SNMP_STRUCTS_H__ +#define __LWIP_SNMP_STRUCTS_H__ + +#include "lwip/opt.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/snmp.h" + +#if SNMP_PRIVATE_MIB +/* When using a private MIB, you have to create a file 'private_mib.h' that contains + * a 'struct mib_array_node mib_private' which contains your MIB. */ +#include "private_mib.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* MIB object instance */ +#define MIB_OBJECT_NONE 0 +#define MIB_OBJECT_SCALAR 1 +#define MIB_OBJECT_TAB 2 + +/* MIB access types */ +#define MIB_ACCESS_READ 1 +#define MIB_ACCESS_WRITE 2 + +/* MIB object access */ +#define MIB_OBJECT_READ_ONLY MIB_ACCESS_READ +#define MIB_OBJECT_READ_WRITE (MIB_ACCESS_READ | MIB_ACCESS_WRITE) +#define MIB_OBJECT_WRITE_ONLY MIB_ACCESS_WRITE +#define MIB_OBJECT_NOT_ACCESSIBLE 0 + +/** object definition returned by (get_object_def)() */ +struct obj_def +{ + /* MIB_OBJECT_NONE (0), MIB_OBJECT_SCALAR (1), MIB_OBJECT_TAB (2) */ + u8_t instance; + /* 0 read-only, 1 read-write, 2 write-only, 3 not-accessible */ + u8_t access; + /* ASN type for this object */ + u8_t asn_type; + /* value length (host length) */ + u16_t v_len; + /* length of instance part of supplied object identifier */ + u8_t id_inst_len; + /* instance part of supplied object identifier */ + s32_t *id_inst_ptr; +}; + +struct snmp_name_ptr +{ + u8_t ident_len; + s32_t *ident; +}; + +/** MIB const scalar (.0) node */ +#define MIB_NODE_SC 0x01 +/** MIB const array node */ +#define MIB_NODE_AR 0x02 +/** MIB array node (mem_malloced from RAM) */ +#define MIB_NODE_RA 0x03 +/** MIB list root node (mem_malloced from RAM) */ +#define MIB_NODE_LR 0x04 +/** MIB node for external objects */ +#define MIB_NODE_EX 0x05 + +/** node "base class" layout, the mandatory fields for a node */ +struct mib_node +{ + /** returns struct obj_def for the given object identifier */ + void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od); + /** returns object value for the given object identifier, + @note the caller must allocate at least len bytes for the value */ + void (*get_value)(struct obj_def *od, u16_t len, void *value); + /** tests length and/or range BEFORE setting */ + u8_t (*set_test)(struct obj_def *od, u16_t len, void *value); + /** sets object value, only to be called when set_test() */ + void (*set_value)(struct obj_def *od, u16_t len, void *value); + /** One out of MIB_NODE_AR, MIB_NODE_LR or MIB_NODE_EX */ + u8_t node_type; + /* array or max list length */ + u16_t maxlength; +}; + +/** derived node for scalars .0 index */ +typedef struct mib_node mib_scalar_node; + +/** derived node, points to a fixed size const array + of sub-identifiers plus a 'child' pointer */ +struct mib_array_node +{ + /* inherited "base class" members */ + void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od); + void (*get_value)(struct obj_def *od, u16_t len, void *value); + u8_t (*set_test)(struct obj_def *od, u16_t len, void *value); + void (*set_value)(struct obj_def *od, u16_t len, void *value); + + u8_t node_type; + u16_t maxlength; + + /* additional struct members */ + const s32_t *objid; + struct mib_node* const *nptr; +}; + +/** derived node, points to a fixed size mem_malloced array + of sub-identifiers plus a 'child' pointer */ +struct mib_ram_array_node +{ + /* inherited "base class" members */ + void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od); + void (*get_value)(struct obj_def *od, u16_t len, void *value); + u8_t (*set_test)(struct obj_def *od, u16_t len, void *value); + void (*set_value)(struct obj_def *od, u16_t len, void *value); + + u8_t node_type; + u16_t maxlength; + + /* aditional struct members */ + s32_t *objid; + struct mib_node **nptr; +}; + +struct mib_list_node +{ + struct mib_list_node *prev; + struct mib_list_node *next; + s32_t objid; + struct mib_node *nptr; +}; + +/** derived node, points to a doubly linked list + of sub-identifiers plus a 'child' pointer */ +struct mib_list_rootnode +{ + /* inherited "base class" members */ + void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od); + void (*get_value)(struct obj_def *od, u16_t len, void *value); + u8_t (*set_test)(struct obj_def *od, u16_t len, void *value); + void (*set_value)(struct obj_def *od, u16_t len, void *value); + + u8_t node_type; + u16_t maxlength; + + /* additional struct members */ + struct mib_list_node *head; + struct mib_list_node *tail; + /* counts list nodes in list */ + u16_t count; +}; + +/** derived node, has access functions for mib object in external memory or device + using 'tree_level' and 'idx', with a range 0 .. (level_length() - 1) */ +struct mib_external_node +{ + /* inherited "base class" members */ + void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od); + void (*get_value)(struct obj_def *od, u16_t len, void *value); + u8_t (*set_test)(struct obj_def *od, u16_t len, void *value); + void (*set_value)(struct obj_def *od, u16_t len, void *value); + + u8_t node_type; + u16_t maxlength; + + /* additional struct members */ + /** points to an external (in memory) record of some sort of addressing + information, passed to and interpreted by the funtions below */ + void* addr_inf; + /** tree levels under this node */ + u8_t tree_levels; + /** number of objects at this level */ + u16_t (*level_length)(void* addr_inf, u8_t level); + /** compares object sub identifier with external id + return zero when equal, nonzero when unequal */ + s32_t (*ident_cmp)(void* addr_inf, u8_t level, u16_t idx, s32_t sub_id); + void (*get_objid)(void* addr_inf, u8_t level, u16_t idx, s32_t *sub_id); + + /** async Questions */ + void (*get_object_def_q)(void* addr_inf, u8_t rid, u8_t ident_len, s32_t *ident); + void (*get_value_q)(u8_t rid, struct obj_def *od); + void (*set_test_q)(u8_t rid, struct obj_def *od); + void (*set_value_q)(u8_t rid, struct obj_def *od, u16_t len, void *value); + /** async Answers */ + void (*get_object_def_a)(u8_t rid, u8_t ident_len, s32_t *ident, struct obj_def *od); + void (*get_value_a)(u8_t rid, struct obj_def *od, u16_t len, void *value); + u8_t (*set_test_a)(u8_t rid, struct obj_def *od, u16_t len, void *value); + void (*set_value_a)(u8_t rid, struct obj_def *od, u16_t len, void *value); + /** async Panic Close (agent returns error reply, + e.g. used for external transaction cleanup) */ + void (*get_object_def_pc)(u8_t rid, u8_t ident_len, s32_t *ident); + void (*get_value_pc)(u8_t rid, struct obj_def *od); + void (*set_test_pc)(u8_t rid, struct obj_def *od); + void (*set_value_pc)(u8_t rid, struct obj_def *od); +}; + +/** export MIB tree from mib2.c */ +extern const struct mib_array_node internet; + +/** dummy function pointers for non-leaf MIB nodes from mib2.c */ +void noleafs_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +void noleafs_get_value(struct obj_def *od, u16_t len, void *value); +u8_t noleafs_set_test(struct obj_def *od, u16_t len, void *value); +void noleafs_set_value(struct obj_def *od, u16_t len, void *value); + +void snmp_oidtoip(s32_t *ident, ip_addr_t *ip); +void snmp_iptooid(ip_addr_t *ip, s32_t *ident); +void snmp_ifindextonetif(s32_t ifindex, struct netif **netif); +void snmp_netiftoifindex(struct netif *netif, s32_t *ifidx); + +struct mib_list_node* snmp_mib_ln_alloc(s32_t id); +void snmp_mib_ln_free(struct mib_list_node *ln); +struct mib_list_rootnode* snmp_mib_lrn_alloc(void); +void snmp_mib_lrn_free(struct mib_list_rootnode *lrn); + +s8_t snmp_mib_node_insert(struct mib_list_rootnode *rn, s32_t objid, struct mib_list_node **insn); +s8_t snmp_mib_node_find(struct mib_list_rootnode *rn, s32_t objid, struct mib_list_node **fn); +struct mib_list_rootnode *snmp_mib_node_delete(struct mib_list_rootnode *rn, struct mib_list_node *n); + +struct mib_node* snmp_search_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct snmp_name_ptr *np); +struct mib_node* snmp_expand_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct snmp_obj_id *oidret); +u8_t snmp_iso_prefix_tst(u8_t ident_len, s32_t *ident); +u8_t snmp_iso_prefix_expand(u8_t ident_len, s32_t *ident, struct snmp_obj_id *oidret); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SNMP */ + +#endif /* __LWIP_SNMP_STRUCTS_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/sockets.h b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/sockets.h new file mode 100644 index 0000000..3ea32f1 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/sockets.h @@ -0,0 +1,379 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + + +#ifndef __LWIP_SOCKETS_H__ +#define __LWIP_SOCKETS_H__ + +#include "lwip/opt.h" + +#if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ + +#include /* for size_t */ + +#include "lwip/ip_addr.h" +#include "lwip/inet.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* members are in network byte order */ +struct sockaddr_in { + u8_t sin_len; + u8_t sin_family; + u16_t sin_port; + struct in_addr sin_addr; + char sin_zero[8]; +}; + +struct sockaddr { + u8_t sa_len; + u8_t sa_family; + char sa_data[14]; +}; + +/* If your port already typedef's socklen_t, define SOCKLEN_T_DEFINED + to prevent this code from redefining it. */ +#if !defined(socklen_t) && !defined(SOCKLEN_T_DEFINED) +typedef u32_t socklen_t; +#endif + +/* Socket protocol types (TCP/UDP/RAW) */ +#define SOCK_STREAM 1 +#define SOCK_DGRAM 2 +#define SOCK_RAW 3 + +/* + * Option flags per-socket. These must match the SOF_ flags in ip.h (checked in init.c) + */ +#define SO_DEBUG 0x0001 /* Unimplemented: turn on debugging info recording */ +#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */ +#define SO_REUSEADDR 0x0004 /* Allow local address reuse */ +#define SO_KEEPALIVE 0x0008 /* keep connections alive */ +#define SO_DONTROUTE 0x0010 /* Unimplemented: just use interface addresses */ +#define SO_BROADCAST 0x0020 /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */ +#define SO_USELOOPBACK 0x0040 /* Unimplemented: bypass hardware when possible */ +#define SO_LINGER 0x0080 /* linger on close if data present */ +#define SO_OOBINLINE 0x0100 /* Unimplemented: leave received OOB data in line */ +#define SO_REUSEPORT 0x0200 /* Unimplemented: allow local address & port reuse */ + +#define SO_DONTLINGER ((int)(~SO_LINGER)) + +/* + * Additional options, not kept in so_options. + */ +#define SO_SNDBUF 0x1001 /* Unimplemented: send buffer size */ +#define SO_RCVBUF 0x1002 /* receive buffer size */ +#define SO_SNDLOWAT 0x1003 /* Unimplemented: send low-water mark */ +#define SO_RCVLOWAT 0x1004 /* Unimplemented: receive low-water mark */ +#define SO_SNDTIMEO 0x1005 /* Unimplemented: send timeout */ +#define SO_RCVTIMEO 0x1006 /* receive timeout */ +#define SO_ERROR 0x1007 /* get error status and clear */ +#define SO_TYPE 0x1008 /* get socket type */ +#define SO_CONTIMEO 0x1009 /* Unimplemented: connect timeout */ +#define SO_NO_CHECK 0x100a /* don't create UDP checksum */ + + +/* + * Structure used for manipulating linger option. + */ +struct linger { + int l_onoff; /* option on/off */ + int l_linger; /* linger time */ +}; + +/* + * Level number for (get/set)sockopt() to apply to socket itself. + */ +#define SOL_SOCKET 0xfff /* options for socket level */ + + +#define AF_UNSPEC 0 +#define AF_INET 2 +#define PF_INET AF_INET +#define PF_UNSPEC AF_UNSPEC + +#define IPPROTO_IP 0 +#define IPPROTO_TCP 6 +#define IPPROTO_UDP 17 +#define IPPROTO_UDPLITE 136 + +/* Flags we can use with send and recv. */ +#define MSG_PEEK 0x01 /* Peeks at an incoming message */ +#define MSG_WAITALL 0x02 /* Unimplemented: Requests that the function block until the full amount of data requested can be returned */ +#define MSG_OOB 0x04 /* Unimplemented: Requests out-of-band data. The significance and semantics of out-of-band data are protocol-specific */ +#define MSG_DONTWAIT 0x08 /* Nonblocking i/o for this operation only */ +#define MSG_MORE 0x10 /* Sender will send more */ + + +/* + * Options for level IPPROTO_IP + */ +#define IP_TOS 1 +#define IP_TTL 2 + +#if LWIP_TCP +/* + * Options for level IPPROTO_TCP + */ +#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */ +#define TCP_KEEPALIVE 0x02 /* send KEEPALIVE probes when idle for pcb->keep_idle milliseconds */ +#define TCP_KEEPIDLE 0x03 /* set pcb->keep_idle - Same as TCP_KEEPALIVE, but use seconds for get/setsockopt */ +#define TCP_KEEPINTVL 0x04 /* set pcb->keep_intvl - Use seconds for get/setsockopt */ +#define TCP_KEEPCNT 0x05 /* set pcb->keep_cnt - Use number of probes sent for get/setsockopt */ +#endif /* LWIP_TCP */ + +#if LWIP_UDP && LWIP_UDPLITE +/* + * Options for level IPPROTO_UDPLITE + */ +#define UDPLITE_SEND_CSCOV 0x01 /* sender checksum coverage */ +#define UDPLITE_RECV_CSCOV 0x02 /* minimal receiver checksum coverage */ +#endif /* LWIP_UDP && LWIP_UDPLITE*/ + + +#if LWIP_IGMP +/* + * Options and types for UDP multicast traffic handling + */ +#define IP_ADD_MEMBERSHIP 3 +#define IP_DROP_MEMBERSHIP 4 +#define IP_MULTICAST_TTL 5 +#define IP_MULTICAST_IF 6 +#define IP_MULTICAST_LOOP 7 + +typedef struct ip_mreq { + struct in_addr imr_multiaddr; /* IP multicast address of group */ + struct in_addr imr_interface; /* local IP address of interface */ +} ip_mreq; +#endif /* LWIP_IGMP */ + +/* + * The Type of Service provides an indication of the abstract + * parameters of the quality of service desired. These parameters are + * to be used to guide the selection of the actual service parameters + * when transmitting a datagram through a particular network. Several + * networks offer service precedence, which somehow treats high + * precedence traffic as more important than other traffic (generally + * by accepting only traffic above a certain precedence at time of high + * load). The major choice is a three way tradeoff between low-delay, + * high-reliability, and high-throughput. + * The use of the Delay, Throughput, and Reliability indications may + * increase the cost (in some sense) of the service. In many networks + * better performance for one of these parameters is coupled with worse + * performance on another. Except for very unusual cases at most two + * of these three indications should be set. + */ +#define IPTOS_TOS_MASK 0x1E +#define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK) +#define IPTOS_LOWDELAY 0x10 +#define IPTOS_THROUGHPUT 0x08 +#define IPTOS_RELIABILITY 0x04 +#define IPTOS_LOWCOST 0x02 +#define IPTOS_MINCOST IPTOS_LOWCOST + +/* + * The Network Control precedence designation is intended to be used + * within a network only. The actual use and control of that + * designation is up to each network. The Internetwork Control + * designation is intended for use by gateway control originators only. + * If the actual use of these precedence designations is of concern to + * a particular network, it is the responsibility of that network to + * control the access to, and use of, those precedence designations. + */ +#define IPTOS_PREC_MASK 0xe0 +#define IPTOS_PREC(tos) ((tos) & IPTOS_PREC_MASK) +#define IPTOS_PREC_NETCONTROL 0xe0 +#define IPTOS_PREC_INTERNETCONTROL 0xc0 +#define IPTOS_PREC_CRITIC_ECP 0xa0 +#define IPTOS_PREC_FLASHOVERRIDE 0x80 +#define IPTOS_PREC_FLASH 0x60 +#define IPTOS_PREC_IMMEDIATE 0x40 +#define IPTOS_PREC_PRIORITY 0x20 +#define IPTOS_PREC_ROUTINE 0x00 + + +/* + * Commands for ioctlsocket(), taken from the BSD file fcntl.h. + * lwip_ioctl only supports FIONREAD and FIONBIO, for now + * + * Ioctl's have the command encoded in the lower word, + * and the size of any in or out parameters in the upper + * word. The high 2 bits of the upper word are used + * to encode the in/out status of the parameter; for now + * we restrict parameters to at most 128 bytes. + */ +#if !defined(FIONREAD) || !defined(FIONBIO) +#define IOCPARM_MASK 0x7fU /* parameters must be < 128 bytes */ +#define IOC_VOID 0x20000000UL /* no parameters */ +#define IOC_OUT 0x40000000UL /* copy out parameters */ +#define IOC_IN 0x80000000UL /* copy in parameters */ +#define IOC_INOUT (IOC_IN|IOC_OUT) + /* 0x20000000 distinguishes new & + old ioctl's */ +#define _IO(x,y) (IOC_VOID|((x)<<8)|(y)) + +#define _IOR(x,y,t) (IOC_OUT|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) + +#define _IOW(x,y,t) (IOC_IN|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) +#endif /* !defined(FIONREAD) || !defined(FIONBIO) */ + +#ifndef FIONREAD +#define FIONREAD _IOR('f', 127, unsigned long) /* get # bytes to read */ +#endif +#ifndef FIONBIO +#define FIONBIO _IOW('f', 126, unsigned long) /* set/clear non-blocking i/o */ +#endif + +/* Socket I/O Controls: unimplemented */ +#ifndef SIOCSHIWAT +#define SIOCSHIWAT _IOW('s', 0, unsigned long) /* set high watermark */ +#define SIOCGHIWAT _IOR('s', 1, unsigned long) /* get high watermark */ +#define SIOCSLOWAT _IOW('s', 2, unsigned long) /* set low watermark */ +#define SIOCGLOWAT _IOR('s', 3, unsigned long) /* get low watermark */ +#define SIOCATMARK _IOR('s', 7, unsigned long) /* at oob mark? */ +#endif + +/* commands for fnctl */ +#ifndef F_GETFL +#define F_GETFL 3 +#endif +#ifndef F_SETFL +#define F_SETFL 4 +#endif + +/* File status flags and file access modes for fnctl, + these are bits in an int. */ +#ifndef O_NONBLOCK +#define O_NONBLOCK 1 /* nonblocking I/O */ +#endif +#ifndef O_NDELAY +#define O_NDELAY 1 /* same as O_NONBLOCK, for compatibility */ +#endif + +#ifndef SHUT_RD + #define SHUT_RD 0 + #define SHUT_WR 1 + #define SHUT_RDWR 2 +#endif + +/* FD_SET used for lwip_select */ +#ifndef FD_SET + #undef FD_SETSIZE + /* Make FD_SETSIZE match NUM_SOCKETS in socket.c */ + #define FD_SETSIZE MEMP_NUM_NETCONN + #define FD_SET(n, p) ((p)->fd_bits[(n)/8] |= (1 << ((n) & 7))) + #define FD_CLR(n, p) ((p)->fd_bits[(n)/8] &= ~(1 << ((n) & 7))) + #define FD_ISSET(n,p) ((p)->fd_bits[(n)/8] & (1 << ((n) & 7))) + #define FD_ZERO(p) memset((void*)(p),0,sizeof(*(p))) + + typedef struct fd_set { + unsigned char fd_bits [(FD_SETSIZE+7)/8]; + } fd_set; + +#endif /* FD_SET */ + +/** LWIP_TIMEVAL_PRIVATE: if you want to use the struct timeval provided + * by your system, set this to 0 and include in cc.h */ +#ifndef LWIP_TIMEVAL_PRIVATE +#define LWIP_TIMEVAL_PRIVATE 1 +#endif + +#if LWIP_TIMEVAL_PRIVATE +struct timeval { + long tv_sec; /* seconds */ + long tv_usec; /* and microseconds */ +}; +#endif /* LWIP_TIMEVAL_PRIVATE */ + +void lwip_socket_init(void); + +int lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen); +int lwip_bind(int s, const struct sockaddr *name, socklen_t namelen); +int lwip_shutdown(int s, int how); +int lwip_getpeername (int s, struct sockaddr *name, socklen_t *namelen); +int lwip_getsockname (int s, struct sockaddr *name, socklen_t *namelen); +int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *optlen); +int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_t optlen); +int lwip_close(int s); +int lwip_connect(int s, const struct sockaddr *name, socklen_t namelen); +int lwip_listen(int s, int backlog); +int lwip_recv(int s, void *mem, size_t len, int flags); +int lwip_read(int s, void *mem, size_t len); +int lwip_recvfrom(int s, void *mem, size_t len, int flags, + struct sockaddr *from, socklen_t *fromlen); +int lwip_send(int s, const void *dataptr, size_t size, int flags); +int lwip_sendto(int s, const void *dataptr, size_t size, int flags, + const struct sockaddr *to, socklen_t tolen); +int lwip_socket(int domain, int type, int protocol); +int lwip_write(int s, const void *dataptr, size_t size); +int lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, + struct timeval *timeout); +int lwip_ioctl(int s, long cmd, void *argp); +int lwip_fcntl(int s, int cmd, int val); + +#if LWIP_COMPAT_SOCKETS +#define accept(a,b,c) lwip_accept(a,b,c) +#define bind(a,b,c) lwip_bind(a,b,c) +#define shutdown(a,b) lwip_shutdown(a,b) +#define closesocket(s) lwip_close(s) +#define connect(a,b,c) lwip_connect(a,b,c) +#define getsockname(a,b,c) lwip_getsockname(a,b,c) +#define getpeername(a,b,c) lwip_getpeername(a,b,c) +#define setsockopt(a,b,c,d,e) lwip_setsockopt(a,b,c,d,e) +#define getsockopt(a,b,c,d,e) lwip_getsockopt(a,b,c,d,e) +#define listen(a,b) lwip_listen(a,b) +#define recv(a,b,c,d) lwip_recv(a,b,c,d) +#define recvfrom(a,b,c,d,e,f) lwip_recvfrom(a,b,c,d,e,f) +#define send(a,b,c,d) lwip_send(a,b,c,d) +#define sendto(a,b,c,d,e,f) lwip_sendto(a,b,c,d,e,f) +#define socket(a,b,c) lwip_socket(a,b,c) +#define select(a,b,c,d,e) lwip_select(a,b,c,d,e) +#define ioctlsocket(a,b,c) lwip_ioctl(a,b,c) + +#if LWIP_POSIX_SOCKETS_IO_NAMES +#define read(a,b,c) lwip_read(a,b,c) +#define write(a,b,c) lwip_write(a,b,c) +#define close(s) lwip_close(s) +#define fcntl(a,b,c) lwip_fcntl(a,b,c) +#endif /* LWIP_POSIX_SOCKETS_IO_NAMES */ + +#endif /* LWIP_COMPAT_SOCKETS */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SOCKET */ + +#endif /* __LWIP_SOCKETS_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/stats.h b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/stats.h new file mode 100644 index 0000000..1f5152a --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/stats.h @@ -0,0 +1,292 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_STATS_H__ +#define __LWIP_STATS_H__ + +#include "lwip/opt.h" + +#include "lwip/mem.h" +#include "lwip/memp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_STATS + +#ifndef LWIP_STATS_LARGE +#define LWIP_STATS_LARGE 0 +#endif + +#if LWIP_STATS_LARGE +#define STAT_COUNTER u32_t +#define STAT_COUNTER_F U32_F +#else +#define STAT_COUNTER u16_t +#define STAT_COUNTER_F U16_F +#endif + +struct stats_proto { + STAT_COUNTER xmit; /* Transmitted packets. */ + STAT_COUNTER recv; /* Received packets. */ + STAT_COUNTER fw; /* Forwarded packets. */ + STAT_COUNTER drop; /* Dropped packets. */ + STAT_COUNTER chkerr; /* Checksum error. */ + STAT_COUNTER lenerr; /* Invalid length error. */ + STAT_COUNTER memerr; /* Out of memory error. */ + STAT_COUNTER rterr; /* Routing error. */ + STAT_COUNTER proterr; /* Protocol error. */ + STAT_COUNTER opterr; /* Error in options. */ + STAT_COUNTER err; /* Misc error. */ + STAT_COUNTER cachehit; +}; + +struct stats_igmp { + STAT_COUNTER xmit; /* Transmitted packets. */ + STAT_COUNTER recv; /* Received packets. */ + STAT_COUNTER drop; /* Dropped packets. */ + STAT_COUNTER chkerr; /* Checksum error. */ + STAT_COUNTER lenerr; /* Invalid length error. */ + STAT_COUNTER memerr; /* Out of memory error. */ + STAT_COUNTER proterr; /* Protocol error. */ + STAT_COUNTER rx_v1; /* Received v1 frames. */ + STAT_COUNTER rx_group; /* Received group-specific queries. */ + STAT_COUNTER rx_general; /* Received general queries. */ + STAT_COUNTER rx_report; /* Received reports. */ + STAT_COUNTER tx_join; /* Sent joins. */ + STAT_COUNTER tx_leave; /* Sent leaves. */ + STAT_COUNTER tx_report; /* Sent reports. */ +}; + +struct stats_mem { +#ifdef LWIP_DEBUG + const char *name; +#endif /* LWIP_DEBUG */ + mem_size_t avail; + mem_size_t used; + mem_size_t max; + STAT_COUNTER err; + STAT_COUNTER illegal; +}; + +struct stats_syselem { + STAT_COUNTER used; + STAT_COUNTER max; + STAT_COUNTER err; +}; + +struct stats_sys { + struct stats_syselem sem; + struct stats_syselem mutex; + struct stats_syselem mbox; +}; + +struct stats_ { +#if LINK_STATS + struct stats_proto link; +#endif +#if ETHARP_STATS + struct stats_proto etharp; +#endif +#if IPFRAG_STATS + struct stats_proto ip_frag; +#endif +#if IP_STATS + struct stats_proto ip; +#endif +#if ICMP_STATS + struct stats_proto icmp; +#endif +#if IGMP_STATS + struct stats_igmp igmp; +#endif +#if UDP_STATS + struct stats_proto udp; +#endif +#if TCP_STATS + struct stats_proto tcp; +#endif +#if MEM_STATS + struct stats_mem mem; +#endif +#if MEMP_STATS + struct stats_mem memp[MEMP_MAX]; +#endif +#if SYS_STATS + struct stats_sys sys; +#endif +}; + +extern struct stats_ lwip_stats; + +void stats_init(void); + +#define STATS_INC(x) ++lwip_stats.x +#define STATS_DEC(x) --lwip_stats.x +#define STATS_INC_USED(x, y) do { lwip_stats.x.used += y; \ + if (lwip_stats.x.max < lwip_stats.x.used) { \ + lwip_stats.x.max = lwip_stats.x.used; \ + } \ + } while(0) +#else /* LWIP_STATS */ +#define stats_init() +#define STATS_INC(x) +#define STATS_DEC(x) +#define STATS_INC_USED(x) +#endif /* LWIP_STATS */ + +#if TCP_STATS +#define TCP_STATS_INC(x) STATS_INC(x) +#define TCP_STATS_DISPLAY() stats_display_proto(&lwip_stats.tcp, "TCP") +#else +#define TCP_STATS_INC(x) +#define TCP_STATS_DISPLAY() +#endif + +#if UDP_STATS +#define UDP_STATS_INC(x) STATS_INC(x) +#define UDP_STATS_DISPLAY() stats_display_proto(&lwip_stats.udp, "UDP") +#else +#define UDP_STATS_INC(x) +#define UDP_STATS_DISPLAY() +#endif + +#if ICMP_STATS +#define ICMP_STATS_INC(x) STATS_INC(x) +#define ICMP_STATS_DISPLAY() stats_display_proto(&lwip_stats.icmp, "ICMP") +#else +#define ICMP_STATS_INC(x) +#define ICMP_STATS_DISPLAY() +#endif + +#if IGMP_STATS +#define IGMP_STATS_INC(x) STATS_INC(x) +#define IGMP_STATS_DISPLAY() stats_display_igmp(&lwip_stats.igmp) +#else +#define IGMP_STATS_INC(x) +#define IGMP_STATS_DISPLAY() +#endif + +#if IP_STATS +#define IP_STATS_INC(x) STATS_INC(x) +#define IP_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip, "IP") +#else +#define IP_STATS_INC(x) +#define IP_STATS_DISPLAY() +#endif + +#if IPFRAG_STATS +#define IPFRAG_STATS_INC(x) STATS_INC(x) +#define IPFRAG_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip_frag, "IP_FRAG") +#else +#define IPFRAG_STATS_INC(x) +#define IPFRAG_STATS_DISPLAY() +#endif + +#if ETHARP_STATS +#define ETHARP_STATS_INC(x) STATS_INC(x) +#define ETHARP_STATS_DISPLAY() stats_display_proto(&lwip_stats.etharp, "ETHARP") +#else +#define ETHARP_STATS_INC(x) +#define ETHARP_STATS_DISPLAY() +#endif + +#if LINK_STATS +#define LINK_STATS_INC(x) STATS_INC(x) +#define LINK_STATS_DISPLAY() stats_display_proto(&lwip_stats.link, "LINK") +#else +#define LINK_STATS_INC(x) +#define LINK_STATS_DISPLAY() +#endif + +#if MEM_STATS +#define MEM_STATS_AVAIL(x, y) lwip_stats.mem.x = y +#define MEM_STATS_INC(x) STATS_INC(mem.x) +#define MEM_STATS_INC_USED(x, y) STATS_INC_USED(mem, y) +#define MEM_STATS_DEC_USED(x, y) lwip_stats.mem.x -= y +#define MEM_STATS_DISPLAY() stats_display_mem(&lwip_stats.mem, "HEAP") +#else +#define MEM_STATS_AVAIL(x, y) +#define MEM_STATS_INC(x) +#define MEM_STATS_INC_USED(x, y) +#define MEM_STATS_DEC_USED(x, y) +#define MEM_STATS_DISPLAY() +#endif + +#if MEMP_STATS +#define MEMP_STATS_AVAIL(x, i, y) lwip_stats.memp[i].x = y +#define MEMP_STATS_INC(x, i) STATS_INC(memp[i].x) +#define MEMP_STATS_DEC(x, i) STATS_DEC(memp[i].x) +#define MEMP_STATS_INC_USED(x, i) STATS_INC_USED(memp[i], 1) +#define MEMP_STATS_DISPLAY(i) stats_display_memp(&lwip_stats.memp[i], i) +#else +#define MEMP_STATS_AVAIL(x, i, y) +#define MEMP_STATS_INC(x, i) +#define MEMP_STATS_DEC(x, i) +#define MEMP_STATS_INC_USED(x, i) +#define MEMP_STATS_DISPLAY(i) +#endif + +#if SYS_STATS +#define SYS_STATS_INC(x) STATS_INC(sys.x) +#define SYS_STATS_DEC(x) STATS_DEC(sys.x) +#define SYS_STATS_INC_USED(x) STATS_INC_USED(sys.x, 1) +#define SYS_STATS_DISPLAY() stats_display_sys(&lwip_stats.sys) +#else +#define SYS_STATS_INC(x) +#define SYS_STATS_DEC(x) +#define SYS_STATS_INC_USED(x) +#define SYS_STATS_DISPLAY() +#endif + +/* Display of statistics */ +#if LWIP_STATS_DISPLAY +void stats_display(void); +void stats_display_proto(struct stats_proto *proto, const char *name); +void stats_display_igmp(struct stats_igmp *igmp); +void stats_display_mem(struct stats_mem *mem, const char *name); +void stats_display_memp(struct stats_mem *mem, int index); +void stats_display_sys(struct stats_sys *sys); +#else /* LWIP_STATS_DISPLAY */ +#define stats_display() +#define stats_display_proto(proto, name) +#define stats_display_igmp(igmp) +#define stats_display_mem(mem, name) +#define stats_display_memp(mem, index) +#define stats_display_sys(sys) +#endif /* LWIP_STATS_DISPLAY */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_STATS_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/sys.h b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/sys.h new file mode 100644 index 0000000..dc93513 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/sys.h @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_SYS_H__ +#define __LWIP_SYS_H__ + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if NO_SYS + +/* For a totally minimal and standalone system, we provide null + definitions of the sys_ functions. */ +typedef u8_t sys_sem_t; +typedef u8_t sys_mutex_t; +typedef u8_t sys_mbox_t; + +#define sys_sem_new(s, c) ERR_OK +#define sys_sem_signal(s) +#define sys_sem_wait(s) +#define sys_arch_sem_wait(s,t) +#define sys_sem_free(s) +#define sys_sem_valid(s) 0 +#define sys_sem_set_invalid(s) +#define sys_mutex_new(mu) ERR_OK +#define sys_mutex_lock(mu) +#define sys_mutex_unlock(mu) +#define sys_mutex_free(mu) +#define sys_mutex_valid(mu) 0 +#define sys_mutex_set_invalid(mu) +#define sys_mbox_new(m, s) ERR_OK +#define sys_mbox_fetch(m,d) +#define sys_mbox_tryfetch(m,d) +#define sys_mbox_post(m,d) +#define sys_mbox_trypost(m,d) +#define sys_mbox_free(m) +#define sys_mbox_valid(m) +#define sys_mbox_set_invalid(m) + +#define sys_thread_new(n,t,a,s,p) + +#define sys_msleep(t) + +#else /* NO_SYS */ + +/** Return code for timeouts from sys_arch_mbox_fetch and sys_arch_sem_wait */ +#define SYS_ARCH_TIMEOUT 0xffffffffUL + +/** sys_mbox_tryfetch() returns SYS_MBOX_EMPTY if appropriate. + * For now we use the same magic value, but we allow this to change in future. + */ +#define SYS_MBOX_EMPTY SYS_ARCH_TIMEOUT + +#include "lwip/err.h" +#include "arch/sys_arch.h" + +/** Function prototype for thread functions */ +typedef void (*lwip_thread_fn)(void *arg); + +/* Function prototypes for functions to be implemented by platform ports + (in sys_arch.c) */ + +/* Mutex functions: */ + +/** Define LWIP_COMPAT_MUTEX if the port has no mutexes and binary semaphores + should be used instead */ +#if LWIP_COMPAT_MUTEX +/* for old ports that don't have mutexes: define them to binary semaphores */ +#define sys_mutex_t sys_sem_t +#define sys_mutex_new(mutex) sys_sem_new(mutex, 1) +#define sys_mutex_lock(mutex) sys_sem_wait(mutex) +#define sys_mutex_unlock(mutex) sys_sem_signal(mutex) +#define sys_mutex_free(mutex) sys_sem_free(mutex) +#define sys_mutex_valid(mutex) sys_sem_valid(mutex) +#define sys_mutex_set_invalid(mutex) sys_sem_set_invalid(mutex) + +#else /* LWIP_COMPAT_MUTEX */ + +/** Create a new mutex + * @param mutex pointer to the mutex to create + * @return a new mutex */ +err_t sys_mutex_new(sys_mutex_t *mutex); +/** Lock a mutex + * @param mutex the mutex to lock */ +void sys_mutex_lock(sys_mutex_t *mutex); +/** Unlock a mutex + * @param mutex the mutex to unlock */ +void sys_mutex_unlock(sys_mutex_t *mutex); +/** Delete a semaphore + * @param mutex the mutex to delete */ +void sys_mutex_free(sys_mutex_t *mutex); +#ifndef sys_mutex_valid +/** Check if a mutex is valid/allocated: return 1 for valid, 0 for invalid */ +int sys_mutex_valid(sys_mutex_t *mutex); +#endif +#ifndef sys_mutex_set_invalid +/** Set a mutex invalid so that sys_mutex_valid returns 0 */ +void sys_mutex_set_invalid(sys_mutex_t *mutex); +#endif +#endif /* LWIP_COMPAT_MUTEX */ + +/* Semaphore functions: */ + +/** Create a new semaphore + * @param sem pointer to the semaphore to create + * @param count initial count of the semaphore + * @return ERR_OK if successful, another err_t otherwise */ +err_t sys_sem_new(sys_sem_t *sem, u8_t count); +/** Signals a semaphore + * @param sem the semaphore to signal */ +void sys_sem_signal(sys_sem_t *sem); +/** Wait for a semaphore for the specified timeout + * @param sem the semaphore to wait for + * @param timeout timeout in milliseconds to wait (0 = wait forever) + * @return time (in milliseconds) waited for the semaphore + * or SYS_ARCH_TIMEOUT on timeout */ +u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout); +/** Delete a semaphore + * @param sem semaphore to delete */ +void sys_sem_free(sys_sem_t *sem); +/** Wait for a semaphore - forever/no timeout */ +#define sys_sem_wait(sem) sys_arch_sem_wait(sem, 0) +#ifndef sys_sem_valid +/** Check if a sempahore is valid/allocated: return 1 for valid, 0 for invalid */ +int sys_sem_valid(sys_sem_t *sem); +#endif +#ifndef sys_sem_set_invalid +/** Set a semaphore invalid so that sys_sem_valid returns 0 */ +void sys_sem_set_invalid(sys_sem_t *sem); +#endif + +/* Time functions. */ +#ifndef sys_msleep +void sys_msleep(u32_t ms); /* only has a (close to) 1 jiffy resolution. */ +#endif + +/* Mailbox functions. */ + +/** Create a new mbox of specified size + * @param mbox pointer to the mbox to create + * @param size (miminum) number of messages in this mbox + * @return ERR_OK if successful, another err_t otherwise */ +err_t sys_mbox_new(sys_mbox_t *mbox, int size); +/** Post a message to an mbox - may not fail + * -> blocks if full, only used from tasks not from ISR + * @param mbox mbox to posts the message + * @param msg message to post (ATTENTION: can be NULL) */ +void sys_mbox_post(sys_mbox_t *mbox, void *msg); +/** Try to post a message to an mbox - may fail if full or ISR + * @param mbox mbox to posts the message + * @param msg message to post (ATTENTION: can be NULL) */ +err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg); +/** Wait for a new message to arrive in the mbox + * @param mbox mbox to get a message from + * @param msg pointer where the message is stored + * @param timeout maximum time (in milliseconds) to wait for a message + * @return time (in milliseconds) waited for a message, may be 0 if not waited + or SYS_ARCH_TIMEOUT on timeout + * The returned time has to be accurate to prevent timer jitter! */ +u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout); +/* Allow port to override with a macro, e.g. special timout for sys_arch_mbox_fetch() */ +#ifndef sys_arch_mbox_tryfetch +/** Wait for a new message to arrive in the mbox + * @param mbox mbox to get a message from + * @param msg pointer where the message is stored + * @param timeout maximum time (in milliseconds) to wait for a message + * @return 0 (milliseconds) if a message has been received + * or SYS_MBOX_EMPTY if the mailbox is empty */ +u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg); +#endif +/** For now, we map straight to sys_arch implementation. */ +#define sys_mbox_tryfetch(mbox, msg) sys_arch_mbox_tryfetch(mbox, msg) +/** Delete an mbox + * @param mbox mbox to delete */ +void sys_mbox_free(sys_mbox_t *mbox); +#define sys_mbox_fetch(mbox, msg) sys_arch_mbox_fetch(mbox, msg, 0) +#ifndef sys_mbox_valid +/** Check if an mbox is valid/allocated: return 1 for valid, 0 for invalid */ +int sys_mbox_valid(sys_mbox_t *mbox); +#endif +#ifndef sys_mbox_set_invalid +/** Set an mbox invalid so that sys_mbox_valid returns 0 */ +void sys_mbox_set_invalid(sys_mbox_t *mbox); +#endif + +/** The only thread function: + * Creates a new thread + * @param name human-readable name for the thread (used for debugging purposes) + * @param thread thread-function + * @param arg parameter passed to 'thread' + * @param stacksize stack size in bytes for the new thread (may be ignored by ports) + * @param prio priority of the new thread (may be ignored by ports) */ +sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio); + +#endif /* NO_SYS */ + +/* sys_init() must be called before anthing else. */ +void sys_init(void); + +#ifndef sys_jiffies +/** Ticks/jiffies since power up. */ +u32_t sys_jiffies(void); +#endif + +/** Returns the current time in milliseconds, + * may be the same as sys_jiffies or at least based on it. */ +u32_t sys_now(void); + +/* Critical Region Protection */ +/* These functions must be implemented in the sys_arch.c file. + In some implementations they can provide a more light-weight protection + mechanism than using semaphores. Otherwise semaphores can be used for + implementation */ +#ifndef SYS_ARCH_PROTECT +/** SYS_LIGHTWEIGHT_PROT + * define SYS_LIGHTWEIGHT_PROT in lwipopts.h if you want inter-task protection + * for certain critical regions during buffer allocation, deallocation and memory + * allocation and deallocation. + */ +#if SYS_LIGHTWEIGHT_PROT + +/** SYS_ARCH_DECL_PROTECT + * declare a protection variable. This macro will default to defining a variable of + * type sys_prot_t. If a particular port needs a different implementation, then + * this macro may be defined in sys_arch.h. + */ +#define SYS_ARCH_DECL_PROTECT(lev) sys_prot_t lev +/** SYS_ARCH_PROTECT + * Perform a "fast" protect. This could be implemented by + * disabling interrupts for an embedded system or by using a semaphore or + * mutex. The implementation should allow calling SYS_ARCH_PROTECT when + * already protected. The old protection level is returned in the variable + * "lev". This macro will default to calling the sys_arch_protect() function + * which should be implemented in sys_arch.c. If a particular port needs a + * different implementation, then this macro may be defined in sys_arch.h + */ +#define SYS_ARCH_PROTECT(lev) lev = sys_arch_protect() +/** SYS_ARCH_UNPROTECT + * Perform a "fast" set of the protection level to "lev". This could be + * implemented by setting the interrupt level to "lev" within the MACRO or by + * using a semaphore or mutex. This macro will default to calling the + * sys_arch_unprotect() function which should be implemented in + * sys_arch.c. If a particular port needs a different implementation, then + * this macro may be defined in sys_arch.h + */ +#define SYS_ARCH_UNPROTECT(lev) sys_arch_unprotect(lev) +sys_prot_t sys_arch_protect(void); +void sys_arch_unprotect(sys_prot_t pval); + +#else + +#define SYS_ARCH_DECL_PROTECT(lev) +#define SYS_ARCH_PROTECT(lev) +#define SYS_ARCH_UNPROTECT(lev) + +#endif /* SYS_LIGHTWEIGHT_PROT */ + +#endif /* SYS_ARCH_PROTECT */ + +/* + * Macros to set/get and increase/decrease variables in a thread-safe way. + * Use these for accessing variable that are used from more than one thread. + */ + +#ifndef SYS_ARCH_INC +#define SYS_ARCH_INC(var, val) do { \ + SYS_ARCH_DECL_PROTECT(old_level); \ + SYS_ARCH_PROTECT(old_level); \ + var += val; \ + SYS_ARCH_UNPROTECT(old_level); \ + } while(0) +#endif /* SYS_ARCH_INC */ + +#ifndef SYS_ARCH_DEC +#define SYS_ARCH_DEC(var, val) do { \ + SYS_ARCH_DECL_PROTECT(old_level); \ + SYS_ARCH_PROTECT(old_level); \ + var -= val; \ + SYS_ARCH_UNPROTECT(old_level); \ + } while(0) +#endif /* SYS_ARCH_DEC */ + +#ifndef SYS_ARCH_GET +#define SYS_ARCH_GET(var, ret) do { \ + SYS_ARCH_DECL_PROTECT(old_level); \ + SYS_ARCH_PROTECT(old_level); \ + ret = var; \ + SYS_ARCH_UNPROTECT(old_level); \ + } while(0) +#endif /* SYS_ARCH_GET */ + +#ifndef SYS_ARCH_SET +#define SYS_ARCH_SET(var, val) do { \ + SYS_ARCH_DECL_PROTECT(old_level); \ + SYS_ARCH_PROTECT(old_level); \ + var = val; \ + SYS_ARCH_UNPROTECT(old_level); \ + } while(0) +#endif /* SYS_ARCH_SET */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_SYS_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/tcp.h b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/tcp.h new file mode 100644 index 0000000..415945c --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/tcp.h @@ -0,0 +1,383 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_TCP_H__ +#define __LWIP_TCP_H__ + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ +#include "lwip/sys.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/ip.h" +#include "lwip/icmp.h" +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct tcp_pcb; + +//Evan add +extern struct tcp_pcb *tcp_tw_pcbs; /* List of all TCP PCBs in TIME-WAIT. */ +//Evan add end + +/** Function prototype for tcp accept callback functions. Called when a new + * connection can be accepted on a listening pcb. + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param newpcb The new connection pcb + * @param err An error code if there has been an error accepting. + * Only return ERR_ABRT if you have called tcp_abort from within the + * callback function! + */ +typedef err_t (*tcp_accept_fn)(void *arg, struct tcp_pcb *newpcb, err_t err); + +/** Function prototype for tcp receive callback functions. Called when data has + * been received. + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param tpcb The connection pcb which received data + * @param p The received data (or NULL when the connection has been closed!) + * @param err An error code if there has been an error receiving + * Only return ERR_ABRT if you have called tcp_abort from within the + * callback function! + */ +typedef err_t (*tcp_recv_fn)(void *arg, struct tcp_pcb *tpcb, + struct pbuf *p, err_t err); + +/** Function prototype for tcp sent callback functions. Called when sent data has + * been acknowledged by the remote side. Use it to free corresponding resources. + * This also means that the pcb has now space available to send new data. + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param tpcb The connection pcb for which data has been acknowledged + * @param len The amount of bytes acknowledged + * @return ERR_OK: try to send some data by calling tcp_output + * Only return ERR_ABRT if you have called tcp_abort from within the + * callback function! + */ +typedef err_t (*tcp_sent_fn)(void *arg, struct tcp_pcb *tpcb, + u16_t len); + +/** Function prototype for tcp poll callback functions. Called periodically as + * specified by @see tcp_poll. + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param tpcb tcp pcb + * @return ERR_OK: try to send some data by calling tcp_output + * Only return ERR_ABRT if you have called tcp_abort from within the + * callback function! + */ +typedef err_t (*tcp_poll_fn)(void *arg, struct tcp_pcb *tpcb); + +/** Function prototype for tcp error callback functions. Called when the pcb + * receives a RST or is unexpectedly closed for any other reason. + * + * @note The corresponding pcb is already freed when this callback is called! + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param err Error code to indicate why the pcb has been closed + * ERR_ABRT: aborted through tcp_abort or by a TCP timer + * ERR_RST: the connection was reset by the remote host + */ +typedef void (*tcp_err_fn)(void *arg, err_t err); + +/** Function prototype for tcp connected callback functions. Called when a pcb + * is connected to the remote side after initiating a connection attempt by + * calling tcp_connect(). + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param tpcb The connection pcb which is connected + * @param err An unused error code, always ERR_OK currently ;-) TODO! + * Only return ERR_ABRT if you have called tcp_abort from within the + * callback function! + * + * @note When a connection attempt fails, the error callback is currently called! + */ +typedef err_t (*tcp_connected_fn)(void *arg, struct tcp_pcb *tpcb, err_t err); + +enum tcp_state { + CLOSED = 0, + LISTEN = 1, + SYN_SENT = 2, + SYN_RCVD = 3, + ESTABLISHED = 4, + FIN_WAIT_1 = 5, + FIN_WAIT_2 = 6, + CLOSE_WAIT = 7, + CLOSING = 8, + LAST_ACK = 9, + TIME_WAIT = 10 +}; + +#if LWIP_CALLBACK_API + /* Function to call when a listener has been connected. + * @param arg user-supplied argument (tcp_pcb.callback_arg) + * @param pcb a new tcp_pcb that now is connected + * @param err an error argument (TODO: that is current always ERR_OK?) + * @return ERR_OK: accept the new connection, + * any other err_t abortsthe new connection + */ +#define DEF_ACCEPT_CALLBACK tcp_accept_fn accept; +#else /* LWIP_CALLBACK_API */ +#define DEF_ACCEPT_CALLBACK +#endif /* LWIP_CALLBACK_API */ + +/** + * members common to struct tcp_pcb and struct tcp_listen_pcb + */ +#define TCP_PCB_COMMON(type) \ + type *next; /* for the linked list */ \ + void *callback_arg; \ + /* the accept callback for listen- and normal pcbs, if LWIP_CALLBACK_API */ \ + DEF_ACCEPT_CALLBACK \ + enum tcp_state state; /* TCP state */ \ + u8_t prio; \ + /* ports are in host byte order */ \ + u16_t local_port + + +/* the TCP protocol control block */ +struct tcp_pcb { +/** common PCB members */ + IP_PCB; +/** protocol specific PCB members */ + TCP_PCB_COMMON(struct tcp_pcb); + + /* ports are in host byte order */ + u16_t remote_port; + + u8_t flags; +#define TF_ACK_DELAY ((u8_t)0x01U) /* Delayed ACK. */ +#define TF_ACK_NOW ((u8_t)0x02U) /* Immediate ACK. */ +#define TF_INFR ((u8_t)0x04U) /* In fast recovery. */ +#define TF_TIMESTAMP ((u8_t)0x08U) /* Timestamp option enabled */ +#define TF_RXCLOSED ((u8_t)0x10U) /* rx closed by tcp_shutdown */ +#define TF_FIN ((u8_t)0x20U) /* Connection was closed locally (FIN segment enqueued). */ +#define TF_NODELAY ((u8_t)0x40U) /* Disable Nagle algorithm */ +#define TF_NAGLEMEMERR ((u8_t)0x80U) /* nagle enabled, memerr, try to output to prevent delayed ACK to happen */ + + /* the rest of the fields are in host byte order + as we have to do some math with them */ + + /* Timers */ + u8_t polltmr, pollinterval; + u8_t last_timer; + u32_t tmr; + + /* receiver variables */ + u32_t rcv_nxt; /* next seqno expected */ + u16_t rcv_wnd; /* receiver window available */ + u16_t rcv_ann_wnd; /* receiver window to announce */ + u32_t rcv_ann_right_edge; /* announced right edge of window */ + + /* Retransmission timer. */ + s16_t rtime; + + u16_t mss; /* maximum segment size */ + + /* RTT (round trip time) estimation variables */ + u32_t rttest; /* RTT estimate in 500ms ticks */ + u32_t rtseq; /* sequence number being timed */ + s16_t sa, sv; /* @todo document this */ + + s16_t rto; /* retransmission time-out */ + u8_t nrtx; /* number of retransmissions */ + + /* fast retransmit/recovery */ + u8_t dupacks; + u32_t lastack; /* Highest acknowledged seqno. */ + + /* congestion avoidance/control variables */ + u16_t cwnd; + u16_t ssthresh; + + /* sender variables */ + u32_t snd_nxt; /* next new seqno to be sent */ + u32_t snd_wl1, snd_wl2; /* Sequence and acknowledgement numbers of last + window update. */ + u32_t snd_lbb; /* Sequence number of next byte to be buffered. */ + u16_t snd_wnd; /* sender window */ + u16_t snd_wnd_max; /* the maximum sender window announced by the remote host */ + + u16_t acked; + + u16_t snd_buf; /* Available buffer space for sending (in bytes). */ +#define TCP_SNDQUEUELEN_OVERFLOW (0xffffU-3) + u16_t snd_queuelen; /* Available buffer space for sending (in tcp_segs). */ + +#if TCP_OVERSIZE + /* Extra bytes available at the end of the last pbuf in unsent. */ + u16_t unsent_oversize; +#endif /* TCP_OVERSIZE */ + + /* These are ordered by sequence number: */ + struct tcp_seg *unsent; /* Unsent (queued) segments. */ + struct tcp_seg *unacked; /* Sent but unacknowledged segments. */ +#if TCP_QUEUE_OOSEQ + struct tcp_seg *ooseq; /* Received out of sequence segments. */ +#endif /* TCP_QUEUE_OOSEQ */ + + struct pbuf *refused_data; /* Data previously received but not yet taken by upper layer */ + +#if LWIP_CALLBACK_API + /* Function to be called when more send buffer space is available. */ + tcp_sent_fn sent; + /* Function to be called when (in-sequence) data has arrived. */ + tcp_recv_fn recv; + /* Function to be called when a connection has been set up. */ + tcp_connected_fn connected; + /* Function which is called periodically. */ + tcp_poll_fn poll; + /* Function to be called whenever a fatal error occurs. */ + tcp_err_fn errf; +#endif /* LWIP_CALLBACK_API */ + +#if LWIP_TCP_TIMESTAMPS + u32_t ts_lastacksent; + u32_t ts_recent; +#endif /* LWIP_TCP_TIMESTAMPS */ + + /* idle time before KEEPALIVE is sent */ + u32_t keep_idle; +#if LWIP_TCP_KEEPALIVE + u32_t keep_intvl; + u32_t keep_cnt; +#endif /* LWIP_TCP_KEEPALIVE */ + + /* Persist timer counter */ + u8_t persist_cnt; + /* Persist timer back-off */ + u8_t persist_backoff; + + /* KEEPALIVE counter */ + u8_t keep_cnt_sent; +}; + +struct tcp_pcb_listen { +/* Common members of all PCB types */ + IP_PCB; +/* Protocol specific PCB members */ + TCP_PCB_COMMON(struct tcp_pcb_listen); + +#if TCP_LISTEN_BACKLOG + u8_t backlog; + u8_t accepts_pending; +#endif /* TCP_LISTEN_BACKLOG */ +}; + +#if LWIP_EVENT_API + +enum lwip_event { + LWIP_EVENT_ACCEPT, + LWIP_EVENT_SENT, + LWIP_EVENT_RECV, + LWIP_EVENT_CONNECTED, + LWIP_EVENT_POLL, + LWIP_EVENT_ERR +}; + +err_t lwip_tcp_event(void *arg, struct tcp_pcb *pcb, + enum lwip_event, + struct pbuf *p, + u16_t size, + err_t err); + +#endif /* LWIP_EVENT_API */ + +/* Application program's interface: */ +struct tcp_pcb * tcp_new (void); + +void tcp_arg (struct tcp_pcb *pcb, void *arg); +void tcp_accept (struct tcp_pcb *pcb, tcp_accept_fn accept); +void tcp_recv (struct tcp_pcb *pcb, tcp_recv_fn recv); +void tcp_sent (struct tcp_pcb *pcb, tcp_sent_fn sent); +void tcp_poll (struct tcp_pcb *pcb, tcp_poll_fn poll, u8_t interval); +void tcp_err (struct tcp_pcb *pcb, tcp_err_fn err); + +#define tcp_mss(pcb) (((pcb)->flags & TF_TIMESTAMP) ? ((pcb)->mss - 12) : (pcb)->mss) +#define tcp_sndbuf(pcb) ((pcb)->snd_buf) +#define tcp_sndqueuelen(pcb) ((pcb)->snd_queuelen) +#define tcp_nagle_disable(pcb) ((pcb)->flags |= TF_NODELAY) +#define tcp_nagle_enable(pcb) ((pcb)->flags &= ~TF_NODELAY) +#define tcp_nagle_disabled(pcb) (((pcb)->flags & TF_NODELAY) != 0) + +#if TCP_LISTEN_BACKLOG +#define tcp_accepted(pcb) do { \ + LWIP_ASSERT("pcb->state == LISTEN (called for wrong pcb?)", pcb->state == LISTEN); \ + (((struct tcp_pcb_listen *)(pcb))->accepts_pending--); } while(0) +#else /* TCP_LISTEN_BACKLOG */ +#define tcp_accepted(pcb) LWIP_ASSERT("pcb->state == LISTEN (called for wrong pcb?)", \ + (pcb)->state == LISTEN) +#endif /* TCP_LISTEN_BACKLOG */ + +void tcp_recved (struct tcp_pcb *pcb, u16_t len); +err_t tcp_bind (struct tcp_pcb *pcb, ip_addr_t *ipaddr, + u16_t port); +err_t tcp_connect (struct tcp_pcb *pcb, ip_addr_t *ipaddr, + u16_t port, tcp_connected_fn connected); + +struct tcp_pcb * tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog); +#define tcp_listen(pcb) tcp_listen_with_backlog(pcb, TCP_DEFAULT_LISTEN_BACKLOG) + +void tcp_abort (struct tcp_pcb *pcb); +err_t tcp_close (struct tcp_pcb *pcb); +err_t tcp_shutdown(struct tcp_pcb *pcb, int shut_rx, int shut_tx); + +/* Flags for "apiflags" parameter in tcp_write */ +#define TCP_WRITE_FLAG_COPY 0x01 +#define TCP_WRITE_FLAG_MORE 0x02 + +err_t tcp_write (struct tcp_pcb *pcb, const void *dataptr, u16_t len, + u8_t apiflags); + +void tcp_setprio (struct tcp_pcb *pcb, u8_t prio); + +#define TCP_PRIO_MIN 1 +#define TCP_PRIO_NORMAL 64 +#define TCP_PRIO_MAX 127 + +err_t tcp_output (struct tcp_pcb *pcb); + + +const char* tcp_debug_state_str(enum tcp_state s); + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_TCP */ + +#endif /* __LWIP_TCP_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/tcp_impl.h b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/tcp_impl.h new file mode 100644 index 0000000..985c54e --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/tcp_impl.h @@ -0,0 +1,493 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_TCP_IMPL_H__ +#define __LWIP_TCP_IMPL_H__ + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/tcp.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/ip.h" +#include "lwip/icmp.h" +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Functions for interfacing with TCP: */ + +/* Lower layer interface to TCP: */ +void tcp_init (void); /* Initialize this module. */ +void tcp_tmr (void); /* Must be called every + TCP_TMR_INTERVAL + ms. (Typically 250 ms). */ +/* It is also possible to call these two functions at the right + intervals (instead of calling tcp_tmr()). */ +void tcp_slowtmr (void); +void tcp_fasttmr (void); + + +/* Only used by IP to pass a TCP segment to TCP: */ +void tcp_input (struct pbuf *p, struct netif *inp); +/* Used within the TCP code only: */ +struct tcp_pcb * tcp_alloc (u8_t prio); +void tcp_abandon (struct tcp_pcb *pcb, int reset); +err_t tcp_send_empty_ack(struct tcp_pcb *pcb); +void tcp_rexmit (struct tcp_pcb *pcb); +void tcp_rexmit_rto (struct tcp_pcb *pcb); +void tcp_rexmit_fast (struct tcp_pcb *pcb); +u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb); +err_t tcp_process_refused_data(struct tcp_pcb *pcb); + +/** + * This is the Nagle algorithm: try to combine user data to send as few TCP + * segments as possible. Only send if + * - no previously transmitted data on the connection remains unacknowledged or + * - the TF_NODELAY flag is set (nagle algorithm turned off for this pcb) or + * - the only unsent segment is at least pcb->mss bytes long (or there is more + * than one unsent segment - with lwIP, this can happen although unsent->len < mss) + * - or if we are in fast-retransmit (TF_INFR) + */ +#define tcp_do_output_nagle(tpcb) ((((tpcb)->unacked == NULL) || \ + ((tpcb)->flags & (TF_NODELAY | TF_INFR)) || \ + (((tpcb)->unsent != NULL) && (((tpcb)->unsent->next != NULL) || \ + ((tpcb)->unsent->len >= (tpcb)->mss))) || \ + ((tcp_sndbuf(tpcb) == 0) || (tcp_sndqueuelen(tpcb) >= TCP_SND_QUEUELEN)) \ + ) ? 1 : 0) +#define tcp_output_nagle(tpcb) (tcp_do_output_nagle(tpcb) ? tcp_output(tpcb) : ERR_OK) + + +#define TCP_SEQ_LT(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) < 0) +#define TCP_SEQ_LEQ(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) <= 0) +#define TCP_SEQ_GT(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) > 0) +#define TCP_SEQ_GEQ(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) >= 0) +/* is b<=a<=c? */ +#if 0 /* see bug #10548 */ +#define TCP_SEQ_BETWEEN(a,b,c) ((c)-(b) >= (a)-(b)) +#endif +#define TCP_SEQ_BETWEEN(a,b,c) (TCP_SEQ_GEQ(a,b) && TCP_SEQ_LEQ(a,c)) +#define TCP_FIN 0x01U +#define TCP_SYN 0x02U +#define TCP_RST 0x04U +#define TCP_PSH 0x08U +#define TCP_ACK 0x10U +#define TCP_URG 0x20U +#define TCP_ECE 0x40U +#define TCP_CWR 0x80U + +#define TCP_FLAGS 0x3fU + +/* Length of the TCP header, excluding options. */ +#define TCP_HLEN 20 + +#ifndef TCP_TMR_INTERVAL +#define TCP_TMR_INTERVAL 250 /* The TCP timer interval in milliseconds. */ +#endif /* TCP_TMR_INTERVAL */ + +#ifndef TCP_FAST_INTERVAL +#define TCP_FAST_INTERVAL TCP_TMR_INTERVAL /* the fine grained timeout in milliseconds */ +#endif /* TCP_FAST_INTERVAL */ + +#ifndef TCP_SLOW_INTERVAL +#define TCP_SLOW_INTERVAL (2*TCP_TMR_INTERVAL) /* the coarse grained timeout in milliseconds */ +#endif /* TCP_SLOW_INTERVAL */ + +#define TCP_FIN_WAIT_TIMEOUT 20000 /* milliseconds */ +#define TCP_SYN_RCVD_TIMEOUT 20000 /* milliseconds */ + +#define TCP_OOSEQ_TIMEOUT 6U /* x RTO */ + +#ifndef TCP_MSL +#define TCP_MSL 60000UL /* The maximum segment lifetime in milliseconds */ +#endif + +/* Keepalive values, compliant with RFC 1122. Don't change this unless you know what you're doing */ +#ifndef TCP_KEEPIDLE_DEFAULT +#define TCP_KEEPIDLE_DEFAULT 7200000UL /* Default KEEPALIVE timer in milliseconds */ +#endif + +#ifndef TCP_KEEPINTVL_DEFAULT +#define TCP_KEEPINTVL_DEFAULT 75000UL /* Default Time between KEEPALIVE probes in milliseconds */ +#endif + +#ifndef TCP_KEEPCNT_DEFAULT +#define TCP_KEEPCNT_DEFAULT 9U /* Default Counter for KEEPALIVE probes */ +#endif + +#define TCP_MAXIDLE TCP_KEEPCNT_DEFAULT * TCP_KEEPINTVL_DEFAULT /* Maximum KEEPALIVE probe time */ + +/* Fields are (of course) in network byte order. + * Some fields are converted to host byte order in tcp_input(). + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct tcp_hdr { + PACK_STRUCT_FIELD(u16_t src); + PACK_STRUCT_FIELD(u16_t dest); + PACK_STRUCT_FIELD(u32_t seqno); + PACK_STRUCT_FIELD(u32_t ackno); + PACK_STRUCT_FIELD(u16_t _hdrlen_rsvd_flags); + PACK_STRUCT_FIELD(u16_t wnd); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u16_t urgp); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define TCPH_HDRLEN(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 12) +#define TCPH_FLAGS(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) & TCP_FLAGS) + +#define TCPH_HDRLEN_SET(phdr, len) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | TCPH_FLAGS(phdr)) +#define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = (((phdr)->_hdrlen_rsvd_flags & PP_HTONS((u16_t)(~(u16_t)(TCP_FLAGS)))) | htons(flags)) +#define TCPH_HDRLEN_FLAGS_SET(phdr, len, flags) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | (flags)) + +#define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags | htons(flags)) +#define TCPH_UNSET_FLAG(phdr, flags) (phdr)->_hdrlen_rsvd_flags = htons(ntohs((phdr)->_hdrlen_rsvd_flags) | (TCPH_FLAGS(phdr) & ~(flags)) ) + +#define TCP_TCPLEN(seg) ((seg)->len + ((TCPH_FLAGS((seg)->tcphdr) & (TCP_FIN | TCP_SYN)) != 0)) + +/** Flags used on input processing, not on pcb->flags +*/ +#define TF_RESET (u8_t)0x08U /* Connection was reset. */ +#define TF_CLOSED (u8_t)0x10U /* Connection was sucessfully closed. */ +#define TF_GOT_FIN (u8_t)0x20U /* Connection was closed by the remote end. */ + + +#if LWIP_EVENT_API + +#define TCP_EVENT_ACCEPT(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_ACCEPT, NULL, 0, err) +#define TCP_EVENT_SENT(pcb,space,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_SENT, NULL, space, ERR_OK) +#define TCP_EVENT_RECV(pcb,p,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_RECV, (p), 0, (err)) +#define TCP_EVENT_CLOSED(pcb,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_RECV, NULL, 0, ERR_OK) +#define TCP_EVENT_CONNECTED(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_CONNECTED, NULL, 0, (err)) +#define TCP_EVENT_POLL(pcb,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_POLL, NULL, 0, ERR_OK) +#define TCP_EVENT_ERR(errf,arg,err) lwip_tcp_event((arg), NULL, \ + LWIP_EVENT_ERR, NULL, 0, (err)) + +#else /* LWIP_EVENT_API */ + +#define TCP_EVENT_ACCEPT(pcb,err,ret) \ + do { \ + if((pcb)->accept != NULL) \ + (ret) = (pcb)->accept((pcb)->callback_arg,(pcb),(err)); \ + else (ret) = ERR_ARG; \ + } while (0) + +#define TCP_EVENT_SENT(pcb,space,ret) \ + do { \ + if((pcb)->sent != NULL) \ + (ret) = (pcb)->sent((pcb)->callback_arg,(pcb),(space)); \ + else (ret) = ERR_OK; \ + } while (0) + +#define TCP_EVENT_RECV(pcb,p,err,ret) \ + do { \ + if((pcb)->recv != NULL) { \ + (ret) = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err));\ + } else { \ + (ret) = tcp_recv_null(NULL, (pcb), (p), (err)); \ + } \ + } while (0) + +#define TCP_EVENT_CLOSED(pcb,ret) \ + do { \ + if(((pcb)->recv != NULL)) { \ + (ret) = (pcb)->recv((pcb)->callback_arg,(pcb),NULL,ERR_OK);\ + } else { \ + (ret) = ERR_OK; \ + } \ + } while (0) + +#define TCP_EVENT_CONNECTED(pcb,err,ret) \ + do { \ + if((pcb)->connected != NULL) \ + (ret) = (pcb)->connected((pcb)->callback_arg,(pcb),(err)); \ + else (ret) = ERR_OK; \ + } while (0) + +#define TCP_EVENT_POLL(pcb,ret) \ + do { \ + if((pcb)->poll != NULL) \ + (ret) = (pcb)->poll((pcb)->callback_arg,(pcb)); \ + else (ret) = ERR_OK; \ + } while (0) + +#define TCP_EVENT_ERR(errf,arg,err) \ + do { \ + if((errf) != NULL) \ + (errf)((arg),(err)); \ + } while (0) + +#endif /* LWIP_EVENT_API */ + +/** Enabled extra-check for TCP_OVERSIZE if LWIP_DEBUG is enabled */ +#if TCP_OVERSIZE && defined(LWIP_DEBUG) +#define TCP_OVERSIZE_DBGCHECK 1 +#else +#define TCP_OVERSIZE_DBGCHECK 0 +#endif + +/** Don't generate checksum on copy if CHECKSUM_GEN_TCP is disabled */ +#define TCP_CHECKSUM_ON_COPY (LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_TCP) + +/* This structure represents a TCP segment on the unsent, unacked and ooseq queues */ +struct tcp_seg { + struct tcp_seg *next; /* used when putting segements on a queue */ + struct pbuf *p; /* buffer containing data + TCP header */ + u16_t len; /* the TCP length of this segment */ +#if TCP_OVERSIZE_DBGCHECK + u16_t oversize_left; /* Extra bytes available at the end of the last + pbuf in unsent (used for asserting vs. + tcp_pcb.unsent_oversized only) */ +#endif /* TCP_OVERSIZE_DBGCHECK */ +#if TCP_CHECKSUM_ON_COPY + u16_t chksum; + u8_t chksum_swapped; +#endif /* TCP_CHECKSUM_ON_COPY */ + u8_t flags; +#define TF_SEG_OPTS_MSS (u8_t)0x01U /* Include MSS option. */ +#define TF_SEG_OPTS_TS (u8_t)0x02U /* Include timestamp option. */ +#define TF_SEG_DATA_CHECKSUMMED (u8_t)0x04U /* ALL data (not the header) is + checksummed into 'chksum' */ + struct tcp_hdr *tcphdr; /* the TCP header */ +}; + +#define LWIP_TCP_OPT_LENGTH(flags) \ + (flags & TF_SEG_OPTS_MSS ? 4 : 0) + \ + (flags & TF_SEG_OPTS_TS ? 12 : 0) + +/** This returns a TCP header option for MSS in an u32_t */ +#define TCP_BUILD_MSS_OPTION(mss) htonl(0x02040000 | ((mss) & 0xFFFF)) + +/* Global variables: */ +extern struct tcp_pcb *tcp_input_pcb; +extern u32_t tcp_ticks; +extern u8_t tcp_active_pcbs_changed; + +/* The TCP PCB lists. */ +union tcp_listen_pcbs_t { /* List of all TCP PCBs in LISTEN state. */ + struct tcp_pcb_listen *listen_pcbs; + struct tcp_pcb *pcbs; +}; +extern struct tcp_pcb *tcp_bound_pcbs; +extern union tcp_listen_pcbs_t tcp_listen_pcbs; +extern struct tcp_pcb *tcp_active_pcbs; /* List of all TCP PCBs that are in a + state in which they accept or send + data. */ +extern struct tcp_pcb *tcp_tw_pcbs; /* List of all TCP PCBs in TIME-WAIT. */ + +extern struct tcp_pcb *tcp_tmp_pcb; /* Only used for temporary storage. */ + +/* Axioms about the above lists: + 1) Every TCP PCB that is not CLOSED is in one of the lists. + 2) A PCB is only in one of the lists. + 3) All PCBs in the tcp_listen_pcbs list is in LISTEN state. + 4) All PCBs in the tcp_tw_pcbs list is in TIME-WAIT state. +*/ +/* Define two macros, TCP_REG and TCP_RMV that registers a TCP PCB + with a PCB list or removes a PCB from a list, respectively. */ +#ifndef TCP_DEBUG_PCB_LISTS +#define TCP_DEBUG_PCB_LISTS 0 +#endif +#if TCP_DEBUG_PCB_LISTS +#define TCP_REG(pcbs, npcb) do {\ + LWIP_DEBUGF(TCP_DEBUG, ("TCP_REG %p local port %d\n", (npcb), (npcb)->local_port)); \ + for(tcp_tmp_pcb = *(pcbs); \ + tcp_tmp_pcb != NULL; \ + tcp_tmp_pcb = tcp_tmp_pcb->next) { \ + LWIP_ASSERT("TCP_REG: already registered\n", tcp_tmp_pcb != (npcb)); \ + } \ + LWIP_ASSERT("TCP_REG: pcb->state != CLOSED", ((pcbs) == &tcp_bound_pcbs) || ((npcb)->state != CLOSED)); \ + (npcb)->next = *(pcbs); \ + LWIP_ASSERT("TCP_REG: npcb->next != npcb", (npcb)->next != (npcb)); \ + *(pcbs) = (npcb); \ + LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \ + tcp_timer_needed(); \ + } while(0) +#define TCP_RMV(pcbs, npcb) do { \ + LWIP_ASSERT("TCP_RMV: pcbs != NULL", *(pcbs) != NULL); \ + LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removing %p from %p\n", (npcb), *(pcbs))); \ + if(*(pcbs) == (npcb)) { \ + *(pcbs) = (*pcbs)->next; \ + } else for(tcp_tmp_pcb = *(pcbs); tcp_tmp_pcb != NULL; tcp_tmp_pcb = tcp_tmp_pcb->next) { \ + if(tcp_tmp_pcb->next == (npcb)) { \ + tcp_tmp_pcb->next = (npcb)->next; \ + break; \ + } \ + } \ + (npcb)->next = NULL; \ + LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \ + LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removed %p from %p\n", (npcb), *(pcbs))); \ + } while(0) + +#else /* LWIP_DEBUG */ + +#define TCP_REG(pcbs, npcb) \ + do { \ + (npcb)->next = *pcbs; \ + *(pcbs) = (npcb); \ + tcp_timer_needed(); \ + } while (0) + +#define TCP_RMV(pcbs, npcb) \ + do { \ + if(*(pcbs) == (npcb)) { \ + (*(pcbs)) = (*pcbs)->next; \ + } \ + else { \ + for(tcp_tmp_pcb = *pcbs; \ + tcp_tmp_pcb != NULL; \ + tcp_tmp_pcb = tcp_tmp_pcb->next) { \ + if(tcp_tmp_pcb->next == (npcb)) { \ + tcp_tmp_pcb->next = (npcb)->next; \ + break; \ + } \ + } \ + } \ + (npcb)->next = NULL; \ + } while(0) + +#endif /* LWIP_DEBUG */ + +#define TCP_REG_ACTIVE(npcb) \ + do { \ + TCP_REG(&tcp_active_pcbs, npcb); \ + tcp_active_pcbs_changed = 1; \ + } while (0) + +#define TCP_RMV_ACTIVE(npcb) \ + do { \ + TCP_RMV(&tcp_active_pcbs, npcb); \ + tcp_active_pcbs_changed = 1; \ + } while (0) + +#define TCP_PCB_REMOVE_ACTIVE(pcb) \ + do { \ + tcp_pcb_remove(&tcp_active_pcbs, pcb); \ + tcp_active_pcbs_changed = 1; \ + } while (0) + + +/* Internal functions: */ +struct tcp_pcb *tcp_pcb_copy(struct tcp_pcb *pcb); +void tcp_pcb_purge(struct tcp_pcb *pcb); +void tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb); + +void tcp_segs_free(struct tcp_seg *seg); +void tcp_seg_free(struct tcp_seg *seg); +struct tcp_seg *tcp_seg_copy(struct tcp_seg *seg); + +#if LWIP_TCP_DELAY_DISABLE +#define tcp_ack(pcb) \ + do { \ + (pcb)->flags |= TF_ACK_NOW; \ + } while (0) +#else +#define tcp_ack(pcb) \ + do { \ + if((pcb)->flags & TF_ACK_DELAY) { \ + (pcb)->flags &= ~TF_ACK_DELAY; \ + (pcb)->flags |= TF_ACK_NOW; \ + } \ + else { \ + (pcb)->flags |= TF_ACK_DELAY; \ + } \ + } while (0) +#endif + +#define tcp_ack_now(pcb) \ + do { \ + (pcb)->flags |= TF_ACK_NOW; \ + } while (0) + +err_t tcp_send_fin(struct tcp_pcb *pcb); +err_t tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags); + +void tcp_rexmit_seg(struct tcp_pcb *pcb, struct tcp_seg *seg); + +void tcp_rst(u32_t seqno, u32_t ackno, + ip_addr_t *local_ip, ip_addr_t *remote_ip, + u16_t local_port, u16_t remote_port); + +u32_t tcp_next_iss(void); + +void tcp_keepalive(struct tcp_pcb *pcb); +void tcp_zero_window_probe(struct tcp_pcb *pcb); + +#if TCP_CALCULATE_EFF_SEND_MSS +u16_t tcp_eff_send_mss(u16_t sendmss, ip_addr_t *addr); +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + +#if LWIP_CALLBACK_API +err_t tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err); +#endif /* LWIP_CALLBACK_API */ + +#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG +void tcp_debug_print(struct tcp_hdr *tcphdr); +void tcp_debug_print_flags(u8_t flags); +void tcp_debug_print_state(enum tcp_state s); +void tcp_debug_print_pcbs(void); +s16_t tcp_pcbs_sane(void); +#else +# define tcp_debug_print(tcphdr) +# define tcp_debug_print_flags(flags) +# define tcp_debug_print_state(s) +# define tcp_debug_print_pcbs() +# define tcp_pcbs_sane() 1 +#endif /* TCP_DEBUG */ + +/** External function (implemented in timers.c), called when TCP detects + * that a timer is needed (i.e. active- or time-wait-pcb found). */ +void tcp_timer_needed(void); + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_TCP */ + +#endif /* __LWIP_TCP_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/tcpip.h b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/tcpip.h new file mode 100644 index 0000000..08aa67a --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/tcpip.h @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_TCPIP_H__ +#define __LWIP_TCPIP_H__ + +#include "lwip/opt.h" + +#if !NO_SYS /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/api_msg.h" +#include "lwip/netifapi.h" +#include "lwip/pbuf.h" +#include "lwip/api.h" +#include "lwip/sys.h" +#include "lwip/lwip_timers.h" +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Define this to something that triggers a watchdog. This is called from + * tcpip_thread after processing a message. */ +#ifndef LWIP_TCPIP_THREAD_ALIVE +#define LWIP_TCPIP_THREAD_ALIVE() +#endif + +#if LWIP_TCPIP_CORE_LOCKING +/** The global semaphore to lock the stack. */ +extern sys_mutex_t lock_tcpip_core; +#define LOCK_TCPIP_CORE() sys_mutex_lock(&lock_tcpip_core) +#define UNLOCK_TCPIP_CORE() sys_mutex_unlock(&lock_tcpip_core) +#define TCPIP_APIMSG(m) tcpip_apimsg_lock(m) +#define TCPIP_APIMSG_ACK(m) +#define TCPIP_NETIFAPI(m) tcpip_netifapi_lock(m) +#define TCPIP_NETIFAPI_ACK(m) +#else /* LWIP_TCPIP_CORE_LOCKING */ +#define LOCK_TCPIP_CORE() +#define UNLOCK_TCPIP_CORE() +#define TCPIP_APIMSG(m) tcpip_apimsg(m) +#define TCPIP_APIMSG_ACK(m) sys_sem_signal(&m->conn->op_completed) +#define TCPIP_NETIFAPI(m) tcpip_netifapi(m) +#define TCPIP_NETIFAPI_ACK(m) sys_sem_signal(&m->sem) +#endif /* LWIP_TCPIP_CORE_LOCKING */ + +/** Function prototype for the init_done function passed to tcpip_init */ +typedef void (*tcpip_init_done_fn)(void *arg); +/** Function prototype for functions passed to tcpip_callback() */ +typedef void (*tcpip_callback_fn)(void *ctx); + +/* Forward declarations */ +struct tcpip_callback_msg; + +void tcpip_init(tcpip_init_done_fn tcpip_init_done, void *arg); + +#if LWIP_NETCONN +err_t tcpip_apimsg(struct api_msg *apimsg); +#if LWIP_TCPIP_CORE_LOCKING +err_t tcpip_apimsg_lock(struct api_msg *apimsg); +#endif /* LWIP_TCPIP_CORE_LOCKING */ +#endif /* LWIP_NETCONN */ + +err_t tcpip_input(struct pbuf *p, struct netif *inp); + +#if LWIP_NETIF_API +err_t tcpip_netifapi(struct netifapi_msg *netifapimsg); +#if LWIP_TCPIP_CORE_LOCKING +err_t tcpip_netifapi_lock(struct netifapi_msg *netifapimsg); +#endif /* LWIP_TCPIP_CORE_LOCKING */ +#endif /* LWIP_NETIF_API */ + +err_t tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block); +#define tcpip_callback(f, ctx) tcpip_callback_with_block(f, ctx, 1) + +struct tcpip_callback_msg* tcpip_callbackmsg_new(tcpip_callback_fn function, void *ctx); +void tcpip_callbackmsg_delete(struct tcpip_callback_msg* msg); +err_t tcpip_trycallback(struct tcpip_callback_msg* msg); + +/* free pbufs or heap memory from another context without blocking */ +err_t pbuf_free_callback(struct pbuf *p); +err_t mem_free_callback(void *m); + +#if LWIP_TCPIP_TIMEOUT +err_t tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg); +err_t tcpip_untimeout(sys_timeout_handler h, void *arg); +#endif /* LWIP_TCPIP_TIMEOUT */ + +enum tcpip_msg_type { +#if LWIP_NETCONN + TCPIP_MSG_API, +#endif /* LWIP_NETCONN */ + TCPIP_MSG_INPKT, +#if LWIP_NETIF_API + TCPIP_MSG_NETIFAPI, +#endif /* LWIP_NETIF_API */ +#if LWIP_TCPIP_TIMEOUT + TCPIP_MSG_TIMEOUT, + TCPIP_MSG_UNTIMEOUT, +#endif /* LWIP_TCPIP_TIMEOUT */ + TCPIP_MSG_CALLBACK, + TCPIP_MSG_CALLBACK_STATIC +}; + +struct tcpip_msg { + enum tcpip_msg_type type; + sys_sem_t *sem; + union { +#if LWIP_NETCONN + struct api_msg *apimsg; +#endif /* LWIP_NETCONN */ +#if LWIP_NETIF_API + struct netifapi_msg *netifapimsg; +#endif /* LWIP_NETIF_API */ + struct { + struct pbuf *p; + struct netif *netif; + } inp; + struct { + tcpip_callback_fn function; + void *ctx; + } cb; +#if LWIP_TCPIP_TIMEOUT + struct { + u32_t msecs; + sys_timeout_handler h; + void *arg; + } tmo; +#endif /* LWIP_TCPIP_TIMEOUT */ + } msg; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* !NO_SYS */ + +#endif /* __LWIP_TCPIP_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/udp.h b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/udp.h new file mode 100644 index 0000000..f1e6d3f --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/lwip/udp.h @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_UDP_H__ +#define __LWIP_UDP_H__ + +#include "lwip/opt.h" + +#if LWIP_UDP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/ip_addr.h" +#include "lwip/ip.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define UDP_HLEN 8 + +/* Fields are (of course) in network byte order. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct udp_hdr { + PACK_STRUCT_FIELD(u16_t src); + PACK_STRUCT_FIELD(u16_t dest); /* src/dest UDP ports */ + PACK_STRUCT_FIELD(u16_t len); + PACK_STRUCT_FIELD(u16_t chksum); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define UDP_FLAGS_NOCHKSUM 0x01U +#define UDP_FLAGS_UDPLITE 0x02U +#define UDP_FLAGS_CONNECTED 0x04U +#define UDP_FLAGS_MULTICAST_LOOP 0x08U + +struct udp_pcb; + +/** Function prototype for udp pcb receive callback functions + * addr and port are in same byte order as in the pcb + * The callback is responsible for freeing the pbuf + * if it's not used any more. + * + * ATTENTION: Be aware that 'addr' points into the pbuf 'p' so freeing this pbuf + * makes 'addr' invalid, too. + * + * @param arg user supplied argument (udp_pcb.recv_arg) + * @param pcb the udp_pcb which received data + * @param p the packet buffer that was received + * @param addr the remote IP address from which the packet was received + * @param port the remote port from which the packet was received + */ +typedef void (*udp_recv_fn)(void *arg, struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *addr, u16_t port); + + +struct udp_pcb { +/* Common members of all PCB types */ + IP_PCB; + +/* Protocol specific PCB members */ + + struct udp_pcb *next; + + u8_t flags; + /** ports are in host byte order */ + u16_t local_port, remote_port; + +#if LWIP_IGMP + /** outgoing network interface for multicast packets */ + ip_addr_t multicast_ip; +#endif /* LWIP_IGMP */ + +#if LWIP_UDPLITE + /** used for UDP_LITE only */ + u16_t chksum_len_rx, chksum_len_tx; +#endif /* LWIP_UDPLITE */ + + /** receive callback function */ + udp_recv_fn recv; + /** user-supplied argument for the recv callback */ + void *recv_arg; +}; +/* udp_pcbs export for exernal reference (e.g. SNMP agent) */ +extern struct udp_pcb *udp_pcbs; + +/* The following functions is the application layer interface to the + UDP code. */ +struct udp_pcb * udp_new (void); +void udp_remove (struct udp_pcb *pcb); +err_t udp_bind (struct udp_pcb *pcb, ip_addr_t *ipaddr, + u16_t port); +err_t udp_connect (struct udp_pcb *pcb, ip_addr_t *ipaddr, + u16_t port); +void udp_disconnect (struct udp_pcb *pcb); +void udp_recv (struct udp_pcb *pcb, udp_recv_fn recv, + void *recv_arg); +err_t udp_sendto_if (struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *dst_ip, u16_t dst_port, + struct netif *netif); +err_t udp_sendto (struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *dst_ip, u16_t dst_port); +err_t udp_send (struct udp_pcb *pcb, struct pbuf *p); + +#if LWIP_CHECKSUM_ON_COPY +err_t udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *dst_ip, u16_t dst_port, + struct netif *netif, u8_t have_chksum, + u16_t chksum); +err_t udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *dst_ip, u16_t dst_port, + u8_t have_chksum, u16_t chksum); +err_t udp_send_chksum(struct udp_pcb *pcb, struct pbuf *p, + u8_t have_chksum, u16_t chksum); +#endif /* LWIP_CHECKSUM_ON_COPY */ + +#define udp_flags(pcb) ((pcb)->flags) +#define udp_setflags(pcb, f) ((pcb)->flags = (f)) + +/* The following functions are the lower layer interface to UDP. */ +void udp_input (struct pbuf *p, struct netif *inp); + +void udp_init (void); + +#if UDP_DEBUG +void udp_debug_print(struct udp_hdr *udphdr); +#else +#define udp_debug_print(udphdr) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_UDP */ + +#endif /* __LWIP_UDP_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/netif/etharp.h b/component/common/network/lwip/lwip_v1.4.1/src/include/netif/etharp.h new file mode 100644 index 0000000..859608d --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/netif/etharp.h @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * Copyright (c) 2003-2004 Leon Woestenberg + * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#ifndef __NETIF_ETHARP_H__ +#define __NETIF_ETHARP_H__ + +#include "lwip/opt.h" + +#if LWIP_ARP || LWIP_ETHERNET /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/ip.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef ETHARP_HWADDR_LEN +#define ETHARP_HWADDR_LEN 6 +#endif + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct eth_addr { + PACK_STRUCT_FIELD(u8_t addr[ETHARP_HWADDR_LEN]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** Ethernet header */ +struct eth_hdr { +#if ETH_PAD_SIZE + PACK_STRUCT_FIELD(u8_t padding[ETH_PAD_SIZE]); +#endif + PACK_STRUCT_FIELD(struct eth_addr dest); + PACK_STRUCT_FIELD(struct eth_addr src); + PACK_STRUCT_FIELD(u16_t type); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define SIZEOF_ETH_HDR (14 + ETH_PAD_SIZE) + +#if ETHARP_SUPPORT_VLAN + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** VLAN header inserted between ethernet header and payload + * if 'type' in ethernet header is ETHTYPE_VLAN. + * See IEEE802.Q */ +struct eth_vlan_hdr { + PACK_STRUCT_FIELD(u16_t prio_vid); + PACK_STRUCT_FIELD(u16_t tpid); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define SIZEOF_VLAN_HDR 4 +#define VLAN_ID(vlan_hdr) (htons((vlan_hdr)->prio_vid) & 0xFFF) + +#endif /* ETHARP_SUPPORT_VLAN */ + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** the ARP message, see RFC 826 ("Packet format") */ +struct etharp_hdr { + PACK_STRUCT_FIELD(u16_t hwtype); + PACK_STRUCT_FIELD(u16_t proto); + PACK_STRUCT_FIELD(u8_t hwlen); + PACK_STRUCT_FIELD(u8_t protolen); + PACK_STRUCT_FIELD(u16_t opcode); + PACK_STRUCT_FIELD(struct eth_addr shwaddr); + PACK_STRUCT_FIELD(struct ip_addr2 sipaddr); + PACK_STRUCT_FIELD(struct eth_addr dhwaddr); + PACK_STRUCT_FIELD(struct ip_addr2 dipaddr); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define SIZEOF_ETHARP_HDR 28 +#define SIZEOF_ETHARP_PACKET (SIZEOF_ETH_HDR + SIZEOF_ETHARP_HDR) + +/** 5 seconds period */ +#define ARP_TMR_INTERVAL 5000 + +#define ETHTYPE_ARP 0x0806U +#define ETHTYPE_IP 0x0800U +#define ETHTYPE_VLAN 0x8100U +#define ETHTYPE_PPPOEDISC 0x8863U /* PPP Over Ethernet Discovery Stage */ +#define ETHTYPE_PPPOE 0x8864U /* PPP Over Ethernet Session Stage */ + +/** MEMCPY-like macro to copy to/from struct eth_addr's that are local variables + * or known to be 32-bit aligned within the protocol header. */ +#ifndef ETHADDR32_COPY +#define ETHADDR32_COPY(src, dst) SMEMCPY(src, dst, ETHARP_HWADDR_LEN) +#endif + +/** MEMCPY-like macro to copy to/from struct eth_addr's that are no local + * variables and known to be 16-bit aligned within the protocol header. */ +#ifndef ETHADDR16_COPY +#define ETHADDR16_COPY(src, dst) SMEMCPY(src, dst, ETHARP_HWADDR_LEN) +#endif + +#if LWIP_ARP /* don't build if not configured for use in lwipopts.h */ + +/** ARP message types (opcodes) */ +#define ARP_REQUEST 1 +#define ARP_REPLY 2 + +/** Define this to 1 and define LWIP_ARP_FILTER_NETIF_FN(pbuf, netif, type) + * to a filter function that returns the correct netif when using multiple + * netifs on one hardware interface where the netif's low-level receive + * routine cannot decide for the correct netif (e.g. when mapping multiple + * IP addresses to one hardware interface). + */ +#ifndef LWIP_ARP_FILTER_NETIF +#define LWIP_ARP_FILTER_NETIF 0 +#endif + +#if ARP_QUEUEING +/** struct for queueing outgoing packets for unknown address + * defined here to be accessed by memp.h + */ +struct etharp_q_entry { + struct etharp_q_entry *next; + struct pbuf *p; +}; +#endif /* ARP_QUEUEING */ + +#define etharp_init() /* Compatibility define, not init needed. */ +void etharp_tmr(void); +s8_t etharp_find_addr(struct netif *netif, ip_addr_t *ipaddr, + struct eth_addr **eth_ret, ip_addr_t **ip_ret); +err_t etharp_output(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr); +err_t etharp_query(struct netif *netif, ip_addr_t *ipaddr, struct pbuf *q); +err_t etharp_request(struct netif *netif, ip_addr_t *ipaddr); +/** For Ethernet network interfaces, we might want to send "gratuitous ARP"; + * this is an ARP packet sent by a node in order to spontaneously cause other + * nodes to update an entry in their ARP cache. + * From RFC 3220 "IP Mobility Support for IPv4" section 4.6. */ +#define etharp_gratuitous(netif) etharp_request((netif), &(netif)->ip_addr) +void etharp_cleanup_netif(struct netif *netif); + +#if ETHARP_SUPPORT_STATIC_ENTRIES +err_t etharp_add_static_entry(ip_addr_t *ipaddr, struct eth_addr *ethaddr); +err_t etharp_remove_static_entry(ip_addr_t *ipaddr); +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + +#if LWIP_AUTOIP +err_t etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr, + const struct eth_addr *ethdst_addr, + const struct eth_addr *hwsrc_addr, const ip_addr_t *ipsrc_addr, + const struct eth_addr *hwdst_addr, const ip_addr_t *ipdst_addr, + const u16_t opcode); +#endif /* LWIP_AUTOIP */ + +#endif /* LWIP_ARP */ + +err_t ethernet_input(struct pbuf *p, struct netif *netif); + +#define eth_addr_cmp(addr1, addr2) (memcmp((addr1)->addr, (addr2)->addr, ETHARP_HWADDR_LEN) == 0) + +extern const struct eth_addr ethbroadcast, ethzero; + +#endif /* LWIP_ARP || LWIP_ETHERNET */ + +#ifdef __cplusplus +} +#endif + +#endif /* __NETIF_ARP_H__ */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/netif/loopif.h b/component/common/network/lwip/lwip_v1.4.1/src/include/netif/loopif.h new file mode 100644 index 0000000..e69de29 diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/netif/ppp_oe.h b/component/common/network/lwip/lwip_v1.4.1/src/include/netif/ppp_oe.h new file mode 100644 index 0000000..e1cdfa5 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/netif/ppp_oe.h @@ -0,0 +1,190 @@ +/***************************************************************************** +* ppp_oe.h - PPP Over Ethernet implementation for lwIP. +* +* Copyright (c) 2006 by Marc Boucher, Services Informatiques (MBSI) inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 06-01-01 Marc Boucher +* Ported to lwIP. +*****************************************************************************/ + + + +/* based on NetBSD: if_pppoe.c,v 1.64 2006/01/31 23:50:15 martin Exp */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Martin Husemann . + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 PPP_OE_H +#define PPP_OE_H + +#include "lwip/opt.h" + +#if PPPOE_SUPPORT > 0 + +#include "netif/etharp.h" + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct pppoehdr { + PACK_STRUCT_FIELD(u8_t vertype); + PACK_STRUCT_FIELD(u8_t code); + PACK_STRUCT_FIELD(u16_t session); + PACK_STRUCT_FIELD(u16_t plen); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct pppoetag { + PACK_STRUCT_FIELD(u16_t tag); + PACK_STRUCT_FIELD(u16_t len); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + + +#define PPPOE_STATE_INITIAL 0 +#define PPPOE_STATE_PADI_SENT 1 +#define PPPOE_STATE_PADR_SENT 2 +#define PPPOE_STATE_SESSION 3 +#define PPPOE_STATE_CLOSING 4 +/* passive */ +#define PPPOE_STATE_PADO_SENT 1 + +#define PPPOE_HEADERLEN sizeof(struct pppoehdr) +#define PPPOE_VERTYPE 0x11 /* VER=1, TYPE = 1 */ + +#define PPPOE_TAG_EOL 0x0000 /* end of list */ +#define PPPOE_TAG_SNAME 0x0101 /* service name */ +#define PPPOE_TAG_ACNAME 0x0102 /* access concentrator name */ +#define PPPOE_TAG_HUNIQUE 0x0103 /* host unique */ +#define PPPOE_TAG_ACCOOKIE 0x0104 /* AC cookie */ +#define PPPOE_TAG_VENDOR 0x0105 /* vendor specific */ +#define PPPOE_TAG_RELAYSID 0x0110 /* relay session id */ +#define PPPOE_TAG_SNAME_ERR 0x0201 /* service name error */ +#define PPPOE_TAG_ACSYS_ERR 0x0202 /* AC system error */ +#define PPPOE_TAG_GENERIC_ERR 0x0203 /* gerneric error */ + +#define PPPOE_CODE_PADI 0x09 /* Active Discovery Initiation */ +#define PPPOE_CODE_PADO 0x07 /* Active Discovery Offer */ +#define PPPOE_CODE_PADR 0x19 /* Active Discovery Request */ +#define PPPOE_CODE_PADS 0x65 /* Active Discovery Session confirmation */ +#define PPPOE_CODE_PADT 0xA7 /* Active Discovery Terminate */ + +#ifndef ETHERMTU +#define ETHERMTU 1500 +#endif + +/* two byte PPP protocol discriminator, then IP data */ +#define PPPOE_MAXMTU (ETHERMTU-PPPOE_HEADERLEN-2) + +#ifndef PPPOE_MAX_AC_COOKIE_LEN +#define PPPOE_MAX_AC_COOKIE_LEN 64 +#endif + +struct pppoe_softc { + struct pppoe_softc *next; + struct netif *sc_ethif; /* ethernet interface we are using */ + int sc_pd; /* ppp unit number */ + void (*sc_linkStatusCB)(int pd, int up); + + int sc_state; /* discovery phase or session connected */ + struct eth_addr sc_dest; /* hardware address of concentrator */ + u16_t sc_session; /* PPPoE session id */ + +#ifdef PPPOE_TODO + char *sc_service_name; /* if != NULL: requested name of service */ + char *sc_concentrator_name; /* if != NULL: requested concentrator id */ +#endif /* PPPOE_TODO */ + u8_t sc_ac_cookie[PPPOE_MAX_AC_COOKIE_LEN]; /* content of AC cookie we must echo back */ + size_t sc_ac_cookie_len; /* length of cookie data */ +#ifdef PPPOE_SERVER + u8_t *sc_hunique; /* content of host unique we must echo back */ + size_t sc_hunique_len; /* length of host unique */ +#endif + int sc_padi_retried; /* number of PADI retries already done */ + int sc_padr_retried; /* number of PADR retries already done */ +}; + + +#define pppoe_init() /* compatibility define, no initialization needed */ + +err_t pppoe_create(struct netif *ethif, int pd, void (*linkStatusCB)(int pd, int up), struct pppoe_softc **scptr); +err_t pppoe_destroy(struct netif *ifp); + +int pppoe_connect(struct pppoe_softc *sc); +void pppoe_disconnect(struct pppoe_softc *sc); + +void pppoe_disc_input(struct netif *netif, struct pbuf *p); +void pppoe_data_input(struct netif *netif, struct pbuf *p); + +err_t pppoe_xmit(struct pppoe_softc *sc, struct pbuf *pb); + +/** used in ppp.c */ +#define PPPOE_HDRLEN (sizeof(struct eth_hdr) + PPPOE_HEADERLEN) + +#endif /* PPPOE_SUPPORT */ + +#endif /* PPP_OE_H */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/netif/slipif.h b/component/common/network/lwip/lwip_v1.4.1/src/include/netif/slipif.h new file mode 100644 index 0000000..7b6ce5e --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/netif/slipif.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2001, Swedish Institute of Computer Science. + * 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 Institute 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 INSTITUTE 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 INSTITUTE 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __NETIF_SLIPIF_H__ +#define __NETIF_SLIPIF_H__ + +#include "lwip/opt.h" +#include "lwip/netif.h" + +/** Set this to 1 to start a thread that blocks reading on the serial line + * (using sio_read()). + */ +#ifndef SLIP_USE_RX_THREAD +#define SLIP_USE_RX_THREAD !NO_SYS +#endif + +/** Set this to 1 to enable functions to pass in RX bytes from ISR context. + * If enabled, slipif_received_byte[s]() process incoming bytes and put assembled + * packets on a queue, which is fed into lwIP from slipif_poll(). + * If disabled, slipif_poll() polls the serila line (using sio_tryread()). + */ +#ifndef SLIP_RX_FROM_ISR +#define SLIP_RX_FROM_ISR 0 +#endif + +/** Set this to 1 (default for SLIP_RX_FROM_ISR) to queue incoming packets + * received by slipif_received_byte[s]() as long as PBUF_POOL pbufs are available. + * If disabled, packets will be dropped if more than one packet is received. + */ +#ifndef SLIP_RX_QUEUE +#define SLIP_RX_QUEUE SLIP_RX_FROM_ISR +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +err_t slipif_init(struct netif * netif); +void slipif_poll(struct netif *netif); +#if SLIP_RX_FROM_ISR +void slipif_process_rxqueue(struct netif *netif); +void slipif_received_byte(struct netif *netif, u8_t data); +void slipif_received_bytes(struct netif *netif, u8_t *data, u8_t len); +#endif /* SLIP_RX_FROM_ISR */ + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/posix/netdb.h b/component/common/network/lwip/lwip_v1.4.1/src/include/posix/netdb.h new file mode 100644 index 0000000..7134032 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/posix/netdb.h @@ -0,0 +1,33 @@ +/** + * @file + * This file is a posix wrapper for lwip/netdb.h. + */ + +/* + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/netdb.h" diff --git a/component/common/network/lwip/lwip_v1.4.1/src/include/posix/sys/socket.h b/component/common/network/lwip/lwip_v1.4.1/src/include/posix/sys/socket.h new file mode 100644 index 0000000..f7c7066 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/include/posix/sys/socket.h @@ -0,0 +1,33 @@ +/** + * @file + * This file is a posix wrapper for lwip/sockets.h. + */ + +/* + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/sockets.h" diff --git a/component/common/network/lwip/lwip_v1.4.1/src/netif/FILES b/component/common/network/lwip/lwip_v1.4.1/src/netif/FILES new file mode 100644 index 0000000..099dbf3 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/netif/FILES @@ -0,0 +1,29 @@ +This directory contains generic network interface device drivers that +do not contain any hardware or architecture specific code. The files +are: + +etharp.c + Implements the ARP (Address Resolution Protocol) over + Ethernet. The code in this file should be used together with + Ethernet device drivers. Note that this module has been + largely made Ethernet independent so you should be able to + adapt this for other link layers (such as Firewire). + +ethernetif.c + An example of how an Ethernet device driver could look. This + file can be used as a "skeleton" for developing new Ethernet + network device drivers. It uses the etharp.c ARP code. + +loopif.c + A "loopback" network interface driver. It requires configuration + through the define LWIP_LOOPIF_MULTITHREADING (see opt.h). + +slipif.c + A generic implementation of the SLIP (Serial Line IP) + protocol. It requires a sio (serial I/O) module to work. + +ppp/ Point-to-Point Protocol stack + The PPP stack has been ported from ucip (http://ucip.sourceforge.net). + It matches quite well to pppd 2.3.1 (http://ppp.samba.org), although + compared to that, it has some modifications for embedded systems and + the source code has been reordered a bit. \ No newline at end of file diff --git a/component/common/network/lwip/lwip_v1.4.1/src/netif/etharp.c b/component/common/network/lwip/lwip_v1.4.1/src/netif/etharp.c new file mode 100644 index 0000000..5e382d1 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/netif/etharp.c @@ -0,0 +1,1399 @@ +/** + * @file + * Address Resolution Protocol module for IP over Ethernet + * + * Functionally, ARP is divided into two parts. The first maps an IP address + * to a physical address when sending a packet, and the second part answers + * requests from other machines for our physical address. + * + * This implementation complies with RFC 826 (Ethernet ARP). It supports + * Gratuitious ARP from RFC3220 (IP Mobility Support for IPv4) section 4.6 + * if an interface calls etharp_gratuitous(our_netif) upon address change. + */ + +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * Copyright (c) 2003-2004 Leon Woestenberg + * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/opt.h" + +#if LWIP_ARP || LWIP_ETHERNET + +#include "lwip/ip_addr.h" +#include "lwip/def.h" +#include "lwip/ip.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" +#include "netif/etharp.h" + +#if PPPOE_SUPPORT +#include "netif/ppp_oe.h" +#endif /* PPPOE_SUPPORT */ + +#include + +const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}}; +const struct eth_addr ethzero = {{0,0,0,0,0,0}}; + +/** The 24-bit IANA multicast OUI is 01-00-5e: */ +#define LL_MULTICAST_ADDR_0 0x01 +#define LL_MULTICAST_ADDR_1 0x00 +#define LL_MULTICAST_ADDR_2 0x5e + +#if LWIP_ARP /* don't build if not configured for use in lwipopts.h */ + +/** the time an ARP entry stays valid after its last update, + * for ARP_TMR_INTERVAL = 5000, this is + * (240 * 5) seconds = 20 minutes. + */ +#define ARP_MAXAGE 240 +/** Re-request a used ARP entry 1 minute before it would expire to prevent + * breaking a steadily used connection because the ARP entry timed out. */ +#define ARP_AGE_REREQUEST_USED (ARP_MAXAGE - 12) + +/** the time an ARP entry stays pending after first request, + * for ARP_TMR_INTERVAL = 5000, this is + * (2 * 5) seconds = 10 seconds. + * + * @internal Keep this number at least 2, otherwise it might + * run out instantly if the timeout occurs directly after a request. + */ +#define ARP_MAXPENDING 2 + +#define HWTYPE_ETHERNET 1 + +enum etharp_state { + ETHARP_STATE_EMPTY = 0, + ETHARP_STATE_PENDING, + ETHARP_STATE_STABLE, + ETHARP_STATE_STABLE_REREQUESTING +#if ETHARP_SUPPORT_STATIC_ENTRIES + ,ETHARP_STATE_STATIC +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ +}; + +struct etharp_entry { +#if ARP_QUEUEING + /** Pointer to queue of pending outgoing packets on this ARP entry. */ + struct etharp_q_entry *q; +#else /* ARP_QUEUEING */ + /** Pointer to a single pending outgoing packet on this ARP entry. */ + struct pbuf *q; +#endif /* ARP_QUEUEING */ + ip_addr_t ipaddr; + struct netif *netif; + struct eth_addr ethaddr; + u8_t state; + u8_t ctime; +}; + +static struct etharp_entry arp_table[ARP_TABLE_SIZE]; + +#if !LWIP_NETIF_HWADDRHINT +static u8_t etharp_cached_entry; +#endif /* !LWIP_NETIF_HWADDRHINT */ + +/** Try hard to create a new entry - we want the IP address to appear in + the cache (even if this means removing an active entry or so). */ +#define ETHARP_FLAG_TRY_HARD 1 +#define ETHARP_FLAG_FIND_ONLY 2 +#if ETHARP_SUPPORT_STATIC_ENTRIES +#define ETHARP_FLAG_STATIC_ENTRY 4 +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + +#if LWIP_NETIF_HWADDRHINT +#define ETHARP_SET_HINT(netif, hint) if (((netif) != NULL) && ((netif)->addr_hint != NULL)) \ + *((netif)->addr_hint) = (hint); +#else /* LWIP_NETIF_HWADDRHINT */ +#define ETHARP_SET_HINT(netif, hint) (etharp_cached_entry = (hint)) +#endif /* LWIP_NETIF_HWADDRHINT */ + + +/* Some checks, instead of etharp_init(): */ +#if (LWIP_ARP && (ARP_TABLE_SIZE > 0x7f)) + #error "ARP_TABLE_SIZE must fit in an s8_t, you have to reduce it in your lwipopts.h" +#endif + + +#if ARP_QUEUEING +/** + * Free a complete queue of etharp entries + * + * @param q a qeueue of etharp_q_entry's to free + */ +static void +free_etharp_q(struct etharp_q_entry *q) +{ + struct etharp_q_entry *r; + LWIP_ASSERT("q != NULL", q != NULL); + LWIP_ASSERT("q->p != NULL", q->p != NULL); + while (q) { + r = q; + q = q->next; + LWIP_ASSERT("r->p != NULL", (r->p != NULL)); + pbuf_free(r->p); + memp_free(MEMP_ARP_QUEUE, r); + } +} +#else /* ARP_QUEUEING */ + +/** Compatibility define: free the queued pbuf */ +#define free_etharp_q(q) pbuf_free(q) + +#endif /* ARP_QUEUEING */ + +/** Clean up ARP table entries */ +static void +etharp_free_entry(int i) +{ + /* remove from SNMP ARP index tree */ + snmp_delete_arpidx_tree(arp_table[i].netif, &arp_table[i].ipaddr); + /* and empty packet queue */ + if (arp_table[i].q != NULL) { + /* remove all queued packets */ + LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_free_entry: freeing entry %"U16_F", packet queue %p.\n", (u16_t)i, (void *)(arp_table[i].q))); + free_etharp_q(arp_table[i].q); + arp_table[i].q = NULL; + } + /* recycle entry for re-use */ + arp_table[i].state = ETHARP_STATE_EMPTY; +#ifdef LWIP_DEBUG + /* for debugging, clean out the complete entry */ + arp_table[i].ctime = 0; + arp_table[i].netif = NULL; + ip_addr_set_zero(&arp_table[i].ipaddr); + arp_table[i].ethaddr = ethzero; +#endif /* LWIP_DEBUG */ +} + +/** + * Clears expired entries in the ARP table. + * + * This function should be called every ETHARP_TMR_INTERVAL milliseconds (5 seconds), + * in order to expire entries in the ARP table. + */ +void +etharp_tmr(void) +{ + u8_t i; + + LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer\n")); + /* remove expired entries from the ARP table */ + for (i = 0; i < ARP_TABLE_SIZE; ++i) { + u8_t state = arp_table[i].state; + if (state != ETHARP_STATE_EMPTY +#if ETHARP_SUPPORT_STATIC_ENTRIES + && (state != ETHARP_STATE_STATIC) +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + ) { + arp_table[i].ctime++; + if ((arp_table[i].ctime >= ARP_MAXAGE) || + ((arp_table[i].state == ETHARP_STATE_PENDING) && + (arp_table[i].ctime >= ARP_MAXPENDING))) { + /* pending or stable entry has become old! */ + LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired %s entry %"U16_F".\n", + arp_table[i].state >= ETHARP_STATE_STABLE ? "stable" : "pending", (u16_t)i)); + /* clean up entries that have just been expired */ + etharp_free_entry(i); + } + else if (arp_table[i].state == ETHARP_STATE_STABLE_REREQUESTING) { + /* Reset state to stable, so that the next transmitted packet will + re-send an ARP request. */ + arp_table[i].state = ETHARP_STATE_STABLE; + } +#if ARP_QUEUEING + /* still pending entry? (not expired) */ + if (arp_table[i].state == ETHARP_STATE_PENDING) { + /* resend an ARP query here? */ + } +#endif /* ARP_QUEUEING */ + } + } +} + +/** + * Search the ARP table for a matching or new entry. + * + * If an IP address is given, return a pending or stable ARP entry that matches + * the address. If no match is found, create a new entry with this address set, + * but in state ETHARP_EMPTY. The caller must check and possibly change the + * state of the returned entry. + * + * If ipaddr is NULL, return a initialized new entry in state ETHARP_EMPTY. + * + * In all cases, attempt to create new entries from an empty entry. If no + * empty entries are available and ETHARP_FLAG_TRY_HARD flag is set, recycle + * old entries. Heuristic choose the least important entry for recycling. + * + * @param ipaddr IP address to find in ARP cache, or to add if not found. + * @param flags @see definition of ETHARP_FLAG_* + * @param netif netif related to this address (used for NETIF_HWADDRHINT) + * + * @return The ARP entry index that matched or is created, ERR_MEM if no + * entry is found or could be recycled. + */ +static s8_t +etharp_find_entry(ip_addr_t *ipaddr, u8_t flags) +{ + s8_t old_pending = ARP_TABLE_SIZE, old_stable = ARP_TABLE_SIZE; + s8_t empty = ARP_TABLE_SIZE; + u8_t i = 0, age_pending = 0, age_stable = 0; + /* oldest entry with packets on queue */ + s8_t old_queue = ARP_TABLE_SIZE; + /* its age */ + u8_t age_queue = 0; + + /** + * a) do a search through the cache, remember candidates + * b) select candidate entry + * c) create new entry + */ + + /* a) in a single search sweep, do all of this + * 1) remember the first empty entry (if any) + * 2) remember the oldest stable entry (if any) + * 3) remember the oldest pending entry without queued packets (if any) + * 4) remember the oldest pending entry with queued packets (if any) + * 5) search for a matching IP entry, either pending or stable + * until 5 matches, or all entries are searched for. + */ + + for (i = 0; i < ARP_TABLE_SIZE; ++i) { + u8_t state = arp_table[i].state; + /* no empty entry found yet and now we do find one? */ + if ((empty == ARP_TABLE_SIZE) && (state == ETHARP_STATE_EMPTY)) { + LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_find_entry: found empty entry %"U16_F"\n", (u16_t)i)); + /* remember first empty entry */ + empty = i; + } else if (state != ETHARP_STATE_EMPTY) { + LWIP_ASSERT("state == ETHARP_STATE_PENDING || state >= ETHARP_STATE_STABLE", + state == ETHARP_STATE_PENDING || state >= ETHARP_STATE_STABLE); + /* if given, does IP address match IP address in ARP entry? */ + if (ipaddr && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: found matching entry %"U16_F"\n", (u16_t)i)); + /* found exact IP address match, simply bail out */ + return i; + } + /* pending entry? */ + if (state == ETHARP_STATE_PENDING) { + /* pending with queued packets? */ + if (arp_table[i].q != NULL) { + if (arp_table[i].ctime >= age_queue) { + old_queue = i; + age_queue = arp_table[i].ctime; + } + } else + /* pending without queued packets? */ + { + if (arp_table[i].ctime >= age_pending) { + old_pending = i; + age_pending = arp_table[i].ctime; + } + } + /* stable entry? */ + } else if (state >= ETHARP_STATE_STABLE) { +#if ETHARP_SUPPORT_STATIC_ENTRIES + /* don't record old_stable for static entries since they never expire */ + if (state < ETHARP_STATE_STATIC) +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + { + /* remember entry with oldest stable entry in oldest, its age in maxtime */ + if (arp_table[i].ctime >= age_stable) { + old_stable = i; + age_stable = arp_table[i].ctime; + } + } + } + } + } + /* { we have no match } => try to create a new entry */ + + /* don't create new entry, only search? */ + if (((flags & ETHARP_FLAG_FIND_ONLY) != 0) || + /* or no empty entry found and not allowed to recycle? */ + ((empty == ARP_TABLE_SIZE) && ((flags & ETHARP_FLAG_TRY_HARD) == 0))) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: no empty entry found and not allowed to recycle\n")); + return (s8_t)ERR_MEM; + } + + /* b) choose the least destructive entry to recycle: + * 1) empty entry + * 2) oldest stable entry + * 3) oldest pending entry without queued packets + * 4) oldest pending entry with queued packets + * + * { ETHARP_FLAG_TRY_HARD is set at this point } + */ + + /* 1) empty entry available? */ + if (empty < ARP_TABLE_SIZE) { + i = empty; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting empty entry %"U16_F"\n", (u16_t)i)); + } else { + /* 2) found recyclable stable entry? */ + if (old_stable < ARP_TABLE_SIZE) { + /* recycle oldest stable*/ + i = old_stable; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest stable entry %"U16_F"\n", (u16_t)i)); + /* no queued packets should exist on stable entries */ + LWIP_ASSERT("arp_table[i].q == NULL", arp_table[i].q == NULL); + /* 3) found recyclable pending entry without queued packets? */ + } else if (old_pending < ARP_TABLE_SIZE) { + /* recycle oldest pending */ + i = old_pending; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest pending entry %"U16_F" (without queue)\n", (u16_t)i)); + /* 4) found recyclable pending entry with queued packets? */ + } else if (old_queue < ARP_TABLE_SIZE) { + /* recycle oldest pending (queued packets are free in etharp_free_entry) */ + i = old_queue; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest pending entry %"U16_F", freeing packet queue %p\n", (u16_t)i, (void *)(arp_table[i].q))); + /* no empty or recyclable entries found */ + } else { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: no empty or recyclable entries found\n")); + return (s8_t)ERR_MEM; + } + + /* { empty or recyclable entry found } */ + LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE); + etharp_free_entry(i); + } + + LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE); + LWIP_ASSERT("arp_table[i].state == ETHARP_STATE_EMPTY", + arp_table[i].state == ETHARP_STATE_EMPTY); + + /* IP address given? */ + if (ipaddr != NULL) { + /* set IP address */ + ip_addr_copy(arp_table[i].ipaddr, *ipaddr); + } + arp_table[i].ctime = 0; + return (err_t)i; +} + +/** + * Send an IP packet on the network using netif->linkoutput + * The ethernet header is filled in before sending. + * + * @params netif the lwIP network interface on which to send the packet + * @params p the packet to send, p->payload pointing to the (uninitialized) ethernet header + * @params src the source MAC address to be copied into the ethernet header + * @params dst the destination MAC address to be copied into the ethernet header + * @return ERR_OK if the packet was sent, any other err_t on failure + */ +static err_t +etharp_send_ip(struct netif *netif, struct pbuf *p, struct eth_addr *src, struct eth_addr *dst) +{ + struct eth_hdr *ethhdr = (struct eth_hdr *)p->payload; + + LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!", + (netif->hwaddr_len == ETHARP_HWADDR_LEN)); + ETHADDR32_COPY(ðhdr->dest, dst); + ETHADDR16_COPY(ðhdr->src, src); + ethhdr->type = PP_HTONS(ETHTYPE_IP); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_send_ip: sending packet %p\n", (void *)p)); + /* send the packet */ + return netif->linkoutput(netif, p); +} + +/** + * Update (or insert) a IP/MAC address pair in the ARP cache. + * + * If a pending entry is resolved, any queued packets will be sent + * at this point. + * + * @param netif netif related to this entry (used for NETIF_ADDRHINT) + * @param ipaddr IP address of the inserted ARP entry. + * @param ethaddr Ethernet address of the inserted ARP entry. + * @param flags @see definition of ETHARP_FLAG_* + * + * @return + * - ERR_OK Succesfully updated ARP cache. + * - ERR_MEM If we could not add a new ARP entry when ETHARP_FLAG_TRY_HARD was set. + * - ERR_ARG Non-unicast address given, those will not appear in ARP cache. + * + * @see pbuf_free() + */ +static err_t +etharp_update_arp_entry(struct netif *netif, ip_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags) +{ + s8_t i; + LWIP_ASSERT("netif->hwaddr_len == ETHARP_HWADDR_LEN", netif->hwaddr_len == ETHARP_HWADDR_LEN); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n", + ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr), + ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2], + ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5])); + /* non-unicast address? */ + if (ip_addr_isany(ipaddr) || + ip_addr_isbroadcast(ipaddr, netif) || + ip_addr_ismulticast(ipaddr)) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: will not add non-unicast IP address to ARP cache\n")); + return ERR_ARG; + } + /* find or create ARP entry */ + i = etharp_find_entry(ipaddr, flags); + /* bail out if no entry could be found */ + if (i < 0) { + return (err_t)i; + } + +#if ETHARP_SUPPORT_STATIC_ENTRIES + if (flags & ETHARP_FLAG_STATIC_ENTRY) { + /* record static type */ + arp_table[i].state = ETHARP_STATE_STATIC; + } else +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + { + /* mark it stable */ + arp_table[i].state = ETHARP_STATE_STABLE; + } + + /* record network interface */ + arp_table[i].netif = netif; + /* insert in SNMP ARP index tree */ + snmp_insert_arpidx_tree(netif, &arp_table[i].ipaddr); + + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: updating stable entry %"S16_F"\n", (s16_t)i)); + /* update address */ + ETHADDR32_COPY(&arp_table[i].ethaddr, ethaddr); + /* reset time stamp */ + arp_table[i].ctime = 0; + /* this is where we will send out queued packets! */ +#if ARP_QUEUEING + while (arp_table[i].q != NULL) { + struct pbuf *p; + /* remember remainder of queue */ + struct etharp_q_entry *q = arp_table[i].q; + /* pop first item off the queue */ + arp_table[i].q = q->next; + /* get the packet pointer */ + p = q->p; + /* now queue entry can be freed */ + memp_free(MEMP_ARP_QUEUE, q); +#else /* ARP_QUEUEING */ + if (arp_table[i].q != NULL) { + struct pbuf *p = arp_table[i].q; + arp_table[i].q = NULL; +#endif /* ARP_QUEUEING */ + /* send the queued IP packet */ + etharp_send_ip(netif, p, (struct eth_addr*)(netif->hwaddr), ethaddr); + /* free the queued IP packet */ + pbuf_free(p); + } + return ERR_OK; +} + +#if ETHARP_SUPPORT_STATIC_ENTRIES +/** Add a new static entry to the ARP table. If an entry exists for the + * specified IP address, this entry is overwritten. + * If packets are queued for the specified IP address, they are sent out. + * + * @param ipaddr IP address for the new static entry + * @param ethaddr ethernet address for the new static entry + * @return @see return values of etharp_add_static_entry + */ +err_t +etharp_add_static_entry(ip_addr_t *ipaddr, struct eth_addr *ethaddr) +{ + struct netif *netif; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_add_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n", + ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr), + ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2], + ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5])); + + netif = ip_route(ipaddr); + if (netif == NULL) { + return ERR_RTE; + } + + return etharp_update_arp_entry(netif, ipaddr, ethaddr, ETHARP_FLAG_TRY_HARD | ETHARP_FLAG_STATIC_ENTRY); +} + +/** Remove a static entry from the ARP table previously added with a call to + * etharp_add_static_entry. + * + * @param ipaddr IP address of the static entry to remove + * @return ERR_OK: entry removed + * ERR_MEM: entry wasn't found + * ERR_ARG: entry wasn't a static entry but a dynamic one + */ +err_t +etharp_remove_static_entry(ip_addr_t *ipaddr) +{ + s8_t i; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_remove_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr))); + + /* find or create ARP entry */ + i = etharp_find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY); + /* bail out if no entry could be found */ + if (i < 0) { + return (err_t)i; + } + + if (arp_table[i].state != ETHARP_STATE_STATIC) { + /* entry wasn't a static entry, cannot remove it */ + return ERR_ARG; + } + /* entry found, free it */ + etharp_free_entry(i); + return ERR_OK; +} +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + +/** + * Remove all ARP table entries of the specified netif. + * + * @param netif points to a network interface + */ +void etharp_cleanup_netif(struct netif *netif) +{ + u8_t i; + + for (i = 0; i < ARP_TABLE_SIZE; ++i) { + u8_t state = arp_table[i].state; + if ((state != ETHARP_STATE_EMPTY) && (arp_table[i].netif == netif)) { + etharp_free_entry(i); + } + } +} + +/** + * Finds (stable) ethernet/IP address pair from ARP table + * using interface and IP address index. + * @note the addresses in the ARP table are in network order! + * + * @param netif points to interface index + * @param ipaddr points to the (network order) IP address index + * @param eth_ret points to return pointer + * @param ip_ret points to return pointer + * @return table index if found, -1 otherwise + */ +s8_t +etharp_find_addr(struct netif *netif, ip_addr_t *ipaddr, + struct eth_addr **eth_ret, ip_addr_t **ip_ret) +{ + s8_t i; + + LWIP_ASSERT("eth_ret != NULL && ip_ret != NULL", + eth_ret != NULL && ip_ret != NULL); + + LWIP_UNUSED_ARG(netif); + + i = etharp_find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY); + if((i >= 0) && (arp_table[i].state >= ETHARP_STATE_STABLE)) { + *eth_ret = &arp_table[i].ethaddr; + *ip_ret = &arp_table[i].ipaddr; + return i; + } + return -1; +} + +#if ETHARP_TRUST_IP_MAC +/** + * Updates the ARP table using the given IP packet. + * + * Uses the incoming IP packet's source address to update the + * ARP cache for the local network. The function does not alter + * or free the packet. This function must be called before the + * packet p is passed to the IP layer. + * + * @param netif The lwIP network interface on which the IP packet pbuf arrived. + * @param p The IP packet that arrived on netif. + * + * @return NULL + * + * @see pbuf_free() + */ +static void +etharp_ip_input(struct netif *netif, struct pbuf *p) +{ + struct eth_hdr *ethhdr; + struct ip_hdr *iphdr; + ip_addr_t iphdr_src; + LWIP_ERROR("netif != NULL", (netif != NULL), return;); + + /* Only insert an entry if the source IP address of the + incoming IP packet comes from a host on the local network. */ + ethhdr = (struct eth_hdr *)p->payload; + iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR); +#if ETHARP_SUPPORT_VLAN + if (ethhdr->type == PP_HTONS(ETHTYPE_VLAN)) { + iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR); + } +#endif /* ETHARP_SUPPORT_VLAN */ + + ip_addr_copy(iphdr_src, iphdr->src); + + /* source is not on the local network? */ + if (!ip_addr_netcmp(&iphdr_src, &(netif->ip_addr), &(netif->netmask))) { + /* do nothing */ + return; + } + + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_ip_input: updating ETHARP table.\n")); + /* update the source IP address in the cache, if present */ + /* @todo We could use ETHARP_FLAG_TRY_HARD if we think we are going to talk + * back soon (for example, if the destination IP address is ours. */ + etharp_update_arp_entry(netif, &iphdr_src, &(ethhdr->src), ETHARP_FLAG_FIND_ONLY); +} +#endif /* ETHARP_TRUST_IP_MAC */ + +/** + * Responds to ARP requests to us. Upon ARP replies to us, add entry to cache + * send out queued IP packets. Updates cache with snooped address pairs. + * + * Should be called for incoming ARP packets. The pbuf in the argument + * is freed by this function. + * + * @param netif The lwIP network interface on which the ARP packet pbuf arrived. + * @param ethaddr Ethernet address of netif. + * @param p The ARP packet that arrived on netif. Is freed by this function. + * + * @return NULL + * + * @see pbuf_free() + */ +static void +etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p) +{ + struct etharp_hdr *hdr; + struct eth_hdr *ethhdr; + /* these are aligned properly, whereas the ARP header fields might not be */ + ip_addr_t sipaddr, dipaddr; + u8_t for_us; +#if LWIP_AUTOIP + const u8_t * ethdst_hwaddr; +#endif /* LWIP_AUTOIP */ + + LWIP_ERROR("netif != NULL", (netif != NULL), return;); + + /* drop short ARP packets: we have to check for p->len instead of p->tot_len here + since a struct etharp_hdr is pointed to p->payload, so it musn't be chained! */ + if (p->len < SIZEOF_ETHARP_PACKET) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("etharp_arp_input: packet dropped, too short (%"S16_F"/%"S16_F")\n", p->tot_len, + (s16_t)SIZEOF_ETHARP_PACKET)); + ETHARP_STATS_INC(etharp.lenerr); + ETHARP_STATS_INC(etharp.drop); + pbuf_free(p); + return; + } + + ethhdr = (struct eth_hdr *)p->payload; + hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR); +#if ETHARP_SUPPORT_VLAN + if (ethhdr->type == PP_HTONS(ETHTYPE_VLAN)) { + hdr = (struct etharp_hdr *)(((u8_t*)ethhdr) + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR); + } +#endif /* ETHARP_SUPPORT_VLAN */ + + /* RFC 826 "Packet Reception": */ + if ((hdr->hwtype != PP_HTONS(HWTYPE_ETHERNET)) || + (hdr->hwlen != ETHARP_HWADDR_LEN) || + (hdr->protolen != sizeof(ip_addr_t)) || + (hdr->proto != PP_HTONS(ETHTYPE_IP))) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("etharp_arp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n", + hdr->hwtype, hdr->hwlen, hdr->proto, hdr->protolen)); + ETHARP_STATS_INC(etharp.proterr); + ETHARP_STATS_INC(etharp.drop); + pbuf_free(p); + return; + } + ETHARP_STATS_INC(etharp.recv); + +#if LWIP_AUTOIP + /* We have to check if a host already has configured our random + * created link local address and continously check if there is + * a host with this IP-address so we can detect collisions */ + autoip_arp_reply(netif, hdr); +#endif /* LWIP_AUTOIP */ + + /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without + * structure packing (not using structure copy which breaks strict-aliasing rules). */ + IPADDR2_COPY(&sipaddr, &hdr->sipaddr); + IPADDR2_COPY(&dipaddr, &hdr->dipaddr); + + /* this interface is not configured? */ + if (ip_addr_isany(&netif->ip_addr)) { + for_us = 0; + } else { + /* ARP packet directed to us? */ + for_us = (u8_t)ip_addr_cmp(&dipaddr, &(netif->ip_addr)); + } + + /* ARP message directed to us? + -> add IP address in ARP cache; assume requester wants to talk to us, + can result in directly sending the queued packets for this host. + ARP message not directed to us? + -> update the source IP address in the cache, if present */ + etharp_update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), + for_us ? ETHARP_FLAG_TRY_HARD : ETHARP_FLAG_FIND_ONLY); + + /* now act on the message itself */ + switch (hdr->opcode) { + /* ARP request? */ + case PP_HTONS(ARP_REQUEST): + /* ARP request. If it asked for our address, we send out a + * reply. In any case, we time-stamp any existing ARP entry, + * and possiby send out an IP packet that was queued on it. */ + + LWIP_DEBUGF (ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: incoming ARP request\n")); + /* ARP request for our address? */ + if (for_us) { + + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: replying to ARP request for our IP address\n")); + /* Re-use pbuf to send ARP reply. + Since we are re-using an existing pbuf, we can't call etharp_raw since + that would allocate a new pbuf. */ + hdr->opcode = htons(ARP_REPLY); + + IPADDR2_COPY(&hdr->dipaddr, &hdr->sipaddr); + IPADDR2_COPY(&hdr->sipaddr, &netif->ip_addr); + + LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!", + (netif->hwaddr_len == ETHARP_HWADDR_LEN)); +#if LWIP_AUTOIP + /* If we are using Link-Local, all ARP packets that contain a Link-Local + * 'sender IP address' MUST be sent using link-layer broadcast instead of + * link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */ + ethdst_hwaddr = ip_addr_islinklocal(&netif->ip_addr) ? (u8_t*)(ethbroadcast.addr) : hdr->shwaddr.addr; +#endif /* LWIP_AUTOIP */ + + ETHADDR16_COPY(&hdr->dhwaddr, &hdr->shwaddr); +#if LWIP_AUTOIP + ETHADDR16_COPY(ðhdr->dest, ethdst_hwaddr); +#else /* LWIP_AUTOIP */ + ETHADDR16_COPY(ðhdr->dest, &hdr->shwaddr); +#endif /* LWIP_AUTOIP */ + ETHADDR16_COPY(&hdr->shwaddr, ethaddr); + ETHADDR16_COPY(ðhdr->src, ethaddr); + + /* hwtype, hwaddr_len, proto, protolen and the type in the ethernet header + are already correct, we tested that before */ + + /* return ARP reply */ + netif->linkoutput(netif, p); + /* we are not configured? */ + } else if (ip_addr_isany(&netif->ip_addr)) { + /* { for_us == 0 and netif->ip_addr.addr == 0 } */ + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: we are unconfigured, ARP request ignored.\n")); + /* request was not directed to us */ + } else { + /* { for_us == 0 and netif->ip_addr.addr != 0 } */ + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: ARP request was not for us.\n")); + } + break; + case PP_HTONS(ARP_REPLY): + /* ARP reply. We already updated the ARP cache earlier. */ + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: incoming ARP reply\n")); +#if (LWIP_DHCP && DHCP_DOES_ARP_CHECK) + /* DHCP wants to know about ARP replies from any host with an + * IP address also offered to us by the DHCP server. We do not + * want to take a duplicate IP address on a single network. + * @todo How should we handle redundant (fail-over) interfaces? */ + dhcp_arp_reply(netif, &sipaddr); +#endif /* (LWIP_DHCP && DHCP_DOES_ARP_CHECK) */ + break; + default: + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: ARP unknown opcode type %"S16_F"\n", htons(hdr->opcode))); + ETHARP_STATS_INC(etharp.err); + break; + } + /* free ARP packet */ + pbuf_free(p); +} + +/** Just a small helper function that sends a pbuf to an ethernet address + * in the arp_table specified by the index 'arp_idx'. + */ +static err_t +etharp_output_to_arp_index(struct netif *netif, struct pbuf *q, u8_t arp_idx) +{ + LWIP_ASSERT("arp_table[arp_idx].state >= ETHARP_STATE_STABLE", + arp_table[arp_idx].state >= ETHARP_STATE_STABLE); + /* if arp table entry is about to expire: re-request it, + but only if its state is ETHARP_STATE_STABLE to prevent flooding the + network with ARP requests if this address is used frequently. */ + if ((arp_table[arp_idx].state == ETHARP_STATE_STABLE) && + (arp_table[arp_idx].ctime >= ARP_AGE_REREQUEST_USED)) { + if (etharp_request(netif, &arp_table[arp_idx].ipaddr) == ERR_OK) { + arp_table[arp_idx].state = ETHARP_STATE_STABLE_REREQUESTING; + } + } + + return etharp_send_ip(netif, q, (struct eth_addr*)(netif->hwaddr), + &arp_table[arp_idx].ethaddr); +} + +/** + * Resolve and fill-in Ethernet address header for outgoing IP packet. + * + * For IP multicast and broadcast, corresponding Ethernet addresses + * are selected and the packet is transmitted on the link. + * + * For unicast addresses, the packet is submitted to etharp_query(). In + * case the IP address is outside the local network, the IP address of + * the gateway is used. + * + * @param netif The lwIP network interface which the IP packet will be sent on. + * @param q The pbuf(s) containing the IP packet to be sent. + * @param ipaddr The IP address of the packet destination. + * + * @return + * - ERR_RTE No route to destination (no gateway to external networks), + * or the return type of either etharp_query() or etharp_send_ip(). + */ +err_t +etharp_output(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr) +{ + struct eth_addr *dest; + struct eth_addr mcastaddr; + ip_addr_t *dst_addr = ipaddr; + + LWIP_ASSERT("netif != NULL", netif != NULL); + LWIP_ASSERT("q != NULL", q != NULL); + LWIP_ASSERT("ipaddr != NULL", ipaddr != NULL); + + /* make room for Ethernet header - should not fail */ + if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) { + /* bail out */ + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("etharp_output: could not allocate room for header.\n")); + LINK_STATS_INC(link.lenerr); + return ERR_BUF; + } + + /* Determine on destination hardware address. Broadcasts and multicasts + * are special, other IP addresses are looked up in the ARP table. */ + + /* broadcast destination IP address? */ + if (ip_addr_isbroadcast(ipaddr, netif)) { + /* broadcast on Ethernet also */ + dest = (struct eth_addr *)ðbroadcast; + /* multicast destination IP address? */ + } else if (ip_addr_ismulticast(ipaddr)) { + /* Hash IP multicast address to MAC address.*/ + mcastaddr.addr[0] = LL_MULTICAST_ADDR_0; + mcastaddr.addr[1] = LL_MULTICAST_ADDR_1; + mcastaddr.addr[2] = LL_MULTICAST_ADDR_2; + mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f; + mcastaddr.addr[4] = ip4_addr3(ipaddr); + mcastaddr.addr[5] = ip4_addr4(ipaddr); + /* destination Ethernet address is multicast */ + dest = &mcastaddr; + /* unicast destination IP address? */ + } else { + s8_t i; + /* outside local network? if so, this can neither be a global broadcast nor + a subnet broadcast. */ + if (!ip_addr_netcmp(ipaddr, &(netif->ip_addr), &(netif->netmask)) && + !ip_addr_islinklocal(ipaddr)) { +#if LWIP_AUTOIP + struct ip_hdr *iphdr = (struct ip_hdr*)((u8_t*)q->payload + + sizeof(struct eth_hdr)); + /* According to RFC 3297, chapter 2.6.2 (Forwarding Rules), a packet with + a link-local source address must always be "directly to its destination + on the same physical link. The host MUST NOT send the packet to any + router for forwarding". */ + if (!ip_addr_islinklocal(&iphdr->src)) +#endif /* LWIP_AUTOIP */ + { + /* interface has default gateway? */ + if (!ip_addr_isany(&netif->gw)) { + /* send to hardware address of default gateway IP address */ + dst_addr = &(netif->gw); + /* no default gateway available */ + } else { + /* no route to destination error (default gateway missing) */ + return ERR_RTE; + } + } + } +#if LWIP_NETIF_HWADDRHINT + if (netif->addr_hint != NULL) { + /* per-pcb cached entry was given */ + u8_t etharp_cached_entry = *(netif->addr_hint); + if (etharp_cached_entry < ARP_TABLE_SIZE) { +#endif /* LWIP_NETIF_HWADDRHINT */ + if ((arp_table[etharp_cached_entry].state >= ETHARP_STATE_STABLE) && + (ip_addr_cmp(dst_addr, &arp_table[etharp_cached_entry].ipaddr))) { + /* the per-pcb-cached entry is stable and the right one! */ + ETHARP_STATS_INC(etharp.cachehit); + return etharp_output_to_arp_index(netif, q, etharp_cached_entry); + } +#if LWIP_NETIF_HWADDRHINT + } + } +#endif /* LWIP_NETIF_HWADDRHINT */ + + /* find stable entry: do this here since this is a critical path for + throughput and etharp_find_entry() is kind of slow */ + for (i = 0; i < ARP_TABLE_SIZE; i++) { + if ((arp_table[i].state >= ETHARP_STATE_STABLE) && + (ip_addr_cmp(dst_addr, &arp_table[i].ipaddr))) { + /* found an existing, stable entry */ + ETHARP_SET_HINT(netif, i); + return etharp_output_to_arp_index(netif, q, i); + } + } + /* no stable entry found, use the (slower) query function: + queue on destination Ethernet address belonging to ipaddr */ + return etharp_query(netif, dst_addr, q); + } + + /* continuation for multicast/broadcast destinations */ + /* obtain source Ethernet address of the given interface */ + /* send packet directly on the link */ + return etharp_send_ip(netif, q, (struct eth_addr*)(netif->hwaddr), dest); +} + +/** + * Send an ARP request for the given IP address and/or queue a packet. + * + * If the IP address was not yet in the cache, a pending ARP cache entry + * is added and an ARP request is sent for the given address. The packet + * is queued on this entry. + * + * If the IP address was already pending in the cache, a new ARP request + * is sent for the given address. The packet is queued on this entry. + * + * If the IP address was already stable in the cache, and a packet is + * given, it is directly sent and no ARP request is sent out. + * + * If the IP address was already stable in the cache, and no packet is + * given, an ARP request is sent out. + * + * @param netif The lwIP network interface on which ipaddr + * must be queried for. + * @param ipaddr The IP address to be resolved. + * @param q If non-NULL, a pbuf that must be delivered to the IP address. + * q is not freed by this function. + * + * @note q must only be ONE packet, not a packet queue! + * + * @return + * - ERR_BUF Could not make room for Ethernet header. + * - ERR_MEM Hardware address unknown, and no more ARP entries available + * to query for address or queue the packet. + * - ERR_MEM Could not queue packet due to memory shortage. + * - ERR_RTE No route to destination (no gateway to external networks). + * - ERR_ARG Non-unicast address given, those will not appear in ARP cache. + * + */ +err_t +etharp_query(struct netif *netif, ip_addr_t *ipaddr, struct pbuf *q) +{ + struct eth_addr * srcaddr = (struct eth_addr *)netif->hwaddr; + err_t result = ERR_MEM; + s8_t i; /* ARP entry index */ + + /* non-unicast address? */ + if (ip_addr_isbroadcast(ipaddr, netif) || + ip_addr_ismulticast(ipaddr) || + ip_addr_isany(ipaddr)) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: will not add non-unicast IP address to ARP cache\n")); + return ERR_ARG; + } + + /* find entry in ARP cache, ask to create entry if queueing packet */ + i = etharp_find_entry(ipaddr, ETHARP_FLAG_TRY_HARD); + + /* could not find or create entry? */ + if (i < 0) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not create ARP entry\n")); + if (q) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: packet dropped\n")); + ETHARP_STATS_INC(etharp.memerr); + } + return (err_t)i; + } + + /* mark a fresh entry as pending (we just sent a request) */ + if (arp_table[i].state == ETHARP_STATE_EMPTY) { + arp_table[i].state = ETHARP_STATE_PENDING; + } + + /* { i is either a STABLE or (new or existing) PENDING entry } */ + LWIP_ASSERT("arp_table[i].state == PENDING or STABLE", + ((arp_table[i].state == ETHARP_STATE_PENDING) || + (arp_table[i].state >= ETHARP_STATE_STABLE))); + + /* do we have a pending entry? or an implicit query request? */ + if ((arp_table[i].state == ETHARP_STATE_PENDING) || (q == NULL)) { + /* try to resolve it; send out ARP request */ + result = etharp_request(netif, ipaddr); + if (result != ERR_OK) { + /* ARP request couldn't be sent */ + /* We don't re-send arp request in etharp_tmr, but we still queue packets, + since this failure could be temporary, and the next packet calling + etharp_query again could lead to sending the queued packets. */ + } + if (q == NULL) { + return result; + } + } + + /* packet given? */ + LWIP_ASSERT("q != NULL", q != NULL); + /* stable entry? */ + if (arp_table[i].state >= ETHARP_STATE_STABLE) { + /* we have a valid IP->Ethernet address mapping */ + ETHARP_SET_HINT(netif, i); + /* send the packet */ + result = etharp_send_ip(netif, q, srcaddr, &(arp_table[i].ethaddr)); + /* pending entry? (either just created or already pending */ + } else if (arp_table[i].state == ETHARP_STATE_PENDING) { + /* entry is still pending, queue the given packet 'q' */ + struct pbuf *p; + int copy_needed = 0; + /* IF q includes a PBUF_REF, PBUF_POOL or PBUF_RAM, we have no choice but + * to copy the whole queue into a new PBUF_RAM (see bug #11400) + * PBUF_ROMs can be left as they are, since ROM must not get changed. */ + p = q; + while (p) { + LWIP_ASSERT("no packet queues allowed!", (p->len != p->tot_len) || (p->next == 0)); + if(p->type != PBUF_ROM) { + copy_needed = 1; + break; + } + p = p->next; + } + if(copy_needed) { + /* copy the whole packet into new pbufs */ + p = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); + if(p != NULL) { + if (pbuf_copy(p, q) != ERR_OK) { + pbuf_free(p); + p = NULL; + } + } + } else { + /* referencing the old pbuf is enough */ + p = q; + pbuf_ref(p); + } + /* packet could be taken over? */ + if (p != NULL) { + /* queue packet ... */ +#if ARP_QUEUEING + struct etharp_q_entry *new_entry; + /* allocate a new arp queue entry */ + new_entry = (struct etharp_q_entry *)memp_malloc(MEMP_ARP_QUEUE); + if (new_entry != NULL) { + new_entry->next = 0; + new_entry->p = p; + if(arp_table[i].q != NULL) { + /* queue was already existent, append the new entry to the end */ + struct etharp_q_entry *r; + r = arp_table[i].q; + while (r->next != NULL) { + r = r->next; + } + r->next = new_entry; + } else { + /* queue did not exist, first item in queue */ + arp_table[i].q = new_entry; + } + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i)); + result = ERR_OK; + } else { + /* the pool MEMP_ARP_QUEUE is empty */ + pbuf_free(p); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q)); + result = ERR_MEM; + } +#else /* ARP_QUEUEING */ + /* always queue one packet per ARP request only, freeing a previously queued packet */ + if (arp_table[i].q != NULL) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: dropped previously queued packet %p for ARP entry %"S16_F"\n", (void *)q, (s16_t)i)); + pbuf_free(arp_table[i].q); + } + arp_table[i].q = p; + result = ERR_OK; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i)); +#endif /* ARP_QUEUEING */ + } else { + ETHARP_STATS_INC(etharp.memerr); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q)); + result = ERR_MEM; + } + } + return result; +} + +/** + * Send a raw ARP packet (opcode and all addresses can be modified) + * + * @param netif the lwip network interface on which to send the ARP packet + * @param ethsrc_addr the source MAC address for the ethernet header + * @param ethdst_addr the destination MAC address for the ethernet header + * @param hwsrc_addr the source MAC address for the ARP protocol header + * @param ipsrc_addr the source IP address for the ARP protocol header + * @param hwdst_addr the destination MAC address for the ARP protocol header + * @param ipdst_addr the destination IP address for the ARP protocol header + * @param opcode the type of the ARP packet + * @return ERR_OK if the ARP packet has been sent + * ERR_MEM if the ARP packet couldn't be allocated + * any other err_t on failure + */ +#if !LWIP_AUTOIP +static +#endif /* LWIP_AUTOIP */ +err_t +etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr, + const struct eth_addr *ethdst_addr, + const struct eth_addr *hwsrc_addr, const ip_addr_t *ipsrc_addr, + const struct eth_addr *hwdst_addr, const ip_addr_t *ipdst_addr, + const u16_t opcode) +{ + struct pbuf *p; + err_t result = ERR_OK; + struct eth_hdr *ethhdr; + struct etharp_hdr *hdr; +#if LWIP_AUTOIP + const u8_t * ethdst_hwaddr; +#endif /* LWIP_AUTOIP */ + + LWIP_ASSERT("netif != NULL", netif != NULL); + + /* allocate a pbuf for the outgoing ARP request packet */ + p = pbuf_alloc(PBUF_RAW, SIZEOF_ETHARP_PACKET, PBUF_RAM); + /* could allocate a pbuf for an ARP request? */ + if (p == NULL) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("etharp_raw: could not allocate pbuf for ARP request.\n")); + ETHARP_STATS_INC(etharp.memerr); + return ERR_MEM; + } + LWIP_ASSERT("check that first pbuf can hold struct etharp_hdr", + (p->len >= SIZEOF_ETHARP_PACKET)); + + ethhdr = (struct eth_hdr *)p->payload; + hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_raw: sending raw ARP packet.\n")); + hdr->opcode = htons(opcode); + + LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!", + (netif->hwaddr_len == ETHARP_HWADDR_LEN)); +#if LWIP_AUTOIP + /* If we are using Link-Local, all ARP packets that contain a Link-Local + * 'sender IP address' MUST be sent using link-layer broadcast instead of + * link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */ + ethdst_hwaddr = ip_addr_islinklocal(ipsrc_addr) ? (u8_t*)(ethbroadcast.addr) : ethdst_addr->addr; +#endif /* LWIP_AUTOIP */ + /* Write the ARP MAC-Addresses */ + ETHADDR16_COPY(&hdr->shwaddr, hwsrc_addr); + ETHADDR16_COPY(&hdr->dhwaddr, hwdst_addr); + /* Write the Ethernet MAC-Addresses */ +#if LWIP_AUTOIP + ETHADDR16_COPY(ðhdr->dest, ethdst_hwaddr); +#else /* LWIP_AUTOIP */ + ETHADDR16_COPY(ðhdr->dest, ethdst_addr); +#endif /* LWIP_AUTOIP */ + ETHADDR16_COPY(ðhdr->src, ethsrc_addr); + /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without + * structure packing. */ + IPADDR2_COPY(&hdr->sipaddr, ipsrc_addr); + IPADDR2_COPY(&hdr->dipaddr, ipdst_addr); + + hdr->hwtype = PP_HTONS(HWTYPE_ETHERNET); + hdr->proto = PP_HTONS(ETHTYPE_IP); + /* set hwlen and protolen */ + hdr->hwlen = ETHARP_HWADDR_LEN; + hdr->protolen = sizeof(ip_addr_t); + + ethhdr->type = PP_HTONS(ETHTYPE_ARP); + /* send ARP query */ + result = netif->linkoutput(netif, p); + ETHARP_STATS_INC(etharp.xmit); + /* free ARP query packet */ + pbuf_free(p); + p = NULL; + /* could not allocate pbuf for ARP request */ + + return result; +} + +/** + * Send an ARP request packet asking for ipaddr. + * + * @param netif the lwip network interface on which to send the request + * @param ipaddr the IP address for which to ask + * @return ERR_OK if the request has been sent + * ERR_MEM if the ARP packet couldn't be allocated + * any other err_t on failure + */ +err_t +etharp_request(struct netif *netif, ip_addr_t *ipaddr) +{ + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_request: sending ARP request.\n")); + return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, ðbroadcast, + (struct eth_addr *)netif->hwaddr, &netif->ip_addr, ðzero, + ipaddr, ARP_REQUEST); +} +#endif /* LWIP_ARP */ + +/** + * Process received ethernet frames. Using this function instead of directly + * calling ip_input and passing ARP frames through etharp in ethernetif_input, + * the ARP cache is protected from concurrent access. + * + * @param p the recevied packet, p->payload pointing to the ethernet header + * @param netif the network interface on which the packet was received + */ +err_t +ethernet_input(struct pbuf *p, struct netif *netif) +{ + struct eth_hdr* ethhdr; + u16_t type; +#if LWIP_ARP || ETHARP_SUPPORT_VLAN + s16_t ip_hdr_offset = SIZEOF_ETH_HDR; +#endif /* LWIP_ARP || ETHARP_SUPPORT_VLAN */ + + if (p->len <= SIZEOF_ETH_HDR) { + /* a packet with only an ethernet header (or less) is not valid for us */ + ETHARP_STATS_INC(etharp.proterr); + ETHARP_STATS_INC(etharp.drop); + goto free_and_return; + } + + /* points to packet payload, which starts with an Ethernet header */ + ethhdr = (struct eth_hdr *)p->payload; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, + ("ethernet_input: dest:%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F", src:%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F", type:%"X16_F"\n", + (unsigned)ethhdr->dest.addr[0], (unsigned)ethhdr->dest.addr[1], (unsigned)ethhdr->dest.addr[2], + (unsigned)ethhdr->dest.addr[3], (unsigned)ethhdr->dest.addr[4], (unsigned)ethhdr->dest.addr[5], + (unsigned)ethhdr->src.addr[0], (unsigned)ethhdr->src.addr[1], (unsigned)ethhdr->src.addr[2], + (unsigned)ethhdr->src.addr[3], (unsigned)ethhdr->src.addr[4], (unsigned)ethhdr->src.addr[5], + (unsigned)htons(ethhdr->type))); + + type = ethhdr->type; +#if ETHARP_SUPPORT_VLAN + if (type == PP_HTONS(ETHTYPE_VLAN)) { + struct eth_vlan_hdr *vlan = (struct eth_vlan_hdr*)(((char*)ethhdr) + SIZEOF_ETH_HDR); + if (p->len <= SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR) { + /* a packet with only an ethernet/vlan header (or less) is not valid for us */ + ETHARP_STATS_INC(etharp.proterr); + ETHARP_STATS_INC(etharp.drop); + goto free_and_return; + } +#if defined(ETHARP_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK_FN) /* if not, allow all VLANs */ +#ifdef ETHARP_VLAN_CHECK_FN + if (!ETHARP_VLAN_CHECK_FN(ethhdr, vlan)) { +#elif defined(ETHARP_VLAN_CHECK) + if (VLAN_ID(vlan) != ETHARP_VLAN_CHECK) { +#endif + /* silently ignore this packet: not for our VLAN */ + pbuf_free(p); + return ERR_OK; + } +#endif /* defined(ETHARP_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK_FN) */ + type = vlan->tpid; + ip_hdr_offset = SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR; + } +#endif /* ETHARP_SUPPORT_VLAN */ + +#if LWIP_ARP_FILTER_NETIF + netif = LWIP_ARP_FILTER_NETIF_FN(p, netif, htons(type)); +#endif /* LWIP_ARP_FILTER_NETIF*/ + + if (ethhdr->dest.addr[0] & 1) { + /* this might be a multicast or broadcast packet */ + if (ethhdr->dest.addr[0] == LL_MULTICAST_ADDR_0) { + if ((ethhdr->dest.addr[1] == LL_MULTICAST_ADDR_1) && + (ethhdr->dest.addr[2] == LL_MULTICAST_ADDR_2)) { + /* mark the pbuf as link-layer multicast */ + p->flags |= PBUF_FLAG_LLMCAST; + } + } else if (eth_addr_cmp(ðhdr->dest, ðbroadcast)) { + /* mark the pbuf as link-layer broadcast */ + p->flags |= PBUF_FLAG_LLBCAST; + } + } + + switch (type) { +#if LWIP_ARP + /* IP packet? */ + case PP_HTONS(ETHTYPE_IP): + if (!(netif->flags & NETIF_FLAG_ETHARP)) { + goto free_and_return; + } +#if ETHARP_TRUST_IP_MAC + /* update ARP table */ + etharp_ip_input(netif, p); +#endif /* ETHARP_TRUST_IP_MAC */ + /* skip Ethernet header */ + if(pbuf_header(p, -ip_hdr_offset)) { + LWIP_ASSERT("Can't move over header in packet", 0); + goto free_and_return; + } else { + /* pass to IP layer */ + ip_input(p, netif); + } + break; + + case PP_HTONS(ETHTYPE_ARP): + if (!(netif->flags & NETIF_FLAG_ETHARP)) { + goto free_and_return; + } + /* pass p to ARP module */ + etharp_arp_input(netif, (struct eth_addr*)(netif->hwaddr), p); + break; +#endif /* LWIP_ARP */ +#if PPPOE_SUPPORT + case PP_HTONS(ETHTYPE_PPPOEDISC): /* PPP Over Ethernet Discovery Stage */ + pppoe_disc_input(netif, p); + break; + + case PP_HTONS(ETHTYPE_PPPOE): /* PPP Over Ethernet Session Stage */ + pppoe_data_input(netif, p); + break; +#endif /* PPPOE_SUPPORT */ + + default: + ETHARP_STATS_INC(etharp.proterr); + ETHARP_STATS_INC(etharp.drop); + goto free_and_return; + } + + /* This means the pbuf is freed or consumed, + so the caller doesn't have to free it again */ + return ERR_OK; + +free_and_return: + pbuf_free(p); + return ERR_OK; +} +#endif /* LWIP_ARP || LWIP_ETHERNET */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/netif/ethernetif.c b/component/common/network/lwip/lwip_v1.4.1/src/netif/ethernetif.c new file mode 100644 index 0000000..8ec40be --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/netif/ethernetif.c @@ -0,0 +1,317 @@ +/** + * @file + * Ethernet Interface Skeleton + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/* + * This file is a skeleton for developing Ethernet network interface + * drivers for lwIP. Add code to the low_level functions and do a + * search-and-replace for the word "ethernetif" to replace it with + * something that better describes your network interface. + */ + +#include "lwip/opt.h" + +#if 0 /* don't build, this is only a skeleton, see previous comment */ + +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include +#include +#include "netif/etharp.h" +#include "netif/ppp_oe.h" + +/* Define those to better describe your network interface. */ +#define IFNAME0 'e' +#define IFNAME1 'n' + +/** + * Helper struct to hold private data used to operate your ethernet interface. + * Keeping the ethernet address of the MAC in this struct is not necessary + * as it is already kept in the struct netif. + * But this is only an example, anyway... + */ +struct ethernetif { + struct eth_addr *ethaddr; + /* Add whatever per-interface state that is needed here. */ +}; + +/* Forward declarations. */ +static void ethernetif_input(struct netif *netif); + +/** + * In this function, the hardware should be initialized. + * Called from ethernetif_init(). + * + * @param netif the already initialized lwip network interface structure + * for this ethernetif + */ +static void +low_level_init(struct netif *netif) +{ + struct ethernetif *ethernetif = netif->state; + + /* set MAC hardware address length */ + netif->hwaddr_len = ETHARP_HWADDR_LEN; + + /* set MAC hardware address */ + netif->hwaddr[0] = ; + ... + netif->hwaddr[5] = ; + + /* maximum transfer unit */ + netif->mtu = 1500; + + /* device capabilities */ + /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; + + /* Do whatever else is needed to initialize interface. */ +} + +/** + * This function should do the actual transmission of the packet. The packet is + * contained in the pbuf that is passed to the function. This pbuf + * might be chained. + * + * @param netif the lwip network interface structure for this ethernetif + * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type) + * @return ERR_OK if the packet could be sent + * an err_t value if the packet couldn't be sent + * + * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to + * strange results. You might consider waiting for space in the DMA queue + * to become availale since the stack doesn't retry to send a packet + * dropped because of memory failure (except for the TCP timers). + */ + +static err_t +low_level_output(struct netif *netif, struct pbuf *p) +{ + struct ethernetif *ethernetif = netif->state; + struct pbuf *q; + + initiate transfer(); + +#if ETH_PAD_SIZE + pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ +#endif + + for(q = p; q != NULL; q = q->next) { + /* Send the data from the pbuf to the interface, one pbuf at a + time. The size of the data in each pbuf is kept in the ->len + variable. */ + send data from(q->payload, q->len); + } + + signal that packet should be sent(); + +#if ETH_PAD_SIZE + pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ +#endif + + LINK_STATS_INC(link.xmit); + + return ERR_OK; +} + +/** + * Should allocate a pbuf and transfer the bytes of the incoming + * packet from the interface into the pbuf. + * + * @param netif the lwip network interface structure for this ethernetif + * @return a pbuf filled with the received packet (including MAC header) + * NULL on memory error + */ +static struct pbuf * +low_level_input(struct netif *netif) +{ + struct ethernetif *ethernetif = netif->state; + struct pbuf *p, *q; + u16_t len; + + /* Obtain the size of the packet and put it into the "len" + variable. */ + len = ; + +#if ETH_PAD_SIZE + len += ETH_PAD_SIZE; /* allow room for Ethernet padding */ +#endif + + /* We allocate a pbuf chain of pbufs from the pool. */ + p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); + + if (p != NULL) { + +#if ETH_PAD_SIZE + pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ +#endif + + /* We iterate over the pbuf chain until we have read the entire + * packet into the pbuf. */ + for(q = p; q != NULL; q = q->next) { + /* Read enough bytes to fill this pbuf in the chain. The + * available data in the pbuf is given by the q->len + * variable. + * This does not necessarily have to be a memcpy, you can also preallocate + * pbufs for a DMA-enabled MAC and after receiving truncate it to the + * actually received size. In this case, ensure the tot_len member of the + * pbuf is the sum of the chained pbuf len members. + */ + read data into(q->payload, q->len); + } + acknowledge that packet has been read(); + +#if ETH_PAD_SIZE + pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ +#endif + + LINK_STATS_INC(link.recv); + } else { + drop packet(); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + } + + return p; +} + +/** + * This function should be called when a packet is ready to be read + * from the interface. It uses the function low_level_input() that + * should handle the actual reception of bytes from the network + * interface. Then the type of the received packet is determined and + * the appropriate input function is called. + * + * @param netif the lwip network interface structure for this ethernetif + */ +static void +ethernetif_input(struct netif *netif) +{ + struct ethernetif *ethernetif; + struct eth_hdr *ethhdr; + struct pbuf *p; + + ethernetif = netif->state; + + /* move received packet into a new pbuf */ + p = low_level_input(netif); + /* no packet could be read, silently ignore this */ + if (p == NULL) return; + /* points to packet payload, which starts with an Ethernet header */ + ethhdr = p->payload; + + switch (htons(ethhdr->type)) { + /* IP or ARP packet? */ + case ETHTYPE_IP: + case ETHTYPE_ARP: +#if PPPOE_SUPPORT + /* PPPoE packet? */ + case ETHTYPE_PPPOEDISC: + case ETHTYPE_PPPOE: +#endif /* PPPOE_SUPPORT */ + /* full packet send to tcpip_thread to process */ + if (netif->input(p, netif)!=ERR_OK) + { LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); + pbuf_free(p); + p = NULL; + } + break; + + default: + pbuf_free(p); + p = NULL; + break; + } +} + +/** + * Should be called at the beginning of the program to set up the + * network interface. It calls the function low_level_init() to do the + * actual setup of the hardware. + * + * This function should be passed as a parameter to netif_add(). + * + * @param netif the lwip network interface structure for this ethernetif + * @return ERR_OK if the loopif is initialized + * ERR_MEM if private data couldn't be allocated + * any other err_t on error + */ +err_t +ethernetif_init(struct netif *netif) +{ + struct ethernetif *ethernetif; + + LWIP_ASSERT("netif != NULL", (netif != NULL)); + + ethernetif = mem_malloc(sizeof(struct ethernetif)); + if (ethernetif == NULL) { + LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n")); + return ERR_MEM; + } + +#if LWIP_NETIF_HOSTNAME + /* Initialize interface hostname */ + netif->hostname = "lwip"; +#endif /* LWIP_NETIF_HOSTNAME */ + + /* + * Initialize the snmp variables and counters inside the struct netif. + * The last argument should be replaced with your link speed, in units + * of bits per second. + */ + NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS); + + netif->state = ethernetif; + netif->name[0] = IFNAME0; + netif->name[1] = IFNAME1; + /* We directly use etharp_output() here to save a function call. + * You can instead declare your own function an call etharp_output() + * from it if you have to do some checks before sending (e.g. if link + * is available...) */ + netif->output = etharp_output; + netif->linkoutput = low_level_output; + + ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]); + + /* initialize the hardware */ + low_level_init(netif); + + return ERR_OK; +} + +#endif /* 0 */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/auth.c b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/auth.c new file mode 100644 index 0000000..0fd87a3 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/auth.c @@ -0,0 +1,1334 @@ +/***************************************************************************** +* auth.c - Network Authentication and Phase Control program file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* Copyright (c) 1997 by Global Election Systems Inc. All rights reserved. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-12-08 Guy Lancaster , Global Election Systems Inc. +* Ported from public pppd code. +*****************************************************************************/ +/* + * auth.c - PPP authentication and phase control. + * + * Copyright (c) 1993 The Australian National University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the Australian National University. The name of the University + * may not be used to endorse or promote products derived from this + * software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "lwip/opt.h" + +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "ppp_impl.h" +#include "pppdebug.h" + +#include "fsm.h" +#include "lcp.h" +#include "pap.h" +#include "chap.h" +#include "auth.h" +#include "ipcp.h" + +#if CBCP_SUPPORT +#include "cbcp.h" +#endif /* CBCP_SUPPORT */ + +#include "lwip/inet.h" + +#include + +#if 0 /* UNUSED */ +/* Bits in scan_authfile return value */ +#define NONWILD_SERVER 1 +#define NONWILD_CLIENT 2 + +#define ISWILD(word) (word[0] == '*' && word[1] == 0) +#endif /* UNUSED */ + +#if PAP_SUPPORT || CHAP_SUPPORT +/* The name by which the peer authenticated itself to us. */ +static char peer_authname[MAXNAMELEN]; +#endif /* PAP_SUPPORT || CHAP_SUPPORT */ + +/* Records which authentication operations haven't completed yet. */ +static int auth_pending[NUM_PPP]; + +/* Set if we have successfully called plogin() */ +static int logged_in; + +/* Set if we have run the /etc/ppp/auth-up script. */ +static int did_authup; /* @todo, we don't need this in lwip*/ + +/* List of addresses which the peer may use. */ +static struct wordlist *addresses[NUM_PPP]; + +#if 0 /* UNUSED */ +/* Wordlist giving addresses which the peer may use + without authenticating itself. */ +static struct wordlist *noauth_addrs; + +/* Extra options to apply, from the secrets file entry for the peer. */ +static struct wordlist *extra_options; +#endif /* UNUSED */ + +/* Number of network protocols which we have opened. */ +static int num_np_open; + +/* Number of network protocols which have come up. */ +static int num_np_up; + +#if PAP_SUPPORT || CHAP_SUPPORT +/* Set if we got the contents of passwd[] from the pap-secrets file. */ +static int passwd_from_file; +#endif /* PAP_SUPPORT || CHAP_SUPPORT */ + +#if 0 /* UNUSED */ +/* Set if we require authentication only because we have a default route. */ +static bool default_auth; + +/* Hook to enable a plugin to control the idle time limit */ +int (*idle_time_hook) __P((struct ppp_idle *)) = NULL; + +/* Hook for a plugin to say whether we can possibly authenticate any peer */ +int (*pap_check_hook) __P((void)) = NULL; + +/* Hook for a plugin to check the PAP user and password */ +int (*pap_auth_hook) __P((char *user, char *passwd, char **msgp, + struct wordlist **paddrs, + struct wordlist **popts)) = NULL; + +/* Hook for a plugin to know about the PAP user logout */ +void (*pap_logout_hook) __P((void)) = NULL; + +/* Hook for a plugin to get the PAP password for authenticating us */ +int (*pap_passwd_hook) __P((char *user, char *passwd)) = NULL; + +/* + * This is used to ensure that we don't start an auth-up/down + * script while one is already running. + */ +enum script_state { + s_down, + s_up +}; + +static enum script_state auth_state = s_down; +static enum script_state auth_script_state = s_down; +static pid_t auth_script_pid = 0; + +/* + * Option variables. + * lwip: some of these are present in the ppp_settings structure + */ +bool uselogin = 0; /* Use /etc/passwd for checking PAP */ +bool cryptpap = 0; /* Passwords in pap-secrets are encrypted */ +bool refuse_pap = 0; /* Don't wanna auth. ourselves with PAP */ +bool refuse_chap = 0; /* Don't wanna auth. ourselves with CHAP */ +bool usehostname = 0; /* Use hostname for our_name */ +bool auth_required = 0; /* Always require authentication from peer */ +bool allow_any_ip = 0; /* Allow peer to use any IP address */ +bool explicit_remote = 0; /* User specified explicit remote name */ +char remote_name[MAXNAMELEN]; /* Peer's name for authentication */ + +#endif /* UNUSED */ + +/* Bits in auth_pending[] */ +#define PAP_WITHPEER 1 +#define PAP_PEER 2 +#define CHAP_WITHPEER 4 +#define CHAP_PEER 8 + +/* @todo, move this somewhere */ +/* Used for storing a sequence of words. Usually malloced. */ +struct wordlist { + struct wordlist *next; + char word[1]; +}; + + +extern char *crypt (const char *, const char *); + +/* Prototypes for procedures local to this file. */ + +static void network_phase (int); +static void check_idle (void *); +static void connect_time_expired (void *); +#if 0 +static int plogin (char *, char *, char **, int *); +#endif +static void plogout (void); +static int null_login (int); +static int get_pap_passwd (int, char *, char *); +static int have_pap_secret (void); +static int have_chap_secret (char *, char *, u32_t); +static int ip_addr_check (u32_t, struct wordlist *); + +#if 0 /* PAP_SUPPORT || CHAP_SUPPORT */ +static int scan_authfile (FILE *, char *, char *, char *, + struct wordlist **, struct wordlist **, + char *); +static void free_wordlist (struct wordlist *); +static void auth_script (char *); +static void auth_script_done (void *); +static void set_allowed_addrs (int unit, struct wordlist *addrs); +static int some_ip_ok (struct wordlist *); +static int setupapfile (char **); +static int privgroup (char **); +static int set_noauth_addr (char **); +static void check_access (FILE *, char *); +#endif /* 0 */ /* PAP_SUPPORT || CHAP_SUPPORT */ + +#if 0 /* UNUSED */ +/* + * Authentication-related options. + */ +option_t auth_options[] = { + { "require-pap", o_bool, &lcp_wantoptions[0].neg_upap, + "Require PAP authentication from peer", 1, &auth_required }, + { "+pap", o_bool, &lcp_wantoptions[0].neg_upap, + "Require PAP authentication from peer", 1, &auth_required }, + { "refuse-pap", o_bool, &refuse_pap, + "Don't agree to auth to peer with PAP", 1 }, + { "-pap", o_bool, &refuse_pap, + "Don't allow PAP authentication with peer", 1 }, + { "require-chap", o_bool, &lcp_wantoptions[0].neg_chap, + "Require CHAP authentication from peer", 1, &auth_required }, + { "+chap", o_bool, &lcp_wantoptions[0].neg_chap, + "Require CHAP authentication from peer", 1, &auth_required }, + { "refuse-chap", o_bool, &refuse_chap, + "Don't agree to auth to peer with CHAP", 1 }, + { "-chap", o_bool, &refuse_chap, + "Don't allow CHAP authentication with peer", 1 }, + { "name", o_string, our_name, + "Set local name for authentication", + OPT_PRIV|OPT_STATIC, NULL, MAXNAMELEN }, + { "user", o_string, user, + "Set name for auth with peer", OPT_STATIC, NULL, MAXNAMELEN }, + { "usehostname", o_bool, &usehostname, + "Must use hostname for authentication", 1 }, + { "remotename", o_string, remote_name, + "Set remote name for authentication", OPT_STATIC, + &explicit_remote, MAXNAMELEN }, + { "auth", o_bool, &auth_required, + "Require authentication from peer", 1 }, + { "noauth", o_bool, &auth_required, + "Don't require peer to authenticate", OPT_PRIV, &allow_any_ip }, + { "login", o_bool, &uselogin, + "Use system password database for PAP", 1 }, + { "papcrypt", o_bool, &cryptpap, + "PAP passwords are encrypted", 1 }, + { "+ua", o_special, (void *)setupapfile, + "Get PAP user and password from file" }, + { "password", o_string, passwd, + "Password for authenticating us to the peer", OPT_STATIC, + NULL, MAXSECRETLEN }, + { "privgroup", o_special, (void *)privgroup, + "Allow group members to use privileged options", OPT_PRIV }, + { "allow-ip", o_special, (void *)set_noauth_addr, + "Set IP address(es) which can be used without authentication", + OPT_PRIV }, + { NULL } +}; +#endif /* UNUSED */ +#if 0 /* UNUSED */ +/* + * setupapfile - specifies UPAP info for authenticating with peer. + */ +static int +setupapfile(char **argv) +{ + FILE * ufile; + int l; + + lcp_allowoptions[0].neg_upap = 1; + + /* open user info file */ + seteuid(getuid()); + ufile = fopen(*argv, "r"); + seteuid(0); + if (ufile == NULL) { + option_error("unable to open user login data file %s", *argv); + return 0; + } + check_access(ufile, *argv); + + /* get username */ + if (fgets(user, MAXNAMELEN - 1, ufile) == NULL + || fgets(passwd, MAXSECRETLEN - 1, ufile) == NULL){ + option_error("unable to read user login data file %s", *argv); + return 0; + } + fclose(ufile); + + /* get rid of newlines */ + l = strlen(user); + if (l > 0 && user[l-1] == '\n') + user[l-1] = 0; + l = strlen(passwd); + if (l > 0 && passwd[l-1] == '\n') + passwd[l-1] = 0; + + return (1); +} +#endif /* UNUSED */ + +#if 0 /* UNUSED */ +/* + * privgroup - allow members of the group to have privileged access. + */ +static int +privgroup(char **argv) +{ + struct group *g; + int i; + + g = getgrnam(*argv); + if (g == 0) { + option_error("group %s is unknown", *argv); + return 0; + } + for (i = 0; i < ngroups; ++i) { + if (groups[i] == g->gr_gid) { + privileged = 1; + break; + } + } + return 1; +} +#endif + +#if 0 /* UNUSED */ +/* + * set_noauth_addr - set address(es) that can be used without authentication. + * Equivalent to specifying an entry like `"" * "" addr' in pap-secrets. + */ +static int +set_noauth_addr(char **argv) +{ + char *addr = *argv; + int l = strlen(addr); + struct wordlist *wp; + + wp = (struct wordlist *) malloc(sizeof(struct wordlist) + l + 1); + if (wp == NULL) + novm("allow-ip argument"); + wp->word = (char *) (wp + 1); + wp->next = noauth_addrs; + BCOPY(addr, wp->word, l); + noauth_addrs = wp; + return 1; +} +#endif /* UNUSED */ + +/* + * An Open on LCP has requested a change from Dead to Establish phase. + * Do what's necessary to bring the physical layer up. + */ +void +link_required(int unit) +{ + LWIP_UNUSED_ARG(unit); + + AUTHDEBUG(LOG_INFO, ("link_required: %d\n", unit)); +} + +/* + * LCP has terminated the link; go to the Dead phase and take the + * physical layer down. + */ +void +link_terminated(int unit) +{ + AUTHDEBUG(LOG_INFO, ("link_terminated: %d\n", unit)); + if (lcp_phase[unit] == PHASE_DEAD) { + return; + } + if (logged_in) { + plogout(); + } + lcp_phase[unit] = PHASE_DEAD; + AUTHDEBUG(LOG_NOTICE, ("Connection terminated.\n")); + pppLinkTerminated(unit); +} + +/* + * LCP has gone down; it will either die or try to re-establish. + */ +void +link_down(int unit) +{ + int i; + struct protent *protp; + + AUTHDEBUG(LOG_INFO, ("link_down: %d\n", unit)); + + if (did_authup) { + /* XXX Do link down processing. */ + did_authup = 0; + } + for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) { + if (!protp->enabled_flag) { + continue; + } + if (protp->protocol != PPP_LCP && protp->lowerdown != NULL) { + (*protp->lowerdown)(unit); + } + if (protp->protocol < 0xC000 && protp->close != NULL) { + (*protp->close)(unit, "LCP down"); + } + } + num_np_open = 0; /* number of network protocols we have opened */ + num_np_up = 0; /* Number of network protocols which have come up */ + + if (lcp_phase[unit] != PHASE_DEAD) { + lcp_phase[unit] = PHASE_TERMINATE; + } + pppLinkDown(unit); +} + +/* + * The link is established. + * Proceed to the Dead, Authenticate or Network phase as appropriate. + */ +void +link_established(int unit) +{ + int auth; + int i; + struct protent *protp; + lcp_options *wo = &lcp_wantoptions[unit]; + lcp_options *go = &lcp_gotoptions[unit]; +#if PAP_SUPPORT || CHAP_SUPPORT + lcp_options *ho = &lcp_hisoptions[unit]; +#endif /* PAP_SUPPORT || CHAP_SUPPORT */ + + AUTHDEBUG(LOG_INFO, ("link_established: unit %d; Lowering up all protocols...\n", unit)); + /* + * Tell higher-level protocols that LCP is up. + */ + for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) { + if (protp->protocol != PPP_LCP && protp->enabled_flag && protp->lowerup != NULL) { + (*protp->lowerup)(unit); + } + } + if (ppp_settings.auth_required && !(go->neg_chap || go->neg_upap)) { + /* + * We wanted the peer to authenticate itself, and it refused: + * treat it as though it authenticated with PAP using a username + * of "" and a password of "". If that's not OK, boot it out. + */ + if (!wo->neg_upap || !null_login(unit)) { + AUTHDEBUG(LOG_WARNING, ("peer refused to authenticate\n")); + lcp_close(unit, "peer refused to authenticate"); + return; + } + } + + lcp_phase[unit] = PHASE_AUTHENTICATE; + auth = 0; +#if CHAP_SUPPORT + if (go->neg_chap) { + ChapAuthPeer(unit, ppp_settings.our_name, go->chap_mdtype); + auth |= CHAP_PEER; + } +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT && CHAP_SUPPORT + else +#endif /* PAP_SUPPORT && CHAP_SUPPORT */ +#if PAP_SUPPORT + if (go->neg_upap) { + upap_authpeer(unit); + auth |= PAP_PEER; + } +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + if (ho->neg_chap) { + ChapAuthWithPeer(unit, ppp_settings.user, ho->chap_mdtype); + auth |= CHAP_WITHPEER; + } +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT && CHAP_SUPPORT + else +#endif /* PAP_SUPPORT && CHAP_SUPPORT */ +#if PAP_SUPPORT + if (ho->neg_upap) { + if (ppp_settings.passwd[0] == 0) { + passwd_from_file = 1; + if (!get_pap_passwd(unit, ppp_settings.user, ppp_settings.passwd)) { + AUTHDEBUG(LOG_ERR, ("No secret found for PAP login\n")); + } + } + upap_authwithpeer(unit, ppp_settings.user, ppp_settings.passwd); + auth |= PAP_WITHPEER; + } +#endif /* PAP_SUPPORT */ + auth_pending[unit] = auth; + + if (!auth) { + network_phase(unit); + } +} + +/* + * Proceed to the network phase. + */ +static void +network_phase(int unit) +{ + int i; + struct protent *protp; + lcp_options *go = &lcp_gotoptions[unit]; + + /* + * If the peer had to authenticate, run the auth-up script now. + */ + if ((go->neg_chap || go->neg_upap) && !did_authup) { + /* XXX Do setup for peer authentication. */ + did_authup = 1; + } + +#if CBCP_SUPPORT + /* + * If we negotiated callback, do it now. + */ + if (go->neg_cbcp) { + lcp_phase[unit] = PHASE_CALLBACK; + (*cbcp_protent.open)(unit); + return; + } +#endif /* CBCP_SUPPORT */ + + lcp_phase[unit] = PHASE_NETWORK; + for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) { + if (protp->protocol < 0xC000 && protp->enabled_flag && protp->open != NULL) { + (*protp->open)(unit); + if (protp->protocol != PPP_CCP) { + ++num_np_open; + } + } + } + + if (num_np_open == 0) { + /* nothing to do */ + lcp_close(0, "No network protocols running"); + } +} +/* @todo: add void start_networks(void) here (pppd 2.3.11) */ + +/* + * The peer has failed to authenticate himself using `protocol'. + */ +void +auth_peer_fail(int unit, u16_t protocol) +{ + LWIP_UNUSED_ARG(protocol); + + AUTHDEBUG(LOG_INFO, ("auth_peer_fail: %d proto=%X\n", unit, protocol)); + /* + * Authentication failure: take the link down + */ + lcp_close(unit, "Authentication failed"); +} + + +#if PAP_SUPPORT || CHAP_SUPPORT +/* + * The peer has been successfully authenticated using `protocol'. + */ +void +auth_peer_success(int unit, u16_t protocol, char *name, int namelen) +{ + int pbit; + + AUTHDEBUG(LOG_INFO, ("auth_peer_success: %d proto=%X\n", unit, protocol)); + switch (protocol) { + case PPP_CHAP: + pbit = CHAP_PEER; + break; + case PPP_PAP: + pbit = PAP_PEER; + break; + default: + AUTHDEBUG(LOG_WARNING, ("auth_peer_success: unknown protocol %x\n", protocol)); + return; + } + + /* + * Save the authenticated name of the peer for later. + */ + if (namelen > (int)sizeof(peer_authname) - 1) { + namelen = sizeof(peer_authname) - 1; + } + BCOPY(name, peer_authname, namelen); + peer_authname[namelen] = 0; + + /* + * If there is no more authentication still to be done, + * proceed to the network (or callback) phase. + */ + if ((auth_pending[unit] &= ~pbit) == 0) { + network_phase(unit); + } +} + +/* + * We have failed to authenticate ourselves to the peer using `protocol'. + */ +void +auth_withpeer_fail(int unit, u16_t protocol) +{ + int errCode = PPPERR_AUTHFAIL; + + LWIP_UNUSED_ARG(protocol); + + AUTHDEBUG(LOG_INFO, ("auth_withpeer_fail: %d proto=%X\n", unit, protocol)); + if (passwd_from_file) { + BZERO(ppp_settings.passwd, MAXSECRETLEN); + } + + /* + * We've failed to authenticate ourselves to our peer. + * He'll probably take the link down, and there's not much + * we can do except wait for that. + */ + pppIOCtl(unit, PPPCTLS_ERRCODE, &errCode); + lcp_close(unit, "Failed to authenticate ourselves to peer"); +} + +/* + * We have successfully authenticated ourselves with the peer using `protocol'. + */ +void +auth_withpeer_success(int unit, u16_t protocol) +{ + int pbit; + + AUTHDEBUG(LOG_INFO, ("auth_withpeer_success: %d proto=%X\n", unit, protocol)); + switch (protocol) { + case PPP_CHAP: + pbit = CHAP_WITHPEER; + break; + case PPP_PAP: + if (passwd_from_file) { + BZERO(ppp_settings.passwd, MAXSECRETLEN); + } + pbit = PAP_WITHPEER; + break; + default: + AUTHDEBUG(LOG_WARNING, ("auth_peer_success: unknown protocol %x\n", protocol)); + pbit = 0; + } + + /* + * If there is no more authentication still being done, + * proceed to the network (or callback) phase. + */ + if ((auth_pending[unit] &= ~pbit) == 0) { + network_phase(unit); + } +} +#endif /* PAP_SUPPORT || CHAP_SUPPORT */ + + +/* + * np_up - a network protocol has come up. + */ +void +np_up(int unit, u16_t proto) +{ + LWIP_UNUSED_ARG(unit); + LWIP_UNUSED_ARG(proto); + + AUTHDEBUG(LOG_INFO, ("np_up: %d proto=%X\n", unit, proto)); + if (num_np_up == 0) { + AUTHDEBUG(LOG_INFO, ("np_up: maxconnect=%d idle_time_limit=%d\n",ppp_settings.maxconnect,ppp_settings.idle_time_limit)); + /* + * At this point we consider that the link has come up successfully. + */ + if (ppp_settings.idle_time_limit > 0) { + TIMEOUT(check_idle, NULL, ppp_settings.idle_time_limit); + } + + /* + * Set a timeout to close the connection once the maximum + * connect time has expired. + */ + if (ppp_settings.maxconnect > 0) { + TIMEOUT(connect_time_expired, 0, ppp_settings.maxconnect); + } + } + ++num_np_up; +} + +/* + * np_down - a network protocol has gone down. + */ +void +np_down(int unit, u16_t proto) +{ + LWIP_UNUSED_ARG(unit); + LWIP_UNUSED_ARG(proto); + + AUTHDEBUG(LOG_INFO, ("np_down: %d proto=%X\n", unit, proto)); + if (--num_np_up == 0 && ppp_settings.idle_time_limit > 0) { + UNTIMEOUT(check_idle, NULL); + } +} + +/* + * np_finished - a network protocol has finished using the link. + */ +void +np_finished(int unit, u16_t proto) +{ + LWIP_UNUSED_ARG(unit); + LWIP_UNUSED_ARG(proto); + + AUTHDEBUG(LOG_INFO, ("np_finished: %d proto=%X\n", unit, proto)); + if (--num_np_open <= 0) { + /* no further use for the link: shut up shop. */ + lcp_close(0, "No network protocols running"); + } +} + +/* + * check_idle - check whether the link has been idle for long + * enough that we can shut it down. + */ +static void +check_idle(void *arg) +{ + struct ppp_idle idle; + u_short itime; + + LWIP_UNUSED_ARG(arg); + if (!get_idle_time(0, &idle)) { + return; + } + itime = LWIP_MIN(idle.xmit_idle, idle.recv_idle); + if (itime >= ppp_settings.idle_time_limit) { + /* link is idle: shut it down. */ + AUTHDEBUG(LOG_INFO, ("Terminating connection due to lack of activity.\n")); + lcp_close(0, "Link inactive"); + } else { + TIMEOUT(check_idle, NULL, ppp_settings.idle_time_limit - itime); + } +} + +/* + * connect_time_expired - log a message and close the connection. + */ +static void +connect_time_expired(void *arg) +{ + LWIP_UNUSED_ARG(arg); + + AUTHDEBUG(LOG_INFO, ("Connect time expired\n")); + lcp_close(0, "Connect time expired"); /* Close connection */ +} + +#if 0 /* UNUSED */ +/* + * auth_check_options - called to check authentication options. + */ +void +auth_check_options(void) +{ + lcp_options *wo = &lcp_wantoptions[0]; + int can_auth; + ipcp_options *ipwo = &ipcp_wantoptions[0]; + u32_t remote; + + /* Default our_name to hostname, and user to our_name */ + if (ppp_settings.our_name[0] == 0 || ppp_settings.usehostname) { + strcpy(ppp_settings.our_name, ppp_settings.hostname); + } + + if (ppp_settings.user[0] == 0) { + strcpy(ppp_settings.user, ppp_settings.our_name); + } + + /* If authentication is required, ask peer for CHAP or PAP. */ + if (ppp_settings.auth_required && !wo->neg_chap && !wo->neg_upap) { + wo->neg_chap = 1; + wo->neg_upap = 1; + } + + /* + * Check whether we have appropriate secrets to use + * to authenticate the peer. + */ + can_auth = wo->neg_upap && have_pap_secret(); + if (!can_auth && wo->neg_chap) { + remote = ipwo->accept_remote? 0: ipwo->hisaddr; + can_auth = have_chap_secret(ppp_settings.remote_name, ppp_settings.our_name, remote); + } + + if (ppp_settings.auth_required && !can_auth) { + ppp_panic("No auth secret"); + } +} +#endif /* UNUSED */ + +/* + * auth_reset - called when LCP is starting negotiations to recheck + * authentication options, i.e. whether we have appropriate secrets + * to use for authenticating ourselves and/or the peer. + */ +void +auth_reset(int unit) +{ + lcp_options *go = &lcp_gotoptions[unit]; + lcp_options *ao = &lcp_allowoptions[0]; + ipcp_options *ipwo = &ipcp_wantoptions[0]; + u32_t remote; + + AUTHDEBUG(LOG_INFO, ("auth_reset: %d\n", unit)); + ao->neg_upap = !ppp_settings.refuse_pap && (ppp_settings.passwd[0] != 0 || get_pap_passwd(unit, NULL, NULL)); + ao->neg_chap = !ppp_settings.refuse_chap && ppp_settings.passwd[0] != 0 /*have_chap_secret(ppp_settings.user, ppp_settings.remote_name, (u32_t)0)*/; + + if (go->neg_upap && !have_pap_secret()) { + go->neg_upap = 0; + } + if (go->neg_chap) { + remote = ipwo->accept_remote? 0: ipwo->hisaddr; + if (!have_chap_secret(ppp_settings.remote_name, ppp_settings.our_name, remote)) { + go->neg_chap = 0; + } + } +} + +#if PAP_SUPPORT +/* + * check_passwd - Check the user name and passwd against the PAP secrets + * file. If requested, also check against the system password database, + * and login the user if OK. + * + * returns: + * UPAP_AUTHNAK: Authentication failed. + * UPAP_AUTHACK: Authentication succeeded. + * In either case, msg points to an appropriate message. + */ +u_char +check_passwd( int unit, char *auser, int userlen, char *apasswd, int passwdlen, char **msg, int *msglen) +{ +#if 1 /* XXX Assume all entries OK. */ + LWIP_UNUSED_ARG(unit); + LWIP_UNUSED_ARG(auser); + LWIP_UNUSED_ARG(userlen); + LWIP_UNUSED_ARG(apasswd); + LWIP_UNUSED_ARG(passwdlen); + LWIP_UNUSED_ARG(msglen); + *msg = (char *) 0; + return UPAP_AUTHACK; /* XXX Assume all entries OK. */ +#else + u_char ret = 0; + struct wordlist *addrs = NULL; + char passwd[256], user[256]; + char secret[MAXWORDLEN]; + static u_short attempts = 0; + + /* + * Make copies of apasswd and auser, then null-terminate them. + */ + BCOPY(apasswd, passwd, passwdlen); + passwd[passwdlen] = '\0'; + BCOPY(auser, user, userlen); + user[userlen] = '\0'; + *msg = (char *) 0; + + /* XXX Validate user name and password. */ + ret = UPAP_AUTHACK; /* XXX Assume all entries OK. */ + + if (ret == UPAP_AUTHNAK) { + if (*msg == (char *) 0) { + *msg = "Login incorrect"; + } + *msglen = strlen(*msg); + /* + * Frustrate passwd stealer programs. + * Allow 10 tries, but start backing off after 3 (stolen from login). + * On 10'th, drop the connection. + */ + if (attempts++ >= 10) { + AUTHDEBUG(LOG_WARNING, ("%d LOGIN FAILURES BY %s\n", attempts, user)); + /*ppp_panic("Excess Bad Logins");*/ + } + if (attempts > 3) { + /* @todo: this was sleep(), i.e. seconds, not milliseconds + * I don't think we really need this in lwIP - we would block tcpip_thread! + */ + /*sys_msleep((attempts - 3) * 5);*/ + } + if (addrs != NULL) { + free_wordlist(addrs); + } + } else { + attempts = 0; /* Reset count */ + if (*msg == (char *) 0) { + *msg = "Login ok"; + } + *msglen = strlen(*msg); + set_allowed_addrs(unit, addrs); + } + + BZERO(passwd, sizeof(passwd)); + BZERO(secret, sizeof(secret)); + + return ret; +#endif +} +#endif /* PAP_SUPPORT */ + +#if 0 /* UNUSED */ +/* + * This function is needed for PAM. + */ + +#ifdef USE_PAM + +/* lwip does not support PAM*/ + +#endif /* USE_PAM */ + +#endif /* UNUSED */ + + +#if 0 /* UNUSED */ +/* + * plogin - Check the user name and password against the system + * password database, and login the user if OK. + * + * returns: + * UPAP_AUTHNAK: Login failed. + * UPAP_AUTHACK: Login succeeded. + * In either case, msg points to an appropriate message. + */ +static int +plogin(char *user, char *passwd, char **msg, int *msglen) +{ + + LWIP_UNUSED_ARG(user); + LWIP_UNUSED_ARG(passwd); + LWIP_UNUSED_ARG(msg); + LWIP_UNUSED_ARG(msglen); + + + /* The new lines are here align the file when + * compared against the pppd 2.3.11 code */ + + + + + + + + + + + + + + + + + /* XXX Fail until we decide that we want to support logins. */ + return (UPAP_AUTHNAK); +} +#endif + + + +/* + * plogout - Logout the user. + */ +static void +plogout(void) +{ + logged_in = 0; +} + +/* + * null_login - Check if a username of "" and a password of "" are + * acceptable, and iff so, set the list of acceptable IP addresses + * and return 1. + */ +static int +null_login(int unit) +{ + LWIP_UNUSED_ARG(unit); + /* XXX Fail until we decide that we want to support logins. */ + return 0; +} + + +/* + * get_pap_passwd - get a password for authenticating ourselves with + * our peer using PAP. Returns 1 on success, 0 if no suitable password + * could be found. + */ +static int +get_pap_passwd(int unit, char *user, char *passwd) +{ + LWIP_UNUSED_ARG(unit); +/* normally we would reject PAP if no password is provided, + but this causes problems with some providers (like CHT in Taiwan) + who incorrectly request PAP and expect a bogus/empty password, so + always provide a default user/passwd of "none"/"none" + + @todo: This should be configured by the user, instead of being hardcoded here! +*/ + if(user) { + strcpy(user, "none"); + } + if(passwd) { + strcpy(passwd, "none"); + } + return 1; +} + +/* + * have_pap_secret - check whether we have a PAP file with any + * secrets that we could possibly use for authenticating the peer. + */ +static int +have_pap_secret(void) +{ + /* XXX Fail until we set up our passwords. */ + return 0; +} + +/* + * have_chap_secret - check whether we have a CHAP file with a + * secret that we could possibly use for authenticating `client' + * on `server'. Either can be the null string, meaning we don't + * know the identity yet. + */ +static int +have_chap_secret(char *client, char *server, u32_t remote) +{ + LWIP_UNUSED_ARG(client); + LWIP_UNUSED_ARG(server); + LWIP_UNUSED_ARG(remote); + + /* XXX Fail until we set up our passwords. */ + return 0; +} +#if CHAP_SUPPORT + +/* + * get_secret - open the CHAP secret file and return the secret + * for authenticating the given client on the given server. + * (We could be either client or server). + */ +int +get_secret(int unit, char *client, char *server, char *secret, int *secret_len, int save_addrs) +{ +#if 1 + int len; + struct wordlist *addrs; + + LWIP_UNUSED_ARG(unit); + LWIP_UNUSED_ARG(server); + LWIP_UNUSED_ARG(save_addrs); + + addrs = NULL; + + if(!client || !client[0] || strcmp(client, ppp_settings.user)) { + return 0; + } + + len = (int)strlen(ppp_settings.passwd); + if (len > MAXSECRETLEN) { + AUTHDEBUG(LOG_ERR, ("Secret for %s on %s is too long\n", client, server)); + len = MAXSECRETLEN; + } + + BCOPY(ppp_settings.passwd, secret, len); + *secret_len = len; + + return 1; +#else + int ret = 0, len; + struct wordlist *addrs; + char secbuf[MAXWORDLEN]; + + addrs = NULL; + secbuf[0] = 0; + + /* XXX Find secret. */ + if (ret < 0) { + return 0; + } + + if (save_addrs) { + set_allowed_addrs(unit, addrs); + } + + len = strlen(secbuf); + if (len > MAXSECRETLEN) { + AUTHDEBUG(LOG_ERR, ("Secret for %s on %s is too long\n", client, server)); + len = MAXSECRETLEN; + } + + BCOPY(secbuf, secret, len); + BZERO(secbuf, sizeof(secbuf)); + *secret_len = len; + + return 1; +#endif +} +#endif /* CHAP_SUPPORT */ + + +#if 0 /* PAP_SUPPORT || CHAP_SUPPORT */ +/* + * set_allowed_addrs() - set the list of allowed addresses. + */ +static void +set_allowed_addrs(int unit, struct wordlist *addrs) +{ + if (addresses[unit] != NULL) { + free_wordlist(addresses[unit]); + } + addresses[unit] = addrs; + +#if 0 + /* + * If there's only one authorized address we might as well + * ask our peer for that one right away + */ + if (addrs != NULL && addrs->next == NULL) { + char *p = addrs->word; + struct ipcp_options *wo = &ipcp_wantoptions[unit]; + u32_t a; + struct hostent *hp; + + if (wo->hisaddr == 0 && *p != '!' && *p != '-' && strchr(p, '/') == NULL) { + hp = gethostbyname(p); + if (hp != NULL && hp->h_addrtype == AF_INET) { + a = *(u32_t *)hp->h_addr; + } else { + a = inet_addr(p); + } + if (a != (u32_t) -1) { + wo->hisaddr = a; + } + } + } +#endif +} +#endif /* 0 */ /* PAP_SUPPORT || CHAP_SUPPORT */ + +/* + * auth_ip_addr - check whether the peer is authorized to use + * a given IP address. Returns 1 if authorized, 0 otherwise. + */ +int +auth_ip_addr(int unit, u32_t addr) +{ + return ip_addr_check(addr, addresses[unit]); +} + +static int /* @todo: integrate this funtion into auth_ip_addr()*/ +ip_addr_check(u32_t addr, struct wordlist *addrs) +{ + /* don't allow loopback or multicast address */ + if (bad_ip_adrs(addr)) { + return 0; + } + + if (addrs == NULL) { + return !ppp_settings.auth_required; /* no addresses authorized */ + } + + /* XXX All other addresses allowed. */ + return 1; +} + +/* + * bad_ip_adrs - return 1 if the IP address is one we don't want + * to use, such as an address in the loopback net or a multicast address. + * addr is in network byte order. + */ +int +bad_ip_adrs(u32_t addr) +{ + addr = ntohl(addr); + return (addr >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET + || IN_MULTICAST(addr) || IN_BADCLASS(addr); +} + +#if 0 /* UNUSED */ /* PAP_SUPPORT || CHAP_SUPPORT */ +/* + * some_ip_ok - check a wordlist to see if it authorizes any + * IP address(es). + */ +static int +some_ip_ok(struct wordlist *addrs) +{ + for (; addrs != 0; addrs = addrs->next) { + if (addrs->word[0] == '-') + break; + if (addrs->word[0] != '!') + return 1; /* some IP address is allowed */ + } + return 0; +} + +/* + * check_access - complain if a secret file has too-liberal permissions. + */ +static void +check_access(FILE *f, char *filename) +{ + struct stat sbuf; + + if (fstat(fileno(f), &sbuf) < 0) { + warn("cannot stat secret file %s: %m", filename); + } else if ((sbuf.st_mode & (S_IRWXG | S_IRWXO)) != 0) { + warn("Warning - secret file %s has world and/or group access", + filename); + } +} + + +/* + * scan_authfile - Scan an authorization file for a secret suitable + * for authenticating `client' on `server'. The return value is -1 + * if no secret is found, otherwise >= 0. The return value has + * NONWILD_CLIENT set if the secret didn't have "*" for the client, and + * NONWILD_SERVER set if the secret didn't have "*" for the server. + * Any following words on the line up to a "--" (i.e. address authorization + * info) are placed in a wordlist and returned in *addrs. Any + * following words (extra options) are placed in a wordlist and + * returned in *opts. + * We assume secret is NULL or points to MAXWORDLEN bytes of space. + */ +static int +scan_authfile(FILE *f, char *client, char *server, char *secret, struct wordlist **addrs, struct wordlist **opts, char *filename) +{ + /* We do not (currently) need this in lwip */ + return 0; /* dummy */ +} +/* + * free_wordlist - release memory allocated for a wordlist. + */ +static void +free_wordlist(struct wordlist *wp) +{ + struct wordlist *next; + + while (wp != NULL) { + next = wp->next; + free(wp); + wp = next; + } +} + +/* + * auth_script_done - called when the auth-up or auth-down script + * has finished. + */ +static void +auth_script_done(void *arg) +{ + auth_script_pid = 0; + switch (auth_script_state) { + case s_up: + if (auth_state == s_down) { + auth_script_state = s_down; + auth_script(_PATH_AUTHDOWN); + } + break; + case s_down: + if (auth_state == s_up) { + auth_script_state = s_up; + auth_script(_PATH_AUTHUP); + } + break; + } +} + +/* + * auth_script - execute a script with arguments + * interface-name peer-name real-user tty speed + */ +static void +auth_script(char *script) +{ + char strspeed[32]; + struct passwd *pw; + char struid[32]; + char *user_name; + char *argv[8]; + + if ((pw = getpwuid(getuid())) != NULL && pw->pw_name != NULL) + user_name = pw->pw_name; + else { + slprintf(struid, sizeof(struid), "%d", getuid()); + user_name = struid; + } + slprintf(strspeed, sizeof(strspeed), "%d", baud_rate); + + argv[0] = script; + argv[1] = ifname; + argv[2] = peer_authname; + argv[3] = user_name; + argv[4] = devnam; + argv[5] = strspeed; + argv[6] = NULL; + + auth_script_pid = run_program(script, argv, 0, auth_script_done, NULL); +} +#endif /* 0 */ /* PAP_SUPPORT || CHAP_SUPPORT */ +#endif /* PPP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/auth.h b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/auth.h new file mode 100644 index 0000000..a8069ec --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/auth.h @@ -0,0 +1,111 @@ +/***************************************************************************** +* auth.h - PPP Authentication and phase control header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1998 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-12-04 Guy Lancaster , Global Election Systems Inc. +* Original derived from BSD pppd.h. +*****************************************************************************/ +/* + * pppd.h - PPP daemon global declarations. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#ifndef AUTH_H +#define AUTH_H + +/*********************** +*** PUBLIC FUNCTIONS *** +***********************/ + +/* we are starting to use the link */ +void link_required (int); + +/* we are finished with the link */ +void link_terminated (int); + +/* the LCP layer has left the Opened state */ +void link_down (int); + +/* the link is up; authenticate now */ +void link_established (int); + +/* a network protocol has come up */ +void np_up (int, u16_t); + +/* a network protocol has gone down */ +void np_down (int, u16_t); + +/* a network protocol no longer needs link */ +void np_finished (int, u16_t); + +/* peer failed to authenticate itself */ +void auth_peer_fail (int, u16_t); + +/* peer successfully authenticated itself */ +void auth_peer_success (int, u16_t, char *, int); + +/* we failed to authenticate ourselves */ +void auth_withpeer_fail (int, u16_t); + +/* we successfully authenticated ourselves */ +void auth_withpeer_success (int, u16_t); + +/* check authentication options supplied */ +void auth_check_options (void); + +/* check what secrets we have */ +void auth_reset (int); + +/* Check peer-supplied username/password */ +u_char check_passwd (int, char *, int, char *, int, char **, int *); + +/* get "secret" for chap */ +int get_secret (int, char *, char *, char *, int *, int); + +/* check if IP address is authorized */ +int auth_ip_addr (int, u32_t); + +/* check if IP address is unreasonable */ +int bad_ip_adrs (u32_t); + +#endif /* AUTH_H */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/chap.c b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/chap.c new file mode 100644 index 0000000..f10e27d --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/chap.c @@ -0,0 +1,908 @@ +/*** WARNING - THIS HAS NEVER BEEN FINISHED ***/ +/***************************************************************************** +* chap.c - Network Challenge Handshake Authentication Protocol program file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 by Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-12-04 Guy Lancaster , Global Election Systems Inc. +* Original based on BSD chap.c. +*****************************************************************************/ +/* + * chap.c - Challenge Handshake Authentication Protocol. + * + * Copyright (c) 1993 The Australian National University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the Australian National University. The name of the University + * may not be used to endorse or promote products derived from this + * software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Copyright (c) 1991 Gregory M. Christy. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Gregory M. Christy. The name of the author may not be used to + * endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "lwip/opt.h" + +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#if CHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "ppp_impl.h" +#include "pppdebug.h" + +#include "magic.h" +#include "randm.h" +#include "auth.h" +#include "md5.h" +#include "chap.h" +#include "chpms.h" + +#include + +#if 0 /* UNUSED */ +/* + * Command-line options. + */ +static option_t chap_option_list[] = { + { "chap-restart", o_int, &chap[0].timeouttime, + "Set timeout for CHAP" }, + { "chap-max-challenge", o_int, &chap[0].max_transmits, + "Set max #xmits for challenge" }, + { "chap-interval", o_int, &chap[0].chal_interval, + "Set interval for rechallenge" }, +#ifdef MSLANMAN + { "ms-lanman", o_bool, &ms_lanman, + "Use LanMan passwd when using MS-CHAP", 1 }, +#endif + { NULL } +}; +#endif /* UNUSED */ + +/* + * Protocol entry points. + */ +static void ChapInit (int); +static void ChapLowerUp (int); +static void ChapLowerDown (int); +static void ChapInput (int, u_char *, int); +static void ChapProtocolReject (int); +#if PPP_ADDITIONAL_CALLBACKS +static int ChapPrintPkt (u_char *, int, void (*) (void *, char *, ...), void *); +#endif + +struct protent chap_protent = { + PPP_CHAP, + ChapInit, + ChapInput, + ChapProtocolReject, + ChapLowerUp, + ChapLowerDown, + NULL, + NULL, +#if PPP_ADDITIONAL_CALLBACKS + ChapPrintPkt, + NULL, +#endif /* PPP_ADDITIONAL_CALLBACKS */ + 1, + "CHAP", +#if PPP_ADDITIONAL_CALLBACKS + NULL, + NULL, + NULL +#endif /* PPP_ADDITIONAL_CALLBACKS */ +}; + +chap_state chap[NUM_PPP]; /* CHAP state; one for each unit */ + +static void ChapChallengeTimeout (void *); +static void ChapResponseTimeout (void *); +static void ChapReceiveChallenge (chap_state *, u_char *, u_char, int); +static void ChapRechallenge (void *); +static void ChapReceiveResponse (chap_state *, u_char *, int, int); +static void ChapReceiveSuccess(chap_state *cstate, u_char *inp, u_char id, int len); +static void ChapReceiveFailure(chap_state *cstate, u_char *inp, u_char id, int len); +static void ChapSendStatus (chap_state *, int); +static void ChapSendChallenge (chap_state *); +static void ChapSendResponse (chap_state *); +static void ChapGenChallenge (chap_state *); + +/* + * ChapInit - Initialize a CHAP unit. + */ +static void +ChapInit(int unit) +{ + chap_state *cstate = &chap[unit]; + + BZERO(cstate, sizeof(*cstate)); + cstate->unit = unit; + cstate->clientstate = CHAPCS_INITIAL; + cstate->serverstate = CHAPSS_INITIAL; + cstate->timeouttime = CHAP_DEFTIMEOUT; + cstate->max_transmits = CHAP_DEFTRANSMITS; + /* random number generator is initialized in magic_init */ +} + + +/* + * ChapAuthWithPeer - Authenticate us with our peer (start client). + * + */ +void +ChapAuthWithPeer(int unit, char *our_name, u_char digest) +{ + chap_state *cstate = &chap[unit]; + + cstate->resp_name = our_name; + cstate->resp_type = digest; + + if (cstate->clientstate == CHAPCS_INITIAL || + cstate->clientstate == CHAPCS_PENDING) { + /* lower layer isn't up - wait until later */ + cstate->clientstate = CHAPCS_PENDING; + return; + } + + /* + * We get here as a result of LCP coming up. + * So even if CHAP was open before, we will + * have to re-authenticate ourselves. + */ + cstate->clientstate = CHAPCS_LISTEN; +} + + +/* + * ChapAuthPeer - Authenticate our peer (start server). + */ +void +ChapAuthPeer(int unit, char *our_name, u_char digest) +{ + chap_state *cstate = &chap[unit]; + + cstate->chal_name = our_name; + cstate->chal_type = digest; + + if (cstate->serverstate == CHAPSS_INITIAL || + cstate->serverstate == CHAPSS_PENDING) { + /* lower layer isn't up - wait until later */ + cstate->serverstate = CHAPSS_PENDING; + return; + } + + ChapGenChallenge(cstate); + ChapSendChallenge(cstate); /* crank it up dude! */ + cstate->serverstate = CHAPSS_INITIAL_CHAL; +} + + +/* + * ChapChallengeTimeout - Timeout expired on sending challenge. + */ +static void +ChapChallengeTimeout(void *arg) +{ + chap_state *cstate = (chap_state *) arg; + + /* if we aren't sending challenges, don't worry. then again we */ + /* probably shouldn't be here either */ + if (cstate->serverstate != CHAPSS_INITIAL_CHAL && + cstate->serverstate != CHAPSS_RECHALLENGE) { + return; + } + + if (cstate->chal_transmits >= cstate->max_transmits) { + /* give up on peer */ + CHAPDEBUG(LOG_ERR, ("Peer failed to respond to CHAP challenge\n")); + cstate->serverstate = CHAPSS_BADAUTH; + auth_peer_fail(cstate->unit, PPP_CHAP); + return; + } + + ChapSendChallenge(cstate); /* Re-send challenge */ +} + + +/* + * ChapResponseTimeout - Timeout expired on sending response. + */ +static void +ChapResponseTimeout(void *arg) +{ + chap_state *cstate = (chap_state *) arg; + + /* if we aren't sending a response, don't worry. */ + if (cstate->clientstate != CHAPCS_RESPONSE) { + return; + } + + ChapSendResponse(cstate); /* re-send response */ +} + + +/* + * ChapRechallenge - Time to challenge the peer again. + */ +static void +ChapRechallenge(void *arg) +{ + chap_state *cstate = (chap_state *) arg; + + /* if we aren't sending a response, don't worry. */ + if (cstate->serverstate != CHAPSS_OPEN) { + return; + } + + ChapGenChallenge(cstate); + ChapSendChallenge(cstate); + cstate->serverstate = CHAPSS_RECHALLENGE; +} + + +/* + * ChapLowerUp - The lower layer is up. + * + * Start up if we have pending requests. + */ +static void +ChapLowerUp(int unit) +{ + chap_state *cstate = &chap[unit]; + + if (cstate->clientstate == CHAPCS_INITIAL) { + cstate->clientstate = CHAPCS_CLOSED; + } else if (cstate->clientstate == CHAPCS_PENDING) { + cstate->clientstate = CHAPCS_LISTEN; + } + + if (cstate->serverstate == CHAPSS_INITIAL) { + cstate->serverstate = CHAPSS_CLOSED; + } else if (cstate->serverstate == CHAPSS_PENDING) { + ChapGenChallenge(cstate); + ChapSendChallenge(cstate); + cstate->serverstate = CHAPSS_INITIAL_CHAL; + } +} + + +/* + * ChapLowerDown - The lower layer is down. + * + * Cancel all timeouts. + */ +static void +ChapLowerDown(int unit) +{ + chap_state *cstate = &chap[unit]; + + /* Timeout(s) pending? Cancel if so. */ + if (cstate->serverstate == CHAPSS_INITIAL_CHAL || + cstate->serverstate == CHAPSS_RECHALLENGE) { + UNTIMEOUT(ChapChallengeTimeout, cstate); + } else if (cstate->serverstate == CHAPSS_OPEN + && cstate->chal_interval != 0) { + UNTIMEOUT(ChapRechallenge, cstate); + } + if (cstate->clientstate == CHAPCS_RESPONSE) { + UNTIMEOUT(ChapResponseTimeout, cstate); + } + cstate->clientstate = CHAPCS_INITIAL; + cstate->serverstate = CHAPSS_INITIAL; +} + + +/* + * ChapProtocolReject - Peer doesn't grok CHAP. + */ +static void +ChapProtocolReject(int unit) +{ + chap_state *cstate = &chap[unit]; + + if (cstate->serverstate != CHAPSS_INITIAL && + cstate->serverstate != CHAPSS_CLOSED) { + auth_peer_fail(unit, PPP_CHAP); + } + if (cstate->clientstate != CHAPCS_INITIAL && + cstate->clientstate != CHAPCS_CLOSED) { + auth_withpeer_fail(unit, PPP_CHAP); /* lwip: just sets the PPP error code on this unit to PPPERR_AUTHFAIL */ + } + ChapLowerDown(unit); /* shutdown chap */ +} + + +/* + * ChapInput - Input CHAP packet. + */ +static void +ChapInput(int unit, u_char *inpacket, int packet_len) +{ + chap_state *cstate = &chap[unit]; + u_char *inp; + u_char code, id; + int len; + + /* + * Parse header (code, id and length). + * If packet too short, drop it. + */ + inp = inpacket; + if (packet_len < CHAP_HEADERLEN) { + CHAPDEBUG(LOG_INFO, ("ChapInput: rcvd short header.\n")); + return; + } + GETCHAR(code, inp); + GETCHAR(id, inp); + GETSHORT(len, inp); + if (len < CHAP_HEADERLEN) { + CHAPDEBUG(LOG_INFO, ("ChapInput: rcvd illegal length.\n")); + return; + } + if (len > packet_len) { + CHAPDEBUG(LOG_INFO, ("ChapInput: rcvd short packet.\n")); + return; + } + len -= CHAP_HEADERLEN; + + /* + * Action depends on code (as in fact it usually does :-). + */ + switch (code) { + case CHAP_CHALLENGE: + ChapReceiveChallenge(cstate, inp, id, len); + break; + + case CHAP_RESPONSE: + ChapReceiveResponse(cstate, inp, id, len); + break; + + case CHAP_FAILURE: + ChapReceiveFailure(cstate, inp, id, len); + break; + + case CHAP_SUCCESS: + ChapReceiveSuccess(cstate, inp, id, len); + break; + + default: /* Need code reject? */ + CHAPDEBUG(LOG_WARNING, ("Unknown CHAP code (%d) received.\n", code)); + break; + } +} + + +/* + * ChapReceiveChallenge - Receive Challenge and send Response. + */ +static void +ChapReceiveChallenge(chap_state *cstate, u_char *inp, u_char id, int len) +{ + int rchallenge_len; + u_char *rchallenge; + int secret_len; + char secret[MAXSECRETLEN]; + char rhostname[256]; + MD5_CTX mdContext; + u_char hash[MD5_SIGNATURE_SIZE]; + + CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: Rcvd id %d.\n", id)); + if (cstate->clientstate == CHAPCS_CLOSED || + cstate->clientstate == CHAPCS_PENDING) { + CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: in state %d\n", + cstate->clientstate)); + return; + } + + if (len < 2) { + CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: rcvd short packet.\n")); + return; + } + + GETCHAR(rchallenge_len, inp); + len -= sizeof (u_char) + rchallenge_len; /* now name field length */ + if (len < 0) { + CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: rcvd short packet.\n")); + return; + } + rchallenge = inp; + INCPTR(rchallenge_len, inp); + + if (len >= (int)sizeof(rhostname)) { + len = sizeof(rhostname) - 1; + } + BCOPY(inp, rhostname, len); + rhostname[len] = '\000'; + + CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: received name field '%s'\n", + rhostname)); + + /* Microsoft doesn't send their name back in the PPP packet */ + if (ppp_settings.remote_name[0] != 0 && (ppp_settings.explicit_remote || rhostname[0] == 0)) { + strncpy(rhostname, ppp_settings.remote_name, sizeof(rhostname)); + rhostname[sizeof(rhostname) - 1] = 0; + CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: using '%s' as remote name\n", + rhostname)); + } + + /* get secret for authenticating ourselves with the specified host */ + if (!get_secret(cstate->unit, cstate->resp_name, rhostname, + secret, &secret_len, 0)) { + secret_len = 0; /* assume null secret if can't find one */ + CHAPDEBUG(LOG_WARNING, ("No CHAP secret found for authenticating us to %s\n", + rhostname)); + } + + /* cancel response send timeout if necessary */ + if (cstate->clientstate == CHAPCS_RESPONSE) { + UNTIMEOUT(ChapResponseTimeout, cstate); + } + + cstate->resp_id = id; + cstate->resp_transmits = 0; + + /* generate MD based on negotiated type */ + switch (cstate->resp_type) { + + case CHAP_DIGEST_MD5: + MD5Init(&mdContext); + MD5Update(&mdContext, &cstate->resp_id, 1); + MD5Update(&mdContext, (u_char*)secret, secret_len); + MD5Update(&mdContext, rchallenge, rchallenge_len); + MD5Final(hash, &mdContext); + BCOPY(hash, cstate->response, MD5_SIGNATURE_SIZE); + cstate->resp_length = MD5_SIGNATURE_SIZE; + break; + +#if MSCHAP_SUPPORT + case CHAP_MICROSOFT: + ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len); + break; +#endif + + default: + CHAPDEBUG(LOG_INFO, ("unknown digest type %d\n", cstate->resp_type)); + return; + } + + BZERO(secret, sizeof(secret)); + ChapSendResponse(cstate); +} + + +/* + * ChapReceiveResponse - Receive and process response. + */ +static void +ChapReceiveResponse(chap_state *cstate, u_char *inp, int id, int len) +{ + u_char *remmd, remmd_len; + int secret_len, old_state; + int code; + char rhostname[256]; + MD5_CTX mdContext; + char secret[MAXSECRETLEN]; + u_char hash[MD5_SIGNATURE_SIZE]; + + CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: Rcvd id %d.\n", id)); + + if (cstate->serverstate == CHAPSS_CLOSED || + cstate->serverstate == CHAPSS_PENDING) { + CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: in state %d\n", + cstate->serverstate)); + return; + } + + if (id != cstate->chal_id) { + return; /* doesn't match ID of last challenge */ + } + + /* + * If we have received a duplicate or bogus Response, + * we have to send the same answer (Success/Failure) + * as we did for the first Response we saw. + */ + if (cstate->serverstate == CHAPSS_OPEN) { + ChapSendStatus(cstate, CHAP_SUCCESS); + return; + } + if (cstate->serverstate == CHAPSS_BADAUTH) { + ChapSendStatus(cstate, CHAP_FAILURE); + return; + } + + if (len < 2) { + CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: rcvd short packet.\n")); + return; + } + GETCHAR(remmd_len, inp); /* get length of MD */ + remmd = inp; /* get pointer to MD */ + INCPTR(remmd_len, inp); + + len -= sizeof (u_char) + remmd_len; + if (len < 0) { + CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: rcvd short packet.\n")); + return; + } + + UNTIMEOUT(ChapChallengeTimeout, cstate); + + if (len >= (int)sizeof(rhostname)) { + len = sizeof(rhostname) - 1; + } + BCOPY(inp, rhostname, len); + rhostname[len] = '\000'; + + CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: received name field: %s\n", + rhostname)); + + /* + * Get secret for authenticating them with us, + * do the hash ourselves, and compare the result. + */ + code = CHAP_FAILURE; + if (!get_secret(cstate->unit, rhostname, cstate->chal_name, + secret, &secret_len, 1)) { + CHAPDEBUG(LOG_WARNING, ("No CHAP secret found for authenticating %s\n", + rhostname)); + } else { + /* generate MD based on negotiated type */ + switch (cstate->chal_type) { + + case CHAP_DIGEST_MD5: /* only MD5 is defined for now */ + if (remmd_len != MD5_SIGNATURE_SIZE) { + break; /* it's not even the right length */ + } + MD5Init(&mdContext); + MD5Update(&mdContext, &cstate->chal_id, 1); + MD5Update(&mdContext, (u_char*)secret, secret_len); + MD5Update(&mdContext, cstate->challenge, cstate->chal_len); + MD5Final(hash, &mdContext); + + /* compare local and remote MDs and send the appropriate status */ + if (memcmp (hash, remmd, MD5_SIGNATURE_SIZE) == 0) { + code = CHAP_SUCCESS; /* they are the same! */ + } + break; + + default: + CHAPDEBUG(LOG_INFO, ("unknown digest type %d\n", cstate->chal_type)); + } + } + + BZERO(secret, sizeof(secret)); + ChapSendStatus(cstate, code); + + if (code == CHAP_SUCCESS) { + old_state = cstate->serverstate; + cstate->serverstate = CHAPSS_OPEN; + if (old_state == CHAPSS_INITIAL_CHAL) { + auth_peer_success(cstate->unit, PPP_CHAP, rhostname, len); + } + if (cstate->chal_interval != 0) { + TIMEOUT(ChapRechallenge, cstate, cstate->chal_interval); + } + } else { + CHAPDEBUG(LOG_ERR, ("CHAP peer authentication failed\n")); + cstate->serverstate = CHAPSS_BADAUTH; + auth_peer_fail(cstate->unit, PPP_CHAP); + } +} + +/* + * ChapReceiveSuccess - Receive Success + */ +static void +ChapReceiveSuccess(chap_state *cstate, u_char *inp, u_char id, int len) +{ + LWIP_UNUSED_ARG(id); + LWIP_UNUSED_ARG(inp); + + CHAPDEBUG(LOG_INFO, ("ChapReceiveSuccess: Rcvd id %d.\n", id)); + + if (cstate->clientstate == CHAPCS_OPEN) { + /* presumably an answer to a duplicate response */ + return; + } + + if (cstate->clientstate != CHAPCS_RESPONSE) { + /* don't know what this is */ + CHAPDEBUG(LOG_INFO, ("ChapReceiveSuccess: in state %d\n", + cstate->clientstate)); + return; + } + + UNTIMEOUT(ChapResponseTimeout, cstate); + + /* + * Print message. + */ + if (len > 0) { + PRINTMSG(inp, len); + } + + cstate->clientstate = CHAPCS_OPEN; + + auth_withpeer_success(cstate->unit, PPP_CHAP); +} + + +/* + * ChapReceiveFailure - Receive failure. + */ +static void +ChapReceiveFailure(chap_state *cstate, u_char *inp, u_char id, int len) +{ + LWIP_UNUSED_ARG(id); + LWIP_UNUSED_ARG(inp); + + CHAPDEBUG(LOG_INFO, ("ChapReceiveFailure: Rcvd id %d.\n", id)); + + if (cstate->clientstate != CHAPCS_RESPONSE) { + /* don't know what this is */ + CHAPDEBUG(LOG_INFO, ("ChapReceiveFailure: in state %d\n", + cstate->clientstate)); + return; + } + + UNTIMEOUT(ChapResponseTimeout, cstate); + + /* + * Print message. + */ + if (len > 0) { + PRINTMSG(inp, len); + } + + CHAPDEBUG(LOG_ERR, ("CHAP authentication failed\n")); + auth_withpeer_fail(cstate->unit, PPP_CHAP); /* lwip: just sets the PPP error code on this unit to PPPERR_AUTHFAIL */ +} + + +/* + * ChapSendChallenge - Send an Authenticate challenge. + */ +static void +ChapSendChallenge(chap_state *cstate) +{ + u_char *outp; + int chal_len, name_len; + int outlen; + + chal_len = cstate->chal_len; + name_len = (int)strlen(cstate->chal_name); + outlen = CHAP_HEADERLEN + sizeof (u_char) + chal_len + name_len; + outp = outpacket_buf[cstate->unit]; + + MAKEHEADER(outp, PPP_CHAP); /* paste in a CHAP header */ + + PUTCHAR(CHAP_CHALLENGE, outp); + PUTCHAR(cstate->chal_id, outp); + PUTSHORT(outlen, outp); + + PUTCHAR(chal_len, outp); /* put length of challenge */ + BCOPY(cstate->challenge, outp, chal_len); + INCPTR(chal_len, outp); + + BCOPY(cstate->chal_name, outp, name_len); /* append hostname */ + + pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN); + + CHAPDEBUG(LOG_INFO, ("ChapSendChallenge: Sent id %d.\n", cstate->chal_id)); + + TIMEOUT(ChapChallengeTimeout, cstate, cstate->timeouttime); + ++cstate->chal_transmits; +} + + +/* + * ChapSendStatus - Send a status response (ack or nak). + */ +static void +ChapSendStatus(chap_state *cstate, int code) +{ + u_char *outp; + int outlen, msglen; + char msg[256]; /* @todo: this can be a char*, no strcpy needed */ + + if (code == CHAP_SUCCESS) { + strcpy(msg, "Welcome!"); + } else { + strcpy(msg, "I don't like you. Go 'way."); + } + msglen = (int)strlen(msg); + + outlen = CHAP_HEADERLEN + msglen; + outp = outpacket_buf[cstate->unit]; + + MAKEHEADER(outp, PPP_CHAP); /* paste in a header */ + + PUTCHAR(code, outp); + PUTCHAR(cstate->chal_id, outp); + PUTSHORT(outlen, outp); + BCOPY(msg, outp, msglen); + pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN); + + CHAPDEBUG(LOG_INFO, ("ChapSendStatus: Sent code %d, id %d.\n", code, + cstate->chal_id)); +} + +/* + * ChapGenChallenge is used to generate a pseudo-random challenge string of + * a pseudo-random length between min_len and max_len. The challenge + * string and its length are stored in *cstate, and various other fields of + * *cstate are initialized. + */ + +static void +ChapGenChallenge(chap_state *cstate) +{ + int chal_len; + u_char *ptr = cstate->challenge; + int i; + + /* pick a random challenge length between MIN_CHALLENGE_LENGTH and + MAX_CHALLENGE_LENGTH */ + chal_len = (unsigned) + ((((magic() >> 16) * + (MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH)) >> 16) + + MIN_CHALLENGE_LENGTH); + LWIP_ASSERT("chal_len <= 0xff", chal_len <= 0xffff); + cstate->chal_len = (u_char)chal_len; + cstate->chal_id = ++cstate->id; + cstate->chal_transmits = 0; + + /* generate a random string */ + for (i = 0; i < chal_len; i++ ) { + *ptr++ = (char) (magic() & 0xff); + } +} + +/* + * ChapSendResponse - send a response packet with values as specified + * in *cstate. + */ +/* ARGSUSED */ +static void +ChapSendResponse(chap_state *cstate) +{ + u_char *outp; + int outlen, md_len, name_len; + + md_len = cstate->resp_length; + name_len = (int)strlen(cstate->resp_name); + outlen = CHAP_HEADERLEN + sizeof (u_char) + md_len + name_len; + outp = outpacket_buf[cstate->unit]; + + MAKEHEADER(outp, PPP_CHAP); + + PUTCHAR(CHAP_RESPONSE, outp); /* we are a response */ + PUTCHAR(cstate->resp_id, outp); /* copy id from challenge packet */ + PUTSHORT(outlen, outp); /* packet length */ + + PUTCHAR(md_len, outp); /* length of MD */ + BCOPY(cstate->response, outp, md_len); /* copy MD to buffer */ + INCPTR(md_len, outp); + + BCOPY(cstate->resp_name, outp, name_len); /* append our name */ + + /* send the packet */ + pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN); + + cstate->clientstate = CHAPCS_RESPONSE; + TIMEOUT(ChapResponseTimeout, cstate, cstate->timeouttime); + ++cstate->resp_transmits; +} + +#if PPP_ADDITIONAL_CALLBACKS +static char *ChapCodenames[] = { + "Challenge", "Response", "Success", "Failure" +}; +/* + * ChapPrintPkt - print the contents of a CHAP packet. + */ +static int +ChapPrintPkt( u_char *p, int plen, void (*printer) (void *, char *, ...), void *arg) +{ + int code, id, len; + int clen, nlen; + u_char x; + + if (plen < CHAP_HEADERLEN) { + return 0; + } + GETCHAR(code, p); + GETCHAR(id, p); + GETSHORT(len, p); + if (len < CHAP_HEADERLEN || len > plen) { + return 0; + } + + if (code >= 1 && code <= sizeof(ChapCodenames) / sizeof(char *)) { + printer(arg, " %s", ChapCodenames[code-1]); + } else { + printer(arg, " code=0x%x", code); + } + printer(arg, " id=0x%x", id); + len -= CHAP_HEADERLEN; + switch (code) { + case CHAP_CHALLENGE: + case CHAP_RESPONSE: + if (len < 1) { + break; + } + clen = p[0]; + if (len < clen + 1) { + break; + } + ++p; + nlen = len - clen - 1; + printer(arg, " <"); + for (; clen > 0; --clen) { + GETCHAR(x, p); + printer(arg, "%.2x", x); + } + printer(arg, ">, name = %.*Z", nlen, p); + break; + case CHAP_FAILURE: + case CHAP_SUCCESS: + printer(arg, " %.*Z", len, p); + break; + default: + for (clen = len; clen > 0; --clen) { + GETCHAR(x, p); + printer(arg, " %.2x", x); + } + } + + return len + CHAP_HEADERLEN; +} +#endif /* PPP_ADDITIONAL_CALLBACKS */ + +#endif /* CHAP_SUPPORT */ + +#endif /* PPP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/chap.h b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/chap.h new file mode 100644 index 0000000..fedcab8 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/chap.h @@ -0,0 +1,150 @@ +/***************************************************************************** +* chap.h - Network Challenge Handshake Authentication Protocol header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1998 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-12-03 Guy Lancaster , Global Election Systems Inc. +* Original built from BSD network code. +******************************************************************************/ +/* + * chap.h - Challenge Handshake Authentication Protocol definitions. + * + * Copyright (c) 1993 The Australian National University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the Australian National University. The name of the University + * may not be used to endorse or promote products derived from this + * software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Copyright (c) 1991 Gregory M. Christy + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the author. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * $Id: chap.h,v 1.6 2010/01/24 13:19:34 goldsimon Exp $ + */ + +#ifndef CHAP_H +#define CHAP_H + +/* Code + ID + length */ +#define CHAP_HEADERLEN 4 + +/* + * CHAP codes. + */ + +#define CHAP_DIGEST_MD5 5 /* use MD5 algorithm */ +#define MD5_SIGNATURE_SIZE 16 /* 16 bytes in a MD5 message digest */ +#define CHAP_MICROSOFT 0x80 /* use Microsoft-compatible alg. */ +#define MS_CHAP_RESPONSE_LEN 49 /* Response length for MS-CHAP */ + +#define CHAP_CHALLENGE 1 +#define CHAP_RESPONSE 2 +#define CHAP_SUCCESS 3 +#define CHAP_FAILURE 4 + +/* + * Challenge lengths (for challenges we send) and other limits. + */ +#define MIN_CHALLENGE_LENGTH 32 +#define MAX_CHALLENGE_LENGTH 64 +#define MAX_RESPONSE_LENGTH 64 /* sufficient for MD5 or MS-CHAP */ + +/* + * Each interface is described by a chap structure. + */ + +typedef struct chap_state { + int unit; /* Interface unit number */ + int clientstate; /* Client state */ + int serverstate; /* Server state */ + u_char challenge[MAX_CHALLENGE_LENGTH]; /* last challenge string sent */ + u_char chal_len; /* challenge length */ + u_char chal_id; /* ID of last challenge */ + u_char chal_type; /* hash algorithm for challenges */ + u_char id; /* Current id */ + char *chal_name; /* Our name to use with challenge */ + int chal_interval; /* Time until we challenge peer again */ + int timeouttime; /* Timeout time in seconds */ + int max_transmits; /* Maximum # of challenge transmissions */ + int chal_transmits; /* Number of transmissions of challenge */ + int resp_transmits; /* Number of transmissions of response */ + u_char response[MAX_RESPONSE_LENGTH]; /* Response to send */ + u_char resp_length; /* length of response */ + u_char resp_id; /* ID for response messages */ + u_char resp_type; /* hash algorithm for responses */ + char *resp_name; /* Our name to send with response */ +} chap_state; + + +/* + * Client (peer) states. + */ +#define CHAPCS_INITIAL 0 /* Lower layer down, not opened */ +#define CHAPCS_CLOSED 1 /* Lower layer up, not opened */ +#define CHAPCS_PENDING 2 /* Auth us to peer when lower up */ +#define CHAPCS_LISTEN 3 /* Listening for a challenge */ +#define CHAPCS_RESPONSE 4 /* Sent response, waiting for status */ +#define CHAPCS_OPEN 5 /* We've received Success */ + +/* + * Server (authenticator) states. + */ +#define CHAPSS_INITIAL 0 /* Lower layer down, not opened */ +#define CHAPSS_CLOSED 1 /* Lower layer up, not opened */ +#define CHAPSS_PENDING 2 /* Auth peer when lower up */ +#define CHAPSS_INITIAL_CHAL 3 /* We've sent the first challenge */ +#define CHAPSS_OPEN 4 /* We've sent a Success msg */ +#define CHAPSS_RECHALLENGE 5 /* We've sent another challenge */ +#define CHAPSS_BADAUTH 6 /* We've sent a Failure msg */ + +extern chap_state chap[]; + +void ChapAuthWithPeer (int, char *, u_char); +void ChapAuthPeer (int, char *, u_char); + +extern struct protent chap_protent; + +#endif /* CHAP_H */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/chpms.c b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/chpms.c new file mode 100644 index 0000000..81a887b --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/chpms.c @@ -0,0 +1,396 @@ +/*** WARNING - THIS CODE HAS NOT BEEN FINISHED! ***/ +/*** The original PPPD code is written in a way to require either the UNIX DES + encryption functions encrypt(3) and setkey(3) or the DES library libdes. + Since both is not included in lwIP, MSCHAP currently does not work! */ +/***************************************************************************** +* chpms.c - Network MicroSoft Challenge Handshake Authentication Protocol program file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* Copyright (c) 1997 by Global Election Systems Inc. All rights reserved. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-12-08 Guy Lancaster , Global Election Systems Inc. +* Original based on BSD chap_ms.c. +*****************************************************************************/ +/* + * chap_ms.c - Microsoft MS-CHAP compatible implementation. + * + * Copyright (c) 1995 Eric Rosenquist, Strata Software Limited. + * http://www.strataware.com/ + * + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Eric Rosenquist. The name of the author may not be used to + * endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* + * Modifications by Lauri Pesonen / lpesonen@clinet.fi, april 1997 + * + * Implemented LANManager type password response to MS-CHAP challenges. + * Now pppd provides both NT style and LANMan style blocks, and the + * prefered is set by option "ms-lanman". Default is to use NT. + * The hash text (StdText) was taken from Win95 RASAPI32.DLL. + * + * You should also use DOMAIN\\USERNAME as described in README.MSCHAP80 + */ + +#define USE_CRYPT + +#include "lwip/opt.h" + +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#if MSCHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "ppp_impl.h" +#include "pppdebug.h" + +#include "md4.h" +#ifndef USE_CRYPT +#include "des.h" +#endif +#include "chap.h" +#include "chpms.h" + +#include + + +/*************************/ +/*** LOCAL DEFINITIONS ***/ +/*************************/ + + +/************************/ +/*** LOCAL DATA TYPES ***/ +/************************/ +typedef struct { + u_char LANManResp[24]; + u_char NTResp[24]; + u_char UseNT; /* If 1, ignore the LANMan response field */ +} MS_ChapResponse; +/* We use MS_CHAP_RESPONSE_LEN, rather than sizeof(MS_ChapResponse), + in case this struct gets padded. */ + + + +/***********************************/ +/*** LOCAL FUNCTION DECLARATIONS ***/ +/***********************************/ + +/* XXX Don't know what to do with these. */ +extern void setkey(const char *); +extern void encrypt(char *, int); + +static void DesEncrypt (u_char *, u_char *, u_char *); +static void MakeKey (u_char *, u_char *); + +#ifdef USE_CRYPT +static void Expand (u_char *, u_char *); +static void Collapse (u_char *, u_char *); +#endif + +static void ChallengeResponse( + u_char *challenge, /* IN 8 octets */ + u_char *pwHash, /* IN 16 octets */ + u_char *response /* OUT 24 octets */ +); +static void ChapMS_NT( + char *rchallenge, + int rchallenge_len, + char *secret, + int secret_len, + MS_ChapResponse *response +); +static u_char Get7Bits( + u_char *input, + int startBit +); + +static void +ChallengeResponse( u_char *challenge, /* IN 8 octets */ + u_char *pwHash, /* IN 16 octets */ + u_char *response /* OUT 24 octets */) +{ + u_char ZPasswordHash[21]; + + BZERO(ZPasswordHash, sizeof(ZPasswordHash)); + BCOPY(pwHash, ZPasswordHash, 16); + +#if 0 + log_packet(ZPasswordHash, sizeof(ZPasswordHash), "ChallengeResponse - ZPasswordHash", LOG_DEBUG); +#endif + + DesEncrypt(challenge, ZPasswordHash + 0, response + 0); + DesEncrypt(challenge, ZPasswordHash + 7, response + 8); + DesEncrypt(challenge, ZPasswordHash + 14, response + 16); + +#if 0 + log_packet(response, 24, "ChallengeResponse - response", LOG_DEBUG); +#endif +} + + +#ifdef USE_CRYPT +static void +DesEncrypt( u_char *clear, /* IN 8 octets */ + u_char *key, /* IN 7 octets */ + u_char *cipher /* OUT 8 octets */) +{ + u_char des_key[8]; + u_char crypt_key[66]; + u_char des_input[66]; + + MakeKey(key, des_key); + + Expand(des_key, crypt_key); + setkey((char*)crypt_key); + +#if 0 + CHAPDEBUG(LOG_INFO, ("DesEncrypt: 8 octet input : %02X%02X%02X%02X%02X%02X%02X%02X\n", + clear[0], clear[1], clear[2], clear[3], clear[4], clear[5], clear[6], clear[7])); +#endif + + Expand(clear, des_input); + encrypt((char*)des_input, 0); + Collapse(des_input, cipher); + +#if 0 + CHAPDEBUG(LOG_INFO, ("DesEncrypt: 8 octet output: %02X%02X%02X%02X%02X%02X%02X%02X\n", + cipher[0], cipher[1], cipher[2], cipher[3], cipher[4], cipher[5], cipher[6], cipher[7])); +#endif +} + +#else /* USE_CRYPT */ + +static void +DesEncrypt( u_char *clear, /* IN 8 octets */ + u_char *key, /* IN 7 octets */ + u_char *cipher /* OUT 8 octets */) +{ + des_cblock des_key; + des_key_schedule key_schedule; + + MakeKey(key, des_key); + + des_set_key(&des_key, key_schedule); + +#if 0 + CHAPDEBUG(LOG_INFO, ("DesEncrypt: 8 octet input : %02X%02X%02X%02X%02X%02X%02X%02X\n", + clear[0], clear[1], clear[2], clear[3], clear[4], clear[5], clear[6], clear[7])); +#endif + + des_ecb_encrypt((des_cblock *)clear, (des_cblock *)cipher, key_schedule, 1); + +#if 0 + CHAPDEBUG(LOG_INFO, ("DesEncrypt: 8 octet output: %02X%02X%02X%02X%02X%02X%02X%02X\n", + cipher[0], cipher[1], cipher[2], cipher[3], cipher[4], cipher[5], cipher[6], cipher[7])); +#endif +} + +#endif /* USE_CRYPT */ + + +static u_char +Get7Bits( u_char *input, int startBit) +{ + register unsigned int word; + + word = (unsigned)input[startBit / 8] << 8; + word |= (unsigned)input[startBit / 8 + 1]; + + word >>= 15 - (startBit % 8 + 7); + + return word & 0xFE; +} + +#ifdef USE_CRYPT + +/* in == 8-byte string (expanded version of the 56-bit key) + * out == 64-byte string where each byte is either 1 or 0 + * Note that the low-order "bit" is always ignored by by setkey() + */ +static void +Expand(u_char *in, u_char *out) +{ + int j, c; + int i; + + for(i = 0; i < 64; in++){ + c = *in; + for(j = 7; j >= 0; j--) { + *out++ = (c >> j) & 01; + } + i += 8; + } +} + +/* The inverse of Expand + */ +static void +Collapse(u_char *in, u_char *out) +{ + int j; + int i; + unsigned int c; + + for (i = 0; i < 64; i += 8, out++) { + c = 0; + for (j = 7; j >= 0; j--, in++) { + c |= *in << j; + } + *out = c & 0xff; + } +} +#endif + +static void +MakeKey( u_char *key, /* IN 56 bit DES key missing parity bits */ + u_char *des_key /* OUT 64 bit DES key with parity bits added */) +{ + des_key[0] = Get7Bits(key, 0); + des_key[1] = Get7Bits(key, 7); + des_key[2] = Get7Bits(key, 14); + des_key[3] = Get7Bits(key, 21); + des_key[4] = Get7Bits(key, 28); + des_key[5] = Get7Bits(key, 35); + des_key[6] = Get7Bits(key, 42); + des_key[7] = Get7Bits(key, 49); + +#ifndef USE_CRYPT + des_set_odd_parity((des_cblock *)des_key); +#endif + +#if 0 + CHAPDEBUG(LOG_INFO, ("MakeKey: 56-bit input : %02X%02X%02X%02X%02X%02X%02X\n", + key[0], key[1], key[2], key[3], key[4], key[5], key[6])); + CHAPDEBUG(LOG_INFO, ("MakeKey: 64-bit output: %02X%02X%02X%02X%02X%02X%02X%02X\n", + des_key[0], des_key[1], des_key[2], des_key[3], des_key[4], des_key[5], des_key[6], des_key[7])); +#endif +} + +static void +ChapMS_NT( char *rchallenge, + int rchallenge_len, + char *secret, + int secret_len, + MS_ChapResponse *response) +{ + int i; + MDstruct md4Context; + u_char unicodePassword[MAX_NT_PASSWORD * 2]; + static int low_byte_first = -1; + + LWIP_UNUSED_ARG(rchallenge_len); + + /* Initialize the Unicode version of the secret (== password). */ + /* This implicitly supports 8-bit ISO8859/1 characters. */ + BZERO(unicodePassword, sizeof(unicodePassword)); + for (i = 0; i < secret_len; i++) { + unicodePassword[i * 2] = (u_char)secret[i]; + } + MDbegin(&md4Context); + MDupdate(&md4Context, unicodePassword, secret_len * 2 * 8); /* Unicode is 2 bytes/char, *8 for bit count */ + + if (low_byte_first == -1) { + low_byte_first = (PP_HTONS((unsigned short int)1) != 1); + } + if (low_byte_first == 0) { + /* @todo: arg type - u_long* or u_int* ? */ + MDreverse((unsigned int*)&md4Context); /* sfb 961105 */ + } + + MDupdate(&md4Context, NULL, 0); /* Tell MD4 we're done */ + + ChallengeResponse((u_char*)rchallenge, (u_char*)md4Context.buffer, response->NTResp); +} + +#ifdef MSLANMAN +static u_char *StdText = (u_char *)"KGS!@#$%"; /* key from rasapi32.dll */ + +static void +ChapMS_LANMan( char *rchallenge, + int rchallenge_len, + char *secret, + int secret_len, + MS_ChapResponse *response) +{ + int i; + u_char UcasePassword[MAX_NT_PASSWORD]; /* max is actually 14 */ + u_char PasswordHash[16]; + + /* LANMan password is case insensitive */ + BZERO(UcasePassword, sizeof(UcasePassword)); + for (i = 0; i < secret_len; i++) { + UcasePassword[i] = (u_char)toupper(secret[i]); + } + DesEncrypt( StdText, UcasePassword + 0, PasswordHash + 0 ); + DesEncrypt( StdText, UcasePassword + 7, PasswordHash + 8 ); + ChallengeResponse(rchallenge, PasswordHash, response->LANManResp); +} +#endif + +void +ChapMS( chap_state *cstate, char *rchallenge, int rchallenge_len, char *secret, int secret_len) +{ + MS_ChapResponse response; +#ifdef MSLANMAN + extern int ms_lanman; +#endif + +#if 0 + CHAPDEBUG(LOG_INFO, ("ChapMS: secret is '%.*s'\n", secret_len, secret)); +#endif + BZERO(&response, sizeof(response)); + + /* Calculate both always */ + ChapMS_NT(rchallenge, rchallenge_len, secret, secret_len, &response); + +#ifdef MSLANMAN + ChapMS_LANMan(rchallenge, rchallenge_len, secret, secret_len, &response); + + /* prefered method is set by option */ + response.UseNT = !ms_lanman; +#else + response.UseNT = 1; +#endif + + BCOPY(&response, cstate->response, MS_CHAP_RESPONSE_LEN); + cstate->resp_length = MS_CHAP_RESPONSE_LEN; +} + +#endif /* MSCHAP_SUPPORT */ + +#endif /* PPP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/chpms.h b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/chpms.h new file mode 100644 index 0000000..df070fb --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/chpms.h @@ -0,0 +1,64 @@ +/***************************************************************************** +* chpms.h - Network Microsoft Challenge Handshake Protocol header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1998 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 98-01-30 Guy Lancaster , Global Election Systems Inc. +* Original built from BSD network code. +******************************************************************************/ +/* + * chap.h - Challenge Handshake Authentication Protocol definitions. + * + * Copyright (c) 1995 Eric Rosenquist, Strata Software Limited. + * http://www.strataware.com/ + * + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Eric Rosenquist. The name of the author may not be used to + * endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * $Id: chpms.h,v 1.5 2007/12/19 20:47:23 fbernon Exp $ + */ + +#ifndef CHPMS_H +#define CHPMS_H + +#define MAX_NT_PASSWORD 256 /* Maximum number of (Unicode) chars in an NT password */ + +void ChapMS (chap_state *, char *, int, char *, int); + +#endif /* CHPMS_H */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/fsm.c b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/fsm.c new file mode 100644 index 0000000..e8a254e --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/fsm.c @@ -0,0 +1,890 @@ +/***************************************************************************** +* fsm.c - Network Control Protocol Finite State Machine program file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 by Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-12-01 Guy Lancaster , Global Election Systems Inc. +* Original based on BSD fsm.c. +*****************************************************************************/ +/* + * fsm.c - {Link, IP} Control Protocol Finite State Machine. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* + * TODO: + * Randomize fsm id on link/init. + * Deal with variable outgoing MTU. + */ + +#include "lwip/opt.h" + +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "ppp_impl.h" +#include "pppdebug.h" + +#include "fsm.h" + +#include + +#if PPP_DEBUG +static const char *ppperr_strerr[] = { + "LS_INITIAL", /* LS_INITIAL 0 */ + "LS_STARTING", /* LS_STARTING 1 */ + "LS_CLOSED", /* LS_CLOSED 2 */ + "LS_STOPPED", /* LS_STOPPED 3 */ + "LS_CLOSING", /* LS_CLOSING 4 */ + "LS_STOPPING", /* LS_STOPPING 5 */ + "LS_REQSENT", /* LS_REQSENT 6 */ + "LS_ACKRCVD", /* LS_ACKRCVD 7 */ + "LS_ACKSENT", /* LS_ACKSENT 8 */ + "LS_OPENED" /* LS_OPENED 9 */ +}; +#endif /* PPP_DEBUG */ + +static void fsm_timeout (void *); +static void fsm_rconfreq (fsm *, u_char, u_char *, int); +static void fsm_rconfack (fsm *, int, u_char *, int); +static void fsm_rconfnakrej (fsm *, int, int, u_char *, int); +static void fsm_rtermreq (fsm *, int, u_char *, int); +static void fsm_rtermack (fsm *); +static void fsm_rcoderej (fsm *, u_char *, int); +static void fsm_sconfreq (fsm *, int); + +#define PROTO_NAME(f) ((f)->callbacks->proto_name) + +int peer_mru[NUM_PPP]; + + +/* + * fsm_init - Initialize fsm. + * + * Initialize fsm state. + */ +void +fsm_init(fsm *f) +{ + f->state = LS_INITIAL; + f->flags = 0; + f->id = 0; /* XXX Start with random id? */ + f->timeouttime = FSM_DEFTIMEOUT; + f->maxconfreqtransmits = FSM_DEFMAXCONFREQS; + f->maxtermtransmits = FSM_DEFMAXTERMREQS; + f->maxnakloops = FSM_DEFMAXNAKLOOPS; + f->term_reason_len = 0; +} + + +/* + * fsm_lowerup - The lower layer is up. + */ +void +fsm_lowerup(fsm *f) +{ + int oldState = f->state; + + LWIP_UNUSED_ARG(oldState); + + switch( f->state ) { + case LS_INITIAL: + f->state = LS_CLOSED; + break; + + case LS_STARTING: + if( f->flags & OPT_SILENT ) { + f->state = LS_STOPPED; + } else { + /* Send an initial configure-request */ + fsm_sconfreq(f, 0); + f->state = LS_REQSENT; + } + break; + + default: + FSMDEBUG(LOG_INFO, ("%s: Up event in state %d (%s)!\n", + PROTO_NAME(f), f->state, ppperr_strerr[f->state])); + } + + FSMDEBUG(LOG_INFO, ("%s: lowerup state %d (%s) -> %d (%s)\n", + PROTO_NAME(f), oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state])); +} + + +/* + * fsm_lowerdown - The lower layer is down. + * + * Cancel all timeouts and inform upper layers. + */ +void +fsm_lowerdown(fsm *f) +{ + int oldState = f->state; + + LWIP_UNUSED_ARG(oldState); + + switch( f->state ) { + case LS_CLOSED: + f->state = LS_INITIAL; + break; + + case LS_STOPPED: + f->state = LS_STARTING; + if( f->callbacks->starting ) { + (*f->callbacks->starting)(f); + } + break; + + case LS_CLOSING: + f->state = LS_INITIAL; + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + break; + + case LS_STOPPING: + case LS_REQSENT: + case LS_ACKRCVD: + case LS_ACKSENT: + f->state = LS_STARTING; + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + break; + + case LS_OPENED: + if( f->callbacks->down ) { + (*f->callbacks->down)(f); + } + f->state = LS_STARTING; + break; + + default: + FSMDEBUG(LOG_INFO, ("%s: Down event in state %d (%s)!\n", + PROTO_NAME(f), f->state, ppperr_strerr[f->state])); + } + + FSMDEBUG(LOG_INFO, ("%s: lowerdown state %d (%s) -> %d (%s)\n", + PROTO_NAME(f), oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state])); +} + + +/* + * fsm_open - Link is allowed to come up. + */ +void +fsm_open(fsm *f) +{ + int oldState = f->state; + + LWIP_UNUSED_ARG(oldState); + + switch( f->state ) { + case LS_INITIAL: + f->state = LS_STARTING; + if( f->callbacks->starting ) { + (*f->callbacks->starting)(f); + } + break; + + case LS_CLOSED: + if( f->flags & OPT_SILENT ) { + f->state = LS_STOPPED; + } else { + /* Send an initial configure-request */ + fsm_sconfreq(f, 0); + f->state = LS_REQSENT; + } + break; + + case LS_CLOSING: + f->state = LS_STOPPING; + /* fall through */ + case LS_STOPPED: + case LS_OPENED: + if( f->flags & OPT_RESTART ) { + fsm_lowerdown(f); + fsm_lowerup(f); + } + break; + } + + FSMDEBUG(LOG_INFO, ("%s: open state %d (%s) -> %d (%s)\n", + PROTO_NAME(f), oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state])); +} + +#if 0 /* backport pppd 2.4.4b1; */ +/* + * terminate_layer - Start process of shutting down the FSM + * + * Cancel any timeout running, notify upper layers we're done, and + * send a terminate-request message as configured. + */ +static void +terminate_layer(fsm *f, int nextstate) +{ + /* @todo */ +} +#endif + +/* + * fsm_close - Start closing connection. + * + * Cancel timeouts and either initiate close or possibly go directly to + * the LS_CLOSED state. + */ +void +fsm_close(fsm *f, char *reason) +{ + int oldState = f->state; + + LWIP_UNUSED_ARG(oldState); + + f->term_reason = reason; + f->term_reason_len = (reason == NULL ? 0 : (int)strlen(reason)); + switch( f->state ) { + case LS_STARTING: + f->state = LS_INITIAL; + break; + case LS_STOPPED: + f->state = LS_CLOSED; + break; + case LS_STOPPING: + f->state = LS_CLOSING; + break; + + case LS_REQSENT: + case LS_ACKRCVD: + case LS_ACKSENT: + case LS_OPENED: + if( f->state != LS_OPENED ) { + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + } else if( f->callbacks->down ) { + (*f->callbacks->down)(f); /* Inform upper layers we're down */ + } + /* Init restart counter, send Terminate-Request */ + f->retransmits = f->maxtermtransmits; + fsm_sdata(f, TERMREQ, f->reqid = ++f->id, + (u_char *) f->term_reason, f->term_reason_len); + TIMEOUT(fsm_timeout, f, f->timeouttime); + --f->retransmits; + + f->state = LS_CLOSING; + break; + } + + FSMDEBUG(LOG_INFO, ("%s: close reason=%s state %d (%s) -> %d (%s)\n", + PROTO_NAME(f), reason, oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state])); +} + + +/* + * fsm_timeout - Timeout expired. + */ +static void +fsm_timeout(void *arg) +{ + fsm *f = (fsm *) arg; + + switch (f->state) { + case LS_CLOSING: + case LS_STOPPING: + if( f->retransmits <= 0 ) { + FSMDEBUG(LOG_WARNING, ("%s: timeout sending Terminate-Request state=%d (%s)\n", + PROTO_NAME(f), f->state, ppperr_strerr[f->state])); + /* + * We've waited for an ack long enough. Peer probably heard us. + */ + f->state = (f->state == LS_CLOSING)? LS_CLOSED: LS_STOPPED; + if( f->callbacks->finished ) { + (*f->callbacks->finished)(f); + } + } else { + FSMDEBUG(LOG_WARNING, ("%s: timeout resending Terminate-Requests state=%d (%s)\n", + PROTO_NAME(f), f->state, ppperr_strerr[f->state])); + /* Send Terminate-Request */ + fsm_sdata(f, TERMREQ, f->reqid = ++f->id, + (u_char *) f->term_reason, f->term_reason_len); + TIMEOUT(fsm_timeout, f, f->timeouttime); + --f->retransmits; + } + break; + + case LS_REQSENT: + case LS_ACKRCVD: + case LS_ACKSENT: + if (f->retransmits <= 0) { + FSMDEBUG(LOG_WARNING, ("%s: timeout sending Config-Requests state=%d (%s)\n", + PROTO_NAME(f), f->state, ppperr_strerr[f->state])); + f->state = LS_STOPPED; + if( (f->flags & OPT_PASSIVE) == 0 && f->callbacks->finished ) { + (*f->callbacks->finished)(f); + } + } else { + FSMDEBUG(LOG_WARNING, ("%s: timeout resending Config-Request state=%d (%s)\n", + PROTO_NAME(f), f->state, ppperr_strerr[f->state])); + /* Retransmit the configure-request */ + if (f->callbacks->retransmit) { + (*f->callbacks->retransmit)(f); + } + fsm_sconfreq(f, 1); /* Re-send Configure-Request */ + if( f->state == LS_ACKRCVD ) { + f->state = LS_REQSENT; + } + } + break; + + default: + FSMDEBUG(LOG_INFO, ("%s: UNHANDLED timeout event in state %d (%s)!\n", + PROTO_NAME(f), f->state, ppperr_strerr[f->state])); + } +} + + +/* + * fsm_input - Input packet. + */ +void +fsm_input(fsm *f, u_char *inpacket, int l) +{ + u_char *inp = inpacket; + u_char code, id; + int len; + + /* + * Parse header (code, id and length). + * If packet too short, drop it. + */ + if (l < HEADERLEN) { + FSMDEBUG(LOG_WARNING, ("fsm_input(%x): Rcvd short header.\n", + f->protocol)); + return; + } + GETCHAR(code, inp); + GETCHAR(id, inp); + GETSHORT(len, inp); + if (len < HEADERLEN) { + FSMDEBUG(LOG_INFO, ("fsm_input(%x): Rcvd illegal length.\n", + f->protocol)); + return; + } + if (len > l) { + FSMDEBUG(LOG_INFO, ("fsm_input(%x): Rcvd short packet.\n", + f->protocol)); + return; + } + len -= HEADERLEN; /* subtract header length */ + + if( f->state == LS_INITIAL || f->state == LS_STARTING ) { + FSMDEBUG(LOG_INFO, ("fsm_input(%x): Rcvd packet in state %d (%s).\n", + f->protocol, f->state, ppperr_strerr[f->state])); + return; + } + FSMDEBUG(LOG_INFO, ("fsm_input(%s):%d,%d,%d\n", PROTO_NAME(f), code, id, l)); + /* + * Action depends on code. + */ + switch (code) { + case CONFREQ: + fsm_rconfreq(f, id, inp, len); + break; + + case CONFACK: + fsm_rconfack(f, id, inp, len); + break; + + case CONFNAK: + case CONFREJ: + fsm_rconfnakrej(f, code, id, inp, len); + break; + + case TERMREQ: + fsm_rtermreq(f, id, inp, len); + break; + + case TERMACK: + fsm_rtermack(f); + break; + + case CODEREJ: + fsm_rcoderej(f, inp, len); + break; + + default: + FSMDEBUG(LOG_INFO, ("fsm_input(%s): default: \n", PROTO_NAME(f))); + if( !f->callbacks->extcode || + !(*f->callbacks->extcode)(f, code, id, inp, len) ) { + fsm_sdata(f, CODEREJ, ++f->id, inpacket, len + HEADERLEN); + } + break; + } +} + + +/* + * fsm_rconfreq - Receive Configure-Request. + */ +static void +fsm_rconfreq(fsm *f, u_char id, u_char *inp, int len) +{ + int code, reject_if_disagree; + + FSMDEBUG(LOG_INFO, ("fsm_rconfreq(%s): Rcvd id %d state=%d (%s)\n", + PROTO_NAME(f), id, f->state, ppperr_strerr[f->state])); + switch( f->state ) { + case LS_CLOSED: + /* Go away, we're closed */ + fsm_sdata(f, TERMACK, id, NULL, 0); + return; + case LS_CLOSING: + case LS_STOPPING: + return; + + case LS_OPENED: + /* Go down and restart negotiation */ + if( f->callbacks->down ) { + (*f->callbacks->down)(f); /* Inform upper layers */ + } + fsm_sconfreq(f, 0); /* Send initial Configure-Request */ + break; + + case LS_STOPPED: + /* Negotiation started by our peer */ + fsm_sconfreq(f, 0); /* Send initial Configure-Request */ + f->state = LS_REQSENT; + break; + } + + /* + * Pass the requested configuration options + * to protocol-specific code for checking. + */ + if (f->callbacks->reqci) { /* Check CI */ + reject_if_disagree = (f->nakloops >= f->maxnakloops); + code = (*f->callbacks->reqci)(f, inp, &len, reject_if_disagree); + } else if (len) { + code = CONFREJ; /* Reject all CI */ + } else { + code = CONFACK; + } + + /* send the Ack, Nak or Rej to the peer */ + fsm_sdata(f, (u_char)code, id, inp, len); + + if (code == CONFACK) { + if (f->state == LS_ACKRCVD) { + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + f->state = LS_OPENED; + if (f->callbacks->up) { + (*f->callbacks->up)(f); /* Inform upper layers */ + } + } else { + f->state = LS_ACKSENT; + } + f->nakloops = 0; + } else { + /* we sent CONFACK or CONFREJ */ + if (f->state != LS_ACKRCVD) { + f->state = LS_REQSENT; + } + if( code == CONFNAK ) { + ++f->nakloops; + } + } +} + + +/* + * fsm_rconfack - Receive Configure-Ack. + */ +static void +fsm_rconfack(fsm *f, int id, u_char *inp, int len) +{ + FSMDEBUG(LOG_INFO, ("fsm_rconfack(%s): Rcvd id %d state=%d (%s)\n", + PROTO_NAME(f), id, f->state, ppperr_strerr[f->state])); + + if (id != f->reqid || f->seen_ack) { /* Expected id? */ + return; /* Nope, toss... */ + } + if( !(f->callbacks->ackci? (*f->callbacks->ackci)(f, inp, len): (len == 0)) ) { + /* Ack is bad - ignore it */ + FSMDEBUG(LOG_INFO, ("%s: received bad Ack (length %d)\n", + PROTO_NAME(f), len)); + return; + } + f->seen_ack = 1; + + switch (f->state) { + case LS_CLOSED: + case LS_STOPPED: + fsm_sdata(f, TERMACK, (u_char)id, NULL, 0); + break; + + case LS_REQSENT: + f->state = LS_ACKRCVD; + f->retransmits = f->maxconfreqtransmits; + break; + + case LS_ACKRCVD: + /* Huh? an extra valid Ack? oh well... */ + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + fsm_sconfreq(f, 0); + f->state = LS_REQSENT; + break; + + case LS_ACKSENT: + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + f->state = LS_OPENED; + f->retransmits = f->maxconfreqtransmits; + if (f->callbacks->up) { + (*f->callbacks->up)(f); /* Inform upper layers */ + } + break; + + case LS_OPENED: + /* Go down and restart negotiation */ + if (f->callbacks->down) { + (*f->callbacks->down)(f); /* Inform upper layers */ + } + fsm_sconfreq(f, 0); /* Send initial Configure-Request */ + f->state = LS_REQSENT; + break; + } +} + + +/* + * fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject. + */ +static void +fsm_rconfnakrej(fsm *f, int code, int id, u_char *inp, int len) +{ + int (*proc) (fsm *, u_char *, int); + int ret; + + FSMDEBUG(LOG_INFO, ("fsm_rconfnakrej(%s): Rcvd id %d state=%d (%s)\n", + PROTO_NAME(f), id, f->state, ppperr_strerr[f->state])); + + if (id != f->reqid || f->seen_ack) { /* Expected id? */ + return; /* Nope, toss... */ + } + proc = (code == CONFNAK)? f->callbacks->nakci: f->callbacks->rejci; + if (!proc || !((ret = proc(f, inp, len)))) { + /* Nak/reject is bad - ignore it */ + FSMDEBUG(LOG_INFO, ("%s: received bad %s (length %d)\n", + PROTO_NAME(f), (code==CONFNAK? "Nak": "reject"), len)); + return; + } + f->seen_ack = 1; + + switch (f->state) { + case LS_CLOSED: + case LS_STOPPED: + fsm_sdata(f, TERMACK, (u_char)id, NULL, 0); + break; + + case LS_REQSENT: + case LS_ACKSENT: + /* They didn't agree to what we wanted - try another request */ + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + if (ret < 0) { + f->state = LS_STOPPED; /* kludge for stopping CCP */ + } else { + fsm_sconfreq(f, 0); /* Send Configure-Request */ + } + break; + + case LS_ACKRCVD: + /* Got a Nak/reject when we had already had an Ack?? oh well... */ + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + fsm_sconfreq(f, 0); + f->state = LS_REQSENT; + break; + + case LS_OPENED: + /* Go down and restart negotiation */ + if (f->callbacks->down) { + (*f->callbacks->down)(f); /* Inform upper layers */ + } + fsm_sconfreq(f, 0); /* Send initial Configure-Request */ + f->state = LS_REQSENT; + break; + } +} + + +/* + * fsm_rtermreq - Receive Terminate-Req. + */ +static void +fsm_rtermreq(fsm *f, int id, u_char *p, int len) +{ + LWIP_UNUSED_ARG(p); + + FSMDEBUG(LOG_INFO, ("fsm_rtermreq(%s): Rcvd id %d state=%d (%s)\n", + PROTO_NAME(f), id, f->state, ppperr_strerr[f->state])); + + switch (f->state) { + case LS_ACKRCVD: + case LS_ACKSENT: + f->state = LS_REQSENT; /* Start over but keep trying */ + break; + + case LS_OPENED: + if (len > 0) { + FSMDEBUG(LOG_INFO, ("%s terminated by peer (%p)\n", PROTO_NAME(f), p)); + } else { + FSMDEBUG(LOG_INFO, ("%s terminated by peer\n", PROTO_NAME(f))); + } + if (f->callbacks->down) { + (*f->callbacks->down)(f); /* Inform upper layers */ + } + f->retransmits = 0; + f->state = LS_STOPPING; + TIMEOUT(fsm_timeout, f, f->timeouttime); + break; + } + + fsm_sdata(f, TERMACK, (u_char)id, NULL, 0); +} + + +/* + * fsm_rtermack - Receive Terminate-Ack. + */ +static void +fsm_rtermack(fsm *f) +{ + FSMDEBUG(LOG_INFO, ("fsm_rtermack(%s): state=%d (%s)\n", + PROTO_NAME(f), f->state, ppperr_strerr[f->state])); + + switch (f->state) { + case LS_CLOSING: + UNTIMEOUT(fsm_timeout, f); + f->state = LS_CLOSED; + if( f->callbacks->finished ) { + (*f->callbacks->finished)(f); + } + break; + + case LS_STOPPING: + UNTIMEOUT(fsm_timeout, f); + f->state = LS_STOPPED; + if( f->callbacks->finished ) { + (*f->callbacks->finished)(f); + } + break; + + case LS_ACKRCVD: + f->state = LS_REQSENT; + break; + + case LS_OPENED: + if (f->callbacks->down) { + (*f->callbacks->down)(f); /* Inform upper layers */ + } + fsm_sconfreq(f, 0); + break; + default: + FSMDEBUG(LOG_INFO, ("fsm_rtermack(%s): UNHANDLED state=%d (%s)!!!\n", + PROTO_NAME(f), f->state, ppperr_strerr[f->state])); + } +} + + +/* + * fsm_rcoderej - Receive an Code-Reject. + */ +static void +fsm_rcoderej(fsm *f, u_char *inp, int len) +{ + u_char code, id; + + FSMDEBUG(LOG_INFO, ("fsm_rcoderej(%s): state=%d (%s)\n", + PROTO_NAME(f), f->state, ppperr_strerr[f->state])); + + if (len < HEADERLEN) { + FSMDEBUG(LOG_INFO, ("fsm_rcoderej: Rcvd short Code-Reject packet!\n")); + return; + } + GETCHAR(code, inp); + GETCHAR(id, inp); + FSMDEBUG(LOG_WARNING, ("%s: Rcvd Code-Reject for code %d, id %d\n", + PROTO_NAME(f), code, id)); + + if( f->state == LS_ACKRCVD ) { + f->state = LS_REQSENT; + } +} + + +/* + * fsm_protreject - Peer doesn't speak this protocol. + * + * Treat this as a catastrophic error (RXJ-). + */ +void +fsm_protreject(fsm *f) +{ + switch( f->state ) { + case LS_CLOSING: + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + /* fall through */ + case LS_CLOSED: + f->state = LS_CLOSED; + if( f->callbacks->finished ) { + (*f->callbacks->finished)(f); + } + break; + + case LS_STOPPING: + case LS_REQSENT: + case LS_ACKRCVD: + case LS_ACKSENT: + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + /* fall through */ + case LS_STOPPED: + f->state = LS_STOPPED; + if( f->callbacks->finished ) { + (*f->callbacks->finished)(f); + } + break; + + case LS_OPENED: + if( f->callbacks->down ) { + (*f->callbacks->down)(f); + } + /* Init restart counter, send Terminate-Request */ + f->retransmits = f->maxtermtransmits; + fsm_sdata(f, TERMREQ, f->reqid = ++f->id, + (u_char *) f->term_reason, f->term_reason_len); + TIMEOUT(fsm_timeout, f, f->timeouttime); + --f->retransmits; + + f->state = LS_STOPPING; + break; + + default: + FSMDEBUG(LOG_INFO, ("%s: Protocol-reject event in state %d (%s)!\n", + PROTO_NAME(f), f->state, ppperr_strerr[f->state])); + } +} + + +/* + * fsm_sconfreq - Send a Configure-Request. + */ +static void +fsm_sconfreq(fsm *f, int retransmit) +{ + u_char *outp; + int cilen; + + if( f->state != LS_REQSENT && f->state != LS_ACKRCVD && f->state != LS_ACKSENT ) { + /* Not currently negotiating - reset options */ + if( f->callbacks->resetci ) { + (*f->callbacks->resetci)(f); + } + f->nakloops = 0; + } + + if( !retransmit ) { + /* New request - reset retransmission counter, use new ID */ + f->retransmits = f->maxconfreqtransmits; + f->reqid = ++f->id; + } + + f->seen_ack = 0; + + /* + * Make up the request packet + */ + outp = outpacket_buf[f->unit] + PPP_HDRLEN + HEADERLEN; + if( f->callbacks->cilen && f->callbacks->addci ) { + cilen = (*f->callbacks->cilen)(f); + if( cilen > peer_mru[f->unit] - (int)HEADERLEN ) { + cilen = peer_mru[f->unit] - HEADERLEN; + } + if (f->callbacks->addci) { + (*f->callbacks->addci)(f, outp, &cilen); + } + } else { + cilen = 0; + } + + /* send the request to our peer */ + fsm_sdata(f, CONFREQ, f->reqid, outp, cilen); + + /* start the retransmit timer */ + --f->retransmits; + TIMEOUT(fsm_timeout, f, f->timeouttime); + + FSMDEBUG(LOG_INFO, ("%s: sending Configure-Request, id %d\n", + PROTO_NAME(f), f->reqid)); +} + + +/* + * fsm_sdata - Send some data. + * + * Used for all packets sent to our peer by this module. + */ +void +fsm_sdata( fsm *f, u_char code, u_char id, u_char *data, int datalen) +{ + u_char *outp; + int outlen; + + /* Adjust length to be smaller than MTU */ + outp = outpacket_buf[f->unit]; + if (datalen > peer_mru[f->unit] - (int)HEADERLEN) { + datalen = peer_mru[f->unit] - HEADERLEN; + } + if (datalen && data != outp + PPP_HDRLEN + HEADERLEN) { + BCOPY(data, outp + PPP_HDRLEN + HEADERLEN, datalen); + } + outlen = datalen + HEADERLEN; + MAKEHEADER(outp, f->protocol); + PUTCHAR(code, outp); + PUTCHAR(id, outp); + PUTSHORT(outlen, outp); + pppWrite(f->unit, outpacket_buf[f->unit], outlen + PPP_HDRLEN); + FSMDEBUG(LOG_INFO, ("fsm_sdata(%s): Sent code %d,%d,%d.\n", + PROTO_NAME(f), code, id, outlen)); +} + +#endif /* PPP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/fsm.h b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/fsm.h new file mode 100644 index 0000000..8d41b5f --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/fsm.h @@ -0,0 +1,157 @@ +/***************************************************************************** +* fsm.h - Network Control Protocol Finite State Machine header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* Copyright (c) 1997 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-11-05 Guy Lancaster , Global Election Systems Inc. +* Original based on BSD code. +*****************************************************************************/ +/* + * fsm.h - {Link, IP} Control Protocol Finite State Machine definitions. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * $Id: fsm.h,v 1.5 2009/12/31 17:08:08 goldsimon Exp $ + */ + +#ifndef FSM_H +#define FSM_H + +/* + * LCP Packet header = Code, id, length. + */ +#define HEADERLEN (sizeof (u_char) + sizeof (u_char) + sizeof (u_short)) + + +/* + * CP (LCP, IPCP, etc.) codes. + */ +#define CONFREQ 1 /* Configuration Request */ +#define CONFACK 2 /* Configuration Ack */ +#define CONFNAK 3 /* Configuration Nak */ +#define CONFREJ 4 /* Configuration Reject */ +#define TERMREQ 5 /* Termination Request */ +#define TERMACK 6 /* Termination Ack */ +#define CODEREJ 7 /* Code Reject */ + + +/* + * Each FSM is described by an fsm structure and fsm callbacks. + */ +typedef struct fsm { + int unit; /* Interface unit number */ + u_short protocol; /* Data Link Layer Protocol field value */ + int state; /* State */ + int flags; /* Contains option bits */ + u_char id; /* Current id */ + u_char reqid; /* Current request id */ + u_char seen_ack; /* Have received valid Ack/Nak/Rej to Req */ + int timeouttime; /* Timeout time in milliseconds */ + int maxconfreqtransmits; /* Maximum Configure-Request transmissions */ + int retransmits; /* Number of retransmissions left */ + int maxtermtransmits; /* Maximum Terminate-Request transmissions */ + int nakloops; /* Number of nak loops since last ack */ + int maxnakloops; /* Maximum number of nak loops tolerated */ + struct fsm_callbacks* callbacks; /* Callback routines */ + char* term_reason; /* Reason for closing protocol */ + int term_reason_len; /* Length of term_reason */ +} fsm; + + +typedef struct fsm_callbacks { + void (*resetci)(fsm*); /* Reset our Configuration Information */ + int (*cilen)(fsm*); /* Length of our Configuration Information */ + void (*addci)(fsm*, u_char*, int*); /* Add our Configuration Information */ + int (*ackci)(fsm*, u_char*, int); /* ACK our Configuration Information */ + int (*nakci)(fsm*, u_char*, int); /* NAK our Configuration Information */ + int (*rejci)(fsm*, u_char*, int); /* Reject our Configuration Information */ + int (*reqci)(fsm*, u_char*, int*, int); /* Request peer's Configuration Information */ + void (*up)(fsm*); /* Called when fsm reaches LS_OPENED state */ + void (*down)(fsm*); /* Called when fsm leaves LS_OPENED state */ + void (*starting)(fsm*); /* Called when we want the lower layer */ + void (*finished)(fsm*); /* Called when we don't want the lower layer */ + void (*protreject)(int); /* Called when Protocol-Reject received */ + void (*retransmit)(fsm*); /* Retransmission is necessary */ + int (*extcode)(fsm*, int, u_char, u_char*, int); /* Called when unknown code received */ + char *proto_name; /* String name for protocol (for messages) */ +} fsm_callbacks; + + +/* + * Link states. + */ +#define LS_INITIAL 0 /* Down, hasn't been opened */ +#define LS_STARTING 1 /* Down, been opened */ +#define LS_CLOSED 2 /* Up, hasn't been opened */ +#define LS_STOPPED 3 /* Open, waiting for down event */ +#define LS_CLOSING 4 /* Terminating the connection, not open */ +#define LS_STOPPING 5 /* Terminating, but open */ +#define LS_REQSENT 6 /* We've sent a Config Request */ +#define LS_ACKRCVD 7 /* We've received a Config Ack */ +#define LS_ACKSENT 8 /* We've sent a Config Ack */ +#define LS_OPENED 9 /* Connection available */ + +/* + * Flags - indicate options controlling FSM operation + */ +#define OPT_PASSIVE 1 /* Don't die if we don't get a response */ +#define OPT_RESTART 2 /* Treat 2nd OPEN as DOWN, UP */ +#define OPT_SILENT 4 /* Wait for peer to speak first */ + + +/* + * Prototypes + */ +void fsm_init (fsm*); +void fsm_lowerup (fsm*); +void fsm_lowerdown (fsm*); +void fsm_open (fsm*); +void fsm_close (fsm*, char*); +void fsm_input (fsm*, u_char*, int); +void fsm_protreject (fsm*); +void fsm_sdata (fsm*, u_char, u_char, u_char*, int); + + +/* + * Variables + */ +extern int peer_mru[]; /* currently negotiated peer MRU (per unit) */ + +#endif /* FSM_H */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/ipcp.c b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/ipcp.c new file mode 100644 index 0000000..f0ab2e0 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/ipcp.c @@ -0,0 +1,1411 @@ +/** In contrast to pppd 2.3.1, DNS support has been added, proxy-ARP and + dial-on-demand has been stripped. */ +/***************************************************************************** +* ipcp.c - Network PPP IP Control Protocol program file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 by Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-12-08 Guy Lancaster , Global Election Systems Inc. +* Original. +*****************************************************************************/ +/* + * ipcp.c - PPP IP Control Protocol. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "lwip/opt.h" + +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "ppp_impl.h" +#include "pppdebug.h" + +#include "auth.h" +#include "fsm.h" +#include "vj.h" +#include "ipcp.h" + +#include "lwip/inet.h" + +#include + +/* #define OLD_CI_ADDRS 1 */ /* Support deprecated address negotiation. */ + +/* global vars */ +ipcp_options ipcp_wantoptions[NUM_PPP]; /* Options that we want to request */ +ipcp_options ipcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */ +ipcp_options ipcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */ +ipcp_options ipcp_hisoptions[NUM_PPP]; /* Options that we ack'd */ + +/* local vars */ +static int default_route_set[NUM_PPP]; /* Have set up a default route */ +static int cis_received[NUM_PPP]; /* # Conf-Reqs received */ + + +/* + * Callbacks for fsm code. (CI = Configuration Information) + */ +static void ipcp_resetci (fsm *); /* Reset our CI */ +static int ipcp_cilen (fsm *); /* Return length of our CI */ +static void ipcp_addci (fsm *, u_char *, int *); /* Add our CI */ +static int ipcp_ackci (fsm *, u_char *, int); /* Peer ack'd our CI */ +static int ipcp_nakci (fsm *, u_char *, int); /* Peer nak'd our CI */ +static int ipcp_rejci (fsm *, u_char *, int); /* Peer rej'd our CI */ +static int ipcp_reqci (fsm *, u_char *, int *, int); /* Rcv CI */ +static void ipcp_up (fsm *); /* We're UP */ +static void ipcp_down (fsm *); /* We're DOWN */ +#if PPP_ADDITIONAL_CALLBACKS +static void ipcp_script (fsm *, char *); /* Run an up/down script */ +#endif +static void ipcp_finished (fsm *); /* Don't need lower layer */ + + +fsm ipcp_fsm[NUM_PPP]; /* IPCP fsm structure */ + + +static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */ + ipcp_resetci, /* Reset our Configuration Information */ + ipcp_cilen, /* Length of our Configuration Information */ + ipcp_addci, /* Add our Configuration Information */ + ipcp_ackci, /* ACK our Configuration Information */ + ipcp_nakci, /* NAK our Configuration Information */ + ipcp_rejci, /* Reject our Configuration Information */ + ipcp_reqci, /* Request peer's Configuration Information */ + ipcp_up, /* Called when fsm reaches LS_OPENED state */ + ipcp_down, /* Called when fsm leaves LS_OPENED state */ + NULL, /* Called when we want the lower layer up */ + ipcp_finished, /* Called when we want the lower layer down */ + NULL, /* Called when Protocol-Reject received */ + NULL, /* Retransmission is necessary */ + NULL, /* Called to handle protocol-specific codes */ + "IPCP" /* String name of protocol */ +}; + +/* + * Protocol entry points from main code. + */ +static void ipcp_init (int); +static void ipcp_open (int); +static void ipcp_close (int, char *); +static void ipcp_lowerup (int); +static void ipcp_lowerdown (int); +static void ipcp_input (int, u_char *, int); +static void ipcp_protrej (int); + + +struct protent ipcp_protent = { + PPP_IPCP, + ipcp_init, + ipcp_input, + ipcp_protrej, + ipcp_lowerup, + ipcp_lowerdown, + ipcp_open, + ipcp_close, +#if PPP_ADDITIONAL_CALLBACKS + ipcp_printpkt, + NULL, +#endif /* PPP_ADDITIONAL_CALLBACKS */ + 1, + "IPCP", +#if PPP_ADDITIONAL_CALLBACKS + ip_check_options, + NULL, + ip_active_pkt +#endif /* PPP_ADDITIONAL_CALLBACKS */ +}; + +static void ipcp_clear_addrs (int); + +/* + * Lengths of configuration options. + */ +#define CILEN_VOID 2 +#define CILEN_COMPRESS 4 /* min length for compression protocol opt. */ +#define CILEN_VJ 6 /* length for RFC1332 Van-Jacobson opt. */ +#define CILEN_ADDR 6 /* new-style single address option */ +#define CILEN_ADDRS 10 /* old-style dual address option */ + + +#define CODENAME(x) ((x) == CONFACK ? "ACK" : \ + (x) == CONFNAK ? "NAK" : "REJ") + + +/* + * ipcp_init - Initialize IPCP. + */ +static void +ipcp_init(int unit) +{ + fsm *f = &ipcp_fsm[unit]; + ipcp_options *wo = &ipcp_wantoptions[unit]; + ipcp_options *ao = &ipcp_allowoptions[unit]; + + f->unit = unit; + f->protocol = PPP_IPCP; + f->callbacks = &ipcp_callbacks; + fsm_init(&ipcp_fsm[unit]); + + memset(wo, 0, sizeof(*wo)); + memset(ao, 0, sizeof(*ao)); + + wo->neg_addr = 1; + wo->ouraddr = 0; +#if VJ_SUPPORT + wo->neg_vj = 1; +#else /* VJ_SUPPORT */ + wo->neg_vj = 0; +#endif /* VJ_SUPPORT */ + wo->vj_protocol = IPCP_VJ_COMP; + wo->maxslotindex = MAX_SLOTS - 1; + wo->cflag = 0; + wo->default_route = 1; + + ao->neg_addr = 1; +#if VJ_SUPPORT + ao->neg_vj = 1; +#else /* VJ_SUPPORT */ + ao->neg_vj = 0; +#endif /* VJ_SUPPORT */ + ao->maxslotindex = MAX_SLOTS - 1; + ao->cflag = 1; + ao->default_route = 1; +} + + +/* + * ipcp_open - IPCP is allowed to come up. + */ +static void +ipcp_open(int unit) +{ + fsm_open(&ipcp_fsm[unit]); +} + + +/* + * ipcp_close - Take IPCP down. + */ +static void +ipcp_close(int unit, char *reason) +{ + fsm_close(&ipcp_fsm[unit], reason); +} + + +/* + * ipcp_lowerup - The lower layer is up. + */ +static void +ipcp_lowerup(int unit) +{ + fsm_lowerup(&ipcp_fsm[unit]); +} + + +/* + * ipcp_lowerdown - The lower layer is down. + */ +static void +ipcp_lowerdown(int unit) +{ + fsm_lowerdown(&ipcp_fsm[unit]); +} + + +/* + * ipcp_input - Input IPCP packet. + */ +static void +ipcp_input(int unit, u_char *p, int len) +{ + fsm_input(&ipcp_fsm[unit], p, len); +} + + +/* + * ipcp_protrej - A Protocol-Reject was received for IPCP. + * + * Pretend the lower layer went down, so we shut up. + */ +static void +ipcp_protrej(int unit) +{ + fsm_lowerdown(&ipcp_fsm[unit]); +} + + +/* + * ipcp_resetci - Reset our CI. + */ +static void +ipcp_resetci(fsm *f) +{ + ipcp_options *wo = &ipcp_wantoptions[f->unit]; + + wo->req_addr = wo->neg_addr && ipcp_allowoptions[f->unit].neg_addr; + if (wo->ouraddr == 0) { + wo->accept_local = 1; + } + if (wo->hisaddr == 0) { + wo->accept_remote = 1; + } + /* Request DNS addresses from the peer */ + wo->req_dns1 = ppp_settings.usepeerdns; + wo->req_dns2 = ppp_settings.usepeerdns; + ipcp_gotoptions[f->unit] = *wo; + cis_received[f->unit] = 0; +} + + +/* + * ipcp_cilen - Return length of our CI. + */ +static int +ipcp_cilen(fsm *f) +{ + ipcp_options *go = &ipcp_gotoptions[f->unit]; + ipcp_options *wo = &ipcp_wantoptions[f->unit]; + ipcp_options *ho = &ipcp_hisoptions[f->unit]; + +#define LENCIVJ(neg, old) (neg ? (old? CILEN_COMPRESS : CILEN_VJ) : 0) +#define LENCIADDR(neg, old) (neg ? (old? CILEN_ADDRS : CILEN_ADDR) : 0) +#define LENCIDNS(neg) (neg ? (CILEN_ADDR) : 0) + + /* + * First see if we want to change our options to the old + * forms because we have received old forms from the peer. + */ + if (wo->neg_addr && !go->neg_addr && !go->old_addrs) { + /* use the old style of address negotiation */ + go->neg_addr = 1; + go->old_addrs = 1; + } + if (wo->neg_vj && !go->neg_vj && !go->old_vj) { + /* try an older style of VJ negotiation */ + if (cis_received[f->unit] == 0) { + /* keep trying the new style until we see some CI from the peer */ + go->neg_vj = 1; + } else { + /* use the old style only if the peer did */ + if (ho->neg_vj && ho->old_vj) { + go->neg_vj = 1; + go->old_vj = 1; + go->vj_protocol = ho->vj_protocol; + } + } + } + + return (LENCIADDR(go->neg_addr, go->old_addrs) + + LENCIVJ(go->neg_vj, go->old_vj) + + LENCIDNS(go->req_dns1) + + LENCIDNS(go->req_dns2)); +} + + +/* + * ipcp_addci - Add our desired CIs to a packet. + */ +static void +ipcp_addci(fsm *f, u_char *ucp, int *lenp) +{ + ipcp_options *go = &ipcp_gotoptions[f->unit]; + int len = *lenp; + +#define ADDCIVJ(opt, neg, val, old, maxslotindex, cflag) \ + if (neg) { \ + int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \ + if (len >= vjlen) { \ + PUTCHAR(opt, ucp); \ + PUTCHAR(vjlen, ucp); \ + PUTSHORT(val, ucp); \ + if (!old) { \ + PUTCHAR(maxslotindex, ucp); \ + PUTCHAR(cflag, ucp); \ + } \ + len -= vjlen; \ + } else { \ + neg = 0; \ + } \ + } + +#define ADDCIADDR(opt, neg, old, val1, val2) \ + if (neg) { \ + int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \ + if (len >= addrlen) { \ + u32_t l; \ + PUTCHAR(opt, ucp); \ + PUTCHAR(addrlen, ucp); \ + l = ntohl(val1); \ + PUTLONG(l, ucp); \ + if (old) { \ + l = ntohl(val2); \ + PUTLONG(l, ucp); \ + } \ + len -= addrlen; \ + } else { \ + neg = 0; \ + } \ + } + +#define ADDCIDNS(opt, neg, addr) \ + if (neg) { \ + if (len >= CILEN_ADDR) { \ + u32_t l; \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_ADDR, ucp); \ + l = ntohl(addr); \ + PUTLONG(l, ucp); \ + len -= CILEN_ADDR; \ + } else { \ + neg = 0; \ + } \ + } + + ADDCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr, + go->old_addrs, go->ouraddr, go->hisaddr); + + ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj, + go->maxslotindex, go->cflag); + + ADDCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]); + + ADDCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]); + + *lenp -= len; +} + + +/* + * ipcp_ackci - Ack our CIs. + * + * Returns: + * 0 - Ack was bad. + * 1 - Ack was good. + */ +static int +ipcp_ackci(fsm *f, u_char *p, int len) +{ + ipcp_options *go = &ipcp_gotoptions[f->unit]; + u_short cilen, citype, cishort; + u32_t cilong; + u_char cimaxslotindex, cicflag; + + /* + * CIs must be in exactly the same order that we sent... + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ + +#define ACKCIVJ(opt, neg, val, old, maxslotindex, cflag) \ + if (neg) { \ + int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \ + if ((len -= vjlen) < 0) { \ + goto bad; \ + } \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != vjlen || \ + citype != opt) { \ + goto bad; \ + } \ + GETSHORT(cishort, p); \ + if (cishort != val) { \ + goto bad; \ + } \ + if (!old) { \ + GETCHAR(cimaxslotindex, p); \ + if (cimaxslotindex != maxslotindex) { \ + goto bad; \ + } \ + GETCHAR(cicflag, p); \ + if (cicflag != cflag) { \ + goto bad; \ + } \ + } \ + } + +#define ACKCIADDR(opt, neg, old, val1, val2) \ + if (neg) { \ + int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \ + u32_t l; \ + if ((len -= addrlen) < 0) { \ + goto bad; \ + } \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != addrlen || \ + citype != opt) { \ + goto bad; \ + } \ + GETLONG(l, p); \ + cilong = htonl(l); \ + if (val1 != cilong) { \ + goto bad; \ + } \ + if (old) { \ + GETLONG(l, p); \ + cilong = htonl(l); \ + if (val2 != cilong) { \ + goto bad; \ + } \ + } \ + } + +#define ACKCIDNS(opt, neg, addr) \ + if (neg) { \ + u32_t l; \ + if ((len -= CILEN_ADDR) < 0) { \ + goto bad; \ + } \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_ADDR || \ + citype != opt) { \ + goto bad; \ + } \ + GETLONG(l, p); \ + cilong = htonl(l); \ + if (addr != cilong) { \ + goto bad; \ + } \ + } + + ACKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr, + go->old_addrs, go->ouraddr, go->hisaddr); + + ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj, + go->maxslotindex, go->cflag); + + ACKCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]); + + ACKCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]); + + /* + * If there are any remaining CIs, then this packet is bad. + */ + if (len != 0) { + goto bad; + } + return (1); + +bad: + IPCPDEBUG(LOG_INFO, ("ipcp_ackci: received bad Ack!\n")); + return (0); +} + +/* + * ipcp_nakci - Peer has sent a NAK for some of our CIs. + * This should not modify any state if the Nak is bad + * or if IPCP is in the LS_OPENED state. + * + * Returns: + * 0 - Nak was bad. + * 1 - Nak was good. + */ +static int +ipcp_nakci(fsm *f, u_char *p, int len) +{ + ipcp_options *go = &ipcp_gotoptions[f->unit]; + u_char cimaxslotindex, cicflag; + u_char citype, cilen, *next; + u_short cishort; + u32_t ciaddr1, ciaddr2, l, cidnsaddr; + ipcp_options no; /* options we've seen Naks for */ + ipcp_options try; /* options to request next time */ + + BZERO(&no, sizeof(no)); + try = *go; + + /* + * Any Nak'd CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define NAKCIADDR(opt, neg, old, code) \ + if (go->neg && \ + len >= (cilen = (old? CILEN_ADDRS: CILEN_ADDR)) && \ + p[1] == cilen && \ + p[0] == opt) { \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + ciaddr1 = htonl(l); \ + if (old) { \ + GETLONG(l, p); \ + ciaddr2 = htonl(l); \ + no.old_addrs = 1; \ + } else { \ + ciaddr2 = 0; \ + } \ + no.neg = 1; \ + code \ + } + +#define NAKCIVJ(opt, neg, code) \ + if (go->neg && \ + ((cilen = p[1]) == CILEN_COMPRESS || cilen == CILEN_VJ) && \ + len >= cilen && \ + p[0] == opt) { \ + len -= cilen; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + no.neg = 1; \ + code \ + } + +#define NAKCIDNS(opt, neg, code) \ + if (go->neg && \ + ((cilen = p[1]) == CILEN_ADDR) && \ + len >= cilen && \ + p[0] == opt) { \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + cidnsaddr = htonl(l); \ + no.neg = 1; \ + code \ + } + + /* + * Accept the peer's idea of {our,his} address, if different + * from our idea, only if the accept_{local,remote} flag is set. + */ + NAKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr, go->old_addrs, + if (go->accept_local && ciaddr1) { /* Do we know our address? */ + try.ouraddr = ciaddr1; + IPCPDEBUG(LOG_INFO, ("local IP address %s\n", + inet_ntoa(ciaddr1))); + } + if (go->accept_remote && ciaddr2) { /* Does he know his? */ + try.hisaddr = ciaddr2; + IPCPDEBUG(LOG_INFO, ("remote IP address %s\n", + inet_ntoa(ciaddr2))); + } + ); + + /* + * Accept the peer's value of maxslotindex provided that it + * is less than what we asked for. Turn off slot-ID compression + * if the peer wants. Send old-style compress-type option if + * the peer wants. + */ + NAKCIVJ(CI_COMPRESSTYPE, neg_vj, + if (cilen == CILEN_VJ) { + GETCHAR(cimaxslotindex, p); + GETCHAR(cicflag, p); + if (cishort == IPCP_VJ_COMP) { + try.old_vj = 0; + if (cimaxslotindex < go->maxslotindex) { + try.maxslotindex = cimaxslotindex; + } + if (!cicflag) { + try.cflag = 0; + } + } else { + try.neg_vj = 0; + } + } else { + if (cishort == IPCP_VJ_COMP || cishort == IPCP_VJ_COMP_OLD) { + try.old_vj = 1; + try.vj_protocol = cishort; + } else { + try.neg_vj = 0; + } + } + ); + + NAKCIDNS(CI_MS_DNS1, req_dns1, + try.dnsaddr[0] = cidnsaddr; + IPCPDEBUG(LOG_INFO, ("primary DNS address %s\n", inet_ntoa(cidnsaddr))); + ); + + NAKCIDNS(CI_MS_DNS2, req_dns2, + try.dnsaddr[1] = cidnsaddr; + IPCPDEBUG(LOG_INFO, ("secondary DNS address %s\n", inet_ntoa(cidnsaddr))); + ); + + /* + * There may be remaining CIs, if the peer is requesting negotiation + * on an option that we didn't include in our request packet. + * If they want to negotiate about IP addresses, we comply. + * If they want us to ask for compression, we refuse. + */ + while (len > CILEN_VOID) { + GETCHAR(citype, p); + GETCHAR(cilen, p); + if( (len -= cilen) < 0 ) { + goto bad; + } + next = p + cilen - 2; + + switch (citype) { + case CI_COMPRESSTYPE: + if (go->neg_vj || no.neg_vj || + (cilen != CILEN_VJ && cilen != CILEN_COMPRESS)) { + goto bad; + } + no.neg_vj = 1; + break; + case CI_ADDRS: + if ((go->neg_addr && go->old_addrs) || no.old_addrs + || cilen != CILEN_ADDRS) { + goto bad; + } + try.neg_addr = 1; + try.old_addrs = 1; + GETLONG(l, p); + ciaddr1 = htonl(l); + if (ciaddr1 && go->accept_local) { + try.ouraddr = ciaddr1; + } + GETLONG(l, p); + ciaddr2 = htonl(l); + if (ciaddr2 && go->accept_remote) { + try.hisaddr = ciaddr2; + } + no.old_addrs = 1; + break; + case CI_ADDR: + if (go->neg_addr || no.neg_addr || cilen != CILEN_ADDR) { + goto bad; + } + try.old_addrs = 0; + GETLONG(l, p); + ciaddr1 = htonl(l); + if (ciaddr1 && go->accept_local) { + try.ouraddr = ciaddr1; + } + if (try.ouraddr != 0) { + try.neg_addr = 1; + } + no.neg_addr = 1; + break; + } + p = next; + } + + /* If there is still anything left, this packet is bad. */ + if (len != 0) { + goto bad; + } + + /* + * OK, the Nak is good. Now we can update state. + */ + if (f->state != LS_OPENED) { + *go = try; + } + + return 1; + +bad: + IPCPDEBUG(LOG_INFO, ("ipcp_nakci: received bad Nak!\n")); + return 0; +} + + +/* + * ipcp_rejci - Reject some of our CIs. + */ +static int +ipcp_rejci(fsm *f, u_char *p, int len) +{ + ipcp_options *go = &ipcp_gotoptions[f->unit]; + u_char cimaxslotindex, ciflag, cilen; + u_short cishort; + u32_t cilong; + ipcp_options try; /* options to request next time */ + + try = *go; + /* + * Any Rejected CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define REJCIADDR(opt, neg, old, val1, val2) \ + if (go->neg && \ + len >= (cilen = old? CILEN_ADDRS: CILEN_ADDR) && \ + p[1] == cilen && \ + p[0] == opt) { \ + u32_t l; \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + cilong = htonl(l); \ + /* Check rejected value. */ \ + if (cilong != val1) { \ + goto bad; \ + } \ + if (old) { \ + GETLONG(l, p); \ + cilong = htonl(l); \ + /* Check rejected value. */ \ + if (cilong != val2) { \ + goto bad; \ + } \ + } \ + try.neg = 0; \ + } + +#define REJCIVJ(opt, neg, val, old, maxslot, cflag) \ + if (go->neg && \ + p[1] == (old? CILEN_COMPRESS : CILEN_VJ) && \ + len >= p[1] && \ + p[0] == opt) { \ + len -= p[1]; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + /* Check rejected value. */ \ + if (cishort != val) { \ + goto bad; \ + } \ + if (!old) { \ + GETCHAR(cimaxslotindex, p); \ + if (cimaxslotindex != maxslot) { \ + goto bad; \ + } \ + GETCHAR(ciflag, p); \ + if (ciflag != cflag) { \ + goto bad; \ + } \ + } \ + try.neg = 0; \ + } + +#define REJCIDNS(opt, neg, dnsaddr) \ + if (go->neg && \ + ((cilen = p[1]) == CILEN_ADDR) && \ + len >= cilen && \ + p[0] == opt) { \ + u32_t l; \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + cilong = htonl(l); \ + /* Check rejected value. */ \ + if (cilong != dnsaddr) { \ + goto bad; \ + } \ + try.neg = 0; \ + } + + REJCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr, + go->old_addrs, go->ouraddr, go->hisaddr); + + REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol, go->old_vj, + go->maxslotindex, go->cflag); + + REJCIDNS(CI_MS_DNS1, req_dns1, go->dnsaddr[0]); + + REJCIDNS(CI_MS_DNS2, req_dns2, go->dnsaddr[1]); + + /* + * If there are any remaining CIs, then this packet is bad. + */ + if (len != 0) { + goto bad; + } + /* + * Now we can update state. + */ + if (f->state != LS_OPENED) { + *go = try; + } + return 1; + +bad: + IPCPDEBUG(LOG_INFO, ("ipcp_rejci: received bad Reject!\n")); + return 0; +} + + +/* + * ipcp_reqci - Check the peer's requested CIs and send appropriate response. + * + * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified + * appropriately. If reject_if_disagree is non-zero, doesn't return + * CONFNAK; returns CONFREJ if it can't return CONFACK. + */ +static int +ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested CIs */,int reject_if_disagree) +{ + ipcp_options *wo = &ipcp_wantoptions[f->unit]; + ipcp_options *ho = &ipcp_hisoptions[f->unit]; + ipcp_options *ao = &ipcp_allowoptions[f->unit]; +#ifdef OLD_CI_ADDRS + ipcp_options *go = &ipcp_gotoptions[f->unit]; +#endif + u_char *cip, *next; /* Pointer to current and next CIs */ + u_short cilen, citype; /* Parsed len, type */ + u_short cishort; /* Parsed short value */ + u32_t tl, ciaddr1; /* Parsed address values */ +#ifdef OLD_CI_ADDRS + u32_t ciaddr2; /* Parsed address values */ +#endif + int rc = CONFACK; /* Final packet return code */ + int orc; /* Individual option return code */ + u_char *p; /* Pointer to next char to parse */ + u_char *ucp = inp; /* Pointer to current output char */ + int l = *len; /* Length left */ + u_char maxslotindex, cflag; + int d; + + cis_received[f->unit] = 1; + + /* + * Reset all his options. + */ + BZERO(ho, sizeof(*ho)); + + /* + * Process all his options. + */ + next = inp; + while (l) { + orc = CONFACK; /* Assume success */ + cip = p = next; /* Remember begining of CI */ + if (l < 2 || /* Not enough data for CI header or */ + p[1] < 2 || /* CI length too small or */ + p[1] > l) { /* CI length too big? */ + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: bad CI length!\n")); + orc = CONFREJ; /* Reject bad CI */ + cilen = (u_short)l;/* Reject till end of packet */ + l = 0; /* Don't loop again */ + goto endswitch; + } + GETCHAR(citype, p); /* Parse CI type */ + GETCHAR(cilen, p); /* Parse CI length */ + l -= cilen; /* Adjust remaining length */ + next += cilen; /* Step to next CI */ + + switch (citype) { /* Check CI type */ +#ifdef OLD_CI_ADDRS /* Need to save space... */ + case CI_ADDRS: + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: received ADDRS\n")); + if (!ao->neg_addr || + cilen != CILEN_ADDRS) { /* Check CI length */ + orc = CONFREJ; /* Reject CI */ + break; + } + + /* + * If he has no address, or if we both have his address but + * disagree about it, then NAK it with our idea. + * In particular, if we don't know his address, but he does, + * then accept it. + */ + GETLONG(tl, p); /* Parse source address (his) */ + ciaddr1 = htonl(tl); + IPCPDEBUG(LOG_INFO, ("his addr %s\n", inet_ntoa(ciaddr1))); + if (ciaddr1 != wo->hisaddr + && (ciaddr1 == 0 || !wo->accept_remote)) { + orc = CONFNAK; + if (!reject_if_disagree) { + DECPTR(sizeof(u32_t), p); + tl = ntohl(wo->hisaddr); + PUTLONG(tl, p); + } + } else if (ciaddr1 == 0 && wo->hisaddr == 0) { + /* + * If neither we nor he knows his address, reject the option. + */ + orc = CONFREJ; + wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */ + break; + } + + /* + * If he doesn't know our address, or if we both have our address + * but disagree about it, then NAK it with our idea. + */ + GETLONG(tl, p); /* Parse desination address (ours) */ + ciaddr2 = htonl(tl); + IPCPDEBUG(LOG_INFO, ("our addr %s\n", inet_ntoa(ciaddr2))); + if (ciaddr2 != wo->ouraddr) { + if (ciaddr2 == 0 || !wo->accept_local) { + orc = CONFNAK; + if (!reject_if_disagree) { + DECPTR(sizeof(u32_t), p); + tl = ntohl(wo->ouraddr); + PUTLONG(tl, p); + } + } else { + go->ouraddr = ciaddr2; /* accept peer's idea */ + } + } + + ho->neg_addr = 1; + ho->old_addrs = 1; + ho->hisaddr = ciaddr1; + ho->ouraddr = ciaddr2; + break; +#endif + + case CI_ADDR: + if (!ao->neg_addr) { + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Reject ADDR not allowed\n")); + orc = CONFREJ; /* Reject CI */ + break; + } else if (cilen != CILEN_ADDR) { /* Check CI length */ + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Reject ADDR bad len\n")); + orc = CONFREJ; /* Reject CI */ + break; + } + + /* + * If he has no address, or if we both have his address but + * disagree about it, then NAK it with our idea. + * In particular, if we don't know his address, but he does, + * then accept it. + */ + GETLONG(tl, p); /* Parse source address (his) */ + ciaddr1 = htonl(tl); + if (ciaddr1 != wo->hisaddr + && (ciaddr1 == 0 || !wo->accept_remote)) { + orc = CONFNAK; + if (!reject_if_disagree) { + DECPTR(sizeof(u32_t), p); + tl = ntohl(wo->hisaddr); + PUTLONG(tl, p); + } + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Nak ADDR %s\n", inet_ntoa(ciaddr1))); + } else if (ciaddr1 == 0 && wo->hisaddr == 0) { + /* + * Don't ACK an address of 0.0.0.0 - reject it instead. + */ + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Reject ADDR %s\n", inet_ntoa(ciaddr1))); + orc = CONFREJ; + wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */ + break; + } + + ho->neg_addr = 1; + ho->hisaddr = ciaddr1; + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: ADDR %s\n", inet_ntoa(ciaddr1))); + break; + + case CI_MS_DNS1: + case CI_MS_DNS2: + /* Microsoft primary or secondary DNS request */ + d = citype == CI_MS_DNS2; + + /* If we do not have a DNS address then we cannot send it */ + if (ao->dnsaddr[d] == 0 || + cilen != CILEN_ADDR) { /* Check CI length */ + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting DNS%d Request\n", d+1)); + orc = CONFREJ; /* Reject CI */ + break; + } + GETLONG(tl, p); + if (htonl(tl) != ao->dnsaddr[d]) { + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Naking DNS%d Request %s\n", + d+1, inet_ntoa(tl))); + DECPTR(sizeof(u32_t), p); + tl = ntohl(ao->dnsaddr[d]); + PUTLONG(tl, p); + orc = CONFNAK; + } + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: received DNS%d Request\n", d+1)); + break; + + case CI_MS_WINS1: + case CI_MS_WINS2: + /* Microsoft primary or secondary WINS request */ + d = citype == CI_MS_WINS2; + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: received WINS%d Request\n", d+1)); + + /* If we do not have a DNS address then we cannot send it */ + if (ao->winsaddr[d] == 0 || + cilen != CILEN_ADDR) { /* Check CI length */ + orc = CONFREJ; /* Reject CI */ + break; + } + GETLONG(tl, p); + if (htonl(tl) != ao->winsaddr[d]) { + DECPTR(sizeof(u32_t), p); + tl = ntohl(ao->winsaddr[d]); + PUTLONG(tl, p); + orc = CONFNAK; + } + break; + + case CI_COMPRESSTYPE: + if (!ao->neg_vj) { + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting COMPRESSTYPE not allowed\n")); + orc = CONFREJ; + break; + } else if (cilen != CILEN_VJ && cilen != CILEN_COMPRESS) { + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting COMPRESSTYPE len=%d\n", cilen)); + orc = CONFREJ; + break; + } + GETSHORT(cishort, p); + + if (!(cishort == IPCP_VJ_COMP || + (cishort == IPCP_VJ_COMP_OLD && cilen == CILEN_COMPRESS))) { + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting COMPRESSTYPE %d\n", cishort)); + orc = CONFREJ; + break; + } + + ho->neg_vj = 1; + ho->vj_protocol = cishort; + if (cilen == CILEN_VJ) { + GETCHAR(maxslotindex, p); + if (maxslotindex > ao->maxslotindex) { + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Naking VJ max slot %d\n", maxslotindex)); + orc = CONFNAK; + if (!reject_if_disagree) { + DECPTR(1, p); + PUTCHAR(ao->maxslotindex, p); + } + } + GETCHAR(cflag, p); + if (cflag && !ao->cflag) { + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Naking VJ cflag %d\n", cflag)); + orc = CONFNAK; + if (!reject_if_disagree) { + DECPTR(1, p); + PUTCHAR(wo->cflag, p); + } + } + ho->maxslotindex = maxslotindex; + ho->cflag = cflag; + } else { + ho->old_vj = 1; + ho->maxslotindex = MAX_SLOTS - 1; + ho->cflag = 1; + } + IPCPDEBUG(LOG_INFO, ( + "ipcp_reqci: received COMPRESSTYPE p=%d old=%d maxslot=%d cflag=%d\n", + ho->vj_protocol, ho->old_vj, ho->maxslotindex, ho->cflag)); + break; + + default: + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting unknown CI type %d\n", citype)); + orc = CONFREJ; + break; + } + +endswitch: + if (orc == CONFACK && /* Good CI */ + rc != CONFACK) { /* but prior CI wasnt? */ + continue; /* Don't send this one */ + } + + if (orc == CONFNAK) { /* Nak this CI? */ + if (reject_if_disagree) { /* Getting fed up with sending NAKs? */ + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting too many naks\n")); + orc = CONFREJ; /* Get tough if so */ + } else { + if (rc == CONFREJ) { /* Rejecting prior CI? */ + continue; /* Don't send this one */ + } + if (rc == CONFACK) { /* Ack'd all prior CIs? */ + rc = CONFNAK; /* Not anymore... */ + ucp = inp; /* Backup */ + } + } + } + + if (orc == CONFREJ && /* Reject this CI */ + rc != CONFREJ) { /* but no prior ones? */ + rc = CONFREJ; + ucp = inp; /* Backup */ + } + + /* Need to move CI? */ + if (ucp != cip) { + BCOPY(cip, ucp, cilen); /* Move it */ + } + + /* Update output pointer */ + INCPTR(cilen, ucp); + } + + /* + * If we aren't rejecting this packet, and we want to negotiate + * their address, and they didn't send their address, then we + * send a NAK with a CI_ADDR option appended. We assume the + * input buffer is long enough that we can append the extra + * option safely. + */ + if (rc != CONFREJ && !ho->neg_addr && + wo->req_addr && !reject_if_disagree) { + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Requesting peer address\n")); + if (rc == CONFACK) { + rc = CONFNAK; + ucp = inp; /* reset pointer */ + wo->req_addr = 0; /* don't ask again */ + } + PUTCHAR(CI_ADDR, ucp); + PUTCHAR(CILEN_ADDR, ucp); + tl = ntohl(wo->hisaddr); + PUTLONG(tl, ucp); + } + + *len = (int)(ucp - inp); /* Compute output length */ + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: returning Configure-%s\n", CODENAME(rc))); + return (rc); /* Return final code */ +} + + +#if 0 +/* + * ip_check_options - check that any IP-related options are OK, + * and assign appropriate defaults. + */ +static void +ip_check_options(u_long localAddr) +{ + ipcp_options *wo = &ipcp_wantoptions[0]; + + /* + * Load our default IP address but allow the remote host to give us + * a new address. + */ + if (wo->ouraddr == 0 && !ppp_settings.disable_defaultip) { + wo->accept_local = 1; /* don't insist on this default value */ + wo->ouraddr = htonl(localAddr); + } +} +#endif + + +/* + * ipcp_up - IPCP has come UP. + * + * Configure the IP network interface appropriately and bring it up. + */ +static void +ipcp_up(fsm *f) +{ + u32_t mask; + ipcp_options *ho = &ipcp_hisoptions[f->unit]; + ipcp_options *go = &ipcp_gotoptions[f->unit]; + ipcp_options *wo = &ipcp_wantoptions[f->unit]; + + np_up(f->unit, PPP_IP); + IPCPDEBUG(LOG_INFO, ("ipcp: up\n")); + + /* + * We must have a non-zero IP address for both ends of the link. + */ + if (!ho->neg_addr) { + ho->hisaddr = wo->hisaddr; + } + + if (ho->hisaddr == 0) { + IPCPDEBUG(LOG_ERR, ("Could not determine remote IP address\n")); + ipcp_close(f->unit, "Could not determine remote IP address"); + return; + } + if (go->ouraddr == 0) { + IPCPDEBUG(LOG_ERR, ("Could not determine local IP address\n")); + ipcp_close(f->unit, "Could not determine local IP address"); + return; + } + + if (ppp_settings.usepeerdns && (go->dnsaddr[0] || go->dnsaddr[1])) { + /*pppGotDNSAddrs(go->dnsaddr[0], go->dnsaddr[1]);*/ + } + + /* + * Check that the peer is allowed to use the IP address it wants. + */ + if (!auth_ip_addr(f->unit, ho->hisaddr)) { + IPCPDEBUG(LOG_ERR, ("Peer is not authorized to use remote address %s\n", + inet_ntoa(ho->hisaddr))); + ipcp_close(f->unit, "Unauthorized remote IP address"); + return; + } + + /* set tcp compression */ + sifvjcomp(f->unit, ho->neg_vj, ho->cflag, ho->maxslotindex); + + /* + * Set IP addresses and (if specified) netmask. + */ + mask = GetMask(go->ouraddr); + + if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask, go->dnsaddr[0], go->dnsaddr[1])) { + IPCPDEBUG(LOG_WARNING, ("sifaddr failed\n")); + ipcp_close(f->unit, "Interface configuration failed"); + return; + } + + /* bring the interface up for IP */ + if (!sifup(f->unit)) { + IPCPDEBUG(LOG_WARNING, ("sifup failed\n")); + ipcp_close(f->unit, "Interface configuration failed"); + return; + } + + sifnpmode(f->unit, PPP_IP, NPMODE_PASS); + + /* assign a default route through the interface if required */ + if (ipcp_wantoptions[f->unit].default_route) { + if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr)) { + default_route_set[f->unit] = 1; + } + } + + IPCPDEBUG(LOG_NOTICE, ("local IP address %s\n", inet_ntoa(go->ouraddr))); + IPCPDEBUG(LOG_NOTICE, ("remote IP address %s\n", inet_ntoa(ho->hisaddr))); + if (go->dnsaddr[0]) { + IPCPDEBUG(LOG_NOTICE, ("primary DNS address %s\n", inet_ntoa(go->dnsaddr[0]))); + } + if (go->dnsaddr[1]) { + IPCPDEBUG(LOG_NOTICE, ("secondary DNS address %s\n", inet_ntoa(go->dnsaddr[1]))); + } +} + + +/* + * ipcp_down - IPCP has gone DOWN. + * + * Take the IP network interface down, clear its addresses + * and delete routes through it. + */ +static void +ipcp_down(fsm *f) +{ + IPCPDEBUG(LOG_INFO, ("ipcp: down\n")); + np_down(f->unit, PPP_IP); + sifvjcomp(f->unit, 0, 0, 0); + + sifdown(f->unit); + ipcp_clear_addrs(f->unit); +} + + +/* + * ipcp_clear_addrs() - clear the interface addresses, routes, etc. + */ +static void +ipcp_clear_addrs(int unit) +{ + u32_t ouraddr, hisaddr; + + ouraddr = ipcp_gotoptions[unit].ouraddr; + hisaddr = ipcp_hisoptions[unit].hisaddr; + if (default_route_set[unit]) { + cifdefaultroute(unit, ouraddr, hisaddr); + default_route_set[unit] = 0; + } + cifaddr(unit, ouraddr, hisaddr); +} + + +/* + * ipcp_finished - possibly shut down the lower layers. + */ +static void +ipcp_finished(fsm *f) +{ + np_finished(f->unit, PPP_IP); +} + +#if PPP_ADDITIONAL_CALLBACKS +static int +ipcp_printpkt(u_char *p, int plen, void (*printer) (void *, char *, ...), void *arg) +{ + LWIP_UNUSED_ARG(p); + LWIP_UNUSED_ARG(plen); + LWIP_UNUSED_ARG(printer); + LWIP_UNUSED_ARG(arg); + return 0; +} + +/* + * ip_active_pkt - see if this IP packet is worth bringing the link up for. + * We don't bring the link up for IP fragments or for TCP FIN packets + * with no data. + */ +#define IP_HDRLEN 20 /* bytes */ +#define IP_OFFMASK 0x1fff +#define IPPROTO_TCP 6 +#define TCP_HDRLEN 20 +#define TH_FIN 0x01 + +/* + * We use these macros because the IP header may be at an odd address, + * and some compilers might use word loads to get th_off or ip_hl. + */ + +#define net_short(x) (((x)[0] << 8) + (x)[1]) +#define get_iphl(x) (((unsigned char *)(x))[0] & 0xF) +#define get_ipoff(x) net_short((unsigned char *)(x) + 6) +#define get_ipproto(x) (((unsigned char *)(x))[9]) +#define get_tcpoff(x) (((unsigned char *)(x))[12] >> 4) +#define get_tcpflags(x) (((unsigned char *)(x))[13]) + +static int +ip_active_pkt(u_char *pkt, int len) +{ + u_char *tcp; + int hlen; + + len -= PPP_HDRLEN; + pkt += PPP_HDRLEN; + if (len < IP_HDRLEN) { + return 0; + } + if ((get_ipoff(pkt) & IP_OFFMASK) != 0) { + return 0; + } + if (get_ipproto(pkt) != IPPROTO_TCP) { + return 1; + } + hlen = get_iphl(pkt) * 4; + if (len < hlen + TCP_HDRLEN) { + return 0; + } + tcp = pkt + hlen; + if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == hlen + get_tcpoff(tcp) * 4) { + return 0; + } + return 1; +} +#endif /* PPP_ADDITIONAL_CALLBACKS */ + +#endif /* PPP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/ipcp.h b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/ipcp.h new file mode 100644 index 0000000..de03f46 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/ipcp.h @@ -0,0 +1,106 @@ +/***************************************************************************** +* ipcp.h - PPP IP NCP: Internet Protocol Network Control Protocol header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-12-04 Guy Lancaster , Global Election Systems Inc. +* Original derived from BSD codes. +*****************************************************************************/ +/* + * ipcp.h - IP Control Protocol definitions. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * $Id: ipcp.h,v 1.4 2010/01/18 20:49:43 goldsimon Exp $ + */ + +#ifndef IPCP_H +#define IPCP_H + +/* + * Options. + */ +#define CI_ADDRS 1 /* IP Addresses */ +#define CI_COMPRESSTYPE 2 /* Compression Type */ +#define CI_ADDR 3 + +#define CI_MS_DNS1 129 /* Primary DNS value */ +#define CI_MS_WINS1 128 /* Primary WINS value */ +#define CI_MS_DNS2 131 /* Secondary DNS value */ +#define CI_MS_WINS2 130 /* Secondary WINS value */ + +#define IPCP_VJMODE_OLD 1 /* "old" mode (option # = 0x0037) */ +#define IPCP_VJMODE_RFC1172 2 /* "old-rfc"mode (option # = 0x002d) */ +#define IPCP_VJMODE_RFC1332 3 /* "new-rfc"mode (option # = 0x002d, */ + /* maxslot and slot number compression) */ + +#define IPCP_VJ_COMP 0x002d /* current value for VJ compression option */ +#define IPCP_VJ_COMP_OLD 0x0037 /* "old" (i.e, broken) value for VJ */ + /* compression option */ + +typedef struct ipcp_options { + u_int neg_addr : 1; /* Negotiate IP Address? */ + u_int old_addrs : 1; /* Use old (IP-Addresses) option? */ + u_int req_addr : 1; /* Ask peer to send IP address? */ + u_int default_route : 1; /* Assign default route through interface? */ + u_int proxy_arp : 1; /* Make proxy ARP entry for peer? */ + u_int neg_vj : 1; /* Van Jacobson Compression? */ + u_int old_vj : 1; /* use old (short) form of VJ option? */ + u_int accept_local : 1; /* accept peer's value for ouraddr */ + u_int accept_remote : 1; /* accept peer's value for hisaddr */ + u_int req_dns1 : 1; /* Ask peer to send primary DNS address? */ + u_int req_dns2 : 1; /* Ask peer to send secondary DNS address? */ + u_short vj_protocol; /* protocol value to use in VJ option */ + u_char maxslotindex; /* VJ slots - 1. */ + u_char cflag; /* VJ slot compression flag. */ + u32_t ouraddr, hisaddr; /* Addresses in NETWORK BYTE ORDER */ + u32_t dnsaddr[2]; /* Primary and secondary MS DNS entries */ + u32_t winsaddr[2]; /* Primary and secondary MS WINS entries */ +} ipcp_options; + +extern fsm ipcp_fsm[]; +extern ipcp_options ipcp_wantoptions[]; +extern ipcp_options ipcp_gotoptions[]; +extern ipcp_options ipcp_allowoptions[]; +extern ipcp_options ipcp_hisoptions[]; + +extern struct protent ipcp_protent; + +#endif /* IPCP_H */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/lcp.c b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/lcp.c new file mode 100644 index 0000000..54f758a --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/lcp.c @@ -0,0 +1,2066 @@ +/***************************************************************************** +* lcp.c - Network Link Control Protocol program file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 by Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-12-01 Guy Lancaster , Global Election Systems Inc. +* Original. +*****************************************************************************/ + +/* + * lcp.c - PPP Link Control Protocol. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + + +#include "lwip/opt.h" + +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "ppp_impl.h" +#include "pppdebug.h" + +#include "fsm.h" +#include "chap.h" +#include "magic.h" +#include "auth.h" +#include "lcp.h" + +#include + +#if PPPOE_SUPPORT +#include "netif/ppp_oe.h" +#else +#define PPPOE_MAXMTU PPP_MAXMRU +#endif + +#if 0 /* UNUSED */ +/* + * LCP-related command-line options. + */ +int lcp_echo_interval = 0; /* Interval between LCP echo-requests */ +int lcp_echo_fails = 0; /* Tolerance to unanswered echo-requests */ +bool lax_recv = 0; /* accept control chars in asyncmap */ + +static int setescape (char **); + +static option_t lcp_option_list[] = { + /* LCP options */ + /* list stripped for simplicity */ + {NULL} +}; +#endif /* UNUSED */ + +/* options */ +LinkPhase lcp_phase[NUM_PPP]; /* Phase of link session (RFC 1661) */ +static u_int lcp_echo_interval = LCP_ECHOINTERVAL; /* Interval between LCP echo-requests */ +static u_int lcp_echo_fails = LCP_MAXECHOFAILS; /* Tolerance to unanswered echo-requests */ + +/* global vars */ +static fsm lcp_fsm[NUM_PPP]; /* LCP fsm structure (global)*/ +lcp_options lcp_wantoptions[NUM_PPP]; /* Options that we want to request */ +lcp_options lcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */ +lcp_options lcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */ +lcp_options lcp_hisoptions[NUM_PPP]; /* Options that we ack'd */ +ext_accm xmit_accm[NUM_PPP]; /* extended transmit ACCM */ + +static u32_t lcp_echos_pending = 0; /* Number of outstanding echo msgs */ +static u32_t lcp_echo_number = 0; /* ID number of next echo frame */ +static u32_t lcp_echo_timer_running = 0; /* TRUE if a timer is running */ + +/* @todo: do we really need such a large buffer? The typical 1500 bytes seem too much. */ +static u_char nak_buffer[PPP_MRU]; /* where we construct a nak packet */ + +/* + * Callbacks for fsm code. (CI = Configuration Information) + */ +static void lcp_resetci (fsm*); /* Reset our CI */ +static int lcp_cilen (fsm*); /* Return length of our CI */ +static void lcp_addci (fsm*, u_char*, int*); /* Add our CI to pkt */ +static int lcp_ackci (fsm*, u_char*, int); /* Peer ack'd our CI */ +static int lcp_nakci (fsm*, u_char*, int); /* Peer nak'd our CI */ +static int lcp_rejci (fsm*, u_char*, int); /* Peer rej'd our CI */ +static int lcp_reqci (fsm*, u_char*, int*, int); /* Rcv peer CI */ +static void lcp_up (fsm*); /* We're UP */ +static void lcp_down (fsm*); /* We're DOWN */ +static void lcp_starting (fsm*); /* We need lower layer up */ +static void lcp_finished (fsm*); /* We need lower layer down */ +static int lcp_extcode (fsm*, int, u_char, u_char*, int); +static void lcp_rprotrej (fsm*, u_char*, int); + +/* + * routines to send LCP echos to peer + */ + +static void lcp_echo_lowerup (int); +static void lcp_echo_lowerdown (int); +static void LcpEchoTimeout (void*); +static void lcp_received_echo_reply (fsm*, int, u_char*, int); +static void LcpSendEchoRequest (fsm*); +static void LcpLinkFailure (fsm*); +static void LcpEchoCheck (fsm*); + +static fsm_callbacks lcp_callbacks = { /* LCP callback routines */ + lcp_resetci, /* Reset our Configuration Information */ + lcp_cilen, /* Length of our Configuration Information */ + lcp_addci, /* Add our Configuration Information */ + lcp_ackci, /* ACK our Configuration Information */ + lcp_nakci, /* NAK our Configuration Information */ + lcp_rejci, /* Reject our Configuration Information */ + lcp_reqci, /* Request peer's Configuration Information */ + lcp_up, /* Called when fsm reaches LS_OPENED state */ + lcp_down, /* Called when fsm leaves LS_OPENED state */ + lcp_starting, /* Called when we want the lower layer up */ + lcp_finished, /* Called when we want the lower layer down */ + NULL, /* Called when Protocol-Reject received */ + NULL, /* Retransmission is necessary */ + lcp_extcode, /* Called to handle LCP-specific codes */ + "LCP" /* String name of protocol */ +}; + +/* + * Protocol entry points. + * Some of these are called directly. + */ + +static void lcp_input (int, u_char *, int); +static void lcp_protrej (int); + +struct protent lcp_protent = { + PPP_LCP, + lcp_init, + lcp_input, + lcp_protrej, + lcp_lowerup, + lcp_lowerdown, + lcp_open, + lcp_close, +#if PPP_ADDITIONAL_CALLBACKS + lcp_printpkt, + NULL, +#endif /* PPP_ADDITIONAL_CALLBACKS */ + 1, + "LCP", +#if PPP_ADDITIONAL_CALLBACKS + NULL, + NULL, + NULL +#endif /* PPP_ADDITIONAL_CALLBACKS */ +}; + +int lcp_loopbackfail = DEFLOOPBACKFAIL; + +/* + * Length of each type of configuration option (in octets) + */ +#define CILEN_VOID 2 +#define CILEN_CHAR 3 +#define CILEN_SHORT 4 /* CILEN_VOID + sizeof(short) */ +#define CILEN_CHAP 5 /* CILEN_VOID + sizeof(short) + 1 */ +#define CILEN_LONG 6 /* CILEN_VOID + sizeof(long) */ +#define CILEN_LQR 8 /* CILEN_VOID + sizeof(short) + sizeof(long) */ +#define CILEN_CBCP 3 + +#define CODENAME(x) ((x) == CONFACK ? "ACK" : (x) == CONFNAK ? "NAK" : "REJ") + +#if 0 /* UNUSED */ +/* + * setescape - add chars to the set we escape on transmission. + */ +static int +setescape(argv) + char **argv; +{ + int n, ret; + char *p, *endp; + + p = *argv; + ret = 1; + while (*p) { + n = strtol(p, &endp, 16); + if (p == endp) { + option_error("escape parameter contains invalid hex number '%s'", p); + return 0; + } + p = endp; + if (n < 0 || n == 0x5E || n > 0xFF) { + option_error("can't escape character 0x%x", n); + ret = 0; + } else + xmit_accm[0][n >> 5] |= 1 << (n & 0x1F); + while (*p == ',' || *p == ' ') + ++p; + } + return ret; +} +#endif /* UNUSED */ + +/* + * lcp_init - Initialize LCP. + */ +void +lcp_init(int unit) +{ + fsm *f = &lcp_fsm[unit]; + lcp_options *wo = &lcp_wantoptions[unit]; + lcp_options *ao = &lcp_allowoptions[unit]; + + f->unit = unit; + f->protocol = PPP_LCP; + f->callbacks = &lcp_callbacks; + + fsm_init(f); + + wo->passive = 0; + wo->silent = 0; + wo->restart = 0; /* Set to 1 in kernels or multi-line implementations */ + wo->neg_mru = 1; + wo->mru = PPP_DEFMRU; + wo->neg_asyncmap = 1; + wo->asyncmap = 0x00000000l; /* Assume don't need to escape any ctl chars. */ + wo->neg_chap = 0; /* Set to 1 on server */ + wo->neg_upap = 0; /* Set to 1 on server */ + wo->chap_mdtype = CHAP_DIGEST_MD5; + wo->neg_magicnumber = 1; + wo->neg_pcompression = 1; + wo->neg_accompression = 1; + wo->neg_lqr = 0; /* no LQR implementation yet */ + wo->neg_cbcp = 0; + + ao->neg_mru = 1; + ao->mru = PPP_MAXMRU; + ao->neg_asyncmap = 1; + ao->asyncmap = 0x00000000l; /* Assume don't need to escape any ctl chars. */ + ao->neg_chap = (CHAP_SUPPORT != 0); + ao->chap_mdtype = CHAP_DIGEST_MD5; + ao->neg_upap = (PAP_SUPPORT != 0); + ao->neg_magicnumber = 1; + ao->neg_pcompression = 1; + ao->neg_accompression = 1; + ao->neg_lqr = 0; /* no LQR implementation yet */ + ao->neg_cbcp = (CBCP_SUPPORT != 0); + + /* + * Set transmit escape for the flag and escape characters plus anything + * set for the allowable options. + */ + memset(xmit_accm[unit], 0, sizeof(xmit_accm[0])); + xmit_accm[unit][15] = 0x60; + xmit_accm[unit][0] = (u_char)((ao->asyncmap & 0xFF)); + xmit_accm[unit][1] = (u_char)((ao->asyncmap >> 8) & 0xFF); + xmit_accm[unit][2] = (u_char)((ao->asyncmap >> 16) & 0xFF); + xmit_accm[unit][3] = (u_char)((ao->asyncmap >> 24) & 0xFF); + LCPDEBUG(LOG_INFO, ("lcp_init: xmit_accm=%X %X %X %X\n", + xmit_accm[unit][0], + xmit_accm[unit][1], + xmit_accm[unit][2], + xmit_accm[unit][3])); + + lcp_phase[unit] = PHASE_INITIALIZE; +} + + +/* + * lcp_open - LCP is allowed to come up. + */ +void +lcp_open(int unit) +{ + fsm *f = &lcp_fsm[unit]; + lcp_options *wo = &lcp_wantoptions[unit]; + + f->flags = 0; + if (wo->passive) { + f->flags |= OPT_PASSIVE; + } + if (wo->silent) { + f->flags |= OPT_SILENT; + } + fsm_open(f); + + lcp_phase[unit] = PHASE_ESTABLISH; +} + + +/* + * lcp_close - Take LCP down. + */ +void +lcp_close(int unit, char *reason) +{ + fsm *f = &lcp_fsm[unit]; + + if (lcp_phase[unit] != PHASE_DEAD) { + lcp_phase[unit] = PHASE_TERMINATE; + } + if (f->state == LS_STOPPED && f->flags & (OPT_PASSIVE|OPT_SILENT)) { + /* + * This action is not strictly according to the FSM in RFC1548, + * but it does mean that the program terminates if you do an + * lcp_close() in passive/silent mode when a connection hasn't + * been established. + */ + f->state = LS_CLOSED; + lcp_finished(f); + } else { + fsm_close(f, reason); + } +} + + +/* + * lcp_lowerup - The lower layer is up. + */ +void +lcp_lowerup(int unit) +{ + lcp_options *wo = &lcp_wantoptions[unit]; + + /* + * Don't use A/C or protocol compression on transmission, + * but accept A/C and protocol compressed packets + * if we are going to ask for A/C and protocol compression. + */ + ppp_set_xaccm(unit, &xmit_accm[unit]); + ppp_send_config(unit, PPP_MRU, 0xffffffffl, 0, 0); + ppp_recv_config(unit, PPP_MRU, 0x00000000l, + wo->neg_pcompression, wo->neg_accompression); + peer_mru[unit] = PPP_MRU; + lcp_allowoptions[unit].asyncmap = (u_long)xmit_accm[unit][0] + | ((u_long)xmit_accm[unit][1] << 8) + | ((u_long)xmit_accm[unit][2] << 16) + | ((u_long)xmit_accm[unit][3] << 24); + LCPDEBUG(LOG_INFO, ("lcp_lowerup: asyncmap=%X %X %X %X\n", + xmit_accm[unit][3], + xmit_accm[unit][2], + xmit_accm[unit][1], + xmit_accm[unit][0])); + + fsm_lowerup(&lcp_fsm[unit]); +} + + +/* + * lcp_lowerdown - The lower layer is down. + */ +void +lcp_lowerdown(int unit) +{ + fsm_lowerdown(&lcp_fsm[unit]); +} + + +/* + * lcp_input - Input LCP packet. + */ +static void +lcp_input(int unit, u_char *p, int len) +{ + fsm *f = &lcp_fsm[unit]; + + fsm_input(f, p, len); +} + + +/* + * lcp_extcode - Handle a LCP-specific code. + */ +static int +lcp_extcode(fsm *f, int code, u_char id, u_char *inp, int len) +{ + u_char *magp; + + switch( code ){ + case PROTREJ: + lcp_rprotrej(f, inp, len); + break; + + case ECHOREQ: + if (f->state != LS_OPENED) { + break; + } + LCPDEBUG(LOG_INFO, ("lcp: Echo-Request, Rcvd id %d\n", id)); + magp = inp; + PUTLONG(lcp_gotoptions[f->unit].magicnumber, magp); + fsm_sdata(f, ECHOREP, id, inp, len); + break; + + case ECHOREP: + lcp_received_echo_reply(f, id, inp, len); + break; + + case DISCREQ: + break; + + default: + return 0; + } + return 1; +} + + +/* + * lcp_rprotrej - Receive an Protocol-Reject. + * + * Figure out which protocol is rejected and inform it. + */ +static void +lcp_rprotrej(fsm *f, u_char *inp, int len) +{ + int i; + struct protent *protp; + u_short prot; + + if (len < (int)sizeof (u_short)) { + LCPDEBUG(LOG_INFO, ("lcp_rprotrej: Rcvd short Protocol-Reject packet!\n")); + return; + } + + GETSHORT(prot, inp); + + LCPDEBUG(LOG_INFO, ("lcp_rprotrej: Rcvd Protocol-Reject packet for %x!\n", prot)); + + /* + * Protocol-Reject packets received in any state other than the LCP + * LS_OPENED state SHOULD be silently discarded. + */ + if( f->state != LS_OPENED ) { + LCPDEBUG(LOG_INFO, ("Protocol-Reject discarded: LCP in state %d\n", f->state)); + return; + } + + /* + * Upcall the proper Protocol-Reject routine. + */ + for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) { + if (protp->protocol == prot && protp->enabled_flag) { + (*protp->protrej)(f->unit); + return; + } + } + + LCPDEBUG(LOG_WARNING, ("Protocol-Reject for unsupported protocol 0x%x\n", prot)); +} + + +/* + * lcp_protrej - A Protocol-Reject was received. + */ +static void +lcp_protrej(int unit) +{ + LWIP_UNUSED_ARG(unit); + /* + * Can't reject LCP! + */ + LCPDEBUG(LOG_WARNING, ("lcp_protrej: Received Protocol-Reject for LCP!\n")); + fsm_protreject(&lcp_fsm[unit]); +} + + +/* + * lcp_sprotrej - Send a Protocol-Reject for some protocol. + */ +void +lcp_sprotrej(int unit, u_char *p, int len) +{ + /* + * Send back the protocol and the information field of the + * rejected packet. We only get here if LCP is in the LS_OPENED state. + */ + + fsm_sdata(&lcp_fsm[unit], PROTREJ, ++lcp_fsm[unit].id, p, len); +} + + +/* + * lcp_resetci - Reset our CI. + */ +static void +lcp_resetci(fsm *f) +{ + lcp_wantoptions[f->unit].magicnumber = magic(); + lcp_wantoptions[f->unit].numloops = 0; + lcp_gotoptions[f->unit] = lcp_wantoptions[f->unit]; + peer_mru[f->unit] = PPP_MRU; + auth_reset(f->unit); +} + + +/* + * lcp_cilen - Return length of our CI. + */ +static int +lcp_cilen(fsm *f) +{ + lcp_options *go = &lcp_gotoptions[f->unit]; + +#define LENCIVOID(neg) ((neg) ? CILEN_VOID : 0) +#define LENCICHAP(neg) ((neg) ? CILEN_CHAP : 0) +#define LENCISHORT(neg) ((neg) ? CILEN_SHORT : 0) +#define LENCILONG(neg) ((neg) ? CILEN_LONG : 0) +#define LENCILQR(neg) ((neg) ? CILEN_LQR: 0) +#define LENCICBCP(neg) ((neg) ? CILEN_CBCP: 0) + /* + * NB: we only ask for one of CHAP and UPAP, even if we will + * accept either. + */ + return (LENCISHORT(go->neg_mru && go->mru != PPP_DEFMRU) + + LENCILONG(go->neg_asyncmap && go->asyncmap != 0xFFFFFFFFl) + + LENCICHAP(go->neg_chap) + + LENCISHORT(!go->neg_chap && go->neg_upap) + + LENCILQR(go->neg_lqr) + + LENCICBCP(go->neg_cbcp) + + LENCILONG(go->neg_magicnumber) + + LENCIVOID(go->neg_pcompression) + + LENCIVOID(go->neg_accompression)); +} + + +/* + * lcp_addci - Add our desired CIs to a packet. + */ +static void +lcp_addci(fsm *f, u_char *ucp, int *lenp) +{ + lcp_options *go = &lcp_gotoptions[f->unit]; + u_char *start_ucp = ucp; + +#define ADDCIVOID(opt, neg) \ + if (neg) { \ + LCPDEBUG(LOG_INFO, ("lcp_addci: opt=%d\n", opt)); \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_VOID, ucp); \ + } +#define ADDCISHORT(opt, neg, val) \ + if (neg) { \ + LCPDEBUG(LOG_INFO, ("lcp_addci: INT opt=%d %X\n", opt, val)); \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_SHORT, ucp); \ + PUTSHORT(val, ucp); \ + } +#define ADDCICHAP(opt, neg, val, digest) \ + if (neg) { \ + LCPDEBUG(LOG_INFO, ("lcp_addci: CHAP opt=%d %X\n", opt, val)); \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_CHAP, ucp); \ + PUTSHORT(val, ucp); \ + PUTCHAR(digest, ucp); \ + } +#define ADDCILONG(opt, neg, val) \ + if (neg) { \ + LCPDEBUG(LOG_INFO, ("lcp_addci: L opt=%d %lX\n", opt, val)); \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_LONG, ucp); \ + PUTLONG(val, ucp); \ + } +#define ADDCILQR(opt, neg, val) \ + if (neg) { \ + LCPDEBUG(LOG_INFO, ("lcp_addci: LQR opt=%d %lX\n", opt, val)); \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_LQR, ucp); \ + PUTSHORT(PPP_LQR, ucp); \ + PUTLONG(val, ucp); \ + } +#define ADDCICHAR(opt, neg, val) \ + if (neg) { \ + LCPDEBUG(LOG_INFO, ("lcp_addci: CHAR opt=%d %X '%z'\n", opt, val, val)); \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_CHAR, ucp); \ + PUTCHAR(val, ucp); \ + } + + ADDCISHORT(CI_MRU, go->neg_mru && go->mru != PPP_DEFMRU, go->mru); + ADDCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFFl, go->asyncmap); + ADDCICHAP(CI_AUTHTYPE, go->neg_chap, PPP_CHAP, go->chap_mdtype); + ADDCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP); + ADDCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period); + ADDCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT); + ADDCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber); + ADDCIVOID(CI_PCOMPRESSION, go->neg_pcompression); + ADDCIVOID(CI_ACCOMPRESSION, go->neg_accompression); + + if (ucp - start_ucp != *lenp) { + /* this should never happen, because peer_mtu should be 1500 */ + LCPDEBUG(LOG_ERR, ("Bug in lcp_addci: wrong length\n")); + } +} + + +/* + * lcp_ackci - Ack our CIs. + * This should not modify any state if the Ack is bad. + * + * Returns: + * 0 - Ack was bad. + * 1 - Ack was good. + */ +static int +lcp_ackci(fsm *f, u_char *p, int len) +{ + lcp_options *go = &lcp_gotoptions[f->unit]; + u_char cilen, citype, cichar; + u_short cishort; + u32_t cilong; + + /* + * CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define ACKCIVOID(opt, neg) \ + if (neg) { \ + if ((len -= CILEN_VOID) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_VOID || citype != opt) \ + goto bad; \ + } +#define ACKCISHORT(opt, neg, val) \ + if (neg) { \ + if ((len -= CILEN_SHORT) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_SHORT || citype != opt) \ + goto bad; \ + GETSHORT(cishort, p); \ + if (cishort != val) \ + goto bad; \ + } +#define ACKCICHAR(opt, neg, val) \ + if (neg) { \ + if ((len -= CILEN_CHAR) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_CHAR || citype != opt) \ + goto bad; \ + GETCHAR(cichar, p); \ + if (cichar != val) \ + goto bad; \ + } +#define ACKCICHAP(opt, neg, val, digest) \ + if (neg) { \ + if ((len -= CILEN_CHAP) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_CHAP || citype != opt) \ + goto bad; \ + GETSHORT(cishort, p); \ + if (cishort != val) \ + goto bad; \ + GETCHAR(cichar, p); \ + if (cichar != digest) \ + goto bad; \ + } +#define ACKCILONG(opt, neg, val) \ + if (neg) { \ + if ((len -= CILEN_LONG) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_LONG || citype != opt) \ + goto bad; \ + GETLONG(cilong, p); \ + if (cilong != val) \ + goto bad; \ + } +#define ACKCILQR(opt, neg, val) \ + if (neg) { \ + if ((len -= CILEN_LQR) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_LQR || citype != opt) \ + goto bad; \ + GETSHORT(cishort, p); \ + if (cishort != PPP_LQR) \ + goto bad; \ + GETLONG(cilong, p); \ + if (cilong != val) \ + goto bad; \ + } + + ACKCISHORT(CI_MRU, go->neg_mru && go->mru != PPP_DEFMRU, go->mru); + ACKCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFFl, go->asyncmap); + ACKCICHAP(CI_AUTHTYPE, go->neg_chap, PPP_CHAP, go->chap_mdtype); + ACKCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP); + ACKCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period); + ACKCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT); + ACKCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber); + ACKCIVOID(CI_PCOMPRESSION, go->neg_pcompression); + ACKCIVOID(CI_ACCOMPRESSION, go->neg_accompression); + + /* + * If there are any remaining CIs, then this packet is bad. + */ + if (len != 0) { + goto bad; + } + LCPDEBUG(LOG_INFO, ("lcp_acki: Ack\n")); + return (1); +bad: + LCPDEBUG(LOG_WARNING, ("lcp_acki: received bad Ack!\n")); + return (0); +} + + +/* + * lcp_nakci - Peer has sent a NAK for some of our CIs. + * This should not modify any state if the Nak is bad + * or if LCP is in the LS_OPENED state. + * + * Returns: + * 0 - Nak was bad. + * 1 - Nak was good. + */ +static int +lcp_nakci(fsm *f, u_char *p, int len) +{ + lcp_options *go = &lcp_gotoptions[f->unit]; + lcp_options *wo = &lcp_wantoptions[f->unit]; + u_char citype, cichar, *next; + u_short cishort; + u32_t cilong; + lcp_options no; /* options we've seen Naks for */ + lcp_options try; /* options to request next time */ + int looped_back = 0; + int cilen; + + BZERO(&no, sizeof(no)); + try = *go; + + /* + * Any Nak'd CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define NAKCIVOID(opt, neg, code) \ + if (go->neg && \ + len >= CILEN_VOID && \ + p[1] == CILEN_VOID && \ + p[0] == opt) { \ + len -= CILEN_VOID; \ + INCPTR(CILEN_VOID, p); \ + no.neg = 1; \ + code \ + } +#define NAKCICHAP(opt, neg, code) \ + if (go->neg && \ + len >= CILEN_CHAP && \ + p[1] == CILEN_CHAP && \ + p[0] == opt) { \ + len -= CILEN_CHAP; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETCHAR(cichar, p); \ + no.neg = 1; \ + code \ + } +#define NAKCICHAR(opt, neg, code) \ + if (go->neg && \ + len >= CILEN_CHAR && \ + p[1] == CILEN_CHAR && \ + p[0] == opt) { \ + len -= CILEN_CHAR; \ + INCPTR(2, p); \ + GETCHAR(cichar, p); \ + no.neg = 1; \ + code \ + } +#define NAKCISHORT(opt, neg, code) \ + if (go->neg && \ + len >= CILEN_SHORT && \ + p[1] == CILEN_SHORT && \ + p[0] == opt) { \ + len -= CILEN_SHORT; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + no.neg = 1; \ + code \ + } +#define NAKCILONG(opt, neg, code) \ + if (go->neg && \ + len >= CILEN_LONG && \ + p[1] == CILEN_LONG && \ + p[0] == opt) { \ + len -= CILEN_LONG; \ + INCPTR(2, p); \ + GETLONG(cilong, p); \ + no.neg = 1; \ + code \ + } +#define NAKCILQR(opt, neg, code) \ + if (go->neg && \ + len >= CILEN_LQR && \ + p[1] == CILEN_LQR && \ + p[0] == opt) { \ + len -= CILEN_LQR; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETLONG(cilong, p); \ + no.neg = 1; \ + code \ + } + + /* + * We don't care if they want to send us smaller packets than + * we want. Therefore, accept any MRU less than what we asked for, + * but then ignore the new value when setting the MRU in the kernel. + * If they send us a bigger MRU than what we asked, accept it, up to + * the limit of the default MRU we'd get if we didn't negotiate. + */ + if (go->neg_mru && go->mru != PPP_DEFMRU) { + NAKCISHORT(CI_MRU, neg_mru, + if (cishort <= wo->mru || cishort < PPP_DEFMRU) { + try.mru = cishort; + } + ); + } + + /* + * Add any characters they want to our (receive-side) asyncmap. + */ + if (go->neg_asyncmap && go->asyncmap != 0xFFFFFFFFl) { + NAKCILONG(CI_ASYNCMAP, neg_asyncmap, + try.asyncmap = go->asyncmap | cilong; + ); + } + + /* + * If they've nak'd our authentication-protocol, check whether + * they are proposing a different protocol, or a different + * hash algorithm for CHAP. + */ + if ((go->neg_chap || go->neg_upap) + && len >= CILEN_SHORT + && p[0] == CI_AUTHTYPE && p[1] >= CILEN_SHORT && p[1] <= len) { + cilen = p[1]; + len -= cilen; + no.neg_chap = go->neg_chap; + no.neg_upap = go->neg_upap; + INCPTR(2, p); + GETSHORT(cishort, p); + if (cishort == PPP_PAP && cilen == CILEN_SHORT) { + /* + * If we were asking for CHAP, they obviously don't want to do it. + * If we weren't asking for CHAP, then we were asking for PAP, + * in which case this Nak is bad. + */ + if (!go->neg_chap) { + goto bad; + } + try.neg_chap = 0; + + } else if (cishort == PPP_CHAP && cilen == CILEN_CHAP) { + GETCHAR(cichar, p); + if (go->neg_chap) { + /* + * We were asking for CHAP/MD5; they must want a different + * algorithm. If they can't do MD5, we'll have to stop + * asking for CHAP. + */ + if (cichar != go->chap_mdtype) { + try.neg_chap = 0; + } + } else { + /* + * Stop asking for PAP if we were asking for it. + */ + try.neg_upap = 0; + } + + } else { + /* + * We don't recognize what they're suggesting. + * Stop asking for what we were asking for. + */ + if (go->neg_chap) { + try.neg_chap = 0; + } else { + try.neg_upap = 0; + } + p += cilen - CILEN_SHORT; + } + } + + /* + * If they can't cope with our link quality protocol, we'll have + * to stop asking for LQR. We haven't got any other protocol. + * If they Nak the reporting period, take their value XXX ? + */ + NAKCILQR(CI_QUALITY, neg_lqr, + if (cishort != PPP_LQR) { + try.neg_lqr = 0; + } else { + try.lqr_period = cilong; + } + ); + + /* + * Only implementing CBCP...not the rest of the callback options + */ + NAKCICHAR(CI_CALLBACK, neg_cbcp, + try.neg_cbcp = 0; + ); + + /* + * Check for a looped-back line. + */ + NAKCILONG(CI_MAGICNUMBER, neg_magicnumber, + try.magicnumber = magic(); + looped_back = 1; + ); + + /* + * Peer shouldn't send Nak for protocol compression or + * address/control compression requests; they should send + * a Reject instead. If they send a Nak, treat it as a Reject. + */ + NAKCIVOID(CI_PCOMPRESSION, neg_pcompression, + try.neg_pcompression = 0; + ); + NAKCIVOID(CI_ACCOMPRESSION, neg_accompression, + try.neg_accompression = 0; + ); + + /* + * There may be remaining CIs, if the peer is requesting negotiation + * on an option that we didn't include in our request packet. + * If we see an option that we requested, or one we've already seen + * in this packet, then this packet is bad. + * If we wanted to respond by starting to negotiate on the requested + * option(s), we could, but we don't, because except for the + * authentication type and quality protocol, if we are not negotiating + * an option, it is because we were told not to. + * For the authentication type, the Nak from the peer means + * `let me authenticate myself with you' which is a bit pointless. + * For the quality protocol, the Nak means `ask me to send you quality + * reports', but if we didn't ask for them, we don't want them. + * An option we don't recognize represents the peer asking to + * negotiate some option we don't support, so ignore it. + */ + while (len > CILEN_VOID) { + GETCHAR(citype, p); + GETCHAR(cilen, p); + if (cilen < CILEN_VOID || (len -= cilen) < 0) { + goto bad; + } + next = p + cilen - 2; + + switch (citype) { + case CI_MRU: + if ((go->neg_mru && go->mru != PPP_DEFMRU) + || no.neg_mru || cilen != CILEN_SHORT) { + goto bad; + } + GETSHORT(cishort, p); + if (cishort < PPP_DEFMRU) { + try.mru = cishort; + } + break; + case CI_ASYNCMAP: + if ((go->neg_asyncmap && go->asyncmap != 0xFFFFFFFFl) + || no.neg_asyncmap || cilen != CILEN_LONG) { + goto bad; + } + break; + case CI_AUTHTYPE: + if (go->neg_chap || no.neg_chap || go->neg_upap || no.neg_upap) { + goto bad; + } + break; + case CI_MAGICNUMBER: + if (go->neg_magicnumber || no.neg_magicnumber || + cilen != CILEN_LONG) { + goto bad; + } + break; + case CI_PCOMPRESSION: + if (go->neg_pcompression || no.neg_pcompression + || cilen != CILEN_VOID) { + goto bad; + } + break; + case CI_ACCOMPRESSION: + if (go->neg_accompression || no.neg_accompression + || cilen != CILEN_VOID) { + goto bad; + } + break; + case CI_QUALITY: + if (go->neg_lqr || no.neg_lqr || cilen != CILEN_LQR) { + goto bad; + } + break; + } + p = next; + } + + /* If there is still anything left, this packet is bad. */ + if (len != 0) { + goto bad; + } + + /* + * OK, the Nak is good. Now we can update state. + */ + if (f->state != LS_OPENED) { + if (looped_back) { + if (++try.numloops >= lcp_loopbackfail) { + LCPDEBUG(LOG_NOTICE, ("Serial line is looped back.\n")); + lcp_close(f->unit, "Loopback detected"); + } + } else { + try.numloops = 0; + } + *go = try; + } + + return 1; + +bad: + LCPDEBUG(LOG_WARNING, ("lcp_nakci: received bad Nak!\n")); + return 0; +} + + +/* + * lcp_rejci - Peer has Rejected some of our CIs. + * This should not modify any state if the Reject is bad + * or if LCP is in the LS_OPENED state. + * + * Returns: + * 0 - Reject was bad. + * 1 - Reject was good. + */ +static int +lcp_rejci(fsm *f, u_char *p, int len) +{ + lcp_options *go = &lcp_gotoptions[f->unit]; + u_char cichar; + u_short cishort; + u32_t cilong; + lcp_options try; /* options to request next time */ + + try = *go; + + /* + * Any Rejected CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define REJCIVOID(opt, neg) \ + if (go->neg && \ + len >= CILEN_VOID && \ + p[1] == CILEN_VOID && \ + p[0] == opt) { \ + len -= CILEN_VOID; \ + INCPTR(CILEN_VOID, p); \ + try.neg = 0; \ + LCPDEBUG(LOG_INFO, ("lcp_rejci: void opt %d rejected\n", opt)); \ + } +#define REJCISHORT(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_SHORT && \ + p[1] == CILEN_SHORT && \ + p[0] == opt) { \ + len -= CILEN_SHORT; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + /* Check rejected value. */ \ + if (cishort != val) { \ + goto bad; \ + } \ + try.neg = 0; \ + LCPDEBUG(LOG_INFO, ("lcp_rejci: short opt %d rejected\n", opt)); \ + } +#define REJCICHAP(opt, neg, val, digest) \ + if (go->neg && \ + len >= CILEN_CHAP && \ + p[1] == CILEN_CHAP && \ + p[0] == opt) { \ + len -= CILEN_CHAP; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETCHAR(cichar, p); \ + /* Check rejected value. */ \ + if (cishort != val || cichar != digest) { \ + goto bad; \ + } \ + try.neg = 0; \ + try.neg_upap = 0; \ + LCPDEBUG(LOG_INFO, ("lcp_rejci: chap opt %d rejected\n", opt)); \ + } +#define REJCILONG(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_LONG && \ + p[1] == CILEN_LONG && \ + p[0] == opt) { \ + len -= CILEN_LONG; \ + INCPTR(2, p); \ + GETLONG(cilong, p); \ + /* Check rejected value. */ \ + if (cilong != val) { \ + goto bad; \ + } \ + try.neg = 0; \ + LCPDEBUG(LOG_INFO, ("lcp_rejci: long opt %d rejected\n", opt)); \ + } +#define REJCILQR(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_LQR && \ + p[1] == CILEN_LQR && \ + p[0] == opt) { \ + len -= CILEN_LQR; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETLONG(cilong, p); \ + /* Check rejected value. */ \ + if (cishort != PPP_LQR || cilong != val) { \ + goto bad; \ + } \ + try.neg = 0; \ + LCPDEBUG(LOG_INFO, ("lcp_rejci: LQR opt %d rejected\n", opt)); \ + } +#define REJCICBCP(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_CBCP && \ + p[1] == CILEN_CBCP && \ + p[0] == opt) { \ + len -= CILEN_CBCP; \ + INCPTR(2, p); \ + GETCHAR(cichar, p); \ + /* Check rejected value. */ \ + if (cichar != val) { \ + goto bad; \ + } \ + try.neg = 0; \ + LCPDEBUG(LOG_INFO, ("lcp_rejci: Callback opt %d rejected\n", opt)); \ + } + + REJCISHORT(CI_MRU, neg_mru, go->mru); + REJCILONG(CI_ASYNCMAP, neg_asyncmap, go->asyncmap); + REJCICHAP(CI_AUTHTYPE, neg_chap, PPP_CHAP, go->chap_mdtype); + if (!go->neg_chap) { + REJCISHORT(CI_AUTHTYPE, neg_upap, PPP_PAP); + } + REJCILQR(CI_QUALITY, neg_lqr, go->lqr_period); + REJCICBCP(CI_CALLBACK, neg_cbcp, CBCP_OPT); + REJCILONG(CI_MAGICNUMBER, neg_magicnumber, go->magicnumber); + REJCIVOID(CI_PCOMPRESSION, neg_pcompression); + REJCIVOID(CI_ACCOMPRESSION, neg_accompression); + + /* + * If there are any remaining CIs, then this packet is bad. + */ + if (len != 0) { + goto bad; + } + /* + * Now we can update state. + */ + if (f->state != LS_OPENED) { + *go = try; + } + return 1; + +bad: + LCPDEBUG(LOG_WARNING, ("lcp_rejci: received bad Reject!\n")); + return 0; +} + + +/* + * lcp_reqci - Check the peer's requested CIs and send appropriate response. + * + * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified + * appropriately. If reject_if_disagree is non-zero, doesn't return + * CONFNAK; returns CONFREJ if it can't return CONFACK. + */ +static int +lcp_reqci(fsm *f, + u_char *inp, /* Requested CIs */ + int *lenp, /* Length of requested CIs */ + int reject_if_disagree) +{ + lcp_options *go = &lcp_gotoptions[f->unit]; + lcp_options *ho = &lcp_hisoptions[f->unit]; + lcp_options *ao = &lcp_allowoptions[f->unit]; + u_char *cip, *next; /* Pointer to current and next CIs */ + int cilen, citype; /* Parsed len, type */ + u_char cichar; /* Parsed char value */ + u_short cishort; /* Parsed short value */ + u32_t cilong; /* Parse long value */ + int rc = CONFACK; /* Final packet return code */ + int orc; /* Individual option return code */ + u_char *p; /* Pointer to next char to parse */ + u_char *rejp; /* Pointer to next char in reject frame */ + u_char *nakp; /* Pointer to next char in Nak frame */ + int l = *lenp; /* Length left */ +#if TRACELCP > 0 + char traceBuf[80]; + size_t traceNdx = 0; +#endif + + /* + * Reset all his options. + */ + BZERO(ho, sizeof(*ho)); + + /* + * Process all his options. + */ + next = inp; + nakp = nak_buffer; + rejp = inp; + while (l) { + orc = CONFACK; /* Assume success */ + cip = p = next; /* Remember begining of CI */ + if (l < 2 || /* Not enough data for CI header or */ + p[1] < 2 || /* CI length too small or */ + p[1] > l) { /* CI length too big? */ + LCPDEBUG(LOG_WARNING, ("lcp_reqci: bad CI length!\n")); + orc = CONFREJ; /* Reject bad CI */ + cilen = l; /* Reject till end of packet */ + l = 0; /* Don't loop again */ + citype = 0; + goto endswitch; + } + GETCHAR(citype, p); /* Parse CI type */ + GETCHAR(cilen, p); /* Parse CI length */ + l -= cilen; /* Adjust remaining length */ + next += cilen; /* Step to next CI */ + + switch (citype) { /* Check CI type */ + case CI_MRU: + if (!ao->neg_mru) { /* Allow option? */ + LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject MRU - not allowed\n")); + orc = CONFREJ; /* Reject CI */ + break; + } else if (cilen != CILEN_SHORT) { /* Check CI length */ + LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject MRU - bad length\n")); + orc = CONFREJ; /* Reject CI */ + break; + } + GETSHORT(cishort, p); /* Parse MRU */ + + /* + * He must be able to receive at least our minimum. + * No need to check a maximum. If he sends a large number, + * we'll just ignore it. + */ + if (cishort < PPP_MINMRU) { + LCPDEBUG(LOG_INFO, ("lcp_reqci: Nak - MRU too small\n")); + orc = CONFNAK; /* Nak CI */ + PUTCHAR(CI_MRU, nakp); + PUTCHAR(CILEN_SHORT, nakp); + PUTSHORT(PPP_MINMRU, nakp); /* Give him a hint */ + break; + } + ho->neg_mru = 1; /* Remember he sent MRU */ + ho->mru = cishort; /* And remember value */ +#if TRACELCP > 0 + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " MRU %d", cishort); + traceNdx = strlen(traceBuf); +#endif + break; + + case CI_ASYNCMAP: + if (!ao->neg_asyncmap) { + LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject ASYNCMAP not allowed\n")); + orc = CONFREJ; + break; + } else if (cilen != CILEN_LONG) { + LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject ASYNCMAP bad length\n")); + orc = CONFREJ; + break; + } + GETLONG(cilong, p); + + /* + * Asyncmap must have set at least the bits + * which are set in lcp_allowoptions[unit].asyncmap. + */ + if ((ao->asyncmap & ~cilong) != 0) { + LCPDEBUG(LOG_INFO, ("lcp_reqci: Nak ASYNCMAP %lX missing %lX\n", + cilong, ao->asyncmap)); + orc = CONFNAK; + PUTCHAR(CI_ASYNCMAP, nakp); + PUTCHAR(CILEN_LONG, nakp); + PUTLONG(ao->asyncmap | cilong, nakp); + break; + } + ho->neg_asyncmap = 1; + ho->asyncmap = cilong; +#if TRACELCP > 0 + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " ASYNCMAP=%lX", cilong); + traceNdx = strlen(traceBuf); +#endif + break; + + case CI_AUTHTYPE: + if (cilen < CILEN_SHORT) { + LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject AUTHTYPE missing arg\n")); + orc = CONFREJ; + break; + } else if (!(ao->neg_upap || ao->neg_chap)) { + /* + * Reject the option if we're not willing to authenticate. + */ + LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject AUTHTYPE not allowed\n")); + orc = CONFREJ; + break; + } + GETSHORT(cishort, p); + + /* + * Authtype must be UPAP or CHAP. + * + * Note: if both ao->neg_upap and ao->neg_chap are set, + * and the peer sends a Configure-Request with two + * authenticate-protocol requests, one for CHAP and one + * for UPAP, then we will reject the second request. + * Whether we end up doing CHAP or UPAP depends then on + * the ordering of the CIs in the peer's Configure-Request. + */ + + if (cishort == PPP_PAP) { + if (ho->neg_chap) { /* we've already accepted CHAP */ + LCPDEBUG(LOG_WARNING, ("lcp_reqci: Reject AUTHTYPE PAP already accepted\n")); + orc = CONFREJ; + break; + } else if (cilen != CILEN_SHORT) { + LCPDEBUG(LOG_WARNING, ("lcp_reqci: Reject AUTHTYPE PAP bad len\n")); + orc = CONFREJ; + break; + } + if (!ao->neg_upap) { /* we don't want to do PAP */ + LCPDEBUG(LOG_WARNING, ("lcp_reqci: Nak AUTHTYPE PAP not allowed\n")); + orc = CONFNAK; /* NAK it and suggest CHAP */ + PUTCHAR(CI_AUTHTYPE, nakp); + PUTCHAR(CILEN_CHAP, nakp); + PUTSHORT(PPP_CHAP, nakp); + PUTCHAR(ao->chap_mdtype, nakp); + break; + } + ho->neg_upap = 1; +#if TRACELCP > 0 + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " PAP (%X)", cishort); + traceNdx = strlen(traceBuf); +#endif + break; + } + if (cishort == PPP_CHAP) { + if (ho->neg_upap) { /* we've already accepted PAP */ + LCPDEBUG(LOG_WARNING, ("lcp_reqci: Reject AUTHTYPE CHAP accepted PAP\n")); + orc = CONFREJ; + break; + } else if (cilen != CILEN_CHAP) { + LCPDEBUG(LOG_WARNING, ("lcp_reqci: Reject AUTHTYPE CHAP bad len\n")); + orc = CONFREJ; + break; + } + if (!ao->neg_chap) { /* we don't want to do CHAP */ + LCPDEBUG(LOG_WARNING, ("lcp_reqci: Nak AUTHTYPE CHAP not allowed\n")); + orc = CONFNAK; /* NAK it and suggest PAP */ + PUTCHAR(CI_AUTHTYPE, nakp); + PUTCHAR(CILEN_SHORT, nakp); + PUTSHORT(PPP_PAP, nakp); + break; + } + GETCHAR(cichar, p); /* get digest type*/ + if (cichar != CHAP_DIGEST_MD5 +#if MSCHAP_SUPPORT + && cichar != CHAP_MICROSOFT +#endif + ) { + LCPDEBUG(LOG_WARNING, ("lcp_reqci: Nak AUTHTYPE CHAP digest=%d\n", (int)cichar)); + orc = CONFNAK; + PUTCHAR(CI_AUTHTYPE, nakp); + PUTCHAR(CILEN_CHAP, nakp); + PUTSHORT(PPP_CHAP, nakp); + PUTCHAR(ao->chap_mdtype, nakp); + break; + } +#if TRACELCP > 0 + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CHAP %X,%d", cishort, (int)cichar); + traceNdx = strlen(traceBuf); +#endif + ho->chap_mdtype = cichar; /* save md type */ + ho->neg_chap = 1; + break; + } + + /* + * We don't recognize the protocol they're asking for. + * Nak it with something we're willing to do. + * (At this point we know ao->neg_upap || ao->neg_chap.) + */ + orc = CONFNAK; + PUTCHAR(CI_AUTHTYPE, nakp); + if (ao->neg_chap) { + LCPDEBUG(LOG_WARNING, ("lcp_reqci: Nak AUTHTYPE %d req CHAP\n", cishort)); + PUTCHAR(CILEN_CHAP, nakp); + PUTSHORT(PPP_CHAP, nakp); + PUTCHAR(ao->chap_mdtype, nakp); + } else { + LCPDEBUG(LOG_WARNING, ("lcp_reqci: Nak AUTHTYPE %d req PAP\n", cishort)); + PUTCHAR(CILEN_SHORT, nakp); + PUTSHORT(PPP_PAP, nakp); + } + break; + + case CI_QUALITY: + GETSHORT(cishort, p); + GETLONG(cilong, p); +#if TRACELCP > 0 + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " QUALITY (%x %x)", cishort, (unsigned int) cilong); + traceNdx = strlen(traceBuf); +#endif + + if (!ao->neg_lqr || + cilen != CILEN_LQR) { + orc = CONFREJ; + break; + } + + /* + * Check the protocol and the reporting period. + * XXX When should we Nak this, and what with? + */ + if (cishort != PPP_LQR) { + orc = CONFNAK; + PUTCHAR(CI_QUALITY, nakp); + PUTCHAR(CILEN_LQR, nakp); + PUTSHORT(PPP_LQR, nakp); + PUTLONG(ao->lqr_period, nakp); + break; + } + break; + + case CI_MAGICNUMBER: + if (!(ao->neg_magicnumber || go->neg_magicnumber) || + cilen != CILEN_LONG) { + orc = CONFREJ; + break; + } + GETLONG(cilong, p); +#if TRACELCP > 0 + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " MAGICNUMBER (%lX)", cilong); + traceNdx = strlen(traceBuf); +#endif + + /* + * He must have a different magic number. + */ + if (go->neg_magicnumber && + cilong == go->magicnumber) { + cilong = magic(); /* Don't put magic() inside macro! */ + orc = CONFNAK; + PUTCHAR(CI_MAGICNUMBER, nakp); + PUTCHAR(CILEN_LONG, nakp); + PUTLONG(cilong, nakp); + break; + } + ho->neg_magicnumber = 1; + ho->magicnumber = cilong; + break; + + + case CI_PCOMPRESSION: +#if TRACELCP > 0 + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " PCOMPRESSION"); + traceNdx = strlen(traceBuf); +#endif + if (!ao->neg_pcompression || + cilen != CILEN_VOID) { + orc = CONFREJ; + break; + } + ho->neg_pcompression = 1; + break; + + case CI_ACCOMPRESSION: +#if TRACELCP > 0 + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " ACCOMPRESSION"); + traceNdx = strlen(traceBuf); +#endif + if (!ao->neg_accompression || + cilen != CILEN_VOID) { + orc = CONFREJ; + break; + } + ho->neg_accompression = 1; + break; + + case CI_MRRU: +#if TRACELCP > 0 + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CI_MRRU"); + traceNdx = strlen(traceBuf); +#endif + orc = CONFREJ; + break; + + case CI_SSNHF: +#if TRACELCP > 0 + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CI_SSNHF"); + traceNdx = strlen(traceBuf); +#endif + orc = CONFREJ; + break; + + case CI_EPDISC: +#if TRACELCP > 0 + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CI_EPDISC"); + traceNdx = strlen(traceBuf); +#endif + orc = CONFREJ; + break; + + default: +#if TRACELCP + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " unknown %d", citype); + traceNdx = strlen(traceBuf); +#endif + orc = CONFREJ; + break; + } + + endswitch: +#if TRACELCP + if (traceNdx >= 80 - 32) { + LCPDEBUG(LOG_INFO, ("lcp_reqci: rcvd%s\n", traceBuf)); + traceNdx = 0; + } +#endif + if (orc == CONFACK && /* Good CI */ + rc != CONFACK) { /* but prior CI wasnt? */ + continue; /* Don't send this one */ + } + + if (orc == CONFNAK) { /* Nak this CI? */ + if (reject_if_disagree /* Getting fed up with sending NAKs? */ + && citype != CI_MAGICNUMBER) { + orc = CONFREJ; /* Get tough if so */ + } else { + if (rc == CONFREJ) { /* Rejecting prior CI? */ + continue; /* Don't send this one */ + } + rc = CONFNAK; + } + } + if (orc == CONFREJ) { /* Reject this CI */ + rc = CONFREJ; + if (cip != rejp) { /* Need to move rejected CI? */ + BCOPY(cip, rejp, cilen); /* Move it */ + } + INCPTR(cilen, rejp); /* Update output pointer */ + } + } + + /* + * If we wanted to send additional NAKs (for unsent CIs), the + * code would go here. The extra NAKs would go at *nakp. + * At present there are no cases where we want to ask the + * peer to negotiate an option. + */ + + switch (rc) { + case CONFACK: + *lenp = (int)(next - inp); + break; + case CONFNAK: + /* + * Copy the Nak'd options from the nak_buffer to the caller's buffer. + */ + *lenp = (int)(nakp - nak_buffer); + BCOPY(nak_buffer, inp, *lenp); + break; + case CONFREJ: + *lenp = (int)(rejp - inp); + break; + } + +#if TRACELCP > 0 + if (traceNdx > 0) { + LCPDEBUG(LOG_INFO, ("lcp_reqci: %s\n", traceBuf)); + } +#endif + LCPDEBUG(LOG_INFO, ("lcp_reqci: returning CONF%s.\n", CODENAME(rc))); + return (rc); /* Return final code */ +} + + +/* + * lcp_up - LCP has come UP. + */ +static void +lcp_up(fsm *f) +{ + lcp_options *wo = &lcp_wantoptions[f->unit]; + lcp_options *ho = &lcp_hisoptions[f->unit]; + lcp_options *go = &lcp_gotoptions[f->unit]; + lcp_options *ao = &lcp_allowoptions[f->unit]; + + if (!go->neg_magicnumber) { + go->magicnumber = 0; + } + if (!ho->neg_magicnumber) { + ho->magicnumber = 0; + } + + /* + * Set our MTU to the smaller of the MTU we wanted and + * the MRU our peer wanted. If we negotiated an MRU, + * set our MRU to the larger of value we wanted and + * the value we got in the negotiation. + */ + ppp_send_config(f->unit, LWIP_MIN(ao->mru, (ho->neg_mru? ho->mru: PPP_MRU)), + (ho->neg_asyncmap? ho->asyncmap: 0xffffffffl), + ho->neg_pcompression, ho->neg_accompression); + /* + * If the asyncmap hasn't been negotiated, we really should + * set the receive asyncmap to ffffffff, but we set it to 0 + * for backwards contemptibility. + */ + ppp_recv_config(f->unit, (go->neg_mru? LWIP_MAX(wo->mru, go->mru): PPP_MRU), + (go->neg_asyncmap? go->asyncmap: 0x00000000), + go->neg_pcompression, go->neg_accompression); + + if (ho->neg_mru) { + peer_mru[f->unit] = ho->mru; + } + + lcp_echo_lowerup(f->unit); /* Enable echo messages */ + + link_established(f->unit); /* The link is up; authenticate now */ +} + + +/* + * lcp_down - LCP has gone DOWN. + * + * Alert other protocols. + */ +static void +lcp_down(fsm *f) +{ + lcp_options *go = &lcp_gotoptions[f->unit]; + + lcp_echo_lowerdown(f->unit); + + link_down(f->unit); + + ppp_send_config(f->unit, PPP_MRU, 0xffffffffl, 0, 0); + ppp_recv_config(f->unit, PPP_MRU, + (go->neg_asyncmap? go->asyncmap: 0x00000000), + go->neg_pcompression, go->neg_accompression); + peer_mru[f->unit] = PPP_MRU; +} + + +/* + * lcp_starting - LCP needs the lower layer up. + */ +static void +lcp_starting(fsm *f) +{ + link_required(f->unit); /* lwip: currently does nothing */ +} + + +/* + * lcp_finished - LCP has finished with the lower layer. + */ +static void +lcp_finished(fsm *f) +{ + link_terminated(f->unit); /* we are finished with the link */ +} + + +#if PPP_ADDITIONAL_CALLBACKS +/* + * print_string - print a readable representation of a string using + * printer. + */ +static void +print_string( char *p, int len, void (*printer) (void *, char *, ...), void *arg) +{ + int c; + + printer(arg, "\""); + for (; len > 0; --len) { + c = *p++; + if (' ' <= c && c <= '~') { + if (c == '\\' || c == '"') { + printer(arg, "\\"); + } + printer(arg, "%c", c); + } else { + switch (c) { + case '\n': + printer(arg, "\\n"); + break; + case '\r': + printer(arg, "\\r"); + break; + case '\t': + printer(arg, "\\t"); + break; + default: + printer(arg, "\\%.3o", c); + } + } + } + printer(arg, "\""); +} + + +/* + * lcp_printpkt - print the contents of an LCP packet. + */ +static char *lcp_codenames[] = { + "ConfReq", "ConfAck", "ConfNak", "ConfRej", + "TermReq", "TermAck", "CodeRej", "ProtRej", + "EchoReq", "EchoRep", "DiscReq" +}; + +static int +lcp_printpkt( u_char *p, int plen, void (*printer) (void *, char *, ...), void *arg) +{ + int code, id, len, olen; + u_char *pstart, *optend; + u_short cishort; + u32_t cilong; + + if (plen < HEADERLEN) { + return 0; + } + pstart = p; + GETCHAR(code, p); + GETCHAR(id, p); + GETSHORT(len, p); + if (len < HEADERLEN || len > plen) { + return 0; + } + + if (code >= 1 && code <= sizeof(lcp_codenames) / sizeof(char *)) { + printer(arg, " %s", lcp_codenames[code-1]); + } else { + printer(arg, " code=0x%x", code); + } + printer(arg, " id=0x%x", id); + len -= HEADERLEN; + switch (code) { + case CONFREQ: + case CONFACK: + case CONFNAK: + case CONFREJ: + /* print option list */ + while (len >= 2) { + GETCHAR(code, p); + GETCHAR(olen, p); + p -= 2; + if (olen < 2 || olen > len) { + break; + } + printer(arg, " <"); + len -= olen; + optend = p + olen; + switch (code) { + case CI_MRU: + if (olen == CILEN_SHORT) { + p += 2; + GETSHORT(cishort, p); + printer(arg, "mru %d", cishort); + } + break; + case CI_ASYNCMAP: + if (olen == CILEN_LONG) { + p += 2; + GETLONG(cilong, p); + printer(arg, "asyncmap 0x%lx", cilong); + } + break; + case CI_AUTHTYPE: + if (olen >= CILEN_SHORT) { + p += 2; + printer(arg, "auth "); + GETSHORT(cishort, p); + switch (cishort) { + case PPP_PAP: + printer(arg, "pap"); + break; + case PPP_CHAP: + printer(arg, "chap"); + break; + default: + printer(arg, "0x%x", cishort); + } + } + break; + case CI_QUALITY: + if (olen >= CILEN_SHORT) { + p += 2; + printer(arg, "quality "); + GETSHORT(cishort, p); + switch (cishort) { + case PPP_LQR: + printer(arg, "lqr"); + break; + default: + printer(arg, "0x%x", cishort); + } + } + break; + case CI_CALLBACK: + if (olen >= CILEN_CHAR) { + p += 2; + printer(arg, "callback "); + GETSHORT(cishort, p); + switch (cishort) { + case CBCP_OPT: + printer(arg, "CBCP"); + break; + default: + printer(arg, "0x%x", cishort); + } + } + break; + case CI_MAGICNUMBER: + if (olen == CILEN_LONG) { + p += 2; + GETLONG(cilong, p); + printer(arg, "magic 0x%x", cilong); + } + break; + case CI_PCOMPRESSION: + if (olen == CILEN_VOID) { + p += 2; + printer(arg, "pcomp"); + } + break; + case CI_ACCOMPRESSION: + if (olen == CILEN_VOID) { + p += 2; + printer(arg, "accomp"); + } + break; + } + while (p < optend) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + printer(arg, ">"); + } + break; + + case TERMACK: + case TERMREQ: + if (len > 0 && *p >= ' ' && *p < 0x7f) { + printer(arg, " "); + print_string((char*)p, len, printer, arg); + p += len; + len = 0; + } + break; + + case ECHOREQ: + case ECHOREP: + case DISCREQ: + if (len >= 4) { + GETLONG(cilong, p); + printer(arg, " magic=0x%x", cilong); + p += 4; + len -= 4; + } + break; + } + + /* print the rest of the bytes in the packet */ + for (; len > 0; --len) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + + return (int)(p - pstart); +} +#endif /* PPP_ADDITIONAL_CALLBACKS */ + +/* + * Time to shut down the link because there is nothing out there. + */ +static void +LcpLinkFailure (fsm *f) +{ + if (f->state == LS_OPENED) { + LCPDEBUG(LOG_INFO, ("No response to %d echo-requests\n", lcp_echos_pending)); + LCPDEBUG(LOG_NOTICE, ("Serial link appears to be disconnected.\n")); + lcp_close(f->unit, "Peer not responding"); + } +} + +/* + * Timer expired for the LCP echo requests from this process. + */ +static void +LcpEchoCheck (fsm *f) +{ + LcpSendEchoRequest (f); + + /* + * Start the timer for the next interval. + */ + LWIP_ASSERT("lcp_echo_timer_running == 0", lcp_echo_timer_running == 0); + + TIMEOUT (LcpEchoTimeout, f, lcp_echo_interval); + lcp_echo_timer_running = 1; +} + +/* + * LcpEchoTimeout - Timer expired on the LCP echo + */ +static void +LcpEchoTimeout (void *arg) +{ + if (lcp_echo_timer_running != 0) { + lcp_echo_timer_running = 0; + LcpEchoCheck ((fsm *) arg); + } +} + +/* + * LcpEchoReply - LCP has received a reply to the echo + */ +static void +lcp_received_echo_reply (fsm *f, int id, u_char *inp, int len) +{ + u32_t magic; + + LWIP_UNUSED_ARG(id); + + /* Check the magic number - don't count replies from ourselves. */ + if (len < 4) { + LCPDEBUG(LOG_WARNING, ("lcp: received short Echo-Reply, length %d\n", len)); + return; + } + GETLONG(magic, inp); + if (lcp_gotoptions[f->unit].neg_magicnumber && magic == lcp_gotoptions[f->unit].magicnumber) { + LCPDEBUG(LOG_WARNING, ("appear to have received our own echo-reply!\n")); + return; + } + + /* Reset the number of outstanding echo frames */ + lcp_echos_pending = 0; +} + +/* + * LcpSendEchoRequest - Send an echo request frame to the peer + */ +static void +LcpSendEchoRequest (fsm *f) +{ + u32_t lcp_magic; + u_char pkt[4], *pktp; + + /* + * Detect the failure of the peer at this point. + */ + if (lcp_echo_fails != 0) { + if (lcp_echos_pending >= lcp_echo_fails) { + LcpLinkFailure(f); + lcp_echos_pending = 0; + } + } + + /* + * Make and send the echo request frame. + */ + if (f->state == LS_OPENED) { + lcp_magic = lcp_gotoptions[f->unit].magicnumber; + pktp = pkt; + PUTLONG(lcp_magic, pktp); + fsm_sdata(f, ECHOREQ, (u_char)(lcp_echo_number++ & 0xFF), pkt, (int)(pktp - pkt)); + ++lcp_echos_pending; + } +} + +/* + * lcp_echo_lowerup - Start the timer for the LCP frame + */ + +static void +lcp_echo_lowerup (int unit) +{ + fsm *f = &lcp_fsm[unit]; + + /* Clear the parameters for generating echo frames */ + lcp_echos_pending = 0; + lcp_echo_number = 0; + lcp_echo_timer_running = 0; + + /* If a timeout interval is specified then start the timer */ + if (lcp_echo_interval != 0) { + LcpEchoCheck (f); + } +} + +/* + * lcp_echo_lowerdown - Stop the timer for the LCP frame + */ + +static void +lcp_echo_lowerdown (int unit) +{ + fsm *f = &lcp_fsm[unit]; + + if (lcp_echo_timer_running != 0) { + UNTIMEOUT (LcpEchoTimeout, f); + lcp_echo_timer_running = 0; + } +} + +#endif /* PPP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/lcp.h b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/lcp.h new file mode 100644 index 0000000..b9201ee --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/lcp.h @@ -0,0 +1,151 @@ +/***************************************************************************** +* lcp.h - Network Link Control Protocol header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-11-05 Guy Lancaster , Global Election Systems Inc. +* Original derived from BSD codes. +*****************************************************************************/ +/* + * lcp.h - Link Control Protocol definitions. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * $Id: lcp.h,v 1.4 2010/01/18 20:49:43 goldsimon Exp $ + */ + +#ifndef LCP_H +#define LCP_H +/* + * Options. + */ +#define CI_MRU 1 /* Maximum Receive Unit */ +#define CI_ASYNCMAP 2 /* Async Control Character Map */ +#define CI_AUTHTYPE 3 /* Authentication Type */ +#define CI_QUALITY 4 /* Quality Protocol */ +#define CI_MAGICNUMBER 5 /* Magic Number */ +#define CI_PCOMPRESSION 7 /* Protocol Field Compression */ +#define CI_ACCOMPRESSION 8 /* Address/Control Field Compression */ +#define CI_CALLBACK 13 /* callback */ +#define CI_MRRU 17 /* max reconstructed receive unit; multilink */ +#define CI_SSNHF 18 /* short sequence numbers for multilink */ +#define CI_EPDISC 19 /* endpoint discriminator */ + +/* + * LCP-specific packet types (code numbers). + */ +#define PROTREJ 8 /* Protocol Reject */ +#define ECHOREQ 9 /* Echo Request */ +#define ECHOREP 10 /* Echo Reply */ +#define DISCREQ 11 /* Discard Request */ +#define CBCP_OPT 6 /* Use callback control protocol */ + +/* + * The state of options is described by an lcp_options structure. + */ +typedef struct lcp_options { + u_int passive : 1; /* Don't die if we don't get a response */ + u_int silent : 1; /* Wait for the other end to start first */ + u_int restart : 1; /* Restart vs. exit after close */ + u_int neg_mru : 1; /* Negotiate the MRU? */ + u_int neg_asyncmap : 1; /* Negotiate the async map? */ + u_int neg_upap : 1; /* Ask for UPAP authentication? */ + u_int neg_chap : 1; /* Ask for CHAP authentication? */ + u_int neg_magicnumber : 1; /* Ask for magic number? */ + u_int neg_pcompression : 1; /* HDLC Protocol Field Compression? */ + u_int neg_accompression : 1; /* HDLC Address/Control Field Compression? */ + u_int neg_lqr : 1; /* Negotiate use of Link Quality Reports */ + u_int neg_cbcp : 1; /* Negotiate use of CBCP */ +#ifdef PPP_MULTILINK + u_int neg_mrru : 1; /* Negotiate multilink MRRU */ + u_int neg_ssnhf : 1; /* Negotiate short sequence numbers */ + u_int neg_endpoint : 1; /* Negotiate endpoint discriminator */ +#endif + u_short mru; /* Value of MRU */ +#ifdef PPP_MULTILINK + u_short mrru; /* Value of MRRU, and multilink enable */ +#endif + u_char chap_mdtype; /* which MD type (hashing algorithm) */ + u32_t asyncmap; /* Value of async map */ + u32_t magicnumber; + int numloops; /* Number of loops during magic number neg. */ + u32_t lqr_period; /* Reporting period for LQR 1/100ths second */ +#ifdef PPP_MULTILINK + struct epdisc endpoint; /* endpoint discriminator */ +#endif +} lcp_options; + +/* + * Values for phase from BSD pppd.h based on RFC 1661. + */ +typedef enum { + PHASE_DEAD = 0, + PHASE_INITIALIZE, + PHASE_ESTABLISH, + PHASE_AUTHENTICATE, + PHASE_CALLBACK, + PHASE_NETWORK, + PHASE_TERMINATE +} LinkPhase; + + + +extern LinkPhase lcp_phase[NUM_PPP]; /* Phase of link session (RFC 1661) */ +extern lcp_options lcp_wantoptions[]; +extern lcp_options lcp_gotoptions[]; +extern lcp_options lcp_allowoptions[]; +extern lcp_options lcp_hisoptions[]; +extern ext_accm xmit_accm[]; + + +void lcp_init (int); +void lcp_open (int); +void lcp_close (int, char *); +void lcp_lowerup (int); +void lcp_lowerdown(int); +void lcp_sprotrej (int, u_char *, int); /* send protocol reject */ + +extern struct protent lcp_protent; + +/* Default number of times we receive our magic number from the peer + before deciding the link is looped-back. */ +#define DEFLOOPBACKFAIL 10 + +#endif /* LCP_H */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/magic.c b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/magic.c new file mode 100644 index 0000000..3732a42 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/magic.c @@ -0,0 +1,80 @@ +/***************************************************************************** +* magic.c - Network Random Number Generator program file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 by Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-12-04 Guy Lancaster , Global Election Systems Inc. +* Original based on BSD magic.c. +*****************************************************************************/ +/* + * magic.c - PPP Magic Number routines. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "lwip/opt.h" + +#if PPP_SUPPORT + +#include "ppp_impl.h" +#include "randm.h" +#include "magic.h" + + +/* + * magicInit - Initialize the magic number generator. + * + * Since we use another random number generator that has its own + * initialization, we do nothing here. + */ +void magicInit() +{ + return; +} + +/* + * magic - Returns the next magic number. + */ +u32_t magic() +{ + return avRandom(); +} + +#endif /* PPP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/magic.h b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/magic.h new file mode 100644 index 0000000..eba70d2 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/magic.h @@ -0,0 +1,63 @@ +/***************************************************************************** +* magic.h - Network Random Number Generator header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-12-04 Guy Lancaster , Global Election Systems Inc. +* Original derived from BSD codes. +*****************************************************************************/ +/* + * magic.h - PPP Magic Number definitions. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * $Id: magic.h,v 1.3 2010/01/18 20:49:43 goldsimon Exp $ + */ + +#ifndef MAGIC_H +#define MAGIC_H + +/* Initialize the magic number generator */ +void magicInit(void); + +/* Returns the next magic number */ +u32_t magic(void); + +#endif /* MAGIC_H */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/md5.c b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/md5.c new file mode 100644 index 0000000..dc3cc75 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/md5.c @@ -0,0 +1,320 @@ +/* + *********************************************************************** + ** md5.c -- the source code for MD5 routines ** + ** RSA Data Security, Inc. MD5 Message-Digest Algorithm ** + ** Created: 2/17/90 RLR ** + ** Revised: 1/91 SRD,AJ,BSK,JT Reference C ver., 7/10 constant corr. ** + *********************************************************************** + */ + +/* + *********************************************************************** + ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. ** + ** ** + ** License to copy and use this software is granted provided that ** + ** it is identified as the "RSA Data Security, Inc. MD5 Message- ** + ** Digest Algorithm" in all material mentioning or referencing this ** + ** software or this function. ** + ** ** + ** License is also granted to make and use derivative works ** + ** provided that such works are identified as "derived from the RSA ** + ** Data Security, Inc. MD5 Message-Digest Algorithm" in all ** + ** material mentioning or referencing the derived work. ** + ** ** + ** RSA Data Security, Inc. makes no representations concerning ** + ** either the merchantability of this software or the suitability ** + ** of this software for any particular purpose. It is provided "as ** + ** is" without express or implied warranty of any kind. ** + ** ** + ** These notices must be retained in any copies of any part of this ** + ** documentation and/or software. ** + *********************************************************************** + */ + +#include "lwip/opt.h" + +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#if CHAP_SUPPORT || MD5_SUPPORT + +#include "ppp_impl.h" +#include "pppdebug.h" + +#include "md5.h" + +#include + +/* + *********************************************************************** + ** Message-digest routines: ** + ** To form the message digest for a message M ** + ** (1) Initialize a context buffer mdContext using MD5Init ** + ** (2) Call MD5Update on mdContext and M ** + ** (3) Call MD5Final on mdContext ** + ** The message digest is now in mdContext->digest[0...15] ** + *********************************************************************** + */ + +/* forward declaration */ +static void Transform (u32_t *buf, u32_t *in); + +static unsigned char PADDING[64] = { + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/* F, G, H and I are basic MD5 functions */ +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) + +/* ROTATE_LEFT rotates x left n bits */ +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */ +/* Rotation is separate from addition to prevent recomputation */ +#define FF(a, b, c, d, x, s, ac) \ + {(a) += F ((b), (c), (d)) + (x) + (u32_t)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define GG(a, b, c, d, x, s, ac) \ + {(a) += G ((b), (c), (d)) + (x) + (u32_t)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define HH(a, b, c, d, x, s, ac) \ + {(a) += H ((b), (c), (d)) + (x) + (u32_t)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define II(a, b, c, d, x, s, ac) \ + {(a) += I ((b), (c), (d)) + (x) + (u32_t)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } + +#ifdef __STDC__ +#define UL(x) x##UL +#else +#ifdef WIN32 +#define UL(x) x##UL +#else +#define UL(x) x +#endif +#endif + +/* The routine MD5Init initializes the message-digest context + mdContext. All fields are set to zero. + */ +void +MD5Init (MD5_CTX *mdContext) +{ + mdContext->i[0] = mdContext->i[1] = (u32_t)0; + + /* Load magic initialization constants. */ + mdContext->buf[0] = (u32_t)0x67452301UL; + mdContext->buf[1] = (u32_t)0xefcdab89UL; + mdContext->buf[2] = (u32_t)0x98badcfeUL; + mdContext->buf[3] = (u32_t)0x10325476UL; +} + +/* The routine MD5Update updates the message-digest context to + account for the presence of each of the characters inBuf[0..inLen-1] + in the message whose digest is being computed. + */ +void +MD5Update(MD5_CTX *mdContext, unsigned char *inBuf, unsigned int inLen) +{ + u32_t in[16]; + int mdi; + unsigned int i, ii; + +#if 0 + PPPDEBUG(LOG_INFO, ("MD5Update: %u:%.*H\n", inLen, LWIP_MIN(inLen, 20) * 2, inBuf)); + PPPDEBUG(LOG_INFO, ("MD5Update: %u:%s\n", inLen, inBuf)); +#endif + + /* compute number of bytes mod 64 */ + mdi = (int)((mdContext->i[0] >> 3) & 0x3F); + + /* update number of bits */ + if ((mdContext->i[0] + ((u32_t)inLen << 3)) < mdContext->i[0]) { + mdContext->i[1]++; + } + mdContext->i[0] += ((u32_t)inLen << 3); + mdContext->i[1] += ((u32_t)inLen >> 29); + + while (inLen--) { + /* add new character to buffer, increment mdi */ + mdContext->in[mdi++] = *inBuf++; + + /* transform if necessary */ + if (mdi == 0x40) { + for (i = 0, ii = 0; i < 16; i++, ii += 4) { + in[i] = (((u32_t)mdContext->in[ii+3]) << 24) | + (((u32_t)mdContext->in[ii+2]) << 16) | + (((u32_t)mdContext->in[ii+1]) << 8) | + ((u32_t)mdContext->in[ii]); + } + Transform (mdContext->buf, in); + mdi = 0; + } + } +} + +/* The routine MD5Final terminates the message-digest computation and + ends with the desired message digest in mdContext->digest[0...15]. + */ +void +MD5Final (unsigned char hash[], MD5_CTX *mdContext) +{ + u32_t in[16]; + int mdi; + unsigned int i, ii; + unsigned int padLen; + + /* save number of bits */ + in[14] = mdContext->i[0]; + in[15] = mdContext->i[1]; + + /* compute number of bytes mod 64 */ + mdi = (int)((mdContext->i[0] >> 3) & 0x3F); + + /* pad out to 56 mod 64 */ + padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi); + MD5Update (mdContext, PADDING, padLen); + + /* append length in bits and transform */ + for (i = 0, ii = 0; i < 14; i++, ii += 4) { + in[i] = (((u32_t)mdContext->in[ii+3]) << 24) | + (((u32_t)mdContext->in[ii+2]) << 16) | + (((u32_t)mdContext->in[ii+1]) << 8) | + ((u32_t)mdContext->in[ii]); + } + Transform (mdContext->buf, in); + + /* store buffer in digest */ + for (i = 0, ii = 0; i < 4; i++, ii += 4) { + mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF); + mdContext->digest[ii+1] = + (unsigned char)((mdContext->buf[i] >> 8) & 0xFF); + mdContext->digest[ii+2] = + (unsigned char)((mdContext->buf[i] >> 16) & 0xFF); + mdContext->digest[ii+3] = + (unsigned char)((mdContext->buf[i] >> 24) & 0xFF); + } + SMEMCPY(hash, mdContext->digest, 16); +} + +/* Basic MD5 step. Transforms buf based on in. + */ +static void +Transform (u32_t *buf, u32_t *in) +{ + u32_t a = buf[0], b = buf[1], c = buf[2], d = buf[3]; + + /* Round 1 */ +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 + FF ( a, b, c, d, in[ 0], S11, UL(3614090360)); /* 1 */ + FF ( d, a, b, c, in[ 1], S12, UL(3905402710)); /* 2 */ + FF ( c, d, a, b, in[ 2], S13, UL( 606105819)); /* 3 */ + FF ( b, c, d, a, in[ 3], S14, UL(3250441966)); /* 4 */ + FF ( a, b, c, d, in[ 4], S11, UL(4118548399)); /* 5 */ + FF ( d, a, b, c, in[ 5], S12, UL(1200080426)); /* 6 */ + FF ( c, d, a, b, in[ 6], S13, UL(2821735955)); /* 7 */ + FF ( b, c, d, a, in[ 7], S14, UL(4249261313)); /* 8 */ + FF ( a, b, c, d, in[ 8], S11, UL(1770035416)); /* 9 */ + FF ( d, a, b, c, in[ 9], S12, UL(2336552879)); /* 10 */ + FF ( c, d, a, b, in[10], S13, UL(4294925233)); /* 11 */ + FF ( b, c, d, a, in[11], S14, UL(2304563134)); /* 12 */ + FF ( a, b, c, d, in[12], S11, UL(1804603682)); /* 13 */ + FF ( d, a, b, c, in[13], S12, UL(4254626195)); /* 14 */ + FF ( c, d, a, b, in[14], S13, UL(2792965006)); /* 15 */ + FF ( b, c, d, a, in[15], S14, UL(1236535329)); /* 16 */ + + /* Round 2 */ +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 + GG ( a, b, c, d, in[ 1], S21, UL(4129170786)); /* 17 */ + GG ( d, a, b, c, in[ 6], S22, UL(3225465664)); /* 18 */ + GG ( c, d, a, b, in[11], S23, UL( 643717713)); /* 19 */ + GG ( b, c, d, a, in[ 0], S24, UL(3921069994)); /* 20 */ + GG ( a, b, c, d, in[ 5], S21, UL(3593408605)); /* 21 */ + GG ( d, a, b, c, in[10], S22, UL( 38016083)); /* 22 */ + GG ( c, d, a, b, in[15], S23, UL(3634488961)); /* 23 */ + GG ( b, c, d, a, in[ 4], S24, UL(3889429448)); /* 24 */ + GG ( a, b, c, d, in[ 9], S21, UL( 568446438)); /* 25 */ + GG ( d, a, b, c, in[14], S22, UL(3275163606)); /* 26 */ + GG ( c, d, a, b, in[ 3], S23, UL(4107603335)); /* 27 */ + GG ( b, c, d, a, in[ 8], S24, UL(1163531501)); /* 28 */ + GG ( a, b, c, d, in[13], S21, UL(2850285829)); /* 29 */ + GG ( d, a, b, c, in[ 2], S22, UL(4243563512)); /* 30 */ + GG ( c, d, a, b, in[ 7], S23, UL(1735328473)); /* 31 */ + GG ( b, c, d, a, in[12], S24, UL(2368359562)); /* 32 */ + + /* Round 3 */ +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 + HH ( a, b, c, d, in[ 5], S31, UL(4294588738)); /* 33 */ + HH ( d, a, b, c, in[ 8], S32, UL(2272392833)); /* 34 */ + HH ( c, d, a, b, in[11], S33, UL(1839030562)); /* 35 */ + HH ( b, c, d, a, in[14], S34, UL(4259657740)); /* 36 */ + HH ( a, b, c, d, in[ 1], S31, UL(2763975236)); /* 37 */ + HH ( d, a, b, c, in[ 4], S32, UL(1272893353)); /* 38 */ + HH ( c, d, a, b, in[ 7], S33, UL(4139469664)); /* 39 */ + HH ( b, c, d, a, in[10], S34, UL(3200236656)); /* 40 */ + HH ( a, b, c, d, in[13], S31, UL( 681279174)); /* 41 */ + HH ( d, a, b, c, in[ 0], S32, UL(3936430074)); /* 42 */ + HH ( c, d, a, b, in[ 3], S33, UL(3572445317)); /* 43 */ + HH ( b, c, d, a, in[ 6], S34, UL( 76029189)); /* 44 */ + HH ( a, b, c, d, in[ 9], S31, UL(3654602809)); /* 45 */ + HH ( d, a, b, c, in[12], S32, UL(3873151461)); /* 46 */ + HH ( c, d, a, b, in[15], S33, UL( 530742520)); /* 47 */ + HH ( b, c, d, a, in[ 2], S34, UL(3299628645)); /* 48 */ + + /* Round 4 */ +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + II ( a, b, c, d, in[ 0], S41, UL(4096336452)); /* 49 */ + II ( d, a, b, c, in[ 7], S42, UL(1126891415)); /* 50 */ + II ( c, d, a, b, in[14], S43, UL(2878612391)); /* 51 */ + II ( b, c, d, a, in[ 5], S44, UL(4237533241)); /* 52 */ + II ( a, b, c, d, in[12], S41, UL(1700485571)); /* 53 */ + II ( d, a, b, c, in[ 3], S42, UL(2399980690)); /* 54 */ + II ( c, d, a, b, in[10], S43, UL(4293915773)); /* 55 */ + II ( b, c, d, a, in[ 1], S44, UL(2240044497)); /* 56 */ + II ( a, b, c, d, in[ 8], S41, UL(1873313359)); /* 57 */ + II ( d, a, b, c, in[15], S42, UL(4264355552)); /* 58 */ + II ( c, d, a, b, in[ 6], S43, UL(2734768916)); /* 59 */ + II ( b, c, d, a, in[13], S44, UL(1309151649)); /* 60 */ + II ( a, b, c, d, in[ 4], S41, UL(4149444226)); /* 61 */ + II ( d, a, b, c, in[11], S42, UL(3174756917)); /* 62 */ + II ( c, d, a, b, in[ 2], S43, UL( 718787259)); /* 63 */ + II ( b, c, d, a, in[ 9], S44, UL(3951481745)); /* 64 */ + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +#endif /* CHAP_SUPPORT || MD5_SUPPORT */ + +#endif /* PPP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/md5.h b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/md5.h new file mode 100644 index 0000000..e129533 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/md5.h @@ -0,0 +1,55 @@ +/* + *********************************************************************** + ** md5.h -- header file for implementation of MD5 ** + ** RSA Data Security, Inc. MD5 Message-Digest Algorithm ** + ** Created: 2/17/90 RLR ** + ** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version ** + ** Revised (for MD5): RLR 4/27/91 ** + ** -- G modified to have y&~z instead of y&z ** + ** -- FF, GG, HH modified to add in last register done ** + ** -- Access pattern: round 2 works mod 5, round 3 works mod 3 ** + ** -- distinct additive constant for each step ** + ** -- round 4 added, working mod 7 ** + *********************************************************************** + */ + +/* + *********************************************************************** + ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. ** + ** ** + ** License to copy and use this software is granted provided that ** + ** it is identified as the "RSA Data Security, Inc. MD5 Message- ** + ** Digest Algorithm" in all material mentioning or referencing this ** + ** software or this function. ** + ** ** + ** License is also granted to make and use derivative works ** + ** provided that such works are identified as "derived from the RSA ** + ** Data Security, Inc. MD5 Message-Digest Algorithm" in all ** + ** material mentioning or referencing the derived work. ** + ** ** + ** RSA Data Security, Inc. makes no representations concerning ** + ** either the merchantability of this software or the suitability ** + ** of this software for any particular purpose. It is provided "as ** + ** is" without express or implied warranty of any kind. ** + ** ** + ** These notices must be retained in any copies of any part of this ** + ** documentation and/or software. ** + *********************************************************************** + */ + +#ifndef MD5_H +#define MD5_H + +/* Data structure for MD5 (Message-Digest) computation */ +typedef struct { + u32_t i[2]; /* number of _bits_ handled mod 2^64 */ + u32_t buf[4]; /* scratch buffer */ + unsigned char in[64]; /* input buffer */ + unsigned char digest[16]; /* actual digest after MD5Final call */ +} MD5_CTX; + +void MD5Init ( MD5_CTX *mdContext); +void MD5Update( MD5_CTX *mdContext, unsigned char *inBuf, unsigned int inLen); +void MD5Final ( unsigned char hash[], MD5_CTX *mdContext); + +#endif /* MD5_H */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/pap.c b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/pap.c new file mode 100644 index 0000000..5fb9f88 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/pap.c @@ -0,0 +1,628 @@ +/***************************************************************************** +* pap.c - Network Password Authentication Protocol program file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 by Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-12-12 Guy Lancaster , Global Election Systems Inc. +* Original. +*****************************************************************************/ +/* + * upap.c - User/Password Authentication Protocol. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "lwip/opt.h" + +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#if PAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "ppp_impl.h" +#include "pppdebug.h" + +#include "auth.h" +#include "pap.h" + +#include + +#if 0 /* UNUSED */ +static bool hide_password = 1; + +/* + * Command-line options. + */ +static option_t pap_option_list[] = { + { "hide-password", o_bool, &hide_password, + "Don't output passwords to log", 1 }, + { "show-password", o_bool, &hide_password, + "Show password string in debug log messages", 0 }, + { "pap-restart", o_int, &upap[0].us_timeouttime, + "Set retransmit timeout for PAP" }, + { "pap-max-authreq", o_int, &upap[0].us_maxtransmits, + "Set max number of transmissions for auth-reqs" }, + { "pap-timeout", o_int, &upap[0].us_reqtimeout, + "Set time limit for peer PAP authentication" }, + { NULL } +}; +#endif + +/* + * Protocol entry points. + */ +static void upap_init (int); +static void upap_lowerup (int); +static void upap_lowerdown (int); +static void upap_input (int, u_char *, int); +static void upap_protrej (int); +#if PPP_ADDITIONAL_CALLBACKS +static int upap_printpkt (u_char *, int, void (*)(void *, char *, ...), void *); +#endif /* PPP_ADDITIONAL_CALLBACKS */ + +struct protent pap_protent = { + PPP_PAP, + upap_init, + upap_input, + upap_protrej, + upap_lowerup, + upap_lowerdown, + NULL, + NULL, +#if PPP_ADDITIONAL_CALLBACKS + upap_printpkt, + NULL, +#endif /* PPP_ADDITIONAL_CALLBACKS */ + 1, + "PAP", +#if PPP_ADDITIONAL_CALLBACKS + NULL, + NULL, + NULL +#endif /* PPP_ADDITIONAL_CALLBACKS */ +}; + +upap_state upap[NUM_PPP]; /* UPAP state; one for each unit */ + +static void upap_timeout (void *); +static void upap_reqtimeout(void *); +static void upap_rauthreq (upap_state *, u_char *, u_char, int); +static void upap_rauthack (upap_state *, u_char *, int, int); +static void upap_rauthnak (upap_state *, u_char *, int, int); +static void upap_sauthreq (upap_state *); +static void upap_sresp (upap_state *, u_char, u_char, char *, int); + + +/* + * upap_init - Initialize a UPAP unit. + */ +static void +upap_init(int unit) +{ + upap_state *u = &upap[unit]; + + UPAPDEBUG(LOG_INFO, ("upap_init: %d\n", unit)); + u->us_unit = unit; + u->us_user = NULL; + u->us_userlen = 0; + u->us_passwd = NULL; + u->us_passwdlen = 0; + u->us_clientstate = UPAPCS_INITIAL; + u->us_serverstate = UPAPSS_INITIAL; + u->us_id = 0; + u->us_timeouttime = UPAP_DEFTIMEOUT; + u->us_maxtransmits = 10; + u->us_reqtimeout = UPAP_DEFREQTIME; +} + +/* + * upap_authwithpeer - Authenticate us with our peer (start client). + * + * Set new state and send authenticate's. + */ +void +upap_authwithpeer(int unit, char *user, char *password) +{ + upap_state *u = &upap[unit]; + + UPAPDEBUG(LOG_INFO, ("upap_authwithpeer: %d user=%s password=%s s=%d\n", + unit, user, password, u->us_clientstate)); + + /* Save the username and password we're given */ + u->us_user = user; + u->us_userlen = (int)strlen(user); + u->us_passwd = password; + u->us_passwdlen = (int)strlen(password); + + u->us_transmits = 0; + + /* Lower layer up yet? */ + if (u->us_clientstate == UPAPCS_INITIAL || + u->us_clientstate == UPAPCS_PENDING) { + u->us_clientstate = UPAPCS_PENDING; + return; + } + + upap_sauthreq(u); /* Start protocol */ +} + + +/* + * upap_authpeer - Authenticate our peer (start server). + * + * Set new state. + */ +void +upap_authpeer(int unit) +{ + upap_state *u = &upap[unit]; + + /* Lower layer up yet? */ + if (u->us_serverstate == UPAPSS_INITIAL || + u->us_serverstate == UPAPSS_PENDING) { + u->us_serverstate = UPAPSS_PENDING; + return; + } + + u->us_serverstate = UPAPSS_LISTEN; + if (u->us_reqtimeout > 0) { + TIMEOUT(upap_reqtimeout, u, u->us_reqtimeout); + } +} + +/* + * upap_timeout - Retransmission timer for sending auth-reqs expired. + */ +static void +upap_timeout(void *arg) +{ + upap_state *u = (upap_state *) arg; + + UPAPDEBUG(LOG_INFO, ("upap_timeout: %d timeout %d expired s=%d\n", + u->us_unit, u->us_timeouttime, u->us_clientstate)); + + if (u->us_clientstate != UPAPCS_AUTHREQ) { + UPAPDEBUG(LOG_INFO, ("upap_timeout: not in AUTHREQ state!\n")); + return; + } + + if (u->us_transmits >= u->us_maxtransmits) { + /* give up in disgust */ + UPAPDEBUG(LOG_ERR, ("No response to PAP authenticate-requests\n")); + u->us_clientstate = UPAPCS_BADAUTH; + auth_withpeer_fail(u->us_unit, PPP_PAP); + return; + } + + upap_sauthreq(u); /* Send Authenticate-Request and set upap timeout*/ +} + + +/* + * upap_reqtimeout - Give up waiting for the peer to send an auth-req. + */ +static void +upap_reqtimeout(void *arg) +{ + upap_state *u = (upap_state *) arg; + + if (u->us_serverstate != UPAPSS_LISTEN) { + return; /* huh?? */ + } + + auth_peer_fail(u->us_unit, PPP_PAP); + u->us_serverstate = UPAPSS_BADAUTH; +} + + +/* + * upap_lowerup - The lower layer is up. + * + * Start authenticating if pending. + */ +static void +upap_lowerup(int unit) +{ + upap_state *u = &upap[unit]; + + UPAPDEBUG(LOG_INFO, ("upap_lowerup: init %d clientstate s=%d\n", unit, u->us_clientstate)); + + if (u->us_clientstate == UPAPCS_INITIAL) { + u->us_clientstate = UPAPCS_CLOSED; + } else if (u->us_clientstate == UPAPCS_PENDING) { + upap_sauthreq(u); /* send an auth-request */ + /* now client state is UPAPCS__AUTHREQ */ + } + + if (u->us_serverstate == UPAPSS_INITIAL) { + u->us_serverstate = UPAPSS_CLOSED; + } else if (u->us_serverstate == UPAPSS_PENDING) { + u->us_serverstate = UPAPSS_LISTEN; + if (u->us_reqtimeout > 0) { + TIMEOUT(upap_reqtimeout, u, u->us_reqtimeout); + } + } +} + + +/* + * upap_lowerdown - The lower layer is down. + * + * Cancel all timeouts. + */ +static void +upap_lowerdown(int unit) +{ + upap_state *u = &upap[unit]; + + UPAPDEBUG(LOG_INFO, ("upap_lowerdown: %d s=%d\n", unit, u->us_clientstate)); + + if (u->us_clientstate == UPAPCS_AUTHREQ) { /* Timeout pending? */ + UNTIMEOUT(upap_timeout, u); /* Cancel timeout */ + } + if (u->us_serverstate == UPAPSS_LISTEN && u->us_reqtimeout > 0) { + UNTIMEOUT(upap_reqtimeout, u); + } + + u->us_clientstate = UPAPCS_INITIAL; + u->us_serverstate = UPAPSS_INITIAL; +} + + +/* + * upap_protrej - Peer doesn't speak this protocol. + * + * This shouldn't happen. In any case, pretend lower layer went down. + */ +static void +upap_protrej(int unit) +{ + upap_state *u = &upap[unit]; + + if (u->us_clientstate == UPAPCS_AUTHREQ) { + UPAPDEBUG(LOG_ERR, ("PAP authentication failed due to protocol-reject\n")); + auth_withpeer_fail(unit, PPP_PAP); + } + if (u->us_serverstate == UPAPSS_LISTEN) { + UPAPDEBUG(LOG_ERR, ("PAP authentication of peer failed (protocol-reject)\n")); + auth_peer_fail(unit, PPP_PAP); + } + upap_lowerdown(unit); +} + + +/* + * upap_input - Input UPAP packet. + */ +static void +upap_input(int unit, u_char *inpacket, int l) +{ + upap_state *u = &upap[unit]; + u_char *inp; + u_char code, id; + int len; + + /* + * Parse header (code, id and length). + * If packet too short, drop it. + */ + inp = inpacket; + if (l < (int)UPAP_HEADERLEN) { + UPAPDEBUG(LOG_INFO, ("pap_input: rcvd short header.\n")); + return; + } + GETCHAR(code, inp); + GETCHAR(id, inp); + GETSHORT(len, inp); + if (len < (int)UPAP_HEADERLEN) { + UPAPDEBUG(LOG_INFO, ("pap_input: rcvd illegal length.\n")); + return; + } + if (len > l) { + UPAPDEBUG(LOG_INFO, ("pap_input: rcvd short packet.\n")); + return; + } + len -= UPAP_HEADERLEN; + + /* + * Action depends on code. + */ + switch (code) { + case UPAP_AUTHREQ: + upap_rauthreq(u, inp, id, len); + break; + + case UPAP_AUTHACK: + upap_rauthack(u, inp, id, len); + break; + + case UPAP_AUTHNAK: + upap_rauthnak(u, inp, id, len); + break; + + default: /* XXX Need code reject */ + UPAPDEBUG(LOG_INFO, ("pap_input: UNHANDLED default: code: %d, id: %d, len: %d.\n", code, id, len)); + break; + } +} + + +/* + * upap_rauth - Receive Authenticate. + */ +static void +upap_rauthreq(upap_state *u, u_char *inp, u_char id, int len) +{ + u_char ruserlen, rpasswdlen; + char *ruser, *rpasswd; + u_char retcode; + char *msg; + int msglen; + + UPAPDEBUG(LOG_INFO, ("pap_rauth: Rcvd id %d.\n", id)); + + if (u->us_serverstate < UPAPSS_LISTEN) { + return; + } + + /* + * If we receive a duplicate authenticate-request, we are + * supposed to return the same status as for the first request. + */ + if (u->us_serverstate == UPAPSS_OPEN) { + upap_sresp(u, UPAP_AUTHACK, id, "", 0); /* return auth-ack */ + return; + } + if (u->us_serverstate == UPAPSS_BADAUTH) { + upap_sresp(u, UPAP_AUTHNAK, id, "", 0); /* return auth-nak */ + return; + } + + /* + * Parse user/passwd. + */ + if (len < (int)sizeof (u_char)) { + UPAPDEBUG(LOG_INFO, ("pap_rauth: rcvd short packet.\n")); + return; + } + GETCHAR(ruserlen, inp); + len -= sizeof (u_char) + ruserlen + sizeof (u_char); + if (len < 0) { + UPAPDEBUG(LOG_INFO, ("pap_rauth: rcvd short packet.\n")); + return; + } + ruser = (char *) inp; + INCPTR(ruserlen, inp); + GETCHAR(rpasswdlen, inp); + if (len < rpasswdlen) { + UPAPDEBUG(LOG_INFO, ("pap_rauth: rcvd short packet.\n")); + return; + } + rpasswd = (char *) inp; + + /* + * Check the username and password given. + */ + retcode = check_passwd(u->us_unit, ruser, ruserlen, rpasswd, rpasswdlen, &msg, &msglen); + /* lwip: currently retcode is always UPAP_AUTHACK */ + BZERO(rpasswd, rpasswdlen); + + upap_sresp(u, retcode, id, msg, msglen); + + if (retcode == UPAP_AUTHACK) { + u->us_serverstate = UPAPSS_OPEN; + auth_peer_success(u->us_unit, PPP_PAP, ruser, ruserlen); + } else { + u->us_serverstate = UPAPSS_BADAUTH; + auth_peer_fail(u->us_unit, PPP_PAP); + } + + if (u->us_reqtimeout > 0) { + UNTIMEOUT(upap_reqtimeout, u); + } +} + + +/* + * upap_rauthack - Receive Authenticate-Ack. + */ +static void +upap_rauthack(upap_state *u, u_char *inp, int id, int len) +{ + u_char msglen; + char *msg; + + LWIP_UNUSED_ARG(id); + + UPAPDEBUG(LOG_INFO, ("pap_rauthack: Rcvd id %d s=%d\n", id, u->us_clientstate)); + + if (u->us_clientstate != UPAPCS_AUTHREQ) { /* XXX */ + UPAPDEBUG(LOG_INFO, ("pap_rauthack: us_clientstate != UPAPCS_AUTHREQ\n")); + return; + } + + /* + * Parse message. + */ + if (len < (int)sizeof (u_char)) { + UPAPDEBUG(LOG_INFO, ("pap_rauthack: ignoring missing msg-length.\n")); + } else { + GETCHAR(msglen, inp); + if (msglen > 0) { + len -= sizeof (u_char); + if (len < msglen) { + UPAPDEBUG(LOG_INFO, ("pap_rauthack: rcvd short packet.\n")); + return; + } + msg = (char *) inp; + PRINTMSG(msg, msglen); + } + } + UNTIMEOUT(upap_timeout, u); /* Cancel timeout */ + u->us_clientstate = UPAPCS_OPEN; + + auth_withpeer_success(u->us_unit, PPP_PAP); +} + + +/* + * upap_rauthnak - Receive Authenticate-Nak. + */ +static void +upap_rauthnak(upap_state *u, u_char *inp, int id, int len) +{ + u_char msglen; + char *msg; + + LWIP_UNUSED_ARG(id); + + UPAPDEBUG(LOG_INFO, ("pap_rauthnak: Rcvd id %d s=%d\n", id, u->us_clientstate)); + + if (u->us_clientstate != UPAPCS_AUTHREQ) { /* XXX */ + return; + } + + /* + * Parse message. + */ + if (len < sizeof (u_char)) { + UPAPDEBUG(LOG_INFO, ("pap_rauthnak: ignoring missing msg-length.\n")); + } else { + GETCHAR(msglen, inp); + if(msglen > 0) { + len -= sizeof (u_char); + if (len < msglen) { + UPAPDEBUG(LOG_INFO, ("pap_rauthnak: rcvd short packet.\n")); + return; + } + msg = (char *) inp; + PRINTMSG(msg, msglen); + } + } + + u->us_clientstate = UPAPCS_BADAUTH; + + UPAPDEBUG(LOG_ERR, ("PAP authentication failed\n")); + auth_withpeer_fail(u->us_unit, PPP_PAP); +} + + +/* + * upap_sauthreq - Send an Authenticate-Request. + */ +static void +upap_sauthreq(upap_state *u) +{ + u_char *outp; + int outlen; + + outlen = UPAP_HEADERLEN + 2 * sizeof (u_char) + + u->us_userlen + u->us_passwdlen; + outp = outpacket_buf[u->us_unit]; + + MAKEHEADER(outp, PPP_PAP); + + PUTCHAR(UPAP_AUTHREQ, outp); + PUTCHAR(++u->us_id, outp); + PUTSHORT(outlen, outp); + PUTCHAR(u->us_userlen, outp); + BCOPY(u->us_user, outp, u->us_userlen); + INCPTR(u->us_userlen, outp); + PUTCHAR(u->us_passwdlen, outp); + BCOPY(u->us_passwd, outp, u->us_passwdlen); + + pppWrite(u->us_unit, outpacket_buf[u->us_unit], outlen + PPP_HDRLEN); + + UPAPDEBUG(LOG_INFO, ("pap_sauth: Sent id %d\n", u->us_id)); + + TIMEOUT(upap_timeout, u, u->us_timeouttime); + ++u->us_transmits; + u->us_clientstate = UPAPCS_AUTHREQ; +} + + +/* + * upap_sresp - Send a response (ack or nak). + */ +static void +upap_sresp(upap_state *u, u_char code, u_char id, char *msg, int msglen) +{ + u_char *outp; + int outlen; + + outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen; + outp = outpacket_buf[u->us_unit]; + MAKEHEADER(outp, PPP_PAP); + + PUTCHAR(code, outp); + PUTCHAR(id, outp); + PUTSHORT(outlen, outp); + PUTCHAR(msglen, outp); + BCOPY(msg, outp, msglen); + pppWrite(u->us_unit, outpacket_buf[u->us_unit], outlen + PPP_HDRLEN); + + UPAPDEBUG(LOG_INFO, ("pap_sresp: Sent code %d, id %d s=%d\n", code, id, u->us_clientstate)); +} + +#if PPP_ADDITIONAL_CALLBACKS +static char *upap_codenames[] = { + "AuthReq", "AuthAck", "AuthNak" +}; + +/* + * upap_printpkt - print the contents of a PAP packet. + */ +static int upap_printpkt( + u_char *p, + int plen, + void (*printer) (void *, char *, ...), + void *arg +) +{ + LWIP_UNUSED_ARG(p); + LWIP_UNUSED_ARG(plen); + LWIP_UNUSED_ARG(printer); + LWIP_UNUSED_ARG(arg); + return 0; +} +#endif /* PPP_ADDITIONAL_CALLBACKS */ + +#endif /* PAP_SUPPORT */ + +#endif /* PPP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/pap.h b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/pap.h new file mode 100644 index 0000000..c99a204 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/pap.h @@ -0,0 +1,118 @@ +/***************************************************************************** +* pap.h - PPP Password Authentication Protocol header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-12-04 Guy Lancaster , Global Election Systems Inc. +* Original derived from BSD codes. +*****************************************************************************/ +/* + * upap.h - User/Password Authentication Protocol definitions. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef PAP_H +#define PAP_H + +#if PAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +/* + * Packet header = Code, id, length. + */ +#define UPAP_HEADERLEN (sizeof (u_char) + sizeof (u_char) + sizeof (u_short)) + + +/* + * UPAP codes. + */ +#define UPAP_AUTHREQ 1 /* Authenticate-Request */ +#define UPAP_AUTHACK 2 /* Authenticate-Ack */ +#define UPAP_AUTHNAK 3 /* Authenticate-Nak */ + +/* + * Each interface is described by upap structure. + */ +typedef struct upap_state { + int us_unit; /* Interface unit number */ + const char *us_user; /* User */ + int us_userlen; /* User length */ + const char *us_passwd; /* Password */ + int us_passwdlen; /* Password length */ + int us_clientstate; /* Client state */ + int us_serverstate; /* Server state */ + u_char us_id; /* Current id */ + int us_timeouttime; /* Timeout (seconds) for auth-req retrans. */ + int us_transmits; /* Number of auth-reqs sent */ + int us_maxtransmits; /* Maximum number of auth-reqs to send */ + int us_reqtimeout; /* Time to wait for auth-req from peer */ +} upap_state; + +/* + * Client states. + */ +#define UPAPCS_INITIAL 0 /* Connection down */ +#define UPAPCS_CLOSED 1 /* Connection up, haven't requested auth */ +#define UPAPCS_PENDING 2 /* Connection down, have requested auth */ +#define UPAPCS_AUTHREQ 3 /* We've sent an Authenticate-Request */ +#define UPAPCS_OPEN 4 /* We've received an Ack */ +#define UPAPCS_BADAUTH 5 /* We've received a Nak */ + +/* + * Server states. + */ +#define UPAPSS_INITIAL 0 /* Connection down */ +#define UPAPSS_CLOSED 1 /* Connection up, haven't requested auth */ +#define UPAPSS_PENDING 2 /* Connection down, have requested auth */ +#define UPAPSS_LISTEN 3 /* Listening for an Authenticate */ +#define UPAPSS_OPEN 4 /* We've sent an Ack */ +#define UPAPSS_BADAUTH 5 /* We've sent a Nak */ + + +extern upap_state upap[]; + +void upap_authwithpeer (int, char *, char *); +void upap_authpeer (int); + +extern struct protent pap_protent; + +#endif /* PAP_SUPPORT */ + +#endif /* PAP_H */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/ppp.c b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/ppp.c new file mode 100644 index 0000000..8e8fae9 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/ppp.c @@ -0,0 +1,2045 @@ +/***************************************************************************** +* ppp.c - Network Point to Point Protocol program file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 by Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-11-05 Guy Lancaster , Global Election Systems Inc. +* Original. +*****************************************************************************/ + +/* + * ppp_defs.h - PPP definitions. + * + * if_pppvar.h - private structures and declarations for PPP. + * + * Copyright (c) 1994 The Australian National University. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, provided that the above copyright + * notice appears in all copies. This software is provided without any + * warranty, express or implied. The Australian National University + * makes no representations about the suitability of this software for + * any purpose. + * + * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY + * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO + * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, + * OR MODIFICATIONS. + */ + +/* + * if_ppp.h - Point-to-Point Protocol definitions. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "lwip/opt.h" + +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "ppp_impl.h" +#include "lwip/ip.h" /* for ip_input() */ + +#include "pppdebug.h" + +#include "randm.h" +#include "fsm.h" +#if PAP_SUPPORT +#include "pap.h" +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT +#include "chap.h" +#endif /* CHAP_SUPPORT */ +#include "ipcp.h" +#include "lcp.h" +#include "magic.h" +#include "auth.h" +#if VJ_SUPPORT +#include "vj.h" +#endif /* VJ_SUPPORT */ +#if PPPOE_SUPPORT +#include "netif/ppp_oe.h" +#endif /* PPPOE_SUPPORT */ + +#include "lwip/tcpip.h" +#include "lwip/api.h" +#include "lwip/snmp.h" + +#include + +/*************************/ +/*** LOCAL DEFINITIONS ***/ +/*************************/ + +/** PPP_INPROC_MULTITHREADED==1 call pppInput using tcpip_callback(). + * Set this to 0 if pppInProc is called inside tcpip_thread or with NO_SYS==1. + * Default is 1 for NO_SYS==0 (multithreaded) and 0 for NO_SYS==1 (single-threaded). + */ +#ifndef PPP_INPROC_MULTITHREADED +#define PPP_INPROC_MULTITHREADED (NO_SYS==0) +#endif + +/** PPP_INPROC_OWNTHREAD==1: start a dedicated RX thread per PPP session. + * Default is 0: call pppos_input() for received raw characters, charcater + * reception is up to the port */ +#ifndef PPP_INPROC_OWNTHREAD +#define PPP_INPROC_OWNTHREAD PPP_INPROC_MULTITHREADED +#endif + +#if PPP_INPROC_OWNTHREAD && !PPP_INPROC_MULTITHREADED + #error "PPP_INPROC_OWNTHREAD needs PPP_INPROC_MULTITHREADED==1" +#endif + +/* + * The basic PPP frame. + */ +#define PPP_ADDRESS(p) (((u_char *)(p))[0]) +#define PPP_CONTROL(p) (((u_char *)(p))[1]) +#define PPP_PROTOCOL(p) ((((u_char *)(p))[2] << 8) + ((u_char *)(p))[3]) + +/* PPP packet parser states. Current state indicates operation yet to be + * completed. */ +typedef enum { + PDIDLE = 0, /* Idle state - waiting. */ + PDSTART, /* Process start flag. */ + PDADDRESS, /* Process address field. */ + PDCONTROL, /* Process control field. */ + PDPROTOCOL1, /* Process protocol field 1. */ + PDPROTOCOL2, /* Process protocol field 2. */ + PDDATA /* Process data byte. */ +} PPPDevStates; + +#define ESCAPE_P(accm, c) ((accm)[(c) >> 3] & pppACCMMask[c & 0x07]) + +/************************/ +/*** LOCAL DATA TYPES ***/ +/************************/ + +/** RX buffer size: this may be configured smaller! */ +#ifndef PPPOS_RX_BUFSIZE +#define PPPOS_RX_BUFSIZE (PPP_MRU + PPP_HDRLEN) +#endif + +typedef struct PPPControlRx_s { + /** unit number / ppp descriptor */ + int pd; + /** the rx file descriptor */ + sio_fd_t fd; + /** receive buffer - encoded data is stored here */ +#if PPP_INPROC_OWNTHREAD + u_char rxbuf[PPPOS_RX_BUFSIZE]; +#endif /* PPP_INPROC_OWNTHREAD */ + + /* The input packet. */ + struct pbuf *inHead, *inTail; + +#if PPPOS_SUPPORT + u16_t inProtocol; /* The input protocol code. */ + u16_t inFCS; /* Input Frame Check Sequence value. */ +#endif /* PPPOS_SUPPORT */ + PPPDevStates inState; /* The input process state. */ + char inEscaped; /* Escape next character. */ + ext_accm inACCM; /* Async-Ctl-Char-Map for input. */ +} PPPControlRx; + +/* + * PPP interface control block. + */ +typedef struct PPPControl_s { + PPPControlRx rx; + char openFlag; /* True when in use. */ +#if PPPOE_SUPPORT + struct netif *ethif; + struct pppoe_softc *pppoe_sc; +#endif /* PPPOE_SUPPORT */ + int if_up; /* True when the interface is up. */ + int errCode; /* Code indicating why interface is down. */ +#if PPPOS_SUPPORT + sio_fd_t fd; /* File device ID of port. */ +#endif /* PPPOS_SUPPORT */ + u16_t mtu; /* Peer's mru */ + int pcomp; /* Does peer accept protocol compression? */ + int accomp; /* Does peer accept addr/ctl compression? */ + u_long lastXMit; /* Time of last transmission. */ + ext_accm outACCM; /* Async-Ctl-Char-Map for output. */ +#if PPPOS_SUPPORT && VJ_SUPPORT + int vjEnabled; /* Flag indicating VJ compression enabled. */ + struct vjcompress vjComp; /* Van Jacobson compression header. */ +#endif /* PPPOS_SUPPORT && VJ_SUPPORT */ + + struct netif netif; + + struct ppp_addrs addrs; + + void (*linkStatusCB)(void *ctx, int errCode, void *arg); + void *linkStatusCtx; + +} PPPControl; + + +/* + * Ioctl definitions. + */ + +struct npioctl { + int protocol; /* PPP procotol, e.g. PPP_IP */ + enum NPmode mode; +}; + + + +/***********************************/ +/*** LOCAL FUNCTION DECLARATIONS ***/ +/***********************************/ +#if PPPOS_SUPPORT +#if PPP_INPROC_OWNTHREAD +static void pppInputThread(void *arg); +#endif /* PPP_INPROC_OWNTHREAD */ +static void pppDrop(PPPControlRx *pcrx); +static void pppInProc(PPPControlRx *pcrx, u_char *s, int l); +static void pppFreeCurrentInputPacket(PPPControlRx *pcrx); +#endif /* PPPOS_SUPPORT */ + + +/******************************/ +/*** PUBLIC DATA STRUCTURES ***/ +/******************************/ +u_long subnetMask; + +static PPPControl pppControl[NUM_PPP]; /* The PPP interface control blocks. */ + +/* + * PPP Data Link Layer "protocol" table. + * One entry per supported protocol. + * The last entry must be NULL. + */ +struct protent *ppp_protocols[] = { + &lcp_protent, +#if PAP_SUPPORT + &pap_protent, +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + &chap_protent, +#endif /* CHAP_SUPPORT */ +#if CBCP_SUPPORT + &cbcp_protent, +#endif /* CBCP_SUPPORT */ + &ipcp_protent, +#if CCP_SUPPORT + &ccp_protent, +#endif /* CCP_SUPPORT */ + NULL +}; + + +/* + * Buffers for outgoing packets. This must be accessed only from the appropriate + * PPP task so that it doesn't need to be protected to avoid collisions. + */ +u_char outpacket_buf[NUM_PPP][PPP_MRU+PPP_HDRLEN]; + + +/*****************************/ +/*** LOCAL DATA STRUCTURES ***/ +/*****************************/ + +#if PPPOS_SUPPORT +/* + * FCS lookup table as calculated by genfcstab. + * @todo: smaller, slower implementation for lower memory footprint? + */ +static const u_short fcstab[256] = { + 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, + 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, + 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, + 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, + 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, + 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, + 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, + 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, + 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, + 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, + 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, + 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, + 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, + 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, + 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, + 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, + 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, + 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, + 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, + 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, + 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, + 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, + 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, + 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, + 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, + 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, + 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, + 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, + 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, + 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, + 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 +}; + +/* PPP's Asynchronous-Control-Character-Map. The mask array is used + * to select the specific bit for a character. */ +static u_char pppACCMMask[] = { + 0x01, + 0x02, + 0x04, + 0x08, + 0x10, + 0x20, + 0x40, + 0x80 +}; + +#if PPP_INPROC_OWNTHREAD +/** Wake up the task blocked in reading from serial line (if any) */ +static void +pppRecvWakeup(int pd) +{ + PPPDEBUG(LOG_DEBUG, ("pppRecvWakeup: unit %d\n", pd)); + if (pppControl[pd].openFlag != 0) { + sio_read_abort(pppControl[pd].fd); + } +} +#endif /* PPP_INPROC_OWNTHREAD */ +#endif /* PPPOS_SUPPORT */ + +void +pppLinkTerminated(int pd) +{ + PPPDEBUG(LOG_DEBUG, ("pppLinkTerminated: unit %d\n", pd)); + +#if PPPOE_SUPPORT + if (pppControl[pd].ethif) { + pppoe_disconnect(pppControl[pd].pppoe_sc); + } else +#endif /* PPPOE_SUPPORT */ + { +#if PPPOS_SUPPORT + PPPControl* pc; +#if PPP_INPROC_OWNTHREAD + pppRecvWakeup(pd); +#endif /* PPP_INPROC_OWNTHREAD */ + pc = &pppControl[pd]; + + PPPDEBUG(LOG_DEBUG, ("pppLinkTerminated: unit %d: linkStatusCB=%p errCode=%d\n", pd, pc->linkStatusCB, pc->errCode)); + if (pc->linkStatusCB) { + pc->linkStatusCB(pc->linkStatusCtx, pc->errCode ? pc->errCode : PPPERR_PROTOCOL, NULL); + } + + pc->openFlag = 0;/**/ +#endif /* PPPOS_SUPPORT */ + } + PPPDEBUG(LOG_DEBUG, ("pppLinkTerminated: finished.\n")); +} + +void +pppLinkDown(int pd) +{ + PPPDEBUG(LOG_DEBUG, ("pppLinkDown: unit %d\n", pd)); + +#if PPPOE_SUPPORT + if (pppControl[pd].ethif) { + pppoe_disconnect(pppControl[pd].pppoe_sc); + } else +#endif /* PPPOE_SUPPORT */ + { +#if PPPOS_SUPPORT && PPP_INPROC_OWNTHREAD + pppRecvWakeup(pd); +#endif /* PPPOS_SUPPORT && PPP_INPROC_OWNTHREAD*/ + } +} + +/** Initiate LCP open request */ +static void +pppStart(int pd) +{ + PPPDEBUG(LOG_DEBUG, ("pppStart: unit %d\n", pd)); + lcp_lowerup(pd); + lcp_open(pd); /* Start protocol */ + PPPDEBUG(LOG_DEBUG, ("pppStart: finished\n")); +} + +/** LCP close request */ +static void +pppStop(int pd) +{ + PPPDEBUG(LOG_DEBUG, ("pppStop: unit %d\n", pd)); + lcp_close(pd, "User request"); +} + +/** Called when carrier/link is lost */ +static void +pppHup(int pd) +{ + PPPDEBUG(LOG_DEBUG, ("pppHupCB: unit %d\n", pd)); + lcp_lowerdown(pd); + link_terminated(pd); +} + +/***********************************/ +/*** PUBLIC FUNCTION DEFINITIONS ***/ +/***********************************/ +/* Initialize the PPP subsystem. */ + +struct ppp_settings ppp_settings; + +void +pppInit(void) +{ + struct protent *protp; + int i, j; + + memset(&ppp_settings, 0, sizeof(ppp_settings)); + ppp_settings.usepeerdns = 1; + pppSetAuth(PPPAUTHTYPE_NONE, NULL, NULL); + + magicInit(); + + subnetMask = PP_HTONL(0xffffff00UL); + + for (i = 0; i < NUM_PPP; i++) { + /* Initialize each protocol to the standard option set. */ + for (j = 0; (protp = ppp_protocols[j]) != NULL; ++j) { + (*protp->init)(i); + } + } +} + +void +pppSetAuth(enum pppAuthType authType, const char *user, const char *passwd) +{ + switch(authType) { + case PPPAUTHTYPE_NONE: + default: +#ifdef LWIP_PPP_STRICT_PAP_REJECT + ppp_settings.refuse_pap = 1; +#else /* LWIP_PPP_STRICT_PAP_REJECT */ + /* some providers request pap and accept an empty login/pw */ + ppp_settings.refuse_pap = 0; +#endif /* LWIP_PPP_STRICT_PAP_REJECT */ + ppp_settings.refuse_chap = 1; + break; + + case PPPAUTHTYPE_ANY: + /* Warning: Using PPPAUTHTYPE_ANY might have security consequences. + * RFC 1994 says: + * + * In practice, within or associated with each PPP server, there is a + * database which associates "user" names with authentication + * information ("secrets"). It is not anticipated that a particular + * named user would be authenticated by multiple methods. This would + * make the user vulnerable to attacks which negotiate the least secure + * method from among a set (such as PAP rather than CHAP). If the same + * secret was used, PAP would reveal the secret to be used later with + * CHAP. + * + * Instead, for each user name there should be an indication of exactly + * one method used to authenticate that user name. If a user needs to + * make use of different authentication methods under different + * circumstances, then distinct user names SHOULD be employed, each of + * which identifies exactly one authentication method. + * + */ + ppp_settings.refuse_pap = 0; + ppp_settings.refuse_chap = 0; + break; + + case PPPAUTHTYPE_PAP: + ppp_settings.refuse_pap = 0; + ppp_settings.refuse_chap = 1; + break; + + case PPPAUTHTYPE_CHAP: + ppp_settings.refuse_pap = 1; + ppp_settings.refuse_chap = 0; + break; + } + + if(user) { + strncpy(ppp_settings.user, user, sizeof(ppp_settings.user)-1); + ppp_settings.user[sizeof(ppp_settings.user)-1] = '\0'; + } else { + ppp_settings.user[0] = '\0'; + } + + if(passwd) { + strncpy(ppp_settings.passwd, passwd, sizeof(ppp_settings.passwd)-1); + ppp_settings.passwd[sizeof(ppp_settings.passwd)-1] = '\0'; + } else { + ppp_settings.passwd[0] = '\0'; + } +} + +#if PPPOS_SUPPORT +/** Open a new PPP connection using the given I/O device. + * This initializes the PPP control block but does not + * attempt to negotiate the LCP session. If this port + * connects to a modem, the modem connection must be + * established before calling this. + * Return a new PPP connection descriptor on success or + * an error code (negative) on failure. + * + * pppOpen() is directly defined to this function. + */ +int +pppOverSerialOpen(sio_fd_t fd, pppLinkStatusCB_fn linkStatusCB, void *linkStatusCtx) +{ + PPPControl *pc; + int pd; + + if (linkStatusCB == NULL) { + /* PPP is single-threaded: without a callback, + * there is no way to know when the link is up. */ + return PPPERR_PARAM; + } + + /* Find a free PPP session descriptor. */ + for (pd = 0; pd < NUM_PPP && pppControl[pd].openFlag != 0; pd++); + + if (pd >= NUM_PPP) { + pd = PPPERR_OPEN; + } else { + pc = &pppControl[pd]; + /* input pbuf left over from last session? */ + pppFreeCurrentInputPacket(&pc->rx); + /* @todo: is this correct or do I overwrite something? */ + memset(pc, 0, sizeof(PPPControl)); + pc->rx.pd = pd; + pc->rx.fd = fd; + + pc->openFlag = 1; + pc->fd = fd; + +#if VJ_SUPPORT + vj_compress_init(&pc->vjComp); +#endif /* VJ_SUPPORT */ + + /* + * Default the in and out accm so that escape and flag characters + * are always escaped. + */ + pc->rx.inACCM[15] = 0x60; /* no need to protect since RX is not running */ + pc->outACCM[15] = 0x60; + + pc->linkStatusCB = linkStatusCB; + pc->linkStatusCtx = linkStatusCtx; + + /* + * Start the connection and handle incoming events (packet or timeout). + */ + PPPDEBUG(LOG_INFO, ("pppOverSerialOpen: unit %d: Connecting\n", pd)); + pppStart(pd); +#if PPP_INPROC_OWNTHREAD + sys_thread_new(PPP_THREAD_NAME, pppInputThread, (void*)&pc->rx, PPP_THREAD_STACKSIZE, PPP_THREAD_PRIO); +#endif /* PPP_INPROC_OWNTHREAD */ + } + + return pd; +} +#endif /* PPPOS_SUPPORT */ + +#if PPPOE_SUPPORT +static void pppOverEthernetLinkStatusCB(int pd, int up); + +void +pppOverEthernetClose(int pd) +{ + PPPControl* pc = &pppControl[pd]; + + /* *TJL* There's no lcp_deinit */ + lcp_close(pd, NULL); + + pppoe_destroy(&pc->netif); +} + +int pppOverEthernetOpen(struct netif *ethif, const char *service_name, const char *concentrator_name, + pppLinkStatusCB_fn linkStatusCB, void *linkStatusCtx) +{ + PPPControl *pc; + int pd; + + LWIP_UNUSED_ARG(service_name); + LWIP_UNUSED_ARG(concentrator_name); + + if (linkStatusCB == NULL) { + /* PPP is single-threaded: without a callback, + * there is no way to know when the link is up. */ + return PPPERR_PARAM; + } + + /* Find a free PPP session descriptor. Critical region? */ + for (pd = 0; pd < NUM_PPP && pppControl[pd].openFlag != 0; pd++); + if (pd >= NUM_PPP) { + pd = PPPERR_OPEN; + } else { + pc = &pppControl[pd]; + memset(pc, 0, sizeof(PPPControl)); + pc->openFlag = 1; + pc->ethif = ethif; + + pc->linkStatusCB = linkStatusCB; + pc->linkStatusCtx = linkStatusCtx; + + lcp_wantoptions[pd].mru = PPPOE_MAXMTU; + lcp_wantoptions[pd].neg_asyncmap = 0; + lcp_wantoptions[pd].neg_pcompression = 0; + lcp_wantoptions[pd].neg_accompression = 0; + + lcp_allowoptions[pd].mru = PPPOE_MAXMTU; + lcp_allowoptions[pd].neg_asyncmap = 0; + lcp_allowoptions[pd].neg_pcompression = 0; + lcp_allowoptions[pd].neg_accompression = 0; + + if(pppoe_create(ethif, pd, pppOverEthernetLinkStatusCB, &pc->pppoe_sc) != ERR_OK) { + pc->openFlag = 0; + return PPPERR_OPEN; + } + + pppoe_connect(pc->pppoe_sc); + } + + return pd; +} +#endif /* PPPOE_SUPPORT */ + + +/* Close a PPP connection and release the descriptor. + * Any outstanding packets in the queues are dropped. + * Return 0 on success, an error code on failure. */ +int +pppClose(int pd) +{ + PPPControl *pc = &pppControl[pd]; + int st = 0; + + PPPDEBUG(LOG_DEBUG, ("pppClose() called\n")); + + /* Disconnect */ +#if PPPOE_SUPPORT + if(pc->ethif) { + PPPDEBUG(LOG_DEBUG, ("pppClose: unit %d kill_link -> pppStop\n", pd)); + pc->errCode = PPPERR_USER; + /* This will leave us at PHASE_DEAD. */ + pppStop(pd); + } else +#endif /* PPPOE_SUPPORT */ + { +#if PPPOS_SUPPORT + PPPDEBUG(LOG_DEBUG, ("pppClose: unit %d kill_link -> pppStop\n", pd)); + pc->errCode = PPPERR_USER; + /* This will leave us at PHASE_DEAD. */ + pppStop(pd); +#if PPP_INPROC_OWNTHREAD + pppRecvWakeup(pd); +#endif /* PPP_INPROC_OWNTHREAD */ +#endif /* PPPOS_SUPPORT */ + } + + return st; +} + +/* This function is called when carrier is lost on the PPP channel. */ +void +pppSigHUP(int pd) +{ + PPPDEBUG(LOG_DEBUG, ("pppSigHUP: unit %d sig_hup -> pppHupCB\n", pd)); + pppHup(pd); +} + +#if PPPOS_SUPPORT +static void +nPut(PPPControl *pc, struct pbuf *nb) +{ + struct pbuf *b; + int c; + + for(b = nb; b != NULL; b = b->next) { + if((c = sio_write(pc->fd, b->payload, b->len)) != b->len) { + PPPDEBUG(LOG_WARNING, + ("PPP nPut: incomplete sio_write(fd:%"SZT_F", len:%d, c: 0x%"X8_F") c = %d\n", (size_t)pc->fd, b->len, c, c)); + LINK_STATS_INC(link.err); + pc->lastXMit = 0; /* prepend PPP_FLAG to next packet */ + snmp_inc_ifoutdiscards(&pc->netif); + pbuf_free(nb); + return; + } + } + + snmp_add_ifoutoctets(&pc->netif, nb->tot_len); + snmp_inc_ifoutucastpkts(&pc->netif); + pbuf_free(nb); + LINK_STATS_INC(link.xmit); +} + +/* + * pppAppend - append given character to end of given pbuf. If outACCM + * is not NULL and the character needs to be escaped, do so. + * If pbuf is full, append another. + * Return the current pbuf. + */ +static struct pbuf * +pppAppend(u_char c, struct pbuf *nb, ext_accm *outACCM) +{ + struct pbuf *tb = nb; + + /* Make sure there is room for the character and an escape code. + * Sure we don't quite fill the buffer if the character doesn't + * get escaped but is one character worth complicating this? */ + /* Note: We assume no packet header. */ + if (nb && (PBUF_POOL_BUFSIZE - nb->len) < 2) { + tb = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); + if (tb) { + nb->next = tb; + } else { + LINK_STATS_INC(link.memerr); + } + nb = tb; + } + + if (nb) { + if (outACCM && ESCAPE_P(*outACCM, c)) { + *((u_char*)nb->payload + nb->len++) = PPP_ESCAPE; + *((u_char*)nb->payload + nb->len++) = c ^ PPP_TRANS; + } else { + *((u_char*)nb->payload + nb->len++) = c; + } + } + + return tb; +} +#endif /* PPPOS_SUPPORT */ + +#if PPPOE_SUPPORT +static err_t +pppifOutputOverEthernet(int pd, struct pbuf *p) +{ + PPPControl *pc = &pppControl[pd]; + struct pbuf *pb; + u_short protocol = PPP_IP; + int i=0; + u16_t tot_len; + + /* @todo: try to use pbuf_header() here! */ + pb = pbuf_alloc(PBUF_LINK, PPPOE_HDRLEN + sizeof(protocol), PBUF_RAM); + if(!pb) { + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.proterr); + snmp_inc_ifoutdiscards(&pc->netif); + return ERR_MEM; + } + + pbuf_header(pb, -(s16_t)PPPOE_HDRLEN); + + pc->lastXMit = sys_jiffies(); + + if (!pc->pcomp || protocol > 0xFF) { + *((u_char*)pb->payload + i++) = (protocol >> 8) & 0xFF; + } + *((u_char*)pb->payload + i) = protocol & 0xFF; + + pbuf_chain(pb, p); + tot_len = pb->tot_len; + + if(pppoe_xmit(pc->pppoe_sc, pb) != ERR_OK) { + LINK_STATS_INC(link.err); + snmp_inc_ifoutdiscards(&pc->netif); + return PPPERR_DEVICE; + } + + snmp_add_ifoutoctets(&pc->netif, tot_len); + snmp_inc_ifoutucastpkts(&pc->netif); + LINK_STATS_INC(link.xmit); + return ERR_OK; +} +#endif /* PPPOE_SUPPORT */ + +/* Send a packet on the given connection. */ +static err_t +pppifOutput(struct netif *netif, struct pbuf *pb, ip_addr_t *ipaddr) +{ + int pd = (int)(size_t)netif->state; + PPPControl *pc = &pppControl[pd]; +#if PPPOS_SUPPORT + u_short protocol = PPP_IP; + u_int fcsOut = PPP_INITFCS; + struct pbuf *headMB = NULL, *tailMB = NULL, *p; + u_char c; +#endif /* PPPOS_SUPPORT */ + + LWIP_UNUSED_ARG(ipaddr); + + /* Validate parameters. */ + /* We let any protocol value go through - it can't hurt us + * and the peer will just drop it if it's not accepting it. */ + if (pd < 0 || pd >= NUM_PPP || !pc->openFlag || !pb) { + PPPDEBUG(LOG_WARNING, ("pppifOutput[%d]: bad parms prot=%d pb=%p\n", + pd, PPP_IP, pb)); + LINK_STATS_INC(link.opterr); + LINK_STATS_INC(link.drop); + snmp_inc_ifoutdiscards(netif); + return ERR_ARG; + } + + /* Check that the link is up. */ + if (lcp_phase[pd] == PHASE_DEAD) { + PPPDEBUG(LOG_ERR, ("pppifOutput[%d]: link not up\n", pd)); + LINK_STATS_INC(link.rterr); + LINK_STATS_INC(link.drop); + snmp_inc_ifoutdiscards(netif); + return ERR_RTE; + } + +#if PPPOE_SUPPORT + if(pc->ethif) { + return pppifOutputOverEthernet(pd, pb); + } +#endif /* PPPOE_SUPPORT */ + +#if PPPOS_SUPPORT + /* Grab an output buffer. */ + headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); + if (headMB == NULL) { + PPPDEBUG(LOG_WARNING, ("pppifOutput[%d]: first alloc fail\n", pd)); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + snmp_inc_ifoutdiscards(netif); + return ERR_MEM; + } + +#if VJ_SUPPORT + /* + * Attempt Van Jacobson header compression if VJ is configured and + * this is an IP packet. + */ + if (protocol == PPP_IP && pc->vjEnabled) { + switch (vj_compress_tcp(&pc->vjComp, pb)) { + case TYPE_IP: + /* No change... + protocol = PPP_IP_PROTOCOL; */ + break; + case TYPE_COMPRESSED_TCP: + protocol = PPP_VJC_COMP; + break; + case TYPE_UNCOMPRESSED_TCP: + protocol = PPP_VJC_UNCOMP; + break; + default: + PPPDEBUG(LOG_WARNING, ("pppifOutput[%d]: bad IP packet\n", pd)); + LINK_STATS_INC(link.proterr); + LINK_STATS_INC(link.drop); + snmp_inc_ifoutdiscards(netif); + pbuf_free(headMB); + return ERR_VAL; + } + } +#endif /* VJ_SUPPORT */ + + tailMB = headMB; + + /* Build the PPP header. */ + if ((sys_jiffies() - pc->lastXMit) >= PPP_MAXIDLEFLAG) { + tailMB = pppAppend(PPP_FLAG, tailMB, NULL); + } + + pc->lastXMit = sys_jiffies(); + if (!pc->accomp) { + fcsOut = PPP_FCS(fcsOut, PPP_ALLSTATIONS); + tailMB = pppAppend(PPP_ALLSTATIONS, tailMB, &pc->outACCM); + fcsOut = PPP_FCS(fcsOut, PPP_UI); + tailMB = pppAppend(PPP_UI, tailMB, &pc->outACCM); + } + if (!pc->pcomp || protocol > 0xFF) { + c = (protocol >> 8) & 0xFF; + fcsOut = PPP_FCS(fcsOut, c); + tailMB = pppAppend(c, tailMB, &pc->outACCM); + } + c = protocol & 0xFF; + fcsOut = PPP_FCS(fcsOut, c); + tailMB = pppAppend(c, tailMB, &pc->outACCM); + + /* Load packet. */ + for(p = pb; p; p = p->next) { + int n; + u_char *sPtr; + + sPtr = (u_char*)p->payload; + n = p->len; + while (n-- > 0) { + c = *sPtr++; + + /* Update FCS before checking for special characters. */ + fcsOut = PPP_FCS(fcsOut, c); + + /* Copy to output buffer escaping special characters. */ + tailMB = pppAppend(c, tailMB, &pc->outACCM); + } + } + + /* Add FCS and trailing flag. */ + c = ~fcsOut & 0xFF; + tailMB = pppAppend(c, tailMB, &pc->outACCM); + c = (~fcsOut >> 8) & 0xFF; + tailMB = pppAppend(c, tailMB, &pc->outACCM); + tailMB = pppAppend(PPP_FLAG, tailMB, NULL); + + /* If we failed to complete the packet, throw it away. */ + if (!tailMB) { + PPPDEBUG(LOG_WARNING, + ("pppifOutput[%d]: Alloc err - dropping proto=%d\n", + pd, protocol)); + pbuf_free(headMB); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + snmp_inc_ifoutdiscards(netif); + return ERR_MEM; + } + + /* Send it. */ + PPPDEBUG(LOG_INFO, ("pppifOutput[%d]: proto=0x%"X16_F"\n", pd, protocol)); + + nPut(pc, headMB); +#endif /* PPPOS_SUPPORT */ + + return ERR_OK; +} + +/* Get and set parameters for the given connection. + * Return 0 on success, an error code on failure. */ +int +pppIOCtl(int pd, int cmd, void *arg) +{ + PPPControl *pc = &pppControl[pd]; + int st = 0; + + if (pd < 0 || pd >= NUM_PPP) { + st = PPPERR_PARAM; + } else { + switch(cmd) { + case PPPCTLG_UPSTATUS: /* Get the PPP up status. */ + if (arg) { + *(int *)arg = (int)(pc->if_up); + } else { + st = PPPERR_PARAM; + } + break; + case PPPCTLS_ERRCODE: /* Set the PPP error code. */ + if (arg) { + pc->errCode = *(int *)arg; + } else { + st = PPPERR_PARAM; + } + break; + case PPPCTLG_ERRCODE: /* Get the PPP error code. */ + if (arg) { + *(int *)arg = (int)(pc->errCode); + } else { + st = PPPERR_PARAM; + } + break; +#if PPPOS_SUPPORT + case PPPCTLG_FD: /* Get the fd associated with the ppp */ + if (arg) { + *(sio_fd_t *)arg = pc->fd; + } else { + st = PPPERR_PARAM; + } + break; +#endif /* PPPOS_SUPPORT */ + default: + st = PPPERR_PARAM; + break; + } + } + + return st; +} + +/* + * Return the Maximum Transmission Unit for the given PPP connection. + */ +u_short +pppMTU(int pd) +{ + PPPControl *pc = &pppControl[pd]; + u_short st; + + /* Validate parameters. */ + if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { + st = 0; + } else { + st = pc->mtu; + } + + return st; +} + +#if PPPOE_SUPPORT +int +pppWriteOverEthernet(int pd, const u_char *s, int n) +{ + PPPControl *pc = &pppControl[pd]; + struct pbuf *pb; + + /* skip address & flags */ + s += 2; + n -= 2; + + LWIP_ASSERT("PPPOE_HDRLEN + n <= 0xffff", PPPOE_HDRLEN + n <= 0xffff); + pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HDRLEN + n), PBUF_RAM); + if(!pb) { + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.proterr); + snmp_inc_ifoutdiscards(&pc->netif); + return PPPERR_ALLOC; + } + + pbuf_header(pb, -(s16_t)PPPOE_HDRLEN); + + pc->lastXMit = sys_jiffies(); + + MEMCPY(pb->payload, s, n); + + if(pppoe_xmit(pc->pppoe_sc, pb) != ERR_OK) { + LINK_STATS_INC(link.err); + snmp_inc_ifoutdiscards(&pc->netif); + return PPPERR_DEVICE; + } + + snmp_add_ifoutoctets(&pc->netif, (u16_t)n); + snmp_inc_ifoutucastpkts(&pc->netif); + LINK_STATS_INC(link.xmit); + return PPPERR_NONE; +} +#endif /* PPPOE_SUPPORT */ + +/* + * Write n characters to a ppp link. + * RETURN: >= 0 Number of characters written + * -1 Failed to write to device + */ +int +pppWrite(int pd, const u_char *s, int n) +{ + PPPControl *pc = &pppControl[pd]; +#if PPPOS_SUPPORT + u_char c; + u_int fcsOut; + struct pbuf *headMB, *tailMB; +#endif /* PPPOS_SUPPORT */ + +#if PPPOE_SUPPORT + if(pc->ethif) { + return pppWriteOverEthernet(pd, s, n); + } +#endif /* PPPOE_SUPPORT */ + +#if PPPOS_SUPPORT + headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); + if (headMB == NULL) { + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.proterr); + snmp_inc_ifoutdiscards(&pc->netif); + return PPPERR_ALLOC; + } + + tailMB = headMB; + + /* If the link has been idle, we'll send a fresh flag character to + * flush any noise. */ + if ((sys_jiffies() - pc->lastXMit) >= PPP_MAXIDLEFLAG) { + tailMB = pppAppend(PPP_FLAG, tailMB, NULL); + } + pc->lastXMit = sys_jiffies(); + + fcsOut = PPP_INITFCS; + /* Load output buffer. */ + while (n-- > 0) { + c = *s++; + + /* Update FCS before checking for special characters. */ + fcsOut = PPP_FCS(fcsOut, c); + + /* Copy to output buffer escaping special characters. */ + tailMB = pppAppend(c, tailMB, &pc->outACCM); + } + + /* Add FCS and trailing flag. */ + c = ~fcsOut & 0xFF; + tailMB = pppAppend(c, tailMB, &pc->outACCM); + c = (~fcsOut >> 8) & 0xFF; + tailMB = pppAppend(c, tailMB, &pc->outACCM); + tailMB = pppAppend(PPP_FLAG, tailMB, NULL); + + /* If we failed to complete the packet, throw it away. + * Otherwise send it. */ + if (!tailMB) { + PPPDEBUG(LOG_WARNING, + ("pppWrite[%d]: Alloc err - dropping pbuf len=%d\n", pd, headMB->len)); + /*"pppWrite[%d]: Alloc err - dropping %d:%.*H", pd, headMB->len, LWIP_MIN(headMB->len * 2, 40), headMB->payload)); */ + pbuf_free(headMB); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.proterr); + snmp_inc_ifoutdiscards(&pc->netif); + return PPPERR_ALLOC; + } + + PPPDEBUG(LOG_INFO, ("pppWrite[%d]: len=%d\n", pd, headMB->len)); + /* "pppWrite[%d]: %d:%.*H", pd, headMB->len, LWIP_MIN(headMB->len * 2, 40), headMB->payload)); */ + nPut(pc, headMB); +#endif /* PPPOS_SUPPORT */ + + return PPPERR_NONE; +} + +/* + * ppp_send_config - configure the transmit characteristics of + * the ppp interface. + */ +void +ppp_send_config( int unit, u16_t mtu, u32_t asyncmap, int pcomp, int accomp) +{ + PPPControl *pc = &pppControl[unit]; + int i; + + pc->mtu = mtu; + pc->pcomp = pcomp; + pc->accomp = accomp; + + /* Load the ACCM bits for the 32 control codes. */ + for (i = 0; i < 32/8; i++) { + pc->outACCM[i] = (u_char)((asyncmap >> (8 * i)) & 0xFF); + } + PPPDEBUG(LOG_INFO, ("ppp_send_config[%d]: outACCM=%X %X %X %X\n", + unit, + pc->outACCM[0], pc->outACCM[1], pc->outACCM[2], pc->outACCM[3])); +} + + +/* + * ppp_set_xaccm - set the extended transmit ACCM for the interface. + */ +void +ppp_set_xaccm(int unit, ext_accm *accm) +{ + SMEMCPY(pppControl[unit].outACCM, accm, sizeof(ext_accm)); + PPPDEBUG(LOG_INFO, ("ppp_set_xaccm[%d]: outACCM=%X %X %X %X\n", + unit, + pppControl[unit].outACCM[0], + pppControl[unit].outACCM[1], + pppControl[unit].outACCM[2], + pppControl[unit].outACCM[3])); +} + + +/* + * ppp_recv_config - configure the receive-side characteristics of + * the ppp interface. + */ +void +ppp_recv_config( int unit, int mru, u32_t asyncmap, int pcomp, int accomp) +{ + PPPControl *pc = &pppControl[unit]; + int i; + SYS_ARCH_DECL_PROTECT(lev); + + LWIP_UNUSED_ARG(accomp); + LWIP_UNUSED_ARG(pcomp); + LWIP_UNUSED_ARG(mru); + + /* Load the ACCM bits for the 32 control codes. */ + SYS_ARCH_PROTECT(lev); + for (i = 0; i < 32 / 8; i++) { + /* @todo: does this work? ext_accm has been modified from pppd! */ + pc->rx.inACCM[i] = (u_char)(asyncmap >> (i * 8)); + } + SYS_ARCH_UNPROTECT(lev); + PPPDEBUG(LOG_INFO, ("ppp_recv_config[%d]: inACCM=%X %X %X %X\n", + unit, + pc->rx.inACCM[0], pc->rx.inACCM[1], pc->rx.inACCM[2], pc->rx.inACCM[3])); +} + +#if 0 +/* + * ccp_test - ask kernel whether a given compression method + * is acceptable for use. Returns 1 if the method and parameters + * are OK, 0 if the method is known but the parameters are not OK + * (e.g. code size should be reduced), or -1 if the method is unknown. + */ +int +ccp_test( int unit, int opt_len, int for_transmit, u_char *opt_ptr) +{ + return 0; /* XXX Currently no compression. */ +} + +/* + * ccp_flags_set - inform kernel about the current state of CCP. + */ +void +ccp_flags_set(int unit, int isopen, int isup) +{ + /* XXX */ +} + +/* + * ccp_fatal_error - returns 1 if decompression was disabled as a + * result of an error detected after decompression of a packet, + * 0 otherwise. This is necessary because of patent nonsense. + */ +int +ccp_fatal_error(int unit) +{ + /* XXX */ + return 0; +} +#endif + +/* + * get_idle_time - return how long the link has been idle. + */ +int +get_idle_time(int u, struct ppp_idle *ip) +{ + /* XXX */ + LWIP_UNUSED_ARG(u); + LWIP_UNUSED_ARG(ip); + + return 0; +} + + +/* + * Return user specified netmask, modified by any mask we might determine + * for address `addr' (in network byte order). + * Here we scan through the system's list of interfaces, looking for + * any non-point-to-point interfaces which might appear to be on the same + * network as `addr'. If we find any, we OR in their netmask to the + * user-specified netmask. + */ +u32_t +GetMask(u32_t addr) +{ + u32_t mask, nmask; + + addr = htonl(addr); + if (IP_CLASSA(addr)) { /* determine network mask for address class */ + nmask = IP_CLASSA_NET; + } else if (IP_CLASSB(addr)) { + nmask = IP_CLASSB_NET; + } else { + nmask = IP_CLASSC_NET; + } + + /* class D nets are disallowed by bad_ip_adrs */ + mask = subnetMask | htonl(nmask); + + /* XXX + * Scan through the system's network interfaces. + * Get each netmask and OR them into our mask. + */ + + return mask; +} + +/* + * sifvjcomp - config tcp header compression + */ +int +sifvjcomp(int pd, int vjcomp, u8_t cidcomp, u8_t maxcid) +{ +#if PPPOS_SUPPORT && VJ_SUPPORT + PPPControl *pc = &pppControl[pd]; + + pc->vjEnabled = vjcomp; + pc->vjComp.compressSlot = cidcomp; + pc->vjComp.maxSlotIndex = maxcid; + PPPDEBUG(LOG_INFO, ("sifvjcomp: VJ compress enable=%d slot=%d max slot=%d\n", + vjcomp, cidcomp, maxcid)); +#else /* PPPOS_SUPPORT && VJ_SUPPORT */ + LWIP_UNUSED_ARG(pd); + LWIP_UNUSED_ARG(vjcomp); + LWIP_UNUSED_ARG(cidcomp); + LWIP_UNUSED_ARG(maxcid); +#endif /* PPPOS_SUPPORT && VJ_SUPPORT */ + + return 0; +} + +/* + * pppifNetifInit - netif init callback + */ +static err_t +pppifNetifInit(struct netif *netif) +{ + netif->name[0] = 'p'; + netif->name[1] = 'p'; + netif->output = pppifOutput; + netif->mtu = pppMTU((int)(size_t)netif->state); + netif->flags = NETIF_FLAG_POINTTOPOINT | NETIF_FLAG_LINK_UP; +#if LWIP_NETIF_HOSTNAME + /* @todo: Initialize interface hostname */ + /* netif_set_hostname(netif, "lwip"); */ +#endif /* LWIP_NETIF_HOSTNAME */ + return ERR_OK; +} + + +/* + * sifup - Config the interface up and enable IP packets to pass. + */ +int +sifup(int pd) +{ + PPPControl *pc = &pppControl[pd]; + int st = 1; + + if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { + st = 0; + PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd)); + } else { + netif_remove(&pc->netif); + if (netif_add(&pc->netif, &pc->addrs.our_ipaddr, &pc->addrs.netmask, + &pc->addrs.his_ipaddr, (void *)(size_t)pd, pppifNetifInit, ip_input)) { + netif_set_up(&pc->netif); + pc->if_up = 1; + pc->errCode = PPPERR_NONE; + + PPPDEBUG(LOG_DEBUG, ("sifup: unit %d: linkStatusCB=%p errCode=%d\n", pd, pc->linkStatusCB, pc->errCode)); + if (pc->linkStatusCB) { + pc->linkStatusCB(pc->linkStatusCtx, pc->errCode, &pc->addrs); + } + } else { + st = 0; + PPPDEBUG(LOG_ERR, ("sifup[%d]: netif_add failed\n", pd)); + } + } + + return st; +} + +/* + * sifnpmode - Set the mode for handling packets for a given NP. + */ +int +sifnpmode(int u, int proto, enum NPmode mode) +{ + LWIP_UNUSED_ARG(u); + LWIP_UNUSED_ARG(proto); + LWIP_UNUSED_ARG(mode); + return 0; +} + +/* + * sifdown - Config the interface down and disable IP. + */ +int +sifdown(int pd) +{ + PPPControl *pc = &pppControl[pd]; + int st = 1; + + if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { + st = 0; + PPPDEBUG(LOG_WARNING, ("sifdown[%d]: bad parms\n", pd)); + } else { + pc->if_up = 0; + /* make sure the netif status callback is called */ + netif_set_down(&pc->netif); + netif_remove(&pc->netif); + PPPDEBUG(LOG_DEBUG, ("sifdown: unit %d: linkStatusCB=%p errCode=%d\n", pd, pc->linkStatusCB, pc->errCode)); + if (pc->linkStatusCB) { + pc->linkStatusCB(pc->linkStatusCtx, PPPERR_CONNECT, NULL); + } + } + return st; +} + +/** + * sifaddr - Config the interface IP addresses and netmask. + * @param pd Interface unit ??? + * @param o Our IP address ??? + * @param h His IP address ??? + * @param m IP subnet mask ??? + * @param ns1 Primary DNS + * @param ns2 Secondary DNS + */ +int +sifaddr( int pd, u32_t o, u32_t h, u32_t m, u32_t ns1, u32_t ns2) +{ + PPPControl *pc = &pppControl[pd]; + int st = 1; + + if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { + st = 0; + PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd)); + } else { + SMEMCPY(&pc->addrs.our_ipaddr, &o, sizeof(o)); + SMEMCPY(&pc->addrs.his_ipaddr, &h, sizeof(h)); + SMEMCPY(&pc->addrs.netmask, &m, sizeof(m)); + SMEMCPY(&pc->addrs.dns1, &ns1, sizeof(ns1)); + SMEMCPY(&pc->addrs.dns2, &ns2, sizeof(ns2)); + } + return st; +} + +/** + * cifaddr - Clear the interface IP addresses, and delete routes + * through the interface if possible. + * @param pd Interface unit ??? + * @param o Our IP address ??? + * @param h IP broadcast address ??? + */ +int +cifaddr( int pd, u32_t o, u32_t h) +{ + PPPControl *pc = &pppControl[pd]; + int st = 1; + + LWIP_UNUSED_ARG(o); + LWIP_UNUSED_ARG(h); + if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { + st = 0; + PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd)); + } else { + IP4_ADDR(&pc->addrs.our_ipaddr, 0,0,0,0); + IP4_ADDR(&pc->addrs.his_ipaddr, 0,0,0,0); + IP4_ADDR(&pc->addrs.netmask, 255,255,255,0); + IP4_ADDR(&pc->addrs.dns1, 0,0,0,0); + IP4_ADDR(&pc->addrs.dns2, 0,0,0,0); + } + return st; +} + +/* + * sifdefaultroute - assign a default route through the address given. + */ +int +sifdefaultroute(int pd, u32_t l, u32_t g) +{ + PPPControl *pc = &pppControl[pd]; + int st = 1; + + LWIP_UNUSED_ARG(l); + LWIP_UNUSED_ARG(g); + + if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { + st = 0; + PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd)); + } else { + netif_set_default(&pc->netif); + } + + /* TODO: check how PPP handled the netMask, previously not set by ipSetDefault */ + + return st; +} + +/* + * cifdefaultroute - delete a default route through the address given. + */ +int +cifdefaultroute(int pd, u32_t l, u32_t g) +{ + PPPControl *pc = &pppControl[pd]; + int st = 1; + + LWIP_UNUSED_ARG(l); + LWIP_UNUSED_ARG(g); + + if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { + st = 0; + PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd)); + } else { + netif_set_default(NULL); + } + + return st; +} + +/**********************************/ +/*** LOCAL FUNCTION DEFINITIONS ***/ +/**********************************/ + +#if PPPOS_SUPPORT && PPP_INPROC_OWNTHREAD +/* The main PPP process function. This implements the state machine according + * to section 4 of RFC 1661: The Point-To-Point Protocol. */ +static void +pppInputThread(void *arg) +{ + int count; + PPPControlRx *pcrx = arg; + + while (lcp_phase[pcrx->pd] != PHASE_DEAD) { + count = sio_read(pcrx->fd, pcrx->rxbuf, PPPOS_RX_BUFSIZE); + if(count > 0) { + pppInProc(pcrx, pcrx->rxbuf, count); + } else { + /* nothing received, give other tasks a chance to run */ + sys_msleep(1); + } + } +} +#endif /* PPPOS_SUPPORT && PPP_INPROC_OWNTHREAD */ + +#if PPPOE_SUPPORT + +void +pppOverEthernetInitFailed(int pd) +{ + PPPControl* pc; + + pppHup(pd); + pppStop(pd); + + pc = &pppControl[pd]; + pppoe_destroy(&pc->netif); + pc->openFlag = 0; + + if(pc->linkStatusCB) { + pc->linkStatusCB(pc->linkStatusCtx, pc->errCode ? pc->errCode : PPPERR_PROTOCOL, NULL); + } +} + +static void +pppOverEthernetLinkStatusCB(int pd, int up) +{ + if(up) { + PPPDEBUG(LOG_INFO, ("pppOverEthernetLinkStatusCB: unit %d: Connecting\n", pd)); + pppStart(pd); + } else { + pppOverEthernetInitFailed(pd); + } +} +#endif /* PPPOE_SUPPORT */ + +struct pbuf * +pppSingleBuf(struct pbuf *p) +{ + struct pbuf *q, *b; + u_char *pl; + + if(p->tot_len == p->len) { + return p; + } + + q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); + if(!q) { + PPPDEBUG(LOG_ERR, + ("pppSingleBuf: unable to alloc new buf (%d)\n", p->tot_len)); + return p; /* live dangerously */ + } + + for(b = p, pl = q->payload; b != NULL; b = b->next) { + MEMCPY(pl, b->payload, b->len); + pl += b->len; + } + + pbuf_free(p); + + return q; +} + +struct pppInputHeader { + int unit; + u16_t proto; +}; + +/* + * Pass the processed input packet to the appropriate handler. + * This function and all handlers run in the context of the tcpip_thread + */ +static void +pppInput(void *arg) +{ + struct pbuf *nb = (struct pbuf *)arg; + u16_t protocol; + int pd; + + pd = ((struct pppInputHeader *)nb->payload)->unit; + protocol = ((struct pppInputHeader *)nb->payload)->proto; + + if(pbuf_header(nb, -(int)sizeof(struct pppInputHeader))) { + LWIP_ASSERT("pbuf_header failed\n", 0); + goto drop; + } + + LINK_STATS_INC(link.recv); + snmp_inc_ifinucastpkts(&pppControl[pd].netif); + snmp_add_ifinoctets(&pppControl[pd].netif, nb->tot_len); + + /* + * Toss all non-LCP packets unless LCP is OPEN. + * Until we get past the authentication phase, toss all packets + * except LCP, LQR and authentication packets. + */ + if((lcp_phase[pd] <= PHASE_AUTHENTICATE) && (protocol != PPP_LCP)) { + if(!((protocol == PPP_LQR) || (protocol == PPP_PAP) || (protocol == PPP_CHAP)) || + (lcp_phase[pd] != PHASE_AUTHENTICATE)) { + PPPDEBUG(LOG_INFO, ("pppInput: discarding proto 0x%"X16_F" in phase %d\n", protocol, lcp_phase[pd])); + goto drop; + } + } + + switch(protocol) { + case PPP_VJC_COMP: /* VJ compressed TCP */ +#if PPPOS_SUPPORT && VJ_SUPPORT + PPPDEBUG(LOG_INFO, ("pppInput[%d]: vj_comp in pbuf len=%d\n", pd, nb->len)); + /* + * Clip off the VJ header and prepend the rebuilt TCP/IP header and + * pass the result to IP. + */ + if ((vj_uncompress_tcp(&nb, &pppControl[pd].vjComp) >= 0) && (pppControl[pd].netif.input)) { + pppControl[pd].netif.input(nb, &pppControl[pd].netif); + return; + } + /* Something's wrong so drop it. */ + PPPDEBUG(LOG_WARNING, ("pppInput[%d]: Dropping VJ compressed\n", pd)); +#else /* PPPOS_SUPPORT && VJ_SUPPORT */ + /* No handler for this protocol so drop the packet. */ + PPPDEBUG(LOG_INFO, ("pppInput[%d]: drop VJ Comp in %d:%s\n", pd, nb->len, nb->payload)); +#endif /* PPPOS_SUPPORT && VJ_SUPPORT */ + break; + + case PPP_VJC_UNCOMP: /* VJ uncompressed TCP */ +#if PPPOS_SUPPORT && VJ_SUPPORT + PPPDEBUG(LOG_INFO, ("pppInput[%d]: vj_un in pbuf len=%d\n", pd, nb->len)); + /* + * Process the TCP/IP header for VJ header compression and then pass + * the packet to IP. + */ + if ((vj_uncompress_uncomp(nb, &pppControl[pd].vjComp) >= 0) && pppControl[pd].netif.input) { + pppControl[pd].netif.input(nb, &pppControl[pd].netif); + return; + } + /* Something's wrong so drop it. */ + PPPDEBUG(LOG_WARNING, ("pppInput[%d]: Dropping VJ uncompressed\n", pd)); +#else /* PPPOS_SUPPORT && VJ_SUPPORT */ + /* No handler for this protocol so drop the packet. */ + PPPDEBUG(LOG_INFO, + ("pppInput[%d]: drop VJ UnComp in %d:.*H\n", + pd, nb->len, LWIP_MIN(nb->len * 2, 40), nb->payload)); +#endif /* PPPOS_SUPPORT && VJ_SUPPORT */ + break; + + case PPP_IP: /* Internet Protocol */ + PPPDEBUG(LOG_INFO, ("pppInput[%d]: ip in pbuf len=%d\n", pd, nb->len)); + if (pppControl[pd].netif.input) { + pppControl[pd].netif.input(nb, &pppControl[pd].netif); + return; + } + break; + + default: { + struct protent *protp; + int i; + + /* + * Upcall the proper protocol input routine. + */ + for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) { + if (protp->protocol == protocol && protp->enabled_flag) { + PPPDEBUG(LOG_INFO, ("pppInput[%d]: %s len=%d\n", pd, protp->name, nb->len)); + nb = pppSingleBuf(nb); + (*protp->input)(pd, nb->payload, nb->len); + PPPDEBUG(LOG_DETAIL, ("pppInput[%d]: packet processed\n", pd)); + goto out; + } + } + + /* No handler for this protocol so reject the packet. */ + PPPDEBUG(LOG_INFO, ("pppInput[%d]: rejecting unsupported proto 0x%"X16_F" len=%d\n", pd, protocol, nb->len)); + if (pbuf_header(nb, sizeof(protocol))) { + LWIP_ASSERT("pbuf_header failed\n", 0); + goto drop; + } +#if BYTE_ORDER == LITTLE_ENDIAN + protocol = htons(protocol); +#endif /* BYTE_ORDER == LITTLE_ENDIAN */ + SMEMCPY(nb->payload, &protocol, sizeof(protocol)); + lcp_sprotrej(pd, nb->payload, nb->len); + } + break; + } + +drop: + LINK_STATS_INC(link.drop); + snmp_inc_ifindiscards(&pppControl[pd].netif); + +out: + pbuf_free(nb); + return; +} + +#if PPPOS_SUPPORT +/* + * Drop the input packet. + */ +static void +pppFreeCurrentInputPacket(PPPControlRx *pcrx) +{ + if (pcrx->inHead != NULL) { + if (pcrx->inTail && (pcrx->inTail != pcrx->inHead)) { + pbuf_free(pcrx->inTail); + } + pbuf_free(pcrx->inHead); + pcrx->inHead = NULL; + } + pcrx->inTail = NULL; +} + +/* + * Drop the input packet and increase error counters. + */ +static void +pppDrop(PPPControlRx *pcrx) +{ + if (pcrx->inHead != NULL) { +#if 0 + PPPDEBUG(LOG_INFO, ("pppDrop: %d:%.*H\n", pcrx->inHead->len, min(60, pcrx->inHead->len * 2), pcrx->inHead->payload)); +#endif + PPPDEBUG(LOG_INFO, ("pppDrop: pbuf len=%d, addr %p\n", pcrx->inHead->len, (void*)pcrx->inHead)); + } + pppFreeCurrentInputPacket(pcrx); +#if VJ_SUPPORT + vj_uncompress_err(&pppControl[pcrx->pd].vjComp); +#endif /* VJ_SUPPORT */ + + LINK_STATS_INC(link.drop); + snmp_inc_ifindiscards(&pppControl[pcrx->pd].netif); +} + +#if !PPP_INPROC_OWNTHREAD +/** Pass received raw characters to PPPoS to be decoded. This function is + * thread-safe and can be called from a dedicated RX-thread or from a main-loop. + * + * @param pd PPP descriptor index, returned by pppOpen() + * @param data received data + * @param len length of received data + */ +void +pppos_input(int pd, u_char* data, int len) +{ + pppInProc(&pppControl[pd].rx, data, len); +} +#endif + +/** + * Process a received octet string. + */ +static void +pppInProc(PPPControlRx *pcrx, u_char *s, int l) +{ + struct pbuf *nextNBuf; + u_char curChar; + u_char escaped; + SYS_ARCH_DECL_PROTECT(lev); + + PPPDEBUG(LOG_DEBUG, ("pppInProc[%d]: got %d bytes\n", pcrx->pd, l)); + while (l-- > 0) { + curChar = *s++; + + SYS_ARCH_PROTECT(lev); + escaped = ESCAPE_P(pcrx->inACCM, curChar); + SYS_ARCH_UNPROTECT(lev); + /* Handle special characters. */ + if (escaped) { + /* Check for escape sequences. */ + /* XXX Note that this does not handle an escaped 0x5d character which + * would appear as an escape character. Since this is an ASCII ']' + * and there is no reason that I know of to escape it, I won't complicate + * the code to handle this case. GLL */ + if (curChar == PPP_ESCAPE) { + pcrx->inEscaped = 1; + /* Check for the flag character. */ + } else if (curChar == PPP_FLAG) { + /* If this is just an extra flag character, ignore it. */ + if (pcrx->inState <= PDADDRESS) { + /* ignore it */; + /* If we haven't received the packet header, drop what has come in. */ + } else if (pcrx->inState < PDDATA) { + PPPDEBUG(LOG_WARNING, + ("pppInProc[%d]: Dropping incomplete packet %d\n", + pcrx->pd, pcrx->inState)); + LINK_STATS_INC(link.lenerr); + pppDrop(pcrx); + /* If the fcs is invalid, drop the packet. */ + } else if (pcrx->inFCS != PPP_GOODFCS) { + PPPDEBUG(LOG_INFO, + ("pppInProc[%d]: Dropping bad fcs 0x%"X16_F" proto=0x%"X16_F"\n", + pcrx->pd, pcrx->inFCS, pcrx->inProtocol)); + /* Note: If you get lots of these, check for UART frame errors or try different baud rate */ + LINK_STATS_INC(link.chkerr); + pppDrop(pcrx); + /* Otherwise it's a good packet so pass it on. */ + } else { + struct pbuf *inp; + /* Trim off the checksum. */ + if(pcrx->inTail->len >= 2) { + pcrx->inTail->len -= 2; + + pcrx->inTail->tot_len = pcrx->inTail->len; + if (pcrx->inTail != pcrx->inHead) { + pbuf_cat(pcrx->inHead, pcrx->inTail); + } + } else { + pcrx->inTail->tot_len = pcrx->inTail->len; + if (pcrx->inTail != pcrx->inHead) { + pbuf_cat(pcrx->inHead, pcrx->inTail); + } + + pbuf_realloc(pcrx->inHead, pcrx->inHead->tot_len - 2); + } + + /* Dispatch the packet thereby consuming it. */ + inp = pcrx->inHead; + /* Packet consumed, release our references. */ + pcrx->inHead = NULL; + pcrx->inTail = NULL; +#if PPP_INPROC_MULTITHREADED + if(tcpip_callback_with_block(pppInput, inp, 0) != ERR_OK) { + PPPDEBUG(LOG_ERR, ("pppInProc[%d]: tcpip_callback() failed, dropping packet\n", pcrx->pd)); + pbuf_free(inp); + LINK_STATS_INC(link.drop); + snmp_inc_ifindiscards(&pppControl[pcrx->pd].netif); + } +#else /* PPP_INPROC_MULTITHREADED */ + pppInput(inp); +#endif /* PPP_INPROC_MULTITHREADED */ + } + + /* Prepare for a new packet. */ + pcrx->inFCS = PPP_INITFCS; + pcrx->inState = PDADDRESS; + pcrx->inEscaped = 0; + /* Other characters are usually control characters that may have + * been inserted by the physical layer so here we just drop them. */ + } else { + PPPDEBUG(LOG_WARNING, + ("pppInProc[%d]: Dropping ACCM char <%d>\n", pcrx->pd, curChar)); + } + /* Process other characters. */ + } else { + /* Unencode escaped characters. */ + if (pcrx->inEscaped) { + pcrx->inEscaped = 0; + curChar ^= PPP_TRANS; + } + + /* Process character relative to current state. */ + switch(pcrx->inState) { + case PDIDLE: /* Idle state - waiting. */ + /* Drop the character if it's not 0xff + * we would have processed a flag character above. */ + if (curChar != PPP_ALLSTATIONS) { + break; + } + + /* Fall through */ + case PDSTART: /* Process start flag. */ + /* Prepare for a new packet. */ + pcrx->inFCS = PPP_INITFCS; + + /* Fall through */ + case PDADDRESS: /* Process address field. */ + if (curChar == PPP_ALLSTATIONS) { + pcrx->inState = PDCONTROL; + break; + } + /* Else assume compressed address and control fields so + * fall through to get the protocol... */ + case PDCONTROL: /* Process control field. */ + /* If we don't get a valid control code, restart. */ + if (curChar == PPP_UI) { + pcrx->inState = PDPROTOCOL1; + break; + } +#if 0 + else { + PPPDEBUG(LOG_WARNING, + ("pppInProc[%d]: Invalid control <%d>\n", pcrx->pd, curChar)); + pcrx->inState = PDSTART; + } +#endif + case PDPROTOCOL1: /* Process protocol field 1. */ + /* If the lower bit is set, this is the end of the protocol + * field. */ + if (curChar & 1) { + pcrx->inProtocol = curChar; + pcrx->inState = PDDATA; + } else { + pcrx->inProtocol = (u_int)curChar << 8; + pcrx->inState = PDPROTOCOL2; + } + break; + case PDPROTOCOL2: /* Process protocol field 2. */ + pcrx->inProtocol |= curChar; + pcrx->inState = PDDATA; + break; + case PDDATA: /* Process data byte. */ + /* Make space to receive processed data. */ + if (pcrx->inTail == NULL || pcrx->inTail->len == PBUF_POOL_BUFSIZE) { + if (pcrx->inTail != NULL) { + pcrx->inTail->tot_len = pcrx->inTail->len; + if (pcrx->inTail != pcrx->inHead) { + pbuf_cat(pcrx->inHead, pcrx->inTail); + /* give up the inTail reference now */ + pcrx->inTail = NULL; + } + } + /* If we haven't started a packet, we need a packet header. */ + nextNBuf = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); + if (nextNBuf == NULL) { + /* No free buffers. Drop the input packet and let the + * higher layers deal with it. Continue processing + * the received pbuf chain in case a new packet starts. */ + PPPDEBUG(LOG_ERR, ("pppInProc[%d]: NO FREE MBUFS!\n", pcrx->pd)); + LINK_STATS_INC(link.memerr); + pppDrop(pcrx); + pcrx->inState = PDSTART; /* Wait for flag sequence. */ + break; + } + if (pcrx->inHead == NULL) { + struct pppInputHeader *pih = nextNBuf->payload; + + pih->unit = pcrx->pd; + pih->proto = pcrx->inProtocol; + + nextNBuf->len += sizeof(*pih); + + pcrx->inHead = nextNBuf; + } + pcrx->inTail = nextNBuf; + } + /* Load character into buffer. */ + ((u_char*)pcrx->inTail->payload)[pcrx->inTail->len++] = curChar; + break; + } + + /* update the frame check sequence number. */ + pcrx->inFCS = PPP_FCS(pcrx->inFCS, curChar); + } + } /* while (l-- > 0), all bytes processed */ + + avRandomize(); +} +#endif /* PPPOS_SUPPORT */ + +#if PPPOE_SUPPORT +void +pppInProcOverEthernet(int pd, struct pbuf *pb) +{ + struct pppInputHeader *pih; + u16_t inProtocol; + + if(pb->len < sizeof(inProtocol)) { + PPPDEBUG(LOG_ERR, ("pppInProcOverEthernet: too small for protocol field\n")); + goto drop; + } + + inProtocol = (((u8_t *)pb->payload)[0] << 8) | ((u8_t*)pb->payload)[1]; + + /* make room for pppInputHeader - should not fail */ + if (pbuf_header(pb, sizeof(*pih) - sizeof(inProtocol)) != 0) { + PPPDEBUG(LOG_ERR, ("pppInProcOverEthernet: could not allocate room for header\n")); + goto drop; + } + + pih = pb->payload; + + pih->unit = pd; + pih->proto = inProtocol; + + /* Dispatch the packet thereby consuming it. */ + pppInput(pb); + return; + +drop: + LINK_STATS_INC(link.drop); + snmp_inc_ifindiscards(&pppControl[pd].netif); + pbuf_free(pb); + return; +} +#endif /* PPPOE_SUPPORT */ + +#if LWIP_NETIF_STATUS_CALLBACK +/** Set the status callback of a PPP's netif + * + * @param pd The PPP descriptor returned by pppOpen() + * @param status_callback pointer to the status callback function + * + * @see netif_set_status_callback + */ +void +ppp_set_netif_statuscallback(int pd, netif_status_callback_fn status_callback) +{ + netif_set_status_callback(&pppControl[pd].netif, status_callback); +} +#endif /* LWIP_NETIF_STATUS_CALLBACK */ + +#if LWIP_NETIF_LINK_CALLBACK +/** Set the link callback of a PPP's netif + * + * @param pd The PPP descriptor returned by pppOpen() + * @param link_callback pointer to the link callback function + * + * @see netif_set_link_callback + */ +void +ppp_set_netif_linkcallback(int pd, netif_status_callback_fn link_callback) +{ + netif_set_link_callback(&pppControl[pd].netif, link_callback); +} +#endif /* LWIP_NETIF_LINK_CALLBACK */ + +#endif /* PPP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/ppp.h b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/ppp.h new file mode 100644 index 0000000..08d6e62 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/ppp.h @@ -0,0 +1,201 @@ +/***************************************************************************** +* ppp.h - Network Point to Point Protocol header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-11-05 Guy Lancaster , Global Election Systems Inc. +* Original derived from BSD codes. +*****************************************************************************/ + +#ifndef PPP_H +#define PPP_H + +#include "lwip/opt.h" + +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/sio.h" +#include "lwip/stats.h" +#include "lwip/mem.h" +#include "lwip/netif.h" +#include "lwip/sys.h" +#include "lwip/timers.h" + + +#ifndef __u_char_defined + +/* Type definitions for BSD code. */ +typedef unsigned long u_long; +typedef unsigned int u_int; +typedef unsigned short u_short; +typedef unsigned char u_char; + +#endif + + +/************************* +*** PUBLIC DEFINITIONS *** +*************************/ + +/* Error codes. */ +#define PPPERR_NONE 0 /* No error. */ +#define PPPERR_PARAM -1 /* Invalid parameter. */ +#define PPPERR_OPEN -2 /* Unable to open PPP session. */ +#define PPPERR_DEVICE -3 /* Invalid I/O device for PPP. */ +#define PPPERR_ALLOC -4 /* Unable to allocate resources. */ +#define PPPERR_USER -5 /* User interrupt. */ +#define PPPERR_CONNECT -6 /* Connection lost. */ +#define PPPERR_AUTHFAIL -7 /* Failed authentication challenge. */ +#define PPPERR_PROTOCOL -8 /* Failed to meet protocol. */ + +/* + * PPP IOCTL commands. + */ +/* + * Get the up status - 0 for down, non-zero for up. The argument must + * point to an int. + */ +#define PPPCTLG_UPSTATUS 100 /* Get the up status - 0 down else up */ +#define PPPCTLS_ERRCODE 101 /* Set the error code */ +#define PPPCTLG_ERRCODE 102 /* Get the error code */ +#define PPPCTLG_FD 103 /* Get the fd associated with the ppp */ + +/************************ +*** PUBLIC DATA TYPES *** +************************/ + +struct ppp_addrs { + ip_addr_t our_ipaddr, his_ipaddr, netmask, dns1, dns2; +}; + + +/*********************** +*** PUBLIC FUNCTIONS *** +***********************/ + +/* Initialize the PPP subsystem. */ +void pppInit(void); + +/* Warning: Using PPPAUTHTYPE_ANY might have security consequences. + * RFC 1994 says: + * + * In practice, within or associated with each PPP server, there is a + * database which associates "user" names with authentication + * information ("secrets"). It is not anticipated that a particular + * named user would be authenticated by multiple methods. This would + * make the user vulnerable to attacks which negotiate the least secure + * method from among a set (such as PAP rather than CHAP). If the same + * secret was used, PAP would reveal the secret to be used later with + * CHAP. + * + * Instead, for each user name there should be an indication of exactly + * one method used to authenticate that user name. If a user needs to + * make use of different authentication methods under different + * circumstances, then distinct user names SHOULD be employed, each of + * which identifies exactly one authentication method. + * + */ +enum pppAuthType { + PPPAUTHTYPE_NONE, + PPPAUTHTYPE_ANY, + PPPAUTHTYPE_PAP, + PPPAUTHTYPE_CHAP +}; + +void pppSetAuth(enum pppAuthType authType, const char *user, const char *passwd); + +/* Link status callback function prototype */ +typedef void (*pppLinkStatusCB_fn)(void *ctx, int errCode, void *arg); + +#if PPPOS_SUPPORT +/* + * Open a new PPP connection using the given serial I/O device. + * This initializes the PPP control block but does not + * attempt to negotiate the LCP session. + * Return a new PPP connection descriptor on success or + * an error code (negative) on failure. + */ +int pppOverSerialOpen(sio_fd_t fd, pppLinkStatusCB_fn linkStatusCB, void *linkStatusCtx); +#endif /* PPPOS_SUPPORT */ + +#if PPPOE_SUPPORT +/* + * Open a new PPP Over Ethernet (PPPOE) connection. + */ +int pppOverEthernetOpen(struct netif *ethif, const char *service_name, const char *concentrator_name, + pppLinkStatusCB_fn linkStatusCB, void *linkStatusCtx); +#endif /* PPPOE_SUPPORT */ + +/* for source code compatibility */ +#define pppOpen(fd,cb,ls) pppOverSerialOpen(fd,cb,ls) + +/* + * Close a PPP connection and release the descriptor. + * Any outstanding packets in the queues are dropped. + * Return 0 on success, an error code on failure. + */ +int pppClose(int pd); + +/* + * Indicate to the PPP process that the line has disconnected. + */ +void pppSigHUP(int pd); + +/* + * Get and set parameters for the given connection. + * Return 0 on success, an error code on failure. + */ +int pppIOCtl(int pd, int cmd, void *arg); + +/* + * Return the Maximum Transmission Unit for the given PPP connection. + */ +u_short pppMTU(int pd); + +#if PPPOS_SUPPORT && !PPP_INPROC_OWNTHREAD +/* + * PPP over Serial: this is the input function to be called for received data. + * If PPP_INPROC_OWNTHREAD==1, a seperate input thread using the blocking + * sio_read() is used, so this is deactivated. + */ +void pppos_input(int pd, u_char* data, int len); +#endif /* PPPOS_SUPPORT && !PPP_INPROC_OWNTHREAD */ + + +#if LWIP_NETIF_STATUS_CALLBACK +/* Set an lwIP-style status-callback for the selected PPP device */ +void ppp_set_netif_statuscallback(int pd, netif_status_callback_fn status_callback); +#endif /* LWIP_NETIF_STATUS_CALLBACK */ +#if LWIP_NETIF_LINK_CALLBACK +/* Set an lwIP-style link-callback for the selected PPP device */ +void ppp_set_netif_linkcallback(int pd, netif_status_callback_fn link_callback); +#endif /* LWIP_NETIF_LINK_CALLBACK */ + +#endif /* PPP_SUPPORT */ + +#endif /* PPP_H */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/ppp_impl.h b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/ppp_impl.h new file mode 100644 index 0000000..89aea60 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/ppp_impl.h @@ -0,0 +1,363 @@ +/***************************************************************************** +* ppp.h - Network Point to Point Protocol header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-11-05 Guy Lancaster , Global Election Systems Inc. +* Original derived from BSD codes. +*****************************************************************************/ + +#ifndef PPP_IMPL_H +#define PPP_IMPL_H + +#include "lwip/opt.h" + +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "ppp.h" +#include "lwip/def.h" +#include "lwip/sio.h" +#include "lwip/stats.h" +#include "lwip/mem.h" +#include "lwip/netif.h" +#include "lwip/sys.h" +#include "lwip/timers.h" + +/** Some defines for code we skip compared to the original pppd. + * These are just here to minimise the use of the ugly "#if 0". */ +#define PPP_ADDITIONAL_CALLBACKS 0 + +/** Some error checks to test for unsupported code */ +#if CBCP_SUPPORT +#error "CBCP is not supported in lwIP PPP" +#endif +#if CCP_SUPPORT +#error "CCP is not supported in lwIP PPP" +#endif + +/* + * pppd.h - PPP daemon global declarations. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + */ +/* + * ppp_defs.h - PPP definitions. + * + * Copyright (c) 1994 The Australian National University. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, provided that the above copyright + * notice appears in all copies. This software is provided without any + * warranty, express or implied. The Australian National University + * makes no representations about the suitability of this software for + * any purpose. + * + * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY + * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO + * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, + * OR MODIFICATIONS. + */ + +#define TIMEOUT(f, a, t) do { sys_untimeout((f), (a)); sys_timeout((t)*1000, (f), (a)); } while(0) +#define UNTIMEOUT(f, a) sys_untimeout((f), (a)) + + +/* + * Constants and structures defined by the internet system, + * Per RFC 790, September 1981, and numerous additions. + */ + +/* + * The basic PPP frame. + */ +#define PPP_HDRLEN 4 /* octets for standard ppp header */ +#define PPP_FCSLEN 2 /* octets for FCS */ + + +/* + * Significant octet values. + */ +#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */ +#define PPP_UI 0x03 /* Unnumbered Information */ +#define PPP_FLAG 0x7e /* Flag Sequence */ +#define PPP_ESCAPE 0x7d /* Asynchronous Control Escape */ +#define PPP_TRANS 0x20 /* Asynchronous transparency modifier */ + +/* + * Protocol field values. + */ +#define PPP_IP 0x21 /* Internet Protocol */ +#define PPP_AT 0x29 /* AppleTalk Protocol */ +#define PPP_VJC_COMP 0x2d /* VJ compressed TCP */ +#define PPP_VJC_UNCOMP 0x2f /* VJ uncompressed TCP */ +#define PPP_COMP 0xfd /* compressed packet */ +#define PPP_IPCP 0x8021 /* IP Control Protocol */ +#define PPP_ATCP 0x8029 /* AppleTalk Control Protocol */ +#define PPP_CCP 0x80fd /* Compression Control Protocol */ +#define PPP_LCP 0xc021 /* Link Control Protocol */ +#define PPP_PAP 0xc023 /* Password Authentication Protocol */ +#define PPP_LQR 0xc025 /* Link Quality Report protocol */ +#define PPP_CHAP 0xc223 /* Cryptographic Handshake Auth. Protocol */ +#define PPP_CBCP 0xc029 /* Callback Control Protocol */ + +/* + * Values for FCS calculations. + */ +#define PPP_INITFCS 0xffff /* Initial FCS value */ +#define PPP_GOODFCS 0xf0b8 /* Good final FCS value */ +#define PPP_FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff]) + +/* + * Extended asyncmap - allows any character to be escaped. + */ +typedef u_char ext_accm[32]; + +/* + * What to do with network protocol (NP) packets. + */ +enum NPmode { + NPMODE_PASS, /* pass the packet through */ + NPMODE_DROP, /* silently drop the packet */ + NPMODE_ERROR, /* return an error */ + NPMODE_QUEUE /* save it up for later. */ +}; + +/* + * Inline versions of get/put char/short/long. + * Pointer is advanced; we assume that both arguments + * are lvalues and will already be in registers. + * cp MUST be u_char *. + */ +#define GETCHAR(c, cp) { \ + (c) = *(cp)++; \ +} +#define PUTCHAR(c, cp) { \ + *(cp)++ = (u_char) (c); \ +} + + +#define GETSHORT(s, cp) { \ + (s) = *(cp); (cp)++; (s) <<= 8; \ + (s) |= *(cp); (cp)++; \ +} +#define PUTSHORT(s, cp) { \ + *(cp)++ = (u_char) ((s) >> 8); \ + *(cp)++ = (u_char) (s & 0xff); \ +} + +#define GETLONG(l, cp) { \ + (l) = *(cp); (cp)++; (l) <<= 8; \ + (l) |= *(cp); (cp)++; (l) <<= 8; \ + (l) |= *(cp); (cp)++; (l) <<= 8; \ + (l) |= *(cp); (cp)++; \ +} +#define PUTLONG(l, cp) { \ + *(cp)++ = (u_char) ((l) >> 24); \ + *(cp)++ = (u_char) ((l) >> 16); \ + *(cp)++ = (u_char) ((l) >> 8); \ + *(cp)++ = (u_char) (l); \ +} + + +#define INCPTR(n, cp) ((cp) += (n)) +#define DECPTR(n, cp) ((cp) -= (n)) + +#define BCMP(s0, s1, l) memcmp((u_char *)(s0), (u_char *)(s1), (l)) +#define BCOPY(s, d, l) MEMCPY((d), (s), (l)) +#define BZERO(s, n) memset(s, 0, n) + +#if PPP_DEBUG +#define PRINTMSG(m, l) { m[l] = '\0'; LWIP_DEBUGF(LOG_INFO, ("Remote message: %s\n", m)); } +#else /* PPP_DEBUG */ +#define PRINTMSG(m, l) +#endif /* PPP_DEBUG */ + +/* + * MAKEHEADER - Add PPP Header fields to a packet. + */ +#define MAKEHEADER(p, t) { \ + PUTCHAR(PPP_ALLSTATIONS, p); \ + PUTCHAR(PPP_UI, p); \ + PUTSHORT(t, p); } + +/************************ +*** PUBLIC DATA TYPES *** +************************/ + +/* + * The following struct gives the addresses of procedures to call + * for a particular protocol. + */ +struct protent { + u_short protocol; /* PPP protocol number */ + /* Initialization procedure */ + void (*init) (int unit); + /* Process a received packet */ + void (*input) (int unit, u_char *pkt, int len); + /* Process a received protocol-reject */ + void (*protrej) (int unit); + /* Lower layer has come up */ + void (*lowerup) (int unit); + /* Lower layer has gone down */ + void (*lowerdown) (int unit); + /* Open the protocol */ + void (*open) (int unit); + /* Close the protocol */ + void (*close) (int unit, char *reason); +#if PPP_ADDITIONAL_CALLBACKS + /* Print a packet in readable form */ + int (*printpkt) (u_char *pkt, int len, + void (*printer) (void *, char *, ...), + void *arg); + /* Process a received data packet */ + void (*datainput) (int unit, u_char *pkt, int len); +#endif /* PPP_ADDITIONAL_CALLBACKS */ + int enabled_flag; /* 0 if protocol is disabled */ + char *name; /* Text name of protocol */ +#if PPP_ADDITIONAL_CALLBACKS + /* Check requested options, assign defaults */ + void (*check_options) (u_long); + /* Configure interface for demand-dial */ + int (*demand_conf) (int unit); + /* Say whether to bring up link for this pkt */ + int (*active_pkt) (u_char *pkt, int len); +#endif /* PPP_ADDITIONAL_CALLBACKS */ +}; + +/* + * The following structure records the time in seconds since + * the last NP packet was sent or received. + */ +struct ppp_idle { + u_short xmit_idle; /* seconds since last NP packet sent */ + u_short recv_idle; /* seconds since last NP packet received */ +}; + +struct ppp_settings { + + u_int disable_defaultip : 1; /* Don't use hostname for default IP addrs */ + u_int auth_required : 1; /* Peer is required to authenticate */ + u_int explicit_remote : 1; /* remote_name specified with remotename opt */ + u_int refuse_pap : 1; /* Don't wanna auth. ourselves with PAP */ + u_int refuse_chap : 1; /* Don't wanna auth. ourselves with CHAP */ + u_int usehostname : 1; /* Use hostname for our_name */ + u_int usepeerdns : 1; /* Ask peer for DNS adds */ + + u_short idle_time_limit; /* Shut down link if idle for this long */ + int maxconnect; /* Maximum connect time (seconds) */ + + char user [MAXNAMELEN + 1]; /* Username for PAP */ + char passwd [MAXSECRETLEN + 1]; /* Password for PAP, secret for CHAP */ + char our_name [MAXNAMELEN + 1]; /* Our name for authentication purposes */ + char remote_name[MAXNAMELEN + 1]; /* Peer's name for authentication */ +}; + +/***************************** +*** PUBLIC DATA STRUCTURES *** +*****************************/ + +/* Buffers for outgoing packets. */ +extern u_char outpacket_buf[NUM_PPP][PPP_MRU+PPP_HDRLEN]; + +extern struct ppp_settings ppp_settings; + +extern struct protent *ppp_protocols[]; /* Table of pointers to supported protocols */ + + +/*********************** +*** PUBLIC FUNCTIONS *** +***********************/ + +/* + * Write n characters to a ppp link. + * RETURN: >= 0 Number of characters written, -1 Failed to write to device. + */ +int pppWrite(int pd, const u_char *s, int n); + +void pppInProcOverEthernet(int pd, struct pbuf *pb); + +struct pbuf *pppSingleBuf(struct pbuf *p); + +void pppLinkTerminated(int pd); + +void pppLinkDown(int pd); + +/* Configure i/f transmit parameters */ +void ppp_send_config (int, u16_t, u32_t, int, int); +/* Set extended transmit ACCM */ +void ppp_set_xaccm (int, ext_accm *); +/* Configure i/f receive parameters */ +void ppp_recv_config (int, int, u32_t, int, int); +/* Find out how long link has been idle */ +int get_idle_time (int, struct ppp_idle *); + +/* Configure VJ TCP header compression */ +int sifvjcomp (int, int, u8_t, u8_t); +/* Configure i/f down (for IP) */ +int sifup (int); +/* Set mode for handling packets for proto */ +int sifnpmode (int u, int proto, enum NPmode mode); +/* Configure i/f down (for IP) */ +int sifdown (int); +/* Configure IP addresses for i/f */ +int sifaddr (int, u32_t, u32_t, u32_t, u32_t, u32_t); +/* Reset i/f IP addresses */ +int cifaddr (int, u32_t, u32_t); +/* Create default route through i/f */ +int sifdefaultroute (int, u32_t, u32_t); +/* Delete default route through i/f */ +int cifdefaultroute (int, u32_t, u32_t); + +/* Get appropriate netmask for address */ +u32_t GetMask (u32_t); + +#endif /* PPP_SUPPORT */ + +#endif /* PPP_IMPL_H */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/ppp_oe.c b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/ppp_oe.c new file mode 100644 index 0000000..fdf52ae --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/ppp_oe.c @@ -0,0 +1,1132 @@ +/***************************************************************************** +* ppp_oe.c - PPP Over Ethernet implementation for lwIP. +* +* Copyright (c) 2006 by Marc Boucher, Services Informatiques (MBSI) inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 06-01-01 Marc Boucher +* Ported to lwIP. +*****************************************************************************/ + + + +/* based on NetBSD: if_pppoe.c,v 1.64 2006/01/31 23:50:15 martin Exp */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Martin Husemann . + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +#include "lwip/opt.h" + +#if PPPOE_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "netif/ppp_oe.h" + +#include "ppp_impl.h" +#include "pppdebug.h" + +#include "lwip/timers.h" +#include "lwip/memp.h" + +#include +#include + + +/* Add a 16 bit unsigned value to a buffer pointed to by PTR */ +#define PPPOE_ADD_16(PTR, VAL) \ + *(PTR)++ = (u8_t)((VAL) / 256); \ + *(PTR)++ = (u8_t)((VAL) % 256) + +/* Add a complete PPPoE header to the buffer pointed to by PTR */ +#define PPPOE_ADD_HEADER(PTR, CODE, SESS, LEN) \ + *(PTR)++ = PPPOE_VERTYPE; \ + *(PTR)++ = (CODE); \ + PPPOE_ADD_16(PTR, SESS); \ + PPPOE_ADD_16(PTR, LEN) + +#define PPPOE_DISC_TIMEOUT (5*1000) /* base for quick timeout calculation */ +#define PPPOE_SLOW_RETRY (60*1000) /* persistent retry interval */ +#define PPPOE_DISC_MAXPADI 4 /* retry PADI four times (quickly) */ +#define PPPOE_DISC_MAXPADR 2 /* retry PADR twice */ + +#ifdef PPPOE_SERVER +#error "PPPOE_SERVER is not yet supported under lwIP!" +/* from if_spppsubr.c */ +#define IFF_PASSIVE IFF_LINK0 /* wait passively for connection */ +#endif + +#ifndef PPPOE_ERRORSTRING_LEN +#define PPPOE_ERRORSTRING_LEN 64 +#endif +static char pppoe_error_tmp[PPPOE_ERRORSTRING_LEN]; + + +/* input routines */ +static void pppoe_dispatch_disc_pkt(struct netif *, struct pbuf *); + +/* management routines */ +static int pppoe_do_disconnect(struct pppoe_softc *); +static void pppoe_abort_connect(struct pppoe_softc *); +static void pppoe_clear_softc(struct pppoe_softc *, const char *); + +/* internal timeout handling */ +static void pppoe_timeout(void *); + +/* sending actual protocol controll packets */ +static err_t pppoe_send_padi(struct pppoe_softc *); +static err_t pppoe_send_padr(struct pppoe_softc *); +#ifdef PPPOE_SERVER +static err_t pppoe_send_pado(struct pppoe_softc *); +static err_t pppoe_send_pads(struct pppoe_softc *); +#endif +static err_t pppoe_send_padt(struct netif *, u_int, const u8_t *); + +/* internal helper functions */ +static struct pppoe_softc * pppoe_find_softc_by_session(u_int, struct netif *); +static struct pppoe_softc * pppoe_find_softc_by_hunique(u8_t *, size_t, struct netif *); + +/** linked list of created pppoe interfaces */ +static struct pppoe_softc *pppoe_softc_list; + +err_t +pppoe_create(struct netif *ethif, int pd, void (*linkStatusCB)(int pd, int up), struct pppoe_softc **scptr) +{ + struct pppoe_softc *sc; + + sc = (struct pppoe_softc *)memp_malloc(MEMP_PPPOE_IF); + if (sc == NULL) { + *scptr = NULL; + return ERR_MEM; + } + memset(sc, 0, sizeof(struct pppoe_softc)); + + /* changed to real address later */ + MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); + + sc->sc_pd = pd; + sc->sc_linkStatusCB = linkStatusCB; + sc->sc_ethif = ethif; + + /* put the new interface at the head of the list */ + sc->next = pppoe_softc_list; + pppoe_softc_list = sc; + + *scptr = sc; + + return ERR_OK; +} + +err_t +pppoe_destroy(struct netif *ifp) +{ + struct pppoe_softc *sc, *prev = NULL; + + for (sc = pppoe_softc_list; sc != NULL; prev = sc, sc = sc->next) { + if (sc->sc_ethif == ifp) { + break; + } + } + + if(!(sc && (sc->sc_ethif == ifp))) { + return ERR_IF; + } + + sys_untimeout(pppoe_timeout, sc); + if (prev == NULL) { + /* remove sc from the head of the list */ + pppoe_softc_list = sc->next; + } else { + /* remove sc from the list */ + prev->next = sc->next; + } + +#ifdef PPPOE_TODO + if (sc->sc_concentrator_name) { + mem_free(sc->sc_concentrator_name); + } + if (sc->sc_service_name) { + mem_free(sc->sc_service_name); + } +#endif /* PPPOE_TODO */ + memp_free(MEMP_PPPOE_IF, sc); + + return ERR_OK; +} + +/* + * Find the interface handling the specified session. + * Note: O(number of sessions open), this is a client-side only, mean + * and lean implementation, so number of open sessions typically should + * be 1. + */ +static struct pppoe_softc * +pppoe_find_softc_by_session(u_int session, struct netif *rcvif) +{ + struct pppoe_softc *sc; + + if (session == 0) { + return NULL; + } + + for (sc = pppoe_softc_list; sc != NULL; sc = sc->next) { + if (sc->sc_state == PPPOE_STATE_SESSION + && sc->sc_session == session) { + if (sc->sc_ethif == rcvif) { + return sc; + } else { + return NULL; + } + } + } + return NULL; +} + +/* Check host unique token passed and return appropriate softc pointer, + * or NULL if token is bogus. */ +static struct pppoe_softc * +pppoe_find_softc_by_hunique(u8_t *token, size_t len, struct netif *rcvif) +{ + struct pppoe_softc *sc, *t; + + if (pppoe_softc_list == NULL) { + return NULL; + } + + if (len != sizeof sc) { + return NULL; + } + MEMCPY(&t, token, len); + + for (sc = pppoe_softc_list; sc != NULL; sc = sc->next) { + if (sc == t) { + break; + } + } + + if (sc == NULL) { + PPPDEBUG(LOG_DEBUG, ("pppoe: alien host unique tag, no session found\n")); + return NULL; + } + + /* should be safe to access *sc now */ + if (sc->sc_state < PPPOE_STATE_PADI_SENT || sc->sc_state >= PPPOE_STATE_SESSION) { + printf("%c%c%"U16_F": host unique tag found, but it belongs to a connection in state %d\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, sc->sc_state); + return NULL; + } + if (sc->sc_ethif != rcvif) { + printf("%c%c%"U16_F": wrong interface, not accepting host unique\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num); + return NULL; + } + return sc; +} + +static void +pppoe_linkstatus_up(struct pppoe_softc *sc) +{ + sc->sc_linkStatusCB(sc->sc_pd, 1); +} + +/* analyze and handle a single received packet while not in session state */ +static void +pppoe_dispatch_disc_pkt(struct netif *netif, struct pbuf *pb) +{ + u16_t tag, len; + u16_t session, plen; + struct pppoe_softc *sc; + const char *err_msg; + char devname[6]; + u8_t *ac_cookie; + u16_t ac_cookie_len; +#ifdef PPPOE_SERVER + u8_t *hunique; + size_t hunique_len; +#endif + struct pppoehdr *ph; + struct pppoetag pt; + int off, err, errortag; + struct eth_hdr *ethhdr; + + pb = pppSingleBuf(pb); + + strcpy(devname, "pppoe"); /* as long as we don't know which instance */ + err_msg = NULL; + errortag = 0; + if (pb->len < sizeof(*ethhdr)) { + goto done; + } + ethhdr = (struct eth_hdr *)pb->payload; + off = sizeof(*ethhdr); + + ac_cookie = NULL; + ac_cookie_len = 0; +#ifdef PPPOE_SERVER + hunique = NULL; + hunique_len = 0; +#endif + session = 0; + if (pb->len - off < PPPOE_HEADERLEN) { + printf("pppoe: packet too short: %d\n", pb->len); + goto done; + } + + ph = (struct pppoehdr *) (ethhdr + 1); + if (ph->vertype != PPPOE_VERTYPE) { + printf("pppoe: unknown version/type packet: 0x%x\n", ph->vertype); + goto done; + } + session = ntohs(ph->session); + plen = ntohs(ph->plen); + off += sizeof(*ph); + + if (plen + off > pb->len) { + printf("pppoe: packet content does not fit: data available = %d, packet size = %u\n", + pb->len - off, plen); + goto done; + } + if(pb->tot_len == pb->len) { + pb->tot_len = pb->len = (u16_t)off + plen; /* ignore trailing garbage */ + } + tag = 0; + len = 0; + sc = NULL; + while (off + sizeof(pt) <= pb->len) { + MEMCPY(&pt, (u8_t*)pb->payload + off, sizeof(pt)); + tag = ntohs(pt.tag); + len = ntohs(pt.len); + if (off + sizeof(pt) + len > pb->len) { + printf("pppoe: tag 0x%x len 0x%x is too long\n", tag, len); + goto done; + } + switch (tag) { + case PPPOE_TAG_EOL: + goto breakbreak; + case PPPOE_TAG_SNAME: + break; /* ignored */ + case PPPOE_TAG_ACNAME: + break; /* ignored */ + case PPPOE_TAG_HUNIQUE: + if (sc != NULL) { + break; + } +#ifdef PPPOE_SERVER + hunique = (u8_t*)pb->payload + off + sizeof(pt); + hunique_len = len; +#endif + sc = pppoe_find_softc_by_hunique((u8_t*)pb->payload + off + sizeof(pt), len, netif); + if (sc != NULL) { + snprintf(devname, sizeof(devname), "%c%c%"U16_F, sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num); + } + break; + case PPPOE_TAG_ACCOOKIE: + if (ac_cookie == NULL) { + ac_cookie = (u8_t*)pb->payload + off + sizeof(pt); + ac_cookie_len = len; + } + break; + case PPPOE_TAG_SNAME_ERR: + err_msg = "SERVICE NAME ERROR"; + errortag = 1; + break; + case PPPOE_TAG_ACSYS_ERR: + err_msg = "AC SYSTEM ERROR"; + errortag = 1; + break; + case PPPOE_TAG_GENERIC_ERR: + err_msg = "GENERIC ERROR"; + errortag = 1; + break; + } + if (err_msg) { + if (errortag && len) { + u16_t error_len = LWIP_MIN(len, sizeof(pppoe_error_tmp)-1); + strncpy(pppoe_error_tmp, (char*)pb->payload + off + sizeof(pt), error_len); + pppoe_error_tmp[error_len-1] = '\0'; + printf("%s: %s: %s\n", devname, err_msg, pppoe_error_tmp); + } else { + printf("%s: %s\n", devname, err_msg); + } + if (errortag) { + goto done; + } + } + off += sizeof(pt) + len; + } + +breakbreak:; + switch (ph->code) { + case PPPOE_CODE_PADI: +#ifdef PPPOE_SERVER + /* + * got service name, concentrator name, and/or host unique. + * ignore if we have no interfaces with IFF_PASSIVE|IFF_UP. + */ + if (LIST_EMPTY(&pppoe_softc_list)) { + goto done; + } + LIST_FOREACH(sc, &pppoe_softc_list, sc_list) { + if (!(sc->sc_sppp.pp_if.if_flags & IFF_UP)) { + continue; + } + if (!(sc->sc_sppp.pp_if.if_flags & IFF_PASSIVE)) { + continue; + } + if (sc->sc_state == PPPOE_STATE_INITIAL) { + break; + } + } + if (sc == NULL) { + /* printf("pppoe: free passive interface is not found\n"); */ + goto done; + } + if (hunique) { + if (sc->sc_hunique) { + mem_free(sc->sc_hunique); + } + sc->sc_hunique = mem_malloc(hunique_len); + if (sc->sc_hunique == NULL) { + goto done; + } + sc->sc_hunique_len = hunique_len; + MEMCPY(sc->sc_hunique, hunique, hunique_len); + } + MEMCPY(&sc->sc_dest, eh->ether_shost, sizeof sc->sc_dest); + sc->sc_state = PPPOE_STATE_PADO_SENT; + pppoe_send_pado(sc); + break; +#endif /* PPPOE_SERVER */ + case PPPOE_CODE_PADR: +#ifdef PPPOE_SERVER + /* + * get sc from ac_cookie if IFF_PASSIVE + */ + if (ac_cookie == NULL) { + /* be quiet if there is not a single pppoe instance */ + printf("pppoe: received PADR but not includes ac_cookie\n"); + goto done; + } + sc = pppoe_find_softc_by_hunique(ac_cookie, ac_cookie_len, netif); + if (sc == NULL) { + /* be quiet if there is not a single pppoe instance */ + if (!LIST_EMPTY(&pppoe_softc_list)) { + printf("pppoe: received PADR but could not find request for it\n"); + } + goto done; + } + if (sc->sc_state != PPPOE_STATE_PADO_SENT) { + printf("%c%c%"U16_F": received unexpected PADR\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num); + goto done; + } + if (hunique) { + if (sc->sc_hunique) { + mem_free(sc->sc_hunique); + } + sc->sc_hunique = mem_malloc(hunique_len); + if (sc->sc_hunique == NULL) { + goto done; + } + sc->sc_hunique_len = hunique_len; + MEMCPY(sc->sc_hunique, hunique, hunique_len); + } + pppoe_send_pads(sc); + sc->sc_state = PPPOE_STATE_SESSION; + pppoe_linkstatus_up(sc); /* notify upper layers */ + break; +#else + /* ignore, we are no access concentrator */ + goto done; +#endif /* PPPOE_SERVER */ + case PPPOE_CODE_PADO: + if (sc == NULL) { + /* be quiet if there is not a single pppoe instance */ + if (pppoe_softc_list != NULL) { + printf("pppoe: received PADO but could not find request for it\n"); + } + goto done; + } + if (sc->sc_state != PPPOE_STATE_PADI_SENT) { + printf("%c%c%"U16_F": received unexpected PADO\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num); + goto done; + } + if (ac_cookie) { + sc->sc_ac_cookie_len = ac_cookie_len; + MEMCPY(sc->sc_ac_cookie, ac_cookie, ac_cookie_len); + } + MEMCPY(&sc->sc_dest, ethhdr->src.addr, sizeof(sc->sc_dest.addr)); + sys_untimeout(pppoe_timeout, sc); + sc->sc_padr_retried = 0; + sc->sc_state = PPPOE_STATE_PADR_SENT; + if ((err = pppoe_send_padr(sc)) != 0) { + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADR, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); + } + sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padr_retried), pppoe_timeout, sc); + break; + case PPPOE_CODE_PADS: + if (sc == NULL) { + goto done; + } + sc->sc_session = session; + sys_untimeout(pppoe_timeout, sc); + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": session 0x%x connected\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, session)); + sc->sc_state = PPPOE_STATE_SESSION; + pppoe_linkstatus_up(sc); /* notify upper layers */ + break; + case PPPOE_CODE_PADT: + if (sc == NULL) { + goto done; + } + pppoe_clear_softc(sc, "received PADT"); + break; + default: + if(sc) { + printf("%c%c%"U16_F": unknown code (0x%"X16_F") session = 0x%"X16_F"\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, + (u16_t)ph->code, session); + } else { + printf("pppoe: unknown code (0x%"X16_F") session = 0x%"X16_F"\n", (u16_t)ph->code, session); + } + break; + } + +done: + pbuf_free(pb); + return; +} + +void +pppoe_disc_input(struct netif *netif, struct pbuf *p) +{ + /* avoid error messages if there is not a single pppoe instance */ + if (pppoe_softc_list != NULL) { + pppoe_dispatch_disc_pkt(netif, p); + } else { + pbuf_free(p); + } +} + +void +pppoe_data_input(struct netif *netif, struct pbuf *pb) +{ + u16_t session, plen; + struct pppoe_softc *sc; + struct pppoehdr *ph; +#ifdef PPPOE_TERM_UNKNOWN_SESSIONS + u8_t shost[ETHER_ADDR_LEN]; +#endif + +#ifdef PPPOE_TERM_UNKNOWN_SESSIONS + MEMCPY(shost, ((struct eth_hdr *)pb->payload)->src.addr, sizeof(shost)); +#endif + if (pbuf_header(pb, -(int)sizeof(struct eth_hdr)) != 0) { + /* bail out */ + PPPDEBUG(LOG_ERR, ("pppoe_data_input: pbuf_header failed\n")); + LINK_STATS_INC(link.lenerr); + goto drop; + } + + pb = pppSingleBuf (pb); + + if (pb->len <= PPPOE_HEADERLEN) { + printf("pppoe (data): dropping too short packet: %d bytes\n", pb->len); + goto drop; + } + + if (pb->len < sizeof(*ph)) { + printf("pppoe_data_input: could not get PPPoE header\n"); + goto drop; + } + ph = (struct pppoehdr *)pb->payload; + + if (ph->vertype != PPPOE_VERTYPE) { + printf("pppoe (data): unknown version/type packet: 0x%x\n", ph->vertype); + goto drop; + } + if (ph->code != 0) { + goto drop; + } + + session = ntohs(ph->session); + sc = pppoe_find_softc_by_session(session, netif); + if (sc == NULL) { +#ifdef PPPOE_TERM_UNKNOWN_SESSIONS + printf("pppoe: input for unknown session 0x%x, sending PADT\n", session); + pppoe_send_padt(netif, session, shost); +#endif + goto drop; + } + + plen = ntohs(ph->plen); + + if (pbuf_header(pb, -(int)(PPPOE_HEADERLEN)) != 0) { + /* bail out */ + PPPDEBUG(LOG_ERR, ("pppoe_data_input: pbuf_header PPPOE_HEADERLEN failed\n")); + LINK_STATS_INC(link.lenerr); + goto drop; + } + + PPPDEBUG(LOG_DEBUG, ("pppoe_data_input: %c%c%"U16_F": pkthdr.len=%d, pppoe.len=%d\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, + pb->len, plen)); + + if (pb->len < plen) { + goto drop; + } + + pppInProcOverEthernet(sc->sc_pd, pb); + + return; + +drop: + pbuf_free(pb); +} + +static err_t +pppoe_output(struct pppoe_softc *sc, struct pbuf *pb) +{ + struct eth_hdr *ethhdr; + u16_t etype; + err_t res; + + if (!sc->sc_ethif) { + pbuf_free(pb); + return ERR_IF; + } + + ethhdr = (struct eth_hdr *)pb->payload; + etype = sc->sc_state == PPPOE_STATE_SESSION ? ETHTYPE_PPPOE : ETHTYPE_PPPOEDISC; + ethhdr->type = htons(etype); + MEMCPY(ethhdr->dest.addr, sc->sc_dest.addr, sizeof(ethhdr->dest.addr)); + MEMCPY(ethhdr->src.addr, ((struct eth_addr *)sc->sc_ethif->hwaddr)->addr, sizeof(ethhdr->src.addr)); + + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F" (%x) state=%d, session=0x%x output -> %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F", len=%d\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, etype, + sc->sc_state, sc->sc_session, + sc->sc_dest.addr[0], sc->sc_dest.addr[1], sc->sc_dest.addr[2], sc->sc_dest.addr[3], sc->sc_dest.addr[4], sc->sc_dest.addr[5], + pb->tot_len)); + + res = sc->sc_ethif->linkoutput(sc->sc_ethif, pb); + + pbuf_free(pb); + + return res; +} + +static err_t +pppoe_send_padi(struct pppoe_softc *sc) +{ + struct pbuf *pb; + u8_t *p; + int len; +#ifdef PPPOE_TODO + int l1 = 0, l2 = 0; /* XXX: gcc */ +#endif /* PPPOE_TODO */ + + if (sc->sc_state >PPPOE_STATE_PADI_SENT) { + PPPDEBUG(LOG_ERR, ("ERROR: pppoe_send_padi in state %d", sc->sc_state)); + } + + /* calculate length of frame (excluding ethernet header + pppoe header) */ + len = 2 + 2 + 2 + 2 + sizeof sc; /* service name tag is required, host unique is send too */ +#ifdef PPPOE_TODO + if (sc->sc_service_name != NULL) { + l1 = (int)strlen(sc->sc_service_name); + len += l1; + } + if (sc->sc_concentrator_name != NULL) { + l2 = (int)strlen(sc->sc_concentrator_name); + len += 2 + 2 + l2; + } +#endif /* PPPOE_TODO */ + LWIP_ASSERT("sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff", + sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff); + + /* allocate a buffer */ + pb = pbuf_alloc(PBUF_LINK, (u16_t)(sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len), PBUF_RAM); + if (!pb) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + + p = (u8_t*)pb->payload + sizeof (struct eth_hdr); + /* fill in pkt */ + PPPOE_ADD_HEADER(p, PPPOE_CODE_PADI, 0, (u16_t)len); + PPPOE_ADD_16(p, PPPOE_TAG_SNAME); +#ifdef PPPOE_TODO + if (sc->sc_service_name != NULL) { + PPPOE_ADD_16(p, l1); + MEMCPY(p, sc->sc_service_name, l1); + p += l1; + } else +#endif /* PPPOE_TODO */ + { + PPPOE_ADD_16(p, 0); + } +#ifdef PPPOE_TODO + if (sc->sc_concentrator_name != NULL) { + PPPOE_ADD_16(p, PPPOE_TAG_ACNAME); + PPPOE_ADD_16(p, l2); + MEMCPY(p, sc->sc_concentrator_name, l2); + p += l2; + } +#endif /* PPPOE_TODO */ + PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); + PPPOE_ADD_16(p, sizeof(sc)); + MEMCPY(p, &sc, sizeof sc); + + /* send pkt */ + return pppoe_output(sc, pb); +} + +static void +pppoe_timeout(void *arg) +{ + int retry_wait, err; + struct pppoe_softc *sc = (struct pppoe_softc*)arg; + + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": timeout\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + + switch (sc->sc_state) { + case PPPOE_STATE_PADI_SENT: + /* + * We have two basic ways of retrying: + * - Quick retry mode: try a few times in short sequence + * - Slow retry mode: we already had a connection successfully + * established and will try infinitely (without user + * intervention) + * We only enter slow retry mode if IFF_LINK1 (aka autodial) + * is not set. + */ + + /* initialize for quick retry mode */ + retry_wait = PPPOE_DISC_TIMEOUT * (1 + sc->sc_padi_retried); + + sc->sc_padi_retried++; + if (sc->sc_padi_retried >= PPPOE_DISC_MAXPADI) { +#if 0 + if ((sc->sc_sppp.pp_if.if_flags & IFF_LINK1) == 0) { + /* slow retry mode */ + retry_wait = PPPOE_SLOW_RETRY; + } else +#endif + { + pppoe_abort_connect(sc); + return; + } + } + if ((err = pppoe_send_padi(sc)) != 0) { + sc->sc_padi_retried--; + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to transmit PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); + } + sys_timeout(retry_wait, pppoe_timeout, sc); + break; + + case PPPOE_STATE_PADR_SENT: + sc->sc_padr_retried++; + if (sc->sc_padr_retried >= PPPOE_DISC_MAXPADR) { + MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); + sc->sc_state = PPPOE_STATE_PADI_SENT; + sc->sc_padr_retried = 0; + if ((err = pppoe_send_padi(sc)) != 0) { + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); + } + sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padi_retried), pppoe_timeout, sc); + return; + } + if ((err = pppoe_send_padr(sc)) != 0) { + sc->sc_padr_retried--; + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADR, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); + } + sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padr_retried), pppoe_timeout, sc); + break; + case PPPOE_STATE_CLOSING: + pppoe_do_disconnect(sc); + break; + default: + return; /* all done, work in peace */ + } +} + +/* Start a connection (i.e. initiate discovery phase) */ +int +pppoe_connect(struct pppoe_softc *sc) +{ + int err; + + if (sc->sc_state != PPPOE_STATE_INITIAL) { + return EBUSY; + } + +#ifdef PPPOE_SERVER + /* wait PADI if IFF_PASSIVE */ + if ((sc->sc_sppp.pp_if.if_flags & IFF_PASSIVE)) { + return 0; + } +#endif + /* save state, in case we fail to send PADI */ + sc->sc_state = PPPOE_STATE_PADI_SENT; + sc->sc_padr_retried = 0; + err = pppoe_send_padi(sc); + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); + sys_timeout(PPPOE_DISC_TIMEOUT, pppoe_timeout, sc); + return err; +} + +/* disconnect */ +void +pppoe_disconnect(struct pppoe_softc *sc) +{ + if (sc->sc_state < PPPOE_STATE_SESSION) { + return; + } + /* + * Do not call pppoe_disconnect here, the upper layer state + * machine gets confused by this. We must return from this + * function and defer disconnecting to the timeout handler. + */ + sc->sc_state = PPPOE_STATE_CLOSING; + sys_timeout(20, pppoe_timeout, sc); +} + +static int +pppoe_do_disconnect(struct pppoe_softc *sc) +{ + int err; + + if (sc->sc_state < PPPOE_STATE_SESSION) { + err = EBUSY; + } else { + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": disconnecting\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + err = pppoe_send_padt(sc->sc_ethif, sc->sc_session, (const u8_t *)&sc->sc_dest); + } + + /* cleanup softc */ + sc->sc_state = PPPOE_STATE_INITIAL; + MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); + sc->sc_ac_cookie_len = 0; +#ifdef PPPOE_SERVER + if (sc->sc_hunique) { + mem_free(sc->sc_hunique); + sc->sc_hunique = NULL; + } + sc->sc_hunique_len = 0; +#endif + sc->sc_session = 0; + + sc->sc_linkStatusCB(sc->sc_pd, 0); /* notify upper layers */ + + return err; +} + +/* Connection attempt aborted */ +static void +pppoe_abort_connect(struct pppoe_softc *sc) +{ + printf("%c%c%"U16_F": could not establish connection\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num); + sc->sc_state = PPPOE_STATE_CLOSING; + + sc->sc_linkStatusCB(sc->sc_pd, 0); /* notify upper layers */ + + /* clear connection state */ + MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); + sc->sc_state = PPPOE_STATE_INITIAL; +} + +/* Send a PADR packet */ +static err_t +pppoe_send_padr(struct pppoe_softc *sc) +{ + struct pbuf *pb; + u8_t *p; + size_t len; +#ifdef PPPOE_TODO + size_t l1 = 0; /* XXX: gcc */ +#endif /* PPPOE_TODO */ + + if (sc->sc_state != PPPOE_STATE_PADR_SENT) { + return ERR_CONN; + } + + len = 2 + 2 + 2 + 2 + sizeof(sc); /* service name, host unique */ +#ifdef PPPOE_TODO + if (sc->sc_service_name != NULL) { /* service name tag maybe empty */ + l1 = strlen(sc->sc_service_name); + len += l1; + } +#endif /* PPPOE_TODO */ + if (sc->sc_ac_cookie_len > 0) { + len += 2 + 2 + sc->sc_ac_cookie_len; /* AC cookie */ + } + LWIP_ASSERT("sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff", + sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff); + pb = pbuf_alloc(PBUF_LINK, (u16_t)(sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len), PBUF_RAM); + if (!pb) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + p = (u8_t*)pb->payload + sizeof (struct eth_hdr); + PPPOE_ADD_HEADER(p, PPPOE_CODE_PADR, 0, len); + PPPOE_ADD_16(p, PPPOE_TAG_SNAME); +#ifdef PPPOE_TODO + if (sc->sc_service_name != NULL) { + PPPOE_ADD_16(p, l1); + MEMCPY(p, sc->sc_service_name, l1); + p += l1; + } else +#endif /* PPPOE_TODO */ + { + PPPOE_ADD_16(p, 0); + } + if (sc->sc_ac_cookie_len > 0) { + PPPOE_ADD_16(p, PPPOE_TAG_ACCOOKIE); + PPPOE_ADD_16(p, sc->sc_ac_cookie_len); + MEMCPY(p, sc->sc_ac_cookie, sc->sc_ac_cookie_len); + p += sc->sc_ac_cookie_len; + } + PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); + PPPOE_ADD_16(p, sizeof(sc)); + MEMCPY(p, &sc, sizeof sc); + + return pppoe_output(sc, pb); +} + +/* send a PADT packet */ +static err_t +pppoe_send_padt(struct netif *outgoing_if, u_int session, const u8_t *dest) +{ + struct pbuf *pb; + struct eth_hdr *ethhdr; + err_t res; + u8_t *p; + + pb = pbuf_alloc(PBUF_LINK, sizeof(struct eth_hdr) + PPPOE_HEADERLEN, PBUF_RAM); + if (!pb) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + + ethhdr = (struct eth_hdr *)pb->payload; + ethhdr->type = PP_HTONS(ETHTYPE_PPPOEDISC); + MEMCPY(ethhdr->dest.addr, dest, sizeof(ethhdr->dest.addr)); + MEMCPY(ethhdr->src.addr, ((struct eth_addr *)outgoing_if->hwaddr)->addr, sizeof(ethhdr->src.addr)); + + p = (u8_t*)(ethhdr + 1); + PPPOE_ADD_HEADER(p, PPPOE_CODE_PADT, session, 0); + + res = outgoing_if->linkoutput(outgoing_if, pb); + + pbuf_free(pb); + + return res; +} + +#ifdef PPPOE_SERVER +static err_t +pppoe_send_pado(struct pppoe_softc *sc) +{ + struct pbuf *pb; + u8_t *p; + size_t len; + + if (sc->sc_state != PPPOE_STATE_PADO_SENT) { + return ERR_CONN; + } + + /* calc length */ + len = 0; + /* include ac_cookie */ + len += 2 + 2 + sizeof(sc); + /* include hunique */ + len += 2 + 2 + sc->sc_hunique_len; + pb = pbuf_alloc(PBUF_LINK, sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len, PBUF_RAM); + if (!pb) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + p = (u8_t*)pb->payload + sizeof (struct eth_hdr); + PPPOE_ADD_HEADER(p, PPPOE_CODE_PADO, 0, len); + PPPOE_ADD_16(p, PPPOE_TAG_ACCOOKIE); + PPPOE_ADD_16(p, sizeof(sc)); + MEMCPY(p, &sc, sizeof(sc)); + p += sizeof(sc); + PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); + PPPOE_ADD_16(p, sc->sc_hunique_len); + MEMCPY(p, sc->sc_hunique, sc->sc_hunique_len); + return pppoe_output(sc, pb); +} + +static err_t +pppoe_send_pads(struct pppoe_softc *sc) +{ + struct pbuf *pb; + u8_t *p; + size_t len, l1 = 0; /* XXX: gcc */ + + if (sc->sc_state != PPPOE_STATE_PADO_SENT) { + return ERR_CONN; + } + + sc->sc_session = mono_time.tv_sec % 0xff + 1; + /* calc length */ + len = 0; + /* include hunique */ + len += 2 + 2 + 2 + 2 + sc->sc_hunique_len; /* service name, host unique*/ + if (sc->sc_service_name != NULL) { /* service name tag maybe empty */ + l1 = strlen(sc->sc_service_name); + len += l1; + } + pb = pbuf_alloc(PBUF_LINK, sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len, PBUF_RAM); + if (!pb) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + p = (u8_t*)pb->payload + sizeof (struct eth_hdr); + PPPOE_ADD_HEADER(p, PPPOE_CODE_PADS, sc->sc_session, len); + PPPOE_ADD_16(p, PPPOE_TAG_SNAME); + if (sc->sc_service_name != NULL) { + PPPOE_ADD_16(p, l1); + MEMCPY(p, sc->sc_service_name, l1); + p += l1; + } else { + PPPOE_ADD_16(p, 0); + } + PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); + PPPOE_ADD_16(p, sc->sc_hunique_len); + MEMCPY(p, sc->sc_hunique, sc->sc_hunique_len); + return pppoe_output(sc, pb); +} +#endif + +err_t +pppoe_xmit(struct pppoe_softc *sc, struct pbuf *pb) +{ + u8_t *p; + size_t len; + + /* are we ready to process data yet? */ + if (sc->sc_state < PPPOE_STATE_SESSION) { + /*sppp_flush(&sc->sc_sppp.pp_if);*/ + pbuf_free(pb); + return ERR_CONN; + } + + len = pb->tot_len; + + /* make room for Ethernet header - should not fail */ + if (pbuf_header(pb, sizeof(struct eth_hdr) + PPPOE_HEADERLEN) != 0) { + /* bail out */ + PPPDEBUG(LOG_ERR, ("pppoe: %c%c%"U16_F": pppoe_xmit: could not allocate room for header\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + LINK_STATS_INC(link.lenerr); + pbuf_free(pb); + return ERR_BUF; + } + + p = (u8_t*)pb->payload + sizeof(struct eth_hdr); + PPPOE_ADD_HEADER(p, 0, sc->sc_session, len); + + return pppoe_output(sc, pb); +} + +#if 0 /*def PFIL_HOOKS*/ +static int +pppoe_ifattach_hook(void *arg, struct pbuf **mp, struct netif *ifp, int dir) +{ + struct pppoe_softc *sc; + int s; + + if (mp != (struct pbuf **)PFIL_IFNET_DETACH) { + return 0; + } + + LIST_FOREACH(sc, &pppoe_softc_list, sc_list) { + if (sc->sc_ethif != ifp) { + continue; + } + if (sc->sc_sppp.pp_if.if_flags & IFF_UP) { + sc->sc_sppp.pp_if.if_flags &= ~(IFF_UP|IFF_RUNNING); + printf("%c%c%"U16_F": ethernet interface detached, going down\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num); + } + sc->sc_ethif = NULL; + pppoe_clear_softc(sc, "ethernet interface detached"); + } + + return 0; +} +#endif + +static void +pppoe_clear_softc(struct pppoe_softc *sc, const char *message) +{ + LWIP_UNUSED_ARG(message); + + /* stop timer */ + sys_untimeout(pppoe_timeout, sc); + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": session 0x%x terminated, %s\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, sc->sc_session, message)); + + /* fix our state */ + sc->sc_state = PPPOE_STATE_INITIAL; + + /* notify upper layers */ + sc->sc_linkStatusCB(sc->sc_pd, 0); + + /* clean up softc */ + MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); + sc->sc_ac_cookie_len = 0; + sc->sc_session = 0; +} + +#endif /* PPPOE_SUPPORT */ + diff --git a/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/pppdebug.h b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/pppdebug.h new file mode 100644 index 0000000..8134997 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/pppdebug.h @@ -0,0 +1,73 @@ +/***************************************************************************** +* pppdebug.h - System debugging utilities. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1998 Global Election Systems Inc. +* portions Copyright (c) 2001 by Cognizant Pty Ltd. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY (please don't use tabs!) +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 98-07-29 Guy Lancaster , Global Election Systems Inc. +* Original. +* +***************************************************************************** +*/ +#ifndef PPPDEBUG_H +#define PPPDEBUG_H + +/* Trace levels. */ +#define LOG_CRITICAL (PPP_DEBUG | LWIP_DBG_LEVEL_SEVERE) +#define LOG_ERR (PPP_DEBUG | LWIP_DBG_LEVEL_SEVERE) +#define LOG_NOTICE (PPP_DEBUG | LWIP_DBG_LEVEL_WARNING) +#define LOG_WARNING (PPP_DEBUG | LWIP_DBG_LEVEL_WARNING) +#define LOG_INFO (PPP_DEBUG) +#define LOG_DETAIL (PPP_DEBUG) +#define LOG_DEBUG (PPP_DEBUG) + + +#define TRACELCP PPP_DEBUG + +#if PPP_DEBUG + +#define AUTHDEBUG(a, b) LWIP_DEBUGF(a, b) +#define IPCPDEBUG(a, b) LWIP_DEBUGF(a, b) +#define UPAPDEBUG(a, b) LWIP_DEBUGF(a, b) +#define LCPDEBUG(a, b) LWIP_DEBUGF(a, b) +#define FSMDEBUG(a, b) LWIP_DEBUGF(a, b) +#define CHAPDEBUG(a, b) LWIP_DEBUGF(a, b) +#define PPPDEBUG(a, b) LWIP_DEBUGF(a, b) + +#else /* PPP_DEBUG */ + +#define AUTHDEBUG(a, b) +#define IPCPDEBUG(a, b) +#define UPAPDEBUG(a, b) +#define LCPDEBUG(a, b) +#define FSMDEBUG(a, b) +#define CHAPDEBUG(a, b) +#define PPPDEBUG(a, b) + +#endif /* PPP_DEBUG */ + +#endif /* PPPDEBUG_H */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/randm.c b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/randm.c new file mode 100644 index 0000000..b736091 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/randm.c @@ -0,0 +1,249 @@ +/***************************************************************************** +* randm.c - Random number generator program file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* Copyright (c) 1998 by Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 98-06-03 Guy Lancaster , Global Election Systems Inc. +* Extracted from avos. +*****************************************************************************/ + +#include "lwip/opt.h" + +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "md5.h" +#include "randm.h" + +#include "ppp_impl.h" +#include "pppdebug.h" + +#include + +#if MD5_SUPPORT /* this module depends on MD5 */ +#define RANDPOOLSZ 16 /* Bytes stored in the pool of randomness. */ + +/*****************************/ +/*** LOCAL DATA STRUCTURES ***/ +/*****************************/ +static char randPool[RANDPOOLSZ]; /* Pool of randomness. */ +static long randCount = 0; /* Pseudo-random incrementer */ + + +/***********************************/ +/*** PUBLIC FUNCTION DEFINITIONS ***/ +/***********************************/ +/* + * Initialize the random number generator. + * + * Since this is to be called on power up, we don't have much + * system randomess to work with. Here all we use is the + * real-time clock. We'll accumulate more randomness as soon + * as things start happening. + */ +void +avRandomInit() +{ + avChurnRand(NULL, 0); +} + +/* + * Churn the randomness pool on a random event. Call this early and often + * on random and semi-random system events to build randomness in time for + * usage. For randomly timed events, pass a null pointer and a zero length + * and this will use the system timer and other sources to add randomness. + * If new random data is available, pass a pointer to that and it will be + * included. + * + * Ref: Applied Cryptography 2nd Ed. by Bruce Schneier p. 427 + */ +void +avChurnRand(char *randData, u32_t randLen) +{ + MD5_CTX md5; + + /* LWIP_DEBUGF(LOG_INFO, ("churnRand: %u@%P\n", randLen, randData)); */ + MD5Init(&md5); + MD5Update(&md5, (u_char *)randPool, sizeof(randPool)); + if (randData) { + MD5Update(&md5, (u_char *)randData, randLen); + } else { + struct { + /* INCLUDE fields for any system sources of randomness */ + char foobar; + } sysData; + + /* Load sysData fields here. */ + MD5Update(&md5, (u_char *)&sysData, sizeof(sysData)); + } + MD5Final((u_char *)randPool, &md5); +/* LWIP_DEBUGF(LOG_INFO, ("churnRand: -> 0\n")); */ +} + +/* + * Use the random pool to generate random data. This degrades to pseudo + * random when used faster than randomness is supplied using churnRand(). + * Note: It's important that there be sufficient randomness in randPool + * before this is called for otherwise the range of the result may be + * narrow enough to make a search feasible. + * + * Ref: Applied Cryptography 2nd Ed. by Bruce Schneier p. 427 + * + * XXX Why does he not just call churnRand() for each block? Probably + * so that you don't ever publish the seed which could possibly help + * predict future values. + * XXX Why don't we preserve md5 between blocks and just update it with + * randCount each time? Probably there is a weakness but I wish that + * it was documented. + */ +void +avGenRand(char *buf, u32_t bufLen) +{ + MD5_CTX md5; + u_char tmp[16]; + u32_t n; + + while (bufLen > 0) { + n = LWIP_MIN(bufLen, RANDPOOLSZ); + MD5Init(&md5); + MD5Update(&md5, (u_char *)randPool, sizeof(randPool)); + MD5Update(&md5, (u_char *)&randCount, sizeof(randCount)); + MD5Final(tmp, &md5); + randCount++; + MEMCPY(buf, tmp, n); + buf += n; + bufLen -= n; + } +} + +/* + * Return a new random number. + */ +u32_t +avRandom() +{ + u32_t newRand; + + avGenRand((char *)&newRand, sizeof(newRand)); + + return newRand; +} + +#else /* MD5_SUPPORT */ + +/*****************************/ +/*** LOCAL DATA STRUCTURES ***/ +/*****************************/ +static int avRandomized = 0; /* Set when truely randomized. */ +static u32_t avRandomSeed = 0; /* Seed used for random number generation. */ + + +/***********************************/ +/*** PUBLIC FUNCTION DEFINITIONS ***/ +/***********************************/ +/* + * Initialize the random number generator. + * + * Here we attempt to compute a random number seed but even if + * it isn't random, we'll randomize it later. + * + * The current method uses the fields from the real time clock, + * the idle process counter, the millisecond counter, and the + * hardware timer tick counter. When this is invoked + * in startup(), then the idle counter and timer values may + * repeat after each boot and the real time clock may not be + * operational. Thus we call it again on the first random + * event. + */ +void +avRandomInit() +{ +#if 0 + /* Get a pointer into the last 4 bytes of clockBuf. */ + u32_t *lptr1 = (u32_t *)((char *)&clockBuf[3]); + + /* + * Initialize our seed using the real-time clock, the idle + * counter, the millisecond timer, and the hardware timer + * tick counter. The real-time clock and the hardware + * tick counter are the best sources of randomness but + * since the tick counter is only 16 bit (and truncated + * at that), the idle counter and millisecond timer + * (which may be small values) are added to help + * randomize the lower 16 bits of the seed. + */ + readClk(); + avRandomSeed += *(u32_t *)clockBuf + *lptr1 + OSIdleCtr + + ppp_mtime() + ((u32_t)TM1 << 16) + TM1; +#else + avRandomSeed += sys_jiffies(); /* XXX */ +#endif + + /* Initialize the Borland random number generator. */ + srand((unsigned)avRandomSeed); +} + +/* + * Randomize our random seed value. Here we use the fact that + * this function is called at *truely random* times by the polling + * and network functions. Here we only get 16 bits of new random + * value but we use the previous value to randomize the other 16 + * bits. + */ +void +avRandomize(void) +{ + static u32_t last_jiffies; + + if (!avRandomized) { + avRandomized = !0; + avRandomInit(); + /* The initialization function also updates the seed. */ + } else { + /* avRandomSeed += (avRandomSeed << 16) + TM1; */ + avRandomSeed += (sys_jiffies() - last_jiffies); /* XXX */ + } + last_jiffies = sys_jiffies(); +} + +/* + * Return a new random number. + * Here we use the Borland rand() function to supply a pseudo random + * number which we make truely random by combining it with our own + * seed which is randomized by truely random events. + * Thus the numbers will be truely random unless there have been no + * operator or network events in which case it will be pseudo random + * seeded by the real time clock. + */ +u32_t +avRandom() +{ + return ((((u32_t)rand() << 16) + rand()) + avRandomSeed); +} + +#endif /* MD5_SUPPORT */ + +#endif /* PPP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/randm.h b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/randm.h new file mode 100644 index 0000000..a0984b0 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/randm.h @@ -0,0 +1,81 @@ +/***************************************************************************** +* randm.h - Random number generator header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* Copyright (c) 1998 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 98-05-29 Guy Lancaster , Global Election Systems Inc. +* Extracted from avos. +*****************************************************************************/ + +#ifndef RANDM_H +#define RANDM_H + +/*********************** +*** PUBLIC FUNCTIONS *** +***********************/ +/* + * Initialize the random number generator. + */ +void avRandomInit(void); + +/* + * Churn the randomness pool on a random event. Call this early and often + * on random and semi-random system events to build randomness in time for + * usage. For randomly timed events, pass a null pointer and a zero length + * and this will use the system timer and other sources to add randomness. + * If new random data is available, pass a pointer to that and it will be + * included. + */ +void avChurnRand(char *randData, u32_t randLen); + +/* + * Randomize our random seed value. To be called for truely random events + * such as user operations and network traffic. + */ +#if MD5_SUPPORT +#define avRandomize() avChurnRand(NULL, 0) +#else /* MD5_SUPPORT */ +void avRandomize(void); +#endif /* MD5_SUPPORT */ + +/* + * Use the random pool to generate random data. This degrades to pseudo + * random when used faster than randomness is supplied using churnRand(). + * Thus it's important to make sure that the results of this are not + * published directly because one could predict the next result to at + * least some degree. Also, it's important to get a good seed before + * the first use. + */ +void avGenRand(char *buf, u32_t bufLen); + +/* + * Return a new random number. + */ +u32_t avRandom(void); + + +#endif /* RANDM_H */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/vj.c b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/vj.c new file mode 100644 index 0000000..40fdad1 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/vj.c @@ -0,0 +1,652 @@ +/* + * Routines to compress and uncompess tcp packets (for transmission + * over low speed serial lines. + * + * Copyright (c) 1989 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989: + * Initial distribution. + * + * Modified June 1993 by Paul Mackerras, paulus@cs.anu.edu.au, + * so that the entire packet being decompressed doesn't have + * to be in contiguous memory (just the compressed header). + * + * Modified March 1998 by Guy Lancaster, glanca@gesn.com, + * for a 16 bit processor. + */ + +#include "lwip/opt.h" + +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "ppp_impl.h" +#include "pppdebug.h" + +#include "vj.h" + +#include + +#if VJ_SUPPORT + +#if LINK_STATS +#define INCR(counter) ++comp->stats.counter +#else +#define INCR(counter) +#endif + +void +vj_compress_init(struct vjcompress *comp) +{ + register u_char i; + register struct cstate *tstate = comp->tstate; + +#if MAX_SLOTS == 0 + memset((char *)comp, 0, sizeof(*comp)); +#endif + comp->maxSlotIndex = MAX_SLOTS - 1; + comp->compressSlot = 0; /* Disable slot ID compression by default. */ + for (i = MAX_SLOTS - 1; i > 0; --i) { + tstate[i].cs_id = i; + tstate[i].cs_next = &tstate[i - 1]; + } + tstate[0].cs_next = &tstate[MAX_SLOTS - 1]; + tstate[0].cs_id = 0; + comp->last_cs = &tstate[0]; + comp->last_recv = 255; + comp->last_xmit = 255; + comp->flags = VJF_TOSS; +} + + +/* ENCODE encodes a number that is known to be non-zero. ENCODEZ + * checks for zero (since zero has to be encoded in the long, 3 byte + * form). + */ +#define ENCODE(n) { \ + if ((u_short)(n) >= 256) { \ + *cp++ = 0; \ + cp[1] = (u_char)(n); \ + cp[0] = (u_char)((n) >> 8); \ + cp += 2; \ + } else { \ + *cp++ = (u_char)(n); \ + } \ +} +#define ENCODEZ(n) { \ + if ((u_short)(n) >= 256 || (u_short)(n) == 0) { \ + *cp++ = 0; \ + cp[1] = (u_char)(n); \ + cp[0] = (u_char)((n) >> 8); \ + cp += 2; \ + } else { \ + *cp++ = (u_char)(n); \ + } \ +} + +#define DECODEL(f) { \ + if (*cp == 0) {\ + u32_t tmp = ntohl(f) + ((cp[1] << 8) | cp[2]); \ + (f) = htonl(tmp); \ + cp += 3; \ + } else { \ + u32_t tmp = ntohl(f) + (u32_t)*cp++; \ + (f) = htonl(tmp); \ + } \ +} + +#define DECODES(f) { \ + if (*cp == 0) {\ + u_short tmp = ntohs(f) + (((u_short)cp[1] << 8) | cp[2]); \ + (f) = htons(tmp); \ + cp += 3; \ + } else { \ + u_short tmp = ntohs(f) + (u_short)*cp++; \ + (f) = htons(tmp); \ + } \ +} + +#define DECODEU(f) { \ + if (*cp == 0) {\ + (f) = htons(((u_short)cp[1] << 8) | cp[2]); \ + cp += 3; \ + } else { \ + (f) = htons((u_short)*cp++); \ + } \ +} + +/* + * vj_compress_tcp - Attempt to do Van Jacobson header compression on a + * packet. This assumes that nb and comp are not null and that the first + * buffer of the chain contains a valid IP header. + * Return the VJ type code indicating whether or not the packet was + * compressed. + */ +u_int +vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb) +{ + register struct ip_hdr *ip = (struct ip_hdr *)pb->payload; + register struct cstate *cs = comp->last_cs->cs_next; + register u_short hlen = IPH_HL(ip); + register struct tcp_hdr *oth; + register struct tcp_hdr *th; + register u_short deltaS, deltaA; + register u_long deltaL; + register u_int changes = 0; + u_char new_seq[16]; + register u_char *cp = new_seq; + + /* + * Check that the packet is IP proto TCP. + */ + if (IPH_PROTO(ip) != IP_PROTO_TCP) { + return (TYPE_IP); + } + + /* + * Bail if this is an IP fragment or if the TCP packet isn't + * `compressible' (i.e., ACK isn't set or some other control bit is + * set). + */ + if ((IPH_OFFSET(ip) & PP_HTONS(0x3fff)) || pb->tot_len < 40) { + return (TYPE_IP); + } + th = (struct tcp_hdr *)&((long *)ip)[hlen]; + if ((TCPH_FLAGS(th) & (TCP_SYN|TCP_FIN|TCP_RST|TCP_ACK)) != TCP_ACK) { + return (TYPE_IP); + } + /* + * Packet is compressible -- we're going to send either a + * COMPRESSED_TCP or UNCOMPRESSED_TCP packet. Either way we need + * to locate (or create) the connection state. Special case the + * most recently used connection since it's most likely to be used + * again & we don't have to do any reordering if it's used. + */ + INCR(vjs_packets); + if (!ip_addr_cmp(&ip->src, &cs->cs_ip.src) + || !ip_addr_cmp(&ip->dest, &cs->cs_ip.dest) + || *(long *)th != ((long *)&cs->cs_ip)[IPH_HL(&cs->cs_ip)]) { + /* + * Wasn't the first -- search for it. + * + * States are kept in a circularly linked list with + * last_cs pointing to the end of the list. The + * list is kept in lru order by moving a state to the + * head of the list whenever it is referenced. Since + * the list is short and, empirically, the connection + * we want is almost always near the front, we locate + * states via linear search. If we don't find a state + * for the datagram, the oldest state is (re-)used. + */ + register struct cstate *lcs; + register struct cstate *lastcs = comp->last_cs; + + do { + lcs = cs; cs = cs->cs_next; + INCR(vjs_searches); + if (ip_addr_cmp(&ip->src, &cs->cs_ip.src) + && ip_addr_cmp(&ip->dest, &cs->cs_ip.dest) + && *(long *)th == ((long *)&cs->cs_ip)[IPH_HL(&cs->cs_ip)]) { + goto found; + } + } while (cs != lastcs); + + /* + * Didn't find it -- re-use oldest cstate. Send an + * uncompressed packet that tells the other side what + * connection number we're using for this conversation. + * Note that since the state list is circular, the oldest + * state points to the newest and we only need to set + * last_cs to update the lru linkage. + */ + INCR(vjs_misses); + comp->last_cs = lcs; + hlen += TCPH_HDRLEN(th); + hlen <<= 2; + /* Check that the IP/TCP headers are contained in the first buffer. */ + if (hlen > pb->len) { + return (TYPE_IP); + } + goto uncompressed; + + found: + /* + * Found it -- move to the front on the connection list. + */ + if (cs == lastcs) { + comp->last_cs = lcs; + } else { + lcs->cs_next = cs->cs_next; + cs->cs_next = lastcs->cs_next; + lastcs->cs_next = cs; + } + } + + oth = (struct tcp_hdr *)&((long *)&cs->cs_ip)[hlen]; + deltaS = hlen; + hlen += TCPH_HDRLEN(th); + hlen <<= 2; + /* Check that the IP/TCP headers are contained in the first buffer. */ + if (hlen > pb->len) { + PPPDEBUG(LOG_INFO, ("vj_compress_tcp: header len %d spans buffers\n", hlen)); + return (TYPE_IP); + } + + /* + * Make sure that only what we expect to change changed. The first + * line of the `if' checks the IP protocol version, header length & + * type of service. The 2nd line checks the "Don't fragment" bit. + * The 3rd line checks the time-to-live and protocol (the protocol + * check is unnecessary but costless). The 4th line checks the TCP + * header length. The 5th line checks IP options, if any. The 6th + * line checks TCP options, if any. If any of these things are + * different between the previous & current datagram, we send the + * current datagram `uncompressed'. + */ + if (((u_short *)ip)[0] != ((u_short *)&cs->cs_ip)[0] + || ((u_short *)ip)[3] != ((u_short *)&cs->cs_ip)[3] + || ((u_short *)ip)[4] != ((u_short *)&cs->cs_ip)[4] + || TCPH_HDRLEN(th) != TCPH_HDRLEN(oth) + || (deltaS > 5 && BCMP(ip + 1, &cs->cs_ip + 1, (deltaS - 5) << 2)) + || (TCPH_HDRLEN(th) > 5 && BCMP(th + 1, oth + 1, (TCPH_HDRLEN(th) - 5) << 2))) { + goto uncompressed; + } + + /* + * Figure out which of the changing fields changed. The + * receiver expects changes in the order: urgent, window, + * ack, seq (the order minimizes the number of temporaries + * needed in this section of code). + */ + if (TCPH_FLAGS(th) & TCP_URG) { + deltaS = ntohs(th->urgp); + ENCODEZ(deltaS); + changes |= NEW_U; + } else if (th->urgp != oth->urgp) { + /* argh! URG not set but urp changed -- a sensible + * implementation should never do this but RFC793 + * doesn't prohibit the change so we have to deal + * with it. */ + goto uncompressed; + } + + if ((deltaS = (u_short)(ntohs(th->wnd) - ntohs(oth->wnd))) != 0) { + ENCODE(deltaS); + changes |= NEW_W; + } + + if ((deltaL = ntohl(th->ackno) - ntohl(oth->ackno)) != 0) { + if (deltaL > 0xffff) { + goto uncompressed; + } + deltaA = (u_short)deltaL; + ENCODE(deltaA); + changes |= NEW_A; + } + + if ((deltaL = ntohl(th->seqno) - ntohl(oth->seqno)) != 0) { + if (deltaL > 0xffff) { + goto uncompressed; + } + deltaS = (u_short)deltaL; + ENCODE(deltaS); + changes |= NEW_S; + } + + switch(changes) { + case 0: + /* + * Nothing changed. If this packet contains data and the + * last one didn't, this is probably a data packet following + * an ack (normal on an interactive connection) and we send + * it compressed. Otherwise it's probably a retransmit, + * retransmitted ack or window probe. Send it uncompressed + * in case the other side missed the compressed version. + */ + if (IPH_LEN(ip) != IPH_LEN(&cs->cs_ip) && + ntohs(IPH_LEN(&cs->cs_ip)) == hlen) { + break; + } + + /* (fall through) */ + + case SPECIAL_I: + case SPECIAL_D: + /* + * actual changes match one of our special case encodings -- + * send packet uncompressed. + */ + goto uncompressed; + + case NEW_S|NEW_A: + if (deltaS == deltaA && deltaS == ntohs(IPH_LEN(&cs->cs_ip)) - hlen) { + /* special case for echoed terminal traffic */ + changes = SPECIAL_I; + cp = new_seq; + } + break; + + case NEW_S: + if (deltaS == ntohs(IPH_LEN(&cs->cs_ip)) - hlen) { + /* special case for data xfer */ + changes = SPECIAL_D; + cp = new_seq; + } + break; + } + + deltaS = (u_short)(ntohs(IPH_ID(ip)) - ntohs(IPH_ID(&cs->cs_ip))); + if (deltaS != 1) { + ENCODEZ(deltaS); + changes |= NEW_I; + } + if (TCPH_FLAGS(th) & TCP_PSH) { + changes |= TCP_PUSH_BIT; + } + /* + * Grab the cksum before we overwrite it below. Then update our + * state with this packet's header. + */ + deltaA = ntohs(th->chksum); + BCOPY(ip, &cs->cs_ip, hlen); + + /* + * We want to use the original packet as our compressed packet. + * (cp - new_seq) is the number of bytes we need for compressed + * sequence numbers. In addition we need one byte for the change + * mask, one for the connection id and two for the tcp checksum. + * So, (cp - new_seq) + 4 bytes of header are needed. hlen is how + * many bytes of the original packet to toss so subtract the two to + * get the new packet size. + */ + deltaS = (u_short)(cp - new_seq); + if (!comp->compressSlot || comp->last_xmit != cs->cs_id) { + comp->last_xmit = cs->cs_id; + hlen -= deltaS + 4; + if(pbuf_header(pb, -hlen)){ + /* Can we cope with this failing? Just assert for now */ + LWIP_ASSERT("pbuf_header failed\n", 0); + } + cp = (u_char *)pb->payload; + *cp++ = (u_char)(changes | NEW_C); + *cp++ = cs->cs_id; + } else { + hlen -= deltaS + 3; + if(pbuf_header(pb, -hlen)) { + /* Can we cope with this failing? Just assert for now */ + LWIP_ASSERT("pbuf_header failed\n", 0); + } + cp = (u_char *)pb->payload; + *cp++ = (u_char)changes; + } + *cp++ = (u_char)(deltaA >> 8); + *cp++ = (u_char)deltaA; + BCOPY(new_seq, cp, deltaS); + INCR(vjs_compressed); + return (TYPE_COMPRESSED_TCP); + + /* + * Update connection state cs & send uncompressed packet (that is, + * a regular ip/tcp packet but with the 'conversation id' we hope + * to use on future compressed packets in the protocol field). + */ +uncompressed: + BCOPY(ip, &cs->cs_ip, hlen); + IPH_PROTO_SET(ip, cs->cs_id); + comp->last_xmit = cs->cs_id; + return (TYPE_UNCOMPRESSED_TCP); +} + +/* + * Called when we may have missed a packet. + */ +void +vj_uncompress_err(struct vjcompress *comp) +{ + comp->flags |= VJF_TOSS; + INCR(vjs_errorin); +} + +/* + * "Uncompress" a packet of type TYPE_UNCOMPRESSED_TCP. + * Return 0 on success, -1 on failure. + */ +int +vj_uncompress_uncomp(struct pbuf *nb, struct vjcompress *comp) +{ + register u_int hlen; + register struct cstate *cs; + register struct ip_hdr *ip; + + ip = (struct ip_hdr *)nb->payload; + hlen = IPH_HL(ip) << 2; + if (IPH_PROTO(ip) >= MAX_SLOTS + || hlen + sizeof(struct tcp_hdr) > nb->len + || (hlen += TCPH_HDRLEN(((struct tcp_hdr *)&((char *)ip)[hlen])) << 2) + > nb->len + || hlen > MAX_HDR) { + PPPDEBUG(LOG_INFO, ("vj_uncompress_uncomp: bad cid=%d, hlen=%d buflen=%d\n", + IPH_PROTO(ip), hlen, nb->len)); + comp->flags |= VJF_TOSS; + INCR(vjs_errorin); + return -1; + } + cs = &comp->rstate[comp->last_recv = IPH_PROTO(ip)]; + comp->flags &=~ VJF_TOSS; + IPH_PROTO_SET(ip, IP_PROTO_TCP); + BCOPY(ip, &cs->cs_ip, hlen); + cs->cs_hlen = (u_short)hlen; + INCR(vjs_uncompressedin); + return 0; +} + +/* + * Uncompress a packet of type TYPE_COMPRESSED_TCP. + * The packet is composed of a buffer chain and the first buffer + * must contain an accurate chain length. + * The first buffer must include the entire compressed TCP/IP header. + * This procedure replaces the compressed header with the uncompressed + * header and returns the length of the VJ header. + */ +int +vj_uncompress_tcp(struct pbuf **nb, struct vjcompress *comp) +{ + u_char *cp; + struct tcp_hdr *th; + struct cstate *cs; + u_short *bp; + struct pbuf *n0 = *nb; + u32_t tmp; + u_int vjlen, hlen, changes; + + INCR(vjs_compressedin); + cp = (u_char *)n0->payload; + changes = *cp++; + if (changes & NEW_C) { + /* + * Make sure the state index is in range, then grab the state. + * If we have a good state index, clear the 'discard' flag. + */ + if (*cp >= MAX_SLOTS) { + PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: bad cid=%d\n", *cp)); + goto bad; + } + + comp->flags &=~ VJF_TOSS; + comp->last_recv = *cp++; + } else { + /* + * this packet has an implicit state index. If we've + * had a line error since the last time we got an + * explicit state index, we have to toss the packet. + */ + if (comp->flags & VJF_TOSS) { + PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: tossing\n")); + INCR(vjs_tossed); + return (-1); + } + } + cs = &comp->rstate[comp->last_recv]; + hlen = IPH_HL(&cs->cs_ip) << 2; + th = (struct tcp_hdr *)&((u_char *)&cs->cs_ip)[hlen]; + th->chksum = htons((*cp << 8) | cp[1]); + cp += 2; + if (changes & TCP_PUSH_BIT) { + TCPH_SET_FLAG(th, TCP_PSH); + } else { + TCPH_UNSET_FLAG(th, TCP_PSH); + } + + switch (changes & SPECIALS_MASK) { + case SPECIAL_I: + { + register u32_t i = ntohs(IPH_LEN(&cs->cs_ip)) - cs->cs_hlen; + /* some compilers can't nest inline assembler.. */ + tmp = ntohl(th->ackno) + i; + th->ackno = htonl(tmp); + tmp = ntohl(th->seqno) + i; + th->seqno = htonl(tmp); + } + break; + + case SPECIAL_D: + /* some compilers can't nest inline assembler.. */ + tmp = ntohl(th->seqno) + ntohs(IPH_LEN(&cs->cs_ip)) - cs->cs_hlen; + th->seqno = htonl(tmp); + break; + + default: + if (changes & NEW_U) { + TCPH_SET_FLAG(th, TCP_URG); + DECODEU(th->urgp); + } else { + TCPH_UNSET_FLAG(th, TCP_URG); + } + if (changes & NEW_W) { + DECODES(th->wnd); + } + if (changes & NEW_A) { + DECODEL(th->ackno); + } + if (changes & NEW_S) { + DECODEL(th->seqno); + } + break; + } + if (changes & NEW_I) { + DECODES(cs->cs_ip._id); + } else { + IPH_ID_SET(&cs->cs_ip, ntohs(IPH_ID(&cs->cs_ip)) + 1); + IPH_ID_SET(&cs->cs_ip, htons(IPH_ID(&cs->cs_ip))); + } + + /* + * At this point, cp points to the first byte of data in the + * packet. Fill in the IP total length and update the IP + * header checksum. + */ + vjlen = (u_short)(cp - (u_char*)n0->payload); + if (n0->len < vjlen) { + /* + * We must have dropped some characters (crc should detect + * this but the old slip framing won't) + */ + PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: head buffer %d too short %d\n", + n0->len, vjlen)); + goto bad; + } + +#if BYTE_ORDER == LITTLE_ENDIAN + tmp = n0->tot_len - vjlen + cs->cs_hlen; + IPH_LEN_SET(&cs->cs_ip, htons((u_short)tmp)); +#else + IPH_LEN_SET(&cs->cs_ip, htons(n0->tot_len - vjlen + cs->cs_hlen)); +#endif + + /* recompute the ip header checksum */ + bp = (u_short *) &cs->cs_ip; + IPH_CHKSUM_SET(&cs->cs_ip, 0); + for (tmp = 0; hlen > 0; hlen -= 2) { + tmp += *bp++; + } + tmp = (tmp & 0xffff) + (tmp >> 16); + tmp = (tmp & 0xffff) + (tmp >> 16); + IPH_CHKSUM_SET(&cs->cs_ip, (u_short)(~tmp)); + + /* Remove the compressed header and prepend the uncompressed header. */ + if(pbuf_header(n0, -((s16_t)(vjlen)))) { + /* Can we cope with this failing? Just assert for now */ + LWIP_ASSERT("pbuf_header failed\n", 0); + goto bad; + } + + if(LWIP_MEM_ALIGN(n0->payload) != n0->payload) { + struct pbuf *np, *q; + u8_t *bufptr; + + np = pbuf_alloc(PBUF_RAW, n0->len + cs->cs_hlen, PBUF_POOL); + if(!np) { + PPPDEBUG(LOG_WARNING, ("vj_uncompress_tcp: realign failed\n")); + goto bad; + } + + if(pbuf_header(np, -cs->cs_hlen)) { + /* Can we cope with this failing? Just assert for now */ + LWIP_ASSERT("pbuf_header failed\n", 0); + goto bad; + } + + bufptr = n0->payload; + for(q = np; q != NULL; q = q->next) { + MEMCPY(q->payload, bufptr, q->len); + bufptr += q->len; + } + + if(n0->next) { + pbuf_chain(np, n0->next); + pbuf_dechain(n0); + } + pbuf_free(n0); + n0 = np; + } + + if(pbuf_header(n0, cs->cs_hlen)) { + struct pbuf *np; + + LWIP_ASSERT("vj_uncompress_tcp: cs->cs_hlen <= PBUF_POOL_BUFSIZE", cs->cs_hlen <= PBUF_POOL_BUFSIZE); + np = pbuf_alloc(PBUF_RAW, cs->cs_hlen, PBUF_POOL); + if(!np) { + PPPDEBUG(LOG_WARNING, ("vj_uncompress_tcp: prepend failed\n")); + goto bad; + } + pbuf_cat(np, n0); + n0 = np; + } + LWIP_ASSERT("n0->len >= cs->cs_hlen", n0->len >= cs->cs_hlen); + MEMCPY(n0->payload, &cs->cs_ip, cs->cs_hlen); + + *nb = n0; + + return vjlen; + +bad: + comp->flags |= VJF_TOSS; + INCR(vjs_errorin); + return (-1); +} + +#endif /* VJ_SUPPORT */ + +#endif /* PPP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/vj.h b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/vj.h new file mode 100644 index 0000000..fad1213 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/netif/ppp/vj.h @@ -0,0 +1,156 @@ +/* + * Definitions for tcp compression routines. + * + * $Id: vj.h,v 1.7 2010/02/22 17:52:09 goldsimon Exp $ + * + * Copyright (c) 1989 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989: + * - Initial distribution. + */ + +#ifndef VJ_H +#define VJ_H + +#include "lwip/ip.h" +#include "lwip/tcp_impl.h" + +#define MAX_SLOTS 16 /* must be > 2 and < 256 */ +#define MAX_HDR 128 + +/* + * Compressed packet format: + * + * The first octet contains the packet type (top 3 bits), TCP + * 'push' bit, and flags that indicate which of the 4 TCP sequence + * numbers have changed (bottom 5 bits). The next octet is a + * conversation number that associates a saved IP/TCP header with + * the compressed packet. The next two octets are the TCP checksum + * from the original datagram. The next 0 to 15 octets are + * sequence number changes, one change per bit set in the header + * (there may be no changes and there are two special cases where + * the receiver implicitly knows what changed -- see below). + * + * There are 5 numbers which can change (they are always inserted + * in the following order): TCP urgent pointer, window, + * acknowlegement, sequence number and IP ID. (The urgent pointer + * is different from the others in that its value is sent, not the + * change in value.) Since typical use of SLIP links is biased + * toward small packets (see comments on MTU/MSS below), changes + * use a variable length coding with one octet for numbers in the + * range 1 - 255 and 3 octets (0, MSB, LSB) for numbers in the + * range 256 - 65535 or 0. (If the change in sequence number or + * ack is more than 65535, an uncompressed packet is sent.) + */ + +/* + * Packet types (must not conflict with IP protocol version) + * + * The top nibble of the first octet is the packet type. There are + * three possible types: IP (not proto TCP or tcp with one of the + * control flags set); uncompressed TCP (a normal IP/TCP packet but + * with the 8-bit protocol field replaced by an 8-bit connection id -- + * this type of packet syncs the sender & receiver); and compressed + * TCP (described above). + * + * LSB of 4-bit field is TCP "PUSH" bit (a worthless anachronism) and + * is logically part of the 4-bit "changes" field that follows. Top + * three bits are actual packet type. For backward compatibility + * and in the interest of conserving bits, numbers are chosen so the + * IP protocol version number (4) which normally appears in this nibble + * means "IP packet". + */ + +/* packet types */ +#define TYPE_IP 0x40 +#define TYPE_UNCOMPRESSED_TCP 0x70 +#define TYPE_COMPRESSED_TCP 0x80 +#define TYPE_ERROR 0x00 + +/* Bits in first octet of compressed packet */ +#define NEW_C 0x40 /* flag bits for what changed in a packet */ +#define NEW_I 0x20 +#define NEW_S 0x08 +#define NEW_A 0x04 +#define NEW_W 0x02 +#define NEW_U 0x01 + +/* reserved, special-case values of above */ +#define SPECIAL_I (NEW_S|NEW_W|NEW_U) /* echoed interactive traffic */ +#define SPECIAL_D (NEW_S|NEW_A|NEW_W|NEW_U) /* unidirectional data */ +#define SPECIALS_MASK (NEW_S|NEW_A|NEW_W|NEW_U) + +#define TCP_PUSH_BIT 0x10 + + +/* + * "state" data for each active tcp conversation on the wire. This is + * basically a copy of the entire IP/TCP header from the last packet + * we saw from the conversation together with a small identifier + * the transmit & receive ends of the line use to locate saved header. + */ +struct cstate { + struct cstate *cs_next; /* next most recently used state (xmit only) */ + u_short cs_hlen; /* size of hdr (receive only) */ + u_char cs_id; /* connection # associated with this state */ + u_char cs_filler; + union { + char csu_hdr[MAX_HDR]; + struct ip_hdr csu_ip; /* ip/tcp hdr from most recent packet */ + } vjcs_u; +}; +#define cs_ip vjcs_u.csu_ip +#define cs_hdr vjcs_u.csu_hdr + + +struct vjstat { + unsigned long vjs_packets; /* outbound packets */ + unsigned long vjs_compressed; /* outbound compressed packets */ + unsigned long vjs_searches; /* searches for connection state */ + unsigned long vjs_misses; /* times couldn't find conn. state */ + unsigned long vjs_uncompressedin; /* inbound uncompressed packets */ + unsigned long vjs_compressedin; /* inbound compressed packets */ + unsigned long vjs_errorin; /* inbound unknown type packets */ + unsigned long vjs_tossed; /* inbound packets tossed because of error */ +}; + +/* + * all the state data for one serial line (we need one of these per line). + */ +struct vjcompress { + struct cstate *last_cs; /* most recently used tstate */ + u_char last_recv; /* last rcvd conn. id */ + u_char last_xmit; /* last sent conn. id */ + u_short flags; + u_char maxSlotIndex; + u_char compressSlot; /* Flag indicating OK to compress slot ID. */ +#if LINK_STATS + struct vjstat stats; +#endif + struct cstate tstate[MAX_SLOTS]; /* xmit connection states */ + struct cstate rstate[MAX_SLOTS]; /* receive connection states */ +}; + +/* flag values */ +#define VJF_TOSS 1U /* tossing rcvd frames because of input err */ + +extern void vj_compress_init (struct vjcompress *comp); +extern u_int vj_compress_tcp (struct vjcompress *comp, struct pbuf *pb); +extern void vj_uncompress_err (struct vjcompress *comp); +extern int vj_uncompress_uncomp(struct pbuf *nb, struct vjcompress *comp); +extern int vj_uncompress_tcp (struct pbuf **nb, struct vjcompress *comp); + +#endif /* VJ_H */ diff --git a/component/common/network/lwip/lwip_v1.4.1/src/netif/slipif.c b/component/common/network/lwip/lwip_v1.4.1/src/netif/slipif.c new file mode 100644 index 0000000..2777630 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.4.1/src/netif/slipif.c @@ -0,0 +1,510 @@ +/** + * @file + * SLIP Interface + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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 Institute 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 INSTITUTE 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 INSTITUTE 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. + * + * This file is built upon the file: src/arch/rtxc/netif/sioslip.c + * + * Author: Magnus Ivarsson + * Simon Goldschmidt + * + * Usage: This netif can be used in three ways: + * 1) For NO_SYS==0, an RX thread can be used which blocks on sio_read() + * until data is received. + * 2) In your main loop, call slipif_poll() to check for new RX bytes, + * completed packets are fed into netif->input(). + * 3) Call slipif_received_byte[s]() from your serial RX ISR and + * slipif_process_rxqueue() from your main loop. ISR level decodes + * packets and puts completed packets on a queue which is fed into + * the stack from the main loop (needs SYS_LIGHTWEIGHT_PROT for + * pbuf_alloc to work on ISR level!). + * + */ + +/* + * This is an arch independent SLIP netif. The specific serial hooks must be + * provided by another file. They are sio_open, sio_read/sio_tryread and sio_send + */ + +#include "netif/slipif.h" +#include "lwip/opt.h" + +#if LWIP_HAVE_SLIPIF + +#include "lwip/def.h" +#include "lwip/pbuf.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "lwip/sio.h" +#include "lwip/sys.h" + +#define SLIP_END 0xC0 /* 0300: start and end of every packet */ +#define SLIP_ESC 0xDB /* 0333: escape start (one byte escaped data follows) */ +#define SLIP_ESC_END 0xDC /* 0334: following escape: original byte is 0xC0 (END) */ +#define SLIP_ESC_ESC 0xDD /* 0335: following escape: original byte is 0xDB (ESC) */ + +/** Maximum packet size that is received by this netif */ +#ifndef SLIP_MAX_SIZE +#define SLIP_MAX_SIZE 1500 +#endif + +/** Define this to the interface speed for SNMP + * (sio_fd is the sio_fd_t returned by sio_open). + * The default value of zero means 'unknown'. + */ +#ifndef SLIP_SIO_SPEED +#define SLIP_SIO_SPEED(sio_fd) 0 +#endif + +enum slipif_recv_state { + SLIP_RECV_NORMAL, + SLIP_RECV_ESCAPE, +}; + +struct slipif_priv { + sio_fd_t sd; + /* q is the whole pbuf chain for a packet, p is the current pbuf in the chain */ + struct pbuf *p, *q; + u8_t state; + u16_t i, recved; +#if SLIP_RX_FROM_ISR + struct pbuf *rxpackets; +#endif +}; + +/** + * Send a pbuf doing the necessary SLIP encapsulation + * + * Uses the serial layer's sio_send() + * + * @param netif the lwip network interface structure for this slipif + * @param p the pbuf chaing packet to send + * @param ipaddr the ip address to send the packet to (not used for slipif) + * @return always returns ERR_OK since the serial layer does not provide return values + */ +err_t +slipif_output(struct netif *netif, struct pbuf *p, ip_addr_t *ipaddr) +{ + struct slipif_priv *priv; + struct pbuf *q; + u16_t i; + u8_t c; + + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + LWIP_ASSERT("p != NULL", (p != NULL)); + + LWIP_UNUSED_ARG(ipaddr); + + LWIP_DEBUGF(SLIP_DEBUG, ("slipif_output(%"U16_F"): sending %"U16_F" bytes\n", (u16_t)netif->num, p->tot_len)); + priv = netif->state; + + /* Send pbuf out on the serial I/O device. */ + /* Start with packet delimiter. */ + sio_send(SLIP_END, priv->sd); + + for (q = p; q != NULL; q = q->next) { + for (i = 0; i < q->len; i++) { + c = ((u8_t *)q->payload)[i]; + switch (c) { + case SLIP_END: + /* need to escape this byte (0xC0 -> 0xDB, 0xDC) */ + sio_send(SLIP_ESC, priv->sd); + sio_send(SLIP_ESC_END, priv->sd); + break; + case SLIP_ESC: + /* need to escape this byte (0xDB -> 0xDB, 0xDD) */ + sio_send(SLIP_ESC, priv->sd); + sio_send(SLIP_ESC_ESC, priv->sd); + break; + default: + /* normal byte - no need for escaping */ + sio_send(c, priv->sd); + break; + } + } + } + /* End with packet delimiter. */ + sio_send(SLIP_END, priv->sd); + return ERR_OK; +} + +/** + * Handle the incoming SLIP stream character by character + * + * @param netif the lwip network interface structure for this slipif + * @param c received character (multiple calls to this function will + * return a complete packet, NULL is returned before - used for polling) + * @return The IP packet when SLIP_END is received + */ +static struct pbuf* +slipif_rxbyte(struct netif *netif, u8_t c) +{ + struct slipif_priv *priv; + struct pbuf *t; + + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + + priv = netif->state; + + switch (priv->state) { + case SLIP_RECV_NORMAL: + switch (c) { + case SLIP_END: + if (priv->recved > 0) { + /* Received whole packet. */ + /* Trim the pbuf to the size of the received packet. */ + pbuf_realloc(priv->q, priv->recved); + + LINK_STATS_INC(link.recv); + + LWIP_DEBUGF(SLIP_DEBUG, ("slipif: Got packet (%"U16_F" bytes)\n", priv->recved)); + t = priv->q; + priv->p = priv->q = NULL; + priv->i = priv->recved = 0; + return t; + } + return NULL; + case SLIP_ESC: + priv->state = SLIP_RECV_ESCAPE; + return NULL; + } /* end switch (c) */ + break; + case SLIP_RECV_ESCAPE: + /* un-escape END or ESC bytes, leave other bytes + (although that would be a protocol error) */ + switch (c) { + case SLIP_ESC_END: + c = SLIP_END; + break; + case SLIP_ESC_ESC: + c = SLIP_ESC; + break; + } + priv->state = SLIP_RECV_NORMAL; + break; + } /* end switch (priv->state) */ + + /* byte received, packet not yet completely received */ + if (priv->p == NULL) { + /* allocate a new pbuf */ + LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: alloc\n")); + priv->p = pbuf_alloc(PBUF_LINK, (PBUF_POOL_BUFSIZE - PBUF_LINK_HLEN), PBUF_POOL); + + if (priv->p == NULL) { + LINK_STATS_INC(link.drop); + LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: no new pbuf! (DROP)\n")); + /* don't process any further since we got no pbuf to receive to */ + return NULL; + } + + if (priv->q != NULL) { + /* 'chain' the pbuf to the existing chain */ + pbuf_cat(priv->q, priv->p); + } else { + /* p is the first pbuf in the chain */ + priv->q = priv->p; + } + } + + /* this automatically drops bytes if > SLIP_MAX_SIZE */ + if ((priv->p != NULL) && (priv->recved <= SLIP_MAX_SIZE)) { + ((u8_t *)priv->p->payload)[priv->i] = c; + priv->recved++; + priv->i++; + if (priv->i >= priv->p->len) { + /* on to the next pbuf */ + priv->i = 0; + if (priv->p->next != NULL && priv->p->next->len > 0) { + /* p is a chain, on to the next in the chain */ + priv->p = priv->p->next; + } else { + /* p is a single pbuf, set it to NULL so next time a new + * pbuf is allocated */ + priv->p = NULL; + } + } + } + return NULL; +} + +/** Like slipif_rxbyte, but passes completed packets to netif->input + * + * @param netif The lwip network interface structure for this slipif + * @param data received character + */ +static void +slipif_rxbyte_input(struct netif *netif, u8_t c) +{ + struct pbuf *p; + p = slipif_rxbyte(netif, c); + if (p != NULL) { + if (netif->input(p, netif) != ERR_OK) { + pbuf_free(p); + } + } +} + +#if SLIP_USE_RX_THREAD +/** + * The SLIP input thread. + * + * Feed the IP layer with incoming packets + * + * @param nf the lwip network interface structure for this slipif + */ +static void +slipif_loop_thread(void *nf) +{ + u8_t c; + struct netif *netif = (struct netif *)nf; + struct slipif_priv *priv = (struct slipif_priv *)netif->state; + + while (1) { + if (sio_read(priv->sd, &c, 1) > 0) { + slipif_rxbyte_input(netif, c); + } + } +} +#endif /* SLIP_USE_RX_THREAD */ + +/** + * SLIP netif initialization + * + * Call the arch specific sio_open and remember + * the opened device in the state field of the netif. + * + * @param netif the lwip network interface structure for this slipif + * @return ERR_OK if serial line could be opened, + * ERR_MEM if no memory could be allocated, + * ERR_IF is serial line couldn't be opened + * + * @note netif->num must contain the number of the serial port to open + * (0 by default). If netif->state is != NULL, it is interpreted as an + * u8_t pointer pointing to the serial port number instead of netif->num. + * + */ +err_t +slipif_init(struct netif *netif) +{ + struct slipif_priv *priv; + u8_t sio_num; + + LWIP_DEBUGF(SLIP_DEBUG, ("slipif_init: netif->num=%"U16_F"\n", (u16_t)netif->num)); + + /* Allocate private data */ + priv = (struct slipif_priv *)mem_malloc(sizeof(struct slipif_priv)); + if (!priv) { + return ERR_MEM; + } + + netif->name[0] = 's'; + netif->name[1] = 'l'; + netif->output = slipif_output; + netif->mtu = SLIP_MAX_SIZE; + netif->flags |= NETIF_FLAG_POINTTOPOINT; + + /* netif->state or netif->num contain the port number */ + if (netif->state != NULL) { + sio_num = *(u8_t*)netif->state; + } else { + sio_num = netif->num; + } + /* Try to open the serial port. */ + priv->sd = sio_open(sio_num); + if (!priv->sd) { + /* Opening the serial port failed. */ + mem_free(priv); + return ERR_IF; + } + + /* Initialize private data */ + priv->p = NULL; + priv->q = NULL; + priv->state = SLIP_RECV_NORMAL; + priv->i = 0; + priv->recved = 0; +#if SLIP_RX_FROM_ISR + priv->rxpackets = NULL; +#endif + + netif->state = priv; + + /* initialize the snmp variables and counters inside the struct netif */ + NETIF_INIT_SNMP(netif, snmp_ifType_slip, SLIP_SIO_SPEED(priv->sd)); + +#if SLIP_USE_RX_THREAD + /* Create a thread to poll the serial line. */ + sys_thread_new(SLIPIF_THREAD_NAME, slipif_loop_thread, netif, + SLIPIF_THREAD_STACKSIZE, SLIPIF_THREAD_PRIO); +#endif /* SLIP_USE_RX_THREAD */ + return ERR_OK; +} + +/** + * Polls the serial device and feeds the IP layer with incoming packets. + * + * @param netif The lwip network interface structure for this slipif + */ +void +slipif_poll(struct netif *netif) +{ + u8_t c; + struct slipif_priv *priv; + + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + + priv = (struct slipif_priv *)netif->state; + + while (sio_tryread(priv->sd, &c, 1) > 0) { + slipif_rxbyte_input(netif, c); + } +} + +#if SLIP_RX_FROM_ISR +/** + * Feeds the IP layer with incoming packets that were receive + * + * @param netif The lwip network interface structure for this slipif + */ +void +slipif_process_rxqueue(struct netif *netif) +{ + struct slipif_priv *priv; + SYS_ARCH_DECL_PROTECT(old_level); + + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + + priv = (struct slipif_priv *)netif->state; + + SYS_ARCH_PROTECT(old_level); + while (priv->rxpackets != NULL) { + struct pbuf *p = priv->rxpackets; +#if SLIP_RX_QUEUE + /* dequeue packet */ + struct pbuf *q = p; + while ((q->len != q->tot_len) && (q->next != NULL)) { + q = q->next; + } + priv->rxpackets = q->next; + q->next = NULL; +#else /* SLIP_RX_QUEUE */ + priv->rxpackets = NULL; +#endif /* SLIP_RX_QUEUE */ + SYS_ARCH_UNPROTECT(old_level); + if (netif->input(p, netif) != ERR_OK) { + pbuf_free(p); + } + SYS_ARCH_PROTECT(old_level); + } +} + +/** Like slipif_rxbyte, but queues completed packets. + * + * @param netif The lwip network interface structure for this slipif + * @param data Received serial byte + */ +static void +slipif_rxbyte_enqueue(struct netif *netif, u8_t data) +{ + struct pbuf *p; + struct slipif_priv *priv = (struct slipif_priv *)netif->state; + SYS_ARCH_DECL_PROTECT(old_level); + + p = slipif_rxbyte(netif, data); + if (p != NULL) { + SYS_ARCH_PROTECT(old_level); + if (priv->rxpackets != NULL) { +#if SLIP_RX_QUEUE + /* queue multiple pbufs */ + struct pbuf *q = p; + while(q->next != NULL) { + q = q->next; + } + q->next = p; + } else { +#else /* SLIP_RX_QUEUE */ + pbuf_free(priv->rxpackets); + } + { +#endif /* SLIP_RX_QUEUE */ + priv->rxpackets = p; + } + SYS_ARCH_UNPROTECT(old_level); + } +} + +/** + * Process a received byte, completed packets are put on a queue that is + * fed into IP through slipif_process_rxqueue(). + * + * This function can be called from ISR if SYS_LIGHTWEIGHT_PROT is enabled. + * + * @param netif The lwip network interface structure for this slipif + * @param data received character + */ +void +slipif_received_byte(struct netif *netif, u8_t data) +{ + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + slipif_rxbyte_enqueue(netif, data); +} + +/** + * Process multiple received byte, completed packets are put on a queue that is + * fed into IP through slipif_process_rxqueue(). + * + * This function can be called from ISR if SYS_LIGHTWEIGHT_PROT is enabled. + * + * @param netif The lwip network interface structure for this slipif + * @param data received character + * @param len Number of received characters + */ +void +slipif_received_bytes(struct netif *netif, u8_t *data, u8_t len) +{ + u8_t i; + u8_t *rxdata = data; + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + + for (i = 0; i < len; i++, rxdata++) { + slipif_rxbyte_enqueue(netif, *rxdata); + } +} +#endif /* SLIP_RX_FROM_ISR */ + +#endif /* LWIP_HAVE_SLIPIF */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/CHANGELOG b/component/common/network/lwip/lwip_v1.5.0.beta/CHANGELOG new file mode 100644 index 0000000..1d757d3 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/CHANGELOG @@ -0,0 +1,3733 @@ +HISTORY + +(git master) + + * [Enter new changes just after this line - do not remove this line] + + ++ New features: + + 2015-01-02: Simon Goldschmidt + * tcp.c: tcp_kill_prio(): prefer nearly-closed connections (waiting for the + last ACK only) over established connections when out of tcp pcbs + + 2015-01-17: Simon Goldschmidt + * api: allow enabling socket API without (public) netconn API - netconn API is + still used by sockets, but keeping it private (static) should allow better + compiler optimizations + + 2015-01-16: Simon Goldschmidt + * tcp_in.c: fixed bug #20506 "Initial congestion window is very small" again + by implementing the calculation formula from RFC3390 + + 2014-12-10: Simon Goldschmidt + * api: added option LWIP_NETCONN_SEM_PER_THREAD to use a semaphore per thread + instead of using one per netconn and per select call + + 2014-12-08: Simon Goldschmidt + * ip6.h: fixed bug #43778: IPv6 header version not set on 16-bit platform + (macro IP6H_VTCFL_SET()) + + 2014-12-08: Simon Goldschmidt + * icmp.c, ip4.c, pbuf.c, udp.c, pbuf.h: task #11472 Support PBUF_REF for RX + (IPv6 and IPv4/v6 reassembly might not work yet) + + 2014-11-06: Simon Goldschmidt + * sockets.c/.h, init.c: lwip_socket_init() is not needed any more + -> compatibility define + + 2014-09-16: Simon Goldschmidt + * dns.c, opt.h: reduced ram usage by parsing DNS responses in place + + 2014-09-16: Simon Goldschmidt + * pbuf.h/.c: added pbuf_take_at() and pbuf_put_at() + + 2014-09-15: Simon Goldschmidt + * dns.c: added source port randomization to make the DNS client more robust + (see bug #43144) + + 2013-09-02: Simon Goldschmidt + * arch.h and many other files: added optional macros PACK_STRUCT_FLD_8() and + PACK_STRUCT_FLD_S() to prevent gcc 4 from warning about struct members that + do not need packing + + 2013-08-19: Simon Goldschmidt + * netif.h: bug #42998: made NETIF_MAX_HWADDR_LEN overridable for some special + networks + + 2013-03-17: Simon Goldschmidt (patch by Ghobad Emadi) + * opt.h, etharp.c: Added LWIP_HOOK_ETHARP_GET_GW to implement IPv4 routing with + multiple gateways + + 2013-04-20: Fatih Asici + * opt.h, etharp.h/.c: patch #7993: Added support for transmitting packets + with VLAN headers via hook function LWIP_HOOK_VLAN_SET and to check them + via hook function LWIP_HOOK_VLAN_CHECK + + 2014-02-20: Simon Goldschmidt (based on patch by Artem Pisarenko) + * patch #7885: modification of api modules to support FreeRTOS-MPU + (don't pass stack-pointers to other threads) + + 2014-02-05: Simon Goldschmidt (patch by "xtian" and "alex_ab") + * patch #6537/#7858: TCP window scaling support + + 2014-01-17: Jiri Engelthaler + * icmp, icmp6, opt.h: patch #8027: Completed HW checksuming for IPv4 and + IPv6 ICMP's + + 2012-08-22: Sylvain Rochet + * New PPP stack for lwIP, developed in ppp-new branch. + Based from pppd 2.4.5, released 2009-11-17, with huge changes to match + code size and memory requirements for embedded devices, including: + - Gluing together the previous low-level PPP code in lwIP to pppd 2.4.5, which + is more or less what pppd sys-* files are, so that we get something working + using the unix port. + - Merged some patchs from lwIP Git repository which add interesting features + or fix bugs. + - Merged some patchs from Debian pppd package which add interesting features + or fix bugs. + - Ported PPP timeout handling to the lwIP timers system + - Disabled all the PPP code using filesystem access, replaced in necessary cases + to configuration variables. + - Disabled all the PPP code forking processes. + - Removed IPX support, lwIP does not support IPX. + - Ported and improved random module from the previous PPP port. + - Removed samba TDB (file-driven database) usage, because it needs a filesystem. + - MS-CHAP required a DES implementation, we added the latest PolarSSL DES + implementation which is under a BSD-ish license. + - Also switched to PolarSSL MD4,MD5,SHA1 implementations, which are meant to be + used in embedded devices with reduced memory footprint. + - Removed PPP configuration file parsing support. + - Added macro definition EAP_SUPPORT to make EAP support optional. + - Added macro definition CHAP_SUPPORT to make CHAP support optional. + - Added macro definition MSCHAP_SUPPORT to make MSCHAP support optional. + - Added macro definition PAP_SUPPORT to make PAP support optional. + - Cleared all Linux syscall calls. + - Disabled demand support using a macro, so that it can be ported later. + - Disabled ECP support using a macro, so that it can be ported later. + - Disabled CCP support using a macro, so that it can be ported later. + - Disabled CBCP support using a macro, so that it can be ported later. + - Disabled LQR support using a macro, so that it can be ported later. + - Print packet debug feature optional, through PRINTPKT_SUPPORT + - Removed POSIX signal usage. + - Fully ported PPPoS code from the previous port. + - Fully ported PPPoE code from the previous port. + - Fully ported VJ compression protocol code from the previous port. + - Removed all malloc()/free() use from PPP, replaced by stack usage or PBUF. + - Disabled PPP server support using a macro, so that it can be ported later. + - Switched all PPP debug to lwIP debug system. + - Created PPP Control Block (PPP PCB), removed PPP unit integer everywhere, + removed all global variables everywhere, did everything necessary for + the PPP stack to support more than one PPP session (pppd only support + one session per process). + - Removed the statically allocated output buffer, now using PBUF. + - Improved structure size of all PPP modules, deep analyze of code to reduce + variables size to the bare minimum. Switched all boolean type (char type in + most architecture) to compiler generated bitfields. + - Added PPP IPv6 support, glued lwIP IPv6 support to PPP. + - Now using a persistent netif interface which can then be used in lwIP + functions requiring a netif. + - Now initializing PPP in lwip_init() function. + - Reworked completely the PPP state machine, so that we don't end up in + anymore in inconsistent state, especially with PPPoE. + - Improved the way we handle PPP reconnection after disconnect, cleaning + everything required so that we start the PPP connection again from a + clean state. + - Added PPP holdoff support, allow the lwIP user to wait a little bit before + reconnecting, prevents connection flood, especially when using PPPoL2TP. + - Added PPPoL2TP LAC support (a.k.a. UDP tunnels), adding a VPN client + feature to lwIP, L2TP being a widely used tunnel protocol. + - Switched all used PPP types to lwIP types (u8t, u16t, u32t, ...) + - Added PPP API "sequential" thread-safe API, based from NETIFAPI. + + 2011-07-21: Simon Goldschmidt + * sockets.c, opt.h: (bug #30185): added LWIP_FIONREAD_LINUXMODE that makes + ioctl/FIONREAD return the size of the next pending datagram. + + 2011-05-25: Simon Goldschmidt + * again nearly the whole stack, renamed ip.c to ip4.c, ip_addr.c to ip4_addr.c, + combined ipv4/ipv6 inet_chksum.c, added ip.h, ip_addr.h: Combined IPv4 + and IPv6 code where possible, added defines to access IPv4/IPv6 in non-IP + code so that the code is more readable. + + 2011-05-17: Patch by Ivan Delamer (only checked in by Simon Goldschmidt) + * nearly the whole stack: Finally, we got decent IPv6 support, big thanks to + Ivan! (this is work in progress: we're just post release anyway :-) + + + ++ Bugfixes: + + 2014-01-27: Simon Goldschmidt + * api_msg.c: fixed that SHUT_RD followed by SHUT_WR was different to SHUT_RDWR, + fixed return value of lwip_netconn_do_close on unconnected netconns + + 2015-01-17: Simon Goldschmidt + * sockets.c: fixed bug #43361 select() crashes with stale FDs + + 2015-01-17: Simon Goldschmidt + * sockets.c/.h, memp_std.h: fixed bug #40788 "lwip_setsockopt_internal() crashes" + by rewriting set/getsockopt functions to combine checks with the actual code + and add more NULL checks; this also fixes that CORE_LOCKING used message + passing for set/getsockopt. + + 2014-12-19: Simon Goldschmidt + * opt.h, dhcp.h/.c: prevent dhcp from starting when netif link is down (only + when LWIP_DHCP_CHECK_LINK_UP==1, which is disabled by default for + compatibility reasons) + + 2014-12-17: Simon Goldschmidt + * tcp_out.c: fixed bug #43840 Checksum error for TCP_CHECKSUM_ON_COPY==1 for + no-copy data with odd length + + 2014-12-10: Simon Goldschmidt + * sockets.c, tcp.c, others: fixed bug #43797 set/getsockopt: SO_SNDTIMEO/SO_RCVTIMEO + take int as option but should take timeval (LWIP_SO_SNDRCVTIMEO_STANDARD==0 can + be used to revert to the old 'winsock' style behaviour) + Fixed implementation of SO_ACCEPTCONN to just look at the pcb state + + 2014-12-09: Simon Goldschmidt + * ip4.c: fixed bug #43596 IGMP queries from 0.0.0.0 are discarded + + 2014-10-21: Simon Goldschmidt (patch by Joel Cunningham and Albert Huitsing) + * sockts.c: fixed bugs #41495 Possible threading issue in select() and #43278 + event_callback() handle context switch when calling sys_sem_signal() + + 2014-10-21: Simon Goldschmidt + * api_msg.c: fixed bug #38219 Assert on TCP netconn_write with sndtimeout set + + 2014-09-16: Kevin Cernekee + * dns.c: patch #8480 Fix handling of dns_seqno wraparound + + 2014-09-16: Simon Goldschmidt + * tcp_out.c: fixed bug #43192 tcp_enqueue_flags() should not check TCP_SND_QUEUELEN + when sending FIN + + 2014-09-03: Simon Goldschmidt + * msg_in.c: fixed bug #39355 SNMP Memory Leak in case of error + + 2014-09-02: Simon Goldschmidt + * err.h/.c, sockets.c, api_msg.c: fixed bug #43110 call getpeername() before + listen() will cause a error + + 2014-09-02: Simon Goldschmidt + * sockets.c: fixed bug #42117 lwip_fcntl does not set errno + + 2014-09-02: Simon Goldschmidt + * tcp.c: fixed bug #42299 tcp_abort() leaves freed pcb on tcp_bound_pcbs list + + 2014-08-20: Simon Goldschmidt + * dns.c: fixed bug #42987 lwIP is vulnerable to DNS cache poisoning due to + non-randomized TXIDs + + 2014-06-03: Simon Goldschmidt + * tcp_impl.h, tcp_in.c: fixed bug #37969 SYN packet dropped as short packet in + tcp_input function + + 2014-05-20: Simon Goldschmidt + * tcp_out.c: fixed bug #37184 tcp_write problem for pcbs in the SYN_SENT state + + 2014-05-19: Simon Goldschmidt + * *.h: Fixed bug #35874 reserved identifier violation (removed leading underscores + from header include guards) + + 2014-04-08: Simon Goldschmidt + * tcp.c: Fixed bug #36167 tcp server crash when client closes (maximum window) + + 2014-04-06: Simon Goldschmidt + * tcp_in.c: Fixed bug #36210 lwIP does not elicit an empty ACK when received + unacceptable ACK + + 2014-04-06: Simon Goldschmidt + * dhcp.c, ip4.c/.h, ip6.c/.h, udp.c/.h, ip.h: Fixed bug #41787 DHCP Discovery + is invalid when an IP is set to thet netif. + + 2014-03-14: Simon Goldschmidt + * tcp_out.c: Fixed bug #36153 TCP Cheksum error if LWIP_CHECKSUM_ON_COPY=1 + + 2014-03-11: Simon Goldschmidt (patch by Mason) + * opt.h, sockets.c: fixed bug #35928 BSD sockets functions must set errno for + POSIX-compliance + + 2014-02-27: Simon Goldschmidt + * dhcp.c: fixed bug #40303 DHCP xid renewed when sending a DHCPREQUEST + + 2014-02-27: Simon Goldschmidt + * raw.c: fixed bug #41680 raw socket can not receive IPv6 packet when + IP_SOF_BROADCAST_RECV==1 + + 2014-02-27: Simon Goldschmidt + * api_msg.c, sockets.c: fixed bug #38404 getpeeraddr returns success on + unconnected/listening TCP sockets + + 2014-02-27: Simon Goldschmidt + * sockets.c: fixed bug #41729 Some socket functions return Exyz instead of -1 + + 2014-02-25: Simon Goldschmidt + * ip4.c: fixed bug #39514 ip_route() may return an IPv6-only interface + + 2014-02-25: Simon Goldschmidt, patch by Fatih Asici + * pbuf.c: fixed bug #39356 Wrong increment in pbuf_memfind() + + 2014-02-25: Simon Goldschmidt + * netif.c/.h, udp.c: fixed bug #39225 udp.c uses netif_matches_ip6_addr() incorrectly; + renamed function netif_matches_ip6_addr() to netif_get_ip6_addr_match() + + 2014-02-25: Simon Goldschmidt + * igmp.c: fixed bug #39145 IGMP membership report for 224.0.0.1 + + 2014-02-22: Simon Goldschmidt (patch by Amir Shalem) + * etharp.c, opt.h: fixed bug #34681 Limit ARP queue length by ARP_QUEUE_LEN (=3) + + 2014-02-22: Simon Goldschmidt (patch by Amir Shalem) + * etharp.h/.c: fixed bug #34682 Limit ARP request flood for unresolved entry + + 2014-02-20: Simon Goldschmidt + * tcp_out.c: fixed bug #39683 Assertion "seg->tcphdr not aligned" failed with + MEM_ALIGNMENT = 8 + + 2014-02-20: Simon Goldschmidt + * sockets.c: fixed bug #39882 No function shall set errno to 0 + + 2014-02-20: Simon Goldschmidt + * mib_structs.c: fixed bug #40050 SNMP problem with MIB arrays > 255 + + 2014-02-20: Simon Goldschmidt + * api.h, sockets.c: fixed bug #41499 netconn::recv_avail can overflow + + 2014-01-08: Stathis Voukelatos + * memp_std.h: patch #7928 Fixed size calculation in MALLOC memory pool + creation macro + + 2014-01-18: Brian Fahs + * tcp_out.c: patch #8237: tcp_rexmit_rto fails to update pcb->unsent_oversize + when necessary + + 2014-01-17: Grant Erickson, Jay Logue, Simon Goldschmidt + * ipv6.c, netif.c: patch #7913 Enable Support for IPv6 Loopback + + 2014-01-16: Stathis Voukelatos + * netif.c: patch #7902 Fixed netif_poll() operation when LWIP_LOOPBACK_MAX_PBUFS > 0 + + 2014-01-14: "Freddie Chopin" + * snmp.h, mib2.c: fixed constness and spelling of sysdescr + + 2014-01-14: Simon Goldschmidt (patch by Thomas Faber) + * tcpip.c: patch #8241: Fix implicit declaration of ip_input with + LWIP_TCPIP_CORE_LOCKING_INPUT disabled + + 2014-01-14: chrysn + * timers.c: patch #8244 make timeouts usable reliably from outside of the + timeout routine + + 2014-01-10: Simon Goldschmidt + * ip_frag.c, ip6_frag.c: fixed bug #41041 Potential use-after-free in IPv6 reassembly + + 2014-01-10: Simon Goldschmidt + * memp.c: fixed bug #41188 Alignment error in memp_init() when MEMP_SEPARATE_POOLS==1 + + 2014-01-10: Simon Goldschmidt + * tcp.c: fixed bug #39898 tcp_fasttmr() possible lock due to infinte queue process loop + + 2013-06-29: Simon Goldschmidt + * inet.h, sockets.h: partially fixed bug #37585: IPv6 compatibility (in socket structs) + + 2013-06-29: Simon Goldschmidt + * inet6.h: bug #37585/task #12600: fixed struct in6_addr.s6_addr to conform to spec + + 2013-04-24: patch by Liam + * api_msg.c: patch #8008 Fix a potential null pointer dereference in assert + + 2013-04-24: Simon Goldschmidt + * igmp.c: fixed possible division by zero + + 2013-04-24: Simon Goldschmidt + * ip6.h, some ipv6 C files: fixed bug #38526 Coverity: Recursive Header Inclusion in ip6.h + + 2013-04-24: Simon Goldschmidt (patch by Emil Ljungdahl): + * netif.c: fixed bug #38586 netif_loop_output() "deadlocks" + + 2013-01-15: Simon Goldschmidt + * ip4.c: fixed bug #37665 ip_canforward operates on address in wrong byte order + + 2013-01-15: Simon Goldschmidt + * pbuf.h: fixed bug #38097 pbuf_free_ooseq() warning + + 2013-01-14: Simon Goldschmidt + * dns.c: fixed bug #37705 Possible memory corruption in DNS query + + 2013-01-11: Simon Goldschmidt + * raw.c: fixed bug #38066 Raw pcbs can alter packet without eating it + + 2012-08-22: Simon Goldschmidt + * memp.c: fixed bug #37166: memp_sanity check loops itself + + 2012-08-13: Simon Goldschmidt + * dhcp.c: fixed bug #36645: Calling dhcp_release before dhcp_start + dereferences NULL + + 2012-08-13: Simon Goldschmidt + * msg_out.c: fixed bug #36840 snmp_send_trap() NULL de-reference if traps + configured but no interfaces available + + 2012-08-13: Simon Goldschmidt + * dns.c: fixed bug #36899 DNS TTL 0 is cached for a long time + + 2012-05-11: Simon Goldschmidt (patch by Marty) + * memp.c: fixed bug #36412: memp.c does not compile when + MEMP_OVERFLOW_CHECK > zero and MEMP_SEPARATE_POOLS == 1 + + 2012-05-03: Simon Goldschmidt (patch by Sylvain Rochet) + * ppp.c: fixed bug #36283 (PPP struct used on header size computation and + not packed) + + 2012-05-03: Simon Goldschmidt (patch by David Empson) + * ppp.c: fixed bug #36388 (PPP: checksum-only in last pbuf leads to pbuf with + zero length) + + 2012-03-25: Simon Goldschmidt + * api_msg.c: Fixed bug #35817: do_connect() invalidly signals op_completed + for UDP/RAW with LWIP_TCPIP_CORE_LOCKING==1 + + 2012-03-25: Simon Goldschmidt + * api_msg.h, api_lib.c, api_msg.c, netifapi.c: fixed bug #35931: Name space + pollution in api_msg.c and netifapi.c + + 2011-08-24: Simon Goldschmidt + * inet6.h: fixed bug #34124 struct in6_addr does not conform to the standard + + + +(STABLE-1.4.1) + + ++ New features: + + 2012-03-25: Simon Goldschmidt (idea by Mason) + * posix/*: added posix-compatibility include files posix/netdb.h and posix/sys/socket.h + which are a simple wrapper to the correct lwIP include files. + + 2012-01-16: Simon Goldschmidt + * opt.h, icmp.c: Added option CHECKSUM_GEN_ICMP + + 2011-12-17: Simon Goldschmidt + * ip.h: implemented API functions to access so_options of IP pcbs (UDP, TCP, RAW) + (fixes bug #35061) + + 2011-09-27: Simon Goldschmidt + * opt.h, tcp.c, tcp_in.c: Implemented limiting data on ooseq queue (task #9989) + (define TCP_OOSEQ_MAX_BYTES / TCP_OOSEQ_MAX_PBUFS in lwipopts.h) + + 2011-09-21: Simon Goldschmidt + * opt.h, api.h, api_lib.c, api_msg.h/.c, sockets.c: Implemented timeout on + send (TCP only, bug #33820) + + 2011-09-21: Simon Goldschmidt + * init.c: Converted runtime-sanity-checks into compile-time checks that can + be disabled (since runtime checks can often not be seen on embedded targets) + + 2011-09-11: Simon Goldschmidt + * ppp.h, ppp_impl.h: splitted ppp.h to an internal and external header file + to get a clear separation of which functions an application or port may use + (task #11281) + + 2011-09-11: Simon Goldschmidt + * opt.h, tcp_impl.h, tcp.c, udp.h/.c: Added a config option to randomize + initial local TCP/UDP ports (so that different port ranges are used after + a reboot; bug #33818; this one added tcp_init/udp_init functions again) + + 2011-09-03: Simon Goldschmidt + * dhcp.c: DHCP uses LWIP_RAND() for xid's (bug #30302) + + 2011-08-24: Simon Goldschmidt + * opt.h, netif.h/.c: added netif remove callback (bug #32397) + + 2011-07-26: Simon Goldschmidt + * etharp.c: ETHARP_SUPPORT_VLAN: add support for an external VLAN filter + function instead of only checking for one VLAN (define ETHARP_VLAN_CHECK_FN) + + 2011-07-21: Simon Goldschmidt (patch by hanhui) + * ip4.c, etharp.c, pbuf.h: bug #33634 ip_forward() have a faulty behaviour: + Added pbuf flags to mark incoming packets as link-layer broadcast/multicast. + Also added code to allow ip_forward() to forward non-broadcast packets to + the input netif (set IP_FORWARD_ALLOW_TX_ON_RX_NETIF==1). + + 2011-06-26: Simon Goldschmidt (patch by Cameron Gutman) + * tcp.c, tcp_out.c: bug #33604: added some more asserts to check that + pcb->state != LISTEN + + 2011-05-14: Simon Goldschmidt (patch by Stéphane Lesage) + * tcpip.c/.h: patch #7449 allow tcpip callback from interrupt with static + memory message + + + ++ Bugfixes: + + 2012-09-26: Simon Goldschmidt + * api_msg.c: fixed bug #37405 'err_tcp()' uses already freed 'netconn' object + + 2012-09-26: patch by Henrik Persson + * dhcp.c: patch #7843 Fix corner case with dhcp timeouts + + 2012-09-26: patch by Henrik Persson + * dhcp.c: patch #7840 Segfault in dhcp_parse_reply if no end marker in dhcp packet + + 2012-08-22: Simon Goldschmidt + * memp.c: fixed bug #37166: memp_sanity check loops itself + + 2012-05-08: Simon Goldschmidt + * tcp_out.c: fixed bug: #36380 unsent_oversize mismatch in 1.4.1RC1 (this was + a debug-check issue only) + + 2012-03-27: Simon Goldschmidt + * vj.c: fixed bug #35756 header length calculation problem in ppp/vj.c + + 2012-03-27: Simon Goldschmidt (patch by Mason) + * tcp_out.c: fixed bug #35945: SYN packet should provide the recv MSS not the + send MSS + + 2012-03-22: Simon Goldschmidt + * ip4.c: fixed bug #35927: missing refragmentaion in ip_forward + + 2012-03-20: Simon Goldschmidt (patch by Mason) + * netdb.c: fixed bug #35907: lwip_gethostbyname_r returns an invalid h_addr_list + + 2012-03-12: Simon Goldschmidt (patch by Bostjan Meglic) + * ppp.c: fixed bug #35809: PPP GetMask(): Compiler warning on big endian, + possible bug on little endian system + + 2012-02-23: Simon Goldschmidt + * etharp.c: fixed bug #35595: Impossible to send broadcast without a gateway + (introduced when fixing bug# 33551) + + 2012-02-16: Simon Goldschmidt + * ppp.c: fixed pbuf leak when PPP session is aborted through pppSigHUP() + (bug #35541: PPP Memory Leak) + + 2012-02-16: Simon Goldschmidt + * etharp.c: fixed bug #35531: Impossible to send multicast without a gateway + (introduced when fixing bug# 33551) + + 2012-02-16: Simon Goldschmidt (patch by Stéphane Lesage) + * msg_in.c, msg_out.c: fixed bug #35536 SNMP: error too big response is malformed + + 2012-02-15: Simon Goldschmidt + * init.c: fixed bug #35537: MEMP_NUM_* sanity checks should be disabled with + MEMP_MEM_MALLOC==1 + + 2012-02-12: Simon Goldschmidt + * tcp.h, tcp_in.c, tcp_out.c: partly fixed bug #25882: TCP hangs on + MSS > pcb->snd_wnd (by not creating segments bigger than half the window) + + 2012-02-11: Simon Goldschmidt + * tcp.c: fixed bug #35435: No pcb state check before adding it to time-wait + queue while closing + + 2012-01-22: Simon Goldschmidt + * tcp.c, tcp_in.c: fixed bug #35305: pcb may be freed too early on shutdown(WR) + + 2012-01-21: Simon Goldschmidt + * tcp.c: fixed bug #34636: FIN_WAIT_2 - Incorrect shutdown of TCP pcb + + 2012-01-20: Simon Goldschmidt + * dhcp.c: fixed bug #35151: DHCP asserts on incoming option lengths + + 2012-01-20: Simon Goldschmidt + * pbuf.c: fixed bug #35291: NULL pointer in pbuf_copy + + 2011-11-25: Simon Goldschmidt + * tcp.h/.c, tcp_impl.h, tcp_in.c: fixed bug #31177: tcp timers can corrupt + tcp_active_pcbs in some cases + + 2011-11-23: Simon Goldschmidt + * sys.c: fixed bug #34884: sys_msleep() body needs to be surrounded with + '#ifndef sys_msleep' + + 2011-11-22: Simon Goldschmidt + * netif.c, etharp.h/.c: fixed bug #34684: Clear the arp table cache when + netif is brought down + + 2011-10-28: Simon Goldschmidt + * tcp_in.c: fixed bug #34638: Dead code in tcp_receive - pcb->dupacks + + 2011-10-23: Simon Goldschmidt + * mem.c: fixed bug #34429: possible memory corruption with + LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT set to 1 + + 2011-10-18: Simon Goldschmidt + * arch.h, netdb.c: fixed bug #34592: lwip_gethostbyname_r uses nonstandard + error value + + 2011-10-18: Simon Goldschmidt + * opt.h: fixed default values of TCP_SNDLOWAT and TCP_SNDQUEUELOWAT for small + windows (bug #34176 select after non-blocking send times out) + + 2011-10-18: Simon Goldschmidt + * tcp_impl.h, tcp_out.c: fixed bug #34587: TCP_BUILD_MSS_OPTION doesn't + consider netif->mtu, causes slow network + + 2011-10-18: Simon Goldschmidt + * sockets.c: fixed bug #34581 missing parentheses in udplite sockets code + + 2011-10-18: Simon Goldschmidt + * sockets.h: fixed bug #34580 fcntl() is missing in LWIP_COMPAT_SOCKETS + + 2011-10-17: Simon Goldschmidt + * api_msg.c: fixed bug #34569: shutdown(SHUT_WR) crashes netconn/socket api + + 2011-10-13: Simon Goldschmidt + * tcp_in.c, tcp_out.c: fixed bug #34517 (persist timer is started although no + zero window is received) by starting the persist timer when a zero window is + received, not when we have more data queued for sending than fits into the + window + + 2011-10-13: Simon Goldschmidt + * def.h, timers.c: fixed bug #34541: LWIP_U32_DIFF is unnecessarily complex + + 2011-10-13: Simon Goldschmidt + * sockets.c, api_lib.c: fixed bug #34540: compiler error when CORE_LOCKING is + used and not all protocols are enabled + + 2011-10-12: Simon Goldschmidt + * pbuf.c: fixed bug #34534: Error in sending fragmented IP if MEM_ALIGNMENT > 4 + + 2011-10-09: Simon Goldschmidt + * tcp_out.c: fixed bug #34426: tcp_zero_window_probe() transmits incorrect + byte value when pcb->unacked != NULL + + 2011-10-09: Simon Goldschmidt + * ip4.c: fixed bug #34447 LWIP_IP_ACCEPT_UDP_PORT(dst_port) wrong + + 2011-09-27: Simon Goldschmidt + * tcp_in.c, tcp_out.c: Reset pcb->unsent_oversize in 2 more places... + + 2011-09-27: Simon Goldschmidt + * tcp_in.c: fixed bug #28288: Data after FIN in oos queue + + 2011-09-27: Simon Goldschmidt + * dhcp.c: fixed bug #34406 dhcp_option_hostname() can overflow the pbuf + + 2011-09-24: Simon Goldschmidt + * mem.h: fixed bug #34377 MEM_SIZE_F is not defined if MEM_LIBC_MALLOC==1 + + 2011-09-23: Simon Goldschmidt + * pbuf.h, tcp.c, tcp_in.c: fixed bug #33871: rejecting TCP_EVENT_RECV() for + the last packet including FIN can lose data + + 2011-09-22: Simon Goldschmidt + * tcp_impl.h: fixed bug #34355: nagle does not take snd_buf/snd_queuelen into + account + + 2011-09-21: Simon Goldschmidt + * opt.h: fixed default value of TCP_SND_BUF to not violate the sanity checks + in init.c + + 2011-09-20: Simon Goldschmidt + * timers.c: fixed bug #34337 (possible NULL pointer in sys_check_timeouts) + + 2011-09-11: Simon Goldschmidt + * tcp_out.c: use pcb->mss instead of TCP_MSS for preallocate mss-sized pbufs + (bug #34019) + + 2011-09-09: Simon Goldschmidt + * udp.c: fixed bug #34072: UDP broadcast is received from wrong UDP pcb if + udp port matches + + 2011-09-03: Simon Goldschmidt + * tcp_in.c: fixed bug #33952 PUSH flag in incoming packet is lost when packet + is aggregated and sent to application + + 2011-09-01: Simon Goldschmidt + * opt.h: fixed bug #31809 LWIP_EVENT_API in opts.h is inconsistent compared + to other options + + 2011-09-01: Simon Goldschmidt + * tcp_in.c: fixed bug #34111 RST for ACK to listening pcb has wrong seqno + + 2011-08-24: Simon Goldschmidt + * api_msg.c, sockets.c: fixed bug #33956 Wrong error returned when calling + accept() on UDP connections + + 2011-08-24: Simon Goldschmidt + * sockets.h: fixed bug #34057 socklen_t should be a typedef + + 2011-08-24: Simon Goldschmidt + * pbuf.c: fixed bug #34112 Odd check in pbuf_alloced_custom (typo) + + 2011-08-24: Simon Goldschmidt + * dhcp.c: fixed bug #34122 dhcp: hostname can overflow + + 2011-08-24: Simon Goldschmidt + * netif.c: fixed bug #34121 netif_add/netif_set_ipaddr fail on NULL ipaddr + + 2011-08-22: Simon Goldschmidt + * tcp_out.c: fixed bug #33962 TF_FIN not always set after FIN is sent. (This + merely prevents nagle from not transmitting fast after closing.) + + 2011-07-22: Simon Goldschmidt + * api_lib.c, api_msg.c, sockets.c, api.h: fixed bug #31084 (socket API returns + always EMSGSIZE on non-blocking sockets if data size > send buffers) -> now + lwip_send() sends as much as possible for non-blocking sockets + + 2011-07-22: Simon Goldschmidt + * pbuf.c/.h, timers.c: freeing ooseq pbufs when the pbuf pool is empty implemented + for NO_SYS==1: when not using sys_check_timeouts(), call PBUF_CHECK_FREE_OOSEQ() + at regular intervals from main level. + + 2011-07-21: Simon Goldschmidt + * etharp.c: fixed bug #33551 (ARP entries may time out although in use) by + sending an ARP request when an ARP entry is used in the last minute before + it would time out. + + 2011-07-04: Simon Goldschmidt + * sys_arch.txt: Fixed documentation after changing sys arch prototypes for 1.4.0. + + 2011-06-26: Simon Goldschmidt + * tcp.c: fixed bug #31723 (tcp_kill_prio() kills pcbs with the same prio) by + updating its documentation only. + + 2011-06-26: Simon Goldschmidt + * mem.c: fixed bug #33545: With MEM_USE_POOLS==1, mem_malloc can return an + unaligned pointer. + + 2011-06-26: Simon Goldschmidt + * mem.c: fixed bug #33544 "warning in mem.c in lwip 1.4.0 with NO_SYS=1" + + 2011-05-25: Simon Goldschmidt + * tcp.c: fixed bug #33398 (pointless conversion when checking TCP port range) + + + +(STABLE-1.4.0) + + ++ New features: + + 2011-03-27: Simon Goldschmidt + * tcp_impl.h, tcp_in.c, tcp_out.c: Removed 'dataptr' from 'struct tcp_seg' and + calculate it in tcp_zero_window_probe (the only place where it was used). + + 2010-11-21: Simon Goldschmidt + * dhcp.c/.h: Added a function to deallocate the struct dhcp from a netif + (fixes bug #31525). + + 2010-07-12: Simon Goldschmidt (patch by Stephane Lesage) + * ip.c, udp.c/.h, pbuf.h, sockets.c: task #10495: Added support for + IP_MULTICAST_LOOP at socket- and raw-API level. + + 2010-06-16: Simon Goldschmidt + * ip.c: Added an optional define (LWIP_IP_ACCEPT_UDP_PORT) that can allow + link-layer-addressed UDP traffic to be received while a netif is down (just + like DHCP during configuration) + + 2010-05-22: Simon Goldschmidt + * many many files: bug #27352: removed packing from ip_addr_t, the packed + version is now only used in protocol headers. Added global storage for + current src/dest IP address while in input functions. + + 2010-05-16: Simon Goldschmidt + * def.h: task #10391: Add preprocessor-macros for compile-time htonl + calculation (and use them throughout the stack where applicable) + + 2010-05-16: Simon Goldschmidt + * opt.h, memp_std.h, memp.c, ppp_oe.h/.c: PPPoE now uses its own MEMP pool + instead of the heap (moved struct pppoe_softc from ppp_oe.c to ppp_oe.h) + + 2010-05-16: Simon Goldschmidt + * opt.h, memp_std.h, dns.h/.c: DNS_LOCAL_HOSTLIST_IS_DYNAMIC uses its own + MEMP pool instead of the heap + + 2010-05-13: Simon Goldschmidt + * tcp.c, udp.c: task #6995: Implement SO_REUSEADDR (correctly), added + new option SO_REUSE_RXTOALL to pass received UDP broadcast/multicast + packets to more than one pcb. + + 2010-05-02: Simon Goldschmidt + * netbuf.h/.c, sockets.c, api_msg.c: use checksum-on-copy for sending + UDP data for LWIP_NETIF_TX_SINGLE_PBUF==1 + + 2010-04-30: Simon Goldschmidt + * udp.h/.c, pbuf.h/.c: task #6849: added udp_send(_to/_if) functions that + take a precalculated checksum, added pbuf_fill_chksum() to copy data + into a pbuf and at the same time calculating the checksum for that data + + 2010-04-29: Simon Goldschmidt + * ip_addr.h, etharp.h/.c, autoip.c: Create overridable macros for copying + 2-byte-aligned IP addresses and MAC addresses + + 2010-04-28: Patch by Bill Auerbach + * ip.c: Inline generating IP checksum to save a function call + + 2010-04-14: Simon Goldschmidt + * tcpip.h/.c, timers.c: Added an overridable define to get informed when the + tcpip_thread processes messages or timeouts to implement a watchdog. + + 2010-03-28: Simon Goldschmidt + * ip_frag.c: create a new (contiguous) PBUF_RAM for every outgoing + fragment if LWIP_NETIF_TX_SINGLE_PBUF==1 + + 2010-03-27: Simon Goldschmidt + * etharp.c: Speedup TX by moving code from find_entry to etharp_output/ + etharp_query to prevent unnecessary function calls (inspired by + patch #7135). + + 2010-03-20: Simon Goldschmidt + * opt.h, tcpip.c/.h: Added an option to disable tcpip_(un)timeout code + since the linker cannot do this automatically to save space. + + 2010-03-20: Simon Goldschmidt + * opt.h, etharp.c/.h: Added support for static ARP table entries + + 2010-03-14: Simon Goldschmidt + * tcp_impl.h, tcp_out.c, inet_chksum.h/.c: task #6849: Calculate checksum + when creating TCP segments, not when (re-)transmitting them. + + 2010-03-07: Simon Goldschmidt + * sockets.c: bug #28775 (select/event_callback: only check select_cb_list + on change) plus use SYS_LIGHTWEIGHT_PROT to protect the select code. + This should speed up receiving data on sockets as the select code in + event_callback is only executed when select is waiting. + + 2010-03-06: Simon Goldschmidt + * tcp_out.c: task #7013 (Create option to have all packets delivered to + netif->output in one piece): Always copy to try to create single pbufs + in tcp_write. + + 2010-03-06: Simon Goldschmidt + * api.h, api_lib.c, sockets.c: task #10167 (sockets: speed up TCP recv + by not allocating a netbuf): added function netconn_recv_tcp_pbuf() + for tcp netconns to receive pbufs, not netbufs; use that function + for tcp sockets. + + 2010-03-05: Jakob Ole Stoklundsen / Simon Goldschmidt + * opt.h, tcp.h, tcp_impl.h, tcp.c, tcp_in.c, tcp_out.c: task #7040: + Work on tcp_enqueue: Don't waste memory when chaining segments, + added option TCP_OVERSIZE to prevent creating many small pbufs when + calling tcp_write with many small blocks of data. Instead, pbufs are + allocated larger than needed and the space is used for later calls to + tcp_write. + + 2010-02-21: Simon Goldschmidt + * stats.c/.h: Added const char* name to mem- and memp-stats for easier + debugging. + + 2010-02-21: Simon Goldschmidt + * tcp.h (and usages), added tcp_impl.h: Splitted API and internal + implementation of tcp to make API usage cleare to application programmers + + 2010-02-14: Simon Goldschmidt/Stephane Lesage + * ip_addr.h: Improved some defines working on ip addresses, added faster + macro to copy addresses that cannot be NULL + + 2010-02-13: Simon Goldschmidt + * api.h, api_lib.c, api_msg.c, sockets.c: task #7865 (implement non- + blocking send operation) + + 2010-02-12: Simon Goldschmidt + * sockets.c/.h: Added a minimal version of posix fctl() to have a + standardised way to set O_NONBLOCK for nonblocking sockets. + + 2010-02-12: Simon Goldschmidt + * dhcp.c/.h, autoip.c/.h: task #10139 (Prefer statically allocated + memory): added autoip_set_struct() and dhcp_set_struct() to let autoip + and dhcp work with user-allocated structs instead of callin mem_malloc + + 2010-02-12: Simon Goldschmidt/Jeff Barber + * tcp.c/h: patch #6865 (SO_REUSEADDR for TCP): if pcb.so_options has + SOF_REUSEADDR set, allow binding to endpoint in TIME_WAIT + + 2010-02-12: Simon Goldschmidt + * sys layer: task #10139 (Prefer statically allocated memory): converted + mbox and semaphore functions to take pointers to sys_mbox_t/sys_sem_t; + converted sys_mbox_new/sys_sem_new to take pointers and return err_t; + task #7212: Add Mutex concept in sys_arch (define LWIP_COMPAT_MUTEX + to let sys.h use binary semaphores instead of mutexes - as before) + + 2010-02-09: Simon Goldschmidt (Simon Kallweit) + * timers.c/.h: Added function sys_restart_timeouts() from patch #7085 + (Restart system timeout handling) + + 2010-02-09: Simon Goldschmidt + * netif.c/.h, removed loopif.c/.h: task #10153 (Integrate loopif into + netif.c) - loopif does not have to be created by the port any more, + just define LWIP_HAVE_LOOPIF to 1. + + 2010-02-08: Simon Goldschmidt + * inet.h, ip_addr.c/.h: Added reentrant versions of inet_ntoa/ipaddr_ntoa + inet_ntoa_r/ipaddr_ntoa_r + + 2010-02-08: Simon Goldschmidt + * netif.h: Added netif_s/get_igmp_mac_filter() macros + + 2010-02-05: Simon Goldschmidt + * netif.h: Added function-like macros to get/set the hostname on a netif + + 2010-02-04: Simon Goldschmidt + * nearly every file: Replaced struct ip_addr by typedef ip_addr_t to + make changing the actual implementation behind the typedef easier. + + 2010-02-01: Simon Goldschmidt + * opt.h, memp_std.h, dns.h, netdb.c, memp.c: Let netdb use a memp pool + for allocating memory when getaddrinfo() is called. + + 2010-01-31: Simon Goldschmidt + * dhcp.h, dhcp.c: Reworked the code that parses DHCP options: parse + them once instead of parsing for every option. This also removes + the need for mem_malloc from dhcp_recv and makes it possible to + correctly retrieve the BOOTP file. + + 2010-01-30: simon Goldschmidt + * sockets.c: Use SYS_LIGHTWEIGHT_PROT instead of a semaphore to protect + the sockets array. + + 2010-01-29: Simon Goldschmidt (patch by Laura Garrett) + * api.h, api_msg.c, sockets.c: Added except set support in select + (patch #6860) + + 2010-01-29: Simon Goldschmidt (patch by Laura Garrett) + * api.h, sockets.h, err.h, api_lib.c, api_msg.c, sockets.c, err.c: + Add non-blocking support for connect (partly from patch #6860), + plus many cleanups in socket & netconn API. + + 2010-01-27: Simon Goldschmidt + * opt.h, tcp.h, init.c, api_msg.c: Added TCP_SNDQUEUELOWAT corresponding + to TCP_SNDLOWAT and added tcp_sndqueuelen() - this fixes bug #28605 + + 2010-01-26: Simon Goldschmidt + * snmp: Use memp pools for snmp instead of the heap; added 4 new pools. + + 2010-01-14: Simon Goldschmidt + * ppp.c/.h: Fixed bug #27856: PPP: Set netif link- and status-callback + by adding ppp_set_netif_statuscallback()/ppp_set_netif_linkcallback() + + 2010-01-13: Simon Goldschmidt + * mem.c: The heap now may be moved to user-defined memory by defining + LWIP_RAM_HEAP_POINTER as a void pointer to that memory's address + (patch #6966 and bug #26133) + + 2010-01-10: Simon Goldschmidt (Bill Auerbach) + * opt.h, memp.c: patch #6822 (Add option to place memory pools in + separate arrays) + + 2010-01-10: Simon Goldschmidt + * init.c, igmp.c: patch #6463 (IGMP - Adding Random Delay): added define + LWIP_RAND() for lwip-wide randomization (to be defined in cc.h) + + 2009-12-31: Simon Goldschmidt + * tcpip.c, init.c, memp.c, sys.c, memp_std.h, sys.h, tcpip.h + added timers.c/.h: Separated timer implementation from semaphore/mbox + implementation, moved timer implementation to timers.c/.h, timers are + now only called from tcpip_thread or by explicitly checking them. + (TASK#7235) + + 2009-12-27: Simon Goldschmidt + * opt.h, etharp.h/.c, init.c, tcpip.c: Added an additional option + LWIP_ETHERNET to support ethernet without ARP (necessary for pure PPPoE) + + + ++ Bugfixes: + + 2011-04-20: Simon Goldschmidt + * sys_arch.txt: sys_arch_timeouts() is not needed any more. + + 2011-04-13: Simon Goldschmidt + * tcp.c, udp.c: Fixed bug #33048 (Bad range for IP source port numbers) by + using ports in the IANA private/dynamic range (49152 through 65535). + + 2011-03-29: Simon Goldschmidt, patch by Emil Lhungdahl: + * etharp.h/.c: Fixed broken VLAN support. + + 2011-03-27: Simon Goldschmidt + * tcp.c: Fixed bug #32926 (TCP_RMV(&tcp_bound_pcbs) is called on unbound tcp + pcbs) by checking if the pcb was bound (local_port != 0). + + 2011-03-27: Simon Goldschmidt + * ppp.c: Fixed bug #32280 (ppp: a pbuf is freed twice) + + 2011-03-27: Simon Goldschmidt + * sockets.c: Fixed bug #32906: lwip_connect+lwip_send did not work for udp and + raw pcbs with LWIP_TCPIP_CORE_LOCKING==1. + + 2011-03-27: Simon Goldschmidt + * tcp_out.c: Fixed bug #32820 (Outgoing TCP connections created before route + is present never times out) by starting retransmission timer before checking + route. + + 2011-03-22: Simon Goldschmidt + * ppp.c: Fixed bug #32648 (PPP code crashes when terminating a link) by only + calling sio_read_abort() if the file descriptor is valid. + + 2011-03-14: Simon Goldschmidt + * err.h/.c, sockets.c, api_msg.c: fixed bug #31748 (Calling non-blocking connect + more than once can render a socket useless) since it mainly involves changing + "FATAL" classification of error codes: ERR_USE and ERR_ISCONN just aren't fatal. + + 2011-03-13: Simon Goldschmidt + * sockets.c: fixed bug #32769 (ESHUTDOWN is linux-specific) by fixing + err_to_errno_table (ERR_CLSD: ENOTCONN instead of ESHUTDOWN), ERR_ISCONN: + use EALRADY instead of -1 + + 2011-03-13: Simon Goldschmidt + * api_lib.c: netconn_accept: return ERR_ABRT instead of ERR_CLSD if the + connection has been aborted by err_tcp (since this is not a normal closing + procedure). + + 2011-03-13: Simon Goldschmidt + * tcp.c: tcp_bind: return ERR_VAL instead of ERR_ISCONN when trying to bind + with pcb->state != CLOSED + + 2011-02-17: Simon Goldschmidt + * rawapi.txt: Fixed bug #32561 tcp_poll argument definition out-of-order in + documentation + + 2011-02-17: Simon Goldschmidt + * many files: Added missing U/UL modifiers to fix 16-bit-arch portability. + + 2011-01-24: Simon Goldschmidt + * sockets.c: Fixed bug #31741: lwip_select seems to have threading problems + + 2010-12-02: Simon Goldschmidt + * err.h: Fixed ERR_IS_FATAL so that ERR_WOULDBLOCK is not fatal. + + 2010-11-23: Simon Goldschmidt + * api.h, api_lib.c, api_msg.c, sockets.c: netconn.recv_avail is only used for + LWIP_SO_RCVBUF and ioctl/FIONREAD. + + 2010-11-23: Simon Goldschmidt + * etharp.c: Fixed bug #31720: ARP-queueing: RFC 1122 recommends to queue at + least 1 packet -> ARP_QUEUEING==0 now queues the most recent packet. + + 2010-11-23: Simon Goldschmidt + * tcp_in.c: Fixed bug #30577: tcp_input: don't discard ACK-only packets after + refusing 'refused_data' again. + + 2010-11-22: Simon Goldschmidt + * sockets.c: Fixed bug #31590: getsockopt(... SO_ERROR ...) gives EINPROGRESS + after a successful nonblocking connection. + + 2010-11-22: Simon Goldschmidt + * etharp.c: Fixed bug #31722: IP packets sent with an AutoIP source addr + must be sent link-local + + 2010-11-22: Simon Goldschmidt + * timers.c: patch #7329: tcp_timer_needed prototype was ifdef'ed out for + LWIP_TIMERS==0 + + 2010-11-20: Simon Goldschmidt + * sockets.c: Fixed bug #31170: lwip_setsockopt() does not set socket number + + 2010-11-20: Simon Goldschmidt + * sockets.h: Fixed bug #31304: Changed SHUT_RD, SHUT_WR and SHUT_RDWR to + resemble other stacks. + + 2010-11-20: Simon Goldschmidt + * dns.c: Fixed bug #31535: TCP_SND_QUEUELEN must be at least 2 or else + no-copy TCP writes will never succeed. + + 2010-11-20: Simon Goldschmidt + * dns.c: Fixed bug #31701: Error return value from dns_gethostbyname() does + not match documentation: return ERR_ARG instead of ERR_VAL if not + initialized or wrong argument. + + 2010-10-20: Simon Goldschmidt + * sockets.h: Fixed bug #31385: sizeof(struct sockaddr) is 30 but should be 16 + + 2010-10-05: Simon Goldschmidt + * dhcp.c: Once again fixed #30038: DHCP/AutoIP cooperation failed when + replugging the network cable after an AutoIP address was assigned. + + 2010-08-10: Simon Goldschmidt + * tcp.c: Fixed bug #30728: tcp_new_port() did not check listen pcbs + + 2010-08-03: Simon Goldschmidt + * udp.c, raw.c: Don't chain empty pbufs when sending them (fixes bug #30625) + + 2010-08-01: Simon Goldschmidt (patch by Greg Renda) + * ppp.c: Applied patch #7264 (PPP protocols are rejected incorrectly on big + endian architectures) + + 2010-07-28: Simon Goldschmidt + * api_lib.c, api_msg.c, sockets.c, mib2.c: Fixed compilation with TCP or UDP + disabled. + + 2010-07-27: Simon Goldschmidt + * tcp.c: Fixed bug #30565 (tcp_connect() check bound list): that check did no + harm but never did anything + + 2010-07-21: Simon Goldschmidt + * ip.c: Fixed invalid fix for bug #30402 (CHECKSUM_GEN_IP_INLINE does not + add IP options) + + 2010-07-16: Kieran Mansley + * msg_in.c: Fixed SNMP ASN constant defines to not use ! operator + + 2010-07-10: Simon Goldschmidt + * ip.c: Fixed bug #30402: CHECKSUM_GEN_IP_INLINE does not add IP options + + 2010-06-30: Simon Goldschmidt + * api_msg.c: fixed bug #30300 (shutdown parameter was not initialized in + netconn_delete) + + 2010-06-28: Kieran Mansley + * timers.c remove unportable printing of C function pointers + + 2010-06-24: Simon Goldschmidt + * init.c, timers.c/.h, opt.h, memp_std.h: From patch #7221: added flag + NO_SYS_NO_TIMERS to drop timer support for NO_SYS==1 for easier upgrading + + 2010-06-24: Simon Goldschmidt + * api(_lib).c/.h, api_msg.c/.h, sockets.c/.h: Fixed bug #10088: Correctly + implemented shutdown at socket level. + + 2010-06-21: Simon Goldschmidt + * pbuf.c/.h, ip_frag.c/.h, opt.h, memp_std.h: Fixed bug #29361 (ip_frag has + problems with zero-copy DMA MACs) by adding custom pbufs and implementing + custom pbufs that reference other (original) pbufs. Additionally set + IP_FRAG_USES_STATIC_BUF=0 as default to be on the safe side. + + 2010-06-15: Simon Goldschmidt + * dhcp.c: Fixed bug #29970: DHCP endian issue parsing option responses + + 2010-06-14: Simon Goldschmidt + * autoip.c: Fixed bug #30039: AutoIP does not reuse previous addresses + + 2010-06-12: Simon Goldschmidt + * dhcp.c: Fixed bug #30038: dhcp_network_changed doesn't reset AUTOIP coop + state + + 2010-05-17: Simon Goldschmidt + * netdb.c: Correctly NULL-terminate h_addr_list + + 2010-05-16: Simon Goldschmidt + * def.h/.c: changed the semantics of LWIP_PREFIX_BYTEORDER_FUNCS to prevent + "symbol already defined" i.e. when linking to winsock + + 2010-05-05: Simon Goldschmidt + * def.h, timers.c: Fixed bug #29769 (sys_check_timeouts: sys_now() may + overflow) + + 2010-04-21: Simon Goldschmidt + * api_msg.c: Fixed bug #29617 (sometime cause stall on delete listening + connection) + + 2010-03-28: Luca Ceresoli + * ip_addr.c/.h: patch #7143: Add a few missing const qualifiers + + 2010-03-27: Luca Ceresoli + * mib2.c: patch #7130: remove meaningless const qualifiers + + 2010-03-26: Simon Goldschmidt + * tcp_out.c: Make LWIP_NETIF_TX_SINGLE_PBUF work for TCP, too + + 2010-03-26: Simon Goldschmidt + * various files: Fixed compiling with different options disabled (TCP/UDP), + triggered by bug #29345; don't allocate acceptmbox if LWIP_TCP is disabled + + 2010-03-25: Simon Goldschmidt + * sockets.c: Fixed bug #29332: lwip_select() processes readset incorrectly + + 2010-03-25: Simon Goldschmidt + * tcp_in.c, test_tcp_oos.c: Fixed bug #29080: Correctly handle remote side + overrunning our rcv_wnd in ooseq case. + + 2010-03-22: Simon Goldschmidt + * tcp.c: tcp_listen() did not copy the pcb's prio. + + 2010-03-19: Simon Goldschmidt + * snmp_msg.c: Fixed bug #29256: SNMP Trap address was not correctly set + + 2010-03-14: Simon Goldschmidt + * opt.h, etharp.h: Fixed bug #29148 (Incorrect PBUF_POOL_BUFSIZE for ports + where ETH_PAD_SIZE > 0) by moving definition of ETH_PAD_SIZE to opt.h + and basing PBUF_LINK_HLEN on it. + + 2010-03-08: Simon Goldschmidt + * netif.c, ipv4/ip.c: task #10241 (AutoIP: don't break existing connections + when assiging routable address): when checking incoming packets and + aborting existing connection on address change, filter out link-local + addresses. + + 2010-03-06: Simon Goldschmidt + * sockets.c: Fixed LWIP_NETIF_TX_SINGLE_PBUF for LWIP_TCPIP_CORE_LOCKING + + 2010-03-06: Simon Goldschmidt + * ipv4/ip.c: Don't try to forward link-local addresses + + 2010-03-06: Simon Goldschmidt + * etharp.c: Fixed bug #29087: etharp: don't send packets for LinkLocal- + addresses to gw + + 2010-03-05: Simon Goldschmidt + * dhcp.c: Fixed bug #29072: Correctly set ciaddr based on message-type + and state. + + 2010-03-05: Simon Goldschmidt + * api_msg.c: Correctly set TCP_WRITE_FLAG_MORE when netconn_write is split + into multiple calls to tcp_write. + + 2010-02-21: Simon Goldschmidt + * opt.h, mem.h, dns.c: task #10140: Remove DNS_USES_STATIC_BUF (keep + the implementation of DNS_USES_STATIC_BUF==1) + + 2010-02-20: Simon Goldschmidt + * tcp.h, tcp.c, tcp_in.c, tcp_out.c: Task #10088: Correctly implement + close() vs. shutdown(). Now the application does not get any more + recv callbacks after calling tcp_close(). Added tcp_shutdown(). + + 2010-02-19: Simon Goldschmidt + * mem.c/.h, pbuf.c: Renamed mem_realloc() to mem_trim() to prevent + confusion with realloc() + + 2010-02-15: Simon Goldschmidt/Stephane Lesage + * netif.c/.h: Link status does not depend on LWIP_NETIF_LINK_CALLBACK + (fixes bug #28899) + + 2010-02-14: Simon Goldschmidt + * netif.c: Fixed bug #28877 (Duplicate ARP gratuitous packet with + LWIP_NETIF_LINK_CALLBACK set on) by only sending if both link- and + admin-status of a netif are up + + 2010-02-14: Simon Goldschmidt + * opt.h: Disable ETHARP_TRUST_IP_MAC by default since it slows down packet + reception and is not really necessary + + 2010-02-14: Simon Goldschmidt + * etharp.c/.h: Fixed ARP input processing: only add a new entry if a + request was directed as us (RFC 826, Packet Reception), otherwise + only update existing entries; internalized some functions + + 2010-02-14: Simon Goldschmidt + * netif.h, etharp.c, tcpip.c: Fixed bug #28183 (ARP and TCP/IP cannot be + disabled on netif used for PPPoE) by adding a new netif flag + (NETIF_FLAG_ETHERNET) that tells the stack the device is an ethernet + device but prevents usage of ARP (so that ethernet_input can be used + for PPPoE). + + 2010-02-12: Simon Goldschmidt + * netif.c: netif_set_link_up/down: only do something if the link state + actually changes + + 2010-02-12: Simon Goldschmidt/Stephane Lesage + * api_msg.c: Fixed bug #28865 (Cannot close socket/netconn in non-blocking + connect) + + 2010-02-12: Simon Goldschmidt + * mem.h: Fixed bug #28866 (mem_realloc function defined in mem.h) + + 2010-02-09: Simon Goldschmidt + * api_lib.c, api_msg.c, sockets.c, api.h, api_msg.h: Fixed bug #22110 + (recv() makes receive window update for data that wasn't received by + application) + + 2010-02-09: Simon Goldschmidt/Stephane Lesage + * sockets.c: Fixed bug #28853 (lwip_recvfrom() returns 0 on receive time-out + or any netconn_recv() error) + + 2010-02-09: Simon Goldschmidt + * ppp.c: task #10154 (PPP: Update snmp in/out counters for tx/rx packets) + + 2010-02-09: Simon Goldschmidt + * netif.c: For loopback packets, adjust the stats- and snmp-counters + for the loopback netif. + + 2010-02-08: Simon Goldschmidt + * igmp.c/.h, ip.h: Moved most defines from igmp.h to igmp.c for clarity + since they are not used anywhere else. + + 2010-02-08: Simon Goldschmidt (Stéphane Lesage) + * igmp.c, igmp.h, stats.c, stats.h: Improved IGMP stats + (patch from bug #28798) + + 2010-02-08: Simon Goldschmidt (Stéphane Lesage) + * igmp.c: Fixed bug #28798 (Error in "Max Response Time" processing) and + another bug when LWIP_RAND() returns zero. + + 2010-02-04: Simon Goldschmidt + * nearly every file: Use macros defined in ip_addr.h (some of them new) + to work with IP addresses (preparation for bug #27352 - Change ip_addr + from struct to typedef (u32_t) - and better code). + + 2010-01-31: Simon Goldschmidt + * netif.c: Don't call the link-callback from netif_set_up/down() since + this invalidly retriggers DHCP. + + 2010-01-29: Simon Goldschmidt + * ip_addr.h, inet.h, def.h, inet.c, def.c, more: Cleanly separate the + portability file inet.h and its contents from the stack: moved htonX- + functions to def.h (and the new def.c - they are not ipv4 dependent), + let inet.h depend on ip_addr.h and not the other way round. + This fixes bug #28732. + + 2010-01-28: Kieran Mansley + * tcp.c: Ensure ssthresh >= 2*MSS + + 2010-01-27: Simon Goldschmidt + * tcp.h, tcp.c, tcp_in.c: Fixed bug #27871: Calling tcp_abort() in recv + callback can lead to accessing unallocated memory. As a consequence, + ERR_ABRT means the application has called tcp_abort()! + + 2010-01-25: Simon Goldschmidt + * snmp_structs.h, msg_in.c: Partly fixed bug #22070 (MIB_OBJECT_WRITE_ONLY + not implemented in SNMP): write-only or not-accessible are still + returned by getnext (though not by get) + + 2010-01-24: Simon Goldschmidt + * snmp: Renamed the private mib node from 'private' to 'mib_private' to + not use reserved C/C++ keywords + + 2010-01-23: Simon Goldschmidt + * sockets.c: Fixed bug #28716: select() returns 0 after waiting for less + than 1 ms + + 2010-01-21: Simon Goldschmidt + * tcp.c, api_msg.c: Fixed bug #28651 (tcp_connect: no callbacks called + if tcp_enqueue fails) both in raw- and netconn-API + + 2010-01-19: Simon Goldschmidt + * api_msg.c: Fixed bug #27316: netconn: Possible deadlock in err_tcp + + 2010-01-18: Iordan Neshev/Simon Goldschmidt + * src/netif/ppp: reorganised PPP sourcecode to 2.3.11 including some + bugfix backports from 2.4.x. + + 2010-01-18: Simon Goldschmidt + * mem.c: Fixed bug #28679: mem_realloc calculates mem_stats wrong + + 2010-01-17: Simon Goldschmidt + * api_lib.c, api_msg.c, (api_msg.h, api.h, sockets.c, tcpip.c): + task #10102: "netconn: clean up conn->err threading issues" by adding + error return value to struct api_msg_msg + + 2010-01-17: Simon Goldschmidt + * api.h, api_lib.c, sockets.c: Changed netconn_recv() and netconn_accept() + to return err_t (bugs #27709 and #28087) + + 2010-01-14: Simon Goldschmidt + * ...: Use typedef for function prototypes throughout the stack. + + 2010-01-13: Simon Goldschmidt + * api_msg.h/.c, api_lib.c: Fixed bug #26672 (close connection when receive + window = 0) by correctly draining recvmbox/acceptmbox + + 2010-01-11: Simon Goldschmidt + * pap.c: Fixed bug #13315 (PPP PAP authentication can result in + erroneous callbacks) by copying the code from recent pppd + + 2010-01-10: Simon Goldschmidt + * raw.c: Fixed bug #28506 (raw_bind should filter received packets) + + 2010-01-10: Simon Goldschmidt + * tcp.h/.c: bug #28127 (remove call to tcp_output() from tcp_ack(_now)()) + + 2010-01-08: Simon Goldschmidt + * sockets.c: Fixed bug #28519 (lwip_recvfrom bug with len > 65535) + + 2010-01-08: Simon Goldschmidt + * dns.c: Copy hostname for DNS_LOCAL_HOSTLIST_IS_DYNAMIC==1 since string + passed to dns_local_addhost() might be volatile + + 2010-01-07: Simon Goldschmidt + * timers.c, tcp.h: Call tcp_timer_needed() with NO_SYS==1, too + + 2010-01-06: Simon Goldschmidt + * netdb.h: Fixed bug #28496: missing include guards in netdb.h + + 2009-12-31: Simon Goldschmidt + * many ppp files: Reorganised PPP source code from ucip structure to pppd + structure to easily compare our code against the pppd code (around v2.3.1) + + 2009-12-27: Simon Goldschmidt + * tcp_in.c: Another fix for bug #28241 (ooseq processing) and adapted + unit test + + +(STABLE-1.3.2) + + ++ New features: + + 2009-10-27 Simon Goldschmidt/Stephan Lesage + * netifapi.c/.h: Added netifapi_netif_set_addr() + + 2009-10-07 Simon Goldschmidt/Fabian Koch + * api_msg.c, netbuf.c/.h, opt.h: patch #6888: Patch for UDP Netbufs to + support dest-addr and dest-port (optional: LWIP_NETBUF_RECVINFO) + + 2009-08-26 Simon Goldschmidt/Simon Kallweit + * slipif.c/.h: bug #26397: SLIP polling support + + 2009-08-25 Simon Goldschmidt + * opt.h, etharp.h/.c: task #9033: Support IEEE 802.1q tagged frame (VLAN), + New configuration options ETHARP_SUPPORT_VLAN and ETHARP_VLAN_CHECK. + + 2009-08-25 Simon Goldschmidt + * ip_addr.h, netdb.c: patch #6900: added define ip_ntoa(struct ip_addr*) + + 2009-08-24 Jakob Stoklund Olesen + * autoip.c, dhcp.c, netif.c: patch #6725: Teach AutoIP and DHCP to respond + to netif_set_link_up(). + + 2009-08-23 Simon Goldschmidt + * tcp.h/.c: Added function tcp_debug_state_str() to convert a tcp state + to a human-readable string. + + ++ Bugfixes: + + 2009-12-24: Kieran Mansley + * tcp_in.c Apply patches from Oleg Tyshev to improve OOS processing + (BUG#28241) + + 2009-12-06: Simon Goldschmidt + * ppp.h/.c: Fixed bug #27079 (Yet another leak in PPP): outpacket_buf can + be statically allocated (like in ucip) + + 2009-12-04: Simon Goldschmidt (patch by Ioardan Neshev) + * pap.c: patch #6969: PPP: missing PAP authentication UNTIMEOUT + + 2009-12-03: Simon Goldschmidt + * tcp.h, tcp_in.c, tcp_out.c: Fixed bug #28106: dup ack for fast retransmit + could have non-zero length + + 2009-12-02: Simon Goldschmidt + * tcp_in.c: Fixed bug #27904: TCP sends too many ACKs: delay resetting + tcp_input_pcb until after calling the pcb's callbacks + + 2009-11-29: Simon Goldschmidt + * tcp_in.c: Fixed bug #28054: Two segments with FIN flag on the out-of- + sequence queue, also fixed PBUF_POOL leak in the out-of-sequence code + + 2009-11-29: Simon Goldschmidt + * pbuf.c: Fixed bug #28064: pbuf_alloc(PBUF_POOL) is not thread-safe by + queueing a call into tcpip_thread to free ooseq-bufs if the pool is empty + + 2009-11-26: Simon Goldschmidt + * tcp.h: Fixed bug #28098: Nagle can prevent fast retransmit from sending + segment + + 2009-11-26: Simon Goldschmidt + * tcp.h, sockets.c: Fixed bug #28099: API required to disable Nagle + algorithm at PCB level + + 2009-11-22: Simon Goldschmidt + * tcp_out.c: Fixed bug #27905: FIN isn't combined with data on unsent + + 2009-11-22: Simon Goldschmidt (suggested by Bill Auerbach) + * tcp.c: tcp_alloc: prevent increasing stats.err for MEMP_TCP_PCB when + reusing time-wait pcb + + 2009-11-20: Simon Goldschmidt (patch by Albert Bartel) + * sockets.c: Fixed bug #28062: Data received directly after accepting + does not wake up select + + 2009-11-11: Simon Goldschmidt + * netdb.h: Fixed bug #27994: incorrect define for freeaddrinfo(addrinfo) + + 2009-10-30: Simon Goldschmidt + * opt.h: Increased default value for TCP_MSS to 536, updated default + value for TCP_WND to 4*TCP_MSS to keep delayed ACK working. + + 2009-10-28: Kieran Mansley + * tcp_in.c, tcp_out.c, tcp.h: re-work the fast retransmission code + to follow algorithm from TCP/IP Illustrated + + 2009-10-27: Kieran Mansley + * tcp_in.c: fix BUG#27445: grow cwnd with every duplicate ACK + + 2009-10-25: Simon Goldschmidt + * tcp.h: bug-fix in the TCP_EVENT_RECV macro (has to call tcp_recved if + pcb->recv is NULL to keep rcv_wnd correct) + + 2009-10-25: Simon Goldschmidt + * tcp_in.c: Fixed bug #26251: RST process in TIME_WAIT TCP state + + 2009-10-23: Simon Goldschmidt (David Empson) + * tcp.c: Fixed bug #27783: Silly window avoidance for small window sizes + + 2009-10-21: Simon Goldschmidt + * tcp_in.c: Fixed bug #27215: TCP sent() callback gives leading and + trailing 1 byte len (SYN/FIN) + + 2009-10-21: Simon Goldschmidt + * tcp_out.c: Fixed bug #27315: zero window probe and FIN + + 2009-10-19: Simon Goldschmidt + * dhcp.c/.h: Minor code simplification (don't store received pbuf, change + conditional code to assert where applicable), check pbuf length before + testing for valid reply + + 2009-10-19: Simon Goldschmidt + * dhcp.c: Removed most calls to udp_connect since they aren't necessary + when using udp_sendto_if() - always stay connected to IP_ADDR_ANY. + + 2009-10-16: Simon Goldschmidt + * ip.c: Fixed bug #27390: Source IP check in ip_input() causes it to drop + valid DHCP packets -> allow 0.0.0.0 as source address when LWIP_DHCP is + enabled + + 2009-10-15: Simon Goldschmidt (Oleg Tyshev) + * tcp_in.c: Fixed bug #27329: dupacks by unidirectional data transmit + + 2009-10-15: Simon Goldschmidt + * api_lib.c: Fixed bug #27709: conn->err race condition on netconn_recv() + timeout + + 2009-10-15: Simon Goldschmidt + * autoip.c: Fixed bug #27704: autoip starts with wrong address + LWIP_AUTOIP_CREATE_SEED_ADDR() returned address in host byte order instead + of network byte order + + 2009-10-11 Simon Goldschmidt (Jörg Kesten) + * tcp_out.c: Fixed bug #27504: tcp_enqueue wrongly concatenates segments + which are not consecutive when retransmitting unacked segments + + 2009-10-09 Simon Goldschmidt + * opt.h: Fixed default values of some stats to only be enabled if used + Fixes bug #27338: sys_stats is defined when NO_SYS = 1 + + 2009-08-30 Simon Goldschmidt + * ip.c: Fixed bug bug #27345: "ip_frag() does not use the LWIP_NETIF_LOOPBACK + function" by checking for loopback before calling ip_frag + + 2009-08-25 Simon Goldschmidt + * dhcp.c: fixed invalid dependency to etharp_query if DHCP_DOES_ARP_CHECK==0 + + 2009-08-23 Simon Goldschmidt + * ppp.c: bug #27078: Possible memory leak in pppInit() + + 2009-08-23 Simon Goldschmidt + * netdb.c, dns.c: bug #26657: DNS, if host name is "localhost", result + is error. + + 2009-08-23 Simon Goldschmidt + * opt.h, init.c: bug #26649: TCP fails when TCP_MSS > TCP_SND_BUF + Fixed wrong parenthesis, added check in init.c + + 2009-08-23 Simon Goldschmidt + * ppp.c: bug #27266: wait-state debug message in pppMain occurs every ms + + 2009-08-23 Simon Goldschmidt + * many ppp files: bug #27267: Added include to string.h where needed + + 2009-08-23 Simon Goldschmidt + * tcp.h: patch #6843: tcp.h macro optimization patch (for little endian) + + +(STABLE-1.3.1) + + ++ New features: + + 2009-05-10 Simon Goldschmidt + * opt.h, sockets.c, pbuf.c, netbuf.h, pbuf.h: task #7013: Added option + LWIP_NETIF_TX_SINGLE_PBUF to try to create transmit packets from only + one pbuf to help MACs that don't support scatter-gather DMA. + + 2009-05-09 Simon Goldschmidt + * icmp.h, icmp.c: Shrinked ICMP code, added option to NOT check icoming + ECHO pbuf for size (just use it): LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN + + 2009-05-05 Simon Goldschmidt, Jakob Stoklund Olesen + * ip.h, ip.c: Added ip_current_netif() & ip_current_header() to receive + extended info about the currently received packet. + + 2009-04-27 Simon Goldschmidt + * sys.h: Made SYS_LIGHTWEIGHT_PROT and sys_now() work with NO_SYS=1 + + 2009-04-25 Simon Goldschmidt + * mem.c, opt.h: Added option MEM_USE_POOLS_TRY_BIGGER_POOL to try the next + bigger malloc pool if one is empty (only usable with MEM_USE_POOLS). + + 2009-04-21 Simon Goldschmidt + * dns.c, init.c, dns.h, opt.h: task #7507, patch #6786: DNS supports static + hosts table. New configuration options DNS_LOCAL_HOSTLIST and + DNS_LOCAL_HOSTLIST_IS_DYNAMIC. Also, DNS_LOOKUP_LOCAL_EXTERN() can be defined + as an external function for lookup. + + 2009-04-15 Simon Goldschmidt + * dhcp.c: patch #6763: Global DHCP XID can be redefined to something more unique + + 2009-03-31 Kieran Mansley + * tcp.c, tcp_out.c, tcp_in.c, sys.h, tcp.h, opts.h: add support for + TCP timestamp options, off by default. Rework tcp_enqueue() to + take option flags rather than specified option data + + 2009-02-18 Simon Goldschmidt + * cc.h: Added printf formatter for size_t: SZT_F + + 2009-02-16 Simon Goldschmidt (patch by Rishi Khan) + * icmp.c, opt.h: patch #6539: (configurable) response to broadcast- and multicast + pings + + 2009-02-12 Simon Goldschmidt + * init.h: Added LWIP_VERSION to get the current version of the stack + + 2009-02-11 Simon Goldschmidt (suggested by Gottfried Spitaler) + * opt.h, memp.h/.c: added MEMP_MEM_MALLOC to use mem_malloc/mem_free instead + of the pool allocator (can save code size with MEM_LIBC_MALLOC if libc-malloc + is otherwise used) + + 2009-01-28 Jonathan Larmour (suggested by Bill Bauerbach) + * ipv4/inet_chksum.c, ipv4/lwip/inet_chksum.h: inet_chksum_pseudo_partial() + is only used by UDPLITE at present, so conditionalise it. + + 2008-12-03 Simon Goldschmidt (base on patch from Luca Ceresoli) + * autoip.c: checked in (slightly modified) patch #6683: Customizable AUTOIP + "seed" address. This should reduce AUTOIP conflicts if + LWIP_AUTOIP_CREATE_SEED_ADDR is overridden. + + 2008-10-02 Jonathan Larmour and Rishi Khan + * sockets.c (lwip_accept): Return EWOULDBLOCK if would block on non-blocking + socket. + + 2008-06-30 Simon Goldschmidt + * mem.c, opt.h, stats.h: fixed bug #21433: Calling mem_free/pbuf_free from + interrupt context isn't safe: LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT allows + mem_free to run between mem_malloc iterations. Added illegal counter for + mem stats. + + 2008-06-27 Simon Goldschmidt + * stats.h/.c, some other files: patch #6483: stats module improvement: + Added defines to display each module's statistic individually, added stats + defines for MEM, MEMP and SYS modules, removed (unused) rexmit counter. + + 2008-06-17 Simon Goldschmidt + * err.h: patch #6459: Made err_t overridable to use a more efficient type + (define LWIP_ERR_T in cc.h) + + 2008-06-17 Simon Goldschmidt + * slipif.c: patch #6480: Added a configuration option for slipif for symmetry + to loopif + + 2008-06-17 Simon Goldschmidt (patch by Luca Ceresoli) + * netif.c, loopif.c, ip.c, netif.h, loopif.h, opt.h: Checked in slightly + modified version of patch # 6370: Moved loopif code to netif.c so that + loopback traffic is supported on all netifs (all local IPs). + Added option to limit loopback packets for each netifs. + + + ++ Bugfixes: + 2009-08-12 Kieran Mansley + * tcp_in.c, tcp.c: Fix bug #27209: handle trimming of segments when + out of window or out of order properly + + 2009-08-12 Kieran Mansley + * tcp_in.c: Fix bug #27199: use snd_wl2 instead of snd_wl1 + + 2009-07-28 Simon Goldschmidt + * mem.h: Fixed bug #27105: "realloc() cannot replace mem_realloc()"s + + 2009-07-27 Kieran Mansley + * api.h api_msg.h netdb.h sockets.h: add missing #include directives + + 2009-07-09 Kieran Mansley + * api_msg.c, sockets.c, api.h: BUG23240 use signed counters for + recv_avail and don't increment counters until message successfully + sent to mbox + + 2009-06-25 Kieran Mansley + * api_msg.c api.h: BUG26722: initialise netconn write variables + in netconn_alloc + + 2009-06-25 Kieran Mansley + * tcp.h: BUG26879: set ret value in TCP_EVENT macros when function is not set + + 2009-06-25 Kieran Mansley + * tcp.c, tcp_in.c, tcp_out.c, tcp.h: BUG26301 and BUG26267: correct + simultaneous close behaviour, and make snd_nxt have the same meaning + as in the RFCs. + + 2009-05-12 Simon Goldschmidt + * etharp.h, etharp.c, netif.c: fixed bug #26507: "Gratuitous ARP depends on + arp_table / uses etharp_query" by adding etharp_gratuitous() + + 2009-05-12 Simon Goldschmidt + * ip.h, ip.c, igmp.c: bug #26487: Added ip_output_if_opt that can add IP options + to the IP header (used by igmp_ip_output_if) + + 2009-05-06 Simon Goldschmidt + * inet_chksum.c: On little endian architectures, use LWIP_PLATFORM_HTONS (if + defined) for SWAP_BYTES_IN_WORD to speed up checksumming. + + 2009-05-05 Simon Goldschmidt + * sockets.c: bug #26405: Prematurely released semaphore causes lwip_select() + to crash + + 2009-05-04 Simon Goldschmidt + * init.c: snmp was not initialized in lwip_init() + + 2009-05-04 Frédéric Bernon + * dhcp.c, netbios.c: Changes if IP_SOF_BROADCAST is enabled. + + 2009-05-03 Simon Goldschmidt + * tcp.h: bug #26349: Nagle algorithm doesn't send although segment is full + (and unsent->next == NULL) + + 2009-05-02 Simon Goldschmidt + * tcpip.h, tcpip.c: fixed tcpip_untimeout (does not need the time, broken after + 1.3.0 in CVS only) - fixes compilation of ppp_oe.c + + 2009-05-02 Simon Goldschmidt + * msg_in.c: fixed bug #25636: SNMPSET value is ignored for integer fields + + 2009-05-01 Simon Goldschmidt + * pap.c: bug #21680: PPP upap_rauthnak() drops legal NAK packets + + 2009-05-01 Simon Goldschmidt + * ppp.c: bug #24228: Memory corruption with PPP and DHCP + + 2009-04-29 Frédéric Bernon + * raw.c, udp.c, init.c, opt.h, ip.h, sockets.h: bug #26309: Implement the + SO(F)_BROADCAST filter for all API layers. Avoid the unindented reception + of broadcast packets even when this option wasn't set. Port maintainers + which want to enable this filter have to set IP_SOF_BROADCAST=1 in opt.h. + If you want this option also filter broadcast on recv operations, you also + have to set IP_SOF_BROADCAST_RECV=1 in opt.h. + + 2009-04-28 Simon Goldschmidt, Jakob Stoklund Olesen + * dhcp.c: patch #6721, bugs #25575, #25576: Some small fixes to DHCP and + DHCP/AUTOIP cooperation + + 2009-04-25 Simon Goldschmidt, Oleg Tyshev + * tcp_out.c: bug #24212: Deadlocked tcp_retransmit due to exceeded pcb->cwnd + Fixed by sorting the unsent and unacked queues (segments are inserted at the + right place in tcp_output and tcp_rexmit). + + 2009-04-25 Simon Goldschmidt + * memp.c, mem.c, memp.h, mem_std.h: bug #26213 "Problem with memory allocation + when debugging": memp_sizes contained the wrong sizes (including sanity + regions); memp pools for MEM_USE_POOLS were too small + + 2009-04-24 Simon Goldschmidt, Frédéric Bernon + * inet.c: patch #6765: Fix a small problem with the last changes (incorrect + behavior, with with ip address string not ended by a '\0', a space or a + end of line) + + 2009-04-19 Simon Goldschmidt + * rawapi.txt: Fixed bug #26069: Corrected documentation: if tcp_connect fails, + pcb->err is called, not pcb->connected (with an error code). + + 2009-04-19 Simon Goldschmidt + * tcp_out.c: Fixed bug #26236: "TCP options (timestamp) don't work with + no-copy-tcpwrite": deallocate option data, only concat segments with same flags + + 2009-04-19 Simon Goldschmidt + * tcp_out.c: Fixed bug #25094: "Zero-length pbuf" (options are now allocated + in the header pbuf, not the data pbuf) + + 2009-04-18 Simon Goldschmidt + * api_msg.c: fixed bug #25695: Segmentation fault in do_writemore() + + 2009-04-15 Simon Goldschmidt + * sockets.c: tried to fix bug #23559: lwip_recvfrom problem with tcp + + 2009-04-15 Simon Goldschmidt + * dhcp.c: task #9192: mem_free of dhcp->options_in and dhcp->msg_in + + 2009-04-15 Simon Goldschmidt + * ip.c, ip6.c, tcp_out.c, ip.h: patch #6808: Add a utility function + ip_hinted_output() (for smaller code mainly) + + 2009-04-15 Simon Goldschmidt + * inet.c: patch #6765: Supporting new line characters in inet_aton() + + 2009-04-15 Simon Goldschmidt + * dhcp.c: patch #6764: DHCP rebind and renew did not send hostnam option; + Converted constant OPTION_MAX_MSG_SIZE to netif->mtu, check if netif->mtu + is big enough in dhcp_start + + 2009-04-15 Simon Goldschmidt + * netbuf.c: bug #26027: netbuf_chain resulted in pbuf memory leak + + 2009-04-15 Simon Goldschmidt + * sockets.c, ppp.c: bug #25763: corrected 4 occurrences of SMEMCPY to MEMCPY + + 2009-04-15 Simon Goldschmidt + * sockets.c: bug #26121: set_errno can be overridden + + 2009-04-09 Kieran Mansley (patch from Luca Ceresoli ) + * init.c, opt.h: Patch#6774 TCP_QUEUE_OOSEQ breaks compilation when + LWIP_TCP==0 + + 2009-04-09 Kieran Mansley (patch from Roy Lee ) + * tcp.h: Patch#6802 Add do-while-clauses to those function like + macros in tcp.h + + 2009-03-31 Kieran Mansley + * tcp.c, tcp_in.c, tcp_out.c, tcp.h, opt.h: Rework the way window + updates are calculated and sent (BUG20515) + + * tcp_in.c: cope with SYN packets received during established states, + and retransmission of initial SYN. + + * tcp_out.c: set push bit correctly when tcp segments are merged + + 2009-03-27 Kieran Mansley + * tcp_out.c set window correctly on probes (correcting change made + yesterday) + + 2009-03-26 Kieran Mansley + * tcp.c, tcp_in.c, tcp.h: add tcp_abandon() to cope with dropping + connections where no reset required (bug #25622) + + * tcp_out.c: set TCP_ACK flag on keepalive and zero window probes + (bug #20779) + + 2009-02-18 Simon Goldschmidt (Jonathan Larmour and Bill Auerbach) + * ip_frag.c: patch #6528: the buffer used for IP_FRAG_USES_STATIC_BUF could be + too small depending on MEM_ALIGNMENT + + 2009-02-16 Simon Goldschmidt + * sockets.h/.c, api_*.h/.c: fixed arguments of socket functions to match the standard; + converted size argument of netconn_write to 'size_t' + + 2009-02-16 Simon Goldschmidt + * tcp.h, tcp.c: fixed bug #24440: TCP connection close problem on 64-bit host + by moving accept callback function pointer to TCP_PCB_COMMON + + 2009-02-12 Simon Goldschmidt + * dhcp.c: fixed bug #25345 (DHCPDECLINE is sent with "Maximum message size" + option) + + 2009-02-11 Simon Goldschmidt + * dhcp.c: fixed bug #24480 (releasing old udp_pdb and pbuf in dhcp_start) + + 2009-02-11 Simon Goldschmidt + * opt.h, api_msg.c: added configurable default valud for netconn->recv_bufsize: + RECV_BUFSIZE_DEFAULT (fixes bug #23726: pbuf pool exhaustion on slow recv()) + + 2009-02-10 Simon Goldschmidt + * tcp.c: fixed bug #25467: Listen backlog is not reset on timeout in SYN_RCVD: + Accepts_pending is decrease on a corresponding listen pcb when a connection + in state SYN_RCVD is close. + + 2009-01-28 Jonathan Larmour + * pbuf.c: reclaim pbufs from TCP out-of-sequence segments if we run + out of pool pbufs. + + 2008-12-19 Simon Goldschmidt + * many files: patch #6699: fixed some warnings on platform where sizeof(int) == 2 + + 2008-12-10 Tamas Somogyi, Frédéric Bernon + * sockets.c: fixed bug #25051: lwip_recvfrom problem with udp: fromaddr and + port uses deleted netbuf. + + 2008-10-18 Simon Goldschmidt + * tcp_in.c: fixed bug ##24596: Vulnerability on faulty TCP options length + in tcp_parseopt + + 2008-10-15 Simon Goldschmidt + * ip_frag.c: fixed bug #24517: IP reassembly crashes on unaligned IP headers + by packing the struct ip_reass_helper. + + 2008-10-03 David Woodhouse, Jonathan Larmour + * etharp.c (etharp_arp_input): Fix type aliasing problem copying ip address. + + 2008-10-02 Jonathan Larmour + * dns.c: Hard-code structure sizes, to avoid issues on some compilers where + padding is included. + + 2008-09-30 Jonathan Larmour + * sockets.c (lwip_accept): check addr isn't NULL. If it's valid, do an + assertion check that addrlen isn't NULL. + + 2008-09-30 Jonathan Larmour + * tcp.c: Fix bug #24227, wrong error message in tcp_bind. + + 2008-08-26 Simon Goldschmidt + * inet.h, ip_addr.h: fixed bug #24132: Cross-dependency between ip_addr.h and + inet.h -> moved declaration of struct in_addr from ip_addr.h to inet.h + + 2008-08-14 Simon Goldschmidt + * api_msg.c: fixed bug #23847: do_close_internal references freed memory (when + tcp_close returns != ERR_OK) + + 2008-07-08 Frédéric Bernon + * stats.h: Fix some build bugs introduced with patch #6483 (missing some parameters + in macros, mainly if MEM_STATS=0 and MEMP_STATS=0). + + 2008-06-24 Jonathan Larmour + * tcp_in.c: Fix for bug #23693 as suggested by Art R. Ensure cseg is unused + if tcp_seg_copy fails. + + 2008-06-17 Simon Goldschmidt + * inet_chksum.c: Checked in some ideas of patch #6460 (loop optimizations) + and created defines for swapping bytes and folding u32 to u16. + + 2008-05-30 Kieran Mansley + * tcp_in.c Remove redundant "if" statement, and use real rcv_wnd + rather than rcv_ann_wnd when deciding if packets are in-window. + Contributed by + + 2008-05-30 Kieran Mansley + * mem.h: Fix BUG#23254. Change macro definition of mem_* to allow + passing as function pointers when MEM_LIBC_MALLOC is defined. + + 2008-05-09 Jonathan Larmour + * err.h, err.c, sockets.c: Fix bug #23119: Reorder timeout error code to + stop it being treated as a fatal error. + + 2008-04-15 Simon Goldschmidt + * dhcp.c: fixed bug #22804: dhcp_stop doesn't clear NETIF_FLAG_DHCP + (flag now cleared) + + 2008-03-27 Simon Goldschmidt + * mem.c, tcpip.c, tcpip.h, opt.h: fixed bug #21433 (Calling mem_free/pbuf_free + from interrupt context isn't safe): set LWIP_USE_HEAP_FROM_INTERRUPT to 1 + in lwipopts.h or use pbuf_free_callback(p)/mem_free_callback(m) to free pbufs + or heap memory from interrupt context + + 2008-03-26 Simon Goldschmidt + * tcp_in.c, tcp.c: fixed bug #22249: division by zero could occur if a remote + host sent a zero mss as TCP option. + + +(STABLE-1.3.0) + + ++ New features: + + 2008-03-10 Jonathan Larmour + * inet_chksum.c: Allow choice of one of the sample algorithms to be + made from lwipopts.h. Fix comment on how to override LWIP_CHKSUM. + + 2008-01-22 Frédéric Bernon + * tcp.c, tcp_in.c, tcp.h, opt.h: Rename LWIP_CALCULATE_EFF_SEND_MSS in + TCP_CALCULATE_EFF_SEND_MSS to have coherent TCP options names. + + 2008-01-14 Frédéric Bernon + * rawapi.txt, api_msg.c, tcp.c, tcp_in.c, tcp.h: changes for task #7675 "Enable + to refuse data on a TCP_EVENT_RECV call". Important, behavior changes for the + tcp_recv callback (see rawapi.txt). + + 2008-01-14 Frédéric Bernon, Marc Chaland + * ip.c: Integrate patch #6369" ip_input : checking before realloc". + + 2008-01-12 Frédéric Bernon + * tcpip.h, tcpip.c, api.h, api_lib.c, api_msg.c, sockets.c: replace the field + netconn::sem per netconn::op_completed like suggested for the task #7490 + "Add return value to sys_mbox_post". + + 2008-01-12 Frédéric Bernon + * api_msg.c, opt.h: replace DEFAULT_RECVMBOX_SIZE per DEFAULT_TCP_RECVMBOX_SIZE, + DEFAULT_UDP_RECVMBOX_SIZE and DEFAULT_RAW_RECVMBOX_SIZE (to optimize queues + sizes), like suggested for the task #7490 "Add return value to sys_mbox_post". + + 2008-01-10 Frédéric Bernon + * tcpip.h, tcpip.c: add tcpip_callback_with_block function for the task #7490 + "Add return value to sys_mbox_post". tcpip_callback is always defined as + "blocking" ("block" parameter = 1). + + 2008-01-10 Frédéric Bernon + * tcpip.h, tcpip.c, api.h, api_lib.c, api_msg.c, sockets.c: replace the field + netconn::mbox (sys_mbox_t) per netconn::sem (sys_sem_t) for the task #7490 + "Add return value to sys_mbox_post". + + 2008-01-05 Frédéric Bernon + * sys_arch.txt, api.h, api_lib.c, api_msg.h, api_msg.c, tcpip.c, sys.h, opt.h: + Introduce changes for task #7490 "Add return value to sys_mbox_post" with some + modifications in the sys_mbox api: sys_mbox_new take a "size" parameters which + indicate the number of pointers query by the mailbox. There is three defines + in opt.h to indicate sizes for tcpip::mbox, netconn::recvmbox, and for the + netconn::acceptmbox. Port maintainers, you can decide to just add this new + parameter in your implementation, but to ignore it to keep the previous behavior. + The new sys_mbox_trypost function return a value to know if the mailbox is + full or if the message is posted. Take a look to sys_arch.txt for more details. + This new function is used in tcpip_input (so, can be called in an interrupt + context since the function is not blocking), and in recv_udp and recv_raw. + + 2008-01-04 Frédéric Bernon, Simon Goldschmidt, Jonathan Larmour + * rawapi.txt, api.h, api_lib.c, api_msg.h, api_msg.c, sockets.c, tcp.h, tcp.c, + tcp_in.c, init.c, opt.h: rename backlog options with TCP_ prefix, limit the + "backlog" parameter in an u8_t, 0 is interpreted as "smallest queue", add + documentation in the rawapi.txt file. + + 2007-12-31 Kieran Mansley (based on patch from Per-Henrik Lundbolm) + * tcp.c, tcp_in.c, tcp_out.c, tcp.h: Add TCP persist timer + + 2007-12-31 Frédéric Bernon, Luca Ceresoli + * autoip.c, etharp.c: ip_addr.h: Integrate patch #6348: "Broadcast ARP packets + in autoip". The change in etharp_raw could be removed, since all calls to + etharp_raw use ethbroadcast for the "ethdst_addr" parameter. But it could be + wrong in the future. + + 2007-12-30 Frédéric Bernon, Tom Evans + * ip.c: Fix bug #21846 "LwIP doesn't appear to perform any IP Source Address + Filtering" reported by Tom Evans. + + 2007-12-21 Frédéric Bernon, Simon Goldschmidt, Jonathan Larmour + * tcp.h, opt.h, api.h, api_msg.h, tcp.c, tcp_in.c, api_lib.c, api_msg.c, + sockets.c, init.c: task #7252: Implement TCP listen backlog: Warning: raw API + applications have to call 'tcp_accepted(pcb)' in their accept callback to + keep accepting new connections. + + 2007-12-13 Frédéric Bernon + * api_msg.c, err.h, err.c, sockets.c, dns.c, dns.h: replace "enum dns_result" + by err_t type. Add a new err_t code "ERR_INPROGRESS". + + 2007-12-12 Frédéric Bernon + * dns.h, dns.c, opt.h: move DNS options to the "right" place. Most visibles + are the one which have ram usage. + + 2007-12-05 Frédéric Bernon + * netdb.c: add a LWIP_DNS_API_HOSTENT_STORAGE option to decide to use a static + set of variables (=0) or a local one (=1). In this last case, your port should + provide a function "struct hostent* sys_thread_hostent( struct hostent* h)" + which have to do a copy of "h" and return a pointer ont the "per-thread" copy. + + 2007-12-03 Simon Goldschmidt + * ip.c: ip_input: check if a packet is for inp first before checking all other + netifs on netif_list (speeds up packet receiving in most cases) + + 2007-11-30 Simon Goldschmidt + * udp.c, raw.c: task #7497: Sort lists (pcb, netif, ...) for faster access + UDP: move a (connected) pcb selected for input to the front of the list of + pcbs so that it is found faster next time. Same for RAW pcbs that have eaten + a packet. + + 2007-11-28 Simon Goldschmidt + * etharp.c, stats.c, stats.h, opt.h: Introduced ETHARP_STATS + + 2007-11-25 Simon Goldschmidt + * dhcp.c: dhcp_unfold_reply() uses pbuf_copy_partial instead of its own copy + algorithm. + + 2007-11-24 Simon Goldschmidt + * netdb.h, netdb.c, sockets.h/.c: Moved lwip_gethostbyname from sockets.c + to the new file netdb.c; included lwip_getaddrinfo. + + 2007-11-21 Simon Goldschmidt + * tcp.h, opt.h, tcp.c, tcp_in.c: implemented calculating the effective send-mss + based on the MTU of the netif used to send. Enabled by default. Disable by + setting LWIP_CALCULATE_EFF_SEND_MSS to 0. This fixes bug #21492. + + 2007-11-19 Frédéric Bernon + * api_msg.c, dns.h, dns.c: Implement DNS_DOES_NAME_CHECK option (check if name + received match the name query), implement DNS_USES_STATIC_BUF (the place where + copy dns payload to parse the response), return an error if there is no place + for a new query, and fix some minor problems. + + 2007-11-16 Simon Goldschmidt + * new files: ipv4/inet.c, ipv4/inet_chksum.c, ipv6/inet6.c + removed files: core/inet.c, core/inet6.c + Moved inet files into ipv4/ipv6 directory; splitted inet.c/inet.h into + inet and chksum part; changed includes in all lwIP files as appropriate + + 2007-11-16 Simon Goldschmidt + * api.h, api_msg.h, api_lib.c, api_msg.c, socket.h, socket.c: Added sequential + dns resolver function for netconn api (netconn_gethostbyname) and socket api + (gethostbyname/gethostbyname_r). + + 2007-11-15 Jim Pettinato, Frédéric Bernon + * opt.h, init.c, tcpip.c, dhcp.c, dns.h, dns.c: add DNS client for simple name + requests with RAW api interface. Initialization is done in lwip_init() with + build time options. DNS timer is added in tcpip_thread context. DHCP can set + DNS server ip addresses when options are received. You need to set LWIP_DNS=1 + in your lwipopts.h file (LWIP_DNS=0 in opt.h). DNS_DEBUG can be set to get + some traces with LWIP_DEBUGF. Sanity check have been added. There is a "todo" + list with points to improve. + + 2007-11-06 Simon Goldschmidt + * opt.h, mib2.c: Patch #6215: added ifAdminStatus write support (if explicitly + enabled by defining SNMP_SAFE_REQUESTS to 0); added code to check link status + for ifOperStatus if LWIP_NETIF_LINK_CALLBACK is defined. + + 2007-11-06 Simon Goldschmidt + * api.h, api_msg.h and dependent files: Task #7410: Removed the need to include + core header files in api.h (ip/tcp/udp/raw.h) to hide the internal + implementation from netconn api applications. + + 2007-11-03 Frédéric Bernon + * api.h, api_lib.c, api_msg.c, sockets.c, opt.h: add SO_RCVBUF option for UDP & + RAW netconn. You need to set LWIP_SO_RCVBUF=1 in your lwipopts.h (it's disabled + by default). Netconn API users can use the netconn_recv_bufsize macro to access + it. This is a first release which have to be improve for TCP. Note it used the + netconn::recv_avail which need to be more "thread-safe" (note there is already + the problem for FIONREAD with lwip_ioctl/ioctlsocket). + + 2007-11-01 Frédéric Bernon, Marc Chaland + * sockets.h, sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c, tcp.h, tcp_out.c: + Integrate "patch #6250 : MSG_MORE flag for send". MSG_MORE is used at socket api + layer, NETCONN_MORE at netconn api layer, and TCP_WRITE_FLAG_MORE at raw api + layer. This option enable to delayed TCP PUSH flag on multiple "write" calls. + Note that previous "copy" parameter for "write" APIs is now called "apiflags". + + 2007-10-24 Frédéric Bernon + * api.h, api_lib.c, api_msg.c: Add macro API_EVENT in the same spirit than + TCP_EVENT_xxx macros to get a code more readable. It could also help to remove + some code (like we have talk in "patch #5919 : Create compile switch to remove + select code"), but it could be done later. + + 2007-10-08 Simon Goldschmidt + * many files: Changed initialization: many init functions are not needed any + more since we now rely on the compiler initializing global and static + variables to zero! + + 2007-10-06 Simon Goldschmidt + * ip_frag.c, memp.c, mib2.c, ip_frag.h, memp_std.h, opt.h: Changed IP_REASSEMBLY + to enqueue the received pbufs so that multiple packets can be reassembled + simultaneously and no static reassembly buffer is needed. + + 2007-10-05 Simon Goldschmidt + * tcpip.c, etharp.h, etharp.c: moved ethernet_input from tcpip.c to etharp.c so + all netifs (or ports) can use it. + + 2007-10-05 Frédéric Bernon + * netifapi.h, netifapi.c: add function netifapi_netif_set_default. Change the + common function to reduce a little bit the footprint (for all functions using + only the "netif" parameter). + + 2007-10-03 Frédéric Bernon + * netifapi.h, netifapi.c: add functions netifapi_netif_set_up, netifapi_netif_set_down, + netifapi_autoip_start and netifapi_autoip_stop. Use a common function to reduce + a little bit the footprint (for all functions using only the "netif" parameter). + + 2007-09-15 Frédéric Bernon + * udp.h, udp.c, sockets.c: Changes for "#20503 IGMP Improvement". Add IP_MULTICAST_IF + option in socket API, and a new field "multicast_ip" in "struct udp_pcb" (for + netconn and raw API users), only if LWIP_IGMP=1. Add getsockopt processing for + IP_MULTICAST_TTL and IP_MULTICAST_IF. + + 2007-09-10 Frédéric Bernon + * snmp.h, mib2.c: enable to remove SNMP timer (which consumne several cycles + even when it's not necessary). snmp_agent.txt tell to call snmp_inc_sysuptime() + each 10ms (but, it's intrusive if you use sys_timeout feature). Now, you can + decide to call snmp_add_sysuptime(100) each 1000ms (which is bigger "step", but + call to a lower frequency). Or, you can decide to not call snmp_inc_sysuptime() + or snmp_add_sysuptime(), and to define the SNMP_GET_SYSUPTIME(sysuptime) macro. + This one is undefined by default in mib2.c. SNMP_GET_SYSUPTIME is called inside + snmp_get_sysuptime(u32_t *value), and enable to change "sysuptime" value only + when it's queried (any direct call to "sysuptime" is changed by a call to + snmp_get_sysuptime). + + 2007-09-09 Frédéric Bernon, Bill Florac + * igmp.h, igmp.c, netif.h, netif.c, ip.c: To enable to have interfaces with IGMP, + and others without it, there is a new NETIF_FLAG_IGMP flag to set in netif->flags + if you want IGMP on an interface. igmp_stop() is now called inside netif_remove(). + igmp_report_groups() is now called inside netif_set_link_up() (need to have + LWIP_NETIF_LINK_CALLBACK=1) to resend reports once the link is up (avoid to wait + the next query message to receive the matching multicast streams). + + 2007-09-08 Frédéric Bernon + * sockets.c, ip.h, api.h, tcp.h: declare a "struct ip_pcb" which only contains + IP_PCB. Add in the netconn's "pcb" union a "struct ip_pcb *ip;" (no size change). + Use this new field to access to common pcb fields (ttl, tos, so_options, etc...). + Enable to access to these fields with LWIP_TCP=0. + + 2007-09-05 Frédéric Bernon + * udp.c, ipv4/icmp.c, ipv4/ip.c, ipv6/icmp.c, ipv6/ip6.c, ipv4/icmp.h, + ipv6/icmp.h, opt.h: Integrate "task #7272 : LWIP_ICMP option". The new option + LWIP_ICMP enable/disable ICMP module inside the IP stack (enable per default). + Be careful, disabling ICMP make your product non-compliant to RFC1122, but + help to reduce footprint, and to reduce "visibility" on the Internet. + + 2007-09-05 Frédéric Bernon, Bill Florac + * opt.h, sys.h, tcpip.c, slipif.c, ppp.c, sys_arch.txt: Change parameters list + for sys_thread_new (see "task #7252 : Create sys_thread_new_ex()"). Two new + parameters have to be provided: a task name, and a task stack size. For this + one, since it's platform dependant, you could define the best one for you in + your lwipopts.h. For port maintainers, you can just add these new parameters + in your sys_arch.c file, and but it's not mandatory, use them in your OS + specific functions. + + 2007-09-05 Frédéric Bernon + * inet.c, autoip.c, msg_in.c, msg_out.c, init.c: Move some build time checkings + inside init.c for task #7142 "Sanity check user-configurable values". + + 2007-09-04 Frédéric Bernon, Bill Florac + * igmp.h, igmp.c, memp_std.h, memp.c, init.c, opt.h: Replace mem_malloc call by + memp_malloc, and use a new MEMP_NUM_IGMP_GROUP option (see opt.h to define the + value). It will avoid potential fragmentation problems, use a counter to know + how many times a group is used on an netif, and free it when all applications + leave it. MEMP_NUM_IGMP_GROUP got 8 as default value (and init.c got a sanity + check if LWIP_IGMP!=0). + + 2007-09-03 Frédéric Bernon + * igmp.h, igmp.c, sockets.c, api_msg.c: Changes for "#20503 IGMP Improvement". + Initialize igmp_mac_filter to NULL in netif_add (this field should be set in + the netif's "init" function). Use the "imr_interface" field (for socket layer) + and/or the "interface" field (for netconn layer), for join/leave operations. + The igmp_join/leavegroup first parameter change from a netif to an ipaddr. + This field could be a netif's ipaddr, or "any" (same meaning than ip_addr_isany). + + 2007-08-30 Frédéric Bernon + * Add netbuf.h, netbuf.c, Change api.h, api_lib.c: #7249 "Split netbuf functions + from api/api_lib". Now netbuf API is independant of netconn, and can be used + with other API (application based on raw API, or future "socket2" API). Ports + maintainers just have to add src/api/netbuf.c in their makefile/projects. + + 2007-08-30 Frédéric Bernon, Jonathan Larmour + * init.c: Add first version of lwip_sanity_check for task #7142 "Sanity check + user-configurable values". + + 2007-08-29 Frédéric Bernon + * igmp.h, igmp.c, tcpip.c, init.c, netif.c: change igmp_init and add igmp_start. + igmp_start is call inside netif_add. Now, igmp initialization is in the same + spirit than the others modules. Modify some IGMP debug traces. + + 2007-08-29 Frédéric Bernon + * Add init.h, init.c, Change opt.h, tcpip.c: Task #7213 "Add a lwip_init function" + Add lwip_init function to regroup all modules initializations, and to provide + a place to add code for task #7142 "Sanity check user-configurable values". + Ports maintainers should remove direct initializations calls from their code, + and add init.c in their makefiles. Note that lwip_init() function is called + inside tcpip_init, but can also be used by raw api users since all calls are + disabled when matching options are disabled. Also note that their is new options + in opt.h, you should configure in your lwipopts.h (they are enabled per default). + + 2007-08-26 Marc Boucher + * api_msg.c: do_close_internal(): Reset the callbacks and arg (conn) to NULL + since they can under certain circumstances be called with an invalid conn + pointer after the connection has been closed (and conn has been freed). + + 2007-08-25 Frédéric Bernon (Artem Migaev's Patch) + * netif.h, netif.c: Integrate "patch #6163 : Function to check if link layer is up". + Add a netif_is_link_up() function if LWIP_NETIF_LINK_CALLBACK option is set. + + 2007-08-22 Frédéric Bernon + * netif.h, netif.c, opt.h: Rename LWIP_NETIF_CALLBACK in LWIP_NETIF_STATUS_CALLBACK + to be coherent with new LWIP_NETIF_LINK_CALLBACK option before next release. + + 2007-08-22 Frédéric Bernon + * tcpip.h, tcpip.c, ethernetif.c, opt.h: remove options ETHARP_TCPIP_INPUT & + ETHARP_TCPIP_ETHINPUT, now, only "ethinput" code is supported, even if the + name is tcpip_input (we keep the name of 1.2.0 function). + + 2007-08-17 Jared Grubb + * memp_std.h, memp.h, memp.c, mem.c, stats.c: (Task #7136) Centralize mempool + settings into new memp_std.h and optional user file lwippools.h. This adds + more dynamic mempools, and allows the user to create an arbitrary number of + mempools for mem_malloc. + + 2007-08-16 Marc Boucher + * api_msg.c: Initialize newconn->state to NETCONN_NONE in accept_function; + otherwise it was left to NETCONN_CLOSE and sent_tcp() could prematurely + close the connection. + + 2007-08-16 Marc Boucher + * sockets.c: lwip_accept(): check netconn_peer() error return. + + 2007-08-16 Marc Boucher + * mem.c, mem.h: Added mem_calloc(). + + 2007-08-16 Marc Boucher + * tcpip.c, tcpip.h memp.c, memp.h: Added distinct memp (MEMP_TCPIP_MSG_INPKT) + for input packets to prevent floods from consuming all of MEMP_TCPIP_MSG + and starving other message types. + Renamed MEMP_TCPIP_MSG to MEMP_TCPIP_MSG_API + + 2007-08-16 Marc Boucher + * pbuf.c, pbuf.h, etharp.c, tcp_in.c, sockets.c: Split pbuf flags in pbuf + type and flgs (later renamed to flags). + Use enum pbuf_flag as pbuf_type. Renumber PBUF_FLAG_*. + Improved lwip_recvfrom(). TCP push now propagated. + + 2007-08-16 Marc Boucher + * ethernetif.c, contrib/ports/various: ethbroadcast now a shared global + provided by etharp. + + 2007-08-16 Marc Boucher + * ppp_oe.c ppp_oe.h, auth.c chap.c fsm.c lcp.c ppp.c ppp.h, + etharp.c ethernetif.c, etharp.h, opt.h tcpip.h, tcpip.c: + Added PPPoE support and various PPP improvements. + + 2007-07-25 Simon Goldschmidt + * api_lib.c, ip_frag.c, pbuf.c, api.h, pbuf.h: Introduced pbuf_copy_partial, + making netbuf_copy_partial use this function. + + 2007-07-25 Simon Goldschmidt + * tcp_in.c: Fix bug #20506: Slow start / initial congestion window starts with + 2 * mss (instead of 1 * mss previously) to comply with some newer RFCs and + other stacks. + + 2007-07-13 Jared Grubb (integrated by Frédéric Bernon) + * opt.h, netif.h, netif.c, ethernetif.c: Add new configuration option to add + a link callback in the netif struct, and functions to handle it. Be carefull + for port maintainers to add the NETIF_FLAG_LINK_UP flag (like in ethernetif.c) + if you want to be sure to be compatible with future changes... + + 2007-06-30 Frédéric Bernon + * sockets.h, sockets.c: Implement MSG_PEEK flag for recv/recvfrom functions. + + 2007-06-21 Simon Goldschmidt + * etharp.h, etharp.c: Combined etharp_request with etharp_raw for both + LWIP_AUTOIP =0 and =1 to remove redundant code. + + 2007-06-21 Simon Goldschmidt + * mem.c, memp.c, mem.h, memp.h, opt.h: task #6863: Introduced the option + MEM_USE_POOLS to use 4 pools with different sized elements instead of a + heap. This both prevents memory fragmentation and gives a higher speed + at the cost of more memory consumption. Turned off by default. + + 2007-06-21 Simon Goldschmidt + * api_lib.c, api_msg.c, api.h, api_msg.h: Converted the length argument of + netconn_write (and therefore also api_msg_msg.msg.w.len) from u16_t into + int to be able to send a bigger buffer than 64K with one time (mainly + used from lwip_send). + + 2007-06-21 Simon Goldschmidt + * tcp.h, api_msg.c: Moved the nagle algorithm from netconn_write/do_write + into a define (tcp_output_nagle) in tcp.h to provide it to raw api users, too. + + 2007-06-21 Simon Goldschmidt + * api.h, api_lib.c, api_msg.c: Fixed bug #20021: Moved sendbuf-processing in + netconn_write from api_lib.c to api_msg.c to also prevent multiple context- + changes on low memory or empty send-buffer. + + 2007-06-18 Simon Goldschmidt + * etharp.c, etharp.h: Changed etharp to use a defined hardware address length + of 6 to avoid loading netif->hwaddr_len every time (since this file is only + used for ethernet and struct eth_addr already had a defined length of 6). + + 2007-06-17 Simon Goldschmidt + * sockets.c, sockets.h: Implemented socket options SO_NO_CHECK for UDP sockets + to disable UDP checksum generation on transmit. + + 2007-06-13 Frédéric Bernon, Simon Goldschmidt + * debug.h, api_msg.c: change LWIP_ERROR to use it to check errors like invalid + pointers or parameters, and let the possibility to redefined it in cc.h. Use + this macro to check "conn" parameter in api_msg.c functions. + + 2007-06-11 Simon Goldschmidt + * sockets.c, sockets.h: Added UDP lite support for sockets + + 2007-06-10 Simon Goldschmidt + * udp.h, opt.h, api_msg.c, ip.c, udp.c: Included switch LWIP_UDPLITE (enabled + by default) to switch off UDP-Lite support if not needed (reduces udp.c code + size) + + 2007-06-09 Dominik Spies (integrated by Frédéric Bernon) + * autoip.h, autoip.c, dhcp.h, dhcp.c, netif.h, netif.c, etharp.h, etharp.c, opt.h: + AutoIP implementation available for IPv4, with new options LWIP_AUTOIP and + LWIP_DHCP_AUTOIP_COOP if you want to cooperate with DHCP. Some tips to adapt + (see TODO mark in the source code). + + 2007-06-09 Simon Goldschmidt + * etharp.h, etharp.c, ethernetif.c: Modified order of parameters for + etharp_output() to match netif->output so etharp_output() can be used + directly as netif->output to save one function call. + + 2007-06-08 Simon Goldschmidt + * netif.h, ethernetif.c, slipif.c, loopif.c: Added define + NETIF_INIT_SNMP(netif, type, speed) to initialize per-netif snmp variables, + added initialization of those to ethernetif, slipif and loopif. + + 2007-05-18 Simon Goldschmidt + * opt.h, ip_frag.c, ip_frag.h, ip.c: Added option IP_FRAG_USES_STATIC_BUF + (defaulting to off for now) that can be set to 0 to send fragmented + packets by passing PBUF_REFs down the stack. + + 2007-05-23 Frédéric Bernon + * api_lib.c: Implement SO_RCVTIMEO for accept and recv on TCP + connections, such present in patch #5959. + + 2007-05-23 Frédéric Bernon + * api.h, api_lib.c, api_msg.c, sockets.c: group the different NETCONN_UDPxxx + code in only one part... + + 2007-05-18 Simon Goldschmidt + * opt.h, memp.h, memp.c: Added option MEMP_OVERFLOW_CHECK to check for memp + elements to overflow. This is achieved by adding some bytes before and after + each pool element (increasing their size, of course), filling them with a + prominent value and checking them on freeing the element. + Set it to 2 to also check every element in every pool each time memp_malloc() + or memp_free() is called (slower but more helpful). + + 2007-05-10 Simon Goldschmidt + * opt.h, memp.h, memp.c, pbuf.c (see task #6831): use a new memp pool for + PBUF_POOL pbufs instead of the old pool implementation in pbuf.c to reduce + code size. + + 2007-05-11 Frédéric Bernon + * sockets.c, api_lib.c, api_msg.h, api_msg.c, netifapi.h, netifapi.c, tcpip.c: + Include a function pointer instead of a table index in the message to reduce + footprint. Disable some part of lwip_send and lwip_sendto if some options are + not set (LWIP_TCP, LWIP_UDP, LWIP_RAW). + + 2007-05-10 Simon Goldschmidt + * *.h (except netif/ppp/*.h): Included patch #5448: include '#ifdef __cplusplus + \ extern "C" {' in all header files. Now you can write your application using + the lwIP stack in C++ and simply #include the core files. Note I have left + out the netif/ppp/*h header files for now, since I don't know which files are + included by applications and which are for internal use only. + + 2007-05-09 Simon Goldschmidt + * opt.h, *.c/*.h: Included patch #5920: Create define to override C-library + memcpy. 2 Defines are created: MEMCPY() for normal memcpy, SMEMCPY() for + situations where some compilers might inline the copy and save a function + call. Also replaced all calls to memcpy() with calls to (S)MEMCPY(). + + 2007-05-08 Simon Goldschmidt + * mem.h: If MEM_LIBC_MALLOC==1, allow the defines (e.g. mem_malloc() -> malloc()) + to be overriden in case the C-library malloc implementation is not protected + against concurrent access. + + 2007-05-04 Simon Goldschmidt (Atte Kojo) + * etharp.c: Introduced fast one-entry-cache to speed up ARP lookup when sending + multiple packets to the same host. + + 2007-05-04 Frédéric Bernon, Jonathan Larmour + * sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c: Fix bug #19162 "lwip_sento: a possible + to corrupt remote addr/port connection state". Reduce problems "not enought memory" with + netbuf (if we receive lot of datagrams). Improve lwip_sendto (only one exchange between + sockets api and api_msg which run in tcpip_thread context). Add netconn_sento function. + Warning, if you directly access to "fromaddr" & "fromport" field from netbuf struct, + these fields are now renamed "addr" & "port". + + 2007-04-11 Jonathan Larmour + * sys.h, api_lib.c: Provide new sys_mbox_tryfetch function. Require ports to provide new + sys_arch_mbox_tryfetch function to get a message if one is there, otherwise return + with SYS_MBOX_EMPTY. sys_arch_mbox_tryfetch can be implemented as a function-like macro + by the port in sys_arch.h if desired. + + 2007-04-06 Frédéric Bernon, Simon Goldschmidt + * opt.h, tcpip.h, tcpip.c, netifapi.h, netifapi.c: New configuration option LWIP_NETIF_API + allow to use thread-safe functions to add/remove netif in list, and to start/stop dhcp + clients, using new functions from netifapi.h. Disable as default (no port change to do). + + 2007-04-05 Frédéric Bernon + * sockets.c: remplace ENOBUFS errors on alloc_socket by ENFILE to be more BSD compliant. + + 2007-04-04 Simon Goldschmidt + * arch.h, api_msg.c, dhcp.c, msg_in.c, sockets.c: Introduced #define LWIP_UNUSED_ARG(x) + use this for and architecture-independent form to tell the compiler you intentionally + are not using this variable. Can be overriden in cc.h. + + 2007-03-28 Frédéric Bernon + * opt.h, netif.h, dhcp.h, dhcp.c: New configuration option LWIP_NETIF_HOSTNAME allow to + define a hostname in netif struct (this is just a pointer, so, you can use a hardcoded + string, point on one of your's ethernetif field, or alloc a string you will free yourself). + It will be used by DHCP to register a client hostname, but can also be use when you call + snmp_set_sysname. + + 2007-03-28 Frédéric Bernon + * netif.h, netif.c: A new NETIF_FLAG_ETHARP flag is defined in netif.h, to allow to + initialize a network interface's flag with. It tell this interface is an ethernet + device, and we can use ARP with it to do a "gratuitous ARP" (RFC 3220 "IP Mobility + Support for IPv4" section 4.6) when interface is "up" with netif_set_up(). + + 2007-03-26 Frédéric Bernon, Jonathan Larmour + * opt.h, tcpip.c: New configuration option LWIP_ARP allow to disable ARP init at build + time if you only use PPP or SLIP. The default is enable. Note we don't have to call + etharp_init in your port's initilization sequence if you use tcpip.c, because this call + is done in tcpip_init function. + + 2007-03-22 Frédéric Bernon + * stats.h, stats.c, msg_in.c: Stats counters can be change to u32_t if necessary with the + new option LWIP_STATS_LARGE. If you need this option, define LWIP_STATS_LARGE to 1 in + your lwipopts.h. More, unused counters are not defined in the stats structs, and not + display by stats_display(). Note that some options (SYS_STATS and RAW_STATS) are defined + but never used. Fix msg_in.c with the correct #if test for a stat display. + + 2007-03-21 Kieran Mansley + * netif.c, netif.h: Apply patch#4197 with some changes (originator: rireland@hmgsl.com). + Provides callback on netif up/down state change. + + 2007-03-11 Frédéric Bernon, Mace Gael, Steve Reynolds + * sockets.h, sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c, igmp.h, igmp.c, + ip.c, netif.h, tcpip.c, opt.h: + New configuration option LWIP_IGMP to enable IGMP processing. Based on only one + filter per all network interfaces. Declare a new function in netif to enable to + control the MAC filter (to reduce lwIP traffic processing). + + 2007-03-11 Frédéric Bernon + * tcp.h, tcp.c, sockets.c, tcp_out.c, tcp_in.c, opt.h: Keepalive values can + be configured at run time with LWIP_TCP_KEEPALIVE, but don't change this + unless you know what you're doing (default are RFC1122 compliant). Note + that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set in seconds. + + 2007-03-08 Frédéric Bernon + * tcp.h: Keepalive values can be configured at compile time, but don't change + this unless you know what you're doing (default are RFC1122 compliant). + + 2007-03-08 Frédéric Bernon + * sockets.c, api.h, api_lib.c, tcpip.c, sys.h, sys.c, err.c, opt.h: + Implement LWIP_SO_RCVTIMEO configuration option to enable/disable SO_RCVTIMEO + on UDP sockets/netconn. + + 2007-03-08 Simon Goldschmidt + * snmp_msg.h, msg_in.c: SNMP UDP ports can be configured at compile time. + + 2007-03-06 Frédéric Bernon + * api.h, api_lib.c, sockets.h, sockets.c, tcpip.c, sys.h, sys.c, err.h: + Implement SO_RCVTIMEO on UDP sockets/netconn. + + 2007-02-28 Kieran Mansley (based on patch from Simon Goldschmidt) + * api_lib.c, tcpip.c, memp.c, memp.h: make API msg structs allocated + on the stack and remove the API msg type from memp + + 2007-02-26 Jonathan Larmour (based on patch from Simon Goldschmidt) + * sockets.h, sockets.c: Move socket initialization to new + lwip_socket_init() function. + NOTE: this changes the API with ports. Ports will have to be + updated to call lwip_socket_init() now. + + 2007-02-26 Jonathan Larmour (based on patch from Simon Goldschmidt) + * api_lib.c: Use memcpy in netbuf_copy_partial. + + + ++ Bug fixes: + + 2008-03-17 Frédéric Bernon, Ed Kerekes + * igmp.h, igmp.c: Fix bug #22613 "IGMP iphdr problem" (could have + some problems to fill the IP header on some targets, use now the + ip.h macros to do it). + + 2008-03-13 Frédéric Bernon + * sockets.c: Fix bug #22435 "lwip_recvfrom with TCP break;". Using + (lwip_)recvfrom with valid "from" and "fromlen" parameters, on a + TCP connection caused a crash. Note that using (lwip_)recvfrom + like this is a bit slow and that using (lwip)getpeername is the + good lwip way to do it (so, using recv is faster on tcp sockets). + + 2008-03-12 Frédéric Bernon, Jonathan Larmour + * api_msg.c, contrib/apps/ping.c: Fix bug #22530 "api_msg.c's + recv_raw() does not consume data", and the ping sample (with + LWIP_SOCKET=1, the code did the wrong supposition that lwip_recvfrom + returned the IP payload, without the IP header). + + 2008-03-04 Jonathan Larmour + * mem.c, stats.c, mem.h: apply patch #6414 to avoid compiler errors + and/or warnings on some systems where mem_size_t and size_t differ. + * pbuf.c, ppp.c: Fix warnings on some systems with mem_malloc. + + 2008-03-04 Kieran Mansley (contributions by others) + * Numerous small compiler error/warning fixes from contributions to + mailing list after 1.3.0 release candidate made. + + 2008-01-25 Cui hengbin (integrated by Frédéric Bernon) + * dns.c: Fix bug #22108 "DNS problem" caused by unaligned structures. + + 2008-01-15 Kieran Mansley + * tcp_out.c: BUG20511. Modify persist timer to start when we are + prevented from sending by a small send window, not just a zero + send window. + + 2008-01-09 Jonathan Larmour + * opt.h, ip.c: Rename IP_OPTIONS define to IP_OPTIONS_ALLOWED to avoid + conflict with Linux system headers. + + 2008-01-06 Jonathan Larmour + * dhcp.c: fix bug #19927: "DHCP NACK problem" by clearing any existing set IP + address entirely on receiving a DHCPNAK, and restarting discovery. + + 2007-12-21 Simon Goldschmidt + * sys.h, api_lib.c, api_msg.c, sockets.c: fix bug #21698: "netconn->recv_avail + is not protected" by using new macros for interlocked access to modify/test + netconn->recv_avail. + + 2007-12-20 Kieran Mansley (based on patch from Oleg Tyshev) + * tcp_in.c: fix bug# 21535 (nrtx not reset correctly in SYN_SENT state) + + 2007-12-20 Kieran Mansley (based on patch from Per-Henrik Lundbolm) + * tcp.c, tcp_in.c, tcp_out.c, tcp.h: fix bug #20199 (better handling + of silly window avoidance and prevent lwIP from shrinking the window) + + 2007-12-04 Simon Goldschmidt + * tcp.c, tcp_in.c: fix bug #21699 (segment leak in ooseq processing when last + data packet was lost): add assert that all segment lists are empty in + tcp_pcb_remove before setting pcb to CLOSED state; don't directly set CLOSED + state from LAST_ACK in tcp_process + + 2007-12-02 Simon Goldschmidt + * sockets.h: fix bug #21654: exclude definition of struct timeval from #ifndef FD_SET + If including for system-struct timeval, LWIP_TIMEVAL_PRIVATE now + has to be set to 0 in lwipopts.h + + 2007-12-02 Simon Goldschmidt + * api_msg.c, api_lib.c: fix bug #21656 (recvmbox problem in netconn API): always + allocate a recvmbox in netconn_new_with_proto_and_callback. For a tcp-listen + netconn, this recvmbox is later freed and a new mbox is allocated for acceptmbox. + This is a fix for thread-safety and allocates all items needed for a netconn + when the netconn is created. + + 2007-11-30 Simon Goldschmidt + * udp.c: first attempt to fix bug #21655 (DHCP doesn't work reliably with multiple + netifs): if LWIP_DHCP is enabled, UDP packets to DHCP_CLIENT_PORT are passed + to netif->dhcp->pcb only (if that exists) and not to any other pcb for the same + port (only solution to let UDP pcbs 'bind' to a netif instead of an IP address) + + 2007-11-27 Simon Goldschmidt + * ip.c: fixed bug #21643 (udp_send/raw_send don't fail if netif is down) by + letting ip_route only use netifs that are up. + + 2007-11-27 Simon Goldschmidt + * err.h, api_lib.c, api_msg.c, sockets.c: Changed error handling: ERR_MEM, ERR_BUF + and ERR_RTE are seen as non-fatal, all other errors are fatal. netconns and + sockets block most operations once they have seen a fatal error. + + 2007-11-27 Simon Goldschmidt + * udp.h, udp.c, dhcp.c: Implemented new function udp_sendto_if which takes the + netif to send as an argument (to be able to send on netifs that are down). + + 2007-11-26 Simon Goldschmidt + * tcp_in.c: Fixed bug #21582: pcb->acked accounting can be wrong when ACKs + arrive out-of-order + + 2007-11-21 Simon Goldschmidt + * tcp.h, tcp_out.c, api_msg.c: Fixed bug #20287: tcp_output_nagle sends too early + Fixed the nagle algorithm; nagle now also works for all raw API applications + and has to be explicitly disabled with 'tcp_pcb->flags |= TF_NODELAY' + + 2007-11-12 Frédéric Bernon + * sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c: Fixed bug #20900. Now, most + of the netconn_peer and netconn_addr processing is done inside tcpip_thread + context in do_getaddr. + + 2007-11-10 Simon Goldschmidt + * etharp.c: Fixed bug: assert fired when MEMP_ARP_QUEUE was empty (which can + happen any time). Now the packet simply isn't enqueued when out of memory. + + 2007-11-01 Simon Goldschmidt + * tcp.c, tcp_in.c: Fixed bug #21494: The send mss (pcb->mss) is set to 536 (or + TCP_MSS if that is smaller) as long as no MSS option is received from the + remote host. + + 2007-11-01 Simon Goldschmidt + * tcp.h, tcp.c, tcp_in.c: Fixed bug #21491: The MSS option sent (with SYN) + is now based on TCP_MSS instead of pcb->mss (on passive open now effectively + sending our configured TCP_MSS instead of the one received). + + 2007-11-01 Simon Goldschmidt + * tcp_in.c: Fixed bug #21181: On active open, the initial congestion window was + calculated based on the configured TCP_MSS, not on the MSS option received + with SYN+ACK. + + 2007-10-09 Simon Goldschmidt + * udp.c, inet.c, inet.h: Fixed UDPLite: send: Checksum was always generated too + short and also was generated wrong if checksum coverage != tot_len; + receive: checksum was calculated wrong if checksum coverage != tot_len + + 2007-10-08 Simon Goldschmidt + * mem.c: lfree was not updated in mem_realloc! + + 2007-10-07 Frédéric Bernon + * sockets.c, api.h, api_lib.c: First step to fix "bug #20900 : Potential + crash error problem with netconn_peer & netconn_addr". VERY IMPORTANT: + this change cause an API breakage for netconn_addr, since a parameter + type change. Any compiler should cause an error without any changes in + yours netconn_peer calls (so, it can't be a "silent change"). It also + reduce a little bit the footprint for socket layer (lwip_getpeername & + lwip_getsockname use now a common lwip_getaddrname function since + netconn_peer & netconn_addr have the same parameters). + + 2007-09-20 Simon Goldschmidt + * tcp.c: Fixed bug #21080 (tcp_bind without check pcbs in TIME_WAIT state) + by checking tcp_tw_pcbs also + + 2007-09-19 Simon Goldschmidt + * icmp.c: Fixed bug #21107 (didn't reset IP TTL in ICMP echo replies) + + 2007-09-15 Mike Kleshov + * mem.c: Fixed bug #21077 (inaccuracy in calculation of lwip_stat.mem.used) + + 2007-09-06 Frédéric Bernon + * several-files: replace some #include "arch/cc.h" by "lwip/arch.h", or simply remove + it as long as "lwip/opt.h" is included before (this one include "lwip/debug.h" which + already include "lwip/arch.h"). Like that, default defines are provided by "lwip/arch.h" + if they are not defined in cc.h, in the same spirit than "lwip/opt.h" for lwipopts.h. + + 2007-08-30 Frédéric Bernon + * igmp.h, igmp.c: Some changes to remove some redundant code, add some traces, + and fix some coding style. + + 2007-08-28 Frédéric Bernon + * tcpip.c: Fix TCPIP_MSG_INPKT processing: now, tcpip_input can be used for any + kind of packets. These packets are considered like Ethernet packets (payload + pointing to ethhdr) if the netif got the NETIF_FLAG_ETHARP flag. Else, packets + are considered like IP packets (payload pointing to iphdr). + + 2007-08-27 Frédéric Bernon + * api.h, api_lib.c, api_msg.c: First fix for "bug #20900 : Potential crash error + problem with netconn_peer & netconn_addr". Introduce NETCONN_LISTEN netconn_state + and remove obsolete ones (NETCONN_RECV & NETCONN_ACCEPT). + + 2007-08-24 Kieran Mansley + * inet.c Modify (acc >> 16) test to ((acc >> 16) != 0) to help buggy + compiler (Paradigm C++) + + 2007-08-09 Frédéric Bernon, Bill Florac + * stats.h, stats.c, igmp.h, igmp.c, opt.h: Fix for bug #20503 : IGMP Improvement. + Introduce IGMP_STATS to centralize statistics management. + + 2007-08-09 Frédéric Bernon, Bill Florac + * udp.c: Fix for bug #20503 : IGMP Improvement. Enable to receive a multicast + packet on a udp pcb binded on an netif's IP address, and not on "any". + + 2007-08-09 Frédéric Bernon, Bill Florac + * igmp.h, igmp.c, ip.c: Fix minor changes from bug #20503 : IGMP Improvement. + This is mainly on using lookup/lookfor, and some coding styles... + + 2007-07-26 Frédéric Bernon (and "thedoctor") + * igmp.c: Fix bug #20595 to accept IGMPv3 "Query" messages. + + 2007-07-25 Simon Goldschmidt + * api_msg.c, tcp.c: Another fix for bug #20021: by not returning an error if + tcp_output fails in tcp_close, the code in do_close_internal gets simpler + (tcp_output is called again later from tcp timers). + + 2007-07-25 Simon Goldschmidt + * ip_frag.c: Fixed bug #20429: use the new pbuf_copy_partial instead of the old + copy_from_pbuf, which illegally modified the given pbuf. + + 2007-07-25 Simon Goldschmidt + * tcp_out.c: tcp_enqueue: pcb->snd_queuelen didn't work for chaine PBUF_RAMs: + changed snd_queuelen++ to snd_queuelen += pbuf_clen(p). + + 2007-07-24 Simon Goldschmidt + * api_msg.c, tcp.c: Fix bug #20480: Check the pcb passed to tcp_listen() for the + correct state (must be CLOSED). + + 2007-07-13 Thomas Taranowski (commited by Jared Grubb) + * memp.c: Fix bug #20478: memp_malloc returned NULL+MEMP_SIZE on failed + allocation. It now returns NULL. + + 2007-07-13 Frédéric Bernon + * api_msg.c: Fix bug #20318: api_msg "recv" callbacks don't call pbuf_free in + all error cases. + + 2007-07-13 Frédéric Bernon + * api_msg.c: Fix bug #20315: possible memory leak problem if tcp_listen failed, + because current code doesn't follow rawapi.txt documentation. + + 2007-07-13 Kieran Mansley + * src/core/tcp_in.c Apply patch#5741 from Oleg Tyshev to fix bug in + out of sequence processing of received packets + + 2007-07-03 Simon Goldschmidt + * nearly-all-files: Added assertions where PBUF_RAM pbufs are used and an + assumption is made that this pbuf is in one piece (i.e. not chained). These + assumptions clash with the possibility of converting to fully pool-based + pbuf implementations, where PBUF_RAM pbufs might be chained. + + 2007-07-03 Simon Goldschmidt + * api.h, api_lib.c, api_msg.c: Final fix for bug #20021 and some other problems + when closing tcp netconns: removed conn->sem, less context switches when + closing, both netconn_close and netconn_delete should safely close tcp + connections. + + 2007-07-02 Simon Goldschmidt + * ipv4/ip.h, ipv6/ip.h, opt.h, netif.h, etharp.h, ipv4/ip.c, netif.c, raw.c, + tcp_out.c, udp.c, etharp.c: Added option LWIP_NETIF_HWADDRHINT (default=off) + to cache ARP table indices with each pcb instead of single-entry cache for + the complete stack. + + 2007-07-02 Simon Goldschmidt + * tcp.h, tcp.c, tcp_in.c, tcp_out.c: Added some ASSERTS and casts to prevent + warnings when assigning to smaller types. + + 2007-06-28 Simon Goldschmidt + * tcp_out.c: Added check to prevent tcp_pcb->snd_queuelen from overflowing. + + 2007-06-28 Simon Goldschmidt + * tcp.h: Fixed bug #20287: Fixed nagle algorithm (sending was done too early if + a segment contained chained pbufs) + + 2007-06-28 Frédéric Bernon + * autoip.c: replace most of rand() calls by a macro LWIP_AUTOIP_RAND which compute + a "pseudo-random" value based on netif's MAC and some autoip fields. It's always + possible to define this macro in your own lwipopts.h to always use C library's + rand(). Note that autoip_create_rand_addr doesn't use this macro. + + 2007-06-28 Frédéric Bernon + * netifapi.h, netifapi.c, tcpip.h, tcpip.c: Update code to handle the option + LWIP_TCPIP_CORE_LOCKING, and do some changes to be coherent with last modifications + in api_lib/api_msg (use pointers and not type with table, etc...) + + 2007-06-26 Simon Goldschmidt + * udp.h: Fixed bug #20259: struct udp_hdr was lacking the packin defines. + + 2007-06-25 Simon Goldschmidt + * udp.c: Fixed bug #20253: icmp_dest_unreach was called with a wrong p->payload + for udp packets with no matching pcb. + + 2007-06-25 Simon Goldschmidt + * udp.c: Fixed bug #20220: UDP PCB search in udp_input(): a non-local match + could get udp input packets if the remote side matched. + + 2007-06-13 Simon Goldschmidt + * netif.c: Fixed bug #20180 (TCP pcbs listening on IP_ADDR_ANY could get + changed in netif_set_ipaddr if previous netif->ip_addr.addr was 0. + + 2007-06-13 Simon Goldschmidt + * api_msg.c: pcb_new sets conn->err if protocol is not implemented + -> netconn_new_..() does not allocate a new connection for unsupported + protocols. + + 2007-06-13 Frédéric Bernon, Simon Goldschmidt + * api_lib.c: change return expression in netconn_addr and netconn_peer, because + conn->err was reset to ERR_OK without any reasons (and error was lost)... + + 2007-06-13 Frédéric Bernon, Matthias Weisser + * opt.h, mem.h, mem.c, memp.c, pbuf.c, ip_frag.c, vj.c: Fix bug #20162. Rename + MEM_ALIGN in LWIP_MEM_ALIGN and MEM_ALIGN_SIZE in LWIP_MEM_ALIGN_SIZE to avoid + some macro names collision with some OS macros. + + 2007-06-11 Simon Goldschmidt + * udp.c: UDP Lite: corrected the use of chksum_len (based on RFC3828: if it's 0, + create checksum over the complete packet. On RX, if it's < 8 (and not 0), + discard the packet. Also removed the duplicate 'udphdr->chksum = 0' for both + UDP & UDP Lite. + + 2007-06-11 Srinivas Gollakota & Oleg Tyshev + * tcp_out.c: Fix for bug #20075 : "A problem with keep-alive timer and TCP flags" + where TCP flags wasn't initialized in tcp_keepalive. + + 2007-06-03 Simon Goldschmidt + * udp.c: udp_input(): Input pbuf was not freed if pcb had no recv function + registered, p->payload was modified without modifying p->len if sending + icmp_dest_unreach() (had no negative effect but was definitively wrong). + + 2007-06-03 Simon Goldschmidt + * icmp.c: Corrected bug #19937: For responding to an icmp echo request, icmp + re-used the input pbuf even if that didn't have enough space to include the + link headers. Now the space is tested and a new pbuf is allocated for the + echo response packet if the echo request pbuf isn't big enough. + + 2007-06-01 Simon Goldschmidt + * sockets.c: Checked in patch #5914: Moved sockopt processing into tcpip_thread. + + 2007-05-23 Frédéric Bernon + * api_lib.c, sockets.c: Fixed bug #5958 for netconn_listen (acceptmbox only + allocated by do_listen if success) and netconn_accept errors handling. In + most of api_lib functions, we replace some errors checkings like "if (conn==NULL)" + by ASSERT, except for netconn_delete. + + 2007-05-23 Frédéric Bernon + * api_lib.c: Fixed bug #5957 "Safe-thread problem inside netconn_recv" to return + an error code if it's impossible to fetch a pbuf on a TCP connection (and not + directly close the recvmbox). + + 2007-05-22 Simon Goldschmidt + * tcp.c: Fixed bug #1895 (tcp_bind not correct) by introducing a list of + bound but unconnected (and non-listening) tcp_pcbs. + + 2007-05-22 Frédéric Bernon + * sys.h, sys.c, api_lib.c, tcpip.c: remove sys_mbox_fetch_timeout() (was only + used for LWIP_SO_RCVTIMEO option) and use sys_arch_mbox_fetch() instead of + sys_mbox_fetch() in api files. Now, users SHOULD NOT use internal lwIP features + like "sys_timeout" in their application threads. + + 2007-05-22 Frédéric Bernon + * api.h, api_lib.c, api_msg.h, api_msg.c: change the struct api_msg_msg to see + which parameters are used by which do_xxx function, and to avoid "misusing" + parameters (patch #5938). + + 2007-05-22 Simon Goldschmidt + * api_lib.c, api_msg.c, raw.c, api.h, api_msg.h, raw.h: Included patch #5938: + changed raw_pcb.protocol from u16_t to u8_t since for IPv4 and IPv6, proto + is only 8 bits wide. This affects the api, as there, the protocol was + u16_t, too. + + 2007-05-18 Simon Goldschmidt + * memp.c: addition to patch #5913: smaller pointer was returned but + memp_memory was the same size -> did not save memory. + + 2007-05-16 Simon Goldschmidt + * loopif.c, slipif.c: Fix bug #19729: free pbuf if netif->input() returns + != ERR_OK. + + 2007-05-16 Simon Goldschmidt + * api_msg.c, udp.c: If a udp_pcb has a local_ip set, check if it is the same + as the one of the netif used for sending to prevent sending from old + addresses after a netif address gets changed (partly fixes bug #3168). + + 2007-05-16 Frédéric Bernon + * tcpip.c, igmp.h, igmp.c: Fixed bug "#19800 : IGMP: igmp_tick() will not work + with NO_SYS=1". Note that igmp_init is always in tcpip_thread (and not in + tcpip_init) because we have to be sure that network interfaces are already + added (mac filter is updated only in igmp_init for the moment). + + 2007-05-16 Simon Goldschmidt + * mem.c, memp.c: Removed semaphores from memp, changed sys_sem_wait calls + into sys_arch_sem_wait calls to prevent timers from running while waiting + for the heap. This fixes bug #19167. + + 2007-05-13 Simon Goldschmidt + * tcp.h, sockets.h, sockets.c: Fixed bug from patch #5865 by moving the defines + for socket options (lwip_set/-getsockopt) used with level IPPROTO_TCP from + tcp.h to sockets.h. + + 2007-05-07 Simon Goldschmidt + * mem.c: Another attempt to fix bug #17922. + + 2007-05-04 Simon Goldschmidt + * pbuf.c, pbuf.h, etharp.c: Further update to ARP queueing: Changed pbuf_copy() + implementation so that it can be reused (don't allocate the target + pbuf inside pbuf_copy()). + + 2007-05-04 Simon Goldschmidt + * memp.c: checked in patch #5913: in memp_malloc() we can return memp as mem + to save a little RAM (next pointer of memp is not used while not in pool). + + 2007-05-03 "maq" + * sockets.c: Fix ioctl FIONREAD when some data remains from last recv. + (patch #3574). + + 2007-04-23 Simon Goldschmidt + * loopif.c, loopif.h, opt.h, src/netif/FILES: fix bug #2595: "loopif results + in NULL reference for incoming TCP packets". Loopif has to be configured + (using LWIP_LOOPIF_MULTITHREADING) to directly call netif->input() + (multithreading environments, e.g. netif->input() = tcpip_input()) or + putting packets on a list that is fed to the stack by calling loopif_poll() + (single-thread / NO_SYS / polling environment where e.g. + netif->input() = ip_input). + + 2007-04-17 Jonathan Larmour + * pbuf.c: Use s32_t in pbuf_realloc(), as an s16_t can't reliably hold + the difference between two u16_t's. + * sockets.h: FD_SETSIZE needs to match number of sockets, which is + MEMP_NUM_NETCONN in sockets.c right now. + + 2007-04-12 Jonathan Larmour + * icmp.c: Reset IP header TTL in ICMP ECHO responses (bug #19580). + + 2007-04-12 Kieran Mansley + * tcp.c, tcp_in.c, tcp_out.c, tcp.h: Modify way the retransmission + timer is reset to fix bug#19434, with help from Oleg Tyshev. + + 2007-04-11 Simon Goldschmidt + * etharp.c, pbuf.c, pbuf.h: 3rd fix for bug #11400 (arp-queuing): More pbufs than + previously thought need to be copied (everything but PBUF_ROM!). Cleaned up + pbuf.c: removed functions no needed any more (by etharp). + + 2007-04-11 Kieran Mansley + * inet.c, ip_addr.h, sockets.h, sys.h, tcp.h: Apply patch #5745: Fix + "Constant is long" warnings with 16bit compilers. Contributed by + avatar@mmlab.cse.yzu.edu.tw + + 2007-04-05 Frédéric Bernon, Jonathan Larmour + * api_msg.c: Fix bug #16830: "err_tcp() posts to connection mailbox when no pend on + the mailbox is active". Now, the post is only done during a connect, and do_send, + do_write and do_join_leave_group don't do anything if a previous error was signaled. + + 2007-04-03 Frédéric Bernon + * ip.c: Don't set the IP_DF ("Don't fragment") flag in the IP header in IP output + packets. See patch #5834. + + 2007-03-30 Frédéric Bernon + * api_msg.c: add a "pcb_new" helper function to avoid redundant code, and to add + missing pcb allocations checking (in do_bind, and for each raw_new). Fix style. + + 2007-03-30 Frédéric Bernon + * most of files: prefix all debug.h define with "LWIP_" to avoid any conflict with + others environment defines (these were too "generic"). + + 2007-03-28 Frédéric Bernon + * api.h, api_lib.c, sockets.c: netbuf_ref doesn't check its internal pbuf_alloc call + result and can cause a crash. lwip_send now check netbuf_ref result. + + 2007-03-28 Simon Goldschmidt + * sockets.c Remove "#include " from sockets.c to avoid multiple + definition of macros (in errno.h and lwip/arch.h) if LWIP_PROVIDE_ERRNO is + defined. This is the way it should have been already (looking at + doc/sys_arch.txt) + + 2007-03-28 Kieran Mansley + * opt.h Change default PBUF_POOL_BUFSIZE (again) to accomodate default MSS + + IP and TCP headers *and* physical link headers + + 2007-03-26 Frédéric Bernon (based on patch from Dmitry Potapov) + * api_lib.c: patch for netconn_write(), fixes a possible race condition which cause + to send some garbage. It is not a definitive solution, but the patch does solve + the problem for most cases. + + 2007-03-22 Frédéric Bernon + * api_msg.h, api_msg.c: Remove obsolete API_MSG_ACCEPT and do_accept (never used). + + 2007-03-22 Frédéric Bernon + * api_lib.c: somes resources couldn't be freed if there was errors during + netconn_new_with_proto_and_callback. + + 2007-03-22 Frédéric Bernon + * ethernetif.c: update netif->input calls to check return value. In older ports, + it's a good idea to upgrade them, even if before, there could be another problem + (access to an uninitialized mailbox). + + 2007-03-21 Simon Goldschmidt + * sockets.c: fixed bug #5067 (essentialy a signed/unsigned warning fixed + by casting to unsigned). + + 2007-03-21 Frédéric Bernon + * api_lib.c, api_msg.c, tcpip.c: integrate sys_mbox_fetch(conn->mbox, NULL) calls from + api_lib.c to tcpip.c's tcpip_apimsg(). Now, use a local variable and not a + dynamic one from memp to send tcpip_msg to tcpip_thread in a synchrone call. + Free tcpip_msg from tcpip_apimsg is not done in tcpip_thread. This give a + faster and more reliable communication between api_lib and tcpip. + + 2007-03-21 Frédéric Bernon + * opt.h: Add LWIP_NETIF_CALLBACK (to avoid compiler warning) and set it to 0. + + 2007-03-21 Frédéric Bernon + * api_msg.c, igmp.c, igmp.h: Fix C++ style comments + + 2007-03-21 Kieran Mansley + * opt.h Change default PBUF_POOL_BUFSIZE to accomodate default MSS + + IP and TCP headers + + 2007-03-21 Kieran Mansley + * Fix all uses of pbuf_header to check the return value. In some + cases just assert if it fails as I'm not sure how to fix them, but + this is no worse than before when they would carry on regardless + of the failure. + + 2007-03-21 Kieran Mansley + * sockets.c, igmp.c, igmp.h, memp.h: Fix C++ style comments and + comment out missing header include in icmp.c + + 2007-03-20 Frédéric Bernon + * memp.h, stats.c: Fix stats_display function where memp_names table wasn't + synchronized with memp.h. + + 2007-03-20 Frédéric Bernon + * tcpip.c: Initialize tcpip's mbox, and verify if initialized in tcpip_input, + tcpip_ethinput, tcpip_callback, tcpip_apimsg, to fix a init problem with + network interfaces. Also fix a compiler warning. + + 2007-03-20 Kieran Mansley + * udp.c: Only try and use pbuf_header() to make space for headers if + not a ROM or REF pbuf. + + 2007-03-19 Frédéric Bernon + * api_msg.h, api_msg.c, tcpip.h, tcpip.c: Add return types to tcpip_apimsg() + and api_msg_post(). + + 2007-03-19 Frédéric Bernon + * Remove unimplemented "memp_realloc" function from memp.h. + + 2007-03-11 Simon Goldschmidt + * pbuf.c: checked in patch #5796: pbuf_alloc: len field claculation caused + memory corruption. + + 2007-03-11 Simon Goldschmidt (based on patch from Dmitry Potapov) + * api_lib.c, sockets.c, api.h, api_msg.h, sockets.h: Fixed bug #19251 + (missing `const' qualifier in socket functions), to get more compatible to + standard POSIX sockets. + + 2007-03-11 Frédéric Bernon (based on patch from Dmitry Potapov) + * sockets.c: Add asserts inside bind, connect and sendto to check input + parameters. Remove excessive set_errno() calls after get_socket(), because + errno is set inside of get_socket(). Move last sock_set_errno() inside + lwip_close. + + 2007-03-09 Simon Goldschmidt + * memp.c: Fixed bug #11400: New etharp queueing introduced bug: memp_memory + was allocated too small. + + 2007-03-06 Simon Goldschmidt + * tcpip.c: Initialize dhcp timers in tcpip_thread (if LWIP_DHCP) to protect + the stack from concurrent access. + + 2007-03-06 Frédéric Bernon, Dmitry Potapov + * tcpip.c, ip_frag.c, ethernetif.c: Fix some build problems, and a redundancy + call to "lwip_stats.link.recv++;" in low_level_input() & ethernetif_input(). + + 2007-03-06 Simon Goldschmidt + * ip_frag.c, ip_frag.h: Reduce code size: don't include code in those files + if IP_FRAG == 0 and IP_REASSEMBLY == 0 + + 2007-03-06 Frédéric Bernon, Simon Goldschmidt + * opt.h, ip_frag.h, tcpip.h, tcpip.c, ethernetif.c: add new configuration + option named ETHARP_TCPIP_ETHINPUT, which enable the new tcpip_ethinput. + Allow to do ARP processing for incoming packets inside tcpip_thread + (protecting ARP layer against concurrent access). You can also disable + old code using tcp_input with new define ETHARP_TCPIP_INPUT set to 0. + Older ports have to use tcpip_ethinput. + + 2007-03-06 Simon Goldschmidt (based on patch from Dmitry Potapov) + * err.h, err.c: fixed compiler warning "initialization dircards qualifiers + from pointer target type" + + 2007-03-05 Frédéric Bernon + * opt.h, sockets.h: add new configuration options (LWIP_POSIX_SOCKETS_IO_NAMES, + ETHARP_TRUST_IP_MAC, review SO_REUSE) + + 2007-03-04 Frédéric Bernon + * api_msg.c: Remove some compiler warnings : parameter "pcb" was never + referenced. + + 2007-03-04 Frédéric Bernon + * api_lib.c: Fix "[patch #5764] api_lib.c cleanup: after patch #5687" (from + Dmitry Potapov). + The api_msg struct stay on the stack (not moved to netconn struct). + + 2007-03-04 Simon Goldschmidt (based on patch from Dmitry Potapov) + * pbuf.c: Fix BUG#19168 - pbuf_free can cause deadlock (if + SYS_LIGHTWEIGHT_PROT=1 & freeing PBUF_RAM when mem_sem is not available) + Also fixed cast warning in pbuf_alloc() + + 2007-03-04 Simon Goldschmidt + * etharp.c, etharp.h, memp.c, memp.h, opt.h: Fix BUG#11400 - don't corrupt + existing pbuf chain when enqueuing multiple pbufs to a pending ARP request + + 2007-03-03 Frédéric Bernon + * udp.c: remove obsolete line "static struct udp_pcb *pcb_cache = NULL;" + It is static, and never used in udp.c except udp_init(). + + 2007-03-02 Simon Goldschmidt + * tcpip.c: Moved call to ip_init(), udp_init() and tcp_init() from + tcpip_thread() to tcpip_init(). This way, raw API connections can be + initialized before tcpip_thread is running (e.g. before OS is started) + + 2007-03-02 Frédéric Bernon + * rawapi.txt: Fix documentation mismatch with etharp.h about etharp_tmr's call + interval. + + 2007-02-28 Kieran Mansley + * pbuf.c: Fix BUG#17645 - ensure pbuf payload pointer is not moved + outside the region of the pbuf by pbuf_header() + + 2007-02-28 Kieran Mansley + * sockets.c: Fix BUG#19161 - ensure milliseconds timeout is non-zero + when supplied timeout is also non-zero + +(STABLE-1.2.0) + + 2006-12-05 Leon Woestenberg + * CHANGELOG: Mention STABLE-1.2.0 release. + + ++ New features: + + 2006-12-01 Christiaan Simons + * mem.h, opt.h: Added MEM_LIBC_MALLOC option. + Note this is a workaround. Currently I have no other options left. + + 2006-10-26 Christiaan Simons (accepted patch by Jonathan Larmour) + * ipv4/ip_frag.c: rename MAX_MTU to IP_FRAG_MAX_MTU and move define + to include/lwip/opt.h. + * ipv4/lwip/ip_frag.h: Remove unused IP_REASS_INTERVAL. + Move IP_REASS_MAXAGE and IP_REASS_BUFSIZE to include/lwip/opt.h. + * opt.h: Add above new options. + + 2006-08-18 Christiaan Simons + * tcp_{in,out}.c: added SNMP counters. + * ipv4/ip.c: added SNMP counters. + * ipv4/ip_frag.c: added SNMP counters. + + 2006-08-08 Christiaan Simons + * etharp.{c,h}: added etharp_find_addr() to read + (stable) ethernet/IP address pair from ARP table + + 2006-07-14 Christiaan Simons + * mib_structs.c: added + * include/lwip/snmp_structs.h: added + * netif.{c,h}, netif/ethernetif.c: added SNMP statistics to netif struct + + 2006-07-06 Christiaan Simons + * snmp/asn1_{enc,dec}.c added + * snmp/mib2.c added + * snmp/msg_{in,out}.c added + * include/lwip/snmp_asn1.h added + * include/lwip/snmp_msg.h added + * doc/snmp_agent.txt added + + 2006-03-29 Christiaan Simons + * inet.c, inet.h: Added platform byteswap support. + Added LWIP_PLATFORM_BYTESWAP define (defaults to 0) and + optional LWIP_PLATFORM_HTONS(), LWIP_PLATFORM_HTONL() macros. + + ++ Bug fixes: + + 2006-11-30 Christiaan Simons + * dhcp.c: Fixed false triggers of request_timeout. + + 2006-11-28 Christiaan Simons + * netif.c: In netif_add() fixed missing clear of ip_addr, netmask, gw and flags. + + 2006-10-11 Christiaan Simons + * api_lib.c etharp.c, ip.c, memp.c, stats.c, sys.{c,h} tcp.h: + Partially accepted patch #5449 for ANSI C compatibility / build fixes. + * ipv4/lwip/ip.h ipv6/lwip/ip.h: Corrected UDP-Lite protocol + identifier from 170 to 136 (bug #17574). + + 2006-10-10 Christiaan Simons + * api_msg.c: Fixed Nagle algorithm as reported by Bob Grice. + + 2006-08-17 Christiaan Simons + * udp.c: Fixed bug #17200, added check for broadcast + destinations for PCBs bound to a unicast address. + + 2006-08-07 Christiaan Simons + * api_msg.c: Flushing TCP output in do_close() (bug #15926). + + 2006-06-27 Christiaan Simons + * api_msg.c: Applied patch for cold case (bug #11135). + In accept_function() ensure newconn->callback is always initialized. + + 2006-06-15 Christiaan Simons + * mem.h: added MEM_SIZE_F alias to fix an ancient cold case (bug #1748), + facilitate printing of mem_size_t and u16_t statistics. + + 2006-06-14 Christiaan Simons + * api_msg.c: Applied patch #5146 to handle allocation failures + in accept() by Kevin Lawson. + + 2006-05-26 Christiaan Simons + * api_lib.c: Removed conn->sem creation and destruction + from netconn_write() and added sys_sem_new to netconn_new_*. + +(STABLE-1_1_1) + + 2006-03-03 Christiaan Simons + * ipv4/ip_frag.c: Added bound-checking assertions on ip_reassbitmap + access and added pbuf_alloc() return value checks. + + 2006-01-01 Leon Woestenberg + * tcp_{in,out}.c, tcp_out.c: Removed 'even sndbuf' fix in TCP, which is + now handled by the checksum routine properly. + + 2006-02-27 Leon Woestenberg + * pbuf.c: Fix alignment; pbuf_init() would not work unless + pbuf_pool_memory[] was properly aligned. (Patch by Curt McDowell.) + + 2005-12-20 Leon Woestenberg + * tcp.c: Remove PCBs which stay in LAST_ACK state too long. Patch + submitted by Mitrani Hiroshi. + + 2005-12-15 Christiaan Simons + * inet.c: Disabled the added summing routine to preserve code space. + + 2005-12-14 Leon Woestenberg + * tcp_in.c: Duplicate FIN ACK race condition fix by Kelvin Lawson. + Added Curt McDowell's optimized checksumming routine for future + inclusion. Need to create test case for unaliged, aligned, odd, + even length combination of cases on various endianess machines. + + 2005-12-09 Christiaan Simons + * inet.c: Rewrote standard checksum routine in proper portable C. + + 2005-11-25 Christiaan Simons + * udp.c tcp.c: Removed SO_REUSE hack. Should reside in socket code only. + * *.c: introduced cc.h LWIP_DEBUG formatters matching the u16_t, s16_t, + u32_t, s32_t typedefs. This solves most debug word-length assumes. + + 2005-07-17 Leon Woestenberg + * inet.c: Fixed unaligned 16-bit access in the standard checksum + routine by Peter Jolasson. + * slipif.c: Fixed implementation assumption of single-pbuf datagrams. + + 2005-02-04 Leon Woestenberg + * tcp_out.c: Fixed uninitialized 'queue' referenced in memerr branch. + * tcp_{out|in}.c: Applied patch fixing unaligned access. + + 2005-01-04 Leon Woestenberg + * pbuf.c: Fixed missing semicolon after LWIP_DEBUG statement. + + 2005-01-03 Leon Woestenberg + * udp.c: UDP pcb->recv() was called even when it was NULL. + +(STABLE-1_1_0) + + 2004-12-28 Leon Woestenberg + * etharp.*: Disabled multiple packets on the ARP queue. + This clashes with TCP queueing. + + 2004-11-28 Leon Woestenberg + * etharp.*: Fixed race condition from ARP request to ARP timeout. + Halved the ARP period, doubled the period counts. + ETHARP_MAX_PENDING now should be at least 2. This prevents + the counter from reaching 0 right away (which would allow + too little time for ARP responses to be received). + + 2004-11-25 Leon Woestenberg + * dhcp.c: Decline messages were not multicast but unicast. + * etharp.c: ETHARP_CREATE is renamed to ETHARP_TRY_HARD. + Do not try hard to insert arbitrary packet's source address, + etharp_ip_input() now calls etharp_update() without ETHARP_TRY_HARD. + etharp_query() now always DOES call ETHARP_TRY_HARD so that users + querying an address will see it appear in the cache (DHCP could + suffer from this when a server invalidly gave an in-use address.) + * ipv4/ip_addr.h: Renamed ip_addr_maskcmp() to _netcmp() as we are + comparing network addresses (identifiers), not the network masks + themselves. + * ipv4/ip_addr.c: ip_addr_isbroadcast() now checks that the given + IP address actually belongs to the network of the given interface. + + 2004-11-24 Kieran Mansley + * tcp.c: Increment pcb->snd_buf when ACK is received in SYN_SENT state. + +(STABLE-1_1_0-RC1) + + 2004-10-16 Kieran Mansley + * tcp.c: Add code to tcp_recved() to send an ACK (window update) immediately, + even if one is already pending, if the rcv_wnd is above a threshold + (currently TCP_WND/2). This avoids waiting for a timer to expire to send a + delayed ACK in order to open the window if the stack is only receiving data. + + 2004-09-12 Kieran Mansley + * tcp*.*: Retransmit time-out handling improvement by Sam Jansen. + + 2004-08-20 Tony Mountifield + * etharp.c: Make sure the first pbuf queued on an ARP entry + is properly ref counted. + + 2004-07-27 Tony Mountifield + * debug.h: Added (int) cast in LWIP_DEBUGF() to avoid compiler + warnings about comparison. + * pbuf.c: Stopped compiler complaining of empty if statement + when LWIP_DEBUGF() empty. Closed an unclosed comment. + * tcp.c: Stopped compiler complaining of empty if statement + when LWIP_DEBUGF() empty. + * ip.h Corrected IPH_TOS() macro: returns a byte, so doesn't need htons(). + * inet.c: Added a couple of casts to quiet the compiler. + No need to test isascii(c) before isdigit(c) or isxdigit(c). + + 2004-07-22 Tony Mountifield + * inet.c: Made data types consistent in inet_ntoa(). + Added casts for return values of checksum routines, to pacify compiler. + * ip_frag.c, tcp_out.c, sockets.c, pbuf.c + Small corrections to some debugging statements, to pacify compiler. + + 2004-07-21 Tony Mountifield + * etharp.c: Removed spurious semicolon and added missing end-of-comment. + * ethernetif.c Updated low_level_output() to match prototype for + netif->linkoutput and changed low_level_input() similarly for consistency. + * api_msg.c: Changed recv_raw() from int to u8_t, to match prototype + of raw_recv() in raw.h and so avoid compiler error. + * sockets.c: Added trivial (int) cast to keep compiler happier. + * ip.c, netif.c Changed debug statements to use the tidier ip4_addrN() macros. + +(STABLE-1_0_0) + + ++ Changes: + + 2004-07-05 Leon Woestenberg + * sockets.*: Restructured LWIP_PRIVATE_TIMEVAL. Make sure + your cc.h file defines this either 1 or 0. If non-defined, + defaults to 1. + * .c: Added and includes where used. + * etharp.c: Made some array indices unsigned. + + 2004-06-27 Leon Woestenberg + * netif.*: Added netif_set_up()/down(). + * dhcp.c: Changes to restart program flow. + + 2004-05-07 Leon Woestenberg + * etharp.c: In find_entry(), instead of a list traversal per candidate, do a + single-pass lookup for different candidates. Should exploit locality. + + 2004-04-29 Leon Woestenberg + * tcp*.c: Cleaned up source comment documentation for Doxygen processing. + * opt.h: ETHARP_ALWAYS_INSERT option removed to comply with ARP RFC. + * etharp.c: update_arp_entry() only adds new ARP entries when adviced to by + the caller. This deprecates the ETHARP_ALWAYS_INSERT overrule option. + + ++ Bug fixes: + + 2004-04-27 Leon Woestenberg + * etharp.c: Applied patch of bug #8708 by Toni Mountifield with a solution + suggested by Timmy Brolin. Fix for 32-bit processors that cannot access + non-aligned 32-bit words, such as soms 32-bit TCP/IP header fields. Fix + is to prefix the 14-bit Ethernet headers with two padding bytes. + + 2004-04-23 Leon Woestenberg + * ip_addr.c: Fix in the ip_addr_isbroadcast() check. + * etharp.c: Fixed the case where the packet that initiates the ARP request + is not queued, and gets lost. Fixed the case where the packets destination + address is already known; we now always queue the packet and perform an ARP + request. + +(STABLE-0_7_0) + + ++ Bug fixes: + + * Fixed TCP bug for SYN_SENT to ESTABLISHED state transition. + * Fixed TCP bug in dequeueing of FIN from out of order segment queue. + * Fixed two possible NULL references in rare cases. + +(STABLE-0_6_6) + + ++ Bug fixes: + + * Fixed DHCP which did not include the IP address in DECLINE messages. + + ++ Changes: + + * etharp.c has been hauled over a bit. + +(STABLE-0_6_5) + + ++ Bug fixes: + + * Fixed TCP bug induced by bad window resizing with unidirectional TCP traffic. + * Packets sent from ARP queue had invalid source hardware address. + + ++ Changes: + + * Pass-by ARP requests do now update the cache. + + ++ New features: + + * No longer dependent on ctype.h. + * New socket options. + * Raw IP pcb support. + +(STABLE-0_6_4) + + ++ Bug fixes: + + * Some debug formatters and casts fixed. + * Numereous fixes in PPP. + + ++ Changes: + + * DEBUGF now is LWIP_DEBUGF + * pbuf_dechain() has been re-enabled. + * Mentioned the changed use of CVS branches in README. + +(STABLE-0_6_3) + + ++ Bug fixes: + + * Fixed pool pbuf memory leak in pbuf_alloc(). + Occured if not enough PBUF_POOL pbufs for a packet pbuf chain. + Reported by Savin Zlobec. + + * PBUF_POOL chains had their tot_len field not set for non-first + pbufs. Fixed in pbuf_alloc(). + + ++ New features: + + * Added PPP stack contributed by Marc Boucher + + ++ Changes: + + * Now drops short packets for ICMP/UDP/TCP protocols. More robust. + + * ARP queueuing now queues the latest packet instead of the first. + This is the RFC recommended behaviour, but can be overridden in + lwipopts.h. + +(0.6.2) + + ++ Bugfixes: + + * TCP has been fixed to deal with the new use of the pbuf->ref + counter. + + * DHCP dhcp_inform() crash bug fixed. + + ++ Changes: + + * Removed pbuf_pool_free_cache and pbuf_pool_alloc_cache. Also removed + pbuf_refresh(). This has sped up pbuf pool operations considerably. + Implemented by David Haas. + +(0.6.1) + + ++ New features: + + * The packet buffer implementation has been enhanced to support + zero-copy and copy-on-demand for packet buffers which have their + payloads in application-managed memory. + Implemented by David Haas. + + Use PBUF_REF to make a pbuf refer to RAM. lwIP will use zero-copy + if an outgoing packet can be directly sent on the link, or perform + a copy-on-demand when necessary. + + The application can safely assume the packet is sent, and the RAM + is available to the application directly after calling udp_send() + or similar function. + + ++ Bugfixes: + + * ARP_QUEUEING should now correctly work for all cases, including + PBUF_REF. + Implemented by Leon Woestenberg. + + ++ Changes: + + * IP_ADDR_ANY is no longer a NULL pointer. Instead, it is a pointer + to a '0.0.0.0' IP address. + + * The packet buffer implementation is changed. The pbuf->ref counter + meaning has changed, and several pbuf functions have been + adapted accordingly. + + * netif drivers have to be changed to set the hardware address length field + that must be initialized correctly by the driver (hint: 6 for Ethernet MAC). + See the contrib/ports/c16x cs8900 driver as a driver example. + + * netif's have a dhcp field that must be initialized to NULL by the driver. + See the contrib/ports/c16x cs8900 driver as a driver example. + +(0.5.x) This file has been unmaintained up to 0.6.1. All changes are + logged in CVS but have not been explained here. + +(0.5.3) Changes since version 0.5.2 + + ++ Bugfixes: + + * memp_malloc(MEMP_API_MSG) could fail with multiple application + threads because it wasn't protected by semaphores. + + ++ Other changes: + + * struct ip_addr now packed. + + * The name of the time variable in arp.c has been changed to ctime + to avoid conflicts with the time() function. + +(0.5.2) Changes since version 0.5.1 + + ++ New features: + + * A new TCP function, tcp_tmr(), now handles both TCP timers. + + ++ Bugfixes: + + * A bug in tcp_parseopt() could cause the stack to hang because of a + malformed TCP option. + + * The address of new connections in the accept() function in the BSD + socket library was not handled correctly. + + * pbuf_dechain() did not update the ->tot_len field of the tail. + + * Aborted TCP connections were not handled correctly in all + situations. + + ++ Other changes: + + * All protocol header structs are now packed. + + * The ->len field in the tcp_seg structure now counts the actual + amount of data, and does not add one for SYN and FIN segments. + +(0.5.1) Changes since version 0.5.0 + + ++ New features: + + * Possible to run as a user process under Linux. + + * Preliminary support for cross platform packed structs. + + * ARP timer now implemented. + + ++ Bugfixes: + + * TCP output queue length was badly initialized when opening + connections. + + * TCP delayed ACKs were not sent correctly. + + * Explicit initialization of BSS segment variables. + + * read() in BSD socket library could drop data. + + * Problems with memory alignment. + + * Situations when all TCP buffers were used could lead to + starvation. + + * TCP MSS option wasn't parsed correctly. + + * Problems with UDP checksum calculation. + + * IP multicast address tests had endianess problems. + + * ARP requests had wrong destination hardware address. + + ++ Other changes: + + * struct eth_addr changed from u16_t[3] array to u8_t[6]. + + * A ->linkoutput() member was added to struct netif. + + * TCP and UDP ->dest_* struct members where changed to ->remote_*. + + * ntoh* macros are now null definitions for big endian CPUs. + +(0.5.0) Changes since version 0.4.2 + + ++ New features: + + * Redesigned operating system emulation layer to make porting easier. + + * Better control over TCP output buffers. + + * Documenation added. + + ++ Bugfixes: + + * Locking issues in buffer management. + + * Bugfixes in the sequential API. + + * IP forwarding could cause memory leakage. This has been fixed. + + ++ Other changes: + + * Directory structure somewhat changed; the core/ tree has been + collapsed. + +(0.4.2) Changes since version 0.4.1 + + ++ New features: + + * Experimental ARP implementation added. + + * Skeleton Ethernet driver added. + + * Experimental BSD socket API library added. + + ++ Bugfixes: + + * In very intense situations, memory leakage could occur. This has + been fixed. + + ++ Other changes: + + * Variables named "data" and "code" have been renamed in order to + avoid name conflicts in certain compilers. + + * Variable++ have in appliciable cases been translated to ++variable + since some compilers generate better code in the latter case. + +(0.4.1) Changes since version 0.4 + + ++ New features: + + * TCP: Connection attempts time out earlier than data + transmissions. Nagle algorithm implemented. Push flag set on the + last segment in a burst. + + * UDP: experimental support for UDP-Lite extensions. + + ++ Bugfixes: + + * TCP: out of order segments were in some cases handled incorrectly, + and this has now been fixed. Delayed acknowledgements was broken + in 0.4, has now been fixed. Binding to an address that is in use + now results in an error. Reset connections sometimes hung an + application; this has been fixed. + + * Checksum calculation sometimes failed for chained pbufs with odd + lengths. This has been fixed. + + * API: a lot of bug fixes in the API. The UDP API has been improved + and tested. Error reporting and handling has been + improved. Logical flaws and race conditions for incoming TCP + connections has been found and removed. + + * Memory manager: alignment issues. Reallocating memory sometimes + failed, this has been fixed. + + * Generic library: bcopy was flawed and has been fixed. + + ++ Other changes: + + * API: all datatypes has been changed from generic ones such as + ints, to specified ones such as u16_t. Functions that return + errors now have the correct type (err_t). + + * General: A lot of code cleaned up and debugging code removed. Many + portability issues have been fixed. + + * The license was changed; the advertising clause was removed. + + * C64 port added. + + * Thanks: Huge thanks go to Dagan Galarneau, Horst Garnetzke, Petri + Kosunen, Mikael Caleres, and Frits Wilmink for reporting and + fixing bugs! + +(0.4) Changes since version 0.3.1 + + * Memory management has been radically changed; instead of + allocating memory from a shared heap, memory for objects that are + rapidly allocated and deallocated is now kept in pools. Allocation + and deallocation from those memory pools is very fast. The shared + heap is still present but is used less frequently. + + * The memory, memory pool, and packet buffer subsystems now support + 4-, 2-, or 1-byte alignment. + + * "Out of memory" situations are handled in a more robust way. + + * Stack usage has been reduced. + + * Easier configuration of lwIP parameters such as memory usage, + TTLs, statistics gathering, etc. All configuration parameters are + now kept in a single header file "lwipopts.h". + + * The directory structure has been changed slightly so that all + architecture specific files are kept under the src/arch + hierarchy. + + * Error propagation has been improved, both in the protocol modules + and in the API. + + * The code for the RTXC architecture has been implemented, tested + and put to use. + + * Bugs have been found and corrected in the TCP, UDP, IP, API, and + the Internet checksum modules. + + * Bugs related to porting between a 32-bit and a 16-bit architecture + have been found and corrected. + + * The license has been changed slightly to conform more with the + original BSD license, including the advertisement clause. + +(0.3.1) Changes since version 0.3 + + * Fix of a fatal bug in the buffer management. Pbufs with allocated + RAM never returned the RAM when the pbuf was deallocated. + + * TCP congestion control, window updates and retransmissions did not + work correctly. This has now been fixed. + + * Bugfixes in the API. + +(0.3) Changes since version 0.2 + + * New and improved directory structure. All include files are now + kept in a dedicated include/ directory. + + * The API now has proper error handling. A new function, + netconn_err(), now returns an error code for the connection in + case of errors. + + * Improvements in the memory management subsystem. The system now + keeps a pointer to the lowest free memory block. A new function, + mem_malloc2() tries to allocate memory once, and if it fails tries + to free some memory and retry the allocation. + + * Much testing has been done with limited memory + configurations. lwIP now does a better job when overloaded. + + * Some bugfixes and improvements to the buffer (pbuf) subsystem. + + * Many bugfixes in the TCP code: + + - Fixed a bug in tcp_close(). + + - The TCP receive window was incorrectly closed when out of + sequence segments was received. This has been fixed. + + - Connections are now timed-out of the FIN-WAIT-2 state. + + - The initial congestion window could in some cases be too + large. This has been fixed. + + - The retransmission queue could in some cases be screwed up. This + has been fixed. + + - TCP RST flag now handled correctly. + + - Out of sequence data was in some cases never delivered to the + application. This has been fixed. + + - Retransmitted segments now contain the correct acknowledgment + number and advertised window. + + - TCP retransmission timeout backoffs are not correctly computed + (ala BSD). After a number of retransmissions, TCP now gives up + the connection. + + * TCP connections now are kept on three lists, one for active + connections, one for listening connections, and one for + connections that are in TIME-WAIT. This greatly speeds up the fast + timeout processing for sending delayed ACKs. + + * TCP now provides proper feedback to the application when a + connection has been successfully set up. + + * More comments have been added to the code. The code has also been + somewhat cleaned up. + +(0.2) Initial public release. diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/COPYING b/component/common/network/lwip/lwip_v1.5.0.beta/COPYING new file mode 100644 index 0000000..e23898b --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/COPYING @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2001, 2002 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + + diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/FILES b/component/common/network/lwip/lwip_v1.5.0.beta/FILES new file mode 100644 index 0000000..6625319 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/FILES @@ -0,0 +1,4 @@ +src/ - The source code for the lwIP TCP/IP stack. +doc/ - The documentation for lwIP. + +See also the FILES file in each subdirectory. diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/README b/component/common/network/lwip/lwip_v1.5.0.beta/README new file mode 100644 index 0000000..a62cc4f --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/README @@ -0,0 +1,89 @@ +INTRODUCTION + +lwIP is a small independent implementation of the TCP/IP protocol +suite that has been developed by Adam Dunkels at the Computer and +Networks Architectures (CNA) lab at the Swedish Institute of Computer +Science (SICS). + +The focus of the lwIP TCP/IP implementation is to reduce the RAM usage +while still having a full scale TCP. This making lwIP suitable for use +in embedded systems with tens of kilobytes of free RAM and room for +around 40 kilobytes of code ROM. + +FEATURES + + * IP (Internet Protocol) including packet forwarding over multiple network + interfaces + * ICMP (Internet Control Message Protocol) for network maintenance and debugging + * IGMP (Internet Group Management Protocol) for multicast traffic management + * UDP (User Datagram Protocol) including experimental UDP-lite extensions + * TCP (Transmission Control Protocol) with congestion control, RTT estimation + and fast recovery/fast retransmit + * Specialized raw/native API for enhanced performance + * Optional Berkeley-like socket API + * DNS (Domain names resolver) + * SNMP (Simple Network Management Protocol) + * DHCP (Dynamic Host Configuration Protocol) + * AUTOIP (for IPv4, conform with RFC 3927) + * PPP (Point-to-Point Protocol) + * ARP (Address Resolution Protocol) for Ethernet + +LICENSE + +lwIP is freely available under a BSD license. + +DEVELOPMENT + +lwIP has grown into an excellent TCP/IP stack for embedded devices, +and developers using the stack often submit bug fixes, improvements, +and additions to the stack to further increase its usefulness. + +Development of lwIP is hosted on Savannah, a central point for +software development, maintenance and distribution. Everyone can +help improve lwIP by use of Savannah's interface, CVS and the +mailing list. A core team of developers will commit changes to the +CVS source tree. + +The lwIP TCP/IP stack is maintained in the 'lwip' CVS module and +contributions (such as platform ports) are in the 'contrib' module. + +See doc/savannah.txt for details on CVS server access for users and +developers. + +Last night's CVS tar ball can be downloaded from: + http://savannah.gnu.org/cvs.backups/lwip.tar.gz [CHANGED - NEEDS FIXING] + +The current CVS trees are web-browsable: + http://savannah.nongnu.org/cgi-bin/viewcvs/lwip/lwip/ + http://savannah.nongnu.org/cgi-bin/viewcvs/lwip/contrib/ + +Submit patches and bugs via the lwIP project page: + http://savannah.nongnu.org/projects/lwip/ + + +DOCUMENTATION + +The original out-dated homepage of lwIP and Adam Dunkels' papers on +lwIP are at the official lwIP home page: + http://www.sics.se/~adam/lwip/ + +Self documentation of the source code is regularly extracted from the +current CVS sources and is available from this web page: + http://www.nongnu.org/lwip/ + +There is now a constantly growin wiki about lwIP at + http://lwip.wikia.com/wiki/LwIP_Wiki + +Also, there are mailing lists you can subscribe at + http://savannah.nongnu.org/mail/?group=lwip +plus searchable archives: + http://lists.nongnu.org/archive/html/lwip-users/ + http://lists.nongnu.org/archive/html/lwip-devel/ + +Reading Adam's papers, the files in docs/, browsing the source code +documentation and browsing the mailing list archives is a good way to +become familiar with the design of lwIP. + +Adam Dunkels +Leon Woestenberg + diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/UPGRADING b/component/common/network/lwip/lwip_v1.5.0.beta/UPGRADING new file mode 100644 index 0000000..6501107 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/UPGRADING @@ -0,0 +1,144 @@ +This file lists major changes between release versions that require +ports or applications to be changed. Use it to update a port or an +application written for an older version of lwIP to correctly work +with newer versions. + + +(CVS HEAD) + + * [Enter new changes just after this line - do not remove this line] + + ++ Application changes: + + * Replaced struct ip_addr by typedef ip_addr_t (struct ip_addr is kept for + compatibility to old applications, but will be removed in the future). + + * Renamed mem_realloc() to mem_trim() to prevent confusion with realloc() + + +++ Raw API: + * Changed the semantics of tcp_close() (since it was rather a + shutdown before): Now the application does *NOT* get any calls to the recv + callback (aside from NULL/closed) after calling tcp_close() + + * When calling tcp_abort() from a raw API TCP callback function, + make sure you return ERR_ABRT to prevent accessing unallocated memory. + (ERR_ABRT now means the applicaiton has called tcp_abort!) + + +++ Netconn API: + * Changed netconn_receive() and netconn_accept() to return + err_t, not a pointer to new data/netconn. + + +++ Socket API: + * LWIP_SO_RCVTIMEO: when accept() or recv() time out, they + now set errno to EWOULDBLOCK/EAGAIN, not ETIMEDOUT. + + * Added a minimal version of posix fctl() to have a + standardised way to set O_NONBLOCK for nonblocking sockets. + + +++ all APIs: + * correctly implemented SO(F)_REUSEADDR + + ++ Port changes + + +++ new files: + + * Added 4 new files: def.c, timers.c, timers.h, tcp_impl.h: + + * Moved stack-internal parts of tcp.h to tcp_impl.h, tcp.h now only contains + the actual application programmer's API + + * Separated timer implementation from sys.h/.c, moved to timers.h/.c; + Added timer implementation for NO_SYS==1, set NO_SYS_NO_TIMERS==1 if you + still want to use your own timer implementation for NO_SYS==0 (as before). + + +++ sys layer: + + * Converted mbox- and semaphore-functions to take pointers to sys_mbox_t/ + sys_sem_t; + + * Converted sys_mbox_new/sys_sem_new to take pointers and return err_t; + + * Added Mutex concept in sys_arch (define LWIP_COMPAT_MUTEX to let sys.h use + binary semaphores instead of mutexes - as before) + + +++ new options: + + * Don't waste memory when chaining segments, added option TCP_OVERSIZE to + prevent creating many small pbufs when calling tcp_write with many small + blocks of data. Instead, pbufs are allocated larger than needed and the + space is used for later calls to tcp_write. + + * Added LWIP_NETIF_TX_SINGLE_PBUF to always copy to try to create single pbufs + in tcp_write/udp_send. + + * Added an additional option LWIP_ETHERNET to support ethernet without ARP + (necessary for pure PPPoE) + + * Add MEMP_SEPARATE_POOLS to place memory pools in separate arrays. This may + be used to place these pools into user-defined memory by using external + declaration. + + * Added TCP_SNDQUEUELOWAT corresponding to TCP_SNDLOWAT + + +++ new pools: + + * Netdb uses a memp pool for allocating memory when getaddrinfo() is called, + so MEMP_NUM_NETDB has to be set accordingly. + + * DNS_LOCAL_HOSTLIST_IS_DYNAMIC uses a memp pool instead of the heap, so + MEMP_NUM_LOCALHOSTLIST has to be set accordingly. + + * Snmp-agent uses a memp pools instead of the heap, so MEMP_NUM_SNMP_* have + to be set accordingly. + + * PPPoE uses a MEMP pool instead of the heap, so MEMP_NUM_PPPOE_INTERFACES + has to be set accordingly + + * Integrated loopif into netif.c - loopif does not have to be created by the + port any more, just define LWIP_HAVE_LOOPIF to 1. + + * Added define LWIP_RAND() for lwip-wide randomization (needs to be defined + in cc.h, e.g. used by igmp) + + * Added printf-formatter X8_F to printf u8_t as hex + + * The heap now may be moved to user-defined memory by defining + LWIP_RAM_HEAP_POINTER as a void pointer to that memory's address + + * added autoip_set_struct() and dhcp_set_struct() to let autoip and dhcp work + with user-allocated structs instead of calling mem_malloc + + * Added const char* name to mem- and memp-stats for easier debugging. + + * Calculate the TCP/UDP checksum while copying to only fetch data once: + Define LWIP_CHKSUM_COPY to a memcpy-like function that returns the checksum + + * Added SO_REUSE_RXTOALL to pass received UDP broadcast/multicast packets to + more than one pcb. + + * Changed the semantics of ARP_QUEUEING==0: ARP_QUEUEING now cannot be turned + off any more, if this is set to 0, only one packet (the most recent one) is + queued (like demanded by RFC 1122). + + + ++ Major bugfixes/improvements + + * Implemented tcp_shutdown() to only shut down one end of a connection + * Implemented shutdown() at socket- and netconn-level + * Added errorset support to select() + improved select speed overhead + * Merged pppd to v2.3.11 (including some backported bugfixes from 2.4.x) + * Added timer implementation for NO_SYS==1 (may be disabled with NO_SYS_NO_TIMERS==1 + * Use macros defined in ip_addr.h to work with IP addresses + * Implemented many nonblocking socket/netconn functions + * Fixed ARP input processing: only add a new entry if a request was directed as us + * mem_realloc() to mem_trim() to prevent confusion with realloc() + * Some improvements for AutoIP (don't route/forward link-local addresses, don't break + existing connections when assigning a routable address) + * Correctly handle remote side overrunning our rcv_wnd in ooseq case + * Removed packing from ip_addr_t, the packed version is now only used in protocol headers + * Corrected PBUF_POOL_BUFSIZE for ports where ETH_PAD_SIZE > 0 + * Added support for static ARP table entries + +(STABLE-1.3.2) + + * initial version of this file diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/doc/FILES b/component/common/network/lwip/lwip_v1.5.0.beta/doc/FILES new file mode 100644 index 0000000..05d356f --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/doc/FILES @@ -0,0 +1,6 @@ +savannah.txt - How to obtain the current development source code. +contrib.txt - How to contribute to lwIP as a developer. +rawapi.txt - The documentation for the core API of lwIP. + Also provides an overview about the other APIs and multithreading. +snmp_agent.txt - The documentation for the lwIP SNMP agent. +sys_arch.txt - The documentation for a system abstraction layer of lwIP. diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/doc/contrib.txt b/component/common/network/lwip/lwip_v1.5.0.beta/doc/contrib.txt new file mode 100644 index 0000000..b986020 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/doc/contrib.txt @@ -0,0 +1,59 @@ +1 Introduction + +This document describes some guidelines for people participating +in lwIP development. + +2 How to contribute to lwIP + +Here is a short list of suggestions to anybody working with lwIP and +trying to contribute bug reports, fixes, enhancements, platform ports etc. +First of all as you may already know lwIP is a volunteer project so feedback +to fixes or questions might often come late. Hopefully the bug and patch tracking +features of Savannah help us not lose users' input. + +2.1 Source code style: + +1. do not use tabs. +2. indentation is two spaces per level (i.e. per tab). +3. end debug messages with a trailing newline (\n). +4. one space between keyword and opening bracket. +5. no space between function and opening bracket. +6. one space and no newline before opening curly braces of a block. +7. closing curly brace on a single line. +8. spaces surrounding assignment and comparisons. +9. don't initialize static and/or global variables to zero, the compiler takes care of that. +10. use current source code style as further reference. + +2.2 Source code documentation style: + +1. JavaDoc compliant and Doxygen compatible. +2. Function documentation above functions in .c files, not .h files. + (This forces you to synchronize documentation and implementation.) +3. Use current documentation style as further reference. + +2.3 Bug reports and patches: + +1. Make sure you are reporting bugs or send patches against the latest + sources. (From the latest release and/or the current CVS sources.) +2. If you think you found a bug make sure it's not already filed in the + bugtracker at Savannah. +3. If you have a fix put the patch on Savannah. If it is a patch that affects + both core and arch specific stuff please separate them so that the core can + be applied separately while leaving the other patch 'open'. The prefered way + is to NOT touch archs you can't test and let maintainers take care of them. + This is a good way to see if they are used at all - the same goes for unix + netifs except tapif. +4. Do not file a bug and post a fix to it to the patch area. Either a bug report + or a patch will be enough. + If you correct an existing bug then attach the patch to the bug rather than creating a new entry in the patch area. +5. Patches should be specific to a single change or to related changes.Do not mix bugfixes with spelling and other + trivial fixes unless the bugfix is trivial too.Do not reorganize code and rename identifiers in the same patch you + change behaviour if not necessary.A patch is easier to read and understand if it's to the point and short than + if it's not to the point and long :) so the chances for it to be applied are greater. + +2.4 Platform porters: + +1. If you have ported lwIP to a platform (an OS, a uC/processor or a combination of these) and + you think it could benefit others[1] you might want discuss this on the mailing list. You + can also ask for CVS access to submit and maintain your port in the contrib CVS module. + \ No newline at end of file diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/doc/rawapi.txt b/component/common/network/lwip/lwip_v1.5.0.beta/doc/rawapi.txt new file mode 100644 index 0000000..8c19030 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/doc/rawapi.txt @@ -0,0 +1,511 @@ +Raw TCP/IP interface for lwIP + +Authors: Adam Dunkels, Leon Woestenberg, Christiaan Simons + +lwIP provides three Application Program's Interfaces (APIs) for programs +to use for communication with the TCP/IP code: +* low-level "core" / "callback" or "raw" API. +* higher-level "sequential" API. +* BSD-style socket API. + +The sequential API provides a way for ordinary, sequential, programs +to use the lwIP stack. It is quite similar to the BSD socket API. The +model of execution is based on the blocking open-read-write-close +paradigm. Since the TCP/IP stack is event based by nature, the TCP/IP +code and the application program must reside in different execution +contexts (threads). + +The socket API is a compatibility API for existing applications, +currently it is built on top of the sequential API. It is meant to +provide all functions needed to run socket API applications running +on other platforms (e.g. unix / windows etc.). However, due to limitations +in the specification of this API, there might be incompatibilities +that require small modifications of existing programs. + +** Threading + +lwIP started targeting single-threaded environments. When adding multi- +threading support, instead of making the core thread-safe, another +approach was chosen: there is one main thread running the lwIP core +(also known as the "tcpip_thread"). The raw API may only be used from +this thread! Application threads using the sequential- or socket API +communicate with this main thread through message passing. + + As such, the list of functions that may be called from + other threads or an ISR is very limited! Only functions + from these API header files are thread-safe: + - api.h + - netbuf.h + - netdb.h + - netifapi.h + - sockets.h + - sys.h + + Additionaly, memory (de-)allocation functions may be + called from multiple threads (not ISR!) with NO_SYS=0 + since they are protected by SYS_LIGHTWEIGHT_PROT and/or + semaphores. + + Only since 1.3.0, if SYS_LIGHTWEIGHT_PROT is set to 1 + and LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT is set to 1, + pbuf_free() may also be called from another thread or + an ISR (since only then, mem_free - for PBUF_RAM - may + be called from an ISR: otherwise, the HEAP is only + protected by semaphores). + + +** The remainder of this document discusses the "raw" API. ** + +The raw TCP/IP interface allows the application program to integrate +better with the TCP/IP code. Program execution is event based by +having callback functions being called from within the TCP/IP +code. The TCP/IP code and the application program both run in the same +thread. The sequential API has a much higher overhead and is not very +well suited for small systems since it forces a multithreaded paradigm +on the application. + +The raw TCP/IP interface is not only faster in terms of code execution +time but is also less memory intensive. The drawback is that program +development is somewhat harder and application programs written for +the raw TCP/IP interface are more difficult to understand. Still, this +is the preferred way of writing applications that should be small in +code size and memory usage. + +Both APIs can be used simultaneously by different application +programs. In fact, the sequential API is implemented as an application +program using the raw TCP/IP interface. + +--- Callbacks + +Program execution is driven by callbacks. Each callback is an ordinary +C function that is called from within the TCP/IP code. Every callback +function is passed the current TCP or UDP connection state as an +argument. Also, in order to be able to keep program specific state, +the callback functions are called with a program specified argument +that is independent of the TCP/IP state. + +The function for setting the application connection state is: + +- void tcp_arg(struct tcp_pcb *pcb, void *arg) + + Specifies the program specific state that should be passed to all + other callback functions. The "pcb" argument is the current TCP + connection control block, and the "arg" argument is the argument + that will be passed to the callbacks. + + +--- TCP connection setup + +The functions used for setting up connections is similar to that of +the sequential API and of the BSD socket API. A new TCP connection +identifier (i.e., a protocol control block - PCB) is created with the +tcp_new() function. This PCB can then be either set to listen for new +incoming connections or be explicitly connected to another host. + +- struct tcp_pcb *tcp_new(void) + + Creates a new connection identifier (PCB). If memory is not + available for creating the new pcb, NULL is returned. + +- err_t tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr, + u16_t port) + + Binds the pcb to a local IP address and port number. The IP address + can be specified as IP_ADDR_ANY in order to bind the connection to + all local IP addresses. + + If another connection is bound to the same port, the function will + return ERR_USE, otherwise ERR_OK is returned. + +- struct tcp_pcb *tcp_listen(struct tcp_pcb *pcb) + + Commands a pcb to start listening for incoming connections. When an + incoming connection is accepted, the function specified with the + tcp_accept() function will be called. The pcb will have to be bound + to a local port with the tcp_bind() function. + + The tcp_listen() function returns a new connection identifier, and + the one passed as an argument to the function will be + deallocated. The reason for this behavior is that less memory is + needed for a connection that is listening, so tcp_listen() will + reclaim the memory needed for the original connection and allocate a + new smaller memory block for the listening connection. + + tcp_listen() may return NULL if no memory was available for the + listening connection. If so, the memory associated with the pcb + passed as an argument to tcp_listen() will not be deallocated. + +- struct tcp_pcb *tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog) + + Same as tcp_listen, but limits the number of outstanding connections + in the listen queue to the value specified by the backlog argument. + To use it, your need to set TCP_LISTEN_BACKLOG=1 in your lwipopts.h. + +- void tcp_accepted(struct tcp_pcb *pcb) + + Inform lwIP that an incoming connection has been accepted. This would + usually be called from the accept callback. This allows lwIP to perform + housekeeping tasks, such as allowing further incoming connections to be + queued in the listen backlog. + ATTENTION: the PCB passed in must be the listening pcb, not the pcb passed + into the accept callback! + +- void tcp_accept(struct tcp_pcb *pcb, + err_t (* accept)(void *arg, struct tcp_pcb *newpcb, + err_t err)) + + Specified the callback function that should be called when a new + connection arrives on a listening connection. + +- err_t tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, + u16_t port, err_t (* connected)(void *arg, + struct tcp_pcb *tpcb, + err_t err)); + + Sets up the pcb to connect to the remote host and sends the + initial SYN segment which opens the connection. + + The tcp_connect() function returns immediately; it does not wait for + the connection to be properly setup. Instead, it will call the + function specified as the fourth argument (the "connected" argument) + when the connection is established. If the connection could not be + properly established, either because the other host refused the + connection or because the other host didn't answer, the "err" + callback function of this pcb (registered with tcp_err, see below) + will be called. + + The tcp_connect() function can return ERR_MEM if no memory is + available for enqueueing the SYN segment. If the SYN indeed was + enqueued successfully, the tcp_connect() function returns ERR_OK. + + +--- Sending TCP data + +TCP data is sent by enqueueing the data with a call to +tcp_write(). When the data is successfully transmitted to the remote +host, the application will be notified with a call to a specified +callback function. + +- err_t tcp_write(struct tcp_pcb *pcb, const void *dataptr, u16_t len, + u8_t apiflags) + + Enqueues the data pointed to by the argument dataptr. The length of + the data is passed as the len parameter. The apiflags can be one or more of: + - TCP_WRITE_FLAG_COPY: indicates whether the new memory should be allocated + for the data to be copied into. If this flag is not given, no new memory + should be allocated and the data should only be referenced by pointer. This + also means that the memory behind dataptr must not change until the data is + ACKed by the remote host + - TCP_WRITE_FLAG_MORE: indicates that more data follows. If this is given, + the PSH flag is set in the last segment created by this call to tcp_write. + If this flag is given, the PSH flag is not set. + + The tcp_write() function will fail and return ERR_MEM if the length + of the data exceeds the current send buffer size or if the length of + the queue of outgoing segment is larger than the upper limit defined + in lwipopts.h. The number of bytes available in the output queue can + be retrieved with the tcp_sndbuf() function. + + The proper way to use this function is to call the function with at + most tcp_sndbuf() bytes of data. If the function returns ERR_MEM, + the application should wait until some of the currently enqueued + data has been successfully received by the other host and try again. + +- void tcp_sent(struct tcp_pcb *pcb, + err_t (* sent)(void *arg, struct tcp_pcb *tpcb, + u16_t len)) + + Specifies the callback function that should be called when data has + successfully been received (i.e., acknowledged) by the remote + host. The len argument passed to the callback function gives the + amount bytes that was acknowledged by the last acknowledgment. + + +--- Receiving TCP data + +TCP data reception is callback based - an application specified +callback function is called when new data arrives. When the +application has taken the data, it has to call the tcp_recved() +function to indicate that TCP can advertise increase the receive +window. + +- void tcp_recv(struct tcp_pcb *pcb, + err_t (* recv)(void *arg, struct tcp_pcb *tpcb, + struct pbuf *p, err_t err)) + + Sets the callback function that will be called when new data + arrives. The callback function will be passed a NULL pbuf to + indicate that the remote host has closed the connection. If + there are no errors and the callback function is to return + ERR_OK, then it must free the pbuf. Otherwise, it must not + free the pbuf so that lwIP core code can store it. + +- void tcp_recved(struct tcp_pcb *pcb, u16_t len) + + Must be called when the application has received the data. The len + argument indicates the length of the received data. + + +--- Application polling + +When a connection is idle (i.e., no data is either transmitted or +received), lwIP will repeatedly poll the application by calling a +specified callback function. This can be used either as a watchdog +timer for killing connections that have stayed idle for too long, or +as a method of waiting for memory to become available. For instance, +if a call to tcp_write() has failed because memory wasn't available, +the application may use the polling functionality to call tcp_write() +again when the connection has been idle for a while. + +- void tcp_poll(struct tcp_pcb *pcb, + err_t (* poll)(void *arg, struct tcp_pcb *tpcb), + u8_t interval) + + Specifies the polling interval and the callback function that should + be called to poll the application. The interval is specified in + number of TCP coarse grained timer shots, which typically occurs + twice a second. An interval of 10 means that the application would + be polled every 5 seconds. + + +--- Closing and aborting connections + +- err_t tcp_close(struct tcp_pcb *pcb) + + Closes the connection. The function may return ERR_MEM if no memory + was available for closing the connection. If so, the application + should wait and try again either by using the acknowledgment + callback or the polling functionality. If the close succeeds, the + function returns ERR_OK. + + The pcb is deallocated by the TCP code after a call to tcp_close(). + +- void tcp_abort(struct tcp_pcb *pcb) + + Aborts the connection by sending a RST (reset) segment to the remote + host. The pcb is deallocated. This function never fails. + + ATTENTION: When calling this from one of the TCP callbacks, make + sure you always return ERR_ABRT (and never return ERR_ABRT otherwise + or you will risk accessing deallocated memory or memory leaks! + + +If a connection is aborted because of an error, the application is +alerted of this event by the err callback. Errors that might abort a +connection are when there is a shortage of memory. The callback +function to be called is set using the tcp_err() function. + +- void tcp_err(struct tcp_pcb *pcb, void (* err)(void *arg, + err_t err)) + + The error callback function does not get the pcb passed to it as a + parameter since the pcb may already have been deallocated. + + +--- Lower layer TCP interface + +TCP provides a simple interface to the lower layers of the +system. During system initialization, the function tcp_init() has +to be called before any other TCP function is called. When the system +is running, the two timer functions tcp_fasttmr() and tcp_slowtmr() +must be called with regular intervals. The tcp_fasttmr() should be +called every TCP_FAST_INTERVAL milliseconds (defined in tcp.h) and +tcp_slowtmr() should be called every TCP_SLOW_INTERVAL milliseconds. + + +--- UDP interface + +The UDP interface is similar to that of TCP, but due to the lower +level of complexity of UDP, the interface is significantly simpler. + +- struct udp_pcb *udp_new(void) + + Creates a new UDP pcb which can be used for UDP communication. The + pcb is not active until it has either been bound to a local address + or connected to a remote address. + +- void udp_remove(struct udp_pcb *pcb) + + Removes and deallocates the pcb. + +- err_t udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, + u16_t port) + + Binds the pcb to a local address. The IP-address argument "ipaddr" + can be IP_ADDR_ANY to indicate that it should listen to any local IP + address. The function currently always return ERR_OK. + +- err_t udp_connect(struct udp_pcb *pcb, ip_addr_t *ipaddr, + u16_t port) + + Sets the remote end of the pcb. This function does not generate any + network traffic, but only set the remote address of the pcb. + +- err_t udp_disconnect(struct udp_pcb *pcb) + + Remove the remote end of the pcb. This function does not generate + any network traffic, but only removes the remote address of the pcb. + +- err_t udp_send(struct udp_pcb *pcb, struct pbuf *p) + + Sends the pbuf p. The pbuf is not deallocated. + +- void udp_recv(struct udp_pcb *pcb, + void (* recv)(void *arg, struct udp_pcb *upcb, + struct pbuf *p, + ip_addr_t *addr, + u16_t port), + void *recv_arg) + + Specifies a callback function that should be called when a UDP + datagram is received. + + +--- System initalization + +A truly complete and generic sequence for initializing the lwip stack +cannot be given because it depends on the build configuration (lwipopts.h) +and additional initializations for your runtime environment (e.g. timers). + +We can give you some idea on how to proceed when using the raw API. +We assume a configuration using a single Ethernet netif and the +UDP and TCP transport layers, IPv4 and the DHCP client. + +Call these functions in the order of appearance: + +- stats_init() + + Clears the structure where runtime statistics are gathered. + +- sys_init() + + Not of much use since we set the NO_SYS 1 option in lwipopts.h, + to be called for easy configuration changes. + +- mem_init() + + Initializes the dynamic memory heap defined by MEM_SIZE. + +- memp_init() + + Initializes the memory pools defined by MEMP_NUM_x. + +- pbuf_init() + + Initializes the pbuf memory pool defined by PBUF_POOL_SIZE. + +- etharp_init() + + Initializes the ARP table and queue. + Note: you must call etharp_tmr at a ARP_TMR_INTERVAL (5 seconds) regular interval + after this initialization. + +- ip_init() + + Doesn't do much, it should be called to handle future changes. + +- udp_init() + + Clears the UDP PCB list. + +- tcp_init() + + Clears the TCP PCB list and clears some internal TCP timers. + Note: you must call tcp_fasttmr() and tcp_slowtmr() at the + predefined regular intervals after this initialization. + +- netif_add(struct netif *netif, ip_addr_t *ipaddr, + ip_addr_t *netmask, ip_addr_t *gw, + void *state, err_t (* init)(struct netif *netif), + err_t (* input)(struct pbuf *p, struct netif *netif)) + + Adds your network interface to the netif_list. Allocate a struct + netif and pass a pointer to this structure as the first argument. + Give pointers to cleared ip_addr structures when using DHCP, + or fill them with sane numbers otherwise. The state pointer may be NULL. + + The init function pointer must point to a initialization function for + your ethernet netif interface. The following code illustrates it's use. + + err_t netif_if_init(struct netif *netif) + { + u8_t i; + + for(i = 0; i < ETHARP_HWADDR_LEN; i++) netif->hwaddr[i] = some_eth_addr[i]; + init_my_eth_device(); + return ERR_OK; + } + + For ethernet drivers, the input function pointer must point to the lwip + function ethernet_input() declared in "netif/etharp.h". Other drivers + must use ip_input() declared in "lwip/ip.h". + +- netif_set_default(struct netif *netif) + + Registers the default network interface. + +- netif_set_up(struct netif *netif) + + When the netif is fully configured this function must be called. + +- dhcp_start(struct netif *netif) + + Creates a new DHCP client for this interface on the first call. + Note: you must call dhcp_fine_tmr() and dhcp_coarse_tmr() at + the predefined regular intervals after starting the client. + + You can peek in the netif->dhcp struct for the actual DHCP status. + + +--- Optimalization hints + +The first thing you want to optimize is the lwip_standard_checksum() +routine from src/core/inet.c. You can override this standard +function with the #define LWIP_CHKSUM . + +There are C examples given in inet.c or you might want to +craft an assembly function for this. RFC1071 is a good +introduction to this subject. + +Other significant improvements can be made by supplying +assembly or inline replacements for htons() and htonl() +if you're using a little-endian architecture. +#define LWIP_PLATFORM_BYTESWAP 1 +#define LWIP_PLATFORM_HTONS(x) +#define LWIP_PLATFORM_HTONL(x) + +Check your network interface driver if it reads at +a higher speed than the maximum wire-speed. If the +hardware isn't serviced frequently and fast enough +buffer overflows are likely to occur. + +E.g. when using the cs8900 driver, call cs8900if_service(ethif) +as frequently as possible. When using an RTOS let the cs8900 interrupt +wake a high priority task that services your driver using a binary +semaphore or event flag. Some drivers might allow additional tuning +to match your application and network. + +For a production release it is recommended to set LWIP_STATS to 0. +Note that speed performance isn't influenced much by simply setting +high values to the memory options. + +For more optimization hints take a look at the lwIP wiki. + +--- Zero-copy MACs + +To achieve zero-copy on transmit, the data passed to the raw API must +remain unchanged until sent. Because the send- (or write-)functions return +when the packets have been enqueued for sending, data must be kept stable +after that, too. + +This implies that PBUF_RAM/PBUF_POOL pbufs passed to raw-API send functions +must *not* be reused by the application unless their ref-count is 1. + +For no-copy pbufs (PBUF_ROM/PBUF_REF), data must be kept unchanged, too, +but the stack/driver will/must copy PBUF_REF'ed data when enqueueing, while +PBUF_ROM-pbufs are just enqueued (as ROM-data is expected to never change). + +Also, data passed to tcp_write without the copy-flag must not be changed! + +Therefore, be careful which type of PBUF you use and if you copy TCP data +or not! diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/doc/savannah.txt b/component/common/network/lwip/lwip_v1.5.0.beta/doc/savannah.txt new file mode 100644 index 0000000..409905b --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/doc/savannah.txt @@ -0,0 +1,135 @@ +Daily Use Guide for using Savannah for lwIP + +Table of Contents: + +1 - Obtaining lwIP from the CVS repository +2 - Committers/developers CVS access using SSH (to be written) +3 - Merging from DEVEL branch to main trunk (stable branch) +4 - How to release lwIP + + + +1 Obtaining lwIP from the CVS repository +---------------------------------------- + +To perform an anonymous CVS checkout of the main trunk (this is where +bug fixes and incremental enhancements occur), do this: + +cvs -z3 -d:pserver:anonymous@cvs.sv.gnu.org:/sources/lwip checkout lwip + +Or, obtain a stable branch (updated with bug fixes only) as follows: +cvs -z3 -d:pserver:anonymous@cvs.sv.gnu.org:/sources/lwip checkout \ + -r STABLE-0_7 -d lwip-0.7 lwip + +Or, obtain a specific (fixed) release as follows: +cvs -z3 -d:pserver:anonymous@cvs.sv.gnu.org:/sources/lwip checkout \ + -r STABLE-0_7_0 -d lwip-0.7.0 lwip + +3 Committers/developers CVS access using SSH +-------------------------------------------- + +The Savannah server uses SSH (Secure Shell) protocol 2 authentication and encryption. +As such, CVS commits to the server occur through a SSH tunnel for project members. +To create a SSH2 key pair in UNIX-like environments, do this: + +ssh-keygen -t dsa + +Under Windows, a recommended SSH client is "PuTTY", freely available with good +documentation and a graphic user interface. Use its key generator. + +Now paste the id_dsa.pub contents into your Savannah account public key list. Wait +a while so that Savannah can update its configuration (This can take minutes). + +Try to login using SSH: + +ssh -v your_login@cvs.sv.gnu.org + +If it tells you: + +Authenticating with public key "your_key_name"... +Server refused to allocate pty + +then you could login; Savannah refuses to give you a shell - which is OK, as we +are allowed to use SSH for CVS only. Now, you should be able to do this: + +export CVS_RSH=ssh +cvs -z3 -d:ext:your_login@cvs.sv.gnu.org:/sources/lwip co lwip + +after which you can edit your local files with bug fixes or new features and +commit them. Make sure you know what you are doing when using CVS to make +changes on the repository. If in doubt, ask on the lwip-members mailing list. + +(If SSH asks about authenticity of the host, you can check the key + fingerprint against http://savannah.nongnu.org/cvs/?group=lwip) + + +3 Merging from DEVEL branch to main trunk (stable) +-------------------------------------------------- + +Merging is a delicate process in CVS and requires the +following disciplined steps in order to prevent conflicts +in the future. Conflicts can be hard to solve! + +Merging from branch A to branch B requires that the A branch +has a tag indicating the previous merger. This tag is called +'merged_from_A_to_B'. After merging, the tag is moved in the +A branch to remember this merger for future merge actions. + +IMPORTANT: AFTER COMMITTING A SUCCESFUL MERGE IN THE +REPOSITORY, THE TAG MUST BE SET ON THE SOURCE BRANCH OF THE +MERGE ACTION (REPLACING EXISTING TAGS WITH THE SAME NAME). + +Merge all changes in DEVEL since our last merge to main: + +In the working copy of the main trunk: +cvs update -P -jmerged_from_DEVEL_to_main -jDEVEL + +(This will apply the changes between 'merged_from_DEVEL_to_main' +and 'DEVEL' to your work set of files) + +We can now commit the merge result. +cvs commit -R -m "Merged from DEVEL to main." + +If this worked out OK, we now move the tag in the DEVEL branch +to this merge point, so we can use this point for future merges: + +cvs rtag -F -r DEVEL merged_from_DEVEL_to_main lwip + +4 How to release lwIP +--------------------- + +First, checkout a clean copy of the branch to be released. Tag this set with +tag name "STABLE-0_6_3". (I use release number 0.6.3 throughout this example). + +Login CVS using pserver authentication, then export a clean copy of the +tagged tree. Export is similar to a checkout, except that the CVS metadata +is not created locally. + +export CVS_RSH=ssh +cvs -z3 -d:pserver:anonymous@cvs.sv.gnu.org:/sources/lwip checkout \ + -r STABLE-0_6_3 -d lwip-0.6.3 lwip + +Archive this directory using tar, gzip'd, bzip2'd and zip'd. + +tar czvf lwip-0.6.3.tar.gz lwip-0.6.3 +tar cjvf lwip-0.6.3.tar.bz2 lwip-0.6.3 +zip -r lwip-0.6.3.zip lwip-0.6.3 + +Now, sign the archives with a detached GPG binary signature as follows: + +gpg -b lwip-0.6.3.tar.gz +gpg -b lwip-0.6.3.tar.bz2 +gpg -b lwip-0.6.3.zip + +Upload these files using anonymous FTP: +ncftp ftp://savannah.gnu.org/incoming/savannah/lwip + +ncftp>mput *0.6.3.* + +Additionally, you may post a news item on Savannah, like this: + +A new 0.6.3 release is now available here: +http://savannah.nongnu.org/files/?group=lwip&highlight=0.6.3 + +You will have to submit this via the user News interface, then approve +this via the Administrator News interface. \ No newline at end of file diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/doc/snmp_agent.txt b/component/common/network/lwip/lwip_v1.5.0.beta/doc/snmp_agent.txt new file mode 100644 index 0000000..2653230 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/doc/snmp_agent.txt @@ -0,0 +1,181 @@ +SNMPv1 agent for lwIP + +Author: Christiaan Simons + +This is a brief introduction how to use and configure the SNMP agent. +Note the agent uses the raw-API UDP interface so you may also want to +read rawapi.txt to gain a better understanding of the SNMP message handling. + +0 Agent Capabilities +==================== + +SNMPv1 per RFC1157 + This is an old(er) standard but is still widely supported. + For SNMPv2c and v3 have a greater complexity and need many + more lines of code. IMHO this breaks the idea of "lightweight IP". + + Note the S in SNMP stands for "Simple". Note that "Simple" is + relative. SNMP is simple compared to the complex ISO network + management protocols CMIP (Common Management Information Protocol) + and CMOT (CMip Over Tcp). + +MIB II per RFC1213 + The standard lwIP stack management information base. + This is a required MIB, so this is always enabled. + When builing lwIP without TCP, the mib-2.tcp group is omitted. + The groups EGP, CMOT and transmission are disabled by default. + + Most mib-2 objects are not writable except: + sysName, sysLocation, sysContact, snmpEnableAuthenTraps. + Writing to or changing the ARP and IP address and route + tables is not possible. + + Note lwIP has a very limited notion of IP routing. It currently + doen't have a route table and doesn't have a notion of the U,G,H flags. + Instead lwIP uses the interface list with only one default interface + acting as a single gateway interface (G) for the default route. + + The agent returns a "virtual table" with the default route 0.0.0.0 + for the default interface and network routes (no H) for each + network interface in the netif_list. + All routes are considered to be up (U). + +Loading additional MIBs + MIBs can only be added in compile-time, not in run-time. + There is no MIB compiler thus additional MIBs must be hand coded. + +Large SNMP message support + The packet decoding and encoding routines are designed + to use pbuf-chains. Larger payloads than the minimum + SNMP requirement of 484 octets are supported if the + PBUF_POOL_SIZE and IP_REASS_BUFSIZE are set to match your + local requirement. + +1 Building the Agent +==================== + +First of all you'll need to add the following define +to your local lwipopts.h: + +#define LWIP_SNMP 1 + +and add the source files in lwip/src/core/snmp +and some snmp headers in lwip/src/include/lwip to your makefile. + +Note you'll might need to adapt you network driver to update +the mib2 variables for your interface. + +2 Running the Agent +=================== + +The following function calls must be made in your program to +actually get the SNMP agent running. + +Before starting the agent you should supply pointers +to non-volatile memory for sysContact, sysLocation, +and snmpEnableAuthenTraps. You can do this by calling + +snmp_set_syscontact() +snmp_set_syslocation() +snmp_set_snmpenableauthentraps() + +Additionally you may want to set + +snmp_set_sysdescr() +snmp_set_sysobjid() (if you have a private MIB) +snmp_set_sysname() + +Also before starting the agent you need to setup +one or more trap destinations using these calls: + +snmp_trap_dst_enable(); +snmp_trap_dst_ip_set(); + +In the lwIP initialisation sequence call snmp_init() just after +the call to udp_init(). + +Exactly every 10 msec the SNMP uptime timestamp must be updated with +snmp_inc_sysuptime(). You should call this from a timer interrupt +or a timer signal handler depending on your runtime environment. + +An alternative way to update the SNMP uptime timestamp is to do a call like +snmp_add_sysuptime(100) each 1000ms (which is bigger "step", but call to +a lower frequency). Another one is to not call snmp_inc_sysuptime() or +snmp_add_sysuptime(), and to define the SNMP_GET_SYSUPTIME(sysuptime) macro. +This one is undefined by default in mib2.c. SNMP_GET_SYSUPTIME is called inside +snmp_get_sysuptime(u32_t *value), and enable to change "sysuptime" value only +when it's queried (any function which need "sysuptime" have to call +snmp_get_sysuptime). + + +3 Private MIBs +============== + +If want to extend the agent with your own private MIB you'll need to +add the following define to your local lwipopts.h: + +#define SNMP_PRIVATE_MIB 1 + +You must provide the private_mib.h and associated files yourself. +Note we don't have a "MIB compiler" that generates C source from a MIB, +so you're required to do some serious coding if you enable this! + +Note the lwIP enterprise ID (26381) is assigned to the lwIP project, +ALL OBJECT IDENTIFIERS LIVING UNDER THIS ID ARE ASSIGNED BY THE lwIP +MAINTAINERS! + +If you need to create your own private MIB you'll need +to apply for your own enterprise ID with IANA: http://www.iana.org/numbers.html + +You can set it by passing a struct snmp_obj_id to the agent +using snmp_set_sysobjid(&my_object_id), just before snmp_init(). + +Note the object identifiers for thes MIB-2 and your private MIB +tree must be kept in sorted ascending (lexicographical) order. +This to ensure correct getnext operation. + +An example for a private MIB is part of the "minimal Unix" project: +contrib/ports/unix/proj/minimal/lwip_prvmib.c + +The next chapter gives a more detailed description of the +MIB-2 tree and the optional private MIB. + +4 The Gory Details +================== + +4.0 Object identifiers and the MIB tree. + +We have three distinct parts for all object identifiers: + +The prefix + .iso.org.dod.internet + +the middle part + .mgmt.mib-2.ip.ipNetToMediaTable.ipNetToMediaEntry.ipNetToMediaPhysAddress + +and the index part + .1.192.168.0.1 + +Objects located above the .internet hierarchy aren't supported. +Currently only the .mgmt sub-tree is available and +when the SNMP_PRIVATE_MIB is enabled the .private tree +becomes available too. + +Object identifiers from incoming requests are checked +for a matching prefix, middle part and index part +or are expanded(*) for GetNext requests with short +or inexisting names in the request. +(* we call this "expansion" but this also +resembles the "auto-completion" operation) + +The middle part is usually located in ROM (const) +to preserve precious RAM on small microcontrollers. +However RAM location is possible for a dynamically +changing private tree. + +The index part is handled by functions which in +turn use dynamically allocated index trees from RAM. +These trees are updated by e.g. the etharp code +when new entries are made or removed form the ARP cache. + +/** @todo more gory details */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/doc/sys_arch.txt b/component/common/network/lwip/lwip_v1.5.0.beta/doc/sys_arch.txt new file mode 100644 index 0000000..847cd77 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/doc/sys_arch.txt @@ -0,0 +1,267 @@ +sys_arch interface for lwIP 0.6++ + +Author: Adam Dunkels + +The operating system emulation layer provides a common interface +between the lwIP code and the underlying operating system kernel. The +general idea is that porting lwIP to new architectures requires only +small changes to a few header files and a new sys_arch +implementation. It is also possible to do a sys_arch implementation +that does not rely on any underlying operating system. + +The sys_arch provides semaphores and mailboxes to lwIP. For the full +lwIP functionality, multiple threads support can be implemented in the +sys_arch, but this is not required for the basic lwIP +functionality. Previous versions of lwIP required the sys_arch to +implement timer scheduling as well but as of lwIP 0.5 this is +implemented in a higher layer. + +In addition to the source file providing the functionality of sys_arch, +the OS emulation layer must provide several header files defining +macros used throughout lwip. The files required and the macros they +must define are listed below the sys_arch description. + +Semaphores can be either counting or binary - lwIP works with both +kinds. Mailboxes are used for message passing and can be implemented +either as a queue which allows multiple messages to be posted to a +mailbox, or as a rendez-vous point where only one message can be +posted at a time. lwIP works with both kinds, but the former type will +be more efficient. A message in a mailbox is just a pointer, nothing +more. + +Semaphores are represented by the type "sys_sem_t" which is typedef'd +in the sys_arch.h file. Mailboxes are equivalently represented by the +type "sys_mbox_t". lwIP does not place any restrictions on how +sys_sem_t or sys_mbox_t are represented internally. + +Since lwIP 1.4.0, semaphore and mailbox functions are prototyped in a way that +allows both using pointers or actual OS structures to be used. This way, memory +required for such types can be either allocated in place (globally or on the +stack) or on the heap (allocated internally in the "*_new()" functions). + +The following functions must be implemented by the sys_arch: + +- void sys_init(void) + + Is called to initialize the sys_arch layer. + +- err_t sys_sem_new(sys_sem_t *sem, u8_t count) + + Creates a new semaphore. The semaphore is allocated to the memory that 'sem' + points to (which can be both a pointer or the actual OS structure). + The "count" argument specifies the initial state of the semaphore (which is + either 0 or 1). + If the semaphore has been created, ERR_OK should be returned. Returning any + other error will provide a hint what went wrong, but except for assertions, + no real error handling is implemented. + +- void sys_sem_free(sys_sem_t *sem) + + Deallocates a semaphore. + +- void sys_sem_signal(sys_sem_t *sem) + + Signals a semaphore. + +- u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) + + Blocks the thread while waiting for the semaphore to be + signaled. If the "timeout" argument is non-zero, the thread should + only be blocked for the specified time (measured in + milliseconds). If the "timeout" argument is zero, the thread should be + blocked until the semaphore is signalled. + + If the timeout argument is non-zero, the return value is the number of + milliseconds spent waiting for the semaphore to be signaled. If the + semaphore wasn't signaled within the specified time, the return value is + SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore + (i.e., it was already signaled), the function may return zero. + + Notice that lwIP implements a function with a similar name, + sys_sem_wait(), that uses the sys_arch_sem_wait() function. + +- int sys_sem_valid(sys_sem_t *sem) + + Returns 1 if the semaphore is valid, 0 if it is not valid. + When using pointers, a simple way is to check the pointer for != NULL. + When directly using OS structures, implementing this may be more complex. + This may also be a define, in which case the function is not prototyped. + +- void sys_sem_set_invalid(sys_sem_t *sem) + + Invalidate a semaphore so that sys_sem_valid() returns 0. + ATTENTION: This does NOT mean that the semaphore shall be deallocated: + sys_sem_free() is always called before calling this function! + This may also be a define, in which case the function is not prototyped. + +- err_t sys_mbox_new(sys_mbox_t *mbox, int size) + + Creates an empty mailbox for maximum "size" elements. Elements stored + in mailboxes are pointers. You have to define macros "_MBOX_SIZE" + in your lwipopts.h, or ignore this parameter in your implementation + and use a default size. + If the mailbox has been created, ERR_OK should be returned. Returning any + other error will provide a hint what went wrong, but except for assertions, + no real error handling is implemented. + +- void sys_mbox_free(sys_mbox_t *mbox) + + Deallocates a mailbox. If there are messages still present in the + mailbox when the mailbox is deallocated, it is an indication of a + programming error in lwIP and the developer should be notified. + +- void sys_mbox_post(sys_mbox_t *mbox, void *msg) + + Posts the "msg" to the mailbox. This function have to block until + the "msg" is really posted. + +- err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) + + Try to post the "msg" to the mailbox. Returns ERR_MEM if this one + is full, else, ERR_OK if the "msg" is posted. + +- u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout) + + Blocks the thread until a message arrives in the mailbox, but does + not block the thread longer than "timeout" milliseconds (similar to + the sys_arch_sem_wait() function). If "timeout" is 0, the thread should + be blocked until a message arrives. The "msg" argument is a result + parameter that is set by the function (i.e., by doing "*msg = + ptr"). The "msg" parameter maybe NULL to indicate that the message + should be dropped. + + The return values are the same as for the sys_arch_sem_wait() function: + Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a + timeout. + + Note that a function with a similar name, sys_mbox_fetch(), is + implemented by lwIP. + +- u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg) + + This is similar to sys_arch_mbox_fetch, however if a message is not + present in the mailbox, it immediately returns with the code + SYS_MBOX_EMPTY. On success 0 is returned. + + To allow for efficient implementations, this can be defined as a + function-like macro in sys_arch.h instead of a normal function. For + example, a naive implementation could be: + #define sys_arch_mbox_tryfetch(mbox,msg) \ + sys_arch_mbox_fetch(mbox,msg,1) + although this would introduce unnecessary delays. + +- int sys_mbox_valid(sys_mbox_t *mbox) + + Returns 1 if the mailbox is valid, 0 if it is not valid. + When using pointers, a simple way is to check the pointer for != NULL. + When directly using OS structures, implementing this may be more complex. + This may also be a define, in which case the function is not prototyped. + +- void sys_mbox_set_invalid(sys_mbox_t *mbox) + + Invalidate a mailbox so that sys_mbox_valid() returns 0. + ATTENTION: This does NOT mean that the mailbox shall be deallocated: + sys_mbox_free() is always called before calling this function! + This may also be a define, in which case the function is not prototyped. + +If threads are supported by the underlying operating system and if +such functionality is needed in lwIP, the following function will have +to be implemented as well: + +- sys_thread_t sys_thread_new(char *name, void (* thread)(void *arg), void *arg, int stacksize, int prio) + + Starts a new thread named "name" with priority "prio" that will begin its + execution in the function "thread()". The "arg" argument will be passed as an + argument to the thread() function. The stack size to used for this thread is + the "stacksize" parameter. The id of the new thread is returned. Both the id + and the priority are system dependent. + +- sys_prot_t sys_arch_protect(void) + + This optional function does a "fast" critical region protection and returns + the previous protection level. This function is only called during very short + critical regions. An embedded system which supports ISR-based drivers might + want to implement this function by disabling interrupts. Task-based systems + might want to implement this by using a mutex or disabling tasking. This + function should support recursive calls from the same task or interrupt. In + other words, sys_arch_protect() could be called while already protected. In + that case the return value indicates that it is already protected. + + sys_arch_protect() is only required if your port is supporting an operating + system. + +- void sys_arch_unprotect(sys_prot_t pval) + + This optional function does a "fast" set of critical region protection to the + value specified by pval. See the documentation for sys_arch_protect() for + more information. This function is only required if your port is supporting + an operating system. + +For some configurations, you also need: + +- u32_t sys_now(void) + + This optional function returns the current time in milliseconds (don't care + for wraparound, this is only used for time diffs). + Not implementing this function means you cannot use some modules (e.g. TCP + timestamps, internal timeouts for NO_SYS==1). + + +Note: + +Be carefull with using mem_malloc() in sys_arch. When malloc() refers to +mem_malloc() you can run into a circular function call problem. In mem.c +mem_init() tries to allcate a semaphore using mem_malloc, which of course +can't be performed when sys_arch uses mem_malloc. + +------------------------------------------------------------------------------- +Additional files required for the "OS support" emulation layer: +------------------------------------------------------------------------------- + +cc.h - Architecture environment, some compiler specific, some + environment specific (probably should move env stuff + to sys_arch.h.) + + Typedefs for the types used by lwip - + u8_t, s8_t, u16_t, s16_t, u32_t, s32_t, mem_ptr_t + + Compiler hints for packing lwip's structures - + PACK_STRUCT_FIELD(x) + PACK_STRUCT_STRUCT + PACK_STRUCT_BEGIN + PACK_STRUCT_END + + Platform specific diagnostic output - + LWIP_PLATFORM_DIAG(x) - non-fatal, print a message. + LWIP_PLATFORM_ASSERT(x) - fatal, print message and abandon execution. + Portability defines for printf formatters: + U16_F, S16_F, X16_F, U32_F, S32_F, X32_F, SZT_F + + "lightweight" synchronization mechanisms - + SYS_ARCH_DECL_PROTECT(x) - declare a protection state variable. + SYS_ARCH_PROTECT(x) - enter protection mode. + SYS_ARCH_UNPROTECT(x) - leave protection mode. + + If the compiler does not provide memset() this file must include a + definition of it, or include a file which defines it. + + This file must either include a system-local which defines + the standard *nix error codes, or it should #define LWIP_PROVIDE_ERRNO + to make lwip/arch.h define the codes which are used throughout. + + +perf.h - Architecture specific performance measurement. + Measurement calls made throughout lwip, these can be defined to nothing. + PERF_START - start measuring something. + PERF_STOP(x) - stop measuring something, and record the result. + +sys_arch.h - Tied to sys_arch.c + + Arch dependent types for the following objects: + sys_sem_t, sys_mbox_t, sys_thread_t, + And, optionally: + sys_prot_t + + Defines to set vars of sys_mbox_t and sys_sem_t to NULL. + SYS_MBOX_NULL NULL + SYS_SEM_NULL NULL diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/port/realtek/arch/bpstruct.h b/component/common/network/lwip/lwip_v1.5.0.beta/port/realtek/arch/bpstruct.h new file mode 100644 index 0000000..177758c --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/port/realtek/arch/bpstruct.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#if defined(__IAR_SYSTEMS_ICC__) +#pragma pack(1) +#endif + diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/port/realtek/arch/cc.h b/component/common/network/lwip/lwip_v1.5.0.beta/port/realtek/arch/cc.h new file mode 100644 index 0000000..85636ef --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/port/realtek/arch/cc.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __CC_H__ +#define __CC_H__ + +#include "cpu.h" + +typedef unsigned char u8_t; +typedef signed char s8_t; +typedef unsigned short u16_t; +typedef signed short s16_t; +typedef unsigned int u32_t; +typedef signed long s32_t; +typedef u32_t mem_ptr_t; +typedef int sys_prot_t; + +#define U16_F "d" +#define S16_F "d" +#define X16_F "x" +#define U32_F "d" +#define S32_F "d" +#define X32_F "x" +#define SZT_F "uz" + +/* define compiler specific symbols */ +#if defined (__ICCARM__) + +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_STRUCT +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x +#define PACK_STRUCT_USE_INCLUDES + +#elif defined (__CC_ARM) + +#define PACK_STRUCT_BEGIN __packed +#define PACK_STRUCT_STRUCT +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x + +#elif defined (__GNUC__) + +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_STRUCT __attribute__ ((__packed__)) +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x + +#elif defined (__TASKING__) + +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_STRUCT +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x + +#endif + +#define LWIP_PLATFORM_ASSERT(x) //do { if(!(x)) while(1); } while(0) + +#endif /* __CC_H__ */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/port/realtek/arch/cpu.h b/component/common/network/lwip/lwip_v1.5.0.beta/port/realtek/arch/cpu.h new file mode 100644 index 0000000..a02f86d --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/port/realtek/arch/cpu.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __CPU_H__ +#define __CPU_H__ + +#define BYTE_ORDER LITTLE_ENDIAN + +#endif /* __CPU_H__ */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/port/realtek/arch/epstruct.h b/component/common/network/lwip/lwip_v1.5.0.beta/port/realtek/arch/epstruct.h new file mode 100644 index 0000000..1e1a049 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/port/realtek/arch/epstruct.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#if defined(__IAR_SYSTEMS_ICC__) +#pragma pack() +#endif + diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/port/realtek/arch/init.h b/component/common/network/lwip/lwip_v1.5.0.beta/port/realtek/arch/init.h new file mode 100644 index 0000000..e622c73 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/port/realtek/arch/init.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __ARCH_INIT_H__ +#define __ARCH_INIT_H__ + +#define TCPIP_INIT_DONE(arg) tcpip_init_done(arg) + +void tcpip_init_done(void *); +int wait_for_tcpip_init(void); + +#endif /* __ARCH_INIT_H__ */ + + + + diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/port/realtek/arch/lib.h b/component/common/network/lwip/lwip_v1.5.0.beta/port/realtek/arch/lib.h new file mode 100644 index 0000000..378f25b --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/port/realtek/arch/lib.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LIB_H__ +#define __LIB_H__ + +#include + + +#endif /* __LIB_H__ */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/port/realtek/arch/perf.h b/component/common/network/lwip/lwip_v1.5.0.beta/port/realtek/arch/perf.h new file mode 100644 index 0000000..334d42a --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/port/realtek/arch/perf.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __PERF_H__ +#define __PERF_H__ + +#define PERF_START /* null definition */ +#define PERF_STOP(x) /* null definition */ + +#endif /* __PERF_H__ */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/port/realtek/arch/sys_arch.h b/component/common/network/lwip/lwip_v1.5.0.beta/port/realtek/arch/sys_arch.h new file mode 100644 index 0000000..2e841bd --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/port/realtek/arch/sys_arch.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __SYS_RTXC_H__ +#define __SYS_RTXC_H__ + +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "semphr.h" + +#define SYS_MBOX_NULL (xQueueHandle)0 +#define SYS_SEM_NULL (xSemaphoreHandle)0 +#define SYS_DEFAULT_THREAD_STACK_DEPTH configMINIMAL_STACK_SIZE + +typedef xSemaphoreHandle sys_sem_t; +typedef xSemaphoreHandle sys_mutex_t; +typedef xQueueHandle sys_mbox_t; +typedef xTaskHandle sys_thread_t; + +typedef struct _sys_arch_state_t +{ + // Task creation data. + char cTaskName[configMAX_TASK_NAME_LEN]; + unsigned short nStackDepth; + unsigned short nTaskCount; +} sys_arch_state_t; + + + +//extern sys_arch_state_t s_sys_arch_state; + +//void sys_set_default_state(); +//void sys_set_state(signed char *pTaskName, unsigned short nStackSize); + +/* Message queue constants. */ +#define archMESG_QUEUE_LENGTH ( 6 ) +#endif /* __SYS_RTXC_H__ */ + diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/port/realtek/freertos/ethernetif.c b/component/common/network/lwip/lwip_v1.5.0.beta/port/realtek/freertos/ethernetif.c new file mode 100644 index 0000000..ed3f6a6 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/port/realtek/freertos/ethernetif.c @@ -0,0 +1,280 @@ +/** + * @file + * Ethernet Interface Skeleton + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/* + * This file is a skeleton for developing Ethernet network interface + * drivers for lwIP. Add code to the low_level functions and do a + * search-and-replace for the word "ethernetif" to replace it with + * something that better describes your network interface. + */ + +#include "lwip/opt.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/sys.h" +#include "lwip/tcpip.h" +#include "lwip/icmp.h" +#include "lwip/lwip_timers.h" +#include "netif/etharp.h" +#include "err.h" +#include "ethernetif.h" +#include "queue.h" + +#include "lwip/ethip6.h" //Evan add for ipv6 +#include +#include + +#define netifMTU (1500) +#define netifINTERFACE_TASK_STACK_SIZE ( 350 ) +#define netifINTERFACE_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) +#define netifGUARD_BLOCK_TIME ( 250 ) +/* The time to block waiting for input. */ +#define emacBLOCK_TIME_WAITING_FOR_INPUT ( ( portTickType ) 100 ) + + +#ifdef CONFIG_CONCURRENT_MODE +#define IF2NAME0 'r' +#define IF2NAME1 '2' +#endif + +static void arp_timer(void *arg); + + +/** + * In this function, the hardware should be initialized. + * Called from ethernetif_init(). + * + * @param netif the already initialized lwip network interface structure + * for this ethernetif + */ + +static void low_level_init(struct netif *netif) +{ + + /* set netif MAC hardware address length */ + netif->hwaddr_len = ETHARP_HWADDR_LEN; + + /* set netif maximum transfer unit */ + netif->mtu = 1500; + + /* Accept broadcast address and ARP traffic */ + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; + + /* Wlan interface is initialized later */ +} + + +/** + * This function should do the actual transmission of the packet. The packet is + * contained in the pbuf that is passed to the function. This pbuf + * might be chained. + * + * @param netif the lwip network interface structure for this ethernetif + * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type) + * @return ERR_OK if the packet could be sent + * an err_t value if the packet couldn't be sent + * + * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to + * strange results. You might consider waiting for space in the DMA queue + * to become availale since the stack doesn't retry to send a packet + * dropped because of memory failure (except for the TCP timers). + */ + +static err_t low_level_output(struct netif *netif, struct pbuf *p) +{ + + + /* Refer to eCos lwip eth_drv_send() */ + struct eth_drv_sg sg_list[MAX_ETH_DRV_SG]; + int sg_len = 0; + struct pbuf *q; + + if(!rltk_wlan_running(netif_get_idx(netif))) + return ERR_IF; + + for (q = p; q != NULL && sg_len < MAX_ETH_DRV_SG; q = q->next) { + sg_list[sg_len].buf = (unsigned int) q->payload; + sg_list[sg_len++].len = q->len; + } + + if (sg_len) + rltk_wlan_send(netif_get_idx(netif), sg_list, sg_len, p->tot_len); + + return ERR_OK; +} + + +/** + * Should allocate a pbuf and transfer the bytes of the incoming + * packet from the interface into the pbuf. + * + * @param netif the lwip network interface structure for this ethernetif + * @return a pbuf filled with the received packet (including MAC header) + * NULL on memory error + */ +//static struct pbuf * low_level_input(struct netif *netif){} + + +/** + * This function is the ethernetif_input task, it is processed when a packet + * is ready to be read from the interface. It uses the function low_level_input() + * that should handle the actual reception of bytes from the network + * interface. Then the type of the received packet is determined and + * the appropriate input function is called. + * + * @param netif the lwip network interface structure for this ethernetif + */ +//void ethernetif_input( void * pvParameters ) + + +/* Refer to eCos eth_drv_recv to do similarly in ethernetif_input */ +void ethernetif_recv(struct netif *netif, int total_len) +{ + struct eth_drv_sg sg_list[MAX_ETH_DRV_SG]; + struct pbuf *p, *q; + int sg_len = 0; + + if(!rltk_wlan_running(netif_get_idx(netif))) + return; + + if ((total_len > MAX_ETH_MSG) || (total_len < 0)) + total_len = MAX_ETH_MSG; + + // Allocate buffer to store received packet + p = pbuf_alloc(PBUF_RAW, total_len, PBUF_POOL); + if (p == NULL) { + printf("\n\rCannot allocate pbuf to receive packet"); + return; + } + + // Create scatter list + for (q = p; q != NULL && sg_len < MAX_ETH_DRV_SG; q = q->next) { + sg_list[sg_len].buf = (unsigned int) q->payload; + sg_list[sg_len++].len = q->len; + } + + // Copy received packet to scatter list from wrapper rx skb + //printf("\n\rwlan:%c: Recv sg_len: %d, tot_len:%d", netif->name[1],sg_len, total_len); + rltk_wlan_recv(netif_get_idx(netif), sg_list, sg_len); + + // Pass received packet to the interface + if (ERR_OK != netif->input(p, netif)) + pbuf_free(p); + +} + +/** + * Should be called at the beginning of the program to set up the + * network interface. It calls the function low_level_init() to do the + * actual setup of the hardware. + * + * This function should be passed as a parameter to netif_add(). + * + * @param netif the lwip network interface structure for this ethernetif + * @return ERR_OK if the loopif is initialized + * ERR_MEM if private data couldn't be allocated + * any other err_t on error + */ +err_t ethernetif_init(struct netif *netif) +{ + LWIP_ASSERT("netif != NULL", (netif != NULL)); + +#if LWIP_NETIF_HOSTNAME + /* Initialize interface hostname */ + if(netif->name[1] == '0') + netif->hostname = "lwip0"; + else if(netif->name[1] == '1') + netif->hostname = "lwip1"; +#endif /* LWIP_NETIF_HOSTNAME */ + + netif->output = etharp_output; +#if LWIP_IPV6 + netif->output_ip6 = ethip6_output; +#endif + netif->linkoutput = low_level_output; + + /* initialize the hardware */ + low_level_init(netif); + + etharp_init(); + + return ERR_OK; +} + +static void arp_timer(void *arg) +{ + etharp_tmr(); + sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); +} + +/* + * For FreeRTOS tickless + */ +int lwip_tickless_used = 0; + +int arp_timeout_exist(void) +{ + struct sys_timeouts *timeouts; + struct sys_timeo *t; + + timeouts = sys_arch_timeouts(); + + for(t = timeouts->next; t != NULL;t = t->next) + if(t->h == arp_timer) + return 1; + + return 0; +} + +//Called by rltk_wlan_PRE_SLEEP_PROCESSING() +void lwip_PRE_SLEEP_PROCESSING(void) +{ + if(arp_timeout_exist()) { + tcpip_untimeout(arp_timer, NULL); + } + lwip_tickless_used = 1; +} + +//Called in ips_leave() path, support tickless when wifi power wakeup due to ioctl or deinit +void lwip_POST_SLEEP_PROCESSING(void) +{ + if(lwip_tickless_used) { + tcpip_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); + } +} diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/port/realtek/freertos/ethernetif.h b/component/common/network/lwip/lwip_v1.5.0.beta/port/realtek/freertos/ethernetif.h new file mode 100644 index 0000000..93139d1 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/port/realtek/freertos/ethernetif.h @@ -0,0 +1,13 @@ +#ifndef __ETHERNETIF_H__ +#define __ETHERNETIF_H__ + + +#include "lwip/err.h" +#include "lwip/netif.h" + +void ethernetif_recv(struct netif *netif, int total_len); +err_t ethernetif_init(struct netif *netif); +void lwip_PRE_SLEEP_PROCESSING(void); +void lwip_POST_SLEEP_PROCESSING(void); + +#endif diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/port/realtek/freertos/sys_arch.c b/component/common/network/lwip/lwip_v1.5.0.beta/port/realtek/freertos/sys_arch.c new file mode 100644 index 0000000..a51e2af --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/port/realtek/freertos/sys_arch.c @@ -0,0 +1,517 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/* lwIP includes. */ +#include "lwip/debug.h" +#include "lwip/def.h" +#include "lwip/sys.h" +#include "lwip/mem.h" +#include "lwip/stats.h" +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "lwip/lwip_timers.h" + +xTaskHandle xTaskGetCurrentTaskHandle( void ) PRIVILEGED_FUNCTION; + +struct timeoutlist +{ + struct sys_timeouts timeouts; + xTaskHandle pid; +}; + +/* This is the number of threads that can be started with sys_thread_new() */ +#define SYS_THREAD_MAX 6 + +static struct timeoutlist s_timeoutlist[SYS_THREAD_MAX]; +static u16_t s_nextthread = 0; + + +/*-----------------------------------------------------------------------------------*/ +// Creates an empty mailbox. +err_t sys_mbox_new(sys_mbox_t *mbox, int size) +{ + (void ) size; + + *mbox = xQueueCreate( archMESG_QUEUE_LENGTH, sizeof( void * ) ); + +#if SYS_STATS + ++lwip_stats.sys.mbox.used; + if (lwip_stats.sys.mbox.max < lwip_stats.sys.mbox.used) { + lwip_stats.sys.mbox.max = lwip_stats.sys.mbox.used; + } +#endif /* SYS_STATS */ + if (*mbox == NULL) + return ERR_MEM; + + return ERR_OK; +} + +/*-----------------------------------------------------------------------------------*/ +/* + Deallocates a mailbox. If there are messages still present in the + mailbox when the mailbox is deallocated, it is an indication of a + programming error in lwIP and the developer should be notified. +*/ +void sys_mbox_free(sys_mbox_t *mbox) +{ + if( uxQueueMessagesWaiting( *mbox ) ) + { + /* Line for breakpoint. Should never break here! */ + portNOP(); +#if SYS_STATS + lwip_stats.sys.mbox.err++; +#endif /* SYS_STATS */ + + // TODO notify the user of failure. + } + + vQueueDelete( *mbox ); + +#if SYS_STATS + --lwip_stats.sys.mbox.used; +#endif /* SYS_STATS */ +} + +/*-----------------------------------------------------------------------------------*/ +// Posts the "msg" to the mailbox. +void sys_mbox_post(sys_mbox_t *mbox, void *data) +{ + while ( xQueueSendToBack(*mbox, &data, portMAX_DELAY ) != pdTRUE ){} +} + + +/*-----------------------------------------------------------------------------------*/ +// Try to post the "msg" to the mailbox. +err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) +{ +err_t result; + + if ( xQueueSend( *mbox, &msg, 0 ) == pdPASS ) + { + result = ERR_OK; + } + else { + // could not post, queue must be full + result = ERR_MEM; + +#if SYS_STATS + lwip_stats.sys.mbox.err++; +#endif /* SYS_STATS */ + + } + + return result; +} + +/*-----------------------------------------------------------------------------------*/ +/* + Blocks the thread until a message arrives in the mailbox, but does + not block the thread longer than "timeout" milliseconds (similar to + the sys_arch_sem_wait() function). The "msg" argument is a result + parameter that is set by the function (i.e., by doing "*msg = + ptr"). The "msg" parameter maybe NULL to indicate that the message + should be dropped. + + The return values are the same as for the sys_arch_sem_wait() function: + Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a + timeout. + + Note that a function with a similar name, sys_mbox_fetch(), is + implemented by lwIP. +*/ +u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout) +{ +void *dummyptr; +portTickType StartTime, EndTime, Elapsed; + + StartTime = xTaskGetTickCount(); + + if ( msg == NULL ) + { + msg = &dummyptr; + } + + if ( timeout != 0 ) + { + if ( pdTRUE == xQueueReceive( *mbox, &(*msg), timeout / portTICK_RATE_MS ) ) + { + EndTime = xTaskGetTickCount(); + Elapsed = (EndTime - StartTime) * portTICK_RATE_MS; + + return ( Elapsed ); + } + else // timed out blocking for message + { + *msg = NULL; + + return SYS_ARCH_TIMEOUT; + } + } + else // block forever for a message. + { + while( pdTRUE != xQueueReceive( *mbox, &(*msg), portMAX_DELAY ) ){} // time is arbitrary + EndTime = xTaskGetTickCount(); + Elapsed = (EndTime - StartTime) * portTICK_RATE_MS; + + return ( Elapsed ); // return time blocked TODO test + } +} + +/*-----------------------------------------------------------------------------------*/ +/* + Similar to sys_arch_mbox_fetch, but if message is not ready immediately, we'll + return with SYS_MBOX_EMPTY. On success, 0 is returned. +*/ +u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg) +{ +void *dummyptr; + + if ( msg == NULL ) + { + msg = &dummyptr; + } + + if ( pdTRUE == xQueueReceive( *mbox, &(*msg), 0 ) ) + { + return ERR_OK; + } + else + { + return SYS_MBOX_EMPTY; + } +} +/*----------------------------------------------------------------------------------*/ +int sys_mbox_valid(sys_mbox_t *mbox) +{ + if (*mbox == SYS_MBOX_NULL) + return 0; + else + return 1; +} +/*-----------------------------------------------------------------------------------*/ +void sys_mbox_set_invalid(sys_mbox_t *mbox) +{ + *mbox = SYS_MBOX_NULL; +} + +/*-----------------------------------------------------------------------------------*/ +// Creates a new semaphore. The "count" argument specifies +// the initial state of the semaphore. +err_t sys_sem_new(sys_sem_t *sem, u8_t count) +{ + vSemaphoreCreateBinary(*sem ); + if(*sem == NULL) + { + +#if SYS_STATS + ++lwip_stats.sys.sem.err; +#endif /* SYS_STATS */ + return ERR_MEM; + } + + if(count == 0) // Means it can't be taken + { + xSemaphoreTake(*sem,1); + } + +#if SYS_STATS + ++lwip_stats.sys.sem.used; + if (lwip_stats.sys.sem.max < lwip_stats.sys.sem.used) { + lwip_stats.sys.sem.max = lwip_stats.sys.sem.used; + } +#endif /* SYS_STATS */ + + return ERR_OK; +} + +/*-----------------------------------------------------------------------------------*/ +/* + Blocks the thread while waiting for the semaphore to be + signaled. If the "timeout" argument is non-zero, the thread should + only be blocked for the specified time (measured in + milliseconds). + + If the timeout argument is non-zero, the return value is the number of + milliseconds spent waiting for the semaphore to be signaled. If the + semaphore wasn't signaled within the specified time, the return value is + SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore + (i.e., it was already signaled), the function may return zero. + + Notice that lwIP implements a function with a similar name, + sys_sem_wait(), that uses the sys_arch_sem_wait() function. +*/ +u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) +{ +portTickType StartTime, EndTime, Elapsed; + + StartTime = xTaskGetTickCount(); + + if( timeout != 0) + { + if( xSemaphoreTake( *sem, timeout / portTICK_RATE_MS ) == pdTRUE ) + { + EndTime = xTaskGetTickCount(); + Elapsed = (EndTime - StartTime) * portTICK_RATE_MS; + + return (Elapsed); // return time blocked TODO test + } + else + { + return SYS_ARCH_TIMEOUT; + } + } + else // must block without a timeout + { + while( xSemaphoreTake(*sem, portMAX_DELAY) != pdTRUE){} + EndTime = xTaskGetTickCount(); + Elapsed = (EndTime - StartTime) * portTICK_RATE_MS; + + return ( Elapsed ); // return time blocked + + } +} + +/*-----------------------------------------------------------------------------------*/ +// Signals a semaphore +void sys_sem_signal(sys_sem_t *sem) +{ + xSemaphoreGive(*sem); +} + +/*-----------------------------------------------------------------------------------*/ +// Deallocates a semaphore +void sys_sem_free(sys_sem_t *sem) +{ +#if SYS_STATS + --lwip_stats.sys.sem.used; +#endif /* SYS_STATS */ + + vQueueDelete(*sem); +} +/*-----------------------------------------------------------------------------------*/ +int sys_sem_valid(sys_sem_t *sem) +{ + if (*sem == SYS_SEM_NULL) + return 0; + else + return 1; +} + +/*-----------------------------------------------------------------------------------*/ +void sys_sem_set_invalid(sys_sem_t *sem) +{ + *sem = SYS_SEM_NULL; +} + +/*-----------------------------------------------------------------------------------*/ +// Initialize sys arch +void sys_init(void) +{ + int i; + + // Initialize the the per-thread sys_timeouts structures + // make sure there are no valid pids in the list + for(i = 0; i < SYS_THREAD_MAX; i++) + { + s_timeoutlist[i].pid = 0; + s_timeoutlist[i].timeouts.next = NULL; + } + + // keep track of how many threads have been created + s_nextthread = 0; +} + +/*-----------------------------------------------------------------------------------*/ +/* + Returns a pointer to the per-thread sys_timeouts structure. In lwIP, + each thread has a list of timeouts which is represented as a linked + list of sys_timeout structures. The sys_timeouts structure holds a + pointer to a linked list of timeouts. This function is called by + the lwIP timeout scheduler and must not return a NULL value. + + In a single threaded sys_arch implementation, this function will + simply return a pointer to a global sys_timeouts variable stored in + the sys_arch module. +*/ +struct sys_timeouts *sys_arch_timeouts(void) +{ +int i; +xTaskHandle pid; +struct timeoutlist *tl; + + pid = xTaskGetCurrentTaskHandle(); + + for(i = 0; i < s_nextthread; i++) + { + tl = &(s_timeoutlist[i]); + if(tl->pid == pid) + { + return &(tl->timeouts); + } + } + // Error + return NULL; +} +/*-----------------------------------------------------------------------------------*/ + /* Mutexes*/ +/*-----------------------------------------------------------------------------------*/ +/*-----------------------------------------------------------------------------------*/ +#if LWIP_COMPAT_MUTEX == 0 +/* Create a new mutex*/ +err_t sys_mutex_new(sys_mutex_t *mutex) { + + *mutex = xSemaphoreCreateMutex(); + if(*mutex == NULL) + { +#if SYS_STATS + ++lwip_stats.sys.mutex.err; +#endif /* SYS_STATS */ + return ERR_MEM; + } + +#if SYS_STATS + ++lwip_stats.sys.mutex.used; + if (lwip_stats.sys.mutex.max < lwip_stats.sys.mutex.used) { + lwip_stats.sys.mutex.max = lwip_stats.sys.mutex.used; + } +#endif /* SYS_STATS */ + return ERR_OK; +} +/*-----------------------------------------------------------------------------------*/ +/* Deallocate a mutex*/ +void sys_mutex_free(sys_mutex_t *mutex) +{ +#if SYS_STATS + --lwip_stats.sys.mutex.used; +#endif /* SYS_STATS */ + + vQueueDelete(*mutex); +} +/*-----------------------------------------------------------------------------------*/ +/* Lock a mutex*/ +void sys_mutex_lock(sys_mutex_t *mutex) +{ + sys_arch_sem_wait(*mutex, 0); +} + +/*-----------------------------------------------------------------------------------*/ +/* Unlock a mutex*/ +void sys_mutex_unlock(sys_mutex_t *mutex) +{ + xSemaphoreGive(*mutex); +} +#endif /*LWIP_COMPAT_MUTEX*/ +/*-----------------------------------------------------------------------------------*/ +// TODO +/*-----------------------------------------------------------------------------------*/ +/* + Starts a new thread with priority "prio" that will begin its execution in the + function "thread()". The "arg" argument will be passed as an argument to the + thread() function. The id of the new thread is returned. Both the id and + the priority are system dependent. +*/ +sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread , void *arg, int stacksize, int prio) +{ +xTaskHandle CreatedTask; +int result; + + if ( s_nextthread < SYS_THREAD_MAX ) + { + vPortEnterCritical(); + result = xTaskCreate( thread, ( signed portCHAR * ) name, stacksize, arg, prio, &CreatedTask ); + + // For each task created, store the task handle (pid) in the timers array. + // This scheme doesn't allow for threads to be deleted + s_timeoutlist[s_nextthread++].pid = CreatedTask; + vPortExitCritical(); + + if(result == pdPASS) + { + return CreatedTask; + } + else + { + return NULL; + } + } + else + { + return NULL; + } +} + +/* + This optional function does a "fast" critical region protection and returns + the previous protection level. This function is only called during very short + critical regions. An embedded system which supports ISR-based drivers might + want to implement this function by disabling interrupts. Task-based systems + might want to implement this by using a mutex or disabling tasking. This + function should support recursive calls from the same task or interrupt. In + other words, sys_arch_protect() could be called while already protected. In + that case the return value indicates that it is already protected. + + sys_arch_protect() is only required if your port is supporting an operating + system. +*/ +sys_prot_t sys_arch_protect(void) +{ + vPortEnterCritical(); + return 1; +} + +/* + This optional function does a "fast" set of critical region protection to the + value specified by pval. See the documentation for sys_arch_protect() for + more information. This function is only required if your port is supporting + an operating system. +*/ +void sys_arch_unprotect(sys_prot_t pval) +{ + ( void ) pval; + vPortExitCritical(); +} + +/* + * Prints an assertion messages and aborts execution. + */ +void sys_assert( const char *msg ) +{ + ( void ) msg; + /*FSL:only needed for debugging + printf(msg); + printf("\n\r"); + */ + vPortEnterCritical( ); + for(;;) + ; +} diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/port/realtek/freertos/sys_arch.h b/component/common/network/lwip/lwip_v1.5.0.beta/port/realtek/freertos/sys_arch.h new file mode 100644 index 0000000..83d0c08 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/port/realtek/freertos/sys_arch.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __SYS_RTXC_H__ +#define __SYS_RTXC_H__ + +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "semphr.h" + +#define SYS_MBOX_NULL (xQueueHandle)0 +#define SYS_SEM_NULL (xSemaphoreHandle)0 +#define SYS_DEFAULT_THREAD_STACK_DEPTH configMINIMAL_STACK_SIZE + +typedef xSemaphoreHandle sys_sem_t; +typedef xQueueHandle sys_mbox_t; +typedef xTaskHandle sys_thread_t; + +typedef struct _sys_arch_state_t +{ + // Task creation data. + char cTaskName[configMAX_TASK_NAME_LEN]; + unsigned short nStackDepth; + unsigned short nTaskCount; +} sys_arch_state_t; + + + +//extern sys_arch_state_t s_sys_arch_state; + +//void sys_set_default_state(); +//void sys_set_state(signed char *pTaskName, unsigned short nStackSize); + +/* Message queue constants. */ +#define archMESG_QUEUE_LENGTH ( 6 ) +#endif /* __SYS_RTXC_H__ */ + diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/arch/bpstruct.h b/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/arch/bpstruct.h new file mode 100644 index 0000000..177758c --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/arch/bpstruct.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#if defined(__IAR_SYSTEMS_ICC__) +#pragma pack(1) +#endif + diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/arch/cc.h b/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/arch/cc.h new file mode 100644 index 0000000..bad923c --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/arch/cc.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __CC_H__ +#define __CC_H__ + +#include "cpu.h" + +typedef unsigned char u8_t; +typedef signed char s8_t; +typedef unsigned short u16_t; +typedef signed short s16_t; +typedef unsigned long u32_t; +typedef signed long s32_t; +typedef u32_t mem_ptr_t; +typedef int sys_prot_t; + + +#define U16_F "hu" +#define S16_F "d" +#define X16_F "hx" +#define U32_F "u" +#define S32_F "d" +#define X32_F "x" +#define SZT_F "uz" + +//Evan add for ipv6 & IGMP +#define LWIP_RAND 1 + +#ifdef LWIP_RAND +#define u32_t_random() (u32_t)(rand() % 0xFFFFFFFF) +#endif +//Evan add end + + +/* define compiler specific symbols */ +#if defined (__ICCARM__) + +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_STRUCT +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x +#define PACK_STRUCT_USE_INCLUDES + +#elif defined (__CC_ARM) + +#define PACK_STRUCT_BEGIN __packed +#define PACK_STRUCT_STRUCT +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x + +#elif defined (__GNUC__) + +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_STRUCT __attribute__ ((__packed__)) +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x + +#elif defined (__TASKING__) + +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_STRUCT +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x + +#endif + +#define LWIP_PLATFORM_ASSERT(x) //do { if(!(x)) while(1); } while(0) + +#endif /* __CC_H__ */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/arch/cpu.h b/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/arch/cpu.h new file mode 100644 index 0000000..a02f86d --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/arch/cpu.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __CPU_H__ +#define __CPU_H__ + +#define BYTE_ORDER LITTLE_ENDIAN + +#endif /* __CPU_H__ */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/arch/epstruct.h b/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/arch/epstruct.h new file mode 100644 index 0000000..1e1a049 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/arch/epstruct.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#if defined(__IAR_SYSTEMS_ICC__) +#pragma pack() +#endif + diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/arch/init.h b/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/arch/init.h new file mode 100644 index 0000000..e622c73 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/arch/init.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __ARCH_INIT_H__ +#define __ARCH_INIT_H__ + +#define TCPIP_INIT_DONE(arg) tcpip_init_done(arg) + +void tcpip_init_done(void *); +int wait_for_tcpip_init(void); + +#endif /* __ARCH_INIT_H__ */ + + + + diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/arch/lib.h b/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/arch/lib.h new file mode 100644 index 0000000..378f25b --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/arch/lib.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LIB_H__ +#define __LIB_H__ + +#include + + +#endif /* __LIB_H__ */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/arch/perf.h b/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/arch/perf.h new file mode 100644 index 0000000..334d42a --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/arch/perf.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __PERF_H__ +#define __PERF_H__ + +#define PERF_START /* null definition */ +#define PERF_STOP(x) /* null definition */ + +#endif /* __PERF_H__ */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/arch/sys_arch.h b/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/arch/sys_arch.h new file mode 100644 index 0000000..2e841bd --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/arch/sys_arch.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __SYS_RTXC_H__ +#define __SYS_RTXC_H__ + +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "semphr.h" + +#define SYS_MBOX_NULL (xQueueHandle)0 +#define SYS_SEM_NULL (xSemaphoreHandle)0 +#define SYS_DEFAULT_THREAD_STACK_DEPTH configMINIMAL_STACK_SIZE + +typedef xSemaphoreHandle sys_sem_t; +typedef xSemaphoreHandle sys_mutex_t; +typedef xQueueHandle sys_mbox_t; +typedef xTaskHandle sys_thread_t; + +typedef struct _sys_arch_state_t +{ + // Task creation data. + char cTaskName[configMAX_TASK_NAME_LEN]; + unsigned short nStackDepth; + unsigned short nTaskCount; +} sys_arch_state_t; + + + +//extern sys_arch_state_t s_sys_arch_state; + +//void sys_set_default_state(); +//void sys_set_state(signed char *pTaskName, unsigned short nStackSize); + +/* Message queue constants. */ +#define archMESG_QUEUE_LENGTH ( 6 ) +#endif /* __SYS_RTXC_H__ */ + diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/freertos/MFC6A0B.tmp b/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/freertos/MFC6A0B.tmp new file mode 100644 index 0000000..5097f29 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/freertos/MFC6A0B.tmp @@ -0,0 +1,489 @@ +/** +* @file +* Ethernet Interface Skeleton +* +*/ + +/* +* Copyright (c) 2001-2004 Swedish Institute of Computer Science. +* 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. The name of the author may not be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. +* +* This file is part of the lwIP TCP/IP stack. +* +* Author: Adam Dunkels +* +*/ + +/* +* This file is a skeleton for developing Ethernet network interface +* drivers for lwIP. Add code to the low_level functions and do a +* search-and-replace for the word "ethernetif" to replace it with +* something that better describes your network interface. +*/ + +#include "lwip/opt.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +//#include "lwip/sys.h" +//#include "lwip/tcpip.h" +//#include "lwip/icmp.h" +#include "lwip/lwip_timers.h" +#include "netif/etharp.h" +#include "err.h" +#include "ethernetif.h" +//#include "queue.h" + +#include "main.h" // for the definition of CONFIG_WLAN + +#if !CONFIG_WLAN +#include "stm32f2x7_eth.h" +#else +#include +#endif +#include + +#include + + +#define netifMTU (1500) +#define netifINTERFACE_TASK_STACK_SIZE ( 350 ) +#define netifINTERFACE_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) +#define netifGUARD_BLOCK_TIME ( 250 ) +/* The time to block waiting for input. */ +#define emacBLOCK_TIME_WAITING_FOR_INPUT ( ( portTickType ) 100 ) + +#if !CONFIG_WLAN +/* Define those to better describe your network interface. */ +#define IFNAME0 's' +#define IFNAME1 't' + +static struct netif *s_pxNetIf = NULL; +xSemaphoreHandle s_xSemaphore = NULL; + + +/* Ethernet Rx & Tx DMA Descriptors */ +extern ETH_DMADESCTypeDef DMARxDscrTab[ETH_RXBUFNB], DMATxDscrTab[ETH_TXBUFNB]; + +/* Ethernet Receive buffers */ +extern uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE]; + +/* Ethernet Transmit buffers */ +extern uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE]; + +/* Global pointers to track current transmit and receive descriptors */ +extern ETH_DMADESCTypeDef *DMATxDescToSet; +extern ETH_DMADESCTypeDef *DMARxDescToGet; + +/* Global pointer for last received frame infos */ +extern ETH_DMA_Rx_Frame_infos *DMA_RX_FRAME_infos; + + +static void ethernetif_input( void * pvParameters ); +#endif + +static void arp_timer(void *arg); + + +/** +* In this function, the hardware should be initialized. +* Called from ethernetif_init(). +* +* @param netif the already initialized lwip network interface structure +* for this ethernetif +*/ +static void low_level_init(struct netif *netif) +{ + uint32_t i; + + /* set netif MAC hardware address length */ + netif->hwaddr_len = ETHARP_HWADDR_LEN; + +#if !CONFIG_WLAN + /* set netif MAC hardware address */ + netif->hwaddr[0] = MAC_ADDR0; + netif->hwaddr[1] = MAC_ADDR1; + netif->hwaddr[2] = MAC_ADDR2; + netif->hwaddr[3] = MAC_ADDR3; + netif->hwaddr[4] = MAC_ADDR4; + netif->hwaddr[5] = MAC_ADDR5; +#endif + + /* set netif maximum transfer unit */ + netif->mtu = 1500; + + /* Accept broadcast address and ARP traffic */ + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; + +#if !CONFIG_WLAN + s_pxNetIf =netif; + + /* create binary semaphore used for informing ethernetif of frame reception */ + if (s_xSemaphore == NULL) + { + vSemaphoreCreateBinary(s_xSemaphore); + xSemaphoreTake( s_xSemaphore, 0); + } + + /* initialize MAC address in ethernet MAC */ + ETH_MACAddressConfig(ETH_MAC_Address0, netif->hwaddr); + + /* Initialize Tx Descriptors list: Chain Mode */ + ETH_DMATxDescChainInit(DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB); + /* Initialize Rx Descriptors list: Chain Mode */ + ETH_DMARxDescChainInit(DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB); + + /* Enable Ethernet Rx interrrupt */ + { + for(i=0; iBuffer1Addr); + bufferoffset = 0; + + for(q = p; q != NULL; q = q->next) + { + if((DmaTxDesc->Status & ETH_DMATxDesc_OWN) != (u32)RESET) + { + goto error; + } + + /* Get bytes in current lwIP buffer */ + byteslefttocopy = q->len; + payloadoffset = 0; + + /* Check if the length of data to copy is bigger than Tx buffer size*/ + while( (byteslefttocopy + bufferoffset) > ETH_TX_BUF_SIZE ) + { + /* Copy data to Tx buffer*/ + memcpy( (u8_t*)((u8_t*)buffer + bufferoffset), (u8_t*)((u8_t*)q->payload + payloadoffset), (ETH_TX_BUF_SIZE - bufferoffset) ); + + /* Point to next descriptor */ + DmaTxDesc = (ETH_DMADESCTypeDef *)(DmaTxDesc->Buffer2NextDescAddr); + + /* Check if the buffer is available */ + if((DmaTxDesc->Status & ETH_DMATxDesc_OWN) != (u32)RESET) + { + goto error; + } + + buffer = (u8 *)(DmaTxDesc->Buffer1Addr); + + byteslefttocopy = byteslefttocopy - (ETH_TX_BUF_SIZE - bufferoffset); + payloadoffset = payloadoffset + (ETH_TX_BUF_SIZE - bufferoffset); + framelength = framelength + (ETH_TX_BUF_SIZE - bufferoffset); + bufferoffset = 0; + } + + /* Copy the remaining bytes */ + memcpy( (u8_t*)((u8_t*)buffer + bufferoffset), (u8_t*)((u8_t*)q->payload + payloadoffset), byteslefttocopy ); + bufferoffset = bufferoffset + byteslefttocopy; + framelength = framelength + byteslefttocopy; + } + + /* Prepare transmit descriptors to give to DMA*/ + ETH_Prepare_Transmit_Descriptors(framelength); + + /* Give semaphore and exit */ + error: + + xSemaphoreGive(xTxSemaphore); + } +#endif // #if !CONFIG_WLAN + + return ERR_OK; +} + + +#if !CONFIG_WLAN +/** +* Should allocate a pbuf and transfer the bytes of the incoming +* packet from the interface into the pbuf. +* +* @param netif the lwip network interface structure for this ethernetif +* @return a pbuf filled with the received packet (including MAC header) +* NULL on memory error +*/ +static struct pbuf * low_level_input(struct netif *netif) +{ + struct pbuf *p= NULL, *q; + u32_t len; + FrameTypeDef frame; + u8 *buffer; + __IO ETH_DMADESCTypeDef *DMARxDesc; + uint32_t bufferoffset = 0; + uint32_t payloadoffset = 0; + uint32_t byteslefttocopy = 0; + uint32_t i=0; + + /* get received frame */ + frame = ETH_Get_Received_Frame_interrupt(); + + /* Obtain the size of the packet and put it into the "len" variable. */ + len = frame.length; + buffer = (u8 *)frame.buffer; + + if (len > 0) + { + /* We allocate a pbuf chain of pbufs from the Lwip buffer pool */ + p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); + } + + if (p != NULL) + { + DMARxDesc = frame.descriptor; + bufferoffset = 0; + for(q = p; q != NULL; q = q->next) + { + byteslefttocopy = q->len; + payloadoffset = 0; + + /* Check if the length of bytes to copy in current pbuf is bigger than Rx buffer size*/ + while( (byteslefttocopy + bufferoffset) > ETH_RX_BUF_SIZE ) + { + /* Copy data to pbuf*/ + memcpy( (u8_t*)((u8_t*)q->payload + payloadoffset), (u8_t*)((u8_t*)buffer + bufferoffset), (ETH_RX_BUF_SIZE - bufferoffset)); + + /* Point to next descriptor */ + DMARxDesc = (ETH_DMADESCTypeDef *)(DMARxDesc->Buffer2NextDescAddr); + buffer = (unsigned char *)(DMARxDesc->Buffer1Addr); + + byteslefttocopy = byteslefttocopy - (ETH_RX_BUF_SIZE - bufferoffset); + payloadoffset = payloadoffset + (ETH_RX_BUF_SIZE - bufferoffset); + bufferoffset = 0; + } + + /* Copy remaining data in pbuf */ + memcpy( (u8_t*)((u8_t*)q->payload + payloadoffset), (u8_t*)((u8_t*)buffer + bufferoffset), byteslefttocopy); + bufferoffset = bufferoffset + byteslefttocopy; + } + + /* Release descriptors to DMA */ + DMARxDesc =frame.descriptor; + + /* Set Own bit in Rx descriptors: gives the buffers back to DMA */ + for (i=0; iSeg_Count; i++) + { + DMARxDesc->Status = ETH_DMARxDesc_OWN; + DMARxDesc = (ETH_DMADESCTypeDef *)(DMARxDesc->Buffer2NextDescAddr); + } + + /* Clear Segment_Count */ + DMA_RX_FRAME_infos->Seg_Count =0; + /* added for test*/ + } + + /* When Rx Buffer unavailable flag is set: clear it and resume reception */ + if ((ETH->DMASR & ETH_DMASR_RBUS) != (u32)RESET) + { + /* Clear RBUS ETHERNET DMA flag */ + ETH->DMASR = ETH_DMASR_RBUS; + /* Resume DMA reception */ + ETH->DMARPDR = 0; + } + return p; +} + + +/** +* This function is the ethernetif_input task, it is processed when a packet +* is ready to be read from the interface. It uses the function low_level_input() +* that should handle the actual reception of bytes from the network +* interface. Then the type of the received packet is determined and +* the appropriate input function is called. +* +* @param netif the lwip network interface structure for this ethernetif +*/ +void ethernetif_input( void * pvParameters ) +{ + struct pbuf *p; + + for( ;; ) + { + if (xSemaphoreTake( s_xSemaphore, emacBLOCK_TIME_WAITING_FOR_INPUT)==pdTRUE) + { +TRY_GET_NEXT_FRAME: + p = low_level_input( s_pxNetIf ); + if (p != NULL) + { + if (ERR_OK != s_pxNetIf->input( p, s_pxNetIf)) + { + pbuf_free(p); + } + else + { + goto TRY_GET_NEXT_FRAME; + } + } + + } + } +} +#endif +/** +* Should be called at the beginning of the program to set up the +* network interface. It calls the function low_level_init() to do the +* actual setup of the hardware. +* +* This function should be passed as a parameter to netif_add(). +* +* @param netif the lwip network interface structure for this ethernetif +* @return ERR_OK if the loopif is initialized +* ERR_MEM if private data couldn't be allocated +* any other err_t on error +*/ +err_t ethernetif_init(struct netif *netif) +{ + LWIP_ASSERT("netif != NULL", (netif != NULL)); + +#if !CONFIG_WLAN + /* ethernet */ + netif->name[0] = IFNAME0; + netif->name[1] = IFNAME1; +#else + /* wlan interface*/ +#if LWIP_NETIF_HOSTNAME + /* Initialize interface hostname */ + netif->hostname = "lwip"; +#endif /* LWIP_NETIF_HOSTNAME */ +#endif // WLAN + + netif->output = etharp_output; + netif->linkoutput = low_level_output; + + /* initialize the hardware */ + low_level_init(netif); + + etharp_init(); + sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); + + return ERR_OK; +} + + +static void arp_timer(void *arg) +{ + etharp_tmr(); + sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); +} + +/* + * For FreeRTOS tickless + */ +int lwip_tickless_used = 0; + +/* +int arp_timeout_exist(void) +{ + struct sys_timeouts *timeouts; + struct sys_timeo *t; + + timeouts = sys_arch_timeouts(); + + for(t = timeouts->next; t != NULL;t = t->next) + if(t->h == arp_timer) + return 1; + + return 0; +} +*/ +//Called by rltk_wlan_PRE_SLEEP_PROCESSING() +void lwip_PRE_SLEEP_PROCESSING(void) +{ + if(arp_timeout_exist()) { + tcpip_untimeout(arp_timer, NULL); + } + lwip_tickless_used = 1; +} + +//Called in ips_leave() path, support tickless when wifi power wakeup due to ioctl or deinit +void lwip_POST_SLEEP_PROCESSING(void) +{ + if(lwip_tickless_used) { + tcpip_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); + } +} + diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/freertos/ethernetif.c b/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/freertos/ethernetif.c new file mode 100644 index 0000000..719bbbd --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/freertos/ethernetif.c @@ -0,0 +1,656 @@ +/** +* @file +* Ethernet Interface Skeleton +* +*/ + +/* +* Copyright (c) 2001-2004 Swedish Institute of Computer Science. +* 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. The name of the author may not be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. +* +* This file is part of the lwIP TCP/IP stack. +* +* Author: Adam Dunkels +* +*/ + +/* +* This file is a skeleton for developing Ethernet network interface +* drivers for lwIP. Add code to the low_level functions and do a +* search-and-replace for the word "ethernetif" to replace it with +* something that better describes your network interface. +*/ + +#include "lwip/opt.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/sys.h" +#include "lwip/tcpip.h" +#include "lwip/icmp.h" +#include "lwip/lwip_timers.h" +#include "netif/etharp.h" +#include "err.h" +#include "ethernetif.h" +#include "queue.h" + +#include "lwip/ethip6.h" //Evan add for ipv6 + +#include "main.h" // for the definition of CONFIG_WLAN + + +#if !CONFIG_WLAN +#include "stm32f2x7_eth.h" +#else +#include +#endif +#include + +#include + +#ifdef CONFIG_DONT_CARE_TP +#define netifMTU (576) +#else +#define netifMTU (1500) +#endif +#define netifINTERFACE_TASK_STACK_SIZE ( 350 ) +#define netifINTERFACE_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) +#define netifGUARD_BLOCK_TIME ( 250 ) +/* The time to block waiting for input. */ +#define emacBLOCK_TIME_WAITING_FOR_INPUT ( ( portTickType ) 100 ) +#define FAKE_PING_REPLY 0 + +#if !CONFIG_WLAN +/* Define those to better describe your network interface. */ +#define IFNAME0 's' +#define IFNAME1 't' + +static struct netif *s_pxNetIf = NULL; +xSemaphoreHandle s_xSemaphore = NULL; + + +/* Ethernet Rx & Tx DMA Descriptors */ +extern ETH_DMADESCTypeDef DMARxDscrTab[ETH_RXBUFNB], DMATxDscrTab[ETH_TXBUFNB]; + +/* Ethernet Receive buffers */ +extern uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE]; + +/* Ethernet Transmit buffers */ +extern uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE]; + +/* Global pointers to track current transmit and receive descriptors */ +extern ETH_DMADESCTypeDef *DMATxDescToSet; +extern ETH_DMADESCTypeDef *DMARxDescToGet; + +/* Global pointer for last received frame infos */ +extern ETH_DMA_Rx_Frame_infos *DMA_RX_FRAME_infos; + +static void ethernetif_input( void * pvParameters ); +#endif + +static void arp_timer(void *arg); + + +/** +* In this function, the hardware should be initialized. +* Called from ethernetif_init(). +* +* @param netif the already initialized lwip network interface structure +* for this ethernetif +*/ +static void low_level_init(struct netif *netif) +{ + uint32_t i; + + /* set netif MAC hardware address length */ + netif->hwaddr_len = ETHARP_HWADDR_LEN; + +#if !CONFIG_WLAN + /* set netif MAC hardware address */ + netif->hwaddr[0] = MAC_ADDR0; + netif->hwaddr[1] = MAC_ADDR1; + netif->hwaddr[2] = MAC_ADDR2; + netif->hwaddr[3] = MAC_ADDR3; + netif->hwaddr[4] = MAC_ADDR4; + netif->hwaddr[5] = MAC_ADDR5; +#endif + + /* set netif maximum transfer unit */ + netif->mtu = netifMTU; + + /* Accept broadcast address and ARP traffic */ + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; + +#if !CONFIG_WLAN + s_pxNetIf =netif; + + /* create binary semaphore used for informing ethernetif of frame reception */ + if (s_xSemaphore == NULL) + { + s_xSemaphore= xSemaphoreCreateCounting(20,0); + } + + /* initialize MAC address in ethernet MAC */ + ETH_MACAddressConfig(ETH_MAC_Address0, netif->hwaddr); + + /* Initialize Tx Descriptors list: Chain Mode */ + ETH_DMATxDescChainInit(DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB); + /* Initialize Rx Descriptors list: Chain Mode */ + ETH_DMARxDescChainInit(DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB); + + /* Enable Ethernet Rx interrrupt */ + { + for(i=0; itot_len, PBUF_POOL); + if (p == NULL) { + printf("\n\rCannot allocate pbuf to receive packet"); + return; + } + for (tq = q, tp = p, q_len = tq->len; tp != NULL ; tp = tp->next) + { + p_len = tp->len; + while(p_len) + { + if(q_len > p_len) { + memcpy((char*)tq->payload + (tq->len - q_len), (char*)tp->payload + (tp->len - p_len), p_len); + q_len -= p_len; + p_len = 0; + }else{ + memcpy((char*)tq->payload + (tq->len - q_len), (char*)tp->payload + (tp->len - p_len), q_len); + p_len -= q_len; + tq = tq->next; + q_len = tq->len; + } + } + } + p_eth = (struct eth_hdr *)p->payload; + q_eth = (struct eth_hdr *)q->payload; + p_arp = (struct etharp_hdr *)((char*)(p->payload) + sizeof(struct eth_hdr)); + q_arp = (struct etharp_hdr *)((char*)(q->payload) + sizeof(struct eth_hdr)); + + q_eth->dest = p_eth->src; + q_eth->src = fake_src_mac; + q_arp->opcode = htons(ARP_REPLY); + q_arp->shwaddr = fake_src_mac; + q_arp->sipaddr = p_arp->dipaddr; + q_arp->dhwaddr = p_eth->src; + q_arp->dipaddr = p_arp->sipaddr; + + if(0){ + int i; + char *buf = q->payload; + printf("\n\r"); + for(i=0;itot_len;i++) + printf("0x%02x, ", buf[i]); + printf("\n\r"); + } + if (ERR_OK != netif->input(q, netif)){ + printf("\n\rfake_arp_reply input error"); + pbuf_free(q); + }else + printf("\n\rfake arp reply \n\r"); +} + +void fake_echo_reply(struct netif *netif, struct pbuf *p) +{ + struct pbuf *q, *tq, *tp; + int q_len, p_len; + struct eth_hdr *p_eth, *q_eth; + struct ip_hdr *p_ip, *q_ip; + struct icmp_echo_hdr *p_echo, *q_echo; + + // Allocate buffer to store received packet + q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_POOL); + if (p == NULL) { + printf("\n\rCannot allocate pbuf to receive packet"); + return; + } + for (tq = q, tp = p, q_len = tq->len; tp != NULL ; tp = tp->next) + { + p_len = tp->len; + while(p_len) + { + if(q_len > p_len) { + memcpy((char*)tq->payload + (tq->len - q_len), (char*)tp->payload + (tp->len - p_len), p_len); + q_len -= p_len; + p_len = 0; + }else{ + memcpy((char*)tq->payload + (tq->len - q_len), (char*)tp->payload + (tp->len - p_len), q_len); + p_len -= q_len; + tq = tq->next; + q_len = tq->len; + } + } + } + p_eth = (struct eth_hdr *)p->payload; + q_eth = (struct eth_hdr *)q->payload; + p_ip = (struct ip_hdr *)((char*)(p->payload) + sizeof(struct eth_hdr)); + q_ip = (struct ip_hdr *)((char*)(q->payload) + sizeof(struct eth_hdr)); + p_echo = (struct icmp_echo_hdr *)((char*)(p->payload) + sizeof(struct eth_hdr) + sizeof(struct ip_hdr)); + q_echo = (struct icmp_echo_hdr *)((char*)(q->payload) + sizeof(struct eth_hdr) + sizeof(struct ip_hdr)); + + q_eth->dest = p_eth->src; + q_eth->src = p_eth->dest; + q_ip->src.addr = p_ip->dest.addr; + q_ip->dest.addr = p_ip->src.addr; + q_ip->_chksum = 0; + q_ip->_chksum = inet_chksum(q_ip, sizeof(struct ip_hdr)); + q_echo->type = ICMP_ER; + q_echo->code = 0; + q_echo->chksum = 0; + q_echo->chksum = inet_chksum(q_echo, q->tot_len - sizeof(struct eth_hdr) - sizeof(struct ip_hdr)); + + if(0){ + int i; + char *buf = q->payload; + printf("\n\r"); + for(i=0;itot_len;i++) + printf("0x%02x, ", buf[i]); + printf("\n\r"); + } + if (ERR_OK != netif->input(q, netif)){ + printf("\n\rfake_echo_reply input error"); + pbuf_free(q); + }else + printf("\n\rfake echo reply \n\r"); +} +#endif // #if FAKE_PING_REPLY + +/** +* This function should do the actual transmission of the packet. The packet is +* contained in the pbuf that is passed to the function. This pbuf +* might be chained. +* +* @param netif the lwip network interface structure for this ethernetif +* @param p the MAC packet to send (e.g. IP packet including MAC addresses and type) +* @return ERR_OK if the packet could be sent +* an err_t value if the packet couldn't be sent +* +* @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to +* strange results. You might consider waiting for space in the DMA queue +* to become availale since the stack doesn't retry to send a packet +* dropped because of memory failure (except for the TCP timers). +*/ + +static err_t low_level_output(struct netif *netif, struct pbuf *p) +{ +#if !CONFIG_WLAN + static xSemaphoreHandle xTxSemaphore = NULL; + struct pbuf *q; + uint32_t l = 0; + u8 *buffer ; + + if (xTxSemaphore == NULL) + { + vSemaphoreCreateBinary (xTxSemaphore); + } + + if (xSemaphoreTake(xTxSemaphore, netifGUARD_BLOCK_TIME)) + { + buffer = (u8 *)(DMATxDescToSet->Buffer1Addr); + for(q = p; q != NULL; q = q->next) + { + memcpy((u8_t*)&buffer[l], q->payload, q->len); + l = l + q->len; + } + ETH_Prepare_Transmit_Descriptors(l); + xSemaphoreGive(xTxSemaphore); + } +#else + /* Refer to eCos lwip eth_drv_send() */ + struct eth_drv_sg sg_list[MAX_ETH_DRV_SG]; + int sg_len = 0; + struct pbuf *q; + + if(!rltk_wlan_running(netif_get_idx(netif))) + return ERR_IF; + + for (q = p; q != NULL && sg_len < MAX_ETH_DRV_SG; q = q->next) { + sg_list[sg_len].buf = (unsigned int) q->payload; + sg_list[sg_len++].len = q->len; + } + +#if FAKE_PING_REPLY + { + char *header = p->payload; + if(header[12] == 0x08 && header[13] == 0x06) + { // arp packet + if(header[21] == 0x01) + { // arp request packet + printf("\n\rfake_ping: arp request packet."); + if(0) + { + int i; + printf("\n\r"); + for (q = p; q != NULL; q = q->next) + { + char *buf = q->payload; + for(i=0;ilen;i++) + printf("0x%02x, ", buf[i]); + } + printf("\n\r"); + } + fake_arp_reply(netif, p); + return ERR_OK; + } + }else if(header[12] == 0x08 && header[13] == 0x00) + { // ip packet + if(header[15] == 0x00 && header[23] == 0x01) + { // icmp packet + printf("\n\rfake_ping: icmp packet."); + if(0){ + int i; + printf("\n\r"); + for (q = p; q != NULL; q = q->next) + { + char *buf = q->payload; + for(i=0;ilen;i++) + printf("0x%02x, ", buf[i]); + } + printf("\n\r"); + } + fake_echo_reply(netif, p); + return ERR_OK; + } + } + } +#endif // #if FAKE_PING_REPLY + if (sg_len) + rltk_wlan_send(netif_get_idx(netif), sg_list, sg_len, p->tot_len); +#endif // #if !CONFIG_WLAN + + return ERR_OK; +} + + +#if !CONFIG_WLAN +/** +* Should allocate a pbuf and transfer the bytes of the incoming +* packet from the interface into the pbuf. +* +* @param netif the lwip network interface structure for this ethernetif +* @return a pbuf filled with the received packet (including MAC header) +* NULL on memory error +*/ +static struct pbuf * low_level_input(struct netif *netif) +{ + struct pbuf *p, *q; + u16_t len; + uint32_t l=0,i =0; + FrameTypeDef frame; + u8 *buffer; + __IO ETH_DMADESCTypeDef *DMARxNextDesc; + + p = NULL; + + /* Get received frame */ + frame = ETH_Get_Received_Frame_interrupt(); + + /* check that frame has no error */ + if ((frame.descriptor->Status & ETH_DMARxDesc_ES) == (uint32_t)RESET) + { + + /* Obtain the size of the packet and put it into the "len" variable. */ + len = frame.length; + buffer = (u8 *)frame.buffer; + + /* We allocate a pbuf chain of pbufs from the pool. */ + p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); + + /* Copy received frame from ethernet driver buffer to stack buffer */ + if (p != NULL) + { + for (q = p; q != NULL; q = q->next) + { + memcpy((u8_t*)q->payload, (u8_t*)&buffer[l], q->len); + l = l + q->len; + } + } + } + + /* Release descriptors to DMA */ + /* Check if received frame with multiple DMA buffer segments */ + if (DMA_RX_FRAME_infos->Seg_Count > 1) + { + DMARxNextDesc = DMA_RX_FRAME_infos->FS_Rx_Desc; + } + else + { + DMARxNextDesc = frame.descriptor; + } + + /* Set Own bit in Rx descriptors: gives the buffers back to DMA */ + for (i=0; iSeg_Count; i++) + { + DMARxNextDesc->Status = ETH_DMARxDesc_OWN; + DMARxNextDesc = (ETH_DMADESCTypeDef *)(DMARxNextDesc->Buffer2NextDescAddr); + } + + /* Clear Segment_Count */ + DMA_RX_FRAME_infos->Seg_Count =0; + + + /* When Rx Buffer unavailable flag is set: clear it and resume reception */ + if ((ETH->DMASR & ETH_DMASR_RBUS) != (u32)RESET) + { + /* Clear RBUS ETHERNET DMA flag */ + ETH->DMASR = ETH_DMASR_RBUS; + + /* Resume DMA reception */ + ETH->DMARPDR = 0; + } + return p; +} + + +/** +* This function is the ethernetif_input task, it is processed when a packet +* is ready to be read from the interface. It uses the function low_level_input() +* that should handle the actual reception of bytes from the network +* interface. Then the type of the received packet is determined and +* the appropriate input function is called. +* +* @param netif the lwip network interface structure for this ethernetif +*/ +void ethernetif_input( void * pvParameters ) +{ + struct pbuf *p; + + for( ;; ) + { + if (xSemaphoreTake( s_xSemaphore, emacBLOCK_TIME_WAITING_FOR_INPUT)==pdTRUE) + { + p = low_level_input( s_pxNetIf ); + if (ERR_OK != s_pxNetIf->input( p, s_pxNetIf)) + { + pbuf_free(p); + p=NULL; + } + } + } +} +#endif + +/* Refer to eCos eth_drv_recv to do similarly in ethernetif_input */ +void ethernetif_recv(struct netif *netif, int total_len) +{ +#if CONFIG_WLAN + struct eth_drv_sg sg_list[MAX_ETH_DRV_SG]; + struct pbuf *p, *q; + int sg_len = 0; + + if(!rltk_wlan_running(netif_get_idx(netif))) + return; + + if ((total_len > MAX_ETH_MSG) || (total_len < 0)) + total_len = MAX_ETH_MSG; + + // Allocate buffer to store received packet + p = pbuf_alloc(PBUF_RAW, total_len, PBUF_POOL); + if (p == NULL) { + printf("\n\rCannot allocate pbuf to receive packet"); + return; + } + + // Create scatter list + for (q = p; q != NULL && sg_len < MAX_ETH_DRV_SG; q = q->next) { + sg_list[sg_len].buf = (unsigned int) q->payload; + sg_list[sg_len++].len = q->len; + } + + // Copy received packet to scatter list from wrapper rx skb + //printf("\n\rwlan:%c: Recv sg_len: %d, tot_len:%d", netif->name[1],sg_len, total_len); + rltk_wlan_recv(netif_get_idx(netif), sg_list, sg_len); + + // Pass received packet to the interface + if (ERR_OK != netif->input(p, netif)) + pbuf_free(p); +#endif +} + +/** +* Should be called at the beginning of the program to set up the +* network interface. It calls the function low_level_init() to do the +* actual setup of the hardware. +* +* This function should be passed as a parameter to netif_add(). +* +* @param netif the lwip network interface structure for this ethernetif +* @return ERR_OK if the loopif is initialized +* ERR_MEM if private data couldn't be allocated +* any other err_t on error +*/ +err_t ethernetif_init(struct netif *netif) +{ + LWIP_ASSERT("netif != NULL", (netif != NULL)); + +#if !CONFIG_WLAN + /* ethernet */ + netif->name[0] = IFNAME0; + netif->name[1] = IFNAME1; +#else + /* wlan interface*/ +#if LWIP_NETIF_HOSTNAME + /* Initialize interface hostname */ + if(netif->name[1] == '0') + netif->hostname = "lwip0"; + else if(netif->name[1] == '1') + netif->hostname = "lwip1"; +#endif /* LWIP_NETIF_HOSTNAME */ + +#endif // WLAN + + netif->output = etharp_output; + netif->output_ip6 = ethip6_output ;//Evan add for ipv6 + netif->linkoutput = low_level_output; + + /* initialize the hardware */ + low_level_init(netif); + + etharp_init(); + sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); + + return ERR_OK; +} + + +static void arp_timer(void *arg) +{ + etharp_tmr(); + sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); +} + +/* + * For FreeRTOS tickless + */ +int lwip_tickless_used = 0; + + +int arp_timeout_exist(void) +{ + struct sys_timeouts *timeouts; + struct sys_timeo *t; + + timeouts = sys_arch_timeouts(); + + for(t = timeouts->next; t != NULL;t = t->next) + if(t->h == arp_timer) + return 1; + + return 0; +} + +//Called by rltk_wlan_PRE_SLEEP_PROCESSING() +void lwip_PRE_SLEEP_PROCESSING(void) +{ + if(arp_timeout_exist()) { + tcpip_untimeout(arp_timer, NULL); + } + lwip_tickless_used = 1; +} + +//Called in ips_leave() path, support tickless when wifi power wakeup due to ioctl or deinit +void lwip_POST_SLEEP_PROCESSING(void) +{ + if(lwip_tickless_used) { + tcpip_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); + } +} diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/freertos/ethernetif.h b/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/freertos/ethernetif.h new file mode 100644 index 0000000..93139d1 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/freertos/ethernetif.h @@ -0,0 +1,13 @@ +#ifndef __ETHERNETIF_H__ +#define __ETHERNETIF_H__ + + +#include "lwip/err.h" +#include "lwip/netif.h" + +void ethernetif_recv(struct netif *netif, int total_len); +err_t ethernetif_init(struct netif *netif); +void lwip_PRE_SLEEP_PROCESSING(void); +void lwip_POST_SLEEP_PROCESSING(void); + +#endif diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/freertos/sys_arch.c b/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/freertos/sys_arch.c new file mode 100644 index 0000000..3d111c6 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/freertos/sys_arch.c @@ -0,0 +1,515 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/* lwIP includes. */ +#include "lwip/debug.h" +#include "lwip/def.h" +#include "lwip/sys.h" +#include "lwip/mem.h" +#include "lwip/stats.h" +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "lwip/lwip_timers.h" + +xTaskHandle xTaskGetCurrentTaskHandle( void ) PRIVILEGED_FUNCTION; + +struct timeoutlist +{ + struct sys_timeouts timeouts; + xTaskHandle pid; +}; + +/* This is the number of threads that can be started with sys_thread_new() */ +#define SYS_THREAD_MAX 6 + +static struct timeoutlist s_timeoutlist[SYS_THREAD_MAX]; +static u16_t s_nextthread = 0; + + +/*-----------------------------------------------------------------------------------*/ +// Creates an empty mailbox. +err_t sys_mbox_new(sys_mbox_t *mbox, int size) +{ + (void ) size; + + *mbox = xQueueCreate( archMESG_QUEUE_LENGTH, sizeof( void * ) ); + +#if SYS_STATS + ++lwip_stats.sys.mbox.used; + if (lwip_stats.sys.mbox.max < lwip_stats.sys.mbox.used) { + lwip_stats.sys.mbox.max = lwip_stats.sys.mbox.used; + } +#endif /* SYS_STATS */ + if (*mbox == NULL) + return ERR_MEM; + + return ERR_OK; +} + +/*-----------------------------------------------------------------------------------*/ +/* + Deallocates a mailbox. If there are messages still present in the + mailbox when the mailbox is deallocated, it is an indication of a + programming error in lwIP and the developer should be notified. +*/ +void sys_mbox_free(sys_mbox_t *mbox) +{ + if( uxQueueMessagesWaiting( *mbox ) ) + { + /* Line for breakpoint. Should never break here! */ + portNOP(); +#if SYS_STATS + lwip_stats.sys.mbox.err++; +#endif /* SYS_STATS */ + + // TODO notify the user of failure. + } + + vQueueDelete( *mbox ); + +#if SYS_STATS + --lwip_stats.sys.mbox.used; +#endif /* SYS_STATS */ +} + +/*-----------------------------------------------------------------------------------*/ +// Posts the "msg" to the mailbox. +void sys_mbox_post(sys_mbox_t *mbox, void *data) +{ + while ( xQueueSendToBack(*mbox, &data, portMAX_DELAY ) != pdTRUE ){} +} + + +/*-----------------------------------------------------------------------------------*/ +// Try to post the "msg" to the mailbox. +err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) +{ +err_t result; + + if ( xQueueSend( *mbox, &msg, 0 ) == pdPASS ) + { + result = ERR_OK; + } + else { + // could not post, queue must be full + result = ERR_MEM; + +#if SYS_STATS + lwip_stats.sys.mbox.err++; +#endif /* SYS_STATS */ + + } + + return result; +} + +/*-----------------------------------------------------------------------------------*/ +/* + Blocks the thread until a message arrives in the mailbox, but does + not block the thread longer than "timeout" milliseconds (similar to + the sys_arch_sem_wait() function). The "msg" argument is a result + parameter that is set by the function (i.e., by doing "*msg = + ptr"). The "msg" parameter maybe NULL to indicate that the message + should be dropped. + + The return values are the same as for the sys_arch_sem_wait() function: + Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a + timeout. + + Note that a function with a similar name, sys_mbox_fetch(), is + implemented by lwIP. +*/ +u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout) +{ +void *dummyptr; +portTickType StartTime, EndTime, Elapsed; + + StartTime = xTaskGetTickCount(); + + if ( msg == NULL ) + { + msg = &dummyptr; + } + + if ( timeout != 0 ) + { + if ( pdTRUE == xQueueReceive( *mbox, &(*msg), timeout / portTICK_RATE_MS ) ) + { + EndTime = xTaskGetTickCount(); + Elapsed = (EndTime - StartTime) * portTICK_RATE_MS; + + return ( Elapsed ); + } + else // timed out blocking for message + { + *msg = NULL; + + return SYS_ARCH_TIMEOUT; + } + } + else // block forever for a message. + { + while( pdTRUE != xQueueReceive( *mbox, &(*msg), portMAX_DELAY ) ){} // time is arbitrary + EndTime = xTaskGetTickCount(); + Elapsed = (EndTime - StartTime) * portTICK_RATE_MS; + + return ( Elapsed ); // return time blocked TODO test + } +} + +/*-----------------------------------------------------------------------------------*/ +/* + Similar to sys_arch_mbox_fetch, but if message is not ready immediately, we'll + return with SYS_MBOX_EMPTY. On success, 0 is returned. +*/ +u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg) +{ +void *dummyptr; + + if ( msg == NULL ) + { + msg = &dummyptr; + } + + if ( pdTRUE == xQueueReceive( *mbox, &(*msg), 0 ) ) + { + return ERR_OK; + } + else + { + return SYS_MBOX_EMPTY; + } +} +/*----------------------------------------------------------------------------------*/ +int sys_mbox_valid(sys_mbox_t *mbox) +{ + if (*mbox == SYS_MBOX_NULL) + return 0; + else + return 1; +} +/*-----------------------------------------------------------------------------------*/ +void sys_mbox_set_invalid(sys_mbox_t *mbox) +{ + *mbox = SYS_MBOX_NULL; +} + +/*-----------------------------------------------------------------------------------*/ +// Creates a new semaphore. The "count" argument specifies +// the initial state of the semaphore. +err_t sys_sem_new(sys_sem_t *sem, u8_t count) +{ + vSemaphoreCreateBinary(*sem ); + if(*sem == NULL) + { +#if SYS_STATS + ++lwip_stats.sys.sem.err; +#endif /* SYS_STATS */ + return ERR_MEM; + } + + if(count == 0) // Means it can't be taken + { + xSemaphoreTake(*sem,1); + } + +#if SYS_STATS + ++lwip_stats.sys.sem.used; + if (lwip_stats.sys.sem.max < lwip_stats.sys.sem.used) { + lwip_stats.sys.sem.max = lwip_stats.sys.sem.used; + } +#endif /* SYS_STATS */ + + return ERR_OK; +} + +/*-----------------------------------------------------------------------------------*/ +/* + Blocks the thread while waiting for the semaphore to be + signaled. If the "timeout" argument is non-zero, the thread should + only be blocked for the specified time (measured in + milliseconds). + + If the timeout argument is non-zero, the return value is the number of + milliseconds spent waiting for the semaphore to be signaled. If the + semaphore wasn't signaled within the specified time, the return value is + SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore + (i.e., it was already signaled), the function may return zero. + + Notice that lwIP implements a function with a similar name, + sys_sem_wait(), that uses the sys_arch_sem_wait() function. +*/ +u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) +{ +portTickType StartTime, EndTime, Elapsed; + + StartTime = xTaskGetTickCount(); + + if( timeout != 0) + { + if( xSemaphoreTake( *sem, timeout / portTICK_RATE_MS ) == pdTRUE ) + { + EndTime = xTaskGetTickCount(); + Elapsed = (EndTime - StartTime) * portTICK_RATE_MS; + + return (Elapsed); // return time blocked TODO test + } + else + { + return SYS_ARCH_TIMEOUT; + } + } + else // must block without a timeout + { + while( xSemaphoreTake(*sem, portMAX_DELAY) != pdTRUE){} + EndTime = xTaskGetTickCount(); + Elapsed = (EndTime - StartTime) * portTICK_RATE_MS; + + return ( Elapsed ); // return time blocked + + } +} + +/*-----------------------------------------------------------------------------------*/ +// Signals a semaphore +void sys_sem_signal(sys_sem_t *sem) +{ + xSemaphoreGive(*sem); +} + +/*-----------------------------------------------------------------------------------*/ +// Deallocates a semaphore +void sys_sem_free(sys_sem_t *sem) +{ +#if SYS_STATS + --lwip_stats.sys.sem.used; +#endif /* SYS_STATS */ + + vQueueDelete(*sem); +} +/*-----------------------------------------------------------------------------------*/ +int sys_sem_valid(sys_sem_t *sem) +{ + if (*sem == SYS_SEM_NULL) + return 0; + else + return 1; +} + +/*-----------------------------------------------------------------------------------*/ +void sys_sem_set_invalid(sys_sem_t *sem) +{ + *sem = SYS_SEM_NULL; +} + +/*-----------------------------------------------------------------------------------*/ +// Initialize sys arch +void sys_init(void) +{ + int i; + + // Initialize the the per-thread sys_timeouts structures + // make sure there are no valid pids in the list + for(i = 0; i < SYS_THREAD_MAX; i++) + { + s_timeoutlist[i].pid = 0; + s_timeoutlist[i].timeouts.next = NULL; + } + + // keep track of how many threads have been created + s_nextthread = 0; +} + +/* + Returns a pointer to the per-thread sys_timeouts structure. In lwIP, + each thread has a list of timeouts which is represented as a linked + list of sys_timeout structures. The sys_timeouts structure holds a + pointer to a linked list of timeouts. This function is called by + the lwIP timeout scheduler and must not return a NULL value. + + In a single threaded sys_arch implementation, this function will + simply return a pointer to a global sys_timeouts variable stored in + the sys_arch module. +*/ +struct sys_timeouts* sys_arch_timeouts(void) +{ +int i; +xTaskHandle pid; +struct timeoutlist *tl; + + pid = xTaskGetCurrentTaskHandle(); + + for(i = 0; i < s_nextthread; i++) + { + tl = &(s_timeoutlist[i]); + if(tl->pid == pid) + { + return &(tl->timeouts); + } + } + // Error + return NULL; +} +/*-----------------------------------------------------------------------------------*/ + /* Mutexes*/ +/*-----------------------------------------------------------------------------------*/ +/*-----------------------------------------------------------------------------------*/ +#if LWIP_COMPAT_MUTEX == 0 +/* Create a new mutex*/ +err_t sys_mutex_new(sys_mutex_t *mutex) { + + *mutex = xSemaphoreCreateMutex(); + if(*mutex == NULL) + { +#if SYS_STATS + ++lwip_stats.sys.mutex.err; +#endif /* SYS_STATS */ + return ERR_MEM; + } + +#if SYS_STATS + ++lwip_stats.sys.mutex.used; + if (lwip_stats.sys.mutex.max < lwip_stats.sys.mutex.used) { + lwip_stats.sys.mutex.max = lwip_stats.sys.mutex.used; + } +#endif /* SYS_STATS */ + return ERR_OK; +} +/*-----------------------------------------------------------------------------------*/ +/* Deallocate a mutex*/ +void sys_mutex_free(sys_mutex_t *mutex) +{ +#if SYS_STATS + --lwip_stats.sys.mutex.used; +#endif /* SYS_STATS */ + + vQueueDelete(*mutex); +} +/*-----------------------------------------------------------------------------------*/ +/* Lock a mutex*/ +void sys_mutex_lock(sys_mutex_t *mutex) +{ + sys_arch_sem_wait(*mutex, 0); +} + +/*-----------------------------------------------------------------------------------*/ +/* Unlock a mutex*/ +void sys_mutex_unlock(sys_mutex_t *mutex) +{ + xSemaphoreGive(*mutex); +} +#endif /*LWIP_COMPAT_MUTEX*/ +/*-----------------------------------------------------------------------------------*/ +// TODO +/*-----------------------------------------------------------------------------------*/ +/* + Starts a new thread with priority "prio" that will begin its execution in the + function "thread()". The "arg" argument will be passed as an argument to the + thread() function. The id of the new thread is returned. Both the id and + the priority are system dependent. +*/ +sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread , void *arg, int stacksize, int prio) +{ +xTaskHandle CreatedTask; +int result; + + if ( s_nextthread < SYS_THREAD_MAX ) + { + vPortEnterCritical(); + result = xTaskCreate( thread, ( signed portCHAR * ) name, stacksize, arg, prio, &CreatedTask ); + + // For each task created, store the task handle (pid) in the timers array. + // This scheme doesn't allow for threads to be deleted + s_timeoutlist[s_nextthread++].pid = CreatedTask; + vPortExitCritical(); + + if(result == pdPASS) + { + return CreatedTask; + } + else + { + return NULL; + } + } + else + { + return NULL; + } +} + +/* + This optional function does a "fast" critical region protection and returns + the previous protection level. This function is only called during very short + critical regions. An embedded system which supports ISR-based drivers might + want to implement this function by disabling interrupts. Task-based systems + might want to implement this by using a mutex or disabling tasking. This + function should support recursive calls from the same task or interrupt. In + other words, sys_arch_protect() could be called while already protected. In + that case the return value indicates that it is already protected. + + sys_arch_protect() is only required if your port is supporting an operating + system. +*/ +sys_prot_t sys_arch_protect(void) +{ + vPortEnterCritical(); + return 1; +} + +/* + This optional function does a "fast" set of critical region protection to the + value specified by pval. See the documentation for sys_arch_protect() for + more information. This function is only required if your port is supporting + an operating system. +*/ +void sys_arch_unprotect(sys_prot_t pval) +{ + ( void ) pval; + vPortExitCritical(); +} + +/* + * Prints an assertion messages and aborts execution. + */ +void sys_assert( const char *msg ) +{ + ( void ) msg; + /*FSL:only needed for debugging + printf(msg); + printf("\n\r"); + */ + vPortEnterCritical( ); + for(;;) + ; +} diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/freertos/sys_arch.h b/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/freertos/sys_arch.h new file mode 100644 index 0000000..83d0c08 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/freertos/sys_arch.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __SYS_RTXC_H__ +#define __SYS_RTXC_H__ + +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "semphr.h" + +#define SYS_MBOX_NULL (xQueueHandle)0 +#define SYS_SEM_NULL (xSemaphoreHandle)0 +#define SYS_DEFAULT_THREAD_STACK_DEPTH configMINIMAL_STACK_SIZE + +typedef xSemaphoreHandle sys_sem_t; +typedef xQueueHandle sys_mbox_t; +typedef xTaskHandle sys_thread_t; + +typedef struct _sys_arch_state_t +{ + // Task creation data. + char cTaskName[configMAX_TASK_NAME_LEN]; + unsigned short nStackDepth; + unsigned short nTaskCount; +} sys_arch_state_t; + + + +//extern sys_arch_state_t s_sys_arch_state; + +//void sys_set_default_state(); +//void sys_set_state(signed char *pTaskName, unsigned short nStackSize); + +/* Message queue constants. */ +#define archMESG_QUEUE_LENGTH ( 6 ) +#endif /* __SYS_RTXC_H__ */ + diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/standalone/ethernetif.c b/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/standalone/ethernetif.c new file mode 100644 index 0000000..f3b74ee --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/standalone/ethernetif.c @@ -0,0 +1,366 @@ +/** + * @file + * Ethernet Interface for standalone applications (without RTOS) - works only for + * ethernet polling mode (polling for ethernet frame reception) + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" +#include "lwip/mem.h" +#include "netif/etharp.h" +#include "ethernetif.h" +#include "stm32f2x7_eth.h" +#include "main.h" +#include + +/* Network interface name */ +#define IFNAME0 's' +#define IFNAME1 't' + + +/* Ethernet Rx & Tx DMA Descriptors */ +extern ETH_DMADESCTypeDef DMARxDscrTab[ETH_RXBUFNB], DMATxDscrTab[ETH_TXBUFNB]; + +/* Ethernet Driver Receive buffers */ +extern uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE]; + +/* Ethernet Driver Transmit buffers */ +extern uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE]; + +/* Global pointers to track current transmit and receive descriptors */ +extern ETH_DMADESCTypeDef *DMATxDescToSet; +extern ETH_DMADESCTypeDef *DMARxDescToGet; + +/* Global pointer for last received frame infos */ +extern ETH_DMA_Rx_Frame_infos *DMA_RX_FRAME_infos; + +/** + * In this function, the hardware should be initialized. + * Called from ethernetif_init(). + * + * @param netif the already initialized lwip network interface structure + * for this ethernetif + */ +static void low_level_init(struct netif *netif) +{ +#ifdef CHECKSUM_BY_HARDWARE + int i; +#endif + /* set MAC hardware address length */ + netif->hwaddr_len = ETHARP_HWADDR_LEN; + + /* set MAC hardware address */ + netif->hwaddr[0] = MAC_ADDR0; + netif->hwaddr[1] = MAC_ADDR1; + netif->hwaddr[2] = MAC_ADDR2; + netif->hwaddr[3] = MAC_ADDR3; + netif->hwaddr[4] = MAC_ADDR4; + netif->hwaddr[5] = MAC_ADDR5; + + /* initialize MAC address in ethernet MAC */ + ETH_MACAddressConfig(ETH_MAC_Address0, netif->hwaddr); + + /* maximum transfer unit */ + netif->mtu = 1500; + + /* device capabilities */ + /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; + + /* Initialize Tx Descriptors list: Chain Mode */ + ETH_DMATxDescChainInit(DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB); + /* Initialize Rx Descriptors list: Chain Mode */ + ETH_DMARxDescChainInit(DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB); + +#ifdef CHECKSUM_BY_HARDWARE + /* Enable the TCP, UDP and ICMP checksum insertion for the Tx frames */ + for(i=0; iBuffer1Addr); + __IO ETH_DMADESCTypeDef *DmaTxDesc; + uint16_t framelength = 0; + uint32_t bufferoffset = 0; + uint32_t byteslefttocopy = 0; + uint32_t payloadoffset = 0; + + DmaTxDesc = DMATxDescToSet; + bufferoffset = 0; + + /* copy frame from pbufs to driver buffers */ + for(q = p; q != NULL; q = q->next) + { + /* Is this buffer available? If not, goto error */ + if((DmaTxDesc->Status & ETH_DMATxDesc_OWN) != (u32)RESET) + { + errval = ERR_BUF; + goto error; + } + + /* Get bytes in current lwIP buffer */ + byteslefttocopy = q->len; + payloadoffset = 0; + + /* Check if the length of data to copy is bigger than Tx buffer size*/ + while( (byteslefttocopy + bufferoffset) > ETH_TX_BUF_SIZE ) + { + /* Copy data to Tx buffer*/ + memcpy( (u8_t*)((u8_t*)buffer + bufferoffset), (u8_t*)((u8_t*)q->payload + payloadoffset), (ETH_TX_BUF_SIZE - bufferoffset) ); + + /* Point to next descriptor */ + DmaTxDesc = (ETH_DMADESCTypeDef *)(DmaTxDesc->Buffer2NextDescAddr); + + /* Check if the buffer is available */ + if((DmaTxDesc->Status & ETH_DMATxDesc_OWN) != (u32)RESET) + { + errval = ERR_USE; + goto error; + } + + buffer = (u8 *)(DmaTxDesc->Buffer1Addr); + + byteslefttocopy = byteslefttocopy - (ETH_TX_BUF_SIZE - bufferoffset); + payloadoffset = payloadoffset + (ETH_TX_BUF_SIZE - bufferoffset); + framelength = framelength + (ETH_TX_BUF_SIZE - bufferoffset); + bufferoffset = 0; + } + + /* Copy the remaining bytes */ + memcpy( (u8_t*)((u8_t*)buffer + bufferoffset), (u8_t*)((u8_t*)q->payload + payloadoffset), byteslefttocopy ); + bufferoffset = bufferoffset + byteslefttocopy; + framelength = framelength + byteslefttocopy; + } + + /* Note: padding and CRC for transmitted frame + are automatically inserted by DMA */ + + /* Prepare transmit descriptors to give to DMA*/ + ETH_Prepare_Transmit_Descriptors(framelength); + + errval = ERR_OK; + +error: + + /* When Transmit Underflow flag is set, clear it and issue a Transmit Poll Demand to resume transmission */ + if ((ETH->DMASR & ETH_DMASR_TUS) != (uint32_t)RESET) + { + /* Clear TUS ETHERNET DMA flag */ + ETH->DMASR = ETH_DMASR_TUS; + + /* Resume DMA transmission*/ + ETH->DMATPDR = 0; + } + return errval; +} + +/** + * Should allocate a pbuf and transfer the bytes of the incoming + * packet from the interface into the pbuf. + * + * @param netif the lwip network interface structure for this ethernetif + * @return a pbuf filled with the received packet (including MAC header) + * NULL on memory error + */ +static struct pbuf * low_level_input(struct netif *netif) +{ + struct pbuf *p, *q; + uint32_t len; + FrameTypeDef frame; + u8 *buffer; + __IO ETH_DMADESCTypeDef *DMARxDesc; + uint32_t bufferoffset = 0; + uint32_t payloadoffset = 0; + uint32_t byteslefttocopy = 0; + uint32_t i=0; + + /* get received frame */ + frame = ETH_Get_Received_Frame(); + + /* Obtain the size of the packet and put it into the "len" variable. */ + len = frame.length; + buffer = (u8 *)frame.buffer; + + /* We allocate a pbuf chain of pbufs from the Lwip buffer pool */ + p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); + + if (p != NULL) + { + DMARxDesc = frame.descriptor; + bufferoffset = 0; + for(q = p; q != NULL; q = q->next) + { + byteslefttocopy = q->len; + payloadoffset = 0; + + /* Check if the length of bytes to copy in current pbuf is bigger than Rx buffer size*/ + while( (byteslefttocopy + bufferoffset) > ETH_RX_BUF_SIZE ) + { + /* Copy data to pbuf*/ + memcpy( (u8_t*)((u8_t*)q->payload + payloadoffset), (u8_t*)((u8_t*)buffer + bufferoffset), (ETH_RX_BUF_SIZE - bufferoffset)); + + /* Point to next descriptor */ + DMARxDesc = (ETH_DMADESCTypeDef *)(DMARxDesc->Buffer2NextDescAddr); + buffer = (unsigned char *)(DMARxDesc->Buffer1Addr); + + byteslefttocopy = byteslefttocopy - (ETH_RX_BUF_SIZE - bufferoffset); + payloadoffset = payloadoffset + (ETH_RX_BUF_SIZE - bufferoffset); + bufferoffset = 0; + } + /* Copy remaining data in pbuf */ + memcpy( (u8_t*)((u8_t*)q->payload + payloadoffset), (u8_t*)((u8_t*)buffer + bufferoffset), byteslefttocopy); + bufferoffset = bufferoffset + byteslefttocopy; + } + } + + /* Release descriptors to DMA */ + DMARxDesc =frame.descriptor; + + /* Set Own bit in Rx descriptors: gives the buffers back to DMA */ + for (i=0; iSeg_Count; i++) + { + DMARxDesc->Status = ETH_DMARxDesc_OWN; + DMARxDesc = (ETH_DMADESCTypeDef *)(DMARxDesc->Buffer2NextDescAddr); + } + + /* Clear Segment_Count */ + DMA_RX_FRAME_infos->Seg_Count =0; + + /* When Rx Buffer unavailable flag is set: clear it and resume reception */ + if ((ETH->DMASR & ETH_DMASR_RBUS) != (u32)RESET) + { + /* Clear RBUS ETHERNET DMA flag */ + ETH->DMASR = ETH_DMASR_RBUS; + /* Resume DMA reception */ + ETH->DMARPDR = 0; + } + return p; +} + +/** + * This function should be called when a packet is ready to be read + * from the interface. It uses the function low_level_input() that + * should handle the actual reception of bytes from the network + * interface. Then the type of the received packet is determined and + * the appropriate input function is called. + * + * @param netif the lwip network interface structure for this ethernetif + */ +err_t ethernetif_input(struct netif *netif) +{ + err_t err; + struct pbuf *p; + + /* move received packet into a new pbuf */ + p = low_level_input(netif); + + /* no packet could be read, silently ignore this */ + if (p == NULL) return ERR_MEM; + + /* entry point to the LwIP stack */ + err = netif->input(p, netif); + + if (err != ERR_OK) + { + LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); + pbuf_free(p); + } + return err; +} + +/** + * Should be called at the beginning of the program to set up the + * network interface. It calls the function low_level_init() to do the + * actual setup of the hardware. + * + * This function should be passed as a parameter to netif_add(). + * + * @param netif the lwip network interface structure for this ethernetif + * @return ERR_OK if the loopif is initialized + * ERR_MEM if private data couldn't be allocated + * any other err_t on error + */ +err_t ethernetif_init(struct netif *netif) +{ + LWIP_ASSERT("netif != NULL", (netif != NULL)); + +#if LWIP_NETIF_HOSTNAME + /* Initialize interface hostname */ + netif->hostname = "lwip"; +#endif /* LWIP_NETIF_HOSTNAME */ + + netif->name[0] = IFNAME0; + netif->name[1] = IFNAME1; + /* We directly use etharp_output() here to save a function call. + * You can instead declare your own function an call etharp_output() + * from it if you have to do some checks before sending (e.g. if link + * is available...) */ + netif->output = etharp_output; + netif->linkoutput = low_level_output; + + /* initialize the hardware */ + low_level_init(netif); + + return ERR_OK; +} \ No newline at end of file diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/standalone/ethernetif.h b/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/standalone/ethernetif.h new file mode 100644 index 0000000..9ff1408 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/port/stm32f2x7/standalone/ethernetif.h @@ -0,0 +1,11 @@ +#ifndef __ETHERNETIF_H__ +#define __ETHERNETIF_H__ + + +#include "lwip/err.h" +#include "lwip/netif.h" + +err_t ethernetif_init(struct netif *netif); +err_t ethernetif_input(struct netif *netif); + +#endif diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/FILES b/component/common/network/lwip/lwip_v1.5.0.beta/src/FILES new file mode 100644 index 0000000..952aeab --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/FILES @@ -0,0 +1,13 @@ +api/ - The code for the high-level wrapper API. Not needed if + you use the lowel-level call-back/raw API. + +core/ - The core of the TPC/IP stack; protocol implementations, + memory and buffer management, and the low-level raw API. + +include/ - lwIP include files. + +netif/ - Generic network interface device drivers are kept here, + as well as the ARP module. + +For more information on the various subdirectories, check the FILES +file in each directory. diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/api/api_lib.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/api/api_lib.c new file mode 100644 index 0000000..7791b56 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/api/api_lib.c @@ -0,0 +1,903 @@ +/** + * @file + * Sequential API External module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/* This is the part of the API that is linked with + the application */ + +#include "lwip/opt.h" + +#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/api.h" +#include "lwip/tcpip.h" +#include "lwip/memp.h" + +#include "lwip/lwip_ip.h" +#include "lwip/raw.h" +#include "lwip/udp.h" +#include "lwip/tcp.h" + +#include + +#define API_MSG_VAR_REF(name) API_VAR_REF(name) +#define API_MSG_VAR_DECLARE(name) API_VAR_DECLARE(struct api_msg, name) +#define API_MSG_VAR_ALLOC(name) API_VAR_ALLOC(struct api_msg, MEMP_API_MSG, name) +#define API_MSG_VAR_ALLOC_DONTFAIL(name) API_VAR_ALLOC_DONTFAIL(struct api_msg, MEMP_API_MSG, name) +#define API_MSG_VAR_FREE(name) API_VAR_FREE(MEMP_API_MSG, name) + +/** + * Create a new netconn (of a specific type) that has a callback function. + * The corresponding pcb is also created. + * + * @param t the type of 'connection' to create (@see enum netconn_type) + * @param proto the IP protocol for RAW IP pcbs + * @param callback a function to call on status changes (RX available, TX'ed) + * @return a newly allocated struct netconn or + * NULL on memory error + */ +struct netconn* +netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_callback callback) +{ + struct netconn *conn; + API_MSG_VAR_DECLARE(msg); + + conn = netconn_alloc(t, callback); + if (conn != NULL) { + err_t err; + API_MSG_VAR_ALLOC_DONTFAIL(msg); + API_MSG_VAR_REF(msg).msg.msg.n.proto = proto; + API_MSG_VAR_REF(msg).msg.conn = conn; + TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_newconn, err); + API_MSG_VAR_FREE(msg); + if (err != ERR_OK) { + LWIP_ASSERT("freeing conn without freeing pcb", conn->pcb.tcp == NULL); + LWIP_ASSERT("conn has no recvmbox", sys_mbox_valid(&conn->recvmbox)); +#if LWIP_TCP + LWIP_ASSERT("conn->acceptmbox shouldn't exist", !sys_mbox_valid(&conn->acceptmbox)); +#endif /* LWIP_TCP */ +#if !LWIP_NETCONN_SEM_PER_THREAD + LWIP_ASSERT("conn has no op_completed", sys_sem_valid(&conn->op_completed)); + sys_sem_free(&conn->op_completed); +#endif /* !LWIP_NETCONN_SEM_PER_THREAD */ + sys_mbox_free(&conn->recvmbox); + memp_free(MEMP_NETCONN, conn); + return NULL; + } + } + return conn; +} + +/** + * Close a netconn 'connection' and free its resources. + * UDP and RAW connection are completely closed, TCP pcbs might still be in a waitstate + * after this returns. + * + * @param conn the netconn to delete + * @return ERR_OK if the connection was deleted + */ +err_t +netconn_delete(struct netconn *conn) +{ + err_t err; + API_MSG_VAR_DECLARE(msg); + + /* No ASSERT here because possible to get a (conn == NULL) if we got an accept error */ + if (conn == NULL) { + return ERR_OK; + } + + API_MSG_VAR_ALLOC(msg); + API_MSG_VAR_REF(msg).function = lwip_netconn_do_delconn; + API_MSG_VAR_REF(msg).msg.conn = conn; + err = tcpip_apimsg(&API_MSG_VAR_REF(msg)); + API_MSG_VAR_FREE(msg); + + if (err != ERR_OK) { + return err; + } + + netconn_free(conn); + + return ERR_OK; +} + +/** + * Get the local or remote IP address and port of a netconn. + * For RAW netconns, this returns the protocol instead of a port! + * + * @param conn the netconn to query + * @param addr a pointer to which to save the IP address + * @param port a pointer to which to save the port (or protocol for RAW) + * @param local 1 to get the local IP address, 0 to get the remote one + * @return ERR_CONN for invalid connections + * ERR_OK if the information was retrieved + */ +err_t +netconn_getaddr(struct netconn *conn, ip_addr_t *addr, u16_t *port, u8_t local) +{ + API_MSG_VAR_DECLARE(msg); + err_t err; + + LWIP_ERROR("netconn_getaddr: invalid conn", (conn != NULL), return ERR_ARG;); + LWIP_ERROR("netconn_getaddr: invalid addr", (addr != NULL), return ERR_ARG;); + LWIP_ERROR("netconn_getaddr: invalid port", (port != NULL), return ERR_ARG;); + + API_MSG_VAR_ALLOC(msg); + API_MSG_VAR_REF(msg).msg.conn = conn; + API_MSG_VAR_REF(msg).msg.msg.ad.local = local; +#if LWIP_MPU_COMPATIBLE + TCPIP_APIMSG(msg, lwip_netconn_do_getaddr, err); + *addr = *ipX_2_ip(&(msg->msg.msg.ad.ipaddr)); + *port = msg->msg.msg.ad.port; +#else /* LWIP_MPU_COMPATIBLE */ + msg.msg.msg.ad.ipaddr = ip_2_ipX(addr); + msg.msg.msg.ad.port = port; + TCPIP_APIMSG(&msg, lwip_netconn_do_getaddr, err); +#endif /* LWIP_MPU_COMPATIBLE */ + API_MSG_VAR_FREE(msg); + + NETCONN_SET_SAFE_ERR(conn, err); + return err; +} + +/** + * Bind a netconn to a specific local IP address and port. + * Binding one netconn twice might not always be checked correctly! + * + * @param conn the netconn to bind + * @param addr the local IP address to bind the netconn to (use IP_ADDR_ANY + * to bind to all addresses) + * @param port the local port to bind the netconn to (not used for RAW) + * @return ERR_OK if bound, any other err_t on failure + */ +err_t +netconn_bind(struct netconn *conn, ip_addr_t *addr, u16_t port) +{ + API_MSG_VAR_DECLARE(msg); + err_t err; + + LWIP_ERROR("netconn_bind: invalid conn", (conn != NULL), return ERR_ARG;); + + API_MSG_VAR_ALLOC(msg); +#if LWIP_MPU_COMPATIBLE + if (addr == NULL) { + addr = IP_ADDR_ANY; + } +#endif /* LWIP_MPU_COMPATIBLE */ + API_MSG_VAR_REF(msg).msg.conn = conn; + API_MSG_VAR_REF(msg).msg.msg.bc.ipaddr = API_MSG_VAR_REF(addr); + API_MSG_VAR_REF(msg).msg.msg.bc.port = port; + TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_bind, err); + API_MSG_VAR_FREE(msg); + + NETCONN_SET_SAFE_ERR(conn, err); + return err; +} + +/** + * Connect a netconn to a specific remote IP address and port. + * + * @param conn the netconn to connect + * @param addr the remote IP address to connect to + * @param port the remote port to connect to (no used for RAW) + * @return ERR_OK if connected, return value of tcp_/udp_/raw_connect otherwise + */ +err_t +netconn_connect(struct netconn *conn, ip_addr_t *addr, u16_t port) +{ + API_MSG_VAR_DECLARE(msg); + err_t err; + + LWIP_ERROR("netconn_connect: invalid conn", (conn != NULL), return ERR_ARG;); + + API_MSG_VAR_ALLOC(msg); +#if LWIP_MPU_COMPATIBLE + if (addr == NULL) { + addr = IP_ADDR_ANY; + } +#endif /* LWIP_MPU_COMPATIBLE */ + API_MSG_VAR_REF(msg).msg.conn = conn; + API_MSG_VAR_REF(msg).msg.msg.bc.ipaddr = API_MSG_VAR_REF(addr); + API_MSG_VAR_REF(msg).msg.msg.bc.port = port; +#if LWIP_TCP +#if (LWIP_UDP || LWIP_RAW) + if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) +#endif /* (LWIP_UDP || LWIP_RAW) */ + { + /* The TCP version waits for the connect to succeed, + so always needs to use message passing. */ + API_MSG_VAR_REF(msg).function = lwip_netconn_do_connect; + err = tcpip_apimsg(&API_MSG_VAR_REF(msg)); + } +#endif /* LWIP_TCP */ +#if (LWIP_UDP || LWIP_RAW) && LWIP_TCP + else +#endif /* (LWIP_UDP || LWIP_RAW) && LWIP_TCP */ +#if (LWIP_UDP || LWIP_RAW) + { + /* UDP and RAW only set flags, so we can use core-locking. */ + TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_connect, err); + } +#endif /* (LWIP_UDP || LWIP_RAW) */ + API_MSG_VAR_FREE(msg); + + NETCONN_SET_SAFE_ERR(conn, err); + return err; +} + +/** + * Disconnect a netconn from its current peer (only valid for UDP netconns). + * + * @param conn the netconn to disconnect + * @return TODO: return value is not set here... + */ +err_t +netconn_disconnect(struct netconn *conn) +{ + API_MSG_VAR_DECLARE(msg); + err_t err; + + LWIP_ERROR("netconn_disconnect: invalid conn", (conn != NULL), return ERR_ARG;); + + API_MSG_VAR_ALLOC(msg); + API_MSG_VAR_REF(msg).msg.conn = conn; + TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_disconnect, err); + API_MSG_VAR_FREE(msg); + + NETCONN_SET_SAFE_ERR(conn, err); + return err; +} + +/** + * Set a TCP netconn into listen mode + * + * @param conn the tcp netconn to set to listen mode + * @param backlog the listen backlog, only used if TCP_LISTEN_BACKLOG==1 + * @return ERR_OK if the netconn was set to listen (UDP and RAW netconns + * don't return any error (yet?)) + */ +err_t +netconn_listen_with_backlog(struct netconn *conn, u8_t backlog) +{ +#if LWIP_TCP + API_MSG_VAR_DECLARE(msg); + err_t err; + + /* This does no harm. If TCP_LISTEN_BACKLOG is off, backlog is unused. */ + LWIP_UNUSED_ARG(backlog); + + LWIP_ERROR("netconn_listen: invalid conn", (conn != NULL), return ERR_ARG;); + + API_MSG_VAR_ALLOC(msg); + API_MSG_VAR_REF(msg).msg.conn = conn; +#if TCP_LISTEN_BACKLOG + API_MSG_VAR_REF(msg).msg.msg.lb.backlog = backlog; +#endif /* TCP_LISTEN_BACKLOG */ + TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_listen, err); + API_MSG_VAR_FREE(msg); + + NETCONN_SET_SAFE_ERR(conn, err); + return err; +#else /* LWIP_TCP */ + LWIP_UNUSED_ARG(conn); + LWIP_UNUSED_ARG(backlog); + return ERR_ARG; +#endif /* LWIP_TCP */ +} + +/** + * Accept a new connection on a TCP listening netconn. + * + * @param conn the TCP listen netconn + * @param new_conn pointer where the new connection is stored + * @return ERR_OK if a new connection has been received or an error + * code otherwise + */ +err_t +netconn_accept(struct netconn *conn, struct netconn **new_conn) +{ +#if LWIP_TCP + struct netconn *newconn; + err_t err; +#if TCP_LISTEN_BACKLOG + API_MSG_VAR_DECLARE(msg); +#endif /* TCP_LISTEN_BACKLOG */ + + LWIP_ERROR("netconn_accept: invalid pointer", (new_conn != NULL), return ERR_ARG;); + *new_conn = NULL; + LWIP_ERROR("netconn_accept: invalid conn", (conn != NULL), return ERR_ARG;); + LWIP_ERROR("netconn_accept: invalid acceptmbox", sys_mbox_valid(&conn->acceptmbox), return ERR_ARG;); + + err = conn->last_err; + if (ERR_IS_FATAL(err)) { + /* don't recv on fatal errors: this might block the application task + waiting on acceptmbox forever! */ + return err; + } + +#if LWIP_SO_RCVTIMEO + if (sys_arch_mbox_fetch(&conn->acceptmbox, (void **)&newconn, conn->recv_timeout) == SYS_ARCH_TIMEOUT) { + NETCONN_SET_SAFE_ERR(conn, ERR_TIMEOUT); + return ERR_TIMEOUT; + } +#else + sys_arch_mbox_fetch(&conn->acceptmbox, (void **)&newconn, 0); +#endif /* LWIP_SO_RCVTIMEO*/ + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0); + + if (newconn == NULL) { + /* connection has been aborted */ + NETCONN_SET_SAFE_ERR(conn, ERR_ABRT); + return ERR_ABRT; + } +#if TCP_LISTEN_BACKLOG + /* Let the stack know that we have accepted the connection. */ + API_MSG_VAR_ALLOC_DONTFAIL(msg); + API_MSG_VAR_REF(msg).msg.conn = conn; + /* don't care for the return value of lwip_netconn_do_recv */ + TCPIP_APIMSG_NOERR(&API_MSG_VAR_REF(msg), lwip_netconn_do_recv); + API_MSG_VAR_FREE(msg); +#endif /* TCP_LISTEN_BACKLOG */ + + *new_conn = newconn; + /* don't set conn->last_err: it's only ERR_OK, anyway */ + return ERR_OK; +#else /* LWIP_TCP */ + LWIP_UNUSED_ARG(conn); + LWIP_UNUSED_ARG(new_conn); + return ERR_ARG; +#endif /* LWIP_TCP */ +} + +/** + * Receive data: actual implementation that doesn't care whether pbuf or netbuf + * is received + * + * @param conn the netconn from which to receive data + * @param new_buf pointer where a new pbuf/netbuf is stored when received data + * @return ERR_OK if data has been received, an error code otherwise (timeout, + * memory error or another error) + */ +static err_t +netconn_recv_data(struct netconn *conn, void **new_buf) +{ + void *buf = NULL; + u16_t len; + err_t err; +#if LWIP_TCP + API_MSG_VAR_DECLARE(msg); +#endif /* LWIP_TCP */ + + LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;); + *new_buf = NULL; + LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;); + LWIP_ERROR("netconn_accept: invalid recvmbox", sys_mbox_valid(&conn->recvmbox), return ERR_CONN;); + + err = conn->last_err; + if (ERR_IS_FATAL(err)) { + /* don't recv on fatal errors: this might block the application task + waiting on recvmbox forever! */ + /* @todo: this does not allow us to fetch data that has been put into recvmbox + before the fatal error occurred - is that a problem? */ + return err; + } + +#if LWIP_SO_RCVTIMEO + if (sys_arch_mbox_fetch(&conn->recvmbox, &buf, conn->recv_timeout) == SYS_ARCH_TIMEOUT) { + NETCONN_SET_SAFE_ERR(conn, ERR_TIMEOUT); + return ERR_TIMEOUT; + } +#else + sys_arch_mbox_fetch(&conn->recvmbox, &buf, 0); +#endif /* LWIP_SO_RCVTIMEO*/ + +#if LWIP_TCP +#if (LWIP_UDP || LWIP_RAW) + if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) +#endif /* (LWIP_UDP || LWIP_RAW) */ + { + if (!netconn_get_noautorecved(conn) || (buf == NULL)) { + /* Let the stack know that we have taken the data. */ + /* TODO: Speedup: Don't block and wait for the answer here + (to prevent multiple thread-switches). */ + API_MSG_VAR_ALLOC_DONTFAIL(msg); + API_MSG_VAR_REF(msg).msg.conn = conn; + if (buf != NULL) { + API_MSG_VAR_REF(msg).msg.msg.r.len = ((struct pbuf *)buf)->tot_len; + } else { + API_MSG_VAR_REF(msg).msg.msg.r.len = 1; + } + /* don't care for the return value of lwip_netconn_do_recv */ + TCPIP_APIMSG_NOERR(&API_MSG_VAR_REF(msg), lwip_netconn_do_recv); + API_MSG_VAR_FREE(msg); + } + + /* If we are closed, we indicate that we no longer wish to use the socket */ + if (buf == NULL) { + API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0); + /* Avoid to lose any previous error code */ + NETCONN_SET_SAFE_ERR(conn, ERR_CLSD); + return ERR_CLSD; + } + len = ((struct pbuf *)buf)->tot_len; + } +#endif /* LWIP_TCP */ +#if LWIP_TCP && (LWIP_UDP || LWIP_RAW) + else +#endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */ +#if (LWIP_UDP || LWIP_RAW) + { + LWIP_ASSERT("buf != NULL", buf != NULL); + len = netbuf_len((struct netbuf *)buf); + } +#endif /* (LWIP_UDP || LWIP_RAW) */ + +#if LWIP_SO_RCVBUF + SYS_ARCH_DEC(conn->recv_avail, len); +#endif /* LWIP_SO_RCVBUF */ + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVMINUS, len); + + LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_recv_data: received %p, len=%"U16_F"\n", buf, len)); + + *new_buf = buf; + /* don't set conn->last_err: it's only ERR_OK, anyway */ + return ERR_OK; +} + +/** + * Receive data (in form of a pbuf) from a TCP netconn + * + * @param conn the netconn from which to receive data + * @param new_buf pointer where a new pbuf is stored when received data + * @return ERR_OK if data has been received, an error code otherwise (timeout, + * memory error or another error) + * ERR_ARG if conn is not a TCP netconn + */ +err_t +netconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf) +{ + LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL) && + NETCONNTYPE_GROUP(netconn_type(conn)) == NETCONN_TCP, return ERR_ARG;); + + return netconn_recv_data(conn, (void **)new_buf); +} + +/** + * Receive data (in form of a netbuf containing a packet buffer) from a netconn + * + * @param conn the netconn from which to receive data + * @param new_buf pointer where a new netbuf is stored when received data + * @return ERR_OK if data has been received, an error code otherwise (timeout, + * memory error or another error) + */ +err_t +netconn_recv(struct netconn *conn, struct netbuf **new_buf) +{ +#if LWIP_TCP + struct netbuf *buf = NULL; + err_t err; +#endif /* LWIP_TCP */ + + LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;); + *new_buf = NULL; + LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;); + LWIP_ERROR("netconn_accept: invalid recvmbox", sys_mbox_valid(&conn->recvmbox), return ERR_CONN;); + +#if LWIP_TCP +#if (LWIP_UDP || LWIP_RAW) + if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) +#endif /* (LWIP_UDP || LWIP_RAW) */ + { + struct pbuf *p = NULL; + /* This is not a listening netconn, since recvmbox is set */ + + buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); + if (buf == NULL) { + NETCONN_SET_SAFE_ERR(conn, ERR_MEM); + return ERR_MEM; + } + + err = netconn_recv_data(conn, (void **)&p); + if (err != ERR_OK) { + memp_free(MEMP_NETBUF, buf); + return err; + } + LWIP_ASSERT("p != NULL", p != NULL); + + buf->p = p; + buf->ptr = p; + buf->port = 0; + ipX_addr_set_any(LWIP_IPV6, &buf->addr); + *new_buf = buf; + /* don't set conn->last_err: it's only ERR_OK, anyway */ + return ERR_OK; + } +#endif /* LWIP_TCP */ +#if LWIP_TCP && (LWIP_UDP || LWIP_RAW) + else +#endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */ + { +#if (LWIP_UDP || LWIP_RAW) + return netconn_recv_data(conn, (void **)new_buf); +#endif /* (LWIP_UDP || LWIP_RAW) */ + } +} + +/** + * TCP: update the receive window: by calling this, the application + * tells the stack that it has processed data and is able to accept + * new data. + * ATTENTION: use with care, this is mainly used for sockets! + * Can only be used when calling netconn_set_noautorecved(conn, 1) before. + * + * @param conn the netconn for which to update the receive window + * @param length amount of data processed (ATTENTION: this must be accurate!) + */ +void +netconn_recved(struct netconn *conn, u32_t length) +{ +#if LWIP_TCP + if ((conn != NULL) && (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) && + (netconn_get_noautorecved(conn))) { + API_MSG_VAR_DECLARE(msg); + /* Let the stack know that we have taken the data. */ + /* TODO: Speedup: Don't block and wait for the answer here + (to prevent multiple thread-switches). */ + API_MSG_VAR_ALLOC_DONTFAIL(msg); + API_MSG_VAR_REF(msg).msg.conn = conn; + API_MSG_VAR_REF(msg).msg.msg.r.len = length; + /* don't care for the return value of lwip_netconn_do_recv */ + TCPIP_APIMSG_NOERR(&API_MSG_VAR_REF(msg), lwip_netconn_do_recv); + API_MSG_VAR_FREE(msg); + } +#else /* LWIP_TCP */ + LWIP_UNUSED_ARG(conn); + LWIP_UNUSED_ARG(length); +#endif /* LWIP_TCP */ +} + +/** + * Send data (in form of a netbuf) to a specific remote IP address and port. + * Only to be used for UDP and RAW netconns (not TCP). + * + * @param conn the netconn over which to send data + * @param buf a netbuf containing the data to send + * @param addr the remote IP address to which to send the data + * @param port the remote port to which to send the data + * @return ERR_OK if data was sent, any other err_t on error + */ +err_t +netconn_sendto(struct netconn *conn, struct netbuf *buf, ip_addr_t *addr, u16_t port) +{ + if (buf != NULL) { + ipX_addr_set_ipaddr(PCB_ISIPV6(conn->pcb.ip), &buf->addr, addr); + buf->port = port; + return netconn_send(conn, buf); + } + return ERR_VAL; +} + +/** + * Send data over a UDP or RAW netconn (that is already connected). + * + * @param conn the UDP or RAW netconn over which to send data + * @param buf a netbuf containing the data to send + * @return ERR_OK if data was sent, any other err_t on error + */ +err_t +netconn_send(struct netconn *conn, struct netbuf *buf) +{ + API_MSG_VAR_DECLARE(msg); + err_t err; + + LWIP_ERROR("netconn_send: invalid conn", (conn != NULL), return ERR_ARG;); + + LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %"U16_F" bytes\n", buf->p->tot_len)); + API_MSG_VAR_ALLOC(msg); + API_MSG_VAR_REF(msg).msg.conn = conn; + API_MSG_VAR_REF(msg).msg.msg.b = buf; + TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_send, err); + API_MSG_VAR_FREE(msg); + + NETCONN_SET_SAFE_ERR(conn, err); + return err; +} + +/** + * Send data over a TCP netconn. + * + * @param conn the TCP netconn over which to send data + * @param dataptr pointer to the application buffer that contains the data to send + * @param size size of the application data to send + * @param apiflags combination of following flags : + * - NETCONN_COPY: data will be copied into memory belonging to the stack + * - NETCONN_MORE: for TCP connection, PSH flag will be set on last segment sent + * - NETCONN_DONTBLOCK: only write the data if all data can be written at once + * @param bytes_written pointer to a location that receives the number of written bytes + * @return ERR_OK if data was sent, any other err_t on error + */ +err_t +netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size, + u8_t apiflags, size_t *bytes_written) +{ + API_MSG_VAR_DECLARE(msg); + err_t err; + u8_t dontblock; + + LWIP_ERROR("netconn_write: invalid conn", (conn != NULL), return ERR_ARG;); + LWIP_ERROR("netconn_write: invalid conn->type", (NETCONNTYPE_GROUP(conn->type)== NETCONN_TCP), return ERR_VAL;); + if (size == 0) { + return ERR_OK; + } + dontblock = netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK); + if (dontblock && !bytes_written) { + /* This implies netconn_write() cannot be used for non-blocking send, since + it has no way to return the number of bytes written. */ + return ERR_VAL; + } + + API_MSG_VAR_ALLOC(msg); + /* non-blocking write sends as much */ + API_MSG_VAR_REF(msg).msg.conn = conn; + API_MSG_VAR_REF(msg).msg.msg.w.dataptr = dataptr; + API_MSG_VAR_REF(msg).msg.msg.w.apiflags = apiflags; + API_MSG_VAR_REF(msg).msg.msg.w.len = size; +#if LWIP_SO_SNDTIMEO + if (conn->send_timeout != 0) { + /* get the time we started, which is later compared to + sys_now() + conn->send_timeout */ + API_MSG_VAR_REF(msg).msg.msg.w.time_started = sys_now(); + } else { + API_MSG_VAR_REF(msg).msg.msg.w.time_started = 0; + } +#endif /* LWIP_SO_SNDTIMEO */ + + /* For locking the core: this _can_ be delayed on low memory/low send buffer, + but if it is, this is done inside api_msg.c:do_write(), so we can use the + non-blocking version here. */ + TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_write, err); + if ((err == ERR_OK) && (bytes_written != NULL)) { + if (dontblock +#if LWIP_SO_SNDTIMEO + || (conn->send_timeout != 0) +#endif /* LWIP_SO_SNDTIMEO */ + ) { + /* nonblocking write: maybe the data has been sent partly */ + *bytes_written = API_MSG_VAR_REF(msg).msg.msg.w.len; + } else { + /* blocking call succeeded: all data has been sent if it */ + *bytes_written = size; + } + } + API_MSG_VAR_FREE(msg); + + NETCONN_SET_SAFE_ERR(conn, err); + return err; +} + +/** + * Close or shutdown a TCP netconn (doesn't delete it). + * + * @param conn the TCP netconn to close or shutdown + * @param how fully close or only shutdown one side? + * @return ERR_OK if the netconn was closed, any other err_t on error + */ +static err_t +netconn_close_shutdown(struct netconn *conn, u8_t how) +{ + API_MSG_VAR_DECLARE(msg); + err_t err; + + LWIP_ERROR("netconn_close: invalid conn", (conn != NULL), return ERR_ARG;); + + API_MSG_VAR_ALLOC(msg); + API_MSG_VAR_REF(msg).function = lwip_netconn_do_close; + API_MSG_VAR_REF(msg).msg.conn = conn; + /* shutting down both ends is the same as closing */ + API_MSG_VAR_REF(msg).msg.msg.sd.shut = how; + /* because of the LWIP_TCPIP_CORE_LOCKING implementation of lwip_netconn_do_close, + don't use TCPIP_APIMSG here */ + err = tcpip_apimsg(&API_MSG_VAR_REF(msg)); + API_MSG_VAR_FREE(msg); + + NETCONN_SET_SAFE_ERR(conn, err); + return err; +} + +/** + * Close a TCP netconn (doesn't delete it). + * + * @param conn the TCP netconn to close + * @return ERR_OK if the netconn was closed, any other err_t on error + */ +err_t +netconn_close(struct netconn *conn) +{ + /* shutting down both ends is the same as closing */ + return netconn_close_shutdown(conn, NETCONN_SHUT_RDWR); +} + +/** + * Shut down one or both sides of a TCP netconn (doesn't delete it). + * + * @param conn the TCP netconn to shut down + * @return ERR_OK if the netconn was closed, any other err_t on error + */ +err_t +netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx) +{ + return netconn_close_shutdown(conn, (shut_rx ? NETCONN_SHUT_RD : 0) | (shut_tx ? NETCONN_SHUT_WR : 0)); +} + +#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) +/** + * Join multicast groups for UDP netconns. + * + * @param conn the UDP netconn for which to change multicast addresses + * @param multiaddr IP address of the multicast group to join or leave + * @param netif_addr the IP address of the network interface on which to send + * the igmp message + * @param join_or_leave flag whether to send a join- or leave-message + * @return ERR_OK if the action was taken, any err_t on error + */ +err_t +netconn_join_leave_group(struct netconn *conn, + ip_addr_t *multiaddr, + ip_addr_t *netif_addr, + enum netconn_igmp join_or_leave) +{ + API_MSG_VAR_DECLARE(msg); + err_t err; + + LWIP_ERROR("netconn_join_leave_group: invalid conn", (conn != NULL), return ERR_ARG;); + + API_MSG_VAR_ALLOC(msg); +#if LWIP_MPU_COMPATIBLE + if (multiaddr == NULL) { + multiaddr = IP_ADDR_ANY; + } + if (netif_addr == NULL) { + netif_addr = IP_ADDR_ANY; + } +#endif /* LWIP_MPU_COMPATIBLE */ + API_MSG_VAR_REF(msg).msg.conn = conn; + API_MSG_VAR_REF(msg).msg.msg.jl.multiaddr = API_MSG_VAR_REF(ip_2_ipX(multiaddr)); + API_MSG_VAR_REF(msg).msg.msg.jl.netif_addr = API_MSG_VAR_REF(ip_2_ipX(netif_addr)); + API_MSG_VAR_REF(msg).msg.msg.jl.join_or_leave = join_or_leave; + TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_join_leave_group, err); + API_MSG_VAR_FREE(msg); + + NETCONN_SET_SAFE_ERR(conn, err); + return err; +} +#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ + +#if LWIP_DNS +/** + * Execute a DNS query, only one IP address is returned + * + * @param name a string representation of the DNS host name to query + * @param addr a preallocated ip_addr_t where to store the resolved IP address + * @return ERR_OK: resolving succeeded + * ERR_MEM: memory error, try again later + * ERR_ARG: dns client not initialized or invalid hostname + * ERR_VAL: dns server response was invalid + */ +err_t +netconn_gethostbyname(const char *name, ip_addr_t *addr) +{ + API_VAR_DECLARE(struct dns_api_msg, msg); +#if !LWIP_MPU_COMPATIBLE + sys_sem_t sem; +#endif /* LWIP_MPU_COMPATIBLE */ + err_t err; + + LWIP_ERROR("netconn_gethostbyname: invalid name", (name != NULL), return ERR_ARG;); + LWIP_ERROR("netconn_gethostbyname: invalid addr", (addr != NULL), return ERR_ARG;); +#if LWIP_MPU_COMPATIBLE + if (strlen(name) >= DNS_MAX_NAME_LENGTH) { + return ERR_ARG; + } +#endif + + API_VAR_ALLOC(struct dns_api_msg, MEMP_DNS_API_MSG, msg); +#if LWIP_MPU_COMPATIBLE + strncpy(API_VAR_REF(msg).name, name, DNS_MAX_NAME_LENGTH-1); + API_VAR_REF(msg).name[DNS_MAX_NAME_LENGTH-1] = 0; +#else /* LWIP_MPU_COMPATIBLE */ + msg.err = &err; + msg.sem = &sem; + API_VAR_REF(msg).addr = API_VAR_REF(addr); + API_VAR_REF(msg).name = name; +#endif /* LWIP_MPU_COMPATIBLE */ + err = sys_sem_new(API_EXPR_REF(API_VAR_REF(msg).sem), 0); + if (err != ERR_OK) { + API_VAR_FREE(MEMP_DNS_API_MSG, msg); + return err; + } + + tcpip_callback(lwip_netconn_do_gethostbyname, &API_VAR_REF(msg)); + sys_sem_wait(API_EXPR_REF(API_VAR_REF(msg).sem)); + sys_sem_free(API_EXPR_REF(API_VAR_REF(msg).sem)); + +#if LWIP_MPU_COMPATIBLE + *addr = msg->addr; + err = msg->err; +#endif /* LWIP_MPU_COMPATIBLE */ + + API_VAR_FREE(MEMP_DNS_API_MSG, msg); + return err; +} +#endif /* LWIP_DNS*/ + +#if LWIP_NETCONN_SEM_PER_THREAD +void netconn_thread_init(void) +{ + sys_sem_t *sem = LWIP_NETCONN_THREAD_SEM_GET(); + if (sem == SYS_SEM_NULL) { + /* call alloc only once */ + LWIP_NETCONN_THREAD_SEM_ALLOC(); + LWIP_ASSERT("LWIP_NETCONN_THREAD_SEM_ALLOC() failed", LWIP_NETCONN_THREAD_SEM_GET() != SYS_SEM_NULL); + } +} + +void netconn_thread_cleanup(void) +{ + sys_sem_t *sem = LWIP_NETCONN_THREAD_SEM_GET(); + if (sem == SYS_SEM_NULL) { + /* call free only once */ + LWIP_NETCONN_THREAD_SEM_FREE(); + } +} +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + +//Realtek add +err_t netconn_abort(struct netconn *conn) +{ + if (conn->acceptmbox != SYS_MBOX_NULL) { + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); + sys_mbox_post(conn->acceptmbox, NULL); + } + return ERR_OK; +} +//Realtek add end + +#endif /* LWIP_NETCONN */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/api/api_msg.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/api/api_msg.c new file mode 100644 index 0000000..42a4f8e --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/api/api_msg.c @@ -0,0 +1,1657 @@ +/** + * @file + * Sequential API Internal module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/api_msg.h" + +#include "lwip/lwip_ip.h" +#include "lwip/udp.h" +#include "lwip/tcp.h" +#include "lwip/raw.h" + +#include "lwip/memp.h" +#include "lwip/tcpip.h" +#include "lwip/igmp.h" +#include "lwip/dns.h" +#include "lwip/mld6.h" + +#include + +#define SET_NONBLOCKING_CONNECT(conn, val) do { if(val) { \ + (conn)->flags |= NETCONN_FLAG_IN_NONBLOCKING_CONNECT; \ +} else { \ + (conn)->flags &= ~ NETCONN_FLAG_IN_NONBLOCKING_CONNECT; }} while(0) +#define IN_NONBLOCKING_CONNECT(conn) (((conn)->flags & NETCONN_FLAG_IN_NONBLOCKING_CONNECT) != 0) + +/* forward declarations */ +#if LWIP_TCP +static err_t lwip_netconn_do_writemore(struct netconn *conn); +static void lwip_netconn_do_close_internal(struct netconn *conn); +#endif + +#if LWIP_RAW +/** + * Receive callback function for RAW netconns. + * Doesn't 'eat' the packet, only copies it and sends it to + * conn->recvmbox + * + * @see raw.h (struct raw_pcb.recv) for parameters and return value + */ +static u8_t +recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p, + ip_addr_t *addr) +{ + struct pbuf *q; + struct netbuf *buf; + struct netconn *conn; + + LWIP_UNUSED_ARG(addr); + conn = (struct netconn *)arg; + + if ((conn != NULL) && sys_mbox_valid(&conn->recvmbox)) { +#if LWIP_SO_RCVBUF + int recv_avail; + SYS_ARCH_GET(conn->recv_avail, recv_avail); + if ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize) { + return 0; + } +#endif /* LWIP_SO_RCVBUF */ + /* copy the whole packet into new pbufs */ + q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); + if(q != NULL) { + if (pbuf_copy(q, p) != ERR_OK) { + pbuf_free(q); + q = NULL; + } + } + + if (q != NULL) { + u16_t len; + buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); + if (buf == NULL) { + pbuf_free(q); + return 0; + } + + buf->p = q; + buf->ptr = q; + ipX_addr_copy(PCB_ISIPV6(pcb), buf->addr, *ipX_current_src_addr()); + buf->port = pcb->protocol; + + len = q->tot_len; + if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) { + netbuf_delete(buf); + return 0; + } else { +#if LWIP_SO_RCVBUF + SYS_ARCH_INC(conn->recv_avail, len); +#endif /* LWIP_SO_RCVBUF */ + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); + } + } + } + + return 0; /* do not eat the packet */ +} +#endif /* LWIP_RAW*/ + +#if LWIP_UDP +/** + * Receive callback function for UDP netconns. + * Posts the packet to conn->recvmbox or deletes it on memory error. + * + * @see udp.h (struct udp_pcb.recv) for parameters + */ +static void +recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *addr, u16_t port) +{ + struct netbuf *buf; + struct netconn *conn; + u16_t len; +#if LWIP_SO_RCVBUF + int recv_avail; +#endif /* LWIP_SO_RCVBUF */ + + LWIP_UNUSED_ARG(pcb); /* only used for asserts... */ + LWIP_ASSERT("recv_udp must have a pcb argument", pcb != NULL); + LWIP_ASSERT("recv_udp must have an argument", arg != NULL); + conn = (struct netconn *)arg; + LWIP_ASSERT("recv_udp: recv for wrong pcb!", conn->pcb.udp == pcb); + +#if LWIP_SO_RCVBUF + SYS_ARCH_GET(conn->recv_avail, recv_avail); + if ((conn == NULL) || !sys_mbox_valid(&conn->recvmbox) || + ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize)) { +#else /* LWIP_SO_RCVBUF */ + if ((conn == NULL) || !sys_mbox_valid(&conn->recvmbox)) { +#endif /* LWIP_SO_RCVBUF */ + pbuf_free(p); + return; + } + + buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); + if (buf == NULL) { + pbuf_free(p); + return; + } else { + buf->p = p; + buf->ptr = p; + ipX_addr_set_ipaddr(ip_current_is_v6(), &buf->addr, addr); + buf->port = port; +#if LWIP_NETBUF_RECVINFO + { + /* get the UDP header - always in the first pbuf, ensured by udp_input */ + const struct udp_hdr* udphdr = ipX_next_header_ptr(); +#if LWIP_CHECKSUM_ON_COPY + buf->flags = NETBUF_FLAG_DESTADDR; +#endif /* LWIP_CHECKSUM_ON_COPY */ + ipX_addr_set(ip_current_is_v6(), &buf->toaddr, ipX_current_dest_addr()); + buf->toport_chksum = udphdr->dest; + } +#endif /* LWIP_NETBUF_RECVINFO */ + } + + len = p->tot_len; + if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) { + netbuf_delete(buf); + return; + } else { +#if LWIP_SO_RCVBUF + SYS_ARCH_INC(conn->recv_avail, len); +#endif /* LWIP_SO_RCVBUF */ + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); + } +} +#endif /* LWIP_UDP */ + +#if LWIP_TCP +/** + * Receive callback function for TCP netconns. + * Posts the packet to conn->recvmbox, but doesn't delete it on errors. + * + * @see tcp.h (struct tcp_pcb.recv) for parameters and return value + */ +static err_t +recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) +{ + struct netconn *conn; + u16_t len; + + LWIP_UNUSED_ARG(pcb); + LWIP_ASSERT("recv_tcp must have a pcb argument", pcb != NULL); + LWIP_ASSERT("recv_tcp must have an argument", arg != NULL); + conn = (struct netconn *)arg; + + if (conn == NULL) { + return ERR_VAL; + } + LWIP_ASSERT("recv_tcp: recv for wrong pcb!", conn->pcb.tcp == pcb); + + if (!sys_mbox_valid(&conn->recvmbox)) { + /* recvmbox already deleted */ + if (p != NULL) { + tcp_recved(pcb, p->tot_len); + pbuf_free(p); + } + return ERR_OK; + } + /* Unlike for UDP or RAW pcbs, don't check for available space + using recv_avail since that could break the connection + (data is already ACKed) */ + + /* don't overwrite fatal errors! */ + NETCONN_SET_SAFE_ERR(conn, err); + + if (p != NULL) { + len = p->tot_len; + } else { + len = 0; + } + + if (sys_mbox_trypost(&conn->recvmbox, p) != ERR_OK) { + /* don't deallocate p: it is presented to us later again from tcp_fasttmr! */ + return ERR_MEM; + } else { +#if LWIP_SO_RCVBUF + SYS_ARCH_INC(conn->recv_avail, len); +#endif /* LWIP_SO_RCVBUF */ + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); + } + + return ERR_OK; +} + +/** + * Poll callback function for TCP netconns. + * Wakes up an application thread that waits for a connection to close + * or data to be sent. The application thread then takes the + * appropriate action to go on. + * + * Signals the conn->sem. + * netconn_close waits for conn->sem if closing failed. + * + * @see tcp.h (struct tcp_pcb.poll) for parameters and return value + */ +static err_t +poll_tcp(void *arg, struct tcp_pcb *pcb) +{ + struct netconn *conn = (struct netconn *)arg; + + LWIP_UNUSED_ARG(pcb); + LWIP_ASSERT("conn != NULL", (conn != NULL)); + + if (conn->state == NETCONN_WRITE) { + lwip_netconn_do_writemore(conn); + } else if (conn->state == NETCONN_CLOSE) { + lwip_netconn_do_close_internal(conn); + } + /* @todo: implement connect timeout here? */ + + /* Did a nonblocking write fail before? Then check available write-space. */ + if (conn->flags & NETCONN_FLAG_CHECK_WRITESPACE) { + /* If the queued byte- or pbuf-count drops below the configured low-water limit, + let select mark this pcb as writable again. */ + if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT) && + (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT)) { + conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE; + API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); + } + } + + return ERR_OK; +} + +/** + * Sent callback function for TCP netconns. + * Signals the conn->sem and calls API_EVENT. + * netconn_write waits for conn->sem if send buffer is low. + * + * @see tcp.h (struct tcp_pcb.sent) for parameters and return value + */ +static err_t +sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len) +{ + struct netconn *conn = (struct netconn *)arg; + + LWIP_UNUSED_ARG(pcb); + LWIP_ASSERT("conn != NULL", (conn != NULL)); + + if (conn->state == NETCONN_WRITE) { + lwip_netconn_do_writemore(conn); + } else if (conn->state == NETCONN_CLOSE) { + lwip_netconn_do_close_internal(conn); + } + + if (conn) { + /* If the queued byte- or pbuf-count drops below the configured low-water limit, + let select mark this pcb as writable again. */ + if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT) && + (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT)) { + conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE; + API_EVENT(conn, NETCONN_EVT_SENDPLUS, len); + } + } + + return ERR_OK; +} + +/** + * Error callback function for TCP netconns. + * Signals conn->sem, posts to all conn mboxes and calls API_EVENT. + * The application thread has then to decide what to do. + * + * @see tcp.h (struct tcp_pcb.err) for parameters + */ +static void +err_tcp(void *arg, err_t err) +{ + struct netconn *conn; + enum netconn_state old_state; + SYS_ARCH_DECL_PROTECT(lev); + + conn = (struct netconn *)arg; + LWIP_ASSERT("conn != NULL", (conn != NULL)); + + conn->pcb.tcp = NULL; + + /* no check since this is always fatal! */ + SYS_ARCH_PROTECT(lev); + conn->last_err = err; + SYS_ARCH_UNPROTECT(lev); + + /* reset conn->state now before waking up other threads */ + old_state = conn->state; + conn->state = NETCONN_NONE; + + /* @todo: the type of NETCONN_EVT created should depend on 'old_state' */ + + /* Notify the user layer about a connection error. Used to signal select. */ + API_EVENT(conn, NETCONN_EVT_ERROR, 0); + /* Try to release selects pending on 'read' or 'write', too. + They will get an error if they actually try to read or write. */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); + API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); + + /* pass NULL-message to recvmbox to wake up pending recv */ + if (sys_mbox_valid(&conn->recvmbox)) { + /* use trypost to prevent deadlock */ + sys_mbox_trypost(&conn->recvmbox, NULL); + } + /* pass NULL-message to acceptmbox to wake up pending accept */ + if (sys_mbox_valid(&conn->acceptmbox)) { + /* use trypost to preven deadlock */ + sys_mbox_trypost(&conn->acceptmbox, NULL); + } + + if ((old_state == NETCONN_WRITE) || (old_state == NETCONN_CLOSE) || + (old_state == NETCONN_CONNECT)) { + /* calling lwip_netconn_do_writemore/lwip_netconn_do_close_internal is not necessary + since the pcb has already been deleted! */ + int was_nonblocking_connect = IN_NONBLOCKING_CONNECT(conn); + SET_NONBLOCKING_CONNECT(conn, 0); + + if (!was_nonblocking_connect) { + sys_sem_t* op_completed_sem; + /* set error return code */ + LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL); + conn->current_msg->err = err; + op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg); + LWIP_ASSERT("inavlid op_completed_sem", op_completed_sem != SYS_SEM_NULL); + conn->current_msg = NULL; + /* wake up the waiting task */ + sys_sem_signal(op_completed_sem); + } + } else { + LWIP_ASSERT("conn->current_msg == NULL", conn->current_msg == NULL); + } +} + +/** + * Setup a tcp_pcb with the correct callback function pointers + * and their arguments. + * + * @param conn the TCP netconn to setup + */ +static void +setup_tcp(struct netconn *conn) +{ + struct tcp_pcb *pcb; + + pcb = conn->pcb.tcp; + tcp_arg(pcb, conn); + tcp_recv(pcb, recv_tcp); + tcp_sent(pcb, sent_tcp); + tcp_poll(pcb, poll_tcp, 4); + tcp_err(pcb, err_tcp); +} + +/** + * Accept callback function for TCP netconns. + * Allocates a new netconn and posts that to conn->acceptmbox. + * + * @see tcp.h (struct tcp_pcb_listen.accept) for parameters and return value + */ +static err_t +accept_function(void *arg, struct tcp_pcb *newpcb, err_t err) +{ + struct netconn *newconn; + struct netconn *conn = (struct netconn *)arg; + + LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: newpcb->tate: %s\n", tcp_debug_state_str(newpcb->state))); + + if (!sys_mbox_valid(&conn->acceptmbox)) { + LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: acceptmbox already deleted\n")); + return ERR_VAL; + } + + /* We have to set the callback here even though + * the new socket is unknown. conn->socket is marked as -1. */ + newconn = netconn_alloc(conn->type, conn->callback); + if (newconn == NULL) { + return ERR_MEM; + } + newconn->pcb.tcp = newpcb; + setup_tcp(newconn); + /* no protection: when creating the pcb, the netconn is not yet known + to the application thread */ + newconn->last_err = err; + + if (sys_mbox_trypost(&conn->acceptmbox, newconn) != ERR_OK) { + /* When returning != ERR_OK, the pcb is aborted in tcp_process(), + so do nothing here! */ + /* remove all references to this netconn from the pcb */ + struct tcp_pcb* pcb = newconn->pcb.tcp; + tcp_arg(pcb, NULL); + tcp_recv(pcb, NULL); + tcp_sent(pcb, NULL); + tcp_poll(pcb, NULL, 4); + tcp_err(pcb, NULL); + /* remove reference from to the pcb from this netconn */ + newconn->pcb.tcp = NULL; + /* no need to drain since we know the recvmbox is empty. */ + sys_mbox_free(&newconn->recvmbox); + sys_mbox_set_invalid(&newconn->recvmbox); + netconn_free(newconn); + return ERR_MEM; + } else { + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); + } + + return ERR_OK; +} +#endif /* LWIP_TCP */ + +/** + * Create a new pcb of a specific type. + * Called from lwip_netconn_do_newconn(). + * + * @param msg the api_msg_msg describing the connection type + * @return msg->conn->err, but the return value is currently ignored + */ +static void +pcb_new(struct api_msg_msg *msg) +{ + LWIP_ASSERT("pcb_new: pcb already allocated", msg->conn->pcb.tcp == NULL); + + /* Allocate a PCB for this connection */ + switch(NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + msg->conn->pcb.raw = raw_new(msg->msg.n.proto); + if(msg->conn->pcb.raw != NULL) { + raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn); + } + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + msg->conn->pcb.udp = udp_new(); + if(msg->conn->pcb.udp != NULL) { +#if LWIP_UDPLITE + if (NETCONNTYPE_ISUDPLITE(msg->conn->type)) { + udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE); + } +#endif /* LWIP_UDPLITE */ + if (NETCONNTYPE_ISUDPNOCHKSUM(msg->conn->type)) { + udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM); + } + udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn); + } + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + msg->conn->pcb.tcp = tcp_new(); + if(msg->conn->pcb.tcp != NULL) { + setup_tcp(msg->conn); + } + break; +#endif /* LWIP_TCP */ + default: + /* Unsupported netconn type, e.g. protocol disabled */ + msg->err = ERR_VAL; + return; + } + if (msg->conn->pcb.ip == NULL) { + msg->err = ERR_MEM; + } +#if LWIP_IPV6 + else { + if (NETCONNTYPE_ISIPV6(msg->conn->type)) { + ip_set_v6(msg->conn->pcb.ip, 1); + } + } +#endif /* LWIP_IPV6 */ +} + +/** + * Create a new pcb of a specific type inside a netconn. + * Called from netconn_new_with_proto_and_callback. + * + * @param msg the api_msg_msg describing the connection type + */ +void +lwip_netconn_do_newconn(struct api_msg_msg *msg) +{ + msg->err = ERR_OK; + if (msg->conn->pcb.tcp == NULL) { + pcb_new(msg); + } + /* Else? This "new" connection already has a PCB allocated. */ + /* Is this an error condition? Should it be deleted? */ + /* We currently just are happy and return. */ + + TCPIP_APIMSG_ACK(msg); +} + +/** + * Create a new netconn (of a specific type) that has a callback function. + * The corresponding pcb is NOT created! + * + * @param t the type of 'connection' to create (@see enum netconn_type) + * @param proto the IP protocol for RAW IP pcbs + * @param callback a function to call on status changes (RX available, TX'ed) + * @return a newly allocated struct netconn or + * NULL on memory error + */ +struct netconn* +netconn_alloc(enum netconn_type t, netconn_callback callback) +{ + struct netconn *conn; + int size; + + conn = (struct netconn *)memp_malloc(MEMP_NETCONN); + if (conn == NULL) { + return NULL; + } + + conn->last_err = ERR_OK; + conn->type = t; + conn->pcb.tcp = NULL; + + /* If all sizes are the same, every compiler should optimize this switch to nothing */ + switch(NETCONNTYPE_GROUP(t)) { +#if LWIP_RAW + case NETCONN_RAW: + size = DEFAULT_RAW_RECVMBOX_SIZE; + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + size = DEFAULT_UDP_RECVMBOX_SIZE; + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + size = DEFAULT_TCP_RECVMBOX_SIZE; + break; +#endif /* LWIP_TCP */ + default: + LWIP_ASSERT("netconn_alloc: undefined netconn_type", 0); + goto free_and_return; + } + + if (sys_mbox_new(&conn->recvmbox, size) != ERR_OK) { + goto free_and_return; + } +#if !LWIP_NETCONN_SEM_PER_THREAD + if (sys_sem_new(&conn->op_completed, 0) != ERR_OK) { + sys_mbox_free(&conn->recvmbox); + goto free_and_return; + } +#endif + +#if LWIP_TCP + sys_mbox_set_invalid(&conn->acceptmbox); +#endif + conn->state = NETCONN_NONE; +#if LWIP_SOCKET + /* initialize socket to -1 since 0 is a valid socket */ + conn->socket = -1; +#endif /* LWIP_SOCKET */ + conn->callback = callback; +#if LWIP_TCP + conn->current_msg = NULL; + conn->write_offset = 0; +#endif /* LWIP_TCP */ +#if LWIP_SO_SNDTIMEO + conn->send_timeout = 0; +#endif /* LWIP_SO_SNDTIMEO */ +#if LWIP_SO_RCVTIMEO + conn->recv_timeout = 0; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + conn->recv_bufsize = RECV_BUFSIZE_DEFAULT; + conn->recv_avail = 0; +#endif /* LWIP_SO_RCVBUF */ + conn->flags = 0; + return conn; +free_and_return: + memp_free(MEMP_NETCONN, conn); + return NULL; +} + +/** + * Delete a netconn and all its resources. + * The pcb is NOT freed (since we might not be in the right thread context do this). + * + * @param conn the netconn to free + */ +void +netconn_free(struct netconn *conn) +{ + LWIP_ASSERT("PCB must be deallocated outside this function", conn->pcb.tcp == NULL); + LWIP_ASSERT("recvmbox must be deallocated before calling this function", + !sys_mbox_valid(&conn->recvmbox)); +#if LWIP_TCP + LWIP_ASSERT("acceptmbox must be deallocated before calling this function", + !sys_mbox_valid(&conn->acceptmbox)); +#endif /* LWIP_TCP */ + +#if !LWIP_NETCONN_SEM_PER_THREAD + sys_sem_free(&conn->op_completed); + sys_sem_set_invalid(&conn->op_completed); +#endif + + memp_free(MEMP_NETCONN, conn); +} + +/** + * Delete rcvmbox and acceptmbox of a netconn and free the left-over data in + * these mboxes + * + * @param conn the netconn to free + * @bytes_drained bytes drained from recvmbox + * @accepts_drained pending connections drained from acceptmbox + */ +static void +netconn_drain(struct netconn *conn) +{ + void *mem; +#if LWIP_TCP + struct pbuf *p; +#endif /* LWIP_TCP */ + + /* This runs in tcpip_thread, so we don't need to lock against rx packets */ + + /* Delete and drain the recvmbox. */ + if (sys_mbox_valid(&conn->recvmbox)) { + while (sys_mbox_tryfetch(&conn->recvmbox, &mem) != SYS_MBOX_EMPTY) { +#if LWIP_TCP + if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) { + if(mem != NULL) { + p = (struct pbuf*)mem; + /* pcb might be set to NULL already by err_tcp() */ + if (conn->pcb.tcp != NULL) { + tcp_recved(conn->pcb.tcp, p->tot_len); + } + pbuf_free(p); + } + } else +#endif /* LWIP_TCP */ + { + netbuf_delete((struct netbuf *)mem); + } + } + sys_mbox_free(&conn->recvmbox); + sys_mbox_set_invalid(&conn->recvmbox); + } + + /* Delete and drain the acceptmbox. */ +#if LWIP_TCP + if (sys_mbox_valid(&conn->acceptmbox)) { + while (sys_mbox_tryfetch(&conn->acceptmbox, &mem) != SYS_MBOX_EMPTY) { + struct netconn *newconn = (struct netconn *)mem; + /* Only tcp pcbs have an acceptmbox, so no need to check conn->type */ + /* pcb might be set to NULL already by err_tcp() */ + if (conn->pcb.tcp != NULL) { + tcp_accepted(conn->pcb.tcp); + } + /* drain recvmbox */ + netconn_drain(newconn); + if (newconn->pcb.tcp != NULL) { + tcp_abort(newconn->pcb.tcp); + newconn->pcb.tcp = NULL; + } + netconn_free(newconn); + } + sys_mbox_free(&conn->acceptmbox); + sys_mbox_set_invalid(&conn->acceptmbox); + } +#endif /* LWIP_TCP */ +} + +#if LWIP_TCP +/** + * Internal helper function to close a TCP netconn: since this sometimes + * doesn't work at the first attempt, this function is called from multiple + * places. + * + * @param conn the TCP netconn to close + */ +static void +lwip_netconn_do_close_internal(struct netconn *conn) +{ + err_t err; + u8_t shut, shut_rx, shut_tx, close; + struct tcp_pcb* tpcb = conn->pcb.tcp; + + LWIP_ASSERT("invalid conn", (conn != NULL)); + LWIP_ASSERT("this is for tcp netconns only", (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP)); + LWIP_ASSERT("conn must be in state NETCONN_CLOSE", (conn->state == NETCONN_CLOSE)); + LWIP_ASSERT("pcb already closed", (conn->pcb.tcp != NULL)); + LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL); + + shut = conn->current_msg->msg.sd.shut; + shut_rx = shut & NETCONN_SHUT_RD; + shut_tx = shut & NETCONN_SHUT_WR; + /* shutting down both ends is the same as closing + (also if RD or WR side was shut down before already) */ + if (shut == NETCONN_SHUT_RDWR) { + close = 1; + } else if (shut_rx && + ((tpcb->state == FIN_WAIT_1) || + (tpcb->state == FIN_WAIT_2) || + (tpcb->state == CLOSING))) { + close = 1; + } else if (shut_tx && ((tpcb->flags & TF_RXCLOSED) != 0)) { + close = 1; + } else { + close = 0; + } + + /* Set back some callback pointers */ + if (close) { + tcp_arg(tpcb, NULL); + } + if (tpcb->state == LISTEN) { + tcp_accept(tpcb, NULL); + } else { + /* some callbacks have to be reset if tcp_close is not successful */ + if (shut_rx) { + tcp_recv(tpcb, NULL); + tcp_accept(tpcb, NULL); + } + if (shut_tx) { + tcp_sent(tpcb, NULL); + } + if (close) { + tcp_poll(tpcb, NULL, 4); + tcp_err(tpcb, NULL); + } + } + /* Try to close the connection */ + if (close) { + err = tcp_close(tpcb); + } else { + err = tcp_shutdown(tpcb, shut_rx, shut_tx); + } + if (err == ERR_OK) { + /* Closing succeeded */ + sys_sem_t* op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg); + conn->current_msg->err = ERR_OK; + conn->current_msg = NULL; + conn->state = NETCONN_NONE; + if (close) { + /* Set back some callback pointers as conn is going away */ + conn->pcb.tcp = NULL; + /* Trigger select() in socket layer. Make sure everybody notices activity + on the connection, error first! */ + API_EVENT(conn, NETCONN_EVT_ERROR, 0); + } + if (shut_rx) { + API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); + } + if (shut_tx) { + API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); + } + /* wake up the application task */ + sys_sem_signal(op_completed_sem); + } else { + /* Closing failed, restore some of the callbacks */ + /* Closing of listen pcb will never fail! */ + LWIP_ASSERT("Closing a listen pcb may not fail!", (conn->pcb.tcp->state != LISTEN)); + tcp_sent(conn->pcb.tcp, sent_tcp); + tcp_poll(conn->pcb.tcp, poll_tcp, 4); + tcp_err(conn->pcb.tcp, err_tcp); + tcp_arg(conn->pcb.tcp, conn); + /* don't restore recv callback: we don't want to receive any more data */ + } + /* If closing didn't succeed, we get called again either + from poll_tcp or from sent_tcp */ +} +#endif /* LWIP_TCP */ + +/** + * Delete the pcb inside a netconn. + * Called from netconn_delete. + * + * @param msg the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_delconn(struct api_msg_msg *msg) +{ + /* @todo TCP: abort running write/connect? */ + if ((msg->conn->state != NETCONN_NONE) && + (msg->conn->state != NETCONN_LISTEN) && + (msg->conn->state != NETCONN_CONNECT)) { + /* this only happens for TCP netconns */ + LWIP_ASSERT("NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP", + NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP); + msg->err = ERR_INPROGRESS; + } else { + LWIP_ASSERT("blocking connect in progress", + (msg->conn->state != NETCONN_CONNECT) || IN_NONBLOCKING_CONNECT(msg->conn)); + msg->err = ERR_OK; + /* Drain and delete mboxes */ + netconn_drain(msg->conn); + + if (msg->conn->pcb.tcp != NULL) { + + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + raw_remove(msg->conn->pcb.raw); + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + msg->conn->pcb.udp->recv_arg = NULL; + udp_remove(msg->conn->pcb.udp); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL && + msg->conn->write_offset == 0); + msg->conn->state = NETCONN_CLOSE; + msg->msg.sd.shut = NETCONN_SHUT_RDWR; + msg->conn->current_msg = msg; + lwip_netconn_do_close_internal(msg->conn); + /* API_EVENT is called inside lwip_netconn_do_close_internal, before releasing + the application thread, so we can return at this point! */ + return; +#endif /* LWIP_TCP */ + default: + break; + } + msg->conn->pcb.tcp = NULL; + } + /* tcp netconns don't come here! */ + + /* @todo: this lets select make the socket readable and writable, + which is wrong! errfd instead? */ + API_EVENT(msg->conn, NETCONN_EVT_RCVPLUS, 0); + API_EVENT(msg->conn, NETCONN_EVT_SENDPLUS, 0); + } + if (sys_sem_valid(LWIP_API_MSG_SEM(msg))) { + sys_sem_signal(LWIP_API_MSG_SEM(msg)); + } +} + +/** + * Bind a pcb contained in a netconn + * Called from netconn_bind. + * + * @param msg the api_msg_msg pointing to the connection and containing + * the IP address and port to bind to + */ +void +lwip_netconn_do_bind(struct api_msg_msg *msg) +{ + if (ERR_IS_FATAL(msg->conn->last_err)) { + msg->err = msg->conn->last_err; + } else { + msg->err = ERR_VAL; + if (msg->conn->pcb.tcp != NULL) { + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + msg->err = raw_bind(msg->conn->pcb.raw, API_EXPR_REF(msg->msg.bc.ipaddr)); + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + msg->err = udp_bind(msg->conn->pcb.udp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + msg->err = tcp_bind(msg->conn->pcb.tcp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); + break; +#endif /* LWIP_TCP */ + default: + break; + } + } + } + TCPIP_APIMSG_ACK(msg); +} + +#if LWIP_TCP +/** + * TCP callback function if a connection (opened by tcp_connect/lwip_netconn_do_connect) has + * been established (or reset by the remote host). + * + * @see tcp.h (struct tcp_pcb.connected) for parameters and return values + */ +static err_t +lwip_netconn_do_connected(void *arg, struct tcp_pcb *pcb, err_t err) +{ + struct netconn *conn; + int was_blocking; + sys_sem_t* op_completed_sem = NULL; + + LWIP_UNUSED_ARG(pcb); + + conn = (struct netconn *)arg; + + if (conn == NULL) { + return ERR_VAL; + } + + LWIP_ASSERT("conn->state == NETCONN_CONNECT", conn->state == NETCONN_CONNECT); + LWIP_ASSERT("(conn->current_msg != NULL) || conn->in_non_blocking_connect", + (conn->current_msg != NULL) || IN_NONBLOCKING_CONNECT(conn)); + + if (conn->current_msg != NULL) { + conn->current_msg->err = err; + op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg); + } + if ((NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) && (err == ERR_OK)) { + setup_tcp(conn); + } + was_blocking = !IN_NONBLOCKING_CONNECT(conn); + SET_NONBLOCKING_CONNECT(conn, 0); + LWIP_ASSERT("blocking connect state error", + (was_blocking && op_completed_sem != NULL) || + (!was_blocking && op_completed_sem == NULL)); + conn->current_msg = NULL; + conn->state = NETCONN_NONE; + if (!was_blocking) { + NETCONN_SET_SAFE_ERR(conn, ERR_OK); + } + API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); + + if (was_blocking) { + sys_sem_signal(op_completed_sem); + } + return ERR_OK; +} +#endif /* LWIP_TCP */ + +/** + * Connect a pcb contained inside a netconn + * Called from netconn_connect. + * + * @param msg the api_msg_msg pointing to the connection and containing + * the IP address and port to connect to + */ +void +lwip_netconn_do_connect(struct api_msg_msg *msg) +{ + if (msg->conn->pcb.tcp == NULL) { + /* This may happen when calling netconn_connect() a second time */ + msg->err = ERR_CLSD; + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) { + /* For TCP, netconn_connect() calls tcpip_apimsg(), so signal op_completed here. */ + sys_sem_signal(LWIP_API_MSG_SEM(msg)); + return; + } + } else { + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + msg->err = raw_connect(msg->conn->pcb.raw, API_EXPR_REF(msg->msg.bc.ipaddr)); + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + msg->err = udp_connect(msg->conn->pcb.udp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + /* Prevent connect while doing any other action. */ + if (msg->conn->state != NETCONN_NONE) { + msg->err = ERR_ISCONN; + } else { + setup_tcp(msg->conn); + msg->err = tcp_connect(msg->conn->pcb.tcp, API_EXPR_REF(msg->msg.bc.ipaddr), + msg->msg.bc.port, lwip_netconn_do_connected); + if (msg->err == ERR_OK) { + u8_t non_blocking = netconn_is_nonblocking(msg->conn); + msg->conn->state = NETCONN_CONNECT; + SET_NONBLOCKING_CONNECT(msg->conn, non_blocking); + if (non_blocking) { + msg->err = ERR_INPROGRESS; + } else { + msg->conn->current_msg = msg; + /* sys_sem_signal() is called from lwip_netconn_do_connected (or err_tcp()), + * when the connection is established! */ + return; + } + } + } + /* For TCP, netconn_connect() calls tcpip_apimsg(), so signal op_completed here. */ + sys_sem_signal(LWIP_API_MSG_SEM(msg)); + return; +#endif /* LWIP_TCP */ + default: + LWIP_ERROR("Invalid netconn type", 0, do{ msg->err = ERR_VAL; }while(0)); + break; + } + } + /* For all other protocols, netconn_connect() calls TCPIP_APIMSG(), + so use TCPIP_APIMSG_ACK() here. */ + TCPIP_APIMSG_ACK(msg); +} + +/** + * Connect a pcb contained inside a netconn + * Only used for UDP netconns. + * Called from netconn_disconnect. + * + * @param msg the api_msg_msg pointing to the connection to disconnect + */ +void +lwip_netconn_do_disconnect(struct api_msg_msg *msg) +{ +#if LWIP_UDP + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) { + udp_disconnect(msg->conn->pcb.udp); + msg->err = ERR_OK; + } else +#endif /* LWIP_UDP */ + { + msg->err = ERR_VAL; + } + TCPIP_APIMSG_ACK(msg); +} + +#if LWIP_TCP +/** + * Set a TCP pcb contained in a netconn into listen mode + * Called from netconn_listen. + * + * @param msg the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_listen(struct api_msg_msg *msg) +{ + if (ERR_IS_FATAL_LISTENCONNECT(msg->conn->last_err)) { + msg->err = msg->conn->last_err; + } else { + msg->err = ERR_CONN; + if (msg->conn->pcb.tcp != NULL) { + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) { + if (msg->conn->state == NETCONN_NONE) { + struct tcp_pcb* lpcb; + if (msg->conn->pcb.tcp->state != CLOSED) { + /* connection is not closed, cannot listen */ + msg->err = ERR_VAL; + } else { +#if LWIP_IPV6 + if ((msg->conn->flags & NETCONN_FLAG_IPV6_V6ONLY) == 0) { +#if TCP_LISTEN_BACKLOG + lpcb = tcp_listen_dual_with_backlog(msg->conn->pcb.tcp, msg->msg.lb.backlog); +#else /* TCP_LISTEN_BACKLOG */ + lpcb = tcp_listen_dual(msg->conn->pcb.tcp); +#endif /* TCP_LISTEN_BACKLOG */ + } else +#endif /* LWIP_IPV6 */ + { +#if TCP_LISTEN_BACKLOG + lpcb = tcp_listen_with_backlog(msg->conn->pcb.tcp, msg->msg.lb.backlog); +#else /* TCP_LISTEN_BACKLOG */ + lpcb = tcp_listen(msg->conn->pcb.tcp); +#endif /* TCP_LISTEN_BACKLOG */ + } + if (lpcb == NULL) { + /* in this case, the old pcb is still allocated */ + msg->err = ERR_MEM; + } else { + /* delete the recvmbox and allocate the acceptmbox */ + if (sys_mbox_valid(&msg->conn->recvmbox)) { + /** @todo: should we drain the recvmbox here? */ + sys_mbox_free(&msg->conn->recvmbox); + sys_mbox_set_invalid(&msg->conn->recvmbox); + } + msg->err = ERR_OK; + if (!sys_mbox_valid(&msg->conn->acceptmbox)) { + msg->err = sys_mbox_new(&msg->conn->acceptmbox, DEFAULT_ACCEPTMBOX_SIZE); + } + if (msg->err == ERR_OK) { + msg->conn->state = NETCONN_LISTEN; + msg->conn->pcb.tcp = lpcb; + tcp_arg(msg->conn->pcb.tcp, msg->conn); + tcp_accept(msg->conn->pcb.tcp, accept_function); + } else { + /* since the old pcb is already deallocated, free lpcb now */ + tcp_close(lpcb); + msg->conn->pcb.tcp = NULL; + } + } + } + } + } else { + msg->err = ERR_ARG; + } + } + } + TCPIP_APIMSG_ACK(msg); +} +#endif /* LWIP_TCP */ + +/** + * Send some data on a RAW or UDP pcb contained in a netconn + * Called from netconn_send + * + * @param msg the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_send(struct api_msg_msg *msg) +{ + if (ERR_IS_FATAL(msg->conn->last_err)) { + msg->err = msg->conn->last_err; + } else { + msg->err = ERR_CONN; + if (msg->conn->pcb.tcp != NULL) { + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + if (ipX_addr_isany(PCB_ISIPV6(msg->conn->pcb.ip), &msg->msg.b->addr)) { + msg->err = raw_send(msg->conn->pcb.raw, msg->msg.b->p); + } else { + msg->err = raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, ipX_2_ip(&msg->msg.b->addr)); + } + break; +#endif +#if LWIP_UDP + case NETCONN_UDP: +#if LWIP_CHECKSUM_ON_COPY + if (ipX_addr_isany(PCB_ISIPV6(msg->conn->pcb.ip), &msg->msg.b->addr)) { + msg->err = udp_send_chksum(msg->conn->pcb.udp, msg->msg.b->p, + msg->msg.b->flags & NETBUF_FLAG_CHKSUM, msg->msg.b->toport_chksum); + } else { + msg->err = udp_sendto_chksum(msg->conn->pcb.udp, msg->msg.b->p, + ipX_2_ip(&msg->msg.b->addr), msg->msg.b->port, + msg->msg.b->flags & NETBUF_FLAG_CHKSUM, msg->msg.b->toport_chksum); + } +#else /* LWIP_CHECKSUM_ON_COPY */ + if (ipX_addr_isany(PCB_ISIPV6(msg->conn->pcb.ip), &msg->msg.b->addr)) { + msg->err = udp_send(msg->conn->pcb.udp, msg->msg.b->p); + } else { + msg->err = udp_sendto(msg->conn->pcb.udp, msg->msg.b->p, ipX_2_ip(&msg->msg.b->addr), msg->msg.b->port); + } +#endif /* LWIP_CHECKSUM_ON_COPY */ + break; +#endif /* LWIP_UDP */ + default: + break; + } + } + } + TCPIP_APIMSG_ACK(msg); +} + +#if LWIP_TCP +/** + * Indicate data has been received from a TCP pcb contained in a netconn + * Called from netconn_recv + * + * @param msg the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_recv(struct api_msg_msg *msg) +{ + msg->err = ERR_OK; + if (msg->conn->pcb.tcp != NULL) { + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) { +#if TCP_LISTEN_BACKLOG + if (msg->conn->pcb.tcp->state == LISTEN) { + tcp_accepted(msg->conn->pcb.tcp); + } else +#endif /* TCP_LISTEN_BACKLOG */ + { + u32_t remaining = msg->msg.r.len; + do { + u16_t recved = (remaining > 0xffff) ? 0xffff : (u16_t)remaining; + tcp_recved(msg->conn->pcb.tcp, recved); + remaining -= recved; + }while(remaining != 0); + } + } + } + TCPIP_APIMSG_ACK(msg); +} + +/** + * See if more data needs to be written from a previous call to netconn_write. + * Called initially from lwip_netconn_do_write. If the first call can't send all data + * (because of low memory or empty send-buffer), this function is called again + * from sent_tcp() or poll_tcp() to send more data. If all data is sent, the + * blocking application thread (waiting in netconn_write) is released. + * + * @param conn netconn (that is currently in state NETCONN_WRITE) to process + * @return ERR_OK + * ERR_MEM if LWIP_TCPIP_CORE_LOCKING=1 and sending hasn't yet finished + */ +static err_t +lwip_netconn_do_writemore(struct netconn *conn) +{ + err_t err; + void *dataptr; + u16_t len, available; + u8_t write_finished = 0; + size_t diff; + u8_t dontblock; + u8_t apiflags; + + LWIP_ASSERT("conn != NULL", conn != NULL); + LWIP_ASSERT("conn->state == NETCONN_WRITE", (conn->state == NETCONN_WRITE)); + LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL); + LWIP_ASSERT("conn->pcb.tcp != NULL", conn->pcb.tcp != NULL); + LWIP_ASSERT("conn->write_offset < conn->current_msg->msg.w.len", + conn->write_offset < conn->current_msg->msg.w.len); + + dontblock = netconn_is_nonblocking(conn) || + (conn->current_msg->msg.w.apiflags & NETCONN_DONTBLOCK); + apiflags = conn->current_msg->msg.w.apiflags; + +#if LWIP_SO_SNDTIMEO + if ((conn->send_timeout != 0) && + ((s32_t)(sys_now() - conn->current_msg->msg.w.time_started) >= conn->send_timeout)) { + write_finished = 1; + if (conn->write_offset == 0) { + /* nothing has been written */ + err = ERR_WOULDBLOCK; + conn->current_msg->msg.w.len = 0; + } else { + /* partial write */ + err = ERR_OK; + conn->current_msg->msg.w.len = conn->write_offset; + conn->write_offset = 0; + } + } else +#endif /* LWIP_SO_SNDTIMEO */ + { + dataptr = (u8_t*)conn->current_msg->msg.w.dataptr + conn->write_offset; + diff = conn->current_msg->msg.w.len - conn->write_offset; + if (diff > 0xffffUL) { /* max_u16_t */ + len = 0xffff; +#if LWIP_TCPIP_CORE_LOCKING + conn->flags |= NETCONN_FLAG_WRITE_DELAYED; +#endif + apiflags |= TCP_WRITE_FLAG_MORE; + } else { + len = (u16_t)diff; + } + available = tcp_sndbuf(conn->pcb.tcp); + if (available < len) { + /* don't try to write more than sendbuf */ + len = available; + if (dontblock) { + if (!len) { + err = ERR_WOULDBLOCK; + goto err_mem; + } + } else { +#if LWIP_TCPIP_CORE_LOCKING + conn->flags |= NETCONN_FLAG_WRITE_DELAYED; +#endif + apiflags |= TCP_WRITE_FLAG_MORE; + } + } + LWIP_ASSERT("lwip_netconn_do_writemore: invalid length!", ((conn->write_offset + len) <= conn->current_msg->msg.w.len)); + err = tcp_write(conn->pcb.tcp, dataptr, len, apiflags); + /* if OK or memory error, check available space */ + if ((err == ERR_OK) || (err == ERR_MEM)) { +err_mem: + if (dontblock && (len < conn->current_msg->msg.w.len)) { + /* non-blocking write did not write everything: mark the pcb non-writable + and let poll_tcp check writable space to mark the pcb writable again */ + API_EVENT(conn, NETCONN_EVT_SENDMINUS, len); + conn->flags |= NETCONN_FLAG_CHECK_WRITESPACE; + } else if ((tcp_sndbuf(conn->pcb.tcp) <= TCP_SNDLOWAT) || + (tcp_sndqueuelen(conn->pcb.tcp) >= TCP_SNDQUEUELOWAT)) { + /* The queued byte- or pbuf-count exceeds the configured low-water limit, + let select mark this pcb as non-writable. */ + API_EVENT(conn, NETCONN_EVT_SENDMINUS, len); + } + } + + if (err == ERR_OK) { + conn->write_offset += len; + if ((conn->write_offset == conn->current_msg->msg.w.len) || dontblock) { + /* return sent length */ + conn->current_msg->msg.w.len = conn->write_offset; + /* everything was written */ + write_finished = 1; + conn->write_offset = 0; + } + tcp_output(conn->pcb.tcp); + } else if ((err == ERR_MEM) && !dontblock) { + /* If ERR_MEM, we wait for sent_tcp or poll_tcp to be called + we do NOT return to the application thread, since ERR_MEM is + only a temporary error! */ + + /* tcp_write returned ERR_MEM, try tcp_output anyway */ + tcp_output(conn->pcb.tcp); + +#if LWIP_TCPIP_CORE_LOCKING + conn->flags |= NETCONN_FLAG_WRITE_DELAYED; +#endif + } else { + /* On errors != ERR_MEM, we don't try writing any more but return + the error to the application thread. */ + write_finished = 1; + conn->current_msg->msg.w.len = 0; + } + } + if (write_finished) { + /* everything was written: set back connection state + and back to application task */ + sys_sem_t* op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg); + conn->current_msg->err = err; + conn->current_msg = NULL; + conn->state = NETCONN_NONE; +#if LWIP_TCPIP_CORE_LOCKING + if ((conn->flags & NETCONN_FLAG_WRITE_DELAYED) != 0) +#endif + { + sys_sem_signal(op_completed_sem); + } + } +#if LWIP_TCPIP_CORE_LOCKING + else { + return ERR_MEM; + } +#endif + return ERR_OK; +} +#endif /* LWIP_TCP */ + +/** + * Send some data on a TCP pcb contained in a netconn + * Called from netconn_write + * + * @param msg the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_write(struct api_msg_msg *msg) +{ + if (ERR_IS_FATAL(msg->conn->last_err)) { + msg->err = msg->conn->last_err; + } else { + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) { +#if LWIP_TCP + if (msg->conn->state != NETCONN_NONE) { + /* netconn is connecting, closing or in blocking write */ + msg->err = ERR_INPROGRESS; + } else if (msg->conn->pcb.tcp != NULL) { + msg->conn->state = NETCONN_WRITE; + /* set all the variables used by lwip_netconn_do_writemore */ + LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL && + msg->conn->write_offset == 0); + LWIP_ASSERT("msg->msg.w.len != 0", msg->msg.w.len != 0); + msg->conn->current_msg = msg; + msg->conn->write_offset = 0; +#if LWIP_TCPIP_CORE_LOCKING + msg->conn->flags &= ~NETCONN_FLAG_WRITE_DELAYED; + if (lwip_netconn_do_writemore(msg->conn) != ERR_OK) { + LWIP_ASSERT("state!", msg->conn->state == NETCONN_WRITE); + UNLOCK_TCPIP_CORE(); + sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0); + LOCK_TCPIP_CORE(); + LWIP_ASSERT("state!", msg->conn->state != NETCONN_WRITE); + } +#else /* LWIP_TCPIP_CORE_LOCKING */ + lwip_netconn_do_writemore(msg->conn); +#endif /* LWIP_TCPIP_CORE_LOCKING */ + /* for both cases: if lwip_netconn_do_writemore was called, don't ACK the APIMSG + since lwip_netconn_do_writemore ACKs it! */ + return; + } else { + msg->err = ERR_CONN; + } +#else /* LWIP_TCP */ + msg->err = ERR_VAL; +#endif /* LWIP_TCP */ +#if (LWIP_UDP || LWIP_RAW) + } else { + msg->err = ERR_VAL; +#endif /* (LWIP_UDP || LWIP_RAW) */ + } + } + TCPIP_APIMSG_ACK(msg); +} + +/** + * Return a connection's local or remote address + * Called from netconn_getaddr + * + * @param msg the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_getaddr(struct api_msg_msg *msg) +{ + if (msg->conn->pcb.ip != NULL) { + if (msg->msg.ad.local) { + ipX_addr_copy(PCB_ISIPV6(msg->conn->pcb.ip), API_EXPR_DEREF(msg->msg.ad.ipaddr), + msg->conn->pcb.ip->local_ip); + } else { + ipX_addr_copy(PCB_ISIPV6(msg->conn->pcb.ip), API_EXPR_DEREF(msg->msg.ad.ipaddr), + msg->conn->pcb.ip->remote_ip); + } + msg->err = ERR_OK; + switch (NETCONNTYPE_GROUP(msg->conn->type)) { +#if LWIP_RAW + case NETCONN_RAW: + if (msg->msg.ad.local) { + API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.raw->protocol; + } else { + /* return an error as connecting is only a helper for upper layers */ + msg->err = ERR_CONN; + } + break; +#endif /* LWIP_RAW */ +#if LWIP_UDP + case NETCONN_UDP: + if (msg->msg.ad.local) { + API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.udp->local_port; + } else { + if ((msg->conn->pcb.udp->flags & UDP_FLAGS_CONNECTED) == 0) { + msg->err = ERR_CONN; + } else { + API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.udp->remote_port; + } + } + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case NETCONN_TCP: + if ((msg->msg.ad.local == 0) && + ((msg->conn->pcb.tcp->state == CLOSED) || (msg->conn->pcb.tcp->state == LISTEN))) { + /* pcb is not connected and remote name is requested */ + msg->err = ERR_CONN; + } else { + API_EXPR_DEREF(msg->msg.ad.port) = (msg->msg.ad.local ? msg->conn->pcb.tcp->local_port : msg->conn->pcb.tcp->remote_port); + } + break; +#endif /* LWIP_TCP */ + default: + LWIP_ASSERT("invalid netconn_type", 0); + break; + } + } else { + msg->err = ERR_CONN; + } + TCPIP_APIMSG_ACK(msg); +} + +/** + * Close or half-shutdown a TCP pcb contained in a netconn + * Called from netconn_close + * In contrast to closing sockets, the netconn is not deallocated. + * + * @param msg the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_close(struct api_msg_msg *msg) +{ +#if LWIP_TCP + /* @todo: abort running write/connect? */ + if ((msg->conn->state != NETCONN_NONE) && (msg->conn->state != NETCONN_LISTEN)) { + /* this only happens for TCP netconns */ + LWIP_ASSERT("NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP", + NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP); + msg->err = ERR_INPROGRESS; + } else if ((msg->conn->pcb.tcp != NULL) && (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP)) { + if ((msg->msg.sd.shut != NETCONN_SHUT_RDWR) && (msg->conn->state == NETCONN_LISTEN)) { + /* LISTEN doesn't support half shutdown */ + msg->err = ERR_CONN; + } else { + if (msg->msg.sd.shut & NETCONN_SHUT_RD) { + /* Drain and delete mboxes */ + netconn_drain(msg->conn); + } + LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL && + msg->conn->write_offset == 0); + msg->conn->state = NETCONN_CLOSE; + msg->conn->current_msg = msg; + lwip_netconn_do_close_internal(msg->conn); + /* for tcp netconns, lwip_netconn_do_close_internal ACKs the message */ + return; + } + } else +#endif /* LWIP_TCP */ + { + msg->err = ERR_CONN; + } + sys_sem_signal(LWIP_API_MSG_SEM(msg)); +} + +#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) +/** + * Join multicast groups for UDP netconns. + * Called from netconn_join_leave_group + * + * @param msg the api_msg_msg pointing to the connection + */ +void +lwip_netconn_do_join_leave_group(struct api_msg_msg *msg) +{ + if (ERR_IS_FATAL(msg->conn->last_err)) { + msg->err = msg->conn->last_err; + } else { + if (msg->conn->pcb.tcp != NULL) { + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) { +#if LWIP_UDP +#if LWIP_IPV6 && LWIP_IPV6_MLD + if (PCB_ISIPV6(msg->conn->pcb.udp)) { + if (msg->msg.jl.join_or_leave == NETCONN_JOIN) { + msg->err = mld6_joingroup(ipX_2_ip6(API_EXPR_REF(msg->msg.jl.netif_addr)), + ipX_2_ip6(API_EXPR_REF(msg->msg.jl.multiaddr))); + } else { + msg->err = mld6_leavegroup(ipX_2_ip6(API_EXPR_REF(msg->msg.jl.netif_addr)), + ipX_2_ip6(API_EXPR_REF(msg->msg.jl.multiaddr))); + } + } + else +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ + { +#if LWIP_IGMP + if (msg->msg.jl.join_or_leave == NETCONN_JOIN) { + msg->err = igmp_joingroup(ipX_2_ip(API_EXPR_REF(msg->msg.jl.netif_addr)), + ipX_2_ip(API_EXPR_REF(msg->msg.jl.multiaddr))); + } else { + msg->err = igmp_leavegroup(ipX_2_ip(API_EXPR_REF(msg->msg.jl.netif_addr)), + ipX_2_ip(API_EXPR_REF(msg->msg.jl.multiaddr))); + } +#endif /* LWIP_IGMP */ + } +#endif /* LWIP_UDP */ +#if (LWIP_TCP || LWIP_RAW) + } else { + msg->err = ERR_VAL; +#endif /* (LWIP_TCP || LWIP_RAW) */ + } + } else { + msg->err = ERR_CONN; + } + } + TCPIP_APIMSG_ACK(msg); +} +#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ + +#if LWIP_DNS +/** + * Callback function that is called when DNS name is resolved + * (or on timeout). A waiting application thread is waked up by + * signaling the semaphore. + */ +static void +lwip_netconn_do_dns_found(const char *name, ip_addr_t *ipaddr, void *arg) +{ + struct dns_api_msg *msg = (struct dns_api_msg*)arg; + + /* we trust the internal implementation to be correct :-) */ + LWIP_UNUSED_ARG(name); + + if (ipaddr == NULL) { + /* timeout or memory error */ + API_EXPR_DEREF(msg->err) = ERR_VAL; + } else { + /* address was resolved */ + API_EXPR_DEREF(msg->err) = ERR_OK; + API_EXPR_DEREF(msg->addr) = *ipaddr; + } + /* wake up the application task waiting in netconn_gethostbyname */ + sys_sem_signal(API_EXPR_REF(msg->sem)); +} + +/** + * Execute a DNS query + * Called from netconn_gethostbyname + * + * @param arg the dns_api_msg pointing to the query + */ +void +lwip_netconn_do_gethostbyname(void *arg) +{ + struct dns_api_msg *msg = (struct dns_api_msg*)arg; + + API_EXPR_DEREF(msg->err) = dns_gethostbyname(msg->name, API_EXPR_REF(msg->addr), lwip_netconn_do_dns_found, msg); + if (API_EXPR_DEREF(msg->err) != ERR_INPROGRESS) { + /* on error or immediate success, wake up the application + * task waiting in netconn_gethostbyname */ + sys_sem_signal(API_EXPR_REF(msg->sem)); + } +} +#endif /* LWIP_DNS */ + +#endif /* LWIP_NETCONN */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/api/err.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/api/err.c new file mode 100644 index 0000000..e970101 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/api/err.c @@ -0,0 +1,75 @@ +/** + * @file + * Error Management module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/err.h" + +#ifdef LWIP_DEBUG + +static const char *err_strerr[] = { + "Ok.", /* ERR_OK 0 */ + "Out of memory error.", /* ERR_MEM -1 */ + "Buffer error.", /* ERR_BUF -2 */ + "Timeout.", /* ERR_TIMEOUT -3 */ + "Routing problem.", /* ERR_RTE -4 */ + "Operation in progress.", /* ERR_INPROGRESS -5 */ + "Illegal value.", /* ERR_VAL -6 */ + "Operation would block.", /* ERR_WOULDBLOCK -7 */ + "Address in use.", /* ERR_USE -8 */ + "Already connected.", /* ERR_ISCONN -9 */ + "Not connected.", /* ERR_CONN -10 */ + "Connection aborted.", /* ERR_ABRT -11 */ + "Connection reset.", /* ERR_RST -12 */ + "Connection closed.", /* ERR_CLSD -13 */ + "Illegal argument.", /* ERR_ARG -14 */ + "Low-level netif error.", /* ERR_IF -15 */ +}; + +/** + * Convert an lwip internal error to a string representation. + * + * @param err an lwip internal err_t + * @return a string representation for err + */ +const char * +lwip_strerr(err_t err) +{ + return err_strerr[-err]; + +} + +#endif /* LWIP_DEBUG */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/api/netbuf.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/api/netbuf.c new file mode 100644 index 0000000..4a417b0 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/api/netbuf.c @@ -0,0 +1,245 @@ +/** + * @file + * Network buffer management + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/netbuf.h" +#include "lwip/memp.h" + +#include + +/** + * Create (allocate) and initialize a new netbuf. + * The netbuf doesn't yet contain a packet buffer! + * + * @return a pointer to a new netbuf + * NULL on lack of memory + */ +struct +netbuf *netbuf_new(void) +{ + struct netbuf *buf; + + buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); + if (buf != NULL) { + buf->p = NULL; + buf->ptr = NULL; + ipX_addr_set_any(LWIP_IPV6, &buf->addr); + buf->port = 0; +#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY +#if LWIP_CHECKSUM_ON_COPY + buf->flags = 0; +#endif /* LWIP_CHECKSUM_ON_COPY */ + buf->toport_chksum = 0; +#if LWIP_NETBUF_RECVINFO + ipX_addr_set_any(LWIP_IPV6, &buf->toaddr); +#endif /* LWIP_NETBUF_RECVINFO */ +#endif /* LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY */ + return buf; + } else { + return NULL; + } +} + +/** + * Deallocate a netbuf allocated by netbuf_new(). + * + * @param buf pointer to a netbuf allocated by netbuf_new() + */ +void +netbuf_delete(struct netbuf *buf) +{ + if (buf != NULL) { + if (buf->p != NULL) { + pbuf_free(buf->p); + buf->p = buf->ptr = NULL; + } + memp_free(MEMP_NETBUF, buf); + } +} + +/** + * Allocate memory for a packet buffer for a given netbuf. + * + * @param buf the netbuf for which to allocate a packet buffer + * @param size the size of the packet buffer to allocate + * @return pointer to the allocated memory + * NULL if no memory could be allocated + */ +void * +netbuf_alloc(struct netbuf *buf, u16_t size) +{ + LWIP_ERROR("netbuf_alloc: invalid buf", (buf != NULL), return NULL;); + + /* Deallocate any previously allocated memory. */ + if (buf->p != NULL) { + pbuf_free(buf->p); + } + buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM); + if (buf->p == NULL) { + return NULL; + } + LWIP_ASSERT("check that first pbuf can hold size", + (buf->p->len >= size)); + buf->ptr = buf->p; + return buf->p->payload; +} + +/** + * Free the packet buffer included in a netbuf + * + * @param buf pointer to the netbuf which contains the packet buffer to free + */ +void +netbuf_free(struct netbuf *buf) +{ + LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return;); + if (buf->p != NULL) { + pbuf_free(buf->p); + } + buf->p = buf->ptr = NULL; +} + +/** + * Let a netbuf reference existing (non-volatile) data. + * + * @param buf netbuf which should reference the data + * @param dataptr pointer to the data to reference + * @param size size of the data + * @return ERR_OK if data is referenced + * ERR_MEM if data couldn't be referenced due to lack of memory + */ +err_t +netbuf_ref(struct netbuf *buf, const void *dataptr, u16_t size) +{ + LWIP_ERROR("netbuf_ref: invalid buf", (buf != NULL), return ERR_ARG;); + if (buf->p != NULL) { + pbuf_free(buf->p); + } + buf->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF); + if (buf->p == NULL) { + buf->ptr = NULL; + return ERR_MEM; + } + buf->p->payload = (void*)dataptr; + buf->p->len = buf->p->tot_len = size; + buf->ptr = buf->p; + return ERR_OK; +} + +/** + * Chain one netbuf to another (@see pbuf_chain) + * + * @param head the first netbuf + * @param tail netbuf to chain after head, freed by this function, may not be reference after returning + */ +void +netbuf_chain(struct netbuf *head, struct netbuf *tail) +{ + LWIP_ERROR("netbuf_ref: invalid head", (head != NULL), return;); + LWIP_ERROR("netbuf_chain: invalid tail", (tail != NULL), return;); + pbuf_cat(head->p, tail->p); + head->ptr = head->p; + memp_free(MEMP_NETBUF, tail); +} + +/** + * Get the data pointer and length of the data inside a netbuf. + * + * @param buf netbuf to get the data from + * @param dataptr pointer to a void pointer where to store the data pointer + * @param len pointer to an u16_t where the length of the data is stored + * @return ERR_OK if the information was retrieved, + * ERR_BUF on error. + */ +err_t +netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len) +{ + LWIP_ERROR("netbuf_data: invalid buf", (buf != NULL), return ERR_ARG;); + LWIP_ERROR("netbuf_data: invalid dataptr", (dataptr != NULL), return ERR_ARG;); + LWIP_ERROR("netbuf_data: invalid len", (len != NULL), return ERR_ARG;); + + if (buf->ptr == NULL) { + return ERR_BUF; + } + *dataptr = buf->ptr->payload; + *len = buf->ptr->len; + return ERR_OK; +} + +/** + * Move the current data pointer of a packet buffer contained in a netbuf + * to the next part. + * The packet buffer itself is not modified. + * + * @param buf the netbuf to modify + * @return -1 if there is no next part + * 1 if moved to the next part but now there is no next part + * 0 if moved to the next part and there are still more parts + */ +s8_t +netbuf_next(struct netbuf *buf) +{ + LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return -1;); + if (buf->ptr->next == NULL) { + return -1; + } + buf->ptr = buf->ptr->next; + if (buf->ptr->next == NULL) { + return 1; + } + return 0; +} + +/** + * Move the current data pointer of a packet buffer contained in a netbuf + * to the beginning of the packet. + * The packet buffer itself is not modified. + * + * @param buf the netbuf to modify + */ +void +netbuf_first(struct netbuf *buf) +{ + LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return;); + buf->ptr = buf->p; +} + +#endif /* LWIP_NETCONN */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/api/netdb.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/api/netdb.c new file mode 100644 index 0000000..ad93944 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/api/netdb.c @@ -0,0 +1,349 @@ +/** + * @file + * API functions for name resolving + * + */ + +/* + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Simon Goldschmidt + * + */ + +#include "lwip/netdb.h" + +#if LWIP_DNS && LWIP_SOCKET + +#include "lwip/err.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/ip_addr.h" +#include "lwip/api.h" +#include "lwip/dns.h" + +#include +#include + +/** helper struct for gethostbyname_r to access the char* buffer */ +struct gethostbyname_r_helper { + ip_addr_t *addr_list[2]; + ip_addr_t addr; + char *aliases; +}; + +/** h_errno is exported in netdb.h for access by applications. */ +#if LWIP_DNS_API_DECLARE_H_ERRNO +int h_errno; +#endif /* LWIP_DNS_API_DECLARE_H_ERRNO */ + +/** define "hostent" variables storage: 0 if we use a static (but unprotected) + * set of variables for lwip_gethostbyname, 1 if we use a local storage */ +#ifndef LWIP_DNS_API_HOSTENT_STORAGE +#define LWIP_DNS_API_HOSTENT_STORAGE 0 +#endif + +/** define "hostent" variables storage */ +#if LWIP_DNS_API_HOSTENT_STORAGE +#define HOSTENT_STORAGE +#else +#define HOSTENT_STORAGE static +#endif /* LWIP_DNS_API_STATIC_HOSTENT */ + +/** + * Returns an entry containing addresses of address family AF_INET + * for the host with name name. + * Due to dns_gethostbyname limitations, only one address is returned. + * + * @param name the hostname to resolve + * @return an entry containing addresses of address family AF_INET + * for the host with name name + */ +struct hostent* +lwip_gethostbyname(const char *name) +{ + err_t err; + ip_addr_t addr; + + /* buffer variables for lwip_gethostbyname() */ + HOSTENT_STORAGE struct hostent s_hostent; + HOSTENT_STORAGE char *s_aliases; + HOSTENT_STORAGE ip_addr_t s_hostent_addr; + HOSTENT_STORAGE ip_addr_t *s_phostent_addr[2]; + + /* query host IP address */ + err = netconn_gethostbyname(name, &addr); + if (err != ERR_OK) { + LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err)); + h_errno = HOST_NOT_FOUND; + return NULL; + } + + /* fill hostent */ + s_hostent_addr = addr; + s_phostent_addr[0] = &s_hostent_addr; + s_phostent_addr[1] = NULL; + s_hostent.h_name = (char*)name; + s_aliases = NULL; + s_hostent.h_aliases = &s_aliases; + s_hostent.h_addrtype = AF_INET; + s_hostent.h_length = sizeof(ip_addr_t); + s_hostent.h_addr_list = (char**)&s_phostent_addr; + +#if DNS_DEBUG + /* dump hostent */ + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_name == %s\n", s_hostent.h_name)); + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases == %p\n", s_hostent.h_aliases)); + /* h_aliases are always empty */ + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addrtype == %d\n", s_hostent.h_addrtype)); + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_length == %d\n", s_hostent.h_length)); + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list == %p\n", s_hostent.h_addr_list)); + if (s_hostent.h_addr_list != NULL) { + u8_t idx; + for ( idx=0; s_hostent.h_addr_list[idx]; idx++) { + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i] == %p\n", idx, s_hostent.h_addr_list[idx])); + LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i]-> == %s\n", idx, ip_ntoa((ip_addr_t*)s_hostent.h_addr_list[idx]))); + } + } +#endif /* DNS_DEBUG */ + +#if LWIP_DNS_API_HOSTENT_STORAGE + /* this function should return the "per-thread" hostent after copy from s_hostent */ + return sys_thread_hostent(&s_hostent); +#else + return &s_hostent; +#endif /* LWIP_DNS_API_HOSTENT_STORAGE */ +} + +/** + * Thread-safe variant of lwip_gethostbyname: instead of using a static + * buffer, this function takes buffer and errno pointers as arguments + * and uses these for the result. + * + * @param name the hostname to resolve + * @param ret pre-allocated struct where to store the result + * @param buf pre-allocated buffer where to store additional data + * @param buflen the size of buf + * @param result pointer to a hostent pointer that is set to ret on success + * and set to zero on error + * @param h_errnop pointer to an int where to store errors (instead of modifying + * the global h_errno) + * @return 0 on success, non-zero on error, additional error information + * is stored in *h_errnop instead of h_errno to be thread-safe + */ +int +lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf, + size_t buflen, struct hostent **result, int *h_errnop) +{ + err_t err; + struct gethostbyname_r_helper *h; + char *hostname; + size_t namelen; + int lh_errno; + + if (h_errnop == NULL) { + /* ensure h_errnop is never NULL */ + h_errnop = &lh_errno; + } + + if (result == NULL) { + /* not all arguments given */ + *h_errnop = EINVAL; + return -1; + } + /* first thing to do: set *result to nothing */ + *result = NULL; + if ((name == NULL) || (ret == NULL) || (buf == NULL)) { + /* not all arguments given */ + *h_errnop = EINVAL; + return -1; + } + + namelen = strlen(name); + if (buflen < (sizeof(struct gethostbyname_r_helper) + namelen + 1 + (MEM_ALIGNMENT - 1))) { + /* buf can't hold the data needed + a copy of name */ + *h_errnop = ERANGE; + return -1; + } + + h = (struct gethostbyname_r_helper*)LWIP_MEM_ALIGN(buf); + hostname = ((char*)h) + sizeof(struct gethostbyname_r_helper); + + /* query host IP address */ + err = netconn_gethostbyname(name, &h->addr); + if (err != ERR_OK) { + LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err)); + *h_errnop = HOST_NOT_FOUND; + return -1; + } + + /* copy the hostname into buf */ + MEMCPY(hostname, name, namelen); + hostname[namelen] = 0; + + /* fill hostent */ + h->addr_list[0] = &h->addr; + h->addr_list[1] = NULL; + h->aliases = NULL; + ret->h_name = hostname; + ret->h_aliases = &h->aliases; + ret->h_addrtype = AF_INET; + ret->h_length = sizeof(ip_addr_t); + ret->h_addr_list = (char**)&h->addr_list; + + /* set result != NULL */ + *result = ret; + + /* return success */ + return 0; +} + +/** + * Frees one or more addrinfo structures returned by getaddrinfo(), along with + * any additional storage associated with those structures. If the ai_next field + * of the structure is not null, the entire list of structures is freed. + * + * @param ai struct addrinfo to free + */ +void +lwip_freeaddrinfo(struct addrinfo *ai) +{ + struct addrinfo *next; + + while (ai != NULL) { + next = ai->ai_next; + memp_free(MEMP_NETDB, ai); + ai = next; + } +} + +/** + * Translates the name of a service location (for example, a host name) and/or + * a service name and returns a set of socket addresses and associated + * information to be used in creating a socket with which to address the + * specified service. + * Memory for the result is allocated internally and must be freed by calling + * lwip_freeaddrinfo()! + * + * Due to a limitation in dns_gethostbyname, only the first address of a + * host is returned. + * Also, service names are not supported (only port numbers)! + * + * @param nodename descriptive name or address string of the host + * (may be NULL -> local address) + * @param servname port number as string of NULL + * @param hints structure containing input values that set socktype and protocol + * @param res pointer to a pointer where to store the result (set to NULL on failure) + * @return 0 on success, non-zero on failure + */ +int +lwip_getaddrinfo(const char *nodename, const char *servname, + const struct addrinfo *hints, struct addrinfo **res) +{ + err_t err; + ip_addr_t addr; + struct addrinfo *ai; + struct sockaddr_in *sa = NULL; + int port_nr = 0; + size_t total_size; + size_t namelen = 0; + + if (res == NULL) { + return EAI_FAIL; + } + *res = NULL; + if ((nodename == NULL) && (servname == NULL)) { + return EAI_NONAME; + } + + if (hints != NULL) { + if ((hints->ai_family != AF_UNSPEC) && (hints->ai_family != AF_INET)) { + return EAI_FAMILY; + } + } + + if (servname != NULL) { + /* service name specified: convert to port number + * @todo?: currently, only ASCII integers (port numbers) are supported! */ + port_nr = atoi(servname); + if ((port_nr <= 0) || (port_nr > 0xffff)) { + return EAI_SERVICE; + } + } + + if (nodename != NULL) { + /* service location specified, try to resolve */ + err = netconn_gethostbyname(nodename, &addr); + if (err != ERR_OK) { + return EAI_FAIL; + } + } else { + /* service location specified, use loopback address */ + ip_addr_set_loopback(&addr); + } + + total_size = sizeof(struct addrinfo) + sizeof(struct sockaddr_in); + if (nodename != NULL) { + namelen = strlen(nodename); + LWIP_ASSERT("namelen is too long", (namelen + 1) <= (mem_size_t)-1); + total_size += namelen + 1; + } + /* If this fails, please report to lwip-devel! :-) */ + LWIP_ASSERT("total_size <= NETDB_ELEM_SIZE: please report this!", + total_size <= NETDB_ELEM_SIZE); + ai = (struct addrinfo *)memp_malloc(MEMP_NETDB); + if (ai == NULL) { + return EAI_MEMORY; + } + memset(ai, 0, total_size); + sa = (struct sockaddr_in*)((u8_t*)ai + sizeof(struct addrinfo)); + /* set up sockaddr */ + inet_addr_from_ipaddr(&sa->sin_addr, &addr); + sa->sin_family = AF_INET; + sa->sin_len = sizeof(struct sockaddr_in); + sa->sin_port = htons((u16_t)port_nr); + + /* set up addrinfo */ + ai->ai_family = AF_INET; + if (hints != NULL) { + /* copy socktype & protocol from hints if specified */ + ai->ai_socktype = hints->ai_socktype; + ai->ai_protocol = hints->ai_protocol; + } + if (nodename != NULL) { + /* copy nodename to canonname if specified */ + ai->ai_canonname = ((char*)ai + sizeof(struct addrinfo) + sizeof(struct sockaddr_in)); + MEMCPY(ai->ai_canonname, nodename, namelen); + ai->ai_canonname[namelen] = 0; + } + ai->ai_addrlen = sizeof(struct sockaddr_in); + ai->ai_addr = (struct sockaddr*)sa; + + *res = ai; + + return 0; +} + +#endif /* LWIP_DNS && LWIP_SOCKET */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/api/netifapi.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/api/netifapi.c new file mode 100644 index 0000000..715d515 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/api/netifapi.c @@ -0,0 +1,204 @@ +/** + * @file + * Network Interface Sequential API module + * + */ + +/* + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/opt.h" + +#if LWIP_NETIF_API /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/netifapi.h" +#include "lwip/tcpip.h" +#include "lwip/memp.h" + +#define NETIFAPI_VAR_REF(name) API_VAR_REF(name) +#define NETIFAPI_VAR_DECLARE(name) API_VAR_DECLARE(struct netifapi_msg, name) +#define NETIFAPI_VAR_ALLOC(name) API_VAR_ALLOC(struct netifapi_msg, MEMP_NETIFAPI_MSG, name) +#define NETIFAPI_VAR_FREE(name) API_VAR_FREE(MEMP_NETIFAPI_MSG, name) + +/** + * Call netif_add() inside the tcpip_thread context. + */ +static void +netifapi_do_netif_add(struct netifapi_msg_msg *msg) +{ + if (!netif_add( msg->netif, + API_EXPR_REF(msg->msg.add.ipaddr), + API_EXPR_REF(msg->msg.add.netmask), + API_EXPR_REF(msg->msg.add.gw), + msg->msg.add.state, + msg->msg.add.init, + msg->msg.add.input)) { + msg->err = ERR_IF; + } else { + msg->err = ERR_OK; + } + TCPIP_NETIFAPI_ACK(msg); +} + +/** + * Call netif_set_addr() inside the tcpip_thread context. + */ +static void +netifapi_do_netif_set_addr(struct netifapi_msg_msg *msg) +{ + netif_set_addr( msg->netif, + API_EXPR_REF(msg->msg.add.ipaddr), + API_EXPR_REF(msg->msg.add.netmask), + API_EXPR_REF(msg->msg.add.gw)); + msg->err = ERR_OK; + TCPIP_NETIFAPI_ACK(msg); +} + +/** + * Call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) inside the + * tcpip_thread context. + */ +static void +netifapi_do_netif_common(struct netifapi_msg_msg *msg) +{ + if (msg->msg.common.errtfunc != NULL) { + msg->err = msg->msg.common.errtfunc(msg->netif); + } else { + msg->err = ERR_OK; + msg->msg.common.voidfunc(msg->netif); + } + TCPIP_NETIFAPI_ACK(msg); +} + +/** + * Call netif_add() in a thread-safe way by running that function inside the + * tcpip_thread context. + * + * @note for params @see netif_add() + */ +err_t +netifapi_netif_add(struct netif *netif, + ip_addr_t *ipaddr, + ip_addr_t *netmask, + ip_addr_t *gw, + void *state, + netif_init_fn init, + netif_input_fn input) +{ + err_t err; + NETIFAPI_VAR_DECLARE(msg); + NETIFAPI_VAR_ALLOC(msg); +#if LWIP_MPU_COMPATIBLE + if (ipaddr == NULL) { + ipaddr = IP_ADDR_ANY; + } + if (netmask == NULL) { + netmask = IP_ADDR_ANY; + } + if (gw == NULL) { + gw = IP_ADDR_ANY; + } +#endif /* LWIP_MPU_COMPATIBLE */ + NETIFAPI_VAR_REF(msg).function = netifapi_do_netif_add; + NETIFAPI_VAR_REF(msg).msg.netif = netif; + NETIFAPI_VAR_REF(msg).msg.msg.add.ipaddr = NETIFAPI_VAR_REF(ipaddr); + NETIFAPI_VAR_REF(msg).msg.msg.add.netmask = NETIFAPI_VAR_REF(netmask); + NETIFAPI_VAR_REF(msg).msg.msg.add.gw = NETIFAPI_VAR_REF(gw); + NETIFAPI_VAR_REF(msg).msg.msg.add.state = state; + NETIFAPI_VAR_REF(msg).msg.msg.add.init = init; + NETIFAPI_VAR_REF(msg).msg.msg.add.input = input; + TCPIP_NETIFAPI(&API_VAR_REF(msg)); + + err = NETIFAPI_VAR_REF(msg).msg.err; + NETIFAPI_VAR_FREE(msg); + return err; +} + +/** + * Call netif_set_addr() in a thread-safe way by running that function inside the + * tcpip_thread context. + * + * @note for params @see netif_set_addr() + */ +err_t +netifapi_netif_set_addr(struct netif *netif, + ip_addr_t *ipaddr, + ip_addr_t *netmask, + ip_addr_t *gw) +{ + err_t err; + NETIFAPI_VAR_DECLARE(msg); + NETIFAPI_VAR_ALLOC(msg); +#if LWIP_MPU_COMPATIBLE + if (ipaddr == NULL) { + ipaddr = IP_ADDR_ANY; + } + if (netmask == NULL) { + netmask = IP_ADDR_ANY; + } + if (gw == NULL) { + gw = IP_ADDR_ANY; + } +#endif /* LWIP_MPU_COMPATIBLE */ + NETIFAPI_VAR_REF(msg).function = netifapi_do_netif_set_addr; + NETIFAPI_VAR_REF(msg).msg.netif = netif; + NETIFAPI_VAR_REF(msg).msg.msg.add.ipaddr = NETIFAPI_VAR_REF(ipaddr); + NETIFAPI_VAR_REF(msg).msg.msg.add.netmask = NETIFAPI_VAR_REF(netmask); + NETIFAPI_VAR_REF(msg).msg.msg.add.gw = NETIFAPI_VAR_REF(gw); + TCPIP_NETIFAPI(&API_VAR_REF(msg)); + + err = NETIFAPI_VAR_REF(msg).msg.err; + NETIFAPI_VAR_FREE(msg); + return err; +} + +/** + * call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) in a thread-safe + * way by running that function inside the tcpip_thread context. + * + * @note use only for functions where there is only "netif" parameter. + */ +err_t +netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc, + netifapi_errt_fn errtfunc) +{ + err_t err; + NETIFAPI_VAR_DECLARE(msg); + NETIFAPI_VAR_ALLOC(msg); + + NETIFAPI_VAR_REF(msg).function = netifapi_do_netif_common; + NETIFAPI_VAR_REF(msg).msg.netif = netif; + NETIFAPI_VAR_REF(msg).msg.msg.common.voidfunc = voidfunc; + NETIFAPI_VAR_REF(msg).msg.msg.common.errtfunc = errtfunc; + TCPIP_NETIFAPI(&API_VAR_REF(msg)); + + err = NETIFAPI_VAR_REF(msg).msg.err; + NETIFAPI_VAR_FREE(msg); + return err; +} + +#endif /* LWIP_NETIF_API */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/api/pppapi.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/api/pppapi.c new file mode 100644 index 0000000..10e4b82 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/api/pppapi.c @@ -0,0 +1,439 @@ +/** + * @file + * Point To Point Protocol Sequential API module + * + */ + +/* + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/opt.h" + +#if LWIP_PPP_API /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pppapi.h" +#include "lwip/tcpip.h" + +/** + * Call ppp_new() inside the tcpip_thread context. + */ +static void +pppapi_do_ppp_new(struct pppapi_msg_msg *msg) +{ + msg->ppp = ppp_new(); + TCPIP_PPPAPI_ACK(msg); +} + +/** + * Call ppp_new() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +ppp_pcb* +pppapi_new(void) +{ + struct pppapi_msg msg; + msg.function = pppapi_do_ppp_new; + TCPIP_PPPAPI(&msg); + return msg.msg.ppp; +} + + +/** + * Call ppp_set_default() inside the tcpip_thread context. + */ +static void +pppapi_do_ppp_set_default(struct pppapi_msg_msg *msg) +{ + ppp_set_default(msg->ppp); + TCPIP_PPPAPI_ACK(msg); +} + +/** + * Call ppp_set_default() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +void +pppapi_set_default(ppp_pcb *pcb) +{ + struct pppapi_msg msg; + msg.function = pppapi_do_ppp_set_default; + msg.msg.ppp = pcb; + TCPIP_PPPAPI(&msg); +} + + +/** + * Call ppp_set_auth() inside the tcpip_thread context. + */ +static void +pppapi_do_ppp_set_auth(struct pppapi_msg_msg *msg) +{ + ppp_set_auth(msg->ppp, msg->msg.setauth.authtype, + msg->msg.setauth.user, msg->msg.setauth.passwd); + TCPIP_PPPAPI_ACK(msg); +} + +/** + * Call ppp_set_auth() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +void +pppapi_set_auth(ppp_pcb *pcb, u8_t authtype, const char *user, const char *passwd) +{ + struct pppapi_msg msg; + msg.function = pppapi_do_ppp_set_auth; + msg.msg.ppp = pcb; + msg.msg.msg.setauth.authtype = authtype; + msg.msg.msg.setauth.user = user; + msg.msg.msg.setauth.passwd = passwd; + TCPIP_PPPAPI(&msg); +} + + +#if PPP_NOTIFY_PHASE +/** + * Call ppp_set_notify_phase_callback() inside the tcpip_thread context. + */ +static void +pppapi_do_ppp_set_notify_phase_callback(struct pppapi_msg_msg *msg) +{ + ppp_set_notify_phase_callback(msg->ppp, msg->msg.setnotifyphasecb.notify_phase_cb); + TCPIP_PPPAPI_ACK(msg); +} + +/** + * Call ppp_set_notify_phase_callback() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +void +pppapi_set_notify_phase_callback(ppp_pcb *pcb, ppp_notify_phase_cb_fn notify_phase_cb) +{ + struct pppapi_msg msg; + msg.function = pppapi_do_ppp_set_notify_phase_callback; + msg.msg.ppp = pcb; + msg.msg.msg.setnotifyphasecb.notify_phase_cb = notify_phase_cb; + TCPIP_PPPAPI(&msg); +} +#endif /* PPP_NOTIFY_PHASE */ + + +#if PPPOS_SUPPORT +/** + * Call ppp_over_serial_create() inside the tcpip_thread context. + */ +static void +pppapi_do_ppp_over_serial_create(struct pppapi_msg_msg *msg) +{ + msg->err = ppp_over_serial_create(msg->ppp, msg->msg.serialcreate.fd, + msg->msg.serialcreate.link_status_cb, msg->msg.serialcreate.ctx_cb); + TCPIP_PPPAPI_ACK(msg); +} + +/** + * Call ppp_over_serial_create() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +int +pppapi_over_serial_create(ppp_pcb *pcb, sio_fd_t fd, ppp_link_status_cb_fn link_status_cb, + void *ctx_cb) +{ + struct pppapi_msg msg; + msg.function = pppapi_do_ppp_over_serial_create; + msg.msg.ppp = pcb; + msg.msg.msg.serialcreate.fd = fd; + msg.msg.msg.serialcreate.link_status_cb = link_status_cb; + msg.msg.msg.serialcreate.ctx_cb = ctx_cb; + TCPIP_PPPAPI(&msg); + return msg.msg.err; +} +#endif /* PPPOS_SUPPORT */ + + +#if PPPOE_SUPPORT +/** + * Call ppp_over_ethernet_create() inside the tcpip_thread context. + */ +static void +pppapi_do_ppp_over_ethernet_create(struct pppapi_msg_msg *msg) +{ + + msg->err = ppp_over_ethernet_create(msg->ppp, msg->msg.ethernetcreate.ethif, + msg->msg.ethernetcreate.service_name, msg->msg.ethernetcreate.concentrator_name, + msg->msg.ethernetcreate.link_status_cb, msg->msg.ethernetcreate.ctx_cb); + TCPIP_PPPAPI_ACK(msg); +} + +/** + * Call ppp_over_ethernet_create() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +int +pppapi_over_ethernet_create(ppp_pcb *pcb, struct netif *ethif, const char *service_name, + const char *concentrator_name, ppp_link_status_cb_fn link_status_cb, + void *ctx_cb) +{ + struct pppapi_msg msg; + msg.function = pppapi_do_ppp_over_ethernet_create; + msg.msg.ppp = pcb; + msg.msg.msg.ethernetcreate.ethif = ethif; + msg.msg.msg.ethernetcreate.service_name = service_name; + msg.msg.msg.ethernetcreate.concentrator_name = concentrator_name; + msg.msg.msg.ethernetcreate.link_status_cb = link_status_cb; + msg.msg.msg.ethernetcreate.ctx_cb = ctx_cb; + TCPIP_PPPAPI(&msg); + return msg.msg.err; +} +#endif /* PPPOE_SUPPORT */ + + +#if PPPOL2TP_SUPPORT +/** + * Call ppp_over_l2tp_create() inside the tcpip_thread context. + */ +static void +pppapi_do_ppp_over_l2tp_create(struct pppapi_msg_msg *msg) +{ + msg->err = ppp_over_l2tp_create(msg->ppp, + msg->msg.l2tpcreate.netif, msg->msg.l2tpcreate.ipaddr, msg->msg.l2tpcreate.port, +#if PPPOL2TP_AUTH_SUPPORT + msg->msg.l2tpcreate.secret, + msg->msg.l2tpcreate.secret_len, +#else /* PPPOL2TP_AUTH_SUPPORT */ + NULL, +#endif /* PPPOL2TP_AUTH_SUPPORT */ + msg->msg.l2tpcreate.link_status_cb, msg->msg.l2tpcreate.ctx_cb); + TCPIP_PPPAPI_ACK(msg); +} + +/** + * Call ppp_over_l2tp_create() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +int +pppapi_over_l2tp_create(ppp_pcb *pcb, struct netif *netif, ip_addr_t *ipaddr, u16_t port, + u8_t *secret, u8_t secret_len, + ppp_link_status_cb_fn link_status_cb, void *ctx_cb) +{ + struct pppapi_msg msg; + msg.function = pppapi_do_ppp_over_l2tp_create; + msg.msg.ppp = pcb; + msg.msg.msg.l2tpcreate.netif = netif; + msg.msg.msg.l2tpcreate.ipaddr = ipaddr; + msg.msg.msg.l2tpcreate.port = port; +#if PPPOL2TP_AUTH_SUPPORT + msg.msg.msg.l2tpcreate.secret = secret; + msg.msg.msg.l2tpcreate.secret_len = secret_len; +#endif /* PPPOL2TP_AUTH_SUPPORT */ + msg.msg.msg.l2tpcreate.link_status_cb = link_status_cb; + msg.msg.msg.l2tpcreate.ctx_cb = ctx_cb; + TCPIP_PPPAPI(&msg); + return msg.msg.err; +} +#endif /* PPPOL2TP_SUPPORT */ + + +/** + * Call ppp_open() inside the tcpip_thread context. + */ +static void +pppapi_do_ppp_open(struct pppapi_msg_msg *msg) +{ + msg->err = ppp_open(msg->ppp, msg->msg.open.holdoff); + TCPIP_PPPAPI_ACK(msg); +} + +/** + * Call ppp_open() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +int +pppapi_open(ppp_pcb *pcb, u16_t holdoff) +{ + struct pppapi_msg msg; + msg.function = pppapi_do_ppp_open; + msg.msg.ppp = pcb; + msg.msg.msg.open.holdoff = holdoff; + TCPIP_PPPAPI(&msg); + return msg.msg.err; +} + + +/** + * Call ppp_close() inside the tcpip_thread context. + */ +static void +pppapi_do_ppp_close(struct pppapi_msg_msg *msg) +{ + msg->err = ppp_close(msg->ppp); + TCPIP_PPPAPI_ACK(msg); +} + +/** + * Call ppp_close() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +int +pppapi_close(ppp_pcb *pcb) +{ + struct pppapi_msg msg; + msg.function = pppapi_do_ppp_close; + msg.msg.ppp = pcb; + TCPIP_PPPAPI(&msg); + return msg.msg.err; +} + + +/** + * Call ppp_sighup() inside the tcpip_thread context. + */ +static void +pppapi_do_ppp_sighup(struct pppapi_msg_msg *msg) +{ + ppp_sighup(msg->ppp); + TCPIP_PPPAPI_ACK(msg); +} + +/** + * Call ppp_sighup() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +void +pppapi_sighup(ppp_pcb *pcb) +{ + struct pppapi_msg msg; + msg.function = pppapi_do_ppp_sighup; + msg.msg.ppp = pcb; + TCPIP_PPPAPI(&msg); +} + + +/** + * Call ppp_delete() inside the tcpip_thread context. + */ +static void +pppapi_do_ppp_delete(struct pppapi_msg_msg *msg) +{ + msg->err = ppp_delete(msg->ppp); + TCPIP_PPPAPI_ACK(msg); +} + +/** + * Call ppp_delete() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +int +pppapi_delete(ppp_pcb *pcb) +{ + struct pppapi_msg msg; + msg.function = pppapi_do_ppp_delete; + msg.msg.ppp = pcb; + TCPIP_PPPAPI(&msg); + return msg.msg.err; +} + + +/** + * Call ppp_ioctl() inside the tcpip_thread context. + */ +static void +pppapi_do_ppp_ioctl(struct pppapi_msg_msg *msg) +{ + msg->err = ppp_ioctl(msg->ppp, msg->msg.ioctl.cmd, msg->msg.ioctl.arg); + TCPIP_PPPAPI_ACK(msg); +} + +/** + * Call ppp_ioctl() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +int +pppapi_ioctl(ppp_pcb *pcb, int cmd, void *arg) +{ + struct pppapi_msg msg; + msg.function = pppapi_do_ppp_ioctl; + msg.msg.ppp = pcb; + msg.msg.msg.ioctl.cmd = cmd; + msg.msg.msg.ioctl.arg = arg; + TCPIP_PPPAPI(&msg); + return msg.msg.err; +} + + +#if LWIP_NETIF_STATUS_CALLBACK +/** + * Call ppp_set_netif_statuscallback() inside the tcpip_thread context. + */ +static void +pppapi_do_ppp_set_netif_statuscallback(struct pppapi_msg_msg *msg) +{ + ppp_set_netif_statuscallback(msg->ppp, msg->msg.netifstatuscallback.status_callback); + TCPIP_PPPAPI_ACK(msg); +} + +/** + * Call ppp_set_netif_statuscallback() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +void +pppapi_set_netif_statuscallback(ppp_pcb *pcb, netif_status_callback_fn status_callback) +{ + struct pppapi_msg msg; + msg.function = pppapi_do_ppp_set_netif_statuscallback; + msg.msg.ppp = pcb; + msg.msg.msg.netifstatuscallback.status_callback = status_callback; + TCPIP_PPPAPI(&msg); +} +#endif /* LWIP_NETIF_STATUS_CALLBACK */ + + +#if LWIP_NETIF_LINK_CALLBACK +/** + * Call ppp_set_netif_linkcallback() inside the tcpip_thread context. + */ +static void +pppapi_do_ppp_set_netif_linkcallback(struct pppapi_msg_msg *msg) +{ + ppp_set_netif_linkcallback(msg->ppp, msg->msg.netiflinkcallback.link_callback); + TCPIP_PPPAPI_ACK(msg); +} + +/** + * Call ppp_set_netif_linkcallback() in a thread-safe way by running that function inside the + * tcpip_thread context. + */ +void +pppapi_set_netif_linkcallback(ppp_pcb *pcb, netif_status_callback_fn link_callback) +{ + struct pppapi_msg msg; + msg.function = pppapi_do_ppp_set_netif_linkcallback; + msg.msg.ppp = pcb; + msg.msg.msg.netiflinkcallback.link_callback = link_callback; + TCPIP_PPPAPI(&msg); +} +#endif /* LWIP_NETIF_LINK_CALLBACK */ + +#endif /* LWIP_PPP_API */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/api/sockets.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/api/sockets.c new file mode 100644 index 0000000..60a8367 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/api/sockets.c @@ -0,0 +1,2480 @@ +/** + * @file + * Sockets BSD-Like API module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + * Improved by Marc Boucher and David Haas + * + */ + +#include "lwip/opt.h" + +#if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ +#include "lwip/arch.h" +#include "lwip/sockets.h" +#include "lwip/api.h" +#include "lwip/sys.h" +#include "lwip/igmp.h" +#include "lwip/inet.h" +#include "lwip/tcp.h" +#include "lwip/raw.h" +#include "lwip/udp.h" +#include "lwip/tcpip.h" +#include "lwip/memp.h" +#include "lwip/pbuf.h" +#if LWIP_CHECKSUM_ON_COPY +#include "lwip/inet_chksum.h" +#endif + +#include + +/* If the netconn API is not required publicly, then we include the necessary + files here to get the implementation */ +#if !LWIP_NETCONN +#undef LWIP_NETCONN +#define LWIP_NETCONN 1 +#include "api_msg.c" +#include "api_lib.c" +#include "netbuf.c" +#undef LWIP_NETCONN +#define LWIP_NETCONN 0 +#endif + +#define IP4ADDR_PORT_TO_SOCKADDR(sin, ipXaddr, port) do { \ + (sin)->sin_len = sizeof(struct sockaddr_in); \ + (sin)->sin_family = AF_INET; \ + (sin)->sin_port = htons((port)); \ + inet_addr_from_ipaddr(&(sin)->sin_addr, ipX_2_ip(ipXaddr)); \ + memset((sin)->sin_zero, 0, SIN_ZERO_LEN); }while(0) +#define SOCKADDR4_TO_IP4ADDR_PORT(sin, ipXaddr, port) do { \ + inet_addr_to_ipaddr(ipX_2_ip(ipXaddr), &((sin)->sin_addr)); \ + (port) = ntohs((sin)->sin_port); }while(0) + +#if LWIP_IPV6 +#define IS_SOCK_ADDR_LEN_VALID(namelen) (((namelen) == sizeof(struct sockaddr_in)) || \ + ((namelen) == sizeof(struct sockaddr_in6))) +#define IS_SOCK_ADDR_TYPE_VALID(name) (((name)->sa_family == AF_INET) || \ + ((name)->sa_family == AF_INET6)) +#define SOCK_ADDR_TYPE_MATCH(name, sock) \ + ((((name)->sa_family == AF_INET) && !(NETCONNTYPE_ISIPV6((sock)->conn->type))) || \ + (((name)->sa_family == AF_INET6) && (NETCONNTYPE_ISIPV6((sock)->conn->type)))) +#define IP6ADDR_PORT_TO_SOCKADDR(sin6, ipXaddr, port) do { \ + (sin6)->sin6_len = sizeof(struct sockaddr_in6); \ + (sin6)->sin6_family = AF_INET6; \ + (sin6)->sin6_port = htons((port)); \ + (sin6)->sin6_flowinfo = 0; \ + inet6_addr_from_ip6addr(&(sin6)->sin6_addr, ipX_2_ip6(ipXaddr)); }while(0) +#define IPXADDR_PORT_TO_SOCKADDR(isipv6, sockaddr, ipXaddr, port) do { \ + if (isipv6) { \ + IP6ADDR_PORT_TO_SOCKADDR((struct sockaddr_in6*)(void*)(sockaddr), ipXaddr, port); \ + } else { \ + IP4ADDR_PORT_TO_SOCKADDR((struct sockaddr_in*)(void*)(sockaddr), ipXaddr, port); \ + } } while(0) +#define SOCKADDR6_TO_IP6ADDR_PORT(sin6, ipXaddr, port) do { \ + inet6_addr_to_ip6addr(ipX_2_ip6(ipXaddr), &((sin6)->sin6_addr)); \ + (port) = ntohs((sin6)->sin6_port); }while(0) +#define SOCKADDR_TO_IPXADDR_PORT(isipv6, sockaddr, ipXaddr, port) do { \ + if (isipv6) { \ + SOCKADDR6_TO_IP6ADDR_PORT((struct sockaddr_in6*)(void*)(sockaddr), ipXaddr, port); \ + } else { \ + SOCKADDR4_TO_IP4ADDR_PORT((struct sockaddr_in*)(void*)(sockaddr), ipXaddr, port); \ + } } while(0) +#define DOMAIN_TO_NETCONN_TYPE(domain, type) (((domain) == AF_INET) ? \ + (type) : (enum netconn_type)((type) | NETCONN_TYPE_IPV6)) +#else /* LWIP_IPV6 */ +#define IS_SOCK_ADDR_LEN_VALID(namelen) ((namelen) == sizeof(struct sockaddr_in)) +#define IS_SOCK_ADDR_TYPE_VALID(name) ((name)->sa_family == AF_INET) +#define SOCK_ADDR_TYPE_MATCH(name, sock) 1 +#define IPXADDR_PORT_TO_SOCKADDR(isipv6, sockaddr, ipXaddr, port) \ + IP4ADDR_PORT_TO_SOCKADDR((struct sockaddr_in*)(void*)(sockaddr), ipXaddr, port) +#define SOCKADDR_TO_IPXADDR_PORT(isipv6, sockaddr, ipXaddr, port) \ + SOCKADDR4_TO_IP4ADDR_PORT((struct sockaddr_in*)(void*)(sockaddr), ipXaddr, port) +#define DOMAIN_TO_NETCONN_TYPE(domain, netconn_type) (netconn_type) +#endif /* LWIP_IPV6 */ + +#define IS_SOCK_ADDR_TYPE_VALID_OR_UNSPEC(name) (((name)->sa_family == AF_UNSPEC) || \ + IS_SOCK_ADDR_TYPE_VALID(name)) +#define SOCK_ADDR_TYPE_MATCH_OR_UNSPEC(name, sock) (((name)->sa_family == AF_UNSPEC) || \ + SOCK_ADDR_TYPE_MATCH(name, sock)) +#define IS_SOCK_ADDR_ALIGNED(name) ((((mem_ptr_t)(name)) % 4) == 0) + + +#define LWIP_SOCKOPT_CHECK_OPTLEN(optlen, opttype) do { if((optlen) < sizeof(opttype)) { return EINVAL; }}while(0) +#define LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, opttype) do { \ + LWIP_SOCKOPT_CHECK_OPTLEN(optlen, opttype); \ + if ((sock)->conn == NULL) { return EINVAL; } }while(0) +#define LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, opttype) do { \ + LWIP_SOCKOPT_CHECK_OPTLEN(optlen, opttype); \ + if (((sock)->conn == NULL) || ((sock)->conn->pcb.tcp == NULL)) { return EINVAL; } }while(0) +#define LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, opttype, netconntype) do { \ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, opttype); \ + if (NETCONNTYPE_GROUP(netconn_type((sock)->conn)) != netconntype) { return ENOPROTOOPT; } }while(0) + + +#define LWIP_SETGETSOCKOPT_DATA_VAR_REF(name) API_VAR_REF(name) +#define LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(name) API_VAR_DECLARE(struct lwip_setgetsockopt_data, name) +#define LWIP_SETGETSOCKOPT_DATA_VAR_FREE(name) API_VAR_FREE(MEMP_SOCKET_SETGETSOCKOPT_DATA, name) +#if LWIP_MPU_COMPATIBLE +#define LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(name, sock) do { \ + name = (struct lwip_setgetsockopt_data *)memp_malloc(MEMP_SOCKET_SETGETSOCKOPT_DATA); \ + if (name == NULL) { \ + sock_set_errno(sock, ENOMEM); \ + return -1; \ + } }while(0) +#else /* LWIP_MPU_COMPATIBLE */ +#define LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(name, sock) +#endif /* LWIP_MPU_COMPATIBLE */ + +#if LWIP_SO_SNDRCVTIMEO_NONSTANDARD +#define LWIP_SO_SNDRCVTIMEO_OPTTYPE int +#define LWIP_SO_SNDRCVTIMEO_SET(optval, val) (*(int *)(optval) = (val)) +#define LWIP_SO_SNDRCVTIMEO_GET_MS(optval) ((s32_t)*(int*)(optval)) +#else +#define LWIP_SO_SNDRCVTIMEO_OPTTYPE struct timeval +#define LWIP_SO_SNDRCVTIMEO_SET(optval, val) do { \ + s32_t loc = (val); \ + ((struct timeval *)(optval))->tv_sec = (loc) / 1000U; \ + ((struct timeval *)(optval))->tv_sec = ((loc) % 1000U) * 1000U; }while(0) +#define LWIP_SO_SNDRCVTIMEO_GET_MS(optval) ((((struct timeval *)(optval))->tv_sec * 1000U) + (((struct timeval *)(optval))->tv_usec / 1000U)) +#endif + +#define NUM_SOCKETS MEMP_NUM_NETCONN + +/** This is overridable for the rare case where more than 255 threads + * select on the same socket... + */ +#ifndef SELWAIT_T +#define SELWAIT_T u8_t +#endif + +/** Contains all internal pointers and states used for a socket */ +struct lwip_sock { + /** sockets currently are built on netconns, each socket has one netconn */ + struct netconn *conn; + /** data that was left from the previous read */ + void *lastdata; + /** offset in the data that was left from the previous read */ + u16_t lastoffset; + /** number of times data was received, set by event_callback(), + tested by the receive and select functions */ + s16_t rcvevent; + /** number of times data was ACKed (free send buffer), set by event_callback(), + tested by select */ + u16_t sendevent; + /** error happened for this socket, set by event_callback(), tested by select */ + u16_t errevent; + /** last error that occurred on this socket (in fact, all our errnos fit into an u8_t) */ + u8_t err; + /** counter of how many threads are waiting for this socket using select */ + SELWAIT_T select_waiting; +}; + +#if LWIP_NETCONN_SEM_PER_THREAD +#define SELECT_SEM_T sys_sem_t* +#define SELECT_SEM_PTR(sem) (sem) +#else /* LWIP_NETCONN_SEM_PER_THREAD */ +#define SELECT_SEM_T sys_sem_t +#define SELECT_SEM_PTR(sem) (&(sem)) +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + +/** Description for a task waiting in select */ +struct lwip_select_cb { + /** Pointer to the next waiting task */ + struct lwip_select_cb *next; + /** Pointer to the previous waiting task */ + struct lwip_select_cb *prev; + /** readset passed to select */ + fd_set *readset; + /** writeset passed to select */ + fd_set *writeset; + /** unimplemented: exceptset passed to select */ + fd_set *exceptset; + /** don't signal the same semaphore twice: set to 1 when signalled */ + int sem_signalled; + /** semaphore to wake up a task waiting for select */ + SELECT_SEM_T sem; +}; + +/** A struct sockaddr replacement that has the same alignment as sockaddr_in/ + * sockaddr_in6 if instantiated. + */ +union sockaddr_aligned { + struct sockaddr sa; +#if LWIP_IPV6 + struct sockaddr_in6 sin6; +#endif /* LWIP_IPV6 */ + struct sockaddr_in sin; +}; + + +/** The global array of available sockets */ +static struct lwip_sock sockets[NUM_SOCKETS]; +/** The global list of tasks waiting for select */ +static struct lwip_select_cb *select_cb_list; +/** This counter is increased from lwip_select when the list is chagned + and checked in event_callback to see if it has changed. */ +static volatile int select_cb_ctr; + +/** Table to quickly map an lwIP error (err_t) to a socket error + * by using -err as an index */ +static const int err_to_errno_table[] = { + 0, /* ERR_OK 0 No error, everything OK. */ + ENOMEM, /* ERR_MEM -1 Out of memory error. */ + ENOBUFS, /* ERR_BUF -2 Buffer error. */ + EWOULDBLOCK, /* ERR_TIMEOUT -3 Timeout */ + EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */ + EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */ + EINVAL, /* ERR_VAL -6 Illegal value. */ + EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */ + EADDRINUSE, /* ERR_USE -8 Address in use. */ + EALREADY, /* ERR_ISCONN -9 Already connected. */ + ENOTCONN, /* ERR_CONN -10 Not connected. */ + ECONNABORTED, /* ERR_ABRT -11 Connection aborted. */ + ECONNRESET, /* ERR_RST -12 Connection reset. */ + ENOTCONN, /* ERR_CLSD -13 Connection closed. */ + EIO, /* ERR_ARG -14 Illegal argument. */ + -1, /* ERR_IF -15 Low-level netif error */ +}; + +#define ERR_TO_ERRNO_TABLE_SIZE \ + (sizeof(err_to_errno_table)/sizeof(err_to_errno_table[0])) + +#define err_to_errno(err) \ + ((unsigned)(-(err)) < ERR_TO_ERRNO_TABLE_SIZE ? \ + err_to_errno_table[-(err)] : EIO) + +#if LWIP_SOCKET_SET_ERRNO +#ifndef set_errno +#define set_errno(err) do { if (err) { errno = (err); } } while(0) +#endif +#else /* LWIP_SOCKET_SET_ERRNO */ +#define set_errno(err) +#endif /* LWIP_SOCKET_SET_ERRNO */ + +#define sock_set_errno(sk, e) do { \ + sk->err = (e); \ + set_errno(sk->err); \ +} while (0) + +/* Forward declaration of some functions */ +static void event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len); +#if !LWIP_TCPIP_CORE_LOCKING +static void lwip_getsockopt_callback(void *arg); +static void lwip_setsockopt_callback(void *arg); +#endif +static u8_t lwip_getsockopt_impl(int s, int level, int optname, void *optval, socklen_t *optlen); +static u8_t lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_t optlen); + +/** + * Map a externally used socket index to the internal socket representation. + * + * @param s externally used socket index + * @return struct lwip_sock for the socket or NULL if not found + */ +static struct lwip_sock * +get_socket(int s) +{ + struct lwip_sock *sock; + + if ((s < 0) || (s >= NUM_SOCKETS)) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): invalid\n", s)); + set_errno(EBADF); + return NULL; + } + + sock = &sockets[s]; + + if (!sock->conn) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): not active\n", s)); + set_errno(EBADF); + return NULL; + } + + return sock; +} + +/** + * Same as get_socket but doesn't set errno + * + * @param s externally used socket index + * @return struct lwip_sock for the socket or NULL if not found + */ +static struct lwip_sock * +tryget_socket(int s) +{ + if ((s < 0) || (s >= NUM_SOCKETS)) { + return NULL; + } + if (!sockets[s].conn) { + return NULL; + } + return &sockets[s]; +} + +/** + * Allocate a new socket for a given netconn. + * + * @param newconn the netconn for which to allocate a socket + * @param accepted 1 if socket has been created by accept(), + * 0 if socket has been created by socket() + * @return the index of the new socket; -1 on error + */ +static int +alloc_socket(struct netconn *newconn, int accepted) +{ + int i; + SYS_ARCH_DECL_PROTECT(lev); + + /* allocate a new socket identifier */ + for (i = 0; i < NUM_SOCKETS; ++i) { + /* Protect socket array */ + SYS_ARCH_PROTECT(lev); + if (!sockets[i].conn) { + sockets[i].conn = newconn; + /* The socket is not yet known to anyone, so no need to protect + after having marked it as used. */ + SYS_ARCH_UNPROTECT(lev); + sockets[i].lastdata = NULL; + sockets[i].lastoffset = 0; + sockets[i].rcvevent = 0; + /* TCP sendbuf is empty, but the socket is not yet writable until connected + * (unless it has been created by accept()). */ + sockets[i].sendevent = (NETCONNTYPE_GROUP(newconn->type) == NETCONN_TCP ? (accepted != 0) : 1); + sockets[i].errevent = 0; + sockets[i].err = 0; + sockets[i].select_waiting = 0; + return i; + } + SYS_ARCH_UNPROTECT(lev); + } + return -1; +} + +/** Free a socket. The socket's netconn must have been + * delete before! + * + * @param sock the socket to free + * @param is_tcp != 0 for TCP sockets, used to free lastdata + */ +static void +free_socket(struct lwip_sock *sock, int is_tcp) +{ + void *lastdata; + SYS_ARCH_DECL_PROTECT(lev); + + lastdata = sock->lastdata; + sock->lastdata = NULL; + sock->lastoffset = 0; + sock->err = 0; + + /* Protect socket array */ + SYS_ARCH_PROTECT(lev); + sock->conn = NULL; + SYS_ARCH_UNPROTECT(lev); + /* don't use 'sock' after this line, as another task might have allocated it */ + + if (lastdata != NULL) { + if (is_tcp) { + pbuf_free((struct pbuf *)lastdata); + } else { + netbuf_delete((struct netbuf *)lastdata); + } + } +} + +/* Below this, the well-known socket functions are implemented. + * Use google.com or opengroup.org to get a good description :-) + * + * Exceptions are documented! + */ + +int +lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen) +{ + struct lwip_sock *sock, *nsock; + struct netconn *newconn; + ipX_addr_t naddr; + u16_t port = 0; + int newsock; + err_t err; + SYS_ARCH_DECL_PROTECT(lev); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s)); + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (netconn_is_nonblocking(sock->conn) && (sock->rcvevent <= 0)) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): returning EWOULDBLOCK\n", s)); + sock_set_errno(sock, EWOULDBLOCK); + return -1; + } + + /* wait for a new connection */ + err = netconn_accept(sock->conn, &newconn); + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_acept failed, err=%d\n", s, err)); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { + sock_set_errno(sock, EOPNOTSUPP); + return EOPNOTSUPP; + } + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + LWIP_ASSERT("newconn != NULL", newconn != NULL); + /* Prevent automatic window updates, we do this on our own! */ + netconn_set_noautorecved(newconn, 1); + + /* Note that POSIX only requires us to check addr is non-NULL. addrlen must + * not be NULL if addr is valid. + */ + if (addr != NULL) { + union sockaddr_aligned tempaddr; + /* get the IP address and port of the remote host */ + err = netconn_peer(newconn, ipX_2_ip(&naddr), &port); + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_peer failed, err=%d\n", s, err)); + netconn_delete(newconn); + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + LWIP_ASSERT("addr valid but addrlen NULL", addrlen != NULL); + + IPXADDR_PORT_TO_SOCKADDR(NETCONNTYPE_ISIPV6(newconn->type), &tempaddr, &naddr, port); + if (*addrlen > tempaddr.sa.sa_len) { + *addrlen = tempaddr.sa.sa_len; + } + MEMCPY(addr, &tempaddr, *addrlen); + } + + newsock = alloc_socket(newconn, 1); + if (newsock == -1) { + netconn_delete(newconn); + sock_set_errno(sock, ENFILE); + return -1; + } + LWIP_ASSERT("invalid socket index", (newsock >= 0) && (newsock < NUM_SOCKETS)); + LWIP_ASSERT("newconn->callback == event_callback", newconn->callback == event_callback); + nsock = &sockets[newsock]; + + /* See event_callback: If data comes in right away after an accept, even + * though the server task might not have created a new socket yet. + * In that case, newconn->socket is counted down (newconn->socket--), + * so nsock->rcvevent is >= 1 here! + */ + SYS_ARCH_PROTECT(lev); + nsock->rcvevent += (s16_t)(-1 - newconn->socket); + newconn->socket = newsock; + SYS_ARCH_UNPROTECT(lev); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d", s, newsock)); + if (addr != NULL) { + LWIP_DEBUGF(SOCKETS_DEBUG, (" addr=")); + ipX_addr_debug_print(NETCONNTYPE_ISIPV6(newconn->type), SOCKETS_DEBUG, &naddr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", port)); + } + + sock_set_errno(sock, 0); + return newsock; +} + +int +lwip_bind(int s, const struct sockaddr *name, socklen_t namelen) +{ + struct lwip_sock *sock; + ipX_addr_t local_addr; + u16_t local_port; + err_t err; + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (!SOCK_ADDR_TYPE_MATCH(name, sock)) { + /* sockaddr does not match socket type (IPv4/IPv6) */ + sock_set_errno(sock, err_to_errno(ERR_VAL)); + return -1; + } + + /* check size, family and alignment of 'name' */ + LWIP_ERROR("lwip_bind: invalid address", (IS_SOCK_ADDR_LEN_VALID(namelen) && + IS_SOCK_ADDR_TYPE_VALID(name) && IS_SOCK_ADDR_ALIGNED(name)), + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + LWIP_UNUSED_ARG(namelen); + + SOCKADDR_TO_IPXADDR_PORT((name->sa_family == AF_INET6), name, &local_addr, local_port); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s)); + ipX_addr_debug_print(name->sa_family == AF_INET6, SOCKETS_DEBUG, &local_addr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", local_port)); + + err = netconn_bind(sock->conn, ipX_2_ip(&local_addr), local_port); + + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) failed, err=%d\n", s, err)); + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) succeeded\n", s)); + sock_set_errno(sock, 0); + return 0; +} + +int +lwip_close(int s) +{ + struct lwip_sock *sock; + int is_tcp = 0; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_close(%d)\n", s)); + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if(sock->conn != NULL) { + is_tcp = NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP; + } else { + LWIP_ASSERT("sock->lastdata == NULL", sock->lastdata == NULL); + } + + netconn_delete(sock->conn); + + free_socket(sock, is_tcp); + set_errno(0); + return 0; +} + +int +lwip_connect(int s, const struct sockaddr *name, socklen_t namelen) +{ + struct lwip_sock *sock; + err_t err; + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (!SOCK_ADDR_TYPE_MATCH_OR_UNSPEC(name, sock)) { + /* sockaddr does not match socket type (IPv4/IPv6) */ + sock_set_errno(sock, err_to_errno(ERR_VAL)); + return -1; + } + + LWIP_UNUSED_ARG(namelen); + if (name->sa_family == AF_UNSPEC) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, AF_UNSPEC)\n", s)); + err = netconn_disconnect(sock->conn); + } else { + ipX_addr_t remote_addr; + u16_t remote_port; + + /* check size, family and alignment of 'name' */ + LWIP_ERROR("lwip_connect: invalid address", IS_SOCK_ADDR_LEN_VALID(namelen) && + IS_SOCK_ADDR_TYPE_VALID_OR_UNSPEC(name) && IS_SOCK_ADDR_ALIGNED(name), + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + + SOCKADDR_TO_IPXADDR_PORT((name->sa_family == AF_INET6), name, &remote_addr, remote_port); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, addr=", s)); + ipX_addr_debug_print(name->sa_family == AF_INET6, SOCKETS_DEBUG, &remote_addr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", remote_port)); + + err = netconn_connect(sock->conn, ipX_2_ip(&remote_addr), remote_port); + } + + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) failed, err=%d\n", s, err)); + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) succeeded\n", s)); + sock_set_errno(sock, 0); + return 0; +} + +/** + * Set a socket into listen mode. + * The socket may not have been used for another connection previously. + * + * @param s the socket to set to listening mode + * @param backlog (ATTENTION: needs TCP_LISTEN_BACKLOG=1) + * @return 0 on success, non-zero on failure + */ +int +lwip_listen(int s, int backlog) +{ + struct lwip_sock *sock; + err_t err; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d, backlog=%d)\n", s, backlog)); + + sock = get_socket(s); + if (!sock) { + return -1; + } + + /* limit the "backlog" parameter to fit in an u8_t */ + backlog = LWIP_MIN(LWIP_MAX(backlog, 0), 0xff); + + err = netconn_listen_with_backlog(sock->conn, (u8_t)backlog); + + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d) failed, err=%d\n", s, err)); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { + sock_set_errno(sock, EOPNOTSUPP); + return -1; + } + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + + sock_set_errno(sock, 0); + return 0; +} + +int +lwip_recvfrom(int s, void *mem, size_t len, int flags, + struct sockaddr *from, socklen_t *fromlen) +{ + struct lwip_sock *sock; + void *buf = NULL; + struct pbuf *p; + u16_t buflen, copylen; + int off = 0; + u8_t done = 0; + err_t err; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %"SZT_F", 0x%x, ..)\n", s, mem, len, flags)); + sock = get_socket(s); + if (!sock) { + return -1; + } + + do { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: top while sock->lastdata=%p\n", sock->lastdata)); + /* Check if there is data left from the last recv operation. */ + if (sock->lastdata) { + buf = sock->lastdata; + } else { + /* If this is non-blocking call, then check first */ + if (((flags & MSG_DONTWAIT) || netconn_is_nonblocking(sock->conn)) && + (sock->rcvevent <= 0)) { + if (off > 0) { + /* update receive window */ + netconn_recved(sock->conn, (u32_t)off); + /* already received data, return that */ + sock_set_errno(sock, 0); + return off; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s)); + sock_set_errno(sock, EWOULDBLOCK); + return -1; + } + + /* No data was left from the previous operation, so we try to get + some from the network. */ + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { + err = netconn_recv_tcp_pbuf(sock->conn, (struct pbuf **)&buf); + } else { + err = netconn_recv(sock->conn, (struct netbuf **)&buf); + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: netconn_recv err=%d, netbuf=%p\n", + err, buf)); + + if (err != ERR_OK) { + if (off > 0) { + /* update receive window */ + netconn_recved(sock->conn, (u32_t)off); + /* already received data, return that */ + sock_set_errno(sock, 0); + return off; + } + /* We should really do some error checking here. */ + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): buf == NULL, error is \"%s\"!\n", + s, lwip_strerr(err))); + sock_set_errno(sock, err_to_errno(err)); + if (err == ERR_CLSD) { + return 0; + } else { + return -1; + } + } + LWIP_ASSERT("buf != NULL", buf != NULL); + sock->lastdata = buf; + } + + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { + p = (struct pbuf *)buf; + } else { + p = ((struct netbuf *)buf)->p; + } + buflen = p->tot_len; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: buflen=%"U16_F" len=%"SZT_F" off=%d sock->lastoffset=%"U16_F"\n", + buflen, len, off, sock->lastoffset)); + + buflen -= sock->lastoffset; + + if (len > buflen) { + copylen = buflen; + } else { + copylen = (u16_t)len; + } + + /* copy the contents of the received buffer into + the supplied memory pointer mem */ + pbuf_copy_partial(p, (u8_t*)mem + off, copylen, sock->lastoffset); + + off += copylen; + + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { + LWIP_ASSERT("invalid copylen, len would underflow", len >= copylen); + len -= copylen; + if ( (len <= 0) || + (p->flags & PBUF_FLAG_PUSH) || + (sock->rcvevent <= 0) || + ((flags & MSG_PEEK)!=0)) { + done = 1; + } + } else { + done = 1; + } + + /* Check to see from where the data was.*/ + if (done) { +#if !SOCKETS_DEBUG + if (from && fromlen) +#endif /* !SOCKETS_DEBUG */ + { + u16_t port; + ipX_addr_t tmpaddr; + ipX_addr_t *fromaddr; + union sockaddr_aligned saddr; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s)); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { + fromaddr = &tmpaddr; + /* @todo: this does not work for IPv6, yet */ + netconn_getaddr(sock->conn, ipX_2_ip(fromaddr), &port, 0); + } else { + port = netbuf_fromport((struct netbuf *)buf); + fromaddr = netbuf_fromaddr_ipX((struct netbuf *)buf); + } + IPXADDR_PORT_TO_SOCKADDR(NETCONNTYPE_ISIPV6(netconn_type(sock->conn)), + &saddr, fromaddr, port); + ipX_addr_debug_print(NETCONNTYPE_ISIPV6(netconn_type(sock->conn)), + SOCKETS_DEBUG, fromaddr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%d\n", port, off)); +#if SOCKETS_DEBUG + if (from && fromlen) +#endif /* SOCKETS_DEBUG */ + { + if (*fromlen > saddr.sa.sa_len) { + *fromlen = saddr.sa.sa_len; + } + MEMCPY(from, &saddr, *fromlen); + } + } + } + + /* If we don't peek the incoming message... */ + if ((flags & MSG_PEEK) == 0) { + /* If this is a TCP socket, check if there is data left in the + buffer. If so, it should be saved in the sock structure for next + time around. */ + if ((NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) && (buflen - copylen > 0)) { + sock->lastdata = buf; + sock->lastoffset += copylen; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: lastdata now netbuf=%p\n", buf)); + } else { + sock->lastdata = NULL; + sock->lastoffset = 0; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: deleting netbuf=%p\n", buf)); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { + pbuf_free((struct pbuf *)buf); + } else { + netbuf_delete((struct netbuf *)buf); + } + } + } + } while (!done); + + if ((off > 0) && (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP)) { + /* update receive window */ + netconn_recved(sock->conn, (u32_t)off); + } + sock_set_errno(sock, 0); + return off; +} + +int +lwip_read(int s, void *mem, size_t len) +{ + return lwip_recvfrom(s, mem, len, 0, NULL, NULL); +} + +int +lwip_recv(int s, void *mem, size_t len, int flags) +{ + return lwip_recvfrom(s, mem, len, flags, NULL, NULL); +} + +int +lwip_send(int s, const void *data, size_t size, int flags) +{ + struct lwip_sock *sock; + err_t err; + u8_t write_flags; + size_t written; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d, data=%p, size=%"SZT_F", flags=0x%x)\n", + s, data, size, flags)); + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { +#if (LWIP_UDP || LWIP_RAW) + return lwip_sendto(s, data, size, flags, NULL, 0); +#else /* (LWIP_UDP || LWIP_RAW) */ + sock_set_errno(sock, err_to_errno(ERR_ARG)); + return -1; +#endif /* (LWIP_UDP || LWIP_RAW) */ + } + + write_flags = NETCONN_COPY | + ((flags & MSG_MORE) ? NETCONN_MORE : 0) | + ((flags & MSG_DONTWAIT) ? NETCONN_DONTBLOCK : 0); + written = 0; + err = netconn_write_partly(sock->conn, data, size, write_flags, &written); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) err=%d written=%"SZT_F"\n", s, err, written)); + sock_set_errno(sock, err_to_errno(err)); + return (err == ERR_OK ? (int)written : -1); +} + +int +lwip_sendto(int s, const void *data, size_t size, int flags, + const struct sockaddr *to, socklen_t tolen) +{ + struct lwip_sock *sock; + err_t err; + u16_t short_size; + u16_t remote_port; +#if !LWIP_TCPIP_CORE_LOCKING + struct netbuf buf; +#endif + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { +#if LWIP_TCP + return lwip_send(s, data, size, flags); +#else /* LWIP_TCP */ + LWIP_UNUSED_ARG(flags); + sock_set_errno(sock, err_to_errno(ERR_ARG)); + return -1; +#endif /* LWIP_TCP */ + } + + if ((to != NULL) && !SOCK_ADDR_TYPE_MATCH(to, sock)) { + /* sockaddr does not match socket type (IPv4/IPv6) */ + sock_set_errno(sock, err_to_errno(ERR_VAL)); + return -1; + } + + /* @todo: split into multiple sendto's? */ + LWIP_ASSERT("lwip_sendto: size must fit in u16_t", size <= 0xffff); + short_size = (u16_t)size; + LWIP_ERROR("lwip_sendto: invalid address", (((to == NULL) && (tolen == 0)) || + (IS_SOCK_ADDR_LEN_VALID(tolen) && + IS_SOCK_ADDR_TYPE_VALID(to) && IS_SOCK_ADDR_ALIGNED(to))), + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + LWIP_UNUSED_ARG(tolen); + +#if LWIP_TCPIP_CORE_LOCKING + /* Special speedup for fast UDP/RAW sending: call the raw API directly + instead of using the netconn functions. */ + { + struct pbuf* p; + ipX_addr_t *remote_addr; + ipX_addr_t remote_addr_tmp; + +#if LWIP_NETIF_TX_SINGLE_PBUF + p = pbuf_alloc(PBUF_TRANSPORT, short_size, PBUF_RAM); + if (p != NULL) { +#if LWIP_CHECKSUM_ON_COPY + u16_t chksum = 0; + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_RAW) { + chksum = LWIP_CHKSUM_COPY(p->payload, data, short_size); + } else +#endif /* LWIP_CHECKSUM_ON_COPY */ + MEMCPY(p->payload, data, size); +#else /* LWIP_NETIF_TX_SINGLE_PBUF */ + p = pbuf_alloc(PBUF_TRANSPORT, short_size, PBUF_REF); + if (p != NULL) { + p->payload = (void*)data; +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + + if (to != NULL) { + SOCKADDR_TO_IPXADDR_PORT(to->sa_family == AF_INET6, + to, &remote_addr_tmp, remote_port); + remote_addr = &remote_addr_tmp; + } else { + remote_addr = &sock->conn->pcb.ip->remote_ip; +#if LWIP_UDP + if (NETCONNTYPE_GROUP(sock->conn->type) == NETCONN_UDP) { + remote_port = sock->conn->pcb.udp->remote_port; + } else +#endif /* LWIP_UDP */ + { + remote_port = 0; + } + } + + LOCK_TCPIP_CORE(); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_RAW) { +#if LWIP_RAW + err = sock->conn->last_err = raw_sendto(sock->conn->pcb.raw, p, ipX_2_ip(remote_addr)); +#else /* LWIP_RAW */ + err = ERR_ARG; +#endif /* LWIP_RAW */ + } +#if LWIP_UDP && LWIP_RAW + else +#endif /* LWIP_UDP && LWIP_RAW */ + { +#if LWIP_UDP +#if LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF + err = sock->conn->last_err = udp_sendto_chksum(sock->conn->pcb.udp, p, + ipX_2_ip(remote_addr), remote_port, 1, chksum); +#else /* LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF */ + err = sock->conn->last_err = udp_sendto(sock->conn->pcb.udp, p, + ipX_2_ip(remote_addr), remote_port); +#endif /* LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF */ +#else /* LWIP_UDP */ + err = ERR_ARG; +#endif /* LWIP_UDP */ + } + UNLOCK_TCPIP_CORE(); + + pbuf_free(p); + } else { + err = ERR_MEM; + } + } +#else /* LWIP_TCPIP_CORE_LOCKING */ + /* initialize a buffer */ + buf.p = buf.ptr = NULL; +#if LWIP_CHECKSUM_ON_COPY + buf.flags = 0; +#endif /* LWIP_CHECKSUM_ON_COPY */ + if (to) { + SOCKADDR_TO_IPXADDR_PORT((to->sa_family) == AF_INET6, to, &buf.addr, remote_port); + } else { + remote_port = 0; + ipX_addr_set_any(NETCONNTYPE_ISIPV6(netconn_type(sock->conn)), &buf.addr); + } + netbuf_fromport(&buf) = remote_port; + + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, short_size=%"U16_F", flags=0x%x to=", + s, data, short_size, flags)); + ipX_addr_debug_print(NETCONNTYPE_ISIPV6(netconn_type(sock->conn)), + SOCKETS_DEBUG, &buf.addr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port)); + + /* make the buffer point to the data that should be sent */ +#if LWIP_NETIF_TX_SINGLE_PBUF + /* Allocate a new netbuf and copy the data into it. */ + if (netbuf_alloc(&buf, short_size) == NULL) { + err = ERR_MEM; + } else { +#if LWIP_CHECKSUM_ON_COPY + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_RAW) { + u16_t chksum = LWIP_CHKSUM_COPY(buf.p->payload, data, short_size); + netbuf_set_chksum(&buf, chksum); + err = ERR_OK; + } else +#endif /* LWIP_CHECKSUM_ON_COPY */ + { + err = netbuf_take(&buf, data, short_size); + } + } +#else /* LWIP_NETIF_TX_SINGLE_PBUF */ + err = netbuf_ref(&buf, data, short_size); +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + if (err == ERR_OK) { + /* send the data */ + err = netconn_send(sock->conn, &buf); + } + + /* deallocated the buffer */ + netbuf_free(&buf); +#endif /* LWIP_TCPIP_CORE_LOCKING */ + sock_set_errno(sock, err_to_errno(err)); + return (err == ERR_OK ? short_size : -1); +} + +int +lwip_socket(int domain, int type, int protocol) +{ + struct netconn *conn; + int i; + +#if !LWIP_IPV6 + LWIP_UNUSED_ARG(domain); /* @todo: check this */ +#endif /* LWIP_IPV6 */ + + /* create a netconn */ + switch (type) { + case SOCK_RAW: + conn = netconn_new_with_proto_and_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_RAW), + (u8_t)protocol, event_callback); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ", + domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); + break; + case SOCK_DGRAM: + conn = netconn_new_with_callback(DOMAIN_TO_NETCONN_TYPE(domain, + ((protocol == IPPROTO_UDPLITE) ? NETCONN_UDPLITE : NETCONN_UDP)) , + event_callback); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_DGRAM, %d) = ", + domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); + break; + case SOCK_STREAM: + conn = netconn_new_with_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_TCP), event_callback); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_STREAM, %d) = ", + domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); + if (conn != NULL) { + /* Prevent automatic window updates, we do this on our own! */ + netconn_set_noautorecved(conn, 1); + } + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%d, %d/UNKNOWN, %d) = -1\n", + domain, type, protocol)); + set_errno(EINVAL); + return -1; + } + + if (!conn) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("-1 / ENOBUFS (could not create netconn)\n")); + set_errno(ENOBUFS); + return -1; + } + + i = alloc_socket(conn, 0); + + if (i == -1) { + netconn_delete(conn); + set_errno(ENFILE); + return -1; + } + conn->socket = i; + LWIP_DEBUGF(SOCKETS_DEBUG, ("%d\n", i)); + set_errno(0); + return i; +} + +int +lwip_write(int s, const void *data, size_t size) +{ + return lwip_send(s, data, size, 0); +} + +/** + * Go through the readset and writeset lists and see which socket of the sockets + * set in the sets has events. On return, readset, writeset and exceptset have + * the sockets enabled that had events. + * + * exceptset is not used for now!!! + * + * @param maxfdp1 the highest socket index in the sets + * @param readset_in: set of sockets to check for read events + * @param writeset_in: set of sockets to check for write events + * @param exceptset_in: set of sockets to check for error events + * @param readset_out: set of sockets that had read events + * @param writeset_out: set of sockets that had write events + * @param exceptset_out: set os sockets that had error events + * @return number of sockets that had events (read/write/exception) (>= 0) + */ +static int +lwip_selscan(int maxfdp1, fd_set *readset_in, fd_set *writeset_in, fd_set *exceptset_in, + fd_set *readset_out, fd_set *writeset_out, fd_set *exceptset_out) +{ + int i, nready = 0; + fd_set lreadset, lwriteset, lexceptset; + struct lwip_sock *sock; + SYS_ARCH_DECL_PROTECT(lev); + + FD_ZERO(&lreadset); + FD_ZERO(&lwriteset); + FD_ZERO(&lexceptset); + + /* Go through each socket in each list to count number of sockets which + currently match */ + for(i = 0; i < maxfdp1; i++) { + void* lastdata = NULL; + s16_t rcvevent = 0; + u16_t sendevent = 0; + u16_t errevent = 0; + /* First get the socket's status (protected)... */ + SYS_ARCH_PROTECT(lev); + sock = tryget_socket(i); + if (sock != NULL) { + lastdata = sock->lastdata; + rcvevent = sock->rcvevent; + sendevent = sock->sendevent; + errevent = sock->errevent; + } + SYS_ARCH_UNPROTECT(lev); + /* ... then examine it: */ + /* See if netconn of this socket is ready for read */ + if (readset_in && FD_ISSET(i, readset_in) && ((lastdata != NULL) || (rcvevent > 0))) { + FD_SET(i, &lreadset); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for reading\n", i)); + nready++; + } + /* See if netconn of this socket is ready for write */ + if (writeset_in && FD_ISSET(i, writeset_in) && (sendevent != 0)) { + FD_SET(i, &lwriteset); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for writing\n", i)); + nready++; + } + /* See if netconn of this socket had an error */ + if (exceptset_in && FD_ISSET(i, exceptset_in) && (errevent != 0)) { + FD_SET(i, &lexceptset); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for exception\n", i)); + nready++; + } + } + /* copy local sets to the ones provided as arguments */ + *readset_out = lreadset; + *writeset_out = lwriteset; + *exceptset_out = lexceptset; + + LWIP_ASSERT("nready >= 0", nready >= 0); + return nready; +} + +/** + * Processing exceptset is not yet implemented. + */ +int +lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, + struct timeval *timeout) +{ + u32_t waitres = 0; + int nready; + fd_set lreadset, lwriteset, lexceptset; + u32_t msectimeout; + struct lwip_select_cb select_cb; + int i; + int maxfdp2; + SYS_ARCH_DECL_PROTECT(lev); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select(%d, %p, %p, %p, tvsec=%"S32_F" tvusec=%"S32_F")\n", + maxfdp1, (void *)readset, (void *) writeset, (void *) exceptset, + timeout ? (s32_t)timeout->tv_sec : (s32_t)-1, + timeout ? (s32_t)timeout->tv_usec : (s32_t)-1)); + + /* Go through each socket in each list to count number of sockets which + currently match */ + nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset); + + /* If we don't have any current events, then suspend if we are supposed to */ + if (!nready) { + if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: no timeout, returning 0\n")); + /* This is OK as the local fdsets are empty and nready is zero, + or we would have returned earlier. */ + goto return_copy_fdsets; + } + + /* None ready: add our semaphore to list: + We don't actually need any dynamic memory. Our entry on the + list is only valid while we are in this function, so it's ok + to use local variables. */ + + select_cb.next = NULL; + select_cb.prev = NULL; + select_cb.readset = readset; + select_cb.writeset = writeset; + select_cb.exceptset = exceptset; + select_cb.sem_signalled = 0; +#if LWIP_NETCONN_SEM_PER_THREAD + select_cb.sem = LWIP_NETCONN_THREAD_SEM_GET(); +#else /* LWIP_NETCONN_SEM_PER_THREAD */ + if (sys_sem_new(&select_cb.sem, 0) != ERR_OK) { + /* failed to create semaphore */ + set_errno(ENOMEM); + return -1; + } +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + + /* Protect the select_cb_list */ + SYS_ARCH_PROTECT(lev); + + /* Put this select_cb on top of list */ + select_cb.next = select_cb_list; + if (select_cb_list != NULL) { + select_cb_list->prev = &select_cb; + } + select_cb_list = &select_cb; + /* Increasing this counter tells even_callback that the list has changed. */ + select_cb_ctr++; + + /* Now we can safely unprotect */ + SYS_ARCH_UNPROTECT(lev); + + /* Increase select_waiting for each socket we are interested in */ + maxfdp2 = maxfdp1; + for (i = 0; i < maxfdp1; i++) { + if ((readset && FD_ISSET(i, readset)) || + (writeset && FD_ISSET(i, writeset)) || + (exceptset && FD_ISSET(i, exceptset))) { + struct lwip_sock *sock; + SYS_ARCH_PROTECT(lev); + sock = tryget_socket(i); + if (sock != NULL) { + sock->select_waiting++; + LWIP_ASSERT("sock->select_waiting > 0", sock->select_waiting > 0); + } else { + /* Not a valid socket */ + nready = -1; + maxfdp2 = i; + SYS_ARCH_UNPROTECT(lev); + break; + } + SYS_ARCH_UNPROTECT(lev); + } + } + + if (nready >= 0) { + /* Call lwip_selscan again: there could have been events between + the last scan (without us on the list) and putting us on the list! */ + nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset); + if (!nready) { + /* Still none ready, just wait to be woken */ + if (timeout == 0) { + /* Wait forever */ + msectimeout = 0; + } else { + msectimeout = ((timeout->tv_sec * 1000) + ((timeout->tv_usec + 500)/1000)); + if (msectimeout == 0) { + /* Wait 1ms at least (0 means wait forever) */ + msectimeout = 1; + } + } + + waitres = sys_arch_sem_wait(SELECT_SEM_PTR(select_cb.sem), msectimeout); + } + } + + /* Decrease select_waiting for each socket we are interested in */ + for (i = 0; i < maxfdp2; i++) { + if ((readset && FD_ISSET(i, readset)) || + (writeset && FD_ISSET(i, writeset)) || + (exceptset && FD_ISSET(i, exceptset))) { + struct lwip_sock *sock; + SYS_ARCH_PROTECT(lev); + sock = tryget_socket(i); + if (sock != NULL) { + /* @todo: what if this is a new socket (reallocated?) in this case, + select_waiting-- would be wrong (a global 'sockalloc' counter, + stored per socket could help) */ + LWIP_ASSERT("sock->select_waiting > 0", sock->select_waiting > 0); + if (sock->select_waiting > 0) { + sock->select_waiting--; + } + } else { + /* Not a valid socket */ + nready = -1; + } + SYS_ARCH_UNPROTECT(lev); + } + } + /* Take us off the list */ + SYS_ARCH_PROTECT(lev); + if (select_cb.next != NULL) { + select_cb.next->prev = select_cb.prev; + } + if (select_cb_list == &select_cb) { + LWIP_ASSERT("select_cb.prev == NULL", select_cb.prev == NULL); + select_cb_list = select_cb.next; + } else { + LWIP_ASSERT("select_cb.prev != NULL", select_cb.prev != NULL); + select_cb.prev->next = select_cb.next; + } + /* Increasing this counter tells even_callback that the list has changed. */ + select_cb_ctr++; + SYS_ARCH_UNPROTECT(lev); + +#if !LWIP_NETCONN_SEM_PER_THREAD + sys_sem_free(&select_cb.sem); +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + + if (nready < 0) { + /* This happens when a socket got closed while waiting */ + set_errno(EBADF); + return -1; + } + + if (waitres == SYS_ARCH_TIMEOUT) { + /* Timeout */ + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n")); + /* This is OK as the local fdsets are empty and nready is zero, + or we would have returned earlier. */ + goto return_copy_fdsets; + } + + /* See what's set */ + nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset); + } + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready)); +return_copy_fdsets: + set_errno(0); + if (readset) { + *readset = lreadset; + } + if (writeset) { + *writeset = lwriteset; + } + if (exceptset) { + *exceptset = lexceptset; + } + return nready; +} + +/** + * Callback registered in the netconn layer for each socket-netconn. + * Processes recvevent (data available) and wakes up tasks waiting for select. + */ +static void +event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len) +{ + int s; + struct lwip_sock *sock; + struct lwip_select_cb *scb; + int last_select_cb_ctr; + SYS_ARCH_DECL_PROTECT(lev); + + LWIP_UNUSED_ARG(len); + + /* Get socket */ + if (conn) { + s = conn->socket; + if (s < 0) { + /* Data comes in right away after an accept, even though + * the server task might not have created a new socket yet. + * Just count down (or up) if that's the case and we + * will use the data later. Note that only receive events + * can happen before the new socket is set up. */ + SYS_ARCH_PROTECT(lev); + if (conn->socket < 0) { + if (evt == NETCONN_EVT_RCVPLUS) { + conn->socket--; + } + SYS_ARCH_UNPROTECT(lev); + return; + } + s = conn->socket; + SYS_ARCH_UNPROTECT(lev); + } + + sock = get_socket(s); + if (!sock) { + return; + } + } else { + return; + } + + SYS_ARCH_PROTECT(lev); + /* Set event as required */ + switch (evt) { + case NETCONN_EVT_RCVPLUS: + sock->rcvevent++; + break; + case NETCONN_EVT_RCVMINUS: + sock->rcvevent--; + break; + case NETCONN_EVT_SENDPLUS: + sock->sendevent = 1; + break; + case NETCONN_EVT_SENDMINUS: + sock->sendevent = 0; + break; + case NETCONN_EVT_ERROR: + sock->errevent = 1; + break; + default: + LWIP_ASSERT("unknown event", 0); + break; + } + + if (sock->select_waiting == 0) { + /* noone is waiting for this socket, no need to check select_cb_list */ + SYS_ARCH_UNPROTECT(lev); + return; + } + + /* Now decide if anyone is waiting for this socket */ + /* NOTE: This code goes through the select_cb_list list multiple times + ONLY IF a select was actually waiting. We go through the list the number + of waiting select calls + 1. This list is expected to be small. */ + + /* At this point, SYS_ARCH is still protected! */ +again: + for (scb = select_cb_list; scb != NULL; scb = scb->next) { + /* remember the state of select_cb_list to detect changes */ + last_select_cb_ctr = select_cb_ctr; + if (scb->sem_signalled == 0) { + /* semaphore not signalled yet */ + int do_signal = 0; + /* Test this select call for our socket */ + if (sock->rcvevent > 0) { + if (scb->readset && FD_ISSET(s, scb->readset)) { + do_signal = 1; + } + } + if (sock->sendevent != 0) { + if (!do_signal && scb->writeset && FD_ISSET(s, scb->writeset)) { + do_signal = 1; + } + } + if (sock->errevent != 0) { + if (!do_signal && scb->exceptset && FD_ISSET(s, scb->exceptset)) { + do_signal = 1; + } + } + if (do_signal) { + scb->sem_signalled = 1; + /* Don't call SYS_ARCH_UNPROTECT() before signaling the semaphore, as this might + lead to the select thread taking itself off the list, invalidating the semaphore. */ + sys_sem_signal(SELECT_SEM_PTR(scb->sem)); + } + } + /* unlock interrupts with each step */ + SYS_ARCH_UNPROTECT(lev); + /* this makes sure interrupt protection time is short */ + SYS_ARCH_PROTECT(lev); + if (last_select_cb_ctr != select_cb_ctr) { + /* someone has changed select_cb_list, restart at the beginning */ + goto again; + } + } + SYS_ARCH_UNPROTECT(lev); +} + +/** + * Unimplemented: Close one end of a full-duplex connection. + * Currently, the full connection is closed. + */ +int +lwip_shutdown(int s, int how) +{ + struct lwip_sock *sock; + err_t err; + u8_t shut_rx = 0, shut_tx = 0; + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_shutdown(%d, how=%d)\n", s, how)); + + sock = get_socket(s); + if (!sock) { + return -1; + } + + if (sock->conn != NULL) { + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { + sock_set_errno(sock, EOPNOTSUPP); + return -1; + } + } else { + sock_set_errno(sock, ENOTCONN); + return -1; + } + + if (how == SHUT_RD) { + shut_rx = 1; + } else if (how == SHUT_WR) { + shut_tx = 1; + } else if(how == SHUT_RDWR) { + shut_rx = 1; + shut_tx = 1; + } else { + sock_set_errno(sock, EINVAL); + return -1; + } + err = netconn_shutdown(sock->conn, shut_rx, shut_tx); + + sock_set_errno(sock, err_to_errno(err)); + return (err == ERR_OK ? 0 : -1); +} + +static int +lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local) +{ + struct lwip_sock *sock; + union sockaddr_aligned saddr; + ipX_addr_t naddr; + u16_t port; + err_t err; + + sock = get_socket(s); + if (!sock) { + return -1; + } + + /* get the IP address and port */ + /* @todo: this does not work for IPv6, yet */ + err = netconn_getaddr(sock->conn, ipX_2_ip(&naddr), &port, local); + if (err != ERR_OK) { + sock_set_errno(sock, err_to_errno(err)); + return -1; + } + IPXADDR_PORT_TO_SOCKADDR(NETCONNTYPE_ISIPV6(netconn_type(sock->conn)), + &saddr, &naddr, port); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getaddrname(%d, addr=", s)); + ipX_addr_debug_print(NETCONNTYPE_ISIPV6(netconn_type(sock->conn)), + SOCKETS_DEBUG, &naddr); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", port)); + + if (*namelen > saddr.sa.sa_len) { + *namelen = saddr.sa.sa_len; + } + MEMCPY(name, &saddr, *namelen); + + sock_set_errno(sock, 0); + return 0; +} + +int +lwip_getpeername(int s, struct sockaddr *name, socklen_t *namelen) +{ + return lwip_getaddrname(s, name, namelen, 0); +} + +int +lwip_getsockname(int s, struct sockaddr *name, socklen_t *namelen) +{ + return lwip_getaddrname(s, name, namelen, 1); +} + +int +lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) +{ + u8_t err; + struct lwip_sock *sock = get_socket(s); +#if !LWIP_TCPIP_CORE_LOCKING + LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(data); +#endif /* !LWIP_TCPIP_CORE_LOCKING */ + + if (!sock) { + return -1; + } + + if ((NULL == optval) || (NULL == optlen)) { + sock_set_errno(sock, EFAULT); + return -1; + } + +#if LWIP_TCPIP_CORE_LOCKING + /* core-locking can just call the -impl function */ + LOCK_TCPIP_CORE(); + err = lwip_getsockopt_impl(s, level, optname, optval, optlen); + UNLOCK_TCPIP_CORE(); + +#else /* LWIP_TCPIP_CORE_LOCKING */ + +#if LWIP_MPU_COMPATIBLE + /* MPU_COMPATIBLE copies the optval data, so check for max size here */ + if (*optlen > LWIP_SETGETSOCKOPT_MAXOPTLEN) { + sock_set_errno(sock, ENOBUFS); + return -1; + } +#endif /* LWIP_MPU_COMPATIBLE */ + + LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(data, sock); + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).s = s; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).level = level; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optname = optname; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen = *optlen; +#if !LWIP_MPU_COMPATIBLE + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval = optval; +#endif /* !LWIP_MPU_COMPATIBLE */ + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err = 0; +#if LWIP_NETCONN_SEM_PER_THREAD + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = LWIP_NETCONN_THREAD_SEM_GET(); +#else + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = &sock->conn->op_completed; +#endif + tcpip_callback(lwip_getsockopt_callback, &LWIP_SETGETSOCKOPT_DATA_VAR_REF(data)); + sys_arch_sem_wait((sys_sem_t*)(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem), 0); + + /* write back optlen and optval */ + *optlen = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen; +#if LWIP_MPU_COMPATIBLE + memcpy(optval, LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval, + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen); +#endif /* LWIP_MPU_COMPATIBLE */ + + /* maybe lwip_getsockopt_internal has changed err */ + err = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err; + LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); +#endif /* LWIP_TCPIP_CORE_LOCKING */ + + sock_set_errno(sock, err); + return err ? -1 : 0; +} + +#if !LWIP_TCPIP_CORE_LOCKING +/** lwip_getsockopt_callback: only used without CORE_LOCKING + * to get into the tcpip_thread + */ +static void +lwip_getsockopt_callback(void *arg) +{ + struct lwip_setgetsockopt_data *data; + LWIP_ASSERT("arg != NULL", arg != NULL); + data = (struct lwip_setgetsockopt_data*)arg; + + data->err = lwip_getsockopt_impl(data->s, data->level, data->optname, data->optval, + &data->optlen); + + sys_sem_signal((sys_sem_t*)(data->completed_sem)); +} +#endif /* LWIP_TCPIP_CORE_LOCKING */ + +/** lwip_getsockopt_impl: the actual implementation of getsockopt: + * same argument as lwip_getsockopt, either called directly or through callback + */ +static u8_t +lwip_getsockopt_impl(int s, int level, int optname, void *optval, socklen_t *optlen) +{ + u8_t err = 0; + struct lwip_sock *sock = tryget_socket(s); + if (!sock) { + return EBADF; + } + + switch (level) { + +/* Level: SOL_SOCKET */ + case SOL_SOCKET: + switch (optname) { + + case SO_ACCEPTCONN: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int); + if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_TCP) { + return ENOPROTOOPT; + } + if ((sock->conn->pcb.tcp != NULL) && (sock->conn->pcb.tcp->state == LISTEN)) { + *(int*)optval = 1; + } else { + *(int*)optval = 0; + } + break; + + /* The option flags */ + case SO_BROADCAST: + case SO_KEEPALIVE: +#if SO_REUSE + case SO_REUSEADDR: +#endif /* SO_REUSE */ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int); + *(int*)optval = ip_get_option(sock->conn->pcb.ip, optname); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, optname=0x%x, ..) = %s\n", + s, optname, (*(int*)optval?"on":"off"))); + break; + + case SO_TYPE: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int); + switch (NETCONNTYPE_GROUP(netconn_type(sock->conn))) { + case NETCONN_RAW: + *(int*)optval = SOCK_RAW; + break; + case NETCONN_TCP: + *(int*)optval = SOCK_STREAM; + break; + case NETCONN_UDP: + *(int*)optval = SOCK_DGRAM; + break; + default: /* unrecognized socket type */ + *(int*)optval = netconn_type(sock->conn); + LWIP_DEBUGF(SOCKETS_DEBUG, + ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n", + s, *(int *)optval)); + } /* switch (netconn_type(sock->conn)) */ + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n", + s, *(int *)optval)); + break; + + case SO_ERROR: + LWIP_SOCKOPT_CHECK_OPTLEN(*optlen, int); + /* only overwrite ERR_OK or temporary errors */ + if (((sock->err == 0) || (sock->err == EINPROGRESS)) && (sock->conn != NULL)) { + sock_set_errno(sock, err_to_errno(sock->conn->last_err)); + } + *(int *)optval = sock->err; + sock->err = 0; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n", + s, *(int *)optval)); + break; + +#if LWIP_SO_SNDTIMEO + case SO_SNDTIMEO: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE); + LWIP_SO_SNDRCVTIMEO_SET(optval, netconn_get_sendtimeout(sock->conn)); + break; +#endif /* LWIP_SO_SNDTIMEO */ +#if LWIP_SO_RCVTIMEO + case SO_RCVTIMEO: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE); + LWIP_SO_SNDRCVTIMEO_SET(optval, netconn_get_recvtimeout(sock->conn)); + break; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + case SO_RCVBUF: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int); + *(int *)optval = netconn_get_recvbufsize(sock->conn); + break; +#endif /* LWIP_SO_RCVBUF */ +#if LWIP_UDP + case SO_NO_CHECK: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen, int, NETCONN_UDP); +#if LWIP_UDPLITE + if ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0) { + /* this flag is only available for UDP, not for UDP lite */ + return EAFNOSUPPORT; + } +#endif /* LWIP_UDPLITE */ + *(int*)optval = (udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_NOCHKSUM) ? 1 : 0; + break; +#endif /* LWIP_UDP*/ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; + +/* Level: IPPROTO_IP */ + case IPPROTO_IP: + switch (optname) { + case IP_TTL: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int); + *(int*)optval = sock->conn->pcb.ip->ttl; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TTL) = %d\n", + s, *(int *)optval)); + break; + case IP_TOS: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int); + *(int*)optval = sock->conn->pcb.ip->tos; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TOS) = %d\n", + s, *(int *)optval)); + break; +#if LWIP_IGMP + case IP_MULTICAST_TTL: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, u8_t); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) { + return ENOPROTOOPT; + } + *(u8_t*)optval = sock->conn->pcb.ip->ttl; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_TTL) = %d\n", + s, *(int *)optval)); + break; + case IP_MULTICAST_IF: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, struct in_addr); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) { + return ENOPROTOOPT; + } + inet_addr_from_ipaddr((struct in_addr*)optval, &sock->conn->pcb.udp->multicast_ip); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_IF) = 0x%"X32_F"\n", + s, *(u32_t *)optval)); + break; + case IP_MULTICAST_LOOP: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, u8_t); + if ((sock->conn->pcb.udp->flags & UDP_FLAGS_MULTICAST_LOOP) != 0) { + *(u8_t*)optval = 1; + } else { + *(u8_t*)optval = 0; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_LOOP) = %d\n", + s, *(int *)optval)); + break; +#endif /* LWIP_IGMP */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; + +#if LWIP_TCP +/* Level: IPPROTO_TCP */ + case IPPROTO_TCP: + /* Special case: all IPPROTO_TCP option take an int */ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen, int, NETCONN_TCP); + switch (optname) { + case TCP_NODELAY: + *(int*)optval = tcp_nagle_disabled(sock->conn->pcb.tcp); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n", + s, (*(int*)optval)?"on":"off") ); + break; + case TCP_KEEPALIVE: + *(int*)optval = (int)sock->conn->pcb.tcp->keep_idle; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) = %d\n", + s, *(int *)optval)); + break; + +#if LWIP_TCP_KEEPALIVE + case TCP_KEEPIDLE: + *(int*)optval = (int)(sock->conn->pcb.tcp->keep_idle/1000); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) = %d\n", + s, *(int *)optval)); + break; + case TCP_KEEPINTVL: + *(int*)optval = (int)(sock->conn->pcb.tcp->keep_intvl/1000); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) = %d\n", + s, *(int *)optval)); + break; + case TCP_KEEPCNT: + *(int*)optval = (int)sock->conn->pcb.tcp->keep_cnt; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) = %d\n", + s, *(int *)optval)); + break; +#endif /* LWIP_TCP_KEEPALIVE */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; +#endif /* LWIP_TCP */ + +#if LWIP_IPV6 +/* Level: IPPROTO_IPV6 */ + case IPPROTO_IPV6: + switch (optname) { + case IPV6_V6ONLY: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int); + /* @todo: this does not work for datagram sockets, yet */ + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { + return ENOPROTOOPT; + } + *(int*)optval = ((sock->conn->flags & NETCONN_FLAG_IPV6_V6ONLY) ? 1 : 0); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IPV6, IPV6_V6ONLY) = %d\n", + s, *(int *)optval)); + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IPV6, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; +#endif /* LWIP_IPV6 */ + +#if LWIP_UDP && LWIP_UDPLITE + /* Level: IPPROTO_UDPLITE */ + case IPPROTO_UDPLITE: + /* Special case: all IPPROTO_UDPLITE option take an int */ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int); + /* If this is no UDP lite socket, ignore any options. */ + if (!NETCONNTYPE_ISUDPLITE(netconn_type(sock->conn))) { + return ENOPROTOOPT; + } + switch (optname) { + case UDPLITE_SEND_CSCOV: + *(int*)optval = sock->conn->pcb.udp->chksum_len_tx; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) = %d\n", + s, (*(int*)optval)) ); + break; + case UDPLITE_RECV_CSCOV: + *(int*)optval = sock->conn->pcb.udp->chksum_len_rx; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) = %d\n", + s, (*(int*)optval)) ); + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; +#endif /* LWIP_UDP */ + /* Level: IPPROTO_RAW */ + case IPPROTO_RAW: + switch (optname) { +#if LWIP_IPV6 + case IPV6_CHECKSUM: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen, int, NETCONN_RAW); + if (sock->conn->pcb.raw->chksum_reqd == 0) { + *(int *)optval = -1; + } else { + *(int *)optval = sock->conn->pcb.raw->chksum_offset; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_RAW, IPV6_CHECKSUM) = %d\n", + s, (*(int*)optval)) ); + break; +#endif /* LWIP_IPV6 */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_RAW, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", + s, level, optname)); + err = ENOPROTOOPT; + break; + } /* switch (level) */ + + return err; +} + +int +lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) +{ + u8_t err = 0; + struct lwip_sock *sock = get_socket(s); +#if !LWIP_TCPIP_CORE_LOCKING + LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(data); +#endif /* !LWIP_TCPIP_CORE_LOCKING */ + + if (!sock) { + return -1; + } + + if (NULL == optval) { + sock_set_errno(sock, EFAULT); + return -1; + } + +#if LWIP_TCPIP_CORE_LOCKING + /* core-locking can just call the -impl function */ + LOCK_TCPIP_CORE(); + err = lwip_setsockopt_impl(s, level, optname, optval, optlen); + UNLOCK_TCPIP_CORE(); + +#else /* LWIP_TCPIP_CORE_LOCKING */ + +#if LWIP_MPU_COMPATIBLE + /* MPU_COMPATIBLE copies the optval data, so check for max size here */ + if (optlen > LWIP_SETGETSOCKOPT_MAXOPTLEN) { + sock_set_errno(sock, ENOBUFS); + return -1; + } +#endif /* LWIP_MPU_COMPATIBLE */ + + LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(data, sock); + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).s = s; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).level = level; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optname = optname; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen = optlen; +#if LWIP_MPU_COMPATIBLE + memcpy(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval, optval, optlen); +#else /* LWIP_MPU_COMPATIBLE */ + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval = (void*)optval; +#endif /* LWIP_MPU_COMPATIBLE */ + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err = 0; +#if LWIP_NETCONN_SEM_PER_THREAD + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = LWIP_NETCONN_THREAD_SEM_GET(); +#else + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = &sock->conn->op_completed; +#endif + tcpip_callback(lwip_setsockopt_callback, &LWIP_SETGETSOCKOPT_DATA_VAR_REF(data)); + sys_arch_sem_wait((sys_sem_t*)(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem), 0); + + /* maybe lwip_getsockopt_internal has changed err */ + err = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err; + LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); +#endif /* LWIP_TCPIP_CORE_LOCKING */ + + sock_set_errno(sock, err); + return err ? -1 : 0; +} + +#if !LWIP_TCPIP_CORE_LOCKING +/** lwip_setsockopt_callback: only used without CORE_LOCKING + * to get into the tcpip_thread + */ +static void +lwip_setsockopt_callback(void *arg) +{ + struct lwip_setgetsockopt_data *data; + LWIP_ASSERT("arg != NULL", arg != NULL); + data = (struct lwip_setgetsockopt_data*)arg; + + data->err = lwip_setsockopt_impl(data->s, data->level, data->optname, data->optval, + data->optlen); + + sys_sem_signal((sys_sem_t*)(data->completed_sem)); +} +#endif /* LWIP_TCPIP_CORE_LOCKING */ + +/** lwip_setsockopt_impl: the actual implementation of setsockopt: + * same argument as lwip_setsockopt, either called directly or through callback + */ +static u8_t +lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_t optlen) +{ + u8_t err = 0; + struct lwip_sock *sock = tryget_socket(s); + if (!sock) { + return EBADF; + } + + switch (level) { + +/* Level: SOL_SOCKET */ + case SOL_SOCKET: + switch (optname) { + + /* SO_ACCEPTCONN is get-only */ + + /* The option flags */ + case SO_BROADCAST: + case SO_KEEPALIVE: +#if SO_REUSE + case SO_REUSEADDR: +#endif /* SO_REUSE */ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int); + if (*(int*)optval) { + ip_set_option(sock->conn->pcb.ip, optname); + } else { + ip_reset_option(sock->conn->pcb.ip, optname); + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n", + s, optname, (*(int*)optval?"on":"off"))); + break; + + /* SO_TYPE is get-only */ + /* SO_ERROR is get-only */ + +#if LWIP_SO_SNDTIMEO + case SO_SNDTIMEO: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE); + netconn_set_sendtimeout(sock->conn, LWIP_SO_SNDRCVTIMEO_GET_MS(optval)); + break; +#endif /* LWIP_SO_SNDTIMEO */ +#if LWIP_SO_RCVTIMEO + case SO_RCVTIMEO: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE); + netconn_set_recvtimeout(sock->conn, (int)LWIP_SO_SNDRCVTIMEO_GET_MS(optval)); + break; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + case SO_RCVBUF: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, int); + netconn_set_recvbufsize(sock->conn, *(int*)optval); + break; +#endif /* LWIP_SO_RCVBUF */ +#if LWIP_UDP + case SO_NO_CHECK: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_UDP); +#if LWIP_UDPLITE + if ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0) { + /* this flag is only available for UDP, not for UDP lite */ + return EAFNOSUPPORT; + } +#endif /* LWIP_UDPLITE */ + if (*(int*)optval) { + udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_NOCHKSUM); + } else { + udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_NOCHKSUM); + } + break; +#endif /* LWIP_UDP */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; + +/* Level: IPPROTO_IP */ + case IPPROTO_IP: + switch (optname) { + case IP_TTL: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int); + sock->conn->pcb.ip->ttl = (u8_t)(*(int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TTL, ..) -> %d\n", + s, sock->conn->pcb.ip->ttl)); + break; + case IP_TOS: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int); + sock->conn->pcb.ip->tos = (u8_t)(*(int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TOS, ..)-> %d\n", + s, sock->conn->pcb.ip->tos)); + break; +#if LWIP_IGMP + case IP_MULTICAST_TTL: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, u8_t, NETCONN_UDP); + sock->conn->pcb.udp->ttl = (u8_t)(*(u8_t*)optval); + break; + case IP_MULTICAST_IF: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, struct in_addr, NETCONN_UDP); + inet_addr_to_ipaddr(&sock->conn->pcb.udp->multicast_ip, (struct in_addr*)optval); + break; + case IP_MULTICAST_LOOP: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, u8_t, NETCONN_UDP); + if (*(u8_t*)optval) { + udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_MULTICAST_LOOP); + } else { + udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_MULTICAST_LOOP); + } + break; + case IP_ADD_MEMBERSHIP: + case IP_DROP_MEMBERSHIP: + { + /* If this is a TCP or a RAW socket, ignore these options. */ + /* @todo: assign membership to this socket so that it is dropped when closing the socket */ + err_t igmp_err; + struct ip_mreq *imr = (struct ip_mreq *)optval; + ip_addr_t if_addr; + ip_addr_t multi_addr; + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, struct ip_mreq, NETCONN_UDP); + inet_addr_to_ipaddr(&if_addr, &imr->imr_interface); + inet_addr_to_ipaddr(&multi_addr, &imr->imr_multiaddr); + if(optname == IP_ADD_MEMBERSHIP){ + igmp_err = igmp_joingroup(&if_addr, &multi_addr); + } else { + igmp_err = igmp_leavegroup(&if_addr, &multi_addr); + } + if (igmp_err != ERR_OK) { + err = EADDRNOTAVAIL; + } + } + break; +#endif /* LWIP_IGMP */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; + +#if LWIP_TCP +/* Level: IPPROTO_TCP */ + case IPPROTO_TCP: + /* Special case: all IPPROTO_TCP option take an int */ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_TCP); + switch (optname) { + case TCP_NODELAY: + if (*(int*)optval) { + tcp_nagle_disable(sock->conn->pcb.tcp); + } else { + tcp_nagle_enable(sock->conn->pcb.tcp); + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n", + s, (*(int *)optval)?"on":"off") ); + break; + case TCP_KEEPALIVE: + sock->conn->pcb.tcp->keep_idle = (u32_t)(*(int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %"U32_F"\n", + s, sock->conn->pcb.tcp->keep_idle)); + break; + +#if LWIP_TCP_KEEPALIVE + case TCP_KEEPIDLE: + sock->conn->pcb.tcp->keep_idle = 1000*(u32_t)(*(int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) -> %"U32_F"\n", + s, sock->conn->pcb.tcp->keep_idle)); + break; + case TCP_KEEPINTVL: + sock->conn->pcb.tcp->keep_intvl = 1000*(u32_t)(*(int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) -> %"U32_F"\n", + s, sock->conn->pcb.tcp->keep_intvl)); + break; + case TCP_KEEPCNT: + sock->conn->pcb.tcp->keep_cnt = (u32_t)(*(int*)optval); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) -> %"U32_F"\n", + s, sock->conn->pcb.tcp->keep_cnt)); + break; +#endif /* LWIP_TCP_KEEPALIVE */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; +#endif /* LWIP_TCP*/ + +#if LWIP_IPV6 +/* Level: IPPROTO_IPV6 */ + case IPPROTO_IPV6: + switch (optname) { + case IPV6_V6ONLY: + /* @todo: this does not work for datagram sockets, yet */ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_TCP); + if (*(int*)optval) { + sock->conn->flags |= NETCONN_FLAG_IPV6_V6ONLY; + } else { + sock->conn->flags &= ~NETCONN_FLAG_IPV6_V6ONLY; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IPV6, IPV6_V6ONLY, ..) -> %d\n", + s, ((sock->conn->flags & NETCONN_FLAG_IPV6_V6ONLY) ? 1 : 0))); + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IPV6, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; +#endif /* LWIP_IPV6 */ + +#if LWIP_UDP && LWIP_UDPLITE + /* Level: IPPROTO_UDPLITE */ + case IPPROTO_UDPLITE: + /* Special case: all IPPROTO_UDPLITE option take an int */ + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int); + /* If this is no UDP lite socket, ignore any options. */ + if (!NETCONNTYPE_ISUDPLITE(netconn_type(sock->conn))) { + return ENOPROTOOPT; + } + switch (optname) { + case UDPLITE_SEND_CSCOV: + if ((*(int*)optval != 0) && ((*(int*)optval < 8) || (*(int*)optval > 0xffff))) { + /* don't allow illegal values! */ + sock->conn->pcb.udp->chksum_len_tx = 8; + } else { + sock->conn->pcb.udp->chksum_len_tx = (u16_t)*(int*)optval; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) -> %d\n", + s, (*(int*)optval)) ); + break; + case UDPLITE_RECV_CSCOV: + if ((*(int*)optval != 0) && ((*(int*)optval < 8) || (*(int*)optval > 0xffff))) { + /* don't allow illegal values! */ + sock->conn->pcb.udp->chksum_len_rx = 8; + } else { + sock->conn->pcb.udp->chksum_len_rx = (u16_t)*(int*)optval; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) -> %d\n", + s, (*(int*)optval)) ); + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; +#endif /* LWIP_UDP */ + /* Level: IPPROTO_RAW */ + case IPPROTO_RAW: + switch (optname) { +#if LWIP_IPV6 + case IPV6_CHECKSUM: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_RAW); + if (*(int *)optval < 0) { + sock->conn->pcb.raw->chksum_reqd = 0; + } else if (*(int *)optval & 1) { + /* Per RFC3542, odd offsets are not allowed */ + return EINVAL; + } else { + sock->conn->pcb.raw->chksum_reqd = 1; + sock->conn->pcb.raw->chksum_offset = *(int *)optval; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_RAW, IPV6_CHECKSUM, ..) -> %d\n", + s, sock->conn->pcb.raw->chksum_reqd)); + break; +#endif /* LWIP_IPV6 */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_RAW, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + break; + } /* switch (optname) */ + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", + s, level, optname)); + err = ENOPROTOOPT; + break; + } /* switch (level) */ + + return err; +} + +int +lwip_ioctl(int s, long cmd, void *argp) +{ + struct lwip_sock *sock = get_socket(s); + u8_t val; +#if LWIP_SO_RCVBUF + u16_t buflen = 0; + int recv_avail; +#endif /* LWIP_SO_RCVBUF */ + + if (!sock) { + return -1; + } + + switch (cmd) { +#if LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE + case FIONREAD: + if (!argp) { + sock_set_errno(sock, EINVAL); + return -1; + } +#if LWIP_FIONREAD_LINUXMODE + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { + struct pbuf *p; + if (sock->lastdata) { + p = ((struct netbuf *)sock->lastdata)->p; + } else { + struct netbuf *rxbuf; + err_t err; + if (sock->rcvevent <= 0) { + *((u16_t*)argp) = 0; + } else { + err = netconn_recv(sock->conn, &rxbuf); + if (err != ERR_OK) { + *((u16_t*)argp) = 0; + } else { + sock->lastdata = rxbuf; + *((u16_t*)argp) = rxbuf->p->tot_len; + } + } + } + return 0; + } +#endif /* LWIP_FIONREAD_LINUXMODE */ + +#if LWIP_SO_RCVBUF + /* we come here if either LWIP_FIONREAD_LINUXMODE==0 or this is a TCP socket */ + SYS_ARCH_GET(sock->conn->recv_avail, recv_avail); + if (recv_avail < 0) { + recv_avail = 0; + } + *((int*)argp) = recv_avail; + + /* Check if there is data left from the last recv operation. /maq 041215 */ + if (sock->lastdata) { + struct pbuf *p = (struct pbuf *)sock->lastdata; + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { + p = ((struct netbuf *)p)->p; + } + buflen = p->tot_len; + buflen -= sock->lastoffset; + + *((int*)argp) += buflen; + } + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %"U16_F"\n", s, argp, *((u16_t*)argp))); + sock_set_errno(sock, 0); + return 0; +#else /* LWIP_SO_RCVBUF */ + break; +#endif /* LWIP_SO_RCVBUF */ +#endif /* LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE */ + + case (long)FIONBIO: + val = 0; + if (argp && *(u32_t*)argp) { + val = 1; + } + netconn_set_nonblocking(sock->conn, val); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, val)); + sock_set_errno(sock, 0); + return 0; + + default: + break; + } /* switch (cmd) */ + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s, cmd, argp)); + sock_set_errno(sock, ENOSYS); /* not yet implemented */ + return -1; +} + +/** A minimal implementation of fcntl. + * Currently only the commands F_GETFL and F_SETFL are implemented. + * Only the flag O_NONBLOCK is implemented. + */ +int +lwip_fcntl(int s, int cmd, int val) +{ + struct lwip_sock *sock = get_socket(s); + int ret = -1; + + if (!sock) { + return -1; + } + + switch (cmd) { + case F_GETFL: + ret = netconn_is_nonblocking(sock->conn) ? O_NONBLOCK : 0; + sock_set_errno(sock, 0); + break; + case F_SETFL: + if ((val & ~O_NONBLOCK) == 0) { + /* only O_NONBLOCK, all other bits are zero */ + netconn_set_nonblocking(sock->conn, val & O_NONBLOCK); + ret = 0; + sock_set_errno(sock, 0); + } else { + sock_set_errno(sock, ENOSYS); /* not yet implemented */ + } + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_fcntl(%d, UNIMPL: %d, %d)\n", s, cmd, val)); + sock_set_errno(sock, ENOSYS); /* not yet implemented */ + break; + } + return ret; +} + +#endif /* LWIP_SOCKET */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/api/tcpip.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/api/tcpip.c new file mode 100644 index 0000000..43ef3bd --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/api/tcpip.c @@ -0,0 +1,571 @@ +/** + * @file + * Sequential API Main thread module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if !NO_SYS /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/sys.h" +#include "lwip/memp.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/tcpip.h" +#include "lwip/init.h" +#include "lwip/lwip_ip.h" +#include "netif/etharp.h" +#include "netif/ppp/pppoe.h" + +#define TCPIP_MSG_VAR_REF(name) API_VAR_REF(name) +#define TCPIP_MSG_VAR_DECLARE(name) API_VAR_DECLARE(struct tcpip_msg, name) +#define TCPIP_MSG_VAR_ALLOC(name) API_VAR_ALLOC(struct tcpip_msg, MEMP_TCPIP_MSG_API, name) +#define TCPIP_MSG_VAR_FREE(name) API_VAR_FREE(MEMP_TCPIP_MSG_API, name) + +/* global variables */ +static tcpip_init_done_fn tcpip_init_done; +static void *tcpip_init_done_arg; +static sys_mbox_t mbox; + +#if LWIP_TCPIP_CORE_LOCKING +/** The global semaphore to lock the stack. */ +sys_mutex_t lock_tcpip_core; +#endif /* LWIP_TCPIP_CORE_LOCKING */ + + +/** + * The main lwIP thread. This thread has exclusive access to lwIP core functions + * (unless access to them is not locked). Other threads communicate with this + * thread using message boxes. + * + * It also starts all the timers to make sure they are running in the right + * thread context. + * + * @param arg unused argument + */ +static void +tcpip_thread(void *arg) +{ + struct tcpip_msg *msg; + LWIP_UNUSED_ARG(arg); + + if (tcpip_init_done != NULL) { + tcpip_init_done(tcpip_init_done_arg); + } + + LOCK_TCPIP_CORE(); + while (1) { /* MAIN Loop */ + UNLOCK_TCPIP_CORE(); + LWIP_TCPIP_THREAD_ALIVE(); + /* wait for a message, timeouts are processed while waiting */ + sys_timeouts_mbox_fetch(&mbox, (void **)&msg); + LOCK_TCPIP_CORE(); + if (msg == NULL) { + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: NULL\n")); + LWIP_ASSERT("tcpip_thread: invalid message", 0); + continue; + } + switch (msg->type) { +#if LWIP_NETCONN || LWIP_SOCKET + case TCPIP_MSG_API: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg)); + msg->msg.apimsg->function(&(msg->msg.apimsg->msg)); + break; +#endif /* LWIP_NETCONN || LWIP_SOCKET */ + +#if !LWIP_TCPIP_CORE_LOCKING_INPUT + case TCPIP_MSG_INPKT: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: PACKET %p\n", (void *)msg)); +#if LWIP_ETHERNET + if (msg->msg.inp.netif->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) { + ethernet_input(msg->msg.inp.p, msg->msg.inp.netif); + } else +#endif /* LWIP_ETHERNET */ +#if LWIP_IPV6 + if ((*((unsigned char *)(msg->msg.inp.p->payload)) & 0xf0) == 0x60) { + ip6_input(msg->msg.inp.p, msg->msg.inp.netif); + } else +#endif /* LWIP_IPV6 */ + { + ip_input(msg->msg.inp.p, msg->msg.inp.netif); + } + memp_free(MEMP_TCPIP_MSG_INPKT, msg); + break; +#endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */ + +#if LWIP_NETIF_API + case TCPIP_MSG_NETIFAPI: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: Netif API message %p\n", (void *)msg)); + msg->msg.netifapimsg->function(&(msg->msg.netifapimsg->msg)); + break; +#endif /* LWIP_NETIF_API */ + +#if LWIP_PPP_API + case TCPIP_MSG_PPPAPI: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: PPP API message %p\n", (void *)msg)); + msg->msg.pppapimsg->function(&(msg->msg.pppapimsg->msg)); + break; +#endif /* LWIP_PPP_API */ + +#if LWIP_TCPIP_TIMEOUT + case TCPIP_MSG_TIMEOUT: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: TIMEOUT %p\n", (void *)msg)); + sys_timeout(msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg); + memp_free(MEMP_TCPIP_MSG_API, msg); + break; + case TCPIP_MSG_UNTIMEOUT: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: UNTIMEOUT %p\n", (void *)msg)); + sys_untimeout(msg->msg.tmo.h, msg->msg.tmo.arg); + memp_free(MEMP_TCPIP_MSG_API, msg); + break; +#endif /* LWIP_TCPIP_TIMEOUT */ + + case TCPIP_MSG_CALLBACK: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg)); + msg->msg.cb.function(msg->msg.cb.ctx); + memp_free(MEMP_TCPIP_MSG_API, msg); + break; + + case TCPIP_MSG_CALLBACK_STATIC: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK_STATIC %p\n", (void *)msg)); + msg->msg.cb.function(msg->msg.cb.ctx); + break; + + default: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: %d\n", msg->type)); + LWIP_ASSERT("tcpip_thread: invalid message", 0); + break; + } + } +} + +/** + * Pass a received packet to tcpip_thread for input processing + * + * @param p the received packet, p->payload pointing to the Ethernet header or + * to an IP header (if inp doesn't have NETIF_FLAG_ETHARP or + * NETIF_FLAG_ETHERNET flags) + * @param inp the network interface on which the packet was received + */ +err_t +tcpip_input(struct pbuf *p, struct netif *inp) +{ +#if LWIP_TCPIP_CORE_LOCKING_INPUT + err_t ret; + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_input: PACKET %p/%p\n", (void *)p, (void *)inp)); + LOCK_TCPIP_CORE(); +#if LWIP_ETHERNET + if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) { + ret = ethernet_input(p, inp); + } else +#endif /* LWIP_ETHERNET */ + { + ret = ip_input(p, inp); + } + UNLOCK_TCPIP_CORE(); + return ret; +#else /* LWIP_TCPIP_CORE_LOCKING_INPUT */ + struct tcpip_msg *msg; + + if (!sys_mbox_valid(&mbox)) { + return ERR_VAL; + } + msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_INPKT); + if (msg == NULL) { + return ERR_MEM; + } + + msg->type = TCPIP_MSG_INPKT; + msg->msg.inp.p = p; + msg->msg.inp.netif = inp; + if (sys_mbox_trypost(&mbox, msg) != ERR_OK) { + memp_free(MEMP_TCPIP_MSG_INPKT, msg); + return ERR_MEM; + } + return ERR_OK; +#endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */ +} + +/** + * Call a specific function in the thread context of + * tcpip_thread for easy access synchronization. + * A function called in that way may access lwIP core code + * without fearing concurrent access. + * + * @param f the function to call + * @param ctx parameter passed to f + * @param block 1 to block until the request is posted, 0 to non-blocking mode + * @return ERR_OK if the function was called, another err_t if not + */ +err_t +tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block) +{ + struct tcpip_msg *msg; + + if (sys_mbox_valid(&mbox)) { + msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); + if (msg == NULL) { + return ERR_MEM; + } + + msg->type = TCPIP_MSG_CALLBACK; + msg->msg.cb.function = function; + msg->msg.cb.ctx = ctx; + if (block) { + sys_mbox_post(&mbox, msg); + } else { + if (sys_mbox_trypost(&mbox, msg) != ERR_OK) { + memp_free(MEMP_TCPIP_MSG_API, msg); + return ERR_MEM; + } + } + return ERR_OK; + } + return ERR_VAL; +} + +#if LWIP_TCPIP_TIMEOUT +/** + * call sys_timeout in tcpip_thread + * + * @param msec time in milliseconds for timeout + * @param h function to be called on timeout + * @param arg argument to pass to timeout function h + * @return ERR_MEM on memory error, ERR_OK otherwise + */ +err_t +tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg) +{ + struct tcpip_msg *msg; + + if (sys_mbox_valid(&mbox)) { + msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); + if (msg == NULL) { + return ERR_MEM; + } + + msg->type = TCPIP_MSG_TIMEOUT; + msg->msg.tmo.msecs = msecs; + msg->msg.tmo.h = h; + msg->msg.tmo.arg = arg; + sys_mbox_post(&mbox, msg); + return ERR_OK; + } + return ERR_VAL; +} + +/** + * call sys_untimeout in tcpip_thread + * + * @param msec time in milliseconds for timeout + * @param h function to be called on timeout + * @param arg argument to pass to timeout function h + * @return ERR_MEM on memory error, ERR_OK otherwise + */ +err_t +tcpip_untimeout(sys_timeout_handler h, void *arg) +{ + struct tcpip_msg *msg; + + if (sys_mbox_valid(&mbox)) { + msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); + if (msg == NULL) { + return ERR_MEM; + } + + msg->type = TCPIP_MSG_UNTIMEOUT; + msg->msg.tmo.h = h; + msg->msg.tmo.arg = arg; + sys_mbox_post(&mbox, msg); + return ERR_OK; + } + return ERR_VAL; +} +#endif /* LWIP_TCPIP_TIMEOUT */ + +#if LWIP_NETCONN || LWIP_SOCKET +/** + * Call the lower part of a netconn_* function + * This function is then running in the thread context + * of tcpip_thread and has exclusive access to lwIP core code. + * + * @param apimsg a struct containing the function to call and its parameters + * @return ERR_OK if the function was called, another err_t if not + */ +err_t +tcpip_apimsg(struct api_msg *apimsg) +{ + TCPIP_MSG_VAR_DECLARE(msg); +#ifdef LWIP_DEBUG + /* catch functions that don't set err */ + apimsg->msg.err = ERR_VAL; +#endif + + if (sys_mbox_valid(&mbox)) { + TCPIP_MSG_VAR_ALLOC(msg); + TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_API; + TCPIP_MSG_VAR_REF(msg).msg.apimsg = apimsg; +#if LWIP_NETCONN_SEM_PER_THREAD + apimsg->msg.op_completed_sem = LWIP_NETCONN_THREAD_SEM_GET(); + LWIP_ASSERT("netconn semaphore not initialized", + apimsg->msg.op_completed_sem != SYS_SEM_NULL); +#endif + sys_mbox_post(&mbox, &TCPIP_MSG_VAR_REF(msg)); + sys_arch_sem_wait(LWIP_API_MSG_SEM(&apimsg->msg), 0); + TCPIP_MSG_VAR_FREE(msg); + return apimsg->msg.err; + } + return ERR_VAL; +} + +#endif /* LWIP_NETCONN || LWIP_SOCKET */ + +#if LWIP_NETIF_API +#if !LWIP_TCPIP_CORE_LOCKING +/** + * Much like tcpip_apimsg, but calls the lower part of a netifapi_* + * function. + * + * @param netifapimsg a struct containing the function to call and its parameters + * @return error code given back by the function that was called + */ +err_t +tcpip_netifapi(struct netifapi_msg* netifapimsg) +{ + TCPIP_MSG_VAR_DECLARE(msg); + + if (sys_mbox_valid(&mbox)) { + err_t err; + TCPIP_MSG_VAR_ALLOC(msg); + + err = sys_sem_new(&netifapimsg->msg.sem, 0); + if (err != ERR_OK) { + netifapimsg->msg.err = err; + return err; + } + + TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_NETIFAPI; + TCPIP_MSG_VAR_REF(msg).msg.netifapimsg = netifapimsg; + sys_mbox_post(&mbox, &TCPIP_MSG_VAR_REF(msg)); + sys_sem_wait(&netifapimsg->msg.sem); + sys_sem_free(&netifapimsg->msg.sem); + TCPIP_MSG_VAR_FREE(msg); + return netifapimsg->msg.err; + } + return ERR_VAL; +} +#else /* !LWIP_TCPIP_CORE_LOCKING */ +/** + * Call the lower part of a netifapi_* function + * This function has exclusive access to lwIP core code by locking it + * before the function is called. + * + * @param netifapimsg a struct containing the function to call and its parameters + * @return ERR_OK (only for compatibility fo tcpip_netifapi()) + */ +err_t +tcpip_netifapi_lock(struct netifapi_msg* netifapimsg) +{ + LOCK_TCPIP_CORE(); + netifapimsg->function(&(netifapimsg->msg)); + UNLOCK_TCPIP_CORE(); + return netifapimsg->msg.err; +} +#endif /* !LWIP_TCPIP_CORE_LOCKING */ +#endif /* LWIP_NETIF_API */ + +#if LWIP_PPP_API +#if !LWIP_TCPIP_CORE_LOCKING +/** + * Much like tcpip_apimsg, but calls the lower part of a pppapi_* + * function. + * + * @param pppapimsg a struct containing the function to call and its parameters + * @return error code given back by the function that was called + */ +err_t +tcpip_pppapi(struct pppapi_msg* pppapimsg) +{ + struct tcpip_msg msg; + + if (sys_mbox_valid(&mbox)) { + err_t err = sys_sem_new(&pppapimsg->msg.sem, 0); + if (err != ERR_OK) { + pppapimsg->msg.err = err; + return err; + } + + msg.type = TCPIP_MSG_PPPAPI; + msg.msg.pppapimsg = pppapimsg; + sys_mbox_post(&mbox, &msg); + sys_sem_wait(&pppapimsg->msg.sem); + sys_sem_free(&pppapimsg->msg.sem); + return pppapimsg->msg.err; + } + return ERR_VAL; +} +#else /* !LWIP_TCPIP_CORE_LOCKING */ +/** + * Call the lower part of a pppapi_* function + * This function has exclusive access to lwIP core code by locking it + * before the function is called. + * + * @param pppapimsg a struct containing the function to call and its parameters + * @return ERR_OK (only for compatibility fo tcpip_pppapi()) + */ +err_t +tcpip_pppapi_lock(struct pppapi_msg* pppapimsg) +{ + LOCK_TCPIP_CORE(); + pppapimsg->function(&(pppapimsg->msg)); + UNLOCK_TCPIP_CORE(); + return pppapimsg->msg.err; +} +#endif /* !LWIP_TCPIP_CORE_LOCKING */ +#endif /* LWIP_PPP_API */ + +/** + * Allocate a structure for a static callback message and initialize it. + * This is intended to be used to send "static" messages from interrupt context. + * + * @param function the function to call + * @param ctx parameter passed to function + * @return a struct pointer to pass to tcpip_trycallback(). + */ +struct tcpip_callback_msg* tcpip_callbackmsg_new(tcpip_callback_fn function, void *ctx) +{ + struct tcpip_msg *msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); + if (msg == NULL) { + return NULL; + } + msg->type = TCPIP_MSG_CALLBACK_STATIC; + msg->msg.cb.function = function; + msg->msg.cb.ctx = ctx; + return (struct tcpip_callback_msg*)msg; +} + +/** + * Free a callback message allocated by tcpip_callbackmsg_new(). + * + * @param msg the message to free + */ +void tcpip_callbackmsg_delete(struct tcpip_callback_msg* msg) +{ + memp_free(MEMP_TCPIP_MSG_API, msg); +} + +/** + * Try to post a callback-message to the tcpip_thread mbox + * This is intended to be used to send "static" messages from interrupt context. + * + * @param msg pointer to the message to post + * @return sys_mbox_trypost() return code + */ +err_t +tcpip_trycallback(struct tcpip_callback_msg* msg) +{ + if (!sys_mbox_valid(&mbox)) { + return ERR_VAL; + } + return sys_mbox_trypost(&mbox, msg); +} + +/** + * Initialize this module: + * - initialize all sub modules + * - start the tcpip_thread + * + * @param initfunc a function to call when tcpip_thread is running and finished initializing + * @param arg argument to pass to initfunc + */ +void +tcpip_init(tcpip_init_done_fn initfunc, void *arg) +{ + lwip_init(); + + tcpip_init_done = initfunc; + tcpip_init_done_arg = arg; + if(sys_mbox_new(&mbox, TCPIP_MBOX_SIZE) != ERR_OK) { + LWIP_ASSERT("failed to create tcpip_thread mbox", 0); + } +#if LWIP_TCPIP_CORE_LOCKING + if(sys_mutex_new(&lock_tcpip_core) != ERR_OK) { + LWIP_ASSERT("failed to create lock_tcpip_core", 0); + } +#endif /* LWIP_TCPIP_CORE_LOCKING */ + + sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO); +} + +/** + * Simple callback function used with tcpip_callback to free a pbuf + * (pbuf_free has a wrong signature for tcpip_callback) + * + * @param p The pbuf (chain) to be dereferenced. + */ +static void +pbuf_free_int(void *p) +{ + struct pbuf *q = (struct pbuf *)p; + pbuf_free(q); +} + +/** + * A simple wrapper function that allows you to free a pbuf from interrupt context. + * + * @param p The pbuf (chain) to be dereferenced. + * @return ERR_OK if callback could be enqueued, an err_t if not + */ +err_t +pbuf_free_callback(struct pbuf *p) +{ + return tcpip_callback_with_block(pbuf_free_int, p, 0); +} + +/** + * A simple wrapper function that allows you to free heap memory from + * interrupt context. + * + * @param m the heap memory to free + * @return ERR_OK if callback could be enqueued, an err_t if not + */ +err_t +mem_free_callback(void *m) +{ + return tcpip_callback_with_block(mem_free, m, 0); +} + +#endif /* !NO_SYS */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/core/def.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/def.c new file mode 100644 index 0000000..352b552 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/def.c @@ -0,0 +1,108 @@ +/** + * @file + * Common functions used throughout the stack. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Simon Goldschmidt + * + */ + +#include "lwip/opt.h" +#include "lwip/def.h" + +/** + * These are reference implementations of the byte swapping functions. + * Again with the aim of being simple, correct and fully portable. + * Byte swapping is the second thing you would want to optimize. You will + * need to port it to your architecture and in your cc.h: + * + * #define LWIP_PLATFORM_BYTESWAP 1 + * #define LWIP_PLATFORM_HTONS(x) + * #define LWIP_PLATFORM_HTONL(x) + * + * Note ntohs() and ntohl() are merely references to the htonx counterparts. + */ + +#if (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN) + +/** + * Convert an u16_t from host- to network byte order. + * + * @param n u16_t in host byte order + * @return n in network byte order + */ +u16_t +lwip_htons(u16_t n) +{ + return ((n & 0xff) << 8) | ((n & 0xff00) >> 8); +} + +/** + * Convert an u16_t from network- to host byte order. + * + * @param n u16_t in network byte order + * @return n in host byte order + */ +u16_t +lwip_ntohs(u16_t n) +{ + return lwip_htons(n); +} + +/** + * Convert an u32_t from host- to network byte order. + * + * @param n u32_t in host byte order + * @return n in network byte order + */ +u32_t +lwip_htonl(u32_t n) +{ + return ((n & 0xff) << 24) | + ((n & 0xff00) << 8) | + ((n & 0xff0000UL) >> 8) | + ((n & 0xff000000UL) >> 24); +} + +/** + * Convert an u32_t from network- to host byte order. + * + * @param n u32_t in network byte order + * @return n in host byte order + */ +u32_t +lwip_ntohl(u32_t n) +{ + return lwip_htonl(n); +} + +#endif /* (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN) */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/core/dhcp.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/dhcp.c new file mode 100644 index 0000000..2dbde23 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/dhcp.c @@ -0,0 +1,1844 @@ +/** + * @file + * Dynamic Host Configuration Protocol client + * + */ + +/* + * + * Copyright (c) 2001-2004 Leon Woestenberg + * Copyright (c) 2001-2004 Axon Digital Design B.V., The Netherlands. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is a contribution to the lwIP TCP/IP stack. + * The Swedish Institute of Computer Science and Adam Dunkels + * are specifically granted permission to redistribute this + * source code. + * + * Author: Leon Woestenberg + * + * This is a DHCP client for the lwIP TCP/IP stack. It aims to conform + * with RFC 2131 and RFC 2132. + * + * TODO: + * - Support for interfaces other than Ethernet (SLIP, PPP, ...) + * + * Please coordinate changes and requests with Leon Woestenberg + * + * + * Integration with your code: + * + * In lwip/dhcp.h + * #define DHCP_COARSE_TIMER_SECS (recommended 60 which is a minute) + * #define DHCP_FINE_TIMER_MSECS (recommended 500 which equals TCP coarse timer) + * + * Then have your application call dhcp_coarse_tmr() and + * dhcp_fine_tmr() on the defined intervals. + * + * dhcp_start(struct netif *netif); + * starts a DHCP client instance which configures the interface by + * obtaining an IP address lease and maintaining it. + * + * Use dhcp_release(netif) to end the lease and use dhcp_stop(netif) + * to remove the DHCP client. + * + */ + +#include "lwip/opt.h" + +#if LWIP_DHCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/stats.h" +#include "lwip/mem.h" +#include "lwip/udp.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/def.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" +#include "lwip/dns.h" +#include "netif/etharp.h" + +#include + +/** DHCP_CREATE_RAND_XID: if this is set to 1, the xid is created using + * LWIP_RAND() (this overrides DHCP_GLOBAL_XID) + */ +#ifndef DHCP_CREATE_RAND_XID +#define DHCP_CREATE_RAND_XID 1 +#endif + +/** Default for DHCP_GLOBAL_XID is 0xABCD0000 + * This can be changed by defining DHCP_GLOBAL_XID and DHCP_GLOBAL_XID_HEADER, e.g. + * #define DHCP_GLOBAL_XID_HEADER "stdlib.h" + * #define DHCP_GLOBAL_XID rand() + */ +#ifdef DHCP_GLOBAL_XID_HEADER +#include DHCP_GLOBAL_XID_HEADER /* include optional starting XID generation prototypes */ +#endif + +/** DHCP_OPTION_MAX_MSG_SIZE is set to the MTU + * MTU is checked to be big enough in dhcp_start */ +#define DHCP_MAX_MSG_LEN(netif) (netif->mtu) +#define DHCP_MAX_MSG_LEN_MIN_REQUIRED 576 +/** Minimum length for reply before packet is parsed */ +#define DHCP_MIN_REPLY_LEN 44 + +#define REBOOT_TRIES 2 + +/** Option handling: options are parsed in dhcp_parse_reply + * and saved in an array where other functions can load them from. + * This might be moved into the struct dhcp (not necessarily since + * lwIP is single-threaded and the array is only used while in recv + * callback). */ +#define DHCP_OPTION_IDX_OVERLOAD 0 +#define DHCP_OPTION_IDX_MSG_TYPE 1 +#define DHCP_OPTION_IDX_SERVER_ID 2 +#define DHCP_OPTION_IDX_LEASE_TIME 3 +#define DHCP_OPTION_IDX_T1 4 +#define DHCP_OPTION_IDX_T2 5 +#define DHCP_OPTION_IDX_SUBNET_MASK 6 +#define DHCP_OPTION_IDX_ROUTER 7 +#define DHCP_OPTION_IDX_DNS_SERVER 8 +#define DHCP_OPTION_IDX_MAX (DHCP_OPTION_IDX_DNS_SERVER + DNS_MAX_SERVERS) + +/** Holds the decoded option values, only valid while in dhcp_recv. + @todo: move this into struct dhcp? */ +u32_t dhcp_rx_options_val[DHCP_OPTION_IDX_MAX]; +/** Holds a flag which option was received and is contained in dhcp_rx_options_val, + only valid while in dhcp_recv. + @todo: move this into struct dhcp? */ +u8_t dhcp_rx_options_given[DHCP_OPTION_IDX_MAX]; + +#ifdef DHCP_GLOBAL_XID +static u32_t xid; +static u8_t xid_initialised; +#endif /* DHCP_GLOBAL_XID */ + +#define dhcp_option_given(dhcp, idx) (dhcp_rx_options_given[idx] != 0) +#define dhcp_got_option(dhcp, idx) (dhcp_rx_options_given[idx] = 1) +#define dhcp_clear_option(dhcp, idx) (dhcp_rx_options_given[idx] = 0) +#define dhcp_clear_all_options(dhcp) (memset(dhcp_rx_options_given, 0, sizeof(dhcp_rx_options_given))) +#define dhcp_get_option_value(dhcp, idx) (dhcp_rx_options_val[idx]) +#define dhcp_set_option_value(dhcp, idx, val) (dhcp_rx_options_val[idx] = (val)) + + +/* DHCP client state machine functions */ +static err_t dhcp_discover(struct netif *netif); +static err_t dhcp_select(struct netif *netif); +static void dhcp_bind(struct netif *netif); +#if DHCP_DOES_ARP_CHECK +static err_t dhcp_decline(struct netif *netif); +#endif /* DHCP_DOES_ARP_CHECK */ +static err_t dhcp_rebind(struct netif *netif); +static err_t dhcp_reboot(struct netif *netif); +static void dhcp_set_state(struct dhcp *dhcp, u8_t new_state); + +/* receive, unfold, parse and free incoming messages */ +static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port); + +/* set the DHCP timers */ +static void dhcp_timeout(struct netif *netif); +static void dhcp_t1_timeout(struct netif *netif); +static void dhcp_t2_timeout(struct netif *netif); + +/* build outgoing messages */ +/* create a DHCP message, fill in common headers */ +static err_t dhcp_create_msg(struct netif *netif, struct dhcp *dhcp, u8_t message_type); +/* free a DHCP request */ +static void dhcp_delete_msg(struct dhcp *dhcp); +/* add a DHCP option (type, then length in bytes) */ +static void dhcp_option(struct dhcp *dhcp, u8_t option_type, u8_t option_len); +/* add option values */ +static void dhcp_option_byte(struct dhcp *dhcp, u8_t value); +static void dhcp_option_short(struct dhcp *dhcp, u16_t value); +static void dhcp_option_long(struct dhcp *dhcp, u32_t value); +#if LWIP_NETIF_HOSTNAME +static void dhcp_option_hostname(struct dhcp *dhcp, struct netif *netif); +#endif /* LWIP_NETIF_HOSTNAME */ +/* always add the DHCP options trailer to end and pad */ +static void dhcp_option_trailer(struct dhcp *dhcp); + +/** + * Back-off the DHCP client (because of a received NAK response). + * + * Back-off the DHCP client because of a received NAK. Receiving a + * NAK means the client asked for something non-sensible, for + * example when it tries to renew a lease obtained on another network. + * + * We clear any existing set IP address and restart DHCP negotiation + * afresh (as per RFC2131 3.2.3). + * + * @param netif the netif under DHCP control + */ +static void +dhcp_handle_nak(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_nak(netif=%p) %c%c%"U16_F"\n", + (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); + /* Set the interface down since the address must no longer be used, as per RFC2131 */ + netif_set_down(netif); + /* remove IP address from interface */ + netif_set_ipaddr(netif, IP_ADDR_ANY); + netif_set_gw(netif, IP_ADDR_ANY); + netif_set_netmask(netif, IP_ADDR_ANY); + /* Change to a defined state */ + dhcp_set_state(dhcp, DHCP_BACKING_OFF); + /* We can immediately restart discovery */ + dhcp_discover(netif); +} + +#if DHCP_DOES_ARP_CHECK +/** + * Checks if the offered IP address is already in use. + * + * It does so by sending an ARP request for the offered address and + * entering CHECKING state. If no ARP reply is received within a small + * interval, the address is assumed to be free for use by us. + * + * @param netif the netif under DHCP control + */ +static void +dhcp_check(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result; + u16_t msecs; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_check(netif=%p) %c%c\n", (void *)netif, (s16_t)netif->name[0], + (s16_t)netif->name[1])); + dhcp_set_state(dhcp, DHCP_CHECKING); + /* create an ARP query for the offered IP address, expecting that no host + responds, as the IP address should not be in use. */ + result = etharp_query(netif, &dhcp->offered_ip_addr, NULL); + if (result != ERR_OK) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_check: could not perform ARP query\n")); + } + dhcp->tries++; + msecs = 500; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_check(): set request timeout %"U16_F" msecs\n", msecs)); +} +#endif /* DHCP_DOES_ARP_CHECK */ + +/** + * Remember the configuration offered by a DHCP server. + * + * @param netif the netif under DHCP control + */ +static void +dhcp_handle_offer(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_offer(netif=%p) %c%c%"U16_F"\n", + (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); + /* obtain the server address */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_SERVER_ID)) { + ip4_addr_set_u32(&dhcp->server_ip_addr, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SERVER_ID))); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): server 0x%08"X32_F"\n", + ip4_addr_get_u32(&dhcp->server_ip_addr))); + /* remember offered address */ + ip_addr_copy(dhcp->offered_ip_addr, dhcp->msg_in->yiaddr); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): offer for 0x%08"X32_F"\n", + ip4_addr_get_u32(&dhcp->offered_ip_addr))); + + dhcp_select(netif); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("dhcp_handle_offer(netif=%p) did not get server ID!\n", (void*)netif)); + } +} + +/** + * Select a DHCP server offer out of all offers. + * + * Simply select the first offer received. + * + * @param netif the netif under DHCP control + * @return lwIP specific error (see error.h) + */ +static err_t +dhcp_select(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result; + u16_t msecs; + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_select(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); + dhcp_set_state(dhcp, DHCP_REQUESTING); + + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); + if (result == ERR_OK) { + dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); + + /* MUST request the offered IP address */ + dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); + dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr))); + + dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4); + dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->server_ip_addr))); + + dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 4/*num options*/); + dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK); + dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER); + dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST); + dhcp_option_byte(dhcp, DHCP_OPTION_DNS_SERVER); + +#if LWIP_NETIF_HOSTNAME + dhcp_option_hostname(dhcp, netif); +#endif /* LWIP_NETIF_HOSTNAME */ + + dhcp_option_trailer(dhcp); + /* shrink the pbuf to the actual content length */ + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + /* send broadcast to any DHCP server */ + udp_sendto_if_src(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP_ADDR_ANY); + dhcp_delete_msg(dhcp); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_select: REQUESTING\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_select: could not allocate DHCP request\n")); + } + dhcp->tries++; + msecs = (dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_select(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} + +/** + * The DHCP timer that checks for lease renewal/rebind timeouts. + */ +void +dhcp_coarse_tmr() +{ + struct netif *netif = netif_list; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_coarse_tmr()\n")); + /* iterate through all network interfaces */ + while (netif != NULL) { + /* only act on DHCP configured interfaces */ + if (netif->dhcp != NULL) { + /* timer is active (non zero), and triggers (zeroes) now? */ + if (netif->dhcp->t2_timeout-- == 1) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t2 timeout\n")); + /* this clients' rebind timeout triggered */ + dhcp_t2_timeout(netif); + /* timer is active (non zero), and triggers (zeroes) now */ + } else if (netif->dhcp->t1_timeout-- == 1) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t1 timeout\n")); + /* this clients' renewal timeout triggered */ + dhcp_t1_timeout(netif); + } + } + /* proceed to next netif */ + netif = netif->next; + } +} + +/** + * DHCP transaction timeout handling + * + * A DHCP server is expected to respond within a short period of time. + * This timer checks whether an outstanding DHCP request is timed out. + */ +void +dhcp_fine_tmr() +{ + struct netif *netif = netif_list; + /* loop through netif's */ + while (netif != NULL) { + /* only act on DHCP configured interfaces */ + if (netif->dhcp != NULL) { + /* timer is active (non zero), and is about to trigger now */ + if (netif->dhcp->request_timeout > 1) { + netif->dhcp->request_timeout--; + } + else if (netif->dhcp->request_timeout == 1) { + netif->dhcp->request_timeout--; + /* { netif->dhcp->request_timeout == 0 } */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_fine_tmr(): request timeout\n")); + /* this client's request timeout triggered */ + dhcp_timeout(netif); + } + } + /* proceed to next network interface */ + netif = netif->next; + } +} + +/** + * A DHCP negotiation transaction, or ARP request, has timed out. + * + * The timer that was started with the DHCP or ARP request has + * timed out, indicating no response was received in time. + * + * @param netif the netif under DHCP control + */ +static void +dhcp_timeout(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout()\n")); + /* back-off period has passed, or server selection timed out */ + if ((dhcp->state == DHCP_BACKING_OFF) || (dhcp->state == DHCP_SELECTING)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout(): restarting discovery\n")); + dhcp_discover(netif); + /* receiving the requested lease timed out */ + } else if (dhcp->state == DHCP_REQUESTING) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REQUESTING, DHCP request timed out\n")); + if (dhcp->tries <= 5) { + dhcp_select(netif); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REQUESTING, releasing, restarting\n")); + dhcp_release(netif); + dhcp_discover(netif); + } +#if DHCP_DOES_ARP_CHECK + /* received no ARP reply for the offered address (which is good) */ + } else if (dhcp->state == DHCP_CHECKING) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): CHECKING, ARP request timed out\n")); + if (dhcp->tries <= 1) { + dhcp_check(netif); + /* no ARP replies on the offered address, + looks like the IP address is indeed free */ + } else { + /* bind the interface to the offered address */ + dhcp_bind(netif); + } +#endif /* DHCP_DOES_ARP_CHECK */ + } + /* did not get response to renew request? */ + else if (dhcp->state == DHCP_RENEWING) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): RENEWING, DHCP request timed out\n")); + /* just retry renewal */ + /* note that the rebind timer will eventually time-out if renew does not work */ + dhcp_renew(netif); + /* did not get response to rebind request? */ + } else if (dhcp->state == DHCP_REBINDING) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REBINDING, DHCP request timed out\n")); + if (dhcp->tries <= 8) { + dhcp_rebind(netif); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): RELEASING, DISCOVERING\n")); + dhcp_release(netif); + dhcp_discover(netif); + } + } else if (dhcp->state == DHCP_REBOOTING) { + if (dhcp->tries < REBOOT_TRIES) { + dhcp_reboot(netif); + } else { + dhcp_discover(netif); + } + } +} + +/** + * The renewal period has timed out. + * + * @param netif the netif under DHCP control + */ +static void +dhcp_t1_timeout(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_t1_timeout()\n")); + if ((dhcp->state == DHCP_REQUESTING) || (dhcp->state == DHCP_BOUND) || + (dhcp->state == DHCP_RENEWING)) { + /* just retry to renew - note that the rebind timer (t2) will + * eventually time-out if renew tries fail. */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("dhcp_t1_timeout(): must renew\n")); + /* This slightly different to RFC2131: DHCPREQUEST will be sent from state + DHCP_RENEWING, not DHCP_BOUND */ + dhcp_renew(netif); + } +} + +/** + * The rebind period has timed out. + * + * @param netif the netif under DHCP control + */ +static void +dhcp_t2_timeout(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_t2_timeout()\n")); + if ((dhcp->state == DHCP_REQUESTING) || (dhcp->state == DHCP_BOUND) || + (dhcp->state == DHCP_RENEWING)) { + /* just retry to rebind */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("dhcp_t2_timeout(): must rebind\n")); + /* This slightly different to RFC2131: DHCPREQUEST will be sent from state + DHCP_REBINDING, not DHCP_BOUND */ + dhcp_rebind(netif); + } +} + +/** + * Handle a DHCP ACK packet + * + * @param netif the netif under DHCP control + */ +static void +dhcp_handle_ack(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; +#if LWIP_DNS + u8_t n; +#endif /* LWIP_DNS */ + + /* clear options we might not get from the ACK */ + ip_addr_set_zero(&dhcp->offered_sn_mask); + ip_addr_set_zero(&dhcp->offered_gw_addr); +#if LWIP_DHCP_BOOTP_FILE + ip_addr_set_zero(&dhcp->offered_si_addr); +#endif /* LWIP_DHCP_BOOTP_FILE */ + + /* lease time given? */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_LEASE_TIME)) { + /* remember offered lease time */ + dhcp->offered_t0_lease = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_LEASE_TIME); + } + /* renewal period given? */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_T1)) { + /* remember given renewal period */ + dhcp->offered_t1_renew = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_T1); + } else { + /* calculate safe periods for renewal */ + dhcp->offered_t1_renew = dhcp->offered_t0_lease / 2; + } + + /* renewal period given? */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_T2)) { + /* remember given rebind period */ + dhcp->offered_t2_rebind = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_T2); + } else { + /* calculate safe periods for rebinding */ + dhcp->offered_t2_rebind = dhcp->offered_t0_lease; + } + + /* (y)our internet address */ + ip_addr_copy(dhcp->offered_ip_addr, dhcp->msg_in->yiaddr); + +#if LWIP_DHCP_BOOTP_FILE + /* copy boot server address, + boot file name copied in dhcp_parse_reply if not overloaded */ + ip_addr_copy(dhcp->offered_si_addr, dhcp->msg_in->siaddr); +#endif /* LWIP_DHCP_BOOTP_FILE */ + + /* subnet mask given? */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_SUBNET_MASK)) { + /* remember given subnet mask */ + ip4_addr_set_u32(&dhcp->offered_sn_mask, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SUBNET_MASK))); + dhcp->subnet_mask_given = 1; + } else { + dhcp->subnet_mask_given = 0; + } + + /* gateway router */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_ROUTER)) { + ip4_addr_set_u32(&dhcp->offered_gw_addr, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_ROUTER))); + } + +#if LWIP_DNS + /* DNS servers */ + for(n = 0; (n < DNS_MAX_SERVERS) && dhcp_option_given(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n); n++) { + ip_addr_t dns_addr; + ip4_addr_set_u32(&dns_addr, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n))); + dns_setserver(n, &dns_addr); + } +#endif /* LWIP_DNS */ +} + +/** Set a statically allocated struct dhcp to work with. + * Using this prevents dhcp_start to allocate it using mem_malloc. + * + * @param netif the netif for which to set the struct dhcp + * @param dhcp (uninitialised) dhcp struct allocated by the application + */ +void +dhcp_set_struct(struct netif *netif, struct dhcp *dhcp) +{ + LWIP_ASSERT("netif != NULL", netif != NULL); + LWIP_ASSERT("dhcp != NULL", dhcp != NULL); + LWIP_ASSERT("netif already has a struct dhcp set", netif->dhcp == NULL); + + /* clear data structure */ + memset(dhcp, 0, sizeof(struct dhcp)); + /* dhcp_set_state(&dhcp, DHCP_OFF); */ + netif->dhcp = dhcp; +} + +/** Removes a struct dhcp from a netif. + * + * ATTENTION: Only use this when not using dhcp_set_struct() to allocate the + * struct dhcp since the memory is passed back to the heap. + * + * @param netif the netif from which to remove the struct dhcp + */ +void dhcp_cleanup(struct netif *netif) +{ + LWIP_ASSERT("netif != NULL", netif != NULL); + + if (netif->dhcp != NULL) { + mem_free(netif->dhcp); + netif->dhcp = NULL; + } +} + +/** + * Start DHCP negotiation for a network interface. + * + * If no DHCP client instance was attached to this interface, + * a new client is created first. If a DHCP client instance + * was already present, it restarts negotiation. + * + * @param netif The lwIP network interface + * @return lwIP error code + * - ERR_OK - No error + * - ERR_MEM - Out of memory + */ +err_t +dhcp_start(struct netif *netif) +{ + struct dhcp *dhcp; + err_t result; + + LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG;); + dhcp = netif->dhcp; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); + + /* check hwtype of the netif */ + if ((netif->flags & NETIF_FLAG_ETHARP) == 0) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): No ETHARP netif\n")); + return ERR_ARG; + } + + /* check MTU of the netif */ + if (netif->mtu < DHCP_MAX_MSG_LEN_MIN_REQUIRED) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): Cannot use this netif with DHCP: MTU is too small\n")); + return ERR_MEM; + } + + /* Remove the flag that says this netif is handled by DHCP, + it is set when we succeeded starting. */ + netif->flags &= ~NETIF_FLAG_DHCP; + + /* no DHCP client attached yet? */ + if (dhcp == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting new DHCP client\n")); + dhcp = (struct dhcp *)mem_malloc(sizeof(struct dhcp)); + if (dhcp == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not allocate dhcp\n")); + return ERR_MEM; + } + /* store this dhcp client in the netif */ + netif->dhcp = dhcp; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): allocated dhcp")); + /* already has DHCP client attached */ + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_start(): restarting DHCP configuration\n")); + if (dhcp->pcb != NULL) { + udp_remove(dhcp->pcb); + } + LWIP_ASSERT("pbuf p_out wasn't freed", dhcp->p_out == NULL); + LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL ); + } + + /* clear data structure */ + memset(dhcp, 0, sizeof(struct dhcp)); + /* dhcp_set_state(&dhcp, DHCP_OFF); */ + /* allocate UDP PCB */ + dhcp->pcb = udp_new(); + if (dhcp->pcb == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not obtain pcb\n")); + return ERR_MEM; + } + ip_set_option(dhcp->pcb, SOF_BROADCAST); + /* set up local and remote port for the pcb */ + udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT); + udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT); + /* set up the recv callback and argument */ + udp_recv(dhcp->pcb, dhcp_recv, netif); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting DHCP configuration\n")); + +#if LWIP_DHCP_CHECK_LINK_UP + if (!netif_is_link_up(netif)) { + /* set state INIT and wait for dhcp_network_changed() to call dhcp_discover() */ + dhcp_set_state(dhcp, DHCP_INIT); + netif->flags |= NETIF_FLAG_DHCP; + return ERR_OK; + } +#endif /* LWIP_DHCP_CHECK_LINK_UP */ + + /* (re)start the DHCP negotiation */ + result = dhcp_discover(netif); + if (result != ERR_OK) { + /* free resources allocated above */ + dhcp_stop(netif); + return ERR_MEM; + } + /* Set the flag that says this netif is handled by DHCP. */ + netif->flags |= NETIF_FLAG_DHCP; + return result; +} + +/** + * Inform a DHCP server of our manual configuration. + * + * This informs DHCP servers of our fixed IP address configuration + * by sending an INFORM message. It does not involve DHCP address + * configuration, it is just here to be nice to the network. + * + * @param netif The lwIP network interface + */ +void +dhcp_inform(struct netif *netif) +{ + struct dhcp dhcp; + err_t result = ERR_OK; + struct udp_pcb *pcb; + + LWIP_ERROR("netif != NULL", (netif != NULL), return;); + + memset(&dhcp, 0, sizeof(struct dhcp)); + dhcp_set_state(&dhcp, DHCP_INFORM); + + if ((netif->dhcp != NULL) && (netif->dhcp->pcb != NULL)) { + /* re-use existing pcb */ + pcb = netif->dhcp->pcb; + } else { + pcb = udp_new(); + if (pcb == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform(): could not obtain pcb")); + return; + } + dhcp.pcb = pcb; + ip_set_option(dhcp.pcb, SOF_BROADCAST); + udp_bind(dhcp.pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_inform(): created new udp pcb\n")); + } + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, &dhcp, DHCP_INFORM); + if (result == ERR_OK) { + dhcp_option(&dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(&dhcp, DHCP_MAX_MSG_LEN(netif)); + + dhcp_option_trailer(&dhcp); + + pbuf_realloc(dhcp.p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp.options_out_len); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_inform: INFORMING\n")); + udp_sendto_if(pcb, dhcp.p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); + dhcp_delete_msg(&dhcp); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform: could not allocate DHCP request\n")); + } + + if (dhcp.pcb != NULL) { + /* otherwise, the existing pcb was used */ + udp_remove(dhcp.pcb); + } +} + +/** Handle a possible change in the network configuration. + * + * This enters the REBOOTING state to verify that the currently bound + * address is still valid. + */ +void +dhcp_network_changed(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + if (!dhcp) + return; + switch (dhcp->state) { + case DHCP_REBINDING: + case DHCP_RENEWING: + case DHCP_BOUND: + case DHCP_REBOOTING: + netif_set_down(netif); + dhcp->tries = 0; + dhcp_reboot(netif); + break; + case DHCP_OFF: + /* stay off */ + break; + default: + /* INIT/REQUESTING/CHECKING/BACKING_OFF restart with new 'rid' because the + state changes, SELECTING: continue with current 'rid' as we stay in the + same state */ +#if LWIP_DHCP_AUTOIP_COOP + if(dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) { + autoip_stop(netif); + dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF; + } +#endif /* LWIP_DHCP_AUTOIP_COOP */ + dhcp_discover(netif); + break; + } +} + +#if DHCP_DOES_ARP_CHECK +/** + * Match an ARP reply with the offered IP address. + * + * @param netif the network interface on which the reply was received + * @param addr The IP address we received a reply from + */ +void dhcp_arp_reply(struct netif *netif, ip_addr_t *addr) +{ + LWIP_ERROR("netif != NULL", (netif != NULL), return;); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_arp_reply()\n")); + /* is a DHCP client doing an ARP check? */ + if ((netif->dhcp != NULL) && (netif->dhcp->state == DHCP_CHECKING)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08"X32_F"\n", + ip4_addr_get_u32(addr))); + /* did a host respond with the address we + were offered by the DHCP server? */ + if (ip_addr_cmp(addr, &netif->dhcp->offered_ip_addr)) { + /* we will not accept the offered address */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING, + ("dhcp_arp_reply(): arp reply matched with offered address, declining\n")); + dhcp_decline(netif); + } + } +} + +/** + * Decline an offered lease. + * + * Tell the DHCP server we do not accept the offered address. + * One reason to decline the lease is when we find out the address + * is already in use by another host (through ARP). + * + * @param netif the netif under DHCP control + */ +static err_t +dhcp_decline(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result = ERR_OK; + u16_t msecs; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline()\n")); + dhcp_set_state(dhcp, DHCP_BACKING_OFF); + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_DECLINE); + if (result == ERR_OK) { + dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); + dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr))); + + dhcp_option_trailer(dhcp); + /* resize pbuf to reflect true size of options */ + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + /* per section 4.4.4, broadcast DECLINE messages */ + udp_sendto_if_src(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP_ADDR_ANY); + dhcp_delete_msg(dhcp); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_decline: BACKING OFF\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("dhcp_decline: could not allocate DHCP request\n")); + } + dhcp->tries++; + msecs = 10*1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} +#endif /* DHCP_DOES_ARP_CHECK */ + + +/** + * Start the DHCP process, discover a DHCP server. + * + * @param netif the netif under DHCP control + */ +static err_t +dhcp_discover(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result = ERR_OK; + u16_t msecs; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover()\n")); + ip_addr_set_any(&dhcp->offered_ip_addr); + dhcp_set_state(dhcp, DHCP_SELECTING); + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_DISCOVER); + if (result == ERR_OK) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: making request\n")); + + dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); + + dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 4/*num options*/); + dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK); + dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER); + dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST); + dhcp_option_byte(dhcp, DHCP_OPTION_DNS_SERVER); + + dhcp_option_trailer(dhcp); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: realloc()ing\n")); + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, DHCP_SERVER_PORT)\n")); + udp_sendto_if_src(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP_ADDR_ANY); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: deleting()ing\n")); + dhcp_delete_msg(dhcp); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover: SELECTING\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_discover: could not allocate DHCP request\n")); + } + dhcp->tries++; +#if LWIP_DHCP_AUTOIP_COOP + if(dhcp->tries >= LWIP_DHCP_AUTOIP_COOP_TRIES && dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_OFF) { + dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_ON; + autoip_start(netif); + } +#endif /* LWIP_DHCP_AUTOIP_COOP */ + msecs = (dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} + + +/** + * Bind the interface to the offered IP address. + * + * @param netif network interface to bind to the offered address + */ +static void +dhcp_bind(struct netif *netif) +{ + u32_t timeout; + struct dhcp *dhcp; + ip_addr_t sn_mask, gw_addr; + LWIP_ERROR("dhcp_bind: netif != NULL", (netif != NULL), return;); + dhcp = netif->dhcp; + LWIP_ERROR("dhcp_bind: dhcp != NULL", (dhcp != NULL), return;); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); + + /* temporary DHCP lease? */ + if (dhcp->offered_t1_renew != 0xffffffffUL) { + /* set renewal period timer */ + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t1 renewal timer %"U32_F" secs\n", dhcp->offered_t1_renew)); + timeout = (dhcp->offered_t1_renew + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS; + if(timeout > 0xffff) { + timeout = 0xffff; + } + dhcp->t1_timeout = (u16_t)timeout; + if (dhcp->t1_timeout == 0) { + dhcp->t1_timeout = 1; + } + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t1_renew*1000)); + } + /* set renewal period timer */ + if (dhcp->offered_t2_rebind != 0xffffffffUL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t2 rebind timer %"U32_F" secs\n", dhcp->offered_t2_rebind)); + timeout = (dhcp->offered_t2_rebind + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS; + if(timeout > 0xffff) { + timeout = 0xffff; + } + dhcp->t2_timeout = (u16_t)timeout; + if (dhcp->t2_timeout == 0) { + dhcp->t2_timeout = 1; + } + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t2_rebind*1000)); + } + + /* If we have sub 1 minute lease, t2 and t1 will kick in at the same time. */ + if ((dhcp->t1_timeout >= dhcp->t2_timeout) && (dhcp->t2_timeout > 0)) { + dhcp->t1_timeout = 0; + } + + if (dhcp->subnet_mask_given) { + /* copy offered network mask */ + ip_addr_copy(sn_mask, dhcp->offered_sn_mask); + } else { + /* subnet mask not given, choose a safe subnet mask given the network class */ + u8_t first_octet = ip4_addr1(&dhcp->offered_ip_addr); + if (first_octet <= 127) { + ip4_addr_set_u32(&sn_mask, PP_HTONL(0xff000000UL)); + } else if (first_octet >= 192) { + ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffffff00UL)); + } else { + ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffff0000UL)); + } + } + + ip_addr_copy(gw_addr, dhcp->offered_gw_addr); + /* gateway address not given? */ + if (ip_addr_isany(&gw_addr)) { + /* copy network address */ + ip_addr_get_network(&gw_addr, &dhcp->offered_ip_addr, &sn_mask); + /* use first host address on network as gateway */ + ip4_addr_set_u32(&gw_addr, ip4_addr_get_u32(&gw_addr) | PP_HTONL(0x00000001UL)); + } + +#if LWIP_DHCP_AUTOIP_COOP + if(dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) { + autoip_stop(netif); + dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF; + } +#endif /* LWIP_DHCP_AUTOIP_COOP */ + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): IP: 0x%08"X32_F"\n", + ip4_addr_get_u32(&dhcp->offered_ip_addr))); + netif_set_ipaddr(netif, &dhcp->offered_ip_addr); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): SN: 0x%08"X32_F"\n", + ip4_addr_get_u32(&sn_mask))); + netif_set_netmask(netif, &sn_mask); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): GW: 0x%08"X32_F"\n", + ip4_addr_get_u32(&gw_addr))); + netif_set_gw(netif, &gw_addr); + /* bring the interface up */ + netif_set_up(netif); + /* netif is now bound to DHCP leased address */ + dhcp_set_state(dhcp, DHCP_BOUND); +} + +/** + * Renew an existing DHCP lease at the involved DHCP server. + * + * @param netif network interface which must renew its lease + */ +err_t +dhcp_renew(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result; + u16_t msecs; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_renew()\n")); + dhcp_set_state(dhcp, DHCP_RENEWING); + + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); + if (result == ERR_OK) { + dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); + +#if 0 + dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); + dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr)); +#endif + +#if 0 + dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4); + dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr)); +#endif + +#if LWIP_NETIF_HOSTNAME + dhcp_option_hostname(dhcp, netif); +#endif /* LWIP_NETIF_HOSTNAME */ + + /* append DHCP message trailer */ + dhcp_option_trailer(dhcp); + + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + udp_sendto_if(dhcp->pcb, dhcp->p_out, &dhcp->server_ip_addr, DHCP_SERVER_PORT, netif); + dhcp_delete_msg(dhcp); + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew: RENEWING\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_renew: could not allocate DHCP request\n")); + } + dhcp->tries++; + /* back-off on retries, but to a maximum of 20 seconds */ + msecs = dhcp->tries < 10 ? dhcp->tries * 2000 : 20 * 1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} + +/** + * Rebind with a DHCP server for an existing DHCP lease. + * + * @param netif network interface which must rebind with a DHCP server + */ +static err_t +dhcp_rebind(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result; + u16_t msecs; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind()\n")); + dhcp_set_state(dhcp, DHCP_REBINDING); + + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); + if (result == ERR_OK) { + dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); + +#if LWIP_NETIF_HOSTNAME + dhcp_option_hostname(dhcp, netif); +#endif /* LWIP_NETIF_HOSTNAME */ + +#if 0 + dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); + dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr)); + + dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4); + dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr)); +#endif + + dhcp_option_trailer(dhcp); + + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + /* broadcast to server */ + udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); + dhcp_delete_msg(dhcp); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind: REBINDING\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_rebind: could not allocate DHCP request\n")); + } + dhcp->tries++; + msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} + +/** + * Enter REBOOTING state to verify an existing lease + * + * @param netif network interface which must reboot + */ +static err_t +dhcp_reboot(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result; + u16_t msecs; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot()\n")); + dhcp_set_state(dhcp, DHCP_REBOOTING); + + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); + if (result == ERR_OK) { + dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); + dhcp_option_short(dhcp, 576); + + dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); + dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr))); + + dhcp_option_trailer(dhcp); + + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + /* broadcast to server */ + udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); + dhcp_delete_msg(dhcp); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot: REBOOTING\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_reboot: could not allocate DHCP request\n")); + } + dhcp->tries++; + msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot(): set request timeout %"U16_F" msecs\n", msecs)); + return result; +} + + +/** + * Release a DHCP lease. + * + * @param netif network interface which must release its lease + */ +err_t +dhcp_release(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result; + u16_t msecs; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_release()\n")); + if (dhcp == NULL) { + return ERR_ARG; + } + + /* idle DHCP client */ + dhcp_set_state(dhcp, DHCP_OFF); + /* clean old DHCP offer */ + ip_addr_set_zero(&dhcp->server_ip_addr); + ip_addr_set_zero(&dhcp->offered_ip_addr); + ip_addr_set_zero(&dhcp->offered_sn_mask); + ip_addr_set_zero(&dhcp->offered_gw_addr); +#if LWIP_DHCP_BOOTP_FILE + ip_addr_set_zero(&dhcp->offered_si_addr); +#endif /* LWIP_DHCP_BOOTP_FILE */ + dhcp->offered_t0_lease = dhcp->offered_t1_renew = dhcp->offered_t2_rebind = 0; + + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif, dhcp, DHCP_RELEASE); + if (result == ERR_OK) { + dhcp_option_trailer(dhcp); + + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + udp_sendto_if(dhcp->pcb, dhcp->p_out, &dhcp->server_ip_addr, DHCP_SERVER_PORT, netif); + dhcp_delete_msg(dhcp); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release: RELEASED, DHCP_OFF\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_release: could not allocate DHCP request\n")); + } + dhcp->tries++; + msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release(): set request timeout %"U16_F" msecs\n", msecs)); + /* bring the interface down */ + netif_set_down(netif); + /* remove IP address from interface */ + netif_set_ipaddr(netif, IP_ADDR_ANY); + netif_set_gw(netif, IP_ADDR_ANY); + netif_set_netmask(netif, IP_ADDR_ANY); + + /* TODO: netif_down(netif); */ + return result; +} + +/** + * Release a DHCP lease. + * + * @param netif network interface which must release its lease + */ +err_t +dhcp_release_unicast(struct netif *netif) +{ + struct dhcp *dhcp = netif->dhcp; + err_t result; + u16_t msecs; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_release()\n")); + + /* idle DHCP client */ + dhcp_set_state(dhcp, DHCP_RELEASING); + /* clean old DHCP offer *//* + dhcp->server_ip_addr.addr = 0; + dhcp->offered_ip_addr.addr = dhcp->offered_sn_mask.addr = 0; + dhcp->offered_gw_addr.addr = dhcp->offered_bc_addr.addr = 0; + dhcp->offered_t0_lease = dhcp->offered_t1_renew = dhcp->offered_t2_rebind = 0; + dhcp->dns_count = 0;*/ + + /* create and initialize the DHCP message header */ + result = dhcp_create_msg(netif,netif->dhcp,DHCP_REQUEST); //Evan modified + if (result == ERR_OK) { + dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN); + dhcp_option_byte(dhcp, DHCP_RELEASE); + + dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4); + dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr)); + + dhcp_option_trailer(dhcp); + + pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); + + udp_sendto_if(dhcp->pcb, dhcp->p_out, &dhcp->server_ip_addr, DHCP_SERVER_PORT, netif); + dhcp_delete_msg(netif->dhcp);//Evan modified + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release: RELEASED, DHCP_OFF\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_release: could not allocate DHCP request\n")); + } + dhcp->tries++; + msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000; + dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release(): set request timeout %"U16_F" msecs\n", msecs)); + /* bring the interface down */ + netif_set_down(netif); + /* remove IP address from interface */ + netif_set_ipaddr(netif, IP_ADDR_ANY); + netif_set_gw(netif, IP_ADDR_ANY); + netif_set_netmask(netif, IP_ADDR_ANY); + + /* TODO: netif_down(netif); */ + return result; +} + +/** + * Remove the DHCP client from the interface. + * + * @param netif The network interface to stop DHCP on + */ +void +dhcp_stop(struct netif *netif) +{ + struct dhcp *dhcp; + LWIP_ERROR("dhcp_stop: netif != NULL", (netif != NULL), return;); + dhcp = netif->dhcp; + /* Remove the flag that says this netif is handled by DHCP. */ + netif->flags &= ~NETIF_FLAG_DHCP; + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_stop()\n")); + /* netif is DHCP configured? */ + if (dhcp != NULL) { +#if LWIP_DHCP_AUTOIP_COOP + if(dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) { + autoip_stop(netif); + dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF; + } +#endif /* LWIP_DHCP_AUTOIP_COOP */ + + if (dhcp->pcb != NULL) { + udp_remove(dhcp->pcb); + dhcp->pcb = NULL; + } + LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL); + dhcp_set_state(dhcp, DHCP_OFF); + } +} + +/* + * Set the DHCP state of a DHCP client. + * + * If the state changed, reset the number of tries. + */ +static void +dhcp_set_state(struct dhcp *dhcp, u8_t new_state) +{ + if (new_state != dhcp->state) { + dhcp->state = new_state; + dhcp->tries = 0; + dhcp->request_timeout = 0; + } +} + +/* + * Concatenate an option type and length field to the outgoing + * DHCP message. + * + */ +static void +dhcp_option(struct dhcp *dhcp, u8_t option_type, u8_t option_len) +{ + LWIP_ASSERT("dhcp_option: dhcp->options_out_len + 2 + option_len <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 2U + option_len <= DHCP_OPTIONS_LEN); + dhcp->msg_out->options[dhcp->options_out_len++] = option_type; + dhcp->msg_out->options[dhcp->options_out_len++] = option_len; +} +/* + * Concatenate a single byte to the outgoing DHCP message. + * + */ +static void +dhcp_option_byte(struct dhcp *dhcp, u8_t value) +{ + LWIP_ASSERT("dhcp_option_byte: dhcp->options_out_len < DHCP_OPTIONS_LEN", dhcp->options_out_len < DHCP_OPTIONS_LEN); + dhcp->msg_out->options[dhcp->options_out_len++] = value; +} + +static void +dhcp_option_short(struct dhcp *dhcp, u16_t value) +{ + LWIP_ASSERT("dhcp_option_short: dhcp->options_out_len + 2 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 2U <= DHCP_OPTIONS_LEN); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0xff00U) >> 8); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t) (value & 0x00ffU); +} + +static void +dhcp_option_long(struct dhcp *dhcp, u32_t value) +{ + LWIP_ASSERT("dhcp_option_long: dhcp->options_out_len + 4 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 4U <= DHCP_OPTIONS_LEN); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0xff000000UL) >> 24); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x00ff0000UL) >> 16); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x0000ff00UL) >> 8); + dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x000000ffUL)); +} + +#if LWIP_NETIF_HOSTNAME +static void +dhcp_option_hostname(struct dhcp *dhcp, struct netif *netif) +{ + if (netif->hostname != NULL) { + size_t namelen = strlen(netif->hostname); + if (namelen > 0) { + u8_t len; + const char *p = netif->hostname; + /* Shrink len to available bytes (need 2 bytes for OPTION_HOSTNAME + and 1 byte for trailer) */ + size_t available = DHCP_OPTIONS_LEN - dhcp->options_out_len - 3; + LWIP_ASSERT("DHCP: hostname is too long!", namelen <= available); + len = LWIP_MIN(namelen, available); + dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, len); + while (len--) { + dhcp_option_byte(dhcp, *p++); + } + } + } +} +#endif /* LWIP_NETIF_HOSTNAME */ + +/** + * Extract the DHCP message and the DHCP options. + * + * Extract the DHCP message and the DHCP options, each into a contiguous + * piece of memory. As a DHCP message is variable sized by its options, + * and also allows overriding some fields for options, the easy approach + * is to first unfold the options into a contiguous piece of memory, and + * use that further on. + * + */ +static err_t +dhcp_parse_reply(struct dhcp *dhcp, struct pbuf *p) +{ + u8_t *options; + u16_t offset; + u16_t offset_max; + u16_t options_idx; + u16_t options_idx_max; + struct pbuf *q; + int parse_file_as_options = 0; + int parse_sname_as_options = 0; + + /* clear received options */ + dhcp_clear_all_options(dhcp); + /* check that beginning of dhcp_msg (up to and including chaddr) is in first pbuf */ + if (p->len < DHCP_SNAME_OFS) { + return ERR_BUF; + } + dhcp->msg_in = (struct dhcp_msg *)p->payload; +#if LWIP_DHCP_BOOTP_FILE + /* clear boot file name */ + dhcp->boot_file_name[0] = 0; +#endif /* LWIP_DHCP_BOOTP_FILE */ + + /* parse options */ + + /* start with options field */ + options_idx = DHCP_OPTIONS_OFS; + /* parse options to the end of the received packet */ + options_idx_max = p->tot_len; +again: + q = p; + while((q != NULL) && (options_idx >= q->len)) { + options_idx -= q->len; + options_idx_max -= q->len; + q = q->next; + } + if (q == NULL) { + return ERR_BUF; + } + offset = options_idx; + offset_max = options_idx_max; + options = (u8_t*)q->payload; + /* at least 1 byte to read and no end marker, then at least 3 bytes to read? */ + while((q != NULL) && (options[offset] != DHCP_OPTION_END) && (offset < offset_max)) { + u8_t op = options[offset]; + u8_t len; + u8_t decode_len = 0; + int decode_idx = -1; + u16_t val_offset = offset + 2; + /* len byte might be in the next pbuf */ + if (offset + 1 < q->len) { + len = options[offset + 1]; + } else { + len = (q->next != NULL ? ((u8_t*)q->next->payload)[0] : 0); + } + /* LWIP_DEBUGF(DHCP_DEBUG, ("msg_offset=%"U16_F", q->len=%"U16_F, msg_offset, q->len)); */ + decode_len = len; + switch(op) { + /* case(DHCP_OPTION_END): handled above */ + case(DHCP_OPTION_PAD): + /* special option: no len encoded */ + decode_len = len = 0; + /* will be increased below */ + offset--; + break; + case(DHCP_OPTION_SUBNET_MASK): + LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_SUBNET_MASK; + break; + case(DHCP_OPTION_ROUTER): + decode_len = 4; /* only copy the first given router */ + LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_ROUTER; + break; + case(DHCP_OPTION_DNS_SERVER): + /* special case: there might be more than one server */ + LWIP_ERROR("len % 4 == 0", len % 4 == 0, return ERR_VAL;); + /* limit number of DNS servers */ + decode_len = LWIP_MIN(len, 4 * DNS_MAX_SERVERS); + LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_DNS_SERVER; + break; + case(DHCP_OPTION_LEASE_TIME): + LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_LEASE_TIME; + break; + case(DHCP_OPTION_OVERLOAD): + LWIP_ERROR("len == 1", len == 1, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_OVERLOAD; + break; + case(DHCP_OPTION_MESSAGE_TYPE): + LWIP_ERROR("len == 1", len == 1, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_MSG_TYPE; + break; + case(DHCP_OPTION_SERVER_ID): + LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_SERVER_ID; + break; + case(DHCP_OPTION_T1): + LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_T1; + break; + case(DHCP_OPTION_T2): + LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); + decode_idx = DHCP_OPTION_IDX_T2; + break; + default: + decode_len = 0; + LWIP_DEBUGF(DHCP_DEBUG, ("skipping option %"U16_F" in options\n", op)); + break; + } + offset += len + 2; + if (decode_len > 0) { + u32_t value = 0; + u16_t copy_len; +decode_next: + LWIP_ASSERT("check decode_idx", decode_idx >= 0 && decode_idx < DHCP_OPTION_IDX_MAX); + if (!dhcp_option_given(dhcp, decode_idx)) { + copy_len = LWIP_MIN(decode_len, 4); + pbuf_copy_partial(q, &value, copy_len, val_offset); + if (decode_len > 4) { + /* decode more than one u32_t */ + LWIP_ERROR("decode_len % 4 == 0", decode_len % 4 == 0, return ERR_VAL;); + dhcp_got_option(dhcp, decode_idx); + dhcp_set_option_value(dhcp, decode_idx, htonl(value)); + decode_len -= 4; + val_offset += 4; + decode_idx++; + goto decode_next; + } else if (decode_len == 4) { + value = ntohl(value); + } else { + LWIP_ERROR("invalid decode_len", decode_len == 1, return ERR_VAL;); + value = ((u8_t*)&value)[0]; + } + dhcp_got_option(dhcp, decode_idx); + dhcp_set_option_value(dhcp, decode_idx, value); + } + } + if (offset >= q->len) { + offset -= q->len; + offset_max -= q->len; + if ((offset < offset_max) && offset_max) { + q = q->next; + LWIP_ASSERT("next pbuf was null", q); + options = (u8_t*)q->payload; + } else { + /* We've run out of bytes, probably no end marker. Don't proceed. */ + break; + } + } + } + /* is this an overloaded message? */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_OVERLOAD)) { + u32_t overload = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_OVERLOAD); + dhcp_clear_option(dhcp, DHCP_OPTION_IDX_OVERLOAD); + if (overload == DHCP_OVERLOAD_FILE) { + parse_file_as_options = 1; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded file field\n")); + } else if (overload == DHCP_OVERLOAD_SNAME) { + parse_sname_as_options = 1; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname field\n")); + } else if (overload == DHCP_OVERLOAD_SNAME_FILE) { + parse_sname_as_options = 1; + parse_file_as_options = 1; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname and file field\n")); + } else { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("invalid overload option: %d\n", (int)overload)); + } +#if LWIP_DHCP_BOOTP_FILE + if (!parse_file_as_options) { + /* only do this for ACK messages */ + if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE) && + (dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_MSG_TYPE) == DHCP_ACK)) + /* copy bootp file name, don't care for sname (server hostname) */ + pbuf_copy_partial(p, dhcp->boot_file_name, DHCP_FILE_LEN-1, DHCP_FILE_OFS); + /* make sure the string is really NULL-terminated */ + dhcp->boot_file_name[DHCP_FILE_LEN-1] = 0; + } +#endif /* LWIP_DHCP_BOOTP_FILE */ + } + if (parse_file_as_options) { + /* if both are overloaded, parse file first and then sname (RFC 2131 ch. 4.1) */ + parse_file_as_options = 0; + options_idx = DHCP_FILE_OFS; + options_idx_max = DHCP_FILE_OFS + DHCP_FILE_LEN; + goto again; + } else if (parse_sname_as_options) { + parse_sname_as_options = 0; + options_idx = DHCP_SNAME_OFS; + options_idx_max = DHCP_SNAME_OFS + DHCP_SNAME_LEN; + goto again; + } + return ERR_OK; +} + +/** + * If an incoming DHCP message is in response to us, then trigger the state machine + */ +static void +dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port) +{ + struct netif *netif = (struct netif *)arg; + struct dhcp *dhcp = netif->dhcp; + struct dhcp_msg *reply_msg = (struct dhcp_msg *)p->payload; + u8_t msg_type; + u8_t i; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_recv(pbuf = %p) from DHCP server %"U16_F".%"U16_F".%"U16_F".%"U16_F" port %"U16_F"\n", (void*)p, + ip4_addr1_16(addr), ip4_addr2_16(addr), ip4_addr3_16(addr), ip4_addr4_16(addr), port)); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->len = %"U16_F"\n", p->len)); + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->tot_len = %"U16_F"\n", p->tot_len)); + /* prevent warnings about unused arguments */ + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(addr); + LWIP_UNUSED_ARG(port); + + LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL); + + if (p->len < DHCP_MIN_REPLY_LEN) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP reply message or pbuf too short\n")); + goto free_pbuf_and_return; + } + + if (reply_msg->op != DHCP_BOOTREPLY) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("not a DHCP reply message, but type %"U16_F"\n", (u16_t)reply_msg->op)); + goto free_pbuf_and_return; + } + /* iterate through hardware address and match against DHCP message */ + for (i = 0; i < netif->hwaddr_len && i < NETIF_MAX_HWADDR_LEN && i < DHCP_CHADDR_LEN; i++) { + if (netif->hwaddr[i] != reply_msg->chaddr[i]) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("netif->hwaddr[%"U16_F"]==%02"X16_F" != reply_msg->chaddr[%"U16_F"]==%02"X16_F"\n", + (u16_t)i, (u16_t)netif->hwaddr[i], (u16_t)i, (u16_t)reply_msg->chaddr[i])); + goto free_pbuf_and_return; + } + } + /* match transaction ID against what we expected */ + if (ntohl(reply_msg->xid) != dhcp->xid) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("transaction id mismatch reply_msg->xid(%"X32_F")!=dhcp->xid(%"X32_F")\n",ntohl(reply_msg->xid),dhcp->xid)); + goto free_pbuf_and_return; + } + /* option fields could be unfold? */ + if (dhcp_parse_reply(dhcp, p) != ERR_OK) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("problem unfolding DHCP message - too short on memory?\n")); + goto free_pbuf_and_return; + } + + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("searching DHCP_OPTION_MESSAGE_TYPE\n")); + /* obtain pointer to DHCP message type */ + if (!dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP_OPTION_MESSAGE_TYPE option not found\n")); + goto free_pbuf_and_return; + } + + /* read DHCP message type */ + msg_type = (u8_t)dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_MSG_TYPE); + /* message type is DHCP ACK? */ + if (msg_type == DHCP_ACK) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_ACK received\n")); + /* in requesting state? */ + if (dhcp->state == DHCP_REQUESTING) { + dhcp_handle_ack(netif); +#if DHCP_DOES_ARP_CHECK + /* check if the acknowledged lease address is already in use */ + dhcp_check(netif); +#else + /* bind interface to the acknowledged lease address */ + dhcp_bind(netif); +#endif + } + /* already bound to the given lease address? */ + else if ((dhcp->state == DHCP_REBOOTING) || (dhcp->state == DHCP_REBINDING) || (dhcp->state == DHCP_RENEWING)) { + dhcp_bind(netif); + } + } + /* received a DHCP_NAK in appropriate state? */ + else if ((msg_type == DHCP_NAK) && + ((dhcp->state == DHCP_REBOOTING) || (dhcp->state == DHCP_REQUESTING) || + (dhcp->state == DHCP_REBINDING) || (dhcp->state == DHCP_RENEWING ))) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_NAK received\n")); + dhcp_handle_nak(netif); + } + /* received a DHCP_OFFER in DHCP_SELECTING state? */ + else if ((msg_type == DHCP_OFFER) && (dhcp->state == DHCP_SELECTING)) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_OFFER received in DHCP_SELECTING state\n")); + dhcp->request_timeout = 0; + /* remember offered lease */ + dhcp_handle_offer(netif); + } +free_pbuf_and_return: + dhcp->msg_in = NULL; + pbuf_free(p); +} + +/** + * Create a DHCP request, fill in common headers + * + * @param netif the netif under DHCP control + * @param dhcp dhcp control struct + * @param message_type message type of the request + */ +static err_t +dhcp_create_msg(struct netif *netif, struct dhcp *dhcp, u8_t message_type) +{ + u16_t i; +#ifndef DHCP_GLOBAL_XID + /** default global transaction identifier starting value (easy to match + * with a packet analyser). We simply increment for each new request. + * Predefine DHCP_GLOBAL_XID to a better value or a function call to generate one + * at runtime, any supporting function prototypes can be defined in DHCP_GLOBAL_XID_HEADER */ +#if DHCP_CREATE_RAND_XID && defined(LWIP_RAND) + static u32_t xid; +#else /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */ + static u32_t xid = 0xABCD0000; +#endif /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */ +#else + if (!xid_initialised) { + xid = DHCP_GLOBAL_XID; + xid_initialised = !xid_initialised; + } +#endif + LWIP_ERROR("dhcp_create_msg: netif != NULL", (netif != NULL), return ERR_ARG;); + LWIP_ERROR("dhcp_create_msg: dhcp != NULL", (dhcp != NULL), return ERR_VAL;); + LWIP_ASSERT("dhcp_create_msg: dhcp->p_out == NULL", dhcp->p_out == NULL); + LWIP_ASSERT("dhcp_create_msg: dhcp->msg_out == NULL", dhcp->msg_out == NULL); + dhcp->p_out = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcp_msg), PBUF_RAM); + if (dhcp->p_out == NULL) { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("dhcp_create_msg(): could not allocate pbuf\n")); + return ERR_MEM; + } + LWIP_ASSERT("dhcp_create_msg: check that first pbuf can hold struct dhcp_msg", + (dhcp->p_out->len >= sizeof(struct dhcp_msg))); + + /* DHCP_REQUEST should reuse 'xid' from DHCPOFFER */ + if (message_type != DHCP_REQUEST) { + /* reuse transaction identifier in retransmissions */ + if (dhcp->tries == 0) { +#if DHCP_CREATE_RAND_XID && defined(LWIP_RAND) + xid = LWIP_RAND(); +#else /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */ + xid++; +#endif /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */ + } + dhcp->xid = xid; + } + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, + ("transaction id xid(%"X32_F")\n", xid)); + + dhcp->msg_out = (struct dhcp_msg *)dhcp->p_out->payload; + + dhcp->msg_out->op = DHCP_BOOTREQUEST; + /* TODO: make link layer independent */ + dhcp->msg_out->htype = DHCP_HTYPE_ETH; + dhcp->msg_out->hlen = netif->hwaddr_len; + dhcp->msg_out->hops = 0; + dhcp->msg_out->xid = htonl(dhcp->xid); + dhcp->msg_out->secs = 0; + /* we don't need the broadcast flag since we can receive unicast traffic + before being fully configured! */ + dhcp->msg_out->flags = 0; + ip_addr_set_zero(&dhcp->msg_out->ciaddr); + /* set ciaddr to netif->ip_addr based on message_type and state */ + if ((message_type == DHCP_INFORM) || (message_type == DHCP_DECLINE) || + ((message_type == DHCP_REQUEST) && /* DHCP_BOUND not used for sending! */ + ((dhcp->state==DHCP_RENEWING) || dhcp->state==DHCP_REBINDING || dhcp->state == DHCP_RELEASING))) { + ip_addr_copy(dhcp->msg_out->ciaddr, netif->ip_addr); + } + ip_addr_set_zero(&dhcp->msg_out->yiaddr); + ip_addr_set_zero(&dhcp->msg_out->siaddr); + ip_addr_set_zero(&dhcp->msg_out->giaddr); + for (i = 0; i < DHCP_CHADDR_LEN; i++) { + /* copy netif hardware address, pad with zeroes */ + dhcp->msg_out->chaddr[i] = (i < netif->hwaddr_len && i < NETIF_MAX_HWADDR_LEN) ? netif->hwaddr[i] : 0/* pad byte*/; + } + for (i = 0; i < DHCP_SNAME_LEN; i++) { + dhcp->msg_out->sname[i] = 0; + } + for (i = 0; i < DHCP_FILE_LEN; i++) { + dhcp->msg_out->file[i] = 0; + } + dhcp->msg_out->cookie = PP_HTONL(DHCP_MAGIC_COOKIE); + dhcp->options_out_len = 0; + /* fill options field with an incrementing array (for debugging purposes) */ + for (i = 0; i < DHCP_OPTIONS_LEN; i++) { + dhcp->msg_out->options[i] = (u8_t)i; /* for debugging only, no matter if truncated */ + } + /* Add option MESSAGE_TYPE */ + dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN); + dhcp_option_byte(dhcp, message_type); + return ERR_OK; +} + +/** + * Free previously allocated memory used to send a DHCP request. + * + * @param dhcp the dhcp struct to free the request from + */ +static void +dhcp_delete_msg(struct dhcp *dhcp) +{ + LWIP_ERROR("dhcp_delete_msg: dhcp != NULL", (dhcp != NULL), return;); + LWIP_ASSERT("dhcp_delete_msg: dhcp->p_out != NULL", dhcp->p_out != NULL); + LWIP_ASSERT("dhcp_delete_msg: dhcp->msg_out != NULL", dhcp->msg_out != NULL); + if (dhcp->p_out != NULL) { + pbuf_free(dhcp->p_out); + } + dhcp->p_out = NULL; + dhcp->msg_out = NULL; +} + +/** + * Add a DHCP message trailer + * + * Adds the END option to the DHCP message, and if + * necessary, up to three padding bytes. + * + * @param dhcp DHCP state structure + */ +static void +dhcp_option_trailer(struct dhcp *dhcp) +{ + LWIP_ERROR("dhcp_option_trailer: dhcp != NULL", (dhcp != NULL), return;); + LWIP_ASSERT("dhcp_option_trailer: dhcp->msg_out != NULL\n", dhcp->msg_out != NULL); + LWIP_ASSERT("dhcp_option_trailer: dhcp->options_out_len < DHCP_OPTIONS_LEN\n", dhcp->options_out_len < DHCP_OPTIONS_LEN); + dhcp->msg_out->options[dhcp->options_out_len++] = DHCP_OPTION_END; + /* packet is too small, or not 4 byte aligned? */ + while (((dhcp->options_out_len < DHCP_MIN_OPTIONS_LEN) || (dhcp->options_out_len & 3)) && + (dhcp->options_out_len < DHCP_OPTIONS_LEN)) { + /* add a fill/padding byte */ + dhcp->msg_out->options[dhcp->options_out_len++] = 0; + } +} + +#endif /* LWIP_DHCP */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/core/dns.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/dns.c new file mode 100644 index 0000000..45b416b --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/dns.c @@ -0,0 +1,1302 @@ +/** + * @file + * DNS - host name to IP address resolver. + * + */ + +/** + + * This file implements a DNS host name to IP address resolver. + + * Port to lwIP from uIP + * by Jim Pettinato April 2007 + + * security fixes and more by Simon Goldschmidt + + * uIP version Copyright (c) 2002-2003, Adam Dunkels. + * 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. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * + * DNS.C + * + * The lwIP DNS resolver functions are used to lookup a host name and + * map it to a numerical IP address. It maintains a list of resolved + * hostnames that can be queried with the dns_lookup() function. + * New hostnames can be resolved using the dns_query() function. + * + * The lwIP version of the resolver also adds a non-blocking version of + * gethostbyname() that will work with a raw API application. This function + * checks for an IP address string first and converts it if it is valid. + * gethostbyname() then does a dns_lookup() to see if the name is + * already in the table. If so, the IP is returned. If not, a query is + * issued and the function returns with a ERR_INPROGRESS status. The app + * using the dns client must then go into a waiting state. + * + * Once a hostname has been resolved (or found to be non-existent), + * the resolver code calls a specified callback function (which + * must be implemented by the module that uses the resolver). + */ + +/*----------------------------------------------------------------------------- + * RFC 1035 - Domain names - implementation and specification + * RFC 2181 - Clarifications to the DNS Specification + *----------------------------------------------------------------------------*/ + +/** @todo: define good default values (rfc compliance) */ +/** @todo: improve answer parsing, more checkings... */ +/** @todo: check RFC1035 - 7.3. Processing responses */ + +/*----------------------------------------------------------------------------- + * Includes + *----------------------------------------------------------------------------*/ + +#include "lwip/opt.h" + +#if LWIP_DNS /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/udp.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/dns.h" + +#include + +/* A list of DNS security features follows */ +#define LWIP_DNS_SECURE_RAND_XID 1 +#define LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING 2 +#define LWIP_DNS_SECURE_RAND_SRC_PORT 4 +/** Use all DNS security features by default. + * This is overridable but should only be needed by very small targets + * or when using against non standard DNS servers. */ +#ifndef LWIP_DNS_SECURE +#define LWIP_DNS_SECURE (LWIP_DNS_SECURE_RAND_XID | LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING | LWIP_DNS_SECURE_RAND_SRC_PORT) +#endif + +/** Random generator function to create random TXIDs and source ports for queries */ +#ifndef DNS_RAND_TXID +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_XID) != 0) +#define DNS_RAND_TXID LWIP_RAND +#else +static u16_t dns_txid; +#define DNS_RAND_TXID() (++dns_txid) +#endif +#endif + +/** Limits the source port to be >= 1024 by default */ +#ifndef DNS_PORT_ALLOWED +#define DNS_PORT_ALLOWED(port) ((port) >= 1024) +#endif + +/** DNS server IP address */ +#ifndef DNS_SERVER_ADDRESS +#define DNS_SERVER_ADDRESS(ipaddr) (ip4_addr_set_u32(ipaddr, ipaddr_addr("208.67.222.222"))) /* resolver1.opendns.com */ +#endif + +/** DNS server port address */ +#ifndef DNS_SERVER_PORT +#define DNS_SERVER_PORT 53 +#endif + +/** DNS maximum number of retries when asking for a name, before "timeout". */ +#ifndef DNS_MAX_RETRIES +#define DNS_MAX_RETRIES 4 +#endif + +/** DNS resource record max. TTL (one week as default) */ +#ifndef DNS_MAX_TTL +#define DNS_MAX_TTL 604800 +#endif + +/* The number of parallel requests (i.e. calls to dns_gethostbyname + * that cannot be answered from the DNS table. + * This is set to the table size by default. + */ +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0) +#ifndef DNS_MAX_REQUESTS +#define DNS_MAX_REQUESTS DNS_TABLE_SIZE +#endif +#else +/* In this configuration, both arrays have to have the same size and are used + * like one entry (used/free) */ +#define DNS_MAX_REQUESTS DNS_TABLE_SIZE +#endif + +/* The number of UDP source ports used in parallel */ +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) +#ifndef DNS_MAX_SOURCE_PORTS +#define DNS_MAX_SOURCE_PORTS DNS_MAX_REQUESTS +#endif +#else +#ifdef DNS_MAX_SOURCE_PORTS +#undef DNS_MAX_SOURCE_PORTS +#endif +#define DNS_MAX_SOURCE_PORTS 1 +#endif + + +/* DNS protocol flags */ +#define DNS_FLAG1_RESPONSE 0x80 +#define DNS_FLAG1_OPCODE_STATUS 0x10 +#define DNS_FLAG1_OPCODE_INVERSE 0x08 +#define DNS_FLAG1_OPCODE_STANDARD 0x00 +#define DNS_FLAG1_AUTHORATIVE 0x04 +#define DNS_FLAG1_TRUNC 0x02 +#define DNS_FLAG1_RD 0x01 +#define DNS_FLAG2_RA 0x80 +#define DNS_FLAG2_ERR_MASK 0x0f +#define DNS_FLAG2_ERR_NONE 0x00 +#define DNS_FLAG2_ERR_NAME 0x03 + +/* DNS protocol states */ +#define DNS_STATE_UNUSED 0 +#define DNS_STATE_NEW 1 +#define DNS_STATE_ASKING 2 +#define DNS_STATE_DONE 3 + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** DNS message header */ +struct dns_hdr { + PACK_STRUCT_FIELD(u16_t id); + PACK_STRUCT_FLD_8(u8_t flags1); + PACK_STRUCT_FLD_8(u8_t flags2); + PACK_STRUCT_FIELD(u16_t numquestions); + PACK_STRUCT_FIELD(u16_t numanswers); + PACK_STRUCT_FIELD(u16_t numauthrr); + PACK_STRUCT_FIELD(u16_t numextrarr); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif +#define SIZEOF_DNS_HDR 12 + +/** DNS query message structure. + No packing needed: only used locally on the stack. */ +struct dns_query { + /* DNS query record starts with either a domain name or a pointer + to a name already present somewhere in the packet. */ + u16_t type; + u16_t cls; +}; +#define SIZEOF_DNS_QUERY 4 + +/** DNS answer message structure. + No packing needed: only used locally on the stack. */ +struct dns_answer { + /* DNS answer record starts with either a domain name or a pointer + to a name already present somewhere in the packet. */ + u16_t type; + u16_t cls; + u32_t ttl; + u16_t len; +}; +#define SIZEOF_DNS_ANSWER 10 +/* maximum allowed size for the struct due to non-packed */ +#define SIZEOF_DNS_ANSWER_ASSERT 12 + +/** DNS table entry */ +struct dns_table_entry { + u32_t ttl; + ip_addr_t ipaddr; + u16_t txid; + u8_t state; + u8_t server_idx; + u8_t tmr; + u8_t retries; + u8_t seqno; +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) + u8_t pcb_idx; +#endif + char name[DNS_MAX_NAME_LENGTH]; +}; + +/** DNS request table entry: used when dns_gehostbyname cannot answer the + * request from the DNS table */ +struct dns_req_entry { + /* pointer to callback on DNS query done */ + dns_found_callback found; + /* argument passed to the callback function */ + void *arg; +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0) + u8_t dns_table_idx; +#endif +}; + +#if DNS_LOCAL_HOSTLIST + +#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC +/** Local host-list. For hostnames in this list, no + * external name resolution is performed */ +static struct local_hostlist_entry *local_hostlist_dynamic; +#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + +/** Defining this allows the local_hostlist_static to be placed in a different + * linker section (e.g. FLASH) */ +#ifndef DNS_LOCAL_HOSTLIST_STORAGE_PRE +#define DNS_LOCAL_HOSTLIST_STORAGE_PRE static +#endif /* DNS_LOCAL_HOSTLIST_STORAGE_PRE */ +/** Defining this allows the local_hostlist_static to be placed in a different + * linker section (e.g. FLASH) */ +#ifndef DNS_LOCAL_HOSTLIST_STORAGE_POST +#define DNS_LOCAL_HOSTLIST_STORAGE_POST +#endif /* DNS_LOCAL_HOSTLIST_STORAGE_POST */ +DNS_LOCAL_HOSTLIST_STORAGE_PRE struct local_hostlist_entry local_hostlist_static[] + DNS_LOCAL_HOSTLIST_STORAGE_POST = DNS_LOCAL_HOSTLIST_INIT; + +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + +static void dns_init_local(); +#endif /* DNS_LOCAL_HOSTLIST */ + + +/* forward declarations */ +static void dns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port); +static void dns_check_entries(void); + +/*----------------------------------------------------------------------------- + * Globals + *----------------------------------------------------------------------------*/ + +/* DNS variables */ +static struct udp_pcb *dns_pcbs[DNS_MAX_SOURCE_PORTS]; +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) +static u8_t dns_last_pcb_idx; +#endif +static u8_t dns_seqno; +static struct dns_table_entry dns_table[DNS_TABLE_SIZE]; +static struct dns_req_entry dns_requests[DNS_MAX_REQUESTS]; +static ip_addr_t dns_servers[DNS_MAX_SERVERS]; + +#ifndef LWIP_DNS_STRICMP +#define LWIP_DNS_STRICMP(str1, str2) dns_stricmp(str1, str2) +/** + * A small but sufficient implementation for case insensitive strcmp. + * This can be defined to e.g. stricmp for windows or strcasecmp for linux. */ +static int +dns_stricmp(const char* str1, const char* str2) +{ + char c1, c2; + + do { + c1 = *str1++; + c2 = *str2++; + if (c1 != c2) { + char c1_upc = c1 | 0x20; + if ((c1_upc >= 'a') && (c1_upc <= 'z')) { + /* characters are not equal an one is in the alphabet range: + downcase both chars and check again */ + char c2_upc = c2 | 0x20; + if (c1_upc != c2_upc) { + /* still not equal */ + /* don't care for < or > */ + return 1; + } + } else { + /* characters are not equal but none is in the alphabet range */ + return 1; + } + } + } while (c1 != 0); + return 0; +} +#endif /* LWIP_DNS_STRICMP */ + +/** + * Initialize the resolver: set up the UDP pcb and configure the default server + * (DNS_SERVER_ADDRESS). + */ +void +dns_init() +{ + ip_addr_t dnsserver; + + LWIP_ASSERT("sanity check SIZEOF_DNS_QUERY", + sizeof(struct dns_query) == SIZEOF_DNS_QUERY); + LWIP_ASSERT("sanity check SIZEOF_DNS_ANSWER", + sizeof(struct dns_answer) <= SIZEOF_DNS_ANSWER_ASSERT); + + /* initialize default DNS server address */ + DNS_SERVER_ADDRESS(&dnsserver); + + LWIP_DEBUGF(DNS_DEBUG, ("dns_init: initializing\n")); + + /* if dns client not yet initialized... */ +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) == 0) + if (dns_pcbs[0] == NULL) { + dns_pcbs[0] = udp_new(); + LWIP_ASSERT("dns_pcbs[0] != NULL", dns_pcbs[0] != NULL); + + /* initialize DNS table not needed (initialized to zero since it is a + * global variable) */ + LWIP_ASSERT("For implicit initialization to work, DNS_STATE_UNUSED needs to be 0", + DNS_STATE_UNUSED == 0); + + /* initialize DNS client */ + udp_bind(dns_pcbs[0], IP_ADDR_ANY, 0); + udp_recv(dns_pcbs[0], dns_recv, NULL); + } +#endif + /* initialize default DNS primary server */ + dns_setserver(0, &dnsserver); +#if DNS_LOCAL_HOSTLIST + dns_init_local(); +#endif +} + +/** + * Initialize one of the DNS servers. + * + * @param numdns the index of the DNS server to set must be < DNS_MAX_SERVERS + * @param dnsserver IP address of the DNS server to set + */ +void +dns_setserver(u8_t numdns, ip_addr_t *dnsserver) +{ + if (numdns < DNS_MAX_SERVERS) { + if (dnsserver != NULL) { + dns_servers[numdns] = (*dnsserver); + } else { + dns_servers[numdns] = *IP_ADDR_ANY; + } + } +} + +/** + * Obtain one of the currently configured DNS server. + * + * @param numdns the index of the DNS server + * @return IP address of the indexed DNS server or "ip_addr_any" if the DNS + * server has not been configured. + */ +ip_addr_t +dns_getserver(u8_t numdns) +{ + if (numdns < DNS_MAX_SERVERS) { + return dns_servers[numdns]; + } else { + return *IP_ADDR_ANY; + } +} + +/** + * The DNS resolver client timer - handle retries and timeouts and should + * be called every DNS_TMR_INTERVAL milliseconds (every second by default). + */ +void +dns_tmr(void) +{ + LWIP_DEBUGF(DNS_DEBUG, ("dns_tmr: dns_check_entries\n")); + dns_check_entries(); +} + +#if DNS_LOCAL_HOSTLIST +static void +dns_init_local() +{ +#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT) + int i; + struct local_hostlist_entry *entry; + /* Dynamic: copy entries from DNS_LOCAL_HOSTLIST_INIT to list */ + struct local_hostlist_entry local_hostlist_init[] = DNS_LOCAL_HOSTLIST_INIT; + size_t namelen; + for (i = 0; i < sizeof(local_hostlist_init) / sizeof(struct local_hostlist_entry); i++) { + struct local_hostlist_entry *init_entry = &local_hostlist_init[i]; + LWIP_ASSERT("invalid host name (NULL)", init_entry->name != NULL); + namelen = strlen(init_entry->name); + LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN); + entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST); + LWIP_ASSERT("mem-error in dns_init_local", entry != NULL); + if (entry != NULL) { + entry->name = (char*)entry + sizeof(struct local_hostlist_entry); + MEMCPY((char*)entry->name, init_entry->name, namelen); + ((char*)entry->name)[namelen] = 0; + entry->addr = init_entry->addr; + entry->next = local_hostlist_dynamic; + local_hostlist_dynamic = entry; + } + } +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT) */ +} + +/** + * Scans the local host-list for a hostname. + * + * @param hostname Hostname to look for in the local host-list + * @return The first IP address for the hostname in the local host-list or + * IPADDR_NONE if not found. + */ +static u32_t +dns_lookup_local(const char *hostname) +{ +#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC + struct local_hostlist_entry *entry = local_hostlist_dynamic; + while(entry != NULL) { + if (LWIP_DNS_STRICMP(entry->name, hostname) == 0) { + return ip4_addr_get_u32(&entry->addr); + } + entry = entry->next; + } +#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + int i; + for (i = 0; i < sizeof(local_hostlist_static) / sizeof(struct local_hostlist_entry); i++) { + if (LWIP_DNS_STRICMP(local_hostlist_static[i].name, hostname) == 0) { + return ip4_addr_get_u32(&local_hostlist_static[i].addr); + } + } +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + return IPADDR_NONE; +} + +#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC +/** Remove all entries from the local host-list for a specific hostname + * and/or IP address + * + * @param hostname hostname for which entries shall be removed from the local + * host-list + * @param addr address for which entries shall be removed from the local host-list + * @return the number of removed entries + */ +int +dns_local_removehost(const char *hostname, const ip_addr_t *addr) +{ + int removed = 0; + struct local_hostlist_entry *entry = local_hostlist_dynamic; + struct local_hostlist_entry *last_entry = NULL; + while (entry != NULL) { + if (((hostname == NULL) || !LWIP_DNS_STRICMP(entry->name, hostname)) && + ((addr == NULL) || ip_addr_cmp(&entry->addr, addr))) { + struct local_hostlist_entry *free_entry; + if (last_entry != NULL) { + last_entry->next = entry->next; + } else { + local_hostlist_dynamic = entry->next; + } + free_entry = entry; + entry = entry->next; + memp_free(MEMP_LOCALHOSTLIST, free_entry); + removed++; + } else { + last_entry = entry; + entry = entry->next; + } + } + return removed; +} + +/** + * Add a hostname/IP address pair to the local host-list. + * Duplicates are not checked. + * + * @param hostname hostname of the new entry + * @param addr IP address of the new entry + * @return ERR_OK if succeeded or ERR_MEM on memory error + */ +err_t +dns_local_addhost(const char *hostname, const ip_addr_t *addr) +{ + struct local_hostlist_entry *entry; + size_t namelen; + LWIP_ASSERT("invalid host name (NULL)", hostname != NULL); + namelen = strlen(hostname); + LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN); + entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST); + if (entry == NULL) { + return ERR_MEM; + } + entry->name = (char*)entry + sizeof(struct local_hostlist_entry); + MEMCPY((char*)entry->name, hostname, namelen); + ((char*)entry->name)[namelen] = 0; + ip_addr_copy(entry->addr, *addr); + entry->next = local_hostlist_dynamic; + local_hostlist_dynamic = entry; + return ERR_OK; +} +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC*/ +#endif /* DNS_LOCAL_HOSTLIST */ + +/** + * Look up a hostname in the array of known hostnames. + * + * @note This function only looks in the internal array of known + * hostnames, it does not send out a query for the hostname if none + * was found. The function dns_enqueue() can be used to send a query + * for a hostname. + * + * @param name the hostname to look up + * @return the hostname's IP address, as u32_t (instead of ip_addr_t to + * better check for failure: != IPADDR_NONE) or IPADDR_NONE if the hostname + * was not found in the cached dns_table. + */ +static u32_t +dns_lookup(const char *name) +{ + u8_t i; +#if DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN) + u32_t addr; +#endif /* DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN) */ +#if DNS_LOCAL_HOSTLIST + if ((addr = dns_lookup_local(name)) != IPADDR_NONE) { + return addr; + } +#endif /* DNS_LOCAL_HOSTLIST */ +#ifdef DNS_LOOKUP_LOCAL_EXTERN + if((addr = DNS_LOOKUP_LOCAL_EXTERN(name)) != IPADDR_NONE) { + return addr; + } +#endif /* DNS_LOOKUP_LOCAL_EXTERN */ + + /* Walk through name list, return entry if found. If not, return NULL. */ + for (i = 0; i < DNS_TABLE_SIZE; ++i) { + if ((dns_table[i].state == DNS_STATE_DONE) && + (LWIP_DNS_STRICMP(name, dns_table[i].name) == 0)) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_lookup: \"%s\": found = ", name)); + ip_addr_debug_print(DNS_DEBUG, &(dns_table[i].ipaddr)); + LWIP_DEBUGF(DNS_DEBUG, ("\n")); + return ip4_addr_get_u32(&dns_table[i].ipaddr); + } + } + + return IPADDR_NONE; +} + +/** + * Compare the "dotted" name "query" with the encoded name "response" + * to make sure an answer from the DNS server matches the current dns_table + * entry (otherwise, answers might arrive late for hostname not on the list + * any more). + * + * @param query hostname (not encoded) from the dns_table + * @param p pbuf containing the encoded hostname in the DNS response + * @param start_offset offset into p where the name starts + * @return 0xFFFF: names differ, other: names equal -> offset behind name + */ +static u16_t +dns_compare_name(char *query, struct pbuf* p, u16_t start_offset) +{ + unsigned char n; + u16_t response_offset = start_offset; + + do { + n = pbuf_get_at(p, response_offset++); + /** @see RFC 1035 - 4.1.4. Message compression */ + if ((n & 0xc0) == 0xc0) { + /* Compressed name: cannot be equal since we don't send them */ + return 0xFFFF; + } else { + /* Not compressed name */ + while (n > 0) { + if ((*query) != pbuf_get_at(p, response_offset)) { + return 0xFFFF; + } + ++response_offset; + ++query; + --n; + }; + ++query; + } + } while (pbuf_get_at(p, response_offset) != 0); + + return response_offset + 1; +} + +/** + * Walk through a compact encoded DNS name and return the end of the name. + * + * @param p pbuf containing the name + * @param query_idx start index into p pointing to encoded DNS name in the DNS server response + * @return index to end of the name + */ +static u16_t +dns_parse_name(struct pbuf* p, u16_t query_idx) +{ + unsigned char n; + + do { + n = pbuf_get_at(p, query_idx++); + /** @see RFC 1035 - 4.1.4. Message compression */ + if ((n & 0xc0) == 0xc0) { + /* Compressed name */ + break; + } else { + /* Not compressed name */ + while (n > 0) { + ++query_idx; + --n; + }; + } + } while (pbuf_get_at(p, query_idx) != 0); + + return query_idx + 1; +} + +/** + * Send a DNS query packet. + * + * @param entry the DNS table entry for which to send a request + * @return ERR_OK if packet is sent; an err_t indicating the problem otherwise + */ +static err_t +dns_send(struct dns_table_entry* entry) +{ + err_t err; + struct dns_hdr hdr; + struct dns_query qry; + struct pbuf *p; + u16_t query_idx, copy_len; + const char *hostname, *hostname_part; + u8_t n; + u8_t pcb_idx; + + LWIP_DEBUGF(DNS_DEBUG, ("dns_send: dns_servers[%"U16_F"] \"%s\": request\n", + (u16_t)(entry->server_idx), entry->name)); + LWIP_ASSERT("dns server out of array", entry->server_idx < DNS_MAX_SERVERS); + LWIP_ASSERT("dns server has no IP address set", !ip_addr_isany(&dns_servers[entry->server_idx])); + + /* if here, we have either a new query or a retry on a previous query to process */ + p = pbuf_alloc(PBUF_TRANSPORT, SIZEOF_DNS_HDR + strlen(entry->name) + 2 + + SIZEOF_DNS_QUERY, PBUF_RAM); + if (p != NULL) { + /* fill dns header */ + memset(&hdr, 0, SIZEOF_DNS_HDR); + hdr.id = htons(entry->txid); + hdr.flags1 = DNS_FLAG1_RD; + hdr.numquestions = PP_HTONS(1); + pbuf_take(p, &hdr, SIZEOF_DNS_HDR); + hostname = entry->name; + --hostname; + + /* convert hostname into suitable query format. */ + query_idx = SIZEOF_DNS_HDR; + do { + ++hostname; + hostname_part = hostname; + for(n = 0; *hostname != '.' && *hostname != 0; ++hostname) { + ++n; + } + copy_len = hostname - hostname_part; + pbuf_put_at(p, query_idx, n); + pbuf_take_at(p, hostname_part, copy_len, query_idx + 1); + query_idx += n + 1; + } while(*hostname != 0); + pbuf_put_at(p, query_idx, 0); + query_idx++; + + /* fill dns query */ + qry.type = PP_HTONS(DNS_RRTYPE_A); + qry.cls = PP_HTONS(DNS_RRCLASS_IN); + pbuf_take_at(p, &qry, SIZEOF_DNS_QUERY, query_idx); + +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) + pcb_idx = entry->pcb_idx; +#else + pcb_idx = 0; +#endif + /* send dns packet */ + LWIP_DEBUGF(DNS_DEBUG, ("sending DNS request ID %d for name \"%s\" to server %d\r\n", + entry->txid, entry->name, entry->server_idx)); + err = udp_sendto(dns_pcbs[pcb_idx], p, &dns_servers[entry->server_idx], DNS_SERVER_PORT); + + /* free pbuf */ + pbuf_free(p); + } else { + err = ERR_MEM; + } + + return err; +} + +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) +static struct udp_pcb* +dns_alloc_random_port(void) +{ + err_t err; + struct udp_pcb* ret; + + ret = udp_new(); + if (ret == NULL) { + /* out of memory, have to reuse an existing pcb */ + return NULL; + } + do { + u16_t port = DNS_RAND_TXID(); + if (!DNS_PORT_ALLOWED(port)) { + /* this port is not allowed, try again */ + err = ERR_USE; + continue; + } + err = udp_bind(ret, IP_ADDR_ANY, port); + } while(err == ERR_USE); + if ((err != ERR_OK) && (err != ERR_USE)) { + udp_remove(ret); + return NULL; + } + udp_recv(ret, dns_recv, NULL); + return ret; +} + +/** + * dns_alloc_pcb() - allocates a new pcb (or reuses an existing one) to be used + * for sending a request + * + * @return an index into dns_pcbs + */ +static u8_t +dns_alloc_pcb(void) +{ + u8_t i; + u8_t idx; + + for (i = 0; i < DNS_MAX_SOURCE_PORTS; i++) { + if (dns_pcbs[i] == NULL) { + break; + } + } + if (i < DNS_MAX_SOURCE_PORTS) { + dns_pcbs[i] = dns_alloc_random_port(); + if (dns_pcbs[i] != NULL) { + /* succeeded */ + dns_last_pcb_idx = i; + return i; + } + } + /* if we come here, creating a new UDP pcb failed, so we have to use + an already existing one */ + idx = dns_last_pcb_idx + 1; + for (i = 0; i < DNS_MAX_SOURCE_PORTS; i++) { + if (idx >= DNS_MAX_SOURCE_PORTS) { + idx = 0; + } + if (dns_pcbs[idx] != NULL) { + dns_last_pcb_idx = idx; + return idx; + } + } + return DNS_MAX_SOURCE_PORTS; +} +#endif /* ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) */ + +/** + * dns_call_found() - call the found callback and check if there are duplicate + * entries for the given hostname. If there are any, their found callback will + * be called and they will be removed. + * + * @param idx dns table index of the entry that is resolved or removed + * @param addr IP address for the hostname (or NULL on error or memory shortage) + */ +static void +dns_call_found(u8_t idx, ip_addr_t* addr) +{ + u8_t i; + LWIP_UNUSED_ARG(i); + +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0) + for (i = 0; i < DNS_MAX_REQUESTS; i++) { + if (dns_requests[i].found && (dns_requests[i].dns_table_idx == idx)) { + (*dns_requests[i].found)(dns_table[idx].name, addr, dns_requests[i].arg); + /* flush this entry */ + dns_requests[i].found = NULL; + } + } +#else + if (dns_requests[idx].found) { + (*dns_requests[idx].found)(dns_table[idx].name, addr, dns_requests[idx].arg); + } + dns_requests[idx].found = NULL; +#endif +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) + /* close the pcb used unless other request are using it */ + for (i = 0; i < DNS_MAX_REQUESTS; i++) { + if (i == idx) { + continue; /* only check other requests */ + } + if (dns_table[i].state == DNS_STATE_ASKING) { + if (dns_table[i].pcb_idx == dns_table[idx].pcb_idx) { + /* another request is still using the same pcb */ + dns_table[idx].pcb_idx = DNS_MAX_SOURCE_PORTS; + break; + } + } + } + if (dns_table[idx].pcb_idx < DNS_MAX_SOURCE_PORTS) { + /* if we come here, the pcb is not used any more and can be removed */ + udp_remove(dns_pcbs[dns_table[idx].pcb_idx]); + dns_pcbs[dns_table[idx].pcb_idx] = NULL; + dns_table[idx].pcb_idx = DNS_MAX_SOURCE_PORTS; + } +#endif +} + +/* Create a query transmission ID that is unique for all outstanding queries */ +static u16_t +dns_create_txid(void) +{ + u16_t txid; + u8_t i; + +again: + txid = DNS_RAND_TXID(); + + /* check whether the ID is unique */ + for (i = 0; i < DNS_TABLE_SIZE; i++) { + if ((dns_table[i].state == DNS_STATE_ASKING) && + (dns_table[i].txid == txid)) { + /* ID already used by another pending query */ + goto again; + } + } + + return txid; +} + +/** + * dns_check_entry() - see if entry has not yet been queried and, if so, sends out a query. + * Check an entry in the dns_table: + * - send out query for new entries + * - retry old pending entries on timeout (also with different servers) + * - remove completed entries from the table if their TTL has expired + * + * @param i index of the dns_table entry to check + */ +static void +dns_check_entry(u8_t i) +{ + err_t err; + struct dns_table_entry *entry = &dns_table[i]; + + LWIP_ASSERT("array index out of bounds", i < DNS_TABLE_SIZE); + + switch (entry->state) { + + case DNS_STATE_NEW: { + u16_t txid; + /* initialize new entry */ + txid = dns_create_txid(); + entry->txid = txid; + entry->state = DNS_STATE_ASKING; + entry->server_idx = 0; + entry->tmr = 1; + entry->retries = 0; + + /* send DNS packet for this entry */ + err = dns_send(entry); + if (err != ERR_OK) { + LWIP_DEBUGF(DNS_DEBUG | LWIP_DBG_LEVEL_WARNING, + ("dns_send returned error: %s\n", lwip_strerr(err))); + } + break; + } + + case DNS_STATE_ASKING: + if (--entry->tmr == 0) { + if (++entry->retries == DNS_MAX_RETRIES) { + if ((entry->server_idx + 1 < DNS_MAX_SERVERS) && !ip_addr_isany(&dns_servers[entry->server_idx + 1])) { + /* change of server */ + entry->server_idx++; + entry->tmr = 1; + entry->retries = 0; + break; + } else { + LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": timeout\n", entry->name)); + /* call specified callback function if provided */ + dns_call_found(i, NULL); + /* flush this entry */ + entry->state = DNS_STATE_UNUSED; + break; + } + } + + /* wait longer for the next retry */ + entry->tmr = entry->retries; + + /* send DNS packet for this entry */ + err = dns_send(entry); + if (err != ERR_OK) { + LWIP_DEBUGF(DNS_DEBUG | LWIP_DBG_LEVEL_WARNING, + ("dns_send returned error: %s\n", lwip_strerr(err))); + } + } + break; + case DNS_STATE_DONE: + /* if the time to live is nul */ + if ((entry->ttl == 0) || (--entry->ttl == 0)) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": flush\n", entry->name)); + /* flush this entry, there cannot be any related pending entries in this state */ + entry->state = DNS_STATE_UNUSED; + } + break; + case DNS_STATE_UNUSED: + /* nothing to do */ + break; + default: + LWIP_ASSERT("unknown dns_table entry state:", 0); + break; + } +} + +/** + * Call dns_check_entry for each entry in dns_table - check all entries. + */ +static void +dns_check_entries(void) +{ + u8_t i; + + for (i = 0; i < DNS_TABLE_SIZE; ++i) { + dns_check_entry(i); + } +} + +/** + * Receive input function for DNS response packets arriving for the dns UDP pcb. + * + * @params see udp.h + */ +static void +dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port) +{ + u8_t i, entry_idx = DNS_TABLE_SIZE; + u16_t txid; + u16_t res_idx; + struct dns_hdr hdr; + struct dns_answer ans; + struct dns_query qry; + u16_t nquestions, nanswers; + + LWIP_UNUSED_ARG(arg); + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(port); + + /* is the dns message big enough ? */ + if (p->tot_len < (SIZEOF_DNS_HDR + SIZEOF_DNS_QUERY + SIZEOF_DNS_ANSWER)) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too small\n")); + /* free pbuf and return */ + goto memerr; + } + + /* copy dns payload inside static buffer for processing */ + if (pbuf_copy_partial(p, &hdr, SIZEOF_DNS_HDR, 0) == SIZEOF_DNS_HDR) { + /* Match the ID in the DNS header with the name table. */ + txid = htons(hdr.id); + for (i = 0; i < DNS_TABLE_SIZE; i++) { + struct dns_table_entry *entry = &dns_table[i]; + entry_idx = i; + if ((entry->state == DNS_STATE_ASKING) && + (entry->txid == txid)) { + u8_t dns_err; + /* This entry is now completed. */ + entry->state = DNS_STATE_DONE; + dns_err = hdr.flags2 & DNS_FLAG2_ERR_MASK; + + /* We only care about the question(s) and the answers. The authrr + and the extrarr are simply discarded. */ + nquestions = htons(hdr.numquestions); + nanswers = htons(hdr.numanswers); + + /* Check for error. If so, call callback to inform. */ + if (((hdr.flags1 & DNS_FLAG1_RESPONSE) == 0) || (dns_err != 0) || (nquestions != 1)) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in flags\n", entry->name)); + /* call callback to indicate error, clean up memory and return */ + goto responseerr; + } + + /* Check whether response comes from the same network address to which the + question was sent. (RFC 5452) */ + if (!ip_addr_cmp(addr, &dns_servers[entry->server_idx])) { + /* call callback to indicate error, clean up memory and return */ + goto responseerr; + } + + /* Check if the name in the "question" part match with the name in the entry and + skip it if equal. */ + res_idx = dns_compare_name(entry->name, p, SIZEOF_DNS_HDR); + if (res_idx == 0xFFFF) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", entry->name)); + /* call callback to indicate error, clean up memory and return */ + goto responseerr; + } + + /* check if "question" part matches the request */ + pbuf_copy_partial(p, &qry, SIZEOF_DNS_QUERY, res_idx); + if((qry.type != PP_HTONS(DNS_RRTYPE_A)) || (qry.cls != PP_HTONS(DNS_RRCLASS_IN))) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", entry->name)); + /* call callback to indicate error, clean up memory and return */ + goto responseerr; + } + /* skip the rest of the "question" part */ + res_idx += SIZEOF_DNS_QUERY; + + while (nanswers > 0) { + /* skip answer resource record's host name */ + res_idx = dns_parse_name(p, res_idx); + + /* Check for IP address type and Internet class. Others are discarded. */ + pbuf_copy_partial(p, &ans, SIZEOF_DNS_ANSWER, res_idx); + if((ans.type == PP_HTONS(DNS_RRTYPE_A)) && (ans.cls == PP_HTONS(DNS_RRCLASS_IN)) && + (ans.len == PP_HTONS(sizeof(ip_addr_t))) ) { + res_idx += SIZEOF_DNS_ANSWER; + /* read the answer resource record's TTL, and maximize it if needed */ + entry->ttl = ntohl(ans.ttl); + if (entry->ttl > DNS_MAX_TTL) { + entry->ttl = DNS_MAX_TTL; + } + /* read the IP address after answer resource record's header */ + pbuf_copy_partial(p, &(entry->ipaddr), sizeof(entry->ipaddr), res_idx); + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response = ", entry->name)); + ip_addr_debug_print(DNS_DEBUG, (&(entry->ipaddr))); + LWIP_DEBUGF(DNS_DEBUG, ("\n")); + /* call specified callback function if provided */ + dns_call_found(entry_idx, &entry->ipaddr); + if (entry->ttl == 0) { + /* RFC 883, page 29: "Zero values are + interpreted to mean that the RR can only be used for the + transaction in progress, and should not be cached." + -> flush this entry now */ + goto flushentry; + } + /* deallocate memory and return */ + goto memerr; + } else { + res_idx += SIZEOF_DNS_ANSWER + htons(ans.len); + } + --nanswers; + } + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in response\n", entry->name)); + /* call callback to indicate error, clean up memory and return */ + goto responseerr; + } + } + } + + /* deallocate memory and return */ + goto memerr; + +responseerr: + /* ERROR: call specified callback function with NULL as name to indicate an error */ + dns_call_found(entry_idx, NULL); +flushentry: + /* flush this entry */ + dns_table[entry_idx].state = DNS_STATE_UNUSED; + +memerr: + /* free pbuf */ + pbuf_free(p); + return; +} + +/** + * Queues a new hostname to resolve and sends out a DNS query for that hostname + * + * @param name the hostname that is to be queried + * @param hostnamelen length of the hostname + * @param found a callback function to be called on success, failure or timeout + * @param callback_arg argument to pass to the callback function + * @return @return a err_t return code. + */ +static err_t +dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found, + void *callback_arg) +{ + u8_t i; + u8_t lseq, lseqi; + struct dns_table_entry *entry = NULL; + size_t namelen; + struct dns_req_entry* req; + +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0) + u8_t r; + /* check for duplicate entries */ + for (i = 0; i < DNS_TABLE_SIZE; i++) { + if ((dns_table[i].state == DNS_STATE_ASKING) && + (LWIP_DNS_STRICMP(name, dns_table[i].name) == 0)) { + /* this is a duplicate entry, find a free request entry */ + for (r = 0; r < DNS_MAX_REQUESTS; r++) { + if (dns_requests[r].found == 0) { + dns_requests[r].found = found; + dns_requests[r].arg = callback_arg; + dns_requests[r].dns_table_idx = i; + LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": duplicate request\n", name)); + return ERR_INPROGRESS; + } + } + } + } + /* no duplicate entries found */ +#endif + + /* search an unused entry, or the oldest one */ + lseq = 0; + lseqi = DNS_TABLE_SIZE; + for (i = 0; i < DNS_TABLE_SIZE; ++i) { + entry = &dns_table[i]; + /* is it an unused entry ? */ + if (entry->state == DNS_STATE_UNUSED) { + break; + } + /* check if this is the oldest completed entry */ + if (entry->state == DNS_STATE_DONE) { + if ((u8_t)(dns_seqno - entry->seqno) > lseq) { + lseq = dns_seqno - entry->seqno; + lseqi = i; + } + } + } + + /* if we don't have found an unused entry, use the oldest completed one */ + if (i == DNS_TABLE_SIZE) { + if ((lseqi >= DNS_TABLE_SIZE) || (dns_table[lseqi].state != DNS_STATE_DONE)) { + /* no entry can be used now, table is full */ + LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": DNS entries table is full\n", name)); + return ERR_MEM; + } else { + /* use the oldest completed one */ + i = lseqi; + entry = &dns_table[i]; + } + } + +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0) + /* find a free request entry */ + req = NULL; + for (r = 0; r < DNS_MAX_REQUESTS; r++) { + if (dns_requests[r].found == NULL) { + req = &dns_requests[r]; + break; + } + } + if (req == NULL) { + /* no request entry can be used now, table is full */ + LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": DNS request entries table is full\n", name)); + return ERR_MEM; + } + req->dns_table_idx = i; +#else + /* in this configuration, the entry index is the same as the request index */ + req = &dns_requests[i]; +#endif + + /* use this entry */ + LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": use DNS entry %"U16_F"\n", name, (u16_t)(i))); + + /* fill the entry */ + entry->state = DNS_STATE_NEW; + entry->seqno = dns_seqno; + req->found = found; + req->arg = callback_arg; + namelen = LWIP_MIN(hostnamelen, DNS_MAX_NAME_LENGTH-1); + MEMCPY(entry->name, name, namelen); + entry->name[namelen] = 0; + +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) + entry->pcb_idx = dns_alloc_pcb(); + if (entry->pcb_idx >= DNS_MAX_SOURCE_PORTS) { + /* failed to get a UDP pcb */ + LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": failed to allocate a pcb\n", name)); + entry->state = DNS_STATE_UNUSED; + req->found = NULL; + return ERR_MEM; + } + LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": use DNS pcb %"U16_F"\n", name, (u16_t)(entry->pcb_idx))); +#endif + + dns_seqno++; + + /* force to send query without waiting timer */ + dns_check_entry(i); + + /* dns query is enqueued */ + return ERR_INPROGRESS; +} + +/** + * Resolve a hostname (string) into an IP address. + * NON-BLOCKING callback version for use with raw API!!! + * + * Returns immediately with one of err_t return codes: + * - ERR_OK if hostname is a valid IP address string or the host + * name is already in the local names table. + * - ERR_INPROGRESS enqueue a request to be sent to the DNS server + * for resolution if no errors are present. + * - ERR_ARG: dns client not initialized or invalid hostname + * + * @param hostname the hostname that is to be queried + * @param addr pointer to a ip_addr_t where to store the address if it is already + * cached in the dns_table (only valid if ERR_OK is returned!) + * @param found a callback function to be called on success, failure or timeout (only if + * ERR_INPROGRESS is returned!) + * @param callback_arg argument to pass to the callback function + * @return a err_t return code. + */ +err_t +dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback found, + void *callback_arg) +{ + u32_t ipaddr; + size_t hostnamelen; + /* not initialized or no valid server yet, or invalid addr pointer + * or invalid hostname or invalid hostname length */ + if ((addr == NULL) || + (!hostname) || (!hostname[0])) { + return ERR_ARG; + } +#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) == 0) + if (dns_pcbs[0] == NULL) { + return ERR_ARG; + } +#endif + hostnamelen = strlen(hostname); + if (hostnamelen >= DNS_MAX_NAME_LENGTH) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_gethostbyname: name too long to resolve")); + return ERR_ARG; + } + + +#if LWIP_HAVE_LOOPIF + if (strcmp(hostname, "localhost") == 0) { + ip_addr_set_loopback(addr); + return ERR_OK; + } +#endif /* LWIP_HAVE_LOOPIF */ + + /* host name already in octet notation? set ip addr and return ERR_OK */ + ipaddr = ipaddr_addr(hostname); + if (ipaddr == IPADDR_NONE) { + /* already have this address cached? */ + ipaddr = dns_lookup(hostname); + } + if (ipaddr != IPADDR_NONE) { + ip4_addr_set_u32(addr, ipaddr); + return ERR_OK; + } + + /* queue query with specified callback */ + return dns_enqueue(hostname, hostnamelen, found, callback_arg); +} + +#endif /* LWIP_DNS */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/core/inet_chksum.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/inet_chksum.c new file mode 100644 index 0000000..01a8fa9 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/inet_chksum.c @@ -0,0 +1,545 @@ +/** + * @file + * Incluse internet checksum functions. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/inet_chksum.h" +#include "lwip/def.h" + +#include +#include + +/* These are some reference implementations of the checksum algorithm, with the + * aim of being simple, correct and fully portable. Checksumming is the + * first thing you would want to optimize for your platform. If you create + * your own version, link it in and in your cc.h put: + * + * #define LWIP_CHKSUM + * + * Or you can select from the implementations below by defining + * LWIP_CHKSUM_ALGORITHM to 1, 2 or 3. + */ + +#ifndef LWIP_CHKSUM +# define LWIP_CHKSUM lwip_standard_chksum +# ifndef LWIP_CHKSUM_ALGORITHM +# define LWIP_CHKSUM_ALGORITHM 2 +# endif +u16_t lwip_standard_chksum(void *dataptr, int len); +#endif +/* If none set: */ +#ifndef LWIP_CHKSUM_ALGORITHM +# define LWIP_CHKSUM_ALGORITHM 0 +#endif + +#if (LWIP_CHKSUM_ALGORITHM == 1) /* Version #1 */ +/** + * lwip checksum + * + * @param dataptr points to start of data to be summed at any boundary + * @param len length of data to be summed + * @return host order (!) lwip checksum (non-inverted Internet sum) + * + * @note accumulator size limits summable length to 64k + * @note host endianess is irrelevant (p3 RFC1071) + */ +u16_t +lwip_standard_chksum(void *dataptr, int len) +{ + u32_t acc; + u16_t src; + u8_t *octetptr; + + acc = 0; + /* dataptr may be at odd or even addresses */ + octetptr = (u8_t*)dataptr; + while (len > 1) { + /* declare first octet as most significant + thus assume network order, ignoring host order */ + src = (*octetptr) << 8; + octetptr++; + /* declare second octet as least significant */ + src |= (*octetptr); + octetptr++; + acc += src; + len -= 2; + } + if (len > 0) { + /* accumulate remaining octet */ + src = (*octetptr) << 8; + acc += src; + } + /* add deferred carry bits */ + acc = (acc >> 16) + (acc & 0x0000ffffUL); + if ((acc & 0xffff0000UL) != 0) { + acc = (acc >> 16) + (acc & 0x0000ffffUL); + } + /* This maybe a little confusing: reorder sum using htons() + instead of ntohs() since it has a little less call overhead. + The caller must invert bits for Internet sum ! */ + return htons((u16_t)acc); +} +#endif + +#if (LWIP_CHKSUM_ALGORITHM == 2) /* Alternative version #2 */ +/* + * Curt McDowell + * Broadcom Corp. + * csm@broadcom.com + * + * IP checksum two bytes at a time with support for + * unaligned buffer. + * Works for len up to and including 0x20000. + * by Curt McDowell, Broadcom Corp. 12/08/2005 + * + * @param dataptr points to start of data to be summed at any boundary + * @param len length of data to be summed + * @return host order (!) lwip checksum (non-inverted Internet sum) + */ + +u16_t +lwip_standard_chksum(void *dataptr, int len) +{ + u8_t *pb = (u8_t *)dataptr; + u16_t *ps, t = 0; + u32_t sum = 0; + int odd = ((mem_ptr_t)pb & 1); + + /* Get aligned to u16_t */ + if (odd && len > 0) { + ((u8_t *)&t)[1] = *pb++; + len--; + } + + /* Add the bulk of the data */ + ps = (u16_t *)(void *)pb; + while (len > 1) { + sum += *ps++; + len -= 2; + } + + /* Consume left-over byte, if any */ + if (len > 0) { + ((u8_t *)&t)[0] = *(u8_t *)ps; + } + + /* Add end bytes */ + sum += t; + + /* Fold 32-bit sum to 16 bits + calling this twice is probably faster than if statements... */ + sum = FOLD_U32T(sum); + sum = FOLD_U32T(sum); + + /* Swap if alignment was odd */ + if (odd) { + sum = SWAP_BYTES_IN_WORD(sum); + } + + return (u16_t)sum; +} +#endif + +#if (LWIP_CHKSUM_ALGORITHM == 3) /* Alternative version #3 */ +/** + * An optimized checksum routine. Basically, it uses loop-unrolling on + * the checksum loop, treating the head and tail bytes specially, whereas + * the inner loop acts on 8 bytes at a time. + * + * @arg start of buffer to be checksummed. May be an odd byte address. + * @len number of bytes in the buffer to be checksummed. + * @return host order (!) lwip checksum (non-inverted Internet sum) + * + * by Curt McDowell, Broadcom Corp. December 8th, 2005 + */ + +u16_t +lwip_standard_chksum(void *dataptr, int len) +{ + u8_t *pb = (u8_t *)dataptr; + u16_t *ps, t = 0; + u32_t *pl; + u32_t sum = 0, tmp; + /* starts at odd byte address? */ + int odd = ((mem_ptr_t)pb & 1); + + if (odd && len > 0) { + ((u8_t *)&t)[1] = *pb++; + len--; + } + + ps = (u16_t *)pb; + + if (((mem_ptr_t)ps & 3) && len > 1) { + sum += *ps++; + len -= 2; + } + + pl = (u32_t *)ps; + + while (len > 7) { + tmp = sum + *pl++; /* ping */ + if (tmp < sum) { + tmp++; /* add back carry */ + } + + sum = tmp + *pl++; /* pong */ + if (sum < tmp) { + sum++; /* add back carry */ + } + + len -= 8; + } + + /* make room in upper bits */ + sum = FOLD_U32T(sum); + + ps = (u16_t *)pl; + + /* 16-bit aligned word remaining? */ + while (len > 1) { + sum += *ps++; + len -= 2; + } + + /* dangling tail byte remaining? */ + if (len > 0) { /* include odd byte */ + ((u8_t *)&t)[0] = *(u8_t *)ps; + } + + sum += t; /* add end bytes */ + + /* Fold 32-bit sum to 16 bits + calling this twice is probably faster than if statements... */ + sum = FOLD_U32T(sum); + sum = FOLD_U32T(sum); + + if (odd) { + sum = SWAP_BYTES_IN_WORD(sum); + } + + return (u16_t)sum; +} +#endif + +/** Parts of the pseudo checksum which are common to IPv4 and IPv6 */ +static u16_t +inet_cksum_pseudo_base(struct pbuf *p, u8_t proto, u16_t proto_len, u32_t acc) +{ + struct pbuf *q; + u8_t swapped = 0; + + /* iterate through all pbuf in chain */ + for(q = p; q != NULL; q = q->next) { + LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n", + (void *)q, (void *)q->next)); + acc += LWIP_CHKSUM(q->payload, q->len); + /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/ + /* just executing this next line is probably faster that the if statement needed + to check whether we really need to execute it, and does no harm */ + acc = FOLD_U32T(acc); + if (q->len % 2 != 0) { + swapped = 1 - swapped; + acc = SWAP_BYTES_IN_WORD(acc); + } + /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/ + } + + if (swapped) { + acc = SWAP_BYTES_IN_WORD(acc); + } + + acc += (u32_t)htons((u16_t)proto); + acc += (u32_t)htons(proto_len); + + /* Fold 32-bit sum to 16 bits + calling this twice is probably faster than if statements... */ + acc = FOLD_U32T(acc); + acc = FOLD_U32T(acc); + LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc)); + return (u16_t)~(acc & 0xffffUL); +} + +/* inet_chksum_pseudo: + * + * Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain. + * IP addresses are expected to be in network byte order. + * + * @param p chain of pbufs over that a checksum should be calculated (ip data part) + * @param src source ip address (used for checksum of pseudo header) + * @param dst destination ip address (used for checksum of pseudo header) + * @param proto ip protocol (used for checksum of pseudo header) + * @param proto_len length of the ip data part (used for checksum of pseudo header) + * @return checksum (as u16_t) to be saved directly in the protocol header + */ +u16_t +inet_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, + ip_addr_t *src, ip_addr_t *dest) +{ + u32_t acc; + u32_t addr; + + addr = ip4_addr_get_u32(src); + acc = (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + addr = ip4_addr_get_u32(dest); + acc += (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + /* fold down to 16 bits */ + acc = FOLD_U32T(acc); + acc = FOLD_U32T(acc); + + return inet_cksum_pseudo_base(p, proto, proto_len, acc); +} +#if LWIP_IPV6 +/** + * Calculates the checksum with IPv6 pseudo header used by TCP and UDP for a pbuf chain. + * IPv6 addresses are expected to be in network byte order. + * + * @param p chain of pbufs over that a checksum should be calculated (ip data part) + * @param src source ipv6 address (used for checksum of pseudo header) + * @param dst destination ipv6 address (used for checksum of pseudo header) + * @param proto ipv6 protocol/next header (used for checksum of pseudo header) + * @param proto_len length of the ipv6 payload (used for checksum of pseudo header) + * @return checksum (as u16_t) to be saved directly in the protocol header + */ +u16_t +ip6_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, + ip6_addr_t *src, ip6_addr_t *dest) +{ + u32_t acc = 0; + u32_t addr; + u8_t addr_part; + + for (addr_part = 0; addr_part < 4; addr_part++) { + addr = src->addr[addr_part]; + acc += (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + addr = dest->addr[addr_part]; + acc += (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + } + /* fold down to 16 bits */ + acc = FOLD_U32T(acc); + acc = FOLD_U32T(acc); + + return inet_cksum_pseudo_base(p, proto, proto_len, acc); +} +#endif /* LWIP_IPV6 */ + +/** Parts of the pseudo checksum which are common to IPv4 and IPv6 */ +static u16_t +inet_cksum_pseudo_partial_base(struct pbuf *p, u8_t proto, u16_t proto_len, + u16_t chksum_len, u32_t acc) +{ + struct pbuf *q; + u8_t swapped = 0; + u16_t chklen; + + /* iterate through all pbuf in chain */ + for(q = p; (q != NULL) && (chksum_len > 0); q = q->next) { + LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n", + (void *)q, (void *)q->next)); + chklen = q->len; + if (chklen > chksum_len) { + chklen = chksum_len; + } + acc += LWIP_CHKSUM(q->payload, chklen); + chksum_len -= chklen; + LWIP_ASSERT("delete me", chksum_len < 0x7fff); + /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/ + /* fold the upper bit down */ + acc = FOLD_U32T(acc); + if (q->len % 2 != 0) { + swapped = 1 - swapped; + acc = SWAP_BYTES_IN_WORD(acc); + } + /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/ + } + + if (swapped) { + acc = SWAP_BYTES_IN_WORD(acc); + } + + acc += (u32_t)htons((u16_t)proto); + acc += (u32_t)htons(proto_len); + + /* Fold 32-bit sum to 16 bits + calling this twice is probably faster than if statements... */ + acc = FOLD_U32T(acc); + acc = FOLD_U32T(acc); + LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc)); + return (u16_t)~(acc & 0xffffUL); +} + +/* inet_chksum_pseudo_partial: + * + * Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain. + * IP addresses are expected to be in network byte order. + * + * @param p chain of pbufs over that a checksum should be calculated (ip data part) + * @param src source ip address (used for checksum of pseudo header) + * @param dst destination ip address (used for checksum of pseudo header) + * @param proto ip protocol (used for checksum of pseudo header) + * @param proto_len length of the ip data part (used for checksum of pseudo header) + * @return checksum (as u16_t) to be saved directly in the protocol header + */ +u16_t +inet_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len, + u16_t chksum_len, ip_addr_t *src, ip_addr_t *dest) +{ + u32_t acc; + u32_t addr; + + addr = ip4_addr_get_u32(src); + acc = (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + addr = ip4_addr_get_u32(dest); + acc += (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + /* fold down to 16 bits */ + acc = FOLD_U32T(acc); + acc = FOLD_U32T(acc); + + return inet_cksum_pseudo_partial_base(p, proto, proto_len, chksum_len, acc); +} + +#if LWIP_IPV6 +/** + * Calculates the checksum with IPv6 pseudo header used by TCP and UDP for a pbuf chain. + * IPv6 addresses are expected to be in network byte order. Will only compute for a + * portion of the payload. + * + * @param p chain of pbufs over that a checksum should be calculated (ip data part) + * @param src source ipv6 address (used for checksum of pseudo header) + * @param dst destination ipv6 address (used for checksum of pseudo header) + * @param proto ipv6 protocol/next header (used for checksum of pseudo header) + * @param proto_len length of the ipv6 payload (used for checksum of pseudo header) + * @param chksum_len number of payload bytes used to compute chksum + * @return checksum (as u16_t) to be saved directly in the protocol header + */ +u16_t +ip6_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len, + u16_t chksum_len, ip6_addr_t *src, ip6_addr_t *dest) +{ + u32_t acc = 0; + u32_t addr; + u8_t addr_part; + + for (addr_part = 0; addr_part < 4; addr_part++) { + addr = src->addr[addr_part]; + acc += (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + addr = dest->addr[addr_part]; + acc += (addr & 0xffffUL); + acc += ((addr >> 16) & 0xffffUL); + } + /* fold down to 16 bits */ + acc = FOLD_U32T(acc); + acc = FOLD_U32T(acc); + + return inet_cksum_pseudo_partial_base(p, proto, proto_len, chksum_len, acc); +} +#endif /* LWIP_IPV6 */ + +/* inet_chksum: + * + * Calculates the Internet checksum over a portion of memory. Used primarily for IP + * and ICMP. + * + * @param dataptr start of the buffer to calculate the checksum (no alignment needed) + * @param len length of the buffer to calculate the checksum + * @return checksum (as u16_t) to be saved directly in the protocol header + */ + +u16_t +inet_chksum(void *dataptr, u16_t len) +{ + return ~LWIP_CHKSUM(dataptr, len); +} + +/** + * Calculate a checksum over a chain of pbufs (without pseudo-header, much like + * inet_chksum only pbufs are used). + * + * @param p pbuf chain over that the checksum should be calculated + * @return checksum (as u16_t) to be saved directly in the protocol header + */ +u16_t +inet_chksum_pbuf(struct pbuf *p) +{ + u32_t acc; + struct pbuf *q; + u8_t swapped; + + acc = 0; + swapped = 0; + for(q = p; q != NULL; q = q->next) { + acc += LWIP_CHKSUM(q->payload, q->len); + acc = FOLD_U32T(acc); + if (q->len % 2 != 0) { + swapped = 1 - swapped; + acc = SWAP_BYTES_IN_WORD(acc); + } + } + + if (swapped) { + acc = SWAP_BYTES_IN_WORD(acc); + } + return (u16_t)~(acc & 0xffffUL); +} + +/* These are some implementations for LWIP_CHKSUM_COPY, which copies data + * like MEMCPY but generates a checksum at the same time. Since this is a + * performance-sensitive function, you might want to create your own version + * in assembly targeted at your hardware by defining it in lwipopts.h: + * #define LWIP_CHKSUM_COPY(dst, src, len) your_chksum_copy(dst, src, len) + */ + +#if (LWIP_CHKSUM_COPY_ALGORITHM == 1) /* Version #1 */ +/** Safe but slow: first call MEMCPY, then call LWIP_CHKSUM. + * For architectures with big caches, data might still be in cache when + * generating the checksum after copying. + */ +u16_t +lwip_chksum_copy(void *dst, const void *src, u16_t len) +{ + MEMCPY(dst, src, len); + return LWIP_CHKSUM(dst, len); +} +#endif /* (LWIP_CHKSUM_COPY_ALGORITHM == 1) */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/core/init.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/init.c new file mode 100644 index 0000000..43e4c4a --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/init.c @@ -0,0 +1,349 @@ +/** + * @file + * Modules initialization + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/init.h" +#include "lwip/stats.h" +#include "lwip/sys.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/sockets.h" +#include "lwip/lwip_ip.h" +#include "lwip/raw.h" +#include "lwip/udp.h" +#include "lwip/tcp_impl.h" +#include "lwip/snmp_msg.h" +#include "lwip/autoip.h" +#include "lwip/igmp.h" +#include "lwip/dns.h" +#include "lwip/lwip_timers.h" // Evan modified timers.h to lwip_timers.h +#include "netif/etharp.h" +#include "lwip/ip6.h" +#include "lwip/nd6.h" +#include "lwip/mld6.h" +#include "lwip/api.h" +#include "netif/ppp/ppp_impl.h" + +/* Compile-time sanity checks for configuration errors. + * These can be done independently of LWIP_DEBUG, without penalty. + */ +#ifndef BYTE_ORDER + #error "BYTE_ORDER is not defined, you have to define it in your cc.h" +#endif +#if (!IP_SOF_BROADCAST && IP_SOF_BROADCAST_RECV) + #error "If you want to use broadcast filter per pcb on recv operations, you have to define IP_SOF_BROADCAST=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_UDPLITE) + #error "If you want to use UDP Lite, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_DHCP) + #error "If you want to use DHCP, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_IGMP) + #error "If you want to use IGMP, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_SNMP) + #error "If you want to use SNMP, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif +#if (!LWIP_UDP && LWIP_DNS) + #error "If you want to use DNS, you have to define LWIP_UDP=1 in your lwipopts.h" +#endif +#if !MEMP_MEM_MALLOC /* MEMP_NUM_* checks are disabled when not using the pool allocator */ +#if (LWIP_ARP && ARP_QUEUEING && (MEMP_NUM_ARP_QUEUE<=0)) + #error "If you want to use ARP Queueing, you have to define MEMP_NUM_ARP_QUEUE>=1 in your lwipopts.h" +#endif +#if (LWIP_RAW && (MEMP_NUM_RAW_PCB<=0)) + #error "If you want to use RAW, you have to define MEMP_NUM_RAW_PCB>=1 in your lwipopts.h" +#endif +#if (LWIP_UDP && (MEMP_NUM_UDP_PCB<=0)) + #error "If you want to use UDP, you have to define MEMP_NUM_UDP_PCB>=1 in your lwipopts.h" +#endif +#if (LWIP_TCP && (MEMP_NUM_TCP_PCB<=0)) + #error "If you want to use TCP, you have to define MEMP_NUM_TCP_PCB>=1 in your lwipopts.h" +#endif +#if (LWIP_IGMP && (MEMP_NUM_IGMP_GROUP<=1)) + #error "If you want to use IGMP, you have to define MEMP_NUM_IGMP_GROUP>1 in your lwipopts.h" +#endif +#if ((LWIP_NETCONN || LWIP_SOCKET) && (MEMP_NUM_TCPIP_MSG_API<=0)) + #error "If you want to use Sequential API, you have to define MEMP_NUM_TCPIP_MSG_API>=1 in your lwipopts.h" +#endif +/* There must be sufficient timeouts, taking into account requirements of the subsystems. */ +#if LWIP_TIMERS && (MEMP_NUM_SYS_TIMEOUT < (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + PPP_SUPPORT + (LWIP_IPV6 ? (1 + LWIP_IPV6_REASS + LWIP_IPV6_MLD) : 0))) + #error "MEMP_NUM_SYS_TIMEOUT is too low to accomodate all required timeouts" +#endif +#if (IP_REASSEMBLY && (MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS)) + #error "MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS doesn't make sense since each struct ip_reassdata must hold 2 pbufs at least!" +#endif +#endif /* !MEMP_MEM_MALLOC */ +#if LWIP_WND_SCALE +#if (LWIP_TCP && (TCP_WND > 0xffffffff)) + #error "If you want to use TCP, TCP_WND must fit in an u32_t, so, you have to reduce it in your lwipopts.h" +#endif +#if (LWIP_TCP && LWIP_WND_SCALE > 14) + #error "The maximum valid window scale value is 14!" +#endif +#if (LWIP_TCP && (TCP_WND > (0xFFFFU << TCP_RCV_SCALE))) + #error "TCP_WND is bigger than the configured LWIP_WND_SCALE allows!" +#endif +#if (LWIP_TCP && ((TCP_WND >> TCP_RCV_SCALE) == 0)) + #error "TCP_WND is too small for the configured LWIP_WND_SCALE (results in zero window)!" +#endif +#else /* LWIP_WND_SCALE */ +#if (LWIP_TCP && (TCP_WND > 0xffff)) + #error "If you want to use TCP, TCP_WND must fit in an u16_t, so, you have to reduce it in your lwipopts.h (or enable window scaling)" +#endif +#endif /* LWIP_WND_SCALE */ +#if (LWIP_TCP && (TCP_SND_QUEUELEN > 0xffff)) + #error "If you want to use TCP, TCP_SND_QUEUELEN must fit in an u16_t, so, you have to reduce it in your lwipopts.h" +#endif +#if (LWIP_TCP && (TCP_SND_QUEUELEN < 2)) + #error "TCP_SND_QUEUELEN must be at least 2 for no-copy TCP writes to work" +#endif +#if (LWIP_TCP && ((TCP_MAXRTX > 12) || (TCP_SYNMAXRTX > 12))) + #error "If you want to use TCP, TCP_MAXRTX and TCP_SYNMAXRTX must less or equal to 12 (due to tcp_backoff table), so, you have to reduce them in your lwipopts.h" +#endif +#if (LWIP_TCP && TCP_LISTEN_BACKLOG && ((TCP_DEFAULT_LISTEN_BACKLOG < 0) || (TCP_DEFAULT_LISTEN_BACKLOG > 0xff))) + #error "If you want to use TCP backlog, TCP_DEFAULT_LISTEN_BACKLOG must fit into an u8_t" +#endif +#if (LWIP_NETIF_API && (NO_SYS==1)) + #error "If you want to use NETIF API, you have to define NO_SYS=0 in your lwipopts.h" +#endif +#if ((LWIP_SOCKET || LWIP_NETCONN) && (NO_SYS==1)) + #error "If you want to use Sequential API, you have to define NO_SYS=0 in your lwipopts.h" +#endif +#if (LWIP_PPP_API && (NO_SYS==1)) + #error "If you want to use PPP API, you have to define NO_SYS=0 in your lwipopts.h" +#endif +#if (((!LWIP_DHCP) || (!LWIP_AUTOIP)) && LWIP_DHCP_AUTOIP_COOP) + #error "If you want to use DHCP/AUTOIP cooperation mode, you have to define LWIP_DHCP=1 and LWIP_AUTOIP=1 in your lwipopts.h" +#endif +#if (((!LWIP_DHCP) || (!LWIP_ARP)) && DHCP_DOES_ARP_CHECK) + #error "If you want to use DHCP ARP checking, you have to define LWIP_DHCP=1 and LWIP_ARP=1 in your lwipopts.h" +#endif +#if (!LWIP_ARP && LWIP_AUTOIP) + #error "If you want to use AUTOIP, you have to define LWIP_ARP=1 in your lwipopts.h" +#endif +#if (LWIP_SNMP && (SNMP_CONCURRENT_REQUESTS<=0)) + #error "If you want to use SNMP, you have to define SNMP_CONCURRENT_REQUESTS>=1 in your lwipopts.h" +#endif +#if (LWIP_SNMP && (SNMP_TRAP_DESTINATIONS<=0)) + #error "If you want to use SNMP, you have to define SNMP_TRAP_DESTINATIONS>=1 in your lwipopts.h" +#endif +#if (LWIP_TCP && ((LWIP_EVENT_API && LWIP_CALLBACK_API) || (!LWIP_EVENT_API && !LWIP_CALLBACK_API))) + #error "One and exactly one of LWIP_EVENT_API and LWIP_CALLBACK_API has to be enabled in your lwipopts.h" +#endif +#if (MEM_LIBC_MALLOC && MEM_USE_POOLS) + #error "MEM_LIBC_MALLOC and MEM_USE_POOLS may not both be simultaneously enabled in your lwipopts.h" +#endif +#if (MEM_USE_POOLS && !MEMP_USE_CUSTOM_POOLS) + #error "MEM_USE_POOLS requires custom pools (MEMP_USE_CUSTOM_POOLS) to be enabled in your lwipopts.h" +#endif +#if (PBUF_POOL_BUFSIZE <= MEM_ALIGNMENT) + #error "PBUF_POOL_BUFSIZE must be greater than MEM_ALIGNMENT or the offset may take the full first pbuf" +#endif +#if (DNS_LOCAL_HOSTLIST && !DNS_LOCAL_HOSTLIST_IS_DYNAMIC && !(defined(DNS_LOCAL_HOSTLIST_INIT))) + #error "you have to define define DNS_LOCAL_HOSTLIST_INIT {{'host1', 0x123}, {'host2', 0x234}} to initialize DNS_LOCAL_HOSTLIST" +#endif +#if PPP_SUPPORT && !PPPOS_SUPPORT && !PPPOE_SUPPORT + #error "PPP_SUPPORT needs either PPPOS_SUPPORT or PPPOE_SUPPORT turned on" +#endif +#if !LWIP_ETHERNET && (LWIP_ARP || PPPOE_SUPPORT) + #error "LWIP_ETHERNET needs to be turned on for LWIP_ARP or PPPOE_SUPPORT" +#endif +#if (LWIP_IGMP || LWIP_IPV6) && !defined(LWIP_RAND) + #error "When using IGMP or IPv6, LWIP_RAND() needs to be defined to a random-function returning an u32_t random value" +#endif +#if LWIP_TCPIP_CORE_LOCKING_INPUT && !LWIP_TCPIP_CORE_LOCKING + #error "When using LWIP_TCPIP_CORE_LOCKING_INPUT, LWIP_TCPIP_CORE_LOCKING must be enabled, too" +#endif +#if LWIP_TCP && LWIP_NETIF_TX_SINGLE_PBUF && !TCP_OVERSIZE + #error "LWIP_NETIF_TX_SINGLE_PBUF needs TCP_OVERSIZE enabled to create single-pbuf TCP packets" +#endif +#if IP_FRAG && IP_FRAG_USES_STATIC_BUF && LWIP_NETIF_TX_SINGLE_PBUF + #error "LWIP_NETIF_TX_SINGLE_PBUF does not work with IP_FRAG_USES_STATIC_BUF==1 as that creates pbuf queues" +#endif +#if LWIP_NETCONN && LWIP_TCP +#if NETCONN_COPY != TCP_WRITE_FLAG_COPY + #error "NETCONN_COPY != TCP_WRITE_FLAG_COPY" +#endif +#if NETCONN_MORE != TCP_WRITE_FLAG_MORE + #error "NETCONN_MORE != TCP_WRITE_FLAG_MORE" +#endif +#endif /* LWIP_NETCONN && LWIP_TCP */ +#if LWIP_SOCKET +/* Check that the SO_* socket options and SOF_* lwIP-internal flags match */ +#if SO_REUSEADDR != SOF_REUSEADDR + #error "WARNING: SO_REUSEADDR != SOF_REUSEADDR" +#endif +#if SO_KEEPALIVE != SOF_KEEPALIVE + #error "WARNING: SO_KEEPALIVE != SOF_KEEPALIVE" +#endif +#if SO_BROADCAST != SOF_BROADCAST + #error "WARNING: SO_BROADCAST != SOF_BROADCAST" +#endif +#endif /* LWIP_SOCKET */ + + +/* Compile-time checks for deprecated options. + */ +#ifdef MEMP_NUM_TCPIP_MSG + #error "MEMP_NUM_TCPIP_MSG option is deprecated. Remove it from your lwipopts.h." +#endif +#ifdef TCP_REXMIT_DEBUG + #error "TCP_REXMIT_DEBUG option is deprecated. Remove it from your lwipopts.h." +#endif +#ifdef RAW_STATS + #error "RAW_STATS option is deprecated. Remove it from your lwipopts.h." +#endif +#ifdef ETHARP_QUEUE_FIRST + #error "ETHARP_QUEUE_FIRST option is deprecated. Remove it from your lwipopts.h." +#endif +#ifdef ETHARP_ALWAYS_INSERT + #error "ETHARP_ALWAYS_INSERT option is deprecated. Remove it from your lwipopts.h." +#endif + +#ifndef LWIP_DISABLE_TCP_SANITY_CHECKS +#define LWIP_DISABLE_TCP_SANITY_CHECKS 0 +#endif +#ifndef LWIP_DISABLE_MEMP_SANITY_CHECKS +#define LWIP_DISABLE_MEMP_SANITY_CHECKS 0 +#endif + +/* MEMP sanity checks */ +#if !LWIP_DISABLE_MEMP_SANITY_CHECKS +#if LWIP_NETCONN +#if MEMP_MEM_MALLOC +#if !MEMP_NUM_NETCONN && LWIP_SOCKET +#error "lwip_sanity_check: WARNING: MEMP_NUM_NETCONN cannot be 0 when using sockets!" +#endif +#else /* MEMP_MEM_MALLOC */ +#if MEMP_NUM_NETCONN > (MEMP_NUM_TCP_PCB+MEMP_NUM_TCP_PCB_LISTEN+MEMP_NUM_UDP_PCB+MEMP_NUM_RAW_PCB) +#error "lwip_sanity_check: WARNING: MEMP_NUM_NETCONN should be less than the sum of MEMP_NUM_{TCP,RAW,UDP}_PCB+MEMP_NUM_TCP_PCB_LISTEN. If you know what you are doing, define LWIP_DISABLE_MEMP_SANITY_CHECKS to 1 to disable this error." +#endif +#endif /* MEMP_MEM_MALLOC */ +#endif /* LWIP_NETCONN */ +#endif /* !LWIP_DISABLE_MEMP_SANITY_CHECKS */ + +/* TCP sanity checks */ +#if !LWIP_DISABLE_TCP_SANITY_CHECKS +#if LWIP_TCP +#if !MEMP_MEM_MALLOC && (MEMP_NUM_TCP_SEG < TCP_SND_QUEUELEN) + #error "lwip_sanity_check: WARNING: MEMP_NUM_TCP_SEG should be at least as big as TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if TCP_SND_BUF < (2 * TCP_MSS) + #error "lwip_sanity_check: WARNING: TCP_SND_BUF must be at least as much as (2 * TCP_MSS) for things to work smoothly. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if TCP_SND_QUEUELEN < (2 * (TCP_SND_BUF / TCP_MSS)) + #error "lwip_sanity_check: WARNING: TCP_SND_QUEUELEN must be at least as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if TCP_SNDLOWAT >= TCP_SND_BUF + #error "lwip_sanity_check: WARNING: TCP_SNDLOWAT must be less than TCP_SND_BUF. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if TCP_SNDQUEUELOWAT >= TCP_SND_QUEUELEN + #error "lwip_sanity_check: WARNING: TCP_SNDQUEUELOWAT must be less than TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if !MEMP_MEM_MALLOC && (PBUF_POOL_BUFSIZE <= (PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)) + #error "lwip_sanity_check: WARNING: PBUF_POOL_BUFSIZE does not provide enough space for protocol headers. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if !MEMP_MEM_MALLOC && (TCP_WND > (PBUF_POOL_SIZE * (PBUF_POOL_BUFSIZE - (PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)))) + #error "lwip_sanity_check: WARNING: TCP_WND is larger than space provided by PBUF_POOL_SIZE * (PBUF_POOL_BUFSIZE - protocol headers). If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#if TCP_WND < TCP_MSS + #error "lwip_sanity_check: WARNING: TCP_WND is smaller than MSS. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." +#endif +#endif /* LWIP_TCP */ +#endif /* !LWIP_DISABLE_TCP_SANITY_CHECKS */ + +/** + * Perform Sanity check of user-configurable values, and initialize all modules. + */ +void +lwip_init(void) +{ + /* Modules initialization */ + stats_init(); +#if !NO_SYS + sys_init(); +#endif /* !NO_SYS */ + mem_init(); + memp_init(); + pbuf_init(); + netif_init(); + ip_init(); +#if LWIP_ARP + etharp_init(); +#endif /* LWIP_ARP */ +#if LWIP_RAW + raw_init(); +#endif /* LWIP_RAW */ +#if LWIP_UDP + udp_init(); +#endif /* LWIP_UDP */ +#if LWIP_TCP + tcp_init(); +#endif /* LWIP_TCP */ +#if LWIP_SNMP + snmp_init(); +#endif /* LWIP_SNMP */ +#if LWIP_AUTOIP + autoip_init(); +#endif /* LWIP_AUTOIP */ +#if LWIP_IGMP + igmp_init(); +#endif /* LWIP_IGMP */ +#if LWIP_DNS + dns_init(); +#endif /* LWIP_DNS */ +#if LWIP_IPV6 + ip6_init(); + nd6_init(); +#if LWIP_IPV6_MLD + mld6_init(); +#endif /* LWIP_IPV6_MLD */ +#endif /* LWIP_IPV6 */ +#if PPP_SUPPORT + ppp_init(); +#endif + +#if LWIP_TIMERS + sys_timeouts_init(); +#endif /* LWIP_TIMERS */ +} diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv4/autoip.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv4/autoip.c new file mode 100644 index 0000000..3052f6b --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv4/autoip.c @@ -0,0 +1,528 @@ +/** + * @file + * AutoIP Automatic LinkLocal IP Configuration + * + */ + +/* + * + * Copyright (c) 2007 Dominik Spies + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * Author: Dominik Spies + * + * This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform + * with RFC 3927. + * + * + * Please coordinate changes and requests with Dominik Spies + * + */ + +/******************************************************************************* + * USAGE: + * + * define LWIP_AUTOIP 1 in your lwipopts.h + * + * If you don't use tcpip.c (so, don't call, you don't call tcpip_init): + * - First, call autoip_init(). + * - call autoip_tmr() all AUTOIP_TMR_INTERVAL msces, + * that should be defined in autoip.h. + * I recommend a value of 100. The value must divide 1000 with a remainder almost 0. + * Possible values are 1000, 500, 333, 250, 200, 166, 142, 125, 111, 100 .... + * + * Without DHCP: + * - Call autoip_start() after netif_add(). + * + * With DHCP: + * - define LWIP_DHCP_AUTOIP_COOP 1 in your lwipopts.h. + * - Configure your DHCP Client. + * + */ + +#include "lwip/opt.h" + +#if LWIP_AUTOIP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/mem.h" +#include "lwip/udp.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/autoip.h" +#include "netif/etharp.h" + +#include +#include + +/* 169.254.0.0 */ +#define AUTOIP_NET 0xA9FE0000 +/* 169.254.1.0 */ +#define AUTOIP_RANGE_START (AUTOIP_NET | 0x0100) +/* 169.254.254.255 */ +#define AUTOIP_RANGE_END (AUTOIP_NET | 0xFEFF) + + +/** Pseudo random macro based on netif informations. + * You could use "rand()" from the C Library if you define LWIP_AUTOIP_RAND in lwipopts.h */ +#ifndef LWIP_AUTOIP_RAND +#define LWIP_AUTOIP_RAND(netif) ( (((u32_t)((netif->hwaddr[5]) & 0xff) << 24) | \ + ((u32_t)((netif->hwaddr[3]) & 0xff) << 16) | \ + ((u32_t)((netif->hwaddr[2]) & 0xff) << 8) | \ + ((u32_t)((netif->hwaddr[4]) & 0xff))) + \ + (netif->autoip?netif->autoip->tried_llipaddr:0)) +#endif /* LWIP_AUTOIP_RAND */ + +/** + * Macro that generates the initial IP address to be tried by AUTOIP. + * If you want to override this, define it to something else in lwipopts.h. + */ +#ifndef LWIP_AUTOIP_CREATE_SEED_ADDR +#define LWIP_AUTOIP_CREATE_SEED_ADDR(netif) \ + htonl(AUTOIP_RANGE_START + ((u32_t)(((u8_t)(netif->hwaddr[4])) | \ + ((u32_t)((u8_t)(netif->hwaddr[5]))) << 8))) +#endif /* LWIP_AUTOIP_CREATE_SEED_ADDR */ + +/* static functions */ +static void autoip_handle_arp_conflict(struct netif *netif); + +/* creates a pseudo random LL IP-Address for a network interface */ +static void autoip_create_addr(struct netif *netif, ip_addr_t *ipaddr); + +/* sends an ARP probe */ +static err_t autoip_arp_probe(struct netif *netif); + +/* sends an ARP announce */ +static err_t autoip_arp_announce(struct netif *netif); + +/* configure interface for use with current LL IP-Address */ +static err_t autoip_bind(struct netif *netif); + +/* start sending probes for llipaddr */ +static void autoip_start_probing(struct netif *netif); + + +/** Set a statically allocated struct autoip to work with. + * Using this prevents autoip_start to allocate it using mem_malloc. + * + * @param netif the netif for which to set the struct autoip + * @param dhcp (uninitialised) dhcp struct allocated by the application + */ +void +autoip_set_struct(struct netif *netif, struct autoip *autoip) +{ + LWIP_ASSERT("netif != NULL", netif != NULL); + LWIP_ASSERT("autoip != NULL", autoip != NULL); + LWIP_ASSERT("netif already has a struct autoip set", netif->autoip == NULL); + + /* clear data structure */ + memset(autoip, 0, sizeof(struct autoip)); + /* autoip->state = AUTOIP_STATE_OFF; */ + netif->autoip = autoip; +} + +/** Restart AutoIP client and check the next address (conflict detected) + * + * @param netif The netif under AutoIP control + */ +static void +autoip_restart(struct netif *netif) +{ + netif->autoip->tried_llipaddr++; + autoip_start(netif); +} + +/** + * Handle a IP address conflict after an ARP conflict detection + */ +static void +autoip_handle_arp_conflict(struct netif *netif) +{ + /* Somehow detect if we are defending or retreating */ + unsigned char defend = 1; /* tbd */ + + if (defend) { + if (netif->autoip->lastconflict > 0) { + /* retreat, there was a conflicting ARP in the last + * DEFEND_INTERVAL seconds + */ + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_handle_arp_conflict(): we are defending, but in DEFEND_INTERVAL, retreating\n")); + + /* TODO: close all TCP sessions */ + autoip_restart(netif); + } else { + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_handle_arp_conflict(): we are defend, send ARP Announce\n")); + autoip_arp_announce(netif); + netif->autoip->lastconflict = DEFEND_INTERVAL * AUTOIP_TICKS_PER_SECOND; + } + } else { + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_handle_arp_conflict(): we do not defend, retreating\n")); + /* TODO: close all TCP sessions */ + autoip_restart(netif); + } +} + +/** + * Create an IP-Address out of range 169.254.1.0 to 169.254.254.255 + * + * @param netif network interface on which create the IP-Address + * @param ipaddr ip address to initialize + */ +static void +autoip_create_addr(struct netif *netif, ip_addr_t *ipaddr) +{ + /* Here we create an IP-Address out of range 169.254.1.0 to 169.254.254.255 + * compliant to RFC 3927 Section 2.1 + * We have 254 * 256 possibilities */ + + u32_t addr = ntohl(LWIP_AUTOIP_CREATE_SEED_ADDR(netif)); + addr += netif->autoip->tried_llipaddr; + addr = AUTOIP_NET | (addr & 0xffff); + /* Now, 169.254.0.0 <= addr <= 169.254.255.255 */ + + if (addr < AUTOIP_RANGE_START) { + addr += AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1; + } + if (addr > AUTOIP_RANGE_END) { + addr -= AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1; + } + LWIP_ASSERT("AUTOIP address not in range", (addr >= AUTOIP_RANGE_START) && + (addr <= AUTOIP_RANGE_END)); + ip4_addr_set_u32(ipaddr, htonl(addr)); + + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_create_addr(): tried_llipaddr=%"U16_F", %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + (u16_t)(netif->autoip->tried_llipaddr), ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), + ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr))); +} + +/** + * Sends an ARP probe from a network interface + * + * @param netif network interface used to send the probe + */ +static err_t +autoip_arp_probe(struct netif *netif) +{ + return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, ðbroadcast, + (struct eth_addr *)netif->hwaddr, IP_ADDR_ANY, ðzero, + &netif->autoip->llipaddr, ARP_REQUEST); +} + +/** + * Sends an ARP announce from a network interface + * + * @param netif network interface used to send the announce + */ +static err_t +autoip_arp_announce(struct netif *netif) +{ + return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, ðbroadcast, + (struct eth_addr *)netif->hwaddr, &netif->autoip->llipaddr, ðzero, + &netif->autoip->llipaddr, ARP_REQUEST); +} + +/** + * Configure interface for use with current LL IP-Address + * + * @param netif network interface to configure with current LL IP-Address + */ +static err_t +autoip_bind(struct netif *netif) +{ + struct autoip *autoip = netif->autoip; + ip_addr_t sn_mask, gw_addr; + + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, + ("autoip_bind(netif=%p) %c%c%"U16_F" %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num, + ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr), + ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr))); + + IP4_ADDR(&sn_mask, 255, 255, 0, 0); + IP4_ADDR(&gw_addr, 0, 0, 0, 0); + + netif_set_ipaddr(netif, &autoip->llipaddr); + netif_set_netmask(netif, &sn_mask); + netif_set_gw(netif, &gw_addr); + + /* bring the interface up */ + netif_set_up(netif); + + return ERR_OK; +} + +/** + * Start AutoIP client + * + * @param netif network interface on which start the AutoIP client + */ +err_t +autoip_start(struct netif *netif) +{ + struct autoip *autoip = netif->autoip; + err_t result = ERR_OK; + + if (netif_is_up(netif)) { + netif_set_down(netif); + } + + /* Set IP-Address, Netmask and Gateway to 0 to make sure that + * ARP Packets are formed correctly + */ + ip_addr_set_zero(&netif->ip_addr); + ip_addr_set_zero(&netif->netmask); + ip_addr_set_zero(&netif->gw); + + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], + netif->name[1], (u16_t)netif->num)); + if (autoip == NULL) { + /* no AutoIP client attached yet? */ + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, + ("autoip_start(): starting new AUTOIP client\n")); + autoip = (struct autoip *)mem_malloc(sizeof(struct autoip)); + if (autoip == NULL) { + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, + ("autoip_start(): could not allocate autoip\n")); + return ERR_MEM; + } + memset(autoip, 0, sizeof(struct autoip)); + /* store this AutoIP client in the netif */ + netif->autoip = autoip; + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_start(): allocated autoip")); + } else { + autoip->state = AUTOIP_STATE_OFF; + autoip->ttw = 0; + autoip->sent_num = 0; + ip_addr_set_zero(&autoip->llipaddr); + autoip->lastconflict = 0; + } + + autoip_create_addr(netif, &(autoip->llipaddr)); + autoip_start_probing(netif); + + return result; +} + +static void +autoip_start_probing(struct netif *netif) +{ + struct autoip *autoip = netif->autoip; + + autoip->state = AUTOIP_STATE_PROBING; + autoip->sent_num = 0; + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_start_probing(): changing state to PROBING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(&netif->autoip->llipaddr), ip4_addr2_16(&netif->autoip->llipaddr), + ip4_addr3_16(&netif->autoip->llipaddr), ip4_addr4_16(&netif->autoip->llipaddr))); + + /* time to wait to first probe, this is randomly + * chosen out of 0 to PROBE_WAIT seconds. + * compliant to RFC 3927 Section 2.2.1 + */ + autoip->ttw = (u16_t)(LWIP_AUTOIP_RAND(netif) % (PROBE_WAIT * AUTOIP_TICKS_PER_SECOND)); + + /* + * if we tried more then MAX_CONFLICTS we must limit our rate for + * acquiring and probing address + * compliant to RFC 3927 Section 2.2.1 + */ + if (autoip->tried_llipaddr >= MAX_CONFLICTS) { + autoip->ttw = RATE_LIMIT_INTERVAL * AUTOIP_TICKS_PER_SECOND; + } +} + +/** + * Handle a possible change in the network configuration. + * + * If there is an AutoIP address configured, take the interface down + * and begin probing with the same address. + */ +void +autoip_network_changed(struct netif *netif) +{ + if (netif->autoip && netif->autoip->state != AUTOIP_STATE_OFF) { + netif_set_down(netif); + autoip_start_probing(netif); + } +} + +/** + * Stop AutoIP client + * + * @param netif network interface on which stop the AutoIP client + */ +err_t +autoip_stop(struct netif *netif) +{ + netif->autoip->state = AUTOIP_STATE_OFF; + netif_set_down(netif); + return ERR_OK; +} + +/** + * Has to be called in loop every AUTOIP_TMR_INTERVAL milliseconds + */ +void +autoip_tmr() +{ + struct netif *netif = netif_list; + /* loop through netif's */ + while (netif != NULL) { + /* only act on AutoIP configured interfaces */ + if (netif->autoip != NULL) { + if (netif->autoip->lastconflict > 0) { + netif->autoip->lastconflict--; + } + + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, + ("autoip_tmr() AutoIP-State: %"U16_F", ttw=%"U16_F"\n", + (u16_t)(netif->autoip->state), netif->autoip->ttw)); + + switch(netif->autoip->state) { + case AUTOIP_STATE_PROBING: + if (netif->autoip->ttw > 0) { + netif->autoip->ttw--; + } else { + if (netif->autoip->sent_num >= PROBE_NUM) { + netif->autoip->state = AUTOIP_STATE_ANNOUNCING; + netif->autoip->sent_num = 0; + netif->autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND; + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_tmr(): changing state to ANNOUNCING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(&netif->autoip->llipaddr), ip4_addr2_16(&netif->autoip->llipaddr), + ip4_addr3_16(&netif->autoip->llipaddr), ip4_addr4_16(&netif->autoip->llipaddr))); + } else { + autoip_arp_probe(netif); + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, + ("autoip_tmr() PROBING Sent Probe\n")); + netif->autoip->sent_num++; + /* calculate time to wait to next probe */ + netif->autoip->ttw = (u16_t)((LWIP_AUTOIP_RAND(netif) % + ((PROBE_MAX - PROBE_MIN) * AUTOIP_TICKS_PER_SECOND) ) + + PROBE_MIN * AUTOIP_TICKS_PER_SECOND); + } + } + break; + + case AUTOIP_STATE_ANNOUNCING: + if (netif->autoip->ttw > 0) { + netif->autoip->ttw--; + } else { + if (netif->autoip->sent_num == 0) { + /* We are here the first time, so we waited ANNOUNCE_WAIT seconds + * Now we can bind to an IP address and use it. + * + * autoip_bind calls netif_set_up. This triggers a gratuitous ARP + * which counts as an announcement. + */ + autoip_bind(netif); + } else { + autoip_arp_announce(netif); + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, + ("autoip_tmr() ANNOUNCING Sent Announce\n")); + } + netif->autoip->ttw = ANNOUNCE_INTERVAL * AUTOIP_TICKS_PER_SECOND; + netif->autoip->sent_num++; + + if (netif->autoip->sent_num >= ANNOUNCE_NUM) { + netif->autoip->state = AUTOIP_STATE_BOUND; + netif->autoip->sent_num = 0; + netif->autoip->ttw = 0; + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + ("autoip_tmr(): changing state to BOUND: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(&netif->autoip->llipaddr), ip4_addr2_16(&netif->autoip->llipaddr), + ip4_addr3_16(&netif->autoip->llipaddr), ip4_addr4_16(&netif->autoip->llipaddr))); + } + } + break; + } + } + /* proceed to next network interface */ + netif = netif->next; + } +} + +/** + * Handles every incoming ARP Packet, called by etharp_arp_input. + * + * @param netif network interface to use for autoip processing + * @param hdr Incoming ARP packet + */ +void +autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr) +{ + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_arp_reply()\n")); + if ((netif->autoip != NULL) && (netif->autoip->state != AUTOIP_STATE_OFF)) { + /* when ip.src == llipaddr && hw.src != netif->hwaddr + * + * when probing ip.dst == llipaddr && hw.src != netif->hwaddr + * we have a conflict and must solve it + */ + ip_addr_t sipaddr, dipaddr; + struct eth_addr netifaddr; + ETHADDR16_COPY(netifaddr.addr, netif->hwaddr); + + /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without + * structure packing (not using structure copy which breaks strict-aliasing rules). + */ + IPADDR2_COPY(&sipaddr, &hdr->sipaddr); + IPADDR2_COPY(&dipaddr, &hdr->dipaddr); + + if ((netif->autoip->state == AUTOIP_STATE_PROBING) || + ((netif->autoip->state == AUTOIP_STATE_ANNOUNCING) && + (netif->autoip->sent_num == 0))) { + /* RFC 3927 Section 2.2.1: + * from beginning to after ANNOUNCE_WAIT + * seconds we have a conflict if + * ip.src == llipaddr OR + * ip.dst == llipaddr && hw.src != own hwaddr + */ + if ((ip_addr_cmp(&sipaddr, &netif->autoip->llipaddr)) || + (ip_addr_cmp(&dipaddr, &netif->autoip->llipaddr) && + !eth_addr_cmp(&netifaddr, &hdr->shwaddr))) { + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING, + ("autoip_arp_reply(): Probe Conflict detected\n")); + autoip_restart(netif); + } + } else { + /* RFC 3927 Section 2.5: + * in any state we have a conflict if + * ip.src == llipaddr && hw.src != own hwaddr + */ + if (ip_addr_cmp(&sipaddr, &netif->autoip->llipaddr) && + !eth_addr_cmp(&netifaddr, &hdr->shwaddr)) { + LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING, + ("autoip_arp_reply(): Conflicting ARP-Packet detected\n")); + autoip_handle_arp_conflict(netif); + } + } + } +} + +#endif /* LWIP_AUTOIP */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv4/icmp.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv4/icmp.c new file mode 100644 index 0000000..cd8f652 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv4/icmp.c @@ -0,0 +1,339 @@ +/** + * @file + * ICMP - Internet Control Message Protocol + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/* Some ICMP messages should be passed to the transport protocols. This + is not implemented. */ + +#include "lwip/opt.h" + +#if LWIP_ICMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/icmp.h" +#include "lwip/inet_chksum.h" +#include "lwip/lwip_ip.h" +#include "lwip/def.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" + +#include + +/** Small optimization: set to 0 if incoming PBUF_POOL pbuf always can be + * used to modify and send a response packet (and to 1 if this is not the case, + * e.g. when link header is stripped of when receiving) */ +#ifndef LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN +#define LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN 1 +#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */ + +/* The amount of data from the original packet to return in a dest-unreachable */ +#define ICMP_DEST_UNREACH_DATASIZE 8 + +static void icmp_send_response(struct pbuf *p, u8_t type, u8_t code); + +/** + * Processes ICMP input packets, called from ip_input(). + * + * Currently only processes icmp echo requests and sends + * out the echo response. + * + * @param p the icmp echo request packet, p->payload pointing to the icmp header + * @param inp the netif on which this packet was received + */ +void +icmp_input(struct pbuf *p, struct netif *inp) +{ + u8_t type; +#ifdef LWIP_DEBUG + u8_t code; +#endif /* LWIP_DEBUG */ + struct icmp_echo_hdr *iecho; + struct ip_hdr *iphdr; + s16_t hlen; + + ICMP_STATS_INC(icmp.recv); + snmp_inc_icmpinmsgs(); + + iphdr = (struct ip_hdr *)ip_current_header(); + hlen = IPH_HL(iphdr) * 4; + if (p->len < sizeof(u16_t)*2) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%"U16_F" bytes) received\n", p->tot_len)); + goto lenerr; + } + + type = *((u8_t *)p->payload); +#ifdef LWIP_DEBUG + code = *(((u8_t *)p->payload)+1); +#endif /* LWIP_DEBUG */ + switch (type) { + case ICMP_ER: + /* This is OK, echo reply might have been parsed by a raw PCB + (as obviously, an echo request has been sent, too). */ + break; + case ICMP_ECHO: +#if !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING + { + int accepted = 1; +#if !LWIP_MULTICAST_PING + /* multicast destination address? */ + if (ip_addr_ismulticast(ip_current_dest_addr())) { + accepted = 0; + } +#endif /* LWIP_MULTICAST_PING */ +#if !LWIP_BROADCAST_PING + /* broadcast destination address? */ + if (ip_addr_isbroadcast(ip_current_dest_addr(), inp)) { + accepted = 0; + } +#endif /* LWIP_BROADCAST_PING */ + /* broadcast or multicast destination address not accepted? */ + if (!accepted) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to multicast or broadcast pings\n")); + ICMP_STATS_INC(icmp.err); + pbuf_free(p); + return; + } + } +#endif /* !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING */ + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ping\n")); + if (p->tot_len < sizeof(struct icmp_echo_hdr)) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n")); + goto lenerr; + } +#if CHECKSUM_CHECK_ICMP + if (inet_chksum_pbuf(p) != 0) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo\n")); + pbuf_free(p); + ICMP_STATS_INC(icmp.chkerr); + snmp_inc_icmpinerrors(); + return; + } +#endif +#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN + if (pbuf_header(p, (PBUF_IP_HLEN + PBUF_LINK_HLEN))) { + /* p is not big enough to contain link headers + * allocate a new one and copy p into it + */ + struct pbuf *r; + /* allocate new packet buffer with space for link headers */ + r = pbuf_alloc(PBUF_LINK, p->tot_len + hlen, PBUF_RAM); + if (r == NULL) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: allocating new pbuf failed\n")); + goto memerr; + } + LWIP_ASSERT("check that first pbuf can hold struct the ICMP header", + (r->len >= hlen + sizeof(struct icmp_echo_hdr))); + /* copy the ip header */ + MEMCPY(r->payload, iphdr, hlen); + iphdr = (struct ip_hdr *)r->payload; + /* switch r->payload back to icmp header */ + if (pbuf_header(r, -hlen)) { + LWIP_ASSERT("icmp_input: moving r->payload to icmp header failed\n", 0); + goto memerr; + } + /* copy the rest of the packet without ip header */ + if (pbuf_copy(r, p) != ERR_OK) { + LWIP_ASSERT("icmp_input: copying to new pbuf failed\n", 0); + goto memerr; + } + /* free the original p */ + pbuf_free(p); + /* we now have an identical copy of p that has room for link headers */ + p = r; + } else { + /* restore p->payload to point to icmp header */ + if (pbuf_header(p, -(s16_t)(PBUF_IP_HLEN + PBUF_LINK_HLEN))) { + LWIP_ASSERT("icmp_input: restoring original p->payload failed\n", 0); + goto memerr; + } + } +#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */ + /* At this point, all checks are OK. */ + /* We generate an answer by switching the dest and src ip addresses, + * setting the icmp type to ECHO_RESPONSE and updating the checksum. */ + iecho = (struct icmp_echo_hdr *)p->payload; + ip_addr_copy(iphdr->src, *ip_current_dest_addr()); + ip_addr_copy(iphdr->dest, *ip_current_src_addr()); + ICMPH_TYPE_SET(iecho, ICMP_ER); +#if CHECKSUM_GEN_ICMP + /* adjust the checksum */ + if (iecho->chksum >= PP_HTONS(0xffffU - (ICMP_ECHO << 8))) { + iecho->chksum += PP_HTONS(ICMP_ECHO << 8) + 1; + } else { + iecho->chksum += PP_HTONS(ICMP_ECHO << 8); + } +#else /* CHECKSUM_GEN_ICMP */ + iecho->chksum = 0; +#endif /* CHECKSUM_GEN_ICMP */ + + /* Set the correct TTL and recalculate the header checksum. */ + IPH_TTL_SET(iphdr, ICMP_TTL); + IPH_CHKSUM_SET(iphdr, 0); +#if CHECKSUM_GEN_IP + IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN)); +#endif /* CHECKSUM_GEN_IP */ + + ICMP_STATS_INC(icmp.xmit); + /* increase number of messages attempted to send */ + snmp_inc_icmpoutmsgs(); + /* increase number of echo replies attempted to send */ + snmp_inc_icmpoutechoreps(); + + if(pbuf_header(p, hlen)) { + LWIP_ASSERT("Can't move over header in packet", 0); + } else { + err_t ret; + /* send an ICMP packet, src addr is the dest addr of the current packet */ + ret = ip_output_if(p, ip_current_dest_addr(), IP_HDRINCL, + ICMP_TTL, 0, IP_PROTO_ICMP, inp); + if (ret != ERR_OK) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ip_output_if returned an error: %c.\n", ret)); + } + } + break; + default: + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %"S16_F" code %"S16_F" not supported.\n", + (s16_t)type, (s16_t)code)); + ICMP_STATS_INC(icmp.proterr); + ICMP_STATS_INC(icmp.drop); + } + pbuf_free(p); + return; +lenerr: + pbuf_free(p); + ICMP_STATS_INC(icmp.lenerr); + snmp_inc_icmpinerrors(); + return; +#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN +memerr: + pbuf_free(p); + ICMP_STATS_INC(icmp.err); + snmp_inc_icmpinerrors(); + return; +#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */ +} + +/** + * Send an icmp 'destination unreachable' packet, called from ip_input() if + * the transport layer protocol is unknown and from udp_input() if the local + * port is not bound. + * + * @param p the input packet for which the 'unreachable' should be sent, + * p->payload pointing to the IP header + * @param t type of the 'unreachable' packet + */ +void +icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t) +{ + icmp_send_response(p, ICMP_DUR, t); +} + +#if IP_FORWARD || IP_REASSEMBLY +/** + * Send a 'time exceeded' packet, called from ip_forward() if TTL is 0. + * + * @param p the input packet for which the 'time exceeded' should be sent, + * p->payload pointing to the IP header + * @param t type of the 'time exceeded' packet + */ +void +icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t) +{ + icmp_send_response(p, ICMP_TE, t); +} + +#endif /* IP_FORWARD || IP_REASSEMBLY */ + +/** + * Send an icmp packet in response to an incoming packet. + * + * @param p the input packet for which the 'unreachable' should be sent, + * p->payload pointing to the IP header + * @param type Type of the ICMP header + * @param code Code of the ICMP header + */ +static void +icmp_send_response(struct pbuf *p, u8_t type, u8_t code) +{ + struct pbuf *q; + struct ip_hdr *iphdr; + /* we can use the echo header here */ + struct icmp_echo_hdr *icmphdr; + ip_addr_t iphdr_src; + + /* ICMP header + IP header + 8 bytes of data */ + q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE, + PBUF_RAM); + if (q == NULL) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMP packet.\n")); + return; + } + LWIP_ASSERT("check that first pbuf can hold icmp message", + (q->len >= (sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE))); + + iphdr = (struct ip_hdr *)p->payload; + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from ")); + ip_addr_debug_print(ICMP_DEBUG, &(iphdr->src)); + LWIP_DEBUGF(ICMP_DEBUG, (" to ")); + ip_addr_debug_print(ICMP_DEBUG, &(iphdr->dest)); + LWIP_DEBUGF(ICMP_DEBUG, ("\n")); + + icmphdr = (struct icmp_echo_hdr *)q->payload; + icmphdr->type = type; + icmphdr->code = code; + icmphdr->id = 0; + icmphdr->seqno = 0; + + /* copy fields from original packet */ + SMEMCPY((u8_t *)q->payload + sizeof(struct icmp_echo_hdr), (u8_t *)p->payload, + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE); + + /* calculate checksum */ + icmphdr->chksum = 0; +#if CHECKSUM_GEN_ICMP + icmphdr->chksum = inet_chksum(icmphdr, q->len); +#endif + ICMP_STATS_INC(icmp.xmit); + /* increase number of messages attempted to send */ + snmp_inc_icmpoutmsgs(); + /* increase number of destination unreachable messages attempted to send */ + snmp_inc_icmpouttimeexcds(); + ip_addr_copy(iphdr_src, iphdr->src); + ip_output(q, NULL, &iphdr_src, ICMP_TTL, 0, IP_PROTO_ICMP); + pbuf_free(q); +} + +#endif /* LWIP_ICMP */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv4/igmp.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv4/igmp.c new file mode 100644 index 0000000..0d09a8c --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv4/igmp.c @@ -0,0 +1,816 @@ +/** + * @file + * IGMP - Internet Group Management Protocol + * + */ + +/* + * Copyright (c) 2002 CITEL Technologies Ltd. + * 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 CITEL Technologies Ltd 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 CITEL TECHNOLOGIES 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 CITEL TECHNOLOGIES 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. + * + * This file is a contribution to the lwIP TCP/IP stack. + * The Swedish Institute of Computer Science and Adam Dunkels + * are specifically granted permission to redistribute this + * source code. +*/ + +/*------------------------------------------------------------- +Note 1) +Although the rfc requires V1 AND V2 capability +we will only support v2 since now V1 is very old (August 1989) +V1 can be added if required + +a debug print and statistic have been implemented to +show this up. +------------------------------------------------------------- +------------------------------------------------------------- +Note 2) +A query for a specific group address (as opposed to ALLHOSTS) +has now been implemented as I am unsure if it is required + +a debug print and statistic have been implemented to +show this up. +------------------------------------------------------------- +------------------------------------------------------------- +Note 3) +The router alert rfc 2113 is implemented in outgoing packets +but not checked rigorously incoming +------------------------------------------------------------- +Steve Reynolds +------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------- + * RFC 988 - Host extensions for IP multicasting - V0 + * RFC 1054 - Host extensions for IP multicasting - + * RFC 1112 - Host extensions for IP multicasting - V1 + * RFC 2236 - Internet Group Management Protocol, Version 2 - V2 <- this code is based on this RFC (it's the "de facto" standard) + * RFC 3376 - Internet Group Management Protocol, Version 3 - V3 + * RFC 4604 - Using Internet Group Management Protocol Version 3... - V3+ + * RFC 2113 - IP Router Alert Option - + *----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------- + * Includes + *----------------------------------------------------------------------------*/ + +#include "lwip/opt.h" + +#if LWIP_IGMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/igmp.h" +#include "lwip/debug.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/lwip_ip.h" +#include "lwip/inet_chksum.h" +#include "lwip/netif.h" +#include "lwip/icmp.h" +#include "lwip/udp.h" +#include "lwip/tcp.h" +#include "lwip/stats.h" + +#include "string.h" + +/* + * IGMP constants + */ +#define IGMP_TTL 1 +#define IGMP_MINLEN 8 +#define ROUTER_ALERT 0x9404U +#define ROUTER_ALERTLEN 4 + +/* + * IGMP message types, including version number. + */ +#define IGMP_MEMB_QUERY 0x11 /* Membership query */ +#define IGMP_V1_MEMB_REPORT 0x12 /* Ver. 1 membership report */ +#define IGMP_V2_MEMB_REPORT 0x16 /* Ver. 2 membership report */ +#define IGMP_LEAVE_GROUP 0x17 /* Leave-group message */ + +/* Group membership states */ +#define IGMP_GROUP_NON_MEMBER 0 +#define IGMP_GROUP_DELAYING_MEMBER 1 +#define IGMP_GROUP_IDLE_MEMBER 2 + +/** + * IGMP packet format. + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct igmp_msg { + PACK_STRUCT_FLD_8(u8_t igmp_msgtype); + PACK_STRUCT_FLD_8(u8_t igmp_maxresp); + PACK_STRUCT_FIELD(u16_t igmp_checksum); + PACK_STRUCT_FLD_S(ip_addr_p_t igmp_group_address); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + + +static struct igmp_group *igmp_lookup_group(struct netif *ifp, ip_addr_t *addr); +static err_t igmp_remove_group(struct igmp_group *group); +static void igmp_timeout( struct igmp_group *group); +static void igmp_start_timer(struct igmp_group *group, u8_t max_time); +static void igmp_delaying_member(struct igmp_group *group, u8_t maxresp); +static err_t igmp_ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, struct netif *netif); +static void igmp_send(struct igmp_group *group, u8_t type); + + +static struct igmp_group* igmp_group_list; +static ip_addr_t allsystems; +static ip_addr_t allrouters; + + +/** + * Initialize the IGMP module + */ +void +igmp_init(void) +{ + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_init: initializing\n")); + + IP4_ADDR(&allsystems, 224, 0, 0, 1); + IP4_ADDR(&allrouters, 224, 0, 0, 2); +} + +#ifdef LWIP_DEBUG +/** + * Dump global IGMP groups list + */ +void +igmp_dump_group_list() +{ + struct igmp_group *group = igmp_group_list; + + while (group != NULL) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_dump_group_list: [%"U32_F"] ", (u32_t)(group->group_state))); + ip_addr_debug_print(IGMP_DEBUG, &group->group_address); + LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", group->netif)); + group = group->next; + } + LWIP_DEBUGF(IGMP_DEBUG, ("\n")); +} +#else +#define igmp_dump_group_list() +#endif /* LWIP_DEBUG */ + +/** + * Start IGMP processing on interface + * + * @param netif network interface on which start IGMP processing + */ +err_t +igmp_start(struct netif *netif) +{ + struct igmp_group* group; + + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_start: starting IGMP processing on if %p\n", netif)); + + group = igmp_lookup_group(netif, &allsystems); + + if (group != NULL) { + group->group_state = IGMP_GROUP_IDLE_MEMBER; + group->use++; + + /* Allow the igmp messages at the MAC level */ + if (netif->igmp_mac_filter != NULL) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_start: igmp_mac_filter(ADD ")); + ip_addr_debug_print(IGMP_DEBUG, &allsystems); + LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif)); + netif->igmp_mac_filter(netif, &allsystems, IGMP_ADD_MAC_FILTER); + } + + return ERR_OK; + } + + return ERR_MEM; +} + +/** + * Stop IGMP processing on interface + * + * @param netif network interface on which stop IGMP processing + */ +err_t +igmp_stop(struct netif *netif) +{ + struct igmp_group *group = igmp_group_list; + struct igmp_group *prev = NULL; + struct igmp_group *next; + + /* look for groups joined on this interface further down the list */ + while (group != NULL) { + next = group->next; + /* is it a group joined on this interface? */ + if (group->netif == netif) { + /* is it the first group of the list? */ + if (group == igmp_group_list) { + igmp_group_list = next; + } + /* is there a "previous" group defined? */ + if (prev != NULL) { + prev->next = next; + } + /* disable the group at the MAC level */ + if (netif->igmp_mac_filter != NULL) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_stop: igmp_mac_filter(DEL ")); + ip_addr_debug_print(IGMP_DEBUG, &group->group_address); + LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif)); + netif->igmp_mac_filter(netif, &(group->group_address), IGMP_DEL_MAC_FILTER); + } + /* free group */ + memp_free(MEMP_IGMP_GROUP, group); + } else { + /* change the "previous" */ + prev = group; + } + /* move to "next" */ + group = next; + } + return ERR_OK; +} + +/** + * Report IGMP memberships for this interface + * + * @param netif network interface on which report IGMP memberships + */ +void +igmp_report_groups(struct netif *netif) +{ + struct igmp_group *group = igmp_group_list; + + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_report_groups: sending IGMP reports on if %p\n", netif)); + + while (group != NULL) { + if ((group->netif == netif) && (!(ip_addr_cmp(&(group->group_address), &allsystems)))) { + igmp_delaying_member(group, IGMP_JOIN_DELAYING_MEMBER_TMR); + } + group = group->next; + } +} + +/** + * Search for a group in the global igmp_group_list + * + * @param ifp the network interface for which to look + * @param addr the group ip address to search for + * @return a struct igmp_group* if the group has been found, + * NULL if the group wasn't found. + */ +struct igmp_group * +igmp_lookfor_group(struct netif *ifp, ip_addr_t *addr) +{ + struct igmp_group *group = igmp_group_list; + + while (group != NULL) { + if ((group->netif == ifp) && (ip_addr_cmp(&(group->group_address), addr))) { + return group; + } + group = group->next; + } + + /* to be clearer, we return NULL here instead of + * 'group' (which is also NULL at this point). + */ + return NULL; +} + +/** + * Search for a specific igmp group and create a new one if not found- + * + * @param ifp the network interface for which to look + * @param addr the group ip address to search + * @return a struct igmp_group*, + * NULL on memory error. + */ +struct igmp_group * +igmp_lookup_group(struct netif *ifp, ip_addr_t *addr) +{ + struct igmp_group *group = igmp_group_list; + + /* Search if the group already exists */ + group = igmp_lookfor_group(ifp, addr); + if (group != NULL) { + /* Group already exists. */ + return group; + } + + /* Group doesn't exist yet, create a new one */ + group = (struct igmp_group *)memp_malloc(MEMP_IGMP_GROUP); + if (group != NULL) { + group->netif = ifp; + ip_addr_set(&(group->group_address), addr); + group->timer = 0; /* Not running */ + group->group_state = IGMP_GROUP_NON_MEMBER; + group->last_reporter_flag = 0; + group->use = 0; + group->next = igmp_group_list; + + igmp_group_list = group; + } + + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_lookup_group: %sallocated a new group with address ", (group?"":"impossible to "))); + ip_addr_debug_print(IGMP_DEBUG, addr); + LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", ifp)); + + return group; +} + +/** + * Remove a group in the global igmp_group_list + * + * @param group the group to remove from the global igmp_group_list + * @return ERR_OK if group was removed from the list, an err_t otherwise + */ +static err_t +igmp_remove_group(struct igmp_group *group) +{ + err_t err = ERR_OK; + + /* Is it the first group? */ + if (igmp_group_list == group) { + igmp_group_list = group->next; + } else { + /* look for group further down the list */ + struct igmp_group *tmpGroup; + for (tmpGroup = igmp_group_list; tmpGroup != NULL; tmpGroup = tmpGroup->next) { + if (tmpGroup->next == group) { + tmpGroup->next = group->next; + break; + } + } + /* Group not found in the global igmp_group_list */ + if (tmpGroup == NULL) + err = ERR_ARG; + } + /* free group */ + memp_free(MEMP_IGMP_GROUP, group); + + return err; +} + +/** + * Called from ip_input() if a new IGMP packet is received. + * + * @param p received igmp packet, p->payload pointing to the igmp header + * @param inp network interface on which the packet was received + * @param dest destination ip address of the igmp packet + */ +void +igmp_input(struct pbuf *p, struct netif *inp, ip_addr_t *dest) +{ + struct igmp_msg* igmp; + struct igmp_group* group; + struct igmp_group* groupref; + + IGMP_STATS_INC(igmp.recv); + + /* Note that the length CAN be greater than 8 but only 8 are used - All are included in the checksum */ + if (p->len < IGMP_MINLEN) { + pbuf_free(p); + IGMP_STATS_INC(igmp.lenerr); + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: length error\n")); + return; + } + + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: message from ")); + ip_addr_debug_print(IGMP_DEBUG, &(ip_current_header()->src)); + LWIP_DEBUGF(IGMP_DEBUG, (" to address ")); + ip_addr_debug_print(IGMP_DEBUG, &(ip_current_header()->dest)); + LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", inp)); + + /* Now calculate and check the checksum */ + igmp = (struct igmp_msg *)p->payload; + if (inet_chksum(igmp, p->len)) { + pbuf_free(p); + IGMP_STATS_INC(igmp.chkerr); + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: checksum error\n")); + return; + } + + /* Packet is ok so find an existing group */ + group = igmp_lookfor_group(inp, dest); /* use the destination IP address of incoming packet */ + + /* If group can be found or create... */ + if (!group) { + pbuf_free(p); + IGMP_STATS_INC(igmp.drop); + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP frame not for us\n")); + return; + } + + /* NOW ACT ON THE INCOMING MESSAGE TYPE... */ + switch (igmp->igmp_msgtype) { + case IGMP_MEMB_QUERY: { + /* IGMP_MEMB_QUERY to the "all systems" address ? */ + if ((ip_addr_cmp(dest, &allsystems)) && ip_addr_isany(&igmp->igmp_group_address)) { + /* THIS IS THE GENERAL QUERY */ + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: General IGMP_MEMB_QUERY on \"ALL SYSTEMS\" address (224.0.0.1) [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp))); + + if (igmp->igmp_maxresp == 0) { + IGMP_STATS_INC(igmp.rx_v1); + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: got an all hosts query with time== 0 - this is V1 and not implemented - treat as v2\n")); + igmp->igmp_maxresp = IGMP_V1_DELAYING_MEMBER_TMR; + } else { + IGMP_STATS_INC(igmp.rx_general); + } + + groupref = igmp_group_list; + while (groupref) { + /* Do not send messages on the all systems group address! */ + if ((groupref->netif == inp) && (!(ip_addr_cmp(&(groupref->group_address), &allsystems)))) { + igmp_delaying_member(groupref, igmp->igmp_maxresp); + } + groupref = groupref->next; + } + } else { + /* IGMP_MEMB_QUERY to a specific group ? */ + if (!ip_addr_isany(&igmp->igmp_group_address)) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP_MEMB_QUERY to a specific group ")); + ip_addr_debug_print(IGMP_DEBUG, &igmp->igmp_group_address); + if (ip_addr_cmp(dest, &allsystems)) { + ip_addr_t groupaddr; + LWIP_DEBUGF(IGMP_DEBUG, (" using \"ALL SYSTEMS\" address (224.0.0.1) [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp))); + /* we first need to re-look for the group since we used dest last time */ + ip_addr_copy(groupaddr, igmp->igmp_group_address); + group = igmp_lookfor_group(inp, &groupaddr); + } else { + LWIP_DEBUGF(IGMP_DEBUG, (" with the group address as destination [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp))); + } + + if (group != NULL) { + IGMP_STATS_INC(igmp.rx_group); + igmp_delaying_member(group, igmp->igmp_maxresp); + } else { + IGMP_STATS_INC(igmp.drop); + } + } else { + IGMP_STATS_INC(igmp.proterr); + } + } + break; + } + case IGMP_V2_MEMB_REPORT: { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP_V2_MEMB_REPORT\n")); + IGMP_STATS_INC(igmp.rx_report); + if (group->group_state == IGMP_GROUP_DELAYING_MEMBER) { + /* This is on a specific group we have already looked up */ + group->timer = 0; /* stopped */ + group->group_state = IGMP_GROUP_IDLE_MEMBER; + group->last_reporter_flag = 0; + } + break; + } + default: { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: unexpected msg %d in state %d on group %p on if %p\n", + igmp->igmp_msgtype, group->group_state, &group, group->netif)); + IGMP_STATS_INC(igmp.proterr); + break; + } + } + + pbuf_free(p); + return; +} + +/** + * Join a group on one network interface. + * + * @param ifaddr ip address of the network interface which should join a new group + * @param groupaddr the ip address of the group which to join + * @return ERR_OK if group was joined on the netif(s), an err_t otherwise + */ +err_t +igmp_joingroup(ip_addr_t *ifaddr, ip_addr_t *groupaddr) +{ + err_t err = ERR_VAL; /* no matching interface */ + struct igmp_group *group; + struct netif *netif; + + /* make sure it is multicast address */ + LWIP_ERROR("igmp_joingroup: attempt to join non-multicast address", ip_addr_ismulticast(groupaddr), return ERR_VAL;); + LWIP_ERROR("igmp_joingroup: attempt to join allsystems address", (!ip_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;); + + /* loop through netif's */ + netif = netif_list; + while (netif != NULL) { + /* Should we join this interface ? */ + if ((netif->flags & NETIF_FLAG_IGMP) && ((ip_addr_isany(ifaddr) || ip_addr_cmp(&(netif->ip_addr), ifaddr)))) { + /* find group or create a new one if not found */ + group = igmp_lookup_group(netif, groupaddr); + + if (group != NULL) { + /* This should create a new group, check the state to make sure */ + if (group->group_state != IGMP_GROUP_NON_MEMBER) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: join to group not in state IGMP_GROUP_NON_MEMBER\n")); + } else { + /* OK - it was new group */ + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: join to new group: ")); + ip_addr_debug_print(IGMP_DEBUG, groupaddr); + LWIP_DEBUGF(IGMP_DEBUG, ("\n")); + + /* If first use of the group, allow the group at the MAC level */ + if ((group->use==0) && (netif->igmp_mac_filter != NULL)) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: igmp_mac_filter(ADD ")); + ip_addr_debug_print(IGMP_DEBUG, groupaddr); + LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif)); + netif->igmp_mac_filter(netif, groupaddr, IGMP_ADD_MAC_FILTER); + } + + IGMP_STATS_INC(igmp.tx_join); + igmp_send(group, IGMP_V2_MEMB_REPORT); + + igmp_start_timer(group, IGMP_JOIN_DELAYING_MEMBER_TMR); + + /* Need to work out where this timer comes from */ + group->group_state = IGMP_GROUP_DELAYING_MEMBER; + } + /* Increment group use */ + group->use++; + /* Join on this interface */ + err = ERR_OK; + } else { + /* Return an error even if some network interfaces are joined */ + /** @todo undo any other netif already joined */ + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: Not enough memory to join to group\n")); + return ERR_MEM; + } + } + /* proceed to next network interface */ + netif = netif->next; + } + + return err; +} + +/** + * Leave a group on one network interface. + * + * @param ifaddr ip address of the network interface which should leave a group + * @param groupaddr the ip address of the group which to leave + * @return ERR_OK if group was left on the netif(s), an err_t otherwise + */ +err_t +igmp_leavegroup(ip_addr_t *ifaddr, ip_addr_t *groupaddr) +{ + err_t err = ERR_VAL; /* no matching interface */ + struct igmp_group *group; + struct netif *netif; + + /* make sure it is multicast address */ + LWIP_ERROR("igmp_leavegroup: attempt to leave non-multicast address", ip_addr_ismulticast(groupaddr), return ERR_VAL;); + LWIP_ERROR("igmp_leavegroup: attempt to leave allsystems address", (!ip_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;); + + /* loop through netif's */ + netif = netif_list; + while (netif != NULL) { + /* Should we leave this interface ? */ + if ((netif->flags & NETIF_FLAG_IGMP) && ((ip_addr_isany(ifaddr) || ip_addr_cmp(&(netif->ip_addr), ifaddr)))) { + /* find group */ + group = igmp_lookfor_group(netif, groupaddr); + + if (group != NULL) { + /* Only send a leave if the flag is set according to the state diagram */ + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: Leaving group: ")); + ip_addr_debug_print(IGMP_DEBUG, groupaddr); + LWIP_DEBUGF(IGMP_DEBUG, ("\n")); + + /* If there is no other use of the group */ + if (group->use <= 1) { + /* If we are the last reporter for this group */ + if (group->last_reporter_flag) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: sending leaving group\n")); + IGMP_STATS_INC(igmp.tx_leave); + igmp_send(group, IGMP_LEAVE_GROUP); + } + + /* Disable the group at the MAC level */ + if (netif->igmp_mac_filter != NULL) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: igmp_mac_filter(DEL ")); + ip_addr_debug_print(IGMP_DEBUG, groupaddr); + LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif)); + netif->igmp_mac_filter(netif, groupaddr, IGMP_DEL_MAC_FILTER); + } + + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: remove group: ")); + ip_addr_debug_print(IGMP_DEBUG, groupaddr); + LWIP_DEBUGF(IGMP_DEBUG, ("\n")); + + /* Free the group */ + igmp_remove_group(group); + } else { + /* Decrement group use */ + group->use--; + } + /* Leave on this interface */ + err = ERR_OK; + } else { + /* It's not a fatal error on "leavegroup" */ + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: not member of group\n")); + } + } + /* proceed to next network interface */ + netif = netif->next; + } + + return err; +} + +/** + * The igmp timer function (both for NO_SYS=1 and =0) + * Should be called every IGMP_TMR_INTERVAL milliseconds (100 ms is default). + */ +void +igmp_tmr(void) +{ + struct igmp_group *group = igmp_group_list; + + while (group != NULL) { + if (group->timer > 0) { + group->timer--; + if (group->timer == 0) { + igmp_timeout(group); + } + } + group = group->next; + } +} + +/** + * Called if a timeout for one group is reached. + * Sends a report for this group. + * + * @param group an igmp_group for which a timeout is reached + */ +static void +igmp_timeout(struct igmp_group *group) +{ + /* If the state is IGMP_GROUP_DELAYING_MEMBER then we send a report for this group + (unless it is the allsystems group) */ + if ((group->group_state == IGMP_GROUP_DELAYING_MEMBER) && + (!(ip_addr_cmp(&(group->group_address), &allsystems)))) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_timeout: report membership for group with address ")); + ip_addr_debug_print(IGMP_DEBUG, &(group->group_address)); + LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", group->netif)); + + IGMP_STATS_INC(igmp.tx_report); + igmp_send(group, IGMP_V2_MEMB_REPORT); + } +} + +/** + * Start a timer for an igmp group + * + * @param group the igmp_group for which to start a timer + * @param max_time the time in multiples of IGMP_TMR_INTERVAL (decrease with + * every call to igmp_tmr()) + */ +static void +igmp_start_timer(struct igmp_group *group, u8_t max_time) +{ + /* ensure the input value is > 0 */ +#ifdef LWIP_RAND + if (max_time == 0) { + max_time = 1; + } + /* ensure the random value is > 0 */ + group->timer = (LWIP_RAND() % max_time); + if (group->timer == 0) { + group->timer = 1; + } +#else /* LWIP_RAND */ + /* ATTENTION: use this only if absolutely necessary! */ + group->timer = max_time / 2; + if (group->timer == 0) { + group->timer = 1; + } +#endif /* LWIP_RAND */ +} + +/** + * Delaying membership report for a group if necessary + * + * @param group the igmp_group for which "delaying" membership report + * @param maxresp query delay + */ +static void +igmp_delaying_member(struct igmp_group *group, u8_t maxresp) +{ + if ((group->group_state == IGMP_GROUP_IDLE_MEMBER) || + ((group->group_state == IGMP_GROUP_DELAYING_MEMBER) && + ((group->timer == 0) || (maxresp < group->timer)))) { + igmp_start_timer(group, maxresp); + group->group_state = IGMP_GROUP_DELAYING_MEMBER; + } +} + + +/** + * Sends an IP packet on a network interface. This function constructs the IP header + * and calculates the IP header checksum. If the source IP address is NULL, + * the IP address of the outgoing network interface is filled in as source address. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == IP_HDRINCL, p already includes an IP + header and p->payload points to that IP header) + * @param src the source IP address to send from (if src == IP_ADDR_ANY, the + * IP address of the netif used to send is used as source address) + * @param dest the destination IP address to send the packet to + * @param ttl the TTL value to be set in the IP header + * @param proto the PROTOCOL to be set in the IP header + * @param netif the netif on which to send this packet + * @return ERR_OK if the packet was sent OK + * ERR_BUF if p doesn't have enough space for IP/LINK headers + * returns errors returned by netif->output + */ +static err_t +igmp_ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, struct netif *netif) +{ + /* This is the "router alert" option */ + u16_t ra[2]; + ra[0] = PP_HTONS(ROUTER_ALERT); + ra[1] = 0x0000; /* Router shall examine packet */ + IGMP_STATS_INC(igmp.xmit); + return ip_output_if_opt(p, src, dest, IGMP_TTL, 0, IP_PROTO_IGMP, netif, ra, ROUTER_ALERTLEN); +} + +/** + * Send an igmp packet to a specific group. + * + * @param group the group to which to send the packet + * @param type the type of igmp packet to send + */ +static void +igmp_send(struct igmp_group *group, u8_t type) +{ + struct pbuf* p = NULL; + struct igmp_msg* igmp = NULL; + ip_addr_t src = *IP_ADDR_ANY; + ip_addr_t* dest = NULL; + + /* IP header + "router alert" option + IGMP header */ + p = pbuf_alloc(PBUF_TRANSPORT, IGMP_MINLEN, PBUF_RAM); + + if (p) { + igmp = (struct igmp_msg *)p->payload; + LWIP_ASSERT("igmp_send: check that first pbuf can hold struct igmp_msg", + (p->len >= sizeof(struct igmp_msg))); + ip_addr_copy(src, group->netif->ip_addr); + + if (type == IGMP_V2_MEMB_REPORT) { + dest = &(group->group_address); + ip_addr_copy(igmp->igmp_group_address, group->group_address); + group->last_reporter_flag = 1; /* Remember we were the last to report */ + } else { + if (type == IGMP_LEAVE_GROUP) { + dest = &allrouters; + ip_addr_copy(igmp->igmp_group_address, group->group_address); + } + } + + if ((type == IGMP_V2_MEMB_REPORT) || (type == IGMP_LEAVE_GROUP)) { + igmp->igmp_msgtype = type; + igmp->igmp_maxresp = 0; + igmp->igmp_checksum = 0; + igmp->igmp_checksum = inet_chksum(igmp, IGMP_MINLEN); + + igmp_ip_output_if(p, &src, dest, group->netif); + } + + pbuf_free(p); + } else { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_send: not enough memory for igmp_send\n")); + IGMP_STATS_INC(igmp.memerr); + } +} + +#endif /* LWIP_IGMP */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv4/ip4.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv4/ip4.c new file mode 100644 index 0000000..c7cb0d7 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv4/ip4.c @@ -0,0 +1,972 @@ +/** + * @file + * This is the IPv4 layer implementation for incoming and outgoing IP traffic. + * + * @see ip_frag.c + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" +#include "lwip/lwip_ip.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/ip_frag.h" +#include "lwip/inet_chksum.h" +#include "lwip/netif.h" +#include "lwip/icmp.h" +#include "lwip/igmp.h" +#include "lwip/raw.h" +#include "lwip/udp.h" +#include "lwip/tcp_impl.h" +#include "lwip/snmp.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" +#include "lwip/stats.h" +#include "arch/perf.h" + +#include + +/** Set this to 0 in the rare case of wanting to call an extra function to + * generate the IP checksum (in contrast to calculating it on-the-fly). */ +#ifndef LWIP_INLINE_IP_CHKSUM +#define LWIP_INLINE_IP_CHKSUM 1 +#endif +#if LWIP_INLINE_IP_CHKSUM && CHECKSUM_GEN_IP +#define CHECKSUM_GEN_IP_INLINE 1 +#else +#define CHECKSUM_GEN_IP_INLINE 0 +#endif + +#if LWIP_DHCP || defined(LWIP_IP_ACCEPT_UDP_PORT) +#define IP_ACCEPT_LINK_LAYER_ADDRESSING 1 + +/** Some defines for DHCP to let link-layer-addressed packets through while the + * netif is down. + * To use this in your own application/protocol, define LWIP_IP_ACCEPT_UDP_PORT + * to return 1 if the port is accepted and 0 if the port is not accepted. + */ +#if LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) +/* accept DHCP client port and custom port */ +#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) (((port) == PP_NTOHS(DHCP_CLIENT_PORT)) \ + || (LWIP_IP_ACCEPT_UDP_PORT(port))) +#elif defined(LWIP_IP_ACCEPT_UDP_PORT) /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */ +/* accept custom port only */ +#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) (LWIP_IP_ACCEPT_UDP_PORT(port)) +#else /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */ +/* accept DHCP client port only */ +#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) ((port) == PP_NTOHS(DHCP_CLIENT_PORT)) +#endif /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */ + +#else /* LWIP_DHCP */ +#define IP_ACCEPT_LINK_LAYER_ADDRESSING 0 +#endif /* LWIP_DHCP */ + +/** Global data for both IPv4 and IPv6 */ +struct ip_globals ip_data; + +/** The IP header ID of the next outgoing IP packet */ +static u16_t ip_id; + +/** + * Finds the appropriate network interface for a given IP address. It + * searches the list of network interfaces linearly. A match is found + * if the masked IP address of the network interface equals the masked + * IP address given to the function. + * + * @param dest the destination IP address for which to find the route + * @return the netif on which to send to reach dest + */ +struct netif * +ip_route(ip_addr_t *dest) +{ + struct netif *netif; + +#ifdef LWIP_HOOK_IP4_ROUTE + netif = LWIP_HOOK_IP4_ROUTE(dest); + if (netif != NULL) { + return netif; + } +#endif + + /* iterate through netifs */ + for (netif = netif_list; netif != NULL; netif = netif->next) { + /* network mask matches? */ + if ((netif_is_up(netif)) +#if LWIP_IPV6 + /* prevent using IPv6-only interfaces */ + && (!ip_addr_isany(&(netif->ip_addr))) +#endif /* LWIP_IPV6 */ + ) { + if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) { + /* return netif on which to forward IP packet */ + return netif; + } + } + } + if ((netif_default == NULL) || (!netif_is_up(netif_default))) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_route: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest))); + IP_STATS_INC(ip.rterr); + snmp_inc_ipoutnoroutes(); + return NULL; + } + /* no matching netif found, use default netif */ + return netif_default; +} + +#if IP_FORWARD +/** + * Determine whether an IP address is in a reserved set of addresses + * that may not be forwarded, or whether datagrams to that destination + * may be forwarded. + * @param p the packet to forward + * @param dest the destination IP address + * @return 1: can forward 0: discard + */ +static int +ip_canforward(struct pbuf *p) +{ + u32_t addr = htonl(ip4_addr_get_u32(ip_current_dest_addr())); + + if (p->flags & PBUF_FLAG_LLBCAST) { + /* don't route link-layer broadcasts */ + return 0; + } + if ((p->flags & PBUF_FLAG_LLMCAST) && !IP_MULTICAST(addr)) { + /* don't route link-layer multicasts unless the destination address is an IP + multicast address */ + return 0; + } + if (IP_EXPERIMENTAL(addr)) { + return 0; + } + if (IP_CLASSA(addr)) { + u32_t net = addr & IP_CLASSA_NET; + if ((net == 0) || (net == ((u32_t)IP_LOOPBACKNET << IP_CLASSA_NSHIFT))) { + /* don't route loopback packets */ + return 0; + } + } + return 1; +} + +/** + * Forwards an IP packet. It finds an appropriate route for the + * packet, decrements the TTL value of the packet, adjusts the + * checksum and outputs the packet on the appropriate interface. + * + * @param p the packet to forward (p->payload points to IP header) + * @param iphdr the IP header of the input packet + * @param inp the netif on which this packet was received + */ +static void +ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp) +{ + struct netif *netif; + + PERF_START; + + if (!ip_canforward(p)) { + goto return_noroute; + } + + /* RFC3927 2.7: do not forward link-local addresses */ + if (ip_addr_islinklocal(ip_current_dest_addr())) { + LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not forwarding LLA %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(ip_current_dest_addr()), ip4_addr2_16(ip_current_dest_addr()), + ip4_addr3_16(ip_current_dest_addr()), ip4_addr4_16(ip_current_dest_addr()))); + goto return_noroute; + } + + /* Find network interface where to forward this IP packet to. */ + netif = ip_route(ip_current_dest_addr()); + if (netif == NULL) { + LWIP_DEBUGF(IP_DEBUG, ("ip_forward: no forwarding route for %"U16_F".%"U16_F".%"U16_F".%"U16_F" found\n", + ip4_addr1_16(ip_current_dest_addr()), ip4_addr2_16(ip_current_dest_addr()), + ip4_addr3_16(ip_current_dest_addr()), ip4_addr4_16(ip_current_dest_addr()))); + /* @todo: send ICMP_DUR_NET? */ + goto return_noroute; + } +#if !IP_FORWARD_ALLOW_TX_ON_RX_NETIF + /* Do not forward packets onto the same network interface on which + * they arrived. */ + if (netif == inp) { + LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not bouncing packets back on incoming interface.\n")); + goto return_noroute; + } +#endif /* IP_FORWARD_ALLOW_TX_ON_RX_NETIF */ + + /* decrement TTL */ + IPH_TTL_SET(iphdr, IPH_TTL(iphdr) - 1); + /* send ICMP if TTL == 0 */ + if (IPH_TTL(iphdr) == 0) { + snmp_inc_ipinhdrerrors(); +#if LWIP_ICMP + /* Don't send ICMP messages in response to ICMP messages */ + if (IPH_PROTO(iphdr) != IP_PROTO_ICMP) { + icmp_time_exceeded(p, ICMP_TE_TTL); + } +#endif /* LWIP_ICMP */ + return; + } + + /* Incrementally update the IP checksum. */ + if (IPH_CHKSUM(iphdr) >= PP_HTONS(0xffffU - 0x100)) { + IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100) + 1); + } else { + IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100)); + } + + LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(ip_current_dest_addr()), ip4_addr2_16(ip_current_dest_addr()), + ip4_addr3_16(ip_current_dest_addr()), ip4_addr4_16(ip_current_dest_addr()))); + + IP_STATS_INC(ip.fw); + IP_STATS_INC(ip.xmit); + snmp_inc_ipforwdatagrams(); + + PERF_STOP("ip_forward"); + /* don't fragment if interface has mtu set to 0 [loopif] */ + if (netif->mtu && (p->tot_len > netif->mtu)) { + if ((IPH_OFFSET(iphdr) & PP_NTOHS(IP_DF)) == 0) { +#if IP_FRAG + ip_frag(p, netif, ip_current_dest_addr()); +#else /* IP_FRAG */ + /* @todo: send ICMP Destination Unreachable code 13 "Communication administratively prohibited"? */ +#endif /* IP_FRAG */ + } else { + /* send ICMP Destination Unreachable code 4: "Fragmentation Needed and DF Set" */ + icmp_dest_unreach(p, ICMP_DUR_FRAG); + } + return; + } + /* transmit pbuf on chosen interface */ + netif->output(netif, p, ip_current_dest_addr()); + return; +return_noroute: + snmp_inc_ipoutnoroutes(); +} +#endif /* IP_FORWARD */ + +/** + * This function is called by the network interface device driver when + * an IP packet is received. The function does the basic checks of the + * IP header such as packet size being at least larger than the header + * size etc. If the packet was not destined for us, the packet is + * forwarded (using ip_forward). The IP checksum is always checked. + * + * Finally, the packet is sent to the upper layer protocol input function. + * + * @param p the received IP packet (p->payload points to IP header) + * @param inp the netif on which this packet was received + * @return ERR_OK if the packet was processed (could return ERR_* if it wasn't + * processed, but currently always returns ERR_OK) + */ +err_t +ip_input(struct pbuf *p, struct netif *inp) +{ + struct ip_hdr *iphdr; + struct netif *netif; + u16_t iphdr_hlen; + u16_t iphdr_len; +#if IP_ACCEPT_LINK_LAYER_ADDRESSING || LWIP_IGMP + int check_ip_src = 1; +#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING || LWIP_IGMP */ + + IP_STATS_INC(ip.recv); + snmp_inc_ipinreceives(); + + /* identify the IP header */ + iphdr = (struct ip_hdr *)p->payload; + if (IPH_V(iphdr) != 4) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_WARNING, ("IP packet dropped due to bad version number %"U16_F"\n", IPH_V(iphdr))); + ip_debug_print(p); + pbuf_free(p); + IP_STATS_INC(ip.err); + IP_STATS_INC(ip.drop); + snmp_inc_ipinhdrerrors(); + return ERR_OK; + } + +#ifdef LWIP_HOOK_IP4_INPUT + if (LWIP_HOOK_IP4_INPUT(p, inp)) { + /* the packet has been eaten */ + return ERR_OK; + } +#endif + + /* obtain IP header length in number of 32-bit words */ + iphdr_hlen = IPH_HL(iphdr); + /* calculate IP header length in bytes */ + iphdr_hlen *= 4; + /* obtain ip length in bytes */ + iphdr_len = ntohs(IPH_LEN(iphdr)); + + /* header length exceeds first pbuf length, or ip length exceeds total pbuf length? */ + if ((iphdr_hlen > p->len) || (iphdr_len > p->tot_len)) { + if (iphdr_hlen > p->len) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IP header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n", + iphdr_hlen, p->len)); + } + if (iphdr_len > p->tot_len) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IP (len %"U16_F") is longer than pbuf (len %"U16_F"), IP packet dropped.\n", + iphdr_len, p->tot_len)); + } + /* free (drop) packet pbufs */ + pbuf_free(p); + IP_STATS_INC(ip.lenerr); + IP_STATS_INC(ip.drop); + snmp_inc_ipindiscards(); + return ERR_OK; + } + + /* verify checksum */ +#if CHECKSUM_CHECK_IP + if (inet_chksum(iphdr, iphdr_hlen) != 0) { + + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("Checksum (0x%"X16_F") failed, IP packet dropped.\n", inet_chksum(iphdr, iphdr_hlen))); + ip_debug_print(p); + pbuf_free(p); + IP_STATS_INC(ip.chkerr); + IP_STATS_INC(ip.drop); + snmp_inc_ipinhdrerrors(); + return ERR_OK; + } +#endif + + /* Trim pbuf. This should have been done at the netif layer, + * but we'll do it anyway just to be sure that its done. */ + pbuf_realloc(p, iphdr_len); + + /* copy IP addresses to aligned ip_addr_t */ + ip_addr_copy(*ipX_2_ip(&ip_data.current_iphdr_dest), iphdr->dest); + ip_addr_copy(*ipX_2_ip(&ip_data.current_iphdr_src), iphdr->src); + + /* match packet against an interface, i.e. is this packet for us? */ +#if LWIP_IGMP + if (ip_addr_ismulticast(ip_current_dest_addr())) { + if ((inp->flags & NETIF_FLAG_IGMP) && (igmp_lookfor_group(inp, ip_current_dest_addr()))) { + /* IGMP snooping switches need 0.0.0.0 to be allowed as source address (RFC 4541) */ + ip_addr_t allsystems; + IP4_ADDR(&allsystems, 224, 0, 0, 1); + if (ip_addr_cmp(ip_current_dest_addr(), &allsystems) && + ip_addr_isany(ip_current_src_addr())) { + check_ip_src = 0; + } + netif = inp; + } else { + netif = NULL; + } + } else +#endif /* LWIP_IGMP */ + { + /* start trying with inp. if that's not acceptable, start walking the + list of configured netifs. + 'first' is used as a boolean to mark whether we started walking the list */ + int first = 1; + netif = inp; + do { + LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest 0x%"X32_F" netif->ip_addr 0x%"X32_F" (0x%"X32_F", 0x%"X32_F", 0x%"X32_F")\n", + ip4_addr_get_u32(&iphdr->dest), ip4_addr_get_u32(&netif->ip_addr), + ip4_addr_get_u32(&iphdr->dest) & ip4_addr_get_u32(&netif->netmask), + ip4_addr_get_u32(&netif->ip_addr) & ip4_addr_get_u32(&netif->netmask), + ip4_addr_get_u32(&iphdr->dest) & ~ip4_addr_get_u32(&netif->netmask))); + + /* interface is up and configured? */ + if ((netif_is_up(netif)) && (!ip_addr_isany(&(netif->ip_addr)))) { + /* unicast to this interface address? */ + if (ip_addr_cmp(ip_current_dest_addr(), &(netif->ip_addr)) || + /* or broadcast on this interface network address? */ + ip_addr_isbroadcast(ip_current_dest_addr(), netif)) { + LWIP_DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n", + netif->name[0], netif->name[1])); + /* break out of for loop */ + break; + } +#if LWIP_AUTOIP + /* connections to link-local addresses must persist after changing + the netif's address (RFC3927 ch. 1.9) */ + if ((netif->autoip != NULL) && + ip_addr_cmp(ip_current_dest_addr(), &(netif->autoip->llipaddr))) { + LWIP_DEBUGF(IP_DEBUG, ("ip_input: LLA packet accepted on interface %c%c\n", + netif->name[0], netif->name[1])); + /* break out of for loop */ + break; + } +#endif /* LWIP_AUTOIP */ + } + if (first) { + first = 0; + netif = netif_list; + } else { + netif = netif->next; + } + if (netif == inp) { + netif = netif->next; + } + } while(netif != NULL); + } + +#if IP_ACCEPT_LINK_LAYER_ADDRESSING + /* Pass DHCP messages regardless of destination address. DHCP traffic is addressed + * using link layer addressing (such as Ethernet MAC) so we must not filter on IP. + * According to RFC 1542 section 3.1.1, referred by RFC 2131). + * + * If you want to accept private broadcast communication while a netif is down, + * define LWIP_IP_ACCEPT_UDP_PORT(dst_port), e.g.: + * + * #define LWIP_IP_ACCEPT_UDP_PORT(dst_port) ((dst_port) == PP_NTOHS(12345)) + */ + if (netif == NULL) { + /* remote port is DHCP server? */ + if (IPH_PROTO(iphdr) == IP_PROTO_UDP) { + struct udp_hdr *udphdr = (struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen); + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: UDP packet to DHCP client port %"U16_F"\n", + ntohs(udphdr->dest))); + if (IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(udphdr->dest)) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: DHCP packet accepted.\n")); + netif = inp; + check_ip_src = 0; + } + } + } +#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */ + + /* broadcast or multicast packet source address? Compliant with RFC 1122: 3.2.1.3 */ +#if LWIP_IGMP || IP_ACCEPT_LINK_LAYER_ADDRESSING + if (check_ip_src +#if IP_ACCEPT_LINK_LAYER_ADDRESSING + /* DHCP servers need 0.0.0.0 to be allowed as source address (RFC 1.1.2.2: 3.2.1.3/a) */ + && !ip_addr_isany(ip_current_src_addr()) +#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */ + ) +#endif /* LWIP_IGMP || IP_ACCEPT_LINK_LAYER_ADDRESSING */ + { if ((ip_addr_isbroadcast(ip_current_src_addr(), inp)) || + (ip_addr_ismulticast(ip_current_src_addr()))) { + /* packet source is not valid */ + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("ip_input: packet source is not valid.\n")); + /* free (drop) packet pbufs */ + pbuf_free(p); + IP_STATS_INC(ip.drop); + snmp_inc_ipinaddrerrors(); + snmp_inc_ipindiscards(); + return ERR_OK; + } + } + + /* packet not for us? */ + if (netif == NULL) { + /* packet not for us, route or discard */ + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: packet not for us.\n")); +#if IP_FORWARD + /* non-broadcast packet? */ + if (!ip_addr_isbroadcast(ip_current_dest_addr(), inp)) { + /* try to forward IP packet on (other) interfaces */ + ip_forward(p, iphdr, inp); + } else +#endif /* IP_FORWARD */ + { + snmp_inc_ipinaddrerrors(); + snmp_inc_ipindiscards(); + } + pbuf_free(p); + return ERR_OK; + } + /* packet consists of multiple fragments? */ + if ((IPH_OFFSET(iphdr) & PP_HTONS(IP_OFFMASK | IP_MF)) != 0) { +#if IP_REASSEMBLY /* packet fragment reassembly code present? */ + LWIP_DEBUGF(IP_DEBUG, ("IP packet is a fragment (id=0x%04"X16_F" tot_len=%"U16_F" len=%"U16_F" MF=%"U16_F" offset=%"U16_F"), calling ip_reass()\n", + ntohs(IPH_ID(iphdr)), p->tot_len, ntohs(IPH_LEN(iphdr)), !!(IPH_OFFSET(iphdr) & PP_HTONS(IP_MF)), (ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8)); + /* reassemble the packet*/ + p = ip_reass(p); + /* packet not fully reassembled yet? */ + if (p == NULL) { + return ERR_OK; + } + iphdr = (struct ip_hdr *)p->payload; +#else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */ + pbuf_free(p); + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since it was fragmented (0x%"X16_F") (while IP_REASSEMBLY == 0).\n", + ntohs(IPH_OFFSET(iphdr)))); + IP_STATS_INC(ip.opterr); + IP_STATS_INC(ip.drop); + /* unsupported protocol feature */ + snmp_inc_ipinunknownprotos(); + return ERR_OK; +#endif /* IP_REASSEMBLY */ + } + +#if IP_OPTIONS_ALLOWED == 0 /* no support for IP options in the IP header? */ + +#if LWIP_IGMP + /* there is an extra "router alert" option in IGMP messages which we allow for but do not police */ + if((iphdr_hlen > IP_HLEN) && (IPH_PROTO(iphdr) != IP_PROTO_IGMP)) { +#else + if (iphdr_hlen > IP_HLEN) { +#endif /* LWIP_IGMP */ + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since there were IP options (while IP_OPTIONS_ALLOWED == 0).\n")); + pbuf_free(p); + IP_STATS_INC(ip.opterr); + IP_STATS_INC(ip.drop); + /* unsupported protocol feature */ + snmp_inc_ipinunknownprotos(); + return ERR_OK; + } +#endif /* IP_OPTIONS_ALLOWED == 0 */ + + /* send to upper layers */ + LWIP_DEBUGF(IP_DEBUG, ("ip_input: \n")); + ip_debug_print(p); + LWIP_DEBUGF(IP_DEBUG, ("ip_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len)); + + //Evan add for debug + //printf("\n\r[Evan] header len = %"U16_F" , total len = %"U16_F"\n", iphdr_hlen, p->tot_len); + //char temp[1000] = {"\0"}; + //memcpy(temp, p->payload, p->tot_len); + //printf("\n\rReceive ipv4 socket = %s\n", &temp[28]); + //Evan add end + + ip_data.current_netif = inp; + ip_data.current_ip4_header = iphdr; + ip_data.current_ip_header_tot_len = IPH_HL(iphdr) * 4; + +#if LWIP_RAW + /* raw input did not eat the packet? */ + if (raw_input(p, inp) == 0) +#endif /* LWIP_RAW */ + { + pbuf_header(p, -(s16_t)iphdr_hlen); /* Move to payload, no check necessary. */ + + switch (IPH_PROTO(iphdr)) { +#if LWIP_UDP + case IP_PROTO_UDP: +#if LWIP_UDPLITE + case IP_PROTO_UDPLITE: +#endif /* LWIP_UDPLITE */ + snmp_inc_ipindelivers(); + udp_input(p, inp); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case IP_PROTO_TCP: + snmp_inc_ipindelivers(); + tcp_input(p, inp); + break; +#endif /* LWIP_TCP */ +#if LWIP_ICMP + case IP_PROTO_ICMP: + snmp_inc_ipindelivers(); + icmp_input(p, inp); + break; +#endif /* LWIP_ICMP */ +#if LWIP_IGMP + case IP_PROTO_IGMP: + igmp_input(p, inp, ip_current_dest_addr()); + break; +#endif /* LWIP_IGMP */ + default: +#if LWIP_ICMP + /* send ICMP destination protocol unreachable unless is was a broadcast */ + if (!ip_addr_isbroadcast(ip_current_dest_addr(), inp) && + !ip_addr_ismulticast(ip_current_dest_addr())) { + pbuf_header_force(p, iphdr_hlen); /* Move to ip header, no check necessary. */ + p->payload = iphdr; + icmp_dest_unreach(p, ICMP_DUR_PROTO); + } +#endif /* LWIP_ICMP */ + pbuf_free(p); + + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("Unsupported transport protocol %"U16_F"\n", IPH_PROTO(iphdr))); + + IP_STATS_INC(ip.proterr); + IP_STATS_INC(ip.drop); + snmp_inc_ipinunknownprotos(); + } + } + + /* @todo: this is not really necessary... */ + ip_data.current_netif = NULL; + ip_data.current_ip4_header = NULL; + ip_data.current_ip_header_tot_len = 0; + ip_addr_set_any(ip_current_src_addr()); + ip_addr_set_any(ip_current_dest_addr()); + + return ERR_OK; +} + +/** + * Sends an IP packet on a network interface. This function constructs + * the IP header and calculates the IP header checksum. If the source + * IP address is NULL, the IP address of the outgoing network + * interface is filled in as source address. + * If the destination IP address is IP_HDRINCL, p is assumed to already + * include an IP header and p->payload points to it instead of the data. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == IP_HDRINCL, p already includes an IP + header and p->payload points to that IP header) + * @param src the source IP address to send from (if src == IP_ADDR_ANY, the + * IP address of the netif used to send is used as source address) + * @param dest the destination IP address to send the packet to + * @param ttl the TTL value to be set in the IP header + * @param tos the TOS value to be set in the IP header + * @param proto the PROTOCOL to be set in the IP header + * @param netif the netif on which to send this packet + * @return ERR_OK if the packet was sent OK + * ERR_BUF if p doesn't have enough space for IP/LINK headers + * returns errors returned by netif->output + * + * @note ip_id: RFC791 "some host may be able to simply use + * unique identifiers independent of destination" + */ +err_t +ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, + u8_t proto, struct netif *netif) +{ +#if IP_OPTIONS_SEND + return ip_output_if_opt(p, src, dest, ttl, tos, proto, netif, NULL, 0); +} + +/** + * Same as ip_output_if() but with the possibility to include IP options: + * + * @ param ip_options pointer to the IP options, copied into the IP header + * @ param optlen length of ip_options + */ +err_t ip_output_if_opt(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, + u16_t optlen) +{ +#endif /* IP_OPTIONS_SEND */ + ip_addr_t *src_used = src; + if (dest != IP_HDRINCL) { + if (ip_addr_isany(src)) { + src_used = &netif->ip_addr; + } + } + +#if IP_OPTIONS_SEND + return ip_output_if_opt_src(p, src_used, dest, ttl, tos, proto, netif, + ip_options, optlen); +#else /* IP_OPTIONS_SEND */ + return ip_output_if_src(p, src_used, dest, ttl, tos, proto, netif); +#endif /* IP_OPTIONS_SEND */ +} + +/** + * Same as ip_output_if() but 'src' address is not replaced by netif address + * when it is 'any'. + */ +err_t +ip_output_if_src(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, + u8_t proto, struct netif *netif) +{ +#if IP_OPTIONS_SEND + return ip_output_if_opt_src(p, src, dest, ttl, tos, proto, netif, NULL, 0); +} + +/** + * Same as ip_output_if_opt() but 'src' address is not replaced by netif address + * when it is 'any'. + */ +err_t ip_output_if_opt_src(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, + u16_t optlen) +{ +#endif /* IP_OPTIONS_SEND */ + struct ip_hdr *iphdr; + ip_addr_t dest_addr; +#if CHECKSUM_GEN_IP_INLINE + u32_t chk_sum = 0; +#endif /* CHECKSUM_GEN_IP_INLINE */ + + LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); + + snmp_inc_ipoutrequests(); + + /* Should the IP header be generated or is it already included in p? */ + if (dest != IP_HDRINCL) { + u16_t ip_hlen = IP_HLEN; +#if IP_OPTIONS_SEND + u16_t optlen_aligned = 0; + if (optlen != 0) { +#if CHECKSUM_GEN_IP_INLINE + int i; +#endif /* CHECKSUM_GEN_IP_INLINE */ + /* round up to a multiple of 4 */ + optlen_aligned = ((optlen + 3) & ~3); + ip_hlen += optlen_aligned; + /* First write in the IP options */ + if (pbuf_header(p, optlen_aligned)) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_output_if_opt: not enough room for IP options in pbuf\n")); + IP_STATS_INC(ip.err); + snmp_inc_ipoutdiscards(); + return ERR_BUF; + } + MEMCPY(p->payload, ip_options, optlen); + if (optlen < optlen_aligned) { + /* zero the remaining bytes */ + memset(((char*)p->payload) + optlen, 0, optlen_aligned - optlen); + } +#if CHECKSUM_GEN_IP_INLINE + for (i = 0; i < optlen_aligned/2; i++) { + chk_sum += ((u16_t*)p->payload)[i]; + } +#endif /* CHECKSUM_GEN_IP_INLINE */ + } +#endif /* IP_OPTIONS_SEND */ + /* generate IP header */ + if (pbuf_header(p, IP_HLEN)) { + LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_output: not enough room for IP header in pbuf\n")); + + IP_STATS_INC(ip.err); + snmp_inc_ipoutdiscards(); + return ERR_BUF; + } + + iphdr = (struct ip_hdr *)p->payload; + LWIP_ASSERT("check that first pbuf can hold struct ip_hdr", + (p->len >= sizeof(struct ip_hdr))); + + IPH_TTL_SET(iphdr, ttl); + IPH_PROTO_SET(iphdr, proto); +#if CHECKSUM_GEN_IP_INLINE + chk_sum += LWIP_MAKE_U16(proto, ttl); +#endif /* CHECKSUM_GEN_IP_INLINE */ + + /* dest cannot be NULL here */ + ip_addr_copy(iphdr->dest, *dest); +#if CHECKSUM_GEN_IP_INLINE + chk_sum += ip4_addr_get_u32(&iphdr->dest) & 0xFFFF; + chk_sum += ip4_addr_get_u32(&iphdr->dest) >> 16; +#endif /* CHECKSUM_GEN_IP_INLINE */ + + IPH_VHL_SET(iphdr, 4, ip_hlen / 4); + IPH_TOS_SET(iphdr, tos); +#if CHECKSUM_GEN_IP_INLINE + chk_sum += LWIP_MAKE_U16(tos, iphdr->_v_hl); +#endif /* CHECKSUM_GEN_IP_INLINE */ + IPH_LEN_SET(iphdr, htons(p->tot_len)); +#if CHECKSUM_GEN_IP_INLINE + chk_sum += iphdr->_len; +#endif /* CHECKSUM_GEN_IP_INLINE */ + IPH_OFFSET_SET(iphdr, 0); + IPH_ID_SET(iphdr, htons(ip_id)); +#if CHECKSUM_GEN_IP_INLINE + chk_sum += iphdr->_id; +#endif /* CHECKSUM_GEN_IP_INLINE */ + ++ip_id; + + if (src == NULL) { + ip_addr_copy(iphdr->src, ip_addr_any); + } else { + /* src cannot be NULL here */ + ip_addr_copy(iphdr->src, *src); + } + +#if CHECKSUM_GEN_IP_INLINE + chk_sum += ip4_addr_get_u32(&iphdr->src) & 0xFFFF; + chk_sum += ip4_addr_get_u32(&iphdr->src) >> 16; + chk_sum = (chk_sum >> 16) + (chk_sum & 0xFFFF); + chk_sum = (chk_sum >> 16) + chk_sum; + chk_sum = ~chk_sum; + iphdr->_chksum = chk_sum; /* network order */ +#else /* CHECKSUM_GEN_IP_INLINE */ + IPH_CHKSUM_SET(iphdr, 0); +#if CHECKSUM_GEN_IP + IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, ip_hlen)); +#endif +#endif /* CHECKSUM_GEN_IP_INLINE */ + } else { + /* IP header already included in p */ + iphdr = (struct ip_hdr *)p->payload; + ip_addr_copy(dest_addr, iphdr->dest); + dest = &dest_addr; + } + + IP_STATS_INC(ip.xmit); + + LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], netif->num)); + ip_debug_print(p); + +#if ENABLE_LOOPBACK + if (ip_addr_cmp(dest, &netif->ip_addr)) { + /* Packet to self, enqueue it for loopback */ + LWIP_DEBUGF(IP_DEBUG, ("netif_loop_output()")); + return netif_loop_output(netif, p); + } +#if LWIP_IGMP + if ((p->flags & PBUF_FLAG_MCASTLOOP) != 0) { + netif_loop_output(netif, p); + } +#endif /* LWIP_IGMP */ +#endif /* ENABLE_LOOPBACK */ +#if IP_FRAG + /* don't fragment if interface has mtu set to 0 [loopif] */ + if (netif->mtu && (p->tot_len > netif->mtu)) { + return ip_frag(p, netif, dest); + } +#endif /* IP_FRAG */ + + LWIP_DEBUGF(IP_DEBUG, ("netif->output()")); + return netif->output(netif, p, dest); +} + +/** + * Simple interface to ip_output_if. It finds the outgoing network + * interface and calls upon ip_output_if to do the actual work. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == IP_HDRINCL, p already includes an IP + header and p->payload points to that IP header) + * @param src the source IP address to send from (if src == IP_ADDR_ANY, the + * IP address of the netif used to send is used as source address) + * @param dest the destination IP address to send the packet to + * @param ttl the TTL value to be set in the IP header + * @param tos the TOS value to be set in the IP header + * @param proto the PROTOCOL to be set in the IP header + * + * @return ERR_RTE if no route is found + * see ip_output_if() for more return values + */ +err_t +ip_output(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto) +{ + struct netif *netif; + + LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); + + if ((netif = ip_route(dest)) == NULL) { + LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest))); + IP_STATS_INC(ip.rterr); + return ERR_RTE; + } + + return ip_output_if(p, src, dest, ttl, tos, proto, netif); +} + +#if LWIP_NETIF_HWADDRHINT +/** Like ip_output, but takes and addr_hint pointer that is passed on to netif->addr_hint + * before calling ip_output_if. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == IP_HDRINCL, p already includes an IP + header and p->payload points to that IP header) + * @param src the source IP address to send from (if src == IP_ADDR_ANY, the + * IP address of the netif used to send is used as source address) + * @param dest the destination IP address to send the packet to + * @param ttl the TTL value to be set in the IP header + * @param tos the TOS value to be set in the IP header + * @param proto the PROTOCOL to be set in the IP header + * @param addr_hint address hint pointer set to netif->addr_hint before + * calling ip_output_if() + * + * @return ERR_RTE if no route is found + * see ip_output_if() for more return values + */ +err_t +ip_output_hinted(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint) +{ + struct netif *netif; + err_t err; + + LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); + + if ((netif = ip_route(dest)) == NULL) { + LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest))); + IP_STATS_INC(ip.rterr); + return ERR_RTE; + } + + NETIF_SET_HWADDRHINT(netif, addr_hint); + err = ip_output_if(p, src, dest, ttl, tos, proto, netif); + NETIF_SET_HWADDRHINT(netif, NULL); + + return err; +} +#endif /* LWIP_NETIF_HWADDRHINT*/ + +#if IP_DEBUG +/* Print an IP header by using LWIP_DEBUGF + * @param p an IP packet, p->payload pointing to the IP header + */ +void +ip_debug_print(struct pbuf *p) +{ + struct ip_hdr *iphdr = (struct ip_hdr *)p->payload; + + LWIP_DEBUGF(IP_DEBUG, ("IP header:\n")); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("|%2"S16_F" |%2"S16_F" | 0x%02"X16_F" | %5"U16_F" | (v, hl, tos, len)\n", + IPH_V(iphdr), + IPH_HL(iphdr), + IPH_TOS(iphdr), + ntohs(IPH_LEN(iphdr)))); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("| %5"U16_F" |%"U16_F"%"U16_F"%"U16_F"| %4"U16_F" | (id, flags, offset)\n", + ntohs(IPH_ID(iphdr)), + ntohs(IPH_OFFSET(iphdr)) >> 15 & 1, + ntohs(IPH_OFFSET(iphdr)) >> 14 & 1, + ntohs(IPH_OFFSET(iphdr)) >> 13 & 1, + ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | 0x%04"X16_F" | (ttl, proto, chksum)\n", + IPH_TTL(iphdr), + IPH_PROTO(iphdr), + ntohs(IPH_CHKSUM(iphdr)))); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (src)\n", + ip4_addr1_16(&iphdr->src), + ip4_addr2_16(&iphdr->src), + ip4_addr3_16(&iphdr->src), + ip4_addr4_16(&iphdr->src))); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (dest)\n", + ip4_addr1_16(&iphdr->dest), + ip4_addr2_16(&iphdr->dest), + ip4_addr3_16(&iphdr->dest), + ip4_addr4_16(&iphdr->dest))); + LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); +} +#endif /* IP_DEBUG */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv4/ip4_addr.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv4/ip4_addr.c new file mode 100644 index 0000000..3836f27 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv4/ip4_addr.c @@ -0,0 +1,312 @@ +/** + * @file + * This is the IPv4 address tools implementation. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" + +/* used by IP_ADDR_ANY and IP_ADDR_BROADCAST in ip_addr.h */ +const ip_addr_t ip_addr_any = { IPADDR_ANY }; +const ip_addr_t ip_addr_broadcast = { IPADDR_BROADCAST }; + +/** + * Determine if an address is a broadcast address on a network interface + * + * @param addr address to be checked + * @param netif the network interface against which the address is checked + * @return returns non-zero if the address is a broadcast address + */ +u8_t +ip4_addr_isbroadcast(u32_t addr, const struct netif *netif) +{ + ip_addr_t ipaddr; + ip4_addr_set_u32(&ipaddr, addr); + + /* all ones (broadcast) or all zeroes (old skool broadcast) */ + if ((~addr == IPADDR_ANY) || + (addr == IPADDR_ANY)) { + return 1; + /* no broadcast support on this network interface? */ + } else if ((netif->flags & NETIF_FLAG_BROADCAST) == 0) { + /* the given address cannot be a broadcast address + * nor can we check against any broadcast addresses */ + return 0; + /* address matches network interface address exactly? => no broadcast */ + } else if (addr == ip4_addr_get_u32(&netif->ip_addr)) { + return 0; + /* on the same (sub) network... */ + } else if (ip_addr_netcmp(&ipaddr, &(netif->ip_addr), &(netif->netmask)) + /* ...and host identifier bits are all ones? =>... */ + && ((addr & ~ip4_addr_get_u32(&netif->netmask)) == + (IPADDR_BROADCAST & ~ip4_addr_get_u32(&netif->netmask)))) { + /* => network broadcast address */ + return 1; + } else { + return 0; + } +} + +/** Checks if a netmask is valid (starting with ones, then only zeros) + * + * @param netmask the IPv4 netmask to check (in network byte order!) + * @return 1 if the netmask is valid, 0 if it is not + */ +u8_t +ip4_addr_netmask_valid(u32_t netmask) +{ + u32_t mask; + u32_t nm_hostorder = lwip_htonl(netmask); + + /* first, check for the first zero */ + for (mask = 1UL << 31 ; mask != 0; mask >>= 1) { + if ((nm_hostorder & mask) == 0) { + break; + } + } + /* then check that there is no one */ + for (; mask != 0; mask >>= 1) { + if ((nm_hostorder & mask) != 0) { + /* there is a one after the first zero -> invalid */ + return 0; + } + } + /* no one after the first zero -> valid */ + return 1; +} + +/* Here for now until needed in other places in lwIP */ +#ifndef isprint +#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up) +#define isprint(c) in_range(c, 0x20, 0x7f) +#define isdigit(c) in_range(c, '0', '9') +#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F')) +#define islower(c) in_range(c, 'a', 'z') +#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v') +#endif + +/** + * Ascii internet address interpretation routine. + * The value returned is in network order. + * + * @param cp IP address in ascii representation (e.g. "127.0.0.1") + * @return ip address in network order + */ +u32_t +ipaddr_addr(const char *cp) +{ + ip_addr_t val; + + if (ipaddr_aton(cp, &val)) { + return ip4_addr_get_u32(&val); + } + return (IPADDR_NONE); +} + +/** + * Check whether "cp" is a valid ascii representation + * of an Internet address and convert to a binary address. + * Returns 1 if the address is valid, 0 if not. + * This replaces inet_addr, the return value from which + * cannot distinguish between failure and a local broadcast address. + * + * @param cp IP address in ascii representation (e.g. "127.0.0.1") + * @param addr pointer to which to save the ip address in network order + * @return 1 if cp could be converted to addr, 0 on failure + */ +int +ipaddr_aton(const char *cp, ip_addr_t *addr) +{ + u32_t val; + u8_t base; + char c; + u32_t parts[4]; + u32_t *pp = parts; + + c = *cp; + for (;;) { + /* + * Collect number up to ``.''. + * Values are specified as for C: + * 0x=hex, 0=octal, 1-9=decimal. + */ + if (!isdigit(c)) + return (0); + val = 0; + base = 10; + if (c == '0') { + c = *++cp; + if (c == 'x' || c == 'X') { + base = 16; + c = *++cp; + } else + base = 8; + } + for (;;) { + if (isdigit(c)) { + val = (val * base) + (int)(c - '0'); + c = *++cp; + } else if (base == 16 && isxdigit(c)) { + val = (val << 4) | (int)(c + 10 - (islower(c) ? 'a' : 'A')); + c = *++cp; + } else + break; + } + if (c == '.') { + /* + * Internet format: + * a.b.c.d + * a.b.c (with c treated as 16 bits) + * a.b (with b treated as 24 bits) + */ + if (pp >= parts + 3) { + return (0); + } + *pp++ = val; + c = *++cp; + } else + break; + } + /* + * Check for trailing characters. + */ + if (c != '\0' && !isspace(c)) { + return (0); + } + /* + * Concoct the address according to + * the number of parts specified. + */ + switch (pp - parts + 1) { + + case 0: + return (0); /* initial nondigit */ + + case 1: /* a -- 32 bits */ + break; + + case 2: /* a.b -- 8.24 bits */ + if (val > 0xffffffUL) { + return (0); + } + val |= parts[0] << 24; + break; + + case 3: /* a.b.c -- 8.8.16 bits */ + if (val > 0xffff) { + return (0); + } + val |= (parts[0] << 24) | (parts[1] << 16); + break; + + case 4: /* a.b.c.d -- 8.8.8.8 bits */ + if (val > 0xff) { + return (0); + } + val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); + break; + default: + LWIP_ASSERT("unhandled", 0); + break; + } + if (addr) { + ip4_addr_set_u32(addr, htonl(val)); + } + return (1); +} + +/** + * Convert numeric IP address into decimal dotted ASCII representation. + * returns ptr to static buffer; not reentrant! + * + * @param addr ip address in network order to convert + * @return pointer to a global static (!) buffer that holds the ASCII + * representation of addr + */ +char * +ipaddr_ntoa(const ip_addr_t *addr) +{ + static char str[16]; + return ipaddr_ntoa_r(addr, str, 16); +} + +/** + * Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used. + * + * @param addr ip address in network order to convert + * @param buf target buffer where the string is stored + * @param buflen length of buf + * @return either pointer to buf which now holds the ASCII + * representation of addr or NULL if buf was too small + */ +char *ipaddr_ntoa_r(const ip_addr_t *addr, char *buf, int buflen) +{ + u32_t s_addr; + char inv[3]; + char *rp; + u8_t *ap; + u8_t rem; + u8_t n; + u8_t i; + int len = 0; + + s_addr = ip4_addr_get_u32(addr); + + rp = buf; + ap = (u8_t *)&s_addr; + for(n = 0; n < 4; n++) { + i = 0; + do { + rem = *ap % (u8_t)10; + *ap /= (u8_t)10; + inv[i++] = '0' + rem; + } while(*ap); + while(i--) { + if (len++ >= buflen) { + return NULL; + } + *rp++ = inv[i]; + } + if (len++ >= buflen) { + return NULL; + } + *rp++ = '.'; + ap++; + } + *--rp = 0; + return buf; +} diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv4/ip_frag.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv4/ip_frag.c new file mode 100644 index 0000000..3450927 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv4/ip_frag.c @@ -0,0 +1,878 @@ +/** + * @file + * This is the IPv4 packet segmentation and reassembly implementation. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Jani Monoses + * Simon Goldschmidt + * original reassembly code by Adam Dunkels + * + */ + +#include "lwip/opt.h" +#include "lwip/ip_frag.h" +#include "lwip/def.h" +#include "lwip/inet_chksum.h" +#include "lwip/netif.h" +#include "lwip/snmp.h" +#include "lwip/stats.h" +#include "lwip/icmp.h" + +#include + +#if IP_REASSEMBLY +/** + * The IP reassembly code currently has the following limitations: + * - IP header options are not supported + * - fragments must not overlap (e.g. due to different routes), + * currently, overlapping or duplicate fragments are thrown away + * if IP_REASS_CHECK_OVERLAP=1 (the default)! + * + * @todo: work with IP header options + */ + +/** Setting this to 0, you can turn off checking the fragments for overlapping + * regions. The code gets a little smaller. Only use this if you know that + * overlapping won't occur on your network! */ +#ifndef IP_REASS_CHECK_OVERLAP +#define IP_REASS_CHECK_OVERLAP 1 +#endif /* IP_REASS_CHECK_OVERLAP */ + +/** Set to 0 to prevent freeing the oldest datagram when the reassembly buffer is + * full (IP_REASS_MAX_PBUFS pbufs are enqueued). The code gets a little smaller. + * Datagrams will be freed by timeout only. Especially useful when MEMP_NUM_REASSDATA + * is set to 1, so one datagram can be reassembled at a time, only. */ +#ifndef IP_REASS_FREE_OLDEST +#define IP_REASS_FREE_OLDEST 1 +#endif /* IP_REASS_FREE_OLDEST */ + +#define IP_REASS_FLAG_LASTFRAG 0x01 + +/** This is a helper struct which holds the starting + * offset and the ending offset of this fragment to + * easily chain the fragments. + * It has the same packing requirements as the IP header, since it replaces + * the IP header in memory in incoming fragments (after copying it) to keep + * track of the various fragments. (-> If the IP header doesn't need packing, + * this struct doesn't need packing, too.) + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip_reass_helper { + PACK_STRUCT_FIELD(struct pbuf *next_pbuf); + PACK_STRUCT_FIELD(u16_t start); + PACK_STRUCT_FIELD(u16_t end); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define IP_ADDRESSES_AND_ID_MATCH(iphdrA, iphdrB) \ + (ip_addr_cmp(&(iphdrA)->src, &(iphdrB)->src) && \ + ip_addr_cmp(&(iphdrA)->dest, &(iphdrB)->dest) && \ + IPH_ID(iphdrA) == IPH_ID(iphdrB)) ? 1 : 0 + +/* global variables */ +static struct ip_reassdata *reassdatagrams; +static u16_t ip_reass_pbufcount; + +/* function prototypes */ +static void ip_reass_dequeue_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev); +static int ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev); + +/** + * Reassembly timer base function + * for both NO_SYS == 0 and 1 (!). + * + * Should be called every 1000 msec (defined by IP_TMR_INTERVAL). + */ +void +ip_reass_tmr(void) +{ + struct ip_reassdata *r, *prev = NULL; + + r = reassdatagrams; + while (r != NULL) { + /* Decrement the timer. Once it reaches 0, + * clean up the incomplete fragment assembly */ + if (r->timer > 0) { + r->timer--; + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass_tmr: timer dec %"U16_F"\n",(u16_t)r->timer)); + prev = r; + r = r->next; + } else { + /* reassembly timed out */ + struct ip_reassdata *tmp; + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass_tmr: timer timed out\n")); + tmp = r; + /* get the next pointer before freeing */ + r = r->next; + /* free the helper struct and all enqueued pbufs */ + ip_reass_free_complete_datagram(tmp, prev); + } + } +} + +/** + * Free a datagram (struct ip_reassdata) and all its pbufs. + * Updates the total count of enqueued pbufs (ip_reass_pbufcount), + * SNMP counters and sends an ICMP time exceeded packet. + * + * @param ipr datagram to free + * @param prev the previous datagram in the linked list + * @return the number of pbufs freed + */ +static int +ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev) +{ + u16_t pbufs_freed = 0; + u8_t clen; + struct pbuf *p; + struct ip_reass_helper *iprh; + + LWIP_ASSERT("prev != ipr", prev != ipr); + if (prev != NULL) { + LWIP_ASSERT("prev->next == ipr", prev->next == ipr); + } + + snmp_inc_ipreasmfails(); +#if LWIP_ICMP + iprh = (struct ip_reass_helper *)ipr->p->payload; + if (iprh->start == 0) { + /* The first fragment was received, send ICMP time exceeded. */ + /* First, de-queue the first pbuf from r->p. */ + p = ipr->p; + ipr->p = iprh->next_pbuf; + /* Then, copy the original header into it. */ + SMEMCPY(p->payload, &ipr->iphdr, IP_HLEN); + icmp_time_exceeded(p, ICMP_TE_FRAG); + clen = pbuf_clen(p); + LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); + pbufs_freed += clen; + pbuf_free(p); + } +#endif /* LWIP_ICMP */ + + /* First, free all received pbufs. The individual pbufs need to be released + separately as they have not yet been chained */ + p = ipr->p; + while (p != NULL) { + struct pbuf *pcur; + iprh = (struct ip_reass_helper *)p->payload; + pcur = p; + /* get the next pointer before freeing */ + p = iprh->next_pbuf; + clen = pbuf_clen(pcur); + LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); + pbufs_freed += clen; + pbuf_free(pcur); + } + /* Then, unchain the struct ip_reassdata from the list and free it. */ + ip_reass_dequeue_datagram(ipr, prev); + LWIP_ASSERT("ip_reass_pbufcount >= clen", ip_reass_pbufcount >= pbufs_freed); + ip_reass_pbufcount -= pbufs_freed; + + return pbufs_freed; +} + +#if IP_REASS_FREE_OLDEST +/** + * Free the oldest datagram to make room for enqueueing new fragments. + * The datagram 'fraghdr' belongs to is not freed! + * + * @param fraghdr IP header of the current fragment + * @param pbufs_needed number of pbufs needed to enqueue + * (used for freeing other datagrams if not enough space) + * @return the number of pbufs freed + */ +static int +ip_reass_remove_oldest_datagram(struct ip_hdr *fraghdr, int pbufs_needed) +{ + /* @todo Can't we simply remove the last datagram in the + * linked list behind reassdatagrams? + */ + struct ip_reassdata *r, *oldest, *prev; + int pbufs_freed = 0, pbufs_freed_current; + int other_datagrams; + + /* Free datagrams until being allowed to enqueue 'pbufs_needed' pbufs, + * but don't free the datagram that 'fraghdr' belongs to! */ + do { + oldest = NULL; + prev = NULL; + other_datagrams = 0; + r = reassdatagrams; + while (r != NULL) { + if (!IP_ADDRESSES_AND_ID_MATCH(&r->iphdr, fraghdr)) { + /* Not the same datagram as fraghdr */ + other_datagrams++; + if (oldest == NULL) { + oldest = r; + } else if (r->timer <= oldest->timer) { + /* older than the previous oldest */ + oldest = r; + } + } + if (r->next != NULL) { + prev = r; + } + r = r->next; + } + if (oldest != NULL) { + pbufs_freed_current = ip_reass_free_complete_datagram(oldest, prev); + pbufs_freed += pbufs_freed_current; + } + } while ((pbufs_freed < pbufs_needed) && (other_datagrams > 1)); + return pbufs_freed; +} +#endif /* IP_REASS_FREE_OLDEST */ + +/** + * Enqueues a new fragment into the fragment queue + * @param fraghdr points to the new fragments IP hdr + * @param clen number of pbufs needed to enqueue (used for freeing other datagrams if not enough space) + * @return A pointer to the queue location into which the fragment was enqueued + */ +static struct ip_reassdata* +ip_reass_enqueue_new_datagram(struct ip_hdr *fraghdr, int clen) +{ + struct ip_reassdata* ipr; + /* No matching previous fragment found, allocate a new reassdata struct */ + ipr = (struct ip_reassdata *)memp_malloc(MEMP_REASSDATA); + if (ipr == NULL) { +#if IP_REASS_FREE_OLDEST + if (ip_reass_remove_oldest_datagram(fraghdr, clen) >= clen) { + ipr = (struct ip_reassdata *)memp_malloc(MEMP_REASSDATA); + } + if (ipr == NULL) +#endif /* IP_REASS_FREE_OLDEST */ + { + IPFRAG_STATS_INC(ip_frag.memerr); + LWIP_DEBUGF(IP_REASS_DEBUG,("Failed to alloc reassdata struct\n")); + return NULL; + } + } + memset(ipr, 0, sizeof(struct ip_reassdata)); + ipr->timer = IP_REASS_MAXAGE; + + /* enqueue the new structure to the front of the list */ + ipr->next = reassdatagrams; + reassdatagrams = ipr; + /* copy the ip header for later tests and input */ + /* @todo: no ip options supported? */ + SMEMCPY(&(ipr->iphdr), fraghdr, IP_HLEN); + return ipr; +} + +/** + * Dequeues a datagram from the datagram queue. Doesn't deallocate the pbufs. + * @param ipr points to the queue entry to dequeue + */ +static void +ip_reass_dequeue_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev) +{ + + /* dequeue the reass struct */ + if (reassdatagrams == ipr) { + /* it was the first in the list */ + reassdatagrams = ipr->next; + } else { + /* it wasn't the first, so it must have a valid 'prev' */ + LWIP_ASSERT("sanity check linked list", prev != NULL); + prev->next = ipr->next; + } + + /* now we can free the ip_reass struct */ + memp_free(MEMP_REASSDATA, ipr); +} + +/** + * Chain a new pbuf into the pbuf list that composes the datagram. The pbuf list + * will grow over time as new pbufs are rx. + * Also checks that the datagram passes basic continuity checks (if the last + * fragment was received at least once). + * @param root_p points to the 'root' pbuf for the current datagram being assembled. + * @param new_p points to the pbuf for the current fragment + * @return 0 if invalid, >0 otherwise + */ +static int +ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct pbuf *new_p) +{ + struct ip_reass_helper *iprh, *iprh_tmp, *iprh_prev=NULL; + struct pbuf *q; + u16_t offset,len; + struct ip_hdr *fraghdr; + int valid = 1; + + /* Extract length and fragment offset from current fragment */ + fraghdr = (struct ip_hdr*)new_p->payload; + len = ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4; + offset = (ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8; + + /* overwrite the fragment's ip header from the pbuf with our helper struct, + * and setup the embedded helper structure. */ + /* make sure the struct ip_reass_helper fits into the IP header */ + LWIP_ASSERT("sizeof(struct ip_reass_helper) <= IP_HLEN", + sizeof(struct ip_reass_helper) <= IP_HLEN); + iprh = (struct ip_reass_helper*)new_p->payload; + iprh->next_pbuf = NULL; + iprh->start = offset; + iprh->end = offset + len; + + /* Iterate through until we either get to the end of the list (append), + * or we find on with a larger offset (insert). */ + for (q = ipr->p; q != NULL;) { + iprh_tmp = (struct ip_reass_helper*)q->payload; + if (iprh->start < iprh_tmp->start) { + /* the new pbuf should be inserted before this */ + iprh->next_pbuf = q; + if (iprh_prev != NULL) { + /* not the fragment with the lowest offset */ +#if IP_REASS_CHECK_OVERLAP + if ((iprh->start < iprh_prev->end) || (iprh->end > iprh_tmp->start)) { + /* fragment overlaps with previous or following, throw away */ + goto freepbuf; + } +#endif /* IP_REASS_CHECK_OVERLAP */ + iprh_prev->next_pbuf = new_p; + } else { + /* fragment with the lowest offset */ + ipr->p = new_p; + } + break; + } else if(iprh->start == iprh_tmp->start) { + /* received the same datagram twice: no need to keep the datagram */ + goto freepbuf; +#if IP_REASS_CHECK_OVERLAP + } else if(iprh->start < iprh_tmp->end) { + /* overlap: no need to keep the new datagram */ + goto freepbuf; +#endif /* IP_REASS_CHECK_OVERLAP */ + } else { + /* Check if the fragments received so far have no wholes. */ + if (iprh_prev != NULL) { + if (iprh_prev->end != iprh_tmp->start) { + /* There is a fragment missing between the current + * and the previous fragment */ + valid = 0; + } + } + } + q = iprh_tmp->next_pbuf; + iprh_prev = iprh_tmp; + } + + /* If q is NULL, then we made it to the end of the list. Determine what to do now */ + if (q == NULL) { + if (iprh_prev != NULL) { + /* this is (for now), the fragment with the highest offset: + * chain it to the last fragment */ +#if IP_REASS_CHECK_OVERLAP + LWIP_ASSERT("check fragments don't overlap", iprh_prev->end <= iprh->start); +#endif /* IP_REASS_CHECK_OVERLAP */ + iprh_prev->next_pbuf = new_p; + if (iprh_prev->end != iprh->start) { + valid = 0; + } + } else { +#if IP_REASS_CHECK_OVERLAP + LWIP_ASSERT("no previous fragment, this must be the first fragment!", + ipr->p == NULL); +#endif /* IP_REASS_CHECK_OVERLAP */ + /* this is the first fragment we ever received for this ip datagram */ + ipr->p = new_p; + } + } + + /* At this point, the validation part begins: */ + /* If we already received the last fragment */ + if ((ipr->flags & IP_REASS_FLAG_LASTFRAG) != 0) { + /* and had no wholes so far */ + if (valid) { + /* then check if the rest of the fragments is here */ + /* Check if the queue starts with the first datagram */ + if ((ipr->p == NULL) || (((struct ip_reass_helper*)ipr->p->payload)->start != 0)) { + valid = 0; + } else { + /* and check that there are no wholes after this datagram */ + iprh_prev = iprh; + q = iprh->next_pbuf; + while (q != NULL) { + iprh = (struct ip_reass_helper*)q->payload; + if (iprh_prev->end != iprh->start) { + valid = 0; + break; + } + iprh_prev = iprh; + q = iprh->next_pbuf; + } + /* if still valid, all fragments are received + * (because to the MF==0 already arrived */ + if (valid) { + LWIP_ASSERT("sanity check", ipr->p != NULL); + LWIP_ASSERT("sanity check", + ((struct ip_reass_helper*)ipr->p->payload) != iprh); + LWIP_ASSERT("validate_datagram:next_pbuf!=NULL", + iprh->next_pbuf == NULL); + LWIP_ASSERT("validate_datagram:datagram end!=datagram len", + iprh->end == ipr->datagram_len); + } + } + } + /* If valid is 0 here, there are some fragments missing in the middle + * (since MF == 0 has already arrived). Such datagrams simply time out if + * no more fragments are received... */ + return valid; + } + /* If we come here, not all fragments were received, yet! */ + return 0; /* not yet valid! */ +#if IP_REASS_CHECK_OVERLAP +freepbuf: + ip_reass_pbufcount -= pbuf_clen(new_p); + pbuf_free(new_p); + return 0; +#endif /* IP_REASS_CHECK_OVERLAP */ +} + +/** + * Reassembles incoming IP fragments into an IP datagram. + * + * @param p points to a pbuf chain of the fragment + * @return NULL if reassembly is incomplete, ? otherwise + */ +struct pbuf * +ip_reass(struct pbuf *p) +{ + struct pbuf *r; + struct ip_hdr *fraghdr; + struct ip_reassdata *ipr; + struct ip_reass_helper *iprh; + u16_t offset, len; + u8_t clen; + + IPFRAG_STATS_INC(ip_frag.recv); + snmp_inc_ipreasmreqds(); + + fraghdr = (struct ip_hdr*)p->payload; + + if ((IPH_HL(fraghdr) * 4) != IP_HLEN) { + LWIP_DEBUGF(IP_REASS_DEBUG,("ip_reass: IP options currently not supported!\n")); + IPFRAG_STATS_INC(ip_frag.err); + goto nullreturn; + } + + offset = (ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8; + len = ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4; + + /* Check if we are allowed to enqueue more datagrams. */ + clen = pbuf_clen(p); + if ((ip_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS) { +#if IP_REASS_FREE_OLDEST + if (!ip_reass_remove_oldest_datagram(fraghdr, clen) || + ((ip_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS)) +#endif /* IP_REASS_FREE_OLDEST */ + { + /* No datagram could be freed and still too many pbufs enqueued */ + LWIP_DEBUGF(IP_REASS_DEBUG,("ip_reass: Overflow condition: pbufct=%d, clen=%d, MAX=%d\n", + ip_reass_pbufcount, clen, IP_REASS_MAX_PBUFS)); + IPFRAG_STATS_INC(ip_frag.memerr); + /* @todo: send ICMP time exceeded here? */ + /* drop this pbuf */ + goto nullreturn; + } + } + + /* Look for the datagram the fragment belongs to in the current datagram queue, + * remembering the previous in the queue for later dequeueing. */ + for (ipr = reassdatagrams; ipr != NULL; ipr = ipr->next) { + /* Check if the incoming fragment matches the one currently present + in the reassembly buffer. If so, we proceed with copying the + fragment into the buffer. */ + if (IP_ADDRESSES_AND_ID_MATCH(&ipr->iphdr, fraghdr)) { + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: matching previous fragment ID=%"X16_F"\n", + ntohs(IPH_ID(fraghdr)))); + IPFRAG_STATS_INC(ip_frag.cachehit); + break; + } + } + + if (ipr == NULL) { + /* Enqueue a new datagram into the datagram queue */ + ipr = ip_reass_enqueue_new_datagram(fraghdr, clen); + /* Bail if unable to enqueue */ + if(ipr == NULL) { + goto nullreturn; + } + } else { + if (((ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) == 0) && + ((ntohs(IPH_OFFSET(&ipr->iphdr)) & IP_OFFMASK) != 0)) { + /* ipr->iphdr is not the header from the first fragment, but fraghdr is + * -> copy fraghdr into ipr->iphdr since we want to have the header + * of the first fragment (for ICMP time exceeded and later, for copying + * all options, if supported)*/ + SMEMCPY(&ipr->iphdr, fraghdr, IP_HLEN); + } + } + /* Track the current number of pbufs current 'in-flight', in order to limit + the number of fragments that may be enqueued at any one time */ + ip_reass_pbufcount += clen; + + /* At this point, we have either created a new entry or pointing + * to an existing one */ + + /* check for 'no more fragments', and update queue entry*/ + if ((IPH_OFFSET(fraghdr) & PP_NTOHS(IP_MF)) == 0) { + ipr->flags |= IP_REASS_FLAG_LASTFRAG; + ipr->datagram_len = offset + len; + LWIP_DEBUGF(IP_REASS_DEBUG, + ("ip_reass: last fragment seen, total len %"S16_F"\n", + ipr->datagram_len)); + } + /* find the right place to insert this pbuf */ + /* @todo: trim pbufs if fragments are overlapping */ + if (ip_reass_chain_frag_into_datagram_and_validate(ipr, p)) { + struct ip_reassdata *ipr_prev; + /* the totally last fragment (flag more fragments = 0) was received at least + * once AND all fragments are received */ + ipr->datagram_len += IP_HLEN; + + /* save the second pbuf before copying the header over the pointer */ + r = ((struct ip_reass_helper*)ipr->p->payload)->next_pbuf; + + /* copy the original ip header back to the first pbuf */ + fraghdr = (struct ip_hdr*)(ipr->p->payload); + SMEMCPY(fraghdr, &ipr->iphdr, IP_HLEN); + IPH_LEN_SET(fraghdr, htons(ipr->datagram_len)); + IPH_OFFSET_SET(fraghdr, 0); + IPH_CHKSUM_SET(fraghdr, 0); + /* @todo: do we need to set calculate the correct checksum? */ +#if CHECKSUM_GEN_IP + IPH_CHKSUM_SET(fraghdr, inet_chksum(fraghdr, IP_HLEN)); +#endif /* CHECKSUM_GEN_IP */ + + p = ipr->p; + + /* chain together the pbufs contained within the reass_data list. */ + while(r != NULL) { + iprh = (struct ip_reass_helper*)r->payload; + + /* hide the ip header for every succeeding fragment */ + pbuf_header(r, -IP_HLEN); + pbuf_cat(p, r); + r = iprh->next_pbuf; + } + + /* find the previous entry in the linked list */ + if (ipr == reassdatagrams) { + ipr_prev = NULL; + } else { + for (ipr_prev = reassdatagrams; ipr_prev != NULL; ipr_prev = ipr_prev->next) { + if (ipr_prev->next == ipr) { + break; + } + } + } + + /* release the sources allocate for the fragment queue entry */ + ip_reass_dequeue_datagram(ipr, ipr_prev); + + /* and adjust the number of pbufs currently queued for reassembly. */ + ip_reass_pbufcount -= pbuf_clen(p); + + /* Return the pbuf chain */ + return p; + } + /* the datagram is not (yet?) reassembled completely */ + LWIP_DEBUGF(IP_REASS_DEBUG,("ip_reass_pbufcount: %d out\n", ip_reass_pbufcount)); + return NULL; + +nullreturn: + LWIP_DEBUGF(IP_REASS_DEBUG,("ip_reass: nullreturn\n")); + IPFRAG_STATS_INC(ip_frag.drop); + pbuf_free(p); + return NULL; +} +#endif /* IP_REASSEMBLY */ + +#if IP_FRAG +#if IP_FRAG_USES_STATIC_BUF +static u8_t buf[LWIP_MEM_ALIGN_SIZE(IP_FRAG_MAX_MTU + MEM_ALIGNMENT - 1)]; +#else /* IP_FRAG_USES_STATIC_BUF */ + +#if !LWIP_NETIF_TX_SINGLE_PBUF +/** Allocate a new struct pbuf_custom_ref */ +static struct pbuf_custom_ref* +ip_frag_alloc_pbuf_custom_ref(void) +{ + return (struct pbuf_custom_ref*)memp_malloc(MEMP_FRAG_PBUF); +} + +/** Free a struct pbuf_custom_ref */ +static void +ip_frag_free_pbuf_custom_ref(struct pbuf_custom_ref* p) +{ + LWIP_ASSERT("p != NULL", p != NULL); + memp_free(MEMP_FRAG_PBUF, p); +} + +/** Free-callback function to free a 'struct pbuf_custom_ref', called by + * pbuf_free. */ +static void +ipfrag_free_pbuf_custom(struct pbuf *p) +{ + struct pbuf_custom_ref *pcr = (struct pbuf_custom_ref*)p; + LWIP_ASSERT("pcr != NULL", pcr != NULL); + LWIP_ASSERT("pcr == p", (void*)pcr == (void*)p); + if (pcr->original != NULL) { + pbuf_free(pcr->original); + } + ip_frag_free_pbuf_custom_ref(pcr); +} +#endif /* !LWIP_NETIF_TX_SINGLE_PBUF */ +#endif /* IP_FRAG_USES_STATIC_BUF */ + +/** + * Fragment an IP datagram if too large for the netif. + * + * Chop the datagram in MTU sized chunks and send them in order + * by using a fixed size static memory buffer (PBUF_REF) or + * point PBUF_REFs into p (depending on IP_FRAG_USES_STATIC_BUF). + * + * @param p ip packet to send + * @param netif the netif on which to send + * @param dest destination ip address to which to send + * + * @return ERR_OK if sent successfully, err_t otherwise + */ +err_t +ip_frag(struct pbuf *p, struct netif *netif, ip_addr_t *dest) +{ + struct pbuf *rambuf; +#if IP_FRAG_USES_STATIC_BUF + struct pbuf *header; +#else +#if !LWIP_NETIF_TX_SINGLE_PBUF + struct pbuf *newpbuf; +#endif + struct ip_hdr *original_iphdr; +#endif + struct ip_hdr *iphdr; + u16_t nfb; + u16_t left, cop; + u16_t mtu = netif->mtu; + u16_t ofo, omf; + u16_t last; + u16_t poff = IP_HLEN; + u16_t tmp; +#if !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF + u16_t newpbuflen = 0; + u16_t left_to_copy; +#endif + + /* Get a RAM based MTU sized pbuf */ +#if IP_FRAG_USES_STATIC_BUF + /* When using a static buffer, we use a PBUF_REF, which we will + * use to reference the packet (without link header). + * Layer and length is irrelevant. + */ + rambuf = pbuf_alloc(PBUF_LINK, 0, PBUF_REF); + if (rambuf == NULL) { + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_frag: pbuf_alloc(PBUF_LINK, 0, PBUF_REF) failed\n")); + return ERR_MEM; + } + rambuf->tot_len = rambuf->len = mtu; + rambuf->payload = LWIP_MEM_ALIGN((void *)buf); + + /* Copy the IP header in it */ + iphdr = (struct ip_hdr *)rambuf->payload; + SMEMCPY(iphdr, p->payload, IP_HLEN); +#else /* IP_FRAG_USES_STATIC_BUF */ + original_iphdr = (struct ip_hdr *)p->payload; + iphdr = original_iphdr; +#endif /* IP_FRAG_USES_STATIC_BUF */ + + /* Save original offset */ + tmp = ntohs(IPH_OFFSET(iphdr)); + ofo = tmp & IP_OFFMASK; + omf = tmp & IP_MF; + + left = p->tot_len - IP_HLEN; + + nfb = (mtu - IP_HLEN) / 8; + + while (left) { + last = (left <= mtu - IP_HLEN); + + /* Set new offset and MF flag */ + tmp = omf | (IP_OFFMASK & (ofo)); + if (!last) { + tmp = tmp | IP_MF; + } + + /* Fill this fragment */ + cop = last ? left : nfb * 8; + +#if IP_FRAG_USES_STATIC_BUF + poff += pbuf_copy_partial(p, (u8_t*)iphdr + IP_HLEN, cop, poff); +#else /* IP_FRAG_USES_STATIC_BUF */ +#if LWIP_NETIF_TX_SINGLE_PBUF + rambuf = pbuf_alloc(PBUF_IP, cop, PBUF_RAM); + if (rambuf == NULL) { + return ERR_MEM; + } + LWIP_ASSERT("this needs a pbuf in one piece!", + (rambuf->len == rambuf->tot_len) && (rambuf->next == NULL)); + poff += pbuf_copy_partial(p, rambuf->payload, cop, poff); + /* make room for the IP header */ + if(pbuf_header(rambuf, IP_HLEN)) { + pbuf_free(rambuf); + return ERR_MEM; + } + /* fill in the IP header */ + SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN); + iphdr = rambuf->payload; +#else /* LWIP_NETIF_TX_SINGLE_PBUF */ + /* When not using a static buffer, create a chain of pbufs. + * The first will be a PBUF_RAM holding the link and IP header. + * The rest will be PBUF_REFs mirroring the pbuf chain to be fragged, + * but limited to the size of an mtu. + */ + rambuf = pbuf_alloc(PBUF_LINK, IP_HLEN, PBUF_RAM); + if (rambuf == NULL) { + return ERR_MEM; + } + LWIP_ASSERT("this needs a pbuf in one piece!", + (p->len >= (IP_HLEN))); + SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN); + iphdr = (struct ip_hdr *)rambuf->payload; + + /* Can just adjust p directly for needed offset. */ + p->payload = (u8_t *)p->payload + poff; + p->len -= poff; + + left_to_copy = cop; + while (left_to_copy) { + struct pbuf_custom_ref *pcr; + newpbuflen = (left_to_copy < p->len) ? left_to_copy : p->len; + /* Is this pbuf already empty? */ + if (!newpbuflen) { + p = p->next; + continue; + } + pcr = ip_frag_alloc_pbuf_custom_ref(); + if (pcr == NULL) { + pbuf_free(rambuf); + return ERR_MEM; + } + /* Mirror this pbuf, although we might not need all of it. */ + newpbuf = pbuf_alloced_custom(PBUF_RAW, newpbuflen, PBUF_REF, &pcr->pc, p->payload, newpbuflen); + if (newpbuf == NULL) { + ip_frag_free_pbuf_custom_ref(pcr); + pbuf_free(rambuf); + return ERR_MEM; + } + pbuf_ref(p); + pcr->original = p; + pcr->pc.custom_free_function = ipfrag_free_pbuf_custom; + + /* Add it to end of rambuf's chain, but using pbuf_cat, not pbuf_chain + * so that it is removed when pbuf_dechain is later called on rambuf. + */ + pbuf_cat(rambuf, newpbuf); + left_to_copy -= newpbuflen; + if (left_to_copy) { + p = p->next; + } + } + poff = newpbuflen; +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ +#endif /* IP_FRAG_USES_STATIC_BUF */ + + /* Correct header */ + IPH_OFFSET_SET(iphdr, htons(tmp)); + IPH_LEN_SET(iphdr, htons(cop + IP_HLEN)); + IPH_CHKSUM_SET(iphdr, 0); +#if CHECKSUM_GEN_IP + IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN)); +#endif /* CHECKSUM_GEN_IP */ + +#if IP_FRAG_USES_STATIC_BUF + if (last) { + pbuf_realloc(rambuf, left + IP_HLEN); + } + + /* This part is ugly: we alloc a RAM based pbuf for + * the link level header for each chunk and then + * free it.A PBUF_ROM style pbuf for which pbuf_header + * worked would make things simpler. + */ + header = pbuf_alloc(PBUF_LINK, 0, PBUF_RAM); + if (header != NULL) { + pbuf_chain(header, rambuf); + netif->output(netif, header, dest); + IPFRAG_STATS_INC(ip_frag.xmit); + snmp_inc_ipfragcreates(); + pbuf_free(header); + } else { + LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_frag: pbuf_alloc() for header failed\n")); + pbuf_free(rambuf); + return ERR_MEM; + } +#else /* IP_FRAG_USES_STATIC_BUF */ + /* No need for separate header pbuf - we allowed room for it in rambuf + * when allocated. + */ + netif->output(netif, rambuf, dest); + IPFRAG_STATS_INC(ip_frag.xmit); + + /* Unfortunately we can't reuse rambuf - the hardware may still be + * using the buffer. Instead we free it (and the ensuing chain) and + * recreate it next time round the loop. If we're lucky the hardware + * will have already sent the packet, the free will really free, and + * there will be zero memory penalty. + */ + + pbuf_free(rambuf); +#endif /* IP_FRAG_USES_STATIC_BUF */ + left -= cop; + ofo += nfb; + } +#if IP_FRAG_USES_STATIC_BUF + pbuf_free(rambuf); +#endif /* IP_FRAG_USES_STATIC_BUF */ + snmp_inc_ipfragoks(); + return ERR_OK; +} +#endif /* IP_FRAG */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv6/README b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv6/README new file mode 100644 index 0000000..3620004 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv6/README @@ -0,0 +1 @@ +IPv6 support in lwIP is very experimental. diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv6/dhcp6.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv6/dhcp6.c new file mode 100644 index 0000000..9656c3b --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv6/dhcp6.c @@ -0,0 +1,50 @@ +/** + * @file + * + * DHCPv6. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV6_DHCP6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/ip6_addr.h" +#include "lwip/def.h" + + +#endif /* LWIP_IPV6_DHCP6 */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv6/ethip6.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv6/ethip6.c new file mode 100644 index 0000000..d9ac30f --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv6/ethip6.c @@ -0,0 +1,193 @@ +/** + * @file + * + * Ethernet output for IPv6. Uses ND tables for link-layer addressing. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV6 && LWIP_ETHERNET + +#include "lwip/ethip6.h" +#include "lwip/nd6.h" +#include "lwip/pbuf.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/inet_chksum.h" +#include "lwip/netif.h" +#include "lwip/icmp6.h" + +#include + +#define ETHTYPE_IPV6 0x86DD + +/** The ethernet address */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct eth_addr { + PACK_STRUCT_FLD_8(u8_t addr[6]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Ethernet header */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct eth_hdr { +#if ETH_PAD_SIZE + PACK_STRUCT_FLD_8(u8_t padding[ETH_PAD_SIZE]); +#endif + PACK_STRUCT_FLD_S(struct eth_addr dest); + PACK_STRUCT_FLD_S(struct eth_addr src); + PACK_STRUCT_FIELD(u16_t type); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define SIZEOF_ETH_HDR (14 + ETH_PAD_SIZE) + +/** + * Send an IPv6 packet on the network using netif->linkoutput + * The ethernet header is filled in before sending. + * + * @params netif the lwIP network interface on which to send the packet + * @params p the packet to send, p->payload pointing to the (uninitialized) ethernet header + * @params src the source MAC address to be copied into the ethernet header + * @params dst the destination MAC address to be copied into the ethernet header + * @return ERR_OK if the packet was sent, any other err_t on failure + */ +static err_t +ethip6_send(struct netif *netif, struct pbuf *p, struct eth_addr *src, struct eth_addr *dst) +{ + struct eth_hdr *ethhdr = (struct eth_hdr *)p->payload; + + LWIP_ASSERT("netif->hwaddr_len must be 6 for ethip6!", + (netif->hwaddr_len == 6)); + SMEMCPY(ðhdr->dest, dst, 6); + SMEMCPY(ðhdr->src, src, 6); + ethhdr->type = PP_HTONS(ETHTYPE_IPV6); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("ethip6_send: sending packet %p\n", (void *)p)); + /* send the packet */ + return netif->linkoutput(netif, p); +} + +/** + * Resolve and fill-in Ethernet address header for outgoing IPv6 packet. + * + * For IPv6 multicast, corresponding Ethernet addresses + * are selected and the packet is transmitted on the link. + * + * For unicast addresses, ... + * + * @TODO anycast addresses + * + * @param netif The lwIP network interface which the IP packet will be sent on. + * @param q The pbuf(s) containing the IP packet to be sent. + * @param ip6addr The IP address of the packet destination. + * + * @return + * - ERR_RTE No route to destination (no gateway to external networks), + * or the return type of either etharp_query() or etharp_send_ip(). + */ +err_t +ethip6_output(struct netif *netif, struct pbuf *q, ip6_addr_t *ip6addr) +{ + struct eth_addr dest; + s8_t i; + + /* make room for Ethernet header - should not fail */ + if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) { + /* bail out */ + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("etharp_output: could not allocate room for header.\n")); + return ERR_BUF; + } + + /* multicast destination IP address? */ + if (ip6_addr_ismulticast(ip6addr)) { + /* Hash IP multicast address to MAC address.*/ + dest.addr[0] = 0x33; + dest.addr[1] = 0x33; + dest.addr[2] = ((u8_t *)(&(ip6addr->addr[3])))[0]; + dest.addr[3] = ((u8_t *)(&(ip6addr->addr[3])))[1]; + dest.addr[4] = ((u8_t *)(&(ip6addr->addr[3])))[2]; + dest.addr[5] = ((u8_t *)(&(ip6addr->addr[3])))[3]; + + /* Send out. */ + return ethip6_send(netif, q, (struct eth_addr*)(netif->hwaddr), &dest); + } + + /* We have a unicast destination IP address */ + /* TODO anycast? */ + /* Get next hop record. */ + i = nd6_get_next_hop_entry(ip6addr, netif); + if (i < 0) { + /* failed to get a next hop neighbor record. */ + return ERR_MEM; + } + + /* Now that we have a destination record, send or queue the packet. */ + if (neighbor_cache[i].state == ND6_STALE) { + /* Switch to delay state. */ + neighbor_cache[i].state = ND6_DELAY; + neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME; + } + /* TODO should we send or queue if PROBE? send for now, to let unicast NS pass. */ + if ((neighbor_cache[i].state == ND6_REACHABLE) || + (neighbor_cache[i].state == ND6_DELAY) || + (neighbor_cache[i].state == ND6_PROBE)) { + + /* Send out. */ + SMEMCPY(dest.addr, neighbor_cache[i].lladdr, 6); + return ethip6_send(netif, q, (struct eth_addr*)(netif->hwaddr), &dest); + } + + /* We should queue packet on this interface. */ + pbuf_header(q, -(s16_t)SIZEOF_ETH_HDR); + return nd6_queue_packet(i, q); +} + +#endif /* LWIP_IPV6 && LWIP_ETHERNET */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv6/icmp6.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv6/icmp6.c new file mode 100644 index 0000000..5cd1bbb --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv6/icmp6.c @@ -0,0 +1,342 @@ +/** + * @file + * + * IPv6 version of ICMP, as per RFC 4443. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#include "lwip/opt.h" + +#if LWIP_ICMP6 && LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/icmp6.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/inet_chksum.h" +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/nd6.h" +#include "lwip/mld6.h" +#include "lwip/lwip_ip.h" +#include "lwip/stats.h" + +#include + +#ifndef LWIP_ICMP6_DATASIZE +#define LWIP_ICMP6_DATASIZE 8 +#endif +#if LWIP_ICMP6_DATASIZE == 0 +#define LWIP_ICMP6_DATASIZE 8 +#endif + +/* Forward declarations */ +static void icmp6_send_response(struct pbuf *p, u8_t code, u32_t data, u8_t type); + + +/** + * Process an input ICMPv6 message. Called by ip6_input. + * + * Will generate a reply for echo requests. Other messages are forwarded + * to nd6_input, or mld6_input. + * + * @param p the mld packet, p->payload pointing to the icmpv6 header + * @param inp the netif on which this packet was received + */ +void +icmp6_input(struct pbuf *p, struct netif *inp) +{ + struct icmp6_hdr *icmp6hdr; + struct pbuf * r; + ip6_addr_t * reply_src; + + ICMP6_STATS_INC(icmp6.recv); + + /* Check that ICMPv6 header fits in payload */ + if (p->len < sizeof(struct icmp6_hdr)) { + /* drop short packets */ + pbuf_free(p); + ICMP6_STATS_INC(icmp6.lenerr); + ICMP6_STATS_INC(icmp6.drop); + return; + } + + icmp6hdr = (struct icmp6_hdr *)p->payload; + +#if CHECKSUM_CHECK_ICMP6 + if (ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->tot_len, ip6_current_src_addr(), + ip6_current_dest_addr()) != 0) { + /* Checksum failed */ + pbuf_free(p); + ICMP6_STATS_INC(icmp6.chkerr); + ICMP6_STATS_INC(icmp6.drop); + return; + } +#endif /* CHECKSUM_CHECK_ICMP6 */ + + switch (icmp6hdr->type) { + case ICMP6_TYPE_NA: /* Neighbor advertisement */ + case ICMP6_TYPE_NS: /* Neighbor solicitation */ + case ICMP6_TYPE_RA: /* Router advertisement */ + case ICMP6_TYPE_RD: /* Redirect */ + case ICMP6_TYPE_PTB: /* Packet too big */ + nd6_input(p, inp); + return; + break; + case ICMP6_TYPE_RS: +#if LWIP_IPV6_FORWARD + /* TODO implement router functionality */ +#endif + break; +#if LWIP_IPV6_MLD + case ICMP6_TYPE_MLQ: + case ICMP6_TYPE_MLR: + case ICMP6_TYPE_MLD: + mld6_input(p, inp); + return; + break; +#endif + case ICMP6_TYPE_EREQ: +#if !LWIP_MULTICAST_PING + /* multicast destination address? */ + if (ip6_addr_ismulticast(ip6_current_dest_addr())) { + /* drop */ + pbuf_free(p); + ICMP6_STATS_INC(icmp6.drop); + return; + } +#endif /* LWIP_MULTICAST_PING */ + + /* Allocate reply. */ + r = pbuf_alloc(PBUF_IP, p->tot_len, PBUF_RAM); + if (r == NULL) { + /* drop */ + pbuf_free(p); + ICMP6_STATS_INC(icmp6.memerr); + return; + } + + /* Copy echo request. */ + if (pbuf_copy(r, p) != ERR_OK) { + /* drop */ + pbuf_free(p); + pbuf_free(r); + ICMP6_STATS_INC(icmp6.err); + return; + } + + /* Determine reply source IPv6 address. */ +#if LWIP_MULTICAST_PING + if (ip6_addr_ismulticast(ip6_current_dest_addr())) { + reply_src = ip6_select_source_address(inp, ip6_current_src_addr()); + if (reply_src == NULL) { + /* drop */ + pbuf_free(p); + pbuf_free(r); + ICMP6_STATS_INC(icmp6.rterr); + return; + } + } + else +#endif /* LWIP_MULTICAST_PING */ + { + reply_src = ip6_current_dest_addr(); + } + + /* Set fields in reply. */ + ((struct icmp6_echo_hdr *)(r->payload))->type = ICMP6_TYPE_EREP; + ((struct icmp6_echo_hdr *)(r->payload))->chksum = 0; +#if CHECKSUM_GEN_ICMP6 + ((struct icmp6_echo_hdr *)(r->payload))->chksum = ip6_chksum_pseudo(r, + IP6_NEXTH_ICMP6, r->tot_len, reply_src, ip6_current_src_addr()); +#endif /* CHECKSUM_GEN_ICMP6 */ + + /* Send reply. */ + ICMP6_STATS_INC(icmp6.xmit); + ip6_output_if(r, reply_src, ip6_current_src_addr(), + LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, inp); + pbuf_free(r); + + break; + default: + ICMP6_STATS_INC(icmp6.proterr); + ICMP6_STATS_INC(icmp6.drop); + break; + } + + pbuf_free(p); +} + + +/** + * Send an icmpv6 'destination unreachable' packet. + * + * @param p the input packet for which the 'unreachable' should be sent, + * p->payload pointing to the IPv6 header + * @param c ICMPv6 code for the unreachable type + */ +void +icmp6_dest_unreach(struct pbuf *p, enum icmp6_dur_code c) +{ + icmp6_send_response(p, c, 0, ICMP6_TYPE_DUR); +} + +/** + * Send an icmpv6 'packet too big' packet. + * + * @param p the input packet for which the 'packet too big' should be sent, + * p->payload pointing to the IPv6 header + * @param mtu the maximum mtu that we can accept + */ +void +icmp6_packet_too_big(struct pbuf *p, u32_t mtu) +{ + icmp6_send_response(p, 0, mtu, ICMP6_TYPE_PTB); +} + +/** + * Send an icmpv6 'time exceeded' packet. + * + * @param p the input packet for which the 'unreachable' should be sent, + * p->payload pointing to the IPv6 header + * @param c ICMPv6 code for the time exceeded type + */ +void +icmp6_time_exceeded(struct pbuf *p, enum icmp6_te_code c) +{ + icmp6_send_response(p, c, 0, ICMP6_TYPE_TE); +} + +/** + * Send an icmpv6 'parameter problem' packet. + * + * @param p the input packet for which the 'param problem' should be sent, + * p->payload pointing to the IP header + * @param c ICMPv6 code for the param problem type + * @param pointer the pointer to the byte where the parameter is found + */ +void +icmp6_param_problem(struct pbuf *p, enum icmp6_pp_code c, u32_t pointer) +{ + icmp6_send_response(p, c, pointer, ICMP6_TYPE_PP); +} + +/** + * Send an ICMPv6 packet in response to an incoming packet. + * + * @param p the input packet for which the response should be sent, + * p->payload pointing to the IPv6 header + * @param code Code of the ICMPv6 header + * @param data Additional 32-bit parameter in the ICMPv6 header + * @param type Type of the ICMPv6 header + */ +static void +icmp6_send_response(struct pbuf *p, u8_t code, u32_t data, u8_t type) +{ + struct pbuf *q; + struct icmp6_hdr *icmp6hdr; + ip6_addr_t *reply_src, *reply_dest; + ip6_addr_t reply_src_local, reply_dest_local; + struct ip6_hdr *ip6hdr; + struct netif *netif; + + /* ICMPv6 header + IPv6 header + data */ + q = pbuf_alloc(PBUF_IP, sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE, + PBUF_RAM); + if (q == NULL) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMPv6 packet.\n")); + ICMP6_STATS_INC(icmp6.memerr); + return; + } + LWIP_ASSERT("check that first pbuf can hold icmp 6message", + (q->len >= (sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE))); + + icmp6hdr = (struct icmp6_hdr *)q->payload; + icmp6hdr->type = type; + icmp6hdr->code = code; + icmp6hdr->data = data; + + /* copy fields from original packet */ + SMEMCPY((u8_t *)q->payload + sizeof(struct icmp6_hdr), (u8_t *)p->payload, + IP6_HLEN + LWIP_ICMP6_DATASIZE); + + /* Get the destination address and netif for this ICMP message. */ + if ((ip_current_netif() == NULL) || + ((code == ICMP6_TE_FRAG) && (type == ICMP6_TYPE_TE))) { + /* Special case, as ip6_current_xxx is either NULL, or points + * to a different packet than the one that expired. + * We must use the addresses that are stored in the expired packet. */ + ip6hdr = (struct ip6_hdr *)p->payload; + /* copy from packed address to aligned address */ + ip6_addr_copy(reply_dest_local, ip6hdr->src); + ip6_addr_copy(reply_src_local, ip6hdr->dest); + reply_dest = &reply_dest_local; + reply_src = &reply_src_local; + netif = ip6_route(reply_src, reply_dest); + if (netif == NULL) { + /* drop */ + pbuf_free(q); + ICMP6_STATS_INC(icmp6.rterr); + return; + } + } + else { + netif = ip_current_netif(); + reply_dest = ip6_current_src_addr(); + + /* Select an address to use as source. */ + reply_src = ip6_select_source_address(netif, reply_dest); + if (reply_src == NULL) { + /* drop */ + pbuf_free(q); + ICMP6_STATS_INC(icmp6.rterr); + return; + } + } + + /* calculate checksum */ + icmp6hdr->chksum = 0; +#if CHECKSUM_GEN_ICMP6 + icmp6hdr->chksum = ip6_chksum_pseudo(q, IP6_NEXTH_ICMP6, q->tot_len, + reply_src, reply_dest); +#endif /* CHECKSUM_GEN_ICMP6 */ + + ICMP6_STATS_INC(icmp6.xmit); + ip6_output_if(q, reply_src, reply_dest, LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif); + pbuf_free(q); +} + +#endif /* LWIP_ICMP6 && LWIP_IPV6 */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv6/inet6.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv6/inet6.c new file mode 100644 index 0000000..bdf4ff4 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv6/inet6.c @@ -0,0 +1,51 @@ +/** + * @file + * + * INET v6 addresses. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV6 && LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/inet6.h" + +/** @see ip6_addr.c for implementation of functions. */ + +#endif /* LWIP_IPV6 */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv6/ip6.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv6/ip6.c new file mode 100644 index 0000000..f29b09b --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv6/ip6.c @@ -0,0 +1,1052 @@ +/** + * @file + * + * IPv6 layer. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + + +#include "lwip/opt.h" + +#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/netif.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/ip6_frag.h" +#include "lwip/icmp6.h" +#include "lwip/raw.h" +#include "lwip/udp.h" +#include "lwip/tcp_impl.h" +#include "lwip/dhcp6.h" +#include "lwip/nd6.h" +#include "lwip/mld6.h" +#include "lwip/debug.h" +#include "lwip/stats.h" + + +/** + * Finds the appropriate network interface for a given IPv6 address. It tries to select + * a netif following a sequence of heuristics: + * 1) if there is only 1 netif, return it + * 2) if the destination is a link-local address, try to match the src address to a netif. + * this is a tricky case because with multiple netifs, link-local addresses only have + * meaning within a particular subnet/link. + * 3) tries to match the destination subnet to a configured address + * 4) tries to find a router + * 5) tries to match the source address to the netif + * 6) returns the default netif, if configured + * + * @param src the source IPv6 address, if known + * @param dest the destination IPv6 address for which to find the route + * @return the netif on which to send to reach dest + */ +struct netif * +ip6_route(struct ip6_addr *src, struct ip6_addr *dest) +{ + struct netif *netif; + s8_t i; + + /* If single netif configuration, fast return. */ + if ((netif_list != NULL) && (netif_list->next == NULL)) { + return netif_list; + } + + /* Special processing for link-local addresses. */ + if (ip6_addr_islinklocal(dest)) { + if (ip6_addr_isany(src)) { + /* Use default netif. */ + return netif_default; + } + + /* Try to find the netif for the source address. */ + for(netif = netif_list; netif != NULL; netif = netif->next) { + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_cmp(src, netif_ip6_addr(netif, i))) { + return netif; + } + } + } + + /* netif not found, use default netif */ + return netif_default; + } + + /* See if the destination subnet matches a configured address. */ + for(netif = netif_list; netif != NULL; netif = netif->next) { + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) { + return netif; + } + } + } + + /* Get the netif for a suitable router. */ + i = nd6_select_router(dest, NULL); + if (i >= 0) { + if (default_router_list[i].neighbor_entry != NULL) { + if (default_router_list[i].neighbor_entry->netif != NULL) { + return default_router_list[i].neighbor_entry->netif; + } + } + } + + /* try with the netif that matches the source address. */ + if (!ip6_addr_isany(src)) { + for(netif = netif_list; netif != NULL; netif = netif->next) { + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_cmp(src, netif_ip6_addr(netif, i))) { + return netif; + } + } + } + } + + /* no matching netif found, use default netif */ + return netif_default; +} + +/** + * Select the best IPv6 source address for a given destination + * IPv6 address. Loosely follows RFC 3484. "Strong host" behavior + * is assumed. + * + * @param netif the netif on which to send a packet + * @param dest the destination we are trying to reach + * @return the most suitable source address to use, or NULL if no suitable + * source address is found + */ +ip6_addr_t * +ip6_select_source_address(struct netif *netif, ip6_addr_t * dest) +{ + ip6_addr_t * src = NULL; + u8_t i; + + /* If dest is link-local, choose a link-local source. */ + if (ip6_addr_islinklocal(dest) || ip6_addr_ismulticast_linklocal(dest) || ip6_addr_ismulticast_iflocal(dest)) { + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_islinklocal(netif_ip6_addr(netif, i))) { + return netif_ip6_addr(netif, i); + } + } + } + + /* Choose a site-local with matching prefix. */ + if (ip6_addr_issitelocal(dest) || ip6_addr_ismulticast_sitelocal(dest)) { + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_issitelocal(netif_ip6_addr(netif, i)) && + ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) { + return netif_ip6_addr(netif, i); + } + } + } + + /* Choose a unique-local with matching prefix. */ + if (ip6_addr_isuniquelocal(dest) || ip6_addr_ismulticast_orglocal(dest)) { + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_isuniquelocal(netif_ip6_addr(netif, i)) && + ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) { + return netif_ip6_addr(netif, i); + } + } + } + + /* Choose a global with best matching prefix. */ + if (ip6_addr_isglobal(dest) || ip6_addr_ismulticast_global(dest)) { + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_isglobal(netif_ip6_addr(netif, i))) { + if (src == NULL) { + src = netif_ip6_addr(netif, i); + } + else { + /* Replace src only if we find a prefix match. */ + /* TODO find longest matching prefix. */ + if ((!(ip6_addr_netcmp(src, dest))) && + ip6_addr_netcmp(netif_ip6_addr(netif, i), dest)) { + src = netif_ip6_addr(netif, i); + } + } + } + } + if (src != NULL) { + return src; + } + } + + /* Last resort: see if arbitrary prefix matches. */ + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) { + return netif_ip6_addr(netif, i); + } + } + + return NULL; +} + +#if LWIP_IPV6_FORWARD +/** + * Forwards an IPv6 packet. It finds an appropriate route for the + * packet, decrements the HL value of the packet, and outputs + * the packet on the appropriate interface. + * + * @param p the packet to forward (p->payload points to IP header) + * @param iphdr the IPv6 header of the input packet + * @param inp the netif on which this packet was received + */ +static void +ip6_forward(struct pbuf *p, struct ip6_hdr *iphdr, struct netif *inp) +{ + struct netif *netif; + + /* do not forward link-local addresses */ + if (ip6_addr_islinklocal(ip6_current_dest_addr())) { + LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not forwarding link-local address.\n")); + IP6_STATS_INC(ip6.rterr); + IP6_STATS_INC(ip6.drop); + return; + } + + /* Find network interface where to forward this IP packet to. */ + netif = ip6_route(IP6_ADDR_ANY, ip6_current_dest_addr()); + if (netif == NULL) { + LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: no route for %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n", + IP6_ADDR_BLOCK1(ip6_current_dest_addr()), + IP6_ADDR_BLOCK2(ip6_current_dest_addr()), + IP6_ADDR_BLOCK3(ip6_current_dest_addr()), + IP6_ADDR_BLOCK4(ip6_current_dest_addr()), + IP6_ADDR_BLOCK5(ip6_current_dest_addr()), + IP6_ADDR_BLOCK6(ip6_current_dest_addr()), + IP6_ADDR_BLOCK7(ip6_current_dest_addr()), + IP6_ADDR_BLOCK8(ip6_current_dest_addr()))); +#if LWIP_ICMP6 + /* Don't send ICMP messages in response to ICMP messages */ + if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) { + icmp6_dest_unreach(p, ICMP6_DUR_NO_ROUTE); + } +#endif /* LWIP_ICMP6 */ + IP6_STATS_INC(ip6.rterr); + IP6_STATS_INC(ip6.drop); + return; + } + /* Do not forward packets onto the same network interface on which + * they arrived. */ + if (netif == inp) { + LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not bouncing packets back on incoming interface.\n")); + IP6_STATS_INC(ip6.rterr); + IP6_STATS_INC(ip6.drop); + return; + } + + /* decrement HL */ + IP6H_HOPLIM_SET(iphdr, IP6H_HOPLIM(iphdr) - 1); + /* send ICMP6 if HL == 0 */ + if (IP6H_HOPLIM(iphdr) == 0) { +#if LWIP_ICMP6 + /* Don't send ICMP messages in response to ICMP messages */ + if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) { + icmp6_time_exceeded(p, ICMP6_TE_HL); + } +#endif /* LWIP_ICMP6 */ + IP6_STATS_INC(ip6.drop); + return; + } + + if (netif->mtu && (p->tot_len > netif->mtu)) { +#if LWIP_ICMP6 + /* Don't send ICMP messages in response to ICMP messages */ + if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) { + icmp6_packet_too_big(p, netif->mtu); + } +#endif /* LWIP_ICMP6 */ + IP6_STATS_INC(ip6.drop); + return; + } + + LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: forwarding packet to %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n", + IP6_ADDR_BLOCK1(ip6_current_dest_addr()), + IP6_ADDR_BLOCK2(ip6_current_dest_addr()), + IP6_ADDR_BLOCK3(ip6_current_dest_addr()), + IP6_ADDR_BLOCK4(ip6_current_dest_addr()), + IP6_ADDR_BLOCK5(ip6_current_dest_addr()), + IP6_ADDR_BLOCK6(ip6_current_dest_addr()), + IP6_ADDR_BLOCK7(ip6_current_dest_addr()), + IP6_ADDR_BLOCK8(ip6_current_dest_addr()))); + + /* transmit pbuf on chosen interface */ + netif->output_ip6(netif, p, ip6_current_dest_addr()); + IP6_STATS_INC(ip6.fw); + IP6_STATS_INC(ip6.xmit); + return; +} +#endif /* LWIP_IPV6_FORWARD */ + + +/** + * This function is called by the network interface device driver when + * an IPv6 packet is received. The function does the basic checks of the + * IP header such as packet size being at least larger than the header + * size etc. If the packet was not destined for us, the packet is + * forwarded (using ip6_forward). + * + * Finally, the packet is sent to the upper layer protocol input function. + * + * @param p the received IPv6 packet (p->payload points to IPv6 header) + * @param inp the netif on which this packet was received + * @return ERR_OK if the packet was processed (could return ERR_* if it wasn't + * processed, but currently always returns ERR_OK) + */ +err_t +ip6_input(struct pbuf *p, struct netif *inp) +{ + struct ip6_hdr *ip6hdr; + struct netif *netif; + u8_t nexth; + u16_t hlen; /* the current header length */ + u8_t i; +#if 0 /*IP_ACCEPT_LINK_LAYER_ADDRESSING*/ + @todo + int check_ip_src=1; +#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */ + + IP6_STATS_INC(ip6.recv); + + /* identify the IP header */ + ip6hdr = (struct ip6_hdr *)p->payload; + if (IP6H_V(ip6hdr) != 6) { + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_WARNING, ("IPv6 packet dropped due to bad version number %"U32_F"\n", + IP6H_V(ip6hdr))); + pbuf_free(p); + IP6_STATS_INC(ip6.err); + IP6_STATS_INC(ip6.drop); + return ERR_OK; + } + + /* header length exceeds first pbuf length, or ip length exceeds total pbuf length? */ + if ((IP6_HLEN > p->len) || ((IP6H_PLEN(ip6hdr) + IP6_HLEN) > p->tot_len)) { + if (IP6_HLEN > p->len) { + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IPv6 header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n", + IP6_HLEN, p->len)); + } + if ((IP6H_PLEN(ip6hdr) + IP6_HLEN) > p->tot_len) { + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IPv6 (plen %"U16_F") is longer than pbuf (len %"U16_F"), IP packet dropped.\n", + IP6H_PLEN(ip6hdr) + IP6_HLEN, p->tot_len)); + } + /* free (drop) packet pbufs */ + pbuf_free(p); + IP6_STATS_INC(ip6.lenerr); + IP6_STATS_INC(ip6.drop); + return ERR_OK; + } + + /* Trim pbuf. This should have been done at the netif layer, + * but we'll do it anyway just to be sure that its done. */ + pbuf_realloc(p, IP6_HLEN + IP6H_PLEN(ip6hdr)); + + /* copy IP addresses to aligned ip6_addr_t */ + ip6_addr_copy(ip_data.current_iphdr_dest.ip6, ip6hdr->dest); + ip6_addr_copy(ip_data.current_iphdr_src.ip6, ip6hdr->src); + + /* current header pointer. */ + ip_data.current_ip6_header = ip6hdr; + + /* In netif, used in case we need to send ICMPv6 packets back. */ + ip_data.current_netif = inp; + + /* match packet against an interface, i.e. is this packet for us? */ + if (ip6_addr_ismulticast(ip6_current_dest_addr())) { + /* Always joined to multicast if-local and link-local all-nodes group. */ + if (ip6_addr_isallnodes_iflocal(ip6_current_dest_addr()) || + ip6_addr_isallnodes_linklocal(ip6_current_dest_addr())) { + netif = inp; + } +#if LWIP_IPV6_MLD + else if (mld6_lookfor_group(inp, ip6_current_dest_addr())) { + netif = inp; + } +#else /* LWIP_IPV6_MLD */ + else if (ip6_addr_issolicitednode(ip6_current_dest_addr())) { + /* Filter solicited node packets when MLD is not enabled + * (for Neighbor discovery). */ + netif = NULL; + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(inp, i)) && + ip6_addr_cmp_solicitednode(ip6_current_dest_addr(), netif_ip6_addr(inp, i))) { + netif = inp; + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: solicited node packet accepted on interface %c%c\n", + netif->name[0], netif->name[1])); + break; + } + } + } +#endif /* LWIP_IPV6_MLD */ + else { + netif = NULL; + } + } + else { + /* start trying with inp. if that's not acceptable, start walking the + list of configured netifs. + 'first' is used as a boolean to mark whether we started walking the list */ + int first = 1; + netif = inp; + do { + /* interface is up? */ + if (netif_is_up(netif)) { + /* unicast to this interface address? address configured? */ + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_cmp(ip6_current_dest_addr(), netif_ip6_addr(netif, i))) { + /* exit outer loop */ + goto netif_found; + } + } + } + if (ip6_addr_islinklocal(ip6_current_dest_addr())) { + /* Do not match link-local addresses to other netifs. */ + netif = NULL; + break; + } + if (first) { + first = 0; + netif = netif_list; + } else { + netif = netif->next; + } + if (netif == inp) { + netif = netif->next; + } + } while(netif != NULL); +netif_found: + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet accepted on interface %c%c\n", + netif ? netif->name[0] : 'X', netif? netif->name[1] : 'X')); + } + + /* "::" packet source address? (used in duplicate address detection) */ + if (ip6_addr_isany(ip6_current_src_addr()) && + (!ip6_addr_issolicitednode(ip6_current_dest_addr()))) { + /* packet source is not valid */ + /* free (drop) packet pbufs */ + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with src ANY_ADDRESS dropped\n")); + pbuf_free(p); + IP6_STATS_INC(ip6.drop); + goto ip6_input_cleanup; + } + + /* packet not for us? */ + if (netif == NULL) { + /* packet not for us, route or discard */ + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_TRACE, ("ip6_input: packet not for us.\n")); +#if LWIP_IPV6_FORWARD + /* non-multicast packet? */ + if (!ip6_addr_ismulticast(ip6_current_dest_addr())) { + /* try to forward IP packet on (other) interfaces */ + ip6_forward(p, ip6hdr, inp); + } +#endif /* LWIP_IPV6_FORWARD */ + pbuf_free(p); + goto ip6_input_cleanup; + } + + /* current netif pointer. */ + ip_data.current_netif = netif; + + /* Save next header type. */ + nexth = IP6H_NEXTH(ip6hdr); + + /* Init header length. */ + hlen = ip_data.current_ip_header_tot_len = IP6_HLEN; + + /* Move to payload. */ + pbuf_header(p, -IP6_HLEN); + + /* Process known option extension headers, if present. */ + while (nexth != IP6_NEXTH_NONE) + { + switch (nexth) { + case IP6_NEXTH_HOPBYHOP: + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Hop-by-Hop options header\n")); + /* Get next header type. */ + nexth = *((u8_t *)p->payload); + + /* Get the header length. */ + hlen = 8 * (1 + *((u8_t *)p->payload + 1)); + ip_data.current_ip_header_tot_len += hlen; + + /* Skip over this header. */ + if (hlen > p->len) { + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", + hlen, p->len)); + /* free (drop) packet pbufs */ + pbuf_free(p); + IP6_STATS_INC(ip6.lenerr); + IP6_STATS_INC(ip6.drop); + goto ip6_input_cleanup; + } + + pbuf_header(p, -hlen); + break; + case IP6_NEXTH_DESTOPTS: + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Destination options header\n")); + /* Get next header type. */ + nexth = *((u8_t *)p->payload); + + /* Get the header length. */ + hlen = 8 * (1 + *((u8_t *)p->payload + 1)); + ip_data.current_ip_header_tot_len += hlen; + + /* Skip over this header. */ + if (hlen > p->len) { + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", + hlen, p->len)); + /* free (drop) packet pbufs */ + pbuf_free(p); + IP6_STATS_INC(ip6.lenerr); + IP6_STATS_INC(ip6.drop); + goto ip6_input_cleanup; + } + + pbuf_header(p, -hlen); + break; + case IP6_NEXTH_ROUTING: + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Routing header\n")); + /* Get next header type. */ + nexth = *((u8_t *)p->payload); + + /* Get the header length. */ + hlen = 8 * (1 + *((u8_t *)p->payload + 1)); + ip_data.current_ip_header_tot_len += hlen; + + /* Skip over this header. */ + if (hlen > p->len) { + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", + hlen, p->len)); + /* free (drop) packet pbufs */ + pbuf_free(p); + IP6_STATS_INC(ip6.lenerr); + IP6_STATS_INC(ip6.drop); + goto ip6_input_cleanup; + } + + pbuf_header(p, -hlen); + break; + + case IP6_NEXTH_FRAGMENT: + { + struct ip6_frag_hdr * frag_hdr; + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Fragment header\n")); + + frag_hdr = (struct ip6_frag_hdr *)p->payload; + + /* Get next header type. */ + nexth = frag_hdr->_nexth; + + /* Fragment Header length. */ + hlen = 8; + ip_data.current_ip_header_tot_len += hlen; + + /* Make sure this header fits in current pbuf. */ + if (hlen > p->len) { + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", + hlen, p->len)); + /* free (drop) packet pbufs */ + pbuf_free(p); + IP6_FRAG_STATS_INC(ip6_frag.lenerr); + IP6_FRAG_STATS_INC(ip6_frag.drop); + goto ip6_input_cleanup; + } + + /* Offset == 0 and more_fragments == 0? */ + if (((frag_hdr->_fragment_offset & IP6_FRAG_OFFSET_MASK) == 0) && + ((frag_hdr->_fragment_offset & IP6_FRAG_MORE_FLAG) == 0)) { + + /* This is a 1-fragment packet, usually a packet that we have + * already reassembled. Skip this header anc continue. */ + pbuf_header(p, -hlen); + } + else { +#if LWIP_IPV6_REASS + + /* reassemble the packet */ + p = ip6_reass(p); + /* packet not fully reassembled yet? */ + if (p == NULL) { + goto ip6_input_cleanup; + } + + /* Returned p point to IPv6 header. + * Update all our variables and pointers and continue. */ + ip6hdr = (struct ip6_hdr *)p->payload; + nexth = IP6H_NEXTH(ip6hdr); + hlen = ip_data.current_ip_header_tot_len = IP6_HLEN; + pbuf_header(p, -IP6_HLEN); + +#else /* LWIP_IPV6_REASS */ + /* free (drop) packet pbufs */ + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Fragment header dropped (with LWIP_IPV6_REASS==0)\n")); + pbuf_free(p); + IP6_STATS_INC(ip6.opterr); + IP6_STATS_INC(ip6.drop); + goto ip6_input_cleanup; +#endif /* LWIP_IPV6_REASS */ + } + break; + } + default: + goto options_done; + break; + } + } +options_done: + + /* p points to IPv6 header again. */ + /* @todo: this does not work for PBUF_REF pbufs */ + pbuf_header(p, ip_data.current_ip_header_tot_len); + + /* send to upper layers */ + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: \n")); + ip6_debug_print(p); + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len)); + + //Evan add for debug + //printf("\n\r[Evan] header len = %"U16_F", total len = %"U16_F"\n", hlen, p->tot_len); + //char temp[1000] = {"\0"}; + //memcpy(temp, p->payload, p->tot_len); + //printf("\n\rReceive ipv6 socket = %s\n", &temp[48]); + //Evan add end + +#if LWIP_RAW + /* raw input did not eat the packet? */ + if (raw_input(p, inp) == 0) +#endif /* LWIP_RAW */ + { + switch (nexth) { + case IP6_NEXTH_NONE: + pbuf_free(p); + break; +#if LWIP_UDP + case IP6_NEXTH_UDP: +#if LWIP_UDPLITE + case IP6_NEXTH_UDPLITE: +#endif /* LWIP_UDPLITE */ + /* Point to payload. */ + pbuf_header(p, -ip_data.current_ip_header_tot_len); + udp_input(p, inp); + break; +#endif /* LWIP_UDP */ +#if LWIP_TCP + case IP6_NEXTH_TCP: + /* Point to payload. */ + pbuf_header(p, -ip_data.current_ip_header_tot_len); + tcp_input(p, inp); + break; +#endif /* LWIP_TCP */ +#if LWIP_ICMP6 + case IP6_NEXTH_ICMP6: + /* Point to payload. */ + pbuf_header(p, -ip_data.current_ip_header_tot_len); + icmp6_input(p, inp); + break; +#endif /* LWIP_ICMP */ + default: +#if LWIP_ICMP6 + /* send ICMP parameter problem unless it was a multicast or ICMPv6 */ + if ((!ip6_addr_ismulticast(ip6_current_dest_addr())) && + (IP6H_NEXTH(ip6hdr) != IP6_NEXTH_ICMP6)) { + icmp6_param_problem(p, ICMP6_PP_HEADER, ip_data.current_ip_header_tot_len - hlen); + } +#endif /* LWIP_ICMP */ + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_input: Unsupported transport protocol %"U16_F"\n", IP6H_NEXTH(ip6hdr))); + pbuf_free(p); + IP6_STATS_INC(ip6.proterr); + IP6_STATS_INC(ip6.drop); + break; + } + } + +ip6_input_cleanup: + ip_data.current_netif = NULL; + ip_data.current_ip6_header = NULL; + ip_data.current_ip_header_tot_len = 0; + ip6_addr_set_any(&ip_data.current_iphdr_src.ip6); + ip6_addr_set_any(&ip_data.current_iphdr_dest.ip6); + + return ERR_OK; +} + + +/** + * Sends an IPv6 packet on a network interface. This function constructs + * the IPv6 header. If the source IPv6 address is NULL, the IPv6 "ANY" address is + * used as source (usually during network startup). If the source IPv6 address it + * IP6_ADDR_ANY, the most appropriate IPv6 address of the outgoing network + * interface is filled in as source address. If the destination IPv6 address is + * IP_HDRINCL, p is assumed to already include an IPv6 header and p->payload points + * to it instead of the data. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == IP_HDRINCL, p already includes an + IPv6 header and p->payload points to that IPv6 header) + * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an + * IP address of the netif is selected and used as source address. + * if src == NULL, IP6_ADDR_ANY is used as source) + * @param dest the destination IPv6 address to send the packet to + * @param hl the Hop Limit value to be set in the IPv6 header + * @param tc the Traffic Class value to be set in the IPv6 header + * @param nexth the Next Header to be set in the IPv6 header + * @param netif the netif on which to send this packet + * @return ERR_OK if the packet was sent OK + * ERR_BUF if p doesn't have enough space for IPv6/LINK headers + * returns errors returned by netif->output + */ +err_t +ip6_output_if(struct pbuf *p, ip6_addr_t *src, ip6_addr_t *dest, + u8_t hl, u8_t tc, + u8_t nexth, struct netif *netif) +{ + ip6_addr_t *src_used = src; + if (dest != IP_HDRINCL) { + if (src != NULL && ip6_addr_isany(src)) { + src = ip6_select_source_address(netif, dest); + if ((src == NULL) || ip6_addr_isany(src)) { + /* No appropriate source address was found for this packet. */ + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: No suitable source address for packet.\n")); + IP6_STATS_INC(ip6.rterr); + return ERR_RTE; + } + } + } + return ip6_output_if_src(p, src_used, dest, hl, tc, nexth, netif); +} + +/** + * Same as ip6_output_if() but 'src' address is not replaced by netif address + * when it is 'any'. + */ +err_t +ip6_output_if_src(struct pbuf *p, ip6_addr_t *src, ip6_addr_t *dest, + u8_t hl, u8_t tc, + u8_t nexth, struct netif *netif) +{ + struct ip6_hdr *ip6hdr; + ip6_addr_t dest_addr; + + LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); + + /* Should the IPv6 header be generated or is it already included in p? */ + if (dest != IP_HDRINCL) { + /* generate IPv6 header */ + if (pbuf_header(p, IP6_HLEN)) { + LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: not enough room for IPv6 header in pbuf\n")); + IP6_STATS_INC(ip6.err); + return ERR_BUF; + } + + ip6hdr = (struct ip6_hdr *)p->payload; + LWIP_ASSERT("check that first pbuf can hold struct ip6_hdr", + (p->len >= sizeof(struct ip6_hdr))); + + IP6H_HOPLIM_SET(ip6hdr, hl); + IP6H_NEXTH_SET(ip6hdr, nexth); + + /* dest cannot be NULL here */ + ip6_addr_copy(ip6hdr->dest, *dest); + + IP6H_VTCFL_SET(ip6hdr, 6, tc, 0); + IP6H_PLEN_SET(ip6hdr, p->tot_len - IP6_HLEN); + + if (src == NULL) { + src = IP6_ADDR_ANY; + } + /* src cannot be NULL here */ + ip6_addr_copy(ip6hdr->src, *src); + + } else { + /* IP header already included in p */ + ip6hdr = (struct ip6_hdr *)p->payload; + ip6_addr_copy(dest_addr, ip6hdr->dest); + dest = &dest_addr; + } + + IP6_STATS_INC(ip6.xmit); + + LWIP_DEBUGF(IP6_DEBUG, ("ip6_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], netif->num)); + ip6_debug_print(p); + +#if ENABLE_LOOPBACK + { + int i; + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_cmp(dest, netif_ip6_addr(netif, i))) { + /* Packet to self, enqueue it for loopback */ + LWIP_DEBUGF(IP6_DEBUG, ("netif_loop_output()\n")); + return netif_loop_output(netif, p); + } + } + } +#endif /* ENABLE_LOOPBACK */ +#if LWIP_IPV6_FRAG + /* don't fragment if interface has mtu set to 0 [loopif] */ + if (netif->mtu && (p->tot_len > nd6_get_destination_mtu(dest, netif))) { + return ip6_frag(p, netif, dest); + } +#endif /* LWIP_IPV6_FRAG */ + + LWIP_DEBUGF(IP6_DEBUG, ("netif->output_ip6()\n")); + return netif->output_ip6(netif, p, dest); +} + +/** + * Simple interface to ip6_output_if. It finds the outgoing network + * interface and calls upon ip6_output_if to do the actual work. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == IP_HDRINCL, p already includes an + IPv6 header and p->payload points to that IPv6 header) + * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an + * IP address of the netif is selected and used as source address. + * if src == NULL, IP6_ADDR_ANY is used as source) + * @param dest the destination IPv6 address to send the packet to + * @param hl the Hop Limit value to be set in the IPv6 header + * @param tc the Traffic Class value to be set in the IPv6 header + * @param nexth the Next Header to be set in the IPv6 header + * + * @return ERR_RTE if no route is found + * see ip_output_if() for more return values + */ +err_t +ip6_output(struct pbuf *p, ip6_addr_t *src, ip6_addr_t *dest, + u8_t hl, u8_t tc, u8_t nexth) +{ + struct netif *netif; + struct ip6_hdr *ip6hdr; + ip6_addr_t src_addr, dest_addr; + + LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); + + if (dest != IP_HDRINCL) { + netif = ip6_route(src, dest); + } else { + /* IP header included in p, read addresses. */ + ip6hdr = (struct ip6_hdr *)p->payload; + ip6_addr_copy(src_addr, ip6hdr->src); + ip6_addr_copy(dest_addr, ip6hdr->dest); + netif = ip6_route(&src_addr, &dest_addr); + } + + if (netif == NULL) { + LWIP_DEBUGF(IP6_DEBUG, ("ip6_output: no route for %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n", + IP6_ADDR_BLOCK1(dest), + IP6_ADDR_BLOCK2(dest), + IP6_ADDR_BLOCK3(dest), + IP6_ADDR_BLOCK4(dest), + IP6_ADDR_BLOCK5(dest), + IP6_ADDR_BLOCK6(dest), + IP6_ADDR_BLOCK7(dest), + IP6_ADDR_BLOCK8(dest))); + IP6_STATS_INC(ip6.rterr); + return ERR_RTE; + } + + return ip6_output_if(p, src, dest, hl, tc, nexth, netif); +} + + +#if LWIP_NETIF_HWADDRHINT +/** Like ip6_output, but takes and addr_hint pointer that is passed on to netif->addr_hint + * before calling ip6_output_if. + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == IP_HDRINCL, p already includes an + IPv6 header and p->payload points to that IPv6 header) + * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an + * IP address of the netif is selected and used as source address. + * if src == NULL, IP6_ADDR_ANY is used as source) + * @param dest the destination IPv6 address to send the packet to + * @param hl the Hop Limit value to be set in the IPv6 header + * @param tc the Traffic Class value to be set in the IPv6 header + * @param nexth the Next Header to be set in the IPv6 header + * @param addr_hint address hint pointer set to netif->addr_hint before + * calling ip_output_if() + * + * @return ERR_RTE if no route is found + * see ip_output_if() for more return values + */ +err_t +ip6_output_hinted(struct pbuf *p, ip6_addr_t *src, ip6_addr_t *dest, + u8_t hl, u8_t tc, u8_t nexth, u8_t *addr_hint) +{ + struct netif *netif; + struct ip6_hdr *ip6hdr; + ip6_addr_t src_addr, dest_addr; + err_t err; + + LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); + + if (dest != IP_HDRINCL) { + netif = ip6_route(src, dest); + } else { + /* IP header included in p, read addresses. */ + ip6hdr = (struct ip6_hdr *)p->payload; + ip6_addr_copy(src_addr, ip6hdr->src); + ip6_addr_copy(dest_addr, ip6hdr->dest); + netif = ip6_route(&src_addr, &dest_addr); + } + + if (netif == NULL) { + LWIP_DEBUGF(IP6_DEBUG, ("ip6_output: no route for %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n", + IP6_ADDR_BLOCK1(dest), + IP6_ADDR_BLOCK2(dest), + IP6_ADDR_BLOCK3(dest), + IP6_ADDR_BLOCK4(dest), + IP6_ADDR_BLOCK5(dest), + IP6_ADDR_BLOCK6(dest), + IP6_ADDR_BLOCK7(dest), + IP6_ADDR_BLOCK8(dest))); + IP6_STATS_INC(ip6.rterr); + return ERR_RTE; + } + + NETIF_SET_HWADDRHINT(netif, addr_hint); + err = ip6_output_if(p, src, dest, hl, tc, nexth, netif); + NETIF_SET_HWADDRHINT(netif, NULL); + + return err; +} +#endif /* LWIP_NETIF_HWADDRHINT*/ + +#if LWIP_IPV6_MLD +/** + * Add a hop-by-hop options header with a router alert option and padding. + * + * Used by MLD when sending a Multicast listener report/done message. + * + * @param p the packet to which we will prepend the options header + * @param nexth the next header protocol number (e.g. IP6_NEXTH_ICMP6) + * @param value the value of the router alert option data (e.g. IP6_ROUTER_ALERT_VALUE_MLD) + * @return ERR_OK if hop-by-hop header was added, ERR_* otherwise + */ +err_t +ip6_options_add_hbh_ra(struct pbuf * p, u8_t nexth, u8_t value) +{ + struct ip6_hbh_hdr * hbh_hdr; + + /* Move pointer to make room for hop-by-hop options header. */ + if (pbuf_header(p, sizeof(struct ip6_hbh_hdr))) { + LWIP_DEBUGF(IP6_DEBUG, ("ip6_options: no space for options header\n")); + IP6_STATS_INC(ip6.err); + return ERR_BUF; + } + + hbh_hdr = (struct ip6_hbh_hdr *)p->payload; + + /* Set fields. */ + hbh_hdr->_nexth = nexth; + hbh_hdr->_hlen = 0; + hbh_hdr->_ra_opt_type = IP6_ROUTER_ALERT_OPTION; + hbh_hdr->_ra_opt_dlen = 2; + hbh_hdr->_ra_opt_data = value; + hbh_hdr->_padn_opt_type = IP6_PADN_ALERT_OPTION; + hbh_hdr->_padn_opt_dlen = 0; + + return ERR_OK; +} +#endif /* LWIP_IPV6_MLD */ + +#if IP6_DEBUG +/* Print an IPv6 header by using LWIP_DEBUGF + * @param p an IPv6 packet, p->payload pointing to the IPv6 header + */ +void +ip6_debug_print(struct pbuf *p) +{ + struct ip6_hdr *ip6hdr = (struct ip6_hdr *)p->payload; + + LWIP_DEBUGF(IP6_DEBUG, ("IPv6 header:\n")); + LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP6_DEBUG, ("| %2"U16_F" | %3"U16_F" | %7"U32_F" | (ver, class, flow)\n", + IP6H_V(ip6hdr), + IP6H_TC(ip6hdr), + IP6H_FL(ip6hdr))); + LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP6_DEBUG, ("| %5"U16_F" | %3"U16_F" | %3"U16_F" | (plen, nexth, hopl)\n", + IP6H_PLEN(ip6hdr), + IP6H_NEXTH(ip6hdr), + IP6H_HOPLIM(ip6hdr))); + LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" | (src)\n", + IP6_ADDR_BLOCK1(&(ip6hdr->src)), + IP6_ADDR_BLOCK2(&(ip6hdr->src)), + IP6_ADDR_BLOCK3(&(ip6hdr->src)), + IP6_ADDR_BLOCK4(&(ip6hdr->src)))); + LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" |\n", + IP6_ADDR_BLOCK5(&(ip6hdr->src)), + IP6_ADDR_BLOCK6(&(ip6hdr->src)), + IP6_ADDR_BLOCK7(&(ip6hdr->src)), + IP6_ADDR_BLOCK8(&(ip6hdr->src)))); + LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" | (dest)\n", + IP6_ADDR_BLOCK1(&(ip6hdr->dest)), + IP6_ADDR_BLOCK2(&(ip6hdr->dest)), + IP6_ADDR_BLOCK3(&(ip6hdr->dest)), + IP6_ADDR_BLOCK4(&(ip6hdr->dest)))); + LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" |\n", + IP6_ADDR_BLOCK5(&(ip6hdr->dest)), + IP6_ADDR_BLOCK6(&(ip6hdr->dest)), + IP6_ADDR_BLOCK7(&(ip6hdr->dest)), + IP6_ADDR_BLOCK8(&(ip6hdr->dest)))); + LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); +} +#endif /* IP6_DEBUG */ + +#endif /* LWIP_IPV6 */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv6/ip6_addr.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv6/ip6_addr.c new file mode 100644 index 0000000..66c1e0c --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv6/ip6_addr.c @@ -0,0 +1,251 @@ +/** + * @file + * + * IPv6 addresses. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * Functions for handling IPv6 addresses. + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/ip6_addr.h" +#include "lwip/def.h" + +/* used by IP6_ADDR_ANY in ip6_addr.h */ +const ip6_addr_t ip6_addr_any = { { 0ul, 0ul, 0ul, 0ul } }; + +#ifndef isprint +#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up) +#define isprint(c) in_range(c, 0x20, 0x7f) +#define isdigit(c) in_range(c, '0', '9') +#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F')) +#define islower(c) in_range(c, 'a', 'z') +#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v') +#define xchar(i) ((i) < 10 ? '0' + (i) : 'A' + (i) - 10) +#endif + +/** + * Check whether "cp" is a valid ascii representation + * of an IPv6 address and convert to a binary address. + * Returns 1 if the address is valid, 0 if not. + * + * @param cp IPv6 address in ascii representation (e.g. "FF01::1") + * @param addr pointer to which to save the ip address in network order + * @return 1 if cp could be converted to addr, 0 on failure + */ +int +ip6addr_aton(const char *cp, ip6_addr_t *addr) +{ + u32_t addr_index, zero_blocks, current_block_index, current_block_value; + const char * s; + + /* Count the number of colons, to count the number of blocks in a "::" sequence + zero_blocks may be 1 even if there are no :: sequences */ + zero_blocks = 8; + for (s = cp; *s != 0; s++) { + if (*s == ':') + zero_blocks--; + else if (!isxdigit(*s)) + break; + } + + /* parse each block */ + addr_index = 0; + current_block_index = 0; + current_block_value = 0; + for (s = cp; *s != 0; s++) { + if (*s == ':') { + if (addr) { + if (current_block_index & 0x1) { + addr->addr[addr_index++] |= current_block_value; + } + else { + addr->addr[addr_index] = current_block_value << 16; + } + } + current_block_index++; + current_block_value = 0; + if (current_block_index > 7) { + /* address too long! */ + return 0; + } if (s[1] == ':') { + s++; + /* "::" found, set zeros */ + while (zero_blocks-- > 0) { + if (current_block_index & 0x1) { + addr_index++; + } + else { + if (addr) { + addr->addr[addr_index] = 0; + } + } + current_block_index++; + } + } + } else if (isxdigit(*s)) { + /* add current digit */ + current_block_value = (current_block_value << 4) + + (isdigit(*s) ? *s - '0' : + 10 + (islower(*s) ? *s - 'a' : *s - 'A')); + } else { + /* unexpected digit, space? CRLF? */ + break; + } + } + + if (addr) { + if (current_block_index & 0x1) { + addr->addr[addr_index++] |= current_block_value; + } + else { + addr->addr[addr_index] = current_block_value << 16; + } + } + + /* convert to network byte order. */ + if (addr) { + for (addr_index = 0; addr_index < 4; addr_index++) { + addr->addr[addr_index] = htonl(addr->addr[addr_index]); + } + } + + if (current_block_index != 7) { + return 0; + } + + return 1; +} + +/** + * Convert numeric IPv6 address into ASCII representation. + * returns ptr to static buffer; not reentrant! + * + * @param addr ip6 address in network order to convert + * @return pointer to a global static (!) buffer that holds the ASCII + * representation of addr + */ +char * +ip6addr_ntoa(const ip6_addr_t *addr) +{ + static char str[40]; + return ip6addr_ntoa_r(addr, str, 40); +} + +/** + * Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used. + * + * @param addr ip6 address in network order to convert + * @param buf target buffer where the string is stored + * @param buflen length of buf + * @return either pointer to buf which now holds the ASCII + * representation of addr or NULL if buf was too small + */ +char * +ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen) +{ + u32_t current_block_index, current_block_value; + s32_t zero_flag, i; + + i = 0; + zero_flag = 0; /* used to indicate a zero chain for "::' */ + + for (current_block_index = 0; current_block_index < 8; current_block_index++) { + /* get the current 16-bit block */ + current_block_value = htonl(addr->addr[current_block_index >> 1]); + if ((current_block_index & 0x1) == 0) { + current_block_value = current_block_value >> 16; + } + current_block_value &= 0xffff; + + if (current_block_value == 0) { + /* generate empty block "::" */ + if (!zero_flag) { + if (current_block_index > 0) { + zero_flag = 1; + buf[i++] = ':'; + if (i >= buflen) return NULL; + } + } + } + else { + if (current_block_index > 0) { + buf[i++] = ':'; + if (i >= buflen) return NULL; + } + + if ((current_block_value & 0xf000) == 0) { + zero_flag = 1; + } + else { + buf[i++] = xchar(((current_block_value & 0xf000) >> 12)); + zero_flag = 0; + if (i >= buflen) return NULL; + } + + if (((current_block_value & 0xf00) == 0) && (zero_flag)) { + /* do nothing */ + } + else { + buf[i++] = xchar(((current_block_value & 0xf00) >> 8)); + zero_flag = 0; + if (i >= buflen) return NULL; + } + + if (((current_block_value & 0xf0) == 0) && (zero_flag)) { + /* do nothing */ + } + else { + buf[i++] = xchar(((current_block_value & 0xf0) >> 4)); + zero_flag = 0; + if (i >= buflen) return NULL; + } + + buf[i++] = xchar((current_block_value & 0xf)); + if (i >= buflen) return NULL; + + zero_flag = 0; + } + } + + buf[i] = 0; + + return buf; +} +#endif /* LWIP_IPV6 */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv6/ip6_frag.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv6/ip6_frag.c new file mode 100644 index 0000000..4829ac3 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv6/ip6_frag.c @@ -0,0 +1,716 @@ +/** + * @file + * + * IPv6 fragmentation and reassembly. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#include "lwip/opt.h" +#include "lwip/ip6_frag.h" +#include "lwip/ip6.h" +#include "lwip/icmp6.h" +#include "lwip/nd6.h" +#include "lwip/lwip_ip.h" + +#include "lwip/pbuf.h" +#include "lwip/memp.h" +#include "lwip/stats.h" + +#include + +#if LWIP_IPV6 && LWIP_IPV6_REASS /* don't build if not configured for use in lwipopts.h */ + + +/** Setting this to 0, you can turn off checking the fragments for overlapping + * regions. The code gets a little smaller. Only use this if you know that + * overlapping won't occur on your network! */ +#ifndef IP_REASS_CHECK_OVERLAP +#define IP_REASS_CHECK_OVERLAP 1 +#endif /* IP_REASS_CHECK_OVERLAP */ + +/** Set to 0 to prevent freeing the oldest datagram when the reassembly buffer is + * full (IP_REASS_MAX_PBUFS pbufs are enqueued). The code gets a little smaller. + * Datagrams will be freed by timeout only. Especially useful when MEMP_NUM_REASSDATA + * is set to 1, so one datagram can be reassembled at a time, only. */ +#ifndef IP_REASS_FREE_OLDEST +#define IP_REASS_FREE_OLDEST 1 +#endif /* IP_REASS_FREE_OLDEST */ + +#define IP_REASS_FLAG_LASTFRAG 0x01 + +/** This is a helper struct which holds the starting + * offset and the ending offset of this fragment to + * easily chain the fragments. + * It has the same packing requirements as the IPv6 header, since it replaces + * the Fragment Header in memory in incoming fragments to keep + * track of the various fragments. + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip6_reass_helper { + PACK_STRUCT_FIELD(struct pbuf *next_pbuf); + PACK_STRUCT_FIELD(u16_t start); + PACK_STRUCT_FIELD(u16_t end); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* static variables */ +static struct ip6_reassdata *reassdatagrams; +static u16_t ip6_reass_pbufcount; + +/* Forward declarations. */ +static void ip6_reass_free_complete_datagram(struct ip6_reassdata *ipr); +#if IP_REASS_FREE_OLDEST +static void ip6_reass_remove_oldest_datagram(struct ip6_reassdata *ipr, int pbufs_needed); +#endif /* IP_REASS_FREE_OLDEST */ + +void +ip6_reass_tmr(void) +{ + struct ip6_reassdata *r, *tmp; + + r = reassdatagrams; + while (r != NULL) { + /* Decrement the timer. Once it reaches 0, + * clean up the incomplete fragment assembly */ + if (r->timer > 0) { + r->timer--; + r = r->next; + } else { + /* reassembly timed out */ + tmp = r; + /* get the next pointer before freeing */ + r = r->next; + /* free the helper struct and all enqueued pbufs */ + ip6_reass_free_complete_datagram(tmp); + } + } +} + +/** + * Free a datagram (struct ip6_reassdata) and all its pbufs. + * Updates the total count of enqueued pbufs (ip6_reass_pbufcount), + * sends an ICMP time exceeded packet. + * + * @param ipr datagram to free + */ +static void +ip6_reass_free_complete_datagram(struct ip6_reassdata *ipr) +{ + struct ip6_reassdata *prev; + u16_t pbufs_freed = 0; + u8_t clen; + struct pbuf *p; + struct ip6_reass_helper *iprh; + +#if LWIP_ICMP6 + iprh = (struct ip6_reass_helper *)ipr->p->payload; + if (iprh->start == 0) { + /* The first fragment was received, send ICMP time exceeded. */ + /* First, de-queue the first pbuf from r->p. */ + p = ipr->p; + ipr->p = iprh->next_pbuf; + /* Then, move back to the original header (we are now pointing to Fragment header). */ + if (pbuf_header(p, (u8_t*)p->payload - (u8_t*)ipr->iphdr)) { + LWIP_ASSERT("ip6_reass_free: moving p->payload to ip6 header failed\n", 0); + } + else { + icmp6_time_exceeded(p, ICMP6_TE_FRAG); + } + clen = pbuf_clen(p); + LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); + pbufs_freed += clen; + pbuf_free(p); + } +#endif /* LWIP_ICMP6 */ + + /* First, free all received pbufs. The individual pbufs need to be released + separately as they have not yet been chained */ + p = ipr->p; + while (p != NULL) { + struct pbuf *pcur; + iprh = (struct ip6_reass_helper *)p->payload; + pcur = p; + /* get the next pointer before freeing */ + p = iprh->next_pbuf; + clen = pbuf_clen(pcur); + LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); + pbufs_freed += clen; + pbuf_free(pcur); + } + + /* Then, unchain the struct ip6_reassdata from the list and free it. */ + if (ipr == reassdatagrams) { + reassdatagrams = ipr->next; + } else { + prev = reassdatagrams; + while (prev != NULL) { + if (prev->next == ipr) { + break; + } + prev = prev->next; + } + if (prev != NULL) { + prev->next = ipr->next; + } + } + memp_free(MEMP_IP6_REASSDATA, ipr); + + /* Finally, update number of pbufs in reassembly queue */ + LWIP_ASSERT("ip_reass_pbufcount >= clen", ip6_reass_pbufcount >= pbufs_freed); + ip6_reass_pbufcount -= pbufs_freed; +} + +#if IP_REASS_FREE_OLDEST +/** + * Free the oldest datagram to make room for enqueueing new fragments. + * The datagram ipr is not freed! + * + * @param ipr ip6_reassdata for the current fragment + * @param pbufs_needed number of pbufs needed to enqueue + * (used for freeing other datagrams if not enough space) + */ +static void +ip6_reass_remove_oldest_datagram(struct ip6_reassdata *ipr, int pbufs_needed) +{ + struct ip6_reassdata *r, *oldest; + + /* Free datagrams until being allowed to enqueue 'pbufs_needed' pbufs, + * but don't free the current datagram! */ + do { + r = oldest = reassdatagrams; + while (r != NULL) { + if (r != ipr) { + if (r->timer <= oldest->timer) { + /* older than the previous oldest */ + oldest = r; + } + } + r = r->next; + } + if (oldest != NULL) { + ip6_reass_free_complete_datagram(oldest); + } + } while (((ip6_reass_pbufcount + pbufs_needed) > IP_REASS_MAX_PBUFS) && (reassdatagrams != NULL)); +} +#endif /* IP_REASS_FREE_OLDEST */ + +/** + * Reassembles incoming IPv6 fragments into an IPv6 datagram. + * + * @param p points to the IPv6 Fragment Header + * @param len the length of the payload (after Fragment Header) + * @return NULL if reassembly is incomplete, pbuf pointing to + * IPv6 Header if reassembly is complete + */ +struct pbuf * +ip6_reass(struct pbuf *p) +{ + struct ip6_reassdata *ipr, *ipr_prev; + struct ip6_reass_helper *iprh, *iprh_tmp, *iprh_prev=NULL; + struct ip6_frag_hdr * frag_hdr; + u16_t offset, len; + u8_t clen, valid = 1; + struct pbuf *q; + + IP6_FRAG_STATS_INC(ip6_frag.recv); + + frag_hdr = (struct ip6_frag_hdr *) p->payload; + + clen = pbuf_clen(p); + + offset = ntohs(frag_hdr->_fragment_offset); + + /* Calculate fragment length from IPv6 payload length. + * Adjust for headers before Fragment Header. + * And finally adjust by Fragment Header length. */ + len = ntohs(ip6_current_header()->_plen); + len -= ((u8_t*)p->payload - (u8_t*)ip6_current_header()) - IP6_HLEN; + len -= IP6_FRAG_HLEN; + + /* Look for the datagram the fragment belongs to in the current datagram queue, + * remembering the previous in the queue for later dequeueing. */ + for (ipr = reassdatagrams, ipr_prev = NULL; ipr != NULL; ipr = ipr->next) { + /* Check if the incoming fragment matches the one currently present + in the reassembly buffer. If so, we proceed with copying the + fragment into the buffer. */ + if ((frag_hdr->_identification == ipr->identification) && + ip6_addr_cmp(ip6_current_src_addr(), &(ipr->iphdr->src)) && + ip6_addr_cmp(ip6_current_dest_addr(), &(ipr->iphdr->dest))) { + IP6_FRAG_STATS_INC(ip6_frag.cachehit); + break; + } + ipr_prev = ipr; + } + + if (ipr == NULL) { + /* Enqueue a new datagram into the datagram queue */ + ipr = (struct ip6_reassdata *)memp_malloc(MEMP_IP6_REASSDATA); + if (ipr == NULL) { +#if IP_REASS_FREE_OLDEST + /* Make room and try again. */ + ip6_reass_remove_oldest_datagram(ipr, clen); + ipr = (struct ip6_reassdata *)memp_malloc(MEMP_IP6_REASSDATA); + if (ipr != NULL) { + /* re-search ipr_prev since it might have been removed */ + for (ipr_prev = reassdatagrams; ipr_prev != NULL; ipr_prev = ipr_prev->next) { + if (ipr_prev->next == ipr) { + break; + } + } + } else +#endif /* IP_REASS_FREE_OLDEST */ + { + IP6_FRAG_STATS_INC(ip6_frag.memerr); + IP6_FRAG_STATS_INC(ip6_frag.drop); + goto nullreturn; + } + } + + memset(ipr, 0, sizeof(struct ip6_reassdata)); + ipr->timer = IP_REASS_MAXAGE; + + /* enqueue the new structure to the front of the list */ + ipr->next = reassdatagrams; + reassdatagrams = ipr; + + /* Use the current IPv6 header for src/dest address reference. + * Eventually, we will replace it when we get the first fragment + * (it might be this one, in any case, it is done later). */ + ipr->iphdr = (struct ip6_hdr *)ip6_current_header(); + + /* copy the fragmented packet id. */ + ipr->identification = frag_hdr->_identification; + + /* copy the nexth field */ + ipr->nexth = frag_hdr->_nexth; + } + + /* Check if we are allowed to enqueue more datagrams. */ + if ((ip6_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS) { +#if IP_REASS_FREE_OLDEST + ip6_reass_remove_oldest_datagram(ipr, clen); + if ((ip6_reass_pbufcount + clen) <= IP_REASS_MAX_PBUFS) { + /* re-search ipr_prev since it might have been removed */ + for (ipr_prev = reassdatagrams; ipr_prev != NULL; ipr_prev = ipr_prev->next) { + if (ipr_prev->next == ipr) { + break; + } + } + } else +#endif /* IP_REASS_FREE_OLDEST */ + { + /* @todo: send ICMPv6 time exceeded here? */ + /* drop this pbuf */ + IP6_FRAG_STATS_INC(ip6_frag.memerr); + IP6_FRAG_STATS_INC(ip6_frag.drop); + goto nullreturn; + } + } + + /* Overwrite Fragment Header with our own helper struct. */ + iprh = (struct ip6_reass_helper *)p->payload; + LWIP_ASSERT("sizeof(struct ip6_reass_helper) <= IP6_FRAG_HLEN", + sizeof(struct ip6_reass_helper) <= IP6_FRAG_HLEN); + iprh->next_pbuf = NULL; + iprh->start = (offset & IP6_FRAG_OFFSET_MASK); + iprh->end = (offset & IP6_FRAG_OFFSET_MASK) + len; + + /* find the right place to insert this pbuf */ + /* Iterate through until we either get to the end of the list (append), + * or we find on with a larger offset (insert). */ + for (q = ipr->p; q != NULL;) { + iprh_tmp = (struct ip6_reass_helper*)q->payload; + if (iprh->start < iprh_tmp->start) { +#if IP_REASS_CHECK_OVERLAP + if (iprh->end > iprh_tmp->start) { + /* fragment overlaps with following, throw away */ + IP6_FRAG_STATS_INC(ip6_frag.proterr); + IP6_FRAG_STATS_INC(ip6_frag.drop); + goto nullreturn; + } + if (iprh_prev != NULL) { + if (iprh->start < iprh_prev->end) { + /* fragment overlaps with previous, throw away */ + IP6_FRAG_STATS_INC(ip6_frag.proterr); + IP6_FRAG_STATS_INC(ip6_frag.drop); + goto nullreturn; + } + } +#endif /* IP_REASS_CHECK_OVERLAP */ + /* the new pbuf should be inserted before this */ + iprh->next_pbuf = q; + if (iprh_prev != NULL) { + /* not the fragment with the lowest offset */ + iprh_prev->next_pbuf = p; + } else { + /* fragment with the lowest offset */ + ipr->p = p; + } + break; + } else if(iprh->start == iprh_tmp->start) { + /* received the same datagram twice: no need to keep the datagram */ + IP6_FRAG_STATS_INC(ip6_frag.drop); + goto nullreturn; +#if IP_REASS_CHECK_OVERLAP + } else if(iprh->start < iprh_tmp->end) { + /* overlap: no need to keep the new datagram */ + IP6_FRAG_STATS_INC(ip6_frag.proterr); + IP6_FRAG_STATS_INC(ip6_frag.drop); + goto nullreturn; +#endif /* IP_REASS_CHECK_OVERLAP */ + } else { + /* Check if the fragments received so far have no gaps. */ + if (iprh_prev != NULL) { + if (iprh_prev->end != iprh_tmp->start) { + /* There is a fragment missing between the current + * and the previous fragment */ + valid = 0; + } + } + } + q = iprh_tmp->next_pbuf; + iprh_prev = iprh_tmp; + } + + /* If q is NULL, then we made it to the end of the list. Determine what to do now */ + if (q == NULL) { + if (iprh_prev != NULL) { + /* this is (for now), the fragment with the highest offset: + * chain it to the last fragment */ +#if IP_REASS_CHECK_OVERLAP + LWIP_ASSERT("check fragments don't overlap", iprh_prev->end <= iprh->start); +#endif /* IP_REASS_CHECK_OVERLAP */ + iprh_prev->next_pbuf = p; + if (iprh_prev->end != iprh->start) { + valid = 0; + } + } else { +#if IP_REASS_CHECK_OVERLAP + LWIP_ASSERT("no previous fragment, this must be the first fragment!", + ipr->p == NULL); +#endif /* IP_REASS_CHECK_OVERLAP */ + /* this is the first fragment we ever received for this ip datagram */ + ipr->p = p; + } + } + + /* Track the current number of pbufs current 'in-flight', in order to limit + the number of fragments that may be enqueued at any one time */ + ip6_reass_pbufcount += clen; + + /* Remember IPv6 header if this is the first fragment. */ + if (iprh->start == 0) { + ipr->iphdr = (struct ip6_hdr *)ip6_current_header(); + } + + /* If this is the last fragment, calculate total packet length. */ + if ((offset & IP6_FRAG_MORE_FLAG) == 0) { + ipr->datagram_len = iprh->end; + } + + /* Additional validity tests: we have received first and last fragment. */ + iprh_tmp = (struct ip6_reass_helper*)ipr->p->payload; + if (iprh_tmp->start != 0) { + valid = 0; + } + if (ipr->datagram_len == 0) { + valid = 0; + } + + /* Final validity test: no gaps between current and last fragment. */ + iprh_prev = iprh; + q = iprh->next_pbuf; + while ((q != NULL) && valid) { + iprh = (struct ip6_reass_helper*)q->payload; + if (iprh_prev->end != iprh->start) { + valid = 0; + break; + } + iprh_prev = iprh; + q = iprh->next_pbuf; + } + + if (valid) { + /* All fragments have been received */ + u8_t* iphdr_ptr; + + /* chain together the pbufs contained within the ip6_reassdata list. */ + iprh = (struct ip6_reass_helper*) ipr->p->payload; + while(iprh != NULL) { + + if (iprh->next_pbuf != NULL) { + /* Save next helper struct (will be hidden in next step). */ + iprh_tmp = (struct ip6_reass_helper*) iprh->next_pbuf->payload; + + /* hide the fragment header for every succeeding fragment */ + pbuf_header(iprh->next_pbuf, -IP6_FRAG_HLEN); + pbuf_cat(ipr->p, iprh->next_pbuf); + } + else { + iprh_tmp = NULL; + } + + iprh = iprh_tmp; + } + + /* Adjust datagram length by adding header lengths. */ + ipr->datagram_len += ((u8_t*)ipr->p->payload - (u8_t*)ipr->iphdr) + + IP6_FRAG_HLEN + - IP6_HLEN ; + + /* Set payload length in ip header. */ + ipr->iphdr->_plen = htons(ipr->datagram_len); + + /* Get the first pbuf. */ + p = ipr->p; + + /* Restore Fragment Header in first pbuf. Mark as "single fragment" + * packet. Restore nexth. */ + frag_hdr = (struct ip6_frag_hdr *) p->payload; + frag_hdr->_nexth = ipr->nexth; + frag_hdr->reserved = 0; + frag_hdr->_fragment_offset = 0; + frag_hdr->_identification = 0; + + /* release the sources allocate for the fragment queue entry */ + if (reassdatagrams == ipr) { + /* it was the first in the list */ + reassdatagrams = ipr->next; + } else { + /* it wasn't the first, so it must have a valid 'prev' */ + LWIP_ASSERT("sanity check linked list", ipr_prev != NULL); + ipr_prev->next = ipr->next; + } + iphdr_ptr = (u8_t*)ipr->iphdr; + memp_free(MEMP_IP6_REASSDATA, ipr); + + /* adjust the number of pbufs currently queued for reassembly. */ + ip6_reass_pbufcount -= pbuf_clen(p); + + /* Move pbuf back to IPv6 header. */ + if (pbuf_header(p, (u8_t*)p->payload - iphdr_ptr)) { + LWIP_ASSERT("ip6_reass: moving p->payload to ip6 header failed\n", 0); + pbuf_free(p); + return NULL; + } + + /* Return the pbuf chain */ + return p; + } + /* the datagram is not (yet?) reassembled completely */ + return NULL; + +nullreturn: + pbuf_free(p); + return NULL; +} + +#endif /* LWIP_IPV6 && LWIP_IPV6_REASS */ + +#if LWIP_IPV6 && LWIP_IPV6_FRAG + +/** Allocate a new struct pbuf_custom_ref */ +static struct pbuf_custom_ref* +ip6_frag_alloc_pbuf_custom_ref(void) +{ + return (struct pbuf_custom_ref*)memp_malloc(MEMP_FRAG_PBUF); +} + +/** Free a struct pbuf_custom_ref */ +static void +ip6_frag_free_pbuf_custom_ref(struct pbuf_custom_ref* p) +{ + LWIP_ASSERT("p != NULL", p != NULL); + memp_free(MEMP_FRAG_PBUF, p); +} + +/** Free-callback function to free a 'struct pbuf_custom_ref', called by + * pbuf_free. */ +static void +ip6_frag_free_pbuf_custom(struct pbuf *p) +{ + struct pbuf_custom_ref *pcr = (struct pbuf_custom_ref*)p; + LWIP_ASSERT("pcr != NULL", pcr != NULL); + LWIP_ASSERT("pcr == p", (void*)pcr == (void*)p); + if (pcr->original != NULL) { + pbuf_free(pcr->original); + } + ip6_frag_free_pbuf_custom_ref(pcr); +} + +/** + * Fragment an IPv6 datagram if too large for the netif or path MTU. + * + * Chop the datagram in MTU sized chunks and send them in order + * by pointing PBUF_REFs into p + * + * @param p ipv6 packet to send + * @param netif the netif on which to send + * @param dest destination ipv6 address to which to send + * + * @return ERR_OK if sent successfully, err_t otherwise + */ +err_t +ip6_frag(struct pbuf *p, struct netif *netif, ip6_addr_t *dest) +{ + struct ip6_hdr *original_ip6hdr; + struct ip6_hdr *ip6hdr; + struct ip6_frag_hdr * frag_hdr; + struct pbuf *rambuf; + struct pbuf *newpbuf; + static u32_t identification; + u16_t nfb; + u16_t left, cop; + u16_t mtu; + u16_t fragment_offset = 0; + u16_t last; + u16_t poff = IP6_HLEN; + u16_t newpbuflen = 0; + u16_t left_to_copy; + + identification++; + + original_ip6hdr = (struct ip6_hdr *)p->payload; + + mtu = nd6_get_destination_mtu(dest, netif); + + /* TODO we assume there are no options in the unfragmentable part (IPv6 header). */ + left = p->tot_len - IP6_HLEN; + + nfb = (mtu - (IP6_HLEN + IP6_FRAG_HLEN)) & IP6_FRAG_OFFSET_MASK; + + while (left) { + last = (left <= nfb); + + /* Fill this fragment */ + cop = last ? left : nfb; + + /* When not using a static buffer, create a chain of pbufs. + * The first will be a PBUF_RAM holding the link, IPv6, and Fragment header. + * The rest will be PBUF_REFs mirroring the pbuf chain to be fragged, + * but limited to the size of an mtu. + */ + rambuf = pbuf_alloc(PBUF_LINK, IP6_HLEN + IP6_FRAG_HLEN, PBUF_RAM); + if (rambuf == NULL) { + IP6_FRAG_STATS_INC(ip6_frag.memerr); + return ERR_MEM; + } + LWIP_ASSERT("this needs a pbuf in one piece!", + (p->len >= (IP6_HLEN + IP6_FRAG_HLEN))); + SMEMCPY(rambuf->payload, original_ip6hdr, IP6_HLEN); + ip6hdr = (struct ip6_hdr *)rambuf->payload; + frag_hdr = (struct ip6_frag_hdr *)((u8_t*)rambuf->payload + IP6_HLEN); + + /* Can just adjust p directly for needed offset. */ + p->payload = (u8_t *)p->payload + poff; + p->len -= poff; + p->tot_len -= poff; + + left_to_copy = cop; + while (left_to_copy) { + struct pbuf_custom_ref *pcr; + newpbuflen = (left_to_copy < p->len) ? left_to_copy : p->len; + /* Is this pbuf already empty? */ + if (!newpbuflen) { + p = p->next; + continue; + } + pcr = ip6_frag_alloc_pbuf_custom_ref(); + if (pcr == NULL) { + pbuf_free(rambuf); + IP6_FRAG_STATS_INC(ip6_frag.memerr); + return ERR_MEM; + } + /* Mirror this pbuf, although we might not need all of it. */ + newpbuf = pbuf_alloced_custom(PBUF_RAW, newpbuflen, PBUF_REF, &pcr->pc, p->payload, newpbuflen); + if (newpbuf == NULL) { + ip6_frag_free_pbuf_custom_ref(pcr); + pbuf_free(rambuf); + IP6_FRAG_STATS_INC(ip6_frag.memerr); + return ERR_MEM; + } + pbuf_ref(p); + pcr->original = p; + pcr->pc.custom_free_function = ip6_frag_free_pbuf_custom; + + /* Add it to end of rambuf's chain, but using pbuf_cat, not pbuf_chain + * so that it is removed when pbuf_dechain is later called on rambuf. + */ + pbuf_cat(rambuf, newpbuf); + left_to_copy -= newpbuflen; + if (left_to_copy) { + p = p->next; + } + } + poff = newpbuflen; + + /* Set headers */ + frag_hdr->_nexth = original_ip6hdr->_nexth; + frag_hdr->reserved = 0; + frag_hdr->_fragment_offset = htons((fragment_offset & IP6_FRAG_OFFSET_MASK) | (last ? 0 : IP6_FRAG_MORE_FLAG)); + frag_hdr->_identification = htonl(identification); + + IP6H_NEXTH_SET(ip6hdr, IP6_NEXTH_FRAGMENT); + IP6H_PLEN_SET(ip6hdr, cop + IP6_FRAG_HLEN); + + /* No need for separate header pbuf - we allowed room for it in rambuf + * when allocated. + */ + IP6_FRAG_STATS_INC(ip6_frag.xmit); + netif->output_ip6(netif, rambuf, dest); + + /* Unfortunately we can't reuse rambuf - the hardware may still be + * using the buffer. Instead we free it (and the ensuing chain) and + * recreate it next time round the loop. If we're lucky the hardware + * will have already sent the packet, the free will really free, and + * there will be zero memory penalty. + */ + + pbuf_free(rambuf); + left -= cop; + fragment_offset += cop; + } + return ERR_OK; +} + +#endif /* LWIP_IPV6 && LWIP_IPV6_FRAG */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv6/mld6.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv6/mld6.c new file mode 100644 index 0000000..a884a39 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv6/mld6.c @@ -0,0 +1,586 @@ +/** + * @file + * + * Multicast listener discovery for IPv6. Aims to be compliant with RFC 2710. + * No support for MLDv2. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +/* Based on igmp.c implementation of igmp v2 protocol */ + +#include "lwip/opt.h" + +#if LWIP_IPV6 && LWIP_IPV6_MLD /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/mld6.h" +#include "lwip/icmp6.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/lwip_ip.h" +#include "lwip/inet_chksum.h" +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/memp.h" +#include "lwip/stats.h" + +#include + + +/* + * MLD constants + */ +#define MLD6_HL 1 +#define MLD6_JOIN_DELAYING_MEMBER_TMR_MS (500) + +#define MLD6_GROUP_NON_MEMBER 0 +#define MLD6_GROUP_DELAYING_MEMBER 1 +#define MLD6_GROUP_IDLE_MEMBER 2 + + +/* The list of joined groups. */ +static struct mld_group* mld_group_list; + + +/* Forward declarations. */ +static struct mld_group * mld6_new_group(struct netif *ifp, ip6_addr_t *addr); +static err_t mld6_free_group(struct mld_group *group); +static void mld6_delayed_report(struct mld_group *group, u16_t maxresp); +static void mld6_send(struct mld_group *group, u8_t type); + + +/** + * Stop MLD processing on interface + * + * @param netif network interface on which stop MLD processing + */ +err_t +mld6_stop(struct netif *netif) +{ + struct mld_group *group = mld_group_list; + struct mld_group *prev = NULL; + struct mld_group *next; + + /* look for groups joined on this interface further down the list */ + while (group != NULL) { + next = group->next; + /* is it a group joined on this interface? */ + if (group->netif == netif) { + /* is it the first group of the list? */ + if (group == mld_group_list) { + mld_group_list = next; + } + /* is there a "previous" group defined? */ + if (prev != NULL) { + prev->next = next; + } + /* disable the group at the MAC level */ + if (netif->mld_mac_filter != NULL) { + netif->mld_mac_filter(netif, &(group->group_address), MLD6_DEL_MAC_FILTER); + } + /* free group */ + memp_free(MEMP_MLD6_GROUP, group); + } else { + /* change the "previous" */ + prev = group; + } + /* move to "next" */ + group = next; + } + return ERR_OK; +} + +/** + * Report MLD memberships for this interface + * + * @param netif network interface on which report MLD memberships + */ +void +mld6_report_groups(struct netif *netif) +{ + struct mld_group *group = mld_group_list; + + while (group != NULL) { + if (group->netif == netif) { + mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR_MS); + } + group = group->next; + } +} + +/** + * Search for a group that is joined on a netif + * + * @param ifp the network interface for which to look + * @param addr the group ipv6 address to search for + * @return a struct mld_group* if the group has been found, + * NULL if the group wasn't found. + */ +struct mld_group * +mld6_lookfor_group(struct netif *ifp, ip6_addr_t *addr) +{ + struct mld_group *group = mld_group_list; + + while (group != NULL) { + if ((group->netif == ifp) && (ip6_addr_cmp(&(group->group_address), addr))) { + return group; + } + group = group->next; + } + + return NULL; +} + + +/** + * create a new group + * + * @param ifp the network interface for which to create + * @param addr the new group ipv6 + * @return a struct mld_group*, + * NULL on memory error. + */ +static struct mld_group * +mld6_new_group(struct netif *ifp, ip6_addr_t *addr) +{ + struct mld_group *group; + + group = (struct mld_group *)memp_malloc(MEMP_MLD6_GROUP); + if (group != NULL) { + group->netif = ifp; + ip6_addr_set(&(group->group_address), addr); + group->timer = 0; /* Not running */ + group->group_state = MLD6_GROUP_IDLE_MEMBER; + group->last_reporter_flag = 0; + group->use = 0; + group->next = mld_group_list; + + mld_group_list = group; + } + + return group; +} + +/** + * Remove a group in the mld_group_list and free + * + * @param group the group to remove + * @return ERR_OK if group was removed from the list, an err_t otherwise + */ +static err_t +mld6_free_group(struct mld_group *group) +{ + err_t err = ERR_OK; + + /* Is it the first group? */ + if (mld_group_list == group) { + mld_group_list = group->next; + } else { + /* look for group further down the list */ + struct mld_group *tmpGroup; + for (tmpGroup = mld_group_list; tmpGroup != NULL; tmpGroup = tmpGroup->next) { + if (tmpGroup->next == group) { + tmpGroup->next = group->next; + break; + } + } + /* Group not find group */ + if (tmpGroup == NULL) + err = ERR_ARG; + } + /* free group */ + memp_free(MEMP_MLD6_GROUP, group); + + return err; +} + + +/** + * Process an input MLD message. Called by icmp6_input. + * + * @param p the mld packet, p->payload pointing to the icmpv6 header + * @param inp the netif on which this packet was received + */ +void +mld6_input(struct pbuf *p, struct netif *inp) +{ + struct mld_header * mld_hdr; + struct mld_group* group; + + MLD6_STATS_INC(mld6.recv); + + /* Check that mld header fits in packet. */ + if (p->len < sizeof(struct mld_header)) { + /* TODO debug message */ + pbuf_free(p); + MLD6_STATS_INC(mld6.lenerr); + MLD6_STATS_INC(mld6.drop); + return; + } + + mld_hdr = (struct mld_header *)p->payload; + + switch (mld_hdr->type) { + case ICMP6_TYPE_MLQ: /* Multicast listener query. */ + { + /* Is it a general query? */ + if (ip6_addr_isallnodes_linklocal(ip6_current_dest_addr()) && + ip6_addr_isany(&(mld_hdr->multicast_address))) { + MLD6_STATS_INC(mld6.rx_general); + /* Report all groups, except all nodes group, and if-local groups. */ + group = mld_group_list; + while (group != NULL) { + if ((group->netif == inp) && + (!(ip6_addr_ismulticast_iflocal(&(group->group_address)))) && + (!(ip6_addr_isallnodes_linklocal(&(group->group_address))))) { + mld6_delayed_report(group, mld_hdr->max_resp_delay); + } + group = group->next; + } + } + else { + /* Have we joined this group? + * We use IP6 destination address to have a memory aligned copy. + * mld_hdr->multicast_address should be the same. */ + MLD6_STATS_INC(mld6.rx_group); + group = mld6_lookfor_group(inp, ip6_current_dest_addr()); + if (group != NULL) { + /* Schedule a report. */ + mld6_delayed_report(group, mld_hdr->max_resp_delay); + } + } + break; /* ICMP6_TYPE_MLQ */ + } + case ICMP6_TYPE_MLR: /* Multicast listener report. */ + { + /* Have we joined this group? + * We use IP6 destination address to have a memory aligned copy. + * mld_hdr->multicast_address should be the same. */ + MLD6_STATS_INC(mld6.rx_report); + group = mld6_lookfor_group(inp, ip6_current_dest_addr()); + if (group != NULL) { + /* If we are waiting to report, cancel it. */ + if (group->group_state == MLD6_GROUP_DELAYING_MEMBER) { + group->timer = 0; /* stopped */ + group->group_state = MLD6_GROUP_IDLE_MEMBER; + group->last_reporter_flag = 0; + } + } + break; /* ICMP6_TYPE_MLR */ + } + case ICMP6_TYPE_MLD: /* Multicast listener done. */ + { + /* Do nothing, router will query us. */ + break; /* ICMP6_TYPE_MLD */ + } + default: + MLD6_STATS_INC(mld6.proterr); + MLD6_STATS_INC(mld6.drop); + break; + } + + pbuf_free(p); +} + +/** + * Join a group on a network interface. + * + * @param srcaddr ipv6 address of the network interface which should + * join a new group. If IP6_ADDR_ANY, join on all netifs + * @param groupaddr the ipv6 address of the group to join + * @return ERR_OK if group was joined on the netif(s), an err_t otherwise + */ +err_t +mld6_joingroup(ip6_addr_t *srcaddr, ip6_addr_t *groupaddr) +{ + err_t err = ERR_VAL; /* no matching interface */ + struct mld_group *group; + struct netif *netif; + u8_t match; + u8_t i; + + /* loop through netif's */ + netif = netif_list; + while (netif != NULL) { + /* Should we join this interface ? */ + match = 0; + if (ip6_addr_isany(srcaddr)) { + match = 1; + } + else { + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_cmp(srcaddr, netif_ip6_addr(netif, i))) { + match = 1; + break; + } + } + } + if (match) { + /* find group or create a new one if not found */ + group = mld6_lookfor_group(netif, groupaddr); + + if (group == NULL) { + /* Joining a new group. Create a new group entry. */ + group = mld6_new_group(netif, groupaddr); + if (group == NULL) { + return ERR_MEM; + } + + /* Activate this address on the MAC layer. */ + if (netif->mld_mac_filter != NULL) { + netif->mld_mac_filter(netif, groupaddr, MLD6_ADD_MAC_FILTER); + } + + /* Report our membership. */ + MLD6_STATS_INC(mld6.tx_report); + mld6_send(group, ICMP6_TYPE_MLR); + mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR_MS); + } + + /* Increment group use */ + group->use++; + err = ERR_OK; + } + + /* proceed to next network interface */ + netif = netif->next; + } + + return err; +} + +/** + * Leave a group on a network interface. + * + * @param srcaddr ipv6 address of the network interface which should + * leave the group. If IP6_ISANY, leave on all netifs + * @param groupaddr the ipv6 address of the group to leave + * @return ERR_OK if group was left on the netif(s), an err_t otherwise + */ +err_t +mld6_leavegroup(ip6_addr_t *srcaddr, ip6_addr_t *groupaddr) +{ + err_t err = ERR_VAL; /* no matching interface */ + struct mld_group *group; + struct netif *netif; + u8_t match; + u8_t i; + + /* loop through netif's */ + netif = netif_list; + while (netif != NULL) { + /* Should we leave this interface ? */ + match = 0; + if (ip6_addr_isany(srcaddr)) { + match = 1; + } + else { + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_cmp(srcaddr, netif_ip6_addr(netif, i))) { + match = 1; + break; + } + } + } + if (match) { + /* find group */ + group = mld6_lookfor_group(netif, groupaddr); + + if (group != NULL) { + /* Leave if there is no other use of the group */ + if (group->use <= 1) { + /* If we are the last reporter for this group */ + if (group->last_reporter_flag) { + MLD6_STATS_INC(mld6.tx_leave); + mld6_send(group, ICMP6_TYPE_MLD); + } + + /* Disable the group at the MAC level */ + if (netif->mld_mac_filter != NULL) { + netif->mld_mac_filter(netif, groupaddr, MLD6_DEL_MAC_FILTER); + } + + /* Free the group */ + mld6_free_group(group); + } else { + /* Decrement group use */ + group->use--; + } + /* Leave on this interface */ + err = ERR_OK; + } + } + /* proceed to next network interface */ + netif = netif->next; + } + + return err; +} + + +/** + * Periodic timer for mld processing. Must be called every + * MLD6_TMR_INTERVAL milliseconds (100). + * + * When a delaying member expires, a membership report is sent. + */ +void +mld6_tmr(void) +{ + struct mld_group *group = mld_group_list; + + while (group != NULL) { + if (group->timer > 0) { + group->timer--; + if (group->timer == 0) { + /* If the state is MLD6_GROUP_DELAYING_MEMBER then we send a report for this group */ + if (group->group_state == MLD6_GROUP_DELAYING_MEMBER) { + MLD6_STATS_INC(mld6.tx_report); + mld6_send(group, ICMP6_TYPE_MLR); + group->group_state = MLD6_GROUP_IDLE_MEMBER; + } + } + } + group = group->next; + } +} + +/** + * Schedule a delayed membership report for a group + * + * @param group the mld_group for which "delaying" membership report + * should be sent + * @param maxresp the max resp delay provided in the query + */ +static void +mld6_delayed_report(struct mld_group *group, u16_t maxresp) +{ + /* Convert maxresp from milliseconds to tmr ticks */ + maxresp = maxresp / MLD6_TMR_INTERVAL; + if (maxresp == 0) { + maxresp = 1; + } + +#ifdef LWIP_RAND + /* Randomize maxresp. (if LWIP_RAND is supported) */ + maxresp = LWIP_RAND() % maxresp; + if (maxresp == 0) { + maxresp = 1; + } +#endif /* LWIP_RAND */ + + /* Apply timer value if no report has been scheduled already. */ + if ((group->group_state == MLD6_GROUP_IDLE_MEMBER) || + ((group->group_state == MLD6_GROUP_DELAYING_MEMBER) && + ((group->timer == 0) || (maxresp < group->timer)))) { + group->timer = maxresp; + group->group_state = MLD6_GROUP_DELAYING_MEMBER; + } +} + +/** + * Send a MLD message (report or done). + * + * An IPv6 hop-by-hop options header with a router alert option + * is prepended. + * + * @param group the group to report or quit + * @param type ICMP6_TYPE_MLR (report) or ICMP6_TYPE_MLD (done) + */ +static void +mld6_send(struct mld_group *group, u8_t type) +{ + struct mld_header * mld_hdr; + struct pbuf * p; + ip6_addr_t * src_addr; + + /* Allocate a packet. Size is MLD header + IPv6 Hop-by-hop options header. */ + p = pbuf_alloc(PBUF_IP, sizeof(struct mld_header) + sizeof(struct ip6_hbh_hdr), PBUF_RAM); + if ((p == NULL) || (p->len < (sizeof(struct mld_header) + sizeof(struct ip6_hbh_hdr)))) { + /* We couldn't allocate a suitable pbuf. drop it. */ + if (p != NULL) { + pbuf_free(p); + } + MLD6_STATS_INC(mld6.memerr); + return; + } + + /* Move to make room for Hop-by-hop options header. */ + if (pbuf_header(p, -IP6_HBH_HLEN)) { + pbuf_free(p); + MLD6_STATS_INC(mld6.lenerr); + return; + } + + /* Select our source address. */ + if (!ip6_addr_isvalid(netif_ip6_addr_state(group->netif, 0))) { + /* This is a special case, when we are performing duplicate address detection. + * We must join the multicast group, but we don't have a valid address yet. */ + src_addr = IP6_ADDR_ANY; + } else { + /* Use link-local address as source address. */ + src_addr = netif_ip6_addr(group->netif, 0); + } + + /* MLD message header pointer. */ + mld_hdr = (struct mld_header *)p->payload; + + /* Set fields. */ + mld_hdr->type = type; + mld_hdr->code = 0; + mld_hdr->chksum = 0; + mld_hdr->max_resp_delay = 0; + mld_hdr->reserved = 0; + ip6_addr_set(&(mld_hdr->multicast_address), &(group->group_address)); + +#if CHECKSUM_GEN_ICMP6 + mld_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, + src_addr, &(group->group_address)); +#endif /* CHECKSUM_GEN_ICMP6 */ + + /* Add hop-by-hop headers options: router alert with MLD value. */ + ip6_options_add_hbh_ra(p, IP6_NEXTH_ICMP6, IP6_ROUTER_ALERT_VALUE_MLD); + + /* Send the packet out. */ + MLD6_STATS_INC(mld6.xmit); + ip6_output_if(p, (ip6_addr_isany(src_addr)) ? NULL : src_addr, &(group->group_address), + MLD6_HL, 0, IP6_NEXTH_HOPBYHOP, group->netif); + pbuf_free(p); +} + + + +#endif /* LWIP_IPV6 */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv6/nd6.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv6/nd6.c new file mode 100644 index 0000000..2a46045 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/ipv6/nd6.c @@ -0,0 +1,1793 @@ +/** + * @file + * + * Neighbor discovery and stateless address autoconfiguration for IPv6. + * Aims to be compliant with RFC 4861 (Neighbor discovery) and RFC 4862 + * (Address autoconfiguration). + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#include "lwip/opt.h" + +#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/nd6.h" +#include "lwip/pbuf.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/inet_chksum.h" +#include "lwip/netif.h" +#include "lwip/icmp6.h" +#include "lwip/mld6.h" +#include "lwip/lwip_ip.h" +#include "lwip/stats.h" + +#include + + +/* Router tables. */ +struct nd6_neighbor_cache_entry neighbor_cache[LWIP_ND6_NUM_NEIGHBORS]; +struct nd6_destination_cache_entry destination_cache[LWIP_ND6_NUM_DESTINATIONS]; +struct nd6_prefix_list_entry prefix_list[LWIP_ND6_NUM_PREFIXES]; +struct nd6_router_list_entry default_router_list[LWIP_ND6_NUM_ROUTERS]; + +/* Default values, can be updated by a RA message. */ +u32_t reachable_time = LWIP_ND6_REACHABLE_TIME; +u32_t retrans_timer = LWIP_ND6_RETRANS_TIMER; /* TODO implement this value in timer */ + +/* Index for cache entries. */ +static u8_t nd6_cached_neighbor_index; +static u8_t nd6_cached_destination_index; + +/* Multicast address holder. */ +static ip6_addr_t multicast_address; + +/* Static buffer to parse RA packet options (size of a prefix option, biggest option) */ +static u8_t nd6_ra_buffer[sizeof(struct prefix_option)]; + +/* Forward declarations. */ +static s8_t nd6_find_neighbor_cache_entry(ip6_addr_t * ip6addr); +static s8_t nd6_new_neighbor_cache_entry(void); +static void nd6_free_neighbor_cache_entry(s8_t i); +static s8_t nd6_find_destination_cache_entry(ip6_addr_t * ip6addr); +static s8_t nd6_new_destination_cache_entry(void); +static s8_t nd6_is_prefix_in_netif(ip6_addr_t * ip6addr, struct netif * netif); +static s8_t nd6_get_router(ip6_addr_t * router_addr, struct netif * netif); +static s8_t nd6_new_router(ip6_addr_t * router_addr, struct netif * netif); +static s8_t nd6_get_onlink_prefix(ip6_addr_t * prefix, struct netif * netif); +static s8_t nd6_new_onlink_prefix(ip6_addr_t * prefix, struct netif * netif); + +#define ND6_SEND_FLAG_MULTICAST_DEST 0x01 +#define ND6_SEND_FLAG_ALLNODES_DEST 0x02 +static void nd6_send_ns(struct netif * netif, ip6_addr_t * target_addr, u8_t flags); +static void nd6_send_na(struct netif * netif, ip6_addr_t * target_addr, u8_t flags); +#if LWIP_IPV6_SEND_ROUTER_SOLICIT +static void nd6_send_rs(struct netif * netif); +#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ + +#if LWIP_ND6_QUEUEING +static void nd6_free_q(struct nd6_q_entry *q); +#else /* LWIP_ND6_QUEUEING */ +#define nd6_free_q(q) pbuf_free(q) +#endif /* LWIP_ND6_QUEUEING */ +static void nd6_send_q(s8_t i); + + +/** + * Process an incoming neighbor discovery message + * + * @param p the nd packet, p->payload pointing to the icmpv6 header + * @param inp the netif on which this packet was received + */ +void +nd6_input(struct pbuf *p, struct netif *inp) +{ + u8_t msg_type; + s8_t i; + + ND6_STATS_INC(nd6.recv); + + msg_type = *((u8_t *)p->payload); + switch (msg_type) { + case ICMP6_TYPE_NA: /* Neighbor Advertisement. */ + { + struct na_header * na_hdr; + struct lladdr_option * lladdr_opt; + + /* Check that na header fits in packet. */ + if (p->len < (sizeof(struct na_header))) { + /* TODO debug message */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + na_hdr = (struct na_header *)p->payload; + + /* Unsolicited NA?*/ + if (ip6_addr_ismulticast(ip6_current_dest_addr())) { + /* This is an unsolicited NA. + * link-layer changed? + * part of DAD mechanism? */ + + /* Check that link-layer address option also fits in packet. */ + if (p->len < (sizeof(struct na_header) + sizeof(struct lladdr_option))) { + /* TODO debug message */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header)); + + /* Override ip6_current_dest_addr() so that we have an aligned copy. */ + ip6_addr_set(ip6_current_dest_addr(), &(na_hdr->target_address)); + +#if LWIP_IPV6_DUP_DETECT_ATTEMPTS + /* If the target address matches this netif, it is a DAD response. */ + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_cmp(ip6_current_dest_addr(), netif_ip6_addr(inp, i))) { + /* We are using a duplicate address. */ + netif_ip6_addr_set_state(inp, i, IP6_ADDR_INVALID); + +#if LWIP_IPV6_MLD + /* Leave solicited node multicast group. */ + ip6_addr_set_solicitednode(&multicast_address, netif_ip6_addr(inp, i)->addr[3]); + mld6_leavegroup(netif_ip6_addr(inp, i), &multicast_address); +#endif /* LWIP_IPV6_MLD */ + + + + +#if LWIP_IPV6_AUTOCONFIG + /* Check to see if this address was autoconfigured. */ + if (!ip6_addr_islinklocal(ip6_current_dest_addr())) { + i = nd6_get_onlink_prefix(ip6_current_dest_addr(), inp); + if (i >= 0) { + /* Mark this prefix as duplicate, so that we don't use it + * to generate this address again. */ + prefix_list[i].flags |= ND6_PREFIX_AUTOCONFIG_ADDRESS_DUPLICATE; + } + } +#endif /* LWIP_IPV6_AUTOCONFIG */ + + pbuf_free(p); + return; + } + } +#endif /* LWIP_IPV6_DUP_DETECT_ATTEMPTS */ + + /* This is an unsolicited NA, most likely there was a LLADDR change. */ + i = nd6_find_neighbor_cache_entry(ip6_current_dest_addr()); + if (i >= 0) { + if (na_hdr->flags & ND6_FLAG_OVERRIDE) { + MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); + } + } + } + else { + /* This is a solicited NA. + * neighbor address resolution response? + * neighbor unreachability detection response? */ + + /* Override ip6_current_dest_addr() so that we have an aligned copy. */ + ip6_addr_set(ip6_current_dest_addr(), &(na_hdr->target_address)); + + /* Find the cache entry corresponding to this na. */ + i = nd6_find_neighbor_cache_entry(ip6_current_dest_addr()); + if (i < 0) { + /* We no longer care about this target address. drop it. */ + pbuf_free(p); + return; + } + + /* Update cache entry. */ + neighbor_cache[i].netif = inp; + neighbor_cache[i].counter.reachable_time = reachable_time; + if ((na_hdr->flags & ND6_FLAG_OVERRIDE) || + (neighbor_cache[i].state == ND6_INCOMPLETE)) { + /* Check that link-layer address option also fits in packet. */ + if (p->len < (sizeof(struct na_header) + sizeof(struct lladdr_option))) { + /* TODO debug message */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header)); + + MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); + } + neighbor_cache[i].state = ND6_REACHABLE; + + /* Send queued packets, if any. */ + if (neighbor_cache[i].q != NULL) { + nd6_send_q(i); + } + } + + break; /* ICMP6_TYPE_NA */ + } + case ICMP6_TYPE_NS: /* Neighbor solicitation. */ + { + struct ns_header * ns_hdr; + struct lladdr_option * lladdr_opt; + u8_t accepted; + + /* Check that ns header fits in packet. */ + if (p->len < sizeof(struct ns_header)) { + /* TODO debug message */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + ns_hdr = (struct ns_header *)p->payload; + + /* Check if there is a link-layer address provided. Only point to it if in this buffer. */ + lladdr_opt = NULL; + if (p->len >= (sizeof(struct ns_header) + sizeof(struct lladdr_option))) { + lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct ns_header)); + } + + /* Check if the target address is configured on the receiving netif. */ + accepted = 0; + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { + if ((ip6_addr_isvalid(netif_ip6_addr_state(inp, i)) || + (ip6_addr_istentative(netif_ip6_addr_state(inp, i)) && + ip6_addr_isany(ip6_current_src_addr()))) && + ip6_addr_cmp(&(ns_hdr->target_address), netif_ip6_addr(inp, i))) { + accepted = 1; + break; + } + } + + /* NS not for us? */ + if (!accepted) { + pbuf_free(p); + return; + } + + /* Check for ANY address in src (DAD algorithm). */ + if (ip6_addr_isany(ip6_current_src_addr())) { + /* Sender is validating this address. */ + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { + if (ip6_addr_cmp(&(ns_hdr->target_address), netif_ip6_addr(inp, i))) { + /* Send a NA back so that the sender does not use this address. */ + nd6_send_na(inp, netif_ip6_addr(inp, i), ND6_FLAG_OVERRIDE | ND6_SEND_FLAG_ALLNODES_DEST); + if (ip6_addr_istentative(netif_ip6_addr_state(inp, i))) { + /* We shouldn't use this address either. */ + netif_ip6_addr_set_state(inp, i, IP6_ADDR_INVALID); + } + } + } + } + else { + /* Sender is trying to resolve our address. */ + /* Verify that they included their own link-layer address. */ + if (lladdr_opt == NULL) { + /* Not a valid message. */ + pbuf_free(p); + ND6_STATS_INC(nd6.proterr); + ND6_STATS_INC(nd6.drop); + return; + } + + i = nd6_find_neighbor_cache_entry(ip6_current_src_addr()); + if ( i>= 0) { + /* We already have a record for the solicitor. */ + if (neighbor_cache[i].state == ND6_INCOMPLETE) { + neighbor_cache[i].netif = inp; + MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); + + /* Delay probe in case we get confirmation of reachability from upper layer (TCP). */ + neighbor_cache[i].state = ND6_DELAY; + neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME; + } + } + else + { + /* Add their IPv6 address and link-layer address to neighbor cache. + * We will need it at least to send a unicast NA message, but most + * likely we will also be communicating with this node soon. */ + i = nd6_new_neighbor_cache_entry(); + if (i < 0) { + /* We couldn't assign a cache entry for this neighbor. + * we won't be able to reply. drop it. */ + pbuf_free(p); + ND6_STATS_INC(nd6.memerr); + return; + } + neighbor_cache[i].netif = inp; + MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); + ip6_addr_set(&(neighbor_cache[i].next_hop_address), ip6_current_src_addr()); + + /* Receiving a message does not prove reachability: only in one direction. + * Delay probe in case we get confirmation of reachability from upper layer (TCP). */ + neighbor_cache[i].state = ND6_DELAY; + neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME; + } + + /* Override ip6_current_dest_addr() so that we have an aligned copy. */ + ip6_addr_set(ip6_current_dest_addr(), &(ns_hdr->target_address)); + + /* Send back a NA for us. Allocate the reply pbuf. */ + nd6_send_na(inp, ip6_current_dest_addr(), ND6_FLAG_SOLICITED | ND6_FLAG_OVERRIDE); + } + + break; /* ICMP6_TYPE_NS */ + } + case ICMP6_TYPE_RA: /* Router Advertisement. */ + { + struct ra_header * ra_hdr; + u8_t * buffer; /* Used to copy options. */ + u16_t offset; + + /* Check that RA header fits in packet. */ + if (p->len < sizeof(struct ra_header)) { + /* TODO debug message */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + ra_hdr = (struct ra_header *)p->payload; + + /* If we are sending RS messages, stop. */ +#if LWIP_IPV6_SEND_ROUTER_SOLICIT + inp->rs_count = 0; +#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ + + /* Get the matching default router entry. */ + i = nd6_get_router(ip6_current_src_addr(), inp); + if (i < 0) { + /* Create a new router entry. */ + i = nd6_new_router(ip6_current_src_addr(), inp); + } + + if (i < 0) { + /* Could not create a new router entry. */ + pbuf_free(p); + ND6_STATS_INC(nd6.memerr); + return; + } + + /* Re-set invalidation timer. */ + default_router_list[i].invalidation_timer = ra_hdr->router_lifetime; + + /* Re-set default timer values. */ +#if LWIP_ND6_ALLOW_RA_UPDATES + if (ra_hdr->retrans_timer > 0) { + retrans_timer = ra_hdr->retrans_timer; + } + if (ra_hdr->reachable_time > 0) { + reachable_time = ra_hdr->reachable_time; + } +#endif /* LWIP_ND6_ALLOW_RA_UPDATES */ + + /* TODO set default hop limit... */ + /* ra_hdr->current_hop_limit;*/ + + /* Update flags in local entry (incl. preference). */ + default_router_list[i].flags = ra_hdr->flags; + + /* Offset to options. */ + offset = sizeof(struct ra_header); + + /* Process each option. */ + while ((p->tot_len - offset) > 0) { + if (p->len == p->tot_len) { + /* no need to copy from contiguous pbuf */ + buffer = &((u8_t*)p->payload)[offset]; + } else { + buffer = nd6_ra_buffer; + pbuf_copy_partial(p, buffer, sizeof(struct prefix_option), offset); + } + switch (buffer[0]) { + case ND6_OPTION_TYPE_SOURCE_LLADDR: + { + struct lladdr_option * lladdr_opt; + lladdr_opt = (struct lladdr_option *)buffer; + if ((default_router_list[i].neighbor_entry != NULL) && + (default_router_list[i].neighbor_entry->state == ND6_INCOMPLETE)) { + SMEMCPY(default_router_list[i].neighbor_entry->lladdr, lladdr_opt->addr, inp->hwaddr_len); + default_router_list[i].neighbor_entry->state = ND6_REACHABLE; + default_router_list[i].neighbor_entry->counter.reachable_time = reachable_time; + } + break; + } + case ND6_OPTION_TYPE_MTU: + { + struct mtu_option * mtu_opt; + mtu_opt = (struct mtu_option *)buffer; + if (mtu_opt->mtu >= 1280) { +#if LWIP_ND6_ALLOW_RA_UPDATES + inp->mtu = mtu_opt->mtu; +#endif /* LWIP_ND6_ALLOW_RA_UPDATES */ + } + break; + } + case ND6_OPTION_TYPE_PREFIX_INFO: + { + struct prefix_option * prefix_opt; + prefix_opt = (struct prefix_option *)buffer; + + if (prefix_opt->flags & ND6_PREFIX_FLAG_ON_LINK) { + /* Add to on-link prefix list. */ + s8_t prefix; + + /* Get a memory-aligned copy of the prefix. */ + ip6_addr_set(ip6_current_dest_addr(), &(prefix_opt->prefix)); + + /* find cache entry for this prefix. */ + prefix = nd6_get_onlink_prefix(ip6_current_dest_addr(), inp); + if (prefix < 0) { + /* Create a new cache entry. */ + prefix = nd6_new_onlink_prefix(ip6_current_dest_addr(), inp); + } + if (prefix >= 0) { + prefix_list[prefix].invalidation_timer = prefix_opt->valid_lifetime; + +#if LWIP_IPV6_AUTOCONFIG + if (prefix_opt->flags & ND6_PREFIX_FLAG_AUTONOMOUS) { + /* Mark prefix as autonomous, so that address autoconfiguration can take place. + * Only OR flag, so that we don't over-write other flags (such as ADDRESS_DUPLICATE)*/ + prefix_list[prefix].flags |= ND6_PREFIX_AUTOCONFIG_AUTONOMOUS; + } +#endif /* LWIP_IPV6_AUTOCONFIG */ + } + } + + break; + } + case ND6_OPTION_TYPE_ROUTE_INFO: + { + /* TODO implement preferred routes. + struct route_option * route_opt; + route_opt = (struct route_option *)buffer;*/ + + break; + } + default: + /* Unrecognized option, abort. */ + ND6_STATS_INC(nd6.proterr); + break; + } + offset += 8 * ((u16_t)buffer[1]); + } + + break; /* ICMP6_TYPE_RA */ + } + case ICMP6_TYPE_RD: /* Redirect */ + { + struct redirect_header * redir_hdr; + struct lladdr_option * lladdr_opt; + + /* Check that Redir header fits in packet. */ + if (p->len < sizeof(struct redirect_header)) { + /* TODO debug message */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + redir_hdr = (struct redirect_header *)p->payload; + + lladdr_opt = NULL; + if (p->len >= (sizeof(struct redirect_header) + sizeof(struct lladdr_option))) { + lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct redirect_header)); + } + + /* Copy original destination address to current source address, to have an aligned copy. */ + ip6_addr_set(ip6_current_src_addr(), &(redir_hdr->destination_address)); + + /* Find dest address in cache */ + i = nd6_find_destination_cache_entry(ip6_current_src_addr()); + if (i < 0) { + /* Destination not in cache, drop packet. */ + pbuf_free(p); + return; + } + + /* Set the new target address. */ + ip6_addr_set(&(destination_cache[i].next_hop_addr), &(redir_hdr->target_address)); + + /* If Link-layer address of other router is given, try to add to neighbor cache. */ + if (lladdr_opt != NULL) { + if (lladdr_opt->type == ND6_OPTION_TYPE_TARGET_LLADDR) { + /* Copy target address to current source address, to have an aligned copy. */ + ip6_addr_set(ip6_current_src_addr(), &(redir_hdr->target_address)); + + i = nd6_find_neighbor_cache_entry(ip6_current_src_addr()); + if (i < 0) { + i = nd6_new_neighbor_cache_entry(); + if (i >= 0) { + neighbor_cache[i].netif = inp; + MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); + ip6_addr_set(&(neighbor_cache[i].next_hop_address), ip6_current_src_addr()); + + /* Receiving a message does not prove reachability: only in one direction. + * Delay probe in case we get confirmation of reachability from upper layer (TCP). */ + neighbor_cache[i].state = ND6_DELAY; + neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME; + } + } + if (i >= 0) { + if (neighbor_cache[i].state == ND6_INCOMPLETE) { + MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); + /* Receiving a message does not prove reachability: only in one direction. + * Delay probe in case we get confirmation of reachability from upper layer (TCP). */ + neighbor_cache[i].state = ND6_DELAY; + neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME; + } + } + } + } + break; /* ICMP6_TYPE_RD */ + } + case ICMP6_TYPE_PTB: /* Packet too big */ + { + struct icmp6_hdr *icmp6hdr; /* Packet too big message */ + struct ip6_hdr * ip6hdr; /* IPv6 header of the packet which caused the error */ + + /* Check that ICMPv6 header + IPv6 header fit in payload */ + if (p->len < (sizeof(struct icmp6_hdr) + IP6_HLEN)) { + /* drop short packets */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + icmp6hdr = (struct icmp6_hdr *)p->payload; + ip6hdr = (struct ip6_hdr *)((u8_t*)p->payload + sizeof(struct icmp6_hdr)); + + /* Copy original destination address to current source address, to have an aligned copy. */ + ip6_addr_set(ip6_current_src_addr(), &(ip6hdr->dest)); + + /* Look for entry in destination cache. */ + i = nd6_find_destination_cache_entry(ip6_current_src_addr()); + if (i < 0) { + /* Destination not in cache, drop packet. */ + pbuf_free(p); + return; + } + + /* Change the Path MTU. */ + destination_cache[i].pmtu = icmp6hdr->data; + + break; /* ICMP6_TYPE_PTB */ + } + + default: + ND6_STATS_INC(nd6.proterr); + ND6_STATS_INC(nd6.drop); + break; /* default */ + } + + pbuf_free(p); +} + + +/** + * Periodic timer for Neighbor discovery functions: + * + * - Update neighbor reachability states + * - Update destination cache entries age + * - Update invalidation timers of default routers and on-link prefixes + * - Perform duplicate address detection (DAD) for our addresses + * - Send router solicitations + */ +void +nd6_tmr(void) +{ + s8_t i, j; + struct netif * netif; + + /* Process neighbor entries. */ + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + switch (neighbor_cache[i].state) { + case ND6_INCOMPLETE: + if (neighbor_cache[i].counter.probes_sent >= LWIP_ND6_MAX_MULTICAST_SOLICIT) { + /* Retries exceeded. */ + nd6_free_neighbor_cache_entry(i); + } + else { + /* Send a NS for this entry. */ + neighbor_cache[i].counter.probes_sent++; + nd6_send_ns(neighbor_cache[i].netif, &(neighbor_cache[i].next_hop_address), ND6_SEND_FLAG_MULTICAST_DEST); + } + break; + case ND6_REACHABLE: + /* Send queued packets, if any are left. Should have been sent already. */ + if (neighbor_cache[i].q != NULL) { + nd6_send_q(i); + } + if (neighbor_cache[i].counter.reachable_time <= ND6_TMR_INTERVAL) { + /* Change to stale state. */ + neighbor_cache[i].state = ND6_STALE; + neighbor_cache[i].counter.stale_time = 0; + } + else { + neighbor_cache[i].counter.reachable_time -= ND6_TMR_INTERVAL; + } + break; + case ND6_STALE: + neighbor_cache[i].counter.stale_time += ND6_TMR_INTERVAL; + break; + case ND6_DELAY: + if (neighbor_cache[i].counter.delay_time <= ND6_TMR_INTERVAL) { + /* Change to PROBE state. */ + neighbor_cache[i].state = ND6_PROBE; + neighbor_cache[i].counter.probes_sent = 0; + } + else { + neighbor_cache[i].counter.delay_time -= ND6_TMR_INTERVAL; + } + break; + case ND6_PROBE: + if (neighbor_cache[i].counter.probes_sent >= LWIP_ND6_MAX_MULTICAST_SOLICIT) { + /* Retries exceeded. */ + nd6_free_neighbor_cache_entry(i); + } + else { + /* Send a NS for this entry. */ + neighbor_cache[i].counter.probes_sent++; + nd6_send_ns(neighbor_cache[i].netif, &(neighbor_cache[i].next_hop_address), 0); + } + break; + case ND6_NO_ENTRY: + default: + /* Do nothing. */ + break; + } + } + + /* Process destination entries. */ + for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { + destination_cache[i].age++; + } + + /* Process router entries. */ + for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { + if (default_router_list[i].neighbor_entry != NULL) { + /* Active entry. */ + if (default_router_list[i].invalidation_timer > 0) { + default_router_list[i].invalidation_timer -= ND6_TMR_INTERVAL / 1000; + } + if (default_router_list[i].invalidation_timer < ND6_TMR_INTERVAL / 1000) { + /* Less than 1 second remaining. Clear this entry. */ + default_router_list[i].neighbor_entry->isrouter = 0; + default_router_list[i].neighbor_entry = NULL; + default_router_list[i].invalidation_timer = 0; + default_router_list[i].flags = 0; + } + } + } + + /* Process prefix entries. */ + for (i = 0; i < LWIP_ND6_NUM_PREFIXES; i++) { + if (prefix_list[i].invalidation_timer < ND6_TMR_INTERVAL / 1000) { + prefix_list[i].invalidation_timer = 0; + } + if ((prefix_list[i].invalidation_timer > 0) && + (prefix_list[i].netif != NULL)) { + prefix_list[i].invalidation_timer -= ND6_TMR_INTERVAL / 1000; + +#if LWIP_IPV6_AUTOCONFIG + /* Initiate address autoconfiguration for this prefix, if conditions are met. */ + if (prefix_list[i].netif->ip6_autoconfig_enabled && + (prefix_list[i].flags & ND6_PREFIX_AUTOCONFIG_AUTONOMOUS) && + !(prefix_list[i].flags & ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED)) { + /* Try to get an address on this netif that is invalid. + * Skip 0 index (link-local address) */ + for (j = 1; j < LWIP_IPV6_NUM_ADDRESSES; j++) { + if (netif_ip6_addr_state(prefix_list[i].netif, j) == IP6_ADDR_INVALID) { + /* Generate an address using this prefix and interface ID from link-local address. */ + prefix_list[i].netif->ip6_addr[j].addr[0] = prefix_list[i].prefix.addr[0]; + prefix_list[i].netif->ip6_addr[j].addr[1] = prefix_list[i].prefix.addr[1]; + prefix_list[i].netif->ip6_addr[j].addr[2] = prefix_list[i].netif->ip6_addr[0].addr[2]; + prefix_list[i].netif->ip6_addr[j].addr[3] = prefix_list[i].netif->ip6_addr[0].addr[3]; + + /* Mark it as tentative (DAD will be performed if configured). */ + netif_ip6_addr_set_state(prefix_list[i].netif, j, IP6_ADDR_TENTATIVE); + + /* Mark this prefix with ADDRESS_GENERATED, so that we don't try again. */ + prefix_list[i].flags |= ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED; + + /* Exit loop. */ + break; + } + } + } +#endif /* LWIP_IPV6_AUTOCONFIG */ + } + } + + + /* Process our own addresses, if DAD configured. */ + for (netif = netif_list; netif != NULL; netif = netif->next) { + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { + if (ip6_addr_istentative(netif->ip6_addr_state[i])) { + if ((netif->ip6_addr_state[i] & 0x07) >= LWIP_IPV6_DUP_DETECT_ATTEMPTS) { + /* No NA received in response. Mark address as valid. */ + netif->ip6_addr_state[i] = IP6_ADDR_PREFERRED; + /* TODO implement preferred and valid lifetimes. */ + } + else if (netif->flags & NETIF_FLAG_UP) { +#if LWIP_IPV6_MLD + if ((netif->ip6_addr_state[i] & 0x07) == 0) { + /* Join solicited node multicast group. */ + ip6_addr_set_solicitednode(&multicast_address, netif_ip6_addr(netif, i)->addr[3]); + mld6_joingroup(netif_ip6_addr(netif, i), &multicast_address); + } +#endif /* LWIP_IPV6_MLD */ + /* Send a NS for this address. */ + nd6_send_ns(netif, netif_ip6_addr(netif, i), ND6_SEND_FLAG_MULTICAST_DEST); + (netif->ip6_addr_state[i])++; + /* TODO send max 1 NS per tmr call? enable return*/ + /*return;*/ + } + } + } + } + +#if LWIP_IPV6_SEND_ROUTER_SOLICIT + /* Send router solicitation messages, if necessary. */ + for (netif = netif_list; netif != NULL; netif = netif->next) { + if ((netif->rs_count > 0) && (netif->flags & NETIF_FLAG_UP)) { + nd6_send_rs(netif); + netif->rs_count--; + } + } +#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ + +} + +/** + * Send a neighbor solicitation message + * + * @param netif the netif on which to send the message + * @param target_addr the IPv6 target address for the ND message + * @param flags one of ND6_SEND_FLAG_* + */ +static void +nd6_send_ns(struct netif * netif, ip6_addr_t * target_addr, u8_t flags) +{ + struct ns_header * ns_hdr; + struct lladdr_option * lladdr_opt; + struct pbuf * p; + ip6_addr_t * src_addr; + + if (ip6_addr_isvalid(netif_ip6_addr_state(netif,0))) { + /* Use link-local address as source address. */ + src_addr = netif_ip6_addr(netif, 0); + } else { + src_addr = IP6_ADDR_ANY; + } + + /* Allocate a packet. */ + p = pbuf_alloc(PBUF_IP, sizeof(struct ns_header) + sizeof(struct lladdr_option), PBUF_RAM); + if ((p == NULL) || (p->len < (sizeof(struct ns_header) + sizeof(struct lladdr_option)))) { + /* We couldn't allocate a suitable pbuf for the ns. drop it. */ + if (p != NULL) { + pbuf_free(p); + } + ND6_STATS_INC(nd6.memerr); + return; + } + + /* Set fields. */ + ns_hdr = (struct ns_header *)p->payload; + lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct ns_header)); + + ns_hdr->type = ICMP6_TYPE_NS; + ns_hdr->code = 0; + ns_hdr->chksum = 0; + ns_hdr->reserved = 0; + ip6_addr_set(&(ns_hdr->target_address), target_addr); + + lladdr_opt->type = ND6_OPTION_TYPE_SOURCE_LLADDR; + lladdr_opt->length = ((netif->hwaddr_len + 2) >> 3) + (((netif->hwaddr_len + 2) & 0x07) ? 1 : 0); + SMEMCPY(lladdr_opt->addr, netif->hwaddr, netif->hwaddr_len); + + /* Generate the solicited node address for the target address. */ + if (flags & ND6_SEND_FLAG_MULTICAST_DEST) { + ip6_addr_set_solicitednode(&multicast_address, target_addr->addr[3]); + target_addr = &multicast_address; + } + +#if CHECKSUM_GEN_ICMP6 + ns_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr, + target_addr); +#endif /* CHECKSUM_GEN_ICMP6 */ + + /* Send the packet out. */ + ND6_STATS_INC(nd6.xmit); + ip6_output_if(p, (src_addr == IP6_ADDR_ANY) ? NULL : src_addr, target_addr, + LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif); + pbuf_free(p); +} + +/** + * Send a neighbor advertisement message + * + * @param netif the netif on which to send the message + * @param target_addr the IPv6 target address for the ND message + * @param flags one of ND6_SEND_FLAG_* + */ +static void +nd6_send_na(struct netif * netif, ip6_addr_t * target_addr, u8_t flags) +{ + struct na_header * na_hdr; + struct lladdr_option * lladdr_opt; + struct pbuf * p; + ip6_addr_t * src_addr; + ip6_addr_t * dest_addr; + + /* Use link-local address as source address. */ + /* src_addr = &(netif->ip6_addr[0]); */ + /* Use target address as source address. */ + src_addr = target_addr; + + /* Allocate a packet. */ + p = pbuf_alloc(PBUF_IP, sizeof(struct na_header) + sizeof(struct lladdr_option), PBUF_RAM); + if ((p == NULL) || (p->len < (sizeof(struct na_header) + sizeof(struct lladdr_option)))) { + /* We couldn't allocate a suitable pbuf for the ns. drop it. */ + if (p != NULL) { + pbuf_free(p); + } + ND6_STATS_INC(nd6.memerr); + return; + } + + /* Set fields. */ + na_hdr = (struct na_header *)p->payload; + lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header)); + + na_hdr->type = ICMP6_TYPE_NA; + na_hdr->code = 0; + na_hdr->chksum = 0; + na_hdr->flags = flags & 0xf0; + na_hdr->reserved[0] = 0; + na_hdr->reserved[1] = 0; + na_hdr->reserved[2] = 0; + ip6_addr_set(&(na_hdr->target_address), target_addr); + + lladdr_opt->type = ND6_OPTION_TYPE_TARGET_LLADDR; + lladdr_opt->length = ((netif->hwaddr_len + 2) >> 3) + (((netif->hwaddr_len + 2) & 0x07) ? 1 : 0); + SMEMCPY(lladdr_opt->addr, netif->hwaddr, netif->hwaddr_len); + + /* Generate the solicited node address for the target address. */ + if (flags & ND6_SEND_FLAG_MULTICAST_DEST) { + ip6_addr_set_solicitednode(&multicast_address, target_addr->addr[3]); + dest_addr = &multicast_address; + } + else if (flags & ND6_SEND_FLAG_ALLNODES_DEST) { + ip6_addr_set_allnodes_linklocal(&multicast_address); + dest_addr = &multicast_address; + } + else { + dest_addr = ip6_current_src_addr(); + } + +#if CHECKSUM_GEN_ICMP6 + na_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr, + dest_addr); +#endif /* CHECKSUM_GEN_ICMP6 */ + + /* Send the packet out. */ + ND6_STATS_INC(nd6.xmit); + ip6_output_if(p, src_addr, dest_addr, + LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif); + pbuf_free(p); +} + +#if LWIP_IPV6_SEND_ROUTER_SOLICIT +/** + * Send a router solicitation message + * + * @param netif the netif on which to send the message + */ +static void +nd6_send_rs(struct netif * netif) +{ + struct rs_header * rs_hdr; + struct lladdr_option * lladdr_opt; + struct pbuf * p; + ip6_addr_t * src_addr; + u16_t packet_len; + + /* Link-local source address, or unspecified address? */ + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, 0))) { + src_addr = netif_ip6_addr(netif, 0); + } + else { + src_addr = IP6_ADDR_ANY; + } + + /* Generate the all routers target address. */ + ip6_addr_set_allrouters_linklocal(&multicast_address); + + /* Allocate a packet. */ + packet_len = sizeof(struct rs_header); + if (src_addr != IP6_ADDR_ANY) { + packet_len += sizeof(struct lladdr_option); + } + p = pbuf_alloc(PBUF_IP, packet_len, PBUF_RAM); + if ((p == NULL) || (p->len < packet_len)) { + /* We couldn't allocate a suitable pbuf for the ns. drop it. */ + if (p != NULL) { + pbuf_free(p); + } + ND6_STATS_INC(nd6.memerr); + return; + } + + /* Set fields. */ + rs_hdr = (struct rs_header *)p->payload; + + rs_hdr->type = ICMP6_TYPE_RS; + rs_hdr->code = 0; + rs_hdr->chksum = 0; + rs_hdr->reserved = 0; + + if (src_addr != IP6_ADDR_ANY) { + /* Include our hw address. */ + lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct rs_header)); + lladdr_opt->type = ND6_OPTION_TYPE_SOURCE_LLADDR; + lladdr_opt->length = ((netif->hwaddr_len + 2) >> 3) + (((netif->hwaddr_len + 2) & 0x07) ? 1 : 0); + SMEMCPY(lladdr_opt->addr, netif->hwaddr, netif->hwaddr_len); + } + +#if CHECKSUM_GEN_ICMP6 + rs_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr, + &multicast_address); +#endif /* CHECKSUM_GEN_ICMP6 */ + + /* Send the packet out. */ + ND6_STATS_INC(nd6.xmit); + ip6_output_if(p, src_addr, &multicast_address, + LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif); + pbuf_free(p); +} +#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ + +/** + * Search for a neighbor cache entry + * + * @param ip6addr the IPv6 address of the neighbor + * @return The neighbor cache entry index that matched, -1 if no + * entry is found + */ +static s8_t +nd6_find_neighbor_cache_entry(ip6_addr_t * ip6addr) +{ + s8_t i; + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if (ip6_addr_cmp(ip6addr, &(neighbor_cache[i].next_hop_address))) { + return i; + } + } + return -1; +} + +/** + * Create a new neighbor cache entry. + * + * If no unused entry is found, will try to recycle an old entry + * according to ad-hoc "age" heuristic. + * + * @return The neighbor cache entry index that was created, -1 if no + * entry could be created + */ +static s8_t +nd6_new_neighbor_cache_entry(void) +{ + s8_t i; + s8_t j; + u32_t time; + + + /* First, try to find an empty entry. */ + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if (neighbor_cache[i].state == ND6_NO_ENTRY) { + return i; + } + } + + /* We need to recycle an entry. in general, do not recycle if it is a router. */ + + /* Next, try to find a Stale entry. */ + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if ((neighbor_cache[i].state == ND6_STALE) && + (!neighbor_cache[i].isrouter)) { + nd6_free_neighbor_cache_entry(i); + return i; + } + } + + /* Next, try to find a Probe entry. */ + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if ((neighbor_cache[i].state == ND6_PROBE) && + (!neighbor_cache[i].isrouter)) { + nd6_free_neighbor_cache_entry(i); + return i; + } + } + + /* Next, try to find a Delayed entry. */ + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if ((neighbor_cache[i].state == ND6_DELAY) && + (!neighbor_cache[i].isrouter)) { + nd6_free_neighbor_cache_entry(i); + return i; + } + } + + /* Next, try to find the oldest reachable entry. */ + time = 0xfffffffful; + j = -1; + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if ((neighbor_cache[i].state == ND6_REACHABLE) && + (!neighbor_cache[i].isrouter)) { + if (neighbor_cache[i].counter.reachable_time < time) { + j = i; + time = neighbor_cache[i].counter.reachable_time; + } + } + } + if (j >= 0) { + nd6_free_neighbor_cache_entry(j); + return j; + } + + /* Next, find oldest incomplete entry without queued packets. */ + time = 0; + j = -1; + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if ( + (neighbor_cache[i].q == NULL) && + (neighbor_cache[i].state == ND6_INCOMPLETE) && + (!neighbor_cache[i].isrouter)) { + if (neighbor_cache[i].counter.probes_sent >= time) { + j = i; + time = neighbor_cache[i].counter.probes_sent; + } + } + } + if (j >= 0) { + nd6_free_neighbor_cache_entry(j); + return j; + } + + /* Next, find oldest incomplete entry with queued packets. */ + time = 0; + j = -1; + for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { + if ((neighbor_cache[i].state == ND6_INCOMPLETE) && + (!neighbor_cache[i].isrouter)) { + if (neighbor_cache[i].counter.probes_sent >= time) { + j = i; + time = neighbor_cache[i].counter.probes_sent; + } + } + } + if (j >= 0) { + nd6_free_neighbor_cache_entry(j); + return j; + } + + /* No more entries to try. */ + return -1; +} + +/** + * Will free any resources associated with a neighbor cache + * entry, and will mark it as unused. + * + * @param i the neighbor cache entry index to free + */ +static void +nd6_free_neighbor_cache_entry(s8_t i) +{ + if ((i < 0) || (i >= LWIP_ND6_NUM_NEIGHBORS)) { + return; + } + + /* Free any queued packets. */ + if (neighbor_cache[i].q != NULL) { + nd6_free_q(neighbor_cache[i].q); + neighbor_cache[i].q = NULL; + } + + neighbor_cache[i].state = ND6_NO_ENTRY; + neighbor_cache[i].isrouter = 0; + neighbor_cache[i].netif = NULL; + neighbor_cache[i].counter.reachable_time = 0; + ip6_addr_set_zero(&(neighbor_cache[i].next_hop_address)); +} + +/** + * Search for a destination cache entry + * + * @param ip6addr the IPv6 address of the destination + * @return The destination cache entry index that matched, -1 if no + * entry is found + */ +static s8_t +nd6_find_destination_cache_entry(ip6_addr_t * ip6addr) +{ + s8_t i; + for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { + if (ip6_addr_cmp(ip6addr, &(destination_cache[i].destination_addr))) { + return i; + } + } + return -1; +} + +/** + * Create a new destination cache entry. If no unused entry is found, + * will recycle oldest entry. + * + * @return The destination cache entry index that was created, -1 if no + * entry was created + */ +static s8_t +nd6_new_destination_cache_entry(void) +{ + s8_t i, j; + u32_t age; + + /* Find an empty entry. */ + for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { + if (ip6_addr_isany(&(destination_cache[i].destination_addr))) { + return i; + } + } + + /* Find oldest entry. */ + age = 0; + j = LWIP_ND6_NUM_DESTINATIONS - 1; + for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { + if (destination_cache[i].age > age) { + j = i; + } + } + + return j; +} + +/** + * Determine whether an address matches an on-link prefix. + * + * @param ip6addr the IPv6 address to match + * @return 1 if the address is on-link, 0 otherwise + */ +static s8_t +nd6_is_prefix_in_netif(ip6_addr_t * ip6addr, struct netif * netif) +{ + s8_t i; + for (i = 0; i < LWIP_ND6_NUM_PREFIXES; i++) { + if ((prefix_list[i].netif == netif) && + (prefix_list[i].invalidation_timer > 0) && + ip6_addr_netcmp(ip6addr, &(prefix_list[i].prefix))) { + return 1; + } + } + /* Check to see if address prefix matches a (manually?) configured address. */ + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_netcmp(ip6addr, netif_ip6_addr(netif, i))) { + return 1; + } + } + return 0; +} + +/** + * Select a default router for a destination. + * + * @param ip6addr the destination address + * @param netif the netif for the outgoing packet, if known + * @return the default router entry index, or -1 if no suitable + * router is found + */ +s8_t +nd6_select_router(ip6_addr_t * ip6addr, struct netif * netif) +{ + s8_t i; + /* last_router is used for round-robin router selection (as recommended + * in RFC). This is more robust in case one router is not reachable, + * we are not stuck trying to resolve it. */ + static s8_t last_router; + (void)ip6addr; /* TODO match preferred routes!! (must implement ND6_OPTION_TYPE_ROUTE_INFO) */ + + /* TODO: implement default router preference */ + + /* Look for reachable routers. */ + for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { + if (++last_router >= LWIP_ND6_NUM_ROUTERS) { + last_router = 0; + } + if ((default_router_list[i].neighbor_entry != NULL) && + (netif != NULL ? netif == default_router_list[i].neighbor_entry->netif : 1) && + (default_router_list[i].invalidation_timer > 0) && + (default_router_list[i].neighbor_entry->state == ND6_REACHABLE)) { + return i; + } + } + + /* Look for router in other reachability states, but still valid according to timer. */ + for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { + if (++last_router >= LWIP_ND6_NUM_ROUTERS) { + last_router = 0; + } + if ((default_router_list[i].neighbor_entry != NULL) && + (netif != NULL ? netif == default_router_list[i].neighbor_entry->netif : 1) && + (default_router_list[i].invalidation_timer > 0)) { + return i; + } + } + + /* Look for any router for which we have any information at all. */ + for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { + if (++last_router >= LWIP_ND6_NUM_ROUTERS) { + last_router = 0; + } + if (default_router_list[i].neighbor_entry != NULL && + (netif != NULL ? netif == default_router_list[i].neighbor_entry->netif : 1)) { + return i; + } + } + + /* no suitable router found. */ + return -1; +} + +/** + * Find an entry for a default router. + * + * @param router_addr the IPv6 address of the router + * @param netif the netif on which the router is found, if known + * @return the index of the router entry, or -1 if not found + */ +static s8_t +nd6_get_router(ip6_addr_t * router_addr, struct netif * netif) +{ + s8_t i; + + /* Look for router. */ + for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { + if ((default_router_list[i].neighbor_entry != NULL) && + ((netif != NULL) ? netif == default_router_list[i].neighbor_entry->netif : 1) && + ip6_addr_cmp(router_addr, &(default_router_list[i].neighbor_entry->next_hop_address))) { + return i; + } + } + + /* router not found. */ + return -1; +} + +/** + * Create a new entry for a default router. + * + * @param router_addr the IPv6 address of the router + * @param netif the netif on which the router is connected, if known + * @return the index on the router table, or -1 if could not be created + */ +static s8_t +nd6_new_router(ip6_addr_t * router_addr, struct netif * netif) +{ + s8_t router_index; + s8_t neighbor_index; + + /* Do we have a neighbor entry for this router? */ + neighbor_index = nd6_find_neighbor_cache_entry(router_addr); + if (neighbor_index < 0) { + /* Create a neighbor entry for this router. */ + neighbor_index = nd6_new_neighbor_cache_entry(); + if (neighbor_index < 0) { + /* Could not create neighbor entry for this router. */ + return -1; + } + ip6_addr_set(&(neighbor_cache[neighbor_index].next_hop_address), router_addr); + neighbor_cache[neighbor_index].netif = netif; + neighbor_cache[neighbor_index].q = NULL; + neighbor_cache[neighbor_index].state = ND6_INCOMPLETE; + neighbor_cache[neighbor_index].counter.probes_sent = 0; + } + + /* Mark neighbor as router. */ + neighbor_cache[neighbor_index].isrouter = 1; + + /* Look for empty entry. */ + for (router_index = 0; router_index < LWIP_ND6_NUM_ROUTERS; router_index++) { + if (default_router_list[router_index].neighbor_entry == NULL) { + default_router_list[router_index].neighbor_entry = &(neighbor_cache[neighbor_index]); + return router_index; + } + } + + /* Could not create a router entry. */ + + /* Mark neighbor entry as not-router. Entry might be useful as neighbor still. */ + neighbor_cache[neighbor_index].isrouter = 0; + + /* router not found. */ + return -1; +} + +/** + * Find the cached entry for an on-link prefix. + * + * @param prefix the IPv6 prefix that is on-link + * @param netif the netif on which the prefix is on-link + * @return the index on the prefix table, or -1 if not found + */ +static s8_t +nd6_get_onlink_prefix(ip6_addr_t * prefix, struct netif * netif) +{ + s8_t i; + + /* Look for prefix in list. */ + for (i = 0; i < LWIP_ND6_NUM_PREFIXES; ++i) { + if ((ip6_addr_netcmp(&(prefix_list[i].prefix), prefix)) && + (prefix_list[i].netif == netif)) { + return i; + } + } + + /* Entry not available. */ + return -1; +} + +/** + * Creates a new entry for an on-link prefix. + * + * @param prefix the IPv6 prefix that is on-link + * @param netif the netif on which the prefix is on-link + * @return the index on the prefix table, or -1 if not created + */ +static s8_t +nd6_new_onlink_prefix(ip6_addr_t * prefix, struct netif * netif) +{ + s8_t i; + + /* Create new entry. */ + for (i = 0; i < LWIP_ND6_NUM_PREFIXES; ++i) { + if ((prefix_list[i].netif == NULL) || + (prefix_list[i].invalidation_timer == 0)) { + /* Found empty prefix entry. */ + prefix_list[i].netif = netif; + ip6_addr_set(&(prefix_list[i].prefix), prefix); + prefix_list[i].flags = 0; + return i; + } + } + + /* Entry not available. */ + return -1; +} + +/** + * Determine the next hop for a destination. Will determine if the + * destination is on-link, else a suitable on-link router is selected. + * + * The last entry index is cached for fast entry search. + * + * @param ip6addr the destination address + * @param netif the netif on which the packet will be sent + * @return the neighbor cache entry for the next hop, ERR_RTE if no + * suitable next hop was found, ERR_MEM if no cache entry + * could be created + */ +s8_t +nd6_get_next_hop_entry(ip6_addr_t * ip6addr, struct netif * netif) +{ + s8_t i; + +#if LWIP_NETIF_HWADDRHINT + if (netif->addr_hint != NULL) { + /* per-pcb cached entry was given */ + u8_t addr_hint = *(netif->addr_hint); + if (addr_hint < LWIP_ND6_NUM_DESTINATIONS) { + nd6_cached_destination_index = addr_hint; + } + } +#endif /* LWIP_NETIF_HWADDRHINT */ + + /* Look for ip6addr in destination cache. */ + if (ip6_addr_cmp(ip6addr, &(destination_cache[nd6_cached_destination_index].destination_addr))) { + /* the cached entry index is the right one! */ + /* do nothing. */ + ND6_STATS_INC(nd6.cachehit); + } else { + /* Search destination cache. */ + i = nd6_find_destination_cache_entry(ip6addr); + if (i >= 0) { + /* found destination entry. make it our new cached index. */ + nd6_cached_destination_index = i; + } + else { + /* Not found. Create a new destination entry. */ + i = nd6_new_destination_cache_entry(); + if (i >= 0) { + /* got new destination entry. make it our new cached index. */ + nd6_cached_destination_index = i; + } else { + /* Could not create a destination cache entry. */ + return ERR_MEM; + } + + /* Copy dest address to destination cache. */ + ip6_addr_set(&(destination_cache[nd6_cached_destination_index].destination_addr), ip6addr); + + /* Now find the next hop. is it a neighbor? */ + if (ip6_addr_islinklocal(ip6addr) || + nd6_is_prefix_in_netif(ip6addr, netif)) { + /* Destination in local link. */ + destination_cache[nd6_cached_destination_index].pmtu = netif->mtu; + ip6_addr_copy(destination_cache[nd6_cached_destination_index].next_hop_addr, destination_cache[nd6_cached_destination_index].destination_addr); + } + else { + /* We need to select a router. */ + i = nd6_select_router(ip6addr, netif); + if (i < 0) { + /* No router found. */ + ip6_addr_set_any(&(destination_cache[nd6_cached_destination_index].destination_addr)); + return ERR_RTE; + } + destination_cache[nd6_cached_destination_index].pmtu = netif->mtu; /* Start with netif mtu, correct through ICMPv6 if necessary */ + ip6_addr_copy(destination_cache[nd6_cached_destination_index].next_hop_addr, default_router_list[i].neighbor_entry->next_hop_address); + } + } + } + +#if LWIP_NETIF_HWADDRHINT + if (netif->addr_hint != NULL) { + /* per-pcb cached entry was given */ + *(netif->addr_hint) = nd6_cached_destination_index; + } +#endif /* LWIP_NETIF_HWADDRHINT */ + + /* Look in neighbor cache for the next-hop address. */ + if (ip6_addr_cmp(&(destination_cache[nd6_cached_destination_index].next_hop_addr), + &(neighbor_cache[nd6_cached_neighbor_index].next_hop_address))) { + /* Cache hit. */ + /* Do nothing. */ + ND6_STATS_INC(nd6.cachehit); + } else { + i = nd6_find_neighbor_cache_entry(&(destination_cache[nd6_cached_destination_index].next_hop_addr)); + if (i >= 0) { + /* Found a matching record, make it new cached entry. */ + nd6_cached_neighbor_index = i; + } + else { + /* Neighbor not in cache. Make a new entry. */ + i = nd6_new_neighbor_cache_entry(); + if (i >= 0) { + /* got new neighbor entry. make it our new cached index. */ + nd6_cached_neighbor_index = i; + } else { + /* Could not create a neighbor cache entry. */ + return ERR_MEM; + } + + /* Initialize fields. */ + ip6_addr_copy(neighbor_cache[i].next_hop_address, + destination_cache[nd6_cached_destination_index].next_hop_addr); + neighbor_cache[i].isrouter = 0; + neighbor_cache[i].netif = netif; + neighbor_cache[i].state = ND6_INCOMPLETE; + neighbor_cache[i].counter.probes_sent = 0; + } + } + + /* Reset this destination's age. */ + destination_cache[nd6_cached_destination_index].age = 0; + + return nd6_cached_neighbor_index; +} + +/** + * Queue a packet for a neighbor. + * + * @param neighbor_index the index in the neighbor cache table + * @param q packet to be queued + * @return ERR_OK if succeeded, ERR_MEM if out of memory + */ +err_t +nd6_queue_packet(s8_t neighbor_index, struct pbuf * q) +{ + err_t result = ERR_MEM; + struct pbuf *p; + int copy_needed = 0; +#if LWIP_ND6_QUEUEING + struct nd6_q_entry *new_entry, *r; +#endif /* LWIP_ND6_QUEUEING */ + + if ((neighbor_index < 0) || (neighbor_index >= LWIP_ND6_NUM_NEIGHBORS)) { + return ERR_ARG; + } + + /* IF q includes a PBUF_REF, PBUF_POOL or PBUF_RAM, we have no choice but + * to copy the whole queue into a new PBUF_RAM (see bug #11400) + * PBUF_ROMs can be left as they are, since ROM must not get changed. */ + p = q; + while (p) { + if(p->type != PBUF_ROM) { + copy_needed = 1; + break; + } + p = p->next; + } + if(copy_needed) { + /* copy the whole packet into new pbufs */ + p = pbuf_alloc(PBUF_LINK, q->tot_len, PBUF_RAM); + while ((p == NULL) && (neighbor_cache[neighbor_index].q != NULL)) { + /* Free oldest packet (as per RFC recommendation) */ +#if LWIP_ND6_QUEUEING + r = neighbor_cache[neighbor_index].q; + neighbor_cache[neighbor_index].q = r->next; + r->next = NULL; + nd6_free_q(r); +#else /* LWIP_ND6_QUEUEING */ + pbuf_free(neighbor_cache[neighbor_index].q); + neighbor_cache[neighbor_index].q = NULL; +#endif /* LWIP_ND6_QUEUEING */ + p = pbuf_alloc(PBUF_LINK, q->tot_len, PBUF_RAM); + } + if(p != NULL) { + if (pbuf_copy(p, q) != ERR_OK) { + pbuf_free(p); + p = NULL; + } + } + } else { + /* referencing the old pbuf is enough */ + p = q; + pbuf_ref(p); + } + /* packet was copied/ref'd? */ + if (p != NULL) { + /* queue packet ... */ +#if LWIP_ND6_QUEUEING + /* allocate a new nd6 queue entry */ + new_entry = (struct nd6_q_entry *)memp_malloc(MEMP_ND6_QUEUE); + if ((new_entry == NULL) && (neighbor_cache[neighbor_index].q != NULL)) { + /* Free oldest packet (as per RFC recommendation) */ + r = neighbor_cache[neighbor_index].q; + neighbor_cache[neighbor_index].q = r->next; + r->next = NULL; + nd6_free_q(r); + new_entry = (struct nd6_q_entry *)memp_malloc(MEMP_ND6_QUEUE); + } + if (new_entry != NULL) { + new_entry->next = NULL; + new_entry->p = p; + if(neighbor_cache[neighbor_index].q != NULL) { + /* queue was already existent, append the new entry to the end */ + r = neighbor_cache[neighbor_index].q; + while (r->next != NULL) { + r = r->next; + } + r->next = new_entry; + } else { + /* queue did not exist, first item in queue */ + neighbor_cache[neighbor_index].q = new_entry; + } + LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: queued packet %p on neighbor entry %"S16_F"\n", (void *)p, (s16_t)neighbor_index)); + result = ERR_OK; + } else { + /* the pool MEMP_ND6_QUEUE is empty */ + pbuf_free(p); + LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: could not queue a copy of packet %p (out of memory)\n", (void *)p)); + /* { result == ERR_MEM } through initialization */ + } +#else /* LWIP_ND6_QUEUEING */ + /* Queue a single packet. If an older packet is already queued, free it as per RFC. */ + if (neighbor_cache[neighbor_index].q != NULL) { + pbuf_free(neighbor_cache[neighbor_index].q); + } + neighbor_cache[neighbor_index].q = p; + LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: queued packet %p on neighbor entry %"S16_F"\n", (void *)p, (s16_t)neighbor_index)); + result = ERR_OK; +#endif /* LWIP_ND6_QUEUEING */ + } else { + LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: could not queue a copy of packet %p (out of memory)\n", (void *)q)); + /* { result == ERR_MEM } through initialization */ + } + + return result; +} + +#if LWIP_ND6_QUEUEING +/** + * Free a complete queue of nd6 q entries + * + * @param q a queue of nd6_q_entry to free + */ +static void +nd6_free_q(struct nd6_q_entry *q) +{ + struct nd6_q_entry *r; + LWIP_ASSERT("q != NULL", q != NULL); + LWIP_ASSERT("q->p != NULL", q->p != NULL); + while (q) { + r = q; + q = q->next; + LWIP_ASSERT("r->p != NULL", (r->p != NULL)); + pbuf_free(r->p); + memp_free(MEMP_ND6_QUEUE, r); + } +} +#endif /* LWIP_ND6_QUEUEING */ + +/** + * Send queued packets for a neighbor + * + * @param i the neighbor to send packets to + */ +static void +nd6_send_q(s8_t i) +{ + struct ip6_hdr *ip6hdr; +#if LWIP_ND6_QUEUEING + struct nd6_q_entry *q; +#endif /* LWIP_ND6_QUEUEING */ + + if ((i < 0) || (i >= LWIP_ND6_NUM_NEIGHBORS)) { + return; + } + +#if LWIP_ND6_QUEUEING + while (neighbor_cache[i].q != NULL) { + /* remember first in queue */ + q = neighbor_cache[i].q; + /* pop first item off the queue */ + neighbor_cache[i].q = q->next; + /* Get ipv6 header. */ + ip6hdr = (struct ip6_hdr *)(q->p->payload); + /* Override ip6_current_dest_addr() so that we have an aligned copy. */ + ip6_addr_set(ip6_current_dest_addr(), &(ip6hdr->dest)); + /* send the queued IPv6 packet */ + (neighbor_cache[i].netif)->output_ip6(neighbor_cache[i].netif, q->p, ip6_current_dest_addr()); + /* free the queued IP packet */ + pbuf_free(q->p); + /* now queue entry can be freed */ + memp_free(MEMP_ND6_QUEUE, q); + } +#else /* LWIP_ND6_QUEUEING */ + if (neighbor_cache[i].q != NULL) { + /* Get ipv6 header. */ + ip6hdr = (struct ip6_hdr *)(neighbor_cache[i].q->payload); + /* Override ip6_current_dest_addr() so that we have an aligned copy. */ + ip6_addr_set(ip6_current_dest_addr(), &(ip6hdr->dest)); + /* send the queued IPv6 packet */ + (neighbor_cache[i].netif)->output_ip6(neighbor_cache[i].netif, neighbor_cache[i].q, ip6_current_dest_addr()); + /* free the queued IP packet */ + pbuf_free(neighbor_cache[i].q); + neighbor_cache[i].q = NULL; + } +#endif /* LWIP_ND6_QUEUEING */ +} + + +/** + * Get the Path MTU for a destination. + * + * @param ip6addr the destination address + * @param netif the netif on which the packet will be sent + * @return the Path MTU, if known, or the netif default MTU + */ +u16_t +nd6_get_destination_mtu(ip6_addr_t * ip6addr, struct netif * netif) +{ + s8_t i; + + i = nd6_find_destination_cache_entry(ip6addr); + if (i >= 0) { + if (destination_cache[i].pmtu > 0) { + return destination_cache[i].pmtu; + } + } + + if (netif != NULL) { + return netif->mtu; + } + + return 1280; /* Minimum MTU */ +} + + +#if LWIP_ND6_TCP_REACHABILITY_HINTS +/** + * Provide the Neighbor discovery process with a hint that a + * destination is reachable. Called by tcp_receive when ACKs are + * received or sent (as per RFC). This is useful to avoid sending + * NS messages every 30 seconds. + * + * @param ip6addr the destination address which is know to be reachable + * by an upper layer protocol (TCP) + */ +void +nd6_reachability_hint(ip6_addr_t * ip6addr) +{ + s8_t i; + + /* Find destination in cache. */ + if (ip6_addr_cmp(ip6addr, &(destination_cache[nd6_cached_destination_index].destination_addr))) { + i = nd6_cached_destination_index; + ND6_STATS_INC(nd6.cachehit); + } + else { + i = nd6_find_destination_cache_entry(ip6addr); + } + if (i < 0) { + return; + } + + /* Find next hop neighbor in cache. */ + if (ip6_addr_cmp(&(destination_cache[i].next_hop_addr), &(neighbor_cache[nd6_cached_neighbor_index].next_hop_address))) { + i = nd6_cached_neighbor_index; + ND6_STATS_INC(nd6.cachehit); + } + else { + i = nd6_find_neighbor_cache_entry(&(destination_cache[i].next_hop_addr)); + } + if (i < 0) { + return; + } + + /* Set reachability state. */ + neighbor_cache[i].state = ND6_REACHABLE; + neighbor_cache[i].counter.reachable_time = reachable_time; +} +#endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */ + +#endif /* LWIP_IPV6 */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/core/lwip_timers.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/lwip_timers.c new file mode 100644 index 0000000..670dc1f --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/lwip_timers.c @@ -0,0 +1,562 @@ +/** + * @file + * Stack-internal timers implementation. + * This file includes timer callbacks for stack-internal timers as well as + * functions to set up or stop timers and check for expired timers. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * Simon Goldschmidt + * + */ + +#include "lwip/opt.h" + +#include "lwip/lwip_timers.h" // Evan modified timers.h to lwip_timers.h +#include "lwip/tcp_impl.h" + +#if LWIP_TIMERS + +#include "lwip/def.h" +#include "lwip/memp.h" +#include "lwip/tcpip.h" + +#include "lwip/ip_frag.h" +#include "netif/etharp.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" +#include "lwip/igmp.h" +#include "lwip/dns.h" +#include "lwip/nd6.h" +#include "lwip/ip6_frag.h" +#include "lwip/mld6.h" +#include "lwip/sys.h" +#include "lwip/pbuf.h" + +/** The one and only timeout list */ +static struct sys_timeo *next_timeout; +#if NO_SYS +static u32_t timeouts_last_time; +#endif /* NO_SYS */ + +#if LWIP_TCP +/** global variable that shows if the tcp timer is currently scheduled or not */ +static int tcpip_tcp_timer_active; + +/** + * Timer callback function that calls tcp_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +tcpip_tcp_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + + /* call TCP timer handler */ + tcp_tmr(); + /* timer still needed? */ + if (tcp_active_pcbs || tcp_tw_pcbs) { + /* restart timer */ + sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL); + } else { + /* disable timer */ + tcpip_tcp_timer_active = 0; + } +} + +/** + * Called from TCP_REG when registering a new PCB: + * the reason is to have the TCP timer only running when + * there are active (or time-wait) PCBs. + */ +void +tcp_timer_needed(void) +{ + /* timer is off but needed again? */ + if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) { + /* enable and start timer */ + tcpip_tcp_timer_active = 1; + sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL); + } +} +#endif /* LWIP_TCP */ + +#if IP_REASSEMBLY +/** + * Timer callback function that calls ip_reass_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +ip_reass_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: ip_reass_tmr()\n")); + ip_reass_tmr(); + sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL); +} +#endif /* IP_REASSEMBLY */ + +#if LWIP_ARP +/** + * Timer callback function that calls etharp_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +arp_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: etharp_tmr()\n")); + etharp_tmr(); + sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); +} +#endif /* LWIP_ARP */ + +#if LWIP_DHCP +/** + * Timer callback function that calls dhcp_coarse_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +dhcp_timer_coarse(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dhcp_coarse_tmr()\n")); + dhcp_coarse_tmr(); + sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL); +} + +/** + * Timer callback function that calls dhcp_fine_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +dhcp_timer_fine(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dhcp_fine_tmr()\n")); + dhcp_fine_tmr(); + sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL); +} +#endif /* LWIP_DHCP */ + +#if LWIP_AUTOIP +/** + * Timer callback function that calls autoip_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +autoip_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: autoip_tmr()\n")); + autoip_tmr(); + sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL); +} +#endif /* LWIP_AUTOIP */ + +#if LWIP_IGMP +/** + * Timer callback function that calls igmp_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +igmp_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: igmp_tmr()\n")); + igmp_tmr(); + sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL); +} +#endif /* LWIP_IGMP */ + +#if LWIP_DNS +/** + * Timer callback function that calls dns_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +dns_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dns_tmr()\n")); + dns_tmr(); + sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL); +} +#endif /* LWIP_DNS */ + +#if LWIP_IPV6 +/** + * Timer callback function that calls nd6_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +nd6_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: nd6_tmr()\n")); + nd6_tmr(); + sys_timeout(ND6_TMR_INTERVAL, nd6_timer, NULL); +} + +#if LWIP_IPV6_REASS +/** + * Timer callback function that calls ip6_reass_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +ip6_reass_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: ip6_reass_tmr()\n")); + ip6_reass_tmr(); + sys_timeout(IP6_REASS_TMR_INTERVAL, ip6_reass_timer, NULL); +} +#endif /* LWIP_IPV6_REASS */ + +#if LWIP_IPV6_MLD +/** + * Timer callback function that calls mld6_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +mld6_timer(void *arg) +{ + LWIP_UNUSED_ARG(arg); + LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: mld6_tmr()\n")); + mld6_tmr(); + sys_timeout(MLD6_TMR_INTERVAL, mld6_timer, NULL); +} +#endif /* LWIP_IPV6_MLD */ +#endif /* LWIP_IPV6 */ + +/** Initialize this module */ +void sys_timeouts_init(void) +{ +#if IP_REASSEMBLY + sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL); +#endif /* IP_REASSEMBLY */ +#if LWIP_ARP + sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); +#endif /* LWIP_ARP */ +#if LWIP_DHCP + sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL); + sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL); +#endif /* LWIP_DHCP */ +#if LWIP_AUTOIP + sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL); +#endif /* LWIP_AUTOIP */ +#if LWIP_IGMP + sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL); +#endif /* LWIP_IGMP */ +#if LWIP_DNS + sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL); +#endif /* LWIP_DNS */ +#if LWIP_IPV6 + sys_timeout(ND6_TMR_INTERVAL, nd6_timer, NULL); +#if LWIP_IPV6_REASS + sys_timeout(IP6_REASS_TMR_INTERVAL, ip6_reass_timer, NULL); +#endif /* LWIP_IPV6_REASS */ +#if LWIP_IPV6_MLD + sys_timeout(MLD6_TMR_INTERVAL, mld6_timer, NULL); +#endif /* LWIP_IPV6_MLD */ +#endif /* LWIP_IPV6 */ + +#if NO_SYS + /* Initialise timestamp for sys_check_timeouts */ + timeouts_last_time = sys_now(); +#endif +} + +/** + * Create a one-shot timer (aka timeout). Timeouts are processed in the + * following cases: + * - while waiting for a message using sys_timeouts_mbox_fetch() + * - by calling sys_check_timeouts() (NO_SYS==1 only) + * + * @param msecs time in milliseconds after that the timer should expire + * @param handler callback function to call when msecs have elapsed + * @param arg argument to pass to the callback function + */ +#if LWIP_DEBUG_TIMERNAMES +void +sys_timeout_debug(u32_t msecs, sys_timeout_handler handler, void *arg, const char* handler_name) +#else /* LWIP_DEBUG_TIMERNAMES */ +void +sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg) +#endif /* LWIP_DEBUG_TIMERNAMES */ +{ + struct sys_timeo *timeout, *t; +#if NO_SYS + u32_t now, diff; +#endif + + timeout = (struct sys_timeo *)memp_malloc(MEMP_SYS_TIMEOUT); + if (timeout == NULL) { + LWIP_ASSERT("sys_timeout: timeout != NULL, pool MEMP_SYS_TIMEOUT is empty", timeout != NULL); + return; + } + +#if NO_SYS + now = sys_now(); + if (next_timeout == NULL) { + diff = 0; + timeouts_last_time = now; + } else { + diff = now - timeouts_last_time; + } +#endif + + timeout->next = NULL; + timeout->h = handler; + timeout->arg = arg; +#if NO_SYS + timeout->time = msecs + diff; +#else + timeout->time = msecs; +#endif +#if LWIP_DEBUG_TIMERNAMES + timeout->handler_name = handler_name; + LWIP_DEBUGF(TIMERS_DEBUG, ("sys_timeout: %p msecs=%"U32_F" handler=%s arg=%p\n", + (void *)timeout, msecs, handler_name, (void *)arg)); +#endif /* LWIP_DEBUG_TIMERNAMES */ + + if (next_timeout == NULL) { + next_timeout = timeout; + return; + } + + if (next_timeout->time > msecs) { + next_timeout->time -= msecs; + timeout->next = next_timeout; + next_timeout = timeout; + } else { + for(t = next_timeout; t != NULL; t = t->next) { + timeout->time -= t->time; + if (t->next == NULL || t->next->time > timeout->time) { + if (t->next != NULL) { + t->next->time -= timeout->time; + } + timeout->next = t->next; + t->next = timeout; + break; + } + } + } +} + +/** + * Go through timeout list (for this task only) and remove the first matching + * entry (subsequent entries remain untouched), even though the timeout has not + * triggered yet. + * + * @param handler callback function that would be called by the timeout + * @param arg callback argument that would be passed to handler +*/ +void +sys_untimeout(sys_timeout_handler handler, void *arg) +{ + struct sys_timeo *prev_t, *t; + + if (next_timeout == NULL) { + return; + } + + for (t = next_timeout, prev_t = NULL; t != NULL; prev_t = t, t = t->next) { + if ((t->h == handler) && (t->arg == arg)) { + /* We have a match */ + /* Unlink from previous in list */ + if (prev_t == NULL) { + next_timeout = t->next; + } else { + prev_t->next = t->next; + } + /* If not the last one, add time of this one back to next */ + if (t->next != NULL) { + t->next->time += t->time; + } + memp_free(MEMP_SYS_TIMEOUT, t); + return; + } + } + return; +} + +#if NO_SYS + +/** Handle timeouts for NO_SYS==1 (i.e. without using + * tcpip_thread/sys_timeouts_mbox_fetch(). Uses sys_now() to call timeout + * handler functions when timeouts expire. + * + * Must be called periodically from your main loop. + */ +void +sys_check_timeouts(void) +{ + if (next_timeout) { + struct sys_timeo *tmptimeout; + u32_t diff; + sys_timeout_handler handler; + void *arg; + u8_t had_one; + u32_t now; + + now = sys_now(); + /* this cares for wraparounds */ + diff = now - timeouts_last_time; + do + { +#if PBUF_POOL_FREE_OOSEQ + PBUF_CHECK_FREE_OOSEQ(); +#endif /* PBUF_POOL_FREE_OOSEQ */ + had_one = 0; + tmptimeout = next_timeout; + if (tmptimeout && (tmptimeout->time <= diff)) { + /* timeout has expired */ + had_one = 1; + timeouts_last_time += tmptimeout->time; + diff -= tmptimeout->time; + next_timeout = tmptimeout->next; + handler = tmptimeout->h; + arg = tmptimeout->arg; +#if LWIP_DEBUG_TIMERNAMES + if (handler != NULL) { + LWIP_DEBUGF(TIMERS_DEBUG, ("sct calling h=%s arg=%p\n", + tmptimeout->handler_name, arg)); + } +#endif /* LWIP_DEBUG_TIMERNAMES */ + memp_free(MEMP_SYS_TIMEOUT, tmptimeout); + if (handler != NULL) { + handler(arg); + } + } + /* repeat until all expired timers have been called */ + }while(had_one); + } +} + +/** Set back the timestamp of the last call to sys_check_timeouts() + * This is necessary if sys_check_timeouts() hasn't been called for a long + * time (e.g. while saving energy) to prevent all timer functions of that + * period being called. + */ +void +sys_restart_timeouts(void) +{ + timeouts_last_time = sys_now(); +} + +#else /* NO_SYS */ + +/** + * Wait (forever) for a message to arrive in an mbox. + * While waiting, timeouts are processed. + * + * @param mbox the mbox to fetch the message from + * @param msg the place to store the message + */ +void +sys_timeouts_mbox_fetch(sys_mbox_t *mbox, void **msg) +{ + u32_t time_needed; + struct sys_timeo *tmptimeout; + sys_timeout_handler handler; + void *arg; + + again: + if (!next_timeout) { + time_needed = sys_arch_mbox_fetch(mbox, msg, 0); + } else { + if (next_timeout->time > 0) { + time_needed = sys_arch_mbox_fetch(mbox, msg, next_timeout->time); + } else { + time_needed = SYS_ARCH_TIMEOUT; + } + + if (time_needed == SYS_ARCH_TIMEOUT) { + /* If time == SYS_ARCH_TIMEOUT, a timeout occurred before a message + could be fetched. We should now call the timeout handler and + deallocate the memory allocated for the timeout. */ + tmptimeout = next_timeout; + next_timeout = tmptimeout->next; + handler = tmptimeout->h; + arg = tmptimeout->arg; +#if LWIP_DEBUG_TIMERNAMES + if (handler != NULL) { + LWIP_DEBUGF(TIMERS_DEBUG, ("stmf calling h=%s arg=%p\n", + tmptimeout->handler_name, arg)); + } +#endif /* LWIP_DEBUG_TIMERNAMES */ + memp_free(MEMP_SYS_TIMEOUT, tmptimeout); + if (handler != NULL) { + /* For LWIP_TCPIP_CORE_LOCKING, lock the core before calling the + timeout handler function. */ + LOCK_TCPIP_CORE(); + handler(arg); + UNLOCK_TCPIP_CORE(); + } + LWIP_TCPIP_THREAD_ALIVE(); + + /* We try again to fetch a message from the mbox. */ + goto again; + } else { + /* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout + occured. The time variable is set to the number of + milliseconds we waited for the message. */ + if (time_needed < next_timeout->time) { + next_timeout->time -= time_needed; + } else { + next_timeout->time = 0; + } + } + } +} + +#endif /* NO_SYS */ + +#else /* LWIP_TIMERS */ +/* Satisfy the TCP code which calls this function */ +void +tcp_timer_needed(void) +{ +} +#endif /* LWIP_TIMERS */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/core/mem.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/mem.c new file mode 100644 index 0000000..634e760 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/mem.c @@ -0,0 +1,677 @@ +/** + * @file + * Dynamic memory manager + * + * This is a lightweight replacement for the standard C library malloc(). + * + * If you want to use the standard C library malloc() instead, define + * MEM_LIBC_MALLOC to 1 in your lwipopts.h + * + * To let mem_malloc() use pools (prevents fragmentation and is much faster than + * a heap but might waste some memory), define MEM_USE_POOLS to 1, define + * MEM_USE_CUSTOM_POOLS to 1 and create a file "lwippools.h" that includes a list + * of pools like this (more pools can be added between _START and _END): + * + * Define three pools with sizes 256, 512, and 1512 bytes + * LWIP_MALLOC_MEMPOOL_START + * LWIP_MALLOC_MEMPOOL(20, 256) + * LWIP_MALLOC_MEMPOOL(10, 512) + * LWIP_MALLOC_MEMPOOL(5, 1512) + * LWIP_MALLOC_MEMPOOL_END + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * Simon Goldschmidt + * + */ + +#include "lwip/opt.h" + +#if !MEM_LIBC_MALLOC /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/sys.h" +#include "lwip/stats.h" +#include "lwip/err.h" + +#include + +#if MEM_USE_POOLS +/* lwIP head implemented with different sized pools */ + +/** + * Allocate memory: determine the smallest pool that is big enough + * to contain an element of 'size' and get an element from that pool. + * + * @param size the size in bytes of the memory needed + * @return a pointer to the allocated memory or NULL if the pool is empty + */ +void * +mem_malloc(mem_size_t size) +{ + void *ret; + struct memp_malloc_helper *element; + memp_t poolnr; + mem_size_t required_size = size + LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper)); + + for (poolnr = MEMP_POOL_FIRST; poolnr <= MEMP_POOL_LAST; poolnr = (memp_t)(poolnr + 1)) { +#if MEM_USE_POOLS_TRY_BIGGER_POOL +again: +#endif /* MEM_USE_POOLS_TRY_BIGGER_POOL */ + /* is this pool big enough to hold an element of the required size + plus a struct memp_malloc_helper that saves the pool this element came from? */ + if (required_size <= memp_sizes[poolnr]) { + break; + } + } + if (poolnr > MEMP_POOL_LAST) { + LWIP_ASSERT("mem_malloc(): no pool is that big!", 0); + return NULL; + } + element = (struct memp_malloc_helper*)memp_malloc(poolnr); + if (element == NULL) { + /* No need to DEBUGF or ASSERT: This error is already + taken care of in memp.c */ +#if MEM_USE_POOLS_TRY_BIGGER_POOL + /** Try a bigger pool if this one is empty! */ + if (poolnr < MEMP_POOL_LAST) { + poolnr++; + goto again; + } +#endif /* MEM_USE_POOLS_TRY_BIGGER_POOL */ + return NULL; + } + + /* save the pool number this element came from */ + element->poolnr = poolnr; + /* and return a pointer to the memory directly after the struct memp_malloc_helper */ + ret = (u8_t*)element + LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper)); + +#if MEMP_OVERFLOW_CHECK + /* initialize unused memory */ + element->size = size; + memset((u8_t*)ret + size, 0xcd, memp_sizes[poolnr] - size); +#endif /* MEMP_OVERFLOW_CHECK */ + return ret; +} + +/** + * Free memory previously allocated by mem_malloc. Loads the pool number + * and calls memp_free with that pool number to put the element back into + * its pool + * + * @param rmem the memory element to free + */ +void +mem_free(void *rmem) +{ + struct memp_malloc_helper *hmem; + + LWIP_ASSERT("rmem != NULL", (rmem != NULL)); + LWIP_ASSERT("rmem == MEM_ALIGN(rmem)", (rmem == LWIP_MEM_ALIGN(rmem))); + + /* get the original struct memp_malloc_helper */ + hmem = (struct memp_malloc_helper*)(void*)((u8_t*)rmem - LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper))); + + LWIP_ASSERT("hmem != NULL", (hmem != NULL)); + LWIP_ASSERT("hmem == MEM_ALIGN(hmem)", (hmem == LWIP_MEM_ALIGN(hmem))); + LWIP_ASSERT("hmem->poolnr < MEMP_MAX", (hmem->poolnr < MEMP_MAX)); + +#if MEMP_OVERFLOW_CHECK + { + u16_t i; + LWIP_ASSERT("MEM_USE_POOLS: invalid chunk size", + hmem->size <= memp_sizes[hmem->poolnr]); + /* check that unused memory remained untouched */ + for (i = hmem->size; i < memp_sizes[hmem->poolnr]; i++) { + u8_t data = *((u8_t*)rmem + i); + LWIP_ASSERT("MEM_USE_POOLS: mem overflow detected", data == 0xcd); + } + } +#endif /* MEMP_OVERFLOW_CHECK */ + + /* and put it in the pool we saved earlier */ + memp_free(hmem->poolnr, hmem); +} + +#else /* MEM_USE_POOLS */ +/* lwIP replacement for your libc malloc() */ + +/** + * The heap is made up as a list of structs of this type. + * This does not have to be aligned since for getting its size, + * we only use the macro SIZEOF_STRUCT_MEM, which automatically aligns. + */ +struct mem { + /** index (-> ram[next]) of the next struct */ + mem_size_t next; + /** index (-> ram[prev]) of the previous struct */ + mem_size_t prev; + /** 1: this area is used; 0: this area is unused */ + u8_t used; +}; + +/** All allocated blocks will be MIN_SIZE bytes big, at least! + * MIN_SIZE can be overridden to suit your needs. Smaller values save space, + * larger values could prevent too small blocks to fragment the RAM too much. */ +#ifndef MIN_SIZE +#define MIN_SIZE 12 +#endif /* MIN_SIZE */ +/* some alignment macros: we define them here for better source code layout */ +#define MIN_SIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(MIN_SIZE) +#define SIZEOF_STRUCT_MEM LWIP_MEM_ALIGN_SIZE(sizeof(struct mem)) +#define MEM_SIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(MEM_SIZE) + +/** If you want to relocate the heap to external memory, simply define + * LWIP_RAM_HEAP_POINTER as a void-pointer to that location. + * If so, make sure the memory at that location is big enough (see below on + * how that space is calculated). */ +#ifndef LWIP_RAM_HEAP_POINTER +/** the heap. we need one struct mem at the end and some room for alignment */ +u8_t ram_heap[MEM_SIZE_ALIGNED + (2U*SIZEOF_STRUCT_MEM) + MEM_ALIGNMENT]; +#define LWIP_RAM_HEAP_POINTER ram_heap +#endif /* LWIP_RAM_HEAP_POINTER */ + +/** pointer to the heap (ram_heap): for alignment, ram is now a pointer instead of an array */ +static u8_t *ram; +/** the last entry, always unused! */ +static struct mem *ram_end; +/** pointer to the lowest free block, this is used for faster search */ +static struct mem *lfree; + +/** concurrent access protection */ +#if !NO_SYS +static sys_mutex_t mem_mutex; +#endif + +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + +static volatile u8_t mem_free_count; + +/* Allow mem_free from other (e.g. interrupt) context */ +#define LWIP_MEM_FREE_DECL_PROTECT() SYS_ARCH_DECL_PROTECT(lev_free) +#define LWIP_MEM_FREE_PROTECT() SYS_ARCH_PROTECT(lev_free) +#define LWIP_MEM_FREE_UNPROTECT() SYS_ARCH_UNPROTECT(lev_free) +#define LWIP_MEM_ALLOC_DECL_PROTECT() SYS_ARCH_DECL_PROTECT(lev_alloc) +#define LWIP_MEM_ALLOC_PROTECT() SYS_ARCH_PROTECT(lev_alloc) +#define LWIP_MEM_ALLOC_UNPROTECT() SYS_ARCH_UNPROTECT(lev_alloc) + +#else /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + +/* Protect the heap only by using a semaphore */ +#define LWIP_MEM_FREE_DECL_PROTECT() +#define LWIP_MEM_FREE_PROTECT() sys_mutex_lock(&mem_mutex) +#define LWIP_MEM_FREE_UNPROTECT() sys_mutex_unlock(&mem_mutex) +/* mem_malloc is protected using semaphore AND LWIP_MEM_ALLOC_PROTECT */ +#define LWIP_MEM_ALLOC_DECL_PROTECT() +#define LWIP_MEM_ALLOC_PROTECT() +#define LWIP_MEM_ALLOC_UNPROTECT() + +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + + +/** + * "Plug holes" by combining adjacent empty struct mems. + * After this function is through, there should not exist + * one empty struct mem pointing to another empty struct mem. + * + * @param mem this points to a struct mem which just has been freed + * @internal this function is only called by mem_free() and mem_trim() + * + * This assumes access to the heap is protected by the calling function + * already. + */ +static void +plug_holes(struct mem *mem) +{ + struct mem *nmem; + struct mem *pmem; + + LWIP_ASSERT("plug_holes: mem >= ram", (u8_t *)mem >= ram); + LWIP_ASSERT("plug_holes: mem < ram_end", (u8_t *)mem < (u8_t *)ram_end); + LWIP_ASSERT("plug_holes: mem->used == 0", mem->used == 0); + + /* plug hole forward */ + LWIP_ASSERT("plug_holes: mem->next <= MEM_SIZE_ALIGNED", mem->next <= MEM_SIZE_ALIGNED); + + nmem = (struct mem *)(void *)&ram[mem->next]; + if (mem != nmem && nmem->used == 0 && (u8_t *)nmem != (u8_t *)ram_end) { + /* if mem->next is unused and not end of ram, combine mem and mem->next */ + if (lfree == nmem) { + lfree = mem; + } + mem->next = nmem->next; + ((struct mem *)(void *)&ram[nmem->next])->prev = (mem_size_t)((u8_t *)mem - ram); + } + + /* plug hole backward */ + pmem = (struct mem *)(void *)&ram[mem->prev]; + if (pmem != mem && pmem->used == 0) { + /* if mem->prev is unused, combine mem and mem->prev */ + if (lfree == mem) { + lfree = pmem; + } + pmem->next = mem->next; + ((struct mem *)(void *)&ram[mem->next])->prev = (mem_size_t)((u8_t *)pmem - ram); + } +} + +/** + * Zero the heap and initialize start, end and lowest-free + */ +void +mem_init(void) +{ + struct mem *mem; + + LWIP_ASSERT("Sanity check alignment", + (SIZEOF_STRUCT_MEM & (MEM_ALIGNMENT-1)) == 0); + + /* align the heap */ + ram = (u8_t *)LWIP_MEM_ALIGN(LWIP_RAM_HEAP_POINTER); + /* initialize the start of the heap */ + mem = (struct mem *)(void *)ram; + mem->next = MEM_SIZE_ALIGNED; + mem->prev = 0; + mem->used = 0; + /* initialize the end of the heap */ + ram_end = (struct mem *)(void *)&ram[MEM_SIZE_ALIGNED]; + ram_end->used = 1; + ram_end->next = MEM_SIZE_ALIGNED; + ram_end->prev = MEM_SIZE_ALIGNED; + + /* initialize the lowest-free pointer to the start of the heap */ + lfree = (struct mem *)(void *)ram; + + MEM_STATS_AVAIL(avail, MEM_SIZE_ALIGNED); + + if(sys_mutex_new(&mem_mutex) != ERR_OK) { + LWIP_ASSERT("failed to create mem_mutex", 0); + } +} + +/** + * Put a struct mem back on the heap + * + * @param rmem is the data portion of a struct mem as returned by a previous + * call to mem_malloc() + */ +void +mem_free(void *rmem) +{ + struct mem *mem; + LWIP_MEM_FREE_DECL_PROTECT(); + + if (rmem == NULL) { + LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("mem_free(p == NULL) was called.\n")); + return; + } + LWIP_ASSERT("mem_free: sanity check alignment", (((mem_ptr_t)rmem) & (MEM_ALIGNMENT-1)) == 0); + + LWIP_ASSERT("mem_free: legal memory", (u8_t *)rmem >= (u8_t *)ram && + (u8_t *)rmem < (u8_t *)ram_end); + + if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) { + SYS_ARCH_DECL_PROTECT(lev); + LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_free: illegal memory\n")); + /* protect mem stats from concurrent access */ + SYS_ARCH_PROTECT(lev); + MEM_STATS_INC(illegal); + SYS_ARCH_UNPROTECT(lev); + return; + } + /* protect the heap from concurrent access */ + LWIP_MEM_FREE_PROTECT(); + /* Get the corresponding struct mem ... */ + mem = (struct mem *)(void *)((u8_t *)rmem - SIZEOF_STRUCT_MEM); + /* ... which has to be in a used state ... */ + LWIP_ASSERT("mem_free: mem->used", mem->used); + /* ... and is now unused. */ + mem->used = 0; + + if (mem < lfree) { + /* the newly freed struct is now the lowest */ + lfree = mem; + } + + MEM_STATS_DEC_USED(used, mem->next - (mem_size_t)(((u8_t *)mem - ram))); + + /* finally, see if prev or next are free also */ + plug_holes(mem); +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + mem_free_count = 1; +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + LWIP_MEM_FREE_UNPROTECT(); +} + +/** + * Shrink memory returned by mem_malloc(). + * + * @param rmem pointer to memory allocated by mem_malloc the is to be shrinked + * @param newsize required size after shrinking (needs to be smaller than or + * equal to the previous size) + * @return for compatibility reasons: is always == rmem, at the moment + * or NULL if newsize is > old size, in which case rmem is NOT touched + * or freed! + */ +void * +mem_trim(void *rmem, mem_size_t newsize) +{ + mem_size_t size; + mem_size_t ptr, ptr2; + struct mem *mem, *mem2; + /* use the FREE_PROTECT here: it protects with sem OR SYS_ARCH_PROTECT */ + LWIP_MEM_FREE_DECL_PROTECT(); + + /* Expand the size of the allocated memory region so that we can + adjust for alignment. */ + newsize = LWIP_MEM_ALIGN_SIZE(newsize); + + if(newsize < MIN_SIZE_ALIGNED) { + /* every data block must be at least MIN_SIZE_ALIGNED long */ + newsize = MIN_SIZE_ALIGNED; + } + + if (newsize > MEM_SIZE_ALIGNED) { + return NULL; + } + + LWIP_ASSERT("mem_trim: legal memory", (u8_t *)rmem >= (u8_t *)ram && + (u8_t *)rmem < (u8_t *)ram_end); + + if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) { + SYS_ARCH_DECL_PROTECT(lev); + LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_trim: illegal memory\n")); + /* protect mem stats from concurrent access */ + SYS_ARCH_PROTECT(lev); + MEM_STATS_INC(illegal); + SYS_ARCH_UNPROTECT(lev); + return rmem; + } + /* Get the corresponding struct mem ... */ + mem = (struct mem *)(void *)((u8_t *)rmem - SIZEOF_STRUCT_MEM); + /* ... and its offset pointer */ + ptr = (mem_size_t)((u8_t *)mem - ram); + + size = mem->next - ptr - SIZEOF_STRUCT_MEM; + LWIP_ASSERT("mem_trim can only shrink memory", newsize <= size); + if (newsize > size) { + /* not supported */ + return NULL; + } + if (newsize == size) { + /* No change in size, simply return */ + return rmem; + } + + /* protect the heap from concurrent access */ + LWIP_MEM_FREE_PROTECT(); + + mem2 = (struct mem *)(void *)&ram[mem->next]; + if(mem2->used == 0) { + /* The next struct is unused, we can simply move it at little */ + mem_size_t next; + /* remember the old next pointer */ + next = mem2->next; + /* create new struct mem which is moved directly after the shrinked mem */ + ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize; + if (lfree == mem2) { + lfree = (struct mem *)(void *)&ram[ptr2]; + } + mem2 = (struct mem *)(void *)&ram[ptr2]; + mem2->used = 0; + /* restore the next pointer */ + mem2->next = next; + /* link it back to mem */ + mem2->prev = ptr; + /* link mem to it */ + mem->next = ptr2; + /* last thing to restore linked list: as we have moved mem2, + * let 'mem2->next->prev' point to mem2 again. but only if mem2->next is not + * the end of the heap */ + if (mem2->next != MEM_SIZE_ALIGNED) { + ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2; + } + MEM_STATS_DEC_USED(used, (size - newsize)); + /* no need to plug holes, we've already done that */ + } else if (newsize + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED <= size) { + /* Next struct is used but there's room for another struct mem with + * at least MIN_SIZE_ALIGNED of data. + * Old size ('size') must be big enough to contain at least 'newsize' plus a struct mem + * ('SIZEOF_STRUCT_MEM') with some data ('MIN_SIZE_ALIGNED'). + * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty + * region that couldn't hold data, but when mem->next gets freed, + * the 2 regions would be combined, resulting in more free memory */ + ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize; + mem2 = (struct mem *)(void *)&ram[ptr2]; + if (mem2 < lfree) { + lfree = mem2; + } + mem2->used = 0; + mem2->next = mem->next; + mem2->prev = ptr; + mem->next = ptr2; + if (mem2->next != MEM_SIZE_ALIGNED) { + ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2; + } + MEM_STATS_DEC_USED(used, (size - newsize)); + /* the original mem->next is used, so no need to plug holes! */ + } + /* else { + next struct mem is used but size between mem and mem2 is not big enough + to create another struct mem + -> don't do anyhting. + -> the remaining space stays unused since it is too small + } */ +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + mem_free_count = 1; +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + LWIP_MEM_FREE_UNPROTECT(); + return rmem; +} + +/** + * Adam's mem_malloc() plus solution for bug #17922 + * Allocate a block of memory with a minimum of 'size' bytes. + * + * @param size is the minimum size of the requested block in bytes. + * @return pointer to allocated memory or NULL if no free memory was found. + * + * Note that the returned value will always be aligned (as defined by MEM_ALIGNMENT). + */ +void * +mem_malloc(mem_size_t size) +{ + mem_size_t ptr, ptr2; + struct mem *mem, *mem2; +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + u8_t local_mem_free_count = 0; +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + LWIP_MEM_ALLOC_DECL_PROTECT(); + + if (size == 0) { + return NULL; + } + + /* Expand the size of the allocated memory region so that we can + adjust for alignment. */ + size = LWIP_MEM_ALIGN_SIZE(size); + + if(size < MIN_SIZE_ALIGNED) { + /* every data block must be at least MIN_SIZE_ALIGNED long */ + size = MIN_SIZE_ALIGNED; + } + + if (size > MEM_SIZE_ALIGNED) { + return NULL; + } + + /* protect the heap from concurrent access */ + sys_mutex_lock(&mem_mutex); + LWIP_MEM_ALLOC_PROTECT(); +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + /* run as long as a mem_free disturbed mem_malloc or mem_trim */ + do { + local_mem_free_count = 0; +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + + /* Scan through the heap searching for a free block that is big enough, + * beginning with the lowest free block. + */ + for (ptr = (mem_size_t)((u8_t *)lfree - ram); ptr < MEM_SIZE_ALIGNED - size; + ptr = ((struct mem *)(void *)&ram[ptr])->next) { + mem = (struct mem *)(void *)&ram[ptr]; +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + mem_free_count = 0; + LWIP_MEM_ALLOC_UNPROTECT(); + /* allow mem_free or mem_trim to run */ + LWIP_MEM_ALLOC_PROTECT(); + if (mem_free_count != 0) { + /* If mem_free or mem_trim have run, we have to restart since they + could have altered our current struct mem. */ + local_mem_free_count = 1; + break; + } +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + + if ((!mem->used) && + (mem->next - (ptr + SIZEOF_STRUCT_MEM)) >= size) { + /* mem is not used and at least perfect fit is possible: + * mem->next - (ptr + SIZEOF_STRUCT_MEM) gives us the 'user data size' of mem */ + + if (mem->next - (ptr + SIZEOF_STRUCT_MEM) >= (size + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED)) { + /* (in addition to the above, we test if another struct mem (SIZEOF_STRUCT_MEM) containing + * at least MIN_SIZE_ALIGNED of data also fits in the 'user data space' of 'mem') + * -> split large block, create empty remainder, + * remainder must be large enough to contain MIN_SIZE_ALIGNED data: if + * mem->next - (ptr + (2*SIZEOF_STRUCT_MEM)) == size, + * struct mem would fit in but no data between mem2 and mem2->next + * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty + * region that couldn't hold data, but when mem->next gets freed, + * the 2 regions would be combined, resulting in more free memory + */ + ptr2 = ptr + SIZEOF_STRUCT_MEM + size; + /* create mem2 struct */ + mem2 = (struct mem *)(void *)&ram[ptr2]; + mem2->used = 0; + mem2->next = mem->next; + mem2->prev = ptr; + /* and insert it between mem and mem->next */ + mem->next = ptr2; + mem->used = 1; + + if (mem2->next != MEM_SIZE_ALIGNED) { + ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2; + } + MEM_STATS_INC_USED(used, (size + SIZEOF_STRUCT_MEM)); + } else { + /* (a mem2 struct does no fit into the user data space of mem and mem->next will always + * be used at this point: if not we have 2 unused structs in a row, plug_holes should have + * take care of this). + * -> near fit or exact fit: do not split, no mem2 creation + * also can't move mem->next directly behind mem, since mem->next + * will always be used at this point! + */ + mem->used = 1; + MEM_STATS_INC_USED(used, mem->next - (mem_size_t)((u8_t *)mem - ram)); + } +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT +mem_malloc_adjust_lfree: +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + if (mem == lfree) { + struct mem *cur = lfree; + /* Find next free block after mem and update lowest free pointer */ + while (cur->used && cur != ram_end) { +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + mem_free_count = 0; + LWIP_MEM_ALLOC_UNPROTECT(); + /* prevent high interrupt latency... */ + LWIP_MEM_ALLOC_PROTECT(); + if (mem_free_count != 0) { + /* If mem_free or mem_trim have run, we have to restart since they + could have altered our current struct mem or lfree. */ + goto mem_malloc_adjust_lfree; + } +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + cur = (struct mem *)(void *)&ram[cur->next]; + } + lfree = cur; + LWIP_ASSERT("mem_malloc: !lfree->used", ((lfree == ram_end) || (!lfree->used))); + } + LWIP_MEM_ALLOC_UNPROTECT(); + sys_mutex_unlock(&mem_mutex); + LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.", + (mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end); + LWIP_ASSERT("mem_malloc: allocated memory properly aligned.", + ((mem_ptr_t)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0); + LWIP_ASSERT("mem_malloc: sanity check alignment", + (((mem_ptr_t)mem) & (MEM_ALIGNMENT-1)) == 0); + + return (u8_t *)mem + SIZEOF_STRUCT_MEM; + } + } +#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT + /* if we got interrupted by a mem_free, try again */ + } while(local_mem_free_count != 0); +#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ + LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("mem_malloc: could not allocate %"S16_F" bytes\n", (s16_t)size)); + MEM_STATS_INC(err); + LWIP_MEM_ALLOC_UNPROTECT(); + sys_mutex_unlock(&mem_mutex); + return NULL; +} + +#endif /* MEM_USE_POOLS */ +/** + * Contiguously allocates enough space for count objects that are size bytes + * of memory each and returns a pointer to the allocated memory. + * + * The allocated memory is filled with bytes of value zero. + * + * @param count number of objects to allocate + * @param size size of the objects to allocate + * @return pointer to allocated memory / NULL pointer if there is an error + */ +void *mem_calloc(mem_size_t count, mem_size_t size) +{ + void *p; + + /* allocate 'count' objects of size 'size' */ + p = mem_malloc(count * size); + if (p) { + /* zero the memory */ + memset(p, 0, count * size); + } + return p; +} + +#endif /* !MEM_LIBC_MALLOC */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/core/memp.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/memp.c new file mode 100644 index 0000000..d7ba6ad --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/memp.c @@ -0,0 +1,489 @@ +/** + * @file + * Dynamic pool memory manager + * + * lwIP has dedicated pools for many structures (netconn, protocol control blocks, + * packet buffers, ...). All these pools are managed here. + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/memp.h" +#include "lwip/pbuf.h" +#include "lwip/udp.h" +#include "lwip/raw.h" +#include "lwip/tcp_impl.h" +#include "lwip/igmp.h" +#include "lwip/api.h" +#include "lwip/api_msg.h" +#include "lwip/sockets.h" +#include "lwip/tcpip.h" +#include "lwip/sys.h" +#include "lwip/lwip_timers.h" // Evan modified timers.h to lwip_timers.h +#include "lwip/stats.h" +#include "netif/etharp.h" +#include "lwip/ip_frag.h" +#include "lwip/snmp_structs.h" +#include "lwip/snmp_msg.h" +#include "lwip/dns.h" +#include "lwip/netdb.h" +#include "netif/ppp/ppp.h" +#include "netif/ppp/pppoe.h" +#include "netif/ppp/pppol2tp.h" +#include "lwip/nd6.h" +#include "lwip/ip6_frag.h" +#include "lwip/mld6.h" + +#include + +#if !MEMP_MEM_MALLOC /* don't build if not configured for use in lwipopts.h */ + +struct memp { + struct memp *next; +#if MEMP_OVERFLOW_CHECK + const char *file; + int line; +#endif /* MEMP_OVERFLOW_CHECK */ +}; + +#if MEMP_OVERFLOW_CHECK +/* if MEMP_OVERFLOW_CHECK is turned on, we reserve some bytes at the beginning + * and at the end of each element, initialize them as 0xcd and check + * them later. */ +/* If MEMP_OVERFLOW_CHECK is >= 2, on every call to memp_malloc or memp_free, + * every single element in each pool is checked! + * This is VERY SLOW but also very helpful. */ +/* MEMP_SANITY_REGION_BEFORE and MEMP_SANITY_REGION_AFTER can be overridden in + * lwipopts.h to change the amount reserved for checking. */ +#ifndef MEMP_SANITY_REGION_BEFORE +#define MEMP_SANITY_REGION_BEFORE 16 +#endif /* MEMP_SANITY_REGION_BEFORE*/ +#if MEMP_SANITY_REGION_BEFORE > 0 +#define MEMP_SANITY_REGION_BEFORE_ALIGNED LWIP_MEM_ALIGN_SIZE(MEMP_SANITY_REGION_BEFORE) +#else +#define MEMP_SANITY_REGION_BEFORE_ALIGNED 0 +#endif /* MEMP_SANITY_REGION_BEFORE*/ +#ifndef MEMP_SANITY_REGION_AFTER +#define MEMP_SANITY_REGION_AFTER 16 +#endif /* MEMP_SANITY_REGION_AFTER*/ +#if MEMP_SANITY_REGION_AFTER > 0 +#define MEMP_SANITY_REGION_AFTER_ALIGNED LWIP_MEM_ALIGN_SIZE(MEMP_SANITY_REGION_AFTER) +#else +#define MEMP_SANITY_REGION_AFTER_ALIGNED 0 +#endif /* MEMP_SANITY_REGION_AFTER*/ + +/* MEMP_SIZE: save space for struct memp and for sanity check */ +#define MEMP_SIZE (LWIP_MEM_ALIGN_SIZE(sizeof(struct memp)) + MEMP_SANITY_REGION_BEFORE_ALIGNED) +#define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x) + MEMP_SANITY_REGION_AFTER_ALIGNED) + +#else /* MEMP_OVERFLOW_CHECK */ + +/* No sanity checks + * We don't need to preserve the struct memp while not allocated, so we + * can save a little space and set MEMP_SIZE to 0. + */ +#define MEMP_SIZE 0 +#define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x)) + +#endif /* MEMP_OVERFLOW_CHECK */ + +/** This array holds the first free element of each pool. + * Elements form a linked list. */ +static struct memp *memp_tab[MEMP_MAX]; + +#else /* MEMP_MEM_MALLOC */ + +#define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x)) + +#endif /* MEMP_MEM_MALLOC */ + +/** This array holds the element sizes of each pool. */ +#if !MEM_USE_POOLS && !MEMP_MEM_MALLOC +static +#endif +const u16_t memp_sizes[MEMP_MAX] = { +#define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEM_ALIGN_SIZE(size), +#include "lwip/memp_std.h" +}; + +#if !MEMP_MEM_MALLOC /* don't build if not configured for use in lwipopts.h */ + +/** This array holds the number of elements in each pool. */ +static const u16_t memp_num[MEMP_MAX] = { +#define LWIP_MEMPOOL(name,num,size,desc) (num), +#include "lwip/memp_std.h" +}; + +/** This array holds a textual description of each pool. */ +#ifdef LWIP_DEBUG +static const char *memp_desc[MEMP_MAX] = { +#define LWIP_MEMPOOL(name,num,size,desc) (desc), +#include "lwip/memp_std.h" +}; +#endif /* LWIP_DEBUG */ + +#if MEMP_SEPARATE_POOLS + +/** This creates each memory pool. These are named memp_memory_XXX_base (where + * XXX is the name of the pool defined in memp_std.h). + * To relocate a pool, declare it as extern in cc.h. Example for GCC: + * extern u8_t __attribute__((section(".onchip_mem"))) memp_memory_UDP_PCB_base[]; + */ +#define LWIP_MEMPOOL(name,num,size,desc) u8_t memp_memory_ ## name ## _base \ + [((num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size)))]; +#include "lwip/memp_std.h" + +/** This array holds the base of each memory pool. */ +static u8_t *const memp_bases[] = { +#define LWIP_MEMPOOL(name,num,size,desc) memp_memory_ ## name ## _base, +#include "lwip/memp_std.h" +}; + +#else /* MEMP_SEPARATE_POOLS */ + +/** This is the actual memory used by the pools (all pools in one big block). */ +static u8_t memp_memory[MEM_ALIGNMENT - 1 +#define LWIP_MEMPOOL(name,num,size,desc) + ( (num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size) ) ) +#include "lwip/memp_std.h" +]; + +#endif /* MEMP_SEPARATE_POOLS */ + +#if MEMP_SANITY_CHECK +/** + * Check that memp-lists don't form a circle, using "Floyd's cycle-finding algorithm". + */ +static int +memp_sanity(void) +{ + s16_t i; + struct memp *t, *h; + + for (i = 0; i < MEMP_MAX; i++) { + t = memp_tab[i]; + if(t != NULL) { + for (h = t->next; (t != NULL) && (h != NULL); t = t->next, + h = (((h->next != NULL) && (h->next->next != NULL)) ? h->next->next : NULL)) { + if (t == h) { + return 0; + } + } + } + } + return 1; +} +#endif /* MEMP_SANITY_CHECK*/ +#if MEMP_OVERFLOW_CHECK +#if defined(LWIP_DEBUG) && MEMP_STATS +static const char * memp_overflow_names[] = { +#define LWIP_MEMPOOL(name,num,size,desc) "/"desc, +#include "lwip/memp_std.h" + }; +#endif + +/** + * Check if a memp element was victim of an overflow + * (e.g. the restricted area after it has been altered) + * + * @param p the memp element to check + * @param memp_type the pool p comes from + */ +static void +memp_overflow_check_element_overflow(struct memp *p, u16_t memp_type) +{ + u16_t k; + u8_t *m; +#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0 + m = (u8_t*)p + MEMP_SIZE + memp_sizes[memp_type]; + for (k = 0; k < MEMP_SANITY_REGION_AFTER_ALIGNED; k++) { + if (m[k] != 0xcd) { + char errstr[128] = "detected memp overflow in pool "; + char digit[] = "0"; + if(memp_type >= 10) { + digit[0] = '0' + (memp_type/10); + strcat(errstr, digit); + } + digit[0] = '0' + (memp_type%10); + strcat(errstr, digit); +#if defined(LWIP_DEBUG) && MEMP_STATS + strcat(errstr, memp_overflow_names[memp_type]); +#endif + LWIP_ASSERT(errstr, 0); + } + } +#endif +} + +/** + * Check if a memp element was victim of an underflow + * (e.g. the restricted area before it has been altered) + * + * @param p the memp element to check + * @param memp_type the pool p comes from + */ +static void +memp_overflow_check_element_underflow(struct memp *p, u16_t memp_type) +{ + u16_t k; + u8_t *m; +#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 + m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED; + for (k = 0; k < MEMP_SANITY_REGION_BEFORE_ALIGNED; k++) { + if (m[k] != 0xcd) { + char errstr[128] = "detected memp underflow in pool "; + char digit[] = "0"; + if(memp_type >= 10) { + digit[0] = '0' + (memp_type/10); + strcat(errstr, digit); + } + digit[0] = '0' + (memp_type%10); + strcat(errstr, digit); +#if defined(LWIP_DEBUG) && MEMP_STATS + strcat(errstr, memp_overflow_names[memp_type]); +#endif + LWIP_ASSERT(errstr, 0); + } + } +#endif +} + +/** + * Do an overflow check for all elements in every pool. + * + * @see memp_overflow_check_element for a description of the check + */ +static void +memp_overflow_check_all(void) +{ + u16_t i, j; + struct memp *p; + +#if !MEMP_SEPARATE_POOLS + p = (struct memp *)LWIP_MEM_ALIGN(memp_memory); +#endif /* !MEMP_SEPARATE_POOLS */ + for (i = 0; i < MEMP_MAX; ++i) { +#if MEMP_SEPARATE_POOLS + p = (struct memp *)(memp_bases[i]); +#endif /* MEMP_SEPARATE_POOLS */ + for (j = 0; j < memp_num[i]; ++j) { + memp_overflow_check_element_overflow(p, i); + p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i] + MEMP_SANITY_REGION_AFTER_ALIGNED); + } + } +#if !MEMP_SEPARATE_POOLS + p = (struct memp *)LWIP_MEM_ALIGN(memp_memory); +#endif /* !MEMP_SEPARATE_POOLS */ + for (i = 0; i < MEMP_MAX; ++i) { +#if MEMP_SEPARATE_POOLS + p = (struct memp *)(memp_bases[i]); +#endif /* MEMP_SEPARATE_POOLS */ + for (j = 0; j < memp_num[i]; ++j) { + memp_overflow_check_element_underflow(p, i); + p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i] + MEMP_SANITY_REGION_AFTER_ALIGNED); + } + } +} + +/** + * Initialize the restricted areas of all memp elements in every pool. + */ +static void +memp_overflow_init(void) +{ + u16_t i, j; + struct memp *p; + u8_t *m; + +#if !MEMP_SEPARATE_POOLS + p = (struct memp *)LWIP_MEM_ALIGN(memp_memory); +#endif /* !MEMP_SEPARATE_POOLS */ + for (i = 0; i < MEMP_MAX; ++i) { +#if MEMP_SEPARATE_POOLS + p = (struct memp *)(memp_bases[i]); +#endif /* MEMP_SEPARATE_POOLS */ + for (j = 0; j < memp_num[i]; ++j) { +#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 + m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED; + memset(m, 0xcd, MEMP_SANITY_REGION_BEFORE_ALIGNED); +#endif +#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0 + m = (u8_t*)p + MEMP_SIZE + memp_sizes[i]; + memset(m, 0xcd, MEMP_SANITY_REGION_AFTER_ALIGNED); +#endif + p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i] + MEMP_SANITY_REGION_AFTER_ALIGNED); + } + } +} +#endif /* MEMP_OVERFLOW_CHECK */ + +/** + * Initialize this module. + * + * Carves out memp_memory into linked lists for each pool-type. + */ +void +memp_init(void) +{ + struct memp *memp; + u16_t i, j; + + for (i = 0; i < MEMP_MAX; ++i) { + MEMP_STATS_AVAIL(used, i, 0); + MEMP_STATS_AVAIL(max, i, 0); + MEMP_STATS_AVAIL(err, i, 0); + MEMP_STATS_AVAIL(avail, i, memp_num[i]); + } + +#if !MEMP_SEPARATE_POOLS + memp = (struct memp *)LWIP_MEM_ALIGN(memp_memory); +#endif /* !MEMP_SEPARATE_POOLS */ + /* for every pool: */ + for (i = 0; i < MEMP_MAX; ++i) { + memp_tab[i] = NULL; +#if MEMP_SEPARATE_POOLS + memp = (struct memp*)LWIP_MEM_ALIGN(memp_bases[i]); +#endif /* MEMP_SEPARATE_POOLS */ + /* create a linked list of memp elements */ + for (j = 0; j < memp_num[i]; ++j) { + memp->next = memp_tab[i]; + memp_tab[i] = memp; + memp = (struct memp *)(void *)((u8_t *)memp + MEMP_SIZE + memp_sizes[i] +#if MEMP_OVERFLOW_CHECK + + MEMP_SANITY_REGION_AFTER_ALIGNED +#endif + ); + } + } +#if MEMP_OVERFLOW_CHECK + memp_overflow_init(); + /* check everything a first time to see if it worked */ + memp_overflow_check_all(); +#endif /* MEMP_OVERFLOW_CHECK */ +} + +/** + * Get an element from a specific pool. + * + * @param type the pool to get an element from + * + * the debug version has two more parameters: + * @param file file name calling this function + * @param line number of line where this function is called + * + * @return a pointer to the allocated memory or a NULL pointer on error + */ +void * +#if !MEMP_OVERFLOW_CHECK +memp_malloc(memp_t type) +#else +memp_malloc_fn(memp_t type, const char* file, const int line) +#endif +{ + struct memp *memp; + SYS_ARCH_DECL_PROTECT(old_level); + + LWIP_ERROR("memp_malloc: type < MEMP_MAX", (type < MEMP_MAX), return NULL;); + + SYS_ARCH_PROTECT(old_level); +#if MEMP_OVERFLOW_CHECK >= 2 + memp_overflow_check_all(); +#endif /* MEMP_OVERFLOW_CHECK >= 2 */ + + memp = memp_tab[type]; + + if (memp != NULL) { + memp_tab[type] = memp->next; +#if MEMP_OVERFLOW_CHECK + memp->next = NULL; + memp->file = file; + memp->line = line; +#endif /* MEMP_OVERFLOW_CHECK */ + MEMP_STATS_INC_USED(used, type); + LWIP_ASSERT("memp_malloc: memp properly aligned", + ((mem_ptr_t)memp % MEM_ALIGNMENT) == 0); + memp = (struct memp*)(void *)((u8_t*)memp + MEMP_SIZE); + } else { + LWIP_DEBUGF(MEMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("memp_malloc: out of memory in pool %s\n", memp_desc[type])); + MEMP_STATS_INC(err, type); + } + + SYS_ARCH_UNPROTECT(old_level); + + return memp; +} + +/** + * Put an element back into its pool. + * + * @param type the pool where to put mem + * @param mem the memp element to free + */ +void +memp_free(memp_t type, void *mem) +{ + struct memp *memp; + SYS_ARCH_DECL_PROTECT(old_level); + + if (mem == NULL) { + return; + } + LWIP_ASSERT("memp_free: mem properly aligned", + ((mem_ptr_t)mem % MEM_ALIGNMENT) == 0); + + memp = (struct memp *)(void *)((u8_t*)mem - MEMP_SIZE); + + SYS_ARCH_PROTECT(old_level); +#if MEMP_OVERFLOW_CHECK +#if MEMP_OVERFLOW_CHECK >= 2 + memp_overflow_check_all(); +#else + memp_overflow_check_element_overflow(memp, type); + memp_overflow_check_element_underflow(memp, type); +#endif /* MEMP_OVERFLOW_CHECK >= 2 */ +#endif /* MEMP_OVERFLOW_CHECK */ + + MEMP_STATS_DEC(used, type); + + memp->next = memp_tab[type]; + memp_tab[type] = memp; + +#if MEMP_SANITY_CHECK + LWIP_ASSERT("memp sanity", memp_sanity()); +#endif /* MEMP_SANITY_CHECK */ + + SYS_ARCH_UNPROTECT(old_level); +} + +#endif /* MEMP_MEM_MALLOC */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/core/netif.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/netif.c new file mode 100644 index 0000000..36e801b --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/netif.c @@ -0,0 +1,940 @@ +/** + * @file + * lwIP network interface abstraction + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/def.h" +#include "lwip/ip_addr.h" +#include "lwip/ip6_addr.h" +#include "lwip/netif.h" +#include "lwip/tcp_impl.h" +#include "lwip/snmp.h" +#include "lwip/igmp.h" +#include "netif/etharp.h" +#include "lwip/stats.h" +#if ENABLE_LOOPBACK +#include "lwip/sys.h" +#if LWIP_NETIF_LOOPBACK_MULTITHREADING +#include "lwip/tcpip.h" +#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ +#endif /* ENABLE_LOOPBACK */ + +#if LWIP_AUTOIP +#include "lwip/autoip.h" +#endif /* LWIP_AUTOIP */ +#if LWIP_DHCP +#include "lwip/dhcp.h" +#endif /* LWIP_DHCP */ +#if LWIP_IPV6_DHCP6 +#include "lwip/dhcp6.h" +#endif /* LWIP_IPV6_DHCP6 */ +#if LWIP_IPV6_MLD +#include "lwip/mld6.h" +#endif /* LWIP_IPV6_MLD */ + +#if LWIP_NETIF_STATUS_CALLBACK +#define NETIF_STATUS_CALLBACK(n) do{ if (n->status_callback) { (n->status_callback)(n); }}while(0) +#else +#define NETIF_STATUS_CALLBACK(n) +#endif /* LWIP_NETIF_STATUS_CALLBACK */ + +#if LWIP_NETIF_LINK_CALLBACK +#define NETIF_LINK_CALLBACK(n) do{ if (n->link_callback) { (n->link_callback)(n); }}while(0) +#else +#define NETIF_LINK_CALLBACK(n) +#endif /* LWIP_NETIF_LINK_CALLBACK */ + +struct netif *netif_list; +struct netif *netif_default; + +static u8_t netif_num; + +#if LWIP_IPV6 +static err_t netif_null_output_ip6(struct netif *netif, struct pbuf *p, ip6_addr_t *ipaddr); +#endif /* LWIP_IPV6 */ + +#if LWIP_IPV6 +#define ipX_input(in, netif) (IP6H_V((const struct ip6_hdr *)in->payload) == 6) ? ip6_input(in, netif) : ip_input(in, netif) +#else +#define ipX_input(in, netif) ip_input(in, netif) +#endif + +#if LWIP_HAVE_LOOPIF +static err_t netif_loop_output_ipv4(struct netif *netif, struct pbuf *p, ip_addr_t* addr); +#if LWIP_IPV6 +static err_t netif_loop_output_ipv6(struct netif *netif, struct pbuf *p, ip6_addr_t* addr); +#endif + + +static struct netif loop_netif; + +/** + * Initialize a lwip network interface structure for a loopback interface + * + * @param netif the lwip network interface structure for this loopif + * @return ERR_OK if the loopif is initialized + * ERR_MEM if private data couldn't be allocated + */ +static err_t +netif_loopif_init(struct netif *netif) +{ + /* initialize the snmp variables and counters inside the struct netif + * ifSpeed: no assumption can be made! + */ + NETIF_INIT_SNMP(netif, snmp_ifType_softwareLoopback, 0); + + netif->name[0] = 'l'; + netif->name[1] = 'o'; + netif->output = netif_loop_output_ipv4; +#if LWIP_IPV6 + netif->output_ip6 = netif_loop_output_ipv6; +#endif + return ERR_OK; +} +#endif /* LWIP_HAVE_LOOPIF */ + +void +netif_init(void) +{ +#if LWIP_HAVE_LOOPIF + ip_addr_t loop_ipaddr, loop_netmask, loop_gw; + IP4_ADDR(&loop_gw, 127,0,0,1); + IP4_ADDR(&loop_ipaddr, 127,0,0,1); + IP4_ADDR(&loop_netmask, 255,0,0,0); + +#if NO_SYS + netif_add(&loop_netif, &loop_ipaddr, &loop_netmask, &loop_gw, NULL, netif_loopif_init, ip_input); +#else /* NO_SYS */ + netif_add(&loop_netif, &loop_ipaddr, &loop_netmask, &loop_gw, NULL, netif_loopif_init, tcpip_input); +#endif /* NO_SYS */ + +#if LWIP_IPV6 + loop_netif.ip6_addr[0].addr[0] = 0; + loop_netif.ip6_addr[0].addr[1] = 0; + loop_netif.ip6_addr[0].addr[2] = 0; + loop_netif.ip6_addr[0].addr[3] = PP_HTONL(0x00000001UL); + loop_netif.ip6_addr_state[0] = IP6_ADDR_VALID; +#endif /* LWIP_IPV6 */ + + netif_set_up(&loop_netif); + +#endif /* LWIP_HAVE_LOOPIF */ +} + +/** + * Add a network interface to the list of lwIP netifs. + * + * @param netif a pre-allocated netif structure + * @param ipaddr IP address for the new netif + * @param netmask network mask for the new netif + * @param gw default gateway IP address for the new netif + * @param state opaque data passed to the new netif + * @param init callback function that initializes the interface + * @param input callback function that is called to pass + * ingress packets up in the protocol layer stack. + * + * @return netif, or NULL if failed. + */ +struct netif * +netif_add(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask, + ip_addr_t *gw, void *state, netif_init_fn init, netif_input_fn input) +{ +#if LWIP_IPV6 + u32_t i; +#endif + + LWIP_ASSERT("No init function given", init != NULL); + + /* reset new interface configuration state */ + ip_addr_set_zero(&netif->ip_addr); + ip_addr_set_zero(&netif->netmask); + ip_addr_set_zero(&netif->gw); +#if LWIP_IPV6 + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + ip6_addr_set_zero(&netif->ip6_addr[i]); + netif_ip6_addr_set_state(netif, i, IP6_ADDR_INVALID); + } + netif->output_ip6 = netif_null_output_ip6; +#endif /* LWIP_IPV6 */ + netif->flags = 0; +#if LWIP_DHCP + /* netif not under DHCP control by default */ + netif->dhcp = NULL; +#endif /* LWIP_DHCP */ +#if LWIP_AUTOIP + /* netif not under AutoIP control by default */ + netif->autoip = NULL; +#endif /* LWIP_AUTOIP */ +#if LWIP_IPV6_AUTOCONFIG + /* IPv6 address autoconfiguration not enabled by default */ + netif->ip6_autoconfig_enabled = 0; +#endif /* LWIP_IPV6_AUTOCONFIG */ +#if LWIP_IPV6_SEND_ROUTER_SOLICIT + netif->rs_count = LWIP_ND6_MAX_MULTICAST_SOLICIT; +#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ +#if LWIP_IPV6_DHCP6 + /* netif not under DHCPv6 control by default */ + netif->dhcp6 = NULL; +#endif /* LWIP_IPV6_DHCP6 */ +#if LWIP_NETIF_STATUS_CALLBACK + netif->status_callback = NULL; +#endif /* LWIP_NETIF_STATUS_CALLBACK */ +#if LWIP_NETIF_LINK_CALLBACK + netif->link_callback = NULL; +#endif /* LWIP_NETIF_LINK_CALLBACK */ +#if LWIP_IGMP + netif->igmp_mac_filter = NULL; +#endif /* LWIP_IGMP */ +#if LWIP_IPV6 && LWIP_IPV6_MLD + netif->mld_mac_filter = NULL; +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ +#if ENABLE_LOOPBACK + netif->loop_first = NULL; + netif->loop_last = NULL; +#endif /* ENABLE_LOOPBACK */ + + /* remember netif specific state information data */ + netif->state = state; + netif->num = netif_num++; + netif->input = input; + NETIF_SET_HWADDRHINT(netif, NULL); +#if ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS + netif->loop_cnt_current = 0; +#endif /* ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS */ + + netif_set_addr(netif, ipaddr, netmask, gw); + + /* call user specified initialization function for netif */ + if (init(netif) != ERR_OK) { + return NULL; + } + + /* add this netif to the list */ + netif->next = netif_list; + netif_list = netif; + snmp_inc_iflist(); + +#if LWIP_IGMP + /* start IGMP processing */ + if (netif->flags & NETIF_FLAG_IGMP) { + igmp_start(netif); + } +#endif /* LWIP_IGMP */ + + LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP addr ", + netif->name[0], netif->name[1])); + ip_addr_debug_print(NETIF_DEBUG, ipaddr); + LWIP_DEBUGF(NETIF_DEBUG, (" netmask ")); + ip_addr_debug_print(NETIF_DEBUG, netmask); + LWIP_DEBUGF(NETIF_DEBUG, (" gw ")); + ip_addr_debug_print(NETIF_DEBUG, gw); + LWIP_DEBUGF(NETIF_DEBUG, ("\n")); + return netif; +} + +/** + * Change IP address configuration for a network interface (including netmask + * and default gateway). + * + * @param netif the network interface to change + * @param ipaddr the new IP address + * @param netmask the new netmask + * @param gw the new default gateway + */ +void +netif_set_addr(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask, + ip_addr_t *gw) +{ + netif_set_ipaddr(netif, ipaddr); + netif_set_netmask(netif, netmask); + netif_set_gw(netif, gw); +} + +/** + * Remove a network interface from the list of lwIP netifs. + * + * @param netif the network interface to remove + */ +void +netif_remove(struct netif *netif) +{ + if (netif == NULL) { + return; + } + +#if LWIP_IGMP + /* stop IGMP processing */ + if (netif->flags & NETIF_FLAG_IGMP) { + igmp_stop(netif); + } +#endif /* LWIP_IGMP */ +#if LWIP_IPV6 && LWIP_IPV6_MLD + /* stop MLD processing */ + mld6_stop(netif); +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ + if (netif_is_up(netif)) { + /* set netif down before removing (call callback function) */ + netif_set_down(netif); + } + + snmp_delete_ipaddridx_tree(netif); + + /* is it the first netif? */ + if (netif_list == netif) { + netif_list = netif->next; + } else { + /* look for netif further down the list */ + struct netif * tmpNetif; + for (tmpNetif = netif_list; tmpNetif != NULL; tmpNetif = tmpNetif->next) { + if (tmpNetif->next == netif) { + tmpNetif->next = netif->next; + break; + } + } + if (tmpNetif == NULL) + return; /* we didn't find any netif today */ + } + snmp_dec_iflist(); + /* this netif is default? */ + if (netif_default == netif) { + /* reset default netif */ + netif_set_default(NULL); + } +#if LWIP_NETIF_REMOVE_CALLBACK + if (netif->remove_callback) { + netif->remove_callback(netif); + } +#endif /* LWIP_NETIF_REMOVE_CALLBACK */ + LWIP_DEBUGF( NETIF_DEBUG, ("netif_remove: removed netif\n") ); +} + +/** + * Find a network interface by searching for its name + * + * @param name the name of the netif (like netif->name) plus concatenated number + * in ascii representation (e.g. 'en0') + */ +struct netif * +netif_find(char *name) +{ + struct netif *netif; + u8_t num; + + if (name == NULL) { + return NULL; + } + + num = name[2] - '0'; + + for(netif = netif_list; netif != NULL; netif = netif->next) { + if (num == netif->num && + name[0] == netif->name[0] && + name[1] == netif->name[1]) { + LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %c%c\n", name[0], name[1])); + return netif; + } + } + LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1])); + return NULL; +} + +/** + * Change the IP address of a network interface + * + * @param netif the network interface to change + * @param ipaddr the new IP address + * + * @note call netif_set_addr() if you also want to change netmask and + * default gateway + */ +void +netif_set_ipaddr(struct netif *netif, ip_addr_t *ipaddr) +{ + /* TODO: Handling of obsolete pcbs */ + /* See: http://mail.gnu.org/archive/html/lwip-users/2003-03/msg00118.html */ +#if LWIP_TCP + struct tcp_pcb *pcb; + struct tcp_pcb_listen *lpcb; + + /* address is actually being changed? */ + if (ipaddr && (ip_addr_cmp(ipaddr, &(netif->ip_addr))) == 0) { + /* extern struct tcp_pcb *tcp_active_pcbs; defined by tcp.h */ + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: netif address being changed\n")); + pcb = tcp_active_pcbs; + while (pcb != NULL) { + /* PCB bound to current local interface address? */ + if (ip_addr_cmp(ipX_2_ip(&pcb->local_ip), &(netif->ip_addr)) +#if LWIP_AUTOIP + /* connections to link-local addresses must persist (RFC3927 ch. 1.9) */ + && !ip_addr_islinklocal(ipX_2_ip(&pcb->local_ip)) +#endif /* LWIP_AUTOIP */ + ) { + /* this connection must be aborted */ + struct tcp_pcb *next = pcb->next; + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: aborting TCP pcb %p\n", (void *)pcb)); + tcp_abort(pcb); + pcb = next; + } else { + pcb = pcb->next; + } + } + for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { + /* PCB bound to current local interface address? */ + if ((!(ip_addr_isany(ipX_2_ip(&lpcb->local_ip)))) && + (ip_addr_cmp(ipX_2_ip(&lpcb->local_ip), &(netif->ip_addr)))) { + /* The PCB is listening to the old ipaddr and + * is set to listen to the new one instead */ + ip_addr_set(ipX_2_ip(&lpcb->local_ip), ipaddr); + } + } + } +#endif + snmp_delete_ipaddridx_tree(netif); + snmp_delete_iprteidx_tree(0,netif); + /* set new IP address to netif */ + ip_addr_set(&(netif->ip_addr), ipaddr); + snmp_insert_ipaddridx_tree(netif); + snmp_insert_iprteidx_tree(0,netif); + + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: IP address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + netif->name[0], netif->name[1], + ip4_addr1_16(&netif->ip_addr), + ip4_addr2_16(&netif->ip_addr), + ip4_addr3_16(&netif->ip_addr), + ip4_addr4_16(&netif->ip_addr))); +} + +/** + * Change the default gateway for a network interface + * + * @param netif the network interface to change + * @param gw the new default gateway + * + * @note call netif_set_addr() if you also want to change ip address and netmask + */ +void +netif_set_gw(struct netif *netif, ip_addr_t *gw) +{ + ip_addr_set(&(netif->gw), gw); + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: GW address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + netif->name[0], netif->name[1], + ip4_addr1_16(&netif->gw), + ip4_addr2_16(&netif->gw), + ip4_addr3_16(&netif->gw), + ip4_addr4_16(&netif->gw))); +} + +/** + * Change the netmask of a network interface + * + * @param netif the network interface to change + * @param netmask the new netmask + * + * @note call netif_set_addr() if you also want to change ip address and + * default gateway + */ +void +netif_set_netmask(struct netif *netif, ip_addr_t *netmask) +{ + snmp_delete_iprteidx_tree(0, netif); + /* set new netmask to netif */ + ip_addr_set(&(netif->netmask), netmask); + snmp_insert_iprteidx_tree(0, netif); + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: netmask of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + netif->name[0], netif->name[1], + ip4_addr1_16(&netif->netmask), + ip4_addr2_16(&netif->netmask), + ip4_addr3_16(&netif->netmask), + ip4_addr4_16(&netif->netmask))); +} + +/** + * Set a network interface as the default network interface + * (used to output all packets for which no specific route is found) + * + * @param netif the default network interface + */ +void +netif_set_default(struct netif *netif) +{ + if (netif == NULL) { + /* remove default route */ + snmp_delete_iprteidx_tree(1, netif); + } else { + /* install default route */ + snmp_insert_iprteidx_tree(1, netif); + } + netif_default = netif; + LWIP_DEBUGF(NETIF_DEBUG, ("netif: setting default interface %c%c\n", + netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\'')); +} + +/** + * Bring an interface up, available for processing + * traffic. + * + * @note: Enabling DHCP on a down interface will make it come + * up once configured. + * + * @see dhcp_start() + */ +void netif_set_up(struct netif *netif) +{ + if (!(netif->flags & NETIF_FLAG_UP)) { + netif->flags |= NETIF_FLAG_UP; + +#if LWIP_SNMP + snmp_get_sysuptime(&netif->ts); +#endif /* LWIP_SNMP */ + + NETIF_STATUS_CALLBACK(netif); + + if (netif->flags & NETIF_FLAG_LINK_UP) { +#if LWIP_ARP + /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */ + if (netif->flags & (NETIF_FLAG_ETHARP)) { + etharp_gratuitous(netif); + } +#endif /* LWIP_ARP */ + +#if LWIP_IGMP + /* resend IGMP memberships */ + if (netif->flags & NETIF_FLAG_IGMP) { + igmp_report_groups( netif); + } +#endif /* LWIP_IGMP */ +#if LWIP_IPV6 && LWIP_IPV6_MLD + /* send mld memberships */ + mld6_report_groups( netif); +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ + +#if LWIP_IPV6_SEND_ROUTER_SOLICIT + /* Send Router Solicitation messages. */ + netif->rs_count = LWIP_ND6_MAX_MULTICAST_SOLICIT; +#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ + + } + } +} + +/** + * Bring an interface down, disabling any traffic processing. + * + * @note: Enabling DHCP on a down interface will make it come + * up once configured. + * + * @see dhcp_start() + */ +void netif_set_down(struct netif *netif) +{ + if (netif->flags & NETIF_FLAG_UP) { + netif->flags &= ~NETIF_FLAG_UP; +#if LWIP_SNMP + snmp_get_sysuptime(&netif->ts); +#endif + +#if LWIP_ARP + if (netif->flags & NETIF_FLAG_ETHARP) { + etharp_cleanup_netif(netif); + } +#endif /* LWIP_ARP */ + NETIF_STATUS_CALLBACK(netif); + } +} + +#if LWIP_NETIF_STATUS_CALLBACK +/** + * Set callback to be called when interface is brought up/down + */ +void netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback) +{ + if (netif) { + netif->status_callback = status_callback; + } +} +#endif /* LWIP_NETIF_STATUS_CALLBACK */ + +#if LWIP_NETIF_REMOVE_CALLBACK +/** + * Set callback to be called when the interface has been removed + */ +void +netif_set_remove_callback(struct netif *netif, netif_status_callback_fn remove_callback) +{ + if (netif) { + netif->remove_callback = remove_callback; + } +} +#endif /* LWIP_NETIF_REMOVE_CALLBACK */ + +/** + * Called by a driver when its link goes up + */ +void netif_set_link_up(struct netif *netif ) +{ + if (!(netif->flags & NETIF_FLAG_LINK_UP)) { + netif->flags |= NETIF_FLAG_LINK_UP; + +#if LWIP_DHCP + if (netif->dhcp) { + dhcp_network_changed(netif); + } +#endif /* LWIP_DHCP */ + +#if LWIP_AUTOIP + if (netif->autoip) { + autoip_network_changed(netif); + } +#endif /* LWIP_AUTOIP */ + + if (netif->flags & NETIF_FLAG_UP) { +#if LWIP_ARP + /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */ + if (netif->flags & NETIF_FLAG_ETHARP) { + etharp_gratuitous(netif); + } +#endif /* LWIP_ARP */ + +#if LWIP_IGMP + /* resend IGMP memberships */ + if (netif->flags & NETIF_FLAG_IGMP) { + igmp_report_groups( netif); + } +#endif /* LWIP_IGMP */ +#if LWIP_IPV6 && LWIP_IPV6_MLD + /* send mld memberships */ + mld6_report_groups( netif); +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ + } + NETIF_LINK_CALLBACK(netif); + } +} + +/** + * Called by a driver when its link goes down + */ +void netif_set_link_down(struct netif *netif ) +{ + if (netif->flags & NETIF_FLAG_LINK_UP) { + netif->flags &= ~NETIF_FLAG_LINK_UP; + NETIF_LINK_CALLBACK(netif); + } +} + +#if LWIP_NETIF_LINK_CALLBACK +/** + * Set callback to be called when link is brought up/down + */ +void netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback) +{ + if (netif) { + netif->link_callback = link_callback; + } +} +#endif /* LWIP_NETIF_LINK_CALLBACK */ + +#if ENABLE_LOOPBACK +/** + * Send an IP packet to be received on the same netif (loopif-like). + * The pbuf is simply copied and handed back to netif->input. + * In multithreaded mode, this is done directly since netif->input must put + * the packet on a queue. + * In callback mode, the packet is put on an internal queue and is fed to + * netif->input by netif_poll(). + * + * @param netif the lwip network interface structure + * @param p the (IP) packet to 'send' + * @return ERR_OK if the packet has been sent + * ERR_MEM if the pbuf used to copy the packet couldn't be allocated + */ +err_t +netif_loop_output(struct netif *netif, struct pbuf *p) +{ + struct pbuf *r; + err_t err; + struct pbuf *last; +#if LWIP_LOOPBACK_MAX_PBUFS + u8_t clen = 0; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ + /* If we have a loopif, SNMP counters are adjusted for it, + * if not they are adjusted for 'netif'. */ +#if LWIP_SNMP +#if LWIP_HAVE_LOOPIF + struct netif *stats_if = &loop_netif; +#else /* LWIP_HAVE_LOOPIF */ + struct netif *stats_if = netif; +#endif /* LWIP_HAVE_LOOPIF */ +#endif /* LWIP_SNMP */ + SYS_ARCH_DECL_PROTECT(lev); + + /* Allocate a new pbuf */ + r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM); + if (r == NULL) { + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + snmp_inc_ifoutdiscards(stats_if); + return ERR_MEM; + } +#if LWIP_LOOPBACK_MAX_PBUFS + clen = pbuf_clen(r); + /* check for overflow or too many pbuf on queue */ + if(((netif->loop_cnt_current + clen) < netif->loop_cnt_current) || + ((netif->loop_cnt_current + clen) > LWIP_LOOPBACK_MAX_PBUFS)) { + pbuf_free(r); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + snmp_inc_ifoutdiscards(stats_if); + return ERR_MEM; + } + netif->loop_cnt_current += clen; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ + + /* Copy the whole pbuf queue p into the single pbuf r */ + if ((err = pbuf_copy(r, p)) != ERR_OK) { + pbuf_free(r); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + snmp_inc_ifoutdiscards(stats_if); + return err; + } + + /* Put the packet on a linked list which gets emptied through calling + netif_poll(). */ + + /* let last point to the last pbuf in chain r */ + for (last = r; last->next != NULL; last = last->next); + + SYS_ARCH_PROTECT(lev); + if (netif->loop_first != NULL) { + LWIP_ASSERT("if first != NULL, last must also be != NULL", netif->loop_last != NULL); + netif->loop_last->next = r; + netif->loop_last = last; + } else { + netif->loop_first = r; + netif->loop_last = last; + } + SYS_ARCH_UNPROTECT(lev); + + LINK_STATS_INC(link.xmit); + snmp_add_ifoutoctets(stats_if, p->tot_len); + snmp_inc_ifoutucastpkts(stats_if); + +#if LWIP_NETIF_LOOPBACK_MULTITHREADING + /* For multithreading environment, schedule a call to netif_poll */ + tcpip_callback_with_block((tcpip_callback_fn)netif_poll, netif, 0); +#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ + + return ERR_OK; +} + +static err_t +netif_loop_output_ipv4(struct netif *netif, struct pbuf *p, ip_addr_t* addr) +{ + LWIP_UNUSED_ARG(addr); + return netif_loop_output(netif, p); +} + +#if LWIP_IPV6 +static err_t +netif_loop_output_ipv6(struct netif *netif, struct pbuf *p, ip6_addr_t* addr) +{ + LWIP_UNUSED_ARG(addr); + return netif_loop_output(netif, p); +} +#endif + + +/** + * Call netif_poll() in the main loop of your application. This is to prevent + * reentering non-reentrant functions like tcp_input(). Packets passed to + * netif_loop_output() are put on a list that is passed to netif->input() by + * netif_poll(). + */ +void +netif_poll(struct netif *netif) +{ + struct pbuf *in; + /* If we have a loopif, SNMP counters are adjusted for it, + * if not they are adjusted for 'netif'. */ +#if LWIP_SNMP +#if LWIP_HAVE_LOOPIF + struct netif *stats_if = &loop_netif; +#else /* LWIP_HAVE_LOOPIF */ + struct netif *stats_if = netif; +#endif /* LWIP_HAVE_LOOPIF */ +#endif /* LWIP_SNMP */ + SYS_ARCH_DECL_PROTECT(lev); + + do { + /* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */ + SYS_ARCH_PROTECT(lev); + in = netif->loop_first; + if (in != NULL) { + struct pbuf *in_end = in; +#if LWIP_LOOPBACK_MAX_PBUFS + u8_t clen = 1; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ + while (in_end->len != in_end->tot_len) { + LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL); + in_end = in_end->next; +#if LWIP_LOOPBACK_MAX_PBUFS + clen++; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ + } +#if LWIP_LOOPBACK_MAX_PBUFS + /* adjust the number of pbufs on queue */ + LWIP_ASSERT("netif->loop_cnt_current underflow", + ((netif->loop_cnt_current - clen) < netif->loop_cnt_current)); + netif->loop_cnt_current -= clen; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ + + /* 'in_end' now points to the last pbuf from 'in' */ + if (in_end == netif->loop_last) { + /* this was the last pbuf in the list */ + netif->loop_first = netif->loop_last = NULL; + } else { + /* pop the pbuf off the list */ + netif->loop_first = in_end->next; + LWIP_ASSERT("should not be null since first != last!", netif->loop_first != NULL); + } + /* De-queue the pbuf from its successors on the 'loop_' list. */ + in_end->next = NULL; + } + SYS_ARCH_UNPROTECT(lev); + + if (in != NULL) { + LINK_STATS_INC(link.recv); + snmp_add_ifinoctets(stats_if, in->tot_len); + snmp_inc_ifinucastpkts(stats_if); + /* loopback packets are always IP packets! */ + if (ipX_input(in, netif) != ERR_OK) { + pbuf_free(in); + } + /* Don't reference the packet any more! */ + in = NULL; + } + /* go on while there is a packet on the list */ + } while (netif->loop_first != NULL); +} + +#if !LWIP_NETIF_LOOPBACK_MULTITHREADING +/** + * Calls netif_poll() for every netif on the netif_list. + */ +void +netif_poll_all(void) +{ + struct netif *netif = netif_list; + /* loop through netifs */ + while (netif != NULL) { + netif_poll(netif); + /* proceed to next network interface */ + netif = netif->next; + } +} +#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */ +#endif /* ENABLE_LOOPBACK */ + +#if LWIP_IPV6 +s8_t +netif_get_ip6_addr_match(struct netif * netif, ip6_addr_t * ip6addr) +{ + s8_t i; + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (ip6_addr_cmp(netif_ip6_addr(netif, i), ip6addr)) { + return i; + } + } + return -1; +} + +void +netif_create_ip6_linklocal_address(struct netif * netif, u8_t from_mac_48bit) +{ + u8_t i, addr_index; + + /* Link-local prefix. */ + netif->ip6_addr[0].addr[0] = PP_HTONL(0xfe800000ul); + netif->ip6_addr[0].addr[1] = 0; + + /* Generate interface ID. */ + if (from_mac_48bit) { + /* Assume hwaddr is a 48-bit IEEE 802 MAC. Convert to EUI-64 address. Complement Group bit. */ + netif->ip6_addr[0].addr[2] = htonl((((u32_t)(netif->hwaddr[0] ^ 0x02)) << 24) | + ((u32_t)(netif->hwaddr[1]) << 16) | + ((u32_t)(netif->hwaddr[2]) << 8) | + (0xff)); + netif->ip6_addr[0].addr[3] = htonl((0xfeul << 24) | + ((u32_t)(netif->hwaddr[3]) << 16) | + ((u32_t)(netif->hwaddr[4]) << 8) | + (netif->hwaddr[5])); + } + else { + /* Use hwaddr directly as interface ID. */ + netif->ip6_addr[0].addr[2] = 0; + netif->ip6_addr[0].addr[3] = 0; + + addr_index = 3; + for (i = 0; i < 8; i++) { + if (i == 4) { + addr_index--; + } + netif->ip6_addr[0].addr[addr_index] |= ((u32_t)(netif->hwaddr[netif->hwaddr_len - i - 1])) << (8 * (i & 0x03)); + } + } + + /* Set address state. */ +#if LWIP_IPV6_DUP_DETECT_ATTEMPTS + /* Will perform duplicate address detection (DAD). */ + netif->ip6_addr_state[0] = IP6_ADDR_TENTATIVE; +#else + /* Consider address valid. */ + netif->ip6_addr_state[0] = IP6_ADDR_PREFERRED; +#endif /* LWIP_IPV6_AUTOCONFIG */ +} + +static err_t +netif_null_output_ip6(struct netif *netif, struct pbuf *p, ip6_addr_t *ipaddr) +{ + (void)netif; + (void)p; + (void)ipaddr; + + return ERR_IF; +} +#endif /* LWIP_IPV6 */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/core/pbuf.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/pbuf.c new file mode 100644 index 0000000..1a91d75 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/pbuf.c @@ -0,0 +1,1329 @@ +/** + * @file + * Packet buffer management + * + * Packets are built from the pbuf data structure. It supports dynamic + * memory allocation for packet contents or can reference externally + * managed packet contents both in RAM and ROM. Quick allocation for + * incoming packets is provided through pools with fixed sized pbufs. + * + * A packet may span over multiple pbufs, chained as a singly linked + * list. This is called a "pbuf chain". + * + * Multiple packets may be queued, also using this singly linked list. + * This is called a "packet queue". + * + * So, a packet queue consists of one or more pbuf chains, each of + * which consist of one or more pbufs. CURRENTLY, PACKET QUEUES ARE + * NOT SUPPORTED!!! Use helper structs to queue multiple packets. + * + * The differences between a pbuf chain and a packet queue are very + * precise but subtle. + * + * The last pbuf of a packet has a ->tot_len field that equals the + * ->len field. It can be found by traversing the list. If the last + * pbuf of a packet has a ->next field other than NULL, more packets + * are on the queue. + * + * Therefore, looping through a pbuf of a single packet, has an + * loop end condition (tot_len == p->len), NOT (next == NULL). + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/stats.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/pbuf.h" +#include "lwip/sys.h" +#include "arch/perf.h" +#if LWIP_TCP && TCP_QUEUE_OOSEQ +#include "lwip/tcp_impl.h" +#endif +#if LWIP_CHECKSUM_ON_COPY +#include "lwip/inet_chksum.h" +#endif + +#include + +#define SIZEOF_STRUCT_PBUF LWIP_MEM_ALIGN_SIZE(sizeof(struct pbuf)) +/* Since the pool is created in memp, PBUF_POOL_BUFSIZE will be automatically + aligned there. Therefore, PBUF_POOL_BUFSIZE_ALIGNED can be used here. */ +#define PBUF_POOL_BUFSIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE) + +#if !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ +#define PBUF_POOL_IS_EMPTY() +#else /* !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ */ + +#if !NO_SYS +#ifndef PBUF_POOL_FREE_OOSEQ_QUEUE_CALL +#include "lwip/tcpip.h" +#define PBUF_POOL_FREE_OOSEQ_QUEUE_CALL() do { \ + if(tcpip_callback_with_block(pbuf_free_ooseq_callback, NULL, 0) != ERR_OK) { \ + SYS_ARCH_PROTECT(old_level); \ + pbuf_free_ooseq_pending = 0; \ + SYS_ARCH_UNPROTECT(old_level); \ + } } while(0) +#endif /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */ +#endif /* !NO_SYS */ + +volatile u8_t pbuf_free_ooseq_pending; +#define PBUF_POOL_IS_EMPTY() pbuf_pool_is_empty() + +/** + * Attempt to reclaim some memory from queued out-of-sequence TCP segments + * if we run out of pool pbufs. It's better to give priority to new packets + * if we're running out. + * + * This must be done in the correct thread context therefore this function + * can only be used with NO_SYS=0 and through tcpip_callback. + */ +#if !NO_SYS +static +#endif /* !NO_SYS */ +void +pbuf_free_ooseq(void) +{ + struct tcp_pcb* pcb; + SYS_ARCH_DECL_PROTECT(old_level); + + SYS_ARCH_PROTECT(old_level); + pbuf_free_ooseq_pending = 0; + SYS_ARCH_UNPROTECT(old_level); + + for (pcb = tcp_active_pcbs; NULL != pcb; pcb = pcb->next) { + if (NULL != pcb->ooseq) { + /** Free the ooseq pbufs of one PCB only */ + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free_ooseq: freeing out-of-sequence pbufs\n")); + tcp_segs_free(pcb->ooseq); + pcb->ooseq = NULL; + return; + } + } +} + +#if !NO_SYS +/** + * Just a callback function for tcpip_timeout() that calls pbuf_free_ooseq(). + */ +static void +pbuf_free_ooseq_callback(void *arg) +{ + LWIP_UNUSED_ARG(arg); + pbuf_free_ooseq(); +} +#endif /* !NO_SYS */ + +/** Queue a call to pbuf_free_ooseq if not already queued. */ +static void +pbuf_pool_is_empty(void) +{ +#ifndef PBUF_POOL_FREE_OOSEQ_QUEUE_CALL + SYS_ARCH_DECL_PROTECT(old_level); + SYS_ARCH_PROTECT(old_level); + pbuf_free_ooseq_pending = 1; + SYS_ARCH_UNPROTECT(old_level); +#else /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */ + u8_t queued; + SYS_ARCH_DECL_PROTECT(old_level); + SYS_ARCH_PROTECT(old_level); + queued = pbuf_free_ooseq_pending; + pbuf_free_ooseq_pending = 1; + SYS_ARCH_UNPROTECT(old_level); + + if(!queued) { + /* queue a call to pbuf_free_ooseq if not already queued */ + PBUF_POOL_FREE_OOSEQ_QUEUE_CALL(); + } +#endif /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */ +} +#endif /* !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ */ + +/** + * Allocates a pbuf of the given type (possibly a chain for PBUF_POOL type). + * + * The actual memory allocated for the pbuf is determined by the + * layer at which the pbuf is allocated and the requested size + * (from the size parameter). + * + * @param layer flag to define header size + * @param length size of the pbuf's payload + * @param type this parameter decides how and where the pbuf + * should be allocated as follows: + * + * - PBUF_RAM: buffer memory for pbuf is allocated as one large + * chunk. This includes protocol headers as well. + * - PBUF_ROM: no buffer memory is allocated for the pbuf, even for + * protocol headers. Additional headers must be prepended + * by allocating another pbuf and chain in to the front of + * the ROM pbuf. It is assumed that the memory used is really + * similar to ROM in that it is immutable and will not be + * changed. Memory which is dynamic should generally not + * be attached to PBUF_ROM pbufs. Use PBUF_REF instead. + * - PBUF_REF: no buffer memory is allocated for the pbuf, even for + * protocol headers. It is assumed that the pbuf is only + * being used in a single thread. If the pbuf gets queued, + * then pbuf_take should be called to copy the buffer. + * - PBUF_POOL: the pbuf is allocated as a pbuf chain, with pbufs from + * the pbuf pool that is allocated during pbuf_init(). + * + * @return the allocated pbuf. If multiple pbufs where allocated, this + * is the first pbuf of a pbuf chain. + */ +struct pbuf * +pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type) +{ + struct pbuf *p, *q, *r; + u16_t offset; + s32_t rem_len; /* remaining length */ + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F")\n", length)); + + /* determine header offset */ + switch (layer) { + case PBUF_TRANSPORT: + /* add room for transport (often TCP) layer header */ + offset = PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN; + break; + case PBUF_IP: + /* add room for IP layer header */ + offset = PBUF_LINK_HLEN + PBUF_IP_HLEN; + break; + case PBUF_LINK: + /* add room for link layer header */ + offset = PBUF_LINK_HLEN; + break; + case PBUF_RAW: + offset = 0; + break; + default: + LWIP_ASSERT("pbuf_alloc: bad pbuf layer", 0); + return NULL; + } + + switch (type) { + case PBUF_POOL: + /* allocate head of pbuf chain into p */ + p = (struct pbuf *)memp_malloc(MEMP_PBUF_POOL); + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc: allocated pbuf %p\n", (void *)p)); + if (p == NULL) { + PBUF_POOL_IS_EMPTY(); + return NULL; + } + p->type = type; + p->next = NULL; + + /* make the payload pointer point 'offset' bytes into pbuf data memory */ + p->payload = LWIP_MEM_ALIGN((void *)((u8_t *)p + (SIZEOF_STRUCT_PBUF + offset))); + LWIP_ASSERT("pbuf_alloc: pbuf p->payload properly aligned", + ((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0); + /* the total length of the pbuf chain is the requested size */ + p->tot_len = length; + /* set the length of the first pbuf in the chain */ + p->len = LWIP_MIN(length, PBUF_POOL_BUFSIZE_ALIGNED - LWIP_MEM_ALIGN_SIZE(offset)); + LWIP_ASSERT("check p->payload + p->len does not overflow pbuf", + ((u8_t*)p->payload + p->len <= + (u8_t*)p + SIZEOF_STRUCT_PBUF + PBUF_POOL_BUFSIZE_ALIGNED)); + LWIP_ASSERT("PBUF_POOL_BUFSIZE must be bigger than MEM_ALIGNMENT", + (PBUF_POOL_BUFSIZE_ALIGNED - LWIP_MEM_ALIGN_SIZE(offset)) > 0 ); + /* set reference count (needed here in case we fail) */ + p->ref = 1; + + /* now allocate the tail of the pbuf chain */ + + /* remember first pbuf for linkage in next iteration */ + r = p; + /* remaining length to be allocated */ + rem_len = length - p->len; + /* any remaining pbufs to be allocated? */ + while (rem_len > 0) { + q = (struct pbuf *)memp_malloc(MEMP_PBUF_POOL); + if (q == NULL) { + PBUF_POOL_IS_EMPTY(); + /* free chain so far allocated */ + pbuf_free(p); + /* bail out unsuccessfully */ + return NULL; + } + q->type = type; + q->flags = 0; + q->next = NULL; + /* make previous pbuf point to this pbuf */ + r->next = q; + /* set total length of this pbuf and next in chain */ + LWIP_ASSERT("rem_len < max_u16_t", rem_len < 0xffff); + q->tot_len = (u16_t)rem_len; + /* this pbuf length is pool size, unless smaller sized tail */ + q->len = LWIP_MIN((u16_t)rem_len, PBUF_POOL_BUFSIZE_ALIGNED); + q->payload = (void *)((u8_t *)q + SIZEOF_STRUCT_PBUF); + LWIP_ASSERT("pbuf_alloc: pbuf q->payload properly aligned", + ((mem_ptr_t)q->payload % MEM_ALIGNMENT) == 0); + LWIP_ASSERT("check p->payload + p->len does not overflow pbuf", + ((u8_t*)p->payload + p->len <= + (u8_t*)p + SIZEOF_STRUCT_PBUF + PBUF_POOL_BUFSIZE_ALIGNED)); + q->ref = 1; + /* calculate remaining length to be allocated */ + rem_len -= q->len; + /* remember this pbuf for linkage in next iteration */ + r = q; + } + /* end of chain */ + /*r->next = NULL;*/ + + break; + case PBUF_RAM: + /* If pbuf is to be allocated in RAM, allocate memory for it. */ + p = (struct pbuf*)mem_malloc(LWIP_MEM_ALIGN_SIZE(SIZEOF_STRUCT_PBUF + offset) + LWIP_MEM_ALIGN_SIZE(length)); + if (p == NULL) { + return NULL; + } + /* Set up internal structure of the pbuf. */ + p->payload = LWIP_MEM_ALIGN((void *)((u8_t *)p + SIZEOF_STRUCT_PBUF + offset)); + p->len = p->tot_len = length; + p->next = NULL; + p->type = type; + + LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned", + ((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0); + break; + /* pbuf references existing (non-volatile static constant) ROM payload? */ + case PBUF_ROM: + /* pbuf references existing (externally allocated) RAM payload? */ + case PBUF_REF: + /* only allocate memory for the pbuf structure */ + p = (struct pbuf *)memp_malloc(MEMP_PBUF); + if (p == NULL) { + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("pbuf_alloc: Could not allocate MEMP_PBUF for PBUF_%s.\n", + (type == PBUF_ROM) ? "ROM" : "REF")); + return NULL; + } + /* caller must set this field properly, afterwards */ + p->payload = NULL; + p->len = p->tot_len = length; + p->next = NULL; + p->type = type; + break; + default: + LWIP_ASSERT("pbuf_alloc: erroneous type", 0); + return NULL; + } + /* set reference count */ + p->ref = 1; + /* set flags */ + p->flags = 0; + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F") == %p\n", length, (void *)p)); + return p; +} + +#if LWIP_SUPPORT_CUSTOM_PBUF +/** Initialize a custom pbuf (already allocated). + * + * @param layer flag to define header size + * @param length size of the pbuf's payload + * @param type type of the pbuf (only used to treat the pbuf accordingly, as + * this function allocates no memory) + * @param p pointer to the custom pbuf to initialize (already allocated) + * @param payload_mem pointer to the buffer that is used for payload and headers, + * must be at least big enough to hold 'length' plus the header size, + * may be NULL if set later. + * ATTENTION: The caller is responsible for correct alignment of this buffer!! + * @param payload_mem_len the size of the 'payload_mem' buffer, must be at least + * big enough to hold 'length' plus the header size + */ +struct pbuf* +pbuf_alloced_custom(pbuf_layer l, u16_t length, pbuf_type type, struct pbuf_custom *p, + void *payload_mem, u16_t payload_mem_len) +{ + u16_t offset; + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloced_custom(length=%"U16_F")\n", length)); + + /* determine header offset */ + switch (l) { + case PBUF_TRANSPORT: + /* add room for transport (often TCP) layer header */ + offset = PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN; + break; + case PBUF_IP: + /* add room for IP layer header */ + offset = PBUF_LINK_HLEN + PBUF_IP_HLEN; + break; + case PBUF_LINK: + /* add room for link layer header */ + offset = PBUF_LINK_HLEN; + break; + case PBUF_RAW: + offset = 0; + break; + default: + LWIP_ASSERT("pbuf_alloced_custom: bad pbuf layer", 0); + return NULL; + } + + if (LWIP_MEM_ALIGN_SIZE(offset) + length > payload_mem_len) { + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_WARNING, ("pbuf_alloced_custom(length=%"U16_F") buffer too short\n", length)); + return NULL; + } + + p->pbuf.next = NULL; + if (payload_mem != NULL) { + p->pbuf.payload = (u8_t *)payload_mem + LWIP_MEM_ALIGN_SIZE(offset); + } else { + p->pbuf.payload = NULL; + } + p->pbuf.flags = PBUF_FLAG_IS_CUSTOM; + p->pbuf.len = p->pbuf.tot_len = length; + p->pbuf.type = type; + p->pbuf.ref = 1; + return &p->pbuf; +} +#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ + +/** + * Shrink a pbuf chain to a desired length. + * + * @param p pbuf to shrink. + * @param new_len desired new length of pbuf chain + * + * Depending on the desired length, the first few pbufs in a chain might + * be skipped and left unchanged. The new last pbuf in the chain will be + * resized, and any remaining pbufs will be freed. + * + * @note If the pbuf is ROM/REF, only the ->tot_len and ->len fields are adjusted. + * @note May not be called on a packet queue. + * + * @note Despite its name, pbuf_realloc cannot grow the size of a pbuf (chain). + */ +void +pbuf_realloc(struct pbuf *p, u16_t new_len) +{ + struct pbuf *q; + u16_t rem_len; /* remaining length */ + s32_t grow; + + LWIP_ASSERT("pbuf_realloc: p != NULL", p != NULL); + LWIP_ASSERT("pbuf_realloc: sane p->type", p->type == PBUF_POOL || + p->type == PBUF_ROM || + p->type == PBUF_RAM || + p->type == PBUF_REF); + + /* desired length larger than current length? */ + if (new_len >= p->tot_len) { + /* enlarging not yet supported */ + return; + } + + /* the pbuf chain grows by (new_len - p->tot_len) bytes + * (which may be negative in case of shrinking) */ + grow = new_len - p->tot_len; + + /* first, step over any pbufs that should remain in the chain */ + rem_len = new_len; + q = p; + /* should this pbuf be kept? */ + while (rem_len > q->len) { + /* decrease remaining length by pbuf length */ + rem_len -= q->len; + /* decrease total length indicator */ + LWIP_ASSERT("grow < max_u16_t", grow < 0xffff); + q->tot_len += (u16_t)grow; + /* proceed to next pbuf in chain */ + q = q->next; + LWIP_ASSERT("pbuf_realloc: q != NULL", q != NULL); + } + /* we have now reached the new last pbuf (in q) */ + /* rem_len == desired length for pbuf q */ + + /* shrink allocated memory for PBUF_RAM */ + /* (other types merely adjust their length fields */ + if ((q->type == PBUF_RAM) && (rem_len != q->len)) { + /* reallocate and adjust the length of the pbuf that will be split */ + q = (struct pbuf *)mem_trim(q, (u16_t)((u8_t *)q->payload - (u8_t *)q) + rem_len); + LWIP_ASSERT("mem_trim returned q == NULL", q != NULL); + } + /* adjust length fields for new last pbuf */ + q->len = rem_len; + q->tot_len = q->len; + + /* any remaining pbufs in chain? */ + if (q->next != NULL) { + /* free remaining pbufs in chain */ + pbuf_free(q->next); + } + /* q is last packet in chain */ + q->next = NULL; + +} + +/** + * Adjusts the payload pointer to hide or reveal headers in the payload. + * @see pbuf_header. + * + * @param p pbuf to change the header size. + * @param header_size_increment Number of bytes to increment header size. + * @param force Allow 'header_size_increment > 0' for PBUF_REF/PBUF_ROM types + * + * @return non-zero on failure, zero on success. + * + */ +static u8_t +pbuf_header_impl(struct pbuf *p, s16_t header_size_increment, u8_t force) +{ + u16_t type; + void *payload; + u16_t increment_magnitude; + + LWIP_ASSERT("p != NULL", p != NULL); + if ((header_size_increment == 0) || (p == NULL)) { + return 0; + } + + if (header_size_increment < 0){ + increment_magnitude = -header_size_increment; + /* Check that we aren't going to move off the end of the pbuf */ + LWIP_ERROR("increment_magnitude <= p->len", (increment_magnitude <= p->len), return 1;); + } else { + increment_magnitude = header_size_increment; +#if 0 + /* Can't assert these as some callers speculatively call + pbuf_header() to see if it's OK. Will return 1 below instead. */ + /* Check that we've got the correct type of pbuf to work with */ + LWIP_ASSERT("p->type == PBUF_RAM || p->type == PBUF_POOL", + p->type == PBUF_RAM || p->type == PBUF_POOL); + /* Check that we aren't going to move off the beginning of the pbuf */ + LWIP_ASSERT("p->payload - increment_magnitude >= p + SIZEOF_STRUCT_PBUF", + (u8_t *)p->payload - increment_magnitude >= (u8_t *)p + SIZEOF_STRUCT_PBUF); +#endif + } + + type = p->type; + /* remember current payload pointer */ + payload = p->payload; + + /* pbuf types containing payloads? */ + if (type == PBUF_RAM || type == PBUF_POOL) { + /* set new payload pointer */ + p->payload = (u8_t *)p->payload - header_size_increment; + /* boundary check fails? */ + if ((u8_t *)p->payload < (u8_t *)p + SIZEOF_STRUCT_PBUF) { + LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("pbuf_header: failed as %p < %p (not enough space for new header size)\n", + (void *)p->payload, (void *)(p + 1))); + /* restore old payload pointer */ + p->payload = payload; + /* bail out unsuccessfully */ + return 1; + } + /* pbuf types referring to external payloads? */ + } else if (type == PBUF_REF || type == PBUF_ROM) { + /* hide a header in the payload? */ + if ((header_size_increment < 0) && (increment_magnitude <= p->len)) { + /* increase payload pointer */ + p->payload = (u8_t *)p->payload - header_size_increment; + } else if ((header_size_increment > 0) && force) { + p->payload = (u8_t *)p->payload - header_size_increment; + } else { + /* cannot expand payload to front (yet!) + * bail out unsuccessfully */ + return 1; + } + } else { + /* Unknown type */ + LWIP_ASSERT("bad pbuf type", 0); + return 1; + } + /* modify pbuf length fields */ + p->len += header_size_increment; + p->tot_len += header_size_increment; + + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_header: old %p new %p (%"S16_F")\n", + (void *)payload, (void *)p->payload, header_size_increment)); + + return 0; +} + +/** + * Adjusts the payload pointer to hide or reveal headers in the payload. + * + * Adjusts the ->payload pointer so that space for a header + * (dis)appears in the pbuf payload. + * + * The ->payload, ->tot_len and ->len fields are adjusted. + * + * @param p pbuf to change the header size. + * @param header_size_increment Number of bytes to increment header size which + * increases the size of the pbuf. New space is on the front. + * (Using a negative value decreases the header size.) + * If hdr_size_inc is 0, this function does nothing and returns successful. + * + * PBUF_ROM and PBUF_REF type buffers cannot have their sizes increased, so + * the call will fail. A check is made that the increase in header size does + * not move the payload pointer in front of the start of the buffer. + * @return non-zero on failure, zero on success. + * + */ +u8_t +pbuf_header(struct pbuf *p, s16_t header_size_increment) +{ + return pbuf_header_impl(p, header_size_increment, 0); +} + +/** + * Same as pbuf_header but does not check if 'header_size > 0' is allowed. + * This is used internally only, to allow PBUF_REF for RX. + */ +u8_t +pbuf_header_force(struct pbuf *p, s16_t header_size_increment) +{ + return pbuf_header_impl(p, header_size_increment, 1); +} + +/** + * Dereference a pbuf chain or queue and deallocate any no-longer-used + * pbufs at the head of this chain or queue. + * + * Decrements the pbuf reference count. If it reaches zero, the pbuf is + * deallocated. + * + * For a pbuf chain, this is repeated for each pbuf in the chain, + * up to the first pbuf which has a non-zero reference count after + * decrementing. So, when all reference counts are one, the whole + * chain is free'd. + * + * @param p The pbuf (chain) to be dereferenced. + * + * @return the number of pbufs that were de-allocated + * from the head of the chain. + * + * @note MUST NOT be called on a packet queue (Not verified to work yet). + * @note the reference counter of a pbuf equals the number of pointers + * that refer to the pbuf (or into the pbuf). + * + * @internal examples: + * + * Assuming existing chains a->b->c with the following reference + * counts, calling pbuf_free(a) results in: + * + * 1->2->3 becomes ...1->3 + * 3->3->3 becomes 2->3->3 + * 1->1->2 becomes ......1 + * 2->1->1 becomes 1->1->1 + * 1->1->1 becomes ....... + * + */ +u8_t +pbuf_free(struct pbuf *p) +{ + u16_t type; + struct pbuf *q; + u8_t count; + + if (p == NULL) { + LWIP_ASSERT("p != NULL", p != NULL); + /* if assertions are disabled, proceed with debug output */ + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("pbuf_free(p == NULL) was called.\n")); + return 0; + } + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free(%p)\n", (void *)p)); + + PERF_START; + + LWIP_ASSERT("pbuf_free: sane type", + p->type == PBUF_RAM || p->type == PBUF_ROM || + p->type == PBUF_REF || p->type == PBUF_POOL); + + count = 0; + /* de-allocate all consecutive pbufs from the head of the chain that + * obtain a zero reference count after decrementing*/ + while (p != NULL) { + u16_t ref; + SYS_ARCH_DECL_PROTECT(old_level); + /* Since decrementing ref cannot be guaranteed to be a single machine operation + * we must protect it. We put the new ref into a local variable to prevent + * further protection. */ + SYS_ARCH_PROTECT(old_level); + /* all pbufs in a chain are referenced at least once */ + LWIP_ASSERT("pbuf_free: p->ref > 0", p->ref > 0); + /* decrease reference count (number of pointers to pbuf) */ + ref = --(p->ref); + SYS_ARCH_UNPROTECT(old_level); + /* this pbuf is no longer referenced to? */ + if (ref == 0) { + /* remember next pbuf in chain for next iteration */ + q = p->next; + LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: deallocating %p\n", (void *)p)); + type = p->type; +#if LWIP_SUPPORT_CUSTOM_PBUF + /* is this a custom pbuf? */ + if ((p->flags & PBUF_FLAG_IS_CUSTOM) != 0) { + struct pbuf_custom *pc = (struct pbuf_custom*)p; + LWIP_ASSERT("pc->custom_free_function != NULL", pc->custom_free_function != NULL); + pc->custom_free_function(p); + } else +#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ + { + /* is this a pbuf from the pool? */ + if (type == PBUF_POOL) { + memp_free(MEMP_PBUF_POOL, p); + /* is this a ROM or RAM referencing pbuf? */ + } else if (type == PBUF_ROM || type == PBUF_REF) { + memp_free(MEMP_PBUF, p); + /* type == PBUF_RAM */ + } else { + mem_free(p); + } + } + count++; + /* proceed to next pbuf */ + p = q; + /* p->ref > 0, this pbuf is still referenced to */ + /* (and so the remaining pbufs in chain as well) */ + } else { + LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: %p has ref %"U16_F", ending here.\n", (void *)p, ref)); + /* stop walking through the chain */ + p = NULL; + } + } + PERF_STOP("pbuf_free"); + /* return number of de-allocated pbufs */ + return count; +} + +/** + * Count number of pbufs in a chain + * + * @param p first pbuf of chain + * @return the number of pbufs in a chain + */ + +u8_t +pbuf_clen(struct pbuf *p) +{ + u8_t len; + + len = 0; + while (p != NULL) { + ++len; + p = p->next; + } + return len; +} + +/** + * Increment the reference count of the pbuf. + * + * @param p pbuf to increase reference counter of + * + */ +void +pbuf_ref(struct pbuf *p) +{ + SYS_ARCH_DECL_PROTECT(old_level); + /* pbuf given? */ + if (p != NULL) { + SYS_ARCH_PROTECT(old_level); + ++(p->ref); + SYS_ARCH_UNPROTECT(old_level); + } +} + +/** + * Concatenate two pbufs (each may be a pbuf chain) and take over + * the caller's reference of the tail pbuf. + * + * @note The caller MAY NOT reference the tail pbuf afterwards. + * Use pbuf_chain() for that purpose. + * + * @see pbuf_chain() + */ + +void +pbuf_cat(struct pbuf *h, struct pbuf *t) +{ + struct pbuf *p; + + LWIP_ERROR("(h != NULL) && (t != NULL) (programmer violates API)", + ((h != NULL) && (t != NULL)), return;); + + /* proceed to last pbuf of chain */ + for (p = h; p->next != NULL; p = p->next) { + /* add total length of second chain to all totals of first chain */ + p->tot_len += t->tot_len; + } + /* { p is last pbuf of first h chain, p->next == NULL } */ + LWIP_ASSERT("p->tot_len == p->len (of last pbuf in chain)", p->tot_len == p->len); + LWIP_ASSERT("p->next == NULL", p->next == NULL); + /* add total length of second chain to last pbuf total of first chain */ + p->tot_len += t->tot_len; + /* chain last pbuf of head (p) with first of tail (t) */ + p->next = t; + /* p->next now references t, but the caller will drop its reference to t, + * so netto there is no change to the reference count of t. + */ +} + +/** + * Chain two pbufs (or pbuf chains) together. + * + * The caller MUST call pbuf_free(t) once it has stopped + * using it. Use pbuf_cat() instead if you no longer use t. + * + * @param h head pbuf (chain) + * @param t tail pbuf (chain) + * @note The pbufs MUST belong to the same packet. + * @note MAY NOT be called on a packet queue. + * + * The ->tot_len fields of all pbufs of the head chain are adjusted. + * The ->next field of the last pbuf of the head chain is adjusted. + * The ->ref field of the first pbuf of the tail chain is adjusted. + * + */ +void +pbuf_chain(struct pbuf *h, struct pbuf *t) +{ + pbuf_cat(h, t); + /* t is now referenced by h */ + pbuf_ref(t); + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_chain: %p references %p\n", (void *)h, (void *)t)); +} + +/** + * Dechains the first pbuf from its succeeding pbufs in the chain. + * + * Makes p->tot_len field equal to p->len. + * @param p pbuf to dechain + * @return remainder of the pbuf chain, or NULL if it was de-allocated. + * @note May not be called on a packet queue. + */ +struct pbuf * +pbuf_dechain(struct pbuf *p) +{ + struct pbuf *q; + u8_t tail_gone = 1; + /* tail */ + q = p->next; + /* pbuf has successor in chain? */ + if (q != NULL) { + /* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */ + LWIP_ASSERT("p->tot_len == p->len + q->tot_len", q->tot_len == p->tot_len - p->len); + /* enforce invariant if assertion is disabled */ + q->tot_len = p->tot_len - p->len; + /* decouple pbuf from remainder */ + p->next = NULL; + /* total length of pbuf p is its own length only */ + p->tot_len = p->len; + /* q is no longer referenced by p, free it */ + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_dechain: unreferencing %p\n", (void *)q)); + tail_gone = pbuf_free(q); + if (tail_gone > 0) { + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, + ("pbuf_dechain: deallocated %p (as it is no longer referenced)\n", (void *)q)); + } + /* return remaining tail or NULL if deallocated */ + } + /* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */ + LWIP_ASSERT("p->tot_len == p->len", p->tot_len == p->len); + return ((tail_gone > 0) ? NULL : q); +} + +/** + * + * Create PBUF_RAM copies of pbufs. + * + * Used to queue packets on behalf of the lwIP stack, such as + * ARP based queueing. + * + * @note You MUST explicitly use p = pbuf_take(p); + * + * @note Only one packet is copied, no packet queue! + * + * @param p_to pbuf destination of the copy + * @param p_from pbuf source of the copy + * + * @return ERR_OK if pbuf was copied + * ERR_ARG if one of the pbufs is NULL or p_to is not big + * enough to hold p_from + */ +err_t +pbuf_copy(struct pbuf *p_to, struct pbuf *p_from) +{ + u16_t offset_to=0, offset_from=0, len; + + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy(%p, %p)\n", + (void*)p_to, (void*)p_from)); + + /* is the target big enough to hold the source? */ + LWIP_ERROR("pbuf_copy: target not big enough to hold source", ((p_to != NULL) && + (p_from != NULL) && (p_to->tot_len >= p_from->tot_len)), return ERR_ARG;); + + /* iterate through pbuf chain */ + do + { + /* copy one part of the original chain */ + if ((p_to->len - offset_to) >= (p_from->len - offset_from)) { + /* complete current p_from fits into current p_to */ + len = p_from->len - offset_from; + } else { + /* current p_from does not fit into current p_to */ + len = p_to->len - offset_to; + } + MEMCPY((u8_t*)p_to->payload + offset_to, (u8_t*)p_from->payload + offset_from, len); + offset_to += len; + offset_from += len; + LWIP_ASSERT("offset_to <= p_to->len", offset_to <= p_to->len); + LWIP_ASSERT("offset_from <= p_from->len", offset_from <= p_from->len); + if (offset_from >= p_from->len) { + /* on to next p_from (if any) */ + offset_from = 0; + p_from = p_from->next; + } + if (offset_to == p_to->len) { + /* on to next p_to (if any) */ + offset_to = 0; + p_to = p_to->next; + LWIP_ERROR("p_to != NULL", (p_to != NULL) || (p_from == NULL) , return ERR_ARG;); + } + + if((p_from != NULL) && (p_from->len == p_from->tot_len)) { + /* don't copy more than one packet! */ + LWIP_ERROR("pbuf_copy() does not allow packet queues!", + (p_from->next == NULL), return ERR_VAL;); + } + if((p_to != NULL) && (p_to->len == p_to->tot_len)) { + /* don't copy more than one packet! */ + LWIP_ERROR("pbuf_copy() does not allow packet queues!", + (p_to->next == NULL), return ERR_VAL;); + } + } while (p_from); + LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy: end of chain reached.\n")); + return ERR_OK; +} + +/** + * Copy (part of) the contents of a packet buffer + * to an application supplied buffer. + * + * @param buf the pbuf from which to copy data + * @param dataptr the application supplied buffer + * @param len length of data to copy (dataptr must be big enough). No more + * than buf->tot_len will be copied, irrespective of len + * @param offset offset into the packet buffer from where to begin copying len bytes + * @return the number of bytes copied, or 0 on failure + */ +u16_t +pbuf_copy_partial(struct pbuf *buf, void *dataptr, u16_t len, u16_t offset) +{ + struct pbuf *p; + u16_t left; + u16_t buf_copy_len; + u16_t copied_total = 0; + + LWIP_ERROR("pbuf_copy_partial: invalid buf", (buf != NULL), return 0;); + LWIP_ERROR("pbuf_copy_partial: invalid dataptr", (dataptr != NULL), return 0;); + + left = 0; + + if((buf == NULL) || (dataptr == NULL)) { + return 0; + } + + /* Note some systems use byte copy if dataptr or one of the pbuf payload pointers are unaligned. */ + for(p = buf; len != 0 && p != NULL; p = p->next) { + if ((offset != 0) && (offset >= p->len)) { + /* don't copy from this buffer -> on to the next */ + offset -= p->len; + } else { + /* copy from this buffer. maybe only partially. */ + buf_copy_len = p->len - offset; + if (buf_copy_len > len) + buf_copy_len = len; + /* copy the necessary parts of the buffer */ + MEMCPY(&((char*)dataptr)[left], &((char*)p->payload)[offset], buf_copy_len); + copied_total += buf_copy_len; + left += buf_copy_len; + len -= buf_copy_len; + offset = 0; + } + } + return copied_total; +} + +#if LWIP_TCP && TCP_QUEUE_OOSEQ && LWIP_WND_SCALE +/** + * This method modifies a 'pbuf chain', so that its total length is + * smaller than 64K. The remainder of the original pbuf chain is stored + * in *rest. + * This function never creates new pbufs, but splits an existing chain + * in two parts. The tot_len of the modified packet queue will likely be + * smaller than 64K. + * 'packet queues' are not supported by this function. + * + * @param p the pbuf queue to be split + * @param rest pointer to store the remainder (after the first 64K) + */ +void pbuf_split_64k(struct pbuf *p, struct pbuf **rest) +{ + *rest = NULL; + if ((p != NULL) && (p->next != NULL)) { + u16_t tot_len_front = p->len; + struct pbuf *i = p; + struct pbuf *r = p->next; + + /* continue until the total length (summed up as u16_t) overflows */ + while ((r != NULL) && ((u16_t)(tot_len_front + r->len) > tot_len_front)) { + tot_len_front += r->len; + i = r; + r = r->next; + } + /* i now points to last packet of the first segment. Set next + pointer to NULL */ + i->next = NULL; + + if (r != NULL) { + /* Update the tot_len field in the first part */ + for (i = p; i != NULL; i = i->next) { + i->tot_len -= r->tot_len; + LWIP_ASSERT("tot_len/len mismatch in last pbuf", + (i->next != NULL) || (i->tot_len == i->len)); + } + if (p->flags & PBUF_FLAG_TCP_FIN) { + r->flags |= PBUF_FLAG_TCP_FIN; + } + + /* tot_len field in rest does not need modifications */ + /* reference counters do not need modifications */ + *rest = r; + } + } +} +#endif /* LWIP_TCP && TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + +/** + * Skip a number of bytes at the start of a pbuf + * + * @param in input pbuf + * @param in_offset offset to skip + * @param out_offset resulting offset in the returned pbuf + * @return the pbuf in the queue where the offset is + */ +static struct pbuf* +pbuf_skip(struct pbuf* in, u16_t in_offset, u16_t* out_offset) +{ + u16_t offset_left = in_offset; + struct pbuf* q = in; + + /* get the correct pbuf */ + while ((q != NULL) && (q->len <= offset_left)) { + offset_left -= q->len; + q = q->next; + } + if (out_offset != NULL) { + *out_offset = offset_left; + } + return q; +} + +/** + * Copy application supplied data into a pbuf. + * This function can only be used to copy the equivalent of buf->tot_len data. + * + * @param buf pbuf to fill with data + * @param dataptr application supplied data buffer + * @param len length of the application supplied data buffer + * + * @return ERR_OK if successful, ERR_MEM if the pbuf is not big enough + */ +err_t +pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len) +{ + struct pbuf *p; + u16_t buf_copy_len; + u16_t total_copy_len = len; + u16_t copied_total = 0; + + LWIP_ERROR("pbuf_take: invalid buf", (buf != NULL), return 0;); + LWIP_ERROR("pbuf_take: invalid dataptr", (dataptr != NULL), return 0;); + + if ((buf == NULL) || (dataptr == NULL) || (buf->tot_len < len)) { + return ERR_ARG; + } + + /* Note some systems use byte copy if dataptr or one of the pbuf payload pointers are unaligned. */ + for(p = buf; total_copy_len != 0; p = p->next) { + LWIP_ASSERT("pbuf_take: invalid pbuf", p != NULL); + buf_copy_len = total_copy_len; + if (buf_copy_len > p->len) { + /* this pbuf cannot hold all remaining data */ + buf_copy_len = p->len; + } + /* copy the necessary parts of the buffer */ + MEMCPY(p->payload, &((char*)dataptr)[copied_total], buf_copy_len); + total_copy_len -= buf_copy_len; + copied_total += buf_copy_len; + } + LWIP_ASSERT("did not copy all data", total_copy_len == 0 && copied_total == len); + return ERR_OK; +} + +/** + * Same as pbuf_take() but puts data at an offset + * + * @param buf pbuf to fill with data + * @param dataptr application supplied data buffer + * @param len length of the application supplied data buffer + * + * @return ERR_OK if successful, ERR_MEM if the pbuf is not big enough + */ +err_t +pbuf_take_at(struct pbuf *buf, const void *dataptr, u16_t len, u16_t offset) +{ + u16_t target_offset; + struct pbuf* q = pbuf_skip(buf, offset, &target_offset); + + /* return requested data if pbuf is OK */ + if ((q != NULL) && (q->tot_len >= target_offset + len)) { + u16_t remaining_len = len; + u8_t* src_ptr = (u8_t*)dataptr; + if (target_offset > 0) { + /* copy the part that goes into the first pbuf */ + u16_t first_copy_len = LWIP_MIN(q->len - target_offset, len); + MEMCPY(((u8_t*)q->payload) + target_offset, dataptr, first_copy_len); + remaining_len -= first_copy_len; + src_ptr += first_copy_len; + } + if (remaining_len > 0) { + return pbuf_take(q->next, src_ptr, remaining_len); + } + return ERR_OK; + } + return ERR_MEM; +} + +/** + * Creates a single pbuf out of a queue of pbufs. + * + * @remark: Either the source pbuf 'p' is freed by this function or the original + * pbuf 'p' is returned, therefore the caller has to check the result! + * + * @param p the source pbuf + * @param layer pbuf_layer of the new pbuf + * + * @return a new, single pbuf (p->next is NULL) + * or the old pbuf if allocation fails + */ +struct pbuf* +pbuf_coalesce(struct pbuf *p, pbuf_layer layer) +{ + struct pbuf *q; + err_t err; + if (p->next == NULL) { + return p; + } + q = pbuf_alloc(layer, p->tot_len, PBUF_RAM); + if (q == NULL) { + /* @todo: what do we do now? */ + return p; + } + err = pbuf_copy(q, p); + LWIP_ASSERT("pbuf_copy failed", err == ERR_OK); + pbuf_free(p); + return q; +} + +#if LWIP_CHECKSUM_ON_COPY +/** + * Copies data into a single pbuf (*not* into a pbuf queue!) and updates + * the checksum while copying + * + * @param p the pbuf to copy data into + * @param start_offset offset of p->payload where to copy the data to + * @param dataptr data to copy into the pbuf + * @param len length of data to copy into the pbuf + * @param chksum pointer to the checksum which is updated + * @return ERR_OK if successful, another error if the data does not fit + * within the (first) pbuf (no pbuf queues!) + */ +err_t +pbuf_fill_chksum(struct pbuf *p, u16_t start_offset, const void *dataptr, + u16_t len, u16_t *chksum) +{ + u32_t acc; + u16_t copy_chksum; + char *dst_ptr; + LWIP_ASSERT("p != NULL", p != NULL); + LWIP_ASSERT("dataptr != NULL", dataptr != NULL); + LWIP_ASSERT("chksum != NULL", chksum != NULL); + LWIP_ASSERT("len != 0", len != 0); + + if ((start_offset >= p->len) || (start_offset + len > p->len)) { + return ERR_ARG; + } + + dst_ptr = ((char*)p->payload) + start_offset; + copy_chksum = LWIP_CHKSUM_COPY(dst_ptr, dataptr, len); + if ((start_offset & 1) != 0) { + copy_chksum = SWAP_BYTES_IN_WORD(copy_chksum); + } + acc = *chksum; + acc += copy_chksum; + *chksum = FOLD_U32T(acc); + return ERR_OK; +} +#endif /* LWIP_CHECKSUM_ON_COPY */ + + /** Get one byte from the specified position in a pbuf + * WARNING: returns zero for offset >= p->tot_len + * + * @param p pbuf to parse + * @param offset offset into p of the byte to return + * @return byte at an offset into p OR ZERO IF 'offset' >= p->tot_len + */ +u8_t +pbuf_get_at(struct pbuf* p, u16_t offset) +{ + u16_t q_idx; + struct pbuf* q = pbuf_skip(p, offset, &q_idx); + + /* return requested data if pbuf is OK */ + if ((q != NULL) && (q->len > q_idx)) { + return ((u8_t*)q->payload)[q_idx]; + } + return 0; +} + + /** Put one byte to the specified position in a pbuf + * WARNING: silently ignores offset >= p->tot_len + * + * @param p pbuf to fill + * @param offset offset into p of the byte to write + * @param data byte to write at an offset into p + */ +void +pbuf_put_at(struct pbuf* p, u16_t offset, u8_t data) +{ + u16_t q_idx; + struct pbuf* q = pbuf_skip(p, offset, &q_idx); + + /* write requested data if pbuf is OK */ + if ((q != NULL) && (q->len > q_idx)) { + ((u8_t*)q->payload)[q_idx] = data; + } +} + +/** Compare pbuf contents at specified offset with memory s2, both of length n + * + * @param p pbuf to compare + * @param offset offset into p at which to start comparing + * @param s2 buffer to compare + * @param n length of buffer to compare + * @return zero if equal, nonzero otherwise + * (0xffff if p is too short, diffoffset+1 otherwise) + */ +u16_t +pbuf_memcmp(struct pbuf* p, u16_t offset, const void* s2, u16_t n) +{ + u16_t start = offset; + struct pbuf* q = p; + + /* get the correct pbuf */ + while ((q != NULL) && (q->len <= start)) { + start -= q->len; + q = q->next; + } + /* return requested data if pbuf is OK */ + if ((q != NULL) && (q->len > start)) { + u16_t i; + for(i = 0; i < n; i++) { + u8_t a = pbuf_get_at(q, start + i); + u8_t b = ((u8_t*)s2)[i]; + if (a != b) { + return i+1; + } + } + return 0; + } + return 0xffff; +} + +/** Find occurrence of mem (with length mem_len) in pbuf p, starting at offset + * start_offset. + * + * @param p pbuf to search, maximum length is 0xFFFE since 0xFFFF is used as + * return value 'not found' + * @param mem search for the contents of this buffer + * @param mem_len length of 'mem' + * @param start_offset offset into p at which to start searching + * @return 0xFFFF if substr was not found in p or the index where it was found + */ +u16_t +pbuf_memfind(struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset) +{ + u16_t i; + u16_t max = p->tot_len - mem_len; + if (p->tot_len >= mem_len + start_offset) { + for(i = start_offset; i <= max; i++) { + u16_t plus = pbuf_memcmp(p, i, mem, mem_len); + if (plus == 0) { + return i; + } + } + } + return 0xFFFF; +} + +/** Find occurrence of substr with length substr_len in pbuf p, start at offset + * start_offset + * WARNING: in contrast to strstr(), this one does not stop at the first \0 in + * the pbuf/source string! + * + * @param p pbuf to search, maximum length is 0xFFFE since 0xFFFF is used as + * return value 'not found' + * @param substr string to search for in p, maximum length is 0xFFFE + * @return 0xFFFF if substr was not found in p or the index where it was found + */ +u16_t +pbuf_strstr(struct pbuf* p, const char* substr) +{ + size_t substr_len; + if ((substr == NULL) || (substr[0] == 0) || (p->tot_len == 0xFFFF)) { + return 0xFFFF; + } + substr_len = strlen(substr); + if (substr_len >= 0xFFFF) { + return 0xFFFF; + } + return pbuf_memfind(p, substr, (u16_t)substr_len, 0); +} diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/core/raw.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/raw.c new file mode 100644 index 0000000..243dd66 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/raw.c @@ -0,0 +1,436 @@ +/** + * @file + * Implementation of raw protocol PCBs for low-level handling of + * different types of protocols besides (or overriding) those + * already available in lwIP. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_RAW /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/memp.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/raw.h" +#include "lwip/stats.h" +#include "arch/perf.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/inet_chksum.h" + +#include + +/** The list of RAW PCBs */ +static struct raw_pcb *raw_pcbs; + +/** + * Determine if in incoming IP packet is covered by a RAW PCB + * and if so, pass it to a user-provided receive callback function. + * + * Given an incoming IP datagram (as a chain of pbufs) this function + * finds a corresponding RAW PCB and calls the corresponding receive + * callback function. + * + * @param p pbuf to be demultiplexed to a RAW PCB. + * @param inp network interface on which the datagram was received. + * @return - 1 if the packet has been eaten by a RAW PCB receive + * callback function. The caller MAY NOT not reference the + * packet any longer, and MAY NOT call pbuf_free(). + * @return - 0 if packet is not eaten (pbuf is still referenced by the + * caller). + * + */ +u8_t +raw_input(struct pbuf *p, struct netif *inp) +{ + struct raw_pcb *pcb, *prev; + struct ip_hdr *iphdr; + s16_t proto; + u8_t eaten = 0; + + LWIP_UNUSED_ARG(inp); + + iphdr = (struct ip_hdr *)p->payload; +#if LWIP_IPV6 + if (IPH_V(iphdr) == 6) { + struct ip6_hdr *ip6hdr = (struct ip6_hdr *)p->payload; + proto = IP6H_NEXTH(ip6hdr); + iphdr = NULL; + } + else +#endif /* LWIP_IPV6 */ + { + proto = IPH_PROTO(iphdr); + } + + prev = NULL; + pcb = raw_pcbs; + /* loop through all raw pcbs until the packet is eaten by one */ + /* this allows multiple pcbs to match against the packet by design */ + while ((eaten == 0) && (pcb != NULL)) { + if ((pcb->protocol == proto) && IP_PCB_IPVER_INPUT_MATCH(pcb) && + (ipX_addr_isany(PCB_ISIPV6(pcb), &pcb->local_ip) || + ipX_addr_cmp(PCB_ISIPV6(pcb), &(pcb->local_ip), ipX_current_dest_addr()))) { +#if IP_SOF_BROADCAST_RECV + /* broadcast filter? */ + if ((ip_get_option(pcb, SOF_BROADCAST) || !ip_addr_isbroadcast(ip_current_dest_addr(), inp)) +#if LWIP_IPV6 + || PCB_ISIPV6(pcb) +#endif /* LWIP_IPV6 */ + ) +#endif /* IP_SOF_BROADCAST_RECV */ + { + /* receive callback function available? */ + if (pcb->recv.ip4 != NULL) { +#ifndef LWIP_NOASSERT + void* old_payload = p->payload; +#endif + /* the receive callback function did not eat the packet? */ +#if LWIP_IPV6 + if (PCB_ISIPV6(pcb)) { + eaten = pcb->recv.ip6(pcb->recv_arg, pcb, p, ip6_current_src_addr()); + } else +#endif /* LWIP_IPV6 */ + { + eaten = pcb->recv.ip4(pcb->recv_arg, pcb, p, ip_current_src_addr()); + } + if (eaten != 0) { + /* receive function ate the packet */ + p = NULL; + eaten = 1; + if (prev != NULL) { + /* move the pcb to the front of raw_pcbs so that is + found faster next time */ + prev->next = pcb->next; + pcb->next = raw_pcbs; + raw_pcbs = pcb; + } + } else { + /* sanity-check that the receive callback did not alter the pbuf */ + LWIP_ASSERT("raw pcb recv callback altered pbuf payload pointer without eating packet", + p->payload == old_payload); + } + } + /* no receive callback function was set for this raw PCB */ + } + /* drop the packet */ + } + prev = pcb; + pcb = pcb->next; + } + return eaten; +} + +/** + * Bind a RAW PCB. + * + * @param pcb RAW PCB to be bound with a local address ipaddr. + * @param ipaddr local IP address to bind with. Use IP_ADDR_ANY to + * bind to all local interfaces. + * + * @return lwIP error code. + * - ERR_OK. Successful. No error occurred. + * - ERR_USE. The specified IP address is already bound to by + * another RAW PCB. + * + * @see raw_disconnect() + */ +err_t +raw_bind(struct raw_pcb *pcb, ip_addr_t *ipaddr) +{ + ipX_addr_set_ipaddr(PCB_ISIPV6(pcb), &pcb->local_ip, ipaddr); + return ERR_OK; +} + +/** + * Connect an RAW PCB. This function is required by upper layers + * of lwip. Using the raw api you could use raw_sendto() instead + * + * This will associate the RAW PCB with the remote address. + * + * @param pcb RAW PCB to be connected with remote address ipaddr and port. + * @param ipaddr remote IP address to connect with. + * + * @return lwIP error code + * + * @see raw_disconnect() and raw_sendto() + */ +err_t +raw_connect(struct raw_pcb *pcb, ip_addr_t *ipaddr) +{ + ipX_addr_set_ipaddr(PCB_ISIPV6(pcb), &pcb->remote_ip, ipaddr); + return ERR_OK; +} + + +/** + * Set the callback function for received packets that match the + * raw PCB's protocol and binding. + * + * The callback function MUST either + * - eat the packet by calling pbuf_free() and returning non-zero. The + * packet will not be passed to other raw PCBs or other protocol layers. + * - not free the packet, and return zero. The packet will be matched + * against further PCBs and/or forwarded to another protocol layers. + * + * @return non-zero if the packet was free()d, zero if the packet remains + * available for others. + */ +void +raw_recv(struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg) +{ + /* remember recv() callback and user data */ + pcb->recv.ip4 = recv; + pcb->recv_arg = recv_arg; +} + +/** + * Send the raw IP packet to the given address. Note that actually you cannot + * modify the IP headers (this is inconsistent with the receive callback where + * you actually get the IP headers), you can only specify the IP payload here. + * It requires some more changes in lwIP. (there will be a raw_send() function + * then.) + * + * @param pcb the raw pcb which to send + * @param p the IP payload to send + * @param ipaddr the destination address of the IP packet + * + */ +err_t +raw_sendto(struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr) +{ + err_t err; + struct netif *netif; + ipX_addr_t *src_ip; + struct pbuf *q; /* q will be sent down the stack */ + s16_t header_size; + ipX_addr_t *dst_ip = ip_2_ipX(ipaddr); + + LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_sendto\n")); + + header_size = ( +#if LWIP_IPV6 + PCB_ISIPV6(pcb) ? IP6_HLEN : +#endif /* LWIP_IPV6 */ + IP_HLEN); + + /* not enough space to add an IP header to first pbuf in given p chain? */ + if (pbuf_header(p, header_size)) { + /* allocate header in new pbuf */ + q = pbuf_alloc(PBUF_IP, 0, PBUF_RAM); + /* new header pbuf could not be allocated? */ + if (q == NULL) { + LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("raw_sendto: could not allocate header\n")); + return ERR_MEM; + } + if (p->tot_len != 0) { + /* chain header q in front of given pbuf p */ + pbuf_chain(q, p); + } + /* { first pbuf q points to header pbuf } */ + LWIP_DEBUGF(RAW_DEBUG, ("raw_sendto: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p)); + } else { + /* first pbuf q equals given pbuf */ + q = p; + if(pbuf_header(q, -header_size)) { + LWIP_ASSERT("Can't restore header we just removed!", 0); + return ERR_MEM; + } + } + + netif = ipX_route(PCB_ISIPV6(pcb), &pcb->local_ip, dst_ip); + if (netif == NULL) { + LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: No route to ")); + ipX_addr_debug_print(PCB_ISIPV6(pcb), RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, dst_ip); + /* free any temporary header pbuf allocated by pbuf_header() */ + if (q != p) { + pbuf_free(q); + } + return ERR_RTE; + } + +#if IP_SOF_BROADCAST +#if LWIP_IPV6 + if (!PCB_ISIPV6(pcb)) +#endif /* LWIP_IPV6 */ + { + /* broadcast filter? */ + if (!ip_get_option(pcb, SOF_BROADCAST) && ip_addr_isbroadcast(ipaddr, netif)) { + LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb)); + /* free any temporary header pbuf allocated by pbuf_header() */ + if (q != p) { + pbuf_free(q); + } + return ERR_VAL; + } + } +#endif /* IP_SOF_BROADCAST */ + + if (ipX_addr_isany(PCB_ISIPV6(pcb), &pcb->local_ip)) { + /* use outgoing network interface IP address as source address */ + src_ip = ipX_netif_get_local_ipX(PCB_ISIPV6(pcb), netif, dst_ip); +#if LWIP_IPV6 + if (src_ip == NULL) { + if (q != p) { + pbuf_free(q); + } + return ERR_RTE; + } +#endif /* LWIP_IPV6 */ + } else { + /* use RAW PCB local IP address as source address */ + src_ip = &pcb->local_ip; + } + +#if LWIP_IPV6 + /* If requested, based on the IPV6_CHECKSUM socket option per RFC3542, + compute the checksum and update the checksum in the payload. */ + if (PCB_ISIPV6(pcb) && pcb->chksum_reqd) { + u16_t chksum = ip6_chksum_pseudo(p, pcb->protocol, p->tot_len, ipX_2_ip6(src_ip), ipX_2_ip6(dst_ip)); + LWIP_ASSERT("Checksum must fit into first pbuf", p->len >= (pcb->chksum_offset + 2)); + SMEMCPY(((u8_t *)p->payload) + pcb->chksum_offset, &chksum, sizeof(u16_t)); + } +#endif + + NETIF_SET_HWADDRHINT(netif, &pcb->addr_hint); + err = ipX_output_if(PCB_ISIPV6(pcb), q, ipX_2_ip(src_ip), ipX_2_ip(dst_ip), pcb->ttl, pcb->tos, pcb->protocol, netif); + NETIF_SET_HWADDRHINT(netif, NULL); + + /* did we chain a header earlier? */ + if (q != p) { + /* free the header */ + pbuf_free(q); + } + return err; +} + +/** + * Send the raw IP packet to the address given by raw_connect() + * + * @param pcb the raw pcb which to send + * @param p the IP payload to send + * + */ +err_t +raw_send(struct raw_pcb *pcb, struct pbuf *p) +{ + return raw_sendto(pcb, p, ipX_2_ip(&pcb->remote_ip)); +} + +/** + * Remove an RAW PCB. + * + * @param pcb RAW PCB to be removed. The PCB is removed from the list of + * RAW PCB's and the data structure is freed from memory. + * + * @see raw_new() + */ +void +raw_remove(struct raw_pcb *pcb) +{ + struct raw_pcb *pcb2; + /* pcb to be removed is first in list? */ + if (raw_pcbs == pcb) { + /* make list start at 2nd pcb */ + raw_pcbs = raw_pcbs->next; + /* pcb not 1st in list */ + } else { + for(pcb2 = raw_pcbs; pcb2 != NULL; pcb2 = pcb2->next) { + /* find pcb in raw_pcbs list */ + if (pcb2->next != NULL && pcb2->next == pcb) { + /* remove pcb from list */ + pcb2->next = pcb->next; + } + } + } + memp_free(MEMP_RAW_PCB, pcb); +} + +/** + * Create a RAW PCB. + * + * @return The RAW PCB which was created. NULL if the PCB data structure + * could not be allocated. + * + * @param proto the protocol number of the IPs payload (e.g. IP_PROTO_ICMP) + * + * @see raw_remove() + */ +struct raw_pcb * +raw_new(u8_t proto) +{ + struct raw_pcb *pcb; + + LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_new\n")); + + pcb = (struct raw_pcb *)memp_malloc(MEMP_RAW_PCB); + /* could allocate RAW PCB? */ + if (pcb != NULL) { + /* initialize PCB to all zeroes */ + memset(pcb, 0, sizeof(struct raw_pcb)); + pcb->protocol = proto; + pcb->ttl = RAW_TTL; + pcb->next = raw_pcbs; + raw_pcbs = pcb; + } + return pcb; +} + +#if LWIP_IPV6 +/** + * Create a RAW PCB for IPv6. + * + * @return The RAW PCB which was created. NULL if the PCB data structure + * could not be allocated. + * + * @param proto the protocol number (next header) of the IPv6 packet payload + * (e.g. IP6_NEXTH_ICMP6) + * + * @see raw_remove() + */ +struct raw_pcb * +raw_new_ip6(u8_t proto) +{ + struct raw_pcb *pcb; + pcb = raw_new(proto); + ip_set_v6(pcb, 1); + return pcb; +} +#endif /* LWIP_IPV6 */ + +#endif /* LWIP_RAW */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/core/snmp/asn1_dec.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/snmp/asn1_dec.c new file mode 100644 index 0000000..39b70bc --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/snmp/asn1_dec.c @@ -0,0 +1,657 @@ +/** + * @file + * Abstract Syntax Notation One (ISO 8824, 8825) decoding + * + * @todo not optimised (yet), favor correctness over speed, favor speed over size + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * Author: Christiaan Simons + */ + +#include "lwip/opt.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/snmp_asn1.h" + +/** + * Retrieves type field from incoming pbuf chain. + * + * @param p points to a pbuf holding an ASN1 coded type field + * @param ofs points to the offset within the pbuf chain of the ASN1 coded type field + * @param type return ASN1 type + * @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode + */ +err_t +snmp_asn1_dec_type(struct pbuf *p, u16_t ofs, u8_t *type) +{ + u16_t plen, base; + u8_t *msg_ptr; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = (u8_t*)p->payload; + msg_ptr += ofs - base; + *type = *msg_ptr; + return ERR_OK; + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +/** + * Decodes length field from incoming pbuf chain into host length. + * + * @param p points to a pbuf holding an ASN1 coded length + * @param ofs points to the offset within the pbuf chain of the ASN1 coded length + * @param octets_used returns number of octets used by the length code + * @param length return host order length, up to 64k + * @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode + */ +err_t +snmp_asn1_dec_length(struct pbuf *p, u16_t ofs, u8_t *octets_used, u16_t *length) +{ + u16_t plen, base; + u8_t *msg_ptr; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = (u8_t*)p->payload; + msg_ptr += ofs - base; + + if (*msg_ptr < 0x80) + { + /* primitive definite length format */ + *octets_used = 1; + *length = *msg_ptr; + return ERR_OK; + } + else if (*msg_ptr == 0x80) + { + /* constructed indefinite length format, termination with two zero octets */ + u8_t zeros; + u8_t i; + + *length = 0; + zeros = 0; + while (zeros != 2) + { + i = 2; + while (i > 0) + { + i--; + (*length) += 1; + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + if (*msg_ptr == 0) + { + zeros++; + if (zeros == 2) + { + /* stop while (i > 0) */ + i = 0; + } + } + else + { + zeros = 0; + } + } + } + *octets_used = 1; + return ERR_OK; + } + else if (*msg_ptr == 0x81) + { + /* constructed definite length format, one octet */ + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + *length = *msg_ptr; + *octets_used = 2; + return ERR_OK; + } + else if (*msg_ptr == 0x82) + { + u8_t i; + + /* constructed definite length format, two octets */ + i = 2; + while (i > 0) + { + i--; + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + if (i == 0) + { + /* least significant length octet */ + *length |= *msg_ptr; + } + else + { + /* most significant length octet */ + *length = (*msg_ptr) << 8; + } + } + *octets_used = 3; + return ERR_OK; + } + else + { + /* constructed definite length format 3..127 octets, this is too big (>64k) */ + /** @todo: do we need to accept inefficient codings with many leading zero's? */ + *octets_used = 1 + ((*msg_ptr) & 0x7f); + return ERR_ARG; + } + } + p = p->next; + } + + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +/** + * Decodes positive integer (counter, gauge, timeticks) into u32_t. + * + * @param p points to a pbuf holding an ASN1 coded integer + * @param ofs points to the offset within the pbuf chain of the ASN1 coded integer + * @param len length of the coded integer field + * @param value return host order integer + * @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode + * + * @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded + * as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value + * of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!! + */ +err_t +snmp_asn1_dec_u32t(struct pbuf *p, u16_t ofs, u16_t len, u32_t *value) +{ + u16_t plen, base; + u8_t *msg_ptr; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = (u8_t*)p->payload; + msg_ptr += ofs - base; + if ((len > 0) && (len < 6)) + { + /* start from zero */ + *value = 0; + if (*msg_ptr & 0x80) + { + /* negative, expecting zero sign bit! */ + return ERR_ARG; + } + else + { + /* positive */ + if ((len > 1) && (*msg_ptr == 0)) + { + /* skip leading "sign byte" octet 0x00 */ + len--; + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + } + /* OR octets with value */ + while (len > 1) + { + len--; + *value |= *msg_ptr; + *value <<= 8; + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + *value |= *msg_ptr; + return ERR_OK; + } + else + { + return ERR_ARG; + } + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +/** + * Decodes integer into s32_t. + * + * @param p points to a pbuf holding an ASN1 coded integer + * @param ofs points to the offset within the pbuf chain of the ASN1 coded integer + * @param len length of the coded integer field + * @param value return host order integer + * @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode + * + * @note ASN coded integers are _always_ signed! + */ +err_t +snmp_asn1_dec_s32t(struct pbuf *p, u16_t ofs, u16_t len, s32_t *value) +{ + u16_t plen, base; + u8_t *msg_ptr; +#if BYTE_ORDER == LITTLE_ENDIAN + u8_t *lsb_ptr = (u8_t*)value; +#endif +#if BYTE_ORDER == BIG_ENDIAN + u8_t *lsb_ptr = (u8_t*)value + sizeof(s32_t) - 1; +#endif + u8_t sign; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = (u8_t*)p->payload; + msg_ptr += ofs - base; + if ((len > 0) && (len < 5)) + { + if (*msg_ptr & 0x80) + { + /* negative, start from -1 */ + *value = -1; + sign = 1; + } + else + { + /* positive, start from 0 */ + *value = 0; + sign = 0; + } + /* OR/AND octets with value */ + while (len > 1) + { + len--; + if (sign) + { + *lsb_ptr &= *msg_ptr; + *value <<= 8; + *lsb_ptr |= 255; + } + else + { + *lsb_ptr |= *msg_ptr; + *value <<= 8; + } + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + if (sign) + { + *lsb_ptr &= *msg_ptr; + } + else + { + *lsb_ptr |= *msg_ptr; + } + return ERR_OK; + } + else + { + return ERR_ARG; + } + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +/** + * Decodes object identifier from incoming message into array of s32_t. + * + * @param p points to a pbuf holding an ASN1 coded object identifier + * @param ofs points to the offset within the pbuf chain of the ASN1 coded object identifier + * @param len length of the coded object identifier + * @param oid return object identifier struct + * @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode + */ +err_t +snmp_asn1_dec_oid(struct pbuf *p, u16_t ofs, u16_t len, struct snmp_obj_id *oid) +{ + u16_t plen, base; + u8_t *msg_ptr; + s32_t *oid_ptr; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = (u8_t*)p->payload; + msg_ptr += ofs - base; + + oid->len = 0; + oid_ptr = &oid->id[0]; + if (len > 0) + { + /* first compressed octet */ + if (*msg_ptr == 0x2B) + { + /* (most) common case 1.3 (iso.org) */ + *oid_ptr = 1; + oid_ptr++; + *oid_ptr = 3; + oid_ptr++; + } + else if (*msg_ptr < 40) + { + *oid_ptr = 0; + oid_ptr++; + *oid_ptr = *msg_ptr; + oid_ptr++; + } + else if (*msg_ptr < 80) + { + *oid_ptr = 1; + oid_ptr++; + *oid_ptr = (*msg_ptr) - 40; + oid_ptr++; + } + else + { + *oid_ptr = 2; + oid_ptr++; + *oid_ptr = (*msg_ptr) - 80; + oid_ptr++; + } + oid->len = 2; + } + else + { + /* accepting zero length identifiers e.g. for + getnext operation. uncommon but valid */ + return ERR_OK; + } + len--; + if (len > 0) + { + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + while ((len > 0) && (oid->len < LWIP_SNMP_OBJ_ID_LEN)) + { + /* sub-identifier uses multiple octets */ + if (*msg_ptr & 0x80) + { + s32_t sub_id = 0; + + while ((*msg_ptr & 0x80) && (len > 1)) + { + len--; + sub_id = (sub_id << 7) + (*msg_ptr & ~0x80); + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + if (!(*msg_ptr & 0x80) && (len > 0)) + { + /* last octet sub-identifier */ + len--; + sub_id = (sub_id << 7) + *msg_ptr; + *oid_ptr = sub_id; + } + } + else + { + /* !(*msg_ptr & 0x80) sub-identifier uses single octet */ + len--; + *oid_ptr = *msg_ptr; + } + if (len > 0) + { + /* remaining oid bytes available ... */ + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + oid_ptr++; + oid->len++; + } + if (len == 0) + { + /* len == 0, end of oid */ + return ERR_OK; + } + else + { + /* len > 0, oid->len == LWIP_SNMP_OBJ_ID_LEN or malformed encoding */ + return ERR_ARG; + } + + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +/** + * Decodes (copies) raw data (ip-addresses, octet strings, opaque encoding) + * from incoming message into array. + * + * @param p points to a pbuf holding an ASN1 coded raw data + * @param ofs points to the offset within the pbuf chain of the ASN1 coded raw data + * @param len length of the coded raw data (zero is valid, e.g. empty string!) + * @param raw_len length of the raw return value + * @param raw return raw bytes + * @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode + */ +err_t +snmp_asn1_dec_raw(struct pbuf *p, u16_t ofs, u16_t len, u16_t raw_len, u8_t *raw) +{ + u16_t plen, base; + u8_t *msg_ptr; + + if (len > 0) + { + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = (u8_t*)p->payload; + msg_ptr += ofs - base; + if (raw_len >= len) + { + while (len > 1) + { + /* copy len - 1 octets */ + len--; + *raw = *msg_ptr; + raw++; + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + /* copy last octet */ + *raw = *msg_ptr; + return ERR_OK; + } + else + { + /* raw_len < len, not enough dst space */ + return ERR_ARG; + } + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; + } + else + { + /* len == 0, empty string */ + return ERR_OK; + } +} + +#endif /* LWIP_SNMP */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/core/snmp/asn1_enc.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/snmp/asn1_enc.c new file mode 100644 index 0000000..d24a5c4 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/snmp/asn1_enc.c @@ -0,0 +1,611 @@ +/** + * @file + * Abstract Syntax Notation One (ISO 8824, 8825) encoding + * + * @todo not optimised (yet), favor correctness over speed, favor speed over size + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * Author: Christiaan Simons + */ + +#include "lwip/opt.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/snmp_asn1.h" + +/** + * Returns octet count for length. + * + * @param length + * @param octets_needed points to the return value + */ +void +snmp_asn1_enc_length_cnt(u16_t length, u8_t *octets_needed) +{ + if (length < 0x80U) + { + *octets_needed = 1; + } + else if (length < 0x100U) + { + *octets_needed = 2; + } + else + { + *octets_needed = 3; + } +} + +/** + * Returns octet count for an u32_t. + * + * @param value + * @param octets_needed points to the return value + * + * @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded + * as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value + * of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!! + */ +void +snmp_asn1_enc_u32t_cnt(u32_t value, u16_t *octets_needed) +{ + if (value < 0x80UL) + { + *octets_needed = 1; + } + else if (value < 0x8000UL) + { + *octets_needed = 2; + } + else if (value < 0x800000UL) + { + *octets_needed = 3; + } + else if (value < 0x80000000UL) + { + *octets_needed = 4; + } + else + { + *octets_needed = 5; + } +} + +/** + * Returns octet count for an s32_t. + * + * @param value + * @param octets_needed points to the return value + * + * @note ASN coded integers are _always_ signed. + */ +void +snmp_asn1_enc_s32t_cnt(s32_t value, u16_t *octets_needed) +{ + if (value < 0) + { + value = ~value; + } + if (value < 0x80L) + { + *octets_needed = 1; + } + else if (value < 0x8000L) + { + *octets_needed = 2; + } + else if (value < 0x800000L) + { + *octets_needed = 3; + } + else + { + *octets_needed = 4; + } +} + +/** + * Returns octet count for an object identifier. + * + * @param ident_len object identifier array length + * @param ident points to object identifier array + * @param octets_needed points to the return value + */ +void +snmp_asn1_enc_oid_cnt(u8_t ident_len, s32_t *ident, u16_t *octets_needed) +{ + s32_t sub_id; + u8_t cnt; + + cnt = 0; + if (ident_len > 1) + { + /* compressed prefix in one octet */ + cnt++; + ident_len -= 2; + ident += 2; + } + while(ident_len > 0) + { + ident_len--; + sub_id = *ident; + + sub_id >>= 7; + cnt++; + while(sub_id > 0) + { + sub_id >>= 7; + cnt++; + } + ident++; + } + *octets_needed = cnt; +} + +/** + * Encodes ASN type field into a pbuf chained ASN1 msg. + * + * @param p points to output pbuf to encode value into + * @param ofs points to the offset within the pbuf chain + * @param type input ASN1 type + * @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode + */ +err_t +snmp_asn1_enc_type(struct pbuf *p, u16_t ofs, u8_t type) +{ + u16_t plen, base; + u8_t *msg_ptr; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = (u8_t*)p->payload; + msg_ptr += ofs - base; + *msg_ptr = type; + return ERR_OK; + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +/** + * Encodes host order length field into a pbuf chained ASN1 msg. + * + * @param p points to output pbuf to encode length into + * @param ofs points to the offset within the pbuf chain + * @param length is the host order length to be encoded + * @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode + */ +err_t +snmp_asn1_enc_length(struct pbuf *p, u16_t ofs, u16_t length) +{ + u16_t plen, base; + u8_t *msg_ptr; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = (u8_t*)p->payload; + msg_ptr += ofs - base; + + if (length < 0x80) + { + *msg_ptr = (u8_t)length; + return ERR_OK; + } + else if (length < 0x100) + { + *msg_ptr = 0x81; + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + *msg_ptr = (u8_t)length; + return ERR_OK; + } + else + { + u8_t i; + + /* length >= 0x100 && length <= 0xFFFF */ + *msg_ptr = 0x82; + i = 2; + while (i > 0) + { + i--; + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + if (i == 0) + { + /* least significant length octet */ + *msg_ptr = (u8_t)length; + } + else + { + /* most significant length octet */ + *msg_ptr = (u8_t)(length >> 8); + } + } + return ERR_OK; + } + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +/** + * Encodes u32_t (counter, gauge, timeticks) into a pbuf chained ASN1 msg. + * + * @param p points to output pbuf to encode value into + * @param ofs points to the offset within the pbuf chain + * @param octets_needed encoding length (from snmp_asn1_enc_u32t_cnt()) + * @param value is the host order u32_t value to be encoded + * @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode + * + * @see snmp_asn1_enc_u32t_cnt() + */ +err_t +snmp_asn1_enc_u32t(struct pbuf *p, u16_t ofs, u16_t octets_needed, u32_t value) +{ + u16_t plen, base; + u8_t *msg_ptr; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = (u8_t*)p->payload; + msg_ptr += ofs - base; + + if (octets_needed == 5) + { + /* not enough bits in 'value' add leading 0x00 */ + octets_needed--; + *msg_ptr = 0x00; + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + while (octets_needed > 1) + { + octets_needed--; + *msg_ptr = (u8_t)(value >> (octets_needed << 3)); + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + /* (only) one least significant octet */ + *msg_ptr = (u8_t)value; + return ERR_OK; + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +/** + * Encodes s32_t integer into a pbuf chained ASN1 msg. + * + * @param p points to output pbuf to encode value into + * @param ofs points to the offset within the pbuf chain + * @param octets_needed encoding length (from snmp_asn1_enc_s32t_cnt()) + * @param value is the host order s32_t value to be encoded + * @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode + * + * @see snmp_asn1_enc_s32t_cnt() + */ +err_t +snmp_asn1_enc_s32t(struct pbuf *p, u16_t ofs, u16_t octets_needed, s32_t value) +{ + u16_t plen, base; + u8_t *msg_ptr; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = (u8_t*)p->payload; + msg_ptr += ofs - base; + + while (octets_needed > 1) + { + octets_needed--; + *msg_ptr = (u8_t)(value >> (octets_needed << 3)); + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + /* (only) one least significant octet */ + *msg_ptr = (u8_t)value; + return ERR_OK; + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +/** + * Encodes object identifier into a pbuf chained ASN1 msg. + * + * @param p points to output pbuf to encode oid into + * @param ofs points to the offset within the pbuf chain + * @param ident_len object identifier array length + * @param ident points to object identifier array + * @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode + */ +err_t +snmp_asn1_enc_oid(struct pbuf *p, u16_t ofs, u8_t ident_len, s32_t *ident) +{ + u16_t plen, base; + u8_t *msg_ptr; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = (u8_t*)p->payload; + msg_ptr += ofs - base; + + if (ident_len > 1) + { + if ((ident[0] == 1) && (ident[1] == 3)) + { + /* compressed (most common) prefix .iso.org */ + *msg_ptr = 0x2b; + } + else + { + /* calculate prefix */ + *msg_ptr = (u8_t)((ident[0] * 40) + ident[1]); + } + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + ident_len -= 2; + ident += 2; + } + else + { +/* @bug: allow empty varbinds for symmetry (we must decode them for getnext), allow partial compression?? */ + /* ident_len <= 1, at least we need zeroDotZero (0.0) (ident_len == 2) */ + return ERR_ARG; + } + while (ident_len > 0) + { + s32_t sub_id; + u8_t shift, tail; + + ident_len--; + sub_id = *ident; + tail = 0; + shift = 28; + while(shift > 0) + { + u8_t code; + + code = (u8_t)(sub_id >> shift); + if ((code != 0) || (tail != 0)) + { + tail = 1; + *msg_ptr = code | 0x80; + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + shift -= 7; + } + *msg_ptr = (u8_t)sub_id & 0x7F; + if (ident_len > 0) + { + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + /* proceed to next sub-identifier */ + ident++; + } + return ERR_OK; + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +/** + * Encodes raw data (octet string, opaque) into a pbuf chained ASN1 msg. + * + * @param p points to output pbuf to encode raw data into + * @param ofs points to the offset within the pbuf chain + * @param raw_len raw data length + * @param raw points raw data + * @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode + */ +err_t +snmp_asn1_enc_raw(struct pbuf *p, u16_t ofs, u16_t raw_len, u8_t *raw) +{ + u16_t plen, base; + u8_t *msg_ptr; + + plen = 0; + while (p != NULL) + { + base = plen; + plen += p->len; + if (ofs < plen) + { + msg_ptr = (u8_t*)p->payload; + msg_ptr += ofs - base; + + while (raw_len > 1) + { + /* copy raw_len - 1 octets */ + raw_len--; + *msg_ptr = *raw; + raw++; + ofs += 1; + if (ofs >= plen) + { + /* next octet in next pbuf */ + p = p->next; + if (p == NULL) { return ERR_ARG; } + msg_ptr = (u8_t*)p->payload; + plen += p->len; + } + else + { + /* next octet in same pbuf */ + msg_ptr++; + } + } + if (raw_len > 0) + { + /* copy last or single octet */ + *msg_ptr = *raw; + } + return ERR_OK; + } + p = p->next; + } + /* p == NULL, ofs >= plen */ + return ERR_ARG; +} + +#endif /* LWIP_SNMP */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/core/snmp/mib2.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/snmp/mib2.c new file mode 100644 index 0000000..553b4de --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/snmp/mib2.c @@ -0,0 +1,4160 @@ +/** + * @file + * Management Information Base II (RFC1213) objects and functions. + * + * @note the object identifiers for this MIB-2 and private MIB tree + * must be kept in sorted ascending order. This to ensure correct getnext operation. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * Author: Christiaan Simons + */ + +#include "lwip/opt.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/snmp.h" +#include "lwip/netif.h" +#include "lwip/ip.h" +#include "lwip/ip_frag.h" +#include "lwip/mem.h" +#include "lwip/tcp_impl.h" +#include "lwip/udp.h" +#include "lwip/snmp_asn1.h" +#include "lwip/snmp_structs.h" +#include "lwip/sys.h" +#include "netif/etharp.h" + +#include + +/** + * IANA assigned enterprise ID for lwIP is 26381 + * @see http://www.iana.org/assignments/enterprise-numbers + * + * @note this enterprise ID is assigned to the lwIP project, + * all object identifiers living under this ID are assigned + * by the lwIP maintainers (contact Christiaan Simons)! + * @note don't change this define, use snmp_set_sysobjid() + * + * If you need to create your own private MIB you'll need + * to apply for your own enterprise ID with IANA: + * http://www.iana.org/numbers.html + */ +#define SNMP_ENTERPRISE_ID 26381 +#define SNMP_SYSOBJID_LEN 7 +#define SNMP_SYSOBJID {1, 3, 6, 1, 4, 1, SNMP_ENTERPRISE_ID} + +#ifndef SNMP_SYSSERVICES +#define SNMP_SYSSERVICES ((1 << 6) | (1 << 3) | ((IP_FORWARD) << 2)) +#endif + +#ifndef SNMP_GET_SYSUPTIME +#define SNMP_GET_SYSUPTIME(sysuptime) (sysuptime = (sys_now() / 10)) +#endif + +static void system_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void system_get_value(struct obj_def *od, u16_t len, void *value); +static u8_t system_set_test(struct obj_def *od, u16_t len, void *value); +static void system_set_value(struct obj_def *od, u16_t len, void *value); +static void interfaces_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void interfaces_get_value(struct obj_def *od, u16_t len, void *value); +static void ifentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void ifentry_get_value(struct obj_def *od, u16_t len, void *value); +#if !SNMP_SAFE_REQUESTS +static u8_t ifentry_set_test (struct obj_def *od, u16_t len, void *value); +static void ifentry_set_value (struct obj_def *od, u16_t len, void *value); +#endif /* SNMP_SAFE_REQUESTS */ +static void atentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void atentry_get_value(struct obj_def *od, u16_t len, void *value); +static void ip_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void ip_get_value(struct obj_def *od, u16_t len, void *value); +static u8_t ip_set_test(struct obj_def *od, u16_t len, void *value); +static void ip_addrentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void ip_addrentry_get_value(struct obj_def *od, u16_t len, void *value); +static void ip_rteentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void ip_rteentry_get_value(struct obj_def *od, u16_t len, void *value); +static void ip_ntomentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void ip_ntomentry_get_value(struct obj_def *od, u16_t len, void *value); +static void icmp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void icmp_get_value(struct obj_def *od, u16_t len, void *value); +#if LWIP_TCP +static void tcp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void tcp_get_value(struct obj_def *od, u16_t len, void *value); +#ifdef THIS_SEEMS_UNUSED +static void tcpconnentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void tcpconnentry_get_value(struct obj_def *od, u16_t len, void *value); +#endif +#endif +static void udp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void udp_get_value(struct obj_def *od, u16_t len, void *value); +static void udpentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void udpentry_get_value(struct obj_def *od, u16_t len, void *value); +static void snmp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +static void snmp_get_value(struct obj_def *od, u16_t len, void *value); +static u8_t snmp_set_test(struct obj_def *od, u16_t len, void *value); +static void snmp_set_value(struct obj_def *od, u16_t len, void *value); + + +/* snmp .1.3.6.1.2.1.11 */ +const mib_scalar_node snmp_scalar = { + &snmp_get_object_def, + &snmp_get_value, + &snmp_set_test, + &snmp_set_value, + MIB_NODE_SC, + 0 +}; +const s32_t snmp_ids[28] = { + 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 24, 25, 26, 27, 28, 29, 30 +}; +struct mib_node* const snmp_nodes[28] = { + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, + (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar +}; +const struct mib_array_node snmp = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 28, + snmp_ids, + snmp_nodes +}; + +/* dot3 and EtherLike MIB not planned. (transmission .1.3.6.1.2.1.10) */ +/* historical (some say hysterical). (cmot .1.3.6.1.2.1.9) */ +/* lwIP has no EGP, thus may not implement it. (egp .1.3.6.1.2.1.8) */ + +/* udp .1.3.6.1.2.1.7 */ +/** index root node for udpTable */ +struct mib_list_rootnode udp_root = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_LR, + 0, + NULL, + NULL, + 0 +}; +const s32_t udpentry_ids[2] = { 1, 2 }; +struct mib_node* const udpentry_nodes[2] = { + (struct mib_node*)&udp_root, (struct mib_node*)&udp_root, +}; +const struct mib_array_node udpentry = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 2, + udpentry_ids, + udpentry_nodes +}; + +s32_t udptable_id = 1; +struct mib_node* udptable_node = (struct mib_node*)&udpentry; +struct mib_ram_array_node udptable = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_RA, + 0, + &udptable_id, + &udptable_node +}; + +const mib_scalar_node udp_scalar = { + &udp_get_object_def, + &udp_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_SC, + 0 +}; +const s32_t udp_ids[5] = { 1, 2, 3, 4, 5 }; +struct mib_node* const udp_nodes[5] = { + (struct mib_node*)&udp_scalar, (struct mib_node*)&udp_scalar, + (struct mib_node*)&udp_scalar, (struct mib_node*)&udp_scalar, + (struct mib_node*)&udptable +}; +const struct mib_array_node udp = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 5, + udp_ids, + udp_nodes +}; + +/* tcp .1.3.6.1.2.1.6 */ +#if LWIP_TCP +/* only if the TCP protocol is available may implement this group */ +/** index root node for tcpConnTable */ +struct mib_list_rootnode tcpconntree_root = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_LR, + 0, + NULL, + NULL, + 0 +}; +const s32_t tcpconnentry_ids[5] = { 1, 2, 3, 4, 5 }; +struct mib_node* const tcpconnentry_nodes[5] = { + (struct mib_node*)&tcpconntree_root, (struct mib_node*)&tcpconntree_root, + (struct mib_node*)&tcpconntree_root, (struct mib_node*)&tcpconntree_root, + (struct mib_node*)&tcpconntree_root +}; +const struct mib_array_node tcpconnentry = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 5, + tcpconnentry_ids, + tcpconnentry_nodes +}; + +s32_t tcpconntable_id = 1; +struct mib_node* tcpconntable_node = (struct mib_node*)&tcpconnentry; +struct mib_ram_array_node tcpconntable = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_RA, +/** @todo update maxlength when inserting / deleting from table + 0 when table is empty, 1 when more than one entry */ + 0, + &tcpconntable_id, + &tcpconntable_node +}; + +const mib_scalar_node tcp_scalar = { + &tcp_get_object_def, + &tcp_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_SC, + 0 +}; +const s32_t tcp_ids[15] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; +struct mib_node* const tcp_nodes[15] = { + (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar, + (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar, + (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar, + (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar, + (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar, + (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar, + (struct mib_node*)&tcpconntable, (struct mib_node*)&tcp_scalar, + (struct mib_node*)&tcp_scalar +}; +const struct mib_array_node tcp = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 15, + tcp_ids, + tcp_nodes +}; +#endif + +/* icmp .1.3.6.1.2.1.5 */ +const mib_scalar_node icmp_scalar = { + &icmp_get_object_def, + &icmp_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_SC, + 0 +}; +const s32_t icmp_ids[26] = { 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 }; +struct mib_node* const icmp_nodes[26] = { + (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, + (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, + (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, + (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, + (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, + (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, + (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, + (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, + (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, + (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, + (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, + (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, + (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar +}; +const struct mib_array_node icmp = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 26, + icmp_ids, + icmp_nodes +}; + +/** index root node for ipNetToMediaTable */ +struct mib_list_rootnode ipntomtree_root = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_LR, + 0, + NULL, + NULL, + 0 +}; +const s32_t ipntomentry_ids[4] = { 1, 2, 3, 4 }; +struct mib_node* const ipntomentry_nodes[4] = { + (struct mib_node*)&ipntomtree_root, (struct mib_node*)&ipntomtree_root, + (struct mib_node*)&ipntomtree_root, (struct mib_node*)&ipntomtree_root +}; +const struct mib_array_node ipntomentry = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 4, + ipntomentry_ids, + ipntomentry_nodes +}; + +s32_t ipntomtable_id = 1; +struct mib_node* ipntomtable_node = (struct mib_node*)&ipntomentry; +struct mib_ram_array_node ipntomtable = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_RA, + 0, + &ipntomtable_id, + &ipntomtable_node +}; + +/** index root node for ipRouteTable */ +struct mib_list_rootnode iprtetree_root = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_LR, + 0, + NULL, + NULL, + 0 +}; +const s32_t iprteentry_ids[13] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 }; +struct mib_node* const iprteentry_nodes[13] = { + (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root, + (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root, + (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root, + (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root, + (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root, + (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root, + (struct mib_node*)&iprtetree_root +}; +const struct mib_array_node iprteentry = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 13, + iprteentry_ids, + iprteentry_nodes +}; + +s32_t iprtetable_id = 1; +struct mib_node* iprtetable_node = (struct mib_node*)&iprteentry; +struct mib_ram_array_node iprtetable = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_RA, + 0, + &iprtetable_id, + &iprtetable_node +}; + +/** index root node for ipAddrTable */ +struct mib_list_rootnode ipaddrtree_root = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_LR, + 0, + NULL, + NULL, + 0 +}; +const s32_t ipaddrentry_ids[5] = { 1, 2, 3, 4, 5 }; +struct mib_node* const ipaddrentry_nodes[5] = { + (struct mib_node*)&ipaddrtree_root, + (struct mib_node*)&ipaddrtree_root, + (struct mib_node*)&ipaddrtree_root, + (struct mib_node*)&ipaddrtree_root, + (struct mib_node*)&ipaddrtree_root +}; +const struct mib_array_node ipaddrentry = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 5, + ipaddrentry_ids, + ipaddrentry_nodes +}; + +s32_t ipaddrtable_id = 1; +struct mib_node* ipaddrtable_node = (struct mib_node*)&ipaddrentry; +struct mib_ram_array_node ipaddrtable = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_RA, + 0, + &ipaddrtable_id, + &ipaddrtable_node +}; + +/* ip .1.3.6.1.2.1.4 */ +const mib_scalar_node ip_scalar = { + &ip_get_object_def, + &ip_get_value, + &ip_set_test, + &noleafs_set_value, + MIB_NODE_SC, + 0 +}; +const s32_t ip_ids[23] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23 }; +struct mib_node* const ip_nodes[23] = { + (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar, + (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar, + (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar, + (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar, + (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar, + (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar, + (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar, + (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar, + (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar, + (struct mib_node*)&ip_scalar, (struct mib_node*)&ipaddrtable, + (struct mib_node*)&iprtetable, (struct mib_node*)&ipntomtable, + (struct mib_node*)&ip_scalar +}; +const struct mib_array_node mib2_ip = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 23, + ip_ids, + ip_nodes +}; + +/** index root node for atTable */ +struct mib_list_rootnode arptree_root = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_LR, + 0, + NULL, + NULL, + 0 +}; +const s32_t atentry_ids[3] = { 1, 2, 3 }; +struct mib_node* const atentry_nodes[3] = { + (struct mib_node*)&arptree_root, + (struct mib_node*)&arptree_root, + (struct mib_node*)&arptree_root +}; +const struct mib_array_node atentry = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 3, + atentry_ids, + atentry_nodes +}; + +const s32_t attable_id = 1; +struct mib_node* const attable_node = (struct mib_node*)&atentry; +const struct mib_array_node attable = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 1, + &attable_id, + &attable_node +}; + +/* at .1.3.6.1.2.1.3 */ +s32_t at_id = 1; +struct mib_node* mib2_at_node = (struct mib_node*)&attable; +struct mib_ram_array_node at = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_RA, + 0, + &at_id, + &mib2_at_node +}; + +/** index root node for ifTable */ +struct mib_list_rootnode iflist_root = { + &ifentry_get_object_def, + &ifentry_get_value, +#if SNMP_SAFE_REQUESTS + &noleafs_set_test, + &noleafs_set_value, +#else /* SNMP_SAFE_REQUESTS */ + &ifentry_set_test, + &ifentry_set_value, +#endif /* SNMP_SAFE_REQUESTS */ + MIB_NODE_LR, + 0, + NULL, + NULL, + 0 +}; +const s32_t ifentry_ids[22] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22 }; +struct mib_node* const ifentry_nodes[22] = { + (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root, + (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root, + (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root, + (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root, + (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root, + (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root, + (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root, + (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root, + (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root, + (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root, + (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root +}; +const struct mib_array_node ifentry = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 22, + ifentry_ids, + ifentry_nodes +}; + +s32_t iftable_id = 1; +struct mib_node* iftable_node = (struct mib_node*)&ifentry; +struct mib_ram_array_node iftable = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_RA, + 0, + &iftable_id, + &iftable_node +}; + +/* interfaces .1.3.6.1.2.1.2 */ +const mib_scalar_node interfaces_scalar = { + &interfaces_get_object_def, + &interfaces_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_SC, + 0 +}; +const s32_t interfaces_ids[2] = { 1, 2 }; +struct mib_node* const interfaces_nodes[2] = { + (struct mib_node*)&interfaces_scalar, (struct mib_node*)&iftable +}; +const struct mib_array_node interfaces = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 2, + interfaces_ids, + interfaces_nodes +}; + + +/* 0 1 2 3 4 5 6 */ +/* system .1.3.6.1.2.1.1 */ +const mib_scalar_node sys_tem_scalar = { + &system_get_object_def, + &system_get_value, + &system_set_test, + &system_set_value, + MIB_NODE_SC, + 0 +}; +const s32_t sys_tem_ids[7] = { 1, 2, 3, 4, 5, 6, 7 }; +struct mib_node* const sys_tem_nodes[7] = { + (struct mib_node*)&sys_tem_scalar, (struct mib_node*)&sys_tem_scalar, + (struct mib_node*)&sys_tem_scalar, (struct mib_node*)&sys_tem_scalar, + (struct mib_node*)&sys_tem_scalar, (struct mib_node*)&sys_tem_scalar, + (struct mib_node*)&sys_tem_scalar +}; +/* work around name issue with 'sys_tem', some compiler(s?) seem to reserve 'system' */ +const struct mib_array_node sys_tem = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 7, + sys_tem_ids, + sys_tem_nodes +}; + +/* mib-2 .1.3.6.1.2.1 */ +#if LWIP_TCP +#define MIB2_GROUPS 8 +#else +#define MIB2_GROUPS 7 +#endif +const s32_t mib2_ids[MIB2_GROUPS] = +{ + 1, + 2, + 3, + 4, + 5, +#if LWIP_TCP + 6, +#endif + 7, + 11 +}; +struct mib_node* const mib2_nodes[MIB2_GROUPS] = { + (struct mib_node*)&sys_tem, + (struct mib_node*)&interfaces, + (struct mib_node*)&at, + (struct mib_node*)&mib2_ip, + (struct mib_node*)&icmp, +#if LWIP_TCP + (struct mib_node*)&tcp, +#endif + (struct mib_node*)&udp, + (struct mib_node*)&snmp +}; + +const struct mib_array_node mib2 = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + MIB2_GROUPS, + mib2_ids, + mib2_nodes +}; + +/* mgmt .1.3.6.1.2 */ +const s32_t mgmt_ids[1] = { 1 }; +struct mib_node* const mgmt_nodes[1] = { (struct mib_node*)&mib2 }; +const struct mib_array_node mgmt = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 1, + mgmt_ids, + mgmt_nodes +}; + +/* internet .1.3.6.1 */ +#if SNMP_PRIVATE_MIB +/* When using a private MIB, you have to create a file 'private_mib.h' that contains + * a 'struct mib_array_node mib_private' which contains your MIB. */ +s32_t internet_ids[2] = { 2, 4 }; +struct mib_node* const internet_nodes[2] = { (struct mib_node*)&mgmt, (struct mib_node*)&mib_private }; +const struct mib_array_node internet = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 2, + internet_ids, + internet_nodes +}; +#else +const s32_t internet_ids[1] = { 2 }; +struct mib_node* const internet_nodes[1] = { (struct mib_node*)&mgmt }; +const struct mib_array_node internet = { + &noleafs_get_object_def, + &noleafs_get_value, + &noleafs_set_test, + &noleafs_set_value, + MIB_NODE_AR, + 1, + internet_ids, + internet_nodes +}; +#endif + +/** mib-2.system.sysObjectID */ +static const struct snmp_obj_id sysobjid_default = {SNMP_SYSOBJID_LEN, SNMP_SYSOBJID}; +static const struct snmp_obj_id* sysobjid_ptr = &sysobjid_default; +/** enterprise ID for generic TRAPs, .iso.org.dod.internet.mgmt.mib-2.snmp */ +static struct snmp_obj_id snmpgrp_id = {7,{1,3,6,1,2,1,11}}; +/** mib-2.system.sysServices */ +static const s32_t sysservices = SNMP_SYSSERVICES; + +/** mib-2.system.sysDescr */ +static const u8_t sysdescr_len_default = 4; +static const u8_t sysdescr_default[] = "lwIP"; +static const u8_t* sysdescr_len_ptr = &sysdescr_len_default; +static const u8_t* sysdescr_ptr = &sysdescr_default[0]; +/** mib-2.system.sysContact */ +static const u8_t syscontact_len_default = 0; +static const u8_t syscontact_default[] = ""; +static u8_t* syscontact_len_ptr = (u8_t*)&syscontact_len_default; +static u8_t* syscontact_ptr = (u8_t*)&syscontact_default[0]; +/** mib-2.system.sysName */ +static const u8_t sysname_len_default = 8; +static const u8_t sysname_default[] = "FQDN-unk"; +static u8_t* sysname_len_ptr = (u8_t*)&sysname_len_default; +static u8_t* sysname_ptr = (u8_t*)&sysname_default[0]; +/** mib-2.system.sysLocation */ +static const u8_t syslocation_len_default = 0; +static const u8_t syslocation_default[] = ""; +static u8_t* syslocation_len_ptr = (u8_t*)&syslocation_len_default; +static u8_t* syslocation_ptr = (u8_t*)&syslocation_default[0]; +/** mib-2.snmp.snmpEnableAuthenTraps */ +static const u8_t snmpenableauthentraps_default = 2; /* disabled */ +static u8_t* snmpenableauthentraps_ptr = (u8_t*)&snmpenableauthentraps_default; + +/** mib-2.interfaces.ifTable.ifEntry.ifSpecific (zeroDotZero) */ +static const struct snmp_obj_id ifspecific = {2, {0, 0}}; +/** mib-2.ip.ipRouteTable.ipRouteEntry.ipRouteInfo (zeroDotZero) */ +static const struct snmp_obj_id iprouteinfo = {2, {0, 0}}; + + + +/* mib-2.system counter(s) */ +static u32_t sysuptime = 0; + +/* mib-2.ip counter(s) */ +static u32_t ipinreceives = 0, + ipinhdrerrors = 0, + ipinaddrerrors = 0, + ipforwdatagrams = 0, + ipinunknownprotos = 0, + ipindiscards = 0, + ipindelivers = 0, + ipoutrequests = 0, + ipoutdiscards = 0, + ipoutnoroutes = 0, + ipreasmreqds = 0, + ipreasmoks = 0, + ipreasmfails = 0, + ipfragoks = 0, + ipfragfails = 0, + ipfragcreates = 0, + iproutingdiscards = 0; +/* mib-2.icmp counter(s) */ +static u32_t icmpinmsgs = 0, + icmpinerrors = 0, + icmpindestunreachs = 0, + icmpintimeexcds = 0, + icmpinparmprobs = 0, + icmpinsrcquenchs = 0, + icmpinredirects = 0, + icmpinechos = 0, + icmpinechoreps = 0, + icmpintimestamps = 0, + icmpintimestampreps = 0, + icmpinaddrmasks = 0, + icmpinaddrmaskreps = 0, + icmpoutmsgs = 0, + icmpouterrors = 0, + icmpoutdestunreachs = 0, + icmpouttimeexcds = 0, + icmpoutparmprobs = 0, + icmpoutsrcquenchs = 0, + icmpoutredirects = 0, + icmpoutechos = 0, + icmpoutechoreps = 0, + icmpouttimestamps = 0, + icmpouttimestampreps = 0, + icmpoutaddrmasks = 0, + icmpoutaddrmaskreps = 0; +/* mib-2.tcp counter(s) */ +static u32_t tcpactiveopens = 0, + tcppassiveopens = 0, + tcpattemptfails = 0, + tcpestabresets = 0, + tcpinsegs = 0, + tcpoutsegs = 0, + tcpretranssegs = 0, + tcpinerrs = 0, + tcpoutrsts = 0; +/* mib-2.udp counter(s) */ +static u32_t udpindatagrams = 0, + udpnoports = 0, + udpinerrors = 0, + udpoutdatagrams = 0; +/* mib-2.snmp counter(s) */ +static u32_t snmpinpkts = 0, + snmpoutpkts = 0, + snmpinbadversions = 0, + snmpinbadcommunitynames = 0, + snmpinbadcommunityuses = 0, + snmpinasnparseerrs = 0, + snmpintoobigs = 0, + snmpinnosuchnames = 0, + snmpinbadvalues = 0, + snmpinreadonlys = 0, + snmpingenerrs = 0, + snmpintotalreqvars = 0, + snmpintotalsetvars = 0, + snmpingetrequests = 0, + snmpingetnexts = 0, + snmpinsetrequests = 0, + snmpingetresponses = 0, + snmpintraps = 0, + snmpouttoobigs = 0, + snmpoutnosuchnames = 0, + snmpoutbadvalues = 0, + snmpoutgenerrs = 0, + snmpoutgetrequests = 0, + snmpoutgetnexts = 0, + snmpoutsetrequests = 0, + snmpoutgetresponses = 0, + snmpouttraps = 0; + + +/** + * Initializes sysDescr pointers. + * + * @param str if non-NULL then copy str pointer + * @param len points to string length, excluding zero terminator + */ +void snmp_set_sysdescr(const u8_t *str, const u8_t *len) +{ + if (str != NULL) + { + sysdescr_ptr = str; + sysdescr_len_ptr = len; + } +} + +void snmp_get_sysobjid_ptr(const struct snmp_obj_id **oid) +{ + *oid = sysobjid_ptr; +} + +/** + * Initializes sysObjectID value. + * + * @param oid points to stuct snmp_obj_id to copy + */ +void snmp_set_sysobjid(const struct snmp_obj_id *oid) +{ + sysobjid_ptr = oid; +} + +/** + * Must be called at regular 10 msec interval from a timer interrupt + * or signal handler depending on your runtime environment. + */ +void snmp_inc_sysuptime(void) +{ + sysuptime++; +} + +void snmp_add_sysuptime(u32_t value) +{ + sysuptime+=value; +} + +void snmp_get_sysuptime(u32_t *value) +{ + SNMP_GET_SYSUPTIME(sysuptime); + *value = sysuptime; +} + +/** + * Initializes sysContact pointers, + * e.g. ptrs to non-volatile memory external to lwIP. + * + * @param ocstr if non-NULL then copy str pointer + * @param ocstrlen points to string length, excluding zero terminator + */ +void snmp_set_syscontact(u8_t *ocstr, u8_t *ocstrlen) +{ + if (ocstr != NULL) + { + syscontact_ptr = ocstr; + syscontact_len_ptr = ocstrlen; + } +} + +/** + * Initializes sysName pointers, + * e.g. ptrs to non-volatile memory external to lwIP. + * + * @param ocstr if non-NULL then copy str pointer + * @param ocstrlen points to string length, excluding zero terminator + */ +void snmp_set_sysname(u8_t *ocstr, u8_t *ocstrlen) +{ + if (ocstr != NULL) + { + sysname_ptr = ocstr; + sysname_len_ptr = ocstrlen; + } +} + +/** + * Initializes sysLocation pointers, + * e.g. ptrs to non-volatile memory external to lwIP. + * + * @param ocstr if non-NULL then copy str pointer + * @param ocstrlen points to string length, excluding zero terminator + */ +void snmp_set_syslocation(u8_t *ocstr, u8_t *ocstrlen) +{ + if (ocstr != NULL) + { + syslocation_ptr = ocstr; + syslocation_len_ptr = ocstrlen; + } +} + + +void snmp_add_ifinoctets(struct netif *ni, u32_t value) +{ + ni->ifinoctets += value; +} + +void snmp_inc_ifinucastpkts(struct netif *ni) +{ + (ni->ifinucastpkts)++; +} + +void snmp_inc_ifinnucastpkts(struct netif *ni) +{ + (ni->ifinnucastpkts)++; +} + +void snmp_inc_ifindiscards(struct netif *ni) +{ + (ni->ifindiscards)++; +} + +void snmp_add_ifoutoctets(struct netif *ni, u32_t value) +{ + ni->ifoutoctets += value; +} + +void snmp_inc_ifoutucastpkts(struct netif *ni) +{ + (ni->ifoutucastpkts)++; +} + +void snmp_inc_ifoutnucastpkts(struct netif *ni) +{ + (ni->ifoutnucastpkts)++; +} + +void snmp_inc_ifoutdiscards(struct netif *ni) +{ + (ni->ifoutdiscards)++; +} + +void snmp_inc_iflist(void) +{ + struct mib_list_node *if_node = NULL; + + snmp_mib_node_insert(&iflist_root, iflist_root.count + 1, &if_node); + /* enable getnext traversal on filled table */ + iftable.maxlength = 1; +} + +void snmp_dec_iflist(void) +{ + snmp_mib_node_delete(&iflist_root, iflist_root.tail); + /* disable getnext traversal on empty table */ + if(iflist_root.count == 0) iftable.maxlength = 0; +} + +/** + * Inserts ARP table indexes (.xIfIndex.xNetAddress) + * into arp table index trees (both atTable and ipNetToMediaTable). + */ +void snmp_insert_arpidx_tree(struct netif *ni, ip_addr_t *ip) +{ + struct mib_list_rootnode *at_rn; + struct mib_list_node *at_node; + s32_t arpidx[5]; + u8_t level, tree; + + LWIP_ASSERT("ni != NULL", ni != NULL); + snmp_netiftoifindex(ni, &arpidx[0]); + snmp_iptooid(ip, &arpidx[1]); + + for (tree = 0; tree < 2; tree++) + { + if (tree == 0) + { + at_rn = &arptree_root; + } + else + { + at_rn = &ipntomtree_root; + } + for (level = 0; level < 5; level++) + { + at_node = NULL; + snmp_mib_node_insert(at_rn, arpidx[level], &at_node); + if ((level != 4) && (at_node != NULL)) + { + if (at_node->nptr == NULL) + { + at_rn = snmp_mib_lrn_alloc(); + at_node->nptr = (struct mib_node*)at_rn; + if (at_rn != NULL) + { + if (level == 3) + { + if (tree == 0) + { + at_rn->get_object_def = atentry_get_object_def; + at_rn->get_value = atentry_get_value; + } + else + { + at_rn->get_object_def = ip_ntomentry_get_object_def; + at_rn->get_value = ip_ntomentry_get_value; + } + at_rn->set_test = noleafs_set_test; + at_rn->set_value = noleafs_set_value; + } + } + else + { + /* at_rn == NULL, malloc failure */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_insert_arpidx_tree() insert failed, mem full")); + break; + } + } + else + { + at_rn = (struct mib_list_rootnode*)at_node->nptr; + } + } + } + } + /* enable getnext traversal on filled tables */ + at.maxlength = 1; + ipntomtable.maxlength = 1; +} + +/** + * Removes ARP table indexes (.xIfIndex.xNetAddress) + * from arp table index trees. + */ +void snmp_delete_arpidx_tree(struct netif *ni, ip_addr_t *ip) +{ + struct mib_list_rootnode *at_rn, *next, *del_rn[5]; + struct mib_list_node *at_n, *del_n[5]; + s32_t arpidx[5]; + u8_t fc, tree, level, del_cnt; + + snmp_netiftoifindex(ni, &arpidx[0]); + snmp_iptooid(ip, &arpidx[1]); + + for (tree = 0; tree < 2; tree++) + { + /* mark nodes for deletion */ + if (tree == 0) + { + at_rn = &arptree_root; + } + else + { + at_rn = &ipntomtree_root; + } + level = 0; + del_cnt = 0; + while ((level < 5) && (at_rn != NULL)) + { + fc = snmp_mib_node_find(at_rn, arpidx[level], &at_n); + if (fc == 0) + { + /* arpidx[level] does not exist */ + del_cnt = 0; + at_rn = NULL; + } + else if (fc == 1) + { + del_rn[del_cnt] = at_rn; + del_n[del_cnt] = at_n; + del_cnt++; + at_rn = (struct mib_list_rootnode*)(at_n->nptr); + } + else if (fc == 2) + { + /* reset delete (2 or more childs) */ + del_cnt = 0; + at_rn = (struct mib_list_rootnode*)(at_n->nptr); + } + level++; + } + /* delete marked index nodes */ + while (del_cnt > 0) + { + del_cnt--; + + at_rn = del_rn[del_cnt]; + at_n = del_n[del_cnt]; + + next = snmp_mib_node_delete(at_rn, at_n); + if (next != NULL) + { + LWIP_ASSERT("next_count == 0",next->count == 0); + snmp_mib_lrn_free(next); + } + } + } + /* disable getnext traversal on empty tables */ + if(arptree_root.count == 0) at.maxlength = 0; + if(ipntomtree_root.count == 0) ipntomtable.maxlength = 0; +} + +void snmp_inc_ipinreceives(void) +{ + ipinreceives++; +} + +void snmp_inc_ipinhdrerrors(void) +{ + ipinhdrerrors++; +} + +void snmp_inc_ipinaddrerrors(void) +{ + ipinaddrerrors++; +} + +void snmp_inc_ipforwdatagrams(void) +{ + ipforwdatagrams++; +} + +void snmp_inc_ipinunknownprotos(void) +{ + ipinunknownprotos++; +} + +void snmp_inc_ipindiscards(void) +{ + ipindiscards++; +} + +void snmp_inc_ipindelivers(void) +{ + ipindelivers++; +} + +void snmp_inc_ipoutrequests(void) +{ + ipoutrequests++; +} + +void snmp_inc_ipoutdiscards(void) +{ + ipoutdiscards++; +} + +void snmp_inc_ipoutnoroutes(void) +{ + ipoutnoroutes++; +} + +void snmp_inc_ipreasmreqds(void) +{ + ipreasmreqds++; +} + +void snmp_inc_ipreasmoks(void) +{ + ipreasmoks++; +} + +void snmp_inc_ipreasmfails(void) +{ + ipreasmfails++; +} + +void snmp_inc_ipfragoks(void) +{ + ipfragoks++; +} + +void snmp_inc_ipfragfails(void) +{ + ipfragfails++; +} + +void snmp_inc_ipfragcreates(void) +{ + ipfragcreates++; +} + +void snmp_inc_iproutingdiscards(void) +{ + iproutingdiscards++; +} + +/** + * Inserts ipAddrTable indexes (.ipAdEntAddr) + * into index tree. + */ +void snmp_insert_ipaddridx_tree(struct netif *ni) +{ + struct mib_list_rootnode *ipa_rn; + struct mib_list_node *ipa_node; + s32_t ipaddridx[4]; + u8_t level; + + LWIP_ASSERT("ni != NULL", ni != NULL); + snmp_iptooid(&ni->ip_addr, &ipaddridx[0]); + + level = 0; + ipa_rn = &ipaddrtree_root; + while (level < 4) + { + ipa_node = NULL; + snmp_mib_node_insert(ipa_rn, ipaddridx[level], &ipa_node); + if ((level != 3) && (ipa_node != NULL)) + { + if (ipa_node->nptr == NULL) + { + ipa_rn = snmp_mib_lrn_alloc(); + ipa_node->nptr = (struct mib_node*)ipa_rn; + if (ipa_rn != NULL) + { + if (level == 2) + { + ipa_rn->get_object_def = ip_addrentry_get_object_def; + ipa_rn->get_value = ip_addrentry_get_value; + ipa_rn->set_test = noleafs_set_test; + ipa_rn->set_value = noleafs_set_value; + } + } + else + { + /* ipa_rn == NULL, malloc failure */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_insert_ipaddridx_tree() insert failed, mem full")); + break; + } + } + else + { + ipa_rn = (struct mib_list_rootnode*)ipa_node->nptr; + } + } + level++; + } + /* enable getnext traversal on filled table */ + ipaddrtable.maxlength = 1; +} + +/** + * Removes ipAddrTable indexes (.ipAdEntAddr) + * from index tree. + */ +void snmp_delete_ipaddridx_tree(struct netif *ni) +{ + struct mib_list_rootnode *ipa_rn, *next, *del_rn[4]; + struct mib_list_node *ipa_n, *del_n[4]; + s32_t ipaddridx[4]; + u8_t fc, level, del_cnt; + + LWIP_ASSERT("ni != NULL", ni != NULL); + snmp_iptooid(&ni->ip_addr, &ipaddridx[0]); + + /* mark nodes for deletion */ + level = 0; + del_cnt = 0; + ipa_rn = &ipaddrtree_root; + while ((level < 4) && (ipa_rn != NULL)) + { + fc = snmp_mib_node_find(ipa_rn, ipaddridx[level], &ipa_n); + if (fc == 0) + { + /* ipaddridx[level] does not exist */ + del_cnt = 0; + ipa_rn = NULL; + } + else if (fc == 1) + { + del_rn[del_cnt] = ipa_rn; + del_n[del_cnt] = ipa_n; + del_cnt++; + ipa_rn = (struct mib_list_rootnode*)(ipa_n->nptr); + } + else if (fc == 2) + { + /* reset delete (2 or more childs) */ + del_cnt = 0; + ipa_rn = (struct mib_list_rootnode*)(ipa_n->nptr); + } + level++; + } + /* delete marked index nodes */ + while (del_cnt > 0) + { + del_cnt--; + + ipa_rn = del_rn[del_cnt]; + ipa_n = del_n[del_cnt]; + + next = snmp_mib_node_delete(ipa_rn, ipa_n); + if (next != NULL) + { + LWIP_ASSERT("next_count == 0",next->count == 0); + snmp_mib_lrn_free(next); + } + } + /* disable getnext traversal on empty table */ + if (ipaddrtree_root.count == 0) ipaddrtable.maxlength = 0; +} + +/** + * Inserts ipRouteTable indexes (.ipRouteDest) + * into index tree. + * + * @param dflt non-zero for the default rte, zero for network rte + * @param ni points to network interface for this rte + * + * @todo record sysuptime for _this_ route when it is installed + * (needed for ipRouteAge) in the netif. + */ +void snmp_insert_iprteidx_tree(u8_t dflt, struct netif *ni) +{ + u8_t insert = 0; + ip_addr_t dst; + + if (dflt != 0) + { + /* the default route 0.0.0.0 */ + ip_addr_set_any(&dst); + insert = 1; + } + else + { + /* route to the network address */ + ip_addr_get_network(&dst, &ni->ip_addr, &ni->netmask); + /* exclude 0.0.0.0 network (reserved for default rte) */ + if (!ip_addr_isany(&dst)) { + insert = 1; + } + } + if (insert) + { + struct mib_list_rootnode *iprte_rn; + struct mib_list_node *iprte_node; + s32_t iprteidx[4]; + u8_t level; + + snmp_iptooid(&dst, &iprteidx[0]); + level = 0; + iprte_rn = &iprtetree_root; + while (level < 4) + { + iprte_node = NULL; + snmp_mib_node_insert(iprte_rn, iprteidx[level], &iprte_node); + if ((level != 3) && (iprte_node != NULL)) + { + if (iprte_node->nptr == NULL) + { + iprte_rn = snmp_mib_lrn_alloc(); + iprte_node->nptr = (struct mib_node*)iprte_rn; + if (iprte_rn != NULL) + { + if (level == 2) + { + iprte_rn->get_object_def = ip_rteentry_get_object_def; + iprte_rn->get_value = ip_rteentry_get_value; + iprte_rn->set_test = noleafs_set_test; + iprte_rn->set_value = noleafs_set_value; + } + } + else + { + /* iprte_rn == NULL, malloc failure */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_insert_iprteidx_tree() insert failed, mem full")); + break; + } + } + else + { + iprte_rn = (struct mib_list_rootnode*)iprte_node->nptr; + } + } + level++; + } + } + /* enable getnext traversal on filled table */ + iprtetable.maxlength = 1; +} + +/** + * Removes ipRouteTable indexes (.ipRouteDest) + * from index tree. + * + * @param dflt non-zero for the default rte, zero for network rte + * @param ni points to network interface for this rte or NULL + * for default route to be removed. + */ +void snmp_delete_iprteidx_tree(u8_t dflt, struct netif *ni) +{ + u8_t del = 0; + ip_addr_t dst; + + if (dflt != 0) + { + /* the default route 0.0.0.0 */ + ip_addr_set_any(&dst); + del = 1; + } + else + { + /* route to the network address */ + ip_addr_get_network(&dst, &ni->ip_addr, &ni->netmask); + /* exclude 0.0.0.0 network (reserved for default rte) */ + if (!ip_addr_isany(&dst)) { + del = 1; + } + } + if (del) + { + struct mib_list_rootnode *iprte_rn, *next, *del_rn[4]; + struct mib_list_node *iprte_n, *del_n[4]; + s32_t iprteidx[4]; + u8_t fc, level, del_cnt; + + snmp_iptooid(&dst, &iprteidx[0]); + /* mark nodes for deletion */ + level = 0; + del_cnt = 0; + iprte_rn = &iprtetree_root; + while ((level < 4) && (iprte_rn != NULL)) + { + fc = snmp_mib_node_find(iprte_rn, iprteidx[level], &iprte_n); + if (fc == 0) + { + /* iprteidx[level] does not exist */ + del_cnt = 0; + iprte_rn = NULL; + } + else if (fc == 1) + { + del_rn[del_cnt] = iprte_rn; + del_n[del_cnt] = iprte_n; + del_cnt++; + iprte_rn = (struct mib_list_rootnode*)(iprte_n->nptr); + } + else if (fc == 2) + { + /* reset delete (2 or more childs) */ + del_cnt = 0; + iprte_rn = (struct mib_list_rootnode*)(iprte_n->nptr); + } + level++; + } + /* delete marked index nodes */ + while (del_cnt > 0) + { + del_cnt--; + + iprte_rn = del_rn[del_cnt]; + iprte_n = del_n[del_cnt]; + + next = snmp_mib_node_delete(iprte_rn, iprte_n); + if (next != NULL) + { + LWIP_ASSERT("next_count == 0",next->count == 0); + snmp_mib_lrn_free(next); + } + } + } + /* disable getnext traversal on empty table */ + if (iprtetree_root.count == 0) iprtetable.maxlength = 0; +} + + +void snmp_inc_icmpinmsgs(void) +{ + icmpinmsgs++; +} + +void snmp_inc_icmpinerrors(void) +{ + icmpinerrors++; +} + +void snmp_inc_icmpindestunreachs(void) +{ + icmpindestunreachs++; +} + +void snmp_inc_icmpintimeexcds(void) +{ + icmpintimeexcds++; +} + +void snmp_inc_icmpinparmprobs(void) +{ + icmpinparmprobs++; +} + +void snmp_inc_icmpinsrcquenchs(void) +{ + icmpinsrcquenchs++; +} + +void snmp_inc_icmpinredirects(void) +{ + icmpinredirects++; +} + +void snmp_inc_icmpinechos(void) +{ + icmpinechos++; +} + +void snmp_inc_icmpinechoreps(void) +{ + icmpinechoreps++; +} + +void snmp_inc_icmpintimestamps(void) +{ + icmpintimestamps++; +} + +void snmp_inc_icmpintimestampreps(void) +{ + icmpintimestampreps++; +} + +void snmp_inc_icmpinaddrmasks(void) +{ + icmpinaddrmasks++; +} + +void snmp_inc_icmpinaddrmaskreps(void) +{ + icmpinaddrmaskreps++; +} + +void snmp_inc_icmpoutmsgs(void) +{ + icmpoutmsgs++; +} + +void snmp_inc_icmpouterrors(void) +{ + icmpouterrors++; +} + +void snmp_inc_icmpoutdestunreachs(void) +{ + icmpoutdestunreachs++; +} + +void snmp_inc_icmpouttimeexcds(void) +{ + icmpouttimeexcds++; +} + +void snmp_inc_icmpoutparmprobs(void) +{ + icmpoutparmprobs++; +} + +void snmp_inc_icmpoutsrcquenchs(void) +{ + icmpoutsrcquenchs++; +} + +void snmp_inc_icmpoutredirects(void) +{ + icmpoutredirects++; +} + +void snmp_inc_icmpoutechos(void) +{ + icmpoutechos++; +} + +void snmp_inc_icmpoutechoreps(void) +{ + icmpoutechoreps++; +} + +void snmp_inc_icmpouttimestamps(void) +{ + icmpouttimestamps++; +} + +void snmp_inc_icmpouttimestampreps(void) +{ + icmpouttimestampreps++; +} + +void snmp_inc_icmpoutaddrmasks(void) +{ + icmpoutaddrmasks++; +} + +void snmp_inc_icmpoutaddrmaskreps(void) +{ + icmpoutaddrmaskreps++; +} + +void snmp_inc_tcpactiveopens(void) +{ + tcpactiveopens++; +} + +void snmp_inc_tcppassiveopens(void) +{ + tcppassiveopens++; +} + +void snmp_inc_tcpattemptfails(void) +{ + tcpattemptfails++; +} + +void snmp_inc_tcpestabresets(void) +{ + tcpestabresets++; +} + +void snmp_inc_tcpinsegs(void) +{ + tcpinsegs++; +} + +void snmp_inc_tcpoutsegs(void) +{ + tcpoutsegs++; +} + +void snmp_inc_tcpretranssegs(void) +{ + tcpretranssegs++; +} + +void snmp_inc_tcpinerrs(void) +{ + tcpinerrs++; +} + +void snmp_inc_tcpoutrsts(void) +{ + tcpoutrsts++; +} + +void snmp_inc_udpindatagrams(void) +{ + udpindatagrams++; +} + +void snmp_inc_udpnoports(void) +{ + udpnoports++; +} + +void snmp_inc_udpinerrors(void) +{ + udpinerrors++; +} + +void snmp_inc_udpoutdatagrams(void) +{ + udpoutdatagrams++; +} + +/** + * Inserts udpTable indexes (.udpLocalAddress.udpLocalPort) + * into index tree. + */ +void snmp_insert_udpidx_tree(struct udp_pcb *pcb) +{ + struct mib_list_rootnode *udp_rn; + struct mib_list_node *udp_node; + s32_t udpidx[5]; + u8_t level; + + LWIP_ASSERT("pcb != NULL", pcb != NULL); + snmp_iptooid(ipX_2_ip(&pcb->local_ip), &udpidx[0]); + udpidx[4] = pcb->local_port; + + udp_rn = &udp_root; + for (level = 0; level < 5; level++) + { + udp_node = NULL; + snmp_mib_node_insert(udp_rn, udpidx[level], &udp_node); + if ((level != 4) && (udp_node != NULL)) + { + if (udp_node->nptr == NULL) + { + udp_rn = snmp_mib_lrn_alloc(); + udp_node->nptr = (struct mib_node*)udp_rn; + if (udp_rn != NULL) + { + if (level == 3) + { + udp_rn->get_object_def = udpentry_get_object_def; + udp_rn->get_value = udpentry_get_value; + udp_rn->set_test = noleafs_set_test; + udp_rn->set_value = noleafs_set_value; + } + } + else + { + /* udp_rn == NULL, malloc failure */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_insert_udpidx_tree() insert failed, mem full")); + break; + } + } + else + { + udp_rn = (struct mib_list_rootnode*)udp_node->nptr; + } + } + } + udptable.maxlength = 1; +} + +/** + * Removes udpTable indexes (.udpLocalAddress.udpLocalPort) + * from index tree. + */ +void snmp_delete_udpidx_tree(struct udp_pcb *pcb) +{ + struct udp_pcb *npcb; + struct mib_list_rootnode *udp_rn, *next, *del_rn[5]; + struct mib_list_node *udp_n, *del_n[5]; + s32_t udpidx[5]; + u8_t bindings, fc, level, del_cnt; + + LWIP_ASSERT("pcb != NULL", pcb != NULL); + snmp_iptooid(ipX_2_ip(&pcb->local_ip), &udpidx[0]); + udpidx[4] = pcb->local_port; + + /* count PCBs for a given binding + (e.g. when reusing ports or for temp output PCBs) */ + bindings = 0; + npcb = udp_pcbs; + while ((npcb != NULL)) + { + if (ipX_addr_cmp(0, &npcb->local_ip, &pcb->local_ip) && + (npcb->local_port == udpidx[4])) + { + bindings++; + } + npcb = npcb->next; + } + if (bindings == 1) + { + /* selectively remove */ + /* mark nodes for deletion */ + level = 0; + del_cnt = 0; + udp_rn = &udp_root; + while ((level < 5) && (udp_rn != NULL)) + { + fc = snmp_mib_node_find(udp_rn, udpidx[level], &udp_n); + if (fc == 0) + { + /* udpidx[level] does not exist */ + del_cnt = 0; + udp_rn = NULL; + } + else if (fc == 1) + { + del_rn[del_cnt] = udp_rn; + del_n[del_cnt] = udp_n; + del_cnt++; + udp_rn = (struct mib_list_rootnode*)(udp_n->nptr); + } + else if (fc == 2) + { + /* reset delete (2 or more childs) */ + del_cnt = 0; + udp_rn = (struct mib_list_rootnode*)(udp_n->nptr); + } + level++; + } + /* delete marked index nodes */ + while (del_cnt > 0) + { + del_cnt--; + + udp_rn = del_rn[del_cnt]; + udp_n = del_n[del_cnt]; + + next = snmp_mib_node_delete(udp_rn, udp_n); + if (next != NULL) + { + LWIP_ASSERT("next_count == 0",next->count == 0); + snmp_mib_lrn_free(next); + } + } + } + /* disable getnext traversal on empty table */ + if (udp_root.count == 0) udptable.maxlength = 0; +} + + +void snmp_inc_snmpinpkts(void) +{ + snmpinpkts++; +} + +void snmp_inc_snmpoutpkts(void) +{ + snmpoutpkts++; +} + +void snmp_inc_snmpinbadversions(void) +{ + snmpinbadversions++; +} + +void snmp_inc_snmpinbadcommunitynames(void) +{ + snmpinbadcommunitynames++; +} + +void snmp_inc_snmpinbadcommunityuses(void) +{ + snmpinbadcommunityuses++; +} + +void snmp_inc_snmpinasnparseerrs(void) +{ + snmpinasnparseerrs++; +} + +void snmp_inc_snmpintoobigs(void) +{ + snmpintoobigs++; +} + +void snmp_inc_snmpinnosuchnames(void) +{ + snmpinnosuchnames++; +} + +void snmp_inc_snmpinbadvalues(void) +{ + snmpinbadvalues++; +} + +void snmp_inc_snmpinreadonlys(void) +{ + snmpinreadonlys++; +} + +void snmp_inc_snmpingenerrs(void) +{ + snmpingenerrs++; +} + +void snmp_add_snmpintotalreqvars(u8_t value) +{ + snmpintotalreqvars += value; +} + +void snmp_add_snmpintotalsetvars(u8_t value) +{ + snmpintotalsetvars += value; +} + +void snmp_inc_snmpingetrequests(void) +{ + snmpingetrequests++; +} + +void snmp_inc_snmpingetnexts(void) +{ + snmpingetnexts++; +} + +void snmp_inc_snmpinsetrequests(void) +{ + snmpinsetrequests++; +} + +void snmp_inc_snmpingetresponses(void) +{ + snmpingetresponses++; +} + +void snmp_inc_snmpintraps(void) +{ + snmpintraps++; +} + +void snmp_inc_snmpouttoobigs(void) +{ + snmpouttoobigs++; +} + +void snmp_inc_snmpoutnosuchnames(void) +{ + snmpoutnosuchnames++; +} + +void snmp_inc_snmpoutbadvalues(void) +{ + snmpoutbadvalues++; +} + +void snmp_inc_snmpoutgenerrs(void) +{ + snmpoutgenerrs++; +} + +void snmp_inc_snmpoutgetrequests(void) +{ + snmpoutgetrequests++; +} + +void snmp_inc_snmpoutgetnexts(void) +{ + snmpoutgetnexts++; +} + +void snmp_inc_snmpoutsetrequests(void) +{ + snmpoutsetrequests++; +} + +void snmp_inc_snmpoutgetresponses(void) +{ + snmpoutgetresponses++; +} + +void snmp_inc_snmpouttraps(void) +{ + snmpouttraps++; +} + +void snmp_get_snmpgrpid_ptr(struct snmp_obj_id **oid) +{ + *oid = &snmpgrp_id; +} + +void snmp_set_snmpenableauthentraps(u8_t *value) +{ + if (value != NULL) + { + snmpenableauthentraps_ptr = value; + } +} + +void snmp_get_snmpenableauthentraps(u8_t *value) +{ + *value = *snmpenableauthentraps_ptr; +} + +void +noleafs_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + LWIP_UNUSED_ARG(ident_len); + LWIP_UNUSED_ARG(ident); + od->instance = MIB_OBJECT_NONE; +} + +void +noleafs_get_value(struct obj_def *od, u16_t len, void *value) +{ + LWIP_UNUSED_ARG(od); + LWIP_UNUSED_ARG(len); + LWIP_UNUSED_ARG(value); +} + +u8_t +noleafs_set_test(struct obj_def *od, u16_t len, void *value) +{ + LWIP_UNUSED_ARG(od); + LWIP_UNUSED_ARG(len); + LWIP_UNUSED_ARG(value); + /* can't set */ + return 0; +} + +void +noleafs_set_value(struct obj_def *od, u16_t len, void *value) +{ + LWIP_UNUSED_ARG(od); + LWIP_UNUSED_ARG(len); + LWIP_UNUSED_ARG(value); +} + + +/** + * Returns systems object definitions. + * + * @param ident_len the address length (2) + * @param ident points to objectname.0 (object id trailer) + * @param od points to object definition. + */ +static void +system_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + u8_t id; + + /* return to object name, adding index depth (1) */ + ident_len += 1; + ident -= 1; + if (ident_len == 2) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff)); + id = (u8_t)ident[0]; + LWIP_DEBUGF(SNMP_MIB_DEBUG,("get_object_def system.%"U16_F".0\n",(u16_t)id)); + switch (id) + { + case 1: /* sysDescr */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); + od->v_len = *sysdescr_len_ptr; + break; + case 2: /* sysObjectID */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID); + od->v_len = sysobjid_ptr->len * sizeof(s32_t); + break; + case 3: /* sysUpTime */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS); + od->v_len = sizeof(u32_t); + break; + case 4: /* sysContact */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); + od->v_len = *syscontact_len_ptr; + break; + case 5: /* sysName */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); + od->v_len = *sysname_len_ptr; + break; + case 6: /* sysLocation */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); + od->v_len = *syslocation_len_ptr; + break; + case 7: /* sysServices */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + }; + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +/** + * Returns system object value. + * + * @param ident_len the address length (2) + * @param ident points to objectname.0 (object id trailer) + * @param len return value space (in bytes) + * @param value points to (varbind) space to copy value into. + */ +static void +system_get_value(struct obj_def *od, u16_t len, void *value) +{ + u8_t id; + + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 1: /* sysDescr */ + MEMCPY(value, sysdescr_ptr, len); + break; + case 2: /* sysObjectID */ + MEMCPY(value, sysobjid_ptr->id, len); + break; + case 3: /* sysUpTime */ + { + snmp_get_sysuptime((u32_t*)value); + } + break; + case 4: /* sysContact */ + MEMCPY(value, syscontact_ptr, len); + break; + case 5: /* sysName */ + MEMCPY(value, sysname_ptr, len); + break; + case 6: /* sysLocation */ + MEMCPY(value, syslocation_ptr, len); + break; + case 7: /* sysServices */ + { + s32_t *sint_ptr = (s32_t*)value; + *sint_ptr = sysservices; + } + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_get_value(): unknown id: %d\n", id)); + break; + }; +} + +static u8_t +system_set_test(struct obj_def *od, u16_t len, void *value) +{ + u8_t id, set_ok; + + LWIP_UNUSED_ARG(value); + set_ok = 0; + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 4: /* sysContact */ + if ((syscontact_ptr != syscontact_default) && + (len <= 255)) + { + set_ok = 1; + } + break; + case 5: /* sysName */ + if ((sysname_ptr != sysname_default) && + (len <= 255)) + { + set_ok = 1; + } + break; + case 6: /* sysLocation */ + if ((syslocation_ptr != syslocation_default) && + (len <= 255)) + { + set_ok = 1; + } + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_set_test(): unknown id: %d\n", id)); + break; + }; + return set_ok; +} + +static void +system_set_value(struct obj_def *od, u16_t len, void *value) +{ + u8_t id; + + LWIP_ASSERT("invalid len", len <= 0xff); + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 4: /* sysContact */ + MEMCPY(syscontact_ptr, value, len); + *syscontact_len_ptr = (u8_t)len; + break; + case 5: /* sysName */ + MEMCPY(sysname_ptr, value, len); + *sysname_len_ptr = (u8_t)len; + break; + case 6: /* sysLocation */ + MEMCPY(syslocation_ptr, value, len); + *syslocation_len_ptr = (u8_t)len; + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_set_value(): unknown id: %d\n", id)); + break; + }; +} + +/** + * Returns interfaces.ifnumber object definition. + * + * @param ident_len the address length (2) + * @param ident points to objectname.index + * @param od points to object definition. + */ +static void +interfaces_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + /* return to object name, adding index depth (1) */ + ident_len += 1; + ident -= 1; + if (ident_len == 2) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("interfaces_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +/** + * Returns interfaces.ifnumber object value. + * + * @param ident_len the address length (2) + * @param ident points to objectname.0 (object id trailer) + * @param len return value space (in bytes) + * @param value points to (varbind) space to copy value into. + */ +static void +interfaces_get_value(struct obj_def *od, u16_t len, void *value) +{ + LWIP_UNUSED_ARG(len); + if (od->id_inst_ptr[0] == 1) + { + s32_t *sint_ptr = (s32_t*)value; + *sint_ptr = iflist_root.count; + } +} + +/** + * Returns ifentry object definitions. + * + * @param ident_len the address length (2) + * @param ident points to objectname.index + * @param od points to object definition. + */ +static void +ifentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + u8_t id; + + /* return to object name, adding index depth (1) */ + ident_len += 1; + ident -= 1; + if (ident_len == 2) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff)); + id = (u8_t)ident[0]; + LWIP_DEBUGF(SNMP_MIB_DEBUG,("get_object_def ifentry.%"U16_F"\n",(u16_t)id)); + switch (id) + { + case 1: /* ifIndex */ + case 3: /* ifType */ + case 4: /* ifMtu */ + case 8: /* ifOperStatus */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + case 2: /* ifDescr */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); + /** @todo this should be some sort of sizeof(struct netif.name) */ + od->v_len = 2; + break; + case 5: /* ifSpeed */ + case 21: /* ifOutQLen */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE); + od->v_len = sizeof(u32_t); + break; + case 6: /* ifPhysAddress */ + { + struct netif *netif; + + snmp_ifindextonetif(ident[1], &netif); + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); + od->v_len = netif->hwaddr_len; + } + break; + case 7: /* ifAdminStatus */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + case 9: /* ifLastChange */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS); + od->v_len = sizeof(u32_t); + break; + case 10: /* ifInOctets */ + case 11: /* ifInUcastPkts */ + case 12: /* ifInNUcastPkts */ + case 13: /* ifInDiscarts */ + case 14: /* ifInErrors */ + case 15: /* ifInUnkownProtos */ + case 16: /* ifOutOctets */ + case 17: /* ifOutUcastPkts */ + case 18: /* ifOutNUcastPkts */ + case 19: /* ifOutDiscarts */ + case 20: /* ifOutErrors */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER); + od->v_len = sizeof(u32_t); + break; + case 22: /* ifSpecific */ + /** @note returning zeroDotZero (0.0) no media specific MIB support */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID); + od->v_len = ifspecific.len * sizeof(s32_t); + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ifentry_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + }; + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ifentry_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +/** + * Returns ifentry object value. + * + * @param ident_len the address length (2) + * @param ident points to objectname.0 (object id trailer) + * @param len return value space (in bytes) + * @param value points to (varbind) space to copy value into. + */ +static void +ifentry_get_value(struct obj_def *od, u16_t len, void *value) +{ + struct netif *netif; + u8_t id; + + snmp_ifindextonetif(od->id_inst_ptr[1], &netif); + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 1: /* ifIndex */ + { + s32_t *sint_ptr = (s32_t*)value; + *sint_ptr = od->id_inst_ptr[1]; + } + break; + case 2: /* ifDescr */ + MEMCPY(value, netif->name, len); + break; + case 3: /* ifType */ + { + s32_t *sint_ptr = (s32_t*)value; + *sint_ptr = netif->link_type; + } + break; + case 4: /* ifMtu */ + { + s32_t *sint_ptr = (s32_t*)value; + *sint_ptr = netif->mtu; + } + break; + case 5: /* ifSpeed */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = netif->link_speed; + } + break; + case 6: /* ifPhysAddress */ + MEMCPY(value, netif->hwaddr, len); + break; + case 7: /* ifAdminStatus */ + { + s32_t *sint_ptr = (s32_t*)value; + if (netif_is_up(netif)) + { + if (netif_is_link_up(netif)) + { + *sint_ptr = 1; /* up */ + } + else + { + *sint_ptr = 7; /* lowerLayerDown */ + } + } + else + { + *sint_ptr = 2; /* down */ + } + } + break; + case 8: /* ifOperStatus */ + { + s32_t *sint_ptr = (s32_t*)value; + if (netif_is_up(netif)) + { + *sint_ptr = 1; + } + else + { + *sint_ptr = 2; + } + } + break; + case 9: /* ifLastChange */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = netif->ts; + } + break; + case 10: /* ifInOctets */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = netif->ifinoctets; + } + break; + case 11: /* ifInUcastPkts */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = netif->ifinucastpkts; + } + break; + case 12: /* ifInNUcastPkts */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = netif->ifinnucastpkts; + } + break; + case 13: /* ifInDiscarts */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = netif->ifindiscards; + } + break; + case 14: /* ifInErrors */ + case 15: /* ifInUnkownProtos */ + /** @todo add these counters! */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = 0; + } + break; + case 16: /* ifOutOctets */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = netif->ifoutoctets; + } + break; + case 17: /* ifOutUcastPkts */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = netif->ifoutucastpkts; + } + break; + case 18: /* ifOutNUcastPkts */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = netif->ifoutnucastpkts; + } + break; + case 19: /* ifOutDiscarts */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = netif->ifoutdiscards; + } + break; + case 20: /* ifOutErrors */ + /** @todo add this counter! */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = 0; + } + break; + case 21: /* ifOutQLen */ + /** @todo figure out if this must be 0 (no queue) or 1? */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = 0; + } + break; + case 22: /* ifSpecific */ + MEMCPY(value, ifspecific.id, len); + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ifentry_get_value(): unknown id: %d\n", id)); + break; + }; +} + +#if !SNMP_SAFE_REQUESTS +static u8_t +ifentry_set_test(struct obj_def *od, u16_t len, void *value) +{ + struct netif *netif; + u8_t id, set_ok; + LWIP_UNUSED_ARG(len); + + set_ok = 0; + snmp_ifindextonetif(od->id_inst_ptr[1], &netif); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 7: /* ifAdminStatus */ + { + s32_t *sint_ptr = (s32_t*)value; + if (*sint_ptr == 1 || *sint_ptr == 2) + set_ok = 1; + } + break; + } + return set_ok; +} + +static void +ifentry_set_value(struct obj_def *od, u16_t len, void *value) +{ + struct netif *netif; + u8_t id; + LWIP_UNUSED_ARG(len); + + snmp_ifindextonetif(od->id_inst_ptr[1], &netif); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 7: /* ifAdminStatus */ + { + s32_t *sint_ptr = (s32_t*)value; + if (*sint_ptr == 1) + { + netif_set_up(netif); + } + else if (*sint_ptr == 2) + { + netif_set_down(netif); + } + } + break; + } +} +#endif /* SNMP_SAFE_REQUESTS */ + +/** + * Returns atentry object definitions. + * + * @param ident_len the address length (6) + * @param ident points to objectname.atifindex.atnetaddress + * @param od points to object definition. + */ +static void +atentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + /* return to object name, adding index depth (5) */ + ident_len += 5; + ident -= 5; + + if (ident_len == 6) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + switch (ident[0]) + { + case 1: /* atIfIndex */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + case 2: /* atPhysAddress */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); + od->v_len = 6; /** @todo try to use netif::hwaddr_len */ + break; + case 3: /* atNetAddress */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR); + od->v_len = 4; + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("atentry_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + } + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("atentry_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +atentry_get_value(struct obj_def *od, u16_t len, void *value) +{ +#if LWIP_ARP + u8_t id; + struct eth_addr* ethaddr_ret; + ip_addr_t* ipaddr_ret; +#endif /* LWIP_ARP */ + ip_addr_t ip; + struct netif *netif; + + LWIP_UNUSED_ARG(len); + LWIP_UNUSED_ARG(value);/* if !LWIP_ARP */ + + snmp_ifindextonetif(od->id_inst_ptr[1], &netif); + snmp_oidtoip(&od->id_inst_ptr[2], &ip); + +#if LWIP_ARP /** @todo implement a netif_find_addr */ + if (etharp_find_addr(netif, &ip, ðaddr_ret, &ipaddr_ret) > -1) + { + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 1: /* atIfIndex */ + { + s32_t *sint_ptr = (s32_t*)value; + *sint_ptr = od->id_inst_ptr[1]; + } + break; + case 2: /* atPhysAddress */ + { + struct eth_addr *dst = (struct eth_addr*)value; + + *dst = *ethaddr_ret; + } + break; + case 3: /* atNetAddress */ + { + ip_addr_t *dst = (ip_addr_t*)value; + + *dst = *ipaddr_ret; + } + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("atentry_get_value(): unknown id: %d\n", id)); + break; + } + } +#endif /* LWIP_ARP */ +} + +static void +ip_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + u8_t id; + + /* return to object name, adding index depth (1) */ + ident_len += 1; + ident -= 1; + if (ident_len == 2) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff)); + id = (u8_t)ident[0]; + LWIP_DEBUGF(SNMP_MIB_DEBUG,("get_object_def ip.%"U16_F".0\n",(u16_t)id)); + switch (id) + { + case 1: /* ipForwarding */ + case 2: /* ipDefaultTTL */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + case 3: /* ipInReceives */ + case 4: /* ipInHdrErrors */ + case 5: /* ipInAddrErrors */ + case 6: /* ipForwDatagrams */ + case 7: /* ipInUnknownProtos */ + case 8: /* ipInDiscards */ + case 9: /* ipInDelivers */ + case 10: /* ipOutRequests */ + case 11: /* ipOutDiscards */ + case 12: /* ipOutNoRoutes */ + case 14: /* ipReasmReqds */ + case 15: /* ipReasmOKs */ + case 16: /* ipReasmFails */ + case 17: /* ipFragOKs */ + case 18: /* ipFragFails */ + case 19: /* ipFragCreates */ + case 23: /* ipRoutingDiscards */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER); + od->v_len = sizeof(u32_t); + break; + case 13: /* ipReasmTimeout */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + }; + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +ip_get_value(struct obj_def *od, u16_t len, void *value) +{ + u8_t id; + + LWIP_UNUSED_ARG(len); + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 1: /* ipForwarding */ + { + s32_t *sint_ptr = (s32_t*)value; +#if IP_FORWARD + /* forwarding */ + *sint_ptr = 1; +#else + /* not-forwarding */ + *sint_ptr = 2; +#endif + } + break; + case 2: /* ipDefaultTTL */ + { + s32_t *sint_ptr = (s32_t*)value; + *sint_ptr = IP_DEFAULT_TTL; + } + break; + case 3: /* ipInReceives */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipinreceives; + } + break; + case 4: /* ipInHdrErrors */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipinhdrerrors; + } + break; + case 5: /* ipInAddrErrors */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipinaddrerrors; + } + break; + case 6: /* ipForwDatagrams */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipforwdatagrams; + } + break; + case 7: /* ipInUnknownProtos */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipinunknownprotos; + } + break; + case 8: /* ipInDiscards */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipindiscards; + } + break; + case 9: /* ipInDelivers */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipindelivers; + } + break; + case 10: /* ipOutRequests */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipoutrequests; + } + break; + case 11: /* ipOutDiscards */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipoutdiscards; + } + break; + case 12: /* ipOutNoRoutes */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipoutnoroutes; + } + break; + case 13: /* ipReasmTimeout */ + { + s32_t *sint_ptr = (s32_t*)value; +#if IP_REASSEMBLY + *sint_ptr = IP_REASS_MAXAGE; +#else + *sint_ptr = 0; +#endif + } + break; + case 14: /* ipReasmReqds */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipreasmreqds; + } + break; + case 15: /* ipReasmOKs */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipreasmoks; + } + break; + case 16: /* ipReasmFails */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipreasmfails; + } + break; + case 17: /* ipFragOKs */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipfragoks; + } + break; + case 18: /* ipFragFails */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipfragfails; + } + break; + case 19: /* ipFragCreates */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = ipfragcreates; + } + break; + case 23: /* ipRoutingDiscards */ + /** @todo can lwIP discard routes at all?? hardwire this to 0?? */ + { + u32_t *uint_ptr = (u32_t*)value; + *uint_ptr = iproutingdiscards; + } + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_get_value(): unknown id: %d\n", id)); + break; + }; +} + +/** + * Test ip object value before setting. + * + * @param od is the object definition + * @param len return value space (in bytes) + * @param value points to (varbind) space to copy value from. + * + * @note we allow set if the value matches the hardwired value, + * otherwise return badvalue. + */ +static u8_t +ip_set_test(struct obj_def *od, u16_t len, void *value) +{ + u8_t id, set_ok; + s32_t *sint_ptr = (s32_t*)value; + + LWIP_UNUSED_ARG(len); + set_ok = 0; + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 1: /* ipForwarding */ +#if IP_FORWARD + /* forwarding */ + if (*sint_ptr == 1) +#else + /* not-forwarding */ + if (*sint_ptr == 2) +#endif + { + set_ok = 1; + } + break; + case 2: /* ipDefaultTTL */ + if (*sint_ptr == IP_DEFAULT_TTL) + { + set_ok = 1; + } + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_set_test(): unknown id: %d\n", id)); + break; + }; + return set_ok; +} + +static void +ip_addrentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + /* return to object name, adding index depth (4) */ + ident_len += 4; + ident -= 4; + + if (ident_len == 5) + { + u8_t id; + + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff)); + id = (u8_t)ident[0]; + switch (id) + { + case 1: /* ipAdEntAddr */ + case 3: /* ipAdEntNetMask */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR); + od->v_len = 4; + break; + case 2: /* ipAdEntIfIndex */ + case 4: /* ipAdEntBcastAddr */ + case 5: /* ipAdEntReasmMaxSize */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_addrentry_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + } + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_addrentry_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +ip_addrentry_get_value(struct obj_def *od, u16_t len, void *value) +{ + u8_t id; + u16_t ifidx; + ip_addr_t ip; + struct netif *netif = netif_list; + + LWIP_UNUSED_ARG(len); + snmp_oidtoip(&od->id_inst_ptr[1], &ip); + ifidx = 0; + while ((netif != NULL) && !ip_addr_cmp(&ip, &netif->ip_addr)) + { + netif = netif->next; + ifidx++; + } + + if (netif != NULL) + { + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 1: /* ipAdEntAddr */ + { + ip_addr_t *dst = (ip_addr_t*)value; + *dst = netif->ip_addr; + } + break; + case 2: /* ipAdEntIfIndex */ + { + s32_t *sint_ptr = (s32_t*)value; + *sint_ptr = ifidx + 1; + } + break; + case 3: /* ipAdEntNetMask */ + { + ip_addr_t *dst = (ip_addr_t*)value; + *dst = netif->netmask; + } + break; + case 4: /* ipAdEntBcastAddr */ + { + s32_t *sint_ptr = (s32_t*)value; + + /* lwIP oddity, there's no broadcast + address in the netif we can rely on */ + *sint_ptr = IPADDR_BROADCAST & 1; + } + break; + case 5: /* ipAdEntReasmMaxSize */ + { + s32_t *sint_ptr = (s32_t*)value; +#if IP_REASSEMBLY + /* @todo The theoretical maximum is IP_REASS_MAX_PBUFS * size of the pbufs, + * but only if receiving one fragmented packet at a time. + * The current solution is to calculate for 2 simultaneous packets... + */ + *sint_ptr = (IP_HLEN + ((IP_REASS_MAX_PBUFS/2) * + (PBUF_POOL_BUFSIZE - PBUF_LINK_HLEN - IP_HLEN))); +#else + /** @todo returning MTU would be a bad thing and + returning a wild guess like '576' isn't good either */ + *sint_ptr = 0; +#endif + } + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_addrentry_get_value(): unknown id: %d\n", id)); + break; + } + } +} + +/** + * @note + * lwIP IP routing is currently using the network addresses in netif_list. + * if no suitable network IP is found in netif_list, the default_netif is used. + */ +static void +ip_rteentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + u8_t id; + + /* return to object name, adding index depth (4) */ + ident_len += 4; + ident -= 4; + + if (ident_len == 5) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff)); + id = (u8_t)ident[0]; + switch (id) + { + case 1: /* ipRouteDest */ + case 7: /* ipRouteNextHop */ + case 11: /* ipRouteMask */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR); + od->v_len = 4; + break; + case 2: /* ipRouteIfIndex */ + case 3: /* ipRouteMetric1 */ + case 4: /* ipRouteMetric2 */ + case 5: /* ipRouteMetric3 */ + case 6: /* ipRouteMetric4 */ + case 8: /* ipRouteType */ + case 10: /* ipRouteAge */ + case 12: /* ipRouteMetric5 */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + case 9: /* ipRouteProto */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + case 13: /* ipRouteInfo */ + /** @note returning zeroDotZero (0.0) no routing protocol specific MIB */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID); + od->v_len = iprouteinfo.len * sizeof(s32_t); + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_rteentry_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + } + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_rteentry_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +ip_rteentry_get_value(struct obj_def *od, u16_t len, void *value) +{ + struct netif *netif; + ip_addr_t dest; + s32_t *ident; + u8_t id; + + ident = od->id_inst_ptr; + snmp_oidtoip(&ident[1], &dest); + + if (ip_addr_isany(&dest)) + { + /* ip_route() uses default netif for default route */ + netif = netif_default; + } + else + { + /* not using ip_route(), need exact match! */ + netif = netif_list; + while ((netif != NULL) && + !ip_addr_netcmp(&dest, &(netif->ip_addr), &(netif->netmask)) ) + { + netif = netif->next; + } + } + if (netif != NULL) + { + LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff)); + id = (u8_t)ident[0]; + switch (id) + { + case 1: /* ipRouteDest */ + { + ip_addr_t *dst = (ip_addr_t*)value; + + if (ip_addr_isany(&dest)) + { + /* default rte has 0.0.0.0 dest */ + ip_addr_set_zero(dst); + } + else + { + /* netifs have netaddress dest */ + ip_addr_get_network(dst, &netif->ip_addr, &netif->netmask); + } + } + break; + case 2: /* ipRouteIfIndex */ + { + s32_t *sint_ptr = (s32_t*)value; + + snmp_netiftoifindex(netif, sint_ptr); + } + break; + case 3: /* ipRouteMetric1 */ + { + s32_t *sint_ptr = (s32_t*)value; + + if (ip_addr_isany(&dest)) + { + /* default rte has metric 1 */ + *sint_ptr = 1; + } + else + { + /* other rtes have metric 0 */ + *sint_ptr = 0; + } + } + break; + case 4: /* ipRouteMetric2 */ + case 5: /* ipRouteMetric3 */ + case 6: /* ipRouteMetric4 */ + case 12: /* ipRouteMetric5 */ + { + s32_t *sint_ptr = (s32_t*)value; + /* not used */ + *sint_ptr = -1; + } + break; + case 7: /* ipRouteNextHop */ + { + ip_addr_t *dst = (ip_addr_t*)value; + + if (ip_addr_isany(&dest)) + { + /* default rte: gateway */ + *dst = netif->gw; + } + else + { + /* other rtes: netif ip_addr */ + *dst = netif->ip_addr; + } + } + break; + case 8: /* ipRouteType */ + { + s32_t *sint_ptr = (s32_t*)value; + + if (ip_addr_isany(&dest)) + { + /* default rte is indirect */ + *sint_ptr = 4; + } + else + { + /* other rtes are direct */ + *sint_ptr = 3; + } + } + break; + case 9: /* ipRouteProto */ + { + s32_t *sint_ptr = (s32_t*)value; + /* locally defined routes */ + *sint_ptr = 2; + } + break; + case 10: /* ipRouteAge */ + { + s32_t *sint_ptr = (s32_t*)value; + /** @todo (sysuptime - timestamp last change) / 100 + @see snmp_insert_iprteidx_tree() */ + *sint_ptr = 0; + } + break; + case 11: /* ipRouteMask */ + { + ip_addr_t *dst = (ip_addr_t*)value; + + if (ip_addr_isany(&dest)) + { + /* default rte use 0.0.0.0 mask */ + ip_addr_set_zero(dst); + } + else + { + /* other rtes use netmask */ + *dst = netif->netmask; + } + } + break; + case 13: /* ipRouteInfo */ + MEMCPY(value, iprouteinfo.id, len); + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_rteentry_get_value(): unknown id: %d\n", id)); + break; + } + } +} + +static void +ip_ntomentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + /* return to object name, adding index depth (5) */ + ident_len += 5; + ident -= 5; + + if (ident_len == 6) + { + u8_t id; + + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff)); + id = (u8_t)ident[0]; + switch (id) + { + case 1: /* ipNetToMediaIfIndex */ + case 4: /* ipNetToMediaType */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + case 2: /* ipNetToMediaPhysAddress */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); + od->v_len = 6; /** @todo try to use netif::hwaddr_len */ + break; + case 3: /* ipNetToMediaNetAddress */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR); + od->v_len = 4; + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_ntomentry_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + } + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_ntomentry_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +ip_ntomentry_get_value(struct obj_def *od, u16_t len, void *value) +{ +#if LWIP_ARP + u8_t id; + struct eth_addr* ethaddr_ret; + ip_addr_t* ipaddr_ret; +#endif /* LWIP_ARP */ + ip_addr_t ip; + struct netif *netif; + + LWIP_UNUSED_ARG(len); + LWIP_UNUSED_ARG(value);/* if !LWIP_ARP */ + + snmp_ifindextonetif(od->id_inst_ptr[1], &netif); + snmp_oidtoip(&od->id_inst_ptr[2], &ip); + +#if LWIP_ARP /** @todo implement a netif_find_addr */ + if (etharp_find_addr(netif, &ip, ðaddr_ret, &ipaddr_ret) > -1) + { + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 1: /* ipNetToMediaIfIndex */ + { + s32_t *sint_ptr = (s32_t*)value; + *sint_ptr = od->id_inst_ptr[1]; + } + break; + case 2: /* ipNetToMediaPhysAddress */ + { + struct eth_addr *dst = (struct eth_addr*)value; + + *dst = *ethaddr_ret; + } + break; + case 3: /* ipNetToMediaNetAddress */ + { + ip_addr_t *dst = (ip_addr_t*)value; + + *dst = *ipaddr_ret; + } + break; + case 4: /* ipNetToMediaType */ + { + s32_t *sint_ptr = (s32_t*)value; + /* dynamic (?) */ + *sint_ptr = 3; + } + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_ntomentry_get_value(): unknown id: %d\n", id)); + break; + } + } +#endif /* LWIP_ARP */ +} + +static void +icmp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + /* return to object name, adding index depth (1) */ + ident_len += 1; + ident -= 1; + if ((ident_len == 2) && + (ident[0] > 0) && (ident[0] < 27)) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER); + od->v_len = sizeof(u32_t); + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("icmp_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +icmp_get_value(struct obj_def *od, u16_t len, void *value) +{ + u32_t *uint_ptr = (u32_t*)value; + u8_t id; + + LWIP_UNUSED_ARG(len); + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 1: /* icmpInMsgs */ + *uint_ptr = icmpinmsgs; + break; + case 2: /* icmpInErrors */ + *uint_ptr = icmpinerrors; + break; + case 3: /* icmpInDestUnreachs */ + *uint_ptr = icmpindestunreachs; + break; + case 4: /* icmpInTimeExcds */ + *uint_ptr = icmpintimeexcds; + break; + case 5: /* icmpInParmProbs */ + *uint_ptr = icmpinparmprobs; + break; + case 6: /* icmpInSrcQuenchs */ + *uint_ptr = icmpinsrcquenchs; + break; + case 7: /* icmpInRedirects */ + *uint_ptr = icmpinredirects; + break; + case 8: /* icmpInEchos */ + *uint_ptr = icmpinechos; + break; + case 9: /* icmpInEchoReps */ + *uint_ptr = icmpinechoreps; + break; + case 10: /* icmpInTimestamps */ + *uint_ptr = icmpintimestamps; + break; + case 11: /* icmpInTimestampReps */ + *uint_ptr = icmpintimestampreps; + break; + case 12: /* icmpInAddrMasks */ + *uint_ptr = icmpinaddrmasks; + break; + case 13: /* icmpInAddrMaskReps */ + *uint_ptr = icmpinaddrmaskreps; + break; + case 14: /* icmpOutMsgs */ + *uint_ptr = icmpoutmsgs; + break; + case 15: /* icmpOutErrors */ + *uint_ptr = icmpouterrors; + break; + case 16: /* icmpOutDestUnreachs */ + *uint_ptr = icmpoutdestunreachs; + break; + case 17: /* icmpOutTimeExcds */ + *uint_ptr = icmpouttimeexcds; + break; + case 18: /* icmpOutParmProbs */ + *uint_ptr = icmpoutparmprobs; + break; + case 19: /* icmpOutSrcQuenchs */ + *uint_ptr = icmpoutsrcquenchs; + break; + case 20: /* icmpOutRedirects */ + *uint_ptr = icmpoutredirects; + break; + case 21: /* icmpOutEchos */ + *uint_ptr = icmpoutechos; + break; + case 22: /* icmpOutEchoReps */ + *uint_ptr = icmpoutechoreps; + break; + case 23: /* icmpOutTimestamps */ + *uint_ptr = icmpouttimestamps; + break; + case 24: /* icmpOutTimestampReps */ + *uint_ptr = icmpouttimestampreps; + break; + case 25: /* icmpOutAddrMasks */ + *uint_ptr = icmpoutaddrmasks; + break; + case 26: /* icmpOutAddrMaskReps */ + *uint_ptr = icmpoutaddrmaskreps; + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("icmp_get_value(): unknown id: %d\n", id)); + break; + } +} + +#if LWIP_TCP +/** @todo tcp grp */ +static void +tcp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + u8_t id; + + /* return to object name, adding index depth (1) */ + ident_len += 1; + ident -= 1; + if (ident_len == 2) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff)); + id = (u8_t)ident[0]; + LWIP_DEBUGF(SNMP_MIB_DEBUG,("get_object_def tcp.%"U16_F".0\n",(u16_t)id)); + + switch (id) + { + case 1: /* tcpRtoAlgorithm */ + case 2: /* tcpRtoMin */ + case 3: /* tcpRtoMax */ + case 4: /* tcpMaxConn */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + case 5: /* tcpActiveOpens */ + case 6: /* tcpPassiveOpens */ + case 7: /* tcpAttemptFails */ + case 8: /* tcpEstabResets */ + case 10: /* tcpInSegs */ + case 11: /* tcpOutSegs */ + case 12: /* tcpRetransSegs */ + case 14: /* tcpInErrs */ + case 15: /* tcpOutRsts */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER); + od->v_len = sizeof(u32_t); + break; + case 9: /* tcpCurrEstab */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE); + od->v_len = sizeof(u32_t); + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("tcp_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + }; + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("tcp_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +tcp_get_value(struct obj_def *od, u16_t len, void *value) +{ + u32_t *uint_ptr = (u32_t*)value; + s32_t *sint_ptr = (s32_t*)value; + u8_t id; + + LWIP_UNUSED_ARG(len); + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 1: /* tcpRtoAlgorithm, vanj(4) */ + *sint_ptr = 4; + break; + case 2: /* tcpRtoMin */ + /* @todo not the actual value, a guess, + needs to be calculated */ + *sint_ptr = 1000; + break; + case 3: /* tcpRtoMax */ + /* @todo not the actual value, a guess, + needs to be calculated */ + *sint_ptr = 60000; + break; + case 4: /* tcpMaxConn */ + *sint_ptr = MEMP_NUM_TCP_PCB; + break; + case 5: /* tcpActiveOpens */ + *uint_ptr = tcpactiveopens; + break; + case 6: /* tcpPassiveOpens */ + *uint_ptr = tcppassiveopens; + break; + case 7: /* tcpAttemptFails */ + *uint_ptr = tcpattemptfails; + break; + case 8: /* tcpEstabResets */ + *uint_ptr = tcpestabresets; + break; + case 9: /* tcpCurrEstab */ + { + u16_t tcpcurrestab = 0; + struct tcp_pcb *pcb = tcp_active_pcbs; + while (pcb != NULL) + { + if ((pcb->state == ESTABLISHED) || + (pcb->state == CLOSE_WAIT)) + { + tcpcurrestab++; + } + pcb = pcb->next; + } + *uint_ptr = tcpcurrestab; + } + break; + case 10: /* tcpInSegs */ + *uint_ptr = tcpinsegs; + break; + case 11: /* tcpOutSegs */ + *uint_ptr = tcpoutsegs; + break; + case 12: /* tcpRetransSegs */ + *uint_ptr = tcpretranssegs; + break; + case 14: /* tcpInErrs */ + *uint_ptr = tcpinerrs; + break; + case 15: /* tcpOutRsts */ + *uint_ptr = tcpoutrsts; + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("tcp_get_value(): unknown id: %d\n", id)); + break; + } +} +#ifdef THIS_SEEMS_UNUSED +static void +tcpconnentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + /* return to object name, adding index depth (10) */ + ident_len += 10; + ident -= 10; + + if (ident_len == 11) + { + u8_t id; + + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + id = ident[0]; + LWIP_DEBUGF(SNMP_MIB_DEBUG,("get_object_def tcp.%"U16_F".0\n",(u16_t)id)); + + switch (id) + { + case 1: /* tcpConnState */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + case 2: /* tcpConnLocalAddress */ + case 4: /* tcpConnRemAddress */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR); + od->v_len = 4; + break; + case 3: /* tcpConnLocalPort */ + case 5: /* tcpConnRemPort */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("tcpconnentry_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + }; + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("tcpconnentry_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +tcpconnentry_get_value(struct obj_def *od, u16_t len, void *value) +{ + ip_addr_t lip, rip; + u16_t lport, rport; + s32_t *ident; + + ident = od->id_inst_ptr; + snmp_oidtoip(&ident[1], &lip); + lport = ident[5]; + snmp_oidtoip(&ident[6], &rip); + rport = ident[10]; + + /** @todo find matching PCB */ +} +#endif /* if 0 */ +#endif + +static void +udp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + /* return to object name, adding index depth (1) */ + ident_len += 1; + ident -= 1; + if ((ident_len == 2) && + (ident[0] > 0) && (ident[0] < 6)) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER); + od->v_len = sizeof(u32_t); + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("udp_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +udp_get_value(struct obj_def *od, u16_t len, void *value) +{ + u32_t *uint_ptr = (u32_t*)value; + u8_t id; + + LWIP_UNUSED_ARG(len); + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 1: /* udpInDatagrams */ + *uint_ptr = udpindatagrams; + break; + case 2: /* udpNoPorts */ + *uint_ptr = udpnoports; + break; + case 3: /* udpInErrors */ + *uint_ptr = udpinerrors; + break; + case 4: /* udpOutDatagrams */ + *uint_ptr = udpoutdatagrams; + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("udp_get_value(): unknown id: %d\n", id)); + break; + } +} + +static void +udpentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + /* return to object name, adding index depth (5) */ + ident_len += 5; + ident -= 5; + + if (ident_len == 6) + { + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + switch (ident[0]) + { + case 1: /* udpLocalAddress */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR); + od->v_len = 4; + break; + case 2: /* udpLocalPort */ + od->instance = MIB_OBJECT_TAB; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("udpentry_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + } + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("udpentry_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +udpentry_get_value(struct obj_def *od, u16_t len, void *value) +{ + u8_t id; + struct udp_pcb *pcb; + ipX_addr_t ip; + u16_t port; + + LWIP_UNUSED_ARG(len); + snmp_oidtoip(&od->id_inst_ptr[1], (ip_addr_t*)&ip); + LWIP_ASSERT("invalid port", (od->id_inst_ptr[5] >= 0) && (od->id_inst_ptr[5] <= 0xffff)); + port = (u16_t)od->id_inst_ptr[5]; + + pcb = udp_pcbs; + while ((pcb != NULL) && + !(ipX_addr_cmp(0, &pcb->local_ip, &ip) && + (pcb->local_port == port))) + { + pcb = pcb->next; + } + + if (pcb != NULL) + { + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 1: /* udpLocalAddress */ + { + ipX_addr_t *dst = (ipX_addr_t*)value; + ipX_addr_copy(0, *dst, pcb->local_ip); + } + break; + case 2: /* udpLocalPort */ + { + s32_t *sint_ptr = (s32_t*)value; + *sint_ptr = pcb->local_port; + } + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("udpentry_get_value(): unknown id: %d\n", id)); + break; + } + } +} + +static void +snmp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) +{ + /* return to object name, adding index depth (1) */ + ident_len += 1; + ident -= 1; + if (ident_len == 2) + { + u8_t id; + + od->id_inst_len = ident_len; + od->id_inst_ptr = ident; + + LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff)); + id = (u8_t)ident[0]; + switch (id) + { + case 1: /* snmpInPkts */ + case 2: /* snmpOutPkts */ + case 3: /* snmpInBadVersions */ + case 4: /* snmpInBadCommunityNames */ + case 5: /* snmpInBadCommunityUses */ + case 6: /* snmpInASNParseErrs */ + case 8: /* snmpInTooBigs */ + case 9: /* snmpInNoSuchNames */ + case 10: /* snmpInBadValues */ + case 11: /* snmpInReadOnlys */ + case 12: /* snmpInGenErrs */ + case 13: /* snmpInTotalReqVars */ + case 14: /* snmpInTotalSetVars */ + case 15: /* snmpInGetRequests */ + case 16: /* snmpInGetNexts */ + case 17: /* snmpInSetRequests */ + case 18: /* snmpInGetResponses */ + case 19: /* snmpInTraps */ + case 20: /* snmpOutTooBigs */ + case 21: /* snmpOutNoSuchNames */ + case 22: /* snmpOutBadValues */ + case 24: /* snmpOutGenErrs */ + case 25: /* snmpOutGetRequests */ + case 26: /* snmpOutGetNexts */ + case 27: /* snmpOutSetRequests */ + case 28: /* snmpOutGetResponses */ + case 29: /* snmpOutTraps */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_ONLY; + od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER); + od->v_len = sizeof(u32_t); + break; + case 30: /* snmpEnableAuthenTraps */ + od->instance = MIB_OBJECT_SCALAR; + od->access = MIB_OBJECT_READ_WRITE; + od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); + od->v_len = sizeof(s32_t); + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_get_object_def: no such object\n")); + od->instance = MIB_OBJECT_NONE; + break; + }; + } + else + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_get_object_def: no scalar\n")); + od->instance = MIB_OBJECT_NONE; + } +} + +static void +snmp_get_value(struct obj_def *od, u16_t len, void *value) +{ + u32_t *uint_ptr = (u32_t*)value; + u8_t id; + + LWIP_UNUSED_ARG(len); + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + switch (id) + { + case 1: /* snmpInPkts */ + *uint_ptr = snmpinpkts; + break; + case 2: /* snmpOutPkts */ + *uint_ptr = snmpoutpkts; + break; + case 3: /* snmpInBadVersions */ + *uint_ptr = snmpinbadversions; + break; + case 4: /* snmpInBadCommunityNames */ + *uint_ptr = snmpinbadcommunitynames; + break; + case 5: /* snmpInBadCommunityUses */ + *uint_ptr = snmpinbadcommunityuses; + break; + case 6: /* snmpInASNParseErrs */ + *uint_ptr = snmpinasnparseerrs; + break; + case 8: /* snmpInTooBigs */ + *uint_ptr = snmpintoobigs; + break; + case 9: /* snmpInNoSuchNames */ + *uint_ptr = snmpinnosuchnames; + break; + case 10: /* snmpInBadValues */ + *uint_ptr = snmpinbadvalues; + break; + case 11: /* snmpInReadOnlys */ + *uint_ptr = snmpinreadonlys; + break; + case 12: /* snmpInGenErrs */ + *uint_ptr = snmpingenerrs; + break; + case 13: /* snmpInTotalReqVars */ + *uint_ptr = snmpintotalreqvars; + break; + case 14: /* snmpInTotalSetVars */ + *uint_ptr = snmpintotalsetvars; + break; + case 15: /* snmpInGetRequests */ + *uint_ptr = snmpingetrequests; + break; + case 16: /* snmpInGetNexts */ + *uint_ptr = snmpingetnexts; + break; + case 17: /* snmpInSetRequests */ + *uint_ptr = snmpinsetrequests; + break; + case 18: /* snmpInGetResponses */ + *uint_ptr = snmpingetresponses; + break; + case 19: /* snmpInTraps */ + *uint_ptr = snmpintraps; + break; + case 20: /* snmpOutTooBigs */ + *uint_ptr = snmpouttoobigs; + break; + case 21: /* snmpOutNoSuchNames */ + *uint_ptr = snmpoutnosuchnames; + break; + case 22: /* snmpOutBadValues */ + *uint_ptr = snmpoutbadvalues; + break; + case 24: /* snmpOutGenErrs */ + *uint_ptr = snmpoutgenerrs; + break; + case 25: /* snmpOutGetRequests */ + *uint_ptr = snmpoutgetrequests; + break; + case 26: /* snmpOutGetNexts */ + *uint_ptr = snmpoutgetnexts; + break; + case 27: /* snmpOutSetRequests */ + *uint_ptr = snmpoutsetrequests; + break; + case 28: /* snmpOutGetResponses */ + *uint_ptr = snmpoutgetresponses; + break; + case 29: /* snmpOutTraps */ + *uint_ptr = snmpouttraps; + break; + case 30: /* snmpEnableAuthenTraps */ + *uint_ptr = *snmpenableauthentraps_ptr; + break; + default: + LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_get_value(): unknown id: %d\n", id)); + break; + }; +} + +/** + * Test snmp object value before setting. + * + * @param od is the object definition + * @param len return value space (in bytes) + * @param value points to (varbind) space to copy value from. + */ +static u8_t +snmp_set_test(struct obj_def *od, u16_t len, void *value) +{ + u8_t id, set_ok; + + LWIP_UNUSED_ARG(len); + set_ok = 0; + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + if (id == 30) + { + /* snmpEnableAuthenTraps */ + s32_t *sint_ptr = (s32_t*)value; + + if (snmpenableauthentraps_ptr != &snmpenableauthentraps_default) + { + /* we should have writable non-volatile mem here */ + if ((*sint_ptr == 1) || (*sint_ptr == 2)) + { + set_ok = 1; + } + } + else + { + /* const or hardwired value */ + if (*sint_ptr == snmpenableauthentraps_default) + { + set_ok = 1; + } + } + } + return set_ok; +} + +static void +snmp_set_value(struct obj_def *od, u16_t len, void *value) +{ + u8_t id; + + LWIP_UNUSED_ARG(len); + LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); + id = (u8_t)od->id_inst_ptr[0]; + if (id == 30) + { + /* snmpEnableAuthenTraps */ + /* @todo @fixme: which kind of pointer is 'value'? s32_t or u8_t??? */ + u8_t *ptr = (u8_t*)value; + *snmpenableauthentraps_ptr = *ptr; + } +} + +#endif /* LWIP_SNMP */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/core/snmp/mib_structs.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/snmp/mib_structs.c new file mode 100644 index 0000000..fa796c5 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/snmp/mib_structs.c @@ -0,0 +1,1175 @@ +/** + * @file + * MIB tree access/construction functions. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * Author: Christiaan Simons + */ + +#include "lwip/opt.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/snmp_structs.h" +#include "lwip/memp.h" +#include "lwip/netif.h" + +/** .iso.org.dod.internet address prefix, @see snmp_iso_*() */ +const s32_t prefix[4] = {1, 3, 6, 1}; + +#define NODE_STACK_SIZE (LWIP_SNMP_OBJ_ID_LEN) +/** node stack entry (old news?) */ +struct nse +{ + /** right child */ + struct mib_node* r_ptr; + /** right child identifier */ + s32_t r_id; + /** right child next level */ + u8_t r_nl; +}; +static u8_t node_stack_cnt; +static struct nse node_stack[NODE_STACK_SIZE]; +const struct nse node_null = {NULL, 0, 0}; + +/** + * Pushes nse struct onto stack. + */ +static void +push_node(const struct nse* node) +{ + LWIP_ASSERT("node_stack_cnt < NODE_STACK_SIZE",node_stack_cnt < NODE_STACK_SIZE); + LWIP_DEBUGF(SNMP_MIB_DEBUG,("push_node() node=%p id=%"S32_F"\n",(void*)(node->r_ptr),node->r_id)); + if (node_stack_cnt < NODE_STACK_SIZE) + { + node_stack[node_stack_cnt] = *node; + node_stack_cnt++; + } +} + +/** + * Pops nse struct from stack. + */ +static void +pop_node(struct nse* node) +{ + if (node_stack_cnt > 0) + { + node_stack_cnt--; + *node = node_stack[node_stack_cnt]; + } + LWIP_DEBUGF(SNMP_MIB_DEBUG,("pop_node() node=%p id=%"S32_F"\n",(void *)(node->r_ptr),node->r_id)); +} + +/** + * Conversion from ifIndex to lwIP netif + * @param ifindex is a s32_t object sub-identifier + * @param netif points to returned netif struct pointer + */ +void +snmp_ifindextonetif(s32_t ifindex, struct netif **netif) +{ + struct netif *nif = netif_list; + s32_t i, ifidx; + + ifidx = ifindex - 1; + i = 0; + while ((nif != NULL) && (i < ifidx)) + { + nif = nif->next; + i++; + } + *netif = nif; +} + +/** + * Conversion from lwIP netif to ifIndex + * @param netif points to a netif struct + * @param ifidx points to s32_t object sub-identifier + */ +void +snmp_netiftoifindex(struct netif *netif, s32_t *ifidx) +{ + struct netif *nif = netif_list; + u16_t i; + + i = 0; + while ((nif != NULL) && (nif != netif)) + { + nif = nif->next; + i++; + } + *ifidx = i+1; +} + +/** + * Conversion from oid to lwIP ip_addr + * @param ident points to s32_t ident[4] input + * @param ip points to output struct + */ +void +snmp_oidtoip(s32_t *ident, ip_addr_t *ip) +{ + IP4_ADDR(ip, ident[0], ident[1], ident[2], ident[3]); +} + +/** + * Conversion from lwIP ip_addr to oid + * @param ip points to input struct + * @param ident points to s32_t ident[4] output + */ +void +snmp_iptooid(ip_addr_t *ip, s32_t *ident) +{ + ident[0] = ip4_addr1(ip); + ident[1] = ip4_addr2(ip); + ident[2] = ip4_addr3(ip); + ident[3] = ip4_addr4(ip); +} + +struct mib_list_node * +snmp_mib_ln_alloc(s32_t id) +{ + struct mib_list_node *ln; + + ln = (struct mib_list_node *)memp_malloc(MEMP_SNMP_NODE); + if (ln != NULL) + { + ln->prev = NULL; + ln->next = NULL; + ln->objid = id; + ln->nptr = NULL; + } + return ln; +} + +void +snmp_mib_ln_free(struct mib_list_node *ln) +{ + memp_free(MEMP_SNMP_NODE, ln); +} + +struct mib_list_rootnode * +snmp_mib_lrn_alloc(void) +{ + struct mib_list_rootnode *lrn; + + lrn = (struct mib_list_rootnode*)memp_malloc(MEMP_SNMP_ROOTNODE); + if (lrn != NULL) + { + lrn->get_object_def = noleafs_get_object_def; + lrn->get_value = noleafs_get_value; + lrn->set_test = noleafs_set_test; + lrn->set_value = noleafs_set_value; + lrn->node_type = MIB_NODE_LR; + lrn->maxlength = 0; + lrn->head = NULL; + lrn->tail = NULL; + lrn->count = 0; + } + return lrn; +} + +void +snmp_mib_lrn_free(struct mib_list_rootnode *lrn) +{ + memp_free(MEMP_SNMP_ROOTNODE, lrn); +} + +/** + * Inserts node in idx list in a sorted + * (ascending order) fashion and + * allocates the node if needed. + * + * @param rn points to the root node + * @param objid is the object sub identifier + * @param insn points to a pointer to the inserted node + * used for constructing the tree. + * @return -1 if failed, 1 if inserted, 2 if present. + */ +s8_t +snmp_mib_node_insert(struct mib_list_rootnode *rn, s32_t objid, struct mib_list_node **insn) +{ + struct mib_list_node *nn; + s8_t insert; + + LWIP_ASSERT("rn != NULL",rn != NULL); + + /* -1 = malloc failure, 0 = not inserted, 1 = inserted, 2 = was present */ + insert = 0; + if (rn->head == NULL) + { + /* empty list, add first node */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("alloc empty list objid==%"S32_F"\n",objid)); + nn = snmp_mib_ln_alloc(objid); + if (nn != NULL) + { + rn->head = nn; + rn->tail = nn; + *insn = nn; + insert = 1; + } + else + { + insert = -1; + } + } + else + { + struct mib_list_node *n; + /* at least one node is present */ + n = rn->head; + while ((n != NULL) && (insert == 0)) + { + if (n->objid == objid) + { + /* node is already there */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("node already there objid==%"S32_F"\n",objid)); + *insn = n; + insert = 2; + } + else if (n->objid < objid) + { + if (n->next == NULL) + { + /* alloc and insert at the tail */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("alloc ins tail objid==%"S32_F"\n",objid)); + nn = snmp_mib_ln_alloc(objid); + if (nn != NULL) + { + nn->next = NULL; + nn->prev = n; + n->next = nn; + rn->tail = nn; + *insn = nn; + insert = 1; + } + else + { + /* insertion failure */ + insert = -1; + } + } + else + { + /* there's more to explore: traverse list */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("traverse list\n")); + n = n->next; + } + } + else + { + /* n->objid > objid */ + /* alloc and insert between n->prev and n */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("alloc ins n->prev, objid==%"S32_F", n\n",objid)); + nn = snmp_mib_ln_alloc(objid); + if (nn != NULL) + { + if (n->prev == NULL) + { + /* insert at the head */ + nn->next = n; + nn->prev = NULL; + rn->head = nn; + n->prev = nn; + } + else + { + /* insert in the middle */ + nn->next = n; + nn->prev = n->prev; + n->prev->next = nn; + n->prev = nn; + } + *insn = nn; + insert = 1; + } + else + { + /* insertion failure */ + insert = -1; + } + } + } + } + if (insert == 1) + { + rn->count += 1; + } + LWIP_ASSERT("insert != 0",insert != 0); + return insert; +} + +/** + * Finds node in idx list and returns deletion mark. + * + * @param rn points to the root node + * @param objid is the object sub identifier + * @param fn returns pointer to found node + * @return 0 if not found, 1 if deletable, + * 2 can't delete (2 or more children), 3 not a list_node + */ +s8_t +snmp_mib_node_find(struct mib_list_rootnode *rn, s32_t objid, struct mib_list_node **fn) +{ + s8_t fc; + struct mib_list_node *n; + + LWIP_ASSERT("rn != NULL",rn != NULL); + n = rn->head; + while ((n != NULL) && (n->objid != objid)) + { + n = n->next; + } + if (n == NULL) + { + fc = 0; + } + else if (n->nptr == NULL) + { + /* leaf, can delete node */ + fc = 1; + } + else + { + struct mib_list_rootnode *r; + + if (n->nptr->node_type == MIB_NODE_LR) + { + r = (struct mib_list_rootnode *)n->nptr; + if (r->count > 1) + { + /* can't delete node */ + fc = 2; + } + else + { + /* count <= 1, can delete node */ + fc = 1; + } + } + else + { + /* other node type */ + fc = 3; + } + } + *fn = n; + return fc; +} + +/** + * Removes node from idx list + * if it has a single child left. + * + * @param rn points to the root node + * @param n points to the node to delete + * @return the nptr to be freed by caller + */ +struct mib_list_rootnode * +snmp_mib_node_delete(struct mib_list_rootnode *rn, struct mib_list_node *n) +{ + struct mib_list_rootnode *next; + + LWIP_ASSERT("rn != NULL",rn != NULL); + LWIP_ASSERT("n != NULL",n != NULL); + + /* caller must remove this sub-tree */ + next = (struct mib_list_rootnode*)(n->nptr); + rn->count -= 1; + + if (n == rn->head) + { + rn->head = n->next; + if (n->next != NULL) + { + /* not last node, new list begin */ + n->next->prev = NULL; + } + } + else if (n == rn->tail) + { + rn->tail = n->prev; + if (n->prev != NULL) + { + /* not last node, new list end */ + n->prev->next = NULL; + } + } + else + { + /* node must be in the middle */ + n->prev->next = n->next; + n->next->prev = n->prev; + } + LWIP_DEBUGF(SNMP_MIB_DEBUG,("free list objid==%"S32_F"\n",n->objid)); + snmp_mib_ln_free(n); + if (rn->count == 0) + { + rn->head = NULL; + rn->tail = NULL; + } + return next; +} + + + +/** + * Searches tree for the supplied (scalar?) object identifier. + * + * @param node points to the root of the tree ('.internet') + * @param ident_len the length of the supplied object identifier + * @param ident points to the array of sub identifiers + * @param np points to the found object instance (return) + * @return pointer to the requested parent (!) node if success, NULL otherwise + */ +struct mib_node * +snmp_search_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct snmp_name_ptr *np) +{ + u8_t node_type, ext_level; + + ext_level = 0; + LWIP_DEBUGF(SNMP_MIB_DEBUG,("node==%p *ident==%"S32_F"\n",(void*)node,*ident)); + while (node != NULL) + { + node_type = node->node_type; + if ((node_type == MIB_NODE_AR) || (node_type == MIB_NODE_RA)) + { + struct mib_array_node *an; + u16_t i; + + if (ident_len > 0) + { + /* array node (internal ROM or RAM, fixed length) */ + an = (struct mib_array_node *)node; + i = 0; + while ((i < an->maxlength) && (an->objid[i] != *ident)) + { + i++; + } + if (i < an->maxlength) + { + /* found it, if available proceed to child, otherwise inspect leaf */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("an->objid[%"U16_F"]==%"S32_F" *ident==%"S32_F"\n",i,an->objid[i],*ident)); + if (an->nptr[i] == NULL) + { + /* a scalar leaf OR table, + inspect remaining instance number / table index */ + np->ident_len = ident_len; + np->ident = ident; + return (struct mib_node*)an; + } + else + { + /* follow next child pointer */ + ident++; + ident_len--; + node = an->nptr[i]; + } + } + else + { + /* search failed, identifier mismatch (nosuchname) */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("an search failed *ident==%"S32_F"\n",*ident)); + return NULL; + } + } + else + { + /* search failed, short object identifier (nosuchname) */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("an search failed, short object identifier\n")); + return NULL; + } + } + else if(node_type == MIB_NODE_LR) + { + struct mib_list_rootnode *lrn; + struct mib_list_node *ln; + + if (ident_len > 0) + { + /* list root node (internal 'RAM', variable length) */ + lrn = (struct mib_list_rootnode *)node; + ln = lrn->head; + /* iterate over list, head to tail */ + while ((ln != NULL) && (ln->objid != *ident)) + { + ln = ln->next; + } + if (ln != NULL) + { + /* found it, proceed to child */; + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ln->objid==%"S32_F" *ident==%"S32_F"\n",ln->objid,*ident)); + if (ln->nptr == NULL) + { + np->ident_len = ident_len; + np->ident = ident; + return (struct mib_node*)lrn; + } + else + { + /* follow next child pointer */ + ident_len--; + ident++; + node = ln->nptr; + } + } + else + { + /* search failed */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ln search failed *ident==%"S32_F"\n",*ident)); + return NULL; + } + } + else + { + /* search failed, short object identifier (nosuchname) */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ln search failed, short object identifier\n")); + return NULL; + } + } + else if(node_type == MIB_NODE_EX) + { + struct mib_external_node *en; + u16_t i, len; + + if (ident_len > 0) + { + /* external node (addressing and access via functions) */ + en = (struct mib_external_node *)node; + + i = 0; + len = en->level_length(en->addr_inf,ext_level); + while ((i < len) && (en->ident_cmp(en->addr_inf,ext_level,i,*ident) != 0)) + { + i++; + } + if (i < len) + { + s32_t debug_id; + + en->get_objid(en->addr_inf,ext_level,i,&debug_id); + LWIP_DEBUGF(SNMP_MIB_DEBUG,("en->objid==%"S32_F" *ident==%"S32_F"\n",debug_id,*ident)); + if ((ext_level + 1) == en->tree_levels) + { + np->ident_len = ident_len; + np->ident = ident; + return (struct mib_node*)en; + } + else + { + /* found it, proceed to child */ + ident_len--; + ident++; + ext_level++; + } + } + else + { + /* search failed */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("en search failed *ident==%"S32_F"\n",*ident)); + return NULL; + } + } + else + { + /* search failed, short object identifier (nosuchname) */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("en search failed, short object identifier\n")); + return NULL; + } + } + else if (node_type == MIB_NODE_SC) + { + mib_scalar_node *sn; + + sn = (mib_scalar_node *)node; + if ((ident_len == 1) && (*ident == 0)) + { + np->ident_len = ident_len; + np->ident = ident; + return (struct mib_node*)sn; + } + else + { + /* search failed, short object identifier (nosuchname) */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("search failed, invalid object identifier length\n")); + return NULL; + } + } + else + { + /* unknown node_type */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("search failed node_type %"U16_F" unkown\n",(u16_t)node_type)); + return NULL; + } + } + /* done, found nothing */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("search failed node==%p\n",(void*)node)); + return NULL; +} + +/** + * Test table for presence of at least one table entry. + */ +static u8_t +empty_table(struct mib_node *node) +{ + u8_t node_type; + u8_t empty = 0; + + if (node != NULL) + { + node_type = node->node_type; + if (node_type == MIB_NODE_LR) + { + struct mib_list_rootnode *lrn; + lrn = (struct mib_list_rootnode *)node; + if ((lrn->count == 0) || (lrn->head == NULL)) + { + empty = 1; + } + } + else if ((node_type == MIB_NODE_AR) || (node_type == MIB_NODE_RA)) + { + struct mib_array_node *an; + an = (struct mib_array_node *)node; + if ((an->maxlength == 0) || (an->nptr == NULL)) + { + empty = 1; + } + } + else if (node_type == MIB_NODE_EX) + { + struct mib_external_node *en; + en = (struct mib_external_node *)node; + if (en->tree_levels == 0) + { + empty = 1; + } + } + } + return empty; +} + +/** + * Tree expansion. + */ +struct mib_node * +snmp_expand_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct snmp_obj_id *oidret) +{ + u8_t node_type, ext_level, climb_tree; + + ext_level = 0; + /* reset node stack */ + node_stack_cnt = 0; + while (node != NULL) + { + climb_tree = 0; + node_type = node->node_type; + if ((node_type == MIB_NODE_AR) || (node_type == MIB_NODE_RA)) + { + struct mib_array_node *an; + u16_t i; + + /* array node (internal ROM or RAM, fixed length) */ + an = (struct mib_array_node *)node; + if (ident_len > 0) + { + i = 0; + while ((i < an->maxlength) && (an->objid[i] < *ident)) + { + i++; + } + if (i < an->maxlength) + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("an->objid[%"U16_F"]==%"S32_F" *ident==%"S32_F"\n",i,an->objid[i],*ident)); + /* add identifier to oidret */ + oidret->id[oidret->len] = an->objid[i]; + (oidret->len)++; + + if (an->nptr[i] == NULL) + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("leaf node\n")); + /* leaf node (e.g. in a fixed size table) */ + if (an->objid[i] > *ident) + { + return (struct mib_node*)an; + } + else if ((i + 1) < an->maxlength) + { + /* an->objid[i] == *ident */ + (oidret->len)--; + oidret->id[oidret->len] = an->objid[i + 1]; + (oidret->len)++; + return (struct mib_node*)an; + } + else + { + /* (i + 1) == an->maxlength */ + (oidret->len)--; + climb_tree = 1; + } + } + else + { + u16_t j; + + LWIP_DEBUGF(SNMP_MIB_DEBUG,("non-leaf node\n")); + /* non-leaf, store right child ptr and id */ + LWIP_ASSERT("i < 0xff", i < 0xff); + j = i + 1; + while ((j < an->maxlength) && (empty_table(an->nptr[j]))) + { + j++; + } + if (j < an->maxlength) + { + struct nse cur_node; + cur_node.r_ptr = an->nptr[j]; + cur_node.r_id = an->objid[j]; + cur_node.r_nl = 0; + push_node(&cur_node); + } + else + { + push_node(&node_null); + } + if (an->objid[i] == *ident) + { + ident_len--; + ident++; + } + else + { + /* an->objid[i] < *ident */ + ident_len = 0; + } + /* follow next child pointer */ + node = an->nptr[i]; + } + } + else + { + /* i == an->maxlength */ + climb_tree = 1; + } + } + else + { + u16_t j; + /* ident_len == 0, complete with leftmost '.thing' */ + j = 0; + while ((j < an->maxlength) && empty_table(an->nptr[j])) + { + j++; + } + if (j < an->maxlength) + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("left an->objid[j]==%"S32_F"\n",an->objid[j])); + oidret->id[oidret->len] = an->objid[j]; + (oidret->len)++; + if (an->nptr[j] == NULL) + { + /* leaf node */ + return (struct mib_node*)an; + } + else + { + /* no leaf, continue */ + node = an->nptr[j]; + } + } + else + { + /* j == an->maxlength */ + climb_tree = 1; + } + } + } + else if(node_type == MIB_NODE_LR) + { + struct mib_list_rootnode *lrn; + struct mib_list_node *ln; + + /* list root node (internal 'RAM', variable length) */ + lrn = (struct mib_list_rootnode *)node; + if (ident_len > 0) + { + ln = lrn->head; + /* iterate over list, head to tail */ + while ((ln != NULL) && (ln->objid < *ident)) + { + ln = ln->next; + } + if (ln != NULL) + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("ln->objid==%"S32_F" *ident==%"S32_F"\n",ln->objid,*ident)); + oidret->id[oidret->len] = ln->objid; + (oidret->len)++; + if (ln->nptr == NULL) + { + /* leaf node */ + if (ln->objid > *ident) + { + return (struct mib_node*)lrn; + } + else if (ln->next != NULL) + { + /* ln->objid == *ident */ + (oidret->len)--; + oidret->id[oidret->len] = ln->next->objid; + (oidret->len)++; + return (struct mib_node*)lrn; + } + else + { + /* ln->next == NULL */ + (oidret->len)--; + climb_tree = 1; + } + } + else + { + struct mib_list_node *jn; + + /* non-leaf, store right child ptr and id */ + jn = ln->next; + while ((jn != NULL) && empty_table(jn->nptr)) + { + jn = jn->next; + } + if (jn != NULL) + { + struct nse cur_node; + cur_node.r_ptr = jn->nptr; + cur_node.r_id = jn->objid; + cur_node.r_nl = 0; + push_node(&cur_node); + } + else + { + push_node(&node_null); + } + if (ln->objid == *ident) + { + ident_len--; + ident++; + } + else + { + /* ln->objid < *ident */ + ident_len = 0; + } + /* follow next child pointer */ + node = ln->nptr; + } + + } + else + { + /* ln == NULL */ + climb_tree = 1; + } + } + else + { + struct mib_list_node *jn; + /* ident_len == 0, complete with leftmost '.thing' */ + jn = lrn->head; + while ((jn != NULL) && empty_table(jn->nptr)) + { + jn = jn->next; + } + if (jn != NULL) + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("left jn->objid==%"S32_F"\n",jn->objid)); + oidret->id[oidret->len] = jn->objid; + (oidret->len)++; + if (jn->nptr == NULL) + { + /* leaf node */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("jn->nptr == NULL\n")); + return (struct mib_node*)lrn; + } + else + { + /* no leaf, continue */ + node = jn->nptr; + } + } + else + { + /* jn == NULL */ + climb_tree = 1; + } + } + } + else if(node_type == MIB_NODE_EX) + { + struct mib_external_node *en; + s32_t ex_id; + + /* external node (addressing and access via functions) */ + en = (struct mib_external_node *)node; + if (ident_len > 0) + { + u16_t i, len; + + i = 0; + len = en->level_length(en->addr_inf,ext_level); + while ((i < len) && (en->ident_cmp(en->addr_inf,ext_level,i,*ident) < 0)) + { + i++; + } + if (i < len) + { + /* add identifier to oidret */ + en->get_objid(en->addr_inf,ext_level,i,&ex_id); + LWIP_DEBUGF(SNMP_MIB_DEBUG,("en->objid[%"U16_F"]==%"S32_F" *ident==%"S32_F"\n",i,ex_id,*ident)); + oidret->id[oidret->len] = ex_id; + (oidret->len)++; + + if ((ext_level + 1) == en->tree_levels) + { + LWIP_DEBUGF(SNMP_MIB_DEBUG,("leaf node\n")); + /* leaf node */ + if (ex_id > *ident) + { + return (struct mib_node*)en; + } + else if ((i + 1) < len) + { + /* ex_id == *ident */ + en->get_objid(en->addr_inf,ext_level,i + 1,&ex_id); + (oidret->len)--; + oidret->id[oidret->len] = ex_id; + (oidret->len)++; + return (struct mib_node*)en; + } + else + { + /* (i + 1) == len */ + (oidret->len)--; + climb_tree = 1; + } + } + else + { + u16_t j; + + LWIP_DEBUGF(SNMP_MIB_DEBUG,("non-leaf node\n")); + /* non-leaf, store right child ptr and id */ + LWIP_ASSERT("i < 0xff", i < 0xff); + j = i + 1; + if (j < len) + { + struct nse cur_node; + /* right node is the current external node */ + cur_node.r_ptr = node; + en->get_objid(en->addr_inf,ext_level,j,&cur_node.r_id); + cur_node.r_nl = ext_level + 1; + push_node(&cur_node); + } + else + { + push_node(&node_null); + } + if (en->ident_cmp(en->addr_inf,ext_level,i,*ident) == 0) + { + ident_len--; + ident++; + } + else + { + /* external id < *ident */ + ident_len = 0; + } + /* proceed to child */ + ext_level++; + } + } + else + { + /* i == len (en->level_len()) */ + climb_tree = 1; + } + } + else + { + /* ident_len == 0, complete with leftmost '.thing' */ + en->get_objid(en->addr_inf,ext_level,0,&ex_id); + LWIP_DEBUGF(SNMP_MIB_DEBUG,("left en->objid==%"S32_F"\n",ex_id)); + oidret->id[oidret->len] = ex_id; + (oidret->len)++; + if ((ext_level + 1) == en->tree_levels) + { + /* leaf node */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("(ext_level + 1) == en->tree_levels\n")); + return (struct mib_node*)en; + } + else + { + /* no leaf, proceed to child */ + ext_level++; + } + } + } + else if(node_type == MIB_NODE_SC) + { + mib_scalar_node *sn; + + /* scalar node */ + sn = (mib_scalar_node *)node; + if (ident_len > 0) + { + /* at .0 */ + climb_tree = 1; + } + else + { + /* ident_len == 0, complete object identifier */ + oidret->id[oidret->len] = 0; + (oidret->len)++; + /* leaf node */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("completed scalar leaf\n")); + return (struct mib_node*)sn; + } + } + else + { + /* unknown/unhandled node_type */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("expand failed node_type %"U16_F" unkown\n",(u16_t)node_type)); + return NULL; + } + + if (climb_tree) + { + struct nse child; + + /* find right child ptr */ + child.r_ptr = NULL; + child.r_id = 0; + child.r_nl = 0; + while ((node_stack_cnt > 0) && (child.r_ptr == NULL)) + { + pop_node(&child); + /* trim returned oid */ + (oidret->len)--; + } + if (child.r_ptr != NULL) + { + /* incoming ident is useless beyond this point */ + ident_len = 0; + oidret->id[oidret->len] = child.r_id; + oidret->len++; + node = child.r_ptr; + ext_level = child.r_nl; + } + else + { + /* tree ends here ... */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("expand failed, tree ends here\n")); + return NULL; + } + } + } + /* done, found nothing */ + LWIP_DEBUGF(SNMP_MIB_DEBUG,("expand failed node==%p\n",(void*)node)); + return NULL; +} + +/** + * Test object identifier for the iso.org.dod.internet prefix. + * + * @param ident_len the length of the supplied object identifier + * @param ident points to the array of sub identifiers + * @return 1 if it matches, 0 otherwise + */ +u8_t +snmp_iso_prefix_tst(u8_t ident_len, s32_t *ident) +{ + if ((ident_len > 3) && + (ident[0] == 1) && (ident[1] == 3) && + (ident[2] == 6) && (ident[3] == 1)) + { + return 1; + } + else + { + return 0; + } +} + +/** + * Expands object identifier to the iso.org.dod.internet + * prefix for use in getnext operation. + * + * @param ident_len the length of the supplied object identifier + * @param ident points to the array of sub identifiers + * @param oidret points to returned expanded object identifier + * @return 1 if it matches, 0 otherwise + * + * @note ident_len 0 is allowed, expanding to the first known object id!! + */ +u8_t +snmp_iso_prefix_expand(u8_t ident_len, s32_t *ident, struct snmp_obj_id *oidret) +{ + const s32_t *prefix_ptr; + s32_t *ret_ptr; + u8_t i; + + i = 0; + prefix_ptr = &prefix[0]; + ret_ptr = &oidret->id[0]; + ident_len = ((ident_len < 4)?ident_len:4); + while ((i < ident_len) && ((*ident) <= (*prefix_ptr))) + { + *ret_ptr++ = *prefix_ptr++; + ident++; + i++; + } + if (i == ident_len) + { + /* match, complete missing bits */ + while (i < 4) + { + *ret_ptr++ = *prefix_ptr++; + i++; + } + oidret->len = i; + return 1; + } + else + { + /* i != ident_len */ + return 0; + } +} + +#endif /* LWIP_SNMP */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/core/snmp/msg_in.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/snmp/msg_in.c new file mode 100644 index 0000000..da9b78c --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/snmp/msg_in.c @@ -0,0 +1,1463 @@ +/** + * @file + * SNMP input message processing (RFC1157). + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * Author: Christiaan Simons + */ + +#include "lwip/opt.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/snmp.h" +#include "lwip/snmp_asn1.h" +#include "lwip/snmp_msg.h" +#include "lwip/snmp_structs.h" +#include "lwip/ip_addr.h" +#include "lwip/memp.h" +#include "lwip/udp.h" +#include "lwip/stats.h" + +#include + +/* public (non-static) constants */ +/** SNMP v1 == 0 */ +const s32_t snmp_version = 0; +/** default SNMP community string */ +const char snmp_publiccommunity[7] = "public"; + +/* statically allocated buffers for SNMP_CONCURRENT_REQUESTS */ +struct snmp_msg_pstat msg_input_list[SNMP_CONCURRENT_REQUESTS]; +/* UDP Protocol Control Block */ +struct udp_pcb *snmp1_pcb; + +static void snmp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port); +static err_t snmp_pdu_header_check(struct pbuf *p, u16_t ofs, u16_t pdu_len, u16_t *ofs_ret, struct snmp_msg_pstat *m_stat); +static err_t snmp_pdu_dec_varbindlist(struct pbuf *p, u16_t ofs, u16_t *ofs_ret, struct snmp_msg_pstat *m_stat); + + +/** + * Starts SNMP Agent. + * Allocates UDP pcb and binds it to IP_ADDR_ANY port 161. + */ +void +snmp_init(void) +{ + struct snmp_msg_pstat *msg_ps; + u8_t i; + + snmp1_pcb = udp_new(); + if (snmp1_pcb != NULL) + { + udp_recv(snmp1_pcb, snmp_recv, (void *)SNMP_IN_PORT); + udp_bind(snmp1_pcb, IP_ADDR_ANY, SNMP_IN_PORT); + } + msg_ps = &msg_input_list[0]; + for (i=0; istate = SNMP_MSG_EMPTY; + msg_ps->error_index = 0; + msg_ps->error_status = SNMP_ES_NOERROR; + msg_ps++; + } + trap_msg.pcb = snmp1_pcb; + +#ifdef SNMP_PRIVATE_MIB_INIT + /* If defined, this must be a function-like define to initialize the + * private MIB after the stack has been initialized. + * The private MIB can also be initialized in tcpip_callback (or after + * the stack is initialized), this define is only for convenience. */ + SNMP_PRIVATE_MIB_INIT(); +#endif /* SNMP_PRIVATE_MIB_INIT */ + + /* The coldstart trap will only be output + if our outgoing interface is up & configured */ + snmp_coldstart_trap(); +} + +static void +snmp_error_response(struct snmp_msg_pstat *msg_ps, u8_t error) +{ + /* move names back from outvb to invb */ + int v; + struct snmp_varbind *vbi = msg_ps->invb.head; + struct snmp_varbind *vbo = msg_ps->outvb.head; + for (v=0; vvb_idx; v++) { + if (vbi->ident != NULL) { + /* free previously allocated value before overwriting the pointer */ + memp_free(MEMP_SNMP_VALUE, vbi->ident); + } + vbi->ident_len = vbo->ident_len; + vbo->ident_len = 0; + vbi->ident = vbo->ident; + vbo->ident = NULL; + vbi = vbi->next; + vbo = vbo->next; + } + /* free outvb */ + snmp_varbind_list_free(&msg_ps->outvb); + /* we send invb back */ + msg_ps->outvb = msg_ps->invb; + msg_ps->invb.head = NULL; + msg_ps->invb.tail = NULL; + msg_ps->invb.count = 0; + msg_ps->error_status = error; + /* error index must be 0 for error too big */ + msg_ps->error_index = (error != SNMP_ES_TOOBIG) ? (1 + msg_ps->vb_idx) : 0; + snmp_send_response(msg_ps); + snmp_varbind_list_free(&msg_ps->outvb); + msg_ps->state = SNMP_MSG_EMPTY; +} + +static void +snmp_ok_response(struct snmp_msg_pstat *msg_ps) +{ + err_t err_ret; + + err_ret = snmp_send_response(msg_ps); + if (err_ret == ERR_MEM) + { + /* serious memory problem, can't return tooBig */ + } + else + { + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event = %"S32_F"\n",msg_ps->error_status)); + } + /* free varbinds (if available) */ + snmp_varbind_list_free(&msg_ps->invb); + snmp_varbind_list_free(&msg_ps->outvb); + msg_ps->state = SNMP_MSG_EMPTY; +} + +/** + * Service an internal or external event for SNMP GET. + * + * @param request_id identifies requests from 0 to (SNMP_CONCURRENT_REQUESTS-1) + * @param msg_ps points to the associated message process state + */ +static void +snmp_msg_get_event(u8_t request_id, struct snmp_msg_pstat *msg_ps) +{ + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_get_event: msg_ps->state==%"U16_F"\n",(u16_t)msg_ps->state)); + + if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_OBJDEF) + { + struct mib_external_node *en; + struct snmp_name_ptr np; + + /* get_object_def() answer*/ + en = msg_ps->ext_mib_node; + np = msg_ps->ext_name_ptr; + + /* translate answer into a known lifeform */ + en->get_object_def_a(request_id, np.ident_len, np.ident, &msg_ps->ext_object_def); + if ((msg_ps->ext_object_def.instance != MIB_OBJECT_NONE) && + (msg_ps->ext_object_def.access & MIB_ACCESS_READ)) + { + msg_ps->state = SNMP_MSG_EXTERNAL_GET_VALUE; + en->get_value_q(request_id, &msg_ps->ext_object_def); + } + else + { + en->get_object_def_pc(request_id, np.ident_len, np.ident); + /* search failed, object id points to unknown object (nosuchname) */ + snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME); + } + } + else if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_VALUE) + { + struct mib_external_node *en; + struct snmp_varbind *vb; + + /* get_value() answer */ + en = msg_ps->ext_mib_node; + + /* allocate output varbind */ + vb = (struct snmp_varbind *)memp_malloc(MEMP_SNMP_VARBIND); + if (vb != NULL) + { + vb->next = NULL; + vb->prev = NULL; + + /* move name from invb to outvb */ + vb->ident = msg_ps->vb_ptr->ident; + vb->ident_len = msg_ps->vb_ptr->ident_len; + /* ensure this memory is referenced once only */ + msg_ps->vb_ptr->ident = NULL; + msg_ps->vb_ptr->ident_len = 0; + + vb->value_type = msg_ps->ext_object_def.asn_type; + LWIP_ASSERT("invalid length", msg_ps->ext_object_def.v_len <= 0xff); + vb->value_len = (u8_t)msg_ps->ext_object_def.v_len; + if (vb->value_len > 0) + { + LWIP_ASSERT("SNMP_MAX_OCTET_STRING_LEN is configured too low", vb->value_len <= SNMP_MAX_VALUE_SIZE); + vb->value = memp_malloc(MEMP_SNMP_VALUE); + if (vb->value != NULL) + { + en->get_value_a(request_id, &msg_ps->ext_object_def, vb->value_len, vb->value); + snmp_varbind_tail_add(&msg_ps->outvb, vb); + /* search again (if vb_idx < msg_ps->invb.count) */ + msg_ps->state = SNMP_MSG_SEARCH_OBJ; + msg_ps->vb_idx += 1; + } + else + { + en->get_value_pc(request_id, &msg_ps->ext_object_def); + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event: no variable space\n")); + msg_ps->vb_ptr->ident = vb->ident; + msg_ps->vb_ptr->ident_len = vb->ident_len; + memp_free(MEMP_SNMP_VARBIND, vb); + snmp_error_response(msg_ps,SNMP_ES_TOOBIG); + } + } + else + { + /* vb->value_len == 0, empty value (e.g. empty string) */ + en->get_value_a(request_id, &msg_ps->ext_object_def, 0, NULL); + vb->value = NULL; + snmp_varbind_tail_add(&msg_ps->outvb, vb); + /* search again (if vb_idx < msg_ps->invb.count) */ + msg_ps->state = SNMP_MSG_SEARCH_OBJ; + msg_ps->vb_idx += 1; + } + } + else + { + en->get_value_pc(request_id, &msg_ps->ext_object_def); + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event: no outvb space\n")); + snmp_error_response(msg_ps,SNMP_ES_TOOBIG); + } + } + + while ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) && + (msg_ps->vb_idx < msg_ps->invb.count)) + { + struct mib_node *mn; + struct snmp_name_ptr np; + + if (msg_ps->vb_idx == 0) + { + msg_ps->vb_ptr = msg_ps->invb.head; + } + else + { + msg_ps->vb_ptr = msg_ps->vb_ptr->next; + } + /** test object identifier for .iso.org.dod.internet prefix */ + if (snmp_iso_prefix_tst(msg_ps->vb_ptr->ident_len, msg_ps->vb_ptr->ident)) + { + mn = snmp_search_tree((struct mib_node*)&internet, msg_ps->vb_ptr->ident_len - 4, + msg_ps->vb_ptr->ident + 4, &np); + if (mn != NULL) + { + if (mn->node_type == MIB_NODE_EX) + { + /* external object */ + struct mib_external_node *en = (struct mib_external_node*)mn; + + msg_ps->state = SNMP_MSG_EXTERNAL_GET_OBJDEF; + /* save en && args in msg_ps!! */ + msg_ps->ext_mib_node = en; + msg_ps->ext_name_ptr = np; + + en->get_object_def_q(en->addr_inf, request_id, np.ident_len, np.ident); + } + else + { + /* internal object */ + struct obj_def object_def; + + msg_ps->state = SNMP_MSG_INTERNAL_GET_OBJDEF; + mn->get_object_def(np.ident_len, np.ident, &object_def); + if ((object_def.instance != MIB_OBJECT_NONE) && + (object_def.access & MIB_ACCESS_READ)) + { + mn = mn; + } + else + { + /* search failed, object id points to unknown object (nosuchname) */ + mn = NULL; + } + if (mn != NULL) + { + struct snmp_varbind *vb; + + msg_ps->state = SNMP_MSG_INTERNAL_GET_VALUE; + /* allocate output varbind */ + vb = (struct snmp_varbind *)memp_malloc(MEMP_SNMP_VARBIND); + if (vb != NULL) + { + vb->next = NULL; + vb->prev = NULL; + + /* move name from invb to outvb */ + vb->ident = msg_ps->vb_ptr->ident; + vb->ident_len = msg_ps->vb_ptr->ident_len; + /* ensure this memory is referenced once only */ + msg_ps->vb_ptr->ident = NULL; + msg_ps->vb_ptr->ident_len = 0; + + vb->value_type = object_def.asn_type; + LWIP_ASSERT("invalid length", object_def.v_len <= 0xff); + vb->value_len = (u8_t)object_def.v_len; + if (vb->value_len > 0) + { + LWIP_ASSERT("SNMP_MAX_OCTET_STRING_LEN is configured too low", + vb->value_len <= SNMP_MAX_VALUE_SIZE); + vb->value = memp_malloc(MEMP_SNMP_VALUE); + if (vb->value != NULL) + { + mn->get_value(&object_def, vb->value_len, vb->value); + snmp_varbind_tail_add(&msg_ps->outvb, vb); + msg_ps->state = SNMP_MSG_SEARCH_OBJ; + msg_ps->vb_idx += 1; + } + else + { + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event: couldn't allocate variable space\n")); + msg_ps->vb_ptr->ident = vb->ident; + msg_ps->vb_ptr->ident_len = vb->ident_len; + vb->ident = NULL; + vb->ident_len = 0; + memp_free(MEMP_SNMP_VARBIND, vb); + snmp_error_response(msg_ps,SNMP_ES_TOOBIG); + } + } + else + { + /* vb->value_len == 0, empty value (e.g. empty string) */ + vb->value = NULL; + snmp_varbind_tail_add(&msg_ps->outvb, vb); + msg_ps->state = SNMP_MSG_SEARCH_OBJ; + msg_ps->vb_idx += 1; + } + } + else + { + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event: couldn't allocate outvb space\n")); + snmp_error_response(msg_ps,SNMP_ES_TOOBIG); + } + } + } + } + } + else + { + mn = NULL; + } + if (mn == NULL) + { + /* mn == NULL, noSuchName */ + snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME); + } + } + if ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) && + (msg_ps->vb_idx == msg_ps->invb.count)) + { + snmp_ok_response(msg_ps); + } +} + +/** + * Service an internal or external event for SNMP GETNEXT. + * + * @param request_id identifies requests from 0 to (SNMP_CONCURRENT_REQUESTS-1) + * @param msg_ps points to the associated message process state + */ +static void +snmp_msg_getnext_event(u8_t request_id, struct snmp_msg_pstat *msg_ps) +{ + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_getnext_event: msg_ps->state==%"U16_F"\n",(u16_t)msg_ps->state)); + + if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_OBJDEF) + { + struct mib_external_node *en; + + /* get_object_def() answer*/ + en = msg_ps->ext_mib_node; + + /* translate answer into a known lifeform */ + en->get_object_def_a(request_id, 1, &msg_ps->ext_oid.id[msg_ps->ext_oid.len - 1], &msg_ps->ext_object_def); + if (msg_ps->ext_object_def.instance != MIB_OBJECT_NONE) + { + msg_ps->state = SNMP_MSG_EXTERNAL_GET_VALUE; + en->get_value_q(request_id, &msg_ps->ext_object_def); + } + else + { + en->get_object_def_pc(request_id, 1, &msg_ps->ext_oid.id[msg_ps->ext_oid.len - 1]); + /* search failed, object id points to unknown object (nosuchname) */ + snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME); + } + } + else if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_VALUE) + { + struct mib_external_node *en; + struct snmp_varbind *vb; + + /* get_value() answer */ + en = msg_ps->ext_mib_node; + + LWIP_ASSERT("invalid length", msg_ps->ext_object_def.v_len <= 0xff); + vb = snmp_varbind_alloc(&msg_ps->ext_oid, + msg_ps->ext_object_def.asn_type, + (u8_t)msg_ps->ext_object_def.v_len); + if (vb != NULL) + { + en->get_value_a(request_id, &msg_ps->ext_object_def, vb->value_len, vb->value); + snmp_varbind_tail_add(&msg_ps->outvb, vb); + msg_ps->state = SNMP_MSG_SEARCH_OBJ; + msg_ps->vb_idx += 1; + } + else + { + en->get_value_pc(request_id, &msg_ps->ext_object_def); + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_getnext_event: couldn't allocate outvb space\n")); + snmp_error_response(msg_ps,SNMP_ES_TOOBIG); + } + } + + while ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) && + (msg_ps->vb_idx < msg_ps->invb.count)) + { + struct mib_node *mn; + struct snmp_obj_id oid; + + if (msg_ps->vb_idx == 0) + { + msg_ps->vb_ptr = msg_ps->invb.head; + } + else + { + msg_ps->vb_ptr = msg_ps->vb_ptr->next; + } + if (snmp_iso_prefix_expand(msg_ps->vb_ptr->ident_len, msg_ps->vb_ptr->ident, &oid)) + { + if (msg_ps->vb_ptr->ident_len > 3) + { + /* can offset ident_len and ident */ + mn = snmp_expand_tree((struct mib_node*)&internet, + msg_ps->vb_ptr->ident_len - 4, + msg_ps->vb_ptr->ident + 4, &oid); + } + else + { + /* can't offset ident_len -4, ident + 4 */ + mn = snmp_expand_tree((struct mib_node*)&internet, 0, NULL, &oid); + } + } + else + { + mn = NULL; + } + if (mn != NULL) + { + if (mn->node_type == MIB_NODE_EX) + { + /* external object */ + struct mib_external_node *en = (struct mib_external_node*)mn; + + msg_ps->state = SNMP_MSG_EXTERNAL_GET_OBJDEF; + /* save en && args in msg_ps!! */ + msg_ps->ext_mib_node = en; + msg_ps->ext_oid = oid; + + en->get_object_def_q(en->addr_inf, request_id, 1, &oid.id[oid.len - 1]); + } + else + { + /* internal object */ + struct obj_def object_def; + struct snmp_varbind *vb; + + msg_ps->state = SNMP_MSG_INTERNAL_GET_OBJDEF; + mn->get_object_def(1, &oid.id[oid.len - 1], &object_def); + + LWIP_ASSERT("invalid length", object_def.v_len <= 0xff); + vb = snmp_varbind_alloc(&oid, object_def.asn_type, (u8_t)object_def.v_len); + if (vb != NULL) + { + msg_ps->state = SNMP_MSG_INTERNAL_GET_VALUE; + mn->get_value(&object_def, object_def.v_len, vb->value); + snmp_varbind_tail_add(&msg_ps->outvb, vb); + msg_ps->state = SNMP_MSG_SEARCH_OBJ; + msg_ps->vb_idx += 1; + } + else + { + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_recv couldn't allocate outvb space\n")); + snmp_error_response(msg_ps,SNMP_ES_TOOBIG); + } + } + } + if (mn == NULL) + { + /* mn == NULL, noSuchName */ + snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME); + } + } + if ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) && + (msg_ps->vb_idx == msg_ps->invb.count)) + { + snmp_ok_response(msg_ps); + } +} + +/** + * Service an internal or external event for SNMP SET. + * + * @param request_id identifies requests from 0 to (SNMP_CONCURRENT_REQUESTS-1) + * @param msg_ps points to the associated message process state + */ +static void +snmp_msg_set_event(u8_t request_id, struct snmp_msg_pstat *msg_ps) +{ + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_set_event: msg_ps->state==%"U16_F"\n",(u16_t)msg_ps->state)); + + if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_OBJDEF) + { + struct mib_external_node *en; + struct snmp_name_ptr np; + + /* get_object_def() answer*/ + en = msg_ps->ext_mib_node; + np = msg_ps->ext_name_ptr; + + /* translate answer into a known lifeform */ + en->get_object_def_a(request_id, np.ident_len, np.ident, &msg_ps->ext_object_def); + if (msg_ps->ext_object_def.instance != MIB_OBJECT_NONE) + { + msg_ps->state = SNMP_MSG_EXTERNAL_SET_TEST; + en->set_test_q(request_id, &msg_ps->ext_object_def); + } + else + { + en->get_object_def_pc(request_id, np.ident_len, np.ident); + /* search failed, object id points to unknown object (nosuchname) */ + snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME); + } + } + else if (msg_ps->state == SNMP_MSG_EXTERNAL_SET_TEST) + { + struct mib_external_node *en; + + /* set_test() answer*/ + en = msg_ps->ext_mib_node; + + if (msg_ps->ext_object_def.access & MIB_ACCESS_WRITE) + { + if ((msg_ps->ext_object_def.asn_type == msg_ps->vb_ptr->value_type) && + (en->set_test_a(request_id,&msg_ps->ext_object_def, + msg_ps->vb_ptr->value_len,msg_ps->vb_ptr->value) != 0)) + { + msg_ps->state = SNMP_MSG_SEARCH_OBJ; + msg_ps->vb_idx += 1; + } + else + { + en->set_test_pc(request_id,&msg_ps->ext_object_def); + /* bad value */ + snmp_error_response(msg_ps,SNMP_ES_BADVALUE); + } + } + else + { + en->set_test_pc(request_id,&msg_ps->ext_object_def); + /* object not available for set */ + snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME); + } + } + else if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_OBJDEF_S) + { + struct mib_external_node *en; + struct snmp_name_ptr np; + + /* get_object_def() answer*/ + en = msg_ps->ext_mib_node; + np = msg_ps->ext_name_ptr; + + /* translate answer into a known lifeform */ + en->get_object_def_a(request_id, np.ident_len, np.ident, &msg_ps->ext_object_def); + if (msg_ps->ext_object_def.instance != MIB_OBJECT_NONE) + { + msg_ps->state = SNMP_MSG_EXTERNAL_SET_VALUE; + en->set_value_q(request_id, &msg_ps->ext_object_def, + msg_ps->vb_ptr->value_len,msg_ps->vb_ptr->value); + } + else + { + en->get_object_def_pc(request_id, np.ident_len, np.ident); + /* set_value failed, object has disappeared for some odd reason?? */ + snmp_error_response(msg_ps,SNMP_ES_GENERROR); + } + } + else if (msg_ps->state == SNMP_MSG_EXTERNAL_SET_VALUE) + { + struct mib_external_node *en; + + /** set_value_a() */ + en = msg_ps->ext_mib_node; + en->set_value_a(request_id, &msg_ps->ext_object_def, + msg_ps->vb_ptr->value_len, msg_ps->vb_ptr->value); + + /** @todo use set_value_pc() if toobig */ + msg_ps->state = SNMP_MSG_INTERNAL_SET_VALUE; + msg_ps->vb_idx += 1; + } + + /* test all values before setting */ + while ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) && + (msg_ps->vb_idx < msg_ps->invb.count)) + { + struct mib_node *mn; + struct snmp_name_ptr np; + + if (msg_ps->vb_idx == 0) + { + msg_ps->vb_ptr = msg_ps->invb.head; + } + else + { + msg_ps->vb_ptr = msg_ps->vb_ptr->next; + } + /** test object identifier for .iso.org.dod.internet prefix */ + if (snmp_iso_prefix_tst(msg_ps->vb_ptr->ident_len, msg_ps->vb_ptr->ident)) + { + mn = snmp_search_tree((struct mib_node*)&internet, msg_ps->vb_ptr->ident_len - 4, + msg_ps->vb_ptr->ident + 4, &np); + if (mn != NULL) + { + if (mn->node_type == MIB_NODE_EX) + { + /* external object */ + struct mib_external_node *en = (struct mib_external_node*)mn; + + msg_ps->state = SNMP_MSG_EXTERNAL_GET_OBJDEF; + /* save en && args in msg_ps!! */ + msg_ps->ext_mib_node = en; + msg_ps->ext_name_ptr = np; + + en->get_object_def_q(en->addr_inf, request_id, np.ident_len, np.ident); + } + else + { + /* internal object */ + struct obj_def object_def; + + msg_ps->state = SNMP_MSG_INTERNAL_GET_OBJDEF; + mn->get_object_def(np.ident_len, np.ident, &object_def); + if (object_def.instance != MIB_OBJECT_NONE) + { + mn = mn; + } + else + { + /* search failed, object id points to unknown object (nosuchname) */ + mn = NULL; + } + if (mn != NULL) + { + msg_ps->state = SNMP_MSG_INTERNAL_SET_TEST; + + if (object_def.access & MIB_ACCESS_WRITE) + { + if ((object_def.asn_type == msg_ps->vb_ptr->value_type) && + (mn->set_test(&object_def,msg_ps->vb_ptr->value_len,msg_ps->vb_ptr->value) != 0)) + { + msg_ps->state = SNMP_MSG_SEARCH_OBJ; + msg_ps->vb_idx += 1; + } + else + { + /* bad value */ + snmp_error_response(msg_ps,SNMP_ES_BADVALUE); + } + } + else + { + /* object not available for set */ + snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME); + } + } + } + } + } + else + { + mn = NULL; + } + if (mn == NULL) + { + /* mn == NULL, noSuchName */ + snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME); + } + } + + if ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) && + (msg_ps->vb_idx == msg_ps->invb.count)) + { + msg_ps->vb_idx = 0; + msg_ps->state = SNMP_MSG_INTERNAL_SET_VALUE; + } + + /* set all values "atomically" (be as "atomic" as possible) */ + while ((msg_ps->state == SNMP_MSG_INTERNAL_SET_VALUE) && + (msg_ps->vb_idx < msg_ps->invb.count)) + { + struct mib_node *mn; + struct snmp_name_ptr np; + + if (msg_ps->vb_idx == 0) + { + msg_ps->vb_ptr = msg_ps->invb.head; + } + else + { + msg_ps->vb_ptr = msg_ps->vb_ptr->next; + } + /* skip iso prefix test, was done previously while settesting() */ + mn = snmp_search_tree((struct mib_node*)&internet, msg_ps->vb_ptr->ident_len - 4, + msg_ps->vb_ptr->ident + 4, &np); + /* check if object is still available + (e.g. external hot-plug thingy present?) */ + if (mn != NULL) + { + if (mn->node_type == MIB_NODE_EX) + { + /* external object */ + struct mib_external_node *en = (struct mib_external_node*)mn; + + msg_ps->state = SNMP_MSG_EXTERNAL_GET_OBJDEF_S; + /* save en && args in msg_ps!! */ + msg_ps->ext_mib_node = en; + msg_ps->ext_name_ptr = np; + + en->get_object_def_q(en->addr_inf, request_id, np.ident_len, np.ident); + } + else + { + /* internal object */ + struct obj_def object_def; + + msg_ps->state = SNMP_MSG_INTERNAL_GET_OBJDEF_S; + mn->get_object_def(np.ident_len, np.ident, &object_def); + msg_ps->state = SNMP_MSG_INTERNAL_SET_VALUE; + mn->set_value(&object_def,msg_ps->vb_ptr->value_len,msg_ps->vb_ptr->value); + msg_ps->vb_idx += 1; + } + } + } + if ((msg_ps->state == SNMP_MSG_INTERNAL_SET_VALUE) && + (msg_ps->vb_idx == msg_ps->invb.count)) + { + /* simply echo the input if we can set it + @todo do we need to return the actual value? + e.g. if value is silently modified or behaves sticky? */ + msg_ps->outvb = msg_ps->invb; + msg_ps->invb.head = NULL; + msg_ps->invb.tail = NULL; + msg_ps->invb.count = 0; + snmp_ok_response(msg_ps); + } +} + + +/** + * Handle one internal or external event. + * Called for one async event. (recv external/private answer) + * + * @param request_id identifies requests from 0 to (SNMP_CONCURRENT_REQUESTS-1) + */ +void +snmp_msg_event(u8_t request_id) +{ + struct snmp_msg_pstat *msg_ps; + + if (request_id < SNMP_CONCURRENT_REQUESTS) + { + msg_ps = &msg_input_list[request_id]; + if (msg_ps->rt == SNMP_ASN1_PDU_GET_NEXT_REQ) + { + snmp_msg_getnext_event(request_id, msg_ps); + } + else if (msg_ps->rt == SNMP_ASN1_PDU_GET_REQ) + { + snmp_msg_get_event(request_id, msg_ps); + } + else if(msg_ps->rt == SNMP_ASN1_PDU_SET_REQ) + { + snmp_msg_set_event(request_id, msg_ps); + } + } +} + + +/* lwIP UDP receive callback function */ +static void +snmp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port) +{ + struct snmp_msg_pstat *msg_ps; + u8_t req_idx; + err_t err_ret; + u16_t payload_len = p->tot_len; + u16_t payload_ofs = 0; + u16_t varbind_ofs = 0; + + /* suppress unused argument warning */ + LWIP_UNUSED_ARG(arg); + + /* traverse input message process list, look for SNMP_MSG_EMPTY */ + msg_ps = &msg_input_list[0]; + req_idx = 0; + while ((req_idx < SNMP_CONCURRENT_REQUESTS) && (msg_ps->state != SNMP_MSG_EMPTY)) + { + req_idx++; + msg_ps++; + } + if (req_idx == SNMP_CONCURRENT_REQUESTS) + { + /* exceeding number of concurrent requests */ + pbuf_free(p); + return; + } + + /* accepting request */ + snmp_inc_snmpinpkts(); + /* record used 'protocol control block' */ + msg_ps->pcb = pcb; + /* source address (network order) */ + msg_ps->sip = *addr; + /* source port (host order (lwIP oddity)) */ + msg_ps->sp = port; + + /* check total length, version, community, pdu type */ + err_ret = snmp_pdu_header_check(p, payload_ofs, payload_len, &varbind_ofs, msg_ps); + /* Only accept requests and requests without error (be robust) */ + /* Reject response and trap headers or error requests as input! */ + if ((err_ret != ERR_OK) || + ((msg_ps->rt != SNMP_ASN1_PDU_GET_REQ) && + (msg_ps->rt != SNMP_ASN1_PDU_GET_NEXT_REQ) && + (msg_ps->rt != SNMP_ASN1_PDU_SET_REQ)) || + ((msg_ps->error_status != SNMP_ES_NOERROR) || + (msg_ps->error_index != 0)) ) + { + /* header check failed drop request silently, do not return error! */ + pbuf_free(p); + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_pdu_header_check() failed\n")); + return; + } + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_recv ok, community %s\n", msg_ps->community)); + + /* Builds a list of variable bindings. Copy the varbinds from the pbuf + chain to glue them when these are divided over two or more pbuf's. */ + err_ret = snmp_pdu_dec_varbindlist(p, varbind_ofs, &varbind_ofs, msg_ps); + /* we've decoded the incoming message, release input msg now */ + pbuf_free(p); + if ((err_ret != ERR_OK) || (msg_ps->invb.count == 0)) + { + /* varbind-list decode failed, or varbind list empty. + drop request silently, do not return error! + (errors are only returned for a specific varbind failure) */ + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_pdu_dec_varbindlist() failed\n")); + return; + } + + msg_ps->error_status = SNMP_ES_NOERROR; + msg_ps->error_index = 0; + /* find object for each variable binding */ + msg_ps->state = SNMP_MSG_SEARCH_OBJ; + /* first variable binding from list to inspect */ + msg_ps->vb_idx = 0; + + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_recv varbind cnt=%"U16_F"\n",(u16_t)msg_ps->invb.count)); + + /* handle input event and as much objects as possible in one go */ + snmp_msg_event(req_idx); +} + +/** + * Checks and decodes incoming SNMP message header, logs header errors. + * + * @param p points to pbuf chain of SNMP message (UDP payload) + * @param ofs points to first octet of SNMP message + * @param pdu_len the length of the UDP payload + * @param ofs_ret returns the ofset of the variable bindings + * @param m_stat points to the current message request state return + * @return + * - ERR_OK SNMP header is sane and accepted + * - ERR_ARG SNMP header is either malformed or rejected + */ +static err_t +snmp_pdu_header_check(struct pbuf *p, u16_t ofs, u16_t pdu_len, u16_t *ofs_ret, struct snmp_msg_pstat *m_stat) +{ + err_t derr; + u16_t len, ofs_base; + u8_t len_octets; + u8_t type; + s32_t version; + + ofs_base = ofs; + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); + if ((derr != ERR_OK) || + (pdu_len != (1 + len_octets + len)) || + (type != (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ))) + { + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + ofs += (1 + len_octets); + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); + if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG))) + { + /* can't decode or no integer (version) */ + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, &version); + if (derr != ERR_OK) + { + /* can't decode */ + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + if (version != 0) + { + /* not version 1 */ + snmp_inc_snmpinbadversions(); + return ERR_ARG; + } + ofs += (1 + len_octets + len); + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); + if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR))) + { + /* can't decode or no octet string (community) */ + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + derr = snmp_asn1_dec_raw(p, ofs + 1 + len_octets, len, SNMP_COMMUNITY_STR_LEN, m_stat->community); + if (derr != ERR_OK) + { + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + /* add zero terminator */ + len = ((len < (SNMP_COMMUNITY_STR_LEN))?(len):(SNMP_COMMUNITY_STR_LEN)); + m_stat->community[len] = 0; + m_stat->com_strlen = (u8_t)len; + if (strncmp(snmp_publiccommunity, (const char*)m_stat->community, SNMP_COMMUNITY_STR_LEN) != 0) + { + /** @todo: move this if we need to check more names */ + snmp_inc_snmpinbadcommunitynames(); + snmp_authfail_trap(); + return ERR_ARG; + } + ofs += (1 + len_octets + len); + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); + if (derr != ERR_OK) + { + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + switch(type) + { + case (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_GET_REQ): + /* GetRequest PDU */ + snmp_inc_snmpingetrequests(); + derr = ERR_OK; + break; + case (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_GET_NEXT_REQ): + /* GetNextRequest PDU */ + snmp_inc_snmpingetnexts(); + derr = ERR_OK; + break; + case (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_GET_RESP): + /* GetResponse PDU */ + snmp_inc_snmpingetresponses(); + derr = ERR_ARG; + break; + case (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_SET_REQ): + /* SetRequest PDU */ + snmp_inc_snmpinsetrequests(); + derr = ERR_OK; + break; + case (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_TRAP): + /* Trap PDU */ + snmp_inc_snmpintraps(); + derr = ERR_ARG; + break; + default: + snmp_inc_snmpinasnparseerrs(); + derr = ERR_ARG; + break; + } + if (derr != ERR_OK) + { + /* unsupported input PDU for this agent (no parse error) */ + return ERR_ARG; + } + m_stat->rt = type & 0x1F; + ofs += (1 + len_octets); + if (len != (pdu_len - (ofs - ofs_base))) + { + /* decoded PDU length does not equal actual payload length */ + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); + if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG))) + { + /* can't decode or no integer (request ID) */ + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, &m_stat->rid); + if (derr != ERR_OK) + { + /* can't decode */ + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + ofs += (1 + len_octets + len); + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); + if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG))) + { + /* can't decode or no integer (error-status) */ + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + /* must be noError (0) for incoming requests. + log errors for mib-2 completeness and for debug purposes */ + derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, &m_stat->error_status); + if (derr != ERR_OK) + { + /* can't decode */ + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + switch (m_stat->error_status) + { + case SNMP_ES_NOERROR: + /* nothing to do */ + break; + case SNMP_ES_TOOBIG: + snmp_inc_snmpintoobigs(); + break; + case SNMP_ES_NOSUCHNAME: + snmp_inc_snmpinnosuchnames(); + break; + case SNMP_ES_BADVALUE: + snmp_inc_snmpinbadvalues(); + break; + case SNMP_ES_READONLY: + snmp_inc_snmpinreadonlys(); + break; + case SNMP_ES_GENERROR: + snmp_inc_snmpingenerrs(); + break; + default: + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_pdu_header_check(): unknown error_status: %d\n", (int)m_stat->error_status)); + break; + } + ofs += (1 + len_octets + len); + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); + if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG))) + { + /* can't decode or no integer (error-index) */ + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + /* must be 0 for incoming requests. + decode anyway to catch bad integers (and dirty tricks) */ + derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, &m_stat->error_index); + if (derr != ERR_OK) + { + /* can't decode */ + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + ofs += (1 + len_octets + len); + *ofs_ret = ofs; + return ERR_OK; +} + +static err_t +snmp_pdu_dec_varbindlist(struct pbuf *p, u16_t ofs, u16_t *ofs_ret, struct snmp_msg_pstat *m_stat) +{ + err_t derr; + u16_t len, vb_len; + u8_t len_octets; + u8_t type; + + /* variable binding list */ + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &vb_len); + if ((derr != ERR_OK) || + (type != (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ))) + { + snmp_inc_snmpinasnparseerrs(); + return ERR_ARG; + } + ofs += (1 + len_octets); + + /* start with empty list */ + m_stat->invb.count = 0; + m_stat->invb.head = NULL; + m_stat->invb.tail = NULL; + + while (vb_len > 0) + { + struct snmp_obj_id oid, oid_value; + struct snmp_varbind *vb; + + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); + if ((derr != ERR_OK) || + (type != (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)) || + (len == 0) || (len > vb_len)) + { + snmp_inc_snmpinasnparseerrs(); + /* free varbinds (if available) */ + snmp_varbind_list_free(&m_stat->invb); + return ERR_ARG; + } + ofs += (1 + len_octets); + vb_len -= (1 + len_octets); + + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); + if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID))) + { + /* can't decode object name length */ + snmp_inc_snmpinasnparseerrs(); + /* free varbinds (if available) */ + snmp_varbind_list_free(&m_stat->invb); + return ERR_ARG; + } + derr = snmp_asn1_dec_oid(p, ofs + 1 + len_octets, len, &oid); + if (derr != ERR_OK) + { + /* can't decode object name */ + snmp_inc_snmpinasnparseerrs(); + /* free varbinds (if available) */ + snmp_varbind_list_free(&m_stat->invb); + return ERR_ARG; + } + ofs += (1 + len_octets + len); + vb_len -= (1 + len_octets + len); + + snmp_asn1_dec_type(p, ofs, &type); + derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); + if (derr != ERR_OK) + { + /* can't decode object value length */ + snmp_inc_snmpinasnparseerrs(); + /* free varbinds (if available) */ + snmp_varbind_list_free(&m_stat->invb); + return ERR_ARG; + } + + switch (type) + { + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG): + vb = snmp_varbind_alloc(&oid, type, sizeof(s32_t)); + if (vb != NULL) + { + s32_t *vptr = (s32_t*)vb->value; + + derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, vptr); + snmp_varbind_tail_add(&m_stat->invb, vb); + } + else + { + derr = ERR_ARG; + } + break; + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS): + vb = snmp_varbind_alloc(&oid, type, sizeof(u32_t)); + if (vb != NULL) + { + u32_t *vptr = (u32_t*)vb->value; + + derr = snmp_asn1_dec_u32t(p, ofs + 1 + len_octets, len, vptr); + snmp_varbind_tail_add(&m_stat->invb, vb); + } + else + { + derr = ERR_ARG; + } + break; + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_OPAQUE): + LWIP_ASSERT("invalid length", len <= 0xff); + vb = snmp_varbind_alloc(&oid, type, (u8_t)len); + if (vb != NULL) + { + derr = snmp_asn1_dec_raw(p, ofs + 1 + len_octets, len, vb->value_len, (u8_t*)vb->value); + snmp_varbind_tail_add(&m_stat->invb, vb); + } + else + { + derr = ERR_ARG; + } + break; + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_NUL): + vb = snmp_varbind_alloc(&oid, type, 0); + if (vb != NULL) + { + snmp_varbind_tail_add(&m_stat->invb, vb); + derr = ERR_OK; + } + else + { + derr = ERR_ARG; + } + break; + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID): + derr = snmp_asn1_dec_oid(p, ofs + 1 + len_octets, len, &oid_value); + if (derr == ERR_OK) + { + vb = snmp_varbind_alloc(&oid, type, oid_value.len * sizeof(s32_t)); + if (vb != NULL) + { + u8_t i = oid_value.len; + s32_t *vptr = (s32_t*)vb->value; + + while(i > 0) + { + i--; + vptr[i] = oid_value.id[i]; + } + snmp_varbind_tail_add(&m_stat->invb, vb); + derr = ERR_OK; + } + else + { + derr = ERR_ARG; + } + } + break; + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR): + if (len == 4) + { + /* must be exactly 4 octets! */ + vb = snmp_varbind_alloc(&oid, type, 4); + if (vb != NULL) + { + derr = snmp_asn1_dec_raw(p, ofs + 1 + len_octets, len, vb->value_len, (u8_t*)vb->value); + snmp_varbind_tail_add(&m_stat->invb, vb); + } + else + { + derr = ERR_ARG; + } + } + else + { + derr = ERR_ARG; + } + break; + default: + derr = ERR_ARG; + break; + } + if (derr != ERR_OK) + { + snmp_inc_snmpinasnparseerrs(); + /* free varbinds (if available) */ + snmp_varbind_list_free(&m_stat->invb); + return ERR_ARG; + } + ofs += (1 + len_octets + len); + vb_len -= (1 + len_octets + len); + } + + if (m_stat->rt == SNMP_ASN1_PDU_SET_REQ) + { + snmp_add_snmpintotalsetvars(m_stat->invb.count); + } + else + { + snmp_add_snmpintotalreqvars(m_stat->invb.count); + } + + *ofs_ret = ofs; + return ERR_OK; +} + +struct snmp_varbind* +snmp_varbind_alloc(struct snmp_obj_id *oid, u8_t type, u8_t len) +{ + struct snmp_varbind *vb; + + vb = (struct snmp_varbind *)memp_malloc(MEMP_SNMP_VARBIND); + if (vb != NULL) + { + u8_t i; + + vb->next = NULL; + vb->prev = NULL; + i = oid->len; + vb->ident_len = i; + if (i > 0) + { + LWIP_ASSERT("SNMP_MAX_TREE_DEPTH is configured too low", i <= SNMP_MAX_TREE_DEPTH); + /* allocate array of s32_t for our object identifier */ + vb->ident = (s32_t*)memp_malloc(MEMP_SNMP_VALUE); + if (vb->ident == NULL) + { + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_varbind_alloc: couldn't allocate ident value space\n")); + memp_free(MEMP_SNMP_VARBIND, vb); + return NULL; + } + while(i > 0) + { + i--; + vb->ident[i] = oid->id[i]; + } + } + else + { + /* i == 0, pass zero length object identifier */ + vb->ident = NULL; + } + vb->value_type = type; + vb->value_len = len; + if (len > 0) + { + LWIP_ASSERT("SNMP_MAX_OCTET_STRING_LEN is configured too low", vb->value_len <= SNMP_MAX_VALUE_SIZE); + /* allocate raw bytes for our object value */ + vb->value = memp_malloc(MEMP_SNMP_VALUE); + if (vb->value == NULL) + { + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_varbind_alloc: couldn't allocate value space\n")); + if (vb->ident != NULL) + { + memp_free(MEMP_SNMP_VALUE, vb->ident); + } + memp_free(MEMP_SNMP_VARBIND, vb); + return NULL; + } + } + else + { + /* ASN1_NUL type, or zero length ASN1_OC_STR */ + vb->value = NULL; + } + } + else + { + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_varbind_alloc: couldn't allocate varbind space\n")); + } + return vb; +} + +void +snmp_varbind_free(struct snmp_varbind *vb) +{ + if (vb->value != NULL ) + { + memp_free(MEMP_SNMP_VALUE, vb->value); + } + if (vb->ident != NULL ) + { + memp_free(MEMP_SNMP_VALUE, vb->ident); + } + memp_free(MEMP_SNMP_VARBIND, vb); +} + +void +snmp_varbind_list_free(struct snmp_varbind_root *root) +{ + struct snmp_varbind *vb, *prev; + + vb = root->tail; + while ( vb != NULL ) + { + prev = vb->prev; + snmp_varbind_free(vb); + vb = prev; + } + root->count = 0; + root->head = NULL; + root->tail = NULL; +} + +void +snmp_varbind_tail_add(struct snmp_varbind_root *root, struct snmp_varbind *vb) +{ + if (root->count == 0) + { + /* add first varbind to list */ + root->head = vb; + root->tail = vb; + } + else + { + /* add nth varbind to list tail */ + root->tail->next = vb; + vb->prev = root->tail; + root->tail = vb; + } + root->count += 1; +} + +struct snmp_varbind* +snmp_varbind_tail_remove(struct snmp_varbind_root *root) +{ + struct snmp_varbind* vb; + + if (root->count > 0) + { + /* remove tail varbind */ + vb = root->tail; + root->tail = vb->prev; + vb->prev->next = NULL; + root->count -= 1; + } + else + { + /* nothing to remove */ + vb = NULL; + } + return vb; +} + +#endif /* LWIP_SNMP */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/core/snmp/msg_out.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/snmp/msg_out.c new file mode 100644 index 0000000..ecc524c --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/snmp/msg_out.c @@ -0,0 +1,684 @@ +/** + * @file + * SNMP output message processing (RFC1157). + * + * Output responses and traps are build in two passes: + * + * Pass 0: iterate over the output message backwards to determine encoding lengths + * Pass 1: the actual forward encoding of internal form into ASN1 + * + * The single-pass encoding method described by Comer & Stevens + * requires extra buffer space and copying for reversal of the packet. + * The buffer requirement can be prohibitively large for big payloads + * (>= 484) therefore we use the two encoding passes. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * Author: Christiaan Simons + */ + +#include "lwip/opt.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/udp.h" +#include "lwip/netif.h" +#include "lwip/snmp.h" +#include "lwip/snmp_asn1.h" +#include "lwip/snmp_msg.h" + +struct snmp_trap_dst +{ + /* destination IP address in network order */ + ip_addr_t dip; + /* set to 0 when disabled, >0 when enabled */ + u8_t enable; +}; +struct snmp_trap_dst trap_dst[SNMP_TRAP_DESTINATIONS]; + +/** TRAP message structure */ +struct snmp_msg_trap trap_msg; + +static u16_t snmp_resp_header_sum(struct snmp_msg_pstat *m_stat, u16_t vb_len); +static u16_t snmp_trap_header_sum(struct snmp_msg_trap *m_trap, u16_t vb_len); +static u16_t snmp_varbind_list_sum(struct snmp_varbind_root *root); + +static u16_t snmp_resp_header_enc(struct snmp_msg_pstat *m_stat, struct pbuf *p); +static u16_t snmp_trap_header_enc(struct snmp_msg_trap *m_trap, struct pbuf *p); +static u16_t snmp_varbind_list_enc(struct snmp_varbind_root *root, struct pbuf *p, u16_t ofs); + +/** + * Sets enable switch for this trap destination. + * @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1 + * @param enable switch if 0 destination is disabled >0 enabled. + */ +void +snmp_trap_dst_enable(u8_t dst_idx, u8_t enable) +{ + if (dst_idx < SNMP_TRAP_DESTINATIONS) + { + trap_dst[dst_idx].enable = enable; + } +} + +/** + * Sets IPv4 address for this trap destination. + * @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1 + * @param dst IPv4 address in host order. + */ +void +snmp_trap_dst_ip_set(u8_t dst_idx, ip_addr_t *dst) +{ + if (dst_idx < SNMP_TRAP_DESTINATIONS) + { + ip_addr_set(&trap_dst[dst_idx].dip, dst); + } +} + +/** + * Sends a 'getresponse' message to the request originator. + * + * @param m_stat points to the current message request state source + * @return ERR_OK when success, ERR_MEM if we're out of memory + * + * @note the caller is responsible for filling in outvb in the m_stat + * and provide error-status and index (except for tooBig errors) ... + */ +err_t +snmp_send_response(struct snmp_msg_pstat *m_stat) +{ + struct snmp_varbind_root emptyvb = {NULL, NULL, 0, 0, 0}; + struct pbuf *p; + u16_t tot_len; + err_t err; + + /* pass 0, calculate length fields */ + tot_len = snmp_varbind_list_sum(&m_stat->outvb); + tot_len = snmp_resp_header_sum(m_stat, tot_len); + + /* try allocating pbuf(s) for complete response */ + p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_POOL); + if (p == NULL) + { + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_snd_response() tooBig\n")); + + /* can't construct reply, return error-status tooBig */ + m_stat->error_status = SNMP_ES_TOOBIG; + m_stat->error_index = 0; + /* pass 0, recalculate lengths, for empty varbind-list */ + tot_len = snmp_varbind_list_sum(&emptyvb); + tot_len = snmp_resp_header_sum(m_stat, tot_len); + /* retry allocation once for header and empty varbind-list */ + p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_POOL); + } + if (p != NULL) + { + /* first pbuf alloc try or retry alloc success */ + u16_t ofs; + + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_snd_response() p != NULL\n")); + + /* pass 1, size error, encode packet ino the pbuf(s) */ + ofs = snmp_resp_header_enc(m_stat, p); + snmp_varbind_list_enc(&m_stat->outvb, p, ofs); + + switch (m_stat->error_status) + { + case SNMP_ES_NOERROR: + /* nothing to do */ + break; + case SNMP_ES_TOOBIG: + snmp_inc_snmpouttoobigs(); + break; + case SNMP_ES_NOSUCHNAME: + snmp_inc_snmpoutnosuchnames(); + break; + case SNMP_ES_BADVALUE: + snmp_inc_snmpoutbadvalues(); + break; + case SNMP_ES_GENERROR: + snmp_inc_snmpoutgenerrs(); + break; + default: + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_send_response(): unknown error_status: %d\n", (int)m_stat->error_status)); + break; + } + snmp_inc_snmpoutgetresponses(); + snmp_inc_snmpoutpkts(); + + /** @todo do we need separate rx and tx pcbs for threaded case? */ + /** connect to the originating source */ + udp_connect(m_stat->pcb, &m_stat->sip, m_stat->sp); + err = udp_send(m_stat->pcb, p); + if (err == ERR_MEM) + { + /** @todo release some memory, retry and return tooBig? tooMuchHassle? */ + err = ERR_MEM; + } + else + { + err = ERR_OK; + } + /** disassociate remote address and port with this pcb */ + udp_disconnect(m_stat->pcb); + + pbuf_free(p); + LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_snd_response() done\n")); + return err; + } + else + { + /* first pbuf alloc try or retry alloc failed + very low on memory, couldn't return tooBig */ + return ERR_MEM; + } +} + + +/** + * Sends an generic or enterprise specific trap message. + * + * @param generic_trap is the trap code + * @param eoid points to enterprise object identifier + * @param specific_trap used for enterprise traps when generic_trap == 6 + * @return ERR_OK when success, ERR_MEM if we're out of memory + * + * @note the caller is responsible for filling in outvb in the trap_msg + * @note the use of the enterprise identifier field + * is per RFC1215. + * Use .iso.org.dod.internet.mgmt.mib-2.snmp for generic traps + * and .iso.org.dod.internet.private.enterprises.yourenterprise + * (sysObjectID) for specific traps. + */ +err_t +snmp_send_trap(s8_t generic_trap, struct snmp_obj_id *eoid, s32_t specific_trap) +{ + struct snmp_trap_dst *td; + struct netif *dst_if; + ip_addr_t dst_ip; + struct pbuf *p; + u16_t i,tot_len; + err_t err = ERR_OK; + + for (i=0, td = &trap_dst[0]; ienable != 0) && !ip_addr_isany(&td->dip)) + { + /* network order trap destination */ + ip_addr_copy(trap_msg.dip, td->dip); + /* lookup current source address for this dst */ + dst_if = ip_route(&td->dip); + if (dst_if != NULL) { + ip_addr_copy(dst_ip, dst_if->ip_addr); + /* @todo: what about IPv6? */ + trap_msg.sip_raw[0] = ip4_addr1(&dst_ip); + trap_msg.sip_raw[1] = ip4_addr2(&dst_ip); + trap_msg.sip_raw[2] = ip4_addr3(&dst_ip); + trap_msg.sip_raw[3] = ip4_addr4(&dst_ip); + trap_msg.gen_trap = generic_trap; + trap_msg.spc_trap = specific_trap; + if (generic_trap == SNMP_GENTRAP_ENTERPRISESPC) + { + /* enterprise-Specific trap */ + trap_msg.enterprise = eoid; + } + else + { + /* generic (MIB-II) trap */ + snmp_get_snmpgrpid_ptr(&trap_msg.enterprise); + } + snmp_get_sysuptime(&trap_msg.ts); + + /* pass 0, calculate length fields */ + tot_len = snmp_varbind_list_sum(&trap_msg.outvb); + tot_len = snmp_trap_header_sum(&trap_msg, tot_len); + + /* allocate pbuf(s) */ + p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_POOL); + if (p != NULL) + { + u16_t ofs; + + /* pass 1, encode packet ino the pbuf(s) */ + ofs = snmp_trap_header_enc(&trap_msg, p); + snmp_varbind_list_enc(&trap_msg.outvb, p, ofs); + + snmp_inc_snmpouttraps(); + snmp_inc_snmpoutpkts(); + + /** send to the TRAP destination */ + udp_sendto(trap_msg.pcb, p, &trap_msg.dip, SNMP_TRAP_PORT); + + pbuf_free(p); + } else { + err = ERR_MEM; + } + } else { + /* routing error */ + err = ERR_RTE; + } + } + } + return err; +} + +void +snmp_coldstart_trap(void) +{ + trap_msg.outvb.head = NULL; + trap_msg.outvb.tail = NULL; + trap_msg.outvb.count = 0; + snmp_send_trap(SNMP_GENTRAP_COLDSTART, NULL, 0); +} + +void +snmp_authfail_trap(void) +{ + u8_t enable; + snmp_get_snmpenableauthentraps(&enable); + if (enable == 1) + { + trap_msg.outvb.head = NULL; + trap_msg.outvb.tail = NULL; + trap_msg.outvb.count = 0; + snmp_send_trap(SNMP_GENTRAP_AUTHFAIL, NULL, 0); + } +} + +/** + * Sums response header field lengths from tail to head and + * returns resp_header_lengths for second encoding pass. + * + * @param vb_len varbind-list length + * @param rhl points to returned header lengths + * @return the required length for encoding the response header + */ +static u16_t +snmp_resp_header_sum(struct snmp_msg_pstat *m_stat, u16_t vb_len) +{ + u16_t tot_len; + struct snmp_resp_header_lengths *rhl; + + rhl = &m_stat->rhl; + tot_len = vb_len; + snmp_asn1_enc_s32t_cnt(m_stat->error_index, &rhl->erridxlen); + snmp_asn1_enc_length_cnt(rhl->erridxlen, &rhl->erridxlenlen); + tot_len += 1 + rhl->erridxlenlen + rhl->erridxlen; + + snmp_asn1_enc_s32t_cnt(m_stat->error_status, &rhl->errstatlen); + snmp_asn1_enc_length_cnt(rhl->errstatlen, &rhl->errstatlenlen); + tot_len += 1 + rhl->errstatlenlen + rhl->errstatlen; + + snmp_asn1_enc_s32t_cnt(m_stat->rid, &rhl->ridlen); + snmp_asn1_enc_length_cnt(rhl->ridlen, &rhl->ridlenlen); + tot_len += 1 + rhl->ridlenlen + rhl->ridlen; + + rhl->pdulen = tot_len; + snmp_asn1_enc_length_cnt(rhl->pdulen, &rhl->pdulenlen); + tot_len += 1 + rhl->pdulenlen; + + rhl->comlen = m_stat->com_strlen; + snmp_asn1_enc_length_cnt(rhl->comlen, &rhl->comlenlen); + tot_len += 1 + rhl->comlenlen + rhl->comlen; + + snmp_asn1_enc_s32t_cnt(snmp_version, &rhl->verlen); + snmp_asn1_enc_length_cnt(rhl->verlen, &rhl->verlenlen); + tot_len += 1 + rhl->verlen + rhl->verlenlen; + + rhl->seqlen = tot_len; + snmp_asn1_enc_length_cnt(rhl->seqlen, &rhl->seqlenlen); + tot_len += 1 + rhl->seqlenlen; + + return tot_len; +} + +/** + * Sums trap header field lengths from tail to head and + * returns trap_header_lengths for second encoding pass. + * + * @param vb_len varbind-list length + * @param thl points to returned header lengths + * @return the required length for encoding the trap header + */ +static u16_t +snmp_trap_header_sum(struct snmp_msg_trap *m_trap, u16_t vb_len) +{ + u16_t tot_len; + struct snmp_trap_header_lengths *thl; + + thl = &m_trap->thl; + tot_len = vb_len; + + snmp_asn1_enc_u32t_cnt(m_trap->ts, &thl->tslen); + snmp_asn1_enc_length_cnt(thl->tslen, &thl->tslenlen); + tot_len += 1 + thl->tslen + thl->tslenlen; + + snmp_asn1_enc_s32t_cnt(m_trap->spc_trap, &thl->strplen); + snmp_asn1_enc_length_cnt(thl->strplen, &thl->strplenlen); + tot_len += 1 + thl->strplen + thl->strplenlen; + + snmp_asn1_enc_s32t_cnt(m_trap->gen_trap, &thl->gtrplen); + snmp_asn1_enc_length_cnt(thl->gtrplen, &thl->gtrplenlen); + tot_len += 1 + thl->gtrplen + thl->gtrplenlen; + + thl->aaddrlen = 4; + snmp_asn1_enc_length_cnt(thl->aaddrlen, &thl->aaddrlenlen); + tot_len += 1 + thl->aaddrlen + thl->aaddrlenlen; + + snmp_asn1_enc_oid_cnt(m_trap->enterprise->len, &m_trap->enterprise->id[0], &thl->eidlen); + snmp_asn1_enc_length_cnt(thl->eidlen, &thl->eidlenlen); + tot_len += 1 + thl->eidlen + thl->eidlenlen; + + thl->pdulen = tot_len; + snmp_asn1_enc_length_cnt(thl->pdulen, &thl->pdulenlen); + tot_len += 1 + thl->pdulenlen; + + thl->comlen = sizeof(snmp_publiccommunity) - 1; + snmp_asn1_enc_length_cnt(thl->comlen, &thl->comlenlen); + tot_len += 1 + thl->comlenlen + thl->comlen; + + snmp_asn1_enc_s32t_cnt(snmp_version, &thl->verlen); + snmp_asn1_enc_length_cnt(thl->verlen, &thl->verlenlen); + tot_len += 1 + thl->verlen + thl->verlenlen; + + thl->seqlen = tot_len; + snmp_asn1_enc_length_cnt(thl->seqlen, &thl->seqlenlen); + tot_len += 1 + thl->seqlenlen; + + return tot_len; +} + +/** + * Sums varbind lengths from tail to head and + * annotates lengths in varbind for second encoding pass. + * + * @param root points to the root of the variable binding list + * @return the required length for encoding the variable bindings + */ +static u16_t +snmp_varbind_list_sum(struct snmp_varbind_root *root) +{ + struct snmp_varbind *vb; + u32_t *uint_ptr; + s32_t *sint_ptr; + u16_t tot_len; + + tot_len = 0; + vb = root->tail; + while ( vb != NULL ) + { + /* encoded value lenght depends on type */ + switch (vb->value_type) + { + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG): + sint_ptr = (s32_t*)vb->value; + snmp_asn1_enc_s32t_cnt(*sint_ptr, &vb->vlen); + break; + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS): + uint_ptr = (u32_t*)vb->value; + snmp_asn1_enc_u32t_cnt(*uint_ptr, &vb->vlen); + break; + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR): + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_NUL): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_OPAQUE): + vb->vlen = vb->value_len; + break; + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID): + sint_ptr = (s32_t*)vb->value; + snmp_asn1_enc_oid_cnt(vb->value_len / sizeof(s32_t), sint_ptr, &vb->vlen); + break; + default: + /* unsupported type */ + vb->vlen = 0; + break; + }; + /* encoding length of value length field */ + snmp_asn1_enc_length_cnt(vb->vlen, &vb->vlenlen); + snmp_asn1_enc_oid_cnt(vb->ident_len, vb->ident, &vb->olen); + snmp_asn1_enc_length_cnt(vb->olen, &vb->olenlen); + + vb->seqlen = 1 + vb->vlenlen + vb->vlen; + vb->seqlen += 1 + vb->olenlen + vb->olen; + snmp_asn1_enc_length_cnt(vb->seqlen, &vb->seqlenlen); + + /* varbind seq */ + tot_len += 1 + vb->seqlenlen + vb->seqlen; + + vb = vb->prev; + } + + /* varbind-list seq */ + root->seqlen = tot_len; + snmp_asn1_enc_length_cnt(root->seqlen, &root->seqlenlen); + tot_len += 1 + root->seqlenlen; + + return tot_len; +} + +/** + * Encodes response header from head to tail. + */ +static u16_t +snmp_resp_header_enc(struct snmp_msg_pstat *m_stat, struct pbuf *p) +{ + u16_t ofs; + + ofs = 0; + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_stat->rhl.seqlen); + ofs += m_stat->rhl.seqlenlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_stat->rhl.verlen); + ofs += m_stat->rhl.verlenlen; + snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.verlen, snmp_version); + ofs += m_stat->rhl.verlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_stat->rhl.comlen); + ofs += m_stat->rhl.comlenlen; + snmp_asn1_enc_raw(p, ofs, m_stat->rhl.comlen, m_stat->community); + ofs += m_stat->rhl.comlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_GET_RESP)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_stat->rhl.pdulen); + ofs += m_stat->rhl.pdulenlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_stat->rhl.ridlen); + ofs += m_stat->rhl.ridlenlen; + snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.ridlen, m_stat->rid); + ofs += m_stat->rhl.ridlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_stat->rhl.errstatlen); + ofs += m_stat->rhl.errstatlenlen; + snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.errstatlen, m_stat->error_status); + ofs += m_stat->rhl.errstatlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_stat->rhl.erridxlen); + ofs += m_stat->rhl.erridxlenlen; + snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.erridxlen, m_stat->error_index); + ofs += m_stat->rhl.erridxlen; + + return ofs; +} + +/** + * Encodes trap header from head to tail. + */ +static u16_t +snmp_trap_header_enc(struct snmp_msg_trap *m_trap, struct pbuf *p) +{ + u16_t ofs; + + ofs = 0; + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_trap->thl.seqlen); + ofs += m_trap->thl.seqlenlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_trap->thl.verlen); + ofs += m_trap->thl.verlenlen; + snmp_asn1_enc_s32t(p, ofs, m_trap->thl.verlen, snmp_version); + ofs += m_trap->thl.verlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_trap->thl.comlen); + ofs += m_trap->thl.comlenlen; + snmp_asn1_enc_raw(p, ofs, m_trap->thl.comlen, (u8_t *)&snmp_publiccommunity[0]); + ofs += m_trap->thl.comlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_TRAP)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_trap->thl.pdulen); + ofs += m_trap->thl.pdulenlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_trap->thl.eidlen); + ofs += m_trap->thl.eidlenlen; + snmp_asn1_enc_oid(p, ofs, m_trap->enterprise->len, &m_trap->enterprise->id[0]); + ofs += m_trap->thl.eidlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_trap->thl.aaddrlen); + ofs += m_trap->thl.aaddrlenlen; + snmp_asn1_enc_raw(p, ofs, m_trap->thl.aaddrlen, &m_trap->sip_raw[0]); + ofs += m_trap->thl.aaddrlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_trap->thl.gtrplen); + ofs += m_trap->thl.gtrplenlen; + snmp_asn1_enc_u32t(p, ofs, m_trap->thl.gtrplen, m_trap->gen_trap); + ofs += m_trap->thl.gtrplen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_trap->thl.strplen); + ofs += m_trap->thl.strplenlen; + snmp_asn1_enc_u32t(p, ofs, m_trap->thl.strplen, m_trap->spc_trap); + ofs += m_trap->thl.strplen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, m_trap->thl.tslen); + ofs += m_trap->thl.tslenlen; + snmp_asn1_enc_u32t(p, ofs, m_trap->thl.tslen, m_trap->ts); + ofs += m_trap->thl.tslen; + + return ofs; +} + +/** + * Encodes varbind list from head to tail. + */ +static u16_t +snmp_varbind_list_enc(struct snmp_varbind_root *root, struct pbuf *p, u16_t ofs) +{ + struct snmp_varbind *vb; + s32_t *sint_ptr; + u32_t *uint_ptr; + u8_t *raw_ptr; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, root->seqlen); + ofs += root->seqlenlen; + + vb = root->head; + while ( vb != NULL ) + { + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, vb->seqlen); + ofs += vb->seqlenlen; + + snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID)); + ofs += 1; + snmp_asn1_enc_length(p, ofs, vb->olen); + ofs += vb->olenlen; + snmp_asn1_enc_oid(p, ofs, vb->ident_len, &vb->ident[0]); + ofs += vb->olen; + + snmp_asn1_enc_type(p, ofs, vb->value_type); + ofs += 1; + snmp_asn1_enc_length(p, ofs, vb->vlen); + ofs += vb->vlenlen; + + switch (vb->value_type) + { + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG): + sint_ptr = (s32_t*)vb->value; + snmp_asn1_enc_s32t(p, ofs, vb->vlen, *sint_ptr); + break; + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS): + uint_ptr = (u32_t*)vb->value; + snmp_asn1_enc_u32t(p, ofs, vb->vlen, *uint_ptr); + break; + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR): + case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_OPAQUE): + raw_ptr = (u8_t*)vb->value; + snmp_asn1_enc_raw(p, ofs, vb->vlen, raw_ptr); + break; + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_NUL): + break; + case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID): + sint_ptr = (s32_t*)vb->value; + snmp_asn1_enc_oid(p, ofs, vb->value_len / sizeof(s32_t), sint_ptr); + break; + default: + /* unsupported type */ + break; + }; + ofs += vb->vlen; + vb = vb->next; + } + return ofs; +} + +#endif /* LWIP_SNMP */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/core/stats.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/stats.c new file mode 100644 index 0000000..ff97853 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/stats.c @@ -0,0 +1,181 @@ +/** + * @file + * Statistics module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_STATS /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/stats.h" +#include "lwip/mem.h" + +#include + +struct stats_ lwip_stats; + +void stats_init(void) +{ +#ifdef LWIP_DEBUG +#if MEMP_STATS + const char * memp_names[] = { +#define LWIP_MEMPOOL(name,num,size,desc) desc, +#include "lwip/memp_std.h" + }; + int i; + for (i = 0; i < MEMP_MAX; i++) { + lwip_stats.memp[i].name = memp_names[i]; + } +#endif /* MEMP_STATS */ +#if MEM_STATS + lwip_stats.mem.name = "MEM"; +#endif /* MEM_STATS */ +#endif /* LWIP_DEBUG */ +} + +#if LWIP_STATS_DISPLAY +void +stats_display_proto(struct stats_proto *proto, const char *name) +{ + LWIP_PLATFORM_DIAG(("\n%s\n\t", name)); + LWIP_PLATFORM_DIAG(("xmit: %"STAT_COUNTER_F"\n\t", proto->xmit)); + LWIP_PLATFORM_DIAG(("recv: %"STAT_COUNTER_F"\n\t", proto->recv)); + LWIP_PLATFORM_DIAG(("fw: %"STAT_COUNTER_F"\n\t", proto->fw)); + LWIP_PLATFORM_DIAG(("drop: %"STAT_COUNTER_F"\n\t", proto->drop)); + LWIP_PLATFORM_DIAG(("chkerr: %"STAT_COUNTER_F"\n\t", proto->chkerr)); + LWIP_PLATFORM_DIAG(("lenerr: %"STAT_COUNTER_F"\n\t", proto->lenerr)); + LWIP_PLATFORM_DIAG(("memerr: %"STAT_COUNTER_F"\n\t", proto->memerr)); + LWIP_PLATFORM_DIAG(("rterr: %"STAT_COUNTER_F"\n\t", proto->rterr)); + LWIP_PLATFORM_DIAG(("proterr: %"STAT_COUNTER_F"\n\t", proto->proterr)); + LWIP_PLATFORM_DIAG(("opterr: %"STAT_COUNTER_F"\n\t", proto->opterr)); + LWIP_PLATFORM_DIAG(("err: %"STAT_COUNTER_F"\n\t", proto->err)); + LWIP_PLATFORM_DIAG(("cachehit: %"STAT_COUNTER_F"\n", proto->cachehit)); +} + +#if IGMP_STATS || MLD6_STATS +void +stats_display_igmp(struct stats_igmp *igmp, const char *name) +{ + LWIP_PLATFORM_DIAG(("\n%s\n\t", name)); + LWIP_PLATFORM_DIAG(("xmit: %"STAT_COUNTER_F"\n\t", igmp->xmit)); + LWIP_PLATFORM_DIAG(("recv: %"STAT_COUNTER_F"\n\t", igmp->recv)); + LWIP_PLATFORM_DIAG(("drop: %"STAT_COUNTER_F"\n\t", igmp->drop)); + LWIP_PLATFORM_DIAG(("chkerr: %"STAT_COUNTER_F"\n\t", igmp->chkerr)); + LWIP_PLATFORM_DIAG(("lenerr: %"STAT_COUNTER_F"\n\t", igmp->lenerr)); + LWIP_PLATFORM_DIAG(("memerr: %"STAT_COUNTER_F"\n\t", igmp->memerr)); + LWIP_PLATFORM_DIAG(("proterr: %"STAT_COUNTER_F"\n\t", igmp->proterr)); + LWIP_PLATFORM_DIAG(("rx_v1: %"STAT_COUNTER_F"\n\t", igmp->rx_v1)); + LWIP_PLATFORM_DIAG(("rx_group: %"STAT_COUNTER_F"\n\t", igmp->rx_group)); + LWIP_PLATFORM_DIAG(("rx_general: %"STAT_COUNTER_F"\n\t", igmp->rx_general)); + LWIP_PLATFORM_DIAG(("rx_report: %"STAT_COUNTER_F"\n\t", igmp->rx_report)); + LWIP_PLATFORM_DIAG(("tx_join: %"STAT_COUNTER_F"\n\t", igmp->tx_join)); + LWIP_PLATFORM_DIAG(("tx_leave: %"STAT_COUNTER_F"\n\t", igmp->tx_leave)); + LWIP_PLATFORM_DIAG(("tx_report: %"STAT_COUNTER_F"\n\t", igmp->tx_report)); +} +#endif /* IGMP_STATS || MLD6_STATS */ + +#if MEM_STATS || MEMP_STATS +void +stats_display_mem(struct stats_mem *mem, const char *name) +{ + LWIP_PLATFORM_DIAG(("\nMEM %s\n\t", name)); + LWIP_PLATFORM_DIAG(("avail: %"U32_F"\n\t", (u32_t)mem->avail)); + LWIP_PLATFORM_DIAG(("used: %"U32_F"\n\t", (u32_t)mem->used)); + LWIP_PLATFORM_DIAG(("max: %"U32_F"\n\t", (u32_t)mem->max)); + LWIP_PLATFORM_DIAG(("err: %"U32_F"\n", (u32_t)mem->err)); +} + +#if MEMP_STATS +void +stats_display_memp(struct stats_mem *mem, int index) +{ + char * memp_names[] = { +#define LWIP_MEMPOOL(name,num,size,desc) desc, +#include "lwip/memp_std.h" + }; + if(index < MEMP_MAX) { + stats_display_mem(mem, memp_names[index]); + } +} +#endif /* MEMP_STATS */ +#endif /* MEM_STATS || MEMP_STATS */ + +#if SYS_STATS +void +stats_display_sys(struct stats_sys *sys) +{ + LWIP_PLATFORM_DIAG(("\nSYS\n\t")); + LWIP_PLATFORM_DIAG(("sem.used: %"U32_F"\n\t", (u32_t)sys->sem.used)); + LWIP_PLATFORM_DIAG(("sem.max: %"U32_F"\n\t", (u32_t)sys->sem.max)); + LWIP_PLATFORM_DIAG(("sem.err: %"U32_F"\n\t", (u32_t)sys->sem.err)); + LWIP_PLATFORM_DIAG(("mutex.used: %"U32_F"\n\t", (u32_t)sys->mutex.used)); + LWIP_PLATFORM_DIAG(("mutex.max: %"U32_F"\n\t", (u32_t)sys->mutex.max)); + LWIP_PLATFORM_DIAG(("mutex.err: %"U32_F"\n\t", (u32_t)sys->mutex.err)); + LWIP_PLATFORM_DIAG(("mbox.used: %"U32_F"\n\t", (u32_t)sys->mbox.used)); + LWIP_PLATFORM_DIAG(("mbox.max: %"U32_F"\n\t", (u32_t)sys->mbox.max)); + LWIP_PLATFORM_DIAG(("mbox.err: %"U32_F"\n\t", (u32_t)sys->mbox.err)); +} +#endif /* SYS_STATS */ + +void +stats_display(void) +{ + s16_t i; + + LINK_STATS_DISPLAY(); + ETHARP_STATS_DISPLAY(); + IPFRAG_STATS_DISPLAY(); + IP6_FRAG_STATS_DISPLAY(); + IP_STATS_DISPLAY(); + ND6_STATS_DISPLAY(); + IP6_STATS_DISPLAY(); + IGMP_STATS_DISPLAY(); + MLD6_STATS_DISPLAY(); + ICMP_STATS_DISPLAY(); + ICMP6_STATS_DISPLAY(); + UDP_STATS_DISPLAY(); + TCP_STATS_DISPLAY(); + MEM_STATS_DISPLAY(); + for (i = 0; i < MEMP_MAX; i++) { + MEMP_STATS_DISPLAY(i); + } + SYS_STATS_DISPLAY(); +} +#endif /* LWIP_STATS_DISPLAY */ + +#endif /* LWIP_STATS */ + diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/core/sys.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/sys.c new file mode 100644 index 0000000..f177737 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/sys.c @@ -0,0 +1,68 @@ +/** + * @file + * lwIP Operating System abstraction + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/sys.h" + +/* Most of the functions defined in sys.h must be implemented in the + * architecture-dependent file sys_arch.c */ + +#if !NO_SYS + +#ifndef sys_msleep +/** + * Sleep for some ms. Timeouts are NOT processed while sleeping. + * + * @param ms number of milliseconds to sleep + */ +void +sys_msleep(u32_t ms) +{ + if (ms > 0) { + sys_sem_t delaysem; + err_t err = sys_sem_new(&delaysem, 0); + if (err == ERR_OK) { + sys_arch_sem_wait(&delaysem, ms); + sys_sem_free(&delaysem); + } + } +} +#endif /* sys_msleep */ + +#endif /* !NO_SYS */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/core/tcp.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/tcp.c new file mode 100644 index 0000000..5edc73c --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/tcp.c @@ -0,0 +1,1880 @@ +/** + * @file + * Transmission Control Protocol for IP + * + * This file contains common functions for the TCP implementation, such as functinos + * for manipulating the data structures and the TCP timer functions. TCP functions + * related to input and output is found in tcp_in.c and tcp_out.c respectively. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/snmp.h" +#include "lwip/tcp.h" +#include "lwip/tcp_impl.h" +#include "lwip/debug.h" +#include "lwip/stats.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/nd6.h" + +#include + +#ifndef TCP_LOCAL_PORT_RANGE_START +/* From http://www.iana.org/assignments/port-numbers: + "The Dynamic and/or Private Ports are those from 49152 through 65535" */ +#define TCP_LOCAL_PORT_RANGE_START 0xc000 +#define TCP_LOCAL_PORT_RANGE_END 0xffff +#define TCP_ENSURE_LOCAL_PORT_RANGE(port) (((port) & ~TCP_LOCAL_PORT_RANGE_START) + TCP_LOCAL_PORT_RANGE_START) +#endif + +#if LWIP_TCP_KEEPALIVE +#define TCP_KEEP_DUR(pcb) ((pcb)->keep_cnt * (pcb)->keep_intvl) +#define TCP_KEEP_INTVL(pcb) ((pcb)->keep_intvl) +#else /* LWIP_TCP_KEEPALIVE */ +#define TCP_KEEP_DUR(pcb) TCP_MAXIDLE +#define TCP_KEEP_INTVL(pcb) TCP_KEEPINTVL_DEFAULT +#endif /* LWIP_TCP_KEEPALIVE */ + +const char * const tcp_state_str[] = { + "CLOSED", + "LISTEN", + "SYN_SENT", + "SYN_RCVD", + "ESTABLISHED", + "FIN_WAIT_1", + "FIN_WAIT_2", + "CLOSE_WAIT", + "CLOSING", + "LAST_ACK", + "TIME_WAIT" +}; + +/* last local TCP port */ +static u16_t tcp_port = TCP_LOCAL_PORT_RANGE_START; + +/* Incremented every coarse grained timer shot (typically every 500 ms). */ +u32_t tcp_ticks; +const u8_t tcp_backoff[13] = + { 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7}; + /* Times per slowtmr hits */ +const u8_t tcp_persist_backoff[7] = { 3, 6, 12, 24, 48, 96, 120 }; + +/* The TCP PCB lists. */ + +/** List of all TCP PCBs bound but not yet (connected || listening) */ +struct tcp_pcb *tcp_bound_pcbs; +/** List of all TCP PCBs in LISTEN state */ +union tcp_listen_pcbs_t tcp_listen_pcbs; +/** List of all TCP PCBs that are in a state in which + * they accept or send data. */ +struct tcp_pcb *tcp_active_pcbs; +/** List of all TCP PCBs in TIME-WAIT state */ +struct tcp_pcb *tcp_tw_pcbs; + +#define NUM_TCP_PCB_LISTS 4 +#define NUM_TCP_PCB_LISTS_NO_TIME_WAIT 3 +/** An array with all (non-temporary) PCB lists, mainly used for smaller code size */ +struct tcp_pcb ** const tcp_pcb_lists[] = {&tcp_listen_pcbs.pcbs, &tcp_bound_pcbs, + &tcp_active_pcbs, &tcp_tw_pcbs}; + +/** Only used for temporary storage. */ +struct tcp_pcb *tcp_tmp_pcb; + +u8_t tcp_active_pcbs_changed; + +/** Timer counter to handle calling slow-timer from tcp_tmr() */ +static u8_t tcp_timer; +static u8_t tcp_timer_ctr; +static u16_t tcp_new_port(void); + +/** + * Initialize this module. + */ +void +tcp_init(void) +{ +#if LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) + tcp_port = TCP_ENSURE_LOCAL_PORT_RANGE(LWIP_RAND()); +#endif /* LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) */ +} + +/** + * Called periodically to dispatch TCP timers. + */ +void +tcp_tmr(void) +{ + /* Call tcp_fasttmr() every 250 ms */ + tcp_fasttmr(); + + if (++tcp_timer & 1) { + /* Call tcp_tmr() every 500 ms, i.e., every other timer + tcp_tmr() is called. */ + tcp_slowtmr(); + } +} + +/** + * Closes the TX side of a connection held by the PCB. + * For tcp_close(), a RST is sent if the application didn't receive all data + * (tcp_recved() not called for all data passed to recv callback). + * + * Listening pcbs are freed and may not be referenced any more. + * Connection pcbs are freed if not yet connected and may not be referenced + * any more. If a connection is established (at least SYN received or in + * a closing state), the connection is closed, and put in a closing state. + * The pcb is then automatically freed in tcp_slowtmr(). It is therefore + * unsafe to reference it. + * + * @param pcb the tcp_pcb to close + * @return ERR_OK if connection has been closed + * another err_t if closing failed and pcb is not freed + */ +static err_t +tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data) +{ + err_t err; + + if (rst_on_unacked_data && ((pcb->state == ESTABLISHED) || (pcb->state == CLOSE_WAIT))) { + if ((pcb->refused_data != NULL) || (pcb->rcv_wnd != TCP_WND)) { + /* Not all data received by application, send RST to tell the remote + side about this. */ + LWIP_ASSERT("pcb->flags & TF_RXCLOSED", pcb->flags & TF_RXCLOSED); + + /* don't call tcp_abort here: we must not deallocate the pcb since + that might not be expected when calling tcp_close */ + tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip, + pcb->local_port, pcb->remote_port, PCB_ISIPV6(pcb)); + + tcp_pcb_purge(pcb); + TCP_RMV_ACTIVE(pcb); + if (pcb->state == ESTABLISHED) { + /* move to TIME_WAIT since we close actively */ + pcb->state = TIME_WAIT; + TCP_REG(&tcp_tw_pcbs, pcb); + } else { + /* CLOSE_WAIT: deallocate the pcb since we already sent a RST for it */ + memp_free(MEMP_TCP_PCB, pcb); + } + return ERR_OK; + } + } + + switch (pcb->state) { + case CLOSED: + /* Closing a pcb in the CLOSED state might seem erroneous, + * however, it is in this state once allocated and as yet unused + * and the user needs some way to free it should the need arise. + * Calling tcp_close() with a pcb that has already been closed, (i.e. twice) + * or for a pcb that has been used and then entered the CLOSED state + * is erroneous, but this should never happen as the pcb has in those cases + * been freed, and so any remaining handles are bogus. */ + err = ERR_OK; + if (pcb->local_port != 0) { + TCP_RMV(&tcp_bound_pcbs, pcb); + } + memp_free(MEMP_TCP_PCB, pcb); + pcb = NULL; + break; + case LISTEN: + err = ERR_OK; + tcp_pcb_remove(&tcp_listen_pcbs.pcbs, pcb); + memp_free(MEMP_TCP_PCB_LISTEN, pcb); + pcb = NULL; + break; + case SYN_SENT: + err = ERR_OK; + TCP_PCB_REMOVE_ACTIVE(pcb); + memp_free(MEMP_TCP_PCB, pcb); + pcb = NULL; + snmp_inc_tcpattemptfails(); + break; + case SYN_RCVD: + err = tcp_send_fin(pcb); + if (err == ERR_OK) { + snmp_inc_tcpattemptfails(); + pcb->state = FIN_WAIT_1; + } + break; + case ESTABLISHED: + err = tcp_send_fin(pcb); + if (err == ERR_OK) { + snmp_inc_tcpestabresets(); + pcb->state = FIN_WAIT_1; + } + break; + case CLOSE_WAIT: + err = tcp_send_fin(pcb); + if (err == ERR_OK) { + snmp_inc_tcpestabresets(); + pcb->state = LAST_ACK; + } + break; + default: + /* Has already been closed, do nothing. */ + err = ERR_OK; + pcb = NULL; + break; + } + + if (pcb != NULL && err == ERR_OK) { + /* To ensure all data has been sent when tcp_close returns, we have + to make sure tcp_output doesn't fail. + Since we don't really have to ensure all data has been sent when tcp_close + returns (unsent data is sent from tcp timer functions, also), we don't care + for the return value of tcp_output for now. */ + tcp_output(pcb); + } + return err; +} + +/** + * Closes the connection held by the PCB. + * + * Listening pcbs are freed and may not be referenced any more. + * Connection pcbs are freed if not yet connected and may not be referenced + * any more. If a connection is established (at least SYN received or in + * a closing state), the connection is closed, and put in a closing state. + * The pcb is then automatically freed in tcp_slowtmr(). It is therefore + * unsafe to reference it (unless an error is returned). + * + * @param pcb the tcp_pcb to close + * @return ERR_OK if connection has been closed + * another err_t if closing failed and pcb is not freed + */ +err_t +tcp_close(struct tcp_pcb *pcb) +{ +#if TCP_DEBUG + LWIP_DEBUGF(TCP_DEBUG, ("tcp_close: closing in ")); + tcp_debug_print_state(pcb->state); +#endif /* TCP_DEBUG */ + + if (pcb->state != LISTEN) { + /* Set a flag not to receive any more data... */ + pcb->flags |= TF_RXCLOSED; + } + /* ... and close */ + return tcp_close_shutdown(pcb, 1); +} + +/** + * Causes all or part of a full-duplex connection of this PCB to be shut down. + * This doesn't deallocate the PCB unless shutting down both sides! + * Shutting down both sides is the same as calling tcp_close, so if it succeds, + * the PCB should not be referenced any more. + * + * @param pcb PCB to shutdown + * @param shut_rx shut down receive side if this is != 0 + * @param shut_tx shut down send side if this is != 0 + * @return ERR_OK if shutdown succeeded (or the PCB has already been shut down) + * another err_t on error. + */ +err_t +tcp_shutdown(struct tcp_pcb *pcb, int shut_rx, int shut_tx) +{ + if (pcb->state == LISTEN) { + return ERR_CONN; + } + if (shut_rx) { + /* shut down the receive side: set a flag not to receive any more data... */ + pcb->flags |= TF_RXCLOSED; + if (shut_tx) { + /* shutting down the tx AND rx side is the same as closing for the raw API */ + return tcp_close_shutdown(pcb, 1); + } + /* ... and free buffered data */ + if (pcb->refused_data != NULL) { + pbuf_free(pcb->refused_data); + pcb->refused_data = NULL; + } + } + if (shut_tx) { + /* This can't happen twice since if it succeeds, the pcb's state is changed. + Only close in these states as the others directly deallocate the PCB */ + switch (pcb->state) { + case SYN_RCVD: + case ESTABLISHED: + case CLOSE_WAIT: + return tcp_close_shutdown(pcb, shut_rx); + default: + /* Not (yet?) connected, cannot shutdown the TX side as that would bring us + into CLOSED state, where the PCB is deallocated. */ + return ERR_CONN; + } + } + return ERR_OK; +} + +/** + * Abandons a connection and optionally sends a RST to the remote + * host. Deletes the local protocol control block. This is done when + * a connection is killed because of shortage of memory. + * + * @param pcb the tcp_pcb to abort + * @param reset boolean to indicate whether a reset should be sent + */ +void +tcp_abandon(struct tcp_pcb *pcb, int reset) +{ + u32_t seqno, ackno; +#if LWIP_CALLBACK_API + tcp_err_fn errf; +#endif /* LWIP_CALLBACK_API */ + void *errf_arg; + + /* pcb->state LISTEN not allowed here */ + LWIP_ASSERT("don't call tcp_abort/tcp_abandon for listen-pcbs", + pcb->state != LISTEN); + /* Figure out on which TCP PCB list we are, and remove us. If we + are in an active state, call the receive function associated with + the PCB with a NULL argument, and send an RST to the remote end. */ + if (pcb->state == TIME_WAIT) { + tcp_pcb_remove(&tcp_tw_pcbs, pcb); + memp_free(MEMP_TCP_PCB, pcb); + } else { + int send_rst = reset && (pcb->state != CLOSED); + seqno = pcb->snd_nxt; + ackno = pcb->rcv_nxt; +#if LWIP_CALLBACK_API + errf = pcb->errf; +#endif /* LWIP_CALLBACK_API */ + errf_arg = pcb->callback_arg; + if ((pcb->state == CLOSED) && (pcb->local_port != 0)) { + /* bound, not yet opened */ + TCP_RMV(&tcp_bound_pcbs, pcb); + } else { + TCP_PCB_REMOVE_ACTIVE(pcb); + } + if (pcb->unacked != NULL) { + tcp_segs_free(pcb->unacked); + } + if (pcb->unsent != NULL) { + tcp_segs_free(pcb->unsent); + } +#if TCP_QUEUE_OOSEQ + if (pcb->ooseq != NULL) { + tcp_segs_free(pcb->ooseq); + } +#endif /* TCP_QUEUE_OOSEQ */ + if (send_rst) { + LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_abandon: sending RST\n")); + tcp_rst(seqno, ackno, &pcb->local_ip, &pcb->remote_ip, pcb->local_port, pcb->remote_port, PCB_ISIPV6(pcb)); + } + memp_free(MEMP_TCP_PCB, pcb); + TCP_EVENT_ERR(errf, errf_arg, ERR_ABRT); + } +} + +/** + * Aborts the connection by sending a RST (reset) segment to the remote + * host. The pcb is deallocated. This function never fails. + * + * ATTENTION: When calling this from one of the TCP callbacks, make + * sure you always return ERR_ABRT (and never return ERR_ABRT otherwise + * or you will risk accessing deallocated memory or memory leaks! + * + * @param pcb the tcp pcb to abort + */ +void +tcp_abort(struct tcp_pcb *pcb) +{ + tcp_abandon(pcb, 1); +} + +/** + * Binds the connection to a local port number and IP address. If the + * IP address is not given (i.e., ipaddr == NULL), the IP address of + * the outgoing network interface is used instead. + * + * @param pcb the tcp_pcb to bind (no check is done whether this pcb is + * already bound!) + * @param ipaddr the local ip address to bind to (use IP_ADDR_ANY to bind + * to any local address + * @param port the local port to bind to + * @return ERR_USE if the port is already in use + * ERR_VAL if bind failed because the PCB is not in a valid state + * ERR_OK if bound + */ +err_t +tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port) +{ + int i; + int max_pcb_list = NUM_TCP_PCB_LISTS; + struct tcp_pcb *cpcb; + + LWIP_ERROR("tcp_bind: can only bind in state CLOSED", pcb->state == CLOSED, return ERR_VAL); + +#if SO_REUSE + /* Unless the REUSEADDR flag is set, + we have to check the pcbs in TIME-WAIT state, also. + We do not dump TIME_WAIT pcb's; they can still be matched by incoming + packets using both local and remote IP addresses and ports to distinguish. + */ + if (ip_get_option(pcb, SOF_REUSEADDR)) { + max_pcb_list = NUM_TCP_PCB_LISTS_NO_TIME_WAIT; + } +#endif /* SO_REUSE */ + + if (port == 0) { + port = tcp_new_port(); + if (port == 0) { + return ERR_BUF; + } + } + + /* Check if the address already is in use (on all lists) */ + for (i = 0; i < max_pcb_list; i++) { + for(cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) { + if (cpcb->local_port == port) { +#if SO_REUSE + /* Omit checking for the same port if both pcbs have REUSEADDR set. + For SO_REUSEADDR, the duplicate-check for a 5-tuple is done in + tcp_connect. */ + if (!ip_get_option(pcb, SOF_REUSEADDR) || + !ip_get_option(cpcb, SOF_REUSEADDR)) +#endif /* SO_REUSE */ + { + /* @todo: check accept_any_ip_version */ + if (IP_PCB_IPVER_EQ(pcb, cpcb) && + (ipX_addr_isany(PCB_ISIPV6(pcb), &cpcb->local_ip) || + ipX_addr_isany(PCB_ISIPV6(pcb), ip_2_ipX(ipaddr)) || + ipX_addr_cmp(PCB_ISIPV6(pcb), &cpcb->local_ip, ip_2_ipX(ipaddr)))) { + return ERR_USE; + } + } + } + } + } + + if (!ipX_addr_isany(PCB_ISIPV6(pcb), ip_2_ipX(ipaddr))) { + ipX_addr_set(PCB_ISIPV6(pcb), &pcb->local_ip, ip_2_ipX(ipaddr)); + } + pcb->local_port = port; + TCP_REG(&tcp_bound_pcbs, pcb); + LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: bind to port %"U16_F"\n", port)); + return ERR_OK; +} +#if LWIP_CALLBACK_API +/** + * Default accept callback if no accept callback is specified by the user. + */ +static err_t +tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err) +{ + LWIP_UNUSED_ARG(arg); + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(err); + + return ERR_ABRT; +} +#endif /* LWIP_CALLBACK_API */ + +/** + * Set the state of the connection to be LISTEN, which means that it + * is able to accept incoming connections. The protocol control block + * is reallocated in order to consume less memory. Setting the + * connection to LISTEN is an irreversible process. + * + * @param pcb the original tcp_pcb + * @param backlog the incoming connections queue limit + * @return tcp_pcb used for listening, consumes less memory. + * + * @note The original tcp_pcb is freed. This function therefore has to be + * called like this: + * tpcb = tcp_listen(tpcb); + */ +struct tcp_pcb * +tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog) +{ + struct tcp_pcb_listen *lpcb; + + LWIP_UNUSED_ARG(backlog); + LWIP_ERROR("tcp_listen: pcb already connected", pcb->state == CLOSED, return NULL); + + /* already listening? */ + if (pcb->state == LISTEN) { + return pcb; + } +#if SO_REUSE + if (ip_get_option(pcb, SOF_REUSEADDR)) { + /* Since SOF_REUSEADDR allows reusing a local address before the pcb's usage + is declared (listen-/connection-pcb), we have to make sure now that + this port is only used once for every local IP. */ + for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { + if ((lpcb->local_port == pcb->local_port) && + IP_PCB_IPVER_EQ(pcb, lpcb)) { + if (ipX_addr_cmp(PCB_ISIPV6(pcb), &lpcb->local_ip, &pcb->local_ip)) { + /* this address/port is already used */ + return NULL; + } + } + } + } +#endif /* SO_REUSE */ + lpcb = (struct tcp_pcb_listen *)memp_malloc(MEMP_TCP_PCB_LISTEN); + if (lpcb == NULL) { + return NULL; + } + lpcb->callback_arg = pcb->callback_arg; + lpcb->local_port = pcb->local_port; + lpcb->state = LISTEN; + lpcb->prio = pcb->prio; + lpcb->so_options = pcb->so_options; + lpcb->ttl = pcb->ttl; + lpcb->tos = pcb->tos; +#if LWIP_IPV6 + PCB_ISIPV6(lpcb) = PCB_ISIPV6(pcb); + lpcb->accept_any_ip_version = 0; +#endif /* LWIP_IPV6 */ + ipX_addr_copy(PCB_ISIPV6(pcb), lpcb->local_ip, pcb->local_ip); + if (pcb->local_port != 0) { + TCP_RMV(&tcp_bound_pcbs, pcb); + } + memp_free(MEMP_TCP_PCB, pcb); +#if LWIP_CALLBACK_API + lpcb->accept = tcp_accept_null; +#endif /* LWIP_CALLBACK_API */ +#if TCP_LISTEN_BACKLOG + lpcb->accepts_pending = 0; + lpcb->backlog = (backlog ? backlog : 1); +#endif /* TCP_LISTEN_BACKLOG */ + TCP_REG(&tcp_listen_pcbs.pcbs, (struct tcp_pcb *)lpcb); + return (struct tcp_pcb *)lpcb; +} + +#if LWIP_IPV6 +/** + * Same as tcp_listen_with_backlog, but allows to accept IPv4 and IPv6 + * connections, if the pcb's local address is set to ANY. + */ +struct tcp_pcb * +tcp_listen_dual_with_backlog(struct tcp_pcb *pcb, u8_t backlog) +{ + struct tcp_pcb *lpcb; + + lpcb = tcp_listen_with_backlog(pcb, backlog); + if ((lpcb != NULL) && + ipX_addr_isany(PCB_ISIPV6(pcb), &pcb->local_ip)) { + /* The default behavior is to accept connections on either + * IPv4 or IPv6, if not bound. */ + /* @see NETCONN_FLAG_IPV6_V6ONLY for changing this behavior */ + ((struct tcp_pcb_listen*)lpcb)->accept_any_ip_version = 1; + } + return lpcb; +} +#endif /* LWIP_IPV6 */ + +/** + * Update the state that tracks the available window space to advertise. + * + * Returns how much extra window would be advertised if we sent an + * update now. + */ +u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb) +{ + u32_t new_right_edge = pcb->rcv_nxt + pcb->rcv_wnd; + + if (TCP_SEQ_GEQ(new_right_edge, pcb->rcv_ann_right_edge + LWIP_MIN((TCP_WND / 2), pcb->mss))) { + /* we can advertise more window */ + pcb->rcv_ann_wnd = pcb->rcv_wnd; + return new_right_edge - pcb->rcv_ann_right_edge; + } else { + if (TCP_SEQ_GT(pcb->rcv_nxt, pcb->rcv_ann_right_edge)) { + /* Can happen due to other end sending out of advertised window, + * but within actual available (but not yet advertised) window */ + pcb->rcv_ann_wnd = 0; + } else { + /* keep the right edge of window constant */ + u32_t new_rcv_ann_wnd = pcb->rcv_ann_right_edge - pcb->rcv_nxt; +#if !LWIP_WND_SCALE + LWIP_ASSERT("new_rcv_ann_wnd <= 0xffff", new_rcv_ann_wnd <= 0xffff); +#endif + pcb->rcv_ann_wnd = (tcpwnd_size_t)new_rcv_ann_wnd; + } + return 0; + } +} + +/** + * This function should be called by the application when it has + * processed the data. The purpose is to advertise a larger window + * when the data has been processed. + * + * @param pcb the tcp_pcb for which data is read + * @param len the amount of bytes that have been read by the application + */ +void +tcp_recved(struct tcp_pcb *pcb, u16_t len) +{ + int wnd_inflation; + + /* pcb->state LISTEN not allowed here */ + LWIP_ASSERT("don't call tcp_recved for listen-pcbs", + pcb->state != LISTEN); + + pcb->rcv_wnd += len; + if (pcb->rcv_wnd > TCP_WND) { + pcb->rcv_wnd = TCP_WND; + } else if(pcb->rcv_wnd == 0) { + /* rcv_wnd overflowed */ + if ((pcb->state == CLOSE_WAIT) || (pcb->state == LAST_ACK)) { + /* In passive close, we allow this, since the FIN bit is added to rcv_wnd + by the stack itself, since it is not mandatory for an application + to call tcp_recved() for the FIN bit, but e.g. the netconn API does so. */ + pcb->rcv_wnd = TCP_WND; + } else { + LWIP_ASSERT("tcp_recved: len wrapped rcv_wnd\n", 0); + } + } + + wnd_inflation = tcp_update_rcv_ann_wnd(pcb); + + /* If the change in the right edge of window is significant (default + * watermark is TCP_WND/4), then send an explicit update now. + * Otherwise wait for a packet to be sent in the normal course of + * events (or more window to be available later) */ + if (wnd_inflation >= TCP_WND_UPDATE_THRESHOLD) { + tcp_ack_now(pcb); + tcp_output(pcb); + } + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_recved: received %"U16_F" bytes, wnd %"U16_F" (%"U16_F").\n", + len, pcb->rcv_wnd, TCP_WND - pcb->rcv_wnd)); +} + +/** + * Allocate a new local TCP port. + * + * @return a new (free) local TCP port number + */ +static u16_t +tcp_new_port(void) +{ + u8_t i; + u16_t n = 0; + struct tcp_pcb *pcb; + +again: + if (tcp_port++ == TCP_LOCAL_PORT_RANGE_END) { + tcp_port = TCP_LOCAL_PORT_RANGE_START; + } + /* Check all PCB lists. */ + for (i = 0; i < NUM_TCP_PCB_LISTS; i++) { + for(pcb = *tcp_pcb_lists[i]; pcb != NULL; pcb = pcb->next) { + if (pcb->local_port == tcp_port) { + if (++n > (TCP_LOCAL_PORT_RANGE_END - TCP_LOCAL_PORT_RANGE_START)) { + return 0; + } + goto again; + } + } + } + return tcp_port; +} + +/** + * Connects to another host. The function given as the "connected" + * argument will be called when the connection has been established. + * + * @param pcb the tcp_pcb used to establish the connection + * @param ipaddr the remote ip address to connect to + * @param port the remote tcp port to connect to + * @param connected callback function to call when connected (on error, + the err calback will be called) + * @return ERR_VAL if invalid arguments are given + * ERR_OK if connect request has been sent + * other err_t values if connect request couldn't be sent + */ +err_t +tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port, + tcp_connected_fn connected) +{ + err_t ret; + u32_t iss; + u16_t old_local_port; + + LWIP_ERROR("tcp_connect: can only connect from state CLOSED", pcb->state == CLOSED, return ERR_ISCONN); + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %"U16_F"\n", port)); + if (ipaddr != NULL) { + ipX_addr_set(PCB_ISIPV6(pcb), &pcb->remote_ip, ip_2_ipX(ipaddr)); + } else { + return ERR_VAL; + } + pcb->remote_port = port; + + /* check if we have a route to the remote host */ + if (ipX_addr_isany(PCB_ISIPV6(pcb), &pcb->local_ip)) { + /* no local IP address set, yet. */ + struct netif *netif; + ipX_addr_t *local_ip; + ipX_route_get_local_ipX(PCB_ISIPV6(pcb), &pcb->local_ip, &pcb->remote_ip, netif, local_ip); + if ((netif == NULL) || (local_ip == NULL)) { + /* Don't even try to send a SYN packet if we have no route + since that will fail. */ + return ERR_RTE; + } + /* Use the address as local address of the pcb. */ + ipX_addr_copy(PCB_ISIPV6(pcb), pcb->local_ip, *local_ip); + } + + old_local_port = pcb->local_port; + if (pcb->local_port == 0) { + pcb->local_port = tcp_new_port(); + if (pcb->local_port == 0) { + return ERR_BUF; + } + } +#if SO_REUSE + if (ip_get_option(pcb, SOF_REUSEADDR)) { + /* Since SOF_REUSEADDR allows reusing a local address, we have to make sure + now that the 5-tuple is unique. */ + struct tcp_pcb *cpcb; + int i; + /* Don't check listen- and bound-PCBs, check active- and TIME-WAIT PCBs. */ + for (i = 2; i < NUM_TCP_PCB_LISTS; i++) { + for(cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) { + if ((cpcb->local_port == pcb->local_port) && + (cpcb->remote_port == port) && + IP_PCB_IPVER_EQ(cpcb, pcb) && + ipX_addr_cmp(PCB_ISIPV6(pcb), &cpcb->local_ip, &pcb->local_ip) && + ipX_addr_cmp(PCB_ISIPV6(pcb), &cpcb->remote_ip, ip_2_ipX(ipaddr))) { + /* linux returns EISCONN here, but ERR_USE should be OK for us */ + return ERR_USE; + } + } + } + } +#endif /* SO_REUSE */ + iss = tcp_next_iss(); + pcb->rcv_nxt = 0; + pcb->snd_nxt = iss; + pcb->lastack = iss - 1; + pcb->snd_lbb = iss - 1; + pcb->rcv_wnd = TCP_WND; + pcb->rcv_ann_wnd = TCP_WND; + pcb->rcv_ann_right_edge = pcb->rcv_nxt; + pcb->snd_wnd = TCP_WND; + /* As initial send MSS, we use TCP_MSS but limit it to 536. + The send MSS is updated when an MSS option is received. */ + pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS; +#if TCP_CALCULATE_EFF_SEND_MSS + pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->local_ip, &pcb->remote_ip, PCB_ISIPV6(pcb)); +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + pcb->cwnd = 1; + pcb->ssthresh = pcb->mss * 10; +#if LWIP_CALLBACK_API + pcb->connected = connected; +#else /* LWIP_CALLBACK_API */ + LWIP_UNUSED_ARG(connected); +#endif /* LWIP_CALLBACK_API */ + + /* Send a SYN together with the MSS option. */ + ret = tcp_enqueue_flags(pcb, TCP_SYN); + if (ret == ERR_OK) { + /* SYN segment was enqueued, changed the pcbs state now */ + pcb->state = SYN_SENT; + if (old_local_port != 0) { + TCP_RMV(&tcp_bound_pcbs, pcb); + } + TCP_REG_ACTIVE(pcb); + snmp_inc_tcpactiveopens(); + + tcp_output(pcb); + } + return ret; +} + +/** + * Called every 500 ms and implements the retransmission timer and the timer that + * removes PCBs that have been in TIME-WAIT for enough time. It also increments + * various timers such as the inactivity timer in each PCB. + * + * Automatically called from tcp_tmr(). + */ +void +tcp_slowtmr(void) +{ + struct tcp_pcb *pcb, *prev; + tcpwnd_size_t eff_wnd; + u8_t pcb_remove; /* flag if a PCB should be removed */ + u8_t pcb_reset; /* flag if a RST should be sent when removing */ + err_t err; + + err = ERR_OK; + + ++tcp_ticks; + ++tcp_timer_ctr; + +tcp_slowtmr_start: + /* Steps through all of the active PCBs. */ + prev = NULL; + pcb = tcp_active_pcbs; + if (pcb == NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: no active pcbs\n")); + } + while (pcb != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: processing active pcb\n")); + LWIP_ASSERT("tcp_slowtmr: active pcb->state != CLOSED\n", pcb->state != CLOSED); + LWIP_ASSERT("tcp_slowtmr: active pcb->state != LISTEN\n", pcb->state != LISTEN); + LWIP_ASSERT("tcp_slowtmr: active pcb->state != TIME-WAIT\n", pcb->state != TIME_WAIT); + if (pcb->last_timer == tcp_timer_ctr) { + /* skip this pcb, we have already processed it */ + pcb = pcb->next; + continue; + } + pcb->last_timer = tcp_timer_ctr; + + pcb_remove = 0; + pcb_reset = 0; + + if (pcb->state == SYN_SENT && pcb->nrtx == TCP_SYNMAXRTX) { + ++pcb_remove; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max SYN retries reached\n")); + } + else if (pcb->nrtx == TCP_MAXRTX) { + ++pcb_remove; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max DATA retries reached\n")); + } else { + if (pcb->persist_backoff > 0) { + /* If snd_wnd is zero, use persist timer to send 1 byte probes + * instead of using the standard retransmission mechanism. */ + pcb->persist_cnt++; + if (pcb->persist_cnt >= tcp_persist_backoff[pcb->persist_backoff-1]) { + pcb->persist_cnt = 0; + if (pcb->persist_backoff < sizeof(tcp_persist_backoff)) { + pcb->persist_backoff++; + } + tcp_zero_window_probe(pcb); + } + } else { + /* Increase the retransmission timer if it is running */ + if(pcb->rtime >= 0) { + ++pcb->rtime; + } + + if (pcb->unacked != NULL && pcb->rtime >= pcb->rto) { + /* Time for a retransmission. */ + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_slowtmr: rtime %"S16_F + " pcb->rto %"S16_F"\n", + pcb->rtime, pcb->rto)); + + /* Double retransmission time-out unless we are trying to + * connect to somebody (i.e., we are in SYN_SENT). */ + if (pcb->state != SYN_SENT) { + pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[pcb->nrtx]; + } + + /* Reset the retransmission timer. */ + pcb->rtime = 0; + + /* Reduce congestion window and ssthresh. */ + eff_wnd = LWIP_MIN(pcb->cwnd, pcb->snd_wnd); + pcb->ssthresh = eff_wnd >> 1; + if (pcb->ssthresh < (tcpwnd_size_t)(pcb->mss << 1)) { + pcb->ssthresh = (pcb->mss << 1); + } + pcb->cwnd = pcb->mss; + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %"TCPWNDSIZE_F + " ssthresh %"TCPWNDSIZE_F"\n", + pcb->cwnd, pcb->ssthresh)); + + /* The following needs to be called AFTER cwnd is set to one + mss - STJ */ + tcp_rexmit_rto(pcb); + } + } + } + /* Check if this PCB has stayed too long in FIN-WAIT-2 */ + if (pcb->state == FIN_WAIT_2) { + /* If this PCB is in FIN_WAIT_2 because of SHUT_WR don't let it time out. */ + if (pcb->flags & TF_RXCLOSED) { + /* PCB was fully closed (either through close() or SHUT_RDWR): + normal FIN-WAIT timeout handling. */ + if ((u32_t)(tcp_ticks - pcb->tmr) > + TCP_FIN_WAIT_TIMEOUT / TCP_SLOW_INTERVAL) { + ++pcb_remove; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in FIN-WAIT-2\n")); + } + } + } + + /* Check if KEEPALIVE should be sent */ + if(ip_get_option(pcb, SOF_KEEPALIVE) && + ((pcb->state == ESTABLISHED) || + (pcb->state == CLOSE_WAIT))) { + if((u32_t)(tcp_ticks - pcb->tmr) > + (pcb->keep_idle + TCP_KEEP_DUR(pcb)) / TCP_SLOW_INTERVAL) + { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to ")); + ipX_addr_debug_print(PCB_ISIPV6(pcb), TCP_DEBUG, &pcb->remote_ip); + LWIP_DEBUGF(TCP_DEBUG, ("\n")); + + ++pcb_remove; + ++pcb_reset; + } + else if((u32_t)(tcp_ticks - pcb->tmr) > + (pcb->keep_idle + pcb->keep_cnt_sent * TCP_KEEP_INTVL(pcb)) + / TCP_SLOW_INTERVAL) + { + tcp_keepalive(pcb); + pcb->keep_cnt_sent++; + } + } + + /* If this PCB has queued out of sequence data, but has been + inactive for too long, will drop the data (it will eventually + be retransmitted). */ +#if TCP_QUEUE_OOSEQ + if (pcb->ooseq != NULL && + (u32_t)tcp_ticks - pcb->tmr >= pcb->rto * TCP_OOSEQ_TIMEOUT) { + tcp_segs_free(pcb->ooseq); + pcb->ooseq = NULL; + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: dropping OOSEQ queued data\n")); + } +#endif /* TCP_QUEUE_OOSEQ */ + + /* Check if this PCB has stayed too long in SYN-RCVD */ + if (pcb->state == SYN_RCVD) { + if ((u32_t)(tcp_ticks - pcb->tmr) > + TCP_SYN_RCVD_TIMEOUT / TCP_SLOW_INTERVAL) { + ++pcb_remove; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in SYN-RCVD\n")); + } + } + + /* Check if this PCB has stayed too long in LAST-ACK */ + if (pcb->state == LAST_ACK) { + if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) { + ++pcb_remove; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in LAST-ACK\n")); + } + } + + /* If the PCB should be removed, do it. */ + if (pcb_remove) { + struct tcp_pcb *pcb2; + tcp_err_fn err_fn; + void *err_arg; + tcp_pcb_purge(pcb); + /* Remove PCB from tcp_active_pcbs list. */ + if (prev != NULL) { + LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_active_pcbs", pcb != tcp_active_pcbs); + prev->next = pcb->next; + } else { + /* This PCB was the first. */ + LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_active_pcbs", tcp_active_pcbs == pcb); + tcp_active_pcbs = pcb->next; + } + + if (pcb_reset) { + tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip, + pcb->local_port, pcb->remote_port, PCB_ISIPV6(pcb)); + } + + err_fn = pcb->errf; + err_arg = pcb->callback_arg; + pcb2 = pcb; + pcb = pcb->next; + memp_free(MEMP_TCP_PCB, pcb2); + + tcp_active_pcbs_changed = 0; + TCP_EVENT_ERR(err_fn, err_arg, ERR_ABRT); + if (tcp_active_pcbs_changed) { + goto tcp_slowtmr_start; + } + } else { + /* get the 'next' element now and work with 'prev' below (in case of abort) */ + prev = pcb; + pcb = pcb->next; + + /* We check if we should poll the connection. */ + ++prev->polltmr; + if (prev->polltmr >= prev->pollinterval) { + prev->polltmr = 0; + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: polling application\n")); + tcp_active_pcbs_changed = 0; + TCP_EVENT_POLL(prev, err); + if (tcp_active_pcbs_changed) { + goto tcp_slowtmr_start; + } + /* if err == ERR_ABRT, 'prev' is already deallocated */ + if (err == ERR_OK) { + tcp_output(prev); + } + } + } + } + + + /* Steps through all of the TIME-WAIT PCBs. */ + prev = NULL; + pcb = tcp_tw_pcbs; + while (pcb != NULL) { + LWIP_ASSERT("tcp_slowtmr: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); + pcb_remove = 0; + + /* Check if this PCB has stayed long enough in TIME-WAIT */ + if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) { + ++pcb_remove; + } + + + + /* If the PCB should be removed, do it. */ + if (pcb_remove) { + struct tcp_pcb *pcb2; + tcp_pcb_purge(pcb); + /* Remove PCB from tcp_tw_pcbs list. */ + if (prev != NULL) { + LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_tw_pcbs", pcb != tcp_tw_pcbs); + prev->next = pcb->next; + } else { + /* This PCB was the first. */ + LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_tw_pcbs", tcp_tw_pcbs == pcb); + tcp_tw_pcbs = pcb->next; + } + pcb2 = pcb; + pcb = pcb->next; + memp_free(MEMP_TCP_PCB, pcb2); + } else { + prev = pcb; + pcb = pcb->next; + } + } +} + +/** + * Is called every TCP_FAST_INTERVAL (250 ms) and process data previously + * "refused" by upper layer (application) and sends delayed ACKs. + * + * Automatically called from tcp_tmr(). + */ +void +tcp_fasttmr(void) +{ + struct tcp_pcb *pcb; + + ++tcp_timer_ctr; + +tcp_fasttmr_start: + pcb = tcp_active_pcbs; + + while(pcb != NULL) { + if (pcb->last_timer != tcp_timer_ctr) { + struct tcp_pcb *next; + pcb->last_timer = tcp_timer_ctr; + /* send delayed ACKs */ + if (pcb->flags & TF_ACK_DELAY) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_fasttmr: delayed ACK\n")); + tcp_ack_now(pcb); + tcp_output(pcb); + pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); + } + + next = pcb->next; + + /* If there is data which was previously "refused" by upper layer */ + if (pcb->refused_data != NULL) { + tcp_active_pcbs_changed = 0; + tcp_process_refused_data(pcb); + if (tcp_active_pcbs_changed) { + /* application callback has changed the pcb list: restart the loop */ + goto tcp_fasttmr_start; + } + } + pcb = next; + } else { + pcb = pcb->next; + } + } +} + +/** Pass pcb->refused_data to the recv callback */ +err_t +tcp_process_refused_data(struct tcp_pcb *pcb) +{ +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + struct pbuf *rest; + while (pcb->refused_data != NULL) +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + { + err_t err; + u8_t refused_flags = pcb->refused_data->flags; + /* set pcb->refused_data to NULL in case the callback frees it and then + closes the pcb */ + struct pbuf *refused_data = pcb->refused_data; +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + pbuf_split_64k(refused_data, &rest); + pcb->refused_data = rest; +#else /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + pcb->refused_data = NULL; +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + /* Notify again application with data previously received. */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: notify kept packet\n")); + TCP_EVENT_RECV(pcb, refused_data, ERR_OK, err); + if (err == ERR_OK) { + /* did refused_data include a FIN? */ + if (refused_flags & PBUF_FLAG_TCP_FIN +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + && (rest == NULL) +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + ) { + /* correct rcv_wnd as the application won't call tcp_recved() + for the FIN's seqno */ + if (pcb->rcv_wnd != TCP_WND) { + pcb->rcv_wnd++; + } + TCP_EVENT_CLOSED(pcb, err); + if (err == ERR_ABRT) { + return ERR_ABRT; + } + } + } else if (err == ERR_ABRT) { + /* if err == ERR_ABRT, 'pcb' is already deallocated */ + /* Drop incoming packets because pcb is "full" (only if the incoming + segment contains data). */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: drop incoming packets, because pcb is \"full\"\n")); + return ERR_ABRT; + } else { + /* data is still refused, pbuf is still valid (go on for ACK-only packets) */ +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + if (rest != NULL) { + pbuf_cat(refused_data, rest); + } +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + pcb->refused_data = refused_data; + return ERR_INPROGRESS; + } + } + return ERR_OK; +} + +/** + * Deallocates a list of TCP segments (tcp_seg structures). + * + * @param seg tcp_seg list of TCP segments to free + */ +void +tcp_segs_free(struct tcp_seg *seg) +{ + while (seg != NULL) { + struct tcp_seg *next = seg->next; + tcp_seg_free(seg); + seg = next; + } +} + +/** + * Frees a TCP segment (tcp_seg structure). + * + * @param seg single tcp_seg to free + */ +void +tcp_seg_free(struct tcp_seg *seg) +{ + if (seg != NULL) { + if (seg->p != NULL) { + pbuf_free(seg->p); +#if TCP_DEBUG + seg->p = NULL; +#endif /* TCP_DEBUG */ + } + memp_free(MEMP_TCP_SEG, seg); + } +} + +/** + * Sets the priority of a connection. + * + * @param pcb the tcp_pcb to manipulate + * @param prio new priority + */ +void +tcp_setprio(struct tcp_pcb *pcb, u8_t prio) +{ + pcb->prio = prio; +} + +#if TCP_QUEUE_OOSEQ +/** + * Returns a copy of the given TCP segment. + * The pbuf and data are not copied, only the pointers + * + * @param seg the old tcp_seg + * @return a copy of seg + */ +struct tcp_seg * +tcp_seg_copy(struct tcp_seg *seg) +{ + struct tcp_seg *cseg; + + cseg = (struct tcp_seg *)memp_malloc(MEMP_TCP_SEG); + if (cseg == NULL) { + return NULL; + } + SMEMCPY((u8_t *)cseg, (const u8_t *)seg, sizeof(struct tcp_seg)); + pbuf_ref(cseg->p); + return cseg; +} +#endif /* TCP_QUEUE_OOSEQ */ + +#if LWIP_CALLBACK_API +/** + * Default receive callback that is called if the user didn't register + * a recv callback for the pcb. + */ +err_t +tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) +{ + LWIP_UNUSED_ARG(arg); + if (p != NULL) { + tcp_recved(pcb, p->tot_len); + pbuf_free(p); + } else if (err == ERR_OK) { + return tcp_close(pcb); + } + return ERR_OK; +} +#endif /* LWIP_CALLBACK_API */ + +/** + * Kills the oldest active connection that has the same or lower priority than + * 'prio'. + * + * @param prio minimum priority + */ +static void +tcp_kill_prio(u8_t prio) +{ + struct tcp_pcb *pcb, *inactive, *lastack; + u32_t inactivity, inactivity_lastack; + u8_t minprio, minprio_lastack; + + minprio = prio; + minprio_lastack = prio; + + /* We kill the oldest active connection that has lower priority than prio. + However, already closed connections waiting for the last ack are closed first + since they don't lose data. */ + inactivity = 0; + inactive = NULL; + inactivity_lastack = 0; + lastack = NULL; + for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + if ((lastack != NULL) || (pcb->state == LAST_ACK) || (pcb->state == CLOSING)) { + /* found at least one pcb in last ack phase */ + if ((pcb->prio < minprio_lastack) || + (u32_t)(tcp_ticks - pcb->tmr) >= inactivity_lastack) { + inactivity_lastack = tcp_ticks - pcb->tmr; + lastack = pcb; + minprio_lastack = pcb->prio; + } + } else if (pcb->prio <= minprio) { + if ((pcb->prio < minprio) || + (u32_t)(tcp_ticks - pcb->tmr) >= inactivity) { + inactivity = tcp_ticks - pcb->tmr; + inactive = pcb; + minprio = pcb->prio; + } + } + } + if (lastack != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB in LAST_ACK or CLOSING %p (%"S32_F")\n", + (void *)lastack, inactivity_lastack)); + tcp_abort(lastack); + } else if (inactive != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB %p (%"S32_F")\n", + (void *)inactive, inactivity)); + tcp_abort(inactive); + } +} + +/** + * Kills the oldest connection that is in TIME_WAIT state. + * Called from tcp_alloc() if no more connections are available. + */ +static void +tcp_kill_timewait(void) +{ + struct tcp_pcb *pcb, *inactive; + u32_t inactivity; + + inactivity = 0; + inactive = NULL; + /* Go through the list of TIME_WAIT pcbs and get the oldest pcb. */ + for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { + if ((u32_t)(tcp_ticks - pcb->tmr) >= inactivity) { + inactivity = tcp_ticks - pcb->tmr; + inactive = pcb; + } + } + if (inactive != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_timewait: killing oldest TIME-WAIT PCB %p (%"S32_F")\n", + (void *)inactive, inactivity)); + tcp_abort(inactive); + } +} + +/** + * Allocate a new tcp_pcb structure. + * + * @param prio priority for the new pcb + * @return a new tcp_pcb that initially is in state CLOSED + */ +struct tcp_pcb * +tcp_alloc(u8_t prio) +{ + struct tcp_pcb *pcb; + u32_t iss; + + pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); + if (pcb == NULL) { + /* Try killing oldest connection in TIME-WAIT. */ + LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing off oldest TIME-WAIT connection\n")); + tcp_kill_timewait(); + /* Try to allocate a tcp_pcb again. */ + pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); + if (pcb == NULL) { + /* Try killing active connections with lower priority than the new one. */ + LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing connection with prio lower than %d\n", prio)); + tcp_kill_prio(prio); + /* Try to allocate a tcp_pcb again. */ + pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); + if (pcb != NULL) { + /* adjust err stats: memp_malloc failed twice before */ + MEMP_STATS_DEC(err, MEMP_TCP_PCB); + } + } + if (pcb != NULL) { + /* adjust err stats: timewait PCB was freed above */ + MEMP_STATS_DEC(err, MEMP_TCP_PCB); + } + } + if (pcb != NULL) { + memset(pcb, 0, sizeof(struct tcp_pcb)); + pcb->prio = prio; + pcb->snd_buf = TCP_SND_BUF; + pcb->snd_queuelen = 0; + pcb->rcv_wnd = TCP_WND; + pcb->rcv_ann_wnd = TCP_WND; +#if LWIP_WND_SCALE + /* snd_scale and rcv_scale are zero unless both sides agree to use scaling */ + pcb->snd_scale = 0; + pcb->rcv_scale = 0; +#endif + pcb->tos = 0; + pcb->ttl = TCP_TTL; + /* As initial send MSS, we use TCP_MSS but limit it to 536. + The send MSS is updated when an MSS option is received. */ + pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS; + pcb->rto = 3000 / TCP_SLOW_INTERVAL; + pcb->sa = 0; + pcb->sv = 3000 / TCP_SLOW_INTERVAL; + pcb->rtime = -1; + pcb->cwnd = 1; + iss = tcp_next_iss(); + pcb->snd_wl2 = iss; + pcb->snd_nxt = iss; + pcb->lastack = iss; + pcb->snd_lbb = iss; + pcb->tmr = tcp_ticks; + pcb->last_timer = tcp_timer_ctr; + + pcb->polltmr = 0; + +#if LWIP_CALLBACK_API + pcb->recv = tcp_recv_null; +#endif /* LWIP_CALLBACK_API */ + + /* Init KEEPALIVE timer */ + pcb->keep_idle = TCP_KEEPIDLE_DEFAULT; + +#if LWIP_TCP_KEEPALIVE + pcb->keep_intvl = TCP_KEEPINTVL_DEFAULT; + pcb->keep_cnt = TCP_KEEPCNT_DEFAULT; +#endif /* LWIP_TCP_KEEPALIVE */ + + pcb->keep_cnt_sent = 0; + } + return pcb; +} + +/** + * Creates a new TCP protocol control block but doesn't place it on + * any of the TCP PCB lists. + * The pcb is not put on any list until binding using tcp_bind(). + * + * @internal: Maybe there should be a idle TCP PCB list where these + * PCBs are put on. Port reservation using tcp_bind() is implemented but + * allocated pcbs that are not bound can't be killed automatically if wanting + * to allocate a pcb with higher prio (@see tcp_kill_prio()) + * + * @return a new tcp_pcb that initially is in state CLOSED + */ +struct tcp_pcb * +tcp_new(void) +{ + return tcp_alloc(TCP_PRIO_NORMAL); +} + +#if LWIP_IPV6 +/** + * Creates a new TCP-over-IPv6 protocol control block but doesn't + * place it on any of the TCP PCB lists. + * The pcb is not put on any list until binding using tcp_bind(). + * + * @return a new tcp_pcb that initially is in state CLOSED + */ +struct tcp_pcb * +tcp_new_ip6(void) +{ + struct tcp_pcb * pcb; + pcb = tcp_alloc(TCP_PRIO_NORMAL); + ip_set_v6(pcb, 1); + return pcb; +} +#endif /* LWIP_IPV6 */ + +/** + * Used to specify the argument that should be passed callback + * functions. + * + * @param pcb tcp_pcb to set the callback argument + * @param arg void pointer argument to pass to callback functions + */ +void +tcp_arg(struct tcp_pcb *pcb, void *arg) +{ + /* This function is allowed to be called for both listen pcbs and + connection pcbs. */ + pcb->callback_arg = arg; +} +#if LWIP_CALLBACK_API + +/** + * Used to specify the function that should be called when a TCP + * connection receives data. + * + * @param pcb tcp_pcb to set the recv callback + * @param recv callback function to call for this pcb when data is received + */ +void +tcp_recv(struct tcp_pcb *pcb, tcp_recv_fn recv) +{ + LWIP_ASSERT("invalid socket state for recv callback", pcb->state != LISTEN); + pcb->recv = recv; +} + +/** + * Used to specify the function that should be called when TCP data + * has been successfully delivered to the remote host. + * + * @param pcb tcp_pcb to set the sent callback + * @param sent callback function to call for this pcb when data is successfully sent + */ +void +tcp_sent(struct tcp_pcb *pcb, tcp_sent_fn sent) +{ + LWIP_ASSERT("invalid socket state for sent callback", pcb->state != LISTEN); + pcb->sent = sent; +} + +/** + * Used to specify the function that should be called when a fatal error + * has occurred on the connection. + * + * @param pcb tcp_pcb to set the err callback + * @param err callback function to call for this pcb when a fatal error + * has occurred on the connection + */ +void +tcp_err(struct tcp_pcb *pcb, tcp_err_fn err) +{ + LWIP_ASSERT("invalid socket state for err callback", pcb->state != LISTEN); + pcb->errf = err; +} + +/** + * Used for specifying the function that should be called when a + * LISTENing connection has been connected to another host. + * + * @param pcb tcp_pcb to set the accept callback + * @param accept callback function to call for this pcb when LISTENing + * connection has been connected to another host + */ +void +tcp_accept(struct tcp_pcb *pcb, tcp_accept_fn accept) +{ + /* This function is allowed to be called for both listen pcbs and + connection pcbs. */ + pcb->accept = accept; +} +#endif /* LWIP_CALLBACK_API */ + + +/** + * Used to specify the function that should be called periodically + * from TCP. The interval is specified in terms of the TCP coarse + * timer interval, which is called twice a second. + * + */ +void +tcp_poll(struct tcp_pcb *pcb, tcp_poll_fn poll, u8_t interval) +{ + LWIP_ASSERT("invalid socket state for poll", pcb->state != LISTEN); +#if LWIP_CALLBACK_API + pcb->poll = poll; +#else /* LWIP_CALLBACK_API */ + LWIP_UNUSED_ARG(poll); +#endif /* LWIP_CALLBACK_API */ + pcb->pollinterval = interval; +} + +/** + * Purges a TCP PCB. Removes any buffered data and frees the buffer memory + * (pcb->ooseq, pcb->unsent and pcb->unacked are freed). + * + * @param pcb tcp_pcb to purge. The pcb itself is not deallocated! + */ +void +tcp_pcb_purge(struct tcp_pcb *pcb) +{ + if (pcb->state != CLOSED && + pcb->state != TIME_WAIT && + pcb->state != LISTEN) { + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge\n")); + +#if TCP_LISTEN_BACKLOG + if (pcb->state == SYN_RCVD) { + /* Need to find the corresponding listen_pcb and decrease its accepts_pending */ + struct tcp_pcb_listen *lpcb; + LWIP_ASSERT("tcp_pcb_purge: pcb->state == SYN_RCVD but tcp_listen_pcbs is NULL", + tcp_listen_pcbs.listen_pcbs != NULL); + for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { + if ((lpcb->local_port == pcb->local_port) && + IP_PCB_IPVER_EQ(pcb, lpcb) && + (ipX_addr_isany(PCB_ISIPV6(lpcb), &lpcb->local_ip) || + ipX_addr_cmp(PCB_ISIPV6(lpcb), &pcb->local_ip, &lpcb->local_ip))) { + /* port and address of the listen pcb match the timed-out pcb */ + LWIP_ASSERT("tcp_pcb_purge: listen pcb does not have accepts pending", + lpcb->accepts_pending > 0); + lpcb->accepts_pending--; + break; + } + } + } +#endif /* TCP_LISTEN_BACKLOG */ + + + if (pcb->refused_data != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->refused_data\n")); + pbuf_free(pcb->refused_data); + pcb->refused_data = NULL; + } + if (pcb->unsent != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: not all data sent\n")); + } + if (pcb->unacked != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->unacked\n")); + } +#if TCP_QUEUE_OOSEQ + if (pcb->ooseq != NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->ooseq\n")); + } + tcp_segs_free(pcb->ooseq); + pcb->ooseq = NULL; +#endif /* TCP_QUEUE_OOSEQ */ + + /* Stop the retransmission timer as it will expect data on unacked + queue if it fires */ + pcb->rtime = -1; + + tcp_segs_free(pcb->unsent); + tcp_segs_free(pcb->unacked); + pcb->unacked = pcb->unsent = NULL; +#if TCP_OVERSIZE + pcb->unsent_oversize = 0; +#endif /* TCP_OVERSIZE */ + } +} + +/** + * Purges the PCB and removes it from a PCB list. Any delayed ACKs are sent first. + * + * @param pcblist PCB list to purge. + * @param pcb tcp_pcb to purge. The pcb itself is NOT deallocated! + */ +void +tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb) +{ + TCP_RMV(pcblist, pcb); + + tcp_pcb_purge(pcb); + + /* if there is an outstanding delayed ACKs, send it */ + if (pcb->state != TIME_WAIT && + pcb->state != LISTEN && + pcb->flags & TF_ACK_DELAY) { + pcb->flags |= TF_ACK_NOW; + tcp_output(pcb); + } + + if (pcb->state != LISTEN) { + LWIP_ASSERT("unsent segments leaking", pcb->unsent == NULL); + LWIP_ASSERT("unacked segments leaking", pcb->unacked == NULL); +#if TCP_QUEUE_OOSEQ + LWIP_ASSERT("ooseq segments leaking", pcb->ooseq == NULL); +#endif /* TCP_QUEUE_OOSEQ */ + } + + pcb->state = CLOSED; + /* reset the local port to prevent the pcb from being 'bound' */ + pcb->local_port = 0; + + LWIP_ASSERT("tcp_pcb_remove: tcp_pcbs_sane()", tcp_pcbs_sane()); +} + +/** + * Calculates a new initial sequence number for new connections. + * + * @return u32_t pseudo random sequence number + */ +u32_t +tcp_next_iss(void) +{ + static u32_t iss = 6510; + + iss += tcp_ticks; /* XXX */ + return iss; +} + +#if TCP_CALCULATE_EFF_SEND_MSS +/** + * Calculates the effective send mss that can be used for a specific IP address + * by using ip_route to determine the netif used to send to the address and + * calculating the minimum of TCP_MSS and that netif's mtu (if set). + */ +u16_t +tcp_eff_send_mss_impl(u16_t sendmss, ipX_addr_t *dest +#if LWIP_IPV6 + , ipX_addr_t *src, u8_t isipv6 +#endif /* LWIP_IPV6 */ + ) +{ + u16_t mss_s; + struct netif *outif; + s16_t mtu; + + outif = ipX_route(isipv6, src, dest); +#if LWIP_IPV6 + if (isipv6) { + /* First look in destination cache, to see if there is a Path MTU. */ + mtu = nd6_get_destination_mtu(ipX_2_ip6(dest), outif); + } else +#endif /* LWIP_IPV6 */ + { + if (outif == NULL) { + return sendmss; + } + mtu = outif->mtu; + } + + if (mtu != 0) { + mss_s = mtu - IP_HLEN - TCP_HLEN; +#if LWIP_IPV6 + if (isipv6) { + /* for IPv6, subtract the difference in header size */ + mss_s -= (IP6_HLEN - IP_HLEN); + } +#endif /* LWIP_IPV6 */ + /* RFC 1122, chap 4.2.2.6: + * Eff.snd.MSS = min(SendMSS+20, MMS_S) - TCPhdrsize - IPoptionsize + * We correct for TCP options in tcp_write(), and don't support IP options. + */ + sendmss = LWIP_MIN(sendmss, mss_s); + } + return sendmss; +} +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + +const char* +tcp_debug_state_str(enum tcp_state s) +{ + return tcp_state_str[s]; +} + +#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG +/** + * Print a tcp header for debugging purposes. + * + * @param tcphdr pointer to a struct tcp_hdr + */ +void +tcp_debug_print(struct tcp_hdr *tcphdr) +{ + LWIP_DEBUGF(TCP_DEBUG, ("TCP header:\n")); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(TCP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n", + ntohs(tcphdr->src), ntohs(tcphdr->dest))); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (seq no)\n", + ntohl(tcphdr->seqno))); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (ack no)\n", + ntohl(tcphdr->ackno))); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(TCP_DEBUG, ("| %2"U16_F" | |%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"| %5"U16_F" | (hdrlen, flags (", + TCPH_HDRLEN(tcphdr), + TCPH_FLAGS(tcphdr) >> 5 & 1, + TCPH_FLAGS(tcphdr) >> 4 & 1, + TCPH_FLAGS(tcphdr) >> 3 & 1, + TCPH_FLAGS(tcphdr) >> 2 & 1, + TCPH_FLAGS(tcphdr) >> 1 & 1, + TCPH_FLAGS(tcphdr) & 1, + ntohs(tcphdr->wnd))); + tcp_debug_print_flags(TCPH_FLAGS(tcphdr)); + LWIP_DEBUGF(TCP_DEBUG, ("), win)\n")); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(TCP_DEBUG, ("| 0x%04"X16_F" | %5"U16_F" | (chksum, urgp)\n", + ntohs(tcphdr->chksum), ntohs(tcphdr->urgp))); + LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); +} + +/** + * Print a tcp state for debugging purposes. + * + * @param s enum tcp_state to print + */ +void +tcp_debug_print_state(enum tcp_state s) +{ + LWIP_DEBUGF(TCP_DEBUG, ("State: %s\n", tcp_state_str[s])); +} + +/** + * Print tcp flags for debugging purposes. + * + * @param flags tcp flags, all active flags are printed + */ +void +tcp_debug_print_flags(u8_t flags) +{ + if (flags & TCP_FIN) { + LWIP_DEBUGF(TCP_DEBUG, ("FIN ")); + } + if (flags & TCP_SYN) { + LWIP_DEBUGF(TCP_DEBUG, ("SYN ")); + } + if (flags & TCP_RST) { + LWIP_DEBUGF(TCP_DEBUG, ("RST ")); + } + if (flags & TCP_PSH) { + LWIP_DEBUGF(TCP_DEBUG, ("PSH ")); + } + if (flags & TCP_ACK) { + LWIP_DEBUGF(TCP_DEBUG, ("ACK ")); + } + if (flags & TCP_URG) { + LWIP_DEBUGF(TCP_DEBUG, ("URG ")); + } + if (flags & TCP_ECE) { + LWIP_DEBUGF(TCP_DEBUG, ("ECE ")); + } + if (flags & TCP_CWR) { + LWIP_DEBUGF(TCP_DEBUG, ("CWR ")); + } + LWIP_DEBUGF(TCP_DEBUG, ("\n")); +} + +/** + * Print all tcp_pcbs in every list for debugging purposes. + */ +void +tcp_debug_print_pcbs(void) +{ + struct tcp_pcb *pcb; + LWIP_DEBUGF(TCP_DEBUG, ("Active PCB states:\n")); + for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", + pcb->local_port, pcb->remote_port, + pcb->snd_nxt, pcb->rcv_nxt)); + tcp_debug_print_state(pcb->state); + } + LWIP_DEBUGF(TCP_DEBUG, ("Listen PCB states:\n")); + for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", + pcb->local_port, pcb->remote_port, + pcb->snd_nxt, pcb->rcv_nxt)); + tcp_debug_print_state(pcb->state); + } + LWIP_DEBUGF(TCP_DEBUG, ("TIME-WAIT PCB states:\n")); + for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", + pcb->local_port, pcb->remote_port, + pcb->snd_nxt, pcb->rcv_nxt)); + tcp_debug_print_state(pcb->state); + } +} + +/** + * Check state consistency of the tcp_pcb lists. + */ +s16_t +tcp_pcbs_sane(void) +{ + struct tcp_pcb *pcb; + for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != CLOSED", pcb->state != CLOSED); + LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != LISTEN", pcb->state != LISTEN); + LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT); + } + for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_ASSERT("tcp_pcbs_sane: tw pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); + } + return 1; +} +#endif /* TCP_DEBUG */ + +#endif /* LWIP_TCP */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/core/tcp_in.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/tcp_in.c new file mode 100644 index 0000000..9eedfc2 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/tcp_in.c @@ -0,0 +1,1770 @@ +/** + * @file + * Transmission Control Protocol, incoming traffic + * + * The input processing functions of the TCP layer. + * + * These functions are generally called in the order (ip_input() ->) + * tcp_input() -> * tcp_process() -> tcp_receive() (-> application). + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/tcp_impl.h" +#include "lwip/def.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/inet_chksum.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "arch/perf.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/inet_chksum.h" +#if LWIP_ND6_TCP_REACHABILITY_HINTS +#include "lwip/nd6.h" +#endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */ + +#define LWIP_TCP_CALC_INITIAL_CWND(mss) LWIP_MIN((4U * (mss)), LWIP_MAX((2U * (mss)), 4380U)); + +/* These variables are global to all functions involved in the input + processing of TCP segments. They are set by the tcp_input() + function. */ +static struct tcp_seg inseg; +static struct tcp_hdr *tcphdr; +static u16_t tcphdr_opt1len; +static u8_t* tcphdr_opt2; +static u16_t tcp_optidx; +static u32_t seqno, ackno; +static u8_t flags; +static u16_t tcplen; + +static u8_t recv_flags; +static struct pbuf *recv_data; + +struct tcp_pcb *tcp_input_pcb; + +/* Forward declarations. */ +static err_t tcp_process(struct tcp_pcb *pcb); +static void tcp_receive(struct tcp_pcb *pcb); +static void tcp_parseopt(struct tcp_pcb *pcb); + +static err_t tcp_listen_input(struct tcp_pcb_listen *pcb); +static err_t tcp_timewait_input(struct tcp_pcb *pcb); + +/** + * The initial input processing of TCP. It verifies the TCP header, demultiplexes + * the segment between the PCBs and passes it on to tcp_process(), which implements + * the TCP finite state machine. This function is called by the IP layer (in + * ip_input()). + * + * @param p received TCP segment to process (p->payload pointing to the TCP header) + * @param inp network interface on which this segment was received + */ +void +tcp_input(struct pbuf *p, struct netif *inp) +{ + struct tcp_pcb *pcb, *prev; + struct tcp_pcb_listen *lpcb; +#if SO_REUSE + struct tcp_pcb *lpcb_prev = NULL; + struct tcp_pcb_listen *lpcb_any = NULL; +#endif /* SO_REUSE */ + u8_t hdrlen; + err_t err; +#if CHECKSUM_CHECK_TCP + u16_t chksum; +#endif /* CHECKSUM_CHECK_TCP */ + + PERF_START; + + TCP_STATS_INC(tcp.recv); + snmp_inc_tcpinsegs(); + + tcphdr = (struct tcp_hdr *)p->payload; + +#if TCP_INPUT_DEBUG + tcp_debug_print(tcphdr); +#endif + + /* Check that TCP header fits in payload */ + if (p->len < sizeof(struct tcp_hdr)) { + /* drop short packets */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%"U16_F" bytes) discarded\n", p->tot_len)); + TCP_STATS_INC(tcp.lenerr); + goto dropped; + } + + /* Don't even process incoming broadcasts/multicasts. */ + if ((!ip_current_is_v6() && ip_addr_isbroadcast(ip_current_dest_addr(), inp)) || + ipX_addr_ismulticast(ip_current_is_v6(), ipX_current_dest_addr())) { + TCP_STATS_INC(tcp.proterr); + goto dropped; + } + +#if CHECKSUM_CHECK_TCP + /* Verify TCP checksum. */ + chksum = ipX_chksum_pseudo(ip_current_is_v6(), p, IP_PROTO_TCP, p->tot_len, + ipX_current_src_addr(), ipX_current_dest_addr()); + if (chksum != 0) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04"X16_F"\n", + chksum)); + tcp_debug_print(tcphdr); + TCP_STATS_INC(tcp.chkerr); + goto dropped; + } +#endif /* CHECKSUM_CHECK_TCP */ + + /* Move the payload pointer in the pbuf so that it points to the + TCP data instead of the TCP header. */ + hdrlen = TCPH_HDRLEN(tcphdr); + tcphdr_opt1len = (hdrlen * 4) - TCP_HLEN; + tcphdr_opt2 = NULL; + if (p->len < hdrlen * 4) { + if (p->len >= TCP_HLEN) { + /* TCP header fits into first pbuf, options don't - data is in the next pbuf */ + u16_t optlen = tcphdr_opt1len; + pbuf_header(p, -TCP_HLEN); /* cannot fail */ + LWIP_ASSERT("tcphdr_opt1len >= p->len", tcphdr_opt1len >= p->len); + LWIP_ASSERT("p->next != NULL", p->next != NULL); + tcphdr_opt1len = p->len; + if (optlen > tcphdr_opt1len) { + s16_t opt2len; + /* options continue in the next pbuf: set p to zero length and hide the + options in the next pbuf (adjusting p->tot_len) */ + u8_t phret = pbuf_header(p, -(s16_t)tcphdr_opt1len); + LWIP_ASSERT("phret == 0", phret == 0); + tcphdr_opt2 = (u8_t*)p->next->payload; + opt2len = optlen - tcphdr_opt1len; + phret = pbuf_header(p->next, -opt2len); + LWIP_ASSERT("phret == 0", phret == 0); + /* p->next->payload now points to the TCP data */ + /* manually adjust p->tot_len to changed p->next->tot_len change */ + p->tot_len -= opt2len; + } + LWIP_ASSERT("p->len == 0", p->len == 0); + } else { + /* drop short packets */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet\n")); + TCP_STATS_INC(tcp.lenerr); + goto dropped; + } + } else { + pbuf_header(p, -(hdrlen * 4)); /* cannot fail */ + } + + /* Convert fields in TCP header to host byte order. */ + tcphdr->src = ntohs(tcphdr->src); + tcphdr->dest = ntohs(tcphdr->dest); + seqno = tcphdr->seqno = ntohl(tcphdr->seqno); + ackno = tcphdr->ackno = ntohl(tcphdr->ackno); + tcphdr->wnd = ntohs(tcphdr->wnd); + + flags = TCPH_FLAGS(tcphdr); + tcplen = p->tot_len + ((flags & (TCP_FIN | TCP_SYN)) ? 1 : 0); + + /* Demultiplex an incoming segment. First, we check if it is destined + for an active connection. */ + prev = NULL; + + + for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED); + LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT); + LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN); + if (pcb->remote_port == tcphdr->src && + pcb->local_port == tcphdr->dest && + IP_PCB_IPVER_INPUT_MATCH(pcb) && + ipX_addr_cmp(ip_current_is_v6(), &pcb->remote_ip, ipX_current_src_addr()) && + ipX_addr_cmp(ip_current_is_v6(),&pcb->local_ip, ipX_current_dest_addr())) { + /* Move this PCB to the front of the list so that subsequent + lookups will be faster (we exploit locality in TCP segment + arrivals). */ + LWIP_ASSERT("tcp_input: pcb->next != pcb (before cache)", pcb->next != pcb); + if (prev != NULL) { + prev->next = pcb->next; + pcb->next = tcp_active_pcbs; + tcp_active_pcbs = pcb; + } + LWIP_ASSERT("tcp_input: pcb->next != pcb (after cache)", pcb->next != pcb); + break; + } + prev = pcb; + } + + if (pcb == NULL) { + /* If it did not go to an active connection, we check the connections + in the TIME-WAIT state. */ + for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { + LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); + if (pcb->remote_port == tcphdr->src && + pcb->local_port == tcphdr->dest && + IP_PCB_IPVER_INPUT_MATCH(pcb) && + ipX_addr_cmp(ip_current_is_v6(), &pcb->remote_ip, ipX_current_src_addr()) && + ipX_addr_cmp(ip_current_is_v6(),&pcb->local_ip, ipX_current_dest_addr())) { + /* We don't really care enough to move this PCB to the front + of the list since we are not very likely to receive that + many segments for connections in TIME-WAIT. */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for TIME_WAITing connection.\n")); + tcp_timewait_input(pcb); + pbuf_free(p); + return; + } + } + + /* Finally, if we still did not get a match, we check all PCBs that + are LISTENing for incoming connections. */ + prev = NULL; + for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { + if (lpcb->local_port == tcphdr->dest) { +#if LWIP_IPV6 + if (lpcb->accept_any_ip_version) { + /* found an ANY-match */ +#if SO_REUSE + lpcb_any = lpcb; + lpcb_prev = prev; +#else /* SO_REUSE */ + break; +#endif /* SO_REUSE */ + } else +#endif /* LWIP_IPV6 */ + if (IP_PCB_IPVER_INPUT_MATCH(lpcb)) { + if (ipX_addr_cmp(ip_current_is_v6(), &lpcb->local_ip, ipX_current_dest_addr())) { + /* found an exact match */ + break; + } else if (ipX_addr_isany(ip_current_is_v6(), &lpcb->local_ip)) { + /* found an ANY-match */ +#if SO_REUSE + lpcb_any = lpcb; + lpcb_prev = prev; +#else /* SO_REUSE */ + break; + #endif /* SO_REUSE */ + } + } + } + prev = (struct tcp_pcb *)lpcb; + } +#if SO_REUSE + /* first try specific local IP */ + if (lpcb == NULL) { + /* only pass to ANY if no specific local IP has been found */ + lpcb = lpcb_any; + prev = lpcb_prev; + } +#endif /* SO_REUSE */ + if (lpcb != NULL) { + /* Move this PCB to the front of the list so that subsequent + lookups will be faster (we exploit locality in TCP segment + arrivals). */ + if (prev != NULL) { + ((struct tcp_pcb_listen *)prev)->next = lpcb->next; + /* our successor is the remainder of the listening list */ + lpcb->next = tcp_listen_pcbs.listen_pcbs; + /* put this listening pcb at the head of the listening list */ + tcp_listen_pcbs.listen_pcbs = lpcb; + } + + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n")); + tcp_listen_input(lpcb); + pbuf_free(p); + return; + } + } + +#if TCP_INPUT_DEBUG + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("+-+-+-+-+-+-+-+-+-+-+-+-+-+- tcp_input: flags ")); + tcp_debug_print_flags(TCPH_FLAGS(tcphdr)); + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n")); +#endif /* TCP_INPUT_DEBUG */ + + + if (pcb != NULL) { + /* The incoming segment belongs to a connection. */ +#if TCP_INPUT_DEBUG +#if TCP_DEBUG + tcp_debug_print_state(pcb->state); +#endif /* TCP_DEBUG */ +#endif /* TCP_INPUT_DEBUG */ + + /* Set up a tcp_seg structure. */ + inseg.next = NULL; + inseg.len = p->tot_len; + inseg.p = p; + inseg.tcphdr = tcphdr; + + recv_data = NULL; + recv_flags = 0; + + if (flags & TCP_PSH) { + p->flags |= PBUF_FLAG_PUSH; + } + + /* If there is data which was previously "refused" by upper layer */ + if (pcb->refused_data != NULL) { + if ((tcp_process_refused_data(pcb) == ERR_ABRT) || + ((pcb->refused_data != NULL) && (tcplen > 0))) { + /* pcb has been aborted or refused data is still refused and the new + segment contains data */ + TCP_STATS_INC(tcp.drop); + snmp_inc_tcpinerrs(); + goto aborted; + } + } + tcp_input_pcb = pcb; + err = tcp_process(pcb); + /* A return value of ERR_ABRT means that tcp_abort() was called + and that the pcb has been freed. If so, we don't do anything. */ + if (err != ERR_ABRT) { + if (recv_flags & TF_RESET) { + /* TF_RESET means that the connection was reset by the other + end. We then call the error callback to inform the + application that the connection is dead before we + deallocate the PCB. */ + TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_RST); + tcp_pcb_remove(&tcp_active_pcbs, pcb); + memp_free(MEMP_TCP_PCB, pcb); + } else if (recv_flags & TF_CLOSED) { + /* The connection has been closed and we will deallocate the + PCB. */ + if (!(pcb->flags & TF_RXCLOSED)) { + /* Connection closed although the application has only shut down the + tx side: call the PCB's err callback and indicate the closure to + ensure the application doesn't continue using the PCB. */ + TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_CLSD); + } + tcp_pcb_remove(&tcp_active_pcbs, pcb); + memp_free(MEMP_TCP_PCB, pcb); + } else { + err = ERR_OK; + /* If the application has registered a "sent" function to be + called when new send buffer space is available, we call it + now. */ + if (pcb->acked > 0) { + u16_t acked; +#if LWIP_WND_SCALE + /* pcb->acked is u32_t but the sent callback only takes a u16_t, + so we might have to call it multiple times. */ + u32_t pcb_acked = pcb->acked; + while(pcb_acked > 0) { + acked = (u16_t)LWIP_MIN(pcb_acked, 0xffffu); + pcb_acked -= acked; +#else + { + acked = pcb->acked; +#endif + TCP_EVENT_SENT(pcb, (u16_t)acked, err); + if (err == ERR_ABRT) { + goto aborted; + } + } + } + +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + while (recv_data != NULL) { + struct pbuf *rest = NULL; + pbuf_split_64k(recv_data, &rest); +#else /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + if (recv_data != NULL) { +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + + LWIP_ASSERT("pcb->refused_data == NULL", pcb->refused_data == NULL); + if (pcb->flags & TF_RXCLOSED) { + /* received data although already closed -> abort (send RST) to + notify the remote host that not all data has been processed */ + pbuf_free(recv_data); +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + if (rest != NULL) { + pbuf_free(rest); + } +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + tcp_abort(pcb); + goto aborted; + } + + /* Notify application that data has been received. */ + TCP_EVENT_RECV(pcb, recv_data, ERR_OK, err); + if (err == ERR_ABRT) { +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + if (rest != NULL) { + pbuf_free(rest); + } +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + goto aborted; + } + + /* If the upper layer can't receive this data, store it */ + if (err != ERR_OK) { +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + if (rest != NULL) { + pbuf_cat(recv_data, rest); + } +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + pcb->refused_data = recv_data; + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: keep incoming packet, because pcb is \"full\"\n")); +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + break; + } else { + /* Upper layer received the data, go on with the rest if > 64K */ + recv_data = rest; +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + } + } + + /* If a FIN segment was received, we call the callback + function with a NULL buffer to indicate EOF. */ + if (recv_flags & TF_GOT_FIN) { + if (pcb->refused_data != NULL) { + /* Delay this if we have refused data. */ + pcb->refused_data->flags |= PBUF_FLAG_TCP_FIN; + } else { + /* correct rcv_wnd as the application won't call tcp_recved() + for the FIN's seqno */ + if (pcb->rcv_wnd != TCP_WND) { + pcb->rcv_wnd++; + } + TCP_EVENT_CLOSED(pcb, err); + if (err == ERR_ABRT) { + goto aborted; + } + } + } + + tcp_input_pcb = NULL; + /* Try to send something out. */ + tcp_output(pcb); +#if TCP_INPUT_DEBUG +#if TCP_DEBUG + tcp_debug_print_state(pcb->state); +#endif /* TCP_DEBUG */ +#endif /* TCP_INPUT_DEBUG */ + } + } + /* Jump target if pcb has been aborted in a callback (by calling tcp_abort()). + Below this line, 'pcb' may not be dereferenced! */ +aborted: + tcp_input_pcb = NULL; + recv_data = NULL; + + /* give up our reference to inseg.p */ + if (inseg.p != NULL) + { + pbuf_free(inseg.p); + inseg.p = NULL; + } + } else { + + /* If no matching PCB was found, send a TCP RST (reset) to the + sender. */ + LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n")); + if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) { + TCP_STATS_INC(tcp.proterr); + TCP_STATS_INC(tcp.drop); + tcp_rst(ackno, seqno + tcplen, ipX_current_dest_addr(), + ipX_current_src_addr(), tcphdr->dest, tcphdr->src, ip_current_is_v6()); + } + pbuf_free(p); + } + + LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane()); + PERF_STOP("tcp_input"); + return; +dropped: + TCP_STATS_INC(tcp.drop); + snmp_inc_tcpinerrs(); + pbuf_free(p); +} + +/** + * Called by tcp_input() when a segment arrives for a listening + * connection (from tcp_input()). + * + * @param pcb the tcp_pcb_listen for which a segment arrived + * @return ERR_OK if the segment was processed + * another err_t on error + * + * @note the return value is not (yet?) used in tcp_input() + * @note the segment which arrived is saved in global variables, therefore only the pcb + * involved is passed as a parameter to this function + */ +static err_t +tcp_listen_input(struct tcp_pcb_listen *pcb) +{ + struct tcp_pcb *npcb; + err_t rc; + + if (flags & TCP_RST) { + /* An incoming RST should be ignored. Return. */ + return ERR_OK; + } + + /* In the LISTEN state, we check for incoming SYN segments, + creates a new PCB, and responds with a SYN|ACK. */ + if (flags & TCP_ACK) { + /* For incoming segments with the ACK flag set, respond with a + RST. */ + LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n")); + tcp_rst(ackno, seqno + tcplen, ipX_current_dest_addr(), + ipX_current_src_addr(), tcphdr->dest, tcphdr->src, ip_current_is_v6()); + } else if (flags & TCP_SYN) { + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest)); +#if TCP_LISTEN_BACKLOG + if (pcb->accepts_pending >= pcb->backlog) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: listen backlog exceeded for port %"U16_F"\n", tcphdr->dest)); + return ERR_ABRT; + } +#endif /* TCP_LISTEN_BACKLOG */ + npcb = tcp_alloc(pcb->prio); + /* If a new PCB could not be created (probably due to lack of memory), + we don't do anything, but rely on the sender will retransmit the + SYN at a time when we have more memory available. */ + if (npcb == NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n")); + TCP_STATS_INC(tcp.memerr); + return ERR_MEM; + } +#if TCP_LISTEN_BACKLOG + pcb->accepts_pending++; +#endif /* TCP_LISTEN_BACKLOG */ + /* Set up the new PCB. */ +#if LWIP_IPV6 + PCB_ISIPV6(npcb) = ip_current_is_v6(); +#endif /* LWIP_IPV6 */ + ipX_addr_copy(ip_current_is_v6(), npcb->local_ip, *ipX_current_dest_addr()); + ipX_addr_copy(ip_current_is_v6(), npcb->remote_ip, *ipX_current_src_addr()); + npcb->local_port = pcb->local_port; + npcb->remote_port = tcphdr->src; + npcb->state = SYN_RCVD; + npcb->rcv_nxt = seqno + 1; + npcb->rcv_ann_right_edge = npcb->rcv_nxt; + npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */ + npcb->callback_arg = pcb->callback_arg; +#if LWIP_CALLBACK_API + npcb->accept = pcb->accept; +#endif /* LWIP_CALLBACK_API */ + /* inherit socket options */ + npcb->so_options = pcb->so_options & SOF_INHERITED; + /* Register the new PCB so that we can begin receiving segments + for it. */ + TCP_REG_ACTIVE(npcb); + + /* Parse any options in the SYN. */ + tcp_parseopt(npcb); + npcb->snd_wnd = SND_WND_SCALE(npcb, tcphdr->wnd); + npcb->snd_wnd_max = npcb->snd_wnd; + npcb->ssthresh = npcb->snd_wnd; + +#if TCP_CALCULATE_EFF_SEND_MSS + npcb->mss = tcp_eff_send_mss(npcb->mss, &npcb->local_ip, + &npcb->remote_ip, PCB_ISIPV6(npcb)); +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + + snmp_inc_tcppassiveopens(); + + /* Send a SYN|ACK together with the MSS option. */ + rc = tcp_enqueue_flags(npcb, TCP_SYN | TCP_ACK); + if (rc != ERR_OK) { + tcp_abandon(npcb, 0); + return rc; + } + return tcp_output(npcb); + } + return ERR_OK; +} + +/** + * Called by tcp_input() when a segment arrives for a connection in + * TIME_WAIT. + * + * @param pcb the tcp_pcb for which a segment arrived + * + * @note the segment which arrived is saved in global variables, therefore only the pcb + * involved is passed as a parameter to this function + */ +static err_t +tcp_timewait_input(struct tcp_pcb *pcb) +{ + /* RFC 1337: in TIME_WAIT, ignore RST and ACK FINs + any 'acceptable' segments */ + /* RFC 793 3.9 Event Processing - Segment Arrives: + * - first check sequence number - we skip that one in TIME_WAIT (always + * acceptable since we only send ACKs) + * - second check the RST bit (... return) */ + if (flags & TCP_RST) { + return ERR_OK; + } + /* - fourth, check the SYN bit, */ + if (flags & TCP_SYN) { + /* If an incoming segment is not acceptable, an acknowledgment + should be sent in reply */ + if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt+pcb->rcv_wnd)) { + /* If the SYN is in the window it is an error, send a reset */ + tcp_rst(ackno, seqno + tcplen, ipX_current_dest_addr(), + ipX_current_src_addr(), tcphdr->dest, tcphdr->src, ip_current_is_v6()); + return ERR_OK; + } + } else if (flags & TCP_FIN) { + /* - eighth, check the FIN bit: Remain in the TIME-WAIT state. + Restart the 2 MSL time-wait timeout.*/ + pcb->tmr = tcp_ticks; + } + + if ((tcplen > 0)) { + /* Acknowledge data, FIN or out-of-window SYN */ + pcb->flags |= TF_ACK_NOW; + return tcp_output(pcb); + } + return ERR_OK; +} + +/** + * Implements the TCP state machine. Called by tcp_input. In some + * states tcp_receive() is called to receive data. The tcp_seg + * argument will be freed by the caller (tcp_input()) unless the + * recv_data pointer in the pcb is set. + * + * @param pcb the tcp_pcb for which a segment arrived + * + * @note the segment which arrived is saved in global variables, therefore only the pcb + * involved is passed as a parameter to this function + */ +static err_t +tcp_process(struct tcp_pcb *pcb) +{ + struct tcp_seg *rseg; + u8_t acceptable = 0; + err_t err; + + err = ERR_OK; + + /* Process incoming RST segments. */ + if (flags & TCP_RST) { + /* First, determine if the reset is acceptable. */ + if (pcb->state == SYN_SENT) { + if (ackno == pcb->snd_nxt) { + acceptable = 1; + } + } else { + if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, + pcb->rcv_nxt+pcb->rcv_wnd)) { + acceptable = 1; + } + } + + if (acceptable) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: Connection RESET\n")); + LWIP_ASSERT("tcp_input: pcb->state != CLOSED", pcb->state != CLOSED); + recv_flags |= TF_RESET; + pcb->flags &= ~TF_ACK_DELAY; + return ERR_RST; + } else { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n", + seqno, pcb->rcv_nxt)); + LWIP_DEBUGF(TCP_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n", + seqno, pcb->rcv_nxt)); + return ERR_OK; + } + } + + if ((flags & TCP_SYN) && (pcb->state != SYN_SENT && pcb->state != SYN_RCVD)) { + /* Cope with new connection attempt after remote end crashed */ + tcp_ack_now(pcb); + return ERR_OK; + } + + if ((pcb->flags & TF_RXCLOSED) == 0) { + /* Update the PCB (in)activity timer unless rx is closed (see tcp_shutdown) */ + pcb->tmr = tcp_ticks; + } + pcb->keep_cnt_sent = 0; + + tcp_parseopt(pcb); + + /* Do different things depending on the TCP state. */ + switch (pcb->state) { + case SYN_SENT: + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %"U32_F" pcb->snd_nxt %"U32_F" unacked %"U32_F"\n", ackno, + pcb->snd_nxt, ntohl(pcb->unacked->tcphdr->seqno))); + /* received SYN ACK with expected sequence number? */ + if ((flags & TCP_ACK) && (flags & TCP_SYN) + && ackno == ntohl(pcb->unacked->tcphdr->seqno) + 1) { + pcb->snd_buf++; + pcb->rcv_nxt = seqno + 1; + pcb->rcv_ann_right_edge = pcb->rcv_nxt; + pcb->lastack = ackno; + pcb->snd_wnd = SND_WND_SCALE(pcb, tcphdr->wnd); + pcb->snd_wnd_max = pcb->snd_wnd; + pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */ + pcb->state = ESTABLISHED; + +#if TCP_CALCULATE_EFF_SEND_MSS + pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->local_ip, &pcb->remote_ip, + PCB_ISIPV6(pcb)); +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + + /* Set ssthresh again after changing pcb->mss (already set in tcp_connect + * but for the default value of pcb->mss) */ + pcb->ssthresh = pcb->mss * 10; + + pcb->cwnd = LWIP_TCP_CALC_INITIAL_CWND(pcb->mss); + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_process (SENT): cwnd %"TCPWNDSIZE_F + " ssthresh %"TCPWNDSIZE_F"\n", + pcb->cwnd, pcb->ssthresh)); + LWIP_ASSERT("pcb->snd_queuelen > 0", (pcb->snd_queuelen > 0)); + --pcb->snd_queuelen; + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %"TCPWNDSIZE_F"\n", (tcpwnd_size_t)pcb->snd_queuelen)); + rseg = pcb->unacked; + pcb->unacked = rseg->next; + tcp_seg_free(rseg); + + /* If there's nothing left to acknowledge, stop the retransmit + timer, otherwise reset it to start again */ + if(pcb->unacked == NULL) + pcb->rtime = -1; + else { + pcb->rtime = 0; + pcb->nrtx = 0; + } + + /* Call the user specified function to call when successfully + * connected. */ + TCP_EVENT_CONNECTED(pcb, ERR_OK, err); + if (err == ERR_ABRT) { + return ERR_ABRT; + } + tcp_ack_now(pcb); + } + /* received ACK? possibly a half-open connection */ + else if (flags & TCP_ACK) { + /* send a RST to bring the other side in a non-synchronized state. */ + tcp_rst(ackno, seqno + tcplen, ipX_current_dest_addr(), + ipX_current_src_addr(), tcphdr->dest, tcphdr->src, ip_current_is_v6()); + } + break; + case SYN_RCVD: + if (flags & TCP_ACK) { + /* expected ACK number? */ + if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) { + pcb->state = ESTABLISHED; + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); +#if LWIP_CALLBACK_API + LWIP_ASSERT("pcb->accept != NULL", pcb->accept != NULL); +#endif + /* Call the accept function. */ + TCP_EVENT_ACCEPT(pcb, ERR_OK, err); + if (err != ERR_OK) { + /* If the accept function returns with an error, we abort + * the connection. */ + /* Already aborted? */ + if (err != ERR_ABRT) { + tcp_abort(pcb); + } + return ERR_ABRT; + } + /* If there was any data contained within this ACK, + * we'd better pass it on to the application as well. */ + tcp_receive(pcb); + + /* Prevent ACK for SYN to generate a sent event */ + if (pcb->acked != 0) { + pcb->acked--; + } + + pcb->cwnd = LWIP_TCP_CALC_INITIAL_CWND(pcb->mss); + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_process (SYN_RCVD): cwnd %"TCPWNDSIZE_F + " ssthresh %"TCPWNDSIZE_F"\n", + pcb->cwnd, pcb->ssthresh)); + + if (recv_flags & TF_GOT_FIN) { + tcp_ack_now(pcb); + pcb->state = CLOSE_WAIT; + } + } else { + /* incorrect ACK number, send RST */ + tcp_rst(ackno, seqno + tcplen, ipX_current_dest_addr(), + ipX_current_src_addr(), tcphdr->dest, tcphdr->src, ip_current_is_v6()); + } + } else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) { + /* Looks like another copy of the SYN - retransmit our SYN-ACK */ + tcp_rexmit(pcb); + } + break; + case CLOSE_WAIT: + /* FALLTHROUGH */ + case ESTABLISHED: + tcp_receive(pcb); + if (recv_flags & TF_GOT_FIN) { /* passive close */ + tcp_ack_now(pcb); + pcb->state = CLOSE_WAIT; + } + break; + case FIN_WAIT_1: + tcp_receive(pcb); + if (recv_flags & TF_GOT_FIN) { + if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) { + LWIP_DEBUGF(TCP_DEBUG, + ("TCP connection closed: FIN_WAIT_1 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); + tcp_ack_now(pcb); + tcp_pcb_purge(pcb); + TCP_RMV_ACTIVE(pcb); + pcb->state = TIME_WAIT; + TCP_REG(&tcp_tw_pcbs, pcb); + } else { + tcp_ack_now(pcb); + pcb->state = CLOSING; + } + } else if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) { + pcb->state = FIN_WAIT_2; + } + break; + case FIN_WAIT_2: + tcp_receive(pcb); + if (recv_flags & TF_GOT_FIN) { + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: FIN_WAIT_2 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); + tcp_ack_now(pcb); + tcp_pcb_purge(pcb); + TCP_RMV_ACTIVE(pcb); + pcb->state = TIME_WAIT; + TCP_REG(&tcp_tw_pcbs, pcb); + } + break; + case CLOSING: + tcp_receive(pcb); + if (flags & TCP_ACK && ackno == pcb->snd_nxt) { + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: CLOSING %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); + tcp_pcb_purge(pcb); + TCP_RMV_ACTIVE(pcb); + pcb->state = TIME_WAIT; + TCP_REG(&tcp_tw_pcbs, pcb); + } + break; + case LAST_ACK: + tcp_receive(pcb); + if (flags & TCP_ACK && ackno == pcb->snd_nxt) { + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: LAST_ACK %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); + /* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */ + recv_flags |= TF_CLOSED; + } + break; + default: + break; + } + return ERR_OK; +} + +#if TCP_QUEUE_OOSEQ +/** + * Insert segment into the list (segments covered with new one will be deleted) + * + * Called from tcp_receive() + */ +static void +tcp_oos_insert_segment(struct tcp_seg *cseg, struct tcp_seg *next) +{ + struct tcp_seg *old_seg; + + if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) { + /* received segment overlaps all following segments */ + tcp_segs_free(next); + next = NULL; + } + else { + /* delete some following segments + oos queue may have segments with FIN flag */ + while (next && + TCP_SEQ_GEQ((seqno + cseg->len), + (next->tcphdr->seqno + next->len))) { + /* cseg with FIN already processed */ + if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) { + TCPH_SET_FLAG(cseg->tcphdr, TCP_FIN); + } + old_seg = next; + next = next->next; + tcp_seg_free(old_seg); + } + if (next && + TCP_SEQ_GT(seqno + cseg->len, next->tcphdr->seqno)) { + /* We need to trim the incoming segment. */ + cseg->len = (u16_t)(next->tcphdr->seqno - seqno); + pbuf_realloc(cseg->p, cseg->len); + } + } + cseg->next = next; +} +#endif /* TCP_QUEUE_OOSEQ */ + +/** + * Called by tcp_process. Checks if the given segment is an ACK for outstanding + * data, and if so frees the memory of the buffered data. Next, is places the + * segment on any of the receive queues (pcb->recved or pcb->ooseq). If the segment + * is buffered, the pbuf is referenced by pbuf_ref so that it will not be freed until + * it has been removed from the buffer. + * + * If the incoming segment constitutes an ACK for a segment that was used for RTT + * estimation, the RTT is estimated here as well. + * + * Called from tcp_process(). + */ +static void +tcp_receive(struct tcp_pcb *pcb) +{ + struct tcp_seg *next; +#if TCP_QUEUE_OOSEQ + struct tcp_seg *prev, *cseg; +#endif /* TCP_QUEUE_OOSEQ */ + struct pbuf *p; + s32_t off; + s16_t m; + u32_t right_wnd_edge; + u16_t new_tot_len; + int found_dupack = 0; +#if TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS + u32_t ooseq_blen; + u16_t ooseq_qlen; +#endif /* TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS */ + + LWIP_ASSERT("tcp_receive: wrong state", pcb->state >= ESTABLISHED); + + if (flags & TCP_ACK) { + right_wnd_edge = pcb->snd_wnd + pcb->snd_wl2; + + /* Update window. */ + if (TCP_SEQ_LT(pcb->snd_wl1, seqno) || + (pcb->snd_wl1 == seqno && TCP_SEQ_LT(pcb->snd_wl2, ackno)) || + (pcb->snd_wl2 == ackno && tcphdr->wnd > pcb->snd_wnd)) { + pcb->snd_wnd = SND_WND_SCALE(pcb, tcphdr->wnd); + /* keep track of the biggest window announced by the remote host to calculate + the maximum segment size */ + if (pcb->snd_wnd_max < pcb->snd_wnd) { + pcb->snd_wnd_max = pcb->snd_wnd; + } + pcb->snd_wl1 = seqno; + pcb->snd_wl2 = ackno; + if (pcb->snd_wnd == 0) { + if (pcb->persist_backoff == 0) { + /* start persist timer */ + pcb->persist_cnt = 0; + pcb->persist_backoff = 1; + } + } else if (pcb->persist_backoff > 0) { + /* stop persist timer */ + pcb->persist_backoff = 0; + } + LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: window update %"U16_F"\n", pcb->snd_wnd)); +#if TCP_WND_DEBUG + } else { + if (pcb->snd_wnd != tcphdr->wnd) { + LWIP_DEBUGF(TCP_WND_DEBUG, + ("tcp_receive: no window update lastack %"U32_F" ackno %" + U32_F" wl1 %"U32_F" seqno %"U32_F" wl2 %"U32_F"\n", + pcb->lastack, ackno, pcb->snd_wl1, seqno, pcb->snd_wl2)); + } +#endif /* TCP_WND_DEBUG */ + } + + /* (From Stevens TCP/IP Illustrated Vol II, p970.) Its only a + * duplicate ack if: + * 1) It doesn't ACK new data + * 2) length of received packet is zero (i.e. no payload) + * 3) the advertised window hasn't changed + * 4) There is outstanding unacknowledged data (retransmission timer running) + * 5) The ACK is == biggest ACK sequence number so far seen (snd_una) + * + * If it passes all five, should process as a dupack: + * a) dupacks < 3: do nothing + * b) dupacks == 3: fast retransmit + * c) dupacks > 3: increase cwnd + * + * If it only passes 1-3, should reset dupack counter (and add to + * stats, which we don't do in lwIP) + * + * If it only passes 1, should reset dupack counter + * + */ + + /* Clause 1 */ + if (TCP_SEQ_LEQ(ackno, pcb->lastack)) { + pcb->acked = 0; + /* Clause 2 */ + if (tcplen == 0) { + /* Clause 3 */ + if (pcb->snd_wl2 + pcb->snd_wnd == right_wnd_edge){ + /* Clause 4 */ + if (pcb->rtime >= 0) { + /* Clause 5 */ + if (pcb->lastack == ackno) { + found_dupack = 1; + if ((u8_t)(pcb->dupacks + 1) > pcb->dupacks) { + ++pcb->dupacks; + } + if (pcb->dupacks > 3) { + /* Inflate the congestion window, but not if it means that + the value overflows. */ + if ((tcpwnd_size_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { + pcb->cwnd += pcb->mss; + } + } else if (pcb->dupacks == 3) { + /* Do fast retransmit */ + tcp_rexmit_fast(pcb); + } + } + } + } + } + /* If Clause (1) or more is true, but not a duplicate ack, reset + * count of consecutive duplicate acks */ + if (!found_dupack) { + pcb->dupacks = 0; + } + } else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)){ + /* We come here when the ACK acknowledges new data. */ + + /* Reset the "IN Fast Retransmit" flag, since we are no longer + in fast retransmit. Also reset the congestion window to the + slow start threshold. */ + if (pcb->flags & TF_INFR) { + pcb->flags &= ~TF_INFR; + pcb->cwnd = pcb->ssthresh; + } + + /* Reset the number of retransmissions. */ + pcb->nrtx = 0; + + /* Reset the retransmission time-out. */ + pcb->rto = (pcb->sa >> 3) + pcb->sv; + + /* Update the send buffer space. Diff between the two can never exceed 64K + unless window scaling is used. */ + pcb->acked = (tcpwnd_size_t)(ackno - pcb->lastack); + + pcb->snd_buf += pcb->acked; + + /* Reset the fast retransmit variables. */ + pcb->dupacks = 0; + pcb->lastack = ackno; + + /* Update the congestion control variables (cwnd and + ssthresh). */ + if (pcb->state >= ESTABLISHED) { + if (pcb->cwnd < pcb->ssthresh) { + if ((tcpwnd_size_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { + pcb->cwnd += pcb->mss; + } + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: slow start cwnd %"TCPWNDSIZE_F"\n", pcb->cwnd)); + } else { + tcpwnd_size_t new_cwnd = (pcb->cwnd + pcb->mss * pcb->mss / pcb->cwnd); + if (new_cwnd > pcb->cwnd) { + pcb->cwnd = new_cwnd; + } + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %"TCPWNDSIZE_F"\n", pcb->cwnd)); + } + } + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %"U32_F", unacked->seqno %"U32_F":%"U32_F"\n", + ackno, + pcb->unacked != NULL? + ntohl(pcb->unacked->tcphdr->seqno): 0, + pcb->unacked != NULL? + ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0)); + + /* Remove segment from the unacknowledged list if the incoming + ACK acknowledges them. */ + while (pcb->unacked != NULL && + TCP_SEQ_LEQ(ntohl(pcb->unacked->tcphdr->seqno) + + TCP_TCPLEN(pcb->unacked), ackno)) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unacked\n", + ntohl(pcb->unacked->tcphdr->seqno), + ntohl(pcb->unacked->tcphdr->seqno) + + TCP_TCPLEN(pcb->unacked))); + + next = pcb->unacked; + pcb->unacked = pcb->unacked->next; + + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"TCPWNDSIZE_F" ... ", (tcpwnd_size_t)pcb->snd_queuelen)); + LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p))); + /* Prevent ACK for FIN to generate a sent event */ + if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) { + pcb->acked--; + } + + pcb->snd_queuelen -= pbuf_clen(next->p); + tcp_seg_free(next); + + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"TCPWNDSIZE_F" (after freeing unacked)\n", (tcpwnd_size_t)pcb->snd_queuelen)); + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL || + pcb->unsent != NULL); + } + } + + /* If there's nothing left to acknowledge, stop the retransmit + timer, otherwise reset it to start again */ + if (pcb->unacked == NULL) { + pcb->rtime = -1; + } else { + pcb->rtime = 0; + } + + pcb->polltmr = 0; + +#if LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS + if (PCB_ISIPV6(pcb)) { + /* Inform neighbor reachability of forward progress. */ + nd6_reachability_hint(ip6_current_src_addr()); + } +#endif /* LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS*/ + } else { + /* Out of sequence ACK, didn't really ack anything */ + pcb->acked = 0; + tcp_send_empty_ack(pcb); + } + + /* We go through the ->unsent list to see if any of the segments + on the list are acknowledged by the ACK. This may seem + strange since an "unsent" segment shouldn't be acked. The + rationale is that lwIP puts all outstanding segments on the + ->unsent list after a retransmission, so these segments may + in fact have been sent once. */ + while (pcb->unsent != NULL && + TCP_SEQ_BETWEEN(ackno, ntohl(pcb->unsent->tcphdr->seqno) + + TCP_TCPLEN(pcb->unsent), pcb->snd_nxt)) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unsent\n", + ntohl(pcb->unsent->tcphdr->seqno), ntohl(pcb->unsent->tcphdr->seqno) + + TCP_TCPLEN(pcb->unsent))); + + next = pcb->unsent; + pcb->unsent = pcb->unsent->next; +#if TCP_OVERSIZE + if (pcb->unsent == NULL) { + pcb->unsent_oversize = 0; + } +#endif /* TCP_OVERSIZE */ + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"TCPWNDSIZE_F" ... ", (tcpwnd_size_t)pcb->snd_queuelen)); + LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p))); + /* Prevent ACK for FIN to generate a sent event */ + if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) { + pcb->acked--; + } + pcb->snd_queuelen -= pbuf_clen(next->p); + tcp_seg_free(next); + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"TCPWNDSIZE_F" (after freeing unsent)\n", (tcpwnd_size_t)pcb->snd_queuelen)); + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_receive: valid queue length", + pcb->unacked != NULL || pcb->unsent != NULL); + } + } + /* End of ACK for new data processing. */ + + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %"U32_F" rtseq %"U32_F" ackno %"U32_F"\n", + pcb->rttest, pcb->rtseq, ackno)); + + /* RTT estimation calculations. This is done by checking if the + incoming segment acknowledges the segment we use to take a + round-trip time measurement. */ + if (pcb->rttest && TCP_SEQ_LT(pcb->rtseq, ackno)) { + /* diff between this shouldn't exceed 32K since this are tcp timer ticks + and a round-trip shouldn't be that long... */ + m = (s16_t)(tcp_ticks - pcb->rttest); + + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: experienced rtt %"U16_F" ticks (%"U16_F" msec).\n", + m, m * TCP_SLOW_INTERVAL)); + + /* This is taken directly from VJs original code in his paper */ + m = m - (pcb->sa >> 3); + pcb->sa += m; + if (m < 0) { + m = -m; + } + m = m - (pcb->sv >> 2); + pcb->sv += m; + pcb->rto = (pcb->sa >> 3) + pcb->sv; + + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: RTO %"U16_F" (%"U16_F" milliseconds)\n", + pcb->rto, pcb->rto * TCP_SLOW_INTERVAL)); + + pcb->rttest = 0; + } + } + + /* If the incoming segment contains data, we must process it + further unless the pcb already received a FIN. + (RFC 793, chapter 3.9, "SEGMENT ARRIVES" in states CLOSE-WAIT, CLOSING, + LAST-ACK and TIME-WAIT: "Ignore the segment text.") */ + if ((tcplen > 0) && (pcb->state < CLOSE_WAIT)) { + /* This code basically does three things: + + +) If the incoming segment contains data that is the next + in-sequence data, this data is passed to the application. This + might involve trimming the first edge of the data. The rcv_nxt + variable and the advertised window are adjusted. + + +) If the incoming segment has data that is above the next + sequence number expected (->rcv_nxt), the segment is placed on + the ->ooseq queue. This is done by finding the appropriate + place in the ->ooseq queue (which is ordered by sequence + number) and trim the segment in both ends if needed. An + immediate ACK is sent to indicate that we received an + out-of-sequence segment. + + +) Finally, we check if the first segment on the ->ooseq queue + now is in sequence (i.e., if rcv_nxt >= ooseq->seqno). If + rcv_nxt > ooseq->seqno, we must trim the first edge of the + segment on ->ooseq before we adjust rcv_nxt. The data in the + segments that are now on sequence are chained onto the + incoming segment so that we only need to call the application + once. + */ + + /* First, we check if we must trim the first edge. We have to do + this if the sequence number of the incoming segment is less + than rcv_nxt, and the sequence number plus the length of the + segment is larger than rcv_nxt. */ + /* if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){ + if (TCP_SEQ_LT(pcb->rcv_nxt, seqno + tcplen)) {*/ + if (TCP_SEQ_BETWEEN(pcb->rcv_nxt, seqno + 1, seqno + tcplen - 1)){ + /* Trimming the first edge is done by pushing the payload + pointer in the pbuf downwards. This is somewhat tricky since + we do not want to discard the full contents of the pbuf up to + the new starting point of the data since we have to keep the + TCP header which is present in the first pbuf in the chain. + + What is done is really quite a nasty hack: the first pbuf in + the pbuf chain is pointed to by inseg.p. Since we need to be + able to deallocate the whole pbuf, we cannot change this + inseg.p pointer to point to any of the later pbufs in the + chain. Instead, we point the ->payload pointer in the first + pbuf to data in one of the later pbufs. We also set the + inseg.data pointer to point to the right place. This way, the + ->p pointer will still point to the first pbuf, but the + ->p->payload pointer will point to data in another pbuf. + + After we are done with adjusting the pbuf pointers we must + adjust the ->data pointer in the seg and the segment + length.*/ + + off = pcb->rcv_nxt - seqno; + p = inseg.p; + LWIP_ASSERT("inseg.p != NULL", inseg.p); + LWIP_ASSERT("insane offset!", (off < 0x7fff)); + if (inseg.p->len < off) { + LWIP_ASSERT("pbuf too short!", (((s32_t)inseg.p->tot_len) >= off)); + new_tot_len = (u16_t)(inseg.p->tot_len - off); + while (p->len < off) { + off -= p->len; + /* KJM following line changed (with addition of new_tot_len var) + to fix bug #9076 + inseg.p->tot_len -= p->len; */ + p->tot_len = new_tot_len; + p->len = 0; + p = p->next; + } + if(pbuf_header(p, (s16_t)-off)) { + /* Do we need to cope with this failing? Assert for now */ + LWIP_ASSERT("pbuf_header failed", 0); + } + } else { + if(pbuf_header(inseg.p, (s16_t)-off)) { + /* Do we need to cope with this failing? Assert for now */ + LWIP_ASSERT("pbuf_header failed", 0); + } + } + inseg.len -= (u16_t)(pcb->rcv_nxt - seqno); + inseg.tcphdr->seqno = seqno = pcb->rcv_nxt; + } + else { + if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){ + /* the whole segment is < rcv_nxt */ + /* must be a duplicate of a packet that has already been correctly handled */ + + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %"U32_F"\n", seqno)); + tcp_ack_now(pcb); + } + } + + /* The sequence number must be within the window (above rcv_nxt + and below rcv_nxt + rcv_wnd) in order to be further + processed. */ + if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, + pcb->rcv_nxt + pcb->rcv_wnd - 1)){ + if (pcb->rcv_nxt == seqno) { + /* The incoming segment is the next in sequence. We check if + we have to trim the end of the segment and update rcv_nxt + and pass the data to the application. */ + tcplen = TCP_TCPLEN(&inseg); + + if (tcplen > pcb->rcv_wnd) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, + ("tcp_receive: other end overran receive window" + "seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n", + seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd)); + if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { + /* Must remove the FIN from the header as we're trimming + * that byte of sequence-space from the packet */ + TCPH_FLAGS_SET(inseg.tcphdr, TCPH_FLAGS(inseg.tcphdr) &~ TCP_FIN); + } + /* Adjust length of segment to fit in the window. */ + inseg.len = pcb->rcv_wnd; + if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) { + inseg.len -= 1; + } + pbuf_realloc(inseg.p, inseg.len); + tcplen = TCP_TCPLEN(&inseg); + LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n", + (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd)); + } +#if TCP_QUEUE_OOSEQ + /* Received in-sequence data, adjust ooseq data if: + - FIN has been received or + - inseq overlaps with ooseq */ + if (pcb->ooseq != NULL) { + if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, + ("tcp_receive: received in-order FIN, binning ooseq queue\n")); + /* Received in-order FIN means anything that was received + * out of order must now have been received in-order, so + * bin the ooseq queue */ + while (pcb->ooseq != NULL) { + struct tcp_seg *old_ooseq = pcb->ooseq; + pcb->ooseq = pcb->ooseq->next; + tcp_seg_free(old_ooseq); + } + } else { + next = pcb->ooseq; + /* Remove all segments on ooseq that are covered by inseg already. + * FIN is copied from ooseq to inseg if present. */ + while (next && + TCP_SEQ_GEQ(seqno + tcplen, + next->tcphdr->seqno + next->len)) { + /* inseg cannot have FIN here (already processed above) */ + if (TCPH_FLAGS(next->tcphdr) & TCP_FIN && + (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) == 0) { + TCPH_SET_FLAG(inseg.tcphdr, TCP_FIN); + tcplen = TCP_TCPLEN(&inseg); + } + prev = next; + next = next->next; + tcp_seg_free(prev); + } + /* Now trim right side of inseg if it overlaps with the first + * segment on ooseq */ + if (next && + TCP_SEQ_GT(seqno + tcplen, + next->tcphdr->seqno)) { + /* inseg cannot have FIN here (already processed above) */ + inseg.len = (u16_t)(next->tcphdr->seqno - seqno); + if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) { + inseg.len -= 1; + } + pbuf_realloc(inseg.p, inseg.len); + tcplen = TCP_TCPLEN(&inseg); + LWIP_ASSERT("tcp_receive: segment not trimmed correctly to ooseq queue\n", + (seqno + tcplen) == next->tcphdr->seqno); + } + pcb->ooseq = next; + } + } +#endif /* TCP_QUEUE_OOSEQ */ + + pcb->rcv_nxt = seqno + tcplen; + + /* Update the receiver's (our) window. */ + LWIP_ASSERT("tcp_receive: tcplen > rcv_wnd\n", pcb->rcv_wnd >= tcplen); + pcb->rcv_wnd -= tcplen; + + tcp_update_rcv_ann_wnd(pcb); + + /* If there is data in the segment, we make preparations to + pass this up to the application. The ->recv_data variable + is used for holding the pbuf that goes to the + application. The code for reassembling out-of-sequence data + chains its data on this pbuf as well. + + If the segment was a FIN, we set the TF_GOT_FIN flag that will + be used to indicate to the application that the remote side has + closed its end of the connection. */ + if (inseg.p->tot_len > 0) { + recv_data = inseg.p; + /* Since this pbuf now is the responsibility of the + application, we delete our reference to it so that we won't + (mistakingly) deallocate it. */ + inseg.p = NULL; + } + if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN.\n")); + recv_flags |= TF_GOT_FIN; + } + +#if TCP_QUEUE_OOSEQ + /* We now check if we have segments on the ->ooseq queue that + are now in sequence. */ + while (pcb->ooseq != NULL && + pcb->ooseq->tcphdr->seqno == pcb->rcv_nxt) { + + cseg = pcb->ooseq; + seqno = pcb->ooseq->tcphdr->seqno; + + pcb->rcv_nxt += TCP_TCPLEN(cseg); + LWIP_ASSERT("tcp_receive: ooseq tcplen > rcv_wnd\n", + pcb->rcv_wnd >= TCP_TCPLEN(cseg)); + pcb->rcv_wnd -= TCP_TCPLEN(cseg); + + tcp_update_rcv_ann_wnd(pcb); + + if (cseg->p->tot_len > 0) { + /* Chain this pbuf onto the pbuf that we will pass to + the application. */ + /* With window scaling, this can overflow recv_data->tot_len, but + that's not a problem since we explicitly fix that before passing + recv_data to the application. */ + if (recv_data) { + pbuf_cat(recv_data, cseg->p); + } else { + recv_data = cseg->p; + } + cseg->p = NULL; + } + if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n")); + recv_flags |= TF_GOT_FIN; + if (pcb->state == ESTABLISHED) { /* force passive close or we can move to active close */ + pcb->state = CLOSE_WAIT; + } + } + + pcb->ooseq = cseg->next; + tcp_seg_free(cseg); + } +#endif /* TCP_QUEUE_OOSEQ */ + + + /* Acknowledge the segment(s). */ + tcp_ack(pcb); + +#if LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS + if (PCB_ISIPV6(pcb)) { + /* Inform neighbor reachability of forward progress. */ + nd6_reachability_hint(ip6_current_src_addr()); + } +#endif /* LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS*/ + + } else { + /* We get here if the incoming segment is out-of-sequence. */ + tcp_send_empty_ack(pcb); +#if TCP_QUEUE_OOSEQ + /* We queue the segment on the ->ooseq queue. */ + if (pcb->ooseq == NULL) { + pcb->ooseq = tcp_seg_copy(&inseg); + } else { + /* If the queue is not empty, we walk through the queue and + try to find a place where the sequence number of the + incoming segment is between the sequence numbers of the + previous and the next segment on the ->ooseq queue. That is + the place where we put the incoming segment. If needed, we + trim the second edges of the previous and the incoming + segment so that it will fit into the sequence. + + If the incoming segment has the same sequence number as a + segment on the ->ooseq queue, we discard the segment that + contains less data. */ + + prev = NULL; + for(next = pcb->ooseq; next != NULL; next = next->next) { + if (seqno == next->tcphdr->seqno) { + /* The sequence number of the incoming segment is the + same as the sequence number of the segment on + ->ooseq. We check the lengths to see which one to + discard. */ + if (inseg.len > next->len) { + /* The incoming segment is larger than the old + segment. We replace some segments with the new + one. */ + cseg = tcp_seg_copy(&inseg); + if (cseg != NULL) { + if (prev != NULL) { + prev->next = cseg; + } else { + pcb->ooseq = cseg; + } + tcp_oos_insert_segment(cseg, next); + } + break; + } else { + /* Either the lengths are the same or the incoming + segment was smaller than the old one; in either + case, we ditch the incoming segment. */ + break; + } + } else { + if (prev == NULL) { + if (TCP_SEQ_LT(seqno, next->tcphdr->seqno)) { + /* The sequence number of the incoming segment is lower + than the sequence number of the first segment on the + queue. We put the incoming segment first on the + queue. */ + cseg = tcp_seg_copy(&inseg); + if (cseg != NULL) { + pcb->ooseq = cseg; + tcp_oos_insert_segment(cseg, next); + } + break; + } + } else { + /*if (TCP_SEQ_LT(prev->tcphdr->seqno, seqno) && + TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {*/ + if (TCP_SEQ_BETWEEN(seqno, prev->tcphdr->seqno+1, next->tcphdr->seqno-1)) { + /* The sequence number of the incoming segment is in + between the sequence numbers of the previous and + the next segment on ->ooseq. We trim trim the previous + segment, delete next segments that included in received segment + and trim received, if needed. */ + cseg = tcp_seg_copy(&inseg); + if (cseg != NULL) { + if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) { + /* We need to trim the prev segment. */ + prev->len = (u16_t)(seqno - prev->tcphdr->seqno); + pbuf_realloc(prev->p, prev->len); + } + prev->next = cseg; + tcp_oos_insert_segment(cseg, next); + } + break; + } + } + /* If the "next" segment is the last segment on the + ooseq queue, we add the incoming segment to the end + of the list. */ + if (next->next == NULL && + TCP_SEQ_GT(seqno, next->tcphdr->seqno)) { + if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) { + /* segment "next" already contains all data */ + break; + } + next->next = tcp_seg_copy(&inseg); + if (next->next != NULL) { + if (TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) { + /* We need to trim the last segment. */ + next->len = (u16_t)(seqno - next->tcphdr->seqno); + pbuf_realloc(next->p, next->len); + } + /* check if the remote side overruns our receive window */ + if ((u32_t)tcplen + seqno > pcb->rcv_nxt + (u32_t)pcb->rcv_wnd) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, + ("tcp_receive: other end overran receive window" + "seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n", + seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd)); + if (TCPH_FLAGS(next->next->tcphdr) & TCP_FIN) { + /* Must remove the FIN from the header as we're trimming + * that byte of sequence-space from the packet */ + TCPH_FLAGS_SET(next->next->tcphdr, TCPH_FLAGS(next->next->tcphdr) &~ TCP_FIN); + } + /* Adjust length of segment to fit in the window. */ + next->next->len = pcb->rcv_nxt + pcb->rcv_wnd - seqno; + pbuf_realloc(next->next->p, next->next->len); + tcplen = TCP_TCPLEN(next->next); + LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n", + (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd)); + } + } + break; + } + } + prev = next; + } + } +#if TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS + /* Check that the data on ooseq doesn't exceed one of the limits + and throw away everything above that limit. */ + ooseq_blen = 0; + ooseq_qlen = 0; + prev = NULL; + for(next = pcb->ooseq; next != NULL; prev = next, next = next->next) { + struct pbuf *p = next->p; + ooseq_blen += p->tot_len; + ooseq_qlen += pbuf_clen(p); + if ((ooseq_blen > TCP_OOSEQ_MAX_BYTES) || + (ooseq_qlen > TCP_OOSEQ_MAX_PBUFS)) { + /* too much ooseq data, dump this and everything after it */ + tcp_segs_free(next); + if (prev == NULL) { + /* first ooseq segment is too much, dump the whole queue */ + pcb->ooseq = NULL; + } else { + /* just dump 'next' and everything after it */ + prev->next = NULL; + } + break; + } + } +#endif /* TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS */ +#endif /* TCP_QUEUE_OOSEQ */ + } + } else { + /* The incoming segment is not within the window. */ + tcp_send_empty_ack(pcb); + } + } else { + /* Segments with length 0 is taken care of here. Segments that + fall out of the window are ACKed. */ + /*if (TCP_SEQ_GT(pcb->rcv_nxt, seqno) || + TCP_SEQ_GEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/ + if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd-1)){ + tcp_ack_now(pcb); + } + } +} + +static u8_t tcp_getoptbyte(void) +{ + if ((tcphdr_opt2 == NULL) || (tcp_optidx < tcphdr_opt1len)) { + u8_t* opts = (u8_t *)tcphdr + TCP_HLEN; + return opts[tcp_optidx++]; + } else { + u8_t idx = tcp_optidx++ - tcphdr_opt1len; + return tcphdr_opt2[idx]; + } +} + +/** + * Parses the options contained in the incoming segment. + * + * Called from tcp_listen_input() and tcp_process(). + * Currently, only the MSS option is supported! + * + * @param pcb the tcp_pcb for which a segment arrived + */ +static void +tcp_parseopt(struct tcp_pcb *pcb) +{ + u8_t data; + u16_t mss; +#if LWIP_TCP_TIMESTAMPS + u32_t tsval; +#endif + + /* Parse the TCP MSS option, if present. */ + if (TCPH_HDRLEN(tcphdr) > 0x5) { + u16_t max_c = (TCPH_HDRLEN(tcphdr) - 5) << 2; + for (tcp_optidx = 0; tcp_optidx < max_c; ) { + u8_t opt = tcp_getoptbyte(); + switch (opt) { + case LWIP_TCP_OPT_EOL: + /* End of options. */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: EOL\n")); + return; + case LWIP_TCP_OPT_NOP: + /* NOP option. */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: NOP\n")); + break; + case LWIP_TCP_OPT_MSS: + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: MSS\n")); + if (tcp_getoptbyte() != LWIP_TCP_OPT_LEN_MSS || (tcp_optidx - 2 + LWIP_TCP_OPT_LEN_MSS) > max_c) { + /* Bad length */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); + return; + } + /* An MSS option with the right option length. */ + mss = (tcp_getoptbyte() << 8); + mss |= tcp_getoptbyte(); + /* Limit the mss to the configured TCP_MSS and prevent division by zero */ + pcb->mss = ((mss > TCP_MSS) || (mss == 0)) ? TCP_MSS : mss; + break; +#if LWIP_WND_SCALE + case LWIP_TCP_OPT_WS: + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: WND_SCALE\n")); + if (tcp_getoptbyte() != LWIP_TCP_OPT_LEN_WS || (tcp_optidx - 2 + LWIP_TCP_OPT_LEN_WS) > max_c) { + /* Bad length */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); + return; + } + /* If syn was received with wnd scale option, + activate wnd scale opt */ + data = tcp_getoptbyte(); + if (flags & TCP_SYN) { + /* An WND_SCALE option with the right option length. */ + pcb->snd_scale = data; + if (pcb->snd_scale > 14U) { + pcb->snd_scale = 14U; + } + pcb->rcv_scale = TCP_RCV_SCALE; + pcb->flags |= TF_WND_SCALE; + } + break; +#endif +#if LWIP_TCP_TIMESTAMPS + case LWIP_TCP_OPT_TS: + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: TS\n")); + if (tcp_getoptbyte() != LWIP_TCP_OPT_LEN_TS || (tcp_optidx - 2 + LWIP_TCP_OPT_LEN_TS) > max_c) { + /* Bad length */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); + return; + } + /* TCP timestamp option with valid length */ + tsval = tcp_getoptbyte(); + tsval |= (tcp_getoptbyte() << 8); + tsval |= (tcp_getoptbyte() << 16); + tsval |= (tcp_getoptbyte() << 24); + if (flags & TCP_SYN) { + pcb->ts_recent = ntohl(tsval); + /* Enable sending timestamps in every segment now that we know + the remote host supports it. */ + pcb->flags |= TF_TIMESTAMP; + } else if (TCP_SEQ_BETWEEN(pcb->ts_lastacksent, seqno, seqno+tcplen)) { + pcb->ts_recent = ntohl(tsval); + } + /* Advance to next option (6 bytes already read) */ + tcp_optidx += LWIP_TCP_OPT_LEN_TS - 6; + break; +#endif + default: + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: other\n")); + data = tcp_getoptbyte(); + if (data < 2) { + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); + /* If the length field is zero, the options are malformed + and we don't process them further. */ + return; + } + /* All other options have a length field, so that we easily + can skip past them. */ + tcp_optidx += data - 2; + } + } + } +} + +#endif /* LWIP_TCP */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/core/tcp_out.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/tcp_out.c new file mode 100644 index 0000000..10ed021 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/tcp_out.c @@ -0,0 +1,1574 @@ +/** + * @file + * Transmission Control Protocol, outgoing traffic + * + * The output functions of TCP. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/tcp_impl.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/inet_chksum.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/inet_chksum.h" +#if LWIP_TCP_TIMESTAMPS +#include "lwip/sys.h" +#endif + +#include + +/* Define some copy-macros for checksum-on-copy so that the code looks + nicer by preventing too many ifdef's. */ +#if TCP_CHECKSUM_ON_COPY +#define TCP_DATA_COPY(dst, src, len, seg) do { \ + tcp_seg_add_chksum(LWIP_CHKSUM_COPY(dst, src, len), \ + len, &seg->chksum, &seg->chksum_swapped); \ + seg->flags |= TF_SEG_DATA_CHECKSUMMED; } while(0) +#define TCP_DATA_COPY2(dst, src, len, chksum, chksum_swapped) \ + tcp_seg_add_chksum(LWIP_CHKSUM_COPY(dst, src, len), len, chksum, chksum_swapped); +#else /* TCP_CHECKSUM_ON_COPY*/ +#define TCP_DATA_COPY(dst, src, len, seg) MEMCPY(dst, src, len) +#define TCP_DATA_COPY2(dst, src, len, chksum, chksum_swapped) MEMCPY(dst, src, len) +#endif /* TCP_CHECKSUM_ON_COPY*/ + +/** Define this to 1 for an extra check that the output checksum is valid + * (usefule when the checksum is generated by the application, not the stack) */ +#ifndef TCP_CHECKSUM_ON_COPY_SANITY_CHECK +#define TCP_CHECKSUM_ON_COPY_SANITY_CHECK 0 +#endif +/* Allow to override the failure of sanity check from warning to e.g. hard failure */ +#if TCP_CHECKSUM_ON_COPY_SANITY_CHECK +#ifndef TCP_CHECKSUM_ON_COPY_SANITY_CHECK_FAIL +#define TCP_CHECKSUM_ON_COPY_SANITY_CHECK_FAIL(msg) LWIP_DEBUGF(TCP_DEBUG | LWIP_DBG_LEVEL_WARNING, msg) +#endif +#endif + +#if TCP_OVERSIZE +/** The size of segment pbufs created when TCP_OVERSIZE is enabled */ +#ifndef TCP_OVERSIZE_CALC_LENGTH +#define TCP_OVERSIZE_CALC_LENGTH(length) ((length) + TCP_OVERSIZE) +#endif +#endif + +/* Forward declarations.*/ +static void tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb); + +/** Allocate a pbuf and create a tcphdr at p->payload, used for output + * functions other than the default tcp_output -> tcp_output_segment + * (e.g. tcp_send_empty_ack, etc.) + * + * @param pcb tcp pcb for which to send a packet (used to initialize tcp_hdr) + * @param optlen length of header-options + * @param datalen length of tcp data to reserve in pbuf + * @param seqno_be seqno in network byte order (big-endian) + * @return pbuf with p->payload being the tcp_hdr + */ +static struct pbuf * +tcp_output_alloc_header(struct tcp_pcb *pcb, u16_t optlen, u16_t datalen, + u32_t seqno_be /* already in network byte order */) +{ + struct tcp_hdr *tcphdr; + struct pbuf *p = pbuf_alloc(PBUF_IP, TCP_HLEN + optlen + datalen, PBUF_RAM); + if (p != NULL) { + LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr", + (p->len >= TCP_HLEN + optlen)); + tcphdr = (struct tcp_hdr *)p->payload; + tcphdr->src = htons(pcb->local_port); + tcphdr->dest = htons(pcb->remote_port); + tcphdr->seqno = seqno_be; + tcphdr->ackno = htonl(pcb->rcv_nxt); + TCPH_HDRLEN_FLAGS_SET(tcphdr, (5 + optlen / 4), TCP_ACK); + tcphdr->wnd = htons(RCV_WND_SCALE(pcb, pcb->rcv_ann_wnd)); + tcphdr->chksum = 0; + tcphdr->urgp = 0; + + /* If we're sending a packet, update the announced right window edge */ + pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd; + } + return p; +} + +/** + * Called by tcp_close() to send a segment including FIN flag but not data. + * + * @param pcb the tcp_pcb over which to send a segment + * @return ERR_OK if sent, another err_t otherwise + */ +err_t +tcp_send_fin(struct tcp_pcb *pcb) +{ + /* first, try to add the fin to the last unsent segment */ + if (pcb->unsent != NULL) { + struct tcp_seg *last_unsent; + for (last_unsent = pcb->unsent; last_unsent->next != NULL; + last_unsent = last_unsent->next); + + if ((TCPH_FLAGS(last_unsent->tcphdr) & (TCP_SYN | TCP_FIN | TCP_RST)) == 0) { + /* no SYN/FIN/RST flag in the header, we can add the FIN flag */ + TCPH_SET_FLAG(last_unsent->tcphdr, TCP_FIN); + pcb->flags |= TF_FIN; + return ERR_OK; + } + } + /* no data, no length, flags, copy=1, no optdata */ + return tcp_enqueue_flags(pcb, TCP_FIN); +} + +/** + * Create a TCP segment with prefilled header. + * + * Called by tcp_write and tcp_enqueue_flags. + * + * @param pcb Protocol control block for the TCP connection. + * @param p pbuf that is used to hold the TCP header. + * @param flags TCP flags for header. + * @param seqno TCP sequence number of this packet + * @param optflags options to include in TCP header + * @return a new tcp_seg pointing to p, or NULL. + * The TCP header is filled in except ackno and wnd. + * p is freed on failure. + */ +static struct tcp_seg * +tcp_create_segment(struct tcp_pcb *pcb, struct pbuf *p, u8_t flags, u32_t seqno, u8_t optflags) +{ + struct tcp_seg *seg; + u8_t optlen = LWIP_TCP_OPT_LENGTH(optflags); + + if ((seg = (struct tcp_seg *)memp_malloc(MEMP_TCP_SEG)) == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_create_segment: no memory.\n")); + pbuf_free(p); + return NULL; + } + seg->flags = optflags; + seg->next = NULL; + seg->p = p; + LWIP_ASSERT("p->tot_len >= optlen", p->tot_len >= optlen); + seg->len = p->tot_len - optlen; +#if TCP_OVERSIZE_DBGCHECK + seg->oversize_left = 0; +#endif /* TCP_OVERSIZE_DBGCHECK */ +#if TCP_CHECKSUM_ON_COPY + seg->chksum = 0; + seg->chksum_swapped = 0; + /* check optflags */ + LWIP_ASSERT("invalid optflags passed: TF_SEG_DATA_CHECKSUMMED", + (optflags & TF_SEG_DATA_CHECKSUMMED) == 0); +#endif /* TCP_CHECKSUM_ON_COPY */ + + /* build TCP header */ + if (pbuf_header(p, TCP_HLEN)) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_create_segment: no room for TCP header in pbuf.\n")); + TCP_STATS_INC(tcp.err); + tcp_seg_free(seg); + return NULL; + } + seg->tcphdr = (struct tcp_hdr *)seg->p->payload; + seg->tcphdr->src = htons(pcb->local_port); + seg->tcphdr->dest = htons(pcb->remote_port); + seg->tcphdr->seqno = htonl(seqno); + /* ackno is set in tcp_output */ + TCPH_HDRLEN_FLAGS_SET(seg->tcphdr, (5 + optlen / 4), flags); + /* wnd and chksum are set in tcp_output */ + seg->tcphdr->urgp = 0; + return seg; +} + +/** + * Allocate a PBUF_RAM pbuf, perhaps with extra space at the end. + * + * This function is like pbuf_alloc(layer, length, PBUF_RAM) except + * there may be extra bytes available at the end. + * + * @param layer flag to define header size. + * @param length size of the pbuf's payload. + * @param max_length maximum usable size of payload+oversize. + * @param oversize pointer to a u16_t that will receive the number of usable tail bytes. + * @param pcb The TCP connection that willo enqueue the pbuf. + * @param apiflags API flags given to tcp_write. + * @param first_seg true when this pbuf will be used in the first enqueued segment. + * @param + */ +#if TCP_OVERSIZE +static struct pbuf * +tcp_pbuf_prealloc(pbuf_layer layer, u16_t length, u16_t max_length, + u16_t *oversize, struct tcp_pcb *pcb, u8_t apiflags, + u8_t first_seg) +{ + struct pbuf *p; + u16_t alloc = length; + +#if LWIP_NETIF_TX_SINGLE_PBUF + LWIP_UNUSED_ARG(max_length); + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(apiflags); + LWIP_UNUSED_ARG(first_seg); + /* always create MSS-sized pbufs */ + alloc = max_length; +#else /* LWIP_NETIF_TX_SINGLE_PBUF */ + if (length < max_length) { + /* Should we allocate an oversized pbuf, or just the minimum + * length required? If tcp_write is going to be called again + * before this segment is transmitted, we want the oversized + * buffer. If the segment will be transmitted immediately, we can + * save memory by allocating only length. We use a simple + * heuristic based on the following information: + * + * Did the user set TCP_WRITE_FLAG_MORE? + * + * Will the Nagle algorithm defer transmission of this segment? + */ + if ((apiflags & TCP_WRITE_FLAG_MORE) || + (!(pcb->flags & TF_NODELAY) && + (!first_seg || + pcb->unsent != NULL || + pcb->unacked != NULL))) { + alloc = LWIP_MIN(max_length, LWIP_MEM_ALIGN_SIZE(TCP_OVERSIZE_CALC_LENGTH(length))); + } + } +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + p = pbuf_alloc(layer, alloc, PBUF_RAM); + if (p == NULL) { + return NULL; + } + LWIP_ASSERT("need unchained pbuf", p->next == NULL); + *oversize = p->len - length; + /* trim p->len to the currently used size */ + p->len = p->tot_len = length; + return p; +} +#else /* TCP_OVERSIZE */ +#define tcp_pbuf_prealloc(layer, length, mx, os, pcb, api, fst) pbuf_alloc((layer), (length), PBUF_RAM) +#endif /* TCP_OVERSIZE */ + +#if TCP_CHECKSUM_ON_COPY +/** Add a checksum of newly added data to the segment */ +static void +tcp_seg_add_chksum(u16_t chksum, u16_t len, u16_t *seg_chksum, + u8_t *seg_chksum_swapped) +{ + u32_t helper; + /* add chksum to old chksum and fold to u16_t */ + helper = chksum + *seg_chksum; + chksum = FOLD_U32T(helper); + if ((len & 1) != 0) { + *seg_chksum_swapped = 1 - *seg_chksum_swapped; + chksum = SWAP_BYTES_IN_WORD(chksum); + } + *seg_chksum = chksum; +} +#endif /* TCP_CHECKSUM_ON_COPY */ + +/** Checks if tcp_write is allowed or not (checks state, snd_buf and snd_queuelen). + * + * @param pcb the tcp pcb to check for + * @param len length of data to send (checked agains snd_buf) + * @return ERR_OK if tcp_write is allowed to proceed, another err_t otherwise + */ +static err_t +tcp_write_checks(struct tcp_pcb *pcb, u16_t len) +{ + /* connection is in invalid state for data transmission? */ + if ((pcb->state != ESTABLISHED) && + (pcb->state != CLOSE_WAIT) && + (pcb->state != SYN_SENT) && + (pcb->state != SYN_RCVD)) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_STATE | LWIP_DBG_LEVEL_SEVERE, ("tcp_write() called in invalid state\n")); + return ERR_CONN; + } else if (len == 0) { + return ERR_OK; + } + + /* fail on too much data */ + if (len > pcb->snd_buf) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_write: too much data (len=%"U16_F" > snd_buf=%"U16_F")\n", + len, pcb->snd_buf)); + pcb->flags |= TF_NAGLEMEMERR; + return ERR_MEM; + } + + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_write: queuelen: %"TCPWNDSIZE_F"\n", (tcpwnd_size_t)pcb->snd_queuelen)); + + /* If total number of pbufs on the unsent/unacked queues exceeds the + * configured maximum, return an error */ + /* check for configured max queuelen and possible overflow */ + if ((pcb->snd_queuelen >= TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_write: too long queue %"TCPWNDSIZE_F" (max %"TCPWNDSIZE_F")\n", + pcb->snd_queuelen, TCP_SND_QUEUELEN)); + TCP_STATS_INC(tcp.memerr); + pcb->flags |= TF_NAGLEMEMERR; + return ERR_MEM; + } + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_write: pbufs on queue => at least one queue non-empty", + pcb->unacked != NULL || pcb->unsent != NULL); + } else { + LWIP_ASSERT("tcp_write: no pbufs on queue => both queues empty", + pcb->unacked == NULL && pcb->unsent == NULL); + } + return ERR_OK; +} + +/** + * Write data for sending (but does not send it immediately). + * + * It waits in the expectation of more data being sent soon (as + * it can send them more efficiently by combining them together). + * To prompt the system to send data now, call tcp_output() after + * calling tcp_write(). + * + * @param pcb Protocol control block for the TCP connection to enqueue data for. + * @param arg Pointer to the data to be enqueued for sending. + * @param len Data length in bytes + * @param apiflags combination of following flags : + * - TCP_WRITE_FLAG_COPY (0x01) data will be copied into memory belonging to the stack + * - TCP_WRITE_FLAG_MORE (0x02) for TCP connection, PSH flag will be set on last segment sent, + * @return ERR_OK if enqueued, another err_t on error + */ +err_t +tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags) +{ + struct pbuf *concat_p = NULL; + struct tcp_seg *last_unsent = NULL, *seg = NULL, *prev_seg = NULL, *queue = NULL; + u16_t pos = 0; /* position in 'arg' data */ + u16_t queuelen; + u8_t optlen = 0; + u8_t optflags = 0; +#if TCP_OVERSIZE + u16_t oversize = 0; + u16_t oversize_used = 0; +#endif /* TCP_OVERSIZE */ +#if TCP_CHECKSUM_ON_COPY + u16_t concat_chksum = 0; + u8_t concat_chksum_swapped = 0; + u16_t concat_chksummed = 0; +#endif /* TCP_CHECKSUM_ON_COPY */ + err_t err; + /* don't allocate segments bigger than half the maximum window we ever received */ + u16_t mss_local = LWIP_MIN(pcb->mss, pcb->snd_wnd_max/2); + mss_local = mss_local ? mss_local : pcb->mss; + +#if LWIP_NETIF_TX_SINGLE_PBUF + /* Always copy to try to create single pbufs for TX */ + apiflags |= TCP_WRITE_FLAG_COPY; +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, data=%p, len=%"U16_F", apiflags=%"U16_F")\n", + (void *)pcb, arg, len, (u16_t)apiflags)); + LWIP_ERROR("tcp_write: arg == NULL (programmer violates API)", + arg != NULL, return ERR_ARG;); + + err = tcp_write_checks(pcb, len); + if (err != ERR_OK) { + return err; + } + queuelen = pcb->snd_queuelen; + +#if LWIP_TCP_TIMESTAMPS + if ((pcb->flags & TF_TIMESTAMP)) { + /* Make sure the timestamp option is only included in data segments if we + agreed about it with the remote host. */ + optflags = TF_SEG_OPTS_TS; + optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS); + /* ensure that segments can hold at least one data byte... */ + mss_local = LWIP_MAX(mss_local, LWIP_TCP_OPT_LEN_TS + 1); + } +#endif /* LWIP_TCP_TIMESTAMPS */ + + + /* + * TCP segmentation is done in three phases with increasing complexity: + * + * 1. Copy data directly into an oversized pbuf. + * 2. Chain a new pbuf to the end of pcb->unsent. + * 3. Create new segments. + * + * We may run out of memory at any point. In that case we must + * return ERR_MEM and not change anything in pcb. Therefore, all + * changes are recorded in local variables and committed at the end + * of the function. Some pcb fields are maintained in local copies: + * + * queuelen = pcb->snd_queuelen + * oversize = pcb->unsent_oversize + * + * These variables are set consistently by the phases: + * + * seg points to the last segment tampered with. + * + * pos records progress as data is segmented. + */ + + /* Find the tail of the unsent queue. */ + if (pcb->unsent != NULL) { + u16_t space; + u16_t unsent_optlen; + + /* @todo: this could be sped up by keeping last_unsent in the pcb */ + for (last_unsent = pcb->unsent; last_unsent->next != NULL; + last_unsent = last_unsent->next); + + /* Usable space at the end of the last unsent segment */ + unsent_optlen = LWIP_TCP_OPT_LENGTH(last_unsent->flags); + LWIP_ASSERT("mss_local is too small", mss_local >= last_unsent->len + unsent_optlen); + space = mss_local - (last_unsent->len + unsent_optlen); + + /* + * Phase 1: Copy data directly into an oversized pbuf. + * + * The number of bytes copied is recorded in the oversize_used + * variable. The actual copying is done at the bottom of the + * function. + */ +#if TCP_OVERSIZE +#if TCP_OVERSIZE_DBGCHECK + /* check that pcb->unsent_oversize matches last_unsent->unsent_oversize */ + LWIP_ASSERT("unsent_oversize mismatch (pcb vs. last_unsent)", + pcb->unsent_oversize == last_unsent->oversize_left); +#endif /* TCP_OVERSIZE_DBGCHECK */ + oversize = pcb->unsent_oversize; + if (oversize > 0) { + LWIP_ASSERT("inconsistent oversize vs. space", oversize_used <= space); + seg = last_unsent; + oversize_used = oversize < len ? oversize : len; + pos += oversize_used; + oversize -= oversize_used; + space -= oversize_used; + } + /* now we are either finished or oversize is zero */ + LWIP_ASSERT("inconsistend oversize vs. len", (oversize == 0) || (pos == len)); +#endif /* TCP_OVERSIZE */ + + /* + * Phase 2: Chain a new pbuf to the end of pcb->unsent. + * + * We don't extend segments containing SYN/FIN flags or options + * (len==0). The new pbuf is kept in concat_p and pbuf_cat'ed at + * the end. + */ + if ((pos < len) && (space > 0) && (last_unsent->len > 0)) { + u16_t seglen = space < len - pos ? space : len - pos; + seg = last_unsent; + + /* Create a pbuf with a copy or reference to seglen bytes. We + * can use PBUF_RAW here since the data appears in the middle of + * a segment. A header will never be prepended. */ + if (apiflags & TCP_WRITE_FLAG_COPY) { + /* Data is copied */ + if ((concat_p = tcp_pbuf_prealloc(PBUF_RAW, seglen, space, &oversize, pcb, apiflags, 1)) == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, + ("tcp_write : could not allocate memory for pbuf copy size %"U16_F"\n", + seglen)); + goto memerr; + } +#if TCP_OVERSIZE_DBGCHECK + last_unsent->oversize_left += oversize; +#endif /* TCP_OVERSIZE_DBGCHECK */ + TCP_DATA_COPY2(concat_p->payload, (u8_t*)arg + pos, seglen, &concat_chksum, &concat_chksum_swapped); +#if TCP_CHECKSUM_ON_COPY + concat_chksummed += seglen; +#endif /* TCP_CHECKSUM_ON_COPY */ + } else { + /* Data is not copied */ + if ((concat_p = pbuf_alloc(PBUF_RAW, seglen, PBUF_ROM)) == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, + ("tcp_write: could not allocate memory for zero-copy pbuf\n")); + goto memerr; + } +#if TCP_CHECKSUM_ON_COPY + /* calculate the checksum of nocopy-data */ + tcp_seg_add_chksum(~inet_chksum((u8_t*)arg + pos, seglen), seglen, + &concat_chksum, &concat_chksum_swapped); + concat_chksummed += seglen; +#endif /* TCP_CHECKSUM_ON_COPY */ + /* reference the non-volatile payload data */ + concat_p->payload = (u8_t*)arg + pos; + } + + pos += seglen; + queuelen += pbuf_clen(concat_p); + } + } else { +#if TCP_OVERSIZE + LWIP_ASSERT("unsent_oversize mismatch (pcb->unsent is NULL)", + pcb->unsent_oversize == 0); +#endif /* TCP_OVERSIZE */ + } + + /* + * Phase 3: Create new segments. + * + * The new segments are chained together in the local 'queue' + * variable, ready to be appended to pcb->unsent. + */ + while (pos < len) { + struct pbuf *p; + u16_t left = len - pos; + u16_t max_len = mss_local - optlen; + u16_t seglen = left > max_len ? max_len : left; +#if TCP_CHECKSUM_ON_COPY + u16_t chksum = 0; + u8_t chksum_swapped = 0; +#endif /* TCP_CHECKSUM_ON_COPY */ + + if (apiflags & TCP_WRITE_FLAG_COPY) { + /* If copy is set, memory should be allocated and data copied + * into pbuf */ + if ((p = tcp_pbuf_prealloc(PBUF_TRANSPORT, seglen + optlen, mss_local, &oversize, pcb, apiflags, queue == NULL)) == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_write : could not allocate memory for pbuf copy size %"U16_F"\n", seglen)); + goto memerr; + } + LWIP_ASSERT("tcp_write: check that first pbuf can hold the complete seglen", + (p->len >= seglen)); + TCP_DATA_COPY2((char *)p->payload + optlen, (u8_t*)arg + pos, seglen, &chksum, &chksum_swapped); + } else { + /* Copy is not set: First allocate a pbuf for holding the data. + * Since the referenced data is available at least until it is + * sent out on the link (as it has to be ACKed by the remote + * party) we can safely use PBUF_ROM instead of PBUF_REF here. + */ + struct pbuf *p2; +#if TCP_OVERSIZE + LWIP_ASSERT("oversize == 0", oversize == 0); +#endif /* TCP_OVERSIZE */ + if ((p2 = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_ROM)) == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_write: could not allocate memory for zero-copy pbuf\n")); + goto memerr; + } +#if TCP_CHECKSUM_ON_COPY + /* calculate the checksum of nocopy-data */ + chksum = ~inet_chksum((u8_t*)arg + pos, seglen); + if (seglen & 1) { + chksum_swapped = 1; + chksum = SWAP_BYTES_IN_WORD(chksum); + } +#endif /* TCP_CHECKSUM_ON_COPY */ + /* reference the non-volatile payload data */ + p2->payload = (u8_t*)arg + pos; + + /* Second, allocate a pbuf for the headers. */ + if ((p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) { + /* If allocation fails, we have to deallocate the data pbuf as + * well. */ + pbuf_free(p2); + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_write: could not allocate memory for header pbuf\n")); + goto memerr; + } + /* Concatenate the headers and data pbufs together. */ + pbuf_cat(p/*header*/, p2/*data*/); + } + + queuelen += pbuf_clen(p); + + /* Now that there are more segments queued, we check again if the + * length of the queue exceeds the configured maximum or + * overflows. */ + if ((queuelen > TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_write: queue too long %"TCPWNDSIZE_F" (%"TCPWNDSIZE_F")\n", queuelen, TCP_SND_QUEUELEN)); + pbuf_free(p); + goto memerr; + } + + if ((seg = tcp_create_segment(pcb, p, 0, pcb->snd_lbb + pos, optflags)) == NULL) { + goto memerr; + } +#if TCP_OVERSIZE_DBGCHECK + seg->oversize_left = oversize; +#endif /* TCP_OVERSIZE_DBGCHECK */ +#if TCP_CHECKSUM_ON_COPY + seg->chksum = chksum; + seg->chksum_swapped = chksum_swapped; + seg->flags |= TF_SEG_DATA_CHECKSUMMED; +#endif /* TCP_CHECKSUM_ON_COPY */ + + /* first segment of to-be-queued data? */ + if (queue == NULL) { + queue = seg; + } else { + /* Attach the segment to the end of the queued segments */ + LWIP_ASSERT("prev_seg != NULL", prev_seg != NULL); + prev_seg->next = seg; + } + /* remember last segment of to-be-queued data for next iteration */ + prev_seg = seg; + + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, ("tcp_write: queueing %"U32_F":%"U32_F"\n", + ntohl(seg->tcphdr->seqno), + ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg))); + + pos += seglen; + } + + /* + * All three segmentation phases were successful. We can commit the + * transaction. + */ + + /* + * Phase 1: If data has been added to the preallocated tail of + * last_unsent, we update the length fields of the pbuf chain. + */ +#if TCP_OVERSIZE + if (oversize_used > 0) { + struct pbuf *p; + /* Bump tot_len of whole chain, len of tail */ + for (p = last_unsent->p; p; p = p->next) { + p->tot_len += oversize_used; + if (p->next == NULL) { + TCP_DATA_COPY((char *)p->payload + p->len, arg, oversize_used, last_unsent); + p->len += oversize_used; + } + } + last_unsent->len += oversize_used; +#if TCP_OVERSIZE_DBGCHECK + LWIP_ASSERT("last_unsent->oversize_left >= oversize_used", + last_unsent->oversize_left >= oversize_used); + last_unsent->oversize_left -= oversize_used; +#endif /* TCP_OVERSIZE_DBGCHECK */ + } + pcb->unsent_oversize = oversize; +#endif /* TCP_OVERSIZE */ + + /* + * Phase 2: concat_p can be concatenated onto last_unsent->p + */ + if (concat_p != NULL) { + LWIP_ASSERT("tcp_write: cannot concatenate when pcb->unsent is empty", + (last_unsent != NULL)); + pbuf_cat(last_unsent->p, concat_p); + last_unsent->len += concat_p->tot_len; +#if TCP_CHECKSUM_ON_COPY + if (concat_chksummed) { + /*if concat checksumm swapped - swap it back */ + if (concat_chksum_swapped){ + concat_chksum = SWAP_BYTES_IN_WORD(concat_chksum); + } + tcp_seg_add_chksum(concat_chksum, concat_chksummed, &last_unsent->chksum, + &last_unsent->chksum_swapped); + last_unsent->flags |= TF_SEG_DATA_CHECKSUMMED; + } +#endif /* TCP_CHECKSUM_ON_COPY */ + } + + /* + * Phase 3: Append queue to pcb->unsent. Queue may be NULL, but that + * is harmless + */ + if (last_unsent == NULL) { + pcb->unsent = queue; + } else { + last_unsent->next = queue; + } + + /* + * Finally update the pcb state. + */ + pcb->snd_lbb += len; + pcb->snd_buf -= len; + pcb->snd_queuelen = queuelen; + + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_write: %"S16_F" (after enqueued)\n", + pcb->snd_queuelen)); + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_write: valid queue length", + pcb->unacked != NULL || pcb->unsent != NULL); + } + + /* Set the PSH flag in the last segment that we enqueued. */ + if (seg != NULL && seg->tcphdr != NULL && ((apiflags & TCP_WRITE_FLAG_MORE)==0)) { + TCPH_SET_FLAG(seg->tcphdr, TCP_PSH); + } + + return ERR_OK; +memerr: + pcb->flags |= TF_NAGLEMEMERR; + TCP_STATS_INC(tcp.memerr); + + if (concat_p != NULL) { + pbuf_free(concat_p); + } + if (queue != NULL) { + tcp_segs_free(queue); + } + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_write: valid queue length", pcb->unacked != NULL || + pcb->unsent != NULL); + } + LWIP_DEBUGF(TCP_QLEN_DEBUG | LWIP_DBG_STATE, ("tcp_write: %"S16_F" (with mem err)\n", pcb->snd_queuelen)); + return ERR_MEM; +} + +/** + * Enqueue TCP options for transmission. + * + * Called by tcp_connect(), tcp_listen_input(), and tcp_send_ctrl(). + * + * @param pcb Protocol control block for the TCP connection. + * @param flags TCP header flags to set in the outgoing segment. + * @param optdata pointer to TCP options, or NULL. + * @param optlen length of TCP options in bytes. + */ +err_t +tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags) +{ + struct pbuf *p; + struct tcp_seg *seg; + u8_t optflags = 0; + u8_t optlen = 0; + + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue_flags: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen)); + + LWIP_ASSERT("tcp_enqueue_flags: need either TCP_SYN or TCP_FIN in flags (programmer violates API)", + (flags & (TCP_SYN | TCP_FIN)) != 0); + + /* check for configured max queuelen and possible overflow (FIN flag should always come through!) */ + if (((pcb->snd_queuelen >= TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) && + ((flags & TCP_FIN) == 0)) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue_flags: too long queue %"U16_F" (max %"U16_F")\n", + pcb->snd_queuelen, TCP_SND_QUEUELEN)); + TCP_STATS_INC(tcp.memerr); + pcb->flags |= TF_NAGLEMEMERR; + return ERR_MEM; + } + + if (flags & TCP_SYN) { + optflags = TF_SEG_OPTS_MSS; +#if LWIP_WND_SCALE + if ((pcb->state != SYN_RCVD) || (pcb->flags & TF_WND_SCALE)) { + /* In a (sent in state SYN_RCVD), the window scale option may only + be sent if we received a window scale option from the remote host. */ + optflags |= TF_SEG_OPTS_WND_SCALE; + } +#endif /* LWIP_WND_SCALE */ + } +#if LWIP_TCP_TIMESTAMPS + if ((pcb->flags & TF_TIMESTAMP)) { + /* Make sure the timestamp option is only included in data segments if we + agreed about it with the remote host. */ + optflags |= TF_SEG_OPTS_TS; + } +#endif /* LWIP_TCP_TIMESTAMPS */ + optlen = LWIP_TCP_OPT_LENGTH(optflags); + + /* tcp_enqueue_flags is always called with either SYN or FIN in flags. + * We need one available snd_buf byte to do that. + * This means we can't send FIN while snd_buf==0. A better fix would be to + * not include SYN and FIN sequence numbers in the snd_buf count. */ + if (pcb->snd_buf == 0) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue_flags: no send buffer available\n")); + TCP_STATS_INC(tcp.memerr); + return ERR_MEM; + } + + /* Allocate pbuf with room for TCP header + options */ + if ((p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) { + pcb->flags |= TF_NAGLEMEMERR; + TCP_STATS_INC(tcp.memerr); + return ERR_MEM; + } + LWIP_ASSERT("tcp_enqueue_flags: check that first pbuf can hold optlen", + (p->len >= optlen)); + + /* Allocate memory for tcp_seg, and fill in fields. */ + if ((seg = tcp_create_segment(pcb, p, flags, pcb->snd_lbb, optflags)) == NULL) { + pcb->flags |= TF_NAGLEMEMERR; + TCP_STATS_INC(tcp.memerr); + return ERR_MEM; + } + LWIP_ASSERT("seg->tcphdr not aligned", ((mem_ptr_t)seg->tcphdr % 4) == 0); + LWIP_ASSERT("tcp_enqueue_flags: invalid segment length", seg->len == 0); + + LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, + ("tcp_enqueue_flags: queueing %"U32_F":%"U32_F" (0x%"X16_F")\n", + ntohl(seg->tcphdr->seqno), + ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg), + (u16_t)flags)); + + /* Now append seg to pcb->unsent queue */ + if (pcb->unsent == NULL) { + pcb->unsent = seg; + } else { + struct tcp_seg *useg; + for (useg = pcb->unsent; useg->next != NULL; useg = useg->next); + useg->next = seg; + } +#if TCP_OVERSIZE + /* The new unsent tail has no space */ + pcb->unsent_oversize = 0; +#endif /* TCP_OVERSIZE */ + + /* SYN and FIN bump the sequence number */ + if ((flags & TCP_SYN) || (flags & TCP_FIN)) { + pcb->snd_lbb++; + /* optlen does not influence snd_buf */ + pcb->snd_buf--; + } + if (flags & TCP_FIN) { + pcb->flags |= TF_FIN; + } + + /* update number of segments on the queues */ + pcb->snd_queuelen += pbuf_clen(seg->p); + LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue_flags: %"S16_F" (after enqueued)\n", pcb->snd_queuelen)); + if (pcb->snd_queuelen != 0) { + LWIP_ASSERT("tcp_enqueue_flags: invalid queue length", + pcb->unacked != NULL || pcb->unsent != NULL); + } + + return ERR_OK; +} + +#if LWIP_TCP_TIMESTAMPS +/* Build a timestamp option (12 bytes long) at the specified options pointer) + * + * @param pcb tcp_pcb + * @param opts option pointer where to store the timestamp option + */ +static void +tcp_build_timestamp_option(struct tcp_pcb *pcb, u32_t *opts) +{ + /* Pad with two NOP options to make everything nicely aligned */ + opts[0] = PP_HTONL(0x0101080A); + opts[1] = htonl(sys_now()); + opts[2] = htonl(pcb->ts_recent); +} +#endif + +#if LWIP_WND_SCALE +/** Build a window scale option (3 bytes long) at the specified options pointer) + * + * @param opts option pointer where to store the window scale option + */ +static void +tcp_build_wnd_scale_option(u32_t *opts) +{ + /* Pad with one NOP option to make everything nicely aligned */ + opts[0] = PP_HTONL(0x01030300 | TCP_RCV_SCALE); +} +#endif + +/** Send an ACK without data. + * + * @param pcb Protocol control block for the TCP connection to send the ACK + */ +err_t +tcp_send_empty_ack(struct tcp_pcb *pcb) +{ + struct pbuf *p; + u8_t optlen = 0; +#if LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP + struct tcp_hdr *tcphdr; +#endif /* LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP */ + +#if LWIP_TCP_TIMESTAMPS + if (pcb->flags & TF_TIMESTAMP) { + optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS); + } +#endif + + p = tcp_output_alloc_header(pcb, optlen, 0, htonl(pcb->snd_nxt)); + if (p == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n")); + return ERR_BUF; + } +#if LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP + tcphdr = (struct tcp_hdr *)p->payload; +#endif /* LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP */ + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, + ("tcp_output: sending ACK for %"U32_F"\n", pcb->rcv_nxt)); + /* remove ACK flags from the PCB, as we send an empty ACK now */ + pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); + + /* NB. MSS and window scale options are only sent on SYNs, so ignore them here */ +#if LWIP_TCP_TIMESTAMPS + pcb->ts_lastacksent = pcb->rcv_nxt; + + if (pcb->flags & TF_TIMESTAMP) { + tcp_build_timestamp_option(pcb, (u32_t *)(tcphdr + 1)); + } +#endif + +#if CHECKSUM_GEN_TCP + tcphdr->chksum = ipX_chksum_pseudo(PCB_ISIPV6(pcb), p, IP_PROTO_TCP, p->tot_len, + &pcb->local_ip, &pcb->remote_ip); +#endif +#if LWIP_NETIF_HWADDRHINT + ipX_output_hinted(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, + IP_PROTO_TCP, &pcb->addr_hint); +#else /* LWIP_NETIF_HWADDRHINT*/ + ipX_output(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, + IP_PROTO_TCP); +#endif /* LWIP_NETIF_HWADDRHINT*/ + pbuf_free(p); + + return ERR_OK; +} + +/** + * Find out what we can send and send it + * + * @param pcb Protocol control block for the TCP connection to send data + * @return ERR_OK if data has been sent or nothing to send + * another err_t on error + */ +err_t +tcp_output(struct tcp_pcb *pcb) +{ + struct tcp_seg *seg, *useg; + u32_t wnd, snd_nxt; +#if TCP_CWND_DEBUG + s16_t i = 0; +#endif /* TCP_CWND_DEBUG */ + + /* pcb->state LISTEN not allowed here */ + LWIP_ASSERT("don't call tcp_output for listen-pcbs", + pcb->state != LISTEN); + + /* First, check if we are invoked by the TCP input processing + code. If so, we do not output anything. Instead, we rely on the + input processing code to call us when input processing is done + with. */ + if (tcp_input_pcb == pcb) { + return ERR_OK; + } + + wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd); + + seg = pcb->unsent; + + /* If the TF_ACK_NOW flag is set and no data will be sent (either + * because the ->unsent queue is empty or because the window does + * not allow it), construct an empty ACK segment and send it. + * + * If data is to be sent, we will just piggyback the ACK (see below). + */ + if (pcb->flags & TF_ACK_NOW && + (seg == NULL || + ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) { + return tcp_send_empty_ack(pcb); + } + + /* useg should point to last segment on unacked queue */ + useg = pcb->unacked; + if (useg != NULL) { + for (; useg->next != NULL; useg = useg->next); + } + +#if TCP_OUTPUT_DEBUG + if (seg == NULL) { + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n", + (void*)pcb->unsent)); + } +#endif /* TCP_OUTPUT_DEBUG */ +#if TCP_CWND_DEBUG + if (seg == NULL) { + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"TCPWNDSIZE_F + ", cwnd %"TCPWNDSIZE_F", wnd %"U32_F + ", seg == NULL, ack %"U32_F"\n", + pcb->snd_wnd, pcb->cwnd, wnd, pcb->lastack)); + } else { + LWIP_DEBUGF(TCP_CWND_DEBUG, + ("tcp_output: snd_wnd %"TCPWNDSIZE_F", cwnd %"TCPWNDSIZE_F", wnd %"U32_F + ", effwnd %"U32_F", seq %"U32_F", ack %"U32_F"\n", + pcb->snd_wnd, pcb->cwnd, wnd, + ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len, + ntohl(seg->tcphdr->seqno), pcb->lastack)); + } +#endif /* TCP_CWND_DEBUG */ + /* data available and window allows it to be sent? */ + while (seg != NULL && + ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) { + LWIP_ASSERT("RST not expected here!", + (TCPH_FLAGS(seg->tcphdr) & TCP_RST) == 0); + /* Stop sending if the nagle algorithm would prevent it + * Don't stop: + * - if tcp_write had a memory error before (prevent delayed ACK timeout) or + * - if FIN was already enqueued for this PCB (SYN is always alone in a segment - + * either seg->next != NULL or pcb->unacked == NULL; + * RST is no sent using tcp_write/tcp_output. + */ + if((tcp_do_output_nagle(pcb) == 0) && + ((pcb->flags & (TF_NAGLEMEMERR | TF_FIN)) == 0)){ + break; + } +#if TCP_CWND_DEBUG + LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"TCPWNDSIZE_F", cwnd %"TCPWNDSIZE_F", wnd %"U32_F", effwnd %"U32_F", seq %"U32_F", ack %"U32_F", i %"S16_F"\n", + pcb->snd_wnd, pcb->cwnd, wnd, + ntohl(seg->tcphdr->seqno) + seg->len - + pcb->lastack, + ntohl(seg->tcphdr->seqno), pcb->lastack, i)); + ++i; +#endif /* TCP_CWND_DEBUG */ + + pcb->unsent = seg->next; + + if (pcb->state != SYN_SENT) { + TCPH_SET_FLAG(seg->tcphdr, TCP_ACK); + pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); + } + +#if TCP_OVERSIZE_DBGCHECK + seg->oversize_left = 0; +#endif /* TCP_OVERSIZE_DBGCHECK */ + tcp_output_segment(seg, pcb); + snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg); + if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) { + pcb->snd_nxt = snd_nxt; + } + /* put segment on unacknowledged list if length > 0 */ + if (TCP_TCPLEN(seg) > 0) { + seg->next = NULL; + /* unacked list is empty? */ + if (pcb->unacked == NULL) { + pcb->unacked = seg; + useg = seg; + /* unacked list is not empty? */ + } else { + /* In the case of fast retransmit, the packet should not go to the tail + * of the unacked queue, but rather somewhere before it. We need to check for + * this case. -STJ Jul 27, 2004 */ + if (TCP_SEQ_LT(ntohl(seg->tcphdr->seqno), ntohl(useg->tcphdr->seqno))) { + /* add segment to before tail of unacked list, keeping the list sorted */ + struct tcp_seg **cur_seg = &(pcb->unacked); + while (*cur_seg && + TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) { + cur_seg = &((*cur_seg)->next ); + } + seg->next = (*cur_seg); + (*cur_seg) = seg; + } else { + /* add segment to tail of unacked list */ + useg->next = seg; + useg = useg->next; + } + } + /* do not queue empty segments on the unacked list */ + } else { + tcp_seg_free(seg); + } + seg = pcb->unsent; + } +#if TCP_OVERSIZE + if (pcb->unsent == NULL) { + /* last unsent has been removed, reset unsent_oversize */ + pcb->unsent_oversize = 0; + } +#endif /* TCP_OVERSIZE */ + + pcb->flags &= ~TF_NAGLEMEMERR; + return ERR_OK; +} + +/** + * Called by tcp_output() to actually send a TCP segment over IP. + * + * @param seg the tcp_seg to send + * @param pcb the tcp_pcb for the TCP connection used to send the segment + */ +static void +tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb) +{ + u16_t len; + u32_t *opts; + + /** @bug Exclude retransmitted segments from this count. */ + snmp_inc_tcpoutsegs(); + + /* The TCP header has already been constructed, but the ackno and + wnd fields remain. */ + seg->tcphdr->ackno = htonl(pcb->rcv_nxt); + + /* advertise our receive window size in this TCP segment */ +#if LWIP_WND_SCALE + if (seg->flags & TF_SEG_OPTS_WND_SCALE) { + /* The Window field in a SYN segment itself (the only type where we send + the window scale option) is never scaled. */ + seg->tcphdr->wnd = htons(pcb->rcv_ann_wnd); + } else +#endif /* LWIP_WND_SCALE */ + { + seg->tcphdr->wnd = htons(RCV_WND_SCALE(pcb, pcb->rcv_ann_wnd)); + } + + pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd; + + /* Add any requested options. NB MSS option is only set on SYN + packets, so ignore it here */ + opts = (u32_t *)(void *)(seg->tcphdr + 1); + if (seg->flags & TF_SEG_OPTS_MSS) { + u16_t mss; +#if TCP_CALCULATE_EFF_SEND_MSS + mss = tcp_eff_send_mss(TCP_MSS, &pcb->local_ip, &pcb->remote_ip, PCB_ISIPV6(pcb)); +#else /* TCP_CALCULATE_EFF_SEND_MSS */ + mss = TCP_MSS; +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + *opts = TCP_BUILD_MSS_OPTION(mss); + opts += 1; + } +#if LWIP_TCP_TIMESTAMPS + pcb->ts_lastacksent = pcb->rcv_nxt; + + if (seg->flags & TF_SEG_OPTS_TS) { + tcp_build_timestamp_option(pcb, opts); + opts += 3; + } +#endif +#if LWIP_WND_SCALE + if (seg->flags & TF_SEG_OPTS_WND_SCALE) { + tcp_build_wnd_scale_option(opts); + opts += 1; + } +#endif + + /* Set retransmission timer running if it is not currently enabled + This must be set before checking the route. */ + if (pcb->rtime == -1) { + pcb->rtime = 0; + } + + /* If we don't have a local IP address, we get one by + calling ip_route(). */ + if (ipX_addr_isany(PCB_ISIPV6(pcb), &pcb->local_ip)) { + struct netif *netif; + ipX_addr_t *local_ip; + ipX_route_get_local_ipX(PCB_ISIPV6(pcb), &pcb->local_ip, &pcb->remote_ip, netif, local_ip); + if ((netif == NULL) || (local_ip == NULL)) { + return; + } + ipX_addr_copy(PCB_ISIPV6(pcb), pcb->local_ip, *local_ip); + } + + if (pcb->rttest == 0) { + pcb->rttest = tcp_ticks; + pcb->rtseq = ntohl(seg->tcphdr->seqno); + + LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %"U32_F"\n", pcb->rtseq)); + } + LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %"U32_F":%"U32_F"\n", + htonl(seg->tcphdr->seqno), htonl(seg->tcphdr->seqno) + + seg->len)); + + len = (u16_t)((u8_t *)seg->tcphdr - (u8_t *)seg->p->payload); + + seg->p->len -= len; + seg->p->tot_len -= len; + + seg->p->payload = seg->tcphdr; + + seg->tcphdr->chksum = 0; +#if TCP_CHECKSUM_ON_COPY + { + u32_t acc; +#if TCP_CHECKSUM_ON_COPY_SANITY_CHECK + u16_t chksum_slow = ipX_chksum_pseudo(PCB_ISIPV6(pcb), seg->p, IP_PROTO_TCP, + seg->p->tot_len, &pcb->local_ip, &pcb->remote_ip); +#endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */ + if ((seg->flags & TF_SEG_DATA_CHECKSUMMED) == 0) { + LWIP_ASSERT("data included but not checksummed", + seg->p->tot_len == (TCPH_HDRLEN(seg->tcphdr) * 4)); + } + + /* rebuild TCP header checksum (TCP header changes for retransmissions!) */ + acc = ipX_chksum_pseudo_partial(PCB_ISIPV6(pcb), seg->p, IP_PROTO_TCP, + seg->p->tot_len, TCPH_HDRLEN(seg->tcphdr) * 4, &pcb->local_ip, &pcb->remote_ip); + /* add payload checksum */ + if (seg->chksum_swapped) { + seg->chksum = SWAP_BYTES_IN_WORD(seg->chksum); + seg->chksum_swapped = 0; + } + acc += (u16_t)~(seg->chksum); + seg->tcphdr->chksum = FOLD_U32T(acc); +#if TCP_CHECKSUM_ON_COPY_SANITY_CHECK + if (chksum_slow != seg->tcphdr->chksum) { + TCP_CHECKSUM_ON_COPY_SANITY_CHECK_FAIL( + ("tcp_output_segment: calculated checksum is %"X16_F" instead of %"X16_F"\n", + seg->tcphdr->chksum, chksum_slow)); + seg->tcphdr->chksum = chksum_slow; + } +#endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */ + } +#else /* TCP_CHECKSUM_ON_COPY */ +#if CHECKSUM_GEN_TCP + seg->tcphdr->chksum = ipX_chksum_pseudo(PCB_ISIPV6(pcb), seg->p, IP_PROTO_TCP, + seg->p->tot_len, &pcb->local_ip, &pcb->remote_ip); +#endif /* CHECKSUM_GEN_TCP */ +#endif /* TCP_CHECKSUM_ON_COPY */ + TCP_STATS_INC(tcp.xmit); + +#if LWIP_NETIF_HWADDRHINT + ipX_output_hinted(PCB_ISIPV6(pcb), seg->p, &pcb->local_ip, &pcb->remote_ip, + pcb->ttl, pcb->tos, IP_PROTO_TCP, &pcb->addr_hint); +#else /* LWIP_NETIF_HWADDRHINT*/ + ipX_output(PCB_ISIPV6(pcb), seg->p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, + pcb->tos, IP_PROTO_TCP); +#endif /* LWIP_NETIF_HWADDRHINT*/ +} + +/** + * Send a TCP RESET packet (empty segment with RST flag set) either to + * abort a connection or to show that there is no matching local connection + * for a received segment. + * + * Called by tcp_abort() (to abort a local connection), tcp_input() (if no + * matching local pcb was found), tcp_listen_input() (if incoming segment + * has ACK flag set) and tcp_process() (received segment in the wrong state) + * + * Since a RST segment is in most cases not sent for an active connection, + * tcp_rst() has a number of arguments that are taken from a tcp_pcb for + * most other segment output functions. + * + * @param seqno the sequence number to use for the outgoing segment + * @param ackno the acknowledge number to use for the outgoing segment + * @param local_ip the local IP address to send the segment from + * @param remote_ip the remote IP address to send the segment to + * @param local_port the local TCP port to send the segment from + * @param remote_port the remote TCP port to send the segment to + */ +void +tcp_rst_impl(u32_t seqno, u32_t ackno, + ipX_addr_t *local_ip, ipX_addr_t *remote_ip, + u16_t local_port, u16_t remote_port +#if LWIP_IPV6 + , u8_t isipv6 +#endif /* LWIP_IPV6 */ + ) +{ + struct pbuf *p; + struct tcp_hdr *tcphdr; + p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM); + if (p == NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n")); + return; + } + LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr", + (p->len >= sizeof(struct tcp_hdr))); + + tcphdr = (struct tcp_hdr *)p->payload; + tcphdr->src = htons(local_port); + tcphdr->dest = htons(remote_port); + tcphdr->seqno = htonl(seqno); + tcphdr->ackno = htonl(ackno); + TCPH_HDRLEN_FLAGS_SET(tcphdr, TCP_HLEN/4, TCP_RST | TCP_ACK); +#if LWIP_WND_SCALE + tcphdr->wnd = PP_HTONS(((TCP_WND >> TCP_RCV_SCALE) & 0xFFFF)); +#else + tcphdr->wnd = PP_HTONS(TCP_WND); +#endif + tcphdr->chksum = 0; + tcphdr->urgp = 0; + + TCP_STATS_INC(tcp.xmit); + snmp_inc_tcpoutrsts(); + +#if CHECKSUM_GEN_TCP + tcphdr->chksum = ipX_chksum_pseudo(isipv6, p, IP_PROTO_TCP, p->tot_len, + local_ip, remote_ip); +#endif + /* Send output with hardcoded TTL/HL since we have no access to the pcb */ + ipX_output(isipv6, p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP); + pbuf_free(p); + LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %"U32_F" ackno %"U32_F".\n", seqno, ackno)); +} + +/** + * Requeue all unacked segments for retransmission + * + * Called by tcp_slowtmr() for slow retransmission. + * + * @param pcb the tcp_pcb for which to re-enqueue all unacked segments + */ +void +tcp_rexmit_rto(struct tcp_pcb *pcb) +{ + struct tcp_seg *seg; + + if (pcb->unacked == NULL) { + return; + } + + /* Move all unacked segments to the head of the unsent queue */ + for (seg = pcb->unacked; seg->next != NULL; seg = seg->next); + /* concatenate unsent queue after unacked queue */ + seg->next = pcb->unsent; +#if TCP_OVERSIZE && TCP_OVERSIZE_DBGCHECK + /* if last unsent changed, we need to update unsent_oversize */ + if (pcb->unsent == NULL) { + pcb->unsent_oversize = seg->oversize_left; + } +#endif /* TCP_OVERSIZE && TCP_OVERSIZE_DBGCHECK*/ + /* unsent queue is the concatenated queue (of unacked, unsent) */ + pcb->unsent = pcb->unacked; + /* unacked queue is now empty */ + pcb->unacked = NULL; + + /* increment number of retransmissions */ + ++pcb->nrtx; + + /* Don't take any RTT measurements after retransmitting. */ + pcb->rttest = 0; + + /* Do the actual retransmission */ + tcp_output(pcb); +} + +/** + * Requeue the first unacked segment for retransmission + * + * Called by tcp_receive() for fast retramsmit. + * + * @param pcb the tcp_pcb for which to retransmit the first unacked segment + */ +void +tcp_rexmit(struct tcp_pcb *pcb) +{ + struct tcp_seg *seg; + struct tcp_seg **cur_seg; + + if (pcb->unacked == NULL) { + return; + } + + /* Move the first unacked segment to the unsent queue */ + /* Keep the unsent queue sorted. */ + seg = pcb->unacked; + pcb->unacked = seg->next; + + cur_seg = &(pcb->unsent); + while (*cur_seg && + TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) { + cur_seg = &((*cur_seg)->next ); + } + seg->next = *cur_seg; + *cur_seg = seg; +#if TCP_OVERSIZE + if (seg->next == NULL) { + /* the retransmitted segment is last in unsent, so reset unsent_oversize */ + pcb->unsent_oversize = 0; + } +#endif /* TCP_OVERSIZE */ + + ++pcb->nrtx; + + /* Don't take any rtt measurements after retransmitting. */ + pcb->rttest = 0; + + /* Do the actual retransmission. */ + snmp_inc_tcpretranssegs(); + /* No need to call tcp_output: we are always called from tcp_input() + and thus tcp_output directly returns. */ +} + + +/** + * Handle retransmission after three dupacks received + * + * @param pcb the tcp_pcb for which to retransmit the first unacked segment + */ +void +tcp_rexmit_fast(struct tcp_pcb *pcb) +{ + if (pcb->unacked != NULL && !(pcb->flags & TF_INFR)) { + /* This is fast retransmit. Retransmit the first unacked segment. */ + LWIP_DEBUGF(TCP_FR_DEBUG, + ("tcp_receive: dupacks %"U16_F" (%"U32_F + "), fast retransmit %"U32_F"\n", + (u16_t)pcb->dupacks, pcb->lastack, + ntohl(pcb->unacked->tcphdr->seqno))); + tcp_rexmit(pcb); + + /* Set ssthresh to half of the minimum of the current + * cwnd and the advertised window */ + if (pcb->cwnd > pcb->snd_wnd) { + pcb->ssthresh = pcb->snd_wnd / 2; + } else { + pcb->ssthresh = pcb->cwnd / 2; + } + + /* The minimum value for ssthresh should be 2 MSS */ + if (pcb->ssthresh < (2U * pcb->mss)) { + LWIP_DEBUGF(TCP_FR_DEBUG, + ("tcp_receive: The minimum value for ssthresh %"U16_F + " should be min 2 mss %"U16_F"...\n", + pcb->ssthresh, 2*pcb->mss)); + pcb->ssthresh = 2*pcb->mss; + } + + pcb->cwnd = pcb->ssthresh + 3 * pcb->mss; + pcb->flags |= TF_INFR; + } +} + + +/** + * Send keepalive packets to keep a connection active although + * no data is sent over it. + * + * Called by tcp_slowtmr() + * + * @param pcb the tcp_pcb for which to send a keepalive packet + */ +void +tcp_keepalive(struct tcp_pcb *pcb) +{ + struct pbuf *p; +#if CHECKSUM_GEN_TCP + struct tcp_hdr *tcphdr; +#endif /* CHECKSUM_GEN_TCP */ + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to ")); + ipX_addr_debug_print(PCB_ISIPV6(pcb), TCP_DEBUG, &pcb->remote_ip); + LWIP_DEBUGF(TCP_DEBUG, ("\n")); + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F" pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n", + tcp_ticks, pcb->tmr, pcb->keep_cnt_sent)); + + p = tcp_output_alloc_header(pcb, 0, 0, htonl(pcb->snd_nxt - 1)); + if(p == NULL) { + LWIP_DEBUGF(TCP_DEBUG, + ("tcp_keepalive: could not allocate memory for pbuf\n")); + return; + } +#if CHECKSUM_GEN_TCP + tcphdr = (struct tcp_hdr *)p->payload; + + tcphdr->chksum = ipX_chksum_pseudo(PCB_ISIPV6(pcb), p, IP_PROTO_TCP, p->tot_len, + &pcb->local_ip, &pcb->remote_ip); +#endif /* CHECKSUM_GEN_TCP */ + TCP_STATS_INC(tcp.xmit); + + /* Send output to IP */ +#if LWIP_NETIF_HWADDRHINT + ipX_output_hinted(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, + pcb->ttl, 0, IP_PROTO_TCP, &pcb->addr_hint); +#else /* LWIP_NETIF_HWADDRHINT*/ + ipX_output(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, + 0, IP_PROTO_TCP); +#endif /* LWIP_NETIF_HWADDRHINT*/ + + pbuf_free(p); + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: seqno %"U32_F" ackno %"U32_F".\n", + pcb->snd_nxt - 1, pcb->rcv_nxt)); +} + + +/** + * Send persist timer zero-window probes to keep a connection active + * when a window update is lost. + * + * Called by tcp_slowtmr() + * + * @param pcb the tcp_pcb for which to send a zero-window probe packet + */ +void +tcp_zero_window_probe(struct tcp_pcb *pcb) +{ + struct pbuf *p; + struct tcp_hdr *tcphdr; + struct tcp_seg *seg; + u16_t len; + u8_t is_fin; + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: sending ZERO WINDOW probe to ")); + ipX_addr_debug_print(PCB_ISIPV6(pcb), TCP_DEBUG, &pcb->remote_ip); + LWIP_DEBUGF(TCP_DEBUG, ("\n")); + + LWIP_DEBUGF(TCP_DEBUG, + ("tcp_zero_window_probe: tcp_ticks %"U32_F + " pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n", + tcp_ticks, pcb->tmr, pcb->keep_cnt_sent)); + + seg = pcb->unacked; + + if(seg == NULL) { + seg = pcb->unsent; + } + if(seg == NULL) { + return; + } + + is_fin = ((TCPH_FLAGS(seg->tcphdr) & TCP_FIN) != 0) && (seg->len == 0); + /* we want to send one seqno: either FIN or data (no options) */ + len = is_fin ? 0 : 1; + + p = tcp_output_alloc_header(pcb, 0, len, seg->tcphdr->seqno); + if(p == NULL) { + LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: no memory for pbuf\n")); + return; + } + tcphdr = (struct tcp_hdr *)p->payload; + + if (is_fin) { + /* FIN segment, no data */ + TCPH_FLAGS_SET(tcphdr, TCP_ACK | TCP_FIN); + } else { + /* Data segment, copy in one byte from the head of the unacked queue */ + char *d = ((char *)p->payload + TCP_HLEN); + /* Depending on whether the segment has already been sent (unacked) or not + (unsent), seg->p->payload points to the IP header or TCP header. + Ensure we copy the first TCP data byte: */ + pbuf_copy_partial(seg->p, d, 1, seg->p->tot_len - seg->len); + } + +#if CHECKSUM_GEN_TCP + tcphdr->chksum = ipX_chksum_pseudo(PCB_ISIPV6(pcb), p, IP_PROTO_TCP, p->tot_len, + &pcb->local_ip, &pcb->remote_ip); +#endif + TCP_STATS_INC(tcp.xmit); + + /* Send output to IP */ +#if LWIP_NETIF_HWADDRHINT + ipX_output_hinted(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, + 0, IP_PROTO_TCP, &pcb->addr_hint); +#else /* LWIP_NETIF_HWADDRHINT*/ + ipX_output(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP); +#endif /* LWIP_NETIF_HWADDRHINT*/ + + pbuf_free(p); + + LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: seqno %"U32_F + " ackno %"U32_F".\n", + pcb->snd_nxt - 1, pcb->rcv_nxt)); +} +#endif /* LWIP_TCP */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/core/udp.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/udp.c new file mode 100644 index 0000000..39a07e3 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/core/udp.c @@ -0,0 +1,1164 @@ +/** + * @file + * User Datagram Protocol module + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + + +/* udp.c + * + * The code for the User Datagram Protocol UDP & UDPLite (RFC 3828). + * + */ + +/* @todo Check the use of '(struct udp_pcb).chksum_len_rx'! + */ + +#include "lwip/opt.h" + +#if LWIP_UDP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/udp.h" +#include "lwip/def.h" +#include "lwip/memp.h" +#include "lwip/inet_chksum.h" +#include "lwip/ip_addr.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/inet_chksum.h" +#include "lwip/netif.h" +#include "lwip/icmp.h" +#include "lwip/icmp6.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "arch/perf.h" +#include "lwip/dhcp.h" + +#include + +#ifndef UDP_LOCAL_PORT_RANGE_START +/* From http://www.iana.org/assignments/port-numbers: + "The Dynamic and/or Private Ports are those from 49152 through 65535" */ +#define UDP_LOCAL_PORT_RANGE_START 0xc000 +#define UDP_LOCAL_PORT_RANGE_END 0xffff +#define UDP_ENSURE_LOCAL_PORT_RANGE(port) (((port) & ~UDP_LOCAL_PORT_RANGE_START) + UDP_LOCAL_PORT_RANGE_START) +#endif + +/* last local UDP port */ +static u16_t udp_port = UDP_LOCAL_PORT_RANGE_START; + +/* The list of UDP PCBs */ +/* exported in udp.h (was static) */ +struct udp_pcb *udp_pcbs; + +/** + * Initialize this module. + */ +void +udp_init(void) +{ +#if LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) + udp_port = UDP_ENSURE_LOCAL_PORT_RANGE(LWIP_RAND()); +#endif /* LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) */ +} + +/** + * Allocate a new local UDP port. + * + * @return a new (free) local UDP port number + */ +static u16_t +udp_new_port(void) +{ + u16_t n = 0; + struct udp_pcb *pcb; + +again: + if (udp_port++ == UDP_LOCAL_PORT_RANGE_END) { + udp_port = UDP_LOCAL_PORT_RANGE_START; + } + /* Check all PCBs. */ + for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) { + if (pcb->local_port == udp_port) { + if (++n > (UDP_LOCAL_PORT_RANGE_END - UDP_LOCAL_PORT_RANGE_START)) { + return 0; + } + goto again; + } + } + return udp_port; +#if 0 + struct udp_pcb *ipcb = udp_pcbs; + while ((ipcb != NULL) && (udp_port != UDP_LOCAL_PORT_RANGE_END)) { + if (ipcb->local_port == udp_port) { + /* port is already used by another udp_pcb */ + udp_port++; + /* restart scanning all udp pcbs */ + ipcb = udp_pcbs; + } else { + /* go on with next udp pcb */ + ipcb = ipcb->next; + } + } + if (ipcb != NULL) { + return 0; + } + return udp_port; +#endif +} + +/** + * Process an incoming UDP datagram. + * + * Given an incoming UDP datagram (as a chain of pbufs) this function + * finds a corresponding UDP PCB and hands over the pbuf to the pcbs + * recv function. If no pcb is found or the datagram is incorrect, the + * pbuf is freed. + * + * @param p pbuf to be demultiplexed to a UDP PCB (p->payload pointing to the UDP header) + * @param inp network interface on which the datagram was received. + * + */ +void +udp_input(struct pbuf *p, struct netif *inp) +{ + struct udp_hdr *udphdr; + struct udp_pcb *pcb, *prev; + struct udp_pcb *uncon_pcb; + u16_t src, dest; + u8_t local_match; + u8_t broadcast; + u8_t for_us; + + PERF_START; + + UDP_STATS_INC(udp.recv); + + /* Check minimum length (UDP header) */ + if (p->len < UDP_HLEN) { + /* drop short packets */ + LWIP_DEBUGF(UDP_DEBUG, + ("udp_input: short UDP datagram (%"U16_F" bytes) discarded\n", p->tot_len)); + UDP_STATS_INC(udp.lenerr); + UDP_STATS_INC(udp.drop); + snmp_inc_udpinerrors(); + pbuf_free(p); + goto end; + } + + udphdr = (struct udp_hdr *)p->payload; + + /* is broadcast packet ? */ +#if LWIP_IPV6 + broadcast = !ip_current_is_v6() && ip_addr_isbroadcast(ip_current_dest_addr(), inp); +#else /* LWIP_IPV6 */ + broadcast = ip_addr_isbroadcast(ip_current_dest_addr(), inp); +#endif /* LWIP_IPV6 */ + + LWIP_DEBUGF(UDP_DEBUG, ("udp_input: received datagram of length %"U16_F"\n", p->tot_len)); + + /* convert src and dest ports to host byte order */ + src = ntohs(udphdr->src); + dest = ntohs(udphdr->dest); + + udp_debug_print(udphdr); + + /* print the UDP source and destination */ + LWIP_DEBUGF(UDP_DEBUG, ("udp (")); + ipX_addr_debug_print(ip_current_is_v6(), UDP_DEBUG, ipX_current_dest_addr()); + LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F") <-- (", ntohs(udphdr->dest))); + ipX_addr_debug_print(ip_current_is_v6(), UDP_DEBUG, ipX_current_src_addr()); + LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F")\n", ntohs(udphdr->src))); + +#if LWIP_DHCP + pcb = NULL; + /* when LWIP_DHCP is active, packets to DHCP_CLIENT_PORT may only be processed by + the dhcp module, no other UDP pcb may use the local UDP port DHCP_CLIENT_PORT */ + if (dest == DHCP_CLIENT_PORT) { + /* all packets for DHCP_CLIENT_PORT not coming from DHCP_SERVER_PORT are dropped! */ + if (src == DHCP_SERVER_PORT) { + if ((inp->dhcp != NULL) && (inp->dhcp->pcb != NULL)) { + /* accept the packet if + (- broadcast or directed to us) -> DHCP is link-layer-addressed, local ip is always ANY! + - inp->dhcp->pcb->remote == ANY or iphdr->src + (no need to check for IPv6 since the dhcp struct always uses IPv4) */ + if (ipX_addr_isany(0, &inp->dhcp->pcb->remote_ip) || + ip_addr_cmp(ipX_2_ip(&(inp->dhcp->pcb->remote_ip)), ip_current_src_addr())) { + pcb = inp->dhcp->pcb; + } + } + } + } else +#endif /* LWIP_DHCP */ + { + prev = NULL; + local_match = 0; + uncon_pcb = NULL; + /* Iterate through the UDP pcb list for a matching pcb. + * 'Perfect match' pcbs (connected to the remote port & ip address) are + * preferred. If no perfect match is found, the first unconnected pcb that + * matches the local port and ip address gets the datagram. */ + for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) { + local_match = 0; + /* print the PCB local and remote address */ + LWIP_DEBUGF(UDP_DEBUG, ("pcb (")); + ipX_addr_debug_print(PCB_ISIPV6(pcb), UDP_DEBUG, &pcb->local_ip); + LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F") <-- (", pcb->local_port)); + ipX_addr_debug_print(PCB_ISIPV6(pcb), UDP_DEBUG, &pcb->remote_ip); + LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F")\n", pcb->remote_port)); + + /* compare PCB local addr+port to UDP destination addr+port */ + if (pcb->local_port == dest) { + if ( +#if LWIP_IPV6 + ((PCB_ISIPV6(pcb) && (ip_current_is_v6()) && + (ip6_addr_isany(ipX_2_ip6(&pcb->local_ip)) || +#if LWIP_IPV6_MLD + ip6_addr_ismulticast(ip6_current_dest_addr()) || +#endif /* LWIP_IPV6_MLD */ + ip6_addr_cmp(ipX_2_ip6(&pcb->local_ip), ip6_current_dest_addr()))) || + (!PCB_ISIPV6(pcb) && + (ip_current_header() != NULL) && +#else /* LWIP_IPV6 */ + (( +#endif /* LWIP_IPV6 */ + ((!broadcast && ipX_addr_isany(0, &pcb->local_ip)) || + ip_addr_cmp(ipX_2_ip(&pcb->local_ip), ip_current_dest_addr()) || +#if LWIP_IGMP + ip_addr_ismulticast(ip_current_dest_addr()) || +#endif /* LWIP_IGMP */ +#if IP_SOF_BROADCAST_RECV + (broadcast && ip_get_option(pcb, SOF_BROADCAST) && + (ipX_addr_isany(0, &pcb->local_ip) || + ip_addr_netcmp(ipX_2_ip(&pcb->local_ip), ip_current_dest_addr(), &inp->netmask))))))) { +#else /* IP_SOF_BROADCAST_RECV */ + (broadcast && + (ipX_addr_isany(0, &pcb->local_ip) || + ip_addr_netcmp(ipX_2_ip(&pcb->local_ip), ip_current_dest_addr(), &inp->netmask))))))) { +#endif /* IP_SOF_BROADCAST_RECV */ + local_match = 1; + if ((uncon_pcb == NULL) && + ((pcb->flags & UDP_FLAGS_CONNECTED) == 0)) { + /* the first unconnected matching PCB */ + uncon_pcb = pcb; + } + } + } + /* compare PCB remote addr+port to UDP source addr+port */ + if ((local_match != 0) && + (pcb->remote_port == src) && IP_PCB_IPVER_INPUT_MATCH(pcb) && + (ipX_addr_isany(PCB_ISIPV6(pcb), &pcb->remote_ip) || + ipX_addr_cmp(PCB_ISIPV6(pcb), &pcb->remote_ip, ipX_current_src_addr()))) { + /* the first fully matching PCB */ + if (prev != NULL) { + /* move the pcb to the front of udp_pcbs so that is + found faster next time */ + prev->next = pcb->next; + pcb->next = udp_pcbs; + udp_pcbs = pcb; + } else { + UDP_STATS_INC(udp.cachehit); + } + break; + } +/* This part of code has been modified by ST's MCD Application Team */ +/* To use the UPnP responder for device discovery */ +#if LWIP_UPNP + if((local_match != 0) && (dest == 1900)) { + break; + } +#endif /* LWIP_UPNP */ + prev = pcb; + } + /* no fully matching pcb found? then look for an unconnected pcb */ + if (pcb == NULL) { + pcb = uncon_pcb; + } + } + + /* Check checksum if this is a match or if it was directed at us. */ + if (pcb != NULL) { + for_us = 1; + } else { +#if LWIP_IPV6 + if (ip_current_is_v6()) { + for_us = netif_get_ip6_addr_match(inp, ip6_current_dest_addr()) >= 0; + } else +#endif /* LWIP_IPV6 */ + { + for_us = ip_addr_cmp(&inp->ip_addr, ip_current_dest_addr()); + } + } + if (for_us) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: calculating checksum\n")); +#if CHECKSUM_CHECK_UDP +#if LWIP_UDPLITE + if (ip_current_header_proto() == IP_PROTO_UDPLITE) { + /* Do the UDP Lite checksum */ + u16_t chklen = ntohs(udphdr->len); + if (chklen < sizeof(struct udp_hdr)) { + if (chklen == 0) { + /* For UDP-Lite, checksum length of 0 means checksum + over the complete packet (See RFC 3828 chap. 3.1) */ + chklen = p->tot_len; + } else { + /* At least the UDP-Lite header must be covered by the + checksum! (Again, see RFC 3828 chap. 3.1) */ + goto chkerr; + } + } + if (ipX_chksum_pseudo_partial(ip_current_is_v6(), p, IP_PROTO_UDPLITE, + p->tot_len, chklen, + ipX_current_src_addr(), ipX_current_dest_addr()) != 0) { + goto chkerr; + } + } else +#endif /* LWIP_UDPLITE */ + { + if (udphdr->chksum != 0) { + if (ipX_chksum_pseudo(ip_current_is_v6(), p, IP_PROTO_UDP, p->tot_len, + ipX_current_src_addr(), + ipX_current_dest_addr()) != 0) { + goto chkerr; + } + } + } +#endif /* CHECKSUM_CHECK_UDP */ + if(pbuf_header(p, -UDP_HLEN)) { + /* Can we cope with this failing? Just assert for now */ + LWIP_ASSERT("pbuf_header failed\n", 0); + UDP_STATS_INC(udp.drop); + snmp_inc_udpinerrors(); + pbuf_free(p); + goto end; + } + if (pcb != NULL) { + snmp_inc_udpindatagrams(); +#if SO_REUSE && SO_REUSE_RXTOALL + if ((broadcast || +#if LWIP_IPV6 + ip6_addr_ismulticast(ip6_current_dest_addr()) || +#endif /* LWIP_IPV6 */ + ip_addr_ismulticast(ip_current_dest_addr())) && + ip_get_option(pcb, SOF_REUSEADDR)) { + /* pass broadcast- or multicast packets to all multicast pcbs + if SOF_REUSEADDR is set on the first match */ + struct udp_pcb *mpcb; + u8_t p_header_changed = 0; + s16_t hdrs_len = (s16_t)(ip_current_header_tot_len() + UDP_HLEN); + for (mpcb = udp_pcbs; mpcb != NULL; mpcb = mpcb->next) { + if (mpcb != pcb) { + /* compare PCB local addr+port to UDP destination addr+port */ + if ((mpcb->local_port == dest) && +#if LWIP_IPV6 + ((PCB_ISIPV6(mpcb) && + (ip6_addr_ismulticast(ip6_current_dest_addr()) || + ip6_addr_cmp(ipX_2_ip6(&mpcb->local_ip), ip6_current_dest_addr()))) || + (!PCB_ISIPV6(mpcb) && +#else /* LWIP_IPV6 */ + (( +#endif /* LWIP_IPV6 */ + ((!broadcast && ipX_addr_isany(0, &mpcb->local_ip)) || + ip_addr_cmp(ipX_2_ip(&mpcb->local_ip), ip_current_dest_addr()) || +#if LWIP_IGMP + ip_addr_ismulticast(ip_current_dest_addr()) || +#endif /* LWIP_IGMP */ +#if IP_SOF_BROADCAST_RECV + (broadcast && ip_get_option(mpcb, SOF_BROADCAST)))))) { +#else /* IP_SOF_BROADCAST_RECV */ + (broadcast))))) { +#endif /* IP_SOF_BROADCAST_RECV */ + /* pass a copy of the packet to all local matches */ + if (mpcb->recv.ip4 != NULL) { + struct pbuf *q; + /* for that, move payload to IP header again */ + if (p_header_changed == 0) { + pbuf_header_force(p, hdrs_len); + p_header_changed = 1; + } + q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); + if (q != NULL) { + err_t err = pbuf_copy(q, p); + if (err == ERR_OK) { + /* move payload to UDP data */ + pbuf_header(q, -hdrs_len); +#if LWIP_IPV6 + if (PCB_ISIPV6(mpcb)) { + mpcb->recv.ip6(mpcb->recv_arg, mpcb, q, ip6_current_src_addr(), src); + } + else +#endif /* LWIP_IPV6 */ + { + mpcb->recv.ip4(mpcb->recv_arg, mpcb, q, ip_current_src_addr(), src); + } + } + } + } + } + } + } + if (p_header_changed) { + /* and move payload to UDP data again */ + pbuf_header(p, -hdrs_len); + } + } +#endif /* SO_REUSE && SO_REUSE_RXTOALL */ + /* callback */ + if (pcb->recv.ip4 != NULL) { + /* now the recv function is responsible for freeing p */ +#if LWIP_IPV6 + if (PCB_ISIPV6(pcb)) { + pcb->recv.ip6(pcb->recv_arg, pcb, p, ip6_current_src_addr(), src); + } + else +#endif /* LWIP_IPV6 */ + { + pcb->recv.ip4(pcb->recv_arg, pcb, p, ip_current_src_addr(), src); + } + } else { + /* no recv function registered? then we have to free the pbuf! */ + pbuf_free(p); + goto end; + } + } else { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: not for us.\n")); + +#if LWIP_ICMP || LWIP_ICMP6 + /* No match was found, send ICMP destination port unreachable unless + destination address was broadcast/multicast. */ + if (!broadcast && +#if LWIP_IPV6 + !ip6_addr_ismulticast(ip6_current_dest_addr()) && +#endif /* LWIP_IPV6 */ + !ip_addr_ismulticast(ip_current_dest_addr())) { + /* move payload pointer back to ip header */ + pbuf_header_force(p, ip_current_header_tot_len() + UDP_HLEN); + icmp_port_unreach(ip_current_is_v6(), p); + } +#endif /* LWIP_ICMP || LWIP_ICMP6 */ + UDP_STATS_INC(udp.proterr); + UDP_STATS_INC(udp.drop); + snmp_inc_udpnoports(); + pbuf_free(p); + } + } else { + pbuf_free(p); + } +end: + PERF_STOP("udp_input"); + return; +#if CHECKSUM_CHECK_UDP +chkerr: + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("udp_input: UDP (or UDP Lite) datagram discarded due to failing checksum\n")); + UDP_STATS_INC(udp.chkerr); + UDP_STATS_INC(udp.drop); + snmp_inc_udpinerrors(); + pbuf_free(p); + PERF_STOP("udp_input"); +#endif /* CHECKSUM_CHECK_UDP */ +} + +/** + * Send data using UDP. + * + * @param pcb UDP PCB used to send the data. + * @param p chain of pbuf's to be sent. + * + * The datagram will be sent to the current remote_ip & remote_port + * stored in pcb. If the pcb is not bound to a port, it will + * automatically be bound to a random port. + * + * @return lwIP error code. + * - ERR_OK. Successful. No error occurred. + * - ERR_MEM. Out of memory. + * - ERR_RTE. Could not find route to destination address. + * - More errors could be returned by lower protocol layers. + * + * @see udp_disconnect() udp_sendto() + */ +err_t +udp_send(struct udp_pcb *pcb, struct pbuf *p) +{ + /* send to the packet using remote ip and port stored in the pcb */ + return udp_sendto(pcb, p, ipX_2_ip(&pcb->remote_ip), pcb->remote_port); +} + +#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP +/** Same as udp_send() but with checksum + */ +err_t +udp_send_chksum(struct udp_pcb *pcb, struct pbuf *p, + u8_t have_chksum, u16_t chksum) +{ + /* send to the packet using remote ip and port stored in the pcb */ + return udp_sendto_chksum(pcb, p, ipX_2_ip(&pcb->remote_ip), pcb->remote_port, + have_chksum, chksum); +} +#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ + +/** + * Send data to a specified address using UDP. + * + * @param pcb UDP PCB used to send the data. + * @param p chain of pbuf's to be sent. + * @param dst_ip Destination IP address. + * @param dst_port Destination UDP port. + * + * dst_ip & dst_port are expected to be in the same byte order as in the pcb. + * + * If the PCB already has a remote address association, it will + * be restored after the data is sent. + * + * @return lwIP error code (@see udp_send for possible error codes) + * + * @see udp_disconnect() udp_send() + */ +err_t +udp_sendto(struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *dst_ip, u16_t dst_port) +{ +#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP + return udp_sendto_chksum(pcb, p, dst_ip, dst_port, 0, 0); +} + +/** Same as udp_sendto(), but with checksum */ +err_t +udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip, + u16_t dst_port, u8_t have_chksum, u16_t chksum) +{ +#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ + struct netif *netif; + ipX_addr_t *dst_ip_route = ip_2_ipX(dst_ip); + + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send\n")); + +#if LWIP_IPV6 || LWIP_IGMP + if (ipX_addr_ismulticast(PCB_ISIPV6(pcb), dst_ip_route)) { + /* For multicast, find a netif based on source address. */ +#if LWIP_IPV6 + if (PCB_ISIPV6(pcb)) { + dst_ip_route = &pcb->local_ip; + } else +#endif /* LWIP_IPV6 */ + { +#if LWIP_IGMP + dst_ip_route = ip_2_ipX(&pcb->multicast_ip); +#endif /* LWIP_IGMP */ + } + } +#endif /* LWIP_IPV6 || LWIP_IGMP */ + + /* find the outgoing network interface for this packet */ + netif = ipX_route(PCB_ISIPV6(pcb), &pcb->local_ip, dst_ip_route); + + /* no outgoing network interface could be found? */ + if (netif == NULL) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: No route to ")); + ipX_addr_debug_print(PCB_ISIPV6(pcb), UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ip_2_ipX(dst_ip)); + LWIP_DEBUGF(UDP_DEBUG, ("\n")); + UDP_STATS_INC(udp.rterr); + return ERR_RTE; + } +#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP + return udp_sendto_if_chksum(pcb, p, dst_ip, dst_port, netif, have_chksum, chksum); +#else /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ + return udp_sendto_if(pcb, p, dst_ip, dst_port, netif); +#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ +} + +/** + * Send data to a specified address using UDP. + * The netif used for sending can be specified. + * + * This function exists mainly for DHCP, to be able to send UDP packets + * on a netif that is still down. + * + * @param pcb UDP PCB used to send the data. + * @param p chain of pbuf's to be sent. + * @param dst_ip Destination IP address. + * @param dst_port Destination UDP port. + * @param netif the netif used for sending. + * + * dst_ip & dst_port are expected to be in the same byte order as in the pcb. + * + * @return lwIP error code (@see udp_send for possible error codes) + * + * @see udp_disconnect() udp_send() + */ +err_t +udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif) +{ +#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP + return udp_sendto_if_chksum(pcb, p, dst_ip, dst_port, netif, 0, 0); +} + +/** Same as udp_sendto_if(), but with checksum */ +err_t +udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip, + u16_t dst_port, struct netif *netif, u8_t have_chksum, + u16_t chksum) +{ +#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ + ip_addr_t *src_ip; + + /* PCB local address is IP_ANY_ADDR? */ +#if LWIP_IPV6 + if (PCB_ISIPV6(pcb)) { + if (ip6_addr_isany(ipX_2_ip6(&pcb->local_ip))) { + src_ip = ip6_2_ip(ip6_select_source_address(netif, ip_2_ip6(dst_ip))); + if (src_ip == NULL) { + /* No suitable source address was found. */ + return ERR_RTE; + } + } else { + /* use UDP PCB local IPv6 address as source address, if still valid. */ + if (netif_get_ip6_addr_match(netif, ipX_2_ip6(&pcb->local_ip)) < 0) { + /* Address isn't valid anymore. */ + return ERR_RTE; + } + src_ip = ipX_2_ip(&pcb->local_ip); + } + } + else +#endif /* LWIP_IPV6 */ + if (ip_addr_isany(ipX_2_ip(&pcb->local_ip))) { + /* use outgoing network interface IP address as source address */ + src_ip = &(netif->ip_addr); + } else { + /* check if UDP PCB local IP address is correct + * this could be an old address if netif->ip_addr has changed */ + if (!ip_addr_cmp(ipX_2_ip(&(pcb->local_ip)), &(netif->ip_addr))) { + /* local_ip doesn't match, drop the packet */ + return ERR_VAL; + } + /* use UDP PCB local IP address as source address */ + src_ip = ipX_2_ip(&(pcb->local_ip)); + } +#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP + return udp_sendto_if_src_chksum(pcb, p, dst_ip, dst_port, netif, have_chksum, chksum, src_ip); +#else /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ + return udp_sendto_if_src(pcb, p, dst_ip, dst_port, netif, src_ip); +#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ +} + +/** Same as udp_sendto_if(), but with source address */ +err_t +udp_sendto_if_src(struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif, ip_addr_t *src_ip) +{ +#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP + return udp_sendto_if_src_chksum(pcb, p, dst_ip, dst_port, netif, 0, 0, src_ip); +} + +/** Same as udp_sendto_if_src(), but with checksum */ +err_t +udp_sendto_if_src_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip, + u16_t dst_port, struct netif *netif, u8_t have_chksum, + u16_t chksum, ip_addr_t *src_ip) +{ +#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ + struct udp_hdr *udphdr; + err_t err; + struct pbuf *q; /* q will be sent down the stack */ + u8_t ip_proto; + +#if IP_SOF_BROADCAST + /* broadcast filter? */ + if (!ip_get_option(pcb, SOF_BROADCAST) && +#if LWIP_IPV6 + !PCB_ISIPV6(pcb) && +#endif /* LWIP_IPV6 */ + ip_addr_isbroadcast(dst_ip, netif) ) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, + ("udp_sendto_if: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb)); + return ERR_VAL; + } +#endif /* IP_SOF_BROADCAST */ + + /* if the PCB is not yet bound to a port, bind it here */ + if (pcb->local_port == 0) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send: not yet bound to a port, binding now\n")); + err = udp_bind(pcb, ipX_2_ip(&pcb->local_ip), pcb->local_port); + if (err != ERR_OK) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: forced port bind failed\n")); + return err; + } + } + + /* not enough space to add an UDP header to first pbuf in given p chain? */ + if (pbuf_header(p, UDP_HLEN)) { + /* allocate header in a separate new pbuf */ + q = pbuf_alloc(PBUF_IP, UDP_HLEN, PBUF_RAM); + /* new header pbuf could not be allocated? */ + if (q == NULL) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: could not allocate header\n")); + return ERR_MEM; + } + if (p->tot_len != 0) { + /* chain header q in front of given pbuf p (only if p contains data) */ + pbuf_chain(q, p); + } + /* first pbuf q points to header pbuf */ + LWIP_DEBUGF(UDP_DEBUG, + ("udp_send: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p)); + } else { + /* adding space for header within p succeeded */ + /* first pbuf q equals given pbuf */ + q = p; + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: added header in given pbuf %p\n", (void *)p)); + } + LWIP_ASSERT("check that first pbuf can hold struct udp_hdr", + (q->len >= sizeof(struct udp_hdr))); + /* q now represents the packet to be sent */ + udphdr = (struct udp_hdr *)q->payload; + udphdr->src = htons(pcb->local_port); + udphdr->dest = htons(dst_port); + /* in UDP, 0 checksum means 'no checksum' */ + udphdr->chksum = 0x0000; + + /* Multicast Loop? */ +#if LWIP_IGMP + if (((pcb->flags & UDP_FLAGS_MULTICAST_LOOP) != 0) && +#if LWIP_IPV6 + ( +#if LWIP_IPV6_MLD + (PCB_ISIPV6(pcb) && + ip6_addr_ismulticast(ip_2_ip6(dst_ip))) || +#endif /* LWIP_IPV6_MLD */ + (!PCB_ISIPV6(pcb) && +#else /* LWIP_IPV6 */ + (( +#endif /* LWIP_IPV6 */ + ip_addr_ismulticast(dst_ip)))) { + q->flags |= PBUF_FLAG_MCASTLOOP; + } +#endif /* LWIP_IGMP */ + + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: sending datagram of length %"U16_F"\n", q->tot_len)); + +#if LWIP_UDPLITE + /* UDP Lite protocol? */ + if (pcb->flags & UDP_FLAGS_UDPLITE) { + u16_t chklen, chklen_hdr; + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE packet length %"U16_F"\n", q->tot_len)); + /* set UDP message length in UDP header */ + chklen_hdr = chklen = pcb->chksum_len_tx; + if ((chklen < sizeof(struct udp_hdr)) || (chklen > q->tot_len)) { + if (chklen != 0) { + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE pcb->chksum_len is illegal: %"U16_F"\n", chklen)); + } + /* For UDP-Lite, checksum length of 0 means checksum + over the complete packet. (See RFC 3828 chap. 3.1) + At least the UDP-Lite header must be covered by the + checksum, therefore, if chksum_len has an illegal + value, we generate the checksum over the complete + packet to be safe. */ + chklen_hdr = 0; + chklen = q->tot_len; + } + udphdr->len = htons(chklen_hdr); + /* calculate checksum */ +#if CHECKSUM_GEN_UDP +#if LWIP_CHECKSUM_ON_COPY + if (have_chksum) { + chklen = UDP_HLEN; + } +#endif /* LWIP_CHECKSUM_ON_COPY */ + udphdr->chksum = ipX_chksum_pseudo_partial(PCB_ISIPV6(pcb), q, IP_PROTO_UDPLITE, + q->tot_len, chklen, ip_2_ipX(src_ip), ip_2_ipX(dst_ip)); +#if LWIP_CHECKSUM_ON_COPY + if (have_chksum) { + u32_t acc; + acc = udphdr->chksum + (u16_t)~(chksum); + udphdr->chksum = FOLD_U32T(acc); + } +#endif /* LWIP_CHECKSUM_ON_COPY */ + + /* chksum zero must become 0xffff, as zero means 'no checksum' */ + if (udphdr->chksum == 0x0000) { + udphdr->chksum = 0xffff; + } +#endif /* CHECKSUM_GEN_UDP */ + + ip_proto = IP_PROTO_UDPLITE; + } else +#endif /* LWIP_UDPLITE */ + { /* UDP */ + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %"U16_F"\n", q->tot_len)); + udphdr->len = htons(q->tot_len); + /* calculate checksum */ +#if CHECKSUM_GEN_UDP + /* Checksum is mandatory over IPv6. */ + if (PCB_ISIPV6(pcb) || (pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) { + u16_t udpchksum; +#if LWIP_CHECKSUM_ON_COPY + if (have_chksum) { + u32_t acc; + udpchksum = ipX_chksum_pseudo_partial(PCB_ISIPV6(pcb), q, IP_PROTO_UDP, + q->tot_len, UDP_HLEN, ip_2_ipX(src_ip), ip_2_ipX(dst_ip)); + acc = udpchksum + (u16_t)~(chksum); + udpchksum = FOLD_U32T(acc); + } else +#endif /* LWIP_CHECKSUM_ON_COPY */ + { + udpchksum = ipX_chksum_pseudo(PCB_ISIPV6(pcb), q, IP_PROTO_UDP, q->tot_len, + ip_2_ipX(src_ip), ip_2_ipX(dst_ip)); + } + + /* chksum zero must become 0xffff, as zero means 'no checksum' */ + if (udpchksum == 0x0000) { + udpchksum = 0xffff; + } + udphdr->chksum = udpchksum; + } +#endif /* CHECKSUM_GEN_UDP */ + ip_proto = IP_PROTO_UDP; + } + + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum 0x%04"X16_F"\n", udphdr->chksum)); + LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,0x%02"X16_F",)\n", (u16_t)ip_proto)); + /* output to IP */ + NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint)); + err = ipX_output_if_src(PCB_ISIPV6(pcb), q, src_ip, dst_ip, pcb->ttl, pcb->tos, ip_proto, netif); + NETIF_SET_HWADDRHINT(netif, NULL); + + /* TODO: must this be increased even if error occurred? */ + snmp_inc_udpoutdatagrams(); + + /* did we chain a separate header pbuf earlier? */ + if (q != p) { + /* free the header pbuf */ + pbuf_free(q); + q = NULL; + /* p is still referenced by the caller, and will live on */ + } + + UDP_STATS_INC(udp.xmit); + return err; +} + +/** + * Bind an UDP PCB. + * + * @param pcb UDP PCB to be bound with a local address ipaddr and port. + * @param ipaddr local IP address to bind with. Use IP_ADDR_ANY to + * bind to all local interfaces. + * @param port local UDP port to bind with. Use 0 to automatically bind + * to a random port between UDP_LOCAL_PORT_RANGE_START and + * UDP_LOCAL_PORT_RANGE_END. + * + * ipaddr & port are expected to be in the same byte order as in the pcb. + * + * @return lwIP error code. + * - ERR_OK. Successful. No error occurred. + * - ERR_USE. The specified ipaddr and port are already bound to by + * another UDP PCB. + * + * @see udp_disconnect() + */ +err_t +udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port) +{ + struct udp_pcb *ipcb; + u8_t rebind; + + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_bind(ipaddr = ")); + ipX_addr_debug_print(PCB_ISIPV6(pcb), UDP_DEBUG | LWIP_DBG_TRACE, ip_2_ipX(ipaddr)); + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, (", port = %"U16_F")\n", port)); + + rebind = 0; + /* Check for double bind and rebind of the same pcb */ + for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) { + /* is this UDP PCB already on active list? */ + if (pcb == ipcb) { + /* pcb may occur at most once in active list */ + LWIP_ASSERT("rebind == 0", rebind == 0); + /* pcb already in list, just rebind */ + rebind = 1; + } + + /* By default, we don't allow to bind to a port that any other udp + PCB is already bound to, unless *all* PCBs with that port have tha + REUSEADDR flag set. */ +#if SO_REUSE + else if (!ip_get_option(pcb, SOF_REUSEADDR) && + !ip_get_option(ipcb, SOF_REUSEADDR)) { +#else /* SO_REUSE */ + /* port matches that of PCB in list and REUSEADDR not set -> reject */ + else { +#endif /* SO_REUSE */ + if ((ipcb->local_port == port) && IP_PCB_IPVER_EQ(pcb, ipcb) && + /* IP address matches, or one is IP_ADDR_ANY? */ + (ipX_addr_isany(PCB_ISIPV6(ipcb), &(ipcb->local_ip)) || + ipX_addr_isany(PCB_ISIPV6(ipcb), ip_2_ipX(ipaddr)) || + ipX_addr_cmp(PCB_ISIPV6(ipcb), &(ipcb->local_ip), ip_2_ipX(ipaddr)))) { + /* other PCB already binds to this local IP and port */ + LWIP_DEBUGF(UDP_DEBUG, + ("udp_bind: local port %"U16_F" already bound by another pcb\n", port)); + return ERR_USE; + } + } + } + + ipX_addr_set_ipaddr(PCB_ISIPV6(pcb), &pcb->local_ip, ipaddr); + + /* no port specified? */ + if (port == 0) { + port = udp_new_port(); + if (port == 0) { + /* no more ports available in local range */ + LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: out of free UDP ports\n")); + return ERR_USE; + } + } + pcb->local_port = port; + snmp_insert_udpidx_tree(pcb); + /* pcb not active yet? */ + if (rebind == 0) { + /* place the PCB on the active list if not already there */ + pcb->next = udp_pcbs; + udp_pcbs = pcb; + } + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("udp_bind: bound to ")); + ipX_addr_debug_print(PCB_ISIPV6(pcb), UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, &pcb->local_ip); + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, (", port %"U16_F")\n", pcb->local_port)); + return ERR_OK; +} + +/** + * Connect an UDP PCB. + * + * This will associate the UDP PCB with the remote address. + * + * @param pcb UDP PCB to be connected with remote address ipaddr and port. + * @param ipaddr remote IP address to connect with. + * @param port remote UDP port to connect with. + * + * @return lwIP error code + * + * ipaddr & port are expected to be in the same byte order as in the pcb. + * + * The udp pcb is bound to a random local port if not already bound. + * + * @see udp_disconnect() + */ +err_t +udp_connect(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port) +{ + struct udp_pcb *ipcb; + + if (pcb->local_port == 0) { + err_t err = udp_bind(pcb, ipX_2_ip(&pcb->local_ip), pcb->local_port); + if (err != ERR_OK) { + return err; + } + } + + ipX_addr_set_ipaddr(PCB_ISIPV6(pcb), &pcb->remote_ip, ipaddr); + pcb->remote_port = port; + pcb->flags |= UDP_FLAGS_CONNECTED; +/** TODO: this functionality belongs in upper layers */ +#ifdef LWIP_UDP_TODO +#if LWIP_IPV6 + if (!PCB_ISIPV6(pcb)) +#endif /* LWIP_IPV6 */ + { + /* Nail down local IP for netconn_addr()/getsockname() */ + if (ip_addr_isany(ipX_2_ip(&pcb->local_ip)) && !ip_addr_isany(ipX_2_ip(&pcb->remote_ip))) { + struct netif *netif; + + if ((netif = ip_route(ipX_2_ip(&pcb->remote_ip))) == NULL) { + LWIP_DEBUGF(UDP_DEBUG, ("udp_connect: No route to 0x%lx\n", + ip4_addr_get_u32(ipX_2_ip(&pcb->remote_ip)))); + UDP_STATS_INC(udp.rterr); + return ERR_RTE; + } + /** TODO: this will bind the udp pcb locally, to the interface which + is used to route output packets to the remote address. However, we + might want to accept incoming packets on any interface! */ + ipX_addr_copy(0, pcb->local_ip, netif->ip_addr); + } else if (ip_addr_isany(ipX_2_ip(&pcb->remote_ip))) { + ipX_addr_set_any(0, &pcb->local_ip); + } + } +#endif + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("udp_connect: connected to ")); + ipX_addr_debug_print(PCB_ISIPV6(pcb), UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, + &pcb->remote_ip); + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, (", port %"U16_F")\n", pcb->remote_port)); + + /* Insert UDP PCB into the list of active UDP PCBs. */ + for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) { + if (pcb == ipcb) { + /* already on the list, just return */ + return ERR_OK; + } + } + /* PCB not yet on the list, add PCB now */ + pcb->next = udp_pcbs; + udp_pcbs = pcb; + return ERR_OK; +} + +/** + * Disconnect a UDP PCB + * + * @param pcb the udp pcb to disconnect. + */ +void +udp_disconnect(struct udp_pcb *pcb) +{ + /* reset remote address association */ + ipX_addr_set_any(PCB_ISIPV6(pcb), &pcb->remote_ip); + pcb->remote_port = 0; + /* mark PCB as unconnected */ + pcb->flags &= ~UDP_FLAGS_CONNECTED; +} + +/** + * Set a receive callback for a UDP PCB + * + * This callback will be called when receiving a datagram for the pcb. + * + * @param pcb the pcb for which to set the recv callback + * @param recv function pointer of the callback function + * @param recv_arg additional argument to pass to the callback function + */ +void +udp_recv(struct udp_pcb *pcb, udp_recv_fn recv, void *recv_arg) +{ + /* remember recv() callback and user data */ + pcb->recv.ip4 = recv; + pcb->recv_arg = recv_arg; +} + +/** + * Remove an UDP PCB. + * + * @param pcb UDP PCB to be removed. The PCB is removed from the list of + * UDP PCB's and the data structure is freed from memory. + * + * @see udp_new() + */ +void +udp_remove(struct udp_pcb *pcb) +{ + struct udp_pcb *pcb2; + + snmp_delete_udpidx_tree(pcb); + /* pcb to be removed is first in list? */ + if (udp_pcbs == pcb) { + /* make list start at 2nd pcb */ + udp_pcbs = udp_pcbs->next; + /* pcb not 1st in list */ + } else { + for (pcb2 = udp_pcbs; pcb2 != NULL; pcb2 = pcb2->next) { + /* find pcb in udp_pcbs list */ + if (pcb2->next != NULL && pcb2->next == pcb) { + /* remove pcb from list */ + pcb2->next = pcb->next; + } + } + } + memp_free(MEMP_UDP_PCB, pcb); +} + +/** + * Create a UDP PCB. + * + * @return The UDP PCB which was created. NULL if the PCB data structure + * could not be allocated. + * + * @see udp_remove() + */ +struct udp_pcb * +udp_new(void) +{ + struct udp_pcb *pcb; + pcb = (struct udp_pcb *)memp_malloc(MEMP_UDP_PCB); + /* could allocate UDP PCB? */ + if (pcb != NULL) { + /* UDP Lite: by initializing to all zeroes, chksum_len is set to 0 + * which means checksum is generated over the whole datagram per default + * (recommended as default by RFC 3828). */ + /* initialize PCB to all zeroes */ + memset(pcb, 0, sizeof(struct udp_pcb)); + pcb->ttl = UDP_TTL; + } + return pcb; +} + +#if LWIP_IPV6 +/** + * Create a UDP PCB for IPv6. + * + * @return The UDP PCB which was created. NULL if the PCB data structure + * could not be allocated. + * + * @see udp_remove() + */ +struct udp_pcb * +udp_new_ip6(void) +{ + struct udp_pcb *pcb; + pcb = udp_new(); + ip_set_v6(pcb, 1); + return pcb; +} +#endif /* LWIP_IPV6 */ + +#if UDP_DEBUG +/** + * Print UDP header information for debug purposes. + * + * @param udphdr pointer to the udp header in memory. + */ +void +udp_debug_print(struct udp_hdr *udphdr) +{ + LWIP_DEBUGF(UDP_DEBUG, ("UDP header:\n")); + LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n", + ntohs(udphdr->src), ntohs(udphdr->dest))); + LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); + LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | 0x%04"X16_F" | (len, chksum)\n", + ntohs(udphdr->len), ntohs(udphdr->chksum))); + LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); +} +#endif /* UDP_DEBUG */ + +#endif /* LWIP_UDP */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/api.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/api.h new file mode 100644 index 0000000..fa9cfa5 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/api.h @@ -0,0 +1,364 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_API_H +#define LWIP_HDR_API_H + +#include "lwip/opt.h" + +#if LWIP_NETCONN || LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ + +/* don't export the netconn functions when socket API is enabled but netconn API is disabled */ +#if LWIP_NETCONN +#define LWIP_NETCONN_SCOPE +#else /* LWIP_NETCONN */ +#define LWIP_NETCONN_SCOPE static +#endif /* LWIP_NETCONN */ + +#include /* for size_t */ + +#include "lwip/netbuf.h" +#include "lwip/sys.h" +#include "lwip/ip_addr.h" +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Evan add for port netconn api +#define port_netconn_recv(conn , buf, ret) do{ret = netconn_recv(conn, &buf);}while(0); +#define port_netconn_accept(conn , newconn, ret) do{ret = netconn_accept(conn, &newconn);}while(0); +// Evan add end + +/* Throughout this file, IP addresses and port numbers are expected to be in + * the same byte order as in the corresponding pcb. + */ + +/* Flags for netconn_write (u8_t) */ +#define NETCONN_NOFLAG 0x00 +#define NETCONN_NOCOPY 0x00 /* Only for source code compatibility */ +#define NETCONN_COPY 0x01 +#define NETCONN_MORE 0x02 +#define NETCONN_DONTBLOCK 0x04 + +/* Flags for struct netconn.flags (u8_t) */ +/** TCP: when data passed to netconn_write doesn't fit into the send buffer, + this temporarily stores whether to wake up the original application task + if data couldn't be sent in the first try. */ +#define NETCONN_FLAG_WRITE_DELAYED 0x01 +/** Should this netconn avoid blocking? */ +#define NETCONN_FLAG_NON_BLOCKING 0x02 +/** Was the last connect action a non-blocking one? */ +#define NETCONN_FLAG_IN_NONBLOCKING_CONNECT 0x04 +/** If this is set, a TCP netconn must call netconn_recved() to update + the TCP receive window (done automatically if not set). */ +#define NETCONN_FLAG_NO_AUTO_RECVED 0x08 +/** If a nonblocking write has been rejected before, poll_tcp needs to + check if the netconn is writable again */ +#define NETCONN_FLAG_CHECK_WRITESPACE 0x10 +#if LWIP_IPV6 +/** If this flag is set then only IPv6 communication is allowed on the + netconn. As per RFC#3493 this features defaults to OFF allowing + dual-stack usage by default. */ +#define NETCONN_FLAG_IPV6_V6ONLY 0x20 +#endif /* LWIP_IPV6 */ + + +/* Helpers to process several netconn_types by the same code */ +#define NETCONNTYPE_GROUP(t) ((t)&0xF0) +#define NETCONNTYPE_DATAGRAM(t) ((t)&0xE0) +#if LWIP_IPV6 +#define NETCONN_TYPE_IPV6 0x08 +#define NETCONNTYPE_ISIPV6(t) ((t)&0x08) +#define NETCONNTYPE_ISUDPLITE(t) (((t)&0xF7) == NETCONN_UDPLITE) +#define NETCONNTYPE_ISUDPNOCHKSUM(t) (((t)&0xF7) == NETCONN_UDPNOCHKSUM) +#else /* LWIP_IPV6 */ +#define NETCONNTYPE_ISUDPLITE(t) ((t) == NETCONN_UDPLITE) +#define NETCONNTYPE_ISUDPNOCHKSUM(t) ((t) == NETCONN_UDPNOCHKSUM) +#endif /* LWIP_IPV6 */ + +/** Protocol family and type of the netconn */ +enum netconn_type { + NETCONN_INVALID = 0, + /* NETCONN_TCP Group */ + NETCONN_TCP = 0x10, +#if LWIP_IPV6 + NETCONN_TCP_IPV6 = NETCONN_TCP | NETCONN_TYPE_IPV6 /* 0x18 */, +#endif /* LWIP_IPV6 */ + /* NETCONN_UDP Group */ + NETCONN_UDP = 0x20, + NETCONN_UDPLITE = 0x21, + NETCONN_UDPNOCHKSUM = 0x22, +#if LWIP_IPV6 + NETCONN_UDP_IPV6 = NETCONN_UDP | NETCONN_TYPE_IPV6 /* 0x28 */, + NETCONN_UDPLITE_IPV6 = NETCONN_UDPLITE | NETCONN_TYPE_IPV6 /* 0x29 */, + NETCONN_UDPNOCHKSUM_IPV6 = NETCONN_UDPNOCHKSUM | NETCONN_TYPE_IPV6 /* 0x2a */, +#endif /* LWIP_IPV6 */ + /* NETCONN_RAW Group */ + NETCONN_RAW = 0x40 +#if LWIP_IPV6 + , + NETCONN_RAW_IPV6 = NETCONN_RAW | NETCONN_TYPE_IPV6 /* 0x48 */ +#endif /* LWIP_IPV6 */ +}; + +/** Current state of the netconn. Non-TCP netconns are always + * in state NETCONN_NONE! */ +enum netconn_state { + NETCONN_NONE, + NETCONN_WRITE, + NETCONN_LISTEN, + NETCONN_CONNECT, + NETCONN_CLOSE +}; + +/** Use to inform the callback function about changes */ +enum netconn_evt { + NETCONN_EVT_RCVPLUS, + NETCONN_EVT_RCVMINUS, + NETCONN_EVT_SENDPLUS, + NETCONN_EVT_SENDMINUS, + NETCONN_EVT_ERROR +}; + +#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) +/** Used for netconn_join_leave_group() */ +enum netconn_igmp { + NETCONN_JOIN, + NETCONN_LEAVE +}; +#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ + +/* forward-declare some structs to avoid to include their headers */ +struct ip_pcb; +struct tcp_pcb; +struct udp_pcb; +struct raw_pcb; +struct netconn; +struct api_msg_msg; + +/** A callback prototype to inform about events for a netconn */ +typedef void (* netconn_callback)(struct netconn *, enum netconn_evt, u16_t len); + +/** A netconn descriptor */ +struct netconn { + /** type of the netconn (TCP, UDP or RAW) */ + enum netconn_type type; + /** current state of the netconn */ + enum netconn_state state; + /** the lwIP internal protocol control block */ + union { + struct ip_pcb *ip; + struct tcp_pcb *tcp; + struct udp_pcb *udp; + struct raw_pcb *raw; + } pcb; + /** the last error this netconn had */ + err_t last_err; +#if !LWIP_NETCONN_SEM_PER_THREAD + /** sem that is used to synchronously execute functions in the core context */ + sys_sem_t op_completed; +#endif + /** mbox where received packets are stored until they are fetched + by the netconn application thread (can grow quite big) */ + sys_mbox_t recvmbox; +#if LWIP_TCP + /** mbox where new connections are stored until processed + by the application thread */ + sys_mbox_t acceptmbox; +#endif /* LWIP_TCP */ + /** only used for socket layer */ +#if LWIP_SOCKET + int socket; +#endif /* LWIP_SOCKET */ +#if LWIP_SO_SNDTIMEO + /** timeout to wait for sending data (which means enqueueing data for sending + in internal buffers) in milliseconds */ + s32_t send_timeout; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVTIMEO + /** timeout in milliseconds to wait for new data to be received + (or connections to arrive for listening netconns) */ + int recv_timeout; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + /** maximum amount of bytes queued in recvmbox + not used for TCP: adjust TCP_WND instead! */ + int recv_bufsize; + /** number of bytes currently in recvmbox to be received, + tested against recv_bufsize to limit bytes on recvmbox + for UDP and RAW, used for FIONREAD */ + int recv_avail; +#endif /* LWIP_SO_RCVBUF */ + /** flags holding more netconn-internal state, see NETCONN_FLAG_* defines */ + u8_t flags; +#if LWIP_TCP + /** TCP: when data passed to netconn_write doesn't fit into the send buffer, + this temporarily stores how much is already sent. */ + size_t write_offset; + /** TCP: when data passed to netconn_write doesn't fit into the send buffer, + this temporarily stores the message. + Also used during connect and close. */ + struct api_msg_msg *current_msg; +#endif /* LWIP_TCP */ + /** A callback function that is informed about events for this netconn */ + netconn_callback callback; +}; + +/** Register an Network connection event */ +#define API_EVENT(c,e,l) if (c->callback) { \ + (*c->callback)(c, e, l); \ + } + +/** Set conn->last_err to err but don't overwrite fatal errors */ +#define NETCONN_SET_SAFE_ERR(conn, err) do { \ + SYS_ARCH_DECL_PROTECT(lev); \ + SYS_ARCH_PROTECT(lev); \ + if (!ERR_IS_FATAL((conn)->last_err)) { \ + (conn)->last_err = err; \ + } \ + SYS_ARCH_UNPROTECT(lev); \ +} while(0); + +// Realtek add +err_t netconn_abort(struct netconn *conn); +// Realtek add end + +/* Network connection functions: */ +#define netconn_new(t) netconn_new_with_proto_and_callback(t, 0, NULL) +#define netconn_new_with_callback(t, c) netconn_new_with_proto_and_callback(t, 0, c) +LWIP_NETCONN_SCOPE struct +netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, + netconn_callback callback); +LWIP_NETCONN_SCOPE err_t netconn_delete(struct netconn *conn); +/** Get the type of a netconn (as enum netconn_type). */ +#define netconn_type(conn) (conn->type) + +LWIP_NETCONN_SCOPE err_t netconn_getaddr(struct netconn *conn, ip_addr_t *addr, + u16_t *port, u8_t local); +#define netconn_peer(c,i,p) netconn_getaddr(c,i,p,0) +#define netconn_addr(c,i,p) netconn_getaddr(c,i,p,1) + +LWIP_NETCONN_SCOPE err_t netconn_bind(struct netconn *conn, ip_addr_t *addr, u16_t port); +LWIP_NETCONN_SCOPE err_t netconn_connect(struct netconn *conn, ip_addr_t *addr, u16_t port); +LWIP_NETCONN_SCOPE err_t netconn_disconnect (struct netconn *conn); +LWIP_NETCONN_SCOPE err_t netconn_listen_with_backlog(struct netconn *conn, u8_t backlog); +#define netconn_listen(conn) netconn_listen_with_backlog(conn, TCP_DEFAULT_LISTEN_BACKLOG) +LWIP_NETCONN_SCOPE err_t netconn_accept(struct netconn *conn, struct netconn **new_conn); +LWIP_NETCONN_SCOPE err_t netconn_recv(struct netconn *conn, struct netbuf **new_buf); +LWIP_NETCONN_SCOPE err_t netconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf); +LWIP_NETCONN_SCOPE void netconn_recved(struct netconn *conn, u32_t length); +LWIP_NETCONN_SCOPE err_t netconn_sendto(struct netconn *conn, struct netbuf *buf, + ip_addr_t *addr, u16_t port); +LWIP_NETCONN_SCOPE err_t netconn_send(struct netconn *conn, struct netbuf *buf); +LWIP_NETCONN_SCOPE err_t netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size, + u8_t apiflags, size_t *bytes_written); +#define netconn_write(conn, dataptr, size, apiflags) \ + netconn_write_partly(conn, dataptr, size, apiflags, NULL) +LWIP_NETCONN_SCOPE err_t netconn_close(struct netconn *conn); +LWIP_NETCONN_SCOPE err_t netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx); + +#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) +LWIP_NETCONN_SCOPE err_t netconn_join_leave_group(struct netconn *conn, ip_addr_t *multiaddr, + ip_addr_t *netif_addr, enum netconn_igmp join_or_leave); +#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ +#if LWIP_DNS +err_t netconn_gethostbyname(const char *name, ip_addr_t *addr); +#endif /* LWIP_DNS */ +#if LWIP_IPV6 + +#define netconn_bind_ip6(conn, ip6addr, port) (NETCONNTYPE_ISIPV6((conn)->type) ? \ + netconn_bind(conn, ip6_2_ip(ip6addr), port) : ERR_VAL) +#define netconn_connect_ip6(conn, ip6addr, port) (NETCONNTYPE_ISIPV6((conn)->type) ? \ + netconn_connect(conn, ip6_2_ip(ip6addr), port) : ERR_VAL) +#define netconn_sendto_ip6(conn, buf, ip6addr, port) (NETCONNTYPE_ISIPV6((conn)->type) ? \ + netconn_sendto(conn, buf, ip6_2_ip(ip6addr), port) : ERR_VAL) +#if LWIP_IPV6_MLD +#define netconn_join_leave_group_ip6(conn, multiaddr, srcaddr, join_or_leave) (NETCONNTYPE_ISIPV6((conn)->type) ? \ + netconn_join_leave_group(conn, ip6_2_ip(multiaddr), ip6_2_ip(srcaddr), join_or_leave) :\ + ERR_VAL) +#endif /* LWIP_IPV6_MLD*/ +#endif /* LWIP_IPV6 */ + +#define netconn_err(conn) ((conn)->last_err) +#define netconn_recv_bufsize(conn) ((conn)->recv_bufsize) + +/** Set the blocking status of netconn calls (@todo: write/send is missing) */ +#define netconn_set_nonblocking(conn, val) do { if(val) { \ + (conn)->flags |= NETCONN_FLAG_NON_BLOCKING; \ +} else { \ + (conn)->flags &= ~ NETCONN_FLAG_NON_BLOCKING; }} while(0) +/** Get the blocking status of netconn calls (@todo: write/send is missing) */ +#define netconn_is_nonblocking(conn) (((conn)->flags & NETCONN_FLAG_NON_BLOCKING) != 0) + +/** TCP: Set the no-auto-recved status of netconn calls (see NETCONN_FLAG_NO_AUTO_RECVED) */ +#define netconn_set_noautorecved(conn, val) do { if(val) { \ + (conn)->flags |= NETCONN_FLAG_NO_AUTO_RECVED; \ +} else { \ + (conn)->flags &= ~ NETCONN_FLAG_NO_AUTO_RECVED; }} while(0) +/** TCP: Get the no-auto-recved status of netconn calls (see NETCONN_FLAG_NO_AUTO_RECVED) */ +#define netconn_get_noautorecved(conn) (((conn)->flags & NETCONN_FLAG_NO_AUTO_RECVED) != 0) + +#if LWIP_SO_SNDTIMEO +/** Set the send timeout in milliseconds */ +#define netconn_set_sendtimeout(conn, timeout) ((conn)->send_timeout = (timeout)) +/** Get the send timeout in milliseconds */ +#define netconn_get_sendtimeout(conn) ((conn)->send_timeout) +#endif /* LWIP_SO_SNDTIMEO */ +#if LWIP_SO_RCVTIMEO +/** Set the receive timeout in milliseconds */ +#define netconn_set_recvtimeout(conn, timeout) ((conn)->recv_timeout = (timeout)) +/** Get the receive timeout in milliseconds */ +#define netconn_get_recvtimeout(conn) ((conn)->recv_timeout) +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF +/** Set the receive buffer in bytes */ +#define netconn_set_recvbufsize(conn, recvbufsize) ((conn)->recv_bufsize = (recvbufsize)) +/** Get the receive buffer in bytes */ +#define netconn_get_recvbufsize(conn) ((conn)->recv_bufsize) +#endif /* LWIP_SO_RCVBUF*/ + +#if LWIP_NETCONN_SEM_PER_THREAD +void netconn_thread_init(void); +void netconn_thread_cleanup(void); +#else /* LWIP_NETCONN_SEM_PER_THREAD */ +#define netconn_thread_init() +#define netconn_thread_cleanup() +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_NETCONN || LWIP_SOCKET */ + +#endif /* LWIP_HDR_API_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/api_msg.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/api_msg.h new file mode 100644 index 0000000..3505bf3 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/api_msg.h @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_API_MSG_H +#define LWIP_HDR_API_MSG_H + +#include "lwip/opt.h" + +#if LWIP_NETCONN || LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ + +/* don't export the netconn functions when socket API is enabled but netconn API is disabled */ +#if LWIP_NETCONN +#define LWIP_NETCONN_SCOPE +#else /* LWIP_NETCONN */ +#define LWIP_NETCONN_SCOPE static +#endif /* LWIP_NETCONN */ + +#include /* for size_t */ + +#include "lwip/ip_addr.h" +#include "lwip/err.h" +#include "lwip/sys.h" +#include "lwip/igmp.h" +#include "lwip/api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_MPU_COMPATIBLE +#define API_MSG_M_DEF(m) m +#else /* LWIP_MPU_COMPATIBLE */ +#define API_MSG_M_DEF(m) *m +#endif /* LWIP_MPU_COMPATIBLE */ + +/* For the netconn API, these values are use as a bitmask! */ +#define NETCONN_SHUT_RD 1 +#define NETCONN_SHUT_WR 2 +#define NETCONN_SHUT_RDWR (NETCONN_SHUT_RD | NETCONN_SHUT_WR) + +/* IP addresses and port numbers are expected to be in + * the same byte order as in the corresponding pcb. + */ +/** This struct includes everything that is necessary to execute a function + for a netconn in another thread context (mainly used to process netconns + in the tcpip_thread context to be thread safe). */ +struct api_msg_msg { + /** The netconn which to process - always needed: it includes the semaphore + which is used to block the application thread until the function finished. */ + struct netconn *conn; + /** The return value of the function executed in tcpip_thread. */ + err_t err; + /** Depending on the executed function, one of these union members is used */ + union { + /** used for lwip_netconn_do_send */ + struct netbuf *b; + /** used for lwip_netconn_do_newconn */ + struct { + u8_t proto; + } n; + /** used for lwip_netconn_do_bind and lwip_netconn_do_connect */ + struct { + ip_addr_t API_MSG_M_DEF(ipaddr); + u16_t port; + } bc; + /** used for lwip_netconn_do_getaddr */ + struct { + ipX_addr_t API_MSG_M_DEF(ipaddr); + u16_t API_MSG_M_DEF(port); + u8_t local; + } ad; + /** used for lwip_netconn_do_write */ + struct { + const void *dataptr; + size_t len; + u8_t apiflags; +#if LWIP_SO_SNDTIMEO + u32_t time_started; +#endif /* LWIP_SO_SNDTIMEO */ + } w; + /** used for lwip_netconn_do_recv */ + struct { + u32_t len; + } r; + /** used for lwip_netconn_do_close (/shutdown) */ + struct { + u8_t shut; + } sd; +#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) + /** used for lwip_netconn_do_join_leave_group */ + struct { + ipX_addr_t API_MSG_M_DEF(multiaddr); + ipX_addr_t API_MSG_M_DEF(netif_addr); + enum netconn_igmp join_or_leave; + } jl; +#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ +#if TCP_LISTEN_BACKLOG + struct { + u8_t backlog; + } lb; +#endif /* TCP_LISTEN_BACKLOG */ + } msg; +#if LWIP_NETCONN_SEM_PER_THREAD + sys_sem_t* op_completed_sem; +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ +}; + +#if LWIP_NETCONN_SEM_PER_THREAD +#define LWIP_API_MSG_SEM(msg) ((msg)->op_completed_sem) +#else /* LWIP_NETCONN_SEM_PER_THREAD */ +#define LWIP_API_MSG_SEM(msg) (&(msg)->conn->op_completed) +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + + +/** This struct contains a function to execute in another thread context and + a struct api_msg_msg that serves as an argument for this function. + This is passed to tcpip_apimsg to execute functions in tcpip_thread context. */ +struct api_msg { + /** function to execute in tcpip_thread context */ + void (* function)(struct api_msg_msg *msg); + /** arguments for this function */ + struct api_msg_msg msg; +}; + +#if LWIP_DNS +/** As lwip_netconn_do_gethostbyname requires more arguments but doesn't require a netconn, + it has its own struct (to avoid struct api_msg getting bigger than necessary). + lwip_netconn_do_gethostbyname must be called using tcpip_callback instead of tcpip_apimsg + (see netconn_gethostbyname). */ +struct dns_api_msg { + /** Hostname to query or dotted IP address string */ +#if LWIP_MPU_COMPATIBLE + char name[DNS_MAX_NAME_LENGTH]; +#else /* LWIP_MPU_COMPATIBLE */ + const char *name; +#endif /* LWIP_MPU_COMPATIBLE */ + /** Rhe resolved address is stored here */ + ip_addr_t API_MSG_M_DEF(addr); + /** This semaphore is posted when the name is resolved, the application thread + should wait on it. */ + sys_sem_t API_MSG_M_DEF(sem); + /** Errors are given back here */ + err_t API_MSG_M_DEF(err); +}; +#endif /* LWIP_DNS */ + +LWIP_NETCONN_SCOPE void lwip_netconn_do_newconn ( struct api_msg_msg *msg); +LWIP_NETCONN_SCOPE void lwip_netconn_do_delconn ( struct api_msg_msg *msg); +LWIP_NETCONN_SCOPE void lwip_netconn_do_bind ( struct api_msg_msg *msg); +LWIP_NETCONN_SCOPE void lwip_netconn_do_connect ( struct api_msg_msg *msg); +LWIP_NETCONN_SCOPE void lwip_netconn_do_disconnect ( struct api_msg_msg *msg); +LWIP_NETCONN_SCOPE void lwip_netconn_do_listen ( struct api_msg_msg *msg); +LWIP_NETCONN_SCOPE void lwip_netconn_do_send ( struct api_msg_msg *msg); +LWIP_NETCONN_SCOPE void lwip_netconn_do_recv ( struct api_msg_msg *msg); +LWIP_NETCONN_SCOPE void lwip_netconn_do_write ( struct api_msg_msg *msg); +LWIP_NETCONN_SCOPE void lwip_netconn_do_getaddr ( struct api_msg_msg *msg); +LWIP_NETCONN_SCOPE void lwip_netconn_do_close ( struct api_msg_msg *msg); +LWIP_NETCONN_SCOPE void lwip_netconn_do_shutdown ( struct api_msg_msg *msg); +#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) +LWIP_NETCONN_SCOPE void lwip_netconn_do_join_leave_group( struct api_msg_msg *msg); +#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ + +#if LWIP_DNS +LWIP_NETCONN_SCOPE void lwip_netconn_do_gethostbyname(void *arg); +#endif /* LWIP_DNS */ + +LWIP_NETCONN_SCOPE struct netconn* netconn_alloc(enum netconn_type t, netconn_callback callback); +LWIP_NETCONN_SCOPE void netconn_free(struct netconn *conn); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_NETCONN || LWIP_SOCKET */ + +#endif /* LWIP_HDR_API_MSG_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/arch.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/arch.h new file mode 100644 index 0000000..4cdb764 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/arch.h @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_ARCH_H +#define LWIP_HDR_ARCH_H + +#ifndef LITTLE_ENDIAN +#define LITTLE_ENDIAN 1234 +#endif + +#ifndef BIG_ENDIAN +#define BIG_ENDIAN 4321 +#endif + +#include "arch/cc.h" + +/** Temporary: define format string for size_t if not defined in cc.h */ +#ifndef SZT_F +#define SZT_F U32_F +#endif /* SZT_F */ +/** Temporary upgrade helper: define format string for u8_t as hex if not + defined in cc.h */ +#ifndef X8_F +#define X8_F "02x" +#endif /* X8_F */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef PACK_STRUCT_BEGIN +#define PACK_STRUCT_BEGIN +#endif /* PACK_STRUCT_BEGIN */ + +#ifndef PACK_STRUCT_END +#define PACK_STRUCT_END +#endif /* PACK_STRUCT_END */ + +#ifndef PACK_STRUCT_STRUCT +#define PACK_STRUCT_STRUCT +#endif /* PACK_STRUCT_STRUCT */ + +#ifndef PACK_STRUCT_FIELD +#define PACK_STRUCT_FIELD(x) x +#endif /* PACK_STRUCT_FIELD */ + +/* Used for struct fields of u8_t, + * where some compilers warn that packing is not necessary */ +#ifndef PACK_STRUCT_FLD_8 +#define PACK_STRUCT_FLD_8(x) PACK_STRUCT_FIELD(x) +#endif /* PACK_STRUCT_FLD_8 */ + +/* Used for struct fields of that are packed structs themself, + * where some compilers warn that packing is not necessary */ +#ifndef PACK_STRUCT_FLD_S +#define PACK_STRUCT_FLD_S(x) PACK_STRUCT_FIELD(x) +#endif /* PACK_STRUCT_FLD_S */ + + +#ifndef LWIP_UNUSED_ARG +#define LWIP_UNUSED_ARG(x) (void)x +#endif /* LWIP_UNUSED_ARG */ + + +#ifdef LWIP_PROVIDE_ERRNO + +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#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 child processes */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device or resource 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 ETXTBSY 26 /* Text file busy */ +#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 EDOM 33 /* Math argument out of domain of func */ +#define ERANGE 34 /* Math result not representable */ +#define EDEADLK 35 /* Resource deadlock would occur */ +#define ENAMETOOLONG 36 /* File name too long */ +#define ENOLCK 37 /* No record locks available */ +#define ENOSYS 38 /* Function not implemented */ +#define ENOTEMPTY 39 /* Directory not empty */ +#define ELOOP 40 /* Too many symbolic links encountered */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define ENOMSG 42 /* No message of desired type */ +#define EIDRM 43 /* Identifier removed */ +#define ECHRNG 44 /* Channel number out of range */ +#define EL2NSYNC 45 /* Level 2 not synchronized */ +#define EL3HLT 46 /* Level 3 halted */ +#define EL3RST 47 /* Level 3 reset */ +#define ELNRNG 48 /* Link number out of range */ +#define EUNATCH 49 /* Protocol driver not attached */ +#define ENOCSI 50 /* No CSI structure available */ +#define EL2HLT 51 /* Level 2 halted */ +#define EBADE 52 /* Invalid exchange */ +#define EBADR 53 /* Invalid request descriptor */ +#define EXFULL 54 /* Exchange full */ +#define ENOANO 55 /* No anode */ +#define EBADRQC 56 /* Invalid request code */ +#define EBADSLT 57 /* Invalid slot */ + +#define EDEADLOCK EDEADLK + +#define EBFONT 59 /* Bad font file format */ +#define ENOSTR 60 /* Device not a stream */ +#define ENODATA 61 /* No data available */ +#define ETIME 62 /* Timer expired */ +#define ENOSR 63 /* Out of streams resources */ +#define ENONET 64 /* Machine is not on the network */ +#define ENOPKG 65 /* Package not installed */ +#define EREMOTE 66 /* Object is remote */ +#define ENOLINK 67 /* Link has been severed */ +#define EADV 68 /* Advertise error */ +#define ESRMNT 69 /* Srmount error */ +#define ECOMM 70 /* Communication error on send */ +#define EPROTO 71 /* Protocol error */ +#define EMULTIHOP 72 /* Multihop attempted */ +#define EDOTDOT 73 /* RFS specific error */ +#define EBADMSG 74 /* Not a data message */ +#define EOVERFLOW 75 /* Value too large for defined data type */ +#define ENOTUNIQ 76 /* Name not unique on network */ +#define EBADFD 77 /* File descriptor in bad state */ +#define EREMCHG 78 /* Remote address changed */ +#define ELIBACC 79 /* Can not access a needed shared library */ +#define ELIBBAD 80 /* Accessing a corrupted shared library */ +#define ELIBSCN 81 /* .lib section in a.out corrupted */ +#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ +#define ELIBEXEC 83 /* Cannot exec a shared library directly */ +#define EILSEQ 84 /* Illegal byte sequence */ +#define ERESTART 85 /* Interrupted system call should be restarted */ +#define ESTRPIPE 86 /* Streams pipe error */ +#define EUSERS 87 /* Too many users */ +#define ENOTSOCK 88 /* Socket operation on non-socket */ +#define EDESTADDRREQ 89 /* Destination address required */ +#define EMSGSIZE 90 /* Message too long */ +#define EPROTOTYPE 91 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 92 /* Protocol not available */ +#define EPROTONOSUPPORT 93 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ +#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ +#define EADDRINUSE 98 /* Address already in use */ +#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ +#define ENETDOWN 100 /* Network is down */ +#define ENETUNREACH 101 /* Network is unreachable */ +#define ENETRESET 102 /* Network dropped connection because of reset */ +#define ECONNABORTED 103 /* Software caused connection abort */ +#define ECONNRESET 104 /* Connection reset by peer */ +#define ENOBUFS 105 /* No buffer space available */ +#define EISCONN 106 /* Transport endpoint is already connected */ +#define ENOTCONN 107 /* Transport endpoint is not connected */ +#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ +#define ETOOMANYREFS 109 /* Too many references: cannot splice */ +#define ETIMEDOUT 110 /* Connection timed out */ +#define ECONNREFUSED 111 /* Connection refused */ +#define EHOSTDOWN 112 /* Host is down */ +#define EHOSTUNREACH 113 /* No route to host */ +#define EALREADY 114 /* Operation already in progress */ +#define EINPROGRESS 115 /* Operation now in progress */ +#define ESTALE 116 /* Stale NFS file handle */ +#define EUCLEAN 117 /* Structure needs cleaning */ +#define ENOTNAM 118 /* Not a XENIX named type file */ +#define ENAVAIL 119 /* No XENIX semaphores available */ +#define EISNAM 120 /* Is a named type file */ +#define EREMOTEIO 121 /* Remote I/O error */ +#define EDQUOT 122 /* Quota exceeded */ + +#define ENOMEDIUM 123 /* No medium found */ +#define EMEDIUMTYPE 124 /* Wrong medium type */ + +#ifndef errno +extern int errno; +#endif + +#endif /* LWIP_PROVIDE_ERRNO */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_ARCH_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/autoip.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/autoip.h new file mode 100644 index 0000000..9a062c6 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/autoip.h @@ -0,0 +1,121 @@ +/** + * @file + * + * AutoIP Automatic LinkLocal IP Configuration + */ + +/* + * + * Copyright (c) 2007 Dominik Spies + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * Author: Dominik Spies + * + * This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform + * with RFC 3927. + * + * + * Please coordinate changes and requests with Dominik Spies + * + */ + +#ifndef LWIP_HDR_AUTOIP_H +#define LWIP_HDR_AUTOIP_H + +#include "lwip/opt.h" + +#if LWIP_AUTOIP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/netif.h" +#include "lwip/udp.h" +#include "netif/etharp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* AutoIP Timing */ +#define AUTOIP_TMR_INTERVAL 100 +#define AUTOIP_TICKS_PER_SECOND (1000 / AUTOIP_TMR_INTERVAL) + +/* RFC 3927 Constants */ +#define PROBE_WAIT 1 /* second (initial random delay) */ +#define PROBE_MIN 1 /* second (minimum delay till repeated probe) */ +#define PROBE_MAX 2 /* seconds (maximum delay till repeated probe) */ +#define PROBE_NUM 3 /* (number of probe packets) */ +#define ANNOUNCE_NUM 2 /* (number of announcement packets) */ +#define ANNOUNCE_INTERVAL 2 /* seconds (time between announcement packets) */ +#define ANNOUNCE_WAIT 2 /* seconds (delay before announcing) */ +#define MAX_CONFLICTS 10 /* (max conflicts before rate limiting) */ +#define RATE_LIMIT_INTERVAL 60 /* seconds (delay between successive attempts) */ +#define DEFEND_INTERVAL 10 /* seconds (min. wait between defensive ARPs) */ + +/* AutoIP client states */ +#define AUTOIP_STATE_OFF 0 +#define AUTOIP_STATE_PROBING 1 +#define AUTOIP_STATE_ANNOUNCING 2 +#define AUTOIP_STATE_BOUND 3 + +struct autoip +{ + ip_addr_t llipaddr; /* the currently selected, probed, announced or used LL IP-Address */ + u8_t state; /* current AutoIP state machine state */ + u8_t sent_num; /* sent number of probes or announces, dependent on state */ + u16_t ttw; /* ticks to wait, tick is AUTOIP_TMR_INTERVAL long */ + u8_t lastconflict; /* ticks until a conflict can be solved by defending */ + u8_t tried_llipaddr; /* total number of probed/used Link Local IP-Addresses */ +}; + + +#define autoip_init() /* Compatibility define, no init needed. */ + +/** Set a struct autoip allocated by the application to work with */ +void autoip_set_struct(struct netif *netif, struct autoip *autoip); + +/** Remove a struct autoip previously set to the netif using autoip_set_struct() */ +#define autoip_remove_struct(netif) do { (netif)->autoip = NULL; } while (0) + +/** Start AutoIP client */ +err_t autoip_start(struct netif *netif); + +/** Stop AutoIP client */ +err_t autoip_stop(struct netif *netif); + +/** Handles every incoming ARP Packet, called by etharp_arp_input */ +void autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr); + +/** Has to be called in loop every AUTOIP_TMR_INTERVAL milliseconds */ +void autoip_tmr(void); + +/** Handle a possible change in the network configuration */ +void autoip_network_changed(struct netif *netif); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_AUTOIP */ + +#endif /* LWIP_HDR_AUTOIP_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/debug.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/debug.h new file mode 100644 index 0000000..8844e73 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/debug.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_DEBUG_H +#define LWIP_HDR_DEBUG_H + +#include "lwip/arch.h" +#include "lwip/opt.h" +#include //Realtek add +/** lower two bits indicate debug level + * - 0 all + * - 1 warning + * - 2 serious + * - 3 severe + */ +#define LWIP_DBG_LEVEL_ALL 0x00 +#define LWIP_DBG_LEVEL_OFF LWIP_DBG_LEVEL_ALL /* compatibility define only */ +#define LWIP_DBG_LEVEL_WARNING 0x01 /* bad checksums, dropped packets, ... */ +#define LWIP_DBG_LEVEL_SERIOUS 0x02 /* memory allocation failures, ... */ +#define LWIP_DBG_LEVEL_SEVERE 0x03 +#define LWIP_DBG_MASK_LEVEL 0x03 + +/** flag for LWIP_DEBUGF to enable that debug message */ +#define LWIP_DBG_ON 0x80U +/** flag for LWIP_DEBUGF to disable that debug message */ +#define LWIP_DBG_OFF 0x00U + +/** flag for LWIP_DEBUGF indicating a tracing message (to follow program flow) */ +#define LWIP_DBG_TRACE 0x40U +/** flag for LWIP_DEBUGF indicating a state debug message (to follow module states) */ +#define LWIP_DBG_STATE 0x20U +/** flag for LWIP_DEBUGF indicating newly added code, not thoroughly tested yet */ +#define LWIP_DBG_FRESH 0x10U +/** flag for LWIP_DEBUGF to halt after printing this debug message */ +#define LWIP_DBG_HALT 0x08U + +#ifndef LWIP_NOASSERT +#define LWIP_ASSERT(message, assertion) do { if(!(assertion)) \ + LWIP_PLATFORM_ASSERT(message); } while(0) +#else /* LWIP_NOASSERT */ +#define LWIP_ASSERT(message, assertion) +#endif /* LWIP_NOASSERT */ + +/** if "expression" isn't true, then print "message" and execute "handler" expression */ +#ifndef LWIP_ERROR +#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \ + LWIP_PLATFORM_ASSERT(message); handler;}} while(0) +#endif /* LWIP_ERROR */ + +#ifdef LWIP_DEBUG +/** print debug message only if debug message type is enabled... + * AND is of correct type AND is at least LWIP_DBG_LEVEL + */ + + +#define LWIP_PLATFORM_DIAG printf //Realtek add +#define LWIP_DEBUGF(debug, message) do { \ + if ( \ + ((debug) & LWIP_DBG_ON) && \ + ((debug) & LWIP_DBG_TYPES_ON) && \ + ((s16_t)((debug) & LWIP_DBG_MASK_LEVEL) >= LWIP_DBG_MIN_LEVEL)) { \ + LWIP_PLATFORM_DIAG message; \ + if ((debug) & LWIP_DBG_HALT) { \ + while(1); \ + } \ + } \ + } while(0) + +#else /* LWIP_DEBUG */ +#define LWIP_DEBUGF(debug, message) +#endif /* LWIP_DEBUG */ + +#endif /* LWIP_HDR_DEBUG_H */ + diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/def.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/def.h new file mode 100644 index 0000000..c985a87 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/def.h @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_DEF_H +#define LWIP_HDR_DEF_H + +/* arch.h might define NULL already */ +#include "lwip/arch.h" +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define LWIP_MAX(x , y) (((x) > (y)) ? (x) : (y)) +#define LWIP_MIN(x , y) (((x) < (y)) ? (x) : (y)) + +#ifndef NULL +#define NULL ((void *)0) +#endif + +/* Endianess-optimized shifting of two u8_t to create one u16_t */ +#if BYTE_ORDER == LITTLE_ENDIAN +#define LWIP_MAKE_U16(a, b) ((a << 8) | b) +#else +#define LWIP_MAKE_U16(a, b) ((b << 8) | a) +#endif + +#ifndef LWIP_PLATFORM_BYTESWAP +#define LWIP_PLATFORM_BYTESWAP 0 +#endif + +#ifndef LWIP_PREFIX_BYTEORDER_FUNCS +/* workaround for naming collisions on some platforms */ + +#ifdef htons +#undef htons +#endif /* htons */ +#ifdef htonl +#undef htonl +#endif /* htonl */ +#ifdef ntohs +#undef ntohs +#endif /* ntohs */ +#ifdef ntohl +#undef ntohl +#endif /* ntohl */ + +#define htons(x) lwip_htons(x) +#define ntohs(x) lwip_ntohs(x) +#define htonl(x) lwip_htonl(x) +#define ntohl(x) lwip_ntohl(x) +#endif /* LWIP_PREFIX_BYTEORDER_FUNCS */ + +#if BYTE_ORDER == BIG_ENDIAN +#define lwip_htons(x) (x) +#define lwip_ntohs(x) (x) +#define lwip_htonl(x) (x) +#define lwip_ntohl(x) (x) +#define PP_HTONS(x) (x) +#define PP_NTOHS(x) (x) +#define PP_HTONL(x) (x) +#define PP_NTOHL(x) (x) +#else /* BYTE_ORDER != BIG_ENDIAN */ +#if LWIP_PLATFORM_BYTESWAP +#define lwip_htons(x) LWIP_PLATFORM_HTONS(x) +#define lwip_ntohs(x) LWIP_PLATFORM_HTONS(x) +#define lwip_htonl(x) LWIP_PLATFORM_HTONL(x) +#define lwip_ntohl(x) LWIP_PLATFORM_HTONL(x) +#else /* LWIP_PLATFORM_BYTESWAP */ +u16_t lwip_htons(u16_t x); +u16_t lwip_ntohs(u16_t x); +u32_t lwip_htonl(u32_t x); +u32_t lwip_ntohl(u32_t x); +#endif /* LWIP_PLATFORM_BYTESWAP */ + +/* These macros should be calculated by the preprocessor and are used + with compile-time constants only (so that there is no little-endian + overhead at runtime). */ +#define PP_HTONS(x) ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8)) +#define PP_NTOHS(x) PP_HTONS(x) +#define PP_HTONL(x) ((((x) & 0xff) << 24) | \ + (((x) & 0xff00) << 8) | \ + (((x) & 0xff0000UL) >> 8) | \ + (((x) & 0xff000000UL) >> 24)) +#define PP_NTOHL(x) PP_HTONL(x) + +#endif /* BYTE_ORDER == BIG_ENDIAN */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_DEF_H */ + diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/dhcp.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/dhcp.h new file mode 100644 index 0000000..6cfbf90 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/dhcp.h @@ -0,0 +1,242 @@ +/** @file + */ + +#ifndef LWIP_HDR_DHCP_H +#define LWIP_HDR_DHCP_H + +#include "lwip/opt.h" + +#if LWIP_DHCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/netif.h" +#include "lwip/udp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** period (in seconds) of the application calling dhcp_coarse_tmr() */ +#define DHCP_COARSE_TIMER_SECS 60 +/** period (in milliseconds) of the application calling dhcp_coarse_tmr() */ +#define DHCP_COARSE_TIMER_MSECS (DHCP_COARSE_TIMER_SECS * 1000UL) +/** period (in milliseconds) of the application calling dhcp_fine_tmr() */ +#define DHCP_FINE_TIMER_MSECS 500 + +#define DHCP_CHADDR_LEN 16U +#define DHCP_SNAME_LEN 64U +#define DHCP_FILE_LEN 128U + +struct dhcp +{ + /** transaction identifier of last sent request */ + u32_t xid; + /** our connection to the DHCP server */ + struct udp_pcb *pcb; + /** incoming msg */ + struct dhcp_msg *msg_in; + /** current DHCP state machine state */ + u8_t state; + /** retries of current request */ + u8_t tries; +#if LWIP_DHCP_AUTOIP_COOP + u8_t autoip_coop_state; +#endif + u8_t subnet_mask_given; + + struct pbuf *p_out; /* pbuf of outcoming msg */ + struct dhcp_msg *msg_out; /* outgoing msg */ + u16_t options_out_len; /* outgoing msg options length */ + u16_t request_timeout; /* #ticks with period DHCP_FINE_TIMER_SECS for request timeout */ + u16_t t1_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for renewal time */ + u16_t t2_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for rebind time */ + ip_addr_t server_ip_addr; /* dhcp server address that offered this lease */ + ip_addr_t offered_ip_addr; + ip_addr_t offered_sn_mask; + ip_addr_t offered_gw_addr; + ip_addr_t offered_bc_addr;//Evan add for used old version lwip api in lwip_netconf.c + + u32_t offered_t0_lease; /* lease period (in seconds) */ + u32_t offered_t1_renew; /* recommended renew time (usually 50% of lease period) */ + u32_t offered_t2_rebind; /* recommended rebind time (usually 66% of lease period) */ +#if LWIP_DHCP_BOOTP_FILE + ip_addr_t offered_si_addr; + char boot_file_name[DHCP_FILE_LEN]; +#endif /* LWIP_DHCP_BOOTPFILE */ +}; + +/* MUST be compiled with "pack structs" or equivalent! */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** minimum set of fields of any DHCP message */ +struct dhcp_msg +{ + PACK_STRUCT_FLD_8(u8_t op); + PACK_STRUCT_FLD_8(u8_t htype); + PACK_STRUCT_FLD_8(u8_t hlen); + PACK_STRUCT_FLD_8(u8_t hops); + PACK_STRUCT_FIELD(u32_t xid); + PACK_STRUCT_FIELD(u16_t secs); + PACK_STRUCT_FIELD(u16_t flags); + PACK_STRUCT_FLD_S(ip_addr_p_t ciaddr); + PACK_STRUCT_FLD_S(ip_addr_p_t yiaddr); + PACK_STRUCT_FLD_S(ip_addr_p_t siaddr); + PACK_STRUCT_FLD_S(ip_addr_p_t giaddr); + PACK_STRUCT_FLD_8(u8_t chaddr[DHCP_CHADDR_LEN]); + PACK_STRUCT_FLD_8(u8_t sname[DHCP_SNAME_LEN]); + PACK_STRUCT_FLD_8(u8_t file[DHCP_FILE_LEN]); + PACK_STRUCT_FIELD(u32_t cookie); +#define DHCP_MIN_OPTIONS_LEN 68U +/** make sure user does not configure this too small */ +#if ((defined(DHCP_OPTIONS_LEN)) && (DHCP_OPTIONS_LEN < DHCP_MIN_OPTIONS_LEN)) +# undef DHCP_OPTIONS_LEN +#endif +/** allow this to be configured in lwipopts.h, but not too small */ +#if (!defined(DHCP_OPTIONS_LEN)) +/** set this to be sufficient for your options in outgoing DHCP msgs */ +# define DHCP_OPTIONS_LEN DHCP_MIN_OPTIONS_LEN +#endif + PACK_STRUCT_FLD_8(u8_t options[DHCP_OPTIONS_LEN]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +void dhcp_set_struct(struct netif *netif, struct dhcp *dhcp); +/** Remove a struct dhcp previously set to the netif using dhcp_set_struct() */ +#define dhcp_remove_struct(netif) do { (netif)->dhcp = NULL; } while(0) +void dhcp_cleanup(struct netif *netif); +/** start DHCP configuration */ +err_t dhcp_start(struct netif *netif); +/** enforce early lease renewal (not needed normally)*/ +err_t dhcp_renew(struct netif *netif); +/** release the DHCP lease, usually called before dhcp_stop()*/ +err_t dhcp_release(struct netif *netif); +err_t dhcp_release_unicast(struct netif *netif); //Realtek add +/** stop DHCP configuration */ +void dhcp_stop(struct netif *netif); +/** inform server of our manual IP address */ +void dhcp_inform(struct netif *netif); +/** Handle a possible change in the network configuration */ +void dhcp_network_changed(struct netif *netif); + +/** if enabled, check whether the offered IP address is not in use, using ARP */ +#if DHCP_DOES_ARP_CHECK +void dhcp_arp_reply(struct netif *netif, ip_addr_t *addr); +#endif + +/** to be called every minute */ +void dhcp_coarse_tmr(void); +/** to be called every half second */ +void dhcp_fine_tmr(void); + +/** DHCP message item offsets and length */ +#define DHCP_OP_OFS 0 +#define DHCP_HTYPE_OFS 1 +#define DHCP_HLEN_OFS 2 +#define DHCP_HOPS_OFS 3 +#define DHCP_XID_OFS 4 +#define DHCP_SECS_OFS 8 +#define DHCP_FLAGS_OFS 10 +#define DHCP_CIADDR_OFS 12 +#define DHCP_YIADDR_OFS 16 +#define DHCP_SIADDR_OFS 20 +#define DHCP_GIADDR_OFS 24 +#define DHCP_CHADDR_OFS 28 +#define DHCP_SNAME_OFS 44 +#define DHCP_FILE_OFS 108 +#define DHCP_MSG_LEN 236 + +#define DHCP_COOKIE_OFS DHCP_MSG_LEN +#define DHCP_OPTIONS_OFS (DHCP_MSG_LEN + 4) + +#define DHCP_CLIENT_PORT 68 +#define DHCP_SERVER_PORT 67 + +/** DHCP client states */ +#define DHCP_OFF 0 +#define DHCP_REQUESTING 1 +#define DHCP_INIT 2 +#define DHCP_REBOOTING 3 +#define DHCP_REBINDING 4 +#define DHCP_RENEWING 5 +#define DHCP_SELECTING 6 +/* not yet implemented #define DHCP_INFORMING 7*/ +#define DHCP_CHECKING 8 +/* not yet implemented #define DHCP_PERMANENT 9*/ +#define DHCP_BOUND 10 +#define DHCP_RELEASING 11 //Realtek modified +#define DHCP_BACKING_OFF 12 + +/** AUTOIP cooperation flags */ +#define DHCP_AUTOIP_COOP_STATE_OFF 0 +#define DHCP_AUTOIP_COOP_STATE_ON 1 + +#define DHCP_BOOTREQUEST 1 +#define DHCP_BOOTREPLY 2 + +/** DHCP message types */ +#define DHCP_DISCOVER 1 +#define DHCP_OFFER 2 +#define DHCP_REQUEST 3 +#define DHCP_DECLINE 4 +#define DHCP_ACK 5 +#define DHCP_NAK 6 +#define DHCP_RELEASE 7 +#define DHCP_INFORM 8 + +/** DHCP hardware type, currently only ethernet is supported */ +#define DHCP_HTYPE_ETH 1 + +#define DHCP_MAGIC_COOKIE 0x63825363UL + +/* This is a list of options for BOOTP and DHCP, see RFC 2132 for descriptions */ + +/** BootP options */ +#define DHCP_OPTION_PAD 0 +#define DHCP_OPTION_SUBNET_MASK 1 /* RFC 2132 3.3 */ +#define DHCP_OPTION_ROUTER 3 +#define DHCP_OPTION_DNS_SERVER 6 +#define DHCP_OPTION_HOSTNAME 12 +#define DHCP_OPTION_IP_TTL 23 +#define DHCP_OPTION_MTU 26 +#define DHCP_OPTION_BROADCAST 28 +#define DHCP_OPTION_TCP_TTL 37 +#define DHCP_OPTION_END 255 + +/** DHCP options */ +#define DHCP_OPTION_REQUESTED_IP 50 /* RFC 2132 9.1, requested IP address */ +#define DHCP_OPTION_LEASE_TIME 51 /* RFC 2132 9.2, time in seconds, in 4 bytes */ +#define DHCP_OPTION_OVERLOAD 52 /* RFC2132 9.3, use file and/or sname field for options */ + +#define DHCP_OPTION_MESSAGE_TYPE 53 /* RFC 2132 9.6, important for DHCP */ +#define DHCP_OPTION_MESSAGE_TYPE_LEN 1 + +#define DHCP_OPTION_SERVER_ID 54 /* RFC 2132 9.7, server IP address */ +#define DHCP_OPTION_PARAMETER_REQUEST_LIST 55 /* RFC 2132 9.8, requested option types */ + +#define DHCP_OPTION_MAX_MSG_SIZE 57 /* RFC 2132 9.10, message size accepted >= 576 */ +#define DHCP_OPTION_MAX_MSG_SIZE_LEN 2 + +#define DHCP_OPTION_T1 58 /* T1 renewal time */ +#define DHCP_OPTION_T2 59 /* T2 rebinding time */ +#define DHCP_OPTION_US 60 +#define DHCP_OPTION_CLIENT_ID 61 +#define DHCP_OPTION_TFTP_SERVERNAME 66 +#define DHCP_OPTION_BOOTFILE 67 + +/** possible combinations of overloading the file and sname fields with options */ +#define DHCP_OVERLOAD_NONE 0 +#define DHCP_OVERLOAD_FILE 1 +#define DHCP_OVERLOAD_SNAME 2 +#define DHCP_OVERLOAD_SNAME_FILE 3 + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_DHCP */ + +#endif /*LWIP_HDR_DHCP_H*/ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/dhcp6.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/dhcp6.h new file mode 100644 index 0000000..345bcf0 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/dhcp6.h @@ -0,0 +1,58 @@ +/** + * @file + * + * IPv6 address autoconfiguration as per RFC 4862. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * IPv6 address autoconfiguration as per RFC 4862. + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#ifndef LWIP_HDR_IP6_DHCP6_H +#define LWIP_HDR_IP6_DHCP6_H + +#include "lwip/opt.h" + +#if LWIP_IPV6_DHCP6 /* don't build if not configured for use in lwipopts.h */ + + +struct dhcp6 +{ + /*TODO: implement DHCP6*/ +}; + +#endif /* LWIP_IPV6_DHCP6 */ + +#endif /* LWIP_HDR_IP6_DHCP6_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/dns.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/dns.h new file mode 100644 index 0000000..eb81c90 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/dns.h @@ -0,0 +1,117 @@ +/** + * lwip DNS resolver header file. + + * Author: Jim Pettinato + * April 2007 + + * ported from uIP resolv.c Copyright (c) 2002-2003, Adam Dunkels. + * + * 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. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 LWIP_HDR_DNS_H +#define LWIP_HDR_DNS_H + +#include "lwip/opt.h" + +#if LWIP_DNS /* don't build if not configured for use in lwipopts.h */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** DNS timer period */ +#define DNS_TMR_INTERVAL 1000 + +/** DNS field TYPE used for "Resource Records" */ +#define DNS_RRTYPE_A 1 /* a host address */ +#define DNS_RRTYPE_NS 2 /* an authoritative name server */ +#define DNS_RRTYPE_MD 3 /* a mail destination (Obsolete - use MX) */ +#define DNS_RRTYPE_MF 4 /* a mail forwarder (Obsolete - use MX) */ +#define DNS_RRTYPE_CNAME 5 /* the canonical name for an alias */ +#define DNS_RRTYPE_SOA 6 /* marks the start of a zone of authority */ +#define DNS_RRTYPE_MB 7 /* a mailbox domain name (EXPERIMENTAL) */ +#define DNS_RRTYPE_MG 8 /* a mail group member (EXPERIMENTAL) */ +#define DNS_RRTYPE_MR 9 /* a mail rename domain name (EXPERIMENTAL) */ +#define DNS_RRTYPE_NULL 10 /* a null RR (EXPERIMENTAL) */ +#define DNS_RRTYPE_WKS 11 /* a well known service description */ +#define DNS_RRTYPE_PTR 12 /* a domain name pointer */ +#define DNS_RRTYPE_HINFO 13 /* host information */ +#define DNS_RRTYPE_MINFO 14 /* mailbox or mail list information */ +#define DNS_RRTYPE_MX 15 /* mail exchange */ +#define DNS_RRTYPE_TXT 16 /* text strings */ + +/** DNS field CLASS used for "Resource Records" */ +#define DNS_RRCLASS_IN 1 /* the Internet */ +#define DNS_RRCLASS_CS 2 /* the CSNET class (Obsolete - used only for examples in some obsolete RFCs) */ +#define DNS_RRCLASS_CH 3 /* the CHAOS class */ +#define DNS_RRCLASS_HS 4 /* Hesiod [Dyer 87] */ +#define DNS_RRCLASS_FLUSH 0x800 /* Flush bit */ + +#if DNS_LOCAL_HOSTLIST +/** struct used for local host-list */ +struct local_hostlist_entry { + /** static hostname */ + const char *name; + /** static host address in network byteorder */ + ip_addr_t addr; + struct local_hostlist_entry *next; +}; +#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC +#ifndef DNS_LOCAL_HOSTLIST_MAX_NAMELEN +#define DNS_LOCAL_HOSTLIST_MAX_NAMELEN DNS_MAX_NAME_LENGTH +#endif +#define LOCALHOSTLIST_ELEM_SIZE ((sizeof(struct local_hostlist_entry) + DNS_LOCAL_HOSTLIST_MAX_NAMELEN + 1)) +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ +#endif /* DNS_LOCAL_HOSTLIST */ + +/** Callback which is invoked when a hostname is found. + * A function of this type must be implemented by the application using the DNS resolver. + * @param name pointer to the name that was looked up. + * @param ipaddr pointer to an ip_addr_t containing the IP address of the hostname, + * or NULL if the name could not be found (or on any other error). + * @param callback_arg a user-specified callback argument passed to dns_gethostbyname +*/ +typedef void (*dns_found_callback)(const char *name, ip_addr_t *ipaddr, void *callback_arg); + +void dns_init(void); +void dns_tmr(void); +void dns_setserver(u8_t numdns, ip_addr_t *dnsserver); +ip_addr_t dns_getserver(u8_t numdns); +err_t dns_gethostbyname(const char *hostname, ip_addr_t *addr, + dns_found_callback found, void *callback_arg); + +#if DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC +int dns_local_removehost(const char *hostname, const ip_addr_t *addr); +err_t dns_local_addhost(const char *hostname, const ip_addr_t *addr); +#endif /* DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_DNS */ + +#endif /* LWIP_HDR_DNS_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/err.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/err.h new file mode 100644 index 0000000..a48430d --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/err.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_ERR_H +#define LWIP_HDR_ERR_H + +#include "lwip/opt.h" +#include "lwip/arch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Define LWIP_ERR_T in cc.h if you want to use + * a different type for your platform (must be signed). */ +#ifdef LWIP_ERR_T +typedef LWIP_ERR_T err_t; +#else /* LWIP_ERR_T */ +typedef s8_t err_t; +#endif /* LWIP_ERR_T*/ + +/* Definitions for error constants. */ + +#define ERR_OK 0 /* No error, everything OK. */ +#define ERR_MEM -1 /* Out of memory error. */ +#define ERR_BUF -2 /* Buffer error. */ +#define ERR_TIMEOUT -3 /* Timeout. */ +#define ERR_RTE -4 /* Routing problem. */ +#define ERR_INPROGRESS -5 /* Operation in progress */ +#define ERR_VAL -6 /* Illegal value. */ +#define ERR_WOULDBLOCK -7 /* Operation would block. */ +#define ERR_USE -8 /* Address in use. */ +#define ERR_ISCONN -9 /* Already connected. */ + +#define ERR_IS_FATAL(e) ((e) < ERR_ISCONN) + +#define ERR_CONN -10 /* Not connected. */ +#define ERR_IS_FATAL_LISTENCONNECT(e) ((e) < ERR_CONN) + +#define ERR_ABRT -11 /* Connection aborted. */ +#define ERR_RST -12 /* Connection reset. */ +#define ERR_CLSD -13 /* Connection closed. */ + +#define ERR_ARG -14 /* Illegal argument. */ + +#define ERR_IF -15 /* Low-level netif error */ + + +#ifdef LWIP_DEBUG +extern const char *lwip_strerr(err_t err); +#else +#define lwip_strerr(x) "" +#endif /* LWIP_DEBUG */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_ERR_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/ethip6.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/ethip6.h new file mode 100644 index 0000000..31fed18 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/ethip6.h @@ -0,0 +1,68 @@ +/** + * @file + * + * Ethernet output for IPv6. Uses ND tables for link-layer addressing. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#ifndef LWIP_HDR_ETHIP6_H +#define LWIP_HDR_ETHIP6_H + +#include "lwip/opt.h" + +#if LWIP_IPV6 && LWIP_ETHERNET /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/netif.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +err_t ethip6_output(struct netif *netif, struct pbuf *q, ip6_addr_t *ip6addr); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV6 && LWIP_ETHERNET */ + +#endif /* LWIP_HDR_ETHIP6_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/icmp.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/icmp.h new file mode 100644 index 0000000..0ca6522 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/icmp.h @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_ICMP_H +#define LWIP_HDR_ICMP_H + +#include "lwip/opt.h" +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" + +#if LWIP_IPV6 && LWIP_ICMP6 +#include "lwip/icmp6.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define ICMP_ER 0 /* echo reply */ +#define ICMP_DUR 3 /* destination unreachable */ +#define ICMP_SQ 4 /* source quench */ +#define ICMP_RD 5 /* redirect */ +#define ICMP_ECHO 8 /* echo */ +#define ICMP_TE 11 /* time exceeded */ +#define ICMP_PP 12 /* parameter problem */ +#define ICMP_TS 13 /* timestamp */ +#define ICMP_TSR 14 /* timestamp reply */ +#define ICMP_IRQ 15 /* information request */ +#define ICMP_IR 16 /* information reply */ + +enum icmp_dur_type { + ICMP_DUR_NET = 0, /* net unreachable */ + ICMP_DUR_HOST = 1, /* host unreachable */ + ICMP_DUR_PROTO = 2, /* protocol unreachable */ + ICMP_DUR_PORT = 3, /* port unreachable */ + ICMP_DUR_FRAG = 4, /* fragmentation needed and DF set */ + ICMP_DUR_SR = 5 /* source route failed */ +}; + +enum icmp_te_type { + ICMP_TE_TTL = 0, /* time to live exceeded in transit */ + ICMP_TE_FRAG = 1 /* fragment reassembly time exceeded */ +}; + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +/** This is the standard ICMP header only that the u32_t data + * is split to two u16_t like ICMP echo needs it. + * This header is also used for other ICMP types that do not + * use the data part. + */ +PACK_STRUCT_BEGIN +struct icmp_echo_hdr { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u16_t id); + PACK_STRUCT_FIELD(u16_t seqno); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define ICMPH_TYPE(hdr) ((hdr)->type) +#define ICMPH_CODE(hdr) ((hdr)->code) + +/** Combines type and code to an u16_t */ +#define ICMPH_TYPE_SET(hdr, t) ((hdr)->type = (t)) +#define ICMPH_CODE_SET(hdr, c) ((hdr)->code = (c)) + + +#if LWIP_ICMP /* don't build if not configured for use in lwipopts.h */ + +void icmp_input(struct pbuf *p, struct netif *inp); +void icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t); +void icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t); + +#endif /* LWIP_ICMP */ + +#if (LWIP_IPV6 && LWIP_ICMP6) +#define icmp_port_unreach(isipv6, pbuf) ((isipv6) ? \ + icmp6_dest_unreach(pbuf, ICMP6_DUR_PORT) : \ + icmp_dest_unreach(pbuf, ICMP_DUR_PORT)) +#elif LWIP_ICMP +#define icmp_port_unreach(isipv6, pbuf) icmp_dest_unreach(pbuf, ICMP_DUR_PORT) +#else /* (LWIP_IPV6 && LWIP_ICMP6) || LWIP_ICMP*/ +#define icmp_port_unreach(isipv6, pbuf) +#endif /* (LWIP_IPV6 && LWIP_ICMP6) || LWIP_ICMP*/ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_ICMP_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/icmp6.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/icmp6.h new file mode 100644 index 0000000..9d57103 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/icmp6.h @@ -0,0 +1,152 @@ +/** + * @file + * + * IPv6 version of ICMP, as per RFC 4443. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ +#ifndef LWIP_HDR_ICMP6_H +#define LWIP_HDR_ICMP6_H + +#include "lwip/opt.h" +#include "lwip/pbuf.h" +#include "lwip/ip6_addr.h" +#include "lwip/netif.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +enum icmp6_type { + ICMP6_TYPE_DUR = 1, /* Destination unreachable */ + ICMP6_TYPE_PTB = 2, /* Packet too big */ + ICMP6_TYPE_TE = 3, /* Time exceeded */ + ICMP6_TYPE_PP = 4, /* Parameter problem */ + ICMP6_TYPE_PE1 = 100, /* Private experimentation */ + ICMP6_TYPE_PE2 = 101, /* Private experimentation */ + ICMP6_TYPE_RSV_ERR = 127, /* Reserved for expansion of error messages */ + + ICMP6_TYPE_EREQ = 128, /* Echo request */ + ICMP6_TYPE_EREP = 129, /* Echo reply */ + ICMP6_TYPE_MLQ = 130, /* Multicast listener query */ + ICMP6_TYPE_MLR = 131, /* Multicast listener report */ + ICMP6_TYPE_MLD = 132, /* Multicast listener done */ + ICMP6_TYPE_RS = 133, /* Router solicitation */ + ICMP6_TYPE_RA = 134, /* Router advertisement */ + ICMP6_TYPE_NS = 135, /* Neighbor solicitation */ + ICMP6_TYPE_NA = 136, /* Neighbor advertisement */ + ICMP6_TYPE_RD = 137, /* Redirect */ + ICMP6_TYPE_MRA = 151, /* Multicast router advertisement */ + ICMP6_TYPE_MRS = 152, /* Multicast router solicitation */ + ICMP6_TYPE_MRT = 153, /* Multicast router termination */ + ICMP6_TYPE_PE3 = 200, /* Private experimentation */ + ICMP6_TYPE_PE4 = 201, /* Private experimentation */ + ICMP6_TYPE_RSV_INF = 255 /* Reserved for expansion of informational messages */ +}; + +enum icmp6_dur_code { + ICMP6_DUR_NO_ROUTE = 0, /* No route to destination */ + ICMP6_DUR_PROHIBITED = 1, /* Communication with destination administratively prohibited */ + ICMP6_DUR_SCOPE = 2, /* Beyond scope of source address */ + ICMP6_DUR_ADDRESS = 3, /* Address unreachable */ + ICMP6_DUR_PORT = 4, /* Port unreachable */ + ICMP6_DUR_POLICY = 5, /* Source address failed ingress/egress policy */ + ICMP6_DUR_REJECT_ROUTE = 6 /* Reject route to destination */ +}; + +enum icmp6_te_code { + ICMP6_TE_HL = 0, /* Hop limit exceeded in transit */ + ICMP6_TE_FRAG = 1 /* Fragment reassembly time exceeded */ +}; + +enum icmp6_pp_code { + ICMP6_PP_FIELD = 0, /* Erroneous header field encountered */ + ICMP6_PP_HEADER = 1, /* Unrecognized next header type encountered */ + ICMP6_PP_OPTION = 2 /* Unrecognized IPv6 option encountered */ +}; + +/** This is the standard ICMP6 header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct icmp6_hdr { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u32_t data); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** This is the ICMP6 header adapted for echo req/resp. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct icmp6_echo_hdr { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u16_t id); + PACK_STRUCT_FIELD(u16_t seqno); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + + +#if LWIP_ICMP6 && LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +void icmp6_input(struct pbuf *p, struct netif *inp); +void icmp6_dest_unreach(struct pbuf *p, enum icmp6_dur_code c); +void icmp6_packet_too_big(struct pbuf *p, u32_t mtu); +void icmp6_time_exceeded(struct pbuf *p, enum icmp6_te_code c); +void icmp6_param_problem(struct pbuf *p, enum icmp6_pp_code c, u32_t pointer); + +#endif /* LWIP_ICMP6 && LWIP_IPV6 */ + + +#ifdef __cplusplus +} +#endif + + +#endif /* LWIP_HDR_ICMP6_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/igmp.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/igmp.h new file mode 100644 index 0000000..4687b1f --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/igmp.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2002 CITEL Technologies Ltd. + * 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 CITEL Technologies Ltd 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 CITEL TECHNOLOGIES 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 CITEL TECHNOLOGIES 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. + * + * This file is a contribution to the lwIP TCP/IP stack. + * The Swedish Institute of Computer Science and Adam Dunkels + * are specifically granted permission to redistribute this + * source code. +*/ + +#ifndef LWIP_HDR_IGMP_H +#define LWIP_HDR_IGMP_H + +#include "lwip/opt.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/pbuf.h" + +#if LWIP_IGMP /* don't build if not configured for use in lwipopts.h */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/* IGMP timer */ +#define IGMP_TMR_INTERVAL 100 /* Milliseconds */ +#define IGMP_V1_DELAYING_MEMBER_TMR (1000/IGMP_TMR_INTERVAL) +#define IGMP_JOIN_DELAYING_MEMBER_TMR (500 /IGMP_TMR_INTERVAL) + +/* MAC Filter Actions, these are passed to a netif's + * igmp_mac_filter callback function. */ +#define IGMP_DEL_MAC_FILTER 0 +#define IGMP_ADD_MAC_FILTER 1 + + +/** + * igmp group structure - there is + * a list of groups for each interface + * these should really be linked from the interface, but + * if we keep them separate we will not affect the lwip original code + * too much + * + * There will be a group for the all systems group address but this + * will not run the state machine as it is used to kick off reports + * from all the other groups + */ +struct igmp_group { + /** next link */ + struct igmp_group *next; + /** interface on which the group is active */ + struct netif *netif; + /** multicast address */ + ip_addr_t group_address; + /** signifies we were the last person to report */ + u8_t last_reporter_flag; + /** current state of the group */ + u8_t group_state; + /** timer for reporting, negative is OFF */ + u16_t timer; + /** counter of simultaneous uses */ + u8_t use; +}; + +/* Prototypes */ +void igmp_init(void); +err_t igmp_start(struct netif *netif); +err_t igmp_stop(struct netif *netif); +void igmp_report_groups(struct netif *netif); +struct igmp_group *igmp_lookfor_group(struct netif *ifp, ip_addr_t *addr); +void igmp_input(struct pbuf *p, struct netif *inp, ip_addr_t *dest); +err_t igmp_joingroup(ip_addr_t *ifaddr, ip_addr_t *groupaddr); +err_t igmp_leavegroup(ip_addr_t *ifaddr, ip_addr_t *groupaddr); +void igmp_tmr(void); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IGMP */ + +#endif /* LWIP_HDR_IGMP_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/inet.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/inet.h new file mode 100644 index 0000000..2895d61 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/inet.h @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_INET_H +#define LWIP_HDR_INET_H + +#include "lwip/opt.h" +#include "lwip/def.h" +#include "lwip/ip_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* If your port already typedef's in_addr_t, define IN_ADDR_T_DEFINED + to prevent this code from redefining it. */ +#if !defined(in_addr_t) && !defined(IN_ADDR_T_DEFINED) +typedef u32_t in_addr_t; +#endif +/** For compatibility with BSD code */ +struct in_addr { + in_addr_t s_addr; +}; + +/** 255.255.255.255 */ +#define INADDR_NONE IPADDR_NONE +/** 127.0.0.1 */ +#define INADDR_LOOPBACK IPADDR_LOOPBACK +/** 0.0.0.0 */ +#define INADDR_ANY IPADDR_ANY +/** 255.255.255.255 */ +#define INADDR_BROADCAST IPADDR_BROADCAST + +/* Definitions of the bits in an Internet address integer. + + On subnets, host and network parts are found according to + the subnet mask, not these masks. */ +#define IN_CLASSA(a) IP_CLASSA(a) +#define IN_CLASSA_NET IP_CLASSA_NET +#define IN_CLASSA_NSHIFT IP_CLASSA_NSHIFT +#define IN_CLASSA_HOST IP_CLASSA_HOST +#define IN_CLASSA_MAX IP_CLASSA_MAX + +#define IN_CLASSB(b) IP_CLASSB(b) +#define IN_CLASSB_NET IP_CLASSB_NET +#define IN_CLASSB_NSHIFT IP_CLASSB_NSHIFT +#define IN_CLASSB_HOST IP_CLASSB_HOST +#define IN_CLASSB_MAX IP_CLASSB_MAX + +#define IN_CLASSC(c) IP_CLASSC(c) +#define IN_CLASSC_NET IP_CLASSC_NET +#define IN_CLASSC_NSHIFT IP_CLASSC_NSHIFT +#define IN_CLASSC_HOST IP_CLASSC_HOST +#define IN_CLASSC_MAX IP_CLASSC_MAX + +#define IN_CLASSD(d) IP_CLASSD(d) +#define IN_CLASSD_NET IP_CLASSD_NET /* These ones aren't really */ +#define IN_CLASSD_NSHIFT IP_CLASSD_NSHIFT /* net and host fields, but */ +#define IN_CLASSD_HOST IP_CLASSD_HOST /* routing needn't know. */ +#define IN_CLASSD_MAX IP_CLASSD_MAX + +#define IN_MULTICAST(a) IP_MULTICAST(a) + +#define IN_EXPERIMENTAL(a) IP_EXPERIMENTAL(a) +#define IN_BADCLASS(a) IP_BADCLASS(a) + +#define IN_LOOPBACKNET IP_LOOPBACKNET + +#ifndef INET_ADDRSTRLEN +#define INET_ADDRSTRLEN IP4ADDR_STRLEN_MAX +#endif +#if LWIP_IPV6 +#ifndef INET6_ADDRSTRLEN +#define INET6_ADDRSTRLEN IP6ADDR_STRLEN_MAX +#endif +#endif + +#define inet_addr_from_ipaddr(target_inaddr, source_ipaddr) ((target_inaddr)->s_addr = ip4_addr_get_u32(source_ipaddr)) +#define inet_addr_to_ipaddr(target_ipaddr, source_inaddr) (ip4_addr_set_u32(target_ipaddr, (source_inaddr)->s_addr)) +/* ATTENTION: the next define only works because both s_addr and ip_addr_t are an u32_t effectively! */ +#define inet_addr_to_ipaddr_p(target_ipaddr_p, source_inaddr) ((target_ipaddr_p) = (ip_addr_t*)&((source_inaddr)->s_addr)) + +/* directly map this to the lwip internal functions */ +#define inet_addr(cp) ipaddr_addr(cp) +#define inet_aton(cp, addr) ipaddr_aton(cp, (ip_addr_t*)addr) +#define inet_ntoa(addr) ipaddr_ntoa((ip_addr_t*)&(addr)) +#define inet_ntoa_r(addr, buf, buflen) ipaddr_ntoa_r((ip_addr_t*)&(addr), buf, buflen) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_INET_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/inet6.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/inet6.h new file mode 100644 index 0000000..afaa923 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/inet6.h @@ -0,0 +1,92 @@ +/** + * @file + * + * INET v6 addresses. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ +#ifndef LWIP_HDR_INET6_H +#define LWIP_HDR_INET6_H + +#include "lwip/opt.h" + +#if LWIP_IPV6 && LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/ip6_addr.h" +#include "lwip/def.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** For compatibility with BSD code */ +struct in6_addr { + union { + u8_t u8_addr[16]; + u32_t u32_addr[4]; + } un; +#define s6_addr un.u8_addr +}; + +#define IN6ADDR_ANY_INIT {0,0,0,0} +#define IN6ADDR_LOOPBACK_INIT {0,0,0,PP_HTONL(1)} + + +#define inet6_addr_from_ip6addr(target_in6addr, source_ip6addr) {(target_in6addr)->un.u32_addr[0] = (source_ip6addr)->addr[0]; \ + (target_in6addr)->un.u32_addr[1] = (source_ip6addr)->addr[1]; \ + (target_in6addr)->un.u32_addr[2] = (source_ip6addr)->addr[2]; \ + (target_in6addr)->un.u32_addr[3] = (source_ip6addr)->addr[3];} +#define inet6_addr_to_ip6addr(target_ip6addr, source_in6addr) {(target_ip6addr)->addr[0] = (source_in6addr)->un.u32_addr[0]; \ + (target_ip6addr)->addr[1] = (source_in6addr)->un.u32_addr[1]; \ + (target_ip6addr)->addr[2] = (source_in6addr)->un.u32_addr[2]; \ + (target_ip6addr)->addr[3] = (source_in6addr)->un.u32_addr[3];} +/* ATTENTION: the next define only works because both in6_addr and ip6_addr_t are an u32_t[4] effectively! */ +#define inet6_addr_to_ip6addr_p(target_ip6addr_p, source_in6addr) ((target_ip6addr_p) = (ip6_addr_t*)(source_in6addr)) + +/* directly map this to the lwip internal functions */ +#define inet6_aton(cp, addr) ip6addr_aton(cp, (ip6_addr_t*)addr) +#define inet6_ntoa(addr) ip6addr_ntoa((ip6_addr_t*)&(addr)) +#define inet6_ntoa_r(addr, buf, buflen) ip6addr_ntoa_r((ip6_addr_t*)&(addr), buf, buflen) + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV6 */ + +#endif /* LWIP_HDR_INET6_H */ + diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/inet_chksum.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/inet_chksum.h new file mode 100644 index 0000000..4171d0a --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/inet_chksum.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_INET_CHKSUM_H +#define LWIP_HDR_INET_CHKSUM_H + +#include "lwip/opt.h" + +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" + +/** Swap the bytes in an u16_t: much like htons() for little-endian */ +#ifndef SWAP_BYTES_IN_WORD +#if LWIP_PLATFORM_BYTESWAP && (BYTE_ORDER == LITTLE_ENDIAN) +/* little endian and PLATFORM_BYTESWAP defined */ +#define SWAP_BYTES_IN_WORD(w) LWIP_PLATFORM_HTONS(w) +#else /* LWIP_PLATFORM_BYTESWAP && (BYTE_ORDER == LITTLE_ENDIAN) */ +/* can't use htons on big endian (or PLATFORM_BYTESWAP not defined)... */ +#define SWAP_BYTES_IN_WORD(w) (((w) & 0xff) << 8) | (((w) & 0xff00) >> 8) +#endif /* LWIP_PLATFORM_BYTESWAP && (BYTE_ORDER == LITTLE_ENDIAN)*/ +#endif /* SWAP_BYTES_IN_WORD */ + +/** Split an u32_t in two u16_ts and add them up */ +#ifndef FOLD_U32T +#define FOLD_U32T(u) (((u) >> 16) + ((u) & 0x0000ffffUL)) +#endif + +#if LWIP_CHECKSUM_ON_COPY +/** Function-like macro: same as MEMCPY but returns the checksum of copied data + as u16_t */ +#ifndef LWIP_CHKSUM_COPY +#define LWIP_CHKSUM_COPY(dst, src, len) lwip_chksum_copy(dst, src, len) +#ifndef LWIP_CHKSUM_COPY_ALGORITHM +#define LWIP_CHKSUM_COPY_ALGORITHM 1 +#endif /* LWIP_CHKSUM_COPY_ALGORITHM */ +#endif /* LWIP_CHKSUM_COPY */ +#else /* LWIP_CHECKSUM_ON_COPY */ +#define LWIP_CHKSUM_COPY_ALGORITHM 0 +#endif /* LWIP_CHECKSUM_ON_COPY */ + +#ifdef __cplusplus +extern "C" { +#endif + +u16_t inet_chksum(void *dataptr, u16_t len); +u16_t inet_chksum_pbuf(struct pbuf *p); +u16_t inet_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, + ip_addr_t *src, ip_addr_t *dest); +u16_t inet_chksum_pseudo_partial(struct pbuf *p, u8_t proto, + u16_t proto_len, u16_t chksum_len, ip_addr_t *src, ip_addr_t *dest); +#if LWIP_CHKSUM_COPY_ALGORITHM +u16_t lwip_chksum_copy(void *dst, const void *src, u16_t len); +#endif /* LWIP_CHKSUM_COPY_ALGORITHM */ + +#if LWIP_IPV6 +u16_t ip6_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, + ip6_addr_t *src, ip6_addr_t *dest); +u16_t ip6_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len, + u16_t chksum_len, ip6_addr_t *src, ip6_addr_t *dest); + +#define ipX_chksum_pseudo(isipv6, p, proto, proto_len, src, dest) \ + ((isipv6) ? \ + ip6_chksum_pseudo(p, proto, proto_len, ipX_2_ip6(src), ipX_2_ip6(dest)) :\ + inet_chksum_pseudo(p, proto, proto_len, ipX_2_ip(src), ipX_2_ip(dest))) +#define ipX_chksum_pseudo_partial(isipv6, p, proto, proto_len, chksum_len, src, dest) \ + ((isipv6) ? \ + ip6_chksum_pseudo_partial(p, proto, proto_len, chksum_len, ipX_2_ip6(src), ipX_2_ip6(dest)) :\ + inet_chksum_pseudo_partial(p, proto, proto_len, chksum_len, ipX_2_ip(src), ipX_2_ip(dest))) + +#else /* LWIP_IPV6 */ + +#define ipX_chksum_pseudo(isipv6, p, proto, proto_len, src, dest) \ + inet_chksum_pseudo(p, proto, proto_len, src, dest) +#define ipX_chksum_pseudo_partial(isipv6, p, proto, proto_len, chksum_len, src, dest) \ + inet_chksum_pseudo_partial(p, proto, proto_len, chksum_len, src, dest) + +#endif /* LWIP_IPV6 */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_INET_H */ + diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/init.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/init.h new file mode 100644 index 0000000..0a35993 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/init.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_INIT_H +#define LWIP_HDR_INIT_H + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** X.x.x: Major version of the stack */ +#define LWIP_VERSION_MAJOR 1U +/** x.X.x: Minor version of the stack */ +#define LWIP_VERSION_MINOR 4U +/** x.x.X: Revision of the stack */ +#define LWIP_VERSION_REVISION 1U +/** For release candidates, this is set to 1..254 + * For official releases, this is set to 255 (LWIP_RC_RELEASE) + * For development versions (CVS), this is set to 0 (LWIP_RC_DEVELOPMENT) */ +#define LWIP_VERSION_RC 0U + +/** LWIP_VERSION_RC is set to LWIP_RC_RELEASE for official releases */ +#define LWIP_RC_RELEASE 255U +/** LWIP_VERSION_RC is set to LWIP_RC_DEVELOPMENT for CVS versions */ +#define LWIP_RC_DEVELOPMENT 0U + +#define LWIP_VERSION_IS_RELEASE (LWIP_VERSION_RC == LWIP_RC_RELEASE) +#define LWIP_VERSION_IS_DEVELOPMENT (LWIP_VERSION_RC == LWIP_RC_DEVELOPMENT) +#define LWIP_VERSION_IS_RC ((LWIP_VERSION_RC != LWIP_RC_RELEASE) && (LWIP_VERSION_RC != LWIP_RC_DEVELOPMENT)) + +/** Provides the version of the stack */ +#define LWIP_VERSION (LWIP_VERSION_MAJOR << 24 | LWIP_VERSION_MINOR << 16 | \ + LWIP_VERSION_REVISION << 8 | LWIP_VERSION_RC) + +/* Modules initialization */ +void lwip_init(void); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_INIT_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/ip4.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/ip4.h new file mode 100644 index 0000000..c49a771 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/ip4.h @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_IP4_H +#define LWIP_HDR_IP4_H + +#include "lwip/opt.h" + +#include "lwip/def.h" +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" +#include "lwip/ip6_addr.h" +#include "lwip/err.h" +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Currently, the function ip_output_if_opt() is only used with IGMP */ +#define IP_OPTIONS_SEND LWIP_IGMP + +#define IP_HLEN 20 + +#define IP_PROTO_ICMP 1 +#define IP_PROTO_IGMP 2 +#define IP_PROTO_UDP 17 +#define IP_PROTO_UDPLITE 136 +#define IP_PROTO_TCP 6 + + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip_hdr { + /* version / header length */ + PACK_STRUCT_FLD_8(u8_t _v_hl); + /* type of service */ + PACK_STRUCT_FLD_8(u8_t _tos); + /* total length */ + PACK_STRUCT_FIELD(u16_t _len); + /* identification */ + PACK_STRUCT_FIELD(u16_t _id); + /* fragment offset field */ + PACK_STRUCT_FIELD(u16_t _offset); +#define IP_RF 0x8000U /* reserved fragment flag */ +#define IP_DF 0x4000U /* don't fragment flag */ +#define IP_MF 0x2000U /* more fragments flag */ +#define IP_OFFMASK 0x1fffU /* mask for fragmenting bits */ + /* time to live */ + PACK_STRUCT_FLD_8(u8_t _ttl); + /* protocol*/ + PACK_STRUCT_FLD_8(u8_t _proto); + /* checksum */ + PACK_STRUCT_FIELD(u16_t _chksum); + /* source and destination IP addresses */ + PACK_STRUCT_FLD_S(ip_addr_p_t src); + PACK_STRUCT_FLD_S(ip_addr_p_t dest); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define IPH_V(hdr) ((hdr)->_v_hl >> 4) +#define IPH_HL(hdr) ((hdr)->_v_hl & 0x0f) +#define IPH_TOS(hdr) ((hdr)->_tos) +#define IPH_LEN(hdr) ((hdr)->_len) +#define IPH_ID(hdr) ((hdr)->_id) +#define IPH_OFFSET(hdr) ((hdr)->_offset) +#define IPH_TTL(hdr) ((hdr)->_ttl) +#define IPH_PROTO(hdr) ((hdr)->_proto) +#define IPH_CHKSUM(hdr) ((hdr)->_chksum) + +#define IPH_VHL_SET(hdr, v, hl) (hdr)->_v_hl = (((v) << 4) | (hl)) +#define IPH_TOS_SET(hdr, tos) (hdr)->_tos = (tos) +#define IPH_LEN_SET(hdr, len) (hdr)->_len = (len) +#define IPH_ID_SET(hdr, id) (hdr)->_id = (id) +#define IPH_OFFSET_SET(hdr, off) (hdr)->_offset = (off) +#define IPH_TTL_SET(hdr, ttl) (hdr)->_ttl = (u8_t)(ttl) +#define IPH_PROTO_SET(hdr, proto) (hdr)->_proto = (u8_t)(proto) +#define IPH_CHKSUM_SET(hdr, chksum) (hdr)->_chksum = (chksum) + + +#define ip_init() /* Compatibility define, no init needed. */ +struct netif *ip_route(ip_addr_t *dest); +err_t ip_input(struct pbuf *p, struct netif *inp); +err_t ip_output(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto); +err_t ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif *netif); +err_t ip_output_if_src(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif *netif); +#if LWIP_NETIF_HWADDRHINT +err_t ip_output_hinted(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint); +#endif /* LWIP_NETIF_HWADDRHINT */ +#if IP_OPTIONS_SEND +err_t ip_output_if_opt(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, + u16_t optlen); +err_t ip_output_if_opt_src(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, + u16_t optlen); +#endif /* IP_OPTIONS_SEND */ + +#define ip_netif_get_local_ipX(netif) (((netif) != NULL) ? ip_2_ipX(&((netif)->ip_addr)) : NULL) + +#if IP_DEBUG +void ip_debug_print(struct pbuf *p); +#else +#define ip_debug_print(p) +#endif /* IP_DEBUG */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_IP_H */ + + diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/ip4_addr.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/ip4_addr.h new file mode 100644 index 0000000..6f6318b --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/ip4_addr.h @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_IP4_ADDR_H +#define LWIP_HDR_IP4_ADDR_H + +#include "lwip/opt.h" +#include "lwip/def.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* This is the aligned version of ip_addr_t, + used as local variable, on the stack, etc. */ +struct ip_addr { + u32_t addr; +}; + +/* This is the packed version of ip_addr_t, + used in network headers that are itself packed */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip_addr_packed { + PACK_STRUCT_FIELD(u32_t addr); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** ip_addr_t uses a struct for convenience only, so that the same defines can + * operate both on ip_addr_t as well as on ip_addr_p_t. */ +typedef struct ip_addr ip_addr_t; +typedef struct ip_addr_packed ip_addr_p_t; + +/* + * struct ipaddr2 is used in the definition of the ARP packet format in + * order to support compilers that don't have structure packing. + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip_addr2 { + PACK_STRUCT_FIELD(u16_t addrw[2]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* Forward declaration to not include netif.h */ +struct netif; + +extern const ip_addr_t ip_addr_any; +extern const ip_addr_t ip_addr_broadcast; + +/** IP_ADDR_ can be used as a fixed IP address + * for the wildcard and the broadcast address + */ +#define IP_ADDR_ANY ((ip_addr_t *)&ip_addr_any) +#define IP_ADDR_BROADCAST ((ip_addr_t *)&ip_addr_broadcast) + +/** 255.255.255.255 */ +#define IPADDR_NONE ((u32_t)0xffffffffUL) +/** 127.0.0.1 */ +#define IPADDR_LOOPBACK ((u32_t)0x7f000001UL) +/** 0.0.0.0 */ +#define IPADDR_ANY ((u32_t)0x00000000UL) +/** 255.255.255.255 */ +#define IPADDR_BROADCAST ((u32_t)0xffffffffUL) + +/* Definitions of the bits in an Internet address integer. + + On subnets, host and network parts are found according to + the subnet mask, not these masks. */ +#define IP_CLASSA(a) ((((u32_t)(a)) & 0x80000000UL) == 0) +#define IP_CLASSA_NET 0xff000000 +#define IP_CLASSA_NSHIFT 24 +#define IP_CLASSA_HOST (0xffffffff & ~IP_CLASSA_NET) +#define IP_CLASSA_MAX 128 + +#define IP_CLASSB(a) ((((u32_t)(a)) & 0xc0000000UL) == 0x80000000UL) +#define IP_CLASSB_NET 0xffff0000 +#define IP_CLASSB_NSHIFT 16 +#define IP_CLASSB_HOST (0xffffffff & ~IP_CLASSB_NET) +#define IP_CLASSB_MAX 65536 + +#define IP_CLASSC(a) ((((u32_t)(a)) & 0xe0000000UL) == 0xc0000000UL) +#define IP_CLASSC_NET 0xffffff00 +#define IP_CLASSC_NSHIFT 8 +#define IP_CLASSC_HOST (0xffffffff & ~IP_CLASSC_NET) + +#define IP_CLASSD(a) (((u32_t)(a) & 0xf0000000UL) == 0xe0000000UL) +#define IP_CLASSD_NET 0xf0000000 /* These ones aren't really */ +#define IP_CLASSD_NSHIFT 28 /* net and host fields, but */ +#define IP_CLASSD_HOST 0x0fffffff /* routing needn't know. */ +#define IP_MULTICAST(a) IP_CLASSD(a) + +#define IP_EXPERIMENTAL(a) (((u32_t)(a) & 0xf0000000UL) == 0xf0000000UL) +#define IP_BADCLASS(a) (((u32_t)(a) & 0xf0000000UL) == 0xf0000000UL) + +#define IP_LOOPBACKNET 127 /* official! */ + + +#if BYTE_ORDER == BIG_ENDIAN +/** Set an IP address given by the four byte-parts */ +#define IP4_ADDR(ipaddr, a,b,c,d) \ + (ipaddr)->addr = ((u32_t)((a) & 0xff) << 24) | \ + ((u32_t)((b) & 0xff) << 16) | \ + ((u32_t)((c) & 0xff) << 8) | \ + (u32_t)((d) & 0xff) +#else +/** Set an IP address given by the four byte-parts. + Little-endian version that prevents the use of htonl. */ +#define IP4_ADDR(ipaddr, a,b,c,d) \ + (ipaddr)->addr = ((u32_t)((d) & 0xff) << 24) | \ + ((u32_t)((c) & 0xff) << 16) | \ + ((u32_t)((b) & 0xff) << 8) | \ + (u32_t)((a) & 0xff) +#endif + +/** MEMCPY-like copying of IP addresses where addresses are known to be + * 16-bit-aligned if the port is correctly configured (so a port could define + * this to copying 2 u16_t's) - no NULL-pointer-checking needed. */ +#ifndef IPADDR2_COPY +#define IPADDR2_COPY(dest, src) SMEMCPY(dest, src, sizeof(ip_addr_t)) +#endif + +/** Copy IP address - faster than ip_addr_set: no NULL check */ +#define ip_addr_copy(dest, src) ((dest).addr = (src).addr) +/** Safely copy one IP address to another (src may be NULL) */ +#define ip_addr_set(dest, src) ((dest)->addr = \ + ((src) == NULL ? 0 : \ + (src)->addr)) +/** Set complete address to zero */ +#define ip_addr_set_zero(ipaddr) ((ipaddr)->addr = 0) +/** Set address to IPADDR_ANY (no need for htonl()) */ +#define ip_addr_set_any(ipaddr) ((ipaddr)->addr = IPADDR_ANY) +/** Set address to loopback address */ +#define ip_addr_set_loopback(ipaddr) ((ipaddr)->addr = PP_HTONL(IPADDR_LOOPBACK)) +/** Safely copy one IP address to another and change byte order + * from host- to network-order. */ +#define ip_addr_set_hton(dest, src) ((dest)->addr = \ + ((src) == NULL ? 0:\ + htonl((src)->addr))) +/** IPv4 only: set the IP address given as an u32_t */ +#define ip4_addr_set_u32(dest_ipaddr, src_u32) ((dest_ipaddr)->addr = (src_u32)) +/** IPv4 only: get the IP address as an u32_t */ +#define ip4_addr_get_u32(src_ipaddr) ((src_ipaddr)->addr) + +/** Get the network address by combining host address with netmask */ +#define ip_addr_get_network(target, host, netmask) ((target)->addr = ((host)->addr) & ((netmask)->addr)) + +/** + * Determine if two address are on the same network. + * + * @arg addr1 IP address 1 + * @arg addr2 IP address 2 + * @arg mask network identifier mask + * @return !0 if the network identifiers of both address match + */ +#define ip_addr_netcmp(addr1, addr2, mask) (((addr1)->addr & \ + (mask)->addr) == \ + ((addr2)->addr & \ + (mask)->addr)) +#define ip_addr_cmp(addr1, addr2) ((addr1)->addr == (addr2)->addr) + +#define ip_addr_isany(addr1) ((addr1) == NULL || (addr1)->addr == IPADDR_ANY) + +#define ip_addr_isbroadcast(ipaddr, netif) ip4_addr_isbroadcast((ipaddr)->addr, (netif)) +u8_t ip4_addr_isbroadcast(u32_t addr, const struct netif *netif); + +#define ip_addr_netmask_valid(netmask) ip4_addr_netmask_valid((netmask)->addr) +u8_t ip4_addr_netmask_valid(u32_t netmask); + +#define ip_addr_ismulticast(addr1) (((addr1)->addr & PP_HTONL(0xf0000000UL)) == PP_HTONL(0xe0000000UL)) + +#define ip_addr_islinklocal(addr1) (((addr1)->addr & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xa9fe0000UL)) + +#define ip_addr_debug_print(debug, ipaddr) \ + LWIP_DEBUGF(debug, ("%" U16_F ".%" U16_F ".%" U16_F ".%" U16_F, \ + ipaddr != NULL ? ip4_addr1_16(ipaddr) : 0, \ + ipaddr != NULL ? ip4_addr2_16(ipaddr) : 0, \ + ipaddr != NULL ? ip4_addr3_16(ipaddr) : 0, \ + ipaddr != NULL ? ip4_addr4_16(ipaddr) : 0)) + +/* Get one byte from the 4-byte address */ +#define ip4_addr1(ipaddr) (((u8_t*)(ipaddr))[0]) +#define ip4_addr2(ipaddr) (((u8_t*)(ipaddr))[1]) +#define ip4_addr3(ipaddr) (((u8_t*)(ipaddr))[2]) +#define ip4_addr4(ipaddr) (((u8_t*)(ipaddr))[3]) +/* These are cast to u16_t, with the intent that they are often arguments + * to printf using the U16_F format from cc.h. */ +#define ip4_addr1_16(ipaddr) ((u16_t)ip4_addr1(ipaddr)) +#define ip4_addr2_16(ipaddr) ((u16_t)ip4_addr2(ipaddr)) +#define ip4_addr3_16(ipaddr) ((u16_t)ip4_addr3(ipaddr)) +#define ip4_addr4_16(ipaddr) ((u16_t)ip4_addr4(ipaddr)) + +#define IP4ADDR_STRLEN_MAX 16 +#define IPADDR_STRLEN_MAX IP4ADDR_STRLEN_MAX + +/** For backwards compatibility */ +#define ip_ntoa(ipaddr) ipaddr_ntoa(ipaddr) + +u32_t ipaddr_addr(const char *cp); +int ipaddr_aton(const char *cp, ip_addr_t *addr); +/** returns ptr to static buffer; not reentrant! */ +char *ipaddr_ntoa(const ip_addr_t *addr); +char *ipaddr_ntoa_r(const ip_addr_t *addr, char *buf, int buflen); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_IP_ADDR_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/ip6.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/ip6.h new file mode 100644 index 0000000..a7b264f --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/ip6.h @@ -0,0 +1,198 @@ +/** + * @file + * + * IPv6 layer. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ +#ifndef LWIP_HDR_IP6_H +#define LWIP_HDR_IP6_H + +#include "lwip/opt.h" + +#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/ip6_addr.h" +#include "lwip/def.h" +#include "lwip/pbuf.h" +#include "lwip/netif.h" + +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define IP6_HLEN 40 + +#define IP6_NEXTH_HOPBYHOP 0 +#define IP6_NEXTH_TCP 6 +#define IP6_NEXTH_UDP 17 +#define IP6_NEXTH_ENCAPS 41 +#define IP6_NEXTH_ROUTING 43 +#define IP6_NEXTH_FRAGMENT 44 +#define IP6_NEXTH_ICMP6 58 +#define IP6_NEXTH_NONE 59 +#define IP6_NEXTH_DESTOPTS 60 +#define IP6_NEXTH_UDPLITE 136 + + +/* The IPv6 header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip6_hdr { + /* version / traffic class / flow label */ + PACK_STRUCT_FIELD(u32_t _v_tc_fl); + /* payload length */ + PACK_STRUCT_FIELD(u16_t _plen); + /* next header */ + PACK_STRUCT_FLD_8(u8_t _nexth); + /* hop limit */ + PACK_STRUCT_FLD_8(u8_t _hoplim); + /* source and destination IP addresses */ + PACK_STRUCT_FLD_S(ip6_addr_p_t src); + PACK_STRUCT_FLD_S(ip6_addr_p_t dest); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* Hop-by-hop router alert option. */ +#define IP6_HBH_HLEN 8 +#define IP6_PAD1_OPTION 0 +#define IP6_PADN_ALERT_OPTION 1 +#define IP6_ROUTER_ALERT_OPTION 5 +#define IP6_ROUTER_ALERT_VALUE_MLD 0 +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip6_hbh_hdr { + /* next header */ + PACK_STRUCT_FLD_8(u8_t _nexth); + /* header length */ + PACK_STRUCT_FLD_8(u8_t _hlen); + /* router alert option type */ + PACK_STRUCT_FLD_8(u8_t _ra_opt_type); + /* router alert option data len */ + PACK_STRUCT_FLD_8(u8_t _ra_opt_dlen); + /* router alert option data */ + PACK_STRUCT_FIELD(u16_t _ra_opt_data); + /* PadN option type */ + PACK_STRUCT_FLD_8(u8_t _padn_opt_type); + /* PadN option data len */ + PACK_STRUCT_FLD_8(u8_t _padn_opt_dlen); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* Fragment header. */ +#define IP6_FRAG_HLEN 8 +#define IP6_FRAG_OFFSET_MASK 0xfff8 +#define IP6_FRAG_MORE_FLAG 0x0001 +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip6_frag_hdr { + /* next header */ + PACK_STRUCT_FLD_8(u8_t _nexth); + /* reserved */ + PACK_STRUCT_FLD_8(u8_t reserved); + /* fragment offset */ + PACK_STRUCT_FIELD(u16_t _fragment_offset); + /* fragmented packet identification */ + PACK_STRUCT_FIELD(u32_t _identification); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define IP6H_V(hdr) ((ntohl((hdr)->_v_tc_fl) >> 28) & 0x0f) +#define IP6H_TC(hdr) ((ntohl((hdr)->_v_tc_fl) >> 20) & 0xff) +#define IP6H_FL(hdr) (ntohl((hdr)->_v_tc_fl) & 0x000fffff) +#define IP6H_PLEN(hdr) (ntohs((hdr)->_plen)) +#define IP6H_NEXTH(hdr) ((hdr)->_nexth) +#define IP6H_NEXTH_P(hdr) ((u8_t *)(hdr) + 6) +#define IP6H_HOPLIM(hdr) ((hdr)->_hoplim) + +#define IP6H_VTCFL_SET(hdr, v, tc, fl) (hdr)->_v_tc_fl = (htonl((((u32_t)(v)) << 28) | (((u32_t)(tc)) << 20) | (fl))) +#define IP6H_PLEN_SET(hdr, plen) (hdr)->_plen = htons(plen) +#define IP6H_NEXTH_SET(hdr, nexth) (hdr)->_nexth = (nexth) +#define IP6H_HOPLIM_SET(hdr, hl) (hdr)->_hoplim = (u8_t)(hl) + + +#define ip6_init() /* TODO should we init current addresses and header pointer? */ +struct netif *ip6_route(struct ip6_addr *src, struct ip6_addr *dest); +ip6_addr_t *ip6_select_source_address(struct netif *netif, ip6_addr_t * dest); +err_t ip6_input(struct pbuf *p, struct netif *inp); +err_t ip6_output(struct pbuf *p, struct ip6_addr *src, struct ip6_addr *dest, + u8_t hl, u8_t tc, u8_t nexth); +err_t ip6_output_if(struct pbuf *p, struct ip6_addr *src, struct ip6_addr *dest, + u8_t hl, u8_t tc, u8_t nexth, struct netif *netif); +err_t ip6_output_if_src(struct pbuf *p, struct ip6_addr *src, struct ip6_addr *dest, + u8_t hl, u8_t tc, u8_t nexth, struct netif *netif); +#if LWIP_NETIF_HWADDRHINT +err_t ip6_output_hinted(struct pbuf *p, ip6_addr_t *src, ip6_addr_t *dest, + u8_t hl, u8_t tc, u8_t nexth, u8_t *addr_hint); +#endif /* LWIP_NETIF_HWADDRHINT */ +#if LWIP_IPV6_MLD +err_t ip6_options_add_hbh_ra(struct pbuf * p, u8_t nexth, u8_t value); +#endif /* LWIP_IPV6_MLD */ + +#define ip6_netif_get_local_ipX(netif, dest) (((netif) != NULL) ? \ + ip6_2_ipX(ip6_select_source_address(netif, dest)) : NULL) + +#if IP6_DEBUG +void ip6_debug_print(struct pbuf *p); +#else +#define ip6_debug_print(p) +#endif /* IP6_DEBUG */ + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV6 */ + +#endif /* LWIP_HDR_IP6_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/ip6_addr.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/ip6_addr.h new file mode 100644 index 0000000..ace219c --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/ip6_addr.h @@ -0,0 +1,289 @@ +/** + * @file + * + * IPv6 addresses. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * Structs and macros for handling IPv6 addresses. + * + * Please coordinate changes and requests with Ivan Delamer + * + */ +#ifndef LWIP_HDR_IP6_ADDR_H +#define LWIP_HDR_IP6_ADDR_H + +#include "lwip/opt.h" + +#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* This is the aligned version of ip6_addr_t, + used as local variable, on the stack, etc. */ +struct ip6_addr { + u32_t addr[4]; +}; + +/* This is the packed version of ip6_addr_t, + used in network headers that are itself packed */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip6_addr_packed { + PACK_STRUCT_FIELD(u32_t addr[4]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** ip6_addr_t uses a struct for convenience only, so that the same defines can + * operate both on ip6_addr_t as well as on ip6_addr_p_t. */ +typedef struct ip6_addr ip6_addr_t; +typedef struct ip6_addr_packed ip6_addr_p_t; + + +/** IP6_ADDR_ANY can be used as a fixed IPv6 address + * for the wildcard + */ +extern const ip6_addr_t ip6_addr_any; +#define IP6_ADDR_ANY ((ip6_addr_t *)&ip6_addr_any) + + +#if BYTE_ORDER == BIG_ENDIAN +/** Set an IPv6 partial address given by byte-parts. */ +#define IP6_ADDR(ip6addr, index, a,b,c,d) \ + (ip6addr)->addr[index] = ((u32_t)((a) & 0xff) << 24) | \ + ((u32_t)((b) & 0xff) << 16) | \ + ((u32_t)((c) & 0xff) << 8) | \ + (u32_t)((d) & 0xff) +#else +/** Set an IPv6 partial address given by byte-parts. +Little-endian version, stored in network order (no htonl). */ +#define IP6_ADDR(ip6addr, index, a,b,c,d) \ + (ip6addr)->addr[index] = ((u32_t)((d) & 0xff) << 24) | \ + ((u32_t)((c) & 0xff) << 16) | \ + ((u32_t)((b) & 0xff) << 8) | \ + (u32_t)((a) & 0xff) +#endif + +/** Access address in 16-bit block */ +#define IP6_ADDR_BLOCK1(ip6addr) ((u16_t)(htonl((ip6addr)->addr[0]) >> 16) & 0xffff) +#define IP6_ADDR_BLOCK2(ip6addr) ((u16_t)(htonl((ip6addr)->addr[0])) & 0xffff) +#define IP6_ADDR_BLOCK3(ip6addr) ((u16_t)(htonl((ip6addr)->addr[1]) >> 16) & 0xffff) +#define IP6_ADDR_BLOCK4(ip6addr) ((u16_t)(htonl((ip6addr)->addr[1])) & 0xffff) +#define IP6_ADDR_BLOCK5(ip6addr) ((u16_t)(htonl((ip6addr)->addr[2]) >> 16) & 0xffff) +#define IP6_ADDR_BLOCK6(ip6addr) ((u16_t)(htonl((ip6addr)->addr[2])) & 0xffff) +#define IP6_ADDR_BLOCK7(ip6addr) ((u16_t)(htonl((ip6addr)->addr[3]) >> 16) & 0xffff) +#define IP6_ADDR_BLOCK8(ip6addr) ((u16_t)(htonl((ip6addr)->addr[3])) & 0xffff) + +/** Copy IPv6 address - faster than ip6_addr_set: no NULL check */ +#define ip6_addr_copy(dest, src) do{(dest).addr[0] = (src).addr[0]; \ + (dest).addr[1] = (src).addr[1]; \ + (dest).addr[2] = (src).addr[2]; \ + (dest).addr[3] = (src).addr[3];}while(0) +/** Safely copy one IPv6 address to another (src may be NULL) */ +#define ip6_addr_set(dest, src) do{(dest)->addr[0] = (src) == NULL ? 0 : (src)->addr[0]; \ + (dest)->addr[1] = (src) == NULL ? 0 : (src)->addr[1]; \ + (dest)->addr[2] = (src) == NULL ? 0 : (src)->addr[2]; \ + (dest)->addr[3] = (src) == NULL ? 0 : (src)->addr[3];}while(0) + +/** Set complete address to zero */ +#define ip6_addr_set_zero(ip6addr) do{(ip6addr)->addr[0] = 0; \ + (ip6addr)->addr[1] = 0; \ + (ip6addr)->addr[2] = 0; \ + (ip6addr)->addr[3] = 0;}while(0) + +/** Set address to ipv6 'any' (no need for htonl()) */ +#define ip6_addr_set_any(ip6addr) ip6_addr_set_zero(ip6addr) +/** Set address to ipv6 loopback address */ +#define ip6_addr_set_loopback(ip6addr) do{(ip6addr)->addr[0] = 0; \ + (ip6addr)->addr[1] = 0; \ + (ip6addr)->addr[2] = 0; \ + (ip6addr)->addr[3] = PP_HTONL(0x00000001UL);}while(0) +/** Safely copy one IPv6 address to another and change byte order + * from host- to network-order. */ +#define ip6_addr_set_hton(dest, src) do{(dest)->addr[0] = (src) == NULL ? 0 : htonl((src)->addr[0]); \ + (dest)->addr[1] = (src) == NULL ? 0 : htonl((src)->addr[1]); \ + (dest)->addr[2] = (src) == NULL ? 0 : htonl((src)->addr[2]); \ + (dest)->addr[3] = (src) == NULL ? 0 : htonl((src)->addr[3]);}while(0) + + +/** + * Determine if two IPv6 address are on the same network. + * + * @arg addr1 IPv6 address 1 + * @arg addr2 IPv6 address 2 + * @return !0 if the network identifiers of both address match + */ +#define ip6_addr_netcmp(addr1, addr2) (((addr1)->addr[0] == (addr2)->addr[0]) && \ + ((addr1)->addr[1] == (addr2)->addr[1])) + +#define ip6_addr_cmp(addr1, addr2) (((addr1)->addr[0] == (addr2)->addr[0]) && \ + ((addr1)->addr[1] == (addr2)->addr[1]) && \ + ((addr1)->addr[2] == (addr2)->addr[2]) && \ + ((addr1)->addr[3] == (addr2)->addr[3])) + +#define ip6_get_subnet_id(ip6addr) (htonl((ip6addr)->addr[2]) & 0x0000ffffUL) + +#define ip6_addr_isany(ip6addr) (((ip6addr) == NULL) || \ + (((ip6addr)->addr[0] == 0) && \ + ((ip6addr)->addr[1] == 0) && \ + ((ip6addr)->addr[2] == 0) && \ + ((ip6addr)->addr[3] == 0))) + +#define ip6_addr_isloopback(ip6addr) (((ip6addr)->addr[0] == 0UL) && \ + ((ip6addr)->addr[1] == 0UL) && \ + ((ip6addr)->addr[2] == 0UL) && \ + ((ip6addr)->addr[3] == PP_HTONL(0x00000001UL))) + +#define ip6_addr_isglobal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xe0000000UL)) == PP_HTONL(0x20000000UL)) + +#define ip6_addr_islinklocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffc00000UL)) == PP_HTONL(0xfe800000UL)) + +#define ip6_addr_issitelocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffc00000UL)) == PP_HTONL(0xfec00000UL)) + +#define ip6_addr_isuniquelocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xfe000000UL)) == PP_HTONL(0xfc000000UL)) + +#define ip6_addr_ismulticast(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff000000UL)) == PP_HTONL(0xff000000UL)) +#define ip6_addr_multicast_transient_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00100000UL)) +#define ip6_addr_multicast_prefix_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00200000UL)) +#define ip6_addr_multicast_rendezvous_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00400000UL)) +#define ip6_addr_multicast_scope(ip6addr) ((htonl((ip6addr)->addr[0]) >> 16) & 0xf) +#define IP6_MULTICAST_SCOPE_RESERVED 0x0 +#define IP6_MULTICAST_SCOPE_RESERVED0 0x0 +#define IP6_MULTICAST_SCOPE_INTERFACE_LOCAL 0x1 +#define IP6_MULTICAST_SCOPE_LINK_LOCAL 0x2 +#define IP6_MULTICAST_SCOPE_RESERVED3 0x3 +#define IP6_MULTICAST_SCOPE_ADMIN_LOCAL 0x4 +#define IP6_MULTICAST_SCOPE_SITE_LOCAL 0x5 +#define IP6_MULTICAST_SCOPE_ORGANIZATION_LOCAL 0x8 +#define IP6_MULTICAST_SCOPE_GLOBAL 0xe +#define IP6_MULTICAST_SCOPE_RESERVEDF 0xf +#define ip6_addr_ismulticast_iflocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xff010000UL)) +#define ip6_addr_ismulticast_linklocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xff020000UL)) +#define ip6_addr_ismulticast_adminlocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xff040000UL)) +#define ip6_addr_ismulticast_sitelocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xff050000UL)) +#define ip6_addr_ismulticast_orglocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xff080000UL)) +#define ip6_addr_ismulticast_global(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xff0e0000UL)) + +/* TODO define get/set for well-know multicast addresses, e.g. ff02::1 */ +#define ip6_addr_isallnodes_iflocal(ip6addr) (((ip6addr)->addr[0] == PP_HTONL(0xff010000UL)) && \ + ((ip6addr)->addr[1] == 0UL) && \ + ((ip6addr)->addr[2] == 0UL) && \ + ((ip6addr)->addr[3] == PP_HTONL(0x00000001UL))) + +#define ip6_addr_isallnodes_linklocal(ip6addr) (((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \ + ((ip6addr)->addr[1] == 0UL) && \ + ((ip6addr)->addr[2] == 0UL) && \ + ((ip6addr)->addr[3] == PP_HTONL(0x00000001UL))) +#define ip6_addr_set_allnodes_linklocal(ip6addr) do{(ip6addr)->addr[0] = PP_HTONL(0xff020000UL); \ + (ip6addr)->addr[1] = 0; \ + (ip6addr)->addr[2] = 0; \ + (ip6addr)->addr[3] = PP_HTONL(0x00000001UL);}while(0) + +#define ip6_addr_isallrouters_linklocal(ip6addr) (((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \ + ((ip6addr)->addr[1] == 0UL) && \ + ((ip6addr)->addr[2] == 0UL) && \ + ((ip6addr)->addr[3] == PP_HTONL(0x00000002UL))) +#define ip6_addr_set_allrouters_linklocal(ip6addr) do{(ip6addr)->addr[0] = PP_HTONL(0xff020000UL); \ + (ip6addr)->addr[1] = 0; \ + (ip6addr)->addr[2] = 0; \ + (ip6addr)->addr[3] = PP_HTONL(0x00000002UL);}while(0) + +#define ip6_addr_issolicitednode(ip6addr) ( ((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \ + ((ip6addr)->addr[2] == PP_HTONL(0x00000001UL)) && \ + (((ip6addr)->addr[3] & PP_HTONL(0xff000000UL)) == PP_HTONL(0xff000000UL)) ) + +#define ip6_addr_set_solicitednode(ip6addr, if_id) do{(ip6addr)->addr[0] = PP_HTONL(0xff020000UL); \ + (ip6addr)->addr[1] = 0; \ + (ip6addr)->addr[2] = PP_HTONL(0x00000001UL); \ + (ip6addr)->addr[3] = (PP_HTONL(0xff000000UL) | (if_id));}while(0) + +#define ip6_addr_cmp_solicitednode(ip6addr, sn_addr) (((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \ + ((ip6addr)->addr[1] == 0) && \ + ((ip6addr)->addr[2] == PP_HTONL(0x00000001UL)) && \ + ((ip6addr)->addr[3] == (PP_HTONL(0xff000000UL) | (sn_addr)->addr[3]))) + +/* IPv6 address states. */ +#define IP6_ADDR_INVALID 0x00 +#define IP6_ADDR_TENTATIVE 0x08 +#define IP6_ADDR_TENTATIVE_1 0x09 /* 1 probe sent */ +#define IP6_ADDR_TENTATIVE_2 0x0a /* 2 probes sent */ +#define IP6_ADDR_TENTATIVE_3 0x0b /* 3 probes sent */ +#define IP6_ADDR_TENTATIVE_4 0x0c /* 4 probes sent */ +#define IP6_ADDR_TENTATIVE_5 0x0d /* 5 probes sent */ +#define IP6_ADDR_TENTATIVE_6 0x0e /* 6 probes sent */ +#define IP6_ADDR_TENTATIVE_7 0x0f /* 7 probes sent */ +#define IP6_ADDR_VALID 0x10 +#define IP6_ADDR_PREFERRED 0x30 +#define IP6_ADDR_DEPRECATED 0x50 + +#define ip6_addr_isinvalid(addr_state) (addr_state == IP6_ADDR_INVALID) +#define ip6_addr_istentative(addr_state) (addr_state & IP6_ADDR_TENTATIVE) +#define ip6_addr_isvalid(addr_state) (addr_state & IP6_ADDR_VALID) /* Include valid, preferred, and deprecated. */ +#define ip6_addr_ispreferred(addr_state) (addr_state == IP6_ADDR_PREFERRED) +#define ip6_addr_isdeprecated(addr_state) (addr_state == IP6_ADDR_DEPRECATED) + +#define ip6_addr_debug_print(debug, ipaddr) \ + LWIP_DEBUGF(debug, ("%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F, \ + ipaddr != NULL ? IP6_ADDR_BLOCK1(ipaddr) : 0, \ + ipaddr != NULL ? IP6_ADDR_BLOCK2(ipaddr) : 0, \ + ipaddr != NULL ? IP6_ADDR_BLOCK3(ipaddr) : 0, \ + ipaddr != NULL ? IP6_ADDR_BLOCK4(ipaddr) : 0, \ + ipaddr != NULL ? IP6_ADDR_BLOCK5(ipaddr) : 0, \ + ipaddr != NULL ? IP6_ADDR_BLOCK6(ipaddr) : 0, \ + ipaddr != NULL ? IP6_ADDR_BLOCK7(ipaddr) : 0, \ + ipaddr != NULL ? IP6_ADDR_BLOCK8(ipaddr) : 0)) + +#define IP6ADDR_STRLEN_MAX 46 + +int ip6addr_aton(const char *cp, ip6_addr_t *addr); +/** returns ptr to static buffer; not reentrant! */ +char *ip6addr_ntoa(const ip6_addr_t *addr); +char *ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen); + + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV6 */ + +#endif /* LWIP_HDR_IP6_ADDR_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/ip6_frag.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/ip6_frag.h new file mode 100644 index 0000000..9987914 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/ip6_frag.h @@ -0,0 +1,102 @@ +/** + * @file + * + * IPv6 fragmentation and reassembly. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ +#ifndef LWIP_HDR_IP6_FRAG_H +#define LWIP_HDR_IP6_FRAG_H + +#include "lwip/opt.h" +#include "lwip/pbuf.h" +#include "lwip/ip6_addr.h" +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#if LWIP_IPV6 && LWIP_IPV6_REASS /* don't build if not configured for use in lwipopts.h */ + +/* The IPv6 reassembly timer interval in milliseconds. */ +#define IP6_REASS_TMR_INTERVAL 1000 + +/* IPv6 reassembly helper struct. + * This is exported because memp needs to know the size. + */ +struct ip6_reassdata { + struct ip6_reassdata *next; + struct pbuf *p; + struct ip6_hdr * iphdr; + u32_t identification; + u16_t datagram_len; + u8_t nexth; + u8_t timer; +}; + +#define ip6_reass_init() /* Compatibility define */ +void ip6_reass_tmr(void); +struct pbuf * ip6_reass(struct pbuf *p); + +#endif /* LWIP_IPV6 && LWIP_IPV6_REASS */ + +#if LWIP_IPV6 && LWIP_IPV6_FRAG /* don't build if not configured for use in lwipopts.h */ + +/** A custom pbuf that holds a reference to another pbuf, which is freed + * when this custom pbuf is freed. This is used to create a custom PBUF_REF + * that points into the original pbuf. */ +#ifndef LWIP_PBUF_CUSTOM_REF_DEFINED +#define LWIP_PBUF_CUSTOM_REF_DEFINED +struct pbuf_custom_ref { + /** 'base class' */ + struct pbuf_custom pc; + /** pointer to the original pbuf that is referenced */ + struct pbuf *original; +}; +#endif /* LWIP_PBUF_CUSTOM_REF_DEFINED */ + +err_t ip6_frag(struct pbuf *p, struct netif *netif, ip6_addr_t *dest); + +#endif /* LWIP_IPV6 && LWIP_IPV6_FRAG */ + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_IP6_FRAG_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/ip_addr.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/ip_addr.h new file mode 100644 index 0000000..1ded93f --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/ip_addr.h @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_IP_ADDR_H__ +#define LWIP_HDR_IP_ADDR_H__ + +#include "lwip/opt.h" +#include "lwip/def.h" + +#include "lwip/ip4_addr.h" +#include "lwip/ip6_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_IPV6 +/* A union struct for both IP version's addresses. */ +typedef union { + ip_addr_t ip4; + ip6_addr_t ip6; +} ipX_addr_t; + +/** These functions only exist for type-safe conversion from ip_addr_t to + ip6_addr_t and back */ +#ifdef LWIP_ALLOW_STATIC_FN_IN_HEADER +static ip6_addr_t* ip_2_ip6(ip_addr_t *ipaddr) +{ return (ip6_addr_t*)ipaddr;} +static ip_addr_t* ip6_2_ip(ip6_addr_t *ip6addr) +{ return (ip_addr_t*)ip6addr; } +static ipX_addr_t* ip_2_ipX(ip_addr_t *ipaddr) +{ return (ipX_addr_t*)ipaddr; } +static ipX_addr_t* ip6_2_ipX(ip6_addr_t *ip6addr) +{ return (ipX_addr_t*)ip6addr; } +#else /* LWIP_ALLOW_STATIC_FN_IN_HEADER */ +#define ip_2_ip6(ipaddr) ((ip6_addr_t*)(ipaddr)) +#define ip6_2_ip(ip6addr) ((ip_addr_t*)(ip6addr)) +#define ip_2_ipX(ipaddr) ((ipX_addr_t*)ipaddr) +#define ip6_2_ipX(ip6addr) ((ipX_addr_t*)ip6addr) +#endif /* LWIP_ALLOW_STATIC_FN_IN_HEADER*/ +#define ipX_2_ip6(ip6addr) (&((ip6addr)->ip6)) +#define ipX_2_ip(ipaddr) (&((ipaddr)->ip4)) + +#define ipX_addr_copy(is_ipv6, dest, src) do{if(is_ipv6){ \ + ip6_addr_copy((dest).ip6, (src).ip6); }else{ \ + ip_addr_copy((dest).ip4, (src).ip4); }}while(0) +#define ipX_addr_set(is_ipv6, dest, src) do{if(is_ipv6){ \ + ip6_addr_set(ipX_2_ip6(dest), ipX_2_ip6(src)); }else{ \ + ip_addr_set(ipX_2_ip(dest), ipX_2_ip(src)); }}while(0) +#define ipX_addr_set_ipaddr(is_ipv6, dest, src) do{if(is_ipv6){ \ + ip6_addr_set(ipX_2_ip6(dest), ip_2_ip6(src)); }else{ \ + ip_addr_set(ipX_2_ip(dest), src); }}while(0) +#define ipX_addr_set_zero(is_ipv6, ipaddr) do{if(is_ipv6){ \ + ip6_addr_set_zero(ipX_2_ip6(ipaddr)); }else{ \ + ip_addr_set_zero(ipX_2_ip(ipaddr)); }}while(0) +#define ipX_addr_set_any(is_ipv6, ipaddr) do{if(is_ipv6){ \ + ip6_addr_set_any(ipX_2_ip6(ipaddr)); }else{ \ + ip_addr_set_any(ipX_2_ip(ipaddr)); }}while(0) +#define ipX_addr_set_loopback(is_ipv6, ipaddr) do{if(is_ipv6){ \ + ip6_addr_set_loopback(ipX_2_ip6(ipaddr)); }else{ \ + ip_addr_set_loopback(ipX_2_ip(ipaddr)); }}while(0) +#define ipX_addr_set_hton(is_ipv6, dest, src) do{if(is_ipv6){ \ + ip6_addr_set_hton(ipX_2_ip6(ipaddr), (src)) ;}else{ \ + ip_addr_set_hton(ipX_2_ip(ipaddr), (src));}}while(0) +#define ipX_addr_cmp(is_ipv6, addr1, addr2) ((is_ipv6) ? \ + ip6_addr_cmp(ipX_2_ip6(addr1), ipX_2_ip6(addr2)) : \ + ip_addr_cmp(ipX_2_ip(addr1), ipX_2_ip(addr2))) +#define ipX_addr_isany(is_ipv6, ipaddr) ((is_ipv6) ? \ + ip6_addr_isany(ipX_2_ip6(ipaddr)) : \ + ip_addr_isany(ipX_2_ip(ipaddr))) +#define ipX_addr_ismulticast(is_ipv6, ipaddr) ((is_ipv6) ? \ + ip6_addr_ismulticast(ipX_2_ip6(ipaddr)) : \ + ip_addr_ismulticast(ipX_2_ip(ipaddr))) +#define ipX_addr_debug_print(is_ipv6, debug, ipaddr) do { if(is_ipv6) { \ + ip6_addr_debug_print(debug, ipX_2_ip6(ipaddr)); } else { \ + ip_addr_debug_print(debug, ipX_2_ip(ipaddr)); }}while(0) + +#else /* LWIP_IPV6 */ + +typedef ip_addr_t ipX_addr_t; +#define ipX_2_ip(ipaddr) (ipaddr) +#define ip_2_ipX(ipaddr) (ipaddr) + +#define ipX_addr_copy(is_ipv6, dest, src) ip_addr_copy(dest, src) +#define ipX_addr_set(is_ipv6, dest, src) ip_addr_set(dest, src) +#define ipX_addr_set_ipaddr(is_ipv6, dest, src) ip_addr_set(dest, src) +#define ipX_addr_set_zero(is_ipv6, ipaddr) ip_addr_set_zero(ipaddr) +#define ipX_addr_set_any(is_ipv6, ipaddr) ip_addr_set_any(ipaddr) +#define ipX_addr_set_loopback(is_ipv6, ipaddr) ip_addr_set_loopback(ipaddr) +#define ipX_addr_set_hton(is_ipv6, dest, src) ip_addr_set_hton(dest, src) +#define ipX_addr_cmp(is_ipv6, addr1, addr2) ip_addr_cmp(addr1, addr2) +#define ipX_addr_isany(is_ipv6, ipaddr) ip_addr_isany(ipaddr) +#define ipX_addr_ismulticast(is_ipv6, ipaddr) ip_addr_ismulticast(ipaddr) +#define ipX_addr_debug_print(is_ipv6, debug, ipaddr) ip_addr_debug_print(debug, ipaddr) + +#endif /* LWIP_IPV6 */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_IP_ADDR_H__ */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/ip_frag.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/ip_frag.h new file mode 100644 index 0000000..143b1e5 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/ip_frag.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Jani Monoses + * + */ + +#ifndef LWIP_HDR_IP_FRAG_H +#define LWIP_HDR_IP_FRAG_H + +#include "lwip/opt.h" +#include "lwip/err.h" +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/ip_addr.h" +#include "lwip/lwip_ip.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if IP_REASSEMBLY +/* The IP reassembly timer interval in milliseconds. */ +#define IP_TMR_INTERVAL 1000 + +/* IP reassembly helper struct. + * This is exported because memp needs to know the size. + */ +struct ip_reassdata { + struct ip_reassdata *next; + struct pbuf *p; + struct ip_hdr iphdr; + u16_t datagram_len; + u8_t flags; + u8_t timer; +}; + +void ip_reass_init(void); +void ip_reass_tmr(void); +struct pbuf * ip_reass(struct pbuf *p); +#endif /* IP_REASSEMBLY */ + +#if IP_FRAG +#if !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF +/** A custom pbuf that holds a reference to another pbuf, which is freed + * when this custom pbuf is freed. This is used to create a custom PBUF_REF + * that points into the original pbuf. */ +#ifndef LWIP_PBUF_CUSTOM_REF_DEFINED +#define LWIP_PBUF_CUSTOM_REF_DEFINED +struct pbuf_custom_ref { + /** 'base class' */ + struct pbuf_custom pc; + /** pointer to the original pbuf that is referenced */ + struct pbuf *original; +}; +#endif /* LWIP_PBUF_CUSTOM_REF_DEFINED */ +#endif /* !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF */ + +err_t ip_frag(struct pbuf *p, struct netif *netif, ip_addr_t *dest); +#endif /* IP_FRAG */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_IP_FRAG_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/lwip_ip.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/lwip_ip.h new file mode 100644 index 0000000..522e98d --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/lwip_ip.h @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_IP_H__ +#define LWIP_HDR_IP_H__ + +#include "lwip/opt.h" + +#include "lwip/def.h" +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" +#include "lwip/err.h" +#include "lwip/netif.h" +#include "lwip/ip4.h" +#include "lwip/ip6.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* This is passed as the destination address to ip_output_if (not + to ip_output), meaning that an IP header already is constructed + in the pbuf. This is used when TCP retransmits. */ +#ifdef IP_HDRINCL +#undef IP_HDRINCL +#endif /* IP_HDRINCL */ +#define IP_HDRINCL NULL + +/** pbufs passed to IP must have a ref-count of 1 as their payload pointer + gets altered as the packet is passed down the stack */ +#ifndef LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX +#define LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p) LWIP_ASSERT("p->ref == 1", (p)->ref == 1) +#endif + +#if LWIP_NETIF_HWADDRHINT +#define IP_PCB_ADDRHINT ;u8_t addr_hint +#else +#define IP_PCB_ADDRHINT +#endif /* LWIP_NETIF_HWADDRHINT */ + +#if LWIP_IPV6 +#define IP_PCB_ISIPV6_MEMBER u8_t isipv6; +#define IP_PCB_IPVER_EQ(pcb1, pcb2) ((pcb1)->isipv6 == (pcb2)->isipv6) +#define IP_PCB_IPVER_INPUT_MATCH(pcb) (ip_current_is_v6() ? \ + ((pcb)->isipv6 != 0) : \ + ((pcb)->isipv6 == 0)) +#define PCB_ISIPV6(pcb) ((pcb)->isipv6) +#else +#define IP_PCB_ISIPV6_MEMBER +#define IP_PCB_IPVER_EQ(pcb1, pcb2) 1 +#define IP_PCB_IPVER_INPUT_MATCH(pcb) 1 +#define PCB_ISIPV6(pcb) 0 +#endif /* LWIP_IPV6 */ + +/* This is the common part of all PCB types. It needs to be at the + beginning of a PCB type definition. It is located here so that + changes to this common part are made in one location instead of + having to change all PCB structs. */ +#define IP_PCB \ + IP_PCB_ISIPV6_MEMBER \ + /* ip addresses in network byte order */ \ + ipX_addr_t local_ip; \ + ipX_addr_t remote_ip; \ + /* Socket options */ \ + u8_t so_options; \ + /* Type Of Service */ \ + u8_t tos; \ + /* Time To Live */ \ + u8_t ttl \ + /* link layer address resolution hint */ \ + IP_PCB_ADDRHINT + +struct ip_pcb { +/* Common members of all PCB types */ + IP_PCB; +}; + +/* + * Option flags per-socket. These are the same like SO_XXX in sockets.h + */ +#define SOF_REUSEADDR 0x04U /* allow local address reuse */ +#define SOF_KEEPALIVE 0x08U /* keep connections alive */ +#define SOF_BROADCAST 0x20U /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */ + +/* These flags are inherited (e.g. from a listen-pcb to a connection-pcb): */ +#define SOF_INHERITED (SOF_REUSEADDR|SOF_KEEPALIVE) + +/* Global variables of this module, kept in a struct for efficient access using base+index. */ +struct ip_globals +{ + /** The interface that provided the packet for the current callback invocation. */ + struct netif *current_netif; + /** Header of the input packet currently being processed. */ + const struct ip_hdr *current_ip4_header; +#if LWIP_IPV6 + /** Header of the input IPv6 packet currently being processed. */ + const struct ip6_hdr *current_ip6_header; +#endif /* LWIP_IPV6 */ + /** Total header length of current_ip4/6_header (i.e. after this, the UDP/TCP header starts) */ + u16_t current_ip_header_tot_len; + /** Source IP address of current_header */ + ipX_addr_t current_iphdr_src; + /** Destination IP address of current_header */ + ipX_addr_t current_iphdr_dest; +}; +extern struct ip_globals ip_data; + + +/** Get the interface that received the current packet. + * This function must only be called from a receive callback (udp_recv, + * raw_recv, tcp_accept). It will return NULL otherwise. */ +#define ip_current_netif() (ip_data.current_netif) +/** Get the IP header of the current packet. + * This function must only be called from a receive callback (udp_recv, + * raw_recv, tcp_accept). It will return NULL otherwise. */ +#define ip_current_header() (ip_data.current_ip4_header) +/** Total header length of ip(6)_current_header() (i.e. after this, the UDP/TCP header starts) */ +#define ip_current_header_tot_len() (ip_data.current_ip_header_tot_len) +/** Source IP address of current_header */ +#define ipX_current_src_addr() (&ip_data.current_iphdr_src) +/** Destination IP address of current_header */ +#define ipX_current_dest_addr() (&ip_data.current_iphdr_dest) + +#if LWIP_IPV6 +/** Get the IPv6 header of the current packet. + * This function must only be called from a receive callback (udp_recv, + * raw_recv, tcp_accept). It will return NULL otherwise. */ +#define ip6_current_header() (ip_data.current_ip6_header) +/** Returns TRUE if the current IP input packet is IPv6, FALSE if it is IPv4 */ +#define ip_current_is_v6() (ip6_current_header() != NULL) +/** Source IPv6 address of current_header */ +#define ip6_current_src_addr() (ipX_2_ip6(&ip_data.current_iphdr_src)) +/** Destination IPv6 address of current_header */ +#define ip6_current_dest_addr() (ipX_2_ip6(&ip_data.current_iphdr_dest)) +/** Get the transport layer protocol */ +#define ip_current_header_proto() (ip_current_is_v6() ? \ + IP6H_NEXTH(ip6_current_header()) :\ + IPH_PROTO(ip_current_header())) +/** Get the transport layer header */ +#define ipX_next_header_ptr() ((void*)((ip_current_is_v6() ? \ + (u8_t*)ip6_current_header() : (u8_t*)ip_current_header()) + ip_current_header_tot_len())) + +/** Set an IP_PCB to IPv6 (IPv4 is the default) */ +#define ip_set_v6(pcb, val) do{if(pcb != NULL) { pcb->isipv6 = val; }}while(0) + +/** Source IP4 address of current_header */ +#define ip_current_src_addr() (ipX_2_ip(&ip_data.current_iphdr_src)) +/** Destination IP4 address of current_header */ +#define ip_current_dest_addr() (ipX_2_ip(&ip_data.current_iphdr_dest)) + +#else /* LWIP_IPV6 */ + +/** Always returns FALSE when only supporting IPv4 */ +#define ip_current_is_v6() 0 +/** Get the transport layer protocol */ +#define ip_current_header_proto() IPH_PROTO(ip_current_header()) +/** Get the transport layer header */ +#define ipX_next_header_ptr() ((void*)((u8_t*)ip_current_header() + ip_current_header_tot_len())) +/** Source IP4 address of current_header */ +#define ip_current_src_addr() (&ip_data.current_iphdr_src) +/** Destination IP4 address of current_header */ +#define ip_current_dest_addr() (&ip_data.current_iphdr_dest) + +#endif /* LWIP_IPV6 */ + +/** Union source address of current_header */ +#define ipX_current_src_addr() (&ip_data.current_iphdr_src) +/** Union destination address of current_header */ +#define ipX_current_dest_addr() (&ip_data.current_iphdr_dest) + +/** Gets an IP pcb option (SOF_* flags) */ +#define ip_get_option(pcb, opt) ((pcb)->so_options & (opt)) +/** Sets an IP pcb option (SOF_* flags) */ +#define ip_set_option(pcb, opt) ((pcb)->so_options |= (opt)) +/** Resets an IP pcb option (SOF_* flags) */ +#define ip_reset_option(pcb, opt) ((pcb)->so_options &= ~(opt)) + +#if LWIP_IPV6 +#define ipX_output(isipv6, p, src, dest, ttl, tos, proto) \ + ((isipv6) ? \ + ip6_output(p, ipX_2_ip6(src), ipX_2_ip6(dest), ttl, tos, proto) : \ + ip_output(p, ipX_2_ip(src), ipX_2_ip(dest), ttl, tos, proto)) +#define ipX_output_if(isipv6, p, src, dest, ttl, tos, proto, netif) \ + ((isipv6) ? \ + ip6_output_if(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto, netif) : \ + ip_output_if(p, (src), (dest), ttl, tos, proto, netif)) +#define ipX_output_if_src(isipv6, p, src, dest, ttl, tos, proto, netif) \ + ((isipv6) ? \ + ip6_output_if_src(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto, netif) : \ + ip_output_if_src(p, (src), (dest), ttl, tos, proto, netif)) +#define ipX_output_hinted(isipv6, p, src, dest, ttl, tos, proto, addr_hint) \ + ((isipv6) ? \ + ip6_output_hinted(p, ipX_2_ip6(src), ipX_2_ip6(dest), ttl, tos, proto, addr_hint) : \ + ip_output_hinted(p, ipX_2_ip(src), ipX_2_ip(dest), ttl, tos, proto, addr_hint)) +#define ipX_route(isipv6, src, dest) \ + ((isipv6) ? \ + ip6_route(ipX_2_ip6(src), ipX_2_ip6(dest)) : \ + ip_route(ipX_2_ip(dest))) +#define ipX_netif_get_local_ipX(isipv6, netif, dest) \ + ((isipv6) ? \ + ip6_netif_get_local_ipX(netif, ipX_2_ip6(dest)) : \ + ip_netif_get_local_ipX(netif)) +#define ipX_debug_print(is_ipv6, p) ((is_ipv6) ? ip6_debug_print(p) : ip_debug_print(p)) +#else /* LWIP_IPV6 */ +#define ipX_output(isipv6, p, src, dest, ttl, tos, proto) \ + ip_output(p, src, dest, ttl, tos, proto) +#define ipX_output_if(isipv6, p, src, dest, ttl, tos, proto, netif) \ + ip_output_if(p, src, dest, ttl, tos, proto, netif) +#define ipX_output_if_src(isipv6, p, src, dest, ttl, tos, proto, netif) \ + ip_output_if_src(p, src, dest, ttl, tos, proto, netif) +#define ipX_output_hinted(isipv6, p, src, dest, ttl, tos, proto, addr_hint) \ + ip_output_hinted(p, src, dest, ttl, tos, proto, addr_hint) +#define ipX_route(isipv6, src, dest) \ + ip_route(ipX_2_ip(dest)) +#define ipX_netif_get_local_ipX(isipv6, netif, dest) \ + ip_netif_get_local_ipX(netif) +#define ipX_debug_print(is_ipv6, p) ip_debug_print(p) +#endif /* LWIP_IPV6 */ + +#define ipX_route_get_local_ipX(isipv6, src, dest, netif, ipXaddr) do { \ + (netif) = ipX_route(isipv6, src, dest); \ + (ipXaddr) = ipX_netif_get_local_ipX(isipv6, netif, dest); \ +}while(0) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_IP_H__ */ + + diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/lwip_timers.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/lwip_timers.h new file mode 100644 index 0000000..e125777 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/lwip_timers.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * Simon Goldschmidt + * + */ +#ifndef LWIP_HDR_TIMERS_H +#define LWIP_HDR_TIMERS_H + +#include "lwip/opt.h" + +/* Timers are not supported when NO_SYS==1 and NO_SYS_NO_TIMERS==1 */ +#define LWIP_TIMERS (!NO_SYS || (NO_SYS && !NO_SYS_NO_TIMERS)) + +#if LWIP_TIMERS + +#include "lwip/err.h" +#if !NO_SYS +#include "lwip/sys.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef LWIP_DEBUG_TIMERNAMES +#ifdef LWIP_DEBUG +#define LWIP_DEBUG_TIMERNAMES SYS_DEBUG +#else /* LWIP_DEBUG */ +#define LWIP_DEBUG_TIMERNAMES 0 +#endif /* LWIP_DEBUG*/ +#endif + +/** Function prototype for a timeout callback function. Register such a function + * using sys_timeout(). + * + * @param arg Additional argument to pass to the function - set up by sys_timeout() + */ +typedef void (* sys_timeout_handler)(void *arg); + +struct sys_timeo { + struct sys_timeo *next; + u32_t time; + sys_timeout_handler h; + void *arg; +#if LWIP_DEBUG_TIMERNAMES + const char* handler_name; +#endif /* LWIP_DEBUG_TIMERNAMES */ +}; + +void sys_timeouts_init(void); + +//Realtek add +struct sys_timeouts { + struct sys_timeo *next; +}; + +struct sys_timeouts *sys_arch_timeouts(void); +//Realtek add end + +#if LWIP_DEBUG_TIMERNAMES +void sys_timeout_debug(u32_t msecs, sys_timeout_handler handler, void *arg, const char* handler_name); +#define sys_timeout(msecs, handler, arg) sys_timeout_debug(msecs, handler, arg, #handler) +#else /* LWIP_DEBUG_TIMERNAMES */ +void sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg); +#endif /* LWIP_DEBUG_TIMERNAMES */ + +void sys_untimeout(sys_timeout_handler handler, void *arg); +#if NO_SYS +void sys_check_timeouts(void); +void sys_restart_timeouts(void); +#else /* NO_SYS */ +void sys_timeouts_mbox_fetch(sys_mbox_t *mbox, void **msg); +#endif /* NO_SYS */ + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_TIMERS */ +#endif /* LWIP_HDR_TIMERS_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/mem.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/mem.h new file mode 100644 index 0000000..7fea25a --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/mem.h @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_MEM_H +#define LWIP_HDR_MEM_H + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if MEM_LIBC_MALLOC + +#include /* for size_t */ + +typedef size_t mem_size_t; +#define MEM_SIZE_F SZT_F + +/* aliases for C library malloc() */ +#define mem_init() +/* in case C library malloc() needs extra protection, + * allow these defines to be overridden. + */ +#ifndef mem_free +#define mem_free free +#endif +#ifndef mem_malloc +#define mem_malloc malloc +#endif +#ifndef mem_calloc +#define mem_calloc calloc +#endif +/* Since there is no C library allocation function to shrink memory without + moving it, define this to nothing. */ +#ifndef mem_trim +#define mem_trim(mem, size) (mem) +#endif +#else /* MEM_LIBC_MALLOC */ + +/* MEM_SIZE would have to be aligned, but using 64000 here instead of + * 65535 leaves some room for alignment... + */ +#if MEM_SIZE > 64000L +typedef u32_t mem_size_t; +#define MEM_SIZE_F U32_F +#else +typedef u16_t mem_size_t; +#define MEM_SIZE_F U16_F +#endif /* MEM_SIZE > 64000 */ + +#if MEM_USE_POOLS +/** mem_init is not used when using pools instead of a heap */ +#define mem_init() +/** mem_trim is not used when using pools instead of a heap: + we can't free part of a pool element and don't want to copy the rest */ +#define mem_trim(mem, size) (mem) +#else /* MEM_USE_POOLS */ +/* lwIP alternative malloc */ +void mem_init(void); +void *mem_trim(void *mem, mem_size_t size); +#endif /* MEM_USE_POOLS */ +void *mem_malloc(mem_size_t size); +void *mem_calloc(mem_size_t count, mem_size_t size); +void mem_free(void *mem); +#endif /* MEM_LIBC_MALLOC */ + +/** Calculate memory size for an aligned buffer - returns the next highest + * multiple of MEM_ALIGNMENT (e.g. LWIP_MEM_ALIGN_SIZE(3) and + * LWIP_MEM_ALIGN_SIZE(4) will both yield 4 for MEM_ALIGNMENT == 4). + */ +#ifndef LWIP_MEM_ALIGN_SIZE +#define LWIP_MEM_ALIGN_SIZE(size) (((size) + MEM_ALIGNMENT - 1U) & ~(MEM_ALIGNMENT-1U)) +#endif + +/** Calculate safe memory size for an aligned buffer when using an unaligned + * type as storage. This includes a safety-margin on (MEM_ALIGNMENT - 1) at the + * start (e.g. if buffer is u8_t[] and actual data will be u32_t*) + */ +#ifndef LWIP_MEM_ALIGN_BUFFER +#define LWIP_MEM_ALIGN_BUFFER(size) (((size) + MEM_ALIGNMENT - 1U)) +#endif + +/** Align a memory pointer to the alignment defined by MEM_ALIGNMENT + * so that ADDR % MEM_ALIGNMENT == 0 + */ +#ifndef LWIP_MEM_ALIGN +#define LWIP_MEM_ALIGN(addr) ((void *)(((mem_ptr_t)(addr) + MEM_ALIGNMENT - 1) & ~(mem_ptr_t)(MEM_ALIGNMENT-1))) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_MEM_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/memp.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/memp.h new file mode 100644 index 0000000..8bcc43a --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/memp.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#ifndef LWIP_HDR_MEMP_H +#define LWIP_HDR_MEMP_H + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Create the list of all memory pools managed by memp. MEMP_MAX represents a NULL pool at the end */ +typedef enum { +#define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name, +#include "lwip/memp_std.h" + MEMP_MAX +} memp_t; + +#if MEM_USE_POOLS +/* Use a helper type to get the start and end of the user "memory pools" for mem_malloc */ +typedef enum { + /* Get the first (via: + MEMP_POOL_HELPER_START = ((u8_t) 1*MEMP_POOL_A + 0*MEMP_POOL_B + 0*MEMP_POOL_C + 0)*/ + MEMP_POOL_HELPER_FIRST = ((u8_t) +#define LWIP_MEMPOOL(name,num,size,desc) +#define LWIP_MALLOC_MEMPOOL_START 1 +#define LWIP_MALLOC_MEMPOOL(num, size) * MEMP_POOL_##size + 0 +#define LWIP_MALLOC_MEMPOOL_END +#include "lwip/memp_std.h" + ) , + /* Get the last (via: + MEMP_POOL_HELPER_END = ((u8_t) 0 + MEMP_POOL_A*0 + MEMP_POOL_B*0 + MEMP_POOL_C*1) */ + MEMP_POOL_HELPER_LAST = ((u8_t) +#define LWIP_MEMPOOL(name,num,size,desc) +#define LWIP_MALLOC_MEMPOOL_START +#define LWIP_MALLOC_MEMPOOL(num, size) 0 + MEMP_POOL_##size * +#define LWIP_MALLOC_MEMPOOL_END 1 +#include "lwip/memp_std.h" + ) +} memp_pool_helper_t; + +/* The actual start and stop values are here (cast them over) + We use this helper type and these defines so we can avoid using const memp_t values */ +#define MEMP_POOL_FIRST ((memp_t) MEMP_POOL_HELPER_FIRST) +#define MEMP_POOL_LAST ((memp_t) MEMP_POOL_HELPER_LAST) +#endif /* MEM_USE_POOLS */ + +#if MEMP_MEM_MALLOC || MEM_USE_POOLS +extern const u16_t memp_sizes[MEMP_MAX]; +#endif /* MEMP_MEM_MALLOC || MEM_USE_POOLS */ + +#if MEMP_MEM_MALLOC + +#include "mem.h" + +#define memp_init() +#define memp_malloc(type) mem_malloc(memp_sizes[type]) +#define memp_free(type, mem) mem_free(mem) + +#else /* MEMP_MEM_MALLOC */ + +#if MEM_USE_POOLS +/** This structure is used to save the pool one element came from. */ +struct memp_malloc_helper +{ + memp_t poolnr; +#if MEMP_OVERFLOW_CHECK + u16_t size; +#endif /* MEMP_OVERFLOW_CHECK */ +}; +#endif /* MEM_USE_POOLS */ + +void memp_init(void); + +#if MEMP_OVERFLOW_CHECK +void *memp_malloc_fn(memp_t type, const char* file, const int line); +#define memp_malloc(t) memp_malloc_fn((t), __FILE__, __LINE__) +#else +void *memp_malloc(memp_t type); +#endif +void memp_free(memp_t type, void *mem); + +#endif /* MEMP_MEM_MALLOC */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_MEMP_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/memp_std.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/memp_std.h new file mode 100644 index 0000000..ce303da --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/memp_std.h @@ -0,0 +1,154 @@ +/* + * SETUP: Make sure we define everything we will need. + * + * We have create three types of pools: + * 1) MEMPOOL - standard pools + * 2) MALLOC_MEMPOOL - to be used by mem_malloc in mem.c + * 3) PBUF_MEMPOOL - a mempool of pbuf's, so include space for the pbuf struct + * + * If the include'r doesn't require any special treatment of each of the types + * above, then will declare #2 & #3 to be just standard mempools. + */ +#ifndef LWIP_MALLOC_MEMPOOL +/* This treats "malloc pools" just like any other pool. + The pools are a little bigger to provide 'size' as the amount of user data. */ +#define LWIP_MALLOC_MEMPOOL(num, size) LWIP_MEMPOOL(POOL_##size, num, (size + LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper))), "MALLOC_"#size) +#define LWIP_MALLOC_MEMPOOL_START +#define LWIP_MALLOC_MEMPOOL_END +#endif /* LWIP_MALLOC_MEMPOOL */ + +#ifndef LWIP_PBUF_MEMPOOL +/* This treats "pbuf pools" just like any other pool. + * Allocates buffers for a pbuf struct AND a payload size */ +#define LWIP_PBUF_MEMPOOL(name, num, payload, desc) LWIP_MEMPOOL(name, num, (MEMP_ALIGN_SIZE(sizeof(struct pbuf)) + MEMP_ALIGN_SIZE(payload)), desc) +#endif /* LWIP_PBUF_MEMPOOL */ + + +/* + * A list of internal pools used by LWIP. + * + * LWIP_MEMPOOL(pool_name, number_elements, element_size, pool_description) + * creates a pool name MEMP_pool_name. description is used in stats.c + */ +#if LWIP_RAW +LWIP_MEMPOOL(RAW_PCB, MEMP_NUM_RAW_PCB, sizeof(struct raw_pcb), "RAW_PCB") +#endif /* LWIP_RAW */ + +#if LWIP_UDP +LWIP_MEMPOOL(UDP_PCB, MEMP_NUM_UDP_PCB, sizeof(struct udp_pcb), "UDP_PCB") +#endif /* LWIP_UDP */ + +#if LWIP_TCP +LWIP_MEMPOOL(TCP_PCB, MEMP_NUM_TCP_PCB, sizeof(struct tcp_pcb), "TCP_PCB") +LWIP_MEMPOOL(TCP_PCB_LISTEN, MEMP_NUM_TCP_PCB_LISTEN, sizeof(struct tcp_pcb_listen), "TCP_PCB_LISTEN") +LWIP_MEMPOOL(TCP_SEG, MEMP_NUM_TCP_SEG, sizeof(struct tcp_seg), "TCP_SEG") +#endif /* LWIP_TCP */ + +#if IP_REASSEMBLY +LWIP_MEMPOOL(REASSDATA, MEMP_NUM_REASSDATA, sizeof(struct ip_reassdata), "REASSDATA") +#endif /* IP_REASSEMBLY */ +#if (IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF) || LWIP_IPV6_FRAG +LWIP_MEMPOOL(FRAG_PBUF, MEMP_NUM_FRAG_PBUF, sizeof(struct pbuf_custom_ref),"FRAG_PBUF") +#endif /* IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF */ + +#if LWIP_NETCONN || LWIP_SOCKET +LWIP_MEMPOOL(NETBUF, MEMP_NUM_NETBUF, sizeof(struct netbuf), "NETBUF") +LWIP_MEMPOOL(NETCONN, MEMP_NUM_NETCONN, sizeof(struct netconn), "NETCONN") +#endif /* LWIP_NETCONN || LWIP_SOCKET */ + +#if NO_SYS==0 +LWIP_MEMPOOL(TCPIP_MSG_API, MEMP_NUM_TCPIP_MSG_API, sizeof(struct tcpip_msg), "TCPIP_MSG_API") +#if LWIP_MPU_COMPATIBLE +LWIP_MEMPOOL(API_MSG, MEMP_NUM_API_MSG, sizeof(struct api_msg), "API_MSG") +#if LWIP_DNS +LWIP_MEMPOOL(DNS_API_MSG, MEMP_NUM_DNS_API_MSG, sizeof(struct dns_api_msg), "DNS_API_MSG") +#endif +#if LWIP_SOCKET && !LWIP_TCPIP_CORE_LOCKING +LWIP_MEMPOOL(SOCKET_SETGETSOCKOPT_DATA, MEMP_NUM_SOCKET_SETGETSOCKOPT_DATA, sizeof(struct lwip_setgetsockopt_data), "SOCKET_SETGETSOCKOPT_DATA") +#endif +#if LWIP_NETIF_API +LWIP_MEMPOOL(NETIFAPI_MSG, MEMP_NUM_NETIFAPI_MSG, sizeof(struct netifapi_msg), "NETIFAPI_MSG") +#endif +#endif /* LWIP_MPU_COMPATIBLE */ +#if !LWIP_TCPIP_CORE_LOCKING_INPUT +LWIP_MEMPOOL(TCPIP_MSG_INPKT,MEMP_NUM_TCPIP_MSG_INPKT, sizeof(struct tcpip_msg), "TCPIP_MSG_INPKT") +#endif /* !LWIP_TCPIP_CORE_LOCKING_INPUT */ +#endif /* NO_SYS==0 */ + +#if LWIP_ARP && ARP_QUEUEING +LWIP_MEMPOOL(ARP_QUEUE, MEMP_NUM_ARP_QUEUE, sizeof(struct etharp_q_entry), "ARP_QUEUE") +#endif /* LWIP_ARP && ARP_QUEUEING */ + +#if LWIP_IGMP +LWIP_MEMPOOL(IGMP_GROUP, MEMP_NUM_IGMP_GROUP, sizeof(struct igmp_group), "IGMP_GROUP") +#endif /* LWIP_IGMP */ + +#if (!NO_SYS || (NO_SYS && !NO_SYS_NO_TIMERS)) /* LWIP_TIMERS */ +LWIP_MEMPOOL(SYS_TIMEOUT, MEMP_NUM_SYS_TIMEOUT, sizeof(struct sys_timeo), "SYS_TIMEOUT") +#endif /* LWIP_TIMERS */ + +#if LWIP_SNMP +LWIP_MEMPOOL(SNMP_ROOTNODE, MEMP_NUM_SNMP_ROOTNODE, sizeof(struct mib_list_rootnode), "SNMP_ROOTNODE") +LWIP_MEMPOOL(SNMP_NODE, MEMP_NUM_SNMP_NODE, sizeof(struct mib_list_node), "SNMP_NODE") +LWIP_MEMPOOL(SNMP_VARBIND, MEMP_NUM_SNMP_VARBIND, sizeof(struct snmp_varbind), "SNMP_VARBIND") +LWIP_MEMPOOL(SNMP_VALUE, MEMP_NUM_SNMP_VALUE, SNMP_MAX_VALUE_SIZE, "SNMP_VALUE") +#endif /* LWIP_SNMP */ +#if LWIP_DNS && LWIP_SOCKET +LWIP_MEMPOOL(NETDB, MEMP_NUM_NETDB, NETDB_ELEM_SIZE, "NETDB") +#endif /* LWIP_DNS && LWIP_SOCKET */ +#if LWIP_DNS && DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC +LWIP_MEMPOOL(LOCALHOSTLIST, MEMP_NUM_LOCALHOSTLIST, LOCALHOSTLIST_ELEM_SIZE, "LOCALHOSTLIST") +#endif /* LWIP_DNS && DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + +#if PPP_SUPPORT +LWIP_MEMPOOL(PPP_PCB, MEMP_NUM_PPP_PCB, sizeof(ppp_pcb), "PPP_PCB") +#if PPPOE_SUPPORT +LWIP_MEMPOOL(PPPOE_IF, MEMP_NUM_PPPOE_INTERFACES, sizeof(struct pppoe_softc), "PPPOE_IF") +#endif /* PPPOE_SUPPORT */ +#if PPPOL2TP_SUPPORT +LWIP_MEMPOOL(PPPOL2TP_PCB, MEMP_NUM_PPPOL2TP_INTERFACES, sizeof(pppol2tp_pcb), "PPPOL2TP_PCB") +#endif /* PPPOL2TP_SUPPORT */ +#endif /* PPP_SUPPORT */ + +#if LWIP_IPV6 && LWIP_ND6_QUEUEING +LWIP_MEMPOOL(ND6_QUEUE, MEMP_NUM_ND6_QUEUE, sizeof(struct nd6_q_entry), "ND6_QUEUE") +#endif /* LWIP_IPV6 && LWIP_ND6_QUEUEING */ + +#if LWIP_IPV6 && LWIP_IPV6_REASS +LWIP_MEMPOOL(IP6_REASSDATA, MEMP_NUM_REASSDATA, sizeof(struct ip6_reassdata), "IP6_REASSDATA") +#endif /* LWIP_IPV6 && LWIP_IPV6_REASS */ + +#if LWIP_IPV6 && LWIP_IPV6_MLD +LWIP_MEMPOOL(MLD6_GROUP, MEMP_NUM_MLD6_GROUP, sizeof(struct mld_group), "MLD6_GROUP") +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ + + +/* + * A list of pools of pbuf's used by LWIP. + * + * LWIP_PBUF_MEMPOOL(pool_name, number_elements, pbuf_payload_size, pool_description) + * creates a pool name MEMP_pool_name. description is used in stats.c + * This allocates enough space for the pbuf struct and a payload. + * (Example: pbuf_payload_size=0 allocates only size for the struct) + */ +LWIP_PBUF_MEMPOOL(PBUF, MEMP_NUM_PBUF, 0, "PBUF_REF/ROM") +LWIP_PBUF_MEMPOOL(PBUF_POOL, PBUF_POOL_SIZE, PBUF_POOL_BUFSIZE, "PBUF_POOL") + + +/* + * Allow for user-defined pools; this must be explicitly set in lwipopts.h + * since the default is to NOT look for lwippools.h + */ +#if MEMP_USE_CUSTOM_POOLS +#include "lwippools.h" +#endif /* MEMP_USE_CUSTOM_POOLS */ + +/* + * REQUIRED CLEANUP: Clear up so we don't get "multiply defined" error later + * (#undef is ignored for something that is not defined) + */ +#undef LWIP_MEMPOOL +#undef LWIP_MALLOC_MEMPOOL +#undef LWIP_MALLOC_MEMPOOL_START +#undef LWIP_MALLOC_MEMPOOL_END +#undef LWIP_PBUF_MEMPOOL diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/mld6.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/mld6.h new file mode 100644 index 0000000..f629c3d --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/mld6.h @@ -0,0 +1,118 @@ +/** + * @file + * + * Multicast listener discovery for IPv6. Aims to be compliant with RFC 2710. + * No support for MLDv2. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#ifndef LWIP_HDR_MLD6_H +#define LWIP_HDR_MLD6_H + +#include "lwip/opt.h" + +#if LWIP_IPV6_MLD && LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/netif.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +struct mld_group { + /** next link */ + struct mld_group *next; + /** interface on which the group is active */ + struct netif *netif; + /** multicast address */ + ip6_addr_t group_address; + /** signifies we were the last person to report */ + u8_t last_reporter_flag; + /** current state of the group */ + u8_t group_state; + /** timer for reporting */ + u16_t timer; + /** counter of simultaneous uses */ + u8_t use; +}; + +/** Multicast listener report/query/done message header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct mld_header { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u16_t max_resp_delay); + PACK_STRUCT_FIELD(u16_t reserved); + PACK_STRUCT_FLD_S(ip6_addr_p_t multicast_address); + /* Options follow. */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define MLD6_TMR_INTERVAL 100 /* Milliseconds */ + +/* MAC Filter Actions, these are passed to a netif's + * mld_mac_filter callback function. */ +#define MLD6_DEL_MAC_FILTER 0 +#define MLD6_ADD_MAC_FILTER 1 + + +#define mld6_init() /* TODO should we init tables? */ +err_t mld6_stop(struct netif *netif); +void mld6_report_groups(struct netif *netif); +void mld6_tmr(void); +struct mld_group *mld6_lookfor_group(struct netif *ifp, ip6_addr_t *addr); +void mld6_input(struct pbuf *p, struct netif *inp); +err_t mld6_joingroup(ip6_addr_t *srcaddr, ip6_addr_t *groupaddr); +err_t mld6_leavegroup(ip6_addr_t *srcaddr, ip6_addr_t *groupaddr); + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV6_MLD && LWIP_IPV6 */ + +#endif /* LWIP_HDR_MLD6_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/nd6.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/nd6.h new file mode 100644 index 0000000..2a8401f --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/nd6.h @@ -0,0 +1,362 @@ +/** + * @file + * + * Neighbor discovery and stateless address autoconfiguration for IPv6. + * Aims to be compliant with RFC 4861 (Neighbor discovery) and RFC 4862 + * (Address autoconfiguration). + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +#ifndef LWIP_HDR_ND6_H +#define LWIP_HDR_ND6_H + +#include "lwip/opt.h" + +#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/netif.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Struct for tables. */ +struct nd6_neighbor_cache_entry { + ip6_addr_t next_hop_address; + struct netif * netif; + u8_t lladdr[NETIF_MAX_HWADDR_LEN]; + /*u32_t pmtu;*/ +#if LWIP_ND6_QUEUEING + /** Pointer to queue of pending outgoing packets on this entry. */ + struct nd6_q_entry *q; +#else /* LWIP_ND6_QUEUEING */ + /** Pointer to a single pending outgoing packet on this entry. */ + struct pbuf *q; +#endif /* LWIP_ND6_QUEUEING */ + u8_t state; + u8_t isrouter; + union { + u32_t reachable_time; + u32_t delay_time; + u32_t probes_sent; + u32_t stale_time; + } counter; +}; + +struct nd6_destination_cache_entry { + ip6_addr_t destination_addr; + ip6_addr_t next_hop_addr; + u32_t pmtu; + u32_t age; +}; + +struct nd6_prefix_list_entry { + ip6_addr_t prefix; + struct netif * netif; + u32_t invalidation_timer; +#if LWIP_IPV6_AUTOCONFIG + u8_t flags; +#define ND6_PREFIX_AUTOCONFIG_AUTONOMOUS 0x01 +#define ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED 0x02 +#define ND6_PREFIX_AUTOCONFIG_ADDRESS_DUPLICATE 0x04 +#endif /* LWIP_IPV6_AUTOCONFIG */ +}; + +struct nd6_router_list_entry { + struct nd6_neighbor_cache_entry * neighbor_entry; + u32_t invalidation_timer; + u8_t flags; +}; + + +enum nd6_neighbor_cache_entry_state { + ND6_NO_ENTRY = 0, + ND6_INCOMPLETE, + ND6_REACHABLE, + ND6_STALE, + ND6_DELAY, + ND6_PROBE +}; + +#if LWIP_ND6_QUEUEING +/** struct for queueing outgoing packets for unknown address + * defined here to be accessed by memp.h + */ +struct nd6_q_entry { + struct nd6_q_entry *next; + struct pbuf *p; +}; +#endif /* LWIP_ND6_QUEUEING */ + +/** Neighbor solicitation message header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ns_header { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u32_t reserved); + PACK_STRUCT_FLD_S(ip6_addr_p_t target_address); + /* Options follow. */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Neighbor advertisement message header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct na_header { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FLD_8(u8_t flags); + PACK_STRUCT_FLD_8(u8_t reserved[3]); + PACK_STRUCT_FLD_S(ip6_addr_p_t target_address); + /* Options follow. */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif +#define ND6_FLAG_ROUTER (0x80) +#define ND6_FLAG_SOLICITED (0x40) +#define ND6_FLAG_OVERRIDE (0x20) + +/** Router solicitation message header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct rs_header { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u32_t reserved); + /* Options follow. */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Router advertisement message header. */ +#define ND6_RA_FLAG_MANAGED_ADDR_CONFIG (0x80) +#define ND6_RA_FLAG_OTHER_STATEFUL_CONFIG (0x40) +#define ND6_RA_FLAG_HOME_AGENT (0x20) +#define ND6_RA_PREFERENCE_MASK (0x18) +#define ND6_RA_PREFERENCE_HIGH (0x08) +#define ND6_RA_PREFERENCE_MEDIUM (0x00) +#define ND6_RA_PREFERENCE_LOW (0x18) +#define ND6_RA_PREFERENCE_DISABLED (0x10) +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ra_header { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FLD_8(u8_t current_hop_limit); + PACK_STRUCT_FLD_8(u8_t flags); + PACK_STRUCT_FIELD(u16_t router_lifetime); + PACK_STRUCT_FIELD(u32_t reachable_time); + PACK_STRUCT_FIELD(u32_t retrans_timer); + /* Options follow. */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Redirect message header. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct redirect_header { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u32_t reserved); + PACK_STRUCT_FLD_S(ip6_addr_p_t target_address); + PACK_STRUCT_FLD_S(ip6_addr_p_t destination_address); + /* Options follow. */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Link-layer address option. */ +#define ND6_OPTION_TYPE_SOURCE_LLADDR (0x01) +#define ND6_OPTION_TYPE_TARGET_LLADDR (0x02) +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct lladdr_option { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t length); + PACK_STRUCT_FLD_8(u8_t addr[NETIF_MAX_HWADDR_LEN]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Prefix information option. */ +#define ND6_OPTION_TYPE_PREFIX_INFO (0x03) +#define ND6_PREFIX_FLAG_ON_LINK (0x80) +#define ND6_PREFIX_FLAG_AUTONOMOUS (0x40) +#define ND6_PREFIX_FLAG_ROUTER_ADDRESS (0x20) +#define ND6_PREFIX_FLAG_SITE_PREFIX (0x10) +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct prefix_option { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t length); + PACK_STRUCT_FLD_8(u8_t prefix_length); + PACK_STRUCT_FLD_8(u8_t flags); + PACK_STRUCT_FIELD(u32_t valid_lifetime); + PACK_STRUCT_FIELD(u32_t preferred_lifetime); + PACK_STRUCT_FLD_8(u8_t reserved2[3]); + PACK_STRUCT_FLD_8(u8_t site_prefix_length); + PACK_STRUCT_FLD_S(ip6_addr_p_t prefix); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Redirected header option. */ +#define ND6_OPTION_TYPE_REDIR_HDR (0x04) +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct redirected_header_option { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t length); + PACK_STRUCT_FLD_8(u8_t reserved[6]); + /* Portion of redirected packet follows. */ + /* PACK_STRUCT_FLD_8(u8_t redirected[8]); */ +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** MTU option. */ +#define ND6_OPTION_TYPE_MTU (0x05) +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct mtu_option { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t length); + PACK_STRUCT_FIELD(u16_t reserved); + PACK_STRUCT_FIELD(u32_t mtu); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** Route information option. */ +#define ND6_OPTION_TYPE_ROUTE_INFO (24) +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct route_option { + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t length); + PACK_STRUCT_FLD_8(u8_t prefix_length); + PACK_STRUCT_FLD_8(u8_t preference); + PACK_STRUCT_FIELD(u32_t route_lifetime); + PACK_STRUCT_FLD_S(ip6_addr_p_t prefix); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** 1 second period */ +#define ND6_TMR_INTERVAL 1000 + +/* Router tables. */ +/* TODO make these static? and entries accessible through API? */ +extern struct nd6_neighbor_cache_entry neighbor_cache[]; +extern struct nd6_destination_cache_entry destination_cache[]; +extern struct nd6_prefix_list_entry prefix_list[]; +extern struct nd6_router_list_entry default_router_list[]; + +/* Default values, can be updated by a RA message. */ +extern u32_t reachable_time; +extern u32_t retrans_timer; + +#define nd6_init() /* TODO should we init tables? */ +void nd6_tmr(void); +void nd6_input(struct pbuf *p, struct netif *inp); +s8_t nd6_get_next_hop_entry(ip6_addr_t * ip6addr, struct netif * netif); +s8_t nd6_select_router(ip6_addr_t * ip6addr, struct netif * netif); +u16_t nd6_get_destination_mtu(ip6_addr_t * ip6addr, struct netif * netif); +err_t nd6_queue_packet(s8_t neighbor_index, struct pbuf * p); +#if LWIP_ND6_TCP_REACHABILITY_HINTS +void nd6_reachability_hint(ip6_addr_t * ip6addr); +#endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV6 */ + +#endif /* LWIP_HDR_ND6_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/netbuf.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/netbuf.h new file mode 100644 index 0000000..54ef1e6 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/netbuf.h @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_NETBUF_H +#define LWIP_HDR_NETBUF_H + +#if LWIP_NETCONN || LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ + +/* don't export the netbuf functions when socket API is enabled but netconn API is disabled */ +#if LWIP_NETCONN +#define LWIP_NETCONN_SCOPE +#else /* LWIP_NETCONN */ +#define LWIP_NETCONN_SCOPE static +#endif /* LWIP_NETCONN */ + +#include "lwip/opt.h" +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" +#include "lwip/ip6_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** This netbuf has dest-addr/port set */ +#define NETBUF_FLAG_DESTADDR 0x01 +/** This netbuf includes a checksum */ +#define NETBUF_FLAG_CHKSUM 0x02 + +struct netbuf { + struct pbuf *p, *ptr; + ipX_addr_t addr; + u16_t port; +#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY +#if LWIP_CHECKSUM_ON_COPY + u8_t flags; +#endif /* LWIP_CHECKSUM_ON_COPY */ + u16_t toport_chksum; +#if LWIP_NETBUF_RECVINFO + ipX_addr_t toaddr; +#endif /* LWIP_NETBUF_RECVINFO */ +#endif /* LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY */ +}; + +/* Network buffer functions: */ +LWIP_NETCONN_SCOPE struct netbuf * netbuf_new (void); +LWIP_NETCONN_SCOPE void netbuf_delete (struct netbuf *buf); +LWIP_NETCONN_SCOPE void * netbuf_alloc (struct netbuf *buf, u16_t size); +LWIP_NETCONN_SCOPE void netbuf_free (struct netbuf *buf); +LWIP_NETCONN_SCOPE err_t netbuf_ref (struct netbuf *buf, + const void *dataptr, u16_t size); +LWIP_NETCONN_SCOPE void netbuf_chain (struct netbuf *head, + struct netbuf *tail); + +LWIP_NETCONN_SCOPE err_t netbuf_data (struct netbuf *buf, + void **dataptr, u16_t *len); +LWIP_NETCONN_SCOPE s8_t netbuf_next (struct netbuf *buf); +LWIP_NETCONN_SCOPE void netbuf_first (struct netbuf *buf); + + +#define netbuf_copy_partial(buf, dataptr, len, offset) \ + pbuf_copy_partial((buf)->p, (dataptr), (len), (offset)) +#define netbuf_copy(buf,dataptr,len) netbuf_copy_partial(buf, dataptr, len, 0) +#define netbuf_take(buf, dataptr, len) pbuf_take((buf)->p, dataptr, len) +#define netbuf_len(buf) ((buf)->p->tot_len) +#define netbuf_fromaddr(buf) (ipX_2_ip(&((buf)->addr))) +#define netbuf_set_fromaddr(buf, fromaddr) ip_addr_set(ipX_2_ip(&((buf)->addr)), fromaddr) +#define netbuf_fromport(buf) ((buf)->port) +#if LWIP_NETBUF_RECVINFO +#define netbuf_destaddr(buf) (ipX_2_ip(&((buf)->toaddr))) +#define netbuf_set_destaddr(buf, destaddr) ip_addr_set(ipX_2_ip(&((buf)->toaddr)), destaddr) +#define netbuf_destport(buf) (((buf)->flags & NETBUF_FLAG_DESTADDR) ? (buf)->toport_chksum : 0) +#endif /* LWIP_NETBUF_RECVINFO */ +#if LWIP_CHECKSUM_ON_COPY +#define netbuf_set_chksum(buf, chksum) do { (buf)->flags = NETBUF_FLAG_CHKSUM; \ + (buf)->toport_chksum = chksum; } while(0) +#endif /* LWIP_CHECKSUM_ON_COPY */ + +#if LWIP_IPV6 +#define netbuf_fromaddr_ip6(buf) (ipX_2_ip6(&((buf)->addr))) +#define netbuf_set_fromaddr_ip6(buf, fromaddr) ip6_addr_set(ipX_2_ip6(&((buf)->addr)), fromaddr) +#define netbuf_destaddr_ip6(buf) (ipX_2_ip6(&((buf)->toaddr))) +#define netbuf_set_destaddr_ip6(buf, destaddr) ip6_addr_set(ipX_2_ip6(&((buf)->toaddr)), destaddr) +#endif /* LWIP_IPV6 */ + +#define netbuf_fromaddr_ipX(buf) (&((buf)->addr)) +#define netbuf_destaddr_ipX(buf) (&((buf)->toaddr)) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_NETCONN || LWIP_SOCKET */ + +#endif /* LWIP_HDR_NETBUF_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/netdb.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/netdb.h new file mode 100644 index 0000000..d7acdc9 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/netdb.h @@ -0,0 +1,127 @@ +/* + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Simon Goldschmidt + * + */ +#ifndef LWIP_HDR_NETDB_H +#define LWIP_HDR_NETDB_H + +#include "lwip/opt.h" + +#if LWIP_DNS && LWIP_SOCKET + +#include /* for size_t */ + +#include "lwip/inet.h" +#include "lwip/sockets.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* some rarely used options */ +#ifndef LWIP_DNS_API_DECLARE_H_ERRNO +#define LWIP_DNS_API_DECLARE_H_ERRNO 1 +#endif + +#ifndef LWIP_DNS_API_DEFINE_ERRORS +#define LWIP_DNS_API_DEFINE_ERRORS 1 +#endif + +#ifndef LWIP_DNS_API_DECLARE_STRUCTS +#define LWIP_DNS_API_DECLARE_STRUCTS 1 +#endif + +#if LWIP_DNS_API_DEFINE_ERRORS +/** Errors used by the DNS API functions, h_errno can be one of them */ +#define EAI_NONAME 200 +#define EAI_SERVICE 201 +#define EAI_FAIL 202 +#define EAI_MEMORY 203 +#define EAI_FAMILY 204 + +#define HOST_NOT_FOUND 210 +#define NO_DATA 211 +#define NO_RECOVERY 212 +#define TRY_AGAIN 213 +#endif /* LWIP_DNS_API_DEFINE_ERRORS */ + +#if LWIP_DNS_API_DECLARE_STRUCTS +struct hostent { + char *h_name; /* Official name of the host. */ + char **h_aliases; /* A pointer to an array of pointers to alternative host names, + terminated by a null pointer. */ + int h_addrtype; /* Address type. */ + int h_length; /* The length, in bytes, of the address. */ + char **h_addr_list; /* A pointer to an array of pointers to network addresses (in + network byte order) for the host, terminated by a null pointer. */ +#define h_addr h_addr_list[0] /* for backward compatibility */ +}; + +struct addrinfo { + int ai_flags; /* Input flags. */ + int ai_family; /* Address family of socket. */ + int ai_socktype; /* Socket type. */ + int ai_protocol; /* Protocol of socket. */ + socklen_t ai_addrlen; /* Length of socket address. */ + struct sockaddr *ai_addr; /* Socket address of socket. */ + char *ai_canonname; /* Canonical name of service location. */ + struct addrinfo *ai_next; /* Pointer to next in list. */ +}; +#endif /* LWIP_DNS_API_DECLARE_STRUCTS */ + +#define NETDB_ELEM_SIZE (sizeof(struct addrinfo) + sizeof(struct sockaddr_in) + DNS_MAX_NAME_LENGTH + 1) + +#if LWIP_DNS_API_DECLARE_H_ERRNO +/* application accessible error code set by the DNS API functions */ +extern int h_errno; +#endif /* LWIP_DNS_API_DECLARE_H_ERRNO*/ + +struct hostent *lwip_gethostbyname(const char *name); +int lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf, + size_t buflen, struct hostent **result, int *h_errnop); +void lwip_freeaddrinfo(struct addrinfo *ai); +int lwip_getaddrinfo(const char *nodename, + const char *servname, + const struct addrinfo *hints, + struct addrinfo **res); + +#if LWIP_COMPAT_SOCKETS +#define gethostbyname(name) lwip_gethostbyname(name) +#define gethostbyname_r(name, ret, buf, buflen, result, h_errnop) \ + lwip_gethostbyname_r(name, ret, buf, buflen, result, h_errnop) +#define freeaddrinfo(addrinfo) lwip_freeaddrinfo(addrinfo) +#define getaddrinfo(nodname, servname, hints, res) \ + lwip_getaddrinfo(nodname, servname, hints, res) +#endif /* LWIP_COMPAT_SOCKETS */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_DNS && LWIP_SOCKET */ + +#endif /* LWIP_HDR_NETDB_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/netif.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/netif.h new file mode 100644 index 0000000..fd2939d --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/netif.h @@ -0,0 +1,401 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_NETIF_H +#define LWIP_HDR_NETIF_H + +#include "lwip/opt.h" + +#define ENABLE_LOOPBACK (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF) + +#include "lwip/err.h" + +#include "lwip/ip_addr.h" +#include "lwip/ip6_addr.h" + +#include "lwip/def.h" +#include "lwip/pbuf.h" +#if LWIP_DHCP +struct dhcp; +#endif +#if LWIP_AUTOIP +struct autoip; +#endif +#if LWIP_IPV6_DHCP6 +#include "lwip/dhcp6.h" +#endif /* LWIP_IPV6_DHCP6 */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Throughout this file, IP addresses are expected to be in + * the same byte order as in IP_PCB. */ + +/** Must be the maximum of all used hardware address lengths + across all types of interfaces in use. + This does not have to be changed, normally. */ +#ifndef NETIF_MAX_HWADDR_LEN +#define NETIF_MAX_HWADDR_LEN 6U +#endif + +/** Whether the network interface is 'up'. This is + * a software flag used to control whether this network + * interface is enabled and processes traffic. + * It is set by the startup code (for static IP configuration) or + * by dhcp/autoip when an address has been assigned. + */ +#define NETIF_FLAG_UP 0x01U +/** If set, the netif has broadcast capability. + * Set by the netif driver in its init function. */ +#define NETIF_FLAG_BROADCAST 0x02U +/** If set, the netif is one end of a point-to-point connection. + * Set by the netif driver in its init function. */ +#define NETIF_FLAG_POINTTOPOINT 0x04U +/** If set, the interface is configured using DHCP. + * Set by the DHCP code when starting or stopping DHCP. */ +#define NETIF_FLAG_DHCP 0x08U +/** If set, the interface has an active link + * (set by the network interface driver). + * Either set by the netif driver in its init function (if the link + * is up at that time) or at a later point once the link comes up + * (if link detection is supported by the hardware). */ +#define NETIF_FLAG_LINK_UP 0x10U +/** If set, the netif is an ethernet device using ARP. + * Set by the netif driver in its init function. + * Used to check input packet types and use of DHCP. */ +#define NETIF_FLAG_ETHARP 0x20U +/** If set, the netif is an ethernet device. It might not use + * ARP or TCP/IP if it is used for PPPoE only. + */ +#define NETIF_FLAG_ETHERNET 0x40U +/** If set, the netif has IGMP capability. + * Set by the netif driver in its init function. */ +#define NETIF_FLAG_IGMP 0x80U + +/* Realtek Modified Start */ +/** if set, the netif has IP layer switch capability */ +#ifdef CONFIG_DONT_CARE_TP +#define NETIF_FLAG_IPSWITCH 0x100U +#endif +/* Realtek Modified End */ + +/** Function prototype for netif init functions. Set up flags and output/linkoutput + * callback functions in this function. + * + * @param netif The netif to initialize + */ +typedef err_t (*netif_init_fn)(struct netif *netif); +/** Function prototype for netif->input functions. This function is saved as 'input' + * callback function in the netif struct. Call it when a packet has been received. + * + * @param p The received packet, copied into a pbuf + * @param inp The netif which received the packet + */ +typedef err_t (*netif_input_fn)(struct pbuf *p, struct netif *inp); +/** Function prototype for netif->output functions. Called by lwIP when a packet + * shall be sent. For ethernet netif, set this to 'etharp_output' and set + * 'linkoutput'. + * + * @param netif The netif which shall send a packet + * @param p The packet to send (p->payload points to IP header) + * @param ipaddr The IP address to which the packet shall be sent + */ +typedef err_t (*netif_output_fn)(struct netif *netif, struct pbuf *p, + ip_addr_t *ipaddr); +#if LWIP_IPV6 +/** Function prototype for netif->output_ip6 functions. Called by lwIP when a packet + * shall be sent. For ethernet netif, set this to 'ethip6_output' and set + * 'linkoutput'. + * + * @param netif The netif which shall send a packet + * @param p The packet to send (p->payload points to IP header) + * @param ipaddr The IPv6 address to which the packet shall be sent + */ +typedef err_t (*netif_output_ip6_fn)(struct netif *netif, struct pbuf *p, + ip6_addr_t *ipaddr); +#endif /* LWIP_IPV6 */ +/** Function prototype for netif->linkoutput functions. Only used for ethernet + * netifs. This function is called by ARP when a packet shall be sent. + * + * @param netif The netif which shall send a packet + * @param p The packet to send (raw ethernet packet) + */ +typedef err_t (*netif_linkoutput_fn)(struct netif *netif, struct pbuf *p); +/** Function prototype for netif status- or link-callback functions. */ +typedef void (*netif_status_callback_fn)(struct netif *netif); +/** Function prototype for netif igmp_mac_filter functions */ +typedef err_t (*netif_igmp_mac_filter_fn)(struct netif *netif, + ip_addr_t *group, u8_t action); +#if LWIP_IPV6 && LWIP_IPV6_MLD +/** Function prototype for netif mld_mac_filter functions */ +typedef err_t (*netif_mld_mac_filter_fn)(struct netif *netif, + ip6_addr_t *group, u8_t action); +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ + +/** Generic data structure used for all lwIP network interfaces. + * The following fields should be filled in by the initialization + * function for the device driver: hwaddr_len, hwaddr[], mtu, flags */ +struct netif { + /** pointer to next in linked list */ + struct netif *next; + + /** IP address configuration in network byte order */ + ip_addr_t ip_addr; + ip_addr_t netmask; + ip_addr_t gw; + +#if LWIP_IPV6 + /** Array of IPv6 addresses for this netif. */ + ip6_addr_t ip6_addr[LWIP_IPV6_NUM_ADDRESSES]; + /** The state of each IPv6 address (Tentative, Preferred, etc). + * @see ip6_addr.h */ + u8_t ip6_addr_state[LWIP_IPV6_NUM_ADDRESSES]; +#endif /* LWIP_IPV6 */ + /** This function is called by the network device driver + * to pass a packet up the TCP/IP stack. */ + netif_input_fn input; + /** This function is called by the IP module when it wants + * to send a packet on the interface. This function typically + * first resolves the hardware address, then sends the packet. */ + netif_output_fn output; + /** This function is called by the ARP module when it wants + * to send a packet on the interface. This function outputs + * the pbuf as-is on the link medium. */ + netif_linkoutput_fn linkoutput; +#if LWIP_IPV6 + /** This function is called by the IPv6 module when it wants + * to send a packet on the interface. This function typically + * first resolves the hardware address, then sends the packet. */ + netif_output_ip6_fn output_ip6; +#endif /* LWIP_IPV6 */ +#if LWIP_NETIF_STATUS_CALLBACK + /** This function is called when the netif state is set to up or down + */ + netif_status_callback_fn status_callback; +#endif /* LWIP_NETIF_STATUS_CALLBACK */ +#if LWIP_NETIF_LINK_CALLBACK + /** This function is called when the netif link is set to up or down + */ + netif_status_callback_fn link_callback; +#endif /* LWIP_NETIF_LINK_CALLBACK */ +#if LWIP_NETIF_REMOVE_CALLBACK + /** This function is called when the netif has been removed */ + netif_status_callback_fn remove_callback; +#endif /* LWIP_NETIF_REMOVE_CALLBACK */ + /** This field can be set by the device driver and could point + * to state information for the device. */ + void *state; +#if LWIP_DHCP + /** the DHCP client state information for this netif */ + struct dhcp *dhcp; +#endif /* LWIP_DHCP */ +#if LWIP_AUTOIP + /** the AutoIP client state information for this netif */ + struct autoip *autoip; +#endif +#if LWIP_IPV6_AUTOCONFIG + /** is this netif enabled for IPv6 autoconfiguration */ + u8_t ip6_autoconfig_enabled; +#endif /* LWIP_IPV6_AUTOCONFIG */ +#if LWIP_IPV6_SEND_ROUTER_SOLICIT + /** Number of Router Solicitation messages that remain to be sent. */ + u8_t rs_count; +#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ +#if LWIP_IPV6_DHCP6 + /** the DHCPv6 client state information for this netif */ + struct dhcp6 *dhcp6; +#endif /* LWIP_IPV6_DHCP6 */ +#if LWIP_NETIF_HOSTNAME + /* the hostname for this netif, NULL is a valid value */ + char* hostname; +#endif /* LWIP_NETIF_HOSTNAME */ + /** maximum transfer unit (in bytes) */ + u16_t mtu; + /** number of bytes used in hwaddr */ + u8_t hwaddr_len; + /** link level hardware address of this interface */ + u8_t hwaddr[NETIF_MAX_HWADDR_LEN]; + /** flags (see NETIF_FLAG_ above) */ + //Realtek modified u8_t to u16_t for NETIF_FLAG_IPSWITCH extend flag + //u8_t flags; + u16_t flags; + //Realtek modified end + + /** descriptive abbreviation */ + char name[2]; + /** number of this interface */ + u8_t num; +#if LWIP_SNMP + /** link type (from "snmp_ifType" enum from snmp.h) */ + u8_t link_type; + /** (estimate) link speed */ + u32_t link_speed; + /** timestamp at last change made (up/down) */ + u32_t ts; + /** counters */ + u32_t ifinoctets; + u32_t ifinucastpkts; + u32_t ifinnucastpkts; + u32_t ifindiscards; + u32_t ifoutoctets; + u32_t ifoutucastpkts; + u32_t ifoutnucastpkts; + u32_t ifoutdiscards; +#endif /* LWIP_SNMP */ +#if LWIP_IGMP + /** This function could be called to add or delete an entry in the multicast + filter table of the ethernet MAC.*/ + netif_igmp_mac_filter_fn igmp_mac_filter; +#endif /* LWIP_IGMP */ +#if LWIP_IPV6 && LWIP_IPV6_MLD + /** This function could be called to add or delete an entry in the IPv6 multicast + filter table of the ethernet MAC. */ + netif_mld_mac_filter_fn mld_mac_filter; +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ +#if LWIP_NETIF_HWADDRHINT + u8_t *addr_hint; +#endif /* LWIP_NETIF_HWADDRHINT */ +#if ENABLE_LOOPBACK + /* List of packets to be queued for ourselves. */ + struct pbuf *loop_first; + struct pbuf *loop_last; +#if LWIP_LOOPBACK_MAX_PBUFS + u16_t loop_cnt_current; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ +#endif /* ENABLE_LOOPBACK */ +}; + +#if LWIP_SNMP +#define NETIF_INIT_SNMP(netif, type, speed) \ + /* use "snmp_ifType" enum from snmp.h for "type", snmp_ifType_ethernet_csmacd by example */ \ + (netif)->link_type = (type); \ + /* your link speed here (units: bits per second) */ \ + (netif)->link_speed = (speed); \ + (netif)->ts = 0; \ + (netif)->ifinoctets = 0; \ + (netif)->ifinucastpkts = 0; \ + (netif)->ifinnucastpkts = 0; \ + (netif)->ifindiscards = 0; \ + (netif)->ifoutoctets = 0; \ + (netif)->ifoutucastpkts = 0; \ + (netif)->ifoutnucastpkts = 0; \ + (netif)->ifoutdiscards = 0 +#else /* LWIP_SNMP */ +#define NETIF_INIT_SNMP(netif, type, speed) +#endif /* LWIP_SNMP */ + + +/** The list of network interfaces. */ +extern struct netif *netif_list; +/** The default network interface. */ +extern struct netif *netif_default; + +void netif_init(void); + +struct netif *netif_add(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask, + ip_addr_t *gw, void *state, netif_init_fn init, netif_input_fn input); + +void +netif_set_addr(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask, + ip_addr_t *gw); +void netif_remove(struct netif * netif); + +/* Returns a network interface given its name. The name is of the form + "et0", where the first two letters are the "name" field in the + netif structure, and the digit is in the num field in the same + structure. */ +struct netif *netif_find(char *name); + +void netif_set_default(struct netif *netif); + +void netif_set_ipaddr(struct netif *netif, ip_addr_t *ipaddr); +void netif_set_netmask(struct netif *netif, ip_addr_t *netmask); +void netif_set_gw(struct netif *netif, ip_addr_t *gw); + +void netif_set_up(struct netif *netif); +void netif_set_down(struct netif *netif); +/** Ask if an interface is up */ +#define netif_is_up(netif) (((netif)->flags & NETIF_FLAG_UP) ? (u8_t)1 : (u8_t)0) + +#if LWIP_NETIF_STATUS_CALLBACK +void netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback); +#endif /* LWIP_NETIF_STATUS_CALLBACK */ +#if LWIP_NETIF_REMOVE_CALLBACK +void netif_set_remove_callback(struct netif *netif, netif_status_callback_fn remove_callback); +#endif /* LWIP_NETIF_REMOVE_CALLBACK */ + +void netif_set_link_up(struct netif *netif); +void netif_set_link_down(struct netif *netif); +/** Ask if a link is up */ +#define netif_is_link_up(netif) (((netif)->flags & NETIF_FLAG_LINK_UP) ? (u8_t)1 : (u8_t)0) + +#if LWIP_NETIF_LINK_CALLBACK +void netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback); +#endif /* LWIP_NETIF_LINK_CALLBACK */ + +#if LWIP_NETIF_HOSTNAME +#define netif_set_hostname(netif, name) do { if((netif) != NULL) { (netif)->hostname = name; }}while(0) +#define netif_get_hostname(netif) (((netif) != NULL) ? ((netif)->hostname) : NULL) +#endif /* LWIP_NETIF_HOSTNAME */ + +#if LWIP_IGMP +#define netif_set_igmp_mac_filter(netif, function) do { if((netif) != NULL) { (netif)->igmp_mac_filter = function; }}while(0) +#define netif_get_igmp_mac_filter(netif) (((netif) != NULL) ? ((netif)->igmp_mac_filter) : NULL) +#endif /* LWIP_IGMP */ + +#if ENABLE_LOOPBACK +err_t netif_loop_output(struct netif *netif, struct pbuf *p); +void netif_poll(struct netif *netif); +#if !LWIP_NETIF_LOOPBACK_MULTITHREADING +void netif_poll_all(void); +#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */ +#endif /* ENABLE_LOOPBACK */ + +#if LWIP_IPV6 +#define netif_ip6_addr(netif, i) (&((netif)->ip6_addr[(i)])) +#define netif_ip6_addr_state(netif, i) ((netif)->ip6_addr_state[(i)]) +#define netif_ip6_addr_set_state(netif, i, state) ((netif)->ip6_addr_state[(i)] = (state)) +s8_t netif_get_ip6_addr_match(struct netif * netif, ip6_addr_t * ip6addr); +void netif_create_ip6_linklocal_address(struct netif * netif, u8_t from_mac_48bit); +#endif /* LWIP_IPV6 */ + +#if LWIP_NETIF_HWADDRHINT +#define NETIF_SET_HWADDRHINT(netif, hint) ((netif)->addr_hint = (hint)) +#else /* LWIP_NETIF_HWADDRHINT */ +#define NETIF_SET_HWADDRHINT(netif, hint) +#endif /* LWIP_NETIF_HWADDRHINT */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_NETIF_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/netifapi.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/netifapi.h new file mode 100644 index 0000000..5d7738a --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/netifapi.h @@ -0,0 +1,117 @@ +/* + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#ifndef LWIP_HDR_NETIFAPI_H +#define LWIP_HDR_NETIFAPI_H + +#include "lwip/opt.h" + +#if LWIP_NETIF_API /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/sys.h" +#include "lwip/netif.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_MPU_COMPATIBLE +#define NETIFAPI_IPADDR_DEF(m) m +#else /* LWIP_MPU_COMPATIBLE */ +#define NETIFAPI_IPADDR_DEF(m) *m +#endif /* LWIP_MPU_COMPATIBLE */ + +typedef void (*netifapi_void_fn)(struct netif *netif); +typedef err_t (*netifapi_errt_fn)(struct netif *netif); + +struct netifapi_msg_msg { +#if !LWIP_TCPIP_CORE_LOCKING + sys_sem_t sem; +#endif /* !LWIP_TCPIP_CORE_LOCKING */ + err_t err; + struct netif *netif; + union { + struct { + ip_addr_t NETIFAPI_IPADDR_DEF(ipaddr); + ip_addr_t NETIFAPI_IPADDR_DEF(netmask); + ip_addr_t NETIFAPI_IPADDR_DEF(gw); + void *state; + netif_init_fn init; + netif_input_fn input; + } add; + struct { + netifapi_void_fn voidfunc; + netifapi_errt_fn errtfunc; + } common; + } msg; +}; + +struct netifapi_msg { + void (* function)(struct netifapi_msg_msg *msg); + struct netifapi_msg_msg msg; +}; + + +/* API for application */ +err_t netifapi_netif_add ( struct netif *netif, + ip_addr_t *ipaddr, + ip_addr_t *netmask, + ip_addr_t *gw, + void *state, + netif_init_fn init, + netif_input_fn input); + +err_t netifapi_netif_set_addr ( struct netif *netif, + ip_addr_t *ipaddr, + ip_addr_t *netmask, + ip_addr_t *gw ); + +err_t netifapi_netif_common ( struct netif *netif, + netifapi_void_fn voidfunc, + netifapi_errt_fn errtfunc); + +#define netifapi_netif_remove(n) netifapi_netif_common(n, netif_remove, NULL) +#define netifapi_netif_set_up(n) netifapi_netif_common(n, netif_set_up, NULL) +#define netifapi_netif_set_down(n) netifapi_netif_common(n, netif_set_down, NULL) +#define netifapi_netif_set_default(n) netifapi_netif_common(n, netif_set_default, NULL) +#define netifapi_dhcp_start(n) netifapi_netif_common(n, NULL, dhcp_start) +#define netifapi_dhcp_stop(n) netifapi_netif_common(n, dhcp_stop, NULL) +#define netifapi_dhcp_inform(n) netifapi_netif_common(n, dhcp_inform, NULL) +#define netifapi_dhcp_renew(n) netifapi_netif_common(n, NULL, dhcp_renew) +#define netifapi_dhcp_release(n) netifapi_netif_common(n, NULL, dhcp_release) +#define netifapi_autoip_start(n) netifapi_netif_common(n, NULL, autoip_start) +#define netifapi_autoip_stop(n) netifapi_netif_common(n, NULL, autoip_stop) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_NETIF_API */ + +#endif /* LWIP_HDR_NETIFAPI_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/opt.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/opt.h new file mode 100644 index 0000000..7e8511d --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/opt.h @@ -0,0 +1,2773 @@ +/** + * @file + * + * lwIP Options Configuration + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_OPT_H +#define LWIP_HDR_OPT_H + +/* + * Include user defined options first. Anything not defined in these files + * will be set to standard values. Override anything you don't like! + */ +#include "lwipopts.h" +#include "lwip/debug.h" + +/* + ----------------------------------------------- + ---------- Platform specific locking ---------- + ----------------------------------------------- +*/ + +/** + * SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain + * critical regions during buffer allocation, deallocation and memory + * allocation and deallocation. + */ +#ifndef SYS_LIGHTWEIGHT_PROT +#define SYS_LIGHTWEIGHT_PROT 0 +#endif + +/** + * NO_SYS==1: Provides VERY minimal functionality. Otherwise, + * use lwIP facilities. + */ +#ifndef NO_SYS +#define NO_SYS 0 +#endif + +/** + * NO_SYS_NO_TIMERS==1: Drop support for sys_timeout when NO_SYS==1 + * Mainly for compatibility to old versions. + */ +#ifndef NO_SYS_NO_TIMERS +#define NO_SYS_NO_TIMERS 0 +#endif + +/** + * MEMCPY: override this if you have a faster implementation at hand than the + * one included in your C library + */ +#ifndef MEMCPY +#define MEMCPY(dst,src,len) memcpy(dst,src,len) +#endif + +/** + * SMEMCPY: override this with care! Some compilers (e.g. gcc) can inline a + * call to memcpy() if the length is known at compile time and is small. + */ +#ifndef SMEMCPY +#define SMEMCPY(dst,src,len) memcpy(dst,src,len) +#endif + +/** + * LWIP_MPU_COMPATIBLE: enables special memory management mechanism + * which makes lwip able to work on MPU (Memory Protection Unit) system + * by not passing stack-pointers to other threads + * (this decreases performance) + */ +#ifndef LWIP_MPU_COMPATIBLE +#define LWIP_MPU_COMPATIBLE 0 +#endif + +/* + ------------------------------------ + ---------- Memory options ---------- + ------------------------------------ +*/ +/** + * MEM_LIBC_MALLOC==1: Use malloc/free/realloc provided by your C-library + * instead of the lwip internal allocator. Can save code size if you + * already use it. + */ +#ifndef MEM_LIBC_MALLOC +#define MEM_LIBC_MALLOC 0 +#endif + +/** +* MEMP_MEM_MALLOC==1: Use mem_malloc/mem_free instead of the lwip pool allocator. +* Especially useful with MEM_LIBC_MALLOC but handle with care regarding execution +* speed and usage from interrupts! +*/ +#ifndef MEMP_MEM_MALLOC +#define MEMP_MEM_MALLOC 0 +#endif + +/** + * MEM_ALIGNMENT: should be set to the alignment of the CPU + * 4 byte alignment -> #define MEM_ALIGNMENT 4 + * 2 byte alignment -> #define MEM_ALIGNMENT 2 + */ +#ifndef MEM_ALIGNMENT +#define MEM_ALIGNMENT 1 +#endif + +/** + * MEM_SIZE: the size of the heap memory. If the application will send + * a lot of data that needs to be copied, this should be set high. + */ +#ifndef MEM_SIZE +#define MEM_SIZE 1600 +#endif + +/** + * MEMP_SEPARATE_POOLS: if defined to 1, each pool is placed in its own array. + * This can be used to individually change the location of each pool. + * Default is one big array for all pools + */ +#ifndef MEMP_SEPARATE_POOLS +#define MEMP_SEPARATE_POOLS 0 +#endif + +/** + * MEMP_OVERFLOW_CHECK: memp overflow protection reserves a configurable + * amount of bytes before and after each memp element in every pool and fills + * it with a prominent default value. + * MEMP_OVERFLOW_CHECK == 0 no checking + * MEMP_OVERFLOW_CHECK == 1 checks each element when it is freed + * MEMP_OVERFLOW_CHECK >= 2 checks each element in every pool every time + * memp_malloc() or memp_free() is called (useful but slow!) + */ +#ifndef MEMP_OVERFLOW_CHECK +#define MEMP_OVERFLOW_CHECK 0 +#endif + +/** + * MEMP_SANITY_CHECK==1: run a sanity check after each memp_free() to make + * sure that there are no cycles in the linked lists. + */ +#ifndef MEMP_SANITY_CHECK +#define MEMP_SANITY_CHECK 0 +#endif + +/** + * MEM_USE_POOLS==1: Use an alternative to malloc() by allocating from a set + * of memory pools of various sizes. When mem_malloc is called, an element of + * the smallest pool that can provide the length needed is returned. + * To use this, MEMP_USE_CUSTOM_POOLS also has to be enabled. + */ +#ifndef MEM_USE_POOLS +#define MEM_USE_POOLS 0 +#endif + +/** + * MEM_USE_POOLS_TRY_BIGGER_POOL==1: if one malloc-pool is empty, try the next + * bigger pool - WARNING: THIS MIGHT WASTE MEMORY but it can make a system more + * reliable. */ +#ifndef MEM_USE_POOLS_TRY_BIGGER_POOL +#define MEM_USE_POOLS_TRY_BIGGER_POOL 0 +#endif + +/** + * MEMP_USE_CUSTOM_POOLS==1: whether to include a user file lwippools.h + * that defines additional pools beyond the "standard" ones required + * by lwIP. If you set this to 1, you must have lwippools.h in your + * include path somewhere. + */ +#ifndef MEMP_USE_CUSTOM_POOLS +#define MEMP_USE_CUSTOM_POOLS 0 +#endif + +/** + * Set this to 1 if you want to free PBUF_RAM pbufs (or call mem_free()) from + * interrupt context (or another context that doesn't allow waiting for a + * semaphore). + * If set to 1, mem_malloc will be protected by a semaphore and SYS_ARCH_PROTECT, + * while mem_free will only use SYS_ARCH_PROTECT. mem_malloc SYS_ARCH_UNPROTECTs + * with each loop so that mem_free can run. + * + * ATTENTION: As you can see from the above description, this leads to dis-/ + * enabling interrupts often, which can be slow! Also, on low memory, mem_malloc + * can need longer. + * + * If you don't want that, at least for NO_SYS=0, you can still use the following + * functions to enqueue a deallocation call which then runs in the tcpip_thread + * context: + * - pbuf_free_callback(p); + * - mem_free_callback(m); + */ +#ifndef LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT +#define LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT 0 +#endif + +/* + ------------------------------------------------ + ---------- Internal Memory Pool Sizes ---------- + ------------------------------------------------ +*/ +/** + * MEMP_NUM_PBUF: the number of memp struct pbufs (used for PBUF_ROM and PBUF_REF). + * If the application sends a lot of data out of ROM (or other static memory), + * this should be set high. + */ +#ifndef MEMP_NUM_PBUF +#define MEMP_NUM_PBUF 16 +#endif + +/** + * MEMP_NUM_RAW_PCB: Number of raw connection PCBs + * (requires the LWIP_RAW option) + */ +#ifndef MEMP_NUM_RAW_PCB +#define MEMP_NUM_RAW_PCB 4 +#endif + +/** + * MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One + * per active UDP "connection". + * (requires the LWIP_UDP option) + */ +#ifndef MEMP_NUM_UDP_PCB +#define MEMP_NUM_UDP_PCB 4 +#endif + +/** + * MEMP_NUM_TCP_PCB: the number of simultaneously active TCP connections. + * (requires the LWIP_TCP option) + */ +#ifndef MEMP_NUM_TCP_PCB +#define MEMP_NUM_TCP_PCB 5 +#endif + +/** + * MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP connections. + * (requires the LWIP_TCP option) + */ +#ifndef MEMP_NUM_TCP_PCB_LISTEN +#define MEMP_NUM_TCP_PCB_LISTEN 8 +#endif + +/** + * MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP segments. + * (requires the LWIP_TCP option) + */ +#ifndef MEMP_NUM_TCP_SEG +#define MEMP_NUM_TCP_SEG 16 +#endif + +/** + * MEMP_NUM_REASSDATA: the number of IP packets simultaneously queued for + * reassembly (whole packets, not fragments!) + */ +#ifndef MEMP_NUM_REASSDATA +#define MEMP_NUM_REASSDATA 5 +#endif + +/** + * MEMP_NUM_FRAG_PBUF: the number of IP fragments simultaneously sent + * (fragments, not whole packets!). + * This is only used with IP_FRAG_USES_STATIC_BUF==0 and + * LWIP_NETIF_TX_SINGLE_PBUF==0 and only has to be > 1 with DMA-enabled MACs + * where the packet is not yet sent when netif->output returns. + */ +#ifndef MEMP_NUM_FRAG_PBUF +#define MEMP_NUM_FRAG_PBUF 15 +#endif + +/** + * MEMP_NUM_ARP_QUEUE: the number of simultaneously queued outgoing + * packets (pbufs) that are waiting for an ARP request (to resolve + * their destination address) to finish. + * (requires the ARP_QUEUEING option) + */ +#ifndef MEMP_NUM_ARP_QUEUE +#define MEMP_NUM_ARP_QUEUE 30 +#endif + +/** + * MEMP_NUM_IGMP_GROUP: The number of multicast groups whose network interfaces + * can be members at the same time (one per netif - allsystems group -, plus one + * per netif membership). + * (requires the LWIP_IGMP option) + */ +#ifndef MEMP_NUM_IGMP_GROUP +#define MEMP_NUM_IGMP_GROUP 8 +#endif + +/** + * MEMP_NUM_SYS_TIMEOUT: the number of simultaneously active timeouts. + * The default number of timeouts is calculated here for all enabled modules. + * The formula expects settings to be either '0' or '1'. + */ +#ifndef MEMP_NUM_SYS_TIMEOUT +#define MEMP_NUM_SYS_TIMEOUT (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + (PPP_SUPPORT*6*MEMP_NUM_PPP_PCB) + (LWIP_IPV6 ? (1 + LWIP_IPV6_REASS + LWIP_IPV6_MLD) : 0)) +#endif + +/** + * MEMP_NUM_NETBUF: the number of struct netbufs. + * (only needed if you use the sequential API, like api_lib.c) + */ +#ifndef MEMP_NUM_NETBUF +#define MEMP_NUM_NETBUF 2 +#endif + +/** + * MEMP_NUM_NETCONN: the number of struct netconns. + * (only needed if you use the sequential API, like api_lib.c) + */ +#ifndef MEMP_NUM_NETCONN +#define MEMP_NUM_NETCONN 4 +#endif + +/** + * MEMP_NUM_TCPIP_MSG_API: the number of struct tcpip_msg, which are used + * for callback/timeout API communication. + * (only needed if you use tcpip.c) + */ +#ifndef MEMP_NUM_TCPIP_MSG_API +#define MEMP_NUM_TCPIP_MSG_API 8 +#endif + +/** + * MEMP_NUM_TCPIP_MSG_INPKT: the number of struct tcpip_msg, which are used + * for incoming packets. + * (only needed if you use tcpip.c) + */ +#ifndef MEMP_NUM_TCPIP_MSG_INPKT +#define MEMP_NUM_TCPIP_MSG_INPKT 8 +#endif + +/** + * MEMP_NUM_SNMP_NODE: the number of leafs in the SNMP tree. + */ +#ifndef MEMP_NUM_SNMP_NODE +#define MEMP_NUM_SNMP_NODE 50 +#endif + +/** + * MEMP_NUM_SNMP_ROOTNODE: the number of branches in the SNMP tree. + * Every branch has one leaf (MEMP_NUM_SNMP_NODE) at least! + */ +#ifndef MEMP_NUM_SNMP_ROOTNODE +#define MEMP_NUM_SNMP_ROOTNODE 30 +#endif + +/** + * MEMP_NUM_SNMP_VARBIND: the number of concurrent requests (does not have to + * be changed normally) - 2 of these are used per request (1 for input, + * 1 for output) + */ +#ifndef MEMP_NUM_SNMP_VARBIND +#define MEMP_NUM_SNMP_VARBIND 2 +#endif + +/** + * MEMP_NUM_SNMP_VALUE: the number of OID or values concurrently used + * (does not have to be changed normally) - 3 of these are used per request + * (1 for the value read and 2 for OIDs - input and output) + */ +#ifndef MEMP_NUM_SNMP_VALUE +#define MEMP_NUM_SNMP_VALUE 3 +#endif + +/** + * MEMP_NUM_NETDB: the number of concurrently running lwip_addrinfo() calls + * (before freeing the corresponding memory using lwip_freeaddrinfo()). + */ +#ifndef MEMP_NUM_NETDB +#define MEMP_NUM_NETDB 1 +#endif + +/** + * MEMP_NUM_LOCALHOSTLIST: the number of host entries in the local host list + * if DNS_LOCAL_HOSTLIST_IS_DYNAMIC==1. + */ +#ifndef MEMP_NUM_LOCALHOSTLIST +#define MEMP_NUM_LOCALHOSTLIST 1 +#endif + +/** + * MEMP_NUM_PPP_PCB: the number of simultaneously active PPP + * connections (requires the PPP_SUPPORT option) + */ +#ifndef MEMP_NUM_PPP_PCB +#define MEMP_NUM_PPP_PCB 1 +#endif + +/** + * MEMP_NUM_PPPOE_INTERFACES: the number of concurrently active PPPoE + * interfaces (only used with PPPOE_SUPPORT==1) + */ +#ifndef MEMP_NUM_PPPOE_INTERFACES +#define MEMP_NUM_PPPOE_INTERFACES 1 +#endif + +/** + * MEMP_NUM_PPPOL2TP_INTERFACES: the number of concurrently active PPPoL2TP + * interfaces (only used with PPPOL2TP_SUPPORT==1) + */ +#ifndef MEMP_NUM_PPPOL2TP_INTERFACES +#define MEMP_NUM_PPPOL2TP_INTERFACES 1 +#endif + +/** + * PBUF_POOL_SIZE: the number of buffers in the pbuf pool. + */ +#ifndef PBUF_POOL_SIZE +#define PBUF_POOL_SIZE 16 +#endif + +/** MEMP_NUM_API_MSG: the number of concurrently active calls to various + * socket, netconn, and tcpip functions + */ +#ifndef MEMP_NUM_API_MSG +#define MEMP_NUM_API_MSG MEMP_NUM_TCPIP_MSG_API +#endif + +/** MEMP_NUM_DNS_API_MSG: the number of concurrently active calls to netconn_gethostbyname + */ +#ifndef MEMP_NUM_DNS_API_MSG +#define MEMP_NUM_DNS_API_MSG MEMP_NUM_TCPIP_MSG_API +#endif + +/** MEMP_NUM_SOCKET_SETGETSOCKOPT_DATA: the number of concurrently active calls + * to getsockopt/setsockopt + */ +#ifndef MEMP_NUM_SOCKET_SETGETSOCKOPT_DATA +#define MEMP_NUM_SOCKET_SETGETSOCKOPT_DATA MEMP_NUM_TCPIP_MSG_API +#endif + +/** MEMP_NUM_NETIFAPI_MSG: the number of concurrently active calls to the + * netifapi functions + */ +#ifndef MEMP_NUM_NETIFAPI_MSG +#define MEMP_NUM_NETIFAPI_MSG MEMP_NUM_TCPIP_MSG_API +#endif + +/* + --------------------------------- + ---------- ARP options ---------- + --------------------------------- +*/ +/** + * LWIP_ARP==1: Enable ARP functionality. + */ +#ifndef LWIP_ARP +#define LWIP_ARP 1 +#endif + +/** + * ARP_TABLE_SIZE: Number of active MAC-IP address pairs cached. + */ +#ifndef ARP_TABLE_SIZE +#define ARP_TABLE_SIZE 10 +#endif + +/** + * ARP_QUEUEING==1: Multiple outgoing packets are queued during hardware address + * resolution. By default, only the most recent packet is queued per IP address. + * This is sufficient for most protocols and mainly reduces TCP connection + * startup time. Set this to 1 if you know your application sends more than one + * packet in a row to an IP address that is not in the ARP cache. + */ +#ifndef ARP_QUEUEING +#define ARP_QUEUEING 1 //Realtek changed 0 -> 1 +#endif + +/** The maximum number of packets which may be queued for each + * unresolved address by other network layers. Defaults to 3, 0 means disabled. + * Old packets are dropped, new packets are queued. + */ +#ifndef ARP_QUEUE_LEN +#define ARP_QUEUE_LEN 0 //Realtek changed 3 -> 0 +#endif + +/** + * ETHARP_TRUST_IP_MAC==1: Incoming IP packets cause the ARP table to be + * updated with the source MAC and IP addresses supplied in the packet. + * You may want to disable this if you do not trust LAN peers to have the + * correct addresses, or as a limited approach to attempt to handle + * spoofing. If disabled, lwIP will need to make a new ARP request if + * the peer is not already in the ARP table, adding a little latency. + * The peer *is* in the ARP table if it requested our address before. + * Also notice that this slows down input processing of every IP packet! + */ +#ifndef ETHARP_TRUST_IP_MAC +#define ETHARP_TRUST_IP_MAC 1 //Realtek changed 0 -> 1 +#endif + +/** + * ETHARP_SUPPORT_VLAN==1: support receiving and sending ethernet packets with + * VLAN header. See the description of LWIP_HOOK_VLAN_CHECK and + * LWIP_HOOK_VLAN_SET hooks to check/set VLAN headers. + * Additionally, you can define ETHARP_VLAN_CHECK to an u16_t VLAN ID to check. + * If ETHARP_VLAN_CHECK is defined, only VLAN-traffic for this VLAN is accepted. + * If ETHARP_VLAN_CHECK is not defined, all traffic is accepted. + * Alternatively, define a function/define ETHARP_VLAN_CHECK_FN(eth_hdr, vlan) + * that returns 1 to accept a packet or 0 to drop a packet. + */ +#ifndef ETHARP_SUPPORT_VLAN +#define ETHARP_SUPPORT_VLAN 0 +#endif + +/** LWIP_ETHERNET==1: enable ethernet support for PPPoE even though ARP + * might be disabled + */ +#ifndef LWIP_ETHERNET +#define LWIP_ETHERNET (LWIP_ARP || PPPOE_SUPPORT) +#endif + +/** ETH_PAD_SIZE: number of bytes added before the ethernet header to ensure + * alignment of payload after that header. Since the header is 14 bytes long, + * without this padding e.g. addresses in the IP header will not be aligned + * on a 32-bit boundary, so setting this to 2 can speed up 32-bit-platforms. + */ +#ifndef ETH_PAD_SIZE +#define ETH_PAD_SIZE 0 +#endif + +/** ETHARP_SUPPORT_STATIC_ENTRIES==1: enable code to support static ARP table + * entries (using etharp_add_static_entry/etharp_remove_static_entry). + */ +#ifndef ETHARP_SUPPORT_STATIC_ENTRIES +#define ETHARP_SUPPORT_STATIC_ENTRIES 0 +#endif + + +/* + -------------------------------- + ---------- IP options ---------- + -------------------------------- +*/ +/** + * IP_FORWARD==1: Enables the ability to forward IP packets across network + * interfaces. If you are going to run lwIP on a device with only one network + * interface, define this to 0. + */ +#ifndef IP_FORWARD +#define IP_FORWARD 0 +#endif + +/** + * IP_OPTIONS_ALLOWED: Defines the behavior for IP options. + * IP_OPTIONS_ALLOWED==0: All packets with IP options are dropped. + * IP_OPTIONS_ALLOWED==1: IP options are allowed (but not parsed). + */ +#ifndef IP_OPTIONS_ALLOWED +#define IP_OPTIONS_ALLOWED 1 +#endif + +/** + * IP_REASSEMBLY==1: Reassemble incoming fragmented IP packets. Note that + * this option does not affect outgoing packet sizes, which can be controlled + * via IP_FRAG. + */ +#ifndef IP_REASSEMBLY +#define IP_REASSEMBLY 1 +#endif + +/** + * IP_FRAG==1: Fragment outgoing IP packets if their size exceeds MTU. Note + * that this option does not affect incoming packet sizes, which can be + * controlled via IP_REASSEMBLY. + */ +#ifndef IP_FRAG +#define IP_FRAG 1 +#endif + +/** + * IP_REASS_MAXAGE: Maximum time (in multiples of IP_TMR_INTERVAL - so seconds, normally) + * a fragmented IP packet waits for all fragments to arrive. If not all fragments arrived + * in this time, the whole packet is discarded. + */ +#ifndef IP_REASS_MAXAGE +#define IP_REASS_MAXAGE 3 +#endif + +/** + * IP_REASS_MAX_PBUFS: Total maximum amount of pbufs waiting to be reassembled. + * Since the received pbufs are enqueued, be sure to configure + * PBUF_POOL_SIZE > IP_REASS_MAX_PBUFS so that the stack is still able to receive + * packets even if the maximum amount of fragments is enqueued for reassembly! + */ +#ifndef IP_REASS_MAX_PBUFS +#define IP_REASS_MAX_PBUFS 10 +#endif + +/** + * IP_FRAG_USES_STATIC_BUF==1: Use a static MTU-sized buffer for IP + * fragmentation. Otherwise pbufs are allocated and reference the original + * packet data to be fragmented (or with LWIP_NETIF_TX_SINGLE_PBUF==1, + * new PBUF_RAM pbufs are used for fragments). + * ATTENTION: IP_FRAG_USES_STATIC_BUF==1 may not be used for DMA-enabled MACs! + */ +#ifndef IP_FRAG_USES_STATIC_BUF +#define IP_FRAG_USES_STATIC_BUF 0 +#endif + +/** + * IP_FRAG_MAX_MTU: Assumed max MTU on any interface for IP frag buffer + * (requires IP_FRAG_USES_STATIC_BUF==1) + */ +#if IP_FRAG_USES_STATIC_BUF && !defined(IP_FRAG_MAX_MTU) +#define IP_FRAG_MAX_MTU 1500 +#endif + +/** + * IP_DEFAULT_TTL: Default value for Time-To-Live used by transport layers. + */ +#ifndef IP_DEFAULT_TTL +#define IP_DEFAULT_TTL 255 +#endif + +/** + * IP_SOF_BROADCAST=1: Use the SOF_BROADCAST field to enable broadcast + * filter per pcb on udp and raw send operations. To enable broadcast filter + * on recv operations, you also have to set IP_SOF_BROADCAST_RECV=1. + */ +#ifndef IP_SOF_BROADCAST +#define IP_SOF_BROADCAST 0 +#endif + +/** + * IP_SOF_BROADCAST_RECV (requires IP_SOF_BROADCAST=1) enable the broadcast + * filter on recv operations. + */ +#ifndef IP_SOF_BROADCAST_RECV +#define IP_SOF_BROADCAST_RECV 0 +#endif + +/** + * IP_FORWARD_ALLOW_TX_ON_RX_NETIF==1: allow ip_forward() to send packets back + * out on the netif where it was received. This should only be used for + * wireless networks. + * ATTENTION: When this is 1, make sure your netif driver correctly marks incoming + * link-layer-broadcast/multicast packets as such using the corresponding pbuf flags! + */ +#ifndef IP_FORWARD_ALLOW_TX_ON_RX_NETIF +#define IP_FORWARD_ALLOW_TX_ON_RX_NETIF 0 +#endif + +/** + * LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS==1: randomize the local port for the first + * local TCP/UDP pcb (default==0). This can prevent creating predictable port + * numbers after booting a device. + */ +#ifndef LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS +#define LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS 0 +#endif + +/* + ---------------------------------- + ---------- ICMP options ---------- + ---------------------------------- +*/ +/** + * LWIP_ICMP==1: Enable ICMP module inside the IP stack. + * Be careful, disable that make your product non-compliant to RFC1122 + */ +#ifndef LWIP_ICMP +#define LWIP_ICMP 1 +#endif + +/** + * ICMP_TTL: Default value for Time-To-Live used by ICMP packets. + */ +#ifndef ICMP_TTL +#define ICMP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * LWIP_BROADCAST_PING==1: respond to broadcast pings (default is unicast only) + */ +#ifndef LWIP_BROADCAST_PING +#define LWIP_BROADCAST_PING 0 +#endif + +/** + * LWIP_MULTICAST_PING==1: respond to multicast pings (default is unicast only) + */ +#ifndef LWIP_MULTICAST_PING +#define LWIP_MULTICAST_PING 0 +#endif + +/* + --------------------------------- + ---------- RAW options ---------- + --------------------------------- +*/ +/** + * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. + */ +#ifndef LWIP_RAW +#define LWIP_RAW 1 +#endif + +/** + * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. + */ +#ifndef RAW_TTL +#define RAW_TTL (IP_DEFAULT_TTL) +#endif + +/* + ---------------------------------- + ---------- DHCP options ---------- + ---------------------------------- +*/ +/** + * LWIP_DHCP==1: Enable DHCP module. + */ +#ifndef LWIP_DHCP +#define LWIP_DHCP 0 +#endif + +/** + * DHCP_DOES_ARP_CHECK==1: Do an ARP check on the offered address. + */ +#ifndef DHCP_DOES_ARP_CHECK +#define DHCP_DOES_ARP_CHECK ((LWIP_DHCP) && (LWIP_ARP)) +#endif + +/** + * LWIP_DHCP_CHECK_LINK_UP==1: dhcp_start() only really starts if the netif has + * NETIF_FLAG_LINK_UP set in its flags. As this is only an optimization and + * netif drivers might not set this flag, the default is off. If enabled, + * netif_set_link_up() must be called to continue dhcp starting. + */ +#ifndef LWIP_DHCP_CHECK_LINK_UP +#define LWIP_DHCP_CHECK_LINK_UP 0 +#endif + +/** + * LWIP_DHCP_BOOTP_FILE==1: Store offered_si_addr and boot_file_name. + */ +#ifndef LWIP_DHCP_BOOTP_FILE +#define LWIP_DHCP_BOOTP_FILE 0 +#endif + +/* + ------------------------------------ + ---------- AUTOIP options ---------- + ------------------------------------ +*/ +/** + * LWIP_AUTOIP==1: Enable AUTOIP module. + */ +#ifndef LWIP_AUTOIP +#define LWIP_AUTOIP 1 //Realtek modified (0->1) +#endif + +/** + * LWIP_DHCP_AUTOIP_COOP==1: Allow DHCP and AUTOIP to be both enabled on + * the same interface at the same time. + */ +#ifndef LWIP_DHCP_AUTOIP_COOP +#define LWIP_DHCP_AUTOIP_COOP 0 +#endif + +/** + * LWIP_DHCP_AUTOIP_COOP_TRIES: Set to the number of DHCP DISCOVER probes + * that should be sent before falling back on AUTOIP. This can be set + * as low as 1 to get an AutoIP address very quickly, but you should + * be prepared to handle a changing IP address when DHCP overrides + * AutoIP. + */ +#ifndef LWIP_DHCP_AUTOIP_COOP_TRIES +#define LWIP_DHCP_AUTOIP_COOP_TRIES 9 +#endif + +/* + ---------------------------------- + ---------- SNMP options ---------- + ---------------------------------- +*/ +/** + * LWIP_SNMP==1: Turn on SNMP module. UDP must be available for SNMP + * transport. + */ +#ifndef LWIP_SNMP +#define LWIP_SNMP 0 +#endif + +/** + * SNMP_CONCURRENT_REQUESTS: Number of concurrent requests the module will + * allow. At least one request buffer is required. + * Does not have to be changed unless external MIBs answer request asynchronously + */ +#ifndef SNMP_CONCURRENT_REQUESTS +#define SNMP_CONCURRENT_REQUESTS 1 +#endif + +/** + * SNMP_TRAP_DESTINATIONS: Number of trap destinations. At least one trap + * destination is required + */ +#ifndef SNMP_TRAP_DESTINATIONS +#define SNMP_TRAP_DESTINATIONS 1 +#endif + +/** + * SNMP_PRIVATE_MIB: + * When using a private MIB, you have to create a file 'private_mib.h' that contains + * a 'struct mib_array_node mib_private' which contains your MIB. + */ +#ifndef SNMP_PRIVATE_MIB +#define SNMP_PRIVATE_MIB 0 +#endif + +/** + * Only allow SNMP write actions that are 'safe' (e.g. disabling netifs is not + * a safe action and disabled when SNMP_SAFE_REQUESTS = 1). + * Unsafe requests are disabled by default! + */ +#ifndef SNMP_SAFE_REQUESTS +#define SNMP_SAFE_REQUESTS 1 +#endif + +/** + * The maximum length of strings used. This affects the size of + * MEMP_SNMP_VALUE elements. + */ +#ifndef SNMP_MAX_OCTET_STRING_LEN +#define SNMP_MAX_OCTET_STRING_LEN 127 +#endif + +/** + * The maximum depth of the SNMP tree. + * With private MIBs enabled, this depends on your MIB! + * This affects the size of MEMP_SNMP_VALUE elements. + */ +#ifndef SNMP_MAX_TREE_DEPTH +#define SNMP_MAX_TREE_DEPTH 15 +#endif + +/** + * The size of the MEMP_SNMP_VALUE elements, normally calculated from + * SNMP_MAX_OCTET_STRING_LEN and SNMP_MAX_TREE_DEPTH. + */ +#ifndef SNMP_MAX_VALUE_SIZE +#define SNMP_MAX_VALUE_SIZE LWIP_MAX((SNMP_MAX_OCTET_STRING_LEN)+1, sizeof(s32_t)*(SNMP_MAX_TREE_DEPTH)) +#endif + +/* + ---------------------------------- + ---------- IGMP options ---------- + ---------------------------------- +*/ +/** + * LWIP_IGMP==1: Turn on IGMP module. + */ +#ifndef LWIP_IGMP +#define LWIP_IGMP 0 +#endif + +/* + ---------------------------------- + ---------- DNS options ----------- + ---------------------------------- +*/ +/** + * LWIP_DNS==1: Turn on DNS module. UDP must be available for DNS + * transport. + */ +#ifndef LWIP_DNS +#define LWIP_DNS 0 +#endif + +/** DNS maximum number of entries to maintain locally. */ +#ifndef DNS_TABLE_SIZE +#define DNS_TABLE_SIZE 4 +#endif + +/** DNS maximum host name length supported in the name table. */ +#ifndef DNS_MAX_NAME_LENGTH +#define DNS_MAX_NAME_LENGTH 256 +#endif + +/** The maximum of DNS servers */ +#ifndef DNS_MAX_SERVERS +#define DNS_MAX_SERVERS 2 +#endif + +/** DNS do a name checking between the query and the response. */ +#ifndef DNS_DOES_NAME_CHECK +#define DNS_DOES_NAME_CHECK 1 +#endif + +/** DNS_LOCAL_HOSTLIST: Implements a local host-to-address list. If enabled, + * you have to define + * #define DNS_LOCAL_HOSTLIST_INIT {{"host1", 0x123}, {"host2", 0x234}} + * (an array of structs name/address, where address is an u32_t in network + * byte order). + * + * Instead, you can also use an external function: + * #define DNS_LOOKUP_LOCAL_EXTERN(x) extern u32_t my_lookup_function(const char *name) + * that returns the IP address or INADDR_NONE if not found. + */ +#ifndef DNS_LOCAL_HOSTLIST +#define DNS_LOCAL_HOSTLIST 0 +#endif /* DNS_LOCAL_HOSTLIST */ + +/** If this is turned on, the local host-list can be dynamically changed + * at runtime. */ +#ifndef DNS_LOCAL_HOSTLIST_IS_DYNAMIC +#define DNS_LOCAL_HOSTLIST_IS_DYNAMIC 0 +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + +/* + --------------------------------- + ---------- UDP options ---------- + --------------------------------- +*/ +/** + * LWIP_UDP==1: Turn on UDP. + */ +#ifndef LWIP_UDP +#define LWIP_UDP 1 +#endif + +/** + * LWIP_UDPLITE==1: Turn on UDP-Lite. (Requires LWIP_UDP) + */ +#ifndef LWIP_UDPLITE +#define LWIP_UDPLITE 0 +#endif + +/** + * UDP_TTL: Default Time-To-Live value. + */ +#ifndef UDP_TTL +#define UDP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * LWIP_NETBUF_RECVINFO==1: append destination addr and port to every netbuf. + */ +#ifndef LWIP_NETBUF_RECVINFO +#define LWIP_NETBUF_RECVINFO 0 +#endif + +/* + --------------------------------- + ---------- TCP options ---------- + --------------------------------- +*/ +/** + * LWIP_TCP==1: Turn on TCP. + */ +#ifndef LWIP_TCP +#define LWIP_TCP 1 +#endif + +/** + * TCP_TTL: Default Time-To-Live value. + */ +#ifndef TCP_TTL +#define TCP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * TCP_WND: The size of a TCP window. This must be at least + * (2 * TCP_MSS) for things to work well + */ +#ifndef TCP_WND +#define TCP_WND (4 * TCP_MSS) +#endif + +/** + * TCP_MAXRTX: Maximum number of retransmissions of data segments. + */ +#ifndef TCP_MAXRTX +#define TCP_MAXRTX 12 +#endif + +/** + * TCP_SYNMAXRTX: Maximum number of retransmissions of SYN segments. + */ +#ifndef TCP_SYNMAXRTX +#define TCP_SYNMAXRTX 6 +#endif + +/** + * TCP_QUEUE_OOSEQ==1: TCP will queue segments that arrive out of order. + * Define to 0 if your device is low on memory. + */ +#ifndef TCP_QUEUE_OOSEQ +#define TCP_QUEUE_OOSEQ (LWIP_TCP) +#endif + +/** + * TCP_MSS: TCP Maximum segment size. (default is 536, a conservative default, + * you might want to increase this.) + * For the receive side, this MSS is advertised to the remote side + * when opening a connection. For the transmit size, this MSS sets + * an upper limit on the MSS advertised by the remote host. + */ +#ifndef TCP_MSS +#define TCP_MSS 536 +#endif + +/** + * TCP_CALCULATE_EFF_SEND_MSS: "The maximum size of a segment that TCP really + * sends, the 'effective send MSS,' MUST be the smaller of the send MSS (which + * reflects the available reassembly buffer size at the remote host) and the + * largest size permitted by the IP layer" (RFC 1122) + * Setting this to 1 enables code that checks TCP_MSS against the MTU of the + * netif used for a connection and limits the MSS if it would be too big otherwise. + */ +#ifndef TCP_CALCULATE_EFF_SEND_MSS +#define TCP_CALCULATE_EFF_SEND_MSS 1 +#endif + + +/** + * TCP_SND_BUF: TCP sender buffer space (bytes). + * To achieve good performance, this should be at least 2 * TCP_MSS. + */ +#ifndef TCP_SND_BUF +#define TCP_SND_BUF (2 * TCP_MSS) +#endif + +/** + * TCP_SND_QUEUELEN: TCP sender buffer space (pbufs). This must be at least + * as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. + */ +#ifndef TCP_SND_QUEUELEN +#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1))/(TCP_MSS)) +#endif + +/** + * TCP_SNDLOWAT: TCP writable space (bytes). This must be less than + * TCP_SND_BUF. It is the amount of space which must be available in the + * TCP snd_buf for select to return writable (combined with TCP_SNDQUEUELOWAT). + */ +#ifndef TCP_SNDLOWAT +#define TCP_SNDLOWAT LWIP_MIN(LWIP_MAX(((TCP_SND_BUF)/2), (2 * TCP_MSS) + 1), (TCP_SND_BUF) - 1) +#endif + +/** + * TCP_SNDQUEUELOWAT: TCP writable bufs (pbuf count). This must be less + * than TCP_SND_QUEUELEN. If the number of pbufs queued on a pcb drops below + * this number, select returns writable (combined with TCP_SNDLOWAT). + */ +#ifndef TCP_SNDQUEUELOWAT +#define TCP_SNDQUEUELOWAT LWIP_MAX(((TCP_SND_QUEUELEN)/2), 5) +#endif + +/** + * TCP_OOSEQ_MAX_BYTES: The maximum number of bytes queued on ooseq per pcb. + * Default is 0 (no limit). Only valid for TCP_QUEUE_OOSEQ==0. + */ +#ifndef TCP_OOSEQ_MAX_BYTES +#define TCP_OOSEQ_MAX_BYTES 0 +#endif + +/** + * TCP_OOSEQ_MAX_PBUFS: The maximum number of pbufs queued on ooseq per pcb. + * Default is 0 (no limit). Only valid for TCP_QUEUE_OOSEQ==0. + */ +#ifndef TCP_OOSEQ_MAX_PBUFS +#define TCP_OOSEQ_MAX_PBUFS 0 +#endif + +/** + * TCP_LISTEN_BACKLOG: Enable the backlog option for tcp listen pcb. + */ +#ifndef TCP_LISTEN_BACKLOG +#define TCP_LISTEN_BACKLOG 0 +#endif + +/** + * The maximum allowed backlog for TCP listen netconns. + * This backlog is used unless another is explicitly specified. + * 0xff is the maximum (u8_t). + */ +#ifndef TCP_DEFAULT_LISTEN_BACKLOG +#define TCP_DEFAULT_LISTEN_BACKLOG 0xff +#endif + +/** + * TCP_OVERSIZE: The maximum number of bytes that tcp_write may + * allocate ahead of time in an attempt to create shorter pbuf chains + * for transmission. The meaningful range is 0 to TCP_MSS. Some + * suggested values are: + * + * 0: Disable oversized allocation. Each tcp_write() allocates a new + pbuf (old behaviour). + * 1: Allocate size-aligned pbufs with minimal excess. Use this if your + * scatter-gather DMA requires aligned fragments. + * 128: Limit the pbuf/memory overhead to 20%. + * TCP_MSS: Try to create unfragmented TCP packets. + * TCP_MSS/4: Try to create 4 fragments or less per TCP packet. + */ +#ifndef TCP_OVERSIZE +#define TCP_OVERSIZE 0 //Realtek changed TCP_MSS -> 0 +#endif + +/** + * LWIP_TCP_TIMESTAMPS==1: support the TCP timestamp option. + * The timestamp option is currently only used to help remote hosts, it is not + * really used locally. Therefore, it is only enabled when a TS option is + * received in the initial SYN packet from a remote host. + */ +#ifndef LWIP_TCP_TIMESTAMPS +#define LWIP_TCP_TIMESTAMPS 0 +#endif + +/** + * TCP_WND_UPDATE_THRESHOLD: difference in window to trigger an + * explicit window update + */ +#ifndef TCP_WND_UPDATE_THRESHOLD +#define TCP_WND_UPDATE_THRESHOLD (TCP_WND / 4) +#endif + +/** + * LWIP_EVENT_API and LWIP_CALLBACK_API: Only one of these should be set to 1. + * LWIP_EVENT_API==1: The user defines lwip_tcp_event() to receive all + * events (accept, sent, etc) that happen in the system. + * LWIP_CALLBACK_API==1: The PCB callback function is called directly + * for the event. This is the default. + */ +#if !defined(LWIP_EVENT_API) && !defined(LWIP_CALLBACK_API) +#define LWIP_EVENT_API 0 +#define LWIP_CALLBACK_API 1 +#endif + +/** + * LWIP_WND_SCALE and TCP_RCV_SCALE: + * Set LWIP_WND_SCALE to 1 to enable window scaling. + * Set TCP_RCV_SCALE to the desired scaling factor (shift count in the + * range of [0..14]). + * When LWIP_WND_SCALE is enabled but TCP_RCV_SCALE is 0, we can use a large + * send window while having a small receive window only. + */ +#ifndef LWIP_WND_SCALE +#define LWIP_WND_SCALE 0 +#define TCP_RCV_SCALE 0 +#endif + + +/* + ---------------------------------- + ---------- Pbuf options ---------- + ---------------------------------- +*/ +/** + * PBUF_LINK_HLEN: the number of bytes that should be allocated for a + * link level header. The default is 14, the standard value for + * Ethernet. + */ +#ifndef PBUF_LINK_HLEN +#ifdef LWIP_HOOK_VLAN_SET +#define PBUF_LINK_HLEN (18 + ETH_PAD_SIZE) +#else /* LWIP_HOOK_VLAN_SET */ +#define PBUF_LINK_HLEN (14 + ETH_PAD_SIZE) +#endif /* LWIP_HOOK_VLAN_SET */ +#endif + +/** + * PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. The default is + * designed to accommodate single full size TCP frame in one pbuf, including + * TCP_MSS, IP header, and link header. + */ +#ifndef PBUF_POOL_BUFSIZE +#define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS+40+PBUF_LINK_HLEN) +#endif + +/* + ------------------------------------------------ + ---------- Network Interfaces options ---------- + ------------------------------------------------ +*/ +/** + * LWIP_NETIF_HOSTNAME==1: use DHCP_OPTION_HOSTNAME with netif's hostname + * field. + */ +#ifndef LWIP_NETIF_HOSTNAME +#define LWIP_NETIF_HOSTNAME 0 +#endif + +/** + * LWIP_NETIF_API==1: Support netif api (in netifapi.c) + */ +#ifndef LWIP_NETIF_API +#define LWIP_NETIF_API 0 +#endif + +/** + * LWIP_NETIF_STATUS_CALLBACK==1: Support a callback function whenever an interface + * changes its up/down status (i.e., due to DHCP IP acquisition) + */ +#ifndef LWIP_NETIF_STATUS_CALLBACK +#define LWIP_NETIF_STATUS_CALLBACK 0 +#endif + +/** + * LWIP_NETIF_LINK_CALLBACK==1: Support a callback function from an interface + * whenever the link changes (i.e., link down) + */ +#ifndef LWIP_NETIF_LINK_CALLBACK +#define LWIP_NETIF_LINK_CALLBACK 0 +#endif + +/** + * LWIP_NETIF_REMOVE_CALLBACK==1: Support a callback function that is called + * when a netif has been removed + */ +#ifndef LWIP_NETIF_REMOVE_CALLBACK +#define LWIP_NETIF_REMOVE_CALLBACK 0 +#endif + +/** + * LWIP_NETIF_HWADDRHINT==1: Cache link-layer-address hints (e.g. table + * indices) in struct netif. TCP and UDP can make use of this to prevent + * scanning the ARP table for every sent packet. While this is faster for big + * ARP tables or many concurrent connections, it might be counterproductive + * if you have a tiny ARP table or if there never are concurrent connections. + */ +#ifndef LWIP_NETIF_HWADDRHINT +#define LWIP_NETIF_HWADDRHINT 0 +#endif + +/** + * LWIP_NETIF_LOOPBACK==1: Support sending packets with a destination IP + * address equal to the netif IP address, looping them back up the stack. + */ +#ifndef LWIP_NETIF_LOOPBACK +#define LWIP_NETIF_LOOPBACK 0 +#endif + +/** + * LWIP_LOOPBACK_MAX_PBUFS: Maximum number of pbufs on queue for loopback + * sending for each netif (0 = disabled) + */ +#ifndef LWIP_LOOPBACK_MAX_PBUFS +#define LWIP_LOOPBACK_MAX_PBUFS 0 +#endif + +/** + * LWIP_NETIF_LOOPBACK_MULTITHREADING: Indicates whether threading is enabled in + * the system, as netifs must change how they behave depending on this setting + * for the LWIP_NETIF_LOOPBACK option to work. + * Setting this is needed to avoid reentering non-reentrant functions like + * tcp_input(). + * LWIP_NETIF_LOOPBACK_MULTITHREADING==1: Indicates that the user is using a + * multithreaded environment like tcpip.c. In this case, netif->input() + * is called directly. + * LWIP_NETIF_LOOPBACK_MULTITHREADING==0: Indicates a polling (or NO_SYS) setup. + * The packets are put on a list and netif_poll() must be called in + * the main application loop. + */ +#ifndef LWIP_NETIF_LOOPBACK_MULTITHREADING +#define LWIP_NETIF_LOOPBACK_MULTITHREADING (!NO_SYS) +#endif + +/** + * LWIP_NETIF_TX_SINGLE_PBUF: if this is set to 1, lwIP tries to put all data + * to be sent into one single pbuf. This is for compatibility with DMA-enabled + * MACs that do not support scatter-gather. + * Beware that this might involve CPU-memcpy before transmitting that would not + * be needed without this flag! Use this only if you need to! + * + * @todo: TCP and IP-frag do not work with this, yet: + */ +#ifndef LWIP_NETIF_TX_SINGLE_PBUF +#define LWIP_NETIF_TX_SINGLE_PBUF 0 +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + +/* + ------------------------------------ + ---------- LOOPIF options ---------- + ------------------------------------ +*/ +/** + * LWIP_HAVE_LOOPIF==1: Support loop interface (127.0.0.1) + */ +#ifndef LWIP_HAVE_LOOPIF +#define LWIP_HAVE_LOOPIF 0 +#endif + +/* + ------------------------------------ + ---------- SLIPIF options ---------- + ------------------------------------ +*/ +/** + * LWIP_HAVE_SLIPIF==1: Support slip interface and slipif.c + */ +#ifndef LWIP_HAVE_SLIPIF +#define LWIP_HAVE_SLIPIF 0 +#endif + +/* + ------------------------------------ + ---------- Thread options ---------- + ------------------------------------ +*/ +/** + * TCPIP_THREAD_NAME: The name assigned to the main tcpip thread. + */ +#ifndef TCPIP_THREAD_NAME +#define TCPIP_THREAD_NAME "TCP_IP" // Realtek modified ("tcpip_thread" -> "TCP_IP") +#endif + +/** + * TCPIP_THREAD_STACKSIZE: The stack size used by the main tcpip thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef TCPIP_THREAD_STACKSIZE +#define TCPIP_THREAD_STACKSIZE 0 +#endif + +/** + * TCPIP_THREAD_PRIO: The priority assigned to the main tcpip thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef TCPIP_THREAD_PRIO +#define TCPIP_THREAD_PRIO 1 +#endif + +/** + * TCPIP_MBOX_SIZE: The mailbox size for the tcpip thread messages + * The queue size value itself is platform-dependent, but is passed to + * sys_mbox_new() when tcpip_init is called. + */ +#ifndef TCPIP_MBOX_SIZE +#define TCPIP_MBOX_SIZE 0 +#endif + +/** + * SLIPIF_THREAD_NAME: The name assigned to the slipif_loop thread. + */ +#ifndef SLIPIF_THREAD_NAME +#define SLIPIF_THREAD_NAME "slipif_loop" +#endif + +/** + * SLIP_THREAD_STACKSIZE: The stack size used by the slipif_loop thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef SLIPIF_THREAD_STACKSIZE +#define SLIPIF_THREAD_STACKSIZE 0 +#endif + +/** + * SLIPIF_THREAD_PRIO: The priority assigned to the slipif_loop thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef SLIPIF_THREAD_PRIO +#define SLIPIF_THREAD_PRIO 1 +#endif + +/** + * DEFAULT_THREAD_NAME: The name assigned to any other lwIP thread. + */ +#ifndef DEFAULT_THREAD_NAME +#define DEFAULT_THREAD_NAME "lwIP" +#endif + +/** + * DEFAULT_THREAD_STACKSIZE: The stack size used by any other lwIP thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef DEFAULT_THREAD_STACKSIZE +#define DEFAULT_THREAD_STACKSIZE 0 +#endif + +/** + * DEFAULT_THREAD_PRIO: The priority assigned to any other lwIP thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef DEFAULT_THREAD_PRIO +#define DEFAULT_THREAD_PRIO 1 +#endif + +/** + * DEFAULT_RAW_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_RAW. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#ifndef DEFAULT_RAW_RECVMBOX_SIZE +#define DEFAULT_RAW_RECVMBOX_SIZE 0 +#endif + +/** + * DEFAULT_UDP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_UDP. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#ifndef DEFAULT_UDP_RECVMBOX_SIZE +#define DEFAULT_UDP_RECVMBOX_SIZE 0 +#endif + +/** + * DEFAULT_TCP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_TCP. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#ifndef DEFAULT_TCP_RECVMBOX_SIZE +#define DEFAULT_TCP_RECVMBOX_SIZE 0 +#endif + +/** + * DEFAULT_ACCEPTMBOX_SIZE: The mailbox size for the incoming connections. + * The queue size value itself is platform-dependent, but is passed to + * sys_mbox_new() when the acceptmbox is created. + */ +#ifndef DEFAULT_ACCEPTMBOX_SIZE +#define DEFAULT_ACCEPTMBOX_SIZE 0 +#endif + +/* + ---------------------------------------------- + ---------- Sequential layer options ---------- + ---------------------------------------------- +*/ +/** + * LWIP_TCPIP_CORE_LOCKING: (EXPERIMENTAL!) + * Don't use it if you're not an active lwIP project member + */ +#ifndef LWIP_TCPIP_CORE_LOCKING +#define LWIP_TCPIP_CORE_LOCKING 0 +#endif + +/** + * LWIP_TCPIP_CORE_LOCKING_INPUT: (EXPERIMENTAL!) + * Don't use it if you're not an active lwIP project member + */ +#ifndef LWIP_TCPIP_CORE_LOCKING_INPUT +#define LWIP_TCPIP_CORE_LOCKING_INPUT 0 +#endif + +/** + * LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c) + */ +#ifndef LWIP_NETCONN +#define LWIP_NETCONN 1 +#endif + +/** LWIP_TCPIP_TIMEOUT==1: Enable tcpip_timeout/tcpip_untimeout to create + * timers running in tcpip_thread from another thread. + */ +#ifndef LWIP_TCPIP_TIMEOUT +#define LWIP_TCPIP_TIMEOUT 1 +#endif + +/** LWIP_NETCONN_SEM_PER_THREAD==1: Use one (thread-local) semaphore per + * thread calling socket/netconn functions instead of allocating one + * semaphore per netconn (and per select etc.) + * ATTENTION: a thread-local semaphore for API calls is needed: + * - LWIP_NETCONN_THREAD_SEM_GET() returning a sys_sem_t* + * - LWIP_NETCONN_THREAD_SEM_ALLOC() creating the semaphore + * - LWIP_NETCONN_THREAD_SEM_FREE() freeing the semaphore + * The latter 2 can be invoked up by calling netconn_thread_init()/netconn_thread_cleanup(). + * Ports may call these for threads created with sys_thread_new(). + */ +#ifndef LWIP_NETCONN_SEM_PER_THREAD +#define LWIP_NETCONN_SEM_PER_THREAD 0 +#endif + +/* + ------------------------------------ + ---------- Socket options ---------- + ------------------------------------ +*/ +/** + * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c) + */ +#ifndef LWIP_SOCKET +#define LWIP_SOCKET 1 +#endif + +/* LWIP_SOCKET_SET_ERRNO==1: Set errno when socket functions cannot complete + * successfully, as required by POSIX. Default is POSIX-compliant. + */ +#ifndef LWIP_SOCKET_SET_ERRNO +#define LWIP_SOCKET_SET_ERRNO 0 +#endif + +/** + * LWIP_COMPAT_SOCKETS==1: Enable BSD-style sockets functions names. + * (only used if you use sockets.c) + */ +#ifndef LWIP_COMPAT_SOCKETS +#define LWIP_COMPAT_SOCKETS 1 +#endif + +/** + * LWIP_POSIX_SOCKETS_IO_NAMES==1: Enable POSIX-style sockets functions names. + * Disable this option if you use a POSIX operating system that uses the same + * names (read, write & close). (only used if you use sockets.c) + */ +#ifndef LWIP_POSIX_SOCKETS_IO_NAMES +#define LWIP_POSIX_SOCKETS_IO_NAMES 1 +#endif + +/** + * LWIP_TCP_KEEPALIVE==1: Enable TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT + * options processing. Note that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set + * in seconds. (does not require sockets.c, and will affect tcp.c) + */ +#ifndef LWIP_TCP_KEEPALIVE +#define LWIP_TCP_KEEPALIVE 0 +#endif + +/** + * LWIP_SO_SNDTIMEO==1: Enable send timeout for sockets/netconns and + * SO_SNDTIMEO processing. + */ +#ifndef LWIP_SO_SNDTIMEO +#define LWIP_SO_SNDTIMEO 0 +#endif + +/** + * LWIP_SO_RCVTIMEO==1: Enable receive timeout for sockets/netconns and + * SO_RCVTIMEO processing. + */ +#ifndef LWIP_SO_RCVTIMEO +#define LWIP_SO_RCVTIMEO 1 //Realtek modified(0->1) +#endif + +/** + * LWIP_SO_SNDRCVTIMEO_NONSTANDARD==1: SO_RCVTIMEO/SO_SNDTIMEO take an int + * (milliseconds, much like winsock does) instead of a struct timeval (default). + */ +#ifndef LWIP_SO_SNDRCVTIMEO_NONSTANDARD +#define LWIP_SO_SNDRCVTIMEO_NONSTANDARD 0 +#endif + +/** + * LWIP_SO_RCVBUF==1: Enable SO_RCVBUF processing. + */ +#ifndef LWIP_SO_RCVBUF +#define LWIP_SO_RCVBUF 0 +#endif + +/** + * If LWIP_SO_RCVBUF is used, this is the default value for recv_bufsize. + */ +#ifndef RECV_BUFSIZE_DEFAULT +#define RECV_BUFSIZE_DEFAULT INT_MAX +#endif + +/** + * SO_REUSE==1: Enable SO_REUSEADDR option. + */ +#ifndef SO_REUSE +#define SO_REUSE 0 +#endif + +/** + * SO_REUSE_RXTOALL==1: Pass a copy of incoming broadcast/multicast packets + * to all local matches if SO_REUSEADDR is turned on. + * WARNING: Adds a memcpy for every packet if passing to more than one pcb! + */ +#ifndef SO_REUSE_RXTOALL +#define SO_REUSE_RXTOALL 0 +#endif + +/** + * LWIP_FIONREAD_LINUXMODE==0 (default): ioctl/FIONREAD returns the amount of + * pending data in the network buffer. This is the way windows does it. It's + * the default for lwIP since it is smaller. + * LWIP_FIONREAD_LINUXMODE==1: ioctl/FIONREAD returns the size of the next + * pending datagram in bytes. This is the way linux does it. This code is only + * here for compatibility. + */ +#ifndef LWIP_FIONREAD_LINUXMODE +#define LWIP_FIONREAD_LINUXMODE 0 +#endif + +/* + ---------------------------------------- + ---------- Statistics options ---------- + ---------------------------------------- +*/ +/** + * LWIP_STATS==1: Enable statistics collection in lwip_stats. + */ +#ifndef LWIP_STATS +#define LWIP_STATS 1 +#endif + +#if LWIP_STATS + +/** + * LWIP_STATS_DISPLAY==1: Compile in the statistics output functions. + */ +#ifndef LWIP_STATS_DISPLAY +#define LWIP_STATS_DISPLAY 0 +#endif + +/** + * LINK_STATS==1: Enable link stats. + */ +#ifndef LINK_STATS +#define LINK_STATS 1 +#endif + +/** + * ETHARP_STATS==1: Enable etharp stats. + */ +#ifndef ETHARP_STATS +#define ETHARP_STATS (LWIP_ARP) +#endif + +/** + * IP_STATS==1: Enable IP stats. + */ +#ifndef IP_STATS +#define IP_STATS 1 +#endif + +/** + * IPFRAG_STATS==1: Enable IP fragmentation stats. Default is + * on if using either frag or reass. + */ +#ifndef IPFRAG_STATS +#define IPFRAG_STATS (IP_REASSEMBLY || IP_FRAG) +#endif + +/** + * ICMP_STATS==1: Enable ICMP stats. + */ +#ifndef ICMP_STATS +#define ICMP_STATS 1 +#endif + +/** + * IGMP_STATS==1: Enable IGMP stats. + */ +#ifndef IGMP_STATS +#define IGMP_STATS (LWIP_IGMP) +#endif + +/** + * UDP_STATS==1: Enable UDP stats. Default is on if + * UDP enabled, otherwise off. + */ +#ifndef UDP_STATS +#define UDP_STATS (LWIP_UDP) +#endif + +/** + * TCP_STATS==1: Enable TCP stats. Default is on if TCP + * enabled, otherwise off. + */ +#ifndef TCP_STATS +#define TCP_STATS (LWIP_TCP) +#endif + +/** + * MEM_STATS==1: Enable mem.c stats. + */ +#ifndef MEM_STATS +#define MEM_STATS ((MEM_LIBC_MALLOC == 0) && (MEM_USE_POOLS == 0)) +#endif + +/** + * MEMP_STATS==1: Enable memp.c pool stats. + */ +#ifndef MEMP_STATS +#define MEMP_STATS (MEMP_MEM_MALLOC == 0) +#endif + +/** + * SYS_STATS==1: Enable system stats (sem and mbox counts, etc). + */ +#ifndef SYS_STATS +#define SYS_STATS (NO_SYS == 0) +#endif + +/** + * IP6_STATS==1: Enable IPv6 stats. + */ +#ifndef IP6_STATS +#define IP6_STATS (LWIP_IPV6) +#endif + +/** + * ICMP6_STATS==1: Enable ICMP for IPv6 stats. + */ +#ifndef ICMP6_STATS +#define ICMP6_STATS (LWIP_IPV6 && LWIP_ICMP6) +#endif + +/** + * IP6_FRAG_STATS==1: Enable IPv6 fragmentation stats. + */ +#ifndef IP6_FRAG_STATS +#define IP6_FRAG_STATS (LWIP_IPV6 && (LWIP_IPV6_FRAG || LWIP_IPV6_REASS)) +#endif + +/** + * MLD6_STATS==1: Enable MLD for IPv6 stats. + */ +#ifndef MLD6_STATS +#define MLD6_STATS (LWIP_IPV6 && LWIP_IPV6_MLD) +#endif + +/** + * ND6_STATS==1: Enable Neighbor discovery for IPv6 stats. + */ +#ifndef ND6_STATS +#define ND6_STATS (LWIP_IPV6) +#endif + +#else + +#define LINK_STATS 0 +#define ETHARP_STATS 0 +#define IP_STATS 0 +#define IPFRAG_STATS 0 +#define ICMP_STATS 0 +#define IGMP_STATS 0 +#define UDP_STATS 0 +#define TCP_STATS 0 +#define MEM_STATS 0 +#define MEMP_STATS 0 +#define SYS_STATS 0 +#define LWIP_STATS_DISPLAY 0 +#define IP6_STATS 0 +#define ICMP6_STATS 0 +#define IP6_FRAG_STATS 0 +#define MLD6_STATS 0 +#define ND6_STATS 0 + +#endif /* LWIP_STATS */ + +/* + --------------------------------- + ---------- PPP options ---------- + --------------------------------- +*/ +/** + * PPP_SUPPORT==1: Enable PPP. + */ +#ifndef PPP_SUPPORT +#define PPP_SUPPORT 0 +#endif + +/** + * PPPOE_SUPPORT==1: Enable PPP Over Ethernet + */ +#ifndef PPPOE_SUPPORT +#define PPPOE_SUPPORT 0 +#endif + +/** + * PPPOL2TP_SUPPORT==1: Enable PPP Over L2TP + */ +#ifndef PPPOL2TP_SUPPORT +#define PPPOL2TP_SUPPORT 0 +#endif + +/** + * PPPOL2TP_AUTH_SUPPORT==1: Enable PPP Over L2TP Auth (enable MD5 support) + */ +#ifndef PPPOL2TP_AUTH_SUPPORT +#define PPPOL2TP_AUTH_SUPPORT PPPOL2TP_SUPPORT +#endif + +/** + * PPPOS_SUPPORT==1: Enable PPP Over Serial + */ +#ifndef PPPOS_SUPPORT +#define PPPOS_SUPPORT PPP_SUPPORT +#endif + +/** + * LWIP_PPP_API==1: Enable PPP API (in pppapi.c) + */ +#ifndef LWIP_PPP_API +#define LWIP_PPP_API 0 +#endif + +#if PPP_SUPPORT + +/** + * PPP_INPROC_MULTITHREADED==1 call ppp_input() using tcpip_callback(). + * Set this to 0 if pppos_input() is called inside tcpip_thread or with NO_SYS==1. + * Default is 1 for NO_SYS==0 (multithreaded) and 0 for NO_SYS==1 (single-threaded). + */ +#ifndef PPP_INPROC_MULTITHREADED +#define PPP_INPROC_MULTITHREADED (NO_SYS==0) +#endif + +/** + * PRINTPKT_SUPPORT==1: Enable PPP print packet support + * + * Mandatory for debugging, it displays exchanged packet content in debug trace. + */ +#ifndef PRINTPKT_SUPPORT +#define PRINTPKT_SUPPORT 0 +#endif + +/** + * PPP_IPV6_SUPPORT==1: Enable PPP IPv6 support + */ +#ifndef PPP_IPV6_SUPPORT +#define PPP_IPV6_SUPPORT 0 +#endif + +/** + * PPP_NOTIFY_PHASE==1: Support PPP notify phase support + * + * PPP notify phase support allows you to set a callback which is + * called on change of the internal PPP state machine. + * + * This can be used for example to set a LED pattern depending on the + * current phase of the PPP session. + */ +#ifndef PPP_NOTIFY_PHASE +#define PPP_NOTIFY_PHASE 0 +#endif + +/** + * pbuf_type PPP is using for LCP, PAP, CHAP, EAP, IPCP and IP6CP packets. + * + * Memory allocated must be single buffered for PPP to works, it requires pbuf + * that are not going to be chained when allocated. This requires setting + * PBUF_POOL_BUFSIZE to at least 512 bytes, which is quite huge for small systems. + * + * Setting PPP_USE_PBUF_RAM to 1 makes PPP use memory from heap where continuous + * buffers are required, allowing you to use a smaller PBUF_POOL_BUFSIZE. + */ +#ifndef PPP_USE_PBUF_RAM +#define PPP_USE_PBUF_RAM 0 +#endif + +/** + * PPP_FCS_TABLE: Keep a 256*2 byte table to speed up FCS calculation + */ +#ifndef PPP_FCS_TABLE +#define PPP_FCS_TABLE 1 +#endif + +/** + * PAP_SUPPORT==1: Support PAP. + */ +#ifndef PAP_SUPPORT +#define PAP_SUPPORT 0 +#endif + +/** + * CHAP_SUPPORT==1: Support CHAP. + */ +#ifndef CHAP_SUPPORT +#define CHAP_SUPPORT 0 +#endif + +/** + * MSCHAP_SUPPORT==1: Support MSCHAP. + */ +#ifndef MSCHAP_SUPPORT +#define MSCHAP_SUPPORT 0 +#endif +#if MSCHAP_SUPPORT +#undef CHAP_SUPPORT +#define CHAP_SUPPORT 1 /* MSCHAP requires CHAP support */ +#endif /* MSCHAP_SUPPORT */ + +/** + * EAP_SUPPORT==1: Support EAP. + */ +#ifndef EAP_SUPPORT +#define EAP_SUPPORT 0 +#endif + +/** + * CBCP_SUPPORT==1: Support CBCP. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef CBCP_SUPPORT +#define CBCP_SUPPORT 0 +#endif + +/** + * CCP_SUPPORT==1: Support CCP. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef CCP_SUPPORT +#define CCP_SUPPORT 0 +#endif + +/** + * ECP_SUPPORT==1: Support ECP. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef ECP_SUPPORT +#define ECP_SUPPORT 0 +#endif + +/** + * DEMAND_SUPPORT==1: Support dial on demand. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef DEMAND_SUPPORT +#define DEMAND_SUPPORT 0 +#endif + +/** + * LQR_SUPPORT==1: Support Link Quality Report. Do nothing except exchanging some LCP packets. + */ +#ifndef LQR_SUPPORT +#define LQR_SUPPORT 0 +#endif + +/** + * PPP_SERVER==1: Enable PPP server support (waiting for incoming PPP session). CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef PPP_SERVER +#define PPP_SERVER 0 +#endif + +/** + * VJ_SUPPORT==1: Support VJ header compression. + */ +#ifndef VJ_SUPPORT +#define VJ_SUPPORT 1 +#endif +#if !PPPOS_SUPPORT +#undef VJ_SUPPORT +#define VJ_SUPPORT 0 /* Only PPPoS may need VJ compression */ +#endif /* !PPPOS_SUPPORT */ + +/** + * PPP_MD5_RANDM==1: Use MD5 for better randomness. Automatically enabled if CHAP or L2TP AUTH support is enabled. + */ +#ifndef PPP_MD5_RANDM +#define PPP_MD5_RANDM 0 +#endif +#if CHAP_SUPPORT || PPPOL2TP_AUTH_SUPPORT +#undef PPP_MD5_RANDM +#define PPP_MD5_RANDM 1 /* MD5 Random is required for CHAP and L2TP AUTH */ +#endif /* CHAP_SUPPORT || PPPOL2TP_AUTH_SUPPORT */ + +/** + * PolarSSL library, used if necessary and not previously disabled + * + * + * lwIP contains some files fetched from the latest BSD release of + * the PolarSSL project for ciphers and encryption methods we need for lwIP + * PPP support. + * + * The PolarSSL files were cleaned to contain only the necessary struct + * fields and functions needed for lwIP. + * + * The PolarSSL API was not changed at all, so if you are already using + * PolarSSL you can choose to skip the compilation of the included PolarSSL + * library into lwIP: + * + * The following defines are available for flexibility: + * + * LWIP_INCLUDED_POLARSSL_MD4 ; Use lwIP internal PolarSSL for MD4 + * LWIP_INCLUDED_POLARSSL_MD5 ; Use lwIP internal PolarSSL for MD5 + * LWIP_INCLUDED_POLARSSL_SHA1 ; Use lwIP internal PolarSSL for SHA1 + * LWIP_INCLUDED_POLARSSL_DES ; Use lwIP internal PolarSSL for DES + * + * If set (=1), the default if required by another enabled PPP feature unless + * explicitly set to 0, using included lwIP PolarSSL. + * + * If clear (=0), using external PolarSSL. + * + * Undefined if not needed. + * + * Beware of the stack requirements which can be a lot larger if you are not + * using our cleaned PolarSSL library. + */ + +#if CHAP_SUPPORT || EAP_SUPPORT || PPPOL2TP_AUTH_SUPPORT || PPP_MD5_RANDM +#ifndef LWIP_INCLUDED_POLARSSL_MD5 +#define LWIP_INCLUDED_POLARSSL_MD5 1 /* CHAP, EAP, L2TP AUTH and MD5 Random require MD5 support */ +#endif /* LWIP_INCLUDED_POLARSSL_MD5 */ +#endif /* CHAP_SUPPORT || EAP_SUPPORT || PPPOL2TP_AUTH_SUPPORT || PPP_MD5_RANDM */ + +#if MSCHAP_SUPPORT +#ifndef LWIP_INCLUDED_POLARSSL_MD4 +#define LWIP_INCLUDED_POLARSSL_MD4 1 /* MSCHAP require MD4 support */ +#endif /* LWIP_INCLUDED_POLARSSL_MD4 */ +#ifndef LWIP_INCLUDED_POLARSSL_SHA1 +#define LWIP_INCLUDED_POLARSSL_SHA1 1 /* MSCHAP require SHA1 support */ +#endif /* LWIP_INCLUDED_POLARSSL_SHA1 */ +#ifndef LWIP_INCLUDED_POLARSSL_DES +#define LWIP_INCLUDED_POLARSSL_DES 1 /* MSCHAP require DES support */ +#endif /* LWIP_INCLUDED_POLARSSL_DES */ +#endif /* MSCHAP_SUPPORT */ + +/* + * Timeouts + */ +#ifndef FSM_DEFTIMEOUT +#define FSM_DEFTIMEOUT 6 /* Timeout time in seconds */ +#endif + +#ifndef FSM_DEFMAXTERMREQS +#define FSM_DEFMAXTERMREQS 2 /* Maximum Terminate-Request transmissions */ +#endif + +#ifndef FSM_DEFMAXCONFREQS +#define FSM_DEFMAXCONFREQS 10 /* Maximum Configure-Request transmissions */ +#endif + +#ifndef FSM_DEFMAXNAKLOOPS +#define FSM_DEFMAXNAKLOOPS 5 /* Maximum number of nak loops */ +#endif + +#ifndef UPAP_DEFTIMEOUT +#define UPAP_DEFTIMEOUT 6 /* Timeout (seconds) for retransmitting req */ +#endif + +#ifndef UPAP_DEFTRANSMITS +#define UPAP_DEFTRANSMITS 10 /* Maximum number of auth-reqs to send */ +#endif + +#if PPP_SERVER +#ifndef UPAP_DEFREQTIME +#define UPAP_DEFREQTIME 30 /* Time to wait for auth-req from peer */ +#endif +#endif /* PPP_SERVER */ + +#ifndef CHAP_DEFTIMEOUT +#define CHAP_DEFTIMEOUT 6 /* Timeout (seconds) for retransmitting req */ +#endif + +#ifndef CHAP_DEFTRANSMITS +#define CHAP_DEFTRANSMITS 10 /* max # times to send challenge */ +#endif + +#if PPP_SERVER +#ifndef CHAP_DEFREQTIME +#define CHAP_DEFREQTIME 30 /* Time to wait for auth-req from peer */ +#endif +#endif /* PPP_SERVER */ + +#ifndef EAP_DEFREQTIME +#define EAP_DEFREQTIME 6 /* Time to wait for peer request */ +#endif + +#ifndef EAP_DEFALLOWREQ +#define EAP_DEFALLOWREQ 10 /* max # times to accept requests */ +#endif + +#if PPP_SERVER +#ifndef EAP_DEFTIMEOUT +#define EAP_DEFTIMEOUT 6 /* Timeout (seconds) for rexmit */ +#endif + +#ifndef EAP_DEFTRANSMITS +#define EAP_DEFTRANSMITS 10 /* max # times to transmit */ +#endif +#endif /* PPP_SERVER */ + +/* Default number of times we receive our magic number from the peer + before deciding the link is looped-back. */ +#ifndef LCP_DEFLOOPBACKFAIL +#define LCP_DEFLOOPBACKFAIL 10 +#endif + +/* Interval in seconds between keepalive echo requests, 0 to disable. */ +#ifndef LCP_ECHOINTERVAL +#define LCP_ECHOINTERVAL 0 +#endif + +/* Number of unanswered echo requests before failure. */ +#ifndef LCP_MAXECHOFAILS +#define LCP_MAXECHOFAILS 3 +#endif + +/* Max Xmit idle time (in jiffies) before resend flag char. */ +#ifndef PPP_MAXIDLEFLAG +#define PPP_MAXIDLEFLAG 100 +#endif + +/* + * Packet sizes + * + * Note - lcp shouldn't be allowed to negotiate stuff outside these + * limits. See lcp.h in the pppd directory. + * (XXX - these constants should simply be shared by lcp.c instead + * of living in lcp.h) + */ +#define PPP_MTU 1500 /* Default MTU (size of Info field) */ +#ifndef PPP_MAXMTU +/* #define PPP_MAXMTU 65535 - (PPP_HDRLEN + PPP_FCSLEN) */ +#define PPP_MAXMTU 1500 /* Largest MTU we allow */ +#endif +#define PPP_MINMTU 64 +#define PPP_MRU 1500 /* default MRU = max length of info field */ +#define PPP_MAXMRU 1500 /* Largest MRU we allow */ +#ifndef PPP_DEFMRU +#define PPP_DEFMRU 296 /* Try for this */ +#endif +#define PPP_MINMRU 128 /* No MRUs below this */ + +#ifndef MAXNAMELEN +#define MAXNAMELEN 256 /* max length of hostname or name for auth */ +#endif +#ifndef MAXSECRETLEN +#define MAXSECRETLEN 256 /* max length of password or secret */ +#endif + +#endif /* PPP_SUPPORT */ + +/* + -------------------------------------- + ---------- Checksum options ---------- + -------------------------------------- +*/ +/** + * CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets. + */ +#ifndef CHECKSUM_GEN_IP +#define CHECKSUM_GEN_IP 1 +#endif + +/** + * CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets. + */ +#ifndef CHECKSUM_GEN_UDP +#define CHECKSUM_GEN_UDP 1 +#endif + +/** + * CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets. + */ +#ifndef CHECKSUM_GEN_TCP +#define CHECKSUM_GEN_TCP 1 +#endif + +/** + * CHECKSUM_GEN_ICMP==1: Generate checksums in software for outgoing ICMP packets. + */ +#ifndef CHECKSUM_GEN_ICMP +#define CHECKSUM_GEN_ICMP 1 +#endif + +/** + * CHECKSUM_GEN_ICMP6==1: Generate checksums in software for outgoing ICMP6 packets. + */ +#ifndef CHECKSUM_GEN_ICMP6 +#define CHECKSUM_GEN_ICMP6 1 +#endif + +/** + * CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets. + */ +#ifndef CHECKSUM_CHECK_IP +#define CHECKSUM_CHECK_IP 1 +#endif + +/** + * CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets. + */ +#ifndef CHECKSUM_CHECK_UDP +#define CHECKSUM_CHECK_UDP 1 +#endif + +/** + * CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets. + */ +#ifndef CHECKSUM_CHECK_TCP +#define CHECKSUM_CHECK_TCP 1 +#endif + +/** + * CHECKSUM_CHECK_ICMP==1: Check checksums in software for incoming ICMP packets. + */ +#ifndef CHECKSUM_CHECK_ICMP +#define CHECKSUM_CHECK_ICMP 1 +#endif + +/** + * CHECKSUM_CHECK_ICMP6==1: Check checksums in software for incoming ICMPv6 packets + */ +#ifndef CHECKSUM_CHECK_ICMP6 +#define CHECKSUM_CHECK_ICMP6 1 +#endif + +/** + * LWIP_CHECKSUM_ON_COPY==1: Calculate checksum when copying data from + * application buffers to pbufs. + */ +#ifndef LWIP_CHECKSUM_ON_COPY +#define LWIP_CHECKSUM_ON_COPY 0 +#endif + +/* + --------------------------------------- + ---------- IPv6 options --------------- + --------------------------------------- +*/ +/** + * LWIP_IPV6==1: Enable IPv6 + */ +#ifndef LWIP_IPV6 +#define LWIP_IPV6 0 +#endif + +/** + * LWIP_IPV6_NUM_ADDRESSES: Number of IPv6 addresses per netif. + */ +#ifndef LWIP_IPV6_NUM_ADDRESSES +#define LWIP_IPV6_NUM_ADDRESSES 3 +#endif + +/** + * LWIP_IPV6_FORWARD==1: Forward IPv6 packets across netifs + */ +#ifndef LWIP_IPV6_FORWARD +#define LWIP_IPV6_FORWARD 0 +#endif + +/** + * LWIP_ICMP6==1: Enable ICMPv6 (mandatory per RFC) + */ +#ifndef LWIP_ICMP6 +#define LWIP_ICMP6 (LWIP_IPV6) +#endif + +/** + * LWIP_ICMP6_DATASIZE: bytes from original packet to send back in + * ICMPv6 error messages. + */ +#ifndef LWIP_ICMP6_DATASIZE +#define LWIP_ICMP6_DATASIZE 8 +#endif + +/** + * LWIP_ICMP6_HL: default hop limit for ICMPv6 messages + */ +#ifndef LWIP_ICMP6_HL +#define LWIP_ICMP6_HL 255 +#endif + +/** + * LWIP_IPV6_MLD==1: Enable multicast listener discovery protocol. + */ +#ifndef LWIP_IPV6_MLD +#define LWIP_IPV6_MLD (LWIP_IPV6) +#endif + +/** + * MEMP_NUM_MLD6_GROUP: Max number of IPv6 multicast that can be joined. + */ +#ifndef MEMP_NUM_MLD6_GROUP +#define MEMP_NUM_MLD6_GROUP 4 +#endif + +/** + * LWIP_IPV6_FRAG==1: Fragment outgoing IPv6 packets that are too big. + */ +#ifndef LWIP_IPV6_FRAG +#define LWIP_IPV6_FRAG 0 +#endif + +/** + * LWIP_IPV6_REASS==1: reassemble incoming IPv6 packets that fragmented + */ +#ifndef LWIP_IPV6_REASS +#define LWIP_IPV6_REASS (LWIP_IPV6) +#endif + +/** + * LWIP_ND6_QUEUEING==1: queue outgoing IPv6 packets while MAC address + * is being resolved. + */ +#ifndef LWIP_ND6_QUEUEING +#define LWIP_ND6_QUEUEING (LWIP_IPV6) +#endif + +/** + * MEMP_NUM_ND6_QUEUE: Max number of IPv6 packets to queue during MAC resolution. + */ +#ifndef MEMP_NUM_ND6_QUEUE +#define MEMP_NUM_ND6_QUEUE 20 +#endif + +/** + * LWIP_ND6_NUM_NEIGHBORS: Number of entries in IPv6 neighbor cache + */ +#ifndef LWIP_ND6_NUM_NEIGHBORS +#define LWIP_ND6_NUM_NEIGHBORS 10 +#endif + +/** + * LWIP_ND6_NUM_DESTINATIONS: number of entries in IPv6 destination cache + */ +#ifndef LWIP_ND6_NUM_DESTINATIONS +#define LWIP_ND6_NUM_DESTINATIONS 10 +#endif + +/** + * LWIP_ND6_NUM_PREFIXES: number of entries in IPv6 on-link prefixes cache + */ +#ifndef LWIP_ND6_NUM_PREFIXES +#define LWIP_ND6_NUM_PREFIXES 5 +#endif + +/** + * LWIP_ND6_NUM_ROUTERS: number of entries in IPv6 default router cache + */ +#ifndef LWIP_ND6_NUM_ROUTERS +#define LWIP_ND6_NUM_ROUTERS 3 +#endif + +/** + * LWIP_ND6_MAX_MULTICAST_SOLICIT: max number of multicast solicit messages to send + * (neighbor solicit and router solicit) + */ +#ifndef LWIP_ND6_MAX_MULTICAST_SOLICIT +#define LWIP_ND6_MAX_MULTICAST_SOLICIT 3 +#endif + +/** + * LWIP_ND6_MAX_UNICAST_SOLICIT: max number of unicast neighbor solicitation messages + * to send during neighbor reachability detection. + */ +#ifndef LWIP_ND6_MAX_UNICAST_SOLICIT +#define LWIP_ND6_MAX_UNICAST_SOLICIT 3 +#endif + +/** + * Unused: See ND RFC (time in milliseconds). + */ +#ifndef LWIP_ND6_MAX_ANYCAST_DELAY_TIME +#define LWIP_ND6_MAX_ANYCAST_DELAY_TIME 1000 +#endif + +/** + * Unused: See ND RFC + */ +#ifndef LWIP_ND6_MAX_NEIGHBOR_ADVERTISEMENT +#define LWIP_ND6_MAX_NEIGHBOR_ADVERTISEMENT 3 +#endif + +/** + * LWIP_ND6_REACHABLE_TIME: default neighbor reachable time (in milliseconds). + * May be updated by router advertisement messages. + */ +#ifndef LWIP_ND6_REACHABLE_TIME +#define LWIP_ND6_REACHABLE_TIME 30000 +#endif + +/** + * LWIP_ND6_RETRANS_TIMER: default retransmission timer for solicitation messages + */ +#ifndef LWIP_ND6_RETRANS_TIMER +#define LWIP_ND6_RETRANS_TIMER 1000 +#endif + +/** + * LWIP_ND6_DELAY_FIRST_PROBE_TIME: Delay before first unicast neighbor solicitation + * message is sent, during neighbor reachability detection. + */ +#ifndef LWIP_ND6_DELAY_FIRST_PROBE_TIME +#define LWIP_ND6_DELAY_FIRST_PROBE_TIME 5000 +#endif + +/** + * LWIP_ND6_ALLOW_RA_UPDATES==1: Allow Router Advertisement messages to update + * Reachable time and retransmission timers, and netif MTU. + */ +#ifndef LWIP_ND6_ALLOW_RA_UPDATES +#define LWIP_ND6_ALLOW_RA_UPDATES 1 +#endif + +/** + * LWIP_IPV6_SEND_ROUTER_SOLICIT==1: Send router solicitation messages during + * network startup. + */ +#ifndef LWIP_IPV6_SEND_ROUTER_SOLICIT +#define LWIP_IPV6_SEND_ROUTER_SOLICIT 1 +#endif + +/** + * LWIP_ND6_TCP_REACHABILITY_HINTS==1: Allow TCP to provide Neighbor Discovery + * with reachability hints for connected destinations. This helps avoid sending + * unicast neighbor solicitation messages. + */ +#ifndef LWIP_ND6_TCP_REACHABILITY_HINTS +#define LWIP_ND6_TCP_REACHABILITY_HINTS 1 +#endif + +/** + * LWIP_IPV6_AUTOCONFIG==1: Enable stateless address autoconfiguration as per RFC 4862. + */ +#ifndef LWIP_IPV6_AUTOCONFIG +#define LWIP_IPV6_AUTOCONFIG (LWIP_IPV6) +#endif + +/** + * LWIP_IPV6_DUP_DETECT_ATTEMPTS: Number of duplicate address detection attempts. + */ +#ifndef LWIP_IPV6_DUP_DETECT_ATTEMPTS +#define LWIP_IPV6_DUP_DETECT_ATTEMPTS 1 +#endif + +/** + * LWIP_IPV6_DHCP6==1: enable DHCPv6 stateful address autoconfiguration. + */ +#ifndef LWIP_IPV6_DHCP6 +#define LWIP_IPV6_DHCP6 0 +#endif + +/* + --------------------------------------- + ---------- Hook options --------------- + --------------------------------------- +*/ + +/* Hooks are undefined by default, define them to a function if you need them. */ + +/** + * LWIP_HOOK_IP4_INPUT(pbuf, input_netif): + * - called from ip_input() (IPv4) + * - pbuf: received struct pbuf passed to ip_input() + * - input_netif: struct netif on which the packet has been received + * Return values: + * - 0: Hook has not consumed the packet, packet is processed as normal + * - != 0: Hook has consumed the packet. + * If the hook consumed the packet, 'pbuf' is in the responsibility of the hook + * (i.e. free it when done). + */ + +/** + * LWIP_HOOK_IP4_ROUTE(dest): + * - called from ip_route() (IPv4) + * - dest: destination IPv4 address + * Returns the destination netif or NULL if no destination netif is found. In + * that case, ip_route() continues as normal. + */ + +/** + * LWIP_HOOK_ETHARP_GET_GW(netif, dest): + * - called from etharp_output() (IPv4) + * - netif: the netif used for sending + * - dest: the destination IPv4 address + * Returns the IPv4 address of the gateway to handle the specified destination + * IPv4 address. If NULL is returned, the netif's default gateway is used. + * The returned address MUST be reachable on the specified netif! + * This function is meant to implement advanced IPv4 routing together with + * LWIP_HOOK_IP4_ROUTE(). The actual routing/gateway table implementation is + * not part of lwIP but can e.g. be hidden in the netif's state argument. +*/ + +/** + * LWIP_HOOK_VLAN_CHECK(netif, eth_hdr, vlan_hdr): + * - called from ethernet_input() if VLAN support is enabled + * - netif: struct netif on which the packet has been received + * - eth_hdr: struct eth_hdr of the packet + * - vlan_hdr: struct eth_vlan_hdr of the packet + * Return values: + * - 0: Packet must be dropped. + * - != 0: Packet must be accepted. + */ + +/** + * LWIP_HOOK_VLAN_SET(netif, eth_hdr, vlan_hdr): + * - called from etharp_raw() and etharp_send_ip() if VLAN support is enabled + * - netif: struct netif that the packet will be sent through + * - eth_hdr: struct eth_hdr of the packet + * - vlan_hdr: struct eth_vlan_hdr of the packet + * Return values: + * - 0: Packet shall not contain VLAN header. + * - != 0: Packet shall contain VLAN header. + * Hook can be used to set prio_vid field of vlan_hdr. + */ + +/* + --------------------------------------- + ---------- Debugging options ---------- + --------------------------------------- +*/ +/** + * LWIP_DBG_MIN_LEVEL: After masking, the value of the debug is + * compared against this value. If it is smaller, then debugging + * messages are written. + */ +#ifndef LWIP_DBG_MIN_LEVEL +#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL +#endif + +/** + * LWIP_DBG_TYPES_ON: A mask that can be used to globally enable/disable + * debug messages of certain types. + */ +#ifndef LWIP_DBG_TYPES_ON +#define LWIP_DBG_TYPES_ON LWIP_DBG_ON +#endif + +/** + * ETHARP_DEBUG: Enable debugging in etharp.c. + */ +#ifndef ETHARP_DEBUG +#define ETHARP_DEBUG LWIP_DBG_OFF +#endif + +/** + * NETIF_DEBUG: Enable debugging in netif.c. + */ +#ifndef NETIF_DEBUG +#define NETIF_DEBUG LWIP_DBG_OFF +#endif + +/** + * PBUF_DEBUG: Enable debugging in pbuf.c. + */ +#ifndef PBUF_DEBUG +#define PBUF_DEBUG LWIP_DBG_OFF +#endif + +/** + * API_LIB_DEBUG: Enable debugging in api_lib.c. + */ +#ifndef API_LIB_DEBUG +#define API_LIB_DEBUG LWIP_DBG_OFF +#endif + +/** + * API_MSG_DEBUG: Enable debugging in api_msg.c. + */ +#ifndef API_MSG_DEBUG +#define API_MSG_DEBUG LWIP_DBG_OFF +#endif + +/** + * SOCKETS_DEBUG: Enable debugging in sockets.c. + */ +#ifndef SOCKETS_DEBUG +#define SOCKETS_DEBUG LWIP_DBG_OFF +#endif + +/** + * ICMP_DEBUG: Enable debugging in icmp.c. + */ +#ifndef ICMP_DEBUG +#define ICMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * IGMP_DEBUG: Enable debugging in igmp.c. + */ +#ifndef IGMP_DEBUG +#define IGMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * INET_DEBUG: Enable debugging in inet.c. + */ +#ifndef INET_DEBUG +#define INET_DEBUG LWIP_DBG_OFF +#endif + +/** + * IP_DEBUG: Enable debugging for IP. + */ +#ifndef IP_DEBUG +#define IP_DEBUG LWIP_DBG_OFF +#endif + +/** + * IP_REASS_DEBUG: Enable debugging in ip_frag.c for both frag & reass. + */ +#ifndef IP_REASS_DEBUG +#define IP_REASS_DEBUG LWIP_DBG_OFF +#endif + +/** + * RAW_DEBUG: Enable debugging in raw.c. + */ +#ifndef RAW_DEBUG +#define RAW_DEBUG LWIP_DBG_OFF +#endif + +/** + * MEM_DEBUG: Enable debugging in mem.c. + */ +#ifndef MEM_DEBUG +#define MEM_DEBUG LWIP_DBG_OFF +#endif + +/** + * MEMP_DEBUG: Enable debugging in memp.c. + */ +#ifndef MEMP_DEBUG +#define MEMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * SYS_DEBUG: Enable debugging in sys.c. + */ +#ifndef SYS_DEBUG +#define SYS_DEBUG LWIP_DBG_OFF +#endif + +/** + * TIMERS_DEBUG: Enable debugging in timers.c. + */ +#ifndef TIMERS_DEBUG +#define TIMERS_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_DEBUG: Enable debugging for TCP. + */ +#ifndef TCP_DEBUG +#define TCP_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_INPUT_DEBUG: Enable debugging in tcp_in.c for incoming debug. + */ +#ifndef TCP_INPUT_DEBUG +#define TCP_INPUT_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_FR_DEBUG: Enable debugging in tcp_in.c for fast retransmit. + */ +#ifndef TCP_FR_DEBUG +#define TCP_FR_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_RTO_DEBUG: Enable debugging in TCP for retransmit + * timeout. + */ +#ifndef TCP_RTO_DEBUG +#define TCP_RTO_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_CWND_DEBUG: Enable debugging for TCP congestion window. + */ +#ifndef TCP_CWND_DEBUG +#define TCP_CWND_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_WND_DEBUG: Enable debugging in tcp_in.c for window updating. + */ +#ifndef TCP_WND_DEBUG +#define TCP_WND_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_OUTPUT_DEBUG: Enable debugging in tcp_out.c output functions. + */ +#ifndef TCP_OUTPUT_DEBUG +#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_RST_DEBUG: Enable debugging for TCP with the RST message. + */ +#ifndef TCP_RST_DEBUG +#define TCP_RST_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_QLEN_DEBUG: Enable debugging for TCP queue lengths. + */ +#ifndef TCP_QLEN_DEBUG +#define TCP_QLEN_DEBUG LWIP_DBG_OFF +#endif + +/** + * UDP_DEBUG: Enable debugging in UDP. + */ +#ifndef UDP_DEBUG +#define UDP_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCPIP_DEBUG: Enable debugging in tcpip.c. + */ +#ifndef TCPIP_DEBUG +#define TCPIP_DEBUG LWIP_DBG_OFF +#endif + +/** + * PPP_DEBUG: Enable debugging for PPP. + */ +#ifndef PPP_DEBUG +#define PPP_DEBUG LWIP_DBG_OFF +#endif + +/** + * SLIP_DEBUG: Enable debugging in slipif.c. + */ +#ifndef SLIP_DEBUG +#define SLIP_DEBUG LWIP_DBG_OFF +#endif + +/** + * DHCP_DEBUG: Enable debugging in dhcp.c. + */ +#ifndef DHCP_DEBUG +#define DHCP_DEBUG LWIP_DBG_OFF +#endif + +/** + * AUTOIP_DEBUG: Enable debugging in autoip.c. + */ +#ifndef AUTOIP_DEBUG +#define AUTOIP_DEBUG LWIP_DBG_OFF +#endif + +/** + * SNMP_MSG_DEBUG: Enable debugging for SNMP messages. + */ +#ifndef SNMP_MSG_DEBUG +#define SNMP_MSG_DEBUG LWIP_DBG_OFF +#endif + +/** + * SNMP_MIB_DEBUG: Enable debugging for SNMP MIBs. + */ +#ifndef SNMP_MIB_DEBUG +#define SNMP_MIB_DEBUG LWIP_DBG_OFF +#endif + +/** + * DNS_DEBUG: Enable debugging for DNS. + */ +#ifndef DNS_DEBUG +#define DNS_DEBUG LWIP_DBG_OFF +#endif + +/** + * IP6_DEBUG: Enable debugging for IPv6. + */ +#ifndef IP6_DEBUG +#define IP6_DEBUG LWIP_DBG_OFF +#endif + +#endif /* LWIP_HDR_OPT_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/pbuf.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/pbuf.h new file mode 100644 index 0000000..6bd6b30 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/pbuf.h @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#ifndef LWIP_HDR_PBUF_H +#define LWIP_HDR_PBUF_H + +#include "lwip/opt.h" +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Currently, the pbuf_custom code is only needed for one specific configuration + * of IP_FRAG */ +#ifndef LWIP_SUPPORT_CUSTOM_PBUF +#define LWIP_SUPPORT_CUSTOM_PBUF (IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF) +#endif + +/* @todo: We need a mechanism to prevent wasting memory in every pbuf + (TCP vs. UDP, IPv4 vs. IPv6: UDP/IPv4 packets may waste up to 28 bytes) */ + +#define PBUF_TRANSPORT_HLEN 20 +#if LWIP_IPV6 +#define PBUF_IP_HLEN 40 +#else +#define PBUF_IP_HLEN 20 +#endif + +typedef enum { + PBUF_TRANSPORT, + PBUF_IP, + PBUF_LINK, + PBUF_RAW +} pbuf_layer; + +typedef enum { + PBUF_RAM, /* pbuf data is stored in RAM */ + PBUF_ROM, /* pbuf data is stored in ROM */ + PBUF_REF, /* pbuf comes from the pbuf pool */ + PBUF_POOL /* pbuf payload refers to RAM */ +} pbuf_type; + + +/** indicates this packet's data should be immediately passed to the application */ +#define PBUF_FLAG_PUSH 0x01U +/** indicates this is a custom pbuf: pbuf_free and pbuf_header handle such a + a pbuf differently */ +#define PBUF_FLAG_IS_CUSTOM 0x02U +/** indicates this pbuf is UDP multicast to be looped back */ +#define PBUF_FLAG_MCASTLOOP 0x04U +/** indicates this pbuf was received as link-level broadcast */ +#define PBUF_FLAG_LLBCAST 0x08U +/** indicates this pbuf was received as link-level multicast */ +#define PBUF_FLAG_LLMCAST 0x10U +/** indicates this pbuf includes a TCP FIN flag */ +#define PBUF_FLAG_TCP_FIN 0x20U + +struct pbuf { + /** next pbuf in singly linked pbuf chain */ + struct pbuf *next; + + /** pointer to the actual data in the buffer */ + void *payload; + + /** + * total length of this buffer and all next buffers in chain + * belonging to the same packet. + * + * For non-queue packet chains this is the invariant: + * p->tot_len == p->len + (p->next? p->next->tot_len: 0) + */ + u16_t tot_len; + + /** length of this buffer */ + u16_t len; + + /** pbuf_type as u8_t instead of enum to save space */ + u8_t /*pbuf_type*/ type; + + /** misc flags */ + u8_t flags; + + /** + * the reference count always equals the number of pointers + * that refer to this pbuf. This can be pointers from an application, + * the stack itself, or pbuf->next pointers from a chain. + */ + u16_t ref; +}; + +#if LWIP_SUPPORT_CUSTOM_PBUF +/** Prototype for a function to free a custom pbuf */ +typedef void (*pbuf_free_custom_fn)(struct pbuf *p); + +/** A custom pbuf: like a pbuf, but following a function pointer to free it. */ +struct pbuf_custom { + /** The actual pbuf */ + struct pbuf pbuf; + /** This function is called when pbuf_free deallocates this pbuf(_custom) */ + pbuf_free_custom_fn custom_free_function; +}; +#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ + +#if LWIP_TCP && TCP_QUEUE_OOSEQ +/** Define this to 0 to prevent freeing ooseq pbufs when the PBUF_POOL is empty */ +#ifndef PBUF_POOL_FREE_OOSEQ +#define PBUF_POOL_FREE_OOSEQ 1 +#endif /* PBUF_POOL_FREE_OOSEQ */ +#if NO_SYS && PBUF_POOL_FREE_OOSEQ +extern volatile u8_t pbuf_free_ooseq_pending; +void pbuf_free_ooseq(void); +/** When not using sys_check_timeouts(), call PBUF_CHECK_FREE_OOSEQ() + at regular intervals from main level to check if ooseq pbufs need to be + freed! */ +#define PBUF_CHECK_FREE_OOSEQ() do { if(pbuf_free_ooseq_pending) { \ + /* pbuf_alloc() reported PBUF_POOL to be empty -> try to free some \ + ooseq queued pbufs now */ \ + pbuf_free_ooseq(); }}while(0) +#endif /* NO_SYS && PBUF_POOL_FREE_OOSEQ*/ +#endif /* LWIP_TCP && TCP_QUEUE_OOSEQ */ + +/* Initializes the pbuf module. This call is empty for now, but may not be in future. */ +#define pbuf_init() + +struct pbuf *pbuf_alloc(pbuf_layer l, u16_t length, pbuf_type type); +#if LWIP_SUPPORT_CUSTOM_PBUF +struct pbuf *pbuf_alloced_custom(pbuf_layer l, u16_t length, pbuf_type type, + struct pbuf_custom *p, void *payload_mem, + u16_t payload_mem_len); +#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ +void pbuf_realloc(struct pbuf *p, u16_t size); +u8_t pbuf_header(struct pbuf *p, s16_t header_size); +u8_t pbuf_header_force(struct pbuf *p, s16_t header_size); +void pbuf_ref(struct pbuf *p); +u8_t pbuf_free(struct pbuf *p); +u8_t pbuf_clen(struct pbuf *p); +void pbuf_cat(struct pbuf *head, struct pbuf *tail); +void pbuf_chain(struct pbuf *head, struct pbuf *tail); +struct pbuf *pbuf_dechain(struct pbuf *p); +err_t pbuf_copy(struct pbuf *p_to, struct pbuf *p_from); +u16_t pbuf_copy_partial(struct pbuf *p, void *dataptr, u16_t len, u16_t offset); +err_t pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len); +err_t pbuf_take_at(struct pbuf *buf, const void *dataptr, u16_t len, u16_t offset); +struct pbuf *pbuf_coalesce(struct pbuf *p, pbuf_layer layer); +#if LWIP_CHECKSUM_ON_COPY +err_t pbuf_fill_chksum(struct pbuf *p, u16_t start_offset, const void *dataptr, + u16_t len, u16_t *chksum); +#endif /* LWIP_CHECKSUM_ON_COPY */ +#if LWIP_TCP && TCP_QUEUE_OOSEQ && LWIP_WND_SCALE +void pbuf_split_64k(struct pbuf *p, struct pbuf **rest); +#endif /* LWIP_TCP && TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + +u8_t pbuf_get_at(struct pbuf* p, u16_t offset); +void pbuf_put_at(struct pbuf* p, u16_t offset, u8_t data); +u16_t pbuf_memcmp(struct pbuf* p, u16_t offset, const void* s2, u16_t n); +u16_t pbuf_memfind(struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset); +u16_t pbuf_strstr(struct pbuf* p, const char* substr); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_PBUF_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/pppapi.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/pppapi.h new file mode 100644 index 0000000..dd24af5 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/pppapi.h @@ -0,0 +1,151 @@ +/* + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#ifndef __LWIP_PPPAPI_H__ +#define __LWIP_PPPAPI_H__ + +#include "lwip/opt.h" + +#if LWIP_PPP_API /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/sys.h" +#include "netif/ppp/ppp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct pppapi_msg_msg { +#if !LWIP_TCPIP_CORE_LOCKING + sys_sem_t sem; +#endif /* !LWIP_TCPIP_CORE_LOCKING */ + int err; + ppp_pcb *ppp; + union { + struct { + u8_t authtype; + const char *user; + const char *passwd; + } setauth; +#if PPP_NOTIFY_PHASE + struct { + ppp_notify_phase_cb_fn notify_phase_cb; + } setnotifyphasecb; +#endif /* PPP_NOTIFY_PHASE */ +#if PPPOS_SUPPORT + struct { + sio_fd_t fd; + ppp_link_status_cb_fn link_status_cb; + void *ctx_cb; + } serialcreate; +#endif /* PPPOS_SUPPORT */ +#if PPPOE_SUPPORT + struct { + struct netif *ethif; + const char *service_name; + const char *concentrator_name; + ppp_link_status_cb_fn link_status_cb; + void *ctx_cb; + } ethernetcreate; +#endif /* PPPOE_SUPPORT */ +#if PPPOL2TP_SUPPORT + struct { + struct netif *netif; + ip_addr_t *ipaddr; + u16_t port; +#if PPPOL2TP_AUTH_SUPPORT + u8_t *secret; + u8_t secret_len; +#endif /* PPPOL2TP_AUTH_SUPPORT */ + ppp_link_status_cb_fn link_status_cb; + void *ctx_cb; + } l2tpcreate; +#endif /* PPPOL2TP_SUPPORT */ + struct { + u16_t holdoff; + } open; + struct { + int cmd; + void *arg; + } ioctl; +#if LWIP_NETIF_STATUS_CALLBACK + struct { + netif_status_callback_fn status_callback; + } netifstatuscallback; +#endif /* LWIP_NETIF_STATUS_CALLBACK */ +#if LWIP_NETIF_LINK_CALLBACK + struct { + netif_status_callback_fn link_callback; + } netiflinkcallback; +#endif /* LWIP_NETIF_LINK_CALLBACK */ + } msg; +}; + +struct pppapi_msg { + void (* function)(struct pppapi_msg_msg *msg); + struct pppapi_msg_msg msg; +}; + +/* API for application */ +ppp_pcb *pppapi_new(void); +void pppapi_set_default(ppp_pcb *pcb); +void pppapi_set_auth(ppp_pcb *pcb, u8_t authtype, const char *user, const char *passwd); +#if PPP_NOTIFY_PHASE +void pppapi_set_notify_phase_callback(ppp_pcb *pcb, ppp_notify_phase_cb_fn notify_phase_cb); +#endif /* PPP_NOTIFY_PHASE */ +#if PPPOS_SUPPORT +int pppapi_over_serial_create(ppp_pcb *pcb, sio_fd_t fd, ppp_link_status_cb_fn link_status_cb, void *ctx_cb); +#endif /* PPPOS_SUPPORT */ +#if PPPOE_SUPPORT +int pppapi_over_ethernet_create(ppp_pcb *pcb, struct netif *ethif, const char *service_name, + const char *concentrator_name, ppp_link_status_cb_fn link_status_cb, + void *ctx_cb); +#endif /* PPPOE_SUPPORT */ +#if PPPOL2TP_SUPPORT +int pppapi_over_l2tp_create(ppp_pcb *pcb, struct netif *netif, ip_addr_t *ipaddr, u16_t port, + u8_t *secret, u8_t secret_len, + ppp_link_status_cb_fn link_status_cb, void *ctx_cb); +#endif /* PPPOL2TP_SUPPORT */ +int pppapi_open(ppp_pcb *pcb, u16_t holdoff); +int pppapi_close(ppp_pcb *pcb); +void pppapi_sighup(ppp_pcb *pcb); +int pppapi_delete(ppp_pcb *pcb); +int pppapi_ioctl(ppp_pcb *pcb, int cmd, void *arg); +#if LWIP_NETIF_STATUS_CALLBACK +void pppapi_set_netif_statuscallback(ppp_pcb *pcb, netif_status_callback_fn status_callback); +#endif /* LWIP_NETIF_STATUS_CALLBACK */ +#if LWIP_NETIF_LINK_CALLBACK +void pppapi_set_netif_linkcallback(ppp_pcb *pcb, netif_status_callback_fn link_callback); +#endif /* LWIP_NETIF_LINK_CALLBACK */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_PPP_API */ + +#endif /* __LWIP_PPPAPI_H__ */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/raw.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/raw.h new file mode 100644 index 0000000..52964f5 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/raw.h @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_RAW_H +#define LWIP_HDR_RAW_H + +#include "lwip/opt.h" + +#if LWIP_RAW /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/def.h" +#include "lwip/lwip_ip.h" +#include "lwip/ip_addr.h" +#include "lwip/ip6_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct raw_pcb; + +/** Function prototype for raw pcb receive callback functions. + * @param arg user supplied argument (raw_pcb.recv_arg) + * @param pcb the raw_pcb which received data + * @param p the packet buffer that was received + * @param addr the remote IP address from which the packet was received + * @return 1 if the packet was 'eaten' (aka. deleted), + * 0 if the packet lives on + * If returning 1, the callback is responsible for freeing the pbuf + * if it's not used any more. + */ +typedef u8_t (*raw_recv_fn)(void *arg, struct raw_pcb *pcb, struct pbuf *p, + ip_addr_t *addr); + +#if LWIP_IPV6 +/** Function prototype for raw pcb IPv6 receive callback functions. + * @param arg user supplied argument (raw_pcb.recv_arg) + * @param pcb the raw_pcb which received data + * @param p the packet buffer that was received + * @param addr the remote IPv6 address from which the packet was received + * @return 1 if the packet was 'eaten' (aka. deleted), + * 0 if the packet lives on + * If returning 1, the callback is responsible for freeing the pbuf + * if it's not used any more. + */ +typedef u8_t (*raw_recv_ip6_fn)(void *arg, struct raw_pcb *pcb, struct pbuf *p, + ip6_addr_t *addr); +#endif /* LWIP_IPV6 */ + +#if LWIP_IPV6 +#define RAW_PCB_RECV_IP6 raw_recv_ip6_fn ip6; +#else +#define RAW_PCB_RECV_IP6 +#endif /* LWIP_IPV6 */ + +struct raw_pcb { + /* Common members of all PCB types */ + IP_PCB; + + struct raw_pcb *next; + + u8_t protocol; + + /** receive callback function */ + union { + raw_recv_fn ip4; + RAW_PCB_RECV_IP6 + } recv; + /* user-supplied argument for the recv callback */ + void *recv_arg; +#if LWIP_IPV6 + /* fields for handling checksum computations as per RFC3542. */ + u16_t chksum_offset; + u8_t chksum_reqd; +#endif +}; + +/* The following functions is the application layer interface to the + RAW code. */ +struct raw_pcb * raw_new (u8_t proto); +void raw_remove (struct raw_pcb *pcb); +err_t raw_bind (struct raw_pcb *pcb, ip_addr_t *ipaddr); +err_t raw_connect (struct raw_pcb *pcb, ip_addr_t *ipaddr); + +void raw_recv (struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg); +err_t raw_sendto (struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr); +err_t raw_send (struct raw_pcb *pcb, struct pbuf *p); + +#if LWIP_IPV6 +struct raw_pcb * raw_new_ip6 (u8_t proto); +#define raw_bind_ip6(pcb, ip6addr) raw_bind(pcb, ip6_2_ip(ip6addr)) +#define raw_connect_ip6(pcb, ip6addr) raw_connect(pcb, ip6_2_ip(ip6addr)) +#define raw_recv_ip6(pcb, recv_ip6_fn, recv_arg) raw_recv(pcb, (raw_recv_fn)recv_ip6_fn, recv_arg) +#define raw_sendto_ip6(pcb, pbuf, ip6addr) raw_sendto(pcb, pbuf, ip6_2_ip(ip6addr)) +#endif /* LWIP_IPV6 */ + +/* The following functions are the lower layer interface to RAW. */ +u8_t raw_input (struct pbuf *p, struct netif *inp); +#define raw_init() /* Compatibility define, no init needed. */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_RAW */ + +#endif /* LWIP_HDR_RAW_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/sio.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/sio.h new file mode 100644 index 0000000..23d116b --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/sio.h @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + */ + +/* + * This is the interface to the platform specific serial IO module + * It needs to be implemented by those platforms which need SLIP or PPP + */ + +#ifndef SIO_H +#define SIO_H + +#include "lwip/arch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* If you want to define sio_fd_t elsewhere or differently, + define this in your cc.h file. */ +#ifndef __sio_fd_t_defined +typedef void * sio_fd_t; +#endif + +/* The following functions can be defined to something else in your cc.h file + or be implemented in your custom sio.c file. */ + +#ifndef sio_open +/** + * Opens a serial device for communication. + * + * @param devnum device number + * @return handle to serial device if successful, NULL otherwise + */ +sio_fd_t sio_open(u8_t devnum); +#endif + +#ifndef sio_send +/** + * Sends a single character to the serial device. + * + * @param c character to send + * @param fd serial device handle + * + * @note This function will block until the character can be sent. + */ +void sio_send(u8_t c, sio_fd_t fd); +#endif + +#ifndef sio_recv +/** + * Receives a single character from the serial device. + * + * @param fd serial device handle + * + * @note This function will block until a character is received. + */ +u8_t sio_recv(sio_fd_t fd); +#endif + +#ifndef sio_read +/** + * Reads from the serial device. + * + * @param fd serial device handle + * @param data pointer to data buffer for receiving + * @param len maximum length (in bytes) of data to receive + * @return number of bytes actually received - may be 0 if aborted by sio_read_abort + * + * @note This function will block until data can be received. The blocking + * can be cancelled by calling sio_read_abort(). + */ +u32_t sio_read(sio_fd_t fd, u8_t *data, u32_t len); +#endif + +#ifndef sio_tryread +/** + * Tries to read from the serial device. Same as sio_read but returns + * immediately if no data is available and never blocks. + * + * @param fd serial device handle + * @param data pointer to data buffer for receiving + * @param len maximum length (in bytes) of data to receive + * @return number of bytes actually received + */ +u32_t sio_tryread(sio_fd_t fd, u8_t *data, u32_t len); +#endif + +#ifndef sio_write +/** + * Writes to the serial device. + * + * @param fd serial device handle + * @param data pointer to data to send + * @param len length (in bytes) of data to send + * @return number of bytes actually sent + * + * @note This function will block until all data can be sent. + */ +u32_t sio_write(sio_fd_t fd, u8_t *data, u32_t len); +#endif + +#ifndef sio_read_abort +/** + * Aborts a blocking sio_read() call. + * + * @param fd serial device handle + */ +void sio_read_abort(sio_fd_t fd); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* SIO_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/snmp.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/snmp.h new file mode 100644 index 0000000..101bb66 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/snmp.h @@ -0,0 +1,367 @@ +/* + * Copyright (c) 2001, 2002 Leon Woestenberg + * Copyright (c) 2001, 2002 Axon Digital Design B.V., The Netherlands. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Leon Woestenberg + * + */ +#ifndef LWIP_HDR_SNMP_H +#define LWIP_HDR_SNMP_H + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include "lwip/ip_addr.h" + +struct udp_pcb; +struct netif; + +/** + * @see RFC1213, "MIB-II, 6. Definitions" + */ +enum snmp_ifType { + snmp_ifType_other=1, /* none of the following */ + snmp_ifType_regular1822, + snmp_ifType_hdh1822, + snmp_ifType_ddn_x25, + snmp_ifType_rfc877_x25, + snmp_ifType_ethernet_csmacd, + snmp_ifType_iso88023_csmacd, + snmp_ifType_iso88024_tokenBus, + snmp_ifType_iso88025_tokenRing, + snmp_ifType_iso88026_man, + snmp_ifType_starLan, + snmp_ifType_proteon_10Mbit, + snmp_ifType_proteon_80Mbit, + snmp_ifType_hyperchannel, + snmp_ifType_fddi, + snmp_ifType_lapb, + snmp_ifType_sdlc, + snmp_ifType_ds1, /* T-1 */ + snmp_ifType_e1, /* european equiv. of T-1 */ + snmp_ifType_basicISDN, + snmp_ifType_primaryISDN, /* proprietary serial */ + snmp_ifType_propPointToPointSerial, + snmp_ifType_ppp, + snmp_ifType_softwareLoopback, + snmp_ifType_eon, /* CLNP over IP [11] */ + snmp_ifType_ethernet_3Mbit, + snmp_ifType_nsip, /* XNS over IP */ + snmp_ifType_slip, /* generic SLIP */ + snmp_ifType_ultra, /* ULTRA technologies */ + snmp_ifType_ds3, /* T-3 */ + snmp_ifType_sip, /* SMDS */ + snmp_ifType_frame_relay +}; + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +/** SNMP "sysuptime" Interval */ +#define SNMP_SYSUPTIME_INTERVAL 10 + +/** fixed maximum length for object identifier type */ +#define LWIP_SNMP_OBJ_ID_LEN 32 + +/** internal object identifier representation */ +struct snmp_obj_id +{ + u8_t len; + s32_t id[LWIP_SNMP_OBJ_ID_LEN]; +}; + +/* system */ +void snmp_set_sysdescr(const u8_t* str, const u8_t* len); +void snmp_set_sysobjid(const struct snmp_obj_id *oid); +void snmp_get_sysobjid_ptr(const struct snmp_obj_id **oid); +void snmp_inc_sysuptime(void); +void snmp_add_sysuptime(u32_t value); +void snmp_get_sysuptime(u32_t *value); +void snmp_set_syscontact(u8_t *ocstr, u8_t *ocstrlen); +void snmp_set_sysname(u8_t *ocstr, u8_t *ocstrlen); +void snmp_set_syslocation(u8_t *ocstr, u8_t *ocstrlen); + +/* network interface */ +void snmp_add_ifinoctets(struct netif *ni, u32_t value); +void snmp_inc_ifinucastpkts(struct netif *ni); +void snmp_inc_ifinnucastpkts(struct netif *ni); +void snmp_inc_ifindiscards(struct netif *ni); +void snmp_add_ifoutoctets(struct netif *ni, u32_t value); +void snmp_inc_ifoutucastpkts(struct netif *ni); +void snmp_inc_ifoutnucastpkts(struct netif *ni); +void snmp_inc_ifoutdiscards(struct netif *ni); +void snmp_inc_iflist(void); +void snmp_dec_iflist(void); + +/* ARP (for atTable and ipNetToMediaTable) */ +void snmp_insert_arpidx_tree(struct netif *ni, ip_addr_t *ip); +void snmp_delete_arpidx_tree(struct netif *ni, ip_addr_t *ip); + +/* IP */ +void snmp_inc_ipinreceives(void); +void snmp_inc_ipinhdrerrors(void); +void snmp_inc_ipinaddrerrors(void); +void snmp_inc_ipforwdatagrams(void); +void snmp_inc_ipinunknownprotos(void); +void snmp_inc_ipindiscards(void); +void snmp_inc_ipindelivers(void); +void snmp_inc_ipoutrequests(void); +void snmp_inc_ipoutdiscards(void); +void snmp_inc_ipoutnoroutes(void); +void snmp_inc_ipreasmreqds(void); +void snmp_inc_ipreasmoks(void); +void snmp_inc_ipreasmfails(void); +void snmp_inc_ipfragoks(void); +void snmp_inc_ipfragfails(void); +void snmp_inc_ipfragcreates(void); +void snmp_inc_iproutingdiscards(void); +void snmp_insert_ipaddridx_tree(struct netif *ni); +void snmp_delete_ipaddridx_tree(struct netif *ni); +void snmp_insert_iprteidx_tree(u8_t dflt, struct netif *ni); +void snmp_delete_iprteidx_tree(u8_t dflt, struct netif *ni); + +/* ICMP */ +void snmp_inc_icmpinmsgs(void); +void snmp_inc_icmpinerrors(void); +void snmp_inc_icmpindestunreachs(void); +void snmp_inc_icmpintimeexcds(void); +void snmp_inc_icmpinparmprobs(void); +void snmp_inc_icmpinsrcquenchs(void); +void snmp_inc_icmpinredirects(void); +void snmp_inc_icmpinechos(void); +void snmp_inc_icmpinechoreps(void); +void snmp_inc_icmpintimestamps(void); +void snmp_inc_icmpintimestampreps(void); +void snmp_inc_icmpinaddrmasks(void); +void snmp_inc_icmpinaddrmaskreps(void); +void snmp_inc_icmpoutmsgs(void); +void snmp_inc_icmpouterrors(void); +void snmp_inc_icmpoutdestunreachs(void); +void snmp_inc_icmpouttimeexcds(void); +void snmp_inc_icmpoutparmprobs(void); +void snmp_inc_icmpoutsrcquenchs(void); +void snmp_inc_icmpoutredirects(void); +void snmp_inc_icmpoutechos(void); +void snmp_inc_icmpoutechoreps(void); +void snmp_inc_icmpouttimestamps(void); +void snmp_inc_icmpouttimestampreps(void); +void snmp_inc_icmpoutaddrmasks(void); +void snmp_inc_icmpoutaddrmaskreps(void); + +/* TCP */ +void snmp_inc_tcpactiveopens(void); +void snmp_inc_tcppassiveopens(void); +void snmp_inc_tcpattemptfails(void); +void snmp_inc_tcpestabresets(void); +void snmp_inc_tcpinsegs(void); +void snmp_inc_tcpoutsegs(void); +void snmp_inc_tcpretranssegs(void); +void snmp_inc_tcpinerrs(void); +void snmp_inc_tcpoutrsts(void); + +/* UDP */ +void snmp_inc_udpindatagrams(void); +void snmp_inc_udpnoports(void); +void snmp_inc_udpinerrors(void); +void snmp_inc_udpoutdatagrams(void); +void snmp_insert_udpidx_tree(struct udp_pcb *pcb); +void snmp_delete_udpidx_tree(struct udp_pcb *pcb); + +/* SNMP */ +void snmp_inc_snmpinpkts(void); +void snmp_inc_snmpoutpkts(void); +void snmp_inc_snmpinbadversions(void); +void snmp_inc_snmpinbadcommunitynames(void); +void snmp_inc_snmpinbadcommunityuses(void); +void snmp_inc_snmpinasnparseerrs(void); +void snmp_inc_snmpintoobigs(void); +void snmp_inc_snmpinnosuchnames(void); +void snmp_inc_snmpinbadvalues(void); +void snmp_inc_snmpinreadonlys(void); +void snmp_inc_snmpingenerrs(void); +void snmp_add_snmpintotalreqvars(u8_t value); +void snmp_add_snmpintotalsetvars(u8_t value); +void snmp_inc_snmpingetrequests(void); +void snmp_inc_snmpingetnexts(void); +void snmp_inc_snmpinsetrequests(void); +void snmp_inc_snmpingetresponses(void); +void snmp_inc_snmpintraps(void); +void snmp_inc_snmpouttoobigs(void); +void snmp_inc_snmpoutnosuchnames(void); +void snmp_inc_snmpoutbadvalues(void); +void snmp_inc_snmpoutgenerrs(void); +void snmp_inc_snmpoutgetrequests(void); +void snmp_inc_snmpoutgetnexts(void); +void snmp_inc_snmpoutsetrequests(void); +void snmp_inc_snmpoutgetresponses(void); +void snmp_inc_snmpouttraps(void); +void snmp_get_snmpgrpid_ptr(struct snmp_obj_id **oid); +void snmp_set_snmpenableauthentraps(u8_t *value); +void snmp_get_snmpenableauthentraps(u8_t *value); + +/* LWIP_SNMP support not available */ +/* define everything to be empty */ +#else + +/* system */ +#define snmp_set_sysdescr(str, len) +#define snmp_set_sysobjid(oid); +#define snmp_get_sysobjid_ptr(oid) +#define snmp_inc_sysuptime() +#define snmp_add_sysuptime(value) +#define snmp_get_sysuptime(value) +#define snmp_set_syscontact(ocstr, ocstrlen); +#define snmp_set_sysname(ocstr, ocstrlen); +#define snmp_set_syslocation(ocstr, ocstrlen); + +/* network interface */ +#define snmp_add_ifinoctets(ni,value) +#define snmp_inc_ifinucastpkts(ni) +#define snmp_inc_ifinnucastpkts(ni) +#define snmp_inc_ifindiscards(ni) +#define snmp_add_ifoutoctets(ni,value) +#define snmp_inc_ifoutucastpkts(ni) +#define snmp_inc_ifoutnucastpkts(ni) +#define snmp_inc_ifoutdiscards(ni) +#define snmp_inc_iflist() +#define snmp_dec_iflist() + +/* ARP */ +#define snmp_insert_arpidx_tree(ni,ip) +#define snmp_delete_arpidx_tree(ni,ip) + +/* IP */ +#define snmp_inc_ipinreceives() +#define snmp_inc_ipinhdrerrors() +#define snmp_inc_ipinaddrerrors() +#define snmp_inc_ipforwdatagrams() +#define snmp_inc_ipinunknownprotos() +#define snmp_inc_ipindiscards() +#define snmp_inc_ipindelivers() +#define snmp_inc_ipoutrequests() +#define snmp_inc_ipoutdiscards() +#define snmp_inc_ipoutnoroutes() +#define snmp_inc_ipreasmreqds() +#define snmp_inc_ipreasmoks() +#define snmp_inc_ipreasmfails() +#define snmp_inc_ipfragoks() +#define snmp_inc_ipfragfails() +#define snmp_inc_ipfragcreates() +#define snmp_inc_iproutingdiscards() +#define snmp_insert_ipaddridx_tree(ni) +#define snmp_delete_ipaddridx_tree(ni) +#define snmp_insert_iprteidx_tree(dflt, ni) +#define snmp_delete_iprteidx_tree(dflt, ni) + +/* ICMP */ +#define snmp_inc_icmpinmsgs() +#define snmp_inc_icmpinerrors() +#define snmp_inc_icmpindestunreachs() +#define snmp_inc_icmpintimeexcds() +#define snmp_inc_icmpinparmprobs() +#define snmp_inc_icmpinsrcquenchs() +#define snmp_inc_icmpinredirects() +#define snmp_inc_icmpinechos() +#define snmp_inc_icmpinechoreps() +#define snmp_inc_icmpintimestamps() +#define snmp_inc_icmpintimestampreps() +#define snmp_inc_icmpinaddrmasks() +#define snmp_inc_icmpinaddrmaskreps() +#define snmp_inc_icmpoutmsgs() +#define snmp_inc_icmpouterrors() +#define snmp_inc_icmpoutdestunreachs() +#define snmp_inc_icmpouttimeexcds() +#define snmp_inc_icmpoutparmprobs() +#define snmp_inc_icmpoutsrcquenchs() +#define snmp_inc_icmpoutredirects() +#define snmp_inc_icmpoutechos() +#define snmp_inc_icmpoutechoreps() +#define snmp_inc_icmpouttimestamps() +#define snmp_inc_icmpouttimestampreps() +#define snmp_inc_icmpoutaddrmasks() +#define snmp_inc_icmpoutaddrmaskreps() +/* TCP */ +#define snmp_inc_tcpactiveopens() +#define snmp_inc_tcppassiveopens() +#define snmp_inc_tcpattemptfails() +#define snmp_inc_tcpestabresets() +#define snmp_inc_tcpinsegs() +#define snmp_inc_tcpoutsegs() +#define snmp_inc_tcpretranssegs() +#define snmp_inc_tcpinerrs() +#define snmp_inc_tcpoutrsts() + +/* UDP */ +#define snmp_inc_udpindatagrams() +#define snmp_inc_udpnoports() +#define snmp_inc_udpinerrors() +#define snmp_inc_udpoutdatagrams() +#define snmp_insert_udpidx_tree(pcb) +#define snmp_delete_udpidx_tree(pcb) + +/* SNMP */ +#define snmp_inc_snmpinpkts() +#define snmp_inc_snmpoutpkts() +#define snmp_inc_snmpinbadversions() +#define snmp_inc_snmpinbadcommunitynames() +#define snmp_inc_snmpinbadcommunityuses() +#define snmp_inc_snmpinasnparseerrs() +#define snmp_inc_snmpintoobigs() +#define snmp_inc_snmpinnosuchnames() +#define snmp_inc_snmpinbadvalues() +#define snmp_inc_snmpinreadonlys() +#define snmp_inc_snmpingenerrs() +#define snmp_add_snmpintotalreqvars(value) +#define snmp_add_snmpintotalsetvars(value) +#define snmp_inc_snmpingetrequests() +#define snmp_inc_snmpingetnexts() +#define snmp_inc_snmpinsetrequests() +#define snmp_inc_snmpingetresponses() +#define snmp_inc_snmpintraps() +#define snmp_inc_snmpouttoobigs() +#define snmp_inc_snmpoutnosuchnames() +#define snmp_inc_snmpoutbadvalues() +#define snmp_inc_snmpoutgenerrs() +#define snmp_inc_snmpoutgetrequests() +#define snmp_inc_snmpoutgetnexts() +#define snmp_inc_snmpoutsetrequests() +#define snmp_inc_snmpoutgetresponses() +#define snmp_inc_snmpouttraps() +#define snmp_get_snmpgrpid_ptr(oid) +#define snmp_set_snmpenableauthentraps(value) +#define snmp_get_snmpenableauthentraps(value) + +#endif /* LWIP_SNMP */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_SNMP_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/snmp_asn1.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/snmp_asn1.h new file mode 100644 index 0000000..9ef9228 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/snmp_asn1.h @@ -0,0 +1,101 @@ +/** + * @file + * Abstract Syntax Notation One (ISO 8824, 8825) codec. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * Author: Christiaan Simons + */ + +#ifndef LWIP_HDR_SNMP_ASN1_H +#define LWIP_HDR_SNMP_ASN1_H + +#include "lwip/opt.h" +#include "lwip/err.h" +#include "lwip/pbuf.h" +#include "lwip/snmp.h" + +#if LWIP_SNMP + +#ifdef __cplusplus +extern "C" { +#endif + +#define SNMP_ASN1_UNIV (0) /* (!0x80 | !0x40) */ +#define SNMP_ASN1_APPLIC (0x40) /* (!0x80 | 0x40) */ +#define SNMP_ASN1_CONTXT (0x80) /* ( 0x80 | !0x40) */ + +#define SNMP_ASN1_CONSTR (0x20) /* ( 0x20) */ +#define SNMP_ASN1_PRIMIT (0) /* (!0x20) */ + +/* universal tags */ +#define SNMP_ASN1_INTEG 2 +#define SNMP_ASN1_OC_STR 4 +#define SNMP_ASN1_NUL 5 +#define SNMP_ASN1_OBJ_ID 6 +#define SNMP_ASN1_SEQ 16 + +/* application specific (SNMP) tags */ +#define SNMP_ASN1_IPADDR 0 /* octet string size(4) */ +#define SNMP_ASN1_COUNTER 1 /* u32_t */ +#define SNMP_ASN1_GAUGE 2 /* u32_t */ +#define SNMP_ASN1_TIMETICKS 3 /* u32_t */ +#define SNMP_ASN1_OPAQUE 4 /* octet string */ + +/* context specific (SNMP) tags */ +#define SNMP_ASN1_PDU_GET_REQ 0 +#define SNMP_ASN1_PDU_GET_NEXT_REQ 1 +#define SNMP_ASN1_PDU_GET_RESP 2 +#define SNMP_ASN1_PDU_SET_REQ 3 +#define SNMP_ASN1_PDU_TRAP 4 + +err_t snmp_asn1_dec_type(struct pbuf *p, u16_t ofs, u8_t *type); +err_t snmp_asn1_dec_length(struct pbuf *p, u16_t ofs, u8_t *octets_used, u16_t *length); +err_t snmp_asn1_dec_u32t(struct pbuf *p, u16_t ofs, u16_t len, u32_t *value); +err_t snmp_asn1_dec_s32t(struct pbuf *p, u16_t ofs, u16_t len, s32_t *value); +err_t snmp_asn1_dec_oid(struct pbuf *p, u16_t ofs, u16_t len, struct snmp_obj_id *oid); +err_t snmp_asn1_dec_raw(struct pbuf *p, u16_t ofs, u16_t len, u16_t raw_len, u8_t *raw); + +void snmp_asn1_enc_length_cnt(u16_t length, u8_t *octets_needed); +void snmp_asn1_enc_u32t_cnt(u32_t value, u16_t *octets_needed); +void snmp_asn1_enc_s32t_cnt(s32_t value, u16_t *octets_needed); +void snmp_asn1_enc_oid_cnt(u8_t ident_len, s32_t *ident, u16_t *octets_needed); +err_t snmp_asn1_enc_type(struct pbuf *p, u16_t ofs, u8_t type); +err_t snmp_asn1_enc_length(struct pbuf *p, u16_t ofs, u16_t length); +err_t snmp_asn1_enc_u32t(struct pbuf *p, u16_t ofs, u16_t octets_needed, u32_t value); +err_t snmp_asn1_enc_s32t(struct pbuf *p, u16_t ofs, u16_t octets_needed, s32_t value); +err_t snmp_asn1_enc_oid(struct pbuf *p, u16_t ofs, u8_t ident_len, s32_t *ident); +err_t snmp_asn1_enc_raw(struct pbuf *p, u16_t ofs, u16_t raw_len, u8_t *raw); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SNMP */ + +#endif /* LWIP_HDR_SNMP_ASN1_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/snmp_msg.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/snmp_msg.h new file mode 100644 index 0000000..3f65395 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/snmp_msg.h @@ -0,0 +1,315 @@ +/** + * @file + * SNMP Agent message handling structures. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * Author: Christiaan Simons + */ + +#ifndef LWIP_HDR_SNMP_MSG_H +#define LWIP_HDR_SNMP_MSG_H + +#include "lwip/opt.h" +#include "lwip/snmp.h" +#include "lwip/snmp_structs.h" +#include "lwip/ip_addr.h" +#include "lwip/err.h" + +#if LWIP_SNMP + +#if SNMP_PRIVATE_MIB +/* When using a private MIB, you have to create a file 'private_mib.h' that contains + * a 'struct mib_array_node mib_private' which contains your MIB. */ +#include "private_mib.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* The listen port of the SNMP agent. Clients have to make their requests to + this port. Most standard clients won't work if you change this! */ +#ifndef SNMP_IN_PORT +#define SNMP_IN_PORT 161 +#endif +/* The remote port the SNMP agent sends traps to. Most standard trap sinks won't + work if you change this! */ +#ifndef SNMP_TRAP_PORT +#define SNMP_TRAP_PORT 162 +#endif + +#define SNMP_ES_NOERROR 0 +#define SNMP_ES_TOOBIG 1 +#define SNMP_ES_NOSUCHNAME 2 +#define SNMP_ES_BADVALUE 3 +#define SNMP_ES_READONLY 4 +#define SNMP_ES_GENERROR 5 + +#define SNMP_GENTRAP_COLDSTART 0 +#define SNMP_GENTRAP_WARMSTART 1 +#define SNMP_GENTRAP_AUTHFAIL 4 +#define SNMP_GENTRAP_ENTERPRISESPC 6 + +struct snmp_varbind +{ + /* next pointer, NULL for last in list */ + struct snmp_varbind *next; + /* previous pointer, NULL for first in list */ + struct snmp_varbind *prev; + + /* object identifier length (in s32_t) */ + u8_t ident_len; + /* object identifier array */ + s32_t *ident; + + /* object value ASN1 type */ + u8_t value_type; + /* object value length (in u8_t) */ + u8_t value_len; + /* object value */ + void *value; + + /* encoding varbind seq length length */ + u8_t seqlenlen; + /* encoding object identifier length length */ + u8_t olenlen; + /* encoding object value length length */ + u8_t vlenlen; + /* encoding varbind seq length */ + u16_t seqlen; + /* encoding object identifier length */ + u16_t olen; + /* encoding object value length */ + u16_t vlen; +}; + +struct snmp_varbind_root +{ + struct snmp_varbind *head; + struct snmp_varbind *tail; + /* number of variable bindings in list */ + u8_t count; + /* encoding varbind-list seq length length */ + u8_t seqlenlen; + /* encoding varbind-list seq length */ + u16_t seqlen; +}; + +/** output response message header length fields */ +struct snmp_resp_header_lengths +{ + /* encoding error-index length length */ + u8_t erridxlenlen; + /* encoding error-status length length */ + u8_t errstatlenlen; + /* encoding request id length length */ + u8_t ridlenlen; + /* encoding pdu length length */ + u8_t pdulenlen; + /* encoding community length length */ + u8_t comlenlen; + /* encoding version length length */ + u8_t verlenlen; + /* encoding sequence length length */ + u8_t seqlenlen; + + /* encoding error-index length */ + u16_t erridxlen; + /* encoding error-status length */ + u16_t errstatlen; + /* encoding request id length */ + u16_t ridlen; + /* encoding pdu length */ + u16_t pdulen; + /* encoding community length */ + u16_t comlen; + /* encoding version length */ + u16_t verlen; + /* encoding sequence length */ + u16_t seqlen; +}; + +/** output response message header length fields */ +struct snmp_trap_header_lengths +{ + /* encoding timestamp length length */ + u8_t tslenlen; + /* encoding specific-trap length length */ + u8_t strplenlen; + /* encoding generic-trap length length */ + u8_t gtrplenlen; + /* encoding agent-addr length length */ + u8_t aaddrlenlen; + /* encoding enterprise-id length length */ + u8_t eidlenlen; + /* encoding pdu length length */ + u8_t pdulenlen; + /* encoding community length length */ + u8_t comlenlen; + /* encoding version length length */ + u8_t verlenlen; + /* encoding sequence length length */ + u8_t seqlenlen; + + /* encoding timestamp length */ + u16_t tslen; + /* encoding specific-trap length */ + u16_t strplen; + /* encoding generic-trap length */ + u16_t gtrplen; + /* encoding agent-addr length */ + u16_t aaddrlen; + /* encoding enterprise-id length */ + u16_t eidlen; + /* encoding pdu length */ + u16_t pdulen; + /* encoding community length */ + u16_t comlen; + /* encoding version length */ + u16_t verlen; + /* encoding sequence length */ + u16_t seqlen; +}; + +/* Accepting new SNMP messages. */ +#define SNMP_MSG_EMPTY 0 +/* Search for matching object for variable binding. */ +#define SNMP_MSG_SEARCH_OBJ 1 +/* Perform SNMP operation on in-memory object. + Pass-through states, for symmetry only. */ +#define SNMP_MSG_INTERNAL_GET_OBJDEF 2 +#define SNMP_MSG_INTERNAL_GET_VALUE 3 +#define SNMP_MSG_INTERNAL_SET_TEST 4 +#define SNMP_MSG_INTERNAL_GET_OBJDEF_S 5 +#define SNMP_MSG_INTERNAL_SET_VALUE 6 +/* Perform SNMP operation on object located externally. + In theory this could be used for building a proxy agent. + Practical use is for an enterprise spc. app. gateway. */ +#define SNMP_MSG_EXTERNAL_GET_OBJDEF 7 +#define SNMP_MSG_EXTERNAL_GET_VALUE 8 +#define SNMP_MSG_EXTERNAL_SET_TEST 9 +#define SNMP_MSG_EXTERNAL_GET_OBJDEF_S 10 +#define SNMP_MSG_EXTERNAL_SET_VALUE 11 + +#define SNMP_COMMUNITY_STR_LEN 64 +struct snmp_msg_pstat +{ + /* lwIP local port (161) binding */ + struct udp_pcb *pcb; + /* source IP address */ + ip_addr_t sip; + /* source UDP port */ + u16_t sp; + /* request type */ + u8_t rt; + /* request ID */ + s32_t rid; + /* error status */ + s32_t error_status; + /* error index */ + s32_t error_index; + /* community name (zero terminated) */ + u8_t community[SNMP_COMMUNITY_STR_LEN + 1]; + /* community string length (exclusive zero term) */ + u8_t com_strlen; + /* one out of MSG_EMPTY, MSG_DEMUX, MSG_INTERNAL, MSG_EXTERNAL_x */ + u8_t state; + /* saved arguments for MSG_EXTERNAL_x */ + struct mib_external_node *ext_mib_node; + struct snmp_name_ptr ext_name_ptr; + struct obj_def ext_object_def; + struct snmp_obj_id ext_oid; + /* index into input variable binding list */ + u8_t vb_idx; + /* ptr into input variable binding list */ + struct snmp_varbind *vb_ptr; + /* list of variable bindings from input */ + struct snmp_varbind_root invb; + /* list of variable bindings to output */ + struct snmp_varbind_root outvb; + /* output response lengths used in ASN encoding */ + struct snmp_resp_header_lengths rhl; +}; + +struct snmp_msg_trap +{ + /* lwIP local port (161) binding */ + struct udp_pcb *pcb; + /* destination IP address in network order */ + ip_addr_t dip; + + /* source enterprise ID (sysObjectID) */ + struct snmp_obj_id *enterprise; + /* source IP address, raw network order format */ + u8_t sip_raw[4]; + /* generic trap code */ + u32_t gen_trap; + /* specific trap code */ + u32_t spc_trap; + /* timestamp */ + u32_t ts; + /* list of variable bindings to output */ + struct snmp_varbind_root outvb; + /* output trap lengths used in ASN encoding */ + struct snmp_trap_header_lengths thl; +}; + +/** Agent Version constant, 0 = v1 oddity */ +extern const s32_t snmp_version; +/** Agent default "public" community string */ +extern const char snmp_publiccommunity[7]; + +extern struct snmp_msg_trap trap_msg; + +/** Agent setup, start listening to port 161. */ +void snmp_init(void); +void snmp_trap_dst_enable(u8_t dst_idx, u8_t enable); +void snmp_trap_dst_ip_set(u8_t dst_idx, ip_addr_t *dst); + +/** Varbind-list functions. */ +struct snmp_varbind* snmp_varbind_alloc(struct snmp_obj_id *oid, u8_t type, u8_t len); +void snmp_varbind_free(struct snmp_varbind *vb); +void snmp_varbind_list_free(struct snmp_varbind_root *root); +void snmp_varbind_tail_add(struct snmp_varbind_root *root, struct snmp_varbind *vb); +struct snmp_varbind* snmp_varbind_tail_remove(struct snmp_varbind_root *root); + +/** Handle an internal (recv) or external (private response) event. */ +void snmp_msg_event(u8_t request_id); +err_t snmp_send_response(struct snmp_msg_pstat *m_stat); +err_t snmp_send_trap(s8_t generic_trap, struct snmp_obj_id *eoid, s32_t specific_trap); +void snmp_coldstart_trap(void); +void snmp_authfail_trap(void); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SNMP */ + +#endif /* LWIP_HDR_SNMP_MSG_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/snmp_structs.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/snmp_structs.h new file mode 100644 index 0000000..b69160c --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/snmp_structs.h @@ -0,0 +1,268 @@ +/** + * @file + * Generic MIB tree structures. + * + * @todo namespace prefixes + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * Author: Christiaan Simons + */ + +#ifndef LWIP_HDR_SNMP_STRUCTS_H +#define LWIP_HDR_SNMP_STRUCTS_H + +#include "lwip/opt.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/snmp.h" + +#if SNMP_PRIVATE_MIB +/* When using a private MIB, you have to create a file 'private_mib.h' that contains + * a 'struct mib_array_node mib_private' which contains your MIB. */ +#include "private_mib.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* MIB object instance */ +#define MIB_OBJECT_NONE 0 +#define MIB_OBJECT_SCALAR 1 +#define MIB_OBJECT_TAB 2 + +/* MIB access types */ +#define MIB_ACCESS_READ 1 +#define MIB_ACCESS_WRITE 2 + +/* MIB object access */ +#define MIB_OBJECT_READ_ONLY MIB_ACCESS_READ +#define MIB_OBJECT_READ_WRITE (MIB_ACCESS_READ | MIB_ACCESS_WRITE) +#define MIB_OBJECT_WRITE_ONLY MIB_ACCESS_WRITE +#define MIB_OBJECT_NOT_ACCESSIBLE 0 + +/** object definition returned by (get_object_def)() */ +struct obj_def +{ + /* MIB_OBJECT_NONE (0), MIB_OBJECT_SCALAR (1), MIB_OBJECT_TAB (2) */ + u8_t instance; + /* 0 read-only, 1 read-write, 2 write-only, 3 not-accessible */ + u8_t access; + /* ASN type for this object */ + u8_t asn_type; + /* value length (host length) */ + u16_t v_len; + /* length of instance part of supplied object identifier */ + u8_t id_inst_len; + /* instance part of supplied object identifier */ + s32_t *id_inst_ptr; +}; + +struct snmp_name_ptr +{ + u8_t ident_len; + s32_t *ident; +}; + +/** MIB const scalar (.0) node */ +#define MIB_NODE_SC 0x01 +/** MIB const array node */ +#define MIB_NODE_AR 0x02 +/** MIB array node (mem_malloced from RAM) */ +#define MIB_NODE_RA 0x03 +/** MIB list root node (mem_malloced from RAM) */ +#define MIB_NODE_LR 0x04 +/** MIB node for external objects */ +#define MIB_NODE_EX 0x05 + +/** node "base class" layout, the mandatory fields for a node */ +struct mib_node +{ + /** returns struct obj_def for the given object identifier */ + void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od); + /** returns object value for the given object identifier, + @note the caller must allocate at least len bytes for the value */ + void (*get_value)(struct obj_def *od, u16_t len, void *value); + /** tests length and/or range BEFORE setting */ + u8_t (*set_test)(struct obj_def *od, u16_t len, void *value); + /** sets object value, only to be called when set_test() */ + void (*set_value)(struct obj_def *od, u16_t len, void *value); + /** One out of MIB_NODE_AR, MIB_NODE_LR or MIB_NODE_EX */ + u8_t node_type; + /* array or max list length */ + u16_t maxlength; +}; + +/** derived node for scalars .0 index */ +typedef struct mib_node mib_scalar_node; + +/** derived node, points to a fixed size const array + of sub-identifiers plus a 'child' pointer */ +struct mib_array_node +{ + /* inherited "base class" members */ + void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od); + void (*get_value)(struct obj_def *od, u16_t len, void *value); + u8_t (*set_test)(struct obj_def *od, u16_t len, void *value); + void (*set_value)(struct obj_def *od, u16_t len, void *value); + + u8_t node_type; + u16_t maxlength; + + /* additional struct members */ + const s32_t *objid; + struct mib_node* const *nptr; +}; + +/** derived node, points to a fixed size mem_malloced array + of sub-identifiers plus a 'child' pointer */ +struct mib_ram_array_node +{ + /* inherited "base class" members */ + void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od); + void (*get_value)(struct obj_def *od, u16_t len, void *value); + u8_t (*set_test)(struct obj_def *od, u16_t len, void *value); + void (*set_value)(struct obj_def *od, u16_t len, void *value); + + u8_t node_type; + u16_t maxlength; + + /* aditional struct members */ + s32_t *objid; + struct mib_node **nptr; +}; + +struct mib_list_node +{ + struct mib_list_node *prev; + struct mib_list_node *next; + s32_t objid; + struct mib_node *nptr; +}; + +/** derived node, points to a doubly linked list + of sub-identifiers plus a 'child' pointer */ +struct mib_list_rootnode +{ + /* inherited "base class" members */ + void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od); + void (*get_value)(struct obj_def *od, u16_t len, void *value); + u8_t (*set_test)(struct obj_def *od, u16_t len, void *value); + void (*set_value)(struct obj_def *od, u16_t len, void *value); + + u8_t node_type; + u16_t maxlength; + + /* additional struct members */ + struct mib_list_node *head; + struct mib_list_node *tail; + /* counts list nodes in list */ + u16_t count; +}; + +/** derived node, has access functions for mib object in external memory or device + using 'tree_level' and 'idx', with a range 0 .. (level_length() - 1) */ +struct mib_external_node +{ + /* inherited "base class" members */ + void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od); + void (*get_value)(struct obj_def *od, u16_t len, void *value); + u8_t (*set_test)(struct obj_def *od, u16_t len, void *value); + void (*set_value)(struct obj_def *od, u16_t len, void *value); + + u8_t node_type; + u16_t maxlength; + + /* additional struct members */ + /** points to an external (in memory) record of some sort of addressing + information, passed to and interpreted by the functions below */ + void* addr_inf; + /** tree levels under this node */ + u8_t tree_levels; + /** number of objects at this level */ + u16_t (*level_length)(void* addr_inf, u8_t level); + /** compares object sub identifier with external id + return zero when equal, nonzero when unequal */ + s32_t (*ident_cmp)(void* addr_inf, u8_t level, u16_t idx, s32_t sub_id); + void (*get_objid)(void* addr_inf, u8_t level, u16_t idx, s32_t *sub_id); + + /** async Questions */ + void (*get_object_def_q)(void* addr_inf, u8_t rid, u8_t ident_len, s32_t *ident); + void (*get_value_q)(u8_t rid, struct obj_def *od); + void (*set_test_q)(u8_t rid, struct obj_def *od); + void (*set_value_q)(u8_t rid, struct obj_def *od, u16_t len, void *value); + /** async Answers */ + void (*get_object_def_a)(u8_t rid, u8_t ident_len, s32_t *ident, struct obj_def *od); + void (*get_value_a)(u8_t rid, struct obj_def *od, u16_t len, void *value); + u8_t (*set_test_a)(u8_t rid, struct obj_def *od, u16_t len, void *value); + void (*set_value_a)(u8_t rid, struct obj_def *od, u16_t len, void *value); + /** async Panic Close (agent returns error reply, + e.g. used for external transaction cleanup) */ + void (*get_object_def_pc)(u8_t rid, u8_t ident_len, s32_t *ident); + void (*get_value_pc)(u8_t rid, struct obj_def *od); + void (*set_test_pc)(u8_t rid, struct obj_def *od); + void (*set_value_pc)(u8_t rid, struct obj_def *od); +}; + +/** export MIB tree from mib2.c */ +extern const struct mib_array_node internet; + +/** dummy function pointers for non-leaf MIB nodes from mib2.c */ +void noleafs_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +void noleafs_get_value(struct obj_def *od, u16_t len, void *value); +u8_t noleafs_set_test(struct obj_def *od, u16_t len, void *value); +void noleafs_set_value(struct obj_def *od, u16_t len, void *value); + +void snmp_oidtoip(s32_t *ident, ip_addr_t *ip); +void snmp_iptooid(ip_addr_t *ip, s32_t *ident); +void snmp_ifindextonetif(s32_t ifindex, struct netif **netif); +void snmp_netiftoifindex(struct netif *netif, s32_t *ifidx); + +struct mib_list_node* snmp_mib_ln_alloc(s32_t id); +void snmp_mib_ln_free(struct mib_list_node *ln); +struct mib_list_rootnode* snmp_mib_lrn_alloc(void); +void snmp_mib_lrn_free(struct mib_list_rootnode *lrn); + +s8_t snmp_mib_node_insert(struct mib_list_rootnode *rn, s32_t objid, struct mib_list_node **insn); +s8_t snmp_mib_node_find(struct mib_list_rootnode *rn, s32_t objid, struct mib_list_node **fn); +struct mib_list_rootnode *snmp_mib_node_delete(struct mib_list_rootnode *rn, struct mib_list_node *n); + +struct mib_node* snmp_search_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct snmp_name_ptr *np); +struct mib_node* snmp_expand_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct snmp_obj_id *oidret); +u8_t snmp_iso_prefix_tst(u8_t ident_len, s32_t *ident); +u8_t snmp_iso_prefix_expand(u8_t ident_len, s32_t *ident, struct snmp_obj_id *oidret); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SNMP */ + +#endif /* LWIP_HDR_SNMP_STRUCTS_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/sockets.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/sockets.h new file mode 100644 index 0000000..97897c8 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/sockets.h @@ -0,0 +1,482 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + + +#ifndef LWIP_HDR_SOCKETS_H +#define LWIP_HDR_SOCKETS_H + +#include "lwip/opt.h" + +#if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ + +#include /* for size_t */ + +#include "lwip/ip_addr.h" +#include "lwip/err.h" +#include "lwip/inet.h" +#include "lwip/inet6.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* If your port already typedef's sa_family_t, define SA_FAMILY_T_DEFINED + to prevent this code from redefining it. */ +#if !defined(sa_family_t) && !defined(SA_FAMILY_T_DEFINED) +typedef u8_t sa_family_t; +#endif +/* If your port already typedef's in_port_t, define IN_PORT_T_DEFINED + to prevent this code from redefining it. */ +#if !defined(in_port_t) && !defined(IN_PORT_T_DEFINED) +typedef u16_t in_port_t; +#endif + +/* members are in network byte order */ +struct sockaddr_in { + u8_t sin_len; + sa_family_t sin_family; + in_port_t sin_port; + struct in_addr sin_addr; +#define SIN_ZERO_LEN 8 + char sin_zero[SIN_ZERO_LEN]; +}; + +#if LWIP_IPV6 +struct sockaddr_in6 { + u8_t sin6_len; /* length of this structure */ + sa_family_t sin6_family; /* AF_INET6 */ + in_port_t sin6_port; /* Transport layer port # */ + u32_t sin6_flowinfo; /* IPv6 flow information */ + struct in6_addr sin6_addr; /* IPv6 address */ +}; +#endif /* LWIP_IPV6 */ + +struct sockaddr { + u8_t sa_len; + sa_family_t sa_family; +#if LWIP_IPV6 + char sa_data[22]; +#else /* LWIP_IPV6 */ + char sa_data[14]; +#endif /* LWIP_IPV6 */ +}; + +struct sockaddr_storage { + u8_t s2_len; + sa_family_t ss_family; + char s2_data1[2]; + u32_t s2_data2[3]; +#if LWIP_IPV6 + u32_t s2_data3[2]; +#endif /* LWIP_IPV6 */ +}; + +/* If your port already typedef's socklen_t, define SOCKLEN_T_DEFINED + to prevent this code from redefining it. */ +#if !defined(socklen_t) && !defined(SOCKLEN_T_DEFINED) +typedef u32_t socklen_t; +#endif + +struct lwip_sock; + +#if !LWIP_TCPIP_CORE_LOCKING +/** Maximum optlen used by setsockopt/getsockopt */ +#define LWIP_SETGETSOCKOPT_MAXOPTLEN 16 + +/** This struct is used to pass data to the set/getsockopt_internal + * functions running in tcpip_thread context (only a void* is allowed) */ +struct lwip_setgetsockopt_data { + /** socket index for which to change options */ + int s; + /** level of the option to process */ + int level; + /** name of the option to process */ + int optname; + /** set: value to set the option to + * get: value of the option is stored here */ +#if LWIP_MPU_COMPATIBLE + u8_t optval[LWIP_SETGETSOCKOPT_MAXOPTLEN]; +#else + void* optval; +#endif + /** size of *optval */ + socklen_t optlen; + /** if an error occurs, it is temporarily stored here */ + err_t err; + /** semaphore to wake up the calling task */ + void* completed_sem; +}; +#endif /* !LWIP_TCPIP_CORE_LOCKING */ + +/* Socket protocol types (TCP/UDP/RAW) */ +#define SOCK_STREAM 1 +#define SOCK_DGRAM 2 +#define SOCK_RAW 3 + +/* + * Option flags per-socket. These must match the SOF_ flags in ip.h (checked in init.c) + */ +#define SO_REUSEADDR 0x0004 /* Allow local address reuse */ +#define SO_KEEPALIVE 0x0008 /* keep connections alive */ +#define SO_BROADCAST 0x0020 /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */ + + +/* + * Additional options, not kept in so_options. + */ +#define SO_DEBUG 0x0001 /* Unimplemented: turn on debugging info recording */ +#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */ +#define SO_DONTROUTE 0x0010 /* Unimplemented: just use interface addresses */ +#define SO_USELOOPBACK 0x0040 /* Unimplemented: bypass hardware when possible */ +#define SO_LINGER 0x0080 /* linger on close if data present */ +#define SO_DONTLINGER ((int)(~SO_LINGER)) +#define SO_OOBINLINE 0x0100 /* Unimplemented: leave received OOB data in line */ +#define SO_REUSEPORT 0x0200 /* allow local address & port reuse */ +#define SO_SNDBUF 0x1001 /* Unimplemented: send buffer size */ +#define SO_RCVBUF 0x1002 /* receive buffer size */ +#define SO_SNDLOWAT 0x1003 /* Unimplemented: send low-water mark */ +#define SO_RCVLOWAT 0x1004 /* Unimplemented: receive low-water mark */ +#define SO_SNDTIMEO 0x1005 /* Unimplemented: send timeout */ +#define SO_RCVTIMEO 0x1006 /* receive timeout */ +#define SO_ERROR 0x1007 /* get error status and clear */ +#define SO_TYPE 0x1008 /* get socket type */ +#define SO_CONTIMEO 0x1009 /* Unimplemented: connect timeout */ +#define SO_NO_CHECK 0x100a /* don't create UDP checksum */ + + +/* + * Structure used for manipulating linger option. + */ +struct linger { + int l_onoff; /* option on/off */ + int l_linger; /* linger time */ +}; + +/* + * Level number for (get/set)sockopt() to apply to socket itself. + */ +#define SOL_SOCKET 0xfff /* options for socket level */ + + +#define AF_UNSPEC 0 +#define AF_INET 2 +#if LWIP_IPV6 +#define AF_INET6 10 +#else /* LWIP_IPV6 */ +#define AF_INET6 AF_UNSPEC +#endif /* LWIP_IPV6 */ +#define PF_INET AF_INET +#define PF_INET6 AF_INET6 +#define PF_UNSPEC AF_UNSPEC + +#define IPPROTO_IP 0 +#define IPPROTO_ICMP 1 +#define IPPROTO_TCP 6 +#define IPPROTO_UDP 17 +#if LWIP_IPV6 +#define IPPROTO_IPV6 41 +#define IPPROTO_ICMPV6 58 +#endif /* LWIP_IPV6 */ +#define IPPROTO_UDPLITE 136 +#define IPPROTO_RAW 255 + +/* Flags we can use with send and recv. */ +#define MSG_PEEK 0x01 /* Peeks at an incoming message */ +#define MSG_WAITALL 0x02 /* Unimplemented: Requests that the function block until the full amount of data requested can be returned */ +#define MSG_OOB 0x04 /* Unimplemented: Requests out-of-band data. The significance and semantics of out-of-band data are protocol-specific */ +#define MSG_DONTWAIT 0x08 /* Nonblocking i/o for this operation only */ +#define MSG_MORE 0x10 /* Sender will send more */ + + +/* + * Options for level IPPROTO_IP + */ +#define IP_TOS 1 +#define IP_TTL 2 + +#if LWIP_TCP +/* + * Options for level IPPROTO_TCP + */ +#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */ +#define TCP_KEEPALIVE 0x02 /* send KEEPALIVE probes when idle for pcb->keep_idle milliseconds */ +#define TCP_KEEPIDLE 0x03 /* set pcb->keep_idle - Same as TCP_KEEPALIVE, but use seconds for get/setsockopt */ +#define TCP_KEEPINTVL 0x04 /* set pcb->keep_intvl - Use seconds for get/setsockopt */ +#define TCP_KEEPCNT 0x05 /* set pcb->keep_cnt - Use number of probes sent for get/setsockopt */ +#endif /* LWIP_TCP */ + +#if LWIP_IPV6 +/* + * Options for level IPPROTO_IPV6 + */ +#define IPV6_CHECKSUM 7 /* RFC3542: calculate and insert the ICMPv6 checksum for raw sockets. */ +#define IPV6_V6ONLY 27 /* RFC3493: boolean control to restrict AF_INET6 sockets to IPv6 communications only. */ +#endif /* LWIP_IPV6 */ + +#if LWIP_UDP && LWIP_UDPLITE +/* + * Options for level IPPROTO_UDPLITE + */ +#define UDPLITE_SEND_CSCOV 0x01 /* sender checksum coverage */ +#define UDPLITE_RECV_CSCOV 0x02 /* minimal receiver checksum coverage */ +#endif /* LWIP_UDP && LWIP_UDPLITE*/ + + +#if LWIP_IGMP +/* + * Options and types for UDP multicast traffic handling + */ +#define IP_ADD_MEMBERSHIP 3 +#define IP_DROP_MEMBERSHIP 4 +#define IP_MULTICAST_TTL 5 +#define IP_MULTICAST_IF 6 +#define IP_MULTICAST_LOOP 7 + +typedef struct ip_mreq { + struct in_addr imr_multiaddr; /* IP multicast address of group */ + struct in_addr imr_interface; /* local IP address of interface */ +} ip_mreq; +#endif /* LWIP_IGMP */ + +/* + * The Type of Service provides an indication of the abstract + * parameters of the quality of service desired. These parameters are + * to be used to guide the selection of the actual service parameters + * when transmitting a datagram through a particular network. Several + * networks offer service precedence, which somehow treats high + * precedence traffic as more important than other traffic (generally + * by accepting only traffic above a certain precedence at time of high + * load). The major choice is a three way tradeoff between low-delay, + * high-reliability, and high-throughput. + * The use of the Delay, Throughput, and Reliability indications may + * increase the cost (in some sense) of the service. In many networks + * better performance for one of these parameters is coupled with worse + * performance on another. Except for very unusual cases at most two + * of these three indications should be set. + */ +#define IPTOS_TOS_MASK 0x1E +#define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK) +#define IPTOS_LOWDELAY 0x10 +#define IPTOS_THROUGHPUT 0x08 +#define IPTOS_RELIABILITY 0x04 +#define IPTOS_LOWCOST 0x02 +#define IPTOS_MINCOST IPTOS_LOWCOST + +/* + * The Network Control precedence designation is intended to be used + * within a network only. The actual use and control of that + * designation is up to each network. The Internetwork Control + * designation is intended for use by gateway control originators only. + * If the actual use of these precedence designations is of concern to + * a particular network, it is the responsibility of that network to + * control the access to, and use of, those precedence designations. + */ +#define IPTOS_PREC_MASK 0xe0 +#define IPTOS_PREC(tos) ((tos) & IPTOS_PREC_MASK) +#define IPTOS_PREC_NETCONTROL 0xe0 +#define IPTOS_PREC_INTERNETCONTROL 0xc0 +#define IPTOS_PREC_CRITIC_ECP 0xa0 +#define IPTOS_PREC_FLASHOVERRIDE 0x80 +#define IPTOS_PREC_FLASH 0x60 +#define IPTOS_PREC_IMMEDIATE 0x40 +#define IPTOS_PREC_PRIORITY 0x20 +#define IPTOS_PREC_ROUTINE 0x00 + + +/* + * Commands for ioctlsocket(), taken from the BSD file fcntl.h. + * lwip_ioctl only supports FIONREAD and FIONBIO, for now + * + * Ioctl's have the command encoded in the lower word, + * and the size of any in or out parameters in the upper + * word. The high 2 bits of the upper word are used + * to encode the in/out status of the parameter; for now + * we restrict parameters to at most 128 bytes. + */ +#if !defined(FIONREAD) || !defined(FIONBIO) +#define IOCPARM_MASK 0x7fU /* parameters must be < 128 bytes */ +#define IOC_VOID 0x20000000UL /* no parameters */ +#define IOC_OUT 0x40000000UL /* copy out parameters */ +#define IOC_IN 0x80000000UL /* copy in parameters */ +#define IOC_INOUT (IOC_IN|IOC_OUT) + /* 0x20000000 distinguishes new & + old ioctl's */ +#define _IO(x,y) (IOC_VOID|((x)<<8)|(y)) + +#define _IOR(x,y,t) (IOC_OUT|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) + +#define _IOW(x,y,t) (IOC_IN|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) +#endif /* !defined(FIONREAD) || !defined(FIONBIO) */ + +#ifndef FIONREAD +#define FIONREAD _IOR('f', 127, unsigned long) /* get # bytes to read */ +#endif +#ifndef FIONBIO +#define FIONBIO _IOW('f', 126, unsigned long) /* set/clear non-blocking i/o */ +#endif + +/* Socket I/O Controls: unimplemented */ +#ifndef SIOCSHIWAT +#define SIOCSHIWAT _IOW('s', 0, unsigned long) /* set high watermark */ +#define SIOCGHIWAT _IOR('s', 1, unsigned long) /* get high watermark */ +#define SIOCSLOWAT _IOW('s', 2, unsigned long) /* set low watermark */ +#define SIOCGLOWAT _IOR('s', 3, unsigned long) /* get low watermark */ +#define SIOCATMARK _IOR('s', 7, unsigned long) /* at oob mark? */ +#endif + +/* commands for fnctl */ +#ifndef F_GETFL +#define F_GETFL 3 +#endif +#ifndef F_SETFL +#define F_SETFL 4 +#endif + +/* File status flags and file access modes for fnctl, + these are bits in an int. */ +#ifndef O_NONBLOCK +#define O_NONBLOCK 1 /* nonblocking I/O */ +#endif +#ifndef O_NDELAY +#define O_NDELAY 1 /* same as O_NONBLOCK, for compatibility */ +#endif + +#ifndef SHUT_RD + #define SHUT_RD 0 + #define SHUT_WR 1 + #define SHUT_RDWR 2 +#endif + +/* FD_SET used for lwip_select */ +#ifndef FD_SET + #undef FD_SETSIZE + /* Make FD_SETSIZE match NUM_SOCKETS in socket.c */ + #define FD_SETSIZE MEMP_NUM_NETCONN + #define FD_SET(n, p) ((p)->fd_bits[(n)/8] |= (1 << ((n) & 7))) + #define FD_CLR(n, p) ((p)->fd_bits[(n)/8] &= ~(1 << ((n) & 7))) + #define FD_ISSET(n,p) ((p)->fd_bits[(n)/8] & (1 << ((n) & 7))) + #define FD_ZERO(p) memset((void*)(p),0,sizeof(*(p))) + + typedef struct fd_set { + unsigned char fd_bits [(FD_SETSIZE+7)/8]; + } fd_set; + +#endif /* FD_SET */ + +/** LWIP_TIMEVAL_PRIVATE: if you want to use the struct timeval provided + * by your system, set this to 0 and include in cc.h */ +#ifndef LWIP_TIMEVAL_PRIVATE +#define LWIP_TIMEVAL_PRIVATE 1 +#endif + +#if LWIP_TIMEVAL_PRIVATE +struct timeval { + long tv_sec; /* seconds */ + long tv_usec; /* and microseconds */ +}; +#endif /* LWIP_TIMEVAL_PRIVATE */ + +#define lwip_socket_init() /* Compatibility define, no init needed. */ + +int lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen); +int lwip_bind(int s, const struct sockaddr *name, socklen_t namelen); +int lwip_shutdown(int s, int how); +int lwip_getpeername (int s, struct sockaddr *name, socklen_t *namelen); +int lwip_getsockname (int s, struct sockaddr *name, socklen_t *namelen); +int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *optlen); +int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_t optlen); +int lwip_close(int s); +int lwip_connect(int s, const struct sockaddr *name, socklen_t namelen); +int lwip_listen(int s, int backlog); +int lwip_recv(int s, void *mem, size_t len, int flags); +int lwip_read(int s, void *mem, size_t len); +int lwip_recvfrom(int s, void *mem, size_t len, int flags, + struct sockaddr *from, socklen_t *fromlen); +int lwip_send(int s, const void *dataptr, size_t size, int flags); +int lwip_sendto(int s, const void *dataptr, size_t size, int flags, + const struct sockaddr *to, socklen_t tolen); +int lwip_socket(int domain, int type, int protocol); +int lwip_write(int s, const void *dataptr, size_t size); +int lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, + struct timeval *timeout); +int lwip_ioctl(int s, long cmd, void *argp); +int lwip_fcntl(int s, int cmd, int val); + +#if LWIP_COMPAT_SOCKETS +#define accept(a,b,c) lwip_accept(a,b,c) +#define bind(a,b,c) lwip_bind(a,b,c) +#define shutdown(a,b) lwip_shutdown(a,b) +#define closesocket(s) lwip_close(s) +#define connect(a,b,c) lwip_connect(a,b,c) +#define getsockname(a,b,c) lwip_getsockname(a,b,c) +#define getpeername(a,b,c) lwip_getpeername(a,b,c) +#define setsockopt(a,b,c,d,e) lwip_setsockopt(a,b,c,d,e) +#define getsockopt(a,b,c,d,e) lwip_getsockopt(a,b,c,d,e) +#define listen(a,b) lwip_listen(a,b) +#define recv(a,b,c,d) lwip_recv(a,b,c,d) +#define recvfrom(a,b,c,d,e,f) lwip_recvfrom(a,b,c,d,e,f) +#define send(a,b,c,d) lwip_send(a,b,c,d) +#define sendto(a,b,c,d,e,f) lwip_sendto(a,b,c,d,e,f) +#define socket(a,b,c) lwip_socket(a,b,c) +#define select(a,b,c,d,e) lwip_select(a,b,c,d,e) +#define ioctlsocket(a,b,c) lwip_ioctl(a,b,c) + +#if LWIP_POSIX_SOCKETS_IO_NAMES +#define read(a,b,c) lwip_read(a,b,c) +#define write(a,b,c) lwip_write(a,b,c) +#define close(s) lwip_close(s) +#define fcntl(a,b,c) lwip_fcntl(a,b,c) +#endif /* LWIP_POSIX_SOCKETS_IO_NAMES */ + +#if LWIP_IPV6 +#define inet_ntop(af,src,dst,size) \ + (((af) == AF_INET6) ? ip6addr_ntoa_r((src),(dst),(size)) \ + : (((af) == AF_INET) ? ipaddr_ntoa_r((src),(dst),(size)) : NULL)) +#define inet_pton(af,src,dst) \ + (((af) == AF_INET6) ? inet6_aton((src),(dst)) \ + : (((af) == AF_INET) ? inet_aton((src),(dst)) : 0)) +#else /* LWIP_IPV6 */ +#define inet_ntop(af,src,dst,size) \ + (((af) == AF_INET) ? ipaddr_ntoa_r((src),(dst),(size)) : NULL) +#define inet_pton(af,src,dst) \ + (((af) == AF_INET) ? inet_aton((src),(dst)) : 0) +#endif /* LWIP_IPV6 */ + +#endif /* LWIP_COMPAT_SOCKETS */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SOCKET */ + +#endif /* LWIP_HDR_SOCKETS_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/stats.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/stats.h new file mode 100644 index 0000000..6385318 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/stats.h @@ -0,0 +1,347 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_STATS_H +#define LWIP_HDR_STATS_H + +#include "lwip/opt.h" + +#include "lwip/mem.h" +#include "lwip/memp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_STATS + +#ifndef LWIP_STATS_LARGE +#define LWIP_STATS_LARGE 0 +#endif + +#if LWIP_STATS_LARGE +#define STAT_COUNTER u32_t +#define STAT_COUNTER_F U32_F +#else +#define STAT_COUNTER u16_t +#define STAT_COUNTER_F U16_F +#endif + +struct stats_proto { + STAT_COUNTER xmit; /* Transmitted packets. */ + STAT_COUNTER recv; /* Received packets. */ + STAT_COUNTER fw; /* Forwarded packets. */ + STAT_COUNTER drop; /* Dropped packets. */ + STAT_COUNTER chkerr; /* Checksum error. */ + STAT_COUNTER lenerr; /* Invalid length error. */ + STAT_COUNTER memerr; /* Out of memory error. */ + STAT_COUNTER rterr; /* Routing error. */ + STAT_COUNTER proterr; /* Protocol error. */ + STAT_COUNTER opterr; /* Error in options. */ + STAT_COUNTER err; /* Misc error. */ + STAT_COUNTER cachehit; +}; + +struct stats_igmp { + STAT_COUNTER xmit; /* Transmitted packets. */ + STAT_COUNTER recv; /* Received packets. */ + STAT_COUNTER drop; /* Dropped packets. */ + STAT_COUNTER chkerr; /* Checksum error. */ + STAT_COUNTER lenerr; /* Invalid length error. */ + STAT_COUNTER memerr; /* Out of memory error. */ + STAT_COUNTER proterr; /* Protocol error. */ + STAT_COUNTER rx_v1; /* Received v1 frames. */ + STAT_COUNTER rx_group; /* Received group-specific queries. */ + STAT_COUNTER rx_general; /* Received general queries. */ + STAT_COUNTER rx_report; /* Received reports. */ + STAT_COUNTER tx_join; /* Sent joins. */ + STAT_COUNTER tx_leave; /* Sent leaves. */ + STAT_COUNTER tx_report; /* Sent reports. */ +}; + +struct stats_mem { +#ifdef LWIP_DEBUG + const char *name; +#endif /* LWIP_DEBUG */ + STAT_COUNTER err; + mem_size_t avail; + mem_size_t used; + mem_size_t max; + STAT_COUNTER illegal; +}; + +struct stats_syselem { + STAT_COUNTER used; + STAT_COUNTER max; + STAT_COUNTER err; +}; + +struct stats_sys { + struct stats_syselem sem; + struct stats_syselem mutex; + struct stats_syselem mbox; +}; + +struct stats_ { +#if LINK_STATS + struct stats_proto link; +#endif +#if ETHARP_STATS + struct stats_proto etharp; +#endif +#if IPFRAG_STATS + struct stats_proto ip_frag; +#endif +#if IP_STATS + struct stats_proto ip; +#endif +#if ICMP_STATS + struct stats_proto icmp; +#endif +#if IGMP_STATS + struct stats_igmp igmp; +#endif +#if UDP_STATS + struct stats_proto udp; +#endif +#if TCP_STATS + struct stats_proto tcp; +#endif +#if MEM_STATS + struct stats_mem mem; +#endif +#if MEMP_STATS + struct stats_mem memp[MEMP_MAX]; +#endif +#if SYS_STATS + struct stats_sys sys; +#endif +#if IP6_STATS + struct stats_proto ip6; +#endif +#if ICMP6_STATS + struct stats_proto icmp6; +#endif +#if IP6_FRAG_STATS + struct stats_proto ip6_frag; +#endif +#if MLD6_STATS + struct stats_igmp mld6; +#endif +#if ND6_STATS + struct stats_proto nd6; +#endif +}; + +extern struct stats_ lwip_stats; + +void stats_init(void); + +#define STATS_INC(x) ++lwip_stats.x +#define STATS_DEC(x) --lwip_stats.x +#define STATS_INC_USED(x, y) do { lwip_stats.x.used += y; \ + if (lwip_stats.x.max < lwip_stats.x.used) { \ + lwip_stats.x.max = lwip_stats.x.used; \ + } \ + } while(0) +#else /* LWIP_STATS */ +#define stats_init() +#define STATS_INC(x) +#define STATS_DEC(x) +#define STATS_INC_USED(x) +#endif /* LWIP_STATS */ + +#if TCP_STATS +#define TCP_STATS_INC(x) STATS_INC(x) +#define TCP_STATS_DISPLAY() stats_display_proto(&lwip_stats.tcp, "TCP") +#else +#define TCP_STATS_INC(x) +#define TCP_STATS_DISPLAY() +#endif + +#if UDP_STATS +#define UDP_STATS_INC(x) STATS_INC(x) +#define UDP_STATS_DISPLAY() stats_display_proto(&lwip_stats.udp, "UDP") +#else +#define UDP_STATS_INC(x) +#define UDP_STATS_DISPLAY() +#endif + +#if ICMP_STATS +#define ICMP_STATS_INC(x) STATS_INC(x) +#define ICMP_STATS_DISPLAY() stats_display_proto(&lwip_stats.icmp, "ICMP") +#else +#define ICMP_STATS_INC(x) +#define ICMP_STATS_DISPLAY() +#endif + +#if IGMP_STATS +#define IGMP_STATS_INC(x) STATS_INC(x) +#define IGMP_STATS_DISPLAY() stats_display_igmp(&lwip_stats.igmp, "IGMP") +#else +#define IGMP_STATS_INC(x) +#define IGMP_STATS_DISPLAY() +#endif + +#if IP_STATS +#define IP_STATS_INC(x) STATS_INC(x) +#define IP_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip, "IP") +#else +#define IP_STATS_INC(x) +#define IP_STATS_DISPLAY() +#endif + +#if IPFRAG_STATS +#define IPFRAG_STATS_INC(x) STATS_INC(x) +#define IPFRAG_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip_frag, "IP_FRAG") +#else +#define IPFRAG_STATS_INC(x) +#define IPFRAG_STATS_DISPLAY() +#endif + +#if ETHARP_STATS +#define ETHARP_STATS_INC(x) STATS_INC(x) +#define ETHARP_STATS_DISPLAY() stats_display_proto(&lwip_stats.etharp, "ETHARP") +#else +#define ETHARP_STATS_INC(x) +#define ETHARP_STATS_DISPLAY() +#endif + +#if LINK_STATS +#define LINK_STATS_INC(x) STATS_INC(x) +#define LINK_STATS_DISPLAY() stats_display_proto(&lwip_stats.link, "LINK") +#else +#define LINK_STATS_INC(x) +#define LINK_STATS_DISPLAY() +#endif + +#if MEM_STATS +#define MEM_STATS_AVAIL(x, y) lwip_stats.mem.x = y +#define MEM_STATS_INC(x) STATS_INC(mem.x) +#define MEM_STATS_INC_USED(x, y) STATS_INC_USED(mem, y) +#define MEM_STATS_DEC_USED(x, y) lwip_stats.mem.x -= y +#define MEM_STATS_DISPLAY() stats_display_mem(&lwip_stats.mem, "HEAP") +#else +#define MEM_STATS_AVAIL(x, y) +#define MEM_STATS_INC(x) +#define MEM_STATS_INC_USED(x, y) +#define MEM_STATS_DEC_USED(x, y) +#define MEM_STATS_DISPLAY() +#endif + +#if MEMP_STATS +#define MEMP_STATS_AVAIL(x, i, y) lwip_stats.memp[i].x = y +#define MEMP_STATS_INC(x, i) STATS_INC(memp[i].x) +#define MEMP_STATS_DEC(x, i) STATS_DEC(memp[i].x) +#define MEMP_STATS_INC_USED(x, i) STATS_INC_USED(memp[i], 1) +#define MEMP_STATS_DISPLAY(i) stats_display_memp(&lwip_stats.memp[i], i) +#else +#define MEMP_STATS_AVAIL(x, i, y) +#define MEMP_STATS_INC(x, i) +#define MEMP_STATS_DEC(x, i) +#define MEMP_STATS_INC_USED(x, i) +#define MEMP_STATS_DISPLAY(i) +#endif + +#if SYS_STATS +#define SYS_STATS_INC(x) STATS_INC(sys.x) +#define SYS_STATS_DEC(x) STATS_DEC(sys.x) +#define SYS_STATS_INC_USED(x) STATS_INC_USED(sys.x, 1) +#define SYS_STATS_DISPLAY() stats_display_sys(&lwip_stats.sys) +#else +#define SYS_STATS_INC(x) +#define SYS_STATS_DEC(x) +#define SYS_STATS_INC_USED(x) +#define SYS_STATS_DISPLAY() +#endif + +#if IP6_STATS +#define IP6_STATS_INC(x) STATS_INC(x) +#define IP6_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip6, "IPv6") +#else +#define IP6_STATS_INC(x) +#define IP6_STATS_DISPLAY() +#endif + +#if ICMP6_STATS +#define ICMP6_STATS_INC(x) STATS_INC(x) +#define ICMP6_STATS_DISPLAY() stats_display_proto(&lwip_stats.icmp6, "ICMPv6") +#else +#define ICMP6_STATS_INC(x) +#define ICMP6_STATS_DISPLAY() +#endif + +#if IP6_FRAG_STATS +#define IP6_FRAG_STATS_INC(x) STATS_INC(x) +#define IP6_FRAG_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip6_frag, "IPv6 FRAG") +#else +#define IP6_FRAG_STATS_INC(x) +#define IP6_FRAG_STATS_DISPLAY() +#endif + +#if MLD6_STATS +#define MLD6_STATS_INC(x) STATS_INC(x) +#define MLD6_STATS_DISPLAY() stats_display_igmp(&lwip_stats.mld6, "MLDv1") +#else +#define MLD6_STATS_INC(x) +#define MLD6_STATS_DISPLAY() +#endif + +#if ND6_STATS +#define ND6_STATS_INC(x) STATS_INC(x) +#define ND6_STATS_DISPLAY() stats_display_proto(&lwip_stats.nd6, "ND") +#else +#define ND6_STATS_INC(x) +#define ND6_STATS_DISPLAY() +#endif + +/* Display of statistics */ +#if LWIP_STATS_DISPLAY +void stats_display(void); +void stats_display_proto(struct stats_proto *proto, const char *name); +void stats_display_igmp(struct stats_igmp *igmp, const char *name); +void stats_display_mem(struct stats_mem *mem, const char *name); +void stats_display_memp(struct stats_mem *mem, int index); +void stats_display_sys(struct stats_sys *sys); +#else /* LWIP_STATS_DISPLAY */ +#define stats_display() +#define stats_display_proto(proto, name) +#define stats_display_igmp(igmp, name) +#define stats_display_mem(mem, name) +#define stats_display_memp(mem, index) +#define stats_display_sys(sys) +#endif /* LWIP_STATS_DISPLAY */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_STATS_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/sys.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/sys.h new file mode 100644 index 0000000..868bbf1 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/sys.h @@ -0,0 +1,334 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_SYS_H +#define LWIP_HDR_SYS_H + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if NO_SYS + +/* For a totally minimal and standalone system, we provide null + definitions of the sys_ functions. */ +typedef u8_t sys_sem_t; +typedef u8_t sys_mutex_t; +typedef u8_t sys_mbox_t; + +#define sys_sem_new(s, c) ERR_OK +#define sys_sem_signal(s) +#define sys_sem_wait(s) +#define sys_arch_sem_wait(s,t) +#define sys_sem_free(s) +#define sys_sem_valid(s) 0 +#define sys_sem_set_invalid(s) +#define sys_mutex_new(mu) ERR_OK +#define sys_mutex_lock(mu) +#define sys_mutex_unlock(mu) +#define sys_mutex_free(mu) +#define sys_mutex_valid(mu) 0 +#define sys_mutex_set_invalid(mu) +#define sys_mbox_new(m, s) ERR_OK +#define sys_mbox_fetch(m,d) +#define sys_mbox_tryfetch(m,d) +#define sys_mbox_post(m,d) +#define sys_mbox_trypost(m,d) +#define sys_mbox_free(m) +#define sys_mbox_valid(m) +#define sys_mbox_set_invalid(m) + +#define sys_thread_new(n,t,a,s,p) + +#define sys_msleep(t) + +#else /* NO_SYS */ + +/** Return code for timeouts from sys_arch_mbox_fetch and sys_arch_sem_wait */ +#define SYS_ARCH_TIMEOUT 0xffffffffUL + +/** sys_mbox_tryfetch() returns SYS_MBOX_EMPTY if appropriate. + * For now we use the same magic value, but we allow this to change in future. + */ +#define SYS_MBOX_EMPTY SYS_ARCH_TIMEOUT + +#include "lwip/err.h" +#include "arch/sys_arch.h" + +/** Function prototype for thread functions */ +typedef void (*lwip_thread_fn)(void *arg); + +/* Function prototypes for functions to be implemented by platform ports + (in sys_arch.c) */ + +/** Define LWIP_COMPAT_MUTEX if the port has no mutexes and binary semaphores + should be used instead */ +#if LWIP_COMPAT_MUTEX +/* for old ports that don't have mutexes: define them to binary semaphores */ +#define sys_mutex_t sys_sem_t +#define sys_mutex_new(mutex) sys_sem_new(mutex, 1) +#define sys_mutex_lock(mutex) sys_sem_wait(mutex) +#define sys_mutex_unlock(mutex) sys_sem_signal(mutex) +#define sys_mutex_free(mutex) sys_sem_free(mutex) +#define sys_mutex_valid(mutex) sys_sem_valid(mutex) +#define sys_mutex_set_invalid(mutex) sys_sem_set_invalid(mutex) + +#else /* LWIP_COMPAT_MUTEX */ + +/** Create a new mutex + * @param mutex pointer to the mutex to create + * @return a new mutex */ +err_t sys_mutex_new(sys_mutex_t *mutex); +/** Lock a mutex + * @param mutex the mutex to lock */ +void sys_mutex_lock(sys_mutex_t *mutex); +/** Unlock a mutex + * @param mutex the mutex to unlock */ +void sys_mutex_unlock(sys_mutex_t *mutex); +/** Delete a semaphore + * @param mutex the mutex to delete */ +void sys_mutex_free(sys_mutex_t *mutex); +#ifndef sys_mutex_valid +/** Check if a mutex is valid/allocated: return 1 for valid, 0 for invalid */ +int sys_mutex_valid(sys_mutex_t *mutex); +#endif +#ifndef sys_mutex_set_invalid +/** Set a mutex invalid so that sys_mutex_valid returns 0 */ +void sys_mutex_set_invalid(sys_mutex_t *mutex); +#endif +#endif /* LWIP_COMPAT_MUTEX */ + +/* Semaphore functions: */ + +/** Create a new semaphore + * @param sem pointer to the semaphore to create + * @param count initial count of the semaphore + * @return ERR_OK if successful, another err_t otherwise */ +err_t sys_sem_new(sys_sem_t *sem, u8_t count); +/** Signals a semaphore + * @param sem the semaphore to signal */ +void sys_sem_signal(sys_sem_t *sem); +/** Wait for a semaphore for the specified timeout + * @param sem the semaphore to wait for + * @param timeout timeout in milliseconds to wait (0 = wait forever) + * @return time (in milliseconds) waited for the semaphore + * or SYS_ARCH_TIMEOUT on timeout */ +u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout); +/** Delete a semaphore + * @param sem semaphore to delete */ +void sys_sem_free(sys_sem_t *sem); +/** Wait for a semaphore - forever/no timeout */ +#define sys_sem_wait(sem) sys_arch_sem_wait(sem, 0) +#ifndef sys_sem_valid +/** Check if a semaphore is valid/allocated: return 1 for valid, 0 for invalid */ +int sys_sem_valid(sys_sem_t *sem); +#endif +#ifndef sys_sem_set_invalid +/** Set a semaphore invalid so that sys_sem_valid returns 0 */ +void sys_sem_set_invalid(sys_sem_t *sem); +#endif + +/* Time functions. */ +#ifndef sys_msleep +void sys_msleep(u32_t ms); /* only has a (close to) 1 jiffy resolution. */ +#endif + +/* Mailbox functions. */ + +/** Create a new mbox of specified size + * @param mbox pointer to the mbox to create + * @param size (minimum) number of messages in this mbox + * @return ERR_OK if successful, another err_t otherwise */ +err_t sys_mbox_new(sys_mbox_t *mbox, int size); +/** Post a message to an mbox - may not fail + * -> blocks if full, only used from tasks not from ISR + * @param mbox mbox to posts the message + * @param msg message to post (ATTENTION: can be NULL) */ +void sys_mbox_post(sys_mbox_t *mbox, void *msg); +/** Try to post a message to an mbox - may fail if full or ISR + * @param mbox mbox to posts the message + * @param msg message to post (ATTENTION: can be NULL) */ +err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg); +/** Wait for a new message to arrive in the mbox + * @param mbox mbox to get a message from + * @param msg pointer where the message is stored + * @param timeout maximum time (in milliseconds) to wait for a message (0 = wait forever) + * @return time (in milliseconds) waited for a message, may be 0 if not waited + or SYS_ARCH_TIMEOUT on timeout + * The returned time has to be accurate to prevent timer jitter! */ +u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout); +/* Allow port to override with a macro, e.g. special timeout for sys_arch_mbox_fetch() */ +#ifndef sys_arch_mbox_tryfetch +/** Wait for a new message to arrive in the mbox + * @param mbox mbox to get a message from + * @param msg pointer where the message is stored + * @return 0 (milliseconds) if a message has been received + * or SYS_MBOX_EMPTY if the mailbox is empty */ +u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg); +#endif +/** For now, we map straight to sys_arch implementation. */ +#define sys_mbox_tryfetch(mbox, msg) sys_arch_mbox_tryfetch(mbox, msg) +/** Delete an mbox + * @param mbox mbox to delete */ +void sys_mbox_free(sys_mbox_t *mbox); +#define sys_mbox_fetch(mbox, msg) sys_arch_mbox_fetch(mbox, msg, 0) +#ifndef sys_mbox_valid +/** Check if an mbox is valid/allocated: return 1 for valid, 0 for invalid */ +int sys_mbox_valid(sys_mbox_t *mbox); +#endif +#ifndef sys_mbox_set_invalid +/** Set an mbox invalid so that sys_mbox_valid returns 0 */ +void sys_mbox_set_invalid(sys_mbox_t *mbox); +#endif + +/** The only thread function: + * Creates a new thread + * @param name human-readable name for the thread (used for debugging purposes) + * @param thread thread-function + * @param arg parameter passed to 'thread' + * @param stacksize stack size in bytes for the new thread (may be ignored by ports) + * @param prio priority of the new thread (may be ignored by ports) */ +sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio); + +#endif /* NO_SYS */ + +/* sys_init() must be called before anything else. */ +void sys_init(void); + +#ifndef sys_jiffies +/** Ticks/jiffies since power up. */ +u32_t sys_jiffies(void); +#endif + +/** Returns the current time in milliseconds, + * may be the same as sys_jiffies or at least based on it. */ +u32_t sys_now(void); + +/* Critical Region Protection */ +/* These functions must be implemented in the sys_arch.c file. + In some implementations they can provide a more light-weight protection + mechanism than using semaphores. Otherwise semaphores can be used for + implementation */ +#ifndef SYS_ARCH_PROTECT +/** SYS_LIGHTWEIGHT_PROT + * define SYS_LIGHTWEIGHT_PROT in lwipopts.h if you want inter-task protection + * for certain critical regions during buffer allocation, deallocation and memory + * allocation and deallocation. + */ +#if SYS_LIGHTWEIGHT_PROT + +/** SYS_ARCH_DECL_PROTECT + * declare a protection variable. This macro will default to defining a variable of + * type sys_prot_t. If a particular port needs a different implementation, then + * this macro may be defined in sys_arch.h. + */ +#define SYS_ARCH_DECL_PROTECT(lev) sys_prot_t lev +/** SYS_ARCH_PROTECT + * Perform a "fast" protect. This could be implemented by + * disabling interrupts for an embedded system or by using a semaphore or + * mutex. The implementation should allow calling SYS_ARCH_PROTECT when + * already protected. The old protection level is returned in the variable + * "lev". This macro will default to calling the sys_arch_protect() function + * which should be implemented in sys_arch.c. If a particular port needs a + * different implementation, then this macro may be defined in sys_arch.h + */ +#define SYS_ARCH_PROTECT(lev) lev = sys_arch_protect() +/** SYS_ARCH_UNPROTECT + * Perform a "fast" set of the protection level to "lev". This could be + * implemented by setting the interrupt level to "lev" within the MACRO or by + * using a semaphore or mutex. This macro will default to calling the + * sys_arch_unprotect() function which should be implemented in + * sys_arch.c. If a particular port needs a different implementation, then + * this macro may be defined in sys_arch.h + */ +#define SYS_ARCH_UNPROTECT(lev) sys_arch_unprotect(lev) +sys_prot_t sys_arch_protect(void); +void sys_arch_unprotect(sys_prot_t pval); + +#else + +#define SYS_ARCH_DECL_PROTECT(lev) +#define SYS_ARCH_PROTECT(lev) +#define SYS_ARCH_UNPROTECT(lev) + +#endif /* SYS_LIGHTWEIGHT_PROT */ + +#endif /* SYS_ARCH_PROTECT */ + +/* + * Macros to set/get and increase/decrease variables in a thread-safe way. + * Use these for accessing variable that are used from more than one thread. + */ + +#ifndef SYS_ARCH_INC +#define SYS_ARCH_INC(var, val) do { \ + SYS_ARCH_DECL_PROTECT(old_level); \ + SYS_ARCH_PROTECT(old_level); \ + var += val; \ + SYS_ARCH_UNPROTECT(old_level); \ + } while(0) +#endif /* SYS_ARCH_INC */ + +#ifndef SYS_ARCH_DEC +#define SYS_ARCH_DEC(var, val) do { \ + SYS_ARCH_DECL_PROTECT(old_level); \ + SYS_ARCH_PROTECT(old_level); \ + var -= val; \ + SYS_ARCH_UNPROTECT(old_level); \ + } while(0) +#endif /* SYS_ARCH_DEC */ + +#ifndef SYS_ARCH_GET +#define SYS_ARCH_GET(var, ret) do { \ + SYS_ARCH_DECL_PROTECT(old_level); \ + SYS_ARCH_PROTECT(old_level); \ + ret = var; \ + SYS_ARCH_UNPROTECT(old_level); \ + } while(0) +#endif /* SYS_ARCH_GET */ + +#ifndef SYS_ARCH_SET +#define SYS_ARCH_SET(var, val) do { \ + SYS_ARCH_DECL_PROTECT(old_level); \ + SYS_ARCH_PROTECT(old_level); \ + var = val; \ + SYS_ARCH_UNPROTECT(old_level); \ + } while(0) +#endif /* SYS_ARCH_SET */ + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_SYS_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/tcp.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/tcp.h new file mode 100644 index 0000000..4a9bb30 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/tcp.h @@ -0,0 +1,421 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_TCP_H +#define LWIP_HDR_TCP_H + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ +#include "lwip/sys.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/lwip_ip.h" +#include "lwip/icmp.h" +#include "lwip/err.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct tcp_pcb; + +//Realtek add +extern struct tcp_pcb *tcp_tw_pcbs; /* List of all TCP PCBs in TIME-WAIT. */ +//Realtek add end + +/** Function prototype for tcp accept callback functions. Called when a new + * connection can be accepted on a listening pcb. + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param newpcb The new connection pcb + * @param err An error code if there has been an error accepting. + * Only return ERR_ABRT if you have called tcp_abort from within the + * callback function! + */ +typedef err_t (*tcp_accept_fn)(void *arg, struct tcp_pcb *newpcb, err_t err); + +/** Function prototype for tcp receive callback functions. Called when data has + * been received. + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param tpcb The connection pcb which received data + * @param p The received data (or NULL when the connection has been closed!) + * @param err An error code if there has been an error receiving + * Only return ERR_ABRT if you have called tcp_abort from within the + * callback function! + */ +typedef err_t (*tcp_recv_fn)(void *arg, struct tcp_pcb *tpcb, + struct pbuf *p, err_t err); + +/** Function prototype for tcp sent callback functions. Called when sent data has + * been acknowledged by the remote side. Use it to free corresponding resources. + * This also means that the pcb has now space available to send new data. + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param tpcb The connection pcb for which data has been acknowledged + * @param len The amount of bytes acknowledged + * @return ERR_OK: try to send some data by calling tcp_output + * Only return ERR_ABRT if you have called tcp_abort from within the + * callback function! + */ +typedef err_t (*tcp_sent_fn)(void *arg, struct tcp_pcb *tpcb, + u16_t len); + +/** Function prototype for tcp poll callback functions. Called periodically as + * specified by @see tcp_poll. + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param tpcb tcp pcb + * @return ERR_OK: try to send some data by calling tcp_output + * Only return ERR_ABRT if you have called tcp_abort from within the + * callback function! + */ +typedef err_t (*tcp_poll_fn)(void *arg, struct tcp_pcb *tpcb); + +/** Function prototype for tcp error callback functions. Called when the pcb + * receives a RST or is unexpectedly closed for any other reason. + * + * @note The corresponding pcb is already freed when this callback is called! + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param err Error code to indicate why the pcb has been closed + * ERR_ABRT: aborted through tcp_abort or by a TCP timer + * ERR_RST: the connection was reset by the remote host + */ +typedef void (*tcp_err_fn)(void *arg, err_t err); + +/** Function prototype for tcp connected callback functions. Called when a pcb + * is connected to the remote side after initiating a connection attempt by + * calling tcp_connect(). + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param tpcb The connection pcb which is connected + * @param err An unused error code, always ERR_OK currently ;-) TODO! + * Only return ERR_ABRT if you have called tcp_abort from within the + * callback function! + * + * @note When a connection attempt fails, the error callback is currently called! + */ +typedef err_t (*tcp_connected_fn)(void *arg, struct tcp_pcb *tpcb, err_t err); + +#if LWIP_WND_SCALE +#define RCV_WND_SCALE(pcb, wnd) (((wnd) >> (pcb)->rcv_scale)) +#define SND_WND_SCALE(pcb, wnd) (((wnd) << (pcb)->snd_scale)) +typedef u32_t tcpwnd_size_t; +typedef u16_t tcpflags_t; +#else +#define RCV_WND_SCALE(pcb, wnd) (wnd) +#define SND_WND_SCALE(pcb, wnd) (wnd) +typedef u16_t tcpwnd_size_t; +typedef u8_t tcpflags_t; +#endif + +enum tcp_state { + CLOSED = 0, + LISTEN = 1, + SYN_SENT = 2, + SYN_RCVD = 3, + ESTABLISHED = 4, + FIN_WAIT_1 = 5, + FIN_WAIT_2 = 6, + CLOSE_WAIT = 7, + CLOSING = 8, + LAST_ACK = 9, + TIME_WAIT = 10 +}; + +#if LWIP_CALLBACK_API + /* Function to call when a listener has been connected. + * @param arg user-supplied argument (tcp_pcb.callback_arg) + * @param pcb a new tcp_pcb that now is connected + * @param err an error argument (TODO: that is current always ERR_OK?) + * @return ERR_OK: accept the new connection, + * any other err_t aborts the new connection + */ +#define DEF_ACCEPT_CALLBACK tcp_accept_fn accept; +#else /* LWIP_CALLBACK_API */ +#define DEF_ACCEPT_CALLBACK +#endif /* LWIP_CALLBACK_API */ + +/** + * members common to struct tcp_pcb and struct tcp_listen_pcb + */ +#define TCP_PCB_COMMON(type) \ + type *next; /* for the linked list */ \ + void *callback_arg; \ + /* the accept callback for listen- and normal pcbs, if LWIP_CALLBACK_API */ \ + DEF_ACCEPT_CALLBACK \ + enum tcp_state state; /* TCP state */ \ + u8_t prio; \ + /* ports are in host byte order */ \ + u16_t local_port + + +/* the TCP protocol control block */ +struct tcp_pcb { +/** common PCB members */ + IP_PCB; +/** protocol specific PCB members */ + TCP_PCB_COMMON(struct tcp_pcb); + + /* ports are in host byte order */ + u16_t remote_port; + + tcpflags_t flags; +#define TF_ACK_DELAY ((tcpflags_t)0x0001U) /* Delayed ACK. */ +#define TF_ACK_NOW ((tcpflags_t)0x0002U) /* Immediate ACK. */ +#define TF_INFR ((tcpflags_t)0x0004U) /* In fast recovery. */ +#define TF_TIMESTAMP ((tcpflags_t)0x0008U) /* Timestamp option enabled */ +#define TF_RXCLOSED ((tcpflags_t)0x0010U) /* rx closed by tcp_shutdown */ +#define TF_FIN ((tcpflags_t)0x0020U) /* Connection was closed locally (FIN segment enqueued). */ +#define TF_NODELAY ((tcpflags_t)0x0040U) /* Disable Nagle algorithm */ +#define TF_NAGLEMEMERR ((tcpflags_t)0x0080U) /* nagle enabled, memerr, try to output to prevent delayed ACK to happen */ +#if LWIP_WND_SCALE +#define TF_WND_SCALE ((tcpflags_t)0x0100U) /* Window Scale option enabled */ +#endif + + /* the rest of the fields are in host byte order + as we have to do some math with them */ + + /* Timers */ + u8_t polltmr, pollinterval; + u8_t last_timer; + u32_t tmr; + + /* receiver variables */ + u32_t rcv_nxt; /* next seqno expected */ + tcpwnd_size_t rcv_wnd; /* receiver window available */ + tcpwnd_size_t rcv_ann_wnd; /* receiver window to announce */ + u32_t rcv_ann_right_edge; /* announced right edge of window */ + + /* Retransmission timer. */ + s16_t rtime; + + u16_t mss; /* maximum segment size */ + + /* RTT (round trip time) estimation variables */ + u32_t rttest; /* RTT estimate in 500ms ticks */ + u32_t rtseq; /* sequence number being timed */ + s16_t sa, sv; /* @todo document this */ + + s16_t rto; /* retransmission time-out */ + u8_t nrtx; /* number of retransmissions */ + + /* fast retransmit/recovery */ + u8_t dupacks; + u32_t lastack; /* Highest acknowledged seqno. */ + + /* congestion avoidance/control variables */ + tcpwnd_size_t cwnd; + tcpwnd_size_t ssthresh; + + /* sender variables */ + u32_t snd_nxt; /* next new seqno to be sent */ + u32_t snd_wl1, snd_wl2; /* Sequence and acknowledgement numbers of last + window update. */ + u32_t snd_lbb; /* Sequence number of next byte to be buffered. */ + tcpwnd_size_t snd_wnd; /* sender window */ + tcpwnd_size_t snd_wnd_max; /* the maximum sender window announced by the remote host */ + + tcpwnd_size_t acked; + + tcpwnd_size_t snd_buf; /* Available buffer space for sending (in bytes). */ +#define TCP_SNDQUEUELEN_OVERFLOW (0xffffU-3) + u16_t snd_queuelen; /* Available buffer space for sending (in pbufs). */ + +#if TCP_OVERSIZE + /* Extra bytes available at the end of the last pbuf in unsent. */ + u16_t unsent_oversize; +#endif /* TCP_OVERSIZE */ + + /* These are ordered by sequence number: */ + struct tcp_seg *unsent; /* Unsent (queued) segments. */ + struct tcp_seg *unacked; /* Sent but unacknowledged segments. */ +#if TCP_QUEUE_OOSEQ + struct tcp_seg *ooseq; /* Received out of sequence segments. */ +#endif /* TCP_QUEUE_OOSEQ */ + + struct pbuf *refused_data; /* Data previously received but not yet taken by upper layer */ + +#if LWIP_CALLBACK_API + /* Function to be called when more send buffer space is available. */ + tcp_sent_fn sent; + /* Function to be called when (in-sequence) data has arrived. */ + tcp_recv_fn recv; + /* Function to be called when a connection has been set up. */ + tcp_connected_fn connected; + /* Function which is called periodically. */ + tcp_poll_fn poll; + /* Function to be called whenever a fatal error occurs. */ + tcp_err_fn errf; +#endif /* LWIP_CALLBACK_API */ + +#if LWIP_TCP_TIMESTAMPS + u32_t ts_lastacksent; + u32_t ts_recent; +#endif /* LWIP_TCP_TIMESTAMPS */ + + /* idle time before KEEPALIVE is sent */ + u32_t keep_idle; +#if LWIP_TCP_KEEPALIVE + u32_t keep_intvl; + u32_t keep_cnt; +#endif /* LWIP_TCP_KEEPALIVE */ + + /* Persist timer counter */ + u8_t persist_cnt; + /* Persist timer back-off */ + u8_t persist_backoff; + + /* KEEPALIVE counter */ + u8_t keep_cnt_sent; + +#if LWIP_WND_SCALE + u8_t snd_scale; + u8_t rcv_scale; +#endif +}; + +struct tcp_pcb_listen { +/* Common members of all PCB types */ + IP_PCB; +/* Protocol specific PCB members */ + TCP_PCB_COMMON(struct tcp_pcb_listen); + +#if TCP_LISTEN_BACKLOG + u8_t backlog; + u8_t accepts_pending; +#endif /* TCP_LISTEN_BACKLOG */ +#if LWIP_IPV6 + u8_t accept_any_ip_version; +#endif /* LWIP_IPV6 */ +}; + +#if LWIP_EVENT_API + +enum lwip_event { + LWIP_EVENT_ACCEPT, + LWIP_EVENT_SENT, + LWIP_EVENT_RECV, + LWIP_EVENT_CONNECTED, + LWIP_EVENT_POLL, + LWIP_EVENT_ERR +}; + +err_t lwip_tcp_event(void *arg, struct tcp_pcb *pcb, + enum lwip_event, + struct pbuf *p, + u16_t size, + err_t err); + +#endif /* LWIP_EVENT_API */ + +/* Application program's interface: */ +struct tcp_pcb * tcp_new (void); + +void tcp_arg (struct tcp_pcb *pcb, void *arg); +void tcp_accept (struct tcp_pcb *pcb, tcp_accept_fn accept); +void tcp_recv (struct tcp_pcb *pcb, tcp_recv_fn recv); +void tcp_sent (struct tcp_pcb *pcb, tcp_sent_fn sent); +void tcp_poll (struct tcp_pcb *pcb, tcp_poll_fn poll, u8_t interval); +void tcp_err (struct tcp_pcb *pcb, tcp_err_fn err); + +#define tcp_mss(pcb) (((pcb)->flags & TF_TIMESTAMP) ? ((pcb)->mss - 12) : (pcb)->mss) +#define tcp_sndbuf(pcb) ((pcb)->snd_buf) +#define tcp_sndqueuelen(pcb) ((pcb)->snd_queuelen) +#define tcp_nagle_disable(pcb) ((pcb)->flags |= TF_NODELAY) +#define tcp_nagle_enable(pcb) ((pcb)->flags &= (tcpflags_t)~TF_NODELAY) +#define tcp_nagle_disabled(pcb) (((pcb)->flags & TF_NODELAY) != 0) + +#if TCP_LISTEN_BACKLOG +#define tcp_accepted(pcb) do { \ + LWIP_ASSERT("pcb->state == LISTEN (called for wrong pcb?)", pcb->state == LISTEN); \ + (((struct tcp_pcb_listen *)(pcb))->accepts_pending--); } while(0) +#else /* TCP_LISTEN_BACKLOG */ +#define tcp_accepted(pcb) LWIP_ASSERT("pcb->state == LISTEN (called for wrong pcb?)", \ + (pcb)->state == LISTEN) +#endif /* TCP_LISTEN_BACKLOG */ + +void tcp_recved (struct tcp_pcb *pcb, u16_t len); +err_t tcp_bind (struct tcp_pcb *pcb, ip_addr_t *ipaddr, + u16_t port); +err_t tcp_connect (struct tcp_pcb *pcb, ip_addr_t *ipaddr, + u16_t port, tcp_connected_fn connected); + +struct tcp_pcb * tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog); +#define tcp_listen(pcb) tcp_listen_with_backlog(pcb, TCP_DEFAULT_LISTEN_BACKLOG) + +void tcp_abort (struct tcp_pcb *pcb); +err_t tcp_close (struct tcp_pcb *pcb); +err_t tcp_shutdown(struct tcp_pcb *pcb, int shut_rx, int shut_tx); + +/* Flags for "apiflags" parameter in tcp_write */ +#define TCP_WRITE_FLAG_COPY 0x01 +#define TCP_WRITE_FLAG_MORE 0x02 + +err_t tcp_write (struct tcp_pcb *pcb, const void *dataptr, u16_t len, + u8_t apiflags); + +void tcp_setprio (struct tcp_pcb *pcb, u8_t prio); + +#define TCP_PRIO_MIN 1 +#define TCP_PRIO_NORMAL 64 +#define TCP_PRIO_MAX 127 + +err_t tcp_output (struct tcp_pcb *pcb); + + +const char* tcp_debug_state_str(enum tcp_state s); + +#if LWIP_IPV6 +struct tcp_pcb * tcp_new_ip6 (void); +#define tcp_bind_ip6(pcb, ip6addr, port) \ + tcp_bind(pcb, ip6_2_ip(ip6addr), port) +#define tcp_connect_ip6(pcb, ip6addr, port, connected) \ + tcp_connect(pcb, ip6_2_ip(ip6addr), port, connected) +struct tcp_pcb * tcp_listen_dual_with_backlog(struct tcp_pcb *pcb, u8_t backlog); +#define tcp_listen_dual(pcb) tcp_listen_dual_with_backlog(pcb, TCP_DEFAULT_LISTEN_BACKLOG) +#else /* LWIP_IPV6 */ +#define tcp_listen_dual_with_backlog(pcb, backlog) tcp_listen_with_backlog(pcb, backlog) +#define tcp_listen_dual(pcb) tcp_listen(pcb) +#endif /* LWIP_IPV6 */ + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_TCP */ + +#endif /* LWIP_HDR_TCP_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/tcp_impl.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/tcp_impl.h new file mode 100644 index 0000000..ac1a716 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/tcp_impl.h @@ -0,0 +1,538 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_TCP_IMPL_H +#define LWIP_HDR_TCP_IMPL_H + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/tcp.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/lwip_ip.h" +#include "lwip/icmp.h" +#include "lwip/err.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Functions for interfacing with TCP: */ + +/* Lower layer interface to TCP: */ +void tcp_init (void); /* Initialize this module. */ +void tcp_tmr (void); /* Must be called every + TCP_TMR_INTERVAL + ms. (Typically 250 ms). */ +/* It is also possible to call these two functions at the right + intervals (instead of calling tcp_tmr()). */ +void tcp_slowtmr (void); +void tcp_fasttmr (void); + + +/* Only used by IP to pass a TCP segment to TCP: */ +void tcp_input (struct pbuf *p, struct netif *inp); +/* Used within the TCP code only: */ +struct tcp_pcb * tcp_alloc (u8_t prio); +void tcp_abandon (struct tcp_pcb *pcb, int reset); +err_t tcp_send_empty_ack(struct tcp_pcb *pcb); +void tcp_rexmit (struct tcp_pcb *pcb); +void tcp_rexmit_rto (struct tcp_pcb *pcb); +void tcp_rexmit_fast (struct tcp_pcb *pcb); +u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb); +err_t tcp_process_refused_data(struct tcp_pcb *pcb); + +/** + * This is the Nagle algorithm: try to combine user data to send as few TCP + * segments as possible. Only send if + * - no previously transmitted data on the connection remains unacknowledged or + * - the TF_NODELAY flag is set (nagle algorithm turned off for this pcb) or + * - the only unsent segment is at least pcb->mss bytes long (or there is more + * than one unsent segment - with lwIP, this can happen although unsent->len < mss) + * - or if we are in fast-retransmit (TF_INFR) + */ +#define tcp_do_output_nagle(tpcb) ((((tpcb)->unacked == NULL) || \ + ((tpcb)->flags & (TF_NODELAY | TF_INFR)) || \ + (((tpcb)->unsent != NULL) && (((tpcb)->unsent->next != NULL) || \ + ((tpcb)->unsent->len >= (tpcb)->mss))) || \ + ((tcp_sndbuf(tpcb) == 0) || (tcp_sndqueuelen(tpcb) >= TCP_SND_QUEUELEN)) \ + ) ? 1 : 0) +#define tcp_output_nagle(tpcb) (tcp_do_output_nagle(tpcb) ? tcp_output(tpcb) : ERR_OK) + + +#define TCP_SEQ_LT(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) < 0) +#define TCP_SEQ_LEQ(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) <= 0) +#define TCP_SEQ_GT(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) > 0) +#define TCP_SEQ_GEQ(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) >= 0) +/* is b<=a<=c? */ +#if 0 /* see bug #10548 */ +#define TCP_SEQ_BETWEEN(a,b,c) ((c)-(b) >= (a)-(b)) +#endif +#define TCP_SEQ_BETWEEN(a,b,c) (TCP_SEQ_GEQ(a,b) && TCP_SEQ_LEQ(a,c)) +#define TCP_FIN 0x01U +#define TCP_SYN 0x02U +#define TCP_RST 0x04U +#define TCP_PSH 0x08U +#define TCP_ACK 0x10U +#define TCP_URG 0x20U +#define TCP_ECE 0x40U +#define TCP_CWR 0x80U + +#define TCP_FLAGS 0x3fU + +/* Length of the TCP header, excluding options. */ +#define TCP_HLEN 20 + +#ifndef TCP_TMR_INTERVAL +#define TCP_TMR_INTERVAL 250 /* The TCP timer interval in milliseconds. */ +#endif /* TCP_TMR_INTERVAL */ + +#ifndef TCP_FAST_INTERVAL +#define TCP_FAST_INTERVAL TCP_TMR_INTERVAL /* the fine grained timeout in milliseconds */ +#endif /* TCP_FAST_INTERVAL */ + +#ifndef TCP_SLOW_INTERVAL +#define TCP_SLOW_INTERVAL (2*TCP_TMR_INTERVAL) /* the coarse grained timeout in milliseconds */ +#endif /* TCP_SLOW_INTERVAL */ + +#define TCP_FIN_WAIT_TIMEOUT 20000 /* milliseconds */ +#define TCP_SYN_RCVD_TIMEOUT 20000 /* milliseconds */ + +#define TCP_OOSEQ_TIMEOUT 6U /* x RTO */ + +#ifndef TCP_MSL +#define TCP_MSL 60000UL /* The maximum segment lifetime in milliseconds */ +#endif + +/* Keepalive values, compliant with RFC 1122. Don't change this unless you know what you're doing */ +#ifndef TCP_KEEPIDLE_DEFAULT +#define TCP_KEEPIDLE_DEFAULT 7200000UL /* Default KEEPALIVE timer in milliseconds */ +#endif + +#ifndef TCP_KEEPINTVL_DEFAULT +#define TCP_KEEPINTVL_DEFAULT 75000UL /* Default Time between KEEPALIVE probes in milliseconds */ +#endif + +#ifndef TCP_KEEPCNT_DEFAULT +#define TCP_KEEPCNT_DEFAULT 9U /* Default Counter for KEEPALIVE probes */ +#endif + +#define TCP_MAXIDLE TCP_KEEPCNT_DEFAULT * TCP_KEEPINTVL_DEFAULT /* Maximum KEEPALIVE probe time */ + +/* Fields are (of course) in network byte order. + * Some fields are converted to host byte order in tcp_input(). + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct tcp_hdr { + PACK_STRUCT_FIELD(u16_t src); + PACK_STRUCT_FIELD(u16_t dest); + PACK_STRUCT_FIELD(u32_t seqno); + PACK_STRUCT_FIELD(u32_t ackno); + PACK_STRUCT_FIELD(u16_t _hdrlen_rsvd_flags); + PACK_STRUCT_FIELD(u16_t wnd); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u16_t urgp); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define TCPH_HDRLEN(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 12) +#define TCPH_FLAGS(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) & TCP_FLAGS) + +#define TCPH_HDRLEN_SET(phdr, len) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | TCPH_FLAGS(phdr)) +#define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = (((phdr)->_hdrlen_rsvd_flags & PP_HTONS((u16_t)(~(u16_t)(TCP_FLAGS)))) | htons(flags)) +#define TCPH_HDRLEN_FLAGS_SET(phdr, len, flags) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | (flags)) + +#define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags | htons(flags)) +#define TCPH_UNSET_FLAG(phdr, flags) (phdr)->_hdrlen_rsvd_flags = htons(ntohs((phdr)->_hdrlen_rsvd_flags) | (TCPH_FLAGS(phdr) & ~(flags)) ) + +#define TCP_TCPLEN(seg) ((seg)->len + (((TCPH_FLAGS((seg)->tcphdr) & (TCP_FIN | TCP_SYN)) != 0) ? 1U : 0U)) + +/** Flags used on input processing, not on pcb->flags +*/ +#define TF_RESET (u8_t)0x08U /* Connection was reset. */ +#define TF_CLOSED (u8_t)0x10U /* Connection was successfully closed. */ +#define TF_GOT_FIN (u8_t)0x20U /* Connection was closed by the remote end. */ + + +#if LWIP_EVENT_API + +#define TCP_EVENT_ACCEPT(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_ACCEPT, NULL, 0, err) +#define TCP_EVENT_SENT(pcb,space,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_SENT, NULL, space, ERR_OK) +#define TCP_EVENT_RECV(pcb,p,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_RECV, (p), 0, (err)) +#define TCP_EVENT_CLOSED(pcb,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_RECV, NULL, 0, ERR_OK) +#define TCP_EVENT_CONNECTED(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_CONNECTED, NULL, 0, (err)) +#define TCP_EVENT_POLL(pcb,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_POLL, NULL, 0, ERR_OK) +#define TCP_EVENT_ERR(errf,arg,err) lwip_tcp_event((arg), NULL, \ + LWIP_EVENT_ERR, NULL, 0, (err)) + +#else /* LWIP_EVENT_API */ + +#define TCP_EVENT_ACCEPT(pcb,err,ret) \ + do { \ + if((pcb)->accept != NULL) \ + (ret) = (pcb)->accept((pcb)->callback_arg,(pcb),(err)); \ + else (ret) = ERR_ARG; \ + } while (0) + +#define TCP_EVENT_SENT(pcb,space,ret) \ + do { \ + if((pcb)->sent != NULL) \ + (ret) = (pcb)->sent((pcb)->callback_arg,(pcb),(space)); \ + else (ret) = ERR_OK; \ + } while (0) + +#define TCP_EVENT_RECV(pcb,p,err,ret) \ + do { \ + if((pcb)->recv != NULL) { \ + (ret) = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err));\ + } else { \ + (ret) = tcp_recv_null(NULL, (pcb), (p), (err)); \ + } \ + } while (0) + +#define TCP_EVENT_CLOSED(pcb,ret) \ + do { \ + if(((pcb)->recv != NULL)) { \ + (ret) = (pcb)->recv((pcb)->callback_arg,(pcb),NULL,ERR_OK);\ + } else { \ + (ret) = ERR_OK; \ + } \ + } while (0) + +#define TCP_EVENT_CONNECTED(pcb,err,ret) \ + do { \ + if((pcb)->connected != NULL) \ + (ret) = (pcb)->connected((pcb)->callback_arg,(pcb),(err)); \ + else (ret) = ERR_OK; \ + } while (0) + +#define TCP_EVENT_POLL(pcb,ret) \ + do { \ + if((pcb)->poll != NULL) \ + (ret) = (pcb)->poll((pcb)->callback_arg,(pcb)); \ + else (ret) = ERR_OK; \ + } while (0) + +#define TCP_EVENT_ERR(errf,arg,err) \ + do { \ + if((errf) != NULL) \ + (errf)((arg),(err)); \ + } while (0) + +#endif /* LWIP_EVENT_API */ + +/** Enabled extra-check for TCP_OVERSIZE if LWIP_DEBUG is enabled */ +#if TCP_OVERSIZE && defined(LWIP_DEBUG) +#define TCP_OVERSIZE_DBGCHECK 1 +#else +#define TCP_OVERSIZE_DBGCHECK 0 +#endif + +/** Don't generate checksum on copy if CHECKSUM_GEN_TCP is disabled */ +#define TCP_CHECKSUM_ON_COPY (LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_TCP) + +/* This structure represents a TCP segment on the unsent, unacked and ooseq queues */ +struct tcp_seg { + struct tcp_seg *next; /* used when putting segments on a queue */ + struct pbuf *p; /* buffer containing data + TCP header */ + u16_t len; /* the TCP length of this segment */ +#if TCP_OVERSIZE_DBGCHECK + u16_t oversize_left; /* Extra bytes available at the end of the last + pbuf in unsent (used for asserting vs. + tcp_pcb.unsent_oversized only) */ +#endif /* TCP_OVERSIZE_DBGCHECK */ +#if TCP_CHECKSUM_ON_COPY + u16_t chksum; + u8_t chksum_swapped; +#endif /* TCP_CHECKSUM_ON_COPY */ + u8_t flags; +#define TF_SEG_OPTS_MSS (u8_t)0x01U /* Include MSS option. */ +#define TF_SEG_OPTS_TS (u8_t)0x02U /* Include timestamp option. */ +#define TF_SEG_DATA_CHECKSUMMED (u8_t)0x04U /* ALL data (not the header) is + checksummed into 'chksum' */ +#define TF_SEG_OPTS_WND_SCALE (u8_t)0x08U /* Include WND SCALE option */ + struct tcp_hdr *tcphdr; /* the TCP header */ +}; + +#define LWIP_TCP_OPT_EOL 0 +#define LWIP_TCP_OPT_NOP 1 +#define LWIP_TCP_OPT_MSS 2 +#define LWIP_TCP_OPT_WS 3 +#define LWIP_TCP_OPT_TS 8 + +#define LWIP_TCP_OPT_LEN_MSS 4 +#if LWIP_TCP_TIMESTAMPS +#define LWIP_TCP_OPT_LEN_TS 10 +#define LWIP_TCP_OPT_LEN_TS_OUT 12 /* aligned for output (includes NOP padding) */ +#else +#define LWIP_TCP_OPT_LEN_TS_OUT 0 +#endif +#if LWIP_WND_SCALE +#define LWIP_TCP_OPT_LEN_WS 3 +#define LWIP_TCP_OPT_LEN_WS_OUT 4 /* aligned for output (includes NOP padding) */ +#else +#define LWIP_TCP_OPT_LEN_WS_OUT 0 +#endif + +#define LWIP_TCP_OPT_LENGTH(flags) \ + (flags & TF_SEG_OPTS_MSS ? LWIP_TCP_OPT_LEN_MSS : 0) + \ + (flags & TF_SEG_OPTS_TS ? LWIP_TCP_OPT_LEN_TS_OUT : 0) + \ + (flags & TF_SEG_OPTS_WND_SCALE ? LWIP_TCP_OPT_LEN_WS_OUT : 0) + +/** This returns a TCP header option for MSS in an u32_t */ +#define TCP_BUILD_MSS_OPTION(mss) htonl(0x02040000 | ((mss) & 0xFFFF)) + +#if LWIP_WND_SCALE +#define TCPWNDSIZE_F U32_F +#define TCPWND_MAX 0xFFFFFFFFU +#else /* LWIP_WND_SCALE */ +#define TCPWNDSIZE_F U16_F +#define TCPWND_MAX 0xFFFFU +#endif /* LWIP_WND_SCALE */ + +/* Global variables: */ +extern struct tcp_pcb *tcp_input_pcb; +extern u32_t tcp_ticks; +extern u8_t tcp_active_pcbs_changed; + +/* The TCP PCB lists. */ +union tcp_listen_pcbs_t { /* List of all TCP PCBs in LISTEN state. */ + struct tcp_pcb_listen *listen_pcbs; + struct tcp_pcb *pcbs; +}; +extern struct tcp_pcb *tcp_bound_pcbs; +extern union tcp_listen_pcbs_t tcp_listen_pcbs; +extern struct tcp_pcb *tcp_active_pcbs; /* List of all TCP PCBs that are in a + state in which they accept or send + data. */ +extern struct tcp_pcb *tcp_tw_pcbs; /* List of all TCP PCBs in TIME-WAIT. */ + +extern struct tcp_pcb *tcp_tmp_pcb; /* Only used for temporary storage. */ + +/* Axioms about the above lists: + 1) Every TCP PCB that is not CLOSED is in one of the lists. + 2) A PCB is only in one of the lists. + 3) All PCBs in the tcp_listen_pcbs list is in LISTEN state. + 4) All PCBs in the tcp_tw_pcbs list is in TIME-WAIT state. +*/ +/* Define two macros, TCP_REG and TCP_RMV that registers a TCP PCB + with a PCB list or removes a PCB from a list, respectively. */ +#ifndef TCP_DEBUG_PCB_LISTS +#define TCP_DEBUG_PCB_LISTS 0 +#endif +#if TCP_DEBUG_PCB_LISTS +#define TCP_REG(pcbs, npcb) do {\ + LWIP_DEBUGF(TCP_DEBUG, ("TCP_REG %p local port %d\n", (npcb), (npcb)->local_port)); \ + for(tcp_tmp_pcb = *(pcbs); \ + tcp_tmp_pcb != NULL; \ + tcp_tmp_pcb = tcp_tmp_pcb->next) { \ + LWIP_ASSERT("TCP_REG: already registered\n", tcp_tmp_pcb != (npcb)); \ + } \ + LWIP_ASSERT("TCP_REG: pcb->state != CLOSED", ((pcbs) == &tcp_bound_pcbs) || ((npcb)->state != CLOSED)); \ + (npcb)->next = *(pcbs); \ + LWIP_ASSERT("TCP_REG: npcb->next != npcb", (npcb)->next != (npcb)); \ + *(pcbs) = (npcb); \ + LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \ + tcp_timer_needed(); \ + } while(0) +#define TCP_RMV(pcbs, npcb) do { \ + LWIP_ASSERT("TCP_RMV: pcbs != NULL", *(pcbs) != NULL); \ + LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removing %p from %p\n", (npcb), *(pcbs))); \ + if(*(pcbs) == (npcb)) { \ + *(pcbs) = (*pcbs)->next; \ + } else for(tcp_tmp_pcb = *(pcbs); tcp_tmp_pcb != NULL; tcp_tmp_pcb = tcp_tmp_pcb->next) { \ + if(tcp_tmp_pcb->next == (npcb)) { \ + tcp_tmp_pcb->next = (npcb)->next; \ + break; \ + } \ + } \ + (npcb)->next = NULL; \ + LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \ + LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removed %p from %p\n", (npcb), *(pcbs))); \ + } while(0) + +#else /* LWIP_DEBUG */ + +#define TCP_REG(pcbs, npcb) \ + do { \ + (npcb)->next = *pcbs; \ + *(pcbs) = (npcb); \ + tcp_timer_needed(); \ + } while (0) + +#define TCP_RMV(pcbs, npcb) \ + do { \ + if(*(pcbs) == (npcb)) { \ + (*(pcbs)) = (*pcbs)->next; \ + } \ + else { \ + for(tcp_tmp_pcb = *pcbs; \ + tcp_tmp_pcb != NULL; \ + tcp_tmp_pcb = tcp_tmp_pcb->next) { \ + if(tcp_tmp_pcb->next == (npcb)) { \ + tcp_tmp_pcb->next = (npcb)->next; \ + break; \ + } \ + } \ + } \ + (npcb)->next = NULL; \ + } while(0) + +#endif /* LWIP_DEBUG */ + +#define TCP_REG_ACTIVE(npcb) \ + do { \ + TCP_REG(&tcp_active_pcbs, npcb); \ + tcp_active_pcbs_changed = 1; \ + } while (0) + +#define TCP_RMV_ACTIVE(npcb) \ + do { \ + TCP_RMV(&tcp_active_pcbs, npcb); \ + tcp_active_pcbs_changed = 1; \ + } while (0) + +#define TCP_PCB_REMOVE_ACTIVE(pcb) \ + do { \ + tcp_pcb_remove(&tcp_active_pcbs, pcb); \ + tcp_active_pcbs_changed = 1; \ + } while (0) + + +/* Internal functions: */ +struct tcp_pcb *tcp_pcb_copy(struct tcp_pcb *pcb); +void tcp_pcb_purge(struct tcp_pcb *pcb); +void tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb); + +void tcp_segs_free(struct tcp_seg *seg); +void tcp_seg_free(struct tcp_seg *seg); +struct tcp_seg *tcp_seg_copy(struct tcp_seg *seg); + +#define tcp_ack(pcb) \ + do { \ + if((pcb)->flags & TF_ACK_DELAY) { \ + (pcb)->flags &= ~TF_ACK_DELAY; \ + (pcb)->flags |= TF_ACK_NOW; \ + } \ + else { \ + (pcb)->flags |= TF_ACK_DELAY; \ + } \ + } while (0) + +#define tcp_ack_now(pcb) \ + do { \ + (pcb)->flags |= TF_ACK_NOW; \ + } while (0) + +err_t tcp_send_fin(struct tcp_pcb *pcb); +err_t tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags); + +void tcp_rexmit_seg(struct tcp_pcb *pcb, struct tcp_seg *seg); + +void tcp_rst_impl(u32_t seqno, u32_t ackno, + ipX_addr_t *local_ip, ipX_addr_t *remote_ip, + u16_t local_port, u16_t remote_port +#if LWIP_IPV6 + , u8_t isipv6 +#endif /* LWIP_IPV6 */ + ); +#if LWIP_IPV6 +#define tcp_rst(seqno, ackno, local_ip, remote_ip, local_port, remote_port, isipv6) \ + tcp_rst_impl(seqno, ackno, local_ip, remote_ip, local_port, remote_port, isipv6) +#else /* LWIP_IPV6 */ +#define tcp_rst(seqno, ackno, local_ip, remote_ip, local_port, remote_port, isipv6) \ + tcp_rst_impl(seqno, ackno, local_ip, remote_ip, local_port, remote_port) +#endif /* LWIP_IPV6 */ + +u32_t tcp_next_iss(void); + +void tcp_keepalive(struct tcp_pcb *pcb); +void tcp_zero_window_probe(struct tcp_pcb *pcb); + +#if TCP_CALCULATE_EFF_SEND_MSS +u16_t tcp_eff_send_mss_impl(u16_t sendmss, ipX_addr_t *dest +#if LWIP_IPV6 + , ipX_addr_t *src, u8_t isipv6 +#endif /* LWIP_IPV6 */ + ); +#if LWIP_IPV6 +#define tcp_eff_send_mss(sendmss, src, dest, isipv6) tcp_eff_send_mss_impl(sendmss, dest, src, isipv6) +#else /* LWIP_IPV6 */ +#define tcp_eff_send_mss(sendmss, src, dest, isipv6) tcp_eff_send_mss_impl(sendmss, dest) +#endif /* LWIP_IPV6 */ +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + +#if LWIP_CALLBACK_API +err_t tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err); +#endif /* LWIP_CALLBACK_API */ + +#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG +void tcp_debug_print(struct tcp_hdr *tcphdr); +void tcp_debug_print_flags(u8_t flags); +void tcp_debug_print_state(enum tcp_state s); +void tcp_debug_print_pcbs(void); +s16_t tcp_pcbs_sane(void); +#else +# define tcp_debug_print(tcphdr) +# define tcp_debug_print_flags(flags) +# define tcp_debug_print_state(s) +# define tcp_debug_print_pcbs() +# define tcp_pcbs_sane() 1 +#endif /* TCP_DEBUG */ + +/** External function (implemented in timers.c), called when TCP detects + * that a timer is needed (i.e. active- or time-wait-pcb found). */ +void tcp_timer_needed(void); + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_TCP */ + +#endif /* LWIP_HDR_TCP_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/tcpip.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/tcpip.h new file mode 100644 index 0000000..fc6b421 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/tcpip.h @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_TCPIP_H +#define LWIP_HDR_TCPIP_H + +#include "lwip/opt.h" + +#if !NO_SYS /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/api_msg.h" +#include "lwip/netifapi.h" +#include "lwip/pppapi.h" +#include "lwip/pbuf.h" +#include "lwip/api.h" +#include "lwip/sys.h" +#include "lwip/lwip_timers.h" //Evan modified timers.h to lwip_timers.h +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Define this to something that triggers a watchdog. This is called from + * tcpip_thread after processing a message. */ +#ifndef LWIP_TCPIP_THREAD_ALIVE +#define LWIP_TCPIP_THREAD_ALIVE() +#endif + +#if LWIP_TCPIP_CORE_LOCKING +/** The global semaphore to lock the stack. */ +extern sys_mutex_t lock_tcpip_core; +#define LOCK_TCPIP_CORE() sys_mutex_lock(&lock_tcpip_core) +#define UNLOCK_TCPIP_CORE() sys_mutex_unlock(&lock_tcpip_core) +#ifdef LWIP_DEBUG +#define TCIP_APIMSG_SET_ERR(m, e) (m)->msg.err = e /* catch functions that don't set err */ +#else +#define TCIP_APIMSG_SET_ERR(m, e) +#endif +#if LWIP_NETCONN_SEM_PER_THREAD +#define TCPIP_APIMSG_SET_SEM(m) ((m)->msg.op_completed_sem = LWIP_NETCONN_THREAD_SEM_GET()) +#else +#define TCPIP_APIMSG_SET_SEM(m) +#endif +#define TCPIP_APIMSG_NOERR(m,f) do { \ + TCIP_APIMSG_SET_ERR(m, ERR_VAL); \ + TCPIP_APIMSG_SET_SEM(m); \ + LOCK_TCPIP_CORE(); \ + f(&((m)->msg)); \ + UNLOCK_TCPIP_CORE(); \ +} while(0) +#define TCPIP_APIMSG(m,f,e) do { \ + TCPIP_APIMSG_NOERR(m,f); \ + (e) = (m)->msg.err; \ +} while(0) +#define TCPIP_APIMSG_ACK(m) +#define TCPIP_NETIFAPI(m) tcpip_netifapi_lock(m) +#define TCPIP_NETIFAPI_ACK(m) +#define TCPIP_PPPAPI(m) tcpip_pppapi_lock(m) +#define TCPIP_PPPAPI_ACK(m) +#else /* LWIP_TCPIP_CORE_LOCKING */ +#define LOCK_TCPIP_CORE() +#define UNLOCK_TCPIP_CORE() +#define TCPIP_APIMSG_NOERR(m,f) do { (m)->function = f; tcpip_apimsg(m); } while(0) +#define TCPIP_APIMSG(m,f,e) do { (m)->function = f; (e) = tcpip_apimsg(m); } while(0) +#define TCPIP_APIMSG_ACK(m) sys_sem_signal(LWIP_API_MSG_SEM(m)) +#define TCPIP_NETIFAPI(m) tcpip_netifapi(m) +#define TCPIP_NETIFAPI_ACK(m) sys_sem_signal(&m->sem) +#define TCPIP_PPPAPI(m) tcpip_pppapi(m) +#define TCPIP_PPPAPI_ACK(m) sys_sem_signal(&m->sem) +#endif /* LWIP_TCPIP_CORE_LOCKING */ + + +#if LWIP_MPU_COMPATIBLE +#define API_VAR_REF(name) (*(name)) +#define API_VAR_DECLARE(type, name) type * name +#define API_VAR_ALLOC(type, pool, name) do { \ + name = (type *)memp_malloc(pool); \ + if (name == NULL) { \ + return ERR_MEM; \ + } \ + } while(0) +#define API_VAR_ALLOC_DONTFAIL(type, pool, name) do { \ + name = (type *)memp_malloc(pool); \ + LWIP_ASSERT("pool empty", name != NULL); \ + } while(0) +#define API_VAR_FREE(pool, name) memp_free(pool, name) +#define API_EXPR_REF(expr) &(expr) +#define API_EXPR_DEREF(expr) expr +#else /* LWIP_MPU_COMPATIBLE */ +#define API_VAR_REF(name) name +#define API_VAR_DECLARE(type, name) type name +#define API_VAR_ALLOC(type, pool, name) +#define API_VAR_ALLOC_DONTFAIL(type, pool, name) +#define API_VAR_FREE(pool, name) +#define API_EXPR_REF(expr) expr +#define API_EXPR_DEREF(expr) *(expr) +#endif /* LWIP_MPU_COMPATIBLE */ + + + +/** Function prototype for the init_done function passed to tcpip_init */ +typedef void (*tcpip_init_done_fn)(void *arg); +/** Function prototype for functions passed to tcpip_callback() */ +typedef void (*tcpip_callback_fn)(void *ctx); + +/* Forward declarations */ +struct tcpip_callback_msg; + +void tcpip_init(tcpip_init_done_fn tcpip_init_done, void *arg); + +#if LWIP_NETCONN || LWIP_SOCKET +err_t tcpip_apimsg(struct api_msg *apimsg); +#endif /* LWIP_NETCONN || LWIP_SOCKET */ + +err_t tcpip_input(struct pbuf *p, struct netif *inp); + +#if LWIP_NETIF_API +err_t tcpip_netifapi(struct netifapi_msg *netifapimsg); +#if LWIP_TCPIP_CORE_LOCKING +err_t tcpip_netifapi_lock(struct netifapi_msg *netifapimsg); +#endif /* LWIP_TCPIP_CORE_LOCKING */ +#endif /* LWIP_NETIF_API */ + +#if LWIP_PPP_API +err_t tcpip_pppapi(struct pppapi_msg *pppapimsg); +#if LWIP_TCPIP_CORE_LOCKING +err_t tcpip_pppapi_lock(struct pppapi_msg *pppapimsg); +#endif /* LWIP_TCPIP_CORE_LOCKING */ +#endif /* LWIP_PPP_API */ + +err_t tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block); +#define tcpip_callback(f, ctx) tcpip_callback_with_block(f, ctx, 1) + +struct tcpip_callback_msg* tcpip_callbackmsg_new(tcpip_callback_fn function, void *ctx); +void tcpip_callbackmsg_delete(struct tcpip_callback_msg* msg); +err_t tcpip_trycallback(struct tcpip_callback_msg* msg); + +/* free pbufs or heap memory from another context without blocking */ +err_t pbuf_free_callback(struct pbuf *p); +err_t mem_free_callback(void *m); + +#if LWIP_TCPIP_TIMEOUT +err_t tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg); +err_t tcpip_untimeout(sys_timeout_handler h, void *arg); +#endif /* LWIP_TCPIP_TIMEOUT */ + +enum tcpip_msg_type { +#if LWIP_NETCONN || LWIP_SOCKET + TCPIP_MSG_API, +#endif /* LWIP_NETCONN || LWIP_SOCKET */ + TCPIP_MSG_INPKT, +#if LWIP_NETIF_API + TCPIP_MSG_NETIFAPI, +#endif /* LWIP_NETIF_API */ +#if LWIP_PPP_API + TCPIP_MSG_PPPAPI, +#endif /* LWIP_PPP_API */ +#if LWIP_TCPIP_TIMEOUT + TCPIP_MSG_TIMEOUT, + TCPIP_MSG_UNTIMEOUT, +#endif /* LWIP_TCPIP_TIMEOUT */ + TCPIP_MSG_CALLBACK, + TCPIP_MSG_CALLBACK_STATIC +}; + +struct tcpip_msg { + enum tcpip_msg_type type; + sys_sem_t *sem; + union { +#if LWIP_NETCONN || LWIP_SOCKET + struct api_msg *apimsg; +#endif /* LWIP_NETCONN || LWIP_SOCKET */ +#if LWIP_NETIF_API + struct netifapi_msg *netifapimsg; +#endif /* LWIP_NETIF_API */ +#if LWIP_PPP_API + struct pppapi_msg *pppapimsg; +#endif /* LWIP_PPP_API */ + struct { + struct pbuf *p; + struct netif *netif; + } inp; + struct { + tcpip_callback_fn function; + void *ctx; + } cb; +#if LWIP_TCPIP_TIMEOUT + struct { + u32_t msecs; + sys_timeout_handler h; + void *arg; + } tmo; +#endif /* LWIP_TCPIP_TIMEOUT */ + } msg; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* !NO_SYS */ + +#endif /* LWIP_HDR_TCPIP_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/udp.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/udp.h new file mode 100644 index 0000000..7593ca1 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/lwip/udp.h @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_UDP_H +#define LWIP_HDR_UDP_H + +#include "lwip/opt.h" + +#if LWIP_UDP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/ip_addr.h" +#include "lwip/lwip_ip.h" +#include "lwip/ip6_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define UDP_HLEN 8 + +/* Fields are (of course) in network byte order. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct udp_hdr { + PACK_STRUCT_FIELD(u16_t src); + PACK_STRUCT_FIELD(u16_t dest); /* src/dest UDP ports */ + PACK_STRUCT_FIELD(u16_t len); + PACK_STRUCT_FIELD(u16_t chksum); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define UDP_FLAGS_NOCHKSUM 0x01U +#define UDP_FLAGS_UDPLITE 0x02U +#define UDP_FLAGS_CONNECTED 0x04U +#define UDP_FLAGS_MULTICAST_LOOP 0x08U + +struct udp_pcb; + +/** Function prototype for udp pcb receive callback functions + * addr and port are in same byte order as in the pcb + * The callback is responsible for freeing the pbuf + * if it's not used any more. + * + * ATTENTION: Be aware that 'addr' points into the pbuf 'p' so freeing this pbuf + * makes 'addr' invalid, too. + * + * @param arg user supplied argument (udp_pcb.recv_arg) + * @param pcb the udp_pcb which received data + * @param p the packet buffer that was received + * @param addr the remote IP address from which the packet was received + * @param port the remote port from which the packet was received + */ +typedef void (*udp_recv_fn)(void *arg, struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *addr, u16_t port); + +#if LWIP_IPV6 +/** Function prototype for udp pcb IPv6 receive callback functions + * The callback is responsible for freeing the pbuf + * if it's not used any more. + * + * @param arg user supplied argument (udp_pcb.recv_arg) + * @param pcb the udp_pcb which received data + * @param p the packet buffer that was received + * @param addr the remote IPv6 address from which the packet was received + * @param port the remote port from which the packet was received + */ +typedef void (*udp_recv_ip6_fn)(void *arg, struct udp_pcb *pcb, struct pbuf *p, + ip6_addr_t *addr, u16_t port); +#endif /* LWIP_IPV6 */ + +#if LWIP_IPV6 +#define UDP_PCB_RECV_IP6 udp_recv_ip6_fn ip6; +#else +#define UDP_PCB_RECV_IP6 +#endif /* LWIP_IPV6 */ + +struct udp_pcb { +/* Common members of all PCB types */ + IP_PCB; + +/* Protocol specific PCB members */ + + struct udp_pcb *next; + + u8_t flags; + /** ports are in host byte order */ + u16_t local_port, remote_port; + +#if LWIP_IGMP + /** outgoing network interface for multicast packets */ + ip_addr_t multicast_ip; +#endif /* LWIP_IGMP */ + +#if LWIP_UDPLITE + /** used for UDP_LITE only */ + u16_t chksum_len_rx, chksum_len_tx; +#endif /* LWIP_UDPLITE */ + + /** receive callback function */ + union { + udp_recv_fn ip4; + UDP_PCB_RECV_IP6 + }recv; + /** user-supplied argument for the recv callback */ + void *recv_arg; +}; +/* udp_pcbs export for external reference (e.g. SNMP agent) */ +extern struct udp_pcb *udp_pcbs; + +/* The following functions is the application layer interface to the + UDP code. */ +struct udp_pcb * udp_new (void); +void udp_remove (struct udp_pcb *pcb); +err_t udp_bind (struct udp_pcb *pcb, ip_addr_t *ipaddr, + u16_t port); +err_t udp_connect (struct udp_pcb *pcb, ip_addr_t *ipaddr, + u16_t port); +void udp_disconnect (struct udp_pcb *pcb); +void udp_recv (struct udp_pcb *pcb, udp_recv_fn recv, + void *recv_arg); +err_t udp_sendto_if (struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *dst_ip, u16_t dst_port, + struct netif *netif); +err_t udp_sendto_if_src(struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *dst_ip, u16_t dst_port, + struct netif *netif, ip_addr_t *src_ip); +err_t udp_sendto (struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *dst_ip, u16_t dst_port); +err_t udp_send (struct udp_pcb *pcb, struct pbuf *p); + +#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP +err_t udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *dst_ip, u16_t dst_port, + struct netif *netif, u8_t have_chksum, + u16_t chksum); +err_t udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *dst_ip, u16_t dst_port, + u8_t have_chksum, u16_t chksum); +err_t udp_send_chksum(struct udp_pcb *pcb, struct pbuf *p, + u8_t have_chksum, u16_t chksum); +err_t udp_sendto_if_src_chksum(struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif, + u8_t have_chksum, u16_t chksum, ip_addr_t *src_ip); +#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ + +#define udp_flags(pcb) ((pcb)->flags) +#define udp_setflags(pcb, f) ((pcb)->flags = (f)) + +/* The following functions are the lower layer interface to UDP. */ +void udp_input (struct pbuf *p, struct netif *inp); + +void udp_init (void); + +#if LWIP_IPV6 +struct udp_pcb * udp_new_ip6(void); +#define udp_bind_ip6(pcb, ip6addr, port) \ + udp_bind(pcb, ip6_2_ip(ip6addr), port) +#define udp_connect_ip6(pcb, ip6addr, port) \ + udp_connect(pcb, ip6_2_ip(ip6addr), port) +#define udp_recv_ip6(pcb, recv_ip6_fn, recv_arg) \ + udp_recv(pcb, (udp_recv_fn)recv_ip6_fn, recv_arg) +#define udp_sendto_ip6(pcb, pbuf, ip6addr, port) \ + udp_sendto(pcb, pbuf, ip6_2_ip(ip6addr), port) +#define udp_sendto_if_ip6(pcb, pbuf, ip6addr, port, netif) \ + udp_sendto_if(pcb, pbuf, ip6_2_ip(ip6addr), port, netif) +#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP +#define udp_sendto_chksum_ip6(pcb, pbuf, ip6addr, port, have_chk, chksum) \ + udp_sendto_chksum(pcb, pbuf, ip6_2_ip(ip6addr), port, have_chk, chksum) +#define udp_sendto_if_chksum_ip6(pcb, pbuf, ip6addr, port, netif, have_chk, chksum) \ + udp_sendto_if_chksum(pcb, pbuf, ip6_2_ip(ip6addr), port, netif, have_chk, chksum) +#endif /*LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ +#endif /* LWIP_IPV6 */ + +#if UDP_DEBUG +void udp_debug_print(struct udp_hdr *udphdr); +#else +#define udp_debug_print(udphdr) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_UDP */ + +#endif /* LWIP_HDR_UDP_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/etharp.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/etharp.h new file mode 100644 index 0000000..39f148a --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/etharp.h @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * Copyright (c) 2003-2004 Leon Woestenberg + * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#ifndef LWIP_HDR_NETIF_ETHARP_H +#define LWIP_HDR_NETIF_ETHARP_H + +#include "lwip/opt.h" + +#if LWIP_ARP || LWIP_ETHERNET /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/lwip_ip.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef ETHARP_HWADDR_LEN +#define ETHARP_HWADDR_LEN 6 +#endif + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct eth_addr { + PACK_STRUCT_FLD_8(u8_t addr[ETHARP_HWADDR_LEN]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** Ethernet header */ +struct eth_hdr { +#if ETH_PAD_SIZE + PACK_STRUCT_FLD_8(u8_t padding[ETH_PAD_SIZE]); +#endif + PACK_STRUCT_FLD_S(struct eth_addr dest); + PACK_STRUCT_FLD_S(struct eth_addr src); + PACK_STRUCT_FIELD(u16_t type); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define SIZEOF_ETH_HDR (14 + ETH_PAD_SIZE) + +#if ETHARP_SUPPORT_VLAN + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** VLAN header inserted between ethernet header and payload + * if 'type' in ethernet header is ETHTYPE_VLAN. + * See IEEE802.Q */ +struct eth_vlan_hdr { + PACK_STRUCT_FIELD(u16_t prio_vid); + PACK_STRUCT_FIELD(u16_t tpid); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define SIZEOF_VLAN_HDR 4 +#define VLAN_ID(vlan_hdr) (htons((vlan_hdr)->prio_vid) & 0xFFF) + +#endif /* ETHARP_SUPPORT_VLAN */ + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** the ARP message, see RFC 826 ("Packet format") */ +struct etharp_hdr { + PACK_STRUCT_FIELD(u16_t hwtype); + PACK_STRUCT_FIELD(u16_t proto); + PACK_STRUCT_FLD_8(u8_t hwlen); + PACK_STRUCT_FLD_8(u8_t protolen); + PACK_STRUCT_FIELD(u16_t opcode); + PACK_STRUCT_FLD_S(struct eth_addr shwaddr); + PACK_STRUCT_FLD_S(struct ip_addr2 sipaddr); + PACK_STRUCT_FLD_S(struct eth_addr dhwaddr); + PACK_STRUCT_FLD_S(struct ip_addr2 dipaddr); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define SIZEOF_ETHARP_HDR 28 + +#define SIZEOF_ETHARP_PACKET (SIZEOF_ETH_HDR + SIZEOF_ETHARP_HDR) +#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) +#define SIZEOF_ETHARP_PACKET_TX (SIZEOF_ETHARP_PACKET + SIZEOF_VLAN_HDR) +#else /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ +#define SIZEOF_ETHARP_PACKET_TX SIZEOF_ETHARP_PACKET +#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ + +/** 1 seconds period */ +#define ARP_TMR_INTERVAL 1000 + +#define ETHTYPE_ARP 0x0806U +#define ETHTYPE_IP 0x0800U +#define ETHTYPE_VLAN 0x8100U +#define ETHTYPE_IPV6 0x86DDU +#define ETHTYPE_PPPOEDISC 0x8863U /* PPP Over Ethernet Discovery Stage */ +#define ETHTYPE_PPPOE 0x8864U /* PPP Over Ethernet Session Stage */ + +/** MEMCPY-like macro to copy to/from struct eth_addr's that are local variables + * or known to be 32-bit aligned within the protocol header. */ +#ifndef ETHADDR32_COPY +#define ETHADDR32_COPY(dst, src) SMEMCPY(dst, src, ETHARP_HWADDR_LEN) +#endif + +/** MEMCPY-like macro to copy to/from struct eth_addr's that are no local + * variables and known to be 16-bit aligned within the protocol header. */ +#ifndef ETHADDR16_COPY +#define ETHADDR16_COPY(dst, src) SMEMCPY(dst, src, ETHARP_HWADDR_LEN) +#endif + +#if LWIP_ARP /* don't build if not configured for use in lwipopts.h */ + +/** ARP message types (opcodes) */ +#define ARP_REQUEST 1 +#define ARP_REPLY 2 + +/** Define this to 1 and define LWIP_ARP_FILTER_NETIF_FN(pbuf, netif, type) + * to a filter function that returns the correct netif when using multiple + * netifs on one hardware interface where the netif's low-level receive + * routine cannot decide for the correct netif (e.g. when mapping multiple + * IP addresses to one hardware interface). + */ +#ifndef LWIP_ARP_FILTER_NETIF +#define LWIP_ARP_FILTER_NETIF 0 +#endif + +#if ARP_QUEUEING +/** struct for queueing outgoing packets for unknown address + * defined here to be accessed by memp.h + */ +struct etharp_q_entry { + struct etharp_q_entry *next; + struct pbuf *p; +}; +#endif /* ARP_QUEUEING */ + +#define etharp_init() /* Compatibility define, no init needed. */ +void etharp_tmr(void); +s8_t etharp_find_addr(struct netif *netif, ip_addr_t *ipaddr, + struct eth_addr **eth_ret, ip_addr_t **ip_ret); +err_t etharp_output(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr); +err_t etharp_query(struct netif *netif, ip_addr_t *ipaddr, struct pbuf *q); +err_t etharp_request(struct netif *netif, ip_addr_t *ipaddr); +/** For Ethernet network interfaces, we might want to send "gratuitous ARP"; + * this is an ARP packet sent by a node in order to spontaneously cause other + * nodes to update an entry in their ARP cache. + * From RFC 3220 "IP Mobility Support for IPv4" section 4.6. */ +#define etharp_gratuitous(netif) etharp_request((netif), &(netif)->ip_addr) +void etharp_cleanup_netif(struct netif *netif); + +#if ETHARP_SUPPORT_STATIC_ENTRIES +err_t etharp_add_static_entry(ip_addr_t *ipaddr, struct eth_addr *ethaddr); +err_t etharp_remove_static_entry(ip_addr_t *ipaddr); +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + +#if LWIP_AUTOIP +err_t etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr, + const struct eth_addr *ethdst_addr, + const struct eth_addr *hwsrc_addr, const ip_addr_t *ipsrc_addr, + const struct eth_addr *hwdst_addr, const ip_addr_t *ipdst_addr, + const u16_t opcode); +#endif /* LWIP_AUTOIP */ + +#endif /* LWIP_ARP */ + +err_t ethernet_input(struct pbuf *p, struct netif *netif); + +#define eth_addr_cmp(addr1, addr2) (memcmp((addr1)->addr, (addr2)->addr, ETHARP_HWADDR_LEN) == 0) + +extern const struct eth_addr ethbroadcast, ethzero; + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_ARP || LWIP_ETHERNET */ + +#endif /* LWIP_HDR_NETIF_ARP_H */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/loopif.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/loopif.h new file mode 100644 index 0000000..e69de29 diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/ccp.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/ccp.h new file mode 100644 index 0000000..f106cb5 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/ccp.h @@ -0,0 +1,57 @@ +/* + * ccp.h - Definitions for PPP Compression Control Protocol. + * + * Copyright (c) 1994-2002 Paul Mackerras. 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. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ccp.h,v 1.12 2004/11/04 10:02:26 paulus Exp $ + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && CCP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +typedef struct ccp_options { + bool bsd_compress; /* do BSD Compress? */ + bool deflate; /* do Deflate? */ + bool predictor_1; /* do Predictor-1? */ + bool predictor_2; /* do Predictor-2? */ + bool deflate_correct; /* use correct code for deflate? */ + bool deflate_draft; /* use draft RFC code for deflate? */ + bool mppe; /* do MPPE? */ + u_short bsd_bits; /* # bits/code for BSD Compress */ + u_short deflate_size; /* lg(window size) for Deflate */ + short method; /* code for chosen compression method */ +} ccp_options; + +extern fsm ccp_fsm[]; +extern ccp_options ccp_wantoptions[]; +extern ccp_options ccp_gotoptions[]; +extern ccp_options ccp_allowoptions[]; +extern ccp_options ccp_hisoptions[]; + +extern const struct protent ccp_protent; + +#endif /* PPP_SUPPORT && CCP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/chap-md5.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/chap-md5.h new file mode 100644 index 0000000..a05a157 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/chap-md5.h @@ -0,0 +1,36 @@ +/* + * chap-md5.h - New CHAP/MD5 implementation. + * + * Copyright (c) 2003 Paul Mackerras. 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. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && CHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +extern const struct chap_digest_type md5_digest; + +#endif /* PPP_SUPPORT && CHAP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/chap-new.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/chap-new.h new file mode 100644 index 0000000..5753fb6 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/chap-new.h @@ -0,0 +1,193 @@ +/* + * chap-new.c - New CHAP implementation. + * + * Copyright (c) 2003 Paul Mackerras. 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. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && CHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef CHAP_H +#define CHAP_H + +#include "ppp.h" + +/* + * CHAP packets begin with a standard header with code, id, len (2 bytes). + */ +#define CHAP_HDRLEN 4 + +/* + * Values for the code field. + */ +#define CHAP_CHALLENGE 1 +#define CHAP_RESPONSE 2 +#define CHAP_SUCCESS 3 +#define CHAP_FAILURE 4 + +/* + * CHAP digest codes. + */ +#define CHAP_MD5 5 +#if MSCHAP_SUPPORT +#define CHAP_MICROSOFT 0x80 +#define CHAP_MICROSOFT_V2 0x81 +#endif /* MSCHAP_SUPPORT */ + +/* + * Semi-arbitrary limits on challenge and response fields. + */ +#define MAX_CHALLENGE_LEN 64 +#define MAX_RESPONSE_LEN 64 + +/* + * These limits apply to challenge and response packets we send. + * The +4 is the +1 that we actually need rounded up. + */ +#define CHAL_MAX_PKTLEN (PPP_HDRLEN + CHAP_HDRLEN + 4 + MAX_CHALLENGE_LEN + MAXNAMELEN) +#define RESP_MAX_PKTLEN (PPP_HDRLEN + CHAP_HDRLEN + 4 + MAX_RESPONSE_LEN + MAXNAMELEN) + +/* bitmask of supported algorithms */ +#if MSCHAP_SUPPORT +#define MDTYPE_MICROSOFT_V2 0x1 +#define MDTYPE_MICROSOFT 0x2 +#endif /* MSCHAP_SUPPORT */ +#define MDTYPE_MD5 0x4 +#define MDTYPE_NONE 0 + +#if MSCHAP_SUPPORT +/* Return the digest alg. ID for the most preferred digest type. */ +#define CHAP_DIGEST(mdtype) \ + ((mdtype) & MDTYPE_MD5)? CHAP_MD5: \ + ((mdtype) & MDTYPE_MICROSOFT_V2)? CHAP_MICROSOFT_V2: \ + ((mdtype) & MDTYPE_MICROSOFT)? CHAP_MICROSOFT: \ + 0 +#else /* !MSCHAP_SUPPORT */ +#define CHAP_DIGEST(mdtype) \ + ((mdtype) & MDTYPE_MD5)? CHAP_MD5: \ + 0 +#endif /* MSCHAP_SUPPORT */ + +/* Return the bit flag (lsb set) for our most preferred digest type. */ +#define CHAP_MDTYPE(mdtype) ((mdtype) ^ ((mdtype) - 1)) & (mdtype) + +/* Return the bit flag for a given digest algorithm ID. */ +#if MSCHAP_SUPPORT +#define CHAP_MDTYPE_D(digest) \ + ((digest) == CHAP_MICROSOFT_V2)? MDTYPE_MICROSOFT_V2: \ + ((digest) == CHAP_MICROSOFT)? MDTYPE_MICROSOFT: \ + ((digest) == CHAP_MD5)? MDTYPE_MD5: \ + 0 +#else /* !MSCHAP_SUPPORT */ +#define CHAP_MDTYPE_D(digest) \ + ((digest) == CHAP_MD5)? MDTYPE_MD5: \ + 0 +#endif /* MSCHAP_SUPPORT */ + +/* Can we do the requested digest? */ +#if MSCHAP_SUPPORT +#define CHAP_CANDIGEST(mdtype, digest) \ + ((digest) == CHAP_MICROSOFT_V2)? (mdtype) & MDTYPE_MICROSOFT_V2: \ + ((digest) == CHAP_MICROSOFT)? (mdtype) & MDTYPE_MICROSOFT: \ + ((digest) == CHAP_MD5)? (mdtype) & MDTYPE_MD5: \ + 0 +#else /* !MSCHAP_SUPPORT */ +#define CHAP_CANDIGEST(mdtype, digest) \ + ((digest) == CHAP_MD5)? (mdtype) & MDTYPE_MD5: \ + 0 +#endif /* MSCHAP_SUPPORT */ + +/* + * The code for each digest type has to supply one of these. + */ +struct chap_digest_type { + int code; + +#if PPP_SERVER + /* + * Note: challenge and response arguments below are formatted as + * a length byte followed by the actual challenge/response data. + */ + void (*generate_challenge)(unsigned char *challenge); + int (*verify_response)(int id, const char *name, + const unsigned char *secret, int secret_len, + const unsigned char *challenge, const unsigned char *response, + char *message, int message_space); +#endif /* PPP_SERVER */ + void (*make_response)(unsigned char *response, int id, const char *our_name, + const unsigned char *challenge, const char *secret, int secret_len, + const unsigned char *priv); + int (*check_success)(unsigned char *pkt, int len, unsigned char *priv); + void (*handle_failure)(unsigned char *pkt, int len); +}; + +/* + * Each interface is described by chap structure. + */ +#if CHAP_SUPPORT +typedef struct chap_client_state { + u8_t flags; + const char *name; + const struct chap_digest_type *digest; + unsigned char priv[64]; /* private area for digest's use */ +} chap_client_state; + +#if PPP_SERVER +typedef struct chap_server_state { + u8_t flags; + int id; + const char *name; + const struct chap_digest_type *digest; + int challenge_xmits; + int challenge_pktlen; + unsigned char challenge[CHAL_MAX_PKTLEN]; + char message[256]; +} chap_server_state; +#endif /* PPP_SERVER */ +#endif /* CHAP_SUPPORT */ + +#if 0 /* UNUSED */ +/* Hook for a plugin to validate CHAP challenge */ +extern int (*chap_verify_hook)(char *name, char *ourname, int id, + const struct chap_digest_type *digest, + unsigned char *challenge, unsigned char *response, + char *message, int message_space); +#endif /* UNUSED */ + +#if PPP_SERVER +/* Called by authentication code to start authenticating the peer. */ +extern void chap_auth_peer(ppp_pcb *pcb, const char *our_name, int digest_code); +#endif /* PPP_SERVER */ + +/* Called by auth. code to start authenticating us to the peer. */ +extern void chap_auth_with_peer(ppp_pcb *pcb, const char *our_name, int digest_code); + +/* Represents the CHAP protocol to the main pppd code */ +extern const struct protent chap_protent; + +#endif /* CHAP_H */ +#endif /* PPP_SUPPORT && CHAP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/chap_ms.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/chap_ms.h new file mode 100644 index 0000000..a366e47 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/chap_ms.h @@ -0,0 +1,115 @@ +/* + * chap_ms.h - Challenge Handshake Authentication Protocol definitions. + * + * Copyright (c) 1995 Eric Rosenquist. 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. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: chap_ms.h,v 1.13 2004/11/15 22:13:26 paulus Exp $ + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && MSCHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef __CHAPMS_INCLUDE__ + +#define MD4_SIGNATURE_SIZE 16 /* 16 bytes in a MD4 message digest */ +#define MAX_NT_PASSWORD 256 /* Max (Unicode) chars in an NT pass */ + +#define MS_CHAP_RESPONSE_LEN 49 /* Response length for MS-CHAP */ +#define MS_CHAP2_RESPONSE_LEN 49 /* Response length for MS-CHAPv2 */ +#define MS_AUTH_RESPONSE_LENGTH 40 /* MS-CHAPv2 authenticator response, */ + /* as ASCII */ + +/* Error codes for MS-CHAP failure messages. */ +#define MS_CHAP_ERROR_RESTRICTED_LOGON_HOURS 646 +#define MS_CHAP_ERROR_ACCT_DISABLED 647 +#define MS_CHAP_ERROR_PASSWD_EXPIRED 648 +#define MS_CHAP_ERROR_NO_DIALIN_PERMISSION 649 +#define MS_CHAP_ERROR_AUTHENTICATION_FAILURE 691 +#define MS_CHAP_ERROR_CHANGING_PASSWORD 709 + +/* + * Offsets within the response field for MS-CHAP + */ +#define MS_CHAP_LANMANRESP 0 +#define MS_CHAP_LANMANRESP_LEN 24 +#define MS_CHAP_NTRESP 24 +#define MS_CHAP_NTRESP_LEN 24 +#define MS_CHAP_USENT 48 + +/* + * Offsets within the response field for MS-CHAP2 + */ +#define MS_CHAP2_PEER_CHALLENGE 0 +#define MS_CHAP2_PEER_CHAL_LEN 16 +#define MS_CHAP2_RESERVED_LEN 8 +#define MS_CHAP2_NTRESP 24 +#define MS_CHAP2_NTRESP_LEN 24 +#define MS_CHAP2_FLAGS 48 + +#ifdef MPPE +#include "mppe.h" /* MPPE_MAX_KEY_LEN */ +extern u_char mppe_send_key[MPPE_MAX_KEY_LEN]; +extern u_char mppe_recv_key[MPPE_MAX_KEY_LEN]; +extern int mppe_keys_set; + +/* These values are the RADIUS attribute values--see RFC 2548. */ +#define MPPE_ENC_POL_ENC_ALLOWED 1 +#define MPPE_ENC_POL_ENC_REQUIRED 2 +#define MPPE_ENC_TYPES_RC4_40 2 +#define MPPE_ENC_TYPES_RC4_128 4 + +/* used by plugins (using above values) */ +extern void set_mppe_enc_types(int, int); +#endif + +/* Are we the authenticator or authenticatee? For MS-CHAPv2 key derivation. */ +#define MS_CHAP2_AUTHENTICATEE 0 +#define MS_CHAP2_AUTHENTICATOR 1 + +void ChapMS (u_char *, char *, int, u_char *); +void ChapMS2 (u_char *, u_char *, char *, char *, int, + u_char *, u_char[MS_AUTH_RESPONSE_LENGTH+1], int); +#ifdef MPPE +void mppe_set_keys (u_char *, u_char[MD4_SIGNATURE_SIZE]); +void mppe_set_keys2(u_char PasswordHashHash[MD4_SIGNATURE_SIZE], + u_char NTResponse[24], int IsServer); +#endif + +void ChallengeHash (u_char[16], u_char *, char *, u_char[8]); + +void GenerateAuthenticatorResponse(u_char PasswordHashHash[MD4_SIGNATURE_SIZE], + u_char NTResponse[24], u_char PeerChallenge[16], + u_char *rchallenge, char *username, + u_char authResponse[MS_AUTH_RESPONSE_LENGTH+1]); + +extern const struct chap_digest_type chapms_digest; +extern const struct chap_digest_type chapms2_digest; + +#define __CHAPMS_INCLUDE__ +#endif /* __CHAPMS_INCLUDE__ */ + +#endif /* PPP_SUPPORT && MSCHAP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/eap.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/eap.h new file mode 100644 index 0000000..cab6901 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/eap.h @@ -0,0 +1,168 @@ +/* + * eap.h - Extensible Authentication Protocol for PPP (RFC 2284) + * + * Copyright (c) 2001 by Sun Microsystems, Inc. + * All rights reserved. + * + * Non-exclusive rights to redistribute, modify, translate, and use + * this software in source and binary forms, in whole or in part, is + * hereby granted, provided that the above copyright notice is + * duplicated in any source form, and that neither the name of the + * copyright holder nor the author is used to endorse or promote + * products derived from this software. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Original version by James Carlson + * + * $Id: eap.h,v 1.2 2003/06/11 23:56:26 paulus Exp $ + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && EAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef PPP_EAP_H +#define PPP_EAP_H + +#include "ppp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Packet header = Code, id, length. + */ +#define EAP_HEADERLEN 4 + + +/* EAP message codes. */ +#define EAP_REQUEST 1 +#define EAP_RESPONSE 2 +#define EAP_SUCCESS 3 +#define EAP_FAILURE 4 + +/* EAP types */ +#define EAPT_IDENTITY 1 +#define EAPT_NOTIFICATION 2 +#define EAPT_NAK 3 /* (response only) */ +#define EAPT_MD5CHAP 4 +#define EAPT_OTP 5 /* One-Time Password; RFC 1938 */ +#define EAPT_TOKEN 6 /* Generic Token Card */ +/* 7 and 8 are unassigned. */ +#define EAPT_RSA 9 /* RSA Public Key Authentication */ +#define EAPT_DSS 10 /* DSS Unilateral */ +#define EAPT_KEA 11 /* KEA */ +#define EAPT_KEA_VALIDATE 12 /* KEA-VALIDATE */ +#define EAPT_TLS 13 /* EAP-TLS */ +#define EAPT_DEFENDER 14 /* Defender Token (AXENT) */ +#define EAPT_W2K 15 /* Windows 2000 EAP */ +#define EAPT_ARCOT 16 /* Arcot Systems */ +#define EAPT_CISCOWIRELESS 17 /* Cisco Wireless */ +#define EAPT_NOKIACARD 18 /* Nokia IP smart card */ +#define EAPT_SRP 19 /* Secure Remote Password */ +/* 20 is deprecated */ + +/* EAP SRP-SHA1 Subtypes */ +#define EAPSRP_CHALLENGE 1 /* Request 1 - Challenge */ +#define EAPSRP_CKEY 1 /* Response 1 - Client Key */ +#define EAPSRP_SKEY 2 /* Request 2 - Server Key */ +#define EAPSRP_CVALIDATOR 2 /* Response 2 - Client Validator */ +#define EAPSRP_SVALIDATOR 3 /* Request 3 - Server Validator */ +#define EAPSRP_ACK 3 /* Response 3 - final ack */ +#define EAPSRP_LWRECHALLENGE 4 /* Req/resp 4 - Lightweight rechal */ + +#define SRPVAL_EBIT 0x00000001 /* Use shared key for ECP */ + +#define SRP_PSEUDO_ID "pseudo_" +#define SRP_PSEUDO_LEN 7 + +#define MD5_SIGNATURE_SIZE 16 +#define EAP_MIN_CHALLENGE_LENGTH 16 +#define EAP_MAX_CHALLENGE_LENGTH 24 + +#define EAP_STATES \ + "Initial", "Pending", "Closed", "Listen", "Identify", \ + "SRP1", "SRP2", "SRP3", "MD5Chall", "Open", "SRP4", "BadAuth" + +#define eap_client_active(pcb) ((pcb)->eap.es_client.ea_state == eapListen) +#if PPP_SERVER +#define eap_server_active(pcb) \ + ((pcb)->eap.es_server.ea_state >= eapIdentify && \ + (pcb)->eap.es_server.ea_state <= eapMD5Chall) +#endif /* PPP_SERVER */ + +/* + * Complete EAP state for one PPP session. + */ +enum eap_state_code { + eapInitial = 0, /* No EAP authentication yet requested */ + eapPending, /* Waiting for LCP (no timer) */ + eapClosed, /* Authentication not in use */ + eapListen, /* Client ready (and timer running) */ + eapIdentify, /* EAP Identify sent */ + eapSRP1, /* Sent EAP SRP-SHA1 Subtype 1 */ + eapSRP2, /* Sent EAP SRP-SHA1 Subtype 2 */ + eapSRP3, /* Sent EAP SRP-SHA1 Subtype 3 */ + eapMD5Chall, /* Sent MD5-Challenge */ + eapOpen, /* Completed authentication */ + eapSRP4, /* Sent EAP SRP-SHA1 Subtype 4 */ + eapBadAuth /* Failed authentication */ +}; + +struct eap_auth { + const char *ea_name; /* Our name */ + char *ea_peer; /* Peer's name */ + void *ea_session; /* Authentication library linkage */ + u_char *ea_skey; /* Shared encryption key */ + u_short ea_namelen; /* Length of our name */ + u_short ea_peerlen; /* Length of peer's name */ + enum eap_state_code ea_state; + u_char ea_id; /* Current id */ + u_char ea_requests; /* Number of Requests sent/received */ + u_char ea_responses; /* Number of Responses */ + u_char ea_type; /* One of EAPT_* */ + u32_t ea_keyflags; /* SRP shared key usage flags */ +}; + +#ifndef EAP_MAX_CHALLENGE_LENGTH +#define EAP_MAX_CHALLENGE_LENGTH 24 +#endif +typedef struct eap_state { + struct eap_auth es_client; /* Client (authenticatee) data */ +#if PPP_SERVER + struct eap_auth es_server; /* Server (authenticator) data */ +#endif /* PPP_SERVER */ + int es_savedtime; /* Saved timeout */ + int es_rechallenge; /* EAP rechallenge interval */ + int es_lwrechallenge; /* SRP lightweight rechallenge inter */ + u8_t es_usepseudo; /* Use SRP Pseudonym if offered one */ + int es_usedpseudo; /* Set if we already sent PN */ + int es_challen; /* Length of challenge string */ + u_char es_challenge[EAP_MAX_CHALLENGE_LENGTH]; +} eap_state; + +/* + * Timeouts. + */ +#if 0 /* moved to opt.h */ +#define EAP_DEFTIMEOUT 3 /* Timeout (seconds) for rexmit */ +#define EAP_DEFTRANSMITS 10 /* max # times to transmit */ +#define EAP_DEFREQTIME 20 /* Time to wait for peer request */ +#define EAP_DEFALLOWREQ 20 /* max # times to accept requests */ +#endif /* moved to opt.h */ + +void eap_authwithpeer(ppp_pcb *pcb, const char *localname); +void eap_authpeer(ppp_pcb *pcb, const char *localname); + +extern const struct protent eap_protent; + +#ifdef __cplusplus +} +#endif + +#endif /* PPP_EAP_H */ + +#endif /* PPP_SUPPORT && EAP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/ecp.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/ecp.h new file mode 100644 index 0000000..cba6678 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/ecp.h @@ -0,0 +1,50 @@ +/* + * ecp.h - Definitions for PPP Encryption Control Protocol. + * + * Copyright (c) 2002 Google, Inc. + * 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. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ecp.h,v 1.2 2003/01/10 07:12:36 fcusack Exp $ + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && ECP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +typedef struct ecp_options { + bool required; /* Is ECP required? */ + unsigned enctype; /* Encryption type */ +} ecp_options; + +extern fsm ecp_fsm[]; +extern ecp_options ecp_wantoptions[]; +extern ecp_options ecp_gotoptions[]; +extern ecp_options ecp_allowoptions[]; +extern ecp_options ecp_hisoptions[]; + +extern const struct protent ecp_protent; + +#endif /* PPP_SUPPORT && ECP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/eui64.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/eui64.h new file mode 100644 index 0000000..dffb5e4 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/eui64.h @@ -0,0 +1,94 @@ +/* + * eui64.h - EUI64 routines for IPv6CP. + * + * Copyright (c) 1999 Tommi Komulainen. 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. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Tommi Komulainen + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: eui64.h,v 1.6 2002/12/04 23:03:32 paulus Exp $ +*/ + +#include "lwip/opt.h" +#if PPP_SUPPORT && PPP_IPV6_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef __EUI64_H__ +#define __EUI64_H__ + +/* + * TODO: + * + * Maybe this should be done by processing struct in6_addr directly... + */ +typedef union +{ + u8_t e8[8]; + u16_t e16[4]; + u32_t e32[2]; +} eui64_t; + +#define eui64_iszero(e) (((e).e32[0] | (e).e32[1]) == 0) +#define eui64_equals(e, o) (((e).e32[0] == (o).e32[0]) && \ + ((e).e32[1] == (o).e32[1])) +#define eui64_zero(e) (e).e32[0] = (e).e32[1] = 0; + +#define eui64_copy(s, d) memcpy(&(d), &(s), sizeof(eui64_t)) + +#define eui64_magic(e) do { \ + (e).e32[0] = magic(); \ + (e).e32[1] = magic(); \ + (e).e8[0] &= ~2; \ + } while (0) +#define eui64_magic_nz(x) do { \ + eui64_magic(x); \ + } while (eui64_iszero(x)) +#define eui64_magic_ne(x, y) do { \ + eui64_magic(x); \ + } while (eui64_equals(x, y)) + +#define eui64_get(ll, cp) do { \ + eui64_copy((*cp), (ll)); \ + (cp) += sizeof(eui64_t); \ + } while (0) + +#define eui64_put(ll, cp) do { \ + eui64_copy((ll), (*cp)); \ + (cp) += sizeof(eui64_t); \ + } while (0) + +#define eui64_set32(e, l) do { \ + (e).e32[0] = 0; \ + (e).e32[1] = htonl(l); \ + } while (0) +#define eui64_setlo32(e, l) eui64_set32(e, l) + +char *eui64_ntoa(eui64_t); /* Returns ascii representation of id */ + +#endif /* __EUI64_H__ */ +#endif /* PPP_SUPPORT && PPP_IPV6_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/fsm.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/fsm.h new file mode 100644 index 0000000..fda2d6e --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/fsm.h @@ -0,0 +1,175 @@ +/* + * fsm.h - {Link, IP} Control Protocol Finite State Machine definitions. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. 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. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: fsm.h,v 1.10 2004/11/13 02:28:15 paulus Exp $ + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef FSM_H +#define FSM_H + +#include "ppp.h" + +/* + * Packet header = Code, id, length. + */ +#define HEADERLEN 4 + + +/* + * CP (LCP, IPCP, etc.) codes. + */ +#define CONFREQ 1 /* Configuration Request */ +#define CONFACK 2 /* Configuration Ack */ +#define CONFNAK 3 /* Configuration Nak */ +#define CONFREJ 4 /* Configuration Reject */ +#define TERMREQ 5 /* Termination Request */ +#define TERMACK 6 /* Termination Ack */ +#define CODEREJ 7 /* Code Reject */ + + +/* + * Each FSM is described by an fsm structure and fsm callbacks. + */ +typedef struct fsm { + ppp_pcb *pcb; /* PPP Interface */ + const struct fsm_callbacks *callbacks; /* Callback routines */ + const char *term_reason; /* Reason for closing protocol */ + u8_t seen_ack; /* Have received valid Ack/Nak/Rej to Req */ + /* -- This is our only flag, we might use u_int :1 if we have more flags */ + u16_t protocol; /* Data Link Layer Protocol field value */ + u8_t state; /* State */ + u8_t flags; /* Contains option bits */ + u8_t id; /* Current id */ + u8_t reqid; /* Current request id */ + u8_t retransmits; /* Number of retransmissions left */ + u8_t nakloops; /* Number of nak loops since last ack */ + u8_t rnakloops; /* Number of naks received */ + u8_t maxnakloops; /* Maximum number of nak loops tolerated + (necessary because IPCP require a custom large max nak loops value) */ + u8_t term_reason_len; /* Length of term_reason */ +} fsm; + + +typedef struct fsm_callbacks { + void (*resetci) /* Reset our Configuration Information */ + (fsm *); + int (*cilen) /* Length of our Configuration Information */ + (fsm *); + void (*addci) /* Add our Configuration Information */ + (fsm *, u_char *, int *); + int (*ackci) /* ACK our Configuration Information */ + (fsm *, u_char *, int); + int (*nakci) /* NAK our Configuration Information */ + (fsm *, u_char *, int, int); + int (*rejci) /* Reject our Configuration Information */ + (fsm *, u_char *, int); + int (*reqci) /* Request peer's Configuration Information */ + (fsm *, u_char *, int *, int); + void (*up) /* Called when fsm reaches PPP_FSM_OPENED state */ + (fsm *); + void (*down) /* Called when fsm leaves PPP_FSM_OPENED state */ + (fsm *); + void (*starting) /* Called when we want the lower layer */ + (fsm *); + void (*finished) /* Called when we don't want the lower layer */ + (fsm *); + void (*protreject) /* Called when Protocol-Reject received */ + (int); + void (*retransmit) /* Retransmission is necessary */ + (fsm *); + int (*extcode) /* Called when unknown code received */ + (fsm *, int, int, u_char *, int); + const char *proto_name; /* String name for protocol (for messages) */ +} fsm_callbacks; + + +/* + * Link states. + */ +#define PPP_FSM_INITIAL 0 /* Down, hasn't been opened */ +#define PPP_FSM_STARTING 1 /* Down, been opened */ +#define PPP_FSM_CLOSED 2 /* Up, hasn't been opened */ +#define PPP_FSM_STOPPED 3 /* Open, waiting for down event */ +#define PPP_FSM_CLOSING 4 /* Terminating the connection, not open */ +#define PPP_FSM_STOPPING 5 /* Terminating, but open */ +#define PPP_FSM_REQSENT 6 /* We've sent a Config Request */ +#define PPP_FSM_ACKRCVD 7 /* We've received a Config Ack */ +#define PPP_FSM_ACKSENT 8 /* We've sent a Config Ack */ +#define PPP_FSM_OPENED 9 /* Connection available */ + + +/* + * Flags - indicate options controlling FSM operation + */ +#define OPT_PASSIVE 1 /* Don't die if we don't get a response */ +#define OPT_RESTART 2 /* Treat 2nd OPEN as DOWN, UP */ +#define OPT_SILENT 4 /* Wait for peer to speak first */ + + +/* + * Timeouts. + */ +#if 0 /* moved to opt.h */ +#define DEFTIMEOUT 3 /* Timeout time in seconds */ +#define DEFMAXTERMREQS 2 /* Maximum Terminate-Request transmissions */ +#define DEFMAXCONFREQS 10 /* Maximum Configure-Request transmissions */ +#define DEFMAXNAKLOOPS 5 /* Maximum number of nak loops */ +#endif /* moved to opt.h */ + + +/* + * Prototypes + */ +void fsm_init(fsm *f); +void fsm_lowerup(fsm *f); +void fsm_lowerdown(fsm *f); +void fsm_open(fsm *f); +void fsm_close(fsm *f, const char *reason); +void fsm_input(fsm *f, u_char *inpacket, int l); +void fsm_protreject(fsm *f); +void fsm_sdata(fsm *f, u_char code, u_char id, u_char *data, int datalen); + + +#endif /* FSM_H */ +#endif /* PPP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/ipcp.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/ipcp.h new file mode 100644 index 0000000..b5f2334 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/ipcp.h @@ -0,0 +1,107 @@ +/* + * ipcp.h - IP Control Protocol definitions. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. 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. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ipcp.h,v 1.14 2002/12/04 23:03:32 paulus Exp $ + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef IPCP_H +#define IPCP_H + +/* + * Options. + */ +#define CI_ADDRS 1 /* IP Addresses */ +#define CI_COMPRESSTYPE 2 /* Compression Type */ +#define CI_ADDR 3 + +#define CI_MS_DNS1 129 /* Primary DNS value */ +#define CI_MS_WINS1 130 /* Primary WINS value */ +#define CI_MS_DNS2 131 /* Secondary DNS value */ +#define CI_MS_WINS2 132 /* Secondary WINS value */ + +#define MAX_STATES 16 /* from slcompress.h */ + +#define IPCP_VJMODE_OLD 1 /* "old" mode (option # = 0x0037) */ +#define IPCP_VJMODE_RFC1172 2 /* "old-rfc"mode (option # = 0x002d) */ +#define IPCP_VJMODE_RFC1332 3 /* "new-rfc"mode (option # = 0x002d, */ + /* maxslot and slot number compression) */ + +#define IPCP_VJ_COMP 0x002d /* current value for VJ compression option*/ +#define IPCP_VJ_COMP_OLD 0x0037 /* "old" (i.e, broken) value for VJ */ + /* compression option*/ + +typedef struct ipcp_options { + unsigned int neg_addr :1; /* Negotiate IP Address? */ + unsigned int old_addrs :1; /* Use old (IP-Addresses) option? */ + unsigned int req_addr :1; /* Ask peer to send IP address? */ +#if 0 /* UNUSED */ + unsigned int default_route :1; /* Assign default route through interface? */ + unsigned int replace_default_route :1; /* Replace default route through interface? */ +#endif /* UNUSED */ + unsigned int proxy_arp :1; /* Make proxy ARP entry for peer? */ + unsigned int neg_vj :1; /* Van Jacobson Compression? */ + unsigned int old_vj :1; /* use old (short) form of VJ option? */ + unsigned int accept_local :1; /* accept peer's value for ouraddr */ + unsigned int accept_remote :1; /* accept peer's value for hisaddr */ + unsigned int req_dns1 :1; /* Ask peer to send primary DNS address? */ + unsigned int req_dns2 :1; /* Ask peer to send secondary DNS address? */ + unsigned int cflag :1; + unsigned int :5; /* 3 bits of padding to round out to 16 bits */ + + u32_t ouraddr, hisaddr; /* Addresses in NETWORK BYTE ORDER */ + u32_t dnsaddr[2]; /* Primary and secondary MS DNS entries */ + u32_t winsaddr[2]; /* Primary and secondary MS WINS entries */ + + u16_t vj_protocol; /* protocol value to use in VJ option */ + u8_t maxslotindex; /* values for RFC1332 VJ compression neg. */ +} ipcp_options; + +#if 0 /* UNUSED, already defined by lwIP */ +char *ip_ntoa (u32_t); +#endif /* UNUSED, already defined by lwIP */ + +extern const struct protent ipcp_protent; + +#endif /* IPCP_H */ +#endif /* PPP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/ipv6cp.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/ipv6cp.h new file mode 100644 index 0000000..e6afddf --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/ipv6cp.h @@ -0,0 +1,177 @@ +/* + * ipv6cp.h - PPP IPV6 Control Protocol. + * + * Copyright (c) 1999 Tommi Komulainen. 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. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Tommi Komulainen + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +/* Original version, based on RFC2023 : + + Copyright (c) 1995, 1996, 1997 Francis.Dupont@inria.fr, INRIA Rocquencourt, + Alain.Durand@imag.fr, IMAG, + Jean-Luc.Richier@imag.fr, IMAG-LSR. + + Copyright (c) 1998, 1999 Francis.Dupont@inria.fr, GIE DYADE, + Alain.Durand@imag.fr, IMAG, + Jean-Luc.Richier@imag.fr, IMAG-LSR. + + Ce travail a été fait au sein du GIE DYADE (Groupement d'Intérêt + Économique ayant pour membres BULL S.A. et l'INRIA). + + Ce logiciel informatique est disponible aux conditions + usuelles dans la recherche, c'est-à-dire qu'il peut + être utilisé, copié, modifié, distribué à l'unique + condition que ce texte soit conservé afin que + l'origine de ce logiciel soit reconnue. + + Le nom de l'Institut National de Recherche en Informatique + et en Automatique (INRIA), de l'IMAG, ou d'une personne morale + ou physique ayant participé à l'élaboration de ce logiciel ne peut + être utilisé sans son accord préalable explicite. + + Ce logiciel est fourni tel quel sans aucune garantie, + support ou responsabilité d'aucune sorte. + Ce logiciel est dérivé de sources d'origine + "University of California at Berkeley" et + "Digital Equipment Corporation" couvertes par des copyrights. + + L'Institut d'Informatique et de Mathématiques Appliquées de Grenoble (IMAG) + est une fédération d'unités mixtes de recherche du CNRS, de l'Institut National + Polytechnique de Grenoble et de l'Université Joseph Fourier regroupant + sept laboratoires dont le laboratoire Logiciels, Systèmes, Réseaux (LSR). + + This work has been done in the context of GIE DYADE (joint R & D venture + between BULL S.A. and INRIA). + + This software is available with usual "research" terms + with the aim of retain credits of the software. + Permission to use, copy, modify and distribute this software for any + purpose and without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies, + and the name of INRIA, IMAG, or any contributor not be used in advertising + or publicity pertaining to this material without the prior explicit + permission. The software is provided "as is" without any + warranties, support or liabilities of any kind. + This software is derived from source code from + "University of California at Berkeley" and + "Digital Equipment Corporation" protected by copyrights. + + Grenoble's Institute of Computer Science and Applied Mathematics (IMAG) + is a federation of seven research units funded by the CNRS, National + Polytechnic Institute of Grenoble and University Joseph Fourier. + The research unit in Software, Systems, Networks (LSR) is member of IMAG. +*/ + +/* + * Derived from : + * + * + * ipcp.h - IP Control Protocol definitions. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. 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. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ipv6cp.h,v 1.7 2002/12/04 23:03:32 paulus Exp $ + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && PPP_IPV6_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef IPV6CP_H +#define IPV6CP_H + +#include "eui64.h" + +/* + * Options. + */ +#define CI_IFACEID 1 /* Interface Identifier */ +#define CI_COMPRESSTYPE 2 /* Compression Type */ + +/* No compression types yet defined. + *#define IPV6CP_COMP 0x004f + */ +typedef struct ipv6cp_options { + unsigned int neg_ifaceid :1; /* Negotiate interface identifier? */ + unsigned int req_ifaceid :1; /* Ask peer to send interface identifier? */ + unsigned int accept_local :1; /* accept peer's value for iface id? */ + unsigned int opt_local :1; /* ourtoken set by option */ + unsigned int opt_remote :1; /* histoken set by option */ + unsigned int use_ip :1; /* use IP as interface identifier */ +#if 0 + unsigned int use_persistent :1; /* use uniquely persistent value for address */ +#endif + unsigned int neg_vj :1; /* Van Jacobson Compression? */ + unsigned int :1; /* 1 bit of padding to round out to 8 bits */ + u_short vj_protocol; /* protocol value to use in VJ option */ + eui64_t ourid, hisid; /* Interface identifiers */ +} ipv6cp_options; + +extern const struct protent ipv6cp_protent; + +#endif /* IPV6CP_H */ +#endif /* PPP_SUPPORT && PPP_IPV6_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/lcp.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/lcp.h new file mode 100644 index 0000000..d7fa7c4 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/lcp.h @@ -0,0 +1,176 @@ +/* + * lcp.h - Link Control Protocol definitions. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. 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. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: lcp.h,v 1.20 2004/11/14 22:53:42 carlsonj Exp $ + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef LCP_H +#define LCP_H + +#include "ppp.h" + +/* + * Options. + */ +#define CI_VENDOR 0 /* Vendor Specific */ +#define CI_MRU 1 /* Maximum Receive Unit */ +#define CI_ASYNCMAP 2 /* Async Control Character Map */ +#define CI_AUTHTYPE 3 /* Authentication Type */ +#define CI_QUALITY 4 /* Quality Protocol */ +#define CI_MAGICNUMBER 5 /* Magic Number */ +#define CI_PCOMPRESSION 7 /* Protocol Field Compression */ +#define CI_ACCOMPRESSION 8 /* Address/Control Field Compression */ +#define CI_FCSALTERN 9 /* FCS-Alternatives */ +#define CI_SDP 10 /* Self-Describing-Pad */ +#define CI_NUMBERED 11 /* Numbered-Mode */ +#define CI_CALLBACK 13 /* callback */ +#define CI_MRRU 17 /* max reconstructed receive unit; multilink */ +#define CI_SSNHF 18 /* short sequence numbers for multilink */ +#define CI_EPDISC 19 /* endpoint discriminator */ +#define CI_MPPLUS 22 /* Multi-Link-Plus-Procedure */ +#define CI_LDISC 23 /* Link-Discriminator */ +#define CI_LCPAUTH 24 /* LCP Authentication */ +#define CI_COBS 25 /* Consistent Overhead Byte Stuffing */ +#define CI_PREFELIS 26 /* Prefix Elision */ +#define CI_MPHDRFMT 27 /* MP Header Format */ +#define CI_I18N 28 /* Internationalization */ +#define CI_SDL 29 /* Simple Data Link */ + +/* + * LCP-specific packet types (code numbers). + */ +#define PROTREJ 8 /* Protocol Reject */ +#define ECHOREQ 9 /* Echo Request */ +#define ECHOREP 10 /* Echo Reply */ +#define DISCREQ 11 /* Discard Request */ +#define IDENTIF 12 /* Identification */ +#define TIMEREM 13 /* Time Remaining */ + +/* Value used as data for CI_CALLBACK option */ +#define CBCP_OPT 6 /* Use callback control protocol */ + +#define DEFMRU 1500 /* Try for this */ +#define MINMRU 128 /* No MRUs below this */ +#define MAXMRU 16384 /* Normally limit MRU to this */ + +/* An endpoint discriminator, used with multilink. */ +#define MAX_ENDP_LEN 20 /* maximum length of discriminator value */ +struct epdisc { + unsigned char class_; /* -- The word "class" is reserved in C++. */ + unsigned char length; + unsigned char value[MAX_ENDP_LEN]; +}; + +/* + * The state of options is described by an lcp_options structure. + */ +typedef struct lcp_options { + unsigned int passive :1; /* Don't die if we don't get a response */ + unsigned int silent :1; /* Wait for the other end to start first */ + unsigned int restart :1; /* Restart vs. exit after close */ + unsigned int neg_mru :1; /* Negotiate the MRU? */ + unsigned int neg_asyncmap :1; /* Negotiate the async map? */ +#if PAP_SUPPORT + unsigned int neg_upap :1; /* Ask for UPAP authentication? */ +#else + unsigned int :1; /* 1 bit of padding */ +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + unsigned int neg_chap :1; /* Ask for CHAP authentication? */ +#else + unsigned int :1; /* 1 bit of padding */ +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + unsigned int neg_eap :1; /* Ask for EAP authentication? */ +#else + unsigned int :1; /* 1 bit of padding */ +#endif /* EAP_SUPPORT */ + unsigned int neg_magicnumber :1; /* Ask for magic number? */ + unsigned int neg_pcompression :1; /* HDLC Protocol Field Compression? */ + unsigned int neg_accompression :1; /* HDLC Address/Control Field Compression? */ +#if LQR_SUPPORT + unsigned int neg_lqr :1; /* Negotiate use of Link Quality Reports */ +#else + unsigned int :1; /* 1 bit of padding */ +#endif /* LQR_SUPPORT */ + unsigned int neg_cbcp :1; /* Negotiate use of CBCP */ +#ifdef HAVE_MULTILINK + unsigned int neg_mrru :1; /* negotiate multilink MRRU */ +#else + unsigned int :1; /* 1 bit of padding */ +#endif /* HAVE_MULTILINK */ + unsigned int neg_ssnhf :1; /* negotiate short sequence numbers */ + unsigned int neg_endpoint :1; /* negotiate endpoint discriminator */ + u16_t mru; /* Value of MRU */ +#ifdef HAVE_MULTILINK + u16_t mrru; /* Value of MRRU, and multilink enable */ +#endif /* MULTILINK */ +#if CHAP_SUPPORT + u8_t chap_mdtype; /* which MD types (hashing algorithm) */ +#endif /* CHAP_SUPPORT */ + u32_t asyncmap; /* Value of async map */ + u32_t magicnumber; + u8_t numloops; /* Number of loops during magic number neg. */ +#if LQR_SUPPORT + u32_t lqr_period; /* Reporting period for LQR 1/100ths second */ +#endif /* LQR_SUPPORT */ + struct epdisc endpoint; /* endpoint discriminator */ +} lcp_options; + +void lcp_open(ppp_pcb *pcb); +void lcp_close(ppp_pcb *pcb, const char *reason); +void lcp_lowerup(ppp_pcb *pcb); +void lcp_lowerdown(ppp_pcb *pcb); +void lcp_sprotrej(ppp_pcb *pcb, u_char *p, int len); /* send protocol reject */ + +extern const struct protent lcp_protent; + +#if 0 /* moved to opt.h */ +/* Default number of times we receive our magic number from the peer + before deciding the link is looped-back. */ +#define DEFLOOPBACKFAIL 10 +#endif /* moved to opt.h */ + +#endif /* LCP_H */ +#endif /* PPP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/magic.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/magic.h new file mode 100644 index 0000000..4661dea --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/magic.h @@ -0,0 +1,119 @@ +/* + * magic.h - PPP Magic Number definitions. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. 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. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: magic.h,v 1.5 2003/06/11 23:56:26 paulus Exp $ + */ +/***************************************************************************** +* randm.h - Random number generator header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* Copyright (c) 1998 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 98-05-29 Guy Lancaster , Global Election Systems Inc. +* Extracted from avos. +*****************************************************************************/ + +#include "lwip/opt.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef MAGIC_H +#define MAGIC_H + +/*********************** +*** PUBLIC FUNCTIONS *** +***********************/ + +/* + * Initialize the random number generator. + */ +void magic_init(void); + +/* + * Randomize our random seed value. To be called for truely random events + * such as user operations and network traffic. + */ +void magic_randomize(void); + +/* + * Return a new random number. + */ +u32_t magic(void); /* Returns the next magic number */ + +#if PPP_MD5_RANDM +/* + * Fill buffer with random bytes + * + * Use the random pool to generate random data. This degrades to pseudo + * random when used faster than randomness is supplied using magic_churnrand(). + * Thus it's important to make sure that the results of this are not + * published directly because one could predict the next result to at + * least some degree. Also, it's important to get a good seed before + * the first use. + */ +void random_bytes(unsigned char *buf, u32_t len); +#endif /* PPP_MD5_RANDM */ + +#endif /* MAGIC_H */ + +#endif /* PPP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/polarssl/des.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/polarssl/des.h new file mode 100644 index 0000000..86417cd --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/polarssl/des.h @@ -0,0 +1,92 @@ +/** + * \file des.h + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the names of PolarSSL or XySSL 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 HOLDERS 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 + * OWNER 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. + */ + +#include "lwip/opt.h" +#if LWIP_INCLUDED_POLARSSL_DES + +#ifndef LWIP_INCLUDED_POLARSSL_DES_H +#define LWIP_INCLUDED_POLARSSL_DES_H + +#define DES_ENCRYPT 1 +#define DES_DECRYPT 0 + +/** + * \brief DES context structure + */ +typedef struct +{ + int mode; /*!< encrypt/decrypt */ + unsigned long sk[32]; /*!< DES subkeys */ +} +des_context; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief DES key schedule (56-bit, encryption) + * + * \param ctx DES context to be initialized + * \param key 8-byte secret key + */ +void des_setkey_enc( des_context *ctx, unsigned char key[8] ); + +/** + * \brief DES key schedule (56-bit, decryption) + * + * \param ctx DES context to be initialized + * \param key 8-byte secret key + */ +void des_setkey_dec( des_context *ctx, unsigned char key[8] ); + +/** + * \brief DES-ECB block encryption/decryption + * + * \param ctx DES context + * \param input 64-bit input block + * \param output 64-bit output block + */ +void des_crypt_ecb( des_context *ctx, + unsigned char input[8], + unsigned char output[8] ); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_INCLUDED_POLARSSL_DES_H */ + +#endif /* LWIP_INCLUDED_POLARSSL_DES */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/polarssl/md4.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/polarssl/md4.h new file mode 100644 index 0000000..46ebf5c --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/polarssl/md4.h @@ -0,0 +1,97 @@ +/** + * \file md4.h + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the names of PolarSSL or XySSL 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 HOLDERS 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 + * OWNER 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. + */ + +#include "lwip/opt.h" +#if LWIP_INCLUDED_POLARSSL_MD4 + +#ifndef LWIP_INCLUDED_POLARSSL_MD4_H +#define LWIP_INCLUDED_POLARSSL_MD4_H + +/** + * \brief MD4 context structure + */ +typedef struct +{ + unsigned long total[2]; /*!< number of bytes processed */ + unsigned long state[4]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ +} +md4_context; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MD4 context setup + * + * \param ctx context to be initialized + */ +void md4_starts( md4_context *ctx ); + +/** + * \brief MD4 process buffer + * + * \param ctx MD4 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void md4_update( md4_context *ctx, unsigned char *input, int ilen ); + +/** + * \brief MD4 final digest + * + * \param ctx MD4 context + * \param output MD4 checksum result + */ +void md4_finish( md4_context *ctx, unsigned char output[16] ); + +/** + * \brief Output = MD4( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD4 checksum result + */ +void md4( unsigned char *input, int ilen, unsigned char output[16] ); + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_INCLUDED_POLARSSL_MD4_H */ + +#endif /* LWIP_INCLUDED_POLARSSL_MD4 */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/polarssl/md5.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/polarssl/md5.h new file mode 100644 index 0000000..3587b4c --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/polarssl/md5.h @@ -0,0 +1,96 @@ +/** + * \file md5.h + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the names of PolarSSL or XySSL 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 HOLDERS 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 + * OWNER 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. + */ + +#include "lwip/opt.h" +#if LWIP_INCLUDED_POLARSSL_MD5 + +#ifndef LWIP_INCLUDED_POLARSSL_MD5_H +#define LWIP_INCLUDED_POLARSSL_MD5_H + +/** + * \brief MD5 context structure + */ +typedef struct +{ + unsigned long total[2]; /*!< number of bytes processed */ + unsigned long state[4]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ +} +md5_context; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MD5 context setup + * + * \param ctx context to be initialized + */ +void md5_starts( md5_context *ctx ); + +/** + * \brief MD5 process buffer + * + * \param ctx MD5 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void md5_update( md5_context *ctx, unsigned char *input, int ilen ); + +/** + * \brief MD5 final digest + * + * \param ctx MD5 context + * \param output MD5 checksum result + */ +void md5_finish( md5_context *ctx, unsigned char output[16] ); + +/** + * \brief Output = MD5( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD5 checksum result + */ +void md5( unsigned char *input, int ilen, unsigned char output[16] ); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_INCLUDED_POLARSSL_MD5_H */ + +#endif /* LWIP_INCLUDED_POLARSSL_MD5 */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/polarssl/sha1.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/polarssl/sha1.h new file mode 100644 index 0000000..9d33163 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/polarssl/sha1.h @@ -0,0 +1,96 @@ +/** + * \file sha1.h + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the names of PolarSSL or XySSL 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 HOLDERS 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 + * OWNER 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. + */ + +#include "lwip/opt.h" +#if LWIP_INCLUDED_POLARSSL_SHA1 + +#ifndef LWIP_INCLUDED_POLARSSL_SHA1_H +#define LWIP_INCLUDED_POLARSSL_SHA1_H + +/** + * \brief SHA-1 context structure + */ +typedef struct +{ + unsigned long total[2]; /*!< number of bytes processed */ + unsigned long state[5]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ +} +sha1_context; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief SHA-1 context setup + * + * \param ctx context to be initialized + */ +void sha1_starts( sha1_context *ctx ); + +/** + * \brief SHA-1 process buffer + * + * \param ctx SHA-1 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void sha1_update( sha1_context *ctx, unsigned char *input, int ilen ); + +/** + * \brief SHA-1 final digest + * + * \param ctx SHA-1 context + * \param output SHA-1 checksum result + */ +void sha1_finish( sha1_context *ctx, unsigned char output[20] ); + +/** + * \brief Output = SHA-1( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output SHA-1 checksum result + */ +void sha1( unsigned char *input, int ilen, unsigned char output[20] ); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_INCLUDED_POLARSSL_SHA1_H */ + +#endif /* LWIP_INCLUDED_POLARSSL_SHA1 */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/ppp.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/ppp.h new file mode 100644 index 0000000..ed60536 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/ppp.h @@ -0,0 +1,644 @@ +/***************************************************************************** +* ppp.h - Network Point to Point Protocol header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-11-05 Guy Lancaster , Global Election Systems Inc. +* Original derived from BSD codes. +*****************************************************************************/ + +#include "lwip/opt.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef PPP_H +#define PPP_H + +#include "lwip/def.h" +#include "lwip/stats.h" +#include "lwip/mem.h" +#include "lwip/netif.h" +#include "lwip/sys.h" +#include "lwip/sio.h" +#include "lwip/timers.h" +#if PPP_IPV6_SUPPORT +#include "lwip/ip6_addr.h" +#endif /* PPP_IPV6_SUPPORT */ + +/* Disable non-working or rarely used PPP feature, so rarely that we don't want to bloat opt.h with them */ +#ifndef PPP_OPTIONS +#define PPP_OPTIONS 0 +#endif + +#ifndef PPP_NOTIFY +#define PPP_NOTIFY 0 +#endif + +#ifndef PPP_REMOTENAME +#define PPP_REMOTENAME 0 +#endif + +#ifndef PPP_IDLETIMELIMIT +#define PPP_IDLETIMELIMIT 0 +#endif + +#ifndef PPP_LCP_ADAPTIVE +#define PPP_LCP_ADAPTIVE 0 +#endif + +#ifndef PPP_MAXCONNECT +#define PPP_MAXCONNECT 0 +#endif + +#ifndef PPP_ALLOWED_ADDRS +#define PPP_ALLOWED_ADDRS 0 +#endif + +#ifndef PPP_PROTOCOLNAME +#define PPP_PROTOCOLNAME 0 +#endif + +#ifndef PPP_STATS_SUPPORT +#define PPP_STATS_SUPPORT 0 +#endif + + +/************************* +*** PUBLIC DEFINITIONS *** +*************************/ + +/* + * The basic PPP frame. + */ +#define PPP_HDRLEN 4 /* octets for standard ppp header */ +#define PPP_FCSLEN 2 /* octets for FCS */ + +/* + * Values for phase. + */ +#define PPP_PHASE_DEAD 0 +#define PPP_PHASE_INITIALIZE 1 +#define PPP_PHASE_SERIALCONN 2 +#define PPP_PHASE_DORMANT 3 +#define PPP_PHASE_ESTABLISH 4 +#define PPP_PHASE_AUTHENTICATE 5 +#define PPP_PHASE_CALLBACK 6 +#define PPP_PHASE_NETWORK 7 +#define PPP_PHASE_RUNNING 8 +#define PPP_PHASE_TERMINATE 9 +#define PPP_PHASE_DISCONNECT 10 +#define PPP_PHASE_HOLDOFF 11 +#define PPP_PHASE_MASTER 12 + +/* Error codes. */ +#define PPPERR_NONE 0 /* No error. */ +#define PPPERR_PARAM 1 /* Invalid parameter. */ +#define PPPERR_OPEN 2 /* Unable to open PPP session. */ +#define PPPERR_DEVICE 3 /* Invalid I/O device for PPP. */ +#define PPPERR_ALLOC 4 /* Unable to allocate resources. */ +#define PPPERR_USER 5 /* User interrupt. */ +#define PPPERR_CONNECT 6 /* Connection lost. */ +#define PPPERR_AUTHFAIL 7 /* Failed authentication challenge. */ +#define PPPERR_PROTOCOL 8 /* Failed to meet protocol. */ +#define PPPERR_PEERDEAD 9 /* Connection timeout */ +#define PPPERR_IDLETIMEOUT 10 /* Idle Timeout */ +#define PPPERR_CONNECTTIME 11 /* Max connect time reached */ +#define PPPERR_LOOPBACK 12 /* Loopback detected */ + +/* + * PPP IOCTL commands. + */ +/* + * Get the up status - 0 for down, non-zero for up. The argument must + * point to an int. + */ +#define PPPCTLG_UPSTATUS 100 /* Get the up status - 0 down else up */ +#define PPPCTLS_ERRCODE 101 /* Set the error code */ +#define PPPCTLG_ERRCODE 102 /* Get the error code */ +#define PPPCTLG_FD 103 /* Get the fd associated with the ppp */ + +/************************ +*** PUBLIC DATA TYPES *** +************************/ + +/* + * Other headers require ppp_pcb definition for prototypes, but ppp_pcb + * require some structure definition from other headers as well, we are + * fixing the dependency loop here by declaring the ppp_pcb type then + * by including headers containing necessary struct definition for ppp_pcb + */ +typedef struct ppp_pcb_s ppp_pcb; + +/* Type definitions for BSD code. */ +#ifndef __u_char_defined +typedef unsigned long u_long; +typedef unsigned int u_int; +typedef unsigned short u_short; +typedef unsigned char u_char; +#endif + +#include "fsm.h" +#include "lcp.h" +#include "ipcp.h" +#if PPP_IPV6_SUPPORT +#include "ipv6cp.h" +#endif /* PPP_IPV6_SUPPORT */ +#if PAP_SUPPORT +#include "upap.h" +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT +#include "chap-new.h" +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT +#include "eap.h" +#endif /* EAP_SUPPORT */ +#if VJ_SUPPORT +#include "vj.h" +#endif /* VJ_SUPPORT */ + +#if PPPOE_SUPPORT +#include "netif/ppp/pppoe.h" +#endif /* PPPOE_SUPPORT */ +#if PPPOL2TP_SUPPORT +#include "netif/ppp/pppol2tp.h" +#endif /* PPPOL2TP_SUPPORT */ + +/* + * PPP configuration. + */ +typedef struct ppp_settings_s { + +#if PPP_SERVER + unsigned int auth_required : 1; /* Peer is required to authenticate */ + unsigned int null_login : 1; /* Username of "" and a password of "" are acceptable */ +#else + unsigned int :2; /* 2 bits of padding */ +#endif /* PPP_SERVER */ +#if PPP_REMOTENAME + unsigned int explicit_remote : 1; /* remote_name specified with remotename opt */ +#else + unsigned int :1; /* 1 bit of padding */ +#endif /* PPP_REMOTENAME */ +#if PAP_SUPPORT + unsigned int refuse_pap : 1; /* Don't wanna auth. ourselves with PAP */ +#else + unsigned int :1; /* 1 bit of padding */ +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + unsigned int refuse_chap : 1; /* Don't wanna auth. ourselves with CHAP */ +#else + unsigned int :1; /* 1 bit of padding */ +#endif /* CHAP_SUPPORT */ +#if MSCHAP_SUPPORT + unsigned int refuse_mschap : 1; /* Don't wanna auth. ourselves with MS-CHAP */ + unsigned int refuse_mschap_v2 : 1; /* Don't wanna auth. ourselves with MS-CHAPv2 */ +#else + unsigned int :2; /* 2 bits of padding */ +#endif /* MSCHAP_SUPPORT */ +#if EAP_SUPPORT + unsigned int refuse_eap : 1; /* Don't wanna auth. ourselves with EAP */ +#else + unsigned int :1; /* 1 bit of padding */ +#endif /* EAP_SUPPORT */ + unsigned int usepeerdns : 1; /* Ask peer for DNS adds */ + unsigned int persist : 1; /* Persist mode, always try to reopen the connection */ +#if PRINTPKT_SUPPORT + unsigned int hide_password : 1; /* Hide password in dumped packets */ +#else + unsigned int :1; /* 1 bit of padding */ +#endif /* PRINTPKT_SUPPORT */ + unsigned int noremoteip : 1; /* Let him have no IP address */ + unsigned int lax_recv : 1; /* accept control chars in asyncmap */ + unsigned int noendpoint : 1; /* don't send/accept endpoint discriminator */ +#if PPP_LCP_ADAPTIVE + unsigned int lcp_echo_adaptive : 1; /* request echo only if the link was idle */ +#else + unsigned int :1; /* 1 bit of padding */ +#endif + unsigned int :1; /* 1 bit of padding to round out to 16 bits */ + + u16_t listen_time; /* time to listen first (ms), waiting for peer to send LCP packet */ + +#if PPP_IDLETIMELIMIT + u16_t idle_time_limit; /* Disconnect if idle for this many seconds */ +#endif /* PPP_IDLETIMELIMIT */ +#if PPP_MAXCONNECT + u32_t maxconnect; /* Maximum connect time (seconds) */ +#endif /* PPP_MAXCONNECT */ + + /* auth data */ + const char *user; /* Username for PAP */ + const char *passwd; /* Password for PAP, secret for CHAP */ +#if PPP_SERVER + char our_name [MAXNAMELEN + 1]; /* Our name for authentication purposes */ +#endif /* PPP_SERVER */ +#if PPP_REMOTENAME + char remote_name[MAXNAMELEN + 1]; /* Peer's name for authentication */ +#endif /* PPP_REMOTENAME */ + +#if PAP_SUPPORT + u8_t pap_timeout_time; /* Timeout (seconds) for auth-req retrans. */ + u8_t pap_max_transmits; /* Number of auth-reqs sent */ +#if PPP_SERVER + u8_t pap_req_timeout; /* Time to wait for auth-req from peer */ +#endif /* PPP_SERVER */ +#endif /* PAP_SUPPPORT */ + +#if CHAP_SUPPORT + u8_t chap_timeout_time; /* Timeout (seconds) for retransmitting req */ + u8_t chap_max_transmits; /* max # times to send challenge */ +#if PPP_SERVER + u8_t chap_rechallenge_time; /* Time to wait for auth-req from peer */ +#endif /* PPP_SERVER */ +#endif /* CHAP_SUPPPORT */ + +#if EAP_SUPPORT + u8_t eap_req_time; /* Time to wait (for retransmit/fail) */ + u8_t eap_allow_req; /* Max Requests allowed */ +#if PPP_SERVER + u8_t eap_timeout_time; /* Time to wait (for retransmit/fail) */ + u8_t eap_max_transmits; /* Max Requests allowed */ +#endif /* PPP_SERVER */ +#endif /* EAP_SUPPORT */ + + u8_t fsm_timeout_time; /* Timeout time in seconds */ + u8_t fsm_max_conf_req_transmits; /* Maximum Configure-Request transmissions */ + u8_t fsm_max_term_transmits; /* Maximum Terminate-Request transmissions */ + u8_t fsm_max_nak_loops; /* Maximum number of nak loops tolerated */ + + u8_t lcp_loopbackfail; /* Number of times we receive our magic number from the peer + before deciding the link is looped-back. */ + u8_t lcp_echo_interval; /* Interval between LCP echo-requests */ + u8_t lcp_echo_fails; /* Tolerance to unanswered echo-requests */ + +} ppp_settings; + +struct ppp_addrs { + ip_addr_t our_ipaddr, his_ipaddr, netmask; + ip_addr_t dns1, dns2; +#if PPP_IPV6_SUPPORT + ip6_addr_t our6_ipaddr, his6_ipaddr; +#endif /* PPP_IPV6_SUPPORT */ +}; + +/* FIXME: find a way to move ppp_dev_states and ppp_pcb_rx_s to ppp_impl.h */ +#if PPPOS_SUPPORT +/* + * Extended asyncmap - allows any character to be escaped. + */ +typedef u_char ext_accm[32]; + +/* PPP packet parser states. Current state indicates operation yet to be + * completed. */ +typedef enum { + PDIDLE = 0, /* Idle state - waiting. */ + PDSTART, /* Process start flag. */ + PDADDRESS, /* Process address field. */ + PDCONTROL, /* Process control field. */ + PDPROTOCOL1, /* Process protocol field 1. */ + PDPROTOCOL2, /* Process protocol field 2. */ + PDDATA /* Process data byte. */ +} ppp_dev_states; + +/* + * PPP interface RX control block. + */ +typedef struct ppp_pcb_rx_s { + /** ppp descriptor */ + ppp_pcb *pcb; + /** the rx file descriptor */ + sio_fd_t fd; + + /* The input packet. */ + struct pbuf *in_head, *in_tail; + + u16_t in_protocol; /* The input protocol code. */ + u16_t in_fcs; /* Input Frame Check Sequence value. */ + ppp_dev_states in_state; /* The input process state. */ + char in_escaped; /* Escape next character. */ + ext_accm in_accm; /* Async-Ctl-Char-Map for input. */ +} ppp_pcb_rx; +#endif /* PPPOS_SUPPORT */ + +/* + * PPP interface control block. + */ +struct ppp_pcb_s { + /* -- below are data that will NOT be cleared between two sessions */ +#if PPP_DEBUG + u8_t num; /* Interface number - only useful for debugging */ +#endif /* PPP_DEBUG */ + ppp_settings settings; +#if PPPOS_SUPPORT + sio_fd_t fd; /* File device ID of port. */ +#endif /* PPPOS_SUPPORT */ +#if PPPOE_SUPPORT + struct pppoe_softc *pppoe_sc; +#endif /* PPPOE_SUPPORT */ +#if PPPOL2TP_SUPPORT + pppol2tp_pcb *l2tp_pcb; +#endif /* PPPOL2TP_SUPPORT */ + void (*link_status_cb)(ppp_pcb *pcb, int err_code, void *ctx); /* Status change callback */ +#if PPP_NOTIFY_PHASE + void (*notify_phase_cb)(ppp_pcb *pcb, u8_t phase, void *ctx); /* Notify phase callback */ +#endif /* PPP_NOTIFY_PHASE */ + void *ctx_cb; /* Callbacks optional pointer */ + struct netif netif; /* PPP interface */ + + /* -- below are data that will be cleared between two sessions */ + + /* + * phase must be the first member of cleared members, because it is used to know + * which part must not be cleared. + */ + u8_t phase; /* where the link is at */ + u8_t err_code; /* Code indicating why interface is down. */ + + /* flags */ + unsigned int if_up :1; /* True when the interface is up. */ +#if PPP_IPV6_SUPPORT + unsigned int if6_up :1; /* True when the IPv6 interface is up. */ +#else + unsigned int :1; /* 1 bit of padding */ +#endif /* PPP_IPV6_SUPPORT */ + unsigned int pcomp :1; /* Does peer accept protocol compression? */ + unsigned int accomp :1; /* Does peer accept addr/ctl compression? */ + unsigned int proxy_arp_set :1; /* Have created proxy arp entry */ + unsigned int ipcp_is_open :1; /* haven't called np_finished() */ + unsigned int ipcp_is_up :1; /* have called ipcp_up() */ +#if PPP_IPV6_SUPPORT + unsigned int ipv6cp_is_up :1; /* have called ip6cp_up() */ +#else + unsigned int :1; /* 1 bit of padding */ +#endif /* PPP_IPV6_SUPPORT */ + unsigned int ask_for_local :1; /* request our address from peer */ + unsigned int lcp_echo_timer_running :1; /* set if a timer is running */ +#if PPPOS_SUPPORT && VJ_SUPPORT + unsigned int vj_enabled :1; /* Flag indicating VJ compression enabled. */ +#else + unsigned int :1; /* 1 bit of padding */ +#endif /* PPPOS_SUPPORT && VJ_SUPPORT */ + unsigned int :5; /* 5 bits of padding to round out to 16 bits */ + +#if PPPOS_SUPPORT +/* FIXME: there is probably one superfluous */ + ext_accm out_accm; /* Async-Ctl-Char-Map for output. */ + ext_accm xmit_accm; /* extended transmit ACCM */ + ppp_pcb_rx rx; +#if VJ_SUPPORT + struct vjcompress vj_comp; /* Van Jacobson compression header. */ +#endif /* VJ_SUPPORT */ +#endif /* PPPOS_SUPPORT */ + + u32_t last_xmit; /* Time of last transmission. */ + + struct ppp_addrs addrs; /* PPP addresses */ + + /* auth data */ +#if PPP_SERVER + char peer_authname[MAXNAMELEN + 1]; /* The name by which the peer authenticated itself to us. */ +#endif /* PPP_SERVER */ + u16_t auth_pending; /* Records which authentication operations haven't completed yet. */ + u16_t auth_done; /* Records which authentication operations have been completed. */ + u8_t num_np_open; /* Number of network protocols which we have opened. */ + u8_t num_np_up; /* Number of network protocols which have come up. */ + +#if PAP_SUPPORT + upap_state upap; /* PAP data */ +#endif /* PAP_SUPPORT */ + +#if CHAP_SUPPORT + chap_client_state chap_client; /* CHAP client data */ +#if PPP_SERVER + chap_server_state chap_server; /* CHAP server data */ +#endif /* PPP_SERVER */ +#endif /* CHAP_SUPPORT */ + +#if EAP_SUPPORT + eap_state eap; /* EAP data */ +#endif /* EAP_SUPPORT */ + + fsm lcp_fsm; /* LCP fsm structure */ + lcp_options lcp_wantoptions; /* Options that we want to request */ + lcp_options lcp_gotoptions; /* Options that peer ack'd */ + lcp_options lcp_allowoptions; /* Options we allow peer to request */ + lcp_options lcp_hisoptions; /* Options that we ack'd */ + u8_t lcp_echos_pending; /* Number of outstanding echo msgs */ + u8_t lcp_echo_number; /* ID number of next echo frame */ + u16_t peer_mru; /* currently negotiated peer MRU */ + + fsm ipcp_fsm; /* IPCP fsm structure */ + ipcp_options ipcp_wantoptions; /* Options that we want to request */ + ipcp_options ipcp_gotoptions; /* Options that peer ack'd */ + ipcp_options ipcp_allowoptions; /* Options we allow peer to request */ + ipcp_options ipcp_hisoptions; /* Options that we ack'd */ + +#if PPP_IPV6_SUPPORT + fsm ipv6cp_fsm; /* IPV6CP fsm structure */ + ipv6cp_options ipv6cp_wantoptions; /* Options that we want to request */ + ipv6cp_options ipv6cp_gotoptions; /* Options that peer ack'd */ + ipv6cp_options ipv6cp_allowoptions; /* Options we allow peer to request */ + ipv6cp_options ipv6cp_hisoptions; /* Options that we ack'd */ +#endif /* PPP_IPV6_SUPPORT */ +}; + +/************************ + *** PUBLIC FUNCTIONS *** + ************************/ + +/* + * Create a new PPP session. + * + * This initializes the PPP control block but does not + * attempt to negotiate the LCP session. + * + * Return a new PPP connection control block pointer + * on success or a null pointer on failure. + */ +ppp_pcb *ppp_new(void); + +/* + * Set a PPP interface as the default network interface + * (used to output all packets for which no specific route is found). + */ +void ppp_set_default(ppp_pcb *pcb); + +/* + * Set auth helper, optional, you can either fill ppp_pcb->settings. + * + * Warning: Using PPPAUTHTYPE_ANY might have security consequences. + * RFC 1994 says: + * + * In practice, within or associated with each PPP server, there is a + * database which associates "user" names with authentication + * information ("secrets"). It is not anticipated that a particular + * named user would be authenticated by multiple methods. This would + * make the user vulnerable to attacks which negotiate the least secure + * method from among a set (such as PAP rather than CHAP). If the same + * secret was used, PAP would reveal the secret to be used later with + * CHAP. + * + * Instead, for each user name there should be an indication of exactly + * one method used to authenticate that user name. If a user needs to + * make use of different authentication methods under different + * circumstances, then distinct user names SHOULD be employed, each of + * which identifies exactly one authentication method. + * + */ +#define PPPAUTHTYPE_NONE 0x00 +#define PPPAUTHTYPE_PAP 0x01 +#define PPPAUTHTYPE_CHAP 0x02 +#define PPPAUTHTYPE_MSCHAP 0x04 +#define PPPAUTHTYPE_EAP 0x08 +#define PPPAUTHTYPE_ANY 0xff + +void ppp_set_auth(ppp_pcb *pcb, u8_t authtype, const char *user, const char *passwd); + +#if PPP_NOTIFY_PHASE +/* + * Set a PPP notify phase callback. + * + * This can be used for example to set a LED pattern depending on the + * current phase of the PPP session. + */ +typedef void (*ppp_notify_phase_cb_fn)(ppp_pcb *pcb, u8_t phase, void *ctx); +void ppp_set_notify_phase_callback(ppp_pcb *pcb, ppp_notify_phase_cb_fn notify_phase_cb); +#endif /* PPP_NOTIFY_PHASE */ + +/* Link status callback function prototype */ +typedef void (*ppp_link_status_cb_fn)(ppp_pcb *pcb, int err_code, void *ctx); + +#if PPPOS_SUPPORT +/* + * Create a new PPP connection using the given serial I/O device. + * + * If this port connects to a modem, the modem connection must be + * established before calling this. + * + * Return 0 on success, an error code on failure. + */ +int ppp_over_serial_create(ppp_pcb *pcb, sio_fd_t fd, ppp_link_status_cb_fn link_status_cb, void *ctx_cb); +#endif /* PPPOS_SUPPORT */ + +#if PPPOE_SUPPORT +/* + * Create a new PPP Over Ethernet (PPPoE) connection. + * + * Return 0 on success, an error code on failure. + */ +int ppp_over_ethernet_create(ppp_pcb *pcb, struct netif *ethif, const char *service_name, const char *concentrator_name, + ppp_link_status_cb_fn link_status_cb, void *ctx_cb); +#endif /* PPPOE_SUPPORT */ + +#if PPPOL2TP_SUPPORT +/* + * Create a new PPP Over L2TP (PPPoL2TP) connection. + */ +int ppp_over_l2tp_create(ppp_pcb *pcb, struct netif *netif, ip_addr_t *ipaddr, u16_t port, + u8_t *secret, u8_t secret_len, + ppp_link_status_cb_fn link_status_cb, void *ctx_cb); +#endif /* PPPOL2TP_SUPPORT */ + +/* + * Open a PPP connection. + * + * This can only be called if PPP is in the dead phase. + * + * Holdoff is the time to wait (in seconds) before initiating + * the connection. + */ +int ppp_open(ppp_pcb *pcb, u16_t holdoff); + +/* + * Initiate the end of a PPP connection. + * Any outstanding packets in the queues are dropped. + * Return 0 on success, an error code on failure. + */ +int ppp_close(ppp_pcb *pcb); + +/* + * Indicate to the PPP stack that the line has disconnected. + */ +void ppp_sighup(ppp_pcb *pcb); + +/* + * Free the control block, clean everything except the PPP PCB itself + * and the netif, it allows you to change the underlying PPP protocol + * (eg. from PPPoE to PPPoS to switch from DSL to GPRS) without losing + * your PPP and netif handlers. + * + * This can only be called if PPP is in the dead phase. + * + * You must use ppp_close() before if you wish to terminate + * an established PPP session. + * + * Return 0 on success, an error code on failure. + */ +int ppp_free(ppp_pcb *pcb); + +/* + * Release the control block. + * + * This can only be called if PPP is in the dead phase. + * + * You must use ppp_close() before if you wish to terminate + * an established PPP session. + * + * Return 0 on success, an error code on failure. + */ +int ppp_delete(ppp_pcb *pcb); + +/* + * Get and set parameters for the given connection. + * Return 0 on success, an error code on failure. + */ +int ppp_ioctl(ppp_pcb *pcb, int cmd, void *arg); + +#if PPPOS_SUPPORT +/* + * PPP over Serial: this is the input function to be called for received data. + */ +void pppos_input(ppp_pcb *pcb, u_char* data, int len); +#endif /* PPPOS_SUPPORT */ + +/* Get the PPP netif interface */ +#define ppp_netif(ppp) (&(ppp)->netif) + +/* Get the PPP addresses */ +#define ppp_addrs(ppp) (&(ppp)->addrs) + +#if LWIP_NETIF_STATUS_CALLBACK +/* Set an lwIP-style status-callback for the selected PPP device */ +void ppp_set_netif_statuscallback(ppp_pcb *pcb, netif_status_callback_fn status_callback); +#endif /* LWIP_NETIF_STATUS_CALLBACK */ +#if LWIP_NETIF_LINK_CALLBACK +/* Set an lwIP-style link-callback for the selected PPP device */ +void ppp_set_netif_linkcallback(ppp_pcb *pcb, netif_status_callback_fn link_callback); +#endif /* LWIP_NETIF_LINK_CALLBACK */ + +#endif /* PPP_H */ + +#endif /* PPP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/ppp_impl.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/ppp_impl.h new file mode 100644 index 0000000..9584871 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/ppp_impl.h @@ -0,0 +1,581 @@ +/***************************************************************************** +* ppp.h - Network Point to Point Protocol header file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-11-05 Guy Lancaster , Global Election Systems Inc. +* Original derived from BSD codes. +*****************************************************************************/ + +#include "lwip/opt.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef PPP_IMP_H_ +#define PPP_IMP_H_ + +#include /* formats */ +#include +#include +#include /* strtol() */ + +#include "lwip/netif.h" +#include "lwip/def.h" +#include "lwip/timers.h" + +#include "ppp.h" +#include "pppdebug.h" + +/* + * Memory used for control packets. + * + * PPP_CTRL_PBUF_MAX_SIZE is the amount of memory we allocate when we + * cannot figure out how much we are going to use before filling the buffer. + */ +#if PPP_USE_PBUF_RAM +#define PPP_CTRL_PBUF_TYPE PBUF_RAM +#define PPP_CTRL_PBUF_MAX_SIZE 512 +#else /* PPP_USE_PBUF_RAM */ +#define PPP_CTRL_PBUF_TYPE PBUF_POOL +#define PPP_CTRL_PBUF_MAX_SIZE PBUF_POOL_BUFSIZE +#endif /* PPP_USE_PBUF_RAM */ + +/* + * Limits. + */ +#define MAXWORDLEN 1024 /* max length of word in file (incl null) */ +#define MAXARGS 1 /* max # args to a command */ +#define MAXNAMELEN 256 /* max length of hostname or name for auth */ +#define MAXSECRETLEN 256 /* max length of password or secret */ + +/* + * The basic PPP frame. + */ +#define PPP_ADDRESS(p) (((u_char *)(p))[0]) +#define PPP_CONTROL(p) (((u_char *)(p))[1]) +#define PPP_PROTOCOL(p) ((((u_char *)(p))[2] << 8) + ((u_char *)(p))[3]) + +/* + * Significant octet values. + */ +#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */ +#define PPP_UI 0x03 /* Unnumbered Information */ +#define PPP_FLAG 0x7e /* Flag Sequence */ +#define PPP_ESCAPE 0x7d /* Asynchronous Control Escape */ +#define PPP_TRANS 0x20 /* Asynchronous transparency modifier */ + +/* + * Protocol field values. + */ +#define PPP_IP 0x21 /* Internet Protocol */ +#if 0 /* UNUSED */ +#define PPP_AT 0x29 /* AppleTalk Protocol */ +#define PPP_IPX 0x2b /* IPX protocol */ +#endif /* UNUSED */ +#if VJ_SUPPORT +#define PPP_VJC_COMP 0x2d /* VJ compressed TCP */ +#define PPP_VJC_UNCOMP 0x2f /* VJ uncompressed TCP */ +#endif /* VJ_SUPPORT */ +#if PPP_IPV6_SUPPORT +#define PPP_IPV6 0x57 /* Internet Protocol Version 6 */ +#endif /* PPP_IPV6_SUPPORT */ +#if CCP_SUPPORT +#define PPP_COMP 0xfd /* compressed packet */ +#endif /* CCP_SUPPORT */ +#define PPP_IPCP 0x8021 /* IP Control Protocol */ +#if 0 /* UNUSED */ +#define PPP_ATCP 0x8029 /* AppleTalk Control Protocol */ +#define PPP_IPXCP 0x802b /* IPX Control Protocol */ +#endif /* UNUSED */ +#if PPP_IPV6_SUPPORT +#define PPP_IPV6CP 0x8057 /* IPv6 Control Protocol */ +#endif /* PPP_IPV6_SUPPORT */ +#if CCP_SUPPORT +#define PPP_CCP 0x80fd /* Compression Control Protocol */ +#endif /* CCP_SUPPORT */ +#if ECP_SUPPORT +#define PPP_ECP 0x8053 /* Encryption Control Protocol */ +#endif /* ECP_SUPPORT */ +#define PPP_LCP 0xc021 /* Link Control Protocol */ +#if PAP_SUPPORT +#define PPP_PAP 0xc023 /* Password Authentication Protocol */ +#endif /* PAP_SUPPORT */ +#if LQR_SUPPORT +#define PPP_LQR 0xc025 /* Link Quality Report protocol */ +#endif /* LQR_SUPPORT */ +#if CHAP_SUPPORT +#define PPP_CHAP 0xc223 /* Cryptographic Handshake Auth. Protocol */ +#endif /* CHAP_SUPPORT */ +#if CBCP_SUPPORT +#define PPP_CBCP 0xc029 /* Callback Control Protocol */ +#endif /* CBCP_SUPPORT */ +#if EAP_SUPPORT +#define PPP_EAP 0xc227 /* Extensible Authentication Protocol */ +#endif /* EAP_SUPPORT */ + +/* + * Values for FCS calculations. + */ +#define PPP_INITFCS 0xffff /* Initial FCS value */ +#define PPP_GOODFCS 0xf0b8 /* Good final FCS value */ +#if PPP_FCS_TABLE + #define PPP_FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff]) +#else +u16_t ppp_get_fcs(u8_t byte); +#define PPP_FCS(fcs, c) (((fcs) >> 8) ^ ppp_get_fcs(((fcs) ^ (c)) & 0xff)) +#endif + + +/* + * What to do with network protocol (NP) packets. + */ +enum NPmode { + NPMODE_PASS, /* pass the packet through */ + NPMODE_DROP, /* silently drop the packet */ + NPMODE_ERROR, /* return an error */ + NPMODE_QUEUE /* save it up for later. */ +}; + +/* + * Statistics. + */ +#if PPP_STATS_SUPPORT +struct pppstat { + unsigned int ppp_ibytes; /* bytes received */ + unsigned int ppp_ipackets; /* packets received */ + unsigned int ppp_ierrors; /* receive errors */ + unsigned int ppp_obytes; /* bytes sent */ + unsigned int ppp_opackets; /* packets sent */ + unsigned int ppp_oerrors; /* transmit errors */ +}; + +#if VJ_SUPPORT +struct vjstat { + unsigned int vjs_packets; /* outbound packets */ + unsigned int vjs_compressed; /* outbound compressed packets */ + unsigned int vjs_searches; /* searches for connection state */ + unsigned int vjs_misses; /* times couldn't find conn. state */ + unsigned int vjs_uncompressedin; /* inbound uncompressed packets */ + unsigned int vjs_compressedin; /* inbound compressed packets */ + unsigned int vjs_errorin; /* inbound unknown type packets */ + unsigned int vjs_tossed; /* inbound packets tossed because of error */ +}; +#endif /* VJ_SUPPORT */ + +struct ppp_stats { + struct pppstat p; /* basic PPP statistics */ +#if VJ_SUPPORT + struct vjstat vj; /* VJ header compression statistics */ +#endif /* VJ_SUPPORT */ +}; + +#if CCP_SUPPORT +struct compstat { + unsigned int unc_bytes; /* total uncompressed bytes */ + unsigned int unc_packets; /* total uncompressed packets */ + unsigned int comp_bytes; /* compressed bytes */ + unsigned int comp_packets; /* compressed packets */ + unsigned int inc_bytes; /* incompressible bytes */ + unsigned int inc_packets; /* incompressible packets */ + unsigned int ratio; /* recent compression ratio << 8 */ +}; + +struct ppp_comp_stats { + struct compstat c; /* packet compression statistics */ + struct compstat d; /* packet decompression statistics */ +}; +#endif /* CCP_SUPPORT */ + +#endif /* PPP_STATS_SUPPORT */ + +#if PPP_IDLETIMELIMIT +/* + * The following structure records the time in seconds since + * the last NP packet was sent or received. + */ +struct ppp_idle { + time_t xmit_idle; /* time since last NP packet sent */ + time_t recv_idle; /* time since last NP packet received */ +}; +#endif /* PPP_IDLETIMELIMIT */ + +/* values for epdisc.class */ +#define EPD_NULL 0 /* null discriminator, no data */ +#define EPD_LOCAL 1 +#define EPD_IP 2 +#define EPD_MAC 3 +#define EPD_MAGIC 4 +#define EPD_PHONENUM 5 + +/* + * Global variables. + */ +#ifdef HAVE_MULTILINK +extern u8_t multilink; /* enable multilink operation */ +extern u8_t doing_multilink; +extern u8_t multilink_master; +extern u8_t bundle_eof; +extern u8_t bundle_terminating; +#endif + +#ifdef MAXOCTETS +extern unsigned int maxoctets; /* Maximum octetes per session (in bytes) */ +extern int maxoctets_dir; /* Direction : + 0 - in+out (default) + 1 - in + 2 - out + 3 - max(in,out) */ +extern int maxoctets_timeout; /* Timeout for check of octets limit */ +#define PPP_OCTETS_DIRECTION_SUM 0 +#define PPP_OCTETS_DIRECTION_IN 1 +#define PPP_OCTETS_DIRECTION_OUT 2 +#define PPP_OCTETS_DIRECTION_MAXOVERAL 3 +/* same as previos, but little different on RADIUS side */ +#define PPP_OCTETS_DIRECTION_MAXSESSION 4 +#endif + +/* + * The following struct gives the addresses of procedures to call + * for a particular protocol. + */ +struct protent { + u_short protocol; /* PPP protocol number */ + /* Initialization procedure */ + void (*init) (ppp_pcb *pcb); + /* Process a received packet */ + void (*input) (ppp_pcb *pcb, u_char *pkt, int len); + /* Process a received protocol-reject */ + void (*protrej) (ppp_pcb *pcb); + /* Lower layer has come up */ + void (*lowerup) (ppp_pcb *pcb); + /* Lower layer has gone down */ + void (*lowerdown) (ppp_pcb *pcb); + /* Open the protocol */ + void (*open) (ppp_pcb *pcb); + /* Close the protocol */ + void (*close) (ppp_pcb *pcb, const char *reason); +#if PRINTPKT_SUPPORT + /* Print a packet in readable form */ + int (*printpkt) (u_char *pkt, int len, + void (*printer) (void *, const char *, ...), + void *arg); +#endif /* PRINTPKT_SUPPORT */ + /* FIXME: data input is only used by CCP, which is not supported at this time, + * should we remove this entry and save some flash ? + */ + /* Process a received data packet */ + void (*datainput) (ppp_pcb *pcb, u_char *pkt, int len); + u8_t enabled_flag; /* 0 if protocol is disabled */ +#if PRINTPKT_SUPPORT + const char *name; /* Text name of protocol */ + const char *data_name; /* Text name of corresponding data protocol */ +#endif /* PRINTPKT_SUPPORT */ +#if PPP_OPTIONS + option_t *options; /* List of command-line options */ + /* Check requested options, assign defaults */ + void (*check_options) (void); +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT + /* Configure interface for demand-dial */ + int (*demand_conf) (int unit); + /* Say whether to bring up link for this pkt */ + int (*active_pkt) (u_char *pkt, int len); +#endif /* DEMAND_SUPPORT */ +}; + +/* Table of pointers to supported protocols */ +extern const struct protent* const protocols[]; + + +/* Values for auth_pending, auth_done */ +#if PAP_SUPPORT +#define PAP_WITHPEER 0x1 +#define PAP_PEER 0x2 +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT +#define CHAP_WITHPEER 0x4 +#define CHAP_PEER 0x8 +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT +#define EAP_WITHPEER 0x10 +#define EAP_PEER 0x20 +#endif /* EAP_SUPPORT */ + +/* Values for auth_done only */ +#if CHAP_SUPPORT +#define CHAP_MD5_WITHPEER 0x40 +#define CHAP_MD5_PEER 0x80 +#if MSCHAP_SUPPORT +#define CHAP_MS_SHIFT 8 /* LSB position for MS auths */ +#define CHAP_MS_WITHPEER 0x100 +#define CHAP_MS_PEER 0x200 +#define CHAP_MS2_WITHPEER 0x400 +#define CHAP_MS2_PEER 0x800 +#endif /* MSCHAP_SUPPORT */ +#endif /* CHAP_SUPPORT */ + +/* Supported CHAP protocols */ +#if CHAP_SUPPORT +#include "chap-new.h" +#if MSCHAP_SUPPORT +#define CHAP_MDTYPE_SUPPORTED (MDTYPE_MICROSOFT_V2 | MDTYPE_MICROSOFT | MDTYPE_MD5) +#else +#define CHAP_MDTYPE_SUPPORTED (MDTYPE_MD5) +#endif +#else +#define CHAP_MDTYPE_SUPPORTED (MDTYPE_NONE) +#endif + +#if PPP_STATS_SUPPORT +/* + * PPP statistics structure + */ +struct pppd_stats { + unsigned int bytes_in; + unsigned int bytes_out; + unsigned int pkts_in; + unsigned int pkts_out; +}; +#endif /* PPP_STATS_SUPPORT */ + + +/* PPP flow functions + */ +/* initialize the PPP subsystem */ +int ppp_init(void); + +/* function called by pppoe.c */ +void ppp_input(ppp_pcb *pcb, struct pbuf *pb); + +/* function called by all PPP subsystems to send packets */ +int ppp_write(ppp_pcb *pcb, struct pbuf *p); + +/* functions called by auth.c link_terminated() */ +void ppp_link_down(ppp_pcb *pcb); +void ppp_link_terminated(ppp_pcb *pcb); + +/* merge a pbuf chain into one pbuf */ +struct pbuf * ppp_singlebuf(struct pbuf *p); + + +/* Functions called by various PPP subsystems to configure + * the PPP interface or change the PPP phase. + */ +void new_phase(ppp_pcb *pcb, int p); + +#if PPPOS_SUPPORT +void ppp_set_xaccm(ppp_pcb *pcb, ext_accm *accm); +#endif /* PPPOS_SUPPORT */ +int ppp_send_config(ppp_pcb *pcb, int mtu, u32_t accm, int pcomp, int accomp); +int ppp_recv_config(ppp_pcb *pcb, int mru, u32_t accm, int pcomp, int accomp); + +int sifaddr(ppp_pcb *pcb, u32_t our_adr, u32_t his_adr, u32_t net_mask); +int cifaddr(ppp_pcb *pcb, u32_t our_adr, u32_t his_adr); + +#if PPP_IPV6_SUPPORT +int sif6addr(ppp_pcb *pcb, eui64_t our_eui64, eui64_t his_eui64); +int cif6addr(ppp_pcb *pcb, eui64_t our_eui64, eui64_t his_eui64); +#endif /* PPP_IPV6_SUPPORT */ + +int sdns(ppp_pcb *pcb, u32_t ns1, u32_t ns2); +int cdns(ppp_pcb *pcb, u32_t ns1, u32_t ns2); + +int sifup(ppp_pcb *pcb); +int sifdown (ppp_pcb *pcb); + +#if PPP_IPV6_SUPPORT +int sif6up(ppp_pcb *pcb); +int sif6down (ppp_pcb *pcb); +#endif /* PPP_IPV6_SUPPORT */ + +int sifnpmode(ppp_pcb *pcb, int proto, enum NPmode mode); + +void netif_set_mtu(ppp_pcb *pcb, int mtu); +int netif_get_mtu(ppp_pcb *pcb); + +int sifproxyarp(ppp_pcb *pcb, u32_t his_adr); +int cifproxyarp(ppp_pcb *pcb, u32_t his_adr); + +int sifvjcomp(ppp_pcb *pcb, int vjcomp, int cidcomp, int maxcid); + +#if PPP_IDLETIMELIMIT +int get_idle_time(ppp_pcb *pcb, struct ppp_idle *ip); +#endif /* PPP_IDLETIMELIMIT */ + +int get_loop_output(void); + +u32_t get_mask (u32_t addr); + + +/* Optional protocol names list, to make our messages a little more informative. */ +#if PPP_PROTOCOLNAME +const char * protocol_name(int proto); +#endif /* PPP_PROTOCOLNAME */ + + +/* Optional stats support, to get some statistics on the PPP interface */ +#if PPP_STATS_SUPPORT +void print_link_stats(void); /* Print stats, if available */ +void reset_link_stats(int u); /* Reset (init) stats when link goes up */ +void update_link_stats(int u); /* Get stats at link termination */ +#endif /* PPP_STATS_SUPPORT */ + + + +/* + * Inline versions of get/put char/short/long. + * Pointer is advanced; we assume that both arguments + * are lvalues and will already be in registers. + * cp MUST be u_char *. + */ +#define GETCHAR(c, cp) { \ + (c) = *(cp)++; \ +} +#define PUTCHAR(c, cp) { \ + *(cp)++ = (u_char) (c); \ +} + + +#define GETSHORT(s, cp) { \ + (s) = *(cp)++ << 8; \ + (s) |= *(cp)++; \ +} +#define PUTSHORT(s, cp) { \ + *(cp)++ = (u_char) ((s) >> 8); \ + *(cp)++ = (u_char) (s); \ +} + +#define GETLONG(l, cp) { \ + (l) = *(cp)++ << 8; \ + (l) |= *(cp)++; (l) <<= 8; \ + (l) |= *(cp)++; (l) <<= 8; \ + (l) |= *(cp)++; \ +} +#define PUTLONG(l, cp) { \ + *(cp)++ = (u_char) ((l) >> 24); \ + *(cp)++ = (u_char) ((l) >> 16); \ + *(cp)++ = (u_char) ((l) >> 8); \ + *(cp)++ = (u_char) (l); \ +} + +#define INCPTR(n, cp) ((cp) += (n)) +#define DECPTR(n, cp) ((cp) -= (n)) + +/* + * System dependent definitions for user-level 4.3BSD UNIX implementation. + */ +#define TIMEOUT(f, a, t) do { sys_untimeout((f), (a)); sys_timeout((t)*1000, (f), (a)); } while(0) +#define TIMEOUTMS(f, a, t) do { sys_untimeout((f), (a)); sys_timeout((t), (f), (a)); } while(0) +#define UNTIMEOUT(f, a) sys_untimeout((f), (a)) + +#define BZERO(s, n) memset(s, 0, n) +#define BCMP(s1, s2, l) memcmp(s1, s2, l) + +#define PRINTMSG(m, l) { ppp_info("Remote message: %0.*v", l, m); } + +/* + * MAKEHEADER - Add Header fields to a packet. + */ +#define MAKEHEADER(p, t) { \ + PUTCHAR(PPP_ALLSTATIONS, p); \ + PUTCHAR(PPP_UI, p); \ + PUTSHORT(t, p); } + +/* Procedures exported from auth.c */ +void link_required(ppp_pcb *pcb); /* we are starting to use the link */ +void link_terminated(ppp_pcb *pcb); /* we are finished with the link */ +void link_down(ppp_pcb *pcb); /* the LCP layer has left the Opened state */ +void upper_layers_down(ppp_pcb *pcb); /* take all NCPs down */ +void link_established(ppp_pcb *pcb); /* the link is up; authenticate now */ +void start_networks(ppp_pcb *pcb); /* start all the network control protos */ +void continue_networks(ppp_pcb *pcb); /* start network [ip, etc] control protos */ +#if PPP_SERVER +void auth_peer_fail(ppp_pcb *pcb, int protocol); + /* peer failed to authenticate itself */ +void auth_peer_success(ppp_pcb *pcb, int protocol, int prot_flavor, const char *name, int namelen); + /* peer successfully authenticated itself */ +#endif /* PPP_SERVER */ +void auth_withpeer_fail(ppp_pcb *pcb, int protocol); + /* we failed to authenticate ourselves */ +void auth_withpeer_success(ppp_pcb *pcb, int protocol, int prot_flavor); + /* we successfully authenticated ourselves */ +void np_up(ppp_pcb *pcb, int proto); /* a network protocol has come up */ +void np_down(ppp_pcb *pcb, int proto); /* a network protocol has gone down */ +void np_finished(ppp_pcb *pcb, int proto); /* a network protocol no longer needs link */ +void auth_reset(ppp_pcb *pcb); /* check what secrets we have */ +int get_secret(ppp_pcb *pcb, const char *client, const char *server, char *secret, int *secret_len, int am_server); + /* get "secret" for chap */ + +/* Procedures exported from ipcp.c */ +/* int parse_dotted_ip (char *, u32_t *); */ + +/* Procedures exported from demand.c */ +#if DEMAND_SUPPORT +void demand_conf (void); /* config interface(s) for demand-dial */ +void demand_block (void); /* set all NPs to queue up packets */ +void demand_unblock (void); /* set all NPs to pass packets */ +void demand_discard (void); /* set all NPs to discard packets */ +void demand_rexmit (int, u32_t); /* retransmit saved frames for an NP*/ +int loop_chars (unsigned char *, int); /* process chars from loopback */ +int loop_frame (unsigned char *, int); /* should we bring link up? */ +#endif /* DEMAND_SUPPORT */ + +/* Procedures exported from multilink.c */ +#ifdef HAVE_MULTILINK +void mp_check_options (void); /* Check multilink-related options */ +int mp_join_bundle (void); /* join our link to an appropriate bundle */ +void mp_exit_bundle (void); /* have disconnected our link from bundle */ +void mp_bundle_terminated (void); +char *epdisc_to_str (struct epdisc *); /* string from endpoint discrim. */ +int str_to_epdisc (struct epdisc *, char *); /* endpt disc. from str */ +#else +#define mp_bundle_terminated() /* nothing */ +#define mp_exit_bundle() /* nothing */ +#define doing_multilink 0 +#define multilink_master 0 +#endif + +/* Procedures exported from utils.c. */ +void ppp_print_string(char *p, int len, void (*printer) (void *, const char *, ...), void *arg); /* Format a string for output */ +int ppp_slprintf(char *buf, int buflen, const char *fmt, ...); /* sprintf++ */ +int ppp_vslprintf(char *buf, int buflen, const char *fmt, va_list args); /* vsprintf++ */ +size_t ppp_strlcpy(char *dest, const char *src, size_t len); /* safe strcpy */ +size_t ppp_strlcat(char *dest, const char *src, size_t len); /* safe strncpy */ +void ppp_dbglog(const char *fmt, ...); /* log a debug message */ +void ppp_info(const char *fmt, ...); /* log an informational message */ +void ppp_notice(const char *fmt, ...); /* log a notice-level message */ +void ppp_warn(const char *fmt, ...); /* log a warning message */ +void ppp_error(const char *fmt, ...); /* log an error message */ +void ppp_fatal(const char *fmt, ...); /* log an error message and die(1) */ +#if PRINTPKT_SUPPORT +void ppp_dump_packet(const char *tag, unsigned char *p, int len); + /* dump packet to debug log if interesting */ +#endif /* PRINTPKT_SUPPORT */ + + +#endif /* PPP_IMP_H_ */ + +#endif /* PPP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/pppcrypt.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/pppcrypt.h new file mode 100644 index 0000000..ef2e87d --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/pppcrypt.h @@ -0,0 +1,43 @@ +/* + * pppcrypt.c - PPP/DES linkage for MS-CHAP and EAP SRP-SHA1 + * + * Extracted from chap_ms.c by James Carlson. + * + * Copyright (c) 1995 Eric Rosenquist. 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. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && MSCHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef PPPCRYPT_H +#define PPPCRYPT_H + +void pppcrypt_56_to_64_bit_key(u_char *key, u_char *des_key); + +#endif /* PPPCRYPT_H */ + +#endif /* PPP_SUPPORT && MSCHAP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/pppdebug.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/pppdebug.h new file mode 100644 index 0000000..e35c8e0 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/pppdebug.h @@ -0,0 +1,80 @@ +/***************************************************************************** +* pppdebug.h - System debugging utilities. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1998 Global Election Systems Inc. +* portions Copyright (c) 2001 by Cognizant Pty Ltd. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY (please don't use tabs!) +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 98-07-29 Guy Lancaster , Global Election Systems Inc. +* Original. +* +***************************************************************************** +*/ + +#include "lwip/opt.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef PPPDEBUG_H +#define PPPDEBUG_H + +/* Trace levels. */ +#define LOG_CRITICAL (PPP_DEBUG | LWIP_DBG_LEVEL_SEVERE) +#define LOG_ERR (PPP_DEBUG | LWIP_DBG_LEVEL_SEVERE) +#define LOG_NOTICE (PPP_DEBUG | LWIP_DBG_LEVEL_WARNING) +#define LOG_WARNING (PPP_DEBUG | LWIP_DBG_LEVEL_WARNING) +#define LOG_INFO (PPP_DEBUG) +#define LOG_DETAIL (PPP_DEBUG) +#define LOG_DEBUG (PPP_DEBUG) + +#if PPP_DEBUG + +#define MAINDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) +#define SYSDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) +#define FSMDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) +#define LCPDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) +#define IPCPDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) +#define IPV6CPDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) +#define UPAPDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) +#define CHAPDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) +#define PPPDEBUG(a, b) LWIP_DEBUGF(a, b) + +#else /* PPP_DEBUG */ + +#define MAINDEBUG(a) +#define SYSDEBUG(a) +#define FSMDEBUG(a) +#define LCPDEBUG(a) +#define IPCPDEBUG(a) +#define IPV6CPDEBUG(a) +#define UPAPDEBUG(a) +#define CHAPDEBUG(a) +#define PPPDEBUG(a, b) + +#endif /* PPP_DEBUG */ + +#endif /* PPPDEBUG_H */ + +#endif /* PPP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/pppoe.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/pppoe.h new file mode 100644 index 0000000..eae032c --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/pppoe.h @@ -0,0 +1,183 @@ +/***************************************************************************** +* pppoe.h - PPP Over Ethernet implementation for lwIP. +* +* Copyright (c) 2006 by Marc Boucher, Services Informatiques (MBSI) inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 06-01-01 Marc Boucher +* Ported to lwIP. +*****************************************************************************/ + + + +/* based on NetBSD: if_pppoe.c,v 1.64 2006/01/31 23:50:15 martin Exp */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Martin Husemann . + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ +#include "lwip/opt.h" +#if PPP_SUPPORT && PPPOE_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef PPP_OE_H +#define PPP_OE_H + +#include "ppp.h" +#include "netif/etharp.h" + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct pppoehdr { + PACK_STRUCT_FLD_8(u8_t vertype); + PACK_STRUCT_FLD_8(u8_t code); + PACK_STRUCT_FIELD(u16_t session); + PACK_STRUCT_FIELD(u16_t plen); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct pppoetag { + PACK_STRUCT_FIELD(u16_t tag); + PACK_STRUCT_FIELD(u16_t len); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + + +#define PPPOE_STATE_INITIAL 0 +#define PPPOE_STATE_PADI_SENT 1 +#define PPPOE_STATE_PADR_SENT 2 +#define PPPOE_STATE_SESSION 3 +/* passive */ +#define PPPOE_STATE_PADO_SENT 1 + +#define PPPOE_CB_STATE_UP 0 /* PPPoE link is UP */ +#define PPPOE_CB_STATE_DOWN 1 /* PPPoE link is DOWN - normal condition */ +#define PPPOE_CB_STATE_FAILED 2 /* Failed to setup PPPoE link */ + +#define PPPOE_HEADERLEN sizeof(struct pppoehdr) +#define PPPOE_VERTYPE 0x11 /* VER=1, TYPE = 1 */ + +#define PPPOE_TAG_EOL 0x0000 /* end of list */ +#define PPPOE_TAG_SNAME 0x0101 /* service name */ +#define PPPOE_TAG_ACNAME 0x0102 /* access concentrator name */ +#define PPPOE_TAG_HUNIQUE 0x0103 /* host unique */ +#define PPPOE_TAG_ACCOOKIE 0x0104 /* AC cookie */ +#define PPPOE_TAG_VENDOR 0x0105 /* vendor specific */ +#define PPPOE_TAG_RELAYSID 0x0110 /* relay session id */ +#define PPPOE_TAG_SNAME_ERR 0x0201 /* service name error */ +#define PPPOE_TAG_ACSYS_ERR 0x0202 /* AC system error */ +#define PPPOE_TAG_GENERIC_ERR 0x0203 /* gerneric error */ + +#define PPPOE_CODE_PADI 0x09 /* Active Discovery Initiation */ +#define PPPOE_CODE_PADO 0x07 /* Active Discovery Offer */ +#define PPPOE_CODE_PADR 0x19 /* Active Discovery Request */ +#define PPPOE_CODE_PADS 0x65 /* Active Discovery Session confirmation */ +#define PPPOE_CODE_PADT 0xA7 /* Active Discovery Terminate */ + +#ifndef PPPOE_MAX_AC_COOKIE_LEN +#define PPPOE_MAX_AC_COOKIE_LEN 64 +#endif + +struct pppoe_softc { + struct pppoe_softc *next; + struct netif *sc_ethif; /* ethernet interface we are using */ + ppp_pcb *pcb; /* PPP PCB */ + void (*sc_link_status_cb)(ppp_pcb *pcb, int up); + + struct eth_addr sc_dest; /* hardware address of concentrator */ + u16_t sc_session; /* PPPoE session id */ + u8_t sc_state; /* discovery phase or session connected */ + +#ifdef PPPOE_TODO + u8_t *sc_service_name; /* if != NULL: requested name of service */ + u8_t *sc_concentrator_name; /* if != NULL: requested concentrator id */ +#endif /* PPPOE_TODO */ + u8_t sc_ac_cookie[PPPOE_MAX_AC_COOKIE_LEN]; /* content of AC cookie we must echo back */ + u8_t sc_ac_cookie_len; /* length of cookie data */ +#ifdef PPPOE_SERVER + u8_t *sc_hunique; /* content of host unique we must echo back */ + u8_t sc_hunique_len; /* length of host unique */ +#endif + u8_t sc_padi_retried; /* number of PADI retries already done */ + u8_t sc_padr_retried; /* number of PADR retries already done */ +}; + + +#define pppoe_init() /* compatibility define, no initialization needed */ + +err_t pppoe_create(struct netif *ethif, ppp_pcb *pcb, void (*link_status_cb)(ppp_pcb *pcb, int up), struct pppoe_softc **scptr); +err_t pppoe_destroy(struct pppoe_softc *sc); + +int pppoe_connect(struct pppoe_softc *sc); +void pppoe_disconnect(struct pppoe_softc *sc); + +void pppoe_disc_input(struct netif *netif, struct pbuf *p); +void pppoe_data_input(struct netif *netif, struct pbuf *p); + +err_t pppoe_xmit(struct pppoe_softc *sc, struct pbuf *pb); + +#endif /* PPP_OE_H */ + +#endif /* PPP_SUPPORT && PPPOE_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/pppol2tp.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/pppol2tp.h new file mode 100644 index 0000000..5b869ae --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/pppol2tp.h @@ -0,0 +1,217 @@ +/** + * @file + * Network Point to Point Protocol over Layer 2 Tunneling Protocol header file. + * + */ + +/* + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && PPPOL2TP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef PPPOL2TP_H_ +#define PPPOL2TP_H_ + +#include "ppp.h" + +/* Timeout */ +#define PPPOL2TP_CONTROL_TIMEOUT (5*1000) /* base for quick timeout calculation */ +#define PPPOL2TP_SLOW_RETRY (60*1000) /* persistent retry interval */ + +#define PPPOL2TP_MAXSCCRQ 4 /* retry SCCRQ four times (quickly) */ +#define PPPOL2TP_MAXICRQ 4 /* retry IRCQ four times */ +#define PPPOL2TP_MAXICCN 4 /* retry ICCN four times */ + +/* L2TP header flags */ +#define PPPOL2TP_HEADERFLAG_CONTROL 0x8000 +#define PPPOL2TP_HEADERFLAG_LENGTH 0x4000 +#define PPPOL2TP_HEADERFLAG_SEQUENCE 0x0800 +#define PPPOL2TP_HEADERFLAG_OFFSET 0x0200 +#define PPPOL2TP_HEADERFLAG_PRIORITY 0x0100 +#define PPPOL2TP_HEADERFLAG_VERSION 0x0002 + +/* Mandatory bits for control: Control, Length, Sequence, Version 2 */ +#define PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY (PPPOL2TP_HEADERFLAG_CONTROL|PPPOL2TP_HEADERFLAG_LENGTH|PPPOL2TP_HEADERFLAG_SEQUENCE|PPPOL2TP_HEADERFLAG_VERSION) +/* Forbidden bits for control: Offset, Priority */ +#define PPPOL2TP_HEADERFLAG_CONTROL_FORBIDDEN (PPPOL2TP_HEADERFLAG_OFFSET|PPPOL2TP_HEADERFLAG_PRIORITY) + +/* Mandatory bits for data: Version 2 */ +#define PPPOL2TP_HEADERFLAG_DATA_MANDATORY (PPPOL2TP_HEADERFLAG_VERSION) + +/* AVP (Attribute Value Pair) header */ +#define PPPOL2TP_AVPHEADERFLAG_MANDATORY 0x8000 +#define PPPOL2TP_AVPHEADERFLAG_HIDDEN 0x4000 +#define PPPOL2TP_AVPHEADERFLAG_LENGTHMASK 0x03ff + +/* -- AVP - Message type */ +#define PPPOL2TP_AVPTYPE_MESSAGE 0 /* Message type */ + +/* Control Connection Management */ +#define PPPOL2TP_MESSAGETYPE_SCCRQ 1 /* Start Control Connection Request */ +#define PPPOL2TP_MESSAGETYPE_SCCRP 2 /* Start Control Connection Reply */ +#define PPPOL2TP_MESSAGETYPE_SCCCN 3 /* Start Control Connection Connected */ +#define PPPOL2TP_MESSAGETYPE_STOPCCN 4 /* Stop Control Connection Notification */ +#define PPPOL2TP_MESSAGETYPE_HELLO 6 /* Hello */ +/* Call Management */ +#define PPPOL2TP_MESSAGETYPE_OCRQ 7 /* Outgoing Call Request */ +#define PPPOL2TP_MESSAGETYPE_OCRP 8 /* Outgoing Call Reply */ +#define PPPOL2TP_MESSAGETYPE_OCCN 9 /* Outgoing Call Connected */ +#define PPPOL2TP_MESSAGETYPE_ICRQ 10 /* Incoming Call Request */ +#define PPPOL2TP_MESSAGETYPE_ICRP 11 /* Incoming Call Reply */ +#define PPPOL2TP_MESSAGETYPE_ICCN 12 /* Incoming Call Connected */ +#define PPPOL2TP_MESSAGETYPE_CDN 14 /* Call Disconnect Notify */ +/* Error reporting */ +#define PPPOL2TP_MESSAGETYPE_WEN 15 /* WAN Error Notify */ +/* PPP Session Control */ +#define PPPOL2TP_MESSAGETYPE_SLI 16 /* Set Link Info */ + +/* -- AVP - Result code */ +#define PPPOL2TP_AVPTYPE_RESULTCODE 1 /* Result code */ +#define PPPOL2TP_RESULTCODE 1 /* General request to clear control connection */ + +/* -- AVP - Protocol version (!= L2TP Header version) */ +#define PPPOL2TP_AVPTYPE_VERSION 2 +#define PPPOL2TP_VERSION 0x0100 /* L2TP Protocol version 1, revision 0 */ + +/* -- AVP - Framing capabilities */ +#define PPPOL2TP_AVPTYPE_FRAMINGCAPABILITIES 3 /* Bearer capabilities */ +#define PPPOL2TP_FRAMINGCAPABILITIES 0x00000003 /* Async + Sync framing */ + +/* -- AVP - Bearer capabilities */ +#define PPPOL2TP_AVPTYPE_BEARERCAPABILITIES 4 /* Bearer capabilities */ +#define PPPOL2TP_BEARERCAPABILITIES 0x00000003 /* Analog + Digital Access */ + +/* -- AVP - Tie breaker */ +#define PPPOL2TP_AVPTYPE_TIEBREAKER 5 + +/* -- AVP - Host name */ +#define PPPOL2TP_AVPTYPE_HOSTNAME 7 /* Host name */ +#define PPPOL2TP_HOSTNAME "lwIP" /* FIXME: make it configurable */ + +/* -- AVP - Vendor name */ +#define PPPOL2TP_AVPTYPE_VENDORNAME 8 /* Vendor name */ +#define PPPOL2TP_VENDORNAME "lwIP" /* FIXME: make it configurable */ + +/* -- AVP - Assign tunnel ID */ +#define PPPOL2TP_AVPTYPE_TUNNELID 9 /* Assign Tunnel ID */ + +/* -- AVP - Receive window size */ +#define PPPOL2TP_AVPTYPE_RECEIVEWINDOWSIZE 10 /* Receive window size */ +#define PPPOL2TP_RECEIVEWINDOWSIZE 8 /* FIXME: make it configurable */ + +/* -- AVP - Challenge */ +#define PPPOL2TP_AVPTYPE_CHALLENGE 11 /* Challenge */ + +/* -- AVP - Cause code */ +#define PPPOL2TP_AVPTYPE_CAUSECODE 12 /* Cause code*/ + +/* -- AVP - Challenge response */ +#define PPPOL2TP_AVPTYPE_CHALLENGERESPONSE 13 /* Challenge response */ +#define PPPOL2TP_AVPTYPE_CHALLENGERESPONSE_SIZE 16 + +/* -- AVP - Assign session ID */ +#define PPPOL2TP_AVPTYPE_SESSIONID 14 /* Assign Session ID */ + +/* -- AVP - Call serial number */ +#define PPPOL2TP_AVPTYPE_CALLSERIALNUMBER 15 /* Call Serial Number */ + +/* -- AVP - Framing type */ +#define PPPOL2TP_AVPTYPE_FRAMINGTYPE 19 /* Framing Type */ +#define PPPOL2TP_FRAMINGTYPE 0x00000001 /* Sync framing */ + +/* -- AVP - TX Connect Speed */ +#define PPPOL2TP_AVPTYPE_TXCONNECTSPEED 24 /* TX Connect Speed */ +#define PPPOL2TP_TXCONNECTSPEED 100000000 /* Connect speed: 100 Mbits/s */ + +/* L2TP Session state */ +#define PPPOL2TP_STATE_INITIAL 0 +#define PPPOL2TP_STATE_SCCRQ_SENT 1 +#define PPPOL2TP_STATE_ICRQ_SENT 2 +#define PPPOL2TP_STATE_ICCN_SENT 3 +#define PPPOL2TP_STATE_DATA 4 + +#define PPPOL2TP_CB_STATE_UP 0 /* PPPoL2TP link is UP */ +#define PPPOL2TP_CB_STATE_DOWN 1 /* PPPo2TP link is DOWN - normal condition */ +#define PPPOL2TP_CB_STATE_FAILED 2 /* Failed to setup PPPo2TP link */ + +#define PPPOL2TP_OUTPUT_DATA_HEADER_LEN 6 /* Our data header len */ + +/* + * PPPoL2TP interface control block. + */ +typedef struct pppol2tp_pcb_s pppol2tp_pcb; +struct pppol2tp_pcb_s { + ppp_pcb *ppp; /* PPP PCB */ + u8_t phase; /* L2TP phase */ + void (*link_status_cb)(ppp_pcb *pcb, int status); + struct udp_pcb *udp; /* UDP L2TP Socket */ + struct netif *netif; /* Output interface, used as a default route */ + ip_addr_t remote_ip; /* LNS IP Address */ + u16_t remote_port; /* LNS port */ +#if PPPOL2TP_AUTH_SUPPORT + u8_t *secret; /* Secret string */ + u8_t secret_len; /* Secret string length */ + u8_t secret_rv[16]; /* Random vector */ + u8_t challenge_hash[16]; /* Challenge response */ + u8_t send_challenge; /* Boolean whether the next sent packet should contains a challenge response */ +#endif /* PPPOL2TP_AUTH_SUPPORT */ + + u16_t tunnel_port; /* Tunnel port */ + u16_t our_ns; /* NS to peer */ + u16_t peer_nr; /* NR from peer */ + u16_t peer_ns; /* NS from peer */ + u16_t source_tunnel_id; /* Tunnel ID assigned by peer */ + u16_t remote_tunnel_id; /* Tunnel ID assigned to peer */ + u16_t source_session_id; /* Session ID assigned by peer */ + u16_t remote_session_id; /* Session ID assigned to peer */ + + u8_t sccrq_retried; /* number of SCCRQ retries already done */ + u8_t icrq_retried; /* number of ICRQ retries already done */ + u8_t iccn_retried; /* number of ICCN retries already done */ +}; + + +/* Create a new L2TP session. */ +err_t pppol2tp_create(ppp_pcb *ppp, void (*link_status_cb)(ppp_pcb *pcb, int status), pppol2tp_pcb **l2tpptr, + struct netif *netif, ip_addr_t *ipaddr, u16_t port, + u8_t *secret, u8_t secret_len); + +/* Destroy a L2TP control block */ +err_t pppol2tp_destroy(pppol2tp_pcb *l2tp); + +/* Be a LAC, connect to a LNS. */ +err_t pppol2tp_connect(pppol2tp_pcb *l2tp); + +/* Disconnect */ +void pppol2tp_disconnect(pppol2tp_pcb *l2tp); + +/* Data packet from PPP to L2TP */ +err_t pppol2tp_xmit(pppol2tp_pcb *l2tp, struct pbuf *pb); + +#endif /* PPPOL2TP_H_ */ +#endif /* PPP_SUPPORT && PPPOL2TP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/upap.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/upap.h new file mode 100644 index 0000000..bb9309b --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/upap.h @@ -0,0 +1,123 @@ +/* + * upap.h - User/Password Authentication Protocol definitions. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. 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. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: upap.h,v 1.8 2002/12/04 23:03:33 paulus Exp $ + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && PAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef UPAP_H +#define UPAP_H + +#include "ppp.h" + +/* + * Packet header = Code, id, length. + */ +#define UPAP_HEADERLEN 4 + + +/* + * UPAP codes. + */ +#define UPAP_AUTHREQ 1 /* Authenticate-Request */ +#define UPAP_AUTHACK 2 /* Authenticate-Ack */ +#define UPAP_AUTHNAK 3 /* Authenticate-Nak */ + + +/* + * Client states. + */ +#define UPAPCS_INITIAL 0 /* Connection down */ +#define UPAPCS_CLOSED 1 /* Connection up, haven't requested auth */ +#define UPAPCS_PENDING 2 /* Connection down, have requested auth */ +#define UPAPCS_AUTHREQ 3 /* We've sent an Authenticate-Request */ +#define UPAPCS_OPEN 4 /* We've received an Ack */ +#define UPAPCS_BADAUTH 5 /* We've received a Nak */ + +/* + * Server states. + */ +#define UPAPSS_INITIAL 0 /* Connection down */ +#define UPAPSS_CLOSED 1 /* Connection up, haven't requested auth */ +#define UPAPSS_PENDING 2 /* Connection down, have requested auth */ +#define UPAPSS_LISTEN 3 /* Listening for an Authenticate */ +#define UPAPSS_OPEN 4 /* We've sent an Ack */ +#define UPAPSS_BADAUTH 5 /* We've sent a Nak */ + + +/* + * Timeouts. + */ +#if 0 /* moved to opt.h */ +#define UPAP_DEFTIMEOUT 3 /* Timeout (seconds) for retransmitting req */ +#define UPAP_DEFREQTIME 30 /* Time to wait for auth-req from peer */ +#endif /* moved to opt.h */ + +/* + * Each interface is described by upap structure. + */ +#if PAP_SUPPORT +typedef struct upap_state { + const char *us_user; /* User */ + u8_t us_userlen; /* User length */ + const char *us_passwd; /* Password */ + u8_t us_passwdlen; /* Password length */ + u8_t us_clientstate; /* Client state */ +#if PPP_SERVER + u8_t us_serverstate; /* Server state */ +#endif /* PPP_SERVER */ + u8_t us_id; /* Current id */ + u8_t us_transmits; /* Number of auth-reqs sent */ +} upap_state; +#endif /* PAP_SUPPORT */ + + +void upap_authwithpeer(ppp_pcb *pcb, const char *user, const char *password); +#if PPP_SERVER +void upap_authpeer(ppp_pcb *pcb); +#endif /* PPP_SERVER */ + +extern const struct protent pap_protent; + +#endif /* UPAP_H */ +#endif /* PPP_SUPPORT && PAP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/vj.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/vj.h new file mode 100644 index 0000000..3780667 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/ppp/vj.h @@ -0,0 +1,161 @@ +/* + * Definitions for tcp compression routines. + * + * $Id: vj.h,v 1.7 2010/02/22 17:52:09 goldsimon Exp $ + * + * Copyright (c) 1989 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989: + * - Initial distribution. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && VJ_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#ifndef VJ_H +#define VJ_H + +#include "lwip/ip.h" +#include "lwip/tcp_impl.h" + +#define MAX_SLOTS 16 /* must be > 2 and < 256 */ +#define MAX_HDR 128 + +/* + * Compressed packet format: + * + * The first octet contains the packet type (top 3 bits), TCP + * 'push' bit, and flags that indicate which of the 4 TCP sequence + * numbers have changed (bottom 5 bits). The next octet is a + * conversation number that associates a saved IP/TCP header with + * the compressed packet. The next two octets are the TCP checksum + * from the original datagram. The next 0 to 15 octets are + * sequence number changes, one change per bit set in the header + * (there may be no changes and there are two special cases where + * the receiver implicitly knows what changed -- see below). + * + * There are 5 numbers which can change (they are always inserted + * in the following order): TCP urgent pointer, window, + * acknowlegement, sequence number and IP ID. (The urgent pointer + * is different from the others in that its value is sent, not the + * change in value.) Since typical use of SLIP links is biased + * toward small packets (see comments on MTU/MSS below), changes + * use a variable length coding with one octet for numbers in the + * range 1 - 255 and 3 octets (0, MSB, LSB) for numbers in the + * range 256 - 65535 or 0. (If the change in sequence number or + * ack is more than 65535, an uncompressed packet is sent.) + */ + +/* + * Packet types (must not conflict with IP protocol version) + * + * The top nibble of the first octet is the packet type. There are + * three possible types: IP (not proto TCP or tcp with one of the + * control flags set); uncompressed TCP (a normal IP/TCP packet but + * with the 8-bit protocol field replaced by an 8-bit connection id -- + * this type of packet syncs the sender & receiver); and compressed + * TCP (described above). + * + * LSB of 4-bit field is TCP "PUSH" bit (a worthless anachronism) and + * is logically part of the 4-bit "changes" field that follows. Top + * three bits are actual packet type. For backward compatibility + * and in the interest of conserving bits, numbers are chosen so the + * IP protocol version number (4) which normally appears in this nibble + * means "IP packet". + */ + +/* packet types */ +#define TYPE_IP 0x40 +#define TYPE_UNCOMPRESSED_TCP 0x70 +#define TYPE_COMPRESSED_TCP 0x80 +#define TYPE_ERROR 0x00 + +/* Bits in first octet of compressed packet */ +#define NEW_C 0x40 /* flag bits for what changed in a packet */ +#define NEW_I 0x20 +#define NEW_S 0x08 +#define NEW_A 0x04 +#define NEW_W 0x02 +#define NEW_U 0x01 + +/* reserved, special-case values of above */ +#define SPECIAL_I (NEW_S|NEW_W|NEW_U) /* echoed interactive traffic */ +#define SPECIAL_D (NEW_S|NEW_A|NEW_W|NEW_U) /* unidirectional data */ +#define SPECIALS_MASK (NEW_S|NEW_A|NEW_W|NEW_U) + +#define TCP_PUSH_BIT 0x10 + + +/* + * "state" data for each active tcp conversation on the wire. This is + * basically a copy of the entire IP/TCP header from the last packet + * we saw from the conversation together with a small identifier + * the transmit & receive ends of the line use to locate saved header. + */ +struct cstate { + struct cstate *cs_next; /* next most recently used state (xmit only) */ + u_short cs_hlen; /* size of hdr (receive only) */ + u_char cs_id; /* connection # associated with this state */ + u_char cs_filler; + union { + char csu_hdr[MAX_HDR]; + struct ip_hdr csu_ip; /* ip/tcp hdr from most recent packet */ + } vjcs_u; +}; +#define cs_ip vjcs_u.csu_ip +#define cs_hdr vjcs_u.csu_hdr + + +struct vjstat { + unsigned long vjs_packets; /* outbound packets */ + unsigned long vjs_compressed; /* outbound compressed packets */ + unsigned long vjs_searches; /* searches for connection state */ + unsigned long vjs_misses; /* times couldn't find conn. state */ + unsigned long vjs_uncompressedin; /* inbound uncompressed packets */ + unsigned long vjs_compressedin; /* inbound compressed packets */ + unsigned long vjs_errorin; /* inbound unknown type packets */ + unsigned long vjs_tossed; /* inbound packets tossed because of error */ +}; + +/* + * all the state data for one serial line (we need one of these per line). + */ +struct vjcompress { + struct cstate *last_cs; /* most recently used tstate */ + u_char last_recv; /* last rcvd conn. id */ + u_char last_xmit; /* last sent conn. id */ + u_short flags; + u_char maxSlotIndex; + u_char compressSlot; /* Flag indicating OK to compress slot ID. */ +#if LINK_STATS + struct vjstat stats; +#endif + struct cstate tstate[MAX_SLOTS]; /* xmit connection states */ + struct cstate rstate[MAX_SLOTS]; /* receive connection states */ +}; + +/* flag values */ +#define VJF_TOSS 1U /* tossing rcvd frames because of input err */ + +extern void vj_compress_init (struct vjcompress *comp); +extern u_int vj_compress_tcp (struct vjcompress *comp, struct pbuf *pb); +extern void vj_uncompress_err (struct vjcompress *comp); +extern int vj_uncompress_uncomp(struct pbuf *nb, struct vjcompress *comp); +extern int vj_uncompress_tcp (struct pbuf **nb, struct vjcompress *comp); + +#endif /* VJ_H */ + +#endif /* PPP_SUPPORT && VJ_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/slipif.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/slipif.h new file mode 100644 index 0000000..dc40d30 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/netif/slipif.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2001, Swedish Institute of Computer Science. + * 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 Institute 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 INSTITUTE 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 INSTITUTE 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_HDR_NETIF_SLIPIF_H +#define LWIP_HDR_NETIF_SLIPIF_H + +#include "lwip/opt.h" +#include "lwip/netif.h" + +/** Set this to 1 to start a thread that blocks reading on the serial line + * (using sio_read()). + */ +#ifndef SLIP_USE_RX_THREAD +#define SLIP_USE_RX_THREAD !NO_SYS +#endif + +/** Set this to 1 to enable functions to pass in RX bytes from ISR context. + * If enabled, slipif_received_byte[s]() process incoming bytes and put assembled + * packets on a queue, which is fed into lwIP from slipif_poll(). + * If disabled, slipif_poll() polls the serial line (using sio_tryread()). + */ +#ifndef SLIP_RX_FROM_ISR +#define SLIP_RX_FROM_ISR 0 +#endif + +/** Set this to 1 (default for SLIP_RX_FROM_ISR) to queue incoming packets + * received by slipif_received_byte[s]() as long as PBUF_POOL pbufs are available. + * If disabled, packets will be dropped if more than one packet is received. + */ +#ifndef SLIP_RX_QUEUE +#define SLIP_RX_QUEUE SLIP_RX_FROM_ISR +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +err_t slipif_init(struct netif * netif); +void slipif_poll(struct netif *netif); +#if SLIP_RX_FROM_ISR +void slipif_process_rxqueue(struct netif *netif); +void slipif_received_byte(struct netif *netif, u8_t data); +void slipif_received_bytes(struct netif *netif, u8_t *data, u8_t len); +#endif /* SLIP_RX_FROM_ISR */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_NETIF_SLIPIF_H */ + diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/posix/netdb.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/posix/netdb.h new file mode 100644 index 0000000..7134032 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/posix/netdb.h @@ -0,0 +1,33 @@ +/** + * @file + * This file is a posix wrapper for lwip/netdb.h. + */ + +/* + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/netdb.h" diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/include/posix/sys/socket.h b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/posix/sys/socket.h new file mode 100644 index 0000000..f7c7066 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/include/posix/sys/socket.h @@ -0,0 +1,33 @@ +/** + * @file + * This file is a posix wrapper for lwip/sockets.h. + */ + +/* + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/sockets.h" diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/FILES b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/FILES new file mode 100644 index 0000000..099dbf3 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/FILES @@ -0,0 +1,29 @@ +This directory contains generic network interface device drivers that +do not contain any hardware or architecture specific code. The files +are: + +etharp.c + Implements the ARP (Address Resolution Protocol) over + Ethernet. The code in this file should be used together with + Ethernet device drivers. Note that this module has been + largely made Ethernet independent so you should be able to + adapt this for other link layers (such as Firewire). + +ethernetif.c + An example of how an Ethernet device driver could look. This + file can be used as a "skeleton" for developing new Ethernet + network device drivers. It uses the etharp.c ARP code. + +loopif.c + A "loopback" network interface driver. It requires configuration + through the define LWIP_LOOPIF_MULTITHREADING (see opt.h). + +slipif.c + A generic implementation of the SLIP (Serial Line IP) + protocol. It requires a sio (serial I/O) module to work. + +ppp/ Point-to-Point Protocol stack + The PPP stack has been ported from ucip (http://ucip.sourceforge.net). + It matches quite well to pppd 2.3.1 (http://ppp.samba.org), although + compared to that, it has some modifications for embedded systems and + the source code has been reordered a bit. \ No newline at end of file diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/etharp.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/etharp.c new file mode 100644 index 0000000..b00cd80 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/etharp.c @@ -0,0 +1,1484 @@ +/** + * @file + * Address Resolution Protocol module for IP over Ethernet + * + * Functionally, ARP is divided into two parts. The first maps an IP address + * to a physical address when sending a packet, and the second part answers + * requests from other machines for our physical address. + * + * This implementation complies with RFC 826 (Ethernet ARP). It supports + * Gratuitious ARP from RFC3220 (IP Mobility Support for IPv4) section 4.6 + * if an interface calls etharp_gratuitous(our_netif) upon address change. + */ + +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * Copyright (c) 2003-2004 Leon Woestenberg + * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwip/opt.h" + +#if LWIP_ARP || LWIP_ETHERNET + +#include "lwip/ip_addr.h" +#include "lwip/def.h" +#include "lwip/lwip_ip.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" +#include "netif/etharp.h" +#include "lwip/ip6.h" + +#if PPPOE_SUPPORT +#include "netif/ppp/pppoe.h" +#endif /* PPPOE_SUPPORT */ + +#include + +const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}}; +const struct eth_addr ethzero = {{0,0,0,0,0,0}}; + +/** The 24-bit IANA multicast OUI is 01-00-5e: */ +#define LL_MULTICAST_ADDR_0 0x01 +#define LL_MULTICAST_ADDR_1 0x00 +#define LL_MULTICAST_ADDR_2 0x5e + +#if LWIP_ARP /* don't build if not configured for use in lwipopts.h */ + +/** the time an ARP entry stays valid after its last update, + * for ARP_TMR_INTERVAL = 1000, this is + * (60 * 20) seconds = 20 minutes. + */ +#define ARP_MAXAGE 1200 +/** Re-request a used ARP entry 1 minute before it would expire to prevent + * breaking a steadily used connection because the ARP entry timed out. */ +#define ARP_AGE_REREQUEST_USED (ARP_MAXAGE - 60) + +/** the time an ARP entry stays pending after first request, + * for ARP_TMR_INTERVAL = 1000, this is + * 10 seconds. + * + * @internal Keep this number at least 2, otherwise it might + * run out instantly if the timeout occurs directly after a request. + */ +#define ARP_MAXPENDING 5 + +#define HWTYPE_ETHERNET 1 + +enum etharp_state { + ETHARP_STATE_EMPTY = 0, + ETHARP_STATE_PENDING, + ETHARP_STATE_STABLE, + ETHARP_STATE_STABLE_REREQUESTING +#if ETHARP_SUPPORT_STATIC_ENTRIES + ,ETHARP_STATE_STATIC +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ +}; + +struct etharp_entry { +#if ARP_QUEUEING + /** Pointer to queue of pending outgoing packets on this ARP entry. */ + struct etharp_q_entry *q; +#else /* ARP_QUEUEING */ + /** Pointer to a single pending outgoing packet on this ARP entry. */ + struct pbuf *q; +#endif /* ARP_QUEUEING */ + ip_addr_t ipaddr; + struct netif *netif; + struct eth_addr ethaddr; + u16_t ctime; + u8_t state; +}; + +static struct etharp_entry arp_table[ARP_TABLE_SIZE]; + +#if !LWIP_NETIF_HWADDRHINT +static u8_t etharp_cached_entry; +#endif /* !LWIP_NETIF_HWADDRHINT */ + +/** Try hard to create a new entry - we want the IP address to appear in + the cache (even if this means removing an active entry or so). */ +#define ETHARP_FLAG_TRY_HARD 1 +#define ETHARP_FLAG_FIND_ONLY 2 +#if ETHARP_SUPPORT_STATIC_ENTRIES +#define ETHARP_FLAG_STATIC_ENTRY 4 +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + +#if LWIP_NETIF_HWADDRHINT +#define ETHARP_SET_HINT(netif, hint) if (((netif) != NULL) && ((netif)->addr_hint != NULL)) \ + *((netif)->addr_hint) = (hint); +#else /* LWIP_NETIF_HWADDRHINT */ +#define ETHARP_SET_HINT(netif, hint) (etharp_cached_entry = (hint)) +#endif /* LWIP_NETIF_HWADDRHINT */ + + +/* Some checks, instead of etharp_init(): */ +#if (LWIP_ARP && (ARP_TABLE_SIZE > 0x7f)) + #error "ARP_TABLE_SIZE must fit in an s8_t, you have to reduce it in your lwipopts.h" +#endif + + +#if ARP_QUEUEING +/** + * Free a complete queue of etharp entries + * + * @param q a qeueue of etharp_q_entry's to free + */ +static void +free_etharp_q(struct etharp_q_entry *q) +{ + struct etharp_q_entry *r; + LWIP_ASSERT("q != NULL", q != NULL); + LWIP_ASSERT("q->p != NULL", q->p != NULL); + while (q) { + r = q; + q = q->next; + LWIP_ASSERT("r->p != NULL", (r->p != NULL)); + pbuf_free(r->p); + memp_free(MEMP_ARP_QUEUE, r); + } +} +#else /* ARP_QUEUEING */ + +/** Compatibility define: free the queued pbuf */ +#define free_etharp_q(q) pbuf_free(q) + +#endif /* ARP_QUEUEING */ + +/** Clean up ARP table entries */ +static void +etharp_free_entry(int i) +{ + /* remove from SNMP ARP index tree */ + snmp_delete_arpidx_tree(arp_table[i].netif, &arp_table[i].ipaddr); + /* and empty packet queue */ + if (arp_table[i].q != NULL) { + /* remove all queued packets */ + LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_free_entry: freeing entry %"U16_F", packet queue %p.\n", (u16_t)i, (void *)(arp_table[i].q))); + free_etharp_q(arp_table[i].q); + arp_table[i].q = NULL; + } + /* recycle entry for re-use */ + arp_table[i].state = ETHARP_STATE_EMPTY; +#ifdef LWIP_DEBUG + /* for debugging, clean out the complete entry */ + arp_table[i].ctime = 0; + arp_table[i].netif = NULL; + ip_addr_set_zero(&arp_table[i].ipaddr); + arp_table[i].ethaddr = ethzero; +#endif /* LWIP_DEBUG */ +} + +/** + * Clears expired entries in the ARP table. + * + * This function should be called every ETHARP_TMR_INTERVAL milliseconds (5 seconds), + * in order to expire entries in the ARP table. + */ +void +etharp_tmr(void) +{ + u8_t i; + + LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer\n")); + /* remove expired entries from the ARP table */ + for (i = 0; i < ARP_TABLE_SIZE; ++i) { + u8_t state = arp_table[i].state; + if (state != ETHARP_STATE_EMPTY +#if ETHARP_SUPPORT_STATIC_ENTRIES + && (state != ETHARP_STATE_STATIC) +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + ) { + arp_table[i].ctime++; + if ((arp_table[i].ctime >= ARP_MAXAGE) || + ((arp_table[i].state == ETHARP_STATE_PENDING) && + (arp_table[i].ctime >= ARP_MAXPENDING))) { + /* pending or stable entry has become old! */ + LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired %s entry %"U16_F".\n", + arp_table[i].state >= ETHARP_STATE_STABLE ? "stable" : "pending", (u16_t)i)); + /* clean up entries that have just been expired */ + etharp_free_entry(i); + } + else if (arp_table[i].state == ETHARP_STATE_STABLE_REREQUESTING) { + /* Reset state to stable, so that the next transmitted packet will + re-send an ARP request. */ + arp_table[i].state = ETHARP_STATE_STABLE; + } + /* still pending entry? (not expired) */ + else if (arp_table[i].state == ETHARP_STATE_PENDING) { + /* resend an ARP query here? */ + if (etharp_request(arp_table[i].netif, &arp_table[i].ipaddr) != ERR_OK) { + } + } + } + } +} + +/** + * Search the ARP table for a matching or new entry. + * + * If an IP address is given, return a pending or stable ARP entry that matches + * the address. If no match is found, create a new entry with this address set, + * but in state ETHARP_EMPTY. The caller must check and possibly change the + * state of the returned entry. + * + * If ipaddr is NULL, return a initialized new entry in state ETHARP_EMPTY. + * + * In all cases, attempt to create new entries from an empty entry. If no + * empty entries are available and ETHARP_FLAG_TRY_HARD flag is set, recycle + * old entries. Heuristic choose the least important entry for recycling. + * + * @param ipaddr IP address to find in ARP cache, or to add if not found. + * @param flags @see definition of ETHARP_FLAG_* + * @param netif netif related to this address (used for NETIF_HWADDRHINT) + * + * @return The ARP entry index that matched or is created, ERR_MEM if no + * entry is found or could be recycled. + */ +static s8_t +etharp_find_entry(ip_addr_t *ipaddr, u8_t flags) +{ + s8_t old_pending = ARP_TABLE_SIZE, old_stable = ARP_TABLE_SIZE; + s8_t empty = ARP_TABLE_SIZE; + u8_t i = 0; + /* oldest entry with packets on queue */ + s8_t old_queue = ARP_TABLE_SIZE; + /* its age */ + u16_t age_queue = 0, age_pending = 0, age_stable = 0; + + /** + * a) do a search through the cache, remember candidates + * b) select candidate entry + * c) create new entry + */ + + /* a) in a single search sweep, do all of this + * 1) remember the first empty entry (if any) + * 2) remember the oldest stable entry (if any) + * 3) remember the oldest pending entry without queued packets (if any) + * 4) remember the oldest pending entry with queued packets (if any) + * 5) search for a matching IP entry, either pending or stable + * until 5 matches, or all entries are searched for. + */ + + for (i = 0; i < ARP_TABLE_SIZE; ++i) { + u8_t state = arp_table[i].state; + /* no empty entry found yet and now we do find one? */ + if ((empty == ARP_TABLE_SIZE) && (state == ETHARP_STATE_EMPTY)) { + LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_find_entry: found empty entry %"U16_F"\n", (u16_t)i)); + /* remember first empty entry */ + empty = i; + } else if (state != ETHARP_STATE_EMPTY) { + LWIP_ASSERT("state == ETHARP_STATE_PENDING || state >= ETHARP_STATE_STABLE", + state == ETHARP_STATE_PENDING || state >= ETHARP_STATE_STABLE); + /* if given, does IP address match IP address in ARP entry? */ + if (ipaddr && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: found matching entry %"U16_F"\n", (u16_t)i)); + /* found exact IP address match, simply bail out */ + return i; + } + /* pending entry? */ + if (state == ETHARP_STATE_PENDING) { + /* pending with queued packets? */ + if (arp_table[i].q != NULL) { + if (arp_table[i].ctime >= age_queue) { + old_queue = i; + age_queue = arp_table[i].ctime; + } + } else + /* pending without queued packets? */ + { + if (arp_table[i].ctime >= age_pending) { + old_pending = i; + age_pending = arp_table[i].ctime; + } + } + /* stable entry? */ + } else if (state >= ETHARP_STATE_STABLE) { +#if ETHARP_SUPPORT_STATIC_ENTRIES + /* don't record old_stable for static entries since they never expire */ + if (state < ETHARP_STATE_STATIC) +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + { + /* remember entry with oldest stable entry in oldest, its age in maxtime */ + if (arp_table[i].ctime >= age_stable) { + old_stable = i; + age_stable = arp_table[i].ctime; + } + } + } + } + } + /* { we have no match } => try to create a new entry */ + + /* don't create new entry, only search? */ + if (((flags & ETHARP_FLAG_FIND_ONLY) != 0) || + /* or no empty entry found and not allowed to recycle? */ + ((empty == ARP_TABLE_SIZE) && ((flags & ETHARP_FLAG_TRY_HARD) == 0))) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: no empty entry found and not allowed to recycle\n")); + return (s8_t)ERR_MEM; + } + + /* b) choose the least destructive entry to recycle: + * 1) empty entry + * 2) oldest stable entry + * 3) oldest pending entry without queued packets + * 4) oldest pending entry with queued packets + * + * { ETHARP_FLAG_TRY_HARD is set at this point } + */ + + /* 1) empty entry available? */ + if (empty < ARP_TABLE_SIZE) { + i = empty; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting empty entry %"U16_F"\n", (u16_t)i)); + } else { + /* 2) found recyclable stable entry? */ + if (old_stable < ARP_TABLE_SIZE) { + /* recycle oldest stable*/ + i = old_stable; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest stable entry %"U16_F"\n", (u16_t)i)); + /* no queued packets should exist on stable entries */ + LWIP_ASSERT("arp_table[i].q == NULL", arp_table[i].q == NULL); + /* 3) found recyclable pending entry without queued packets? */ + } else if (old_pending < ARP_TABLE_SIZE) { + /* recycle oldest pending */ + i = old_pending; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest pending entry %"U16_F" (without queue)\n", (u16_t)i)); + /* 4) found recyclable pending entry with queued packets? */ + } else if (old_queue < ARP_TABLE_SIZE) { + /* recycle oldest pending (queued packets are free in etharp_free_entry) */ + i = old_queue; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest pending entry %"U16_F", freeing packet queue %p\n", (u16_t)i, (void *)(arp_table[i].q))); + /* no empty or recyclable entries found */ + } else { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: no empty or recyclable entries found\n")); + return (s8_t)ERR_MEM; + } + + /* { empty or recyclable entry found } */ + LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE); + etharp_free_entry(i); + } + + LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE); + LWIP_ASSERT("arp_table[i].state == ETHARP_STATE_EMPTY", + arp_table[i].state == ETHARP_STATE_EMPTY); + + /* IP address given? */ + if (ipaddr != NULL) { + /* set IP address */ + ip_addr_copy(arp_table[i].ipaddr, *ipaddr); + } + arp_table[i].ctime = 0; + return (err_t)i; +} + +/** + * Send an IP packet on the network using netif->linkoutput + * The ethernet header is filled in before sending. + * + * @params netif the lwIP network interface on which to send the packet + * @params p the packet to send, p->payload pointing to the (uninitialized) ethernet header + * @params src the source MAC address to be copied into the ethernet header + * @params dst the destination MAC address to be copied into the ethernet header + * @return ERR_OK if the packet was sent, any other err_t on failure + */ +static err_t +etharp_send_ip(struct netif *netif, struct pbuf *p, struct eth_addr *src, struct eth_addr *dst) +{ + struct eth_hdr *ethhdr = (struct eth_hdr *)p->payload; +#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) + struct eth_vlan_hdr *vlanhdr; +#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ + + LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!", + (netif->hwaddr_len == ETHARP_HWADDR_LEN)); +#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) + ethhdr->type = PP_HTONS(ETHTYPE_VLAN); + vlanhdr = (struct eth_vlan_hdr*)(((u8_t*)ethhdr) + SIZEOF_ETH_HDR); + vlanhdr->prio_vid = 0; + vlanhdr->tpid = PP_HTONS(ETHTYPE_IP); + if (!LWIP_HOOK_VLAN_SET(netif, ethhdr, vlanhdr)) { + /* packet shall not contain VLAN header, so hide it and set correct ethertype */ + pbuf_header(p, -SIZEOF_VLAN_HDR); + ethhdr = (struct eth_hdr *)p->payload; +#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ + ethhdr->type = PP_HTONS(ETHTYPE_IP); +#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) + } +#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ + ETHADDR32_COPY(ðhdr->dest, dst); + ETHADDR16_COPY(ðhdr->src, src); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_send_ip: sending packet %p\n", (void *)p)); + /* send the packet */ + return netif->linkoutput(netif, p); +} + +/** + * Update (or insert) a IP/MAC address pair in the ARP cache. + * + * If a pending entry is resolved, any queued packets will be sent + * at this point. + * + * @param netif netif related to this entry (used for NETIF_ADDRHINT) + * @param ipaddr IP address of the inserted ARP entry. + * @param ethaddr Ethernet address of the inserted ARP entry. + * @param flags @see definition of ETHARP_FLAG_* + * + * @return + * - ERR_OK Successfully updated ARP cache. + * - ERR_MEM If we could not add a new ARP entry when ETHARP_FLAG_TRY_HARD was set. + * - ERR_ARG Non-unicast address given, those will not appear in ARP cache. + * + * @see pbuf_free() + */ +static err_t +etharp_update_arp_entry(struct netif *netif, ip_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags) +{ + s8_t i; + LWIP_ASSERT("netif->hwaddr_len == ETHARP_HWADDR_LEN", netif->hwaddr_len == ETHARP_HWADDR_LEN); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n", + ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr), + ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2], + ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5])); + /* non-unicast address? */ + if (ip_addr_isany(ipaddr) || + ip_addr_isbroadcast(ipaddr, netif) || + ip_addr_ismulticast(ipaddr)) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: will not add non-unicast IP address to ARP cache\n")); + return ERR_ARG; + } + /* find or create ARP entry */ + i = etharp_find_entry(ipaddr, flags); + /* bail out if no entry could be found */ + if (i < 0) { + return (err_t)i; + } + +#if ETHARP_SUPPORT_STATIC_ENTRIES + if (flags & ETHARP_FLAG_STATIC_ENTRY) { + /* record static type */ + arp_table[i].state = ETHARP_STATE_STATIC; + } else +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + { + /* mark it stable */ + arp_table[i].state = ETHARP_STATE_STABLE; + } + + /* record network interface */ + arp_table[i].netif = netif; + /* insert in SNMP ARP index tree */ + snmp_insert_arpidx_tree(netif, &arp_table[i].ipaddr); + + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: updating stable entry %"S16_F"\n", (s16_t)i)); + /* update address */ + ETHADDR32_COPY(&arp_table[i].ethaddr, ethaddr); + /* reset time stamp */ + arp_table[i].ctime = 0; + /* this is where we will send out queued packets! */ +#if ARP_QUEUEING + while (arp_table[i].q != NULL) { + struct pbuf *p; + /* remember remainder of queue */ + struct etharp_q_entry *q = arp_table[i].q; + /* pop first item off the queue */ + arp_table[i].q = q->next; + /* get the packet pointer */ + p = q->p; + /* now queue entry can be freed */ + memp_free(MEMP_ARP_QUEUE, q); +#else /* ARP_QUEUEING */ + if (arp_table[i].q != NULL) { + struct pbuf *p = arp_table[i].q; + arp_table[i].q = NULL; +#endif /* ARP_QUEUEING */ + /* send the queued IP packet */ + etharp_send_ip(netif, p, (struct eth_addr*)(netif->hwaddr), ethaddr); + /* free the queued IP packet */ + pbuf_free(p); + } + return ERR_OK; +} + +#if ETHARP_SUPPORT_STATIC_ENTRIES +/** Add a new static entry to the ARP table. If an entry exists for the + * specified IP address, this entry is overwritten. + * If packets are queued for the specified IP address, they are sent out. + * + * @param ipaddr IP address for the new static entry + * @param ethaddr ethernet address for the new static entry + * @return @see return values of etharp_add_static_entry + */ +err_t +etharp_add_static_entry(ip_addr_t *ipaddr, struct eth_addr *ethaddr) +{ + struct netif *netif; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_add_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n", + ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr), + ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2], + ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5])); + + netif = ip_route(ipaddr); + if (netif == NULL) { + return ERR_RTE; + } + + return etharp_update_arp_entry(netif, ipaddr, ethaddr, ETHARP_FLAG_TRY_HARD | ETHARP_FLAG_STATIC_ENTRY); +} + +/** Remove a static entry from the ARP table previously added with a call to + * etharp_add_static_entry. + * + * @param ipaddr IP address of the static entry to remove + * @return ERR_OK: entry removed + * ERR_MEM: entry wasn't found + * ERR_ARG: entry wasn't a static entry but a dynamic one + */ +err_t +etharp_remove_static_entry(ip_addr_t *ipaddr) +{ + s8_t i; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_remove_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr))); + + /* find or create ARP entry */ + i = etharp_find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY); + /* bail out if no entry could be found */ + if (i < 0) { + return (err_t)i; + } + + if (arp_table[i].state != ETHARP_STATE_STATIC) { + /* entry wasn't a static entry, cannot remove it */ + return ERR_ARG; + } + /* entry found, free it */ + etharp_free_entry(i); + return ERR_OK; +} +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + +/** + * Remove all ARP table entries of the specified netif. + * + * @param netif points to a network interface + */ +void etharp_cleanup_netif(struct netif *netif) +{ + u8_t i; + + for (i = 0; i < ARP_TABLE_SIZE; ++i) { + u8_t state = arp_table[i].state; + if ((state != ETHARP_STATE_EMPTY) && (arp_table[i].netif == netif)) { + etharp_free_entry(i); + } + } +} + +/** + * Finds (stable) ethernet/IP address pair from ARP table + * using interface and IP address index. + * @note the addresses in the ARP table are in network order! + * + * @param netif points to interface index + * @param ipaddr points to the (network order) IP address index + * @param eth_ret points to return pointer + * @param ip_ret points to return pointer + * @return table index if found, -1 otherwise + */ +s8_t +etharp_find_addr(struct netif *netif, ip_addr_t *ipaddr, + struct eth_addr **eth_ret, ip_addr_t **ip_ret) +{ + s8_t i; + + LWIP_ASSERT("eth_ret != NULL && ip_ret != NULL", + eth_ret != NULL && ip_ret != NULL); + + LWIP_UNUSED_ARG(netif); + + i = etharp_find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY); + if((i >= 0) && (arp_table[i].state >= ETHARP_STATE_STABLE)) { + *eth_ret = &arp_table[i].ethaddr; + *ip_ret = &arp_table[i].ipaddr; + return i; + } + return -1; +} + +#if ETHARP_TRUST_IP_MAC +/** + * Updates the ARP table using the given IP packet. + * + * Uses the incoming IP packet's source address to update the + * ARP cache for the local network. The function does not alter + * or free the packet. This function must be called before the + * packet p is passed to the IP layer. + * + * @param netif The lwIP network interface on which the IP packet pbuf arrived. + * @param p The IP packet that arrived on netif. + * + * @return NULL + * + * @see pbuf_free() + */ +static void +etharp_ip_input(struct netif *netif, struct pbuf *p) +{ + struct eth_hdr *ethhdr; + struct ip_hdr *iphdr; + ip_addr_t iphdr_src; + LWIP_ERROR("netif != NULL", (netif != NULL), return;); + + /* Only insert an entry if the source IP address of the + incoming IP packet comes from a host on the local network. */ + ethhdr = (struct eth_hdr *)p->payload; + iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR); +#if ETHARP_SUPPORT_VLAN + if (ethhdr->type == PP_HTONS(ETHTYPE_VLAN)) { + iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR); + } +#endif /* ETHARP_SUPPORT_VLAN */ + + ip_addr_copy(iphdr_src, iphdr->src); + + /* source is not on the local network? */ + if (!ip_addr_netcmp(&iphdr_src, &(netif->ip_addr), &(netif->netmask))) { + /* do nothing */ + return; + } + + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_ip_input: updating ETHARP table.\n")); + /* update the source IP address in the cache, if present */ + /* @todo We could use ETHARP_FLAG_TRY_HARD if we think we are going to talk + * back soon (for example, if the destination IP address is ours. */ + etharp_update_arp_entry(netif, &iphdr_src, &(ethhdr->src), ETHARP_FLAG_FIND_ONLY); +} +#endif /* ETHARP_TRUST_IP_MAC */ + +/** + * Responds to ARP requests to us. Upon ARP replies to us, add entry to cache + * send out queued IP packets. Updates cache with snooped address pairs. + * + * Should be called for incoming ARP packets. The pbuf in the argument + * is freed by this function. + * + * @param netif The lwIP network interface on which the ARP packet pbuf arrived. + * @param ethaddr Ethernet address of netif. + * @param p The ARP packet that arrived on netif. Is freed by this function. + * + * @return NULL + * + * @see pbuf_free() + */ +static void +etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p) +{ + struct etharp_hdr *hdr; + struct eth_hdr *ethhdr; + /* these are aligned properly, whereas the ARP header fields might not be */ + ip_addr_t sipaddr, dipaddr; + u8_t for_us; +#if LWIP_AUTOIP + const u8_t * ethdst_hwaddr; +#endif /* LWIP_AUTOIP */ + + LWIP_ERROR("netif != NULL", (netif != NULL), return;); + + /* drop short ARP packets: we have to check for p->len instead of p->tot_len here + since a struct etharp_hdr is pointed to p->payload, so it musn't be chained! */ + if (p->len < SIZEOF_ETHARP_PACKET) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("etharp_arp_input: packet dropped, too short (%"S16_F"/%"S16_F")\n", p->tot_len, + (s16_t)SIZEOF_ETHARP_PACKET)); + ETHARP_STATS_INC(etharp.lenerr); + ETHARP_STATS_INC(etharp.drop); + pbuf_free(p); + return; + } + + ethhdr = (struct eth_hdr *)p->payload; + hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR); +#if ETHARP_SUPPORT_VLAN + if (ethhdr->type == PP_HTONS(ETHTYPE_VLAN)) { + hdr = (struct etharp_hdr *)(((u8_t*)ethhdr) + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR); + } +#endif /* ETHARP_SUPPORT_VLAN */ + + /* RFC 826 "Packet Reception": */ + if ((hdr->hwtype != PP_HTONS(HWTYPE_ETHERNET)) || + (hdr->hwlen != ETHARP_HWADDR_LEN) || + (hdr->protolen != sizeof(ip_addr_t)) || + (hdr->proto != PP_HTONS(ETHTYPE_IP))) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, + ("etharp_arp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n", + hdr->hwtype, hdr->hwlen, hdr->proto, hdr->protolen)); + ETHARP_STATS_INC(etharp.proterr); + ETHARP_STATS_INC(etharp.drop); + pbuf_free(p); + return; + } + ETHARP_STATS_INC(etharp.recv); + +#if LWIP_AUTOIP + /* We have to check if a host already has configured our random + * created link local address and continuously check if there is + * a host with this IP-address so we can detect collisions */ + autoip_arp_reply(netif, hdr); +#endif /* LWIP_AUTOIP */ + + /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without + * structure packing (not using structure copy which breaks strict-aliasing rules). */ + IPADDR2_COPY(&sipaddr, &hdr->sipaddr); + IPADDR2_COPY(&dipaddr, &hdr->dipaddr); + + /* this interface is not configured? */ + if (ip_addr_isany(&netif->ip_addr)) { + for_us = 0; + } else { + /* ARP packet directed to us? */ + for_us = (u8_t)ip_addr_cmp(&dipaddr, &(netif->ip_addr)); + } + + /* ARP message directed to us? + -> add IP address in ARP cache; assume requester wants to talk to us, + can result in directly sending the queued packets for this host. + ARP message not directed to us? + -> update the source IP address in the cache, if present */ + etharp_update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), + for_us ? ETHARP_FLAG_TRY_HARD : ETHARP_FLAG_FIND_ONLY); + + /* now act on the message itself */ + switch (hdr->opcode) { + /* ARP request? */ + case PP_HTONS(ARP_REQUEST): + /* ARP request. If it asked for our address, we send out a + * reply. In any case, we time-stamp any existing ARP entry, + * and possibly send out an IP packet that was queued on it. */ + + LWIP_DEBUGF (ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: incoming ARP request\n")); + /* ARP request for our address? */ + if (for_us) { + + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: replying to ARP request for our IP address\n")); + /* Re-use pbuf to send ARP reply. + Since we are re-using an existing pbuf, we can't call etharp_raw since + that would allocate a new pbuf. */ + hdr->opcode = htons(ARP_REPLY); + + IPADDR2_COPY(&hdr->dipaddr, &hdr->sipaddr); + IPADDR2_COPY(&hdr->sipaddr, &netif->ip_addr); + + LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!", + (netif->hwaddr_len == ETHARP_HWADDR_LEN)); +#if LWIP_AUTOIP + /* If we are using Link-Local, all ARP packets that contain a Link-Local + * 'sender IP address' MUST be sent using link-layer broadcast instead of + * link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */ + ethdst_hwaddr = ip_addr_islinklocal(&netif->ip_addr) ? (u8_t*)(ethbroadcast.addr) : hdr->shwaddr.addr; +#endif /* LWIP_AUTOIP */ + + ETHADDR16_COPY(&hdr->dhwaddr, &hdr->shwaddr); +#if LWIP_AUTOIP + ETHADDR16_COPY(ðhdr->dest, ethdst_hwaddr); +#else /* LWIP_AUTOIP */ + ETHADDR16_COPY(ðhdr->dest, &hdr->shwaddr); +#endif /* LWIP_AUTOIP */ + ETHADDR16_COPY(&hdr->shwaddr, ethaddr); + ETHADDR16_COPY(ðhdr->src, ethaddr); + + /* hwtype, hwaddr_len, proto, protolen and the type in the ethernet header + are already correct, we tested that before */ + + /* return ARP reply */ + netif->linkoutput(netif, p); + /* we are not configured? */ + } else if (ip_addr_isany(&netif->ip_addr)) { + /* { for_us == 0 and netif->ip_addr.addr == 0 } */ + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: we are unconfigured, ARP request ignored.\n")); + /* request was not directed to us */ + } else { + /* { for_us == 0 and netif->ip_addr.addr != 0 } */ + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: ARP request was not for us.\n")); + } + break; + case PP_HTONS(ARP_REPLY): + /* ARP reply. We already updated the ARP cache earlier. */ + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: incoming ARP reply\n")); +#if (LWIP_DHCP && DHCP_DOES_ARP_CHECK) + /* DHCP wants to know about ARP replies from any host with an + * IP address also offered to us by the DHCP server. We do not + * want to take a duplicate IP address on a single network. + * @todo How should we handle redundant (fail-over) interfaces? */ + dhcp_arp_reply(netif, &sipaddr); +#endif /* (LWIP_DHCP && DHCP_DOES_ARP_CHECK) */ + break; + default: + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: ARP unknown opcode type %"S16_F"\n", htons(hdr->opcode))); + ETHARP_STATS_INC(etharp.err); + break; + } + /* free ARP packet */ + pbuf_free(p); +} + +/** Just a small helper function that sends a pbuf to an ethernet address + * in the arp_table specified by the index 'arp_idx'. + */ +static err_t +etharp_output_to_arp_index(struct netif *netif, struct pbuf *q, u8_t arp_idx) +{ + LWIP_ASSERT("arp_table[arp_idx].state >= ETHARP_STATE_STABLE", + arp_table[arp_idx].state >= ETHARP_STATE_STABLE); + /* if arp table entry is about to expire: re-request it, + but only if its state is ETHARP_STATE_STABLE to prevent flooding the + network with ARP requests if this address is used frequently. */ + if ((arp_table[arp_idx].state == ETHARP_STATE_STABLE) && + (arp_table[arp_idx].ctime >= ARP_AGE_REREQUEST_USED)) { + if (etharp_request(netif, &arp_table[arp_idx].ipaddr) == ERR_OK) { + arp_table[arp_idx].state = ETHARP_STATE_STABLE_REREQUESTING; + } + } + + return etharp_send_ip(netif, q, (struct eth_addr*)(netif->hwaddr), + &arp_table[arp_idx].ethaddr); +} + +/** + * Resolve and fill-in Ethernet address header for outgoing IP packet. + * + * For IP multicast and broadcast, corresponding Ethernet addresses + * are selected and the packet is transmitted on the link. + * + * For unicast addresses, the packet is submitted to etharp_query(). In + * case the IP address is outside the local network, the IP address of + * the gateway is used. + * + * @param netif The lwIP network interface which the IP packet will be sent on. + * @param q The pbuf(s) containing the IP packet to be sent. + * @param ipaddr The IP address of the packet destination. + * + * @return + * - ERR_RTE No route to destination (no gateway to external networks), + * or the return type of either etharp_query() or etharp_send_ip(). + */ +err_t +etharp_output(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr) +{ + struct eth_addr *dest; + struct eth_addr mcastaddr; + ip_addr_t *dst_addr = ipaddr; + + LWIP_ASSERT("netif != NULL", netif != NULL); + LWIP_ASSERT("q != NULL", q != NULL); + LWIP_ASSERT("ipaddr != NULL", ipaddr != NULL); + + /* make room for Ethernet header - should not fail */ +#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) + if (pbuf_header(q, sizeof(struct eth_hdr) + SIZEOF_VLAN_HDR) != 0) { +#else /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ + if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) { +#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ + /* bail out */ + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("etharp_output: could not allocate room for header.\n")); + LINK_STATS_INC(link.lenerr); + return ERR_BUF; + } + + /* Determine on destination hardware address. Broadcasts and multicasts + * are special, other IP addresses are looked up in the ARP table. */ + + /* broadcast destination IP address? */ + if (ip_addr_isbroadcast(ipaddr, netif)) { + /* broadcast on Ethernet also */ + dest = (struct eth_addr *)ðbroadcast; + /* multicast destination IP address? */ + } else if (ip_addr_ismulticast(ipaddr)) { + /* Hash IP multicast address to MAC address.*/ + mcastaddr.addr[0] = LL_MULTICAST_ADDR_0; + mcastaddr.addr[1] = LL_MULTICAST_ADDR_1; + mcastaddr.addr[2] = LL_MULTICAST_ADDR_2; + mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f; + mcastaddr.addr[4] = ip4_addr3(ipaddr); + mcastaddr.addr[5] = ip4_addr4(ipaddr); + /* destination Ethernet address is multicast */ + dest = &mcastaddr; + /* unicast destination IP address? */ + } else { + s8_t i; + /* outside local network? if so, this can neither be a global broadcast nor + a subnet broadcast. */ + if (!ip_addr_netcmp(ipaddr, &(netif->ip_addr), &(netif->netmask)) && + !ip_addr_islinklocal(ipaddr)) { +#if LWIP_AUTOIP + struct ip_hdr *iphdr = (struct ip_hdr*)((u8_t*)q->payload + +#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) + SIZEOF_VLAN_HDR + +#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ + sizeof(struct eth_hdr)); + /* According to RFC 3297, chapter 2.6.2 (Forwarding Rules), a packet with + a link-local source address must always be "directly to its destination + on the same physical link. The host MUST NOT send the packet to any + router for forwarding". */ + if (!ip_addr_islinklocal(&iphdr->src)) +#endif /* LWIP_AUTOIP */ + { +#ifdef LWIP_HOOK_ETHARP_GET_GW + /* For advanced routing, a single default gateway might not be enough, so get + the IP address of the gateway to handle the current destination address. */ + dst_addr = LWIP_HOOK_ETHARP_GET_GW(netif, ipaddr); + if(dst_addr == NULL) +#endif /* LWIP_HOOK_ETHARP_GET_GW */ + { + /* interface has default gateway? */ + if (!ip_addr_isany(&netif->gw)) { + /* send to hardware address of default gateway IP address */ + dst_addr = &(netif->gw); + /* no default gateway available */ + } else { + /* no route to destination error (default gateway missing) */ + return ERR_RTE; + } + } + } + } +#if LWIP_NETIF_HWADDRHINT + if (netif->addr_hint != NULL) { + /* per-pcb cached entry was given */ + u8_t etharp_cached_entry = *(netif->addr_hint); + if (etharp_cached_entry < ARP_TABLE_SIZE) { +#endif /* LWIP_NETIF_HWADDRHINT */ + if ((arp_table[etharp_cached_entry].state >= ETHARP_STATE_STABLE) && + (ip_addr_cmp(dst_addr, &arp_table[etharp_cached_entry].ipaddr))) { + /* the per-pcb-cached entry is stable and the right one! */ + ETHARP_STATS_INC(etharp.cachehit); + return etharp_output_to_arp_index(netif, q, etharp_cached_entry); + } +#if LWIP_NETIF_HWADDRHINT + } + } +#endif /* LWIP_NETIF_HWADDRHINT */ + + /* find stable entry: do this here since this is a critical path for + throughput and etharp_find_entry() is kind of slow */ + for (i = 0; i < ARP_TABLE_SIZE; i++) { + if ((arp_table[i].state >= ETHARP_STATE_STABLE) && + (ip_addr_cmp(dst_addr, &arp_table[i].ipaddr))) { + /* found an existing, stable entry */ + ETHARP_SET_HINT(netif, i); + return etharp_output_to_arp_index(netif, q, i); + } + } + /* no stable entry found, use the (slower) query function: + queue on destination Ethernet address belonging to ipaddr */ + return etharp_query(netif, dst_addr, q); + } + + /* continuation for multicast/broadcast destinations */ + /* obtain source Ethernet address of the given interface */ + /* send packet directly on the link */ + return etharp_send_ip(netif, q, (struct eth_addr*)(netif->hwaddr), dest); +} + +/** + * Send an ARP request for the given IP address and/or queue a packet. + * + * If the IP address was not yet in the cache, a pending ARP cache entry + * is added and an ARP request is sent for the given address. The packet + * is queued on this entry. + * + * If the IP address was already pending in the cache, a new ARP request + * is sent for the given address. The packet is queued on this entry. + * + * If the IP address was already stable in the cache, and a packet is + * given, it is directly sent and no ARP request is sent out. + * + * If the IP address was already stable in the cache, and no packet is + * given, an ARP request is sent out. + * + * @param netif The lwIP network interface on which ipaddr + * must be queried for. + * @param ipaddr The IP address to be resolved. + * @param q If non-NULL, a pbuf that must be delivered to the IP address. + * q is not freed by this function. + * + * @note q must only be ONE packet, not a packet queue! + * + * @return + * - ERR_BUF Could not make room for Ethernet header. + * - ERR_MEM Hardware address unknown, and no more ARP entries available + * to query for address or queue the packet. + * - ERR_MEM Could not queue packet due to memory shortage. + * - ERR_RTE No route to destination (no gateway to external networks). + * - ERR_ARG Non-unicast address given, those will not appear in ARP cache. + * + */ +err_t +etharp_query(struct netif *netif, ip_addr_t *ipaddr, struct pbuf *q) +{ + struct eth_addr * srcaddr = (struct eth_addr *)netif->hwaddr; + err_t result = ERR_MEM; + int is_new_entry = 0; + s8_t i; /* ARP entry index */ + + /* non-unicast address? */ + if (ip_addr_isbroadcast(ipaddr, netif) || + ip_addr_ismulticast(ipaddr) || + ip_addr_isany(ipaddr)) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: will not add non-unicast IP address to ARP cache\n")); + return ERR_ARG; + } + + /* find entry in ARP cache, ask to create entry if queueing packet */ + i = etharp_find_entry(ipaddr, ETHARP_FLAG_TRY_HARD); + + /* could not find or create entry? */ + if (i < 0) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not create ARP entry\n")); + if (q) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: packet dropped\n")); + ETHARP_STATS_INC(etharp.memerr); + } + return (err_t)i; + } + + /* mark a fresh entry as pending (we just sent a request) */ + if (arp_table[i].state == ETHARP_STATE_EMPTY) { + is_new_entry = 1; + arp_table[i].state = ETHARP_STATE_PENDING; + /* record network interface for re-sending arp request in etharp_tmr */ + arp_table[i].netif = netif; + } + + /* { i is either a STABLE or (new or existing) PENDING entry } */ + LWIP_ASSERT("arp_table[i].state == PENDING or STABLE", + ((arp_table[i].state == ETHARP_STATE_PENDING) || + (arp_table[i].state >= ETHARP_STATE_STABLE))); + + /* do we have a new entry? or an implicit query request? */ + if (is_new_entry || (q == NULL)) { + /* try to resolve it; send out ARP request */ + result = etharp_request(netif, ipaddr); + if (result != ERR_OK) { + /* ARP request couldn't be sent */ + /* We don't re-send arp request in etharp_tmr, but we still queue packets, + since this failure could be temporary, and the next packet calling + etharp_query again could lead to sending the queued packets. */ + } + if (q == NULL) { + return result; + } + } + + /* packet given? */ + LWIP_ASSERT("q != NULL", q != NULL); + /* stable entry? */ + if (arp_table[i].state >= ETHARP_STATE_STABLE) { + /* we have a valid IP->Ethernet address mapping */ + ETHARP_SET_HINT(netif, i); + /* send the packet */ + result = etharp_send_ip(netif, q, srcaddr, &(arp_table[i].ethaddr)); + /* pending entry? (either just created or already pending */ + } else if (arp_table[i].state == ETHARP_STATE_PENDING) { + /* entry is still pending, queue the given packet 'q' */ + struct pbuf *p; + int copy_needed = 0; + /* IF q includes a PBUF_REF, PBUF_POOL or PBUF_RAM, we have no choice but + * to copy the whole queue into a new PBUF_RAM (see bug #11400) + * PBUF_ROMs can be left as they are, since ROM must not get changed. */ + p = q; + while (p) { + LWIP_ASSERT("no packet queues allowed!", (p->len != p->tot_len) || (p->next == 0)); + if(p->type != PBUF_ROM) { + copy_needed = 1; + break; + } + p = p->next; + } + if(copy_needed) { + /* copy the whole packet into new pbufs */ + p = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); + if(p != NULL) { + if (pbuf_copy(p, q) != ERR_OK) { + pbuf_free(p); + p = NULL; + } + } + } else { + /* referencing the old pbuf is enough */ + p = q; + pbuf_ref(p); + } + /* packet could be taken over? */ + if (p != NULL) { + /* queue packet ... */ +#if ARP_QUEUEING + struct etharp_q_entry *new_entry; + /* allocate a new arp queue entry */ + new_entry = (struct etharp_q_entry *)memp_malloc(MEMP_ARP_QUEUE); + if (new_entry != NULL) { + unsigned int qlen = 0; + new_entry->next = 0; + new_entry->p = p; + if(arp_table[i].q != NULL) { + /* queue was already existent, append the new entry to the end */ + struct etharp_q_entry *r; + r = arp_table[i].q; + qlen++; + while (r->next != NULL) { + r = r->next; + qlen++; + } + r->next = new_entry; + } else { + /* queue did not exist, first item in queue */ + arp_table[i].q = new_entry; + } +#if ARP_QUEUE_LEN + if (qlen >= ARP_QUEUE_LEN) { + struct etharp_q_entry *old; + old = arp_table[i].q; + arp_table[i].q = arp_table[i].q->next; + pbuf_free(old->p); + memp_free(MEMP_ARP_QUEUE, old); + } +#endif + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i)); + result = ERR_OK; + } else { + /* the pool MEMP_ARP_QUEUE is empty */ + pbuf_free(p); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q)); + result = ERR_MEM; + } +#else /* ARP_QUEUEING */ + /* always queue one packet per ARP request only, freeing a previously queued packet */ + if (arp_table[i].q != NULL) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: dropped previously queued packet %p for ARP entry %"S16_F"\n", (void *)q, (s16_t)i)); + pbuf_free(arp_table[i].q); + } + arp_table[i].q = p; + result = ERR_OK; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i)); +#endif /* ARP_QUEUEING */ + } else { + ETHARP_STATS_INC(etharp.memerr); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q)); + result = ERR_MEM; + } + } + return result; +} + +/** + * Send a raw ARP packet (opcode and all addresses can be modified) + * + * @param netif the lwip network interface on which to send the ARP packet + * @param ethsrc_addr the source MAC address for the ethernet header + * @param ethdst_addr the destination MAC address for the ethernet header + * @param hwsrc_addr the source MAC address for the ARP protocol header + * @param ipsrc_addr the source IP address for the ARP protocol header + * @param hwdst_addr the destination MAC address for the ARP protocol header + * @param ipdst_addr the destination IP address for the ARP protocol header + * @param opcode the type of the ARP packet + * @return ERR_OK if the ARP packet has been sent + * ERR_MEM if the ARP packet couldn't be allocated + * any other err_t on failure + */ +#if !LWIP_AUTOIP +static +#endif /* LWIP_AUTOIP */ +err_t +etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr, + const struct eth_addr *ethdst_addr, + const struct eth_addr *hwsrc_addr, const ip_addr_t *ipsrc_addr, + const struct eth_addr *hwdst_addr, const ip_addr_t *ipdst_addr, + const u16_t opcode) +{ + struct pbuf *p; + err_t result = ERR_OK; + struct eth_hdr *ethhdr; +#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) + struct eth_vlan_hdr *vlanhdr; +#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ + struct etharp_hdr *hdr; +#if LWIP_AUTOIP + const u8_t * ethdst_hwaddr; +#endif /* LWIP_AUTOIP */ + + LWIP_ASSERT("netif != NULL", netif != NULL); + + /* allocate a pbuf for the outgoing ARP request packet */ + p = pbuf_alloc(PBUF_RAW, SIZEOF_ETHARP_PACKET_TX, PBUF_RAM); + /* could allocate a pbuf for an ARP request? */ + if (p == NULL) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, + ("etharp_raw: could not allocate pbuf for ARP request.\n")); + ETHARP_STATS_INC(etharp.memerr); + return ERR_MEM; + } + LWIP_ASSERT("check that first pbuf can hold struct etharp_hdr", + (p->len >= SIZEOF_ETHARP_PACKET_TX)); + + ethhdr = (struct eth_hdr *)p->payload; +#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) + vlanhdr = (struct eth_vlan_hdr*)(((u8_t*)ethhdr) + SIZEOF_ETH_HDR); + hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR); +#else /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ + hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR); +#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_raw: sending raw ARP packet.\n")); + hdr->opcode = htons(opcode); + + LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!", + (netif->hwaddr_len == ETHARP_HWADDR_LEN)); +#if LWIP_AUTOIP + /* If we are using Link-Local, all ARP packets that contain a Link-Local + * 'sender IP address' MUST be sent using link-layer broadcast instead of + * link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */ + ethdst_hwaddr = ip_addr_islinklocal(ipsrc_addr) ? (u8_t*)(ethbroadcast.addr) : ethdst_addr->addr; +#endif /* LWIP_AUTOIP */ + /* Write the ARP MAC-Addresses */ + ETHADDR16_COPY(&hdr->shwaddr, hwsrc_addr); + ETHADDR16_COPY(&hdr->dhwaddr, hwdst_addr); + /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without + * structure packing. */ + IPADDR2_COPY(&hdr->sipaddr, ipsrc_addr); + IPADDR2_COPY(&hdr->dipaddr, ipdst_addr); + + hdr->hwtype = PP_HTONS(HWTYPE_ETHERNET); + hdr->proto = PP_HTONS(ETHTYPE_IP); + /* set hwlen and protolen */ + hdr->hwlen = ETHARP_HWADDR_LEN; + hdr->protolen = sizeof(ip_addr_t); + +#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) + ethhdr->type = PP_HTONS(ETHTYPE_VLAN); + vlanhdr->tpid = PP_HTONS(ETHTYPE_ARP); + vlanhdr->prio_vid = 0; + if (!LWIP_HOOK_VLAN_SET(netif, ethhdr, vlanhdr)) { + /* packet shall not contain VLAN header, so hide it and set correct ethertype */ + pbuf_header(p, -SIZEOF_VLAN_HDR); + ethhdr = (struct eth_hdr *)p->payload; +#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ + ethhdr->type = PP_HTONS(ETHTYPE_ARP); +#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) + } +#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ + + /* Write the Ethernet MAC-Addresses */ +#if LWIP_AUTOIP + ETHADDR16_COPY(ðhdr->dest, ethdst_hwaddr); +#else /* LWIP_AUTOIP */ + ETHADDR16_COPY(ðhdr->dest, ethdst_addr); +#endif /* LWIP_AUTOIP */ + ETHADDR16_COPY(ðhdr->src, ethsrc_addr); + + /* send ARP query */ + result = netif->linkoutput(netif, p); + ETHARP_STATS_INC(etharp.xmit); + /* free ARP query packet */ + pbuf_free(p); + p = NULL; + /* could not allocate pbuf for ARP request */ + + return result; +} + +/** + * Send an ARP request packet asking for ipaddr. + * + * @param netif the lwip network interface on which to send the request + * @param ipaddr the IP address for which to ask + * @return ERR_OK if the request has been sent + * ERR_MEM if the ARP packet couldn't be allocated + * any other err_t on failure + */ +err_t +etharp_request(struct netif *netif, ip_addr_t *ipaddr) +{ + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_request: sending ARP request.\n")); + return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, ðbroadcast, + (struct eth_addr *)netif->hwaddr, &netif->ip_addr, ðzero, + ipaddr, ARP_REQUEST); +} +#endif /* LWIP_ARP */ + +/** + * Process received ethernet frames. Using this function instead of directly + * calling ip_input and passing ARP frames through etharp in ethernetif_input, + * the ARP cache is protected from concurrent access. + * + * @param p the received packet, p->payload pointing to the ethernet header + * @param netif the network interface on which the packet was received + */ +err_t +ethernet_input(struct pbuf *p, struct netif *netif) +{ + struct eth_hdr* ethhdr; + u16_t type; +#if LWIP_ARP || ETHARP_SUPPORT_VLAN + s16_t ip_hdr_offset = SIZEOF_ETH_HDR; +#endif /* LWIP_ARP || ETHARP_SUPPORT_VLAN */ + + if (p->len <= SIZEOF_ETH_HDR) { + /* a packet with only an ethernet header (or less) is not valid for us */ + ETHARP_STATS_INC(etharp.proterr); + ETHARP_STATS_INC(etharp.drop); + goto free_and_return; + } + + /* points to packet payload, which starts with an Ethernet header */ + ethhdr = (struct eth_hdr *)p->payload; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, + ("ethernet_input: dest:%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F", src:%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F", type:%"X16_F"\n", + (unsigned)ethhdr->dest.addr[0], (unsigned)ethhdr->dest.addr[1], (unsigned)ethhdr->dest.addr[2], + (unsigned)ethhdr->dest.addr[3], (unsigned)ethhdr->dest.addr[4], (unsigned)ethhdr->dest.addr[5], + (unsigned)ethhdr->src.addr[0], (unsigned)ethhdr->src.addr[1], (unsigned)ethhdr->src.addr[2], + (unsigned)ethhdr->src.addr[3], (unsigned)ethhdr->src.addr[4], (unsigned)ethhdr->src.addr[5], + (unsigned)htons(ethhdr->type))); + + type = ethhdr->type; +#if ETHARP_SUPPORT_VLAN + if (type == PP_HTONS(ETHTYPE_VLAN)) { + struct eth_vlan_hdr *vlan = (struct eth_vlan_hdr*)(((char*)ethhdr) + SIZEOF_ETH_HDR); + if (p->len <= SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR) { + /* a packet with only an ethernet/vlan header (or less) is not valid for us */ + ETHARP_STATS_INC(etharp.proterr); + ETHARP_STATS_INC(etharp.drop); + goto free_and_return; + } +#if defined(LWIP_HOOK_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK_FN) /* if not, allow all VLANs */ +#ifdef LWIP_HOOK_VLAN_CHECK + if (!LWIP_HOOK_VLAN_CHECK(netif, ethhdr, vlan)) { +#elif defined(ETHARP_VLAN_CHECK_FN) + if (!ETHARP_VLAN_CHECK_FN(ethhdr, vlan)) { +#elif defined(ETHARP_VLAN_CHECK) + if (VLAN_ID(vlan) != ETHARP_VLAN_CHECK) { +#endif + /* silently ignore this packet: not for our VLAN */ + pbuf_free(p); + return ERR_OK; + } +#endif /* defined(LWIP_HOOK_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK_FN) */ + type = vlan->tpid; + ip_hdr_offset = SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR; + } +#endif /* ETHARP_SUPPORT_VLAN */ + +#if LWIP_ARP_FILTER_NETIF + netif = LWIP_ARP_FILTER_NETIF_FN(p, netif, htons(type)); +#endif /* LWIP_ARP_FILTER_NETIF*/ + + if (ethhdr->dest.addr[0] & 1) { + /* this might be a multicast or broadcast packet */ + if (ethhdr->dest.addr[0] == LL_MULTICAST_ADDR_0) { + if ((ethhdr->dest.addr[1] == LL_MULTICAST_ADDR_1) && + (ethhdr->dest.addr[2] == LL_MULTICAST_ADDR_2)) { + /* mark the pbuf as link-layer multicast */ + p->flags |= PBUF_FLAG_LLMCAST; + } + } else if (eth_addr_cmp(ðhdr->dest, ðbroadcast)) { + /* mark the pbuf as link-layer broadcast */ + p->flags |= PBUF_FLAG_LLBCAST; + } + } + + switch (type) { +#if LWIP_ARP + /* IP packet? */ + case PP_HTONS(ETHTYPE_IP): + if (!(netif->flags & NETIF_FLAG_ETHARP)) { + goto free_and_return; + } +#if ETHARP_TRUST_IP_MAC + /* update ARP table */ + etharp_ip_input(netif, p); +#endif /* ETHARP_TRUST_IP_MAC */ + /* skip Ethernet header */ + if(pbuf_header(p, (s16_t)-ip_hdr_offset)) { + LWIP_ASSERT("Can't move over header in packet", 0); + goto free_and_return; + } else { + /* pass to IP layer */ + ip_input(p, netif); + } + break; + + case PP_HTONS(ETHTYPE_ARP): + if (!(netif->flags & NETIF_FLAG_ETHARP)) { + goto free_and_return; + } + /* pass p to ARP module */ + etharp_arp_input(netif, (struct eth_addr*)(netif->hwaddr), p); + break; +#endif /* LWIP_ARP */ +#if PPPOE_SUPPORT + case PP_HTONS(ETHTYPE_PPPOEDISC): /* PPP Over Ethernet Discovery Stage */ + pppoe_disc_input(netif, p); + break; + + case PP_HTONS(ETHTYPE_PPPOE): /* PPP Over Ethernet Session Stage */ + pppoe_data_input(netif, p); + break; +#endif /* PPPOE_SUPPORT */ + +#if LWIP_IPV6 + case PP_HTONS(ETHTYPE_IPV6): /* IPv6 */ + /* skip Ethernet header */ + if(pbuf_header(p, -(s16_t)SIZEOF_ETH_HDR)) { + LWIP_ASSERT("Can't move over header in packet", 0); + goto free_and_return; + } else { + /* pass to IPv6 layer */ + ip6_input(p, netif); + } + break; +#endif /* LWIP_IPV6 */ + + default: + ETHARP_STATS_INC(etharp.proterr); + ETHARP_STATS_INC(etharp.drop); + goto free_and_return; + } + + /* This means the pbuf is freed or consumed, + so the caller doesn't have to free it again */ + return ERR_OK; + +free_and_return: + pbuf_free(p); + return ERR_OK; +} +#endif /* LWIP_ARP || LWIP_ETHERNET */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ethernetif.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ethernetif.c new file mode 100644 index 0000000..b9276b6 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ethernetif.c @@ -0,0 +1,322 @@ +/** + * @file + * Ethernet Interface Skeleton + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/* + * This file is a skeleton for developing Ethernet network interface + * drivers for lwIP. Add code to the low_level functions and do a + * search-and-replace for the word "ethernetif" to replace it with + * something that better describes your network interface. + */ + +#include "lwip/opt.h" + +#if 0 /* don't build, this is only a skeleton, see previous comment */ + +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "lwip/ethip6.h" +#include "netif/etharp.h" +#include "netif/ppp/pppoe.h" + +/* Define those to better describe your network interface. */ +#define IFNAME0 'e' +#define IFNAME1 'n' + +/** + * Helper struct to hold private data used to operate your ethernet interface. + * Keeping the ethernet address of the MAC in this struct is not necessary + * as it is already kept in the struct netif. + * But this is only an example, anyway... + */ +struct ethernetif { + struct eth_addr *ethaddr; + /* Add whatever per-interface state that is needed here. */ +}; + +/* Forward declarations. */ +static void ethernetif_input(struct netif *netif); + +/** + * In this function, the hardware should be initialized. + * Called from ethernetif_init(). + * + * @param netif the already initialized lwip network interface structure + * for this ethernetif + */ +static void +low_level_init(struct netif *netif) +{ + struct ethernetif *ethernetif = netif->state; + + /* set MAC hardware address length */ + netif->hwaddr_len = ETHARP_HWADDR_LEN; + + /* set MAC hardware address */ + netif->hwaddr[0] = ; + ... + netif->hwaddr[5] = ; + + /* maximum transfer unit */ + netif->mtu = 1500; + + /* device capabilities */ + /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; + + /* Do whatever else is needed to initialize interface. */ +} + +/** + * This function should do the actual transmission of the packet. The packet is + * contained in the pbuf that is passed to the function. This pbuf + * might be chained. + * + * @param netif the lwip network interface structure for this ethernetif + * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type) + * @return ERR_OK if the packet could be sent + * an err_t value if the packet couldn't be sent + * + * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to + * strange results. You might consider waiting for space in the DMA queue + * to become available since the stack doesn't retry to send a packet + * dropped because of memory failure (except for the TCP timers). + */ + +static err_t +low_level_output(struct netif *netif, struct pbuf *p) +{ + struct ethernetif *ethernetif = netif->state; + struct pbuf *q; + + initiate transfer(); + +#if ETH_PAD_SIZE + pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ +#endif + + for(q = p; q != NULL; q = q->next) { + /* Send the data from the pbuf to the interface, one pbuf at a + time. The size of the data in each pbuf is kept in the ->len + variable. */ + send data from(q->payload, q->len); + } + + signal that packet should be sent(); + +#if ETH_PAD_SIZE + pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ +#endif + + LINK_STATS_INC(link.xmit); + + return ERR_OK; +} + +/** + * Should allocate a pbuf and transfer the bytes of the incoming + * packet from the interface into the pbuf. + * + * @param netif the lwip network interface structure for this ethernetif + * @return a pbuf filled with the received packet (including MAC header) + * NULL on memory error + */ +static struct pbuf * +low_level_input(struct netif *netif) +{ + struct ethernetif *ethernetif = netif->state; + struct pbuf *p, *q; + u16_t len; + + /* Obtain the size of the packet and put it into the "len" + variable. */ + len = ; + +#if ETH_PAD_SIZE + len += ETH_PAD_SIZE; /* allow room for Ethernet padding */ +#endif + + /* We allocate a pbuf chain of pbufs from the pool. */ + p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); + + if (p != NULL) { + +#if ETH_PAD_SIZE + pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ +#endif + + /* We iterate over the pbuf chain until we have read the entire + * packet into the pbuf. */ + for(q = p; q != NULL; q = q->next) { + /* Read enough bytes to fill this pbuf in the chain. The + * available data in the pbuf is given by the q->len + * variable. + * This does not necessarily have to be a memcpy, you can also preallocate + * pbufs for a DMA-enabled MAC and after receiving truncate it to the + * actually received size. In this case, ensure the tot_len member of the + * pbuf is the sum of the chained pbuf len members. + */ + read data into(q->payload, q->len); + } + acknowledge that packet has been read(); + +#if ETH_PAD_SIZE + pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ +#endif + + LINK_STATS_INC(link.recv); + } else { + drop packet(); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + } + + return p; +} + +/** + * This function should be called when a packet is ready to be read + * from the interface. It uses the function low_level_input() that + * should handle the actual reception of bytes from the network + * interface. Then the type of the received packet is determined and + * the appropriate input function is called. + * + * @param netif the lwip network interface structure for this ethernetif + */ +static void +ethernetif_input(struct netif *netif) +{ + struct ethernetif *ethernetif; + struct eth_hdr *ethhdr; + struct pbuf *p; + + ethernetif = netif->state; + + /* move received packet into a new pbuf */ + p = low_level_input(netif); + /* no packet could be read, silently ignore this */ + if (p == NULL) return; + /* points to packet payload, which starts with an Ethernet header */ + ethhdr = p->payload; + + switch (htons(ethhdr->type)) { + /* IP or ARP packet? */ + case ETHTYPE_IP: + case ETHTYPE_IPV6: + case ETHTYPE_ARP: +#if PPPOE_SUPPORT + /* PPPoE packet? */ + case ETHTYPE_PPPOEDISC: + case ETHTYPE_PPPOE: +#endif /* PPPOE_SUPPORT */ + /* full packet send to tcpip_thread to process */ + if (netif->input(p, netif)!=ERR_OK) + { LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); + pbuf_free(p); + p = NULL; + } + break; + + default: + pbuf_free(p); + p = NULL; + break; + } +} + +/** + * Should be called at the beginning of the program to set up the + * network interface. It calls the function low_level_init() to do the + * actual setup of the hardware. + * + * This function should be passed as a parameter to netif_add(). + * + * @param netif the lwip network interface structure for this ethernetif + * @return ERR_OK if the loopif is initialized + * ERR_MEM if private data couldn't be allocated + * any other err_t on error + */ +err_t +ethernetif_init(struct netif *netif) +{ + struct ethernetif *ethernetif; + + LWIP_ASSERT("netif != NULL", (netif != NULL)); + + ethernetif = mem_malloc(sizeof(struct ethernetif)); + if (ethernetif == NULL) { + LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n")); + return ERR_MEM; + } + +#if LWIP_NETIF_HOSTNAME + /* Initialize interface hostname */ + netif->hostname = "lwip"; +#endif /* LWIP_NETIF_HOSTNAME */ + + /* + * Initialize the snmp variables and counters inside the struct netif. + * The last argument should be replaced with your link speed, in units + * of bits per second. + */ + NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS); + + netif->state = ethernetif; + netif->name[0] = IFNAME0; + netif->name[1] = IFNAME1; + /* We directly use etharp_output() here to save a function call. + * You can instead declare your own function an call etharp_output() + * from it if you have to do some checks before sending (e.g. if link + * is available...) */ + netif->output = etharp_output; +#if LWIP_IPV6 + netif->output_ip6 = ethip6_output; +#endif /* LWIP_IPV6 */ + netif->linkoutput = low_level_output; + + ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]); + + /* initialize the hardware */ + low_level_init(netif); + + return ERR_OK; +} + +#endif /* 0 */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/PPPD_FOLLOWUP b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/PPPD_FOLLOWUP new file mode 100644 index 0000000..4a82915 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/PPPD_FOLLOWUP @@ -0,0 +1,382 @@ +The lwIP PPP support is based from pppd 2.4.5 (http://ppp.samba.org) with +huge changes to match code size and memory requirements for embedded devices. + +Anyway, pppd has a mature codebase for years and the average commit count +is getting low on their Git repositories, meaning that we can follow what +is happening on their side and merge what is relevant for lwIP. + +So, here is the pppd follow up, so that we don't get away too far from pppd. + + +== Patch fetched from from pppd Debian packages == + +This has nothing to do with pppd, but we merged some good patch from +Debian and this is a good place to be. + +- LCP adaptive echo, so that we don't send LCP echo request if we + are receiving data from peer, can be enabled by setting PPP_LCP_ADAPTIVE + to true. + +- IPCP no/replace default route option, were added in the early stage of + the ppp port, but it wasn't really helpful and was disabled when adding + the new API ppp_set_default() call, which gives the lwIP user control over + which one is the default interface, it was actually a requirement if you + are doing PPP over PPP (i.e. PPPoL2TP, VPN link, over PPPoE, ADSL link). + +- using rp-pppoe pppd exits with EXIT_OK after receiving a timeout waiting + for PADO due to no modem attached, bug reported to pppd bug tracker, fixed + in Debian but not in the latest (at the time when the port were started) + pppd release. + + +== Commits on pppd == + +2010-03-06 - Document +ipv6 and ipv6cp-accept-local + e7537958aee79b3f653c601e903cb31d78fb7dcc + +Don't care. + + +2010-03-06 - Install pppol2tp plugins with sane permissions + 406215672cfadc03017341fe03802d1c7294b903 + +Don't care. + + +2010-03-07 - pppd: Terminate correctly if lcp_lowerup delayed calling + fsm_lowerup + 3eb9e810cfa515543655659b72dde30c54fea0a5 + +Merged 2012-05-17. + + +2010-03-07 - rp_pppoe: Copy acName and pppd_pppoe_service after option parsing + cab58617fd9d328029fffabc788020264b4fa91f + +Don't care, is a patch for pppd/plugins/rp-pppoe/plugin.c which is not part +of the port. + + +2010-08-23 - set and reset options to control environment variables + for scripts. + 2b6310fd24dba8e0fca8999916a162f0a1842a84 + +We can't fork processes in embedded, therefore all the pppd process run +feature is disabled in the port, so we don't care about the new +"environment variables" pppd feature. + + +2010-08-23 - Nit: use _exit when exec fails and restrict values to 0-255 + per POSIX. + 2b4ea140432eeba5a007c0d4e6236bd0e0c12ba4 + +Again, we are not running as a heavy process, so all exit() or _exit() calls +were removed. + + +2010-08-23 - Fix quote handling in configuration files to be more like shell + quoting. + 3089132cdf5b58dbdfc2daf08ec5c08eb47f8aca + +We are not parsing config file, all the filesystem I/O stuff were disabled +in our port. + + +2010-08-24 - rp-pppoe: allow MTU to be increased up to 1500 + fd1dcdf758418f040da3ed801ab001b5e46854e7 + +Only concern changes on RP-PPPoE plugin, which we don't use. + + +2010-09-11 - chat: Allow TIMEOUT value to come from environment variable + ae80bf833e48a6202f44a935a68083ae52ad3824 + +See 2b6310fd24dba8e0fca8999916a162f0a1842a84. + + +2011-03-05 - pppdump: Fix printfs with insufficient arguments + 7b8db569642c83ba3283745034f2e2c95e459423 + +pppdump is a ppp tool outside pppd source tree. + + +2012-05-06 - pppd: Don't unconditionally disable VJ compression under Linux + d8a66adf98a0e525cf38031b42098d539da6eeb6 + +Patch for sys-linux.c, which we don't use. + + +2012-05-20 - Remove old version of Linux if_pppol2tp.h + c41092dd4c49267f232f6cba3d31c6c68bfdf68d + +Not in the port. + + +2012-05-20 - pppd: Make MSCHAP-v2 cope better with packet loss + 08ef47ca532294eb428238c831616748940e24a2 + +This is an interesting patch. However it consumes much more memory for +MSCHAP and I am not sure if the benefit worth it. The PPP client can +always start the authentication again if it failed for whatever reason. + + +2012-05-20 - scripts: Make poff ignore extra arguments to pppd + 18f515f32c9f5723a9c2c912601e04335106534b + +Again, we are not running scripts. + + +2012-05-20 - rp-pppoe plugin: Print leading zeros in MAC address + f5dda0cfc220c4b52e26144096d729e27b30f0f7 + +Again, we are not using the RP-PPPoE plugin. + + +2012-05-20 - pppd: Notify IPv6 up/down as we do for IPv4 + 845cda8fa18939cf56e60b073f63a7efa65336fc + +This is just a patch that adds plugins hooks for IPv6, the plugin interface +was disabled because we don't have .so plugins in embedded. + + +2012-05-20 - pppd: Enable IPV6 by default and fix some warnings + 0b6118239615e98959f7e0b4e746bdd197533248 + +Change on Makefile for IPv6, warnings were already cleared during port. + + +2012-05-20 - contrib: Fix pppgetpass.gtk compilation + 80a8e2ce257ca12cce723519a0f20ea1d663b14a + +Change on Makefile, don't care. + + +2012-05-20 - pppd: Don't crash if crypt() returns NULL + 04c4348108d847e034dd91066cc6843f60d71731 + +We are using the PolarSSL DES implementation that does not return NULL. + + +2012-05-20 - pppd: Eliminate some warnings + c44ae5e6a7338c96eb463881fe709b2dfaffe568 + +Again, we are handling compilation warnings on our own. + + +2012-05-20 - rp-pppoe plugin: Import some fixes from rp-pppoe-3.10 + 1817d83e51a411044e730ba89ebdb0480e1c8cd4 + +Once more, we are not using the RP-PPPoE plugin. + + +2013-01-23 - pppd: Clarify circumstances where DNS1/DNS2 environment variables are set + cf2f5c9538b9400ade23446a194729b0a4113b3a + +Documentation only. + + +2013-02-03 - ppp: ignore unrecognised radiusclient configuration directives + 7f736dde0da3c19855997d9e67370e351e15e923 + +Radius plugin, not in the port. + + +2013-02-03 - pppd: Take out unused %r conversion completely + 356d8d558d844412119aa18c8e5a113bc6459c7b + +Merged 2014-04-15. + + +2013-02-03 - pppd: Arrange to use logwtmp from libutil on Linux + 9617a7eb137f4fee62799a677a9ecf8d834db3f5 + +Patch for sys-linux.c, which we don't use. + + +2013-02-03 - pppdump: Eliminate some compiler warnings + 3e3acf1ba2b3046c072a42c19164788a9e419bd1 + +pppdump is a ppp tool outside pppd source tree. + + +2013-02-03 - chat: Correct spelling errors in the man page + 8dea1b969d266ccbf6f3a8c5474eb6dcd8838e3b + +Documentation only. + + +2013-02-03 - pppd: Fix spelling errors in man page + 9e05a25d76b3f83096c661678010320df673df6b + +Documentation only. + + +2013-02-03 - plugins/passprompt: Fix potential out-of-bounds array reference + 8edb889b753056a691a3e4b217a110a35f9fdedb + +Plugin patch, we do not have plugins. + + +2013-02-03 - chat: Fix *roff errors in the man page + a7c3489eeaf44e83ce592143c7c8a5b5c29f4c48 + +Documentation only. + + +2013-03-02 - pppd: Fix man page description of case when remote IP address isn't known + 224841f4799f4f1e2e71bc490c54448d66740f4f + +Documentation only. + + +2013-03-02 - pppd: Add master_detach option + 398ed2585640d198c53e736ee5bbd67f7ce8168e + +Option for multilink support, we do not support multilink and this option +is about detaching from the terminal, which is out of the embedded scope. + + +2013-03-11 - pppd: Default exit status to EXIT_CONNECT_FAILED during connection phase + 225361d64ae737afdc8cb57579a2f33525461bc9 + +Commented out in our port, and already fixed by a previously applied Debian patch. + + +2013-03-11 - pppstats: Fix undefined macro in man page + d16a3985eade5280b8e171f5dd0670a91cba0d39 + +Documentation only. + + +2013-05-11 - plugins/radius: Handle bindaddr keyword in radiusclient.conf + d883b2dbafeed3ebd9d7a56ab1469373bd001a3b + +Radius plugin, not in the port. + + +2013-06-09 - pppoatm: Remove explicit loading of pppoatm kernel module + 52cd43a84bea524033b918b603698104f221bbb7 + +PPPoATM plugin, not in the port. + + +2013-06-09 - pppd: Fix segfault in update_db_entry() + 37476164f15a45015310b9d4b197c2d7db1f7f8f + +We do not use the samba db. + + +2013-06-09 - chat: Fix some text that was intended to be literal + cd9683676618adcee8add2c3cfa3382341b5a1f6 + +Documentation only. + + +2013-06-09 - README.pppoe: Minor semantic fix + b5b8898af6fd3d44e873cfc66810ace5f1f47e17 + +Documentation only. + + +2013-06-10 - radius: Handle additional attributes + 2f581cd986a56f2ec4a95abad4f8297a1b10d7e2 + +Radius plugin, not in the port. + + +2013-06-10 - chat, pppd: Use \e instead of \\ in man pages + 8d6942415d22f6ca4377340ca26e345c3f5fa5db + +Documentation only. + + +2014-01-02 - pppd: Don't crash if NULL pointer passed to vslprintf for %q or %v + 906814431bddeb2061825fa1ebad1a967b6d87a9 + +Merged 2014-04-15. + + +2014-01-02 - pppd: Accept IPCP ConfAck packets containing MS-WINS options + a243f217f1c6ac1aa7793806bc88590d077f490a + +Merged 2014-04-15. + + +2014-01-02 - config: Update Solaris compiler options and enable CHAPMS and IPV6 + 99c46caaed01b7edba87962aa52b77fad61bfd7b + +Solaris port, don't care. + + +2014-01-02 - Update README and patchlevel for 2.4.6 release + 4043750fca36e7e0eb90d702e048ad1da4929418 + +Just release stuff. + + +2014-02-18 - pppd: Add option "stop-bits" to set number of serial port stop bits. + ad993a20ee485f0d0e2ac4105221641b200da6e2 + +Low level serial port, not in the port. + + +2014-03-09 - pppd: Separate IPv6 handling for sifup/sifdown + b04d2dc6df5c6b5650fea44250d58757ee3dac4a + +Reimplemented. + + +2014-03-09 - pppol2tp: Connect up/down events to notifiers and add IPv6 ones + fafbe50251efc7d6b4a8be652d085316e112b34f + +Not in the port. + + +2014-03-09 - pppd: Add declarations to eliminate compile warnings + 50967962addebe15c7a7e63116ff46a0441dc464 + +We are handling compilation warnings on our own + + +2014-03-09 - pppd: Eliminate some unnecessary ifdefs + de8da14d845ee6db9236ccfddabf1d8ebf045ddb + +We mostly did that previously. Anyway, merged 2014-12-24. + + +2014-08-01 - radius: Fix realms-config-file option + 880a81be7c8e0fe8567227bc17a1bff3ea035943 + +Radius plugin, not in the port. + + +2014-08-01 - pppd: Eliminate potential integer overflow in option parsing + 7658e8257183f062dc01f87969c140707c7e52cb + +pppd config file parser, not in the port. + + +2014-08-01 - pppd: Eliminate memory leak with multiple instances of a string option + b94b7fbbaa0589aa6ec5fdc733aeb9ff294d2656 + +pppd config file parser, not in the port. + + +2014-08-01 - pppd: Fix a stack variable overflow in MSCHAP-v2 + 36733a891fb56594fcee580f667b33a64b990981 + +This fixes a bug introduced in 08ef47ca ("pppd: Make MSCHAP-v2 cope better with packet loss"). + +We didn't merge 08ef47ca ;-) + + +2014-08-01 - winbind plugin: Add -DMPPE=1 to eliminate compiler warnings + 2b05e22c62095e97dd0a97e4b5588402c2185071 + +Linux plugin, not in the port. + + +2014-08-09 - Update README and patchlevel for 2.4.7 release + 6e8eaa7a78b31cdab2edf140a9c8afdb02ffaca5 + +Just release stuff. diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/auth.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/auth.c new file mode 100644 index 0000000..b98691e --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/auth.c @@ -0,0 +1,2563 @@ +/* + * auth.c - PPP authentication and phase control. + * + * Copyright (c) 1993-2002 Paul Mackerras. 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. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Derived from main.c, which is: + * + * Copyright (c) 1984-2000 Carnegie Mellon University. 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. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#if 0 /* UNUSED */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(_PATH_LASTLOG) && defined(__linux__) +#include +#endif + +#include +#include +#include + +#ifdef HAS_SHADOW +#include +#ifndef PW_PPP +#define PW_PPP PW_LOGIN +#endif +#endif + +#include +#endif /* UNUSED */ + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/fsm.h" +#include "netif/ppp/lcp.h" +#if CCP_SUPPORT +#include "netif/ppp/ccp.h" +#endif /* CCP_SUPPORT */ +#if ECP_SUPPORT +#include "netif/ppp/ecp.h" +#endif /* ECP_SUPPORT */ +#include "netif/ppp/ipcp.h" +#if PAP_SUPPORT +#include "netif/ppp/upap.h" +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT +#include "netif/ppp/chap-new.h" +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT +#include "netif/ppp/eap.h" +#endif /* EAP_SUPPORT */ +#if CBCP_SUPPORT +#include "netif/ppp/cbcp.h" +#endif + +#if 0 /* UNUSED */ +#include "session.h" +#endif /* UNUSED */ + +#if 0 /* UNUSED */ +/* Bits in scan_authfile return value */ +#define NONWILD_SERVER 1 +#define NONWILD_CLIENT 2 + +#define ISWILD(word) (word[0] == '*' && word[1] == 0) +#endif /* UNUSED */ + +#if 0 /* UNUSED */ +/* List of addresses which the peer may use. */ +static struct permitted_ip *addresses[NUM_PPP]; + +/* Wordlist giving addresses which the peer may use + without authenticating itself. */ +static struct wordlist *noauth_addrs; + +/* Remote telephone number, if available */ +char remote_number[MAXNAMELEN]; + +/* Wordlist giving remote telephone numbers which may connect. */ +static struct wordlist *permitted_numbers; + +/* Extra options to apply, from the secrets file entry for the peer. */ +static struct wordlist *extra_options; +#endif /* UNUSED */ + +#if 0 /* UNUSED */ +/* Set if we require authentication only because we have a default route. */ +static bool default_auth; + +/* Hook to enable a plugin to control the idle time limit */ +int (*idle_time_hook) (struct ppp_idle *) = NULL; + +/* Hook for a plugin to say whether we can possibly authenticate any peer */ +int (*pap_check_hook) (void) = NULL; + +/* Hook for a plugin to check the PAP user and password */ +int (*pap_auth_hook) (char *user, char *passwd, char **msgp, + struct wordlist **paddrs, + struct wordlist **popts) = NULL; + +/* Hook for a plugin to know about the PAP user logout */ +void (*pap_logout_hook) (void) = NULL; + +/* Hook for a plugin to get the PAP password for authenticating us */ +int (*pap_passwd_hook) (char *user, char *passwd) = NULL; + +/* Hook for a plugin to say if we can possibly authenticate a peer using CHAP */ +int (*chap_check_hook) (void) = NULL; + +/* Hook for a plugin to get the CHAP password for authenticating us */ +int (*chap_passwd_hook) (char *user, char *passwd) = NULL; + +/* Hook for a plugin to say whether it is OK if the peer + refuses to authenticate. */ +int (*null_auth_hook) (struct wordlist **paddrs, + struct wordlist **popts) = NULL; + +int (*allowed_address_hook) (u32_t addr) = NULL; +#endif /* UNUSED */ + +#ifdef HAVE_MULTILINK +/* Hook for plugin to hear when an interface joins a multilink bundle */ +void (*multilink_join_hook) (void) = NULL; +#endif + +#if PPP_NOTIFY +/* A notifier for when the peer has authenticated itself, + and we are proceeding to the network phase. */ +struct notifier *auth_up_notifier = NULL; + +/* A notifier for when the link goes down. */ +struct notifier *link_down_notifier = NULL; +#endif /* PPP_NOTIFY */ + +/* + * Option variables. + */ +#if 0 /* MOVED TO ppp_settings */ +bool uselogin = 0; /* Use /etc/passwd for checking PAP */ +bool session_mgmt = 0; /* Do session management (login records) */ +bool cryptpap = 0; /* Passwords in pap-secrets are encrypted */ +bool refuse_pap = 0; /* Don't wanna auth. ourselves with PAP */ +bool refuse_chap = 0; /* Don't wanna auth. ourselves with CHAP */ +bool refuse_eap = 0; /* Don't wanna auth. ourselves with EAP */ +#if MSCHAP_SUPPORT +bool refuse_mschap = 0; /* Don't wanna auth. ourselves with MS-CHAP */ +bool refuse_mschap_v2 = 0; /* Don't wanna auth. ourselves with MS-CHAPv2 */ +#else /* MSCHAP_SUPPORT */ +bool refuse_mschap = 1; /* Don't wanna auth. ourselves with MS-CHAP */ +bool refuse_mschap_v2 = 1; /* Don't wanna auth. ourselves with MS-CHAPv2 */ +#endif /* MSCHAP_SUPPORT */ +bool usehostname = 0; /* Use hostname for our_name */ +bool auth_required = 0; /* Always require authentication from peer */ +bool allow_any_ip = 0; /* Allow peer to use any IP address */ +bool explicit_remote = 0; /* User specified explicit remote name */ +bool explicit_user = 0; /* Set if "user" option supplied */ +bool explicit_passwd = 0; /* Set if "password" option supplied */ +char remote_name[MAXNAMELEN]; /* Peer's name for authentication */ +static char *uafname; /* name of most recent +ua file */ + +extern char *crypt (const char *, const char *); +#endif /* UNUSED */ +/* Prototypes for procedures local to this file. */ + +static void network_phase(ppp_pcb *pcb); +#if PPP_IDLETIMELIMIT +static void check_idle(void *arg); +#endif /* PPP_IDLETIMELIMIT */ +#if PPP_MAXCONNECT +static void connect_time_expired(void *arg); +#endif /* PPP_MAXCONNECT */ +#if 0 /* UNUSED */ +static int null_login (int); +/* static int get_pap_passwd (char *); */ +static int have_pap_secret (int *); +static int have_chap_secret (char *, char *, int, int *); +static int have_srp_secret (char *client, char *server, int need_ip, + int *lacks_ipp); +static int ip_addr_check (u32_t, struct permitted_ip *); +static int scan_authfile (FILE *, char *, char *, char *, + struct wordlist **, struct wordlist **, + char *, int); +static void free_wordlist (struct wordlist *); +static void set_allowed_addrs (int, struct wordlist *, struct wordlist *); +static int some_ip_ok (struct wordlist *); +static int setupapfile (char **); +static int privgroup (char **); +static int set_noauth_addr (char **); +static int set_permitted_number (char **); +static void check_access (FILE *, char *); +static int wordlist_count (struct wordlist *); +#endif /* UNUSED */ + +#ifdef MAXOCTETS +static void check_maxoctets (void *); +#endif + +#if PPP_OPTIONS +/* + * Authentication-related options. + */ +option_t auth_options[] = { + { "auth", o_bool, &auth_required, + "Require authentication from peer", OPT_PRIO | 1 }, + { "noauth", o_bool, &auth_required, + "Don't require peer to authenticate", OPT_PRIOSUB | OPT_PRIV, + &allow_any_ip }, + { "require-pap", o_bool, &lcp_wantoptions[0].neg_upap, + "Require PAP authentication from peer", + OPT_PRIOSUB | 1, &auth_required }, + { "+pap", o_bool, &lcp_wantoptions[0].neg_upap, + "Require PAP authentication from peer", + OPT_ALIAS | OPT_PRIOSUB | 1, &auth_required }, + { "require-chap", o_bool, &auth_required, + "Require CHAP authentication from peer", + OPT_PRIOSUB | OPT_A2OR | MDTYPE_MD5, + &lcp_wantoptions[0].chap_mdtype }, + { "+chap", o_bool, &auth_required, + "Require CHAP authentication from peer", + OPT_ALIAS | OPT_PRIOSUB | OPT_A2OR | MDTYPE_MD5, + &lcp_wantoptions[0].chap_mdtype }, +#if MSCHAP_SUPPORT + { "require-mschap", o_bool, &auth_required, + "Require MS-CHAP authentication from peer", + OPT_PRIOSUB | OPT_A2OR | MDTYPE_MICROSOFT, + &lcp_wantoptions[0].chap_mdtype }, + { "+mschap", o_bool, &auth_required, + "Require MS-CHAP authentication from peer", + OPT_ALIAS | OPT_PRIOSUB | OPT_A2OR | MDTYPE_MICROSOFT, + &lcp_wantoptions[0].chap_mdtype }, + { "require-mschap-v2", o_bool, &auth_required, + "Require MS-CHAPv2 authentication from peer", + OPT_PRIOSUB | OPT_A2OR | MDTYPE_MICROSOFT_V2, + &lcp_wantoptions[0].chap_mdtype }, + { "+mschap-v2", o_bool, &auth_required, + "Require MS-CHAPv2 authentication from peer", + OPT_ALIAS | OPT_PRIOSUB | OPT_A2OR | MDTYPE_MICROSOFT_V2, + &lcp_wantoptions[0].chap_mdtype }, +#endif /* MSCHAP_SUPPORT */ +#if 0 + { "refuse-pap", o_bool, &refuse_pap, + "Don't agree to auth to peer with PAP", 1 }, + { "-pap", o_bool, &refuse_pap, + "Don't allow PAP authentication with peer", OPT_ALIAS | 1 }, + { "refuse-chap", o_bool, &refuse_chap, + "Don't agree to auth to peer with CHAP", + OPT_A2CLRB | MDTYPE_MD5, + &lcp_allowoptions[0].chap_mdtype }, + { "-chap", o_bool, &refuse_chap, + "Don't allow CHAP authentication with peer", + OPT_ALIAS | OPT_A2CLRB | MDTYPE_MD5, + &lcp_allowoptions[0].chap_mdtype }, +#endif +#if MSCHAP_SUPPORT +#if 0 + { "refuse-mschap", o_bool, &refuse_mschap, + "Don't agree to auth to peer with MS-CHAP", + OPT_A2CLRB | MDTYPE_MICROSOFT, + &lcp_allowoptions[0].chap_mdtype }, + { "-mschap", o_bool, &refuse_mschap, + "Don't allow MS-CHAP authentication with peer", + OPT_ALIAS | OPT_A2CLRB | MDTYPE_MICROSOFT, + &lcp_allowoptions[0].chap_mdtype }, + { "refuse-mschap-v2", o_bool, &refuse_mschap_v2, + "Don't agree to auth to peer with MS-CHAPv2", + OPT_A2CLRB | MDTYPE_MICROSOFT_V2, + &lcp_allowoptions[0].chap_mdtype }, + { "-mschap-v2", o_bool, &refuse_mschap_v2, + "Don't allow MS-CHAPv2 authentication with peer", + OPT_ALIAS | OPT_A2CLRB | MDTYPE_MICROSOFT_V2, + &lcp_allowoptions[0].chap_mdtype }, +#endif +#endif /* MSCHAP_SUPPORT*/ +#if EAP_SUPPORT + { "require-eap", o_bool, &lcp_wantoptions[0].neg_eap, + "Require EAP authentication from peer", OPT_PRIOSUB | 1, + &auth_required }, +#if 0 + { "refuse-eap", o_bool, &refuse_eap, + "Don't agree to authenticate to peer with EAP", 1 }, +#endif +#endif /* EAP_SUPPORT */ + { "name", o_string, our_name, + "Set local name for authentication", + OPT_PRIO | OPT_PRIV | OPT_STATIC, NULL, MAXNAMELEN }, + + { "+ua", o_special, (void *)setupapfile, + "Get PAP user and password from file", + OPT_PRIO | OPT_A2STRVAL, &uafname }, + +#if 0 + { "user", o_string, user, + "Set name for auth with peer", OPT_PRIO | OPT_STATIC, + &explicit_user, MAXNAMELEN }, + + { "password", o_string, passwd, + "Password for authenticating us to the peer", + OPT_PRIO | OPT_STATIC | OPT_HIDE, + &explicit_passwd, MAXSECRETLEN }, +#endif + + { "usehostname", o_bool, &usehostname, + "Must use hostname for authentication", 1 }, + + { "remotename", o_string, remote_name, + "Set remote name for authentication", OPT_PRIO | OPT_STATIC, + &explicit_remote, MAXNAMELEN }, + + { "login", o_bool, &uselogin, + "Use system password database for PAP", OPT_A2COPY | 1 , + &session_mgmt }, + { "enable-session", o_bool, &session_mgmt, + "Enable session accounting for remote peers", OPT_PRIV | 1 }, + + { "papcrypt", o_bool, &cryptpap, + "PAP passwords are encrypted", 1 }, + + { "privgroup", o_special, (void *)privgroup, + "Allow group members to use privileged options", OPT_PRIV | OPT_A2LIST }, + + { "allow-ip", o_special, (void *)set_noauth_addr, + "Set IP address(es) which can be used without authentication", + OPT_PRIV | OPT_A2LIST }, + + { "remotenumber", o_string, remote_number, + "Set remote telephone number for authentication", OPT_PRIO | OPT_STATIC, + NULL, MAXNAMELEN }, + + { "allow-number", o_special, (void *)set_permitted_number, + "Set telephone number(s) which are allowed to connect", + OPT_PRIV | OPT_A2LIST }, + + { NULL } +}; +#endif /* PPP_OPTIONS */ + +#if 0 /* UNUSED */ +/* + * setupapfile - specifies UPAP info for authenticating with peer. + */ +static int +setupapfile(argv) + char **argv; +{ + FILE *ufile; + int l; + uid_t euid; + char u[MAXNAMELEN], p[MAXSECRETLEN]; + char *fname; + + lcp_allowoptions[0].neg_upap = 1; + + /* open user info file */ + fname = strdup(*argv); + if (fname == NULL) + novm("+ua file name"); + euid = geteuid(); + if (seteuid(getuid()) == -1) { + option_error("unable to reset uid before opening %s: %m", fname); + return 0; + } + ufile = fopen(fname, "r"); + if (seteuid(euid) == -1) + fatal("unable to regain privileges: %m"); + if (ufile == NULL) { + option_error("unable to open user login data file %s", fname); + return 0; + } + check_access(ufile, fname); + uafname = fname; + + /* get username */ + if (fgets(u, MAXNAMELEN - 1, ufile) == NULL + || fgets(p, MAXSECRETLEN - 1, ufile) == NULL) { + fclose(ufile); + option_error("unable to read user login data file %s", fname); + return 0; + } + fclose(ufile); + + /* get rid of newlines */ + l = strlen(u); + if (l > 0 && u[l-1] == '\n') + u[l-1] = 0; + l = strlen(p); + if (l > 0 && p[l-1] == '\n') + p[l-1] = 0; + + if (override_value("user", option_priority, fname)) { + strlcpy(ppp_settings.user, u, sizeof(ppp_settings.user)); + explicit_user = 1; + } + if (override_value("passwd", option_priority, fname)) { + strlcpy(ppp_settings.passwd, p, sizeof(ppp_settings.passwd)); + explicit_passwd = 1; + } + + return (1); +} + +/* + * privgroup - allow members of the group to have privileged access. + */ +static int +privgroup(argv) + char **argv; +{ + struct group *g; + int i; + + g = getgrnam(*argv); + if (g == 0) { + option_error("group %s is unknown", *argv); + return 0; + } + for (i = 0; i < ngroups; ++i) { + if (groups[i] == g->gr_gid) { + privileged = 1; + break; + } + } + return 1; +} + + +/* + * set_noauth_addr - set address(es) that can be used without authentication. + * Equivalent to specifying an entry like `"" * "" addr' in pap-secrets. + */ +static int +set_noauth_addr(argv) + char **argv; +{ + char *addr = *argv; + int l = strlen(addr) + 1; + struct wordlist *wp; + + wp = (struct wordlist *) malloc(sizeof(struct wordlist) + l); + if (wp == NULL) + novm("allow-ip argument"); + wp->word = (char *) (wp + 1); + wp->next = noauth_addrs; + MEMCPY(wp->word, addr, l); + noauth_addrs = wp; + return 1; +} + + +/* + * set_permitted_number - set remote telephone number(s) that may connect. + */ +static int +set_permitted_number(argv) + char **argv; +{ + char *number = *argv; + int l = strlen(number) + 1; + struct wordlist *wp; + + wp = (struct wordlist *) malloc(sizeof(struct wordlist) + l); + if (wp == NULL) + novm("allow-number argument"); + wp->word = (char *) (wp + 1); + wp->next = permitted_numbers; + MEMCPY(wp->word, number, l); + permitted_numbers = wp; + return 1; +} +#endif + +/* + * An Open on LCP has requested a change from Dead to Establish phase. + */ +void link_required(ppp_pcb *pcb) { + LWIP_UNUSED_ARG(pcb); +} + +#if 0 +/* + * Bring the link up to the point of being able to do ppp. + */ +void start_link(unit) + int unit; +{ + ppp_pcb *pcb = &ppp_pcb_list[unit]; + char *msg; + + status = EXIT_NEGOTIATION_FAILED; + new_phase(pcb, PPP_PHASE_SERIALCONN); + + hungup = 0; + devfd = the_channel->connect(); + msg = "Connect script failed"; + if (devfd < 0) + goto fail; + + /* set up the serial device as a ppp interface */ + /* + * N.B. we used to do tdb_writelock/tdb_writeunlock around this + * (from establish_ppp to set_ifunit). However, we won't be + * doing the set_ifunit in multilink mode, which is the only time + * we need the atomicity that the tdb_writelock/tdb_writeunlock + * gives us. Thus we don't need the tdb_writelock/tdb_writeunlock. + */ + fd_ppp = the_channel->establish_ppp(devfd); + msg = "ppp establishment failed"; + if (fd_ppp < 0) { + status = EXIT_FATAL_ERROR; + goto disconnect; + } + + if (!demand && ifunit >= 0) + set_ifunit(1); + + /* + * Start opening the connection and wait for + * incoming events (reply, timeout, etc.). + */ + if (ifunit >= 0) + ppp_notice("Connect: %s <--> %s", ifname, ppp_devnam); + else + ppp_notice("Starting negotiation on %s", ppp_devnam); + add_fd(fd_ppp); + + new_phase(pcb, PPP_PHASE_ESTABLISH); + + lcp_lowerup(pcb); + return; + + disconnect: + new_phase(pcb, PPP_PHASE_DISCONNECT); + if (the_channel->disconnect) + the_channel->disconnect(); + + fail: + new_phase(pcb, PPP_PHASE_DEAD); + if (the_channel->cleanup) + (*the_channel->cleanup)(); +} +#endif + +/* + * LCP has terminated the link; go to the Dead phase and take the + * physical layer down. + */ +void link_terminated(ppp_pcb *pcb) { + if (pcb->phase == PPP_PHASE_DEAD || pcb->phase == PPP_PHASE_MASTER) + return; + new_phase(pcb, PPP_PHASE_DISCONNECT); + +#if 0 /* UNUSED */ + if (pap_logout_hook) { + pap_logout_hook(); + } + session_end(devnam); +#endif /* UNUSED */ + + if (!doing_multilink) { + ppp_notice("Connection terminated."); +#if PPP_STATS_SUPPORT + print_link_stats(); +#endif /* PPP_STATS_SUPPORT */ + } else + ppp_notice("Link terminated."); + + lcp_lowerdown(pcb); + + new_phase(pcb, PPP_PHASE_DEAD); + ppp_link_terminated(pcb); +#if 0 + /* + * Delete pid files before disestablishing ppp. Otherwise it + * can happen that another pppd gets the same unit and then + * we delete its pid file. + */ + if (!doing_multilink && !demand) + remove_pidfiles(); + + /* + * If we may want to bring the link up again, transfer + * the ppp unit back to the loopback. Set the + * real serial device back to its normal mode of operation. + */ + if (fd_ppp >= 0) { + remove_fd(fd_ppp); + clean_check(); + the_channel->disestablish_ppp(devfd); + if (doing_multilink) + mp_exit_bundle(); + fd_ppp = -1; + } + if (!hungup) + lcp_lowerdown(pcb); + if (!doing_multilink && !demand) + script_unsetenv("IFNAME"); + + /* + * Run disconnector script, if requested. + * XXX we may not be able to do this if the line has hung up! + */ + if (devfd >= 0 && the_channel->disconnect) { + the_channel->disconnect(); + devfd = -1; + } + if (the_channel->cleanup) + (*the_channel->cleanup)(); + + if (doing_multilink && multilink_master) { + if (!bundle_terminating) + new_phase(pcb, PPP_PHASE_MASTER); + else + mp_bundle_terminated(); + } else + new_phase(pcb, PPP_PHASE_DEAD); +#endif +} + +/* + * LCP has gone down; it will either die or try to re-establish. + */ +void link_down(ppp_pcb *pcb) { +#if PPP_NOTIFY + notify(link_down_notifier, 0); +#endif /* PPP_NOTIFY */ + + if (!doing_multilink) { + upper_layers_down(pcb); + if (pcb->phase != PPP_PHASE_DEAD && pcb->phase != PPP_PHASE_MASTER) + new_phase(pcb, PPP_PHASE_ESTABLISH); + } + /* XXX if doing_multilink, should do something to stop + network-layer traffic on the link */ + + ppp_link_down(pcb); +} + +void upper_layers_down(ppp_pcb *pcb) { + int i; + const struct protent *protp; + + for (i = 0; (protp = protocols[i]) != NULL; ++i) { + if (!protp->enabled_flag) + continue; + if (protp->protocol != PPP_LCP && protp->lowerdown != NULL) + (*protp->lowerdown)(pcb); + if (protp->protocol < 0xC000 && protp->close != NULL) + (*protp->close)(pcb, "LCP down"); + } + pcb->num_np_open = 0; + pcb->num_np_up = 0; +} + +/* + * The link is established. + * Proceed to the Dead, Authenticate or Network phase as appropriate. + */ +void link_established(ppp_pcb *pcb) { + int auth; +#if PPP_SERVER + lcp_options *wo = &pcb->lcp_wantoptions; + lcp_options *go = &pcb->lcp_gotoptions; +#endif /* PPP_SERVER */ + lcp_options *ho = &pcb->lcp_hisoptions; + int i; + const struct protent *protp; +#if PPP_SERVER + int errcode; +#endif /* PPP_SERVER */ + + /* + * Tell higher-level protocols that LCP is up. + */ + if (!doing_multilink) { + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if (protp->protocol != PPP_LCP && protp->enabled_flag + && protp->lowerup != NULL) + (*protp->lowerup)(pcb); + } + +#if PPP_SERVER +#if PPP_ALLOWED_ADDRS + if (!auth_required && noauth_addrs != NULL) + set_allowed_addrs(unit, NULL, NULL); +#endif /* PPP_ALLOWED_ADDRS */ + + if (pcb->settings.auth_required && !(0 +#if PAP_SUPPORT + || go->neg_upap +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + || go->neg_chap +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + || go->neg_eap +#endif /* EAP_SUPPORT */ + )) { + +#if PPP_ALLOWED_ADDRS + /* + * We wanted the peer to authenticate itself, and it refused: + * if we have some address(es) it can use without auth, fine, + * otherwise treat it as though it authenticated with PAP using + * a username of "" and a password of "". If that's not OK, + * boot it out. + */ + if (noauth_addrs != NULL) { + set_allowed_addrs(unit, NULL, NULL); + } else +#endif /* PPP_ALLOWED_ADDRS */ + if (!wo->neg_upap || !pcb->settings.null_login) { + ppp_warn("peer refused to authenticate: terminating link"); +#if 0 /* UNUSED */ + status = EXIT_PEER_AUTH_FAILED; +#endif /* UNUSED */ + errcode = PPPERR_AUTHFAIL; + ppp_ioctl(pcb, PPPCTLS_ERRCODE, &errcode); + lcp_close(pcb, "peer refused to authenticate"); + return; + } + } +#endif /* PPP_SERVER */ + + new_phase(pcb, PPP_PHASE_AUTHENTICATE); + auth = 0; +#if PPP_SERVER +#if EAP_SUPPORT + if (go->neg_eap) { + eap_authpeer(pcb, pcb->settings.our_name); + auth |= EAP_PEER; + } else +#endif /* EAP_SUPPORT */ +#if CHAP_SUPPORT + if (go->neg_chap) { + chap_auth_peer(pcb, pcb->settings.our_name, CHAP_DIGEST(go->chap_mdtype)); + auth |= CHAP_PEER; + } else +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + if (go->neg_upap) { + upap_authpeer(pcb); + auth |= PAP_PEER; + } else +#endif /* PAP_SUPPORT */ + {} +#endif /* PPP_SERVER */ + +#if EAP_SUPPORT + if (ho->neg_eap) { + eap_authwithpeer(pcb, pcb->settings.user); + auth |= EAP_WITHPEER; + } else +#endif /* EAP_SUPPORT */ +#if CHAP_SUPPORT + if (ho->neg_chap) { + chap_auth_with_peer(pcb, pcb->settings.user, CHAP_DIGEST(ho->chap_mdtype)); + auth |= CHAP_WITHPEER; + } else +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + if (ho->neg_upap) { + upap_authwithpeer(pcb, pcb->settings.user, pcb->settings.passwd); + auth |= PAP_WITHPEER; + } else +#endif /* PAP_SUPPORT */ + {} + + pcb->auth_pending = auth; + pcb->auth_done = 0; + + if (!auth) + + network_phase(pcb); +} + +/* + * Proceed to the network phase. + */ +static void network_phase(ppp_pcb *pcb) { +#if CBCP_SUPPORT + ppp_pcb *pcb = &ppp_pcb_list[unit]; +#endif +#if 0 /* UNUSED */ + lcp_options *go = &lcp_gotoptions[unit]; +#endif /* UNUSED */ + +#if 0 /* UNUSED */ + /* Log calling number. */ + if (*remote_number) + ppp_notice("peer from calling number %q authorized", remote_number); +#endif /* UNUSED */ + +#if PPP_NOTIFY + /* + * If the peer had to authenticate, notify it now. + */ + if (0 +#if CHAP_SUPPORT + || go->neg_chap +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + || go->neg_upap +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + || go->neg_eap +#endif /* EAP_SUPPORT */ + ) { + notify(auth_up_notifier, 0); + } +#endif /* PPP_NOTIFY */ + +#if CBCP_SUPPORT + /* + * If we negotiated callback, do it now. + */ + if (go->neg_cbcp) { + new_phase(pcb, PPP_PHASE_CALLBACK); + (*cbcp_protent.open)(pcb); + return; + } +#endif + +#if PPP_OPTIONS + /* + * Process extra options from the secrets file + */ + if (extra_options) { + options_from_list(extra_options, 1); + free_wordlist(extra_options); + extra_options = 0; + } +#endif /* PPP_OPTIONS */ + start_networks(pcb); +} + +void start_networks(ppp_pcb *pcb) { +#if CCP_SUPPORT || ECP_SUPPORT + int i; + const struct protent *protp; +#endif /* CCP_SUPPORT || ECP_SUPPORT */ +#if ECP_SUPPORT + int ecp_required; +#endif /* ECP_SUPPORT */ +#ifdef MPPE + int mppe_required; +#endif /* MPPE */ + + new_phase(pcb, PPP_PHASE_NETWORK); + +#ifdef HAVE_MULTILINK + if (multilink) { + if (mp_join_bundle()) { + if (multilink_join_hook) + (*multilink_join_hook)(); + if (updetach && !nodetach) + detach(); + return; + } + } +#endif /* HAVE_MULTILINK */ + +#ifdef PPP_FILTER + if (!demand) + set_filters(&pass_filter, &active_filter); +#endif +#if CCP_SUPPORT || ECP_SUPPORT + /* Start CCP and ECP */ + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if ( + (0 +#if ECP_SUPPORT + || protp->protocol == PPP_ECP +#endif /* ECP_SUPPORT */ +#if CCP_SUPPORT + || protp->protocol == PPP_CCP +#endif /* CCP_SUPPORT */ + ) + && protp->enabled_flag && protp->open != NULL) + (*protp->open)(pcb); +#endif /* CCP_SUPPORT || ECP_SUPPORT */ + + /* + * Bring up other network protocols iff encryption is not required. + */ +#if ECP_SUPPORT + ecp_required = ecp_gotoptions[unit].required; +#endif /* ECP_SUPPORT */ +#ifdef MPPE + mppe_required = ccp_gotoptions[unit].mppe; +#endif /* MPPE */ + + if (1 +#if ECP_SUPPORT + && !ecp_required +#endif /* ECP_SUPPORT */ +#ifdef MPPE + && !mppe_required +#endif /* MPPE */ + ) + continue_networks(pcb); +} + +void continue_networks(ppp_pcb *pcb) { + int i; + const struct protent *protp; + + /* + * Start the "real" network protocols. + */ + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if (protp->protocol < 0xC000 +#if CCP_SUPPORT + && protp->protocol != PPP_CCP +#endif /* CCP_SUPPORT */ +#if ECP_SUPPORT + && protp->protocol != PPP_ECP +#endif /* ECP_SUPPORT */ + && protp->enabled_flag && protp->open != NULL) { + (*protp->open)(pcb); + ++pcb->num_np_open; + } + + if (pcb->num_np_open == 0) + /* nothing to do */ + lcp_close(pcb, "No network protocols running"); +} + +#if PPP_SERVER +/* + * The peer has failed to authenticate himself using `protocol'. + */ +void auth_peer_fail(ppp_pcb *pcb, int protocol) { + int errcode = PPPERR_AUTHFAIL; + LWIP_UNUSED_ARG(protocol); + /* + * Authentication failure: take the link down + */ +#if 0 /* UNUSED */ + status = EXIT_PEER_AUTH_FAILED; +#endif /* UNUSED */ + ppp_ioctl(pcb, PPPCTLS_ERRCODE, &errcode); + lcp_close(pcb, "Authentication failed"); +} + +/* + * The peer has been successfully authenticated using `protocol'. + */ +void auth_peer_success(ppp_pcb *pcb, int protocol, int prot_flavor, const char *name, int namelen) { + int bit; + + switch (protocol) { +#if CHAP_SUPPORT + case PPP_CHAP: + bit = CHAP_PEER; + switch (prot_flavor) { + case CHAP_MD5: + bit |= CHAP_MD5_PEER; + break; +#if MSCHAP_SUPPORT + case CHAP_MICROSOFT: + bit |= CHAP_MS_PEER; + break; + case CHAP_MICROSOFT_V2: + bit |= CHAP_MS2_PEER; + break; +#endif /* MSCHAP_SUPPORT */ + default: + break; + } + break; +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + case PPP_PAP: + bit = PAP_PEER; + break; +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + case PPP_EAP: + bit = EAP_PEER; + break; +#endif /* EAP_SUPPORT */ + default: + ppp_warn("auth_peer_success: unknown protocol %x", protocol); + return; + } + + /* + * Save the authenticated name of the peer for later. + */ + /* FIXME: do we need that ? */ + if (namelen > (int)sizeof(pcb->peer_authname) - 1) + namelen = (int)sizeof(pcb->peer_authname) - 1; + MEMCPY(pcb->peer_authname, name, namelen); + pcb->peer_authname[namelen] = 0; +#if 0 /* UNUSED */ + script_setenv("PEERNAME", , 0); +#endif /* UNUSED */ + + /* Save the authentication method for later. */ + pcb->auth_done |= bit; + + /* + * If there is no more authentication still to be done, + * proceed to the network (or callback) phase. + */ + if ((pcb->auth_pending &= ~bit) == 0) + network_phase(pcb); +} +#endif /* PPP_SERVER */ + +/* + * We have failed to authenticate ourselves to the peer using `protocol'. + */ +void auth_withpeer_fail(ppp_pcb *pcb, int protocol) { + int errcode = PPPERR_AUTHFAIL; + LWIP_UNUSED_ARG(protocol); + /* + * We've failed to authenticate ourselves to our peer. + * + * Some servers keep sending CHAP challenges, but there + * is no point in persisting without any way to get updated + * authentication secrets. + * + * He'll probably take the link down, and there's not much + * we can do except wait for that. + */ + ppp_ioctl(pcb, PPPCTLS_ERRCODE, &errcode); + lcp_close(pcb, "Failed to authenticate ourselves to peer"); +} + +/* + * We have successfully authenticated ourselves with the peer using `protocol'. + */ +void auth_withpeer_success(ppp_pcb *pcb, int protocol, int prot_flavor) { + int bit; + const char *prot = ""; + + switch (protocol) { +#if CHAP_SUPPORT + case PPP_CHAP: + bit = CHAP_WITHPEER; + prot = "CHAP"; + switch (prot_flavor) { + case CHAP_MD5: + bit |= CHAP_MD5_WITHPEER; + break; +#if MSCHAP_SUPPORT + case CHAP_MICROSOFT: + bit |= CHAP_MS_WITHPEER; + break; + case CHAP_MICROSOFT_V2: + bit |= CHAP_MS2_WITHPEER; + break; +#endif /* MSCHAP_SUPPORT */ + default: + break; + } + break; +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + case PPP_PAP: + bit = PAP_WITHPEER; + prot = "PAP"; + break; +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + case PPP_EAP: + bit = EAP_WITHPEER; + prot = "EAP"; + break; +#endif /* EAP_SUPPORT */ + default: + ppp_warn("auth_withpeer_success: unknown protocol %x", protocol); + bit = 0; + /* no break */ + } + + ppp_notice("%s authentication succeeded", prot); + + /* Save the authentication method for later. */ + pcb->auth_done |= bit; + + /* + * If there is no more authentication still being done, + * proceed to the network (or callback) phase. + */ + if ((pcb->auth_pending &= ~bit) == 0) + network_phase(pcb); +} + + +/* + * np_up - a network protocol has come up. + */ +void np_up(ppp_pcb *pcb, int proto) { +#if PPP_IDLETIMELIMIT + int tlim; +#endif /* PPP_IDLETIMELIMIT */ + LWIP_UNUSED_ARG(proto); + + if (pcb->num_np_up == 0) { + /* + * At this point we consider that the link has come up successfully. + */ + new_phase(pcb, PPP_PHASE_RUNNING); + +#if PPP_IDLETIMELIMIT +#if 0 /* UNUSED */ + if (idle_time_hook != 0) + tlim = (*idle_time_hook)(NULL); + else +#endif /* UNUSED */ + tlim = pcb->settings.idle_time_limit; + if (tlim > 0) + TIMEOUT(check_idle, (void*)pcb, tlim); +#endif /* PPP_IDLETIMELIMIT */ + +#if PPP_MAXCONNECT + /* + * Set a timeout to close the connection once the maximum + * connect time has expired. + */ + if (pcb->settings.maxconnect > 0) + TIMEOUT(connect_time_expired, (void*)pcb, pcb->settings.maxconnect); +#endif /* PPP_MAXCONNECT */ + +#ifdef MAXOCTETS + if (maxoctets > 0) + TIMEOUT(check_maxoctets, NULL, maxoctets_timeout); +#endif + +#if 0 /* Unused */ + /* + * Detach now, if the updetach option was given. + */ + if (updetach && !nodetach) + detach(); +#endif /* Unused */ + } + ++pcb->num_np_up; +} + +/* + * np_down - a network protocol has gone down. + */ +void np_down(ppp_pcb *pcb, int proto) { + LWIP_UNUSED_ARG(proto); + if (--pcb->num_np_up == 0) { +#if PPP_IDLETIMELIMIT + UNTIMEOUT(check_idle, (void*)pcb); +#endif /* PPP_IDLETIMELIMIT */ +#if PPP_MAXCONNECT + UNTIMEOUT(connect_time_expired, NULL); +#endif /* PPP_MAXCONNECT */ +#ifdef MAXOCTETS + UNTIMEOUT(check_maxoctets, NULL); +#endif + new_phase(pcb, PPP_PHASE_NETWORK); + } +} + +/* + * np_finished - a network protocol has finished using the link. + */ +void np_finished(ppp_pcb *pcb, int proto) { + LWIP_UNUSED_ARG(proto); + if (--pcb->num_np_open <= 0) { + /* no further use for the link: shut up shop. */ + lcp_close(pcb, "No network protocols running"); + } +} + +#ifdef MAXOCTETS +static void +check_maxoctets(arg) + void *arg; +{ +#if PPP_STATS_SUPPORT + unsigned int used; + + update_link_stats(ifunit); + link_stats_valid=0; + + switch(maxoctets_dir) { + case PPP_OCTETS_DIRECTION_IN: + used = link_stats.bytes_in; + break; + case PPP_OCTETS_DIRECTION_OUT: + used = link_stats.bytes_out; + break; + case PPP_OCTETS_DIRECTION_MAXOVERAL: + case PPP_OCTETS_DIRECTION_MAXSESSION: + used = (link_stats.bytes_in > link_stats.bytes_out) ? link_stats.bytes_in : link_stats.bytes_out; + break; + default: + used = link_stats.bytes_in+link_stats.bytes_out; + break; + } + if (used > maxoctets) { + ppp_notice("Traffic limit reached. Limit: %u Used: %u", maxoctets, used); + status = EXIT_TRAFFIC_LIMIT; + lcp_close(pcb, "Traffic limit"); +#if 0 /* UNUSED */ + need_holdoff = 0; +#endif /* UNUSED */ + } else { + TIMEOUT(check_maxoctets, NULL, maxoctets_timeout); + } +#endif /* PPP_STATS_SUPPORT */ +} +#endif /* MAXOCTETS */ + +#if PPP_IDLETIMELIMIT +/* + * check_idle - check whether the link has been idle for long + * enough that we can shut it down. + */ +static void check_idle(void *arg) { + ppp_pcb *pcb = (ppp_pcb*)arg; + struct ppp_idle idle; + time_t itime; + int tlim; + + if (!get_idle_time(pcb, &idle)) + return; +#if 0 /* UNUSED */ + if (idle_time_hook != 0) { + tlim = idle_time_hook(&idle); + } else { +#endif /* UNUSED */ + itime = LWIP_MIN(idle.xmit_idle, idle.recv_idle); + tlim = pcb->settings.idle_time_limit - itime; +#if 0 /* UNUSED */ + } +#endif /* UNUSED */ + if (tlim <= 0) { + int errcode = PPPERR_IDLETIMEOUT; + /* link is idle: shut it down. */ + ppp_notice("Terminating connection due to lack of activity."); + ppp_ioctl(pcb, PPPCTLS_ERRCODE, &errcode); + lcp_close(pcb, "Link inactive"); +#if 0 /* UNUSED */ + need_holdoff = 0; +#endif /* UNUSED */ + } else { + TIMEOUT(check_idle, (void*)pcb, tlim); + } +} +#endif /* PPP_IDLETIMELIMIT */ + +#if PPP_MAXCONNECT +/* + * connect_time_expired - log a message and close the connection. + */ +static void connect_time_expired(void *arg) { + int errcode = PPPERR_CONNECTTIME; + ppp_pcb *pcb = (ppp_pcb*)arg; + ppp_info("Connect time expired"); + ppp_ioctl(pcb, PPPCTLS_ERRCODE, &errcode); + lcp_close(pcb, "Connect time expired"); /* Close connection */ +} +#endif /* PPP_MAXCONNECT */ + +#if PPP_OPTIONS +/* + * auth_check_options - called to check authentication options. + */ +void +auth_check_options() +{ + lcp_options *wo = &lcp_wantoptions[0]; + int can_auth; + int lacks_ip; + + /* Default our_name to hostname, and user to our_name */ + if (our_name[0] == 0 || usehostname) + strlcpy(our_name, hostname, sizeof(our_name)); + /* If a blank username was explicitly given as an option, trust + the user and don't use our_name */ + if (ppp_settings.user[0] == 0 && !explicit_user) + strlcpy(ppp_settings.user, our_name, sizeof(ppp_settings.user)); + + /* + * If we have a default route, require the peer to authenticate + * unless the noauth option was given or the real user is root. + */ + if (!auth_required && !allow_any_ip && have_route_to(0) && !privileged) { + auth_required = 1; + default_auth = 1; + } + +#if CHAP_SUPPORT + /* If we selected any CHAP flavors, we should probably negotiate it. :-) */ + if (wo->chap_mdtype) + wo->neg_chap = 1; +#endif /* CHAP_SUPPORT */ + + /* If authentication is required, ask peer for CHAP, PAP, or EAP. */ + if (auth_required) { + allow_any_ip = 0; + if (1 +#if CHAP_SUPPORT + && !wo->neg_chap +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + && !wo->neg_upap +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + && !wo->neg_eap +#endif /* EAP_SUPPORT */ + ) { +#if CHAP_SUPPORT + wo->neg_chap = CHAP_MDTYPE_SUPPORTED != MDTYPE_NONE; + wo->chap_mdtype = CHAP_MDTYPE_SUPPORTED; +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + wo->neg_upap = 1; +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + wo->neg_eap = 1; +#endif /* EAP_SUPPORT */ + } + } else { +#if CHAP_SUPPORT + wo->neg_chap = 0; + wo->chap_mdtype = MDTYPE_NONE; +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + wo->neg_upap = 0; +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + wo->neg_eap = 0; +#endif /* EAP_SUPPORT */ + } + + /* + * Check whether we have appropriate secrets to use + * to authenticate the peer. Note that EAP can authenticate by way + * of a CHAP-like exchanges as well as SRP. + */ + lacks_ip = 0; +#if PAP_SUPPORT + can_auth = wo->neg_upap && (uselogin || have_pap_secret(&lacks_ip)); +#else + can_auth = 0; +#endif /* PAP_SUPPORT */ + if (!can_auth && (0 +#if CHAP_SUPPORT + || wo->neg_chap +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + || wo->neg_eap +#endif /* EAP_SUPPORT */ + )) { +#if CHAP_SUPPORT + can_auth = have_chap_secret((explicit_remote? remote_name: NULL), + our_name, 1, &lacks_ip); +#else + can_auth = 0; +#endif + } + if (!can_auth +#if EAP_SUPPORT + && wo->neg_eap +#endif /* EAP_SUPPORT */ + ) { + can_auth = have_srp_secret((explicit_remote? remote_name: NULL), + our_name, 1, &lacks_ip); + } + + if (auth_required && !can_auth && noauth_addrs == NULL) { + if (default_auth) { + option_error( +"By default the remote system is required to authenticate itself"); + option_error( +"(because this system has a default route to the internet)"); + } else if (explicit_remote) + option_error( +"The remote system (%s) is required to authenticate itself", + remote_name); + else + option_error( +"The remote system is required to authenticate itself"); + option_error( +"but I couldn't find any suitable secret (password) for it to use to do so."); + if (lacks_ip) + option_error( +"(None of the available passwords would let it use an IP address.)"); + + exit(1); + } + + /* + * Early check for remote number authorization. + */ + if (!auth_number()) { + ppp_warn("calling number %q is not authorized", remote_number); + exit(EXIT_CNID_AUTH_FAILED); + } +} +#endif /* PPP_OPTIONS */ + +/* + * auth_reset - called when LCP is starting negotiations to recheck + * authentication options, i.e. whether we have appropriate secrets + * to use for authenticating ourselves and/or the peer. + */ +void auth_reset(ppp_pcb *pcb) { + lcp_options *go = &pcb->lcp_gotoptions; + lcp_options *ao = &pcb->lcp_allowoptions; + + if(pcb->settings.passwd) { + +#if PAP_SUPPORT + ao->neg_upap = !pcb->settings.refuse_pap; +#endif /* PAP_SUPPORT */ + +#if EAP_SUPPORT + ao->neg_eap = !pcb->settings.refuse_eap; +#endif /* EAP_SUPPORT */ + +#if CHAP_SUPPORT + ao->chap_mdtype = MDTYPE_NONE; + if(!pcb->settings.refuse_chap) + ao->chap_mdtype |= MDTYPE_MD5; +#if MSCHAP_SUPPORT + if(!pcb->settings.refuse_mschap) + ao->chap_mdtype |= MDTYPE_MICROSOFT; + if(!pcb->settings.refuse_mschap_v2) + ao->chap_mdtype |= MDTYPE_MICROSOFT_V2; +#endif /* MSCHAP_SUPPORT */ + + ao->neg_chap = (ao->chap_mdtype != MDTYPE_NONE); +#endif /* CHAP_SUPPORT */ + + } else { +#if PAP_SUPPORT + ao->neg_upap = 0; +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + ao->neg_chap = 0; + ao->chap_mdtype = MDTYPE_NONE; +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + ao->neg_eap = 0; +#endif /* EAP_SUPPORT */ + } + +#if PAP_SUPPORT + PPPDEBUG(LOG_DEBUG, ("neg_upap: %d\n", ao->neg_upap) ); +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + PPPDEBUG(LOG_DEBUG, ("neg_chap: %d\n", ao->neg_chap) ); + PPPDEBUG(LOG_DEBUG, ("neg_chap_md5: %d\n", !!(ao->chap_mdtype&MDTYPE_MD5)) ); +#if MSCHAP_SUPPORT + PPPDEBUG(LOG_DEBUG, ("neg_chap_ms: %d\n", !!(ao->chap_mdtype&MDTYPE_MICROSOFT)) ); + PPPDEBUG(LOG_DEBUG, ("neg_chap_ms2: %d\n", !!(ao->chap_mdtype&MDTYPE_MICROSOFT_V2)) ); +#endif /* MSCHAP_SUPPORT */ +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + PPPDEBUG(LOG_DEBUG, ("neg_eap: %d\n", ao->neg_eap) ); +#endif /* EAP_SUPPORT */ + +#if 0 /* OLD CODE */ + ao->neg_upap = !ppp_settings.refuse_pap && (ppp_settings.passwd[0] != 0 || get_pap_passwd(NULL)); + + /* + ao->neg_chap = (!ppp_settings.refuse_chap || !refuse_mschap || !refuse_mschap_v2) + && (passwd[0] != 0 || + (hadchap = have_chap_secret(user, (explicit_remote? remote_name: + NULL), 0, NULL))); */ + /* + ao->neg_eap = !refuse_eap && ( + passwd[0] != 0 || + (hadchap == 1 || (hadchap == -1 && have_chap_secret(ppp_settings.user, + (explicit_remote? remote_name: NULL), 0, NULL))) || + have_srp_secret(ppp_settings.user, (explicit_remote? remote_name: NULL), 0, NULL)); */ +#endif /* OLD CODE */ + +#if PAP_SUPPORT + go->neg_upap = 0; +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + go->neg_chap = 0; + go->chap_mdtype = MDTYPE_NONE; +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + go->neg_eap = 0; +#endif /* EAP_SUPPORT */ + return; +#if 0 + /* FIXME: find what the below stuff do */ + int hadchap; + hadchap = -1; + + hadchap = -1; + if (go->neg_upap && !uselogin && !have_pap_secret(NULL)) + go->neg_upap = 0; + + if (go->neg_chap) { + if (!(hadchap = have_chap_secret((explicit_remote? remote_name: NULL), + our_name, 1, NULL))) + go->neg_chap = 0; + } + + if (go->neg_eap && + (hadchap == 0 || (hadchap == -1 && + !have_chap_secret((explicit_remote? remote_name: NULL), our_name, + 1, NULL))) && + !have_srp_secret((explicit_remote? remote_name: NULL), our_name, 1, + NULL)) + go->neg_eap = 0; +#endif +} + +#if 0 /* UNUSED */ +/* + * check_passwd - Check the user name and passwd against the PAP secrets + * file. If requested, also check against the system password database, + * and login the user if OK. + * + * returns: + * UPAP_AUTHNAK: Authentication failed. + * UPAP_AUTHACK: Authentication succeeded. + * In either case, msg points to an appropriate message. + */ +int +check_passwd(unit, auser, userlen, apasswd, passwdlen, msg) + int unit; + char *auser; + int userlen; + char *apasswd; + int passwdlen; + char **msg; +{ + return UPAP_AUTHNAK; + int ret; + char *filename; + FILE *f; + struct wordlist *addrs = NULL, *opts = NULL; + char passwd[256], user[256]; + char secret[MAXWORDLEN]; + static int attempts = 0; + + /* + * Make copies of apasswd and auser, then null-terminate them. + * If there are unprintable characters in the password, make + * them visible. + */ + slprintf(ppp_settings.passwd, sizeof(ppp_settings.passwd), "%.*v", passwdlen, apasswd); + slprintf(ppp_settings.user, sizeof(ppp_settings.user), "%.*v", userlen, auser); + *msg = ""; + + /* + * Check if a plugin wants to handle this. + */ + if (pap_auth_hook) { + ret = (*pap_auth_hook)(ppp_settings.user, ppp_settings.passwd, msg, &addrs, &opts); + if (ret >= 0) { + /* note: set_allowed_addrs() saves opts (but not addrs): + don't free it! */ + if (ret) + set_allowed_addrs(unit, addrs, opts); + else if (opts != 0) + free_wordlist(opts); + if (addrs != 0) + free_wordlist(addrs); + BZERO(ppp_settings.passwd, sizeof(ppp_settings.passwd)); + return ret? UPAP_AUTHACK: UPAP_AUTHNAK; + } + } + + /* + * Open the file of pap secrets and scan for a suitable secret + * for authenticating this user. + */ + filename = _PATH_UPAPFILE; + addrs = opts = NULL; + ret = UPAP_AUTHNAK; + f = fopen(filename, "r"); + if (f == NULL) { + ppp_error("Can't open PAP password file %s: %m", filename); + + } else { + check_access(f, filename); + if (scan_authfile(f, ppp_settings.user, our_name, secret, &addrs, &opts, filename, 0) < 0) { + ppp_warn("no PAP secret found for %s", user); + } else { + /* + * If the secret is "@login", it means to check + * the password against the login database. + */ + int login_secret = strcmp(secret, "@login") == 0; + ret = UPAP_AUTHACK; + if (uselogin || login_secret) { + /* login option or secret is @login */ + if (session_full(ppp_settings.user, ppp_settings.passwd, devnam, msg) == 0) { + ret = UPAP_AUTHNAK; + } + } else if (session_mgmt) { + if (session_check(ppp_settings.user, NULL, devnam, NULL) == 0) { + ppp_warn("Peer %q failed PAP Session verification", user); + ret = UPAP_AUTHNAK; + } + } + if (secret[0] != 0 && !login_secret) { + /* password given in pap-secrets - must match */ + if ((cryptpap || strcmp(ppp_settings.passwd, secret) != 0) + && strcmp(crypt(ppp_settings.passwd, secret), secret) != 0) + ret = UPAP_AUTHNAK; + } + } + fclose(f); + } + + if (ret == UPAP_AUTHNAK) { + if (**msg == 0) + *msg = "Login incorrect"; + /* + * XXX can we ever get here more than once?? + * Frustrate passwd stealer programs. + * Allow 10 tries, but start backing off after 3 (stolen from login). + * On 10'th, drop the connection. + */ + if (attempts++ >= 10) { + ppp_warn("%d LOGIN FAILURES ON %s, %s", attempts, devnam, user); + lcp_close(pcb, "login failed"); + } + if (attempts > 3) + sleep((u_int) (attempts - 3) * 5); + if (opts != NULL) + free_wordlist(opts); + + } else { + attempts = 0; /* Reset count */ + if (**msg == 0) + *msg = "Login ok"; + set_allowed_addrs(unit, addrs, opts); + } + + if (addrs != NULL) + free_wordlist(addrs); + BZERO(ppp_settings.passwd, sizeof(ppp_settings.passwd)); + BZERO(secret, sizeof(secret)); + + return ret; +} + +/* + * null_login - Check if a username of "" and a password of "" are + * acceptable, and iff so, set the list of acceptable IP addresses + * and return 1. + */ +static int +null_login(unit) + int unit; +{ + char *filename; + FILE *f; + int i, ret; + struct wordlist *addrs, *opts; + char secret[MAXWORDLEN]; + + /* + * Check if a plugin wants to handle this. + */ + ret = -1; + if (null_auth_hook) + ret = (*null_auth_hook)(&addrs, &opts); + + /* + * Open the file of pap secrets and scan for a suitable secret. + */ + if (ret <= 0) { + filename = _PATH_UPAPFILE; + addrs = NULL; + f = fopen(filename, "r"); + if (f == NULL) + return 0; + check_access(f, filename); + + i = scan_authfile(f, "", our_name, secret, &addrs, &opts, filename, 0); + ret = i >= 0 && secret[0] == 0; + BZERO(secret, sizeof(secret)); + fclose(f); + } + + if (ret) + set_allowed_addrs(unit, addrs, opts); + else if (opts != 0) + free_wordlist(opts); + if (addrs != 0) + free_wordlist(addrs); + + return ret; +} + +/* + * get_pap_passwd - get a password for authenticating ourselves with + * our peer using PAP. Returns 1 on success, 0 if no suitable password + * could be found. + * Assumes passwd points to MAXSECRETLEN bytes of space (if non-null). + */ +static int +get_pap_passwd(passwd) + char *passwd; +{ + char *filename; + FILE *f; + int ret; + char secret[MAXWORDLEN]; + + /* + * Check whether a plugin wants to supply this. + */ + if (pap_passwd_hook) { + ret = (*pap_passwd_hook)(ppp_settings,user, ppp_settings.passwd); + if (ret >= 0) + return ret; + } + + filename = _PATH_UPAPFILE; + f = fopen(filename, "r"); + if (f == NULL) + return 0; + check_access(f, filename); + ret = scan_authfile(f, user, + (remote_name[0]? remote_name: NULL), + secret, NULL, NULL, filename, 0); + fclose(f); + if (ret < 0) + return 0; + if (passwd != NULL) + strlcpy(passwd, secret, MAXSECRETLEN); + BZERO(secret, sizeof(secret)); + return 1; +} + +/* + * have_pap_secret - check whether we have a PAP file with any + * secrets that we could possibly use for authenticating the peer. + */ +static int +have_pap_secret(lacks_ipp) + int *lacks_ipp; +{ + FILE *f; + int ret; + char *filename; + struct wordlist *addrs; + + /* let the plugin decide, if there is one */ + if (pap_check_hook) { + ret = (*pap_check_hook)(); + if (ret >= 0) + return ret; + } + + filename = _PATH_UPAPFILE; + f = fopen(filename, "r"); + if (f == NULL) + return 0; + + ret = scan_authfile(f, (explicit_remote? remote_name: NULL), our_name, + NULL, &addrs, NULL, filename, 0); + fclose(f); + if (ret >= 0 && !some_ip_ok(addrs)) { + if (lacks_ipp != 0) + *lacks_ipp = 1; + ret = -1; + } + if (addrs != 0) + free_wordlist(addrs); + + return ret >= 0; +} + +/* + * have_chap_secret - check whether we have a CHAP file with a + * secret that we could possibly use for authenticating `client' + * on `server'. Either can be the null string, meaning we don't + * know the identity yet. + */ +static int +have_chap_secret(client, server, need_ip, lacks_ipp) + char *client; + char *server; + int need_ip; + int *lacks_ipp; +{ + FILE *f; + int ret; + char *filename; + struct wordlist *addrs; + + if (chap_check_hook) { + ret = (*chap_check_hook)(); + if (ret >= 0) { + return ret; + } + } + + filename = _PATH_CHAPFILE; + f = fopen(filename, "r"); + if (f == NULL) + return 0; + + if (client != NULL && client[0] == 0) + client = NULL; + else if (server != NULL && server[0] == 0) + server = NULL; + + ret = scan_authfile(f, client, server, NULL, &addrs, NULL, filename, 0); + fclose(f); + if (ret >= 0 && need_ip && !some_ip_ok(addrs)) { + if (lacks_ipp != 0) + *lacks_ipp = 1; + ret = -1; + } + if (addrs != 0) + free_wordlist(addrs); + + return ret >= 0; +} + +/* + * have_srp_secret - check whether we have a SRP file with a + * secret that we could possibly use for authenticating `client' + * on `server'. Either can be the null string, meaning we don't + * know the identity yet. + */ +static int +have_srp_secret(client, server, need_ip, lacks_ipp) + char *client; + char *server; + int need_ip; + int *lacks_ipp; +{ + FILE *f; + int ret; + char *filename; + struct wordlist *addrs; + + filename = _PATH_SRPFILE; + f = fopen(filename, "r"); + if (f == NULL) + return 0; + + if (client != NULL && client[0] == 0) + client = NULL; + else if (server != NULL && server[0] == 0) + server = NULL; + + ret = scan_authfile(f, client, server, NULL, &addrs, NULL, filename, 0); + fclose(f); + if (ret >= 0 && need_ip && !some_ip_ok(addrs)) { + if (lacks_ipp != 0) + *lacks_ipp = 1; + ret = -1; + } + if (addrs != 0) + free_wordlist(addrs); + + return ret >= 0; +} +#endif /* UNUSED */ + +/* + * get_secret - open the CHAP secret file and return the secret + * for authenticating the given client on the given server. + * (We could be either client or server). + */ +int get_secret(ppp_pcb *pcb, const char *client, const char *server, char *secret, int *secret_len, int am_server) { + int len; + + LWIP_UNUSED_ARG(server); + LWIP_UNUSED_ARG(am_server); + + if(!client || !client[0] || !pcb->settings.user || !pcb->settings.passwd || strcmp(client, pcb->settings.user)) { + return 0; + } + + len = (int)strlen(pcb->settings.passwd); + if (len > MAXSECRETLEN) { + ppp_error("Secret for %s on %s is too long", client, server); + len = MAXSECRETLEN; + } + + MEMCPY(secret, pcb->settings.passwd, len); + *secret_len = len; + + return 1; + +/* FIXME: clean that */ +#if 0 + strlcpy(rname, ppp_settings.user, sizeof(rname)); + + +/* + strlcpy(rname, ppp_settings.user, sizeof(rname)); + strlcpy(secret, ppp_settings.passwd, sizeof(secret)); + secret_len = strlen(secret); +*/ + + FILE *f; + int ret, len; + char *filename; + struct wordlist *addrs, *opts; + char secbuf[MAXWORDLEN]; + struct wordlist *addrs; + addrs = NULL; + + if (!am_server && ppp_settings.passwd[0] != 0) { + strlcpy(secbuf, ppp_settings.passwd, sizeof(secbuf)); + } else if (!am_server && chap_passwd_hook) { + if ( (*chap_passwd_hook)(client, secbuf) < 0) { + ppp_error("Unable to obtain CHAP password for %s on %s from plugin", + client, server); + return 0; + } + } else { + filename = _PATH_CHAPFILE; + addrs = NULL; + secbuf[0] = 0; + + f = fopen(filename, "r"); + if (f == NULL) { + ppp_error("Can't open chap secret file %s: %m", filename); + return 0; + } + check_access(f, filename); + + ret = scan_authfile(f, client, server, secbuf, &addrs, &opts, filename, 0); + fclose(f); + if (ret < 0) + return 0; + + if (am_server) + set_allowed_addrs(unit, addrs, opts); + else if (opts != 0) + free_wordlist(opts); + if (addrs != 0) + free_wordlist(addrs); + } + + len = strlen(secbuf); + if (len > MAXSECRETLEN) { + ppp_error("Secret for %s on %s is too long", client, server); + len = MAXSECRETLEN; + } + MEMCPY(secret, secbuf, len); + BZERO(secbuf, sizeof(secbuf)); + *secret_len = len; + + return 1; +#endif +} + + +#if 0 /* UNUSED */ +/* + * get_srp_secret - open the SRP secret file and return the secret + * for authenticating the given client on the given server. + * (We could be either client or server). + */ +int +get_srp_secret(unit, client, server, secret, am_server) + int unit; + char *client; + char *server; + char *secret; + int am_server; +{ + FILE *fp; + int ret; + char *filename; + struct wordlist *addrs, *opts; + + if (!am_server && ppp_settings.passwd[0] != '\0') { + strlcpy(secret, ppp_settings.passwd, MAXWORDLEN); + } else { + filename = _PATH_SRPFILE; + addrs = NULL; + + fp = fopen(filename, "r"); + if (fp == NULL) { + ppp_error("Can't open srp secret file %s: %m", filename); + return 0; + } + check_access(fp, filename); + + secret[0] = '\0'; + ret = scan_authfile(fp, client, server, secret, &addrs, &opts, + filename, am_server); + fclose(fp); + if (ret < 0) + return 0; + + if (am_server) + set_allowed_addrs(unit, addrs, opts); + else if (opts != NULL) + free_wordlist(opts); + if (addrs != NULL) + free_wordlist(addrs); + } + + return 1; +} + +/* + * set_allowed_addrs() - set the list of allowed addresses. + * Also looks for `--' indicating options to apply for this peer + * and leaves the following words in extra_options. + */ +static void +set_allowed_addrs(unit, addrs, opts) + int unit; + struct wordlist *addrs; + struct wordlist *opts; +{ + int n; + struct wordlist *ap, **plink; + struct permitted_ip *ip; + char *ptr_word, *ptr_mask; + struct hostent *hp; + struct netent *np; + u32_t a, mask, ah, offset; + struct ipcp_options *wo = &ipcp_wantoptions[unit]; + u32_t suggested_ip = 0; + + if (addresses[unit] != NULL) + free(addresses[unit]); + addresses[unit] = NULL; + if (extra_options != NULL) + free_wordlist(extra_options); + extra_options = opts; + + /* + * Count the number of IP addresses given. + */ + n = wordlist_count(addrs) + wordlist_count(noauth_addrs); + if (n == 0) + return; + ip = (struct permitted_ip *) malloc((n + 1) * sizeof(struct permitted_ip)); + if (ip == 0) + return; + + /* temporarily append the noauth_addrs list to addrs */ + for (plink = &addrs; *plink != NULL; plink = &(*plink)->next) + ; + *plink = noauth_addrs; + + n = 0; + for (ap = addrs; ap != NULL; ap = ap->next) { + /* "-" means no addresses authorized, "*" means any address allowed */ + ptr_word = ap->word; + if (strcmp(ptr_word, "-") == 0) + break; + if (strcmp(ptr_word, "*") == 0) { + ip[n].permit = 1; + ip[n].base = ip[n].mask = 0; + ++n; + break; + } + + ip[n].permit = 1; + if (*ptr_word == '!') { + ip[n].permit = 0; + ++ptr_word; + } + + mask = ~ (u32_t) 0; + offset = 0; + ptr_mask = strchr (ptr_word, '/'); + if (ptr_mask != NULL) { + int bit_count; + char *endp; + + bit_count = (int) strtol (ptr_mask+1, &endp, 10); + if (bit_count <= 0 || bit_count > 32) { + ppp_warn("invalid address length %v in auth. address list", + ptr_mask+1); + continue; + } + bit_count = 32 - bit_count; /* # bits in host part */ + if (*endp == '+') { + offset = ifunit + 1; + ++endp; + } + if (*endp != 0) { + ppp_warn("invalid address length syntax: %v", ptr_mask+1); + continue; + } + *ptr_mask = '\0'; + mask <<= bit_count; + } + + hp = gethostbyname(ptr_word); + if (hp != NULL && hp->h_addrtype == AF_INET) { + a = *(u32_t *)hp->h_addr; + } else { + np = getnetbyname (ptr_word); + if (np != NULL && np->n_addrtype == AF_INET) { + a = htonl ((u32_t)np->n_net); + if (ptr_mask == NULL) { + /* calculate appropriate mask for net */ + ah = ntohl(a); + if (IN_CLASSA(ah)) + mask = IN_CLASSA_NET; + else if (IN_CLASSB(ah)) + mask = IN_CLASSB_NET; + else if (IN_CLASSC(ah)) + mask = IN_CLASSC_NET; + } + } else { + a = inet_addr (ptr_word); + } + } + + if (ptr_mask != NULL) + *ptr_mask = '/'; + + if (a == (u32_t)-1L) { + ppp_warn("unknown host %s in auth. address list", ap->word); + continue; + } + if (offset != 0) { + if (offset >= ~mask) { + ppp_warn("interface unit %d too large for subnet %v", + ifunit, ptr_word); + continue; + } + a = htonl((ntohl(a) & mask) + offset); + mask = ~(u32_t)0; + } + ip[n].mask = htonl(mask); + ip[n].base = a & ip[n].mask; + ++n; + if (~mask == 0 && suggested_ip == 0) + suggested_ip = a; + } + *plink = NULL; + + ip[n].permit = 0; /* make the last entry forbid all addresses */ + ip[n].base = 0; /* to terminate the list */ + ip[n].mask = 0; + + addresses[unit] = ip; + + /* + * If the address given for the peer isn't authorized, or if + * the user hasn't given one, AND there is an authorized address + * which is a single host, then use that if we find one. + */ + if (suggested_ip != 0 + && (wo->hisaddr == 0 || !auth_ip_addr(unit, wo->hisaddr))) { + wo->hisaddr = suggested_ip; + /* + * Do we insist on this address? No, if there are other + * addresses authorized than the suggested one. + */ + if (n > 1) + wo->accept_remote = 1; + } +} + +/* + * auth_ip_addr - check whether the peer is authorized to use + * a given IP address. Returns 1 if authorized, 0 otherwise. + */ +int +auth_ip_addr(unit, addr) + int unit; + u32_t addr; +{ + int ok; + + /* don't allow loopback or multicast address */ + if (bad_ip_adrs(addr)) + return 0; + + if (allowed_address_hook) { + ok = allowed_address_hook(addr); + if (ok >= 0) return ok; + } + + if (addresses[unit] != NULL) { + ok = ip_addr_check(addr, addresses[unit]); + if (ok >= 0) + return ok; + } + + if (auth_required) + return 0; /* no addresses authorized */ + return allow_any_ip || privileged || !have_route_to(addr); +} + +static int +ip_addr_check(addr, addrs) + u32_t addr; + struct permitted_ip *addrs; +{ + for (; ; ++addrs) + if ((addr & addrs->mask) == addrs->base) + return addrs->permit; +} + +/* + * bad_ip_adrs - return 1 if the IP address is one we don't want + * to use, such as an address in the loopback net or a multicast address. + * addr is in network byte order. + */ +int +bad_ip_adrs(addr) + u32_t addr; +{ + addr = ntohl(addr); + return (addr >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET + || IN_MULTICAST(addr) || IN_BADCLASS(addr); +} + +/* + * some_ip_ok - check a wordlist to see if it authorizes any + * IP address(es). + */ +static int +some_ip_ok(addrs) + struct wordlist *addrs; +{ + for (; addrs != 0; addrs = addrs->next) { + if (addrs->word[0] == '-') + break; + if (addrs->word[0] != '!') + return 1; /* some IP address is allowed */ + } + return 0; +} + +/* + * auth_number - check whether the remote number is allowed to connect. + * Returns 1 if authorized, 0 otherwise. + */ +int +auth_number() +{ + struct wordlist *wp = permitted_numbers; + int l; + + /* Allow all if no authorization list. */ + if (!wp) + return 1; + + /* Allow if we have a match in the authorization list. */ + while (wp) { + /* trailing '*' wildcard */ + l = strlen(wp->word); + if ((wp->word)[l - 1] == '*') + l--; + if (!strncasecmp(wp->word, remote_number, l)) + return 1; + wp = wp->next; + } + + return 0; +} + +/* + * check_access - complain if a secret file has too-liberal permissions. + */ +static void +check_access(f, filename) + FILE *f; + char *filename; +{ + struct stat sbuf; + + if (fstat(fileno(f), &sbuf) < 0) { + ppp_warn("cannot stat secret file %s: %m", filename); + } else if ((sbuf.st_mode & (S_IRWXG | S_IRWXO)) != 0) { + ppp_warn("Warning - secret file %s has world and/or group access", + filename); + } +} + +/* + * scan_authfile - Scan an authorization file for a secret suitable + * for authenticating `client' on `server'. The return value is -1 + * if no secret is found, otherwise >= 0. The return value has + * NONWILD_CLIENT set if the secret didn't have "*" for the client, and + * NONWILD_SERVER set if the secret didn't have "*" for the server. + * Any following words on the line up to a "--" (i.e. address authorization + * info) are placed in a wordlist and returned in *addrs. Any + * following words (extra options) are placed in a wordlist and + * returned in *opts. + * We assume secret is NULL or points to MAXWORDLEN bytes of space. + * Flags are non-zero if we need two colons in the secret in order to + * match. + */ +static int +scan_authfile(f, client, server, secret, addrs, opts, filename, flags) + FILE *f; + char *client; + char *server; + char *secret; + struct wordlist **addrs; + struct wordlist **opts; + char *filename; + int flags; +{ + int newline, xxx; + int got_flag, best_flag; + FILE *sf; + struct wordlist *ap, *addr_list, *alist, **app; + char word[MAXWORDLEN]; + char atfile[MAXWORDLEN]; + char lsecret[MAXWORDLEN]; + char *cp; + + if (addrs != NULL) + *addrs = NULL; + if (opts != NULL) + *opts = NULL; + addr_list = NULL; + if (!getword(f, word, &newline, filename)) + return -1; /* file is empty??? */ + newline = 1; + best_flag = -1; + for (;;) { + /* + * Skip until we find a word at the start of a line. + */ + while (!newline && getword(f, word, &newline, filename)) + ; + if (!newline) + break; /* got to end of file */ + + /* + * Got a client - check if it's a match or a wildcard. + */ + got_flag = 0; + if (client != NULL && strcmp(word, client) != 0 && !ISWILD(word)) { + newline = 0; + continue; + } + if (!ISWILD(word)) + got_flag = NONWILD_CLIENT; + + /* + * Now get a server and check if it matches. + */ + if (!getword(f, word, &newline, filename)) + break; + if (newline) + continue; + if (!ISWILD(word)) { + if (server != NULL && strcmp(word, server) != 0) + continue; + got_flag |= NONWILD_SERVER; + } + + /* + * Got some sort of a match - see if it's better than what + * we have already. + */ + if (got_flag <= best_flag) + continue; + + /* + * Get the secret. + */ + if (!getword(f, word, &newline, filename)) + break; + if (newline) + continue; + + /* + * SRP-SHA1 authenticator should never be reading secrets from + * a file. (Authenticatee may, though.) + */ + if (flags && ((cp = strchr(word, ':')) == NULL || + strchr(cp + 1, ':') == NULL)) + continue; + + if (secret != NULL) { + /* + * Special syntax: @/pathname means read secret from file. + */ + if (word[0] == '@' && word[1] == '/') { + strlcpy(atfile, word+1, sizeof(atfile)); + if ((sf = fopen(atfile, "r")) == NULL) { + ppp_warn("can't open indirect secret file %s", atfile); + continue; + } + check_access(sf, atfile); + if (!getword(sf, word, &xxx, atfile)) { + ppp_warn("no secret in indirect secret file %s", atfile); + fclose(sf); + continue; + } + fclose(sf); + } + strlcpy(lsecret, word, sizeof(lsecret)); + } + + /* + * Now read address authorization info and make a wordlist. + */ + app = &alist; + for (;;) { + if (!getword(f, word, &newline, filename) || newline) + break; + ap = (struct wordlist *) + malloc(sizeof(struct wordlist) + strlen(word) + 1); + if (ap == NULL) + novm("authorized addresses"); + ap->word = (char *) (ap + 1); + strcpy(ap->word, word); + *app = ap; + app = &ap->next; + } + *app = NULL; + + /* + * This is the best so far; remember it. + */ + best_flag = got_flag; + if (addr_list) + free_wordlist(addr_list); + addr_list = alist; + if (secret != NULL) + strlcpy(secret, lsecret, MAXWORDLEN); + + if (!newline) + break; + } + + /* scan for a -- word indicating the start of options */ + for (app = &addr_list; (ap = *app) != NULL; app = &ap->next) + if (strcmp(ap->word, "--") == 0) + break; + /* ap = start of options */ + if (ap != NULL) { + ap = ap->next; /* first option */ + free(*app); /* free the "--" word */ + *app = NULL; /* terminate addr list */ + } + if (opts != NULL) + *opts = ap; + else if (ap != NULL) + free_wordlist(ap); + if (addrs != NULL) + *addrs = addr_list; + else if (addr_list != NULL) + free_wordlist(addr_list); + + return best_flag; +} + +/* + * wordlist_count - return the number of items in a wordlist + */ +static int +wordlist_count(wp) + struct wordlist *wp; +{ + int n; + + for (n = 0; wp != NULL; wp = wp->next) + ++n; + return n; +} + +/* + * free_wordlist - release memory allocated for a wordlist. + */ +static void +free_wordlist(wp) + struct wordlist *wp; +{ + struct wordlist *next; + + while (wp != NULL) { + next = wp->next; + free(wp); + wp = next; + } +} +#endif /* UNUSED */ + +#endif /* PPP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/ccp.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/ccp.c new file mode 100644 index 0000000..0af3548 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/ccp.c @@ -0,0 +1,1694 @@ +/* + * ccp.c - PPP Compression Control Protocol. + * + * Copyright (c) 1994-2002 Paul Mackerras. 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. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && CCP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include +#include + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/fsm.h" +#include "netif/ppp/ccp.h" +#include + +#ifdef MPPE +#include "netif/ppp/chap_ms.h" /* mppe_xxxx_key, mppe_keys_set */ +#include "netif/ppp/lcp.h" /* lcp_close(), lcp_fsm */ +#endif + +/* + * Unfortunately there is a bug in zlib which means that using a + * size of 8 (window size = 256) for Deflate compression will cause + * buffer overruns and kernel crashes in the deflate module. + * Until this is fixed we only accept sizes in the range 9 .. 15. + * Thanks to James Carlson for pointing this out. + */ +#define DEFLATE_MIN_WORKS 9 + +/* + * Command-line options. + */ +static int setbsdcomp (char **); +static int setdeflate (char **); +static char bsd_value[8]; +static char deflate_value[8]; + +/* + * Option variables. + */ +#ifdef MPPE +bool refuse_mppe_stateful = 1; /* Allow stateful mode? */ +#endif + +#if PPP_OPTIONS +static option_t ccp_option_list[] = { + { "noccp", o_bool, &ccp_protent.enabled_flag, + "Disable CCP negotiation" }, + { "-ccp", o_bool, &ccp_protent.enabled_flag, + "Disable CCP negotiation", OPT_ALIAS }, + + { "bsdcomp", o_special, (void *)setbsdcomp, + "Request BSD-Compress packet compression", + OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, bsd_value }, + { "nobsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress, + "don't allow BSD-Compress", OPT_PRIOSUB | OPT_A2CLR, + &ccp_allowoptions[0].bsd_compress }, + { "-bsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress, + "don't allow BSD-Compress", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR, + &ccp_allowoptions[0].bsd_compress }, + + { "deflate", o_special, (void *)setdeflate, + "request Deflate compression", + OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, deflate_value }, + { "nodeflate", o_bool, &ccp_wantoptions[0].deflate, + "don't allow Deflate compression", OPT_PRIOSUB | OPT_A2CLR, + &ccp_allowoptions[0].deflate }, + { "-deflate", o_bool, &ccp_wantoptions[0].deflate, + "don't allow Deflate compression", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR, + &ccp_allowoptions[0].deflate }, + + { "nodeflatedraft", o_bool, &ccp_wantoptions[0].deflate_draft, + "don't use draft deflate #", OPT_A2COPY, + &ccp_allowoptions[0].deflate_draft }, + + { "predictor1", o_bool, &ccp_wantoptions[0].predictor_1, + "request Predictor-1", OPT_PRIO | 1 }, + { "nopredictor1", o_bool, &ccp_wantoptions[0].predictor_1, + "don't allow Predictor-1", OPT_PRIOSUB | OPT_A2CLR, + &ccp_allowoptions[0].predictor_1 }, + { "-predictor1", o_bool, &ccp_wantoptions[0].predictor_1, + "don't allow Predictor-1", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR, + &ccp_allowoptions[0].predictor_1 }, + +#ifdef MPPE + /* MPPE options are symmetrical ... we only set wantoptions here */ + { "require-mppe", o_bool, &ccp_wantoptions[0].mppe, + "require MPPE encryption", + OPT_PRIO | MPPE_OPT_40 | MPPE_OPT_128 }, + { "+mppe", o_bool, &ccp_wantoptions[0].mppe, + "require MPPE encryption", + OPT_ALIAS | OPT_PRIO | MPPE_OPT_40 | MPPE_OPT_128 }, + { "nomppe", o_bool, &ccp_wantoptions[0].mppe, + "don't allow MPPE encryption", OPT_PRIO }, + { "-mppe", o_bool, &ccp_wantoptions[0].mppe, + "don't allow MPPE encryption", OPT_ALIAS | OPT_PRIO }, + + /* We use ccp_allowoptions[0].mppe as a junk var ... it is reset later */ + { "require-mppe-40", o_bool, &ccp_allowoptions[0].mppe, + "require MPPE 40-bit encryption", OPT_PRIO | OPT_A2OR | MPPE_OPT_40, + &ccp_wantoptions[0].mppe }, + { "+mppe-40", o_bool, &ccp_allowoptions[0].mppe, + "require MPPE 40-bit encryption", OPT_PRIO | OPT_A2OR | MPPE_OPT_40, + &ccp_wantoptions[0].mppe }, + { "nomppe-40", o_bool, &ccp_allowoptions[0].mppe, + "don't allow MPPE 40-bit encryption", + OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_40, &ccp_wantoptions[0].mppe }, + { "-mppe-40", o_bool, &ccp_allowoptions[0].mppe, + "don't allow MPPE 40-bit encryption", + OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_40, + &ccp_wantoptions[0].mppe }, + + { "require-mppe-128", o_bool, &ccp_allowoptions[0].mppe, + "require MPPE 128-bit encryption", OPT_PRIO | OPT_A2OR | MPPE_OPT_128, + &ccp_wantoptions[0].mppe }, + { "+mppe-128", o_bool, &ccp_allowoptions[0].mppe, + "require MPPE 128-bit encryption", + OPT_ALIAS | OPT_PRIO | OPT_A2OR | MPPE_OPT_128, + &ccp_wantoptions[0].mppe }, + { "nomppe-128", o_bool, &ccp_allowoptions[0].mppe, + "don't allow MPPE 128-bit encryption", + OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_128, &ccp_wantoptions[0].mppe }, + { "-mppe-128", o_bool, &ccp_allowoptions[0].mppe, + "don't allow MPPE 128-bit encryption", + OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_128, + &ccp_wantoptions[0].mppe }, + + /* strange one; we always request stateless, but will we allow stateful? */ + { "mppe-stateful", o_bool, &refuse_mppe_stateful, + "allow MPPE stateful mode", OPT_PRIO }, + { "nomppe-stateful", o_bool, &refuse_mppe_stateful, + "disallow MPPE stateful mode", OPT_PRIO | 1 }, +#endif /* MPPE */ + + { NULL } +}; +#endif /* PPP_OPTIONS */ + +/* + * Protocol entry points from main code. + */ +static void ccp_init (int unit); +static void ccp_open (int unit); +static void ccp_close (int unit, const char *); +static void ccp_lowerup (int unit); +static void ccp_lowerdown (int); +static void ccp_input (int unit, u_char *pkt, int len); +static void ccp_protrej (int unit); +#if PRINTPKT_SUPPORT +static int ccp_printpkt (u_char *pkt, int len, + void (*printer) (void *, char *, ...), + void *arg); +#endif /* PRINTPKT_SUPPORT */ +static void ccp_datainput (int unit, u_char *pkt, int len); + +const struct protent ccp_protent = { + PPP_CCP, + ccp_init, + ccp_input, + ccp_protrej, + ccp_lowerup, + ccp_lowerdown, + ccp_open, + ccp_close, +#if PRINTPKT_SUPPORT + ccp_printpkt, +#endif /* PRINTPKT_SUPPORT */ + ccp_datainput, + 1, +#if PRINTPKT_SUPPORT + "CCP", + "Compressed", +#endif /* PRINTPKT_SUPPORT */ +#if PPP_OPTIONS + ccp_option_list, + NULL, +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT + NULL, + NULL +#endif /* DEMAND_SUPPORT */ +}; + +fsm ccp_fsm[NUM_PPP]; +ccp_options ccp_wantoptions[NUM_PPP]; /* what to request the peer to use */ +ccp_options ccp_gotoptions[NUM_PPP]; /* what the peer agreed to do */ +ccp_options ccp_allowoptions[NUM_PPP]; /* what we'll agree to do */ +ccp_options ccp_hisoptions[NUM_PPP]; /* what we agreed to do */ + +/* + * Callbacks for fsm code. + */ +static void ccp_resetci (fsm *); +static int ccp_cilen (fsm *); +static void ccp_addci (fsm *, u_char *, int *); +static int ccp_ackci (fsm *, u_char *, int); +static int ccp_nakci (fsm *, u_char *, int, int); +static int ccp_rejci (fsm *, u_char *, int); +static int ccp_reqci (fsm *, u_char *, int *, int); +static void ccp_up (fsm *); +static void ccp_down (fsm *); +static int ccp_extcode (fsm *, int, int, u_char *, int); +static void ccp_rack_timeout (void *); +static char *method_name (ccp_options *, ccp_options *); + +static const fsm_callbacks ccp_callbacks = { + ccp_resetci, + ccp_cilen, + ccp_addci, + ccp_ackci, + ccp_nakci, + ccp_rejci, + ccp_reqci, + ccp_up, + ccp_down, + NULL, + NULL, + NULL, + NULL, + ccp_extcode, + "CCP" +}; + +/* + * Do we want / did we get any compression? + */ +#define ANY_COMPRESS(opt) ((opt).deflate || (opt).bsd_compress \ + || (opt).predictor_1 || (opt).predictor_2 \ + || (opt).mppe) + +/* + * Local state (mainly for handling reset-reqs and reset-acks). + */ +static int ccp_localstate[NUM_PPP]; +#define RACK_PENDING 1 /* waiting for reset-ack */ +#define RREQ_REPEAT 2 /* send another reset-req if no reset-ack */ + +#define RACKTIMEOUT 1 /* second */ + +static int all_rejected[NUM_PPP]; /* we rejected all peer's options */ + +/* + * Option parsing + */ +static int +setbsdcomp(argv) + char **argv; +{ + int rbits, abits; + char *str, *endp; + + str = *argv; + abits = rbits = strtol(str, &endp, 0); + if (endp != str && *endp == ',') { + str = endp + 1; + abits = strtol(str, &endp, 0); + } + if (*endp != 0 || endp == str) { + option_error("invalid parameter '%s' for bsdcomp option", *argv); + return 0; + } + if ((rbits != 0 && (rbits < BSD_MIN_BITS || rbits > BSD_MAX_BITS)) + || (abits != 0 && (abits < BSD_MIN_BITS || abits > BSD_MAX_BITS))) { + option_error("bsdcomp option values must be 0 or %d .. %d", + BSD_MIN_BITS, BSD_MAX_BITS); + return 0; + } + if (rbits > 0) { + ccp_wantoptions[0].bsd_compress = 1; + ccp_wantoptions[0].bsd_bits = rbits; + } else + ccp_wantoptions[0].bsd_compress = 0; + if (abits > 0) { + ccp_allowoptions[0].bsd_compress = 1; + ccp_allowoptions[0].bsd_bits = abits; + } else + ccp_allowoptions[0].bsd_compress = 0; + slprintf(bsd_value, sizeof(bsd_value), + rbits == abits? "%d": "%d,%d", rbits, abits); + + return 1; +} + +static int +setdeflate(argv) + char **argv; +{ + int rbits, abits; + char *str, *endp; + + str = *argv; + abits = rbits = strtol(str, &endp, 0); + if (endp != str && *endp == ',') { + str = endp + 1; + abits = strtol(str, &endp, 0); + } + if (*endp != 0 || endp == str) { + option_error("invalid parameter '%s' for deflate option", *argv); + return 0; + } + if ((rbits != 0 && (rbits < DEFLATE_MIN_SIZE || rbits > DEFLATE_MAX_SIZE)) + || (abits != 0 && (abits < DEFLATE_MIN_SIZE + || abits > DEFLATE_MAX_SIZE))) { + option_error("deflate option values must be 0 or %d .. %d", + DEFLATE_MIN_SIZE, DEFLATE_MAX_SIZE); + return 0; + } + if (rbits == DEFLATE_MIN_SIZE || abits == DEFLATE_MIN_SIZE) { + if (rbits == DEFLATE_MIN_SIZE) + rbits = DEFLATE_MIN_WORKS; + if (abits == DEFLATE_MIN_SIZE) + abits = DEFLATE_MIN_WORKS; + warn("deflate option value of %d changed to %d to avoid zlib bug", + DEFLATE_MIN_SIZE, DEFLATE_MIN_WORKS); + } + if (rbits > 0) { + ccp_wantoptions[0].deflate = 1; + ccp_wantoptions[0].deflate_size = rbits; + } else + ccp_wantoptions[0].deflate = 0; + if (abits > 0) { + ccp_allowoptions[0].deflate = 1; + ccp_allowoptions[0].deflate_size = abits; + } else + ccp_allowoptions[0].deflate = 0; + slprintf(deflate_value, sizeof(deflate_value), + rbits == abits? "%d": "%d,%d", rbits, abits); + + return 1; +} + +/* + * ccp_init - initialize CCP. + */ +static void +ccp_init(unit) + int unit; +{ + fsm *f = &ccp_fsm[unit]; + + f->unit = unit; + f->protocol = PPP_CCP; + f->callbacks = &ccp_callbacks; + fsm_init(f); + + memset(&ccp_wantoptions[unit], 0, sizeof(ccp_options)); + memset(&ccp_gotoptions[unit], 0, sizeof(ccp_options)); + memset(&ccp_allowoptions[unit], 0, sizeof(ccp_options)); + memset(&ccp_hisoptions[unit], 0, sizeof(ccp_options)); + + ccp_wantoptions[0].deflate = 1; + ccp_wantoptions[0].deflate_size = DEFLATE_MAX_SIZE; + ccp_wantoptions[0].deflate_correct = 1; + ccp_wantoptions[0].deflate_draft = 1; + ccp_allowoptions[0].deflate = 1; + ccp_allowoptions[0].deflate_size = DEFLATE_MAX_SIZE; + ccp_allowoptions[0].deflate_correct = 1; + ccp_allowoptions[0].deflate_draft = 1; + + ccp_wantoptions[0].bsd_compress = 1; + ccp_wantoptions[0].bsd_bits = BSD_MAX_BITS; + ccp_allowoptions[0].bsd_compress = 1; + ccp_allowoptions[0].bsd_bits = BSD_MAX_BITS; + + ccp_allowoptions[0].predictor_1 = 1; +} + +/* + * ccp_open - CCP is allowed to come up. + */ +static void +ccp_open(unit) + int unit; +{ + fsm *f = &ccp_fsm[unit]; + + if (f->state != OPENED) + ccp_flags_set(unit, 1, 0); + + /* + * Find out which compressors the kernel supports before + * deciding whether to open in silent mode. + */ + ccp_resetci(f); + if (!ANY_COMPRESS(ccp_gotoptions[unit])) + f->flags |= OPT_SILENT; + + fsm_open(f); +} + +/* + * ccp_close - Terminate CCP. + */ +static void +ccp_close(unit, reason) + int unit; + const char *reason; +{ + ccp_flags_set(unit, 0, 0); + fsm_close(&ccp_fsm[unit], reason); +} + +/* + * ccp_lowerup - we may now transmit CCP packets. + */ +static void +ccp_lowerup(unit) + int unit; +{ + fsm_lowerup(&ccp_fsm[unit]); +} + +/* + * ccp_lowerdown - we may not transmit CCP packets. + */ +static void +ccp_lowerdown(unit) + int unit; +{ + fsm_lowerdown(&ccp_fsm[unit]); +} + +/* + * ccp_input - process a received CCP packet. + */ +static void +ccp_input(unit, p, len) + int unit; + u_char *p; + int len; +{ + fsm *f = &ccp_fsm[unit]; + int oldstate; + + /* + * Check for a terminate-request so we can print a message. + */ + oldstate = f->state; + fsm_input(f, p, len); + if (oldstate == OPENED && p[0] == TERMREQ && f->state != OPENED) { + notice("Compression disabled by peer."); +#ifdef MPPE + if (ccp_gotoptions[unit].mppe) { + error("MPPE disabled, closing LCP"); + lcp_close(unit, "MPPE disabled by peer"); + } +#endif + } + + /* + * If we get a terminate-ack and we're not asking for compression, + * close CCP. + */ + if (oldstate == REQSENT && p[0] == TERMACK + && !ANY_COMPRESS(ccp_gotoptions[unit])) + ccp_close(unit, "No compression negotiated"); +} + +/* + * Handle a CCP-specific code. + */ +static int +ccp_extcode(f, code, id, p, len) + fsm *f; + int code, id; + u_char *p; + int len; +{ + switch (code) { + case CCP_RESETREQ: + if (f->state != OPENED) + break; + /* send a reset-ack, which the transmitter will see and + reset its compression state. */ + fsm_sdata(f, CCP_RESETACK, id, NULL, 0); + break; + + case CCP_RESETACK: + if (ccp_localstate[f->unit] & RACK_PENDING && id == f->reqid) { + ccp_localstate[f->unit] &= ~(RACK_PENDING | RREQ_REPEAT); + UNTIMEOUT(ccp_rack_timeout, f); + } + break; + + default: + return 0; + } + + return 1; +} + +/* + * ccp_protrej - peer doesn't talk CCP. + */ +static void +ccp_protrej(unit) + int unit; +{ + ccp_flags_set(unit, 0, 0); + fsm_lowerdown(&ccp_fsm[unit]); + +#ifdef MPPE + if (ccp_gotoptions[unit].mppe) { + error("MPPE required but peer negotiation failed"); + lcp_close(unit, "MPPE required but peer negotiation failed"); + } +#endif + +} + +/* + * ccp_resetci - initialize at start of negotiation. + */ +static void +ccp_resetci(f) + fsm *f; +{ + ccp_options *go = &ccp_gotoptions[f->unit]; + u_char opt_buf[CCP_MAX_OPTION_LENGTH]; + + *go = ccp_wantoptions[f->unit]; + all_rejected[f->unit] = 0; + +#ifdef MPPE + if (go->mppe) { + ccp_options *ao = &ccp_allowoptions[f->unit]; + int auth_mschap_bits = auth_done[f->unit]; + int numbits; + + /* + * Start with a basic sanity check: mschap[v2] auth must be in + * exactly one direction. RFC 3079 says that the keys are + * 'derived from the credentials of the peer that initiated the call', + * however the PPP protocol doesn't have such a concept, and pppd + * cannot get this info externally. Instead we do the best we can. + * NB: If MPPE is required, all other compression opts are invalid. + * So, we return right away if we can't do it. + */ + + /* Leave only the mschap auth bits set */ + auth_mschap_bits &= (CHAP_MS_WITHPEER | CHAP_MS_PEER | + CHAP_MS2_WITHPEER | CHAP_MS2_PEER); + /* Count the mschap auths */ + auth_mschap_bits >>= CHAP_MS_SHIFT; + numbits = 0; + do { + numbits += auth_mschap_bits & 1; + auth_mschap_bits >>= 1; + } while (auth_mschap_bits); + if (numbits > 1) { + error("MPPE required, but auth done in both directions."); + lcp_close(f->unit, "MPPE required but not available"); + return; + } + if (!numbits) { + error("MPPE required, but MS-CHAP[v2] auth not performed."); + lcp_close(f->unit, "MPPE required but not available"); + return; + } + + /* A plugin (eg radius) may not have obtained key material. */ + if (!mppe_keys_set) { + error("MPPE required, but keys are not available. " + "Possible plugin problem?"); + lcp_close(f->unit, "MPPE required but not available"); + return; + } + + /* LM auth not supported for MPPE */ + if (auth_done[f->unit] & (CHAP_MS_WITHPEER | CHAP_MS_PEER)) { + /* This might be noise */ + if (go->mppe & MPPE_OPT_40) { + notice("Disabling 40-bit MPPE; MS-CHAP LM not supported"); + go->mppe &= ~MPPE_OPT_40; + ccp_wantoptions[f->unit].mppe &= ~MPPE_OPT_40; + } + } + + /* Last check: can we actually negotiate something? */ + if (!(go->mppe & (MPPE_OPT_40 | MPPE_OPT_128))) { + /* Could be misconfig, could be 40-bit disabled above. */ + error("MPPE required, but both 40-bit and 128-bit disabled."); + lcp_close(f->unit, "MPPE required but not available"); + return; + } + + /* sync options */ + ao->mppe = go->mppe; + /* MPPE is not compatible with other compression types */ + ao->bsd_compress = go->bsd_compress = 0; + ao->predictor_1 = go->predictor_1 = 0; + ao->predictor_2 = go->predictor_2 = 0; + ao->deflate = go->deflate = 0; + } +#endif /* MPPE */ + + /* + * Check whether the kernel knows about the various + * compression methods we might request. + */ +#ifdef MPPE + if (go->mppe) { + opt_buf[0] = CI_MPPE; + opt_buf[1] = CILEN_MPPE; + MPPE_OPTS_TO_CI(go->mppe, &opt_buf[2]); + /* Key material unimportant here. */ + if (ccp_test(f->unit, opt_buf, CILEN_MPPE + MPPE_MAX_KEY_LEN, 0) <= 0) { + error("MPPE required, but kernel has no support."); + lcp_close(f->unit, "MPPE required but not available"); + } + } +#endif + if (go->bsd_compress) { + opt_buf[0] = CI_BSD_COMPRESS; + opt_buf[1] = CILEN_BSD_COMPRESS; + opt_buf[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, BSD_MIN_BITS); + if (ccp_test(f->unit, opt_buf, CILEN_BSD_COMPRESS, 0) <= 0) + go->bsd_compress = 0; + } + if (go->deflate) { + if (go->deflate_correct) { + opt_buf[0] = CI_DEFLATE; + opt_buf[1] = CILEN_DEFLATE; + opt_buf[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_WORKS); + opt_buf[3] = DEFLATE_CHK_SEQUENCE; + if (ccp_test(f->unit, opt_buf, CILEN_DEFLATE, 0) <= 0) + go->deflate_correct = 0; + } + if (go->deflate_draft) { + opt_buf[0] = CI_DEFLATE_DRAFT; + opt_buf[1] = CILEN_DEFLATE; + opt_buf[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_WORKS); + opt_buf[3] = DEFLATE_CHK_SEQUENCE; + if (ccp_test(f->unit, opt_buf, CILEN_DEFLATE, 0) <= 0) + go->deflate_draft = 0; + } + if (!go->deflate_correct && !go->deflate_draft) + go->deflate = 0; + } + if (go->predictor_1) { + opt_buf[0] = CI_PREDICTOR_1; + opt_buf[1] = CILEN_PREDICTOR_1; + if (ccp_test(f->unit, opt_buf, CILEN_PREDICTOR_1, 0) <= 0) + go->predictor_1 = 0; + } + if (go->predictor_2) { + opt_buf[0] = CI_PREDICTOR_2; + opt_buf[1] = CILEN_PREDICTOR_2; + if (ccp_test(f->unit, opt_buf, CILEN_PREDICTOR_2, 0) <= 0) + go->predictor_2 = 0; + } +} + +/* + * ccp_cilen - Return total length of our configuration info. + */ +static int +ccp_cilen(f) + fsm *f; +{ + ccp_options *go = &ccp_gotoptions[f->unit]; + + return (go->bsd_compress? CILEN_BSD_COMPRESS: 0) + + (go->deflate? CILEN_DEFLATE: 0) + + (go->predictor_1? CILEN_PREDICTOR_1: 0) + + (go->predictor_2? CILEN_PREDICTOR_2: 0) + + (go->mppe? CILEN_MPPE: 0); +} + +/* + * ccp_addci - put our requests in a packet. + */ +static void +ccp_addci(f, p, lenp) + fsm *f; + u_char *p; + int *lenp; +{ + int res; + ccp_options *go = &ccp_gotoptions[f->unit]; + u_char *p0 = p; + + /* + * Add the compression types that we can receive, in decreasing + * preference order. Get the kernel to allocate the first one + * in case it gets Acked. + */ +#ifdef MPPE + if (go->mppe) { + u_char opt_buf[CILEN_MPPE + MPPE_MAX_KEY_LEN]; + + p[0] = opt_buf[0] = CI_MPPE; + p[1] = opt_buf[1] = CILEN_MPPE; + MPPE_OPTS_TO_CI(go->mppe, &p[2]); + MPPE_OPTS_TO_CI(go->mppe, &opt_buf[2]); + MEMCPY(&opt_buf[CILEN_MPPE], mppe_recv_key, MPPE_MAX_KEY_LEN); + res = ccp_test(f->unit, opt_buf, CILEN_MPPE + MPPE_MAX_KEY_LEN, 0); + if (res > 0) + p += CILEN_MPPE; + else + /* This shouldn't happen, we've already tested it! */ + lcp_close(f->unit, "MPPE required but not available in kernel"); + } +#endif + if (go->deflate) { + p[0] = go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT; + p[1] = CILEN_DEFLATE; + p[2] = DEFLATE_MAKE_OPT(go->deflate_size); + p[3] = DEFLATE_CHK_SEQUENCE; + if (p != p0) { + p += CILEN_DEFLATE; + } else { + for (;;) { + if (go->deflate_size < DEFLATE_MIN_WORKS) { + go->deflate = 0; + break; + } + res = ccp_test(f->unit, p, CILEN_DEFLATE, 0); + if (res > 0) { + p += CILEN_DEFLATE; + break; + } else if (res < 0) { + go->deflate = 0; + break; + } + --go->deflate_size; + p[2] = DEFLATE_MAKE_OPT(go->deflate_size); + } + } + if (p != p0 && go->deflate_correct && go->deflate_draft) { + p[0] = CI_DEFLATE_DRAFT; + p[1] = CILEN_DEFLATE; + p[2] = p[2 - CILEN_DEFLATE]; + p[3] = DEFLATE_CHK_SEQUENCE; + p += CILEN_DEFLATE; + } + } + if (go->bsd_compress) { + p[0] = CI_BSD_COMPRESS; + p[1] = CILEN_BSD_COMPRESS; + p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits); + if (p != p0) { + p += CILEN_BSD_COMPRESS; /* not the first option */ + } else { + for (;;) { + if (go->bsd_bits < BSD_MIN_BITS) { + go->bsd_compress = 0; + break; + } + res = ccp_test(f->unit, p, CILEN_BSD_COMPRESS, 0); + if (res > 0) { + p += CILEN_BSD_COMPRESS; + break; + } else if (res < 0) { + go->bsd_compress = 0; + break; + } + --go->bsd_bits; + p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits); + } + } + } + /* XXX Should Predictor 2 be preferable to Predictor 1? */ + if (go->predictor_1) { + p[0] = CI_PREDICTOR_1; + p[1] = CILEN_PREDICTOR_1; + if (p == p0 && ccp_test(f->unit, p, CILEN_PREDICTOR_1, 0) <= 0) { + go->predictor_1 = 0; + } else { + p += CILEN_PREDICTOR_1; + } + } + if (go->predictor_2) { + p[0] = CI_PREDICTOR_2; + p[1] = CILEN_PREDICTOR_2; + if (p == p0 && ccp_test(f->unit, p, CILEN_PREDICTOR_2, 0) <= 0) { + go->predictor_2 = 0; + } else { + p += CILEN_PREDICTOR_2; + } + } + + go->method = (p > p0)? p0[0]: -1; + + *lenp = p - p0; +} + +/* + * ccp_ackci - process a received configure-ack, and return + * 1 iff the packet was OK. + */ +static int +ccp_ackci(f, p, len) + fsm *f; + u_char *p; + int len; +{ + ccp_options *go = &ccp_gotoptions[f->unit]; + u_char *p0 = p; + +#ifdef MPPE + if (go->mppe) { + u_char opt_buf[CILEN_MPPE]; + + opt_buf[0] = CI_MPPE; + opt_buf[1] = CILEN_MPPE; + MPPE_OPTS_TO_CI(go->mppe, &opt_buf[2]); + if (len < CILEN_MPPE || memcmp(opt_buf, p, CILEN_MPPE)) + return 0; + p += CILEN_MPPE; + len -= CILEN_MPPE; + /* XXX Cope with first/fast ack */ + if (len == 0) + return 1; + } +#endif + if (go->deflate) { + if (len < CILEN_DEFLATE + || p[0] != (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT) + || p[1] != CILEN_DEFLATE + || p[2] != DEFLATE_MAKE_OPT(go->deflate_size) + || p[3] != DEFLATE_CHK_SEQUENCE) + return 0; + p += CILEN_DEFLATE; + len -= CILEN_DEFLATE; + /* XXX Cope with first/fast ack */ + if (len == 0) + return 1; + if (go->deflate_correct && go->deflate_draft) { + if (len < CILEN_DEFLATE + || p[0] != CI_DEFLATE_DRAFT + || p[1] != CILEN_DEFLATE + || p[2] != DEFLATE_MAKE_OPT(go->deflate_size) + || p[3] != DEFLATE_CHK_SEQUENCE) + return 0; + p += CILEN_DEFLATE; + len -= CILEN_DEFLATE; + } + } + if (go->bsd_compress) { + if (len < CILEN_BSD_COMPRESS + || p[0] != CI_BSD_COMPRESS || p[1] != CILEN_BSD_COMPRESS + || p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits)) + return 0; + p += CILEN_BSD_COMPRESS; + len -= CILEN_BSD_COMPRESS; + /* XXX Cope with first/fast ack */ + if (p == p0 && len == 0) + return 1; + } + if (go->predictor_1) { + if (len < CILEN_PREDICTOR_1 + || p[0] != CI_PREDICTOR_1 || p[1] != CILEN_PREDICTOR_1) + return 0; + p += CILEN_PREDICTOR_1; + len -= CILEN_PREDICTOR_1; + /* XXX Cope with first/fast ack */ + if (p == p0 && len == 0) + return 1; + } + if (go->predictor_2) { + if (len < CILEN_PREDICTOR_2 + || p[0] != CI_PREDICTOR_2 || p[1] != CILEN_PREDICTOR_2) + return 0; + p += CILEN_PREDICTOR_2; + len -= CILEN_PREDICTOR_2; + /* XXX Cope with first/fast ack */ + if (p == p0 && len == 0) + return 1; + } + + if (len != 0) + return 0; + return 1; +} + +/* + * ccp_nakci - process received configure-nak. + * Returns 1 iff the nak was OK. + */ +static int +ccp_nakci(f, p, len, treat_as_reject) + fsm *f; + u_char *p; + int len; + int treat_as_reject; +{ + ccp_options *go = &ccp_gotoptions[f->unit]; + ccp_options no; /* options we've seen already */ + ccp_options try; /* options to ask for next time */ + + memset(&no, 0, sizeof(no)); + try = *go; + +#ifdef MPPE + if (go->mppe && len >= CILEN_MPPE + && p[0] == CI_MPPE && p[1] == CILEN_MPPE) { + no.mppe = 1; + /* + * Peer wants us to use a different strength or other setting. + * Fail if we aren't willing to use his suggestion. + */ + MPPE_CI_TO_OPTS(&p[2], try.mppe); + if ((try.mppe & MPPE_OPT_STATEFUL) && refuse_mppe_stateful) { + error("Refusing MPPE stateful mode offered by peer"); + try.mppe = 0; + } else if (((go->mppe | MPPE_OPT_STATEFUL) & try.mppe) != try.mppe) { + /* Peer must have set options we didn't request (suggest) */ + try.mppe = 0; + } + + if (!try.mppe) { + error("MPPE required but peer negotiation failed"); + lcp_close(f->unit, "MPPE required but peer negotiation failed"); + } + } +#endif /* MPPE */ + if (go->deflate && len >= CILEN_DEFLATE + && p[0] == (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT) + && p[1] == CILEN_DEFLATE) { + no.deflate = 1; + /* + * Peer wants us to use a different code size or something. + * Stop asking for Deflate if we don't understand his suggestion. + */ + if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL + || DEFLATE_SIZE(p[2]) < DEFLATE_MIN_WORKS + || p[3] != DEFLATE_CHK_SEQUENCE) + try.deflate = 0; + else if (DEFLATE_SIZE(p[2]) < go->deflate_size) + try.deflate_size = DEFLATE_SIZE(p[2]); + p += CILEN_DEFLATE; + len -= CILEN_DEFLATE; + if (go->deflate_correct && go->deflate_draft + && len >= CILEN_DEFLATE && p[0] == CI_DEFLATE_DRAFT + && p[1] == CILEN_DEFLATE) { + p += CILEN_DEFLATE; + len -= CILEN_DEFLATE; + } + } + + if (go->bsd_compress && len >= CILEN_BSD_COMPRESS + && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) { + no.bsd_compress = 1; + /* + * Peer wants us to use a different number of bits + * or a different version. + */ + if (BSD_VERSION(p[2]) != BSD_CURRENT_VERSION) + try.bsd_compress = 0; + else if (BSD_NBITS(p[2]) < go->bsd_bits) + try.bsd_bits = BSD_NBITS(p[2]); + p += CILEN_BSD_COMPRESS; + len -= CILEN_BSD_COMPRESS; + } + + /* + * Predictor-1 and 2 have no options, so they can't be Naked. + * + * There may be remaining options but we ignore them. + */ + + if (f->state != OPENED) + *go = try; + return 1; +} + +/* + * ccp_rejci - reject some of our suggested compression methods. + */ +static int +ccp_rejci(f, p, len) + fsm *f; + u_char *p; + int len; +{ + ccp_options *go = &ccp_gotoptions[f->unit]; + ccp_options try; /* options to request next time */ + + try = *go; + + /* + * Cope with empty configure-rejects by ceasing to send + * configure-requests. + */ + if (len == 0 && all_rejected[f->unit]) + return -1; + +#ifdef MPPE + if (go->mppe && len >= CILEN_MPPE + && p[0] == CI_MPPE && p[1] == CILEN_MPPE) { + error("MPPE required but peer refused"); + lcp_close(f->unit, "MPPE required but peer refused"); + p += CILEN_MPPE; + len -= CILEN_MPPE; + } +#endif + if (go->deflate_correct && len >= CILEN_DEFLATE + && p[0] == CI_DEFLATE && p[1] == CILEN_DEFLATE) { + if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size) + || p[3] != DEFLATE_CHK_SEQUENCE) + return 0; /* Rej is bad */ + try.deflate_correct = 0; + p += CILEN_DEFLATE; + len -= CILEN_DEFLATE; + } + if (go->deflate_draft && len >= CILEN_DEFLATE + && p[0] == CI_DEFLATE_DRAFT && p[1] == CILEN_DEFLATE) { + if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size) + || p[3] != DEFLATE_CHK_SEQUENCE) + return 0; /* Rej is bad */ + try.deflate_draft = 0; + p += CILEN_DEFLATE; + len -= CILEN_DEFLATE; + } + if (!try.deflate_correct && !try.deflate_draft) + try.deflate = 0; + if (go->bsd_compress && len >= CILEN_BSD_COMPRESS + && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) { + if (p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits)) + return 0; + try.bsd_compress = 0; + p += CILEN_BSD_COMPRESS; + len -= CILEN_BSD_COMPRESS; + } + if (go->predictor_1 && len >= CILEN_PREDICTOR_1 + && p[0] == CI_PREDICTOR_1 && p[1] == CILEN_PREDICTOR_1) { + try.predictor_1 = 0; + p += CILEN_PREDICTOR_1; + len -= CILEN_PREDICTOR_1; + } + if (go->predictor_2 && len >= CILEN_PREDICTOR_2 + && p[0] == CI_PREDICTOR_2 && p[1] == CILEN_PREDICTOR_2) { + try.predictor_2 = 0; + p += CILEN_PREDICTOR_2; + len -= CILEN_PREDICTOR_2; + } + + if (len != 0) + return 0; + + if (f->state != OPENED) + *go = try; + + return 1; +} + +/* + * ccp_reqci - processed a received configure-request. + * Returns CONFACK, CONFNAK or CONFREJ and the packet modified + * appropriately. + */ +static int +ccp_reqci(f, p, lenp, dont_nak) + fsm *f; + u_char *p; + int *lenp; + int dont_nak; +{ + ppp_pcb *pcb = &ppp_pcb_list[f->unit]; + int ret, newret, res; + u_char *p0, *retp; + int len, clen, type, nb; + ccp_options *ho = &ccp_hisoptions[f->unit]; + ccp_options *ao = &ccp_allowoptions[f->unit]; +#ifdef MPPE + bool rej_for_ci_mppe = 1; /* Are we rejecting based on a bad/missing */ + /* CI_MPPE, or due to other options? */ +#endif + + ret = CONFACK; + retp = p0 = p; + len = *lenp; + + memset(ho, 0, sizeof(ccp_options)); + ho->method = (len > 0)? p[0]: -1; + + while (len > 0) { + newret = CONFACK; + if (len < 2 || p[1] < 2 || p[1] > len) { + /* length is bad */ + clen = len; + newret = CONFREJ; + + } else { + type = p[0]; + clen = p[1]; + + switch (type) { +#ifdef MPPE + case CI_MPPE: + if (!ao->mppe || clen != CILEN_MPPE) { + newret = CONFREJ; + break; + } + MPPE_CI_TO_OPTS(&p[2], ho->mppe); + + /* Nak if anything unsupported or unknown are set. */ + if (ho->mppe & MPPE_OPT_UNSUPPORTED) { + newret = CONFNAK; + ho->mppe &= ~MPPE_OPT_UNSUPPORTED; + } + if (ho->mppe & MPPE_OPT_UNKNOWN) { + newret = CONFNAK; + ho->mppe &= ~MPPE_OPT_UNKNOWN; + } + + /* Check state opt */ + if (ho->mppe & MPPE_OPT_STATEFUL) { + /* + * We can Nak and request stateless, but it's a + * lot easier to just assume the peer will request + * it if he can do it; stateful mode is bad over + * the Internet -- which is where we expect MPPE. + */ + if (refuse_mppe_stateful) { + error("Refusing MPPE stateful mode offered by peer"); + newret = CONFREJ; + break; + } + } + + /* Find out which of {S,L} are set. */ + if ((ho->mppe & MPPE_OPT_128) + && (ho->mppe & MPPE_OPT_40)) { + /* Both are set, negotiate the strongest. */ + newret = CONFNAK; + if (ao->mppe & MPPE_OPT_128) + ho->mppe &= ~MPPE_OPT_40; + else if (ao->mppe & MPPE_OPT_40) + ho->mppe &= ~MPPE_OPT_128; + else { + newret = CONFREJ; + break; + } + } else if (ho->mppe & MPPE_OPT_128) { + if (!(ao->mppe & MPPE_OPT_128)) { + newret = CONFREJ; + break; + } + } else if (ho->mppe & MPPE_OPT_40) { + if (!(ao->mppe & MPPE_OPT_40)) { + newret = CONFREJ; + break; + } + } else { + /* Neither are set. */ + /* We cannot accept this. */ + newret = CONFNAK; + /* Give the peer our idea of what can be used, + so it can choose and confirm */ + ho->mppe = ao->mppe; + } + + /* rebuild the opts */ + MPPE_OPTS_TO_CI(ho->mppe, &p[2]); + if (newret == CONFACK) { + u_char opt_buf[CILEN_MPPE + MPPE_MAX_KEY_LEN]; + int mtu; + + MEMCPY(opt_buf, p, CILEN_MPPE); + MEMCPY(&opt_buf[CILEN_MPPE], mppe_send_key, + MPPE_MAX_KEY_LEN); + if (ccp_test(f->unit, opt_buf, + CILEN_MPPE + MPPE_MAX_KEY_LEN, 1) <= 0) { + /* This shouldn't happen, we've already tested it! */ + error("MPPE required, but kernel has no support."); + lcp_close(f->unit, "MPPE required but not available"); + newret = CONFREJ; + break; + } + /* + * We need to decrease the interface MTU by MPPE_PAD + * because MPPE frames **grow**. The kernel [must] + * allocate MPPE_PAD extra bytes in xmit buffers. + */ + mtu = netif_get_mtu(pcb); + if (mtu) + netif_set_mtu(pcb, mtu - MPPE_PAD); + else + newret = CONFREJ; + } + + /* + * We have accepted MPPE or are willing to negotiate + * MPPE parameters. A CONFREJ is due to subsequent + * (non-MPPE) processing. + */ + rej_for_ci_mppe = 0; + break; +#endif /* MPPE */ + case CI_DEFLATE: + case CI_DEFLATE_DRAFT: + if (!ao->deflate || clen != CILEN_DEFLATE + || (!ao->deflate_correct && type == CI_DEFLATE) + || (!ao->deflate_draft && type == CI_DEFLATE_DRAFT)) { + newret = CONFREJ; + break; + } + + ho->deflate = 1; + ho->deflate_size = nb = DEFLATE_SIZE(p[2]); + if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL + || p[3] != DEFLATE_CHK_SEQUENCE + || nb > ao->deflate_size || nb < DEFLATE_MIN_WORKS) { + newret = CONFNAK; + if (!dont_nak) { + p[2] = DEFLATE_MAKE_OPT(ao->deflate_size); + p[3] = DEFLATE_CHK_SEQUENCE; + /* fall through to test this #bits below */ + } else + break; + } + + /* + * Check whether we can do Deflate with the window + * size they want. If the window is too big, reduce + * it until the kernel can cope and nak with that. + * We only check this for the first option. + */ + if (p == p0) { + for (;;) { + res = ccp_test(f->unit, p, CILEN_DEFLATE, 1); + if (res > 0) + break; /* it's OK now */ + if (res < 0 || nb == DEFLATE_MIN_WORKS || dont_nak) { + newret = CONFREJ; + p[2] = DEFLATE_MAKE_OPT(ho->deflate_size); + break; + } + newret = CONFNAK; + --nb; + p[2] = DEFLATE_MAKE_OPT(nb); + } + } + break; + + case CI_BSD_COMPRESS: + if (!ao->bsd_compress || clen != CILEN_BSD_COMPRESS) { + newret = CONFREJ; + break; + } + + ho->bsd_compress = 1; + ho->bsd_bits = nb = BSD_NBITS(p[2]); + if (BSD_VERSION(p[2]) != BSD_CURRENT_VERSION + || nb > ao->bsd_bits || nb < BSD_MIN_BITS) { + newret = CONFNAK; + if (!dont_nak) { + p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, ao->bsd_bits); + /* fall through to test this #bits below */ + } else + break; + } + + /* + * Check whether we can do BSD-Compress with the code + * size they want. If the code size is too big, reduce + * it until the kernel can cope and nak with that. + * We only check this for the first option. + */ + if (p == p0) { + for (;;) { + res = ccp_test(f->unit, p, CILEN_BSD_COMPRESS, 1); + if (res > 0) + break; + if (res < 0 || nb == BSD_MIN_BITS || dont_nak) { + newret = CONFREJ; + p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, + ho->bsd_bits); + break; + } + newret = CONFNAK; + --nb; + p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, nb); + } + } + break; + + case CI_PREDICTOR_1: + if (!ao->predictor_1 || clen != CILEN_PREDICTOR_1) { + newret = CONFREJ; + break; + } + + ho->predictor_1 = 1; + if (p == p0 + && ccp_test(f->unit, p, CILEN_PREDICTOR_1, 1) <= 0) { + newret = CONFREJ; + } + break; + + case CI_PREDICTOR_2: + if (!ao->predictor_2 || clen != CILEN_PREDICTOR_2) { + newret = CONFREJ; + break; + } + + ho->predictor_2 = 1; + if (p == p0 + && ccp_test(f->unit, p, CILEN_PREDICTOR_2, 1) <= 0) { + newret = CONFREJ; + } + break; + + default: + newret = CONFREJ; + } + } + + if (newret == CONFNAK && dont_nak) + newret = CONFREJ; + if (!(newret == CONFACK || (newret == CONFNAK && ret == CONFREJ))) { + /* we're returning this option */ + if (newret == CONFREJ && ret == CONFNAK) + retp = p0; + ret = newret; + if (p != retp) + MEMCPY(retp, p, clen); + retp += clen; + } + + p += clen; + len -= clen; + } + + if (ret != CONFACK) { + if (ret == CONFREJ && *lenp == retp - p0) + all_rejected[f->unit] = 1; + else + *lenp = retp - p0; + } +#ifdef MPPE + if (ret == CONFREJ && ao->mppe && rej_for_ci_mppe) { + error("MPPE required but peer negotiation failed"); + lcp_close(f->unit, "MPPE required but peer negotiation failed"); + } +#endif + return ret; +} + +/* + * Make a string name for a compression method (or 2). + */ +static char * +method_name(opt, opt2) + ccp_options *opt, *opt2; +{ + static char result[64]; + + if (!ANY_COMPRESS(*opt)) + return "(none)"; + switch (opt->method) { +#ifdef MPPE + case CI_MPPE: + { + char *p = result; + char *q = result + sizeof(result); /* 1 past result */ + + slprintf(p, q - p, "MPPE "); + p += 5; + if (opt->mppe & MPPE_OPT_128) { + slprintf(p, q - p, "128-bit "); + p += 8; + } + if (opt->mppe & MPPE_OPT_40) { + slprintf(p, q - p, "40-bit "); + p += 7; + } + if (opt->mppe & MPPE_OPT_STATEFUL) + slprintf(p, q - p, "stateful"); + else + slprintf(p, q - p, "stateless"); + + break; + } +#endif + case CI_DEFLATE: + case CI_DEFLATE_DRAFT: + if (opt2 != NULL && opt2->deflate_size != opt->deflate_size) + slprintf(result, sizeof(result), "Deflate%s (%d/%d)", + (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""), + opt->deflate_size, opt2->deflate_size); + else + slprintf(result, sizeof(result), "Deflate%s (%d)", + (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""), + opt->deflate_size); + break; + case CI_BSD_COMPRESS: + if (opt2 != NULL && opt2->bsd_bits != opt->bsd_bits) + slprintf(result, sizeof(result), "BSD-Compress (%d/%d)", + opt->bsd_bits, opt2->bsd_bits); + else + slprintf(result, sizeof(result), "BSD-Compress (%d)", + opt->bsd_bits); + break; + case CI_PREDICTOR_1: + return "Predictor 1"; + case CI_PREDICTOR_2: + return "Predictor 2"; + default: + slprintf(result, sizeof(result), "Method %d", opt->method); + } + return result; +} + +/* + * CCP has come up - inform the kernel driver and log a message. + */ +static void +ccp_up(f) + fsm *f; +{ + ccp_options *go = &ccp_gotoptions[f->unit]; + ccp_options *ho = &ccp_hisoptions[f->unit]; + char method1[64]; + + ccp_flags_set(f->unit, 1, 1); + if (ANY_COMPRESS(*go)) { + if (ANY_COMPRESS(*ho)) { + if (go->method == ho->method) { + notice("%s compression enabled", method_name(go, ho)); + } else { + strlcpy(method1, method_name(go, NULL), sizeof(method1)); + notice("%s / %s compression enabled", + method1, method_name(ho, NULL)); + } + } else + notice("%s receive compression enabled", method_name(go, NULL)); + } else if (ANY_COMPRESS(*ho)) + notice("%s transmit compression enabled", method_name(ho, NULL)); +#ifdef MPPE + if (go->mppe) { + BZERO(mppe_recv_key, MPPE_MAX_KEY_LEN); + BZERO(mppe_send_key, MPPE_MAX_KEY_LEN); + continue_networks(f->unit); /* Bring up IP et al */ + } +#endif +} + +/* + * CCP has gone down - inform the kernel driver. + */ +static void +ccp_down(f) + fsm *f; +{ + if (ccp_localstate[f->unit] & RACK_PENDING) + UNTIMEOUT(ccp_rack_timeout, f); + ccp_localstate[f->unit] = 0; + ccp_flags_set(f->unit, 1, 0); +#ifdef MPPE + if (ccp_gotoptions[f->unit].mppe) { + ccp_gotoptions[f->unit].mppe = 0; + if (lcp_fsm[f->unit].state == OPENED) { + /* If LCP is not already going down, make sure it does. */ + error("MPPE disabled"); + lcp_close(f->unit, "MPPE disabled"); + } + } +#endif +} + +#if PRINTPKT_SUPPORT +/* + * Print the contents of a CCP packet. + */ +static char *ccp_codenames[] = { + "ConfReq", "ConfAck", "ConfNak", "ConfRej", + "TermReq", "TermAck", "CodeRej", + NULL, NULL, NULL, NULL, NULL, NULL, + "ResetReq", "ResetAck", +}; + +static int +ccp_printpkt(p, plen, printer, arg) + u_char *p; + int plen; + void (*printer) (void *, char *, ...); + void *arg; +{ + u_char *p0, *optend; + int code, id, len; + int optlen; + + p0 = p; + if (plen < HEADERLEN) + return 0; + code = p[0]; + id = p[1]; + len = (p[2] << 8) + p[3]; + if (len < HEADERLEN || len > plen) + return 0; + + if (code >= 1 && code <= sizeof(ccp_codenames) / sizeof(char *) + && ccp_codenames[code-1] != NULL) + printer(arg, " %s", ccp_codenames[code-1]); + else + printer(arg, " code=0x%x", code); + printer(arg, " id=0x%x", id); + len -= HEADERLEN; + p += HEADERLEN; + + switch (code) { + case CONFREQ: + case CONFACK: + case CONFNAK: + case CONFREJ: + /* print list of possible compression methods */ + while (len >= 2) { + code = p[0]; + optlen = p[1]; + if (optlen < 2 || optlen > len) + break; + printer(arg, " <"); + len -= optlen; + optend = p + optlen; + switch (code) { +#ifdef MPPE + case CI_MPPE: + if (optlen >= CILEN_MPPE) { + u_char mppe_opts; + + MPPE_CI_TO_OPTS(&p[2], mppe_opts); + printer(arg, "mppe %s %s %s %s %s %s%s", + (p[2] & MPPE_H_BIT)? "+H": "-H", + (p[5] & MPPE_M_BIT)? "+M": "-M", + (p[5] & MPPE_S_BIT)? "+S": "-S", + (p[5] & MPPE_L_BIT)? "+L": "-L", + (p[5] & MPPE_D_BIT)? "+D": "-D", + (p[5] & MPPE_C_BIT)? "+C": "-C", + (mppe_opts & MPPE_OPT_UNKNOWN)? " +U": ""); + if (mppe_opts & MPPE_OPT_UNKNOWN) + printer(arg, " (%.2x %.2x %.2x %.2x)", + p[2], p[3], p[4], p[5]); + p += CILEN_MPPE; + } + break; +#endif + case CI_DEFLATE: + case CI_DEFLATE_DRAFT: + if (optlen >= CILEN_DEFLATE) { + printer(arg, "deflate%s %d", + (code == CI_DEFLATE_DRAFT? "(old#)": ""), + DEFLATE_SIZE(p[2])); + if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL) + printer(arg, " method %d", DEFLATE_METHOD(p[2])); + if (p[3] != DEFLATE_CHK_SEQUENCE) + printer(arg, " check %d", p[3]); + p += CILEN_DEFLATE; + } + break; + case CI_BSD_COMPRESS: + if (optlen >= CILEN_BSD_COMPRESS) { + printer(arg, "bsd v%d %d", BSD_VERSION(p[2]), + BSD_NBITS(p[2])); + p += CILEN_BSD_COMPRESS; + } + break; + case CI_PREDICTOR_1: + if (optlen >= CILEN_PREDICTOR_1) { + printer(arg, "predictor 1"); + p += CILEN_PREDICTOR_1; + } + break; + case CI_PREDICTOR_2: + if (optlen >= CILEN_PREDICTOR_2) { + printer(arg, "predictor 2"); + p += CILEN_PREDICTOR_2; + } + break; + } + while (p < optend) + printer(arg, " %.2x", *p++); + printer(arg, ">"); + } + break; + + case TERMACK: + case TERMREQ: + if (len > 0 && *p >= ' ' && *p < 0x7f) { + print_string((char *)p, len, printer, arg); + p += len; + len = 0; + } + break; + } + + /* dump out the rest of the packet in hex */ + while (--len >= 0) + printer(arg, " %.2x", *p++); + + return p - p0; +} +#endif /* PRINTPKT_SUPPORT */ + +/* + * We have received a packet that the decompressor failed to + * decompress. Here we would expect to issue a reset-request, but + * Motorola has a patent on resetting the compressor as a result of + * detecting an error in the decompressed data after decompression. + * (See US patent 5,130,993; international patent publication number + * WO 91/10289; Australian patent 73296/91.) + * + * So we ask the kernel whether the error was detected after + * decompression; if it was, we take CCP down, thus disabling + * compression :-(, otherwise we issue the reset-request. + */ +static void +ccp_datainput(unit, pkt, len) + int unit; + u_char *pkt; + int len; +{ + fsm *f; + + f = &ccp_fsm[unit]; + if (f->state == OPENED) { + if (ccp_fatal_error(unit)) { + /* + * Disable compression by taking CCP down. + */ + error("Lost compression sync: disabling compression"); + ccp_close(unit, "Lost compression sync"); +#ifdef MPPE + /* + * If we were doing MPPE, we must also take the link down. + */ + if (ccp_gotoptions[unit].mppe) { + error("Too many MPPE errors, closing LCP"); + lcp_close(unit, "Too many MPPE errors"); + } +#endif + } else { + /* + * Send a reset-request to reset the peer's compressor. + * We don't do that if we are still waiting for an + * acknowledgement to a previous reset-request. + */ + if (!(ccp_localstate[f->unit] & RACK_PENDING)) { + fsm_sdata(f, CCP_RESETREQ, f->reqid = ++f->id, NULL, 0); + TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT); + ccp_localstate[f->unit] |= RACK_PENDING; + } else + ccp_localstate[f->unit] |= RREQ_REPEAT; + } + } +} + +/* + * Timeout waiting for reset-ack. + */ +static void +ccp_rack_timeout(arg) + void *arg; +{ + fsm *f = arg; + + if (f->state == OPENED && ccp_localstate[f->unit] & RREQ_REPEAT) { + fsm_sdata(f, CCP_RESETREQ, f->reqid, NULL, 0); + TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT); + ccp_localstate[f->unit] &= ~RREQ_REPEAT; + } else + ccp_localstate[f->unit] &= ~RACK_PENDING; +} + +#endif /* PPP_SUPPORT && CCP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/chap-md5.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/chap-md5.c new file mode 100644 index 0000000..70b879a --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/chap-md5.c @@ -0,0 +1,124 @@ +/* + * chap-md5.c - New CHAP/MD5 implementation. + * + * Copyright (c) 2003 Paul Mackerras. 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. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && CHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#if 0 /* UNUSED */ +#include +#include +#endif /* UNUSED */ + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/chap-new.h" +#include "netif/ppp/chap-md5.h" +#include "netif/ppp/magic.h" + +#if LWIP_INCLUDED_POLARSSL_MD5 +#include "netif/ppp/polarssl/md5.h" +#else +#include "polarssl/md5.h" +#endif + +#define MD5_HASH_SIZE 16 +#define MD5_MIN_CHALLENGE 16 +#define MD5_MAX_CHALLENGE 24 + +#if PPP_SERVER +static void chap_md5_generate_challenge(unsigned char *cp) { + int clen; + + clen = (int)(drand48() * (MD5_MAX_CHALLENGE - MD5_MIN_CHALLENGE)) + + MD5_MIN_CHALLENGE; + *cp++ = clen; + random_bytes(cp, clen); +} + +static int chap_md5_verify_response(int id, const char *name, + const unsigned char *secret, int secret_len, + const unsigned char *challenge, const unsigned char *response, + char *message, int message_space) { + md5_context ctx; + unsigned char idbyte = id; + unsigned char hash[MD5_HASH_SIZE]; + int challenge_len, response_len; + LWIP_UNUSED_ARG(name); + + challenge_len = *challenge++; + response_len = *response++; + if (response_len == MD5_HASH_SIZE) { + /* Generate hash of ID, secret, challenge */ + md5_starts(&ctx); + md5_update(&ctx, &idbyte, 1); + md5_update(&ctx, (unsigned char*)secret, secret_len); + md5_update(&ctx, (unsigned char*)challenge, challenge_len); + md5_finish(&ctx, hash); + + /* Test if our hash matches the peer's response */ + if (memcmp(hash, response, MD5_HASH_SIZE) == 0) { + ppp_slprintf(message, message_space, "Access granted"); + return 1; + } + } + ppp_slprintf(message, message_space, "Access denied"); + return 0; +} +#endif /* PPP_SERVER */ + +static void chap_md5_make_response(unsigned char *response, int id, const char *our_name, + const unsigned char *challenge, const char *secret, int secret_len, + const unsigned char *private_) { + md5_context ctx; + unsigned char idbyte = id; + int challenge_len = *challenge++; + LWIP_UNUSED_ARG(our_name); + LWIP_UNUSED_ARG(private_); + + md5_starts(&ctx); + md5_update(&ctx, &idbyte, 1); + md5_update(&ctx, (u_char *)secret, secret_len); + md5_update(&ctx, (unsigned char *)challenge, challenge_len); + md5_finish(&ctx, &response[1]); + response[0] = MD5_HASH_SIZE; +} + +const struct chap_digest_type md5_digest = { + CHAP_MD5, /* code */ +#if PPP_SERVER + chap_md5_generate_challenge, + chap_md5_verify_response, +#endif /* PPP_SERVER */ + chap_md5_make_response, + NULL, /* check_success */ + NULL, /* handle_failure */ +}; + +#endif /* PPP_SUPPORT && CHAP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/chap-new.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/chap-new.c new file mode 100644 index 0000000..8432dac --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/chap-new.c @@ -0,0 +1,670 @@ +/* + * chap-new.c - New CHAP implementation. + * + * Copyright (c) 2003 Paul Mackerras. 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. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && CHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#if 0 /* UNUSED */ +#include +#include +#endif /* UNUSED */ + +#include "netif/ppp/ppp_impl.h" + +#if 0 /* UNUSED */ +#include "session.h" +#endif /* UNUSED */ + +#include "netif/ppp/chap-new.h" +#include "netif/ppp/chap-md5.h" +#if MSCHAP_SUPPORT +#include "netif/ppp/chap_ms.h" +#endif + +/* Hook for a plugin to validate CHAP challenge */ +int (*chap_verify_hook)(const char *name, const char *ourname, int id, + const struct chap_digest_type *digest, + const unsigned char *challenge, const unsigned char *response, + char *message, int message_space) = NULL; + +#if PPP_OPTIONS +/* + * Command-line options. + */ +static option_t chap_option_list[] = { + { "chap-restart", o_int, &chap_timeout_time, + "Set timeout for CHAP", OPT_PRIO }, + { "chap-max-challenge", o_int, &pcb->settings.chap_max_transmits, + "Set max #xmits for challenge", OPT_PRIO }, + { "chap-interval", o_int, &pcb->settings.chap_rechallenge_time, + "Set interval for rechallenge", OPT_PRIO }, + { NULL } +}; +#endif /* PPP_OPTIONS */ + + +/* Values for flags in chap_client_state and chap_server_state */ +#define LOWERUP 1 +#define AUTH_STARTED 2 +#define AUTH_DONE 4 +#define AUTH_FAILED 8 +#define TIMEOUT_PENDING 0x10 +#define CHALLENGE_VALID 0x20 + +/* + * Prototypes. + */ +static void chap_init(ppp_pcb *pcb); +static void chap_lowerup(ppp_pcb *pcb); +static void chap_lowerdown(ppp_pcb *pcb); +#if PPP_SERVER +static void chap_timeout(void *arg); +static void chap_generate_challenge(ppp_pcb *pcb); +static void chap_handle_response(ppp_pcb *pcb, int code, + unsigned char *pkt, int len); +static int chap_verify_response(const char *name, const char *ourname, int id, + const struct chap_digest_type *digest, + const unsigned char *challenge, const unsigned char *response, + char *message, int message_space); +#endif /* PPP_SERVER */ +static void chap_respond(ppp_pcb *pcb, int id, + unsigned char *pkt, int len); +static void chap_handle_status(ppp_pcb *pcb, int code, int id, + unsigned char *pkt, int len); +static void chap_protrej(ppp_pcb *pcb); +static void chap_input(ppp_pcb *pcb, unsigned char *pkt, int pktlen); +#if PRINTPKT_SUPPORT +static int chap_print_pkt(unsigned char *p, int plen, + void (*printer) (void *, const char *, ...), void *arg); +#endif /* PRINTPKT_SUPPORT */ + +/* List of digest types that we know about */ +static const struct chap_digest_type* const chap_digests[] = { + &md5_digest, +#if MSCHAP_SUPPORT + &chapms_digest, + &chapms2_digest, +#endif /* MSCHAP_SUPPORT */ + NULL +}; + +/* + * chap_init - reset to initial state. + */ +static void chap_init(ppp_pcb *pcb) { + + memset(&pcb->chap_client, 0, sizeof(chap_client_state)); +#if PPP_SERVER + memset(&pcb->chap_server, 0, sizeof(chap_server_state)); +#endif /* PPP_SERVER */ +} + +/* + * chap_lowerup - we can start doing stuff now. + */ +static void chap_lowerup(ppp_pcb *pcb) { + + pcb->chap_client.flags |= LOWERUP; +#if PPP_SERVER + pcb->chap_server.flags |= LOWERUP; + if (pcb->chap_server.flags & AUTH_STARTED) + chap_timeout(pcb); +#endif /* PPP_SERVER */ +} + +static void chap_lowerdown(ppp_pcb *pcb) { + + pcb->chap_client.flags = 0; +#if PPP_SERVER + if (pcb->chap_server.flags & TIMEOUT_PENDING) + UNTIMEOUT(chap_timeout, pcb); + pcb->chap_server.flags = 0; +#endif /* PPP_SERVER */ +} + +#if PPP_SERVER +/* + * chap_auth_peer - Start authenticating the peer. + * If the lower layer is already up, we start sending challenges, + * otherwise we wait for the lower layer to come up. + */ +void chap_auth_peer(ppp_pcb *pcb, const char *our_name, int digest_code) { + struct chap_server_state *ss = &pcb->chap_server; + const struct chap_digest_type *dp; + int i; + + if (pcb->chap_server.flags & AUTH_STARTED) { + ppp_error("CHAP: peer authentication already started!"); + return; + } + for (i = 0; (dp = chap_digests[i]) != NULL; ++i) + if (dp->code == digest_code) + break; + if (dp == NULL) + ppp_fatal("CHAP digest 0x%x requested but not available", + digest_code); + + pcb->chap_server.digest = dp; + pcb->chap_server.name = our_name; + /* Start with a random ID value */ + pcb->chap_server.id = (unsigned char)(drand48() * 256); + pcb->chap_server.flags |= AUTH_STARTED; + if (pcb->chap_server.flags & LOWERUP) + chap_timeout(ss); +} +#endif /* PPP_SERVER */ + +/* + * chap_auth_with_peer - Prepare to authenticate ourselves to the peer. + * There isn't much to do until we receive a challenge. + */ +void chap_auth_with_peer(ppp_pcb *pcb, const char *our_name, int digest_code) { + const struct chap_digest_type *dp; + int i; + + if(NULL == our_name) + return; + + if (pcb->chap_client.flags & AUTH_STARTED) { + ppp_error("CHAP: authentication with peer already started!"); + return; + } + for (i = 0; (dp = chap_digests[i]) != NULL; ++i) + if (dp->code == digest_code) + break; + + if (dp == NULL) + ppp_fatal("CHAP digest 0x%x requested but not available", + digest_code); + + pcb->chap_client.digest = dp; + pcb->chap_client.name = our_name; + pcb->chap_client.flags |= AUTH_STARTED; +} + +#if PPP_SERVER +/* + * chap_timeout - It's time to send another challenge to the peer. + * This could be either a retransmission of a previous challenge, + * or a new challenge to start re-authentication. + */ +static void chap_timeout(void *arg) { + ppp_pcb *pcb = (ppp_pcb*)arg; + struct pbuf *p; + + pcb->chap_server.flags &= ~TIMEOUT_PENDING; + if ((pcb->chap_server.flags & CHALLENGE_VALID) == 0) { + pcb->chap_server.challenge_xmits = 0; + chap_generate_challenge(pcb); + pcb->chap_server.flags |= CHALLENGE_VALID; + } else if (pcb->chap_server.challenge_xmits >= pcb->settings.chap_max_transmits) { + pcb->chap_server.flags &= ~CHALLENGE_VALID; + pcb->chap_server.flags |= AUTH_DONE | AUTH_FAILED; + auth_peer_fail(pcb, PPP_CHAP); + return; + } + + p = pbuf_alloc(PBUF_RAW, (u16_t)(pcb->chap_server.challenge_pktlen), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + MEMCPY(p->payload, pcb->chap_server.challenge, pcb->chap_server.challenge_pktlen); + ppp_write(pcb, p); + ++pcb->chap_server.challenge_xmits; + pcb->chap_server.flags |= TIMEOUT_PENDING; + TIMEOUT(chap_timeout, arg, pcb->settings.chap_timeout_time); +} + +/* + * chap_generate_challenge - generate a challenge string and format + * the challenge packet in pcb->chap_server.challenge_pkt. + */ +static void chap_generate_challenge(ppp_pcb *pcb) { + int clen = 1, nlen, len; + unsigned char *p; + + p = pcb->chap_server.challenge; + MAKEHEADER(p, PPP_CHAP); + p += CHAP_HDRLEN; + pcb->chap_server.digest->generate_challenge(p); + clen = *p; + nlen = strlen(pcb->chap_server.name); + memcpy(p + 1 + clen, pcb->chap_server.name, nlen); + + len = CHAP_HDRLEN + 1 + clen + nlen; + pcb->chap_server.challenge_pktlen = PPP_HDRLEN + len; + + p = pcb->chap_server.challenge + PPP_HDRLEN; + p[0] = CHAP_CHALLENGE; + p[1] = ++pcb->chap_server.id; + p[2] = len >> 8; + p[3] = len; +} + +/* + * chap_handle_response - check the response to our challenge. + */ +static void chap_handle_response(ppp_pcb *pcb, int id, + unsigned char *pkt, int len) { + int response_len, ok, mlen; + const unsigned char *response; + unsigned char *outp; + struct pbuf *p; + const char *name = NULL; /* initialized to shut gcc up */ + int (*verifier)(const char *, const char *, int, const struct chap_digest_type *, + const unsigned char *, const unsigned char *, char *, int); + char rname[MAXNAMELEN+1]; + + if ((pcb->chap_server.flags & LOWERUP) == 0) + return; + if (id != pcb->chap_server.challenge[PPP_HDRLEN+1] || len < 2) + return; + if (pcb->chap_server.flags & CHALLENGE_VALID) { + response = pkt; + GETCHAR(response_len, pkt); + len -= response_len + 1; /* length of name */ + name = (char *)pkt + response_len; + if (len < 0) + return; + + if (pcb->chap_server.flags & TIMEOUT_PENDING) { + pcb->chap_server.flags &= ~TIMEOUT_PENDING; + UNTIMEOUT(chap_timeout, pcb); + } +#if PPP_REMOTENAME + if (pcb->settings.explicit_remote) { + name = pcb->remote_name; + } else +#endif /* PPP_REMOTENAME */ + { + /* Null terminate and clean remote name. */ + ppp_slprintf(rname, sizeof(rname), "%.*v", len, name); + name = rname; + } + + if (chap_verify_hook) + verifier = chap_verify_hook; + else + verifier = chap_verify_response; + ok = (*verifier)(name, pcb->chap_server.name, id, pcb->chap_server.digest, + pcb->chap_server.challenge + PPP_HDRLEN + CHAP_HDRLEN, + response, pcb->chap_server.message, sizeof(pcb->chap_server.message)); +#if 0 /* UNUSED */ + if (!ok || !auth_number()) { +#endif /* UNUSED */ + if (!ok) { + pcb->chap_server.flags |= AUTH_FAILED; + ppp_warn("Peer %q failed CHAP authentication", name); + } + } else if ((pcb->chap_server.flags & AUTH_DONE) == 0) + return; + + /* send the response */ + mlen = strlen(pcb->chap_server.message); + len = CHAP_HDRLEN + mlen; + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +len), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = (unsigned char *)p->payload; + MAKEHEADER(outp, PPP_CHAP); + + outp[0] = (pcb->chap_server.flags & AUTH_FAILED)? CHAP_FAILURE: CHAP_SUCCESS; + outp[1] = id; + outp[2] = len >> 8; + outp[3] = len; + if (mlen > 0) + memcpy(outp + CHAP_HDRLEN, pcb->chap_server.message, mlen); + ppp_write(pcb, p); + + if (pcb->chap_server.flags & CHALLENGE_VALID) { + pcb->chap_server.flags &= ~CHALLENGE_VALID; + if (!(pcb->chap_server.flags & AUTH_DONE) && !(pcb->chap_server.flags & AUTH_FAILED)) { + +#if 0 /* UNUSED */ + /* + * Auth is OK, so now we need to check session restrictions + * to ensure everything is OK, but only if we used a + * plugin, and only if we're configured to check. This + * allows us to do PAM checks on PPP servers that + * authenticate against ActiveDirectory, and use AD for + * account info (like when using Winbind integrated with + * PAM). + */ + if (session_mgmt && + session_check(name, NULL, devnam, NULL) == 0) { + pcb->chap_server.flags |= AUTH_FAILED; + ppp_warn("Peer %q failed CHAP Session verification", name); + } +#endif /* UNUSED */ + + } + if (pcb->chap_server.flags & AUTH_FAILED) { + auth_peer_fail(pcb, PPP_CHAP); + } else { + if ((pcb->chap_server.flags & AUTH_DONE) == 0) + auth_peer_success(pcb, PPP_CHAP, + pcb->chap_server.digest->code, + name, strlen(name)); + if (pcb->settings.chap_rechallenge_time) { + pcb->chap_server.flags |= TIMEOUT_PENDING; + TIMEOUT(chap_timeout, pcb, + pcb->settings.chap_rechallenge_time); + } + } + pcb->chap_server.flags |= AUTH_DONE; + } +} + +/* + * chap_verify_response - check whether the peer's response matches + * what we think it should be. Returns 1 if it does (authentication + * succeeded), or 0 if it doesn't. + */ +static int chap_verify_response(const char *name, const char *ourname, int id, + const struct chap_digest_type *digest, + const unsigned char *challenge, const unsigned char *response, + char *message, int message_space) { + int ok; + unsigned char secret[MAXSECRETLEN]; + int secret_len; + +/* FIXME: we need a way to check peer secret */ +#if 0 + /* Get the secret that the peer is supposed to know */ + if (!get_secret(pcb, name, ourname, (char *)secret, &secret_len, 1)) { + ppp_error("No CHAP secret found for authenticating %q", name); + return 0; + } +#else + /* only here to clean compiler warnings */ + LWIP_UNUSED_ARG(ourname); + secret_len = 0; +#endif /* 0 */ + ok = digest->verify_response(id, name, secret, secret_len, challenge, + response, message, message_space); + memset(secret, 0, sizeof(secret)); + + return ok; +} +#endif /* PPP_SERVER */ + +/* + * chap_respond - Generate and send a response to a challenge. + */ +static void chap_respond(ppp_pcb *pcb, int id, + unsigned char *pkt, int len) { + int clen, nlen; + int secret_len; + struct pbuf *p; + u_char *outp; + char rname[MAXNAMELEN+1]; + char secret[MAXSECRETLEN+1]; + + p = pbuf_alloc(PBUF_RAW, (u16_t)(RESP_MAX_PKTLEN), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + if ((pcb->chap_client.flags & (LOWERUP | AUTH_STARTED)) != (LOWERUP | AUTH_STARTED)) + return; /* not ready */ + if (len < 2 || len < pkt[0] + 1) + return; /* too short */ + clen = pkt[0]; + nlen = len - (clen + 1); + + /* Null terminate and clean remote name. */ + ppp_slprintf(rname, sizeof(rname), "%.*v", nlen, pkt + clen + 1); + +#if PPP_REMOTENAME + /* Microsoft doesn't send their name back in the PPP packet */ + if (pcb->settings.explicit_remote || (pcb->settings.remote_name[0] != 0 && rname[0] == 0)) + strlcpy(rname, pcb->settings.remote_name, sizeof(rname)); +#endif /* PPP_REMOTENAME */ + + /* get secret for authenticating ourselves with the specified host */ + if (!get_secret(pcb, pcb->chap_client.name, rname, secret, &secret_len, 0)) { + secret_len = 0; /* assume null secret if can't find one */ + ppp_warn("No CHAP secret found for authenticating us to %q", rname); + } + + outp = (u_char*)p->payload; + MAKEHEADER(outp, PPP_CHAP); + outp += CHAP_HDRLEN; + + pcb->chap_client.digest->make_response(outp, id, pcb->chap_client.name, pkt, + secret, secret_len, pcb->chap_client.priv); + memset(secret, 0, secret_len); + + clen = *outp; + nlen = strlen(pcb->chap_client.name); + memcpy(outp + clen + 1, pcb->chap_client.name, nlen); + + outp = (u_char*)p->payload + PPP_HDRLEN; + len = CHAP_HDRLEN + clen + 1 + nlen; + outp[0] = CHAP_RESPONSE; + outp[1] = id; + outp[2] = len >> 8; + outp[3] = len; + + pbuf_realloc(p, PPP_HDRLEN + len); + ppp_write(pcb, p); +} + +static void chap_handle_status(ppp_pcb *pcb, int code, int id, + unsigned char *pkt, int len) { + const char *msg = NULL; + LWIP_UNUSED_ARG(id); + + if ((pcb->chap_client.flags & (AUTH_DONE|AUTH_STARTED|LOWERUP)) + != (AUTH_STARTED|LOWERUP)) + return; + pcb->chap_client.flags |= AUTH_DONE; + + if (code == CHAP_SUCCESS) { + /* used for MS-CHAP v2 mutual auth, yuck */ + if (pcb->chap_client.digest->check_success != NULL) { + if (!(*pcb->chap_client.digest->check_success)(pkt, len, pcb->chap_client.priv)) + code = CHAP_FAILURE; + } else + msg = "CHAP authentication succeeded"; + } else { + if (pcb->chap_client.digest->handle_failure != NULL) + (*pcb->chap_client.digest->handle_failure)(pkt, len); + else + msg = "CHAP authentication failed"; + } + if (msg) { + if (len > 0) + ppp_info("%s: %.*v", msg, len, pkt); + else + ppp_info("%s", msg); + } + if (code == CHAP_SUCCESS) + auth_withpeer_success(pcb, PPP_CHAP, pcb->chap_client.digest->code); + else { + pcb->chap_client.flags |= AUTH_FAILED; + ppp_error("CHAP authentication failed"); + auth_withpeer_fail(pcb, PPP_CHAP); + } +} + +static void chap_input(ppp_pcb *pcb, unsigned char *pkt, int pktlen) { + unsigned char code, id; + int len; + + if (pktlen < CHAP_HDRLEN) + return; + GETCHAR(code, pkt); + GETCHAR(id, pkt); + GETSHORT(len, pkt); + if (len < CHAP_HDRLEN || len > pktlen) + return; + len -= CHAP_HDRLEN; + + switch (code) { + case CHAP_CHALLENGE: + chap_respond(pcb, id, pkt, len); + break; +#if PPP_SERVER + case CHAP_RESPONSE: + chap_handle_response(pcb, id, pkt, len); + break; +#endif /* PPP_SERVER */ + case CHAP_FAILURE: + case CHAP_SUCCESS: + chap_handle_status(pcb, code, id, pkt, len); + break; + default: + break; + } +} + +static void chap_protrej(ppp_pcb *pcb) { + +#if PPP_SERVER + if (pcb->chap_server.flags & TIMEOUT_PENDING) { + pcb->chap_server.flags &= ~TIMEOUT_PENDING; + UNTIMEOUT(chap_timeout, pcb); + } + if (pcb->chap_server.flags & AUTH_STARTED) { + pcb->chap_server.flags = 0; + auth_peer_fail(pcb, PPP_CHAP); + } +#endif /* PPP_SERVER */ + if ((pcb->chap_client.flags & (AUTH_STARTED|AUTH_DONE)) == AUTH_STARTED) { + pcb->chap_client.flags &= ~AUTH_STARTED; + ppp_error("CHAP authentication failed due to protocol-reject"); + auth_withpeer_fail(pcb, PPP_CHAP); + } +} + +#if PRINTPKT_SUPPORT +/* + * chap_print_pkt - print the contents of a CHAP packet. + */ +static const char *chap_code_names[] = { + "Challenge", "Response", "Success", "Failure" +}; + +static int chap_print_pkt(unsigned char *p, int plen, + void (*printer) (void *, const char *, ...), void *arg) { + int code, id, len; + int clen, nlen; + unsigned char x; + + if (plen < CHAP_HDRLEN) + return 0; + GETCHAR(code, p); + GETCHAR(id, p); + GETSHORT(len, p); + if (len < CHAP_HDRLEN || len > plen) + return 0; + + if (code >= 1 && code <= (int)sizeof(chap_code_names) / (int)sizeof(char *)) + printer(arg, " %s", chap_code_names[code-1]); + else + printer(arg, " code=0x%x", code); + printer(arg, " id=0x%x", id); + len -= CHAP_HDRLEN; + switch (code) { + case CHAP_CHALLENGE: + case CHAP_RESPONSE: + if (len < 1) + break; + clen = p[0]; + if (len < clen + 1) + break; + ++p; + nlen = len - clen - 1; + printer(arg, " <"); + for (; clen > 0; --clen) { + GETCHAR(x, p); + printer(arg, "%.2x", x); + } + printer(arg, ">, name = "); + ppp_print_string((char *)p, nlen, printer, arg); + break; + case CHAP_FAILURE: + case CHAP_SUCCESS: + printer(arg, " "); + ppp_print_string((char *)p, len, printer, arg); + break; + default: + for (clen = len; clen > 0; --clen) { + GETCHAR(x, p); + printer(arg, " %.2x", x); + } + /* no break */ + } + + return len + CHAP_HDRLEN; +} +#endif /* PRINTPKT_SUPPORT */ + +const struct protent chap_protent = { + PPP_CHAP, + chap_init, + chap_input, + chap_protrej, + chap_lowerup, + chap_lowerdown, + NULL, /* open */ + NULL, /* close */ +#if PRINTPKT_SUPPORT + chap_print_pkt, +#endif /* PRINTPKT_SUPPORT */ + NULL, /* datainput */ + 1, /* enabled_flag */ +#if PRINTPKT_SUPPORT + "CHAP", /* name */ + NULL, /* data_name */ +#endif /* PRINTPKT_SUPPORT */ +#if PPP_OPTIONS + chap_option_list, + NULL, /* check_options */ +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT + NULL, + NULL +#endif /* DEMAND_SUPPORT */ +}; + +#endif /* PPP_SUPPORT && CHAP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/chap_ms.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/chap_ms.c new file mode 100644 index 0000000..e0b67d4 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/chap_ms.c @@ -0,0 +1,913 @@ +/* + * chap_ms.c - Microsoft MS-CHAP compatible implementation. + * + * Copyright (c) 1995 Eric Rosenquist. 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. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Modifications by Lauri Pesonen / lpesonen@clinet.fi, april 1997 + * + * Implemented LANManager type password response to MS-CHAP challenges. + * Now pppd provides both NT style and LANMan style blocks, and the + * prefered is set by option "ms-lanman". Default is to use NT. + * The hash text (StdText) was taken from Win95 RASAPI32.DLL. + * + * You should also use DOMAIN\\USERNAME as described in README.MSCHAP80 + */ + +/* + * Modifications by Frank Cusack, frank@google.com, March 2002. + * + * Implemented MS-CHAPv2 functionality, heavily based on sample + * implementation in RFC 2759. Implemented MPPE functionality, + * heavily based on sample implementation in RFC 3079. + * + * Copyright (c) 2002 Google, Inc. 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. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && MSCHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#if 0 /* UNUSED */ +#include +#include +#include +#include +#include +#include +#include +#endif /* UNUSED */ + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/chap-new.h" +#include "netif/ppp/chap_ms.h" +#include "netif/ppp/pppcrypt.h" +#include "netif/ppp/magic.h" + +#if LWIP_INCLUDED_POLARSSL_MD4 +#include "netif/ppp/polarssl/md4.h" +#else +#include "polarssl/md4.h" +#endif + +#if LWIP_INCLUDED_POLARSSL_SHA1 +#include "netif/ppp/polarssl/sha1.h" +#else +#include "polarssl/sha1.h" +#endif + +#if LWIP_INCLUDED_POLARSSL_DES +#include "netif/ppp/polarssl/des.h" +#else +#include "polarssl/des.h" +#endif + +#define SHA1_SIGNATURE_SIZE 20 + +static void ascii2unicode (char[], int, u_char[]); +static void NTPasswordHash (u_char *, int, u_char[MD4_SIGNATURE_SIZE]); +static void ChallengeResponse (u_char *, u_char *, u_char[24]); +static void ChapMS_NT (u_char *, char *, int, u_char[24]); +static void ChapMS2_NT (u_char *, u_char[16], char *, char *, int, + u_char[24]); +static void GenerateAuthenticatorResponsePlain + (char*, int, u_char[24], u_char[16], u_char *, + char *, u_char[41]); +#ifdef MSLANMAN +static void ChapMS_LANMan (u_char *, char *, int, u_char *); +#endif + +#ifdef MPPE +static void Set_Start_Key (u_char *, char *, int); +static void SetMasterKeys (char *, int, u_char[24], int); +#endif + +#ifdef MSLANMAN +bool ms_lanman = 0; /* Use LanMan password instead of NT */ + /* Has meaning only with MS-CHAP challenges */ +#endif + +#ifdef MPPE +u_char mppe_send_key[MPPE_MAX_KEY_LEN]; +u_char mppe_recv_key[MPPE_MAX_KEY_LEN]; +int mppe_keys_set = 0; /* Have the MPPE keys been set? */ + +#ifdef DEBUGMPPEKEY +/* For MPPE debug */ +/* Use "[]|}{?/><,`!2&&(" (sans quotes) for RFC 3079 MS-CHAPv2 test value */ +static char *mschap_challenge = NULL; +/* Use "!@\#$%^&*()_+:3|~" (sans quotes, backslash is to escape #) for ... */ +static char *mschap2_peer_challenge = NULL; +#endif + +#include "netif/ppp/fsm.h" /* Need to poke MPPE options */ +#include "netif/ppp/ccp.h" +#include +#endif + +#if PPP_OPTIONS +/* + * Command-line options. + */ +static option_t chapms_option_list[] = { +#ifdef MSLANMAN + { "ms-lanman", o_bool, &ms_lanman, + "Use LanMan passwd when using MS-CHAP", 1 }, +#endif +#ifdef DEBUGMPPEKEY + { "mschap-challenge", o_string, &mschap_challenge, + "specify CHAP challenge" }, + { "mschap2-peer-challenge", o_string, &mschap2_peer_challenge, + "specify CHAP peer challenge" }, +#endif + { NULL } +}; +#endif /* PPP_OPTIONS */ + +#if PPP_SERVER +/* + * chapms_generate_challenge - generate a challenge for MS-CHAP. + * For MS-CHAP the challenge length is fixed at 8 bytes. + * The length goes in challenge[0] and the actual challenge starts + * at challenge[1]. + */ +static void chapms_generate_challenge(unsigned char *challenge) { + *challenge++ = 8; +#ifdef DEBUGMPPEKEY + if (mschap_challenge && strlen(mschap_challenge) == 8) + memcpy(challenge, mschap_challenge, 8); + else +#endif + random_bytes(challenge, 8); +} + +static void chapms2_generate_challenge(unsigned char *challenge) { + *challenge++ = 16; +#ifdef DEBUGMPPEKEY + if (mschap_challenge && strlen(mschap_challenge) == 16) + memcpy(challenge, mschap_challenge, 16); + else +#endif + random_bytes(challenge, 16); +} + +static int chapms_verify_response(int id, const char *name, + const unsigned char *secret, int secret_len, + const unsigned char *challenge, const unsigned char *response, + char *message, int message_space) { + unsigned char md[MS_CHAP_RESPONSE_LEN]; + int diff; + int challenge_len, response_len; + LWIP_UNUSED_ARG(id); + LWIP_UNUSED_ARG(name); + + challenge_len = *challenge++; /* skip length, is 8 */ + response_len = *response++; + if (response_len != MS_CHAP_RESPONSE_LEN) + goto bad; + +#ifndef MSLANMAN + if (!response[MS_CHAP_USENT]) { + /* Should really propagate this into the error packet. */ + ppp_notice("Peer request for LANMAN auth not supported"); + goto bad; + } +#endif + + /* Generate the expected response. */ + ChapMS((u_char *)challenge, (char *)secret, secret_len, md); + +#ifdef MSLANMAN + /* Determine which part of response to verify against */ + if (!response[MS_CHAP_USENT]) + diff = memcmp(&response[MS_CHAP_LANMANRESP], + &md[MS_CHAP_LANMANRESP], MS_CHAP_LANMANRESP_LEN); + else +#endif + diff = memcmp(&response[MS_CHAP_NTRESP], &md[MS_CHAP_NTRESP], + MS_CHAP_NTRESP_LEN); + + if (diff == 0) { + ppp_slprintf(message, message_space, "Access granted"); + return 1; + } + + bad: + /* See comments below for MS-CHAP V2 */ + ppp_slprintf(message, message_space, "E=691 R=1 C=%0.*B V=0", + challenge_len, challenge); + return 0; +} + +static int chapms2_verify_response(int id, const char *name, + const unsigned char *secret, int secret_len, + const unsigned char *challenge, const unsigned char *response, + char *message, int message_space) { + unsigned char md[MS_CHAP2_RESPONSE_LEN]; + char saresponse[MS_AUTH_RESPONSE_LENGTH+1]; + int challenge_len, response_len; + LWIP_UNUSED_ARG(id); + + challenge_len = *challenge++; /* skip length, is 16 */ + response_len = *response++; + if (response_len != MS_CHAP2_RESPONSE_LEN) + goto bad; /* not even the right length */ + + /* Generate the expected response and our mutual auth. */ + ChapMS2((u_char*)challenge, (u_char*)&response[MS_CHAP2_PEER_CHALLENGE], (char*)name, + (char *)secret, secret_len, md, + (unsigned char *)saresponse, MS_CHAP2_AUTHENTICATOR); + + /* compare MDs and send the appropriate status */ + /* + * Per RFC 2759, success message must be formatted as + * "S= M=" + * where + * is the Authenticator Response (mutual auth) + * is a text message + * + * However, some versions of Windows (win98 tested) do not know + * about the M= part (required per RFC 2759) and flag + * it as an error (reported incorrectly as an encryption error + * to the user). Since the RFC requires it, and it can be + * useful information, we supply it if the peer is a conforming + * system. Luckily (?), win98 sets the Flags field to 0x04 + * (contrary to RFC requirements) so we can use that to + * distinguish between conforming and non-conforming systems. + * + * Special thanks to Alex Swiridov for + * help debugging this. + */ + if (memcmp(&md[MS_CHAP2_NTRESP], &response[MS_CHAP2_NTRESP], + MS_CHAP2_NTRESP_LEN) == 0) { + if (response[MS_CHAP2_FLAGS]) + ppp_slprintf(message, message_space, "S=%s", saresponse); + else + ppp_slprintf(message, message_space, "S=%s M=%s", + saresponse, "Access granted"); + return 1; + } + + bad: + /* + * Failure message must be formatted as + * "E=e R=r C=c V=v M=m" + * where + * e = error code (we use 691, ERROR_AUTHENTICATION_FAILURE) + * r = retry (we use 1, ok to retry) + * c = challenge to use for next response, we reuse previous + * v = Change Password version supported, we use 0 + * m = text message + * + * The M=m part is only for MS-CHAPv2. Neither win2k nor + * win98 (others untested) display the message to the user anyway. + * They also both ignore the E=e code. + * + * Note that it's safe to reuse the same challenge as we don't + * actually accept another response based on the error message + * (and no clients try to resend a response anyway). + * + * Basically, this whole bit is useless code, even the small + * implementation here is only because of overspecification. + */ + ppp_slprintf(message, message_space, "E=691 R=1 C=%0.*B V=0 M=%s", + challenge_len, challenge, "Access denied"); + return 0; +} +#endif /* PPP_SERVER */ + +static void chapms_make_response(unsigned char *response, int id, const char *our_name, + const unsigned char *challenge, const char *secret, int secret_len, + const unsigned char *private_) { + LWIP_UNUSED_ARG(id); + LWIP_UNUSED_ARG(our_name); + LWIP_UNUSED_ARG(private_); + challenge++; /* skip length, should be 8 */ + *response++ = MS_CHAP_RESPONSE_LEN; + ChapMS((u_char*)challenge, (char*)secret, secret_len, response); +} + +static void chapms2_make_response(unsigned char *response, int id, const char *our_name, + const unsigned char *challenge, const char *secret, int secret_len, + const unsigned char *private_) { + LWIP_UNUSED_ARG(id); + challenge++; /* skip length, should be 16 */ + *response++ = MS_CHAP2_RESPONSE_LEN; + ChapMS2((u_char*)challenge, +#ifdef DEBUGMPPEKEY + mschap2_peer_challenge, +#else + NULL, +#endif + (char*)our_name, (char*)secret, secret_len, response, (u_char*)private_, + MS_CHAP2_AUTHENTICATEE); +} + +static int chapms2_check_success(unsigned char *msg, int len, unsigned char *private_) { + if ((len < MS_AUTH_RESPONSE_LENGTH + 2) || + strncmp((char *)msg, "S=", 2) != 0) { + /* Packet does not start with "S=" */ + ppp_error("MS-CHAPv2 Success packet is badly formed."); + return 0; + } + msg += 2; + len -= 2; + if (len < MS_AUTH_RESPONSE_LENGTH + || memcmp(msg, private_, MS_AUTH_RESPONSE_LENGTH)) { + /* Authenticator Response did not match expected. */ + ppp_error("MS-CHAPv2 mutual authentication failed."); + return 0; + } + /* Authenticator Response matches. */ + msg += MS_AUTH_RESPONSE_LENGTH; /* Eat it */ + len -= MS_AUTH_RESPONSE_LENGTH; + if ((len >= 3) && !strncmp((char *)msg, " M=", 3)) { + msg += 3; /* Eat the delimiter */ + } else if (len) { + /* Packet has extra text which does not begin " M=" */ + ppp_error("MS-CHAPv2 Success packet is badly formed."); + return 0; + } + return 1; +} + +static void chapms_handle_failure(unsigned char *inp, int len) { + int err; + const char *p; + char msg[64]; + + /* We want a null-terminated string for strxxx(). */ + len = LWIP_MIN(len, 63); + MEMCPY(msg, inp, len); + msg[len] = 0; + p = msg; + + /* + * Deal with MS-CHAP formatted failure messages; just print the + * M= part (if any). For MS-CHAP we're not really supposed + * to use M=, but it shouldn't hurt. See + * chapms[2]_verify_response. + */ + if (!strncmp(p, "E=", 2)) + err = strtol(p+2, NULL, 10); /* Remember the error code. */ + else + goto print_msg; /* Message is badly formatted. */ + + if (len && ((p = strstr(p, " M=")) != NULL)) { + /* M= field found. */ + p += 3; + } else { + /* No M=; use the error code. */ + switch (err) { + case MS_CHAP_ERROR_RESTRICTED_LOGON_HOURS: + p = "E=646 Restricted logon hours"; + break; + + case MS_CHAP_ERROR_ACCT_DISABLED: + p = "E=647 Account disabled"; + break; + + case MS_CHAP_ERROR_PASSWD_EXPIRED: + p = "E=648 Password expired"; + break; + + case MS_CHAP_ERROR_NO_DIALIN_PERMISSION: + p = "E=649 No dialin permission"; + break; + + case MS_CHAP_ERROR_AUTHENTICATION_FAILURE: + p = "E=691 Authentication failure"; + break; + + case MS_CHAP_ERROR_CHANGING_PASSWORD: + /* Should never see this, we don't support Change Password. */ + p = "E=709 Error changing password"; + break; + + default: + ppp_error("Unknown MS-CHAP authentication failure: %.*v", + len, inp); + return; + } + } +print_msg: + if (p != NULL) + ppp_error("MS-CHAP authentication failed: %v", p); +} + +static void ChallengeResponse(u_char *challenge, + u_char PasswordHash[MD4_SIGNATURE_SIZE], + u_char response[24]) { + u_char ZPasswordHash[21]; + des_context des; + u_char des_key[8]; + + BZERO(ZPasswordHash, sizeof(ZPasswordHash)); + MEMCPY(ZPasswordHash, PasswordHash, MD4_SIGNATURE_SIZE); + +#if 0 + dbglog("ChallengeResponse - ZPasswordHash %.*B", + sizeof(ZPasswordHash), ZPasswordHash); +#endif + + pppcrypt_56_to_64_bit_key(ZPasswordHash + 0, des_key); + des_setkey_enc(&des, des_key); + des_crypt_ecb(&des, challenge, response +0); + + pppcrypt_56_to_64_bit_key(ZPasswordHash + 7, des_key); + des_setkey_enc(&des, des_key); + des_crypt_ecb(&des, challenge, response +8); + + pppcrypt_56_to_64_bit_key(ZPasswordHash + 14, des_key); + des_setkey_enc(&des, des_key); + des_crypt_ecb(&des, challenge, response +16); + +#if 0 + dbglog("ChallengeResponse - response %.24B", response); +#endif +} + +void ChallengeHash(u_char PeerChallenge[16], u_char *rchallenge, + char *username, u_char Challenge[8]) { + sha1_context sha1Context; + u_char sha1Hash[SHA1_SIGNATURE_SIZE]; + char *user; + + /* remove domain from "domain\username" */ + if ((user = strrchr(username, '\\')) != NULL) + ++user; + else + user = username; + + sha1_starts(&sha1Context); + sha1_update(&sha1Context, PeerChallenge, 16); + sha1_update(&sha1Context, rchallenge, 16); + sha1_update(&sha1Context, (unsigned char *)user, strlen(user)); + sha1_finish(&sha1Context, sha1Hash); + + MEMCPY(Challenge, sha1Hash, 8); +} + +/* + * Convert the ASCII version of the password to Unicode. + * This implicitly supports 8-bit ISO8859/1 characters. + * This gives us the little-endian representation, which + * is assumed by all M$ CHAP RFCs. (Unicode byte ordering + * is machine-dependent.) + */ +static void ascii2unicode(char ascii[], int ascii_len, u_char unicode[]) { + int i; + + BZERO(unicode, ascii_len * 2); + for (i = 0; i < ascii_len; i++) + unicode[i * 2] = (u_char) ascii[i]; +} + +static void NTPasswordHash(u_char *secret, int secret_len, u_char hash[MD4_SIGNATURE_SIZE]) { + md4_context md4Context; + + md4_starts(&md4Context); + md4_update(&md4Context, secret, secret_len); + md4_finish(&md4Context, hash); +} + +static void ChapMS_NT(u_char *rchallenge, char *secret, int secret_len, + u_char NTResponse[24]) { + u_char unicodePassword[MAX_NT_PASSWORD * 2]; + u_char PasswordHash[MD4_SIGNATURE_SIZE]; + + /* Hash the Unicode version of the secret (== password). */ + ascii2unicode(secret, secret_len, unicodePassword); + NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); + + ChallengeResponse(rchallenge, PasswordHash, NTResponse); +} + +static void ChapMS2_NT(u_char *rchallenge, u_char PeerChallenge[16], char *username, + char *secret, int secret_len, u_char NTResponse[24]) { + u_char unicodePassword[MAX_NT_PASSWORD * 2]; + u_char PasswordHash[MD4_SIGNATURE_SIZE]; + u_char Challenge[8]; + + ChallengeHash(PeerChallenge, rchallenge, username, Challenge); + + /* Hash the Unicode version of the secret (== password). */ + ascii2unicode(secret, secret_len, unicodePassword); + NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); + + ChallengeResponse(Challenge, PasswordHash, NTResponse); +} + +#ifdef MSLANMAN +static u_char *StdText = (u_char *)"KGS!@#$%"; /* key from rasapi32.dll */ + +static void ChapMS_LANMan(u_char *rchallenge, char *secret, int secret_len, + unsigned char *response) { + int i; + u_char UcasePassword[MAX_NT_PASSWORD]; /* max is actually 14 */ + u_char PasswordHash[MD4_SIGNATURE_SIZE]; + des_context des; + u_char des_key[8]; + + /* LANMan password is case insensitive */ + BZERO(UcasePassword, sizeof(UcasePassword)); + for (i = 0; i < secret_len; i++) + UcasePassword[i] = (u_char)toupper(secret[i]); + + pppcrypt_56_to_64_bit_key(UcasePassword +0, des_key); + des_setkey_enc(&des, des_key); + des_crypt_ecb(&des, StdText, PasswordHash +0); + + pppcrypt_56_to_64_bit_key(UcasePassword +7, des_key); + des_setkey_enc(&des, des_key); + des_crypt_ecb(&des, StdText, PasswordHash +8); + + ChallengeResponse(rchallenge, PasswordHash, &response[MS_CHAP_LANMANRESP]); +} +#endif + + +void GenerateAuthenticatorResponse(u_char PasswordHashHash[MD4_SIGNATURE_SIZE], + u_char NTResponse[24], u_char PeerChallenge[16], + u_char *rchallenge, char *username, + u_char authResponse[MS_AUTH_RESPONSE_LENGTH+1]) { + /* + * "Magic" constants used in response generation, from RFC 2759. + */ + u_char Magic1[39] = /* "Magic server to client signing constant" */ + { 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65, + 0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67, + 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74 }; + u_char Magic2[41] = /* "Pad to make it do more than one iteration" */ + { 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B, + 0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F, + 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E, + 0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F, + 0x6E }; + + int i; + sha1_context sha1Context; + u_char Digest[SHA1_SIGNATURE_SIZE]; + u_char Challenge[8]; + + sha1_starts(&sha1Context); + sha1_update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE); + sha1_update(&sha1Context, NTResponse, 24); + sha1_update(&sha1Context, Magic1, sizeof(Magic1)); + sha1_finish(&sha1Context, Digest); + + ChallengeHash(PeerChallenge, rchallenge, username, Challenge); + + sha1_starts(&sha1Context); + sha1_update(&sha1Context, Digest, sizeof(Digest)); + sha1_update(&sha1Context, Challenge, sizeof(Challenge)); + sha1_update(&sha1Context, Magic2, sizeof(Magic2)); + sha1_finish(&sha1Context, Digest); + + /* Convert to ASCII hex string. */ + for (i = 0; i < LWIP_MAX((MS_AUTH_RESPONSE_LENGTH / 2), (int)sizeof(Digest)); i++) + sprintf((char *)&authResponse[i * 2], "%02X", Digest[i]); +} + + +static void GenerateAuthenticatorResponsePlain + (char *secret, int secret_len, + u_char NTResponse[24], u_char PeerChallenge[16], + u_char *rchallenge, char *username, + u_char authResponse[MS_AUTH_RESPONSE_LENGTH+1]) { + u_char unicodePassword[MAX_NT_PASSWORD * 2]; + u_char PasswordHash[MD4_SIGNATURE_SIZE]; + u_char PasswordHashHash[MD4_SIGNATURE_SIZE]; + + /* Hash (x2) the Unicode version of the secret (== password). */ + ascii2unicode(secret, secret_len, unicodePassword); + NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); + NTPasswordHash(PasswordHash, sizeof(PasswordHash), + PasswordHashHash); + + GenerateAuthenticatorResponse(PasswordHashHash, NTResponse, PeerChallenge, + rchallenge, username, authResponse); +} + + +#ifdef MPPE +/* + * Set mppe_xxxx_key from the NTPasswordHashHash. + * RFC 2548 (RADIUS support) requires us to export this function (ugh). + */ +void mppe_set_keys(u_char *rchallenge, u_char PasswordHashHash[MD4_SIGNATURE_SIZE]) { + sha1_context sha1Context; + u_char Digest[SHA1_SIGNATURE_SIZE]; /* >= MPPE_MAX_KEY_LEN */ + + sha1_starts(&sha1Context); + sha1_update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE); + sha1_update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE); + sha1_update(&sha1Context, rchallenge, 8); + sha1_finish(&sha1Context, Digest); + + /* Same key in both directions. */ + MEMCPY(mppe_send_key, Digest, sizeof(mppe_send_key)); + MEMCPY(mppe_recv_key, Digest, sizeof(mppe_recv_key)); + + mppe_keys_set = 1; +} + +/* + * Set mppe_xxxx_key from MS-CHAP credentials. (see RFC 3079) + */ +static void Set_Start_Key(u_char *rchallenge, char *secret, int secret_len) { + u_char unicodePassword[MAX_NT_PASSWORD * 2]; + u_char PasswordHash[MD4_SIGNATURE_SIZE]; + u_char PasswordHashHash[MD4_SIGNATURE_SIZE]; + + /* Hash (x2) the Unicode version of the secret (== password). */ + ascii2unicode(secret, secret_len, unicodePassword); + NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); + NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash); + + mppe_set_keys(rchallenge, PasswordHashHash); +} + +/* + * Set mppe_xxxx_key from MS-CHAPv2 credentials. (see RFC 3079) + * + * This helper function used in the Winbind module, which gets the + * NTHashHash from the server. + */ +void mppe_set_keys2(u_char PasswordHashHash[MD4_SIGNATURE_SIZE], + u_char NTResponse[24], int IsServer) { + sha1_context sha1Context; + u_char MasterKey[SHA1_SIGNATURE_SIZE]; /* >= MPPE_MAX_KEY_LEN */ + u_char Digest[SHA1_SIGNATURE_SIZE]; /* >= MPPE_MAX_KEY_LEN */ + + u_char SHApad1[40] = + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + u_char SHApad2[40] = + { 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, + 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, + 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, + 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2 }; + + /* "This is the MPPE Master Key" */ + u_char Magic1[27] = + { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d, + 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79 }; + /* "On the client side, this is the send key; " + "on the server side, it is the receive key." */ + u_char Magic2[84] = + { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, + 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79, + 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65, + 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, + 0x6b, 0x65, 0x79, 0x2e }; + /* "On the client side, this is the receive key; " + "on the server side, it is the send key." */ + u_char Magic3[84] = + { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, + 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, + 0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, + 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, + 0x6b, 0x65, 0x79, 0x2e }; + u_char *s; + + sha1_starts(&sha1Context); + sha1_update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE); + sha1_update(&sha1Context, NTResponse, 24); + sha1_update(&sha1Context, Magic1, sizeof(Magic1)); + sha1_finish(&sha1Context, MasterKey); + + /* + * generate send key + */ + if (IsServer) + s = Magic3; + else + s = Magic2; + sha1_starts(&sha1Context); + sha1_update(&sha1Context, MasterKey, 16); + sha1_update(&sha1Context, SHApad1, sizeof(SHApad1)); + sha1_update(&sha1Context, s, 84); + sha1_update(&sha1Context, SHApad2, sizeof(SHApad2)); + sha1_finish(&sha1Context, Digest); + + MEMCPY(mppe_send_key, Digest, sizeof(mppe_send_key)); + + /* + * generate recv key + */ + if (IsServer) + s = Magic2; + else + s = Magic3; + sha1_starts(&sha1Context); + sha1_update(&sha1Context, MasterKey, 16); + sha1_update(&sha1Context, SHApad1, sizeof(SHApad1)); + sha1_update(&sha1Context, s, 84); + sha1_update(&sha1Context, SHApad2, sizeof(SHApad2)); + sha1_finish(&sha1Context, Digest); + + MEMCPY(mppe_recv_key, Digest, sizeof(mppe_recv_key)); + + mppe_keys_set = 1; +} + +/* + * Set mppe_xxxx_key from MS-CHAPv2 credentials. (see RFC 3079) + */ +static void SetMasterKeys(char *secret, int secret_len, u_char NTResponse[24], int IsServer) { + u_char unicodePassword[MAX_NT_PASSWORD * 2]; + u_char PasswordHash[MD4_SIGNATURE_SIZE]; + u_char PasswordHashHash[MD4_SIGNATURE_SIZE]; + /* Hash (x2) the Unicode version of the secret (== password). */ + ascii2unicode(secret, secret_len, unicodePassword); + NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); + NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash); + mppe_set_keys2(PasswordHashHash, NTResponse, IsServer); +} + +#endif /* MPPE */ + + +void ChapMS(u_char *rchallenge, char *secret, int secret_len, + unsigned char *response) { + BZERO(response, MS_CHAP_RESPONSE_LEN); + + ChapMS_NT(rchallenge, secret, secret_len, &response[MS_CHAP_NTRESP]); + +#ifdef MSLANMAN + ChapMS_LANMan(rchallenge, secret, secret_len, + &response[MS_CHAP_LANMANRESP]); + + /* preferred method is set by option */ + response[MS_CHAP_USENT] = !ms_lanman; +#else + response[MS_CHAP_USENT] = 1; +#endif + +#ifdef MPPE + Set_Start_Key(rchallenge, secret, secret_len); +#endif +} + + +/* + * If PeerChallenge is NULL, one is generated and the PeerChallenge + * field of response is filled in. Call this way when generating a response. + * If PeerChallenge is supplied, it is copied into the PeerChallenge field. + * Call this way when verifying a response (or debugging). + * Do not call with PeerChallenge = response. + * + * The PeerChallenge field of response is then used for calculation of the + * Authenticator Response. + */ +void ChapMS2(u_char *rchallenge, u_char *PeerChallenge, + char *user, char *secret, int secret_len, unsigned char *response, + u_char authResponse[], int authenticator) { + /* ARGSUSED */ + u_char *p = &response[MS_CHAP2_PEER_CHALLENGE]; + int i; + LWIP_UNUSED_ARG(authenticator); + + BZERO(response, MS_CHAP2_RESPONSE_LEN); + + /* Generate the Peer-Challenge if requested, or copy it if supplied. */ + if (!PeerChallenge) + for (i = 0; i < MS_CHAP2_PEER_CHAL_LEN; i++) + *p++ = (u_char) (drand48() * 0xff); + else + MEMCPY(&response[MS_CHAP2_PEER_CHALLENGE], PeerChallenge, + MS_CHAP2_PEER_CHAL_LEN); + + /* Generate the NT-Response */ + ChapMS2_NT(rchallenge, &response[MS_CHAP2_PEER_CHALLENGE], user, + secret, secret_len, &response[MS_CHAP2_NTRESP]); + + /* Generate the Authenticator Response. */ + GenerateAuthenticatorResponsePlain(secret, secret_len, + &response[MS_CHAP2_NTRESP], + &response[MS_CHAP2_PEER_CHALLENGE], + rchallenge, user, authResponse); + +#ifdef MPPE + SetMasterKeys(secret, secret_len, + &response[MS_CHAP2_NTRESP], authenticator); +#endif +} + +#ifdef MPPE +/* + * Set MPPE options from plugins. + */ +void set_mppe_enc_types(int policy, int types) { + /* Early exit for unknown policies. */ + if (policy != MPPE_ENC_POL_ENC_ALLOWED || + policy != MPPE_ENC_POL_ENC_REQUIRED) + return; + + /* Don't modify MPPE if it's optional and wasn't already configured. */ + if (policy == MPPE_ENC_POL_ENC_ALLOWED && !ccp_wantoptions[0].mppe) + return; + + /* + * Disable undesirable encryption types. Note that we don't ENABLE + * any encryption types, to avoid overriding manual configuration. + */ + switch(types) { + case MPPE_ENC_TYPES_RC4_40: + ccp_wantoptions[0].mppe &= ~MPPE_OPT_128; /* disable 128-bit */ + break; + case MPPE_ENC_TYPES_RC4_128: + ccp_wantoptions[0].mppe &= ~MPPE_OPT_40; /* disable 40-bit */ + break; + default: + break; + } +} +#endif /* MPPE */ + +const struct chap_digest_type chapms_digest = { + CHAP_MICROSOFT, /* code */ +#if PPP_SERVER + chapms_generate_challenge, + chapms_verify_response, +#endif /* PPP_SERVER */ + chapms_make_response, + NULL, /* check_success */ + chapms_handle_failure, +}; + +const struct chap_digest_type chapms2_digest = { + CHAP_MICROSOFT_V2, /* code */ +#if PPP_SERVER + chapms2_generate_challenge, + chapms2_verify_response, +#endif /* PPP_SERVER */ + chapms2_make_response, + chapms2_check_success, + chapms_handle_failure, +}; + +#endif /* PPP_SUPPORT && MSCHAP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/demand.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/demand.c new file mode 100644 index 0000000..f31a124 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/demand.c @@ -0,0 +1,467 @@ +/* + * demand.c - Support routines for demand-dialling. + * + * Copyright (c) 1996-2002 Paul Mackerras. 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. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && DEMAND_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef PPP_FILTER +#include +#endif + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/fsm.h" +#include "netif/ppp/ipcp.h" +#include "netif/ppp/lcp.h" + +char *frame; +int framelen; +int framemax; +int escape_flag; +int flush_flag; +int fcs; + +struct packet { + int length; + struct packet *next; + unsigned char data[1]; +}; + +struct packet *pend_q; +struct packet *pend_qtail; + +static int active_packet (unsigned char *, int); + +/* + * demand_conf - configure the interface for doing dial-on-demand. + */ +void +demand_conf() +{ + int i; + const struct protent *protp; + +/* framemax = lcp_allowoptions[0].mru; + if (framemax < PPP_MRU) */ + framemax = PPP_MRU; + framemax += PPP_HDRLEN + PPP_FCSLEN; + frame = malloc(framemax); + if (frame == NULL) + novm("demand frame"); + framelen = 0; + pend_q = NULL; + escape_flag = 0; + flush_flag = 0; + fcs = PPP_INITFCS; + + netif_set_mtu(pcb, LWIP_MIN(lcp_allowoptions[0].mru, PPP_MRU)); + if (ppp_send_config(pcb, PPP_MRU, (u32_t) 0, 0, 0) < 0 + || ppp_recv_config(pcb, PPP_MRU, (u32_t) 0, 0, 0) < 0) + fatal("Couldn't set up demand-dialled PPP interface: %m"); + +#ifdef PPP_FILTER + set_filters(&pass_filter, &active_filter); +#endif + + /* + * Call the demand_conf procedure for each protocol that's got one. + */ + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if (protp->enabled_flag && protp->demand_conf != NULL) + ((*protp->demand_conf)(pcb)); +/* FIXME: find a way to die() here */ +#if 0 + if (!((*protp->demand_conf)(pcb))) + die(1); +#endif +} + + +/* + * demand_block - set each network protocol to block further packets. + */ +void +demand_block() +{ + int i; + const struct protent *protp; + + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if (protp->enabled_flag && protp->demand_conf != NULL) + sifnpmode(pcb, protp->protocol & ~0x8000, NPMODE_QUEUE); + get_loop_output(); +} + +/* + * demand_discard - set each network protocol to discard packets + * with an error. + */ +void +demand_discard() +{ + struct packet *pkt, *nextpkt; + int i; + const struct protent *protp; + + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if (protp->enabled_flag && protp->demand_conf != NULL) + sifnpmode(pcb, protp->protocol & ~0x8000, NPMODE_ERROR); + get_loop_output(); + + /* discard all saved packets */ + for (pkt = pend_q; pkt != NULL; pkt = nextpkt) { + nextpkt = pkt->next; + free(pkt); + } + pend_q = NULL; + framelen = 0; + flush_flag = 0; + escape_flag = 0; + fcs = PPP_INITFCS; +} + +/* + * demand_unblock - set each enabled network protocol to pass packets. + */ +void +demand_unblock() +{ + int i; + const struct protent *protp; + + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if (protp->enabled_flag && protp->demand_conf != NULL) + sifnpmode(pcb, protp->protocol & ~0x8000, NPMODE_PASS); +} + +/* + * FCS lookup table as calculated by genfcstab. + */ +static u_short fcstab[256] = { + 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, + 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, + 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, + 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, + 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, + 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, + 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, + 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, + 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, + 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, + 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, + 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, + 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, + 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, + 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, + 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, + 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, + 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, + 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, + 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, + 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, + 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, + 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, + 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, + 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, + 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, + 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, + 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, + 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, + 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, + 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 +}; + +/* + * loop_chars - process characters received from the loopback. + * Calls loop_frame when a complete frame has been accumulated. + * Return value is 1 if we need to bring up the link, 0 otherwise. + */ +int +loop_chars(p, n) + unsigned char *p; + int n; +{ + int c, rv; + + rv = 0; + +/* check for synchronous connection... */ + + if ( (p[0] == 0xFF) && (p[1] == 0x03) ) { + rv = loop_frame(p,n); + return rv; + } + + for (; n > 0; --n) { + c = *p++; + if (c == PPP_FLAG) { + if (!escape_flag && !flush_flag + && framelen > 2 && fcs == PPP_GOODFCS) { + framelen -= 2; + if (loop_frame((unsigned char *)frame, framelen)) + rv = 1; + } + framelen = 0; + flush_flag = 0; + escape_flag = 0; + fcs = PPP_INITFCS; + continue; + } + if (flush_flag) + continue; + if (escape_flag) { + c ^= PPP_TRANS; + escape_flag = 0; + } else if (c == PPP_ESCAPE) { + escape_flag = 1; + continue; + } + if (framelen >= framemax) { + flush_flag = 1; + continue; + } + frame[framelen++] = c; + fcs = PPP_FCS(fcs, c); + } + return rv; +} + +/* + * loop_frame - given a frame obtained from the loopback, + * decide whether to bring up the link or not, and, if we want + * to transmit this frame later, put it on the pending queue. + * Return value is 1 if we need to bring up the link, 0 otherwise. + * We assume that the kernel driver has already applied the + * pass_filter, so we won't get packets it rejected. + * We apply the active_filter to see if we want this packet to + * bring up the link. + */ +int +loop_frame(frame, len) + unsigned char *frame; + int len; +{ + struct packet *pkt; + + /* dbglog("from loop: %P", frame, len); */ + if (len < PPP_HDRLEN) + return 0; + if ((PPP_PROTOCOL(frame) & 0x8000) != 0) + return 0; /* shouldn't get any of these anyway */ + if (!active_packet(frame, len)) + return 0; + + pkt = (struct packet *) malloc(sizeof(struct packet) + len); + if (pkt != NULL) { + pkt->length = len; + pkt->next = NULL; + memcpy(pkt->data, frame, len); + if (pend_q == NULL) + pend_q = pkt; + else + pend_qtail->next = pkt; + pend_qtail = pkt; + } + return 1; +} + +/* + * demand_rexmit - Resend all those frames which we got via the + * loopback, now that the real serial link is up. + */ +void +demand_rexmit(proto, newip) + int proto; + u32_t newip; +{ + struct packet *pkt, *prev, *nextpkt; + unsigned short checksum; + unsigned short pkt_checksum = 0; + unsigned iphdr; + struct timeval tv; + char cv = 0; + char ipstr[16]; + + prev = NULL; + pkt = pend_q; + pend_q = NULL; + tv.tv_sec = 1; + tv.tv_usec = 0; + select(0,NULL,NULL,NULL,&tv); /* Sleep for 1 Seconds */ + for (; pkt != NULL; pkt = nextpkt) { + nextpkt = pkt->next; + if (PPP_PROTOCOL(pkt->data) == proto) { + if ( (proto == PPP_IP) && newip ) { + /* Get old checksum */ + + iphdr = (pkt->data[4] & 15) << 2; + checksum = *((unsigned short *) (pkt->data+14)); + if (checksum == 0xFFFF) { + checksum = 0; + } + + + if (pkt->data[13] == 17) { + pkt_checksum = *((unsigned short *) (pkt->data+10+iphdr)); + if (pkt_checksum) { + cv = 1; + if (pkt_checksum == 0xFFFF) { + pkt_checksum = 0; + } + } + else { + cv = 0; + } + } + + if (pkt->data[13] == 6) { + pkt_checksum = *((unsigned short *) (pkt->data+20+iphdr)); + cv = 1; + if (pkt_checksum == 0xFFFF) { + pkt_checksum = 0; + } + } + + /* Delete old Source-IP-Address */ + checksum -= *((unsigned short *) (pkt->data+16)) ^ 0xFFFF; + checksum -= *((unsigned short *) (pkt->data+18)) ^ 0xFFFF; + + pkt_checksum -= *((unsigned short *) (pkt->data+16)) ^ 0xFFFF; + pkt_checksum -= *((unsigned short *) (pkt->data+18)) ^ 0xFFFF; + + /* Change Source-IP-Address */ + * ((u32_t *) (pkt->data + 16)) = newip; + + /* Add new Source-IP-Address */ + checksum += *((unsigned short *) (pkt->data+16)) ^ 0xFFFF; + checksum += *((unsigned short *) (pkt->data+18)) ^ 0xFFFF; + + pkt_checksum += *((unsigned short *) (pkt->data+16)) ^ 0xFFFF; + pkt_checksum += *((unsigned short *) (pkt->data+18)) ^ 0xFFFF; + + /* Write new checksum */ + if (!checksum) { + checksum = 0xFFFF; + } + *((unsigned short *) (pkt->data+14)) = checksum; + if (pkt->data[13] == 6) { + *((unsigned short *) (pkt->data+20+iphdr)) = pkt_checksum; + } + if (cv && (pkt->data[13] == 17) ) { + *((unsigned short *) (pkt->data+10+iphdr)) = pkt_checksum; + } + + /* Log Packet */ + strcpy(ipstr,inet_ntoa(*( (struct in_addr *) (pkt->data+16)))); + if (pkt->data[13] == 1) { + syslog(LOG_INFO,"Open ICMP %s -> %s\n", + ipstr, + inet_ntoa(*( (struct in_addr *) (pkt->data+20)))); + } else { + syslog(LOG_INFO,"Open %s %s:%d -> %s:%d\n", + pkt->data[13] == 6 ? "TCP" : "UDP", + ipstr, + ntohs(*( (short *) (pkt->data+iphdr+4))), + inet_ntoa(*( (struct in_addr *) (pkt->data+20))), + ntohs(*( (short *) (pkt->data+iphdr+6)))); + } + } + output(pcb, pkt->data, pkt->length); + free(pkt); + } else { + if (prev == NULL) + pend_q = pkt; + else + prev->next = pkt; + prev = pkt; + } + } + pend_qtail = prev; + if (prev != NULL) + prev->next = NULL; +} + +/* + * Scan a packet to decide whether it is an "active" packet, + * that is, whether it is worth bringing up the link for. + */ +static int +active_packet(p, len) + unsigned char *p; + int len; +{ + int proto, i; + const struct protent *protp; + + if (len < PPP_HDRLEN) + return 0; + proto = PPP_PROTOCOL(p); +#ifdef PPP_FILTER + p[0] = 1; /* outbound packet indicator */ + if ((pass_filter.bf_len != 0 + && bpf_filter(pass_filter.bf_insns, p, len, len) == 0) + || (active_filter.bf_len != 0 + && bpf_filter(active_filter.bf_insns, p, len, len) == 0)) { + p[0] = 0xff; + return 0; + } + p[0] = 0xff; +#endif + for (i = 0; (protp = protocols[i]) != NULL; ++i) { + if (protp->protocol < 0xC000 && (protp->protocol & ~0x8000) == proto) { + if (!protp->enabled_flag) + return 0; + if (protp->active_pkt == NULL) + return 1; + return (*protp->active_pkt)(p, len); + } + } + return 0; /* not a supported protocol !!?? */ +} + +#endif /* PPP_SUPPORT && DEMAND_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/eap.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/eap.c new file mode 100644 index 0000000..5016eac --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/eap.c @@ -0,0 +1,2455 @@ +/* + * eap.c - Extensible Authentication Protocol for PPP (RFC 2284) + * + * Copyright (c) 2001 by Sun Microsystems, Inc. + * All rights reserved. + * + * Non-exclusive rights to redistribute, modify, translate, and use + * this software in source and binary forms, in whole or in part, is + * hereby granted, provided that the above copyright notice is + * duplicated in any source form, and that neither the name of the + * copyright holder nor the author is used to endorse or promote + * products derived from this software. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Original version by James Carlson + * + * This implementation of EAP supports MD5-Challenge and SRP-SHA1 + * authentication styles. Note that support of MD5-Challenge is a + * requirement of RFC 2284, and that it's essentially just a + * reimplementation of regular RFC 1994 CHAP using EAP messages. + * + * As an authenticator ("server"), there are multiple phases for each + * style. In the first phase of each style, the unauthenticated peer + * name is queried using the EAP Identity request type. If the + * "remotename" option is used, then this phase is skipped, because + * the peer's name is presumed to be known. + * + * For MD5-Challenge, there are two phases, and the second phase + * consists of sending the challenge itself and handling the + * associated response. + * + * For SRP-SHA1, there are four phases. The second sends 's', 'N', + * and 'g'. The reply contains 'A'. The third sends 'B', and the + * reply contains 'M1'. The forth sends the 'M2' value. + * + * As an authenticatee ("client"), there's just a single phase -- + * responding to the queries generated by the peer. EAP is an + * authenticator-driven protocol. + * + * Based on draft-ietf-pppext-eap-srp-03.txt. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && EAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "netif/ppp/ppp_impl.h" + +#if LWIP_INCLUDED_POLARSSL_MD5 +#include "netif/ppp/polarssl/md5.h" +#else +#include "polarssl/md5.h" +#endif + +#include "netif/ppp/eap.h" + +#ifdef USE_SRP +#include +#include +#include +#include "netif/ppp/pppcrypt.h" +#endif /* USE_SRP */ + +#ifndef SHA_DIGESTSIZE +#define SHA_DIGESTSIZE 20 +#endif + +#ifdef USE_SRP +static char *pn_secret = NULL; /* Pseudonym generating secret */ +#endif + +#if PPP_OPTIONS +/* + * Command-line options. + */ +static option_t eap_option_list[] = { + { "eap-restart", o_int, &eap_states[0].es_server.ea_timeout, + "Set retransmit timeout for EAP Requests (server)" }, + { "eap-max-sreq", o_int, &eap_states[0].es_server.ea_maxrequests, + "Set max number of EAP Requests sent (server)" }, + { "eap-timeout", o_int, &eap_states[0].es_client.ea_timeout, + "Set time limit for peer EAP authentication" }, + { "eap-max-rreq", o_int, &eap_states[0].es_client.ea_maxrequests, + "Set max number of EAP Requests allows (client)" }, + { "eap-interval", o_int, &eap_states[0].es_rechallenge, + "Set interval for EAP rechallenge" }, +#ifdef USE_SRP + { "srp-interval", o_int, &eap_states[0].es_lwrechallenge, + "Set interval for SRP lightweight rechallenge" }, + { "srp-pn-secret", o_string, &pn_secret, + "Long term pseudonym generation secret" }, + { "srp-use-pseudonym", o_bool, &eap_states[0].es_usepseudo, + "Use pseudonym if offered one by server", 1 }, +#endif + { NULL } +}; +#endif /* PPP_OPTIONS */ + +/* + * Protocol entry points. + */ +static void eap_init(ppp_pcb *pcb); +static void eap_input(ppp_pcb *pcb, u_char *inp, int inlen); +static void eap_protrej(ppp_pcb *pcb); +static void eap_lowerup(ppp_pcb *pcb); +static void eap_lowerdown(ppp_pcb *pcb); +#if PRINTPKT_SUPPORT +static int eap_printpkt(u_char *inp, int inlen, + void (*)(void *arg, const char *fmt, ...), void *arg); +#endif /* PRINTPKT_SUPPORT */ + +const struct protent eap_protent = { + PPP_EAP, /* protocol number */ + eap_init, /* initialization procedure */ + eap_input, /* process a received packet */ + eap_protrej, /* process a received protocol-reject */ + eap_lowerup, /* lower layer has gone up */ + eap_lowerdown, /* lower layer has gone down */ + NULL, /* open the protocol */ + NULL, /* close the protocol */ +#if PRINTPKT_SUPPORT + eap_printpkt, /* print a packet in readable form */ +#endif /* PRINTPKT_SUPPORT */ + NULL, /* process a received data packet */ + 1, /* protocol enabled */ +#if PRINTPKT_SUPPORT + "EAP", /* text name of protocol */ + NULL, /* text name of corresponding data protocol */ +#endif /* PRINTPKT_SUPPORT */ +#if PPP_OPTIONS + eap_option_list, /* list of command-line options */ + NULL, /* check requested options; assign defaults */ +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT + NULL, /* configure interface for demand-dial */ + NULL /* say whether to bring up link for this pkt */ +#endif /* DEMAND_SUPPORT */ +}; + +#ifdef USE_SRP +/* + * A well-known 2048 bit modulus. + */ +static const u_char wkmodulus[] = { + 0xAC, 0x6B, 0xDB, 0x41, 0x32, 0x4A, 0x9A, 0x9B, + 0xF1, 0x66, 0xDE, 0x5E, 0x13, 0x89, 0x58, 0x2F, + 0xAF, 0x72, 0xB6, 0x65, 0x19, 0x87, 0xEE, 0x07, + 0xFC, 0x31, 0x92, 0x94, 0x3D, 0xB5, 0x60, 0x50, + 0xA3, 0x73, 0x29, 0xCB, 0xB4, 0xA0, 0x99, 0xED, + 0x81, 0x93, 0xE0, 0x75, 0x77, 0x67, 0xA1, 0x3D, + 0xD5, 0x23, 0x12, 0xAB, 0x4B, 0x03, 0x31, 0x0D, + 0xCD, 0x7F, 0x48, 0xA9, 0xDA, 0x04, 0xFD, 0x50, + 0xE8, 0x08, 0x39, 0x69, 0xED, 0xB7, 0x67, 0xB0, + 0xCF, 0x60, 0x95, 0x17, 0x9A, 0x16, 0x3A, 0xB3, + 0x66, 0x1A, 0x05, 0xFB, 0xD5, 0xFA, 0xAA, 0xE8, + 0x29, 0x18, 0xA9, 0x96, 0x2F, 0x0B, 0x93, 0xB8, + 0x55, 0xF9, 0x79, 0x93, 0xEC, 0x97, 0x5E, 0xEA, + 0xA8, 0x0D, 0x74, 0x0A, 0xDB, 0xF4, 0xFF, 0x74, + 0x73, 0x59, 0xD0, 0x41, 0xD5, 0xC3, 0x3E, 0xA7, + 0x1D, 0x28, 0x1E, 0x44, 0x6B, 0x14, 0x77, 0x3B, + 0xCA, 0x97, 0xB4, 0x3A, 0x23, 0xFB, 0x80, 0x16, + 0x76, 0xBD, 0x20, 0x7A, 0x43, 0x6C, 0x64, 0x81, + 0xF1, 0xD2, 0xB9, 0x07, 0x87, 0x17, 0x46, 0x1A, + 0x5B, 0x9D, 0x32, 0xE6, 0x88, 0xF8, 0x77, 0x48, + 0x54, 0x45, 0x23, 0xB5, 0x24, 0xB0, 0xD5, 0x7D, + 0x5E, 0xA7, 0x7A, 0x27, 0x75, 0xD2, 0xEC, 0xFA, + 0x03, 0x2C, 0xFB, 0xDB, 0xF5, 0x2F, 0xB3, 0x78, + 0x61, 0x60, 0x27, 0x90, 0x04, 0xE5, 0x7A, 0xE6, + 0xAF, 0x87, 0x4E, 0x73, 0x03, 0xCE, 0x53, 0x29, + 0x9C, 0xCC, 0x04, 0x1C, 0x7B, 0xC3, 0x08, 0xD8, + 0x2A, 0x56, 0x98, 0xF3, 0xA8, 0xD0, 0xC3, 0x82, + 0x71, 0xAE, 0x35, 0xF8, 0xE9, 0xDB, 0xFB, 0xB6, + 0x94, 0xB5, 0xC8, 0x03, 0xD8, 0x9F, 0x7A, 0xE4, + 0x35, 0xDE, 0x23, 0x6D, 0x52, 0x5F, 0x54, 0x75, + 0x9B, 0x65, 0xE3, 0x72, 0xFC, 0xD6, 0x8E, 0xF2, + 0x0F, 0xA7, 0x11, 0x1F, 0x9E, 0x4A, 0xFF, 0x73 +}; +#endif + +#if PPP_SERVER +/* Local forward declarations. */ +static void eap_server_timeout(void *arg); +#endif /* PPP_SERVER */ + +/* + * Convert EAP state code to printable string for debug. + */ +static const char * eap_state_name(enum eap_state_code esc) +{ + static const char *state_names[] = { EAP_STATES }; + + return (state_names[(int)esc]); +} + +/* + * eap_init - Initialize state for an EAP user. This is currently + * called once by main() during start-up. + */ +static void eap_init(ppp_pcb *pcb) { + + BZERO(&pcb->eap, sizeof(eap_state)); +#if PPP_SERVER + pcb->eap.es_server.ea_id = (u_char)(drand48() * 0x100); /* FIXME: use magic.c random function */ +#endif /* PPP_SERVER */ +} + +/* + * eap_client_timeout - Give up waiting for the peer to send any + * Request messages. + */ +static void eap_client_timeout(void *arg) { + ppp_pcb *pcb = (ppp_pcb*)arg; + + if (!eap_client_active(pcb)) + return; + + ppp_error("EAP: timeout waiting for Request from peer"); + auth_withpeer_fail(pcb, PPP_EAP); + pcb->eap.es_client.ea_state = eapBadAuth; +} + +/* + * eap_authwithpeer - Authenticate to our peer (behave as client). + * + * Start client state and wait for requests. This is called only + * after eap_lowerup. + */ +void eap_authwithpeer(ppp_pcb *pcb, const char *localname) { + + if(NULL == localname) + return; + + /* Save the peer name we're given */ + pcb->eap.es_client.ea_name = localname; + pcb->eap.es_client.ea_namelen = strlen(localname); + + pcb->eap.es_client.ea_state = eapListen; + + /* + * Start a timer so that if the other end just goes + * silent, we don't sit here waiting forever. + */ + if (pcb->settings.eap_req_time > 0) + TIMEOUT(eap_client_timeout, pcb, + pcb->settings.eap_req_time); +} + +#if PPP_SERVER +/* + * Format a standard EAP Failure message and send it to the peer. + * (Server operation) + */ +static void eap_send_failure(ppp_pcb *pcb) { + struct pbuf *p; + u_char *outp; + + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + EAP_HEADERLEN), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = (u_char*)p->payload; + + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_FAILURE, outp); + pcb->eap.es_server.ea_id++; + PUTCHAR(pcb->eap.es_server.ea_id, outp); + PUTSHORT(EAP_HEADERLEN, outp); + + ppp_write(pcb, p); + + pcb->eap.es_server.ea_state = eapBadAuth; + auth_peer_fail(pcb, PPP_EAP); +} + +/* + * Format a standard EAP Success message and send it to the peer. + * (Server operation) + */ +static void eap_send_success(ppp_pcb *pcb) { + struct pbuf *p; + u_char *outp; + + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + EAP_HEADERLEN), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = (u_char*)p->payload; + + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_SUCCESS, outp); + pcb->eap.es_server.ea_id++; + PUTCHAR(pcb->eap.es_server.ea_id, outp); + PUTSHORT(EAP_HEADERLEN, outp); + + ppp_write(pcb, p); + + auth_peer_success(pcb, PPP_EAP, 0, + pcb->eap.es_server.ea_peer, pcb->eap.es_server.ea_peerlen); +} +#endif /* PPP_SERVER */ + +#ifdef USE_SRP +/* + * Set DES key according to pseudonym-generating secret and current + * date. + */ +static bool +pncrypt_setkey(int timeoffs) +{ + struct tm *tp; + char tbuf[9]; + SHA1_CTX ctxt; + u_char dig[SHA_DIGESTSIZE]; + time_t reftime; + + if (pn_secret == NULL) + return (0); + reftime = time(NULL) + timeoffs; + tp = localtime(&reftime); + SHA1Init(&ctxt); + SHA1Update(&ctxt, pn_secret, strlen(pn_secret)); + strftime(tbuf, sizeof (tbuf), "%Y%m%d", tp); + SHA1Update(&ctxt, tbuf, strlen(tbuf)); + SHA1Final(dig, &ctxt); + /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ + return (DesSetkey(dig)); +} + +static char base64[] = +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +struct b64state { + u32_t bs_bits; + int bs_offs; +}; + +static int +b64enc(bs, inp, inlen, outp) +struct b64state *bs; +u_char *inp; +int inlen; +u_char *outp; +{ + int outlen = 0; + + while (inlen > 0) { + bs->bs_bits = (bs->bs_bits << 8) | *inp++; + inlen--; + bs->bs_offs += 8; + if (bs->bs_offs >= 24) { + *outp++ = base64[(bs->bs_bits >> 18) & 0x3F]; + *outp++ = base64[(bs->bs_bits >> 12) & 0x3F]; + *outp++ = base64[(bs->bs_bits >> 6) & 0x3F]; + *outp++ = base64[bs->bs_bits & 0x3F]; + outlen += 4; + bs->bs_offs = 0; + bs->bs_bits = 0; + } + } + return (outlen); +} + +static int +b64flush(bs, outp) +struct b64state *bs; +u_char *outp; +{ + int outlen = 0; + + if (bs->bs_offs == 8) { + *outp++ = base64[(bs->bs_bits >> 2) & 0x3F]; + *outp++ = base64[(bs->bs_bits << 4) & 0x3F]; + outlen = 2; + } else if (bs->bs_offs == 16) { + *outp++ = base64[(bs->bs_bits >> 10) & 0x3F]; + *outp++ = base64[(bs->bs_bits >> 4) & 0x3F]; + *outp++ = base64[(bs->bs_bits << 2) & 0x3F]; + outlen = 3; + } + bs->bs_offs = 0; + bs->bs_bits = 0; + return (outlen); +} + +static int +b64dec(bs, inp, inlen, outp) +struct b64state *bs; +u_char *inp; +int inlen; +u_char *outp; +{ + int outlen = 0; + char *cp; + + while (inlen > 0) { + if ((cp = strchr(base64, *inp++)) == NULL) + break; + bs->bs_bits = (bs->bs_bits << 6) | (cp - base64); + inlen--; + bs->bs_offs += 6; + if (bs->bs_offs >= 8) { + *outp++ = bs->bs_bits >> (bs->bs_offs - 8); + outlen++; + bs->bs_offs -= 8; + } + } + return (outlen); +} +#endif /* USE_SRP */ + +#if PPP_SERVER +/* + * Assume that current waiting server state is complete and figure + * next state to use based on available authentication data. 'status' + * indicates if there was an error in handling the last query. It is + * 0 for success and non-zero for failure. + */ +static void eap_figure_next_state(ppp_pcb *pcb, int status) { +#ifdef USE_SRP + unsigned char secbuf[MAXWORDLEN], clear[8], *sp, *dp; + struct t_pw tpw; + struct t_confent *tce, mytce; + char *cp, *cp2; + struct t_server *ts; + int id, i, plen, toffs; + u_char vals[2]; + struct b64state bs; +#endif /* USE_SRP */ + + pcb->settings.eap_timeout_time = pcb->eap.es_savedtime; + switch (pcb->eap.es_server.ea_state) { + case eapBadAuth: + return; + + case eapIdentify: +#ifdef USE_SRP + /* Discard any previous session. */ + ts = (struct t_server *)pcb->eap.es_server.ea_session; + if (ts != NULL) { + t_serverclose(ts); + pcb->eap.es_server.ea_session = NULL; + pcb->eap.es_server.ea_skey = NULL; + } +#endif /* USE_SRP */ + if (status != 0) { + pcb->eap.es_server.ea_state = eapBadAuth; + break; + } +#ifdef USE_SRP + /* If we've got a pseudonym, try to decode to real name. */ + if (pcb->eap.es_server.ea_peerlen > SRP_PSEUDO_LEN && + strncmp(pcb->eap.es_server.ea_peer, SRP_PSEUDO_ID, + SRP_PSEUDO_LEN) == 0 && + (pcb->eap.es_server.ea_peerlen - SRP_PSEUDO_LEN) * 3 / 4 < + sizeof (secbuf)) { + BZERO(&bs, sizeof (bs)); + plen = b64dec(&bs, + pcb->eap.es_server.ea_peer + SRP_PSEUDO_LEN, + pcb->eap.es_server.ea_peerlen - SRP_PSEUDO_LEN, + secbuf); + toffs = 0; + for (i = 0; i < 5; i++) { + pncrypt_setkey(toffs); + toffs -= 86400; + /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ + if (!DesDecrypt(secbuf, clear)) { + ppp_dbglog("no DES here; cannot decode " + "pseudonym"); + return; + } + id = *(unsigned char *)clear; + if (id + 1 <= plen && id + 9 > plen) + break; + } + if (plen % 8 == 0 && i < 5) { + /* + * Note that this is always shorter than the + * original stored string, so there's no need + * to realloc. + */ + if ((i = plen = *(unsigned char *)clear) > 7) + i = 7; + pcb->eap.es_server.ea_peerlen = plen; + dp = (unsigned char *)pcb->eap.es_server.ea_peer; + MEMCPY(dp, clear + 1, i); + plen -= i; + dp += i; + sp = secbuf + 8; + while (plen > 0) { + /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ + (void) DesDecrypt(sp, dp); + sp += 8; + dp += 8; + plen -= 8; + } + pcb->eap.es_server.ea_peer[ + pcb->eap.es_server.ea_peerlen] = '\0'; + ppp_dbglog("decoded pseudonym to \"%.*q\"", + pcb->eap.es_server.ea_peerlen, + pcb->eap.es_server.ea_peer); + } else { + ppp_dbglog("failed to decode real name"); + /* Stay in eapIdentfy state; requery */ + break; + } + } + /* Look up user in secrets database. */ + if (get_srp_secret(pcb->eap.es_unit, pcb->eap.es_server.ea_peer, + pcb->eap.es_server.ea_name, (char *)secbuf, 1) != 0) { + /* Set up default in case SRP entry is bad */ + pcb->eap.es_server.ea_state = eapMD5Chall; + /* Get t_confent based on index in srp-secrets */ + id = strtol((char *)secbuf, &cp, 10); + if (*cp++ != ':' || id < 0) + break; + if (id == 0) { + mytce.index = 0; + mytce.modulus.data = (u_char *)wkmodulus; + mytce.modulus.len = sizeof (wkmodulus); + mytce.generator.data = (u_char *)"\002"; + mytce.generator.len = 1; + tce = &mytce; + } else if ((tce = gettcid(id)) != NULL) { + /* + * Client will have to verify this modulus/ + * generator combination, and that will take + * a while. Lengthen the timeout here. + */ + if (pcb->settings.eap_timeout_time > 0 && + pcb->settings.eap_timeout_time < 30) + pcb->settings.eap_timeout_time = 30; + } else { + break; + } + if ((cp2 = strchr(cp, ':')) == NULL) + break; + *cp2++ = '\0'; + tpw.pebuf.name = pcb->eap.es_server.ea_peer; + tpw.pebuf.password.len = t_fromb64((char *)tpw.pwbuf, + cp); + tpw.pebuf.password.data = tpw.pwbuf; + tpw.pebuf.salt.len = t_fromb64((char *)tpw.saltbuf, + cp2); + tpw.pebuf.salt.data = tpw.saltbuf; + if ((ts = t_serveropenraw(&tpw.pebuf, tce)) == NULL) + break; + pcb->eap.es_server.ea_session = (void *)ts; + pcb->eap.es_server.ea_state = eapSRP1; + vals[0] = pcb->eap.es_server.ea_id + 1; + vals[1] = EAPT_SRP; + t_serveraddexdata(ts, vals, 2); + /* Generate B; must call before t_servergetkey() */ + t_servergenexp(ts); + break; + } +#endif /* USE_SRP */ + pcb->eap.es_server.ea_state = eapMD5Chall; + break; + + case eapSRP1: +#ifdef USE_SRP + ts = (struct t_server *)pcb->eap.es_server.ea_session; + if (ts != NULL && status != 0) { + t_serverclose(ts); + pcb->eap.es_server.ea_session = NULL; + pcb->eap.es_server.ea_skey = NULL; + } +#endif /* USE_SRP */ + if (status == 1) { + pcb->eap.es_server.ea_state = eapMD5Chall; + } else if (status != 0 || pcb->eap.es_server.ea_session == NULL) { + pcb->eap.es_server.ea_state = eapBadAuth; + } else { + pcb->eap.es_server.ea_state = eapSRP2; + } + break; + + case eapSRP2: +#ifdef USE_SRP + ts = (struct t_server *)pcb->eap.es_server.ea_session; + if (ts != NULL && status != 0) { + t_serverclose(ts); + pcb->eap.es_server.ea_session = NULL; + pcb->eap.es_server.ea_skey = NULL; + } +#endif /* USE_SRP */ + if (status != 0 || pcb->eap.es_server.ea_session == NULL) { + pcb->eap.es_server.ea_state = eapBadAuth; + } else { + pcb->eap.es_server.ea_state = eapSRP3; + } + break; + + case eapSRP3: + case eapSRP4: +#ifdef USE_SRP + ts = (struct t_server *)pcb->eap.es_server.ea_session; + if (ts != NULL && status != 0) { + t_serverclose(ts); + pcb->eap.es_server.ea_session = NULL; + pcb->eap.es_server.ea_skey = NULL; + } +#endif /* USE_SRP */ + if (status != 0 || pcb->eap.es_server.ea_session == NULL) { + pcb->eap.es_server.ea_state = eapBadAuth; + } else { + pcb->eap.es_server.ea_state = eapOpen; + } + break; + + case eapMD5Chall: + if (status != 0) { + pcb->eap.es_server.ea_state = eapBadAuth; + } else { + pcb->eap.es_server.ea_state = eapOpen; + } + break; + + default: + pcb->eap.es_server.ea_state = eapBadAuth; + break; + } + if (pcb->eap.es_server.ea_state == eapBadAuth) + eap_send_failure(pcb); +} + +/* + * Format an EAP Request message and send it to the peer. Message + * type depends on current state. (Server operation) + */ +static void eap_send_request(ppp_pcb *pcb) { + struct pbuf *p; + u_char *outp; + u_char *lenloc; + u_char *ptr; + int outlen; + int challen; + const char *str; +#ifdef USE_SRP + struct t_server *ts; + u_char clear[8], cipher[8], dig[SHA_DIGESTSIZE], *optr, *cp; + int i, j; + struct b64state b64; + SHA1_CTX ctxt; +#endif /* USE_SRP */ + + /* Handle both initial auth and restart */ + if (pcb->eap.es_server.ea_state < eapIdentify && + pcb->eap.es_server.ea_state != eapInitial) { + pcb->eap.es_server.ea_state = eapIdentify; +#if PPP_REMOTENAME + if (pcb->settings.explicit_remote) { + /* + * If we already know the peer's + * unauthenticated name, then there's no + * reason to ask. Go to next state instead. + */ + pcb->eap.es_server.ea_peer = pcb->remote_name; + pcb->eap.es_server.ea_peerlen = strlen(pcb->remote_name); + eap_figure_next_state(pcb, 0); + } +#endif /* PPP_REMOTENAME */ + } + + if (pcb->settings.eap_max_transmits > 0 && + pcb->eap.es_server.ea_requests >= pcb->settings.eap_max_transmits) { + if (pcb->eap.es_server.ea_responses > 0) + ppp_error("EAP: too many Requests sent"); + else + ppp_error("EAP: no response to Requests"); + eap_send_failure(pcb); + return; + } + + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_CTRL_PBUF_MAX_SIZE), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = (u_char*)p->payload; + + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_REQUEST, outp); + PUTCHAR(pcb->eap.es_server.ea_id, outp); + lenloc = outp; + INCPTR(2, outp); + + switch (pcb->eap.es_server.ea_state) { + case eapIdentify: + PUTCHAR(EAPT_IDENTITY, outp); + str = "Name"; + challen = strlen(str); + MEMCPY(outp, str, challen); + INCPTR(challen, outp); + break; + + case eapMD5Chall: + PUTCHAR(EAPT_MD5CHAP, outp); + /* + * pick a random challenge length between + * EAP_MIN_CHALLENGE_LENGTH and EAP_MAX_CHALLENGE_LENGTH + */ + challen = (drand48() * + (EAP_MAX_CHALLENGE_LENGTH - EAP_MIN_CHALLENGE_LENGTH)) + + EAP_MIN_CHALLENGE_LENGTH; + PUTCHAR(challen, outp); + pcb->eap.es_challen = challen; + ptr = pcb->eap.es_challenge; + while (--challen >= 0) + *ptr++ = (u_char) (drand48() * 0x100); + MEMCPY(outp, pcb->eap.es_challenge, pcb->eap.es_challen); + INCPTR(pcb->eap.es_challen, outp); + MEMCPY(outp, pcb->eap.es_server.ea_name, pcb->eap.es_server.ea_namelen); + INCPTR(pcb->eap.es_server.ea_namelen, outp); + break; + +#ifdef USE_SRP + case eapSRP1: + PUTCHAR(EAPT_SRP, outp); + PUTCHAR(EAPSRP_CHALLENGE, outp); + + PUTCHAR(pcb->eap.es_server.ea_namelen, outp); + MEMCPY(outp, pcb->eap.es_server.ea_name, pcb->eap.es_server.ea_namelen); + INCPTR(pcb->eap.es_server.ea_namelen, outp); + + ts = (struct t_server *)pcb->eap.es_server.ea_session; + assert(ts != NULL); + PUTCHAR(ts->s.len, outp); + MEMCPY(outp, ts->s.data, ts->s.len); + INCPTR(ts->s.len, outp); + + if (ts->g.len == 1 && ts->g.data[0] == 2) { + PUTCHAR(0, outp); + } else { + PUTCHAR(ts->g.len, outp); + MEMCPY(outp, ts->g.data, ts->g.len); + INCPTR(ts->g.len, outp); + } + + if (ts->n.len != sizeof (wkmodulus) || + BCMP(ts->n.data, wkmodulus, sizeof (wkmodulus)) != 0) { + MEMCPY(outp, ts->n.data, ts->n.len); + INCPTR(ts->n.len, outp); + } + break; + + case eapSRP2: + PUTCHAR(EAPT_SRP, outp); + PUTCHAR(EAPSRP_SKEY, outp); + + ts = (struct t_server *)pcb->eap.es_server.ea_session; + assert(ts != NULL); + MEMCPY(outp, ts->B.data, ts->B.len); + INCPTR(ts->B.len, outp); + break; + + case eapSRP3: + PUTCHAR(EAPT_SRP, outp); + PUTCHAR(EAPSRP_SVALIDATOR, outp); + PUTLONG(SRPVAL_EBIT, outp); + ts = (struct t_server *)pcb->eap.es_server.ea_session; + assert(ts != NULL); + MEMCPY(outp, t_serverresponse(ts), SHA_DIGESTSIZE); + INCPTR(SHA_DIGESTSIZE, outp); + + if (pncrypt_setkey(0)) { + /* Generate pseudonym */ + optr = outp; + cp = (unsigned char *)pcb->eap.es_server.ea_peer; + if ((j = i = pcb->eap.es_server.ea_peerlen) > 7) + j = 7; + clear[0] = i; + MEMCPY(clear + 1, cp, j); + i -= j; + cp += j; + /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ + if (!DesEncrypt(clear, cipher)) { + ppp_dbglog("no DES here; not generating pseudonym"); + break; + } + BZERO(&b64, sizeof (b64)); + outp++; /* space for pseudonym length */ + outp += b64enc(&b64, cipher, 8, outp); + while (i >= 8) { + /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ + (void) DesEncrypt(cp, cipher); + outp += b64enc(&b64, cipher, 8, outp); + cp += 8; + i -= 8; + } + if (i > 0) { + MEMCPY(clear, cp, i); + cp += i; + while (i < 8) { + *cp++ = drand48() * 0x100; + i++; + } + /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ + (void) DesEncrypt(clear, cipher); + outp += b64enc(&b64, cipher, 8, outp); + } + outp += b64flush(&b64, outp); + + /* Set length and pad out to next 20 octet boundary */ + i = outp - optr - 1; + *optr = i; + i %= SHA_DIGESTSIZE; + if (i != 0) { + while (i < SHA_DIGESTSIZE) { + *outp++ = drand48() * 0x100; + i++; + } + } + + /* Obscure the pseudonym with SHA1 hash */ + SHA1Init(&ctxt); + SHA1Update(&ctxt, &pcb->eap.es_server.ea_id, 1); + SHA1Update(&ctxt, pcb->eap.es_server.ea_skey, + SESSION_KEY_LEN); + SHA1Update(&ctxt, pcb->eap.es_server.ea_peer, + pcb->eap.es_server.ea_peerlen); + while (optr < outp) { + SHA1Final(dig, &ctxt); + cp = dig; + while (cp < dig + SHA_DIGESTSIZE) + *optr++ ^= *cp++; + SHA1Init(&ctxt); + SHA1Update(&ctxt, &pcb->eap.es_server.ea_id, 1); + SHA1Update(&ctxt, pcb->eap.es_server.ea_skey, + SESSION_KEY_LEN); + SHA1Update(&ctxt, optr - SHA_DIGESTSIZE, + SHA_DIGESTSIZE); + } + } + break; + + case eapSRP4: + PUTCHAR(EAPT_SRP, outp); + PUTCHAR(EAPSRP_LWRECHALLENGE, outp); + challen = EAP_MIN_CHALLENGE_LENGTH + + ((EAP_MAX_CHALLENGE_LENGTH - EAP_MIN_CHALLENGE_LENGTH) * drand48()); + pcb->eap.es_challen = challen; + ptr = pcb->eap.es_challenge; + while (--challen >= 0) + *ptr++ = drand48() * 0x100; + MEMCPY(outp, pcb->eap.es_challenge, pcb->eap.es_challen); + INCPTR(pcb->eap.es_challen, outp); + break; +#endif /* USE_SRP */ + + default: + return; + } + + outlen = (outp - (unsigned char*)p->payload) - PPP_HDRLEN; + PUTSHORT(outlen, lenloc); + + pbuf_realloc(p, outlen + PPP_HDRLEN); + ppp_write(pcb, p); + + pcb->eap.es_server.ea_requests++; + + if (pcb->settings.eap_timeout_time > 0) + TIMEOUT(eap_server_timeout, pcb, pcb->settings.eap_timeout_time); +} + +/* + * eap_authpeer - Authenticate our peer (behave as server). + * + * Start server state and send first request. This is called only + * after eap_lowerup. + */ +void eap_authpeer(ppp_pcb *pcb, const char *localname) { + + /* Save the name we're given. */ + pcb->eap.es_server.ea_name = localname; + pcb->eap.es_server.ea_namelen = strlen(localname); + + pcb->eap.es_savedtime = pcb->settings.eap_timeout_time; + + /* Lower layer up yet? */ + if (pcb->eap.es_server.ea_state == eapInitial || + pcb->eap.es_server.ea_state == eapPending) { + pcb->eap.es_server.ea_state = eapPending; + return; + } + + pcb->eap.es_server.ea_state = eapPending; + + /* ID number not updated here intentionally; hashed into M1 */ + eap_send_request(pcb); +} + +/* + * eap_server_timeout - Retransmission timer for sending Requests + * expired. + */ +static void eap_server_timeout(void *arg) { + ppp_pcb *pcb = (ppp_pcb*)arg; + + if (!eap_server_active(pcb)) + return; + + /* EAP ID number must not change on timeout. */ + eap_send_request(pcb); +} + +/* + * When it's time to send rechallenge the peer, this timeout is + * called. Once the rechallenge is successful, the response handler + * will restart the timer. If it fails, then the link is dropped. + */ +static void eap_rechallenge(void *arg) { + ppp_pcb *pcb = (ppp_pcb*)arg; + + if (pcb->eap.es_server.ea_state != eapOpen && + pcb->eap.es_server.ea_state != eapSRP4) + return; + + pcb->eap.es_server.ea_requests = 0; + pcb->eap.es_server.ea_state = eapIdentify; + eap_figure_next_state(pcb, 0); + pcb->eap.es_server.ea_id++; + eap_send_request(pcb); +} + +static void srp_lwrechallenge(void *arg) { + ppp_pcb *pcb = (ppp_pcb*)arg; + + if (pcb->eap.es_server.ea_state != eapOpen || + pcb->eap.es_server.ea_type != EAPT_SRP) + return; + + pcb->eap.es_server.ea_requests = 0; + pcb->eap.es_server.ea_state = eapSRP4; + pcb->eap.es_server.ea_id++; + eap_send_request(pcb); +} +#endif /* PPP_SERVER */ + +/* + * eap_lowerup - The lower layer is now up. + * + * This is called before either eap_authpeer or eap_authwithpeer. See + * link_established() in auth.c. All that's necessary here is to + * return to closed state so that those two routines will do the right + * thing. + */ +static void eap_lowerup(ppp_pcb *pcb) { + + /* Discard any (possibly authenticated) peer name. */ +#if PPP_SERVER + if (pcb->eap.es_server.ea_peer != NULL +#if PPP_REMOTENAME + && pcb->eap.es_server.ea_peer != pcb->remote_name +#endif /* PPP_REMOTENAME */ + ) + free(pcb->eap.es_server.ea_peer); + pcb->eap.es_server.ea_peer = NULL; +#endif /* PPP_SERVER */ + if (pcb->eap.es_client.ea_peer != NULL) + free(pcb->eap.es_client.ea_peer); + pcb->eap.es_client.ea_peer = NULL; + + pcb->eap.es_client.ea_state = eapClosed; +#if PPP_SERVER + pcb->eap.es_server.ea_state = eapClosed; +#endif /* PPP_SERVER */ +} + +/* + * eap_lowerdown - The lower layer is now down. + * + * Cancel all timeouts and return to initial state. + */ +static void eap_lowerdown(ppp_pcb *pcb) { + + if (eap_client_active(pcb) && pcb->settings.eap_req_time > 0) { + UNTIMEOUT(eap_client_timeout, pcb); + } +#if PPP_SERVER + if (eap_server_active(pcb)) { + if (pcb->settings.eap_timeout_time > 0) { + UNTIMEOUT(eap_server_timeout, pcb); + } + } else { + if ((pcb->eap.es_server.ea_state == eapOpen || + pcb->eap.es_server.ea_state == eapSRP4) && + pcb->eap.es_rechallenge > 0) { + UNTIMEOUT(eap_rechallenge, (void *)pcb); + } + if (pcb->eap.es_server.ea_state == eapOpen && + pcb->eap.es_lwrechallenge > 0) { + UNTIMEOUT(srp_lwrechallenge, (void *)pcb); + } + } + + pcb->eap.es_client.ea_state = pcb->eap.es_server.ea_state = eapInitial; + pcb->eap.es_client.ea_requests = pcb->eap.es_server.ea_requests = 0; +#endif /* PPP_SERVER */ +} + +/* + * eap_protrej - Peer doesn't speak this protocol. + * + * This shouldn't happen. If it does, it represents authentication + * failure. + */ +static void eap_protrej(ppp_pcb *pcb) { + + if (eap_client_active(pcb)) { + ppp_error("EAP authentication failed due to Protocol-Reject"); + auth_withpeer_fail(pcb, PPP_EAP); + } +#if PPP_SERVER + if (eap_server_active(pcb)) { + ppp_error("EAP authentication of peer failed on Protocol-Reject"); + auth_peer_fail(pcb, PPP_EAP); + } +#endif /* PPP_SERVER */ + eap_lowerdown(pcb); +} + +/* + * Format and send a regular EAP Response message. + */ +static void eap_send_response(ppp_pcb *pcb, u_char id, u_char typenum, u_char *str, int lenstr) { + struct pbuf *p; + u_char *outp; + int msglen; + + msglen = EAP_HEADERLEN + sizeof (u_char) + lenstr; + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = (u_char*)p->payload; + + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_RESPONSE, outp); + PUTCHAR(id, outp); + pcb->eap.es_client.ea_id = id; + PUTSHORT(msglen, outp); + PUTCHAR(typenum, outp); + if (lenstr > 0) { + MEMCPY(outp, str, lenstr); + } + + ppp_write(pcb, p); +} + +/* + * Format and send an MD5-Challenge EAP Response message. + */ +static void eap_chap_response(ppp_pcb *pcb, u_char id, u_char *hash, const char *name, int namelen) { + struct pbuf *p; + u_char *outp; + int msglen; + + msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + MD5_SIGNATURE_SIZE + + namelen; + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = (u_char*)p->payload; + + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_RESPONSE, outp); + PUTCHAR(id, outp); + pcb->eap.es_client.ea_id = id; + PUTSHORT(msglen, outp); + PUTCHAR(EAPT_MD5CHAP, outp); + PUTCHAR(MD5_SIGNATURE_SIZE, outp); + MEMCPY(outp, hash, MD5_SIGNATURE_SIZE); + INCPTR(MD5_SIGNATURE_SIZE, outp); + if (namelen > 0) { + MEMCPY(outp, name, namelen); + } + + ppp_write(pcb, p); +} + +#ifdef USE_SRP +/* + * Format and send a SRP EAP Response message. + */ +static void +eap_srp_response(esp, id, subtypenum, str, lenstr) +eap_state *esp; +u_char id; +u_char subtypenum; +u_char *str; +int lenstr; +{ + ppp_pcb *pcb = &ppp_pcb_list[pcb->eap.es_unit]; + struct pbuf *p; + u_char *outp; + int msglen; + + msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + lenstr; + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = p->payload; + + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_RESPONSE, outp); + PUTCHAR(id, outp); + pcb->eap.es_client.ea_id = id; + PUTSHORT(msglen, outp); + PUTCHAR(EAPT_SRP, outp); + PUTCHAR(subtypenum, outp); + if (lenstr > 0) { + MEMCPY(outp, str, lenstr); + } + + ppp_write(pcb, p); +} + +/* + * Format and send a SRP EAP Client Validator Response message. + */ +static void +eap_srpval_response(esp, id, flags, str) +eap_state *esp; +u_char id; +u32_t flags; +u_char *str; +{ + ppp_pcb *pcb = &ppp_pcb_list[pcb->eap.es_unit]; + struct pbuf *p; + u_char *outp; + int msglen; + + msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + sizeof (u32_t) + + SHA_DIGESTSIZE; + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = p->payload; + + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_RESPONSE, outp); + PUTCHAR(id, outp); + pcb->eap.es_client.ea_id = id; + PUTSHORT(msglen, outp); + PUTCHAR(EAPT_SRP, outp); + PUTCHAR(EAPSRP_CVALIDATOR, outp); + PUTLONG(flags, outp); + MEMCPY(outp, str, SHA_DIGESTSIZE); + + ppp_write(pcb, p); +} +#endif /* USE_SRP */ + +static void eap_send_nak(ppp_pcb *pcb, u_char id, u_char type) { + struct pbuf *p; + u_char *outp; + int msglen; + + msglen = EAP_HEADERLEN + 2 * sizeof (u_char); + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = (u_char*)p->payload; + + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_RESPONSE, outp); + PUTCHAR(id, outp); + pcb->eap.es_client.ea_id = id; + PUTSHORT(msglen, outp); + PUTCHAR(EAPT_NAK, outp); + PUTCHAR(type, outp); + + ppp_write(pcb, p); +} + +#ifdef USE_SRP +static char * +name_of_pn_file() +{ + char *user, *path, *file; + struct passwd *pw; + size_t pl; + static bool pnlogged = 0; + + pw = getpwuid(getuid()); + if (pw == NULL || (user = pw->pw_dir) == NULL || user[0] == 0) { + errno = EINVAL; + return (NULL); + } + file = _PATH_PSEUDONYM; + pl = strlen(user) + strlen(file) + 2; + path = malloc(pl); + if (path == NULL) + return (NULL); + (void) slprintf(path, pl, "%s/%s", user, file); + if (!pnlogged) { + ppp_dbglog("pseudonym file: %s", path); + pnlogged = 1; + } + return (path); +} + +static int +open_pn_file(modebits) +mode_t modebits; +{ + char *path; + int fd, err; + + if ((path = name_of_pn_file()) == NULL) + return (-1); + fd = open(path, modebits, S_IRUSR | S_IWUSR); + err = errno; + free(path); + errno = err; + return (fd); +} + +static void +remove_pn_file() +{ + char *path; + + if ((path = name_of_pn_file()) != NULL) { + (void) unlink(path); + (void) free(path); + } +} + +static void +write_pseudonym(esp, inp, len, id) +eap_state *esp; +u_char *inp; +int len, id; +{ + u_char val; + u_char *datp, *digp; + SHA1_CTX ctxt; + u_char dig[SHA_DIGESTSIZE]; + int dsize, fd, olen = len; + + /* + * Do the decoding by working backwards. This eliminates the need + * to save the decoded output in a separate buffer. + */ + val = id; + while (len > 0) { + if ((dsize = len % SHA_DIGESTSIZE) == 0) + dsize = SHA_DIGESTSIZE; + len -= dsize; + datp = inp + len; + SHA1Init(&ctxt); + SHA1Update(&ctxt, &val, 1); + SHA1Update(&ctxt, pcb->eap.es_client.ea_skey, SESSION_KEY_LEN); + if (len > 0) { + SHA1Update(&ctxt, datp, SHA_DIGESTSIZE); + } else { + SHA1Update(&ctxt, pcb->eap.es_client.ea_name, + pcb->eap.es_client.ea_namelen); + } + SHA1Final(dig, &ctxt); + for (digp = dig; digp < dig + SHA_DIGESTSIZE; digp++) + *datp++ ^= *digp; + } + + /* Now check that the result is sane */ + if (olen <= 0 || *inp + 1 > olen) { + ppp_dbglog("EAP: decoded pseudonym is unusable <%.*B>", olen, inp); + return; + } + + /* Save it away */ + fd = open_pn_file(O_WRONLY | O_CREAT | O_TRUNC); + if (fd < 0) { + ppp_dbglog("EAP: error saving pseudonym: %m"); + return; + } + len = write(fd, inp + 1, *inp); + if (close(fd) != -1 && len == *inp) { + ppp_dbglog("EAP: saved pseudonym"); + pcb->eap.es_usedpseudo = 0; + } else { + ppp_dbglog("EAP: failed to save pseudonym"); + remove_pn_file(); + } +} +#endif /* USE_SRP */ + +/* + * eap_request - Receive EAP Request message (client mode). + */ +static void eap_request(ppp_pcb *pcb, u_char *inp, int id, int len) { + u_char typenum; + u_char vallen; + int secret_len; + char secret[MAXWORDLEN]; + char rhostname[256]; + md5_context mdContext; + u_char hash[MD5_SIGNATURE_SIZE]; +#ifdef USE_SRP + struct t_client *tc; + struct t_num sval, gval, Nval, *Ap, Bval; + u_char vals[2]; + SHA1_CTX ctxt; + u_char dig[SHA_DIGESTSIZE]; + int fd; +#endif /* USE_SRP */ + + /* + * Note: we update es_client.ea_id *only if* a Response + * message is being generated. Otherwise, we leave it the + * same for duplicate detection purposes. + */ + + pcb->eap.es_client.ea_requests++; + if (pcb->settings.eap_allow_req != 0 && + pcb->eap.es_client.ea_requests > pcb->settings.eap_allow_req) { + ppp_info("EAP: received too many Request messages"); + if (pcb->settings.eap_req_time > 0) { + UNTIMEOUT(eap_client_timeout, pcb); + } + auth_withpeer_fail(pcb, PPP_EAP); + return; + } + + if (len <= 0) { + ppp_error("EAP: empty Request message discarded"); + return; + } + + GETCHAR(typenum, inp); + len--; + + switch (typenum) { + case EAPT_IDENTITY: + if (len > 0) + ppp_info("EAP: Identity prompt \"%.*q\"", len, inp); +#ifdef USE_SRP + if (pcb->eap.es_usepseudo && + (pcb->eap.es_usedpseudo == 0 || + (pcb->eap.es_usedpseudo == 1 && + id == pcb->eap.es_client.ea_id))) { + pcb->eap.es_usedpseudo = 1; + /* Try to get a pseudonym */ + if ((fd = open_pn_file(O_RDONLY)) >= 0) { + strcpy(rhostname, SRP_PSEUDO_ID); + len = read(fd, rhostname + SRP_PSEUDO_LEN, + sizeof (rhostname) - SRP_PSEUDO_LEN); + /* XXX NAI unsupported */ + if (len > 0) { + eap_send_response(pcb, id, typenum, + rhostname, len + SRP_PSEUDO_LEN); + } + (void) close(fd); + if (len > 0) + break; + } + } + /* Stop using pseudonym now. */ + if (pcb->eap.es_usepseudo && pcb->eap.es_usedpseudo != 2) { + remove_pn_file(); + pcb->eap.es_usedpseudo = 2; + } +#endif /* USE_SRP */ + eap_send_response(pcb, id, typenum, (u_char*)pcb->eap.es_client.ea_name, + pcb->eap.es_client.ea_namelen); + break; + + case EAPT_NOTIFICATION: + if (len > 0) + ppp_info("EAP: Notification \"%.*q\"", len, inp); + eap_send_response(pcb, id, typenum, NULL, 0); + break; + + case EAPT_NAK: + /* + * Avoid the temptation to send Response Nak in reply + * to Request Nak here. It can only lead to trouble. + */ + ppp_warn("EAP: unexpected Nak in Request; ignored"); + /* Return because we're waiting for something real. */ + return; + + case EAPT_MD5CHAP: + if (len < 1) { + ppp_error("EAP: received MD5-Challenge with no data"); + /* Bogus request; wait for something real. */ + return; + } + GETCHAR(vallen, inp); + len--; + if (vallen < 8 || vallen > len) { + ppp_error("EAP: MD5-Challenge with bad length %d (8..%d)", + vallen, len); + /* Try something better. */ + eap_send_nak(pcb, id, EAPT_SRP); + break; + } + + /* Not so likely to happen. */ + if (vallen >= len + sizeof (rhostname)) { + ppp_dbglog("EAP: trimming really long peer name down"); + MEMCPY(rhostname, inp + vallen, sizeof (rhostname) - 1); + rhostname[sizeof (rhostname) - 1] = '\0'; + } else { + MEMCPY(rhostname, inp + vallen, len - vallen); + rhostname[len - vallen] = '\0'; + } + +#if PPP_REMOTENAME + /* In case the remote doesn't give us his name. */ + if (pcb->settings.explicit_remote || + (pcb->settings.remote_name[0] != '\0' && vallen == len)) + strlcpy(rhostname, pcb->settings.remote_name, sizeof (rhostname)); +#endif /* PPP_REMOTENAME */ + + /* + * Get the secret for authenticating ourselves with + * the specified host. + */ + if (!get_secret(pcb, pcb->eap.es_client.ea_name, + rhostname, secret, &secret_len, 0)) { + ppp_dbglog("EAP: no MD5 secret for auth to %q", rhostname); + eap_send_nak(pcb, id, EAPT_SRP); + break; + } + md5_starts(&mdContext); + typenum = id; + md5_update(&mdContext, &typenum, 1); + md5_update(&mdContext, (u_char *)secret, secret_len); + BZERO(secret, sizeof (secret)); + md5_update(&mdContext, inp, vallen); + md5_finish(&mdContext, hash); + eap_chap_response(pcb, id, hash, pcb->eap.es_client.ea_name, + pcb->eap.es_client.ea_namelen); + break; + +#ifdef USE_SRP + case EAPT_SRP: + if (len < 1) { + ppp_error("EAP: received empty SRP Request"); + /* Bogus request; wait for something real. */ + return; + } + + /* Get subtype */ + GETCHAR(vallen, inp); + len--; + switch (vallen) { + case EAPSRP_CHALLENGE: + tc = NULL; + if (pcb->eap.es_client.ea_session != NULL) { + tc = (struct t_client *)pcb->eap.es_client. + ea_session; + /* + * If this is a new challenge, then start + * over with a new client session context. + * Otherwise, just resend last response. + */ + if (id != pcb->eap.es_client.ea_id) { + t_clientclose(tc); + pcb->eap.es_client.ea_session = NULL; + tc = NULL; + } + } + /* No session key just yet */ + pcb->eap.es_client.ea_skey = NULL; + if (tc == NULL) { + GETCHAR(vallen, inp); + len--; + if (vallen >= len) { + ppp_error("EAP: badly-formed SRP Challenge" + " (name)"); + /* Ignore badly-formed messages */ + return; + } + MEMCPY(rhostname, inp, vallen); + rhostname[vallen] = '\0'; + INCPTR(vallen, inp); + len -= vallen; + + /* + * In case the remote doesn't give us his name, + * use configured name. + */ + if (explicit_remote || + (remote_name[0] != '\0' && vallen == 0)) { + strlcpy(rhostname, remote_name, + sizeof (rhostname)); + } + + if (pcb->eap.es_client.ea_peer != NULL) + free(pcb->eap.es_client.ea_peer); + pcb->eap.es_client.ea_peer = strdup(rhostname); + pcb->eap.es_client.ea_peerlen = strlen(rhostname); + + GETCHAR(vallen, inp); + len--; + if (vallen >= len) { + ppp_error("EAP: badly-formed SRP Challenge" + " (s)"); + /* Ignore badly-formed messages */ + return; + } + sval.data = inp; + sval.len = vallen; + INCPTR(vallen, inp); + len -= vallen; + + GETCHAR(vallen, inp); + len--; + if (vallen > len) { + ppp_error("EAP: badly-formed SRP Challenge" + " (g)"); + /* Ignore badly-formed messages */ + return; + } + /* If no generator present, then use value 2 */ + if (vallen == 0) { + gval.data = (u_char *)"\002"; + gval.len = 1; + } else { + gval.data = inp; + gval.len = vallen; + } + INCPTR(vallen, inp); + len -= vallen; + + /* + * If no modulus present, then use well-known + * value. + */ + if (len == 0) { + Nval.data = (u_char *)wkmodulus; + Nval.len = sizeof (wkmodulus); + } else { + Nval.data = inp; + Nval.len = len; + } + tc = t_clientopen(pcb->eap.es_client.ea_name, + &Nval, &gval, &sval); + if (tc == NULL) { + eap_send_nak(pcb, id, EAPT_MD5CHAP); + break; + } + pcb->eap.es_client.ea_session = (void *)tc; + + /* Add Challenge ID & type to verifier */ + vals[0] = id; + vals[1] = EAPT_SRP; + t_clientaddexdata(tc, vals, 2); + } + Ap = t_clientgenexp(tc); + eap_srp_response(esp, id, EAPSRP_CKEY, Ap->data, + Ap->len); + break; + + case EAPSRP_SKEY: + tc = (struct t_client *)pcb->eap.es_client.ea_session; + if (tc == NULL) { + ppp_warn("EAP: peer sent Subtype 2 without 1"); + eap_send_nak(pcb, id, EAPT_MD5CHAP); + break; + } + if (pcb->eap.es_client.ea_skey != NULL) { + /* + * ID number should not change here. Warn + * if it does (but otherwise ignore). + */ + if (id != pcb->eap.es_client.ea_id) { + ppp_warn("EAP: ID changed from %d to %d " + "in SRP Subtype 2 rexmit", + pcb->eap.es_client.ea_id, id); + } + } else { + if (get_srp_secret(pcb->eap.es_unit, + pcb->eap.es_client.ea_name, + pcb->eap.es_client.ea_peer, secret, 0) == 0) { + /* + * Can't work with this peer because + * the secret is missing. Just give + * up. + */ + eap_send_nak(pcb, id, EAPT_MD5CHAP); + break; + } + Bval.data = inp; + Bval.len = len; + t_clientpasswd(tc, secret); + BZERO(secret, sizeof (secret)); + pcb->eap.es_client.ea_skey = + t_clientgetkey(tc, &Bval); + if (pcb->eap.es_client.ea_skey == NULL) { + /* Server is rogue; stop now */ + ppp_error("EAP: SRP server is rogue"); + goto client_failure; + } + } + eap_srpval_response(esp, id, SRPVAL_EBIT, + t_clientresponse(tc)); + break; + + case EAPSRP_SVALIDATOR: + tc = (struct t_client *)pcb->eap.es_client.ea_session; + if (tc == NULL || pcb->eap.es_client.ea_skey == NULL) { + ppp_warn("EAP: peer sent Subtype 3 without 1/2"); + eap_send_nak(pcb, id, EAPT_MD5CHAP); + break; + } + /* + * If we're already open, then this ought to be a + * duplicate. Otherwise, check that the server is + * who we think it is. + */ + if (pcb->eap.es_client.ea_state == eapOpen) { + if (id != pcb->eap.es_client.ea_id) { + ppp_warn("EAP: ID changed from %d to %d " + "in SRP Subtype 3 rexmit", + pcb->eap.es_client.ea_id, id); + } + } else { + len -= sizeof (u32_t) + SHA_DIGESTSIZE; + if (len < 0 || t_clientverify(tc, inp + + sizeof (u32_t)) != 0) { + ppp_error("EAP: SRP server verification " + "failed"); + goto client_failure; + } + GETLONG(pcb->eap.es_client.ea_keyflags, inp); + /* Save pseudonym if user wants it. */ + if (len > 0 && pcb->eap.es_usepseudo) { + INCPTR(SHA_DIGESTSIZE, inp); + write_pseudonym(esp, inp, len, id); + } + } + /* + * We've verified our peer. We're now mostly done, + * except for waiting on the regular EAP Success + * message. + */ + eap_srp_response(esp, id, EAPSRP_ACK, NULL, 0); + break; + + case EAPSRP_LWRECHALLENGE: + if (len < 4) { + ppp_warn("EAP: malformed Lightweight rechallenge"); + return; + } + SHA1Init(&ctxt); + vals[0] = id; + SHA1Update(&ctxt, vals, 1); + SHA1Update(&ctxt, pcb->eap.es_client.ea_skey, + SESSION_KEY_LEN); + SHA1Update(&ctxt, inp, len); + SHA1Update(&ctxt, pcb->eap.es_client.ea_name, + pcb->eap.es_client.ea_namelen); + SHA1Final(dig, &ctxt); + eap_srp_response(esp, id, EAPSRP_LWRECHALLENGE, dig, + SHA_DIGESTSIZE); + break; + + default: + ppp_error("EAP: unknown SRP Subtype %d", vallen); + eap_send_nak(pcb, id, EAPT_MD5CHAP); + break; + } + break; +#endif /* USE_SRP */ + + default: + ppp_info("EAP: unknown authentication type %d; Naking", typenum); + eap_send_nak(pcb, id, EAPT_SRP); + break; + } + + if (pcb->settings.eap_req_time > 0) { + UNTIMEOUT(eap_client_timeout, pcb); + TIMEOUT(eap_client_timeout, pcb, + pcb->settings.eap_req_time); + } + return; + +#ifdef USE_SRP +client_failure: + pcb->eap.es_client.ea_state = eapBadAuth; + if (pcb->settings.eap_req_time > 0) { + UNTIMEOUT(eap_client_timeout, (void *)esp); + } + pcb->eap.es_client.ea_session = NULL; + t_clientclose(tc); + auth_withpeer_fail(pcb, PPP_EAP); +#endif /* USE_SRP */ +} + +#if PPP_SERVER +/* FIXME: remove malloc() and free() */ +/* + * eap_response - Receive EAP Response message (server mode). + */ +static void eap_response(ppp_pcb *pcb, u_char *inp, int id, int len) { + u_char typenum; + u_char vallen; + int secret_len; + char secret[MAXSECRETLEN]; + char rhostname[256]; + md5_context mdContext; + u_char hash[MD5_SIGNATURE_SIZE]; +#ifdef USE_SRP + struct t_server *ts; + struct t_num A; + SHA1_CTX ctxt; + u_char dig[SHA_DIGESTSIZE]; +#endif /* USE_SRP */ + + if (pcb->eap.es_server.ea_id != id) { + ppp_dbglog("EAP: discarding Response %d; expected ID %d", id, + pcb->eap.es_server.ea_id); + return; + } + + pcb->eap.es_server.ea_responses++; + + if (len <= 0) { + ppp_error("EAP: empty Response message discarded"); + return; + } + + GETCHAR(typenum, inp); + len--; + + switch (typenum) { + case EAPT_IDENTITY: + if (pcb->eap.es_server.ea_state != eapIdentify) { + ppp_dbglog("EAP discarding unwanted Identify \"%.q\"", len, + inp); + break; + } + ppp_info("EAP: unauthenticated peer name \"%.*q\"", len, inp); + if (pcb->eap.es_server.ea_peer != NULL +#if PPP_REMOTENAME + && pcb->eap.es_server.ea_peer != pcb->remote_name +#endif /* PPP_REMOTENAME */ + ) + free(pcb->eap.es_server.ea_peer); + pcb->eap.es_server.ea_peer = (char*)malloc(len + 1); + if (pcb->eap.es_server.ea_peer == NULL) { + pcb->eap.es_server.ea_peerlen = 0; + eap_figure_next_state(pcb, 1); + break; + } + MEMCPY(pcb->eap.es_server.ea_peer, inp, len); + pcb->eap.es_server.ea_peer[len] = '\0'; + pcb->eap.es_server.ea_peerlen = len; + eap_figure_next_state(pcb, 0); + break; + + case EAPT_NOTIFICATION: + ppp_dbglog("EAP unexpected Notification; response discarded"); + break; + + case EAPT_NAK: + if (len < 1) { + ppp_info("EAP: Nak Response with no suggested protocol"); + eap_figure_next_state(pcb, 1); + break; + } + + GETCHAR(vallen, inp); + len--; + + if ( +#if PPP_REMOTENAME + !pcb->explicit_remote && +#endif /* PPP_REMOTENAME */ + pcb->eap.es_server.ea_state == eapIdentify){ + /* Peer cannot Nak Identify Request */ + eap_figure_next_state(pcb, 1); + break; + } + + switch (vallen) { + case EAPT_SRP: + /* Run through SRP validator selection again. */ + pcb->eap.es_server.ea_state = eapIdentify; + eap_figure_next_state(pcb, 0); + break; + + case EAPT_MD5CHAP: + pcb->eap.es_server.ea_state = eapMD5Chall; + break; + + default: + ppp_dbglog("EAP: peer requesting unknown Type %d", vallen); + switch (pcb->eap.es_server.ea_state) { + case eapSRP1: + case eapSRP2: + case eapSRP3: + pcb->eap.es_server.ea_state = eapMD5Chall; + break; + case eapMD5Chall: + case eapSRP4: + pcb->eap.es_server.ea_state = eapIdentify; + eap_figure_next_state(pcb, 0); + break; + default: + break; + } + break; + } + break; + + case EAPT_MD5CHAP: + if (pcb->eap.es_server.ea_state != eapMD5Chall) { + ppp_error("EAP: unexpected MD5-Response"); + eap_figure_next_state(pcb, 1); + break; + } + if (len < 1) { + ppp_error("EAP: received MD5-Response with no data"); + eap_figure_next_state(pcb, 1); + break; + } + GETCHAR(vallen, inp); + len--; + if (vallen != 16 || vallen > len) { + ppp_error("EAP: MD5-Response with bad length %d", vallen); + eap_figure_next_state(pcb, 1); + break; + } + + /* Not so likely to happen. */ + if (vallen >= len + sizeof (rhostname)) { + ppp_dbglog("EAP: trimming really long peer name down"); + MEMCPY(rhostname, inp + vallen, sizeof (rhostname) - 1); + rhostname[sizeof (rhostname) - 1] = '\0'; + } else { + MEMCPY(rhostname, inp + vallen, len - vallen); + rhostname[len - vallen] = '\0'; + } + +#if PPP_REMOTENAME + /* In case the remote doesn't give us his name. */ + if (explicit_remote || + (remote_name[0] != '\0' && vallen == len)) + strlcpy(rhostname, remote_name, sizeof (rhostname)); +#endif /* PPP_REMOTENAME */ + + /* + * Get the secret for authenticating the specified + * host. + */ + if (!get_secret(pcb, rhostname, + pcb->eap.es_server.ea_name, secret, &secret_len, 1)) { + ppp_dbglog("EAP: no MD5 secret for auth of %q", rhostname); + eap_send_failure(pcb); + break; + } + md5_starts(&mdContext); + md5_update(&mdContext, &pcb->eap.es_server.ea_id, 1); + md5_update(&mdContext, (u_char *)secret, secret_len); + BZERO(secret, sizeof (secret)); + md5_update(&mdContext, pcb->eap.es_challenge, pcb->eap.es_challen); + md5_finish(&mdContext, hash); + if (BCMP(hash, inp, MD5_SIGNATURE_SIZE) != 0) { + eap_send_failure(pcb); + break; + } + pcb->eap.es_server.ea_type = EAPT_MD5CHAP; + eap_send_success(pcb); + eap_figure_next_state(pcb, 0); + if (pcb->eap.es_rechallenge != 0) + TIMEOUT(eap_rechallenge, pcb, pcb->eap.es_rechallenge); + break; + +#ifdef USE_SRP + case EAPT_SRP: + if (len < 1) { + ppp_error("EAP: empty SRP Response"); + eap_figure_next_state(pcb, 1); + break; + } + GETCHAR(typenum, inp); + len--; + switch (typenum) { + case EAPSRP_CKEY: + if (pcb->eap.es_server.ea_state != eapSRP1) { + ppp_error("EAP: unexpected SRP Subtype 1 Response"); + eap_figure_next_state(pcb, 1); + break; + } + A.data = inp; + A.len = len; + ts = (struct t_server *)pcb->eap.es_server.ea_session; + assert(ts != NULL); + pcb->eap.es_server.ea_skey = t_servergetkey(ts, &A); + if (pcb->eap.es_server.ea_skey == NULL) { + /* Client's A value is bogus; terminate now */ + ppp_error("EAP: bogus A value from client"); + eap_send_failure(pcb); + } else { + eap_figure_next_state(pcb, 0); + } + break; + + case EAPSRP_CVALIDATOR: + if (pcb->eap.es_server.ea_state != eapSRP2) { + ppp_error("EAP: unexpected SRP Subtype 2 Response"); + eap_figure_next_state(pcb, 1); + break; + } + if (len < sizeof (u32_t) + SHA_DIGESTSIZE) { + ppp_error("EAP: M1 length %d < %d", len, + sizeof (u32_t) + SHA_DIGESTSIZE); + eap_figure_next_state(pcb, 1); + break; + } + GETLONG(pcb->eap.es_server.ea_keyflags, inp); + ts = (struct t_server *)pcb->eap.es_server.ea_session; + assert(ts != NULL); + if (t_serververify(ts, inp)) { + ppp_info("EAP: unable to validate client identity"); + eap_send_failure(pcb); + break; + } + eap_figure_next_state(pcb, 0); + break; + + case EAPSRP_ACK: + if (pcb->eap.es_server.ea_state != eapSRP3) { + ppp_error("EAP: unexpected SRP Subtype 3 Response"); + eap_send_failure(esp); + break; + } + pcb->eap.es_server.ea_type = EAPT_SRP; + eap_send_success(pcb, esp); + eap_figure_next_state(pcb, 0); + if (pcb->eap.es_rechallenge != 0) + TIMEOUT(eap_rechallenge, pcb, + pcb->eap.es_rechallenge); + if (pcb->eap.es_lwrechallenge != 0) + TIMEOUT(srp_lwrechallenge, pcb, + pcb->eap.es_lwrechallenge); + break; + + case EAPSRP_LWRECHALLENGE: + if (pcb->eap.es_server.ea_state != eapSRP4) { + ppp_info("EAP: unexpected SRP Subtype 4 Response"); + return; + } + if (len != SHA_DIGESTSIZE) { + ppp_error("EAP: bad Lightweight rechallenge " + "response"); + return; + } + SHA1Init(&ctxt); + vallen = id; + SHA1Update(&ctxt, &vallen, 1); + SHA1Update(&ctxt, pcb->eap.es_server.ea_skey, + SESSION_KEY_LEN); + SHA1Update(&ctxt, pcb->eap.es_challenge, pcb->eap.es_challen); + SHA1Update(&ctxt, pcb->eap.es_server.ea_peer, + pcb->eap.es_server.ea_peerlen); + SHA1Final(dig, &ctxt); + if (BCMP(dig, inp, SHA_DIGESTSIZE) != 0) { + ppp_error("EAP: failed Lightweight rechallenge"); + eap_send_failure(pcb); + break; + } + pcb->eap.es_server.ea_state = eapOpen; + if (pcb->eap.es_lwrechallenge != 0) + TIMEOUT(srp_lwrechallenge, esp, + pcb->eap.es_lwrechallenge); + break; + } + break; +#endif /* USE_SRP */ + + default: + /* This can't happen. */ + ppp_error("EAP: unknown Response type %d; ignored", typenum); + return; + } + + if (pcb->settings.eap_timeout_time > 0) { + UNTIMEOUT(eap_server_timeout, pcb); + } + + if (pcb->eap.es_server.ea_state != eapBadAuth && + pcb->eap.es_server.ea_state != eapOpen) { + pcb->eap.es_server.ea_id++; + eap_send_request(pcb); + } +} +#endif /* PPP_SERVER */ + +/* + * eap_success - Receive EAP Success message (client mode). + */ +static void eap_success(ppp_pcb *pcb, u_char *inp, int id, int len) { + LWIP_UNUSED_ARG(id); + + if (pcb->eap.es_client.ea_state != eapOpen && !eap_client_active(pcb)) { + ppp_dbglog("EAP unexpected success message in state %s (%d)", + eap_state_name(pcb->eap.es_client.ea_state), + pcb->eap.es_client.ea_state); + return; + } + + if (pcb->settings.eap_req_time > 0) { + UNTIMEOUT(eap_client_timeout, pcb); + } + + if (len > 0) { + /* This is odd. The spec doesn't allow for this. */ + PRINTMSG(inp, len); + } + + pcb->eap.es_client.ea_state = eapOpen; + auth_withpeer_success(pcb, PPP_EAP, 0); +} + +/* + * eap_failure - Receive EAP Failure message (client mode). + */ +static void eap_failure(ppp_pcb *pcb, u_char *inp, int id, int len) { + LWIP_UNUSED_ARG(id); + + if (!eap_client_active(pcb)) { + ppp_dbglog("EAP unexpected failure message in state %s (%d)", + eap_state_name(pcb->eap.es_client.ea_state), + pcb->eap.es_client.ea_state); + } + + if (pcb->settings.eap_req_time > 0) { + UNTIMEOUT(eap_client_timeout, pcb); + } + + if (len > 0) { + /* This is odd. The spec doesn't allow for this. */ + PRINTMSG(inp, len); + } + + pcb->eap.es_client.ea_state = eapBadAuth; + + ppp_error("EAP: peer reports authentication failure"); + auth_withpeer_fail(pcb, PPP_EAP); +} + +/* + * eap_input - Handle received EAP message. + */ +static void eap_input(ppp_pcb *pcb, u_char *inp, int inlen) { + u_char code, id; + int len; + + /* + * Parse header (code, id and length). If packet too short, + * drop it. + */ + if (inlen < EAP_HEADERLEN) { + ppp_error("EAP: packet too short: %d < %d", inlen, EAP_HEADERLEN); + return; + } + GETCHAR(code, inp); + GETCHAR(id, inp); + GETSHORT(len, inp); + if (len < EAP_HEADERLEN || len > inlen) { + ppp_error("EAP: packet has illegal length field %d (%d..%d)", len, + EAP_HEADERLEN, inlen); + return; + } + len -= EAP_HEADERLEN; + + /* Dispatch based on message code */ + switch (code) { + case EAP_REQUEST: + eap_request(pcb, inp, id, len); + break; + +#if PPP_SERVER + case EAP_RESPONSE: + eap_response(pcb, inp, id, len); + break; +#endif /* PPP_SERVER */ + + case EAP_SUCCESS: + eap_success(pcb, inp, id, len); + break; + + case EAP_FAILURE: + eap_failure(pcb, inp, id, len); + break; + + default: /* XXX Need code reject */ + /* Note: it's not legal to send EAP Nak here. */ + ppp_warn("EAP: unknown code %d received", code); + break; + } +} + +#if PRINTPKT_SUPPORT +/* + * eap_printpkt - print the contents of an EAP packet. + */ +static const char *eap_codenames[] = { + "Request", "Response", "Success", "Failure" +}; + +static const char *eap_typenames[] = { + "Identity", "Notification", "Nak", "MD5-Challenge", + "OTP", "Generic-Token", NULL, NULL, + "RSA", "DSS", "KEA", "KEA-Validate", + "TLS", "Defender", "Windows 2000", "Arcot", + "Cisco", "Nokia", "SRP" +}; + +static int eap_printpkt(u_char *inp, int inlen, void (*printer) (void *, const char *, ...), void *arg) { + int code, id, len, rtype, vallen; + u_char *pstart; + u32_t uval; + + if (inlen < EAP_HEADERLEN) + return (0); + pstart = inp; + GETCHAR(code, inp); + GETCHAR(id, inp); + GETSHORT(len, inp); + if (len < EAP_HEADERLEN || len > inlen) + return (0); + + if (code >= 1 && code <= (int)sizeof(eap_codenames) / (int)sizeof(char *)) + printer(arg, " %s", eap_codenames[code-1]); + else + printer(arg, " code=0x%x", code); + printer(arg, " id=0x%x", id); + len -= EAP_HEADERLEN; + switch (code) { + case EAP_REQUEST: + if (len < 1) { + printer(arg, " "); + break; + } + GETCHAR(rtype, inp); + len--; + if (rtype >= 1 && + rtype <= (int)sizeof (eap_typenames) / (int)sizeof (char *)) + printer(arg, " %s", eap_typenames[rtype-1]); + else + printer(arg, " type=0x%x", rtype); + switch (rtype) { + case EAPT_IDENTITY: + case EAPT_NOTIFICATION: + if (len > 0) { + printer(arg, " "); + INCPTR(len, inp); + len = 0; + } else { + printer(arg, " "); + } + break; + + case EAPT_MD5CHAP: + if (len <= 0) + break; + GETCHAR(vallen, inp); + len--; + if (vallen > len) + goto truncated; + printer(arg, " ", vallen, inp); + INCPTR(vallen, inp); + len -= vallen; + if (len > 0) { + printer(arg, " "); + INCPTR(len, inp); + len = 0; + } else { + printer(arg, " "); + } + break; + + case EAPT_SRP: + if (len < 3) + goto truncated; + GETCHAR(vallen, inp); + len--; + printer(arg, "-%d", vallen); + switch (vallen) { + case EAPSRP_CHALLENGE: + GETCHAR(vallen, inp); + len--; + if (vallen >= len) + goto truncated; + if (vallen > 0) { + printer(arg, " "); + } else { + printer(arg, " "); + } + INCPTR(vallen, inp); + len -= vallen; + GETCHAR(vallen, inp); + len--; + if (vallen >= len) + goto truncated; + printer(arg, " ", vallen, inp); + INCPTR(vallen, inp); + len -= vallen; + GETCHAR(vallen, inp); + len--; + if (vallen > len) + goto truncated; + if (vallen == 0) { + printer(arg, " "); + } else { + printer(arg, " ", vallen, inp); + } + INCPTR(vallen, inp); + len -= vallen; + if (len == 0) { + printer(arg, " "); + } else { + printer(arg, " ", len, inp); + INCPTR(len, inp); + len = 0; + } + break; + + case EAPSRP_SKEY: + printer(arg, " ", len, inp); + INCPTR(len, inp); + len = 0; + break; + + case EAPSRP_SVALIDATOR: + if (len < (int)sizeof (u32_t)) + break; + GETLONG(uval, inp); + len -= sizeof (u32_t); + if (uval & SRPVAL_EBIT) { + printer(arg, " E"); + uval &= ~SRPVAL_EBIT; + } + if (uval != 0) { + printer(arg, " f<%X>", uval); + } + if ((vallen = len) > SHA_DIGESTSIZE) + vallen = SHA_DIGESTSIZE; + printer(arg, " ", len, inp, + len < SHA_DIGESTSIZE ? "?" : ""); + INCPTR(vallen, inp); + len -= vallen; + if (len > 0) { + printer(arg, " ", len, inp); + INCPTR(len, inp); + len = 0; + } + break; + + case EAPSRP_LWRECHALLENGE: + printer(arg, " ", len, inp); + INCPTR(len, inp); + len = 0; + break; + default: + break; + } + break; + default: + break; + } + break; + + case EAP_RESPONSE: + if (len < 1) + break; + GETCHAR(rtype, inp); + len--; + if (rtype >= 1 && + rtype <= (int)sizeof (eap_typenames) / (int)sizeof (char *)) + printer(arg, " %s", eap_typenames[rtype-1]); + else + printer(arg, " type=0x%x", rtype); + switch (rtype) { + case EAPT_IDENTITY: + if (len > 0) { + printer(arg, " "); + INCPTR(len, inp); + len = 0; + } + break; + + case EAPT_NAK: + if (len <= 0) { + printer(arg, " "); + break; + } + GETCHAR(rtype, inp); + len--; + printer(arg, " = 1 && + rtype < (int)sizeof (eap_typenames) / (int)sizeof (char *)) + printer(arg, " (%s)", eap_typenames[rtype-1]); + printer(arg, ">"); + break; + + case EAPT_MD5CHAP: + if (len <= 0) { + printer(arg, " "); + break; + } + GETCHAR(vallen, inp); + len--; + if (vallen > len) + goto truncated; + printer(arg, " ", vallen, inp); + INCPTR(vallen, inp); + len -= vallen; + if (len > 0) { + printer(arg, " "); + INCPTR(len, inp); + len = 0; + } else { + printer(arg, " "); + } + break; + + case EAPT_SRP: + if (len < 1) + goto truncated; + GETCHAR(vallen, inp); + len--; + printer(arg, "-%d", vallen); + switch (vallen) { + case EAPSRP_CKEY: + printer(arg, " ", len, inp); + INCPTR(len, inp); + len = 0; + break; + + case EAPSRP_CVALIDATOR: + if (len < (int)sizeof (u32_t)) + break; + GETLONG(uval, inp); + len -= sizeof (u32_t); + if (uval & SRPVAL_EBIT) { + printer(arg, " E"); + uval &= ~SRPVAL_EBIT; + } + if (uval != 0) { + printer(arg, " f<%X>", uval); + } + printer(arg, " ", len, inp, + len == SHA_DIGESTSIZE ? "" : "?"); + INCPTR(len, inp); + len = 0; + break; + + case EAPSRP_ACK: + break; + + case EAPSRP_LWRECHALLENGE: + printer(arg, " ", len, inp, + len == SHA_DIGESTSIZE ? "" : "?"); + if ((vallen = len) > SHA_DIGESTSIZE) + vallen = SHA_DIGESTSIZE; + INCPTR(vallen, inp); + len -= vallen; + break; + default: + break; + } + break; + default: + break; + } + break; + + case EAP_SUCCESS: /* No payload expected for these! */ + case EAP_FAILURE: + default: + break; + + truncated: + printer(arg, " "); + break; + } + + if (len > 8) + printer(arg, "%8B...", inp); + else if (len > 0) + printer(arg, "%.*B", len, inp); + INCPTR(len, inp); + + return (inp - pstart); +} +#endif /* PRINTPKT_SUPPORT */ + +#endif /* PPP_SUPPORT && EAP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/ecp.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/ecp.c new file mode 100644 index 0000000..728fb5f --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/ecp.c @@ -0,0 +1,188 @@ +/* + * ecp.c - PPP Encryption Control Protocol. + * + * Copyright (c) 2002 Google, Inc. + * 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. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Derived from ccp.c, which is: + * + * Copyright (c) 1994-2002 Paul Mackerras. 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. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && ECP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/fsm.h" +#include "netif/ppp/ecp.h" + +#if PPP_OPTIONS +static option_t ecp_option_list[] = { + { "noecp", o_bool, &ecp_protent.enabled_flag, + "Disable ECP negotiation" }, + { "-ecp", o_bool, &ecp_protent.enabled_flag, + "Disable ECP negotiation", OPT_ALIAS }, + + { NULL } +}; +#endif /* PPP_OPTIONS */ + +/* + * Protocol entry points from main code. + */ +static void ecp_init (int unit); +/* +static void ecp_open (int unit); +static void ecp_close (int unit, char *); +static void ecp_lowerup (int unit); +static void ecp_lowerdown (int); +static void ecp_input (int unit, u_char *pkt, int len); +static void ecp_protrej (int unit); +*/ +#if PRINTPKT_SUPPORT +static int ecp_printpkt (u_char *pkt, int len, + void (*printer) (void *, char *, ...), + void *arg); +#endif /* PRINTPKT_SUPPORT */ +/* +static void ecp_datainput (int unit, u_char *pkt, int len); +*/ + +const struct protent ecp_protent = { + PPP_ECP, + ecp_init, + NULL, /* ecp_input, */ + NULL, /* ecp_protrej, */ + NULL, /* ecp_lowerup, */ + NULL, /* ecp_lowerdown, */ + NULL, /* ecp_open, */ + NULL, /* ecp_close, */ +#if PRINTPKT_SUPPORT + ecp_printpkt, +#endif /* PRINTPKT_SUPPORT */ + NULL, /* ecp_datainput, */ + 0, +#if PRINTPKT_SUPPORT + "ECP", + "Encrypted", +#endif /* PRINTPKT_SUPPORT */ +#if PPP_OPTIONS + ecp_option_list, + NULL, +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT + NULL, + NULL +#endif /* DEMAND_SUPPORT */ +}; + +fsm ecp_fsm[NUM_PPP]; +ecp_options ecp_wantoptions[NUM_PPP]; /* what to request the peer to use */ +ecp_options ecp_gotoptions[NUM_PPP]; /* what the peer agreed to do */ +ecp_options ecp_allowoptions[NUM_PPP]; /* what we'll agree to do */ +ecp_options ecp_hisoptions[NUM_PPP]; /* what we agreed to do */ + +static const fsm_callbacks ecp_callbacks = { + NULL, /* ecp_resetci, */ + NULL, /* ecp_cilen, */ + NULL, /* ecp_addci, */ + NULL, /* ecp_ackci, */ + NULL, /* ecp_nakci, */ + NULL, /* ecp_rejci, */ + NULL, /* ecp_reqci, */ + NULL, /* ecp_up, */ + NULL, /* ecp_down, */ + NULL, + NULL, + NULL, + NULL, + NULL, /* ecp_extcode, */ + "ECP" +}; + +/* + * ecp_init - initialize ECP. + */ +static void +ecp_init(unit) + int unit; +{ + fsm *f = &ecp_fsm[unit]; + + f->unit = unit; + f->protocol = PPP_ECP; + f->callbacks = &ecp_callbacks; + fsm_init(f); + + memset(&ecp_wantoptions[unit], 0, sizeof(ecp_options)); + memset(&ecp_gotoptions[unit], 0, sizeof(ecp_options)); + memset(&ecp_allowoptions[unit], 0, sizeof(ecp_options)); + memset(&ecp_hisoptions[unit], 0, sizeof(ecp_options)); + +} + + +#if PRINTPKT_SUPPORT +static int +ecp_printpkt(p, plen, printer, arg) + u_char *p; + int plen; + void (*printer) (void *, char *, ...); + void *arg; +{ + return 0; +} +#endif /* PRINTPKT_SUPPORT */ + +#endif /* PPP_SUPPORT && ECP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/eui64.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/eui64.c new file mode 100644 index 0000000..e23a34e --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/eui64.c @@ -0,0 +1,56 @@ +/* + * eui64.c - EUI64 routines for IPv6CP. + * + * Copyright (c) 1999 Tommi Komulainen. 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. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Tommi Komulainen + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: eui64.c,v 1.6 2002/12/04 23:03:32 paulus Exp $ + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && PPP_IPV6_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "netif/ppp/ppp_impl.h" +#include "netif/ppp/eui64.h" + +/* + * eui64_ntoa - Make an ascii representation of an interface identifier + */ +char *eui64_ntoa(eui64_t e) { + static char buf[32]; + + snprintf(buf, 32, "%02x%02x:%02x%02x:%02x%02x:%02x%02x", + e.e8[0], e.e8[1], e.e8[2], e.e8[3], + e.e8[4], e.e8[5], e.e8[6], e.e8[7]); + return buf; +} + +#endif /* PPP_SUPPORT && PPP_IPV6_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/fsm.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/fsm.c new file mode 100644 index 0000000..71f2c95 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/fsm.c @@ -0,0 +1,798 @@ +/* + * fsm.c - {Link, IP} Control Protocol Finite State Machine. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. 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. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +/* + * TODO: + * Randomize fsm id on link/init. + * Deal with variable outgoing MTU. + */ + +#if 0 /* UNUSED */ +#include +#include +#include +#endif /* UNUSED */ + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/fsm.h" + +static void fsm_timeout (void *); +static void fsm_rconfreq(fsm *f, u_char id, u_char *inp, int len); +static void fsm_rconfack(fsm *f, int id, u_char *inp, int len); +static void fsm_rconfnakrej(fsm *f, int code, int id, u_char *inp, int len); +static void fsm_rtermreq(fsm *f, int id, u_char *p, int len); +static void fsm_rtermack(fsm *f); +static void fsm_rcoderej(fsm *f, u_char *inp, int len); +static void fsm_sconfreq(fsm *f, int retransmit); + +#define PROTO_NAME(f) ((f)->callbacks->proto_name) + +/* + * fsm_init - Initialize fsm. + * + * Initialize fsm state. + */ +void fsm_init(fsm *f) { + ppp_pcb *pcb = f->pcb; + f->state = PPP_FSM_INITIAL; + f->flags = 0; + f->id = 0; /* XXX Start with random id? */ + f->maxnakloops = pcb->settings.fsm_max_nak_loops; + f->term_reason_len = 0; +} + + +/* + * fsm_lowerup - The lower layer is up. + */ +void fsm_lowerup(fsm *f) { + switch( f->state ){ + case PPP_FSM_INITIAL: + f->state = PPP_FSM_CLOSED; + break; + + case PPP_FSM_STARTING: + if( f->flags & OPT_SILENT ) + f->state = PPP_FSM_STOPPED; + else { + /* Send an initial configure-request */ + fsm_sconfreq(f, 0); + f->state = PPP_FSM_REQSENT; + } + break; + + default: + FSMDEBUG(("%s: Up event in state %d!", PROTO_NAME(f), f->state)); + /* no break */ + } +} + + +/* + * fsm_lowerdown - The lower layer is down. + * + * Cancel all timeouts and inform upper layers. + */ +void fsm_lowerdown(fsm *f) { + switch( f->state ){ + case PPP_FSM_CLOSED: + f->state = PPP_FSM_INITIAL; + break; + + case PPP_FSM_STOPPED: + f->state = PPP_FSM_STARTING; + if( f->callbacks->starting ) + (*f->callbacks->starting)(f); + break; + + case PPP_FSM_CLOSING: + f->state = PPP_FSM_INITIAL; + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + break; + + case PPP_FSM_STOPPING: + case PPP_FSM_REQSENT: + case PPP_FSM_ACKRCVD: + case PPP_FSM_ACKSENT: + f->state = PPP_FSM_STARTING; + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + break; + + case PPP_FSM_OPENED: + if( f->callbacks->down ) + (*f->callbacks->down)(f); + f->state = PPP_FSM_STARTING; + break; + + default: + FSMDEBUG(("%s: Down event in state %d!", PROTO_NAME(f), f->state)); + /* no break */ + } +} + + +/* + * fsm_open - Link is allowed to come up. + */ +void fsm_open(fsm *f) { + switch( f->state ){ + case PPP_FSM_INITIAL: + f->state = PPP_FSM_STARTING; + if( f->callbacks->starting ) + (*f->callbacks->starting)(f); + break; + + case PPP_FSM_CLOSED: + if( f->flags & OPT_SILENT ) + f->state = PPP_FSM_STOPPED; + else { + /* Send an initial configure-request */ + fsm_sconfreq(f, 0); + f->state = PPP_FSM_REQSENT; + } + break; + + case PPP_FSM_CLOSING: + f->state = PPP_FSM_STOPPING; + /* fall through */ + /* no break */ + case PPP_FSM_STOPPED: + case PPP_FSM_OPENED: + if( f->flags & OPT_RESTART ){ + fsm_lowerdown(f); + fsm_lowerup(f); + } + break; + default: + break; + } +} + +/* + * terminate_layer - Start process of shutting down the FSM + * + * Cancel any timeout running, notify upper layers we're done, and + * send a terminate-request message as configured. + */ +static void terminate_layer(fsm *f, int nextstate) { + ppp_pcb *pcb = f->pcb; + + if( f->state != PPP_FSM_OPENED ) + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + else if( f->callbacks->down ) + (*f->callbacks->down)(f); /* Inform upper layers we're down */ + + /* Init restart counter and send Terminate-Request */ + f->retransmits = pcb->settings.fsm_max_term_transmits; + fsm_sdata(f, TERMREQ, f->reqid = ++f->id, + (u_char *) f->term_reason, f->term_reason_len); + + if (f->retransmits == 0) { + /* + * User asked for no terminate requests at all; just close it. + * We've already fired off one Terminate-Request just to be nice + * to the peer, but we're not going to wait for a reply. + */ + f->state = nextstate == PPP_FSM_CLOSING ? PPP_FSM_CLOSED : PPP_FSM_STOPPED; + if( f->callbacks->finished ) + (*f->callbacks->finished)(f); + return; + } + + TIMEOUT(fsm_timeout, f, pcb->settings.fsm_timeout_time); + --f->retransmits; + + f->state = nextstate; +} + +/* + * fsm_close - Start closing connection. + * + * Cancel timeouts and either initiate close or possibly go directly to + * the PPP_FSM_CLOSED state. + */ +void fsm_close(fsm *f, const char *reason) { + f->term_reason = reason; + f->term_reason_len = (reason == NULL? 0: LWIP_MIN(strlen(reason), 0xFF) ); + switch( f->state ){ + case PPP_FSM_STARTING: + f->state = PPP_FSM_INITIAL; + break; + case PPP_FSM_STOPPED: + f->state = PPP_FSM_CLOSED; + break; + case PPP_FSM_STOPPING: + f->state = PPP_FSM_CLOSING; + break; + + case PPP_FSM_REQSENT: + case PPP_FSM_ACKRCVD: + case PPP_FSM_ACKSENT: + case PPP_FSM_OPENED: + terminate_layer(f, PPP_FSM_CLOSING); + break; + default: + break; + } +} + + +/* + * fsm_timeout - Timeout expired. + */ +static void fsm_timeout(void *arg) { + fsm *f = (fsm *) arg; + ppp_pcb *pcb = f->pcb; + + switch (f->state) { + case PPP_FSM_CLOSING: + case PPP_FSM_STOPPING: + if( f->retransmits <= 0 ){ + /* + * We've waited for an ack long enough. Peer probably heard us. + */ + f->state = (f->state == PPP_FSM_CLOSING)? PPP_FSM_CLOSED: PPP_FSM_STOPPED; + if( f->callbacks->finished ) + (*f->callbacks->finished)(f); + } else { + /* Send Terminate-Request */ + fsm_sdata(f, TERMREQ, f->reqid = ++f->id, + (u_char *) f->term_reason, f->term_reason_len); + TIMEOUT(fsm_timeout, f, pcb->settings.fsm_timeout_time); + --f->retransmits; + } + break; + + case PPP_FSM_REQSENT: + case PPP_FSM_ACKRCVD: + case PPP_FSM_ACKSENT: + if (f->retransmits <= 0) { + ppp_warn("%s: timeout sending Config-Requests\n", PROTO_NAME(f)); + f->state = PPP_FSM_STOPPED; + if( (f->flags & OPT_PASSIVE) == 0 && f->callbacks->finished ) + (*f->callbacks->finished)(f); + + } else { + /* Retransmit the configure-request */ + if (f->callbacks->retransmit) + (*f->callbacks->retransmit)(f); + fsm_sconfreq(f, 1); /* Re-send Configure-Request */ + if( f->state == PPP_FSM_ACKRCVD ) + f->state = PPP_FSM_REQSENT; + } + break; + + default: + FSMDEBUG(("%s: Timeout event in state %d!", PROTO_NAME(f), f->state)); + /* no break */ + } +} + + +/* + * fsm_input - Input packet. + */ +void fsm_input(fsm *f, u_char *inpacket, int l) { + u_char *inp; + u_char code, id; + int len; + + /* + * Parse header (code, id and length). + * If packet too short, drop it. + */ + inp = inpacket; + if (l < HEADERLEN) { + FSMDEBUG(("fsm_input(%x): Rcvd short header.", f->protocol)); + return; + } + GETCHAR(code, inp); + GETCHAR(id, inp); + GETSHORT(len, inp); + if (len < HEADERLEN) { + FSMDEBUG(("fsm_input(%x): Rcvd illegal length.", f->protocol)); + return; + } + if (len > l) { + FSMDEBUG(("fsm_input(%x): Rcvd short packet.", f->protocol)); + return; + } + len -= HEADERLEN; /* subtract header length */ + + if( f->state == PPP_FSM_INITIAL || f->state == PPP_FSM_STARTING ){ + FSMDEBUG(("fsm_input(%x): Rcvd packet in state %d.", + f->protocol, f->state)); + return; + } + + /* + * Action depends on code. + */ + switch (code) { + case CONFREQ: + fsm_rconfreq(f, id, inp, len); + break; + + case CONFACK: + fsm_rconfack(f, id, inp, len); + break; + + case CONFNAK: + case CONFREJ: + fsm_rconfnakrej(f, code, id, inp, len); + break; + + case TERMREQ: + fsm_rtermreq(f, id, inp, len); + break; + + case TERMACK: + fsm_rtermack(f); + break; + + case CODEREJ: + fsm_rcoderej(f, inp, len); + break; + + default: + if( !f->callbacks->extcode + || !(*f->callbacks->extcode)(f, code, id, inp, len) ) + fsm_sdata(f, CODEREJ, ++f->id, inpacket, len + HEADERLEN); + break; + } +} + + +/* + * fsm_rconfreq - Receive Configure-Request. + */ +static void fsm_rconfreq(fsm *f, u_char id, u_char *inp, int len) { + int code, reject_if_disagree; + + switch( f->state ){ + case PPP_FSM_CLOSED: + /* Go away, we're closed */ + fsm_sdata(f, TERMACK, id, NULL, 0); + return; + case PPP_FSM_CLOSING: + case PPP_FSM_STOPPING: + return; + + case PPP_FSM_OPENED: + /* Go down and restart negotiation */ + if( f->callbacks->down ) + (*f->callbacks->down)(f); /* Inform upper layers */ + fsm_sconfreq(f, 0); /* Send initial Configure-Request */ + f->state = PPP_FSM_REQSENT; + break; + + case PPP_FSM_STOPPED: + /* Negotiation started by our peer */ + fsm_sconfreq(f, 0); /* Send initial Configure-Request */ + f->state = PPP_FSM_REQSENT; + break; + default: + break; + } + + /* + * Pass the requested configuration options + * to protocol-specific code for checking. + */ + if (f->callbacks->reqci){ /* Check CI */ + reject_if_disagree = (f->nakloops >= f->maxnakloops); + code = (*f->callbacks->reqci)(f, inp, &len, reject_if_disagree); + } else if (len) + code = CONFREJ; /* Reject all CI */ + else + code = CONFACK; + + /* send the Ack, Nak or Rej to the peer */ + fsm_sdata(f, code, id, inp, len); + + if (code == CONFACK) { + if (f->state == PPP_FSM_ACKRCVD) { + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + f->state = PPP_FSM_OPENED; + if (f->callbacks->up) + (*f->callbacks->up)(f); /* Inform upper layers */ + } else + f->state = PPP_FSM_ACKSENT; + f->nakloops = 0; + + } else { + /* we sent CONFACK or CONFREJ */ + if (f->state != PPP_FSM_ACKRCVD) + f->state = PPP_FSM_REQSENT; + if( code == CONFNAK ) + ++f->nakloops; + } +} + + +/* + * fsm_rconfack - Receive Configure-Ack. + */ +static void fsm_rconfack(fsm *f, int id, u_char *inp, int len) { + ppp_pcb *pcb = f->pcb; + + if (id != f->reqid || f->seen_ack) /* Expected id? */ + return; /* Nope, toss... */ + if( !(f->callbacks->ackci? (*f->callbacks->ackci)(f, inp, len): + (len == 0)) ){ + /* Ack is bad - ignore it */ + ppp_error("Received bad configure-ack: %P", inp, len); + return; + } + f->seen_ack = 1; + f->rnakloops = 0; + + switch (f->state) { + case PPP_FSM_CLOSED: + case PPP_FSM_STOPPED: + fsm_sdata(f, TERMACK, id, NULL, 0); + break; + + case PPP_FSM_REQSENT: + f->state = PPP_FSM_ACKRCVD; + f->retransmits = pcb->settings.fsm_max_conf_req_transmits; + break; + + case PPP_FSM_ACKRCVD: + /* Huh? an extra valid Ack? oh well... */ + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + fsm_sconfreq(f, 0); + f->state = PPP_FSM_REQSENT; + break; + + case PPP_FSM_ACKSENT: + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + f->state = PPP_FSM_OPENED; + f->retransmits = pcb->settings.fsm_max_conf_req_transmits; + if (f->callbacks->up) + (*f->callbacks->up)(f); /* Inform upper layers */ + break; + + case PPP_FSM_OPENED: + /* Go down and restart negotiation */ + if (f->callbacks->down) + (*f->callbacks->down)(f); /* Inform upper layers */ + fsm_sconfreq(f, 0); /* Send initial Configure-Request */ + f->state = PPP_FSM_REQSENT; + break; + default: + break; + } +} + + +/* + * fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject. + */ +static void fsm_rconfnakrej(fsm *f, int code, int id, u_char *inp, int len) { + int ret; + int treat_as_reject; + + if (id != f->reqid || f->seen_ack) /* Expected id? */ + return; /* Nope, toss... */ + + if (code == CONFNAK) { + ++f->rnakloops; + treat_as_reject = (f->rnakloops >= f->maxnakloops); + if (f->callbacks->nakci == NULL + || !(ret = f->callbacks->nakci(f, inp, len, treat_as_reject))) { + ppp_error("Received bad configure-nak: %P", inp, len); + return; + } + } else { + f->rnakloops = 0; + if (f->callbacks->rejci == NULL + || !(ret = f->callbacks->rejci(f, inp, len))) { + ppp_error("Received bad configure-rej: %P", inp, len); + return; + } + } + + f->seen_ack = 1; + + switch (f->state) { + case PPP_FSM_CLOSED: + case PPP_FSM_STOPPED: + fsm_sdata(f, TERMACK, id, NULL, 0); + break; + + case PPP_FSM_REQSENT: + case PPP_FSM_ACKSENT: + /* They didn't agree to what we wanted - try another request */ + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + if (ret < 0) + f->state = PPP_FSM_STOPPED; /* kludge for stopping CCP */ + else + fsm_sconfreq(f, 0); /* Send Configure-Request */ + break; + + case PPP_FSM_ACKRCVD: + /* Got a Nak/reject when we had already had an Ack?? oh well... */ + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + fsm_sconfreq(f, 0); + f->state = PPP_FSM_REQSENT; + break; + + case PPP_FSM_OPENED: + /* Go down and restart negotiation */ + if (f->callbacks->down) + (*f->callbacks->down)(f); /* Inform upper layers */ + fsm_sconfreq(f, 0); /* Send initial Configure-Request */ + f->state = PPP_FSM_REQSENT; + break; + default: + break; + } +} + + +/* + * fsm_rtermreq - Receive Terminate-Req. + */ +static void fsm_rtermreq(fsm *f, int id, u_char *p, int len) { + ppp_pcb *pcb = f->pcb; + + switch (f->state) { + case PPP_FSM_ACKRCVD: + case PPP_FSM_ACKSENT: + f->state = PPP_FSM_REQSENT; /* Start over but keep trying */ + break; + + case PPP_FSM_OPENED: + if (len > 0) { + ppp_info("%s terminated by peer (%0.*v)", PROTO_NAME(f), len, p); + } else + ppp_info("%s terminated by peer", PROTO_NAME(f)); + f->retransmits = 0; + f->state = PPP_FSM_STOPPING; + if (f->callbacks->down) + (*f->callbacks->down)(f); /* Inform upper layers */ + TIMEOUT(fsm_timeout, f, pcb->settings.fsm_timeout_time); + break; + default: + break; + } + + fsm_sdata(f, TERMACK, id, NULL, 0); +} + + +/* + * fsm_rtermack - Receive Terminate-Ack. + */ +static void fsm_rtermack(fsm *f) { + switch (f->state) { + case PPP_FSM_CLOSING: + UNTIMEOUT(fsm_timeout, f); + f->state = PPP_FSM_CLOSED; + if( f->callbacks->finished ) + (*f->callbacks->finished)(f); + break; + case PPP_FSM_STOPPING: + UNTIMEOUT(fsm_timeout, f); + f->state = PPP_FSM_STOPPED; + if( f->callbacks->finished ) + (*f->callbacks->finished)(f); + break; + + case PPP_FSM_ACKRCVD: + f->state = PPP_FSM_REQSENT; + break; + + case PPP_FSM_OPENED: + if (f->callbacks->down) + (*f->callbacks->down)(f); /* Inform upper layers */ + fsm_sconfreq(f, 0); + f->state = PPP_FSM_REQSENT; + break; + default: + break; + } +} + + +/* + * fsm_rcoderej - Receive an Code-Reject. + */ +static void fsm_rcoderej(fsm *f, u_char *inp, int len) { + u_char code, id; + + if (len < HEADERLEN) { + FSMDEBUG(("fsm_rcoderej: Rcvd short Code-Reject packet!")); + return; + } + GETCHAR(code, inp); + GETCHAR(id, inp); + ppp_warn("%s: Rcvd Code-Reject for code %d, id %d", PROTO_NAME(f), code, id); + + if( f->state == PPP_FSM_ACKRCVD ) + f->state = PPP_FSM_REQSENT; +} + + +/* + * fsm_protreject - Peer doesn't speak this protocol. + * + * Treat this as a catastrophic error (RXJ-). + */ +void fsm_protreject(fsm *f) { + switch( f->state ){ + case PPP_FSM_CLOSING: + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + /* fall through */ + /* no break */ + case PPP_FSM_CLOSED: + f->state = PPP_FSM_CLOSED; + if( f->callbacks->finished ) + (*f->callbacks->finished)(f); + break; + + case PPP_FSM_STOPPING: + case PPP_FSM_REQSENT: + case PPP_FSM_ACKRCVD: + case PPP_FSM_ACKSENT: + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + /* fall through */ + /* no break */ + case PPP_FSM_STOPPED: + f->state = PPP_FSM_STOPPED; + if( f->callbacks->finished ) + (*f->callbacks->finished)(f); + break; + + case PPP_FSM_OPENED: + terminate_layer(f, PPP_FSM_STOPPING); + break; + + default: + FSMDEBUG(("%s: Protocol-reject event in state %d!", + PROTO_NAME(f), f->state)); + /* no break */ + } +} + + +/* + * fsm_sconfreq - Send a Configure-Request. + */ +static void fsm_sconfreq(fsm *f, int retransmit) { + ppp_pcb *pcb = f->pcb; + struct pbuf *p; + u_char *outp; + int cilen; + + if( f->state != PPP_FSM_REQSENT && f->state != PPP_FSM_ACKRCVD && f->state != PPP_FSM_ACKSENT ){ + /* Not currently negotiating - reset options */ + if( f->callbacks->resetci ) + (*f->callbacks->resetci)(f); + f->nakloops = 0; + f->rnakloops = 0; + } + + if( !retransmit ){ + /* New request - reset retransmission counter, use new ID */ + f->retransmits = pcb->settings.fsm_max_conf_req_transmits; + f->reqid = ++f->id; + } + + f->seen_ack = 0; + + /* + * Make up the request packet + */ + if( f->callbacks->cilen && f->callbacks->addci ){ + cilen = (*f->callbacks->cilen)(f); + if( cilen > pcb->peer_mru - HEADERLEN ) + cilen = pcb->peer_mru - HEADERLEN; + } else + cilen = 0; + + p = pbuf_alloc(PBUF_RAW, (u16_t)(cilen + HEADERLEN + PPP_HDRLEN), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + /* send the request to our peer */ + outp = (u_char*)p->payload; + MAKEHEADER(outp, f->protocol); + PUTCHAR(CONFREQ, outp); + PUTCHAR(f->reqid, outp); + PUTSHORT(cilen + HEADERLEN, outp); + if (cilen != 0) { + (*f->callbacks->addci)(f, outp, &cilen); + } + + ppp_write(pcb, p); + + /* start the retransmit timer */ + --f->retransmits; + TIMEOUT(fsm_timeout, f, pcb->settings.fsm_timeout_time); +} + + +/* + * fsm_sdata - Send some data. + * + * Used for all packets sent to our peer by this module. + */ +void fsm_sdata(fsm *f, u_char code, u_char id, u_char *data, int datalen) { + ppp_pcb *pcb = f->pcb; + struct pbuf *p; + u_char *outp; + int outlen; + + /* Adjust length to be smaller than MTU */ + if (datalen > pcb->peer_mru - HEADERLEN) + datalen = pcb->peer_mru - HEADERLEN; + outlen = datalen + HEADERLEN; + + p = pbuf_alloc(PBUF_RAW, (u16_t)(outlen + PPP_HDRLEN), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = (u_char*)p->payload; +/* if (datalen && data != outp + PPP_HDRLEN + HEADERLEN) -- was only for fsm_sconfreq() */ + MEMCPY(outp + PPP_HDRLEN + HEADERLEN, data, datalen); + MAKEHEADER(outp, f->protocol); + PUTCHAR(code, outp); + PUTCHAR(id, outp); + PUTSHORT(outlen, outp); + ppp_write(pcb, p); +} + +#endif /* PPP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/ipcp.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/ipcp.c new file mode 100644 index 0000000..970e69e --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/ipcp.c @@ -0,0 +1,2274 @@ +/* + * ipcp.c - PPP IP Control Protocol. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. 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. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +/* + * TODO: + */ + +#if 0 /* UNUSED */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif /* UNUSED */ + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/fsm.h" +#include "netif/ppp/ipcp.h" + +#if 0 /* UNUSED */ +/* global vars */ +u32_t netmask = 0; /* IP netmask to set on interface */ +#endif /* UNUSED */ + +#if 0 /* UNUSED */ +bool disable_defaultip = 0; /* Don't use hostname for default IP adrs */ +#endif /* UNUSED */ + +#if 0 /* moved to ppp_settings */ +bool noremoteip = 0; /* Let him have no IP address */ +#endif /* moved to ppp_setting */ + +#if 0 /* UNUSED */ +/* Hook for a plugin to know when IP protocol has come up */ +void (*ip_up_hook) (void) = NULL; + +/* Hook for a plugin to know when IP protocol has come down */ +void (*ip_down_hook) (void) = NULL; + +/* Hook for a plugin to choose the remote IP address */ +void (*ip_choose_hook) (u32_t *) = NULL; +#endif /* UNUSED */ + +#if PPP_NOTIFY +/* Notifiers for when IPCP goes up and down */ +struct notifier *ip_up_notifier = NULL; +struct notifier *ip_down_notifier = NULL; +#endif /* PPP_NOTIFY */ + +/* local vars */ +#if 0 /* moved to ppp_pcb */ +static int default_route_set[NUM_PPP]; /* Have set up a default route */ +static int proxy_arp_set[NUM_PPP]; /* Have created proxy arp entry */ +static int ipcp_is_up; /* have called np_up() */ +static int ipcp_is_open; /* haven't called np_finished() */ +static bool ask_for_local; /* request our address from peer */ +#endif /* moved to ppp_pcb */ +#if 0 /* UNUSED */ +static char vj_value[8]; /* string form of vj option value */ +static char netmask_str[20]; /* string form of netmask value */ +#endif /* UNUSED */ + +/* + * Callbacks for fsm code. (CI = Configuration Information) + */ +static void ipcp_resetci(fsm *f); /* Reset our CI */ +static int ipcp_cilen(fsm *f); /* Return length of our CI */ +static void ipcp_addci(fsm *f, u_char *ucp, int *lenp); /* Add our CI */ +static int ipcp_ackci(fsm *f, u_char *p, int len); /* Peer ack'd our CI */ +static int ipcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject);/* Peer nak'd our CI */ +static int ipcp_rejci(fsm *f, u_char *p, int len); /* Peer rej'd our CI */ +static int ipcp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree); /* Rcv CI */ +static void ipcp_up(fsm *f); /* We're UP */ +static void ipcp_down(fsm *f); /* We're DOWN */ +static void ipcp_finished(fsm *f); /* Don't need lower layer */ + +static const fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */ + ipcp_resetci, /* Reset our Configuration Information */ + ipcp_cilen, /* Length of our Configuration Information */ + ipcp_addci, /* Add our Configuration Information */ + ipcp_ackci, /* ACK our Configuration Information */ + ipcp_nakci, /* NAK our Configuration Information */ + ipcp_rejci, /* Reject our Configuration Information */ + ipcp_reqci, /* Request peer's Configuration Information */ + ipcp_up, /* Called when fsm reaches OPENED state */ + ipcp_down, /* Called when fsm leaves OPENED state */ + NULL, /* Called when we want the lower layer up */ + ipcp_finished, /* Called when we want the lower layer down */ + NULL, /* Called when Protocol-Reject received */ + NULL, /* Retransmission is necessary */ + NULL, /* Called to handle protocol-specific codes */ + "IPCP" /* String name of protocol */ +}; + +/* + * Command-line options. + */ +#if PPP_OPTIONS +static int setvjslots (char **); +static int setdnsaddr (char **); +static int setwinsaddr (char **); +static int setnetmask (char **); +int setipaddr (char *, char **, int); + +static void printipaddr (option_t *, void (*)(void *, char *,...),void *); + +static option_t ipcp_option_list[] = { + { "noip", o_bool, &ipcp_protent.enabled_flag, + "Disable IP and IPCP" }, + { "-ip", o_bool, &ipcp_protent.enabled_flag, + "Disable IP and IPCP", OPT_ALIAS }, + + { "novj", o_bool, &ipcp_wantoptions[0].neg_vj, + "Disable VJ compression", OPT_A2CLR, &ipcp_allowoptions[0].neg_vj }, + { "-vj", o_bool, &ipcp_wantoptions[0].neg_vj, + "Disable VJ compression", OPT_ALIAS | OPT_A2CLR, + &ipcp_allowoptions[0].neg_vj }, + + { "novjccomp", o_bool, &ipcp_wantoptions[0].cflag, + "Disable VJ connection-ID compression", OPT_A2CLR, + &ipcp_allowoptions[0].cflag }, + { "-vjccomp", o_bool, &ipcp_wantoptions[0].cflag, + "Disable VJ connection-ID compression", OPT_ALIAS | OPT_A2CLR, + &ipcp_allowoptions[0].cflag }, + + { "vj-max-slots", o_special, (void *)setvjslots, + "Set maximum VJ header slots", + OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, vj_value }, + + { "ipcp-accept-local", o_bool, &ipcp_wantoptions[0].accept_local, + "Accept peer's address for us", 1 }, + { "ipcp-accept-remote", o_bool, &ipcp_wantoptions[0].accept_remote, + "Accept peer's address for it", 1 }, + + { "ipparam", o_string, &ipparam, + "Set ip script parameter", OPT_PRIO }, + + { "noipdefault", o_bool, &disable_defaultip, + "Don't use name for default IP adrs", 1 }, + + { "ms-dns", 1, (void *)setdnsaddr, + "DNS address for the peer's use" }, + { "ms-wins", 1, (void *)setwinsaddr, + "Nameserver for SMB over TCP/IP for peer" }, + + { "ipcp-restart", o_int, &ipcp_fsm[0].timeouttime, + "Set timeout for IPCP", OPT_PRIO }, + { "ipcp-max-terminate", o_int, &ipcp_fsm[0].maxtermtransmits, + "Set max #xmits for term-reqs", OPT_PRIO }, + { "ipcp-max-configure", o_int, &ipcp_fsm[0].maxconfreqtransmits, + "Set max #xmits for conf-reqs", OPT_PRIO }, + { "ipcp-max-failure", o_int, &ipcp_fsm[0].maxnakloops, + "Set max #conf-naks for IPCP", OPT_PRIO }, + + { "defaultroute", o_bool, &ipcp_wantoptions[0].default_route, + "Add default route", OPT_ENABLE|1, &ipcp_allowoptions[0].default_route }, + { "nodefaultroute", o_bool, &ipcp_allowoptions[0].default_route, + "disable defaultroute option", OPT_A2CLR, + &ipcp_wantoptions[0].default_route }, + { "-defaultroute", o_bool, &ipcp_allowoptions[0].default_route, + "disable defaultroute option", OPT_ALIAS | OPT_A2CLR, + &ipcp_wantoptions[0].default_route }, + + { "replacedefaultroute", o_bool, + &ipcp_wantoptions[0].replace_default_route, + "Replace default route", 1 + }, + { "noreplacedefaultroute", o_bool, + &ipcp_allowoptions[0].replace_default_route, + "Never replace default route", OPT_A2COPY, + &ipcp_wantoptions[0].replace_default_route }, + { "proxyarp", o_bool, &ipcp_wantoptions[0].proxy_arp, + "Add proxy ARP entry", OPT_ENABLE|1, &ipcp_allowoptions[0].proxy_arp }, + { "noproxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp, + "disable proxyarp option", OPT_A2CLR, + &ipcp_wantoptions[0].proxy_arp }, + { "-proxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp, + "disable proxyarp option", OPT_ALIAS | OPT_A2CLR, + &ipcp_wantoptions[0].proxy_arp }, + + { "usepeerdns", o_bool, &usepeerdns, + "Ask peer for DNS address(es)", 1 }, + + { "netmask", o_special, (void *)setnetmask, + "set netmask", OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, netmask_str }, + + { "ipcp-no-addresses", o_bool, &ipcp_wantoptions[0].old_addrs, + "Disable old-style IP-Addresses usage", OPT_A2CLR, + &ipcp_allowoptions[0].old_addrs }, + { "ipcp-no-address", o_bool, &ipcp_wantoptions[0].neg_addr, + "Disable IP-Address usage", OPT_A2CLR, + &ipcp_allowoptions[0].neg_addr }, + + { "noremoteip", o_bool, &noremoteip, + "Allow peer to have no IP address", 1 }, + + { "nosendip", o_bool, &ipcp_wantoptions[0].neg_addr, + "Don't send our IP address to peer", OPT_A2CLR, + &ipcp_wantoptions[0].old_addrs}, + + { "IP addresses", o_wild, (void *) &setipaddr, + "set local and remote IP addresses", + OPT_NOARG | OPT_A2PRINTER, (void *) &printipaddr }, + + { NULL } +}; +#endif /* PPP_OPTIONS */ + +/* + * Protocol entry points from main code. + */ +static void ipcp_init(ppp_pcb *pcb); +static void ipcp_open(ppp_pcb *pcb); +static void ipcp_close(ppp_pcb *pcb, const char *reason); +static void ipcp_lowerup(ppp_pcb *pcb); +static void ipcp_lowerdown(ppp_pcb *pcb); +static void ipcp_input(ppp_pcb *pcb, u_char *p, int len); +static void ipcp_protrej(ppp_pcb *pcb); +#if PRINTPKT_SUPPORT +static int ipcp_printpkt(u_char *p, int plen, + void (*printer) (void *, const char *, ...), void *arg); +#endif /* PRINTPKT_SUPPORT */ +#if PPP_OPTIONS +static void ip_check_options (void); +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT +static int ip_demand_conf (int); +static int ip_active_pkt (u_char *, int); +#endif /* DEMAND_SUPPORT */ +#if 0 /* UNUSED */ +static void create_resolv (u32_t, u32_t); +#endif /* UNUSED */ + +const struct protent ipcp_protent = { + PPP_IPCP, + ipcp_init, + ipcp_input, + ipcp_protrej, + ipcp_lowerup, + ipcp_lowerdown, + ipcp_open, + ipcp_close, +#if PRINTPKT_SUPPORT + ipcp_printpkt, +#endif /* PRINTPKT_SUPPORT */ + NULL, + 1, +#if PRINTPKT_SUPPORT + "IPCP", + "IP", +#endif /* PRINTPKT_SUPPORT */ +#if PPP_OPTIONS + ipcp_option_list, + ip_check_options, +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT + ip_demand_conf, + ip_active_pkt +#endif /* DEMAND_SUPPORT */ +}; + +static void ipcp_clear_addrs(ppp_pcb *pcb, u32_t ouraddr, u32_t hisaddr, u8_t replacedefaultroute); + +/* + * Lengths of configuration options. + */ +#define CILEN_VOID 2 +#define CILEN_COMPRESS 4 /* min length for compression protocol opt. */ +#define CILEN_VJ 6 /* length for RFC1332 Van-Jacobson opt. */ +#define CILEN_ADDR 6 /* new-style single address option */ +#define CILEN_ADDRS 10 /* old-style dual address option */ + + +#define CODENAME(x) ((x) == CONFACK ? "ACK" : \ + (x) == CONFNAK ? "NAK" : "REJ") + +#if 0 /* UNUSED, already defined by lwIP */ +/* + * Make a string representation of a network IP address. + */ +char * +ip_ntoa(ipaddr) +u32_t ipaddr; +{ + static char b[64]; + + slprintf(b, sizeof(b), "%I", ipaddr); + return b; +} +#endif /* UNUSED, already defined by lwIP */ + +/* + * Option parsing. + */ +#if PPP_OPTIONS +/* + * setvjslots - set maximum number of connection slots for VJ compression + */ +static int +setvjslots(argv) + char **argv; +{ + int value; + +/* FIXME: found what int_option() did */ +#if PPP_OPTIONS + if (!int_option(*argv, &value)) + return 0; +#endif /* PPP_OPTIONS */ + + if (value < 2 || value > 16) { + option_error("vj-max-slots value must be between 2 and 16"); + return 0; + } + ipcp_wantoptions [0].maxslotindex = + ipcp_allowoptions[0].maxslotindex = value - 1; + slprintf(vj_value, sizeof(vj_value), "%d", value); + return 1; +} + +/* + * setdnsaddr - set the dns address(es) + */ +static int +setdnsaddr(argv) + char **argv; +{ + u32_t dns; + struct hostent *hp; + + dns = inet_addr(*argv); + if (dns == (u32_t) -1) { + if ((hp = gethostbyname(*argv)) == NULL) { + option_error("invalid address parameter '%s' for ms-dns option", + *argv); + return 0; + } + dns = *(u32_t *)hp->h_addr; + } + + /* We take the last 2 values given, the 2nd-last as the primary + and the last as the secondary. If only one is given it + becomes both primary and secondary. */ + if (ipcp_allowoptions[0].dnsaddr[1] == 0) + ipcp_allowoptions[0].dnsaddr[0] = dns; + else + ipcp_allowoptions[0].dnsaddr[0] = ipcp_allowoptions[0].dnsaddr[1]; + + /* always set the secondary address value. */ + ipcp_allowoptions[0].dnsaddr[1] = dns; + + return (1); +} + +/* + * setwinsaddr - set the wins address(es) + * This is primrarly used with the Samba package under UNIX or for pointing + * the caller to the existing WINS server on a Windows NT platform. + */ +static int +setwinsaddr(argv) + char **argv; +{ + u32_t wins; + struct hostent *hp; + + wins = inet_addr(*argv); + if (wins == (u32_t) -1) { + if ((hp = gethostbyname(*argv)) == NULL) { + option_error("invalid address parameter '%s' for ms-wins option", + *argv); + return 0; + } + wins = *(u32_t *)hp->h_addr; + } + + /* We take the last 2 values given, the 2nd-last as the primary + and the last as the secondary. If only one is given it + becomes both primary and secondary. */ + if (ipcp_allowoptions[0].winsaddr[1] == 0) + ipcp_allowoptions[0].winsaddr[0] = wins; + else + ipcp_allowoptions[0].winsaddr[0] = ipcp_allowoptions[0].winsaddr[1]; + + /* always set the secondary address value. */ + ipcp_allowoptions[0].winsaddr[1] = wins; + + return (1); +} + +/* + * setipaddr - Set the IP address + * If doit is 0, the call is to check whether this option is + * potentially an IP address specification. + * Not static so that plugins can call it to set the addresses + */ +int +setipaddr(arg, argv, doit) + char *arg; + char **argv; + int doit; +{ + struct hostent *hp; + char *colon; + u32_t local, remote; + ipcp_options *wo = &ipcp_wantoptions[0]; + static int prio_local = 0, prio_remote = 0; + + /* + * IP address pair separated by ":". + */ + if ((colon = strchr(arg, ':')) == NULL) + return 0; + if (!doit) + return 1; + + /* + * If colon first character, then no local addr. + */ + if (colon != arg && option_priority >= prio_local) { + *colon = '\0'; + if ((local = inet_addr(arg)) == (u32_t) -1) { + if ((hp = gethostbyname(arg)) == NULL) { + option_error("unknown host: %s", arg); + return 0; + } + local = *(u32_t *)hp->h_addr; + } + if (bad_ip_adrs(local)) { + option_error("bad local IP address %s", ip_ntoa(local)); + return 0; + } + if (local != 0) + wo->ouraddr = local; + *colon = ':'; + prio_local = option_priority; + } + + /* + * If colon last character, then no remote addr. + */ + if (*++colon != '\0' && option_priority >= prio_remote) { + if ((remote = inet_addr(colon)) == (u32_t) -1) { + if ((hp = gethostbyname(colon)) == NULL) { + option_error("unknown host: %s", colon); + return 0; + } + remote = *(u32_t *)hp->h_addr; + if (remote_name[0] == 0) + strlcpy(remote_name, colon, sizeof(remote_name)); + } + if (bad_ip_adrs(remote)) { + option_error("bad remote IP address %s", ip_ntoa(remote)); + return 0; + } + if (remote != 0) + wo->hisaddr = remote; + prio_remote = option_priority; + } + + return 1; +} + +static void +printipaddr(opt, printer, arg) + option_t *opt; + void (*printer) (void *, char *, ...); + void *arg; +{ + ipcp_options *wo = &ipcp_wantoptions[0]; + + if (wo->ouraddr != 0) + printer(arg, "%I", wo->ouraddr); + printer(arg, ":"); + if (wo->hisaddr != 0) + printer(arg, "%I", wo->hisaddr); +} + +/* + * setnetmask - set the netmask to be used on the interface. + */ +static int +setnetmask(argv) + char **argv; +{ + u32_t mask; + int n; + char *p; + + /* + * Unfortunately, if we use inet_addr, we can't tell whether + * a result of all 1s is an error or a valid 255.255.255.255. + */ + p = *argv; + n = parse_dotted_ip(p, &mask); + + mask = htonl(mask); + + if (n == 0 || p[n] != 0 || (netmask & ~mask) != 0) { + option_error("invalid netmask value '%s'", *argv); + return 0; + } + + netmask = mask; + slprintf(netmask_str, sizeof(netmask_str), "%I", mask); + + return (1); +} + +int +parse_dotted_ip(p, vp) + char *p; + u32_t *vp; +{ + int n; + u32_t v, b; + char *endp, *p0 = p; + + v = 0; + for (n = 3;; --n) { + b = strtoul(p, &endp, 0); + if (endp == p) + return 0; + if (b > 255) { + if (n < 3) + return 0; + /* accept e.g. 0xffffff00 */ + *vp = b; + return endp - p0; + } + v |= b << (n * 8); + p = endp; + if (n == 0) + break; + if (*p != '.') + return 0; + ++p; + } + *vp = v; + return p - p0; +} +#endif /* PPP_OPTIONS */ + +/* + * ipcp_init - Initialize IPCP. + */ +static void ipcp_init(ppp_pcb *pcb) { + fsm *f = &pcb->ipcp_fsm; + + ipcp_options *wo = &pcb->ipcp_wantoptions; + ipcp_options *ao = &pcb->ipcp_allowoptions; + + f->pcb = pcb; + f->protocol = PPP_IPCP; + f->callbacks = &ipcp_callbacks; + fsm_init(f); + + /* + * Some 3G modems use repeated IPCP NAKs as a way of stalling + * until they can contact a server on the network, so we increase + * the default number of NAKs we accept before we start treating + * them as rejects. + */ + f->maxnakloops = 100; + + memset(wo, 0, sizeof(*wo)); + memset(ao, 0, sizeof(*ao)); + + wo->neg_addr = wo->old_addrs = 1; + wo->neg_vj = 1; + wo->vj_protocol = IPCP_VJ_COMP; + wo->maxslotindex = MAX_STATES - 1; /* really max index */ + wo->cflag = 1; + +#if 0 /* UNUSED */ + /* wanting default route by default */ + wo->default_route = 1; +#endif /* UNUSED */ + + /* max slots and slot-id compression are currently hardwired in */ + /* ppp_if.c to 16 and 1, this needs to be changed (among other */ + /* things) gmc */ + + ao->neg_addr = ao->old_addrs = 1; + ao->neg_vj = 1; + ao->maxslotindex = MAX_STATES - 1; + ao->cflag = 1; + +#if 0 /* UNUSED */ + /* + * XXX These control whether the user may use the proxyarp + * and defaultroute options. + */ + ao->proxy_arp = 1; + ao->default_route = 1; +#endif /* UNUSED */ +} + + +/* + * ipcp_open - IPCP is allowed to come up. + */ +static void ipcp_open(ppp_pcb *pcb) { + fsm *f = &pcb->ipcp_fsm; + fsm_open(f); + pcb->ipcp_is_open = 1; +} + + +/* + * ipcp_close - Take IPCP down. + */ +static void ipcp_close(ppp_pcb *pcb, const char *reason) { + fsm *f = &pcb->ipcp_fsm; + fsm_close(f, reason); +} + + +/* + * ipcp_lowerup - The lower layer is up. + */ +static void ipcp_lowerup(ppp_pcb *pcb) { + fsm *f = &pcb->ipcp_fsm; + fsm_lowerup(f); +} + + +/* + * ipcp_lowerdown - The lower layer is down. + */ +static void ipcp_lowerdown(ppp_pcb *pcb) { + fsm *f = &pcb->ipcp_fsm; + fsm_lowerdown(f); +} + + +/* + * ipcp_input - Input IPCP packet. + */ +static void ipcp_input(ppp_pcb *pcb, u_char *p, int len) { + fsm *f = &pcb->ipcp_fsm; + fsm_input(f, p, len); +} + + +/* + * ipcp_protrej - A Protocol-Reject was received for IPCP. + * + * Pretend the lower layer went down, so we shut up. + */ +static void ipcp_protrej(ppp_pcb *pcb) { + fsm *f = &pcb->ipcp_fsm; + fsm_lowerdown(f); +} + + +/* + * ipcp_resetci - Reset our CI. + * Called by fsm_sconfreq, Send Configure Request. + */ +static void ipcp_resetci(fsm *f) { + ppp_pcb *pcb = f->pcb; + ipcp_options *wo = &pcb->ipcp_wantoptions; + ipcp_options *go = &pcb->ipcp_gotoptions; + ipcp_options *ao = &pcb->ipcp_allowoptions; + + wo->req_addr = (wo->neg_addr || wo->old_addrs) && + (ao->neg_addr || ao->old_addrs); + if (wo->ouraddr == 0) + wo->accept_local = 1; + if (wo->hisaddr == 0) + wo->accept_remote = 1; + wo->req_dns1 = pcb->settings.usepeerdns; /* Request DNS addresses from the peer */ + wo->req_dns2 = pcb->settings.usepeerdns; + *go = *wo; + if (!pcb->ask_for_local) + go->ouraddr = 0; +#if 0 /* UNUSED */ + if (ip_choose_hook) { + ip_choose_hook(&wo->hisaddr); + if (wo->hisaddr) { + wo->accept_remote = 0; + } + } +#endif /* UNUSED */ + BZERO(&pcb->ipcp_hisoptions, sizeof(ipcp_options)); +} + + +/* + * ipcp_cilen - Return length of our CI. + * Called by fsm_sconfreq, Send Configure Request. + */ +static int ipcp_cilen(fsm *f) { + ppp_pcb *pcb = f->pcb; + ipcp_options *go = &pcb->ipcp_gotoptions; + ipcp_options *wo = &pcb->ipcp_wantoptions; + ipcp_options *ho = &pcb->ipcp_hisoptions; + +#define LENCIADDRS(neg) (neg ? CILEN_ADDRS : 0) +#define LENCIVJ(neg, old) (neg ? (old? CILEN_COMPRESS : CILEN_VJ) : 0) +#define LENCIADDR(neg) (neg ? CILEN_ADDR : 0) +#define LENCIDNS(neg) LENCIADDR(neg) +#define LENCIWINS(neg) LENCIADDR(neg) + + /* + * First see if we want to change our options to the old + * forms because we have received old forms from the peer. + */ + if (go->neg_addr && go->old_addrs && !ho->neg_addr && ho->old_addrs) + go->neg_addr = 0; + if (wo->neg_vj && !go->neg_vj && !go->old_vj) { + /* try an older style of VJ negotiation */ + /* use the old style only if the peer did */ + if (ho->neg_vj && ho->old_vj) { + go->neg_vj = 1; + go->old_vj = 1; + go->vj_protocol = ho->vj_protocol; + } + } + + return (LENCIADDRS(!go->neg_addr && go->old_addrs) + + LENCIVJ(go->neg_vj, go->old_vj) + + LENCIADDR(go->neg_addr) + + LENCIDNS(go->req_dns1) + + LENCIDNS(go->req_dns2) + + LENCIWINS(go->winsaddr[0]) + + LENCIWINS(go->winsaddr[1])) ; +} + + +/* + * ipcp_addci - Add our desired CIs to a packet. + * Called by fsm_sconfreq, Send Configure Request. + */ +static void ipcp_addci(fsm *f, u_char *ucp, int *lenp) { + ppp_pcb *pcb = f->pcb; + ipcp_options *go = &pcb->ipcp_gotoptions; + int len = *lenp; + +#define ADDCIADDRS(opt, neg, val1, val2) \ + if (neg) { \ + if (len >= CILEN_ADDRS) { \ + u32_t l; \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_ADDRS, ucp); \ + l = ntohl(val1); \ + PUTLONG(l, ucp); \ + l = ntohl(val2); \ + PUTLONG(l, ucp); \ + len -= CILEN_ADDRS; \ + } else \ + go->old_addrs = 0; \ + } + +#define ADDCIVJ(opt, neg, val, old, maxslotindex, cflag) \ + if (neg) { \ + int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \ + if (len >= vjlen) { \ + PUTCHAR(opt, ucp); \ + PUTCHAR(vjlen, ucp); \ + PUTSHORT(val, ucp); \ + if (!old) { \ + PUTCHAR(maxslotindex, ucp); \ + PUTCHAR(cflag, ucp); \ + } \ + len -= vjlen; \ + } else \ + neg = 0; \ + } + +#define ADDCIADDR(opt, neg, val) \ + if (neg) { \ + if (len >= CILEN_ADDR) { \ + u32_t l; \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_ADDR, ucp); \ + l = ntohl(val); \ + PUTLONG(l, ucp); \ + len -= CILEN_ADDR; \ + } else \ + neg = 0; \ + } + +#define ADDCIDNS(opt, neg, addr) \ + if (neg) { \ + if (len >= CILEN_ADDR) { \ + u32_t l; \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_ADDR, ucp); \ + l = ntohl(addr); \ + PUTLONG(l, ucp); \ + len -= CILEN_ADDR; \ + } else \ + neg = 0; \ + } + +#define ADDCIWINS(opt, addr) \ + if (addr) { \ + if (len >= CILEN_ADDR) { \ + u32_t l; \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_ADDR, ucp); \ + l = ntohl(addr); \ + PUTLONG(l, ucp); \ + len -= CILEN_ADDR; \ + } else \ + addr = 0; \ + } + + ADDCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, go->ouraddr, + go->hisaddr); + + ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj, + go->maxslotindex, go->cflag); + + ADDCIADDR(CI_ADDR, go->neg_addr, go->ouraddr); + + ADDCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]); + + ADDCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]); + + ADDCIWINS(CI_MS_WINS1, go->winsaddr[0]); + + ADDCIWINS(CI_MS_WINS2, go->winsaddr[1]); + + *lenp -= len; +} + + +/* + * ipcp_ackci - Ack our CIs. + * Called by fsm_rconfack, Receive Configure ACK. + * + * Returns: + * 0 - Ack was bad. + * 1 - Ack was good. + */ +static int ipcp_ackci(fsm *f, u_char *p, int len) { + ppp_pcb *pcb = f->pcb; + ipcp_options *go = &pcb->ipcp_gotoptions; + u_short cilen, citype, cishort; + u32_t cilong; + u_char cimaxslotindex, cicflag; + + /* + * CIs must be in exactly the same order that we sent... + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ + +#define ACKCIADDRS(opt, neg, val1, val2) \ + if (neg) { \ + u32_t l; \ + if ((len -= CILEN_ADDRS) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_ADDRS || \ + citype != opt) \ + goto bad; \ + GETLONG(l, p); \ + cilong = htonl(l); \ + if (val1 != cilong) \ + goto bad; \ + GETLONG(l, p); \ + cilong = htonl(l); \ + if (val2 != cilong) \ + goto bad; \ + } + +#define ACKCIVJ(opt, neg, val, old, maxslotindex, cflag) \ + if (neg) { \ + int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \ + if ((len -= vjlen) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != vjlen || \ + citype != opt) \ + goto bad; \ + GETSHORT(cishort, p); \ + if (cishort != val) \ + goto bad; \ + if (!old) { \ + GETCHAR(cimaxslotindex, p); \ + if (cimaxslotindex != maxslotindex) \ + goto bad; \ + GETCHAR(cicflag, p); \ + if (cicflag != cflag) \ + goto bad; \ + } \ + } + +#define ACKCIADDR(opt, neg, val) \ + if (neg) { \ + u32_t l; \ + if ((len -= CILEN_ADDR) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_ADDR || \ + citype != opt) \ + goto bad; \ + GETLONG(l, p); \ + cilong = htonl(l); \ + if (val != cilong) \ + goto bad; \ + } + +#define ACKCIDNS(opt, neg, addr) \ + if (neg) { \ + u32_t l; \ + if ((len -= CILEN_ADDR) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_ADDR || citype != opt) \ + goto bad; \ + GETLONG(l, p); \ + cilong = htonl(l); \ + if (addr != cilong) \ + goto bad; \ + } + +#define ACKCIWINS(opt, addr) \ + if (addr) { \ + u32_t l; \ + if ((len -= CILEN_ADDR) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_ADDR || citype != opt) \ + goto bad; \ + GETLONG(l, p); \ + cilong = htonl(l); \ + if (addr != cilong) \ + goto bad; \ + } + + ACKCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, go->ouraddr, + go->hisaddr); + + ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj, + go->maxslotindex, go->cflag); + + ACKCIADDR(CI_ADDR, go->neg_addr, go->ouraddr); + + ACKCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]); + + ACKCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]); + + ACKCIWINS(CI_MS_WINS1, go->winsaddr[0]); + + ACKCIWINS(CI_MS_WINS2, go->winsaddr[1]); + + /* + * If there are any remaining CIs, then this packet is bad. + */ + if (len != 0) + goto bad; + return (1); + +bad: + IPCPDEBUG(("ipcp_ackci: received bad Ack!")); + return (0); +} + +/* + * ipcp_nakci - Peer has sent a NAK for some of our CIs. + * This should not modify any state if the Nak is bad + * or if IPCP is in the OPENED state. + * Calback from fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject. + * + * Returns: + * 0 - Nak was bad. + * 1 - Nak was good. + */ +static int ipcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) { + ppp_pcb *pcb = f->pcb; + ipcp_options *go = &pcb->ipcp_gotoptions; + u_char cimaxslotindex, cicflag; + u_char citype, cilen, *next; + u_short cishort; + u32_t ciaddr1, ciaddr2, l, cidnsaddr; + ipcp_options no; /* options we've seen Naks for */ + ipcp_options try_; /* options to request next time */ + + BZERO(&no, sizeof(no)); + try_ = *go; + + /* + * Any Nak'd CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define NAKCIADDRS(opt, neg, code) \ + if ((neg) && \ + (cilen = p[1]) == CILEN_ADDRS && \ + len >= cilen && \ + p[0] == opt) { \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + ciaddr1 = htonl(l); \ + GETLONG(l, p); \ + ciaddr2 = htonl(l); \ + no.old_addrs = 1; \ + code \ + } + +#define NAKCIVJ(opt, neg, code) \ + if (go->neg && \ + ((cilen = p[1]) == CILEN_COMPRESS || cilen == CILEN_VJ) && \ + len >= cilen && \ + p[0] == opt) { \ + len -= cilen; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + no.neg = 1; \ + code \ + } + +#define NAKCIADDR(opt, neg, code) \ + if (go->neg && \ + (cilen = p[1]) == CILEN_ADDR && \ + len >= cilen && \ + p[0] == opt) { \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + ciaddr1 = htonl(l); \ + no.neg = 1; \ + code \ + } + +#define NAKCIDNS(opt, neg, code) \ + if (go->neg && \ + ((cilen = p[1]) == CILEN_ADDR) && \ + len >= cilen && \ + p[0] == opt) { \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + cidnsaddr = htonl(l); \ + no.neg = 1; \ + code \ + } + + /* + * Accept the peer's idea of {our,his} address, if different + * from our idea, only if the accept_{local,remote} flag is set. + */ + NAKCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, + if (treat_as_reject) { + try_.old_addrs = 0; + } else { + if (go->accept_local && ciaddr1) { + /* take his idea of our address */ + try_.ouraddr = ciaddr1; + } + if (go->accept_remote && ciaddr2) { + /* take his idea of his address */ + try_.hisaddr = ciaddr2; + } + } + ); + + /* + * Accept the peer's value of maxslotindex provided that it + * is less than what we asked for. Turn off slot-ID compression + * if the peer wants. Send old-style compress-type option if + * the peer wants. + */ + NAKCIVJ(CI_COMPRESSTYPE, neg_vj, + if (treat_as_reject) { + try_.neg_vj = 0; + } else if (cilen == CILEN_VJ) { + GETCHAR(cimaxslotindex, p); + GETCHAR(cicflag, p); + if (cishort == IPCP_VJ_COMP) { + try_.old_vj = 0; + if (cimaxslotindex < go->maxslotindex) + try_.maxslotindex = cimaxslotindex; + if (!cicflag) + try_.cflag = 0; + } else { + try_.neg_vj = 0; + } + } else { + if (cishort == IPCP_VJ_COMP || cishort == IPCP_VJ_COMP_OLD) { + try_.old_vj = 1; + try_.vj_protocol = cishort; + } else { + try_.neg_vj = 0; + } + } + ); + + NAKCIADDR(CI_ADDR, neg_addr, + if (treat_as_reject) { + try_.neg_addr = 0; + try_.old_addrs = 0; + } else if (go->accept_local && ciaddr1) { + /* take his idea of our address */ + try_.ouraddr = ciaddr1; + } + ); + + NAKCIDNS(CI_MS_DNS1, req_dns1, + if (treat_as_reject) { + try_.req_dns1 = 0; + } else { + try_.dnsaddr[0] = cidnsaddr; + } + ); + + NAKCIDNS(CI_MS_DNS2, req_dns2, + if (treat_as_reject) { + try_.req_dns2 = 0; + } else { + try_.dnsaddr[1] = cidnsaddr; + } + ); + + /* + * There may be remaining CIs, if the peer is requesting negotiation + * on an option that we didn't include in our request packet. + * If they want to negotiate about IP addresses, we comply. + * If they want us to ask for compression, we refuse. + * If they want us to ask for ms-dns, we do that, since some + * peers get huffy if we don't. + */ + while (len >= CILEN_VOID) { + GETCHAR(citype, p); + GETCHAR(cilen, p); + if ( cilen < CILEN_VOID || (len -= cilen) < 0 ) + goto bad; + next = p + cilen - 2; + + switch (citype) { + case CI_COMPRESSTYPE: + if (go->neg_vj || no.neg_vj || + (cilen != CILEN_VJ && cilen != CILEN_COMPRESS)) + goto bad; + no.neg_vj = 1; + break; + case CI_ADDRS: + if ((!go->neg_addr && go->old_addrs) || no.old_addrs + || cilen != CILEN_ADDRS) + goto bad; + try_.neg_addr = 0; + GETLONG(l, p); + ciaddr1 = htonl(l); + if (ciaddr1 && go->accept_local) + try_.ouraddr = ciaddr1; + GETLONG(l, p); + ciaddr2 = htonl(l); + if (ciaddr2 && go->accept_remote) + try_.hisaddr = ciaddr2; + no.old_addrs = 1; + break; + case CI_ADDR: + if (go->neg_addr || no.neg_addr || cilen != CILEN_ADDR) + goto bad; + try_.old_addrs = 0; + GETLONG(l, p); + ciaddr1 = htonl(l); + if (ciaddr1 && go->accept_local) + try_.ouraddr = ciaddr1; + if (try_.ouraddr != 0) + try_.neg_addr = 1; + no.neg_addr = 1; + break; + case CI_MS_DNS1: + if (go->req_dns1 || no.req_dns1 || cilen != CILEN_ADDR) + goto bad; + GETLONG(l, p); + try_.dnsaddr[0] = htonl(l); + try_.req_dns1 = 1; + no.req_dns1 = 1; + break; + case CI_MS_DNS2: + if (go->req_dns2 || no.req_dns2 || cilen != CILEN_ADDR) + goto bad; + GETLONG(l, p); + try_.dnsaddr[1] = htonl(l); + try_.req_dns2 = 1; + no.req_dns2 = 1; + break; + case CI_MS_WINS1: + case CI_MS_WINS2: + if (cilen != CILEN_ADDR) + goto bad; + GETLONG(l, p); + ciaddr1 = htonl(l); + if (ciaddr1) + try_.winsaddr[citype == CI_MS_WINS2] = ciaddr1; + break; + default: + break; + } + p = next; + } + + /* + * OK, the Nak is good. Now we can update state. + * If there are any remaining options, we ignore them. + */ + if (f->state != PPP_FSM_OPENED) + *go = try_; + + return 1; + +bad: + IPCPDEBUG(("ipcp_nakci: received bad Nak!")); + return 0; +} + + +/* + * ipcp_rejci - Reject some of our CIs. + * Callback from fsm_rconfnakrej. + */ +static int ipcp_rejci(fsm *f, u_char *p, int len) { + ppp_pcb *pcb = f->pcb; + ipcp_options *go = &pcb->ipcp_gotoptions; + u_char cimaxslotindex, ciflag, cilen; + u_short cishort; + u32_t cilong; + ipcp_options try_; /* options to request next time */ + + try_ = *go; + /* + * Any Rejected CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define REJCIADDRS(opt, neg, val1, val2) \ + if ((neg) && \ + (cilen = p[1]) == CILEN_ADDRS && \ + len >= cilen && \ + p[0] == opt) { \ + u32_t l; \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + cilong = htonl(l); \ + /* Check rejected value. */ \ + if (cilong != val1) \ + goto bad; \ + GETLONG(l, p); \ + cilong = htonl(l); \ + /* Check rejected value. */ \ + if (cilong != val2) \ + goto bad; \ + try_.old_addrs = 0; \ + } + +#define REJCIVJ(opt, neg, val, old, maxslot, cflag) \ + if (go->neg && \ + p[1] == (old? CILEN_COMPRESS : CILEN_VJ) && \ + len >= p[1] && \ + p[0] == opt) { \ + len -= p[1]; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + /* Check rejected value. */ \ + if (cishort != val) \ + goto bad; \ + if (!old) { \ + GETCHAR(cimaxslotindex, p); \ + if (cimaxslotindex != maxslot) \ + goto bad; \ + GETCHAR(ciflag, p); \ + if (ciflag != cflag) \ + goto bad; \ + } \ + try_.neg = 0; \ + } + +#define REJCIADDR(opt, neg, val) \ + if (go->neg && \ + (cilen = p[1]) == CILEN_ADDR && \ + len >= cilen && \ + p[0] == opt) { \ + u32_t l; \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + cilong = htonl(l); \ + /* Check rejected value. */ \ + if (cilong != val) \ + goto bad; \ + try_.neg = 0; \ + } + +#define REJCIDNS(opt, neg, dnsaddr) \ + if (go->neg && \ + ((cilen = p[1]) == CILEN_ADDR) && \ + len >= cilen && \ + p[0] == opt) { \ + u32_t l; \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + cilong = htonl(l); \ + /* Check rejected value. */ \ + if (cilong != dnsaddr) \ + goto bad; \ + try_.neg = 0; \ + } + +#define REJCIWINS(opt, addr) \ + if (addr && \ + ((cilen = p[1]) == CILEN_ADDR) && \ + len >= cilen && \ + p[0] == opt) { \ + u32_t l; \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + cilong = htonl(l); \ + /* Check rejected value. */ \ + if (cilong != addr) \ + goto bad; \ + try_.winsaddr[opt == CI_MS_WINS2] = 0; \ + } + + REJCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, + go->ouraddr, go->hisaddr); + + REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol, go->old_vj, + go->maxslotindex, go->cflag); + + REJCIADDR(CI_ADDR, neg_addr, go->ouraddr); + + REJCIDNS(CI_MS_DNS1, req_dns1, go->dnsaddr[0]); + + REJCIDNS(CI_MS_DNS2, req_dns2, go->dnsaddr[1]); + + REJCIWINS(CI_MS_WINS1, go->winsaddr[0]); + + REJCIWINS(CI_MS_WINS2, go->winsaddr[1]); + + /* + * If there are any remaining CIs, then this packet is bad. + */ + if (len != 0) + goto bad; + /* + * Now we can update state. + */ + if (f->state != PPP_FSM_OPENED) + *go = try_; + return 1; + +bad: + IPCPDEBUG(("ipcp_rejci: received bad Reject!")); + return 0; +} + + +/* + * ipcp_reqci - Check the peer's requested CIs and send appropriate response. + * Callback from fsm_rconfreq, Receive Configure Request + * + * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified + * appropriately. If reject_if_disagree is non-zero, doesn't return + * CONFNAK; returns CONFREJ if it can't return CONFACK. + * + * inp = Requested CIs + * len = Length of requested CIs + */ +static int ipcp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree) { + ppp_pcb *pcb = f->pcb; + ipcp_options *wo = &pcb->ipcp_wantoptions; + ipcp_options *ho = &pcb->ipcp_hisoptions; + ipcp_options *ao = &pcb->ipcp_allowoptions; + u_char *cip, *next; /* Pointer to current and next CIs */ + u_short cilen, citype; /* Parsed len, type */ + u_short cishort; /* Parsed short value */ + u32_t tl, ciaddr1, ciaddr2;/* Parsed address values */ + int rc = CONFACK; /* Final packet return code */ + int orc; /* Individual option return code */ + u_char *p; /* Pointer to next char to parse */ + u_char *ucp = inp; /* Pointer to current output char */ + int l = *len; /* Length left */ + u_char maxslotindex, cflag; + int d; + + /* + * Reset all his options. + */ + BZERO(ho, sizeof(*ho)); + + /* + * Process all his options. + */ + next = inp; + while (l) { + orc = CONFACK; /* Assume success */ + cip = p = next; /* Remember begining of CI */ + if (l < 2 || /* Not enough data for CI header or */ + p[1] < 2 || /* CI length too small or */ + p[1] > l) { /* CI length too big? */ + IPCPDEBUG(("ipcp_reqci: bad CI length!")); + orc = CONFREJ; /* Reject bad CI */ + cilen = l; /* Reject till end of packet */ + l = 0; /* Don't loop again */ + goto endswitch; + } + GETCHAR(citype, p); /* Parse CI type */ + GETCHAR(cilen, p); /* Parse CI length */ + l -= cilen; /* Adjust remaining length */ + next += cilen; /* Step to next CI */ + + switch (citype) { /* Check CI type */ + case CI_ADDRS: + if (!ao->old_addrs || ho->neg_addr || + cilen != CILEN_ADDRS) { /* Check CI length */ + orc = CONFREJ; /* Reject CI */ + break; + } + + /* + * If he has no address, or if we both have his address but + * disagree about it, then NAK it with our idea. + * In particular, if we don't know his address, but he does, + * then accept it. + */ + GETLONG(tl, p); /* Parse source address (his) */ + ciaddr1 = htonl(tl); + if (ciaddr1 != wo->hisaddr + && (ciaddr1 == 0 || !wo->accept_remote)) { + orc = CONFNAK; + if (!reject_if_disagree) { + DECPTR(sizeof(u32_t), p); + tl = ntohl(wo->hisaddr); + PUTLONG(tl, p); + } + } else if (ciaddr1 == 0 && wo->hisaddr == 0) { + /* + * If neither we nor he knows his address, reject the option. + */ + orc = CONFREJ; + wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */ + break; + } + + /* + * If he doesn't know our address, or if we both have our address + * but disagree about it, then NAK it with our idea. + */ + GETLONG(tl, p); /* Parse desination address (ours) */ + ciaddr2 = htonl(tl); + if (ciaddr2 != wo->ouraddr) { + if (ciaddr2 == 0 || !wo->accept_local) { + orc = CONFNAK; + if (!reject_if_disagree) { + DECPTR(sizeof(u32_t), p); + tl = ntohl(wo->ouraddr); + PUTLONG(tl, p); + } + } else { + wo->ouraddr = ciaddr2; /* accept peer's idea */ + } + } + + ho->old_addrs = 1; + ho->hisaddr = ciaddr1; + ho->ouraddr = ciaddr2; + break; + + case CI_ADDR: + if (!ao->neg_addr || ho->old_addrs || + cilen != CILEN_ADDR) { /* Check CI length */ + orc = CONFREJ; /* Reject CI */ + break; + } + + /* + * If he has no address, or if we both have his address but + * disagree about it, then NAK it with our idea. + * In particular, if we don't know his address, but he does, + * then accept it. + */ + GETLONG(tl, p); /* Parse source address (his) */ + ciaddr1 = htonl(tl); + if (ciaddr1 != wo->hisaddr + && (ciaddr1 == 0 || !wo->accept_remote)) { + orc = CONFNAK; + if (!reject_if_disagree) { + DECPTR(sizeof(u32_t), p); + tl = ntohl(wo->hisaddr); + PUTLONG(tl, p); + } + } else if (ciaddr1 == 0 && wo->hisaddr == 0) { + /* + * Don't ACK an address of 0.0.0.0 - reject it instead. + */ + orc = CONFREJ; + wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */ + break; + } + + ho->neg_addr = 1; + ho->hisaddr = ciaddr1; + break; + + case CI_MS_DNS1: + case CI_MS_DNS2: + /* Microsoft primary or secondary DNS request */ + d = citype == CI_MS_DNS2; + + /* If we do not have a DNS address then we cannot send it */ + if (ao->dnsaddr[d] == 0 || + cilen != CILEN_ADDR) { /* Check CI length */ + orc = CONFREJ; /* Reject CI */ + break; + } + GETLONG(tl, p); + if (htonl(tl) != ao->dnsaddr[d]) { + DECPTR(sizeof(u32_t), p); + tl = ntohl(ao->dnsaddr[d]); + PUTLONG(tl, p); + orc = CONFNAK; + } + break; + + case CI_MS_WINS1: + case CI_MS_WINS2: + /* Microsoft primary or secondary WINS request */ + d = citype == CI_MS_WINS2; + + /* If we do not have a DNS address then we cannot send it */ + if (ao->winsaddr[d] == 0 || + cilen != CILEN_ADDR) { /* Check CI length */ + orc = CONFREJ; /* Reject CI */ + break; + } + GETLONG(tl, p); + if (htonl(tl) != ao->winsaddr[d]) { + DECPTR(sizeof(u32_t), p); + tl = ntohl(ao->winsaddr[d]); + PUTLONG(tl, p); + orc = CONFNAK; + } + break; + + case CI_COMPRESSTYPE: + if (!ao->neg_vj || + (cilen != CILEN_VJ && cilen != CILEN_COMPRESS)) { + orc = CONFREJ; + break; + } + GETSHORT(cishort, p); + + if (!(cishort == IPCP_VJ_COMP || + (cishort == IPCP_VJ_COMP_OLD && cilen == CILEN_COMPRESS))) { + orc = CONFREJ; + break; + } + + ho->neg_vj = 1; + ho->vj_protocol = cishort; + if (cilen == CILEN_VJ) { + GETCHAR(maxslotindex, p); + if (maxslotindex > ao->maxslotindex) { + orc = CONFNAK; + if (!reject_if_disagree){ + DECPTR(1, p); + PUTCHAR(ao->maxslotindex, p); + } + } + GETCHAR(cflag, p); + if (cflag && !ao->cflag) { + orc = CONFNAK; + if (!reject_if_disagree){ + DECPTR(1, p); + PUTCHAR(wo->cflag, p); + } + } + ho->maxslotindex = maxslotindex; + ho->cflag = cflag; + } else { + ho->old_vj = 1; + ho->maxslotindex = MAX_STATES - 1; + ho->cflag = 1; + } + break; + + default: + orc = CONFREJ; + break; + } +endswitch: + if (orc == CONFACK && /* Good CI */ + rc != CONFACK) /* but prior CI wasnt? */ + continue; /* Don't send this one */ + + if (orc == CONFNAK) { /* Nak this CI? */ + if (reject_if_disagree) /* Getting fed up with sending NAKs? */ + orc = CONFREJ; /* Get tough if so */ + else { + if (rc == CONFREJ) /* Rejecting prior CI? */ + continue; /* Don't send this one */ + if (rc == CONFACK) { /* Ack'd all prior CIs? */ + rc = CONFNAK; /* Not anymore... */ + ucp = inp; /* Backup */ + } + } + } + + if (orc == CONFREJ && /* Reject this CI */ + rc != CONFREJ) { /* but no prior ones? */ + rc = CONFREJ; + ucp = inp; /* Backup */ + } + + /* Need to move CI? */ + if (ucp != cip) + MEMCPY(ucp, cip, cilen); /* Move it */ + + /* Update output pointer */ + INCPTR(cilen, ucp); + } + + /* + * If we aren't rejecting this packet, and we want to negotiate + * their address, and they didn't send their address, then we + * send a NAK with a CI_ADDR option appended. We assume the + * input buffer is long enough that we can append the extra + * option safely. + */ + if (rc != CONFREJ && !ho->neg_addr && !ho->old_addrs && + wo->req_addr && !reject_if_disagree && !pcb->settings.noremoteip) { + if (rc == CONFACK) { + rc = CONFNAK; + ucp = inp; /* reset pointer */ + wo->req_addr = 0; /* don't ask again */ + } + PUTCHAR(CI_ADDR, ucp); + PUTCHAR(CILEN_ADDR, ucp); + tl = ntohl(wo->hisaddr); + PUTLONG(tl, ucp); + } + + *len = ucp - inp; /* Compute output length */ + IPCPDEBUG(("ipcp: returning Configure-%s", CODENAME(rc))); + return (rc); /* Return final code */ +} + + +#if 0 /* UNUSED */ +/* + * ip_check_options - check that any IP-related options are OK, + * and assign appropriate defaults. + */ +static void +ip_check_options() +{ + struct hostent *hp; + u32_t local; + ipcp_options *wo = &ipcp_wantoptions[0]; + + /* + * Default our local IP address based on our hostname. + * If local IP address already given, don't bother. + */ + if (wo->ouraddr == 0 && !disable_defaultip) { + /* + * Look up our hostname (possibly with domain name appended) + * and take the first IP address as our local IP address. + * If there isn't an IP address for our hostname, too bad. + */ + wo->accept_local = 1; /* don't insist on this default value */ + if ((hp = gethostbyname(hostname)) != NULL) { + local = *(u32_t *)hp->h_addr; + if (local != 0 && !bad_ip_adrs(local)) + wo->ouraddr = local; + } + } + ask_for_local = wo->ouraddr != 0 || !disable_defaultip; +} +#endif /* UNUSED */ + +#if DEMAND_SUPPORT +/* + * ip_demand_conf - configure the interface as though + * IPCP were up, for use with dial-on-demand. + */ +static int +ip_demand_conf(u) + int u; +{ + ppp_pcb *pcb = &ppp_pcb_list[u]; + ipcp_options *wo = &ipcp_wantoptions[u]; + + if (wo->hisaddr == 0 && !pcb->settings.noremoteip) { + /* make up an arbitrary address for the peer */ + wo->hisaddr = htonl(0x0a707070 + ifunit); + wo->accept_remote = 1; + } + if (wo->ouraddr == 0) { + /* make up an arbitrary address for us */ + wo->ouraddr = htonl(0x0a404040 + ifunit); + wo->accept_local = 1; + ask_for_local = 0; /* don't tell the peer this address */ + } + if (!sifaddr(pcb, wo->ouraddr, wo->hisaddr, get_mask(wo->ouraddr))) + return 0; + if (!sifup(pcb)) + return 0; + if (!sifnpmode(pcb, PPP_IP, NPMODE_QUEUE)) + return 0; +#if 0 /* UNUSED */ + if (wo->default_route) + if (sifdefaultroute(pcb, wo->ouraddr, wo->hisaddr, + wo->replace_default_route)) + default_route_set[u] = 1; +#endif /* UNUSED */ + if (wo->proxy_arp) + if (sifproxyarp(pcb, wo->hisaddr)) + proxy_arp_set[u] = 1; + + ppp_notice("local IP address %I", wo->ouraddr); + if (wo->hisaddr) + ppp_notice("remote IP address %I", wo->hisaddr); + + return 1; +} +#endif /* DEMAND_SUPPORT */ + +/* + * ipcp_up - IPCP has come UP. + * + * Configure the IP network interface appropriately and bring it up. + */ +static void ipcp_up(fsm *f) { + ppp_pcb *pcb = f->pcb; + u32_t mask; + ipcp_options *ho = &pcb->ipcp_hisoptions; + ipcp_options *go = &pcb->ipcp_gotoptions; + ipcp_options *wo = &pcb->ipcp_wantoptions; + + IPCPDEBUG(("ipcp: up")); + + /* + * We must have a non-zero IP address for both ends of the link. + */ + if (!ho->neg_addr && !ho->old_addrs) + ho->hisaddr = wo->hisaddr; + + if (!(go->neg_addr || go->old_addrs) && (wo->neg_addr || wo->old_addrs) + && wo->ouraddr != 0) { + ppp_error("Peer refused to agree to our IP address"); + ipcp_close(f->pcb, "Refused our IP address"); + return; + } + if (go->ouraddr == 0) { + ppp_error("Could not determine local IP address"); + ipcp_close(f->pcb, "Could not determine local IP address"); + return; + } + if (ho->hisaddr == 0 && !pcb->settings.noremoteip) { + ho->hisaddr = htonl(0x0a404040); + ppp_warn("Could not determine remote IP address: defaulting to %I", + ho->hisaddr); + } +#if 0 /* UNUSED */ + script_setenv("IPLOCAL", ip_ntoa(go->ouraddr), 0); + if (ho->hisaddr != 0) + script_setenv("IPREMOTE", ip_ntoa(ho->hisaddr), 1); +#endif /* UNUSED */ + + if (!go->req_dns1) + go->dnsaddr[0] = 0; + if (!go->req_dns2) + go->dnsaddr[1] = 0; +#if 0 /* UNUSED */ + if (go->dnsaddr[0]) + script_setenv("DNS1", ip_ntoa(go->dnsaddr[0]), 0); + if (go->dnsaddr[1]) + script_setenv("DNS2", ip_ntoa(go->dnsaddr[1]), 0); +#endif /* UNUSED */ + if (pcb->settings.usepeerdns && (go->dnsaddr[0] || go->dnsaddr[1])) { + sdns(pcb, go->dnsaddr[0], go->dnsaddr[1]); +#if 0 /* UNUSED */ + script_setenv("USEPEERDNS", "1", 0); + create_resolv(go->dnsaddr[0], go->dnsaddr[1]); +#endif /* UNUSED */ + } + +/* FIXME: check why it fails, just to know */ +#if 0 /* Unused */ + /* + * Check that the peer is allowed to use the IP address it wants. + */ + if (ho->hisaddr != 0 && !auth_ip_addr(f->unit, ho->hisaddr)) { + ppp_error("Peer is not authorized to use remote address %I", ho->hisaddr); + ipcp_close(f->unit, "Unauthorized remote IP address"); + return; + } +#endif /* Unused */ + + /* set tcp compression */ + sifvjcomp(pcb, ho->neg_vj, ho->cflag, ho->maxslotindex); + +#if DEMAND_SUPPORT + /* + * If we are doing dial-on-demand, the interface is already + * configured, so we put out any saved-up packets, then set the + * interface to pass IP packets. + */ + if (demand) { + if (go->ouraddr != wo->ouraddr || ho->hisaddr != wo->hisaddr) { + ipcp_clear_addrs(f->unit, wo->ouraddr, wo->hisaddr, + wo->replace_default_route); + if (go->ouraddr != wo->ouraddr) { + ppp_warn("Local IP address changed to %I", go->ouraddr); + script_setenv("OLDIPLOCAL", ip_ntoa(wo->ouraddr), 0); + wo->ouraddr = go->ouraddr; + } else + script_unsetenv("OLDIPLOCAL"); + if (ho->hisaddr != wo->hisaddr && wo->hisaddr != 0) { + ppp_warn("Remote IP address changed to %I", ho->hisaddr); + script_setenv("OLDIPREMOTE", ip_ntoa(wo->hisaddr), 0); + wo->hisaddr = ho->hisaddr; + } else + script_unsetenv("OLDIPREMOTE"); + + /* Set the interface to the new addresses */ + mask = get_mask(go->ouraddr); + if (!sifaddr(pcb, go->ouraddr, ho->hisaddr, mask)) { +#if PPP_DEBUG + ppp_warn("Interface configuration failed"); +#endif /* PPP_DEBUG */ + ipcp_close(f->unit, "Interface configuration failed"); + return; + } + + /* assign a default route through the interface if required */ + if (ipcp_wantoptions[f->unit].default_route) + if (sifdefaultroute(pcb, go->ouraddr, ho->hisaddr, + wo->replace_default_route)) + default_route_set[f->unit] = 1; + + /* Make a proxy ARP entry if requested. */ + if (ho->hisaddr != 0 && ipcp_wantoptions[f->unit].proxy_arp) + if (sifproxyarp(pcb, ho->hisaddr)) + proxy_arp_set[f->unit] = 1; + + } + demand_rexmit(PPP_IP,go->ouraddr); + sifnpmode(pcb, PPP_IP, NPMODE_PASS); + + } else +#endif /* DEMAND_SUPPORT */ + { + /* + * Set IP addresses and (if specified) netmask. + */ + mask = get_mask(go->ouraddr); + +#if !(defined(SVR4) && (defined(SNI) || defined(__USLC__))) + if (!sifaddr(pcb, go->ouraddr, ho->hisaddr, mask)) { +#if PPP_DEBUG + ppp_warn("Interface configuration failed"); +#endif /* PPP_DEBUG */ + ipcp_close(f->pcb, "Interface configuration failed"); + return; + } +#endif + + /* bring the interface up for IP */ + if (!sifup(pcb)) { +#if PPP_DEBUG + ppp_warn("Interface failed to come up"); +#endif /* PPP_DEBUG */ + ipcp_close(f->pcb, "Interface configuration failed"); + return; + } + +#if (defined(SVR4) && (defined(SNI) || defined(__USLC__))) + if (!sifaddr(pcb, go->ouraddr, ho->hisaddr, mask)) { +#if PPP_DEBUG + ppp_warn("Interface configuration failed"); +#endif /* PPP_DEBUG */ + ipcp_close(f->unit, "Interface configuration failed"); + return; + } +#endif + sifnpmode(pcb, PPP_IP, NPMODE_PASS); + +#if 0 /* UNUSED */ + /* assign a default route through the interface if required */ + if (wo->default_route) + if (sifdefaultroute(pcb, go->ouraddr, ho->hisaddr, + wo->replace_default_route)) + pcb->default_route_set = 1; +#endif /* UNUSED */ + + /* Make a proxy ARP entry if requested. */ + if (ho->hisaddr != 0 && wo->proxy_arp) + if (sifproxyarp(pcb, ho->hisaddr)) + pcb->proxy_arp_set = 1; + + wo->ouraddr = go->ouraddr; + + ppp_notice("local IP address %I", go->ouraddr); + if (ho->hisaddr != 0) + ppp_notice("remote IP address %I", ho->hisaddr); + if (go->dnsaddr[0]) + ppp_notice("primary DNS address %I", go->dnsaddr[0]); + if (go->dnsaddr[1]) + ppp_notice("secondary DNS address %I", go->dnsaddr[1]); + } + +#if PPP_STATS_SUPPORT + reset_link_stats(f->unit); +#endif /* PPP_STATS_SUPPORT */ + + np_up(pcb, PPP_IP); + pcb->ipcp_is_up = 1; + +#if PPP_NOTIFY + notify(ip_up_notifier, 0); +#endif /* PPP_NOTIFY */ +#if 0 /* UNUSED */ + if (ip_up_hook) + ip_up_hook(); +#endif /* UNUSED */ +} + + +/* + * ipcp_down - IPCP has gone DOWN. + * + * Take the IP network interface down, clear its addresses + * and delete routes through it. + */ +static void ipcp_down(fsm *f) { + ppp_pcb *pcb = f->pcb; + ipcp_options *ho = &pcb->ipcp_hisoptions; + ipcp_options *go = &pcb->ipcp_gotoptions; + + IPCPDEBUG(("ipcp: down")); +#if PPP_STATS_SUPPORT + /* XXX a bit IPv4-centric here, we only need to get the stats + * before the interface is marked down. */ + /* XXX more correct: we must get the stats before running the notifiers, + * at least for the radius plugin */ + update_link_stats(f->unit); +#endif /* PPP_STATS_SUPPORT */ +#if PPP_NOTIFY + notify(ip_down_notifier, 0); +#endif /* PPP_NOTIFY */ +#if 0 /* UNUSED */ + if (ip_down_hook) + ip_down_hook(); +#endif /* UNUSED */ + if (pcb->ipcp_is_up) { + pcb->ipcp_is_up = 0; + np_down(pcb, PPP_IP); + } + sifvjcomp(pcb, 0, 0, 0); + +#if PPP_STATS_SUPPORT + print_link_stats(); /* _after_ running the notifiers and ip_down_hook(), + * because print_link_stats() sets link_stats_valid + * to 0 (zero) */ +#endif /* PPP_STATS_SUPPORT */ + +#if DEMAND_SUPPORT + /* + * If we are doing dial-on-demand, set the interface + * to queue up outgoing packets (for now). + */ + if (demand) { + sifnpmode(pcb, PPP_IP, NPMODE_QUEUE); + } else +#endif /* DEMAND_SUPPORT */ + { + sifnpmode(pcb, PPP_IP, NPMODE_DROP); + sifdown(pcb); + ipcp_clear_addrs(pcb, go->ouraddr, + ho->hisaddr, 0); + cdns(pcb, go->dnsaddr[0], go->dnsaddr[1]); + } +} + + +/* + * ipcp_clear_addrs() - clear the interface addresses, routes, + * proxy arp entries, etc. + */ +static void ipcp_clear_addrs(ppp_pcb *pcb, u32_t ouraddr, u32_t hisaddr, u8_t replacedefaultroute) { + LWIP_UNUSED_ARG(replacedefaultroute); + + if (pcb->proxy_arp_set) { + cifproxyarp(pcb, hisaddr); + pcb->proxy_arp_set = 0; + } +#if 0 /* UNUSED */ + /* If replacedefaultroute, sifdefaultroute will be called soon + * with replacedefaultroute set and that will overwrite the current + * default route. This is the case only when doing demand, otherwise + * during demand, this cifdefaultroute would restore the old default + * route which is not what we want in this case. In the non-demand + * case, we'll delete the default route and restore the old if there + * is one saved by an sifdefaultroute with replacedefaultroute. + */ + if (!replacedefaultroute && pcb->default_route_set) { + cifdefaultroute(pcb, ouraddr, hisaddr); + pcb->default_route_set = 0; + } +#endif /* UNUSED */ + cifaddr(pcb, ouraddr, hisaddr); +} + + +/* + * ipcp_finished - possibly shut down the lower layers. + */ +static void ipcp_finished(fsm *f) { + ppp_pcb *pcb = f->pcb; + if (pcb->ipcp_is_open) { + pcb->ipcp_is_open = 0; + np_finished(pcb, PPP_IP); + } +} + + +#if 0 /* UNUSED */ +/* + * create_resolv - create the replacement resolv.conf file + */ +static void +create_resolv(peerdns1, peerdns2) + u32_t peerdns1, peerdns2; +{ + +} +#endif /* UNUSED */ + +#if PRINTPKT_SUPPORT +/* + * ipcp_printpkt - print the contents of an IPCP packet. + */ +static const char *ipcp_codenames[] = { + "ConfReq", "ConfAck", "ConfNak", "ConfRej", + "TermReq", "TermAck", "CodeRej" +}; + +static int ipcp_printpkt(u_char *p, int plen, + void (*printer) (void *, const char *, ...), void *arg) { + int code, id, len, olen; + u_char *pstart, *optend; + u_short cishort; + u32_t cilong; + + if (plen < HEADERLEN) + return 0; + pstart = p; + GETCHAR(code, p); + GETCHAR(id, p); + GETSHORT(len, p); + if (len < HEADERLEN || len > plen) + return 0; + + if (code >= 1 && code <= (int)sizeof(ipcp_codenames) / (int)sizeof(char *)) + printer(arg, " %s", ipcp_codenames[code-1]); + else + printer(arg, " code=0x%x", code); + printer(arg, " id=0x%x", id); + len -= HEADERLEN; + switch (code) { + case CONFREQ: + case CONFACK: + case CONFNAK: + case CONFREJ: + /* print option list */ + while (len >= 2) { + GETCHAR(code, p); + GETCHAR(olen, p); + p -= 2; + if (olen < 2 || olen > len) { + break; + } + printer(arg, " <"); + len -= olen; + optend = p + olen; + switch (code) { + case CI_ADDRS: + if (olen == CILEN_ADDRS) { + p += 2; + GETLONG(cilong, p); + printer(arg, "addrs %I", htonl(cilong)); + GETLONG(cilong, p); + printer(arg, " %I", htonl(cilong)); + } + break; + case CI_COMPRESSTYPE: + if (olen >= CILEN_COMPRESS) { + p += 2; + GETSHORT(cishort, p); + printer(arg, "compress "); + switch (cishort) { + case IPCP_VJ_COMP: + printer(arg, "VJ"); + break; + case IPCP_VJ_COMP_OLD: + printer(arg, "old-VJ"); + break; + default: + printer(arg, "0x%x", cishort); + } + } + break; + case CI_ADDR: + if (olen == CILEN_ADDR) { + p += 2; + GETLONG(cilong, p); + printer(arg, "addr %I", htonl(cilong)); + } + break; + case CI_MS_DNS1: + case CI_MS_DNS2: + p += 2; + GETLONG(cilong, p); + printer(arg, "ms-dns%d %I", (code == CI_MS_DNS1? 1: 2), + htonl(cilong)); + break; + case CI_MS_WINS1: + case CI_MS_WINS2: + p += 2; + GETLONG(cilong, p); + printer(arg, "ms-wins %I", htonl(cilong)); + break; + default: + break; + } + while (p < optend) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + printer(arg, ">"); + } + break; + + case TERMACK: + case TERMREQ: + if (len > 0 && *p >= ' ' && *p < 0x7f) { + printer(arg, " "); + ppp_print_string((char *)p, len, printer, arg); + p += len; + len = 0; + } + break; + default: + break; + } + + /* print the rest of the bytes in the packet */ + for (; len > 0; --len) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + + return p - pstart; +} +#endif /* PRINTPKT_SUPPORT */ + +#if DEMAND_SUPPORT +/* + * ip_active_pkt - see if this IP packet is worth bringing the link up for. + * We don't bring the link up for IP fragments or for TCP FIN packets + * with no data. + */ +#define IP_HDRLEN 20 /* bytes */ +#define IP_OFFMASK 0x1fff +#ifndef IPPROTO_TCP +#define IPPROTO_TCP 6 +#endif +#define TCP_HDRLEN 20 +#define TH_FIN 0x01 + +/* + * We use these macros because the IP header may be at an odd address, + * and some compilers might use word loads to get th_off or ip_hl. + */ + +#define net_short(x) (((x)[0] << 8) + (x)[1]) +#define get_iphl(x) (((unsigned char *)(x))[0] & 0xF) +#define get_ipoff(x) net_short((unsigned char *)(x) + 6) +#define get_ipproto(x) (((unsigned char *)(x))[9]) +#define get_tcpoff(x) (((unsigned char *)(x))[12] >> 4) +#define get_tcpflags(x) (((unsigned char *)(x))[13]) + +static int +ip_active_pkt(pkt, len) + u_char *pkt; + int len; +{ + u_char *tcp; + int hlen; + + len -= PPP_HDRLEN; + pkt += PPP_HDRLEN; + if (len < IP_HDRLEN) + return 0; + if ((get_ipoff(pkt) & IP_OFFMASK) != 0) + return 0; + if (get_ipproto(pkt) != IPPROTO_TCP) + return 1; + hlen = get_iphl(pkt) * 4; + if (len < hlen + TCP_HDRLEN) + return 0; + tcp = pkt + hlen; + if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == hlen + get_tcpoff(tcp) * 4) + return 0; + return 1; +} +#endif /* DEMAND_SUPPORT */ + +#endif /* PPP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/ipv6cp.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/ipv6cp.c new file mode 100644 index 0000000..5ff6183 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/ipv6cp.c @@ -0,0 +1,1498 @@ +/* + * ipv6cp.c - PPP IPV6 Control Protocol. + * + * Copyright (c) 1999 Tommi Komulainen. 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. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Tommi Komulainen + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +/* Original version, based on RFC2023 : + + Copyright (c) 1995, 1996, 1997 Francis.Dupont@inria.fr, INRIA Rocquencourt, + Alain.Durand@imag.fr, IMAG, + Jean-Luc.Richier@imag.fr, IMAG-LSR. + + Copyright (c) 1998, 1999 Francis.Dupont@inria.fr, GIE DYADE, + Alain.Durand@imag.fr, IMAG, + Jean-Luc.Richier@imag.fr, IMAG-LSR. + + Ce travail a �t� fait au sein du GIE DYADE (Groupement d'Int�r�t + �conomique ayant pour membres BULL S.A. et l'INRIA). + + Ce logiciel informatique est disponible aux conditions + usuelles dans la recherche, c'est-�-dire qu'il peut + �tre utilis�, copi�, modifi�, distribu� � l'unique + condition que ce texte soit conserv� afin que + l'origine de ce logiciel soit reconnue. + + Le nom de l'Institut National de Recherche en Informatique + et en Automatique (INRIA), de l'IMAG, ou d'une personne morale + ou physique ayant particip� � l'�laboration de ce logiciel ne peut + �tre utilis� sans son accord pr�alable explicite. + + Ce logiciel est fourni tel quel sans aucune garantie, + support ou responsabilit� d'aucune sorte. + Ce logiciel est d�riv� de sources d'origine + "University of California at Berkeley" et + "Digital Equipment Corporation" couvertes par des copyrights. + + L'Institut d'Informatique et de Math�matiques Appliqu�es de Grenoble (IMAG) + est une f�d�ration d'unit�s mixtes de recherche du CNRS, de l'Institut National + Polytechnique de Grenoble et de l'Universit� Joseph Fourier regroupant + sept laboratoires dont le laboratoire Logiciels, Syst�mes, R�seaux (LSR). + + This work has been done in the context of GIE DYADE (joint R & D venture + between BULL S.A. and INRIA). + + This software is available with usual "research" terms + with the aim of retain credits of the software. + Permission to use, copy, modify and distribute this software for any + purpose and without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies, + and the name of INRIA, IMAG, or any contributor not be used in advertising + or publicity pertaining to this material without the prior explicit + permission. The software is provided "as is" without any + warranties, support or liabilities of any kind. + This software is derived from source code from + "University of California at Berkeley" and + "Digital Equipment Corporation" protected by copyrights. + + Grenoble's Institute of Computer Science and Applied Mathematics (IMAG) + is a federation of seven research units funded by the CNRS, National + Polytechnic Institute of Grenoble and University Joseph Fourier. + The research unit in Software, Systems, Networks (LSR) is member of IMAG. +*/ + +/* + * Derived from : + * + * + * ipcp.c - PPP IP Control Protocol. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. 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. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $Id: ipv6cp.c,v 1.21 2005/08/25 23:59:34 paulus Exp $ + */ + +/* + * TODO: + * + * Proxy Neighbour Discovery. + * + * Better defines for selecting the ordering of + * interface up / set address. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && PPP_IPV6_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#if 0 /* UNUSED */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif /* UNUSED */ + +#include "netif/ppp/ppp_impl.h" +#include "netif/ppp/fsm.h" +#include "netif/ppp/ipcp.h" +#include "netif/ppp/ipv6cp.h" +#include "netif/ppp/magic.h" + +/* global vars */ +#if 0 /* UNUSED */ +int no_ifaceid_neg = 0; +#endif /* UNUSED */ + +/* + * Callbacks for fsm code. (CI = Configuration Information) + */ +static void ipv6cp_resetci(fsm *f); /* Reset our CI */ +static int ipv6cp_cilen(fsm *f); /* Return length of our CI */ +static void ipv6cp_addci(fsm *f, u_char *ucp, int *lenp); /* Add our CI */ +static int ipv6cp_ackci(fsm *f, u_char *p, int len); /* Peer ack'd our CI */ +static int ipv6cp_nakci(fsm *f, u_char *p, int len, int treat_as_reject); /* Peer nak'd our CI */ +static int ipv6cp_rejci(fsm *f, u_char *p, int len); /* Peer rej'd our CI */ +static int ipv6cp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree); /* Rcv CI */ +static void ipv6cp_up(fsm *f); /* We're UP */ +static void ipv6cp_down(fsm *f); /* We're DOWN */ +static void ipv6cp_finished(fsm *f); /* Don't need lower layer */ + +static const fsm_callbacks ipv6cp_callbacks = { /* IPV6CP callback routines */ + ipv6cp_resetci, /* Reset our Configuration Information */ + ipv6cp_cilen, /* Length of our Configuration Information */ + ipv6cp_addci, /* Add our Configuration Information */ + ipv6cp_ackci, /* ACK our Configuration Information */ + ipv6cp_nakci, /* NAK our Configuration Information */ + ipv6cp_rejci, /* Reject our Configuration Information */ + ipv6cp_reqci, /* Request peer's Configuration Information */ + ipv6cp_up, /* Called when fsm reaches OPENED state */ + ipv6cp_down, /* Called when fsm leaves OPENED state */ + NULL, /* Called when we want the lower layer up */ + ipv6cp_finished, /* Called when we want the lower layer down */ + NULL, /* Called when Protocol-Reject received */ + NULL, /* Retransmission is necessary */ + NULL, /* Called to handle protocol-specific codes */ + "IPV6CP" /* String name of protocol */ +}; + +#if PPP_OPTIONS +/* + * Command-line options. + */ +static int setifaceid(char **arg)); +static void printifaceid(option_t *, + void (*)(void *, char *, ...), void *)); + +static option_t ipv6cp_option_list[] = { + { "ipv6", o_special, (void *)setifaceid, + "Set interface identifiers for IPV6", + OPT_A2PRINTER, (void *)printifaceid }, + + { "+ipv6", o_bool, &ipv6cp_protent.enabled_flag, + "Enable IPv6 and IPv6CP", OPT_PRIO | 1 }, + { "noipv6", o_bool, &ipv6cp_protent.enabled_flag, + "Disable IPv6 and IPv6CP", OPT_PRIOSUB }, + { "-ipv6", o_bool, &ipv6cp_protent.enabled_flag, + "Disable IPv6 and IPv6CP", OPT_PRIOSUB | OPT_ALIAS }, + + { "ipv6cp-accept-local", o_bool, &ipv6cp_allowoptions[0].accept_local, + "Accept peer's interface identifier for us", 1 }, + + { "ipv6cp-use-ipaddr", o_bool, &ipv6cp_allowoptions[0].use_ip, + "Use (default) IPv4 address as interface identifier", 1 }, + + { "ipv6cp-use-persistent", o_bool, &ipv6cp_wantoptions[0].use_persistent, + "Use uniquely-available persistent value for link local address", 1 }, + + { "ipv6cp-restart", o_int, &ipv6cp_fsm[0].timeouttime, + "Set timeout for IPv6CP", OPT_PRIO }, + { "ipv6cp-max-terminate", o_int, &ipv6cp_fsm[0].maxtermtransmits, + "Set max #xmits for term-reqs", OPT_PRIO }, + { "ipv6cp-max-configure", o_int, &ipv6cp_fsm[0].maxconfreqtransmits, + "Set max #xmits for conf-reqs", OPT_PRIO }, + { "ipv6cp-max-failure", o_int, &ipv6cp_fsm[0].maxnakloops, + "Set max #conf-naks for IPv6CP", OPT_PRIO }, + + { NULL } +}; +#endif /* PPP_OPTIONS */ + +/* + * Protocol entry points from main code. + */ +static void ipv6cp_init(ppp_pcb *pcb); +static void ipv6cp_open(ppp_pcb *pcb); +static void ipv6cp_close(ppp_pcb *pcb, const char *reason); +static void ipv6cp_lowerup(ppp_pcb *pcb); +static void ipv6cp_lowerdown(ppp_pcb *pcb); +static void ipv6cp_input(ppp_pcb *pcb, u_char *p, int len); +static void ipv6cp_protrej(ppp_pcb *pcb); +#if PPP_OPTIONS +static void ipv6_check_options(void); +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT +static int ipv6_demand_conf(int u); +#endif /* DEMAND_SUPPORT */ +#if PRINTPKT_SUPPORT +static int ipv6cp_printpkt(u_char *p, int plen, + void (*printer)(void *, const char *, ...), void *arg); +#endif /* PRINTPKT_SUPPORT */ +#if DEMAND_SUPPORT +static int ipv6_active_pkt(u_char *pkt, int len); +#endif /* DEMAND_SUPPORT */ + +const struct protent ipv6cp_protent = { + PPP_IPV6CP, + ipv6cp_init, + ipv6cp_input, + ipv6cp_protrej, + ipv6cp_lowerup, + ipv6cp_lowerdown, + ipv6cp_open, + ipv6cp_close, +#if PRINTPKT_SUPPORT + ipv6cp_printpkt, +#endif /* PRINTPKT_SUPPORT */ + NULL, + 1, +#if PRINTPKT_SUPPORT + "IPV6CP", + "IPV6", +#endif /* PRINTPKT_SUPPORT */ +#if PPP_OPTIONS + ipv6cp_option_list, + ipv6_check_options, +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT + ipv6_demand_conf, + ipv6_active_pkt +#endif /* DEMAND_SUPPORT */ +}; + +static void ipv6cp_clear_addrs(ppp_pcb *pcb, eui64_t ourid, eui64_t hisid); +#if 0 /* UNUSED */ +static void ipv6cp_script(char *)); +static void ipv6cp_script_done(void *)); +#endif /* UNUSED */ + +/* + * Lengths of configuration options. + */ +#define CILEN_VOID 2 +#define CILEN_COMPRESS 4 /* length for RFC2023 compress opt. */ +#define CILEN_IFACEID 10 /* RFC2472, interface identifier */ + +#define CODENAME(x) ((x) == CONFACK ? "ACK" : \ + (x) == CONFNAK ? "NAK" : "REJ") + +#if 0 /* UNUSED */ +/* + * This state variable is used to ensure that we don't + * run an ipcp-up/down script while one is already running. + */ +static enum script_state { + s_down, + s_up, +} ipv6cp_script_state; +static pid_t ipv6cp_script_pid; +#endif /* UNUSED */ + +static char *llv6_ntoa(eui64_t ifaceid); + +#if PPP_OPTIONS +/* + * setifaceid - set the interface identifiers manually + */ +static int +setifaceid(argv) + char **argv; +{ + char *comma, *arg, c; + ipv6cp_options *wo = &ipv6cp_wantoptions[0]; + struct in6_addr addr; + static int prio_local, prio_remote; + +#define VALIDID(a) ( (((a).s6_addr32[0] == 0) && ((a).s6_addr32[1] == 0)) && \ + (((a).s6_addr32[2] != 0) || ((a).s6_addr32[3] != 0)) ) + + arg = *argv; + if ((comma = strchr(arg, ',')) == NULL) + comma = arg + strlen(arg); + + /* + * If comma first character, then no local identifier + */ + if (comma != arg) { + c = *comma; + *comma = '\0'; + + if (inet_pton(AF_INET6, arg, &addr) == 0 || !VALIDID(addr)) { + option_error("Illegal interface identifier (local): %s", arg); + return 0; + } + + if (option_priority >= prio_local) { + eui64_copy(addr.s6_addr32[2], wo->ourid); + wo->opt_local = 1; + prio_local = option_priority; + } + *comma = c; + } + + /* + * If comma last character, the no remote identifier + */ + if (*comma != 0 && *++comma != '\0') { + if (inet_pton(AF_INET6, comma, &addr) == 0 || !VALIDID(addr)) { + option_error("Illegal interface identifier (remote): %s", comma); + return 0; + } + if (option_priority >= prio_remote) { + eui64_copy(addr.s6_addr32[2], wo->hisid); + wo->opt_remote = 1; + prio_remote = option_priority; + } + } + + if (override_value("+ipv6", option_priority, option_source)) + ipv6cp_protent.enabled_flag = 1; + return 1; +} + +static void +printifaceid(opt, printer, arg) + option_t *opt; + void (*printer)(void *, char *, ...)); + void *arg; +{ + ipv6cp_options *wo = &ipv6cp_wantoptions[0]; + + if (wo->opt_local) + printer(arg, "%s", llv6_ntoa(wo->ourid)); + printer(arg, ","); + if (wo->opt_remote) + printer(arg, "%s", llv6_ntoa(wo->hisid)); +} +#endif /* PPP_OPTIONS */ + +/* + * Make a string representation of a network address. + */ +static char * +llv6_ntoa(eui64_t ifaceid) +{ + static char b[64]; + + sprintf(b, "fe80::%s", eui64_ntoa(ifaceid)); + return b; +} + + +/* + * ipv6cp_init - Initialize IPV6CP. + */ +static void ipv6cp_init(ppp_pcb *pcb) { + fsm *f = &pcb->ipv6cp_fsm; + ipv6cp_options *wo = &pcb->ipv6cp_wantoptions; + ipv6cp_options *ao = &pcb->ipv6cp_allowoptions; + + f->pcb = pcb; + f->protocol = PPP_IPV6CP; + f->callbacks = &ipv6cp_callbacks; + fsm_init(f); + + memset(wo, 0, sizeof(*wo)); + memset(ao, 0, sizeof(*ao)); + + wo->accept_local = 1; + wo->neg_ifaceid = 1; + ao->neg_ifaceid = 1; + +#ifdef IPV6CP_COMP + wo->neg_vj = 1; + ao->neg_vj = 1; + wo->vj_protocol = IPV6CP_COMP; +#endif + +} + + +/* + * ipv6cp_open - IPV6CP is allowed to come up. + */ +static void ipv6cp_open(ppp_pcb *pcb) { + fsm_open(&pcb->ipv6cp_fsm); +} + + +/* + * ipv6cp_close - Take IPV6CP down. + */ +static void ipv6cp_close(ppp_pcb *pcb, const char *reason) { + fsm_close(&pcb->ipv6cp_fsm, reason); +} + + +/* + * ipv6cp_lowerup - The lower layer is up. + */ +static void ipv6cp_lowerup(ppp_pcb *pcb) { + fsm_lowerup(&pcb->ipv6cp_fsm); +} + + +/* + * ipv6cp_lowerdown - The lower layer is down. + */ +static void ipv6cp_lowerdown(ppp_pcb *pcb) { + fsm_lowerdown(&pcb->ipv6cp_fsm); +} + + +/* + * ipv6cp_input - Input IPV6CP packet. + */ +static void ipv6cp_input(ppp_pcb *pcb, u_char *p, int len) { + fsm_input(&pcb->ipv6cp_fsm, p, len); +} + + +/* + * ipv6cp_protrej - A Protocol-Reject was received for IPV6CP. + * + * Pretend the lower layer went down, so we shut up. + */ +static void ipv6cp_protrej(ppp_pcb *pcb) { + fsm_lowerdown(&pcb->ipv6cp_fsm); +} + + +/* + * ipv6cp_resetci - Reset our CI. + */ +static void ipv6cp_resetci(fsm *f) { + ppp_pcb *pcb = f->pcb; + ipv6cp_options *wo = &pcb->ipv6cp_wantoptions; + ipv6cp_options *go = &pcb->ipv6cp_gotoptions; + ipv6cp_options *ao = &pcb->ipv6cp_allowoptions; + + wo->req_ifaceid = wo->neg_ifaceid && ao->neg_ifaceid; + + if (!wo->opt_local) { + eui64_magic_nz(wo->ourid); + } + + *go = *wo; + eui64_zero(go->hisid); /* last proposed interface identifier */ +} + + +/* + * ipv6cp_cilen - Return length of our CI. + */ +static int ipv6cp_cilen(fsm *f) { + ppp_pcb *pcb = f->pcb; + ipv6cp_options *go = &pcb->ipv6cp_gotoptions; + +#define LENCIVJ(neg) (neg ? CILEN_COMPRESS : 0) +#define LENCIIFACEID(neg) (neg ? CILEN_IFACEID : 0) + + return (LENCIIFACEID(go->neg_ifaceid) + + LENCIVJ(go->neg_vj)); +} + + +/* + * ipv6cp_addci - Add our desired CIs to a packet. + */ +static void ipv6cp_addci(fsm *f, u_char *ucp, int *lenp) { + ppp_pcb *pcb = f->pcb; + ipv6cp_options *go = &pcb->ipv6cp_gotoptions; + int len = *lenp; + +#define ADDCIVJ(opt, neg, val) \ + if (neg) { \ + int vjlen = CILEN_COMPRESS; \ + if (len >= vjlen) { \ + PUTCHAR(opt, ucp); \ + PUTCHAR(vjlen, ucp); \ + PUTSHORT(val, ucp); \ + len -= vjlen; \ + } else \ + neg = 0; \ + } + +#define ADDCIIFACEID(opt, neg, val1) \ + if (neg) { \ + int idlen = CILEN_IFACEID; \ + if (len >= idlen) { \ + PUTCHAR(opt, ucp); \ + PUTCHAR(idlen, ucp); \ + eui64_put(val1, ucp); \ + len -= idlen; \ + } else \ + neg = 0; \ + } + + ADDCIIFACEID(CI_IFACEID, go->neg_ifaceid, go->ourid); + + ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol); + + *lenp -= len; +} + + +/* + * ipv6cp_ackci - Ack our CIs. + * + * Returns: + * 0 - Ack was bad. + * 1 - Ack was good. + */ +static int ipv6cp_ackci(fsm *f, u_char *p, int len) { + ppp_pcb *pcb = f->pcb; + ipv6cp_options *go = &pcb->ipv6cp_gotoptions; + u_short cilen, citype, cishort; + eui64_t ifaceid; + + /* + * CIs must be in exactly the same order that we sent... + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ + +#define ACKCIVJ(opt, neg, val) \ + if (neg) { \ + int vjlen = CILEN_COMPRESS; \ + if ((len -= vjlen) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != vjlen || \ + citype != opt) \ + goto bad; \ + GETSHORT(cishort, p); \ + if (cishort != val) \ + goto bad; \ + } + +#define ACKCIIFACEID(opt, neg, val1) \ + if (neg) { \ + int idlen = CILEN_IFACEID; \ + if ((len -= idlen) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != idlen || \ + citype != opt) \ + goto bad; \ + eui64_get(ifaceid, p); \ + if (! eui64_equals(val1, ifaceid)) \ + goto bad; \ + } + + ACKCIIFACEID(CI_IFACEID, go->neg_ifaceid, go->ourid); + + ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol); + + /* + * If there are any remaining CIs, then this packet is bad. + */ + if (len != 0) + goto bad; + return (1); + +bad: + IPV6CPDEBUG(("ipv6cp_ackci: received bad Ack!")); + return (0); +} + +/* + * ipv6cp_nakci - Peer has sent a NAK for some of our CIs. + * This should not modify any state if the Nak is bad + * or if IPV6CP is in the OPENED state. + * + * Returns: + * 0 - Nak was bad. + * 1 - Nak was good. + */ +static int ipv6cp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) { + ppp_pcb *pcb = f->pcb; + ipv6cp_options *go = &pcb->ipv6cp_gotoptions; + u_char citype, cilen, *next; + u_short cishort; + eui64_t ifaceid; + ipv6cp_options no; /* options we've seen Naks for */ + ipv6cp_options try_; /* options to request next time */ + + BZERO(&no, sizeof(no)); + try_ = *go; + + /* + * Any Nak'd CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define NAKCIIFACEID(opt, neg, code) \ + if (go->neg && \ + len >= (cilen = CILEN_IFACEID) && \ + p[1] == cilen && \ + p[0] == opt) { \ + len -= cilen; \ + INCPTR(2, p); \ + eui64_get(ifaceid, p); \ + no.neg = 1; \ + code \ + } + +#define NAKCIVJ(opt, neg, code) \ + if (go->neg && \ + ((cilen = p[1]) == CILEN_COMPRESS) && \ + len >= cilen && \ + p[0] == opt) { \ + len -= cilen; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + no.neg = 1; \ + code \ + } + + /* + * Accept the peer's idea of {our,his} interface identifier, if different + * from our idea, only if the accept_{local,remote} flag is set. + */ + NAKCIIFACEID(CI_IFACEID, neg_ifaceid, + if (treat_as_reject) { + try_.neg_ifaceid = 0; + } else if (go->accept_local) { + while (eui64_iszero(ifaceid) || + eui64_equals(ifaceid, go->hisid)) /* bad luck */ + eui64_magic(ifaceid); + try_.ourid = ifaceid; + IPV6CPDEBUG(("local LL address %s", llv6_ntoa(ifaceid))); + } + ); + +#ifdef IPV6CP_COMP + NAKCIVJ(CI_COMPRESSTYPE, neg_vj, + { + if (cishort == IPV6CP_COMP && !treat_as_reject) { + try_.vj_protocol = cishort; + } else { + try_.neg_vj = 0; + } + } + ); +#else + NAKCIVJ(CI_COMPRESSTYPE, neg_vj, + { + try_.neg_vj = 0; + } + ); +#endif + + /* + * There may be remaining CIs, if the peer is requesting negotiation + * on an option that we didn't include in our request packet. + * If they want to negotiate about interface identifier, we comply. + * If they want us to ask for compression, we refuse. + */ + while (len >= CILEN_VOID) { + GETCHAR(citype, p); + GETCHAR(cilen, p); + if ( cilen < CILEN_VOID || (len -= cilen) < 0 ) + goto bad; + next = p + cilen - 2; + + switch (citype) { + case CI_COMPRESSTYPE: + if (go->neg_vj || no.neg_vj || + (cilen != CILEN_COMPRESS)) + goto bad; + no.neg_vj = 1; + break; + case CI_IFACEID: + if (go->neg_ifaceid || no.neg_ifaceid || cilen != CILEN_IFACEID) + goto bad; + try_.neg_ifaceid = 1; + eui64_get(ifaceid, p); + if (go->accept_local) { + while (eui64_iszero(ifaceid) || + eui64_equals(ifaceid, go->hisid)) /* bad luck */ + eui64_magic(ifaceid); + try_.ourid = ifaceid; + } + no.neg_ifaceid = 1; + break; + default: + break; + } + p = next; + } + + /* If there is still anything left, this packet is bad. */ + if (len != 0) + goto bad; + + /* + * OK, the Nak is good. Now we can update state. + */ + if (f->state != PPP_FSM_OPENED) + *go = try_; + + return 1; + +bad: + IPV6CPDEBUG(("ipv6cp_nakci: received bad Nak!")); + return 0; +} + + +/* + * ipv6cp_rejci - Reject some of our CIs. + */ +static int ipv6cp_rejci(fsm *f, u_char *p, int len) { + ppp_pcb *pcb = f->pcb; + ipv6cp_options *go = &pcb->ipv6cp_gotoptions; + u_char cilen; + u_short cishort; + eui64_t ifaceid; + ipv6cp_options try_; /* options to request next time */ + + try_ = *go; + /* + * Any Rejected CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define REJCIIFACEID(opt, neg, val1) \ + if (go->neg && \ + len >= (cilen = CILEN_IFACEID) && \ + p[1] == cilen && \ + p[0] == opt) { \ + len -= cilen; \ + INCPTR(2, p); \ + eui64_get(ifaceid, p); \ + /* Check rejected value. */ \ + if (! eui64_equals(ifaceid, val1)) \ + goto bad; \ + try_.neg = 0; \ + } + +#define REJCIVJ(opt, neg, val) \ + if (go->neg && \ + p[1] == CILEN_COMPRESS && \ + len >= p[1] && \ + p[0] == opt) { \ + len -= p[1]; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + /* Check rejected value. */ \ + if (cishort != val) \ + goto bad; \ + try_.neg = 0; \ + } + + REJCIIFACEID(CI_IFACEID, neg_ifaceid, go->ourid); + + REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol); + + /* + * If there are any remaining CIs, then this packet is bad. + */ + if (len != 0) + goto bad; + /* + * Now we can update state. + */ + if (f->state != PPP_FSM_OPENED) + *go = try_; + return 1; + +bad: + IPV6CPDEBUG(("ipv6cp_rejci: received bad Reject!")); + return 0; +} + + +/* + * ipv6cp_reqci - Check the peer's requested CIs and send appropriate response. + * + * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified + * appropriately. If reject_if_disagree is non-zero, doesn't return + * CONFNAK; returns CONFREJ if it can't return CONFACK. + * + * inp = Requested CIs + * len = Length of requested CIs + * + */ +static int ipv6cp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree) { + ppp_pcb *pcb = f->pcb; + ipv6cp_options *wo = &pcb->ipv6cp_wantoptions; + ipv6cp_options *ho = &pcb->ipv6cp_hisoptions; + ipv6cp_options *ao = &pcb->ipv6cp_allowoptions; + ipv6cp_options *go = &pcb->ipv6cp_gotoptions; + u_char *cip, *next; /* Pointer to current and next CIs */ + u_short cilen, citype; /* Parsed len, type */ + u_short cishort; /* Parsed short value */ + eui64_t ifaceid; /* Parsed interface identifier */ + int rc = CONFACK; /* Final packet return code */ + int orc; /* Individual option return code */ + u_char *p; /* Pointer to next char to parse */ + u_char *ucp = inp; /* Pointer to current output char */ + int l = *len; /* Length left */ + + /* + * Reset all his options. + */ + BZERO(ho, sizeof(*ho)); + + /* + * Process all his options. + */ + next = inp; + while (l) { + orc = CONFACK; /* Assume success */ + cip = p = next; /* Remember begining of CI */ + if (l < 2 || /* Not enough data for CI header or */ + p[1] < 2 || /* CI length too small or */ + p[1] > l) { /* CI length too big? */ + IPV6CPDEBUG(("ipv6cp_reqci: bad CI length!")); + orc = CONFREJ; /* Reject bad CI */ + cilen = l; /* Reject till end of packet */ + l = 0; /* Don't loop again */ + goto endswitch; + } + GETCHAR(citype, p); /* Parse CI type */ + GETCHAR(cilen, p); /* Parse CI length */ + l -= cilen; /* Adjust remaining length */ + next += cilen; /* Step to next CI */ + + switch (citype) { /* Check CI type */ + case CI_IFACEID: + IPV6CPDEBUG(("ipv6cp: received interface identifier ")); + + if (!ao->neg_ifaceid || + cilen != CILEN_IFACEID) { /* Check CI length */ + orc = CONFREJ; /* Reject CI */ + break; + } + + /* + * If he has no interface identifier, or if we both have same + * identifier then NAK it with new idea. + * In particular, if we don't know his identifier, but he does, + * then accept it. + */ + eui64_get(ifaceid, p); + IPV6CPDEBUG(("(%s)", llv6_ntoa(ifaceid))); + if (eui64_iszero(ifaceid) && eui64_iszero(go->ourid)) { + orc = CONFREJ; /* Reject CI */ + break; + } + if (!eui64_iszero(wo->hisid) && + !eui64_equals(ifaceid, wo->hisid) && + eui64_iszero(go->hisid)) { + + orc = CONFNAK; + ifaceid = wo->hisid; + go->hisid = ifaceid; + DECPTR(sizeof(ifaceid), p); + eui64_put(ifaceid, p); + } else + if (eui64_iszero(ifaceid) || eui64_equals(ifaceid, go->ourid)) { + orc = CONFNAK; + if (eui64_iszero(go->hisid)) /* first time, try option */ + ifaceid = wo->hisid; + while (eui64_iszero(ifaceid) || + eui64_equals(ifaceid, go->ourid)) /* bad luck */ + eui64_magic(ifaceid); + go->hisid = ifaceid; + DECPTR(sizeof(ifaceid), p); + eui64_put(ifaceid, p); + } + + ho->neg_ifaceid = 1; + ho->hisid = ifaceid; + break; + + case CI_COMPRESSTYPE: + IPV6CPDEBUG(("ipv6cp: received COMPRESSTYPE ")); + if (!ao->neg_vj || + (cilen != CILEN_COMPRESS)) { + orc = CONFREJ; + break; + } + GETSHORT(cishort, p); + IPV6CPDEBUG(("(%d)", cishort)); + +#ifdef IPV6CP_COMP + if (!(cishort == IPV6CP_COMP)) { + orc = CONFREJ; + break; + } + + ho->neg_vj = 1; + ho->vj_protocol = cishort; + break; +#else + orc = CONFREJ; + break; +#endif + + default: + orc = CONFREJ; + break; + } + +endswitch: + IPV6CPDEBUG((" (%s)\n", CODENAME(orc))); + + if (orc == CONFACK && /* Good CI */ + rc != CONFACK) /* but prior CI wasnt? */ + continue; /* Don't send this one */ + + if (orc == CONFNAK) { /* Nak this CI? */ + if (reject_if_disagree) /* Getting fed up with sending NAKs? */ + orc = CONFREJ; /* Get tough if so */ + else { + if (rc == CONFREJ) /* Rejecting prior CI? */ + continue; /* Don't send this one */ + if (rc == CONFACK) { /* Ack'd all prior CIs? */ + rc = CONFNAK; /* Not anymore... */ + ucp = inp; /* Backup */ + } + } + } + + if (orc == CONFREJ && /* Reject this CI */ + rc != CONFREJ) { /* but no prior ones? */ + rc = CONFREJ; + ucp = inp; /* Backup */ + } + + /* Need to move CI? */ + if (ucp != cip) + MEMCPY(ucp, cip, cilen); /* Move it */ + + /* Update output pointer */ + INCPTR(cilen, ucp); + } + + /* + * If we aren't rejecting this packet, and we want to negotiate + * their identifier and they didn't send their identifier, then we + * send a NAK with a CI_IFACEID option appended. We assume the + * input buffer is long enough that we can append the extra + * option safely. + */ + if (rc != CONFREJ && !ho->neg_ifaceid && + wo->req_ifaceid && !reject_if_disagree) { + if (rc == CONFACK) { + rc = CONFNAK; + ucp = inp; /* reset pointer */ + wo->req_ifaceid = 0; /* don't ask again */ + } + PUTCHAR(CI_IFACEID, ucp); + PUTCHAR(CILEN_IFACEID, ucp); + eui64_put(wo->hisid, ucp); + } + + *len = ucp - inp; /* Compute output length */ + IPV6CPDEBUG(("ipv6cp: returning Configure-%s", CODENAME(rc))); + return (rc); /* Return final code */ +} + +#if PPP_OPTIONS +/* + * ipv6_check_options - check that any IP-related options are OK, + * and assign appropriate defaults. + */ +static void ipv6_check_options() { + ipv6cp_options *wo = &ipv6cp_wantoptions[0]; + + if (!ipv6cp_protent.enabled_flag) + return; + + /* + * Persistent link-local id is only used when user has not explicitly + * configure/hard-code the id + */ + if ((wo->use_persistent) && (!wo->opt_local) && (!wo->opt_remote)) { + + /* + * On systems where there are no Ethernet interfaces used, there + * may be other ways to obtain a persistent id. Right now, it + * will fall back to using magic [see eui64_magic] below when + * an EUI-48 from MAC address can't be obtained. Other possibilities + * include obtaining EEPROM serial numbers, or some other unique + * yet persistent number. On Sparc platforms, this is possible, + * but too bad there's no standards yet for x86 machines. + */ + if (ether_to_eui64(&wo->ourid)) { + wo->opt_local = 1; + } + } + + if (!wo->opt_local) { /* init interface identifier */ + if (wo->use_ip && eui64_iszero(wo->ourid)) { + eui64_setlo32(wo->ourid, ntohl(ipcp_wantoptions[0].ouraddr)); + if (!eui64_iszero(wo->ourid)) + wo->opt_local = 1; + } + + while (eui64_iszero(wo->ourid)) + eui64_magic(wo->ourid); + } + + if (!wo->opt_remote) { + if (wo->use_ip && eui64_iszero(wo->hisid)) { + eui64_setlo32(wo->hisid, ntohl(ipcp_wantoptions[0].hisaddr)); + if (!eui64_iszero(wo->hisid)) + wo->opt_remote = 1; + } + } + + if (demand && (eui64_iszero(wo->ourid) || eui64_iszero(wo->hisid))) { + option_error("local/remote LL address required for demand-dialling\n"); + exit(1); + } +} +#endif /* PPP_OPTIONS */ + +#if DEMAND_SUPPORT +/* + * ipv6_demand_conf - configure the interface as though + * IPV6CP were up, for use with dial-on-demand. + */ +static int ipv6_demand_conf(int u) { + ipv6cp_options *wo = &ipv6cp_wantoptions[u]; + + if (!sif6up(u)) + return 0; + + if (!sif6addr(u, wo->ourid, wo->hisid)) + return 0; + + if (!sifnpmode(u, PPP_IPV6, NPMODE_QUEUE)) + return 0; + + ppp_notice("ipv6_demand_conf"); + ppp_notice("local LL address %s", llv6_ntoa(wo->ourid)); + ppp_notice("remote LL address %s", llv6_ntoa(wo->hisid)); + + return 1; +} +#endif /* DEMAND_SUPPORT */ + + +/* + * ipv6cp_up - IPV6CP has come UP. + * + * Configure the IPv6 network interface appropriately and bring it up. + */ +static void ipv6cp_up(fsm *f) { + ppp_pcb *pcb = f->pcb; + ipv6cp_options *wo = &pcb->ipv6cp_wantoptions; + ipv6cp_options *ho = &pcb->ipv6cp_hisoptions; + ipv6cp_options *go = &pcb->ipv6cp_gotoptions; + + IPV6CPDEBUG(("ipv6cp: up")); + + /* + * We must have a non-zero LL address for both ends of the link. + */ + if (!ho->neg_ifaceid) + ho->hisid = wo->hisid; + +#if 0 /* UNUSED */ + if(!no_ifaceid_neg) { +#endif /* UNUSED */ + if (eui64_iszero(ho->hisid)) { + ppp_error("Could not determine remote LL address"); + ipv6cp_close(f->pcb, "Could not determine remote LL address"); + return; + } + if (eui64_iszero(go->ourid)) { + ppp_error("Could not determine local LL address"); + ipv6cp_close(f->pcb, "Could not determine local LL address"); + return; + } + if (eui64_equals(go->ourid, ho->hisid)) { + ppp_error("local and remote LL addresses are equal"); + ipv6cp_close(f->pcb, "local and remote LL addresses are equal"); + return; + } +#if 0 /* UNUSED */ + } +#endif /* UNUSED */ +#if 0 /* UNUSED */ + script_setenv("LLLOCAL", llv6_ntoa(go->ourid), 0); + script_setenv("LLREMOTE", llv6_ntoa(ho->hisid), 0); +#endif /* UNUSED */ + +#ifdef IPV6CP_COMP + /* set tcp compression */ + sif6comp(f->unit, ho->neg_vj); +#endif + +#if DEMAND_SUPPORT + /* + * If we are doing dial-on-demand, the interface is already + * configured, so we put out any saved-up packets, then set the + * interface to pass IPv6 packets. + */ + if (demand) { + if (! eui64_equals(go->ourid, wo->ourid) || + ! eui64_equals(ho->hisid, wo->hisid)) { + if (! eui64_equals(go->ourid, wo->ourid)) + warn("Local LL address changed to %s", + llv6_ntoa(go->ourid)); + if (! eui64_equals(ho->hisid, wo->hisid)) + warn("Remote LL address changed to %s", + llv6_ntoa(ho->hisid)); + ipv6cp_clear_addrs(f->pcb, go->ourid, ho->hisid); + + /* Set the interface to the new addresses */ + if (!sif6addr(f->pcb, go->ourid, ho->hisid)) { + if (debug) + warn("sif6addr failed"); + ipv6cp_close(f->unit, "Interface configuration failed"); + return; + } + + } + demand_rexmit(PPP_IPV6); + sifnpmode(f->unit, PPP_IPV6, NPMODE_PASS); + + } else +#endif /* DEMAND_SUPPORT */ + { + /* + * Set LL addresses + */ + if (!sif6addr(f->pcb, go->ourid, ho->hisid)) { + PPPDEBUG(LOG_DEBUG, ("sif6addr failed")); + ipv6cp_close(f->pcb, "Interface configuration failed"); + return; + } + + /* bring the interface up for IPv6 */ + if (!sif6up(f->pcb)) { + PPPDEBUG(LOG_DEBUG, ("sif6up failed (IPV6)")); + ipv6cp_close(f->pcb, "Interface configuration failed"); + return; + } + sifnpmode(f->pcb, PPP_IPV6, NPMODE_PASS); + + ppp_notice("local LL address %s", llv6_ntoa(go->ourid)); + ppp_notice("remote LL address %s", llv6_ntoa(ho->hisid)); + } + + np_up(f->pcb, PPP_IPV6); + pcb->ipv6cp_is_up = 1; + +#if 0 /* UNUSED */ + /* + * Execute the ipv6-up script, like this: + * /etc/ppp/ipv6-up interface tty speed local-LL remote-LL + */ + if (ipv6cp_script_state == s_down && ipv6cp_script_pid == 0) { + ipv6cp_script_state = s_up; + ipv6cp_script(_PATH_IPV6UP); + } +#endif /* UNUSED */ +} + + +/* + * ipv6cp_down - IPV6CP has gone DOWN. + * + * Take the IPv6 network interface down, clear its addresses + * and delete routes through it. + */ +static void ipv6cp_down(fsm *f) { + ppp_pcb *pcb = f->pcb; + ipv6cp_options *go = &pcb->ipv6cp_gotoptions; + ipv6cp_options *ho = &pcb->ipv6cp_hisoptions; + + IPV6CPDEBUG(("ipv6cp: down")); +#if PPP_STATS_SUPPORT + update_link_stats(f->unit); +#endif /* PPP_STATS_SUPPORT */ + if (pcb->ipv6cp_is_up) { + pcb->ipv6cp_is_up = 0; + np_down(f->pcb, PPP_IPV6); + } +#ifdef IPV6CP_COMP + sif6comp(f->unit, 0); +#endif + +#if DEMAND_SUPPORT + /* + * If we are doing dial-on-demand, set the interface + * to queue up outgoing packets (for now). + */ + if (demand) { + sifnpmode(f->pcb, PPP_IPV6, NPMODE_QUEUE); + } else +#endif /* DEMAND_SUPPORT */ + { + sifnpmode(f->pcb, PPP_IPV6, NPMODE_DROP); + ipv6cp_clear_addrs(f->pcb, + go->ourid, + ho->hisid); + sif6down(f->pcb); + } + +#if 0 /* UNUSED */ + /* Execute the ipv6-down script */ + if (ipv6cp_script_state == s_up && ipv6cp_script_pid == 0) { + ipv6cp_script_state = s_down; + ipv6cp_script(_PATH_IPV6DOWN); + } +#endif /* UNUSED */ +} + + +/* + * ipv6cp_clear_addrs() - clear the interface addresses, routes, + * proxy neighbour discovery entries, etc. + */ +static void ipv6cp_clear_addrs(ppp_pcb *pcb, eui64_t ourid, eui64_t hisid) { + cif6addr(pcb, ourid, hisid); +} + + +/* + * ipv6cp_finished - possibly shut down the lower layers. + */ +static void ipv6cp_finished(fsm *f) { + np_finished(f->pcb, PPP_IPV6); +} + + +#if 0 /* UNUSED */ +/* + * ipv6cp_script_done - called when the ipv6-up or ipv6-down script + * has finished. + */ +static void +ipv6cp_script_done(arg) + void *arg; +{ + ipv6cp_script_pid = 0; + switch (ipv6cp_script_state) { + case s_up: + if (ipv6cp_fsm[0].state != PPP_FSM_OPENED) { + ipv6cp_script_state = s_down; + ipv6cp_script(_PATH_IPV6DOWN); + } + break; + case s_down: + if (ipv6cp_fsm[0].state == PPP_FSM_OPENED) { + ipv6cp_script_state = s_up; + ipv6cp_script(_PATH_IPV6UP); + } + break; + } +} + + +/* + * ipv6cp_script - Execute a script with arguments + * interface-name tty-name speed local-LL remote-LL. + */ +static void +ipv6cp_script(script) + char *script; +{ + char strspeed[32], strlocal[32], strremote[32]; + char *argv[8]; + + sprintf(strspeed, "%d", baud_rate); + strcpy(strlocal, llv6_ntoa(ipv6cp_gotoptions[0].ourid)); + strcpy(strremote, llv6_ntoa(ipv6cp_hisoptions[0].hisid)); + + argv[0] = script; + argv[1] = ifname; + argv[2] = devnam; + argv[3] = strspeed; + argv[4] = strlocal; + argv[5] = strremote; + argv[6] = ipparam; + argv[7] = NULL; + + ipv6cp_script_pid = run_program(script, argv, 0, ipv6cp_script_done, + NULL, 0); +} +#endif /* UNUSED */ + +#if PRINTPKT_SUPPORT +/* + * ipv6cp_printpkt - print the contents of an IPV6CP packet. + */ +static const char *ipv6cp_codenames[] = { + "ConfReq", "ConfAck", "ConfNak", "ConfRej", + "TermReq", "TermAck", "CodeRej" +}; + +static int ipv6cp_printpkt(u_char *p, int plen, + void (*printer)(void *, const char *, ...), void *arg) { + int code, id, len, olen; + u_char *pstart, *optend; + u_short cishort; + eui64_t ifaceid; + + if (plen < HEADERLEN) + return 0; + pstart = p; + GETCHAR(code, p); + GETCHAR(id, p); + GETSHORT(len, p); + if (len < HEADERLEN || len > plen) + return 0; + + if (code >= 1 && code <= (int)sizeof(ipv6cp_codenames) / (int)sizeof(char *)) + printer(arg, " %s", ipv6cp_codenames[code-1]); + else + printer(arg, " code=0x%x", code); + printer(arg, " id=0x%x", id); + len -= HEADERLEN; + switch (code) { + case CONFREQ: + case CONFACK: + case CONFNAK: + case CONFREJ: + /* print option list */ + while (len >= 2) { + GETCHAR(code, p); + GETCHAR(olen, p); + p -= 2; + if (olen < 2 || olen > len) { + break; + } + printer(arg, " <"); + len -= olen; + optend = p + olen; + switch (code) { + case CI_COMPRESSTYPE: + if (olen >= CILEN_COMPRESS) { + p += 2; + GETSHORT(cishort, p); + printer(arg, "compress "); + printer(arg, "0x%x", cishort); + } + break; + case CI_IFACEID: + if (olen == CILEN_IFACEID) { + p += 2; + eui64_get(ifaceid, p); + printer(arg, "addr %s", llv6_ntoa(ifaceid)); + } + break; + default: + break; + } + while (p < optend) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + printer(arg, ">"); + } + break; + + case TERMACK: + case TERMREQ: + if (len > 0 && *p >= ' ' && *p < 0x7f) { + printer(arg, " "); + ppp_print_string((char *)p, len, printer, arg); + p += len; + len = 0; + } + break; + default: + break; + } + + /* print the rest of the bytes in the packet */ + for (; len > 0; --len) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + + return p - pstart; +} +#endif /* PRINTPKT_SUPPORT */ + +#if DEMAND_SUPPORT +/* + * ipv6_active_pkt - see if this IP packet is worth bringing the link up for. + * We don't bring the link up for IP fragments or for TCP FIN packets + * with no data. + */ +#define IP6_HDRLEN 40 /* bytes */ +#define IP6_NHDR_FRAG 44 /* fragment IPv6 header */ +#define TCP_HDRLEN 20 +#define TH_FIN 0x01 + +/* + * We use these macros because the IP header may be at an odd address, + * and some compilers might use word loads to get th_off or ip_hl. + */ + +#define get_ip6nh(x) (((unsigned char *)(x))[6]) +#define get_tcpoff(x) (((unsigned char *)(x))[12] >> 4) +#define get_tcpflags(x) (((unsigned char *)(x))[13]) + +static int ipv6_active_pkt(u_char *pkt, int len) { + u_char *tcp; + + len -= PPP_HDRLEN; + pkt += PPP_HDRLEN; + if (len < IP6_HDRLEN) + return 0; + if (get_ip6nh(pkt) == IP6_NHDR_FRAG) + return 0; + if (get_ip6nh(pkt) != IPPROTO_TCP) + return 1; + if (len < IP6_HDRLEN + TCP_HDRLEN) + return 0; + tcp = pkt + IP6_HDRLEN; + if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == IP6_HDRLEN + get_tcpoff(tcp) * 4) + return 0; + return 1; +} +#endif /* DEMAND_SUPPORT */ + +#endif /* PPP_SUPPORT && PPP_IPV6_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/lcp.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/lcp.c new file mode 100644 index 0000000..5aa99da --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/lcp.c @@ -0,0 +1,2732 @@ +/* + * lcp.c - PPP Link Control Protocol. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. 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. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +/* + * TODO: + */ + +#if 0 /* UNUSED */ +#include +#include +#include +#endif /* UNUSED */ + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/fsm.h" +#include "netif/ppp/lcp.h" +#if CHAP_SUPPORT +#include "netif/ppp/chap-new.h" +#endif /* CHAP_SUPPORT */ +#include "netif/ppp/magic.h" + +/* + * When the link comes up we want to be able to wait for a short while, + * or until seeing some input from the peer, before starting to send + * configure-requests. We do this by delaying the fsm_lowerup call. + */ +/* steal a bit in fsm flags word */ +#define DELAYED_UP 0x80 + +static void lcp_delayed_up(void *arg); + +/* + * LCP-related command-line options. + */ +#if 0 /* UNUSED */ +int lcp_echo_interval = 0; /* Interval between LCP echo-requests */ +int lcp_echo_fails = 0; /* Tolerance to unanswered echo-requests */ +#endif /* UNUSED */ + +#if 0 /* UNUSED */ +/* options */ +static u_int lcp_echo_interval = LCP_ECHOINTERVAL; /* Interval between LCP echo-requests */ +static u_int lcp_echo_fails = LCP_MAXECHOFAILS; /* Tolerance to unanswered echo-requests */ +#endif /* UNUSED */ + +#if 0 /* UNUSED */ +#if PPP_LCP_ADAPTIVE +bool lcp_echo_adaptive = 0; /* request echo only if the link was idle */ +#endif +bool lax_recv = 0; /* accept control chars in asyncmap */ +bool noendpoint = 0; /* don't send/accept endpoint discriminator */ +#endif /* UNUSED */ + +#if PPP_OPTIONS +static int noopt (char **); +#endif /* PPP_OPTIONS */ + +#ifdef HAVE_MULTILINK +static int setendpoint (char **); +static void printendpoint (option_t *, void (*)(void *, char *, ...), + void *); +#endif /* HAVE_MULTILINK */ + +#if PPP_OPTIONS +static option_t lcp_option_list[] = { + /* LCP options */ + { "-all", o_special_noarg, (void *)noopt, + "Don't request/allow any LCP options" }, + + { "noaccomp", o_bool, &lcp_wantoptions[0].neg_accompression, + "Disable address/control compression", + OPT_A2CLR, &lcp_allowoptions[0].neg_accompression }, + { "-ac", o_bool, &lcp_wantoptions[0].neg_accompression, + "Disable address/control compression", + OPT_ALIAS | OPT_A2CLR, &lcp_allowoptions[0].neg_accompression }, + + { "asyncmap", o_uint32, &lcp_wantoptions[0].asyncmap, + "Set asyncmap (for received packets)", + OPT_OR, &lcp_wantoptions[0].neg_asyncmap }, + { "-as", o_uint32, &lcp_wantoptions[0].asyncmap, + "Set asyncmap (for received packets)", + OPT_ALIAS | OPT_OR, &lcp_wantoptions[0].neg_asyncmap }, + { "default-asyncmap", o_uint32, &lcp_wantoptions[0].asyncmap, + "Disable asyncmap negotiation", + OPT_OR | OPT_NOARG | OPT_VAL(~0U) | OPT_A2CLR, + &lcp_allowoptions[0].neg_asyncmap }, + { "-am", o_uint32, &lcp_wantoptions[0].asyncmap, + "Disable asyncmap negotiation", + OPT_ALIAS | OPT_OR | OPT_NOARG | OPT_VAL(~0U) | OPT_A2CLR, + &lcp_allowoptions[0].neg_asyncmap }, + + { "nomagic", o_bool, &lcp_wantoptions[0].neg_magicnumber, + "Disable magic number negotiation (looped-back line detection)", + OPT_A2CLR, &lcp_allowoptions[0].neg_magicnumber }, + { "-mn", o_bool, &lcp_wantoptions[0].neg_magicnumber, + "Disable magic number negotiation (looped-back line detection)", + OPT_ALIAS | OPT_A2CLR, &lcp_allowoptions[0].neg_magicnumber }, + + { "mru", o_int, &lcp_wantoptions[0].mru, + "Set MRU (maximum received packet size) for negotiation", + OPT_PRIO, &lcp_wantoptions[0].neg_mru }, + { "default-mru", o_bool, &lcp_wantoptions[0].neg_mru, + "Disable MRU negotiation (use default 1500)", + OPT_PRIOSUB | OPT_A2CLR, &lcp_allowoptions[0].neg_mru }, + { "-mru", o_bool, &lcp_wantoptions[0].neg_mru, + "Disable MRU negotiation (use default 1500)", + OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR, &lcp_allowoptions[0].neg_mru }, + + { "mtu", o_int, &lcp_allowoptions[0].mru, + "Set our MTU", OPT_LIMITS, NULL, MAXMRU, MINMRU }, + + { "nopcomp", o_bool, &lcp_wantoptions[0].neg_pcompression, + "Disable protocol field compression", + OPT_A2CLR, &lcp_allowoptions[0].neg_pcompression }, + { "-pc", o_bool, &lcp_wantoptions[0].neg_pcompression, + "Disable protocol field compression", + OPT_ALIAS | OPT_A2CLR, &lcp_allowoptions[0].neg_pcompression }, + + { "passive", o_bool, &lcp_wantoptions[0].passive, + "Set passive mode", 1 }, + { "-p", o_bool, &lcp_wantoptions[0].passive, + "Set passive mode", OPT_ALIAS | 1 }, + + { "silent", o_bool, &lcp_wantoptions[0].silent, + "Set silent mode", 1 }, + + { "lcp-echo-failure", o_int, &lcp_echo_fails, + "Set number of consecutive echo failures to indicate link failure", + OPT_PRIO }, + { "lcp-echo-interval", o_int, &lcp_echo_interval, + "Set time in seconds between LCP echo requests", OPT_PRIO }, +#if PPP_LCP_ADAPTIVE + { "lcp-echo-adaptive", o_bool, &lcp_echo_adaptive, + "Suppress LCP echo requests if traffic was received", 1 }, +#endif + { "lcp-restart", o_int, &lcp_fsm[0].timeouttime, + "Set time in seconds between LCP retransmissions", OPT_PRIO }, + { "lcp-max-terminate", o_int, &lcp_fsm[0].maxtermtransmits, + "Set maximum number of LCP terminate-request transmissions", OPT_PRIO }, + { "lcp-max-configure", o_int, &lcp_fsm[0].maxconfreqtransmits, + "Set maximum number of LCP configure-request transmissions", OPT_PRIO }, + { "lcp-max-failure", o_int, &lcp_fsm[0].maxnakloops, + "Set limit on number of LCP configure-naks", OPT_PRIO }, + + { "receive-all", o_bool, &lax_recv, + "Accept all received control characters", 1 }, + +#ifdef HAVE_MULTILINK + { "mrru", o_int, &lcp_wantoptions[0].mrru, + "Maximum received packet size for multilink bundle", + OPT_PRIO, &lcp_wantoptions[0].neg_mrru }, + + { "mpshortseq", o_bool, &lcp_wantoptions[0].neg_ssnhf, + "Use short sequence numbers in multilink headers", + OPT_PRIO | 1, &lcp_allowoptions[0].neg_ssnhf }, + { "nompshortseq", o_bool, &lcp_wantoptions[0].neg_ssnhf, + "Don't use short sequence numbers in multilink headers", + OPT_PRIOSUB | OPT_A2CLR, &lcp_allowoptions[0].neg_ssnhf }, + + { "endpoint", o_special, (void *) setendpoint, + "Endpoint discriminator for multilink", + OPT_PRIO | OPT_A2PRINTER, (void *) printendpoint }, +#endif /* HAVE_MULTILINK */ + + { "noendpoint", o_bool, &noendpoint, + "Don't send or accept multilink endpoint discriminator", 1 }, + + {NULL} +}; +#endif /* PPP_OPTIONS */ + +/* + * Callbacks for fsm code. (CI = Configuration Information) + */ +static void lcp_resetci(fsm *f); /* Reset our CI */ +static int lcp_cilen(fsm *f); /* Return length of our CI */ +static void lcp_addci(fsm *f, u_char *ucp, int *lenp); /* Add our CI to pkt */ +static int lcp_ackci(fsm *f, u_char *p, int len); /* Peer ack'd our CI */ +static int lcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject); /* Peer nak'd our CI */ +static int lcp_rejci(fsm *f, u_char *p, int len); /* Peer rej'd our CI */ +static int lcp_reqci(fsm *f, u_char *inp, int *lenp, int reject_if_disagree); /* Rcv peer CI */ +static void lcp_up(fsm *f); /* We're UP */ +static void lcp_down(fsm *f); /* We're DOWN */ +static void lcp_starting (fsm *); /* We need lower layer up */ +static void lcp_finished (fsm *); /* We need lower layer down */ +static int lcp_extcode(fsm *f, int code, int id, u_char *inp, int len); +static void lcp_rprotrej(fsm *f, u_char *inp, int len); + +/* + * routines to send LCP echos to peer + */ + +static void lcp_echo_lowerup(ppp_pcb *pcb); +static void lcp_echo_lowerdown(ppp_pcb *pcb); +static void LcpEchoTimeout(void *arg); +static void lcp_received_echo_reply(fsm *f, int id, u_char *inp, int len); +static void LcpSendEchoRequest(fsm *f); +static void LcpLinkFailure(fsm *f); +static void LcpEchoCheck(fsm *f); + +static const fsm_callbacks lcp_callbacks = { /* LCP callback routines */ + lcp_resetci, /* Reset our Configuration Information */ + lcp_cilen, /* Length of our Configuration Information */ + lcp_addci, /* Add our Configuration Information */ + lcp_ackci, /* ACK our Configuration Information */ + lcp_nakci, /* NAK our Configuration Information */ + lcp_rejci, /* Reject our Configuration Information */ + lcp_reqci, /* Request peer's Configuration Information */ + lcp_up, /* Called when fsm reaches OPENED state */ + lcp_down, /* Called when fsm leaves OPENED state */ + lcp_starting, /* Called when we want the lower layer up */ + lcp_finished, /* Called when we want the lower layer down */ + NULL, /* Called when Protocol-Reject received */ + NULL, /* Retransmission is necessary */ + lcp_extcode, /* Called to handle LCP-specific codes */ + "LCP" /* String name of protocol */ +}; + +/* + * Protocol entry points. + * Some of these are called directly. + */ + +static void lcp_init(ppp_pcb *pcb); +static void lcp_input(ppp_pcb *pcb, u_char *p, int len); +static void lcp_protrej(ppp_pcb *pcb); +#if PRINTPKT_SUPPORT +static int lcp_printpkt(u_char *p, int plen, + void (*printer) (void *, const char *, ...), void *arg); +#endif /* PRINTPKT_SUPPORT */ + +const struct protent lcp_protent = { + PPP_LCP, + lcp_init, + lcp_input, + lcp_protrej, + lcp_lowerup, + lcp_lowerdown, + lcp_open, + lcp_close, +#if PRINTPKT_SUPPORT + lcp_printpkt, +#endif /* PRINTPKT_SUPPORT */ + NULL, + 1, +#if PRINTPKT_SUPPORT + "LCP", + NULL, +#endif /* PRINTPKT_SUPPORT */ +#if PPP_OPTIONS + lcp_option_list, + NULL, +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT + NULL, + NULL +#endif /* DEMAND_SUPPORT */ +}; + +/* + * Length of each type of configuration option (in octets) + */ +#define CILEN_VOID 2 +#define CILEN_CHAR 3 +#define CILEN_SHORT 4 /* CILEN_VOID + 2 */ +#if CHAP_SUPPORT +#define CILEN_CHAP 5 /* CILEN_VOID + 2 + 1 */ +#endif /* CHAP_SUPPORT */ +#define CILEN_LONG 6 /* CILEN_VOID + 4 */ +#if LQR_SUPPORT +#define CILEN_LQR 8 /* CILEN_VOID + 2 + 4 */ +#endif /* LQR_SUPPORT */ +#define CILEN_CBCP 3 + +#define CODENAME(x) ((x) == CONFACK ? "ACK" : \ + (x) == CONFNAK ? "NAK" : "REJ") + +#if PPP_OPTIONS +/* + * noopt - Disable all options (why?). + */ +static int +noopt(argv) + char **argv; +{ + BZERO((char *) &lcp_wantoptions[0], sizeof (struct lcp_options)); + BZERO((char *) &lcp_allowoptions[0], sizeof (struct lcp_options)); + + return (1); +} +#endif /* PPP_OPTIONS */ + +#ifdef HAVE_MULTILINK +static int +setendpoint(argv) + char **argv; +{ + if (str_to_epdisc(&lcp_wantoptions[0].endpoint, *argv)) { + lcp_wantoptions[0].neg_endpoint = 1; + return 1; + } + option_error("Can't parse '%s' as an endpoint discriminator", *argv); + return 0; +} + +static void +printendpoint(opt, printer, arg) + option_t *opt; + void (*printer) (void *, char *, ...); + void *arg; +{ + printer(arg, "%s", epdisc_to_str(&lcp_wantoptions[0].endpoint)); +} +#endif /* HAVE_MULTILINK */ + +/* + * lcp_init - Initialize LCP. + */ +static void lcp_init(ppp_pcb *pcb) { + fsm *f = &pcb->lcp_fsm; + lcp_options *wo = &pcb->lcp_wantoptions; + lcp_options *ao = &pcb->lcp_allowoptions; + + f->pcb = pcb; + f->protocol = PPP_LCP; + f->callbacks = &lcp_callbacks; + + fsm_init(f); + + BZERO(wo, sizeof(*wo)); + wo->neg_mru = 1; + wo->mru = DEFMRU; + wo->neg_asyncmap = 1; + wo->neg_magicnumber = 1; + wo->neg_pcompression = 1; + wo->neg_accompression = 1; + + BZERO(ao, sizeof(*ao)); + ao->neg_mru = 1; + ao->mru = MAXMRU; + ao->neg_asyncmap = 1; +#if CHAP_SUPPORT + ao->neg_chap = 1; + ao->chap_mdtype = CHAP_MDTYPE_SUPPORTED; +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + ao->neg_upap = 1; +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + ao->neg_eap = 1; +#endif /* EAP_SUPPORT */ + ao->neg_magicnumber = 1; + ao->neg_pcompression = 1; + ao->neg_accompression = 1; + ao->neg_endpoint = 1; + +#if PPPOS_SUPPORT + /* + * Set transmit escape for the flag and escape characters plus anything + * set for the allowable options. + */ + memset(pcb->xmit_accm, 0, sizeof(ext_accm)); + pcb->xmit_accm[15] = 0x60; + pcb->xmit_accm[0] = (u_char)((ao->asyncmap & 0xFF)); + pcb->xmit_accm[1] = (u_char)((ao->asyncmap >> 8) & 0xFF); + pcb->xmit_accm[2] = (u_char)((ao->asyncmap >> 16) & 0xFF); + pcb->xmit_accm[3] = (u_char)((ao->asyncmap >> 24) & 0xFF); + LCPDEBUG(("lcp_init: xmit_accm=%X %X %X %X\n", + pcb->xmit_accm[0], + pcb->xmit_accm[1], + pcb->xmit_accm[2], + pcb->xmit_accm[3])); +#endif /* PPPOS_SUPPORT */ +} + + +/* + * lcp_open - LCP is allowed to come up. + */ +void lcp_open(ppp_pcb *pcb) { + fsm *f = &pcb->lcp_fsm; + lcp_options *wo = &pcb->lcp_wantoptions; + + f->flags &= ~(OPT_PASSIVE | OPT_SILENT); + if (wo->passive) + f->flags |= OPT_PASSIVE; + if (wo->silent) + f->flags |= OPT_SILENT; + fsm_open(f); +} + + +/* + * lcp_close - Take LCP down. + */ +void lcp_close(ppp_pcb *pcb, const char *reason) { + fsm *f = &pcb->lcp_fsm; + int oldstate; + + if (pcb->phase != PPP_PHASE_DEAD && pcb->phase != PPP_PHASE_MASTER) + new_phase(pcb, PPP_PHASE_TERMINATE); + + if (f->flags & DELAYED_UP) { + UNTIMEOUT(lcp_delayed_up, f); + f->state = PPP_FSM_STOPPED; + } + oldstate = f->state; + + fsm_close(f, reason); + if (oldstate == PPP_FSM_STOPPED && (f->flags & (OPT_PASSIVE|OPT_SILENT|DELAYED_UP))) { + /* + * This action is not strictly according to the FSM in RFC1548, + * but it does mean that the program terminates if you do a + * lcp_close() when a connection hasn't been established + * because we are in passive/silent mode or because we have + * delayed the fsm_lowerup() call and it hasn't happened yet. + */ + f->flags &= ~DELAYED_UP; + lcp_finished(f); + } +} + + +/* + * lcp_lowerup - The lower layer is up. + */ +void lcp_lowerup(ppp_pcb *pcb) { + lcp_options *wo = &pcb->lcp_wantoptions; +#if PPPOS_SUPPORT + lcp_options *ao = &pcb->lcp_allowoptions; +#endif /* PPPOS_SUPPORT */ + fsm *f = &pcb->lcp_fsm; + /* + * Don't use A/C or protocol compression on transmission, + * but accept A/C and protocol compressed packets + * if we are going to ask for A/C and protocol compression. + */ +#if PPPOS_SUPPORT + ppp_set_xaccm(pcb, &pcb->xmit_accm); +#endif /* PPPOS_SUPPORT */ + if (ppp_send_config(pcb, PPP_MRU, 0xffffffff, 0, 0) < 0 + || ppp_recv_config(pcb, PPP_MRU, (pcb->settings.lax_recv? 0: 0xffffffff), + wo->neg_pcompression, wo->neg_accompression) < 0) + return; + pcb->peer_mru = PPP_MRU; + +#if PPPOS_SUPPORT + ao->asyncmap = (u_long)pcb->xmit_accm[0] + | ((u_long)pcb->xmit_accm[1] << 8) + | ((u_long)pcb->xmit_accm[2] << 16) + | ((u_long)pcb->xmit_accm[3] << 24); + LCPDEBUG(("lcp_lowerup: asyncmap=%X %X %X %X\n", + pcb->xmit_accm[3], + pcb->xmit_accm[2], + pcb->xmit_accm[1], + pcb->xmit_accm[0])); +#endif /* PPPOS_SUPPORT */ + + if (pcb->settings.listen_time != 0) { + f->flags |= DELAYED_UP; + TIMEOUTMS(lcp_delayed_up, f, pcb->settings.listen_time); + } else + fsm_lowerup(f); +} + + +/* + * lcp_lowerdown - The lower layer is down. + */ +void lcp_lowerdown(ppp_pcb *pcb) { + fsm *f = &pcb->lcp_fsm; + + if (f->flags & DELAYED_UP) { + f->flags &= ~DELAYED_UP; + UNTIMEOUT(lcp_delayed_up, f); + } else + fsm_lowerdown(f); +} + + +/* + * lcp_delayed_up - Bring the lower layer up now. + */ +static void lcp_delayed_up(void *arg) { + fsm *f = (fsm*)arg; + + if (f->flags & DELAYED_UP) { + f->flags &= ~DELAYED_UP; + fsm_lowerup(f); + } +} + + +/* + * lcp_input - Input LCP packet. + */ +static void lcp_input(ppp_pcb *pcb, u_char *p, int len) { + fsm *f = &pcb->lcp_fsm; + + if (f->flags & DELAYED_UP) { + f->flags &= ~DELAYED_UP; + UNTIMEOUT(lcp_delayed_up, f); + fsm_lowerup(f); + } + fsm_input(f, p, len); +} + +/* + * lcp_extcode - Handle a LCP-specific code. + */ +static int lcp_extcode(fsm *f, int code, int id, u_char *inp, int len) { + ppp_pcb *pcb = f->pcb; + lcp_options *go = &pcb->lcp_gotoptions; + u_char *magp; + + switch( code ){ + case PROTREJ: + lcp_rprotrej(f, inp, len); + break; + + case ECHOREQ: + if (f->state != PPP_FSM_OPENED) + break; + magp = inp; + PUTLONG(go->magicnumber, magp); + fsm_sdata(f, ECHOREP, id, inp, len); + break; + + case ECHOREP: + lcp_received_echo_reply(f, id, inp, len); + break; + + case DISCREQ: + case IDENTIF: + case TIMEREM: + break; + + default: + return 0; + } + return 1; +} + + +/* + * lcp_rprotrej - Receive an Protocol-Reject. + * + * Figure out which protocol is rejected and inform it. + */ +static void lcp_rprotrej(fsm *f, u_char *inp, int len) { + int i; + const struct protent *protp; + u_short prot; +#if PPP_PROTOCOLNAME + const char *pname; +#endif /* PPP_PROTOCOLNAME */ + + if (len < 2) { + LCPDEBUG(("lcp_rprotrej: Rcvd short Protocol-Reject packet!")); + return; + } + + GETSHORT(prot, inp); + + /* + * Protocol-Reject packets received in any state other than the LCP + * OPENED state SHOULD be silently discarded. + */ + if( f->state != PPP_FSM_OPENED ){ + LCPDEBUG(("Protocol-Reject discarded: LCP in state %d", f->state)); + return; + } + +#if PPP_PROTOCOLNAME + pname = protocol_name(prot); +#endif /* PPP_PROTOCOLNAME */ + + /* + * Upcall the proper Protocol-Reject routine. + */ + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if (protp->protocol == prot && protp->enabled_flag) { +#if PPP_PROTOCOLNAME + if (pname != NULL) + ppp_dbglog("Protocol-Reject for '%s' (0x%x) received", pname, + prot); + else +#endif /* PPP_PROTOCOLNAME */ + ppp_dbglog("Protocol-Reject for 0x%x received", prot); + (*protp->protrej)(f->pcb); + return; + } + +#if PPP_PROTOCOLNAME + if (pname != NULL) + ppp_warn("Protocol-Reject for unsupported protocol '%s' (0x%x)", pname, + prot); + else +#endif /* #if PPP_PROTOCOLNAME */ + ppp_warn("Protocol-Reject for unsupported protocol 0x%x", prot); +} + + +/* + * lcp_protrej - A Protocol-Reject was received. + */ +/*ARGSUSED*/ +static void lcp_protrej(ppp_pcb *pcb) { + /* + * Can't reject LCP! + */ + ppp_error("Received Protocol-Reject for LCP!"); + fsm_protreject(&pcb->lcp_fsm); +} + + +/* + * lcp_sprotrej - Send a Protocol-Reject for some protocol. + */ +void lcp_sprotrej(ppp_pcb *pcb, u_char *p, int len) { + fsm *f = &pcb->lcp_fsm; + /* + * Send back the protocol and the information field of the + * rejected packet. We only get here if LCP is in the OPENED state. + */ +#if 0 + p += 2; + len -= 2; +#endif + + fsm_sdata(f, PROTREJ, ++f->id, + p, len); +} + + +/* + * lcp_resetci - Reset our CI. + */ +static void lcp_resetci(fsm *f) { + ppp_pcb *pcb = f->pcb; + lcp_options *wo = &pcb->lcp_wantoptions; + lcp_options *go = &pcb->lcp_gotoptions; + lcp_options *ao = &pcb->lcp_allowoptions; + + wo->magicnumber = magic(); + wo->numloops = 0; + *go = *wo; +#ifdef HAVE_MULTILINK + if (!multilink) { + go->neg_mrru = 0; +#endif /* HAVE_MULTILINK */ + go->neg_ssnhf = 0; + go->neg_endpoint = 0; +#ifdef HAVE_MULTILINK + } +#endif /* HAVE_MULTILINK */ + if (pcb->settings.noendpoint) + ao->neg_endpoint = 0; + pcb->peer_mru = PPP_MRU; + auth_reset(pcb); +} + + +/* + * lcp_cilen - Return length of our CI. + */ +static int lcp_cilen(fsm *f) { + ppp_pcb *pcb = f->pcb; + lcp_options *go = &pcb->lcp_gotoptions; + +#define LENCIVOID(neg) ((neg) ? CILEN_VOID : 0) +#if CHAP_SUPPORT +#define LENCICHAP(neg) ((neg) ? CILEN_CHAP : 0) +#endif /* CHAP_SUPPORT */ +#define LENCISHORT(neg) ((neg) ? CILEN_SHORT : 0) +#define LENCILONG(neg) ((neg) ? CILEN_LONG : 0) +#if LQR_SUPPORT +#define LENCILQR(neg) ((neg) ? CILEN_LQR: 0) +#endif /* LQR_SUPPORT */ +#define LENCICBCP(neg) ((neg) ? CILEN_CBCP: 0) + /* + * NB: we only ask for one of CHAP, UPAP, or EAP, even if we will + * accept more than one. We prefer EAP first, then CHAP, then + * PAP. + */ + return (LENCISHORT(go->neg_mru && go->mru != DEFMRU) + + LENCILONG(go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) + +#if EAP_SUPPORT + LENCISHORT(go->neg_eap) + +#endif /* EAP_SUPPORT */ +#if CHAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */ +#if EAP_SUPPORT + LENCICHAP(!go->neg_eap && go->neg_chap) + +#endif /* EAP_SUPPORT */ +#if !EAP_SUPPORT + LENCICHAP(go->neg_chap) + +#endif /* !EAP_SUPPORT */ +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */ +#if EAP_SUPPORT && CHAP_SUPPORT + LENCISHORT(!go->neg_eap && !go->neg_chap && go->neg_upap) + +#endif /* EAP_SUPPORT && CHAP_SUPPORT */ +#if EAP_SUPPORT && !CHAP_SUPPORT + LENCISHORT(!go->neg_eap && go->neg_upap) + +#endif /* EAP_SUPPORT && !CHAP_SUPPORT */ +#if !EAP_SUPPORT && CHAP_SUPPORT + LENCISHORT(!go->neg_chap && go->neg_upap) + +#endif /* !EAP_SUPPORT && CHAP_SUPPORT */ +#if !EAP_SUPPORT && !CHAP_SUPPORT + LENCISHORT(go->neg_upap) + +#endif /* !EAP_SUPPORT && !CHAP_SUPPORT */ +#endif /* PAP_SUPPORT */ +#if LQR_SUPPORT + LENCILQR(go->neg_lqr) + +#endif /* LQR_SUPPORT */ + LENCICBCP(go->neg_cbcp) + + LENCILONG(go->neg_magicnumber) + + LENCIVOID(go->neg_pcompression) + + LENCIVOID(go->neg_accompression) + +#ifdef HAVE_MULTILINK + LENCISHORT(go->neg_mrru) + +#endif /* HAVE_MULTILINK */ + LENCIVOID(go->neg_ssnhf) + + (go->neg_endpoint? CILEN_CHAR + go->endpoint.length: 0)); +} + + +/* + * lcp_addci - Add our desired CIs to a packet. + */ +static void lcp_addci(fsm *f, u_char *ucp, int *lenp) { + ppp_pcb *pcb = f->pcb; + lcp_options *go = &pcb->lcp_gotoptions; + u_char *start_ucp = ucp; + +#define ADDCIVOID(opt, neg) \ + if (neg) { \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_VOID, ucp); \ + } +#define ADDCISHORT(opt, neg, val) \ + if (neg) { \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_SHORT, ucp); \ + PUTSHORT(val, ucp); \ + } +#if CHAP_SUPPORT +#define ADDCICHAP(opt, neg, val) \ + if (neg) { \ + PUTCHAR((opt), ucp); \ + PUTCHAR(CILEN_CHAP, ucp); \ + PUTSHORT(PPP_CHAP, ucp); \ + PUTCHAR((CHAP_DIGEST(val)), ucp); \ + } +#endif /* CHAP_SUPPORT */ +#define ADDCILONG(opt, neg, val) \ + if (neg) { \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_LONG, ucp); \ + PUTLONG(val, ucp); \ + } +#if LQR_SUPPORT +#define ADDCILQR(opt, neg, val) \ + if (neg) { \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_LQR, ucp); \ + PUTSHORT(PPP_LQR, ucp); \ + PUTLONG(val, ucp); \ + } +#endif /* LQR_SUPPORT */ +#define ADDCICHAR(opt, neg, val) \ + if (neg) { \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_CHAR, ucp); \ + PUTCHAR(val, ucp); \ + } +#define ADDCIENDP(opt, neg, class, val, len) \ + if (neg) { \ + int i; \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_CHAR + len, ucp); \ + PUTCHAR(class, ucp); \ + for (i = 0; i < len; ++i) \ + PUTCHAR(val[i], ucp); \ + } + + ADDCISHORT(CI_MRU, go->neg_mru && go->mru != DEFMRU, go->mru); + ADDCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF, + go->asyncmap); +#if EAP_SUPPORT + ADDCISHORT(CI_AUTHTYPE, go->neg_eap, PPP_EAP); +#endif /* EAP_SUPPORT */ +#if CHAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */ +#if EAP_SUPPORT + ADDCICHAP(CI_AUTHTYPE, !go->neg_eap && go->neg_chap, go->chap_mdtype); +#endif /* EAP_SUPPORT */ +#if !EAP_SUPPORT + ADDCICHAP(CI_AUTHTYPE, go->neg_chap, go->chap_mdtype); +#endif /* !EAP_SUPPORT */ +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */ +#if EAP_SUPPORT && CHAP_SUPPORT + ADDCISHORT(CI_AUTHTYPE, !go->neg_eap && !go->neg_chap && go->neg_upap, PPP_PAP); +#endif /* EAP_SUPPORT && CHAP_SUPPORT */ +#if EAP_SUPPORT && !CHAP_SUPPORT + ADDCISHORT(CI_AUTHTYPE, !go->neg_eap && go->neg_upap, PPP_PAP); +#endif /* EAP_SUPPORT && !CHAP_SUPPORT */ +#if !EAP_SUPPORT && CHAP_SUPPORT + ADDCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP); +#endif /* !EAP_SUPPORT && CHAP_SUPPORT */ +#if !EAP_SUPPORT && !CHAP_SUPPORT + ADDCISHORT(CI_AUTHTYPE, go->neg_upap, PPP_PAP); +#endif /* !EAP_SUPPORT && !CHAP_SUPPORT */ +#endif /* PAP_SUPPORT */ +#if LQR_SUPPORT + ADDCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period); +#endif /* LQR_SUPPORT */ + ADDCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT); + ADDCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber); + ADDCIVOID(CI_PCOMPRESSION, go->neg_pcompression); + ADDCIVOID(CI_ACCOMPRESSION, go->neg_accompression); +#ifdef HAVE_MULTILINK + ADDCISHORT(CI_MRRU, go->neg_mrru, go->mrru); +#endif + ADDCIVOID(CI_SSNHF, go->neg_ssnhf); + ADDCIENDP(CI_EPDISC, go->neg_endpoint, go->endpoint.class_, + go->endpoint.value, go->endpoint.length); + + if (ucp - start_ucp != *lenp) { + /* this should never happen, because peer_mtu should be 1500 */ + ppp_error("Bug in lcp_addci: wrong length"); + } +} + + +/* + * lcp_ackci - Ack our CIs. + * This should not modify any state if the Ack is bad. + * + * Returns: + * 0 - Ack was bad. + * 1 - Ack was good. + */ +static int lcp_ackci(fsm *f, u_char *p, int len) { + ppp_pcb *pcb = f->pcb; + lcp_options *go = &pcb->lcp_gotoptions; + u_char cilen, citype, cichar; + u_short cishort; + u32_t cilong; + + /* + * CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define ACKCIVOID(opt, neg) \ + if (neg) { \ + if ((len -= CILEN_VOID) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_VOID || \ + citype != opt) \ + goto bad; \ + } +#define ACKCISHORT(opt, neg, val) \ + if (neg) { \ + if ((len -= CILEN_SHORT) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_SHORT || \ + citype != opt) \ + goto bad; \ + GETSHORT(cishort, p); \ + if (cishort != val) \ + goto bad; \ + } +#define ACKCICHAR(opt, neg, val) \ + if (neg) { \ + if ((len -= CILEN_CHAR) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_CHAR || \ + citype != opt) \ + goto bad; \ + GETCHAR(cichar, p); \ + if (cichar != val) \ + goto bad; \ + } +#if CHAP_SUPPORT +#define ACKCICHAP(opt, neg, val) \ + if (neg) { \ + if ((len -= CILEN_CHAP) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_CHAP || \ + citype != (opt)) \ + goto bad; \ + GETSHORT(cishort, p); \ + if (cishort != PPP_CHAP) \ + goto bad; \ + GETCHAR(cichar, p); \ + if (cichar != (CHAP_DIGEST(val))) \ + goto bad; \ + } +#endif /* CHAP_SUPPORT */ +#define ACKCILONG(opt, neg, val) \ + if (neg) { \ + if ((len -= CILEN_LONG) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_LONG || \ + citype != opt) \ + goto bad; \ + GETLONG(cilong, p); \ + if (cilong != val) \ + goto bad; \ + } +#if LQR_SUPPORT +#define ACKCILQR(opt, neg, val) \ + if (neg) { \ + if ((len -= CILEN_LQR) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_LQR || \ + citype != opt) \ + goto bad; \ + GETSHORT(cishort, p); \ + if (cishort != PPP_LQR) \ + goto bad; \ + GETLONG(cilong, p); \ + if (cilong != val) \ + goto bad; \ + } +#endif /* LQR_SUPPORT */ +#define ACKCIENDP(opt, neg, class, val, vlen) \ + if (neg) { \ + int i; \ + if ((len -= CILEN_CHAR + vlen) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_CHAR + vlen || \ + citype != opt) \ + goto bad; \ + GETCHAR(cichar, p); \ + if (cichar != class) \ + goto bad; \ + for (i = 0; i < vlen; ++i) { \ + GETCHAR(cichar, p); \ + if (cichar != val[i]) \ + goto bad; \ + } \ + } + + ACKCISHORT(CI_MRU, go->neg_mru && go->mru != DEFMRU, go->mru); + ACKCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF, + go->asyncmap); +#if EAP_SUPPORT + ACKCISHORT(CI_AUTHTYPE, go->neg_eap, PPP_EAP); +#endif /* EAP_SUPPORT */ +#if CHAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */ +#if EAP_SUPPORT + ACKCICHAP(CI_AUTHTYPE, !go->neg_eap && go->neg_chap, go->chap_mdtype); +#endif /* EAP_SUPPORT */ +#if !EAP_SUPPORT + ACKCICHAP(CI_AUTHTYPE, go->neg_chap, go->chap_mdtype); +#endif /* !EAP_SUPPORT */ +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */ +#if EAP_SUPPORT && CHAP_SUPPORT + ACKCISHORT(CI_AUTHTYPE, !go->neg_eap && !go->neg_chap && go->neg_upap, PPP_PAP); +#endif /* EAP_SUPPORT && CHAP_SUPPORT */ +#if EAP_SUPPORT && !CHAP_SUPPORT + ACKCISHORT(CI_AUTHTYPE, !go->neg_eap && go->neg_upap, PPP_PAP); +#endif /* EAP_SUPPORT && !CHAP_SUPPORT */ +#if !EAP_SUPPORT && CHAP_SUPPORT + ACKCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP); +#endif /* !EAP_SUPPORT && CHAP_SUPPORT */ +#if !EAP_SUPPORT && !CHAP_SUPPORT + ACKCISHORT(CI_AUTHTYPE, go->neg_upap, PPP_PAP); +#endif /* !EAP_SUPPORT && !CHAP_SUPPORT */ +#endif /* PAP_SUPPORT */ +#if LQR_SUPPORT + ACKCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period); +#endif /* LQR_SUPPORT */ + ACKCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT); + ACKCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber); + ACKCIVOID(CI_PCOMPRESSION, go->neg_pcompression); + ACKCIVOID(CI_ACCOMPRESSION, go->neg_accompression); +#ifdef HAVE_MULTILINK + ACKCISHORT(CI_MRRU, go->neg_mrru, go->mrru); +#endif /* HAVE_MULTILINK */ + ACKCIVOID(CI_SSNHF, go->neg_ssnhf); + ACKCIENDP(CI_EPDISC, go->neg_endpoint, go->endpoint.class_, + go->endpoint.value, go->endpoint.length); + + /* + * If there are any remaining CIs, then this packet is bad. + */ + if (len != 0) + goto bad; + return (1); +bad: + LCPDEBUG(("lcp_acki: received bad Ack!")); + return (0); +} + + +/* + * lcp_nakci - Peer has sent a NAK for some of our CIs. + * This should not modify any state if the Nak is bad + * or if LCP is in the OPENED state. + * + * Returns: + * 0 - Nak was bad. + * 1 - Nak was good. + */ +static int lcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) { + ppp_pcb *pcb = f->pcb; + lcp_options *go = &pcb->lcp_gotoptions; + lcp_options *wo = &pcb->lcp_wantoptions; + u_char citype, cichar, *next; + u_short cishort; + u32_t cilong; + lcp_options no; /* options we've seen Naks for */ + lcp_options try_; /* options to request next time */ + int looped_back = 0; + int cilen; + + BZERO(&no, sizeof(no)); + try_ = *go; + + /* + * Any Nak'd CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define NAKCIVOID(opt, neg) \ + if (go->neg && \ + len >= CILEN_VOID && \ + p[1] == CILEN_VOID && \ + p[0] == opt) { \ + len -= CILEN_VOID; \ + INCPTR(CILEN_VOID, p); \ + no.neg = 1; \ + try_.neg = 0; \ + } +#if CHAP_SUPPORT +#define NAKCICHAP(opt, neg, code) \ + if (go->neg && \ + len >= CILEN_CHAP && \ + p[1] == CILEN_CHAP && \ + p[0] == opt) { \ + len -= CILEN_CHAP; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETCHAR(cichar, p); \ + no.neg = 1; \ + code \ + } +#endif /* CHAP_SUPPORT */ +#define NAKCICHAR(opt, neg, code) \ + if (go->neg && \ + len >= CILEN_CHAR && \ + p[1] == CILEN_CHAR && \ + p[0] == opt) { \ + len -= CILEN_CHAR; \ + INCPTR(2, p); \ + GETCHAR(cichar, p); \ + no.neg = 1; \ + code \ + } +#define NAKCISHORT(opt, neg, code) \ + if (go->neg && \ + len >= CILEN_SHORT && \ + p[1] == CILEN_SHORT && \ + p[0] == opt) { \ + len -= CILEN_SHORT; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + no.neg = 1; \ + code \ + } +#define NAKCILONG(opt, neg, code) \ + if (go->neg && \ + len >= CILEN_LONG && \ + p[1] == CILEN_LONG && \ + p[0] == opt) { \ + len -= CILEN_LONG; \ + INCPTR(2, p); \ + GETLONG(cilong, p); \ + no.neg = 1; \ + code \ + } +#if LQR_SUPPORT +#define NAKCILQR(opt, neg, code) \ + if (go->neg && \ + len >= CILEN_LQR && \ + p[1] == CILEN_LQR && \ + p[0] == opt) { \ + len -= CILEN_LQR; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETLONG(cilong, p); \ + no.neg = 1; \ + code \ + } +#endif /* LQR_SUPPORT */ +#define NAKCIENDP(opt, neg) \ + if (go->neg && \ + len >= CILEN_CHAR && \ + p[0] == opt && \ + p[1] >= CILEN_CHAR && \ + p[1] <= len) { \ + len -= p[1]; \ + INCPTR(p[1], p); \ + no.neg = 1; \ + try_.neg = 0; \ + } + + /* + * NOTE! There must be no assignments to individual fields of *go in + * the code below. Any such assignment is a BUG! + */ + /* + * We don't care if they want to send us smaller packets than + * we want. Therefore, accept any MRU less than what we asked for, + * but then ignore the new value when setting the MRU in the kernel. + * If they send us a bigger MRU than what we asked, accept it, up to + * the limit of the default MRU we'd get if we didn't negotiate. + */ + if (go->neg_mru && go->mru != DEFMRU) { + NAKCISHORT(CI_MRU, neg_mru, + if (cishort <= wo->mru || cishort <= DEFMRU) + try_.mru = cishort; + ); + } + + /* + * Add any characters they want to our (receive-side) asyncmap. + */ + if (go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) { + NAKCILONG(CI_ASYNCMAP, neg_asyncmap, + try_.asyncmap = go->asyncmap | cilong; + ); + } + + /* + * If they've nak'd our authentication-protocol, check whether + * they are proposing a different protocol, or a different + * hash algorithm for CHAP. + */ + if ((0 +#if CHAP_SUPPORT + || go->neg_chap +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + || go->neg_upap +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + || go->neg_eap +#endif /* EAP_SUPPORT */ + ) + && len >= CILEN_SHORT + && p[0] == CI_AUTHTYPE && p[1] >= CILEN_SHORT && p[1] <= len) { + cilen = p[1]; + len -= cilen; +#if CHAP_SUPPORT + no.neg_chap = go->neg_chap; +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + no.neg_upap = go->neg_upap; +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + no.neg_eap = go->neg_eap; +#endif /* EAP_SUPPORT */ + INCPTR(2, p); + GETSHORT(cishort, p); + +#if PAP_SUPPORT + if (cishort == PPP_PAP && cilen == CILEN_SHORT) { +#if EAP_SUPPORT + /* If we were asking for EAP, then we need to stop that. */ + if (go->neg_eap) + try_.neg_eap = 0; + else +#endif /* EAP_SUPPORT */ + +#if CHAP_SUPPORT + /* If we were asking for CHAP, then we need to stop that. */ + if (go->neg_chap) + try_.neg_chap = 0; + else +#endif /* CHAP_SUPPORT */ + + /* + * If we weren't asking for CHAP or EAP, then we were asking for + * PAP, in which case this Nak is bad. + */ + goto bad; + } else +#endif /* PAP_SUPPORT */ + +#if CHAP_SUPPORT + if (cishort == PPP_CHAP && cilen == CILEN_CHAP) { + GETCHAR(cichar, p); +#if EAP_SUPPORT + /* Stop asking for EAP, if we were. */ + if (go->neg_eap) { + try_.neg_eap = 0; + /* Try to set up to use their suggestion, if possible */ + if (CHAP_CANDIGEST(go->chap_mdtype, cichar)) + try_.chap_mdtype = CHAP_MDTYPE_D(cichar); + } else +#endif /* EAP_SUPPORT */ + if (go->neg_chap) { + /* + * We were asking for our preferred algorithm, they must + * want something different. + */ + if (cichar != CHAP_DIGEST(go->chap_mdtype)) { + if (CHAP_CANDIGEST(go->chap_mdtype, cichar)) { + /* Use their suggestion if we support it ... */ + try_.chap_mdtype = CHAP_MDTYPE_D(cichar); + } else { + /* ... otherwise, try our next-preferred algorithm. */ + try_.chap_mdtype &= ~(CHAP_MDTYPE(try_.chap_mdtype)); + if (try_.chap_mdtype == MDTYPE_NONE) /* out of algos */ + try_.neg_chap = 0; + } + } else { + /* + * Whoops, they Nak'd our algorithm of choice + * but then suggested it back to us. + */ + goto bad; + } + } else { + /* + * Stop asking for PAP if we were asking for it. + */ +#if PAP_SUPPORT + try_.neg_upap = 0; +#endif /* PAP_SUPPORT */ + } + + } else +#endif /* CHAP_SUPPORT */ + { + +#if EAP_SUPPORT + /* + * If we were asking for EAP, and they're Conf-Naking EAP, + * well, that's just strange. Nobody should do that. + */ + if (cishort == PPP_EAP && cilen == CILEN_SHORT && go->neg_eap) + ppp_dbglog("Unexpected Conf-Nak for EAP"); + + /* + * We don't recognize what they're suggesting. + * Stop asking for what we were asking for. + */ + if (go->neg_eap) + try_.neg_eap = 0; + else +#endif /* EAP_SUPPORT */ + +#if CHAP_SUPPORT + if (go->neg_chap) + try_.neg_chap = 0; + else +#endif /* CHAP_SUPPORT */ + +#if PAP_SUPPORT + if(1) + try_.neg_upap = 0; + else +#endif /* PAP_SUPPORT */ + {} + + p += cilen - CILEN_SHORT; + } + } + +#if LQR_SUPPORT + /* + * If they can't cope with our link quality protocol, we'll have + * to stop asking for LQR. We haven't got any other protocol. + * If they Nak the reporting period, take their value XXX ? + */ + NAKCILQR(CI_QUALITY, neg_lqr, + if (cishort != PPP_LQR) + try_.neg_lqr = 0; + else + try_.lqr_period = cilong; + ); +#endif /* LQR_SUPPORT */ + + /* + * Only implementing CBCP...not the rest of the callback options + */ + NAKCICHAR(CI_CALLBACK, neg_cbcp, + try_.neg_cbcp = 0; + (void)cichar; /* if CHAP support is not compiled, cichar is set but not used, which makes some compilers complaining */ + ); + + /* + * Check for a looped-back line. + */ + NAKCILONG(CI_MAGICNUMBER, neg_magicnumber, + try_.magicnumber = magic(); + looped_back = 1; + ); + + /* + * Peer shouldn't send Nak for protocol compression or + * address/control compression requests; they should send + * a Reject instead. If they send a Nak, treat it as a Reject. + */ + NAKCIVOID(CI_PCOMPRESSION, neg_pcompression); + NAKCIVOID(CI_ACCOMPRESSION, neg_accompression); + +#ifdef HAVE_MULTILINK + /* + * Nak for MRRU option - accept their value if it is smaller + * than the one we want. + */ + if (go->neg_mrru) { + NAKCISHORT(CI_MRRU, neg_mrru, + if (treat_as_reject) + try_.neg_mrru = 0; + else if (cishort <= wo->mrru) + try_.mrru = cishort; + ); + } +#else /* HAVE_MULTILINK */ + LWIP_UNUSED_ARG(treat_as_reject); +#endif /* HAVE_MULTILINK */ + + /* + * Nak for short sequence numbers shouldn't be sent, treat it + * like a reject. + */ + NAKCIVOID(CI_SSNHF, neg_ssnhf); + + /* + * Nak of the endpoint discriminator option is not permitted, + * treat it like a reject. + */ + NAKCIENDP(CI_EPDISC, neg_endpoint); + + /* + * There may be remaining CIs, if the peer is requesting negotiation + * on an option that we didn't include in our request packet. + * If we see an option that we requested, or one we've already seen + * in this packet, then this packet is bad. + * If we wanted to respond by starting to negotiate on the requested + * option(s), we could, but we don't, because except for the + * authentication type and quality protocol, if we are not negotiating + * an option, it is because we were told not to. + * For the authentication type, the Nak from the peer means + * `let me authenticate myself with you' which is a bit pointless. + * For the quality protocol, the Nak means `ask me to send you quality + * reports', but if we didn't ask for them, we don't want them. + * An option we don't recognize represents the peer asking to + * negotiate some option we don't support, so ignore it. + */ + while (len >= CILEN_VOID) { + GETCHAR(citype, p); + GETCHAR(cilen, p); + if (cilen < CILEN_VOID || (len -= cilen) < 0) + goto bad; + next = p + cilen - 2; + + switch (citype) { + case CI_MRU: + if ((go->neg_mru && go->mru != DEFMRU) + || no.neg_mru || cilen != CILEN_SHORT) + goto bad; + GETSHORT(cishort, p); + if (cishort < DEFMRU) { + try_.neg_mru = 1; + try_.mru = cishort; + } + break; + case CI_ASYNCMAP: + if ((go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) + || no.neg_asyncmap || cilen != CILEN_LONG) + goto bad; + break; + case CI_AUTHTYPE: + if (0 +#if CHAP_SUPPORT + || go->neg_chap || no.neg_chap +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + || go->neg_upap || no.neg_upap +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + || go->neg_eap || no.neg_eap +#endif /* EAP_SUPPORT */ + ) + goto bad; + break; + case CI_MAGICNUMBER: + if (go->neg_magicnumber || no.neg_magicnumber || + cilen != CILEN_LONG) + goto bad; + break; + case CI_PCOMPRESSION: + if (go->neg_pcompression || no.neg_pcompression + || cilen != CILEN_VOID) + goto bad; + break; + case CI_ACCOMPRESSION: + if (go->neg_accompression || no.neg_accompression + || cilen != CILEN_VOID) + goto bad; + break; +#if LQR_SUPPORT + case CI_QUALITY: + if (go->neg_lqr || no.neg_lqr || cilen != CILEN_LQR) + goto bad; + break; +#endif /* LQR_SUPPORT */ +#ifdef HAVE_MULTILINK + case CI_MRRU: + if (go->neg_mrru || no.neg_mrru || cilen != CILEN_SHORT) + goto bad; + break; +#endif /* HAVE_MULTILINK */ + case CI_SSNHF: + if (go->neg_ssnhf || no.neg_ssnhf || cilen != CILEN_VOID) + goto bad; + try_.neg_ssnhf = 1; + break; + case CI_EPDISC: + if (go->neg_endpoint || no.neg_endpoint || cilen < CILEN_CHAR) + goto bad; + break; + default: + break; + } + p = next; + } + + /* + * OK, the Nak is good. Now we can update state. + * If there are any options left we ignore them. + */ + if (f->state != PPP_FSM_OPENED) { + if (looped_back) { + if (++try_.numloops >= pcb->settings.lcp_loopbackfail) { + int errcode = PPPERR_LOOPBACK; + ppp_notice("Serial line is looped back."); + ppp_ioctl(pcb, PPPCTLS_ERRCODE, &errcode); + lcp_close(f->pcb, "Loopback detected"); + } + } else + try_.numloops = 0; + *go = try_; + } + + return 1; + +bad: + LCPDEBUG(("lcp_nakci: received bad Nak!")); + return 0; +} + + +/* + * lcp_rejci - Peer has Rejected some of our CIs. + * This should not modify any state if the Reject is bad + * or if LCP is in the OPENED state. + * + * Returns: + * 0 - Reject was bad. + * 1 - Reject was good. + */ +static int lcp_rejci(fsm *f, u_char *p, int len) { + ppp_pcb *pcb = f->pcb; + lcp_options *go = &pcb->lcp_gotoptions; + u_char cichar; + u_short cishort; + u32_t cilong; + lcp_options try_; /* options to request next time */ + + try_ = *go; + + /* + * Any Rejected CIs must be in exactly the same order that we sent. + * Check packet length and CI length at each step. + * If we find any deviations, then this packet is bad. + */ +#define REJCIVOID(opt, neg) \ + if (go->neg && \ + len >= CILEN_VOID && \ + p[1] == CILEN_VOID && \ + p[0] == opt) { \ + len -= CILEN_VOID; \ + INCPTR(CILEN_VOID, p); \ + try_.neg = 0; \ + } +#define REJCISHORT(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_SHORT && \ + p[1] == CILEN_SHORT && \ + p[0] == opt) { \ + len -= CILEN_SHORT; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + /* Check rejected value. */ \ + if (cishort != val) \ + goto bad; \ + try_.neg = 0; \ + } + +#if CHAP_SUPPORT && EAP_SUPPORT && PAP_SUPPORT +#define REJCICHAP(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_CHAP && \ + p[1] == CILEN_CHAP && \ + p[0] == opt) { \ + len -= CILEN_CHAP; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETCHAR(cichar, p); \ + /* Check rejected value. */ \ + if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \ + goto bad; \ + try_.neg = 0; \ + try_.neg_eap = try_.neg_upap = 0; \ + } +#endif /* CHAP_SUPPORT && EAP_SUPPORT && PAP_SUPPORT */ + +#if CHAP_SUPPORT && !EAP_SUPPORT && PAP_SUPPORT +#define REJCICHAP(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_CHAP && \ + p[1] == CILEN_CHAP && \ + p[0] == opt) { \ + len -= CILEN_CHAP; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETCHAR(cichar, p); \ + /* Check rejected value. */ \ + if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \ + goto bad; \ + try_.neg = 0; \ + try_.neg_upap = 0; \ + } +#endif /* CHAP_SUPPORT && !EAP_SUPPORT && PAP_SUPPORT */ + +#if CHAP_SUPPORT && EAP_SUPPORT && !PAP_SUPPORT +#define REJCICHAP(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_CHAP && \ + p[1] == CILEN_CHAP && \ + p[0] == opt) { \ + len -= CILEN_CHAP; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETCHAR(cichar, p); \ + /* Check rejected value. */ \ + if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \ + goto bad; \ + try_.neg = 0; \ + try_.neg_eap = 0; \ + } +#endif /* CHAP_SUPPORT && EAP_SUPPORT && !PAP_SUPPORT */ + +#if CHAP_SUPPORT && !EAP_SUPPORT && !PAP_SUPPORT +#define REJCICHAP(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_CHAP && \ + p[1] == CILEN_CHAP && \ + p[0] == opt) { \ + len -= CILEN_CHAP; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETCHAR(cichar, p); \ + /* Check rejected value. */ \ + if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \ + goto bad; \ + try_.neg = 0; \ + } +#endif /* CHAP_SUPPORT && !EAP_SUPPORT && !PAP_SUPPORT */ + +#define REJCILONG(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_LONG && \ + p[1] == CILEN_LONG && \ + p[0] == opt) { \ + len -= CILEN_LONG; \ + INCPTR(2, p); \ + GETLONG(cilong, p); \ + /* Check rejected value. */ \ + if (cilong != val) \ + goto bad; \ + try_.neg = 0; \ + } +#if LQR_SUPPORT +#define REJCILQR(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_LQR && \ + p[1] == CILEN_LQR && \ + p[0] == opt) { \ + len -= CILEN_LQR; \ + INCPTR(2, p); \ + GETSHORT(cishort, p); \ + GETLONG(cilong, p); \ + /* Check rejected value. */ \ + if (cishort != PPP_LQR || cilong != val) \ + goto bad; \ + try_.neg = 0; \ + } +#endif /* LQR_SUPPORT */ +#define REJCICBCP(opt, neg, val) \ + if (go->neg && \ + len >= CILEN_CBCP && \ + p[1] == CILEN_CBCP && \ + p[0] == opt) { \ + len -= CILEN_CBCP; \ + INCPTR(2, p); \ + GETCHAR(cichar, p); \ + /* Check rejected value. */ \ + if (cichar != val) \ + goto bad; \ + try_.neg = 0; \ + } +#define REJCIENDP(opt, neg, class, val, vlen) \ + if (go->neg && \ + len >= CILEN_CHAR + vlen && \ + p[0] == opt && \ + p[1] == CILEN_CHAR + vlen) { \ + int i; \ + len -= CILEN_CHAR + vlen; \ + INCPTR(2, p); \ + GETCHAR(cichar, p); \ + if (cichar != class) \ + goto bad; \ + for (i = 0; i < vlen; ++i) { \ + GETCHAR(cichar, p); \ + if (cichar != val[i]) \ + goto bad; \ + } \ + try_.neg = 0; \ + } + + REJCISHORT(CI_MRU, neg_mru, go->mru); + REJCILONG(CI_ASYNCMAP, neg_asyncmap, go->asyncmap); +#if EAP_SUPPORT + REJCISHORT(CI_AUTHTYPE, neg_eap, PPP_EAP); + if (!go->neg_eap) { +#endif /* EAP_SUPPORT */ +#if CHAP_SUPPORT + REJCICHAP(CI_AUTHTYPE, neg_chap, go->chap_mdtype); + if (!go->neg_chap) { +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + REJCISHORT(CI_AUTHTYPE, neg_upap, PPP_PAP); +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + } +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + } +#endif /* EAP_SUPPORT */ +#if LQR_SUPPORT + REJCILQR(CI_QUALITY, neg_lqr, go->lqr_period); +#endif /* LQR_SUPPORT */ + REJCICBCP(CI_CALLBACK, neg_cbcp, CBCP_OPT); + REJCILONG(CI_MAGICNUMBER, neg_magicnumber, go->magicnumber); + REJCIVOID(CI_PCOMPRESSION, neg_pcompression); + REJCIVOID(CI_ACCOMPRESSION, neg_accompression); +#ifdef HAVE_MULTILINK + REJCISHORT(CI_MRRU, neg_mrru, go->mrru); +#endif /* HAVE_MULTILINK */ + REJCIVOID(CI_SSNHF, neg_ssnhf); + REJCIENDP(CI_EPDISC, neg_endpoint, go->endpoint.class_, + go->endpoint.value, go->endpoint.length); + + /* + * If there are any remaining CIs, then this packet is bad. + */ + if (len != 0) + goto bad; + /* + * Now we can update state. + */ + if (f->state != PPP_FSM_OPENED) + *go = try_; + return 1; + +bad: + LCPDEBUG(("lcp_rejci: received bad Reject!")); + return 0; +} + + +/* + * lcp_reqci - Check the peer's requested CIs and send appropriate response. + * + * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified + * appropriately. If reject_if_disagree is non-zero, doesn't return + * CONFNAK; returns CONFREJ if it can't return CONFACK. + * + * inp = Requested CIs + * lenp = Length of requested CIs + */ +static int lcp_reqci(fsm *f, u_char *inp, int *lenp, int reject_if_disagree) { + ppp_pcb *pcb = f->pcb; + lcp_options *go = &pcb->lcp_gotoptions; + lcp_options *ho = &pcb->lcp_hisoptions; + lcp_options *ao = &pcb->lcp_allowoptions; + u_char *cip, *next; /* Pointer to current and next CIs */ + int cilen, citype, cichar; /* Parsed len, type, char value */ + u_short cishort; /* Parsed short value */ + u32_t cilong; /* Parse long value */ + int rc = CONFACK; /* Final packet return code */ + int orc; /* Individual option return code */ + u_char *p; /* Pointer to next char to parse */ + u_char *rejp; /* Pointer to next char in reject frame */ + struct pbuf *nakp; /* Nak buffer */ + u_char *nakoutp; /* Pointer to next char in Nak frame */ + int l = *lenp; /* Length left */ + + /* + * Reset all his options. + */ + BZERO(ho, sizeof(*ho)); + + /* + * Process all his options. + */ + next = inp; + nakp = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_CTRL_PBUF_MAX_SIZE), PPP_CTRL_PBUF_TYPE); + if(NULL == nakp) + return 0; + if(nakp->tot_len != nakp->len) { + pbuf_free(nakp); + return 0; + } + + nakoutp = (u_char*)nakp->payload; + rejp = inp; + while (l) { + orc = CONFACK; /* Assume success */ + cip = p = next; /* Remember begining of CI */ + if (l < 2 || /* Not enough data for CI header or */ + p[1] < 2 || /* CI length too small or */ + p[1] > l) { /* CI length too big? */ + LCPDEBUG(("lcp_reqci: bad CI length!")); + orc = CONFREJ; /* Reject bad CI */ + cilen = l; /* Reject till end of packet */ + l = 0; /* Don't loop again */ + citype = 0; + goto endswitch; + } + GETCHAR(citype, p); /* Parse CI type */ + GETCHAR(cilen, p); /* Parse CI length */ + l -= cilen; /* Adjust remaining length */ + next += cilen; /* Step to next CI */ + + switch (citype) { /* Check CI type */ + case CI_MRU: + if (!ao->neg_mru || /* Allow option? */ + cilen != CILEN_SHORT) { /* Check CI length */ + orc = CONFREJ; /* Reject CI */ + break; + } + GETSHORT(cishort, p); /* Parse MRU */ + + /* + * He must be able to receive at least our minimum. + * No need to check a maximum. If he sends a large number, + * we'll just ignore it. + */ + if (cishort < MINMRU) { + orc = CONFNAK; /* Nak CI */ + PUTCHAR(CI_MRU, nakoutp); + PUTCHAR(CILEN_SHORT, nakoutp); + PUTSHORT(MINMRU, nakoutp); /* Give him a hint */ + break; + } + ho->neg_mru = 1; /* Remember he sent MRU */ + ho->mru = cishort; /* And remember value */ + break; + + case CI_ASYNCMAP: + if (!ao->neg_asyncmap || + cilen != CILEN_LONG) { + orc = CONFREJ; + break; + } + GETLONG(cilong, p); + + /* + * Asyncmap must have set at least the bits + * which are set in lcp_allowoptions[unit].asyncmap. + */ + if ((ao->asyncmap & ~cilong) != 0) { + orc = CONFNAK; + PUTCHAR(CI_ASYNCMAP, nakoutp); + PUTCHAR(CILEN_LONG, nakoutp); + PUTLONG(ao->asyncmap | cilong, nakoutp); + break; + } + ho->neg_asyncmap = 1; + ho->asyncmap = cilong; + break; + + case CI_AUTHTYPE: + if (cilen < CILEN_SHORT || + !(0 +#if PAP_SUPPORT + || ao->neg_upap +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + || ao->neg_chap +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + || ao->neg_eap +#endif /* EAP_SUPPORT */ + )) { + /* + * Reject the option if we're not willing to authenticate. + */ + ppp_dbglog("No auth is possible"); + orc = CONFREJ; + break; + } + GETSHORT(cishort, p); + + /* + * Authtype must be PAP, CHAP, or EAP. + * + * Note: if more than one of ao->neg_upap, ao->neg_chap, and + * ao->neg_eap are set, and the peer sends a Configure-Request + * with two or more authenticate-protocol requests, then we will + * reject the second request. + * Whether we end up doing CHAP, UPAP, or EAP depends then on + * the ordering of the CIs in the peer's Configure-Request. + */ + +#if PAP_SUPPORT + if (cishort == PPP_PAP) { + /* we've already accepted CHAP or EAP */ + if (0 +#if CHAP_SUPPORT + || ho->neg_chap +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + || ho->neg_eap +#endif /* EAP_SUPPORT */ + || cilen != CILEN_SHORT) { + LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE PAP, rejecting...")); + orc = CONFREJ; + break; + } + if (!ao->neg_upap) { /* we don't want to do PAP */ + orc = CONFNAK; /* NAK it and suggest CHAP or EAP */ + PUTCHAR(CI_AUTHTYPE, nakoutp); +#if EAP_SUPPORT + if (ao->neg_eap) { + PUTCHAR(CILEN_SHORT, nakoutp); + PUTSHORT(PPP_EAP, nakoutp); + } else { +#endif /* EAP_SUPPORT */ +#if CHAP_SUPPORT + PUTCHAR(CILEN_CHAP, nakoutp); + PUTSHORT(PPP_CHAP, nakoutp); + PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakoutp); +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + } +#endif /* EAP_SUPPORT */ + break; + } + ho->neg_upap = 1; + break; + } +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + if (cishort == PPP_CHAP) { + /* we've already accepted PAP or EAP */ + if ( +#if PAP_SUPPORT + ho->neg_upap || +#endif /* PAP_SUPPORT */ +#if EAP_SUPPORT + ho->neg_eap || +#endif /* EAP_SUPPORT */ + cilen != CILEN_CHAP) { + LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE CHAP, rejecting...")); + orc = CONFREJ; + break; + } + if (!ao->neg_chap) { /* we don't want to do CHAP */ + orc = CONFNAK; /* NAK it and suggest EAP or PAP */ + PUTCHAR(CI_AUTHTYPE, nakoutp); + PUTCHAR(CILEN_SHORT, nakoutp); +#if EAP_SUPPORT + if (ao->neg_eap) { + PUTSHORT(PPP_EAP, nakoutp); + } else +#endif /* EAP_SUPPORT */ +#if PAP_SUPPORT + if(1) { + PUTSHORT(PPP_PAP, nakoutp); + } + else +#endif /* PAP_SUPPORT */ + {} + break; + } + GETCHAR(cichar, p); /* get digest type */ + if (!(CHAP_CANDIGEST(ao->chap_mdtype, cichar))) { + /* + * We can't/won't do the requested type, + * suggest something else. + */ + orc = CONFNAK; + PUTCHAR(CI_AUTHTYPE, nakoutp); + PUTCHAR(CILEN_CHAP, nakoutp); + PUTSHORT(PPP_CHAP, nakoutp); + PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakoutp); + break; + } + ho->chap_mdtype = CHAP_MDTYPE_D(cichar); /* save md type */ + ho->neg_chap = 1; + break; + } +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + if (cishort == PPP_EAP) { + /* we've already accepted CHAP or PAP */ + if ( +#if CHAP_SUPPORT + ho->neg_chap || +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + ho->neg_upap || +#endif /* PAP_SUPPORT */ + cilen != CILEN_SHORT) { + LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE EAP, rejecting...")); + orc = CONFREJ; + break; + } + if (!ao->neg_eap) { /* we don't want to do EAP */ + orc = CONFNAK; /* NAK it and suggest CHAP or PAP */ + PUTCHAR(CI_AUTHTYPE, nakoutp); +#if CHAP_SUPPORT + if (ao->neg_chap) { + PUTCHAR(CILEN_CHAP, nakoutp); + PUTSHORT(PPP_CHAP, nakoutp); + PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakoutp); + } else +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + if(1) { + PUTCHAR(CILEN_SHORT, nakoutp); + PUTSHORT(PPP_PAP, nakoutp); + } else +#endif /* PAP_SUPPORT */ + {} + break; + } + ho->neg_eap = 1; + break; + } +#endif /* EAP_SUPPORT */ + + /* + * We don't recognize the protocol they're asking for. + * Nak it with something we're willing to do. + * (At this point we know ao->neg_upap || ao->neg_chap || + * ao->neg_eap.) + */ + orc = CONFNAK; + PUTCHAR(CI_AUTHTYPE, nakoutp); + +#if EAP_SUPPORT + if (ao->neg_eap) { + PUTCHAR(CILEN_SHORT, nakoutp); + PUTSHORT(PPP_EAP, nakoutp); + } else +#endif /* EAP_SUPPORT */ +#if CHAP_SUPPORT + if (ao->neg_chap) { + PUTCHAR(CILEN_CHAP, nakoutp); + PUTSHORT(PPP_CHAP, nakoutp); + PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakoutp); + } else +#endif /* CHAP_SUPPORT */ +#if PAP_SUPPORT + if(1) { + PUTCHAR(CILEN_SHORT, nakoutp); + PUTSHORT(PPP_PAP, nakoutp); + } else +#endif /* PAP_SUPPORT */ + {} + break; + +#if LQR_SUPPORT + case CI_QUALITY: + if (!ao->neg_lqr || + cilen != CILEN_LQR) { + orc = CONFREJ; + break; + } + + GETSHORT(cishort, p); + GETLONG(cilong, p); + + /* + * Check the protocol and the reporting period. + * XXX When should we Nak this, and what with? + */ + if (cishort != PPP_LQR) { + orc = CONFNAK; + PUTCHAR(CI_QUALITY, nakoutp); + PUTCHAR(CILEN_LQR, nakoutp); + PUTSHORT(PPP_LQR, nakoutp); + PUTLONG(ao->lqr_period, nakoutp); + break; + } + break; +#endif /* LQR_SUPPORT */ + + case CI_MAGICNUMBER: + if (!(ao->neg_magicnumber || go->neg_magicnumber) || + cilen != CILEN_LONG) { + orc = CONFREJ; + break; + } + GETLONG(cilong, p); + + /* + * He must have a different magic number. + */ + if (go->neg_magicnumber && + cilong == go->magicnumber) { + cilong = magic(); /* Don't put magic() inside macro! */ + orc = CONFNAK; + PUTCHAR(CI_MAGICNUMBER, nakoutp); + PUTCHAR(CILEN_LONG, nakoutp); + PUTLONG(cilong, nakoutp); + break; + } + ho->neg_magicnumber = 1; + ho->magicnumber = cilong; + break; + + + case CI_PCOMPRESSION: + if (!ao->neg_pcompression || + cilen != CILEN_VOID) { + orc = CONFREJ; + break; + } + ho->neg_pcompression = 1; + break; + + case CI_ACCOMPRESSION: + if (!ao->neg_accompression || + cilen != CILEN_VOID) { + orc = CONFREJ; + break; + } + ho->neg_accompression = 1; + break; + +#ifdef HAVE_MULTILINK + case CI_MRRU: + if (!ao->neg_mrru + || !multilink + || cilen != CILEN_SHORT) { + orc = CONFREJ; + break; + } + + GETSHORT(cishort, p); + /* possibly should insist on a minimum/maximum MRRU here */ + ho->neg_mrru = 1; + ho->mrru = cishort; + break; +#endif /* HAVE_MULTILINK */ + + case CI_SSNHF: + if (!ao->neg_ssnhf +#ifdef HAVE_MULTILINK + || !multilink +#endif /* HAVE_MULTILINK */ + || cilen != CILEN_VOID) { + orc = CONFREJ; + break; + } + ho->neg_ssnhf = 1; + break; + + case CI_EPDISC: + if (!ao->neg_endpoint || + cilen < CILEN_CHAR || + cilen > CILEN_CHAR + MAX_ENDP_LEN) { + orc = CONFREJ; + break; + } + GETCHAR(cichar, p); + cilen -= CILEN_CHAR; + ho->neg_endpoint = 1; + ho->endpoint.class_ = cichar; + ho->endpoint.length = cilen; + MEMCPY(ho->endpoint.value, p, cilen); + INCPTR(cilen, p); + break; + + default: + LCPDEBUG(("lcp_reqci: rcvd unknown option %d", citype)); + orc = CONFREJ; + break; + } + +endswitch: + if (orc == CONFACK && /* Good CI */ + rc != CONFACK) /* but prior CI wasnt? */ + continue; /* Don't send this one */ + + if (orc == CONFNAK) { /* Nak this CI? */ + if (reject_if_disagree /* Getting fed up with sending NAKs? */ + && citype != CI_MAGICNUMBER) { + orc = CONFREJ; /* Get tough if so */ + } else { + if (rc == CONFREJ) /* Rejecting prior CI? */ + continue; /* Don't send this one */ + rc = CONFNAK; + } + } + if (orc == CONFREJ) { /* Reject this CI */ + rc = CONFREJ; + if (cip != rejp) /* Need to move rejected CI? */ + MEMCPY(rejp, cip, cilen); /* Move it */ + INCPTR(cilen, rejp); /* Update output pointer */ + } + } + + /* + * If we wanted to send additional NAKs (for unsent CIs), the + * code would go here. The extra NAKs would go at *nakoutp. + * At present there are no cases where we want to ask the + * peer to negotiate an option. + */ + + switch (rc) { + case CONFACK: + *lenp = next - inp; + break; + case CONFNAK: + /* + * Copy the Nak'd options from the nak buffer to the caller's buffer. + */ + *lenp = nakoutp - (u_char*)nakp->payload; + MEMCPY(inp, nakp->payload, *lenp); + break; + case CONFREJ: + *lenp = rejp - inp; + break; + default: + break; + } + + pbuf_free(nakp); + LCPDEBUG(("lcp_reqci: returning CONF%s.", CODENAME(rc))); + return (rc); /* Return final code */ +} + + +/* + * lcp_up - LCP has come UP. + */ +static void lcp_up(fsm *f) { + ppp_pcb *pcb = f->pcb; + lcp_options *wo = &pcb->lcp_wantoptions; + lcp_options *ho = &pcb->lcp_hisoptions; + lcp_options *go = &pcb->lcp_gotoptions; + lcp_options *ao = &pcb->lcp_allowoptions; + int mtu, mru; + + if (!go->neg_magicnumber) + go->magicnumber = 0; + if (!ho->neg_magicnumber) + ho->magicnumber = 0; + + /* + * Set our MTU to the smaller of the MTU we wanted and + * the MRU our peer wanted. If we negotiated an MRU, + * set our MRU to the larger of value we wanted and + * the value we got in the negotiation. + * Note on the MTU: the link MTU can be the MRU the peer wanted, + * the interface MTU is set to the lowest of that, the + * MTU we want to use, and our link MRU. + */ + mtu = ho->neg_mru? ho->mru: PPP_MRU; + mru = go->neg_mru? LWIP_MAX(wo->mru, go->mru): PPP_MRU; +#ifdef HAVE_MULTILINK + if (!(multilink && go->neg_mrru && ho->neg_mrru)) +#endif /* HAVE_MULTILINK */ + netif_set_mtu(pcb, LWIP_MIN(LWIP_MIN(mtu, mru), ao->mru)); + ppp_send_config(pcb, mtu, + (ho->neg_asyncmap? ho->asyncmap: 0xffffffff), + ho->neg_pcompression, ho->neg_accompression); + ppp_recv_config(pcb, mru, + (pcb->settings.lax_recv? 0: go->neg_asyncmap? go->asyncmap: 0xffffffff), + go->neg_pcompression, go->neg_accompression); + + if (ho->neg_mru) + pcb->peer_mru = ho->mru; + + lcp_echo_lowerup(f->pcb); /* Enable echo messages */ + + link_established(pcb); +} + + +/* + * lcp_down - LCP has gone DOWN. + * + * Alert other protocols. + */ +static void lcp_down(fsm *f) { + ppp_pcb *pcb = f->pcb; + lcp_options *go = &pcb->lcp_gotoptions; + + lcp_echo_lowerdown(f->pcb); + + link_down(pcb); + + ppp_send_config(pcb, PPP_MRU, 0xffffffff, 0, 0); + ppp_recv_config(pcb, PPP_MRU, + (go->neg_asyncmap? go->asyncmap: 0xffffffff), + go->neg_pcompression, go->neg_accompression); + pcb->peer_mru = PPP_MRU; +} + + +/* + * lcp_starting - LCP needs the lower layer up. + */ +static void lcp_starting(fsm *f) { + ppp_pcb *pcb = f->pcb; + link_required(pcb); +} + + +/* + * lcp_finished - LCP has finished with the lower layer. + */ +static void lcp_finished(fsm *f) { + ppp_pcb *pcb = f->pcb; + link_terminated(pcb); +} + + +#if PRINTPKT_SUPPORT +/* + * lcp_printpkt - print the contents of an LCP packet. + */ +static const char *lcp_codenames[] = { + "ConfReq", "ConfAck", "ConfNak", "ConfRej", + "TermReq", "TermAck", "CodeRej", "ProtRej", + "EchoReq", "EchoRep", "DiscReq", "Ident", + "TimeRem" +}; + +static int lcp_printpkt(u_char *p, int plen, + void (*printer) (void *, const char *, ...), void *arg) { + int code, id, len, olen, i; + u_char *pstart, *optend; + u_short cishort; + u32_t cilong; + + if (plen < HEADERLEN) + return 0; + pstart = p; + GETCHAR(code, p); + GETCHAR(id, p); + GETSHORT(len, p); + if (len < HEADERLEN || len > plen) + return 0; + + if (code >= 1 && code <= (int)sizeof(lcp_codenames) / (int)sizeof(char *)) + printer(arg, " %s", lcp_codenames[code-1]); + else + printer(arg, " code=0x%x", code); + printer(arg, " id=0x%x", id); + len -= HEADERLEN; + switch (code) { + case CONFREQ: + case CONFACK: + case CONFNAK: + case CONFREJ: + /* print option list */ + while (len >= 2) { + GETCHAR(code, p); + GETCHAR(olen, p); + p -= 2; + if (olen < 2 || olen > len) { + break; + } + printer(arg, " <"); + len -= olen; + optend = p + olen; + switch (code) { + case CI_MRU: + if (olen == CILEN_SHORT) { + p += 2; + GETSHORT(cishort, p); + printer(arg, "mru %d", cishort); + } + break; + case CI_ASYNCMAP: + if (olen == CILEN_LONG) { + p += 2; + GETLONG(cilong, p); + printer(arg, "asyncmap 0x%x", cilong); + } + break; + case CI_AUTHTYPE: + if (olen >= CILEN_SHORT) { + p += 2; + printer(arg, "auth "); + GETSHORT(cishort, p); + switch (cishort) { +#if PAP_SUPPORT + case PPP_PAP: + printer(arg, "pap"); + break; +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + case PPP_CHAP: + printer(arg, "chap"); + if (p < optend) { + switch (*p) { + case CHAP_MD5: + printer(arg, " MD5"); + ++p; + break; +#if MSCHAP_SUPPORT + case CHAP_MICROSOFT: + printer(arg, " MS"); + ++p; + break; + + case CHAP_MICROSOFT_V2: + printer(arg, " MS-v2"); + ++p; + break; +#endif /* MSCHAP_SUPPORT */ + default: + break; + } + } + break; +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + case PPP_EAP: + printer(arg, "eap"); + break; +#endif /* EAP_SUPPORT */ + default: + printer(arg, "0x%x", cishort); + } + } + break; +#if LQR_SUPPORT + case CI_QUALITY: + if (olen >= CILEN_SHORT) { + p += 2; + printer(arg, "quality "); + GETSHORT(cishort, p); + switch (cishort) { + case PPP_LQR: + printer(arg, "lqr"); + break; + default: + printer(arg, "0x%x", cishort); + } + } + break; +#endif /* LQR_SUPPORT */ + case CI_CALLBACK: + if (olen >= CILEN_CHAR) { + p += 2; + printer(arg, "callback "); + GETCHAR(cishort, p); + switch (cishort) { + case CBCP_OPT: + printer(arg, "CBCP"); + break; + default: + printer(arg, "0x%x", cishort); + } + } + break; + case CI_MAGICNUMBER: + if (olen == CILEN_LONG) { + p += 2; + GETLONG(cilong, p); + printer(arg, "magic 0x%x", cilong); + } + break; + case CI_PCOMPRESSION: + if (olen == CILEN_VOID) { + p += 2; + printer(arg, "pcomp"); + } + break; + case CI_ACCOMPRESSION: + if (olen == CILEN_VOID) { + p += 2; + printer(arg, "accomp"); + } + break; + case CI_MRRU: + if (olen == CILEN_SHORT) { + p += 2; + GETSHORT(cishort, p); + printer(arg, "mrru %d", cishort); + } + break; + case CI_SSNHF: + if (olen == CILEN_VOID) { + p += 2; + printer(arg, "ssnhf"); + } + break; + case CI_EPDISC: +#ifdef HAVE_MULTILINK + if (olen >= CILEN_CHAR) { + struct epdisc epd; + p += 2; + GETCHAR(epd.class, p); + epd.length = olen - CILEN_CHAR; + if (epd.length > MAX_ENDP_LEN) + epd.length = MAX_ENDP_LEN; + if (epd.length > 0) { + MEMCPY(epd.value, p, epd.length); + p += epd.length; + } + printer(arg, "endpoint [%s]", epdisc_to_str(&epd)); + } +#else + printer(arg, "endpoint"); +#endif + break; + default: + break; + } + while (p < optend) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + printer(arg, ">"); + } + break; + + case TERMACK: + case TERMREQ: + if (len > 0 && *p >= ' ' && *p < 0x7f) { + printer(arg, " "); + ppp_print_string((char *)p, len, printer, arg); + p += len; + len = 0; + } + break; + + case ECHOREQ: + case ECHOREP: + case DISCREQ: + if (len >= 4) { + GETLONG(cilong, p); + printer(arg, " magic=0x%x", cilong); + len -= 4; + } + break; + + case IDENTIF: + case TIMEREM: + if (len >= 4) { + GETLONG(cilong, p); + printer(arg, " magic=0x%x", cilong); + len -= 4; + } + if (code == TIMEREM) { + if (len < 4) + break; + GETLONG(cilong, p); + printer(arg, " seconds=%u", cilong); + len -= 4; + } + if (len > 0) { + printer(arg, " "); + ppp_print_string((char *)p, len, printer, arg); + p += len; + len = 0; + } + break; + default: + break; + } + + /* print the rest of the bytes in the packet */ + for (i = 0; i < len && i < 32; ++i) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + if (i < len) { + printer(arg, " ..."); + p += len - i; + } + + return p - pstart; +} +#endif /* PRINTPKT_SUPPORT */ + +/* + * Time to shut down the link because there is nothing out there. + */ + +static void LcpLinkFailure(fsm *f) { + ppp_pcb *pcb = f->pcb; + if (f->state == PPP_FSM_OPENED) { + int errcode = PPPERR_PEERDEAD; + ppp_info("No response to %d echo-requests", pcb->lcp_echos_pending); + ppp_notice("Serial link appears to be disconnected."); + ppp_ioctl(pcb, PPPCTLS_ERRCODE, &errcode); + lcp_close(pcb, "Peer not responding"); + } +} + +/* + * Timer expired for the LCP echo requests from this process. + */ + +static void LcpEchoCheck(fsm *f) { + ppp_pcb *pcb = f->pcb; + + LcpSendEchoRequest (f); + if (f->state != PPP_FSM_OPENED) + return; + + /* + * Start the timer for the next interval. + */ + if (pcb->lcp_echo_timer_running) + ppp_warn("assertion lcp_echo_timer_running==0 failed"); + TIMEOUT (LcpEchoTimeout, f, pcb->settings.lcp_echo_interval); + pcb->lcp_echo_timer_running = 1; +} + +/* + * LcpEchoTimeout - Timer expired on the LCP echo + */ + +static void LcpEchoTimeout(void *arg) { + fsm *f = (fsm*)arg; + ppp_pcb *pcb = f->pcb; + if (pcb->lcp_echo_timer_running != 0) { + pcb->lcp_echo_timer_running = 0; + LcpEchoCheck ((fsm *) arg); + } +} + +/* + * LcpEchoReply - LCP has received a reply to the echo + */ + +static void lcp_received_echo_reply(fsm *f, int id, u_char *inp, int len) { + ppp_pcb *pcb = f->pcb; + lcp_options *go = &pcb->lcp_gotoptions; + u32_t magic; + LWIP_UNUSED_ARG(id); + + /* Check the magic number - don't count replies from ourselves. */ + if (len < 4) { + ppp_dbglog("lcp: received short Echo-Reply, length %d", len); + return; + } + GETLONG(magic, inp); + if (go->neg_magicnumber + && magic == go->magicnumber) { + ppp_warn("appear to have received our own echo-reply!"); + return; + } + + /* Reset the number of outstanding echo frames */ + pcb->lcp_echos_pending = 0; +} + +/* + * LcpSendEchoRequest - Send an echo request frame to the peer + */ + +static void LcpSendEchoRequest(fsm *f) { + ppp_pcb *pcb = f->pcb; + lcp_options *go = &pcb->lcp_gotoptions; + u32_t lcp_magic; + u_char pkt[4], *pktp; + + /* + * Detect the failure of the peer at this point. + */ + if (pcb->settings.lcp_echo_fails != 0) { + if (pcb->lcp_echos_pending >= pcb->settings.lcp_echo_fails) { + LcpLinkFailure(f); + pcb->lcp_echos_pending = 0; + } + } + +#if PPP_LCP_ADAPTIVE + /* + * If adaptive echos have been enabled, only send the echo request if + * no traffic was received since the last one. + */ + if (pcb->settings.lcp_echo_adaptive) { + static unsigned int last_pkts_in = 0; + +#if PPP_STATS_SUPPORT + update_link_stats(f->unit); + link_stats_valid = 0; +#endif /* PPP_STATS_SUPPORT */ + + if (link_stats.pkts_in != last_pkts_in) { + last_pkts_in = link_stats.pkts_in; + return; + } + } +#endif + + /* + * Make and send the echo request frame. + */ + if (f->state == PPP_FSM_OPENED) { + lcp_magic = go->magicnumber; + pktp = pkt; + PUTLONG(lcp_magic, pktp); + fsm_sdata(f, ECHOREQ, pcb->lcp_echo_number++, pkt, pktp - pkt); + ++pcb->lcp_echos_pending; + } +} + +/* + * lcp_echo_lowerup - Start the timer for the LCP frame + */ + +static void lcp_echo_lowerup(ppp_pcb *pcb) { + fsm *f = &pcb->lcp_fsm; + + /* Clear the parameters for generating echo frames */ + pcb->lcp_echos_pending = 0; + pcb->lcp_echo_number = 0; + pcb->lcp_echo_timer_running = 0; + + /* If a timeout interval is specified then start the timer */ + if (pcb->settings.lcp_echo_interval != 0) + LcpEchoCheck (f); +} + +/* + * lcp_echo_lowerdown - Stop the timer for the LCP frame + */ + +static void lcp_echo_lowerdown(ppp_pcb *pcb) { + fsm *f = &pcb->lcp_fsm; + + if (pcb->lcp_echo_timer_running != 0) { + UNTIMEOUT (LcpEchoTimeout, f); + pcb->lcp_echo_timer_running = 0; + } +} + +#endif /* PPP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/magic.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/magic.c new file mode 100644 index 0000000..a6a5549 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/magic.c @@ -0,0 +1,267 @@ +/* + * magic.c - PPP Magic Number routines. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. 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. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/***************************************************************************** +* randm.c - Random number generator program file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* Copyright (c) 1998 by Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 98-06-03 Guy Lancaster , Global Election Systems Inc. +* Extracted from avos. +*****************************************************************************/ + +#include "lwip/opt.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "netif/ppp/ppp_impl.h" +#include "netif/ppp/magic.h" + +#if PPP_MD5_RANDM /* Using MD5 for better randomness if enabled */ + +#if LWIP_INCLUDED_POLARSSL_MD5 +#include "netif/ppp/polarssl/md5.h" +#else +#include "polarssl/md5.h" +#endif + +#define MAGIC_RANDPOOLSIZE 16 /* Bytes stored in the pool of randomness. */ + +/*****************************/ +/*** LOCAL DATA STRUCTURES ***/ +/*****************************/ +static char magic_randpool[MAGIC_RANDPOOLSIZE]; /* Pool of randomness. */ +static long magic_randcount = 0; /* Pseudo-random incrementer */ + + +/***********************************/ +/*** PUBLIC FUNCTION DEFINITIONS ***/ +/***********************************/ + +/* + * Churn the randomness pool on a random event. Call this early and often + * on random and semi-random system events to build randomness in time for + * usage. For randomly timed events, pass a null pointer and a zero length + * and this will use the system timer and other sources to add randomness. + * If new random data is available, pass a pointer to that and it will be + * included. + * + * Ref: Applied Cryptography 2nd Ed. by Bruce Schneier p. 427 + */ +static void magic_churnrand(char *rand_data, u32_t rand_len) { + md5_context md5; + + /* LWIP_DEBUGF(LOG_INFO, ("magic_churnrand: %u@%P\n", rand_len, rand_data)); */ + md5_starts(&md5); + md5_update(&md5, (u_char *)magic_randpool, sizeof(magic_randpool)); + if (rand_data) { + md5_update(&md5, (u_char *)rand_data, rand_len); + } else { + struct { + /* INCLUDE fields for any system sources of randomness */ + u32_t jiffies; + } sys_data; + sys_data.jiffies = sys_jiffies(); + /* Load sys_data fields here. */ + md5_update(&md5, (u_char *)&sys_data, sizeof(sys_data)); + } + md5_finish(&md5, (u_char *)magic_randpool); +/* LWIP_DEBUGF(LOG_INFO, ("magic_churnrand: -> 0\n")); */ +} + +/* + * Initialize the random number generator. + */ +void magic_init(void) { + magic_churnrand(NULL, 0); +} + +/* + * Randomize our random seed value. + */ +void magic_randomize(void) { + magic_churnrand(NULL, 0); +} + +/* + * random_bytes - Fill a buffer with random bytes. + * + * Use the random pool to generate random data. This degrades to pseudo + * random when used faster than randomness is supplied using magic_churnrand(). + * Note: It's important that there be sufficient randomness in magic_randpool + * before this is called for otherwise the range of the result may be + * narrow enough to make a search feasible. + * + * Ref: Applied Cryptography 2nd Ed. by Bruce Schneier p. 427 + * + * XXX Why does he not just call magic_churnrand() for each block? Probably + * so that you don't ever publish the seed which could possibly help + * predict future values. + * XXX Why don't we preserve md5 between blocks and just update it with + * magic_randcount each time? Probably there is a weakness but I wish that + * it was documented. + */ +void random_bytes(unsigned char *buf, u32_t buf_len) { + md5_context md5; + u_char tmp[16]; + u32_t n; + + while (buf_len > 0) { + n = LWIP_MIN(buf_len, MAGIC_RANDPOOLSIZE); + md5_starts(&md5); + md5_update(&md5, (u_char *)magic_randpool, sizeof(magic_randpool)); + md5_update(&md5, (u_char *)&magic_randcount, sizeof(magic_randcount)); + md5_finish(&md5, tmp); + magic_randcount++; + MEMCPY(buf, tmp, n); + buf += n; + buf_len -= n; + } +} + +/* + * Return a new random number. + */ +u32_t magic(void) { + u32_t new_rand; + + random_bytes((unsigned char *)&new_rand, sizeof(new_rand)); + + return new_rand; +} + +#else /* PPP_MD5_RANDM */ + +/*****************************/ +/*** LOCAL DATA STRUCTURES ***/ +/*****************************/ +static int magic_randomized = 0; /* Set when truely randomized. */ +static u32_t magic_randomseed = 0; /* Seed used for random number generation. */ + + +/***********************************/ +/*** PUBLIC FUNCTION DEFINITIONS ***/ +/***********************************/ + +/* + * Initialize the random number generator. + * + * Here we attempt to compute a random number seed but even if + * it isn't random, we'll randomize it later. + * + * The current method uses the fields from the real time clock, + * the idle process counter, the millisecond counter, and the + * hardware timer tick counter. When this is invoked + * in startup(), then the idle counter and timer values may + * repeat after each boot and the real time clock may not be + * operational. Thus we call it again on the first random + * event. + */ +void magic_init() { + magic_randomseed += sys_jiffies(); + + /* Initialize the Borland random number generator. */ + srand((unsigned)magic_randomseed); +} + +/* + * magic_init - Initialize the magic number generator. + * + * Randomize our random seed value. Here we use the fact that + * this function is called at *truely random* times by the polling + * and network functions. Here we only get 16 bits of new random + * value but we use the previous value to randomize the other 16 + * bits. + */ +void magic_randomize(void) { + static u32_t last_jiffies; + + if (!magic_randomized) { + magic_randomized = !0; + magic_init(); + /* The initialization function also updates the seed. */ + } else { + /* magic_randomseed += (magic_randomseed << 16) + TM1; */ + magic_randomseed += (sys_jiffies() - last_jiffies); /* XXX */ + } + last_jiffies = sys_jiffies(); +} + +/* + * Return a new random number. + * + * Here we use the Borland rand() function to supply a pseudo random + * number which we make truely random by combining it with our own + * seed which is randomized by truely random events. + * Thus the numbers will be truely random unless there have been no + * operator or network events in which case it will be pseudo random + * seeded by the real time clock. + */ +u32_t magic() { + return ((((u32_t)rand() << 16) + rand()) + magic_randomseed); +} + +#endif /* PPP_MD5_RANDM */ + +#endif /* PPP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/multilink.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/multilink.c new file mode 100644 index 0000000..3bea516 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/multilink.c @@ -0,0 +1,609 @@ +/* + * multilink.c - support routines for multilink. + * + * Copyright (c) 2000-2002 Paul Mackerras. 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. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && defined(HAVE_MULTILINK) /* don't build if not configured for use in lwipopts.h */ + +/* Multilink support + * + * Multilink uses Samba TDB (Trivial Database Library), which + * we cannot port, because it needs a filesystem. + * + * We have to choose between doing a memory-shared TDB-clone, + * or dropping multilink support at all. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/fsm.h" +#include "netif/ppp/lcp.h" +#include "netif/ppp/tdb.h" + +bool endpoint_specified; /* user gave explicit endpoint discriminator */ +char *bundle_id; /* identifier for our bundle */ +char *blinks_id; /* key for the list of links */ +bool doing_multilink; /* multilink was enabled and agreed to */ +bool multilink_master; /* we own the multilink bundle */ + +extern TDB_CONTEXT *pppdb; +extern char db_key[]; + +static void make_bundle_links (int append); +static void remove_bundle_link (void); +static void iterate_bundle_links (void (*func) (char *)); + +static int get_default_epdisc (struct epdisc *); +static int parse_num (char *str, const char *key, int *valp); +static int owns_unit (TDB_DATA pid, int unit); + +#define set_ip_epdisc(ep, addr) do { \ + ep->length = 4; \ + ep->value[0] = addr >> 24; \ + ep->value[1] = addr >> 16; \ + ep->value[2] = addr >> 8; \ + ep->value[3] = addr; \ +} while (0) + +#define LOCAL_IP_ADDR(addr) \ + (((addr) & 0xff000000) == 0x0a000000 /* 10.x.x.x */ \ + || ((addr) & 0xfff00000) == 0xac100000 /* 172.16.x.x */ \ + || ((addr) & 0xffff0000) == 0xc0a80000) /* 192.168.x.x */ + +#define process_exists(n) (kill((n), 0) == 0 || errno != ESRCH) + +void +mp_check_options() +{ + lcp_options *wo = &lcp_wantoptions[0]; + lcp_options *ao = &lcp_allowoptions[0]; + + doing_multilink = 0; + if (!multilink) + return; + /* if we're doing multilink, we have to negotiate MRRU */ + if (!wo->neg_mrru) { + /* mrru not specified, default to mru */ + wo->mrru = wo->mru; + wo->neg_mrru = 1; + } + ao->mrru = ao->mru; + ao->neg_mrru = 1; + + if (!wo->neg_endpoint && !noendpoint) { + /* get a default endpoint value */ + wo->neg_endpoint = get_default_epdisc(&wo->endpoint); + } +} + +/* + * Make a new bundle or join us to an existing bundle + * if we are doing multilink. + */ +int +mp_join_bundle() +{ + lcp_options *go = &lcp_gotoptions[0]; + lcp_options *ho = &lcp_hisoptions[0]; + lcp_options *ao = &lcp_allowoptions[0]; + int unit, pppd_pid; + int l, mtu; + char *p; + TDB_DATA key, pid, rec; + + if (doing_multilink) { + /* have previously joined a bundle */ + if (!go->neg_mrru || !ho->neg_mrru) { + notice("oops, didn't get multilink on renegotiation"); + lcp_close(pcb, "multilink required"); + return 0; + } + /* XXX should check the peer_authname and ho->endpoint + are the same as previously */ + return 0; + } + + if (!go->neg_mrru || !ho->neg_mrru) { + /* not doing multilink */ + if (go->neg_mrru) + notice("oops, multilink negotiated only for receive"); + mtu = ho->neg_mru? ho->mru: PPP_MRU; + if (mtu > ao->mru) + mtu = ao->mru; + if (demand) { + /* already have a bundle */ + cfg_bundle(0, 0, 0, 0); + netif_set_mtu(pcb, mtu); + return 0; + } + make_new_bundle(0, 0, 0, 0); + set_ifunit(1); + netif_set_mtu(pcb, mtu); + return 0; + } + + doing_multilink = 1; + + /* + * Find the appropriate bundle or join a new one. + * First we make up a name for the bundle. + * The length estimate is worst-case assuming every + * character has to be quoted. + */ + l = 4 * strlen(peer_authname) + 10; + if (ho->neg_endpoint) + l += 3 * ho->endpoint.length + 8; + if (bundle_name) + l += 3 * strlen(bundle_name) + 2; + bundle_id = malloc(l); + if (bundle_id == 0) + novm("bundle identifier"); + + p = bundle_id; + p += slprintf(p, l-1, "BUNDLE=\"%q\"", peer_authname); + if (ho->neg_endpoint || bundle_name) + *p++ = '/'; + if (ho->neg_endpoint) + p += slprintf(p, bundle_id+l-p, "%s", + epdisc_to_str(&ho->endpoint)); + if (bundle_name) + p += slprintf(p, bundle_id+l-p, "/%v", bundle_name); + + /* Make the key for the list of links belonging to the bundle */ + l = p - bundle_id; + blinks_id = malloc(l + 7); + if (blinks_id == NULL) + novm("bundle links key"); + slprintf(blinks_id, l + 7, "BUNDLE_LINKS=%s", bundle_id + 7); + + /* + * For demand mode, we only need to configure the bundle + * and attach the link. + */ + mtu = LWIP_MIN(ho->mrru, ao->mru); + if (demand) { + cfg_bundle(go->mrru, ho->mrru, go->neg_ssnhf, ho->neg_ssnhf); + netif_set_mtu(pcb, mtu); + script_setenv("BUNDLE", bundle_id + 7, 1); + return 0; + } + + /* + * Check if the bundle ID is already in the database. + */ + unit = -1; + lock_db(); + key.dptr = bundle_id; + key.dsize = p - bundle_id; + pid = tdb_fetch(pppdb, key); + if (pid.dptr != NULL) { + /* bundle ID exists, see if the pppd record exists */ + rec = tdb_fetch(pppdb, pid); + if (rec.dptr != NULL && rec.dsize > 0) { + /* make sure the string is null-terminated */ + rec.dptr[rec.dsize-1] = 0; + /* parse the interface number */ + parse_num(rec.dptr, "IFNAME=ppp", &unit); + /* check the pid value */ + if (!parse_num(rec.dptr, "PPPD_PID=", &pppd_pid) + || !process_exists(pppd_pid) + || !owns_unit(pid, unit)) + unit = -1; + free(rec.dptr); + } + free(pid.dptr); + } + + if (unit >= 0) { + /* attach to existing unit */ + if (bundle_attach(unit)) { + set_ifunit(0); + script_setenv("BUNDLE", bundle_id + 7, 0); + make_bundle_links(1); + unlock_db(); + info("Link attached to %s", ifname); + return 1; + } + /* attach failed because bundle doesn't exist */ + } + + /* we have to make a new bundle */ + make_new_bundle(go->mrru, ho->mrru, go->neg_ssnhf, ho->neg_ssnhf); + set_ifunit(1); + netif_set_mtu(pcb, mtu); + script_setenv("BUNDLE", bundle_id + 7, 1); + make_bundle_links(pcb); + unlock_db(); + info("New bundle %s created", ifname); + multilink_master = 1; + return 0; +} + +void mp_exit_bundle() +{ + lock_db(); + remove_bundle_link(); + unlock_db(); +} + +static void sendhup(char *str) +{ + int pid; + + if (parse_num(str, "PPPD_PID=", &pid) && pid != getpid()) { + if (debug) + dbglog("sending SIGHUP to process %d", pid); + kill(pid, SIGHUP); + } +} + +void mp_bundle_terminated() +{ + TDB_DATA key; + + bundle_terminating = 1; + upper_layers_down(pcb); + notice("Connection terminated."); +#if PPP_STATS_SUPPORT + print_link_stats(); +#endif /* PPP_STATS_SUPPORT */ + if (!demand) { + remove_pidfiles(); + script_unsetenv("IFNAME"); + } + + lock_db(); + destroy_bundle(); + iterate_bundle_links(sendhup); + key.dptr = blinks_id; + key.dsize = strlen(blinks_id); + tdb_delete(pppdb, key); + unlock_db(); + + new_phase(PPP_PHASE_DEAD); + + doing_multilink = 0; + multilink_master = 0; +} + +static void make_bundle_links(int append) +{ + TDB_DATA key, rec; + char *p; + char entry[32]; + int l; + + key.dptr = blinks_id; + key.dsize = strlen(blinks_id); + slprintf(entry, sizeof(entry), "%s;", db_key); + p = entry; + if (append) { + rec = tdb_fetch(pppdb, key); + if (rec.dptr != NULL && rec.dsize > 0) { + rec.dptr[rec.dsize-1] = 0; + if (strstr(rec.dptr, db_key) != NULL) { + /* already in there? strange */ + warn("link entry already exists in tdb"); + return; + } + l = rec.dsize + strlen(entry); + p = malloc(l); + if (p == NULL) + novm("bundle link list"); + slprintf(p, l, "%s%s", rec.dptr, entry); + } else { + warn("bundle link list not found"); + } + if (rec.dptr != NULL) + free(rec.dptr); + } + rec.dptr = p; + rec.dsize = strlen(p) + 1; + if (tdb_store(pppdb, key, rec, TDB_REPLACE)) + error("couldn't %s bundle link list", + append? "update": "create"); + if (p != entry) + free(p); +} + +static void remove_bundle_link() +{ + TDB_DATA key, rec; + char entry[32]; + char *p, *q; + int l; + + key.dptr = blinks_id; + key.dsize = strlen(blinks_id); + slprintf(entry, sizeof(entry), "%s;", db_key); + + rec = tdb_fetch(pppdb, key); + if (rec.dptr == NULL || rec.dsize <= 0) { + if (rec.dptr != NULL) + free(rec.dptr); + return; + } + rec.dptr[rec.dsize-1] = 0; + p = strstr(rec.dptr, entry); + if (p != NULL) { + q = p + strlen(entry); + l = strlen(q) + 1; + memmove(p, q, l); + rec.dsize = p - rec.dptr + l; + if (tdb_store(pppdb, key, rec, TDB_REPLACE)) + error("couldn't update bundle link list (removal)"); + } + free(rec.dptr); +} + +static void iterate_bundle_links(void (*func)(char *)) +{ + TDB_DATA key, rec, pp; + char *p, *q; + + key.dptr = blinks_id; + key.dsize = strlen(blinks_id); + rec = tdb_fetch(pppdb, key); + if (rec.dptr == NULL || rec.dsize <= 0) { + error("bundle link list not found (iterating list)"); + if (rec.dptr != NULL) + free(rec.dptr); + return; + } + p = rec.dptr; + p[rec.dsize-1] = 0; + while ((q = strchr(p, ';')) != NULL) { + *q = 0; + key.dptr = p; + key.dsize = q - p; + pp = tdb_fetch(pppdb, key); + if (pp.dptr != NULL && pp.dsize > 0) { + pp.dptr[pp.dsize-1] = 0; + func(pp.dptr); + } + if (pp.dptr != NULL) + free(pp.dptr); + p = q + 1; + } + free(rec.dptr); +} + +static int +parse_num(str, key, valp) + char *str; + const char *key; + int *valp; +{ + char *p, *endp; + int i; + + p = strstr(str, key); + if (p != 0) { + p += strlen(key); + i = strtol(p, &endp, 10); + if (endp != p && (*endp == 0 || *endp == ';')) { + *valp = i; + return 1; + } + } + return 0; +} + +/* + * Check whether the pppd identified by `key' still owns ppp unit `unit'. + */ +static int +owns_unit(key, unit) + TDB_DATA key; + int unit; +{ + char ifkey[32]; + TDB_DATA kd, vd; + int ret = 0; + + slprintf(ifkey, sizeof(ifkey), "IFNAME=ppp%d", unit); + kd.dptr = ifkey; + kd.dsize = strlen(ifkey); + vd = tdb_fetch(pppdb, kd); + if (vd.dptr != NULL) { + ret = vd.dsize == key.dsize + && memcmp(vd.dptr, key.dptr, vd.dsize) == 0; + free(vd.dptr); + } + return ret; +} + +static int +get_default_epdisc(ep) + struct epdisc *ep; +{ + char *p; + struct hostent *hp; + u32_t addr; + + /* First try for an ethernet MAC address */ + p = get_first_ethernet(); + if (p != 0 && get_if_hwaddr(ep->value, p) >= 0) { + ep->class = EPD_MAC; + ep->length = 6; + return 1; + } + + /* see if our hostname corresponds to a reasonable IP address */ + hp = gethostbyname(hostname); + if (hp != NULL) { + addr = *(u32_t *)hp->h_addr; + if (!bad_ip_adrs(addr)) { + addr = ntohl(addr); + if (!LOCAL_IP_ADDR(addr)) { + ep->class = EPD_IP; + set_ip_epdisc(ep, addr); + return 1; + } + } + } + + return 0; +} + +/* + * epdisc_to_str - make a printable string from an endpoint discriminator. + */ + +static char *endp_class_names[] = { + "null", "local", "IP", "MAC", "magic", "phone" +}; + +char * +epdisc_to_str(ep) + struct epdisc *ep; +{ + static char str[MAX_ENDP_LEN*3+8]; + u_char *p = ep->value; + int i, mask = 0; + char *q, c, c2; + + if (ep->class == EPD_NULL && ep->length == 0) + return "null"; + if (ep->class == EPD_IP && ep->length == 4) { + u32_t addr; + + GETLONG(addr, p); + slprintf(str, sizeof(str), "IP:%I", htonl(addr)); + return str; + } + + c = ':'; + c2 = '.'; + if (ep->class == EPD_MAC && ep->length == 6) + c2 = ':'; + else if (ep->class == EPD_MAGIC && (ep->length % 4) == 0) + mask = 3; + q = str; + if (ep->class <= EPD_PHONENUM) + q += slprintf(q, sizeof(str)-1, "%s", + endp_class_names[ep->class]); + else + q += slprintf(q, sizeof(str)-1, "%d", ep->class); + c = ':'; + for (i = 0; i < ep->length && i < MAX_ENDP_LEN; ++i) { + if ((i & mask) == 0) { + *q++ = c; + c = c2; + } + q += slprintf(q, str + sizeof(str) - q, "%.2x", ep->value[i]); + } + return str; +} + +static int hexc_val(int c) +{ + if (c >= 'a') + return c - 'a' + 10; + if (c >= 'A') + return c - 'A' + 10; + return c - '0'; +} + +int +str_to_epdisc(ep, str) + struct epdisc *ep; + char *str; +{ + int i, l; + char *p, *endp; + + for (i = EPD_NULL; i <= EPD_PHONENUM; ++i) { + int sl = strlen(endp_class_names[i]); + if (strncasecmp(str, endp_class_names[i], sl) == 0) { + str += sl; + break; + } + } + if (i > EPD_PHONENUM) { + /* not a class name, try a decimal class number */ + i = strtol(str, &endp, 10); + if (endp == str) + return 0; /* can't parse class number */ + str = endp; + } + ep->class = i; + if (*str == 0) { + ep->length = 0; + return 1; + } + if (*str != ':' && *str != '.') + return 0; + ++str; + + if (i == EPD_IP) { + u32_t addr; + i = parse_dotted_ip(str, &addr); + if (i == 0 || str[i] != 0) + return 0; + set_ip_epdisc(ep, addr); + return 1; + } + if (i == EPD_MAC && get_if_hwaddr(ep->value, str) >= 0) { + ep->length = 6; + return 1; + } + + p = str; + for (l = 0; l < MAX_ENDP_LEN; ++l) { + if (*str == 0) + break; + if (p <= str) + for (p = str; isxdigit(*p); ++p) + ; + i = p - str; + if (i == 0) + return 0; + ep->value[l] = hexc_val(*str++); + if ((i & 1) == 0) + ep->value[l] = (ep->value[l] << 4) + hexc_val(*str++); + if (*str == ':' || *str == '.') + ++str; + } + if (*str != 0 || (ep->class == EPD_MAC && l != 6)) + return 0; + ep->length = l; + return 1; +} + +#endif /* PPP_SUPPORT && HAVE_MULTILINK */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/polarssl/README b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/polarssl/README new file mode 100644 index 0000000..71f78fa --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/polarssl/README @@ -0,0 +1,34 @@ +About PolarSSL files into lwIP PPP support +------------------------------------------ + +This folder contains some files fetched from the latest BSD release of +the PolarSSL project for ciphers and encryption methods we need for lwIP +PPP support. + +The PolarSSL files were cleaned to contain only the necessary struct +fields and functions needed for lwIP. + + +The PolarSSL API was not changed at all, so if you are already using +PolarSSL you can choose to skip the compilation of the included PolarSSL +library into lwIP: + +The following defines are available for flexibility: + +LWIP_INCLUDED_POLARSSL_MD4 ; Use lwIP internal PolarSSL for MD4 +LWIP_INCLUDED_POLARSSL_MD5 ; Use lwIP internal PolarSSL for MD5 +LWIP_INCLUDED_POLARSSL_SHA1 ; Use lwIP internal PolarSSL for SHA1 +LWIP_INCLUDED_POLARSSL_DES ; Use lwIP internal PolarSSL for DES + +If set (=1), the default if required by another enabled PPP feature unless +explicitly set to 0, using included lwIP PolarSSL. + +If clear (=0), using external PolarSSL. + +Undefined if not needed. + +Beware of the stack requirements which can be a lot larger if you are not +using our cleaned PolarSSL library. + + +PolarSSL project website: http://polarssl.org/ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/polarssl/des.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/polarssl/des.c new file mode 100644 index 0000000..38f3a74 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/polarssl/des.c @@ -0,0 +1,422 @@ +/* + * FIPS-46-3 compliant Triple-DES implementation + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the names of PolarSSL or XySSL 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 HOLDERS 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 + * OWNER 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. + */ +/* + * DES, on which TDES is based, was originally designed by Horst Feistel + * at IBM in 1974, and was adopted as a standard by NIST (formerly NBS). + * + * http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_DES + +#include "netif/ppp/polarssl/des.h" + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_ULONG_BE +#define GET_ULONG_BE(n,b,i) \ +{ \ + (n) = ( (unsigned long) (b)[(i) ] << 24 ) \ + | ( (unsigned long) (b)[(i) + 1] << 16 ) \ + | ( (unsigned long) (b)[(i) + 2] << 8 ) \ + | ( (unsigned long) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_ULONG_BE +#define PUT_ULONG_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +/* + * Expanded DES S-boxes + */ +static const unsigned long SB1[64] = +{ + 0x01010400, 0x00000000, 0x00010000, 0x01010404, + 0x01010004, 0x00010404, 0x00000004, 0x00010000, + 0x00000400, 0x01010400, 0x01010404, 0x00000400, + 0x01000404, 0x01010004, 0x01000000, 0x00000004, + 0x00000404, 0x01000400, 0x01000400, 0x00010400, + 0x00010400, 0x01010000, 0x01010000, 0x01000404, + 0x00010004, 0x01000004, 0x01000004, 0x00010004, + 0x00000000, 0x00000404, 0x00010404, 0x01000000, + 0x00010000, 0x01010404, 0x00000004, 0x01010000, + 0x01010400, 0x01000000, 0x01000000, 0x00000400, + 0x01010004, 0x00010000, 0x00010400, 0x01000004, + 0x00000400, 0x00000004, 0x01000404, 0x00010404, + 0x01010404, 0x00010004, 0x01010000, 0x01000404, + 0x01000004, 0x00000404, 0x00010404, 0x01010400, + 0x00000404, 0x01000400, 0x01000400, 0x00000000, + 0x00010004, 0x00010400, 0x00000000, 0x01010004 +}; + +static const unsigned long SB2[64] = +{ + 0x80108020, 0x80008000, 0x00008000, 0x00108020, + 0x00100000, 0x00000020, 0x80100020, 0x80008020, + 0x80000020, 0x80108020, 0x80108000, 0x80000000, + 0x80008000, 0x00100000, 0x00000020, 0x80100020, + 0x00108000, 0x00100020, 0x80008020, 0x00000000, + 0x80000000, 0x00008000, 0x00108020, 0x80100000, + 0x00100020, 0x80000020, 0x00000000, 0x00108000, + 0x00008020, 0x80108000, 0x80100000, 0x00008020, + 0x00000000, 0x00108020, 0x80100020, 0x00100000, + 0x80008020, 0x80100000, 0x80108000, 0x00008000, + 0x80100000, 0x80008000, 0x00000020, 0x80108020, + 0x00108020, 0x00000020, 0x00008000, 0x80000000, + 0x00008020, 0x80108000, 0x00100000, 0x80000020, + 0x00100020, 0x80008020, 0x80000020, 0x00100020, + 0x00108000, 0x00000000, 0x80008000, 0x00008020, + 0x80000000, 0x80100020, 0x80108020, 0x00108000 +}; + +static const unsigned long SB3[64] = +{ + 0x00000208, 0x08020200, 0x00000000, 0x08020008, + 0x08000200, 0x00000000, 0x00020208, 0x08000200, + 0x00020008, 0x08000008, 0x08000008, 0x00020000, + 0x08020208, 0x00020008, 0x08020000, 0x00000208, + 0x08000000, 0x00000008, 0x08020200, 0x00000200, + 0x00020200, 0x08020000, 0x08020008, 0x00020208, + 0x08000208, 0x00020200, 0x00020000, 0x08000208, + 0x00000008, 0x08020208, 0x00000200, 0x08000000, + 0x08020200, 0x08000000, 0x00020008, 0x00000208, + 0x00020000, 0x08020200, 0x08000200, 0x00000000, + 0x00000200, 0x00020008, 0x08020208, 0x08000200, + 0x08000008, 0x00000200, 0x00000000, 0x08020008, + 0x08000208, 0x00020000, 0x08000000, 0x08020208, + 0x00000008, 0x00020208, 0x00020200, 0x08000008, + 0x08020000, 0x08000208, 0x00000208, 0x08020000, + 0x00020208, 0x00000008, 0x08020008, 0x00020200 +}; + +static const unsigned long SB4[64] = +{ + 0x00802001, 0x00002081, 0x00002081, 0x00000080, + 0x00802080, 0x00800081, 0x00800001, 0x00002001, + 0x00000000, 0x00802000, 0x00802000, 0x00802081, + 0x00000081, 0x00000000, 0x00800080, 0x00800001, + 0x00000001, 0x00002000, 0x00800000, 0x00802001, + 0x00000080, 0x00800000, 0x00002001, 0x00002080, + 0x00800081, 0x00000001, 0x00002080, 0x00800080, + 0x00002000, 0x00802080, 0x00802081, 0x00000081, + 0x00800080, 0x00800001, 0x00802000, 0x00802081, + 0x00000081, 0x00000000, 0x00000000, 0x00802000, + 0x00002080, 0x00800080, 0x00800081, 0x00000001, + 0x00802001, 0x00002081, 0x00002081, 0x00000080, + 0x00802081, 0x00000081, 0x00000001, 0x00002000, + 0x00800001, 0x00002001, 0x00802080, 0x00800081, + 0x00002001, 0x00002080, 0x00800000, 0x00802001, + 0x00000080, 0x00800000, 0x00002000, 0x00802080 +}; + +static const unsigned long SB5[64] = +{ + 0x00000100, 0x02080100, 0x02080000, 0x42000100, + 0x00080000, 0x00000100, 0x40000000, 0x02080000, + 0x40080100, 0x00080000, 0x02000100, 0x40080100, + 0x42000100, 0x42080000, 0x00080100, 0x40000000, + 0x02000000, 0x40080000, 0x40080000, 0x00000000, + 0x40000100, 0x42080100, 0x42080100, 0x02000100, + 0x42080000, 0x40000100, 0x00000000, 0x42000000, + 0x02080100, 0x02000000, 0x42000000, 0x00080100, + 0x00080000, 0x42000100, 0x00000100, 0x02000000, + 0x40000000, 0x02080000, 0x42000100, 0x40080100, + 0x02000100, 0x40000000, 0x42080000, 0x02080100, + 0x40080100, 0x00000100, 0x02000000, 0x42080000, + 0x42080100, 0x00080100, 0x42000000, 0x42080100, + 0x02080000, 0x00000000, 0x40080000, 0x42000000, + 0x00080100, 0x02000100, 0x40000100, 0x00080000, + 0x00000000, 0x40080000, 0x02080100, 0x40000100 +}; + +static const unsigned long SB6[64] = +{ + 0x20000010, 0x20400000, 0x00004000, 0x20404010, + 0x20400000, 0x00000010, 0x20404010, 0x00400000, + 0x20004000, 0x00404010, 0x00400000, 0x20000010, + 0x00400010, 0x20004000, 0x20000000, 0x00004010, + 0x00000000, 0x00400010, 0x20004010, 0x00004000, + 0x00404000, 0x20004010, 0x00000010, 0x20400010, + 0x20400010, 0x00000000, 0x00404010, 0x20404000, + 0x00004010, 0x00404000, 0x20404000, 0x20000000, + 0x20004000, 0x00000010, 0x20400010, 0x00404000, + 0x20404010, 0x00400000, 0x00004010, 0x20000010, + 0x00400000, 0x20004000, 0x20000000, 0x00004010, + 0x20000010, 0x20404010, 0x00404000, 0x20400000, + 0x00404010, 0x20404000, 0x00000000, 0x20400010, + 0x00000010, 0x00004000, 0x20400000, 0x00404010, + 0x00004000, 0x00400010, 0x20004010, 0x00000000, + 0x20404000, 0x20000000, 0x00400010, 0x20004010 +}; + +static const unsigned long SB7[64] = +{ + 0x00200000, 0x04200002, 0x04000802, 0x00000000, + 0x00000800, 0x04000802, 0x00200802, 0x04200800, + 0x04200802, 0x00200000, 0x00000000, 0x04000002, + 0x00000002, 0x04000000, 0x04200002, 0x00000802, + 0x04000800, 0x00200802, 0x00200002, 0x04000800, + 0x04000002, 0x04200000, 0x04200800, 0x00200002, + 0x04200000, 0x00000800, 0x00000802, 0x04200802, + 0x00200800, 0x00000002, 0x04000000, 0x00200800, + 0x04000000, 0x00200800, 0x00200000, 0x04000802, + 0x04000802, 0x04200002, 0x04200002, 0x00000002, + 0x00200002, 0x04000000, 0x04000800, 0x00200000, + 0x04200800, 0x00000802, 0x00200802, 0x04200800, + 0x00000802, 0x04000002, 0x04200802, 0x04200000, + 0x00200800, 0x00000000, 0x00000002, 0x04200802, + 0x00000000, 0x00200802, 0x04200000, 0x00000800, + 0x04000002, 0x04000800, 0x00000800, 0x00200002 +}; + +static const unsigned long SB8[64] = +{ + 0x10001040, 0x00001000, 0x00040000, 0x10041040, + 0x10000000, 0x10001040, 0x00000040, 0x10000000, + 0x00040040, 0x10040000, 0x10041040, 0x00041000, + 0x10041000, 0x00041040, 0x00001000, 0x00000040, + 0x10040000, 0x10000040, 0x10001000, 0x00001040, + 0x00041000, 0x00040040, 0x10040040, 0x10041000, + 0x00001040, 0x00000000, 0x00000000, 0x10040040, + 0x10000040, 0x10001000, 0x00041040, 0x00040000, + 0x00041040, 0x00040000, 0x10041000, 0x00001000, + 0x00000040, 0x10040040, 0x00001000, 0x00041040, + 0x10001000, 0x00000040, 0x10000040, 0x10040000, + 0x10040040, 0x10000000, 0x00040000, 0x10001040, + 0x00000000, 0x10041040, 0x00040040, 0x10000040, + 0x10040000, 0x10001000, 0x10001040, 0x00000000, + 0x10041040, 0x00041000, 0x00041000, 0x00001040, + 0x00001040, 0x00040040, 0x10000000, 0x10041000 +}; + +/* + * PC1: left and right halves bit-swap + */ +static const unsigned long LHs[16] = +{ + 0x00000000, 0x00000001, 0x00000100, 0x00000101, + 0x00010000, 0x00010001, 0x00010100, 0x00010101, + 0x01000000, 0x01000001, 0x01000100, 0x01000101, + 0x01010000, 0x01010001, 0x01010100, 0x01010101 +}; + +static const unsigned long RHs[16] = +{ + 0x00000000, 0x01000000, 0x00010000, 0x01010000, + 0x00000100, 0x01000100, 0x00010100, 0x01010100, + 0x00000001, 0x01000001, 0x00010001, 0x01010001, + 0x00000101, 0x01000101, 0x00010101, 0x01010101, +}; + +/* + * Initial Permutation macro + */ +#define DES_IP(X,Y) \ +{ \ + T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \ + T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \ + T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \ + T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \ + Y = ((Y << 1) | (Y >> 31)) & 0xFFFFFFFF; \ + T = (X ^ Y) & 0xAAAAAAAA; Y ^= T; X ^= T; \ + X = ((X << 1) | (X >> 31)) & 0xFFFFFFFF; \ +} + +/* + * Final Permutation macro + */ +#define DES_FP(X,Y) \ +{ \ + X = ((X << 31) | (X >> 1)) & 0xFFFFFFFF; \ + T = (X ^ Y) & 0xAAAAAAAA; X ^= T; Y ^= T; \ + Y = ((Y << 31) | (Y >> 1)) & 0xFFFFFFFF; \ + T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \ + T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \ + T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \ + T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \ +} + +/* + * DES round macro + */ +#define DES_ROUND(X,Y) \ +{ \ + T = *SK++ ^ X; \ + Y ^= SB8[ (T ) & 0x3F ] ^ \ + SB6[ (T >> 8) & 0x3F ] ^ \ + SB4[ (T >> 16) & 0x3F ] ^ \ + SB2[ (T >> 24) & 0x3F ]; \ + \ + T = *SK++ ^ ((X << 28) | (X >> 4)); \ + Y ^= SB7[ (T ) & 0x3F ] ^ \ + SB5[ (T >> 8) & 0x3F ] ^ \ + SB3[ (T >> 16) & 0x3F ] ^ \ + SB1[ (T >> 24) & 0x3F ]; \ +} + +#define SWAP(a,b) { unsigned long t = a; a = b; b = t; t = 0; } + +static void des_setkey( unsigned long SK[32], unsigned char key[8] ) +{ + int i; + unsigned long X, Y, T; + + GET_ULONG_BE( X, key, 0 ); + GET_ULONG_BE( Y, key, 4 ); + + /* + * Permuted Choice 1 + */ + T = ((Y >> 4) ^ X) & 0x0F0F0F0F; X ^= T; Y ^= (T << 4); + T = ((Y ) ^ X) & 0x10101010; X ^= T; Y ^= (T ); + + X = (LHs[ (X ) & 0xF] << 3) | (LHs[ (X >> 8) & 0xF ] << 2) + | (LHs[ (X >> 16) & 0xF] << 1) | (LHs[ (X >> 24) & 0xF ] ) + | (LHs[ (X >> 5) & 0xF] << 7) | (LHs[ (X >> 13) & 0xF ] << 6) + | (LHs[ (X >> 21) & 0xF] << 5) | (LHs[ (X >> 29) & 0xF ] << 4); + + Y = (RHs[ (Y >> 1) & 0xF] << 3) | (RHs[ (Y >> 9) & 0xF ] << 2) + | (RHs[ (Y >> 17) & 0xF] << 1) | (RHs[ (Y >> 25) & 0xF ] ) + | (RHs[ (Y >> 4) & 0xF] << 7) | (RHs[ (Y >> 12) & 0xF ] << 6) + | (RHs[ (Y >> 20) & 0xF] << 5) | (RHs[ (Y >> 28) & 0xF ] << 4); + + X &= 0x0FFFFFFF; + Y &= 0x0FFFFFFF; + + /* + * calculate subkeys + */ + for( i = 0; i < 16; i++ ) + { + if( i < 2 || i == 8 || i == 15 ) + { + X = ((X << 1) | (X >> 27)) & 0x0FFFFFFF; + Y = ((Y << 1) | (Y >> 27)) & 0x0FFFFFFF; + } + else + { + X = ((X << 2) | (X >> 26)) & 0x0FFFFFFF; + Y = ((Y << 2) | (Y >> 26)) & 0x0FFFFFFF; + } + + *SK++ = ((X << 4) & 0x24000000) | ((X << 28) & 0x10000000) + | ((X << 14) & 0x08000000) | ((X << 18) & 0x02080000) + | ((X << 6) & 0x01000000) | ((X << 9) & 0x00200000) + | ((X >> 1) & 0x00100000) | ((X << 10) & 0x00040000) + | ((X << 2) & 0x00020000) | ((X >> 10) & 0x00010000) + | ((Y >> 13) & 0x00002000) | ((Y >> 4) & 0x00001000) + | ((Y << 6) & 0x00000800) | ((Y >> 1) & 0x00000400) + | ((Y >> 14) & 0x00000200) | ((Y ) & 0x00000100) + | ((Y >> 5) & 0x00000020) | ((Y >> 10) & 0x00000010) + | ((Y >> 3) & 0x00000008) | ((Y >> 18) & 0x00000004) + | ((Y >> 26) & 0x00000002) | ((Y >> 24) & 0x00000001); + + *SK++ = ((X << 15) & 0x20000000) | ((X << 17) & 0x10000000) + | ((X << 10) & 0x08000000) | ((X << 22) & 0x04000000) + | ((X >> 2) & 0x02000000) | ((X << 1) & 0x01000000) + | ((X << 16) & 0x00200000) | ((X << 11) & 0x00100000) + | ((X << 3) & 0x00080000) | ((X >> 6) & 0x00040000) + | ((X << 15) & 0x00020000) | ((X >> 4) & 0x00010000) + | ((Y >> 2) & 0x00002000) | ((Y << 8) & 0x00001000) + | ((Y >> 14) & 0x00000808) | ((Y >> 9) & 0x00000400) + | ((Y ) & 0x00000200) | ((Y << 7) & 0x00000100) + | ((Y >> 7) & 0x00000020) | ((Y >> 3) & 0x00000011) + | ((Y << 2) & 0x00000004) | ((Y >> 21) & 0x00000002); + } +} + +/* + * DES key schedule (56-bit, encryption) + */ +void des_setkey_enc( des_context *ctx, unsigned char key[8] ) +{ + des_setkey( ctx->sk, key ); +} + +/* + * DES key schedule (56-bit, decryption) + */ +void des_setkey_dec( des_context *ctx, unsigned char key[8] ) +{ + int i; + + des_setkey( ctx->sk, key ); + + for( i = 0; i < 16; i += 2 ) + { + SWAP( ctx->sk[i ], ctx->sk[30 - i] ); + SWAP( ctx->sk[i + 1], ctx->sk[31 - i] ); + } +} + +/* + * DES-ECB block encryption/decryption + */ +void des_crypt_ecb( des_context *ctx, + unsigned char input[8], + unsigned char output[8] ) +{ + int i; + unsigned long X, Y, T, *SK; + + SK = ctx->sk; + + GET_ULONG_BE( X, input, 0 ); + GET_ULONG_BE( Y, input, 4 ); + + DES_IP( X, Y ); + + for( i = 0; i < 8; i++ ) + { + DES_ROUND( Y, X ); + DES_ROUND( X, Y ); + } + + DES_FP( Y, X ); + + PUT_ULONG_BE( Y, output, 0 ); + PUT_ULONG_BE( X, output, 4 ); +} + +#endif /* PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_DES */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/polarssl/md4.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/polarssl/md4.c new file mode 100644 index 0000000..8de2eb9 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/polarssl/md4.c @@ -0,0 +1,279 @@ +/* + * RFC 1186/1320 compliant MD4 implementation + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the names of PolarSSL or XySSL 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 HOLDERS 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 + * OWNER 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. + */ +/* + * The MD4 algorithm was designed by Ron Rivest in 1990. + * + * http://www.ietf.org/rfc/rfc1186.txt + * http://www.ietf.org/rfc/rfc1320.txt + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_MD4 + +#include "netif/ppp/polarssl/md4.h" + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_ULONG_LE +#define GET_ULONG_LE(n,b,i) \ +{ \ + (n) = ( (unsigned long) (b)[(i) ] ) \ + | ( (unsigned long) (b)[(i) + 1] << 8 ) \ + | ( (unsigned long) (b)[(i) + 2] << 16 ) \ + | ( (unsigned long) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_ULONG_LE +#define PUT_ULONG_LE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \ +} +#endif + +/* + * MD4 context setup + */ +void md4_starts( md4_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; +} + +static void md4_process( md4_context *ctx, unsigned char data[64] ) +{ + unsigned long X[16], A, B, C, D; + + GET_ULONG_LE( X[ 0], data, 0 ); + GET_ULONG_LE( X[ 1], data, 4 ); + GET_ULONG_LE( X[ 2], data, 8 ); + GET_ULONG_LE( X[ 3], data, 12 ); + GET_ULONG_LE( X[ 4], data, 16 ); + GET_ULONG_LE( X[ 5], data, 20 ); + GET_ULONG_LE( X[ 6], data, 24 ); + GET_ULONG_LE( X[ 7], data, 28 ); + GET_ULONG_LE( X[ 8], data, 32 ); + GET_ULONG_LE( X[ 9], data, 36 ); + GET_ULONG_LE( X[10], data, 40 ); + GET_ULONG_LE( X[11], data, 44 ); + GET_ULONG_LE( X[12], data, 48 ); + GET_ULONG_LE( X[13], data, 52 ); + GET_ULONG_LE( X[14], data, 56 ); + GET_ULONG_LE( X[15], data, 60 ); + +#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + +#define F(x, y, z) ((x & y) | ((~x) & z)) +#define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); } + + P( A, B, C, D, X[ 0], 3 ); + P( D, A, B, C, X[ 1], 7 ); + P( C, D, A, B, X[ 2], 11 ); + P( B, C, D, A, X[ 3], 19 ); + P( A, B, C, D, X[ 4], 3 ); + P( D, A, B, C, X[ 5], 7 ); + P( C, D, A, B, X[ 6], 11 ); + P( B, C, D, A, X[ 7], 19 ); + P( A, B, C, D, X[ 8], 3 ); + P( D, A, B, C, X[ 9], 7 ); + P( C, D, A, B, X[10], 11 ); + P( B, C, D, A, X[11], 19 ); + P( A, B, C, D, X[12], 3 ); + P( D, A, B, C, X[13], 7 ); + P( C, D, A, B, X[14], 11 ); + P( B, C, D, A, X[15], 19 ); + +#undef P +#undef F + +#define F(x,y,z) ((x & y) | (x & z) | (y & z)) +#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); } + + P( A, B, C, D, X[ 0], 3 ); + P( D, A, B, C, X[ 4], 5 ); + P( C, D, A, B, X[ 8], 9 ); + P( B, C, D, A, X[12], 13 ); + P( A, B, C, D, X[ 1], 3 ); + P( D, A, B, C, X[ 5], 5 ); + P( C, D, A, B, X[ 9], 9 ); + P( B, C, D, A, X[13], 13 ); + P( A, B, C, D, X[ 2], 3 ); + P( D, A, B, C, X[ 6], 5 ); + P( C, D, A, B, X[10], 9 ); + P( B, C, D, A, X[14], 13 ); + P( A, B, C, D, X[ 3], 3 ); + P( D, A, B, C, X[ 7], 5 ); + P( C, D, A, B, X[11], 9 ); + P( B, C, D, A, X[15], 13 ); + +#undef P +#undef F + +#define F(x,y,z) (x ^ y ^ z) +#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); } + + P( A, B, C, D, X[ 0], 3 ); + P( D, A, B, C, X[ 8], 9 ); + P( C, D, A, B, X[ 4], 11 ); + P( B, C, D, A, X[12], 15 ); + P( A, B, C, D, X[ 2], 3 ); + P( D, A, B, C, X[10], 9 ); + P( C, D, A, B, X[ 6], 11 ); + P( B, C, D, A, X[14], 15 ); + P( A, B, C, D, X[ 1], 3 ); + P( D, A, B, C, X[ 9], 9 ); + P( C, D, A, B, X[ 5], 11 ); + P( B, C, D, A, X[13], 15 ); + P( A, B, C, D, X[ 3], 3 ); + P( D, A, B, C, X[11], 9 ); + P( C, D, A, B, X[ 7], 11 ); + P( B, C, D, A, X[15], 15 ); + +#undef F +#undef P + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; +} + +/* + * MD4 process buffer + */ +void md4_update( md4_context *ctx, unsigned char *input, int ilen ) +{ + int fill; + unsigned long left; + + if( ilen <= 0 ) + return; + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (unsigned long) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + MEMCPY( (void *) (ctx->buffer + left), + (void *) input, fill ); + md4_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + md4_process( ctx, input ); + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + MEMCPY( (void *) (ctx->buffer + left), + (void *) input, ilen ); + } +} + +static const unsigned char md4_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * MD4 final digest + */ +void md4_finish( md4_context *ctx, unsigned char output[16] ) +{ + unsigned long last, padn; + unsigned long high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_ULONG_LE( low, msglen, 0 ); + PUT_ULONG_LE( high, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + md4_update( ctx, (unsigned char *) md4_padding, padn ); + md4_update( ctx, msglen, 8 ); + + PUT_ULONG_LE( ctx->state[0], output, 0 ); + PUT_ULONG_LE( ctx->state[1], output, 4 ); + PUT_ULONG_LE( ctx->state[2], output, 8 ); + PUT_ULONG_LE( ctx->state[3], output, 12 ); +} + +/* + * output = MD4( input buffer ) + */ +void md4( unsigned char *input, int ilen, unsigned char output[16] ) +{ + md4_context ctx; + + md4_starts( &ctx ); + md4_update( &ctx, input, ilen ); + md4_finish( &ctx, output ); +} + +#endif /* PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_MD4 */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/polarssl/md5.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/polarssl/md5.c new file mode 100644 index 0000000..50aa911 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/polarssl/md5.c @@ -0,0 +1,298 @@ +/* + * RFC 1321 compliant MD5 implementation + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the names of PolarSSL or XySSL 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 HOLDERS 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 + * OWNER 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. + */ +/* + * The MD5 algorithm was designed by Ron Rivest in 1991. + * + * http://www.ietf.org/rfc/rfc1321.txt + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_MD5 + +#include "netif/ppp/polarssl/md5.h" + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_ULONG_LE +#define GET_ULONG_LE(n,b,i) \ +{ \ + (n) = ( (unsigned long) (b)[(i) ] ) \ + | ( (unsigned long) (b)[(i) + 1] << 8 ) \ + | ( (unsigned long) (b)[(i) + 2] << 16 ) \ + | ( (unsigned long) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_ULONG_LE +#define PUT_ULONG_LE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \ +} +#endif + +/* + * MD5 context setup + */ +void md5_starts( md5_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; +} + +static void md5_process( md5_context *ctx, unsigned char data[64] ) +{ + unsigned long X[16], A, B, C, D; + + GET_ULONG_LE( X[ 0], data, 0 ); + GET_ULONG_LE( X[ 1], data, 4 ); + GET_ULONG_LE( X[ 2], data, 8 ); + GET_ULONG_LE( X[ 3], data, 12 ); + GET_ULONG_LE( X[ 4], data, 16 ); + GET_ULONG_LE( X[ 5], data, 20 ); + GET_ULONG_LE( X[ 6], data, 24 ); + GET_ULONG_LE( X[ 7], data, 28 ); + GET_ULONG_LE( X[ 8], data, 32 ); + GET_ULONG_LE( X[ 9], data, 36 ); + GET_ULONG_LE( X[10], data, 40 ); + GET_ULONG_LE( X[11], data, 44 ); + GET_ULONG_LE( X[12], data, 48 ); + GET_ULONG_LE( X[13], data, 52 ); + GET_ULONG_LE( X[14], data, 56 ); + GET_ULONG_LE( X[15], data, 60 ); + +#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) + +#define P(a,b,c,d,k,s,t) \ +{ \ + a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \ +} + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + +#define F(x,y,z) (z ^ (x & (y ^ z))) + + P( A, B, C, D, 0, 7, 0xD76AA478 ); + P( D, A, B, C, 1, 12, 0xE8C7B756 ); + P( C, D, A, B, 2, 17, 0x242070DB ); + P( B, C, D, A, 3, 22, 0xC1BDCEEE ); + P( A, B, C, D, 4, 7, 0xF57C0FAF ); + P( D, A, B, C, 5, 12, 0x4787C62A ); + P( C, D, A, B, 6, 17, 0xA8304613 ); + P( B, C, D, A, 7, 22, 0xFD469501 ); + P( A, B, C, D, 8, 7, 0x698098D8 ); + P( D, A, B, C, 9, 12, 0x8B44F7AF ); + P( C, D, A, B, 10, 17, 0xFFFF5BB1 ); + P( B, C, D, A, 11, 22, 0x895CD7BE ); + P( A, B, C, D, 12, 7, 0x6B901122 ); + P( D, A, B, C, 13, 12, 0xFD987193 ); + P( C, D, A, B, 14, 17, 0xA679438E ); + P( B, C, D, A, 15, 22, 0x49B40821 ); + +#undef F + +#define F(x,y,z) (y ^ (z & (x ^ y))) + + P( A, B, C, D, 1, 5, 0xF61E2562 ); + P( D, A, B, C, 6, 9, 0xC040B340 ); + P( C, D, A, B, 11, 14, 0x265E5A51 ); + P( B, C, D, A, 0, 20, 0xE9B6C7AA ); + P( A, B, C, D, 5, 5, 0xD62F105D ); + P( D, A, B, C, 10, 9, 0x02441453 ); + P( C, D, A, B, 15, 14, 0xD8A1E681 ); + P( B, C, D, A, 4, 20, 0xE7D3FBC8 ); + P( A, B, C, D, 9, 5, 0x21E1CDE6 ); + P( D, A, B, C, 14, 9, 0xC33707D6 ); + P( C, D, A, B, 3, 14, 0xF4D50D87 ); + P( B, C, D, A, 8, 20, 0x455A14ED ); + P( A, B, C, D, 13, 5, 0xA9E3E905 ); + P( D, A, B, C, 2, 9, 0xFCEFA3F8 ); + P( C, D, A, B, 7, 14, 0x676F02D9 ); + P( B, C, D, A, 12, 20, 0x8D2A4C8A ); + +#undef F + +#define F(x,y,z) (x ^ y ^ z) + + P( A, B, C, D, 5, 4, 0xFFFA3942 ); + P( D, A, B, C, 8, 11, 0x8771F681 ); + P( C, D, A, B, 11, 16, 0x6D9D6122 ); + P( B, C, D, A, 14, 23, 0xFDE5380C ); + P( A, B, C, D, 1, 4, 0xA4BEEA44 ); + P( D, A, B, C, 4, 11, 0x4BDECFA9 ); + P( C, D, A, B, 7, 16, 0xF6BB4B60 ); + P( B, C, D, A, 10, 23, 0xBEBFBC70 ); + P( A, B, C, D, 13, 4, 0x289B7EC6 ); + P( D, A, B, C, 0, 11, 0xEAA127FA ); + P( C, D, A, B, 3, 16, 0xD4EF3085 ); + P( B, C, D, A, 6, 23, 0x04881D05 ); + P( A, B, C, D, 9, 4, 0xD9D4D039 ); + P( D, A, B, C, 12, 11, 0xE6DB99E5 ); + P( C, D, A, B, 15, 16, 0x1FA27CF8 ); + P( B, C, D, A, 2, 23, 0xC4AC5665 ); + +#undef F + +#define F(x,y,z) (y ^ (x | ~z)) + + P( A, B, C, D, 0, 6, 0xF4292244 ); + P( D, A, B, C, 7, 10, 0x432AFF97 ); + P( C, D, A, B, 14, 15, 0xAB9423A7 ); + P( B, C, D, A, 5, 21, 0xFC93A039 ); + P( A, B, C, D, 12, 6, 0x655B59C3 ); + P( D, A, B, C, 3, 10, 0x8F0CCC92 ); + P( C, D, A, B, 10, 15, 0xFFEFF47D ); + P( B, C, D, A, 1, 21, 0x85845DD1 ); + P( A, B, C, D, 8, 6, 0x6FA87E4F ); + P( D, A, B, C, 15, 10, 0xFE2CE6E0 ); + P( C, D, A, B, 6, 15, 0xA3014314 ); + P( B, C, D, A, 13, 21, 0x4E0811A1 ); + P( A, B, C, D, 4, 6, 0xF7537E82 ); + P( D, A, B, C, 11, 10, 0xBD3AF235 ); + P( C, D, A, B, 2, 15, 0x2AD7D2BB ); + P( B, C, D, A, 9, 21, 0xEB86D391 ); + +#undef F + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; +} + +/* + * MD5 process buffer + */ +void md5_update( md5_context *ctx, unsigned char *input, int ilen ) +{ + int fill; + unsigned long left; + + if( ilen <= 0 ) + return; + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (unsigned long) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + MEMCPY( (void *) (ctx->buffer + left), + (void *) input, fill ); + md5_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + md5_process( ctx, input ); + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + MEMCPY( (void *) (ctx->buffer + left), + (void *) input, ilen ); + } +} + +static const unsigned char md5_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * MD5 final digest + */ +void md5_finish( md5_context *ctx, unsigned char output[16] ) +{ + unsigned long last, padn; + unsigned long high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_ULONG_LE( low, msglen, 0 ); + PUT_ULONG_LE( high, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + md5_update( ctx, (unsigned char *) md5_padding, padn ); + md5_update( ctx, msglen, 8 ); + + PUT_ULONG_LE( ctx->state[0], output, 0 ); + PUT_ULONG_LE( ctx->state[1], output, 4 ); + PUT_ULONG_LE( ctx->state[2], output, 8 ); + PUT_ULONG_LE( ctx->state[3], output, 12 ); +} + +/* + * output = MD5( input buffer ) + */ +void md5( unsigned char *input, int ilen, unsigned char output[16] ) +{ + md5_context ctx; + + md5_starts( &ctx ); + md5_update( &ctx, input, ilen ); + md5_finish( &ctx, output ); +} + +#endif /* PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_MD5 */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/polarssl/sha1.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/polarssl/sha1.c new file mode 100644 index 0000000..78fe46e --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/polarssl/sha1.c @@ -0,0 +1,333 @@ +/* + * FIPS-180-1 compliant SHA-1 implementation + * + * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine + * + * Copyright (C) 2009 Paul Bakker + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the names of PolarSSL or XySSL 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 HOLDERS 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 + * OWNER 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. + */ +/* + * The SHA-1 standard was published by NIST in 1993. + * + * http://www.itl.nist.gov/fipspubs/fip180-1.htm + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_SHA1 + +#include "netif/ppp/polarssl/sha1.h" + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_ULONG_BE +#define GET_ULONG_BE(n,b,i) \ +{ \ + (n) = ( (unsigned long) (b)[(i) ] << 24 ) \ + | ( (unsigned long) (b)[(i) + 1] << 16 ) \ + | ( (unsigned long) (b)[(i) + 2] << 8 ) \ + | ( (unsigned long) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_ULONG_BE +#define PUT_ULONG_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +/* + * SHA-1 context setup + */ +void sha1_starts( sha1_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + ctx->state[4] = 0xC3D2E1F0; +} + +static void sha1_process( sha1_context *ctx, unsigned char data[64] ) +{ + unsigned long temp, W[16], A, B, C, D, E; + + GET_ULONG_BE( W[ 0], data, 0 ); + GET_ULONG_BE( W[ 1], data, 4 ); + GET_ULONG_BE( W[ 2], data, 8 ); + GET_ULONG_BE( W[ 3], data, 12 ); + GET_ULONG_BE( W[ 4], data, 16 ); + GET_ULONG_BE( W[ 5], data, 20 ); + GET_ULONG_BE( W[ 6], data, 24 ); + GET_ULONG_BE( W[ 7], data, 28 ); + GET_ULONG_BE( W[ 8], data, 32 ); + GET_ULONG_BE( W[ 9], data, 36 ); + GET_ULONG_BE( W[10], data, 40 ); + GET_ULONG_BE( W[11], data, 44 ); + GET_ULONG_BE( W[12], data, 48 ); + GET_ULONG_BE( W[13], data, 52 ); + GET_ULONG_BE( W[14], data, 56 ); + GET_ULONG_BE( W[15], data, 60 ); + +#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) + +#define R(t) \ +( \ + temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ \ + W[(t - 14) & 0x0F] ^ W[ t & 0x0F], \ + ( W[t & 0x0F] = S(temp,1) ) \ +) + +#define P(a,b,c,d,e,x) \ +{ \ + e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \ +} + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + E = ctx->state[4]; + +#define F(x,y,z) (z ^ (x & (y ^ z))) +#define K 0x5A827999 + + P( A, B, C, D, E, W[0] ); + P( E, A, B, C, D, W[1] ); + P( D, E, A, B, C, W[2] ); + P( C, D, E, A, B, W[3] ); + P( B, C, D, E, A, W[4] ); + P( A, B, C, D, E, W[5] ); + P( E, A, B, C, D, W[6] ); + P( D, E, A, B, C, W[7] ); + P( C, D, E, A, B, W[8] ); + P( B, C, D, E, A, W[9] ); + P( A, B, C, D, E, W[10] ); + P( E, A, B, C, D, W[11] ); + P( D, E, A, B, C, W[12] ); + P( C, D, E, A, B, W[13] ); + P( B, C, D, E, A, W[14] ); + P( A, B, C, D, E, W[15] ); + P( E, A, B, C, D, R(16) ); + P( D, E, A, B, C, R(17) ); + P( C, D, E, A, B, R(18) ); + P( B, C, D, E, A, R(19) ); + +#undef K +#undef F + +#define F(x,y,z) (x ^ y ^ z) +#define K 0x6ED9EBA1 + + P( A, B, C, D, E, R(20) ); + P( E, A, B, C, D, R(21) ); + P( D, E, A, B, C, R(22) ); + P( C, D, E, A, B, R(23) ); + P( B, C, D, E, A, R(24) ); + P( A, B, C, D, E, R(25) ); + P( E, A, B, C, D, R(26) ); + P( D, E, A, B, C, R(27) ); + P( C, D, E, A, B, R(28) ); + P( B, C, D, E, A, R(29) ); + P( A, B, C, D, E, R(30) ); + P( E, A, B, C, D, R(31) ); + P( D, E, A, B, C, R(32) ); + P( C, D, E, A, B, R(33) ); + P( B, C, D, E, A, R(34) ); + P( A, B, C, D, E, R(35) ); + P( E, A, B, C, D, R(36) ); + P( D, E, A, B, C, R(37) ); + P( C, D, E, A, B, R(38) ); + P( B, C, D, E, A, R(39) ); + +#undef K +#undef F + +#define F(x,y,z) ((x & y) | (z & (x | y))) +#define K 0x8F1BBCDC + + P( A, B, C, D, E, R(40) ); + P( E, A, B, C, D, R(41) ); + P( D, E, A, B, C, R(42) ); + P( C, D, E, A, B, R(43) ); + P( B, C, D, E, A, R(44) ); + P( A, B, C, D, E, R(45) ); + P( E, A, B, C, D, R(46) ); + P( D, E, A, B, C, R(47) ); + P( C, D, E, A, B, R(48) ); + P( B, C, D, E, A, R(49) ); + P( A, B, C, D, E, R(50) ); + P( E, A, B, C, D, R(51) ); + P( D, E, A, B, C, R(52) ); + P( C, D, E, A, B, R(53) ); + P( B, C, D, E, A, R(54) ); + P( A, B, C, D, E, R(55) ); + P( E, A, B, C, D, R(56) ); + P( D, E, A, B, C, R(57) ); + P( C, D, E, A, B, R(58) ); + P( B, C, D, E, A, R(59) ); + +#undef K +#undef F + +#define F(x,y,z) (x ^ y ^ z) +#define K 0xCA62C1D6 + + P( A, B, C, D, E, R(60) ); + P( E, A, B, C, D, R(61) ); + P( D, E, A, B, C, R(62) ); + P( C, D, E, A, B, R(63) ); + P( B, C, D, E, A, R(64) ); + P( A, B, C, D, E, R(65) ); + P( E, A, B, C, D, R(66) ); + P( D, E, A, B, C, R(67) ); + P( C, D, E, A, B, R(68) ); + P( B, C, D, E, A, R(69) ); + P( A, B, C, D, E, R(70) ); + P( E, A, B, C, D, R(71) ); + P( D, E, A, B, C, R(72) ); + P( C, D, E, A, B, R(73) ); + P( B, C, D, E, A, R(74) ); + P( A, B, C, D, E, R(75) ); + P( E, A, B, C, D, R(76) ); + P( D, E, A, B, C, R(77) ); + P( C, D, E, A, B, R(78) ); + P( B, C, D, E, A, R(79) ); + +#undef K +#undef F + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; + ctx->state[4] += E; +} + +/* + * SHA-1 process buffer + */ +void sha1_update( sha1_context *ctx, unsigned char *input, int ilen ) +{ + int fill; + unsigned long left; + + if( ilen <= 0 ) + return; + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (unsigned long) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + MEMCPY( (void *) (ctx->buffer + left), + (void *) input, fill ); + sha1_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + sha1_process( ctx, input ); + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + MEMCPY( (void *) (ctx->buffer + left), + (void *) input, ilen ); + } +} + +static const unsigned char sha1_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * SHA-1 final digest + */ +void sha1_finish( sha1_context *ctx, unsigned char output[20] ) +{ + unsigned long last, padn; + unsigned long high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_ULONG_BE( high, msglen, 0 ); + PUT_ULONG_BE( low, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + sha1_update( ctx, (unsigned char *) sha1_padding, padn ); + sha1_update( ctx, msglen, 8 ); + + PUT_ULONG_BE( ctx->state[0], output, 0 ); + PUT_ULONG_BE( ctx->state[1], output, 4 ); + PUT_ULONG_BE( ctx->state[2], output, 8 ); + PUT_ULONG_BE( ctx->state[3], output, 12 ); + PUT_ULONG_BE( ctx->state[4], output, 16 ); +} + +/* + * output = SHA-1( input buffer ) + */ +void sha1( unsigned char *input, int ilen, unsigned char output[20] ) +{ + sha1_context ctx; + + sha1_starts( &ctx ); + sha1_update( &ctx, input, ilen ); + sha1_finish( &ctx, output ); +} + +#endif /* PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_SHA1 */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/ppp.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/ppp.c new file mode 100644 index 0000000..bc85396 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/ppp.c @@ -0,0 +1,2606 @@ +/***************************************************************************** +* ppp.c - Network Point to Point Protocol program file. +* +* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. +* portions Copyright (c) 1997 by Global Election Systems Inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 03-01-01 Marc Boucher +* Ported to lwIP. +* 97-11-05 Guy Lancaster , Global Election Systems Inc. +* Original. +*****************************************************************************/ + +/* + * ppp_defs.h - PPP definitions. + * + * if_pppvar.h - private structures and declarations for PPP. + * + * Copyright (c) 1994 The Australian National University. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, provided that the above copyright + * notice appears in all copies. This software is provided without any + * warranty, express or implied. The Australian National University + * makes no representations about the suitability of this software for + * any purpose. + * + * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY + * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO + * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, + * OR MODIFICATIONS. + */ + +/* + * if_ppp.h - Point-to-Point Protocol definitions. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/stats.h" +#include "lwip/sys.h" +#include "lwip/tcpip.h" +#include "lwip/api.h" +#include "lwip/snmp.h" +#include "lwip/sio.h" +#include "lwip/sys.h" +#include "lwip/ip.h" /* for ip_input() */ + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/fsm.h" +#include "netif/ppp/lcp.h" +#include "netif/ppp/ipcp.h" +#include "netif/ppp/magic.h" + +#if PAP_SUPPORT +#include "netif/ppp/upap.h" +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT +#include "netif/ppp/chap-new.h" +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT +#include "netif/ppp/eap.h" +#endif /* EAP_SUPPORT */ +#if CCP_SUPPORT +#include "netif/ppp/ccp.h" +#endif /* EAP_SUPPORT */ +#if ECP_SUPPORT +#include "netif/ppp/ecp.h" +#endif /* EAP_SUPPORT */ +#if VJ_SUPPORT +#include "netif/ppp/vj.h" +#endif /* VJ_SUPPORT */ +#if PPP_IPV6_SUPPORT +#include "netif/ppp/ipv6cp.h" +#endif /* PPP_IPV6_SUPPORT */ + +#if PPPOE_SUPPORT +#include "netif/ppp/pppoe.h" +#endif /* PPPOE_SUPPORT */ +#if PPPOL2TP_SUPPORT +#include "netif/ppp/pppol2tp.h" +#endif /* PPPOL2TP_SUPPORT */ + +/* Global variables */ + +#if PPP_DEBUG +u8_t ppp_num; /* PPP Interface counter, used for debugging messages */ +#endif /* PPP_DEBUG */ + +/*************************/ +/*** LOCAL DEFINITIONS ***/ +/*************************/ + +/* FIXME: add stats per PPP session */ +#if PPP_STATS_SUPPORT +static struct timeval start_time; /* Time when link was started. */ +static struct pppd_stats old_link_stats; +struct pppd_stats link_stats; +unsigned link_connect_time; +int link_stats_valid; +#endif /* PPP_STATS_SUPPORT */ + +/* + * PPP Data Link Layer "protocol" table. + * One entry per supported protocol. + * The last entry must be NULL. + */ +const struct protent* const protocols[] = { + &lcp_protent, +#if PAP_SUPPORT + &pap_protent, +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + &chap_protent, +#endif /* CHAP_SUPPORT */ +#if CBCP_SUPPORT + &cbcp_protent, +#endif + &ipcp_protent, +#if PPP_IPV6_SUPPORT + &ipv6cp_protent, +#endif +#if CCP_SUPPORT + &ccp_protent, +#endif /* CCP_SUPPORT */ +#if ECP_SUPPORT + &ecp_protent, +#endif /* ECP_SUPPORT */ +#ifdef AT_CHANGE + &atcp_protent, +#endif +#if EAP_SUPPORT + &eap_protent, +#endif /* EAP_SUPPORT */ + NULL +}; + +/* Prototypes for procedures local to this file. */ +static void ppp_clear(ppp_pcb *pcb); +static void ppp_do_open(void *arg); +static void ppp_start(ppp_pcb *pcb); /** Initiate LCP open request */ +static void ppp_stop(ppp_pcb *pcb); +static void ppp_hup(ppp_pcb *pcb); + +static err_t ppp_netif_init_cb(struct netif *netif); +static err_t ppp_netif_output_ip4(struct netif *netif, struct pbuf *pb, ip_addr_t *ipaddr); +#if PPP_IPV6_SUPPORT +static err_t ppp_netif_output_ip6(struct netif *netif, struct pbuf *pb, ip6_addr_t *ipaddr); +#endif /* PPP_IPV6_SUPPORT */ +static err_t ppp_netif_output(struct netif *netif, struct pbuf *pb, u_short protocol); + +#if PPPOS_SUPPORT +#define ESCAPE_P(accm, c) ((accm)[(c) >> 3] & ppp_accm_mask[c & 0x07]) +static void ppp_over_serial_open(ppp_pcb *pcb); +static err_t ppp_netif_output_over_serial(ppp_pcb *pcb, struct pbuf *pb, u_short protocol); +static int ppp_write_over_serial(ppp_pcb *pcb, struct pbuf *p); +static void ppp_drop(ppp_pcb_rx *pcrx); +#if PPP_INPROC_MULTITHREADED +static void pppos_input_callback(void *arg); +#endif /* PPP_INPROC_MULTITHREADED */ +static void ppp_free_current_input_packet(ppp_pcb_rx *pcrx); +#endif /* PPPOS_SUPPORT */ + +#if PPPOE_SUPPORT +static void ppp_over_ethernet_open(ppp_pcb *pcb); +static err_t ppp_netif_output_over_ethernet(ppp_pcb *pcb, struct pbuf *p, u_short protocol); +static int ppp_write_over_ethernet(ppp_pcb *pcb, struct pbuf *p); +#endif /* PPPOE_SUPPORT */ + +#if PPPOL2TP_SUPPORT +static void ppp_over_l2tp_open(ppp_pcb *pcb); +static err_t ppp_netif_output_over_l2tp(ppp_pcb *pcb, struct pbuf *p, u_short protocol); +static int ppp_write_over_l2tp(ppp_pcb *pcb, struct pbuf *p); +#endif /* PPPOL2TP_SUPPORT */ + +/***********************************/ +/*** PUBLIC FUNCTION DEFINITIONS ***/ +/***********************************/ + +/* Initialize the PPP subsystem. */ +int ppp_init(void) { + + /* + * Initialize magic number generator now so that protocols may + * use magic numbers in initialization. + */ + magic_init(); + + return 0; +} + +/* Create a new PPP session. */ +ppp_pcb *ppp_new(void) { + ppp_pcb *pcb; + + pcb = (ppp_pcb*)memp_malloc(MEMP_PPP_PCB); + if (pcb == NULL) { + return NULL; + } + + memset(pcb, 0, sizeof(ppp_pcb)); +#if PPP_DEBUG + pcb->num = ppp_num++; +#endif /* PPP_DEBUG */ + + /* default configuration */ + pcb->settings.usepeerdns = 1; + +#if PAP_SUPPORT + pcb->settings.pap_timeout_time = UPAP_DEFTIMEOUT; + pcb->settings.pap_max_transmits = UPAP_DEFTRANSMITS; +#if PPP_SERVER + pcb->settings.pap_req_timeout = UPAP_DEFREQTIME; +#endif /* PPP_SERVER */ +#endif /* PAP_SUPPORT */ + +#if CHAP_SUPPORT + pcb->settings.chap_timeout_time = CHAP_DEFTIMEOUT; + pcb->settings.chap_max_transmits = CHAP_DEFTRANSMITS; +#if PPP_SERVER + pcb->settings.chap_rechallenge_time = CHAP_DEFREQTIME; +#endif /* PPP_SERVER */ +#endif /* CHAP_SUPPPORT */ + +#if EAP_SUPPORT + pcb->settings.eap_req_time = EAP_DEFREQTIME; + pcb->settings.eap_allow_req = EAP_DEFALLOWREQ; +#if PPP_SERVER + pcb->settings.eap_timeout_time = EAP_DEFTIMEOUT; + pcb->settings.eap_max_transmits = EAP_DEFTRANSMITS; +#endif /* PPP_SERVER */ +#endif /* EAP_SUPPORT */ + + pcb->settings.lcp_loopbackfail = LCP_DEFLOOPBACKFAIL; + pcb->settings.lcp_echo_interval = LCP_ECHOINTERVAL; + pcb->settings.lcp_echo_fails = LCP_MAXECHOFAILS; + + pcb->settings.fsm_timeout_time = FSM_DEFTIMEOUT; + pcb->settings.fsm_max_conf_req_transmits = FSM_DEFMAXCONFREQS; + pcb->settings.fsm_max_term_transmits = FSM_DEFMAXTERMREQS; + pcb->settings.fsm_max_nak_loops = FSM_DEFMAXNAKLOOPS; + + if (!netif_add(&pcb->netif, &pcb->addrs.our_ipaddr, &pcb->addrs.netmask, + &pcb->addrs.his_ipaddr, (void *)pcb, ppp_netif_init_cb, NULL)) { + memp_free(MEMP_PPP_PCB, pcb); + PPPDEBUG(LOG_ERR, ("ppp_new[%d]: netif_add failed\n", pcb->num)); + return NULL; + } + + new_phase(pcb, PPP_PHASE_DEAD); + return pcb; +} + +void ppp_set_default(ppp_pcb *pcb) { + netif_set_default(&pcb->netif); +} + +void ppp_set_auth(ppp_pcb *pcb, u8_t authtype, const char *user, const char *passwd) { + +#if PAP_SUPPORT + if (authtype & PPPAUTHTYPE_PAP) { + pcb->settings.refuse_pap = 0; + } else { + pcb->settings.refuse_pap = 1; + } +#endif /* PAP_SUPPORT */ + +#if CHAP_SUPPORT + if (authtype & PPPAUTHTYPE_CHAP) { + pcb->settings.refuse_chap = 0; + } else { + pcb->settings.refuse_chap = 1; + } +#if MSCHAP_SUPPORT + if (authtype & PPPAUTHTYPE_MSCHAP) { + pcb->settings.refuse_mschap = 0; + pcb->settings.refuse_mschap_v2 = 0; + } else { + pcb->settings.refuse_mschap = 1; + pcb->settings.refuse_mschap_v2 = 1; + } +#endif /* MSCHAP_SUPPORT */ +#endif /* CHAP_SUPPORT */ + +#if EAP_SUPPORT + if (authtype & PPPAUTHTYPE_EAP) { + pcb->settings.refuse_eap = 0; + } else { + pcb->settings.refuse_eap = 1; + } +#endif /* EAP_SUPPORT */ + + if (user) { + pcb->settings.user = user; + } + + if (passwd) { + pcb->settings.passwd = passwd; + } +} + +#if PPP_NOTIFY_PHASE +void ppp_set_notify_phase_callback(ppp_pcb *pcb, ppp_notify_phase_cb_fn notify_phase_cb) { + pcb->notify_phase_cb = notify_phase_cb; + notify_phase_cb(pcb, pcb->phase, pcb->ctx_cb); +} +#endif /* PPP_NOTIFY_PHASE */ + +#if PPPOS_SUPPORT +int ppp_over_serial_create(ppp_pcb *pcb, sio_fd_t fd, ppp_link_status_cb_fn link_status_cb, void *ctx_cb) { + + /* PPP is single-threaded: without a callback, + * there is no way to know when the link is up. */ + if (link_status_cb == NULL) { + return PPPERR_PARAM; + } + + pcb->fd = fd; + pcb->link_status_cb = link_status_cb; + pcb->ctx_cb = ctx_cb; + return PPPERR_NONE; +} + +/* + * ppp_set_xaccm - set the extended transmit ACCM for the interface. + */ +void ppp_set_xaccm(ppp_pcb *pcb, ext_accm *accm) { + SMEMCPY(pcb->out_accm, accm, sizeof(ext_accm)); + PPPDEBUG(LOG_INFO, ("ppp_set_xaccm[%d]: out_accm=%X %X %X %X\n", + pcb->num, + pcb->out_accm[0], + pcb->out_accm[1], + pcb->out_accm[2], + pcb->out_accm[3])); +} +#endif /* PPPOS_SUPPORT */ + +#if PPPOE_SUPPORT +static void ppp_over_ethernet_link_status_cb(ppp_pcb *pcb, int state); + +int ppp_over_ethernet_create(ppp_pcb *pcb, struct netif *ethif, const char *service_name, const char *concentrator_name, + ppp_link_status_cb_fn link_status_cb, void *ctx_cb) { + + LWIP_UNUSED_ARG(service_name); + LWIP_UNUSED_ARG(concentrator_name); + + /* PPP is single-threaded: without a callback, + * there is no way to know when the link is up. */ + if (link_status_cb == NULL) { + return PPPERR_PARAM; + } + + pcb->link_status_cb = link_status_cb; + pcb->ctx_cb = ctx_cb; + + if (pppoe_create(ethif, pcb, ppp_over_ethernet_link_status_cb, &pcb->pppoe_sc) != ERR_OK) { + return PPPERR_OPEN; + } + + return PPPERR_NONE; +} +#endif /* PPPOE_SUPPORT */ + +#if PPPOL2TP_SUPPORT +static void ppp_over_l2tp_link_status_cb(ppp_pcb *pcb, int state); + +int ppp_over_l2tp_create(ppp_pcb *pcb, struct netif *netif, ip_addr_t *ipaddr, u16_t port, + u8_t *secret, u8_t secret_len, + ppp_link_status_cb_fn link_status_cb, void *ctx_cb) { + + /* PPP is single-threaded: without a callback, + * there is no way to know when the link is up. */ + if (link_status_cb == NULL) { + return PPPERR_PARAM; + } + + pcb->link_status_cb = link_status_cb; + pcb->ctx_cb = ctx_cb; + + if (pppol2tp_create(pcb, ppp_over_l2tp_link_status_cb, &pcb->l2tp_pcb, netif, ipaddr, port, secret, secret_len) != ERR_OK) { + return PPPERR_OPEN; + } + + return PPPERR_NONE; +} +#endif /* PPPOL2TP_SUPPORT */ + +/* + * Open a PPP connection. + * + * This can only be called if PPP is in the dead phase. + * + * Holdoff is the time to wait (in seconds) before initiating + * the connection. + */ +int ppp_open(ppp_pcb *pcb, u16_t holdoff) { + if (pcb->phase != PPP_PHASE_DEAD) { + return PPPERR_PARAM; + } + + PPPDEBUG(LOG_DEBUG, ("ppp_open() called, holdoff=%d\n", holdoff)); + + if (holdoff == 0) { + ppp_do_open(pcb); + return PPPERR_NONE; + } + + new_phase(pcb, PPP_PHASE_HOLDOFF); + sys_timeout((u32_t)(holdoff*1000), ppp_do_open, pcb); + return PPPERR_NONE; +} + +/* + * Initiate the end of a PPP connection. + * Any outstanding packets in the queues are dropped. + * Return 0 on success, an error code on failure. + */ +int +ppp_close(ppp_pcb *pcb) +{ + int st = 0; + + pcb->err_code = PPPERR_USER; + + /* dead phase, nothing to do, call the status callback to be consistent */ + if (pcb->phase == PPP_PHASE_DEAD) { + pcb->link_status_cb(pcb, pcb->err_code, pcb->ctx_cb); + return PPPERR_NONE; + } + + /* holdoff phase, cancel the reconnection and call the status callback */ + if (pcb->phase == PPP_PHASE_HOLDOFF) { + sys_untimeout(ppp_do_open, pcb); + pcb->link_status_cb(pcb, pcb->err_code, pcb->ctx_cb); + return PPPERR_NONE; + } + + PPPDEBUG(LOG_DEBUG, ("ppp_close() called\n")); + + /* Disconnect */ +#if PPPOE_SUPPORT + if (pcb->pppoe_sc) { + PPPDEBUG(LOG_DEBUG, ("ppp_close: unit %d kill_link -> ppp_stop\n", pcb->num)); + /* This will leave us at PPP_PHASE_DEAD. */ + ppp_stop(pcb); + } else +#endif /* PPPOE_SUPPORT */ +#if PPPOL2TP_SUPPORT + if (pcb->l2tp_pcb) { + PPPDEBUG(LOG_DEBUG, ("ppp_close: unit %d kill_link -> ppp_stop\n", pcb->num)); + /* This will leave us at PPP_PHASE_DEAD. */ + ppp_stop(pcb); + } else +#endif /* PPPOL2TP_SUPPORT */ + { +#if PPPOS_SUPPORT + PPPDEBUG(LOG_DEBUG, ("ppp_close: unit %d kill_link -> ppp_stop\n", pcb->num)); + /* This will leave us at PPP_PHASE_DEAD. */ + ppp_stop(pcb); +#endif /* PPPOS_SUPPORT */ + } + + return st; +} + +/* This function is called when carrier is lost on the PPP channel. */ +void +ppp_sighup(ppp_pcb *pcb) +{ + PPPDEBUG(LOG_DEBUG, ("ppp_sighup: unit %d sig_hup -> ppp_hup\n", pcb->num)); + ppp_hup(pcb); +} + +/* + * Free the control block, clean everything except the PPP PCB itself + * and the netif, it allows you to change the underlying PPP protocol + * (eg. from PPPoE to PPPoS to switch from DSL to GPRS) without losing + * your PPP and netif handlers. + * + * This can only be called if PPP is in the dead phase. + * + * You must use ppp_close() before if you wish to terminate + * an established PPP session. + * + * Return 0 on success, an error code on failure. + */ +int ppp_free(ppp_pcb *pcb) { + if (pcb->phase != PPP_PHASE_DEAD) { + return PPPERR_PARAM; + } + + PPPDEBUG(LOG_DEBUG, ("ppp_free: unit %d\n", pcb->num)); + +#if PPPOE_SUPPORT + if (pcb->pppoe_sc) { + pppoe_destroy(pcb->pppoe_sc); + pcb->pppoe_sc = NULL; + } +#endif /* PPPOE_SUPPORT */ + +#if PPPOL2TP_SUPPORT + if (pcb->l2tp_pcb) { + pppol2tp_destroy(pcb->l2tp_pcb); + pcb->l2tp_pcb = NULL; + } +#endif /* PPPOL2TP_SUPPORT */ + +#if PPPOS_SUPPORT + /* input pbuf left ? */ + ppp_free_current_input_packet(&pcb->rx); +#endif /* PPPOS_SUPPORT */ + + return 0; +} + +/* + * Release the control block. + * + * This can only be called if PPP is in the dead phase. + * + * You must use ppp_close() before if you wish to terminate + * an established PPP session. + * + * Return 0 on success, an error code on failure. + */ +int ppp_delete(ppp_pcb *pcb) { + int err; + + if (pcb->phase != PPP_PHASE_DEAD) { + return PPPERR_PARAM; + } + + PPPDEBUG(LOG_DEBUG, ("ppp_delete: unit %d\n", pcb->num)); + + netif_remove(&pcb->netif); + if( (err = ppp_free(pcb)) != PPPERR_NONE) { + return err; + } + + memp_free(MEMP_PPP_PCB, pcb); + return 0; +} + + + + +/************************************/ +/*** PRIVATE FUNCTION DEFINITIONS ***/ +/************************************/ + +/* Set a PPP PCB to its initial state */ +static void ppp_clear(ppp_pcb *pcb) { + const struct protent *protp; + int i; + + LWIP_ASSERT("pcb->phase == PPP_PHASE_DEAD || pcb->phase == PPP_PHASE_HOLDOFF", pcb->phase == PPP_PHASE_DEAD || pcb->phase == PPP_PHASE_HOLDOFF); + +#if PPP_STATS_SUPPORT + link_stats_valid = 0; +#endif /* PPP_STATS_SUPPORT */ + + memset(&pcb->phase, 0, sizeof(ppp_pcb) - ( (char*)&((ppp_pcb*)0)->phase - (char*)0 ) ); + IP4_ADDR(&pcb->addrs.netmask, 255,255,255,255); + + /* + * Initialize each protocol. + */ + for (i = 0; (protp = protocols[i]) != NULL; ++i) { + (*protp->init)(pcb); + } + + new_phase(pcb, PPP_PHASE_INITIALIZE); +} + +static void ppp_do_open(void *arg) { + ppp_pcb *pcb = (ppp_pcb*)arg; + + LWIP_ASSERT("pcb->phase == PPP_PHASE_DEAD || pcb->phase == PPP_PHASE_HOLDOFF", pcb->phase == PPP_PHASE_DEAD || pcb->phase == PPP_PHASE_HOLDOFF); + +#if PPPOE_SUPPORT + if (pcb->pppoe_sc) { + ppp_over_ethernet_open(pcb); + return; + } +#endif /* PPPOE_SUPPORT */ + +#if PPPOL2TP_SUPPORT + if (pcb->l2tp_pcb) { + ppp_over_l2tp_open(pcb); + return; + } +#endif /* PPPOL2TP_SUPPORT */ + +#if PPPOS_SUPPORT + ppp_over_serial_open(pcb); +#endif /* PPPOS_SUPPORT */ +} + +/** Initiate LCP open request */ +static void ppp_start(ppp_pcb *pcb) { + PPPDEBUG(LOG_DEBUG, ("ppp_start: unit %d\n", pcb->num)); + lcp_open(pcb); /* Start protocol */ + lcp_lowerup(pcb); + PPPDEBUG(LOG_DEBUG, ("ppp_start: finished\n")); +} + +/** LCP close request */ +static void ppp_stop(ppp_pcb *pcb) { + PPPDEBUG(LOG_DEBUG, ("ppp_stop: unit %d\n", pcb->num)); + lcp_close(pcb, "User request"); +} + +/** Called when carrier/link is lost */ +static void ppp_hup(ppp_pcb *pcb) { + PPPDEBUG(LOG_DEBUG, ("ppp_hup: unit %d\n", pcb->num)); + lcp_lowerdown(pcb); + link_terminated(pcb); +} + +/* + * Pass the processed input packet to the appropriate handler. + * This function and all handlers run in the context of the tcpip_thread + */ +void ppp_input(ppp_pcb *pcb, struct pbuf *pb) { + u16_t protocol; + + protocol = (((u8_t *)pb->payload)[0] << 8) | ((u8_t*)pb->payload)[1]; + +#if PRINTPKT_SUPPORT + ppp_dump_packet("rcvd", (unsigned char *)pb->payload, pb->len); +#endif /* PRINTPKT_SUPPORT */ + + if(pbuf_header(pb, -(s16_t)sizeof(protocol))) { + LWIP_ASSERT("pbuf_header failed\n", 0); + goto drop; + } + + LINK_STATS_INC(link.recv); + snmp_inc_ifinucastpkts(&pcb->netif); + snmp_add_ifinoctets(&pcb->netif, pb->tot_len); + + /* + * Toss all non-LCP packets unless LCP is OPEN. + */ + if (protocol != PPP_LCP && pcb->lcp_fsm.state != PPP_FSM_OPENED) { + ppp_dbglog("Discarded non-LCP packet when LCP not open"); + goto drop; + } + + /* + * Until we get past the authentication phase, toss all packets + * except LCP, LQR and authentication packets. + */ + if (pcb->phase <= PPP_PHASE_AUTHENTICATE + && !(protocol == PPP_LCP +#if LQR_SUPPORT + || protocol == PPP_LQR +#endif /* LQR_SUPPORT */ +#if PAP_SUPPORT + || protocol == PPP_PAP +#endif /* PAP_SUPPORT */ +#if CHAP_SUPPORT + || protocol == PPP_CHAP +#endif /* CHAP_SUPPORT */ +#if EAP_SUPPORT + || protocol == PPP_EAP +#endif /* EAP_SUPPORT */ + )) { + ppp_dbglog("discarding proto 0x%x in phase %d", + protocol, pcb->phase); + goto drop; + } + + /* FIXME: should we write protent to do that ? */ + + switch(protocol) { + +#if VJ_SUPPORT + case PPP_VJC_COMP: /* VJ compressed TCP */ + PPPDEBUG(LOG_INFO, ("ppp_input[%d]: vj_comp in pbuf len=%d\n", pcb->num, pb->len)); + /* + * Clip off the VJ header and prepend the rebuilt TCP/IP header and + * pass the result to IP. + */ + if (vj_uncompress_tcp(&pb, &pcb->vj_comp) >= 0) { + ip_input(pb, &pcb->netif); + return; + } + /* Something's wrong so drop it. */ + PPPDEBUG(LOG_WARNING, ("ppp_input[%d]: Dropping VJ compressed\n", pcb->num)); + break; + + case PPP_VJC_UNCOMP: /* VJ uncompressed TCP */ + PPPDEBUG(LOG_INFO, ("ppp_input[%d]: vj_un in pbuf len=%d\n", pcb->num, pb->len)); + /* + * Process the TCP/IP header for VJ header compression and then pass + * the packet to IP. + */ + if (vj_uncompress_uncomp(pb, &pcb->vj_comp) >= 0) { + ip_input(pb, &pcb->netif); + return; + } + /* Something's wrong so drop it. */ + PPPDEBUG(LOG_WARNING, ("ppp_input[%d]: Dropping VJ uncompressed\n", pcb->num)); + break; +#endif /* VJ_SUPPORT */ + + case PPP_IP: /* Internet Protocol */ + PPPDEBUG(LOG_INFO, ("ppp_input[%d]: ip in pbuf len=%d\n", pcb->num, pb->len)); + ip_input(pb, &pcb->netif); + return; + +#if PPP_IPV6_SUPPORT + case PPP_IPV6: /* Internet Protocol Version 6 */ + PPPDEBUG(LOG_INFO, ("ppp_input[%d]: ip6 in pbuf len=%d\n", pcb->num, pb->len)); + ip6_input(pb, &pcb->netif); + return; +#endif /* PPP_IPV6_SUPPORT */ + + default: { + + int i; + const struct protent *protp; + /* + * Upcall the proper protocol input routine. + */ + for (i = 0; (protp = protocols[i]) != NULL; ++i) { + if (protp->protocol == protocol && protp->enabled_flag) { + pb = ppp_singlebuf(pb); + (*protp->input)(pcb, (u_char*)pb->payload, pb->len); + goto out; + } +#if 0 /* UNUSED + * + * This is actually a (hacked?) way for the PPP kernel implementation to pass a + * data packet to the PPP daemon. The PPP daemon normally only do signaling + * (LCP, PAP, CHAP, IPCP, ...) and does not handle any data packet at all. + * + * This is only used by CCP, which we cannot support until we have a CCP data + * implementation. + */ + if (protocol == (protp->protocol & ~0x8000) && protp->enabled_flag + && protp->datainput != NULL) { + (*protp->datainput)(pcb, pb->payload, pb->len); + goto out; + } +#endif /* UNUSED */ + } + +#if PPP_DEBUG +#if PPP_PROTOCOLNAME + const char *pname = protocol_name(protocol); + if (pname != NULL) { + ppp_warn("Unsupported protocol '%s' (0x%x) received", pname, protocol); + } else +#endif /* PPP_PROTOCOLNAME */ + ppp_warn("Unsupported protocol 0x%x received", protocol); +#endif /* PPP_DEBUG */ + if (pbuf_header(pb, (s16_t)sizeof(protocol))) { + LWIP_ASSERT("pbuf_header failed\n", 0); + goto drop; + } + lcp_sprotrej(pcb, (u_char*)pb->payload, pb->len); + } + break; + } + +drop: + LINK_STATS_INC(link.drop); + snmp_inc_ifindiscards(&pcb->netif); + +out: + pbuf_free(pb); + magic_randomize(); + return; +} + +#if PPPOS_SUPPORT +#if PPP_FCS_TABLE +/* + * FCS lookup table as calculated by genfcstab. + */ +static const u_short fcstab[256] = { + 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, + 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, + 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, + 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, + 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, + 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, + 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, + 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, + 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, + 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, + 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, + 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, + 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, + 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, + 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, + 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, + 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, + 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, + 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, + 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, + 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, + 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, + 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, + 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, + 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, + 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, + 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, + 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, + 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, + 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, + 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 +}; +#else /* PPP_FCS_TABLE */ +/* The HDLC polynomial: X**0 + X**5 + X**12 + X**16 (0x8408) */ +#define PPP_FCS_POLYNOMIAL 0x8408 +u16_t ppp_get_fcs(u8_t byte) { + unsigned int octet; + int bit; + octet = byte; + for (bit = 8; bit-- > 0; ) { + octet = (octet & 0x01) ? ((octet >> 1) ^ PPP_FCS_POLYNOMIAL) : (octet >> 1); + } + return octet & 0xffff; +} +#endif /* PPP_FCS_TABLE */ + +/* PPP's Asynchronous-Control-Character-Map. The mask array is used + * to select the specific bit for a character. */ +static u_char ppp_accm_mask[] = { + 0x01, + 0x02, + 0x04, + 0x08, + 0x10, + 0x20, + 0x40, + 0x80 +}; +#endif /* PPPOS_SUPPORT */ + +/* + * ppp_netif_init_cb - netif init callback + */ +static err_t ppp_netif_init_cb(struct netif *netif) { + netif->name[0] = 'p'; + netif->name[1] = 'p'; + netif->output = ppp_netif_output_ip4; +#if PPP_IPV6_SUPPORT + netif->output_ip6 = ppp_netif_output_ip6; +#endif /* PPP_IPV6_SUPPORT */ + netif->flags = NETIF_FLAG_POINTTOPOINT | NETIF_FLAG_LINK_UP; +#if LWIP_NETIF_HOSTNAME + /* @todo: Initialize interface hostname */ + /* netif_set_hostname(netif, "lwip"); */ +#endif /* LWIP_NETIF_HOSTNAME */ + return ERR_OK; +} + + +/**********************************/ +/*** LOCAL FUNCTION DEFINITIONS ***/ +/**********************************/ + +#if PPPOS_SUPPORT +static void ppp_over_serial_open(ppp_pcb *pcb) { + + /* input pbuf left over from last session? */ + ppp_free_current_input_packet(&pcb->rx); + + ppp_clear(pcb); + + pcb->rx.pcb = pcb; + pcb->rx.fd = pcb->fd; + +#if VJ_SUPPORT + vj_compress_init(&pcb->vj_comp); +#endif /* VJ_SUPPORT */ + + /* + * Default the in and out accm so that escape and flag characters + * are always escaped. + */ + pcb->rx.in_accm[15] = 0x60; /* no need to protect since RX is not running */ + pcb->out_accm[15] = 0x60; + + /* + * Start the connection and handle incoming events (packet or timeout). + */ + PPPDEBUG(LOG_INFO, ("ppp_over_serial_open: unit %d: connecting\n", pcb->num)); + ppp_start(pcb); +} + +static void +pppos_put(ppp_pcb *pcb, struct pbuf *nb) +{ + struct pbuf *b; + int c; + + for(b = nb; b != NULL; b = b->next) { + c = sio_write(pcb->fd, (u8_t*)b->payload, b->len); + if(c != b->len) { + PPPDEBUG(LOG_WARNING, + ("PPP pppos_put: incomplete sio_write(fd:%"SZT_F", len:%d, c: 0x%"X8_F") c = %d\n", (size_t)pcb->fd, b->len, c, c)); + LINK_STATS_INC(link.err); + pcb->last_xmit = 0; /* prepend PPP_FLAG to next packet */ + snmp_inc_ifoutdiscards(&pcb->netif); + pbuf_free(nb); + return; + } + } + + snmp_add_ifoutoctets(&pcb->netif, nb->tot_len); + snmp_inc_ifoutucastpkts(&pcb->netif); + pbuf_free(nb); + LINK_STATS_INC(link.xmit); +} + +/* + * ppp_append - append given character to end of given pbuf. If out_accm + * is not NULL and the character needs to be escaped, do so. + * If pbuf is full, append another. + * Return the current pbuf. + */ +static struct pbuf * +ppp_append(u_char c, struct pbuf *nb, ext_accm *out_accm) +{ + struct pbuf *tb = nb; + + /* Make sure there is room for the character and an escape code. + * Sure we don't quite fill the buffer if the character doesn't + * get escaped but is one character worth complicating this? */ + /* Note: We assume no packet header. */ + if (nb && (PBUF_POOL_BUFSIZE - nb->len) < 2) { + tb = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); + if (tb) { + nb->next = tb; + } else { + LINK_STATS_INC(link.memerr); + } + nb = tb; + } + + if (nb) { + if (out_accm && ESCAPE_P(*out_accm, c)) { + *((u_char*)nb->payload + nb->len++) = PPP_ESCAPE; + *((u_char*)nb->payload + nb->len++) = c ^ PPP_TRANS; + } else { + *((u_char*)nb->payload + nb->len++) = c; + } + } + + return tb; +} +#endif /* PPPOS_SUPPORT */ + + +/* Send a IPv4 packet on the given connection. + */ +static err_t ppp_netif_output_ip4(struct netif *netif, struct pbuf *pb, ip_addr_t *ipaddr) { + LWIP_UNUSED_ARG(ipaddr); + return ppp_netif_output(netif, pb, PPP_IP); +} + +#if PPP_IPV6_SUPPORT +/* Send a IPv6 packet on the given connection. + */ +static err_t ppp_netif_output_ip6(struct netif *netif, struct pbuf *pb, ip6_addr_t *ipaddr) { + LWIP_UNUSED_ARG(ipaddr); + return ppp_netif_output(netif, pb, PPP_IPV6); +} +#endif /* PPP_IPV6_SUPPORT */ + +/* Send a packet on the given connection. + * + * This is the low level function that send the PPP packet, + * only for IPv4 and IPv6 packets coming from lwIP. + */ +static err_t ppp_netif_output(struct netif *netif, struct pbuf *pb, u_short protocol) { + ppp_pcb *pcb = (ppp_pcb*)netif->state; + + /* Validate parameters. */ + /* We let any protocol value go through - it can't hurt us + * and the peer will just drop it if it's not accepting it. */ + if (!pcb || !pb) { + PPPDEBUG(LOG_WARNING, ("ppp_netif_output[%d]: bad params prot=%d pb=%p\n", + pcb->num, PPP_IP, (void*)pb)); + LINK_STATS_INC(link.opterr); + LINK_STATS_INC(link.drop); + snmp_inc_ifoutdiscards(netif); + return ERR_ARG; + } + + /* Check that the link is up. */ + if (!pcb->if_up) { + PPPDEBUG(LOG_ERR, ("ppp_netif_output[%d]: link not up\n", pcb->num)); + LINK_STATS_INC(link.rterr); + LINK_STATS_INC(link.drop); + snmp_inc_ifoutdiscards(netif); + return ERR_RTE; + } + +#if PPPOE_SUPPORT + if(pcb->pppoe_sc) { + return ppp_netif_output_over_ethernet(pcb, pb, protocol); + } +#endif /* PPPOE_SUPPORT */ + +#if PPPOL2TP_SUPPORT + if(pcb->l2tp_pcb) { + return ppp_netif_output_over_l2tp(pcb, pb, protocol); + } +#endif /* PPPOL2TP_SUPPORT */ + +#if PPPOS_SUPPORT + return ppp_netif_output_over_serial(pcb, pb, protocol); +#endif /* PPPOS_SUPPORT */ + +#if !PPPOS_SUPPORT + return ERR_OK; +#endif +} + +#if PPPOS_SUPPORT +static err_t ppp_netif_output_over_serial(ppp_pcb *pcb, struct pbuf *pb, u_short protocol) { + u_int fcs_out = PPP_INITFCS; + struct pbuf *head = NULL, *tail = NULL, *p; + u_char c; + + /* Grab an output buffer. */ + head = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); + if (head == NULL) { + PPPDEBUG(LOG_WARNING, ("ppp_netif_output[%d]: first alloc fail\n", pcb->num)); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + snmp_inc_ifoutdiscards(&pcb->netif); + return ERR_MEM; + } + +#if VJ_SUPPORT + /* + * Attempt Van Jacobson header compression if VJ is configured and + * this is an IP packet. + */ + if (protocol == PPP_IP && pcb->vj_enabled) { + switch (vj_compress_tcp(&pcb->vj_comp, pb)) { + case TYPE_IP: + /* No change... + protocol = PPP_IP_PROTOCOL; */ + break; + case TYPE_COMPRESSED_TCP: + protocol = PPP_VJC_COMP; + break; + case TYPE_UNCOMPRESSED_TCP: + protocol = PPP_VJC_UNCOMP; + break; + default: + PPPDEBUG(LOG_WARNING, ("ppp_netif_output[%d]: bad IP packet\n", pcb->num)); + LINK_STATS_INC(link.proterr); + LINK_STATS_INC(link.drop); + snmp_inc_ifoutdiscards(&pcb->netif); + pbuf_free(head); + return ERR_VAL; + } + } +#endif /* VJ_SUPPORT */ + + tail = head; + + /* Build the PPP header. */ + if ((sys_jiffies() - pcb->last_xmit) >= PPP_MAXIDLEFLAG) { + tail = ppp_append(PPP_FLAG, tail, NULL); + } + + pcb->last_xmit = sys_jiffies(); + if (!pcb->accomp) { + fcs_out = PPP_FCS(fcs_out, PPP_ALLSTATIONS); + tail = ppp_append(PPP_ALLSTATIONS, tail, &pcb->out_accm); + fcs_out = PPP_FCS(fcs_out, PPP_UI); + tail = ppp_append(PPP_UI, tail, &pcb->out_accm); + } + if (!pcb->pcomp || protocol > 0xFF) { + c = (protocol >> 8) & 0xFF; + fcs_out = PPP_FCS(fcs_out, c); + tail = ppp_append(c, tail, &pcb->out_accm); + } + c = protocol & 0xFF; + fcs_out = PPP_FCS(fcs_out, c); + tail = ppp_append(c, tail, &pcb->out_accm); + + /* Load packet. */ + for(p = pb; p; p = p->next) { + int n; + u_char *sPtr; + + sPtr = (u_char*)p->payload; + n = p->len; + while (n-- > 0) { + c = *sPtr++; + + /* Update FCS before checking for special characters. */ + fcs_out = PPP_FCS(fcs_out, c); + + /* Copy to output buffer escaping special characters. */ + tail = ppp_append(c, tail, &pcb->out_accm); + } + } + + /* Add FCS and trailing flag. */ + c = ~fcs_out & 0xFF; + tail = ppp_append(c, tail, &pcb->out_accm); + c = (~fcs_out >> 8) & 0xFF; + tail = ppp_append(c, tail, &pcb->out_accm); + tail = ppp_append(PPP_FLAG, tail, NULL); + + /* If we failed to complete the packet, throw it away. */ + if (!tail) { + PPPDEBUG(LOG_WARNING, + ("ppp_netif_output[%d]: Alloc err - dropping proto=%d\n", + pcb->num, protocol)); + pbuf_free(head); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + snmp_inc_ifoutdiscards(&pcb->netif); + return ERR_MEM; + } + + /* Send it. */ + PPPDEBUG(LOG_INFO, ("ppp_netif_output[%d]: proto=0x%"X16_F"\n", pcb->num, protocol)); + + pppos_put(pcb, head); + return ERR_OK; +} +#endif /* PPPOS_SUPPORT */ + +#if PPPOE_SUPPORT +static err_t ppp_netif_output_over_ethernet(ppp_pcb *pcb, struct pbuf *p, u_short protocol) { + struct pbuf *pb; + int i=0; +#if LWIP_SNMP + u16_t tot_len; +#endif /* LWIP_SNMP */ + err_t err; + + /* @todo: try to use pbuf_header() here! */ + pb = pbuf_alloc(PBUF_LINK, PPPOE_HEADERLEN + sizeof(protocol), PBUF_RAM); + if(!pb) { + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.proterr); + snmp_inc_ifoutdiscards(&pcb->netif); + return ERR_MEM; + } + + pbuf_header(pb, -(s16_t)PPPOE_HEADERLEN); + + pcb->last_xmit = sys_jiffies(); + + if (!pcb->pcomp || protocol > 0xFF) { + *((u_char*)pb->payload + i++) = (protocol >> 8) & 0xFF; + } + *((u_char*)pb->payload + i) = protocol & 0xFF; + + pbuf_chain(pb, p); +#if LWIP_SNMP + tot_len = pb->tot_len; +#endif /* LWIP_SNMP */ + + if( (err = pppoe_xmit(pcb->pppoe_sc, pb)) != ERR_OK) { + LINK_STATS_INC(link.err); + snmp_inc_ifoutdiscards(&pcb->netif); + return err; + } + + snmp_add_ifoutoctets(&pcb->netif, tot_len); + snmp_inc_ifoutucastpkts(&pcb->netif); + LINK_STATS_INC(link.xmit); + return ERR_OK; +} +#endif /* PPPOE_SUPPORT */ + + +#if PPPOL2TP_SUPPORT +static err_t ppp_netif_output_over_l2tp(ppp_pcb *pcb, struct pbuf *p, u_short protocol) { + struct pbuf *pb; + int i=0; +#if LWIP_SNMP + u16_t tot_len; +#endif /* LWIP_SNMP */ + err_t err; + + /* @todo: try to use pbuf_header() here! */ + pb = pbuf_alloc(PBUF_TRANSPORT, PPPOL2TP_OUTPUT_DATA_HEADER_LEN + sizeof(protocol), PBUF_RAM); + if(!pb) { + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.proterr); + snmp_inc_ifoutdiscards(&pcb->netif); + return ERR_MEM; + } + + pbuf_header(pb, -(s16_t)PPPOL2TP_OUTPUT_DATA_HEADER_LEN); + + pcb->last_xmit = sys_jiffies(); + + if (!pcb->pcomp || protocol > 0xFF) { + *((u_char*)pb->payload + i++) = (protocol >> 8) & 0xFF; + } + *((u_char*)pb->payload + i) = protocol & 0xFF; + + pbuf_chain(pb, p); +#if LWIP_SNMP + tot_len = pb->tot_len; +#endif /* LWIP_SNMP */ + + if( (err = pppol2tp_xmit(pcb->l2tp_pcb, pb)) != ERR_OK) { + LINK_STATS_INC(link.err); + snmp_inc_ifoutdiscards(&pcb->netif); + return err; + } + + snmp_add_ifoutoctets(&pcb->netif, tot_len); + snmp_inc_ifoutucastpkts(&pcb->netif); + LINK_STATS_INC(link.xmit); + return ERR_OK; +} +#endif /* PPPOL2TP_SUPPORT */ + + +/* Get and set parameters for the given connection. + * Return 0 on success, an error code on failure. */ +int +ppp_ioctl(ppp_pcb *pcb, int cmd, void *arg) +{ + if(NULL == pcb) + return PPPERR_PARAM; + + switch(cmd) { + case PPPCTLG_UPSTATUS: /* Get the PPP up status. */ + if (arg) { + *(int *)arg = (int)(pcb->if_up); + return PPPERR_NONE; + } + return PPPERR_PARAM; + break; + + case PPPCTLS_ERRCODE: /* Set the PPP error code. */ + if (arg) { + pcb->err_code = (u8_t)(*(int *)arg); + return PPPERR_NONE; + } + return PPPERR_PARAM; + break; + + case PPPCTLG_ERRCODE: /* Get the PPP error code. */ + if (arg) { + *(int *)arg = (int)(pcb->err_code); + return PPPERR_NONE; + } + return PPPERR_PARAM; + break; + +#if PPPOS_SUPPORT + case PPPCTLG_FD: /* Get the fd associated with the ppp */ + if (arg) { + *(sio_fd_t *)arg = pcb->fd; + return PPPERR_NONE; + } + return PPPERR_PARAM; + break; +#endif /* PPPOS_SUPPORT */ + + default: + break; + } + + return PPPERR_PARAM; +} + +/* + * Write a pbuf to a ppp link, only used from PPP functions + * to send PPP packets. + * + * IPv4 and IPv6 packets from lwIP are sent, respectively, + * with ppp_netif_output_ip4() and ppp_netif_output_ip6() + * functions (which are callbacks of the netif PPP interface). + * + * RETURN: >= 0 Number of characters written + * -1 Failed to write to device + */ +int ppp_write(ppp_pcb *pcb, struct pbuf *p) { +#if PRINTPKT_SUPPORT + ppp_dump_packet("sent", (unsigned char *)p->payload+2, p->len-2); +#endif /* PRINTPKT_SUPPORT */ + +#if PPPOE_SUPPORT + if(pcb->pppoe_sc) { + return ppp_write_over_ethernet(pcb, p); + } +#endif /* PPPOE_SUPPORT */ + +#if PPPOL2TP_SUPPORT + if(pcb->l2tp_pcb) { + return ppp_write_over_l2tp(pcb, p); + } +#endif /* PPPOL2TP_SUPPORT */ + +#if PPPOS_SUPPORT + return ppp_write_over_serial(pcb, p); +#endif /* PPPOS_SUPPORT */ + +#if !PPPOS_SUPPORT + pbuf_free(p); + return PPPERR_NONE; +#endif +} + +#if PPPOS_SUPPORT +static int ppp_write_over_serial(ppp_pcb *pcb, struct pbuf *p) { + u_char *s = (u_char*)p->payload; + int n = p->len; + u_char c; + u_int fcs_out; + struct pbuf *head, *tail; + + head = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); + if (head == NULL) { + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.proterr); + snmp_inc_ifoutdiscards(&pcb->netif); + pbuf_free(p); + return PPPERR_ALLOC; + } + + tail = head; + + /* If the link has been idle, we'll send a fresh flag character to + * flush any noise. */ + if ((sys_jiffies() - pcb->last_xmit) >= PPP_MAXIDLEFLAG) { + tail = ppp_append(PPP_FLAG, tail, NULL); + } + pcb->last_xmit = sys_jiffies(); + + fcs_out = PPP_INITFCS; + /* Load output buffer. */ + while (n-- > 0) { + c = *s++; + + /* Update FCS before checking for special characters. */ + fcs_out = PPP_FCS(fcs_out, c); + + /* Copy to output buffer escaping special characters. */ + tail = ppp_append(c, tail, &pcb->out_accm); + } + + /* Add FCS and trailing flag. */ + c = ~fcs_out & 0xFF; + tail = ppp_append(c, tail, &pcb->out_accm); + c = (~fcs_out >> 8) & 0xFF; + tail = ppp_append(c, tail, &pcb->out_accm); + tail = ppp_append(PPP_FLAG, tail, NULL); + + /* If we failed to complete the packet, throw it away. + * Otherwise send it. */ + if (!tail) { + PPPDEBUG(LOG_WARNING, + ("ppp_write[%d]: Alloc err - dropping pbuf len=%d\n", pcb->num, head->len)); + /*"ppp_write[%d]: Alloc err - dropping %d:%.*H", pd, head->len, LWIP_MIN(head->len * 2, 40), head->payload)); */ + pbuf_free(head); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.proterr); + snmp_inc_ifoutdiscards(&pcb->netif); + pbuf_free(p); + return PPPERR_ALLOC; + } + + PPPDEBUG(LOG_INFO, ("ppp_write[%d]: len=%d\n", pcb->num, head->len)); + /* "ppp_write[%d]: %d:%.*H", pd, head->len, LWIP_MIN(head->len * 2, 40), head->payload)); */ + pppos_put(pcb, head); + pbuf_free(p); + return PPPERR_NONE; +} +#endif /* PPPOS_SUPPORT */ + +#if PPPOE_SUPPORT +static int ppp_write_over_ethernet(ppp_pcb *pcb, struct pbuf *p) { + struct pbuf *ph; /* Ethernet + PPPoE header */ +#if LWIP_SNMP + u16_t tot_len; +#endif /* LWIP_SNMP */ + + /* skip address & flags */ + pbuf_header(p, -(s16_t)2); + + ph = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN), PBUF_RAM); + if(!ph) { + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.proterr); + snmp_inc_ifoutdiscards(&pcb->netif); + pbuf_free(p); + return PPPERR_ALLOC; + } + + pbuf_header(ph, -(s16_t)PPPOE_HEADERLEN); /* hide PPPoE header */ + pbuf_cat(ph, p); +#if LWIP_SNMP + tot_len = ph->tot_len; +#endif /* LWIP_SNMP */ + + pcb->last_xmit = sys_jiffies(); + + if(pppoe_xmit(pcb->pppoe_sc, ph) != ERR_OK) { + LINK_STATS_INC(link.err); + snmp_inc_ifoutdiscards(&pcb->netif); + return PPPERR_DEVICE; + } + + snmp_add_ifoutoctets(&pcb->netif, (u16_t)tot_len); + snmp_inc_ifoutucastpkts(&pcb->netif); + LINK_STATS_INC(link.xmit); + return PPPERR_NONE; +} +#endif /* PPPOE_SUPPORT */ + +#if PPPOL2TP_SUPPORT +static int ppp_write_over_l2tp(ppp_pcb *pcb, struct pbuf *p) { + struct pbuf *ph; /* UDP + L2TP header */ +#if LWIP_SNMP + u16_t tot_len; +#endif /* LWIP_SNMP */ + + ph = pbuf_alloc(PBUF_TRANSPORT, (u16_t)(PPPOL2TP_OUTPUT_DATA_HEADER_LEN), PBUF_RAM); + if(!ph) { + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.proterr); + snmp_inc_ifoutdiscards(&pcb->netif); + pbuf_free(p); + return PPPERR_ALLOC; + } + + pbuf_header(ph, -(s16_t)PPPOL2TP_OUTPUT_DATA_HEADER_LEN); /* hide L2TP header */ + pbuf_cat(ph, p); +#if LWIP_SNMP + tot_len = ph->tot_len; +#endif /* LWIP_SNMP */ + + pcb->last_xmit = sys_jiffies(); + + if(pppol2tp_xmit(pcb->l2tp_pcb, ph) != ERR_OK) { + LINK_STATS_INC(link.err); + snmp_inc_ifoutdiscards(&pcb->netif); + return PPPERR_DEVICE; + } + + snmp_add_ifoutoctets(&pcb->netif, (u16_t)tot_len); + snmp_inc_ifoutucastpkts(&pcb->netif); + LINK_STATS_INC(link.xmit); + return PPPERR_NONE; +} +#endif /* PPPOL2TP_SUPPORT */ + +#if PPPOS_SUPPORT +/* + * Drop the input packet. + */ +static void +ppp_free_current_input_packet(ppp_pcb_rx *pcrx) +{ + if (pcrx->in_head != NULL) { + if (pcrx->in_tail && (pcrx->in_tail != pcrx->in_head)) { + pbuf_free(pcrx->in_tail); + } + pbuf_free(pcrx->in_head); + pcrx->in_head = NULL; + } + pcrx->in_tail = NULL; +} + +/* + * Drop the input packet and increase error counters. + */ +static void +ppp_drop(ppp_pcb_rx *pcrx) +{ +#if LWIP_SNMP || VJ_SUPPORT + ppp_pcb *pcb = (ppp_pcb*)pcrx->pcb; +#endif /* LWIP_SNMP || VJ_SUPPORT */ + if (pcrx->in_head != NULL) { +#if 0 + PPPDEBUG(LOG_INFO, ("ppp_drop: %d:%.*H\n", pcrx->in_head->len, min(60, pcrx->in_head->len * 2), pcrx->in_head->payload)); +#endif + PPPDEBUG(LOG_INFO, ("ppp_drop: pbuf len=%d, addr %p\n", pcrx->in_head->len, (void*)pcrx->in_head)); + } + ppp_free_current_input_packet(pcrx); +#if VJ_SUPPORT + vj_uncompress_err(&pcb->vj_comp); +#endif /* VJ_SUPPORT */ + + LINK_STATS_INC(link.drop); + snmp_inc_ifindiscards(&pcb->netif); +} + +/** PPPoS input helper struct, must be packed since it is stored + * to pbuf->payload, which might be unaligned. */ +#if PPP_INPROC_MULTITHREADED +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct pppos_input_header { + PACK_STRUCT_FIELD(ppp_pcb *pcb); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif +#endif /* PPP_INPROC_MULTITHREADED */ + +/** Pass received raw characters to PPPoS to be decoded. This function is + * thread-safe and can be called from a dedicated RX-thread or from a main-loop. + * + * @param pcb PPP descriptor index, returned by ppp_new() + * @param data received data + * @param len length of received data + */ +void +pppos_input(ppp_pcb *pcb, u_char *s, int l) +{ + ppp_pcb_rx *pcrx = &pcb->rx; + struct pbuf *next_pbuf; + u_char cur_char; + u_char escaped; + SYS_ARCH_DECL_PROTECT(lev); + + PPPDEBUG(LOG_DEBUG, ("pppos_input[%d]: got %d bytes\n", pcb->num, l)); + while (l-- > 0) { + cur_char = *s++; + + SYS_ARCH_PROTECT(lev); + escaped = ESCAPE_P(pcrx->in_accm, cur_char); + SYS_ARCH_UNPROTECT(lev); + /* Handle special characters. */ + if (escaped) { + /* Check for escape sequences. */ + /* XXX Note that this does not handle an escaped 0x5d character which + * would appear as an escape character. Since this is an ASCII ']' + * and there is no reason that I know of to escape it, I won't complicate + * the code to handle this case. GLL */ + if (cur_char == PPP_ESCAPE) { + pcrx->in_escaped = 1; + /* Check for the flag character. */ + } else if (cur_char == PPP_FLAG) { + /* If this is just an extra flag character, ignore it. */ + if (pcrx->in_state <= PDADDRESS) { + /* ignore it */; + /* If we haven't received the packet header, drop what has come in. */ + } else if (pcrx->in_state < PDDATA) { + PPPDEBUG(LOG_WARNING, + ("pppos_input[%d]: Dropping incomplete packet %d\n", + pcb->num, pcrx->in_state)); + LINK_STATS_INC(link.lenerr); + ppp_drop(pcrx); + /* If the fcs is invalid, drop the packet. */ + } else if (pcrx->in_fcs != PPP_GOODFCS) { + PPPDEBUG(LOG_INFO, + ("pppos_input[%d]: Dropping bad fcs 0x%"X16_F" proto=0x%"X16_F"\n", + pcb->num, pcrx->in_fcs, pcrx->in_protocol)); + /* Note: If you get lots of these, check for UART frame errors or try different baud rate */ + LINK_STATS_INC(link.chkerr); + ppp_drop(pcrx); + /* Otherwise it's a good packet so pass it on. */ + } else { + struct pbuf *inp; + /* Trim off the checksum. */ + if(pcrx->in_tail->len > 2) { + pcrx->in_tail->len -= 2; + + pcrx->in_tail->tot_len = pcrx->in_tail->len; + if (pcrx->in_tail != pcrx->in_head) { + pbuf_cat(pcrx->in_head, pcrx->in_tail); + } + } else { + pcrx->in_tail->tot_len = pcrx->in_tail->len; + if (pcrx->in_tail != pcrx->in_head) { + pbuf_cat(pcrx->in_head, pcrx->in_tail); + } + + pbuf_realloc(pcrx->in_head, pcrx->in_head->tot_len - 2); + } + + /* Dispatch the packet thereby consuming it. */ + inp = pcrx->in_head; + /* Packet consumed, release our references. */ + pcrx->in_head = NULL; + pcrx->in_tail = NULL; +#if IP_FORWARD || LWIP_IPV6_FORWARD + /* hide the room for Ethernet forwarding header */ + pbuf_header(inp, -(s16_t)PBUF_LINK_HLEN); +#endif /* IP_FORWARD || LWIP_IPV6_FORWARD */ +#if PPP_INPROC_MULTITHREADED + if(tcpip_callback_with_block(pppos_input_callback, inp, 0) != ERR_OK) { + PPPDEBUG(LOG_ERR, ("pppos_input[%d]: tcpip_callback() failed, dropping packet\n", pcb->num)); + pbuf_free(inp); + LINK_STATS_INC(link.drop); + snmp_inc_ifindiscards(&pcb->netif); + } +#else /* PPP_INPROC_MULTITHREADED */ + ppp_input(pcb, inp); +#endif /* PPP_INPROC_MULTITHREADED */ + } + + /* Prepare for a new packet. */ + pcrx->in_fcs = PPP_INITFCS; + pcrx->in_state = PDADDRESS; + pcrx->in_escaped = 0; + /* Other characters are usually control characters that may have + * been inserted by the physical layer so here we just drop them. */ + } else { + PPPDEBUG(LOG_WARNING, + ("pppos_input[%d]: Dropping ACCM char <%d>\n", pcb->num, cur_char)); + } + /* Process other characters. */ + } else { + /* Unencode escaped characters. */ + if (pcrx->in_escaped) { + pcrx->in_escaped = 0; + cur_char ^= PPP_TRANS; + } + + /* Process character relative to current state. */ + switch(pcrx->in_state) { + case PDIDLE: /* Idle state - waiting. */ + /* Drop the character if it's not 0xff + * we would have processed a flag character above. */ + if (cur_char != PPP_ALLSTATIONS) { + break; + } + /* no break */ + /* Fall through */ + + case PDSTART: /* Process start flag. */ + /* Prepare for a new packet. */ + pcrx->in_fcs = PPP_INITFCS; + /* no break */ + /* Fall through */ + + case PDADDRESS: /* Process address field. */ + if (cur_char == PPP_ALLSTATIONS) { + pcrx->in_state = PDCONTROL; + break; + } + /* no break */ + + /* Else assume compressed address and control fields so + * fall through to get the protocol... */ + case PDCONTROL: /* Process control field. */ + /* If we don't get a valid control code, restart. */ + if (cur_char == PPP_UI) { + pcrx->in_state = PDPROTOCOL1; + break; + } + /* no break */ + +#if 0 + else { + PPPDEBUG(LOG_WARNING, + ("pppos_input[%d]: Invalid control <%d>\n", pcb->num, cur_char)); + pcrx->in_state = PDSTART; + } +#endif + case PDPROTOCOL1: /* Process protocol field 1. */ + /* If the lower bit is set, this is the end of the protocol + * field. */ + if (cur_char & 1) { + pcrx->in_protocol = cur_char; + pcrx->in_state = PDDATA; + } else { + pcrx->in_protocol = (u_int)cur_char << 8; + pcrx->in_state = PDPROTOCOL2; + } + break; + case PDPROTOCOL2: /* Process protocol field 2. */ + pcrx->in_protocol |= cur_char; + pcrx->in_state = PDDATA; + break; + case PDDATA: /* Process data byte. */ + /* Make space to receive processed data. */ + if (pcrx->in_tail == NULL || pcrx->in_tail->len == PBUF_POOL_BUFSIZE) { + u16_t pbuf_alloc_len; + if (pcrx->in_tail != NULL) { + pcrx->in_tail->tot_len = pcrx->in_tail->len; + if (pcrx->in_tail != pcrx->in_head) { + pbuf_cat(pcrx->in_head, pcrx->in_tail); + /* give up the in_tail reference now */ + pcrx->in_tail = NULL; + } + } + /* If we haven't started a packet, we need a packet header. */ + pbuf_alloc_len = 0; +#if IP_FORWARD || LWIP_IPV6_FORWARD + /* If IP forwarding is enabled we are reserving PBUF_LINK_HLEN bytes so + * the packet is being allocated with enough header space to be + * forwarded (to Ethernet for example). + */ + if (pcrx->in_head == NULL) { + pbuf_alloc_len = PBUF_LINK_HLEN; + } +#endif /* IP_FORWARD || LWIP_IPV6_FORWARD */ + next_pbuf = pbuf_alloc(PBUF_RAW, pbuf_alloc_len, PBUF_POOL); + if (next_pbuf == NULL) { + /* No free buffers. Drop the input packet and let the + * higher layers deal with it. Continue processing + * the received pbuf chain in case a new packet starts. */ + PPPDEBUG(LOG_ERR, ("pppos_input[%d]: NO FREE PBUFS!\n", pcb->num)); + LINK_STATS_INC(link.memerr); + ppp_drop(pcrx); + pcrx->in_state = PDSTART; /* Wait for flag sequence. */ + break; + } + if (pcrx->in_head == NULL) { + u8_t *payload = ((u8_t*)next_pbuf->payload) + pbuf_alloc_len; +#if PPP_INPROC_MULTITHREADED + ((struct pppos_input_header*)payload)->pcb = pcb; + payload += sizeof(struct pppos_input_header); + next_pbuf->len += sizeof(struct pppos_input_header); +#endif /* PPP_INPROC_MULTITHREADED */ + next_pbuf->len += sizeof(pcrx->in_protocol); + *(payload++) = pcrx->in_protocol >> 8; + *(payload) = pcrx->in_protocol & 0xFF; + pcrx->in_head = next_pbuf; + } + pcrx->in_tail = next_pbuf; + } + /* Load character into buffer. */ + ((u_char*)pcrx->in_tail->payload)[pcrx->in_tail->len++] = cur_char; + break; + default: + break; + } + + /* update the frame check sequence number. */ + pcrx->in_fcs = PPP_FCS(pcrx->in_fcs, cur_char); + } + } /* while (l-- > 0), all bytes processed */ + + magic_randomize(); +} + +#if PPP_INPROC_MULTITHREADED +/* PPPoS input callback using one input pointer + */ +static void pppos_input_callback(void *arg) { + struct pbuf *pb = (struct pbuf*)arg; + ppp_pcb *pcb; + + pcb = ((struct pppos_input_header*)pb->payload)->pcb; + if(pbuf_header(pb, -(s16_t)sizeof(struct pppos_input_header))) { + LWIP_ASSERT("pbuf_header failed\n", 0); + goto drop; + } + + /* Dispatch the packet thereby consuming it. */ + ppp_input(pcb, pb); + return; + +drop: + LINK_STATS_INC(link.drop); + snmp_inc_ifindiscards(&pcb->netif); + pbuf_free(pb); +} +#endif /* PPP_INPROC_MULTITHREADED */ +#endif /* PPPOS_SUPPORT */ + +/* merge a pbuf chain into one pbuf */ +struct pbuf * ppp_singlebuf(struct pbuf *p) { + struct pbuf *q, *b; + u_char *pl; + + if(p->tot_len == p->len) { + return p; + } + + q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); + if(!q) { + PPPDEBUG(LOG_ERR, + ("ppp_singlebuf: unable to alloc new buf (%d)\n", p->tot_len)); + return p; /* live dangerously */ + } + + for(b = p, pl = (u_char*)q->payload; b != NULL; b = b->next) { + MEMCPY(pl, b->payload, b->len); + pl += b->len; + } + + pbuf_free(p); + + return q; +} + +#if PPPOE_SUPPORT +static void ppp_over_ethernet_link_status_cb(ppp_pcb *pcb, int state) { + int pppoe_err_code = PPPERR_NONE; + + switch(state) { + + /* PPPoE link is established, starting PPP negotiation */ + case PPPOE_CB_STATE_UP: + PPPDEBUG(LOG_INFO, ("ppp_over_ethernet_link_status_cb: unit %d: UP, connecting\n", pcb->num)); + ppp_start(pcb); + return; + + /* PPPoE link normally down (i.e. asked to do so) */ + case PPPOE_CB_STATE_DOWN: + PPPDEBUG(LOG_INFO, ("ppp_over_ethernet_link_status_cb: unit %d: DOWN, disconnected\n", pcb->num)); + pppoe_err_code = PPPERR_CONNECT; + break; + + /* PPPoE link failed to setup (i.e. PADI/PADO timeout) */ + case PPPOE_CB_STATE_FAILED: + PPPDEBUG(LOG_INFO, ("ppp_over_ethernet_link_status_cb: unit %d: FAILED, aborting\n", pcb->num)); + pppoe_err_code = PPPERR_OPEN; + new_phase(pcb, PPP_PHASE_DEAD); + break; + + default: + break; + } + + pcb->link_status_cb(pcb, pcb->err_code ? pcb->err_code : pppoe_err_code, pcb->ctx_cb); +} + +static void ppp_over_ethernet_open(ppp_pcb *pcb) { + + lcp_options *wo = &pcb->lcp_wantoptions; + lcp_options *ao = &pcb->lcp_allowoptions; + + ppp_clear(pcb); + + wo->mru = pcb->pppoe_sc->sc_ethif->mtu-PPPOE_HEADERLEN-2; /* two byte PPP protocol discriminator, then IP data */ + wo->neg_asyncmap = 0; + wo->neg_pcompression = 0; + wo->neg_accompression = 0; + + ao->mru = pcb->pppoe_sc->sc_ethif->mtu-PPPOE_HEADERLEN-2; /* two byte PPP protocol discriminator, then IP data */ + ao->neg_asyncmap = 0; + ao->neg_pcompression = 0; + ao->neg_accompression = 0; + + pppoe_connect(pcb->pppoe_sc); +} +#endif /* PPPOE_SUPPORT */ + +#if PPPOL2TP_SUPPORT +static void ppp_over_l2tp_link_status_cb(ppp_pcb *pcb, int state) { + int pppol2tp_err_code = PPPERR_NONE; + + switch(state) { + + /* PPPoL2TP link is established, starting PPP negotiation */ + case PPPOL2TP_CB_STATE_UP: + PPPDEBUG(LOG_INFO, ("ppp_over_l2tp_link_status_cb: unit %d: UP, connecting\n", pcb->num)); + ppp_start(pcb); + return; + + /* PPPoL2TP link normally down (i.e. asked to do so) */ + case PPPOL2TP_CB_STATE_DOWN: + PPPDEBUG(LOG_INFO, ("ppp_over_l2tp_link_status_cb: unit %d: DOWN, disconnected\n", pcb->num)); + pppol2tp_err_code = PPPERR_CONNECT; + break; + + /* PPPoL2TP link failed to setup (i.e. L2TP timeout) */ + case PPPOL2TP_CB_STATE_FAILED: + PPPDEBUG(LOG_INFO, ("ppp_over_l2tp_link_status_cb: unit %d: FAILED, aborting\n", pcb->num)); + pppol2tp_err_code = PPPERR_OPEN; + new_phase(pcb, PPP_PHASE_DEAD); + break; + + default: + break; + } + + pcb->link_status_cb(pcb, pcb->err_code ? pcb->err_code : pppol2tp_err_code, pcb->ctx_cb); +} + +static void ppp_over_l2tp_open(ppp_pcb *pcb) { + + lcp_options *wo = &pcb->lcp_wantoptions; + lcp_options *ao = &pcb->lcp_allowoptions; + + ppp_clear(pcb); + + wo->mru = 1500; /* FIXME: MTU depends if we support IP fragmentation or not */ + wo->neg_asyncmap = 0; + wo->neg_pcompression = 0; + wo->neg_accompression = 0; + + ao->mru = 1500; /* FIXME: MTU depends if we support IP fragmentation or not */ + ao->neg_asyncmap = 0; + ao->neg_pcompression = 0; + ao->neg_accompression = 0; + + pppol2tp_connect(pcb->l2tp_pcb); +} +#endif /* PPPOL2TP_SUPPORT */ + +void ppp_link_down(ppp_pcb *pcb) { + LWIP_UNUSED_ARG(pcb); /* necessary if PPPDEBUG is defined to an empty function */ + PPPDEBUG(LOG_DEBUG, ("ppp_link_down: unit %d\n", pcb->num)); +} + +void ppp_link_terminated(ppp_pcb *pcb) { + PPPDEBUG(LOG_DEBUG, ("ppp_link_terminated: unit %d\n", pcb->num)); + +#if PPPOE_SUPPORT + if (pcb->pppoe_sc) { + pppoe_disconnect(pcb->pppoe_sc); + } else +#endif /* PPPOE_SUPPORT */ +#if PPPOL2TP_SUPPORT + if (pcb->l2tp_pcb) { + pppol2tp_disconnect(pcb->l2tp_pcb); + } else +#endif /* PPPOL2TP_SUPPORT */ + { +#if PPPOS_SUPPORT + /* We cannot call ppp_free_current_input_packet() here because + * rx thread might still call pppos_input() + */ + PPPDEBUG(LOG_DEBUG, ("ppp_link_terminated: unit %d: err_code=%d\n", pcb->num, pcb->err_code)); + pcb->link_status_cb(pcb, pcb->err_code ? pcb->err_code : PPPERR_PROTOCOL, pcb->ctx_cb); +#endif /* PPPOS_SUPPORT */ + } + PPPDEBUG(LOG_DEBUG, ("ppp_link_terminated: finished.\n")); +} + +#if LWIP_NETIF_STATUS_CALLBACK +/** Set the status callback of a PPP's netif + * + * @param pcb The PPP descriptor returned by ppp_new() + * @param status_callback pointer to the status callback function + * + * @see netif_set_status_callback + */ +void +ppp_set_netif_statuscallback(ppp_pcb *pcb, netif_status_callback_fn status_callback) +{ + netif_set_status_callback(&pcb->netif, status_callback); +} +#endif /* LWIP_NETIF_STATUS_CALLBACK */ + +#if LWIP_NETIF_LINK_CALLBACK +/** Set the link callback of a PPP's netif + * + * @param pcb The PPP descriptor returned by ppp_new() + * @param link_callback pointer to the link callback function + * + * @see netif_set_link_callback + */ +void +ppp_set_netif_linkcallback(ppp_pcb *pcb, netif_status_callback_fn link_callback) +{ + netif_set_link_callback(&pcb->netif, link_callback); +} +#endif /* LWIP_NETIF_LINK_CALLBACK */ + +/************************************************************************ + * Functions called by various PPP subsystems to configure + * the PPP interface or change the PPP phase. + */ + +/* + * new_phase - signal the start of a new phase of pppd's operation. + */ +void new_phase(ppp_pcb *pcb, int p) { + pcb->phase = p; + PPPDEBUG(LOG_DEBUG, ("ppp phase changed: unit %d: phase=%d\n", pcb->num, pcb->phase)); +#if PPP_NOTIFY_PHASE + if(NULL != pcb->notify_phase_cb) { + pcb->notify_phase_cb(pcb, p, pcb->ctx_cb); + } +#endif /* PPP_NOTIFY_PHASE */ +} + +/* + * ppp_send_config - configure the transmit-side characteristics of + * the ppp interface. + */ +int ppp_send_config(ppp_pcb *pcb, int mtu, u32_t accm, int pcomp, int accomp) { +#if PPPOS_SUPPORT + int i; +#endif /* PPPOS_SUPPORT */ + LWIP_UNUSED_ARG(mtu); + + /* pcb->mtu = mtu; -- set correctly with netif_set_mtu */ + pcb->pcomp = pcomp; + pcb->accomp = accomp; + +#if PPPOS_SUPPORT + /* Load the ACCM bits for the 32 control codes. */ + for (i = 0; i < 32/8; i++) { + pcb->out_accm[i] = (u_char)((accm >> (8 * i)) & 0xFF); + } +#else + LWIP_UNUSED_ARG(accm); +#endif /* PPPOS_SUPPORT */ + +#if PPPOS_SUPPORT + PPPDEBUG(LOG_INFO, ("ppp_send_config[%d]: out_accm=%X %X %X %X\n", + pcb->num, + pcb->out_accm[0], pcb->out_accm[1], pcb->out_accm[2], pcb->out_accm[3])); +#else + PPPDEBUG(LOG_INFO, ("ppp_send_config[%d]\n", pcb->num) ); +#endif /* PPPOS_SUPPORT */ + return 0; +} + +/* + * ppp_recv_config - configure the receive-side characteristics of + * the ppp interface. + */ +int ppp_recv_config(ppp_pcb *pcb, int mru, u32_t accm, int pcomp, int accomp) { +#if PPPOS_SUPPORT + int i; + SYS_ARCH_DECL_PROTECT(lev); +#endif /* PPPOS_SUPPORT */ + + LWIP_UNUSED_ARG(accomp); + LWIP_UNUSED_ARG(pcomp); + LWIP_UNUSED_ARG(mru); + + /* Load the ACCM bits for the 32 control codes. */ +#if PPPOS_SUPPORT + SYS_ARCH_PROTECT(lev); + for (i = 0; i < 32 / 8; i++) { + /* @todo: does this work? ext_accm has been modified from pppd! */ + pcb->rx.in_accm[i] = (u_char)(accm >> (i * 8)); + } + SYS_ARCH_UNPROTECT(lev); +#else + LWIP_UNUSED_ARG(accm); +#endif /* PPPOS_SUPPORT */ + +#if PPPOS_SUPPORT + PPPDEBUG(LOG_INFO, ("ppp_recv_config[%d]: in_accm=%X %X %X %X\n", + pcb->num, + pcb->rx.in_accm[0], pcb->rx.in_accm[1], pcb->rx.in_accm[2], pcb->rx.in_accm[3])); +#else + PPPDEBUG(LOG_INFO, ("ppp_recv_config[%d]\n", pcb->num) ); +#endif /* PPPOS_SUPPORT */ + return 0; +} + + +/* + * sifaddr - Config the interface IP addresses and netmask. + */ +int sifaddr(ppp_pcb *pcb, u32_t our_adr, u32_t his_adr, + u32_t net_mask) { + + SMEMCPY(&pcb->addrs.our_ipaddr, &our_adr, sizeof(our_adr)); + SMEMCPY(&pcb->addrs.his_ipaddr, &his_adr, sizeof(his_adr)); + SMEMCPY(&pcb->addrs.netmask, &net_mask, sizeof(net_mask)); + return 1; +} + + +/******************************************************************** + * + * cifaddr - Clear the interface IP addresses, and delete routes + * through the interface if possible. + */ +int cifaddr(ppp_pcb *pcb, u32_t our_adr, u32_t his_adr) { + + LWIP_UNUSED_ARG(our_adr); + LWIP_UNUSED_ARG(his_adr); + + IP4_ADDR(&pcb->addrs.our_ipaddr, 0,0,0,0); + IP4_ADDR(&pcb->addrs.his_ipaddr, 0,0,0,0); + IP4_ADDR(&pcb->addrs.netmask, 255,255,255,255); + return 1; +} + + +#if PPP_IPV6_SUPPORT +#define IN6_LLADDR_FROM_EUI64(ip6, eui64) do { \ + memset(&ip6.addr, 0, sizeof(ip6_addr_t)); \ + ip6.addr[0] = PP_HTONL(0xfe800000); \ + eui64_copy(eui64, ip6.addr[2]); \ + } while (0) + +/******************************************************************** + * + * sif6addr - Config the interface with an IPv6 link-local address + */ +int sif6addr(ppp_pcb *pcb, eui64_t our_eui64, eui64_t his_eui64) { + + IN6_LLADDR_FROM_EUI64(pcb->addrs.our6_ipaddr, our_eui64); + IN6_LLADDR_FROM_EUI64(pcb->addrs.his6_ipaddr, his_eui64); + return 1; +} + +/******************************************************************** + * + * cif6addr - Remove IPv6 address from interface + */ +int cif6addr(ppp_pcb *pcb, eui64_t our_eui64, eui64_t his_eui64) { + + LWIP_UNUSED_ARG(our_eui64); + LWIP_UNUSED_ARG(his_eui64); + + IP6_ADDR(&pcb->addrs.our6_ipaddr, 0, 0,0,0,0); + IP6_ADDR(&pcb->addrs.his6_ipaddr, 0, 0,0,0,0); + return 1; +} +#endif /* PPP_IPV6_SUPPORT */ + + +/* + * sdns - Config the DNS servers + */ +int sdns(ppp_pcb *pcb, u32_t ns1, u32_t ns2) { + + SMEMCPY(&pcb->addrs.dns1, &ns1, sizeof(ns1)); + SMEMCPY(&pcb->addrs.dns2, &ns2, sizeof(ns2)); + return 1; +} + + +/******************************************************************** + * + * cdns - Clear the DNS servers + */ +int cdns(ppp_pcb *pcb, u32_t ns1, u32_t ns2) { + + LWIP_UNUSED_ARG(ns1); + LWIP_UNUSED_ARG(ns2); + + IP4_ADDR(&pcb->addrs.dns1, 0,0,0,0); + IP4_ADDR(&pcb->addrs.dns2, 0,0,0,0); + return 1; +} + + +/* + * sifup - Config the interface up and enable IP packets to pass. + */ +int sifup(ppp_pcb *pcb) { + + netif_set_addr(&pcb->netif, &pcb->addrs.our_ipaddr, &pcb->addrs.netmask, + &pcb->addrs.his_ipaddr); + + netif_set_up(&pcb->netif); + pcb->if_up = 1; + pcb->err_code = PPPERR_NONE; + + PPPDEBUG(LOG_DEBUG, ("sifup: unit %d: err_code=%d\n", pcb->num, pcb->err_code)); + pcb->link_status_cb(pcb, pcb->err_code, pcb->ctx_cb); + return 1; +} + +/******************************************************************** + * + * sifdown - Disable the indicated protocol and config the interface + * down if there are no remaining protocols. + */ +int sifdown(ppp_pcb *pcb) { + + if(!pcb->if_up) + return 1; + + pcb->if_up = 0; + + if (1 +#if PPP_IPV6_SUPPORT + /* set the interface down if IPv6 is down as well */ + && !pcb->if6_up +#endif /* PPP_IPV6_SUPPORT */ + ) { + /* make sure the netif status callback is called */ + netif_set_down(&pcb->netif); + } + PPPDEBUG(LOG_DEBUG, ("sifdown: unit %d: err_code=%d\n", pcb->num, pcb->err_code)); + return 1; +} + +#if PPP_IPV6_SUPPORT +/* + * sif6up - Config the interface up and enable IPv6 packets to pass. + */ +int sif6up(ppp_pcb *pcb) { + + ip6_addr_copy(pcb->netif.ip6_addr[0], pcb->addrs.our6_ipaddr); + netif_ip6_addr_set_state(&pcb->netif, 0, IP6_ADDR_PREFERRED); + + netif_set_up(&pcb->netif); + pcb->if6_up = 1; + pcb->err_code = PPPERR_NONE; + + PPPDEBUG(LOG_DEBUG, ("sif6up: unit %d: err_code=%d\n", pcb->num, pcb->err_code)); + pcb->link_status_cb(pcb, pcb->err_code, pcb->ctx_cb); + return 1; +} + +/******************************************************************** + * + * sif6down - Disable the indicated protocol and config the interface + * down if there are no remaining protocols. + */ +int sif6down(ppp_pcb *pcb) { + + if(!pcb->if6_up) + return 1; + + pcb->if6_up = 0; + /* set the interface down if IPv4 is down as well */ + if (!pcb->if_up) { + /* make sure the netif status callback is called */ + netif_set_down(&pcb->netif); + } + PPPDEBUG(LOG_DEBUG, ("sif6down: unit %d: err_code=%d\n", pcb->num, pcb->err_code)); + return 1; +} +#endif /* PPP_IPV6_SUPPORT */ + +/* + * sifnpmode - Set the mode for handling packets for a given NP. + */ +int sifnpmode(ppp_pcb *pcb, int proto, enum NPmode mode) { + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(proto); + LWIP_UNUSED_ARG(mode); + return 0; +} + +/* + * netif_set_mtu - set the MTU on the PPP network interface. + */ +void netif_set_mtu(ppp_pcb *pcb, int mtu) { + + pcb->netif.mtu = mtu; +} + +/* + * netif_get_mtu - get PPP interface MTU + */ +int netif_get_mtu(ppp_pcb *pcb) { + + return pcb->netif.mtu; +} + +/******************************************************************** + * + * sifproxyarp - Make a proxy ARP entry for the peer. + */ + +int sifproxyarp(ppp_pcb *pcb, u32_t his_adr) { + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(his_adr); + /* FIXME: do we really need that in IPCP ? */ + return 0; +} + +/******************************************************************** + * + * cifproxyarp - Delete the proxy ARP entry for the peer. + */ + +int cifproxyarp(ppp_pcb *pcb, u32_t his_adr) { + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(his_adr); + /* FIXME: do we really need that in IPCP ? */ + return 0; +} + +/******************************************************************** + * + * sifvjcomp - config tcp header compression + */ +int sifvjcomp(ppp_pcb *pcb, int vjcomp, int cidcomp, int maxcid) { + +#if PPPOS_SUPPORT && VJ_SUPPORT + pcb->vj_enabled = vjcomp; + pcb->vj_comp.compressSlot = cidcomp; + pcb->vj_comp.maxSlotIndex = maxcid; + PPPDEBUG(LOG_INFO, ("sifvjcomp: VJ compress enable=%d slot=%d max slot=%d\n", + vjcomp, cidcomp, maxcid)); +#else /* PPPOS_SUPPORT && VJ_SUPPORT */ + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(vjcomp); + LWIP_UNUSED_ARG(cidcomp); + LWIP_UNUSED_ARG(maxcid); +#endif /* PPPOS_SUPPORT && VJ_SUPPORT */ + + return 0; +} + +#if PPP_IDLETIMELIMIT +/******************************************************************** + * + * get_idle_time - return how long the link has been idle. + */ +int get_idle_time(ppp_pcb *pcb, struct ppp_idle *ip) { + /* FIXME: add idle time support and make it optional */ + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(ip); + return 1; +} +#endif /* PPP_IDLETIMELIMIT */ + +/******************************************************************** + * + * get_loop_output - get outgoing packets from the ppp device, + * and detect when we want to bring the real link up. + * Return value is 1 if we need to bring up the link, 0 otherwise. + */ +int get_loop_output(void) { + /* FIXME: necessary for "demand", do we really need to support on-demand ? */ + return 0; +} + +/******************************************************************** + * + * Return user specified netmask, modified by any mask we might determine + * for address `addr' (in network byte order). + * Here we scan through the system's list of interfaces, looking for + * any non-point-to-point interfaces which might appear to be on the same + * network as `addr'. If we find any, we OR in their netmask to the + * user-specified netmask. + */ +u32_t get_mask(u32_t addr) { +#if 0 + u32_t mask, nmask; + + addr = htonl(addr); + if (IP_CLASSA(addr)) { /* determine network mask for address class */ + nmask = IP_CLASSA_NET; + } else if (IP_CLASSB(addr)) { + nmask = IP_CLASSB_NET; + } else { + nmask = IP_CLASSC_NET; + } + + /* class D nets are disallowed by bad_ip_adrs */ + mask = PP_HTONL(0xffffff00UL) | htonl(nmask); + + /* XXX + * Scan through the system's network interfaces. + * Get each netmask and OR them into our mask. + */ + /* return mask; */ + return mask; +#endif + LWIP_UNUSED_ARG(addr); + return 0xFFFFFFFF; +} + + +#if PPP_PROTOCOLNAME +/* List of protocol names, to make our messages a little more informative. */ +struct protocol_list { + u_short proto; + const char *name; +} protocol_list[] = { + { 0x21, "IP" }, + { 0x23, "OSI Network Layer" }, + { 0x25, "Xerox NS IDP" }, + { 0x27, "DECnet Phase IV" }, + { 0x29, "Appletalk" }, + { 0x2b, "Novell IPX" }, + { 0x2d, "VJ compressed TCP/IP" }, + { 0x2f, "VJ uncompressed TCP/IP" }, + { 0x31, "Bridging PDU" }, + { 0x33, "Stream Protocol ST-II" }, + { 0x35, "Banyan Vines" }, + { 0x39, "AppleTalk EDDP" }, + { 0x3b, "AppleTalk SmartBuffered" }, + { 0x3d, "Multi-Link" }, + { 0x3f, "NETBIOS Framing" }, + { 0x41, "Cisco Systems" }, + { 0x43, "Ascom Timeplex" }, + { 0x45, "Fujitsu Link Backup and Load Balancing (LBLB)" }, + { 0x47, "DCA Remote Lan" }, + { 0x49, "Serial Data Transport Protocol (PPP-SDTP)" }, + { 0x4b, "SNA over 802.2" }, + { 0x4d, "SNA" }, + { 0x4f, "IP6 Header Compression" }, + { 0x51, "KNX Bridging Data" }, + { 0x53, "Encryption" }, + { 0x55, "Individual Link Encryption" }, + { 0x57, "IPv6" }, + { 0x59, "PPP Muxing" }, + { 0x5b, "Vendor-Specific Network Protocol" }, + { 0x61, "RTP IPHC Full Header" }, + { 0x63, "RTP IPHC Compressed TCP" }, + { 0x65, "RTP IPHC Compressed non-TCP" }, + { 0x67, "RTP IPHC Compressed UDP 8" }, + { 0x69, "RTP IPHC Compressed RTP 8" }, + { 0x6f, "Stampede Bridging" }, + { 0x73, "MP+" }, + { 0xc1, "NTCITS IPI" }, + { 0xfb, "single-link compression" }, + { 0xfd, "Compressed Datagram" }, + { 0x0201, "802.1d Hello Packets" }, + { 0x0203, "IBM Source Routing BPDU" }, + { 0x0205, "DEC LANBridge100 Spanning Tree" }, + { 0x0207, "Cisco Discovery Protocol" }, + { 0x0209, "Netcs Twin Routing" }, + { 0x020b, "STP - Scheduled Transfer Protocol" }, + { 0x020d, "EDP - Extreme Discovery Protocol" }, + { 0x0211, "Optical Supervisory Channel Protocol" }, + { 0x0213, "Optical Supervisory Channel Protocol" }, + { 0x0231, "Luxcom" }, + { 0x0233, "Sigma Network Systems" }, + { 0x0235, "Apple Client Server Protocol" }, + { 0x0281, "MPLS Unicast" }, + { 0x0283, "MPLS Multicast" }, + { 0x0285, "IEEE p1284.4 standard - data packets" }, + { 0x0287, "ETSI TETRA Network Protocol Type 1" }, + { 0x0289, "Multichannel Flow Treatment Protocol" }, + { 0x2063, "RTP IPHC Compressed TCP No Delta" }, + { 0x2065, "RTP IPHC Context State" }, + { 0x2067, "RTP IPHC Compressed UDP 16" }, + { 0x2069, "RTP IPHC Compressed RTP 16" }, + { 0x4001, "Cray Communications Control Protocol" }, + { 0x4003, "CDPD Mobile Network Registration Protocol" }, + { 0x4005, "Expand accelerator protocol" }, + { 0x4007, "ODSICP NCP" }, + { 0x4009, "DOCSIS DLL" }, + { 0x400B, "Cetacean Network Detection Protocol" }, + { 0x4021, "Stacker LZS" }, + { 0x4023, "RefTek Protocol" }, + { 0x4025, "Fibre Channel" }, + { 0x4027, "EMIT Protocols" }, + { 0x405b, "Vendor-Specific Protocol (VSP)" }, + { 0x8021, "Internet Protocol Control Protocol" }, + { 0x8023, "OSI Network Layer Control Protocol" }, + { 0x8025, "Xerox NS IDP Control Protocol" }, + { 0x8027, "DECnet Phase IV Control Protocol" }, + { 0x8029, "Appletalk Control Protocol" }, + { 0x802b, "Novell IPX Control Protocol" }, + { 0x8031, "Bridging NCP" }, + { 0x8033, "Stream Protocol Control Protocol" }, + { 0x8035, "Banyan Vines Control Protocol" }, + { 0x803d, "Multi-Link Control Protocol" }, + { 0x803f, "NETBIOS Framing Control Protocol" }, + { 0x8041, "Cisco Systems Control Protocol" }, + { 0x8043, "Ascom Timeplex" }, + { 0x8045, "Fujitsu LBLB Control Protocol" }, + { 0x8047, "DCA Remote Lan Network Control Protocol (RLNCP)" }, + { 0x8049, "Serial Data Control Protocol (PPP-SDCP)" }, + { 0x804b, "SNA over 802.2 Control Protocol" }, + { 0x804d, "SNA Control Protocol" }, + { 0x804f, "IP6 Header Compression Control Protocol" }, + { 0x8051, "KNX Bridging Control Protocol" }, + { 0x8053, "Encryption Control Protocol" }, + { 0x8055, "Individual Link Encryption Control Protocol" }, + { 0x8057, "IPv6 Control Protocol" }, + { 0x8059, "PPP Muxing Control Protocol" }, + { 0x805b, "Vendor-Specific Network Control Protocol (VSNCP)" }, + { 0x806f, "Stampede Bridging Control Protocol" }, + { 0x8073, "MP+ Control Protocol" }, + { 0x80c1, "NTCITS IPI Control Protocol" }, + { 0x80fb, "Single Link Compression Control Protocol" }, + { 0x80fd, "Compression Control Protocol" }, + { 0x8207, "Cisco Discovery Protocol Control" }, + { 0x8209, "Netcs Twin Routing" }, + { 0x820b, "STP - Control Protocol" }, + { 0x820d, "EDPCP - Extreme Discovery Protocol Ctrl Prtcl" }, + { 0x8235, "Apple Client Server Protocol Control" }, + { 0x8281, "MPLSCP" }, + { 0x8285, "IEEE p1284.4 standard - Protocol Control" }, + { 0x8287, "ETSI TETRA TNP1 Control Protocol" }, + { 0x8289, "Multichannel Flow Treatment Protocol" }, + { 0xc021, "Link Control Protocol" }, + { 0xc023, "Password Authentication Protocol" }, + { 0xc025, "Link Quality Report" }, + { 0xc027, "Shiva Password Authentication Protocol" }, + { 0xc029, "CallBack Control Protocol (CBCP)" }, + { 0xc02b, "BACP Bandwidth Allocation Control Protocol" }, + { 0xc02d, "BAP" }, + { 0xc05b, "Vendor-Specific Authentication Protocol (VSAP)" }, + { 0xc081, "Container Control Protocol" }, + { 0xc223, "Challenge Handshake Authentication Protocol" }, + { 0xc225, "RSA Authentication Protocol" }, + { 0xc227, "Extensible Authentication Protocol" }, + { 0xc229, "Mitsubishi Security Info Exch Ptcl (SIEP)" }, + { 0xc26f, "Stampede Bridging Authorization Protocol" }, + { 0xc281, "Proprietary Authentication Protocol" }, + { 0xc283, "Proprietary Authentication Protocol" }, + { 0xc481, "Proprietary Node ID Authentication Protocol" }, + { 0, NULL }, +}; + +/* + * protocol_name - find a name for a PPP protocol. + */ +const char * protocol_name(int proto) { + struct protocol_list *lp; + + for (lp = protocol_list; lp->proto != 0; ++lp) + if (proto == lp->proto) + return lp->name; + return NULL; +} +#endif /* PPP_PROTOCOLNAME */ + +#if PPP_STATS_SUPPORT + +/* ---- Note on PPP Stats support ---- + * + * The one willing link stats support should add the get_ppp_stats() + * to fetch statistics from lwIP. + */ + +/* + * reset_link_stats - "reset" stats when link goes up. + */ +void reset_link_stats(int u) { + if (!get_ppp_stats(u, &old_link_stats)) + return; + gettimeofday(&start_time, NULL); +} + +/* + * update_link_stats - get stats at link termination. + */ +void update_link_stats(int u) { + + struct timeval now; + char numbuf[32]; + + if (!get_ppp_stats(u, &link_stats) + || gettimeofday(&now, NULL) < 0) + return; + link_connect_time = now.tv_sec - start_time.tv_sec; + link_stats_valid = 1; + + link_stats.bytes_in -= old_link_stats.bytes_in; + link_stats.bytes_out -= old_link_stats.bytes_out; + link_stats.pkts_in -= old_link_stats.pkts_in; + link_stats.pkts_out -= old_link_stats.pkts_out; +} + +void print_link_stats() { + /* + * Print connect time and statistics. + */ + if (link_stats_valid) { + int t = (link_connect_time + 5) / 6; /* 1/10ths of minutes */ + info("Connect time %d.%d minutes.", t/10, t%10); + info("Sent %u bytes, received %u bytes.", + link_stats.bytes_out, link_stats.bytes_in); + link_stats_valid = 0; + } +} +#endif /* PPP_STATS_SUPPORT */ + +#endif /* PPP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/pppcrypt.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/pppcrypt.c new file mode 100644 index 0000000..097f702 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/pppcrypt.c @@ -0,0 +1,66 @@ +/* + * pppcrypt.c - PPP/DES linkage for MS-CHAP and EAP SRP-SHA1 + * + * Extracted from chap_ms.c by James Carlson. + * + * Copyright (c) 1995 Eric Rosenquist. 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. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && MSCHAP_SUPPORT /* don't build if not necessary */ + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/pppcrypt.h" + + +static u_char pppcrypt_get_7bits(u_char *input, int startBit) { + unsigned int word; + + word = (unsigned)input[startBit / 8] << 8; + word |= (unsigned)input[startBit / 8 + 1]; + + word >>= 15 - (startBit % 8 + 7); + + return word & 0xFE; +} + +/* IN 56 bit DES key missing parity bits + * OUT 64 bit DES key with parity bits added + */ +void pppcrypt_56_to_64_bit_key(u_char *key, u_char * des_key) { + des_key[0] = pppcrypt_get_7bits(key, 0); + des_key[1] = pppcrypt_get_7bits(key, 7); + des_key[2] = pppcrypt_get_7bits(key, 14); + des_key[3] = pppcrypt_get_7bits(key, 21); + des_key[4] = pppcrypt_get_7bits(key, 28); + des_key[5] = pppcrypt_get_7bits(key, 35); + des_key[6] = pppcrypt_get_7bits(key, 42); + des_key[7] = pppcrypt_get_7bits(key, 49); +} + +#endif /* PPP_SUPPORT && MSCHAP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/pppoe.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/pppoe.c new file mode 100644 index 0000000..2aa819c --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/pppoe.c @@ -0,0 +1,1113 @@ +/***************************************************************************** +* pppoe.c - PPP Over Ethernet implementation for lwIP. +* +* Copyright (c) 2006 by Marc Boucher, Services Informatiques (MBSI) inc. +* +* The authors hereby grant permission to use, copy, modify, distribute, +* and license this software and its documentation for any purpose, provided +* that existing copyright notices are retained in all copies and that this +* notice and the following disclaimer are included verbatim in any +* distributions. No written agreement, license, or royalty fee is required +* for any of the authorized uses. +* +* THIS SOFTWARE IS PROVIDED BY THE 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 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. +* +****************************************************************************** +* REVISION HISTORY +* +* 06-01-01 Marc Boucher +* Ported to lwIP. +*****************************************************************************/ + + + +/* based on NetBSD: if_pppoe.c,v 1.64 2006/01/31 23:50:15 martin Exp */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Martin Husemann . + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && PPPOE_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#if 0 /* UNUSED */ +#include +#include +#endif /* UNUSED */ + +#include "lwip/timers.h" +#include "lwip/memp.h" +#include "lwip/stats.h" + +#include "netif/ppp/ppp_impl.h" +#include "netif/ppp/pppoe.h" + +/* Add a 16 bit unsigned value to a buffer pointed to by PTR */ +#define PPPOE_ADD_16(PTR, VAL) \ + *(PTR)++ = (u8_t)((VAL) / 256); \ + *(PTR)++ = (u8_t)((VAL) % 256) + +/* Add a complete PPPoE header to the buffer pointed to by PTR */ +#define PPPOE_ADD_HEADER(PTR, CODE, SESS, LEN) \ + *(PTR)++ = PPPOE_VERTYPE; \ + *(PTR)++ = (CODE); \ + PPPOE_ADD_16(PTR, SESS); \ + PPPOE_ADD_16(PTR, LEN) + +#define PPPOE_DISC_TIMEOUT (5*1000) /* base for quick timeout calculation */ +#define PPPOE_SLOW_RETRY (60*1000) /* persistent retry interval */ +#define PPPOE_DISC_MAXPADI 4 /* retry PADI four times (quickly) */ +#define PPPOE_DISC_MAXPADR 2 /* retry PADR twice */ + +#ifdef PPPOE_SERVER +#error "PPPOE_SERVER is not yet supported under lwIP!" +/* from if_spppsubr.c */ +#define IFF_PASSIVE IFF_LINK0 /* wait passively for connection */ +#endif + +/* FIXME: we should probably remove that, this is only used for debug purposes */ +#ifndef PPPOE_ERRORSTRING_LEN +#define PPPOE_ERRORSTRING_LEN 64 +#endif +static char pppoe_error_tmp[PPPOE_ERRORSTRING_LEN]; + + +/* management routines */ +static void pppoe_abort_connect(struct pppoe_softc *); +static void pppoe_clear_softc(struct pppoe_softc *, const char *); + +/* internal timeout handling */ +static void pppoe_timeout(void *); + +/* sending actual protocol controll packets */ +static err_t pppoe_send_padi(struct pppoe_softc *); +static err_t pppoe_send_padr(struct pppoe_softc *); +#ifdef PPPOE_SERVER +static err_t pppoe_send_pado(struct pppoe_softc *); +static err_t pppoe_send_pads(struct pppoe_softc *); +#endif +static err_t pppoe_send_padt(struct netif *, u_int, const u8_t *); + +/* internal helper functions */ +static struct pppoe_softc* pppoe_find_softc_by_session(u_int session, struct netif *rcvif); +static struct pppoe_softc* pppoe_find_softc_by_hunique(u8_t *token, size_t len, struct netif *rcvif); + +/** linked list of created pppoe interfaces */ +static struct pppoe_softc *pppoe_softc_list; + +err_t +pppoe_create(struct netif *ethif, ppp_pcb *pcb, void (*link_status_cb)(ppp_pcb *pcb, int up), struct pppoe_softc **scptr) +{ + struct pppoe_softc *sc; + + sc = (struct pppoe_softc *)memp_malloc(MEMP_PPPOE_IF); + if (sc == NULL) { + *scptr = NULL; + return ERR_MEM; + } + memset(sc, 0, sizeof(struct pppoe_softc)); + + /* changed to real address later */ + MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); + + sc->pcb = pcb; + sc->sc_link_status_cb = link_status_cb; + sc->sc_ethif = ethif; + + /* put the new interface at the head of the list */ + sc->next = pppoe_softc_list; + pppoe_softc_list = sc; + + *scptr = sc; + + return ERR_OK; +} + +err_t +pppoe_destroy(struct pppoe_softc *sc) +{ + struct pppoe_softc *cur, *prev = NULL; + + /* find previous linked list entry */ + for (cur = pppoe_softc_list; cur != NULL; prev = cur, cur = cur->next) { + if (sc == cur) { + break; + } + } + + if (cur != sc) { + return ERR_IF; + } + + sys_untimeout(pppoe_timeout, sc); + if (prev == NULL) { + /* remove sc from the head of the list */ + pppoe_softc_list = sc->next; + } else { + /* remove sc from the list */ + prev->next = sc->next; + } + +#ifdef PPPOE_TODO + if (sc->sc_concentrator_name) { + mem_free(sc->sc_concentrator_name); + } + if (sc->sc_service_name) { + mem_free(sc->sc_service_name); + } +#endif /* PPPOE_TODO */ + memp_free(MEMP_PPPOE_IF, sc); + + return ERR_OK; +} + +/* + * Find the interface handling the specified session. + * Note: O(number of sessions open), this is a client-side only, mean + * and lean implementation, so number of open sessions typically should + * be 1. + */ +static struct pppoe_softc* pppoe_find_softc_by_session(u_int session, struct netif *rcvif) { + struct pppoe_softc *sc; + + if (session == 0) { + return NULL; + } + + for (sc = pppoe_softc_list; sc != NULL; sc = sc->next) { + if (sc->sc_state == PPPOE_STATE_SESSION + && sc->sc_session == session + && sc->sc_ethif == rcvif) { + return sc; + } + } + return NULL; +} + +/* Check host unique token passed and return appropriate softc pointer, + * or NULL if token is bogus. */ +static struct pppoe_softc* pppoe_find_softc_by_hunique(u8_t *token, size_t len, struct netif *rcvif) { + struct pppoe_softc *sc, *t; + + if (pppoe_softc_list == NULL) { + return NULL; + } + + if (len != sizeof sc) { + return NULL; + } + MEMCPY(&t, token, len); + + for (sc = pppoe_softc_list; sc != NULL; sc = sc->next) { + if (sc == t) { + break; + } + } + + if (sc == NULL) { + PPPDEBUG(LOG_DEBUG, ("pppoe: alien host unique tag, no session found\n")); + return NULL; + } + + /* should be safe to access *sc now */ + if (sc->sc_state < PPPOE_STATE_PADI_SENT || sc->sc_state >= PPPOE_STATE_SESSION) { + PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": host unique tag found, but it belongs to a connection in state %d\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, sc->sc_state)); + return NULL; + } + if (sc->sc_ethif != rcvif) { + PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": wrong interface, not accepting host unique\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + return NULL; + } + return sc; +} + +static void +pppoe_linkstatus_up(struct pppoe_softc *sc) +{ + sc->sc_link_status_cb(sc->pcb, PPPOE_CB_STATE_UP); +} + +/* analyze and handle a single received packet while not in session state */ +void +pppoe_disc_input(struct netif *netif, struct pbuf *pb) +{ + u16_t tag, len; + u16_t session, plen; + struct pppoe_softc *sc; + const char *err_msg; + char devname[6]; + u8_t *ac_cookie; + u16_t ac_cookie_len; +#ifdef PPPOE_SERVER + u8_t *hunique; + size_t hunique_len; +#endif + struct pppoehdr *ph; + struct pppoetag pt; + int off, err; + struct eth_hdr *ethhdr; + + /* don't do anything if there is not a single PPPoE instance */ + if (pppoe_softc_list == NULL) { + pbuf_free(pb); + return; + } + + pb = ppp_singlebuf(pb); + + strcpy(devname, "pppoe"); /* as long as we don't know which instance */ + err_msg = NULL; + if (pb->len < sizeof(*ethhdr)) { + goto done; + } + ethhdr = (struct eth_hdr *)pb->payload; + off = sizeof(*ethhdr); + + ac_cookie = NULL; + ac_cookie_len = 0; +#ifdef PPPOE_SERVER + hunique = NULL; + hunique_len = 0; +#endif + session = 0; + if (pb->len - off < (u16_t)PPPOE_HEADERLEN) { + PPPDEBUG(LOG_DEBUG, ("pppoe: packet too short: %d\n", pb->len)); + goto done; + } + + ph = (struct pppoehdr *) (ethhdr + 1); + if (ph->vertype != PPPOE_VERTYPE) { + PPPDEBUG(LOG_DEBUG, ("pppoe: unknown version/type packet: 0x%x\n", ph->vertype)); + goto done; + } + session = ntohs(ph->session); + plen = ntohs(ph->plen); + off += sizeof(*ph); + + if (plen + off > pb->len) { + PPPDEBUG(LOG_DEBUG, ("pppoe: packet content does not fit: data available = %d, packet size = %u\n", + pb->len - off, plen)); + goto done; + } + if(pb->tot_len == pb->len) { + pb->tot_len = pb->len = (u16_t)off + plen; /* ignore trailing garbage */ + } + tag = 0; + len = 0; + sc = NULL; + while (off + sizeof(pt) <= pb->len) { + MEMCPY(&pt, (u8_t*)pb->payload + off, sizeof(pt)); + tag = ntohs(pt.tag); + len = ntohs(pt.len); + if (off + sizeof(pt) + len > pb->len) { + PPPDEBUG(LOG_DEBUG, ("pppoe: tag 0x%x len 0x%x is too long\n", tag, len)); + goto done; + } + switch (tag) { + case PPPOE_TAG_EOL: + goto breakbreak; + case PPPOE_TAG_SNAME: + break; /* ignored */ + case PPPOE_TAG_ACNAME: + break; /* ignored */ + case PPPOE_TAG_HUNIQUE: + if (sc != NULL) { + break; + } +#ifdef PPPOE_SERVER + hunique = (u8_t*)pb->payload + off + sizeof(pt); + hunique_len = len; +#endif + sc = pppoe_find_softc_by_hunique((u8_t*)pb->payload + off + sizeof(pt), len, netif); + if (sc != NULL) { + devname[0] = sc->sc_ethif->name[0]; + devname[1] = sc->sc_ethif->name[1]; + devname[2] = sc->sc_ethif->num; + devname[3] = '\0'; + } + break; + case PPPOE_TAG_ACCOOKIE: + if (ac_cookie == NULL) { + ac_cookie = (u8_t*)pb->payload + off + sizeof(pt); + ac_cookie_len = len; + } + break; + case PPPOE_TAG_SNAME_ERR: + err_msg = "SERVICE NAME ERROR"; + break; + case PPPOE_TAG_ACSYS_ERR: + err_msg = "AC SYSTEM ERROR"; + break; + case PPPOE_TAG_GENERIC_ERR: + err_msg = "GENERIC ERROR"; + break; + default: + break; + } + if (NULL != err_msg) { + if (len) { + u16_t error_len = LWIP_MIN(len, sizeof(pppoe_error_tmp)-1); + strncpy(pppoe_error_tmp, (char*)pb->payload + off + sizeof(pt), error_len); + pppoe_error_tmp[error_len] = '\0'; + PPPDEBUG(LOG_DEBUG, ("%s: %s: %s\n", devname, err_msg, pppoe_error_tmp)); + } else { + PPPDEBUG(LOG_DEBUG, ("%s: %s\n", devname, err_msg)); + } + } + off += sizeof(pt) + len; + } + +breakbreak:; + switch (ph->code) { + case PPPOE_CODE_PADI: +#ifdef PPPOE_SERVER + /* + * got service name, concentrator name, and/or host unique. + * ignore if we have no interfaces with IFF_PASSIVE|IFF_UP. + */ + if (LIST_EMPTY(&pppoe_softc_list)) { + goto done; + } + LIST_FOREACH(sc, &pppoe_softc_list, sc_list) { + if (!(sc->sc_sppp.pp_if.if_flags & IFF_UP)) { + continue; + } + if (!(sc->sc_sppp.pp_if.if_flags & IFF_PASSIVE)) { + continue; + } + if (sc->sc_state == PPPOE_STATE_INITIAL) { + break; + } + } + if (sc == NULL) { + /* PPPDEBUG(LOG_DEBUG, ("pppoe: free passive interface is not found\n")); */ + goto done; + } + if (hunique) { + if (sc->sc_hunique) { + mem_free(sc->sc_hunique); + } + sc->sc_hunique = mem_malloc(hunique_len); + if (sc->sc_hunique == NULL) { + goto done; + } + sc->sc_hunique_len = hunique_len; + MEMCPY(sc->sc_hunique, hunique, hunique_len); + } + MEMCPY(&sc->sc_dest, eh->ether_shost, sizeof sc->sc_dest); + sc->sc_state = PPPOE_STATE_PADO_SENT; + pppoe_send_pado(sc); + break; +#endif /* PPPOE_SERVER */ + case PPPOE_CODE_PADR: +#ifdef PPPOE_SERVER + /* + * get sc from ac_cookie if IFF_PASSIVE + */ + if (ac_cookie == NULL) { + /* be quiet if there is not a single pppoe instance */ + PPPDEBUG(LOG_DEBUG, ("pppoe: received PADR but not includes ac_cookie\n")); + goto done; + } + sc = pppoe_find_softc_by_hunique(ac_cookie, ac_cookie_len, netif); + if (sc == NULL) { + /* be quiet if there is not a single pppoe instance */ + if (!LIST_EMPTY(&pppoe_softc_list)) { + PPPDEBUG(LOG_DEBUG, ("pppoe: received PADR but could not find request for it\n")); + } + goto done; + } + if (sc->sc_state != PPPOE_STATE_PADO_SENT) { + PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": received unexpected PADR\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + goto done; + } + if (hunique) { + if (sc->sc_hunique) { + mem_free(sc->sc_hunique); + } + sc->sc_hunique = mem_malloc(hunique_len); + if (sc->sc_hunique == NULL) { + goto done; + } + sc->sc_hunique_len = hunique_len; + MEMCPY(sc->sc_hunique, hunique, hunique_len); + } + pppoe_send_pads(sc); + sc->sc_state = PPPOE_STATE_SESSION; + pppoe_linkstatus_up(sc); /* notify upper layers */ + break; +#else + /* ignore, we are no access concentrator */ + goto done; +#endif /* PPPOE_SERVER */ + case PPPOE_CODE_PADO: + if (sc == NULL) { + /* be quiet if there is not a single pppoe instance */ + if (pppoe_softc_list != NULL) { + PPPDEBUG(LOG_DEBUG, ("pppoe: received PADO but could not find request for it\n")); + } + goto done; + } + if (sc->sc_state != PPPOE_STATE_PADI_SENT) { + PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": received unexpected PADO\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + goto done; + } + if (ac_cookie) { + sc->sc_ac_cookie_len = ac_cookie_len; + MEMCPY(sc->sc_ac_cookie, ac_cookie, ac_cookie_len); + } + MEMCPY(&sc->sc_dest, ethhdr->src.addr, sizeof(sc->sc_dest.addr)); + sys_untimeout(pppoe_timeout, sc); + sc->sc_padr_retried = 0; + sc->sc_state = PPPOE_STATE_PADR_SENT; + if ((err = pppoe_send_padr(sc)) != 0) { + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADR, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); + } + sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padr_retried), pppoe_timeout, sc); + break; + case PPPOE_CODE_PADS: + if (sc == NULL) { + goto done; + } + sc->sc_session = session; + sys_untimeout(pppoe_timeout, sc); + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": session 0x%x connected\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, session)); + sc->sc_state = PPPOE_STATE_SESSION; + pppoe_linkstatus_up(sc); /* notify upper layers */ + break; + case PPPOE_CODE_PADT: + if (sc == NULL) { + goto done; + } + pppoe_clear_softc(sc, "received PADT"); + break; + default: + if(sc) { + PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": unknown code (0x%"X16_F") session = 0x%"X16_F"\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, + (u16_t)ph->code, session)); + } else { + PPPDEBUG(LOG_DEBUG, ("pppoe: unknown code (0x%"X16_F") session = 0x%"X16_F"\n", (u16_t)ph->code, session)); + } + break; + } + +done: + pbuf_free(pb); + return; +} + +void +pppoe_data_input(struct netif *netif, struct pbuf *pb) +{ + u16_t session, plen; + struct pppoe_softc *sc; + struct pppoehdr *ph; +#ifdef PPPOE_TERM_UNKNOWN_SESSIONS + u8_t shost[ETHER_ADDR_LEN]; +#endif + +#ifdef PPPOE_TERM_UNKNOWN_SESSIONS + MEMCPY(shost, ((struct eth_hdr *)pb->payload)->src.addr, sizeof(shost)); +#endif + if (pbuf_header(pb, -(int)sizeof(struct eth_hdr)) != 0) { + /* bail out */ + PPPDEBUG(LOG_ERR, ("pppoe_data_input: pbuf_header failed\n")); + LINK_STATS_INC(link.lenerr); + goto drop; + } + + pb = ppp_singlebuf (pb); + + if (pb->len <= PPPOE_HEADERLEN) { + PPPDEBUG(LOG_DEBUG, ("pppoe (data): dropping too short packet: %d bytes\n", pb->len)); + goto drop; + } + + if (pb->len < sizeof(*ph)) { + PPPDEBUG(LOG_DEBUG, ("pppoe_data_input: could not get PPPoE header\n")); + goto drop; + } + ph = (struct pppoehdr *)pb->payload; + + if (ph->vertype != PPPOE_VERTYPE) { + PPPDEBUG(LOG_DEBUG, ("pppoe (data): unknown version/type packet: 0x%x\n", ph->vertype)); + goto drop; + } + if (ph->code != 0) { + goto drop; + } + + session = ntohs(ph->session); + sc = pppoe_find_softc_by_session(session, netif); + if (sc == NULL) { +#ifdef PPPOE_TERM_UNKNOWN_SESSIONS + PPPDEBUG(LOG_DEBUG, ("pppoe: input for unknown session 0x%x, sending PADT\n", session)); + pppoe_send_padt(netif, session, shost); +#endif + goto drop; + } + + plen = ntohs(ph->plen); + + if (pbuf_header(pb, -(int)(PPPOE_HEADERLEN)) != 0) { + /* bail out */ + PPPDEBUG(LOG_ERR, ("pppoe_data_input: pbuf_header PPPOE_HEADERLEN failed\n")); + LINK_STATS_INC(link.lenerr); + goto drop; + } + + PPPDEBUG(LOG_DEBUG, ("pppoe_data_input: %c%c%"U16_F": pkthdr.len=%d, pppoe.len=%d\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, + pb->len, plen)); + + if (pb->len < plen) { + goto drop; + } + + /* Dispatch the packet thereby consuming it. */ + ppp_input(sc->pcb, pb); + return; + +drop: + pbuf_free(pb); +} + +static err_t +pppoe_output(struct pppoe_softc *sc, struct pbuf *pb) +{ + struct eth_hdr *ethhdr; + u16_t etype; + err_t res; + + if (!sc->sc_ethif) { + pbuf_free(pb); + return ERR_IF; + } + + /* make room for Ethernet header - should not fail */ + if (pbuf_header(pb, (u16_t)(sizeof(struct eth_hdr))) != 0) { + /* bail out */ + PPPDEBUG(LOG_ERR, ("pppoe: %c%c%"U16_F": pppoe_output: could not allocate room for Ethernet header\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + LINK_STATS_INC(link.lenerr); + pbuf_free(pb); + return ERR_BUF; + } + ethhdr = (struct eth_hdr *)pb->payload; + etype = sc->sc_state == PPPOE_STATE_SESSION ? ETHTYPE_PPPOE : ETHTYPE_PPPOEDISC; + ethhdr->type = htons(etype); + MEMCPY(ðhdr->dest.addr, &sc->sc_dest.addr, sizeof(ethhdr->dest.addr)); + MEMCPY(ðhdr->src.addr, &sc->sc_ethif->hwaddr, sizeof(ethhdr->src.addr)); + + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F" (%x) state=%d, session=0x%x output -> %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F", len=%d\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, etype, + sc->sc_state, sc->sc_session, + sc->sc_dest.addr[0], sc->sc_dest.addr[1], sc->sc_dest.addr[2], sc->sc_dest.addr[3], sc->sc_dest.addr[4], sc->sc_dest.addr[5], + pb->tot_len)); + + res = sc->sc_ethif->linkoutput(sc->sc_ethif, pb); + + pbuf_free(pb); + + return res; +} + +static err_t +pppoe_send_padi(struct pppoe_softc *sc) +{ + struct pbuf *pb; + u8_t *p; + int len; +#ifdef PPPOE_TODO + int l1 = 0, l2 = 0; /* XXX: gcc */ +#endif /* PPPOE_TODO */ + + if (sc->sc_state >PPPOE_STATE_PADI_SENT) { + PPPDEBUG(LOG_ERR, ("ERROR: pppoe_send_padi in state %d", sc->sc_state)); + } + + /* calculate length of frame (excluding ethernet header + pppoe header) */ + len = 2 + 2 + 2 + 2 + sizeof sc; /* service name tag is required, host unique is send too */ +#ifdef PPPOE_TODO + if (sc->sc_service_name != NULL) { + l1 = (int)strlen(sc->sc_service_name); + len += l1; + } + if (sc->sc_concentrator_name != NULL) { + l2 = (int)strlen(sc->sc_concentrator_name); + len += 2 + 2 + l2; + } +#endif /* PPPOE_TODO */ + LWIP_ASSERT("sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff", + sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff); + + /* allocate a buffer */ + pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN + len), PBUF_RAM); + if (!pb) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + + p = (u8_t*)pb->payload; + /* fill in pkt */ + PPPOE_ADD_HEADER(p, PPPOE_CODE_PADI, 0, (u16_t)len); + PPPOE_ADD_16(p, PPPOE_TAG_SNAME); +#ifdef PPPOE_TODO + if (sc->sc_service_name != NULL) { + PPPOE_ADD_16(p, l1); + MEMCPY(p, sc->sc_service_name, l1); + p += l1; + } else +#endif /* PPPOE_TODO */ + { + PPPOE_ADD_16(p, 0); + } +#ifdef PPPOE_TODO + if (sc->sc_concentrator_name != NULL) { + PPPOE_ADD_16(p, PPPOE_TAG_ACNAME); + PPPOE_ADD_16(p, l2); + MEMCPY(p, sc->sc_concentrator_name, l2); + p += l2; + } +#endif /* PPPOE_TODO */ + PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); + PPPOE_ADD_16(p, sizeof(sc)); + MEMCPY(p, &sc, sizeof sc); + + /* send pkt */ + return pppoe_output(sc, pb); +} + +static void +pppoe_timeout(void *arg) +{ + u32_t retry_wait; + int err; + struct pppoe_softc *sc = (struct pppoe_softc*)arg; + + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": timeout\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + + switch (sc->sc_state) { + case PPPOE_STATE_PADI_SENT: + /* + * We have two basic ways of retrying: + * - Quick retry mode: try a few times in short sequence + * - Slow retry mode: we already had a connection successfully + * established and will try infinitely (without user + * intervention) + * We only enter slow retry mode if IFF_LINK1 (aka autodial) + * is not set. + */ + if (sc->sc_padi_retried < 0xff) { + sc->sc_padi_retried++; + } + if (!sc->pcb->settings.persist && sc->sc_padi_retried >= PPPOE_DISC_MAXPADI) { +#if 0 + if ((sc->sc_sppp.pp_if.if_flags & IFF_LINK1) == 0) { + /* slow retry mode */ + retry_wait = PPPOE_SLOW_RETRY; + } else +#endif + { + pppoe_abort_connect(sc); + return; + } + } + /* initialize for quick retry mode */ + retry_wait = LWIP_MIN(PPPOE_DISC_TIMEOUT * sc->sc_padi_retried, PPPOE_SLOW_RETRY); + if ((err = pppoe_send_padi(sc)) != 0) { + sc->sc_padi_retried--; + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to transmit PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); + } + sys_timeout(retry_wait, pppoe_timeout, sc); + break; + + case PPPOE_STATE_PADR_SENT: + sc->sc_padr_retried++; + if (sc->sc_padr_retried >= PPPOE_DISC_MAXPADR) { + MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); + sc->sc_state = PPPOE_STATE_PADI_SENT; + sc->sc_padr_retried = 0; + if ((err = pppoe_send_padi(sc)) != 0) { + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); + } + sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padi_retried), pppoe_timeout, sc); + return; + } + if ((err = pppoe_send_padr(sc)) != 0) { + sc->sc_padr_retried--; + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADR, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); + } + sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padr_retried), pppoe_timeout, sc); + break; + default: + return; /* all done, work in peace */ + } +} + +/* Start a connection (i.e. initiate discovery phase) */ +int +pppoe_connect(struct pppoe_softc *sc) +{ + int err; + + if (sc->sc_state != PPPOE_STATE_INITIAL) { + return EBUSY; + } + + /* stop any timer */ + sys_untimeout(pppoe_timeout, sc); + sc->sc_session = 0; + sc->sc_padi_retried = 0; + sc->sc_padr_retried = 0; +#ifdef PPPOE_SERVER + /* wait PADI if IFF_PASSIVE */ + if ((sc->sc_sppp.pp_if.if_flags & IFF_PASSIVE)) { + return 0; + } +#endif + /* save state, in case we fail to send PADI */ + sc->sc_state = PPPOE_STATE_PADI_SENT; + if ((err = pppoe_send_padi(sc)) != 0) { + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); + } + sys_timeout(PPPOE_DISC_TIMEOUT, pppoe_timeout, sc); + return err; +} + +/* disconnect */ +void +pppoe_disconnect(struct pppoe_softc *sc) +{ + if (sc->sc_state < PPPOE_STATE_SESSION) { + return; + } + + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": disconnecting\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + pppoe_send_padt(sc->sc_ethif, sc->sc_session, (const u8_t *)&sc->sc_dest); + + /* cleanup softc */ + sc->sc_state = PPPOE_STATE_INITIAL; + MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); + sc->sc_ac_cookie_len = 0; +#ifdef PPPOE_SERVER + if (sc->sc_hunique) { + mem_free(sc->sc_hunique); + sc->sc_hunique = NULL; + } + sc->sc_hunique_len = 0; +#endif + sc->sc_session = 0; + sc->sc_padi_retried = 0; + sc->sc_padr_retried = 0; + + sc->sc_link_status_cb(sc->pcb, PPPOE_CB_STATE_DOWN); /* notify upper layers */ + return; +} + +/* Connection attempt aborted */ +static void +pppoe_abort_connect(struct pppoe_softc *sc) +{ + PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": could not establish connection\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + + /* clear connection state */ + sc->sc_state = PPPOE_STATE_INITIAL; + MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); + sc->sc_ac_cookie_len = 0; + sc->sc_session = 0; + sc->sc_padi_retried = 0; + sc->sc_padr_retried = 0; + + sc->sc_link_status_cb(sc->pcb, PPPOE_CB_STATE_FAILED); /* notify upper layers */ +} + +/* Send a PADR packet */ +static err_t +pppoe_send_padr(struct pppoe_softc *sc) +{ + struct pbuf *pb; + u8_t *p; + size_t len; +#ifdef PPPOE_TODO + size_t l1 = 0; /* XXX: gcc */ +#endif /* PPPOE_TODO */ + + if (sc->sc_state != PPPOE_STATE_PADR_SENT) { + return ERR_CONN; + } + + len = 2 + 2 + 2 + 2 + sizeof(sc); /* service name, host unique */ +#ifdef PPPOE_TODO + if (sc->sc_service_name != NULL) { /* service name tag maybe empty */ + l1 = strlen(sc->sc_service_name); + len += l1; + } +#endif /* PPPOE_TODO */ + if (sc->sc_ac_cookie_len > 0) { + len += 2 + 2 + sc->sc_ac_cookie_len; /* AC cookie */ + } + LWIP_ASSERT("sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff", + sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff); + pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN + len), PBUF_RAM); + if (!pb) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + p = (u8_t*)pb->payload; + PPPOE_ADD_HEADER(p, PPPOE_CODE_PADR, 0, len); + PPPOE_ADD_16(p, PPPOE_TAG_SNAME); +#ifdef PPPOE_TODO + if (sc->sc_service_name != NULL) { + PPPOE_ADD_16(p, l1); + MEMCPY(p, sc->sc_service_name, l1); + p += l1; + } else +#endif /* PPPOE_TODO */ + { + PPPOE_ADD_16(p, 0); + } + if (sc->sc_ac_cookie_len > 0) { + PPPOE_ADD_16(p, PPPOE_TAG_ACCOOKIE); + PPPOE_ADD_16(p, sc->sc_ac_cookie_len); + MEMCPY(p, sc->sc_ac_cookie, sc->sc_ac_cookie_len); + p += sc->sc_ac_cookie_len; + } + PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); + PPPOE_ADD_16(p, sizeof(sc)); + MEMCPY(p, &sc, sizeof sc); + + return pppoe_output(sc, pb); +} + +/* send a PADT packet */ +static err_t +pppoe_send_padt(struct netif *outgoing_if, u_int session, const u8_t *dest) +{ + struct pbuf *pb; + struct eth_hdr *ethhdr; + err_t res; + u8_t *p; + + pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN), PBUF_RAM); + if (!pb) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + + pbuf_header(pb, sizeof(struct eth_hdr)); + ethhdr = (struct eth_hdr *)pb->payload; + ethhdr->type = PP_HTONS(ETHTYPE_PPPOEDISC); + MEMCPY(ðhdr->dest.addr, dest, sizeof(ethhdr->dest.addr)); + MEMCPY(ðhdr->src.addr, &outgoing_if->hwaddr, sizeof(ethhdr->src.addr)); + + p = (u8_t*)(ethhdr + 1); + PPPOE_ADD_HEADER(p, PPPOE_CODE_PADT, session, 0); + + res = outgoing_if->linkoutput(outgoing_if, pb); + + pbuf_free(pb); + + return res; +} + +#ifdef PPPOE_SERVER +static err_t +pppoe_send_pado(struct pppoe_softc *sc) +{ + struct pbuf *pb; + u8_t *p; + size_t len; + + if (sc->sc_state != PPPOE_STATE_PADO_SENT) { + return ERR_CONN; + } + + /* calc length */ + len = 0; + /* include ac_cookie */ + len += 2 + 2 + sizeof(sc); + /* include hunique */ + len += 2 + 2 + sc->sc_hunique_len; + pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN + len), PBUF_RAM); + if (!pb) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + p = (u8_t*)pb->payload; + PPPOE_ADD_HEADER(p, PPPOE_CODE_PADO, 0, len); + PPPOE_ADD_16(p, PPPOE_TAG_ACCOOKIE); + PPPOE_ADD_16(p, sizeof(sc)); + MEMCPY(p, &sc, sizeof(sc)); + p += sizeof(sc); + PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); + PPPOE_ADD_16(p, sc->sc_hunique_len); + MEMCPY(p, sc->sc_hunique, sc->sc_hunique_len); + return pppoe_output(sc, pb); +} + +static err_t +pppoe_send_pads(struct pppoe_softc *sc) +{ + struct pbuf *pb; + u8_t *p; + size_t len, l1 = 0; /* XXX: gcc */ + + if (sc->sc_state != PPPOE_STATE_PADO_SENT) { + return ERR_CONN; + } + + sc->sc_session = mono_time.tv_sec % 0xff + 1; + /* calc length */ + len = 0; + /* include hunique */ + len += 2 + 2 + 2 + 2 + sc->sc_hunique_len; /* service name, host unique*/ + if (sc->sc_service_name != NULL) { /* service name tag maybe empty */ + l1 = strlen(sc->sc_service_name); + len += l1; + } + pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN + len), PBUF_RAM); + if (!pb) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + p = (u8_t*)pb->payload; + PPPOE_ADD_HEADER(p, PPPOE_CODE_PADS, sc->sc_session, len); + PPPOE_ADD_16(p, PPPOE_TAG_SNAME); + if (sc->sc_service_name != NULL) { + PPPOE_ADD_16(p, l1); + MEMCPY(p, sc->sc_service_name, l1); + p += l1; + } else { + PPPOE_ADD_16(p, 0); + } + PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); + PPPOE_ADD_16(p, sc->sc_hunique_len); + MEMCPY(p, sc->sc_hunique, sc->sc_hunique_len); + return pppoe_output(sc, pb); +} +#endif + +err_t +pppoe_xmit(struct pppoe_softc *sc, struct pbuf *pb) +{ + u8_t *p; + size_t len; + + /* are we ready to process data yet? */ + if (sc->sc_state < PPPOE_STATE_SESSION) { + /*sppp_flush(&sc->sc_sppp.pp_if);*/ + pbuf_free(pb); + return ERR_CONN; + } + + len = pb->tot_len; + + /* make room for PPPoE header - should not fail */ + if (pbuf_header(pb, (u16_t)(PPPOE_HEADERLEN)) != 0) { + /* bail out */ + PPPDEBUG(LOG_ERR, ("pppoe: %c%c%"U16_F": pppoe_xmit: could not allocate room for PPPoE header\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + LINK_STATS_INC(link.lenerr); + pbuf_free(pb); + return ERR_BUF; + } + + p = (u8_t*)pb->payload; + PPPOE_ADD_HEADER(p, 0, sc->sc_session, len); + + return pppoe_output(sc, pb); +} + +#if 0 /*def PFIL_HOOKS*/ +static int +pppoe_ifattach_hook(void *arg, struct pbuf **mp, struct netif *ifp, int dir) +{ + struct pppoe_softc *sc; + int s; + + if (mp != (struct pbuf **)PFIL_IFNET_DETACH) { + return 0; + } + + LIST_FOREACH(sc, &pppoe_softc_list, sc_list) { + if (sc->sc_ethif != ifp) { + continue; + } + if (sc->sc_sppp.pp_if.if_flags & IFF_UP) { + sc->sc_sppp.pp_if.if_flags &= ~(IFF_UP|IFF_RUNNING); + PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": ethernet interface detached, going down\n", + sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + } + sc->sc_ethif = NULL; + pppoe_clear_softc(sc, "ethernet interface detached"); + } + + return 0; +} +#endif + +static void +pppoe_clear_softc(struct pppoe_softc *sc, const char *message) +{ + LWIP_UNUSED_ARG(message); + + /* stop timer */ + sys_untimeout(pppoe_timeout, sc); + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": session 0x%x terminated, %s\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, sc->sc_session, message)); + /* fix our state */ + sc->sc_state = PPPOE_STATE_INITIAL; + + /* notify upper layers */ + sc->sc_link_status_cb(sc->pcb, PPPOE_CB_STATE_DOWN); + + /* clean up softc */ + MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); + sc->sc_ac_cookie_len = 0; + sc->sc_session = 0; + sc->sc_padi_retried = 0; + sc->sc_padr_retried = 0; +} +#endif /* PPP_SUPPORT && PPPOE_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/pppol2tp.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/pppol2tp.c new file mode 100644 index 0000000..b526410 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/pppol2tp.c @@ -0,0 +1,1016 @@ +/** + * @file + * Network Point to Point Protocol over Layer 2 Tunneling Protocol program file. + * + */ + +/* + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +/* + * L2TP Support status: + * + * Supported: + * - L2TPv2 (PPP over L2TP, a.k.a. UDP tunnels) + * - LAC + * + * Not supported: + * - LNS (require PPP server support) + * - L2TPv3 ethernet pseudowires + * - L2TPv3 VLAN pseudowire + * - L2TPv3 PPP pseudowires + * - L2TPv3 IP encapsulation + * - L2TPv3 IP pseudowire + * - L2TP tunnel switching - http://tools.ietf.org/html/draft-ietf-l2tpext-tunnel-switching-08 + * - Multiple tunnels per UDP socket, as well as multiple sessions per tunnel + * - Hidden AVPs + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && PPPOL2TP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/err.h" +#include "lwip/memp.h" +#include "lwip/netif.h" +#include "lwip/udp.h" + +#include "netif/ppp/ppp_impl.h" +#include "netif/ppp/pppol2tp.h" + +#include "netif/ppp/magic.h" + +#if PPPOL2TP_AUTH_SUPPORT +#if LWIP_INCLUDED_POLARSSL_MD5 +#include "netif/ppp/polarssl/md5.h" +#else +#include "polarssl/md5.h" +#endif +#endif /* PPPOL2TP_AUTH_SUPPORT */ + + /* Prototypes for procedures local to this file. */ +static void pppol2tp_input(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port); +static void pppol2tp_dispatch_control_packet(pppol2tp_pcb *l2tp, struct ip_addr *addr, u16_t port, + struct pbuf *p, u16_t len, u16_t tunnel_id, u16_t session_id, u16_t ns, u16_t nr); +static void pppol2tp_timeout(void *arg); +static void pppol2tp_abort_connect(pppol2tp_pcb *l2tp); +static void pppol2tp_clear(pppol2tp_pcb *l2tp); +static err_t pppol2tp_send_sccrq(pppol2tp_pcb *l2tp); +static err_t pppol2tp_send_scccn(pppol2tp_pcb *l2tp, u16_t ns); +static err_t pppol2tp_send_icrq(pppol2tp_pcb *l2tp, u16_t ns); +static err_t pppol2tp_send_iccn(pppol2tp_pcb *l2tp, u16_t ns); +static err_t pppol2tp_send_zlb(pppol2tp_pcb *l2tp, u16_t ns); +static err_t pppol2tp_send_stopccn(pppol2tp_pcb *l2tp, u16_t ns); + + +/* Create a new L2TP session. */ +err_t pppol2tp_create(ppp_pcb *ppp, void (*link_status_cb)(ppp_pcb *pcb, int status), pppol2tp_pcb **l2tpptr, + struct netif *netif, ip_addr_t *ipaddr, u16_t port, + u8_t *secret, u8_t secret_len) { + pppol2tp_pcb *l2tp; + struct udp_pcb *udp; + + l2tp = (pppol2tp_pcb *)memp_malloc(MEMP_PPPOL2TP_PCB); + if (l2tp == NULL) { + *l2tpptr = NULL; + return ERR_MEM; + } + + udp = udp_new(); + if (udp == NULL) { + memp_free(MEMP_PPPOL2TP_PCB, l2tp); + *l2tpptr = NULL; + return ERR_MEM; + } + udp_recv(udp, pppol2tp_input, l2tp); + + memset(l2tp, 0, sizeof(pppol2tp_pcb)); + l2tp->phase = PPPOL2TP_STATE_INITIAL; + l2tp->ppp = ppp; + l2tp->udp = udp; + l2tp->link_status_cb = link_status_cb; + l2tp->netif = netif; + ip_addr_set(&l2tp->remote_ip, ipaddr); + l2tp->remote_port = port; + #if PPPOL2TP_AUTH_SUPPORT + l2tp->secret = secret; + l2tp->secret_len = secret_len; +#endif /* PPPOL2TP_AUTH_SUPPORT */ + + *l2tpptr = l2tp; + return ERR_OK; +} + +/* Destroy a L2TP control block */ +err_t pppol2tp_destroy(pppol2tp_pcb *l2tp) { + + sys_untimeout(pppol2tp_timeout, l2tp); + if (l2tp->udp != NULL) { + udp_remove(l2tp->udp); + } + memp_free(MEMP_PPPOL2TP_PCB, l2tp); + return ERR_OK; +} + +/* Be a LAC, connect to a LNS. */ +err_t pppol2tp_connect(pppol2tp_pcb *l2tp) { + err_t err; + + if (l2tp->phase != PPPOL2TP_STATE_INITIAL) { + return ERR_VAL; + } + + pppol2tp_clear(l2tp); + + /* Listen to a random source port, we need to do that instead of using udp_connect() + * because the L2TP LNS might answer with its own random source port (!= 1701) + */ + udp_bind(l2tp->udp, IP_ADDR_ANY, 0); + +#if PPPOL2TP_AUTH_SUPPORT + /* Generate random vector */ + if (l2tp->secret != NULL) { + random_bytes(l2tp->secret_rv, sizeof(l2tp->secret_rv)); + } +#endif /* PPPOL2TP_AUTH_SUPPORT */ + + do { + l2tp->remote_tunnel_id = magic(); + } while(l2tp->remote_tunnel_id == 0); + /* save state, in case we fail to send SCCRQ */ + l2tp->sccrq_retried = 0; + l2tp->phase = PPPOL2TP_STATE_SCCRQ_SENT; + if ((err = pppol2tp_send_sccrq(l2tp)) != 0) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send SCCRQ, error=%d\n", err)); + } + sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp); + return err; +} + +/* Disconnect */ +void pppol2tp_disconnect(pppol2tp_pcb *l2tp) { + + if (l2tp->phase < PPPOL2TP_STATE_DATA) { + return; + } + + l2tp->our_ns++; + pppol2tp_send_stopccn(l2tp, l2tp->our_ns); + + pppol2tp_clear(l2tp); + l2tp->link_status_cb(l2tp->ppp, PPPOL2TP_CB_STATE_DOWN); /* notify upper layers */ +} + +/* UDP Callback for incoming L2TP frames */ +static void pppol2tp_input(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port) { + pppol2tp_pcb *l2tp = (pppol2tp_pcb*)arg; + u16_t hflags, hlen, len=0, tunnel_id=0, session_id=0, ns=0, nr=0, offset=0; + u8_t *inp; + LWIP_UNUSED_ARG(pcb); + + if (l2tp->phase < PPPOL2TP_STATE_SCCRQ_SENT) { + goto free_and_return; + } + + /* printf("-----------\nL2TP INPUT, %d\n", p->len); */ + p = ppp_singlebuf(p); + + /* L2TP header */ + if (p->len < sizeof(hflags) + sizeof(tunnel_id) + sizeof(session_id) ) { + goto packet_too_short; + } + + inp = (u8_t*)p->payload; + GETSHORT(hflags, inp); + + if (hflags & PPPOL2TP_HEADERFLAG_CONTROL) { + /* check mandatory flags for a control packet */ + if ( (hflags & PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY) != PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY ) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: mandatory header flags for control packet not set\n")); + goto free_and_return; + } + /* check forbidden flags for a control packet */ + if (hflags & PPPOL2TP_HEADERFLAG_CONTROL_FORBIDDEN) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: forbidden header flags for control packet found\n")); + goto free_and_return; + } + } else { + /* check mandatory flags for a data packet */ + if ( (hflags & PPPOL2TP_HEADERFLAG_DATA_MANDATORY) != PPPOL2TP_HEADERFLAG_DATA_MANDATORY) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: mandatory header flags for data packet not set\n")); + goto free_and_return; + } + } + + /* Expected header size */ + hlen = sizeof(hflags) + sizeof(tunnel_id) + sizeof(session_id); + if (hflags & PPPOL2TP_HEADERFLAG_LENGTH) { + hlen += sizeof(len); + } + if (hflags & PPPOL2TP_HEADERFLAG_SEQUENCE) { + hlen += sizeof(ns) + sizeof(nr); + } + if (hflags & PPPOL2TP_HEADERFLAG_OFFSET) { + hlen += sizeof(offset); + } + if (p->len < hlen) { + goto packet_too_short; + } + + if (hflags & PPPOL2TP_HEADERFLAG_LENGTH) { + GETSHORT(len, inp); + if (p->len < len || len < hlen) { + goto packet_too_short; + } + } + GETSHORT(tunnel_id, inp); + GETSHORT(session_id, inp); + if (hflags & PPPOL2TP_HEADERFLAG_SEQUENCE) { + GETSHORT(ns, inp); + GETSHORT(nr, inp); + } + if (hflags & PPPOL2TP_HEADERFLAG_OFFSET) { + GETSHORT(offset, inp) + if (offset > 4096) { /* don't be fooled with large offset which might overflow hlen */ + PPPDEBUG(LOG_DEBUG, ("pppol2tp: strange packet received, offset=%d\n", offset)); + goto free_and_return; + } + hlen += offset; + if (p->len < hlen) { + goto packet_too_short; + } + INCPTR(offset, inp); + } + + /* printf("HLEN = %d\n", hlen); */ + + /* skip L2TP header */ + if (pbuf_header(p, -hlen) != 0) { + goto free_and_return; + } + + /* printf("LEN=%d, TUNNEL_ID=%d, SESSION_ID=%d, NS=%d, NR=%d, OFFSET=%d\n", len, tunnel_id, session_id, ns, nr, offset); */ + PPPDEBUG(LOG_DEBUG, ("pppol2tp: input packet, len=%"U16_F", tunnel=%"U16_F", session=%"U16_F", ns=%"U16_F", nr=%"U16_F"\n", + len, tunnel_id, session_id, ns, nr)); + + /* Control packet */ + if (hflags & PPPOL2TP_HEADERFLAG_CONTROL) { + pppol2tp_dispatch_control_packet(l2tp, addr, port, p, len, tunnel_id, session_id, ns, nr); + goto free_and_return; + } + + /* Data packet */ + if(l2tp->phase != PPPOL2TP_STATE_DATA) { + goto free_and_return; + } + if(tunnel_id != l2tp->remote_tunnel_id) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: tunnel ID mismatch, assigned=%d, received=%d\n", l2tp->remote_tunnel_id, tunnel_id)); + goto free_and_return; + } + if(session_id != l2tp->remote_session_id) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: session ID mismatch, assigned=%d, received=%d\n", l2tp->remote_session_id, session_id)); + goto free_and_return; + } + /* + * skip address & flags if necessary + * + * RFC 2661 does not specify whether the PPP frame in the L2TP payload should + * have a HDLC header or not. We handle both cases for compatibility. + */ + GETSHORT(hflags, inp); + if (hflags == 0xff03) { + pbuf_header(p, -(s16_t)2); + } + /* Dispatch the packet thereby consuming it. */ + ppp_input(l2tp->ppp, p); + return; + +packet_too_short: + PPPDEBUG(LOG_DEBUG, ("pppol2tp: packet too short: %d\n", p->len)); +free_and_return: + pbuf_free(p); +} + +/* L2TP Control packet entry point */ +static void pppol2tp_dispatch_control_packet(pppol2tp_pcb *l2tp, struct ip_addr *addr, u16_t port, + struct pbuf *p, u16_t len, u16_t tunnel_id, u16_t session_id, u16_t ns, u16_t nr) { + u8_t *inp; + u16_t avplen, avpflags, vendorid, attributetype, messagetype=0; + err_t err; +#if PPPOL2TP_AUTH_SUPPORT + md5_context md5_ctx; + u8_t md5_hash[16]; + u8_t challenge_id = 0; +#endif /* PPPOL2TP_AUTH_SUPPORT */ + LWIP_UNUSED_ARG(addr); + LWIP_UNUSED_ARG(len); + LWIP_UNUSED_ARG(tunnel_id); + LWIP_UNUSED_ARG(session_id); + + l2tp->peer_nr = nr; + l2tp->peer_ns = ns; + /* printf("L2TP CTRL INPUT, ns=%d, nr=%d, len=%d\n", ns, nr, p->len); */ + + /* Handle the special case of the ICCN acknowledge */ + if (l2tp->phase == PPPOL2TP_STATE_ICCN_SENT && l2tp->peer_nr > l2tp->our_ns) { + l2tp->phase = PPPOL2TP_STATE_DATA; + } + + /* ZLB packets */ + if (p->len == 0) { + return; + } + + inp = (u8_t*)p->payload; + /* Decode AVPs */ + while (p->len > 0) { + if (p->len < sizeof(avpflags) + sizeof(vendorid) + sizeof(attributetype) ) { + goto packet_too_short; + } + GETSHORT(avpflags, inp); + avplen = avpflags & PPPOL2TP_AVPHEADERFLAG_LENGTHMASK; + /* printf("AVPLEN = %d\n", avplen); */ + if (p->len < avplen || avplen < sizeof(avpflags) + sizeof(vendorid) + sizeof(attributetype)) { + goto packet_too_short; + } + GETSHORT(vendorid, inp); + GETSHORT(attributetype, inp); + avplen -= sizeof(avpflags) + sizeof(vendorid) + sizeof(attributetype); + + /* Message type must be the first AVP */ + if (messagetype == 0) { + if (attributetype != 0 || vendorid != 0 || avplen != sizeof(messagetype) ) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: message type must be the first AVP\n")); + return; + } + GETSHORT(messagetype, inp); + /* printf("Message type = %d\n", messagetype); */ + switch(messagetype) { + /* Start Control Connection Reply */ + case PPPOL2TP_MESSAGETYPE_SCCRP: + /* Only accept SCCRP packet if we sent a SCCRQ */ + if (l2tp->phase != PPPOL2TP_STATE_SCCRQ_SENT) { + goto send_zlb; + } + break; + /* Incoming Call Reply */ + case PPPOL2TP_MESSAGETYPE_ICRP: + /* Only accept ICRP packet if we sent a IRCQ */ + if (l2tp->phase != PPPOL2TP_STATE_ICRQ_SENT) { + goto send_zlb; + } + break; + /* Stop Control Connection Notification */ + case PPPOL2TP_MESSAGETYPE_STOPCCN: + pppol2tp_send_zlb(l2tp, l2tp->our_ns); /* Ack the StopCCN before we switch to down state */ + if (l2tp->phase < PPPOL2TP_STATE_DATA) { + pppol2tp_abort_connect(l2tp); + } else if (l2tp->phase == PPPOL2TP_STATE_DATA) { + /* Don't disconnect here, we let the LCP Echo/Reply find the fact + * that PPP session is down. Asking the PPP stack to end the session + * require strict checking about the PPP phase to prevent endless + * disconnection loops. + */ + } + return; + default: + break; + } + goto nextavp; + } + + /* Skip proprietary L2TP extensions */ + if (vendorid != 0) { + goto skipavp; + } + + switch (messagetype) { + /* Start Control Connection Reply */ + case PPPOL2TP_MESSAGETYPE_SCCRP: + switch (attributetype) { + case PPPOL2TP_AVPTYPE_TUNNELID: + if (avplen != sizeof(l2tp->source_tunnel_id) ) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: AVP Assign tunnel ID length check failed\n")); + return; + } + GETSHORT(l2tp->source_tunnel_id, inp); + PPPDEBUG(LOG_DEBUG, ("pppol2tp: Assigned tunnel ID %"U16_F"\n", l2tp->source_tunnel_id)); + goto nextavp; +#if PPPOL2TP_AUTH_SUPPORT + case PPPOL2TP_AVPTYPE_CHALLENGE: + if (avplen == 0) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: Challenge length check failed\n")); + return; + } + if (l2tp->secret == NULL) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: Received challenge from peer and no secret key available\n")); + pppol2tp_abort_connect(l2tp); + return; + } + /* Generate hash of ID, secret, challenge */ + md5_starts(&md5_ctx); + challenge_id = PPPOL2TP_MESSAGETYPE_SCCCN; + md5_update(&md5_ctx, &challenge_id, 1); + md5_update(&md5_ctx, l2tp->secret, l2tp->secret_len); + md5_update(&md5_ctx, inp, avplen); + md5_finish(&md5_ctx, l2tp->challenge_hash); + l2tp->send_challenge = 1; + goto skipavp; + case PPPOL2TP_AVPTYPE_CHALLENGERESPONSE: + if (avplen != PPPOL2TP_AVPTYPE_CHALLENGERESPONSE_SIZE) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: AVP Challenge Response length check failed\n")); + return; + } + /* Generate hash of ID, secret, challenge */ + md5_starts(&md5_ctx); + challenge_id = PPPOL2TP_MESSAGETYPE_SCCRP; + md5_update(&md5_ctx, &challenge_id, 1); + md5_update(&md5_ctx, l2tp->secret, l2tp->secret_len); + md5_update(&md5_ctx, l2tp->secret_rv, sizeof(l2tp->secret_rv)); + md5_finish(&md5_ctx, md5_hash); + if ( memcmp(inp, md5_hash, sizeof(md5_hash)) ) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: Received challenge response from peer and secret key do not match\n")); + pppol2tp_abort_connect(l2tp); + return; + } + goto skipavp; +#endif /* PPPOL2TP_AUTH_SUPPORT */ + default: + break; + } + break; + /* Incoming Call Reply */ + case PPPOL2TP_MESSAGETYPE_ICRP: + switch (attributetype) { + case PPPOL2TP_AVPTYPE_SESSIONID: + if (avplen != sizeof(l2tp->source_session_id) ) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: AVP Assign session ID length check failed\n")); + return; + } + GETSHORT(l2tp->source_session_id, inp); + PPPDEBUG(LOG_DEBUG, ("pppol2tp: Assigned session ID %"U16_F"\n", l2tp->source_session_id)); + goto nextavp; + default: + break; + } + break; + default: + break; + } + +skipavp: + INCPTR(avplen, inp); +nextavp: + /* printf("AVP Found, vendor=%d, attribute=%d, len=%d\n", vendorid, attributetype, avplen); */ + /* next AVP */ + if (pbuf_header(p, -avplen - sizeof(avpflags) - sizeof(vendorid) - sizeof(attributetype) ) != 0) { + return; + } + } + + switch(messagetype) { + /* Start Control Connection Reply */ + case PPPOL2TP_MESSAGETYPE_SCCRP: + do { + l2tp->remote_session_id = magic(); + } while(l2tp->remote_session_id == 0); + l2tp->tunnel_port = port; /* LNS server might have chosen its own local port */ + l2tp->icrq_retried = 0; + l2tp->phase = PPPOL2TP_STATE_ICRQ_SENT; + l2tp->our_ns++; + if ((err = pppol2tp_send_scccn(l2tp, l2tp->our_ns)) != 0) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send SCCCN, error=%d\n", err)); + } + l2tp->our_ns++; + if ((err = pppol2tp_send_icrq(l2tp, l2tp->our_ns)) != 0) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send ICRQ, error=%d\n", err)); + } + sys_untimeout(pppol2tp_timeout, l2tp); + sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp); + break; + /* Incoming Call Reply */ + case PPPOL2TP_MESSAGETYPE_ICRP: + l2tp->iccn_retried = 0; + l2tp->phase = PPPOL2TP_STATE_ICCN_SENT; + l2tp->our_ns++; + l2tp->link_status_cb(l2tp->ppp, PPPOL2TP_CB_STATE_UP); /* notify upper layers */ + if ((err = pppol2tp_send_iccn(l2tp, l2tp->our_ns)) != 0) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send ICCN, error=%d\n", err)); + } + sys_untimeout(pppol2tp_timeout, l2tp); + sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp); + break; + /* Unhandled packet, send ZLB ACK */ + default: + goto send_zlb; + } + return; + +send_zlb: + pppol2tp_send_zlb(l2tp, l2tp->our_ns); + return; +packet_too_short: + PPPDEBUG(LOG_DEBUG, ("pppol2tp: packet too short: %d\n", p->len)); +} + +/* L2TP Timeout handler */ +static void pppol2tp_timeout(void *arg) { + pppol2tp_pcb *l2tp = (pppol2tp_pcb*)arg; + err_t err; + u32_t retry_wait; + + PPPDEBUG(LOG_DEBUG, ("pppol2tp: timeout\n")); + + switch (l2tp->phase) { + case PPPOL2TP_STATE_SCCRQ_SENT: + /* backoff wait */ + if (l2tp->sccrq_retried < 0xff) { + l2tp->sccrq_retried++; + } + if (!l2tp->ppp->settings.persist && l2tp->sccrq_retried >= PPPOL2TP_MAXSCCRQ) { + pppol2tp_abort_connect(l2tp); + return; + } + retry_wait = LWIP_MIN(PPPOL2TP_CONTROL_TIMEOUT * l2tp->sccrq_retried, PPPOL2TP_SLOW_RETRY); + PPPDEBUG(LOG_DEBUG, ("pppol2tp: sccrq_retried=%d\n", l2tp->sccrq_retried)); + if ((err = pppol2tp_send_sccrq(l2tp)) != 0) { + l2tp->sccrq_retried--; + PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send SCCRQ, error=%d\n", err)); + } + sys_timeout(retry_wait, pppol2tp_timeout, l2tp); + break; + + case PPPOL2TP_STATE_ICRQ_SENT: + l2tp->icrq_retried++; + if (l2tp->icrq_retried >= PPPOL2TP_MAXICRQ) { + pppol2tp_abort_connect(l2tp); + return; + } + PPPDEBUG(LOG_DEBUG, ("pppol2tp: icrq_retried=%d\n", l2tp->icrq_retried)); + if (l2tp->peer_nr <= l2tp->our_ns -1) { /* the SCCCN was not acknowledged */ + if ((err = pppol2tp_send_scccn(l2tp, l2tp->our_ns -1)) != 0) { + l2tp->icrq_retried--; + PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send SCCCN, error=%d\n", err)); + sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp); + break; + } + } + if ((err = pppol2tp_send_icrq(l2tp, l2tp->our_ns)) != 0) { + l2tp->icrq_retried--; + PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send ICRQ, error=%d\n", err)); + } + sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp); + break; + + case PPPOL2TP_STATE_ICCN_SENT: + l2tp->iccn_retried++; + if (l2tp->iccn_retried >= PPPOL2TP_MAXICCN) { + pppol2tp_abort_connect(l2tp); + return; + } + PPPDEBUG(LOG_DEBUG, ("pppol2tp: iccn_retried=%d\n", l2tp->iccn_retried)); + if ((err = pppol2tp_send_iccn(l2tp, l2tp->our_ns)) != 0) { + l2tp->iccn_retried--; + PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send ICCN, error=%d\n", err)); + } + sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp); + break; + + default: + return; /* all done, work in peace */ + } +} + +/* Connection attempt aborted */ +static void pppol2tp_abort_connect(pppol2tp_pcb *l2tp) { + PPPDEBUG(LOG_DEBUG, ("pppol2tp: could not establish connection\n")); + pppol2tp_clear(l2tp); + l2tp->link_status_cb(l2tp->ppp, PPPOL2TP_CB_STATE_FAILED); /* notify upper layers */ +} + +/* Reset L2TP control block to its initial state */ +static void pppol2tp_clear(pppol2tp_pcb *l2tp) { + /* stop any timer */ + sys_untimeout(pppol2tp_timeout, l2tp); + l2tp->phase = PPPOL2TP_STATE_INITIAL; + l2tp->tunnel_port = l2tp->remote_port; + l2tp->our_ns = 0; + l2tp->peer_nr = 0; + l2tp->peer_ns = 0; + l2tp->source_tunnel_id = 0; + l2tp->remote_tunnel_id = 0; + l2tp->source_session_id = 0; + l2tp->remote_session_id = 0; + /* l2tp->*_retried are cleared when used */ +} + +/* Initiate a new tunnel */ +static err_t pppol2tp_send_sccrq(pppol2tp_pcb *l2tp) { + struct pbuf *pb; + u8_t *p; + u16_t len; + + /* calculate UDP packet length */ + len = 12 +8 +8 +10 +10 +6+sizeof(PPPOL2TP_HOSTNAME)-1 +6+sizeof(PPPOL2TP_VENDORNAME)-1 +8 +8; +#if PPPOL2TP_AUTH_SUPPORT + if (l2tp->secret != NULL) { + len += 6 + sizeof(l2tp->secret_rv); + } +#endif /* PPPOL2TP_AUTH_SUPPORT */ + + /* allocate a buffer */ + pb = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); + if (pb == NULL) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + + p = (u8_t*)pb->payload; + /* fill in pkt */ + /* L2TP control header */ + PUTSHORT(PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY, p); + PUTSHORT(len, p); /* Length */ + PUTSHORT(0, p); /* Tunnel Id */ + PUTSHORT(0, p); /* Session Id */ + PUTSHORT(0, p); /* NS Sequence number - to peer */ + PUTSHORT(0, p); /* NR Sequence number - expected for peer */ + + /* AVP - Message type */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_MESSAGE, p); /* Attribute type: Message Type */ + PUTSHORT(PPPOL2TP_MESSAGETYPE_SCCRQ, p); /* Attribute value: Message type: SCCRQ */ + + /* AVP - L2TP Version */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_VERSION, p); /* Attribute type: Version */ + PUTSHORT(PPPOL2TP_VERSION, p); /* Attribute value: L2TP Version */ + + /* AVP - Framing capabilities */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 10, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_FRAMINGCAPABILITIES, p); /* Attribute type: Framing capabilities */ + PUTLONG(PPPOL2TP_FRAMINGCAPABILITIES, p); /* Attribute value: Framing capabilities */ + + /* AVP - Bearer capabilities */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 10, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_BEARERCAPABILITIES, p); /* Attribute type: Bearer capabilities */ + PUTLONG(PPPOL2TP_BEARERCAPABILITIES, p); /* Attribute value: Bearer capabilities */ + + /* AVP - Host name */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 6+sizeof(PPPOL2TP_HOSTNAME)-1, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_HOSTNAME, p); /* Attribute type: Hostname */ + MEMCPY(p, PPPOL2TP_HOSTNAME, sizeof(PPPOL2TP_HOSTNAME)-1); /* Attribute value: Hostname */ + INCPTR(sizeof(PPPOL2TP_HOSTNAME)-1, p); + + /* AVP - Vendor name */ + PUTSHORT(6+sizeof(PPPOL2TP_VENDORNAME)-1, p); /* len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_VENDORNAME, p); /* Attribute type: Vendor name */ + MEMCPY(p, PPPOL2TP_VENDORNAME, sizeof(PPPOL2TP_VENDORNAME)-1); /* Attribute value: Vendor name */ + INCPTR(sizeof(PPPOL2TP_VENDORNAME)-1, p); + + /* AVP - Assign tunnel ID */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_TUNNELID, p); /* Attribute type: Tunnel ID */ + PUTSHORT(l2tp->remote_tunnel_id, p); /* Attribute value: Tunnel ID */ + + /* AVP - Receive window size */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_RECEIVEWINDOWSIZE, p); /* Attribute type: Receive window size */ + PUTSHORT(PPPOL2TP_RECEIVEWINDOWSIZE, p); /* Attribute value: Receive window size */ + +#if PPPOL2TP_AUTH_SUPPORT + /* AVP - Challenge */ + if (l2tp->secret != NULL) { + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 6 + sizeof(l2tp->secret_rv), p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_CHALLENGE, p); /* Attribute type: Challenge */ + MEMCPY(p, l2tp->secret_rv, sizeof(l2tp->secret_rv)); /* Attribute value: Random vector */ + INCPTR(sizeof(l2tp->secret_rv), p); + } +#endif /* PPPOL2TP_AUTH_SUPPORT */ + + if(l2tp->netif) { + udp_sendto_if(l2tp->udp, pb, &l2tp->remote_ip, l2tp->remote_port, l2tp->netif); + } else { + udp_sendto(l2tp->udp, pb, &l2tp->remote_ip, l2tp->remote_port); + } + pbuf_free(pb); + return ERR_OK; +} + +/* Complete tunnel establishment */ +static err_t pppol2tp_send_scccn(pppol2tp_pcb *l2tp, u16_t ns) { + struct pbuf *pb; + u8_t *p; + u16_t len; + + /* calculate UDP packet length */ + len = 12 +8; +#if PPPOL2TP_AUTH_SUPPORT + if (l2tp->send_challenge) { + len += 6 + sizeof(l2tp->challenge_hash); + } +#endif /* PPPOL2TP_AUTH_SUPPORT */ + + /* allocate a buffer */ + pb = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); + if (pb == NULL) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + + p = (u8_t*)pb->payload; + /* fill in pkt */ + /* L2TP control header */ + PUTSHORT(PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY, p); + PUTSHORT(len, p); /* Length */ + PUTSHORT(l2tp->source_tunnel_id, p); /* Tunnel Id */ + PUTSHORT(0, p); /* Session Id */ + PUTSHORT(ns, p); /* NS Sequence number - to peer */ + PUTSHORT(l2tp->peer_ns+1, p); /* NR Sequence number - expected for peer */ + + /* AVP - Message type */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_MESSAGE, p); /* Attribute type: Message Type */ + PUTSHORT(PPPOL2TP_MESSAGETYPE_SCCCN, p); /* Attribute value: Message type: SCCCN */ + +#if PPPOL2TP_AUTH_SUPPORT + /* AVP - Challenge response */ + if (l2tp->send_challenge) { + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 6 + sizeof(l2tp->challenge_hash), p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_CHALLENGERESPONSE, p); /* Attribute type: Challenge response */ + MEMCPY(p, l2tp->challenge_hash, sizeof(l2tp->challenge_hash)); /* Attribute value: Computed challenge */ + INCPTR(sizeof(l2tp->challenge_hash), p); + } +#endif /* PPPOL2TP_AUTH_SUPPORT */ + + if(l2tp->netif) { + udp_sendto_if(l2tp->udp, pb, &l2tp->remote_ip, l2tp->remote_port, l2tp->netif); + } else { + udp_sendto(l2tp->udp, pb, &l2tp->remote_ip, l2tp->remote_port); + } + pbuf_free(pb); + return ERR_OK; +} + +/* Initiate a new session */ +static err_t pppol2tp_send_icrq(pppol2tp_pcb *l2tp, u16_t ns) { + struct pbuf *pb; + u8_t *p; + u16_t len; + u32_t serialnumber; + + /* calculate UDP packet length */ + len = 12 +8 +8 +10; + + /* allocate a buffer */ + pb = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); + if (pb == NULL) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + + p = (u8_t*)pb->payload; + /* fill in pkt */ + /* L2TP control header */ + PUTSHORT(PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY, p); + PUTSHORT(len, p); /* Length */ + PUTSHORT(l2tp->source_tunnel_id, p); /* Tunnel Id */ + PUTSHORT(0, p); /* Session Id */ + PUTSHORT(ns, p); /* NS Sequence number - to peer */ + PUTSHORT(l2tp->peer_ns+1, p); /* NR Sequence number - expected for peer */ + + /* AVP - Message type */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_MESSAGE, p); /* Attribute type: Message Type */ + PUTSHORT(PPPOL2TP_MESSAGETYPE_ICRQ, p); /* Attribute value: Message type: ICRQ */ + + /* AVP - Assign session ID */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_SESSIONID, p); /* Attribute type: Session ID */ + PUTSHORT(l2tp->remote_session_id, p); /* Attribute value: Session ID */ + + /* AVP - Call Serial Number */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 10, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_CALLSERIALNUMBER, p); /* Attribute type: Serial number */ + serialnumber = magic(); + PUTLONG(serialnumber, p); /* Attribute value: Serial number */ + + if(l2tp->netif) { + udp_sendto_if(l2tp->udp, pb, &l2tp->remote_ip, l2tp->remote_port, l2tp->netif); + } else { + udp_sendto(l2tp->udp, pb, &l2tp->remote_ip, l2tp->remote_port); + } + pbuf_free(pb); + return ERR_OK; +} + +/* Complete tunnel establishment */ +static err_t pppol2tp_send_iccn(pppol2tp_pcb *l2tp, u16_t ns) { + struct pbuf *pb; + u8_t *p; + u16_t len; + + /* calculate UDP packet length */ + len = 12 +8 +10 +10; + + /* allocate a buffer */ + pb = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); + if (pb == NULL) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + + p = (u8_t*)pb->payload; + /* fill in pkt */ + /* L2TP control header */ + PUTSHORT(PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY, p); + PUTSHORT(len, p); /* Length */ + PUTSHORT(l2tp->source_tunnel_id, p); /* Tunnel Id */ + PUTSHORT(l2tp->source_session_id, p); /* Session Id */ + PUTSHORT(ns, p); /* NS Sequence number - to peer */ + PUTSHORT(l2tp->peer_ns+1, p); /* NR Sequence number - expected for peer */ + + /* AVP - Message type */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_MESSAGE, p); /* Attribute type: Message Type */ + PUTSHORT(PPPOL2TP_MESSAGETYPE_ICCN, p); /* Attribute value: Message type: ICCN */ + + /* AVP - Framing type */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 10, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_FRAMINGTYPE, p); /* Attribute type: Framing type */ + PUTLONG(PPPOL2TP_FRAMINGTYPE, p); /* Attribute value: Framing type */ + + /* AVP - TX Connect speed */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 10, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_TXCONNECTSPEED, p); /* Attribute type: TX Connect speed */ + PUTLONG(PPPOL2TP_TXCONNECTSPEED, p); /* Attribute value: TX Connect speed */ + + if(l2tp->netif) { + udp_sendto_if(l2tp->udp, pb, &l2tp->remote_ip, l2tp->remote_port, l2tp->netif); + } else { + udp_sendto(l2tp->udp, pb, &l2tp->remote_ip, l2tp->remote_port); + } + pbuf_free(pb); + return ERR_OK; +} + +/* Send a ZLB ACK packet */ +static err_t pppol2tp_send_zlb(pppol2tp_pcb *l2tp, u16_t ns) { + struct pbuf *pb; + u8_t *p; + u16_t len; + + /* calculate UDP packet length */ + len = 12; + + /* allocate a buffer */ + pb = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); + if (pb == NULL) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + + p = (u8_t*)pb->payload; + /* fill in pkt */ + /* L2TP control header */ + PUTSHORT(PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY, p); + PUTSHORT(len, p); /* Length */ + PUTSHORT(l2tp->source_tunnel_id, p); /* Tunnel Id */ + PUTSHORT(0, p); /* Session Id */ + PUTSHORT(ns, p); /* NS Sequence number - to peer */ + PUTSHORT(l2tp->peer_ns+1, p); /* NR Sequence number - expected for peer */ + + if(l2tp->netif) { + udp_sendto_if(l2tp->udp, pb, &l2tp->remote_ip, l2tp->remote_port, l2tp->netif); + } else { + udp_sendto(l2tp->udp, pb, &l2tp->remote_ip, l2tp->remote_port); + } + pbuf_free(pb); + return ERR_OK; +} + +/* Send a StopCCN packet */ +static err_t pppol2tp_send_stopccn(pppol2tp_pcb *l2tp, u16_t ns) { + struct pbuf *pb; + u8_t *p; + u16_t len; + + /* calculate UDP packet length */ + len = 12 +8 +8 +8; + + /* allocate a buffer */ + pb = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); + if (pb == NULL) { + return ERR_MEM; + } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); + + p = (u8_t*)pb->payload; + /* fill in pkt */ + /* L2TP control header */ + PUTSHORT(PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY, p); + PUTSHORT(len, p); /* Length */ + PUTSHORT(l2tp->source_tunnel_id, p); /* Tunnel Id */ + PUTSHORT(0, p); /* Session Id */ + PUTSHORT(ns, p); /* NS Sequence number - to peer */ + PUTSHORT(l2tp->peer_ns+1, p); /* NR Sequence number - expected for peer */ + + /* AVP - Message type */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_MESSAGE, p); /* Attribute type: Message Type */ + PUTSHORT(PPPOL2TP_MESSAGETYPE_STOPCCN, p); /* Attribute value: Message type: StopCCN */ + + /* AVP - Assign tunnel ID */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_TUNNELID, p); /* Attribute type: Tunnel ID */ + PUTSHORT(l2tp->remote_tunnel_id, p); /* Attribute value: Tunnel ID */ + + /* AVP - Result code */ + PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ + PUTSHORT(0, p); /* Vendor ID */ + PUTSHORT(PPPOL2TP_AVPTYPE_RESULTCODE, p); /* Attribute type: Result code */ + PUTSHORT(PPPOL2TP_RESULTCODE, p); /* Attribute value: Result code */ + + if(l2tp->netif) { + udp_sendto_if(l2tp->udp, pb, &l2tp->remote_ip, l2tp->remote_port, l2tp->netif); + } else { + udp_sendto(l2tp->udp, pb, &l2tp->remote_ip, l2tp->remote_port); + } + pbuf_free(pb); + return ERR_OK; +} + +err_t pppol2tp_xmit(pppol2tp_pcb *l2tp, struct pbuf *pb) { + u8_t *p; + + /* are we ready to process data yet? */ + if (l2tp->phase < PPPOL2TP_STATE_DATA) { + pbuf_free(pb); + return ERR_CONN; + } + + /* make room for L2TP header - should not fail */ + if (pbuf_header(pb, PPPOL2TP_OUTPUT_DATA_HEADER_LEN) != 0) { + /* bail out */ + PPPDEBUG(LOG_ERR, ("pppol2tp: pppol2tp_pcb: could not allocate room for L2TP header\n")); + LINK_STATS_INC(link.lenerr); + pbuf_free(pb); + return ERR_BUF; + } + + p = (u8_t*)pb->payload; + PUTSHORT(PPPOL2TP_HEADERFLAG_DATA_MANDATORY, p); + PUTSHORT(l2tp->source_tunnel_id, p); /* Tunnel Id */ + PUTSHORT(l2tp->source_session_id, p); /* Session Id */ + + if(l2tp->netif) { + udp_sendto_if(l2tp->udp, pb, &l2tp->remote_ip, l2tp->remote_port, l2tp->netif); + } else { + udp_sendto(l2tp->udp, pb, &l2tp->remote_ip, l2tp->remote_port); + } + pbuf_free(pb); + return ERR_OK; +} + +#endif /* PPP_SUPPORT && PPPOL2TP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/upap.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/upap.c new file mode 100644 index 0000000..14f80b6 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/upap.c @@ -0,0 +1,682 @@ +/* + * upap.c - User/Password Authentication Protocol. + * + * Copyright (c) 1984-2000 Carnegie Mellon University. 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. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && PAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +/* + * TODO: + */ + +#if 0 /* UNUSED */ +#include +#include +#endif /* UNUSED */ + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/upap.h" + +#if PPP_OPTIONS +/* + * Command-line options. + */ +static option_t pap_option_list[] = { + { "hide-password", o_bool, &hide_password, + "Don't output passwords to log", OPT_PRIO | 1 }, + { "show-password", o_bool, &hide_password, + "Show password string in debug log messages", OPT_PRIOSUB | 0 }, + + { "pap-restart", o_int, &upap[0].us_timeouttime, + "Set retransmit timeout for PAP", OPT_PRIO }, + { "pap-max-authreq", o_int, &upap[0].us_maxtransmits, + "Set max number of transmissions for auth-reqs", OPT_PRIO }, + { "pap-timeout", o_int, &upap[0].us_reqtimeout, + "Set time limit for peer PAP authentication", OPT_PRIO }, + + { NULL } +}; +#endif /* PPP_OPTIONS */ + +/* + * Protocol entry points. + */ +static void upap_init(ppp_pcb *pcb); +static void upap_lowerup(ppp_pcb *pcb); +static void upap_lowerdown(ppp_pcb *pcb); +static void upap_input(ppp_pcb *pcb, u_char *inpacket, int l); +static void upap_protrej(ppp_pcb *pcb); +#if PRINTPKT_SUPPORT +static int upap_printpkt(u_char *p, int plen, void (*printer) (void *, const char *, ...), void *arg); +#endif /* PRINTPKT_SUPPORT */ + +const struct protent pap_protent = { + PPP_PAP, + upap_init, + upap_input, + upap_protrej, + upap_lowerup, + upap_lowerdown, + NULL, + NULL, +#if PRINTPKT_SUPPORT + upap_printpkt, +#endif /* PRINTPKT_SUPPORT */ + NULL, + 1, +#if PRINTPKT_SUPPORT + "PAP", + NULL, +#endif /* PRINTPKT_SUPPORT */ +#if PPP_OPTIONS + pap_option_list, + NULL, +#endif /* PPP_OPTIONS */ +#if DEMAND_SUPPORT + NULL, + NULL +#endif /* DEMAND_SUPPORT */ +}; + +static void upap_timeout(void *arg); +#if PPP_SERVER +static void upap_reqtimeout(void *arg); +static void upap_rauthreq(ppp_pcb *pcb, u_char *inp, int id, int len); +#endif /* PPP_SERVER */ +static void upap_rauthack(ppp_pcb *pcb, u_char *inp, int id, int len); +static void upap_rauthnak(ppp_pcb *pcb, u_char *inp, int id, int len); +static void upap_sauthreq(ppp_pcb *pcb); +#if PPP_SERVER +static void upap_sresp(ppp_pcb *pcb, u_char code, u_char id, const char *msg, int msglen); +#endif /* PPP_SERVER */ + + +/* + * upap_init - Initialize a UPAP unit. + */ +static void upap_init(ppp_pcb *pcb) { + pcb->upap.us_user = NULL; + pcb->upap.us_userlen = 0; + pcb->upap.us_passwd = NULL; + pcb->upap.us_passwdlen = 0; + pcb->upap.us_clientstate = UPAPCS_INITIAL; +#if PPP_SERVER + pcb->upap.us_serverstate = UPAPSS_INITIAL; +#endif /* PPP_SERVER */ + pcb->upap.us_id = 0; +} + + +/* + * upap_authwithpeer - Authenticate us with our peer (start client). + * + * Set new state and send authenticate's. + */ +void upap_authwithpeer(ppp_pcb *pcb, const char *user, const char *password) { + + if(!user || !password) + return; + + /* Save the username and password we're given */ + pcb->upap.us_user = user; + pcb->upap.us_userlen = LWIP_MIN(strlen(user), 0xff); + pcb->upap.us_passwd = password; + pcb->upap.us_passwdlen = LWIP_MIN(strlen(password), 0xff); + pcb->upap.us_transmits = 0; + + /* Lower layer up yet? */ + if (pcb->upap.us_clientstate == UPAPCS_INITIAL || + pcb->upap.us_clientstate == UPAPCS_PENDING) { + pcb->upap.us_clientstate = UPAPCS_PENDING; + return; + } + + upap_sauthreq(pcb); /* Start protocol */ +} + +#if PPP_SERVER +/* + * upap_authpeer - Authenticate our peer (start server). + * + * Set new state. + */ +void upap_authpeer(ppp_pcb *pcb) { + + /* Lower layer up yet? */ + if (pcb->upap.us_serverstate == UPAPSS_INITIAL || + pcb->upap.us_serverstate == UPAPSS_PENDING) { + pcb->upap.us_serverstate = UPAPSS_PENDING; + return; + } + + pcb->upap.us_serverstate = UPAPSS_LISTEN; + if (pcb->settings.pap_req_timeout > 0) + TIMEOUT(upap_reqtimeout, pcb, pcb->settings.pap_req_timeout); +} +#endif /* PPP_SERVER */ + +/* + * upap_timeout - Retransmission timer for sending auth-reqs expired. + */ +static void upap_timeout(void *arg) { + ppp_pcb *pcb = (ppp_pcb*)arg; + + if (pcb->upap.us_clientstate != UPAPCS_AUTHREQ) + return; + + if (pcb->upap.us_transmits >= pcb->settings.pap_max_transmits) { + /* give up in disgust */ + ppp_error("No response to PAP authenticate-requests"); + pcb->upap.us_clientstate = UPAPCS_BADAUTH; + auth_withpeer_fail(pcb, PPP_PAP); + return; + } + + upap_sauthreq(pcb); /* Send Authenticate-Request */ +} + + +#if PPP_SERVER +/* + * upap_reqtimeout - Give up waiting for the peer to send an auth-req. + */ +static void upap_reqtimeout(void *arg) { + ppp_pcb *pcb = (ppp_pcb*)arg; + + if (pcb->upap.us_serverstate != UPAPSS_LISTEN) + return; /* huh?? */ + + auth_peer_fail(pcb, PPP_PAP); + pcb->upap.us_serverstate = UPAPSS_BADAUTH; +} +#endif /* PPP_SERVER */ + + +/* + * upap_lowerup - The lower layer is up. + * + * Start authenticating if pending. + */ +static void upap_lowerup(ppp_pcb *pcb) { + + if (pcb->upap.us_clientstate == UPAPCS_INITIAL) + pcb->upap.us_clientstate = UPAPCS_CLOSED; + else if (pcb->upap.us_clientstate == UPAPCS_PENDING) { + upap_sauthreq(pcb); /* send an auth-request */ + } + +#if PPP_SERVER + if (pcb->upap.us_serverstate == UPAPSS_INITIAL) + pcb->upap.us_serverstate = UPAPSS_CLOSED; + else if (pcb->upap.us_serverstate == UPAPSS_PENDING) { + pcb->upap.us_serverstate = UPAPSS_LISTEN; + if (pcb->settings.pap_req_timeout > 0) + TIMEOUT(upap_reqtimeout, pcb, pcb->settings.pap_req_timeout); + } +#endif /* PPP_SERVER */ +} + + +/* + * upap_lowerdown - The lower layer is down. + * + * Cancel all timeouts. + */ +static void upap_lowerdown(ppp_pcb *pcb) { + + if (pcb->upap.us_clientstate == UPAPCS_AUTHREQ) /* Timeout pending? */ + UNTIMEOUT(upap_timeout, pcb); /* Cancel timeout */ +#if PPP_SERVER + if (pcb->upap.us_serverstate == UPAPSS_LISTEN && pcb->settings.pap_req_timeout > 0) + UNTIMEOUT(upap_reqtimeout, pcb); +#endif /* PPP_SERVER */ + + pcb->upap.us_clientstate = UPAPCS_INITIAL; +#if PPP_SERVER + pcb->upap.us_serverstate = UPAPSS_INITIAL; +#endif /* PPP_SERVER */ +} + + +/* + * upap_protrej - Peer doesn't speak this protocol. + * + * This shouldn't happen. In any case, pretend lower layer went down. + */ +static void upap_protrej(ppp_pcb *pcb) { + + if (pcb->upap.us_clientstate == UPAPCS_AUTHREQ) { + ppp_error("PAP authentication failed due to protocol-reject"); + auth_withpeer_fail(pcb, PPP_PAP); + } +#if PPP_SERVER + if (pcb->upap.us_serverstate == UPAPSS_LISTEN) { + ppp_error("PAP authentication of peer failed (protocol-reject)"); + auth_peer_fail(pcb, PPP_PAP); + } +#endif /* PPP_SERVER */ + upap_lowerdown(pcb); +} + + +/* + * upap_input - Input UPAP packet. + */ +static void upap_input(ppp_pcb *pcb, u_char *inpacket, int l) { + u_char *inp; + u_char code, id; + int len; + + /* + * Parse header (code, id and length). + * If packet too short, drop it. + */ + inp = inpacket; + if (l < UPAP_HEADERLEN) { + UPAPDEBUG(("pap_input: rcvd short header.")); + return; + } + GETCHAR(code, inp); + GETCHAR(id, inp); + GETSHORT(len, inp); + if (len < UPAP_HEADERLEN) { + UPAPDEBUG(("pap_input: rcvd illegal length.")); + return; + } + if (len > l) { + UPAPDEBUG(("pap_input: rcvd short packet.")); + return; + } + len -= UPAP_HEADERLEN; + + /* + * Action depends on code. + */ + switch (code) { + case UPAP_AUTHREQ: +#if PPP_SERVER + upap_rauthreq(pcb, inp, id, len); +#endif /* PPP_SERVER */ + break; + + case UPAP_AUTHACK: + upap_rauthack(pcb, inp, id, len); + break; + + case UPAP_AUTHNAK: + upap_rauthnak(pcb, inp, id, len); + break; + + default: /* XXX Need code reject */ + break; + } +} + +#if PPP_SERVER +/* + * upap_rauth - Receive Authenticate. + */ +static void upap_rauthreq(ppp_pcb *pcb, u_char *inp, int id, int len) { + u_char ruserlen, rpasswdlen; + char *ruser; +#if 0 + char *rpasswd; +#endif + char rhostname[256]; + int retcode; + const char *msg; + int msglen; + + if (pcb->upap.us_serverstate < UPAPSS_LISTEN) + return; + + /* + * If we receive a duplicate authenticate-request, we are + * supposed to return the same status as for the first request. + */ + if (pcb->upap.us_serverstate == UPAPSS_OPEN) { + upap_sresp(pcb, UPAP_AUTHACK, id, "", 0); /* return auth-ack */ + return; + } + if (pcb->upap.us_serverstate == UPAPSS_BADAUTH) { + upap_sresp(pcb, UPAP_AUTHNAK, id, "", 0); /* return auth-nak */ + return; + } + + /* + * Parse user/passwd. + */ + if (len < 1) { + UPAPDEBUG(("pap_rauth: rcvd short packet.")); + return; + } + GETCHAR(ruserlen, inp); + len -= sizeof (u_char) + ruserlen + sizeof (u_char); + if (len < 0) { + UPAPDEBUG(("pap_rauth: rcvd short packet.")); + return; + } + ruser = (char *) inp; + INCPTR(ruserlen, inp); + GETCHAR(rpasswdlen, inp); + if (len < rpasswdlen) { + UPAPDEBUG(("pap_rauth: rcvd short packet.")); + return; + } + + /* FIXME: we need a way to check peer secret */ +#if 0 + rpasswd = (char *) inp; + + /* + * Check the username and password given. + */ + retcode = check_passwd(pcb->upap.us_unit, ruser, ruserlen, rpasswd, + rpasswdlen, &msg); + BZERO(rpasswd, rpasswdlen); + + /* + * Check remote number authorization. A plugin may have filled in + * the remote number or added an allowed number, and rather than + * return an authenticate failure, is leaving it for us to verify. + */ + if (retcode == UPAP_AUTHACK) { + if (!auth_number()) { + /* We do not want to leak info about the pap result. */ + retcode = UPAP_AUTHNAK; /* XXX exit value will be "wrong" */ + warn("calling number %q is not authorized", remote_number); + } + } + + msglen = strlen(msg); + if (msglen > 255) + msglen = 255; +#else + /* only here to clean compiler warnings */ + retcode = UPAP_AUTHNAK; + msg = NULL; + msglen = 0; +#endif /* 0 */ + + upap_sresp(pcb, retcode, id, msg, msglen); + + /* Null terminate and clean remote name. */ + ppp_slprintf(rhostname, sizeof(rhostname), "%.*v", ruserlen, ruser); + + if (retcode == UPAP_AUTHACK) { + pcb->upap.us_serverstate = UPAPSS_OPEN; + ppp_notice("PAP peer authentication succeeded for %q", rhostname); + auth_peer_success(pcb, PPP_PAP, 0, ruser, ruserlen); + } else { + pcb->upap.us_serverstate = UPAPSS_BADAUTH; + ppp_warn("PAP peer authentication failed for %q", rhostname); + auth_peer_fail(pcb, PPP_PAP); + } + + if (pcb->settings.pap_req_timeout > 0) + UNTIMEOUT(upap_reqtimeout, pcb); +} +#endif /* PPP_SERVER */ + +/* + * upap_rauthack - Receive Authenticate-Ack. + */ +static void upap_rauthack(ppp_pcb *pcb, u_char *inp, int id, int len) { + u_char msglen; + char *msg; + LWIP_UNUSED_ARG(id); + + if (pcb->upap.us_clientstate != UPAPCS_AUTHREQ) /* XXX */ + return; + + /* + * Parse message. + */ + if (len < 1) { + UPAPDEBUG(("pap_rauthack: ignoring missing msg-length.")); + } else { + GETCHAR(msglen, inp); + if (msglen > 0) { + len -= sizeof (u_char); + if (len < msglen) { + UPAPDEBUG(("pap_rauthack: rcvd short packet.")); + return; + } + msg = (char *) inp; + PRINTMSG(msg, msglen); + } + } + + pcb->upap.us_clientstate = UPAPCS_OPEN; + + auth_withpeer_success(pcb, PPP_PAP, 0); +} + + +/* + * upap_rauthnak - Receive Authenticate-Nak. + */ +static void upap_rauthnak(ppp_pcb *pcb, u_char *inp, int id, int len) { + u_char msglen; + char *msg; + LWIP_UNUSED_ARG(id); + + if (pcb->upap.us_clientstate != UPAPCS_AUTHREQ) /* XXX */ + return; + + /* + * Parse message. + */ + if (len < 1) { + UPAPDEBUG(("pap_rauthnak: ignoring missing msg-length.")); + } else { + GETCHAR(msglen, inp); + if (msglen > 0) { + len -= sizeof (u_char); + if (len < msglen) { + UPAPDEBUG(("pap_rauthnak: rcvd short packet.")); + return; + } + msg = (char *) inp; + PRINTMSG(msg, msglen); + } + } + + pcb->upap.us_clientstate = UPAPCS_BADAUTH; + + ppp_error("PAP authentication failed"); + auth_withpeer_fail(pcb, PPP_PAP); +} + + +/* + * upap_sauthreq - Send an Authenticate-Request. + */ +static void upap_sauthreq(ppp_pcb *pcb) { + struct pbuf *p; + u_char *outp; + int outlen; + + outlen = UPAP_HEADERLEN + 2 * sizeof (u_char) + + pcb->upap.us_userlen + pcb->upap.us_passwdlen; + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +outlen), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = (u_char*)p->payload; + MAKEHEADER(outp, PPP_PAP); + + PUTCHAR(UPAP_AUTHREQ, outp); + PUTCHAR(++pcb->upap.us_id, outp); + PUTSHORT(outlen, outp); + PUTCHAR(pcb->upap.us_userlen, outp); + MEMCPY(outp, pcb->upap.us_user, pcb->upap.us_userlen); + INCPTR(pcb->upap.us_userlen, outp); + PUTCHAR(pcb->upap.us_passwdlen, outp); + MEMCPY(outp, pcb->upap.us_passwd, pcb->upap.us_passwdlen); + + ppp_write(pcb, p); + + TIMEOUT(upap_timeout, pcb, pcb->settings.pap_timeout_time); + ++pcb->upap.us_transmits; + pcb->upap.us_clientstate = UPAPCS_AUTHREQ; +} + +#if PPP_SERVER +/* + * upap_sresp - Send a response (ack or nak). + */ +static void upap_sresp(ppp_pcb *pcb, u_char code, u_char id, const char *msg, int msglen) { + struct pbuf *p; + u_char *outp; + int outlen; + + outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen; + p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +outlen), PPP_CTRL_PBUF_TYPE); + if(NULL == p) + return; + if(p->tot_len != p->len) { + pbuf_free(p); + return; + } + + outp = (u_char*)p->payload; + MAKEHEADER(outp, PPP_PAP); + + PUTCHAR(code, outp); + PUTCHAR(id, outp); + PUTSHORT(outlen, outp); + PUTCHAR(msglen, outp); + MEMCPY(outp, msg, msglen); + + ppp_write(pcb, p); +} +#endif /* PPP_SERVER */ + +#if PRINTPKT_SUPPORT +/* + * upap_printpkt - print the contents of a PAP packet. + */ +static const char *upap_codenames[] = { + "AuthReq", "AuthAck", "AuthNak" +}; + +static int upap_printpkt(u_char *p, int plen, void (*printer) (void *, const char *, ...), void *arg) { + int code, id, len; + int mlen, ulen, wlen; + char *user, *pwd, *msg; + u_char *pstart; + + if (plen < UPAP_HEADERLEN) + return 0; + pstart = p; + GETCHAR(code, p); + GETCHAR(id, p); + GETSHORT(len, p); + if (len < UPAP_HEADERLEN || len > plen) + return 0; + + if (code >= 1 && code <= (int)sizeof(upap_codenames) / (int)sizeof(char *)) + printer(arg, " %s", upap_codenames[code-1]); + else + printer(arg, " code=0x%x", code); + printer(arg, " id=0x%x", id); + len -= UPAP_HEADERLEN; + switch (code) { + case UPAP_AUTHREQ: + if (len < 1) + break; + ulen = p[0]; + if (len < ulen + 2) + break; + wlen = p[ulen + 1]; + if (len < ulen + wlen + 2) + break; + user = (char *) (p + 1); + pwd = (char *) (p + ulen + 2); + p += ulen + wlen + 2; + len -= ulen + wlen + 2; + printer(arg, " user="); + ppp_print_string(user, ulen, printer, arg); + printer(arg, " password="); +/* FIXME: require ppp_pcb struct as printpkt() argument */ +#if 0 + if (!pcb->settings.hide_password) +#endif + ppp_print_string(pwd, wlen, printer, arg); +#if 0 + else + printer(arg, ""); +#endif + break; + case UPAP_AUTHACK: + case UPAP_AUTHNAK: + if (len < 1) + break; + mlen = p[0]; + if (len < mlen + 1) + break; + msg = (char *) (p + 1); + p += mlen + 1; + len -= mlen + 1; + printer(arg, " "); + ppp_print_string(msg, mlen, printer, arg); + break; + default: + break; + } + + /* print the rest of the bytes in the packet */ + for (; len > 0; --len) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + + return p - pstart; +} +#endif /* PRINTPKT_SUPPORT */ + +#endif /* PPP_SUPPORT && PAP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/utils.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/utils.c new file mode 100644 index 0000000..ecd305a --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/utils.c @@ -0,0 +1,964 @@ +/* + * utils.c - various utility functions used in pppd. + * + * Copyright (c) 1999-2002 Paul Mackerras. 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. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#if 0 /* UNUSED */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef SVR4 +#include +#endif +#endif /* UNUSED */ + +#include /* isdigit() */ + +#include "netif/ppp/ppp_impl.h" + +#include "netif/ppp/fsm.h" +#include "netif/ppp/lcp.h" + +#if defined(SUNOS4) +extern char *strerror(); +#endif + +static void ppp_logit(int level, const char *fmt, va_list args); +static void ppp_log_write(int level, char *buf); +#if PRINTPKT_SUPPORT +static void ppp_vslp_printer(void *arg, const char *fmt, ...); +static void ppp_format_packet(u_char *p, int len, + void (*printer) (void *, const char *, ...), void *arg); + +struct buffer_info { + char *ptr; + int len; +}; +#endif /* PRINTPKT_SUPPORT */ + +/* + * ppp_strlcpy - like strcpy/strncpy, doesn't overflow destination buffer, + * always leaves destination null-terminated (for len > 0). + */ +size_t ppp_strlcpy(char *dest, const char *src, size_t len) { + size_t ret = strlen(src); + + if (len != 0) { + if (ret < len) + strcpy(dest, src); + else { + strncpy(dest, src, len - 1); + dest[len-1] = 0; + } + } + return ret; +} + +/* + * ppp_strlcat - like strcat/strncat, doesn't overflow destination buffer, + * always leaves destination null-terminated (for len > 0). + */ +size_t ppp_strlcat(char *dest, const char *src, size_t len) { + size_t dlen = strlen(dest); + + return dlen + ppp_strlcpy(dest + dlen, src, (len > dlen? len - dlen: 0)); +} + + +/* + * ppp_slprintf - format a message into a buffer. Like sprintf except we + * also specify the length of the output buffer, and we handle + * %m (error message), %v (visible string), + * %q (quoted string), %t (current time) and %I (IP address) formats. + * Doesn't do floating-point formats. + * Returns the number of chars put into buf. + */ +int ppp_slprintf(char *buf, int buflen, const char *fmt, ...) { + va_list args; + int n; + + va_start(args, fmt); + n = ppp_vslprintf(buf, buflen, fmt, args); + va_end(args); + return n; +} + +/* + * ppp_vslprintf - like ppp_slprintf, takes a va_list instead of a list of args. + */ +#define OUTCHAR(c) (buflen > 0? (--buflen, *buf++ = (c)): 0) + +int ppp_vslprintf(char *buf, int buflen, const char *fmt, va_list args) { + int c, i, n; + int width, prec, fillch; + int base, len, neg, quoted; + unsigned long val = 0; + const char *f; + char *str, *buf0; + unsigned char *p; + char num[32]; +#if 0 /* need port */ + time_t t; +#endif /* need port */ + u32_t ip; + static char hexchars[] = "0123456789abcdef"; +#if PRINTPKT_SUPPORT + struct buffer_info bufinfo; +#endif /* PRINTPKT_SUPPORT */ + + buf0 = buf; + --buflen; + while (buflen > 0) { + for (f = fmt; *f != '%' && *f != 0; ++f) + ; + if (f > fmt) { + len = f - fmt; + if (len > buflen) + len = buflen; + memcpy(buf, fmt, len); + buf += len; + buflen -= len; + fmt = f; + } + if (*fmt == 0) + break; + c = *++fmt; + width = 0; + prec = -1; + fillch = ' '; + if (c == '0') { + fillch = '0'; + c = *++fmt; + } + if (c == '*') { + width = va_arg(args, int); + c = *++fmt; + } else { + while (isdigit(c)) { + width = width * 10 + c - '0'; + c = *++fmt; + } + } + if (c == '.') { + c = *++fmt; + if (c == '*') { + prec = va_arg(args, int); + c = *++fmt; + } else { + prec = 0; + while (isdigit(c)) { + prec = prec * 10 + c - '0'; + c = *++fmt; + } + } + } + str = 0; + base = 0; + neg = 0; + ++fmt; + switch (c) { + case 'l': + c = *fmt++; + switch (c) { + case 'd': + val = va_arg(args, long); + if ((long)val < 0) { + neg = 1; + val = (unsigned long)-val; + } + base = 10; + break; + case 'u': + val = va_arg(args, unsigned long); + base = 10; + break; + default: + OUTCHAR('%'); + OUTCHAR('l'); + --fmt; /* so %lz outputs %lz etc. */ + continue; + } + break; + case 'd': + i = va_arg(args, int); + if (i < 0) { + neg = 1; + val = -i; + } else + val = i; + base = 10; + break; + case 'u': + val = va_arg(args, unsigned int); + base = 10; + break; + case 'o': + val = va_arg(args, unsigned int); + base = 8; + break; + case 'x': + case 'X': + val = va_arg(args, unsigned int); + base = 16; + break; + case 'p': + val = (unsigned long) va_arg(args, void *); + base = 16; + neg = 2; + break; + case 's': + str = va_arg(args, char *); + break; + case 'c': + num[0] = va_arg(args, int); + num[1] = 0; + str = num; + break; +#if 0 /* do we always have strerror() in embedded ? */ + case 'm': + str = strerror(errno); + break; +#endif /* do we always have strerror() in embedded ? */ + case 'I': + ip = va_arg(args, u32_t); + ip = ntohl(ip); + ppp_slprintf(num, sizeof(num), "%d.%d.%d.%d", (ip >> 24) & 0xff, + (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff); + str = num; + break; +#if 0 /* need port */ + case 't': + time(&t); + str = ctime(&t); + str += 4; /* chop off the day name */ + str[15] = 0; /* chop off year and newline */ + break; +#endif /* need port */ + case 'v': /* "visible" string */ + case 'q': /* quoted string */ + quoted = c == 'q'; + p = va_arg(args, unsigned char *); + if (p == NULL) + p = (unsigned char *)""; + if (fillch == '0' && prec >= 0) { + n = prec; + } else { + n = strlen((char *)p); + if (prec >= 0 && n > prec) + n = prec; + } + while (n > 0 && buflen > 0) { + c = *p++; + --n; + if (!quoted && c >= 0x80) { + OUTCHAR('M'); + OUTCHAR('-'); + c -= 0x80; + } + if (quoted && (c == '"' || c == '\\')) + OUTCHAR('\\'); + if (c < 0x20 || (0x7f <= c && c < 0xa0)) { + if (quoted) { + OUTCHAR('\\'); + switch (c) { + case '\t': OUTCHAR('t'); break; + case '\n': OUTCHAR('n'); break; + case '\b': OUTCHAR('b'); break; + case '\f': OUTCHAR('f'); break; + default: + OUTCHAR('x'); + OUTCHAR(hexchars[c >> 4]); + OUTCHAR(hexchars[c & 0xf]); + } + } else { + if (c == '\t') + OUTCHAR(c); + else { + OUTCHAR('^'); + OUTCHAR(c ^ 0x40); + } + } + } else + OUTCHAR(c); + } + continue; +#if PRINTPKT_SUPPORT + case 'P': /* print PPP packet */ + bufinfo.ptr = buf; + bufinfo.len = buflen + 1; + p = va_arg(args, unsigned char *); + n = va_arg(args, int); + ppp_format_packet(p, n, ppp_vslp_printer, &bufinfo); + buf = bufinfo.ptr; + buflen = bufinfo.len - 1; + continue; +#endif /* PRINTPKT_SUPPORT */ + case 'B': + p = va_arg(args, unsigned char *); + for (n = prec; n > 0; --n) { + c = *p++; + if (fillch == ' ') + OUTCHAR(' '); + OUTCHAR(hexchars[(c >> 4) & 0xf]); + OUTCHAR(hexchars[c & 0xf]); + } + continue; + default: + *buf++ = '%'; + if (c != '%') + --fmt; /* so %z outputs %z etc. */ + --buflen; + continue; + } + if (base != 0) { + str = num + sizeof(num); + *--str = 0; + while (str > num + neg) { + *--str = hexchars[val % base]; + val = val / base; + if (--prec <= 0 && val == 0) + break; + } + switch (neg) { + case 1: + *--str = '-'; + break; + case 2: + *--str = 'x'; + *--str = '0'; + break; + default: + break; + } + len = num + sizeof(num) - 1 - str; + } else { + len = strlen(str); + if (prec >= 0 && len > prec) + len = prec; + } + if (width > 0) { + if (width > buflen) + width = buflen; + if ((n = width - len) > 0) { + buflen -= n; + for (; n > 0; --n) + *buf++ = fillch; + } + } + if (len > buflen) + len = buflen; + memcpy(buf, str, len); + buf += len; + buflen -= len; + } + *buf = 0; + return buf - buf0; +} + +#if PRINTPKT_SUPPORT +/* + * vslp_printer - used in processing a %P format + */ +static void ppp_vslp_printer(void *arg, const char *fmt, ...) { + int n; + va_list pvar; + struct buffer_info *bi; + + va_start(pvar, fmt); + bi = (struct buffer_info *) arg; + n = ppp_vslprintf(bi->ptr, bi->len, fmt, pvar); + va_end(pvar); + + bi->ptr += n; + bi->len -= n; +} +#endif /* PRINTPKT_SUPPORT */ + +#if 0 /* UNUSED */ +/* + * log_packet - format a packet and log it. + */ + +void +log_packet(p, len, prefix, level) + u_char *p; + int len; + char *prefix; + int level; +{ + init_pr_log(prefix, level); + ppp_format_packet(p, len, pr_log, &level); + end_pr_log(); +} +#endif /* UNUSED */ + +#if PRINTPKT_SUPPORT +/* + * ppp_format_packet - make a readable representation of a packet, + * calling `printer(arg, format, ...)' to output it. + */ +static void ppp_format_packet(u_char *p, int len, + void (*printer) (void *, const char *, ...), void *arg) { + int i, n; + u_short proto; + const struct protent *protp; + + if (len >= 2) { + GETSHORT(proto, p); + len -= 2; + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if (proto == protp->protocol) + break; + if (protp != NULL) { + printer(arg, "[%s", protp->name); + n = (*protp->printpkt)(p, len, printer, arg); + printer(arg, "]"); + p += n; + len -= n; + } else { + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if (proto == (protp->protocol & ~0x8000)) + break; + if (protp != 0 && protp->data_name != 0) { + printer(arg, "[%s data]", protp->data_name); + if (len > 8) + printer(arg, "%.8B ...", p); + else + printer(arg, "%.*B", len, p); + len = 0; + } else + printer(arg, "[proto=0x%x]", proto); + } + } + + if (len > 32) + printer(arg, "%.32B ...", p); + else + printer(arg, "%.*B", len, p); +} +#endif /* PRINTPKT_SUPPORT */ + +#if 0 /* UNUSED */ +/* + * init_pr_log, end_pr_log - initialize and finish use of pr_log. + */ + +static char line[256]; /* line to be logged accumulated here */ +static char *linep; /* current pointer within line */ +static int llevel; /* level for logging */ + +void +init_pr_log(prefix, level) + const char *prefix; + int level; +{ + linep = line; + if (prefix != NULL) { + ppp_strlcpy(line, prefix, sizeof(line)); + linep = line + strlen(line); + } + llevel = level; +} + +void +end_pr_log() +{ + if (linep != line) { + *linep = 0; + ppp_log_write(llevel, line); + } +} + +/* + * pr_log - printer routine for outputting to log + */ +void +pr_log (void *arg, const char *fmt, ...) +{ + int l, n; + va_list pvar; + char *p, *eol; + char buf[256]; + + va_start(pvar, fmt); + n = ppp_vslprintf(buf, sizeof(buf), fmt, pvar); + va_end(pvar); + + p = buf; + eol = strchr(buf, '\n'); + if (linep != line) { + l = (eol == NULL)? n: eol - buf; + if (linep + l < line + sizeof(line)) { + if (l > 0) { + memcpy(linep, buf, l); + linep += l; + } + if (eol == NULL) + return; + p = eol + 1; + eol = strchr(p, '\n'); + } + *linep = 0; + ppp_log_write(llevel, line); + linep = line; + } + + while (eol != NULL) { + *eol = 0; + ppp_log_write(llevel, p); + p = eol + 1; + eol = strchr(p, '\n'); + } + + /* assumes sizeof(buf) <= sizeof(line) */ + l = buf + n - p; + if (l > 0) { + memcpy(line, p, n); + linep = line + l; + } +} +#endif /* UNUSED */ + +/* + * ppp_print_string - print a readable representation of a string using + * printer. + */ +void ppp_print_string(char *p, int len, void (*printer) (void *, const char *, ...), void *arg) { + int c; + + printer(arg, "\""); + for (; len > 0; --len) { + c = *p++; + if (' ' <= c && c <= '~') { + if (c == '\\' || c == '"') + printer(arg, "\\"); + printer(arg, "%c", c); + } else { + switch (c) { + case '\n': + printer(arg, "\\n"); + break; + case '\r': + printer(arg, "\\r"); + break; + case '\t': + printer(arg, "\\t"); + break; + default: + printer(arg, "\\%.3o", c); + /* no break */ + } + } + } + printer(arg, "\""); +} + +/* + * ppp_logit - does the hard work for fatal et al. + */ +static void ppp_logit(int level, const char *fmt, va_list args) { + char buf[1024]; + + ppp_vslprintf(buf, sizeof(buf), fmt, args); + ppp_log_write(level, buf); +} + +static void ppp_log_write(int level, char *buf) { + LWIP_UNUSED_ARG(level); /* necessary if PPPDEBUG is defined to an empty function */ + LWIP_UNUSED_ARG(buf); + PPPDEBUG(level, ("%s\n", buf) ); +#if 0 + if (log_to_fd >= 0 && (level != LOG_DEBUG || debug)) { + int n = strlen(buf); + + if (n > 0 && buf[n-1] == '\n') + --n; + if (write(log_to_fd, buf, n) != n + || write(log_to_fd, "\n", 1) != 1) + log_to_fd = -1; + } +#endif +} + +/* + * ppp_fatal - log an error message and die horribly. + */ +void ppp_fatal(const char *fmt, ...) { + va_list pvar; + + va_start(pvar, fmt); + ppp_logit(LOG_ERR, fmt, pvar); + va_end(pvar); + +/* FIXME: find a way to die */ +#if 0 + die(1); /* as promised */ +#endif +} + +/* + * ppp_error - log an error message. + */ +void ppp_error(const char *fmt, ...) { + va_list pvar; + + va_start(pvar, fmt); + ppp_logit(LOG_ERR, fmt, pvar); + va_end(pvar); +#if 0 /* UNUSED */ + ++error_count; +#endif /* UNUSED */ +} + +/* + * ppp_warn - log a warning message. + */ +void ppp_warn(const char *fmt, ...) { + va_list pvar; + + va_start(pvar, fmt); + ppp_logit(LOG_WARNING, fmt, pvar); + va_end(pvar); +} + +/* + * ppp_notice - log a notice-level message. + */ +void ppp_notice(const char *fmt, ...) { + va_list pvar; + + va_start(pvar, fmt); + ppp_logit(LOG_NOTICE, fmt, pvar); + va_end(pvar); +} + +/* + * ppp_info - log an informational message. + */ +void ppp_info(const char *fmt, ...) { + va_list pvar; + + va_start(pvar, fmt); + ppp_logit(LOG_INFO, fmt, pvar); + va_end(pvar); +} + +/* + * ppp_dbglog - log a debug message. + */ +void ppp_dbglog(const char *fmt, ...) { + va_list pvar; + + va_start(pvar, fmt); + ppp_logit(LOG_DEBUG, fmt, pvar); + va_end(pvar); +} + +#if PRINTPKT_SUPPORT +/* + * ppp_dump_packet - print out a packet in readable form if it is interesting. + * Assumes len >= PPP_HDRLEN. + */ +void ppp_dump_packet(const char *tag, unsigned char *p, int len) { + int proto; + + /* + * don't print IPv4 and IPv6 packets. + */ + proto = (p[0] << 8) + p[1]; + if (proto == PPP_IP) + return; +#if PPP_IPV6_SUPPORT + if (proto == PPP_IPV6) + return; +#endif + + /* + * don't print LCP echo request/reply packets if the link is up. + */ + if (proto == PPP_LCP && len >= 2 + HEADERLEN) { + unsigned char *lcp = p + 2; + int l = (lcp[2] << 8) + lcp[3]; + + if ((lcp[0] == ECHOREQ || lcp[0] == ECHOREP) + && l >= HEADERLEN && l <= len - 2) + return; + } + + ppp_dbglog("%s %P", tag, p, len); +} +#endif /* PRINTPKT_SUPPORT */ + +#if 0 /* Unused */ + +/* + * complete_read - read a full `count' bytes from fd, + * unless end-of-file or an error other than EINTR is encountered. + */ +ssize_t +complete_read(int fd, void *buf, size_t count) +{ + size_t done; + ssize_t nb; + char *ptr = buf; + + for (done = 0; done < count; ) { + nb = read(fd, ptr, count - done); + if (nb < 0) { + if (errno == EINTR) + continue; + return -1; + } + if (nb == 0) + break; + done += nb; + ptr += nb; + } + return done; +} + +/* Procedures for locking the serial device using a lock file. */ +#ifndef LOCK_DIR +#ifdef __linux__ +#define LOCK_DIR "/var/lock" +#else +#ifdef SVR4 +#define LOCK_DIR "/var/spool/locks" +#else +#define LOCK_DIR "/var/spool/lock" +#endif +#endif +#endif /* LOCK_DIR */ + +static char lock_file[MAXPATHLEN]; + +/* + * lock - create a lock file for the named device + */ +int +lock(dev) + char *dev; +{ +#ifdef LOCKLIB + int result; + + result = mklock (dev, (void *) 0); + if (result == 0) { + ppp_strlcpy(lock_file, dev, sizeof(lock_file)); + return 0; + } + + if (result > 0) + ppp_notice("Device %s is locked by pid %d", dev, result); + else + ppp_error("Can't create lock file %s", lock_file); + return -1; + +#else /* LOCKLIB */ + + char lock_buffer[12]; + int fd, pid, n; + +#ifdef SVR4 + struct stat sbuf; + + if (stat(dev, &sbuf) < 0) { + ppp_error("Can't get device number for %s: %m", dev); + return -1; + } + if ((sbuf.st_mode & S_IFMT) != S_IFCHR) { + ppp_error("Can't lock %s: not a character device", dev); + return -1; + } + ppp_slprintf(lock_file, sizeof(lock_file), "%s/LK.%03d.%03d.%03d", + LOCK_DIR, major(sbuf.st_dev), + major(sbuf.st_rdev), minor(sbuf.st_rdev)); +#else + char *p; + char lockdev[MAXPATHLEN]; + + if ((p = strstr(dev, "dev/")) != NULL) { + dev = p + 4; + strncpy(lockdev, dev, MAXPATHLEN-1); + lockdev[MAXPATHLEN-1] = 0; + while ((p = strrchr(lockdev, '/')) != NULL) { + *p = '_'; + } + dev = lockdev; + } else + if ((p = strrchr(dev, '/')) != NULL) + dev = p + 1; + + ppp_slprintf(lock_file, sizeof(lock_file), "%s/LCK..%s", LOCK_DIR, dev); +#endif + + while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) { + if (errno != EEXIST) { + ppp_error("Can't create lock file %s: %m", lock_file); + break; + } + + /* Read the lock file to find out who has the device locked. */ + fd = open(lock_file, O_RDONLY, 0); + if (fd < 0) { + if (errno == ENOENT) /* This is just a timing problem. */ + continue; + ppp_error("Can't open existing lock file %s: %m", lock_file); + break; + } +#ifndef LOCK_BINARY + n = read(fd, lock_buffer, 11); +#else + n = read(fd, &pid, sizeof(pid)); +#endif /* LOCK_BINARY */ + close(fd); + fd = -1; + if (n <= 0) { + ppp_error("Can't read pid from lock file %s", lock_file); + break; + } + + /* See if the process still exists. */ +#ifndef LOCK_BINARY + lock_buffer[n] = 0; + pid = atoi(lock_buffer); +#endif /* LOCK_BINARY */ + if (pid == getpid()) + return 1; /* somebody else locked it for us */ + if (pid == 0 + || (kill(pid, 0) == -1 && errno == ESRCH)) { + if (unlink (lock_file) == 0) { + ppp_notice("Removed stale lock on %s (pid %d)", dev, pid); + continue; + } + ppp_warn("Couldn't remove stale lock on %s", dev); + } else + ppp_notice("Device %s is locked by pid %d", dev, pid); + break; + } + + if (fd < 0) { + lock_file[0] = 0; + return -1; + } + + pid = getpid(); +#ifndef LOCK_BINARY + ppp_slprintf(lock_buffer, sizeof(lock_buffer), "%10d\n", pid); + write (fd, lock_buffer, 11); +#else + write(fd, &pid, sizeof (pid)); +#endif + close(fd); + return 0; + +#endif +} + +/* + * relock - called to update our lockfile when we are about to detach, + * thus changing our pid (we fork, the child carries on, and the parent dies). + * Note that this is called by the parent, with pid equal to the pid + * of the child. This avoids a potential race which would exist if + * we had the child rewrite the lockfile (the parent might die first, + * and another process could think the lock was stale if it checked + * between when the parent died and the child rewrote the lockfile). + */ +int +relock(pid) + int pid; +{ +#ifdef LOCKLIB + /* XXX is there a way to do this? */ + return -1; +#else /* LOCKLIB */ + + int fd; + char lock_buffer[12]; + + if (lock_file[0] == 0) + return -1; + fd = open(lock_file, O_WRONLY, 0); + if (fd < 0) { + ppp_error("Couldn't reopen lock file %s: %m", lock_file); + lock_file[0] = 0; + return -1; + } + +#ifndef LOCK_BINARY + ppp_slprintf(lock_buffer, sizeof(lock_buffer), "%10d\n", pid); + write (fd, lock_buffer, 11); +#else + write(fd, &pid, sizeof(pid)); +#endif /* LOCK_BINARY */ + close(fd); + return 0; + +#endif /* LOCKLIB */ +} + +/* + * unlock - remove our lockfile + */ +void +unlock() +{ + if (lock_file[0]) { +#ifdef LOCKLIB + (void) rmlock(lock_file, (void *) 0); +#else + unlink(lock_file); +#endif + lock_file[0] = 0; + } +} + +#endif /* Unused */ + +#endif /* PPP_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/vj.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/vj.c new file mode 100644 index 0000000..dc805ad --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/ppp/vj.c @@ -0,0 +1,657 @@ +/* + * Routines to compress and uncompess tcp packets (for transmission + * over low speed serial lines. + * + * Copyright (c) 1989 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989: + * Initial distribution. + * + * Modified June 1993 by Paul Mackerras, paulus@cs.anu.edu.au, + * so that the entire packet being decompressed doesn't have + * to be in contiguous memory (just the compressed header). + * + * Modified March 1998 by Guy Lancaster, glanca@gesn.com, + * for a 16 bit processor. + */ + +#include "lwip/opt.h" +#if PPP_SUPPORT && VJ_SUPPORT /* don't build if not configured for use in lwipopts.h */ + +#include "netif/ppp/ppp_impl.h" +#include "netif/ppp/pppdebug.h" + +#include "netif/ppp/vj.h" + +#include + +#if LINK_STATS +#define INCR(counter) ++comp->stats.counter +#else +#define INCR(counter) +#endif + +void +vj_compress_init(struct vjcompress *comp) +{ + register u_char i; + register struct cstate *tstate = comp->tstate; + +#if MAX_SLOTS == 0 + memset((char *)comp, 0, sizeof(*comp)); +#endif + comp->maxSlotIndex = MAX_SLOTS - 1; + comp->compressSlot = 0; /* Disable slot ID compression by default. */ + for (i = MAX_SLOTS - 1; i > 0; --i) { + tstate[i].cs_id = i; + tstate[i].cs_next = &tstate[i - 1]; + } + tstate[0].cs_next = &tstate[MAX_SLOTS - 1]; + tstate[0].cs_id = 0; + comp->last_cs = &tstate[0]; + comp->last_recv = 255; + comp->last_xmit = 255; + comp->flags = VJF_TOSS; +} + + +/* ENCODE encodes a number that is known to be non-zero. ENCODEZ + * checks for zero (since zero has to be encoded in the long, 3 byte + * form). + */ +#define ENCODE(n) { \ + if ((u_short)(n) >= 256) { \ + *cp++ = 0; \ + cp[1] = (u_char)(n); \ + cp[0] = (u_char)((n) >> 8); \ + cp += 2; \ + } else { \ + *cp++ = (u_char)(n); \ + } \ +} +#define ENCODEZ(n) { \ + if ((u_short)(n) >= 256 || (u_short)(n) == 0) { \ + *cp++ = 0; \ + cp[1] = (u_char)(n); \ + cp[0] = (u_char)((n) >> 8); \ + cp += 2; \ + } else { \ + *cp++ = (u_char)(n); \ + } \ +} + +#define DECODEL(f) { \ + if (*cp == 0) {\ + u32_t tmp_ = ntohl(f) + ((cp[1] << 8) | cp[2]); \ + (f) = htonl(tmp_); \ + cp += 3; \ + } else { \ + u32_t tmp_ = ntohl(f) + (u32_t)*cp++; \ + (f) = htonl(tmp_); \ + } \ +} + +#define DECODES(f) { \ + if (*cp == 0) {\ + u_short tmp_ = ntohs(f) + (((u_short)cp[1] << 8) | cp[2]); \ + (f) = htons(tmp_); \ + cp += 3; \ + } else { \ + u_short tmp_ = ntohs(f) + (u_short)*cp++; \ + (f) = htons(tmp_); \ + } \ +} + +#define DECODEU(f) { \ + if (*cp == 0) {\ + (f) = htons(((u_short)cp[1] << 8) | cp[2]); \ + cp += 3; \ + } else { \ + (f) = htons((u_short)*cp++); \ + } \ +} + +/* + * vj_compress_tcp - Attempt to do Van Jacobson header compression on a + * packet. This assumes that nb and comp are not null and that the first + * buffer of the chain contains a valid IP header. + * Return the VJ type code indicating whether or not the packet was + * compressed. + */ +u_int +vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb) +{ + register struct ip_hdr *ip = (struct ip_hdr *)pb->payload; + register struct cstate *cs = comp->last_cs->cs_next; + register u_short hlen = IPH_HL(ip); + register struct tcp_hdr *oth; + register struct tcp_hdr *th; + register u_short deltaS, deltaA = 0; + register u_long deltaL; + register u_int changes = 0; + u_char new_seq[16]; + register u_char *cp = new_seq; + + /* + * Check that the packet is IP proto TCP. + */ + if (IPH_PROTO(ip) != IP_PROTO_TCP) { + return (TYPE_IP); + } + + /* + * Bail if this is an IP fragment or if the TCP packet isn't + * `compressible' (i.e., ACK isn't set or some other control bit is + * set). + */ + if ((IPH_OFFSET(ip) & PP_HTONS(0x3fff)) || pb->tot_len < 40) { + return (TYPE_IP); + } + th = (struct tcp_hdr *)&((long *)ip)[hlen]; + if ((TCPH_FLAGS(th) & (TCP_SYN|TCP_FIN|TCP_RST|TCP_ACK)) != TCP_ACK) { + return (TYPE_IP); + } + /* + * Packet is compressible -- we're going to send either a + * COMPRESSED_TCP or UNCOMPRESSED_TCP packet. Either way we need + * to locate (or create) the connection state. Special case the + * most recently used connection since it's most likely to be used + * again & we don't have to do any reordering if it's used. + */ + INCR(vjs_packets); + if (!ip_addr_cmp(&ip->src, &cs->cs_ip.src) + || !ip_addr_cmp(&ip->dest, &cs->cs_ip.dest) + || *(long *)th != ((long *)&cs->cs_ip)[IPH_HL(&cs->cs_ip)]) { + /* + * Wasn't the first -- search for it. + * + * States are kept in a circularly linked list with + * last_cs pointing to the end of the list. The + * list is kept in lru order by moving a state to the + * head of the list whenever it is referenced. Since + * the list is short and, empirically, the connection + * we want is almost always near the front, we locate + * states via linear search. If we don't find a state + * for the datagram, the oldest state is (re-)used. + */ + register struct cstate *lcs; + register struct cstate *lastcs = comp->last_cs; + + do { + lcs = cs; cs = cs->cs_next; + INCR(vjs_searches); + if (ip_addr_cmp(&ip->src, &cs->cs_ip.src) + && ip_addr_cmp(&ip->dest, &cs->cs_ip.dest) + && *(long *)th == ((long *)&cs->cs_ip)[IPH_HL(&cs->cs_ip)]) { + goto found; + } + } while (cs != lastcs); + + /* + * Didn't find it -- re-use oldest cstate. Send an + * uncompressed packet that tells the other side what + * connection number we're using for this conversation. + * Note that since the state list is circular, the oldest + * state points to the newest and we only need to set + * last_cs to update the lru linkage. + */ + INCR(vjs_misses); + comp->last_cs = lcs; + hlen += TCPH_HDRLEN(th); + hlen <<= 2; + /* Check that the IP/TCP headers are contained in the first buffer. */ + if (hlen > pb->len) { + return (TYPE_IP); + } + goto uncompressed; + + found: + /* + * Found it -- move to the front on the connection list. + */ + if (cs == lastcs) { + comp->last_cs = lcs; + } else { + lcs->cs_next = cs->cs_next; + cs->cs_next = lastcs->cs_next; + lastcs->cs_next = cs; + } + } + + oth = (struct tcp_hdr *)&((long *)&cs->cs_ip)[hlen]; + deltaS = hlen; + hlen += TCPH_HDRLEN(th); + hlen <<= 2; + /* Check that the IP/TCP headers are contained in the first buffer. */ + if (hlen > pb->len) { + PPPDEBUG(LOG_INFO, ("vj_compress_tcp: header len %d spans buffers\n", hlen)); + return (TYPE_IP); + } + + /* + * Make sure that only what we expect to change changed. The first + * line of the `if' checks the IP protocol version, header length & + * type of service. The 2nd line checks the "Don't fragment" bit. + * The 3rd line checks the time-to-live and protocol (the protocol + * check is unnecessary but costless). The 4th line checks the TCP + * header length. The 5th line checks IP options, if any. The 6th + * line checks TCP options, if any. If any of these things are + * different between the previous & current datagram, we send the + * current datagram `uncompressed'. + */ + if (((u_short *)ip)[0] != ((u_short *)&cs->cs_ip)[0] + || ((u_short *)ip)[3] != ((u_short *)&cs->cs_ip)[3] + || ((u_short *)ip)[4] != ((u_short *)&cs->cs_ip)[4] + || TCPH_HDRLEN(th) != TCPH_HDRLEN(oth) + || (deltaS > 5 && BCMP(ip + 1, &cs->cs_ip + 1, (deltaS - 5) << 2)) + || (TCPH_HDRLEN(th) > 5 && BCMP(th + 1, oth + 1, (TCPH_HDRLEN(th) - 5) << 2))) { + goto uncompressed; + } + + /* + * Figure out which of the changing fields changed. The + * receiver expects changes in the order: urgent, window, + * ack, seq (the order minimizes the number of temporaries + * needed in this section of code). + */ + if (TCPH_FLAGS(th) & TCP_URG) { + deltaS = ntohs(th->urgp); + ENCODEZ(deltaS); + changes |= NEW_U; + } else if (th->urgp != oth->urgp) { + /* argh! URG not set but urp changed -- a sensible + * implementation should never do this but RFC793 + * doesn't prohibit the change so we have to deal + * with it. */ + goto uncompressed; + } + + if ((deltaS = (u_short)(ntohs(th->wnd) - ntohs(oth->wnd))) != 0) { + ENCODE(deltaS); + changes |= NEW_W; + } + + if ((deltaL = ntohl(th->ackno) - ntohl(oth->ackno)) != 0) { + if (deltaL > 0xffff) { + goto uncompressed; + } + deltaA = (u_short)deltaL; + ENCODE(deltaA); + changes |= NEW_A; + } + + if ((deltaL = ntohl(th->seqno) - ntohl(oth->seqno)) != 0) { + if (deltaL > 0xffff) { + goto uncompressed; + } + deltaS = (u_short)deltaL; + ENCODE(deltaS); + changes |= NEW_S; + } + + switch(changes) { + case 0: + /* + * Nothing changed. If this packet contains data and the + * last one didn't, this is probably a data packet following + * an ack (normal on an interactive connection) and we send + * it compressed. Otherwise it's probably a retransmit, + * retransmitted ack or window probe. Send it uncompressed + * in case the other side missed the compressed version. + */ + if (IPH_LEN(ip) != IPH_LEN(&cs->cs_ip) && + ntohs(IPH_LEN(&cs->cs_ip)) == hlen) { + break; + } + /* no break */ + /* fall through */ + + case SPECIAL_I: + case SPECIAL_D: + /* + * actual changes match one of our special case encodings -- + * send packet uncompressed. + */ + goto uncompressed; + + case NEW_S|NEW_A: + if (deltaS == deltaA && deltaS == ntohs(IPH_LEN(&cs->cs_ip)) - hlen) { + /* special case for echoed terminal traffic */ + changes = SPECIAL_I; + cp = new_seq; + } + break; + + case NEW_S: + if (deltaS == ntohs(IPH_LEN(&cs->cs_ip)) - hlen) { + /* special case for data xfer */ + changes = SPECIAL_D; + cp = new_seq; + } + break; + default: + break; + } + + deltaS = (u_short)(ntohs(IPH_ID(ip)) - ntohs(IPH_ID(&cs->cs_ip))); + if (deltaS != 1) { + ENCODEZ(deltaS); + changes |= NEW_I; + } + if (TCPH_FLAGS(th) & TCP_PSH) { + changes |= TCP_PUSH_BIT; + } + /* + * Grab the cksum before we overwrite it below. Then update our + * state with this packet's header. + */ + deltaA = ntohs(th->chksum); + MEMCPY(&cs->cs_ip, ip, hlen); + + /* + * We want to use the original packet as our compressed packet. + * (cp - new_seq) is the number of bytes we need for compressed + * sequence numbers. In addition we need one byte for the change + * mask, one for the connection id and two for the tcp checksum. + * So, (cp - new_seq) + 4 bytes of header are needed. hlen is how + * many bytes of the original packet to toss so subtract the two to + * get the new packet size. + */ + deltaS = (u_short)(cp - new_seq); + if (!comp->compressSlot || comp->last_xmit != cs->cs_id) { + comp->last_xmit = cs->cs_id; + hlen -= deltaS + 4; + if(pbuf_header(pb, -hlen)){ + /* Can we cope with this failing? Just assert for now */ + LWIP_ASSERT("pbuf_header failed\n", 0); + } + cp = (u_char *)pb->payload; + *cp++ = (u_char)(changes | NEW_C); + *cp++ = cs->cs_id; + } else { + hlen -= deltaS + 3; + if(pbuf_header(pb, -hlen)) { + /* Can we cope with this failing? Just assert for now */ + LWIP_ASSERT("pbuf_header failed\n", 0); + } + cp = (u_char *)pb->payload; + *cp++ = (u_char)changes; + } + *cp++ = (u_char)(deltaA >> 8); + *cp++ = (u_char)deltaA; + MEMCPY(cp, new_seq, deltaS); + INCR(vjs_compressed); + return (TYPE_COMPRESSED_TCP); + + /* + * Update connection state cs & send uncompressed packet (that is, + * a regular ip/tcp packet but with the 'conversation id' we hope + * to use on future compressed packets in the protocol field). + */ +uncompressed: + MEMCPY(&cs->cs_ip, ip, hlen); + IPH_PROTO_SET(ip, cs->cs_id); + comp->last_xmit = cs->cs_id; + return (TYPE_UNCOMPRESSED_TCP); +} + +/* + * Called when we may have missed a packet. + */ +void +vj_uncompress_err(struct vjcompress *comp) +{ + comp->flags |= VJF_TOSS; + INCR(vjs_errorin); +} + +/* + * "Uncompress" a packet of type TYPE_UNCOMPRESSED_TCP. + * Return 0 on success, -1 on failure. + */ +int +vj_uncompress_uncomp(struct pbuf *nb, struct vjcompress *comp) +{ + register u_int hlen; + register struct cstate *cs; + register struct ip_hdr *ip; + + ip = (struct ip_hdr *)nb->payload; + hlen = IPH_HL(ip) << 2; + if (IPH_PROTO(ip) >= MAX_SLOTS + || hlen + sizeof(struct tcp_hdr) > nb->len + || (hlen += TCPH_HDRLEN(((struct tcp_hdr *)&((char *)ip)[hlen])) << 2) + > nb->len + || hlen > MAX_HDR) { + PPPDEBUG(LOG_INFO, ("vj_uncompress_uncomp: bad cid=%d, hlen=%d buflen=%d\n", + IPH_PROTO(ip), hlen, nb->len)); + comp->flags |= VJF_TOSS; + INCR(vjs_errorin); + return -1; + } + cs = &comp->rstate[comp->last_recv = IPH_PROTO(ip)]; + comp->flags &=~ VJF_TOSS; + IPH_PROTO_SET(ip, IP_PROTO_TCP); + MEMCPY(&cs->cs_ip, ip, hlen); + cs->cs_hlen = (u_short)hlen; + INCR(vjs_uncompressedin); + return 0; +} + +/* + * Uncompress a packet of type TYPE_COMPRESSED_TCP. + * The packet is composed of a buffer chain and the first buffer + * must contain an accurate chain length. + * The first buffer must include the entire compressed TCP/IP header. + * This procedure replaces the compressed header with the uncompressed + * header and returns the length of the VJ header. + */ +int +vj_uncompress_tcp(struct pbuf **nb, struct vjcompress *comp) +{ + u_char *cp; + struct tcp_hdr *th; + struct cstate *cs; + u_short *bp; + struct pbuf *n0 = *nb; + u32_t tmp; + u_int vjlen, hlen, changes; + + INCR(vjs_compressedin); + cp = (u_char *)n0->payload; + changes = *cp++; + if (changes & NEW_C) { + /* + * Make sure the state index is in range, then grab the state. + * If we have a good state index, clear the 'discard' flag. + */ + if (*cp >= MAX_SLOTS) { + PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: bad cid=%d\n", *cp)); + goto bad; + } + + comp->flags &=~ VJF_TOSS; + comp->last_recv = *cp++; + } else { + /* + * this packet has an implicit state index. If we've + * had a line error since the last time we got an + * explicit state index, we have to toss the packet. + */ + if (comp->flags & VJF_TOSS) { + PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: tossing\n")); + INCR(vjs_tossed); + return (-1); + } + } + cs = &comp->rstate[comp->last_recv]; + hlen = IPH_HL(&cs->cs_ip) << 2; + th = (struct tcp_hdr *)&((u_char *)&cs->cs_ip)[hlen]; + th->chksum = htons((*cp << 8) | cp[1]); + cp += 2; + if (changes & TCP_PUSH_BIT) { + TCPH_SET_FLAG(th, TCP_PSH); + } else { + TCPH_UNSET_FLAG(th, TCP_PSH); + } + + switch (changes & SPECIALS_MASK) { + case SPECIAL_I: + { + register u32_t i = ntohs(IPH_LEN(&cs->cs_ip)) - cs->cs_hlen; + /* some compilers can't nest inline assembler.. */ + tmp = ntohl(th->ackno) + i; + th->ackno = htonl(tmp); + tmp = ntohl(th->seqno) + i; + th->seqno = htonl(tmp); + } + break; + + case SPECIAL_D: + /* some compilers can't nest inline assembler.. */ + tmp = ntohl(th->seqno) + ntohs(IPH_LEN(&cs->cs_ip)) - cs->cs_hlen; + th->seqno = htonl(tmp); + break; + + default: + if (changes & NEW_U) { + TCPH_SET_FLAG(th, TCP_URG); + DECODEU(th->urgp); + } else { + TCPH_UNSET_FLAG(th, TCP_URG); + } + if (changes & NEW_W) { + DECODES(th->wnd); + } + if (changes & NEW_A) { + DECODEL(th->ackno); + } + if (changes & NEW_S) { + DECODEL(th->seqno); + } + break; + } + if (changes & NEW_I) { + DECODES(cs->cs_ip._id); + } else { + IPH_ID_SET(&cs->cs_ip, ntohs(IPH_ID(&cs->cs_ip)) + 1); + IPH_ID_SET(&cs->cs_ip, htons(IPH_ID(&cs->cs_ip))); + } + + /* + * At this point, cp points to the first byte of data in the + * packet. Fill in the IP total length and update the IP + * header checksum. + */ + vjlen = (u_short)(cp - (u_char*)n0->payload); + if (n0->len < vjlen) { + /* + * We must have dropped some characters (crc should detect + * this but the old slip framing won't) + */ + PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: head buffer %d too short %d\n", + n0->len, vjlen)); + goto bad; + } + +#if BYTE_ORDER == LITTLE_ENDIAN + tmp = n0->tot_len - vjlen + cs->cs_hlen; + IPH_LEN_SET(&cs->cs_ip, htons((u_short)tmp)); +#else + IPH_LEN_SET(&cs->cs_ip, htons(n0->tot_len - vjlen + cs->cs_hlen)); +#endif + + /* recompute the ip header checksum */ + bp = (u_short *) &cs->cs_ip; + IPH_CHKSUM_SET(&cs->cs_ip, 0); + for (tmp = 0; hlen > 0; hlen -= 2) { + tmp += *bp++; + } + tmp = (tmp & 0xffff) + (tmp >> 16); + tmp = (tmp & 0xffff) + (tmp >> 16); + IPH_CHKSUM_SET(&cs->cs_ip, (u_short)(~tmp)); + + /* Remove the compressed header and prepend the uncompressed header. */ + if(pbuf_header(n0, -((s16_t)(vjlen)))) { + /* Can we cope with this failing? Just assert for now */ + LWIP_ASSERT("pbuf_header failed\n", 0); + goto bad; + } + + if(LWIP_MEM_ALIGN(n0->payload) != n0->payload) { + struct pbuf *np, *q; + u8_t *bufptr; + +#if IP_FORWARD + /* If IP forwarding is enabled we are using a PBUF_LINK packet type so + * the packet is being allocated with enough header space to be + * forwarded (to Ethernet for example). + */ + np = pbuf_alloc(PBUF_LINK, n0->len + cs->cs_hlen, PBUF_POOL); +#else /* IP_FORWARD */ + np = pbuf_alloc(PBUF_RAW, n0->len + cs->cs_hlen, PBUF_POOL); +#endif /* IP_FORWARD */ + if(!np) { + PPPDEBUG(LOG_WARNING, ("vj_uncompress_tcp: realign failed\n")); + goto bad; + } + + if(pbuf_header(np, -cs->cs_hlen)) { + /* Can we cope with this failing? Just assert for now */ + LWIP_ASSERT("pbuf_header failed\n", 0); + goto bad; + } + + bufptr = (u8_t*)n0->payload; + for(q = np; q != NULL; q = q->next) { + MEMCPY(q->payload, bufptr, q->len); + bufptr += q->len; + } + + if(n0->next) { + pbuf_chain(np, n0->next); + pbuf_dechain(n0); + } + pbuf_free(n0); + n0 = np; + } + + if(pbuf_header(n0, cs->cs_hlen)) { + struct pbuf *np; + + LWIP_ASSERT("vj_uncompress_tcp: cs->cs_hlen <= PBUF_POOL_BUFSIZE", cs->cs_hlen <= PBUF_POOL_BUFSIZE); + np = pbuf_alloc(PBUF_RAW, cs->cs_hlen, PBUF_POOL); + if(!np) { + PPPDEBUG(LOG_WARNING, ("vj_uncompress_tcp: prepend failed\n")); + goto bad; + } + pbuf_cat(np, n0); + n0 = np; + } + LWIP_ASSERT("n0->len >= cs->cs_hlen", n0->len >= cs->cs_hlen); + MEMCPY(n0->payload, &cs->cs_ip, cs->cs_hlen); + + *nb = n0; + + return vjlen; + +bad: + comp->flags |= VJF_TOSS; + INCR(vjs_errorin); + return (-1); +} + +#endif /* PPP_SUPPORT && VJ_SUPPORT */ diff --git a/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/slipif.c b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/slipif.c new file mode 100644 index 0000000..ca9f0b9 --- /dev/null +++ b/component/common/network/lwip/lwip_v1.5.0.beta/src/netif/slipif.c @@ -0,0 +1,546 @@ +/** + * @file + * SLIP Interface + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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 Institute 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 INSTITUTE 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 INSTITUTE 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. + * + * This file is built upon the file: src/arch/rtxc/netif/sioslip.c + * + * Author: Magnus Ivarsson + * Simon Goldschmidt + * + * Usage: This netif can be used in three ways: + * 1) For NO_SYS==0, an RX thread can be used which blocks on sio_read() + * until data is received. + * 2) In your main loop, call slipif_poll() to check for new RX bytes, + * completed packets are fed into netif->input(). + * 3) Call slipif_received_byte[s]() from your serial RX ISR and + * slipif_process_rxqueue() from your main loop. ISR level decodes + * packets and puts completed packets on a queue which is fed into + * the stack from the main loop (needs SYS_LIGHTWEIGHT_PROT for + * pbuf_alloc to work on ISR level!). + * + */ + +/* + * This is an arch independent SLIP netif. The specific serial hooks must be + * provided by another file. They are sio_open, sio_read/sio_tryread and sio_send + */ + +#include "netif/slipif.h" +#include "lwip/opt.h" + +#if LWIP_HAVE_SLIPIF + +#include "lwip/def.h" +#include "lwip/pbuf.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "lwip/sys.h" +#include "lwip/sio.h" + +#define SLIP_END 0xC0 /* 0300: start and end of every packet */ +#define SLIP_ESC 0xDB /* 0333: escape start (one byte escaped data follows) */ +#define SLIP_ESC_END 0xDC /* 0334: following escape: original byte is 0xC0 (END) */ +#define SLIP_ESC_ESC 0xDD /* 0335: following escape: original byte is 0xDB (ESC) */ + +/** Maximum packet size that is received by this netif */ +#ifndef SLIP_MAX_SIZE +#define SLIP_MAX_SIZE 1500 +#endif + +/** Define this to the interface speed for SNMP + * (sio_fd is the sio_fd_t returned by sio_open). + * The default value of zero means 'unknown'. + */ +#ifndef SLIP_SIO_SPEED +#define SLIP_SIO_SPEED(sio_fd) 0 +#endif + +enum slipif_recv_state { + SLIP_RECV_NORMAL, + SLIP_RECV_ESCAPE, +}; + +struct slipif_priv { + sio_fd_t sd; + /* q is the whole pbuf chain for a packet, p is the current pbuf in the chain */ + struct pbuf *p, *q; + u8_t state; + u16_t i, recved; +#if SLIP_RX_FROM_ISR + struct pbuf *rxpackets; +#endif +}; + +/** + * Send a pbuf doing the necessary SLIP encapsulation + * + * Uses the serial layer's sio_send() + * + * @param netif the lwip network interface structure for this slipif + * @param p the pbuf chain packet to send + * @return always returns ERR_OK since the serial layer does not provide return values + */ +static err_t +slipif_output(struct netif *netif, struct pbuf *p) +{ + struct slipif_priv *priv; + struct pbuf *q; + u16_t i; + u8_t c; + + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + LWIP_ASSERT("p != NULL", (p != NULL)); + + LWIP_DEBUGF(SLIP_DEBUG, ("slipif_output(%"U16_F"): sending %"U16_F" bytes\n", (u16_t)netif->num, p->tot_len)); + priv = netif->state; + + /* Send pbuf out on the serial I/O device. */ + /* Start with packet delimiter. */ + sio_send(SLIP_END, priv->sd); + + for (q = p; q != NULL; q = q->next) { + for (i = 0; i < q->len; i++) { + c = ((u8_t *)q->payload)[i]; + switch (c) { + case SLIP_END: + /* need to escape this byte (0xC0 -> 0xDB, 0xDC) */ + sio_send(SLIP_ESC, priv->sd); + sio_send(SLIP_ESC_END, priv->sd); + break; + case SLIP_ESC: + /* need to escape this byte (0xDB -> 0xDB, 0xDD) */ + sio_send(SLIP_ESC, priv->sd); + sio_send(SLIP_ESC_ESC, priv->sd); + break; + default: + /* normal byte - no need for escaping */ + sio_send(c, priv->sd); + break; + } + } + } + /* End with packet delimiter. */ + sio_send(SLIP_END, priv->sd); + return ERR_OK; +} + +/** + * Send a pbuf doing the necessary SLIP encapsulation + * + * Uses the serial layer's sio_send() + * + * @param netif the lwip network interface structure for this slipif + * @param p the pbuf chain packet to send + * @param ipaddr the ip address to send the packet to (not used for slipif) + * @return always returns ERR_OK since the serial layer does not provide return values + */ +static err_t +slipif_output_v4(struct netif *netif, struct pbuf *p, ip_addr_t *ipaddr) +{ + LWIP_UNUSED_ARG(ipaddr); + return slipif_output(netif, p); +} + +#if LWIP_IPV6 +/** + * Send a pbuf doing the necessary SLIP encapsulation + * + * Uses the serial layer's sio_send() + * + * @param netif the lwip network interface structure for this slipif + * @param p the pbuf chain packet to send + * @param ipaddr the ip address to send the packet to (not used for slipif) + * @return always returns ERR_OK since the serial layer does not provide return values + */ +static err_t +slipif_output_v6(struct netif *netif, struct pbuf *p, ip6_addr_t *ipaddr) +{ + LWIP_UNUSED_ARG(ipaddr); + return slipif_output(netif, p); +} +#endif /* LWIP_IPV6 */ + +/** + * Handle the incoming SLIP stream character by character + * + * @param netif the lwip network interface structure for this slipif + * @param c received character (multiple calls to this function will + * return a complete packet, NULL is returned before - used for polling) + * @return The IP packet when SLIP_END is received + */ +static struct pbuf* +slipif_rxbyte(struct netif *netif, u8_t c) +{ + struct slipif_priv *priv; + struct pbuf *t; + + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + + priv = netif->state; + + switch (priv->state) { + case SLIP_RECV_NORMAL: + switch (c) { + case SLIP_END: + if (priv->recved > 0) { + /* Received whole packet. */ + /* Trim the pbuf to the size of the received packet. */ + pbuf_realloc(priv->q, priv->recved); + + LINK_STATS_INC(link.recv); + + LWIP_DEBUGF(SLIP_DEBUG, ("slipif: Got packet (%"U16_F" bytes)\n", priv->recved)); + t = priv->q; + priv->p = priv->q = NULL; + priv->i = priv->recved = 0; + return t; + } + return NULL; + case SLIP_ESC: + priv->state = SLIP_RECV_ESCAPE; + return NULL; + } /* end switch (c) */ + break; + case SLIP_RECV_ESCAPE: + /* un-escape END or ESC bytes, leave other bytes + (although that would be a protocol error) */ + switch (c) { + case SLIP_ESC_END: + c = SLIP_END; + break; + case SLIP_ESC_ESC: + c = SLIP_ESC; + break; + } + priv->state = SLIP_RECV_NORMAL; + break; + } /* end switch (priv->state) */ + + /* byte received, packet not yet completely received */ + if (priv->p == NULL) { + /* allocate a new pbuf */ + LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: alloc\n")); + priv->p = pbuf_alloc(PBUF_LINK, (PBUF_POOL_BUFSIZE - PBUF_LINK_HLEN), PBUF_POOL); + + if (priv->p == NULL) { + LINK_STATS_INC(link.drop); + LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: no new pbuf! (DROP)\n")); + /* don't process any further since we got no pbuf to receive to */ + return NULL; + } + + if (priv->q != NULL) { + /* 'chain' the pbuf to the existing chain */ + pbuf_cat(priv->q, priv->p); + } else { + /* p is the first pbuf in the chain */ + priv->q = priv->p; + } + } + + /* this automatically drops bytes if > SLIP_MAX_SIZE */ + if ((priv->p != NULL) && (priv->recved <= SLIP_MAX_SIZE)) { + ((u8_t *)priv->p->payload)[priv->i] = c; + priv->recved++; + priv->i++; + if (priv->i >= priv->p->len) { + /* on to the next pbuf */ + priv->i = 0; + if (priv->p->next != NULL && priv->p->next->len > 0) { + /* p is a chain, on to the next in the chain */ + priv->p = priv->p->next; + } else { + /* p is a single pbuf, set it to NULL so next time a new + * pbuf is allocated */ + priv->p = NULL; + } + } + } + return NULL; +} + +/** Like slipif_rxbyte, but passes completed packets to netif->input + * + * @param netif The lwip network interface structure for this slipif + * @param data received character + */ +static void +slipif_rxbyte_input(struct netif *netif, u8_t c) +{ + struct pbuf *p; + p = slipif_rxbyte(netif, c); + if (p != NULL) { + if (netif->input(p, netif) != ERR_OK) { + pbuf_free(p); + } + } +} + +#if SLIP_USE_RX_THREAD +/** + * The SLIP input thread. + * + * Feed the IP layer with incoming packets + * + * @param nf the lwip network interface structure for this slipif + */ +static void +slipif_loop_thread(void *nf) +{ + u8_t c; + struct netif *netif = (struct netif *)nf; + struct slipif_priv *priv = (struct slipif_priv *)netif->state; + + while (1) { + if (sio_read(priv->sd, &c, 1) > 0) { + slipif_rxbyte_input(netif, c); + } + } +} +#endif /* SLIP_USE_RX_THREAD */ + +/** + * SLIP netif initialization + * + * Call the arch specific sio_open and remember + * the opened device in the state field of the netif. + * + * @param netif the lwip network interface structure for this slipif + * @return ERR_OK if serial line could be opened, + * ERR_MEM if no memory could be allocated, + * ERR_IF is serial line couldn't be opened + * + * @note netif->num must contain the number of the serial port to open + * (0 by default). If netif->state is != NULL, it is interpreted as an + * u8_t pointer pointing to the serial port number instead of netif->num. + * + */ +err_t +slipif_init(struct netif *netif) +{ + struct slipif_priv *priv; + u8_t sio_num; + + LWIP_DEBUGF(SLIP_DEBUG, ("slipif_init: netif->num=%"U16_F"\n", (u16_t)netif->num)); + + /* Allocate private data */ + priv = (struct slipif_priv *)mem_malloc(sizeof(struct slipif_priv)); + if (!priv) { + return ERR_MEM; + } + + netif->name[0] = 's'; + netif->name[1] = 'l'; + netif->output = slipif_output_v4; +#if LWIP_IPV6 + netif->output_ip6 = slipif_output_v6; +#endif /* LWIP_IPV6 */ + netif->mtu = SLIP_MAX_SIZE; + netif->flags |= NETIF_FLAG_POINTTOPOINT; + + /* netif->state or netif->num contain the port number */ + if (netif->state != NULL) { + sio_num = *(u8_t*)netif->state; + } else { + sio_num = netif->num; + } + /* Try to open the serial port. */ + priv->sd = sio_open(sio_num); + if (!priv->sd) { + /* Opening the serial port failed. */ + mem_free(priv); + return ERR_IF; + } + + /* Initialize private data */ + priv->p = NULL; + priv->q = NULL; + priv->state = SLIP_RECV_NORMAL; + priv->i = 0; + priv->recved = 0; +#if SLIP_RX_FROM_ISR + priv->rxpackets = NULL; +#endif + + netif->state = priv; + + /* initialize the snmp variables and counters inside the struct netif */ + NETIF_INIT_SNMP(netif, snmp_ifType_slip, SLIP_SIO_SPEED(priv->sd)); + +#if SLIP_USE_RX_THREAD + /* Create a thread to poll the serial line. */ + sys_thread_new(SLIPIF_THREAD_NAME, slipif_loop_thread, netif, + SLIPIF_THREAD_STACKSIZE, SLIPIF_THREAD_PRIO); +#endif /* SLIP_USE_RX_THREAD */ + return ERR_OK; +} + +/** + * Polls the serial device and feeds the IP layer with incoming packets. + * + * @param netif The lwip network interface structure for this slipif + */ +void +slipif_poll(struct netif *netif) +{ + u8_t c; + struct slipif_priv *priv; + + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + + priv = (struct slipif_priv *)netif->state; + + while (sio_tryread(priv->sd, &c, 1) > 0) { + slipif_rxbyte_input(netif, c); + } +} + +#if SLIP_RX_FROM_ISR +/** + * Feeds the IP layer with incoming packets that were receive + * + * @param netif The lwip network interface structure for this slipif + */ +void +slipif_process_rxqueue(struct netif *netif) +{ + struct slipif_priv *priv; + SYS_ARCH_DECL_PROTECT(old_level); + + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + + priv = (struct slipif_priv *)netif->state; + + SYS_ARCH_PROTECT(old_level); + while (priv->rxpackets != NULL) { + struct pbuf *p = priv->rxpackets; +#if SLIP_RX_QUEUE + /* dequeue packet */ + struct pbuf *q = p; + while ((q->len != q->tot_len) && (q->next != NULL)) { + q = q->next; + } + priv->rxpackets = q->next; + q->next = NULL; +#else /* SLIP_RX_QUEUE */ + priv->rxpackets = NULL; +#endif /* SLIP_RX_QUEUE */ + SYS_ARCH_UNPROTECT(old_level); + if (netif->input(p, netif) != ERR_OK) { + pbuf_free(p); + } + SYS_ARCH_PROTECT(old_level); + } +} + +/** Like slipif_rxbyte, but queues completed packets. + * + * @param netif The lwip network interface structure for this slipif + * @param data Received serial byte + */ +static void +slipif_rxbyte_enqueue(struct netif *netif, u8_t data) +{ + struct pbuf *p; + struct slipif_priv *priv = (struct slipif_priv *)netif->state; + SYS_ARCH_DECL_PROTECT(old_level); + + p = slipif_rxbyte(netif, data); + if (p != NULL) { + SYS_ARCH_PROTECT(old_level); + if (priv->rxpackets != NULL) { +#if SLIP_RX_QUEUE + /* queue multiple pbufs */ + struct pbuf *q = p; + while(q->next != NULL) { + q = q->next; + } + q->next = p; + } else { +#else /* SLIP_RX_QUEUE */ + pbuf_free(priv->rxpackets); + } + { +#endif /* SLIP_RX_QUEUE */ + priv->rxpackets = p; + } + SYS_ARCH_UNPROTECT(old_level); + } +} + +/** + * Process a received byte, completed packets are put on a queue that is + * fed into IP through slipif_process_rxqueue(). + * + * This function can be called from ISR if SYS_LIGHTWEIGHT_PROT is enabled. + * + * @param netif The lwip network interface structure for this slipif + * @param data received character + */ +void +slipif_received_byte(struct netif *netif, u8_t data) +{ + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + slipif_rxbyte_enqueue(netif, data); +} + +/** + * Process multiple received byte, completed packets are put on a queue that is + * fed into IP through slipif_process_rxqueue(). + * + * This function can be called from ISR if SYS_LIGHTWEIGHT_PROT is enabled. + * + * @param netif The lwip network interface structure for this slipif + * @param data received character + * @param len Number of received characters + */ +void +slipif_received_bytes(struct netif *netif, u8_t *data, u8_t len) +{ + u8_t i; + u8_t *rxdata = data; + LWIP_ASSERT("netif != NULL", (netif != NULL)); + LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); + + for (i = 0; i < len; i++, rxdata++) { + slipif_rxbyte_enqueue(netif, *rxdata); + } +} +#endif /* SLIP_RX_FROM_ISR */ + +#endif /* LWIP_HAVE_SLIPIF */ diff --git a/component/common/network/mdns/mDNS.h b/component/common/network/mdns/mDNS.h new file mode 100644 index 0000000..c7ecedd --- /dev/null +++ b/component/common/network/mdns/mDNS.h @@ -0,0 +1,26 @@ +#ifndef _MDNS_H +#define _MDNS_H + +#include + +/* Text Record */ +typedef struct _TXTRecordRef_t { + char PrivateData[16]; +} TXTRecordRef; + +extern void TXTRecordCreate(TXTRecordRef *txtRecord, uint16_t bufferLen, void *buffer); +extern int TXTRecordSetValue(TXTRecordRef *txtRecord, const char *key, uint8_t valueSize, const void *value); +extern void TXTRecordDeallocate(TXTRecordRef *txtRecord); + +/* mDNS */ +typedef void *DNSServiceRef; + +extern int mDNSResponderInit(void); +extern void mDNSResponderDeinit(void); +extern DNSServiceRef mDNSRegisterService(char *name, char *service_type, char *domain, unsigned short port, TXTRecordRef *txtRecord); +extern void mDNSDeregisterService(DNSServiceRef serviceRef); +extern void mDNSUpdateService(DNSServiceRef serviceRef, TXTRecordRef *txtRecord); +extern void mDNSRegisterAllInterfaces(void); +extern void mDNSDeregisterAllInterfaces(void); + +#endif /* _MDNS_H */ diff --git a/component/common/network/mdns/mDNSPlatform.c b/component/common/network/mdns/mDNSPlatform.c new file mode 100644 index 0000000..29d61d1 --- /dev/null +++ b/component/common/network/mdns/mDNSPlatform.c @@ -0,0 +1,37 @@ +#include +#include +extern struct netif xnetif[]; + +/*----------------------------------------------------------------------- + * Mandatory functions + *-----------------------------------------------------------------------*/ + +// Mandatory function for custom initialization +// called when mDNS initialization +void mDNSPlatformCustomInit(void) +{ + xnetif[0].flags |= NETIF_FLAG_IGMP; +} + +uint16_t mDNSPlatformHtons(uint16_t hostshort) +{ + return htons(hostshort); +} + +uint32_t mDNSPlatformInetAddr(char *cp) +{ + return inet_addr(cp); +} + +// Mandatory function to get hostname +// called when mDNS initialization +char *mDNSPlatformHostname(void) +{ +#if LWIP_NETIF_HOSTNAME + return xnetif[0].hostname; +#else + return "ameba"; +#endif +} + +/*-----------------------------------------------------------------------*/ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/aes.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/aes.h new file mode 100644 index 0000000..d08073c --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/aes.h @@ -0,0 +1,264 @@ +/** + * \file aes.h + * + * \brief AES block cipher + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_AES_H +#define POLARSSL_AES_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +// Rename to fix function conflict to ROM codes +#define aes_init polarssl_aes_init + +#include + +#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32) +#include +typedef UINT32 uint32_t; +#else +#include +#endif + +/* padlock.c and aesni.c rely on these values! */ +#define AES_ENCRYPT 1 +#define AES_DECRYPT 0 + +#define POLARSSL_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */ +#define POLARSSL_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */ + +#if !defined(POLARSSL_AES_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief AES context structure + * + * \note buf is able to hold 32 extra bytes, which can be used: + * - for alignment purposes if VIA padlock is used, and/or + * - to simplify key expansion in the 256-bit case by + * generating an extra round key + */ +typedef struct +{ + int nr; /*!< number of rounds */ + uint32_t *rk; /*!< AES round keys */ + uint32_t buf[68]; /*!< unaligned data */ +#ifdef RTL_HW_CRYPTO + unsigned char enc_key[32]; + unsigned char dec_key[32]; +#endif +} +aes_context; + +/** + * \brief Initialize AES context + * + * \param ctx AES context to be initialized + */ +void aes_init( aes_context *ctx ); + +/** + * \brief Clear AES context + * + * \param ctx AES context to be cleared + */ +void aes_free( aes_context *ctx ); + +/** + * \brief AES key schedule (encryption) + * + * \param ctx AES context to be initialized + * \param key encryption key + * \param keysize must be 128, 192 or 256 + * + * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH + */ +int aes_setkey_enc( aes_context *ctx, const unsigned char *key, + unsigned int keysize ); + +/** + * \brief AES key schedule (decryption) + * + * \param ctx AES context to be initialized + * \param key decryption key + * \param keysize must be 128, 192 or 256 + * + * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH + */ +int aes_setkey_dec( aes_context *ctx, const unsigned char *key, + unsigned int keysize ); + +/** + * \brief AES-ECB block encryption/decryption + * + * \param ctx AES context + * \param mode AES_ENCRYPT or AES_DECRYPT + * \param input 16-byte input block + * \param output 16-byte output block + * + * \return 0 if successful + */ +int aes_crypt_ecb( aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +#if defined(POLARSSL_CIPHER_MODE_CBC) +/** + * \brief AES-CBC buffer encryption/decryption + * Length should be a multiple of the block + * size (16 bytes) + * + * \param ctx AES context + * \param mode AES_ENCRYPT or AES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_INPUT_LENGTH + */ +int aes_crypt_cbc( aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_CIPHER_MODE_CFB) +/** + * \brief AES-CFB128 buffer encryption/decryption. + * + * Note: Due to the nature of CFB you should use the same key schedule for + * both encryption and decryption. So a context initialized with + * aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT. + * + * \param ctx AES context + * \param mode AES_ENCRYPT or AES_DECRYPT + * \param length length of the input data + * \param iv_off offset in IV (updated after use) + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful + */ +int aes_crypt_cfb128( aes_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); + +/** + * \brief AES-CFB8 buffer encryption/decryption. + * + * Note: Due to the nature of CFB you should use the same key schedule for + * both encryption and decryption. So a context initialized with + * aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT. + * + * \param ctx AES context + * \param mode AES_ENCRYPT or AES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful + */ +int aes_crypt_cfb8( aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /*POLARSSL_CIPHER_MODE_CFB */ + +#if defined(POLARSSL_CIPHER_MODE_CTR) +/** + * \brief AES-CTR buffer encryption/decryption + * + * Warning: You have to keep the maximum use of your counter in mind! + * + * Note: Due to the nature of CTR you should use the same key schedule for + * both encryption and decryption. So a context initialized with + * aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT. + * + * \param ctx AES context + * \param length The length of the data + * \param nc_off The offset in the current stream_block (for resuming + * within current cipher stream). The offset pointer to + * should be 0 at the start of a stream. + * \param nonce_counter The 128-bit nonce and counter. + * \param stream_block The saved stream-block for resuming. Is overwritten + * by the function. + * \param input The input data stream + * \param output The output data stream + * + * \return 0 if successful + */ +int aes_crypt_ctr( aes_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ); +#endif /* POLARSSL_CIPHER_MODE_CTR */ + +#ifdef __cplusplus +} +#endif + +#else /* POLARSSL_AES_ALT */ +#include "aes_alt.h" +#endif /* POLARSSL_AES_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int aes_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* aes.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/aesni.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/aesni.h new file mode 100644 index 0000000..92b23cd --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/aesni.h @@ -0,0 +1,107 @@ +/** + * \file aesni.h + * + * \brief AES-NI for hardware AES acceleration on some Intel processors + * + * Copyright (C) 2013, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_AESNI_H +#define POLARSSL_AESNI_H + +#include "aes.h" + +#define POLARSSL_AESNI_AES 0x02000000u +#define POLARSSL_AESNI_CLMUL 0x00000002u + +#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && \ + ( defined(__amd64__) || defined(__x86_64__) ) && \ + ! defined(POLARSSL_HAVE_X86_64) +#define POLARSSL_HAVE_X86_64 +#endif + +#if defined(POLARSSL_HAVE_X86_64) + +/** + * \brief AES-NI features detection routine + * + * \param what The feature to detect + * (POLARSSL_AESNI_AES or POLARSSL_AESNI_CLMUL) + * + * \return 1 if CPU has support for the feature, 0 otherwise + */ +int aesni_supports( unsigned int what ); + +/** + * \brief AES-NI AES-ECB block en(de)cryption + * + * \param ctx AES context + * \param mode AES_ENCRYPT or AES_DECRYPT + * \param input 16-byte input block + * \param output 16-byte output block + * + * \return 0 on success (cannot fail) + */ +int aesni_crypt_ecb( aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +/** + * \brief GCM multiplication: c = a * b in GF(2^128) + * + * \param c Result + * \param a First operand + * \param b Second operand + * + * \note Both operands and result are bit strings interpreted as + * elements of GF(2^128) as per the GCM spec. + */ +void aesni_gcm_mult( unsigned char c[16], + const unsigned char a[16], + const unsigned char b[16] ); + +/** + * \brief Compute decryption round keys from encryption round keys + * + * \param invkey Round keys for the equivalent inverse cipher + * \param fwdkey Original round keys (for encryption) + * \param nr Number of rounds (that is, number of round keys minus one) + */ +void aesni_inverse_key( unsigned char *invkey, + const unsigned char *fwdkey, int nr ); + +/** + * \brief Perform key expansion (for encryption) + * + * \param rk Destination buffer where the round keys are written + * \param key Encryption key + * \param bits Key size in bits (must be 128, 192 or 256) + * + * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH + */ +int aesni_setkey_enc( unsigned char *rk, + const unsigned char *key, + size_t bits ); + +#endif /* POLARSSL_HAVE_X86_64 */ + +#endif /* POLARSSL_AESNI_H */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/arc4.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/arc4.h new file mode 100644 index 0000000..555f54f --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/arc4.h @@ -0,0 +1,117 @@ +/** + * \file arc4.h + * + * \brief The ARCFOUR stream cipher + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_ARC4_H +#define POLARSSL_ARC4_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include + +#if !defined(POLARSSL_ARC4_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief ARC4 context structure + */ +typedef struct +{ + int x; /*!< permutation index */ + int y; /*!< permutation index */ + unsigned char m[256]; /*!< permutation table */ +} +arc4_context; + +/** + * \brief Initialize ARC4 context + * + * \param ctx ARC4 context to be initialized + */ +void arc4_init( arc4_context *ctx ); + +/** + * \brief Clear ARC4 context + * + * \param ctx ARC4 context to be cleared + */ +void arc4_free( arc4_context *ctx ); + +/** + * \brief ARC4 key schedule + * + * \param ctx ARC4 context to be setup + * \param key the secret key + * \param keylen length of the key, in bytes + */ +void arc4_setup( arc4_context *ctx, const unsigned char *key, + unsigned int keylen ); + +/** + * \brief ARC4 cipher function + * + * \param ctx ARC4 context + * \param length length of the input data + * \param input buffer holding the input data + * \param output buffer for the output data + * + * \return 0 if successful + */ +int arc4_crypt( arc4_context *ctx, size_t length, const unsigned char *input, + unsigned char *output ); + +#ifdef __cplusplus +} +#endif + +#else /* POLARSSL_ARC4_ALT */ +#include "arc4_alt.h" +#endif /* POLARSSL_ARC4_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int arc4_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* arc4.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/asn1.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/asn1.h new file mode 100644 index 0000000..eacdd08 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/asn1.h @@ -0,0 +1,347 @@ +/** + * \file asn1.h + * + * \brief Generic ASN.1 parsing + * + * Copyright (C) 2006-2013, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_ASN1_H +#define POLARSSL_ASN1_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_BIGNUM_C) +#include "bignum.h" +#endif + +#include + +/** + * \addtogroup asn1_module + * \{ + */ + +/** + * \name ASN1 Error codes + * These error codes are OR'ed to X509 error codes for + * higher error granularity. + * ASN1 is a standard to specify data structures. + * \{ + */ +#define POLARSSL_ERR_ASN1_OUT_OF_DATA -0x0060 /**< Out of data when parsing an ASN1 data structure. */ +#define POLARSSL_ERR_ASN1_UNEXPECTED_TAG -0x0062 /**< ASN1 tag was of an unexpected value. */ +#define POLARSSL_ERR_ASN1_INVALID_LENGTH -0x0064 /**< Error when trying to determine the length or invalid length. */ +#define POLARSSL_ERR_ASN1_LENGTH_MISMATCH -0x0066 /**< Actual length differs from expected length. */ +#define POLARSSL_ERR_ASN1_INVALID_DATA -0x0068 /**< Data is invalid. (not used) */ +#define POLARSSL_ERR_ASN1_MALLOC_FAILED -0x006A /**< Memory allocation failed */ +#define POLARSSL_ERR_ASN1_BUF_TOO_SMALL -0x006C /**< Buffer too small when writing ASN.1 data structure. */ + +/* \} name */ + +/** + * \name DER constants + * These constants comply with DER encoded the ANS1 type tags. + * DER encoding uses hexadecimal representation. + * An example DER sequence is:\n + * - 0x02 -- tag indicating INTEGER + * - 0x01 -- length in octets + * - 0x05 -- value + * Such sequences are typically read into \c ::x509_buf. + * \{ + */ +#define ASN1_BOOLEAN 0x01 +#define ASN1_INTEGER 0x02 +#define ASN1_BIT_STRING 0x03 +#define ASN1_OCTET_STRING 0x04 +#define ASN1_NULL 0x05 +#define ASN1_OID 0x06 +#define ASN1_UTF8_STRING 0x0C +#define ASN1_SEQUENCE 0x10 +#define ASN1_SET 0x11 +#define ASN1_PRINTABLE_STRING 0x13 +#define ASN1_T61_STRING 0x14 +#define ASN1_IA5_STRING 0x16 +#define ASN1_UTC_TIME 0x17 +#define ASN1_GENERALIZED_TIME 0x18 +#define ASN1_UNIVERSAL_STRING 0x1C +#define ASN1_BMP_STRING 0x1E +#define ASN1_PRIMITIVE 0x00 +#define ASN1_CONSTRUCTED 0x20 +#define ASN1_CONTEXT_SPECIFIC 0x80 +/* \} name */ +/* \} addtogroup asn1_module */ + +/** Returns the size of the binary string, without the trailing \\0 */ +#define OID_SIZE(x) (sizeof(x) - 1) + +/** + * Compares an asn1_buf structure to a reference OID. + * + * Only works for 'defined' oid_str values (OID_HMAC_SHA1), you cannot use a + * 'unsigned char *oid' here! + * + * Warning: returns true when the OIDs are equal (unlike memcmp)! + */ +#define OID_CMP(oid_str, oid_buf) \ + ( ( OID_SIZE(oid_str) == (oid_buf)->len ) && \ + memcmp( (oid_str), (oid_buf)->p, (oid_buf)->len) == 0 ) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name Functions to parse ASN.1 data structures + * \{ + */ + +/** + * Type-length-value structure that allows for ASN1 using DER. + */ +typedef struct _asn1_buf +{ + int tag; /**< ASN1 type, e.g. ASN1_UTF8_STRING. */ + size_t len; /**< ASN1 length, e.g. in octets. */ + unsigned char *p; /**< ASN1 data, e.g. in ASCII. */ +} +asn1_buf; + +/** + * Container for ASN1 bit strings. + */ +typedef struct _asn1_bitstring +{ + size_t len; /**< ASN1 length, e.g. in octets. */ + unsigned char unused_bits; /**< Number of unused bits at the end of the string */ + unsigned char *p; /**< Raw ASN1 data for the bit string */ +} +asn1_bitstring; + +/** + * Container for a sequence of ASN.1 items + */ +typedef struct _asn1_sequence +{ + asn1_buf buf; /**< Buffer containing the given ASN.1 item. */ + struct _asn1_sequence *next; /**< The next entry in the sequence. */ +} +asn1_sequence; + +/** + * Container for a sequence or list of 'named' ASN.1 data items + */ +typedef struct _asn1_named_data +{ + asn1_buf oid; /**< The object identifier. */ + asn1_buf val; /**< The named value. */ + struct _asn1_named_data *next; /**< The next entry in the sequence. */ +} +asn1_named_data; + +/** + * \brief Get the length of an ASN.1 element. + * Updates the pointer to immediately behind the length. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param len The variable that will receive the value + * + * \return 0 if successful, POLARSSL_ERR_ASN1_OUT_OF_DATA on reaching + * end of data, POLARSSL_ERR_ASN1_INVALID_LENGTH if length is + * unparseable. + */ +int asn1_get_len( unsigned char **p, + const unsigned char *end, + size_t *len ); + +/** + * \brief Get the tag and length of the tag. Check for the requested tag. + * Updates the pointer to immediately behind the tag and length. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param len The variable that will receive the length + * \param tag The expected tag + * + * \return 0 if successful, POLARSSL_ERR_ASN1_UNEXPECTED_TAG if tag did + * not match requested tag, or another specific ASN.1 error code. + */ +int asn1_get_tag( unsigned char **p, + const unsigned char *end, + size_t *len, int tag ); + +/** + * \brief Retrieve a boolean ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param val The variable that will receive the value + * + * \return 0 if successful or a specific ASN.1 error code. + */ +int asn1_get_bool( unsigned char **p, + const unsigned char *end, + int *val ); + +/** + * \brief Retrieve an integer ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param val The variable that will receive the value + * + * \return 0 if successful or a specific ASN.1 error code. + */ +int asn1_get_int( unsigned char **p, + const unsigned char *end, + int *val ); + +/** + * \brief Retrieve a bitstring ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param bs The variable that will receive the value + * + * \return 0 if successful or a specific ASN.1 error code. + */ +int asn1_get_bitstring( unsigned char **p, const unsigned char *end, + asn1_bitstring *bs); + +/** + * \brief Retrieve a bitstring ASN.1 tag without unused bits and its + * value. + * Updates the pointer to the beginning of the bit/octet string. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param len Length of the actual bit/octect string in bytes + * + * \return 0 if successful or a specific ASN.1 error code. + */ +int asn1_get_bitstring_null( unsigned char **p, const unsigned char *end, + size_t *len ); + +/** + * \brief Parses and splits an ASN.1 "SEQUENCE OF " + * Updated the pointer to immediately behind the full sequence tag. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param cur First variable in the chain to fill + * \param tag Type of sequence + * + * \return 0 if successful or a specific ASN.1 error code. + */ +int asn1_get_sequence_of( unsigned char **p, + const unsigned char *end, + asn1_sequence *cur, + int tag); + +#if defined(POLARSSL_BIGNUM_C) +/** + * \brief Retrieve a MPI value from an integer ASN.1 tag. + * Updates the pointer to immediately behind the full tag. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param X The MPI that will receive the value + * + * \return 0 if successful or a specific ASN.1 or MPI error code. + */ +int asn1_get_mpi( unsigned char **p, + const unsigned char *end, + mpi *X ); +#endif /* POLARSSL_BIGNUM_C */ + +/** + * \brief Retrieve an AlgorithmIdentifier ASN.1 sequence. + * Updates the pointer to immediately behind the full + * AlgorithmIdentifier. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param alg The buffer to receive the OID + * \param params The buffer to receive the params (if any) + * + * \return 0 if successful or a specific ASN.1 or MPI error code. + */ +int asn1_get_alg( unsigned char **p, + const unsigned char *end, + asn1_buf *alg, asn1_buf *params ); + +/** + * \brief Retrieve an AlgorithmIdentifier ASN.1 sequence with NULL or no + * params. + * Updates the pointer to immediately behind the full + * AlgorithmIdentifier. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param alg The buffer to receive the OID + * + * \return 0 if successful or a specific ASN.1 or MPI error code. + */ +int asn1_get_alg_null( unsigned char **p, + const unsigned char *end, + asn1_buf *alg ); + +/** + * \brief Find a specific named_data entry in a sequence or list based on + * the OID. + * + * \param list The list to seek through + * \param oid The OID to look for + * \param len Size of the OID + * + * \return NULL if not found, or a pointer to the existing entry. + */ +asn1_named_data *asn1_find_named_data( asn1_named_data *list, + const char *oid, size_t len ); + +/** + * \brief Free a asn1_named_data entry + * + * \param entry The named data entry to free + */ +void asn1_free_named_data( asn1_named_data *entry ); + +/** + * \brief Free all entries in a asn1_named_data list + * Head will be set to NULL + * + * \param head Pointer to the head of the list of named data entries to free + */ +void asn1_free_named_data_list( asn1_named_data **head ); + +#ifdef __cplusplus +} +#endif + +#endif /* asn1.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/asn1write.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/asn1write.h new file mode 100644 index 0000000..7a7fbf7 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/asn1write.h @@ -0,0 +1,243 @@ +/** + * \file asn1write.h + * + * \brief ASN.1 buffer writing functionality + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_ASN1_WRITE_H +#define POLARSSL_ASN1_WRITE_H + +#include "asn1.h" + +#define ASN1_CHK_ADD(g, f) do { if( ( ret = f ) < 0 ) return( ret ); else \ + g += ret; } while( 0 ) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Write a length field in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param len the length to write + * + * \return the length written or a negative error code + */ +int asn1_write_len( unsigned char **p, unsigned char *start, size_t len ); + +/** + * \brief Write a ASN.1 tag in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param tag the tag to write + * + * \return the length written or a negative error code + */ +int asn1_write_tag( unsigned char **p, unsigned char *start, + unsigned char tag ); + +/** + * \brief Write raw buffer data + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param buf data buffer to write + * \param size length of the data buffer + * + * \return the length written or a negative error code + */ +int asn1_write_raw_buffer( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ); + +#if defined(POLARSSL_BIGNUM_C) +/** + * \brief Write a big number (ASN1_INTEGER) in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param X the MPI to write + * + * \return the length written or a negative error code + */ +int asn1_write_mpi( unsigned char **p, unsigned char *start, mpi *X ); +#endif /* POLARSSL_BIGNUM_C */ + +/** + * \brief Write a NULL tag (ASN1_NULL) with zero data in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * + * \return the length written or a negative error code + */ +int asn1_write_null( unsigned char **p, unsigned char *start ); + +/** + * \brief Write an OID tag (ASN1_OID) and data in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param oid the OID to write + * \param oid_len length of the OID + * + * \return the length written or a negative error code + */ +int asn1_write_oid( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len ); + +/** + * \brief Write an AlgorithmIdentifier sequence in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param oid the OID of the algorithm + * \param oid_len length of the OID + * \param par_len length of parameters, which must be already written. + * If 0, NULL parameters are added + * + * \return the length written or a negative error code + */ +int asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len, + size_t par_len ); + +/** + * \brief Write a boolean tag (ASN1_BOOLEAN) and value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param boolean 0 or 1 + * + * \return the length written or a negative error code + */ +int asn1_write_bool( unsigned char **p, unsigned char *start, int boolean ); + +/** + * \brief Write an int tag (ASN1_INTEGER) and value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param val the integer value + * + * \return the length written or a negative error code + */ +int asn1_write_int( unsigned char **p, unsigned char *start, int val ); + +/** + * \brief Write a printable string tag (ASN1_PRINTABLE_STRING) and + * value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param text the text to write + * \param text_len length of the text + * + * \return the length written or a negative error code + */ +int asn1_write_printable_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ); + +/** + * \brief Write an IA5 string tag (ASN1_IA5_STRING) and + * value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param text the text to write + * \param text_len length of the text + * + * \return the length written or a negative error code + */ +int asn1_write_ia5_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ); + +/** + * \brief Write a bitstring tag (ASN1_BIT_STRING) and + * value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param buf the bitstring + * \param bits the total number of bits in the bitstring + * + * \return the length written or a negative error code + */ +int asn1_write_bitstring( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t bits ); + +/** + * \brief Write an octet string tag (ASN1_OCTET_STRING) and + * value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param buf data buffer to write + * \param size length of the data buffer + * + * \return the length written or a negative error code + */ +int asn1_write_octet_string( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ); + +/** + * \brief Create or find a specific named_data entry for writing in a + * sequence or list based on the OID. If not already in there, + * a new entry is added to the head of the list. + * Warning: Destructive behaviour for the val data! + * + * \param list Pointer to the location of the head of the list to seek + * through (will be updated in case of a new entry) + * \param oid The OID to look for + * \param oid_len Size of the OID + * \param val Data to store (can be NULL if you want to fill it by hand) + * \param val_len Minimum length of the data buffer needed + * + * \return NULL if if there was a memory allocation error, or a pointer + * to the new / existing entry. + */ +asn1_named_data *asn1_store_named_data( asn1_named_data **list, + const char *oid, size_t oid_len, + const unsigned char *val, + size_t val_len ); + +#ifdef __cplusplus +} +#endif + +#endif /* POLARSSL_ASN1_WRITE_H */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/base64.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/base64.h new file mode 100644 index 0000000..d041493 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/base64.h @@ -0,0 +1,87 @@ +/** + * \file base64.h + * + * \brief RFC 1521 base64 encoding/decoding + * + * Copyright (C) 2006-2013, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_BASE64_H +#define POLARSSL_BASE64_H + +#include + +#define POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL -0x002A /**< Output buffer too small. */ +#define POLARSSL_ERR_BASE64_INVALID_CHARACTER -0x002C /**< Invalid character in input. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Encode a buffer into base64 format + * + * \param dst destination buffer + * \param dlen size of the buffer + * \param src source buffer + * \param slen amount of data to be encoded + * + * \return 0 if successful, or POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL. + * *dlen is always updated to reflect the amount + * of data that has (or would have) been written. + * + * \note Call this function with *dlen = 0 to obtain the + * required buffer size in *dlen + */ +int base64_encode( unsigned char *dst, size_t *dlen, + const unsigned char *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 buffer + * \param src source buffer + * \param slen amount of data to be decoded + * + * \return 0 if successful, POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL, or + * POLARSSL_ERR_BASE64_INVALID_CHARACTER if the input data is + * not correct. *dlen 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 *dlen + */ +int base64_decode( unsigned char *dst, size_t *dlen, + const unsigned char *src, size_t slen ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int base64_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* base64.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/bignum.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/bignum.h new file mode 100644 index 0000000..cd7592c --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/bignum.h @@ -0,0 +1,752 @@ +/** + * \file bignum.h + * + * \brief Multi-precision integer library + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_BIGNUM_H +#define POLARSSL_BIGNUM_H + +#include +#include + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32) +#include +#if (_MSC_VER <= 1200) +typedef signed short int16_t; +typedef unsigned short uint16_t; +#else +typedef INT16 int16_t; +typedef UINT16 uint16_t; +#endif +typedef INT32 int32_t; +typedef INT64 int64_t; +typedef UINT32 uint32_t; +typedef UINT64 uint64_t; +#else +#include +#endif /* _MSC_VER && !EFIX64 && !EFI32 */ + +#define POLARSSL_ERR_MPI_FILE_IO_ERROR -0x0002 /**< An error occurred while reading from or writing to a file. */ +#define POLARSSL_ERR_MPI_BAD_INPUT_DATA -0x0004 /**< Bad input parameters to function. */ +#define POLARSSL_ERR_MPI_INVALID_CHARACTER -0x0006 /**< There is an invalid character in the digit string. */ +#define POLARSSL_ERR_MPI_BUFFER_TOO_SMALL -0x0008 /**< The buffer is too small to write to. */ +#define POLARSSL_ERR_MPI_NEGATIVE_VALUE -0x000A /**< The input arguments are negative or result in illegal output. */ +#define POLARSSL_ERR_MPI_DIVISION_BY_ZERO -0x000C /**< The input argument for division is zero, which is not allowed. */ +#define POLARSSL_ERR_MPI_NOT_ACCEPTABLE -0x000E /**< The input arguments are not acceptable. */ +#define POLARSSL_ERR_MPI_MALLOC_FAILED -0x0010 /**< Memory allocation failed. */ + +#define MPI_CHK(f) do { if( ( ret = f ) != 0 ) goto cleanup; } while( 0 ) + +/* + * Maximum size MPIs are allowed to grow to in number of limbs. + */ +#define POLARSSL_MPI_MAX_LIMBS 10000 + +#if !defined(POLARSSL_MPI_WINDOW_SIZE) +/* + * Maximum window size used for modular exponentiation. Default: 6 + * Minimum value: 1. Maximum value: 6. + * + * Result is an array of ( 2 << POLARSSL_MPI_WINDOW_SIZE ) MPIs used + * for the sliding window calculation. (So 64 by default) + * + * Reduction in size, reduces speed. + */ +#define POLARSSL_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */ +#endif /* !POLARSSL_MPI_WINDOW_SIZE */ + +#if !defined(POLARSSL_MPI_MAX_SIZE) +/* + * Maximum size of MPIs allowed in bits and bytes for user-MPIs. + * ( Default: 512 bytes => 4096 bits, Maximum tested: 2048 bytes => 16384 bits ) + * + * Note: Calculations can results temporarily in larger MPIs. So the number + * of limbs required (POLARSSL_MPI_MAX_LIMBS) is higher. + */ +#define POLARSSL_MPI_MAX_SIZE 512 /**< Maximum number of bytes for usable MPIs. */ +#endif /* !POLARSSL_MPI_MAX_SIZE */ + +#define POLARSSL_MPI_MAX_BITS ( 8 * POLARSSL_MPI_MAX_SIZE ) /**< Maximum number of bits for usable MPIs. */ + +/* + * When reading from files with mpi_read_file() and writing to files with + * mpi_write_file() the buffer should have space + * for a (short) label, the MPI (in the provided radix), the newline + * characters and the '\0'. + * + * By default we assume at least a 10 char label, a minimum radix of 10 + * (decimal) and a maximum of 4096 bit numbers (1234 decimal chars). + * Autosized at compile time for at least a 10 char label, a minimum radix + * of 10 (decimal) for a number of POLARSSL_MPI_MAX_BITS size. + * + * This used to be statically sized to 1250 for a maximum of 4096 bit + * numbers (1234 decimal chars). + * + * Calculate using the formula: + * POLARSSL_MPI_RW_BUFFER_SIZE = ceil(POLARSSL_MPI_MAX_BITS / ln(10) * ln(2)) + + * LabelSize + 6 + */ +#define POLARSSL_MPI_MAX_BITS_SCALE100 ( 100 * POLARSSL_MPI_MAX_BITS ) +#define LN_2_DIV_LN_10_SCALE100 332 +#define POLARSSL_MPI_RW_BUFFER_SIZE ( ((POLARSSL_MPI_MAX_BITS_SCALE100 + LN_2_DIV_LN_10_SCALE100 - 1) / LN_2_DIV_LN_10_SCALE100) + 10 + 6 ) + +/* + * Define the base integer type, architecture-wise + */ +#if defined(POLARSSL_HAVE_INT8) +typedef signed char t_sint; +typedef unsigned char t_uint; +typedef uint16_t t_udbl; +#define POLARSSL_HAVE_UDBL +#else +#if defined(POLARSSL_HAVE_INT16) +typedef int16_t t_sint; +typedef uint16_t t_uint; +typedef uint32_t t_udbl; +#define POLARSSL_HAVE_UDBL +#else + /* + * 32-bit integers can be forced on 64-bit arches (eg. for testing purposes) + * by defining POLARSSL_HAVE_INT32 and undefining POLARSSL_HAVE_ASM + */ + #if ( ! defined(POLARSSL_HAVE_INT32) && \ + defined(_MSC_VER) && defined(_M_AMD64) ) + #define POLARSSL_HAVE_INT64 + typedef int64_t t_sint; + typedef uint64_t t_uint; + #else + #if ( ! defined(POLARSSL_HAVE_INT32) && \ + defined(__GNUC__) && ( \ + defined(__amd64__) || defined(__x86_64__) || \ + defined(__ppc64__) || defined(__powerpc64__) || \ + defined(__ia64__) || defined(__alpha__) || \ + (defined(__sparc__) && defined(__arch64__)) || \ + defined(__s390x__) ) ) + #define POLARSSL_HAVE_INT64 + typedef int64_t t_sint; + typedef uint64_t t_uint; + typedef unsigned int t_udbl __attribute__((mode(TI))); + #define POLARSSL_HAVE_UDBL + #else + #define POLARSSL_HAVE_INT32 + typedef int32_t t_sint; + typedef uint32_t t_uint; + #if ( defined(_MSC_VER) && defined(_M_IX86) ) + typedef uint64_t t_udbl; + #define POLARSSL_HAVE_UDBL + #else + #if defined( POLARSSL_HAVE_LONGLONG ) + typedef unsigned long long t_udbl; + #define POLARSSL_HAVE_UDBL + #endif + #endif + #endif /* !POLARSSL_HAVE_INT32 && __GNUC__ && 64-bit platform */ + #endif /* !POLARSSL_HAVE_INT32 && _MSC_VER && _M_AMD64 */ +#endif /* POLARSSL_HAVE_INT16 */ +#endif /* POLARSSL_HAVE_INT8 */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MPI structure + */ +typedef struct +{ + int s; /*!< integer sign */ + size_t n; /*!< total # of limbs */ + t_uint *p; /*!< pointer to limbs */ +} +mpi; + +/** + * \brief Initialize one MPI + * + * \param X One MPI to initialize. + */ +void mpi_init( mpi *X ); + +/** + * \brief Unallocate one MPI + * + * \param X One MPI to unallocate. + */ +void mpi_free( mpi *X ); + +/** + * \brief Enlarge to the specified number of limbs + * + * \param X MPI to grow + * \param nblimbs The target number of limbs + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_grow( mpi *X, size_t nblimbs ); + +/** + * \brief Resize down, keeping at least the specified number of limbs + * + * \param X MPI to shrink + * \param nblimbs The minimum number of limbs to keep + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_shrink( mpi *X, size_t nblimbs ); + +/** + * \brief Copy the contents of Y into X + * + * \param X Destination MPI + * \param Y Source MPI + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_copy( mpi *X, const mpi *Y ); + +/** + * \brief Swap the contents of X and Y + * + * \param X First MPI value + * \param Y Second MPI value + */ +void mpi_swap( mpi *X, mpi *Y ); + +/** + * \brief Safe conditional assignement X = Y if assign is 1 + * + * \param X MPI to conditionally assign to + * \param Y Value to be assigned + * \param assign 1: perform the assignment, 0: keep X's original value + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * + * \note This function is equivalent to + * if( assign ) mpi_copy( X, Y ); + * except that it avoids leaking any information about whether + * the assignment was done or not (the above code may leak + * information through branch prediction and/or memory access + * patterns analysis). + */ +int mpi_safe_cond_assign( mpi *X, const mpi *Y, unsigned char assign ); + +/** + * \brief Safe conditional swap X <-> Y if swap is 1 + * + * \param X First mpi value + * \param Y Second mpi value + * \param assign 1: perform the swap, 0: keep X and Y's original values + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * + * \note This function is equivalent to + * if( assign ) mpi_swap( X, Y ); + * except that it avoids leaking any information about whether + * the assignment was done or not (the above code may leak + * information through branch prediction and/or memory access + * patterns analysis). + */ +int mpi_safe_cond_swap( mpi *X, mpi *Y, unsigned char assign ); + +/** + * \brief Set value from integer + * + * \param X MPI to set + * \param z Value to use + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_lset( mpi *X, t_sint z ); + +/** + * \brief Get a specific bit from X + * + * \param X MPI to use + * \param pos Zero-based index of the bit in X + * + * \return Either a 0 or a 1 + */ +int mpi_get_bit( const mpi *X, size_t pos ); + +/** + * \brief Set a bit of X to a specific value of 0 or 1 + * + * \note Will grow X if necessary to set a bit to 1 in a not yet + * existing limb. Will not grow if bit should be set to 0 + * + * \param X MPI to use + * \param pos Zero-based index of the bit in X + * \param val The value to set the bit to (0 or 1) + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_MPI_BAD_INPUT_DATA if val is not 0 or 1 + */ +int mpi_set_bit( mpi *X, size_t pos, unsigned char val ); + +/** + * \brief Return the number of zero-bits before the least significant + * '1' bit + * + * Note: Thus also the zero-based index of the least significant '1' bit + * + * \param X MPI to use + */ +size_t mpi_lsb( const mpi *X ); + +/** + * \brief Return the number of bits up to and including the most + * significant '1' bit' + * + * Note: Thus also the one-based index of the most significant '1' bit + * + * \param X MPI to use + */ +size_t mpi_msb( const mpi *X ); + +/** + * \brief Return the total size in bytes + * + * \param X MPI to use + */ +size_t mpi_size( const mpi *X ); + +/** + * \brief Import from an ASCII string + * + * \param X Destination MPI + * \param radix Input numeric base + * \param s Null-terminated string buffer + * + * \return 0 if successful, or a POLARSSL_ERR_MPI_XXX error code + */ +int mpi_read_string( mpi *X, int radix, const char *s ); + +/** + * \brief Export into an ASCII string + * + * \param X Source MPI + * \param radix Output numeric base + * \param s String buffer + * \param slen String buffer size + * + * \return 0 if successful, or a POLARSSL_ERR_MPI_XXX error code. + * *slen is always updated to reflect the amount + * of data that has (or would have) been written. + * + * \note Call this function with *slen = 0 to obtain the + * minimum required buffer size in *slen. + */ +int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen ); + +#if defined(POLARSSL_FS_IO) +/** + * \brief Read X from an opened file + * + * \param X Destination MPI + * \param radix Input numeric base + * \param fin Input file handle + * + * \return 0 if successful, POLARSSL_ERR_MPI_BUFFER_TOO_SMALL if + * the file read buffer is too small or a + * POLARSSL_ERR_MPI_XXX error code + */ +int mpi_read_file( mpi *X, int radix, FILE *fin ); + +/** + * \brief Write X into an opened file, or stdout if fout is NULL + * + * \param p Prefix, can be NULL + * \param X Source MPI + * \param radix Output numeric base + * \param fout Output file handle (can be NULL) + * + * \return 0 if successful, or a POLARSSL_ERR_MPI_XXX error code + * + * \note Set fout == NULL to print X on the console. + */ +int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout ); +#endif /* POLARSSL_FS_IO */ + +/** + * \brief Import X from unsigned binary data, big endian + * + * \param X Destination MPI + * \param buf Input buffer + * \param buflen Input buffer size + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen ); + +/** + * \brief Export X into unsigned binary data, big endian. + * Always fills the whole buffer, which will start with zeros + * if the number is smaller. + * + * \param X Source MPI + * \param buf Output buffer + * \param buflen Output buffer size + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_BUFFER_TOO_SMALL if buf isn't large enough + */ +int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen ); + +/** + * \brief Left-shift: X <<= count + * + * \param X MPI to shift + * \param count Amount to shift + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_shift_l( mpi *X, size_t count ); + +/** + * \brief Right-shift: X >>= count + * + * \param X MPI to shift + * \param count Amount to shift + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_shift_r( mpi *X, size_t count ); + +/** + * \brief Compare unsigned values + * + * \param X Left-hand MPI + * \param Y Right-hand MPI + * + * \return 1 if |X| is greater than |Y|, + * -1 if |X| is lesser than |Y| or + * 0 if |X| is equal to |Y| + */ +int mpi_cmp_abs( const mpi *X, const mpi *Y ); + +/** + * \brief Compare signed values + * + * \param X Left-hand MPI + * \param Y Right-hand MPI + * + * \return 1 if X is greater than Y, + * -1 if X is lesser than Y or + * 0 if X is equal to Y + */ +int mpi_cmp_mpi( const mpi *X, const mpi *Y ); + +/** + * \brief Compare signed values + * + * \param X Left-hand MPI + * \param z The integer value to compare to + * + * \return 1 if X is greater than z, + * -1 if X is lesser than z or + * 0 if X is equal to z + */ +int mpi_cmp_int( const mpi *X, t_sint z ); + +/** + * \brief Unsigned addition: X = |A| + |B| + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_add_abs( mpi *X, const mpi *A, const mpi *B ); + +/** + * \brief Unsigned subtraction: X = |A| - |B| + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_NEGATIVE_VALUE if B is greater than A + */ +int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B ); + +/** + * \brief Signed addition: X = A + B + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B ); + +/** + * \brief Signed subtraction: X = A - B + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B ); + +/** + * \brief Signed addition: X = A + b + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param b The integer value to add + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_add_int( mpi *X, const mpi *A, t_sint b ); + +/** + * \brief Signed subtraction: X = A - b + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param b The integer value to subtract + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_sub_int( mpi *X, const mpi *A, t_sint b ); + +/** + * \brief Baseline multiplication: X = A * B + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B ); + +/** + * \brief Baseline multiplication: X = A * b + * Note: despite the functon signature, b is treated as a + * t_uint. Negative values of b are treated as large positive + * values. + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param b The integer value to multiply with + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_mul_int( mpi *X, const mpi *A, t_sint b ); + +/** + * \brief Division by mpi: A = Q * B + R + * + * \param Q Destination MPI for the quotient + * \param R Destination MPI for the rest value + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0 + * + * \note Either Q or R can be NULL. + */ +int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B ); + +/** + * \brief Division by int: A = Q * b + R + * + * \param Q Destination MPI for the quotient + * \param R Destination MPI for the rest value + * \param A Left-hand MPI + * \param b Integer to divide by + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0 + * + * \note Either Q or R can be NULL. + */ +int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b ); + +/** + * \brief Modulo: R = A mod B + * + * \param R Destination MPI for the rest value + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0, + * POLARSSL_ERR_MPI_NEGATIVE_VALUE if B < 0 + */ +int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B ); + +/** + * \brief Modulo: r = A mod b + * + * \param r Destination t_uint + * \param A Left-hand MPI + * \param b Integer to divide by + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0, + * POLARSSL_ERR_MPI_NEGATIVE_VALUE if b < 0 + */ +int mpi_mod_int( t_uint *r, const mpi *A, t_sint b ); + +/** + * \brief Sliding-window exponentiation: X = A^E mod N + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param E Exponent MPI + * \param N Modular MPI + * \param _RR Speed-up MPI used for recalculations + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or even or + * if E is negative + * + * \note _RR is used to avoid re-computing R*R mod N across + * multiple calls, which speeds up things a bit. It can + * be set to NULL if the extra performance is unneeded. + */ +int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR ); + +/** + * \brief Fill an MPI X with size bytes of random + * + * \param X Destination MPI + * \param size Size in bytes + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_fill_random( mpi *X, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Greatest common divisor: G = gcd(A, B) + * + * \param G Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int mpi_gcd( mpi *G, const mpi *A, const mpi *B ); + +/** + * \brief Modular inverse: X = A^-1 mod N + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param N Right-hand MPI + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or nil + POLARSSL_ERR_MPI_NOT_ACCEPTABLE if A has no inverse mod N + */ +int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N ); + +/** + * \brief Miller-Rabin primality test + * + * \param X MPI to check + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful (probably prime), + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_MPI_NOT_ACCEPTABLE if X is not prime + */ +int mpi_is_prime( mpi *X, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Prime number generation + * + * \param X Destination MPI + * \param nbits Required size of X in bits + * ( 3 <= nbits <= POLARSSL_MPI_MAX_BITS ) + * \param dh_flag If 1, then (X-1)/2 will be prime too + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful (probably prime), + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_MPI_BAD_INPUT_DATA if nbits is < 3 + */ +int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mpi_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* bignum.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/blowfish.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/blowfish.h new file mode 100644 index 0000000..c652b46 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/blowfish.h @@ -0,0 +1,197 @@ +/** + * \file blowfish.h + * + * \brief Blowfish block cipher + * + * Copyright (C) 2012-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_BLOWFISH_H +#define POLARSSL_BLOWFISH_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include + +#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32) +#include +typedef UINT32 uint32_t; +#else +#include +#endif + +#define BLOWFISH_ENCRYPT 1 +#define BLOWFISH_DECRYPT 0 +#define BLOWFISH_MAX_KEY 448 +#define BLOWFISH_MIN_KEY 32 +#define BLOWFISH_ROUNDS 16 /**< Rounds to use. When increasing this value, make sure to extend the initialisation vectors */ +#define BLOWFISH_BLOCKSIZE 8 /* Blowfish uses 64 bit blocks */ + +#define POLARSSL_ERR_BLOWFISH_INVALID_KEY_LENGTH -0x0016 /**< Invalid key length. */ +#define POLARSSL_ERR_BLOWFISH_INVALID_INPUT_LENGTH -0x0018 /**< Invalid data input length. */ + +#if !defined(POLARSSL_BLOWFISH_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Blowfish context structure + */ +typedef struct +{ + uint32_t P[BLOWFISH_ROUNDS + 2]; /*!< Blowfish round keys */ + uint32_t S[4][256]; /*!< key dependent S-boxes */ +} +blowfish_context; + +/** + * \brief Initialize Blowfish context + * + * \param ctx Blowfish context to be initialized + */ +void blowfish_init( blowfish_context *ctx ); + +/** + * \brief Clear Blowfish context + * + * \param ctx Blowfish context to be cleared + */ +void blowfish_free( blowfish_context *ctx ); + +/** + * \brief Blowfish key schedule + * + * \param ctx Blowfish context to be initialized + * \param key encryption key + * \param keysize must be between 32 and 448 bits + * + * \return 0 if successful, or POLARSSL_ERR_BLOWFISH_INVALID_KEY_LENGTH + */ +int blowfish_setkey( blowfish_context *ctx, const unsigned char *key, + unsigned int keysize ); + +/** + * \brief Blowfish-ECB block encryption/decryption + * + * \param ctx Blowfish context + * \param mode BLOWFISH_ENCRYPT or BLOWFISH_DECRYPT + * \param input 8-byte input block + * \param output 8-byte output block + * + * \return 0 if successful + */ +int blowfish_crypt_ecb( blowfish_context *ctx, + int mode, + const unsigned char input[BLOWFISH_BLOCKSIZE], + unsigned char output[BLOWFISH_BLOCKSIZE] ); + +#if defined(POLARSSL_CIPHER_MODE_CBC) +/** + * \brief Blowfish-CBC buffer encryption/decryption + * Length should be a multiple of the block + * size (8 bytes) + * + * \param ctx Blowfish context + * \param mode BLOWFISH_ENCRYPT or BLOWFISH_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful, or + * POLARSSL_ERR_BLOWFISH_INVALID_INPUT_LENGTH + */ +int blowfish_crypt_cbc( blowfish_context *ctx, + int mode, + size_t length, + unsigned char iv[BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_CIPHER_MODE_CFB) +/** + * \brief Blowfish CFB buffer encryption/decryption. + * + * \param ctx Blowfish context + * \param mode BLOWFISH_ENCRYPT or BLOWFISH_DECRYPT + * \param length length of the input data + * \param iv_off offset in IV (updated after use) + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful + */ +int blowfish_crypt_cfb64( blowfish_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /*POLARSSL_CIPHER_MODE_CFB */ + +#if defined(POLARSSL_CIPHER_MODE_CTR) +/** + * \brief Blowfish-CTR buffer encryption/decryption + * + * Warning: You have to keep the maximum use of your counter in mind! + * + * \param ctx Blowfish context + * \param length The length of the data + * \param nc_off The offset in the current stream_block (for resuming + * within current cipher stream). The offset pointer to + * should be 0 at the start of a stream. + * \param nonce_counter The 64-bit nonce and counter. + * \param stream_block The saved stream-block for resuming. Is overwritten + * by the function. + * \param input The input data stream + * \param output The output data stream + * + * \return 0 if successful + */ +int blowfish_crypt_ctr( blowfish_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[BLOWFISH_BLOCKSIZE], + unsigned char stream_block[BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /* POLARSSL_CIPHER_MODE_CTR */ + +#ifdef __cplusplus +} +#endif + +#else /* POLARSSL_BLOWFISH_ALT */ +#include "blowfish_alt.h" +#endif /* POLARSSL_BLOWFISH_ALT */ + +#endif /* blowfish.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/bn_mul.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/bn_mul.h new file mode 100644 index 0000000..64b59ff --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/bn_mul.h @@ -0,0 +1,873 @@ +/** + * \file bn_mul.h + * + * \brief Multi-precision integer library + * + * Copyright (C) 2006-2010, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * Multiply source vector [s] with b, add result + * to destination vector [d] and set carry c. + * + * Currently supports: + * + * . IA-32 (386+) . AMD64 / EM64T + * . IA-32 (SSE2) . Motorola 68000 + * . PowerPC, 32-bit . MicroBlaze + * . PowerPC, 64-bit . TriCore + * . SPARC v8 . ARM v3+ + * . Alpha . MIPS32 + * . C, longlong . C, generic + */ +#ifndef POLARSSL_BN_MUL_H +#define POLARSSL_BN_MUL_H + +#include "bignum.h" + +#if defined(POLARSSL_HAVE_ASM) + +#if defined(__GNUC__) +#if defined(__i386__) + +#define MULADDC_INIT \ + asm( \ + "movl %%ebx, %0 \n\t" \ + "movl %5, %%esi \n\t" \ + "movl %6, %%edi \n\t" \ + "movl %7, %%ecx \n\t" \ + "movl %8, %%ebx \n\t" + +#define MULADDC_CORE \ + "lodsl \n\t" \ + "mull %%ebx \n\t" \ + "addl %%ecx, %%eax \n\t" \ + "adcl $0, %%edx \n\t" \ + "addl (%%edi), %%eax \n\t" \ + "adcl $0, %%edx \n\t" \ + "movl %%edx, %%ecx \n\t" \ + "stosl \n\t" + +#if defined(POLARSSL_HAVE_SSE2) + +#define MULADDC_HUIT \ + "movd %%ecx, %%mm1 \n\t" \ + "movd %%ebx, %%mm0 \n\t" \ + "movd (%%edi), %%mm3 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd (%%esi), %%mm2 \n\t" \ + "pmuludq %%mm0, %%mm2 \n\t" \ + "movd 4(%%esi), %%mm4 \n\t" \ + "pmuludq %%mm0, %%mm4 \n\t" \ + "movd 8(%%esi), %%mm6 \n\t" \ + "pmuludq %%mm0, %%mm6 \n\t" \ + "movd 12(%%esi), %%mm7 \n\t" \ + "pmuludq %%mm0, %%mm7 \n\t" \ + "paddq %%mm2, %%mm1 \n\t" \ + "movd 4(%%edi), %%mm3 \n\t" \ + "paddq %%mm4, %%mm3 \n\t" \ + "movd 8(%%edi), %%mm5 \n\t" \ + "paddq %%mm6, %%mm5 \n\t" \ + "movd 12(%%edi), %%mm4 \n\t" \ + "paddq %%mm4, %%mm7 \n\t" \ + "movd %%mm1, (%%edi) \n\t" \ + "movd 16(%%esi), %%mm2 \n\t" \ + "pmuludq %%mm0, %%mm2 \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd 20(%%esi), %%mm4 \n\t" \ + "pmuludq %%mm0, %%mm4 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd 24(%%esi), %%mm6 \n\t" \ + "pmuludq %%mm0, %%mm6 \n\t" \ + "movd %%mm1, 4(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd 28(%%esi), %%mm3 \n\t" \ + "pmuludq %%mm0, %%mm3 \n\t" \ + "paddq %%mm5, %%mm1 \n\t" \ + "movd 16(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm2 \n\t" \ + "movd %%mm1, 8(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm7, %%mm1 \n\t" \ + "movd 20(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm4 \n\t" \ + "movd %%mm1, 12(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm2, %%mm1 \n\t" \ + "movd 24(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm6 \n\t" \ + "movd %%mm1, 16(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm4, %%mm1 \n\t" \ + "movd 28(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm3 \n\t" \ + "movd %%mm1, 20(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm6, %%mm1 \n\t" \ + "movd %%mm1, 24(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd %%mm1, 28(%%edi) \n\t" \ + "addl $32, %%edi \n\t" \ + "addl $32, %%esi \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd %%mm1, %%ecx \n\t" + +#define MULADDC_STOP \ + "emms \n\t" \ + "movl %4, %%ebx \n\t" \ + "movl %%ecx, %1 \n\t" \ + "movl %%edi, %2 \n\t" \ + "movl %%esi, %3 \n\t" \ + : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ + : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ + : "eax", "ecx", "edx", "esi", "edi" \ + ); + +#else + +#define MULADDC_STOP \ + "movl %4, %%ebx \n\t" \ + "movl %%ecx, %1 \n\t" \ + "movl %%edi, %2 \n\t" \ + "movl %%esi, %3 \n\t" \ + : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ + : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ + : "eax", "ecx", "edx", "esi", "edi" \ + ); +#endif /* SSE2 */ +#endif /* i386 */ + +#if defined(__amd64__) || defined (__x86_64__) + +#define MULADDC_INIT \ + asm( \ + "movq %3, %%rsi \n\t" \ + "movq %4, %%rdi \n\t" \ + "movq %5, %%rcx \n\t" \ + "movq %6, %%rbx \n\t" \ + "xorq %%r8, %%r8 \n\t" + +#define MULADDC_CORE \ + "movq (%%rsi), %%rax \n\t" \ + "mulq %%rbx \n\t" \ + "addq $8, %%rsi \n\t" \ + "addq %%rcx, %%rax \n\t" \ + "movq %%r8, %%rcx \n\t" \ + "adcq $0, %%rdx \n\t" \ + "nop \n\t" \ + "addq %%rax, (%%rdi) \n\t" \ + "adcq %%rdx, %%rcx \n\t" \ + "addq $8, %%rdi \n\t" + +#define MULADDC_STOP \ + "movq %%rcx, %0 \n\t" \ + "movq %%rdi, %1 \n\t" \ + "movq %%rsi, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "rax", "rcx", "rdx", "rbx", "rsi", "rdi", "r8" \ + ); + +#endif /* AMD64 */ + +#if defined(__mc68020__) || defined(__mcpu32__) + +#define MULADDC_INIT \ + asm( \ + "movl %3, %%a2 \n\t" \ + "movl %4, %%a3 \n\t" \ + "movl %5, %%d3 \n\t" \ + "movl %6, %%d2 \n\t" \ + "moveq #0, %%d0 \n\t" + +#define MULADDC_CORE \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "moveq #0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "addxl %%d4, %%d3 \n\t" + +#define MULADDC_STOP \ + "movl %%d3, %0 \n\t" \ + "movl %%a3, %1 \n\t" \ + "movl %%a2, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "d0", "d1", "d2", "d3", "d4", "a2", "a3" \ + ); + +#define MULADDC_HUIT \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "addxl %%d0, %%d3 \n\t" + +#endif /* MC68000 */ + +#if defined(__powerpc64__) || defined(__ppc64__) + +#if defined(__MACH__) && defined(__APPLE__) + +#define MULADDC_INIT \ + asm( \ + "ld r3, %3 \n\t" \ + "ld r4, %4 \n\t" \ + "ld r5, %5 \n\t" \ + "ld r6, %6 \n\t" \ + "addi r3, r3, -8 \n\t" \ + "addi r4, r4, -8 \n\t" \ + "addic r5, r5, 0 \n\t" + +#define MULADDC_CORE \ + "ldu r7, 8(r3) \n\t" \ + "mulld r8, r7, r6 \n\t" \ + "mulhdu r9, r7, r6 \n\t" \ + "adde r8, r8, r5 \n\t" \ + "ld r7, 8(r4) \n\t" \ + "addze r5, r9 \n\t" \ + "addc r8, r8, r7 \n\t" \ + "stdu r8, 8(r4) \n\t" + +#define MULADDC_STOP \ + "addze r5, r5 \n\t" \ + "addi r4, r4, 8 \n\t" \ + "addi r3, r3, 8 \n\t" \ + "std r5, %0 \n\t" \ + "std r4, %1 \n\t" \ + "std r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + + +#else /* __MACH__ && __APPLE__ */ + +#define MULADDC_INIT \ + asm( \ + "ld %%r3, %3 \n\t" \ + "ld %%r4, %4 \n\t" \ + "ld %%r5, %5 \n\t" \ + "ld %%r6, %6 \n\t" \ + "addi %%r3, %%r3, -8 \n\t" \ + "addi %%r4, %%r4, -8 \n\t" \ + "addic %%r5, %%r5, 0 \n\t" + +#define MULADDC_CORE \ + "ldu %%r7, 8(%%r3) \n\t" \ + "mulld %%r8, %%r7, %%r6 \n\t" \ + "mulhdu %%r9, %%r7, %%r6 \n\t" \ + "adde %%r8, %%r8, %%r5 \n\t" \ + "ld %%r7, 8(%%r4) \n\t" \ + "addze %%r5, %%r9 \n\t" \ + "addc %%r8, %%r8, %%r7 \n\t" \ + "stdu %%r8, 8(%%r4) \n\t" + +#define MULADDC_STOP \ + "addze %%r5, %%r5 \n\t" \ + "addi %%r4, %%r4, 8 \n\t" \ + "addi %%r3, %%r3, 8 \n\t" \ + "std %%r5, %0 \n\t" \ + "std %%r4, %1 \n\t" \ + "std %%r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#endif /* __MACH__ && __APPLE__ */ + +#elif defined(__powerpc__) || defined(__ppc__) /* end PPC64/begin PPC32 */ + +#if defined(__MACH__) && defined(__APPLE__) + +#define MULADDC_INIT \ + asm( \ + "lwz r3, %3 \n\t" \ + "lwz r4, %4 \n\t" \ + "lwz r5, %5 \n\t" \ + "lwz r6, %6 \n\t" \ + "addi r3, r3, -4 \n\t" \ + "addi r4, r4, -4 \n\t" \ + "addic r5, r5, 0 \n\t" + +#define MULADDC_CORE \ + "lwzu r7, 4(r3) \n\t" \ + "mullw r8, r7, r6 \n\t" \ + "mulhwu r9, r7, r6 \n\t" \ + "adde r8, r8, r5 \n\t" \ + "lwz r7, 4(r4) \n\t" \ + "addze r5, r9 \n\t" \ + "addc r8, r8, r7 \n\t" \ + "stwu r8, 4(r4) \n\t" + +#define MULADDC_STOP \ + "addze r5, r5 \n\t" \ + "addi r4, r4, 4 \n\t" \ + "addi r3, r3, 4 \n\t" \ + "stw r5, %0 \n\t" \ + "stw r4, %1 \n\t" \ + "stw r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#else /* __MACH__ && __APPLE__ */ + +#define MULADDC_INIT \ + asm( \ + "lwz %%r3, %3 \n\t" \ + "lwz %%r4, %4 \n\t" \ + "lwz %%r5, %5 \n\t" \ + "lwz %%r6, %6 \n\t" \ + "addi %%r3, %%r3, -4 \n\t" \ + "addi %%r4, %%r4, -4 \n\t" \ + "addic %%r5, %%r5, 0 \n\t" + +#define MULADDC_CORE \ + "lwzu %%r7, 4(%%r3) \n\t" \ + "mullw %%r8, %%r7, %%r6 \n\t" \ + "mulhwu %%r9, %%r7, %%r6 \n\t" \ + "adde %%r8, %%r8, %%r5 \n\t" \ + "lwz %%r7, 4(%%r4) \n\t" \ + "addze %%r5, %%r9 \n\t" \ + "addc %%r8, %%r8, %%r7 \n\t" \ + "stwu %%r8, 4(%%r4) \n\t" + +#define MULADDC_STOP \ + "addze %%r5, %%r5 \n\t" \ + "addi %%r4, %%r4, 4 \n\t" \ + "addi %%r3, %%r3, 4 \n\t" \ + "stw %%r5, %0 \n\t" \ + "stw %%r4, %1 \n\t" \ + "stw %%r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#endif /* __MACH__ && __APPLE__ */ + +#endif /* PPC32 */ + +/* + * The Sparc64 assembly is reported to be broken. + * Disable it for now, until we're able to fix it. + */ +#if 0 && defined(__sparc__) && defined(__sparc64__) + +#define MULADDC_INIT \ + asm( \ + "ldx %3, %%o0 \n\t" \ + "ldx %4, %%o1 \n\t" \ + "ld %5, %%o2 \n\t" \ + "ld %6, %%o3 \n\t" + +#define MULADDC_CORE \ + "ld [%%o0], %%o4 \n\t" \ + "inc 4, %%o0 \n\t" \ + "ld [%%o1], %%o5 \n\t" \ + "umul %%o3, %%o4, %%o4 \n\t" \ + "addcc %%o4, %%o2, %%o4 \n\t" \ + "rd %%y, %%g1 \n\t" \ + "addx %%g1, 0, %%g1 \n\t" \ + "addcc %%o4, %%o5, %%o4 \n\t" \ + "st %%o4, [%%o1] \n\t" \ + "addx %%g1, 0, %%o2 \n\t" \ + "inc 4, %%o1 \n\t" + + #define MULADDC_STOP \ + "st %%o2, %0 \n\t" \ + "stx %%o1, %1 \n\t" \ + "stx %%o0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "g1", "o0", "o1", "o2", "o3", "o4", \ + "o5" \ + ); +#endif /* SPARCv9 */ + +#if defined(__sparc__) && !defined(__sparc64__) + +#define MULADDC_INIT \ + asm( \ + "ld %3, %%o0 \n\t" \ + "ld %4, %%o1 \n\t" \ + "ld %5, %%o2 \n\t" \ + "ld %6, %%o3 \n\t" + +#define MULADDC_CORE \ + "ld [%%o0], %%o4 \n\t" \ + "inc 4, %%o0 \n\t" \ + "ld [%%o1], %%o5 \n\t" \ + "umul %%o3, %%o4, %%o4 \n\t" \ + "addcc %%o4, %%o2, %%o4 \n\t" \ + "rd %%y, %%g1 \n\t" \ + "addx %%g1, 0, %%g1 \n\t" \ + "addcc %%o4, %%o5, %%o4 \n\t" \ + "st %%o4, [%%o1] \n\t" \ + "addx %%g1, 0, %%o2 \n\t" \ + "inc 4, %%o1 \n\t" + +#define MULADDC_STOP \ + "st %%o2, %0 \n\t" \ + "st %%o1, %1 \n\t" \ + "st %%o0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "g1", "o0", "o1", "o2", "o3", "o4", \ + "o5" \ + ); + +#endif /* SPARCv8 */ + +#if defined(__microblaze__) || defined(microblaze) + +#define MULADDC_INIT \ + asm( \ + "lwi r3, %3 \n\t" \ + "lwi r4, %4 \n\t" \ + "lwi r5, %5 \n\t" \ + "lwi r6, %6 \n\t" \ + "andi r7, r6, 0xffff \n\t" \ + "bsrli r6, r6, 16 \n\t" + +#define MULADDC_CORE \ + "lhui r8, r3, 0 \n\t" \ + "addi r3, r3, 2 \n\t" \ + "lhui r9, r3, 0 \n\t" \ + "addi r3, r3, 2 \n\t" \ + "mul r10, r9, r6 \n\t" \ + "mul r11, r8, r7 \n\t" \ + "mul r12, r9, r7 \n\t" \ + "mul r13, r8, r6 \n\t" \ + "bsrli r8, r10, 16 \n\t" \ + "bsrli r9, r11, 16 \n\t" \ + "add r13, r13, r8 \n\t" \ + "add r13, r13, r9 \n\t" \ + "bslli r10, r10, 16 \n\t" \ + "bslli r11, r11, 16 \n\t" \ + "add r12, r12, r10 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "add r12, r12, r11 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "lwi r10, r4, 0 \n\t" \ + "add r12, r12, r10 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "add r12, r12, r5 \n\t" \ + "addc r5, r13, r0 \n\t" \ + "swi r12, r4, 0 \n\t" \ + "addi r4, r4, 4 \n\t" + +#define MULADDC_STOP \ + "swi r5, %0 \n\t" \ + "swi r4, %1 \n\t" \ + "swi r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4" "r5", "r6", "r7", "r8", \ + "r9", "r10", "r11", "r12", "r13" \ + ); + +#endif /* MicroBlaze */ + +#if defined(__tricore__) + +#define MULADDC_INIT \ + asm( \ + "ld.a %%a2, %3 \n\t" \ + "ld.a %%a3, %4 \n\t" \ + "ld.w %%d4, %5 \n\t" \ + "ld.w %%d1, %6 \n\t" \ + "xor %%d5, %%d5 \n\t" + +#define MULADDC_CORE \ + "ld.w %%d0, [%%a2+] \n\t" \ + "madd.u %%e2, %%e4, %%d0, %%d1 \n\t" \ + "ld.w %%d0, [%%a3] \n\t" \ + "addx %%d2, %%d2, %%d0 \n\t" \ + "addc %%d3, %%d3, 0 \n\t" \ + "mov %%d4, %%d3 \n\t" \ + "st.w [%%a3+], %%d2 \n\t" + +#define MULADDC_STOP \ + "st.w %0, %%d4 \n\t" \ + "st.a %1, %%a3 \n\t" \ + "st.a %2, %%a2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "d0", "d1", "e2", "d4", "a2", "a3" \ + ); + +#endif /* TriCore */ + +#if defined(__arm__) + +#if defined(__thumb__) && !defined(__thumb2__) + +#define MULADDC_INIT \ + asm( \ + "ldr r0, %3 \n\t" \ + "ldr r1, %4 \n\t" \ + "ldr r2, %5 \n\t" \ + "ldr r3, %6 \n\t" \ + "lsr r7, r3, #16 \n\t" \ + "mov r9, r7 \n\t" \ + "lsl r7, r3, #16 \n\t" \ + "lsr r7, r7, #16 \n\t" \ + "mov r8, r7 \n\t" + +#define MULADDC_CORE \ + "ldmia r0!, {r6} \n\t" \ + "lsr r7, r6, #16 \n\t" \ + "lsl r6, r6, #16 \n\t" \ + "lsr r6, r6, #16 \n\t" \ + "mov r4, r8 \n\t" \ + "mul r4, r6 \n\t" \ + "mov r3, r9 \n\t" \ + "mul r6, r3 \n\t" \ + "mov r5, r9 \n\t" \ + "mul r5, r7 \n\t" \ + "mov r3, r8 \n\t" \ + "mul r7, r3 \n\t" \ + "lsr r3, r6, #16 \n\t" \ + "add r5, r5, r3 \n\t" \ + "lsr r3, r7, #16 \n\t" \ + "add r5, r5, r3 \n\t" \ + "add r4, r4, r2 \n\t" \ + "mov r2, #0 \n\t" \ + "adc r5, r2 \n\t" \ + "lsl r3, r6, #16 \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r5, r2 \n\t" \ + "lsl r3, r7, #16 \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r5, r2 \n\t" \ + "ldr r3, [r1] \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r2, r5 \n\t" \ + "stmia r1!, {r4} \n\t" + +#define MULADDC_STOP \ + "str r2, %0 \n\t" \ + "str r1, %1 \n\t" \ + "str r0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r0", "r1", "r2", "r3", "r4", "r5", \ + "r6", "r7", "r8", "r9", "cc" \ + ); + +#else + +#define MULADDC_INIT \ + asm( \ + "ldr r0, %3 \n\t" \ + "ldr r1, %4 \n\t" \ + "ldr r2, %5 \n\t" \ + "ldr r3, %6 \n\t" + +#define MULADDC_CORE \ + "ldr r4, [r0], #4 \n\t" \ + "mov r5, #0 \n\t" \ + "ldr r6, [r1] \n\t" \ + "umlal r2, r5, r3, r4 \n\t" \ + "adds r7, r6, r2 \n\t" \ + "adc r2, r5, #0 \n\t" \ + "str r7, [r1], #4 \n\t" + +#define MULADDC_STOP \ + "str r2, %0 \n\t" \ + "str r1, %1 \n\t" \ + "str r0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r0", "r1", "r2", "r3", "r4", "r5", \ + "r6", "r7", "cc" \ + ); + +#endif /* Thumb */ + +#endif /* ARMv3 */ + +#if defined(__alpha__) + +#define MULADDC_INIT \ + asm( \ + "ldq $1, %3 \n\t" \ + "ldq $2, %4 \n\t" \ + "ldq $3, %5 \n\t" \ + "ldq $4, %6 \n\t" + +#define MULADDC_CORE \ + "ldq $6, 0($1) \n\t" \ + "addq $1, 8, $1 \n\t" \ + "mulq $6, $4, $7 \n\t" \ + "umulh $6, $4, $6 \n\t" \ + "addq $7, $3, $7 \n\t" \ + "cmpult $7, $3, $3 \n\t" \ + "ldq $5, 0($2) \n\t" \ + "addq $7, $5, $7 \n\t" \ + "cmpult $7, $5, $5 \n\t" \ + "stq $7, 0($2) \n\t" \ + "addq $2, 8, $2 \n\t" \ + "addq $6, $3, $3 \n\t" \ + "addq $5, $3, $3 \n\t" + +#define MULADDC_STOP \ + "stq $3, %0 \n\t" \ + "stq $2, %1 \n\t" \ + "stq $1, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "$1", "$2", "$3", "$4", "$5", "$6", "$7" \ + ); +#endif /* Alpha */ + +#if defined(__mips__) && !defined(__mips64__) + +#define MULADDC_INIT \ + asm( \ + "lw $10, %3 \n\t" \ + "lw $11, %4 \n\t" \ + "lw $12, %5 \n\t" \ + "lw $13, %6 \n\t" + +#define MULADDC_CORE \ + "lw $14, 0($10) \n\t" \ + "multu $13, $14 \n\t" \ + "addi $10, $10, 4 \n\t" \ + "mflo $14 \n\t" \ + "mfhi $9 \n\t" \ + "addu $14, $12, $14 \n\t" \ + "lw $15, 0($11) \n\t" \ + "sltu $12, $14, $12 \n\t" \ + "addu $15, $14, $15 \n\t" \ + "sltu $14, $15, $14 \n\t" \ + "addu $12, $12, $9 \n\t" \ + "sw $15, 0($11) \n\t" \ + "addu $12, $12, $14 \n\t" \ + "addi $11, $11, 4 \n\t" + +#define MULADDC_STOP \ + "sw $12, %0 \n\t" \ + "sw $11, %1 \n\t" \ + "sw $10, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "$9", "$10", "$11", "$12", "$13", "$14", "$15" \ + ); + +#endif /* MIPS */ +#endif /* GNUC */ + +#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) + +#define MULADDC_INIT \ + __asm mov esi, s \ + __asm mov edi, d \ + __asm mov ecx, c \ + __asm mov ebx, b + +#define MULADDC_CORE \ + __asm lodsd \ + __asm mul ebx \ + __asm add eax, ecx \ + __asm adc edx, 0 \ + __asm add eax, [edi] \ + __asm adc edx, 0 \ + __asm mov ecx, edx \ + __asm stosd + +#if defined(POLARSSL_HAVE_SSE2) + +#define EMIT __asm _emit + +#define MULADDC_HUIT \ + EMIT 0x0F EMIT 0x6E EMIT 0xC9 \ + EMIT 0x0F EMIT 0x6E EMIT 0xC3 \ + EMIT 0x0F EMIT 0x6E EMIT 0x1F \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x6E EMIT 0x16 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x04 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x08 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x7E EMIT 0x0C \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF8 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ + EMIT 0x0F EMIT 0x6E EMIT 0x5F EMIT 0x04 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xDC \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x08 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xEE \ + EMIT 0x0F EMIT 0x6E EMIT 0x67 EMIT 0x0C \ + EMIT 0x0F EMIT 0xD4 EMIT 0xFC \ + EMIT 0x0F EMIT 0x7E EMIT 0x0F \ + EMIT 0x0F EMIT 0x6E EMIT 0x56 EMIT 0x10 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x14 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x18 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x04 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x6E EMIT 0x5E EMIT 0x1C \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD8 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCD \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x10 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xD5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x08 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCF \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x14 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xE5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x0C \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x18 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xF5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x10 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCC \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x1C \ + EMIT 0x0F EMIT 0xD4 EMIT 0xDD \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x14 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCE \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x18 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x1C \ + EMIT 0x83 EMIT 0xC7 EMIT 0x20 \ + EMIT 0x83 EMIT 0xC6 EMIT 0x20 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x7E EMIT 0xC9 + +#define MULADDC_STOP \ + EMIT 0x0F EMIT 0x77 \ + __asm mov c, ecx \ + __asm mov d, edi \ + __asm mov s, esi \ + +#else + +#define MULADDC_STOP \ + __asm mov c, ecx \ + __asm mov d, edi \ + __asm mov s, esi \ + +#endif /* SSE2 */ +#endif /* MSVC */ + +#endif /* POLARSSL_HAVE_ASM */ + +#if !defined(MULADDC_CORE) +#if defined(POLARSSL_HAVE_UDBL) + +#define MULADDC_INIT \ +{ \ + t_udbl r; \ + t_uint r0, r1; + +#define MULADDC_CORE \ + r = *(s++) * (t_udbl) b; \ + r0 = r; \ + r1 = r >> biL; \ + r0 += c; r1 += (r0 < c); \ + r0 += *d; r1 += (r0 < *d); \ + c = r1; *(d++) = r0; + +#define MULADDC_STOP \ +} + +#else +#define MULADDC_INIT \ +{ \ + t_uint s0, s1, b0, b1; \ + t_uint r0, r1, rx, ry; \ + b0 = ( b << biH ) >> biH; \ + b1 = ( b >> biH ); + +#define MULADDC_CORE \ + s0 = ( *s << biH ) >> biH; \ + s1 = ( *s >> biH ); s++; \ + rx = s0 * b1; r0 = s0 * b0; \ + ry = s1 * b0; r1 = s1 * b1; \ + r1 += ( rx >> biH ); \ + r1 += ( ry >> biH ); \ + rx <<= biH; ry <<= biH; \ + r0 += rx; r1 += (r0 < rx); \ + r0 += ry; r1 += (r0 < ry); \ + r0 += c; r1 += (r0 < c); \ + r0 += *d; r1 += (r0 < *d); \ + c = r1; *(d++) = r0; + +#define MULADDC_STOP \ +} + +#endif /* C (generic) */ +#endif /* C (longlong) */ + +#endif /* bn_mul.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/camellia.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/camellia.h new file mode 100644 index 0000000..8488d1d --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/camellia.h @@ -0,0 +1,229 @@ +/** + * \file camellia.h + * + * \brief Camellia block cipher + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_CAMELLIA_H +#define POLARSSL_CAMELLIA_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include + +#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32) +#include +typedef UINT32 uint32_t; +#else +#include +#endif + +#define CAMELLIA_ENCRYPT 1 +#define CAMELLIA_DECRYPT 0 + +#define POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH -0x0024 /**< Invalid key length. */ +#define POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH -0x0026 /**< Invalid data input length. */ + +#if !defined(POLARSSL_CAMELLIA_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief CAMELLIA context structure + */ +typedef struct +{ + int nr; /*!< number of rounds */ + uint32_t rk[68]; /*!< CAMELLIA round keys */ +} +camellia_context; + +/** + * \brief Initialize CAMELLIA context + * + * \param ctx CAMELLIA context to be initialized + */ +void camellia_init( camellia_context *ctx ); + +/** + * \brief Clear CAMELLIA context + * + * \param ctx CAMELLIA context to be cleared + */ +void camellia_free( camellia_context *ctx ); + +/** + * \brief CAMELLIA key schedule (encryption) + * + * \param ctx CAMELLIA context to be initialized + * \param key encryption key + * \param keysize must be 128, 192 or 256 + * + * \return 0 if successful, or POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH + */ +int camellia_setkey_enc( camellia_context *ctx, const unsigned char *key, + unsigned int keysize ); + +/** + * \brief CAMELLIA key schedule (decryption) + * + * \param ctx CAMELLIA context to be initialized + * \param key decryption key + * \param keysize must be 128, 192 or 256 + * + * \return 0 if successful, or POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH + */ +int camellia_setkey_dec( camellia_context *ctx, const unsigned char *key, + unsigned int keysize ); + +/** + * \brief CAMELLIA-ECB block encryption/decryption + * + * \param ctx CAMELLIA context + * \param mode CAMELLIA_ENCRYPT or CAMELLIA_DECRYPT + * \param input 16-byte input block + * \param output 16-byte output block + * + * \return 0 if successful + */ +int camellia_crypt_ecb( camellia_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +#if defined(POLARSSL_CIPHER_MODE_CBC) +/** + * \brief CAMELLIA-CBC buffer encryption/decryption + * Length should be a multiple of the block + * size (16 bytes) + * + * \param ctx CAMELLIA context + * \param mode CAMELLIA_ENCRYPT or CAMELLIA_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful, or + * POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH + */ +int camellia_crypt_cbc( camellia_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_CIPHER_MODE_CFB) +/** + * \brief CAMELLIA-CFB128 buffer encryption/decryption + * + * Note: Due to the nature of CFB you should use the same key schedule for + * both encryption and decryption. So a context initialized with + * camellia_setkey_enc() for both CAMELLIA_ENCRYPT and CAMELLIE_DECRYPT. + * + * \param ctx CAMELLIA context + * \param mode CAMELLIA_ENCRYPT or CAMELLIA_DECRYPT + * \param length length of the input data + * \param iv_off offset in IV (updated after use) + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful, or + * POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH + */ +int camellia_crypt_cfb128( camellia_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /* POLARSSL_CIPHER_MODE_CFB */ + +#if defined(POLARSSL_CIPHER_MODE_CTR) +/** + * \brief CAMELLIA-CTR buffer encryption/decryption + * + * Warning: You have to keep the maximum use of your counter in mind! + * + * Note: Due to the nature of CTR you should use the same key schedule for + * both encryption and decryption. So a context initialized with + * camellia_setkey_enc() for both CAMELLIA_ENCRYPT and CAMELLIA_DECRYPT. + * + * \param ctx CAMELLIA context + * \param length The length of the data + * \param nc_off The offset in the current stream_block (for resuming + * within current cipher stream). The offset pointer to + * should be 0 at the start of a stream. + * \param nonce_counter The 128-bit nonce and counter. + * \param stream_block The saved stream-block for resuming. Is overwritten + * by the function. + * \param input The input data stream + * \param output The output data stream + * + * \return 0 if successful + */ +int camellia_crypt_ctr( camellia_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ); +#endif /* POLARSSL_CIPHER_MODE_CTR */ + +#ifdef __cplusplus +} +#endif + +#else /* POLARSSL_CAMELLIA_ALT */ +#include "camellia_alt.h" +#endif /* POLARSSL_CAMELLIA_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int camellia_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* camellia.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/ccm.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/ccm.h new file mode 100644 index 0000000..439152f --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/ccm.h @@ -0,0 +1,134 @@ +/** + * \file ccm.h + * + * \brief Counter with CBC-MAC (CCM) for 128-bit block ciphers + * + * Copyright (C) 2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_CCM_H +#define POLARSSL_CCM_H + +#include "cipher.h" + +#define POLARSSL_ERR_CCM_BAD_INPUT -0x000D /**< Bad input parameters to function. */ +#define POLARSSL_ERR_CCM_AUTH_FAILED -0x000F /**< Authenticated decryption failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief CCM context structure + */ +typedef struct { + cipher_context_t cipher_ctx; /*!< cipher context used */ +} +ccm_context; + +/** + * \brief CCM initialization (encryption and decryption) + * + * \param ctx CCM context to be initialized + * \param cipher cipher to use (a 128-bit block cipher) + * \param key encryption key + * \param keysize key size in bits (must be acceptable by the cipher) + * + * \return 0 if successful, or a cipher specific error code + */ +int ccm_init( ccm_context *ctx, cipher_id_t cipher, + const unsigned char *key, unsigned int keysize ); + +/** + * \brief Free a CCM context and underlying cipher sub-context + * + * \param ctx CCM context to free + */ +void ccm_free( ccm_context *ctx ); + +/** + * \brief CCM buffer encryption + * + * \param ctx CCM context + * \param length length of the input data in bytes + * \param iv nonce (initialization vector) + * \param iv_len length of IV in bytes + * must be 2, 3, 4, 5, 6, 7 or 8 + * \param add additional data + * \param add_len length of additional data in bytes + * must be less than 2^16 - 2^8 + * \param input buffer holding the input data + * \param output buffer for holding the output data + * must be at least 'length' bytes wide + * \param tag buffer for holding the tag + * \param tag_len length of the tag to generate in bytes + * must be 4, 6, 8, 10, 14 or 16 + * + * \note The tag is written to a separate buffer. To get the tag + * concatenated with the output as in the CCM spec, use + * tag = output + length and make sure the output buffer is + * at least length + tag_len wide. + * + * \return 0 if successful + */ +int ccm_encrypt_and_tag( ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len ); + +/** + * \brief CCM buffer authenticated decryption + * + * \param ctx CCM context + * \param length length of the input data + * \param iv initialization vector + * \param iv_len length of IV + * \param add additional data + * \param add_len length of additional data + * \param input buffer holding the input data + * \param output buffer for holding the output data + * \param tag buffer holding the tag + * \param tag_len length of the tag + * + * \return 0 if successful and authenticated, + * POLARSSL_ERR_CCM_AUTH_FAILED if tag does not match + */ +int ccm_auth_decrypt( ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + const unsigned char *tag, size_t tag_len ); + +#if defined(POLARSSL_SELF_TEST) && defined(POLARSSL_AES_C) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int ccm_self_test( int verbose ); +#endif /* POLARSSL_SELF_TEST && POLARSSL_AES_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* POLARSSL_CGM_H */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/certs.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/certs.h new file mode 100644 index 0000000..ba7c028 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/certs.h @@ -0,0 +1,77 @@ +/** + * \file certs.h + * + * \brief Sample certificates and DHM parameters for testing + * + * Copyright (C) 2006-2010, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_CERTS_H +#define POLARSSL_CERTS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Concatenation of all available CA certificates */ +extern const char test_ca_list[]; + +/* + * Convenience for users who just want a certificate: + * RSA by default, or ECDSA if RSA i not available + */ +extern const char *test_ca_crt; +extern const char *test_ca_key; +extern const char *test_ca_pwd; +extern const char *test_srv_crt; +extern const char *test_srv_key; +extern const char *test_cli_crt; +extern const char *test_cli_key; + +#if defined(POLARSSL_ECDSA_C) +extern const char test_ca_crt_ec[]; +extern const char test_ca_key_ec[]; +extern const char test_ca_pwd_ec[]; +extern const char test_srv_crt_ec[]; +extern const char test_srv_key_ec[]; +extern const char test_cli_crt_ec[]; +extern const char test_cli_key_ec[]; +#endif + +#if defined(POLARSSL_RSA_C) +extern const char test_ca_crt_rsa[]; +extern const char test_ca_key_rsa[]; +extern const char test_ca_pwd_rsa[]; +extern const char test_srv_crt_rsa[]; +extern const char test_srv_key_rsa[]; +extern const char test_cli_crt_rsa[]; +extern const char test_cli_key_rsa[]; +#endif + +#if defined(POLARSSL_DHM_C) +extern const char test_dhm_params[]; +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* certs.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/check_config.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/check_config.h new file mode 100644 index 0000000..328b881 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/check_config.h @@ -0,0 +1,326 @@ +/** + * \file check_config.h + * + * \brief Consistency checks for configuration options + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* + * It is recommended to include this file from your config.h + * in order to catch dependency issues early. + */ + +#ifndef POLARSSL_CHECK_CONFIG_H +#define POLARSSL_CHECK_CONFIG_H + +#if defined(POLARSSL_AESNI_C) && !defined(POLARSSL_HAVE_ASM) +#error "POLARSSL_AESNI_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_CERTS_C) && !defined(POLARSSL_PEM_PARSE_C) +#error "POLARSSL_CERTS_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_CTR_DRBG_C) && !defined(POLARSSL_AES_C) +#error "POLARSSL_CTR_DRBG_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_DHM_C) && !defined(POLARSSL_BIGNUM_C) +#error "POLARSSL_DHM_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_ECDH_C) && !defined(POLARSSL_ECP_C) +#error "POLARSSL_ECDH_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_ECDSA_C) && \ + ( !defined(POLARSSL_ECP_C) || \ + !defined(POLARSSL_ASN1_PARSE_C) || \ + !defined(POLARSSL_ASN1_WRITE_C) ) +#error "POLARSSL_ECDSA_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_ECDSA_DETERMINISTIC) && !defined(POLARSSL_HMAC_DRBG_C) +#error "POLARSSL_ECDSA_DETERMINISTIC defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_ECP_C) && ( !defined(POLARSSL_BIGNUM_C) || ( \ + !defined(POLARSSL_ECP_DP_SECP192R1_ENABLED) && \ + !defined(POLARSSL_ECP_DP_SECP224R1_ENABLED) && \ + !defined(POLARSSL_ECP_DP_SECP256R1_ENABLED) && \ + !defined(POLARSSL_ECP_DP_SECP384R1_ENABLED) && \ + !defined(POLARSSL_ECP_DP_SECP521R1_ENABLED) && \ + !defined(POLARSSL_ECP_DP_BP256R1_ENABLED) && \ + !defined(POLARSSL_ECP_DP_BP384R1_ENABLED) && \ + !defined(POLARSSL_ECP_DP_BP512R1_ENABLED) && \ + !defined(POLARSSL_ECP_DP_SECP192K1_ENABLED) && \ + !defined(POLARSSL_ECP_DP_SECP224K1_ENABLED) && \ + !defined(POLARSSL_ECP_DP_SECP256K1_ENABLED) ) ) +#error "POLARSSL_ECP_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_ENTROPY_C) && (!defined(POLARSSL_SHA512_C) && \ + !defined(POLARSSL_SHA256_C)) +#error "POLARSSL_ENTROPY_C defined, but not all prerequisites" +#endif +#if defined(POLARSSL_ENTROPY_C) && defined(POLARSSL_SHA512_C) && \ + defined(CTR_DRBG_ENTROPY_LEN) && (CTR_DRBG_ENTROPY_LEN > 64) +#error "CTR_DRBG_ENTROPY_LEN value too high" +#endif +#if defined(POLARSSL_ENTROPY_C) && \ + ( !defined(POLARSSL_SHA512_C) || defined(POLARSSL_ENTROPY_FORCE_SHA256) ) \ + && defined(CTR_DRBG_ENTROPY_LEN) && (CTR_DRBG_ENTROPY_LEN > 32) +#error "CTR_DRBG_ENTROPY_LEN value too high" +#endif +#if defined(POLARSSL_ENTROPY_C) && \ + defined(POLARSSL_ENTROPY_FORCE_SHA256) && !defined(POLARSSL_SHA256_C) +#error "POLARSSL_ENTROPY_FORCE_SHA256 defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_GCM_C) && ( \ + !defined(POLARSSL_AES_C) && !defined(POLARSSL_CAMELLIA_C) ) +#error "POLARSSL_GCM_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_HAVEGE_C) && !defined(POLARSSL_TIMING_C) +#error "POLARSSL_HAVEGE_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_HMAC_DRBG) && !defined(POLARSSL_MD_C) +#error "POLARSSL_HMAC_DRBG_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) && \ + ( !defined(POLARSSL_ECDH_C) || !defined(POLARSSL_X509_CRT_PARSE_C) ) +#error "POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ + ( !defined(POLARSSL_ECDH_C) || !defined(POLARSSL_X509_CRT_PARSE_C) ) +#error "POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) && !defined(POLARSSL_DHM_C) +#error "POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) && \ + !defined(POLARSSL_ECDH_C) +#error "POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ + ( !defined(POLARSSL_DHM_C) || !defined(POLARSSL_RSA_C) || \ + !defined(POLARSSL_X509_CRT_PARSE_C) || !defined(POLARSSL_PKCS1_V15) ) +#error "POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ + ( !defined(POLARSSL_ECDH_C) || !defined(POLARSSL_RSA_C) || \ + !defined(POLARSSL_X509_CRT_PARSE_C) || !defined(POLARSSL_PKCS1_V15) ) +#error "POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \ + ( !defined(POLARSSL_ECDH_C) || !defined(POLARSSL_ECDSA_C) || \ + !defined(POLARSSL_X509_CRT_PARSE_C) ) +#error "POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) && \ + ( !defined(POLARSSL_RSA_C) || !defined(POLARSSL_X509_CRT_PARSE_C) ||\ + !defined(POLARSSL_PKCS1_V15) ) +#error "POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) && \ + ( !defined(POLARSSL_RSA_C) || !defined(POLARSSL_X509_CRT_PARSE_C) ||\ + !defined(POLARSSL_PKCS1_V15) ) +#error "POLARSSL_KEY_EXCHANGE_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_MEMORY_BUFFER_ALLOC_C) && \ + ( !defined(POLARSSL_PLATFORM_C) || !defined(POLARSSL_PLATFORM_MEMORY) ) +#error "POLARSSL_MEMORY_BUFFER_ALLOC_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_PADLOCK_C) && !defined(POLARSSL_HAVE_ASM) +#error "POLARSSL_PADLOCK_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_PBKDF2_C) && !defined(POLARSSL_MD_C) +#error "POLARSSL_PBKDF2_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_PEM_PARSE_C) && !defined(POLARSSL_BASE64_C) +#error "POLARSSL_PEM_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_PEM_WRITE_C) && !defined(POLARSSL_BASE64_C) +#error "POLARSSL_PEM_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_PK_PARSE_C) && !defined(POLARSSL_PK_C) +#error "POLARSSL_PK_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_PK_WRITE_C) && !defined(POLARSSL_PK_C) +#error "POLARSSL_PK_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_PKCS11_C) && !defined(POLARSSL_PK_C) +#error "POLARSSL_PKCS11_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_RSA_C) && ( !defined(POLARSSL_BIGNUM_C) || \ + !defined(POLARSSL_OID_C) ) +#error "POLARSSL_RSA_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_X509_RSASSA_PSS_SUPPORT) && \ + ( !defined(POLARSSL_RSA_C) || !defined(POLARSSL_PKCS1_V21) ) +#error "POLARSSL_X509_RSASSA_PSS_SUPPORT defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_SSL_PROTO_SSL3) && ( !defined(POLARSSL_MD5_C) || \ + !defined(POLARSSL_SHA1_C) ) +#error "POLARSSL_SSL_PROTO_SSL3 defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_SSL_PROTO_TLS1) && ( !defined(POLARSSL_MD5_C) || \ + !defined(POLARSSL_SHA1_C) ) +#error "POLARSSL_SSL_PROTO_TLS1 defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_SSL_PROTO_TLS1_1) && ( !defined(POLARSSL_MD5_C) || \ + !defined(POLARSSL_SHA1_C) ) +#error "POLARSSL_SSL_PROTO_TLS1_1 defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_SSL_PROTO_TLS1_2) && ( !defined(POLARSSL_SHA1_C) && \ + !defined(POLARSSL_SHA256_C) && !defined(POLARSSL_SHA512_C) ) +#error "POLARSSL_SSL_PROTO_TLS1_2 defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_SSL_CLI_C) && !defined(POLARSSL_SSL_TLS_C) +#error "POLARSSL_SSL_CLI_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_SSL_TLS_C) && ( !defined(POLARSSL_CIPHER_C) || \ + !defined(POLARSSL_MD_C) ) +#error "POLARSSL_SSL_TLS_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_SSL_SRV_C) && !defined(POLARSSL_SSL_TLS_C) +#error "POLARSSL_SSL_SRV_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_SSL_TLS_C) && (!defined(POLARSSL_SSL_PROTO_SSL3) && \ + !defined(POLARSSL_SSL_PROTO_TLS1) && !defined(POLARSSL_SSL_PROTO_TLS1_1) && \ + !defined(POLARSSL_SSL_PROTO_TLS1_2)) +#error "POLARSSL_SSL_TLS_C defined, but no protocols are active" +#endif + +#if defined(POLARSSL_SSL_TLS_C) && (defined(POLARSSL_SSL_PROTO_SSL3) && \ + defined(POLARSSL_SSL_PROTO_TLS1_1) && !defined(POLARSSL_SSL_PROTO_TLS1)) +#error "Illegal protocol selection" +#endif + +#if defined(POLARSSL_SSL_TLS_C) && (defined(POLARSSL_SSL_PROTO_TLS1) && \ + defined(POLARSSL_SSL_PROTO_TLS1_2) && !defined(POLARSSL_SSL_PROTO_TLS1_1)) +#error "Illegal protocol selection" +#endif + +#if defined(POLARSSL_SSL_TLS_C) && (defined(POLARSSL_SSL_PROTO_SSL3) && \ + defined(POLARSSL_SSL_PROTO_TLS1_2) && (!defined(POLARSSL_SSL_PROTO_TLS1) || \ + !defined(POLARSSL_SSL_PROTO_TLS1_1))) +#error "Illegal protocol selection" +#endif + +#if defined(POLARSSL_SSL_SESSION_TICKETS) && defined(POLARSSL_SSL_TLS_C) && \ + ( !defined(POLARSSL_AES_C) || !defined(POLARSSL_SHA256_C) || \ + !defined(POLARSSL_CIPHER_MODE_CBC) ) +#error "POLARSSL_SSL_SESSION_TICKETS_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION) && \ + !defined(POLARSSL_X509_CRT_PARSE_C) +#error "POLARSSL_SSL_SERVER_NAME_INDICATION defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_THREADING_PTHREAD) +#if !defined(POLARSSL_THREADING_C) || defined(POLARSSL_THREADING_IMPL) +#error "POLARSSL_THREADING_PTHREAD defined, but not all prerequisites" +#endif +#define POLARSSL_THREADING_IMPL +#endif + +#if defined(POLARSSL_THREADING_ALT) +#if !defined(POLARSSL_THREADING_C) || defined(POLARSSL_THREADING_IMPL) +#error "POLARSSL_THREADING_ALT defined, but not all prerequisites" +#endif +#define POLARSSL_THREADING_IMPL +#endif + +#if defined(POLARSSL_THREADING_C) && !defined(POLARSSL_THREADING_IMPL) +#error "POLARSSL_THREADING_C defined, single threading implementation required" +#endif +#undef POLARSSL_THREADING_IMPL + +#if defined(POLARSSL_VERSION_FEATURES) && !defined(POLARSSL_VERSION_C) +#error "POLARSSL_VERSION_FEATURES defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_X509_USE_C) && ( !defined(POLARSSL_BIGNUM_C) || \ + !defined(POLARSSL_OID_C) || !defined(POLARSSL_ASN1_PARSE_C) || \ + !defined(POLARSSL_PK_PARSE_C) ) +#error "POLARSSL_X509_USE_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_X509_CREATE_C) && ( !defined(POLARSSL_BIGNUM_C) || \ + !defined(POLARSSL_OID_C) || !defined(POLARSSL_ASN1_WRITE_C) || \ + !defined(POLARSSL_PK_WRITE_C) ) +#error "POLARSSL_X509_CREATE_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_X509_CRT_PARSE_C) && ( !defined(POLARSSL_X509_USE_C) ) +#error "POLARSSL_X509_CRT_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_X509_CRL_PARSE_C) && ( !defined(POLARSSL_X509_USE_C) ) +#error "POLARSSL_X509_CRL_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_X509_CSR_PARSE_C) && ( !defined(POLARSSL_X509_USE_C) ) +#error "POLARSSL_X509_CSR_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_X509_CRT_WRITE_C) && ( !defined(POLARSSL_X509_CREATE_C) ) +#error "POLARSSL_X509_CRT_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_X509_CSR_WRITE_C) && ( !defined(POLARSSL_X509_CREATE_C) ) +#error "POLARSSL_X509_CSR_WRITE_C defined, but not all prerequisites" +#endif + +#endif /* POLARSSL_CHECK_CONFIG_H */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/cipher.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/cipher.h new file mode 100644 index 0000000..087e590 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/cipher.h @@ -0,0 +1,760 @@ +/** + * \file cipher.h + * + * \brief Generic cipher wrapper. + * + * \author Adriaan de Jong + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef POLARSSL_CIPHER_H +#define POLARSSL_CIPHER_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_GCM_C) || defined(POLARSSL_CCM_C) +#define POLARSSL_CIPHER_MODE_AEAD +#endif + +#if defined(POLARSSL_CIPHER_MODE_CBC) +#define POLARSSL_CIPHER_MODE_WITH_PADDING +#endif + +#include + +#if defined(_MSC_VER) && !defined(inline) +#define inline _inline +#else +#if defined(__ARMCC_VERSION) && !defined(inline) +#define inline __inline +#endif /* __ARMCC_VERSION */ +#endif /*_MSC_VER */ + +#define POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE -0x6080 /**< The selected feature is not available. */ +#define POLARSSL_ERR_CIPHER_BAD_INPUT_DATA -0x6100 /**< Bad input parameters to function. */ +#define POLARSSL_ERR_CIPHER_ALLOC_FAILED -0x6180 /**< Failed to allocate memory. */ +#define POLARSSL_ERR_CIPHER_INVALID_PADDING -0x6200 /**< Input data contains invalid padding and is rejected. */ +#define POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED -0x6280 /**< Decryption of block requires a full block. */ +#define POLARSSL_ERR_CIPHER_AUTH_FAILED -0x6300 /**< Authentication failed (for AEAD modes). */ + +#define POLARSSL_CIPHER_VARIABLE_IV_LEN 0x01 /**< Cipher accepts IVs of variable length */ +#define POLARSSL_CIPHER_VARIABLE_KEY_LEN 0x02 /**< Cipher accepts keys of variable length */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + POLARSSL_CIPHER_ID_NONE = 0, + POLARSSL_CIPHER_ID_NULL, + POLARSSL_CIPHER_ID_AES, + POLARSSL_CIPHER_ID_DES, + POLARSSL_CIPHER_ID_3DES, + POLARSSL_CIPHER_ID_CAMELLIA, + POLARSSL_CIPHER_ID_BLOWFISH, + POLARSSL_CIPHER_ID_ARC4, +} cipher_id_t; + +typedef enum { + POLARSSL_CIPHER_NONE = 0, + POLARSSL_CIPHER_NULL, + POLARSSL_CIPHER_AES_128_ECB, + POLARSSL_CIPHER_AES_192_ECB, + POLARSSL_CIPHER_AES_256_ECB, + POLARSSL_CIPHER_AES_128_CBC, + POLARSSL_CIPHER_AES_192_CBC, + POLARSSL_CIPHER_AES_256_CBC, + POLARSSL_CIPHER_AES_128_CFB128, + POLARSSL_CIPHER_AES_192_CFB128, + POLARSSL_CIPHER_AES_256_CFB128, + POLARSSL_CIPHER_AES_128_CTR, + POLARSSL_CIPHER_AES_192_CTR, + POLARSSL_CIPHER_AES_256_CTR, + POLARSSL_CIPHER_AES_128_GCM, + POLARSSL_CIPHER_AES_192_GCM, + POLARSSL_CIPHER_AES_256_GCM, + POLARSSL_CIPHER_CAMELLIA_128_ECB, + POLARSSL_CIPHER_CAMELLIA_192_ECB, + POLARSSL_CIPHER_CAMELLIA_256_ECB, + POLARSSL_CIPHER_CAMELLIA_128_CBC, + POLARSSL_CIPHER_CAMELLIA_192_CBC, + POLARSSL_CIPHER_CAMELLIA_256_CBC, + POLARSSL_CIPHER_CAMELLIA_128_CFB128, + POLARSSL_CIPHER_CAMELLIA_192_CFB128, + POLARSSL_CIPHER_CAMELLIA_256_CFB128, + POLARSSL_CIPHER_CAMELLIA_128_CTR, + POLARSSL_CIPHER_CAMELLIA_192_CTR, + POLARSSL_CIPHER_CAMELLIA_256_CTR, + POLARSSL_CIPHER_CAMELLIA_128_GCM, + POLARSSL_CIPHER_CAMELLIA_192_GCM, + POLARSSL_CIPHER_CAMELLIA_256_GCM, + POLARSSL_CIPHER_DES_ECB, + POLARSSL_CIPHER_DES_CBC, + POLARSSL_CIPHER_DES_EDE_ECB, + POLARSSL_CIPHER_DES_EDE_CBC, + POLARSSL_CIPHER_DES_EDE3_ECB, + POLARSSL_CIPHER_DES_EDE3_CBC, + POLARSSL_CIPHER_BLOWFISH_ECB, + POLARSSL_CIPHER_BLOWFISH_CBC, + POLARSSL_CIPHER_BLOWFISH_CFB64, + POLARSSL_CIPHER_BLOWFISH_CTR, + POLARSSL_CIPHER_ARC4_128, + POLARSSL_CIPHER_AES_128_CCM, + POLARSSL_CIPHER_AES_192_CCM, + POLARSSL_CIPHER_AES_256_CCM, + POLARSSL_CIPHER_CAMELLIA_128_CCM, + POLARSSL_CIPHER_CAMELLIA_192_CCM, + POLARSSL_CIPHER_CAMELLIA_256_CCM, +} cipher_type_t; + +typedef enum { + POLARSSL_MODE_NONE = 0, + POLARSSL_MODE_ECB, + POLARSSL_MODE_CBC, + POLARSSL_MODE_CFB, + POLARSSL_MODE_OFB, /* Unused! */ + POLARSSL_MODE_CTR, + POLARSSL_MODE_GCM, + POLARSSL_MODE_STREAM, + POLARSSL_MODE_CCM, +} cipher_mode_t; + +typedef enum { + POLARSSL_PADDING_PKCS7 = 0, /**< PKCS7 padding (default) */ + POLARSSL_PADDING_ONE_AND_ZEROS, /**< ISO/IEC 7816-4 padding */ + POLARSSL_PADDING_ZEROS_AND_LEN, /**< ANSI X.923 padding */ + POLARSSL_PADDING_ZEROS, /**< zero padding (not reversible!) */ + POLARSSL_PADDING_NONE, /**< never pad (full blocks only) */ +} cipher_padding_t; + +typedef enum { + POLARSSL_OPERATION_NONE = -1, + POLARSSL_DECRYPT = 0, + POLARSSL_ENCRYPT, +} operation_t; + +enum { + /** Undefined key length */ + POLARSSL_KEY_LENGTH_NONE = 0, + /** Key length, in bits (including parity), for DES keys */ + POLARSSL_KEY_LENGTH_DES = 64, + /** Key length, in bits (including parity), for DES in two key EDE */ + POLARSSL_KEY_LENGTH_DES_EDE = 128, + /** Key length, in bits (including parity), for DES in three-key EDE */ + POLARSSL_KEY_LENGTH_DES_EDE3 = 192, +}; + +/** Maximum length of any IV, in bytes */ +#define POLARSSL_MAX_IV_LENGTH 16 +/** Maximum block size of any cipher, in bytes */ +#define POLARSSL_MAX_BLOCK_LENGTH 16 + +/** + * Base cipher information. The non-mode specific functions and values. + */ +typedef struct { + + /** Base Cipher type (e.g. POLARSSL_CIPHER_ID_AES) */ + cipher_id_t cipher; + + /** Encrypt using ECB */ + int (*ecb_func)( void *ctx, operation_t mode, + const unsigned char *input, unsigned char *output ); + + /** Encrypt using CBC */ + int (*cbc_func)( void *ctx, operation_t mode, size_t length, + unsigned char *iv, const unsigned char *input, + unsigned char *output ); + + /** Encrypt using CFB (Full length) */ + int (*cfb_func)( void *ctx, operation_t mode, size_t length, size_t *iv_off, + unsigned char *iv, const unsigned char *input, + unsigned char *output ); + + /** Encrypt using CTR */ + int (*ctr_func)( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ); + + /** Encrypt using STREAM */ + int (*stream_func)( void *ctx, size_t length, + const unsigned char *input, unsigned char *output ); + + /** Set key for encryption purposes */ + int (*setkey_enc_func)( void *ctx, const unsigned char *key, + unsigned int key_length ); + + /** Set key for decryption purposes */ + int (*setkey_dec_func)( void *ctx, const unsigned char *key, + unsigned int key_length); + + /** Allocate a new context */ + void * (*ctx_alloc_func)( void ); + + /** Free the given context */ + void (*ctx_free_func)( void *ctx ); + +} cipher_base_t; + +/** + * Cipher information. Allows cipher functions to be called in a generic way. + */ +typedef struct { + /** Full cipher identifier (e.g. POLARSSL_CIPHER_AES_256_CBC) */ + cipher_type_t type; + + /** Cipher mode (e.g. POLARSSL_MODE_CBC) */ + cipher_mode_t mode; + + /** Cipher key length, in bits (default length for variable sized ciphers) + * (Includes parity bits for ciphers like DES) */ + unsigned int key_length; + + /** Name of the cipher */ + const char * name; + + /** IV/NONCE size, in bytes. + * For cipher that accept many sizes: recommended size */ + unsigned int iv_size; + + /** Flags for variable IV size, variable key size, etc. */ + int flags; + + /** block size, in bytes */ + unsigned int block_size; + + /** Base cipher information and functions */ + const cipher_base_t *base; + +} cipher_info_t; + +/** + * Generic cipher context. + */ +typedef struct { + /** Information about the associated cipher */ + const cipher_info_t *cipher_info; + + /** Key length to use */ + int key_length; + + /** Operation that the context's key has been initialised for */ + operation_t operation; + + /** Padding functions to use, if relevant for cipher mode */ + void (*add_padding)( unsigned char *output, size_t olen, size_t data_len ); + int (*get_padding)( unsigned char *input, size_t ilen, size_t *data_len ); + + /** Buffer for data that hasn't been encrypted yet */ + unsigned char unprocessed_data[POLARSSL_MAX_BLOCK_LENGTH]; + + /** Number of bytes that still need processing */ + size_t unprocessed_len; + + /** Current IV or NONCE_COUNTER for CTR-mode */ + unsigned char iv[POLARSSL_MAX_IV_LENGTH]; + + /** IV size in bytes (for ciphers with variable-length IVs) */ + size_t iv_size; + + /** Cipher-specific context */ + void *cipher_ctx; +} cipher_context_t; + +/** + * \brief Returns the list of ciphers supported by the generic cipher module. + * + * \return a statically allocated array of ciphers, the last entry + * is 0. + */ +const int *cipher_list( void ); + +/** + * \brief Returns the cipher information structure associated + * with the given cipher name. + * + * \param cipher_name Name of the cipher to search for. + * + * \return the cipher information structure associated with the + * given cipher_name, or NULL if not found. + */ +const cipher_info_t *cipher_info_from_string( const char *cipher_name ); + +/** + * \brief Returns the cipher information structure associated + * with the given cipher type. + * + * \param cipher_type Type of the cipher to search for. + * + * \return the cipher information structure associated with the + * given cipher_type, or NULL if not found. + */ +const cipher_info_t *cipher_info_from_type( const cipher_type_t cipher_type ); + +/** + * \brief Returns the cipher information structure associated + * with the given cipher id, key size and mode. + * + * \param cipher_id Id of the cipher to search for + * (e.g. POLARSSL_CIPHER_ID_AES) + * \param key_length Length of the key in bits + * \param mode Cipher mode (e.g. POLARSSL_MODE_CBC) + * + * \return the cipher information structure associated with the + * given cipher_type, or NULL if not found. + */ +const cipher_info_t *cipher_info_from_values( const cipher_id_t cipher_id, + int key_length, + const cipher_mode_t mode ); + +/** + * \brief Initialize a cipher_context (as NONE) + */ +void cipher_init( cipher_context_t *ctx ); + +/** + * \brief Free and clear the cipher-specific context of ctx. + * Freeing ctx itself remains the responsibility of the + * caller. + */ +void cipher_free( cipher_context_t *ctx ); + +/** + * \brief Initialises and fills the cipher context structure with + * the appropriate values. + * + * \note Currently also clears structure. In future versions you + * will be required to call cipher_init() on the structure + * first. + * + * \param ctx context to initialise. May not be NULL. + * \param cipher_info cipher to use. + * + * \return 0 on success, + * POLARSSL_ERR_CIPHER_BAD_INPUT_DATA on parameter failure, + * POLARSSL_ERR_CIPHER_ALLOC_FAILED if allocation of the + * cipher-specific context failed. + */ +int cipher_init_ctx( cipher_context_t *ctx, const cipher_info_t *cipher_info ); + +/** + * \brief Free the cipher-specific context of ctx. Freeing ctx + * itself remains the responsibility of the caller. + * + * \note Deprecated: Redirects to cipher_free() + * + * \param ctx Free the cipher-specific context + * + * \returns 0 + */ +int cipher_free_ctx( cipher_context_t *ctx ); + +/** + * \brief Returns the block size of the given cipher. + * + * \param ctx cipher's context. Must have been initialised. + * + * \return size of the cipher's blocks, or 0 if ctx has not been + * initialised. + */ +static inline unsigned int cipher_get_block_size( const cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return 0; + + return ctx->cipher_info->block_size; +} + +/** + * \brief Returns the mode of operation for the cipher. + * (e.g. POLARSSL_MODE_CBC) + * + * \param ctx cipher's context. Must have been initialised. + * + * \return mode of operation, or POLARSSL_MODE_NONE if ctx + * has not been initialised. + */ +static inline cipher_mode_t cipher_get_cipher_mode( const cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return POLARSSL_MODE_NONE; + + return ctx->cipher_info->mode; +} + +/** + * \brief Returns the size of the cipher's IV/NONCE in bytes. + * + * \param ctx cipher's context. Must have been initialised. + * + * \return If IV has not been set yet: (recommended) IV size + * (0 for ciphers not using IV/NONCE). + * If IV has already been set: actual size. + */ +static inline int cipher_get_iv_size( const cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return 0; + + if( ctx->iv_size != 0 ) + return (int) ctx->iv_size; + + return ctx->cipher_info->iv_size; +} + +/** + * \brief Returns the type of the given cipher. + * + * \param ctx cipher's context. Must have been initialised. + * + * \return type of the cipher, or POLARSSL_CIPHER_NONE if ctx has + * not been initialised. + */ +static inline cipher_type_t cipher_get_type( const cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return POLARSSL_CIPHER_NONE; + + return ctx->cipher_info->type; +} + +/** + * \brief Returns the name of the given cipher, as a string. + * + * \param ctx cipher's context. Must have been initialised. + * + * \return name of the cipher, or NULL if ctx was not initialised. + */ +static inline const char *cipher_get_name( const cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return 0; + + return ctx->cipher_info->name; +} + +/** + * \brief Returns the key length of the cipher. + * + * \param ctx cipher's context. Must have been initialised. + * + * \return cipher's key length, in bits, or + * POLARSSL_KEY_LENGTH_NONE if ctx has not been + * initialised. + */ +static inline int cipher_get_key_size ( const cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return POLARSSL_KEY_LENGTH_NONE; + + return ctx->cipher_info->key_length; +} + +/** + * \brief Returns the operation of the given cipher. + * + * \param ctx cipher's context. Must have been initialised. + * + * \return operation (POLARSSL_ENCRYPT or POLARSSL_DECRYPT), + * or POLARSSL_OPERATION_NONE if ctx has not been + * initialised. + */ +static inline operation_t cipher_get_operation( const cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return POLARSSL_OPERATION_NONE; + + return ctx->operation; +} + +/** + * \brief Set the key to use with the given context. + * + * \param ctx generic cipher context. May not be NULL. Must have been + * initialised using cipher_context_from_type or + * cipher_context_from_string. + * \param key The key to use. + * \param key_length key length to use, in bits. + * \param operation Operation that the key will be used for, either + * POLARSSL_ENCRYPT or POLARSSL_DECRYPT. + * + * \returns 0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA if + * parameter verification fails or a cipher specific + * error code. + */ +int cipher_setkey( cipher_context_t *ctx, const unsigned char *key, + int key_length, const operation_t operation ); + +#if defined(POLARSSL_CIPHER_MODE_WITH_PADDING) +/** + * \brief Set padding mode, for cipher modes that use padding. + * (Default: PKCS7 padding.) + * + * \param ctx generic cipher context + * \param mode padding mode + * + * \returns 0 on success, POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE + * if selected padding mode is not supported, or + * POLARSSL_ERR_CIPHER_BAD_INPUT_DATA if the cipher mode + * does not support padding. + */ +int cipher_set_padding_mode( cipher_context_t *ctx, cipher_padding_t mode ); +#endif /* POLARSSL_CIPHER_MODE_WITH_PADDING */ + +/** + * \brief Set the initialization vector (IV) or nonce + * + * \param ctx generic cipher context + * \param iv IV to use (or NONCE_COUNTER for CTR-mode ciphers) + * \param iv_len IV length for ciphers with variable-size IV; + * discarded by ciphers with fixed-size IV. + * + * \returns 0 on success, or POLARSSL_ERR_CIPHER_BAD_INPUT_DATA + * + * \note Some ciphers don't use IVs nor NONCE. For these + * ciphers, this function has no effect. + */ +int cipher_set_iv( cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len ); + +/** + * \brief Finish preparation of the given context + * + * \param ctx generic cipher context + * + * \returns 0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA + * if parameter verification fails. + */ +int cipher_reset( cipher_context_t *ctx ); + +#if defined(POLARSSL_GCM_C) +/** + * \brief Add additional data (for AEAD ciphers). + * Currently only supported with GCM. + * Must be called exactly once, after cipher_reset(). + * + * \param ctx generic cipher context + * \param ad Additional data to use. + * \param ad_len Length of ad. + * + * \return 0 on success, or a specific error code. + */ +int cipher_update_ad( cipher_context_t *ctx, + const unsigned char *ad, size_t ad_len ); +#endif /* POLARSSL_GCM_C */ + +/** + * \brief Generic cipher update function. Encrypts/decrypts + * using the given cipher context. Writes as many block + * size'd blocks of data as possible to output. Any data + * that cannot be written immediately will either be added + * to the next block, or flushed when cipher_final is + * called. + * Exception: for POLARSSL_MODE_ECB, expects single block + * in size (e.g. 16 bytes for AES) + * + * \param ctx generic cipher context + * \param input buffer holding the input data + * \param ilen length of the input data + * \param output buffer for the output data. Should be able to hold at + * least ilen + block_size. Cannot be the same buffer as + * input! + * \param olen length of the output data, will be filled with the + * actual number of bytes written. + * + * \returns 0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA if + * parameter verification fails, + * POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE on an + * unsupported mode for a cipher or a cipher specific + * error code. + * + * \note If the underlying cipher is GCM, all calls to this + * function, except the last one before cipher_finish(), + * must have ilen a multiple of the block size. + */ +int cipher_update( cipher_context_t *ctx, const unsigned char *input, + size_t ilen, unsigned char *output, size_t *olen ); + +/** + * \brief Generic cipher finalisation function. If data still + * needs to be flushed from an incomplete block, data + * contained within it will be padded with the size of + * the last block, and written to the output buffer. + * + * \param ctx Generic cipher context + * \param output buffer to write data to. Needs block_size available. + * \param olen length of the data written to the output buffer. + * + * \returns 0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA if + * parameter verification fails, + * POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED if decryption + * expected a full block but was not provided one, + * POLARSSL_ERR_CIPHER_INVALID_PADDING on invalid padding + * while decrypting or a cipher specific error code. + */ +int cipher_finish( cipher_context_t *ctx, + unsigned char *output, size_t *olen ); + +#if defined(POLARSSL_GCM_C) +/** + * \brief Write tag for AEAD ciphers. + * Currently only supported with GCM. + * Must be called after cipher_finish(). + * + * \param ctx Generic cipher context + * \param tag buffer to write the tag + * \param tag_len Length of the tag to write + * + * \return 0 on success, or a specific error code. + */ +int cipher_write_tag( cipher_context_t *ctx, + unsigned char *tag, size_t tag_len ); + +/** + * \brief Check tag for AEAD ciphers. + * Currently only supported with GCM. + * Must be called after cipher_finish(). + * + * \param ctx Generic cipher context + * \param tag Buffer holding the tag + * \param tag_len Length of the tag to check + * + * \return 0 on success, or a specific error code. + */ +int cipher_check_tag( cipher_context_t *ctx, + const unsigned char *tag, size_t tag_len ); +#endif /* POLARSSL_GCM_C */ + +/** + * \brief Generic all-in-one encryption/decryption + * (for all ciphers except AEAD constructs). + * + * \param ctx generic cipher context + * \param iv IV to use (or NONCE_COUNTER for CTR-mode ciphers) + * \param iv_len IV length for ciphers with variable-size IV; + * discarded by ciphers with fixed-size IV. + * \param input buffer holding the input data + * \param ilen length of the input data + * \param output buffer for the output data. Should be able to hold at + * least ilen + block_size. Cannot be the same buffer as + * input! + * \param olen length of the output data, will be filled with the + * actual number of bytes written. + * + * \note Some ciphers don't use IVs nor NONCE. For these + * ciphers, use iv = NULL and iv_len = 0. + * + * \returns 0 on success, or + * POLARSSL_ERR_CIPHER_BAD_INPUT_DATA, or + * POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED if decryption + * expected a full block but was not provided one, or + * POLARSSL_ERR_CIPHER_INVALID_PADDING on invalid padding + * while decrypting, or + * a cipher specific error code. + */ +int cipher_crypt( cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen ); + +#if defined(POLARSSL_CIPHER_MODE_AEAD) +/** + * \brief Generic autenticated encryption (AEAD ciphers). + * + * \param ctx generic cipher context + * \param iv IV to use (or NONCE_COUNTER for CTR-mode ciphers) + * \param iv_len IV length for ciphers with variable-size IV; + * discarded by ciphers with fixed-size IV. + * \param ad Additional data to authenticate. + * \param ad_len Length of ad. + * \param input buffer holding the input data + * \param ilen length of the input data + * \param output buffer for the output data. + * Should be able to hold at least ilen. + * \param olen length of the output data, will be filled with the + * actual number of bytes written. + * \param tag buffer for the authentication tag + * \param tag_len desired tag length + * + * \returns 0 on success, or + * POLARSSL_ERR_CIPHER_BAD_INPUT_DATA, or + * a cipher specific error code. + */ +int cipher_auth_encrypt( cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + unsigned char *tag, size_t tag_len ); + +/** + * \brief Generic autenticated decryption (AEAD ciphers). + * + * \param ctx generic cipher context + * \param iv IV to use (or NONCE_COUNTER for CTR-mode ciphers) + * \param iv_len IV length for ciphers with variable-size IV; + * discarded by ciphers with fixed-size IV. + * \param ad Additional data to be authenticated. + * \param ad_len Length of ad. + * \param input buffer holding the input data + * \param ilen length of the input data + * \param output buffer for the output data. + * Should be able to hold at least ilen. + * \param olen length of the output data, will be filled with the + * actual number of bytes written. + * \param tag buffer holding the authentication tag + * \param tag_len length of the authentication tag + * + * \returns 0 on success, or + * POLARSSL_ERR_CIPHER_BAD_INPUT_DATA, or + * POLARSSL_ERR_CIPHER_AUTH_FAILED if data isn't authentic, + * or a cipher specific error code. + * + * \note If the data is not authentic, then the output buffer + * is zeroed out to prevent the unauthentic plaintext to + * be used by mistake, making this interface safer. + */ +int cipher_auth_decrypt( cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + const unsigned char *tag, size_t tag_len ); +#endif /* POLARSSL_CIPHER_MODE_AEAD */ + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int cipher_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* POLARSSL_CIPHER_H */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/cipher_wrap.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/cipher_wrap.h new file mode 100644 index 0000000..46bc757 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/cipher_wrap.h @@ -0,0 +1,57 @@ +/** + * \file cipher_wrap.h + * + * \brief Cipher wrappers. + * + * \author Adriaan de Jong + * + * Copyright (C) 2006-2013, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_CIPHER_WRAP_H +#define POLARSSL_CIPHER_WRAP_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif +#include "cipher.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + cipher_type_t type; + const cipher_info_t *info; +} cipher_definition_t; + +extern const cipher_definition_t cipher_definitions[]; + +extern int supported_ciphers[]; + +#ifdef __cplusplus +} +#endif + +#endif /* POLARSSL_CIPHER_WRAP_H */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/compat-1.2.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/compat-1.2.h new file mode 100644 index 0000000..15b5aa1 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/compat-1.2.h @@ -0,0 +1,389 @@ +/** + * \file compat-1.2.h + * + * \brief Backwards compatibility header for PolarSSL-1.2 from PolarSSL-1.3 + * + * Copyright (C) 2006-2013, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_COMPAT_1_2_H +#define POLARSSL_COMPAT_1_2_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +// Comment out to disable prototype change warnings +#define SHOW_PROTOTYPE_CHANGE_WARNINGS + +#if defined(_MSC_VER) && !defined(inline) +#define inline _inline +#else +#if defined(__ARMCC_VERSION) && !defined(inline) +#define inline __inline +#endif /* __ARMCC_VERSION */ +#endif /* _MSC_VER */ + +#if defined(_MSC_VER) +// MSVC does not support #warning +#undef SHOW_PROTOTYPE_CHANGE_WARNINGS +#endif + +#if defined(SHOW_PROTOTYPE_CHANGE_WARNINGS) +#warning "You can disable these warnings by commenting SHOW_PROTOTYPE_CHANGE_WARNINGS in compat-1.2.h" +#endif + +#if defined(POLARSSL_SHA256_C) +#define POLARSSL_SHA2_C +#include "sha256.h" + +/* + * SHA-2 -> SHA-256 + */ +typedef sha256_context sha2_context; + +static inline void sha2_starts( sha256_context *ctx, int is224 ) { + sha256_starts( ctx, is224 ); +} +static inline void sha2_update( sha256_context *ctx, const unsigned char *input, + size_t ilen ) { + sha256_update( ctx, input, ilen ); +} +static inline void sha2_finish( sha256_context *ctx, unsigned char output[32] ) { + sha256_finish( ctx, output ); +} +static inline int sha2_file( const char *path, unsigned char output[32], int is224 ) { + return sha256_file( path, output, is224 ); +} +static inline void sha2( const unsigned char *input, size_t ilen, + unsigned char output[32], int is224 ) { + sha256( input, ilen, output, is224 ); +} +static inline void sha2_hmac_starts( sha256_context *ctx, const unsigned char *key, + size_t keylen, int is224 ) { + sha256_hmac_starts( ctx, key, keylen, is224 ); +} +static inline void sha2_hmac_update( sha256_context *ctx, const unsigned char *input, size_t ilen ) { + sha256_hmac_update( ctx, input, ilen ); +} +static inline void sha2_hmac_finish( sha256_context *ctx, unsigned char output[32] ) { + sha256_hmac_finish( ctx, output ); +} +static inline void sha2_hmac_reset( sha256_context *ctx ) { + sha256_hmac_reset( ctx ); +} +static inline void sha2_hmac( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char output[32], int is224 ) { + sha256_hmac( key, keylen, input, ilen, output, is224 ); +} +static inline int sha2_self_test( int verbose ) { + return sha256_self_test( verbose ); +} +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA512_C) +#define POLARSSL_SHA4_C +#include "sha512.h" + +/* + * SHA-4 -> SHA-512 + */ +typedef sha512_context sha4_context; + +static inline void sha4_starts( sha512_context *ctx, int is384 ) { + sha512_starts( ctx, is384 ); +} +static inline void sha4_update( sha512_context *ctx, const unsigned char *input, + size_t ilen ) { + sha512_update( ctx, input, ilen ); +} +static inline void sha4_finish( sha512_context *ctx, unsigned char output[64] ) { + sha512_finish( ctx, output ); +} +static inline int sha4_file( const char *path, unsigned char output[64], int is384 ) { + return sha512_file( path, output, is384 ); +} +static inline void sha4( const unsigned char *input, size_t ilen, + unsigned char output[32], int is384 ) { + sha512( input, ilen, output, is384 ); +} +static inline void sha4_hmac_starts( sha512_context *ctx, const unsigned char *key, + size_t keylen, int is384 ) { + sha512_hmac_starts( ctx, key, keylen, is384 ); +} +static inline void sha4_hmac_update( sha512_context *ctx, const unsigned char *input, size_t ilen ) { + sha512_hmac_update( ctx, input, ilen ); +} +static inline void sha4_hmac_finish( sha512_context *ctx, unsigned char output[64] ) { + sha512_hmac_finish( ctx, output ); +} +static inline void sha4_hmac_reset( sha512_context *ctx ) { + sha512_hmac_reset( ctx ); +} +static inline void sha4_hmac( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char output[64], int is384 ) { + sha512_hmac( key, keylen, input, ilen, output, is384 ); +} +static inline int sha4_self_test( int verbose ) { + return sha512_self_test( verbose ); +} +#endif /* POLARSSL_SHA512_C */ + +#if defined(POLARSSL_CIPHER_C) +#if defined(SHOW_PROTOTYPE_CHANGE_WARNINGS) +#warning "cipher_reset() prototype changed. Manual change required if used" +#endif +#endif + +#if defined(POLARSSL_RSA_C) +#define SIG_RSA_RAW POLARSSL_MD_NONE +#define SIG_RSA_MD2 POLARSSL_MD_MD2 +#define SIG_RSA_MD4 POLARSSL_MD_MD4 +#define SIG_RSA_MD5 POLARSSL_MD_MD5 +#define SIG_RSA_SHA1 POLARSSL_MD_SHA1 +#define SIG_RSA_SHA224 POLARSSL_MD_SHA224 +#define SIG_RSA_SHA256 POLARSSL_MD_SHA256 +#define SIG_RSA_SHA384 POLARSSL_MD_SHA384 +#define SIG_RSA_SHA512 POLARSSL_MD_SHA512 +#if defined(SHOW_PROTOTYPE_CHANGE_WARNINGS) +#warning "rsa_pkcs1_verify() prototype changed. Manual change required if used" +#warning "rsa_pkcs1_decrypt() prototype changed. Manual change required if used" +#endif +#endif /* POLARSSL_RSA_C */ + +#if defined(POLARSSL_DHM_C) +#if defined(SHOW_PROTOTYPE_CHANGE_WARNINGS) +#warning "dhm_calc_secret() prototype changed. Manual change required if used" +#endif +#endif + +#if defined(POLARSSL_GCM_C) +#if defined(SHOW_PROTOTYPE_CHANGE_WARNINGS) +#warning "gcm_init() prototype changed. Manual change required if used" +#endif +#endif + +#if defined(POLARSSL_SSL_CLI_C) +#if defined(SHOW_PROTOTYPE_CHANGE_WARNINGS) +#warning "ssl_set_own_cert() prototype changed. Change to ssl_set_own_cert_rsa(). Manual change required if used" +#endif +#endif + +#if defined(POLARSSL_X509_USE_C) || defined(POLARSSL_X509_CREATE_C) +#include "x509.h" + +#define POLARSSL_ERR_X509_CERT_INVALID_FORMAT POLARSSL_ERR_X509_INVALID_FORMAT +#define POLARSSL_ERR_X509_CERT_INVALID_VERSION POLARSSL_ERR_X509_INVALID_VERSION +#define POLARSSL_ERR_X509_CERT_INVALID_ALG POLARSSL_ERR_X509_INVALID_ALG +#define POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG POLARSSL_ERR_X509_UNKNOWN_SIG_ALG +#define POLARSSL_ERR_X509_CERT_INVALID_NAME POLARSSL_ERR_X509_INVALID_NAME +#define POLARSSL_ERR_X509_CERT_INVALID_DATE POLARSSL_ERR_X509_INVALID_DATE +#define POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS POLARSSL_ERR_X509_INVALID_EXTENSIONS +#define POLARSSL_ERR_X509_CERT_SIG_MISMATCH POLARSSL_ERR_X509_SIG_MISMATCH +#define POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE POLARSSL_ERR_X509_INVALID_SIGNATURE +#define POLARSSL_ERR_X509_CERT_INVALID_SERIAL POLARSSL_ERR_X509_INVALID_SERIAL +#define POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION POLARSSL_ERR_X509_UNKNOWN_VERSION + +static inline int x509parse_serial_gets( char *buf, size_t size, const x509_buf *serial ) { + return x509_serial_gets( buf, size, serial ); +} +static inline int x509parse_dn_gets( char *buf, size_t size, const x509_name *dn ) { + return x509_dn_gets( buf, size, dn ); +} +static inline int x509parse_time_expired( const x509_time *time ) { + return x509_time_expired( time ); +} +#endif /* POLARSSL_X509_USE_C || POLARSSL_X509_CREATE_C */ + +#if defined(POLARSSL_X509_CRT_PARSE_C) +#define POLARSSL_X509_PARSE_C +#include "x509_crt.h" +typedef x509_crt x509_cert; + +static inline int x509parse_crt_der( x509_cert *chain, const unsigned char *buf, + size_t buflen ) { + return x509_crt_parse_der( chain, buf, buflen ); +} +static inline int x509parse_crt( x509_cert *chain, const unsigned char *buf, size_t buflen ) { + return x509_crt_parse( chain, buf, buflen ); +} +static inline int x509parse_crtfile( x509_cert *chain, const char *path ) { + return x509_crt_parse_file( chain, path ); +} +static inline int x509parse_crtpath( x509_cert *chain, const char *path ) { + return x509_crt_parse_path( chain, path ); +} +static inline int x509parse_cert_info( char *buf, size_t size, const char *prefix, + const x509_cert *crt ) { + return x509_crt_info( buf, size, prefix, crt ); +} +static inline int x509parse_verify( x509_cert *crt, x509_cert *trust_ca, + x509_crl *ca_crl, const char *cn, int *flags, + int (*f_vrfy)(void *, x509_cert *, int, int *), + void *p_vrfy ) { + return x509_crt_verify( crt, trust_ca, ca_crl, cn, flags, f_vrfy, p_vrfy ); +} +static inline int x509parse_revoked( const x509_cert *crt, const x509_crl *crl ) { + return x509_crt_revoked( crt, crl ); +} +static inline void x509_free( x509_cert *crt ) { + x509_crt_free( crt ); +} +#endif /* POLARSSL_X509_CRT_PARSE_C */ + +#if defined(POLARSSL_X509_CRL_PARSE_C) +#define POLARSSL_X509_PARSE_C +#include "x509_crl.h" +static inline int x509parse_crl( x509_crl *chain, const unsigned char *buf, size_t buflen ) { + return x509_crl_parse( chain, buf, buflen ); +} +static inline int x509parse_crlfile( x509_crl *chain, const char *path ) { + return x509_crl_parse_file( chain, path ); +} +static inline int x509parse_crl_info( char *buf, size_t size, const char *prefix, + const x509_crl *crl ) { + return x509_crl_info( buf, size, prefix, crl ); +} +#endif /* POLARSSL_X509_CRL_PARSE_C */ + +#if defined(POLARSSL_X509_CSR_PARSE_C) +#define POLARSSL_X509_PARSE_C +#include "x509_csr.h" +static inline int x509parse_csr( x509_csr *csr, const unsigned char *buf, size_t buflen ) { + return x509_csr_parse( csr, buf, buflen ); +} +static inline int x509parse_csrfile( x509_csr *csr, const char *path ) { + return x509_csr_parse_file( csr, path ); +} +static inline int x509parse_csr_info( char *buf, size_t size, const char *prefix, + const x509_csr *csr ) { + return x509_csr_info( buf, size, prefix, csr ); +} +#endif /* POLARSSL_X509_CSR_PARSE_C */ + +#if defined(POLARSSL_SSL_TLS_C) +#include "ssl_ciphersuites.h" + +#define ssl_default_ciphersuites ssl_list_ciphersuites() +#endif + +#if defined(POLARSSL_PK_PARSE_C) && defined(POLARSSL_RSA_C) +#include "rsa.h" +#include "pk.h" + +#define POLARSSL_ERR_X509_PASSWORD_MISMATCH POLARSSL_ERR_PK_PASSWORD_MISMATCH +#define POLARSSL_ERR_X509_KEY_INVALID_FORMAT POLARSSL_ERR_PK_KEY_INVALID_FORMAT +#define POLARSSL_ERR_X509_UNKNOWN_PK_ALG POLARSSL_ERR_PK_UNKNOWN_PK_ALG +#define POLARSSL_ERR_X509_CERT_INVALID_PUBKEY POLARSSL_ERR_PK_INVALID_PUBKEY + +#if defined(POLARSSL_FS_IO) +static inline int x509parse_keyfile( rsa_context *rsa, const char *path, + const char *pwd ) { + int ret; + pk_context pk; + pk_init( &pk ); + ret = pk_parse_keyfile( &pk, path, pwd ); + if( ret == 0 && ! pk_can_do( &pk, POLARSSL_PK_RSA ) ) + ret = POLARSSL_ERR_PK_TYPE_MISMATCH; + if( ret == 0 ) + rsa_copy( rsa, pk_rsa( pk ) ); + else + rsa_free( rsa ); + pk_free( &pk ); + return( ret ); +} +static inline int x509parse_public_keyfile( rsa_context *rsa, const char *path ) { + int ret; + pk_context pk; + pk_init( &pk ); + ret = pk_parse_public_keyfile( &pk, path ); + if( ret == 0 && ! pk_can_do( &pk, POLARSSL_PK_RSA ) ) + ret = POLARSSL_ERR_PK_TYPE_MISMATCH; + if( ret == 0 ) + rsa_copy( rsa, pk_rsa( pk ) ); + else + rsa_free( rsa ); + pk_free( &pk ); + return( ret ); +} +#endif /* POLARSSL_FS_IO */ + +static inline int x509parse_key( rsa_context *rsa, const unsigned char *key, + size_t keylen, + const unsigned char *pwd, size_t pwdlen ) { + int ret; + pk_context pk; + pk_init( &pk ); + ret = pk_parse_key( &pk, key, keylen, pwd, pwdlen ); + if( ret == 0 && ! pk_can_do( &pk, POLARSSL_PK_RSA ) ) + ret = POLARSSL_ERR_PK_TYPE_MISMATCH; + if( ret == 0 ) + rsa_copy( rsa, pk_rsa( pk ) ); + else + rsa_free( rsa ); + pk_free( &pk ); + return( ret ); +} + +static inline int x509parse_public_key( rsa_context *rsa, + const unsigned char *key, size_t keylen ) +{ + int ret; + pk_context pk; + pk_init( &pk ); + ret = pk_parse_public_key( &pk, key, keylen ); + if( ret == 0 && ! pk_can_do( &pk, POLARSSL_PK_RSA ) ) + ret = POLARSSL_ERR_PK_TYPE_MISMATCH; + if( ret == 0 ) + rsa_copy( rsa, pk_rsa( pk ) ); + else + rsa_free( rsa ); + pk_free( &pk ); + return( ret ); +} +#endif /* POLARSSL_PK_PARSE_C && POLARSSL_RSA_C */ + +#if defined(POLARSSL_PK_WRITE_C) && defined(POLARSSL_RSA_C) +#include "pk.h" +static inline int x509_write_pubkey_der( unsigned char *buf, size_t len, rsa_context *rsa ) { + int ret; + pk_context ctx; + if( ( ret = pk_init_ctx( &ctx, pk_info_from_type( POLARSSL_PK_RSA ) ) ) != 0 ) return( ret ); + if( ( ret = rsa_copy( pk_rsa( ctx ), rsa ) ) != 0 ) return( ret ); + ret = pk_write_pubkey_der( &ctx, buf, len ); + pk_free( &ctx ); + return( ret ); +} +static inline int x509_write_key_der( unsigned char *buf, size_t len, rsa_context *rsa ) { + int ret; + pk_context ctx; + if( ( ret = pk_init_ctx( &ctx, pk_info_from_type( POLARSSL_PK_RSA ) ) ) != 0 ) return( ret ); + if( ( ret = rsa_copy( pk_rsa( ctx ), rsa ) ) != 0 ) return( ret ); + ret = pk_write_key_der( &ctx, buf, len ); + pk_free( &ctx ); + return( ret ); +} +#endif /* POLARSSL_PK_WRITE_C && POLARSSL_RSA_C */ +#endif /* compat-1.2.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/config.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/config.h new file mode 100644 index 0000000..99c1dc8 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/config.h @@ -0,0 +1,14 @@ +#define CONFIG_SSL_RSA 1 +#define CONFIG_SSL_SRP 0 +#define POLARSSL_PEM_PARSE_C 1 +#define POLARSSL_BASE64_C 1 + +#include "platform_stdlib.h" + +#if CONFIG_SSL_RSA +#include "polarssl/config_rsa.h" +#elif CONFIG_SSL_SRP +#include "polarssl/config_srp.h" +#else +#include "polarssl/config_all.h" +#endif diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/config_all.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/config_all.h new file mode 100644 index 0000000..d43365f --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/config_all.h @@ -0,0 +1,2180 @@ +/** + * \file config.h + * + * \brief Configuration options (set of defines) + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * This set of compile-time options may be used to enable + * or disable features selectively, and reduce the global + * memory footprint. + */ +#ifndef POLARSSL_CONFIG_H +#define POLARSSL_CONFIG_H + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif + +/** + * \name SECTION: System support + * + * This section sets system specific settings. + * \{ + */ + +/** + * \def POLARSSL_HAVE_INT8 + * + * The system uses 8-bit wide native integers. + * + * Uncomment if native integers are 8-bit wide. + */ +//#define POLARSSL_HAVE_INT8 + +/** + * \def POLARSSL_HAVE_INT16 + * + * The system uses 16-bit wide native integers. + * + * Uncomment if native integers are 16-bit wide. + */ +//#define POLARSSL_HAVE_INT16 + +/** + * \def POLARSSL_HAVE_LONGLONG + * + * The compiler supports the 'long long' type. + * (Only used on 32-bit platforms) + */ +#define POLARSSL_HAVE_LONGLONG + +/** + * \def POLARSSL_HAVE_ASM + * + * The compiler has support for asm(). + * + * Requires support for asm() in compiler. + * + * Used in: + * library/timing.c + * library/padlock.c + * include/polarssl/bn_mul.h + * + * Comment to disable the use of assembly code. + */ +#define POLARSSL_HAVE_ASM + +/** + * \def POLARSSL_HAVE_SSE2 + * + * CPU supports SSE2 instruction set. + * + * Uncomment if the CPU supports SSE2 (IA-32 specific). + */ +//#define POLARSSL_HAVE_SSE2 + +/** + * \def POLARSSL_HAVE_TIME + * + * System has time.h and time() / localtime() / gettimeofday(). + * + * Comment if your system does not support time functions + */ +#define POLARSSL_HAVE_TIME + +/** + * \def POLARSSL_HAVE_IPV6 + * + * System supports the basic socket interface for IPv6 (RFC 3493), + * specifically getaddrinfo(), freeaddrinfo() and struct sockaddr_storage. + * + * Note: on Windows/MingW, XP or higher is required. + * + * Comment if your system does not support the IPv6 socket interface + */ +#define POLARSSL_HAVE_IPV6 + +/** + * \def POLARSSL_PLATFORM_MEMORY + * + * Enable the memory allocation layer. + * + * By default PolarSSL uses the system-provided malloc() and free(). + * This allows different allocators (self-implemented or provided) to be + * provided to the platform abstraction layer. + * + * Enabling POLARSSL_PLATFORM_MEMORY will provide "platform_set_malloc_free()" + * to allow you to set an alternative malloc() and free() function pointer. + * + * Requires: POLARSSL_PLATFORM_C + * + * Enable this layer to allow use of alternative memory allocators. + */ +//#define POLARSSL_PLATFORM_MEMORY + +/** + * \def POLARSSL_PLATFORM_NO_STD_FUNCTIONS + * + * Do not assign standard functions in the platform layer (e.g. malloc() to + * POLARSSL_PLATFORM_STD_MALLOC and printf() to POLARSSL_PLATFORM_STD_PRINTF) + * + * This makes sure there are no linking errors on platforms that do not support + * these functions. You will HAVE to provide alternatives, either at runtime + * via the platform_set_xxx() functions or at compile time by setting + * the POLARSSL_PLATFORM_STD_XXX defines. + * + * Requires: POLARSSL_PLATFORM_C + * + * Uncomment to prevent default assignment of standard functions in the + * platform layer. + */ +//#define POLARSSL_PLATFORM_NO_STD_FUNCTIONS + +/** + * \def POLARSSL_PLATFORM_XXX_ALT + * + * Uncomment a macro to let PolarSSL support the function in the platform + * abstraction layer. + * + * Example: In case you uncomment POLARSSL_PLATFORM_PRINTF_ALT, PolarSSL will + * provide a function "platform_set_printf()" that allows you to set an + * alternative printf function pointer. + * + * All these define require POLARSSL_PLATFORM_C to be defined! + * + * Uncomment a macro to enable alternate implementation of specific base + * platform function + */ +//#define POLARSSL_PLATFORM_PRINTF_ALT +//#define POLARSSL_PLATFORM_FPRINTF_ALT +/* \} name SECTION: System support */ + +/** + * \name SECTION: PolarSSL feature support + * + * This section sets support for features that are or are not needed + * within the modules that are enabled. + * \{ + */ + +/** + * \def POLARSSL_TIMING_ALT + * + * Uncomment to provide your own alternate implementation for hardclock(), + * get_timer(), set_alarm() and m_sleep(). + * + * Only works if you have POLARSSL_TIMING_C enabled. + * + * You will need to provide a header "timing_alt.h" and an implementation at + * compile time. + */ +//#define POLARSSL_TIMING_ALT + +/** + * \def POLARSSL_XXX_ALT + * + * Uncomment a macro to let PolarSSL use your alternate core implementation of + * a symmetric or hash algorithm (e.g. platform specific assembly optimized + * implementations). Keep in mind that the function prototypes should remain + * the same. + * + * Example: In case you uncomment POLARSSL_AES_ALT, PolarSSL will no longer + * provide the "struct aes_context" definition and omit the base function + * declarations and implementations. "aes_alt.h" will be included from + * "aes.h" to include the new function definitions. + * + * Uncomment a macro to enable alternate implementation for core algorithm + * functions + */ +//#define POLARSSL_AES_ALT +//#define POLARSSL_ARC4_ALT +//#define POLARSSL_BLOWFISH_ALT +//#define POLARSSL_CAMELLIA_ALT +//#define POLARSSL_DES_ALT +//#define POLARSSL_XTEA_ALT +//#define POLARSSL_MD2_ALT +//#define POLARSSL_MD4_ALT +//#define POLARSSL_MD5_ALT +//#define POLARSSL_RIPEMD160_ALT +//#define POLARSSL_SHA1_ALT +//#define POLARSSL_SHA256_ALT +//#define POLARSSL_SHA512_ALT + +/** + * \def POLARSSL_AES_ROM_TABLES + * + * Store the AES tables in ROM. + * + * Uncomment this macro to store the AES tables in ROM. + * + */ +//#define POLARSSL_AES_ROM_TABLES + +/** + * \def POLARSSL_CIPHER_MODE_CBC + * + * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers. + */ +#define POLARSSL_CIPHER_MODE_CBC + +/** + * \def POLARSSL_CIPHER_MODE_CFB + * + * Enable Cipher Feedback mode (CFB) for symmetric ciphers. + */ +#define POLARSSL_CIPHER_MODE_CFB + +/** + * \def POLARSSL_CIPHER_MODE_CTR + * + * Enable Counter Block Cipher mode (CTR) for symmetric ciphers. + */ +#define POLARSSL_CIPHER_MODE_CTR + +/** + * \def POLARSSL_CIPHER_NULL_CIPHER + * + * Enable NULL cipher. + * Warning: Only do so when you know what you are doing. This allows for + * encryption or channels without any security! + * + * Requires POLARSSL_ENABLE_WEAK_CIPHERSUITES as well to enable + * the following ciphersuites: + * TLS_ECDH_ECDSA_WITH_NULL_SHA + * TLS_ECDH_RSA_WITH_NULL_SHA + * TLS_ECDHE_ECDSA_WITH_NULL_SHA + * TLS_ECDHE_RSA_WITH_NULL_SHA + * TLS_ECDHE_PSK_WITH_NULL_SHA384 + * TLS_ECDHE_PSK_WITH_NULL_SHA256 + * TLS_ECDHE_PSK_WITH_NULL_SHA + * TLS_DHE_PSK_WITH_NULL_SHA384 + * TLS_DHE_PSK_WITH_NULL_SHA256 + * TLS_DHE_PSK_WITH_NULL_SHA + * TLS_RSA_WITH_NULL_SHA256 + * TLS_RSA_WITH_NULL_SHA + * TLS_RSA_WITH_NULL_MD5 + * TLS_RSA_PSK_WITH_NULL_SHA384 + * TLS_RSA_PSK_WITH_NULL_SHA256 + * TLS_RSA_PSK_WITH_NULL_SHA + * TLS_PSK_WITH_NULL_SHA384 + * TLS_PSK_WITH_NULL_SHA256 + * TLS_PSK_WITH_NULL_SHA + * + * Uncomment this macro to enable the NULL cipher and ciphersuites + */ +//#define POLARSSL_CIPHER_NULL_CIPHER + +/** + * \def POLARSSL_CIPHER_PADDING_XXX + * + * Uncomment or comment macros to add support for specific padding modes + * in the cipher layer with cipher modes that support padding (e.g. CBC) + * + * If you disable all padding modes, only full blocks can be used with CBC. + * + * Enable padding modes in the cipher layer. + */ +#define POLARSSL_CIPHER_PADDING_PKCS7 +#define POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS +#define POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN +#define POLARSSL_CIPHER_PADDING_ZEROS + +/** + * \def POLARSSL_ENABLE_WEAK_CIPHERSUITES + * + * Enable weak ciphersuites in SSL / TLS. + * Warning: Only do so when you know what you are doing. This allows for + * channels with virtually no security at all! + * + * This enables the following ciphersuites: + * TLS_RSA_WITH_DES_CBC_SHA + * TLS_DHE_RSA_WITH_DES_CBC_SHA + * + * Uncomment this macro to enable weak ciphersuites + */ +//#define POLARSSL_ENABLE_WEAK_CIPHERSUITES + +/** + * \def POLARSSL_REMOVE_ARC4_CIPHERSUITES + * + * Remove RC4 ciphersuites by default in SSL / TLS. + * This flag removes the ciphersuites based on RC4 from the default list as + * returned by ssl_list_ciphersuites(). However, it is still possible to + * enable (some of) them with ssl_set_ciphersuites() by including them + * explicitly. + * + * Uncomment this macro to remove RC4 ciphersuites by default. + */ +//#define POLARSSL_REMOVE_ARC4_CIPHERSUITES + +/** + * \def POLARSSL_ECP_XXXX_ENABLED + * + * Enables specific curves within the Elliptic Curve module. + * By default all supported curves are enabled. + * + * Comment macros to disable the curve and functions for it + */ +#define POLARSSL_ECP_DP_SECP192R1_ENABLED +#define POLARSSL_ECP_DP_SECP224R1_ENABLED +#define POLARSSL_ECP_DP_SECP256R1_ENABLED +#define POLARSSL_ECP_DP_SECP384R1_ENABLED +#define POLARSSL_ECP_DP_SECP521R1_ENABLED +#define POLARSSL_ECP_DP_SECP192K1_ENABLED +#define POLARSSL_ECP_DP_SECP224K1_ENABLED +#define POLARSSL_ECP_DP_SECP256K1_ENABLED +#define POLARSSL_ECP_DP_BP256R1_ENABLED +#define POLARSSL_ECP_DP_BP384R1_ENABLED +#define POLARSSL_ECP_DP_BP512R1_ENABLED +//#define POLARSSL_ECP_DP_M221_ENABLED // Not implemented yet! +#define POLARSSL_ECP_DP_M255_ENABLED +//#define POLARSSL_ECP_DP_M383_ENABLED // Not implemented yet! +//#define POLARSSL_ECP_DP_M511_ENABLED // Not implemented yet! + +/** + * \def POLARSSL_ECP_NIST_OPTIM + * + * Enable specific 'modulo p' routines for each NIST prime. + * Depending on the prime and architecture, makes operations 4 to 8 times + * faster on the corresponding curve. + * + * Comment this macro to disable NIST curves optimisation. + */ +#define POLARSSL_ECP_NIST_OPTIM + +/** + * \def POLARSSL_ECDSA_DETERMINISTIC + * + * Enable deterministic ECDSA (RFC 6979). + * Standard ECDSA is "fragile" in the sense that lack of entropy when signing + * may result in a compromise of the long-term signing key. This is avoided by + * the deterministic variant. + * + * Requires: POLARSSL_HMAC_DRBG_C + * + * Comment this macro to disable deterministic ECDSA. + */ +#define POLARSSL_ECDSA_DETERMINISTIC + +/** + * \def POLARSSL_KEY_EXCHANGE_PSK_ENABLED + * + * Enable the PSK based ciphersuite modes in SSL / TLS. + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_PSK_WITH_AES_256_GCM_SHA384 + * TLS_PSK_WITH_AES_256_CBC_SHA384 + * TLS_PSK_WITH_AES_256_CBC_SHA + * TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_PSK_WITH_AES_128_GCM_SHA256 + * TLS_PSK_WITH_AES_128_CBC_SHA256 + * TLS_PSK_WITH_AES_128_CBC_SHA + * TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_PSK_WITH_3DES_EDE_CBC_SHA + * TLS_PSK_WITH_RC4_128_SHA + */ +#define POLARSSL_KEY_EXCHANGE_PSK_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED + * + * Enable the DHE-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_DHM_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA + * TLS_DHE_PSK_WITH_RC4_128_SHA + */ +#define POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED + * + * Enable the ECDHE-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_ECDH_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA + * TLS_ECDHE_PSK_WITH_RC4_128_SHA + */ +#define POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED + * + * Enable the RSA-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_RSA_C, POLARSSL_PKCS1_V15, + * POLARSSL_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA + * TLS_RSA_PSK_WITH_RC4_128_SHA + */ +#define POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_RSA_ENABLED + * + * Enable the RSA-only based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_RSA_C, POLARSSL_PKCS1_V15, + * POLARSSL_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_RSA_WITH_AES_256_GCM_SHA384 + * TLS_RSA_WITH_AES_256_CBC_SHA256 + * TLS_RSA_WITH_AES_256_CBC_SHA + * TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * TLS_RSA_WITH_AES_128_GCM_SHA256 + * TLS_RSA_WITH_AES_128_CBC_SHA256 + * TLS_RSA_WITH_AES_128_CBC_SHA + * TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * TLS_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_RSA_WITH_RC4_128_SHA + * TLS_RSA_WITH_RC4_128_MD5 + */ +#define POLARSSL_KEY_EXCHANGE_RSA_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED + * + * Enable the DHE-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_DHM_C, POLARSSL_RSA_C, POLARSSL_PKCS1_V15, + * POLARSSL_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + * TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + */ +#define POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED + * + * Enable the ECDHE-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_ECDH_C, POLARSSL_RSA_C, POLARSSL_PKCS1_V15, + * POLARSSL_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + * TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + * TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + * TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + * TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + * TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_ECDHE_RSA_WITH_RC4_128_SHA + */ +#define POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + * + * Enable the ECDHE-ECDSA based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_ECDH_C, POLARSSL_ECDSA_C, POLARSSL_X509_CRT_PARSE_C, + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + * TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + * TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + * TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + */ +#define POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED + * + * Enable the ECDH-ECDSA based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_ECDH_C, POLARSSL_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDH_ECDSA_WITH_RC4_128_SHA + * TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + * TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + * TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + * TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + * TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + * TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + * TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + * TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + */ +#define POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED + * + * Enable the ECDH-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_ECDH_C, POLARSSL_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDH_RSA_WITH_RC4_128_SHA + * TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + * TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + * TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + * TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + * TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + * TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + * TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 + */ +#define POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED + +/** + * \def POLARSSL_PK_PARSE_EC_EXTENDED + * + * Enhance support for reading EC keys using variants of SEC1 not allowed by + * RFC 5915 and RFC 5480. + * + * Currently this means parsing the SpecifiedECDomain choice of EC + * parameters (only known groups are supported, not arbitrary domains, to + * avoid validation issues). + * + * Disable if you only need to support RFC 5915 + 5480 key formats. + */ +#define POLARSSL_PK_PARSE_EC_EXTENDED + +/** + * \def POLARSSL_ERROR_STRERROR_BC + * + * Make available the backward compatible error_strerror() next to the + * current polarssl_strerror(). + * + * For new code, it is recommended to use polarssl_strerror() instead and + * disable this. + * + * Disable if you run into name conflicts and want to really remove the + * error_strerror() + */ +#define POLARSSL_ERROR_STRERROR_BC + +/** + * \def POLARSSL_ERROR_STRERROR_DUMMY + * + * Enable a dummy error function to make use of polarssl_strerror() in + * third party libraries easier when POLARSSL_ERROR_C is disabled + * (no effect when POLARSSL_ERROR_C is enabled). + * + * You can safely disable this if POLARSSL_ERROR_C is enabled, or if you're + * not using polarssl_strerror() or error_strerror() in your application. + * + * Disable if you run into name conflicts and want to really remove the + * polarssl_strerror() + */ +#define POLARSSL_ERROR_STRERROR_DUMMY + +/** + * \def POLARSSL_GENPRIME + * + * Enable the prime-number generation code. + * + * Requires: POLARSSL_BIGNUM_C + */ +#define POLARSSL_GENPRIME + +/** + * \def POLARSSL_FS_IO + * + * Enable functions that use the filesystem. + */ +#define POLARSSL_FS_IO + +/** + * \def POLARSSL_NO_DEFAULT_ENTROPY_SOURCES + * + * Do not add default entropy sources. These are the platform specific, + * hardclock and HAVEGE based poll functions. + * + * This is useful to have more control over the added entropy sources in an + * application. + * + * Uncomment this macro to prevent loading of default entropy functions. + */ +//#define POLARSSL_NO_DEFAULT_ENTROPY_SOURCES + +/** + * \def POLARSSL_NO_PLATFORM_ENTROPY + * + * Do not use built-in platform entropy functions. + * This is useful if your platform does not support + * standards like the /dev/urandom or Windows CryptoAPI. + * + * Uncomment this macro to disable the built-in platform entropy functions. + */ +//#define POLARSSL_NO_PLATFORM_ENTROPY + +/** + * \def POLARSSL_ENTROPY_FORCE_SHA256 + * + * Force the entropy accumulator to use a SHA-256 accumulator instead of the + * default SHA-512 based one (if both are available). + * + * Requires: POLARSSL_SHA256_C + * + * On 32-bit systems SHA-256 can be much faster than SHA-512. Use this option + * if you have performance concerns. + * + * This option is only useful if both POLARSSL_SHA256_C and + * POLARSSL_SHA512_C are defined. Otherwise the available hash module is used. + */ +//#define POLARSSL_ENTROPY_FORCE_SHA256 + +/** + * \def POLARSSL_MEMORY_DEBUG + * + * Enable debugging of buffer allocator memory issues. Automatically prints + * (to stderr) all (fatal) messages on memory allocation issues. Enables + * function for 'debug output' of allocated memory. + * + * Requires: POLARSSL_MEMORY_BUFFER_ALLOC_C + * + * Uncomment this macro to let the buffer allocator print out error messages. + */ +//#define POLARSSL_MEMORY_DEBUG + +/** + * \def POLARSSL_MEMORY_BACKTRACE + * + * Include backtrace information with each allocated block. + * + * Requires: POLARSSL_MEMORY_BUFFER_ALLOC_C + * GLIBC-compatible backtrace() an backtrace_symbols() support + * + * Uncomment this macro to include backtrace information + */ +//#define POLARSSL_MEMORY_BACKTRACE + +/** + * \def POLARSSL_PKCS1_V15 + * + * Enable support for PKCS#1 v1.5 encoding. + * + * Requires: POLARSSL_RSA_C + * + * This enables support for PKCS#1 v1.5 operations. + */ +#define POLARSSL_PKCS1_V15 + +/** + * \def POLARSSL_PKCS1_V21 + * + * Enable support for PKCS#1 v2.1 encoding. + * + * Requires: POLARSSL_MD_C, POLARSSL_RSA_C + * + * This enables support for RSAES-OAEP and RSASSA-PSS operations. + */ +#define POLARSSL_PKCS1_V21 + +/** + * \def POLARSSL_RSA_NO_CRT + * + * Do not use the Chinese Remainder Theorem for the RSA private operation. + * + * Uncomment this macro to disable the use of CRT in RSA. + * + */ +//#define POLARSSL_RSA_NO_CRT + +/** + * \def POLARSSL_SELF_TEST + * + * Enable the checkup functions (*_self_test). + */ +#define POLARSSL_SELF_TEST + +/** + * \def POLARSSL_SSL_ALL_ALERT_MESSAGES + * + * Enable sending of alert messages in case of encountered errors as per RFC. + * If you choose not to send the alert messages, PolarSSL can still communicate + * with other servers, only debugging of failures is harder. + * + * The advantage of not sending alert messages, is that no information is given + * about reasons for failures thus preventing adversaries of gaining intel. + * + * Enable sending of all alert messages + */ +#define POLARSSL_SSL_ALERT_MESSAGES + +/** + * \def POLARSSL_SSL_DEBUG_ALL + * + * Enable the debug messages in SSL module for all issues. + * Debug messages have been disabled in some places to prevent timing + * attacks due to (unbalanced) debugging function calls. + * + * If you need all error reporting you should enable this during debugging, + * but remove this for production servers that should log as well. + * + * Uncomment this macro to report all debug messages on errors introducing + * a timing side-channel. + * + */ +//#define POLARSSL_SSL_DEBUG_ALL + +/** + * \def POLARSSL_SSL_HW_RECORD_ACCEL + * + * Enable hooking functions in SSL module for hardware acceleration of + * individual records. + * + * Uncomment this macro to enable hooking functions. + */ +//#define POLARSSL_SSL_HW_RECORD_ACCEL + +/** + * \def POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO + * + * Enable support for receiving and parsing SSLv2 Client Hello messages for the + * SSL Server module (POLARSSL_SSL_SRV_C). + * + * Comment this macro to disable support for SSLv2 Client Hello messages. + */ +#define POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO + +/** + * \def POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE + * + * Pick the ciphersuite according to the client's preferences rather than ours + * in the SSL Server module (POLARSSL_SSL_SRV_C). + * + * Uncomment this macro to respect client's ciphersuite order + */ +//#define POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE + +/** + * \def POLARSSL_SSL_MAX_FRAGMENT_LENGTH + * + * Enable support for RFC 6066 max_fragment_length extension in SSL. + * + * Comment this macro to disable support for the max_fragment_length extension + */ +#define POLARSSL_SSL_MAX_FRAGMENT_LENGTH + +/** + * \def POLARSSL_SSL_PROTO_SSL3 + * + * Enable support for SSL 3.0. + * + * Requires: POLARSSL_MD5_C + * POLARSSL_SHA1_C + * + * Comment this macro to disable support for SSL 3.0 + */ +#define POLARSSL_SSL_PROTO_SSL3 + +/** + * \def POLARSSL_SSL_PROTO_TLS1 + * + * Enable support for TLS 1.0. + * + * Requires: POLARSSL_MD5_C + * POLARSSL_SHA1_C + * + * Comment this macro to disable support for TLS 1.0 + */ +#define POLARSSL_SSL_PROTO_TLS1 + +/** + * \def POLARSSL_SSL_PROTO_TLS1_1 + * + * Enable support for TLS 1.1. + * + * Requires: POLARSSL_MD5_C + * POLARSSL_SHA1_C + * + * Comment this macro to disable support for TLS 1.1 + */ +#define POLARSSL_SSL_PROTO_TLS1_1 + +/** + * \def POLARSSL_SSL_PROTO_TLS1_2 + * + * Enable support for TLS 1.2. + * + * Requires: POLARSSL_SHA1_C or POLARSSL_SHA256_C or POLARSSL_SHA512_C + * (Depends on ciphersuites) + * + * Comment this macro to disable support for TLS 1.2 + */ +#define POLARSSL_SSL_PROTO_TLS1_2 + +/** + * \def POLARSSL_SSL_ALPN + * + * Enable support for Application Layer Protocol Negotiation. + * draft-ietf-tls-applayerprotoneg-05 + * + * Comment this macro to disable support for ALPN. + */ +#define POLARSSL_SSL_ALPN + +/** + * \def POLARSSL_SSL_SESSION_TICKETS + * + * Enable support for RFC 5077 session tickets in SSL. + * + * Requires: POLARSSL_AES_C + * POLARSSL_SHA256_C + * POLARSSL_CIPHER_MODE_CBC + * + * Comment this macro to disable support for SSL session tickets + */ +#define POLARSSL_SSL_SESSION_TICKETS + +/** + * \def POLARSSL_SSL_SERVER_NAME_INDICATION + * + * Enable support for RFC 6066 server name indication (SNI) in SSL. + * + * Comment this macro to disable support for server name indication in SSL + */ +#define POLARSSL_SSL_SERVER_NAME_INDICATION + +/** + * \def POLARSSL_SSL_TRUNCATED_HMAC + * + * Enable support for RFC 6066 truncated HMAC in SSL. + * + * Comment this macro to disable support for truncated HMAC in SSL + */ +#define POLARSSL_SSL_TRUNCATED_HMAC + +/** + * \def POLARSSL_SSL_SET_CURVES + * + * Enable ssl_set_curves(). + * + * This is disabled by default since it breaks binary compatibility with the + * 1.3.x line. If you choose to enable it, you will need to rebuild your + * application against the new header files, relinking will not be enough. + * It will be enabled by default, or no longer an option, in the 1.4 branch. + * + * Uncomment to make ssl_set_curves() available. + */ +//#define POLARSSL_SSL_SET_CURVES + +/** + * \def POLARSSL_THREADING_ALT + * + * Provide your own alternate threading implementation. + * + * Requires: POLARSSL_THREADING_C + * + * Uncomment this to allow your own alternate threading implementation. + */ +//#define POLARSSL_THREADING_ALT + +/** + * \def POLARSSL_THREADING_PTHREAD + * + * Enable the pthread wrapper layer for the threading layer. + * + * Requires: POLARSSL_THREADING_C + * + * Uncomment this to enable pthread mutexes. + */ +//#define POLARSSL_THREADING_PTHREAD + +/** + * \def POLARSSL_VERSION_FEATURES + * + * Allow run-time checking of compile-time enabled features. Thus allowing users + * to check at run-time if the library is for instance compiled with threading + * support via version_check_feature(). + * + * Requires: POLARSSL_VERSION_C + * + * Comment this to disable run-time checking and save ROM space + */ +#define POLARSSL_VERSION_FEATURES + +/** + * \def POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3 + * + * If set, the X509 parser will not break-off when parsing an X509 certificate + * and encountering an extension in a v1 or v2 certificate. + * + * Uncomment to prevent an error. + */ +//#define POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3 + +/** + * \def POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + * + * If set, the X509 parser will not break-off when parsing an X509 certificate + * and encountering an unknown critical extension. + * + * Uncomment to prevent an error. + */ +//#define POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + +/** + * \def POLARSSL_X509_CHECK_KEY_USAGE + * + * Enable verification of the keyUsage extension (CA and leaf certificates). + * + * Disabling this avoids problems with mis-issued and/or misused + * (intermediate) CA and leaf certificates. + * + * \warning Depending on your PKI use, disabling this can be a security risk! + * + * Comment to skip keyUsage checking for both CA and leaf certificates. + */ +#define POLARSSL_X509_CHECK_KEY_USAGE + +/** + * \def POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE + * + * Enable verification of the extendedKeyUsage extension (leaf certificates). + * + * Disabling this avoids problems with mis-issued and/or misused certificates. + * + * \warning Depending on your PKI use, disabling this can be a security risk! + * + * Comment to skip extendedKeyUsage checking for certificates. + */ +#define POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE + +/** + * \def POLARSSL_X509_RSASSA_PSS_SUPPORT + * + * Enable parsing and verification of X.509 certificates, CRLs and CSRS + * signed with RSASSA-PSS (aka PKCS#1 v2.1). + * + * Comment this macro to disallow using RSASSA-PSS in certificates. + */ +#define POLARSSL_X509_RSASSA_PSS_SUPPORT + +/** + * \def POLARSSL_ZLIB_SUPPORT + * + * If set, the SSL/TLS module uses ZLIB to support compression and + * decompression of packet data. + * + * \warning TLS-level compression MAY REDUCE SECURITY! See for example the + * CRIME attack. Before enabling this option, you should examine with care if + * CRIME or similar exploits may be a applicable to your use case. + * + * Used in: library/ssl_tls.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * This feature requires zlib library and headers to be present. + * + * Uncomment to enable use of ZLIB + */ +//#define POLARSSL_ZLIB_SUPPORT +/* \} name SECTION: PolarSSL feature support */ + +/** + * \name SECTION: PolarSSL modules + * + * This section enables or disables entire modules in PolarSSL + * \{ + */ + +/** + * \def POLARSSL_AESNI_C + * + * Enable AES-NI support on x86-64. + * + * Module: library/aesni.c + * Caller: library/aes.c + * + * Requires: POLARSSL_HAVE_ASM + * + * This modules adds support for the AES-NI instructions on x86-64 + */ +#define POLARSSL_AESNI_C + +/** + * \def POLARSSL_AES_C + * + * Enable the AES block cipher. + * + * Module: library/aes.c + * Caller: library/ssl_tls.c + * library/pem.c + * library/ctr_drbg.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + * TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + * TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + * TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + * TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + * TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + * TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + * TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + * TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + * TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + * TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + * TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + * TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + * TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + * TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + * TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + * TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + * TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + * TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + * TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + * TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + * TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + * TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * TLS_RSA_WITH_AES_256_GCM_SHA384 + * TLS_RSA_WITH_AES_256_CBC_SHA256 + * TLS_RSA_WITH_AES_256_CBC_SHA + * TLS_RSA_WITH_AES_128_GCM_SHA256 + * TLS_RSA_WITH_AES_128_CBC_SHA256 + * TLS_RSA_WITH_AES_128_CBC_SHA + * TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * TLS_PSK_WITH_AES_256_GCM_SHA384 + * TLS_PSK_WITH_AES_256_CBC_SHA384 + * TLS_PSK_WITH_AES_256_CBC_SHA + * TLS_PSK_WITH_AES_128_GCM_SHA256 + * TLS_PSK_WITH_AES_128_CBC_SHA256 + * TLS_PSK_WITH_AES_128_CBC_SHA + * + * PEM_PARSE uses AES for decrypting encrypted keys. + */ +#define POLARSSL_AES_C + +/** + * \def POLARSSL_ARC4_C + * + * Enable the ARCFOUR stream cipher. + * + * Module: library/arc4.c + * Caller: library/ssl_tls.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDH_ECDSA_WITH_RC4_128_SHA + * TLS_ECDH_RSA_WITH_RC4_128_SHA + * TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + * TLS_ECDHE_RSA_WITH_RC4_128_SHA + * TLS_ECDHE_PSK_WITH_RC4_128_SHA + * TLS_DHE_PSK_WITH_RC4_128_SHA + * TLS_RSA_WITH_RC4_128_SHA + * TLS_RSA_WITH_RC4_128_MD5 + * TLS_RSA_PSK_WITH_RC4_128_SHA + * TLS_PSK_WITH_RC4_128_SHA + */ +#define POLARSSL_ARC4_C + +/** + * \def POLARSSL_ASN1_PARSE_C + * + * Enable the generic ASN1 parser. + * + * Module: library/asn1.c + * Caller: library/x509.c + * library/dhm.c + * library/pkcs12.c + * library/pkcs5.c + * library/pkparse.c + */ +#define POLARSSL_ASN1_PARSE_C + +/** + * \def POLARSSL_ASN1_WRITE_C + * + * Enable the generic ASN1 writer. + * + * Module: library/asn1write.c + * Caller: library/ecdsa.c + * library/pkwrite.c + * library/x509_create.c + * library/x509write_crt.c + * library/x509write_csr.c + */ +#define POLARSSL_ASN1_WRITE_C + +/** + * \def POLARSSL_BASE64_C + * + * Enable the Base64 module. + * + * Module: library/base64.c + * Caller: library/pem.c + * + * This module is required for PEM support (required by X.509). + */ +#define POLARSSL_BASE64_C + +/** + * \def POLARSSL_BIGNUM_C + * + * Enable the multi-precision integer library. + * + * Module: library/bignum.c + * Caller: library/dhm.c + * library/ecp.c + * library/ecdsa.c + * library/rsa.c + * library/ssl_tls.c + * + * This module is required for RSA, DHM and ECC (ECDH, ECDSA) support. + */ +#define POLARSSL_BIGNUM_C + +/** + * \def POLARSSL_BLOWFISH_C + * + * Enable the Blowfish block cipher. + * + * Module: library/blowfish.c + */ +#define POLARSSL_BLOWFISH_C + +/** + * \def POLARSSL_CAMELLIA_C + * + * Enable the Camellia block cipher. + * + * Module: library/camellia.c + * Caller: library/ssl_tls.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 + */ +#define POLARSSL_CAMELLIA_C + +/** + * \def POLARSSL_CCM_C + * + * Enable the Counter with CBC-MAC (CCM) mode for 128-bit block cipher. + * + * Module: library/ccm.c + * + * Requires: POLARSSL_AES_C or POLARSSL_CAMELLIA_C + * + * This module enables the AES-CCM ciphersuites, if other requisites are + * enabled as well. + */ +#define POLARSSL_CCM_C + +/** + * \def POLARSSL_CERTS_C + * + * Enable the test certificates. + * + * Module: library/certs.c + * Caller: + * + * Requires: POLARSSL_PEM_PARSE_C + * + * This module is used for testing (ssl_client/server). + */ +#define POLARSSL_CERTS_C + +/** + * \def POLARSSL_CIPHER_C + * + * Enable the generic cipher layer. + * + * Module: library/cipher.c + * Caller: library/ssl_tls.c + * + * Uncomment to enable generic cipher wrappers. + */ +#define POLARSSL_CIPHER_C + +/** + * \def POLARSSL_CTR_DRBG_C + * + * Enable the CTR_DRBG AES-256-based random generator. + * + * Module: library/ctr_drbg.c + * Caller: + * + * Requires: POLARSSL_AES_C + * + * This module provides the CTR_DRBG AES-256 random number generator. + */ +#define POLARSSL_CTR_DRBG_C + +/** + * \def POLARSSL_DEBUG_C + * + * Enable the debug functions. + * + * Module: library/debug.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module provides debugging functions. + */ +#define POLARSSL_DEBUG_C + +/** + * \def POLARSSL_DES_C + * + * Enable the DES block cipher. + * + * Module: library/des.c + * Caller: library/pem.c + * library/ssl_tls.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + * TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + * TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA + * TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA + * TLS_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA + * TLS_PSK_WITH_3DES_EDE_CBC_SHA + * + * PEM_PARSE uses DES/3DES for decrypting encrypted keys. + */ +#define POLARSSL_DES_C + +/** + * \def POLARSSL_DHM_C + * + * Enable the Diffie-Hellman-Merkle module. + * + * Module: library/dhm.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module is used by the following key exchanges: + * DHE-RSA, DHE-PSK + */ +#define POLARSSL_DHM_C + +/** + * \def POLARSSL_ECDH_C + * + * Enable the elliptic curve Diffie-Hellman library. + * + * Module: library/ecdh.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA, ECDHE-RSA, DHE-PSK + * + * Requires: POLARSSL_ECP_C + */ +#define POLARSSL_ECDH_C + +/** + * \def POLARSSL_ECDSA_C + * + * Enable the elliptic curve DSA library. + * + * Module: library/ecdsa.c + * Caller: + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA + * + * Requires: POLARSSL_ECP_C, POLARSSL_ASN1_WRITE_C, POLARSSL_ASN1_PARSE_C + */ +#define POLARSSL_ECDSA_C + +/** + * \def POLARSSL_ECP_C + * + * Enable the elliptic curve over GF(p) library. + * + * Module: library/ecp.c + * Caller: library/ecdh.c + * library/ecdsa.c + * + * Requires: POLARSSL_BIGNUM_C and at least one POLARSSL_ECP_DP_XXX_ENABLED + */ +#define POLARSSL_ECP_C + +/** + * \def POLARSSL_ENTROPY_C + * + * Enable the platform-specific entropy code. + * + * Module: library/entropy.c + * Caller: + * + * Requires: POLARSSL_SHA512_C or POLARSSL_SHA256_C + * + * This module provides a generic entropy pool + */ +#define POLARSSL_ENTROPY_C + +/** + * \def POLARSSL_ERROR_C + * + * Enable error code to error string conversion. + * + * Module: library/error.c + * Caller: + * + * This module enables polarssl_strerror(). + */ +#define POLARSSL_ERROR_C + +/** + * \def POLARSSL_GCM_C + * + * Enable the Galois/Counter Mode (GCM) for AES. + * + * Module: library/gcm.c + * + * Requires: POLARSSL_AES_C or POLARSSL_CAMELLIA_C + * + * This module enables the AES-GCM and CAMELLIA-GCM ciphersuites, if other + * requisites are enabled as well. + */ +#define POLARSSL_GCM_C + +/** + * \def POLARSSL_HAVEGE_C + * + * Enable the HAVEGE random generator. + * + * Warning: the HAVEGE random generator is not suitable for virtualized + * environments + * + * Warning: the HAVEGE random generator is dependent on timing and specific + * processor traits. It is therefore not advised to use HAVEGE as + * your applications primary random generator or primary entropy pool + * input. As a secondary input to your entropy pool, it IS able add + * the (limited) extra entropy it provides. + * + * Module: library/havege.c + * Caller: + * + * Requires: POLARSSL_TIMING_C + * + * Uncomment to enable the HAVEGE random generator. + */ +//#define POLARSSL_HAVEGE_C + +/** + * \def POLARSSL_HMAC_DRBG_C + * + * Enable the HMAC_DRBG random generator. + * + * Module: library/hmac_drbg.c + * Caller: + * + * Requires: POLARSSL_MD_C + * + * Uncomment to enable the HMAC_DRBG random number geerator. + */ +#define POLARSSL_HMAC_DRBG_C + +/** + * \def POLARSSL_MD_C + * + * Enable the generic message digest layer. + * + * Module: library/md.c + * Caller: + * + * Uncomment to enable generic message digest wrappers. + */ +#define POLARSSL_MD_C + +/** + * \def POLARSSL_MD2_C + * + * Enable the MD2 hash algorithm. + * + * Module: library/md2.c + * Caller: + * + * Uncomment to enable support for (rare) MD2-signed X.509 certs. + */ +//#define POLARSSL_MD2_C + +/** + * \def POLARSSL_MD4_C + * + * Enable the MD4 hash algorithm. + * + * Module: library/md4.c + * Caller: + * + * Uncomment to enable support for (rare) MD4-signed X.509 certs. + */ +//#define POLARSSL_MD4_C + +/** + * \def POLARSSL_MD5_C + * + * Enable the MD5 hash algorithm. + * + * Module: library/md5.c + * Caller: library/md.c + * library/pem.c + * library/ssl_tls.c + * + * This module is required for SSL/TLS and X.509. + * PEM_PARSE uses MD5 for decrypting encrypted keys. + */ +#define POLARSSL_MD5_C + +/** + * \def POLARSSL_MEMORY_C + * Deprecated since 1.3.5. Please use POLARSSL_PLATFORM_MEMORY instead. + */ +//#define POLARSSL_MEMORY_C + +/** + * \def POLARSSL_MEMORY_BUFFER_ALLOC_C + * + * Enable the buffer allocator implementation that makes use of a (stack) + * based buffer to 'allocate' dynamic memory. (replaces malloc() and free() + * calls) + * + * Module: library/memory_buffer_alloc.c + * + * Requires: POLARSSL_PLATFORM_C + * POLARSSL_PLATFORM_MEMORY (to use it within PolarSSL) + * + * Enable this module to enable the buffer memory allocator. + */ +//#define POLARSSL_MEMORY_BUFFER_ALLOC_C + +/** + * \def POLARSSL_NET_C + * + * Enable the TCP/IP networking routines. + * + * Module: library/net.c + * + * This module provides TCP/IP networking routines. + */ +#define POLARSSL_NET_C + +/** + * \def POLARSSL_OID_C + * + * Enable the OID database. + * + * Module: library/oid.c + * Caller: library/asn1write.c + * library/pkcs5.c + * library/pkparse.c + * library/pkwrite.c + * library/rsa.c + * library/x509.c + * library/x509_create.c + * library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * library/x509write_crt.c + * library/x509write_csr.c + * + * This modules translates between OIDs and internal values. + */ +#define POLARSSL_OID_C + +/** + * \def POLARSSL_PADLOCK_C + * + * Enable VIA Padlock support on x86. + * + * Module: library/padlock.c + * Caller: library/aes.c + * + * Requires: POLARSSL_HAVE_ASM + * + * This modules adds support for the VIA PadLock on x86. + */ +#define POLARSSL_PADLOCK_C + +/** + * \def POLARSSL_PBKDF2_C + * + * Enable PKCS#5 PBKDF2 key derivation function. + * DEPRECATED: Use POLARSSL_PKCS5_C instead + * + * Module: library/pbkdf2.c + * + * Requires: POLARSSL_PKCS5_C + * + * This module adds support for the PKCS#5 PBKDF2 key derivation function. + */ +#define POLARSSL_PBKDF2_C + +/** + * \def POLARSSL_PEM_PARSE_C + * + * Enable PEM decoding / parsing. + * + * Module: library/pem.c + * Caller: library/dhm.c + * library/pkparse.c + * library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * + * Requires: POLARSSL_BASE64_C + * + * This modules adds support for decoding / parsing PEM files. + */ +#define POLARSSL_PEM_PARSE_C + +/** + * \def POLARSSL_PEM_WRITE_C + * + * Enable PEM encoding / writing. + * + * Module: library/pem.c + * Caller: library/pkwrite.c + * library/x509write_crt.c + * library/x509write_csr.c + * + * Requires: POLARSSL_BASE64_C + * + * This modules adds support for encoding / writing PEM files. + */ +#define POLARSSL_PEM_WRITE_C + +/** + * \def POLARSSL_PK_C + * + * Enable the generic public (asymetric) key layer. + * + * Module: library/pk.c + * Caller: library/ssl_tls.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: POLARSSL_RSA_C or POLARSSL_ECP_C + * + * Uncomment to enable generic public key wrappers. + */ +#define POLARSSL_PK_C + +/** + * \def POLARSSL_PK_PARSE_C + * + * Enable the generic public (asymetric) key parser. + * + * Module: library/pkparse.c + * Caller: library/x509_crt.c + * library/x509_csr.c + * + * Requires: POLARSSL_PK_C + * + * Uncomment to enable generic public key parse functions. + */ +#define POLARSSL_PK_PARSE_C + +/** + * \def POLARSSL_PK_WRITE_C + * + * Enable the generic public (asymetric) key writer. + * + * Module: library/pkwrite.c + * Caller: library/x509write.c + * + * Requires: POLARSSL_PK_C + * + * Uncomment to enable generic public key write functions. + */ +#define POLARSSL_PK_WRITE_C + +/** + * \def POLARSSL_PKCS5_C + * + * Enable PKCS#5 functions. + * + * Module: library/pkcs5.c + * + * Requires: POLARSSL_MD_C + * + * This module adds support for the PKCS#5 functions. + */ +#define POLARSSL_PKCS5_C + +/** + * \def POLARSSL_PKCS11_C + * + * Enable wrapper for PKCS#11 smartcard support. + * + * Module: library/pkcs11.c + * Caller: library/pk.c + * + * Requires: POLARSSL_PK_C + * + * This module enables SSL/TLS PKCS #11 smartcard support. + * Requires the presence of the PKCS#11 helper library (libpkcs11-helper) + */ +//#define POLARSSL_PKCS11_C + +/** + * \def POLARSSL_PKCS12_C + * + * Enable PKCS#12 PBE functions. + * Adds algorithms for parsing PKCS#8 encrypted private keys + * + * Module: library/pkcs12.c + * Caller: library/pkparse.c + * + * Requires: POLARSSL_ASN1_PARSE_C, POLARSSL_CIPHER_C, POLARSSL_MD_C + * Can use: POLARSSL_ARC4_C + * + * This module enables PKCS#12 functions. + */ +#define POLARSSL_PKCS12_C + +/** + * \def POLARSSL_PLATFORM_C + * + * Enable the platform abstraction layer that allows you to re-assign + * functions like malloc(), free(), printf(), fprintf() + * + * Module: library/platform.c + * Caller: Most other .c files + * + * This module enables abstraction of common (libc) functions. + */ +#define POLARSSL_PLATFORM_C + +/** + * \def POLARSSL_RIPEMD160_C + * + * Enable the RIPEMD-160 hash algorithm. + * + * Module: library/ripemd160.c + * Caller: library/md.c + * + */ +#define POLARSSL_RIPEMD160_C + +/** + * \def POLARSSL_RSA_C + * + * Enable the RSA public-key cryptosystem. + * + * Module: library/rsa.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509.c + * + * This module is used by the following key exchanges: + * RSA, DHE-RSA, ECDHE-RSA, RSA-PSK + * + * Requires: POLARSSL_BIGNUM_C, POLARSSL_OID_C + */ +#define POLARSSL_RSA_C + +/** + * \def POLARSSL_SHA1_C + * + * Enable the SHA1 cryptographic hash algorithm. + * + * Module: library/sha1.c + * Caller: library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509write_crt.c + * + * This module is required for SSL/TLS and SHA1-signed certificates. + */ +#define POLARSSL_SHA1_C + +/** + * \def POLARSSL_SHA256_C + * + * Enable the SHA-224 and SHA-256 cryptographic hash algorithms. + * (Used to be POLARSSL_SHA2_C) + * + * Module: library/sha256.c + * Caller: library/entropy.c + * library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module adds support for SHA-224 and SHA-256. + * This module is required for the SSL/TLS 1.2 PRF function. + */ +#define POLARSSL_SHA256_C + +/** + * \def POLARSSL_SHA512_C + * + * Enable the SHA-384 and SHA-512 cryptographic hash algorithms. + * (Used to be POLARSSL_SHA4_C) + * + * Module: library/sha512.c + * Caller: library/entropy.c + * library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * This module adds support for SHA-384 and SHA-512. + */ +#define POLARSSL_SHA512_C + +/** + * \def POLARSSL_SSL_CACHE_C + * + * Enable simple SSL cache implementation. + * + * Module: library/ssl_cache.c + * Caller: + * + * Requires: POLARSSL_SSL_CACHE_C + */ +#define POLARSSL_SSL_CACHE_C + +/** + * \def POLARSSL_SSL_CLI_C + * + * Enable the SSL/TLS client code. + * + * Module: library/ssl_cli.c + * Caller: + * + * Requires: POLARSSL_SSL_TLS_C + * + * This module is required for SSL/TLS client support. + */ +#define POLARSSL_SSL_CLI_C + +/** + * \def POLARSSL_SSL_SRV_C + * + * Enable the SSL/TLS server code. + * + * Module: library/ssl_srv.c + * Caller: + * + * Requires: POLARSSL_SSL_TLS_C + * + * This module is required for SSL/TLS server support. + */ +#define POLARSSL_SSL_SRV_C + +/** + * \def POLARSSL_SSL_TLS_C + * + * Enable the generic SSL/TLS code. + * + * Module: library/ssl_tls.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: POLARSSL_CIPHER_C, POLARSSL_MD_C + * and at least one of the POLARSSL_SSL_PROTO_* defines + * + * This module is required for SSL/TLS. + */ +#define POLARSSL_SSL_TLS_C + +/** + * \def POLARSSL_THREADING_C + * + * Enable the threading abstraction layer. + * By default PolarSSL assumes it is used in a non-threaded environment or that + * contexts are not shared between threads. If you do intend to use contexts + * between threads, you will need to enable this layer to prevent race + * conditions. + * + * Module: library/threading.c + * + * This allows different threading implementations (self-implemented or + * provided). + * + * You will have to enable either POLARSSL_THREADING_ALT or + * POLARSSL_THREADING_PTHREAD. + * + * Enable this layer to allow use of mutexes within PolarSSL + */ +//#define POLARSSL_THREADING_C + +/** + * \def POLARSSL_TIMING_C + * + * Enable the portable timing interface. + * + * Module: library/timing.c + * Caller: library/havege.c + * + * This module is used by the HAVEGE random number generator. + */ +#define POLARSSL_TIMING_C + +/** + * \def POLARSSL_VERSION_C + * + * Enable run-time version information. + * + * Module: library/version.c + * + * This module provides run-time version information. + */ +#define POLARSSL_VERSION_C + +/** + * \def POLARSSL_X509_USE_C + * + * Enable X.509 core for using certificates. + * + * Module: library/x509.c + * Caller: library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * + * Requires: POLARSSL_ASN1_PARSE_C, POLARSSL_BIGNUM_C, POLARSSL_OID_C, + * POLARSSL_PK_PARSE_C + * + * This module is required for the X.509 parsing modules. + */ +#define POLARSSL_X509_USE_C + +/** + * \def POLARSSL_X509_CRT_PARSE_C + * + * Enable X.509 certificate parsing. + * + * Module: library/x509_crt.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * Requires: POLARSSL_X509_USE_C + * + * This module is required for X.509 certificate parsing. + */ +#define POLARSSL_X509_CRT_PARSE_C + +/** + * \def POLARSSL_X509_CRL_PARSE_C + * + * Enable X.509 CRL parsing. + * + * Module: library/x509_crl.c + * Caller: library/x509_crt.c + * + * Requires: POLARSSL_X509_USE_C + * + * This module is required for X.509 CRL parsing. + */ +#define POLARSSL_X509_CRL_PARSE_C + +/** + * \def POLARSSL_X509_CSR_PARSE_C + * + * Enable X.509 Certificate Signing Request (CSR) parsing. + * + * Module: library/x509_csr.c + * Caller: library/x509_crt_write.c + * + * Requires: POLARSSL_X509_USE_C + * + * This module is used for reading X.509 certificate request. + */ +#define POLARSSL_X509_CSR_PARSE_C + +/** + * \def POLARSSL_X509_CREATE_C + * + * Enable X.509 core for creating certificates. + * + * Module: library/x509_create.c + * + * Requires: POLARSSL_BIGNUM_C, POLARSSL_OID_C, POLARSSL_PK_WRITE_C + * + * This module is the basis for creating X.509 certificates and CSRs. + */ +#define POLARSSL_X509_CREATE_C + +/** + * \def POLARSSL_X509_CRT_WRITE_C + * + * Enable creating X.509 certificates. + * + * Module: library/x509_crt_write.c + * + * Requires: POLARSSL_CREATE_C + * + * This module is required for X.509 certificate creation. + */ +#define POLARSSL_X509_CRT_WRITE_C + +/** + * \def POLARSSL_X509_CSR_WRITE_C + * + * Enable creating X.509 Certificate Signing Requests (CSR). + * + * Module: library/x509_csr_write.c + * + * Requires: POLARSSL_CREATE_C + * + * This module is required for X.509 certificate request writing. + */ +#define POLARSSL_X509_CSR_WRITE_C + +/** + * \def POLARSSL_XTEA_C + * + * Enable the XTEA block cipher. + * + * Module: library/xtea.c + * Caller: + */ +#define POLARSSL_XTEA_C + +/* \} name SECTION: PolarSSL modules */ + +/** + * \name SECTION: Module configuration options + * + * This section allows for the setting of module specific sizes and + * configuration options. The default values are already present in the + * relevant header files and should suffice for the regular use cases. + * + * Our advice is to enable options and change their values here + * only if you have a good reason and know the consequences. + * + * Please check the respective header file for documentation on these + * parameters (to prevent duplicate documentation). + * \{ + */ + +/* MPI / BIGNUM options */ +//#define POLARSSL_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */ +//#define POLARSSL_MPI_MAX_SIZE 512 /**< Maximum number of bytes for usable MPIs. */ + +/* CTR_DRBG options */ +//#define CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */ +//#define CTR_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +//#define CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +//#define CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +//#define CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ + +/* HMAC_DRBG options */ +//#define POLARSSL_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +//#define POLARSSL_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +//#define POLARSSL_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +//#define POLARSSL_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ + +/* ECP options */ +//#define POLARSSL_ECP_MAX_BITS 521 /**< Maximum bit size of groups */ +//#define POLARSSL_ECP_WINDOW_SIZE 6 /**< Maximum window size used */ +//#define POLARSSL_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up */ + +/* Entropy options */ +//#define ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ +//#define ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ + +/* Memory buffer allocator options */ +//#define POLARSSL_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */ + +/* Platform options */ +//#define POLARSSL_PLATFORM_STD_MEM_HDR /**< Header to include if POLARSSL_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is needed. */ +//#define POLARSSL_PLATFORM_STD_MALLOC malloc /**< Default allocator to use, can be undefined */ +//#define POLARSSL_PLATFORM_STD_FREE free /**< Default free to use, can be undefined */ +//#define POLARSSL_PLATFORM_STD_PRINTF printf /**< Default printf to use, can be undefined */ +//#define POLARSSL_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use, can be undefined */ + +/* SSL Cache options */ +//#define SSL_CACHE_DEFAULT_TIMEOUT 86400 /**< 1 day */ +//#define SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /**< Maximum entries in cache */ + +/* SSL options */ +//#define SSL_MAX_CONTENT_LEN 16384 /**< Size of the input / output buffer */ +//#define SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ +//#define POLARSSL_PSK_MAX_LEN 32 /**< Max size of TLS pre-shared keys, in bytes (default 256 bits) */ + +/** + * Complete list of ciphersuites to use, in order of preference. + * + * \warning No dependency checking is done on that field! This option can only + * be used to restrict the set of available ciphersuites. It is your + * responsibility to make sure the needed modules are active. + * + * Use this to save a few hundred bytes of ROM (default ordering of all + * available ciphersuites) and a few to a few hundred bytes of RAM. + * + * The value below is only an example, not the default. + */ +//#define SSL_CIPHERSUITES TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + +/* Debug options */ +//#define POLARSSL_DEBUG_DFL_MODE POLARSSL_DEBUG_LOG_FULL /**< Default log: Full or Raw */ + +/* \} name SECTION: Module configuration options */ + +#include "check_config.h" + +#endif /* POLARSSL_CONFIG_H */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/config_rsa.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/config_rsa.h new file mode 100644 index 0000000..8c340c2 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/config_rsa.h @@ -0,0 +1,2183 @@ +/** + * \file config.h + * + * \brief Configuration options (set of defines) + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * This set of compile-time options may be used to enable + * or disable features selectively, and reduce the global + * memory footprint. + */ +#ifndef POLARSSL_CONFIG_H +#define POLARSSL_CONFIG_H + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif + +/** + * \name SECTION: System support + * + * This section sets system specific settings. + * \{ + */ + +/** + * \def POLARSSL_HAVE_INT8 + * + * The system uses 8-bit wide native integers. + * + * Uncomment if native integers are 8-bit wide. + */ +//#define POLARSSL_HAVE_INT8 + +/** + * \def POLARSSL_HAVE_INT16 + * + * The system uses 16-bit wide native integers. + * + * Uncomment if native integers are 16-bit wide. + */ +//#define POLARSSL_HAVE_INT16 + +/** + * \def POLARSSL_HAVE_LONGLONG + * + * The compiler supports the 'long long' type. + * (Only used on 32-bit platforms) + */ +#define POLARSSL_HAVE_LONGLONG + +/** + * \def POLARSSL_HAVE_ASM + * + * The compiler has support for asm(). + * + * Requires support for asm() in compiler. + * + * Used in: + * library/timing.c + * library/padlock.c + * include/polarssl/bn_mul.h + * + * Comment to disable the use of assembly code. + */ +//#define POLARSSL_HAVE_ASM + +/** + * \def POLARSSL_HAVE_SSE2 + * + * CPU supports SSE2 instruction set. + * + * Uncomment if the CPU supports SSE2 (IA-32 specific). + */ +//#define POLARSSL_HAVE_SSE2 + +/** + * \def POLARSSL_HAVE_TIME + * + * System has time.h and time() / localtime() / gettimeofday(). + * + * Comment if your system does not support time functions + */ +//#define POLARSSL_HAVE_TIME + +/** + * \def POLARSSL_HAVE_IPV6 + * + * System supports the basic socket interface for IPv6 (RFC 3493), + * specifically getaddrinfo(), freeaddrinfo() and struct sockaddr_storage. + * + * Note: on Windows/MingW, XP or higher is required. + * + * Comment if your system does not support the IPv6 socket interface + */ +//#define POLARSSL_HAVE_IPV6 + +/** + * \def POLARSSL_PLATFORM_MEMORY + * + * Enable the memory allocation layer. + * + * By default PolarSSL uses the system-provided malloc() and free(). + * This allows different allocators (self-implemented or provided) to be + * provided to the platform abstraction layer. + * + * Enabling POLARSSL_PLATFORM_MEMORY will provide "platform_set_malloc_free()" + * to allow you to set an alternative malloc() and free() function pointer. + * + * Requires: POLARSSL_PLATFORM_C + * + * Enable this layer to allow use of alternative memory allocators. + */ +#define POLARSSL_PLATFORM_MEMORY + +/** + * \def POLARSSL_PLATFORM_NO_STD_FUNCTIONS + * + * Do not assign standard functions in the platform layer (e.g. malloc() to + * POLARSSL_PLATFORM_STD_MALLOC and printf() to POLARSSL_PLATFORM_STD_PRINTF) + * + * This makes sure there are no linking errors on platforms that do not support + * these functions. You will HAVE to provide alternatives, either at runtime + * via the platform_set_xxx() functions or at compile time by setting + * the POLARSSL_PLATFORM_STD_XXX defines. + * + * Requires: POLARSSL_PLATFORM_C + * + * Uncomment to prevent default assignment of standard functions in the + * platform layer. + */ +//#define POLARSSL_PLATFORM_NO_STD_FUNCTIONS + +/** + * \def POLARSSL_PLATFORM_XXX_ALT + * + * Uncomment a macro to let PolarSSL support the function in the platform + * abstraction layer. + * + * Example: In case you uncomment POLARSSL_PLATFORM_PRINTF_ALT, PolarSSL will + * provide a function "platform_set_printf()" that allows you to set an + * alternative printf function pointer. + * + * All these define require POLARSSL_PLATFORM_C to be defined! + * + * Uncomment a macro to enable alternate implementation of specific base + * platform function + */ +//#define POLARSSL_PLATFORM_PRINTF_ALT +//#define POLARSSL_PLATFORM_FPRINTF_ALT +/* \} name SECTION: System support */ + +/** + * \name SECTION: PolarSSL feature support + * + * This section sets support for features that are or are not needed + * within the modules that are enabled. + * \{ + */ + +/** + * \def POLARSSL_TIMING_ALT + * + * Uncomment to provide your own alternate implementation for hardclock(), + * get_timer(), set_alarm() and m_sleep(). + * + * Only works if you have POLARSSL_TIMING_C enabled. + * + * You will need to provide a header "timing_alt.h" and an implementation at + * compile time. + */ +//#define POLARSSL_TIMING_ALT + +/** + * \def POLARSSL_XXX_ALT + * + * Uncomment a macro to let PolarSSL use your alternate core implementation of + * a symmetric or hash algorithm (e.g. platform specific assembly optimized + * implementations). Keep in mind that the function prototypes should remain + * the same. + * + * Example: In case you uncomment POLARSSL_AES_ALT, PolarSSL will no longer + * provide the "struct aes_context" definition and omit the base function + * declarations and implementations. "aes_alt.h" will be included from + * "aes.h" to include the new function definitions. + * + * Uncomment a macro to enable alternate implementation for core algorithm + * functions + */ +//#define POLARSSL_AES_ALT +//#define POLARSSL_ARC4_ALT +//#define POLARSSL_BLOWFISH_ALT +//#define POLARSSL_CAMELLIA_ALT +//#define POLARSSL_DES_ALT +//#define POLARSSL_XTEA_ALT +//#define POLARSSL_MD2_ALT +//#define POLARSSL_MD4_ALT +//#define POLARSSL_MD5_ALT +//#define POLARSSL_RIPEMD160_ALT +//#define POLARSSL_SHA1_ALT +//#define POLARSSL_SHA256_ALT +//#define POLARSSL_SHA512_ALT + +/** + * \def POLARSSL_AES_ROM_TABLES + * + * Store the AES tables in ROM. + * + * Uncomment this macro to store the AES tables in ROM. + * + */ +#define POLARSSL_AES_ROM_TABLES + +/** + * \def POLARSSL_CIPHER_MODE_CBC + * + * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers. + */ +#define POLARSSL_CIPHER_MODE_CBC + +/** + * \def POLARSSL_CIPHER_MODE_CFB + * + * Enable Cipher Feedback mode (CFB) for symmetric ciphers. + */ +#define POLARSSL_CIPHER_MODE_CFB + +/** + * \def POLARSSL_CIPHER_MODE_CTR + * + * Enable Counter Block Cipher mode (CTR) for symmetric ciphers. + */ +#define POLARSSL_CIPHER_MODE_CTR + +/** + * \def POLARSSL_CIPHER_NULL_CIPHER + * + * Enable NULL cipher. + * Warning: Only do so when you know what you are doing. This allows for + * encryption or channels without any security! + * + * Requires POLARSSL_ENABLE_WEAK_CIPHERSUITES as well to enable + * the following ciphersuites: + * TLS_ECDH_ECDSA_WITH_NULL_SHA + * TLS_ECDH_RSA_WITH_NULL_SHA + * TLS_ECDHE_ECDSA_WITH_NULL_SHA + * TLS_ECDHE_RSA_WITH_NULL_SHA + * TLS_ECDHE_PSK_WITH_NULL_SHA384 + * TLS_ECDHE_PSK_WITH_NULL_SHA256 + * TLS_ECDHE_PSK_WITH_NULL_SHA + * TLS_DHE_PSK_WITH_NULL_SHA384 + * TLS_DHE_PSK_WITH_NULL_SHA256 + * TLS_DHE_PSK_WITH_NULL_SHA + * TLS_RSA_WITH_NULL_SHA256 + * TLS_RSA_WITH_NULL_SHA + * TLS_RSA_WITH_NULL_MD5 + * TLS_RSA_PSK_WITH_NULL_SHA384 + * TLS_RSA_PSK_WITH_NULL_SHA256 + * TLS_RSA_PSK_WITH_NULL_SHA + * TLS_PSK_WITH_NULL_SHA384 + * TLS_PSK_WITH_NULL_SHA256 + * TLS_PSK_WITH_NULL_SHA + * + * Uncomment this macro to enable the NULL cipher and ciphersuites + */ +//#define POLARSSL_CIPHER_NULL_CIPHER + +/** + * \def POLARSSL_CIPHER_PADDING_XXX + * + * Uncomment or comment macros to add support for specific padding modes + * in the cipher layer with cipher modes that support padding (e.g. CBC) + * + * If you disable all padding modes, only full blocks can be used with CBC. + * + * Enable padding modes in the cipher layer. + */ +#define POLARSSL_CIPHER_PADDING_PKCS7 +#define POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS +#define POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN +#define POLARSSL_CIPHER_PADDING_ZEROS + +/** + * \def POLARSSL_ENABLE_WEAK_CIPHERSUITES + * + * Enable weak ciphersuites in SSL / TLS. + * Warning: Only do so when you know what you are doing. This allows for + * channels with virtually no security at all! + * + * This enables the following ciphersuites: + * TLS_RSA_WITH_DES_CBC_SHA + * TLS_DHE_RSA_WITH_DES_CBC_SHA + * + * Uncomment this macro to enable weak ciphersuites + */ +//#define POLARSSL_ENABLE_WEAK_CIPHERSUITES + +/** + * \def POLARSSL_REMOVE_ARC4_CIPHERSUITES + * + * Remove RC4 ciphersuites by default in SSL / TLS. + * This flag removes the ciphersuites based on RC4 from the default list as + * returned by ssl_list_ciphersuites(). However, it is still possible to + * enable (some of) them with ssl_set_ciphersuites() by including them + * explicitly. + * + * Uncomment this macro to remove RC4 ciphersuites by default. + */ +//#define POLARSSL_REMOVE_ARC4_CIPHERSUITES + +/** + * \def POLARSSL_ECP_XXXX_ENABLED + * + * Enables specific curves within the Elliptic Curve module. + * By default all supported curves are enabled. + * + * Comment macros to disable the curve and functions for it + */ +#define POLARSSL_ECP_DP_SECP192R1_ENABLED +#define POLARSSL_ECP_DP_SECP224R1_ENABLED +#define POLARSSL_ECP_DP_SECP256R1_ENABLED +#define POLARSSL_ECP_DP_SECP384R1_ENABLED +#define POLARSSL_ECP_DP_SECP521R1_ENABLED +#define POLARSSL_ECP_DP_SECP192K1_ENABLED +#define POLARSSL_ECP_DP_SECP224K1_ENABLED +#define POLARSSL_ECP_DP_SECP256K1_ENABLED +#define POLARSSL_ECP_DP_BP256R1_ENABLED +#define POLARSSL_ECP_DP_BP384R1_ENABLED +#define POLARSSL_ECP_DP_BP512R1_ENABLED +//#define POLARSSL_ECP_DP_M221_ENABLED // Not implemented yet! +#define POLARSSL_ECP_DP_M255_ENABLED +//#define POLARSSL_ECP_DP_M383_ENABLED // Not implemented yet! +//#define POLARSSL_ECP_DP_M511_ENABLED // Not implemented yet! + +/** + * \def POLARSSL_ECP_NIST_OPTIM + * + * Enable specific 'modulo p' routines for each NIST prime. + * Depending on the prime and architecture, makes operations 4 to 8 times + * faster on the corresponding curve. + * + * Comment this macro to disable NIST curves optimisation. + */ +#define POLARSSL_ECP_NIST_OPTIM + +/** + * \def POLARSSL_ECDSA_DETERMINISTIC + * + * Enable deterministic ECDSA (RFC 6979). + * Standard ECDSA is "fragile" in the sense that lack of entropy when signing + * may result in a compromise of the long-term signing key. This is avoided by + * the deterministic variant. + * + * Requires: POLARSSL_HMAC_DRBG_C + * + * Comment this macro to disable deterministic ECDSA. + */ +//#define POLARSSL_ECDSA_DETERMINISTIC + +/** + * \def POLARSSL_KEY_EXCHANGE_PSK_ENABLED + * + * Enable the PSK based ciphersuite modes in SSL / TLS. + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_PSK_WITH_AES_256_GCM_SHA384 + * TLS_PSK_WITH_AES_256_CBC_SHA384 + * TLS_PSK_WITH_AES_256_CBC_SHA + * TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_PSK_WITH_AES_128_GCM_SHA256 + * TLS_PSK_WITH_AES_128_CBC_SHA256 + * TLS_PSK_WITH_AES_128_CBC_SHA + * TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_PSK_WITH_3DES_EDE_CBC_SHA + * TLS_PSK_WITH_RC4_128_SHA + */ +//#define POLARSSL_KEY_EXCHANGE_PSK_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED + * + * Enable the DHE-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_DHM_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA + * TLS_DHE_PSK_WITH_RC4_128_SHA + */ +//#define POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED + * + * Enable the ECDHE-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_ECDH_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA + * TLS_ECDHE_PSK_WITH_RC4_128_SHA + */ +//#define POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED + * + * Enable the RSA-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_RSA_C, POLARSSL_PKCS1_V15, + * POLARSSL_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA + * TLS_RSA_PSK_WITH_RC4_128_SHA + */ +//#define POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_RSA_ENABLED + * + * Enable the RSA-only based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_RSA_C, POLARSSL_PKCS1_V15, + * POLARSSL_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_RSA_WITH_AES_256_GCM_SHA384 + * TLS_RSA_WITH_AES_256_CBC_SHA256 + * TLS_RSA_WITH_AES_256_CBC_SHA + * TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * TLS_RSA_WITH_AES_128_GCM_SHA256 + * TLS_RSA_WITH_AES_128_CBC_SHA256 + * TLS_RSA_WITH_AES_128_CBC_SHA + * TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * TLS_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_RSA_WITH_RC4_128_SHA + * TLS_RSA_WITH_RC4_128_MD5 + */ +#define POLARSSL_KEY_EXCHANGE_RSA_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED + * + * Enable the DHE-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_DHM_C, POLARSSL_RSA_C, POLARSSL_PKCS1_V15, + * POLARSSL_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + * TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + */ +//#define POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED + * + * Enable the ECDHE-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_ECDH_C, POLARSSL_RSA_C, POLARSSL_PKCS1_V15, + * POLARSSL_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + * TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + * TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + * TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + * TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + * TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_ECDHE_RSA_WITH_RC4_128_SHA + */ +//#define POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + * + * Enable the ECDHE-ECDSA based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_ECDH_C, POLARSSL_ECDSA_C, POLARSSL_X509_CRT_PARSE_C, + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + * TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + * TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + * TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + */ +//#define POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED + * + * Enable the ECDH-ECDSA based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_ECDH_C, POLARSSL_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDH_ECDSA_WITH_RC4_128_SHA + * TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + * TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + * TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + * TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + * TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + * TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + * TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + * TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + */ +//#define POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED + * + * Enable the ECDH-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_ECDH_C, POLARSSL_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDH_RSA_WITH_RC4_128_SHA + * TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + * TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + * TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + * TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + * TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + * TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + * TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 + */ +//#define POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED + +/** + * \def POLARSSL_PK_PARSE_EC_EXTENDED + * + * Enhance support for reading EC keys using variants of SEC1 not allowed by + * RFC 5915 and RFC 5480. + * + * Currently this means parsing the SpecifiedECDomain choice of EC + * parameters (only known groups are supported, not arbitrary domains, to + * avoid validation issues). + * + * Disable if you only need to support RFC 5915 + 5480 key formats. + */ +//#define POLARSSL_PK_PARSE_EC_EXTENDED + +/** + * \def POLARSSL_ERROR_STRERROR_BC + * + * Make available the backward compatible error_strerror() next to the + * current polarssl_strerror(). + * + * For new code, it is recommended to use polarssl_strerror() instead and + * disable this. + * + * Disable if you run into name conflicts and want to really remove the + * error_strerror() + */ +#define POLARSSL_ERROR_STRERROR_BC + +/** + * \def POLARSSL_ERROR_STRERROR_DUMMY + * + * Enable a dummy error function to make use of polarssl_strerror() in + * third party libraries easier when POLARSSL_ERROR_C is disabled + * (no effect when POLARSSL_ERROR_C is enabled). + * + * You can safely disable this if POLARSSL_ERROR_C is enabled, or if you're + * not using polarssl_strerror() or error_strerror() in your application. + * + * Disable if you run into name conflicts and want to really remove the + * polarssl_strerror() + */ +#define POLARSSL_ERROR_STRERROR_DUMMY + +/** + * \def POLARSSL_GENPRIME + * + * Enable the prime-number generation code. + * + * Requires: POLARSSL_BIGNUM_C + */ +#define POLARSSL_GENPRIME + +/** + * \def POLARSSL_FS_IO + * + * Enable functions that use the filesystem. + */ +//#define POLARSSL_FS_IO + +/** + * \def POLARSSL_NO_DEFAULT_ENTROPY_SOURCES + * + * Do not add default entropy sources. These are the platform specific, + * hardclock and HAVEGE based poll functions. + * + * This is useful to have more control over the added entropy sources in an + * application. + * + * Uncomment this macro to prevent loading of default entropy functions. + */ +//#define POLARSSL_NO_DEFAULT_ENTROPY_SOURCES + +/** + * \def POLARSSL_NO_PLATFORM_ENTROPY + * + * Do not use built-in platform entropy functions. + * This is useful if your platform does not support + * standards like the /dev/urandom or Windows CryptoAPI. + * + * Uncomment this macro to disable the built-in platform entropy functions. + */ +//#define POLARSSL_NO_PLATFORM_ENTROPY + +/** + * \def POLARSSL_ENTROPY_FORCE_SHA256 + * + * Force the entropy accumulator to use a SHA-256 accumulator instead of the + * default SHA-512 based one (if both are available). + * + * Requires: POLARSSL_SHA256_C + * + * On 32-bit systems SHA-256 can be much faster than SHA-512. Use this option + * if you have performance concerns. + * + * This option is only useful if both POLARSSL_SHA256_C and + * POLARSSL_SHA512_C are defined. Otherwise the available hash module is used. + */ +//#define POLARSSL_ENTROPY_FORCE_SHA256 + +/** + * \def POLARSSL_MEMORY_DEBUG + * + * Enable debugging of buffer allocator memory issues. Automatically prints + * (to stderr) all (fatal) messages on memory allocation issues. Enables + * function for 'debug output' of allocated memory. + * + * Requires: POLARSSL_MEMORY_BUFFER_ALLOC_C + * + * Uncomment this macro to let the buffer allocator print out error messages. + */ +//#define POLARSSL_MEMORY_DEBUG + +/** + * \def POLARSSL_MEMORY_BACKTRACE + * + * Include backtrace information with each allocated block. + * + * Requires: POLARSSL_MEMORY_BUFFER_ALLOC_C + * GLIBC-compatible backtrace() an backtrace_symbols() support + * + * Uncomment this macro to include backtrace information + */ +//#define POLARSSL_MEMORY_BACKTRACE + +/** + * \def POLARSSL_PKCS1_V15 + * + * Enable support for PKCS#1 v1.5 encoding. + * + * Requires: POLARSSL_RSA_C + * + * This enables support for PKCS#1 v1.5 operations. + */ +#define POLARSSL_PKCS1_V15 + +/** + * \def POLARSSL_PKCS1_V21 + * + * Enable support for PKCS#1 v2.1 encoding. + * + * Requires: POLARSSL_MD_C, POLARSSL_RSA_C + * + * This enables support for RSAES-OAEP and RSASSA-PSS operations. + */ +//#define POLARSSL_PKCS1_V21 + +/** + * \def POLARSSL_RSA_NO_CRT + * + * Do not use the Chinese Remainder Theorem for the RSA private operation. + * + * Uncomment this macro to disable the use of CRT in RSA. + * + */ +//#define POLARSSL_RSA_NO_CRT + +/** + * \def POLARSSL_SELF_TEST + * + * Enable the checkup functions (*_self_test). + */ +//#define POLARSSL_SELF_TEST + +/** + * \def POLARSSL_SSL_ALL_ALERT_MESSAGES + * + * Enable sending of alert messages in case of encountered errors as per RFC. + * If you choose not to send the alert messages, PolarSSL can still communicate + * with other servers, only debugging of failures is harder. + * + * The advantage of not sending alert messages, is that no information is given + * about reasons for failures thus preventing adversaries of gaining intel. + * + * Enable sending of all alert messages + */ +#define POLARSSL_SSL_ALERT_MESSAGES + +/** + * \def POLARSSL_SSL_DEBUG_ALL + * + * Enable the debug messages in SSL module for all issues. + * Debug messages have been disabled in some places to prevent timing + * attacks due to (unbalanced) debugging function calls. + * + * If you need all error reporting you should enable this during debugging, + * but remove this for production servers that should log as well. + * + * Uncomment this macro to report all debug messages on errors introducing + * a timing side-channel. + * + */ +//#define POLARSSL_SSL_DEBUG_ALL + +/** + * \def POLARSSL_SSL_HW_RECORD_ACCEL + * + * Enable hooking functions in SSL module for hardware acceleration of + * individual records. + * + * Uncomment this macro to enable hooking functions. + */ +//#define POLARSSL_SSL_HW_RECORD_ACCEL + +/** + * \def POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO + * + * Enable support for receiving and parsing SSLv2 Client Hello messages for the + * SSL Server module (POLARSSL_SSL_SRV_C). + * + * Comment this macro to disable support for SSLv2 Client Hello messages. + */ +//#define POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO + +/** + * \def POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE + * + * Pick the ciphersuite according to the client's preferences rather than ours + * in the SSL Server module (POLARSSL_SSL_SRV_C). + * + * Uncomment this macro to respect client's ciphersuite order + */ +//#define POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE + +/** + * \def POLARSSL_SSL_MAX_FRAGMENT_LENGTH + * + * Enable support for RFC 6066 max_fragment_length extension in SSL. + * + * Comment this macro to disable support for the max_fragment_length extension + */ +#define POLARSSL_SSL_MAX_FRAGMENT_LENGTH + +/** + * \def POLARSSL_SSL_PROTO_SSL3 + * + * Enable support for SSL 3.0. + * + * Requires: POLARSSL_MD5_C + * POLARSSL_SHA1_C + * + * Comment this macro to disable support for SSL 3.0 + */ +#define POLARSSL_SSL_PROTO_SSL3 + +/** + * \def POLARSSL_SSL_PROTO_TLS1 + * + * Enable support for TLS 1.0. + * + * Requires: POLARSSL_MD5_C + * POLARSSL_SHA1_C + * + * Comment this macro to disable support for TLS 1.0 + */ +#define POLARSSL_SSL_PROTO_TLS1 + +/** + * \def POLARSSL_SSL_PROTO_TLS1_1 + * + * Enable support for TLS 1.1. + * + * Requires: POLARSSL_MD5_C + * POLARSSL_SHA1_C + * + * Comment this macro to disable support for TLS 1.1 + */ +#define POLARSSL_SSL_PROTO_TLS1_1 + +/** + * \def POLARSSL_SSL_PROTO_TLS1_2 + * + * Enable support for TLS 1.2. + * + * Requires: POLARSSL_SHA1_C or POLARSSL_SHA256_C or POLARSSL_SHA512_C + * (Depends on ciphersuites) + * + * Comment this macro to disable support for TLS 1.2 + */ +#define POLARSSL_SSL_PROTO_TLS1_2 + +/** + * \def POLARSSL_SSL_ALPN + * + * Enable support for Application Layer Protocol Negotiation. + * draft-ietf-tls-applayerprotoneg-05 + * + * Comment this macro to disable support for ALPN. + */ +//#define POLARSSL_SSL_ALPN + +/** + * \def POLARSSL_SSL_SESSION_TICKETS + * + * Enable support for RFC 5077 session tickets in SSL. + * + * Requires: POLARSSL_AES_C + * POLARSSL_SHA256_C + * POLARSSL_CIPHER_MODE_CBC + * + * Comment this macro to disable support for SSL session tickets + */ +#define POLARSSL_SSL_SESSION_TICKETS + +/** + * \def POLARSSL_SSL_SERVER_NAME_INDICATION + * + * Enable support for RFC 6066 server name indication (SNI) in SSL. + * + * Comment this macro to disable support for server name indication in SSL + */ +#define POLARSSL_SSL_SERVER_NAME_INDICATION + +/** + * \def POLARSSL_SSL_TRUNCATED_HMAC + * + * Enable support for RFC 6066 truncated HMAC in SSL. + * + * Comment this macro to disable support for truncated HMAC in SSL + */ +#define POLARSSL_SSL_TRUNCATED_HMAC + +/** + * \def POLARSSL_SSL_SET_CURVES + * + * Enable ssl_set_curves(). + * + * This is disabled by default since it breaks binary compatibility with the + * 1.3.x line. If you choose to enable it, you will need to rebuild your + * application against the new header files, relinking will not be enough. + * It will be enabled by default, or no longer an option, in the 1.4 branch. + * + * Uncomment to make ssl_set_curves() available. + */ +//#define POLARSSL_SSL_SET_CURVES + +/** + * \def POLARSSL_THREADING_ALT + * + * Provide your own alternate threading implementation. + * + * Requires: POLARSSL_THREADING_C + * + * Uncomment this to allow your own alternate threading implementation. + */ +//#define POLARSSL_THREADING_ALT + +/** + * \def POLARSSL_THREADING_PTHREAD + * + * Enable the pthread wrapper layer for the threading layer. + * + * Requires: POLARSSL_THREADING_C + * + * Uncomment this to enable pthread mutexes. + */ +//#define POLARSSL_THREADING_PTHREAD + +/** + * \def POLARSSL_VERSION_FEATURES + * + * Allow run-time checking of compile-time enabled features. Thus allowing users + * to check at run-time if the library is for instance compiled with threading + * support via version_check_feature(). + * + * Requires: POLARSSL_VERSION_C + * + * Comment this to disable run-time checking and save ROM space + */ +//#define POLARSSL_VERSION_FEATURES + +/** + * \def POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3 + * + * If set, the X509 parser will not break-off when parsing an X509 certificate + * and encountering an extension in a v1 or v2 certificate. + * + * Uncomment to prevent an error. + */ +//#define POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3 + +/** + * \def POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + * + * If set, the X509 parser will not break-off when parsing an X509 certificate + * and encountering an unknown critical extension. + * + * Uncomment to prevent an error. + */ +//#define POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + +/** + * \def POLARSSL_X509_CHECK_KEY_USAGE + * + * Enable verification of the keyUsage extension (CA and leaf certificates). + * + * Disabling this avoids problems with mis-issued and/or misused + * (intermediate) CA and leaf certificates. + * + * \warning Depending on your PKI use, disabling this can be a security risk! + * + * Comment to skip keyUsage checking for both CA and leaf certificates. + */ +//#define POLARSSL_X509_CHECK_KEY_USAGE + +/** + * \def POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE + * + * Enable verification of the extendedKeyUsage extension (leaf certificates). + * + * Disabling this avoids problems with mis-issued and/or misused certificates. + * + * \warning Depending on your PKI use, disabling this can be a security risk! + * + * Comment to skip extendedKeyUsage checking for certificates. + */ +//#define POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE + +/** + * \def POLARSSL_X509_RSASSA_PSS_SUPPORT + * + * Enable parsing and verification of X.509 certificates, CRLs and CSRS + * signed with RSASSA-PSS (aka PKCS#1 v2.1). + * + * Comment this macro to disallow using RSASSA-PSS in certificates. + */ +//#define POLARSSL_X509_RSASSA_PSS_SUPPORT + +/** + * \def POLARSSL_ZLIB_SUPPORT + * + * If set, the SSL/TLS module uses ZLIB to support compression and + * decompression of packet data. + * + * \warning TLS-level compression MAY REDUCE SECURITY! See for example the + * CRIME attack. Before enabling this option, you should examine with care if + * CRIME or similar exploits may be a applicable to your use case. + * + * Used in: library/ssl_tls.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * This feature requires zlib library and headers to be present. + * + * Uncomment to enable use of ZLIB + */ +//#define POLARSSL_ZLIB_SUPPORT +/* \} name SECTION: PolarSSL feature support */ + +/** + * \name SECTION: PolarSSL modules + * + * This section enables or disables entire modules in PolarSSL + * \{ + */ + +/** + * \def POLARSSL_AESNI_C + * + * Enable AES-NI support on x86-64. + * + * Module: library/aesni.c + * Caller: library/aes.c + * + * Requires: POLARSSL_HAVE_ASM + * + * This modules adds support for the AES-NI instructions on x86-64 + */ +//#define POLARSSL_AESNI_C + +/** + * \def POLARSSL_AES_C + * + * Enable the AES block cipher. + * + * Module: library/aes.c + * Caller: library/ssl_tls.c + * library/pem.c + * library/ctr_drbg.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + * TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + * TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + * TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + * TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + * TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + * TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + * TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + * TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + * TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + * TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + * TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + * TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + * TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + * TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + * TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + * TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + * TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + * TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + * TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + * TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + * TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + * TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * TLS_RSA_WITH_AES_256_GCM_SHA384 + * TLS_RSA_WITH_AES_256_CBC_SHA256 + * TLS_RSA_WITH_AES_256_CBC_SHA + * TLS_RSA_WITH_AES_128_GCM_SHA256 + * TLS_RSA_WITH_AES_128_CBC_SHA256 + * TLS_RSA_WITH_AES_128_CBC_SHA + * TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * TLS_PSK_WITH_AES_256_GCM_SHA384 + * TLS_PSK_WITH_AES_256_CBC_SHA384 + * TLS_PSK_WITH_AES_256_CBC_SHA + * TLS_PSK_WITH_AES_128_GCM_SHA256 + * TLS_PSK_WITH_AES_128_CBC_SHA256 + * TLS_PSK_WITH_AES_128_CBC_SHA + * + * PEM_PARSE uses AES for decrypting encrypted keys. + */ +#define POLARSSL_AES_C + +/** + * \def POLARSSL_ARC4_C + * + * Enable the ARCFOUR stream cipher. + * + * Module: library/arc4.c + * Caller: library/ssl_tls.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDH_ECDSA_WITH_RC4_128_SHA + * TLS_ECDH_RSA_WITH_RC4_128_SHA + * TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + * TLS_ECDHE_RSA_WITH_RC4_128_SHA + * TLS_ECDHE_PSK_WITH_RC4_128_SHA + * TLS_DHE_PSK_WITH_RC4_128_SHA + * TLS_RSA_WITH_RC4_128_SHA + * TLS_RSA_WITH_RC4_128_MD5 + * TLS_RSA_PSK_WITH_RC4_128_SHA + * TLS_PSK_WITH_RC4_128_SHA + */ +//#define POLARSSL_ARC4_C + +/** + * \def POLARSSL_ASN1_PARSE_C + * + * Enable the generic ASN1 parser. + * + * Module: library/asn1.c + * Caller: library/x509.c + * library/dhm.c + * library/pkcs12.c + * library/pkcs5.c + * library/pkparse.c + */ +#define POLARSSL_ASN1_PARSE_C + +/** + * \def POLARSSL_ASN1_WRITE_C + * + * Enable the generic ASN1 writer. + * + * Module: library/asn1write.c + * Caller: library/ecdsa.c + * library/pkwrite.c + * library/x509_create.c + * library/x509write_crt.c + * library/x509write_csr.c + */ +//#define POLARSSL_ASN1_WRITE_C + +/** + * \def POLARSSL_BASE64_C + * + * Enable the Base64 module. + * + * Module: library/base64.c + * Caller: library/pem.c + * + * This module is required for PEM support (required by X.509). + */ +//#define POLARSSL_BASE64_C + +/** + * \def POLARSSL_BIGNUM_C + * + * Enable the multi-precision integer library. + * + * Module: library/bignum.c + * Caller: library/dhm.c + * library/ecp.c + * library/ecdsa.c + * library/rsa.c + * library/ssl_tls.c + * + * This module is required for RSA, DHM and ECC (ECDH, ECDSA) support. + */ +#define POLARSSL_BIGNUM_C + +/** + * \def POLARSSL_BLOWFISH_C + * + * Enable the Blowfish block cipher. + * + * Module: library/blowfish.c + */ +//#define POLARSSL_BLOWFISH_C + +/** + * \def POLARSSL_CAMELLIA_C + * + * Enable the Camellia block cipher. + * + * Module: library/camellia.c + * Caller: library/ssl_tls.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 + */ +//#define POLARSSL_CAMELLIA_C + +/** + * \def POLARSSL_CCM_C + * + * Enable the Counter with CBC-MAC (CCM) mode for 128-bit block cipher. + * + * Module: library/ccm.c + * + * Requires: POLARSSL_AES_C or POLARSSL_CAMELLIA_C + * + * This module enables the AES-CCM ciphersuites, if other requisites are + * enabled as well. + */ +//#define POLARSSL_CCM_C + +/** + * \def POLARSSL_CERTS_C + * + * Enable the test certificates. + * + * Module: library/certs.c + * Caller: + * + * Requires: POLARSSL_PEM_PARSE_C + * + * This module is used for testing (ssl_client/server). + */ +//#define POLARSSL_CERTS_C + +/** + * \def POLARSSL_CIPHER_C + * + * Enable the generic cipher layer. + * + * Module: library/cipher.c + * Caller: library/ssl_tls.c + * + * Uncomment to enable generic cipher wrappers. + */ +#define POLARSSL_CIPHER_C + +/** + * \def POLARSSL_CTR_DRBG_C + * + * Enable the CTR_DRBG AES-256-based random generator. + * + * Module: library/ctr_drbg.c + * Caller: + * + * Requires: POLARSSL_AES_C + * + * This module provides the CTR_DRBG AES-256 random number generator. + */ +//#define POLARSSL_CTR_DRBG_C + +/** + * \def POLARSSL_DEBUG_C + * + * Enable the debug functions. + * + * Module: library/debug.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module provides debugging functions. + */ +//#define POLARSSL_DEBUG_C + +/** + * \def POLARSSL_DES_C + * + * Enable the DES block cipher. + * + * Module: library/des.c + * Caller: library/pem.c + * library/ssl_tls.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + * TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + * TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA + * TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA + * TLS_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA + * TLS_PSK_WITH_3DES_EDE_CBC_SHA + * + * PEM_PARSE uses DES/3DES for decrypting encrypted keys. + */ +//#define POLARSSL_DES_C + +/** + * \def POLARSSL_DHM_C + * + * Enable the Diffie-Hellman-Merkle module. + * + * Module: library/dhm.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module is used by the following key exchanges: + * DHE-RSA, DHE-PSK + */ +//#define POLARSSL_DHM_C + +/** + * \def POLARSSL_ECDH_C + * + * Enable the elliptic curve Diffie-Hellman library. + * + * Module: library/ecdh.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA, ECDHE-RSA, DHE-PSK + * + * Requires: POLARSSL_ECP_C + */ +//#define POLARSSL_ECDH_C + +/** + * \def POLARSSL_ECDSA_C + * + * Enable the elliptic curve DSA library. + * + * Module: library/ecdsa.c + * Caller: + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA + * + * Requires: POLARSSL_ECP_C, POLARSSL_ASN1_WRITE_C, POLARSSL_ASN1_PARSE_C + */ +//#define POLARSSL_ECDSA_C + +/** + * \def POLARSSL_ECP_C + * + * Enable the elliptic curve over GF(p) library. + * + * Module: library/ecp.c + * Caller: library/ecdh.c + * library/ecdsa.c + * + * Requires: POLARSSL_BIGNUM_C and at least one POLARSSL_ECP_DP_XXX_ENABLED + */ +//#define POLARSSL_ECP_C + +/** + * \def POLARSSL_ENTROPY_C + * + * Enable the platform-specific entropy code. + * + * Module: library/entropy.c + * Caller: + * + * Requires: POLARSSL_SHA512_C or POLARSSL_SHA256_C + * + * This module provides a generic entropy pool + */ +//#define POLARSSL_ENTROPY_C + +/** + * \def POLARSSL_ERROR_C + * + * Enable error code to error string conversion. + * + * Module: library/error.c + * Caller: + * + * This module enables polarssl_strerror(). + */ +//#define POLARSSL_ERROR_C + +/** + * \def POLARSSL_GCM_C + * + * Enable the Galois/Counter Mode (GCM) for AES. + * + * Module: library/gcm.c + * + * Requires: POLARSSL_AES_C or POLARSSL_CAMELLIA_C + * + * This module enables the AES-GCM and CAMELLIA-GCM ciphersuites, if other + * requisites are enabled as well. + */ +//#define POLARSSL_GCM_C + +/** + * \def POLARSSL_HAVEGE_C + * + * Enable the HAVEGE random generator. + * + * Warning: the HAVEGE random generator is not suitable for virtualized + * environments + * + * Warning: the HAVEGE random generator is dependent on timing and specific + * processor traits. It is therefore not advised to use HAVEGE as + * your applications primary random generator or primary entropy pool + * input. As a secondary input to your entropy pool, it IS able add + * the (limited) extra entropy it provides. + * + * Module: library/havege.c + * Caller: + * + * Requires: POLARSSL_TIMING_C + * + * Uncomment to enable the HAVEGE random generator. + */ +//#define POLARSSL_HAVEGE_C + +/** + * \def POLARSSL_HMAC_DRBG_C + * + * Enable the HMAC_DRBG random generator. + * + * Module: library/hmac_drbg.c + * Caller: + * + * Requires: POLARSSL_MD_C + * + * Uncomment to enable the HMAC_DRBG random number geerator. + */ +//#define POLARSSL_HMAC_DRBG_C + +/** + * \def POLARSSL_MD_C + * + * Enable the generic message digest layer. + * + * Module: library/md.c + * Caller: + * + * Uncomment to enable generic message digest wrappers. + */ +#define POLARSSL_MD_C + +/** + * \def POLARSSL_MD2_C + * + * Enable the MD2 hash algorithm. + * + * Module: library/md2.c + * Caller: + * + * Uncomment to enable support for (rare) MD2-signed X.509 certs. + */ +//#define POLARSSL_MD2_C + +/** + * \def POLARSSL_MD4_C + * + * Enable the MD4 hash algorithm. + * + * Module: library/md4.c + * Caller: + * + * Uncomment to enable support for (rare) MD4-signed X.509 certs. + */ +//#define POLARSSL_MD4_C + +/** + * \def POLARSSL_MD5_C + * + * Enable the MD5 hash algorithm. + * + * Module: library/md5.c + * Caller: library/md.c + * library/pem.c + * library/ssl_tls.c + * + * This module is required for SSL/TLS and X.509. + * PEM_PARSE uses MD5 for decrypting encrypted keys. + */ +#define POLARSSL_MD5_C + +/** + * \def POLARSSL_MEMORY_C + * Deprecated since 1.3.5. Please use POLARSSL_PLATFORM_MEMORY instead. + */ +#define POLARSSL_MEMORY_C + +/** + * \def POLARSSL_MEMORY_BUFFER_ALLOC_C + * + * Enable the buffer allocator implementation that makes use of a (stack) + * based buffer to 'allocate' dynamic memory. (replaces malloc() and free() + * calls) + * + * Module: library/memory_buffer_alloc.c + * + * Requires: POLARSSL_PLATFORM_C + * POLARSSL_PLATFORM_MEMORY (to use it within PolarSSL) + * + * Enable this module to enable the buffer memory allocator. + */ +//#define POLARSSL_MEMORY_BUFFER_ALLOC_C + +/** + * \def POLARSSL_NET_C + * + * Enable the TCP/IP networking routines. + * + * Module: library/net.c + * + * This module provides TCP/IP networking routines. + */ +#define POLARSSL_NET_C + +/** + * \def POLARSSL_OID_C + * + * Enable the OID database. + * + * Module: library/oid.c + * Caller: library/asn1write.c + * library/pkcs5.c + * library/pkparse.c + * library/pkwrite.c + * library/rsa.c + * library/x509.c + * library/x509_create.c + * library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * library/x509write_crt.c + * library/x509write_csr.c + * + * This modules translates between OIDs and internal values. + */ +#define POLARSSL_OID_C + +/** + * \def POLARSSL_PADLOCK_C + * + * Enable VIA Padlock support on x86. + * + * Module: library/padlock.c + * Caller: library/aes.c + * + * Requires: POLARSSL_HAVE_ASM + * + * This modules adds support for the VIA PadLock on x86. + */ +//#define POLARSSL_PADLOCK_C + +/** + * \def POLARSSL_PBKDF2_C + * + * Enable PKCS#5 PBKDF2 key derivation function. + * DEPRECATED: Use POLARSSL_PKCS5_C instead + * + * Module: library/pbkdf2.c + * + * Requires: POLARSSL_PKCS5_C + * + * This module adds support for the PKCS#5 PBKDF2 key derivation function. + */ +//#define POLARSSL_PBKDF2_C + +/** + * \def POLARSSL_PEM_PARSE_C + * + * Enable PEM decoding / parsing. + * + * Module: library/pem.c + * Caller: library/dhm.c + * library/pkparse.c + * library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * + * Requires: POLARSSL_BASE64_C + * + * This modules adds support for decoding / parsing PEM files. + */ +//#define POLARSSL_PEM_PARSE_C + +/** + * \def POLARSSL_PEM_WRITE_C + * + * Enable PEM encoding / writing. + * + * Module: library/pem.c + * Caller: library/pkwrite.c + * library/x509write_crt.c + * library/x509write_csr.c + * + * Requires: POLARSSL_BASE64_C + * + * This modules adds support for encoding / writing PEM files. + */ +//#define POLARSSL_PEM_WRITE_C + +/** + * \def POLARSSL_PK_C + * + * Enable the generic public (asymetric) key layer. + * + * Module: library/pk.c + * Caller: library/ssl_tls.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: POLARSSL_RSA_C or POLARSSL_ECP_C + * + * Uncomment to enable generic public key wrappers. + */ +#define POLARSSL_PK_C + +/** + * \def POLARSSL_PK_PARSE_C + * + * Enable the generic public (asymetric) key parser. + * + * Module: library/pkparse.c + * Caller: library/x509_crt.c + * library/x509_csr.c + * + * Requires: POLARSSL_PK_C + * + * Uncomment to enable generic public key parse functions. + */ +#define POLARSSL_PK_PARSE_C + +/** + * \def POLARSSL_PK_WRITE_C + * + * Enable the generic public (asymetric) key writer. + * + * Module: library/pkwrite.c + * Caller: library/x509write.c + * + * Requires: POLARSSL_PK_C + * + * Uncomment to enable generic public key write functions. + */ +//#define POLARSSL_PK_WRITE_C + +/** + * \def POLARSSL_PKCS5_C + * + * Enable PKCS#5 functions. + * + * Module: library/pkcs5.c + * + * Requires: POLARSSL_MD_C + * + * This module adds support for the PKCS#5 functions. + */ +//#define POLARSSL_PKCS5_C + +/** + * \def POLARSSL_PKCS11_C + * + * Enable wrapper for PKCS#11 smartcard support. + * + * Module: library/pkcs11.c + * Caller: library/pk.c + * + * Requires: POLARSSL_PK_C + * + * This module enables SSL/TLS PKCS #11 smartcard support. + * Requires the presence of the PKCS#11 helper library (libpkcs11-helper) + */ +//#define POLARSSL_PKCS11_C + +/** + * \def POLARSSL_PKCS12_C + * + * Enable PKCS#12 PBE functions. + * Adds algorithms for parsing PKCS#8 encrypted private keys + * + * Module: library/pkcs12.c + * Caller: library/pkparse.c + * + * Requires: POLARSSL_ASN1_PARSE_C, POLARSSL_CIPHER_C, POLARSSL_MD_C + * Can use: POLARSSL_ARC4_C + * + * This module enables PKCS#12 functions. + */ +//#define POLARSSL_PKCS12_C + +/** + * \def POLARSSL_PLATFORM_C + * + * Enable the platform abstraction layer that allows you to re-assign + * functions like malloc(), free(), printf(), fprintf() + * + * Module: library/platform.c + * Caller: Most other .c files + * + * This module enables abstraction of common (libc) functions. + */ +#define POLARSSL_PLATFORM_C + +/** + * \def POLARSSL_RIPEMD160_C + * + * Enable the RIPEMD-160 hash algorithm. + * + * Module: library/ripemd160.c + * Caller: library/md.c + * + */ +//#define POLARSSL_RIPEMD160_C + +/** + * \def POLARSSL_RSA_C + * + * Enable the RSA public-key cryptosystem. + * + * Module: library/rsa.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509.c + * + * This module is used by the following key exchanges: + * RSA, DHE-RSA, ECDHE-RSA, RSA-PSK + * + * Requires: POLARSSL_BIGNUM_C, POLARSSL_OID_C + */ +#define POLARSSL_RSA_C + +/** + * \def POLARSSL_SHA1_C + * + * Enable the SHA1 cryptographic hash algorithm. + * + * Module: library/sha1.c + * Caller: library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509write_crt.c + * + * This module is required for SSL/TLS and SHA1-signed certificates. + */ +#define POLARSSL_SHA1_C + +/** + * \def POLARSSL_SHA256_C + * + * Enable the SHA-224 and SHA-256 cryptographic hash algorithms. + * (Used to be POLARSSL_SHA2_C) + * + * Module: library/sha256.c + * Caller: library/entropy.c + * library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module adds support for SHA-224 and SHA-256. + * This module is required for the SSL/TLS 1.2 PRF function. + */ +#define POLARSSL_SHA256_C + +/** + * \def POLARSSL_SHA512_C + * + * Enable the SHA-384 and SHA-512 cryptographic hash algorithms. + * (Used to be POLARSSL_SHA4_C) + * + * Module: library/sha512.c + * Caller: library/entropy.c + * library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * This module adds support for SHA-384 and SHA-512. + */ +#define POLARSSL_SHA512_C + +/** + * \def POLARSSL_SSL_CACHE_C + * + * Enable simple SSL cache implementation. + * + * Module: library/ssl_cache.c + * Caller: + * + * Requires: POLARSSL_SSL_CACHE_C + */ +#define POLARSSL_SSL_CACHE_C + +/** + * \def POLARSSL_SSL_CLI_C + * + * Enable the SSL/TLS client code. + * + * Module: library/ssl_cli.c + * Caller: + * + * Requires: POLARSSL_SSL_TLS_C + * + * This module is required for SSL/TLS client support. + */ +#define POLARSSL_SSL_CLI_C + +/** + * \def POLARSSL_SSL_SRV_C + * + * Enable the SSL/TLS server code. + * + * Module: library/ssl_srv.c + * Caller: + * + * Requires: POLARSSL_SSL_TLS_C + * + * This module is required for SSL/TLS server support. + */ +//#define POLARSSL_SSL_SRV_C + +/** + * \def POLARSSL_SSL_TLS_C + * + * Enable the generic SSL/TLS code. + * + * Module: library/ssl_tls.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: POLARSSL_CIPHER_C, POLARSSL_MD_C + * and at least one of the POLARSSL_SSL_PROTO_* defines + * + * This module is required for SSL/TLS. + */ +#define POLARSSL_SSL_TLS_C + +/** + * \def POLARSSL_THREADING_C + * + * Enable the threading abstraction layer. + * By default PolarSSL assumes it is used in a non-threaded environment or that + * contexts are not shared between threads. If you do intend to use contexts + * between threads, you will need to enable this layer to prevent race + * conditions. + * + * Module: library/threading.c + * + * This allows different threading implementations (self-implemented or + * provided). + * + * You will have to enable either POLARSSL_THREADING_ALT or + * POLARSSL_THREADING_PTHREAD. + * + * Enable this layer to allow use of mutexes within PolarSSL + */ +//#define POLARSSL_THREADING_C + +/** + * \def POLARSSL_TIMING_C + * + * Enable the portable timing interface. + * + * Module: library/timing.c + * Caller: library/havege.c + * + * This module is used by the HAVEGE random number generator. + */ +//#define POLARSSL_TIMING_C + +/** + * \def POLARSSL_VERSION_C + * + * Enable run-time version information. + * + * Module: library/version.c + * + * This module provides run-time version information. + */ +#define POLARSSL_VERSION_C + +/** + * \def POLARSSL_X509_USE_C + * + * Enable X.509 core for using certificates. + * + * Module: library/x509.c + * Caller: library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * + * Requires: POLARSSL_ASN1_PARSE_C, POLARSSL_BIGNUM_C, POLARSSL_OID_C, + * POLARSSL_PK_PARSE_C + * + * This module is required for the X.509 parsing modules. + */ +#define POLARSSL_X509_USE_C + +/** + * \def POLARSSL_X509_CRT_PARSE_C + * + * Enable X.509 certificate parsing. + * + * Module: library/x509_crt.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * Requires: POLARSSL_X509_USE_C + * + * This module is required for X.509 certificate parsing. + */ +#define POLARSSL_X509_CRT_PARSE_C + +/** + * \def POLARSSL_X509_CRL_PARSE_C + * + * Enable X.509 CRL parsing. + * + * Module: library/x509_crl.c + * Caller: library/x509_crt.c + * + * Requires: POLARSSL_X509_USE_C + * + * This module is required for X.509 CRL parsing. + */ +//#define POLARSSL_X509_CRL_PARSE_C + +/** + * \def POLARSSL_X509_CSR_PARSE_C + * + * Enable X.509 Certificate Signing Request (CSR) parsing. + * + * Module: library/x509_csr.c + * Caller: library/x509_crt_write.c + * + * Requires: POLARSSL_X509_USE_C + * + * This module is used for reading X.509 certificate request. + */ +//#define POLARSSL_X509_CSR_PARSE_C + +/** + * \def POLARSSL_X509_CREATE_C + * + * Enable X.509 core for creating certificates. + * + * Module: library/x509_create.c + * + * Requires: POLARSSL_BIGNUM_C, POLARSSL_OID_C, POLARSSL_PK_WRITE_C + * + * This module is the basis for creating X.509 certificates and CSRs. + */ +//#define POLARSSL_X509_CREATE_C + +/** + * \def POLARSSL_X509_CRT_WRITE_C + * + * Enable creating X.509 certificates. + * + * Module: library/x509_crt_write.c + * + * Requires: POLARSSL_CREATE_C + * + * This module is required for X.509 certificate creation. + */ +//#define POLARSSL_X509_CRT_WRITE_C + +/** + * \def POLARSSL_X509_CSR_WRITE_C + * + * Enable creating X.509 Certificate Signing Requests (CSR). + * + * Module: library/x509_csr_write.c + * + * Requires: POLARSSL_CREATE_C + * + * This module is required for X.509 certificate request writing. + */ +//#define POLARSSL_X509_CSR_WRITE_C + +/** + * \def POLARSSL_XTEA_C + * + * Enable the XTEA block cipher. + * + * Module: library/xtea.c + * Caller: + */ +//#define POLARSSL_XTEA_C + +/* \} name SECTION: PolarSSL modules */ + +/** + * \name SECTION: Module configuration options + * + * This section allows for the setting of module specific sizes and + * configuration options. The default values are already present in the + * relevant header files and should suffice for the regular use cases. + * + * Our advice is to enable options and change their values here + * only if you have a good reason and know the consequences. + * + * Please check the respective header file for documentation on these + * parameters (to prevent duplicate documentation). + * \{ + */ + +/* MPI / BIGNUM options */ +//#define POLARSSL_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */ +//#define POLARSSL_MPI_MAX_SIZE 512 /**< Maximum number of bytes for usable MPIs. */ + +/* CTR_DRBG options */ +//#define CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */ +//#define CTR_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +//#define CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +//#define CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +//#define CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ + +/* HMAC_DRBG options */ +//#define POLARSSL_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +//#define POLARSSL_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +//#define POLARSSL_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +//#define POLARSSL_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ + +/* ECP options */ +//#define POLARSSL_ECP_MAX_BITS 521 /**< Maximum bit size of groups */ +//#define POLARSSL_ECP_WINDOW_SIZE 6 /**< Maximum window size used */ +//#define POLARSSL_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up */ + +/* Entropy options */ +//#define ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ +//#define ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ + +/* Memory buffer allocator options */ +//#define POLARSSL_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */ + +/* Platform options */ +//#define POLARSSL_PLATFORM_STD_MEM_HDR /**< Header to include if POLARSSL_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is needed. */ +//#define POLARSSL_PLATFORM_STD_MALLOC malloc /**< Default allocator to use, can be undefined */ +//#define POLARSSL_PLATFORM_STD_FREE free /**< Default free to use, can be undefined */ +//#define POLARSSL_PLATFORM_STD_PRINTF printf /**< Default printf to use, can be undefined */ +//#define POLARSSL_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use, can be undefined */ + +/* SSL Cache options */ +//#define SSL_CACHE_DEFAULT_TIMEOUT 86400 /**< 1 day */ +//#define SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /**< Maximum entries in cache */ + +/* SSL options */ +#define SSL_MAX_CONTENT_LEN 4096 /**< Size of the input / output buffer */ +//#define SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ +//#define POLARSSL_PSK_MAX_LEN 32 /**< Max size of TLS pre-shared keys, in bytes (default 256 bits) */ + +/* Realteck Ameba HW Crypto */ +#define RTL_HW_CRYPTO + +/** + * Complete list of ciphersuites to use, in order of preference. + * + * \warning No dependency checking is done on that field! This option can only + * be used to restrict the set of available ciphersuites. It is your + * responsibility to make sure the needed modules are active. + * + * Use this to save a few hundred bytes of ROM (default ordering of all + * available ciphersuites) and a few to a few hundred bytes of RAM. + * + * The value below is only an example, not the default. + */ +//#define SSL_CIPHERSUITES TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + +/* Debug options */ +//#define POLARSSL_DEBUG_DFL_MODE POLARSSL_DEBUG_LOG_FULL /**< Default log: Full or Raw */ + +/* \} name SECTION: Module configuration options */ + +#include "check_config.h" + +#endif /* POLARSSL_CONFIG_H */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/config_srp.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/config_srp.h new file mode 100644 index 0000000..fa174a4 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/config_srp.h @@ -0,0 +1,2194 @@ +/** + * \file config.h + * + * \brief Configuration options (set of defines) + * + * Copyright (C) 2006-2013, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * This set of compile-time options may be used to enable + * or disable features selectively, and reduce the global + * memory footprint. + */ +#ifndef POLARSSL_CONFIG_H +#define POLARSSL_CONFIG_H + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif + +/** + * \name SECTION: System support + * + * This section sets system specific settings. + * \{ + */ + +/** + * \def POLARSSL_HAVE_INT8 + * + * The system uses 8-bit wide native integers. + * + * Uncomment if native integers are 8-bit wide. + */ +//#define POLARSSL_HAVE_INT8 + +/** + * \def POLARSSL_HAVE_INT16 + * + * The system uses 16-bit wide native integers. + * + * Uncomment if native integers are 16-bit wide. + */ +//#define POLARSSL_HAVE_INT16 + +/** + * \def POLARSSL_HAVE_LONGLONG + * + * The compiler supports the 'long long' type. + * (Only used on 32-bit platforms) + */ +#define POLARSSL_HAVE_LONGLONG + +/** + * \def POLARSSL_HAVE_ASM + * + * The compiler has support for asm(). + * + * Requires support for asm() in compiler. + * + * Used in: + * library/timing.c + * library/padlock.c + * include/polarssl/bn_mul.h + * + * Comment to disable the use of assembly code. + */ +//#define POLARSSL_HAVE_ASM + +/** + * \def POLARSSL_HAVE_SSE2 + * + * CPU supports SSE2 instruction set. + * + * Uncomment if the CPU supports SSE2 (IA-32 specific). + */ +//#define POLARSSL_HAVE_SSE2 + +/** + * \def POLARSSL_HAVE_TIME + * + * System has time.h and time() / localtime() / gettimeofday(). + * + * Comment if your system does not support time functions + */ +//#define POLARSSL_HAVE_TIME + +/** + * \def POLARSSL_HAVE_IPV6 + * + * System supports the basic socket interface for IPv6 (RFC 3493), + * specifically getaddrinfo(), freeaddrinfo() and struct sockaddr_storage. + * + * Note: on Windows/MingW, XP or higher is required. + * + * Comment if your system does not support the IPv6 socket interface + */ +//#define POLARSSL_HAVE_IPV6 +/* \} name SECTION: System support */ + +/** + * \name SECTION: PolarSSL feature support + * + * This section sets support for features that are or are not needed + * within the modules that are enabled. + * \{ + */ + +/** + * \def POLARSSL_XXX_ALT + * + * Uncomment a macro to let PolarSSL use your alternate core implementation of + * a symmetric or hash algorithm (e.g. platform specific assembly optimized + * implementations). Keep in mind that the function prototypes should remain + * the same. + * + * Example: In case you uncomment POLARSSL_AES_ALT, PolarSSL will no longer + * provide the "struct aes_context" definition and omit the base function + * declarations and implementations. "aes_alt.h" will be included from + * "aes.h" to include the new function definitions. + * + * Uncomment a macro to enable alternate implementation for core algorithm + * functions + */ +//#define POLARSSL_AES_ALT +//#define POLARSSL_ARC4_ALT +//#define POLARSSL_BLOWFISH_ALT +//#define POLARSSL_CAMELLIA_ALT +//#define POLARSSL_DES_ALT +//#define POLARSSL_XTEA_ALT +//#define POLARSSL_MD2_ALT +//#define POLARSSL_MD4_ALT +//#define POLARSSL_MD5_ALT +//#define POLARSSL_SHA1_ALT +//#define POLARSSL_SHA256_ALT +//#define POLARSSL_SHA512_ALT + +/** + * \def POLARSSL_AES_ROM_TABLES + * + * Store the AES tables in ROM. + * + * Uncomment this macro to store the AES tables in ROM. + * + */ +#define POLARSSL_AES_ROM_TABLES + +/** + * \def POLARSSL_CIPHER_MODE_CBC + * + * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers. + */ +#define POLARSSL_CIPHER_MODE_CBC + +/** + * \def POLARSSL_CIPHER_MODE_CFB + * + * Enable Cipher Feedback mode (CFB) for symmetric ciphers. + */ +#define POLARSSL_CIPHER_MODE_CFB + +/** + * \def POLARSSL_CIPHER_MODE_CTR + * + * Enable Counter Block Cipher mode (CTR) for symmetric ciphers. + */ +#define POLARSSL_CIPHER_MODE_CTR + +/** + * \def POLARSSL_CIPHER_NULL_CIPHER + * + * Enable NULL cipher. + * Warning: Only do so when you know what you are doing. This allows for + * encryption or channels without any security! + * + * Requires POLARSSL_ENABLE_WEAK_CIPHERSUITES as well to enable + * the following ciphersuites: + * TLS_ECDH_ECDSA_WITH_NULL_SHA + * TLS_ECDH_RSA_WITH_NULL_SHA + * TLS_ECDHE_ECDSA_WITH_NULL_SHA + * TLS_ECDHE_RSA_WITH_NULL_SHA + * TLS_ECDHE_PSK_WITH_NULL_SHA384 + * TLS_ECDHE_PSK_WITH_NULL_SHA256 + * TLS_ECDHE_PSK_WITH_NULL_SHA + * TLS_DHE_PSK_WITH_NULL_SHA384 + * TLS_DHE_PSK_WITH_NULL_SHA256 + * TLS_DHE_PSK_WITH_NULL_SHA + * TLS_RSA_WITH_NULL_SHA256 + * TLS_RSA_WITH_NULL_SHA + * TLS_RSA_WITH_NULL_MD5 + * TLS_RSA_PSK_WITH_NULL_SHA384 + * TLS_RSA_PSK_WITH_NULL_SHA256 + * TLS_RSA_PSK_WITH_NULL_SHA + * TLS_PSK_WITH_NULL_SHA384 + * TLS_PSK_WITH_NULL_SHA256 + * TLS_PSK_WITH_NULL_SHA + * + * Uncomment this macro to enable the NULL cipher and ciphersuites +#define POLARSSL_CIPHER_NULL_CIPHER + */ + +/** + * \def POLARSSL_CIPHER_PADDING_XXX + * + * Uncomment or comment macros to add support for specific padding modes + * in the cipher layer with cipher modes that support padding (e.g. CBC) + * + * If you disable all padding modes, only full blocks can be used with CBC. + * + * Enable padding modes in the cipher layer. + */ +#define POLARSSL_CIPHER_PADDING_PKCS7 +#define POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS +#define POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN +#define POLARSSL_CIPHER_PADDING_ZEROS + +/** + * \def POLARSSL_ENABLE_WEAK_CIPHERSUITES + * + * Enable weak ciphersuites in SSL / TLS. + * Warning: Only do so when you know what you are doing. This allows for + * channels with virtually no security at all! + * + * This enables the following ciphersuites: + * TLS_RSA_WITH_DES_CBC_SHA + * TLS_DHE_RSA_WITH_DES_CBC_SHA + * + * Uncomment this macro to enable weak ciphersuites +#define POLARSSL_ENABLE_WEAK_CIPHERSUITES + */ + +/** + * \def POLARSSL_ECP_XXXX_ENABLED + * + * Enables specific curves within the Elliptic Curve module. + * By default all supported curves are enabled. + * + * Comment macros to disable the curve and functions for it + */ +#define POLARSSL_ECP_DP_SECP192R1_ENABLED +#define POLARSSL_ECP_DP_SECP224R1_ENABLED +#define POLARSSL_ECP_DP_SECP256R1_ENABLED +#define POLARSSL_ECP_DP_SECP384R1_ENABLED +#define POLARSSL_ECP_DP_SECP521R1_ENABLED +#define POLARSSL_ECP_DP_BP256R1_ENABLED +#define POLARSSL_ECP_DP_BP384R1_ENABLED +#define POLARSSL_ECP_DP_BP512R1_ENABLED +//#define POLARSSL_ECP_DP_M221_ENABLED // Not implemented yet! +#define POLARSSL_ECP_DP_M255_ENABLED +//#define POLARSSL_ECP_DP_M383_ENABLED // Not implemented yet! +//#define POLARSSL_ECP_DP_M511_ENABLED // Not implemented yet! + +/** + * \def POLARSSL_ECP_NIST_OPTIM + * + * Enable specific 'modulo p' routines for each NIST prime. + * Depending on the prime and architecture, makes operations 4 to 8 times + * faster on the corresponding curve. + * + * Comment this macro to disable NIST curves optimisation. + */ +#define POLARSSL_ECP_NIST_OPTIM + +/** + * \def POLARSSL_KEY_EXCHANGE_SRP_ENABLED + * + * Enable the SRP based ciphersuite modes in SSL / TLS. + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_SRP_WITH_AES_256_CBC_SHA + */ +#define POLARSSL_KEY_EXCHANGE_SRP_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_PSK_ENABLED + * + * Enable the PSK based ciphersuite modes in SSL / TLS. + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_PSK_WITH_AES_256_GCM_SHA384 + * TLS_PSK_WITH_AES_256_CBC_SHA384 + * TLS_PSK_WITH_AES_256_CBC_SHA + * TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_PSK_WITH_AES_128_GCM_SHA256 + * TLS_PSK_WITH_AES_128_CBC_SHA256 + * TLS_PSK_WITH_AES_128_CBC_SHA + * TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_PSK_WITH_3DES_EDE_CBC_SHA + * TLS_PSK_WITH_RC4_128_SHA + */ +//#define POLARSSL_KEY_EXCHANGE_PSK_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED + * + * Enable the DHE-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_DHM_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA + * TLS_DHE_PSK_WITH_RC4_128_SHA + */ +//#define POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED + * + * Enable the ECDHE-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_ECDH_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA + * TLS_ECDHE_PSK_WITH_RC4_128_SHA + */ +//#define POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED + * + * Enable the RSA-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_RSA_C, POLARSSL_PKCS1_V15, + * POLARSSL_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA + * TLS_RSA_PSK_WITH_RC4_128_SHA + */ +//#define POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_RSA_ENABLED + * + * Enable the RSA-only based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_RSA_C, POLARSSL_PKCS1_V15, + * POLARSSL_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_RSA_WITH_AES_256_GCM_SHA384 + * TLS_RSA_WITH_AES_256_CBC_SHA256 + * TLS_RSA_WITH_AES_256_CBC_SHA + * TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * TLS_RSA_WITH_AES_128_GCM_SHA256 + * TLS_RSA_WITH_AES_128_CBC_SHA256 + * TLS_RSA_WITH_AES_128_CBC_SHA + * TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * TLS_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_RSA_WITH_RC4_128_SHA + * TLS_RSA_WITH_RC4_128_MD5 + */ +//#define POLARSSL_KEY_EXCHANGE_RSA_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED + * + * Enable the DHE-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_DHM_C, POLARSSL_RSA_C, POLARSSL_PKCS1_V15, + * POLARSSL_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + * TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + */ +//#define POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED + * + * Enable the ECDHE-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_ECDH_C, POLARSSL_RSA_C, POLARSSL_PKCS1_V15, + * POLARSSL_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + * TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + * TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + * TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + * TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + * TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_ECDHE_RSA_WITH_RC4_128_SHA + */ +//#define POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + * + * Enable the ECDHE-ECDSA based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_ECDH_C, POLARSSL_ECDSA_C, POLARSSL_X509_CRT_PARSE_C, + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + * TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + * TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + * TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + */ +//#define POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED + * + * Enable the ECDH-ECDSA based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_ECDH_C, POLARSSL_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDH_ECDSA_WITH_RC4_128_SHA + * TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + * TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + * TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + * TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + * TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + * TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + * TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + * TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + */ +//#define POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED + * + * Enable the ECDH-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_ECDH_C, POLARSSL_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDH_RSA_WITH_RC4_128_SHA + * TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + * TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + * TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + * TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + * TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + * TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + * TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 + */ +//#define POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED + +/** + * \def POLARSSL_ERROR_STRERROR_BC + * + * Make available the backward compatible error_strerror() next to the + * current polarssl_strerror(). + * + * Disable if you run into name conflicts and want to really remove the + * error_strerror() + */ +#define POLARSSL_ERROR_STRERROR_BC + +/** + * \def POLARSSL_ERROR_STRERROR_DUMMY + * + * Enable a dummy error function to make use of polarssl_strerror() in + * third party libraries easier. + * + * Disable if you run into name conflicts and want to really remove the + * polarssl_strerror() + */ +#define POLARSSL_ERROR_STRERROR_DUMMY + +/** + * \def POLARSSL_GENPRIME + * + * Enable the prime-number generation code. + * + * Requires: POLARSSL_BIGNUM_C + */ +#define POLARSSL_GENPRIME + +/** + * \def POLARSSL_FS_IO + * + * Enable functions that use the filesystem. + */ +//#define POLARSSL_FS_IO + +/** + * \def POLARSSL_NO_DEFAULT_ENTROPY_SOURCES + * + * Do not add default entropy sources. These are the platform specific, + * hardclock and HAVEGE based poll functions. + * + * This is useful to have more control over the added entropy sources in an + * application. + * + * Uncomment this macro to prevent loading of default entropy functions. + */ +//#define POLARSSL_NO_DEFAULT_ENTROPY_SOURCES + +/** + * \def POLARSSL_NO_PLATFORM_ENTROPY + * + * Do not use built-in platform entropy functions. + * This is useful if your platform does not support + * standards like the /dev/urandom or Windows CryptoAPI. + * + * Uncomment this macro to disable the built-in platform entropy functions. + */ +//#define POLARSSL_NO_PLATFORM_ENTROPY + +/** + * \def POLARSSL_MEMORY_DEBUG + * + * Enable debugging of buffer allocator memory issues. Automatically prints + * (to stderr) all (fatal) messages on memory allocation issues. Enables + * function for 'debug output' of allocated memory. + * + * Requires: POLARSSL_MEMORY_BUFFER_ALLOC_C + * fprintf() + * + * Uncomment this macro to let the buffer allocator print out error messages. + */ +//#define POLARSSL_MEMORY_DEBUG + +/** + * \def POLARSSL_MEMORY_BACKTRACE + * + * Include backtrace information with each allocated block. + * + * Requires: POLARSSL_MEMORY_BUFFER_ALLOC_C + * GLIBC-compatible backtrace() an backtrace_symbols() support + * + * Uncomment this macro to include backtrace information + */ +//#define POLARSSL_MEMORY_BACKTRACE + +/** + * \def POLARSSL_PKCS1_V15 + * + * Enable support for PKCS#1 v1.5 encoding. + * + * Requires: POLARSSL_RSA_C + * + * This enables support for PKCS#1 v1.5 operations. + */ +//#define POLARSSL_PKCS1_V15 + +/** + * \def POLARSSL_PKCS1_V21 + * + * Enable support for PKCS#1 v2.1 encoding. + * + * Requires: POLARSSL_MD_C, POLARSSL_RSA_C + * + * This enables support for RSAES-OAEP and RSASSA-PSS operations. + */ +//#define POLARSSL_PKCS1_V21 + +/** + * \def POLARSSL_RSA_NO_CRT + * + * Do not use the Chinese Remainder Theorem for the RSA private operation. + * + * Uncomment this macro to disable the use of CRT in RSA. + * + */ +//#define POLARSSL_RSA_NO_CRT + +/** + * \def POLARSSL_SELF_TEST + * + * Enable the checkup functions (*_self_test). + */ +//#define POLARSSL_SELF_TEST + +/** + * \def POLARSSL_SSL_ALL_ALERT_MESSAGES + * + * Enable sending of alert messages in case of encountered errors as per RFC. + * If you choose not to send the alert messages, PolarSSL can still communicate + * with other servers, only debugging of failures is harder. + * + * The advantage of not sending alert messages, is that no information is given + * about reasons for failures thus preventing adversaries of gaining intel. + * + * Enable sending of all alert messages + */ +#define POLARSSL_SSL_ALERT_MESSAGES + +/** + * \def POLARSSL_SSL_DEBUG_ALL + * + * Enable the debug messages in SSL module for all issues. + * Debug messages have been disabled in some places to prevent timing + * attacks due to (unbalanced) debugging function calls. + * + * If you need all error reporting you should enable this during debugging, + * but remove this for production servers that should log as well. + * + * Uncomment this macro to report all debug messages on errors introducing + * a timing side-channel. + * + */ +//#define POLARSSL_SSL_DEBUG_ALL + +/** + * \def POLARSSL_SSL_HW_RECORD_ACCEL + * + * Enable hooking functions in SSL module for hardware acceleration of + * individual records. + * + * Uncomment this macro to enable hooking functions. + */ +//#define POLARSSL_SSL_HW_RECORD_ACCEL + +/** + * \def POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO + * + * Enable support for receiving and parsing SSLv2 Client Hello messages for the + * SSL Server module (POLARSSL_SSL_SRV_C). + * + * Comment this macro to disable support for SSLv2 Client Hello messages. + */ +//#define POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO + +/** + * \def POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE + * + * Pick the ciphersuite according to the client's preferences rather than ours + * in the SSL Server module (POLARSSL_SSL_SRV_C). + * + * Uncomment this macro to respect client's ciphersuite order + */ +//#define POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE + +/** + * \def POLARSSL_SSL_MAX_FRAGMENT_LENGTH + * + * Enable support for RFC 6066 max_fragment_length extension in SSL. + * + * Comment this macro to disable support for the max_fragment_length extension + */ +#define POLARSSL_SSL_MAX_FRAGMENT_LENGTH + +/** + * \def POLARSSL_SSL_PROTO_SSL3 + * + * Enable support for SSL 3.0. + * + * Requires: POLARSSL_MD5_C + * POLARSSL_SHA1_C + * + * Comment this macro to disable support for SSL 3.0 + */ +#define POLARSSL_SSL_PROTO_SSL3 + +/** + * \def POLARSSL_SSL_PROTO_TLS1 + * + * Enable support for TLS 1.0. + * + * Requires: POLARSSL_MD5_C + * POLARSSL_SHA1_C + * + * Comment this macro to disable support for TLS 1.0 + */ +#define POLARSSL_SSL_PROTO_TLS1 + +/** + * \def POLARSSL_SSL_PROTO_TLS1_1 + * + * Enable support for TLS 1.1. + * + * Requires: POLARSSL_MD5_C + * POLARSSL_SHA1_C + * + * Comment this macro to disable support for TLS 1.1 + */ +#define POLARSSL_SSL_PROTO_TLS1_1 + +/** + * \def POLARSSL_SSL_PROTO_TLS1_2 + * + * Enable support for TLS 1.2. + * + * Requires: POLARSSL_SHA1_C or POLARSSL_SHA256_C or POLARSSL_SHA512_C + * (Depends on ciphersuites) + * + * Comment this macro to disable support for TLS 1.2 + */ +#define POLARSSL_SSL_PROTO_TLS1_2 + +/** + * \def POLARSSL_SSL_SESSION_TICKETS + * + * Enable support for RFC 5077 session tickets in SSL. + * + * Requires: POLARSSL_AES_C + * POLARSSL_SHA256_C + * POLARSSL_CIPHER_MODE_CBC + * + * Comment this macro to disable support for SSL session tickets + */ +#define POLARSSL_SSL_SESSION_TICKETS + +/** + * \def POLARSSL_SSL_SERVER_NAME_INDICATION + * + * Enable support for RFC 6066 server name indication (SNI) in SSL. + * + * Comment this macro to disable support for server name indication in SSL + */ +#define POLARSSL_SSL_SERVER_NAME_INDICATION + +/** + * \def POLARSSL_SSL_TRUNCATED_HMAC + * + * Enable support for RFC 6066 truncated HMAC in SSL. + * + * Comment this macro to disable support for truncated HMAC in SSL + */ +#define POLARSSL_SSL_TRUNCATED_HMAC + +/** + * \def POLARSSL_THREADING_ALT + * + * Provide your own alternate threading implementation. + * + * Requires: POLARSSL_THREADING_C + * + * Uncomment this to allow your own alternate threading implementation. + */ +//#define POLARSSL_THREADING_ALT + +/** + * \def POLARSSL_THREADING_PTHREAD + * + * Enable the pthread wrapper layer for the threading layer. + * + * Requires: POLARSSL_THREADING_C + * + * Uncomment this to enable pthread mutexes. + */ +//#define POLARSSL_THREADING_PTHREAD + +/** + * \def POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3 + * + * If set, the X509 parser will not break-off when parsing an X509 certificate + * and encountering an extension in a v1 or v2 certificate. + * + * Uncomment to prevent an error. + */ +//#define POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3 + +/** + * \def POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + * + * If set, the X509 parser will not break-off when parsing an X509 certificate + * and encountering an unknown critical extension. + * + * Uncomment to prevent an error. + */ +//#define POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + +/** + * \def POLARSSL_ZLIB_SUPPORT + * + * If set, the SSL/TLS module uses ZLIB to support compression and + * decompression of packet data. + * + * Used in: library/ssl_tls.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * This feature requires zlib library and headers to be present. + * + * Uncomment to enable use of ZLIB + */ +//#define POLARSSL_ZLIB_SUPPORT +/* \} name SECTION: PolarSSL feature support */ + +/** + * \name SECTION: PolarSSL modules + * + * This section enables or disables entire modules in PolarSSL + * \{ + */ + +/** + * \def POLARSSL_AESNI_C + * + * Enable AES-NI support on x86-64. + * + * Module: library/aesni.c + * Caller: library/aes.c + * + * Requires: POLARSSL_HAVE_ASM + * + * This modules adds support for the AES-NI instructions on x86-64 + */ +//#define POLARSSL_AESNI_C + +/** + * \def POLARSSL_AES_C + * + * Enable the AES block cipher. + * + * Module: library/aes.c + * Caller: library/ssl_tls.c + * library/pem.c + * library/ctr_drbg.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + * TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + * TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + * TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + * TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + * TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + * TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + * TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + * TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + * TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + * TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + * TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + * TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + * TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + * TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + * TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + * TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + * TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + * TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + * TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + * TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + * TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + * TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * TLS_RSA_WITH_AES_256_GCM_SHA384 + * TLS_RSA_WITH_AES_256_CBC_SHA256 + * TLS_RSA_WITH_AES_256_CBC_SHA + * TLS_RSA_WITH_AES_128_GCM_SHA256 + * TLS_RSA_WITH_AES_128_CBC_SHA256 + * TLS_RSA_WITH_AES_128_CBC_SHA + * TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * TLS_PSK_WITH_AES_256_GCM_SHA384 + * TLS_PSK_WITH_AES_256_CBC_SHA384 + * TLS_PSK_WITH_AES_256_CBC_SHA + * TLS_PSK_WITH_AES_128_GCM_SHA256 + * TLS_PSK_WITH_AES_128_CBC_SHA256 + * TLS_PSK_WITH_AES_128_CBC_SHA + * + * PEM_PARSE uses AES for decrypting encrypted keys. + */ +#define POLARSSL_AES_C + +/** + * \def POLARSSL_ARC4_C + * + * Enable the ARCFOUR stream cipher. + * + * Module: library/arc4.c + * Caller: library/ssl_tls.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDH_ECDSA_WITH_RC4_128_SHA + * TLS_ECDH_RSA_WITH_RC4_128_SHA + * TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + * TLS_ECDHE_RSA_WITH_RC4_128_SHA + * TLS_ECDHE_PSK_WITH_RC4_128_SHA + * TLS_DHE_PSK_WITH_RC4_128_SHA + * TLS_RSA_WITH_RC4_128_SHA + * TLS_RSA_WITH_RC4_128_MD5 + * TLS_RSA_PSK_WITH_RC4_128_SHA + * TLS_PSK_WITH_RC4_128_SHA + */ +//#define POLARSSL_ARC4_C + +/** + * \def POLARSSL_ASN1_PARSE_C + * + * Enable the generic ASN1 parser. + * + * Module: library/asn1.c + * Caller: library/x509.c + * library/dhm.c + * library/pkcs12.c + * library/pkcs5.c + * library/pkparse.c + */ +//#define POLARSSL_ASN1_PARSE_C + +/** + * \def POLARSSL_ASN1_WRITE_C + * + * Enable the generic ASN1 writer. + * + * Module: library/asn1write.c + * Caller: library/ecdsa.c + * library/pkwrite.c + * library/x509_create.c + * library/x509write_crt.c + * library/x509write_csr.c + */ +//#define POLARSSL_ASN1_WRITE_C + +/** + * \def POLARSSL_BASE64_C + * + * Enable the Base64 module. + * + * Module: library/base64.c + * Caller: library/pem.c + * + * This module is required for PEM support (required by X.509). + */ +//#define POLARSSL_BASE64_C + +/** + * \def POLARSSL_BIGNUM_C + * + * Enable the multi-precision integer library. + * + * Module: library/bignum.c + * Caller: library/dhm.c + * library/ecp.c + * library/rsa.c + * library/ssl_tls.c + * + * This module is required for RSA and DHM support. + */ +#define POLARSSL_BIGNUM_C + +/** + * \def POLARSSL_BLOWFISH_C + * + * Enable the Blowfish block cipher. + * + * Module: library/blowfish.c + */ +//#define POLARSSL_BLOWFISH_C + +/** + * \def POLARSSL_CAMELLIA_C + * + * Enable the Camellia block cipher. + * + * Module: library/camellia.c + * Caller: library/ssl_tls.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 + */ +//#define POLARSSL_CAMELLIA_C + +/** + * \def POLARSSL_CERTS_C + * + * Enable the test certificates. + * + * Module: library/certs.c + * Caller: + * + * Requires: POLARSSL_PEM_PARSE_C + * + * This module is used for testing (ssl_client/server). + */ +//#define POLARSSL_CERTS_C + +/** + * \def POLARSSL_CIPHER_C + * + * Enable the generic cipher layer. + * + * Module: library/cipher.c + * Caller: library/ssl_tls.c + * + * Uncomment to enable generic cipher wrappers. + */ +#define POLARSSL_CIPHER_C + +/** + * \def POLARSSL_CTR_DRBG_C + * + * Enable the CTR_DRBG AES-256-based random generator. + * + * Module: library/ctr_drbg.c + * Caller: + * + * Requires: POLARSSL_AES_C + * + * This module provides the CTR_DRBG AES-256 random number generator. + */ +//#define POLARSSL_CTR_DRBG_C + +/** + * \def POLARSSL_DEBUG_C + * + * Enable the debug functions. + * + * Module: library/debug.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module provides debugging functions. + */ +#define POLARSSL_DEBUG_C + +/** + * \def POLARSSL_DES_C + * + * Enable the DES block cipher. + * + * Module: library/des.c + * Caller: library/pem.c + * library/ssl_tls.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + * TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + * TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA + * TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA + * TLS_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA + * TLS_PSK_WITH_3DES_EDE_CBC_SHA + * + * PEM_PARSE uses DES/3DES for decrypting encrypted keys. + */ +//#define POLARSSL_DES_C + +/** + * \def POLARSSL_DHM_C + * + * Enable the Diffie-Hellman-Merkle module. + * + * Module: library/dhm.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module is used by the following key exchanges: + * DHE-RSA, DHE-PSK + */ +//#define POLARSSL_DHM_C + +/** + * \def POLARSSL_ECDH_C + * + * Enable the elliptic curve Diffie-Hellman library. + * + * Module: library/ecdh.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA, ECDHE-RSA, DHE-PSK + * + * Requires: POLARSSL_ECP_C + */ +//#define POLARSSL_ECDH_C + +/** + * \def POLARSSL_ECDSA_C + * + * Enable the elliptic curve DSA library. + * + * Module: library/ecdsa.c + * Caller: + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA + * + * Requires: POLARSSL_ECP_C, POLARSSL_ASN1_WRITE_C, POLARSSL_ASN1_PARSE_C + */ +//#define POLARSSL_ECDSA_C + +/** + * \def POLARSSL_ECP_C + * + * Enable the elliptic curve over GF(p) library. + * + * Module: library/ecp.c + * Caller: library/ecdh.c + * library/ecdsa.c + * + * Requires: POLARSSL_BIGNUM_C and at least one POLARSSL_ECP_DP_XXX_ENABLED + */ +//#define POLARSSL_ECP_C + +/** + * \def POLARSSL_ENTROPY_C + * + * Enable the platform-specific entropy code. + * + * Module: library/entropy.c + * Caller: + * + * Requires: POLARSSL_SHA512_C + * + * This module provides a generic entropy pool + */ +//#define POLARSSL_ENTROPY_C + +/** + * \def POLARSSL_ERROR_C + * + * Enable error code to error string conversion. + * + * Module: library/error.c + * Caller: + * + * This module enables err_strerror(). + */ +#define POLARSSL_ERROR_C + +/** + * \def POLARSSL_GCM_C + * + * Enable the Galois/Counter Mode (GCM) for AES. + * + * Module: library/gcm.c + * + * Requires: POLARSSL_AES_C or POLARSSL_CAMELLIA_C + * + * This module enables the AES-GCM and CAMELLIA-GCM ciphersuites, if other + * requisites are enabled as well. + */ +//#define POLARSSL_GCM_C + +/** + * \def POLARSSL_HAVEGE_C + * + * Enable the HAVEGE random generator. + * + * Warning: the HAVEGE random generator is not suitable for virtualized + * environments + * + * Warning: the HAVEGE random generator is dependent on timing and specific + * processor traits. It is therefore not advised to use HAVEGE as + * your applications primary random generator or primary entropy pool + * input. As a secondary input to your entropy pool, it IS able add + * the (limited) extra entropy it provides. + * + * Module: library/havege.c + * Caller: + * + * Requires: POLARSSL_TIMING_C + * + * Uncomment to enable the HAVEGE random generator. + */ +//#define POLARSSL_HAVEGE_C + +/** + * \def POLARSSL_MD_C + * + * Enable the generic message digest layer. + * + * Module: library/md.c + * Caller: + * + * Uncomment to enable generic message digest wrappers. + */ +#define POLARSSL_MD_C + +/** + * \def POLARSSL_MD2_C + * + * Enable the MD2 hash algorithm. + * + * Module: library/md2.c + * Caller: + * + * Uncomment to enable support for (rare) MD2-signed X.509 certs. + */ +//#define POLARSSL_MD2_C + +/** + * \def POLARSSL_MD4_C + * + * Enable the MD4 hash algorithm. + * + * Module: library/md4.c + * Caller: + * + * Uncomment to enable support for (rare) MD4-signed X.509 certs. + */ +//#define POLARSSL_MD4_C + +/** + * \def POLARSSL_MD5_C + * + * Enable the MD5 hash algorithm. + * + * Module: library/md5.c + * Caller: library/md.c + * library/pem.c + * library/ssl_tls.c + * + * This module is required for SSL/TLS and X.509. + * PEM_PARSE uses MD5 for decrypting encrypted keys. + */ +#define POLARSSL_MD5_C + +/** + * \def POLARSSL_MEMORY_C + * + * Enable the memory allocation layer. + * By default PolarSSL uses the system-provided malloc() and free(). + * (As long as POLARSSL_MEMORY_STDMALLOC and POLARSSL_MEMORY_STDFREE + * are defined and unmodified) + * + * This allows different allocators (self-implemented or provided) + * + * Enable this layer to allow use of alternative memory allocators. + */ +#define POLARSSL_MEMORY_C + +/** + * \def POLARSSL_MEMORY_BUFFER_ALLOC_C + * + * Enable the buffer allocator implementation that makes use of a (stack) + * based buffer to 'allocate' dynamic memory. (replaces malloc() and free() + * calls) + * + * Module: library/memory_buffer_alloc.c + * + * Requires: POLARSSL_MEMORY_C + * + * Enable this module to enable the buffer memory allocator. + */ +//#define POLARSSL_MEMORY_BUFFER_ALLOC_C + +/** + * \def POLARSSL_NET_C + * + * Enable the TCP/IP networking routines. + * + * Module: library/net.c + * + * This module provides TCP/IP networking routines. + */ +#define POLARSSL_NET_C + +/** + * \def POLARSSL_OID_C + * + * Enable the OID database. + * + * Module: library/oid.c + * Caller: library/asn1write.c + * library/pkcs5.c + * library/pkparse.c + * library/pkwrite.c + * library/rsa.c + * library/x509.c + * library/x509_create.c + * library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * library/x509write_crt.c + * library/x509write_csr.c + * + * This modules translates between OIDs and internal values. + */ +#define POLARSSL_OID_C + +/** + * \def POLARSSL_PADLOCK_C + * + * Enable VIA Padlock support on x86. + * + * Module: library/padlock.c + * Caller: library/aes.c + * + * Requires: POLARSSL_HAVE_ASM + * + * This modules adds support for the VIA PadLock on x86. + */ +//#define POLARSSL_PADLOCK_C + +/** + * \def POLARSSL_PBKDF2_C + * + * Enable PKCS#5 PBKDF2 key derivation function. + * DEPRECATED: Use POLARSSL_PKCS5_C instead + * + * Module: library/pbkdf2.c + * + * Requires: POLARSSL_PKCS5_C + * + * This module adds support for the PKCS#5 PBKDF2 key derivation function. + */ +//#define POLARSSL_PBKDF2_C + +/** + * \def POLARSSL_PEM_PARSE_C + * + * Enable PEM decoding / parsing. + * + * Module: library/pem.c + * Caller: library/dhm.c + * library/pkparse.c + * library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * + * Requires: POLARSSL_BASE64_C + * + * This modules adds support for decoding / parsing PEM files. + */ +//#define POLARSSL_PEM_PARSE_C + +/** + * \def POLARSSL_PEM_WRITE_C + * + * Enable PEM encoding / writing. + * + * Module: library/pem.c + * Caller: library/pkwrite.c + * library/x509write_crt.c + * library/x509write_csr.c + * + * Requires: POLARSSL_BASE64_C + * + * This modules adds support for encoding / writing PEM files. + */ +//#define POLARSSL_PEM_WRITE_C + +/** + * \def POLARSSL_PK_C + * + * Enable the generic public (asymetric) key layer. + * + * Module: library/pk.c + * Caller: library/ssl_tls.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: POLARSSL_RSA_C or POLARSSL_ECP_C + * + * Uncomment to enable generic public key wrappers. + */ +//#define POLARSSL_PK_C + +/** + * \def POLARSSL_PK_PARSE_C + * + * Enable the generic public (asymetric) key parser. + * + * Module: library/pkparse.c + * Caller: library/x509_crt.c + * library/x509_csr.c + * + * Requires: POLARSSL_PK_C + * + * Uncomment to enable generic public key parse functions. + */ +//#define POLARSSL_PK_PARSE_C + +/** + * \def POLARSSL_PK_WRITE_C + * + * Enable the generic public (asymetric) key writer. + * + * Module: library/pkwrite.c + * Caller: library/x509write.c + * + * Requires: POLARSSL_PK_C + * + * Uncomment to enable generic public key write functions. + */ +//#define POLARSSL_PK_WRITE_C + +/** + * \def POLARSSL_PKCS5_C + * + * Enable PKCS#5 functions. + * + * Module: library/pkcs5.c + * + * Requires: POLARSSL_MD_C + * + * This module adds support for the PKCS#5 functions. + */ +//#define POLARSSL_PKCS5_C + +/** + * \def POLARSSL_PKCS11_C + * + * Enable wrapper for PKCS#11 smartcard support. + * + * Module: library/pkcs11.c + * Caller: library/pk.c + * + * Requires: POLARSSL_PK_C + * + * This module enables SSL/TLS PKCS #11 smartcard support. + * Requires the presence of the PKCS#11 helper library (libpkcs11-helper) + */ +//#define POLARSSL_PKCS11_C + +/** + * \def POLARSSL_PKCS12_C + * + * Enable PKCS#12 PBE functions. + * Adds algorithms for parsing PKCS#8 encrypted private keys + * + * Module: library/pkcs12.c + * Caller: library/pkparse.c + * + * Requires: POLARSSL_ASN1_PARSE_C, POLARSSL_CIPHER_C, POLARSSL_MD_C + * Can use: POLARSSL_ARC4_C + * + * This module enables PKCS#12 functions. + */ +//#define POLARSSL_PKCS12_C + +/** + * \def POLARSSL_RSA_C + * + * Enable the RSA public-key cryptosystem. + * + * Module: library/rsa.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509.c + * + * This module is used by the following key exchanges: + * RSA, DHE-RSA, ECDHE-RSA, RSA-PSK + * + * Requires: POLARSSL_BIGNUM_C, POLARSSL_OID_C + */ +//#define POLARSSL_RSA_C + +/** + * \def POLARSSL_SHA1_C + * + * Enable the SHA1 cryptographic hash algorithm. + * + * Module: library/sha1.c + * Caller: library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509write_crt.c + * + * This module is required for SSL/TLS and SHA1-signed certificates. + */ +#define POLARSSL_SHA1_C + +/** + * \def POLARSSL_SHA256_C + * + * Enable the SHA-224 and SHA-256 cryptographic hash algorithms. + * (Used to be POLARSSL_SHA2_C) + * + * Module: library/sha256.c + * Caller: library/entropy.c + * library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module adds support for SHA-224 and SHA-256. + * This module is required for the SSL/TLS 1.2 PRF function. + */ +#define POLARSSL_SHA256_C + +/** + * \def POLARSSL_SHA512_C + * + * Enable the SHA-384 and SHA-512 cryptographic hash algorithms. + * (Used to be POLARSSL_SHA4_C) + * + * Module: library/sha512.c + * Caller: library/entropy.c + * library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * This module adds support for SHA-384 and SHA-512. + */ +#define POLARSSL_SHA512_C + +/** + * \def POLARSSL_SSL_CACHE_C + * + * Enable simple SSL cache implementation. + * + * Module: library/ssl_cache.c + * Caller: + * + * Requires: POLARSSL_SSL_CACHE_C + */ +#define POLARSSL_SSL_CACHE_C + +/** + * \def POLARSSL_SSL_CLI_C + * + * Enable the SSL/TLS client code. + * + * Module: library/ssl_cli.c + * Caller: + * + * Requires: POLARSSL_SSL_TLS_C + * + * This module is required for SSL/TLS client support. + */ +#define POLARSSL_SSL_CLI_C + +/** + * \def POLARSSL_SSL_SRV_C + * + * Enable the SSL/TLS server code. + * + * Module: library/ssl_srv.c + * Caller: + * + * Requires: POLARSSL_SSL_TLS_C + * + * This module is required for SSL/TLS server support. + */ +//#define POLARSSL_SSL_SRV_C + +/** + * \def POLARSSL_SSL_TLS_C + * + * Enable the generic SSL/TLS code. + * + * Module: library/ssl_tls.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: POLARSSL_CIPHER_C, POLARSSL_MD_C + * and at least one of the POLARSSL_SSL_PROTO_* defines + * + * This module is required for SSL/TLS. + */ +#define POLARSSL_SSL_TLS_C + +/** + * \def POLARSSL_THREADING_C + * + * Enable the threading abstraction layer. + * By default PolarSSL assumes it is used in a non-threaded environment or that + * contexts are not shared between threads. If you do intend to use contexts + * between threads, you will need to enable this layer to prevent race + * conditions. + * + * Module: library/threading.c + * + * This allows different threading implementations (self-implemented or + * provided). + * + * You will have to enable either POLARSSL_THREADING_ALT or + * POLARSSL_THREADING_PTHREAD. + * + * Enable this layer to allow use of mutexes within PolarSSL + */ +//#define POLARSSL_THREADING_C + +/** + * \def POLARSSL_TIMING_C + * + * Enable the portable timing interface. + * + * Module: library/timing.c + * Caller: library/havege.c + * + * This module is used by the HAVEGE random number generator. + */ +//#define POLARSSL_TIMING_C + +/** + * \def POLARSSL_VERSION_C + * + * Enable run-time version information. + * + * Module: library/version.c + * + * This module provides run-time version information. + */ +#define POLARSSL_VERSION_C + +/** + * \def POLARSSL_X509_USE_C + * + * Enable X.509 core for using certificates. + * + * Module: library/x509.c + * Caller: library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * + * Requires: POLARSSL_ASN1_PARSE_C, POLARSSL_BIGNUM_C, POLARSSL_OID_C, + * POLARSSL_PK_PARSE_C + * + * This module is required for the X.509 parsing modules. + */ +//#define POLARSSL_X509_USE_C + +/** + * \def POLARSSL_X509_CRT_PARSE_C + * + * Enable X.509 certificate parsing. + * + * Module: library/x509_crt.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * Requires: POLARSSL_X509_USE_C + * + * This module is required for X.509 certificate parsing. + */ +//#define POLARSSL_X509_CRT_PARSE_C + +/** + * \def POLARSSL_X509_CRL_PARSE_C + * + * Enable X.509 CRL parsing. + * + * Module: library/x509_crl.c + * Caller: library/x509_crt.c + * + * Requires: POLARSSL_X509_USE_C + * + * This module is required for X.509 CRL parsing. + */ +//#define POLARSSL_X509_CRL_PARSE_C + +/** + * \def POLARSSL_X509_CSR_PARSE_C + * + * Enable X.509 Certificate Signing Request (CSR) parsing. + * + * Module: library/x509_csr.c + * Caller: library/x509_crt_write.c + * + * Requires: POLARSSL_X509_USE_C + * + * This module is used for reading X.509 certificate request. + */ +//#define POLARSSL_X509_CSR_PARSE_C + +/** + * \def POLARSSL_X509_CREATE_C + * + * Enable X.509 core for creating certificates. + * + * Module: library/x509_create.c + * + * Requires: POLARSSL_BIGNUM_C, POLARSSL_OID_C, POLARSSL_PK_WRITE_C + * + * This module is the basis for creating X.509 certificates and CSRs. + */ +//#define POLARSSL_X509_CREATE_C + +/** + * \def POLARSSL_X509_CRT_WRITE_C + * + * Enable creating X.509 certificates. + * + * Module: library/x509_crt_write.c + * + * Requires: POLARSSL_CREATE_C + * + * This module is required for X.509 certificate creation. + */ +//#define POLARSSL_X509_CRT_WRITE_C + +/** + * \def POLARSSL_X509_CSR_WRITE_C + * + * Enable creating X.509 Certificate Signing Requests (CSR). + * + * Module: library/x509_csr_write.c + * + * Requires: POLARSSL_CREATE_C + * + * This module is required for X.509 certificate request writing. + */ +//#define POLARSSL_X509_CSR_WRITE_C + +/** + * \def POLARSSL_XTEA_C + * + * Enable the XTEA block cipher. + * + * Module: library/xtea.c + * Caller: + */ +//#define POLARSSL_XTEA_C + +/** + * \def POLARSSL_SRP_C + * + * Enable the SRP library. + * + * Module: library/srp.c + * Caller: library/ssl_cli.c + */ +#define POLARSSL_SRP_C + +/* \} name SECTION: PolarSSL modules */ + +/** + * \name SECTION: Module configuration options + * + * This section allows for the setting of module specific sizes and + * configuration options. The default values are already present in the + * relevant header files and should suffice for the regular use cases. + * Our advice is to enable POLARSSL_CONFIG_OPTIONS and change values here + * only if you have a good reason and know the consequences. + * + * If POLARSSL_CONFIG_OPTIONS is undefined here the options in the module + * header file take precedence. + * + * Please check the respective header file for documentation on these + * parameters (to prevent duplicate documentation). + * + * Uncomment POLARSSL_CONFIG_OPTIONS to enable using the values defined here. + * \{ + */ +#define POLARSSL_CONFIG_OPTIONS /**< Enable config.h module value configuration */ + +#if defined(POLARSSL_CONFIG_OPTIONS) + +// MPI / BIGNUM options +// +#define POLARSSL_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */ +#define POLARSSL_MPI_MAX_SIZE 128 /**< Maximum number of bytes for usable MPIs. Default in 512. + POLARSSL_MPI_MAX_SIZE 128 for bignum and premaster size is only verified for SSL SRP handshake with group parameter of 1024 */ +// CTR_DRBG options +// +#define CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */ +#define CTR_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +#define CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +#define CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +#define CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ + +// ECP options +// +#define POLARSSL_ECP_MAX_BITS 521 /**< Maximum bit size of groups */ +#define POLARSSL_ECP_WINDOW_SIZE 6 /**< Maximum window size used */ +#define POLARSSL_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up */ + +// Entropy options +// +#define ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ +#define ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ + +// Memory options +#define MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */ +#define POLARSSL_MEMORY_STDMALLOC malloc /**< Default allocator to use, can be undefined */ +#define POLARSSL_MEMORY_STDFREE free /**< Default free to use, can be undefined */ + +// SSL Cache options +// +#define SSL_CACHE_DEFAULT_TIMEOUT 86400 /**< 1 day */ +#define SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /**< Maximum entries in cache */ + +// SSL options +// +#define SSL_MAX_CONTENT_LEN 512 /**< Size of the input / output buffer. Default in 16384. + SSL_MAX_CONTENT_LEN 512 is only verified for SSL SRP handshake */ +#define SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ + +#endif /* POLARSSL_CONFIG_OPTIONS */ + +/* \} name */ + +/* + * Sanity checks on defines and dependencies + */ +#if defined(POLARSSL_AESNI_C) && !defined(POLARSSL_HAVE_ASM) +#error "POLARSSL_AESNI_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_CERTS_C) && !defined(POLARSSL_PEM_PARSE_C) +#error "POLARSSL_CERTS_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_CTR_DRBG_C) && !defined(POLARSSL_AES_C) +#error "POLARSSL_CTR_DRBG_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_DHM_C) && !defined(POLARSSL_BIGNUM_C) +#error "POLARSSL_DHM_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_ECDH_C) && !defined(POLARSSL_ECP_C) +#error "POLARSSL_ECDH_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_ECDSA_C) && \ + ( !defined(POLARSSL_ECP_C) || \ + !defined(POLARSSL_ASN1_PARSE_C) || \ + !defined(POLARSSL_ASN1_WRITE_C) ) +#error "POLARSSL_ECDSA_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_ECP_C) && ( !defined(POLARSSL_BIGNUM_C) || ( \ + !defined(POLARSSL_ECP_DP_SECP192R1_ENABLED) && \ + !defined(POLARSSL_ECP_DP_SECP224R1_ENABLED) && \ + !defined(POLARSSL_ECP_DP_SECP256R1_ENABLED) && \ + !defined(POLARSSL_ECP_DP_SECP384R1_ENABLED) && \ + !defined(POLARSSL_ECP_DP_SECP521R1_ENABLED) && \ + !defined(POLARSSL_ECP_DP_BP256R1_ENABLED) && \ + !defined(POLARSSL_ECP_DP_BP384R1_ENABLED) && \ + !defined(POLARSSL_ECP_DP_BP512R1_ENABLED) ) ) +#error "POLARSSL_ECP_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_ENTROPY_C) && (!defined(POLARSSL_SHA512_C) && \ + !defined(POLARSSL_SHA256_C)) +#error "POLARSSL_ENTROPY_C defined, but not all prerequisites" +#endif +#if defined(POLARSSL_ENTROPY_C) && defined(POLARSSL_SHA512_C) && \ + defined(POLARSSL_CONFIG_OPTIONS) && (CTR_DRBG_ENTROPY_LEN > 64) +#error "CTR_DRBG_ENTROPY_LEN value too high" +#endif +#if defined(POLARSSL_ENTROPY_C) && !defined(POLARSSL_SHA512_C) && \ + defined(POLARSSL_CONFIG_OPTIONS) && (CTR_DRBG_ENTROPY_LEN > 32) +#error "CTR_DRBG_ENTROPY_LEN value too high" +#endif + +#if defined(POLARSSL_GCM_C) && ( \ + !defined(POLARSSL_AES_C) && !defined(POLARSSL_CAMELLIA_C) ) +#error "POLARSSL_GCM_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_HAVEGE_C) && !defined(POLARSSL_TIMING_C) +#error "POLARSSL_HAVEGE_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) && \ + ( !defined(POLARSSL_ECDH_C) || !defined(POLARSSL_X509_CRT_PARSE_C) ) +#error "POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ + ( !defined(POLARSSL_ECDH_C) || !defined(POLARSSL_X509_CRT_PARSE_C) ) +#error "POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) && !defined(POLARSSL_DHM_C) +#error "POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) && \ + !defined(POLARSSL_ECDH_C) +#error "POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ + ( !defined(POLARSSL_DHM_C) || !defined(POLARSSL_RSA_C) || \ + !defined(POLARSSL_X509_CRT_PARSE_C) || !defined(POLARSSL_PKCS1_V15) ) +#error "POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ + ( !defined(POLARSSL_ECDH_C) || !defined(POLARSSL_RSA_C) || \ + !defined(POLARSSL_X509_CRT_PARSE_C) || !defined(POLARSSL_PKCS1_V15) ) +#error "POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \ + ( !defined(POLARSSL_ECDH_C) || !defined(POLARSSL_ECDSA_C) || \ + !defined(POLARSSL_X509_CRT_PARSE_C) ) +#error "POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) && \ + ( !defined(POLARSSL_RSA_C) || !defined(POLARSSL_X509_CRT_PARSE_C) ||\ + !defined(POLARSSL_PKCS1_V15) ) +#error "POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) && \ + ( !defined(POLARSSL_RSA_C) || !defined(POLARSSL_X509_CRT_PARSE_C) ||\ + !defined(POLARSSL_PKCS1_V15) ) +#error "POLARSSL_KEY_EXCHANGE_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_MEMORY_BUFFER_ALLOC_C) && !defined(POLARSSL_MEMORY_C) +#error "POLARSSL_MEMORY_BUFFER_ALLOC_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_PADLOCK_C) && !defined(POLARSSL_HAVE_ASM) +#error "POLARSSL_PADLOCK_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_PBKDF2_C) && !defined(POLARSSL_MD_C) +#error "POLARSSL_PBKDF2_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_PEM_PARSE_C) && !defined(POLARSSL_BASE64_C) +#error "POLARSSL_PEM_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_PEM_WRITE_C) && !defined(POLARSSL_BASE64_C) +#error "POLARSSL_PEM_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_PK_PARSE_C) && !defined(POLARSSL_PK_C) +#error "POLARSSL_PK_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_PK_WRITE_C) && !defined(POLARSSL_PK_C) +#error "POLARSSL_PK_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_PKCS11_C) && !defined(POLARSSL_PK_C) +#error "POLARSSL_PKCS11_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_RSA_C) && ( !defined(POLARSSL_BIGNUM_C) || \ + !defined(POLARSSL_OID_C) ) +#error "POLARSSL_RSA_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_SSL_PROTO_SSL3) && ( !defined(POLARSSL_MD5_C) || \ + !defined(POLARSSL_SHA1_C) ) +#error "POLARSSL_SSL_PROTO_SSL3 defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_SSL_PROTO_TLS1) && ( !defined(POLARSSL_MD5_C) || \ + !defined(POLARSSL_SHA1_C) ) +#error "POLARSSL_SSL_PROTO_TLS1 defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_SSL_PROTO_TLS1_1) && ( !defined(POLARSSL_MD5_C) || \ + !defined(POLARSSL_SHA1_C) ) +#error "POLARSSL_SSL_PROTO_TLS1_1 defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_SSL_PROTO_TLS1_2) && ( !defined(POLARSSL_SHA1_C) && \ + !defined(POLARSSL_SHA256_C) && !defined(POLARSSL_SHA512_C) ) +#error "POLARSSL_SSL_PROTO_TLS1_2 defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_SSL_CLI_C) && !defined(POLARSSL_SSL_TLS_C) +#error "POLARSSL_SSL_CLI_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_SSL_TLS_C) && ( !defined(POLARSSL_CIPHER_C) || \ + !defined(POLARSSL_MD_C) ) +#error "POLARSSL_SSL_TLS_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_SSL_SRV_C) && !defined(POLARSSL_SSL_TLS_C) +#error "POLARSSL_SSL_SRV_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_SSL_TLS_C) && (!defined(POLARSSL_SSL_PROTO_SSL3) && \ + !defined(POLARSSL_SSL_PROTO_TLS1) && !defined(POLARSSL_SSL_PROTO_TLS1_1) && \ + !defined(POLARSSL_SSL_PROTO_TLS1_2)) +#error "POLARSSL_SSL_TLS_C defined, but no protocols are active" +#endif + +#if defined(POLARSSL_SSL_TLS_C) && (defined(POLARSSL_SSL_PROTO_SSL3) && \ + defined(POLARSSL_SSL_PROTO_TLS1_1) && !defined(POLARSSL_SSL_PROTO_TLS1)) +#error "Illegal protocol selection" +#endif + +#if defined(POLARSSL_SSL_TLS_C) && (defined(POLARSSL_SSL_PROTO_TLS1) && \ + defined(POLARSSL_SSL_PROTO_TLS1_2) && !defined(POLARSSL_SSL_PROTO_TLS1_1)) +#error "Illegal protocol selection" +#endif + +#if defined(POLARSSL_SSL_TLS_C) && (defined(POLARSSL_SSL_PROTO_SSL3) && \ + defined(POLARSSL_SSL_PROTO_TLS1_2) && (!defined(POLARSSL_SSL_PROTO_TLS1) || \ + !defined(POLARSSL_SSL_PROTO_TLS1_1))) +#error "Illegal protocol selection" +#endif + +#if defined(POLARSSL_SSL_SESSION_TICKETS) && defined(POLARSSL_SSL_TLS_C) && \ + ( !defined(POLARSSL_AES_C) || !defined(POLARSSL_SHA256_C) || \ + !defined(POLARSSL_CIPHER_MODE_CBC) ) +#error "POLARSSL_SSL_SESSION_TICKETS_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_THREADING_PTHREAD) +#if !defined(POLARSSL_THREADING_C) || defined(POLARSSL_THREADING_IMPL) +#error "POLARSSL_THREADING_PTHREAD defined, but not all prerequisites" +#endif +#define POLARSSL_THREADING_IMPL +#endif + +#if defined(POLARSSL_THREADING_ALT) +#if !defined(POLARSSL_THREADING_C) || defined(POLARSSL_THREADING_IMPL) +#error "POLARSSL_THREADING_ALT defined, but not all prerequisites" +#endif +#define POLARSSL_THREADING_IMPL +#endif + +#if defined(POLARSSL_THREADING_C) && !defined(POLARSSL_THREADING_IMPL) +#error "POLARSSL_THREADING_C defined, single threading implementation required" +#endif +#undef POLARSSL_THREADING_IMPL + +#if defined(POLARSSL_X509_USE_C) && ( !defined(POLARSSL_BIGNUM_C) || \ + !defined(POLARSSL_OID_C) || !defined(POLARSSL_ASN1_PARSE_C) || \ + !defined(POLARSSL_PK_PARSE_C) ) +#error "POLARSSL_X509_USE_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_X509_CREATE_C) && ( !defined(POLARSSL_BIGNUM_C) || \ + !defined(POLARSSL_OID_C) || !defined(POLARSSL_ASN1_WRITE_C) || \ + !defined(POLARSSL_PK_WRITE_C) ) +#error "POLARSSL_X509_CREATE_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_X509_CRT_PARSE_C) && ( !defined(POLARSSL_X509_USE_C) ) +#error "POLARSSL_X509_CRT_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_X509_CRL_PARSE_C) && ( !defined(POLARSSL_X509_USE_C) ) +#error "POLARSSL_X509_CRL_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_X509_CSR_PARSE_C) && ( !defined(POLARSSL_X509_USE_C) ) +#error "POLARSSL_X509_CSR_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_X509_CRT_WRITE_C) && ( !defined(POLARSSL_X509_CREATE_C) ) +#error "POLARSSL_X509_CRT_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_X509_CSR_WRITE_C) && ( !defined(POLARSSL_X509_CREATE_C) ) +#error "POLARSSL_X509_CSR_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(POLARSSL_KEY_EXCHANGE_SRP_ENABLED) && ( !defined(POLARSSL_SRP_C) ) +#error "POLARSSL_KEY_EXCHANGE_SRP_ENABLED defined, but not all prerequisites" +#endif + +#endif /* config.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/ctr_drbg.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/ctr_drbg.h new file mode 100644 index 0000000..bebbfe9 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/ctr_drbg.h @@ -0,0 +1,274 @@ +/** + * \file ctr_drbg.h + * + * \brief CTR_DRBG based on AES-256 (NIST SP 800-90) + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_CTR_DRBG_H +#define POLARSSL_CTR_DRBG_H + +#include + +#include "aes.h" + +#define POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED -0x0034 /**< The entropy source failed. */ +#define POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG -0x0036 /**< Too many random requested in single call. */ +#define POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG -0x0038 /**< Input too large (Entropy + additional). */ +#define POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR -0x003A /**< Read/write error in file. */ + +#define CTR_DRBG_BLOCKSIZE 16 /**< Block size used by the cipher */ +#define CTR_DRBG_KEYSIZE 32 /**< Key size used by the cipher */ +#define CTR_DRBG_KEYBITS ( CTR_DRBG_KEYSIZE * 8 ) +#define CTR_DRBG_SEEDLEN ( CTR_DRBG_KEYSIZE + CTR_DRBG_BLOCKSIZE ) + /**< The seed length (counter + AES key) */ + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(CTR_DRBG_ENTROPY_LEN) +#if defined(POLARSSL_SHA512_C) && !defined(POLARSSL_ENTROPY_FORCE_SHA256) +#define CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */ +#else +#define CTR_DRBG_ENTROPY_LEN 32 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */ +#endif +#endif + +#if !defined(CTR_DRBG_RESEED_INTERVAL) +#define CTR_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +#endif + +#if !defined(CTR_DRBG_MAX_INPUT) +#define CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +#endif + +#if !defined(CTR_DRBG_MAX_REQUEST) +#define CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +#endif + +#if !defined(CTR_DRBG_MAX_SEED_INPUT) +#define CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ +#endif + +/* \} name SECTION: Module settings */ + +#define CTR_DRBG_PR_OFF 0 /**< No prediction resistance */ +#define CTR_DRBG_PR_ON 1 /**< Prediction resistance enabled */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief CTR_DRBG context structure + */ +typedef struct +{ + unsigned char counter[16]; /*!< counter (V) */ + int reseed_counter; /*!< reseed counter */ + int prediction_resistance; /*!< enable prediction resistance (Automatic + reseed before every random generation) */ + size_t entropy_len; /*!< amount of entropy grabbed on each + (re)seed */ + int reseed_interval; /*!< reseed interval */ + + aes_context aes_ctx; /*!< AES context */ + + /* + * Callbacks (Entropy) + */ + int (*f_entropy)(void *, unsigned char *, size_t); + + void *p_entropy; /*!< context for the entropy function */ +} +ctr_drbg_context; + +/** + * \brief CTR_DRBG initialization + * + * Note: Personalization data can be provided in addition to the more generic + * entropy source to make this instantiation as unique as possible. + * + * \param ctx CTR_DRBG context to be initialized + * \param f_entropy Entropy callback (p_entropy, buffer to fill, buffer + * length) + * \param p_entropy Entropy context + * \param custom Personalization data (Device specific identifiers) + * (Can be NULL) + * \param len Length of personalization data + * + * \return 0 if successful, or + * POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED + */ +int ctr_drbg_init( ctr_drbg_context *ctx, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len ); + +/** + * \brief Clear CTR_CRBG context data + * + * \param ctx CTR_DRBG context to clear + */ +void ctr_drbg_free( ctr_drbg_context *ctx ); + +/** + * \brief Enable / disable prediction resistance (Default: Off) + * + * Note: If enabled, entropy is used for ctx->entropy_len before each call! + * Only use this if you have ample supply of good entropy! + * + * \param ctx CTR_DRBG context + * \param resistance CTR_DRBG_PR_ON or CTR_DRBG_PR_OFF + */ +void ctr_drbg_set_prediction_resistance( ctr_drbg_context *ctx, + int resistance ); + +/** + * \brief Set the amount of entropy grabbed on each (re)seed + * (Default: CTR_DRBG_ENTROPY_LEN) + * + * \param ctx CTR_DRBG context + * \param len Amount of entropy to grab + */ +void ctr_drbg_set_entropy_len( ctr_drbg_context *ctx, + size_t len ); + +/** + * \brief Set the reseed interval + * (Default: CTR_DRBG_RESEED_INTERVAL) + * + * \param ctx CTR_DRBG context + * \param interval Reseed interval + */ +void ctr_drbg_set_reseed_interval( ctr_drbg_context *ctx, + int interval ); + +/** + * \brief CTR_DRBG reseeding (extracts data from entropy source) + * + * \param ctx CTR_DRBG context + * \param additional Additional data to add to state (Can be NULL) + * \param len Length of additional data + * + * \return 0 if successful, or + * POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED + */ +int ctr_drbg_reseed( ctr_drbg_context *ctx, + const unsigned char *additional, size_t len ); + +/** + * \brief CTR_DRBG update state + * + * \param ctx CTR_DRBG context + * \param additional Additional data to update state with + * \param add_len Length of additional data + */ +void ctr_drbg_update( ctr_drbg_context *ctx, + const unsigned char *additional, size_t add_len ); + +/** + * \brief CTR_DRBG generate random with additional update input + * + * Note: Automatically reseeds if reseed_counter is reached. + * + * \param p_rng CTR_DRBG context + * \param output Buffer to fill + * \param output_len Length of the buffer + * \param additional Additional data to update with (Can be NULL) + * \param add_len Length of additional data + * + * \return 0 if successful, or + * POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED, or + * POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG + */ +int ctr_drbg_random_with_add( void *p_rng, + unsigned char *output, size_t output_len, + const unsigned char *additional, size_t add_len ); + +/** + * \brief CTR_DRBG generate random + * + * Note: Automatically reseeds if reseed_counter is reached. + * + * \param p_rng CTR_DRBG context + * \param output Buffer to fill + * \param output_len Length of the buffer + * + * \return 0 if successful, or + * POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED, or + * POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG + */ +int ctr_drbg_random( void *p_rng, + unsigned char *output, size_t output_len ); + +#if defined(POLARSSL_FS_IO) +/** + * \brief Write a seed file + * + * \param ctx CTR_DRBG context + * \param path Name of the file + * + * \return 0 if successful, + * POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR on file error, or + * POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED + */ +int ctr_drbg_write_seed_file( ctr_drbg_context *ctx, const char *path ); + +/** + * \brief Read and update a seed file. Seed is added to this + * instance + * + * \param ctx CTR_DRBG context + * \param path Name of the file + * + * \return 0 if successful, + * POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR on file error, + * POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or + * POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG + */ +int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path ); +#endif /* POLARSSL_FS_IO */ + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int ctr_drbg_self_test( int verbose ); + +/* Internal functions (do not call directly) */ +int ctr_drbg_init_entropy_len( ctr_drbg_context *, + int (*)(void *, unsigned char *, size_t), void *, + const unsigned char *, size_t, size_t ); + +#ifdef __cplusplus +} +#endif + +#endif /* ctr_drbg.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/debug.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/debug.h new file mode 100644 index 0000000..0dd79d5 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/debug.h @@ -0,0 +1,152 @@ +/** + * \file debug.h + * + * \brief Debug functions + * + * Copyright (C) 2006-2011, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_DEBUG_H +#define POLARSSL_DEBUG_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif +#include "ssl.h" +#if defined(POLARSSL_ECP_C) +#include "ecp.h" +#endif + +#if defined(POLARSSL_DEBUG_C) + +#define POLARSSL_DEBUG_LOG_FULL 0 /**< Include file:line in log lines */ +#define POLARSSL_DEBUG_LOG_RAW 1 /**< Only log raw debug lines */ + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(POLARSSL_DEBUG_DFL_MODE) +#define POLARSSL_DEBUG_DFL_MODE POLARSSL_DEBUG_LOG_FULL /**< Default log: Full or Raw */ +#endif + +/* \} name SECTION: Module settings */ + + +#define SSL_DEBUG_MSG( level, args ) \ + debug_print_msg( ssl, level, __FILE__, __LINE__, debug_fmt args ); + +#define SSL_DEBUG_RET( level, text, ret ) \ + debug_print_ret( ssl, level, __FILE__, __LINE__, text, ret ); + +#define SSL_DEBUG_BUF( level, text, buf, len ) \ + debug_print_buf( ssl, level, __FILE__, __LINE__, text, buf, len ); + +#if defined(POLARSSL_BIGNUM_C) +#define SSL_DEBUG_MPI( level, text, X ) \ + debug_print_mpi( ssl, level, __FILE__, __LINE__, text, X ); +#endif + +#if defined(POLARSSL_ECP_C) +#define SSL_DEBUG_ECP( level, text, X ) \ + debug_print_ecp( ssl, level, __FILE__, __LINE__, text, X ); +#endif + +#if defined(POLARSSL_X509_CRT_PARSE_C) +#define SSL_DEBUG_CRT( level, text, crt ) \ + debug_print_crt( ssl, level, __FILE__, __LINE__, text, crt ); +#endif + +#else /* POLARSSL_DEBUG_C */ + +#define SSL_DEBUG_MSG( level, args ) do { } while( 0 ) +#define SSL_DEBUG_RET( level, text, ret ) do { } while( 0 ) +#define SSL_DEBUG_BUF( level, text, buf, len ) do { } while( 0 ) +#define SSL_DEBUG_MPI( level, text, X ) do { } while( 0 ) +#define SSL_DEBUG_ECP( level, text, X ) do { } while( 0 ) +#define SSL_DEBUG_CRT( level, text, crt ) do { } while( 0 ) + +#endif /* POLARSSL_DEBUG_C */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Set the log mode for the debug functions globally + * (Default value: POLARSSL_DEBUG_DFL_MODE) + * + * \param log_mode The log mode to use (POLARSSL_DEBUG_LOG_FULL or + * POLARSSL_DEBUG_LOG_RAW) + */ +void debug_set_log_mode( int log_mode ); + +/** + * \brief Set the level threshold to handle globally. Messages that have a + * level over the threshold value are ignored. + * (Default value: 0 (No debug)) + * + * \param threshold maximum level of messages to pass on + */ +void debug_set_threshold( int threshold ); + +char *debug_fmt( const char *format, ... ); + +void debug_print_msg( const ssl_context *ssl, int level, + const char *file, int line, const char *text ); + +void debug_print_ret( const ssl_context *ssl, int level, + const char *file, int line, + const char *text, int ret ); + +void debug_print_buf( const ssl_context *ssl, int level, + const char *file, int line, const char *text, + unsigned char *buf, size_t len ); + +#if defined(POLARSSL_BIGNUM_C) +void debug_print_mpi( const ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mpi *X ); +#endif + +#if defined(POLARSSL_ECP_C) +void debug_print_ecp( const ssl_context *ssl, int level, + const char *file, int line, + const char *text, const ecp_point *X ); +#endif + +#if defined(POLARSSL_X509_CRT_PARSE_C) +void debug_print_crt( const ssl_context *ssl, int level, + const char *file, int line, + const char *text, const x509_crt *crt ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* debug.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/des.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/des.h new file mode 100644 index 0000000..8cf1a3b --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/des.h @@ -0,0 +1,300 @@ +/** + * \file des.h + * + * \brief DES block cipher + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_DES_H +#define POLARSSL_DES_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include + +#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32) +#include +typedef UINT32 uint32_t; +#else +#include +#endif + +#define DES_ENCRYPT 1 +#define DES_DECRYPT 0 + +#define POLARSSL_ERR_DES_INVALID_INPUT_LENGTH -0x0032 /**< The data input has an invalid length. */ + +#define DES_KEY_SIZE 8 + +#if !defined(POLARSSL_DES_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief DES context structure + */ +typedef struct +{ + int mode; /*!< encrypt/decrypt */ + uint32_t sk[32]; /*!< DES subkeys */ +#ifdef RTL_HW_CRYPTO + unsigned char enc_key[DES_KEY_SIZE]; + unsigned char dec_key[DES_KEY_SIZE]; +#endif +} +des_context; + +/** + * \brief Triple-DES context structure + */ +typedef struct +{ + int mode; /*!< encrypt/decrypt */ + uint32_t sk[96]; /*!< 3DES subkeys */ +#ifdef RTL_HW_CRYPTO + unsigned char enc_key[DES_KEY_SIZE * 3]; + unsigned char dec_key[DES_KEY_SIZE * 3]; +#endif +} +des3_context; + +/** + * \brief Initialize DES context + * + * \param ctx DES context to be initialized + */ +void des_init( des_context *ctx ); + +/** + * \brief Clear DES context + * + * \param ctx DES context to be cleared + */ +void des_free( des_context *ctx ); + +/** + * \brief Initialize Triple-DES context + * + * \param ctx DES3 context to be initialized + */ +void des3_init( des3_context *ctx ); + +/** + * \brief Clear Triple-DES context + * + * \param ctx DES3 context to be cleared + */ +void des3_free( des3_context *ctx ); + +/** + * \brief Set key parity on the given key to odd. + * + * DES keys are 56 bits long, but each byte is padded with + * a parity bit to allow verification. + * + * \param key 8-byte secret key + */ +void des_key_set_parity( unsigned char key[DES_KEY_SIZE] ); + +/** + * \brief Check that key parity on the given key is odd. + * + * DES keys are 56 bits long, but each byte is padded with + * a parity bit to allow verification. + * + * \param key 8-byte secret key + * + * \return 0 is parity was ok, 1 if parity was not correct. + */ +int des_key_check_key_parity( const unsigned char key[DES_KEY_SIZE] ); + +/** + * \brief Check that key is not a weak or semi-weak DES key + * + * \param key 8-byte secret key + * + * \return 0 if no weak key was found, 1 if a weak key was identified. + */ +int des_key_check_weak( const unsigned char key[DES_KEY_SIZE] ); + +/** + * \brief DES key schedule (56-bit, encryption) + * + * \param ctx DES context to be initialized + * \param key 8-byte secret key + * + * \return 0 + */ +int des_setkey_enc( des_context *ctx, const unsigned char key[DES_KEY_SIZE] ); + +/** + * \brief DES key schedule (56-bit, decryption) + * + * \param ctx DES context to be initialized + * \param key 8-byte secret key + * + * \return 0 + */ +int des_setkey_dec( des_context *ctx, const unsigned char key[DES_KEY_SIZE] ); + +/** + * \brief Triple-DES key schedule (112-bit, encryption) + * + * \param ctx 3DES context to be initialized + * \param key 16-byte secret key + * + * \return 0 + */ +int des3_set2key_enc( des3_context *ctx, + const unsigned char key[DES_KEY_SIZE * 2] ); + +/** + * \brief Triple-DES key schedule (112-bit, decryption) + * + * \param ctx 3DES context to be initialized + * \param key 16-byte secret key + * + * \return 0 + */ +int des3_set2key_dec( des3_context *ctx, + const unsigned char key[DES_KEY_SIZE * 2] ); + +/** + * \brief Triple-DES key schedule (168-bit, encryption) + * + * \param ctx 3DES context to be initialized + * \param key 24-byte secret key + * + * \return 0 + */ +int des3_set3key_enc( des3_context *ctx, + const unsigned char key[DES_KEY_SIZE * 3] ); + +/** + * \brief Triple-DES key schedule (168-bit, decryption) + * + * \param ctx 3DES context to be initialized + * \param key 24-byte secret key + * + * \return 0 + */ +int des3_set3key_dec( des3_context *ctx, + const unsigned char key[DES_KEY_SIZE * 3] ); + +/** + * \brief DES-ECB block encryption/decryption + * + * \param ctx DES context + * \param input 64-bit input block + * \param output 64-bit output block + * + * \return 0 if successful + */ +int des_crypt_ecb( des_context *ctx, + const unsigned char input[8], + unsigned char output[8] ); + +#if defined(POLARSSL_CIPHER_MODE_CBC) +/** + * \brief DES-CBC buffer encryption/decryption + * + * \param ctx DES context + * \param mode DES_ENCRYPT or DES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + */ +int des_crypt_cbc( des_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ); +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +/** + * \brief 3DES-ECB block encryption/decryption + * + * \param ctx 3DES context + * \param input 64-bit input block + * \param output 64-bit output block + * + * \return 0 if successful + */ +int des3_crypt_ecb( des3_context *ctx, + const unsigned char input[8], + unsigned char output[8] ); + +#if defined(POLARSSL_CIPHER_MODE_CBC) +/** + * \brief 3DES-CBC buffer encryption/decryption + * + * \param ctx 3DES context + * \param mode DES_ENCRYPT or DES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful, or POLARSSL_ERR_DES_INVALID_INPUT_LENGTH + */ +int des3_crypt_cbc( des3_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ); +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#ifdef __cplusplus +} +#endif + +#else /* POLARSSL_DES_ALT */ +#include "des_alt.h" +#endif /* POLARSSL_DES_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int des_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* des.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/dhm.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/dhm.h new file mode 100644 index 0000000..064472f --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/dhm.h @@ -0,0 +1,311 @@ +/** + * \file dhm.h + * + * \brief Diffie-Hellman-Merkle key exchange + * + * Copyright (C) 2006-2013, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_DHM_H +#define POLARSSL_DHM_H + +#include "bignum.h" + +/* + * DHM Error codes + */ +#define POLARSSL_ERR_DHM_BAD_INPUT_DATA -0x3080 /**< Bad input parameters to function. */ +#define POLARSSL_ERR_DHM_READ_PARAMS_FAILED -0x3100 /**< Reading of the DHM parameters failed. */ +#define POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED -0x3180 /**< Making of the DHM parameters failed. */ +#define POLARSSL_ERR_DHM_READ_PUBLIC_FAILED -0x3200 /**< Reading of the public values failed. */ +#define POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED -0x3280 /**< Making of the public value failed. */ +#define POLARSSL_ERR_DHM_CALC_SECRET_FAILED -0x3300 /**< Calculation of the DHM secret failed. */ +#define POLARSSL_ERR_DHM_INVALID_FORMAT -0x3380 /**< The ASN.1 data is not formatted correctly. */ +#define POLARSSL_ERR_DHM_MALLOC_FAILED -0x3400 /**< Allocation of memory failed. */ +#define POLARSSL_ERR_DHM_FILE_IO_ERROR -0x3480 /**< Read/write of file failed. */ + +/** + * RFC 2409 defines a number of standardized Diffie-Hellman groups + * that can be used. + * RFC 3526 defines a number of standardized Diffie-Hellman groups + * for IKE. + * RFC 5114 defines a number of standardized Diffie-Hellman groups + * that can be used. + * + * Some are included here for convenience. + * + * Included are: + * RFC 2409 6.2. 1024-bit MODP Group (Second Oakley Group) + * RFC 3526 3. 2048-bit MODP Group + * RFC 3526 4. 3072-bit MODP Group + * RFC 5114 2.1. 1024-bit MODP Group with 160-bit Prime Order Subgroup + * RFC 5114 2.2. 2048-bit MODP Group with 224-bit Prime Order Subgroup + */ +#define POLARSSL_DHM_RFC2409_MODP_1024_P \ + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" \ + "FFFFFFFFFFFFFFFF" + +#define POLARSSL_DHM_RFC2409_MODP_1024_G "02" + +#define POLARSSL_DHM_RFC3526_MODP_2048_P \ + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ + "15728E5A8AACAA68FFFFFFFFFFFFFFFF" + +#define POLARSSL_DHM_RFC3526_MODP_2048_G "02" + +#define POLARSSL_DHM_RFC3526_MODP_3072_P \ + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \ + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \ + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \ + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \ + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \ + "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF" + +#define POLARSSL_DHM_RFC3526_MODP_3072_G "02" + +#define POLARSSL_DHM_RFC5114_MODP_1024_P \ + "B10B8F96A080E01DDE92DE5EAE5D54EC52C99FBCFB06A3C6" \ + "9A6A9DCA52D23B616073E28675A23D189838EF1E2EE652C0" \ + "13ECB4AEA906112324975C3CD49B83BFACCBDD7D90C4BD70" \ + "98488E9C219A73724EFFD6FAE5644738FAA31A4FF55BCCC0" \ + "A151AF5F0DC8B4BD45BF37DF365C1A65E68CFDA76D4DA708" \ + "DF1FB2BC2E4A4371" + +#define POLARSSL_DHM_RFC5114_MODP_1024_G \ + "A4D1CBD5C3FD34126765A442EFB99905F8104DD258AC507F" \ + "D6406CFF14266D31266FEA1E5C41564B777E690F5504F213" \ + "160217B4B01B886A5E91547F9E2749F4D7FBD7D3B9A92EE1" \ + "909D0D2263F80A76A6A24C087A091F531DBF0A0169B6A28A" \ + "D662A4D18E73AFA32D779D5918D08BC8858F4DCEF97C2A24" \ + "855E6EEB22B3B2E5" + +#define POLARSSL_DHM_RFC5114_MODP_2048_P \ + "AD107E1E9123A9D0D660FAA79559C51FA20D64E5683B9FD1" \ + "B54B1597B61D0A75E6FA141DF95A56DBAF9A3C407BA1DF15" \ + "EB3D688A309C180E1DE6B85A1274A0A66D3F8152AD6AC212" \ + "9037C9EDEFDA4DF8D91E8FEF55B7394B7AD5B7D0B6C12207" \ + "C9F98D11ED34DBF6C6BA0B2C8BBC27BE6A00E0A0B9C49708" \ + "B3BF8A317091883681286130BC8985DB1602E714415D9330" \ + "278273C7DE31EFDC7310F7121FD5A07415987D9ADC0A486D" \ + "CDF93ACC44328387315D75E198C641A480CD86A1B9E587E8" \ + "BE60E69CC928B2B9C52172E413042E9B23F10B0E16E79763" \ + "C9B53DCF4BA80A29E3FB73C16B8E75B97EF363E2FFA31F71" \ + "CF9DE5384E71B81C0AC4DFFE0C10E64F" + +#define POLARSSL_DHM_RFC5114_MODP_2048_G \ + "AC4032EF4F2D9AE39DF30B5C8FFDAC506CDEBE7B89998CAF"\ + "74866A08CFE4FFE3A6824A4E10B9A6F0DD921F01A70C4AFA"\ + "AB739D7700C29F52C57DB17C620A8652BE5E9001A8D66AD7"\ + "C17669101999024AF4D027275AC1348BB8A762D0521BC98A"\ + "E247150422EA1ED409939D54DA7460CDB5F6C6B250717CBE"\ + "F180EB34118E98D119529A45D6F834566E3025E316A330EF"\ + "BB77A86F0C1AB15B051AE3D428C8F8ACB70A8137150B8EEB"\ + "10E183EDD19963DDD9E263E4770589EF6AA21E7F5F2FF381"\ + "B539CCE3409D13CD566AFBB48D6C019181E1BCFE94B30269"\ + "EDFE72FE9B6AA4BD7B5A0F1C71CFFF4C19C418E1F6EC0179"\ + "81BC087F2A7065B384B890D3191F2BFA" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief DHM context structure + */ +typedef struct +{ + size_t len; /*!< size(P) in chars */ + mpi P; /*!< prime modulus */ + mpi G; /*!< generator */ + mpi X; /*!< secret value */ + mpi GX; /*!< self = G^X mod P */ + mpi GY; /*!< peer = G^Y mod P */ + mpi K; /*!< key = GY^X mod P */ + mpi RP; /*!< cached R^2 mod P */ + mpi Vi; /*!< blinding value */ + mpi Vf; /*!< un-blinding value */ + mpi pX; /*!< previous X */ +} +dhm_context; + +/** + * \brief Initialize DHM context + * + * \param ctx DHM context to be initialized + */ +void dhm_init( dhm_context *ctx ); + +/** + * \brief Parse the ServerKeyExchange parameters + * + * \param ctx DHM context + * \param p &(start of input buffer) + * \param end end of buffer + * + * \return 0 if successful, or an POLARSSL_ERR_DHM_XXX error code + */ +int dhm_read_params( dhm_context *ctx, + unsigned char **p, + const unsigned char *end ); + +/** + * \brief Setup and write the ServerKeyExchange parameters + * + * \param ctx DHM context + * \param x_size private value size in bytes + * \param output destination buffer + * \param olen number of chars written + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \note This function assumes that ctx->P and ctx->G + * have already been properly set (for example + * using mpi_read_string or mpi_read_binary). + * + * \return 0 if successful, or an POLARSSL_ERR_DHM_XXX error code + */ +int dhm_make_params( dhm_context *ctx, int x_size, + unsigned char *output, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Import the peer's public value G^Y + * + * \param ctx DHM context + * \param input input buffer + * \param ilen size of buffer + * + * \return 0 if successful, or an POLARSSL_ERR_DHM_XXX error code + */ +int dhm_read_public( dhm_context *ctx, + const unsigned char *input, size_t ilen ); + +/** + * \brief Create own private value X and export G^X + * + * \param ctx DHM context + * \param x_size private value size in bytes + * \param output destination buffer + * \param olen must be equal to ctx->P.len + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful, or an POLARSSL_ERR_DHM_XXX error code + */ +int dhm_make_public( dhm_context *ctx, int x_size, + unsigned char *output, size_t olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Derive and export the shared secret (G^Y)^X mod P + * + * \param ctx DHM context + * \param output destination buffer + * \param olen on entry, must hold the size of the destination buffer + * on exit, holds the actual number of bytes written + * \param f_rng RNG function, for blinding purposes + * \param p_rng RNG parameter + * + * \return 0 if successful, or an POLARSSL_ERR_DHM_XXX error code + * + * \note If non-NULL, f_rng is used to blind the input as + * countermeasure against timing attacks. Blinding is + * automatically used if and only if our secret value X is + * re-used and costs nothing otherwise, so it is recommended + * to always pass a non-NULL f_rng argument. + */ +int dhm_calc_secret( dhm_context *ctx, + unsigned char *output, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Free and clear the components of a DHM key + * + * \param ctx DHM context to free and clear + */ +void dhm_free( dhm_context *ctx ); + +#if defined(POLARSSL_ASN1_PARSE_C) +/** \ingroup x509_module */ +/** + * \brief Parse DHM parameters + * + * \param dhm DHM context to be initialized + * \param dhmin input buffer + * \param dhminlen size of the buffer + * + * \return 0 if successful, or a specific DHM or PEM error code + */ +int dhm_parse_dhm( dhm_context *dhm, const unsigned char *dhmin, + size_t dhminlen ); + +#if defined(POLARSSL_FS_IO) +/** \ingroup x509_module */ +/** + * \brief Load and parse DHM parameters + * + * \param dhm DHM context to be initialized + * \param path filename to read the DHM Parameters from + * + * \return 0 if successful, or a specific DHM or PEM error code + */ +int dhm_parse_dhmfile( dhm_context *dhm, const char *path ); +#endif /* POLARSSL_FS_IO */ +#endif /* POLARSSL_ASN1_PARSE_C */ + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int dhm_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* dhm.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/ecdh.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/ecdh.h new file mode 100644 index 0000000..525cade --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/ecdh.h @@ -0,0 +1,225 @@ +/** + * \file ecdh.h + * + * \brief Elliptic curve Diffie-Hellman + * + * Copyright (C) 2006-2013, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_ECDH_H +#define POLARSSL_ECDH_H + +#include "ecp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * When importing from an EC key, select if it is our key or the peer's key + */ +typedef enum +{ + POLARSSL_ECDH_OURS, + POLARSSL_ECDH_THEIRS, +} ecdh_side; + +/** + * \brief ECDH context structure + */ +typedef struct +{ + ecp_group grp; /*!< elliptic curve used */ + mpi d; /*!< our secret value (private key) */ + ecp_point Q; /*!< our public value (public key) */ + ecp_point Qp; /*!< peer's public value (public key) */ + mpi z; /*!< shared secret */ + int point_format; /*!< format for point export in TLS messages */ + ecp_point Vi; /*!< blinding value (for later) */ + ecp_point Vf; /*!< un-blinding value (for later) */ + mpi _d; /*!< previous d (for later) */ +} +ecdh_context; + +/** + * \brief Generate a public key. + * Raw function that only does the core computation. + * + * \param grp ECP group + * \param d Destination MPI (secret exponent, aka private key) + * \param Q Destination point (public key) + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful, + * or a POLARSSL_ERR_ECP_XXX or POLARSSL_MPI_XXX error code + */ +int ecdh_gen_public( ecp_group *grp, mpi *d, ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Compute shared secret + * Raw function that only does the core computation. + * + * \param grp ECP group + * \param z Destination MPI (shared secret) + * \param Q Public key from other party + * \param d Our secret exponent (private key) + * \param f_rng RNG function (see notes) + * \param p_rng RNG parameter + * + * \return 0 if successful, + * or a POLARSSL_ERR_ECP_XXX or POLARSSL_MPI_XXX error code + * + * \note If f_rng is not NULL, it is used to implement + * countermeasures against potential elaborate timing + * attacks, see \c ecp_mul() for details. + */ +int ecdh_compute_shared( ecp_group *grp, mpi *z, + const ecp_point *Q, const mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Initialize context + * + * \param ctx Context to initialize + */ +void ecdh_init( ecdh_context *ctx ); + +/** + * \brief Free context + * + * \param ctx Context to free + */ +void ecdh_free( ecdh_context *ctx ); + +/** + * \brief Generate a public key and a TLS ServerKeyExchange payload. + * (First function used by a TLS server for ECDHE.) + * + * \param ctx ECDH context + * \param olen number of chars written + * \param buf destination buffer + * \param blen length of buffer + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \note This function assumes that ctx->grp has already been + * properly set (for example using ecp_use_known_dp). + * + * \return 0 if successful, or an POLARSSL_ERR_ECP_XXX error code + */ +int ecdh_make_params( ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Parse and procress a TLS ServerKeyExhange payload. + * (First function used by a TLS client for ECDHE.) + * + * \param ctx ECDH context + * \param buf pointer to start of input buffer + * \param end one past end of buffer + * + * \return 0 if successful, or an POLARSSL_ERR_ECP_XXX error code + */ +int ecdh_read_params( ecdh_context *ctx, + const unsigned char **buf, const unsigned char *end ); + +/** + * \brief Setup an ECDH context from an EC key. + * (Used by clients and servers in place of the + * ServerKeyEchange for static ECDH: import ECDH parameters + * from a certificate's EC key information.) + * + * \param ctx ECDH constext to set + * \param key EC key to use + * \param side Is it our key (1) or the peer's key (0) ? + * + * \return 0 if successful, or an POLARSSL_ERR_ECP_XXX error code + */ +int ecdh_get_params( ecdh_context *ctx, const ecp_keypair *key, + ecdh_side side ); + +/** + * \brief Generate a public key and a TLS ClientKeyExchange payload. + * (Second function used by a TLS client for ECDH(E).) + * + * \param ctx ECDH context + * \param olen number of bytes actually written + * \param buf destination buffer + * \param blen size of destination buffer + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful, or an POLARSSL_ERR_ECP_XXX error code + */ +int ecdh_make_public( ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Parse and process a TLS ClientKeyExchange payload. + * (Second function used by a TLS server for ECDH(E).) + * + * \param ctx ECDH context + * \param buf start of input buffer + * \param blen length of input buffer + * + * \return 0 if successful, or an POLARSSL_ERR_ECP_XXX error code + */ +int ecdh_read_public( ecdh_context *ctx, + const unsigned char *buf, size_t blen ); + +/** + * \brief Derive and export the shared secret. + * (Last function used by both TLS client en servers.) + * + * \param ctx ECDH context + * \param olen number of bytes written + * \param buf destination buffer + * \param blen buffer length + * \param f_rng RNG function, see notes for \c ecdh_compute_shared() + * \param p_rng RNG parameter + * + * \return 0 if successful, or an POLARSSL_ERR_ECP_XXX error code + */ +int ecdh_calc_secret( ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int ecdh_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* ecdh.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/ecdsa.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/ecdsa.h new file mode 100644 index 0000000..d99a17a --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/ecdsa.h @@ -0,0 +1,236 @@ +/** + * \file ecdsa.h + * + * \brief Elliptic curve DSA + * + * Copyright (C) 2006-2013, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_ECDSA_H +#define POLARSSL_ECDSA_H + +#include "ecp.h" + +#if defined(POLARSSL_ECDSA_DETERMINISTIC) +#include "md.h" +#endif + +/** + * \brief ECDSA context structure + * + * \note Purposefully begins with the same members as struct ecp_keypair. + */ +typedef struct +{ + ecp_group grp; /*!< elliptic curve used */ + mpi d; /*!< secret signature key */ + ecp_point Q; /*!< public signature key */ + mpi r; /*!< first integer from signature */ + mpi s; /*!< second integer from signature */ +} +ecdsa_context; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Compute ECDSA signature of a previously hashed message + * + * \param grp ECP group + * \param r First output integer + * \param s Second output integer + * \param d Private signing key + * \param buf Message hash + * \param blen Length of buf + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful, + * or a POLARSSL_ERR_ECP_XXX or POLARSSL_MPI_XXX error code + */ +int ecdsa_sign( ecp_group *grp, mpi *r, mpi *s, + const mpi *d, const unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +#if defined(POLARSSL_ECDSA_DETERMINISTIC) +/** + * \brief Compute ECDSA signature of a previously hashed message + * (deterministic version) + * + * \param grp ECP group + * \param r First output integer + * \param s Second output integer + * \param d Private signing key + * \param buf Message hash + * \param blen Length of buf + * \param md_alg MD algorithm used to hash the message + * + * \return 0 if successful, + * or a POLARSSL_ERR_ECP_XXX or POLARSSL_MPI_XXX error code + */ +int ecdsa_sign_det( ecp_group *grp, mpi *r, mpi *s, + const mpi *d, const unsigned char *buf, size_t blen, + md_type_t md_alg ); +#endif /* POLARSSL_ECDSA_DETERMINISTIC */ + +/** + * \brief Verify ECDSA signature of a previously hashed message + * + * \param grp ECP group + * \param buf Message hash + * \param blen Length of buf + * \param Q Public key to use for verification + * \param r First integer of the signature + * \param s Second integer of the signature + * + * \return 0 if successful, + * POLARSSL_ERR_ECP_BAD_INPUT_DATA if signature is invalid + * or a POLARSSL_ERR_ECP_XXX or POLARSSL_MPI_XXX error code + */ +int ecdsa_verify( ecp_group *grp, + const unsigned char *buf, size_t blen, + const ecp_point *Q, const mpi *r, const mpi *s); + +/** + * \brief Compute ECDSA signature and write it to buffer, + * serialized as defined in RFC 4492 page 20. + * (Not thread-safe to use same context in multiple threads) + * + * \param ctx ECDSA context + * \param hash Message hash + * \param hlen Length of hash + * \param sig Buffer that will hold the signature + * \param slen Length of the signature written + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \note The "sig" buffer must be at least as large as twice the + * size of the curve used, plus 7 (eg. 71 bytes if a 256-bit + * curve is used). + * + * \return 0 if successful, + * or a POLARSSL_ERR_ECP, POLARSSL_ERR_MPI or + * POLARSSL_ERR_ASN1 error code + */ +int ecdsa_write_signature( ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#if defined(POLARSSL_ECDSA_DETERMINISTIC) +/** + * \brief Compute ECDSA signature and write it to buffer, + * serialized as defined in RFC 4492 page 20. + * Deterministic version, RFC 6979. + * (Not thread-safe to use same context in multiple threads) + * + * \param ctx ECDSA context + * \param hash Message hash + * \param hlen Length of hash + * \param sig Buffer that will hold the signature + * \param slen Length of the signature written + * \param md_alg MD algorithm used to hash the message + * + * \note The "sig" buffer must be at least as large as twice the + * size of the curve used, plus 7 (eg. 71 bytes if a 256-bit + * curve is used). + * + * \return 0 if successful, + * or a POLARSSL_ERR_ECP, POLARSSL_ERR_MPI or + * POLARSSL_ERR_ASN1 error code + */ +int ecdsa_write_signature_det( ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + md_type_t md_alg ); +#endif /* POLARSSL_ECDSA_DETERMINISTIC */ + +/** + * \brief Read and verify an ECDSA signature + * + * \param ctx ECDSA context + * \param hash Message hash + * \param hlen Size of hash + * \param sig Signature to read and verify + * \param slen Size of sig + * + * \return 0 if successful, + * POLARSSL_ERR_ECP_BAD_INPUT_DATA if signature is invalid, + * POLARSSL_ERR_ECP_SIG_LEN_MISTMATCH if the signature is + * valid but its actual length is less than siglen, + * or a POLARSSL_ERR_ECP or POLARSSL_ERR_MPI error code + */ +int ecdsa_read_signature( ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + const unsigned char *sig, size_t slen ); + +/** + * \brief Generate an ECDSA keypair on the given curve + * + * \param ctx ECDSA context in which the keypair should be stored + * \param gid Group (elliptic curve) to use. One of the various + * POLARSSL_ECP_DP_XXX macros depending on configuration. + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 on success, or a POLARSSL_ERR_ECP code. + */ +int ecdsa_genkey( ecdsa_context *ctx, ecp_group_id gid, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Set an ECDSA context from an EC key pair + * + * \param ctx ECDSA context to set + * \param key EC key to use + * + * \return 0 on success, or a POLARSSL_ERR_ECP code. + */ +int ecdsa_from_keypair( ecdsa_context *ctx, const ecp_keypair *key ); + +/** + * \brief Initialize context + * + * \param ctx Context to initialize + */ +void ecdsa_init( ecdsa_context *ctx ); + +/** + * \brief Free context + * + * \param ctx Context to free + */ +void ecdsa_free( ecdsa_context *ctx ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int ecdsa_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* ecdsa.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/ecp.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/ecp.h new file mode 100644 index 0000000..7192f1e --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/ecp.h @@ -0,0 +1,651 @@ +/** + * \file ecp.h + * + * \brief Elliptic curves over GF(p) + * + * Copyright (C) 2006-2013, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_ECP_H +#define POLARSSL_ECP_H + +#include "bignum.h" + +/* + * ECP error codes + */ +#define POLARSSL_ERR_ECP_BAD_INPUT_DATA -0x4F80 /**< Bad input parameters to function. */ +#define POLARSSL_ERR_ECP_BUFFER_TOO_SMALL -0x4F00 /**< The buffer is too small to write to. */ +#define POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE -0x4E80 /**< Requested curve not available. */ +#define POLARSSL_ERR_ECP_VERIFY_FAILED -0x4E00 /**< The signature is not valid. */ +#define POLARSSL_ERR_ECP_MALLOC_FAILED -0x4D80 /**< Memory allocation failed. */ +#define POLARSSL_ERR_ECP_RANDOM_FAILED -0x4D00 /**< Generation of random value, such as (ephemeral) key, failed. */ +#define POLARSSL_ERR_ECP_INVALID_KEY -0x4C80 /**< Invalid private or public key. */ +#define POLARSSL_ERR_ECP_SIG_LEN_MISMATCH -0x4C00 /**< Signature is valid but shorter than the user-supplied length. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Domain parameters (curve, subgroup and generator) identifiers. + * + * Only curves over prime fields are supported. + * + * \warning This library does not support validation of arbitrary domain + * parameters. Therefore, only well-known domain parameters from trusted + * sources should be used. See ecp_use_known_dp(). + */ +typedef enum +{ + POLARSSL_ECP_DP_NONE = 0, + POLARSSL_ECP_DP_SECP192R1, /*!< 192-bits NIST curve */ + POLARSSL_ECP_DP_SECP224R1, /*!< 224-bits NIST curve */ + POLARSSL_ECP_DP_SECP256R1, /*!< 256-bits NIST curve */ + POLARSSL_ECP_DP_SECP384R1, /*!< 384-bits NIST curve */ + POLARSSL_ECP_DP_SECP521R1, /*!< 521-bits NIST curve */ + POLARSSL_ECP_DP_BP256R1, /*!< 256-bits Brainpool curve */ + POLARSSL_ECP_DP_BP384R1, /*!< 384-bits Brainpool curve */ + POLARSSL_ECP_DP_BP512R1, /*!< 512-bits Brainpool curve */ + POLARSSL_ECP_DP_M221, /*!< (not implemented yet) */ + POLARSSL_ECP_DP_M255, /*!< Curve25519 */ + POLARSSL_ECP_DP_M383, /*!< (not implemented yet) */ + POLARSSL_ECP_DP_M511, /*!< (not implemented yet) */ + POLARSSL_ECP_DP_SECP192K1, /*!< 192-bits "Koblitz" curve */ + POLARSSL_ECP_DP_SECP224K1, /*!< 224-bits "Koblitz" curve */ + POLARSSL_ECP_DP_SECP256K1, /*!< 256-bits "Koblitz" curve */ +} ecp_group_id; + +/** + * Number of supported curves (plus one for NONE). + * + * (Montgomery curves excluded for now.) + */ +#define POLARSSL_ECP_DP_MAX 12 + +/** + * Curve information for use by other modules + */ +typedef struct +{ + ecp_group_id grp_id; /*!< Internal identifier */ + uint16_t tls_id; /*!< TLS NamedCurve identifier */ + uint16_t size; /*!< Curve size in bits */ + const char *name; /*!< Human-friendly name */ +} ecp_curve_info; + +/** + * \brief ECP point structure (jacobian coordinates) + * + * \note All functions expect and return points satisfying + * the following condition: Z == 0 or Z == 1. (Other + * values of Z are used by internal functions only.) + * The point is zero, or "at infinity", if Z == 0. + * Otherwise, X and Y are its standard (affine) coordinates. + */ +typedef struct +{ + mpi X; /*!< the point's X coordinate */ + mpi Y; /*!< the point's Y coordinate */ + mpi Z; /*!< the point's Z coordinate */ +} +ecp_point; + +/** + * \brief ECP group structure + * + * We consider two types of curves equations: + * 1. Short Weierstrass y^2 = x^3 + A x + B mod P (SEC1 + RFC 4492) + * 2. Montgomery, y^2 = x^3 + A x^2 + x mod P (M255 + draft) + * In both cases, a generator G for a prime-order subgroup is fixed. In the + * short weierstrass, this subgroup is actually the whole curve, and its + * cardinal is denoted by N. + * + * In the case of Short Weierstrass curves, our code requires that N is an odd + * prime. (Use odd in ecp_mul() and prime in ecdsa_sign() for blinding.) + * + * In the case of Montgomery curves, we don't store A but (A + 2) / 4 which is + * the quantity actually used in the formulas. Also, nbits is not the size of N + * but the required size for private keys. + * + * If modp is NULL, reduction modulo P is done using a generic algorithm. + * Otherwise, it must point to a function that takes an mpi in the range + * 0..2^(2*pbits)-1 and transforms it in-place in an integer of little more + * than pbits, so that the integer may be efficiently brought in the 0..P-1 + * range by a few additions or substractions. It must return 0 on success and + * non-zero on failure. + */ +typedef struct +{ + ecp_group_id id; /*!< internal group identifier */ + mpi P; /*!< prime modulus of the base field */ + mpi A; /*!< 1. A in the equation, or 2. (A + 2) / 4 */ + mpi B; /*!< 1. B in the equation, or 2. unused */ + ecp_point G; /*!< generator of the (sub)group used */ + mpi N; /*!< 1. the order of G, or 2. unused */ + size_t pbits; /*!< number of bits in P */ + size_t nbits; /*!< number of bits in 1. P, or 2. private keys */ + unsigned int h; /*!< internal: 1 if the constants are static */ + int (*modp)(mpi *); /*!< function for fast reduction mod P */ + int (*t_pre)(ecp_point *, void *); /*!< unused */ + int (*t_post)(ecp_point *, void *); /*!< unused */ + void *t_data; /*!< unused */ + ecp_point *T; /*!< pre-computed points for ecp_mul_comb() */ + size_t T_size; /*!< number for pre-computed points */ +} +ecp_group; + +/** + * \brief ECP key pair structure + * + * A generic key pair that could be used for ECDSA, fixed ECDH, etc. + * + * \note Members purposefully in the same order as struc ecdsa_context. + */ +typedef struct +{ + ecp_group grp; /*!< Elliptic curve and base point */ + mpi d; /*!< our secret value */ + ecp_point Q; /*!< our public value */ +} +ecp_keypair; + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(POLARSSL_ECP_MAX_BITS) +/** + * Maximum size of the groups (that is, of N and P) + */ +#define POLARSSL_ECP_MAX_BITS 521 /**< Maximum bit size of groups */ +#endif + +#define POLARSSL_ECP_MAX_BYTES ( ( POLARSSL_ECP_MAX_BITS + 7 ) / 8 ) +#define POLARSSL_ECP_MAX_PT_LEN ( 2 * POLARSSL_ECP_MAX_BYTES + 1 ) + +#if !defined(POLARSSL_ECP_WINDOW_SIZE) +/* + * Maximum "window" size used for point multiplication. + * Default: 6. + * Minimum value: 2. Maximum value: 7. + * + * Result is an array of at most ( 1 << ( POLARSSL_ECP_WINDOW_SIZE - 1 ) ) + * points used for point multiplication. This value is directly tied to EC + * peak memory usage, so decreasing it by one should roughly cut memory usage + * by two (if large curves are in use). + * + * Reduction in size may reduce speed, but larger curves are impacted first. + * Sample performances (in ECDHE handshakes/s, with FIXED_POINT_OPTIM = 1): + * w-size: 6 5 4 3 2 + * 521 145 141 135 120 97 + * 384 214 209 198 177 146 + * 256 320 320 303 262 226 + + * 224 475 475 453 398 342 + * 192 640 640 633 587 476 + */ +#define POLARSSL_ECP_WINDOW_SIZE 6 /**< Maximum window size used */ +#endif /* POLARSSL_ECP_WINDOW_SIZE */ + +#if !defined(POLARSSL_ECP_FIXED_POINT_OPTIM) +/* + * Trade memory for speed on fixed-point multiplication. + * + * This speeds up repeated multiplication of the generator (that is, the + * multiplication in ECDSA signatures, and half of the multiplications in + * ECDSA verification and ECDHE) by a factor roughly 3 to 4. + * + * The cost is increasing EC peak memory usage by a factor roughly 2. + * + * Change this value to 0 to reduce peak memory usage. + */ +#define POLARSSL_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up */ +#endif /* POLARSSL_ECP_FIXED_POINT_OPTIM */ + +/* \} name SECTION: Module settings */ + +/* + * Point formats, from RFC 4492's enum ECPointFormat + */ +#define POLARSSL_ECP_PF_UNCOMPRESSED 0 /**< Uncompressed point format */ +#define POLARSSL_ECP_PF_COMPRESSED 1 /**< Compressed point format */ + +/* + * Some other constants from RFC 4492 + */ +#define POLARSSL_ECP_TLS_NAMED_CURVE 3 /**< ECCurveType's named_curve */ + +/** + * \brief Get the list of supported curves in order of preferrence + * (full information) + * + * \return A statically allocated array, the last entry is 0. + */ +const ecp_curve_info *ecp_curve_list( void ); + +/** + * \brief Get the list of supported curves in order of preferrence + * (grp_id only) + * + * \return A statically allocated array, + * terminated with POLARSSL_ECP_DP_NONE. + */ +const ecp_group_id *ecp_grp_id_list( void ); + +/** + * \brief Get curve information from an internal group identifier + * + * \param grp_id A POLARSSL_ECP_DP_XXX value + * + * \return The associated curve information or NULL + */ +const ecp_curve_info *ecp_curve_info_from_grp_id( ecp_group_id grp_id ); + +/** + * \brief Get curve information from a TLS NamedCurve value + * + * \param tls_id A POLARSSL_ECP_DP_XXX value + * + * \return The associated curve information or NULL + */ +const ecp_curve_info *ecp_curve_info_from_tls_id( uint16_t tls_id ); + +/** + * \brief Get curve information from a human-readable name + * + * \param name The name + * + * \return The associated curve information or NULL + */ +const ecp_curve_info *ecp_curve_info_from_name( const char *name ); + +/** + * \brief Initialize a point (as zero) + */ +void ecp_point_init( ecp_point *pt ); + +/** + * \brief Initialize a group (to something meaningless) + */ +void ecp_group_init( ecp_group *grp ); + +/** + * \brief Initialize a key pair (as an invalid one) + */ +void ecp_keypair_init( ecp_keypair *key ); + +/** + * \brief Free the components of a point + */ +void ecp_point_free( ecp_point *pt ); + +/** + * \brief Free the components of an ECP group + */ +void ecp_group_free( ecp_group *grp ); + +/** + * \brief Free the components of a key pair + */ +void ecp_keypair_free( ecp_keypair *key ); + +/** + * \brief Copy the contents of point Q into P + * + * \param P Destination point + * \param Q Source point + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int ecp_copy( ecp_point *P, const ecp_point *Q ); + +/** + * \brief Copy the contents of a group object + * + * \param dst Destination group + * \param src Source group + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int ecp_group_copy( ecp_group *dst, const ecp_group *src ); + +/** + * \brief Set a point to zero + * + * \param pt Destination point + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + */ +int ecp_set_zero( ecp_point *pt ); + +/** + * \brief Tell if a point is zero + * + * \param pt Point to test + * + * \return 1 if point is zero, 0 otherwise + */ +int ecp_is_zero( ecp_point *pt ); + +/** + * \brief Import a non-zero point from two ASCII strings + * + * \param P Destination point + * \param radix Input numeric base + * \param x First affine coordinate as a null-terminated string + * \param y Second affine coordinate as a null-terminated string + * + * \return 0 if successful, or a POLARSSL_ERR_MPI_XXX error code + */ +int ecp_point_read_string( ecp_point *P, int radix, + const char *x, const char *y ); + +/** + * \brief Export a point into unsigned binary data + * + * \param grp Group to which the point should belong + * \param P Point to export + * \param format Point format, should be a POLARSSL_ECP_PF_XXX macro + * \param olen Length of the actual output + * \param buf Output buffer + * \param buflen Length of the output buffer + * + * \return 0 if successful, + * or POLARSSL_ERR_ECP_BAD_INPUT_DATA + * or POLARSSL_ERR_ECP_BUFFER_TOO_SMALL + */ +int ecp_point_write_binary( const ecp_group *grp, const ecp_point *P, + int format, size_t *olen, + unsigned char *buf, size_t buflen ); + +/** + * \brief Import a point from unsigned binary data + * + * \param grp Group to which the point should belong + * \param P Point to import + * \param buf Input buffer + * \param ilen Actual length of input + * + * \return 0 if successful, + * POLARSSL_ERR_ECP_BAD_INPUT_DATA if input is invalid, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE if the point format + * is not implemented. + * + * \note This function does NOT check that the point actually + * belongs to the given group, see ecp_check_pubkey() for + * that. + */ +int ecp_point_read_binary( const ecp_group *grp, ecp_point *P, + const unsigned char *buf, size_t ilen ); + +/** + * \brief Import a point from a TLS ECPoint record + * + * \param grp ECP group used + * \param pt Destination point + * \param buf $(Start of input buffer) + * \param len Buffer length + * + * \return O if successful, + * POLARSSL_ERR_MPI_XXX if initialization failed + * POLARSSL_ERR_ECP_BAD_INPUT_DATA if input is invalid + */ +int ecp_tls_read_point( const ecp_group *grp, ecp_point *pt, + const unsigned char **buf, size_t len ); + +/** + * \brief Export a point as a TLS ECPoint record + * + * \param grp ECP group used + * \param pt Point to export + * \param format Export format + * \param olen length of data written + * \param buf Buffer to write to + * \param blen Buffer length + * + * \return 0 if successful, + * or POLARSSL_ERR_ECP_BAD_INPUT_DATA + * or POLARSSL_ERR_ECP_BUFFER_TOO_SMALL + */ +int ecp_tls_write_point( const ecp_group *grp, const ecp_point *pt, + int format, size_t *olen, + unsigned char *buf, size_t blen ); + +/** + * \brief Import an ECP group from null-terminated ASCII strings + * + * \param grp Destination group + * \param radix Input numeric base + * \param p Prime modulus of the base field + * \param b Constant term in the equation + * \param gx The generator's X coordinate + * \param gy The generator's Y coordinate + * \param n The generator's order + * + * \return 0 if successful, or a POLARSSL_ERR_MPI_XXX error code + * + * \note Sets all fields except modp. + */ +int ecp_group_read_string( ecp_group *grp, int radix, + const char *p, const char *b, + const char *gx, const char *gy, const char *n); + +/** + * \brief Set a group using well-known domain parameters + * + * \param grp Destination group + * \param index Index in the list of well-known domain parameters + * + * \return O if successful, + * POLARSSL_ERR_MPI_XXX if initialization failed + * POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE for unkownn groups + * + * \note Index should be a value of RFC 4492's enum NamdeCurve, + * possibly in the form of a POLARSSL_ECP_DP_XXX macro. + */ +int ecp_use_known_dp( ecp_group *grp, ecp_group_id index ); + +/** + * \brief Set a group from a TLS ECParameters record + * + * \param grp Destination group + * \param buf &(Start of input buffer) + * \param len Buffer length + * + * \return O if successful, + * POLARSSL_ERR_MPI_XXX if initialization failed + * POLARSSL_ERR_ECP_BAD_INPUT_DATA if input is invalid + */ +int ecp_tls_read_group( ecp_group *grp, const unsigned char **buf, size_t len ); + +/** + * \brief Write the TLS ECParameters record for a group + * + * \param grp ECP group used + * \param olen Number of bytes actually written + * \param buf Buffer to write to + * \param blen Buffer length + * + * \return 0 if successful, + * or POLARSSL_ERR_ECP_BUFFER_TOO_SMALL + */ +int ecp_tls_write_group( const ecp_group *grp, size_t *olen, + unsigned char *buf, size_t blen ); + +/** + * \brief Addition: R = P + Q + * + * \param grp ECP group + * \param R Destination point + * \param P Left-hand point + * \param Q Right-hand point + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + * + * \note This function does not support Montgomery curves, such as + * Curve25519. + */ +int ecp_add( const ecp_group *grp, ecp_point *R, + const ecp_point *P, const ecp_point *Q ); + +/** + * \brief Subtraction: R = P - Q + * + * \param grp ECP group + * \param R Destination point + * \param P Left-hand point + * \param Q Right-hand point + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + * + * \note This function does not support Montgomery curves, such as + * Curve25519. + */ +int ecp_sub( const ecp_group *grp, ecp_point *R, + const ecp_point *P, const ecp_point *Q ); + +/** + * \brief Multiplication by an integer: R = m * P + * (Not thread-safe to use same group in multiple threads) + * + * \param grp ECP group + * \param R Destination point + * \param m Integer by which to multiply + * \param P Point to multiply + * \param f_rng RNG function (see notes) + * \param p_rng RNG parameter + * + * \return 0 if successful, + * POLARSSL_ERR_ECP_INVALID_KEY if m is not a valid privkey + * or P is not a valid pubkey, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed + * + * \note In order to prevent timing attacks, this function + * executes the exact same sequence of (base field) + * operations for any valid m. It avoids any if-branch or + * array index depending on the value of m. + * + * \note If f_rng is not NULL, it is used to randomize intermediate + * results in order to prevent potential timing attacks + * targeting these results. It is recommended to always + * provide a non-NULL f_rng (the overhead is negligible). + */ +int ecp_mul( ecp_group *grp, ecp_point *R, + const mpi *m, const ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Check that a point is a valid public key on this curve + * + * \param grp Curve/group the point should belong to + * \param pt Point to check + * + * \return 0 if point is a valid public key, + * POLARSSL_ERR_ECP_INVALID_KEY otherwise. + * + * \note This function only checks the point is non-zero, has valid + * coordinates and lies on the curve, but not that it is + * indeed a multiple of G. This is additional check is more + * expensive, isn't required by standards, and shouldn't be + * necessary if the group used has a small cofactor. In + * particular, it is useless for the NIST groups which all + * have a cofactor of 1. + * + * \note Uses bare components rather than an ecp_keypair structure + * in order to ease use with other structures such as + * ecdh_context of ecdsa_context. + */ +int ecp_check_pubkey( const ecp_group *grp, const ecp_point *pt ); + +/** + * \brief Check that an mpi is a valid private key for this curve + * + * \param grp Group used + * \param d Integer to check + * + * \return 0 if point is a valid private key, + * POLARSSL_ERR_ECP_INVALID_KEY otherwise. + * + * \note Uses bare components rather than an ecp_keypair structure + * in order to ease use with other structures such as + * ecdh_context of ecdsa_context. + */ +int ecp_check_privkey( const ecp_group *grp, const mpi *d ); + +/** + * \brief Generate a keypair + * + * \param grp ECP group + * \param d Destination MPI (secret part) + * \param Q Destination point (public part) + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful, + * or a POLARSSL_ERR_ECP_XXX or POLARSSL_MPI_XXX error code + * + * \note Uses bare components rather than an ecp_keypair structure + * in order to ease use with other structures such as + * ecdh_context of ecdsa_context. + */ +int ecp_gen_keypair( ecp_group *grp, mpi *d, ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Generate a keypair + * + * \param grp_id ECP group identifier + * \param key Destination keypair + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful, + * or a POLARSSL_ERR_ECP_XXX or POLARSSL_MPI_XXX error code + */ +int ecp_gen_key( ecp_group_id grp_id, ecp_keypair *key, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +#if defined(POLARSSL_SELF_TEST) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if a test failed + */ +int ecp_self_test( int verbose ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* ecp.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/entropy.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/entropy.h new file mode 100644 index 0000000..f5fa928 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/entropy.h @@ -0,0 +1,246 @@ +/** + * \file entropy.h + * + * \brief Entropy accumulator implementation + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_ENTROPY_H +#define POLARSSL_ENTROPY_H + +#include + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_SHA512_C) && !defined(POLARSSL_ENTROPY_FORCE_SHA256) +#include "sha512.h" +#define POLARSSL_ENTROPY_SHA512_ACCUMULATOR +#else +#if defined(POLARSSL_SHA256_C) +#define POLARSSL_ENTROPY_SHA256_ACCUMULATOR +#include "sha256.h" +#endif +#endif + +#if defined(POLARSSL_THREADING_C) +#include "threading.h" +#endif + +#if defined(POLARSSL_HAVEGE_C) +#include "havege.h" +#endif + +#define POLARSSL_ERR_ENTROPY_SOURCE_FAILED -0x003C /**< Critical entropy source failure. */ +#define POLARSSL_ERR_ENTROPY_MAX_SOURCES -0x003E /**< No more sources can be added. */ +#define POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED -0x0040 /**< No sources have been added to poll. */ +#define POLARSSL_ERR_ENTROPY_FILE_IO_ERROR -0x0058 /**< Read/write error in file. */ + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(ENTROPY_MAX_SOURCES) +#define ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ +#endif + +#if !defined(ENTROPY_MAX_GATHER) +#define ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ +#endif + +/* \} name SECTION: Module settings */ + +#if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR) +#define ENTROPY_BLOCK_SIZE 64 /**< Block size of entropy accumulator (SHA-512) */ +#else +#define ENTROPY_BLOCK_SIZE 32 /**< Block size of entropy accumulator (SHA-256) */ +#endif + +#define ENTROPY_MAX_SEED_SIZE 1024 /**< Maximum size of seed we read from seed file */ +#define ENTROPY_SOURCE_MANUAL ENTROPY_MAX_SOURCES + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Entropy poll callback pointer + * + * \param data Callback-specific data pointer + * \param output Data to fill + * \param len Maximum size to provide + * \param olen The actual amount of bytes put into the buffer (Can be 0) + * + * \return 0 if no critical failures occurred, + * POLARSSL_ERR_ENTROPY_SOURCE_FAILED otherwise + */ +typedef int (*f_source_ptr)(void *data, unsigned char *output, size_t len, + size_t *olen); + +/** + * \brief Entropy source state + */ +typedef struct +{ + f_source_ptr f_source; /**< The entropy source callback */ + void * p_source; /**< The callback data pointer */ + size_t size; /**< Amount received */ + size_t threshold; /**< Minimum level required before release */ +} +source_state; + +/** + * \brief Entropy context structure + */ +typedef struct +{ +#if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR) + sha512_context accumulator; +#else + sha256_context accumulator; +#endif + int source_count; + source_state source[ENTROPY_MAX_SOURCES]; +#if defined(POLARSSL_HAVEGE_C) + havege_state havege_data; +#endif +#if defined(POLARSSL_THREADING_C) + threading_mutex_t mutex; /*!< mutex */ +#endif +} +entropy_context; + +/** + * \brief Initialize the context + * + * \param ctx Entropy context to initialize + */ +void entropy_init( entropy_context *ctx ); + +/** + * \brief Free the data in the context + * + * \param ctx Entropy context to free + */ +void entropy_free( entropy_context *ctx ); + +/** + * \brief Adds an entropy source to poll + * (Thread-safe if POLARSSL_THREADING_C is enabled) + * + * \param ctx Entropy context + * \param f_source Entropy function + * \param p_source Function data + * \param threshold Minimum required from source before entropy is released + * ( with entropy_func() ) + * + * \return 0 if successful or POLARSSL_ERR_ENTROPY_MAX_SOURCES + */ +int entropy_add_source( entropy_context *ctx, + f_source_ptr f_source, void *p_source, + size_t threshold ); + +/** + * \brief Trigger an extra gather poll for the accumulator + * (Thread-safe if POLARSSL_THREADING_C is enabled) + * + * \param ctx Entropy context + * + * \return 0 if successful, or POLARSSL_ERR_ENTROPY_SOURCE_FAILED + */ +int entropy_gather( entropy_context *ctx ); + +/** + * \brief Retrieve entropy from the accumulator + * (Maximum length: ENTROPY_BLOCK_SIZE) + * (Thread-safe if POLARSSL_THREADING_C is enabled) + * + * \param data Entropy context + * \param output Buffer to fill + * \param len Number of bytes desired, must be at most ENTROPY_BLOCK_SIZE + * + * \return 0 if successful, or POLARSSL_ERR_ENTROPY_SOURCE_FAILED + */ +int entropy_func( void *data, unsigned char *output, size_t len ); + +/** + * \brief Add data to the accumulator manually + * (Thread-safe if POLARSSL_THREADING_C is enabled) + * + * \param ctx Entropy context + * \param data Data to add + * \param len Length of data + * + * \return 0 if successful + */ +int entropy_update_manual( entropy_context *ctx, + const unsigned char *data, size_t len ); + +#if defined(POLARSSL_FS_IO) +/** + * \brief Write a seed file + * + * \param ctx Entropy context + * \param path Name of the file + * + * \return 0 if successful, + * POLARSSL_ERR_ENTROPY_FILE_IO_ERROR on file error, or + * POLARSSL_ERR_ENTROPY_SOURCE_FAILED + */ +int entropy_write_seed_file( entropy_context *ctx, const char *path ); + +/** + * \brief Read and update a seed file. Seed is added to this + * instance. No more than ENTROPY_MAX_SEED_SIZE bytes are + * read from the seed file. The rest is ignored. + * + * \param ctx Entropy context + * \param path Name of the file + * + * \return 0 if successful, + * POLARSSL_ERR_ENTROPY_FILE_IO_ERROR on file error, + * POLARSSL_ERR_ENTROPY_SOURCE_FAILED + */ +int entropy_update_seed_file( entropy_context *ctx, const char *path ); +#endif /* POLARSSL_FS_IO */ + +#if defined(POLARSSL_SELF_TEST) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if a test failed + */ +int entropy_self_test( int verbose ); +#endif /* POLARSSL_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* entropy.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/entropy_poll.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/entropy_poll.h new file mode 100644 index 0000000..92efa00 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/entropy_poll.h @@ -0,0 +1,79 @@ +/** + * \file entropy_poll.h + * + * \brief Platform-specific and custom entropy polling functions + * + * Copyright (C) 2006-2011, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_ENTROPY_POLL_H +#define POLARSSL_ENTROPY_POLL_H + +#include + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Default thresholds for built-in sources + */ +#define ENTROPY_MIN_PLATFORM 128 /**< Minimum for platform source */ +#define ENTROPY_MIN_HAVEGE 128 /**< Minimum for HAVEGE */ +#define ENTROPY_MIN_HARDCLOCK 32 /**< Minimum for hardclock() */ + +#if !defined(POLARSSL_NO_PLATFORM_ENTROPY) +/** + * \brief Platform-specific entropy poll callback + */ +int platform_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if defined(POLARSSL_HAVEGE_C) +/** + * \brief HAVEGE based entropy poll callback + * + * Requires an HAVEGE state as its data pointer. + */ +int havege_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if defined(POLARSSL_TIMING_C) +/** + * \brief hardclock-based entropy poll callback + */ +int hardclock_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* entropy_poll.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/error.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/error.h new file mode 100644 index 0000000..cdee952 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/error.h @@ -0,0 +1,123 @@ +/** + * \file error.h + * + * \brief Error to string translation + * + * Copyright (C) 2006-2013, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_ERROR_H +#define POLARSSL_ERROR_H + +#include + +/** + * Error code layout. + * + * Currently we try to keep all error codes within the negative space of 16 + * bytes signed integers to support all platforms (-0x0000 - -0x8000). In + * addition we'd like to give two layers of information on the error if + * possible. + * + * For that purpose the error codes are segmented in the following manner: + * + * 16 bit error code bit-segmentation + * + * 1 bit - Sign bit + * 3 bits - High level module ID + * 5 bits - Module-dependent error code + * 7 bits - Low level module errors + * + * For historical reasons, low-level error codes are divided in even and odd, + * even codes were assigned first, and -1 is reserved for other errors. + * + * Low-level module errors (0x0002-0x007E, 0x0003-0x007F) + * + * Module Nr Codes assigned + * MPI 7 0x0002-0x0010 + * GCM 2 0x0012-0x0014 + * BLOWFISH 2 0x0016-0x0018 + * THREADING 3 0x001A-0x001E + * AES 2 0x0020-0x0022 + * CAMELLIA 2 0x0024-0x0026 + * XTEA 1 0x0028-0x0028 + * BASE64 2 0x002A-0x002C + * OID 1 0x002E-0x002E 0x000B-0x000B + * PADLOCK 1 0x0030-0x0030 + * DES 1 0x0032-0x0032 + * CTR_DBRG 4 0x0034-0x003A + * ENTROPY 3 0x003C-0x0040 + * NET 11 0x0042-0x0056 + * ENTROPY 1 0x0058-0x0058 + * ASN1 7 0x0060-0x006C + * MD2 1 0x0070-0x0070 + * MD4 1 0x0072-0x0072 + * MD5 1 0x0074-0x0074 + * SHA1 1 0x0076-0x0076 + * SHA256 1 0x0078-0x0078 + * SHA512 1 0x007A-0x007A + * PBKDF2 1 0x007C-0x007C + * RIPEMD160 1 0x007E-0x007E + * HMAC_DRBG 4 0x0003-0x0009 + * CCM 2 0x000D-0x000F + * + * High-level module nr (3 bits - 0x0...-0x7...) + * Name ID Nr of Errors + * PEM 1 9 + * PKCS#12 1 4 (Started from top) + * X509 2 18 + * PK 2 14 (Started from top, plus 0x2000) + * DHM 3 9 + * PKCS5 3 4 (Started from top) + * RSA 4 9 + * ECP 4 8 (Started from top) + * MD 5 4 + * CIPHER 6 6 + * SSL 6 9 (Started from top) + * SSL 7 31 + * + * Module dependent error code (5 bits 0x.00.-0x.F8.) + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Translate a PolarSSL error code into a string representation, + * Result is truncated if necessary and always includes a terminating + * null byte. + * + * \param errnum error code + * \param buffer buffer to place representation in + * \param buflen length of the buffer + */ +void polarssl_strerror( int errnum, char *buffer, size_t buflen ); + +#if defined(POLARSSL_ERROR_STRERROR_BC) +void error_strerror( int errnum, char *buffer, size_t buflen ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* error.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/gcm.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/gcm.h new file mode 100644 index 0000000..c2829a0 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/gcm.h @@ -0,0 +1,219 @@ +/** + * \file gcm.h + * + * \brief Galois/Counter mode for 128-bit block ciphers + * + * Copyright (C) 2006-2013, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_GCM_H +#define POLARSSL_GCM_H + +#include "cipher.h" + +#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32) +#include +typedef UINT32 uint32_t; +typedef UINT64 uint64_t; +#else +#include +#endif + +#define GCM_ENCRYPT 1 +#define GCM_DECRYPT 0 + +#define POLARSSL_ERR_GCM_AUTH_FAILED -0x0012 /**< Authenticated decryption failed. */ +#define POLARSSL_ERR_GCM_BAD_INPUT -0x0014 /**< Bad input parameters to function. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief GCM context structure + */ +typedef struct { + cipher_context_t cipher_ctx;/*!< cipher context used */ + uint64_t HL[16]; /*!< Precalculated HTable */ + uint64_t HH[16]; /*!< Precalculated HTable */ + uint64_t len; /*!< Total data length */ + uint64_t add_len; /*!< Total add length */ + unsigned char base_ectr[16];/*!< First ECTR for tag */ + unsigned char y[16]; /*!< Y working value */ + unsigned char buf[16]; /*!< buf working value */ + int mode; /*!< Encrypt or Decrypt */ +} +gcm_context; + +/** + * \brief GCM initialization (encryption) + * + * \param ctx GCM context to be initialized + * \param cipher cipher to use (a 128-bit block cipher) + * \param key encryption key + * \param keysize must be 128, 192 or 256 + * + * \return 0 if successful, or a cipher specific error code + */ +int gcm_init( gcm_context *ctx, cipher_id_t cipher, const unsigned char *key, + unsigned int keysize ); + +/** + * \brief GCM buffer encryption/decryption using a block cipher + * + * \note On encryption, the output buffer can be the same as the input buffer. + * On decryption, the output buffer cannot be the same as input buffer. + * If buffers overlap, the output buffer must trail at least 8 bytes + * behind the input buffer. + * + * \param ctx GCM context + * \param mode GCM_ENCRYPT or GCM_DECRYPT + * \param length length of the input data + * \param iv initialization vector + * \param iv_len length of IV + * \param add additional data + * \param add_len length of additional data + * \param input buffer holding the input data + * \param output buffer for holding the output data + * \param tag_len length of the tag to generate + * \param tag buffer for holding the tag + * + * \return 0 if successful + */ +int gcm_crypt_and_tag( gcm_context *ctx, + int mode, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len, + const unsigned char *input, + unsigned char *output, + size_t tag_len, + unsigned char *tag ); + +/** + * \brief GCM buffer authenticated decryption using a block cipher + * + * \note On decryption, the output buffer cannot be the same as input buffer. + * If buffers overlap, the output buffer must trail at least 8 bytes + * behind the input buffer. + * + * \param ctx GCM context + * \param length length of the input data + * \param iv initialization vector + * \param iv_len length of IV + * \param add additional data + * \param add_len length of additional data + * \param tag buffer holding the tag + * \param tag_len length of the tag + * \param input buffer holding the input data + * \param output buffer for holding the output data + * + * \return 0 if successful and authenticated, + * POLARSSL_ERR_GCM_AUTH_FAILED if tag does not match + */ +int gcm_auth_decrypt( gcm_context *ctx, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len, + const unsigned char *tag, + size_t tag_len, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief Generic GCM stream start function + * + * \param ctx GCM context + * \param mode GCM_ENCRYPT or GCM_DECRYPT + * \param iv initialization vector + * \param iv_len length of IV + * \param add additional data (or NULL if length is 0) + * \param add_len length of additional data + * + * \return 0 if successful + */ +int gcm_starts( gcm_context *ctx, + int mode, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len ); + +/** + * \brief Generic GCM update function. Encrypts/decrypts using the + * given GCM context. Expects input to be a multiple of 16 + * bytes! Only the last call before gcm_finish() can be less + * than 16 bytes! + * + * \note On decryption, the output buffer cannot be the same as input buffer. + * If buffers overlap, the output buffer must trail at least 8 bytes + * behind the input buffer. + * + * \param ctx GCM context + * \param length length of the input data + * \param input buffer holding the input data + * \param output buffer for holding the output data + * + * \return 0 if successful or POLARSSL_ERR_GCM_BAD_INPUT + */ +int gcm_update( gcm_context *ctx, + size_t length, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief Generic GCM finalisation function. Wraps up the GCM stream + * and generates the tag. The tag can have a maximum length of + * 16 bytes. + * + * \param ctx GCM context + * \param tag buffer for holding the tag (may be NULL if tag_len is 0) + * \param tag_len length of the tag to generate + * + * \return 0 if successful or POLARSSL_ERR_GCM_BAD_INPUT + */ +int gcm_finish( gcm_context *ctx, + unsigned char *tag, + size_t tag_len ); + +/** + * \brief Free a GCM context and underlying cipher sub-context + * + * \param ctx GCM context to free + */ +void gcm_free( gcm_context *ctx ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int gcm_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* gcm.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/havege.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/havege.h new file mode 100644 index 0000000..536eb08 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/havege.h @@ -0,0 +1,78 @@ +/** + * \file havege.h + * + * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion + * + * Copyright (C) 2006-2013, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_HAVEGE_H +#define POLARSSL_HAVEGE_H + +#include + +#define COLLECT_SIZE 1024 + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief HAVEGE state structure + */ +typedef struct +{ + int PT1, PT2, offset[2]; + int pool[COLLECT_SIZE]; + int WALK[8192]; +} +havege_state; + +/** + * \brief HAVEGE initialization + * + * \param hs HAVEGE state to be initialized + */ +void havege_init( havege_state *hs ); + +/** + * \brief Clear HAVEGE state + * + * \param hs HAVEGE state to be cleared + */ +void havege_free( havege_state *hs ); + +/** + * \brief HAVEGE rand function + * + * \param p_rng A HAVEGE state + * \param output Buffer to fill + * \param len Length of buffer + * + * \return 0 + */ +int havege_random( void *p_rng, unsigned char *output, size_t len ); + +#ifdef __cplusplus +} +#endif + +#endif /* havege.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/hmac_drbg.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/hmac_drbg.h new file mode 100644 index 0000000..2d765d5 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/hmac_drbg.h @@ -0,0 +1,284 @@ +/** + * \file hmac_drbg.h + * + * \brief HMAC_DRBG (NIST SP 800-90A) + * + * Copyright (C) 2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_HMAC_DRBG_H +#define POLARSSL_HMAC_DRBG_H + +#include "md.h" + +/* + * Error codes + */ +#define POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG -0x0003 /**< Too many random requested in single call. */ +#define POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG -0x0005 /**< Input too large (Entropy + additional). */ +#define POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR -0x0007 /**< Read/write error in file. */ +#define POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED -0x0009 /**< The entropy source failed. */ + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(POLARSSL_HMAC_DRBG_RESEED_INTERVAL) +#define POLARSSL_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +#endif + +#if !defined(POLARSSL_HMAC_DRBG_MAX_INPUT) +#define POLARSSL_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +#endif + +#if !defined(POLARSSL_HMAC_DRBG_MAX_REQUEST) +#define POLARSSL_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +#endif + +#if !defined(POLARSSL_HMAC_DRBG_MAX_SEED_INPUT) +#define POLARSSL_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ +#endif + +/* \} name SECTION: Module settings */ + +#define POLARSSL_HMAC_DRBG_PR_OFF 0 /**< No prediction resistance */ +#define POLARSSL_HMAC_DRBG_PR_ON 1 /**< Prediction resistance enabled */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * HMAC_DRBG context. + */ +typedef struct +{ + /* Working state: the key K is not stored explicitely, + * but is implied by the HMAC context */ + md_context_t md_ctx; /*!< HMAC context (inc. K) */ + unsigned char V[POLARSSL_MD_MAX_SIZE]; /*!< V in the spec */ + int reseed_counter; /*!< reseed counter */ + + /* Administrative state */ + size_t entropy_len; /*!< entropy bytes grabbed on each (re)seed */ + int prediction_resistance; /*!< enable prediction resistance (Automatic + reseed before every random generation) */ + int reseed_interval; /*!< reseed interval */ + + /* Callbacks */ + int (*f_entropy)(void *, unsigned char *, size_t); /*!< entropy function */ + void *p_entropy; /*!< context for the entropy function */ +} hmac_drbg_context; + +/** + * \brief HMAC_DRBG initialisation + * + * \param ctx HMAC_DRBG context to be initialised + * \param md_info MD algorithm to use for HMAC_DRBG + * \param f_entropy Entropy callback (p_entropy, buffer to fill, buffer + * length) + * \param p_entropy Entropy context + * \param custom Personalization data (Device specific identifiers) + * (Can be NULL) + * \param len Length of personalization data + * + * \note The "security strength" as defined by NIST is set to: + * 128 bits if md_alg is SHA-1, + * 192 bits if md_alg is SHA-224, + * 256 bits if md_alg is SHA-256 or higher. + * Note that SHA-256 is just as efficient as SHA-224. + * + * \return 0 if successful, or + * POLARSSL_ERR_MD_BAD_INPUT_DATA, or + * POLARSSL_ERR_MD_ALLOC_FAILED, or + * POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED. + */ +int hmac_drbg_init( hmac_drbg_context *ctx, + const md_info_t * md_info, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len ); + +/** + * \brief Initilisation of simpified HMAC_DRBG (never reseeds). + * (For use with deterministic ECDSA.) + * + * \param ctx HMAC_DRBG context to be initialised + * \param md_info MD algorithm to use for HMAC_DRBG + * \param data Concatenation of entropy string and additional data + * \param data_len Length of data in bytes + * + * \return 0 if successful, or + * POLARSSL_ERR_MD_BAD_INPUT_DATA, or + * POLARSSL_ERR_MD_ALLOC_FAILED. + */ +int hmac_drbg_init_buf( hmac_drbg_context *ctx, + const md_info_t * md_info, + const unsigned char *data, size_t data_len ); + +/** + * \brief Enable / disable prediction resistance (Default: Off) + * + * Note: If enabled, entropy is used for ctx->entropy_len before each call! + * Only use this if you have ample supply of good entropy! + * + * \param ctx HMAC_DRBG context + * \param resistance POLARSSL_HMAC_DRBG_PR_ON or POLARSSL_HMAC_DRBG_PR_OFF + */ +void hmac_drbg_set_prediction_resistance( hmac_drbg_context *ctx, + int resistance ); + +/** + * \brief Set the amount of entropy grabbed on each reseed + * (Default: given by the security strength, which + * depends on the hash used, see \c hmac_drbg_init() ) + * + * \param ctx HMAC_DRBG context + * \param len Amount of entropy to grab, in bytes + */ +void hmac_drbg_set_entropy_len( hmac_drbg_context *ctx, + size_t len ); + +/** + * \brief Set the reseed interval + * (Default: POLARSSL_HMAC_DRBG_RESEED_INTERVAL) + * + * \param ctx HMAC_DRBG context + * \param interval Reseed interval + */ +void hmac_drbg_set_reseed_interval( hmac_drbg_context *ctx, + int interval ); + +/** + * \brief HMAC_DRBG update state + * + * \param ctx HMAC_DRBG context + * \param additional Additional data to update state with, or NULL + * \param add_len Length of additional data, or 0 + * + * \note Additional data is optional, pass NULL and 0 as second + * third argument if no additional data is being used. + */ +void hmac_drbg_update( hmac_drbg_context *ctx, + const unsigned char *additional, size_t add_len ); + +/** + * \brief HMAC_DRBG reseeding (extracts data from entropy source) + * + * \param ctx HMAC_DRBG context + * \param additional Additional data to add to state (Can be NULL) + * \param len Length of additional data + * + * \return 0 if successful, or + * POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + */ +int hmac_drbg_reseed( hmac_drbg_context *ctx, + const unsigned char *additional, size_t len ); + +/** + * \brief HMAC_DRBG generate random with additional update input + * + * Note: Automatically reseeds if reseed_counter is reached or PR is enabled. + * + * \param p_rng HMAC_DRBG context + * \param output Buffer to fill + * \param output_len Length of the buffer + * \param additional Additional data to update with (can be NULL) + * \param add_len Length of additional data (can be 0) + * + * \return 0 if successful, or + * POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED, or + * POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG, or + * POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG. + */ +int hmac_drbg_random_with_add( void *p_rng, + unsigned char *output, size_t output_len, + const unsigned char *additional, + size_t add_len ); + +/** + * \brief HMAC_DRBG generate random + * + * Note: Automatically reseeds if reseed_counter is reached or PR is enabled. + * + * \param p_rng HMAC_DRBG context + * \param output Buffer to fill + * \param out_len Length of the buffer + * + * \return 0 if successful, or + * POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED, or + * POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG + */ +int hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len ); + +/** + * \brief Free an HMAC_DRBG context + * + * \param ctx HMAC_DRBG context to free. + */ +void hmac_drbg_free( hmac_drbg_context *ctx ); + +#if defined(POLARSSL_FS_IO) +/** + * \brief Write a seed file + * + * \param ctx HMAC_DRBG context + * \param path Name of the file + * + * \return 0 if successful, 1 on file error, or + * POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + */ +int hmac_drbg_write_seed_file( hmac_drbg_context *ctx, const char *path ); + +/** + * \brief Read and update a seed file. Seed is added to this + * instance + * + * \param ctx HMAC_DRBG context + * \param path Name of the file + * + * \return 0 if successful, 1 on file error, + * POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED or + * POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG + */ +int hmac_drbg_update_seed_file( hmac_drbg_context *ctx, const char *path ); +#endif /* POLARSSL_FS_IO */ + + +#if defined(POLARSSL_SELF_TEST) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int hmac_drbg_self_test( int verbose ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* hmac_drbg.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/md.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/md.h new file mode 100644 index 0000000..81d8a2e --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/md.h @@ -0,0 +1,395 @@ +/** + * \file md.h + * + * \brief Generic message digest wrapper + * + * \author Adriaan de Jong + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_MD_H +#define POLARSSL_MD_H + +#include + +#if defined(_MSC_VER) && !defined(inline) +#define inline _inline +#else +#if defined(__ARMCC_VERSION) && !defined(inline) +#define inline __inline +#endif /* __ARMCC_VERSION */ +#endif /*_MSC_VER */ + +#define POLARSSL_ERR_MD_FEATURE_UNAVAILABLE -0x5080 /**< The selected feature is not available. */ +#define POLARSSL_ERR_MD_BAD_INPUT_DATA -0x5100 /**< Bad input parameters to function. */ +#define POLARSSL_ERR_MD_ALLOC_FAILED -0x5180 /**< Failed to allocate memory. */ +#define POLARSSL_ERR_MD_FILE_IO_ERROR -0x5200 /**< Opening or reading of file failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + POLARSSL_MD_NONE=0, + POLARSSL_MD_MD2, + POLARSSL_MD_MD4, + POLARSSL_MD_MD5, + POLARSSL_MD_SHA1, + POLARSSL_MD_SHA224, + POLARSSL_MD_SHA256, + POLARSSL_MD_SHA384, + POLARSSL_MD_SHA512, + POLARSSL_MD_RIPEMD160, +} md_type_t; + +#if defined(POLARSSL_SHA512_C) +#define POLARSSL_MD_MAX_SIZE 64 /* longest known is SHA512 */ +#else +#define POLARSSL_MD_MAX_SIZE 32 /* longest known is SHA256 or less */ +#endif + +/** + * Message digest information. Allows message digest functions to be called + * in a generic way. + */ +typedef struct { + /** Digest identifier */ + md_type_t type; + + /** Name of the message digest */ + const char * name; + + /** Output length of the digest function */ + int size; + + /** Digest initialisation function */ + void (*starts_func)( void *ctx ); + + /** Digest update function */ + void (*update_func)( void *ctx, const unsigned char *input, size_t ilen ); + + /** Digest finalisation function */ + void (*finish_func)( void *ctx, unsigned char *output ); + + /** Generic digest function */ + void (*digest_func)( const unsigned char *input, size_t ilen, + unsigned char *output ); + + /** Generic file digest function */ + int (*file_func)( const char *path, unsigned char *output ); + + /** HMAC Initialisation function */ + void (*hmac_starts_func)( void *ctx, const unsigned char *key, + size_t keylen ); + + /** HMAC update function */ + void (*hmac_update_func)( void *ctx, const unsigned char *input, + size_t ilen ); + + /** HMAC finalisation function */ + void (*hmac_finish_func)( void *ctx, unsigned char *output); + + /** HMAC context reset function */ + void (*hmac_reset_func)( void *ctx ); + + /** Generic HMAC function */ + void (*hmac_func)( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ); + + /** Allocate a new context */ + void * (*ctx_alloc_func)( void ); + + /** Free the given context */ + void (*ctx_free_func)( void *ctx ); + + /** Internal use only */ + void (*process_func)( void *ctx, const unsigned char *input ); +} md_info_t; + +/** + * Generic message digest context. + */ +typedef struct { + /** Information about the associated message digest */ + const md_info_t *md_info; + + /** Digest-specific context */ + void *md_ctx; +} md_context_t; + +#define MD_CONTEXT_T_INIT { \ + NULL, /* md_info */ \ + NULL, /* md_ctx */ \ +} + +/** + * \brief Returns the list of digests supported by the generic digest module. + * + * \return a statically allocated array of digests, the last entry + * is 0. + */ +const int *md_list( void ); + +/** + * \brief Returns the message digest information associated with the + * given digest name. + * + * \param md_name Name of the digest to search for. + * + * \return The message digest information associated with md_name or + * NULL if not found. + */ +const md_info_t *md_info_from_string( const char *md_name ); + +/** + * \brief Returns the message digest information associated with the + * given digest type. + * + * \param md_type type of digest to search for. + * + * \return The message digest information associated with md_type or + * NULL if not found. + */ +const md_info_t *md_info_from_type( md_type_t md_type ); + +/** + * \brief Initialize a md_context (as NONE) + */ +void md_init( md_context_t *ctx ); + +/** + * \brief Free and clear the message-specific context of ctx. + * Freeing ctx itself remains the responsibility of the + * caller. + */ +void md_free( md_context_t *ctx ); + +/** + * \brief Initialises and fills the message digest context structure + * with the appropriate values. + * + * \note Currently also clears structure. In future versions you + * will be required to call md_init() on the structure + * first. + * + * \param ctx context to initialise. May not be NULL. The + * digest-specific context (ctx->md_ctx) must be NULL. It will + * be allocated, and must be freed using md_free_ctx() later. + * \param md_info message digest to use. + * + * \returns \c 0 on success, \c POLARSSL_ERR_MD_BAD_INPUT_DATA on + * parameter failure, \c POLARSSL_ERR_MD_ALLOC_FAILED if + * allocation of the digest-specific context failed. + */ +int md_init_ctx( md_context_t *ctx, const md_info_t *md_info ); + +/** + * \brief Free the message-specific context of ctx. Freeing ctx itself + * remains the responsibility of the caller. + * + * \note Deprecated: Redirects to md_free() + * + * \param ctx Free the message-specific context + * + * \returns 0 + */ +int md_free_ctx( md_context_t *ctx ); + +/** + * \brief Returns the size of the message digest output. + * + * \param md_info message digest info + * + * \return size of the message digest output. + */ +static inline unsigned char md_get_size( const md_info_t *md_info ) +{ + if( md_info == NULL ) + return( 0 ); + + return md_info->size; +} + +/** + * \brief Returns the type of the message digest output. + * + * \param md_info message digest info + * + * \return type of the message digest output. + */ +static inline md_type_t md_get_type( const md_info_t *md_info ) +{ + if( md_info == NULL ) + return( POLARSSL_MD_NONE ); + + return md_info->type; +} + +/** + * \brief Returns the name of the message digest output. + * + * \param md_info message digest info + * + * \return name of the message digest output. + */ +static inline const char *md_get_name( const md_info_t *md_info ) +{ + if( md_info == NULL ) + return( NULL ); + + return md_info->name; +} + +/** + * \brief Set-up the given context for a new message digest + * + * \param ctx generic message digest context. + * + * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter + * verification fails. + */ +int md_starts( md_context_t *ctx ); + +/** + * \brief Generic message digest process buffer + * + * \param ctx Generic message digest context + * \param input buffer holding the datal + * \param ilen length of the input data + * + * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter + * verification fails. + */ +int md_update( md_context_t *ctx, const unsigned char *input, size_t ilen ); + +/** + * \brief Generic message digest final digest + * + * \param ctx Generic message digest context + * \param output Generic message digest checksum result + * + * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter + * verification fails. + */ +int md_finish( md_context_t *ctx, unsigned char *output ); + +/** + * \brief Output = message_digest( input buffer ) + * + * \param md_info message digest info + * \param input buffer holding the data + * \param ilen length of the input data + * \param output Generic message digest checksum result + * + * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter + * verification fails. + */ +int md( const md_info_t *md_info, const unsigned char *input, size_t ilen, + unsigned char *output ); + +/** + * \brief Output = message_digest( file contents ) + * + * \param md_info message digest info + * \param path input file name + * \param output generic message digest checksum result + * + * \return 0 if successful, POLARSSL_ERR_MD_FILE_OPEN_FAILED if fopen + * failed, POLARSSL_ERR_MD_FILE_READ_FAILED if fread failed, + * POLARSSL_ERR_MD_BAD_INPUT_DATA if md_info was NULL. + */ +int md_file( const md_info_t *md_info, const char *path, + unsigned char *output ); + +/** + * \brief Generic HMAC context setup + * + * \param ctx HMAC context to be initialized + * \param key HMAC secret key + * \param keylen length of the HMAC key + * + * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter + * verification fails. + */ +int md_hmac_starts( md_context_t *ctx, const unsigned char *key, + size_t keylen ); + +/** + * \brief Generic HMAC process buffer + * + * \param ctx HMAC context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter + * verification fails. + */ +int md_hmac_update( md_context_t *ctx, const unsigned char *input, + size_t ilen ); + +/** + * \brief Generic HMAC final digest + * + * \param ctx HMAC context + * \param output Generic HMAC checksum result + * + * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter + * verification fails. + */ +int md_hmac_finish( md_context_t *ctx, unsigned char *output); + +/** + * \brief Generic HMAC context reset + * + * \param ctx HMAC context to be reset + * + * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter + * verification fails. + */ +int md_hmac_reset( md_context_t *ctx ); + +/** + * \brief Output = Generic_HMAC( hmac key, input buffer ) + * + * \param md_info message digest info + * \param key HMAC secret key + * \param keylen length of the HMAC key + * \param input buffer holding the data + * \param ilen length of the input data + * \param output Generic HMAC-result + * + * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter + * verification fails. + */ +int md_hmac( const md_info_t *md_info, const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ); + +/* Internal use */ +int md_process( md_context_t *ctx, const unsigned char *data ); + +#ifdef __cplusplus +} +#endif + +#endif /* POLARSSL_MD_H */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/md2.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/md2.h new file mode 100644 index 0000000..952b0bf --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/md2.h @@ -0,0 +1,194 @@ +/** + * \file md2.h + * + * \brief MD2 message digest algorithm (hash function) + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_MD2_H +#define POLARSSL_MD2_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include + +#define POLARSSL_ERR_MD2_FILE_IO_ERROR -0x0070 /**< Read/write error in file. */ + +#if !defined(POLARSSL_MD2_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MD2 context structure + */ +typedef struct +{ + unsigned char cksum[16]; /*!< checksum of the data block */ + unsigned char state[48]; /*!< intermediate digest state */ + unsigned char buffer[16]; /*!< data block being processed */ + + unsigned char ipad[16]; /*!< HMAC: inner padding */ + unsigned char opad[16]; /*!< HMAC: outer padding */ + size_t left; /*!< amount of data in buffer */ +} +md2_context; + +/** + * \brief Initialize MD2 context + * + * \param ctx MD2 context to be initialized + */ +void md2_init( md2_context *ctx ); + +/** + * \brief Clear MD2 context + * + * \param ctx MD2 context to be cleared + */ +void md2_free( md2_context *ctx ); + +/** + * \brief MD2 context setup + * + * \param ctx context to be initialized + */ +void md2_starts( md2_context *ctx ); + +/** + * \brief MD2 process buffer + * + * \param ctx MD2 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void md2_update( md2_context *ctx, const unsigned char *input, size_t ilen ); + +/** + * \brief MD2 final digest + * + * \param ctx MD2 context + * \param output MD2 checksum result + */ +void md2_finish( md2_context *ctx, unsigned char output[16] ); + +#ifdef __cplusplus +} +#endif + +#else /* POLARSSL_MD2_ALT */ +#include "md2_alt.h" +#endif /* POLARSSL_MD2_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Output = MD2( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD2 checksum result + */ +void md2( const unsigned char *input, size_t ilen, unsigned char output[16] ); + +/** + * \brief Output = MD2( file contents ) + * + * \param path input file name + * \param output MD2 checksum result + * + * \return 0 if successful, or POLARSSL_ERR_MD2_FILE_IO_ERROR + */ +int md2_file( const char *path, unsigned char output[16] ); + +/** + * \brief MD2 HMAC context setup + * + * \param ctx HMAC context to be initialized + * \param key HMAC secret key + * \param keylen length of the HMAC key + */ +void md2_hmac_starts( md2_context *ctx, const unsigned char *key, + size_t keylen ); + +/** + * \brief MD2 HMAC process buffer + * + * \param ctx HMAC context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void md2_hmac_update( md2_context *ctx, const unsigned char *input, + size_t ilen ); + +/** + * \brief MD2 HMAC final digest + * + * \param ctx HMAC context + * \param output MD2 HMAC checksum result + */ +void md2_hmac_finish( md2_context *ctx, unsigned char output[16] ); + +/** + * \brief MD2 HMAC context reset + * + * \param ctx HMAC context to be reset + */ +void md2_hmac_reset( md2_context *ctx ); + +/** + * \brief Output = HMAC-MD2( hmac key, input buffer ) + * + * \param key HMAC secret key + * \param keylen length of the HMAC key + * \param input buffer holding the data + * \param ilen length of the input data + * \param output HMAC-MD2 result + */ +void md2_hmac( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char output[16] ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int md2_self_test( int verbose ); + +/* Internal use */ +void md2_process( md2_context *ctx ); + +#ifdef __cplusplus +} +#endif + +#endif /* md2.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/md4.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/md4.h new file mode 100644 index 0000000..fc5a5cd --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/md4.h @@ -0,0 +1,200 @@ +/** + * \file md4.h + * + * \brief MD4 message digest algorithm (hash function) + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_MD4_H +#define POLARSSL_MD4_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include + +#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32) +#include +typedef UINT32 uint32_t; +#else +#include +#endif + +#define POLARSSL_ERR_MD4_FILE_IO_ERROR -0x0072 /**< Read/write error in file. */ + +#if !defined(POLARSSL_MD4_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MD4 context structure + */ +typedef struct +{ + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[4]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ + + unsigned char ipad[64]; /*!< HMAC: inner padding */ + unsigned char opad[64]; /*!< HMAC: outer padding */ +} +md4_context; + +/** + * \brief Initialize MD4 context + * + * \param ctx MD4 context to be initialized + */ +void md4_init( md4_context *ctx ); + +/** + * \brief Clear MD4 context + * + * \param ctx MD4 context to be cleared + */ +void md4_free( md4_context *ctx ); + +/** + * \brief MD4 context setup + * + * \param ctx context to be initialized + */ +void md4_starts( md4_context *ctx ); + +/** + * \brief MD4 process buffer + * + * \param ctx MD4 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void md4_update( md4_context *ctx, const unsigned char *input, size_t ilen ); + +/** + * \brief MD4 final digest + * + * \param ctx MD4 context + * \param output MD4 checksum result + */ +void md4_finish( md4_context *ctx, unsigned char output[16] ); + +#ifdef __cplusplus +} +#endif + +#else /* POLARSSL_MD4_ALT */ +#include "md4_alt.h" +#endif /* POLARSSL_MD4_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Output = MD4( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD4 checksum result + */ +void md4( const unsigned char *input, size_t ilen, unsigned char output[16] ); + +/** + * \brief Output = MD4( file contents ) + * + * \param path input file name + * \param output MD4 checksum result + * + * \return 0 if successful, or POLARSSL_ERR_MD4_FILE_IO_ERROR + */ +int md4_file( const char *path, unsigned char output[16] ); + +/** + * \brief MD4 HMAC context setup + * + * \param ctx HMAC context to be initialized + * \param key HMAC secret key + * \param keylen length of the HMAC key + */ +void md4_hmac_starts( md4_context *ctx, const unsigned char *key, + size_t keylen ); + +/** + * \brief MD4 HMAC process buffer + * + * \param ctx HMAC context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void md4_hmac_update( md4_context *ctx, const unsigned char *input, + size_t ilen ); + +/** + * \brief MD4 HMAC final digest + * + * \param ctx HMAC context + * \param output MD4 HMAC checksum result + */ +void md4_hmac_finish( md4_context *ctx, unsigned char output[16] ); + +/** + * \brief MD4 HMAC context reset + * + * \param ctx HMAC context to be reset + */ +void md4_hmac_reset( md4_context *ctx ); + +/** + * \brief Output = HMAC-MD4( hmac key, input buffer ) + * + * \param key HMAC secret key + * \param keylen length of the HMAC key + * \param input buffer holding the data + * \param ilen length of the input data + * \param output HMAC-MD4 result + */ +void md4_hmac( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char output[16] ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int md4_self_test( int verbose ); + +/* Internal use */ +void md4_process( md4_context *ctx, const unsigned char data[64] ); + +#ifdef __cplusplus +} +#endif + +#endif /* md4.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/md5.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/md5.h new file mode 100644 index 0000000..2f378f6 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/md5.h @@ -0,0 +1,200 @@ +/** + * \file md5.h + * + * \brief MD5 message digest algorithm (hash function) + * + * Copyright (C) 2006-2013, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_MD5_H +#define POLARSSL_MD5_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include + +#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32) +#include +typedef UINT32 uint32_t; +#else +#include +#endif + +#define POLARSSL_ERR_MD5_FILE_IO_ERROR -0x0074 /**< Read/write error in file. */ + +#if !defined(POLARSSL_MD5_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MD5 context structure + */ +typedef struct +{ + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[4]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ + + unsigned char ipad[64]; /*!< HMAC: inner padding */ + unsigned char opad[64]; /*!< HMAC: outer padding */ +} +md5_context; + +/** + * \brief Initialize MD5 context + * + * \param ctx MD5 context to be initialized + */ +void md5_init( md5_context *ctx ); + +/** + * \brief Clear MD5 context + * + * \param ctx MD5 context to be cleared + */ +void md5_free( md5_context *ctx ); + +/** + * \brief MD5 context setup + * + * \param ctx context to be initialized + */ +void md5_starts( md5_context *ctx ); + +/** + * \brief MD5 process buffer + * + * \param ctx MD5 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void md5_update( md5_context *ctx, const unsigned char *input, size_t ilen ); + +/** + * \brief MD5 final digest + * + * \param ctx MD5 context + * \param output MD5 checksum result + */ +void md5_finish( md5_context *ctx, unsigned char output[16] ); + +/* Internal use */ +void md5_process( md5_context *ctx, const unsigned char data[64] ); + +#ifdef __cplusplus +} +#endif + +#else /* POLARSSL_MD5_ALT */ +#include "md5_alt.h" +#endif /* POLARSSL_MD5_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Output = MD5( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD5 checksum result + */ +void md5( const unsigned char *input, size_t ilen, unsigned char output[16] ); + +/** + * \brief Output = MD5( file contents ) + * + * \param path input file name + * \param output MD5 checksum result + * + * \return 0 if successful, or POLARSSL_ERR_MD5_FILE_IO_ERROR + */ +int md5_file( const char *path, unsigned char output[16] ); + +/** + * \brief MD5 HMAC context setup + * + * \param ctx HMAC context to be initialized + * \param key HMAC secret key + * \param keylen length of the HMAC key + */ +void md5_hmac_starts( md5_context *ctx, + const unsigned char *key, size_t keylen ); + +/** + * \brief MD5 HMAC process buffer + * + * \param ctx HMAC context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void md5_hmac_update( md5_context *ctx, + const unsigned char *input, size_t ilen ); + +/** + * \brief MD5 HMAC final digest + * + * \param ctx HMAC context + * \param output MD5 HMAC checksum result + */ +void md5_hmac_finish( md5_context *ctx, unsigned char output[16] ); + +/** + * \brief MD5 HMAC context reset + * + * \param ctx HMAC context to be reset + */ +void md5_hmac_reset( md5_context *ctx ); + +/** + * \brief Output = HMAC-MD5( hmac key, input buffer ) + * + * \param key HMAC secret key + * \param keylen length of the HMAC key + * \param input buffer holding the data + * \param ilen length of the input data + * \param output HMAC-MD5 result + */ +void md5_hmac( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char output[16] ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int md5_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* md5.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/md_wrap.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/md_wrap.h new file mode 100644 index 0000000..eb1db0f --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/md_wrap.h @@ -0,0 +1,71 @@ +/** + * \file md_wrap.h + * + * \brief Message digest wrappers. + * + * \author Adriaan de Jong + * + * Copyright (C) 2006-2011, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_MD_WRAP_H +#define POLARSSL_MD_WRAP_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif +#include "md.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(POLARSSL_MD2_C) +extern const md_info_t md2_info; +#endif +#if defined(POLARSSL_MD4_C) +extern const md_info_t md4_info; +#endif +#if defined(POLARSSL_MD5_C) +extern const md_info_t md5_info; +#endif +#if defined(POLARSSL_RIPEMD160_C) +extern const md_info_t ripemd160_info; +#endif +#if defined(POLARSSL_SHA1_C) +extern const md_info_t sha1_info; +#endif +#if defined(POLARSSL_SHA256_C) +extern const md_info_t sha224_info; +extern const md_info_t sha256_info; +#endif +#if defined(POLARSSL_SHA512_C) +extern const md_info_t sha384_info; +extern const md_info_t sha512_info; +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* POLARSSL_MD_WRAP_H */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/memory.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/memory.h new file mode 100644 index 0000000..188f855 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/memory.h @@ -0,0 +1,52 @@ +/** + * \file memory.h + * + * \brief Memory allocation layer (Deprecated to platform layer) + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_MEMORY_H +#define POLARSSL_MEMORY_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include + +#if defined(POLARSSL_MEMORY_C) && !defined(POLARSSL_PLATFORM_MEMORY) +#define POLARSSL_PLATFORM_MEMORY +#endif + +#include "platform.h" +#include "memory_buffer_alloc.h" + +static int memory_set_own( void * (*malloc_func)( size_t ), + void (*free_func)( void * ) ) +{ + return platform_set_malloc_free( malloc_func, free_func ); +} + + +#endif /* memory.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/memory_buffer_alloc.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/memory_buffer_alloc.h new file mode 100644 index 0000000..c449752 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/memory_buffer_alloc.h @@ -0,0 +1,122 @@ +/** + * \file memory_buffer_alloc.h + * + * \brief Buffer-based memory allocator + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_MEMORY_BUFFER_ALLOC_H +#define POLARSSL_MEMORY_BUFFER_ALLOC_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(POLARSSL_MEMORY_ALIGN_MULTIPLE) +#define POLARSSL_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */ +#endif + +/* \} name SECTION: Module settings */ + +#define MEMORY_VERIFY_NONE 0 +#define MEMORY_VERIFY_ALLOC (1 << 0) +#define MEMORY_VERIFY_FREE (1 << 1) +#define MEMORY_VERIFY_ALWAYS (MEMORY_VERIFY_ALLOC | MEMORY_VERIFY_FREE) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Initialize use of stack-based memory allocator. + * The stack-based allocator does memory management inside the + * presented buffer and does not call malloc() and free(). + * It sets the global polarssl_malloc() and polarssl_free() pointers + * to its own functions. + * (Provided polarssl_malloc() and polarssl_free() are thread-safe if + * POLARSSL_THREADING_C is defined) + * + * \note This code is not optimized and provides a straight-forward + * implementation of a stack-based memory allocator. + * + * \param buf buffer to use as heap + * \param len size of the buffer + * + * \return 0 if successful + */ +int memory_buffer_alloc_init( unsigned char *buf, size_t len ); + +/** + * \brief Free the mutex for thread-safety and clear remaining memory + */ +void memory_buffer_alloc_free( void ); + +/** + * \brief Determine when the allocator should automatically verify the state + * of the entire chain of headers / meta-data. + * (Default: MEMORY_VERIFY_NONE) + * + * \param verify One of MEMORY_VERIFY_NONE, MEMORY_VERIFY_ALLOC, + * MEMORY_VERIFY_FREE or MEMORY_VERIFY_ALWAYS + */ +void memory_buffer_set_verify( int verify ); + +#if defined(POLARSSL_MEMORY_DEBUG) +/** + * \brief Print out the status of the allocated memory (primarily for use + * after a program should have de-allocated all memory) + * Prints out a list of 'still allocated' blocks and their stack + * trace if POLARSSL_MEMORY_BACKTRACE is defined. + */ +void memory_buffer_alloc_status( void ); +#endif /* POLARSSL_MEMORY_DEBUG */ + +/** + * \brief Verifies that all headers in the memory buffer are correct + * and contain sane values. Helps debug buffer-overflow errors. + * + * Prints out first failure if POLARSSL_MEMORY_DEBUG is defined. + * Prints out full header information if POLARSSL_MEMORY_DEBUG_HEADERS + * is defined. (Includes stack trace information for each block if + * POLARSSL_MEMORY_BACKTRACE is defined as well). + * + * \returns 0 if verified, 1 otherwise + */ +int memory_buffer_alloc_verify( void ); + +#ifdef __cplusplus +} +#endif + +#endif /* memory_buffer_alloc.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/net.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/net.h new file mode 100644 index 0000000..22698b4 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/net.h @@ -0,0 +1,160 @@ +/** + * \file net.h + * + * \brief Network communication functions + * + * Copyright (C) 2006-2011, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_NET_H +#define POLARSSL_NET_H + +#include + +#define POLARSSL_ERR_NET_UNKNOWN_HOST -0x0056 /**< Failed to get an IP address for the given hostname. */ +#define POLARSSL_ERR_NET_SOCKET_FAILED -0x0042 /**< Failed to open a socket. */ +#define POLARSSL_ERR_NET_CONNECT_FAILED -0x0044 /**< The connection to the given server / port failed. */ +#define POLARSSL_ERR_NET_BIND_FAILED -0x0046 /**< Binding of the socket failed. */ +#define POLARSSL_ERR_NET_LISTEN_FAILED -0x0048 /**< Could not listen on the socket. */ +#define POLARSSL_ERR_NET_ACCEPT_FAILED -0x004A /**< Could not accept the incoming connection. */ +#define POLARSSL_ERR_NET_RECV_FAILED -0x004C /**< Reading information from the socket failed. */ +#define POLARSSL_ERR_NET_SEND_FAILED -0x004E /**< Sending information through the socket failed. */ +#define POLARSSL_ERR_NET_CONN_RESET -0x0050 /**< Connection was reset by peer. */ +#define POLARSSL_ERR_NET_WANT_READ -0x0052 /**< Connection requires a read call. */ +#define POLARSSL_ERR_NET_WANT_WRITE -0x0054 /**< Connection requires a write call. */ + +#define POLARSSL_NET_LISTEN_BACKLOG 10 /**< The backlog that listen() should use. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Initiate a TCP connection with host:port + * + * \param fd Socket to use + * \param host Host to connect to + * \param port Port to connect to + * + * \return 0 if successful, or one of: + * POLARSSL_ERR_NET_SOCKET_FAILED, + * POLARSSL_ERR_NET_UNKNOWN_HOST, + * POLARSSL_ERR_NET_CONNECT_FAILED + */ +int net_connect( int *fd, const char *host, int port ); + +/** + * \brief Create a listening socket on bind_ip:port. + * If bind_ip == NULL, all interfaces are binded. + * + * \param fd Socket to use + * \param bind_ip IP to bind to, can be NULL + * \param port Port number to use + * + * \return 0 if successful, or one of: + * POLARSSL_ERR_NET_SOCKET_FAILED, + * POLARSSL_ERR_NET_BIND_FAILED, + * POLARSSL_ERR_NET_LISTEN_FAILED + */ +int net_bind( int *fd, const char *bind_ip, int port ); + +/** + * \brief Accept a connection from a remote client + * + * \param bind_fd Relevant socket + * \param client_fd Will contain the connected client socket + * \param client_ip Will contain the client IP address + * Must be at least 4 bytes, or 16 if IPv6 is supported + * + * \return 0 if successful, POLARSSL_ERR_NET_ACCEPT_FAILED, or + * POLARSSL_ERR_NET_WANT_READ is bind_fd was set to + * non-blocking and accept() is blocking. + */ +int net_accept( int bind_fd, int *client_fd, void *client_ip ); + +/** + * \brief Set the socket blocking + * + * \param fd Socket to set + * + * \return 0 if successful, or a non-zero error code + */ +int net_set_block( int fd ); + +/** + * \brief Set the socket non-blocking + * + * \param fd Socket to set + * + * \return 0 if successful, or a non-zero error code + */ +int net_set_nonblock( int fd ); + +/** + * \brief Portable usleep helper + * + * \param usec Amount of microseconds to sleep + * + * \note Real amount of time slept will not be less than + * select()'s timeout granularity (typically, 10ms). + */ +void net_usleep( unsigned long usec ); + +/** + * \brief Read at most 'len' characters. If no error occurs, + * the actual amount read is returned. + * + * \param ctx Socket + * \param buf The buffer to write to + * \param len Maximum length of the buffer + * + * \return This function returns the number of bytes received, + * or a non-zero error code; POLARSSL_ERR_NET_WANT_READ + * indicates read() is blocking. + */ +int net_recv( void *ctx, unsigned char *buf, size_t len ); + +/** + * \brief Write at most 'len' characters. If no error occurs, + * the actual amount read is returned. + * + * \param ctx Socket + * \param buf The buffer to read from + * \param len The length of the buffer + * + * \return This function returns the number of bytes sent, + * or a non-zero error code; POLARSSL_ERR_NET_WANT_WRITE + * indicates write() is blocking. + */ +int net_send( void *ctx, const unsigned char *buf, size_t len ); + +/** + * \brief Gracefully shutdown the connection + * + * \param fd The socket to close + */ +void net_close( int fd ); + +#ifdef __cplusplus +} +#endif + +#endif /* net.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/oid.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/oid.h new file mode 100644 index 0000000..c4d5c3f --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/oid.h @@ -0,0 +1,570 @@ +/** + * \file oid.h + * + * \brief Object Identifier (OID) database + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_OID_H +#define POLARSSL_OID_H + +#include +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif +#include "asn1.h" +#include "pk.h" +#if defined(POLARSSL_CIPHER_C) +#include "cipher.h" +#endif + +#if defined(POLARSSL_MD_C) +#include "md.h" +#endif + +#if defined(POLARSSL_X509_USE_C) || defined(POLARSSL_X509_CREATE_C) +#include "x509.h" +#endif + +#define POLARSSL_ERR_OID_NOT_FOUND -0x002E /**< OID is not found. */ +#define POLARSSL_ERR_OID_BUF_TOO_SMALL -0x000B /**< output buffer is too small */ + +/* + * Top level OID tuples + */ +#define OID_ISO_MEMBER_BODIES "\x2a" /* {iso(1) member-body(2)} */ +#define OID_ISO_IDENTIFIED_ORG "\x2b" /* {iso(1) identified-organization(3)} */ +#define OID_ISO_CCITT_DS "\x55" /* {joint-iso-ccitt(2) ds(5)} */ +#define OID_ISO_ITU_COUNTRY "\x60" /* {joint-iso-itu-t(2) country(16)} */ + +/* + * ISO Member bodies OID parts + */ +#define OID_COUNTRY_US "\x86\x48" /* {us(840)} */ +#define OID_ORG_RSA_DATA_SECURITY "\x86\xf7\x0d" /* {rsadsi(113549)} */ +#define OID_RSA_COMPANY OID_ISO_MEMBER_BODIES OID_COUNTRY_US \ + OID_ORG_RSA_DATA_SECURITY /* {iso(1) member-body(2) us(840) rsadsi(113549)} */ +#define OID_ORG_ANSI_X9_62 "\xce\x3d" /* ansi-X9-62(10045) */ +#define OID_ANSI_X9_62 OID_ISO_MEMBER_BODIES OID_COUNTRY_US \ + OID_ORG_ANSI_X9_62 + +/* + * ISO Identified organization OID parts + */ +#define OID_ORG_DOD "\x06" /* {dod(6)} */ +#define OID_ORG_OIW "\x0e" +#define OID_OIW_SECSIG OID_ORG_OIW "\x03" +#define OID_OIW_SECSIG_ALG OID_OIW_SECSIG "\x02" +#define OID_OIW_SECSIG_SHA1 OID_OIW_SECSIG_ALG "\x1a" +#define OID_ORG_CERTICOM "\x81\x04" /* certicom(132) */ +#define OID_CERTICOM OID_ISO_IDENTIFIED_ORG OID_ORG_CERTICOM +#define OID_ORG_TELETRUST "\x24" /* teletrust(36) */ +#define OID_TELETRUST OID_ISO_IDENTIFIED_ORG OID_ORG_TELETRUST + +/* + * ISO ITU OID parts + */ +#define OID_ORGANIZATION "\x01" /* {organization(1)} */ +#define OID_ISO_ITU_US_ORG OID_ISO_ITU_COUNTRY OID_COUNTRY_US OID_ORGANIZATION /* {joint-iso-itu-t(2) country(16) us(840) organization(1)} */ + +#define OID_ORG_GOV "\x65" /* {gov(101)} */ +#define OID_GOV OID_ISO_ITU_US_ORG OID_ORG_GOV /* {joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101)} */ + +#define OID_ORG_NETSCAPE "\x86\xF8\x42" /* {netscape(113730)} */ +#define OID_NETSCAPE OID_ISO_ITU_US_ORG OID_ORG_NETSCAPE /* Netscape OID {joint-iso-itu-t(2) country(16) us(840) organization(1) netscape(113730)} */ + +/* ISO arc for standard certificate and CRL extensions */ +#define OID_ID_CE OID_ISO_CCITT_DS "\x1D" /**< id-ce OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 29} */ + +/** + * Private Internet Extensions + * { iso(1) identified-organization(3) dod(6) internet(1) + * security(5) mechanisms(5) pkix(7) } + */ +#define OID_PKIX OID_ISO_IDENTIFIED_ORG OID_ORG_DOD "\x01\x05\x05\x07" + +/* + * Arc for standard naming attributes + */ +#define OID_AT OID_ISO_CCITT_DS "\x04" /**< id-at OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 4} */ +#define OID_AT_CN OID_AT "\x03" /**< id-at-commonName AttributeType:= {id-at 3} */ +#define OID_AT_SUR_NAME OID_AT "\x04" /**< id-at-surName AttributeType:= {id-at 4} */ +#define OID_AT_SERIAL_NUMBER OID_AT "\x05" /**< id-at-serialNumber AttributeType:= {id-at 5} */ +#define OID_AT_COUNTRY OID_AT "\x06" /**< id-at-countryName AttributeType:= {id-at 6} */ +#define OID_AT_LOCALITY OID_AT "\x07" /**< id-at-locality AttributeType:= {id-at 7} */ +#define OID_AT_STATE OID_AT "\x08" /**< id-at-state AttributeType:= {id-at 8} */ +#define OID_AT_ORGANIZATION OID_AT "\x0A" /**< id-at-organizationName AttributeType:= {id-at 10} */ +#define OID_AT_ORG_UNIT OID_AT "\x0B" /**< id-at-organizationalUnitName AttributeType:= {id-at 11} */ +#define OID_AT_TITLE OID_AT "\x0C" /**< id-at-title AttributeType:= {id-at 12} */ +#define OID_AT_POSTAL_ADDRESS OID_AT "\x10" /**< id-at-postalAddress AttributeType:= {id-at 16} */ +#define OID_AT_POSTAL_CODE OID_AT "\x11" /**< id-at-postalCode AttributeType:= {id-at 17} */ +#define OID_AT_GIVEN_NAME OID_AT "\x2A" /**< id-at-givenName AttributeType:= {id-at 42} */ +#define OID_AT_INITIALS OID_AT "\x2B" /**< id-at-initials AttributeType:= {id-at 43} */ +#define OID_AT_GENERATION_QUALIFIER OID_AT "\x2C" /**< id-at-generationQualifier AttributeType:= {id-at 44} */ +#define OID_AT_DN_QUALIFIER OID_AT "\x2E" /**< id-at-dnQualifier AttributeType:= {id-at 46} */ +#define OID_AT_PSEUDONYM OID_AT "\x41" /**< id-at-pseudonym AttributeType:= {id-at 65} */ + +#define OID_DOMAIN_COMPONENT "\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x19" /** id-domainComponent AttributeType:= {itu-t(0) data(9) pss(2342) ucl(19200300) pilot(100) pilotAttributeType(1) domainComponent(25)} */ + +/* + * OIDs for standard certificate extensions + */ +#define OID_AUTHORITY_KEY_IDENTIFIER OID_ID_CE "\x23" /**< id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 } */ +#define OID_SUBJECT_KEY_IDENTIFIER OID_ID_CE "\x0E" /**< id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 } */ +#define OID_KEY_USAGE OID_ID_CE "\x0F" /**< id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } */ +#define OID_CERTIFICATE_POLICIES OID_ID_CE "\x20" /**< id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } */ +#define OID_POLICY_MAPPINGS OID_ID_CE "\x21" /**< id-ce-policyMappings OBJECT IDENTIFIER ::= { id-ce 33 } */ +#define OID_SUBJECT_ALT_NAME OID_ID_CE "\x11" /**< id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 } */ +#define OID_ISSUER_ALT_NAME OID_ID_CE "\x12" /**< id-ce-issuerAltName OBJECT IDENTIFIER ::= { id-ce 18 } */ +#define OID_SUBJECT_DIRECTORY_ATTRS OID_ID_CE "\x09" /**< id-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::= { id-ce 9 } */ +#define OID_BASIC_CONSTRAINTS OID_ID_CE "\x13" /**< id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } */ +#define OID_NAME_CONSTRAINTS OID_ID_CE "\x1E" /**< id-ce-nameConstraints OBJECT IDENTIFIER ::= { id-ce 30 } */ +#define OID_POLICY_CONSTRAINTS OID_ID_CE "\x24" /**< id-ce-policyConstraints OBJECT IDENTIFIER ::= { id-ce 36 } */ +#define OID_EXTENDED_KEY_USAGE OID_ID_CE "\x25" /**< id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 } */ +#define OID_CRL_DISTRIBUTION_POINTS OID_ID_CE "\x1F" /**< id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= { id-ce 31 } */ +#define OID_INIHIBIT_ANYPOLICY OID_ID_CE "\x36" /**< id-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::= { id-ce 54 } */ +#define OID_FRESHEST_CRL OID_ID_CE "\x2E" /**< id-ce-freshestCRL OBJECT IDENTIFIER ::= { id-ce 46 } */ + +/* + * Netscape certificate extensions + */ +#define OID_NS_CERT OID_NETSCAPE "\x01" +#define OID_NS_CERT_TYPE OID_NS_CERT "\x01" +#define OID_NS_BASE_URL OID_NS_CERT "\x02" +#define OID_NS_REVOCATION_URL OID_NS_CERT "\x03" +#define OID_NS_CA_REVOCATION_URL OID_NS_CERT "\x04" +#define OID_NS_RENEWAL_URL OID_NS_CERT "\x07" +#define OID_NS_CA_POLICY_URL OID_NS_CERT "\x08" +#define OID_NS_SSL_SERVER_NAME OID_NS_CERT "\x0C" +#define OID_NS_COMMENT OID_NS_CERT "\x0D" +#define OID_NS_DATA_TYPE OID_NETSCAPE "\x02" +#define OID_NS_CERT_SEQUENCE OID_NS_DATA_TYPE "\x05" + +/* + * OIDs for CRL extensions + */ +#define OID_PRIVATE_KEY_USAGE_PERIOD OID_ID_CE "\x10" +#define OID_CRL_NUMBER OID_ID_CE "\x14" /**< id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 } */ + +/* + * X.509 v3 Extended key usage OIDs + */ +#define OID_ANY_EXTENDED_KEY_USAGE OID_EXTENDED_KEY_USAGE "\x00" /**< anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 } */ + +#define OID_KP OID_PKIX "\x03" /**< id-kp OBJECT IDENTIFIER ::= { id-pkix 3 } */ +#define OID_SERVER_AUTH OID_KP "\x01" /**< id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 } */ +#define OID_CLIENT_AUTH OID_KP "\x02" /**< id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 } */ +#define OID_CODE_SIGNING OID_KP "\x03" /**< id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 } */ +#define OID_EMAIL_PROTECTION OID_KP "\x04" /**< id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 } */ +#define OID_TIME_STAMPING OID_KP "\x08" /**< id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 } */ +#define OID_OCSP_SIGNING OID_KP "\x09" /**< id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 } */ + +/* + * PKCS definition OIDs + */ + +#define OID_PKCS OID_RSA_COMPANY "\x01" /**< pkcs OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) 1 } */ +#define OID_PKCS1 OID_PKCS "\x01" /**< pkcs-1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 } */ +#define OID_PKCS5 OID_PKCS "\x05" /**< pkcs-5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 5 } */ +#define OID_PKCS9 OID_PKCS "\x09" /**< pkcs-9 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 } */ +#define OID_PKCS12 OID_PKCS "\x0c" /**< pkcs-12 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 12 } */ + +/* + * PKCS#1 OIDs + */ +#define OID_PKCS1_RSA OID_PKCS1 "\x01" /**< rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 } */ +#define OID_PKCS1_MD2 OID_PKCS1 "\x02" /**< md2WithRSAEncryption ::= { pkcs-1 2 } */ +#define OID_PKCS1_MD4 OID_PKCS1 "\x03" /**< md4WithRSAEncryption ::= { pkcs-1 3 } */ +#define OID_PKCS1_MD5 OID_PKCS1 "\x04" /**< md5WithRSAEncryption ::= { pkcs-1 4 } */ +#define OID_PKCS1_SHA1 OID_PKCS1 "\x05" /**< sha1WithRSAEncryption ::= { pkcs-1 5 } */ +#define OID_PKCS1_SHA224 OID_PKCS1 "\x0e" /**< sha224WithRSAEncryption ::= { pkcs-1 14 } */ +#define OID_PKCS1_SHA256 OID_PKCS1 "\x0b" /**< sha256WithRSAEncryption ::= { pkcs-1 11 } */ +#define OID_PKCS1_SHA384 OID_PKCS1 "\x0c" /**< sha384WithRSAEncryption ::= { pkcs-1 12 } */ +#define OID_PKCS1_SHA512 OID_PKCS1 "\x0d" /**< sha512WithRSAEncryption ::= { pkcs-1 13 } */ + +#define OID_RSA_SHA_OBS "\x2B\x0E\x03\x02\x1D" + +#define OID_PKCS9_EMAIL OID_PKCS9 "\x01" /**< emailAddress AttributeType ::= { pkcs-9 1 } */ + +/* RFC 4055 */ +#define OID_RSASSA_PSS OID_PKCS1 "\x0a" /**< id-RSASSA-PSS ::= { pkcs-1 10 } */ +#define OID_MGF1 OID_PKCS1 "\x08" /**< id-mgf1 ::= { pkcs-1 8 } */ + +/* + * Digest algorithms + */ +#define OID_DIGEST_ALG_MD2 OID_RSA_COMPANY "\x02\x02" /**< id-md2 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 2 } */ +#define OID_DIGEST_ALG_MD4 OID_RSA_COMPANY "\x02\x04" /**< id-md4 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 4 } */ +#define OID_DIGEST_ALG_MD5 OID_RSA_COMPANY "\x02\x05" /**< id-md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5 } */ +#define OID_DIGEST_ALG_SHA1 OID_ISO_IDENTIFIED_ORG OID_OIW_SECSIG_SHA1 /**< id-sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } */ +#define OID_DIGEST_ALG_SHA224 OID_GOV "\x03\x04\x02\x04" /**< id-sha224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 4 } */ +#define OID_DIGEST_ALG_SHA256 OID_GOV "\x03\x04\x02\x01" /**< id-sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1 } */ + +#define OID_DIGEST_ALG_SHA384 OID_GOV "\x03\x04\x02\x02" /**< id-sha384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 2 } */ + +#define OID_DIGEST_ALG_SHA512 OID_GOV "\x03\x04\x02\x03" /**< id-sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 } */ + +#define OID_HMAC_SHA1 OID_RSA_COMPANY "\x02\x07" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 7 } */ + +/* + * Encryption algorithms + */ +#define OID_DES_CBC OID_ISO_IDENTIFIED_ORG OID_OIW_SECSIG_ALG "\x07" /**< desCBC OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 7 } */ +#define OID_DES_EDE3_CBC OID_RSA_COMPANY "\x03\x07" /**< des-ede3-cbc OBJECT IDENTIFIER ::= { iso(1) member-body(2) -- us(840) rsadsi(113549) encryptionAlgorithm(3) 7 } */ + +/* + * PKCS#5 OIDs + */ +#define OID_PKCS5_PBKDF2 OID_PKCS5 "\x0c" /**< id-PBKDF2 OBJECT IDENTIFIER ::= {pkcs-5 12} */ +#define OID_PKCS5_PBES2 OID_PKCS5 "\x0d" /**< id-PBES2 OBJECT IDENTIFIER ::= {pkcs-5 13} */ +#define OID_PKCS5_PBMAC1 OID_PKCS5 "\x0e" /**< id-PBMAC1 OBJECT IDENTIFIER ::= {pkcs-5 14} */ + +/* + * PKCS#5 PBES1 algorithms + */ +#define OID_PKCS5_PBE_MD2_DES_CBC OID_PKCS5 "\x01" /**< pbeWithMD2AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 1} */ +#define OID_PKCS5_PBE_MD2_RC2_CBC OID_PKCS5 "\x04" /**< pbeWithMD2AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 4} */ +#define OID_PKCS5_PBE_MD5_DES_CBC OID_PKCS5 "\x03" /**< pbeWithMD5AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 3} */ +#define OID_PKCS5_PBE_MD5_RC2_CBC OID_PKCS5 "\x06" /**< pbeWithMD5AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 6} */ +#define OID_PKCS5_PBE_SHA1_DES_CBC OID_PKCS5 "\x0a" /**< pbeWithSHA1AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 10} */ +#define OID_PKCS5_PBE_SHA1_RC2_CBC OID_PKCS5 "\x0b" /**< pbeWithSHA1AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 11} */ + +/* + * PKCS#8 OIDs + */ +#define OID_PKCS9_CSR_EXT_REQ OID_PKCS9 "\x0e" /**< extensionRequest OBJECT IDENTIFIER ::= {pkcs-9 14} */ + +/* + * PKCS#12 PBE OIDs + */ +#define OID_PKCS12_PBE OID_PKCS12 "\x01" /**< pkcs-12PbeIds OBJECT IDENTIFIER ::= {pkcs-12 1} */ + +#define OID_PKCS12_PBE_SHA1_RC4_128 OID_PKCS12_PBE "\x01" /**< pbeWithSHAAnd128BitRC4 OBJECT IDENTIFIER ::= {pkcs-12PbeIds 1} */ +#define OID_PKCS12_PBE_SHA1_RC4_40 OID_PKCS12_PBE "\x02" /**< pbeWithSHAAnd40BitRC4 OBJECT IDENTIFIER ::= {pkcs-12PbeIds 2} */ +#define OID_PKCS12_PBE_SHA1_DES3_EDE_CBC OID_PKCS12_PBE "\x03" /**< pbeWithSHAAnd3-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 3} */ +#define OID_PKCS12_PBE_SHA1_DES2_EDE_CBC OID_PKCS12_PBE "\x04" /**< pbeWithSHAAnd2-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 4} */ +#define OID_PKCS12_PBE_SHA1_RC2_128_CBC OID_PKCS12_PBE "\x05" /**< pbeWithSHAAnd128BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 5} */ +#define OID_PKCS12_PBE_SHA1_RC2_40_CBC OID_PKCS12_PBE "\x06" /**< pbeWithSHAAnd40BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 6} */ + +/* + * EC key algorithms from RFC 5480 + */ + +/* id-ecPublicKey OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 } */ +#define OID_EC_ALG_UNRESTRICTED OID_ANSI_X9_62 "\x02\01" + +/* id-ecDH OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) + * schemes(1) ecdh(12) } */ +#define OID_EC_ALG_ECDH OID_CERTICOM "\x01\x0c" + +/* + * ECParameters namedCurve identifiers, from RFC 5480, RFC 5639, and SEC2 + */ + +/* secp192r1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 1 } */ +#define OID_EC_GRP_SECP192R1 OID_ANSI_X9_62 "\x03\x01\x01" + +/* secp224r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 33 } */ +#define OID_EC_GRP_SECP224R1 OID_CERTICOM "\x00\x21" + +/* secp256r1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 7 } */ +#define OID_EC_GRP_SECP256R1 OID_ANSI_X9_62 "\x03\x01\x07" + +/* secp384r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 34 } */ +#define OID_EC_GRP_SECP384R1 OID_CERTICOM "\x00\x22" + +/* secp521r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 35 } */ +#define OID_EC_GRP_SECP521R1 OID_CERTICOM "\x00\x23" + +/* secp192k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 31 } */ +#define OID_EC_GRP_SECP192K1 OID_CERTICOM "\x00\x1f" + +/* secp224k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 32 } */ +#define OID_EC_GRP_SECP224K1 OID_CERTICOM "\x00\x20" + +/* secp256k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 10 } */ +#define OID_EC_GRP_SECP256K1 OID_CERTICOM "\x00\x0a" + +/* RFC 5639 4.1 + * ecStdCurvesAndGeneration OBJECT IDENTIFIER::= {iso(1) + * identified-organization(3) teletrust(36) algorithm(3) signature- + * algorithm(3) ecSign(2) 8} + * ellipticCurve OBJECT IDENTIFIER ::= {ecStdCurvesAndGeneration 1} + * versionOne OBJECT IDENTIFIER ::= {ellipticCurve 1} */ +#define OID_EC_BRAINPOOL_V1 OID_TELETRUST "\x03\x03\x02\x08\x01\x01" + +/* brainpoolP256r1 OBJECT IDENTIFIER ::= {versionOne 7} */ +#define OID_EC_GRP_BP256R1 OID_EC_BRAINPOOL_V1 "\x07" + +/* brainpoolP384r1 OBJECT IDENTIFIER ::= {versionOne 11} */ +#define OID_EC_GRP_BP384R1 OID_EC_BRAINPOOL_V1 "\x0B" + +/* brainpoolP512r1 OBJECT IDENTIFIER ::= {versionOne 13} */ +#define OID_EC_GRP_BP512R1 OID_EC_BRAINPOOL_V1 "\x0D" + +/* + * SEC1 C.1 + * + * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } + * id-fieldType OBJECT IDENTIFIER ::= { ansi-X9-62 fieldType(1)} + */ +#define OID_ANSI_X9_62_FIELD_TYPE OID_ANSI_X9_62 "\x01" +#define OID_ANSI_X9_62_PRIME_FIELD OID_ANSI_X9_62_FIELD_TYPE "\x01" + +/* + * ECDSA signature identifiers, from RFC 5480 + */ +#define OID_ANSI_X9_62_SIG OID_ANSI_X9_62 "\x04" /* signatures(4) */ +#define OID_ANSI_X9_62_SIG_SHA2 OID_ANSI_X9_62_SIG "\x03" /* ecdsa-with-SHA2(3) */ + +/* ecdsa-with-SHA1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) 1 } */ +#define OID_ECDSA_SHA1 OID_ANSI_X9_62_SIG "\x01" + +/* ecdsa-with-SHA224 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 1 } */ +#define OID_ECDSA_SHA224 OID_ANSI_X9_62_SIG_SHA2 "\x01" + +/* ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 2 } */ +#define OID_ECDSA_SHA256 OID_ANSI_X9_62_SIG_SHA2 "\x02" + +/* ecdsa-with-SHA384 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 3 } */ +#define OID_ECDSA_SHA384 OID_ANSI_X9_62_SIG_SHA2 "\x03" + +/* ecdsa-with-SHA512 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 4 } */ +#define OID_ECDSA_SHA512 OID_ANSI_X9_62_SIG_SHA2 "\x04" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Base OID descriptor structure + */ +typedef struct { + const char *asn1; /*!< OID ASN.1 representation */ + size_t asn1_len; /*!< length of asn1 */ + const char *name; /*!< official name (e.g. from RFC) */ + const char *description; /*!< human friendly description */ +} oid_descriptor_t; + +/** + * \brief Translate an ASN.1 OID into its numeric representation + * (e.g. "\x2A\x86\x48\x86\xF7\x0D" into "1.2.840.113549") + * + * \param buf buffer to put representation in + * \param size size of the buffer + * \param oid OID to translate + * + * \return Length of the string written (excluding final NULL) or + * POLARSSL_ERR_OID_BUF_TO_SMALL in case of error + */ +int oid_get_numeric_string( char *buf, size_t size, const asn1_buf *oid ); + +#if defined(POLARSSL_X509_USE_C) || defined(POLARSSL_X509_CREATE_C) +/** + * \brief Translate an X.509 extension OID into local values + * + * \param oid OID to use + * \param ext_type place to store the extension type + * + * \return 0 if successful, or POLARSSL_ERR_OID_NOT_FOUND + */ +int oid_get_x509_ext_type( const asn1_buf *oid, int *ext_type ); +#endif + +/** + * \brief Translate an X.509 attribute type OID into the short name + * (e.g. the OID for an X520 Common Name into "CN") + * + * \param oid OID to use + * \param short_name place to store the string pointer + * + * \return 0 if successful, or POLARSSL_ERR_OID_NOT_FOUND + */ +int oid_get_attr_short_name( const asn1_buf *oid, const char **short_name ); + +/** + * \brief Translate PublicKeyAlgorithm OID into pk_type + * + * \param oid OID to use + * \param pk_alg place to store public key algorithm + * + * \return 0 if successful, or POLARSSL_ERR_OID_NOT_FOUND + */ +int oid_get_pk_alg( const asn1_buf *oid, pk_type_t *pk_alg ); + +/** + * \brief Translate pk_type into PublicKeyAlgorithm OID + * + * \param pk_alg Public key type to look for + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or POLARSSL_ERR_OID_NOT_FOUND + */ +int oid_get_oid_by_pk_alg( pk_type_t pk_alg, + const char **oid, size_t *olen ); + +#if defined(POLARSSL_ECP_C) +/** + * \brief Translate NamedCurve OID into an EC group identifier + * + * \param oid OID to use + * \param grp_id place to store group id + * + * \return 0 if successful, or POLARSSL_ERR_OID_NOT_FOUND + */ +int oid_get_ec_grp( const asn1_buf *oid, ecp_group_id *grp_id ); + +/** + * \brief Translate EC group identifier into NamedCurve OID + * + * \param grp_id EC group identifier + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or POLARSSL_ERR_OID_NOT_FOUND + */ +int oid_get_oid_by_ec_grp( ecp_group_id grp_id, + const char **oid, size_t *olen ); +#endif /* POLARSSL_ECP_C */ + +#if defined(POLARSSL_MD_C) +/** + * \brief Translate SignatureAlgorithm OID into md_type and pk_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * \param pk_alg place to store public key algorithm + * + * \return 0 if successful, or POLARSSL_ERR_OID_NOT_FOUND + */ +int oid_get_sig_alg( const asn1_buf *oid, + md_type_t *md_alg, pk_type_t *pk_alg ); + +/** + * \brief Translate SignatureAlgorithm OID into description + * + * \param oid OID to use + * \param desc place to store string pointer + * + * \return 0 if successful, or POLARSSL_ERR_OID_NOT_FOUND + */ +int oid_get_sig_alg_desc( const asn1_buf *oid, const char **desc ); + +/** + * \brief Translate md_type and pk_type into SignatureAlgorithm OID + * + * \param md_alg message digest algorithm + * \param pk_alg public key algorithm + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or POLARSSL_ERR_OID_NOT_FOUND + */ +int oid_get_oid_by_sig_alg( pk_type_t pk_alg, md_type_t md_alg, + const char **oid, size_t *olen ); + +/** + * \brief Translate hash algorithm OID into md_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * + * \return 0 if successful, or POLARSSL_ERR_OID_NOT_FOUND + */ +int oid_get_md_alg( const asn1_buf *oid, md_type_t *md_alg ); +#endif /* POLARSSL_MD_C */ + +/** + * \brief Translate Extended Key Usage OID into description + * + * \param oid OID to use + * \param desc place to store string pointer + * + * \return 0 if successful, or POLARSSL_ERR_OID_NOT_FOUND + */ +int oid_get_extended_key_usage( const asn1_buf *oid, const char **desc ); + +/** + * \brief Translate md_type into hash algorithm OID + * + * \param md_alg message digest algorithm + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or POLARSSL_ERR_OID_NOT_FOUND + */ +int oid_get_oid_by_md( md_type_t md_alg, const char **oid, size_t *olen ); + +#if defined(POLARSSL_CIPHER_C) +/** + * \brief Translate encryption algorithm OID into cipher_type + * + * \param oid OID to use + * \param cipher_alg place to store cipher algorithm + * + * \return 0 if successful, or POLARSSL_ERR_OID_NOT_FOUND + */ +int oid_get_cipher_alg( const asn1_buf *oid, cipher_type_t *cipher_alg ); +#endif /* POLARSSL_CIPHER_C */ + +#if defined(POLARSSL_PKCS12_C) +/** + * \brief Translate PKCS#12 PBE algorithm OID into md_type and + * cipher_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * \param cipher_alg place to store cipher algorithm + * + * \return 0 if successful, or POLARSSL_ERR_OID_NOT_FOUND + */ +int oid_get_pkcs12_pbe_alg( const asn1_buf *oid, md_type_t *md_alg, + cipher_type_t *cipher_alg ); +#endif /* POLARSSL_PKCS12_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* oid.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/openssl.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/openssl.h new file mode 100644 index 0000000..b77e7da --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/openssl.h @@ -0,0 +1,140 @@ +/** + * \file openssl.h + * + * \brief OpenSSL wrapper (definitions, inline functions). + * + * Copyright (C) 2006-2010, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * OpenSSL wrapper contributed by David Barett + */ +#ifndef POLARSSL_OPENSSL_H +#define POLARSSL_OPENSSL_H + +#include "aes.h" +#include "md5.h" +#include "rsa.h" +#include "sha1.h" + +#define AES_SIZE 16 +#define AES_BLOCK_SIZE 16 +#define AES_KEY aes_context +#define MD5_CTX md5_context +#define SHA_CTX sha1_context + +#define SHA1_Init( CTX ) \ + sha1_starts( (CTX) ) +#define SHA1_Update( CTX, BUF, LEN ) \ + sha1_update( (CTX), (unsigned char *)(BUF), (LEN) ) +#define SHA1_Final( OUT, CTX ) \ + sha1_finish( (CTX), (OUT) ) + +#define MD5_Init( CTX ) \ + md5_starts( (CTX) ) +#define MD5_Update( CTX, BUF, LEN ) \ + md5_update( (CTX), (unsigned char *)(BUF), (LEN) ) +#define MD5_Final( OUT, CTX ) \ + md5_finish( (CTX), (OUT) ) + +#define AES_set_encrypt_key( KEY, KEYSIZE, CTX ) \ + aes_setkey_enc( (CTX), (KEY), (KEYSIZE) ) +#define AES_set_decrypt_key( KEY, KEYSIZE, CTX ) \ + aes_setkey_dec( (CTX), (KEY), (KEYSIZE) ) +#define AES_cbc_encrypt( INPUT, OUTPUT, LEN, CTX, IV, MODE ) \ + aes_crypt_cbc( (CTX), (MODE), (LEN), (IV), (INPUT), (OUTPUT) ) + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * RSA stuff follows. TODO: needs cleanup + */ +inline int __RSA_Passthrough( void *output, void *input, int size ) +{ + memcpy( output, input, size ); + return size; +} + +inline rsa_context* d2i_RSA_PUBKEY( void *ignore, unsigned char **bufptr, + int len ) +{ + unsigned char *buffer = *(unsigned char **) bufptr; + rsa_context *rsa; + + /* + * Not a general-purpose parser: only parses public key from *exactly* + * openssl genrsa -out privkey.pem 512 (or 1024) + * openssl rsa -in privkey.pem -out privatekey.der -outform der + * openssl rsa -in privkey.pem -out pubkey.der -outform der -pubout + * + * TODO: make a general-purpose parse + */ + if( ignore != 0 || ( len != 94 && len != 162 ) ) + return( 0 ); + + rsa = (rsa_context *) malloc( sizeof( rsa_rsa ) ); + if( rsa == NULL ) + return( 0 ); + + memset( rsa, 0, sizeof( rsa_context ) ); + + if( ( len == 94 && + mpi_read_binary( &rsa->N, &buffer[ 25], 64 ) == 0 && + mpi_read_binary( &rsa->E, &buffer[ 91], 3 ) == 0 ) || + ( len == 162 && + mpi_read_binary( &rsa->N, &buffer[ 29], 128 ) == 0 ) && + mpi_read_binary( &rsa->E, &buffer[159], 3 ) == 0 ) + { + /* + * key read successfully + */ + rsa->len = ( mpi_msb( &rsa->N ) + 7 ) >> 3; + return( rsa ); + } + else + { + memset( rsa, 0, sizeof( rsa_context ) ); + free( rsa ); + return( 0 ); + } +} + +#define RSA rsa_context +#define RSA_PKCS1_PADDING 1 /* ignored; always encrypt with this */ +#define RSA_size( CTX ) (CTX)->len +#define RSA_free( CTX ) rsa_free( CTX ) +#define ERR_get_error( ) "ERR_get_error() not supported" +#define RSA_blinding_off( IGNORE ) + +#define d2i_RSAPrivateKey( a, b, c ) new rsa_context /* TODO: C++ bleh */ + +inline int RSA_public_decrypt ( int size, unsigned char* input, unsigned char* output, RSA* key, int ignore ) { int outsize=size; if( !rsa_pkcs1_decrypt( key, RSA_PUBLIC, &outsize, input, output ) ) return outsize; else return -1; } +inline int RSA_private_decrypt( int size, unsigned char* input, unsigned char* output, RSA* key, int ignore ) { int outsize=size; if( !rsa_pkcs1_decrypt( key, RSA_PRIVATE, &outsize, input, output ) ) return outsize; else return -1; } +inline int RSA_public_encrypt ( int size, unsigned char* input, unsigned char* output, RSA* key, int ignore ) { if( !rsa_pkcs1_encrypt( key, RSA_PUBLIC, size, input, output ) ) return RSA_size(key); else return -1; } +inline int RSA_private_encrypt( int size, unsigned char* input, unsigned char* output, RSA* key, int ignore ) { if( !rsa_pkcs1_encrypt( key, RSA_PRIVATE, size, input, output ) ) return RSA_size(key); else return -1; } + +#ifdef __cplusplus +} +#endif + +#endif /* openssl.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/padlock.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/padlock.h new file mode 100644 index 0000000..3c5f725 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/padlock.h @@ -0,0 +1,109 @@ +/** + * \file padlock.h + * + * \brief VIA PadLock ACE for HW encryption/decryption supported by some + * processors + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_PADLOCK_H +#define POLARSSL_PADLOCK_H + +#include "aes.h" + +#define POLARSSL_ERR_PADLOCK_DATA_MISALIGNED -0x0030 /**< Input data should be aligned. */ + +#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && defined(__i386__) + +#ifndef POLARSSL_HAVE_X86 +#define POLARSSL_HAVE_X86 +#endif + +#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32) +#include +typedef INT32 int32_t; +#else +#include +#endif + + +#define PADLOCK_RNG 0x000C +#define PADLOCK_ACE 0x00C0 +#define PADLOCK_PHE 0x0C00 +#define PADLOCK_PMM 0x3000 + +#define PADLOCK_ALIGN16(x) (uint32_t *) (16 + ((int32_t) x & ~15)) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief PadLock detection routine + * + * \param feature The feature to detect + * + * \return 1 if CPU has support for the feature, 0 otherwise + */ +int padlock_supports( int feature ); + +/** + * \brief PadLock AES-ECB block en(de)cryption + * + * \param ctx AES context + * \param mode AES_ENCRYPT or AES_DECRYPT + * \param input 16-byte input block + * \param output 16-byte output block + * + * \return 0 if success, 1 if operation failed + */ +int padlock_xcryptecb( aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +/** + * \brief PadLock AES-CBC buffer en(de)cryption + * + * \param ctx AES context + * \param mode AES_ENCRYPT or AES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if success, 1 if operation failed + */ +int padlock_xcryptcbc( aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); + +#ifdef __cplusplus +} +#endif + +#endif /* HAVE_X86 */ + +#endif /* padlock.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/pbkdf2.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/pbkdf2.h new file mode 100644 index 0000000..5ccb2fa --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/pbkdf2.h @@ -0,0 +1,82 @@ +/** + * \file pbkdf2.h + * + * \brief Password-Based Key Derivation Function 2 (from PKCS#5) + * DEPRECATED: use pkcs5.h instead. + * + * \author Mathias Olsson + * + * Copyright (C) 2006-2012, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_PBKDF2_H +#define POLARSSL_PBKDF2_H + +#include + +#include "md.h" + +#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32) +#include +typedef UINT32 uint32_t; +#else +#include +#endif + +#define POLARSSL_ERR_PBKDF2_BAD_INPUT_DATA -0x007C /**< Bad input parameters to function. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief PKCS#5 PBKDF2 using HMAC + * DEPRECATED: Use pkcs5_pbkdf2_hmac() instead! + * + * \param ctx Generic HMAC context + * \param password Password to use when generating key + * \param plen Length of password + * \param salt Salt to use when generating key + * \param slen Length of salt + * \param iteration_count Iteration count + * \param key_length Length of generated key + * \param output Generated key. Must be at least as big as key_length + * + * \returns 0 on success, or a PolarSSL error code if verification fails. + */ +int pbkdf2_hmac( md_context_t *ctx, const unsigned char *password, + size_t plen, const unsigned char *salt, size_t slen, + unsigned int iteration_count, + uint32_t key_length, unsigned char *output ); + +/** + * \brief Checkup routine + * DEPRECATED: Use pkcs5_self_test() instead! + * + * \return 0 if successful, or 1 if the test failed + */ +int pbkdf2_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* pbkdf2.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/pem.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/pem.h new file mode 100644 index 0000000..e606cf0 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/pem.h @@ -0,0 +1,133 @@ +/** + * \file pem.h + * + * \brief Privacy Enhanced Mail (PEM) decoding + * + * Copyright (C) 2006-2013, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_PEM_H +#define POLARSSL_PEM_H + +#include + +/** + * \name PEM Error codes + * These error codes are returned in case of errors reading the + * PEM data. + * \{ + */ +#define POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT -0x1080 /**< No PEM header or footer found. */ +#define POLARSSL_ERR_PEM_INVALID_DATA -0x1100 /**< PEM string is not as expected. */ +#define POLARSSL_ERR_PEM_MALLOC_FAILED -0x1180 /**< Failed to allocate memory. */ +#define POLARSSL_ERR_PEM_INVALID_ENC_IV -0x1200 /**< RSA IV is not in hex-format. */ +#define POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG -0x1280 /**< Unsupported key encryption algorithm. */ +#define POLARSSL_ERR_PEM_PASSWORD_REQUIRED -0x1300 /**< Private key password can't be empty. */ +#define POLARSSL_ERR_PEM_PASSWORD_MISMATCH -0x1380 /**< Given private key password does not allow for correct decryption. */ +#define POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE -0x1400 /**< Unavailable feature, e.g. hashing/encryption combination. */ +#define POLARSSL_ERR_PEM_BAD_INPUT_DATA -0x1480 /**< Bad input parameters to function. */ +/* \} name */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(POLARSSL_PEM_PARSE_C) +/** + * \brief PEM context structure + */ +typedef struct +{ + unsigned char *buf; /*!< buffer for decoded data */ + size_t buflen; /*!< length of the buffer */ + unsigned char *info; /*!< buffer for extra header information */ +} +pem_context; + +/** + * \brief PEM context setup + * + * \param ctx context to be initialized + */ +void pem_init( pem_context *ctx ); + +/** + * \brief Read a buffer for PEM information and store the resulting + * data into the specified context buffers. + * + * \param ctx context to use + * \param header header string to seek and expect + * \param footer footer string to seek and expect + * \param data source data to look in + * \param pwd password for decryption (can be NULL) + * \param pwdlen length of password + * \param use_len destination for total length used (set after header is + * correctly read, so unless you get + * POLARSSL_ERR_PEM_BAD_INPUT_DATA or + * POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT, use_len is + * the length to skip) + * + * \note Attempts to check password correctness by verifying if + * the decrypted text starts with an ASN.1 sequence of + * appropriate length + * + * \return 0 on success, or a specific PEM error code + */ +int pem_read_buffer( pem_context *ctx, const char *header, const char *footer, + const unsigned char *data, + const unsigned char *pwd, + size_t pwdlen, size_t *use_len ); + +/** + * \brief PEM context memory freeing + * + * \param ctx context to be freed + */ +void pem_free( pem_context *ctx ); +#endif /* POLARSSL_PEM_PARSE_C */ + +#if defined(POLARSSL_PEM_WRITE_C) +/** + * \brief Write a buffer of PEM information from a DER encoded + * buffer. + * + * \param header header string to write + * \param footer footer string to write + * \param der_data DER data to write + * \param der_len length of the DER data + * \param buf buffer to write to + * \param buf_len length of output buffer + * \param olen total length written / required (if buf_len is not enough) + * + * \return 0 on success, or a specific PEM or BASE64 error code. On + * POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL olen is the required + * size. + */ +int pem_write_buffer( const char *header, const char *footer, + const unsigned char *der_data, size_t der_len, + unsigned char *buf, size_t buf_len, size_t *olen ); +#endif /* POLARSSL_PEM_WRITE_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* pem.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/pk.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/pk.h new file mode 100644 index 0000000..754dda2 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/pk.h @@ -0,0 +1,632 @@ +/** + * \file pk.h + * + * \brief Public Key abstraction layer + * + * Copyright (C) 2006-2013, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef POLARSSL_PK_H +#define POLARSSL_PK_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include "md.h" + +#if defined(POLARSSL_RSA_C) +#include "rsa.h" +#endif + +#if defined(POLARSSL_ECP_C) +#include "ecp.h" +#endif + +#if defined(POLARSSL_ECDSA_C) +#include "ecdsa.h" +#endif + +#define POLARSSL_ERR_PK_MALLOC_FAILED -0x2F80 /**< Memory alloation failed. */ +#define POLARSSL_ERR_PK_TYPE_MISMATCH -0x2F00 /**< Type mismatch, eg attempt to encrypt with an ECDSA key */ +#define POLARSSL_ERR_PK_BAD_INPUT_DATA -0x2E80 /**< Bad input parameters to function. */ +#define POLARSSL_ERR_PK_FILE_IO_ERROR -0x2E00 /**< Read/write of file failed. */ +#define POLARSSL_ERR_PK_KEY_INVALID_VERSION -0x2D80 /**< Unsupported key version */ +#define POLARSSL_ERR_PK_KEY_INVALID_FORMAT -0x2D00 /**< Invalid key tag or value. */ +#define POLARSSL_ERR_PK_UNKNOWN_PK_ALG -0x2C80 /**< Key algorithm is unsupported (only RSA and EC are supported). */ +#define POLARSSL_ERR_PK_PASSWORD_REQUIRED -0x2C00 /**< Private key password can't be empty. */ +#define POLARSSL_ERR_PK_PASSWORD_MISMATCH -0x2B80 /**< Given private key password does not allow for correct decryption. */ +#define POLARSSL_ERR_PK_INVALID_PUBKEY -0x2B00 /**< The pubkey tag or value is invalid (only RSA and EC are supported). */ +#define POLARSSL_ERR_PK_INVALID_ALG -0x2A80 /**< The algorithm tag or value is invalid. */ +#define POLARSSL_ERR_PK_UNKNOWN_NAMED_CURVE -0x2A00 /**< Elliptic curve is unsupported (only NIST curves are supported). */ +#define POLARSSL_ERR_PK_FEATURE_UNAVAILABLE -0x2980 /**< Unavailable feature, e.g. RSA disabled for RSA key. */ +#define POLARSSL_ERR_PK_SIG_LEN_MISMATCH -0x2000 /**< The signature is valid but its length is less than expected. */ + + +#if defined(POLARSSL_RSA_C) +/** + * Quick access to an RSA context inside a PK context. + * + * \warning You must make sure the PK context actually holds an RSA context + * before using this macro! + */ +#define pk_rsa( pk ) ( (rsa_context *) (pk).pk_ctx ) +#endif /* POLARSSL_RSA_C */ + +#if defined(POLARSSL_ECP_C) +/** + * Quick access to an EC context inside a PK context. + * + * \warning You must make sure the PK context actually holds an EC context + * before using this macro! + */ +#define pk_ec( pk ) ( (ecp_keypair *) (pk).pk_ctx ) +#endif /* POLARSSL_ECP_C */ + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Public key types + */ +typedef enum { + POLARSSL_PK_NONE=0, + POLARSSL_PK_RSA, + POLARSSL_PK_ECKEY, + POLARSSL_PK_ECKEY_DH, + POLARSSL_PK_ECDSA, + POLARSSL_PK_RSA_ALT, + POLARSSL_PK_RSASSA_PSS, +} pk_type_t; + +/** + * \brief Options for RSASSA-PSS signature verification. + * See \c rsa_rsassa_pss_verify_ext() + */ +typedef struct +{ + md_type_t mgf1_hash_id; + int expected_salt_len; + +} pk_rsassa_pss_options; + +/** + * \brief Types for interfacing with the debug module + */ +typedef enum +{ + POLARSSL_PK_DEBUG_NONE = 0, + POLARSSL_PK_DEBUG_MPI, + POLARSSL_PK_DEBUG_ECP, +} pk_debug_type; + +/** + * \brief Item to send to the debug module + */ +typedef struct +{ + pk_debug_type type; + const char *name; + void *value; +} pk_debug_item; + +/** Maximum number of item send for debugging, plus 1 */ +#define POLARSSL_PK_DEBUG_MAX_ITEMS 3 + +/** + * \brief Public key information and operations + */ +typedef struct +{ + /** Public key type */ + pk_type_t type; + + /** Type name */ + const char *name; + + /** Get key size in bits */ + size_t (*get_size)( const void * ); + + /** Tell if the context implements this type (e.g. ECKEY can do ECDSA) */ + int (*can_do)( pk_type_t type ); + + /** Verify signature */ + int (*verify_func)( void *ctx, md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + + /** Make signature */ + int (*sign_func)( void *ctx, md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + + /** Decrypt message */ + int (*decrypt_func)( void *ctx, const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + + /** Encrypt message */ + int (*encrypt_func)( void *ctx, const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + + /** Allocate a new context */ + void * (*ctx_alloc_func)( void ); + + /** Free the given context */ + void (*ctx_free_func)( void *ctx ); + + /** Interface with the debug module */ + void (*debug_func)( const void *ctx, pk_debug_item *items ); + +} pk_info_t; + +/** + * \brief Public key container + */ +typedef struct +{ + const pk_info_t * pk_info; /**< Public key informations */ + void * pk_ctx; /**< Underlying public key context */ +} pk_context; + +/** + * \brief Types for RSA-alt abstraction + */ +typedef int (*pk_rsa_alt_decrypt_func)( void *ctx, int mode, size_t *olen, + const unsigned char *input, unsigned char *output, + size_t output_max_len ); +typedef int (*pk_rsa_alt_sign_func)( void *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + int mode, md_type_t md_alg, unsigned int hashlen, + const unsigned char *hash, unsigned char *sig ); +typedef size_t (*pk_rsa_alt_key_len_func)( void *ctx ); + +/** + * \brief Return information associated with the given PK type + * + * \param pk_type PK type to search for. + * + * \return The PK info associated with the type or NULL if not found. + */ +const pk_info_t *pk_info_from_type( pk_type_t pk_type ); + +/** + * \brief Initialize a pk_context (as NONE) + */ +void pk_init( pk_context *ctx ); + +/** + * \brief Free a pk_context + */ +void pk_free( pk_context *ctx ); + +/** + * \brief Initialize a PK context with the information given + * and allocates the type-specific PK subcontext. + * + * \param ctx Context to initialize. Must be empty (type NONE). + * \param info Information to use + * + * \return 0 on success, + * POLARSSL_ERR_PK_BAD_INPUT_DATA on invalid input, + * POLARSSL_ERR_PK_MALLOC_FAILED on allocation failure. + * + * \note For contexts holding an RSA-alt key, use + * \c pk_init_ctx_rsa_alt() instead. + */ +int pk_init_ctx( pk_context *ctx, const pk_info_t *info ); + +/** + * \brief Initialize an RSA-alt context + * + * \param ctx Context to initialize. Must be empty (type NONE). + * \param key RSA key pointer + * \param decrypt_func Decryption function + * \param sign_func Signing function + * \param key_len_func Function returning key length in bytes + * + * \return 0 on success, or POLARSSL_ERR_PK_BAD_INPUT_DATA if the + * context wasn't already initialized as RSA_ALT. + * + * \note This function replaces \c pk_init_ctx() for RSA-alt. + */ +int pk_init_ctx_rsa_alt( pk_context *ctx, void * key, + pk_rsa_alt_decrypt_func decrypt_func, + pk_rsa_alt_sign_func sign_func, + pk_rsa_alt_key_len_func key_len_func ); + +/** + * \brief Get the size in bits of the underlying key + * + * \param ctx Context to use + * + * \return Key size in bits, or 0 on error + */ +size_t pk_get_size( const pk_context *ctx ); + +/** + * \brief Get the length in bytes of the underlying key + * \param ctx Context to use + * + * \return Key length in bytes, or 0 on error + */ +static inline size_t pk_get_len( const pk_context *ctx ) +{ + return( ( pk_get_size( ctx ) + 7 ) / 8 ); +} + +/** + * \brief Tell if a context can do the operation given by type + * + * \param ctx Context to test + * \param type Target type + * + * \return 0 if context can't do the operations, + * 1 otherwise. + */ +int pk_can_do( pk_context *ctx, pk_type_t type ); + +/** + * \brief Verify signature (including padding if relevant). + * + * \param ctx PK context to use + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Signature to verify + * \param sig_len Signature length + * + * \return 0 on success (signature is valid), + * POLARSSL_ERR_PK_SIG_LEN_MISMATCH if the signature is + * valid but its actual length is less than sig_len, + * or a specific error code. + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * Use \c pk_verify_ext( POLARSSL_PK_RSASSA_PSS, ... ) + * to verify RSASSA_PSS signatures. + * + * \note If hash_len is 0, then the length associated with md_alg + * is used instead, or an error returned if it is invalid. + * + * \note md_alg may be POLARSSL_MD_NONE, only if hash_len != 0 + */ +int pk_verify( pk_context *ctx, md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + +/** + * \brief Verify signature, with options. + * (Includes verification of the padding depending on type.) + * + * \param type Signature type (inc. possible padding type) to verify + * \param options Pointer to type-specific options, or NULL + * \param ctx PK context to use + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Signature to verify + * \param sig_len Signature length + * + * \return 0 on success (signature is valid), + * POLARSSL_ERR_PK_TYPE_MISMATCH if the PK context can't be + * used for this type of signatures, + * POLARSSL_ERR_PK_SIG_LEN_MISMATCH if the signature is + * valid but its actual length is less than sig_len, + * or a specific error code. + * + * \note If hash_len is 0, then the length associated with md_alg + * is used instead, or an error returned if it is invalid. + * + * \note md_alg may be POLARSSL_MD_NONE, only if hash_len != 0 + * + * \note If type is POLARSSL_PK_RSASSA_PSS, then options must point + * to a pk_rsassa_pss_options structure, + * otherwise it must be NULL. + */ +int pk_verify_ext( pk_type_t type, const void *options, + pk_context *ctx, md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + +/** + * \brief Make signature, including padding if relevant. + * + * \param ctx PK context to use + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Place to write the signature + * \param sig_len Number of bytes written + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 on success, or a specific error code. + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * There is no interface in the PK module to make RSASSA-PSS + * signatures yet. + * + * \note If hash_len is 0, then the length associated with md_alg + * is used instead, or an error returned if it is invalid. + * + * \note md_alg may be POLARSSL_MD_NONE, only if hash_len != 0 + */ +int pk_sign( pk_context *ctx, md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Decrypt message (including padding if relevant). + * + * \param ctx PK context to use + * \param input Input to decrypt + * \param ilen Input size + * \param output Decrypted output + * \param olen Decrypted message length + * \param osize Size of the output buffer + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * + * \return 0 on success, or a specific error code. + */ +int pk_decrypt( pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Encrypt message (including padding if relevant). + * + * \param ctx PK context to use + * \param input Message to encrypt + * \param ilen Message size + * \param output Encrypted output + * \param olen Encrypted output length + * \param osize Size of the output buffer + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * + * \return 0 on success, or a specific error code. + */ +int pk_encrypt( pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Export debug information + * + * \param ctx Context to use + * \param items Place to write debug items + * + * \return 0 on success or POLARSSL_ERR_PK_BAD_INPUT_DATA + */ +int pk_debug( const pk_context *ctx, pk_debug_item *items ); + +/** + * \brief Access the type name + * + * \param ctx Context to use + * + * \return Type name on success, or "invalid PK" + */ +const char * pk_get_name( const pk_context *ctx ); + +/** + * \brief Get the key type + * + * \param ctx Context to use + * + * \return Type on success, or POLARSSL_PK_NONE + */ +pk_type_t pk_get_type( const pk_context *ctx ); + +#if defined(POLARSSL_PK_PARSE_C) +/** \ingroup pk_module */ +/** + * \brief Parse a private key + * + * \param ctx key to be initialized + * \param key input buffer + * \param keylen size of the buffer + * \param pwd password for decryption (optional) + * \param pwdlen size of the password + * + * \note On entry, ctx must be empty, either freshly initialised + * with pk_init() or reset with pk_free(). If you need a + * specific key type, check the result with pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int pk_parse_key( pk_context *ctx, + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen ); + +/** \ingroup pk_module */ +/** + * \brief Parse a public key + * + * \param ctx key to be initialized + * \param key input buffer + * \param keylen size of the buffer + * + * \note On entry, ctx must be empty, either freshly initialised + * with pk_init() or reset with pk_free(). If you need a + * specific key type, check the result with pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int pk_parse_public_key( pk_context *ctx, + const unsigned char *key, size_t keylen ); + +#if defined(POLARSSL_FS_IO) +/** \ingroup pk_module */ +/** + * \brief Load and parse a private key + * + * \param ctx key to be initialized + * \param path filename to read the private key from + * \param password password to decrypt the file (can be NULL) + * + * \note On entry, ctx must be empty, either freshly initialised + * with pk_init() or reset with pk_free(). If you need a + * specific key type, check the result with pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int pk_parse_keyfile( pk_context *ctx, + const char *path, const char *password ); + +/** \ingroup pk_module */ +/** + * \brief Load and parse a public key + * + * \param ctx key to be initialized + * \param path filename to read the private key from + * + * \note On entry, ctx must be empty, either freshly initialised + * with pk_init() or reset with pk_free(). If you need a + * specific key type, check the result with pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int pk_parse_public_keyfile( pk_context *ctx, const char *path ); +#endif /* POLARSSL_FS_IO */ +#endif /* POLARSSL_PK_PARSE_C */ + +#if defined(POLARSSL_PK_WRITE_C) +/** + * \brief Write a private key to a PKCS#1 or SEC1 DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx private to write away + * \param buf buffer to write to + * \param size size of the buffer + * + * \return length of data written if successful, or a specific + * error code + */ +int pk_write_key_der( pk_context *ctx, unsigned char *buf, size_t size ); + +/** + * \brief Write a public key to a SubjectPublicKeyInfo DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx public key to write away + * \param buf buffer to write to + * \param size size of the buffer + * + * \return length of data written if successful, or a specific + * error code + */ +int pk_write_pubkey_der( pk_context *ctx, unsigned char *buf, size_t size ); + +#if defined(POLARSSL_PEM_WRITE_C) +/** + * \brief Write a public key to a PEM string + * + * \param ctx public key to write away + * \param buf buffer to write to + * \param size size of the buffer + * + * \return 0 successful, or a specific error code + */ +int pk_write_pubkey_pem( pk_context *ctx, unsigned char *buf, size_t size ); + +/** + * \brief Write a private key to a PKCS#1 or SEC1 PEM string + * + * \param ctx private to write away + * \param buf buffer to write to + * \param size size of the buffer + * + * \return 0 successful, or a specific error code + */ +int pk_write_key_pem( pk_context *ctx, unsigned char *buf, size_t size ); +#endif /* POLARSSL_PEM_WRITE_C */ +#endif /* POLARSSL_PK_WRITE_C */ + +/* + * WARNING: Low-level functions. You probably do not want to use these unless + * you are certain you do ;) + */ + +#if defined(POLARSSL_PK_PARSE_C) +/** + * \brief Parse a SubjectPublicKeyInfo DER structure + * + * \param p the position in the ASN.1 data + * \param end end of the buffer + * \param pk the key to fill + * + * \return 0 if successful, or a specific PK error code + */ +int pk_parse_subpubkey( unsigned char **p, const unsigned char *end, + pk_context *pk ); +#endif /* POLARSSL_PK_PARSE_C */ + +#if defined(POLARSSL_PK_WRITE_C) +/** + * \brief Write a subjectPublicKey to ASN.1 data + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param key public key to write away + * + * \return the length written or a negative error code + */ +int pk_write_pubkey( unsigned char **p, unsigned char *start, + const pk_context *key ); +#endif /* POLARSSL_PK_WRITE_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* POLARSSL_PK_H */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/pk_wrap.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/pk_wrap.h new file mode 100644 index 0000000..7baafb9 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/pk_wrap.h @@ -0,0 +1,63 @@ +/** + * \file pk.h + * + * \brief Public Key abstraction layer: wrapper functions + * + * Copyright (C) 2006-2013, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef POLARSSL_PK_WRAP_H +#define POLARSSL_PK_WRAP_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include "pk.h" + +/* Container for RSA-alt */ +typedef struct +{ + void *key; + pk_rsa_alt_decrypt_func decrypt_func; + pk_rsa_alt_sign_func sign_func; + pk_rsa_alt_key_len_func key_len_func; +} rsa_alt_context; + +#if defined(POLARSSL_RSA_C) +extern const pk_info_t rsa_info; +#endif + +#if defined(POLARSSL_ECP_C) +extern const pk_info_t eckey_info; +extern const pk_info_t eckeydh_info; +#endif + +#if defined(POLARSSL_ECDSA_C) +extern const pk_info_t ecdsa_info; +#endif + +extern const pk_info_t rsa_alt_info; + +#endif /* POLARSSL_PK_WRAP_H */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/pkcs11.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/pkcs11.h new file mode 100644 index 0000000..84f862d --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/pkcs11.h @@ -0,0 +1,174 @@ +/** + * \file pkcs11.h + * + * \brief Wrapper for PKCS#11 library libpkcs11-helper + * + * \author Adriaan de Jong + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_PKCS11_H +#define POLARSSL_PKCS11_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_PKCS11_C) + +#include "x509_crt.h" + +#include + +#if defined(_MSC_VER) && !defined(inline) +#define inline _inline +#else +#if defined(__ARMCC_VERSION) && !defined(inline) +#define inline __inline +#endif /* __ARMCC_VERSION */ +#endif /*_MSC_VER */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Context for PKCS #11 private keys. + */ +typedef struct { + pkcs11h_certificate_t pkcs11h_cert; + int len; +} pkcs11_context; + +/** + * Fill in a PolarSSL certificate, based on the given PKCS11 helper certificate. + * + * \param cert X.509 certificate to fill + * \param pkcs11h_cert PKCS #11 helper certificate + * + * \return 0 on success. + */ +int pkcs11_x509_cert_init( x509_crt *cert, pkcs11h_certificate_t pkcs11h_cert ); + +/** + * Initialise a pkcs11_context, storing the given certificate. Note that the + * pkcs11_context will take over control of the certificate, freeing it when + * done. + * + * \param priv_key Private key structure to fill. + * \param pkcs11_cert PKCS #11 helper certificate + * + * \return 0 on success + */ +int pkcs11_priv_key_init( pkcs11_context *priv_key, + pkcs11h_certificate_t pkcs11_cert ); + +/** + * Free the contents of the given private key context. Note that the structure + * itself is not freed. + * + * \param priv_key Private key structure to cleanup + */ +void pkcs11_priv_key_free( pkcs11_context *priv_key ); + +/** + * \brief Do an RSA private key decrypt, then remove the message + * padding + * + * \param ctx PKCS #11 context + * \param mode must be RSA_PRIVATE, for compatibility with rsa.c's signature + * \param input buffer holding the encrypted data + * \param output buffer that will hold the plaintext + * \param olen will contain the plaintext length + * \param output_max_len maximum length of the output buffer + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + * + * \note The output buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise + * an error is thrown. + */ +int pkcs11_decrypt( pkcs11_context *ctx, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief Do a private RSA to sign a message digest + * + * \param ctx PKCS #11 context + * \param mode must be RSA_PRIVATE, for compatibility with rsa.c's signature + * \param md_alg a POLARSSL_MD_* (use POLARSSL_MD_NONE for signing raw data) + * \param hashlen message digest length (for POLARSSL_MD_NONE only) + * \param hash buffer holding the message digest + * \param sig buffer that will hold the ciphertext + * + * \return 0 if the signing operation was successful, + * or an POLARSSL_ERR_RSA_XXX error code + * + * \note The "sig" buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + */ +int pkcs11_sign( pkcs11_context *ctx, + int mode, + md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * SSL/TLS wrappers for PKCS#11 functions + */ +static inline int ssl_pkcs11_decrypt( void *ctx, int mode, size_t *olen, + const unsigned char *input, unsigned char *output, + size_t output_max_len ) +{ + return pkcs11_decrypt( (pkcs11_context *) ctx, mode, olen, input, output, + output_max_len ); +} + +static inline int ssl_pkcs11_sign( void *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + int mode, md_type_t md_alg, unsigned int hashlen, + const unsigned char *hash, unsigned char *sig ) +{ + ((void) f_rng); + ((void) p_rng); + return pkcs11_sign( (pkcs11_context *) ctx, mode, md_alg, + hashlen, hash, sig ); +} + +static inline size_t ssl_pkcs11_key_len( void *ctx ) +{ + return ( (pkcs11_context *) ctx )->len; +} + +#ifdef __cplusplus +} +#endif + +#endif /* POLARSSL_PKCS11_C */ + +#endif /* POLARSSL_PKCS11_H */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/pkcs12.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/pkcs12.h new file mode 100644 index 0000000..4bd5018 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/pkcs12.h @@ -0,0 +1,123 @@ +/** + * \file pkcs12.h + * + * \brief PKCS#12 Personal Information Exchange Syntax + * + * Copyright (C) 2006-2013, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_PKCS12_H +#define POLARSSL_PKCS12_H + +#include + +#include "md.h" +#include "cipher.h" +#include "asn1.h" + +#define POLARSSL_ERR_PKCS12_BAD_INPUT_DATA -0x1F80 /**< Bad input parameters to function. */ +#define POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE -0x1F00 /**< Feature not available, e.g. unsupported encryption scheme. */ +#define POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT -0x1E80 /**< PBE ASN.1 data not as expected. */ +#define POLARSSL_ERR_PKCS12_PASSWORD_MISMATCH -0x1E00 /**< Given private key password does not allow for correct decryption. */ + +#define PKCS12_DERIVE_KEY 1 /**< encryption/decryption key */ +#define PKCS12_DERIVE_IV 2 /**< initialization vector */ +#define PKCS12_DERIVE_MAC_KEY 3 /**< integrity / MAC key */ + +#define PKCS12_PBE_DECRYPT 0 +#define PKCS12_PBE_ENCRYPT 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief PKCS12 Password Based function (encryption / decryption) + * for pbeWithSHAAnd128BitRC4 + * + * \param pbe_params an ASN1 buffer containing the pkcs-12PbeParams structure + * \param mode either PKCS12_PBE_ENCRYPT or PKCS12_PBE_DECRYPT + * \param pwd the password used (may be NULL if no password is used) + * \param pwdlen length of the password (may be 0) + * \param input the input data + * \param len data length + * \param output the output buffer + * + * \return 0 if successful, or a PolarSSL error code + */ +int pkcs12_pbe_sha1_rc4_128( asn1_buf *pbe_params, int mode, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *input, size_t len, + unsigned char *output ); + +/** + * \brief PKCS12 Password Based function (encryption / decryption) + * for cipher-based and md-based PBE's + * + * \param pbe_params an ASN1 buffer containing the pkcs-12PbeParams structure + * \param mode either PKCS12_PBE_ENCRYPT or PKCS12_PBE_DECRYPT + * \param cipher_type the cipher used + * \param md_type the md used + * \param pwd the password used (may be NULL if no password is used) + * \param pwdlen length of the password (may be 0) + * \param input the input data + * \param len data length + * \param output the output buffer + * + * \return 0 if successful, or a PolarSSL error code + */ +int pkcs12_pbe( asn1_buf *pbe_params, int mode, + cipher_type_t cipher_type, md_type_t md_type, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *input, size_t len, + unsigned char *output ); + +/** + * \brief The PKCS#12 derivation function uses a password and a salt + * to produce pseudo-random bits for a particular "purpose". + * + * Depending on the given id, this function can produce an + * encryption/decryption key, an nitialization vector or an + * integrity key. + * + * \param data buffer to store the derived data in + * \param datalen length to fill + * \param pwd password to use (may be NULL if no password is used) + * \param pwdlen length of the password (may be 0) + * \param salt salt buffer to use + * \param saltlen length of the salt + * \param md md type to use during the derivation + * \param id id that describes the purpose (can be PKCS12_DERIVE_KEY, + * PKCS12_DERIVE_IV or PKCS12_DERIVE_MAC_KEY) + * \param iterations number of iterations + * + * \return 0 if successful, or a MD, BIGNUM type error. + */ +int pkcs12_derivation( unsigned char *data, size_t datalen, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *salt, size_t saltlen, + md_type_t md, int id, int iterations ); + +#ifdef __cplusplus +} +#endif + +#endif /* pkcs12.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/pkcs5.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/pkcs5.h new file mode 100644 index 0000000..34e824b --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/pkcs5.h @@ -0,0 +1,104 @@ +/** + * \file pkcs5.h + * + * \brief PKCS#5 functions + * + * \author Mathias Olsson + * + * Copyright (C) 2006-2013, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_PKCS5_H +#define POLARSSL_PKCS5_H + +#include + +#include "asn1.h" +#include "md.h" + +#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32) +#include +typedef UINT32 uint32_t; +#else +#include +#endif + +#define POLARSSL_ERR_PKCS5_BAD_INPUT_DATA -0x3f80 /**< Bad input parameters to function. */ +#define POLARSSL_ERR_PKCS5_INVALID_FORMAT -0x3f00 /**< Unexpected ASN.1 data. */ +#define POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE -0x3e80 /**< Requested encryption or digest alg not available. */ +#define POLARSSL_ERR_PKCS5_PASSWORD_MISMATCH -0x3e00 /**< Given private key password does not allow for correct decryption. */ + +#define PKCS5_DECRYPT 0 +#define PKCS5_ENCRYPT 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief PKCS#5 PBES2 function + * + * \param pbe_params the ASN.1 algorithm parameters + * \param mode either PKCS5_DECRYPT or PKCS5_ENCRYPT + * \param pwd password to use when generating key + * \param pwdlen length of password + * \param data data to process + * \param datalen length of data + * \param output output buffer + * + * \returns 0 on success, or a PolarSSL error code if verification fails. + */ +int pkcs5_pbes2( asn1_buf *pbe_params, int mode, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *data, size_t datalen, + unsigned char *output ); + +/** + * \brief PKCS#5 PBKDF2 using HMAC + * + * \param ctx Generic HMAC context + * \param password Password to use when generating key + * \param plen Length of password + * \param salt Salt to use when generating key + * \param slen Length of salt + * \param iteration_count Iteration count + * \param key_length Length of generated key + * \param output Generated key. Must be at least as big as key_length + * + * \returns 0 on success, or a PolarSSL error code if verification fails. + */ +int pkcs5_pbkdf2_hmac( md_context_t *ctx, const unsigned char *password, + size_t plen, const unsigned char *salt, size_t slen, + unsigned int iteration_count, + uint32_t key_length, unsigned char *output ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int pkcs5_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* pkcs5.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/platform.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/platform.h new file mode 100644 index 0000000..eae887a --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/platform.h @@ -0,0 +1,128 @@ +/** + * \file platform.h + * + * \brief PolarSSL Platform abstraction layer + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_PLATFORM_H +#define POLARSSL_PLATFORM_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(POLARSSL_PLATFORM_NO_STD_FUNCTIONS) +#include +#if !defined(POLARSSL_PLATFORM_STD_PRINTF) +#define POLARSSL_PLATFORM_STD_PRINTF printf /**< Default printf to use */ +#endif +#if !defined(POLARSSL_PLATFORM_STD_FPRINTF) +#define POLARSSL_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use */ +#endif +#if !defined(POLARSSL_PLATFORM_STD_MALLOC) +#define POLARSSL_PLATFORM_STD_MALLOC malloc /**< Default allocator to use */ +#endif +#if !defined(POLARSSL_PLATFORM_STD_FREE) +#define POLARSSL_PLATFORM_STD_FREE free /**< Default free to use */ +#endif +#else /* POLARSSL_PLATFORM_NO_STD_FUNCTIONS */ +#if defined(POLARSSL_PLATFORM_STD_MEM_HDR) +#include POLARSSL_PLATFORM_STD_MEM_HDR +#endif +#endif /* POLARSSL_PLATFORM_NO_STD_FUNCTIONS */ + +/* \} name SECTION: Module settings */ + +/* + * The function pointers for malloc and free + */ +#if defined(POLARSSL_PLATFORM_MEMORY) +extern void * (*polarssl_malloc)( size_t len ); +extern void (*polarssl_free)( void *ptr ); + +/** + * \brief Set your own memory implementation function pointers + * + * \param malloc_func the malloc function implementation + * \param free_func the free function implementation + * + * \return 0 if successful + */ +int platform_set_malloc_free( void * (*malloc_func)( size_t ), + void (*free_func)( void * ) ); +#else /* POLARSSL_PLATFORM_ENTROPY */ +#define polarssl_malloc malloc +#define polarssl_free free +#endif /* POLARSSL_PLATFORM_ENTROPY */ + +/* + * The function pointers for printf + */ +#if defined(POLARSSL_PLATFORM_PRINTF_ALT) +extern int (*polarssl_printf)( const char *format, ... ); + +/** + * \brief Set your own printf function pointer + * + * \param printf_func the printf function implementation + * + * \return 0 + */ +int platform_set_printf( int (*printf_func)( const char *, ... ) ); +#else /* POLARSSL_PLATFORM_PRINTF_ALT */ +#define polarssl_printf printf +#endif /* POLARSSL_PLATFORM_PRINTF_ALT */ + +/* + * The function pointers for fprintf + */ +#if defined(POLARSSL_PLATFORM_FPRINTF_ALT) +extern int (*polarssl_fprintf)( FILE *stream, const char *format, ... ); + +int platform_set_fprintf( int (*fprintf_func)( FILE *stream, const char *, + ... ) ); +#else +#define polarssl_fprintf fprintf +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* platform.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/ripemd160.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/ripemd160.h new file mode 100644 index 0000000..e3b66c9 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/ripemd160.h @@ -0,0 +1,204 @@ +/** + * \file ripemd160.h + * + * \brief RIPE MD-160 message digest + * + * Copyright (C) 2014-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_RIPEMD160_H +#define POLARSSL_RIPEMD160_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include + +#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32) +#include +typedef UINT32 uint32_t; +#else +#include +#endif + +#define POLARSSL_ERR_RIPEMD160_FILE_IO_ERROR -0x007E /**< Read/write error in file. */ + +#if !defined(POLARSSL_RIPEMD160_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief RIPEMD-160 context structure + */ +typedef struct +{ + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[5]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ + + unsigned char ipad[64]; /*!< HMAC: inner padding */ + unsigned char opad[64]; /*!< HMAC: outer padding */ +} +ripemd160_context; + +/** + * \brief Initialize RIPEMD-160 context + * + * \param ctx RIPEMD-160 context to be initialized + */ +void ripemd160_init( ripemd160_context *ctx ); + +/** + * \brief Clear RIPEMD-160 context + * + * \param ctx RIPEMD-160 context to be cleared + */ +void ripemd160_free( ripemd160_context *ctx ); + +/** + * \brief RIPEMD-160 context setup + * + * \param ctx context to be initialized + */ +void ripemd160_starts( ripemd160_context *ctx ); + +/** + * \brief RIPEMD-160 process buffer + * + * \param ctx RIPEMD-160 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void ripemd160_update( ripemd160_context *ctx, + const unsigned char *input, size_t ilen ); + +/** + * \brief RIPEMD-160 final digest + * + * \param ctx RIPEMD-160 context + * \param output RIPEMD-160 checksum result + */ +void ripemd160_finish( ripemd160_context *ctx, unsigned char output[20] ); + +/* Internal use */ +void ripemd160_process( ripemd160_context *ctx, const unsigned char data[64] ); + +#ifdef __cplusplus +} +#endif + +#else /* POLARSSL_RIPEMD160_ALT */ +#include "ripemd160.h" +#endif /* POLARSSL_RIPEMD160_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Output = RIPEMD-160( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output RIPEMD-160 checksum result + */ +void ripemd160( const unsigned char *input, size_t ilen, + unsigned char output[20] ); + +#if defined(POLARSSL_FS_IO) +/** + * \brief Output = RIPEMD-160( file contents ) + * + * \param path input file name + * \param output RIPEMD-160 checksum result + * + * \return 0 if successful, or POLARSSL_ERR_RIPEMD160_FILE_IO_ERROR + */ +int ripemd160_file( const char *path, unsigned char output[20] ); +#endif /* POLARSSL_FS_IO */ + +/** + * \brief RIPEMD-160 HMAC context setup + * + * \param ctx HMAC context to be initialized + * \param key HMAC secret key + * \param keylen length of the HMAC key + */ +void ripemd160_hmac_starts( ripemd160_context *ctx, + const unsigned char *key, size_t keylen ); + +/** + * \brief RIPEMD-160 HMAC process buffer + * + * \param ctx HMAC context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void ripemd160_hmac_update( ripemd160_context *ctx, + const unsigned char *input, size_t ilen ); + +/** + * \brief RIPEMD-160 HMAC final digest + * + * \param ctx HMAC context + * \param output RIPEMD-160 HMAC checksum result + */ +void ripemd160_hmac_finish( ripemd160_context *ctx, unsigned char output[20] ); + +/** + * \brief RIPEMD-160 HMAC context reset + * + * \param ctx HMAC context to be reset + */ +void ripemd160_hmac_reset( ripemd160_context *ctx ); + +/** + * \brief Output = HMAC-RIPEMD-160( hmac key, input buffer ) + * + * \param key HMAC secret key + * \param keylen length of the HMAC key + * \param input buffer holding the data + * \param ilen length of the input data + * \param output HMAC-RIPEMD-160 result + */ +void ripemd160_hmac( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char output[20] ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int ripemd160_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* ripemd160.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/rsa.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/rsa.h new file mode 100644 index 0000000..c06c7d5 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/rsa.h @@ -0,0 +1,647 @@ +/** + * \file rsa.h + * + * \brief The RSA public-key cryptosystem + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_RSA_H +#define POLARSSL_RSA_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include "bignum.h" +#include "md.h" + +#if defined(POLARSSL_THREADING_C) +#include "threading.h" +#endif + +/* + * RSA Error codes + */ +#define POLARSSL_ERR_RSA_BAD_INPUT_DATA -0x4080 /**< Bad input parameters to function. */ +#define POLARSSL_ERR_RSA_INVALID_PADDING -0x4100 /**< Input data contains invalid padding and is rejected. */ +#define POLARSSL_ERR_RSA_KEY_GEN_FAILED -0x4180 /**< Something failed during generation of a key. */ +#define POLARSSL_ERR_RSA_KEY_CHECK_FAILED -0x4200 /**< Key failed to pass the libraries validity check. */ +#define POLARSSL_ERR_RSA_PUBLIC_FAILED -0x4280 /**< The public key operation failed. */ +#define POLARSSL_ERR_RSA_PRIVATE_FAILED -0x4300 /**< The private key operation failed. */ +#define POLARSSL_ERR_RSA_VERIFY_FAILED -0x4380 /**< The PKCS#1 verification failed. */ +#define POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE -0x4400 /**< The output buffer for decryption is not large enough. */ +#define POLARSSL_ERR_RSA_RNG_FAILED -0x4480 /**< The random generator failed to generate non-zeros. */ + +/* + * RSA constants + */ +#define RSA_PUBLIC 0 +#define RSA_PRIVATE 1 + +#define RSA_PKCS_V15 0 +#define RSA_PKCS_V21 1 + +#define RSA_SIGN 1 +#define RSA_CRYPT 2 + +#define RSA_SALT_LEN_ANY -1 + +/* + * The above constants may be used even if the RSA module is compile out, + * eg for alternative (PKCS#11) RSA implemenations in the PK layers. + */ +#if defined(POLARSSL_RSA_C) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief RSA context structure + */ +typedef struct +{ + int ver; /*!< always 0 */ + size_t len; /*!< size(N) in chars */ + + mpi N; /*!< public modulus */ + mpi E; /*!< public exponent */ + + mpi D; /*!< private exponent */ + mpi P; /*!< 1st prime factor */ + mpi Q; /*!< 2nd prime factor */ + mpi DP; /*!< D % (P - 1) */ + mpi DQ; /*!< D % (Q - 1) */ + mpi QP; /*!< 1 / (Q % P) */ + + mpi RN; /*!< cached R^2 mod N */ + mpi RP; /*!< cached R^2 mod P */ + mpi RQ; /*!< cached R^2 mod Q */ + +#if !defined(POLARSSL_RSA_NO_CRT) + mpi Vi; /*!< cached blinding value */ + mpi Vf; /*!< cached un-blinding value */ +#endif + + int padding; /*!< RSA_PKCS_V15 for 1.5 padding and + RSA_PKCS_v21 for OAEP/PSS */ + int hash_id; /*!< Hash identifier of md_type_t as + specified in the md.h header file + for the EME-OAEP and EMSA-PSS + encoding */ +#if defined(POLARSSL_THREADING_C) + threading_mutex_t mutex; /*!< Thread-safety mutex */ +#endif +} +rsa_context; + +/** + * \brief Initialize an RSA context + * + * Note: Set padding to RSA_PKCS_V21 for the RSAES-OAEP + * encryption scheme and the RSASSA-PSS signature scheme. + * + * \param ctx RSA context to be initialized + * \param padding RSA_PKCS_V15 or RSA_PKCS_V21 + * \param hash_id RSA_PKCS_V21 hash identifier + * + * \note The hash_id parameter is actually ignored + * when using RSA_PKCS_V15 padding. + * + * \note Choice of padding mode is strictly enforced for private key + * operations, since there might be security concerns in + * mixing padding modes. For public key operations it's merely + * a default value, which can be overriden by calling specific + * rsa_rsaes_xxx or rsa_rsassa_xxx functions. + * + * \note The chosen hash is always used for OEAP encryption. + * For PSS signatures, it's always used for making signatures, + * but can be overriden (and always is, if set to + * POLARSSL_MD_NONE) for verifying them. + */ +void rsa_init( rsa_context *ctx, + int padding, + int hash_id); + +/** + * \brief Set padding for an already initialized RSA context + * See \c rsa_init() for details. + * + * \param ctx RSA context to be set + * \param padding RSA_PKCS_V15 or RSA_PKCS_V21 + * \param hash_id RSA_PKCS_V21 hash identifier + */ +void rsa_set_padding( rsa_context *ctx, int padding, int hash_id); + +/** + * \brief Generate an RSA keypair + * + * \param ctx RSA context that will hold the key + * \param f_rng RNG function + * \param p_rng RNG parameter + * \param nbits size of the public key in bits + * \param exponent public exponent (e.g., 65537) + * + * \note rsa_init() must be called beforehand to setup + * the RSA context. + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + */ +int rsa_gen_key( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + unsigned int nbits, int exponent ); + +/** + * \brief Check a public RSA key + * + * \param ctx RSA context to be checked + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + */ +int rsa_check_pubkey( const rsa_context *ctx ); + +/** + * \brief Check a private RSA key + * + * \param ctx RSA context to be checked + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + */ +int rsa_check_privkey( const rsa_context *ctx ); + +/** + * \brief Do an RSA public key operation + * + * \param ctx RSA context + * \param input input buffer + * \param output output buffer + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + * + * \note This function does NOT take care of message + * padding. Also, be sure to set input[0] = 0 or assure that + * input is smaller than N. + * + * \note The input and output buffers must be large + * enough (eg. 128 bytes if RSA-1024 is used). + */ +int rsa_public( rsa_context *ctx, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief Do an RSA private key operation + * + * \param ctx RSA context + * \param f_rng RNG function (Needed for blinding) + * \param p_rng RNG parameter + * \param input input buffer + * \param output output buffer + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + * + * \note The input and output buffers must be large + * enough (eg. 128 bytes if RSA-1024 is used). + */ +int rsa_private( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief Generic wrapper to perform a PKCS#1 encryption using the + * mode from the context. Add the message padding, then do an + * RSA operation. + * + * \param ctx RSA context + * \param f_rng RNG function (Needed for padding and PKCS#1 v2.1 encoding + * and RSA_PRIVATE) + * \param p_rng RNG parameter + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param ilen contains the plaintext length + * \param input buffer holding the data to be encrypted + * \param output buffer that will hold the ciphertext + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + * + * \note The output buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + */ +int rsa_pkcs1_encrypt( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t ilen, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief Perform a PKCS#1 v1.5 encryption (RSAES-PKCS1-v1_5-ENCRYPT) + * + * \param ctx RSA context + * \param f_rng RNG function (Needed for padding and RSA_PRIVATE) + * \param p_rng RNG parameter + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param ilen contains the plaintext length + * \param input buffer holding the data to be encrypted + * \param output buffer that will hold the ciphertext + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + * + * \note The output buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + */ +int rsa_rsaes_pkcs1_v15_encrypt( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t ilen, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief Perform a PKCS#1 v2.1 OAEP encryption (RSAES-OAEP-ENCRYPT) + * + * \param ctx RSA context + * \param f_rng RNG function (Needed for padding and PKCS#1 v2.1 encoding + * and RSA_PRIVATE) + * \param p_rng RNG parameter + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param label buffer holding the custom label to use + * \param label_len contains the label length + * \param ilen contains the plaintext length + * \param input buffer holding the data to be encrypted + * \param output buffer that will hold the ciphertext + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + * + * \note The output buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + */ +int rsa_rsaes_oaep_encrypt( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + const unsigned char *label, size_t label_len, + size_t ilen, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief Generic wrapper to perform a PKCS#1 decryption using the + * mode from the context. Do an RSA operation, then remove + * the message padding + * + * \param ctx RSA context + * \param f_rng RNG function (Only needed for RSA_PRIVATE) + * \param p_rng RNG parameter + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param olen will contain the plaintext length + * \param input buffer holding the encrypted data + * \param output buffer that will hold the plaintext + * \param output_max_len maximum length of the output buffer + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + * + * \note The output buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise + * an error is thrown. + */ +int rsa_pkcs1_decrypt( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief Perform a PKCS#1 v1.5 decryption (RSAES-PKCS1-v1_5-DECRYPT) + * + * \param ctx RSA context + * \param f_rng RNG function (Only needed for RSA_PRIVATE) + * \param p_rng RNG parameter + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param olen will contain the plaintext length + * \param input buffer holding the encrypted data + * \param output buffer that will hold the plaintext + * \param output_max_len maximum length of the output buffer + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + * + * \note The output buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise + * an error is thrown. + */ +int rsa_rsaes_pkcs1_v15_decrypt( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief Perform a PKCS#1 v2.1 OAEP decryption (RSAES-OAEP-DECRYPT) + * + * \param ctx RSA context + * \param f_rng RNG function (Only needed for RSA_PRIVATE) + * \param p_rng RNG parameter + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param label buffer holding the custom label to use + * \param label_len contains the label length + * \param olen will contain the plaintext length + * \param input buffer holding the encrypted data + * \param output buffer that will hold the plaintext + * \param output_max_len maximum length of the output buffer + * + * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code + * + * \note The output buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise + * an error is thrown. + */ +int rsa_rsaes_oaep_decrypt( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + const unsigned char *label, size_t label_len, + size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief Generic wrapper to perform a PKCS#1 signature using the + * mode from the context. Do a private RSA operation to sign + * a message digest + * + * \param ctx RSA context + * \param f_rng RNG function (Needed for PKCS#1 v2.1 encoding and for + * RSA_PRIVATE) + * \param p_rng RNG parameter + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param md_alg a POLARSSL_MD_* (use POLARSSL_MD_NONE for signing raw data) + * \param hashlen message digest length (for POLARSSL_MD_NONE only) + * \param hash buffer holding the message digest + * \param sig buffer that will hold the ciphertext + * + * \return 0 if the signing operation was successful, + * or an POLARSSL_ERR_RSA_XXX error code + * + * \note The "sig" buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + * + * \note In case of PKCS#1 v2.1 encoding, see comments on + * \note \c rsa_rsassa_pss_sign() for details on md_alg and hash_id. + */ +int rsa_pkcs1_sign( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * \brief Perform a PKCS#1 v1.5 signature (RSASSA-PKCS1-v1_5-SIGN) + * + * \param ctx RSA context + * \param f_rng RNG function (Only needed for RSA_PRIVATE) + * \param p_rng RNG parameter + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param md_alg a POLARSSL_MD_* (use POLARSSL_MD_NONE for signing raw data) + * \param hashlen message digest length (for POLARSSL_MD_NONE only) + * \param hash buffer holding the message digest + * \param sig buffer that will hold the ciphertext + * + * \return 0 if the signing operation was successful, + * or an POLARSSL_ERR_RSA_XXX error code + * + * \note The "sig" buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + */ +int rsa_rsassa_pkcs1_v15_sign( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * \brief Perform a PKCS#1 v2.1 PSS signature (RSASSA-PSS-SIGN) + * + * \param ctx RSA context + * \param f_rng RNG function (Needed for PKCS#1 v2.1 encoding and for + * RSA_PRIVATE) + * \param p_rng RNG parameter + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param md_alg a POLARSSL_MD_* (use POLARSSL_MD_NONE for signing raw data) + * \param hashlen message digest length (for POLARSSL_MD_NONE only) + * \param hash buffer holding the message digest + * \param sig buffer that will hold the ciphertext + * + * \return 0 if the signing operation was successful, + * or an POLARSSL_ERR_RSA_XXX error code + * + * \note The "sig" buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + * + * \note The hash_id in the RSA context is the one used for the + * encoding. md_alg in the function call is the type of hash + * that is encoded. According to RFC 3447 it is advised to + * keep both hashes the same. + */ +int rsa_rsassa_pss_sign( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * \brief Generic wrapper to perform a PKCS#1 verification using the + * mode from the context. Do a public RSA operation and check + * the message digest + * + * \param ctx points to an RSA public key + * \param f_rng RNG function (Only needed for RSA_PRIVATE) + * \param p_rng RNG parameter + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param md_alg a POLARSSL_MD_* (use POLARSSL_MD_NONE for signing raw data) + * \param hashlen message digest length (for POLARSSL_MD_NONE only) + * \param hash buffer holding the message digest + * \param sig buffer holding the ciphertext + * + * \return 0 if the verify operation was successful, + * or an POLARSSL_ERR_RSA_XXX error code + * + * \note The "sig" buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + * + * \note In case of PKCS#1 v2.1 encoding, see comments on + * \c rsa_rsassa_pss_verify() about md_alg and hash_id. + */ +int rsa_pkcs1_verify( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ); + +/** + * \brief Perform a PKCS#1 v1.5 verification (RSASSA-PKCS1-v1_5-VERIFY) + * + * \param ctx points to an RSA public key + * \param f_rng RNG function (Only needed for RSA_PRIVATE) + * \param p_rng RNG parameter + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param md_alg a POLARSSL_MD_* (use POLARSSL_MD_NONE for signing raw data) + * \param hashlen message digest length (for POLARSSL_MD_NONE only) + * \param hash buffer holding the message digest + * \param sig buffer holding the ciphertext + * + * \return 0 if the verify operation was successful, + * or an POLARSSL_ERR_RSA_XXX error code + * + * \note The "sig" buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + */ +int rsa_rsassa_pkcs1_v15_verify( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ); + +/** + * \brief Perform a PKCS#1 v2.1 PSS verification (RSASSA-PSS-VERIFY) + * (This is the "simple" version.) + * + * \param ctx points to an RSA public key + * \param f_rng RNG function (Only needed for RSA_PRIVATE) + * \param p_rng RNG parameter + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param md_alg a POLARSSL_MD_* (use POLARSSL_MD_NONE for signing raw data) + * \param hashlen message digest length (for POLARSSL_MD_NONE only) + * \param hash buffer holding the message digest + * \param sig buffer holding the ciphertext + * + * \return 0 if the verify operation was successful, + * or an POLARSSL_ERR_RSA_XXX error code + * + * \note The "sig" buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + * + * \note The hash_id in the RSA context is the one used for the + * verification. md_alg in the function call is the type of + * hash that is verified. According to RFC 3447 it is advised to + * keep both hashes the same. If hash_id in the RSA context is + * unset, the md_alg from the function call is used. + */ +int rsa_rsassa_pss_verify( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ); + +/** + * \brief Perform a PKCS#1 v2.1 PSS verification (RSASSA-PSS-VERIFY) + * (This is the version with "full" options.) + * + * \param ctx points to an RSA public key + * \param f_rng RNG function (Only needed for RSA_PRIVATE) + * \param p_rng RNG parameter + * \param mode RSA_PUBLIC or RSA_PRIVATE + * \param md_alg a POLARSSL_MD_* (use POLARSSL_MD_NONE for signing raw data) + * \param hashlen message digest length (for POLARSSL_MD_NONE only) + * \param hash buffer holding the message digest + * \param mgf1_hash_id message digest used for mask generation + * \param expected_salt_len Length of the salt used in padding, use + * RSA_SALT_LEN_ANY to accept any salt length + * \param sig buffer holding the ciphertext + * + * \return 0 if the verify operation was successful, + * or an POLARSSL_ERR_RSA_XXX error code + * + * \note The "sig" buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + * + * \note The hash_id in the RSA context is ignored. + */ +int rsa_rsassa_pss_verify_ext( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + md_type_t mgf1_hash_id, + int expected_salt_len, + const unsigned char *sig ); + +/** + * \brief Copy the components of an RSA context + * + * \param dst Destination context + * \param src Source context + * + * \return O on success, + * POLARSSL_ERR_MPI_MALLOC_FAILED on memory allocation failure + */ +int rsa_copy( rsa_context *dst, const rsa_context *src ); + +/** + * \brief Free the components of an RSA key + * + * \param ctx RSA Context to free + */ +void rsa_free( rsa_context *ctx ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int rsa_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* POLARSSL_RSA_C */ + +#endif /* rsa.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/sha1.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/sha1.h new file mode 100644 index 0000000..cb0c436 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/sha1.h @@ -0,0 +1,200 @@ +/** + * \file sha1.h + * + * \brief SHA-1 cryptographic hash function + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_SHA1_H +#define POLARSSL_SHA1_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include + +#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32) +#include +typedef UINT32 uint32_t; +#else +#include +#endif + +#define POLARSSL_ERR_SHA1_FILE_IO_ERROR -0x0076 /**< Read/write error in file. */ + +#if !defined(POLARSSL_SHA1_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief SHA-1 context structure + */ +typedef struct +{ + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[5]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ + + unsigned char ipad[64]; /*!< HMAC: inner padding */ + unsigned char opad[64]; /*!< HMAC: outer padding */ +} +sha1_context; + +/** + * \brief Initialize SHA-1 context + * + * \param ctx SHA-1 context to be initialized + */ +void sha1_init( sha1_context *ctx ); + +/** + * \brief Clear SHA-1 context + * + * \param ctx SHA-1 context to be cleared + */ +void sha1_free( sha1_context *ctx ); + +/** + * \brief SHA-1 context setup + * + * \param ctx context to be initialized + */ +void sha1_starts( sha1_context *ctx ); + +/** + * \brief SHA-1 process buffer + * + * \param ctx SHA-1 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen ); + +/** + * \brief SHA-1 final digest + * + * \param ctx SHA-1 context + * \param output SHA-1 checksum result + */ +void sha1_finish( sha1_context *ctx, unsigned char output[20] ); + +/* Internal use */ +void sha1_process( sha1_context *ctx, const unsigned char data[64] ); + +#ifdef __cplusplus +} +#endif + +#else /* POLARSSL_SHA1_ALT */ +#include "sha1_alt.h" +#endif /* POLARSSL_SHA1_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Output = SHA-1( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output SHA-1 checksum result + */ +void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] ); + +/** + * \brief Output = SHA-1( file contents ) + * + * \param path input file name + * \param output SHA-1 checksum result + * + * \return 0 if successful, or POLARSSL_ERR_SHA1_FILE_IO_ERROR + */ +int sha1_file( const char *path, unsigned char output[20] ); + +/** + * \brief SHA-1 HMAC context setup + * + * \param ctx HMAC context to be initialized + * \param key HMAC secret key + * \param keylen length of the HMAC key + */ +void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key, + size_t keylen ); + +/** + * \brief SHA-1 HMAC process buffer + * + * \param ctx HMAC context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void sha1_hmac_update( sha1_context *ctx, const unsigned char *input, + size_t ilen ); + +/** + * \brief SHA-1 HMAC final digest + * + * \param ctx HMAC context + * \param output SHA-1 HMAC checksum result + */ +void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] ); + +/** + * \brief SHA-1 HMAC context reset + * + * \param ctx HMAC context to be reset + */ +void sha1_hmac_reset( sha1_context *ctx ); + +/** + * \brief Output = HMAC-SHA-1( hmac key, input buffer ) + * + * \param key HMAC secret key + * \param keylen length of the HMAC key + * \param input buffer holding the data + * \param ilen length of the input data + * \param output HMAC-SHA-1 result + */ +void sha1_hmac( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char output[20] ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int sha1_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* sha1.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/sha256.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/sha256.h new file mode 100644 index 0000000..b143674 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/sha256.h @@ -0,0 +1,208 @@ +/** + * \file sha256.h + * + * \brief SHA-224 and SHA-256 cryptographic hash function + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_SHA256_H +#define POLARSSL_SHA256_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include + +#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32) +#include +typedef UINT32 uint32_t; +#else +#include +#endif + +#define POLARSSL_ERR_SHA256_FILE_IO_ERROR -0x0078 /**< Read/write error in file. */ + +#if !defined(POLARSSL_SHA256_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief SHA-256 context structure + */ +typedef struct +{ + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[8]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ + + unsigned char ipad[64]; /*!< HMAC: inner padding */ + unsigned char opad[64]; /*!< HMAC: outer padding */ + int is224; /*!< 0 => SHA-256, else SHA-224 */ +} +sha256_context; + +/** + * \brief Initialize SHA-256 context + * + * \param ctx SHA-256 context to be initialized + */ +void sha256_init( sha256_context *ctx ); + +/** + * \brief Clear SHA-256 context + * + * \param ctx SHA-256 context to be cleared + */ +void sha256_free( sha256_context *ctx ); + +/** + * \brief SHA-256 context setup + * + * \param ctx context to be initialized + * \param is224 0 = use SHA256, 1 = use SHA224 + */ +void sha256_starts( sha256_context *ctx, int is224 ); + +/** + * \brief SHA-256 process buffer + * + * \param ctx SHA-256 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void sha256_update( sha256_context *ctx, const unsigned char *input, + size_t ilen ); + +/** + * \brief SHA-256 final digest + * + * \param ctx SHA-256 context + * \param output SHA-224/256 checksum result + */ +void sha256_finish( sha256_context *ctx, unsigned char output[32] ); + +/* Internal use */ +void sha256_process( sha256_context *ctx, const unsigned char data[64] ); + +#ifdef __cplusplus +} +#endif + +#else /* POLARSSL_SHA256_ALT */ +#include "sha256_alt.h" +#endif /* POLARSSL_SHA256_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Output = SHA-256( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output SHA-224/256 checksum result + * \param is224 0 = use SHA256, 1 = use SHA224 + */ +void sha256( const unsigned char *input, size_t ilen, + unsigned char output[32], int is224 ); + +/** + * \brief Output = SHA-256( file contents ) + * + * \param path input file name + * \param output SHA-224/256 checksum result + * \param is224 0 = use SHA256, 1 = use SHA224 + * + * \return 0 if successful, or POLARSSL_ERR_SHA256_FILE_IO_ERROR + */ +int sha256_file( const char *path, unsigned char output[32], int is224 ); + +/** + * \brief SHA-256 HMAC context setup + * + * \param ctx HMAC context to be initialized + * \param key HMAC secret key + * \param keylen length of the HMAC key + * \param is224 0 = use SHA256, 1 = use SHA224 + */ +void sha256_hmac_starts( sha256_context *ctx, const unsigned char *key, + size_t keylen, int is224 ); + +/** + * \brief SHA-256 HMAC process buffer + * + * \param ctx HMAC context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void sha256_hmac_update( sha256_context *ctx, const unsigned char *input, + size_t ilen ); + +/** + * \brief SHA-256 HMAC final digest + * + * \param ctx HMAC context + * \param output SHA-224/256 HMAC checksum result + */ +void sha256_hmac_finish( sha256_context *ctx, unsigned char output[32] ); + +/** + * \brief SHA-256 HMAC context reset + * + * \param ctx HMAC context to be reset + */ +void sha256_hmac_reset( sha256_context *ctx ); + +/** + * \brief Output = HMAC-SHA-256( hmac key, input buffer ) + * + * \param key HMAC secret key + * \param keylen length of the HMAC key + * \param input buffer holding the data + * \param ilen length of the input data + * \param output HMAC-SHA-224/256 result + * \param is224 0 = use SHA256, 1 = use SHA224 + */ +void sha256_hmac( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char output[32], int is224 ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int sha256_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* sha256.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/sha512.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/sha512.h new file mode 100644 index 0000000..dfbae4a --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/sha512.h @@ -0,0 +1,209 @@ +/** + * \file sha512.h + * + * \brief SHA-384 and SHA-512 cryptographic hash function + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_SHA512_H +#define POLARSSL_SHA512_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include + +#if defined(_MSC_VER) || defined(__WATCOMC__) + #define UL64(x) x##ui64 + typedef unsigned __int64 uint64_t; +#else + #include + #define UL64(x) x##ULL +#endif + +#define POLARSSL_ERR_SHA512_FILE_IO_ERROR -0x007A /**< Read/write error in file. */ + +#if !defined(POLARSSL_SHA512_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief SHA-512 context structure + */ +typedef struct +{ + uint64_t total[2]; /*!< number of bytes processed */ + uint64_t state[8]; /*!< intermediate digest state */ + unsigned char buffer[128]; /*!< data block being processed */ + + unsigned char ipad[128]; /*!< HMAC: inner padding */ + unsigned char opad[128]; /*!< HMAC: outer padding */ + int is384; /*!< 0 => SHA-512, else SHA-384 */ +} +sha512_context; + +/** + * \brief Initialize SHA-512 context + * + * \param ctx SHA-512 context to be initialized + */ +void sha512_init( sha512_context *ctx ); + +/** + * \brief Clear SHA-512 context + * + * \param ctx SHA-512 context to be cleared + */ +void sha512_free( sha512_context *ctx ); + +/** + * \brief SHA-512 context setup + * + * \param ctx context to be initialized + * \param is384 0 = use SHA512, 1 = use SHA384 + */ +void sha512_starts( sha512_context *ctx, int is384 ); + +/** + * \brief SHA-512 process buffer + * + * \param ctx SHA-512 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void sha512_update( sha512_context *ctx, const unsigned char *input, + size_t ilen ); + +/** + * \brief SHA-512 final digest + * + * \param ctx SHA-512 context + * \param output SHA-384/512 checksum result + */ +void sha512_finish( sha512_context *ctx, unsigned char output[64] ); + +#ifdef __cplusplus +} +#endif + +#else /* POLARSSL_SHA512_ALT */ +#include "sha512_alt.h" +#endif /* POLARSSL_SHA512_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Output = SHA-512( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output SHA-384/512 checksum result + * \param is384 0 = use SHA512, 1 = use SHA384 + */ +void sha512( const unsigned char *input, size_t ilen, + unsigned char output[64], int is384 ); + +/** + * \brief Output = SHA-512( file contents ) + * + * \param path input file name + * \param output SHA-384/512 checksum result + * \param is384 0 = use SHA512, 1 = use SHA384 + * + * \return 0 if successful, or POLARSSL_ERR_SHA512_FILE_IO_ERROR + */ +int sha512_file( const char *path, unsigned char output[64], int is384 ); + +/** + * \brief SHA-512 HMAC context setup + * + * \param ctx HMAC context to be initialized + * \param is384 0 = use SHA512, 1 = use SHA384 + * \param key HMAC secret key + * \param keylen length of the HMAC key + */ +void sha512_hmac_starts( sha512_context *ctx, const unsigned char *key, + size_t keylen, int is384 ); + +/** + * \brief SHA-512 HMAC process buffer + * + * \param ctx HMAC context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void sha512_hmac_update( sha512_context *ctx, const unsigned char *input, + size_t ilen ); + +/** + * \brief SHA-512 HMAC final digest + * + * \param ctx HMAC context + * \param output SHA-384/512 HMAC checksum result + */ +void sha512_hmac_finish( sha512_context *ctx, unsigned char output[64] ); + +/** + * \brief SHA-512 HMAC context reset + * + * \param ctx HMAC context to be reset + */ +void sha512_hmac_reset( sha512_context *ctx ); + +/** + * \brief Output = HMAC-SHA-512( hmac key, input buffer ) + * + * \param key HMAC secret key + * \param keylen length of the HMAC key + * \param input buffer holding the data + * \param ilen length of the input data + * \param output HMAC-SHA-384/512 result + * \param is384 0 = use SHA512, 1 = use SHA384 + */ +void sha512_hmac( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char output[64], int is384 ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int sha512_self_test( int verbose ); + +/* Internal use */ +void sha512_process( sha512_context *ctx, const unsigned char data[128] ); + +#ifdef __cplusplus +} +#endif + +#endif /* sha512.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/ssl.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/ssl.h new file mode 100644 index 0000000..bd7f1f7 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/ssl.h @@ -0,0 +1,1809 @@ +/** + * \file ssl.h + * + * \brief SSL/TLS functions. + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_SSL_H +#define POLARSSL_SSL_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif +#include "net.h" +#include "bignum.h" +#include "ecp.h" + +#include "ssl_ciphersuites.h" + +#if defined(POLARSSL_MD5_C) +#include "md5.h" +#endif + +#if defined(POLARSSL_SHA1_C) +#include "sha1.h" +#endif + +#if defined(POLARSSL_SHA256_C) +#include "sha256.h" +#endif + +#if defined(POLARSSL_SHA512_C) +#include "sha512.h" +#endif + +// for session tickets +#if defined(POLARSSL_AES_C) +#include "aes.h" +#endif + +#if defined(POLARSSL_X509_CRT_PARSE_C) +#include "x509_crt.h" +#include "x509_crl.h" +#endif + +#if defined(POLARSSL_DHM_C) +#include "dhm.h" +#endif + +#if defined(POLARSSL_ECDH_C) +#include "ecdh.h" +#endif + +#if defined(POLARSSL_ZLIB_SUPPORT) +#include "zlib.h" +#endif + +#if defined(POLARSSL_HAVE_TIME) +#include +#endif + +/* For convenience below and in programs */ +#if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#define POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED +#endif + +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#define POLARSSL_KEY_EXCHANGE__SOME__ECDHE_ENABLED +#endif + +#if defined(_MSC_VER) && !defined(inline) +#define inline _inline +#else +#if defined(__ARMCC_VERSION) && !defined(inline) +#define inline __inline +#endif /* __ARMCC_VERSION */ +#endif /*_MSC_VER */ + +/* + * SSL Error codes + */ +#define POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE -0x7080 /**< The requested feature is not available. */ +#define POLARSSL_ERR_SSL_BAD_INPUT_DATA -0x7100 /**< Bad input parameters to function. */ +#define POLARSSL_ERR_SSL_INVALID_MAC -0x7180 /**< Verification of the message MAC failed. */ +#define POLARSSL_ERR_SSL_INVALID_RECORD -0x7200 /**< An invalid SSL record was received. */ +#define POLARSSL_ERR_SSL_CONN_EOF -0x7280 /**< The connection indicated an EOF. */ +#define POLARSSL_ERR_SSL_UNKNOWN_CIPHER -0x7300 /**< An unknown cipher was received. */ +#define POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN -0x7380 /**< The server has no ciphersuites in common with the client. */ +#define POLARSSL_ERR_SSL_NO_RNG -0x7400 /**< No RNG was provided to the SSL module. */ +#define POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE -0x7480 /**< No client certification received from the client, but required by the authentication mode. */ +#define POLARSSL_ERR_SSL_CERTIFICATE_TOO_LARGE -0x7500 /**< Our own certificate(s) is/are too large to send in an SSL message.*/ +#define POLARSSL_ERR_SSL_CERTIFICATE_REQUIRED -0x7580 /**< The own certificate is not set, but needed by the server. */ +#define POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED -0x7600 /**< The own private key or pre-shared key is not set, but needed. */ +#define POLARSSL_ERR_SSL_CA_CHAIN_REQUIRED -0x7680 /**< No CA Chain is set, but required to operate. */ +#define POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE -0x7700 /**< An unexpected message was received from our peer. */ +#define POLARSSL_ERR_SSL_FATAL_ALERT_MESSAGE -0x7780 /**< A fatal alert message was received from our peer. */ +#define POLARSSL_ERR_SSL_PEER_VERIFY_FAILED -0x7800 /**< Verification of our peer failed. */ +#define POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY -0x7880 /**< The peer notified us that the connection is going to be closed. */ +#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO -0x7900 /**< Processing of the ClientHello handshake message failed. */ +#define POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO -0x7980 /**< Processing of the ServerHello handshake message failed. */ +#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE -0x7A00 /**< Processing of the Certificate handshake message failed. */ +#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST -0x7A80 /**< Processing of the CertificateRequest handshake message failed. */ +#define POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE -0x7B00 /**< Processing of the ServerKeyExchange handshake message failed. */ +#define POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO_DONE -0x7B80 /**< Processing of the ServerHelloDone handshake message failed. */ +#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE -0x7C00 /**< Processing of the ClientKeyExchange handshake message failed. */ +#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP -0x7C80 /**< Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Read Public. */ +#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS -0x7D00 /**< Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Calculate Secret. */ +#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY -0x7D80 /**< Processing of the CertificateVerify handshake message failed. */ +#define POLARSSL_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC -0x7E00 /**< Processing of the ChangeCipherSpec handshake message failed. */ +#define POLARSSL_ERR_SSL_BAD_HS_FINISHED -0x7E80 /**< Processing of the Finished handshake message failed. */ +#define POLARSSL_ERR_SSL_MALLOC_FAILED -0x7F00 /**< Memory allocation failed */ +#define POLARSSL_ERR_SSL_HW_ACCEL_FAILED -0x7F80 /**< Hardware acceleration function returned with error */ +#define POLARSSL_ERR_SSL_HW_ACCEL_FALLTHROUGH -0x6F80 /**< Hardware acceleration function skipped / left alone data */ +#define POLARSSL_ERR_SSL_COMPRESSION_FAILED -0x6F00 /**< Processing of the compression / decompression failed */ +#define POLARSSL_ERR_SSL_BAD_HS_PROTOCOL_VERSION -0x6E80 /**< Handshake protocol not within min/max boundaries */ +#define POLARSSL_ERR_SSL_BAD_HS_NEW_SESSION_TICKET -0x6E00 /**< Processing of the NewSessionTicket handshake message failed. */ +#define POLARSSL_ERR_SSL_SESSION_TICKET_EXPIRED -0x6D80 /**< Session ticket has expired. */ +#define POLARSSL_ERR_SSL_PK_TYPE_MISMATCH -0x6D00 /**< Public key type mismatch (eg, asked for RSA key exchange and presented EC key) */ +#define POLARSSL_ERR_SSL_UNKNOWN_IDENTITY -0x6C80 /**< Unknown identity received (eg, PSK identity) */ +#define POLARSSL_ERR_SSL_INTERNAL_ERROR -0x6C00 /**< Internal error (eg, unexpected failure in lower-level module) */ +#define POLARSSL_ERR_SSL_COUNTER_WRAPPING -0x6B80 /**< A counter would wrap (eg, too many messages exchanged). */ + +/* + * Various constants + */ +#define SSL_MAJOR_VERSION_3 3 +#define SSL_MINOR_VERSION_0 0 /*!< SSL v3.0 */ +#define SSL_MINOR_VERSION_1 1 /*!< TLS v1.0 */ +#define SSL_MINOR_VERSION_2 2 /*!< TLS v1.1 */ +#define SSL_MINOR_VERSION_3 3 /*!< TLS v1.2 */ + +/* Determine minimum supported version */ +#define SSL_MIN_MAJOR_VERSION SSL_MAJOR_VERSION_3 + +#if defined(POLARSSL_SSL_PROTO_SSL3) +#define SSL_MIN_MINOR_VERSION SSL_MINOR_VERSION_0 +#else +#if defined(POLARSSL_SSL_PROTO_TLS1) +#define SSL_MIN_MINOR_VERSION SSL_MINOR_VERSION_1 +#else +#if defined(POLARSSL_SSL_PROTO_TLS1_1) +#define SSL_MIN_MINOR_VERSION SSL_MINOR_VERSION_2 +#else +#if defined(POLARSSL_SSL_PROTO_TLS1_2) +#define SSL_MIN_MINOR_VERSION SSL_MINOR_VERSION_3 +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ +#endif /* POLARSSL_SSL_PROTO_TLS1_1 */ +#endif /* POLARSSL_SSL_PROTO_TLS1 */ +#endif /* POLARSSL_SSL_PROTO_SSL3 */ + +/* Determine maximum supported version */ +#define SSL_MAX_MAJOR_VERSION SSL_MAJOR_VERSION_3 + +#if defined(POLARSSL_SSL_PROTO_TLS1_2) +#define SSL_MAX_MINOR_VERSION SSL_MINOR_VERSION_3 +#else +#if defined(POLARSSL_SSL_PROTO_TLS1_1) +#define SSL_MAX_MINOR_VERSION SSL_MINOR_VERSION_2 +#else +#if defined(POLARSSL_SSL_PROTO_TLS1) +#define SSL_MAX_MINOR_VERSION SSL_MINOR_VERSION_1 +#else +#if defined(POLARSSL_SSL_PROTO_SSL3) +#define SSL_MAX_MINOR_VERSION SSL_MINOR_VERSION_0 +#endif /* POLARSSL_SSL_PROTO_SSL3 */ +#endif /* POLARSSL_SSL_PROTO_TLS1 */ +#endif /* POLARSSL_SSL_PROTO_TLS1_1 */ +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ + +/* RFC 6066 section 4, see also mfl_code_to_length in ssl_tls.c + * NONE must be zero so that memset()ing structure to zero works */ +#define SSL_MAX_FRAG_LEN_NONE 0 /*!< don't use this extension */ +#define SSL_MAX_FRAG_LEN_512 1 /*!< MaxFragmentLength 2^9 */ +#define SSL_MAX_FRAG_LEN_1024 2 /*!< MaxFragmentLength 2^10 */ +#define SSL_MAX_FRAG_LEN_2048 3 /*!< MaxFragmentLength 2^11 */ +#define SSL_MAX_FRAG_LEN_4096 4 /*!< MaxFragmentLength 2^12 */ +#define SSL_MAX_FRAG_LEN_INVALID 5 /*!< first invalid value */ + +#define SSL_IS_CLIENT 0 +#define SSL_IS_SERVER 1 +#define SSL_COMPRESS_NULL 0 +#define SSL_COMPRESS_DEFLATE 1 + +#define SSL_VERIFY_NONE 0 +#define SSL_VERIFY_OPTIONAL 1 +#define SSL_VERIFY_REQUIRED 2 + +#define SSL_INITIAL_HANDSHAKE 0 +#define SSL_RENEGOTIATION 1 /* In progress */ +#define SSL_RENEGOTIATION_DONE 2 /* Done */ +#define SSL_RENEGOTIATION_PENDING 3 /* Requested (server only) */ + +#define SSL_LEGACY_RENEGOTIATION 0 +#define SSL_SECURE_RENEGOTIATION 1 + +#define SSL_RENEGOTIATION_DISABLED 0 +#define SSL_RENEGOTIATION_ENABLED 1 + +#define SSL_RENEGOTIATION_NOT_ENFORCED -1 +#define SSL_RENEGO_MAX_RECORDS_DEFAULT 16 + +#define SSL_LEGACY_NO_RENEGOTIATION 0 +#define SSL_LEGACY_ALLOW_RENEGOTIATION 1 +#define SSL_LEGACY_BREAK_HANDSHAKE 2 + +#define SSL_TRUNC_HMAC_DISABLED 0 +#define SSL_TRUNC_HMAC_ENABLED 1 +#define SSL_TRUNCATED_HMAC_LEN 10 /* 80 bits, rfc 6066 section 7 */ + +#define SSL_SESSION_TICKETS_DISABLED 0 +#define SSL_SESSION_TICKETS_ENABLED 1 + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(SSL_DEFAULT_TICKET_LIFETIME) +#define SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ +#endif + +/* + * Size of the input / output buffer. + * Note: the RFC defines the default size of SSL / TLS messages. If you + * change the value here, other clients / servers may not be able to + * communicate with you anymore. Only change this value if you control + * both sides of the connection and have it reduced at both sides, or + * if you're using the Max Fragment Length extension and you know all your + * peers are using it too! + */ +#if !defined(SSL_MAX_CONTENT_LEN) +#define SSL_MAX_CONTENT_LEN 16384 /**< Size of the input / output buffer */ +#endif + +/* \} name SECTION: Module settings */ + +/* + * Allow extra bytes for record, authentication and encryption overhead: + * counter (8) + header (5) + IV(16) + MAC (16-48) + padding (0-256) + * and allow for a maximum of 1024 of compression expansion if + * enabled. + */ +#if defined(POLARSSL_ZLIB_SUPPORT) +#define SSL_COMPRESSION_ADD 1024 +#else +#define SSL_COMPRESSION_ADD 0 +#endif + +#if defined(POLARSSL_RC4_C) || defined(POLARSSL_CIPHER_MODE_CBC) +/* Ciphersuites using HMAC */ +#if defined(POLARSSL_SHA512_C) +#define SSL_MAC_ADD 48 /* SHA-384 used for HMAC */ +#elif defined(POLARSSL_SHA256_C) +#define SSL_MAC_ADD 32 /* SHA-256 used for HMAC */ +#else +#define SSL_MAC_ADD 20 /* SHA-1 used for HMAC */ +#endif +#else +/* AEAD ciphersuites: GCM and CCM use a 128 bits tag */ +#define SSL_MAC_ADD 16 +#endif + +#if defined(POLARSSL_CIPHER_MODE_CBC) +#define SSL_PADDING_ADD 256 +#else +#define SSL_PADDING_ADD 0 +#endif + +#define SSL_BUFFER_LEN ( SSL_MAX_CONTENT_LEN \ + + SSL_COMPRESSION_ADD \ + + 29 /* counter + header + IV */ \ + + SSL_MAC_ADD \ + + SSL_PADDING_ADD \ + ) + +/* + * Signaling ciphersuite values (SCSV) + */ +#define SSL_EMPTY_RENEGOTIATION_INFO 0xFF /**< renegotiation info ext */ + +/* + * Supported Signature and Hash algorithms (For TLS 1.2) + * RFC 5246 section 7.4.1.4.1 + */ +#define SSL_HASH_NONE 0 +#define SSL_HASH_MD5 1 +#define SSL_HASH_SHA1 2 +#define SSL_HASH_SHA224 3 +#define SSL_HASH_SHA256 4 +#define SSL_HASH_SHA384 5 +#define SSL_HASH_SHA512 6 + +#define SSL_SIG_ANON 0 +#define SSL_SIG_RSA 1 +#define SSL_SIG_ECDSA 3 + +/* + * Client Certificate Types + * RFC 5246 section 7.4.4 plus RFC 4492 section 5.5 + */ +#define SSL_CERT_TYPE_RSA_SIGN 1 +#define SSL_CERT_TYPE_ECDSA_SIGN 64 + +/* + * Message, alert and handshake types + */ +#define SSL_MSG_CHANGE_CIPHER_SPEC 20 +#define SSL_MSG_ALERT 21 +#define SSL_MSG_HANDSHAKE 22 +#define SSL_MSG_APPLICATION_DATA 23 + +#define SSL_ALERT_LEVEL_WARNING 1 +#define SSL_ALERT_LEVEL_FATAL 2 + +#define SSL_ALERT_MSG_CLOSE_NOTIFY 0 /* 0x00 */ +#define SSL_ALERT_MSG_UNEXPECTED_MESSAGE 10 /* 0x0A */ +#define SSL_ALERT_MSG_BAD_RECORD_MAC 20 /* 0x14 */ +#define SSL_ALERT_MSG_DECRYPTION_FAILED 21 /* 0x15 */ +#define SSL_ALERT_MSG_RECORD_OVERFLOW 22 /* 0x16 */ +#define SSL_ALERT_MSG_DECOMPRESSION_FAILURE 30 /* 0x1E */ +#define SSL_ALERT_MSG_HANDSHAKE_FAILURE 40 /* 0x28 */ +#define SSL_ALERT_MSG_NO_CERT 41 /* 0x29 */ +#define SSL_ALERT_MSG_BAD_CERT 42 /* 0x2A */ +#define SSL_ALERT_MSG_UNSUPPORTED_CERT 43 /* 0x2B */ +#define SSL_ALERT_MSG_CERT_REVOKED 44 /* 0x2C */ +#define SSL_ALERT_MSG_CERT_EXPIRED 45 /* 0x2D */ +#define SSL_ALERT_MSG_CERT_UNKNOWN 46 /* 0x2E */ +#define SSL_ALERT_MSG_ILLEGAL_PARAMETER 47 /* 0x2F */ +#define SSL_ALERT_MSG_UNKNOWN_CA 48 /* 0x30 */ +#define SSL_ALERT_MSG_ACCESS_DENIED 49 /* 0x31 */ +#define SSL_ALERT_MSG_DECODE_ERROR 50 /* 0x32 */ +#define SSL_ALERT_MSG_DECRYPT_ERROR 51 /* 0x33 */ +#define SSL_ALERT_MSG_EXPORT_RESTRICTION 60 /* 0x3C */ +#define SSL_ALERT_MSG_PROTOCOL_VERSION 70 /* 0x46 */ +#define SSL_ALERT_MSG_INSUFFICIENT_SECURITY 71 /* 0x47 */ +#define SSL_ALERT_MSG_INTERNAL_ERROR 80 /* 0x50 */ +#define SSL_ALERT_MSG_USER_CANCELED 90 /* 0x5A */ +#define SSL_ALERT_MSG_NO_RENEGOTIATION 100 /* 0x64 */ +#define SSL_ALERT_MSG_UNSUPPORTED_EXT 110 /* 0x6E */ +#define SSL_ALERT_MSG_UNRECOGNIZED_NAME 112 /* 0x70 */ +#define SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY 115 /* 0x73 */ +#define SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL 120 /* 0x78 */ + +#define SSL_HS_HELLO_REQUEST 0 +#define SSL_HS_CLIENT_HELLO 1 +#define SSL_HS_SERVER_HELLO 2 +#define SSL_HS_NEW_SESSION_TICKET 4 +#define SSL_HS_CERTIFICATE 11 +#define SSL_HS_SERVER_KEY_EXCHANGE 12 +#define SSL_HS_CERTIFICATE_REQUEST 13 +#define SSL_HS_SERVER_HELLO_DONE 14 +#define SSL_HS_CERTIFICATE_VERIFY 15 +#define SSL_HS_CLIENT_KEY_EXCHANGE 16 +#define SSL_HS_FINISHED 20 + +/* + * TLS extensions + */ +#define TLS_EXT_SERVERNAME 0 +#define TLS_EXT_SERVERNAME_HOSTNAME 0 + +#define TLS_EXT_MAX_FRAGMENT_LENGTH 1 + +#define TLS_EXT_TRUNCATED_HMAC 4 + +#define TLS_EXT_SUPPORTED_ELLIPTIC_CURVES 10 +#define TLS_EXT_SUPPORTED_POINT_FORMATS 11 + +#define TLS_EXT_SIG_ALG 13 + +#define TLS_EXT_ALPN 16 + +#define TLS_EXT_SESSION_TICKET 35 + +#define TLS_EXT_RENEGOTIATION_INFO 0xFF01 + +/* + * TLS extension flags (for extensions with outgoing ServerHello content + * that need it (e.g. for RENEGOTIATION_INFO the server already knows because + * of state of the renegotiation flag, so no indicator is required) + */ +#define TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT (1 << 0) + +/* + * Size defines + */ +#if !defined(POLARSSL_PSK_MAX_LEN) +#define POLARSSL_PSK_MAX_LEN 32 /* 256 bits */ +#endif + +/* Dummy type used only for its size */ +union _ssl_premaster_secret +{ +#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) + unsigned char _pms_rsa[48]; /* RFC 5246 8.1.1 */ +#endif +#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) + unsigned char _pms_dhm[POLARSSL_MPI_MAX_SIZE]; /* RFC 5246 8.1.2 */ +#endif +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + unsigned char _pms_ecdh[POLARSSL_ECP_MAX_BYTES]; /* RFC 4492 5.10 */ +#endif +#if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) + unsigned char _pms_psk[4 + 2 * POLARSSL_PSK_MAX_LEN]; /* RFC 4279 2 */ +#endif +#if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) + unsigned char _pms_dhe_psk[4 + POLARSSL_MPI_MAX_SIZE + + POLARSSL_PSK_MAX_LEN]; /* RFC 4279 3 */ +#endif +#if defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) + unsigned char _pms_rsa_psk[52 + POLARSSL_PSK_MAX_LEN]; /* RFC 4279 4 */ +#endif +#if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) + unsigned char _pms_ecdhe_psk[4 + POLARSSL_ECP_MAX_BYTES + + POLARSSL_PSK_MAX_LEN]; /* RFC 5489 2 */ +#endif +}; + +#define POLARSSL_PREMASTER_SIZE sizeof( union _ssl_premaster_secret ) + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Generic function pointers for allowing external RSA private key + * implementations. + */ +typedef int (*rsa_decrypt_func)( void *ctx, int mode, size_t *olen, + const unsigned char *input, unsigned char *output, + size_t output_max_len ); +typedef int (*rsa_sign_func)( void *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + int mode, md_type_t md_alg, unsigned int hashlen, + const unsigned char *hash, unsigned char *sig ); +typedef size_t (*rsa_key_len_func)( void *ctx ); + +/* + * SSL state machine + */ +typedef enum +{ + SSL_HELLO_REQUEST, + SSL_CLIENT_HELLO, + SSL_SERVER_HELLO, + SSL_SERVER_CERTIFICATE, + SSL_SERVER_KEY_EXCHANGE, + SSL_CERTIFICATE_REQUEST, + SSL_SERVER_HELLO_DONE, + SSL_CLIENT_CERTIFICATE, + SSL_CLIENT_KEY_EXCHANGE, + SSL_CERTIFICATE_VERIFY, + SSL_CLIENT_CHANGE_CIPHER_SPEC, + SSL_CLIENT_FINISHED, + SSL_SERVER_CHANGE_CIPHER_SPEC, + SSL_SERVER_FINISHED, + SSL_FLUSH_BUFFERS, + SSL_HANDSHAKE_WRAPUP, + SSL_HANDSHAKE_OVER, + SSL_SERVER_NEW_SESSION_TICKET, +} +ssl_states; + +typedef struct _ssl_session ssl_session; +typedef struct _ssl_context ssl_context; +typedef struct _ssl_transform ssl_transform; +typedef struct _ssl_handshake_params ssl_handshake_params; +#if defined(POLARSSL_SSL_SESSION_TICKETS) +typedef struct _ssl_ticket_keys ssl_ticket_keys; +#endif +#if defined(POLARSSL_X509_CRT_PARSE_C) +typedef struct _ssl_key_cert ssl_key_cert; +#endif + +/* + * This structure is used for storing current session data. + */ +struct _ssl_session +{ +#if defined(POLARSSL_HAVE_TIME) + time_t start; /*!< starting time */ +#endif + int ciphersuite; /*!< chosen ciphersuite */ + int compression; /*!< chosen compression */ + size_t length; /*!< session id length */ + unsigned char id[32]; /*!< session identifier */ + unsigned char master[48]; /*!< the master secret */ + +#if defined(POLARSSL_X509_CRT_PARSE_C) + x509_crt *peer_cert; /*!< peer X.509 cert chain */ +#endif /* POLARSSL_X509_CRT_PARSE_C */ + int verify_result; /*!< verification result */ + +#if defined(POLARSSL_SSL_SESSION_TICKETS) + unsigned char *ticket; /*!< RFC 5077 session ticket */ + size_t ticket_len; /*!< session ticket length */ + uint32_t ticket_lifetime; /*!< ticket lifetime hint */ +#endif /* POLARSSL_SSL_SESSION_TICKETS */ + +#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH) + unsigned char mfl_code; /*!< MaxFragmentLength negotiated by peer */ +#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(POLARSSL_SSL_TRUNCATED_HMAC) + int trunc_hmac; /*!< flag for truncated hmac activation */ +#endif /* POLARSSL_SSL_TRUNCATED_HMAC */ +}; + +/* + * This structure contains a full set of runtime transform parameters + * either in negotiation or active. + */ +struct _ssl_transform +{ + /* + * Session specific crypto layer + */ + const ssl_ciphersuite_t *ciphersuite_info; + /*!< Chosen cipersuite_info */ + unsigned int keylen; /*!< symmetric key length */ + size_t minlen; /*!< min. ciphertext length */ + size_t ivlen; /*!< IV length */ + size_t fixed_ivlen; /*!< Fixed part of IV (AEAD) */ + size_t maclen; /*!< MAC length */ + + unsigned char iv_enc[16]; /*!< IV (encryption) */ + unsigned char iv_dec[16]; /*!< IV (decryption) */ + +#if defined(POLARSSL_SSL_PROTO_SSL3) + /* Needed only for SSL v3.0 secret */ + unsigned char mac_enc[48]; /*!< SSL v3.0 secret (enc) */ + unsigned char mac_dec[48]; /*!< SSL v3.0 secret (dec) */ +#endif /* POLARSSL_SSL_PROTO_SSL3 */ + + md_context_t md_ctx_enc; /*!< MAC (encryption) */ + md_context_t md_ctx_dec; /*!< MAC (decryption) */ + + cipher_context_t cipher_ctx_enc; /*!< encryption context */ + cipher_context_t cipher_ctx_dec; /*!< decryption context */ + + /* + * Session specific compression layer + */ +#if defined(POLARSSL_ZLIB_SUPPORT) + z_stream ctx_deflate; /*!< compression context */ + z_stream ctx_inflate; /*!< decompression context */ +#endif +}; + +/* + * This structure contains the parameters only needed during handshake. + */ +struct _ssl_handshake_params +{ + /* + * Handshake specific crypto variables + */ + int sig_alg; /*!< Hash algorithm for signature */ + int cert_type; /*!< Requested cert type */ + int verify_sig_alg; /*!< Signature algorithm for verify */ +#if defined(POLARSSL_DHM_C) + dhm_context dhm_ctx; /*!< DHM key exchange */ +#endif +#if defined(POLARSSL_ECDH_C) + ecdh_context ecdh_ctx; /*!< ECDH key exchange */ +#endif +#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C) + const ecp_curve_info **curves; /*!< Supported elliptic curves */ +#endif +#if defined(POLARSSL_X509_CRT_PARSE_C) + /** + * Current key/cert or key/cert list. + * On client: pointer to ssl->key_cert, only the first entry used. + * On server: starts as a pointer to ssl->key_cert, then becomes + * a pointer to the chosen key from this list or the SNI list. + */ + ssl_key_cert *key_cert; +#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION) + ssl_key_cert *sni_key_cert; /*!< key/cert list from SNI */ +#endif +#endif /* POLARSSL_X509_CRT_PARSE_C */ + + /* + * Checksum contexts + */ +#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_1) + md5_context fin_md5; + sha1_context fin_sha1; +#endif +#if defined(POLARSSL_SSL_PROTO_TLS1_2) +#if defined(POLARSSL_SHA256_C) + sha256_context fin_sha256; +#endif +#if defined(POLARSSL_SHA512_C) + sha512_context fin_sha512; +#endif +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ + + void (*update_checksum)(ssl_context *, const unsigned char *, size_t); + void (*calc_verify)(ssl_context *, unsigned char *); + void (*calc_finished)(ssl_context *, unsigned char *, int); + int (*tls_prf)(const unsigned char *, size_t, const char *, + const unsigned char *, size_t, + unsigned char *, size_t); + + size_t pmslen; /*!< premaster length */ + + unsigned char randbytes[64]; /*!< random bytes */ + unsigned char premaster[POLARSSL_PREMASTER_SIZE]; + /*!< premaster secret */ + + int resume; /*!< session resume indicator*/ + int max_major_ver; /*!< max. major version client*/ + int max_minor_ver; /*!< max. minor version client*/ + int cli_exts; /*!< client extension presence*/ + +#if defined(POLARSSL_SSL_SESSION_TICKETS) + int new_session_ticket; /*!< use NewSessionTicket? */ +#endif /* POLARSSL_SSL_SESSION_TICKETS */ +}; + +#if defined(POLARSSL_SSL_SESSION_TICKETS) +/* + * Parameters needed to secure session tickets + */ +struct _ssl_ticket_keys +{ + unsigned char key_name[16]; /*!< name to quickly discard bad tickets */ + aes_context enc; /*!< encryption context */ + aes_context dec; /*!< decryption context */ + unsigned char mac_key[16]; /*!< authentication key */ +}; +#endif /* POLARSSL_SSL_SESSION_TICKETS */ + +#if defined(POLARSSL_X509_CRT_PARSE_C) +/* + * List of certificate + private key pairs + */ +struct _ssl_key_cert +{ + x509_crt *cert; /*!< cert */ + pk_context *key; /*!< private key */ + int key_own_alloc; /*!< did we allocate key? */ + ssl_key_cert *next; /*!< next key/cert pair */ +}; +#endif /* POLARSSL_X509_CRT_PARSE_C */ + +struct _ssl_context +{ + /* + * Miscellaneous + */ + int state; /*!< SSL handshake: current state */ + int renegotiation; /*!< Initial or renegotiation */ + int renego_records_seen; /*!< Records since renego request */ + + int major_ver; /*!< equal to SSL_MAJOR_VERSION_3 */ + int minor_ver; /*!< either 0 (SSL3) or 1 (TLS1.0) */ + + int max_major_ver; /*!< max. major version used */ + int max_minor_ver; /*!< max. minor version used */ + int min_major_ver; /*!< min. major version used */ + int min_minor_ver; /*!< min. minor version used */ + + /* + * Callbacks (RNG, debug, I/O, verification) + */ + int (*f_rng)(void *, unsigned char *, size_t); + void (*f_dbg)(void *, int, const char *); + int (*f_recv)(void *, unsigned char *, size_t); + int (*f_send)(void *, const unsigned char *, size_t); + int (*f_get_cache)(void *, ssl_session *); + int (*f_set_cache)(void *, const ssl_session *); + + void *p_rng; /*!< context for the RNG function */ + void *p_dbg; /*!< context for the debug function */ + void *p_recv; /*!< context for reading operations */ + void *p_send; /*!< context for writing operations */ + void *p_get_cache; /*!< context for cache retrieval */ + void *p_set_cache; /*!< context for cache store */ + void *p_hw_data; /*!< context for HW acceleration */ + +#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION) + int (*f_sni)(void *, ssl_context *, const unsigned char *, size_t); + void *p_sni; /*!< context for SNI extension */ +#endif + +#if defined(POLARSSL_X509_CRT_PARSE_C) + int (*f_vrfy)(void *, x509_crt *, int, int *); + void *p_vrfy; /*!< context for verification */ +#endif + +#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED) + int (*f_psk)(void *, ssl_context *, const unsigned char *, size_t); + void *p_psk; /*!< context for PSK retrieval */ +#endif + + /* + * Session layer + */ + ssl_session *session_in; /*!< current session data (in) */ + ssl_session *session_out; /*!< current session data (out) */ + ssl_session *session; /*!< negotiated session data */ + ssl_session *session_negotiate; /*!< session data in negotiation */ + + ssl_handshake_params *handshake; /*!< params required only during + the handshake process */ + + /* + * Record layer transformations + */ + ssl_transform *transform_in; /*!< current transform params (in) */ + ssl_transform *transform_out; /*!< current transform params (in) */ + ssl_transform *transform; /*!< negotiated transform params */ + ssl_transform *transform_negotiate; /*!< transform params in negotiation */ + + /* + * Record layer (incoming data) + */ + unsigned char *in_ctr; /*!< 64-bit incoming message counter */ + unsigned char *in_hdr; /*!< 5-byte record header (in_ctr+8) */ + unsigned char *in_iv; /*!< ivlen-byte IV (in_hdr+5) */ + unsigned char *in_msg; /*!< message contents (in_iv+ivlen) */ + unsigned char *in_offt; /*!< read offset in application data */ + + int in_msgtype; /*!< record header: message type */ + size_t in_msglen; /*!< record header: message length */ + size_t in_left; /*!< amount of data read so far */ + + size_t in_hslen; /*!< current handshake message length */ + int nb_zero; /*!< # of 0-length encrypted messages */ + int record_read; /*!< record is already present */ + + /* + * Record layer (outgoing data) + */ + unsigned char *out_ctr; /*!< 64-bit outgoing message counter */ + unsigned char *out_hdr; /*!< 5-byte record header (out_ctr+8) */ + unsigned char *out_iv; /*!< ivlen-byte IV (out_hdr+5) */ + unsigned char *out_msg; /*!< message contents (out_iv+ivlen) */ + + int out_msgtype; /*!< record header: message type */ + size_t out_msglen; /*!< record header: message length */ + size_t out_left; /*!< amount of data not yet written */ + +#if defined(POLARSSL_ZLIB_SUPPORT) + unsigned char *compress_buf; /*!< zlib data buffer */ +#endif +#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH) + unsigned char mfl_code; /*!< MaxFragmentLength chosen by us */ +#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */ + + /* + * PKI layer + */ +#if defined(POLARSSL_X509_CRT_PARSE_C) + ssl_key_cert *key_cert; /*!< own certificate(s)/key(s) */ + + x509_crt *ca_chain; /*!< own trusted CA chain */ + x509_crl *ca_crl; /*!< trusted CA CRLs */ + const char *peer_cn; /*!< expected peer CN */ +#endif /* POLARSSL_X509_CRT_PARSE_C */ + + /* + * Support for generating and checking session tickets + */ +#if defined(POLARSSL_SSL_SESSION_TICKETS) + ssl_ticket_keys *ticket_keys; /*!< keys for ticket encryption */ +#endif /* POLARSSL_SSL_SESSION_TICKETS */ + + /* + * User settings + */ + int endpoint; /*!< 0: client, 1: server */ + int authmode; /*!< verification mode */ + int client_auth; /*!< flag for client auth. */ + int verify_result; /*!< verification result */ + int disable_renegotiation; /*!< enable/disable renegotiation */ + int allow_legacy_renegotiation; /*!< allow legacy renegotiation */ + int renego_max_records; /*!< grace period for renegotiation */ + const int *ciphersuite_list[4]; /*!< allowed ciphersuites / version */ +#if defined(POLARSSL_SSL_SET_CURVES) + const ecp_group_id *curve_list; /*!< allowed curves */ +#endif +#if defined(POLARSSL_SSL_TRUNCATED_HMAC) + int trunc_hmac; /*!< negotiate truncated hmac? */ +#endif +#if defined(POLARSSL_SSL_SESSION_TICKETS) + int session_tickets; /*!< use session tickets? */ + int ticket_lifetime; /*!< session ticket lifetime */ +#endif + +#if defined(POLARSSL_DHM_C) + mpi dhm_P; /*!< prime modulus for DHM */ + mpi dhm_G; /*!< generator for DHM */ +#endif + +#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED) + /* + * PSK values + */ + unsigned char *psk; + size_t psk_len; + unsigned char *psk_identity; + size_t psk_identity_len; +#endif + +#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION) + /* + * SNI extension + */ + unsigned char *hostname; + size_t hostname_len; +#endif + +#if defined(POLARSSL_SSL_ALPN) + /* + * ALPN extension + */ + const char **alpn_list; /*!< ordered list of supported protocols */ + const char *alpn_chosen; /*!< negotiated protocol */ +#endif + + /* + * Secure renegotiation + */ + int secure_renegotiation; /*!< does peer support legacy or + secure renegotiation */ + size_t verify_data_len; /*!< length of verify data stored */ + char own_verify_data[36]; /*!< previous handshake verify data */ + char peer_verify_data[36]; /*!< previous handshake verify data */ +}; + +#if defined(POLARSSL_SSL_HW_RECORD_ACCEL) + +#define SSL_CHANNEL_OUTBOUND 0 +#define SSL_CHANNEL_INBOUND 1 + +extern int (*ssl_hw_record_init)(ssl_context *ssl, + const unsigned char *key_enc, const unsigned char *key_dec, + size_t keylen, + const unsigned char *iv_enc, const unsigned char *iv_dec, + size_t ivlen, + const unsigned char *mac_enc, const unsigned char *mac_dec, + size_t maclen); +extern int (*ssl_hw_record_activate)(ssl_context *ssl, int direction); +extern int (*ssl_hw_record_reset)(ssl_context *ssl); +extern int (*ssl_hw_record_write)(ssl_context *ssl); +extern int (*ssl_hw_record_read)(ssl_context *ssl); +extern int (*ssl_hw_record_finish)(ssl_context *ssl); +#endif /* POLARSSL_SSL_HW_RECORD_ACCEL */ + +/** + * \brief Returns the list of ciphersuites supported by the SSL/TLS module. + * + * \return a statically allocated array of ciphersuites, the last + * entry is 0. + */ +const int *ssl_list_ciphersuites( void ); + +/** + * \brief Return the name of the ciphersuite associated with the + * given ID + * + * \param ciphersuite_id SSL ciphersuite ID + * + * \return a string containing the ciphersuite name + */ +const char *ssl_get_ciphersuite_name( const int ciphersuite_id ); + +/** + * \brief Return the ID of the ciphersuite associated with the + * given name + * + * \param ciphersuite_name SSL ciphersuite name + * + * \return the ID with the ciphersuite or 0 if not found + */ +int ssl_get_ciphersuite_id( const char *ciphersuite_name ); + +/** + * \brief Initialize an SSL context + * (An individual SSL context is not thread-safe) + * + * \param ssl SSL context + * + * \return 0 if successful, or POLARSSL_ERR_SSL_MALLOC_FAILED if + * memory allocation failed + */ +int ssl_init( ssl_context *ssl ); + +/** + * \brief Reset an already initialized SSL context for re-use + * while retaining application-set variables, function + * pointers and data. + * + * \param ssl SSL context + * \return 0 if successful, or POLASSL_ERR_SSL_MALLOC_FAILED, + POLARSSL_ERR_SSL_HW_ACCEL_FAILED or + * POLARSSL_ERR_SSL_COMPRESSION_FAILED + */ +int ssl_session_reset( ssl_context *ssl ); + +/** + * \brief Set the current endpoint type + * + * \param ssl SSL context + * \param endpoint must be SSL_IS_CLIENT or SSL_IS_SERVER + * + * \note This function should be called right after ssl_init() since + * some other ssl_set_foo() functions depend on it. + */ +void ssl_set_endpoint( ssl_context *ssl, int endpoint ); + +/** + * \brief Set the certificate verification mode + * + * \param ssl SSL context + * \param authmode can be: + * + * SSL_VERIFY_NONE: peer certificate is not checked (default), + * this is insecure and SHOULD be avoided. + * + * SSL_VERIFY_OPTIONAL: peer certificate is checked, however the + * handshake continues even if verification failed; + * ssl_get_verify_result() can be called after the + * handshake is complete. + * + * SSL_VERIFY_REQUIRED: peer *must* present a valid certificate, + * handshake is aborted if verification failed. + * + * \note On client, SSL_VERIFY_REQUIRED is the recommended mode. + * With SSL_VERIFY_OPTIONAL, the user needs to call ssl_get_verify_result() at + * the right time(s), which may not be obvious, while REQUIRED always perform + * the verification as soon as possible. For example, REQUIRED was protecting + * against the "triple handshake" attack even before it was found. + */ +void ssl_set_authmode( ssl_context *ssl, int authmode ); + +#if defined(POLARSSL_X509_CRT_PARSE_C) +/** + * \brief Set the verification callback (Optional). + * + * If set, the verify callback is called for each + * certificate in the chain. For implementation + * information, please see \c x509parse_verify() + * + * \param ssl SSL context + * \param f_vrfy verification function + * \param p_vrfy verification parameter + */ +void ssl_set_verify( ssl_context *ssl, + int (*f_vrfy)(void *, x509_crt *, int, int *), + void *p_vrfy ); +#endif /* POLARSSL_X509_CRT_PARSE_C */ + +/** + * \brief Set the random number generator callback + * + * \param ssl SSL context + * \param f_rng RNG function + * \param p_rng RNG parameter + */ +void ssl_set_rng( ssl_context *ssl, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Set the debug callback + * + * \param ssl SSL context + * \param f_dbg debug function + * \param p_dbg debug parameter + */ +void ssl_set_dbg( ssl_context *ssl, + void (*f_dbg)(void *, int, const char *), + void *p_dbg ); + +/** + * \brief Set the underlying BIO read and write callbacks + * + * \param ssl SSL context + * \param f_recv read callback + * \param p_recv read parameter + * \param f_send write callback + * \param p_send write parameter + */ +void ssl_set_bio( ssl_context *ssl, + int (*f_recv)(void *, unsigned char *, size_t), void *p_recv, + int (*f_send)(void *, const unsigned char *, size_t), void *p_send ); + +/** + * \brief Set the session cache callbacks (server-side only) + * If not set, no session resuming is done. + * + * The session cache has the responsibility to check for stale + * entries based on timeout. See RFC 5246 for recommendations. + * + * Warning: session.peer_cert is cleared by the SSL/TLS layer on + * connection shutdown, so do not cache the pointer! Either set + * it to NULL or make a full copy of the certificate. + * + * The get callback is called once during the initial handshake + * to enable session resuming. The get function has the + * following parameters: (void *parameter, ssl_session *session) + * If a valid entry is found, it should fill the master of + * the session object with the cached values and return 0, + * return 1 otherwise. Optionally peer_cert can be set as well + * if it is properly present in cache entry. + * + * The set callback is called once during the initial handshake + * to enable session resuming after the entire handshake has + * been finished. The set function has the following parameters: + * (void *parameter, const ssl_session *session). The function + * should create a cache entry for future retrieval based on + * the data in the session structure and should keep in mind + * that the ssl_session object presented (and all its referenced + * data) is cleared by the SSL/TLS layer when the connection is + * terminated. It is recommended to add metadata to determine if + * an entry is still valid in the future. Return 0 if + * successfully cached, return 1 otherwise. + * + * \param ssl SSL context + * \param f_get_cache session get callback + * \param p_get_cache session get parameter + * \param f_set_cache session set callback + * \param p_set_cache session set parameter + */ +void ssl_set_session_cache( ssl_context *ssl, + int (*f_get_cache)(void *, ssl_session *), void *p_get_cache, + int (*f_set_cache)(void *, const ssl_session *), void *p_set_cache ); + +/** + * \brief Request resumption of session (client-side only) + * Session data is copied from presented session structure. + * + * \param ssl SSL context + * \param session session context + * + * \return 0 if successful, + * POLARSSL_ERR_SSL_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_SSL_BAD_INPUT_DATA if used server-side or + * arguments are otherwise invalid + * + * \sa ssl_get_session() + */ +int ssl_set_session( ssl_context *ssl, const ssl_session *session ); + +/** + * \brief Set the list of allowed ciphersuites and the preference + * order. First in the list has the highest preference. + * (Overrides all version specific lists) + * + * Note: The PolarSSL SSL server uses its own preferences + * over the preference of the connection SSL client unless + * POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE is defined! + * + * \param ssl SSL context + * \param ciphersuites 0-terminated list of allowed ciphersuites + */ +void ssl_set_ciphersuites( ssl_context *ssl, const int *ciphersuites ); + +/** + * \brief Set the list of allowed ciphersuites and the + * preference order for a specific version of the protocol. + * (Only useful on the server side) + * + * \param ssl SSL context + * \param ciphersuites 0-terminated list of allowed ciphersuites + * \param major Major version number (only SSL_MAJOR_VERSION_3 + * supported) + * \param minor Minor version number (SSL_MINOR_VERSION_0, + * SSL_MINOR_VERSION_1 and SSL_MINOR_VERSION_2, + * SSL_MINOR_VERSION_3 supported) + */ +void ssl_set_ciphersuites_for_version( ssl_context *ssl, + const int *ciphersuites, + int major, int minor ); + +#if defined(POLARSSL_X509_CRT_PARSE_C) +/** + * \brief Set the data required to verify peer certificate + * + * \param ssl SSL context + * \param ca_chain trusted CA chain (meaning all fully trusted top-level CAs) + * \param ca_crl trusted CA CRLs + * \param peer_cn expected peer CommonName (or NULL) + */ +void ssl_set_ca_chain( ssl_context *ssl, x509_crt *ca_chain, + x509_crl *ca_crl, const char *peer_cn ); + +/** + * \brief Set own certificate chain and private key + * + * \note own_cert should contain in order from the bottom up your + * certificate chain. The top certificate (self-signed) + * can be omitted. + * + * \note This function may be called more than once if you want to + * support multiple certificates (eg, one using RSA and one + * using ECDSA). However, on client, currently only the first + * certificate is used (subsequent calls have no effect). + * + * \param ssl SSL context + * \param own_cert own public certificate chain + * \param pk_key own private key + * + * \return 0 on success or POLARSSL_ERR_SSL_MALLOC_FAILED + */ +int ssl_set_own_cert( ssl_context *ssl, x509_crt *own_cert, + pk_context *pk_key ); + +#if defined(POLARSSL_RSA_C) +/** + * \brief Set own certificate chain and private RSA key + * + * Note: own_cert should contain IN order from the bottom + * up your certificate chain. The top certificate (self-signed) + * can be omitted. + * + * \warning This backwards-compatibility function is deprecated! + * Please use \c ssl_set_own_cert() instead. + * + * \param ssl SSL context + * \param own_cert own public certificate chain + * \param rsa_key own private RSA key + * + * \return 0 on success, or a specific error code. + */ +int ssl_set_own_cert_rsa( ssl_context *ssl, x509_crt *own_cert, + rsa_context *rsa_key ); +#endif /* POLARSSL_RSA_C */ + +/** + * \brief Set own certificate and alternate non-PolarSSL RSA private + * key and handling callbacks, such as the PKCS#11 wrappers + * or any other external private key handler. + * (see the respective RSA functions in rsa.h for documentation + * of the callback parameters, with the only change being + * that the rsa_context * is a void * in the callbacks) + * + * Note: own_cert should contain IN order from the bottom + * up your certificate chain. The top certificate (self-signed) + * can be omitted. + * + * \warning This backwards-compatibility function is deprecated! + * Please use \c pk_init_ctx_rsa_alt() + * and \c ssl_set_own_cert() instead. + * + * \param ssl SSL context + * \param own_cert own public certificate chain + * \param rsa_key alternate implementation private RSA key + * \param rsa_decrypt alternate implementation of \c rsa_pkcs1_decrypt() + * \param rsa_sign alternate implementation of \c rsa_pkcs1_sign() + * \param rsa_key_len function returning length of RSA key in bytes + * + * \return 0 on success, or a specific error code. + */ +int ssl_set_own_cert_alt( ssl_context *ssl, x509_crt *own_cert, + void *rsa_key, + rsa_decrypt_func rsa_decrypt, + rsa_sign_func rsa_sign, + rsa_key_len_func rsa_key_len ); +#endif /* POLARSSL_X509_CRT_PARSE_C */ + +#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED) +/** + * \brief Set the Pre Shared Key (PSK) and the identity name connected + * to it. + * + * \param ssl SSL context + * \param psk pointer to the pre-shared key + * \param psk_len pre-shared key length + * \param psk_identity pointer to the pre-shared key identity + * \param psk_identity_len identity key length + * + * \return 0 if successful or POLARSSL_ERR_SSL_MALLOC_FAILED + */ +int ssl_set_psk( ssl_context *ssl, const unsigned char *psk, size_t psk_len, + const unsigned char *psk_identity, size_t psk_identity_len ); + +/** + * \brief Set the PSK callback (server-side only) (Optional). + * + * If set, the PSK callback is called for each + * handshake where a PSK ciphersuite was negotiated. + * The caller provides the identity received and wants to + * receive the actual PSK data and length. + * + * The callback has the following parameters: (void *parameter, + * ssl_context *ssl, const unsigned char *psk_identity, + * size_t identity_len) + * If a valid PSK identity is found, the callback should use + * ssl_set_psk() on the ssl context to set the correct PSK and + * identity and return 0. + * Any other return value will result in a denied PSK identity. + * + * \param ssl SSL context + * \param f_psk PSK identity function + * \param p_psk PSK identity parameter + */ +void ssl_set_psk_cb( ssl_context *ssl, + int (*f_psk)(void *, ssl_context *, const unsigned char *, + size_t), + void *p_psk ); +#endif /* POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#if defined(POLARSSL_DHM_C) +/** + * \brief Set the Diffie-Hellman public P and G values, + * read as hexadecimal strings (server-side only) + * (Default: POLARSSL_DHM_RFC5114_MODP_1024_[PG]) + * + * \param ssl SSL context + * \param dhm_P Diffie-Hellman-Merkle modulus + * \param dhm_G Diffie-Hellman-Merkle generator + * + * \return 0 if successful + */ +int ssl_set_dh_param( ssl_context *ssl, const char *dhm_P, const char *dhm_G ); + +/** + * \brief Set the Diffie-Hellman public P and G values, + * read from existing context (server-side only) + * + * \param ssl SSL context + * \param dhm_ctx Diffie-Hellman-Merkle context + * + * \return 0 if successful + */ +int ssl_set_dh_param_ctx( ssl_context *ssl, dhm_context *dhm_ctx ); +#endif /* POLARSSL_DHM_C */ + +#if defined(POLARSSL_SSL_SET_CURVES) +/** + * \brief Set the allowed curves in order of preference. + * (Default: all defined curves.) + * + * On server: this only affects selection of the ECDHE curve; + * the curves used for ECDH and ECDSA are determined by the + * list of available certificates instead. + * + * On client: this affects the list of curves offered for any + * use. The server can override our preference order. + * + * Both sides: limits the set of curves used by peer to the + * listed curves for any use (ECDH(E), certificates). + * + * \param ssl SSL context + * \param curves Ordered list of allowed curves, + * terminated by POLARSSL_ECP_DP_NONE. + */ +void ssl_set_curves( ssl_context *ssl, const ecp_group_id *curves ); +#endif /* POLARSSL_SSL_SET_CURVES */ + +#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION) +/** + * \brief Set hostname for ServerName TLS extension + * (client-side only) + * + * + * \param ssl SSL context + * \param hostname the server hostname + * + * \return 0 if successful or POLARSSL_ERR_SSL_MALLOC_FAILED + */ +int ssl_set_hostname( ssl_context *ssl, const char *hostname ); + +/** + * \brief Set server side ServerName TLS extension callback + * (optional, server-side only). + * + * If set, the ServerName callback is called whenever the + * server receives a ServerName TLS extension from the client + * during a handshake. The ServerName callback has the + * following parameters: (void *parameter, ssl_context *ssl, + * const unsigned char *hostname, size_t len). If a suitable + * certificate is found, the callback should set the + * certificate and key to use with ssl_set_own_cert() (and + * possibly adjust the CA chain as well) and return 0. The + * callback should return -1 to abort the handshake at this + * point. + * + * \param ssl SSL context + * \param f_sni verification function + * \param p_sni verification parameter + */ +void ssl_set_sni( ssl_context *ssl, + int (*f_sni)(void *, ssl_context *, const unsigned char *, + size_t), + void *p_sni ); +#endif /* POLARSSL_SSL_SERVER_NAME_INDICATION */ + +#if defined(POLARSSL_SSL_ALPN) +/** + * \brief Set the supported Application Layer Protocols. + * + * \param ssl SSL context + * \param protos NULL-terminated list of supported protocols, + * in decreasing preference order. + * + * \return 0 on success, or POLARSSL_ERR_SSL_BAD_INPUT_DATA. + */ +int ssl_set_alpn_protocols( ssl_context *ssl, const char **protos ); + +/** + * \brief Get the name of the negotiated Application Layer Protocol. + * This function should be called after the handshake is + * completed. + * + * \param ssl SSL context + * + * \return Protcol name, or NULL if no protocol was negotiated. + */ +const char *ssl_get_alpn_protocol( const ssl_context *ssl ); +#endif /* POLARSSL_SSL_ALPN */ + +/** + * \brief Set the maximum supported version sent from the client side + * and/or accepted at the server side + * (Default: SSL_MAX_MAJOR_VERSION, SSL_MAX_MINOR_VERSION) + * + * Note: This ignores ciphersuites from 'higher' versions. + * Note: Input outside of the SSL_MAX_XXXXX_VERSION and + * SSL_MIN_XXXXX_VERSION range is ignored. + * + * \param ssl SSL context + * \param major Major version number (only SSL_MAJOR_VERSION_3 supported) + * \param minor Minor version number (SSL_MINOR_VERSION_0, + * SSL_MINOR_VERSION_1 and SSL_MINOR_VERSION_2, + * SSL_MINOR_VERSION_3 supported) + */ +void ssl_set_max_version( ssl_context *ssl, int major, int minor ); + + +/** + * \brief Set the minimum accepted SSL/TLS protocol version + * (Default: SSL_MIN_MAJOR_VERSION, SSL_MIN_MINOR_VERSION) + * + * Note: Input outside of the SSL_MAX_XXXXX_VERSION and + * SSL_MIN_XXXXX_VERSION range is ignored. + * + * \param ssl SSL context + * \param major Major version number (only SSL_MAJOR_VERSION_3 supported) + * \param minor Minor version number (SSL_MINOR_VERSION_0, + * SSL_MINOR_VERSION_1 and SSL_MINOR_VERSION_2, + * SSL_MINOR_VERSION_3 supported) + */ +void ssl_set_min_version( ssl_context *ssl, int major, int minor ); + +#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH) +/** + * \brief Set the maximum fragment length to emit and/or negotiate + * (Default: SSL_MAX_CONTENT_LEN, usually 2^14 bytes) + * (Server: set maximum fragment length to emit, + * usually negotiated by the client during handshake + * (Client: set maximum fragment length to emit *and* + * negotiate with the server during handshake) + * + * \param ssl SSL context + * \param mfl_code Code for maximum fragment length (allowed values: + * SSL_MAX_FRAG_LEN_512, SSL_MAX_FRAG_LEN_1024, + * SSL_MAX_FRAG_LEN_2048, SSL_MAX_FRAG_LEN_4096) + * + * \return O if successful or POLARSSL_ERR_SSL_BAD_INPUT_DATA + */ +int ssl_set_max_frag_len( ssl_context *ssl, unsigned char mfl_code ); +#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(POLARSSL_SSL_TRUNCATED_HMAC) +/** + * \brief Activate negotiation of truncated HMAC (Client only) + * (Default: SSL_TRUNC_HMAC_ENABLED) + * + * \param ssl SSL context + * \param truncate Enable or disable (SSL_TRUNC_HMAC_ENABLED or + * SSL_TRUNC_HMAC_DISABLED) + * + * \return O if successful, + * POLARSSL_ERR_SSL_BAD_INPUT_DATA if used server-side + */ +int ssl_set_truncated_hmac( ssl_context *ssl, int truncate ); +#endif /* POLARSSL_SSL_TRUNCATED_HMAC */ + +#if defined(POLARSSL_SSL_SESSION_TICKETS) +/** + * \brief Enable / Disable session tickets + * (Default: SSL_SESSION_TICKETS_ENABLED on client, + * SSL_SESSION_TICKETS_DISABLED on server) + * + * \note On server, ssl_set_rng() must be called before this function + * to allow generating the ticket encryption and + * authentication keys. + * + * \param ssl SSL context + * \param use_tickets Enable or disable (SSL_SESSION_TICKETS_ENABLED or + * SSL_SESSION_TICKETS_DISABLED) + * + * \return O if successful, + * or a specific error code (server only). + */ +int ssl_set_session_tickets( ssl_context *ssl, int use_tickets ); + +/** + * \brief Set session ticket lifetime (server only) + * (Default: SSL_DEFAULT_TICKET_LIFETIME (86400 secs / 1 day)) + * + * \param ssl SSL context + * \param lifetime session ticket lifetime + */ +void ssl_set_session_ticket_lifetime( ssl_context *ssl, int lifetime ); +#endif /* POLARSSL_SSL_SESSION_TICKETS */ + +/** + * \brief Enable / Disable renegotiation support for connection when + * initiated by peer + * (Default: SSL_RENEGOTIATION_DISABLED) + * + * Note: A server with support enabled is more vulnerable for a + * resource DoS by a malicious client. You should enable this on + * a client to enable server-initiated renegotiation. + * + * \param ssl SSL context + * \param renegotiation Enable or disable (SSL_RENEGOTIATION_ENABLED or + * SSL_RENEGOTIATION_DISABLED) + */ +void ssl_set_renegotiation( ssl_context *ssl, int renegotiation ); + +/** + * \brief Prevent or allow legacy renegotiation. + * (Default: SSL_LEGACY_NO_RENEGOTIATION) + * + * SSL_LEGACY_NO_RENEGOTIATION allows connections to + * be established even if the peer does not support + * secure renegotiation, but does not allow renegotiation + * to take place if not secure. + * (Interoperable and secure option) + * + * SSL_LEGACY_ALLOW_RENEGOTIATION allows renegotiations + * with non-upgraded peers. Allowing legacy renegotiation + * makes the connection vulnerable to specific man in the + * middle attacks. (See RFC 5746) + * (Most interoperable and least secure option) + * + * SSL_LEGACY_BREAK_HANDSHAKE breaks off connections + * if peer does not support secure renegotiation. Results + * in interoperability issues with non-upgraded peers + * that do not support renegotiation altogether. + * (Most secure option, interoperability issues) + * + * \param ssl SSL context + * \param allow_legacy Prevent or allow (SSL_NO_LEGACY_RENEGOTIATION, + * SSL_ALLOW_LEGACY_RENEGOTIATION or + * SSL_LEGACY_BREAK_HANDSHAKE) + */ +void ssl_legacy_renegotiation( ssl_context *ssl, int allow_legacy ); + +/** + * \brief Enforce server-requested renegotiation. + * (Default: enforced, max_records = 16) + * (No effect on client.) + * + * When a server requests a renegotiation, the client can + * comply or ignore the request. This function allows the + * server to decide if it should enforce its renegotiation + * requests by closing the connection if the client doesn't + * initiate a renegotiation. + * + * However, records could already be in transit from the + * client to the server when the request is emitted. In order + * to increase reliability, the server can accept a number of + * records containing application data before the ClientHello + * that was requested. + * + * The optimal value is highly dependent on the specific usage + * scenario. + * + * \param ssl SSL context + * \param max_records Use SSL_RENEGOTIATION_NOT_ENFORCED if you don't want to + * enforce renegotiation, or a non-negative value to enforce + * it but allow for a grace period of max_records records. + */ +void ssl_set_renegotiation_enforced( ssl_context *ssl, int max_records ); + +/** + * \brief Return the number of data bytes available to read + * + * \param ssl SSL context + * + * \return how many bytes are available in the read buffer + */ +size_t ssl_get_bytes_avail( const ssl_context *ssl ); + +/** + * \brief Return the result of the certificate verification + * + * \param ssl SSL context + * + * \return 0 if successful, or a combination of: + * BADCERT_EXPIRED + * BADCERT_REVOKED + * BADCERT_CN_MISMATCH + * BADCERT_NOT_TRUSTED + */ +int ssl_get_verify_result( const ssl_context *ssl ); + +/** + * \brief Return the name of the current ciphersuite + * + * \param ssl SSL context + * + * \return a string containing the ciphersuite name + */ +const char *ssl_get_ciphersuite( const ssl_context *ssl ); + +/** + * \brief Return the current SSL version (SSLv3/TLSv1/etc) + * + * \param ssl SSL context + * + * \return a string containing the SSL version + */ +const char *ssl_get_version( const ssl_context *ssl ); + +#if defined(POLARSSL_X509_CRT_PARSE_C) +/** + * \brief Return the peer certificate from the current connection + * + * Note: Can be NULL in case no certificate was sent during + * the handshake. Different calls for the same connection can + * return the same or different pointers for the same + * certificate and even a different certificate altogether. + * The peer cert CAN change in a single connection if + * renegotiation is performed. + * + * \param ssl SSL context + * + * \return the current peer certificate + */ +const x509_crt *ssl_get_peer_cert( const ssl_context *ssl ); +#endif /* POLARSSL_X509_CRT_PARSE_C */ + +/** + * \brief Save session in order to resume it later (client-side only) + * Session data is copied to presented session structure. + * + * \warning Currently, peer certificate is lost in the operation. + * + * \param ssl SSL context + * \param session session context + * + * \return 0 if successful, + * POLARSSL_ERR_SSL_MALLOC_FAILED if memory allocation failed, + * POLARSSL_ERR_SSL_BAD_INPUT_DATA if used server-side or + * arguments are otherwise invalid + * + * \sa ssl_set_session() + */ +int ssl_get_session( const ssl_context *ssl, ssl_session *session ); + +/** + * \brief Perform the SSL handshake + * + * \param ssl SSL context + * + * \return 0 if successful, POLARSSL_ERR_NET_WANT_READ, + * POLARSSL_ERR_NET_WANT_WRITE, or a specific SSL error code. + */ +int ssl_handshake( ssl_context *ssl ); + +/** + * \brief Perform a single step of the SSL handshake + * + * Note: the state of the context (ssl->state) will be at + * the following state after execution of this function. + * Do not call this function if state is SSL_HANDSHAKE_OVER. + * + * \param ssl SSL context + * + * \return 0 if successful, POLARSSL_ERR_NET_WANT_READ, + * POLARSSL_ERR_NET_WANT_WRITE, or a specific SSL error code. + */ +int ssl_handshake_step( ssl_context *ssl ); + +/** + * \brief Initiate an SSL renegotiation on the running connection. + * Client: perform the renegotiation right now. + * Server: request renegotiation, which will be performed + * during the next call to ssl_read() if honored by client. + * + * \param ssl SSL context + * + * \return 0 if successful, or any ssl_handshake() return value. + */ +int ssl_renegotiate( ssl_context *ssl ); + +/** + * \brief Read at most 'len' application data bytes + * + * \param ssl SSL context + * \param buf buffer that will hold the data + * \param len how many bytes must be read + * + * \return This function returns the number of bytes read, 0 for EOF, + * or a negative error code. + */ +int ssl_read( ssl_context *ssl, unsigned char *buf, size_t len ); + +/** + * \brief Write exactly 'len' application data bytes + * + * \param ssl SSL context + * \param buf buffer holding the data + * \param len how many bytes must be written + * + * \return This function returns the number of bytes written, + * or a negative error code. + * + * \note When this function returns POLARSSL_ERR_NET_WANT_WRITE, + * it must be called later with the *same* arguments, + * until it returns a positive value. + */ +int ssl_write( ssl_context *ssl, const unsigned char *buf, size_t len ); + +/** + * \brief Send an alert message + * + * \param ssl SSL context + * \param level The alert level of the message + * (SSL_ALERT_LEVEL_WARNING or SSL_ALERT_LEVEL_FATAL) + * \param message The alert message (SSL_ALERT_MSG_*) + * + * \return 0 if successful, or a specific SSL error code. + */ +int ssl_send_alert_message( ssl_context *ssl, + unsigned char level, + unsigned char message ); +/** + * \brief Notify the peer that the connection is being closed + * + * \param ssl SSL context + */ +int ssl_close_notify( ssl_context *ssl ); + +/** + * \brief Free referenced items in an SSL context and clear memory + * + * \param ssl SSL context + */ +void ssl_free( ssl_context *ssl ); + +/** + * \brief Initialize SSL session structure + * + * \param session SSL session + */ +void ssl_session_init( ssl_session *session ); + +/** + * \brief Free referenced items in an SSL session including the + * peer certificate and clear memory + * + * \param session SSL session + */ +void ssl_session_free( ssl_session *session ); + +/** + * \brief Free referenced items in an SSL transform context and clear + * memory + * + * \param transform SSL transform context + */ +void ssl_transform_free( ssl_transform *transform ); + +/** + * \brief Free referenced items in an SSL handshake context and clear + * memory + * + * \param handshake SSL handshake context + */ +void ssl_handshake_free( ssl_handshake_params *handshake ); + +/* + * Internal functions (do not call directly) + */ +int ssl_handshake_client_step( ssl_context *ssl ); +int ssl_handshake_server_step( ssl_context *ssl ); +void ssl_handshake_wrapup( ssl_context *ssl ); + +int ssl_send_fatal_handshake_failure( ssl_context *ssl ); + +int ssl_derive_keys( ssl_context *ssl ); + +int ssl_read_record( ssl_context *ssl ); +/** + * \return 0 if successful, POLARSSL_ERR_SSL_CONN_EOF on EOF or + * another negative error code. + */ +int ssl_fetch_input( ssl_context *ssl, size_t nb_want ); + +int ssl_write_record( ssl_context *ssl ); +int ssl_flush_output( ssl_context *ssl ); + +int ssl_parse_certificate( ssl_context *ssl ); +int ssl_write_certificate( ssl_context *ssl ); + +int ssl_parse_change_cipher_spec( ssl_context *ssl ); +int ssl_write_change_cipher_spec( ssl_context *ssl ); + +int ssl_parse_finished( ssl_context *ssl ); +int ssl_write_finished( ssl_context *ssl ); + +void ssl_optimize_checksum( ssl_context *ssl, + const ssl_ciphersuite_t *ciphersuite_info ); + +#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED) +int ssl_psk_derive_premaster( ssl_context *ssl, key_exchange_type_t key_ex ); +#endif + +#if defined(POLARSSL_PK_C) +unsigned char ssl_sig_from_pk( pk_context *pk ); +pk_type_t ssl_pk_alg_from_sig( unsigned char sig ); +#endif + +md_type_t ssl_md_alg_from_hash( unsigned char hash ); + +#if defined(POLARSSL_SSL_SET_CURVES) +int ssl_curve_is_acceptable( const ssl_context *ssl, ecp_group_id grp_id ); +#endif + +#if defined(POLARSSL_X509_CRT_PARSE_C) +static inline pk_context *ssl_own_key( ssl_context *ssl ) +{ + return( ssl->handshake->key_cert == NULL ? NULL + : ssl->handshake->key_cert->key ); +} + +static inline x509_crt *ssl_own_cert( ssl_context *ssl ) +{ + return( ssl->handshake->key_cert == NULL ? NULL + : ssl->handshake->key_cert->cert ); +} + +/* + * Check usage of a certificate wrt extensions: + * keyUsage, extendedKeyUsage (later), and nSCertType (later). + * + * Warning: cert_endpoint is the endpoint of the cert (ie, of our peer when we + * check a cert we received from them)! + * + * Return 0 if everything is OK, -1 if not. + */ +int ssl_check_cert_usage( const x509_crt *cert, + const ssl_ciphersuite_t *ciphersuite, + int cert_endpoint ); +#endif /* POLARSSL_X509_CRT_PARSE_C */ + +/* constant-time buffer comparison */ +static inline int safer_memcmp( const void *a, const void *b, size_t n ) +{ + size_t i; + const unsigned char *A = (const unsigned char *) a; + const unsigned char *B = (const unsigned char *) b; + unsigned char diff = 0; + + for( i = 0; i < n; i++ ) + diff |= A[i] ^ B[i]; + + return( diff ); +} + +#ifdef __cplusplus +} +#endif + +#endif /* ssl.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/ssl_cache.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/ssl_cache.h new file mode 100644 index 0000000..918fb60 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/ssl_cache.h @@ -0,0 +1,147 @@ +/** + * \file ssl_cache.h + * + * \brief SSL session cache implementation + * + * Copyright (C) 2006-2013, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_SSL_CACHE_H +#define POLARSSL_SSL_CACHE_H + +#include "ssl.h" + +#if defined(POLARSSL_THREADING_C) +#include "threading.h" +#endif + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(SSL_CACHE_DEFAULT_TIMEOUT) +#define SSL_CACHE_DEFAULT_TIMEOUT 86400 /*!< 1 day */ +#endif + +#if !defined(SSL_CACHE_DEFAULT_MAX_ENTRIES) +#define SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /*!< Maximum entries in cache */ +#endif + +/* \} name SECTION: Module settings */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _ssl_cache_context ssl_cache_context; +typedef struct _ssl_cache_entry ssl_cache_entry; + +/** + * \brief This structure is used for storing cache entries + */ +struct _ssl_cache_entry +{ +#if defined(POLARSSL_HAVE_TIME) + time_t timestamp; /*!< entry timestamp */ +#endif + ssl_session session; /*!< entry session */ +#if defined(POLARSSL_X509_CRT_PARSE_C) + x509_buf peer_cert; /*!< entry peer_cert */ +#endif + ssl_cache_entry *next; /*!< chain pointer */ +}; + +/** + * \brief Cache context + */ +struct _ssl_cache_context +{ + ssl_cache_entry *chain; /*!< start of the chain */ + int timeout; /*!< cache entry timeout */ + int max_entries; /*!< maximum entries */ +#if defined(POLARSSL_THREADING_C) + threading_mutex_t mutex; /*!< mutex */ +#endif +}; + +/** + * \brief Initialize an SSL cache context + * + * \param cache SSL cache context + */ +void ssl_cache_init( ssl_cache_context *cache ); + +/** + * \brief Cache get callback implementation + * (Thread-safe if POLARSSL_THREADING_C is enabled) + * + * \param data SSL cache context + * \param session session to retrieve entry for + */ +int ssl_cache_get( void *data, ssl_session *session ); + +/** + * \brief Cache set callback implementation + * (Thread-safe if POLARSSL_THREADING_C is enabled) + * + * \param data SSL cache context + * \param session session to store entry for + */ +int ssl_cache_set( void *data, const ssl_session *session ); + +#if defined(POLARSSL_HAVE_TIME) +/** + * \brief Set the cache timeout + * (Default: SSL_CACHE_DEFAULT_TIMEOUT (1 day)) + * + * A timeout of 0 indicates no timeout. + * + * \param cache SSL cache context + * \param timeout cache entry timeout in seconds + */ +void ssl_cache_set_timeout( ssl_cache_context *cache, int timeout ); +#endif /* POLARSSL_HAVE_TIME */ + +/** + * \brief Set the cache timeout + * (Default: SSL_CACHE_DEFAULT_MAX_ENTRIES (50)) + * + * \param cache SSL cache context + * \param max cache entry maximum + */ +void ssl_cache_set_max_entries( ssl_cache_context *cache, int max ); + +/** + * \brief Free referenced items in a cache context and clear memory + * + * \param cache SSL cache context + */ +void ssl_cache_free( ssl_cache_context *cache ); + +#ifdef __cplusplus +} +#endif + +#endif /* ssl_cache.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/ssl_ciphersuites.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/ssl_ciphersuites.h new file mode 100644 index 0000000..c4f1ffe --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/ssl_ciphersuites.h @@ -0,0 +1,293 @@ +/** + * \file ssl_ciphersuites.h + * + * \brief SSL Ciphersuites for PolarSSL + * + * Copyright (C) 2006-2013, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_SSL_CIPHERSUITES_H +#define POLARSSL_SSL_CIPHERSUITES_H + +#include "pk.h" +#include "cipher.h" +#include "md.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Supported ciphersuites (Official IANA names) + */ +#define TLS_RSA_WITH_NULL_MD5 0x01 /**< Weak! */ +#define TLS_RSA_WITH_NULL_SHA 0x02 /**< Weak! */ + +#define TLS_RSA_WITH_RC4_128_MD5 0x04 +#define TLS_RSA_WITH_RC4_128_SHA 0x05 +#define TLS_RSA_WITH_DES_CBC_SHA 0x09 /**< Weak! Not in TLS 1.2 */ + +#define TLS_RSA_WITH_3DES_EDE_CBC_SHA 0x0A + +#define TLS_DHE_RSA_WITH_DES_CBC_SHA 0x15 /**< Weak! Not in TLS 1.2 */ +#define TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x16 + +#define TLS_PSK_WITH_NULL_SHA 0x2C /**< Weak! */ +#define TLS_DHE_PSK_WITH_NULL_SHA 0x2D /**< Weak! */ +#define TLS_RSA_PSK_WITH_NULL_SHA 0x2E /**< Weak! */ +#define TLS_RSA_WITH_AES_128_CBC_SHA 0x2F + +#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x33 +#define TLS_RSA_WITH_AES_256_CBC_SHA 0x35 +#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x39 + +#define TLS_RSA_WITH_NULL_SHA256 0x3B /**< Weak! */ +#define TLS_RSA_WITH_AES_128_CBC_SHA256 0x3C /**< TLS 1.2 */ +#define TLS_RSA_WITH_AES_256_CBC_SHA256 0x3D /**< TLS 1.2 */ + +#define TLS_RSA_WITH_CAMELLIA_128_CBC_SHA 0x41 +#define TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA 0x45 + +#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x67 /**< TLS 1.2 */ +#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x6B /**< TLS 1.2 */ + +#define TLS_RSA_WITH_CAMELLIA_256_CBC_SHA 0x84 +#define TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA 0x88 + +#define TLS_PSK_WITH_RC4_128_SHA 0x8A +#define TLS_PSK_WITH_3DES_EDE_CBC_SHA 0x8B +#define TLS_PSK_WITH_AES_128_CBC_SHA 0x8C +#define TLS_PSK_WITH_AES_256_CBC_SHA 0x8D + +#define TLS_DHE_PSK_WITH_RC4_128_SHA 0x8E +#define TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA 0x8F +#define TLS_DHE_PSK_WITH_AES_128_CBC_SHA 0x90 +#define TLS_DHE_PSK_WITH_AES_256_CBC_SHA 0x91 + +#define TLS_RSA_PSK_WITH_RC4_128_SHA 0x92 +#define TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA 0x93 +#define TLS_RSA_PSK_WITH_AES_128_CBC_SHA 0x94 +#define TLS_RSA_PSK_WITH_AES_256_CBC_SHA 0x95 + +#define TLS_RSA_WITH_AES_128_GCM_SHA256 0x9C /**< TLS 1.2 */ +#define TLS_RSA_WITH_AES_256_GCM_SHA384 0x9D /**< TLS 1.2 */ +#define TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 0x9E /**< TLS 1.2 */ +#define TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 0x9F /**< TLS 1.2 */ + +#define TLS_PSK_WITH_AES_128_GCM_SHA256 0xA8 /**< TLS 1.2 */ +#define TLS_PSK_WITH_AES_256_GCM_SHA384 0xA9 /**< TLS 1.2 */ +#define TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 0xAA /**< TLS 1.2 */ +#define TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 0xAB /**< TLS 1.2 */ +#define TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 0xAC /**< TLS 1.2 */ +#define TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 0xAD /**< TLS 1.2 */ + +#define TLS_PSK_WITH_AES_128_CBC_SHA256 0xAE +#define TLS_PSK_WITH_AES_256_CBC_SHA384 0xAF +#define TLS_PSK_WITH_NULL_SHA256 0xB0 /**< Weak! */ +#define TLS_PSK_WITH_NULL_SHA384 0xB1 /**< Weak! */ + +#define TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 0xB2 +#define TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 0xB3 +#define TLS_DHE_PSK_WITH_NULL_SHA256 0xB4 /**< Weak! */ +#define TLS_DHE_PSK_WITH_NULL_SHA384 0xB5 /**< Weak! */ + +#define TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 0xB6 +#define TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 0xB7 +#define TLS_RSA_PSK_WITH_NULL_SHA256 0xB8 /**< Weak! */ +#define TLS_RSA_PSK_WITH_NULL_SHA384 0xB9 /**< Weak! */ + +#define TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xBA /**< TLS 1.2 */ +#define TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xBE /**< TLS 1.2 */ + +#define TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC0 /**< TLS 1.2 */ +#define TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC4 /**< TLS 1.2 */ + +#define TLS_ECDH_ECDSA_WITH_NULL_SHA 0xC001 /**< Weak! */ +#define TLS_ECDH_ECDSA_WITH_RC4_128_SHA 0xC002 /**< Not in SSL3! */ +#define TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC003 /**< Not in SSL3! */ +#define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0xC004 /**< Not in SSL3! */ +#define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0xC005 /**< Not in SSL3! */ + +#define TLS_ECDHE_ECDSA_WITH_NULL_SHA 0xC006 /**< Weak! */ +#define TLS_ECDHE_ECDSA_WITH_RC4_128_SHA 0xC007 /**< Not in SSL3! */ +#define TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC008 /**< Not in SSL3! */ +#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC009 /**< Not in SSL3! */ +#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC00A /**< Not in SSL3! */ + +#define TLS_ECDH_RSA_WITH_NULL_SHA 0xC00B /**< Weak! */ +#define TLS_ECDH_RSA_WITH_RC4_128_SHA 0xC00C /**< Not in SSL3! */ +#define TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA 0xC00D /**< Not in SSL3! */ +#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA 0xC00E /**< Not in SSL3! */ +#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 0xC00F /**< Not in SSL3! */ + +#define TLS_ECDHE_RSA_WITH_NULL_SHA 0xC010 /**< Weak! */ +#define TLS_ECDHE_RSA_WITH_RC4_128_SHA 0xC011 /**< Not in SSL3! */ +#define TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 0xC012 /**< Not in SSL3! */ +#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013 /**< Not in SSL3! */ +#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014 /**< Not in SSL3! */ + +#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023 /**< TLS 1.2 */ +#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC024 /**< TLS 1.2 */ +#define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 0xC025 /**< TLS 1.2 */ +#define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 0xC026 /**< TLS 1.2 */ +#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC027 /**< TLS 1.2 */ +#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 0xC028 /**< TLS 1.2 */ +#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 0xC029 /**< TLS 1.2 */ +#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 0xC02A /**< TLS 1.2 */ + +#define TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B /**< TLS 1.2 */ +#define TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xC02C /**< TLS 1.2 */ +#define TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0xC02D /**< TLS 1.2 */ +#define TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 0xC02E /**< TLS 1.2 */ +#define TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F /**< TLS 1.2 */ +#define TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC030 /**< TLS 1.2 */ +#define TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031 /**< TLS 1.2 */ +#define TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 0xC032 /**< TLS 1.2 */ + +#define TLS_ECDHE_PSK_WITH_RC4_128_SHA 0xC033 /**< Not in SSL3! */ +#define TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA 0xC034 /**< Not in SSL3! */ +#define TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA 0xC035 /**< Not in SSL3! */ +#define TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA 0xC036 /**< Not in SSL3! */ +#define TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 0xC037 /**< Not in SSL3! */ +#define TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 0xC038 /**< Not in SSL3! */ +#define TLS_ECDHE_PSK_WITH_NULL_SHA 0xC039 /**< Weak! No SSL3! */ +#define TLS_ECDHE_PSK_WITH_NULL_SHA256 0xC03A /**< Weak! No SSL3! */ +#define TLS_ECDHE_PSK_WITH_NULL_SHA384 0xC03B /**< Weak! No SSL3! */ + +#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC072 /**< Not in SSL3! */ +#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC073 /**< Not in SSL3! */ +#define TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC074 /**< Not in SSL3! */ +#define TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC075 /**< Not in SSL3! */ +#define TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xC076 /**< Not in SSL3! */ +#define TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 0xC077 /**< Not in SSL3! */ +#define TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xC078 /**< Not in SSL3! */ +#define TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 0xC079 /**< Not in SSL3! */ + +#define TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC07A /**< TLS 1.2 */ +#define TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC07B /**< TLS 1.2 */ +#define TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC07C /**< TLS 1.2 */ +#define TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC07D /**< TLS 1.2 */ +#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 0xC086 /**< TLS 1.2 */ +#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 0xC087 /**< TLS 1.2 */ +#define TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 0xC088 /**< TLS 1.2 */ +#define TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 0xC089 /**< TLS 1.2 */ +#define TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC08A /**< TLS 1.2 */ +#define TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC08B /**< TLS 1.2 */ +#define TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC08C /**< TLS 1.2 */ +#define TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC08D /**< TLS 1.2 */ + +#define TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC08E /**< TLS 1.2 */ +#define TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC08F /**< TLS 1.2 */ +#define TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC090 /**< TLS 1.2 */ +#define TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC091 /**< TLS 1.2 */ +#define TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC092 /**< TLS 1.2 */ +#define TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC093 /**< TLS 1.2 */ + +#define TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC094 +#define TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC095 +#define TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC096 +#define TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC097 +#define TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC098 +#define TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC099 +#define TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC09A /**< Not in SSL3! */ +#define TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC09B /**< Not in SSL3! */ + +#define TLS_RSA_WITH_AES_128_CCM 0xC09C /**< TLS 1.2 */ +#define TLS_RSA_WITH_AES_256_CCM 0xC09D /**< TLS 1.2 */ +#define TLS_DHE_RSA_WITH_AES_128_CCM 0xC09E /**< TLS 1.2 */ +#define TLS_DHE_RSA_WITH_AES_256_CCM 0xC09F /**< TLS 1.2 */ +#define TLS_RSA_WITH_AES_128_CCM_8 0xC0A0 /**< TLS 1.2 */ +#define TLS_RSA_WITH_AES_256_CCM_8 0xC0A1 /**< TLS 1.2 */ +#define TLS_DHE_RSA_WITH_AES_128_CCM_8 0xC0A2 /**< TLS 1.2 */ +#define TLS_DHE_RSA_WITH_AES_256_CCM_8 0xC0A3 /**< TLS 1.2 */ +#define TLS_PSK_WITH_AES_128_CCM 0xC0A4 /**< TLS 1.2 */ +#define TLS_PSK_WITH_AES_256_CCM 0xC0A5 /**< TLS 1.2 */ +#define TLS_DHE_PSK_WITH_AES_128_CCM 0xC0A6 /**< TLS 1.2 */ +#define TLS_DHE_PSK_WITH_AES_256_CCM 0xC0A7 /**< TLS 1.2 */ +#define TLS_PSK_WITH_AES_128_CCM_8 0xC0A8 /**< TLS 1.2 */ +#define TLS_PSK_WITH_AES_256_CCM_8 0xC0A9 /**< TLS 1.2 */ +#define TLS_DHE_PSK_WITH_AES_128_CCM_8 0xC0AA /**< TLS 1.2 */ +#define TLS_DHE_PSK_WITH_AES_256_CCM_8 0xC0AB /**< TLS 1.2 */ +/* The last two are named with PSK_DHE in the RFC, which looks like a typo */ + +#define TLS_ECDHE_ECDSA_WITH_AES_128_CCM 0xC0AC /**< TLS 1.2 */ +#define TLS_ECDHE_ECDSA_WITH_AES_256_CCM 0xC0AD /**< TLS 1.2 */ +#define TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 0xC0AE /**< TLS 1.2 */ +#define TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 0xC0AF /**< TLS 1.2 */ + +/* Reminder: update _ssl_premaster_secret when adding a new key exchange */ +typedef enum { + POLARSSL_KEY_EXCHANGE_NONE = 0, + POLARSSL_KEY_EXCHANGE_RSA, + POLARSSL_KEY_EXCHANGE_DHE_RSA, + POLARSSL_KEY_EXCHANGE_ECDHE_RSA, + POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA, + POLARSSL_KEY_EXCHANGE_PSK, + POLARSSL_KEY_EXCHANGE_DHE_PSK, + POLARSSL_KEY_EXCHANGE_RSA_PSK, + POLARSSL_KEY_EXCHANGE_ECDHE_PSK, + POLARSSL_KEY_EXCHANGE_ECDH_RSA, + POLARSSL_KEY_EXCHANGE_ECDH_ECDSA, +} key_exchange_type_t; + +typedef struct _ssl_ciphersuite_t ssl_ciphersuite_t; + +#define POLARSSL_CIPHERSUITE_WEAK 0x01 /**< Weak ciphersuite flag */ +#define POLARSSL_CIPHERSUITE_SHORT_TAG 0x02 /**< Short authentication tag, + eg for CCM_8 */ + +/** + * \brief This structure is used for storing ciphersuite information + */ +struct _ssl_ciphersuite_t +{ + int id; + const char * name; + + cipher_type_t cipher; + md_type_t mac; + key_exchange_type_t key_exchange; + + int min_major_ver; + int min_minor_ver; + int max_major_ver; + int max_minor_ver; + + unsigned char flags; +}; + +const int *ssl_list_ciphersuites( void ); + +const ssl_ciphersuite_t *ssl_ciphersuite_from_string( const char *ciphersuite_name ); +const ssl_ciphersuite_t *ssl_ciphersuite_from_id( int ciphersuite_id ); + +#if defined(POLARSSL_PK_C) +pk_type_t ssl_get_ciphersuite_sig_pk_alg( const ssl_ciphersuite_t *info ); +#endif + +int ssl_ciphersuite_uses_ec( const ssl_ciphersuite_t *info ); +int ssl_ciphersuite_uses_psk( const ssl_ciphersuite_t *info ); + +#ifdef __cplusplus +} +#endif + +#endif /* ssl_ciphersuites.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/threading.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/threading.h new file mode 100644 index 0000000..1fc9f98 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/threading.h @@ -0,0 +1,86 @@ +/** + * \file threading.h + * + * \brief Threading abstraction layer + * + * Copyright (C) 2006-2013, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_THREADING_H +#define POLARSSL_THREADING_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define POLARSSL_ERR_THREADING_FEATURE_UNAVAILABLE -0x001A /**< The selected feature is not available. */ +#define POLARSSL_ERR_THREADING_BAD_INPUT_DATA -0x001C /**< Bad input parameters to function. */ +#define POLARSSL_ERR_THREADING_MUTEX_ERROR -0x001E /**< Locking / unlocking / free failed with error code. */ + +#if defined(POLARSSL_THREADING_PTHREAD) +#include +typedef pthread_mutex_t threading_mutex_t; +#endif + +#if defined(POLARSSL_THREADING_ALT) +/* You should define the threading_mutex_t type in your header */ +#include "threading_alt.h" + +/** + * \brief Set your alternate threading implementation function + * pointers + * + * \param mutex_init the init function implementation + * \param mutex_free the free function implementation + * \param mutex_lock the lock function implementation + * \param mutex_unlock the unlock function implementation + * + * \return 0 if successful + */ +int threading_set_alt( int (*mutex_init)( threading_mutex_t * ), + int (*mutex_free)( threading_mutex_t * ), + int (*mutex_lock)( threading_mutex_t * ), + int (*mutex_unlock)( threading_mutex_t * ) ); +#endif /* POLARSSL_THREADING_ALT_C */ + +/* + * The function pointers for mutex_init, mutex_free, mutex_ and mutex_unlock + * + * All these functions are expected to work or the result will be undefined. + */ +extern int (*polarssl_mutex_init)( threading_mutex_t *mutex ); +extern int (*polarssl_mutex_free)( threading_mutex_t *mutex ); +extern int (*polarssl_mutex_lock)( threading_mutex_t *mutex ); +extern int (*polarssl_mutex_unlock)( threading_mutex_t *mutex ); + +#ifdef __cplusplus +} +#endif + +#endif /* threading.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/timing.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/timing.h new file mode 100644 index 0000000..383120e --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/timing.h @@ -0,0 +1,98 @@ +/** + * \file timing.h + * + * \brief Portable interface to the CPU cycle counter + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_TIMING_H +#define POLARSSL_TIMING_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if !defined(POLARSSL_TIMING_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief timer structure + */ +struct hr_time +{ + unsigned char opaque[32]; +}; + +extern volatile int alarmed; + +/** + * \brief Return the CPU cycle counter value + */ +unsigned long hardclock( void ); + +/** + * \brief Return the elapsed time in milliseconds + * + * \param val points to a timer structure + * \param reset if set to 1, the timer is restarted + */ +unsigned long get_timer( struct hr_time *val, int reset ); + +/** + * \brief Setup an alarm clock + * + * \param seconds delay before the "alarmed" flag is set + */ +void set_alarm( int seconds ); + +/** + * \brief Sleep for a certain amount of time + * + * \param milliseconds delay in milliseconds + */ +void m_sleep( int milliseconds ); + +#if defined(POLARSSL_SELF_TEST) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if a test failed + */ +int timing_self_test( int verbose ); +#endif + +#ifdef __cplusplus +} +#endif + +#else /* POLARSSL_TIMING_ALT */ +#include "timing_alt.h" +#endif /* POLARSSL_TIMING_ALT */ + +#endif /* timing.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/version.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/version.h new file mode 100644 index 0000000..1ee2a3b --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/version.h @@ -0,0 +1,114 @@ +/** + * \file version.h + * + * \brief Run-time version information + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * This set of compile-time defines and run-time variables can be used to + * determine the version number of the PolarSSL library used. + */ +#ifndef POLARSSL_VERSION_H +#define POLARSSL_VERSION_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +/** + * The version number x.y.z is split into three parts. + * Major, Minor, Patchlevel + */ +#define POLARSSL_VERSION_MAJOR 1 +#define POLARSSL_VERSION_MINOR 3 +#define POLARSSL_VERSION_PATCH 8 + +/** + * The single version number has the following structure: + * MMNNPP00 + * Major version | Minor version | Patch version + */ +#define POLARSSL_VERSION_NUMBER 0x01030800 +#define POLARSSL_VERSION_STRING "1.3.8" +#define POLARSSL_VERSION_STRING_FULL "PolarSSL 1.3.8" + +#if defined(POLARSSL_VERSION_C) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Get the version number. + * + * \return The constructed version number in the format + * MMNNPP00 (Major, Minor, Patch). + */ +unsigned int version_get_number( void ); + +/** + * Get the version string ("x.y.z"). + * + * \param string The string that will receive the value. + * (Should be at least 9 bytes in size) + */ +void version_get_string( char *string ); + +/** + * Get the full version string ("PolarSSL x.y.z"). + * + * \param string The string that will receive the value. The PolarSSL version + * string will use 18 bytes AT MOST including a terminating + * null byte. + * (So the buffer should be at least 18 bytes to receive this + * version string). + */ +void version_get_string_full( char *string ); + +/** + * \brief Check if support for a feature was compiled into this + * PolarSSL binary. This allows you to see at runtime if the + * library was for instance compiled with or without + * Multi-threading support. + * + * Note: only checks against defines in the sections "System + * support", "PolarSSL modules" and "PolarSSL feature + * support" in config.h + * + * \param feature The string for the define to check (e.g. "POLARSSL_AES_C") + * + * \return 0 if the feature is present, -1 if the feature is not + * present and -2 if support for feature checking as a whole + * was not compiled in. + */ +int version_check_feature( const char *feature ); + +#ifdef __cplusplus +} +#endif + +#endif /* POLARSSL_VERSION_C */ + +#endif /* version.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/x509.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/x509.h new file mode 100644 index 0000000..583cb83 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/x509.h @@ -0,0 +1,317 @@ +/** + * \file x509.h + * + * \brief X.509 generic defines and structures + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_X509_H +#define POLARSSL_X509_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include "asn1.h" +#include "pk.h" + +#if defined(POLARSSL_RSA_C) +#include "rsa.h" +#endif + +/** + * \addtogroup x509_module + * \{ + */ + +/** + * \name X509 Error codes + * \{ + */ +#define POLARSSL_ERR_X509_FEATURE_UNAVAILABLE -0x2080 /**< Unavailable feature, e.g. RSA hashing/encryption combination. */ +#define POLARSSL_ERR_X509_UNKNOWN_OID -0x2100 /**< Requested OID is unknown. */ +#define POLARSSL_ERR_X509_INVALID_FORMAT -0x2180 /**< The CRT/CRL/CSR format is invalid, e.g. different type expected. */ +#define POLARSSL_ERR_X509_INVALID_VERSION -0x2200 /**< The CRT/CRL/CSR version element is invalid. */ +#define POLARSSL_ERR_X509_INVALID_SERIAL -0x2280 /**< The serial tag or value is invalid. */ +#define POLARSSL_ERR_X509_INVALID_ALG -0x2300 /**< The algorithm tag or value is invalid. */ +#define POLARSSL_ERR_X509_INVALID_NAME -0x2380 /**< The name tag or value is invalid. */ +#define POLARSSL_ERR_X509_INVALID_DATE -0x2400 /**< The date tag or value is invalid. */ +#define POLARSSL_ERR_X509_INVALID_SIGNATURE -0x2480 /**< The signature tag or value invalid. */ +#define POLARSSL_ERR_X509_INVALID_EXTENSIONS -0x2500 /**< The extension tag or value is invalid. */ +#define POLARSSL_ERR_X509_UNKNOWN_VERSION -0x2580 /**< CRT/CRL/CSR has an unsupported version number. */ +#define POLARSSL_ERR_X509_UNKNOWN_SIG_ALG -0x2600 /**< Signature algorithm (oid) is unsupported. */ +#define POLARSSL_ERR_X509_SIG_MISMATCH -0x2680 /**< Signature algorithms do not match. (see \c ::x509_crt sig_oid) */ +#define POLARSSL_ERR_X509_CERT_VERIFY_FAILED -0x2700 /**< Certificate verification failed, e.g. CRL, CA or signature check failed. */ +#define POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT -0x2780 /**< Format not recognized as DER or PEM. */ +#define POLARSSL_ERR_X509_BAD_INPUT_DATA -0x2800 /**< Input invalid. */ +#define POLARSSL_ERR_X509_MALLOC_FAILED -0x2880 /**< Allocation of memory failed. */ +#define POLARSSL_ERR_X509_FILE_IO_ERROR -0x2900 /**< Read/write of file failed. */ +/* \} name */ + +/** + * \name X509 Verify codes + * \{ + */ +#define BADCERT_EXPIRED 0x01 /**< The certificate validity has expired. */ +#define BADCERT_REVOKED 0x02 /**< The certificate has been revoked (is on a CRL). */ +#define BADCERT_CN_MISMATCH 0x04 /**< The certificate Common Name (CN) does not match with the expected CN. */ +#define BADCERT_NOT_TRUSTED 0x08 /**< The certificate is not correctly signed by the trusted CA. */ +#define BADCRL_NOT_TRUSTED 0x10 /**< CRL is not correctly signed by the trusted CA. */ +#define BADCRL_EXPIRED 0x20 /**< CRL is expired. */ +#define BADCERT_MISSING 0x40 /**< Certificate was missing. */ +#define BADCERT_SKIP_VERIFY 0x80 /**< Certificate verification was skipped. */ +#define BADCERT_OTHER 0x0100 /**< Other reason (can be used by verify callback) */ +#define BADCERT_FUTURE 0x0200 /**< The certificate validity starts in the future. */ +#define BADCRL_FUTURE 0x0400 /**< The CRL is from the future */ +/* \} name */ +/* \} addtogroup x509_module */ + +/* + * X.509 v3 Key Usage Extension flags + */ +#define KU_DIGITAL_SIGNATURE (0x80) /* bit 0 */ +#define KU_NON_REPUDIATION (0x40) /* bit 1 */ +#define KU_KEY_ENCIPHERMENT (0x20) /* bit 2 */ +#define KU_DATA_ENCIPHERMENT (0x10) /* bit 3 */ +#define KU_KEY_AGREEMENT (0x08) /* bit 4 */ +#define KU_KEY_CERT_SIGN (0x04) /* bit 5 */ +#define KU_CRL_SIGN (0x02) /* bit 6 */ + +/* + * Netscape certificate types + * (http://www.mozilla.org/projects/security/pki/nss/tech-notes/tn3.html) + */ + +#define NS_CERT_TYPE_SSL_CLIENT (0x80) /* bit 0 */ +#define NS_CERT_TYPE_SSL_SERVER (0x40) /* bit 1 */ +#define NS_CERT_TYPE_EMAIL (0x20) /* bit 2 */ +#define NS_CERT_TYPE_OBJECT_SIGNING (0x10) /* bit 3 */ +#define NS_CERT_TYPE_RESERVED (0x08) /* bit 4 */ +#define NS_CERT_TYPE_SSL_CA (0x04) /* bit 5 */ +#define NS_CERT_TYPE_EMAIL_CA (0x02) /* bit 6 */ +#define NS_CERT_TYPE_OBJECT_SIGNING_CA (0x01) /* bit 7 */ + +/* + * X.509 extension types + * + * Comments refer to the status for using certificates. Status can be + * different for writing certificates or reading CRLs or CSRs. + */ +#define EXT_AUTHORITY_KEY_IDENTIFIER (1 << 0) +#define EXT_SUBJECT_KEY_IDENTIFIER (1 << 1) +#define EXT_KEY_USAGE (1 << 2) /* Parsed but not used */ +#define EXT_CERTIFICATE_POLICIES (1 << 3) +#define EXT_POLICY_MAPPINGS (1 << 4) +#define EXT_SUBJECT_ALT_NAME (1 << 5) /* Supported (DNS) */ +#define EXT_ISSUER_ALT_NAME (1 << 6) +#define EXT_SUBJECT_DIRECTORY_ATTRS (1 << 7) +#define EXT_BASIC_CONSTRAINTS (1 << 8) /* Supported */ +#define EXT_NAME_CONSTRAINTS (1 << 9) +#define EXT_POLICY_CONSTRAINTS (1 << 10) +#define EXT_EXTENDED_KEY_USAGE (1 << 11) /* Parsed but not used */ +#define EXT_CRL_DISTRIBUTION_POINTS (1 << 12) +#define EXT_INIHIBIT_ANYPOLICY (1 << 13) +#define EXT_FRESHEST_CRL (1 << 14) + +#define EXT_NS_CERT_TYPE (1 << 16) /* Parsed (and then ?) */ + +/* + * Storage format identifiers + * Recognized formats: PEM and DER + */ +#define X509_FORMAT_DER 1 +#define X509_FORMAT_PEM 2 + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup x509_module + * \{ */ + +/** + * \name Structures for parsing X.509 certificates, CRLs and CSRs + * \{ + */ + +/** + * Type-length-value structure that allows for ASN1 using DER. + */ +typedef asn1_buf x509_buf; + +/** + * Container for ASN1 bit strings. + */ +typedef asn1_bitstring x509_bitstring; + +/** + * Container for ASN1 named information objects. + * It allows for Relative Distinguished Names (e.g. cn=polarssl,ou=code,etc.). + */ +typedef asn1_named_data x509_name; + +/** + * Container for a sequence of ASN.1 items + */ +typedef asn1_sequence x509_sequence; + +/** Container for date and time (precision in seconds). */ +typedef struct _x509_time +{ + int year, mon, day; /**< Date. */ + int hour, min, sec; /**< Time. */ +} +x509_time; + +/** \} name Structures for parsing X.509 certificates, CRLs and CSRs */ +/** \} addtogroup x509_module */ + +/** + * \brief Store the certificate DN in printable form into buf; + * no more than size characters will be written. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param dn The X509 name to represent + * + * \return The amount of data written to the buffer, or -1 in + * case of an error. + */ +int x509_dn_gets( char *buf, size_t size, const x509_name *dn ); + +/** + * \brief Store the certificate serial in printable form into buf; + * no more than size characters will be written. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param serial The X509 serial to represent + * + * \return The amount of data written to the buffer, or -1 in + * case of an error. + */ +int x509_serial_gets( char *buf, size_t size, const x509_buf *serial ); + +/** + * \brief Give an known OID, return its descriptive string. + * (Deprecated. Use oid_get_extended_key_usage() instead.) + * Warning: only works for extended_key_usage OIDs! + * + * \param oid buffer containing the oid + * + * \return Return a string if the OID is known, + * or NULL otherwise. + */ +const char *x509_oid_get_description( x509_buf *oid ); + +/** + * \brief Give an OID, return a string version of its OID number. + * (Deprecated. Use oid_get_numeric_string() instead) + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param oid Buffer containing the OID + * + * \return Length of the string written (excluding final NULL) or + * POLARSSL_ERR_OID_BUF_TO_SMALL in case of error + */ +int x509_oid_get_numeric_string( char *buf, size_t size, x509_buf *oid ); + +/** + * \brief Check a given x509_time against the system time and check + * if it is not expired. + * + * \param time x509_time to check + * + * \return 0 if the x509_time is still valid, + * 1 otherwise. + */ +int x509_time_expired( const x509_time *time ); + +/** + * \brief Check a given x509_time against the system time and check + * if it is not from the future. + * + * \param time x509_time to check + * + * \return 0 if the x509_time is already valid, + * 1 otherwise. + */ +int x509_time_future( const x509_time *time ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int x509_self_test( int verbose ); + +/* + * Internal module functions. You probably do not want to use these unless you + * know you do. + */ +int x509_get_name( unsigned char **p, const unsigned char *end, + x509_name *cur ); +int x509_get_alg_null( unsigned char **p, const unsigned char *end, + x509_buf *alg ); +int x509_get_alg( unsigned char **p, const unsigned char *end, + x509_buf *alg, x509_buf *params ); +#if defined(POLARSSL_X509_RSASSA_PSS_SUPPORT) +int x509_get_rsassa_pss_params( const x509_buf *params, + md_type_t *md_alg, md_type_t *mgf_md, + int *salt_len ); +#endif +int x509_get_sig( unsigned char **p, const unsigned char *end, x509_buf *sig ); +int x509_get_sig_alg( const x509_buf *sig_oid, const x509_buf *sig_params, + md_type_t *md_alg, pk_type_t *pk_alg, + void **sig_opts ); +int x509_get_time( unsigned char **p, const unsigned char *end, + x509_time *time ); +int x509_get_serial( unsigned char **p, const unsigned char *end, + x509_buf *serial ); +int x509_get_ext( unsigned char **p, const unsigned char *end, + x509_buf *ext, int tag ); +int x509_load_file( const char *path, unsigned char **buf, size_t *n ); +int x509_sig_alg_gets( char *buf, size_t size, const x509_buf *sig_oid, + pk_type_t pk_alg, md_type_t md_alg, + const void *sig_opts ); +int x509_key_size_helper( char *buf, size_t size, const char *name ); +int x509_string_to_names( asn1_named_data **head, const char *name ); +int x509_set_extension( asn1_named_data **head, const char *oid, size_t oid_len, + int critical, const unsigned char *val, + size_t val_len ); +int x509_write_extensions( unsigned char **p, unsigned char *start, + asn1_named_data *first ); +int x509_write_names( unsigned char **p, unsigned char *start, + asn1_named_data *first ); +int x509_write_sig( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len, + unsigned char *sig, size_t size ); + +#ifdef __cplusplus +} +#endif + +#endif /* x509.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/x509_crl.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/x509_crl.h new file mode 100644 index 0000000..9f597a8 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/x509_crl.h @@ -0,0 +1,162 @@ +/** + * \file x509_crl.h + * + * \brief X.509 certificate revocation list parsing + * + * Copyright (C) 2006-2013, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_X509_CRL_H +#define POLARSSL_X509_CRL_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include "x509.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup x509_module + * \{ */ + +/** + * \name Structures and functions for parsing CRLs + * \{ + */ + +/** + * Certificate revocation list entry. + * Contains the CA-specific serial numbers and revocation dates. + */ +typedef struct _x509_crl_entry +{ + x509_buf raw; + + x509_buf serial; + + x509_time revocation_date; + + x509_buf entry_ext; + + struct _x509_crl_entry *next; +} +x509_crl_entry; + +/** + * Certificate revocation list structure. + * Every CRL may have multiple entries. + */ +typedef struct _x509_crl +{ + x509_buf raw; /**< The raw certificate data (DER). */ + x509_buf tbs; /**< The raw certificate body (DER). The part that is To Be Signed. */ + + int version; /**< CRL version (1=v1, 2=v2) */ + x509_buf sig_oid1; + + x509_buf issuer_raw; /**< The raw issuer data (DER). */ + + x509_name issuer; /**< The parsed issuer data (named information object). */ + + x509_time this_update; + x509_time next_update; + + x509_crl_entry entry; /**< The CRL entries containing the certificate revocation times for this CA. */ + + x509_buf crl_ext; + + x509_buf sig_oid2; + x509_buf sig; + md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. POLARSSL_MD_SHA256 */ + pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. POLARSSL_PK_RSA */ + void *sig_opts; /**< Signature options to be passed to pk_verify_ext(), e.g. for RSASSA-PSS */ + + struct _x509_crl *next; +} +x509_crl; + +/** + * \brief Parse one or more CRLs and add them + * to the chained list + * + * \param chain points to the start of the chain + * \param buf buffer holding the CRL data + * \param buflen size of the buffer + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int x509_crl_parse( x509_crl *chain, const unsigned char *buf, size_t buflen ); + +#if defined(POLARSSL_FS_IO) +/** + * \brief Load one or more CRLs and add them + * to the chained list + * + * \param chain points to the start of the chain + * \param path filename to read the CRLs from + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int x509_crl_parse_file( x509_crl *chain, const char *path ); +#endif /* POLARSSL_FS_IO */ + +/** + * \brief Returns an informational string about the CRL. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param crl The X509 CRL to represent + * + * \return The amount of data written to the buffer, or -1 in + * case of an error. + */ +int x509_crl_info( char *buf, size_t size, const char *prefix, + const x509_crl *crl ); + +/** + * \brief Initialize a CRL (chain) + * + * \param crl CRL chain to initialize + */ +void x509_crl_init( x509_crl *crl ); + +/** + * \brief Unallocate all CRL data + * + * \param crl CRL chain to free + */ +void x509_crl_free( x509_crl *crl ); + +/* \} name */ +/* \} addtogroup x509_module */ + +#ifdef __cplusplus +} +#endif + +#endif /* x509_crl.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/x509_crt.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/x509_crt.h new file mode 100644 index 0000000..4bf8e56 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/x509_crt.h @@ -0,0 +1,558 @@ +/** + * \file x509_crt.h + * + * \brief X.509 certificate parsing and writing + * + * Copyright (C) 2006-2013, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_X509_CRT_H +#define POLARSSL_X509_CRT_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include "x509.h" + +#include "x509_crl.h" + +/** + * \addtogroup x509_module + * \{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name Structures and functions for parsing and writing X.509 certificates + * \{ + */ + +/** + * Container for an X.509 certificate. The certificate may be chained. + */ +typedef struct _x509_crt +{ + x509_buf raw; /**< The raw certificate data (DER). */ + x509_buf tbs; /**< The raw certificate body (DER). The part that is To Be Signed. */ + + int version; /**< The X.509 version. (1=v1, 2=v2, 3=v3) */ + x509_buf serial; /**< Unique id for certificate issued by a specific CA. */ + x509_buf sig_oid1; /**< Signature algorithm, e.g. sha1RSA */ + + x509_buf issuer_raw; /**< The raw issuer data (DER). Used for quick comparison. */ + x509_buf subject_raw; /**< The raw subject data (DER). Used for quick comparison. */ + + x509_name issuer; /**< The parsed issuer data (named information object). */ + x509_name subject; /**< The parsed subject data (named information object). */ + + x509_time valid_from; /**< Start time of certificate validity. */ + x509_time valid_to; /**< End time of certificate validity. */ + + pk_context pk; /**< Container for the public key context. */ + + x509_buf issuer_id; /**< Optional X.509 v2/v3 issuer unique identifier. */ + x509_buf subject_id; /**< Optional X.509 v2/v3 subject unique identifier. */ + x509_buf v3_ext; /**< Optional X.509 v3 extensions. */ + x509_sequence subject_alt_names; /**< Optional list of Subject Alternative Names (Only dNSName supported). */ + + int ext_types; /**< Bit string containing detected and parsed extensions */ + int ca_istrue; /**< Optional Basic Constraint extension value: 1 if this certificate belongs to a CA, 0 otherwise. */ + int max_pathlen; /**< Optional Basic Constraint extension value: The maximum path length to the root certificate. Path length is 1 higher than RFC 5280 'meaning', so 1+ */ + + unsigned char key_usage; /**< Optional key usage extension value: See the values in x509.h */ + + x509_sequence ext_key_usage; /**< Optional list of extended key usage OIDs. */ + + unsigned char ns_cert_type; /**< Optional Netscape certificate type extension value: See the values in x509.h */ + + x509_buf sig_oid2; /**< Signature algorithm. Must match sig_oid1. */ + x509_buf sig; /**< Signature: hash of the tbs part signed with the private key. */ + md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. POLARSSL_MD_SHA256 */ + pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. POLARSSL_PK_RSA */ + void *sig_opts; /**< Signature options to be passed to pk_verify_ext(), e.g. for RSASSA-PSS */ + + struct _x509_crt *next; /**< Next certificate in the CA-chain. */ +} +x509_crt; + +#define X509_CRT_VERSION_1 0 +#define X509_CRT_VERSION_2 1 +#define X509_CRT_VERSION_3 2 + +#define X509_RFC5280_MAX_SERIAL_LEN 32 +#define X509_RFC5280_UTC_TIME_LEN 15 + +/** + * Container for writing a certificate (CRT) + */ +typedef struct _x509write_cert +{ + int version; + mpi serial; + pk_context *subject_key; + pk_context *issuer_key; + asn1_named_data *subject; + asn1_named_data *issuer; + md_type_t md_alg; + char not_before[X509_RFC5280_UTC_TIME_LEN + 1]; + char not_after[X509_RFC5280_UTC_TIME_LEN + 1]; + asn1_named_data *extensions; +} +x509write_cert; + +#if defined(POLARSSL_X509_CRT_PARSE_C) +/** + * \brief Parse a single DER formatted certificate and add it + * to the chained list. + * + * \param chain points to the start of the chain + * \param buf buffer holding the certificate DER data + * \param buflen size of the buffer + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int x509_crt_parse_der( x509_crt *chain, const unsigned char *buf, + size_t buflen ); + +/** + * \brief Parse one or more certificates and add them + * to the chained list. Parses permissively. If some + * certificates can be parsed, the result is the number + * of failed certificates it encountered. If none complete + * correctly, the first error is returned. + * + * \param chain points to the start of the chain + * \param buf buffer holding the certificate data + * \param buflen size of the buffer + * + * \return 0 if all certificates parsed successfully, a positive number + * if partly successful or a specific X509 or PEM error code + */ +int x509_crt_parse( x509_crt *chain, const unsigned char *buf, size_t buflen ); + +#if defined(POLARSSL_FS_IO) +/** + * \brief Load one or more certificates and add them + * to the chained list. Parses permissively. If some + * certificates can be parsed, the result is the number + * of failed certificates it encountered. If none complete + * correctly, the first error is returned. + * + * \param chain points to the start of the chain + * \param path filename to read the certificates from + * + * \return 0 if all certificates parsed successfully, a positive number + * if partly successful or a specific X509 or PEM error code + */ +int x509_crt_parse_file( x509_crt *chain, const char *path ); + +/** + * \brief Load one or more certificate files from a path and add them + * to the chained list. Parses permissively. If some + * certificates can be parsed, the result is the number + * of failed certificates it encountered. If none complete + * correctly, the first error is returned. + * + * \warning This function is NOT thread-safe unless + * POLARSSL_THREADING_PTHREADS is defined. If you're using an + * alternative threading implementation, you should either use + * this function only in the main thread, or mutex it. + * + * \param chain points to the start of the chain + * \param path directory / folder to read the certificate files from + * + * \return 0 if all certificates parsed successfully, a positive number + * if partly successful or a specific X509 or PEM error code + */ +int x509_crt_parse_path( x509_crt *chain, const char *path ); +#endif /* POLARSSL_FS_IO */ + +/** + * \brief Returns an informational string about the + * certificate. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param crt The X509 certificate to represent + * + * \return The amount of data written to the buffer, or -1 in + * case of an error. + */ +int x509_crt_info( char *buf, size_t size, const char *prefix, + const x509_crt *crt ); + +/** + * \brief Verify the certificate signature + * + * The verify callback is a user-supplied callback that + * can clear / modify / add flags for a certificate. If set, + * the verification callback is called for each + * certificate in the chain (from the trust-ca down to the + * presented crt). The parameters for the callback are: + * (void *parameter, x509_crt *crt, int certificate_depth, + * int *flags). With the flags representing current flags for + * that specific certificate and the certificate depth from + * the bottom (Peer cert depth = 0). + * + * All flags left after returning from the callback + * are also returned to the application. The function should + * return 0 for anything but a fatal error. + * + * \param crt a certificate to be verified + * \param trust_ca the trusted CA chain + * \param ca_crl the CRL chain for trusted CA's + * \param cn expected Common Name (can be set to + * NULL if the CN must not be verified) + * \param flags result of the verification + * \param f_vrfy verification function + * \param p_vrfy verification parameter + * + * \return 0 if successful or POLARSSL_ERR_X509_SIG_VERIFY_FAILED, + * in which case *flags will have one or more of + * the following values set: + * BADCERT_EXPIRED -- + * BADCERT_REVOKED -- + * BADCERT_CN_MISMATCH -- + * BADCERT_NOT_TRUSTED + * or another error in case of a fatal error encountered + * during the verification process. + */ +int x509_crt_verify( x509_crt *crt, + x509_crt *trust_ca, + x509_crl *ca_crl, + const char *cn, int *flags, + int (*f_vrfy)(void *, x509_crt *, int, int *), + void *p_vrfy ); + +#if defined(POLARSSL_X509_CHECK_KEY_USAGE) +/** + * \brief Check usage of certificate against keyUsage extension. + * + * \param crt Leaf certificate used. + * \param usage Intended usage(s) (eg KU_KEY_ENCIPHERMENT before using the + * certificate to perform an RSA key exchange). + * + * \return 0 is these uses of the certificate are allowed, + * POLARSSL_ERR_X509_BAD_INPUT_DATA if the keyUsage extension + * is present but does not contain all the bits set in the + * usage argument. + * + * \note You should only call this function on leaf certificates, on + * (intermediate) CAs the keyUsage extension is automatically + * checked by \c x509_crt_verify(). + */ +int x509_crt_check_key_usage( const x509_crt *crt, int usage ); +#endif /* POLARSSL_X509_CHECK_KEY_USAGE) */ + +#if defined(POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE) +/** + * \brief Check usage of certificate against extentedJeyUsage. + * + * \param crt Leaf certificate used. + * \param usage_oid Intended usage (eg OID_SERVER_AUTH or OID_CLIENT_AUTH). + * \param usage_len Length of usage_oid (eg given by OID_SIZE()). + * + * \return 0 is this use of the certificate is allowed, + * POLARSSL_ERR_X509_BAD_INPUT_DATA if not. + * + * \note Usually only makes sense on leaf certificates. + */ +int x509_crt_check_extended_key_usage( const x509_crt *crt, + const char *usage_oid, + size_t usage_len ); +#endif /* POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE) */ + +#if defined(POLARSSL_X509_CRL_PARSE_C) +/** + * \brief Verify the certificate revocation status + * + * \param crt a certificate to be verified + * \param crl the CRL to verify against + * + * \return 1 if the certificate is revoked, 0 otherwise + * + */ +int x509_crt_revoked( const x509_crt *crt, const x509_crl *crl ); +#endif /* POLARSSL_X509_CRL_PARSE_C */ + +/** + * \brief Initialize a certificate (chain) + * + * \param crt Certificate chain to initialize + */ +void x509_crt_init( x509_crt *crt ); + +/** + * \brief Unallocate all certificate data + * + * \param crt Certificate chain to free + */ +void x509_crt_free( x509_crt *crt ); +#endif /* POLARSSL_X509_CRT_PARSE_C */ + +/* \} name */ +/* \} addtogroup x509_module */ + +#if defined(POLARSSL_X509_CRT_WRITE_C) +/** + * \brief Initialize a CRT writing context + * + * \param ctx CRT context to initialize + */ +void x509write_crt_init( x509write_cert *ctx ); + +/** + * \brief Set the verion for a Certificate + * Default: X509_CRT_VERSION_3 + * + * \param ctx CRT context to use + * \param version version to set (X509_CRT_VERSION_1, X509_CRT_VERSION_2 or + * X509_CRT_VERSION_3) + */ +void x509write_crt_set_version( x509write_cert *ctx, int version ); + +/** + * \brief Set the serial number for a Certificate. + * + * \param ctx CRT context to use + * \param serial serial number to set + * + * \return 0 if successful + */ +int x509write_crt_set_serial( x509write_cert *ctx, const mpi *serial ); + +/** + * \brief Set the validity period for a Certificate + * Timestamps should be in string format for UTC timezone + * i.e. "YYYYMMDDhhmmss" + * e.g. "20131231235959" for December 31st 2013 + * at 23:59:59 + * + * \param ctx CRT context to use + * \param not_before not_before timestamp + * \param not_after not_after timestamp + * + * \return 0 if timestamp was parsed successfully, or + * a specific error code + */ +int x509write_crt_set_validity( x509write_cert *ctx, const char *not_before, + const char *not_after ); + +/** + * \brief Set the issuer name for a Certificate + * Issuer names should contain a comma-separated list + * of OID types and values: + * e.g. "C=NL,O=Offspark,CN=PolarSSL CA" + * + * \param ctx CRT context to use + * \param issuer_name issuer name to set + * + * \return 0 if issuer name was parsed successfully, or + * a specific error code + */ +int x509write_crt_set_issuer_name( x509write_cert *ctx, + const char *issuer_name ); + +/** + * \brief Set the subject name for a Certificate + * Subject names should contain a comma-separated list + * of OID types and values: + * e.g. "C=NL,O=Offspark,CN=PolarSSL Server 1" + * + * \param ctx CRT context to use + * \param subject_name subject name to set + * + * \return 0 if subject name was parsed successfully, or + * a specific error code + */ +int x509write_crt_set_subject_name( x509write_cert *ctx, + const char *subject_name ); + +/** + * \brief Set the subject public key for the certificate + * + * \param ctx CRT context to use + * \param key public key to include + */ +void x509write_crt_set_subject_key( x509write_cert *ctx, pk_context *key ); + +/** + * \brief Set the issuer key used for signing the certificate + * + * \param ctx CRT context to use + * \param key private key to sign with + */ +void x509write_crt_set_issuer_key( x509write_cert *ctx, pk_context *key ); + +/** + * \brief Set the MD algorithm to use for the signature + * (e.g. POLARSSL_MD_SHA1) + * + * \param ctx CRT context to use + * \param md_alg MD algorithm to use + */ +void x509write_crt_set_md_alg( x509write_cert *ctx, md_type_t md_alg ); + +/** + * \brief Generic function to add to or replace an extension in the + * CRT + * + * \param ctx CRT context to use + * \param oid OID of the extension + * \param oid_len length of the OID + * \param critical if the extension is critical (per the RFC's definition) + * \param val value of the extension OCTET STRING + * \param val_len length of the value data + * + * \return 0 if successful, or a POLARSSL_ERR_X509WRITE_MALLOC_FAILED + */ +int x509write_crt_set_extension( x509write_cert *ctx, + const char *oid, size_t oid_len, + int critical, + const unsigned char *val, size_t val_len ); + +/** + * \brief Set the basicConstraints extension for a CRT + * + * \param ctx CRT context to use + * \param is_ca is this a CA certificate + * \param max_pathlen maximum length of certificate chains below this + * certificate (only for CA certificates, -1 is + * inlimited) + * + * \return 0 if successful, or a POLARSSL_ERR_X509WRITE_MALLOC_FAILED + */ +int x509write_crt_set_basic_constraints( x509write_cert *ctx, + int is_ca, int max_pathlen ); + +#if defined(POLARSSL_SHA1_C) +/** + * \brief Set the subjectKeyIdentifier extension for a CRT + * Requires that x509write_crt_set_subject_key() has been + * called before + * + * \param ctx CRT context to use + * + * \return 0 if successful, or a POLARSSL_ERR_X509WRITE_MALLOC_FAILED + */ +int x509write_crt_set_subject_key_identifier( x509write_cert *ctx ); + +/** + * \brief Set the authorityKeyIdentifier extension for a CRT + * Requires that x509write_crt_set_issuer_key() has been + * called before + * + * \param ctx CRT context to use + * + * \return 0 if successful, or a POLARSSL_ERR_X509WRITE_MALLOC_FAILED + */ +int x509write_crt_set_authority_key_identifier( x509write_cert *ctx ); +#endif /* POLARSSL_SHA1_C */ + +/** + * \brief Set the Key Usage Extension flags + * (e.g. KU_DIGITAL_SIGNATURE | KU_KEY_CERT_SIGN) + * + * \param ctx CRT context to use + * \param key_usage key usage flags to set + * + * \return 0 if successful, or POLARSSL_ERR_X509WRITE_MALLOC_FAILED + */ +int x509write_crt_set_key_usage( x509write_cert *ctx, unsigned char key_usage ); + +/** + * \brief Set the Netscape Cert Type flags + * (e.g. NS_CERT_TYPE_SSL_CLIENT | NS_CERT_TYPE_EMAIL) + * + * \param ctx CRT context to use + * \param ns_cert_type Netscape Cert Type flags to set + * + * \return 0 if successful, or POLARSSL_ERR_X509WRITE_MALLOC_FAILED + */ +int x509write_crt_set_ns_cert_type( x509write_cert *ctx, + unsigned char ns_cert_type ); + +/** + * \brief Free the contents of a CRT write context + * + * \param ctx CRT context to free + */ +void x509write_crt_free( x509write_cert *ctx ); + +/** + * \brief Write a built up certificate to a X509 DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx certificate to write away + * \param buf buffer to write to + * \param size size of the buffer + * \param f_rng RNG function (for signature, see note) + * \param p_rng RNG parameter + * + * \return length of data written if successful, or a specific + * error code + * + * \note f_rng may be NULL if RSA is used for signature and the + * signature is made offline (otherwise f_rng is desirable + * for countermeasures against timing attacks). + * ECDSA signatures always require a non-NULL f_rng. + */ +int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#if defined(POLARSSL_PEM_WRITE_C) +/** + * \brief Write a built up certificate to a X509 PEM string + * + * \param ctx certificate to write away + * \param buf buffer to write to + * \param size size of the buffer + * \param f_rng RNG function (for signature, see note) + * \param p_rng RNG parameter + * + * \return 0 successful, or a specific error code + * + * \note f_rng may be NULL if RSA is used for signature and the + * signature is made offline (otherwise f_rng is desirable + * for countermeasures against timing attacks). + * ECDSA signatures always require a non-NULL f_rng. + */ +int x509write_crt_pem( x509write_cert *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +#endif /* POLARSSL_PEM_WRITE_C */ +#endif /* POLARSSL_X509_CRT_WRITE_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* x509_crt.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/x509_csr.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/x509_csr.h new file mode 100644 index 0000000..6591e38 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/x509_csr.h @@ -0,0 +1,295 @@ +/** + * \file x509_csr.h + * + * \brief X.509 certificate signing request parsing and writing + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_X509_CSR_H +#define POLARSSL_X509_CSR_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include "x509.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup x509_module + * \{ */ + +/** + * \name Structures and functions for X.509 Certificate Signing Requests (CSR) + * \{ + */ + +/** + * Certificate Signing Request (CSR) structure. + */ +typedef struct _x509_csr +{ + x509_buf raw; /**< The raw CSR data (DER). */ + x509_buf cri; /**< The raw CertificateRequestInfo body (DER). */ + + int version; /**< CSR version (1=v1). */ + + x509_buf subject_raw; /**< The raw subject data (DER). */ + x509_name subject; /**< The parsed subject data (named information object). */ + + pk_context pk; /**< Container for the public key context. */ + + x509_buf sig_oid; + x509_buf sig; + md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. POLARSSL_MD_SHA256 */ + pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. POLARSSL_PK_RSA */ + void *sig_opts; /**< Signature options to be passed to pk_verify_ext(), e.g. for RSASSA-PSS */ +} +x509_csr; + +/** + * Container for writing a CSR + */ +typedef struct _x509write_csr +{ + pk_context *key; + asn1_named_data *subject; + md_type_t md_alg; + asn1_named_data *extensions; +} +x509write_csr; + +#if defined(POLARSSL_X509_CSR_PARSE_C) +/** + * \brief Load a Certificate Signing Request (CSR) in DER format + * + * \param csr CSR context to fill + * \param buf buffer holding the CRL data + * \param buflen size of the buffer + * + * \return 0 if successful, or a specific X509 error code + */ +int x509_csr_parse_der( x509_csr *csr, + const unsigned char *buf, size_t buflen ); + +/** + * \brief Load a Certificate Signing Request (CSR), DER or PEM format + * + * \param csr CSR context to fill + * \param buf buffer holding the CRL data + * \param buflen size of the buffer + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int x509_csr_parse( x509_csr *csr, const unsigned char *buf, size_t buflen ); + +#if defined(POLARSSL_FS_IO) +/** + * \brief Load a Certificate Signing Request (CSR) + * + * \param csr CSR context to fill + * \param path filename to read the CSR from + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int x509_csr_parse_file( x509_csr *csr, const char *path ); +#endif /* POLARSSL_FS_IO */ + +/** + * \brief Returns an informational string about the + * CSR. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param csr The X509 CSR to represent + * + * \return The length of the string written (exluding the terminating + * null byte), or a negative value in case of an error. + */ +int x509_csr_info( char *buf, size_t size, const char *prefix, + const x509_csr *csr ); + +/** + * \brief Initialize a CSR + * + * \param csr CSR to initialize + */ +void x509_csr_init( x509_csr *csr ); + +/** + * \brief Unallocate all CSR data + * + * \param csr CSR to free + */ +void x509_csr_free( x509_csr *csr ); +#endif /* POLARSSL_X509_CSR_PARSE_C */ + +/* \} name */ +/* \} addtogroup x509_module */ + +#if defined(POLARSSL_X509_CSR_WRITE_C) +/** + * \brief Initialize a CSR context + * + * \param ctx CSR context to initialize + */ +void x509write_csr_init( x509write_csr *ctx ); + +/** + * \brief Set the subject name for a CSR + * Subject names should contain a comma-separated list + * of OID types and values: + * e.g. "C=NL,O=Offspark,CN=PolarSSL Server 1" + * + * \param ctx CSR context to use + * \param subject_name subject name to set + * + * \return 0 if subject name was parsed successfully, or + * a specific error code + */ +int x509write_csr_set_subject_name( x509write_csr *ctx, + const char *subject_name ); + +/** + * \brief Set the key for a CSR (public key will be included, + * private key used to sign the CSR when writing it) + * + * \param ctx CSR context to use + * \param key Asymetric key to include + */ +void x509write_csr_set_key( x509write_csr *ctx, pk_context *key ); + +/** + * \brief Set the MD algorithm to use for the signature + * (e.g. POLARSSL_MD_SHA1) + * + * \param ctx CSR context to use + * \param md_alg MD algorithm to use + */ +void x509write_csr_set_md_alg( x509write_csr *ctx, md_type_t md_alg ); + +/** + * \brief Set the Key Usage Extension flags + * (e.g. KU_DIGITAL_SIGNATURE | KU_KEY_CERT_SIGN) + * + * \param ctx CSR context to use + * \param key_usage key usage flags to set + * + * \return 0 if successful, or POLARSSL_ERR_X509WRITE_MALLOC_FAILED + */ +int x509write_csr_set_key_usage( x509write_csr *ctx, unsigned char key_usage ); + +/** + * \brief Set the Netscape Cert Type flags + * (e.g. NS_CERT_TYPE_SSL_CLIENT | NS_CERT_TYPE_EMAIL) + * + * \param ctx CSR context to use + * \param ns_cert_type Netscape Cert Type flags to set + * + * \return 0 if successful, or POLARSSL_ERR_X509WRITE_MALLOC_FAILED + */ +int x509write_csr_set_ns_cert_type( x509write_csr *ctx, + unsigned char ns_cert_type ); + +/** + * \brief Generic function to add to or replace an extension in the + * CSR + * + * \param ctx CSR context to use + * \param oid OID of the extension + * \param oid_len length of the OID + * \param val value of the extension OCTET STRING + * \param val_len length of the value data + * + * \return 0 if successful, or a POLARSSL_ERR_X509WRITE_MALLOC_FAILED + */ +int x509write_csr_set_extension( x509write_csr *ctx, + const char *oid, size_t oid_len, + const unsigned char *val, size_t val_len ); + +/** + * \brief Free the contents of a CSR context + * + * \param ctx CSR context to free + */ +void x509write_csr_free( x509write_csr *ctx ); + +/** + * \brief Write a CSR (Certificate Signing Request) to a + * DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx CSR to write away + * \param buf buffer to write to + * \param size size of the buffer + * \param f_rng RNG function (for signature, see note) + * \param p_rng RNG parameter + * + * \return length of data written if successful, or a specific + * error code + * + * \note f_rng may be NULL if RSA is used for signature and the + * signature is made offline (otherwise f_rng is desirable + * for countermeasures against timing attacks). + * ECDSA signatures always require a non-NULL f_rng. + */ +int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#if defined(POLARSSL_PEM_WRITE_C) +/** + * \brief Write a CSR (Certificate Signing Request) to a + * PEM string + * + * \param ctx CSR to write away + * \param buf buffer to write to + * \param size size of the buffer + * \param f_rng RNG function (for signature, see note) + * \param p_rng RNG parameter + * + * \return 0 successful, or a specific error code + * + * \note f_rng may be NULL if RSA is used for signature and the + * signature is made offline (otherwise f_rng is desirable + * for couermeasures against timing attacks). + * ECDSA signatures always require a non-NULL f_rng. + */ +int x509write_csr_pem( x509write_csr *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +#endif /* POLARSSL_PEM_WRITE_C */ +#endif /* POLARSSL_X509_CSR_WRITE_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* x509_csr.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/include/polarssl/xtea.h b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/xtea.h new file mode 100644 index 0000000..794c5ef --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/include/polarssl/xtea.h @@ -0,0 +1,149 @@ +/** + * \file xtea.h + * + * \brief XTEA block cipher (32-bit) + * + * Copyright (C) 2006-2013, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_XTEA_H +#define POLARSSL_XTEA_H + +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#include + +#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32) +#include +typedef UINT32 uint32_t; +#else +#include +#endif + +#define XTEA_ENCRYPT 1 +#define XTEA_DECRYPT 0 + +#define POLARSSL_ERR_XTEA_INVALID_INPUT_LENGTH -0x0028 /**< The data input has an invalid length. */ + +#if !defined(POLARSSL_XTEA_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief XTEA context structure + */ +typedef struct +{ + uint32_t k[4]; /*!< key */ +} +xtea_context; + +/** + * \brief Initialize XTEA context + * + * \param ctx XTEA context to be initialized + */ +void xtea_init( xtea_context *ctx ); + +/** + * \brief Clear XTEA context + * + * \param ctx XTEA context to be cleared + */ +void xtea_free( xtea_context *ctx ); + +/** + * \brief XTEA key schedule + * + * \param ctx XTEA context to be initialized + * \param key the secret key + */ +void xtea_setup( xtea_context *ctx, const unsigned char key[16] ); + +/** + * \brief XTEA cipher function + * + * \param ctx XTEA context + * \param mode XTEA_ENCRYPT or XTEA_DECRYPT + * \param input 8-byte input block + * \param output 8-byte output block + * + * \return 0 if successful + */ +int xtea_crypt_ecb( xtea_context *ctx, + int mode, + const unsigned char input[8], + unsigned char output[8] ); + +#if defined(POLARSSL_CIPHER_MODE_CBC) +/** + * \brief XTEA CBC cipher function + * + * \param ctx XTEA context + * \param mode XTEA_ENCRYPT or XTEA_DECRYPT + * \param length the length of input, multiple of 8 + * \param iv initialization vector for CBC mode + * \param input input block + * \param output output block + * + * \return 0 if successful, + * POLARSSL_ERR_XTEA_INVALID_INPUT_LENGTH if the length % 8 != 0 + */ +int xtea_crypt_cbc( xtea_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output); +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#ifdef __cplusplus +} +#endif + +#else /* POLARSSL_XTEA_ALT */ +#include "xtea_alt.h" +#endif /* POLARSSL_XTEA_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int xtea_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* xtea.h */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/.gitignore b/component/common/network/ssl/polarssl-1.3.8/library/.gitignore new file mode 100644 index 0000000..9d80fa4 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/.gitignore @@ -0,0 +1,2 @@ +*.o +libpolarssl* diff --git a/component/common/network/ssl/polarssl-1.3.8/library/CMakeLists.txt b/component/common/network/ssl/polarssl-1.3.8/library/CMakeLists.txt new file mode 100644 index 0000000..bc986ee --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/CMakeLists.txt @@ -0,0 +1,136 @@ +option(USE_STATIC_POLARSSL_LIBRARY "Build PolarSSL static library." ON) +option(USE_SHARED_POLARSSL_LIBRARY "Build PolarSSL shared library." OFF) +option(LINK_WITH_PTHREAD "Explicitly link PolarSSL library to pthread." OFF) + +set(src + aes.c + aesni.c + arc4.c + asn1parse.c + asn1write.c + base64.c + bignum.c + blowfish.c + camellia.c + ccm.c + certs.c + cipher.c + cipher_wrap.c + ctr_drbg.c + debug.c + des.c + dhm.c + ecp.c + ecp_curves.c + ecdh.c + ecdsa.c + entropy.c + entropy_poll.c + error.c + gcm.c + havege.c + hmac_drbg.c + md.c + md_wrap.c + md2.c + md4.c + md5.c + memory_buffer_alloc.c + net.c + oid.c + padlock.c + pbkdf2.c + pem.c + pkcs5.c + pkcs11.c + pkcs12.c + pk.c + pk_wrap.c + pkparse.c + pkwrite.c + platform.c + ripemd160.c + rsa.c + sha1.c + sha256.c + sha512.c + ssl_cache.c + ssl_ciphersuites.c + ssl_cli.c + ssl_srv.c + ssl_tls.c + threading.c + timing.c + version.c + version_features.c + x509.c + x509_crt.c + x509_crl.c + x509_csr.c + x509_create.c + x509write_crt.c + x509write_csr.c + xtea.c +) + +if(WIN32) +set(libs ws2_32) +endif(WIN32) + +if(CMAKE_COMPILER_IS_GNUCC) + set(CMAKE_C_FLAGS_CHECK "${CMAKE_C_FLAGS_CHECK} -Wmissing-declarations -Wmissing-prototypes") + set(CMAKE_C_FLAGS_CHECKFULL "${CMAKE_C_FLAGS_CHECK} -Wcast-qual") +endif(CMAKE_COMPILER_IS_GNUCC) + +if(CMAKE_COMPILER_IS_CLANG) + set(CMAKE_C_FLAGS_CHECK "${CMAKE_C_FLAGS_CHECK} -Wmissing-declarations -Wmissing-prototypes") +endif(CMAKE_COMPILER_IS_CLANG) + +if (NOT USE_STATIC_POLARSSL_LIBRARY AND NOT USE_SHARED_POLARSSL_LIBRARY) + message(FATAL_ERROR "Need to choose static or shared polarssl build!") +endif(NOT USE_STATIC_POLARSSL_LIBRARY AND NOT USE_SHARED_POLARSSL_LIBRARY) + +if(USE_STATIC_POLARSSL_LIBRARY AND USE_SHARED_POLARSSL_LIBRARY) + # if we build both static an shared, then let + # tests and programs link to the shared lib target + set(polarssl_static_target "polarssl_static") +elseif(USE_STATIC_POLARSSL_LIBRARY) + set(polarssl_static_target "polarssl") +endif() + +if(USE_STATIC_POLARSSL_LIBRARY) + add_library(${polarssl_static_target} STATIC ${src}) + set_target_properties(${polarssl_static_target} PROPERTIES OUTPUT_NAME polarssl) + target_link_libraries(${polarssl_static_target} ${libs}) + + if(ZLIB_FOUND) + target_link_libraries(${polarssl_static_target} ${ZLIB_LIBRARIES}) + endif(ZLIB_FOUND) + + if(LINK_WITH_PTHREAD) + target_link_libraries(${polarssl_static_target} pthread) + endif() + + install(TARGETS ${polarssl_static_target} + DESTINATION ${LIB_INSTALL_DIR} + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) +endif() + +if(USE_SHARED_POLARSSL_LIBRARY) + add_library(polarssl SHARED ${src}) + set_target_properties(polarssl PROPERTIES VERSION 1.3.8 SOVERSION 7) + + target_link_libraries(polarssl ${libs}) + + if(ZLIB_FOUND) + target_link_libraries(polarssl ${ZLIB_LIBRARIES}) + endif(ZLIB_FOUND) + + if(LINK_WITH_PTHREAD) + target_link_libraries(polarssl pthread) + endif() + + install(TARGETS polarssl + DESTINATION ${LIB_INSTALL_DIR} + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) +endif(USE_SHARED_POLARSSL_LIBRARY) diff --git a/component/common/network/ssl/polarssl-1.3.8/library/Makefile b/component/common/network/ssl/polarssl-1.3.8/library/Makefile new file mode 100644 index 0000000..d637417 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/Makefile @@ -0,0 +1,110 @@ + +# Also see "include/polarssl/config.h" + +# To compile on MinGW: add "-lws2_32" to LDFLAGS or define WINDOWS in your +# environment +# +CFLAGS += -I../include -D_FILE_OFFSET_BITS=64 -Wall -W -Wdeclaration-after-statement +OFLAGS = -O2 + +ifdef DEBUG +CFLAGS += -g3 +endif + +# MicroBlaze specific options: +# CFLAGS += -mno-xl-soft-mul -mxl-barrel-shift + +# To compile on Plan9: +# CFLAGS += -D_BSD_EXTENSION + +# To compile as a shared library: +ifdef SHARED +CFLAGS += -fPIC +endif + +SONAME=libpolarssl.so.7 + +DLEXT=so.7 +# OSX shared library extension: +# DLEXT=dylib + +# Windows shared library extension: +ifdef WINDOWS +DLEXT=dll +LDFLAGS += -lws2_32 +endif + +OBJS= aes.o aesni.o arc4.o \ + asn1parse.o \ + asn1write.o base64.o bignum.o \ + blowfish.o camellia.o ccm.o \ + certs.o cipher.o cipher_wrap.o \ + ctr_drbg.o debug.o des.o \ + dhm.o ecdh.o ecdsa.o \ + ecp.o ecp_curves.o \ + entropy.o entropy_poll.o \ + error.o gcm.o havege.o \ + hmac_drbg.o \ + md.o md_wrap.o md2.o \ + md4.o md5.o \ + memory_buffer_alloc.o net.o \ + oid.o \ + padlock.o pbkdf2.o pem.o \ + pkcs5.o pkcs11.o pkcs12.o \ + pk.o pk_wrap.o pkparse.o \ + pkwrite.o platform.o ripemd160.o \ + rsa.o sha1.o sha256.o \ + sha512.o ssl_cache.o ssl_cli.o \ + ssl_srv.o ssl_ciphersuites.o \ + ssl_tls.o threading.o timing.o \ + version.o version_features.o \ + x509.o x509_create.o \ + x509_crl.o x509_crt.o x509_csr.o \ + x509write_crt.o x509write_csr.o \ + xtea.o + +.SILENT: + +ifndef SHARED +all: static +else +all: shared +endif + +static: libpolarssl.a + +shared: libpolarssl.$(DLEXT) libpolarssl.so + +libpolarssl.a: $(OBJS) + echo " AR $@" + $(AR) r $@ $(OBJS) + echo " RL $@" + $(AR) s $@ + +libpolarssl.${DLEXT}: libpolarssl.a + echo " LD $@" + $(CC) ${LDFLAGS} -shared -Wl,-soname,$(SONAME) -o $@ $(OBJS) + +libpolarssl.so: libpolarssl.${DLEXT} + echo " LN $@ -> libpolarssl.${DLEXT}" + ln -sf libpolarssl.${DLEXT} $@ + +libpolarssl.dylib: libpolarssl.a + echo " LD $@" + $(CC) ${LDFLAGS} -dynamiclib -o $@ $(OBJS) + +libpolarssl.dll: libpolarssl.a + echo " LD $@" + $(CC) -shared -Wl,-soname,$@ -o $@ $(OBJS) -lws2_32 -lwinmm -lgdi32 + +.c.o: + echo " CC $<" + $(CC) $(CFLAGS) $(OFLAGS) -c $< + +clean: +ifndef WINDOWS + rm -f *.o libpolarssl.* +endif +ifdef WINDOWS + del /Q /F *.o libpolarssl.* +endif diff --git a/component/common/network/ssl/polarssl-1.3.8/library/aes.c b/component/common/network/ssl/polarssl-1.3.8/library/aes.c new file mode 100644 index 0000000..8d08ddb --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/aes.c @@ -0,0 +1,1554 @@ +/* + * FIPS-197 compliant AES implementation + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * The AES block cipher was designed by Vincent Rijmen and Joan Daemen. + * + * http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf + * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#ifdef RTL_HW_CRYPTO +#include +#endif + +#if defined(POLARSSL_AES_C) + +#include "polarssl/aes.h" +#if defined(POLARSSL_PADLOCK_C) +#include "polarssl/padlock.h" +#endif +#if defined(POLARSSL_AESNI_C) +#include "polarssl/aesni.h" +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#define polarssl_printf printf +#endif + +#if !defined(POLARSSL_AES_ALT) + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +#ifndef RTL_HW_CRYPTO + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_UINT32_LE +#define GET_UINT32_LE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] ) \ + | ( (uint32_t) (b)[(i) + 1] << 8 ) \ + | ( (uint32_t) (b)[(i) + 2] << 16 ) \ + | ( (uint32_t) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_UINT32_LE +#define PUT_UINT32_LE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \ +} +#endif + +#if defined(POLARSSL_PADLOCK_C) && \ + ( defined(POLARSSL_HAVE_X86) || defined(PADLOCK_ALIGN16) ) +static int aes_padlock_ace = -1; +#endif + +#if defined(POLARSSL_AES_ROM_TABLES) +/* + * Forward S-box + */ +static const unsigned char FSb[256] = +{ + 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, + 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, + 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, + 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, + 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, + 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, + 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, + 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, + 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, + 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, + 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, + 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, + 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, + 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, + 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, + 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, + 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, + 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, + 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, + 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, + 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, + 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, + 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, + 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, + 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, + 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, + 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, + 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, + 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, + 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, + 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, + 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 +}; + +/* + * Forward tables + */ +#define FT \ +\ + V(A5,63,63,C6), V(84,7C,7C,F8), V(99,77,77,EE), V(8D,7B,7B,F6), \ + V(0D,F2,F2,FF), V(BD,6B,6B,D6), V(B1,6F,6F,DE), V(54,C5,C5,91), \ + V(50,30,30,60), V(03,01,01,02), V(A9,67,67,CE), V(7D,2B,2B,56), \ + V(19,FE,FE,E7), V(62,D7,D7,B5), V(E6,AB,AB,4D), V(9A,76,76,EC), \ + V(45,CA,CA,8F), V(9D,82,82,1F), V(40,C9,C9,89), V(87,7D,7D,FA), \ + V(15,FA,FA,EF), V(EB,59,59,B2), V(C9,47,47,8E), V(0B,F0,F0,FB), \ + V(EC,AD,AD,41), V(67,D4,D4,B3), V(FD,A2,A2,5F), V(EA,AF,AF,45), \ + V(BF,9C,9C,23), V(F7,A4,A4,53), V(96,72,72,E4), V(5B,C0,C0,9B), \ + V(C2,B7,B7,75), V(1C,FD,FD,E1), V(AE,93,93,3D), V(6A,26,26,4C), \ + V(5A,36,36,6C), V(41,3F,3F,7E), V(02,F7,F7,F5), V(4F,CC,CC,83), \ + V(5C,34,34,68), V(F4,A5,A5,51), V(34,E5,E5,D1), V(08,F1,F1,F9), \ + V(93,71,71,E2), V(73,D8,D8,AB), V(53,31,31,62), V(3F,15,15,2A), \ + V(0C,04,04,08), V(52,C7,C7,95), V(65,23,23,46), V(5E,C3,C3,9D), \ + V(28,18,18,30), V(A1,96,96,37), V(0F,05,05,0A), V(B5,9A,9A,2F), \ + V(09,07,07,0E), V(36,12,12,24), V(9B,80,80,1B), V(3D,E2,E2,DF), \ + V(26,EB,EB,CD), V(69,27,27,4E), V(CD,B2,B2,7F), V(9F,75,75,EA), \ + V(1B,09,09,12), V(9E,83,83,1D), V(74,2C,2C,58), V(2E,1A,1A,34), \ + V(2D,1B,1B,36), V(B2,6E,6E,DC), V(EE,5A,5A,B4), V(FB,A0,A0,5B), \ + V(F6,52,52,A4), V(4D,3B,3B,76), V(61,D6,D6,B7), V(CE,B3,B3,7D), \ + V(7B,29,29,52), V(3E,E3,E3,DD), V(71,2F,2F,5E), V(97,84,84,13), \ + V(F5,53,53,A6), V(68,D1,D1,B9), V(00,00,00,00), V(2C,ED,ED,C1), \ + V(60,20,20,40), V(1F,FC,FC,E3), V(C8,B1,B1,79), V(ED,5B,5B,B6), \ + V(BE,6A,6A,D4), V(46,CB,CB,8D), V(D9,BE,BE,67), V(4B,39,39,72), \ + V(DE,4A,4A,94), V(D4,4C,4C,98), V(E8,58,58,B0), V(4A,CF,CF,85), \ + V(6B,D0,D0,BB), V(2A,EF,EF,C5), V(E5,AA,AA,4F), V(16,FB,FB,ED), \ + V(C5,43,43,86), V(D7,4D,4D,9A), V(55,33,33,66), V(94,85,85,11), \ + V(CF,45,45,8A), V(10,F9,F9,E9), V(06,02,02,04), V(81,7F,7F,FE), \ + V(F0,50,50,A0), V(44,3C,3C,78), V(BA,9F,9F,25), V(E3,A8,A8,4B), \ + V(F3,51,51,A2), V(FE,A3,A3,5D), V(C0,40,40,80), V(8A,8F,8F,05), \ + V(AD,92,92,3F), V(BC,9D,9D,21), V(48,38,38,70), V(04,F5,F5,F1), \ + V(DF,BC,BC,63), V(C1,B6,B6,77), V(75,DA,DA,AF), V(63,21,21,42), \ + V(30,10,10,20), V(1A,FF,FF,E5), V(0E,F3,F3,FD), V(6D,D2,D2,BF), \ + V(4C,CD,CD,81), V(14,0C,0C,18), V(35,13,13,26), V(2F,EC,EC,C3), \ + V(E1,5F,5F,BE), V(A2,97,97,35), V(CC,44,44,88), V(39,17,17,2E), \ + V(57,C4,C4,93), V(F2,A7,A7,55), V(82,7E,7E,FC), V(47,3D,3D,7A), \ + V(AC,64,64,C8), V(E7,5D,5D,BA), V(2B,19,19,32), V(95,73,73,E6), \ + V(A0,60,60,C0), V(98,81,81,19), V(D1,4F,4F,9E), V(7F,DC,DC,A3), \ + V(66,22,22,44), V(7E,2A,2A,54), V(AB,90,90,3B), V(83,88,88,0B), \ + V(CA,46,46,8C), V(29,EE,EE,C7), V(D3,B8,B8,6B), V(3C,14,14,28), \ + V(79,DE,DE,A7), V(E2,5E,5E,BC), V(1D,0B,0B,16), V(76,DB,DB,AD), \ + V(3B,E0,E0,DB), V(56,32,32,64), V(4E,3A,3A,74), V(1E,0A,0A,14), \ + V(DB,49,49,92), V(0A,06,06,0C), V(6C,24,24,48), V(E4,5C,5C,B8), \ + V(5D,C2,C2,9F), V(6E,D3,D3,BD), V(EF,AC,AC,43), V(A6,62,62,C4), \ + V(A8,91,91,39), V(A4,95,95,31), V(37,E4,E4,D3), V(8B,79,79,F2), \ + V(32,E7,E7,D5), V(43,C8,C8,8B), V(59,37,37,6E), V(B7,6D,6D,DA), \ + V(8C,8D,8D,01), V(64,D5,D5,B1), V(D2,4E,4E,9C), V(E0,A9,A9,49), \ + V(B4,6C,6C,D8), V(FA,56,56,AC), V(07,F4,F4,F3), V(25,EA,EA,CF), \ + V(AF,65,65,CA), V(8E,7A,7A,F4), V(E9,AE,AE,47), V(18,08,08,10), \ + V(D5,BA,BA,6F), V(88,78,78,F0), V(6F,25,25,4A), V(72,2E,2E,5C), \ + V(24,1C,1C,38), V(F1,A6,A6,57), V(C7,B4,B4,73), V(51,C6,C6,97), \ + V(23,E8,E8,CB), V(7C,DD,DD,A1), V(9C,74,74,E8), V(21,1F,1F,3E), \ + V(DD,4B,4B,96), V(DC,BD,BD,61), V(86,8B,8B,0D), V(85,8A,8A,0F), \ + V(90,70,70,E0), V(42,3E,3E,7C), V(C4,B5,B5,71), V(AA,66,66,CC), \ + V(D8,48,48,90), V(05,03,03,06), V(01,F6,F6,F7), V(12,0E,0E,1C), \ + V(A3,61,61,C2), V(5F,35,35,6A), V(F9,57,57,AE), V(D0,B9,B9,69), \ + V(91,86,86,17), V(58,C1,C1,99), V(27,1D,1D,3A), V(B9,9E,9E,27), \ + V(38,E1,E1,D9), V(13,F8,F8,EB), V(B3,98,98,2B), V(33,11,11,22), \ + V(BB,69,69,D2), V(70,D9,D9,A9), V(89,8E,8E,07), V(A7,94,94,33), \ + V(B6,9B,9B,2D), V(22,1E,1E,3C), V(92,87,87,15), V(20,E9,E9,C9), \ + V(49,CE,CE,87), V(FF,55,55,AA), V(78,28,28,50), V(7A,DF,DF,A5), \ + V(8F,8C,8C,03), V(F8,A1,A1,59), V(80,89,89,09), V(17,0D,0D,1A), \ + V(DA,BF,BF,65), V(31,E6,E6,D7), V(C6,42,42,84), V(B8,68,68,D0), \ + V(C3,41,41,82), V(B0,99,99,29), V(77,2D,2D,5A), V(11,0F,0F,1E), \ + V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C) + +#define V(a,b,c,d) 0x##a##b##c##d +static const uint32_t FT0[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##b##c##d##a +static const uint32_t FT1[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##c##d##a##b +static const uint32_t FT2[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##d##a##b##c +static const uint32_t FT3[256] = { FT }; +#undef V + +#undef FT + +/* + * Reverse S-box + */ +static const unsigned char RSb[256] = +{ + 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, + 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, + 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, + 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, + 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, + 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, + 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, + 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, + 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, + 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, + 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, + 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, + 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, + 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, + 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, + 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, + 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, + 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, + 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, + 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, + 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, + 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, + 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, + 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, + 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, + 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, + 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, + 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, + 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, + 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, + 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D +}; + +/* + * Reverse tables + */ +#define RT \ +\ + V(50,A7,F4,51), V(53,65,41,7E), V(C3,A4,17,1A), V(96,5E,27,3A), \ + V(CB,6B,AB,3B), V(F1,45,9D,1F), V(AB,58,FA,AC), V(93,03,E3,4B), \ + V(55,FA,30,20), V(F6,6D,76,AD), V(91,76,CC,88), V(25,4C,02,F5), \ + V(FC,D7,E5,4F), V(D7,CB,2A,C5), V(80,44,35,26), V(8F,A3,62,B5), \ + V(49,5A,B1,DE), V(67,1B,BA,25), V(98,0E,EA,45), V(E1,C0,FE,5D), \ + V(02,75,2F,C3), V(12,F0,4C,81), V(A3,97,46,8D), V(C6,F9,D3,6B), \ + V(E7,5F,8F,03), V(95,9C,92,15), V(EB,7A,6D,BF), V(DA,59,52,95), \ + V(2D,83,BE,D4), V(D3,21,74,58), V(29,69,E0,49), V(44,C8,C9,8E), \ + V(6A,89,C2,75), V(78,79,8E,F4), V(6B,3E,58,99), V(DD,71,B9,27), \ + V(B6,4F,E1,BE), V(17,AD,88,F0), V(66,AC,20,C9), V(B4,3A,CE,7D), \ + V(18,4A,DF,63), V(82,31,1A,E5), V(60,33,51,97), V(45,7F,53,62), \ + V(E0,77,64,B1), V(84,AE,6B,BB), V(1C,A0,81,FE), V(94,2B,08,F9), \ + V(58,68,48,70), V(19,FD,45,8F), V(87,6C,DE,94), V(B7,F8,7B,52), \ + V(23,D3,73,AB), V(E2,02,4B,72), V(57,8F,1F,E3), V(2A,AB,55,66), \ + V(07,28,EB,B2), V(03,C2,B5,2F), V(9A,7B,C5,86), V(A5,08,37,D3), \ + V(F2,87,28,30), V(B2,A5,BF,23), V(BA,6A,03,02), V(5C,82,16,ED), \ + V(2B,1C,CF,8A), V(92,B4,79,A7), V(F0,F2,07,F3), V(A1,E2,69,4E), \ + V(CD,F4,DA,65), V(D5,BE,05,06), V(1F,62,34,D1), V(8A,FE,A6,C4), \ + V(9D,53,2E,34), V(A0,55,F3,A2), V(32,E1,8A,05), V(75,EB,F6,A4), \ + V(39,EC,83,0B), V(AA,EF,60,40), V(06,9F,71,5E), V(51,10,6E,BD), \ + V(F9,8A,21,3E), V(3D,06,DD,96), V(AE,05,3E,DD), V(46,BD,E6,4D), \ + V(B5,8D,54,91), V(05,5D,C4,71), V(6F,D4,06,04), V(FF,15,50,60), \ + V(24,FB,98,19), V(97,E9,BD,D6), V(CC,43,40,89), V(77,9E,D9,67), \ + V(BD,42,E8,B0), V(88,8B,89,07), V(38,5B,19,E7), V(DB,EE,C8,79), \ + V(47,0A,7C,A1), V(E9,0F,42,7C), V(C9,1E,84,F8), V(00,00,00,00), \ + V(83,86,80,09), V(48,ED,2B,32), V(AC,70,11,1E), V(4E,72,5A,6C), \ + V(FB,FF,0E,FD), V(56,38,85,0F), V(1E,D5,AE,3D), V(27,39,2D,36), \ + V(64,D9,0F,0A), V(21,A6,5C,68), V(D1,54,5B,9B), V(3A,2E,36,24), \ + V(B1,67,0A,0C), V(0F,E7,57,93), V(D2,96,EE,B4), V(9E,91,9B,1B), \ + V(4F,C5,C0,80), V(A2,20,DC,61), V(69,4B,77,5A), V(16,1A,12,1C), \ + V(0A,BA,93,E2), V(E5,2A,A0,C0), V(43,E0,22,3C), V(1D,17,1B,12), \ + V(0B,0D,09,0E), V(AD,C7,8B,F2), V(B9,A8,B6,2D), V(C8,A9,1E,14), \ + V(85,19,F1,57), V(4C,07,75,AF), V(BB,DD,99,EE), V(FD,60,7F,A3), \ + V(9F,26,01,F7), V(BC,F5,72,5C), V(C5,3B,66,44), V(34,7E,FB,5B), \ + V(76,29,43,8B), V(DC,C6,23,CB), V(68,FC,ED,B6), V(63,F1,E4,B8), \ + V(CA,DC,31,D7), V(10,85,63,42), V(40,22,97,13), V(20,11,C6,84), \ + V(7D,24,4A,85), V(F8,3D,BB,D2), V(11,32,F9,AE), V(6D,A1,29,C7), \ + V(4B,2F,9E,1D), V(F3,30,B2,DC), V(EC,52,86,0D), V(D0,E3,C1,77), \ + V(6C,16,B3,2B), V(99,B9,70,A9), V(FA,48,94,11), V(22,64,E9,47), \ + V(C4,8C,FC,A8), V(1A,3F,F0,A0), V(D8,2C,7D,56), V(EF,90,33,22), \ + V(C7,4E,49,87), V(C1,D1,38,D9), V(FE,A2,CA,8C), V(36,0B,D4,98), \ + V(CF,81,F5,A6), V(28,DE,7A,A5), V(26,8E,B7,DA), V(A4,BF,AD,3F), \ + V(E4,9D,3A,2C), V(0D,92,78,50), V(9B,CC,5F,6A), V(62,46,7E,54), \ + V(C2,13,8D,F6), V(E8,B8,D8,90), V(5E,F7,39,2E), V(F5,AF,C3,82), \ + V(BE,80,5D,9F), V(7C,93,D0,69), V(A9,2D,D5,6F), V(B3,12,25,CF), \ + V(3B,99,AC,C8), V(A7,7D,18,10), V(6E,63,9C,E8), V(7B,BB,3B,DB), \ + V(09,78,26,CD), V(F4,18,59,6E), V(01,B7,9A,EC), V(A8,9A,4F,83), \ + V(65,6E,95,E6), V(7E,E6,FF,AA), V(08,CF,BC,21), V(E6,E8,15,EF), \ + V(D9,9B,E7,BA), V(CE,36,6F,4A), V(D4,09,9F,EA), V(D6,7C,B0,29), \ + V(AF,B2,A4,31), V(31,23,3F,2A), V(30,94,A5,C6), V(C0,66,A2,35), \ + V(37,BC,4E,74), V(A6,CA,82,FC), V(B0,D0,90,E0), V(15,D8,A7,33), \ + V(4A,98,04,F1), V(F7,DA,EC,41), V(0E,50,CD,7F), V(2F,F6,91,17), \ + V(8D,D6,4D,76), V(4D,B0,EF,43), V(54,4D,AA,CC), V(DF,04,96,E4), \ + V(E3,B5,D1,9E), V(1B,88,6A,4C), V(B8,1F,2C,C1), V(7F,51,65,46), \ + V(04,EA,5E,9D), V(5D,35,8C,01), V(73,74,87,FA), V(2E,41,0B,FB), \ + V(5A,1D,67,B3), V(52,D2,DB,92), V(33,56,10,E9), V(13,47,D6,6D), \ + V(8C,61,D7,9A), V(7A,0C,A1,37), V(8E,14,F8,59), V(89,3C,13,EB), \ + V(EE,27,A9,CE), V(35,C9,61,B7), V(ED,E5,1C,E1), V(3C,B1,47,7A), \ + V(59,DF,D2,9C), V(3F,73,F2,55), V(79,CE,14,18), V(BF,37,C7,73), \ + V(EA,CD,F7,53), V(5B,AA,FD,5F), V(14,6F,3D,DF), V(86,DB,44,78), \ + V(81,F3,AF,CA), V(3E,C4,68,B9), V(2C,34,24,38), V(5F,40,A3,C2), \ + V(72,C3,1D,16), V(0C,25,E2,BC), V(8B,49,3C,28), V(41,95,0D,FF), \ + V(71,01,A8,39), V(DE,B3,0C,08), V(9C,E4,B4,D8), V(90,C1,56,64), \ + V(61,84,CB,7B), V(70,B6,32,D5), V(74,5C,6C,48), V(42,57,B8,D0) + +#define V(a,b,c,d) 0x##a##b##c##d +static const uint32_t RT0[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##b##c##d##a +static const uint32_t RT1[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##c##d##a##b +static const uint32_t RT2[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##d##a##b##c +static const uint32_t RT3[256] = { RT }; +#undef V + +#undef RT + +/* + * Round constants + */ +static const uint32_t RCON[10] = +{ + 0x00000001, 0x00000002, 0x00000004, 0x00000008, + 0x00000010, 0x00000020, 0x00000040, 0x00000080, + 0x0000001B, 0x00000036 +}; + +#else /* POLARSSL_AES_ROM_TABLES */ + +/* + * Forward S-box & tables + */ +static unsigned char FSb[256]; +static uint32_t FT0[256]; +static uint32_t FT1[256]; +static uint32_t FT2[256]; +static uint32_t FT3[256]; + +/* + * Reverse S-box & tables + */ +static unsigned char RSb[256]; +static uint32_t RT0[256]; +static uint32_t RT1[256]; +static uint32_t RT2[256]; +static uint32_t RT3[256]; + +/* + * Round constants + */ +static uint32_t RCON[10]; + +/* + * Tables generation code + */ +#define ROTL8(x) ( ( x << 8 ) & 0xFFFFFFFF ) | ( x >> 24 ) +#define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) ) +#define MUL(x,y) ( ( x && y ) ? pow[(log[x]+log[y]) % 255] : 0 ) + +static int aes_init_done = 0; + +static void aes_gen_tables( void ) +{ + int i, x, y, z; + int pow[256]; + int log[256]; + + /* + * compute pow and log tables over GF(2^8) + */ + for( i = 0, x = 1; i < 256; i++ ) + { + pow[i] = x; + log[x] = i; + x = ( x ^ XTIME( x ) ) & 0xFF; + } + + /* + * calculate the round constants + */ + for( i = 0, x = 1; i < 10; i++ ) + { + RCON[i] = (uint32_t) x; + x = XTIME( x ) & 0xFF; + } + + /* + * generate the forward and reverse S-boxes + */ + FSb[0x00] = 0x63; + RSb[0x63] = 0x00; + + for( i = 1; i < 256; i++ ) + { + x = pow[255 - log[i]]; + + y = x; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; + x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; + x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; + x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; + x ^= y ^ 0x63; + + FSb[i] = (unsigned char) x; + RSb[x] = (unsigned char) i; + } + + /* + * generate the forward and reverse tables + */ + for( i = 0; i < 256; i++ ) + { + x = FSb[i]; + y = XTIME( x ) & 0xFF; + z = ( y ^ x ) & 0xFF; + + FT0[i] = ( (uint32_t) y ) ^ + ( (uint32_t) x << 8 ) ^ + ( (uint32_t) x << 16 ) ^ + ( (uint32_t) z << 24 ); + + FT1[i] = ROTL8( FT0[i] ); + FT2[i] = ROTL8( FT1[i] ); + FT3[i] = ROTL8( FT2[i] ); + + x = RSb[i]; + + RT0[i] = ( (uint32_t) MUL( 0x0E, x ) ) ^ + ( (uint32_t) MUL( 0x09, x ) << 8 ) ^ + ( (uint32_t) MUL( 0x0D, x ) << 16 ) ^ + ( (uint32_t) MUL( 0x0B, x ) << 24 ); + + RT1[i] = ROTL8( RT0[i] ); + RT2[i] = ROTL8( RT1[i] ); + RT3[i] = ROTL8( RT2[i] ); + } +} + +#endif /* POLARSSL_AES_ROM_TABLES */ +#endif /* RTL_HW_CRYPTO */ + +void aes_init( aes_context *ctx ) +{ + memset( ctx, 0, sizeof( aes_context ) ); +} + +void aes_free( aes_context *ctx ) +{ + if( ctx == NULL ) + return; + + polarssl_zeroize( ctx, sizeof( aes_context ) ); +} + +/* + * AES key schedule (encryption) + */ +int aes_setkey_enc( aes_context *ctx, const unsigned char *key, + unsigned int keysize ) +{ +#ifdef RTL_HW_CRYPTO + switch(keysize) + { + case 128: ctx->nr = 10; break; + case 192: ctx->nr = 12; break; + case 256: ctx->nr = 14; break; + default : return(POLARSSL_ERR_AES_INVALID_KEY_LENGTH); + } + + memcpy(ctx->enc_key, key, (keysize / 8)); + return 0; +#else /* RTL_HW_CRYPTO */ + unsigned int i; + uint32_t *RK; + +#if !defined(POLARSSL_AES_ROM_TABLES) + if( aes_init_done == 0 ) + { + aes_gen_tables(); + aes_init_done = 1; + + } +#endif + + switch( keysize ) + { + case 128: ctx->nr = 10; break; + case 192: ctx->nr = 12; break; + case 256: ctx->nr = 14; break; + default : return( POLARSSL_ERR_AES_INVALID_KEY_LENGTH ); + } + +#if defined(POLARSSL_PADLOCK_C) && defined(PADLOCK_ALIGN16) + if( aes_padlock_ace == -1 ) + aes_padlock_ace = padlock_supports( PADLOCK_ACE ); + + if( aes_padlock_ace ) + ctx->rk = RK = PADLOCK_ALIGN16( ctx->buf ); + else +#endif + ctx->rk = RK = ctx->buf; + +#if defined(POLARSSL_AESNI_C) && defined(POLARSSL_HAVE_X86_64) + if( aesni_supports( POLARSSL_AESNI_AES ) ) + return( aesni_setkey_enc( (unsigned char *) ctx->rk, key, keysize ) ); +#endif + + for( i = 0; i < ( keysize >> 5 ); i++ ) + { + GET_UINT32_LE( RK[i], key, i << 2 ); + } + + switch( ctx->nr ) + { + case 10: + + for( i = 0; i < 10; i++, RK += 4 ) + { + RK[4] = RK[0] ^ RCON[i] ^ + ( (uint32_t) FSb[ ( RK[3] >> 8 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( RK[3] >> 16 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( RK[3] ) & 0xFF ] << 24 ); + + RK[5] = RK[1] ^ RK[4]; + RK[6] = RK[2] ^ RK[5]; + RK[7] = RK[3] ^ RK[6]; + } + break; + + case 12: + + for( i = 0; i < 8; i++, RK += 6 ) + { + RK[6] = RK[0] ^ RCON[i] ^ + ( (uint32_t) FSb[ ( RK[5] >> 8 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( RK[5] >> 16 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( RK[5] ) & 0xFF ] << 24 ); + + RK[7] = RK[1] ^ RK[6]; + RK[8] = RK[2] ^ RK[7]; + RK[9] = RK[3] ^ RK[8]; + RK[10] = RK[4] ^ RK[9]; + RK[11] = RK[5] ^ RK[10]; + } + break; + + case 14: + + for( i = 0; i < 7; i++, RK += 8 ) + { + RK[8] = RK[0] ^ RCON[i] ^ + ( (uint32_t) FSb[ ( RK[7] >> 8 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( RK[7] >> 16 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( RK[7] ) & 0xFF ] << 24 ); + + RK[9] = RK[1] ^ RK[8]; + RK[10] = RK[2] ^ RK[9]; + RK[11] = RK[3] ^ RK[10]; + + RK[12] = RK[4] ^ + ( (uint32_t) FSb[ ( RK[11] ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( RK[11] >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 ); + + RK[13] = RK[5] ^ RK[12]; + RK[14] = RK[6] ^ RK[13]; + RK[15] = RK[7] ^ RK[14]; + } + break; + } + + return( 0 ); +#endif /* RTL_HW_CRYPTO */ +} + +/* + * AES key schedule (decryption) + */ +int aes_setkey_dec( aes_context *ctx, const unsigned char *key, + unsigned int keysize ) +{ +#ifdef RTL_HW_CRYPTO + switch(keysize) + { + case 128: ctx->nr = 10; break; + case 192: ctx->nr = 12; break; + case 256: ctx->nr = 14; break; + default : return(POLARSSL_ERR_AES_INVALID_KEY_LENGTH); + } + + memcpy(ctx->dec_key, key, (keysize / 8)); + return 0; +#else /* RTL_HW_CRYPTO */ + int i, j, ret; + aes_context cty; + uint32_t *RK; + uint32_t *SK; + + aes_init( &cty ); + +#if defined(POLARSSL_PADLOCK_C) && defined(PADLOCK_ALIGN16) + if( aes_padlock_ace == -1 ) + aes_padlock_ace = padlock_supports( PADLOCK_ACE ); + + if( aes_padlock_ace ) + ctx->rk = RK = PADLOCK_ALIGN16( ctx->buf ); + else +#endif + ctx->rk = RK = ctx->buf; + + /* Also checks keysize */ + if( ( ret = aes_setkey_enc( &cty, key, keysize ) ) != 0 ) + goto exit; + + ctx->nr = cty.nr; + +#if defined(POLARSSL_AESNI_C) && defined(POLARSSL_HAVE_X86_64) + if( aesni_supports( POLARSSL_AESNI_AES ) ) + { + aesni_inverse_key( (unsigned char *) ctx->rk, + (const unsigned char *) cty.rk, ctx->nr ); + goto exit; + } +#endif + + SK = cty.rk + cty.nr * 4; + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + + for( i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8 ) + { + for( j = 0; j < 4; j++, SK++ ) + { + *RK++ = RT0[ FSb[ ( *SK ) & 0xFF ] ] ^ + RT1[ FSb[ ( *SK >> 8 ) & 0xFF ] ] ^ + RT2[ FSb[ ( *SK >> 16 ) & 0xFF ] ] ^ + RT3[ FSb[ ( *SK >> 24 ) & 0xFF ] ]; + } + } + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + +exit: + aes_free( &cty ); + + return( ret ); +#endif /* RTL_HW_CRYPTO */ +} + +#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ +{ \ + X0 = *RK++ ^ FT0[ ( Y0 ) & 0xFF ] ^ \ + FT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ + FT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ + FT3[ ( Y3 >> 24 ) & 0xFF ]; \ + \ + X1 = *RK++ ^ FT0[ ( Y1 ) & 0xFF ] ^ \ + FT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ + FT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ + FT3[ ( Y0 >> 24 ) & 0xFF ]; \ + \ + X2 = *RK++ ^ FT0[ ( Y2 ) & 0xFF ] ^ \ + FT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ + FT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ + FT3[ ( Y1 >> 24 ) & 0xFF ]; \ + \ + X3 = *RK++ ^ FT0[ ( Y3 ) & 0xFF ] ^ \ + FT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ + FT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ + FT3[ ( Y2 >> 24 ) & 0xFF ]; \ +} + +#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ +{ \ + X0 = *RK++ ^ RT0[ ( Y0 ) & 0xFF ] ^ \ + RT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ + RT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ + RT3[ ( Y1 >> 24 ) & 0xFF ]; \ + \ + X1 = *RK++ ^ RT0[ ( Y1 ) & 0xFF ] ^ \ + RT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ + RT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ + RT3[ ( Y2 >> 24 ) & 0xFF ]; \ + \ + X2 = *RK++ ^ RT0[ ( Y2 ) & 0xFF ] ^ \ + RT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ + RT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ + RT3[ ( Y3 >> 24 ) & 0xFF ]; \ + \ + X3 = *RK++ ^ RT0[ ( Y3 ) & 0xFF ] ^ \ + RT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ + RT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ + RT3[ ( Y0 >> 24 ) & 0xFF ]; \ +} + +/* + * AES-ECB block encryption/decryption + */ +int aes_crypt_ecb( aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ) +{ +#ifdef RTL_HW_CRYPTO + unsigned char key_buf[32 + 4], *key_buf_aligned; + unsigned char *output_buf[16 + 4], *output_buf_aligned; + + key_buf_aligned = (unsigned char *) (((unsigned int) key_buf + 4) / 4 * 4); + output_buf_aligned = (unsigned char *) (((unsigned int) output_buf + 4) / 4 * 4); + memset(output_buf, 0, 16 + 4); + + if(mode == AES_DECRYPT) + { + memcpy(key_buf_aligned, ctx->dec_key, ((ctx->nr - 6) * 4)); + rtl_crypto_aes_ecb_init(key_buf_aligned, ((ctx->nr - 6) * 4)); + rtl_crypto_aes_ecb_decrypt(input, 16, NULL, 0, output_buf_aligned); + } + else + { + memcpy(key_buf_aligned, ctx->enc_key, ((ctx->nr - 6) * 4)); + rtl_crypto_aes_ecb_init(key_buf_aligned,((ctx->nr - 6) * 4)); + rtl_crypto_aes_ecb_encrypt(input, 16, NULL, 0, output_buf_aligned); + } + + memcpy(output, output_buf_aligned, 16); + + return 0; +#else /* RTL_HW_CRYPTO */ + int i; + uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; + +#if defined(POLARSSL_AESNI_C) && defined(POLARSSL_HAVE_X86_64) + if( aesni_supports( POLARSSL_AESNI_AES ) ) + return( aesni_crypt_ecb( ctx, mode, input, output ) ); +#endif + +#if defined(POLARSSL_PADLOCK_C) && defined(POLARSSL_HAVE_X86) + if( aes_padlock_ace ) + { + if( padlock_xcryptecb( ctx, mode, input, output ) == 0 ) + return( 0 ); + + // If padlock data misaligned, we just fall back to + // unaccelerated mode + // + } +#endif + + RK = ctx->rk; + + GET_UINT32_LE( X0, input, 0 ); X0 ^= *RK++; + GET_UINT32_LE( X1, input, 4 ); X1 ^= *RK++; + GET_UINT32_LE( X2, input, 8 ); X2 ^= *RK++; + GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++; + + if( mode == AES_DECRYPT ) + { + for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- ) + { + AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); + AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); + } + + AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); + + X0 = *RK++ ^ \ + ( (uint32_t) RSb[ ( Y0 ) & 0xFF ] ) ^ + ( (uint32_t) RSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) RSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) RSb[ ( Y1 >> 24 ) & 0xFF ] << 24 ); + + X1 = *RK++ ^ \ + ( (uint32_t) RSb[ ( Y1 ) & 0xFF ] ) ^ + ( (uint32_t) RSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) RSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) RSb[ ( Y2 >> 24 ) & 0xFF ] << 24 ); + + X2 = *RK++ ^ \ + ( (uint32_t) RSb[ ( Y2 ) & 0xFF ] ) ^ + ( (uint32_t) RSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) RSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) RSb[ ( Y3 >> 24 ) & 0xFF ] << 24 ); + + X3 = *RK++ ^ \ + ( (uint32_t) RSb[ ( Y3 ) & 0xFF ] ) ^ + ( (uint32_t) RSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) RSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) RSb[ ( Y0 >> 24 ) & 0xFF ] << 24 ); + } + else /* AES_ENCRYPT */ + { + for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- ) + { + AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); + AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); + } + + AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); + + X0 = *RK++ ^ \ + ( (uint32_t) FSb[ ( Y0 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( Y3 >> 24 ) & 0xFF ] << 24 ); + + X1 = *RK++ ^ \ + ( (uint32_t) FSb[ ( Y1 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( Y0 >> 24 ) & 0xFF ] << 24 ); + + X2 = *RK++ ^ \ + ( (uint32_t) FSb[ ( Y2 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( Y1 >> 24 ) & 0xFF ] << 24 ); + + X3 = *RK++ ^ \ + ( (uint32_t) FSb[ ( Y3 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( Y2 >> 24 ) & 0xFF ] << 24 ); + } + + PUT_UINT32_LE( X0, output, 0 ); + PUT_UINT32_LE( X1, output, 4 ); + PUT_UINT32_LE( X2, output, 8 ); + PUT_UINT32_LE( X3, output, 12 ); + + return( 0 ); +#endif /* RTL_HW_CRYPTO */ +} + +#if defined(POLARSSL_CIPHER_MODE_CBC) +/* + * AES-CBC buffer encryption/decryption + */ +int aes_crypt_cbc( aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ +#ifdef RTL_HW_CRYPTO + unsigned char key_buf[32 + 4], *key_buf_aligned; + unsigned char iv_buf[16 + 4], *iv_buf_aligned, iv_tmp[16]; + unsigned char *output_buf, *output_buf_aligned; + + if(length % 16) + return(POLARSSL_ERR_AES_INVALID_INPUT_LENGTH); + + if(length > 0) + { + key_buf_aligned = (unsigned char *) (((unsigned int) key_buf + 4) / 4 * 4); + iv_buf_aligned = (unsigned char *) (((unsigned int) iv_buf + 4) / 4 * 4); + output_buf = polarssl_malloc(length + 4); + output_buf_aligned = (unsigned char *) (((unsigned int) output_buf + 4) / 4 * 4); + + memcpy(iv_buf_aligned, iv, 16); + memset(output_buf, 0, length + 4); + + if(mode == AES_DECRYPT) + { + memcpy(key_buf_aligned, ctx->dec_key, ((ctx->nr - 6) * 4)); + memcpy(iv_tmp, (input + length - 16), 16); + rtl_crypto_aes_cbc_init(key_buf_aligned, ((ctx->nr - 6) * 4)); + rtl_crypto_aes_cbc_decrypt(input, length, iv_buf_aligned, 16, output_buf_aligned); + memcpy(iv, iv_tmp, 16); + } + else + { + memcpy(key_buf_aligned, ctx->enc_key, ((ctx->nr - 6) * 4)); + rtl_crypto_aes_cbc_init(key_buf_aligned,((ctx->nr - 6) * 4)); + rtl_crypto_aes_cbc_encrypt(input, length, iv_buf_aligned, 16, output_buf_aligned); + memcpy(iv, (output_buf_aligned + length - 16), 16); + } + + memcpy(output, output_buf_aligned, length); + polarssl_free(output_buf); + } + + return 0; +#else /* RTL_HW_CRYPTO */ + int i; + unsigned char temp[16]; + + if( length % 16 ) + return( POLARSSL_ERR_AES_INVALID_INPUT_LENGTH ); + +#if defined(POLARSSL_PADLOCK_C) && defined(POLARSSL_HAVE_X86) + if( aes_padlock_ace ) + { + if( padlock_xcryptcbc( ctx, mode, length, iv, input, output ) == 0 ) + return( 0 ); + + // If padlock data misaligned, we just fall back to + // unaccelerated mode + // + } +#endif + + if( mode == AES_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, 16 ); + aes_crypt_ecb( ctx, mode, input, output ); + + for( i = 0; i < 16; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + else + { + while( length > 0 ) + { + for( i = 0; i < 16; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + aes_crypt_ecb( ctx, mode, output, output ); + memcpy( iv, output, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + + return( 0 ); +#endif /* RTL_HW_CRYPTO */ +} +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_CIPHER_MODE_CFB) +/* + * AES-CFB128 buffer encryption/decryption + */ +int aes_crypt_cfb128( aes_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int c; + size_t n = *iv_off; + + if( mode == AES_DECRYPT ) + { + while( length-- ) + { + if( n == 0 ) + aes_crypt_ecb( ctx, AES_ENCRYPT, iv, iv ); + + c = *input++; + *output++ = (unsigned char)( c ^ iv[n] ); + iv[n] = (unsigned char) c; + + n = ( n + 1 ) & 0x0F; + } + } + else + { + while( length-- ) + { + if( n == 0 ) + aes_crypt_ecb( ctx, AES_ENCRYPT, iv, iv ); + + iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); + + n = ( n + 1 ) & 0x0F; + } + } + + *iv_off = n; + + return( 0 ); +} + +/* + * AES-CFB8 buffer encryption/decryption + */ +#include +int aes_crypt_cfb8( aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + unsigned char c; + unsigned char ov[17]; + + while( length-- ) + { + memcpy( ov, iv, 16 ); + aes_crypt_ecb( ctx, AES_ENCRYPT, iv, iv ); + + if( mode == AES_DECRYPT ) + ov[16] = *input; + + c = *output++ = (unsigned char)( iv[0] ^ *input++ ); + + if( mode == AES_ENCRYPT ) + ov[16] = c; + + memcpy( iv, ov + 1, 16 ); + } + + return( 0 ); +} +#endif /*POLARSSL_CIPHER_MODE_CFB */ + +#if defined(POLARSSL_CIPHER_MODE_CTR) +/* + * AES-CTR buffer encryption/decryption + */ +int aes_crypt_ctr( aes_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ) +{ + int c, i; + size_t n = *nc_off; + + while( length-- ) + { + if( n == 0 ) { + aes_crypt_ecb( ctx, AES_ENCRYPT, nonce_counter, stream_block ); + + for( i = 16; i > 0; i-- ) + if( ++nonce_counter[i - 1] != 0 ) + break; + } + c = *input++; + *output++ = (unsigned char)( c ^ stream_block[n] ); + + n = ( n + 1 ) & 0x0F; + } + + *nc_off = n; + + return( 0 ); +} +#endif /* POLARSSL_CIPHER_MODE_CTR */ + +#endif /* !POLARSSL_AES_ALT */ + +#if defined(POLARSSL_SELF_TEST) + +#include + +/* + * AES test vectors from: + * + * http://csrc.nist.gov/archive/aes/rijndael/rijndael-vals.zip + */ +static const unsigned char aes_test_ecb_dec[3][16] = +{ + { 0x44, 0x41, 0x6A, 0xC2, 0xD1, 0xF5, 0x3C, 0x58, + 0x33, 0x03, 0x91, 0x7E, 0x6B, 0xE9, 0xEB, 0xE0 }, + { 0x48, 0xE3, 0x1E, 0x9E, 0x25, 0x67, 0x18, 0xF2, + 0x92, 0x29, 0x31, 0x9C, 0x19, 0xF1, 0x5B, 0xA4 }, + { 0x05, 0x8C, 0xCF, 0xFD, 0xBB, 0xCB, 0x38, 0x2D, + 0x1F, 0x6F, 0x56, 0x58, 0x5D, 0x8A, 0x4A, 0xDE } +}; + +static const unsigned char aes_test_ecb_enc[3][16] = +{ + { 0xC3, 0x4C, 0x05, 0x2C, 0xC0, 0xDA, 0x8D, 0x73, + 0x45, 0x1A, 0xFE, 0x5F, 0x03, 0xBE, 0x29, 0x7F }, + { 0xF3, 0xF6, 0x75, 0x2A, 0xE8, 0xD7, 0x83, 0x11, + 0x38, 0xF0, 0x41, 0x56, 0x06, 0x31, 0xB1, 0x14 }, + { 0x8B, 0x79, 0xEE, 0xCC, 0x93, 0xA0, 0xEE, 0x5D, + 0xFF, 0x30, 0xB4, 0xEA, 0x21, 0x63, 0x6D, 0xA4 } +}; + +#if defined(POLARSSL_CIPHER_MODE_CBC) +static const unsigned char aes_test_cbc_dec[3][16] = +{ + { 0xFA, 0xCA, 0x37, 0xE0, 0xB0, 0xC8, 0x53, 0x73, + 0xDF, 0x70, 0x6E, 0x73, 0xF7, 0xC9, 0xAF, 0x86 }, + { 0x5D, 0xF6, 0x78, 0xDD, 0x17, 0xBA, 0x4E, 0x75, + 0xB6, 0x17, 0x68, 0xC6, 0xAD, 0xEF, 0x7C, 0x7B }, + { 0x48, 0x04, 0xE1, 0x81, 0x8F, 0xE6, 0x29, 0x75, + 0x19, 0xA3, 0xE8, 0x8C, 0x57, 0x31, 0x04, 0x13 } +}; + +static const unsigned char aes_test_cbc_enc[3][16] = +{ + { 0x8A, 0x05, 0xFC, 0x5E, 0x09, 0x5A, 0xF4, 0x84, + 0x8A, 0x08, 0xD3, 0x28, 0xD3, 0x68, 0x8E, 0x3D }, + { 0x7B, 0xD9, 0x66, 0xD5, 0x3A, 0xD8, 0xC1, 0xBB, + 0x85, 0xD2, 0xAD, 0xFA, 0xE8, 0x7B, 0xB1, 0x04 }, + { 0xFE, 0x3C, 0x53, 0x65, 0x3E, 0x2F, 0x45, 0xB5, + 0x6F, 0xCD, 0x88, 0xB2, 0xCC, 0x89, 0x8F, 0xF0 } +}; +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_CIPHER_MODE_CFB) +/* + * AES-CFB128 test vectors from: + * + * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf + */ +static const unsigned char aes_test_cfb128_key[3][32] = +{ + { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, + 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }, + { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, + 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, + 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }, + { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, + 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, + 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, + 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } +}; + +static const unsigned char aes_test_cfb128_iv[16] = +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F +}; + +static const unsigned char aes_test_cfb128_pt[64] = +{ + 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 const unsigned char aes_test_cfb128_ct[3][64] = +{ + { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20, + 0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A, + 0xC8, 0xA6, 0x45, 0x37, 0xA0, 0xB3, 0xA9, 0x3F, + 0xCD, 0xE3, 0xCD, 0xAD, 0x9F, 0x1C, 0xE5, 0x8B, + 0x26, 0x75, 0x1F, 0x67, 0xA3, 0xCB, 0xB1, 0x40, + 0xB1, 0x80, 0x8C, 0xF1, 0x87, 0xA4, 0xF4, 0xDF, + 0xC0, 0x4B, 0x05, 0x35, 0x7C, 0x5D, 0x1C, 0x0E, + 0xEA, 0xC4, 0xC6, 0x6F, 0x9F, 0xF7, 0xF2, 0xE6 }, + { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB, + 0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74, + 0x67, 0xCE, 0x7F, 0x7F, 0x81, 0x17, 0x36, 0x21, + 0x96, 0x1A, 0x2B, 0x70, 0x17, 0x1D, 0x3D, 0x7A, + 0x2E, 0x1E, 0x8A, 0x1D, 0xD5, 0x9B, 0x88, 0xB1, + 0xC8, 0xE6, 0x0F, 0xED, 0x1E, 0xFA, 0xC4, 0xC9, + 0xC0, 0x5F, 0x9F, 0x9C, 0xA9, 0x83, 0x4F, 0xA0, + 0x42, 0xAE, 0x8F, 0xBA, 0x58, 0x4B, 0x09, 0xFF }, + { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B, + 0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60, + 0x39, 0xFF, 0xED, 0x14, 0x3B, 0x28, 0xB1, 0xC8, + 0x32, 0x11, 0x3C, 0x63, 0x31, 0xE5, 0x40, 0x7B, + 0xDF, 0x10, 0x13, 0x24, 0x15, 0xE5, 0x4B, 0x92, + 0xA1, 0x3E, 0xD0, 0xA8, 0x26, 0x7A, 0xE2, 0xF9, + 0x75, 0xA3, 0x85, 0x74, 0x1A, 0xB9, 0xCE, 0xF8, + 0x20, 0x31, 0x62, 0x3D, 0x55, 0xB1, 0xE4, 0x71 } +}; +#endif /* POLARSSL_CIPHER_MODE_CFB */ + +#if defined(POLARSSL_CIPHER_MODE_CTR) +/* + * AES-CTR test vectors from: + * + * http://www.faqs.org/rfcs/rfc3686.html + */ + +static const unsigned char aes_test_ctr_key[3][16] = +{ + { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC, + 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E }, + { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7, + 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 }, + { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8, + 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC } +}; + +static const unsigned char aes_test_ctr_nonce_counter[3][16] = +{ + { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59, + 0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 }, + { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F, + 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 } +}; + +static const unsigned char aes_test_ctr_pt[3][48] = +{ + { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62, + 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 }, + + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }, + + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x20, 0x21, 0x22, 0x23 } +}; + +static const unsigned char aes_test_ctr_ct[3][48] = +{ + { 0xE4, 0x09, 0x5D, 0x4F, 0xB7, 0xA7, 0xB3, 0x79, + 0x2D, 0x61, 0x75, 0xA3, 0x26, 0x13, 0x11, 0xB8 }, + { 0x51, 0x04, 0xA1, 0x06, 0x16, 0x8A, 0x72, 0xD9, + 0x79, 0x0D, 0x41, 0xEE, 0x8E, 0xDA, 0xD3, 0x88, + 0xEB, 0x2E, 0x1E, 0xFC, 0x46, 0xDA, 0x57, 0xC8, + 0xFC, 0xE6, 0x30, 0xDF, 0x91, 0x41, 0xBE, 0x28 }, + { 0xC1, 0xCF, 0x48, 0xA8, 0x9F, 0x2F, 0xFD, 0xD9, + 0xCF, 0x46, 0x52, 0xE9, 0xEF, 0xDB, 0x72, 0xD7, + 0x45, 0x40, 0xA4, 0x2B, 0xDE, 0x6D, 0x78, 0x36, + 0xD5, 0x9A, 0x5C, 0xEA, 0xAE, 0xF3, 0x10, 0x53, + 0x25, 0xB2, 0x07, 0x2F } +}; + +static const int aes_test_ctr_len[3] = + { 16, 32, 36 }; +#endif /* POLARSSL_CIPHER_MODE_CTR */ + +/* + * Checkup routine + */ +int aes_self_test( int verbose ) +{ + int ret = 0, i, j, u, v; + unsigned char key[32]; + unsigned char buf[64]; + unsigned char iv[16]; +#if defined(POLARSSL_CIPHER_MODE_CBC) + unsigned char prv[16]; +#endif +#if defined(POLARSSL_CIPHER_MODE_CTR) || defined(POLARSSL_CIPHER_MODE_CFB) + size_t offset; +#endif +#if defined(POLARSSL_CIPHER_MODE_CTR) + int len; + unsigned char nonce_counter[16]; + unsigned char stream_block[16]; +#endif + aes_context ctx; + + memset( key, 0, 32 ); + aes_init( &ctx ); + + /* + * ECB mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + polarssl_printf( " AES-ECB-%3d (%s): ", 128 + u * 64, + ( v == AES_DECRYPT ) ? "dec" : "enc" ); + + memset( buf, 0, 16 ); + + if( v == AES_DECRYPT ) + { + aes_setkey_dec( &ctx, key, 128 + u * 64 ); + + for( j = 0; j < 10000; j++ ) + aes_crypt_ecb( &ctx, v, buf, buf ); + + if( memcmp( buf, aes_test_ecb_dec[u], 16 ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto exit; + } + } + else + { + aes_setkey_enc( &ctx, key, 128 + u * 64 ); + + for( j = 0; j < 10000; j++ ) + aes_crypt_ecb( &ctx, v, buf, buf ); + + if( memcmp( buf, aes_test_ecb_enc[u], 16 ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto exit; + } + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); + +#if defined(POLARSSL_CIPHER_MODE_CBC) + /* + * CBC mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + polarssl_printf( " AES-CBC-%3d (%s): ", 128 + u * 64, + ( v == AES_DECRYPT ) ? "dec" : "enc" ); + + memset( iv , 0, 16 ); + memset( prv, 0, 16 ); + memset( buf, 0, 16 ); + + if( v == AES_DECRYPT ) + { + aes_setkey_dec( &ctx, key, 128 + u * 64 ); + + for( j = 0; j < 10000; j++ ) + aes_crypt_cbc( &ctx, v, 16, iv, buf, buf ); + + if( memcmp( buf, aes_test_cbc_dec[u], 16 ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto exit; + } + } + else + { + aes_setkey_enc( &ctx, key, 128 + u * 64 ); + + for( j = 0; j < 10000; j++ ) + { + unsigned char tmp[16]; + + aes_crypt_cbc( &ctx, v, 16, iv, buf, buf ); + + memcpy( tmp, prv, 16 ); + memcpy( prv, buf, 16 ); + memcpy( buf, tmp, 16 ); + } + + if( memcmp( prv, aes_test_cbc_enc[u], 16 ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto exit; + } + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_CIPHER_MODE_CFB) + /* + * CFB128 mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + polarssl_printf( " AES-CFB128-%3d (%s): ", 128 + u * 64, + ( v == AES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( iv, aes_test_cfb128_iv, 16 ); + memcpy( key, aes_test_cfb128_key[u], 16 + u * 8 ); + + offset = 0; + aes_setkey_enc( &ctx, key, 128 + u * 64 ); + + if( v == AES_DECRYPT ) + { + memcpy( buf, aes_test_cfb128_ct[u], 64 ); + aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf ); + + if( memcmp( buf, aes_test_cfb128_pt, 64 ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto exit; + } + } + else + { + memcpy( buf, aes_test_cfb128_pt, 64 ); + aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf ); + + if( memcmp( buf, aes_test_cfb128_ct[u], 64 ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto exit; + } + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); +#endif /* POLARSSL_CIPHER_MODE_CFB */ + +#if defined(POLARSSL_CIPHER_MODE_CTR) + /* + * CTR mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + polarssl_printf( " AES-CTR-128 (%s): ", + ( v == AES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( nonce_counter, aes_test_ctr_nonce_counter[u], 16 ); + memcpy( key, aes_test_ctr_key[u], 16 ); + + offset = 0; + aes_setkey_enc( &ctx, key, 128 ); + + if( v == AES_DECRYPT ) + { + len = aes_test_ctr_len[u]; + memcpy( buf, aes_test_ctr_ct[u], len ); + + aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, + buf, buf ); + + if( memcmp( buf, aes_test_ctr_pt[u], len ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto exit; + } + } + else + { + len = aes_test_ctr_len[u]; + memcpy( buf, aes_test_ctr_pt[u], len ); + + aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, + buf, buf ); + + if( memcmp( buf, aes_test_ctr_ct[u], len ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto exit; + } + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); +#endif /* POLARSSL_CIPHER_MODE_CTR */ + + ret = 0; + +exit: + aes_free( &ctx ); + + return( ret ); +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_AES_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/aesni.c b/component/common/network/ssl/polarssl-1.3.8/library/aesni.c new file mode 100644 index 0000000..97f646e --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/aesni.c @@ -0,0 +1,463 @@ +/* + * AES-NI support functions + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* + * [AES-WP] http://software.intel.com/en-us/articles/intel-advanced-encryption-standard-aes-instructions-set + * [CLMUL-WP] http://software.intel.com/en-us/articles/intel-carry-less-multiplication-instruction-and-its-usage-for-computing-the-gcm-mode/ + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_AESNI_C) + +#include "polarssl/aesni.h" +#include + +#if defined(POLARSSL_HAVE_X86_64) + +/* + * AES-NI support detection routine + */ +int aesni_supports( unsigned int what ) +{ + static int done = 0; + static unsigned int c = 0; + + if( ! done ) + { + asm( "movl $1, %%eax \n\t" + "cpuid \n\t" + : "=c" (c) + : + : "eax", "ebx", "edx" ); + done = 1; + } + + return( ( c & what ) != 0 ); +} + +/* + * Binutils needs to be at least 2.19 to support AES-NI instructions. + * Unfortunately, a lot of users have a lower version now (2014-04). + * Emit bytecode directly in order to support "old" version of gas. + * + * Opcodes from the Intel architecture reference manual, vol. 3. + * We always use registers, so we don't need prefixes for memory operands. + * Operand macros are in gas order (src, dst) as opposed to Intel order + * (dst, src) in order to blend better into the surrounding assembly code. + */ +#define AESDEC ".byte 0x66,0x0F,0x38,0xDE," +#define AESDECLAST ".byte 0x66,0x0F,0x38,0xDF," +#define AESENC ".byte 0x66,0x0F,0x38,0xDC," +#define AESENCLAST ".byte 0x66,0x0F,0x38,0xDD," +#define AESIMC ".byte 0x66,0x0F,0x38,0xDB," +#define AESKEYGENA ".byte 0x66,0x0F,0x3A,0xDF," +#define PCLMULQDQ ".byte 0x66,0x0F,0x3A,0x44," + +#define xmm0_xmm0 "0xC0" +#define xmm0_xmm1 "0xC8" +#define xmm0_xmm2 "0xD0" +#define xmm0_xmm3 "0xD8" +#define xmm0_xmm4 "0xE0" +#define xmm1_xmm0 "0xC1" +#define xmm1_xmm2 "0xD1" + +/* + * AES-NI AES-ECB block en(de)cryption + */ +int aesni_crypt_ecb( aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ) +{ + asm( "movdqu (%3), %%xmm0 \n\t" // load input + "movdqu (%1), %%xmm1 \n\t" // load round key 0 + "pxor %%xmm1, %%xmm0 \n\t" // round 0 + "addq $16, %1 \n\t" // point to next round key + "subl $1, %0 \n\t" // normal rounds = nr - 1 + "test %2, %2 \n\t" // mode? + "jz 2f \n\t" // 0 = decrypt + + "1: \n\t" // encryption loop + "movdqu (%1), %%xmm1 \n\t" // load round key + AESENC xmm1_xmm0 "\n\t" // do round + "addq $16, %1 \n\t" // point to next round key + "subl $1, %0 \n\t" // loop + "jnz 1b \n\t" + "movdqu (%1), %%xmm1 \n\t" // load round key + AESENCLAST xmm1_xmm0 "\n\t" // last round + "jmp 3f \n\t" + + "2: \n\t" // decryption loop + "movdqu (%1), %%xmm1 \n\t" + AESDEC xmm1_xmm0 "\n\t" // do round + "addq $16, %1 \n\t" + "subl $1, %0 \n\t" + "jnz 2b \n\t" + "movdqu (%1), %%xmm1 \n\t" // load round key + AESDECLAST xmm1_xmm0 "\n\t" // last round + + "3: \n\t" + "movdqu %%xmm0, (%4) \n\t" // export output + : + : "r" (ctx->nr), "r" (ctx->rk), "r" (mode), "r" (input), "r" (output) + : "memory", "cc", "xmm0", "xmm1" ); + + + return( 0 ); +} + +/* + * GCM multiplication: c = a times b in GF(2^128) + * Based on [CLMUL-WP] algorithms 1 (with equation 27) and 5. + */ +void aesni_gcm_mult( unsigned char c[16], + const unsigned char a[16], + const unsigned char b[16] ) +{ + unsigned char aa[16], bb[16], cc[16]; + size_t i; + + /* The inputs are in big-endian order, so byte-reverse them */ + for( i = 0; i < 16; i++ ) + { + aa[i] = a[15 - i]; + bb[i] = b[15 - i]; + } + + asm( "movdqu (%0), %%xmm0 \n\t" // a1:a0 + "movdqu (%1), %%xmm1 \n\t" // b1:b0 + + /* + * Caryless multiplication xmm2:xmm1 = xmm0 * xmm1 + * using [CLMUL-WP] algorithm 1 (p. 13). + */ + "movdqa %%xmm1, %%xmm2 \n\t" // copy of b1:b0 + "movdqa %%xmm1, %%xmm3 \n\t" // same + "movdqa %%xmm1, %%xmm4 \n\t" // same + PCLMULQDQ xmm0_xmm1 ",0x00 \n\t" // a0*b0 = c1:c0 + PCLMULQDQ xmm0_xmm2 ",0x11 \n\t" // a1*b1 = d1:d0 + PCLMULQDQ xmm0_xmm3 ",0x10 \n\t" // a0*b1 = e1:e0 + PCLMULQDQ xmm0_xmm4 ",0x01 \n\t" // a1*b0 = f1:f0 + "pxor %%xmm3, %%xmm4 \n\t" // e1+f1:e0+f0 + "movdqa %%xmm4, %%xmm3 \n\t" // same + "psrldq $8, %%xmm4 \n\t" // 0:e1+f1 + "pslldq $8, %%xmm3 \n\t" // e0+f0:0 + "pxor %%xmm4, %%xmm2 \n\t" // d1:d0+e1+f1 + "pxor %%xmm3, %%xmm1 \n\t" // c1+e0+f1:c0 + + /* + * Now shift the result one bit to the left, + * taking advantage of [CLMUL-WP] eq 27 (p. 20) + */ + "movdqa %%xmm1, %%xmm3 \n\t" // r1:r0 + "movdqa %%xmm2, %%xmm4 \n\t" // r3:r2 + "psllq $1, %%xmm1 \n\t" // r1<<1:r0<<1 + "psllq $1, %%xmm2 \n\t" // r3<<1:r2<<1 + "psrlq $63, %%xmm3 \n\t" // r1>>63:r0>>63 + "psrlq $63, %%xmm4 \n\t" // r3>>63:r2>>63 + "movdqa %%xmm3, %%xmm5 \n\t" // r1>>63:r0>>63 + "pslldq $8, %%xmm3 \n\t" // r0>>63:0 + "pslldq $8, %%xmm4 \n\t" // r2>>63:0 + "psrldq $8, %%xmm5 \n\t" // 0:r1>>63 + "por %%xmm3, %%xmm1 \n\t" // r1<<1|r0>>63:r0<<1 + "por %%xmm4, %%xmm2 \n\t" // r3<<1|r2>>62:r2<<1 + "por %%xmm5, %%xmm2 \n\t" // r3<<1|r2>>62:r2<<1|r1>>63 + + /* + * Now reduce modulo the GCM polynomial x^128 + x^7 + x^2 + x + 1 + * using [CLMUL-WP] algorithm 5 (p. 20). + * Currently xmm2:xmm1 holds x3:x2:x1:x0 (already shifted). + */ + /* Step 2 (1) */ + "movdqa %%xmm1, %%xmm3 \n\t" // x1:x0 + "movdqa %%xmm1, %%xmm4 \n\t" // same + "movdqa %%xmm1, %%xmm5 \n\t" // same + "psllq $63, %%xmm3 \n\t" // x1<<63:x0<<63 = stuff:a + "psllq $62, %%xmm4 \n\t" // x1<<62:x0<<62 = stuff:b + "psllq $57, %%xmm5 \n\t" // x1<<57:x0<<57 = stuff:c + + /* Step 2 (2) */ + "pxor %%xmm4, %%xmm3 \n\t" // stuff:a+b + "pxor %%xmm5, %%xmm3 \n\t" // stuff:a+b+c + "pslldq $8, %%xmm3 \n\t" // a+b+c:0 + "pxor %%xmm3, %%xmm1 \n\t" // x1+a+b+c:x0 = d:x0 + + /* Steps 3 and 4 */ + "movdqa %%xmm1,%%xmm0 \n\t" // d:x0 + "movdqa %%xmm1,%%xmm4 \n\t" // same + "movdqa %%xmm1,%%xmm5 \n\t" // same + "psrlq $1, %%xmm0 \n\t" // e1:x0>>1 = e1:e0' + "psrlq $2, %%xmm4 \n\t" // f1:x0>>2 = f1:f0' + "psrlq $7, %%xmm5 \n\t" // g1:x0>>7 = g1:g0' + "pxor %%xmm4, %%xmm0 \n\t" // e1+f1:e0'+f0' + "pxor %%xmm5, %%xmm0 \n\t" // e1+f1+g1:e0'+f0'+g0' + // e0'+f0'+g0' is almost e0+f0+g0, ex\tcept for some missing + // bits carried from d. Now get those\t bits back in. + "movdqa %%xmm1,%%xmm3 \n\t" // d:x0 + "movdqa %%xmm1,%%xmm4 \n\t" // same + "movdqa %%xmm1,%%xmm5 \n\t" // same + "psllq $63, %%xmm3 \n\t" // d<<63:stuff + "psllq $62, %%xmm4 \n\t" // d<<62:stuff + "psllq $57, %%xmm5 \n\t" // d<<57:stuff + "pxor %%xmm4, %%xmm3 \n\t" // d<<63+d<<62:stuff + "pxor %%xmm5, %%xmm3 \n\t" // missing bits of d:stuff + "psrldq $8, %%xmm3 \n\t" // 0:missing bits of d + "pxor %%xmm3, %%xmm0 \n\t" // e1+f1+g1:e0+f0+g0 + "pxor %%xmm1, %%xmm0 \n\t" // h1:h0 + "pxor %%xmm2, %%xmm0 \n\t" // x3+h1:x2+h0 + + "movdqu %%xmm0, (%2) \n\t" // done + : + : "r" (aa), "r" (bb), "r" (cc) + : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" ); + + /* Now byte-reverse the outputs */ + for( i = 0; i < 16; i++ ) + c[i] = cc[15 - i]; + + return; +} + +/* + * Compute decryption round keys from encryption round keys + */ +void aesni_inverse_key( unsigned char *invkey, + const unsigned char *fwdkey, int nr ) +{ + unsigned char *ik = invkey; + const unsigned char *fk = fwdkey + 16 * nr; + + memcpy( ik, fk, 16 ); + + for( fk -= 16, ik += 16; fk > fwdkey; fk -= 16, ik += 16 ) + asm( "movdqu (%0), %%xmm0 \n\t" + AESIMC xmm0_xmm0 "\n\t" + "movdqu %%xmm0, (%1) \n\t" + : + : "r" (fk), "r" (ik) + : "memory", "xmm0" ); + + memcpy( ik, fk, 16 ); +} + +/* + * Key expansion, 128-bit case + */ +static void aesni_setkey_enc_128( unsigned char *rk, + const unsigned char *key ) +{ + asm( "movdqu (%1), %%xmm0 \n\t" // copy the original key + "movdqu %%xmm0, (%0) \n\t" // as round key 0 + "jmp 2f \n\t" // skip auxiliary routine + + /* + * Finish generating the next round key. + * + * On entry xmm0 is r3:r2:r1:r0 and xmm1 is X:stuff:stuff:stuff + * with X = rot( sub( r3 ) ) ^ RCON. + * + * On exit, xmm0 is r7:r6:r5:r4 + * with r4 = X + r0, r5 = r4 + r1, r6 = r5 + r2, r7 = r6 + r3 + * and those are written to the round key buffer. + */ + "1: \n\t" + "pshufd $0xff, %%xmm1, %%xmm1 \n\t" // X:X:X:X + "pxor %%xmm0, %%xmm1 \n\t" // X+r3:X+r2:X+r1:r4 + "pslldq $4, %%xmm0 \n\t" // r2:r1:r0:0 + "pxor %%xmm0, %%xmm1 \n\t" // X+r3+r2:X+r2+r1:r5:r4 + "pslldq $4, %%xmm0 \n\t" // etc + "pxor %%xmm0, %%xmm1 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm1, %%xmm0 \n\t" // update xmm0 for next time! + "add $16, %0 \n\t" // point to next round key + "movdqu %%xmm0, (%0) \n\t" // write it + "ret \n\t" + + /* Main "loop" */ + "2: \n\t" + AESKEYGENA xmm0_xmm1 ",0x01 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x02 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x04 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x08 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x10 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x20 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x40 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x80 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x1B \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x36 \n\tcall 1b \n\t" + : + : "r" (rk), "r" (key) + : "memory", "cc", "0" ); +} + +/* + * Key expansion, 192-bit case + */ +static void aesni_setkey_enc_192( unsigned char *rk, + const unsigned char *key ) +{ + asm( "movdqu (%1), %%xmm0 \n\t" // copy original round key + "movdqu %%xmm0, (%0) \n\t" + "add $16, %0 \n\t" + "movq 16(%1), %%xmm1 \n\t" + "movq %%xmm1, (%0) \n\t" + "add $8, %0 \n\t" + "jmp 2f \n\t" // skip auxiliary routine + + /* + * Finish generating the next 6 quarter-keys. + * + * On entry xmm0 is r3:r2:r1:r0, xmm1 is stuff:stuff:r5:r4 + * and xmm2 is stuff:stuff:X:stuff with X = rot( sub( r3 ) ) ^ RCON. + * + * On exit, xmm0 is r9:r8:r7:r6 and xmm1 is stuff:stuff:r11:r10 + * and those are written to the round key buffer. + */ + "1: \n\t" + "pshufd $0x55, %%xmm2, %%xmm2 \n\t" // X:X:X:X + "pxor %%xmm0, %%xmm2 \n\t" // X+r3:X+r2:X+r1:r4 + "pslldq $4, %%xmm0 \n\t" // etc + "pxor %%xmm0, %%xmm2 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm0, %%xmm2 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm2, %%xmm0 \n\t" // update xmm0 = r9:r8:r7:r6 + "movdqu %%xmm0, (%0) \n\t" + "add $16, %0 \n\t" + "pshufd $0xff, %%xmm0, %%xmm2 \n\t" // r9:r9:r9:r9 + "pxor %%xmm1, %%xmm2 \n\t" // stuff:stuff:r9+r5:r10 + "pslldq $4, %%xmm1 \n\t" // r2:r1:r0:0 + "pxor %%xmm2, %%xmm1 \n\t" // xmm1 = stuff:stuff:r11:r10 + "movq %%xmm1, (%0) \n\t" + "add $8, %0 \n\t" + "ret \n\t" + + "2: \n\t" + AESKEYGENA xmm1_xmm2 ",0x01 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x02 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x04 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x08 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x10 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x20 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x40 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x80 \n\tcall 1b \n\t" + + : + : "r" (rk), "r" (key) + : "memory", "cc", "0" ); +} + +/* + * Key expansion, 256-bit case + */ +static void aesni_setkey_enc_256( unsigned char *rk, + const unsigned char *key ) +{ + asm( "movdqu (%1), %%xmm0 \n\t" + "movdqu %%xmm0, (%0) \n\t" + "add $16, %0 \n\t" + "movdqu 16(%1), %%xmm1 \n\t" + "movdqu %%xmm1, (%0) \n\t" + "jmp 2f \n\t" // skip auxiliary routine + + /* + * Finish generating the next two round keys. + * + * On entry xmm0 is r3:r2:r1:r0, xmm1 is r7:r6:r5:r4 and + * xmm2 is X:stuff:stuff:stuff with X = rot( sub( r7 )) ^ RCON + * + * On exit, xmm0 is r11:r10:r9:r8 and xmm1 is r15:r14:r13:r12 + * and those have been written to the output buffer. + */ + "1: \n\t" + "pshufd $0xff, %%xmm2, %%xmm2 \n\t" + "pxor %%xmm0, %%xmm2 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm0, %%xmm2 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm0, %%xmm2 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm2, %%xmm0 \n\t" + "add $16, %0 \n\t" + "movdqu %%xmm0, (%0) \n\t" + + /* Set xmm2 to stuff:Y:stuff:stuff with Y = subword( r11 ) + * and proceed to generate next round key from there */ + AESKEYGENA xmm0_xmm2 ",0x00 \n\t" + "pshufd $0xaa, %%xmm2, %%xmm2 \n\t" + "pxor %%xmm1, %%xmm2 \n\t" + "pslldq $4, %%xmm1 \n\t" + "pxor %%xmm1, %%xmm2 \n\t" + "pslldq $4, %%xmm1 \n\t" + "pxor %%xmm1, %%xmm2 \n\t" + "pslldq $4, %%xmm1 \n\t" + "pxor %%xmm2, %%xmm1 \n\t" + "add $16, %0 \n\t" + "movdqu %%xmm1, (%0) \n\t" + "ret \n\t" + + /* + * Main "loop" - Generating one more key than necessary, + * see definition of aes_context.buf + */ + "2: \n\t" + AESKEYGENA xmm1_xmm2 ",0x01 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x02 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x04 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x08 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x10 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x20 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x40 \n\tcall 1b \n\t" + : + : "r" (rk), "r" (key) + : "memory", "cc", "0" ); +} + +/* + * Key expansion, wrapper + */ +int aesni_setkey_enc( unsigned char *rk, + const unsigned char *key, + size_t bits ) +{ + switch( bits ) + { + case 128: aesni_setkey_enc_128( rk, key ); break; + case 192: aesni_setkey_enc_192( rk, key ); break; + case 256: aesni_setkey_enc_256( rk, key ); break; + default : return( POLARSSL_ERR_AES_INVALID_KEY_LENGTH ); + } + + return( 0 ); +} + +#endif /* POLARSSL_HAVE_X86_64 */ + +#endif /* POLARSSL_AESNI_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/arc4.c b/component/common/network/ssl/polarssl-1.3.8/library/arc4.c new file mode 100644 index 0000000..54e89ea --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/arc4.c @@ -0,0 +1,208 @@ +/* + * An implementation of the ARCFOUR algorithm + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * The ARCFOUR algorithm was publicly disclosed on 94/09. + * + * http://groups.google.com/group/sci.crypt/msg/10a300c9d21afca0 + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_ARC4_C) + +#include "polarssl/arc4.h" + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#define polarssl_printf printf +#endif + +#if !defined(POLARSSL_ARC4_ALT) + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +void arc4_init( arc4_context *ctx ) +{ + memset( ctx, 0, sizeof( arc4_context ) ); +} + +void arc4_free( arc4_context *ctx ) +{ + if( ctx == NULL ) + return; + + polarssl_zeroize( ctx, sizeof( arc4_context ) ); +} + +/* + * ARC4 key schedule + */ +void arc4_setup( arc4_context *ctx, const unsigned char *key, + unsigned int keylen ) +{ + int i, j, a; + unsigned int k; + unsigned char *m; + + ctx->x = 0; + ctx->y = 0; + m = ctx->m; + + for( i = 0; i < 256; i++ ) + m[i] = (unsigned char) i; + + j = k = 0; + + for( i = 0; i < 256; i++, k++ ) + { + if( k >= keylen ) k = 0; + + a = m[i]; + j = ( j + a + key[k] ) & 0xFF; + m[i] = m[j]; + m[j] = (unsigned char) a; + } +} + +/* + * ARC4 cipher function + */ +int arc4_crypt( arc4_context *ctx, size_t length, const unsigned char *input, + unsigned char *output ) +{ + int x, y, a, b; + size_t i; + unsigned char *m; + + x = ctx->x; + y = ctx->y; + m = ctx->m; + + for( i = 0; i < length; i++ ) + { + x = ( x + 1 ) & 0xFF; a = m[x]; + y = ( y + a ) & 0xFF; b = m[y]; + + m[x] = (unsigned char) b; + m[y] = (unsigned char) a; + + output[i] = (unsigned char) + ( input[i] ^ m[(unsigned char)( a + b )] ); + } + + ctx->x = x; + ctx->y = y; + + return( 0 ); +} + +#endif /* !POLARSSL_ARC4_ALT */ + +#if defined(POLARSSL_SELF_TEST) + +#include +#include + +/* + * ARC4 tests vectors as posted by Eric Rescorla in sep. 1994: + * + * http://groups.google.com/group/comp.security.misc/msg/10a300c9d21afca0 + */ +static const unsigned char arc4_test_key[3][8] = +{ + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}; + +static const unsigned char arc4_test_pt[3][8] = +{ + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}; + +static const unsigned char arc4_test_ct[3][8] = +{ + { 0x75, 0xB7, 0x87, 0x80, 0x99, 0xE0, 0xC5, 0x96 }, + { 0x74, 0x94, 0xC2, 0xE7, 0x10, 0x4B, 0x08, 0x79 }, + { 0xDE, 0x18, 0x89, 0x41, 0xA3, 0x37, 0x5D, 0x3A } +}; + +/* + * Checkup routine + */ +int arc4_self_test( int verbose ) +{ + int i, ret = 0; + unsigned char ibuf[8]; + unsigned char obuf[8]; + arc4_context ctx; + + arc4_init( &ctx ); + + for( i = 0; i < 3; i++ ) + { + if( verbose != 0 ) + polarssl_printf( " ARC4 test #%d: ", i + 1 ); + + memcpy( ibuf, arc4_test_pt[i], 8 ); + + arc4_setup( &ctx, arc4_test_key[i], 8 ); + arc4_crypt( &ctx, 8, ibuf, obuf ); + + if( memcmp( obuf, arc4_test_ct[i], 8 ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); + +exit: + arc4_free( &ctx ); + + return( ret ); +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_ARC4_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/asn1parse.c b/component/common/network/ssl/polarssl-1.3.8/library/asn1parse.c new file mode 100644 index 0000000..9744352 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/asn1parse.c @@ -0,0 +1,391 @@ +/* + * Generic ASN.1 parsing + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_ASN1_PARSE_C) + +#include "polarssl/asn1.h" + +#if defined(POLARSSL_BIGNUM_C) +#include "polarssl/bignum.h" +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#define polarssl_malloc malloc +#define polarssl_free free +#endif + +#include +#include + +/* + * ASN.1 DER decoding routines + */ +int asn1_get_len( unsigned char **p, + const unsigned char *end, + size_t *len ) +{ + if( ( end - *p ) < 1 ) + return( POLARSSL_ERR_ASN1_OUT_OF_DATA ); + + if( ( **p & 0x80 ) == 0 ) + *len = *(*p)++; + else + { + switch( **p & 0x7F ) + { + case 1: + if( ( end - *p ) < 2 ) + return( POLARSSL_ERR_ASN1_OUT_OF_DATA ); + + *len = (*p)[1]; + (*p) += 2; + break; + + case 2: + if( ( end - *p ) < 3 ) + return( POLARSSL_ERR_ASN1_OUT_OF_DATA ); + + *len = ( (*p)[1] << 8 ) | (*p)[2]; + (*p) += 3; + break; + + case 3: + if( ( end - *p ) < 4 ) + return( POLARSSL_ERR_ASN1_OUT_OF_DATA ); + + *len = ( (*p)[1] << 16 ) | ( (*p)[2] << 8 ) | (*p)[3]; + (*p) += 4; + break; + + case 4: + if( ( end - *p ) < 5 ) + return( POLARSSL_ERR_ASN1_OUT_OF_DATA ); + + *len = ( (*p)[1] << 24 ) | ( (*p)[2] << 16 ) | ( (*p)[3] << 8 ) | + (*p)[4]; + (*p) += 5; + break; + + default: + return( POLARSSL_ERR_ASN1_INVALID_LENGTH ); + } + } + + if( *len > (size_t) ( end - *p ) ) + return( POLARSSL_ERR_ASN1_OUT_OF_DATA ); + + return( 0 ); +} + +int asn1_get_tag( unsigned char **p, + const unsigned char *end, + size_t *len, int tag ) +{ + if( ( end - *p ) < 1 ) + return( POLARSSL_ERR_ASN1_OUT_OF_DATA ); + + if( **p != tag ) + return( POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); + + (*p)++; + + return( asn1_get_len( p, end, len ) ); +} + +int asn1_get_bool( unsigned char **p, + const unsigned char *end, + int *val ) +{ + int ret; + size_t len; + + if( ( ret = asn1_get_tag( p, end, &len, ASN1_BOOLEAN ) ) != 0 ) + return( ret ); + + if( len != 1 ) + return( POLARSSL_ERR_ASN1_INVALID_LENGTH ); + + *val = ( **p != 0 ) ? 1 : 0; + (*p)++; + + return( 0 ); +} + +int asn1_get_int( unsigned char **p, + const unsigned char *end, + int *val ) +{ + int ret; + size_t len; + + if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 ) + return( ret ); + + if( len > sizeof( int ) || ( **p & 0x80 ) != 0 ) + return( POLARSSL_ERR_ASN1_INVALID_LENGTH ); + + *val = 0; + + while( len-- > 0 ) + { + *val = ( *val << 8 ) | **p; + (*p)++; + } + + return( 0 ); +} + +#if defined(POLARSSL_BIGNUM_C) +int asn1_get_mpi( unsigned char **p, + const unsigned char *end, + mpi *X ) +{ + int ret; + size_t len; + + if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 ) + return( ret ); + + ret = mpi_read_binary( X, *p, len ); + + *p += len; + + return( ret ); +} +#endif /* POLARSSL_BIGNUM_C */ + +int asn1_get_bitstring( unsigned char **p, const unsigned char *end, + asn1_bitstring *bs) +{ + int ret; + + /* Certificate type is a single byte bitstring */ + if( ( ret = asn1_get_tag( p, end, &bs->len, ASN1_BIT_STRING ) ) != 0 ) + return( ret ); + + /* Check length, subtract one for actual bit string length */ + if( bs->len < 1 ) + return( POLARSSL_ERR_ASN1_OUT_OF_DATA ); + bs->len -= 1; + + /* Get number of unused bits, ensure unused bits <= 7 */ + bs->unused_bits = **p; + if( bs->unused_bits > 7 ) + return( POLARSSL_ERR_ASN1_INVALID_LENGTH ); + (*p)++; + + /* Get actual bitstring */ + bs->p = *p; + *p += bs->len; + + if( *p != end ) + return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * Get a bit string without unused bits + */ +int asn1_get_bitstring_null( unsigned char **p, const unsigned char *end, + size_t *len ) +{ + int ret; + + if( ( ret = asn1_get_tag( p, end, len, ASN1_BIT_STRING ) ) != 0 ) + return( ret ); + + if( (*len)-- < 2 || *(*p)++ != 0 ) + return( POLARSSL_ERR_ASN1_INVALID_DATA ); + + return( 0 ); +} + + + +/* + * Parses and splits an ASN.1 "SEQUENCE OF " + */ +int asn1_get_sequence_of( unsigned char **p, + const unsigned char *end, + asn1_sequence *cur, + int tag) +{ + int ret; + size_t len; + asn1_buf *buf; + + /* Get main sequence tag */ + if( ( ret = asn1_get_tag( p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + if( *p + len != end ) + return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + while( *p < end ) + { + buf = &(cur->buf); + buf->tag = **p; + + if( ( ret = asn1_get_tag( p, end, &buf->len, tag ) ) != 0 ) + return( ret ); + + buf->p = *p; + *p += buf->len; + + /* Allocate and assign next pointer */ + if( *p < end ) + { + cur->next = (asn1_sequence *) polarssl_malloc( + sizeof( asn1_sequence ) ); + + if( cur->next == NULL ) + return( POLARSSL_ERR_ASN1_MALLOC_FAILED ); + + cur = cur->next; + } + } + + /* Set final sequence entry's next pointer to NULL */ + cur->next = NULL; + + if( *p != end ) + return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +int asn1_get_alg( unsigned char **p, + const unsigned char *end, + asn1_buf *alg, asn1_buf *params ) +{ + int ret; + size_t len; + + if( ( ret = asn1_get_tag( p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + if( ( end - *p ) < 1 ) + return( POLARSSL_ERR_ASN1_OUT_OF_DATA ); + + alg->tag = **p; + end = *p + len; + + if( ( ret = asn1_get_tag( p, end, &alg->len, ASN1_OID ) ) != 0 ) + return( ret ); + + alg->p = *p; + *p += alg->len; + + if( *p == end ) + { + memset( params, 0, sizeof(asn1_buf) ); + return( 0 ); + } + + params->tag = **p; + (*p)++; + + if( ( ret = asn1_get_len( p, end, ¶ms->len ) ) != 0 ) + return( ret ); + + params->p = *p; + *p += params->len; + + if( *p != end ) + return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +int asn1_get_alg_null( unsigned char **p, + const unsigned char *end, + asn1_buf *alg ) +{ + int ret; + asn1_buf params; + + memset( ¶ms, 0, sizeof(asn1_buf) ); + + if( ( ret = asn1_get_alg( p, end, alg, ¶ms ) ) != 0 ) + return( ret ); + + if( ( params.tag != ASN1_NULL && params.tag != 0 ) || params.len != 0 ) + return( POLARSSL_ERR_ASN1_INVALID_DATA ); + + return( 0 ); +} + +void asn1_free_named_data( asn1_named_data *cur ) +{ + if( cur == NULL ) + return; + + polarssl_free( cur->oid.p ); + polarssl_free( cur->val.p ); + + memset( cur, 0, sizeof( asn1_named_data ) ); +} + +void asn1_free_named_data_list( asn1_named_data **head ) +{ + asn1_named_data *cur; + + while( ( cur = *head ) != NULL ) + { + *head = cur->next; + asn1_free_named_data( cur ); + polarssl_free( cur ); + } +} + +asn1_named_data *asn1_find_named_data( asn1_named_data *list, + const char *oid, size_t len ) +{ + while( list != NULL ) + { + if( list->oid.len == len && + memcmp( list->oid.p, oid, len ) == 0 ) + { + break; + } + + list = list->next; + } + + return( list ); +} + +#endif /* POLARSSL_ASN1_PARSE_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/asn1write.c b/component/common/network/ssl/polarssl-1.3.8/library/asn1write.c new file mode 100644 index 0000000..ebc0e97 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/asn1write.c @@ -0,0 +1,366 @@ +/* + * ASN.1 buffer writing functionality + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_ASN1_WRITE_C) + +#include "polarssl/asn1write.h" + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include +#define polarssl_malloc malloc +#define polarssl_free free +#endif + +int asn1_write_len( unsigned char **p, unsigned char *start, size_t len ) +{ + if( len < 0x80 ) + { + if( *p - start < 1 ) + return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = (unsigned char) len; + return( 1 ); + } + + if( len <= 0xFF ) + { + if( *p - start < 2 ) + return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = (unsigned char) len; + *--(*p) = 0x81; + return( 2 ); + } + + if( *p - start < 3 ) + return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + + // We assume we never have lengths larger than 65535 bytes + // + *--(*p) = len % 256; + *--(*p) = ( len / 256 ) % 256; + *--(*p) = 0x82; + + return( 3 ); +} + +int asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag ) +{ + if( *p - start < 1 ) + return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = tag; + + return( 1 ); +} + +int asn1_write_raw_buffer( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ) +{ + size_t len = 0; + + if( *p - start < (int) size ) + return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + + len = size; + (*p) -= len; + memcpy( *p, buf, len ); + + return( (int) len ); +} + +#if defined(POLARSSL_BIGNUM_C) +int asn1_write_mpi( unsigned char **p, unsigned char *start, mpi *X ) +{ + int ret; + size_t len = 0; + + // Write the MPI + // + len = mpi_size( X ); + + if( *p - start < (int) len ) + return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + + (*p) -= len; + MPI_CHK( mpi_write_binary( X, *p, len ) ); + + // DER format assumes 2s complement for numbers, so the leftmost bit + // should be 0 for positive numbers and 1 for negative numbers. + // + if( X->s ==1 && **p & 0x80 ) + { + if( *p - start < 1 ) + return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = 0x00; + len += 1; + } + + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_INTEGER ) ); + + ret = (int) len; + +cleanup: + return( ret ); +} +#endif /* POLARSSL_BIGNUM_C */ + +int asn1_write_null( unsigned char **p, unsigned char *start ) +{ + int ret; + size_t len = 0; + + // Write NULL + // + ASN1_CHK_ADD( len, asn1_write_len( p, start, 0) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_NULL ) ); + + return( (int) len ); +} + +int asn1_write_oid( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len ) +{ + int ret; + size_t len = 0; + + ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, + (const unsigned char *) oid, oid_len ) ); + ASN1_CHK_ADD( len , asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len , asn1_write_tag( p, start, ASN1_OID ) ); + + return( (int) len ); +} + +int asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len, + size_t par_len ) +{ + int ret; + size_t len = 0; + + if( par_len == 0 ) + ASN1_CHK_ADD( len, asn1_write_null( p, start ) ); + else + len += par_len; + + ASN1_CHK_ADD( len, asn1_write_oid( p, start, oid, oid_len ) ); + + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +int asn1_write_bool( unsigned char **p, unsigned char *start, int boolean ) +{ + int ret; + size_t len = 0; + + if( *p - start < 1 ) + return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = (boolean) ? 1 : 0; + len++; + + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_BOOLEAN ) ); + + return( (int) len ); +} + +int asn1_write_int( unsigned char **p, unsigned char *start, int val ) +{ + int ret; + size_t len = 0; + + // TODO negative values and values larger than 128 + // DER format assumes 2s complement for numbers, so the leftmost bit + // should be 0 for positive numbers and 1 for negative numbers. + // + if( *p - start < 1 ) + return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + + len += 1; + *--(*p) = val; + + if( val > 0 && **p & 0x80 ) + { + if( *p - start < 1 ) + return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = 0x00; + len += 1; + } + + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_INTEGER ) ); + + return( (int) len ); +} + +int asn1_write_printable_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ) +{ + int ret; + size_t len = 0; + + ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, + (const unsigned char *) text, text_len ) ); + + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_PRINTABLE_STRING ) ); + + return( (int) len ); +} + +int asn1_write_ia5_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ) +{ + int ret; + size_t len = 0; + + ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, + (const unsigned char *) text, text_len ) ); + + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_IA5_STRING ) ); + + return( (int) len ); +} + +int asn1_write_bitstring( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t bits ) +{ + int ret; + size_t len = 0, size; + + size = ( bits / 8 ) + ( ( bits % 8 ) ? 1 : 0 ); + + // Calculate byte length + // + if( *p - start < (int) size + 1 ) + return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + + len = size + 1; + (*p) -= size; + memcpy( *p, buf, size ); + + // Write unused bits + // + *--(*p) = (unsigned char) (size * 8 - bits); + + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_BIT_STRING ) ); + + return( (int) len ); +} + +int asn1_write_octet_string( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ) +{ + int ret; + size_t len = 0; + + ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, buf, size ) ); + + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OCTET_STRING ) ); + + return( (int) len ); +} + +asn1_named_data *asn1_store_named_data( asn1_named_data **head, + const char *oid, size_t oid_len, + const unsigned char *val, + size_t val_len ) +{ + asn1_named_data *cur; + + if( ( cur = asn1_find_named_data( *head, oid, oid_len ) ) == NULL ) + { + // Add new entry if not present yet based on OID + // + if( ( cur = polarssl_malloc( sizeof(asn1_named_data) ) ) == NULL ) + return( NULL ); + + memset( cur, 0, sizeof(asn1_named_data) ); + + cur->oid.len = oid_len; + cur->oid.p = polarssl_malloc( oid_len ); + if( cur->oid.p == NULL ) + { + polarssl_free( cur ); + return( NULL ); + } + + cur->val.len = val_len; + cur->val.p = polarssl_malloc( val_len ); + if( cur->val.p == NULL ) + { + polarssl_free( cur->oid.p ); + polarssl_free( cur ); + return( NULL ); + } + + memcpy( cur->oid.p, oid, oid_len ); + + cur->next = *head; + *head = cur; + } + else if( cur->val.len < val_len ) + { + // Enlarge existing value buffer if needed + // + polarssl_free( cur->val.p ); + cur->val.p = NULL; + + cur->val.len = val_len; + cur->val.p = polarssl_malloc( val_len ); + if( cur->val.p == NULL ) + { + polarssl_free( cur->oid.p ); + polarssl_free( cur ); + return( NULL ); + } + } + + if( val != NULL ) + memcpy( cur->val.p, val, val_len ); + + return( cur ); +} +#endif /* POLARSSL_ASN1_WRITE_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/base64.c b/component/common/network/ssl/polarssl-1.3.8/library/base64.c new file mode 100644 index 0000000..39a8323 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/base64.c @@ -0,0 +1,273 @@ +/* + * RFC 1521 base64 encoding/decoding + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_BASE64_C) + +#include "polarssl/base64.h" + +#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32) +#include +typedef UINT32 uint32_t; +#else +#include +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#define polarssl_printf printf +#endif + +static const unsigned char base64_enc_map[64] = +{ + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', + 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', + 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', + 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', '+', '/' +}; + +static const unsigned char base64_dec_map[128] = +{ + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 62, 127, 127, 127, 63, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 127, 127, + 127, 64, 127, 127, 127, 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, 127, 127, 127, 127, 127, 127, 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, 127, 127, 127, 127, 127 +}; + +/* + * Encode a buffer into base64 format + */ +int base64_encode( unsigned char *dst, size_t *dlen, + const unsigned char *src, size_t slen ) +{ + size_t i, n; + int C1, C2, C3; + unsigned char *p; + + if( slen == 0 ) + return( 0 ); + + n = ( slen << 3 ) / 6; + + switch( ( slen << 3 ) - ( n * 6 ) ) + { + case 2: n += 3; break; + case 4: n += 2; break; + default: break; + } + + if( *dlen < n + 1 ) + { + *dlen = n + 1; + return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + n = ( slen / 3 ) * 3; + + for( i = 0, p = dst; i < n; i += 3 ) + { + C1 = *src++; + C2 = *src++; + C3 = *src++; + + *p++ = base64_enc_map[(C1 >> 2) & 0x3F]; + *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; + *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F]; + *p++ = base64_enc_map[C3 & 0x3F]; + } + + if( i < slen ) + { + C1 = *src++; + C2 = ( ( i + 1 ) < slen ) ? *src++ : 0; + + *p++ = base64_enc_map[(C1 >> 2) & 0x3F]; + *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; + + if( ( i + 1 ) < slen ) + *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F]; + else *p++ = '='; + + *p++ = '='; + } + + *dlen = p - dst; + *p = 0; + + return( 0 ); +} + +/* + * Decode a base64-formatted buffer + */ +int base64_decode( unsigned char *dst, size_t *dlen, + const unsigned char *src, size_t slen ) +{ + size_t i, n; + uint32_t j, x; + unsigned char *p; + + for( i = n = j = 0; i < slen; i++ ) + { + if( ( slen - i ) >= 2 && + src[i] == '\r' && src[i + 1] == '\n' ) + continue; + + if( src[i] == '\n' ) + continue; + + if( src[i] == '=' && ++j > 2 ) + return( POLARSSL_ERR_BASE64_INVALID_CHARACTER ); + + if( src[i] > 127 || base64_dec_map[src[i]] == 127 ) + return( POLARSSL_ERR_BASE64_INVALID_CHARACTER ); + + if( base64_dec_map[src[i]] < 64 && j != 0 ) + return( POLARSSL_ERR_BASE64_INVALID_CHARACTER ); + + n++; + } + + if( n == 0 ) + return( 0 ); + + n = ( ( n * 6 ) + 7 ) >> 3; + n -= j; + + if( dst == NULL || *dlen < n ) + { + *dlen = n; + return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ ) + { + if( *src == '\r' || *src == '\n' ) + continue; + + j -= ( base64_dec_map[*src] == 64 ); + x = ( x << 6 ) | ( base64_dec_map[*src] & 0x3F ); + + if( ++n == 4 ) + { + n = 0; + if( j > 0 ) *p++ = (unsigned char)( x >> 16 ); + if( j > 1 ) *p++ = (unsigned char)( x >> 8 ); + if( j > 2 ) *p++ = (unsigned char)( x ); + } + } + + *dlen = p - dst; + + return( 0 ); +} + +#if defined(POLARSSL_SELF_TEST) + +#include +#include + +static const unsigned char base64_test_dec[64] = +{ + 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD, + 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01, + 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09, + 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13, + 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31, + 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38, + 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B, + 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97 +}; + +static const unsigned char base64_test_enc[] = + "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK" + "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw=="; + +/* + * Checkup routine + */ +int base64_self_test( int verbose ) +{ + size_t len; + const unsigned char *src; + unsigned char buffer[128]; + + if( verbose != 0 ) + polarssl_printf( " Base64 encoding test: " ); + + len = sizeof( buffer ); + src = base64_test_dec; + + if( base64_encode( buffer, &len, src, 64 ) != 0 || + memcmp( base64_test_enc, buffer, 88 ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + polarssl_printf( "passed\n Base64 decoding test: " ); + + len = sizeof( buffer ); + src = base64_test_enc; + + if( base64_decode( buffer, &len, src, 88 ) != 0 || + memcmp( base64_test_dec, buffer, 64 ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + polarssl_printf( "passed\n\n" ); + + return( 0 ); +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_BASE64_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/bignum.c b/component/common/network/ssl/polarssl-1.3.8/library/bignum.c new file mode 100644 index 0000000..80cf0f8 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/bignum.c @@ -0,0 +1,2344 @@ +/* + * Multi-precision integer library + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * This MPI implementation is based on: + * + * http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf + * http://www.stillhq.com/extracted/gnupg-api/mpi/ + * http://math.libtomcrypt.com/files/tommath.pdf + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_BIGNUM_C) + +#include "polarssl/bignum.h" +#include "polarssl/bn_mul.h" + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#define polarssl_printf printf +#define polarssl_malloc malloc +#define polarssl_free free +#endif + +#include + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +#define ciL (sizeof(t_uint)) /* chars in limb */ +#define biL (ciL << 3) /* bits in limb */ +#define biH (ciL << 2) /* half limb size */ + +/* + * Convert between bits/chars and number of limbs + */ +#define BITS_TO_LIMBS(i) (((i) + biL - 1) / biL) +#define CHARS_TO_LIMBS(i) (((i) + ciL - 1) / ciL) + +/* + * Initialize one MPI + */ +void mpi_init( mpi *X ) +{ + if( X == NULL ) + return; + + X->s = 1; + X->n = 0; + X->p = NULL; +} + +/* + * Unallocate one MPI + */ +void mpi_free( mpi *X ) +{ + if( X == NULL ) + return; + + if( X->p != NULL ) + { + polarssl_zeroize( X->p, X->n * ciL ); + polarssl_free( X->p ); + } + + X->s = 1; + X->n = 0; + X->p = NULL; +} + +/* + * Enlarge to the specified number of limbs + */ +int mpi_grow( mpi *X, size_t nblimbs ) +{ + t_uint *p; + + if( nblimbs > POLARSSL_MPI_MAX_LIMBS ) + return( POLARSSL_ERR_MPI_MALLOC_FAILED ); + + if( X->n < nblimbs ) + { + if( ( p = (t_uint *) polarssl_malloc( nblimbs * ciL ) ) == NULL ) + return( POLARSSL_ERR_MPI_MALLOC_FAILED ); + + memset( p, 0, nblimbs * ciL ); + + if( X->p != NULL ) + { + memcpy( p, X->p, X->n * ciL ); + polarssl_zeroize( X->p, X->n * ciL ); + polarssl_free( X->p ); + } + + X->n = nblimbs; + X->p = p; + } + + return( 0 ); +} + +/* + * Resize down as much as possible, + * while keeping at least the specified number of limbs + */ +int mpi_shrink( mpi *X, size_t nblimbs ) +{ + t_uint *p; + size_t i; + + /* Actually resize up in this case */ + if( X->n <= nblimbs ) + return( mpi_grow( X, nblimbs ) ); + + for( i = X->n - 1; i > 0; i-- ) + if( X->p[i] != 0 ) + break; + i++; + + if( i < nblimbs ) + i = nblimbs; + + if( ( p = (t_uint *) polarssl_malloc( i * ciL ) ) == NULL ) + return( POLARSSL_ERR_MPI_MALLOC_FAILED ); + + memset( p, 0, i * ciL ); + + if( X->p != NULL ) + { + memcpy( p, X->p, i * ciL ); + polarssl_zeroize( X->p, X->n * ciL ); + polarssl_free( X->p ); + } + + X->n = i; + X->p = p; + + return( 0 ); +} + +/* + * Copy the contents of Y into X + */ +int mpi_copy( mpi *X, const mpi *Y ) +{ + int ret; + size_t i; + + if( X == Y ) + return( 0 ); + + if( Y->p == NULL ) + { + mpi_free( X ); + return( 0 ); + } + + for( i = Y->n - 1; i > 0; i-- ) + if( Y->p[i] != 0 ) + break; + i++; + + X->s = Y->s; + + MPI_CHK( mpi_grow( X, i ) ); + + memset( X->p, 0, X->n * ciL ); + memcpy( X->p, Y->p, i * ciL ); + +cleanup: + + return( ret ); +} + +/* + * Swap the contents of X and Y + */ +void mpi_swap( mpi *X, mpi *Y ) +{ + mpi T; + + memcpy( &T, X, sizeof( mpi ) ); + memcpy( X, Y, sizeof( mpi ) ); + memcpy( Y, &T, sizeof( mpi ) ); +} + +/* + * Conditionally assign X = Y, without leaking information + * about whether the assignment was made or not. + * (Leaking information about the respective sizes of X and Y is ok however.) + */ +int mpi_safe_cond_assign( mpi *X, const mpi *Y, unsigned char assign ) +{ + int ret = 0; + size_t i; + + /* make sure assign is 0 or 1 */ + assign = ( assign != 0 ); + + MPI_CHK( mpi_grow( X, Y->n ) ); + + X->s = X->s * ( 1 - assign ) + Y->s * assign; + + for( i = 0; i < Y->n; i++ ) + X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign; + + for( ; i < X->n; i++ ) + X->p[i] *= ( 1 - assign ); + +cleanup: + return( ret ); +} + +/* + * Conditionally swap X and Y, without leaking information + * about whether the swap was made or not. + * Here it is not ok to simply swap the pointers, which whould lead to + * different memory access patterns when X and Y are used afterwards. + */ +int mpi_safe_cond_swap( mpi *X, mpi *Y, unsigned char swap ) +{ + int ret, s; + size_t i; + t_uint tmp; + + if( X == Y ) + return( 0 ); + + /* make sure swap is 0 or 1 */ + swap = ( swap != 0 ); + + MPI_CHK( mpi_grow( X, Y->n ) ); + MPI_CHK( mpi_grow( Y, X->n ) ); + + s = X->s; + X->s = X->s * ( 1 - swap ) + Y->s * swap; + Y->s = Y->s * ( 1 - swap ) + s * swap; + + + for( i = 0; i < X->n; i++ ) + { + tmp = X->p[i]; + X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap; + Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap; + } + +cleanup: + return( ret ); +} + +/* + * Set value from integer + */ +int mpi_lset( mpi *X, t_sint z ) +{ + int ret; + + MPI_CHK( mpi_grow( X, 1 ) ); + memset( X->p, 0, X->n * ciL ); + + X->p[0] = ( z < 0 ) ? -z : z; + X->s = ( z < 0 ) ? -1 : 1; + +cleanup: + + return( ret ); +} + +/* + * Get a specific bit + */ +int mpi_get_bit( const mpi *X, size_t pos ) +{ + if( X->n * biL <= pos ) + return( 0 ); + + return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 ); +} + +/* + * Set a bit to a specific value of 0 or 1 + */ +int mpi_set_bit( mpi *X, size_t pos, unsigned char val ) +{ + int ret = 0; + size_t off = pos / biL; + size_t idx = pos % biL; + + if( val != 0 && val != 1 ) + return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); + + if( X->n * biL <= pos ) + { + if( val == 0 ) + return( 0 ); + + MPI_CHK( mpi_grow( X, off + 1 ) ); + } + + X->p[off] &= ~( (t_uint) 0x01 << idx ); + X->p[off] |= (t_uint) val << idx; + +cleanup: + + return( ret ); +} + +/* + * Return the number of least significant bits + */ +size_t mpi_lsb( const mpi *X ) +{ + size_t i, j, count = 0; + + for( i = 0; i < X->n; i++ ) + for( j = 0; j < biL; j++, count++ ) + if( ( ( X->p[i] >> j ) & 1 ) != 0 ) + return( count ); + + return( 0 ); +} + +/* + * Return the number of most significant bits + */ +size_t mpi_msb( const mpi *X ) +{ + size_t i, j; + + for( i = X->n - 1; i > 0; i-- ) + if( X->p[i] != 0 ) + break; + + for( j = biL; j > 0; j-- ) + if( ( ( X->p[i] >> ( j - 1 ) ) & 1 ) != 0 ) + break; + + return( ( i * biL ) + j ); +} + +/* + * Return the total size in bytes + */ +size_t mpi_size( const mpi *X ) +{ + return( ( mpi_msb( X ) + 7 ) >> 3 ); +} + +/* + * Convert an ASCII character to digit value + */ +static int mpi_get_digit( t_uint *d, int radix, char c ) +{ + *d = 255; + + if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30; + if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37; + if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57; + + if( *d >= (t_uint) radix ) + return( POLARSSL_ERR_MPI_INVALID_CHARACTER ); + + return( 0 ); +} + +/* + * Import from an ASCII string + */ +int mpi_read_string( mpi *X, int radix, const char *s ) +{ + int ret; + size_t i, j, slen, n; + t_uint d; + mpi T; + + if( radix < 2 || radix > 16 ) + return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); + + mpi_init( &T ); + + slen = strlen( s ); + + if( radix == 16 ) + { + n = BITS_TO_LIMBS( slen << 2 ); + + MPI_CHK( mpi_grow( X, n ) ); + MPI_CHK( mpi_lset( X, 0 ) ); + + for( i = slen, j = 0; i > 0; i--, j++ ) + { + if( i == 1 && s[i - 1] == '-' ) + { + X->s = -1; + break; + } + + MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) ); + X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 ); + } + } + else + { + MPI_CHK( mpi_lset( X, 0 ) ); + + for( i = 0; i < slen; i++ ) + { + if( i == 0 && s[i] == '-' ) + { + X->s = -1; + continue; + } + + MPI_CHK( mpi_get_digit( &d, radix, s[i] ) ); + MPI_CHK( mpi_mul_int( &T, X, radix ) ); + + if( X->s == 1 ) + { + MPI_CHK( mpi_add_int( X, &T, d ) ); + } + else + { + MPI_CHK( mpi_sub_int( X, &T, d ) ); + } + } + } + +cleanup: + + mpi_free( &T ); + + return( ret ); +} + +/* + * Helper to write the digits high-order first + */ +static int mpi_write_hlp( mpi *X, int radix, char **p ) +{ + int ret; + t_uint r; + + if( radix < 2 || radix > 16 ) + return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); + + MPI_CHK( mpi_mod_int( &r, X, radix ) ); + MPI_CHK( mpi_div_int( X, NULL, X, radix ) ); + + if( mpi_cmp_int( X, 0 ) != 0 ) + MPI_CHK( mpi_write_hlp( X, radix, p ) ); + + if( r < 10 ) + *(*p)++ = (char)( r + 0x30 ); + else + *(*p)++ = (char)( r + 0x37 ); + +cleanup: + + return( ret ); +} + +/* + * Export into an ASCII string + */ +int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen ) +{ + int ret = 0; + size_t n; + char *p; + mpi T; + + if( radix < 2 || radix > 16 ) + return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); + + n = mpi_msb( X ); + if( radix >= 4 ) n >>= 1; + if( radix >= 16 ) n >>= 1; + n += 3; + + if( *slen < n ) + { + *slen = n; + return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL ); + } + + p = s; + mpi_init( &T ); + + if( X->s == -1 ) + *p++ = '-'; + + if( radix == 16 ) + { + int c; + size_t i, j, k; + + for( i = X->n, k = 0; i > 0; i-- ) + { + for( j = ciL; j > 0; j-- ) + { + c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF; + + if( c == 0 && k == 0 && ( i + j ) != 2 ) + continue; + + *(p++) = "0123456789ABCDEF" [c / 16]; + *(p++) = "0123456789ABCDEF" [c % 16]; + k = 1; + } + } + } + else + { + MPI_CHK( mpi_copy( &T, X ) ); + + if( T.s == -1 ) + T.s = 1; + + MPI_CHK( mpi_write_hlp( &T, radix, &p ) ); + } + + *p++ = '\0'; + *slen = p - s; + +cleanup: + + mpi_free( &T ); + + return( ret ); +} + +#if defined(POLARSSL_FS_IO) +/* + * Read X from an opened file + */ +int mpi_read_file( mpi *X, int radix, FILE *fin ) +{ + t_uint d; + size_t slen; + char *p; + /* + * Buffer should have space for (short) label and decimal formatted MPI, + * newline characters and '\0' + */ + char s[ POLARSSL_MPI_RW_BUFFER_SIZE ]; + + memset( s, 0, sizeof( s ) ); + if( fgets( s, sizeof( s ) - 1, fin ) == NULL ) + return( POLARSSL_ERR_MPI_FILE_IO_ERROR ); + + slen = strlen( s ); + if( slen == sizeof( s ) - 2 ) + return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL ); + + if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; } + if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; } + + p = s + slen; + while( --p >= s ) + if( mpi_get_digit( &d, radix, *p ) != 0 ) + break; + + return( mpi_read_string( X, radix, p + 1 ) ); +} + +/* + * Write X into an opened file (or stdout if fout == NULL) + */ +int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout ) +{ + int ret; + size_t n, slen, plen; + /* + * Buffer should have space for (short) label and decimal formatted MPI, + * newline characters and '\0' + */ + char s[ POLARSSL_MPI_RW_BUFFER_SIZE ]; + + n = sizeof( s ); + memset( s, 0, n ); + n -= 2; + + MPI_CHK( mpi_write_string( X, radix, s, (size_t *) &n ) ); + + if( p == NULL ) p = ""; + + plen = strlen( p ); + slen = strlen( s ); + s[slen++] = '\r'; + s[slen++] = '\n'; + + if( fout != NULL ) + { + if( fwrite( p, 1, plen, fout ) != plen || + fwrite( s, 1, slen, fout ) != slen ) + return( POLARSSL_ERR_MPI_FILE_IO_ERROR ); + } + else + polarssl_printf( "%s%s", p, s ); + +cleanup: + + return( ret ); +} +#endif /* POLARSSL_FS_IO */ + +/* + * Import X from unsigned binary data, big endian + */ +int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen ) +{ + int ret; + size_t i, j, n; + + for( n = 0; n < buflen; n++ ) + if( buf[n] != 0 ) + break; + + MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) ); + MPI_CHK( mpi_lset( X, 0 ) ); + + for( i = buflen, j = 0; i > n; i--, j++ ) + X->p[j / ciL] |= ((t_uint) buf[i - 1]) << ((j % ciL) << 3); + +cleanup: + + return( ret ); +} + +/* + * Export X into unsigned binary data, big endian + */ +int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen ) +{ + size_t i, j, n; + + n = mpi_size( X ); + + if( buflen < n ) + return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL ); + + memset( buf, 0, buflen ); + + for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- ) + buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) ); + + return( 0 ); +} + +/* + * Left-shift: X <<= count + */ +int mpi_shift_l( mpi *X, size_t count ) +{ + int ret; + size_t i, v0, t1; + t_uint r0 = 0, r1; + + v0 = count / (biL ); + t1 = count & (biL - 1); + + i = mpi_msb( X ) + count; + + if( X->n * biL < i ) + MPI_CHK( mpi_grow( X, BITS_TO_LIMBS( i ) ) ); + + ret = 0; + + /* + * shift by count / limb_size + */ + if( v0 > 0 ) + { + for( i = X->n; i > v0; i-- ) + X->p[i - 1] = X->p[i - v0 - 1]; + + for( ; i > 0; i-- ) + X->p[i - 1] = 0; + } + + /* + * shift by count % limb_size + */ + if( t1 > 0 ) + { + for( i = v0; i < X->n; i++ ) + { + r1 = X->p[i] >> (biL - t1); + X->p[i] <<= t1; + X->p[i] |= r0; + r0 = r1; + } + } + +cleanup: + + return( ret ); +} + +/* + * Right-shift: X >>= count + */ +int mpi_shift_r( mpi *X, size_t count ) +{ + size_t i, v0, v1; + t_uint r0 = 0, r1; + + v0 = count / biL; + v1 = count & (biL - 1); + + if( v0 > X->n || ( v0 == X->n && v1 > 0 ) ) + return mpi_lset( X, 0 ); + + /* + * shift by count / limb_size + */ + if( v0 > 0 ) + { + for( i = 0; i < X->n - v0; i++ ) + X->p[i] = X->p[i + v0]; + + for( ; i < X->n; i++ ) + X->p[i] = 0; + } + + /* + * shift by count % limb_size + */ + if( v1 > 0 ) + { + for( i = X->n; i > 0; i-- ) + { + r1 = X->p[i - 1] << (biL - v1); + X->p[i - 1] >>= v1; + X->p[i - 1] |= r0; + r0 = r1; + } + } + + return( 0 ); +} + +/* + * Compare unsigned values + */ +int mpi_cmp_abs( const mpi *X, const mpi *Y ) +{ + size_t i, j; + + for( i = X->n; i > 0; i-- ) + if( X->p[i - 1] != 0 ) + break; + + for( j = Y->n; j > 0; j-- ) + if( Y->p[j - 1] != 0 ) + break; + + if( i == 0 && j == 0 ) + return( 0 ); + + if( i > j ) return( 1 ); + if( j > i ) return( -1 ); + + for( ; i > 0; i-- ) + { + if( X->p[i - 1] > Y->p[i - 1] ) return( 1 ); + if( X->p[i - 1] < Y->p[i - 1] ) return( -1 ); + } + + return( 0 ); +} + +/* + * Compare signed values + */ +int mpi_cmp_mpi( const mpi *X, const mpi *Y ) +{ + size_t i, j; + + for( i = X->n; i > 0; i-- ) + if( X->p[i - 1] != 0 ) + break; + + for( j = Y->n; j > 0; j-- ) + if( Y->p[j - 1] != 0 ) + break; + + if( i == 0 && j == 0 ) + return( 0 ); + + if( i > j ) return( X->s ); + if( j > i ) return( -Y->s ); + + if( X->s > 0 && Y->s < 0 ) return( 1 ); + if( Y->s > 0 && X->s < 0 ) return( -1 ); + + for( ; i > 0; i-- ) + { + if( X->p[i - 1] > Y->p[i - 1] ) return( X->s ); + if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s ); + } + + return( 0 ); +} + +/* + * Compare signed values + */ +int mpi_cmp_int( const mpi *X, t_sint z ) +{ + mpi Y; + t_uint p[1]; + + *p = ( z < 0 ) ? -z : z; + Y.s = ( z < 0 ) ? -1 : 1; + Y.n = 1; + Y.p = p; + + return( mpi_cmp_mpi( X, &Y ) ); +} + +/* + * Unsigned addition: X = |A| + |B| (HAC 14.7) + */ +int mpi_add_abs( mpi *X, const mpi *A, const mpi *B ) +{ + int ret; + size_t i, j; + t_uint *o, *p, c; + + if( X == B ) + { + const mpi *T = A; A = X; B = T; + } + + if( X != A ) + MPI_CHK( mpi_copy( X, A ) ); + + /* + * X should always be positive as a result of unsigned additions. + */ + X->s = 1; + + for( j = B->n; j > 0; j-- ) + if( B->p[j - 1] != 0 ) + break; + + MPI_CHK( mpi_grow( X, j ) ); + + o = B->p; p = X->p; c = 0; + + for( i = 0; i < j; i++, o++, p++ ) + { + *p += c; c = ( *p < c ); + *p += *o; c += ( *p < *o ); + } + + while( c != 0 ) + { + if( i >= X->n ) + { + MPI_CHK( mpi_grow( X, i + 1 ) ); + p = X->p + i; + } + + *p += c; c = ( *p < c ); i++; p++; + } + +cleanup: + + return( ret ); +} + +/* + * Helper for mpi subtraction + */ +static void mpi_sub_hlp( size_t n, t_uint *s, t_uint *d ) +{ + size_t i; + t_uint c, z; + + for( i = c = 0; i < n; i++, s++, d++ ) + { + z = ( *d < c ); *d -= c; + c = ( *d < *s ) + z; *d -= *s; + } + + while( c != 0 ) + { + z = ( *d < c ); *d -= c; + c = z; i++; d++; + } +} + +/* + * Unsigned subtraction: X = |A| - |B| (HAC 14.9) + */ +int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B ) +{ + mpi TB; + int ret; + size_t n; + + if( mpi_cmp_abs( A, B ) < 0 ) + return( POLARSSL_ERR_MPI_NEGATIVE_VALUE ); + + mpi_init( &TB ); + + if( X == B ) + { + MPI_CHK( mpi_copy( &TB, B ) ); + B = &TB; + } + + if( X != A ) + MPI_CHK( mpi_copy( X, A ) ); + + /* + * X should always be positive as a result of unsigned subtractions. + */ + X->s = 1; + + ret = 0; + + for( n = B->n; n > 0; n-- ) + if( B->p[n - 1] != 0 ) + break; + + mpi_sub_hlp( n, B->p, X->p ); + +cleanup: + + mpi_free( &TB ); + + return( ret ); +} + +/* + * Signed addition: X = A + B + */ +int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B ) +{ + int ret, s = A->s; + + if( A->s * B->s < 0 ) + { + if( mpi_cmp_abs( A, B ) >= 0 ) + { + MPI_CHK( mpi_sub_abs( X, A, B ) ); + X->s = s; + } + else + { + MPI_CHK( mpi_sub_abs( X, B, A ) ); + X->s = -s; + } + } + else + { + MPI_CHK( mpi_add_abs( X, A, B ) ); + X->s = s; + } + +cleanup: + + return( ret ); +} + +/* + * Signed subtraction: X = A - B + */ +int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B ) +{ + int ret, s = A->s; + + if( A->s * B->s > 0 ) + { + if( mpi_cmp_abs( A, B ) >= 0 ) + { + MPI_CHK( mpi_sub_abs( X, A, B ) ); + X->s = s; + } + else + { + MPI_CHK( mpi_sub_abs( X, B, A ) ); + X->s = -s; + } + } + else + { + MPI_CHK( mpi_add_abs( X, A, B ) ); + X->s = s; + } + +cleanup: + + return( ret ); +} + +/* + * Signed addition: X = A + b + */ +int mpi_add_int( mpi *X, const mpi *A, t_sint b ) +{ + mpi _B; + t_uint p[1]; + + p[0] = ( b < 0 ) ? -b : b; + _B.s = ( b < 0 ) ? -1 : 1; + _B.n = 1; + _B.p = p; + + return( mpi_add_mpi( X, A, &_B ) ); +} + +/* + * Signed subtraction: X = A - b + */ +int mpi_sub_int( mpi *X, const mpi *A, t_sint b ) +{ + mpi _B; + t_uint p[1]; + + p[0] = ( b < 0 ) ? -b : b; + _B.s = ( b < 0 ) ? -1 : 1; + _B.n = 1; + _B.p = p; + + return( mpi_sub_mpi( X, A, &_B ) ); +} + +/* + * Helper for mpi multiplication + */ +static +#if defined(__APPLE__) && defined(__arm__) +/* + * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn) + * appears to need this to prevent bad ARM code generation at -O3. + */ +__attribute__ ((noinline)) +#endif +void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b ) +{ + t_uint c = 0, t = 0; + +#if defined(MULADDC_HUIT) + for( ; i >= 8; i -= 8 ) + { + MULADDC_INIT + MULADDC_HUIT + MULADDC_STOP + } + + for( ; i > 0; i-- ) + { + MULADDC_INIT + MULADDC_CORE + MULADDC_STOP + } +#else /* MULADDC_HUIT */ + for( ; i >= 16; i -= 16 ) + { + MULADDC_INIT + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_STOP + } + + for( ; i >= 8; i -= 8 ) + { + MULADDC_INIT + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_STOP + } + + for( ; i > 0; i-- ) + { + MULADDC_INIT + MULADDC_CORE + MULADDC_STOP + } +#endif /* MULADDC_HUIT */ + + t++; + + do { + *d += c; c = ( *d < c ); d++; + } + while( c != 0 ); +} + +/* + * Baseline multiplication: X = A * B (HAC 14.12) + */ +int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B ) +{ + int ret; + size_t i, j; + mpi TA, TB; + + mpi_init( &TA ); mpi_init( &TB ); + + if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; } + if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; } + + for( i = A->n; i > 0; i-- ) + if( A->p[i - 1] != 0 ) + break; + + for( j = B->n; j > 0; j-- ) + if( B->p[j - 1] != 0 ) + break; + + MPI_CHK( mpi_grow( X, i + j ) ); + MPI_CHK( mpi_lset( X, 0 ) ); + + for( i++; j > 0; j-- ) + mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] ); + + X->s = A->s * B->s; + +cleanup: + + mpi_free( &TB ); mpi_free( &TA ); + + return( ret ); +} + +/* + * Baseline multiplication: X = A * b + */ +int mpi_mul_int( mpi *X, const mpi *A, t_sint b ) +{ + mpi _B; + t_uint p[1]; + + _B.s = 1; + _B.n = 1; + _B.p = p; + p[0] = b; + + return( mpi_mul_mpi( X, A, &_B ) ); +} + +/* + * Division by mpi: A = Q * B + R (HAC 14.20) + */ +int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B ) +{ + int ret; + size_t i, n, t, k; + mpi X, Y, Z, T1, T2; + + if( mpi_cmp_int( B, 0 ) == 0 ) + return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO ); + + mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z ); + mpi_init( &T1 ); mpi_init( &T2 ); + + if( mpi_cmp_abs( A, B ) < 0 ) + { + if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) ); + if( R != NULL ) MPI_CHK( mpi_copy( R, A ) ); + return( 0 ); + } + + MPI_CHK( mpi_copy( &X, A ) ); + MPI_CHK( mpi_copy( &Y, B ) ); + X.s = Y.s = 1; + + MPI_CHK( mpi_grow( &Z, A->n + 2 ) ); + MPI_CHK( mpi_lset( &Z, 0 ) ); + MPI_CHK( mpi_grow( &T1, 2 ) ); + MPI_CHK( mpi_grow( &T2, 3 ) ); + + k = mpi_msb( &Y ) % biL; + if( k < biL - 1 ) + { + k = biL - 1 - k; + MPI_CHK( mpi_shift_l( &X, k ) ); + MPI_CHK( mpi_shift_l( &Y, k ) ); + } + else k = 0; + + n = X.n - 1; + t = Y.n - 1; + MPI_CHK( mpi_shift_l( &Y, biL * ( n - t ) ) ); + + while( mpi_cmp_mpi( &X, &Y ) >= 0 ) + { + Z.p[n - t]++; + MPI_CHK( mpi_sub_mpi( &X, &X, &Y ) ); + } + MPI_CHK( mpi_shift_r( &Y, biL * ( n - t ) ) ); + + for( i = n; i > t ; i-- ) + { + if( X.p[i] >= Y.p[t] ) + Z.p[i - t - 1] = ~0; + else + { + /* + * The version of Clang shipped by Apple with Mavericks around + * 2014-03 can't handle 128-bit division properly. Disable + * 128-bits division for this version. Let's be optimistic and + * assume it'll be fixed in the next minor version (next + * patchlevel is probably a bit too optimistic). + */ +#if defined(POLARSSL_HAVE_UDBL) && \ + ! ( defined(__x86_64__) && defined(__APPLE__) && \ + defined(__clang_major__) && __clang_major__ == 5 && \ + defined(__clang_minor__) && __clang_minor__ == 0 ) + t_udbl r; + + r = (t_udbl) X.p[i] << biL; + r |= (t_udbl) X.p[i - 1]; + r /= Y.p[t]; + if( r > ( (t_udbl) 1 << biL ) - 1 ) + r = ( (t_udbl) 1 << biL ) - 1; + + Z.p[i - t - 1] = (t_uint) r; +#else + /* + * __udiv_qrnnd_c, from gmp/longlong.h + */ + t_uint q0, q1, r0, r1; + t_uint d0, d1, d, m; + + d = Y.p[t]; + d0 = ( d << biH ) >> biH; + d1 = ( d >> biH ); + + q1 = X.p[i] / d1; + r1 = X.p[i] - d1 * q1; + r1 <<= biH; + r1 |= ( X.p[i - 1] >> biH ); + + m = q1 * d0; + if( r1 < m ) + { + q1--, r1 += d; + while( r1 >= d && r1 < m ) + q1--, r1 += d; + } + r1 -= m; + + q0 = r1 / d1; + r0 = r1 - d1 * q0; + r0 <<= biH; + r0 |= ( X.p[i - 1] << biH ) >> biH; + + m = q0 * d0; + if( r0 < m ) + { + q0--, r0 += d; + while( r0 >= d && r0 < m ) + q0--, r0 += d; + } + r0 -= m; + + Z.p[i - t - 1] = ( q1 << biH ) | q0; +#endif /* POLARSSL_HAVE_UDBL && !64-bit Apple with Clang 5.0 */ + } + + Z.p[i - t - 1]++; + do + { + Z.p[i - t - 1]--; + + MPI_CHK( mpi_lset( &T1, 0 ) ); + T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1]; + T1.p[1] = Y.p[t]; + MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) ); + + MPI_CHK( mpi_lset( &T2, 0 ) ); + T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2]; + T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1]; + T2.p[2] = X.p[i]; + } + while( mpi_cmp_mpi( &T1, &T2 ) > 0 ); + + MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) ); + MPI_CHK( mpi_shift_l( &T1, biL * ( i - t - 1 ) ) ); + MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) ); + + if( mpi_cmp_int( &X, 0 ) < 0 ) + { + MPI_CHK( mpi_copy( &T1, &Y ) ); + MPI_CHK( mpi_shift_l( &T1, biL * ( i - t - 1 ) ) ); + MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) ); + Z.p[i - t - 1]--; + } + } + + if( Q != NULL ) + { + MPI_CHK( mpi_copy( Q, &Z ) ); + Q->s = A->s * B->s; + } + + if( R != NULL ) + { + MPI_CHK( mpi_shift_r( &X, k ) ); + X.s = A->s; + MPI_CHK( mpi_copy( R, &X ) ); + + if( mpi_cmp_int( R, 0 ) == 0 ) + R->s = 1; + } + +cleanup: + + mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z ); + mpi_free( &T1 ); mpi_free( &T2 ); + + return( ret ); +} + +/* + * Division by int: A = Q * b + R + */ +int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b ) +{ + mpi _B; + t_uint p[1]; + + p[0] = ( b < 0 ) ? -b : b; + _B.s = ( b < 0 ) ? -1 : 1; + _B.n = 1; + _B.p = p; + + return( mpi_div_mpi( Q, R, A, &_B ) ); +} + +/* + * Modulo: R = A mod B + */ +int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B ) +{ + int ret; + + if( mpi_cmp_int( B, 0 ) < 0 ) + return( POLARSSL_ERR_MPI_NEGATIVE_VALUE ); + + MPI_CHK( mpi_div_mpi( NULL, R, A, B ) ); + + while( mpi_cmp_int( R, 0 ) < 0 ) + MPI_CHK( mpi_add_mpi( R, R, B ) ); + + while( mpi_cmp_mpi( R, B ) >= 0 ) + MPI_CHK( mpi_sub_mpi( R, R, B ) ); + +cleanup: + + return( ret ); +} + +/* + * Modulo: r = A mod b + */ +int mpi_mod_int( t_uint *r, const mpi *A, t_sint b ) +{ + size_t i; + t_uint x, y, z; + + if( b == 0 ) + return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO ); + + if( b < 0 ) + return( POLARSSL_ERR_MPI_NEGATIVE_VALUE ); + + /* + * handle trivial cases + */ + if( b == 1 ) + { + *r = 0; + return( 0 ); + } + + if( b == 2 ) + { + *r = A->p[0] & 1; + return( 0 ); + } + + /* + * general case + */ + for( i = A->n, y = 0; i > 0; i-- ) + { + x = A->p[i - 1]; + y = ( y << biH ) | ( x >> biH ); + z = y / b; + y -= z * b; + + x <<= biH; + y = ( y << biH ) | ( x >> biH ); + z = y / b; + y -= z * b; + } + + /* + * If A is negative, then the current y represents a negative value. + * Flipping it to the positive side. + */ + if( A->s < 0 && y != 0 ) + y = b - y; + + *r = y; + + return( 0 ); +} + +/* + * Fast Montgomery initialization (thanks to Tom St Denis) + */ +static void mpi_montg_init( t_uint *mm, const mpi *N ) +{ + t_uint x, m0 = N->p[0]; + unsigned int i; + + x = m0; + x += ( ( m0 + 2 ) & 4 ) << 1; + + for( i = biL; i >= 8; i /= 2 ) + x *= ( 2 - ( m0 * x ) ); + + *mm = ~x + 1; +} + +/* + * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36) + */ +static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm, + const mpi *T ) +{ + size_t i, n, m; + t_uint u0, u1, *d; + + memset( T->p, 0, T->n * ciL ); + + d = T->p; + n = N->n; + m = ( B->n < n ) ? B->n : n; + + for( i = 0; i < n; i++ ) + { + /* + * T = (T + u0*B + u1*N) / 2^biL + */ + u0 = A->p[i]; + u1 = ( d[0] + u0 * B->p[0] ) * mm; + + mpi_mul_hlp( m, B->p, d, u0 ); + mpi_mul_hlp( n, N->p, d, u1 ); + + *d++ = u0; d[n + 1] = 0; + } + + memcpy( A->p, d, ( n + 1 ) * ciL ); + + if( mpi_cmp_abs( A, N ) >= 0 ) + mpi_sub_hlp( n, N->p, A->p ); + else + /* prevent timing attacks */ + mpi_sub_hlp( n, A->p, T->p ); +} + +/* + * Montgomery reduction: A = A * R^-1 mod N + */ +static void mpi_montred( mpi *A, const mpi *N, t_uint mm, const mpi *T ) +{ + t_uint z = 1; + mpi U; + + U.n = U.s = (int) z; + U.p = &z; + + mpi_montmul( A, &U, N, mm, T ); +} + +/* + * Sliding-window exponentiation: X = A^E mod N (HAC 14.85) + */ +int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR ) +{ + int ret; + size_t wbits, wsize, one = 1; + size_t i, j, nblimbs; + size_t bufsize, nbits; + t_uint ei, mm, state; + mpi RR, T, W[ 2 << POLARSSL_MPI_WINDOW_SIZE ], Apos; + int neg; + + if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 ) + return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); + + if( mpi_cmp_int( E, 0 ) < 0 ) + return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); + + /* + * Init temps and window size + */ + mpi_montg_init( &mm, N ); + mpi_init( &RR ); mpi_init( &T ); + mpi_init( &Apos ); + memset( W, 0, sizeof( W ) ); + + i = mpi_msb( E ); + + wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 : + ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1; + + if( wsize > POLARSSL_MPI_WINDOW_SIZE ) + wsize = POLARSSL_MPI_WINDOW_SIZE; + + j = N->n + 1; + MPI_CHK( mpi_grow( X, j ) ); + MPI_CHK( mpi_grow( &W[1], j ) ); + MPI_CHK( mpi_grow( &T, j * 2 ) ); + + /* + * Compensate for negative A (and correct at the end) + */ + neg = ( A->s == -1 ); + if( neg ) + { + MPI_CHK( mpi_copy( &Apos, A ) ); + Apos.s = 1; + A = &Apos; + } + + /* + * If 1st call, pre-compute R^2 mod N + */ + if( _RR == NULL || _RR->p == NULL ) + { + MPI_CHK( mpi_lset( &RR, 1 ) ); + MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) ); + MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) ); + + if( _RR != NULL ) + memcpy( _RR, &RR, sizeof( mpi ) ); + } + else + memcpy( &RR, _RR, sizeof( mpi ) ); + + /* + * W[1] = A * R^2 * R^-1 mod N = A * R mod N + */ + if( mpi_cmp_mpi( A, N ) >= 0 ) + MPI_CHK( mpi_mod_mpi( &W[1], A, N ) ); + else + MPI_CHK( mpi_copy( &W[1], A ) ); + + mpi_montmul( &W[1], &RR, N, mm, &T ); + + /* + * X = R^2 * R^-1 mod N = R mod N + */ + MPI_CHK( mpi_copy( X, &RR ) ); + mpi_montred( X, N, mm, &T ); + + if( wsize > 1 ) + { + /* + * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1) + */ + j = one << ( wsize - 1 ); + + MPI_CHK( mpi_grow( &W[j], N->n + 1 ) ); + MPI_CHK( mpi_copy( &W[j], &W[1] ) ); + + for( i = 0; i < wsize - 1; i++ ) + mpi_montmul( &W[j], &W[j], N, mm, &T ); + + /* + * W[i] = W[i - 1] * W[1] + */ + for( i = j + 1; i < ( one << wsize ); i++ ) + { + MPI_CHK( mpi_grow( &W[i], N->n + 1 ) ); + MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) ); + + mpi_montmul( &W[i], &W[1], N, mm, &T ); + } + } + + nblimbs = E->n; + bufsize = 0; + nbits = 0; + wbits = 0; + state = 0; + + while( 1 ) + { + if( bufsize == 0 ) + { + if( nblimbs == 0 ) + break; + + nblimbs--; + + bufsize = sizeof( t_uint ) << 3; + } + + bufsize--; + + ei = (E->p[nblimbs] >> bufsize) & 1; + + /* + * skip leading 0s + */ + if( ei == 0 && state == 0 ) + continue; + + if( ei == 0 && state == 1 ) + { + /* + * out of window, square X + */ + mpi_montmul( X, X, N, mm, &T ); + continue; + } + + /* + * add ei to current window + */ + state = 2; + + nbits++; + wbits |= ( ei << ( wsize - nbits ) ); + + if( nbits == wsize ) + { + /* + * X = X^wsize R^-1 mod N + */ + for( i = 0; i < wsize; i++ ) + mpi_montmul( X, X, N, mm, &T ); + + /* + * X = X * W[wbits] R^-1 mod N + */ + mpi_montmul( X, &W[wbits], N, mm, &T ); + + state--; + nbits = 0; + wbits = 0; + } + } + + /* + * process the remaining bits + */ + for( i = 0; i < nbits; i++ ) + { + mpi_montmul( X, X, N, mm, &T ); + + wbits <<= 1; + + if( ( wbits & ( one << wsize ) ) != 0 ) + mpi_montmul( X, &W[1], N, mm, &T ); + } + + /* + * X = A^E * R * R^-1 mod N = A^E mod N + */ + mpi_montred( X, N, mm, &T ); + + if( neg ) + { + X->s = -1; + MPI_CHK( mpi_add_mpi( X, N, X ) ); + } + +cleanup: + + for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ ) + mpi_free( &W[i] ); + + mpi_free( &W[1] ); mpi_free( &T ); mpi_free( &Apos ); + + if( _RR == NULL || _RR->p == NULL ) + mpi_free( &RR ); + + return( ret ); +} + +/* + * Greatest common divisor: G = gcd(A, B) (HAC 14.54) + */ +int mpi_gcd( mpi *G, const mpi *A, const mpi *B ) +{ + int ret; + size_t lz, lzt; + mpi TG, TA, TB; + + mpi_init( &TG ); mpi_init( &TA ); mpi_init( &TB ); + + MPI_CHK( mpi_copy( &TA, A ) ); + MPI_CHK( mpi_copy( &TB, B ) ); + + lz = mpi_lsb( &TA ); + lzt = mpi_lsb( &TB ); + + if( lzt < lz ) + lz = lzt; + + MPI_CHK( mpi_shift_r( &TA, lz ) ); + MPI_CHK( mpi_shift_r( &TB, lz ) ); + + TA.s = TB.s = 1; + + while( mpi_cmp_int( &TA, 0 ) != 0 ) + { + MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) ); + MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) ); + + if( mpi_cmp_mpi( &TA, &TB ) >= 0 ) + { + MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) ); + MPI_CHK( mpi_shift_r( &TA, 1 ) ); + } + else + { + MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) ); + MPI_CHK( mpi_shift_r( &TB, 1 ) ); + } + } + + MPI_CHK( mpi_shift_l( &TB, lz ) ); + MPI_CHK( mpi_copy( G, &TB ) ); + +cleanup: + + mpi_free( &TG ); mpi_free( &TA ); mpi_free( &TB ); + + return( ret ); +} + +/* + * Fill X with size bytes of random. + * + * Use a temporary bytes representation to make sure the result is the same + * regardless of the platform endianness (useful when f_rng is actually + * deterministic, eg for tests). + */ +int mpi_fill_random( mpi *X, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + unsigned char buf[POLARSSL_MPI_MAX_SIZE]; + + if( size > POLARSSL_MPI_MAX_SIZE ) + return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); + + MPI_CHK( f_rng( p_rng, buf, size ) ); + MPI_CHK( mpi_read_binary( X, buf, size ) ); + +cleanup: + return( ret ); +} + +/* + * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64) + */ +int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N ) +{ + int ret; + mpi G, TA, TU, U1, U2, TB, TV, V1, V2; + + if( mpi_cmp_int( N, 0 ) <= 0 ) + return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); + + mpi_init( &TA ); mpi_init( &TU ); mpi_init( &U1 ); mpi_init( &U2 ); + mpi_init( &G ); mpi_init( &TB ); mpi_init( &TV ); + mpi_init( &V1 ); mpi_init( &V2 ); + + MPI_CHK( mpi_gcd( &G, A, N ) ); + + if( mpi_cmp_int( &G, 1 ) != 0 ) + { + ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE; + goto cleanup; + } + + MPI_CHK( mpi_mod_mpi( &TA, A, N ) ); + MPI_CHK( mpi_copy( &TU, &TA ) ); + MPI_CHK( mpi_copy( &TB, N ) ); + MPI_CHK( mpi_copy( &TV, N ) ); + + MPI_CHK( mpi_lset( &U1, 1 ) ); + MPI_CHK( mpi_lset( &U2, 0 ) ); + MPI_CHK( mpi_lset( &V1, 0 ) ); + MPI_CHK( mpi_lset( &V2, 1 ) ); + + do + { + while( ( TU.p[0] & 1 ) == 0 ) + { + MPI_CHK( mpi_shift_r( &TU, 1 ) ); + + if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 ) + { + MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) ); + MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) ); + } + + MPI_CHK( mpi_shift_r( &U1, 1 ) ); + MPI_CHK( mpi_shift_r( &U2, 1 ) ); + } + + while( ( TV.p[0] & 1 ) == 0 ) + { + MPI_CHK( mpi_shift_r( &TV, 1 ) ); + + if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 ) + { + MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) ); + MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) ); + } + + MPI_CHK( mpi_shift_r( &V1, 1 ) ); + MPI_CHK( mpi_shift_r( &V2, 1 ) ); + } + + if( mpi_cmp_mpi( &TU, &TV ) >= 0 ) + { + MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) ); + MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) ); + MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) ); + } + else + { + MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) ); + MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) ); + MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) ); + } + } + while( mpi_cmp_int( &TU, 0 ) != 0 ); + + while( mpi_cmp_int( &V1, 0 ) < 0 ) + MPI_CHK( mpi_add_mpi( &V1, &V1, N ) ); + + while( mpi_cmp_mpi( &V1, N ) >= 0 ) + MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) ); + + MPI_CHK( mpi_copy( X, &V1 ) ); + +cleanup: + + mpi_free( &TA ); mpi_free( &TU ); mpi_free( &U1 ); mpi_free( &U2 ); + mpi_free( &G ); mpi_free( &TB ); mpi_free( &TV ); + mpi_free( &V1 ); mpi_free( &V2 ); + + return( ret ); +} + +#if defined(POLARSSL_GENPRIME) + +static const int small_prime[] = +{ + 3, 5, 7, 11, 13, 17, 19, 23, + 29, 31, 37, 41, 43, 47, 53, 59, + 61, 67, 71, 73, 79, 83, 89, 97, + 101, 103, 107, 109, 113, 127, 131, 137, + 139, 149, 151, 157, 163, 167, 173, 179, + 181, 191, 193, 197, 199, 211, 223, 227, + 229, 233, 239, 241, 251, 257, 263, 269, + 271, 277, 281, 283, 293, 307, 311, 313, + 317, 331, 337, 347, 349, 353, 359, 367, + 373, 379, 383, 389, 397, 401, 409, 419, + 421, 431, 433, 439, 443, 449, 457, 461, + 463, 467, 479, 487, 491, 499, 503, 509, + 521, 523, 541, 547, 557, 563, 569, 571, + 577, 587, 593, 599, 601, 607, 613, 617, + 619, 631, 641, 643, 647, 653, 659, 661, + 673, 677, 683, 691, 701, 709, 719, 727, + 733, 739, 743, 751, 757, 761, 769, 773, + 787, 797, 809, 811, 821, 823, 827, 829, + 839, 853, 857, 859, 863, 877, 881, 883, + 887, 907, 911, 919, 929, 937, 941, 947, + 953, 967, 971, 977, 983, 991, 997, -103 +}; + +/* + * Small divisors test (X must be positive) + * + * Return values: + * 0: no small factor (possible prime, more tests needed) + * 1: certain prime + * POLARSSL_ERR_MPI_NOT_ACCEPTABLE: certain non-prime + * other negative: error + */ +static int mpi_check_small_factors( const mpi *X ) +{ + int ret = 0; + size_t i; + t_uint r; + + if( ( X->p[0] & 1 ) == 0 ) + return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE ); + + for( i = 0; small_prime[i] > 0; i++ ) + { + if( mpi_cmp_int( X, small_prime[i] ) <= 0 ) + return( 1 ); + + MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) ); + + if( r == 0 ) + return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE ); + } + +cleanup: + return( ret ); +} + +/* + * Miller-Rabin pseudo-primality test (HAC 4.24) + */ +static int mpi_miller_rabin( const mpi *X, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + size_t i, j, n, s; + mpi W, R, T, A, RR; + + mpi_init( &W ); mpi_init( &R ); mpi_init( &T ); mpi_init( &A ); + mpi_init( &RR ); + + /* + * W = |X| - 1 + * R = W >> lsb( W ) + */ + MPI_CHK( mpi_sub_int( &W, X, 1 ) ); + s = mpi_lsb( &W ); + MPI_CHK( mpi_copy( &R, &W ) ); + MPI_CHK( mpi_shift_r( &R, s ) ); + + i = mpi_msb( X ); + /* + * HAC, table 4.4 + */ + n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 : + ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 : + ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 ); + + for( i = 0; i < n; i++ ) + { + /* + * pick a random A, 1 < A < |X| - 1 + */ + MPI_CHK( mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) ); + + if( mpi_cmp_mpi( &A, &W ) >= 0 ) + { + j = mpi_msb( &A ) - mpi_msb( &W ); + MPI_CHK( mpi_shift_r( &A, j + 1 ) ); + } + A.p[0] |= 3; + + /* + * A = A^R mod |X| + */ + MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) ); + + if( mpi_cmp_mpi( &A, &W ) == 0 || + mpi_cmp_int( &A, 1 ) == 0 ) + continue; + + j = 1; + while( j < s && mpi_cmp_mpi( &A, &W ) != 0 ) + { + /* + * A = A * A mod |X| + */ + MPI_CHK( mpi_mul_mpi( &T, &A, &A ) ); + MPI_CHK( mpi_mod_mpi( &A, &T, X ) ); + + if( mpi_cmp_int( &A, 1 ) == 0 ) + break; + + j++; + } + + /* + * not prime if A != |X| - 1 or A == 1 + */ + if( mpi_cmp_mpi( &A, &W ) != 0 || + mpi_cmp_int( &A, 1 ) == 0 ) + { + ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE; + break; + } + } + +cleanup: + mpi_free( &W ); mpi_free( &R ); mpi_free( &T ); mpi_free( &A ); + mpi_free( &RR ); + + return( ret ); +} + +/* + * Pseudo-primality test: small factors, then Miller-Rabin + */ +int mpi_is_prime( mpi *X, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + const mpi XX = { 1, X->n, X->p }; /* Abs(X) */ + + if( mpi_cmp_int( &XX, 0 ) == 0 || + mpi_cmp_int( &XX, 1 ) == 0 ) + return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE ); + + if( mpi_cmp_int( &XX, 2 ) == 0 ) + return( 0 ); + + if( ( ret = mpi_check_small_factors( &XX ) ) != 0 ) + { + if( ret == 1 ) + return( 0 ); + + return( ret ); + } + + return( mpi_miller_rabin( &XX, f_rng, p_rng ) ); +} + +/* + * Prime number generation + */ +int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + size_t k, n; + t_uint r; + mpi Y; + + if( nbits < 3 || nbits > POLARSSL_MPI_MAX_BITS ) + return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); + + mpi_init( &Y ); + + n = BITS_TO_LIMBS( nbits ); + + MPI_CHK( mpi_fill_random( X, n * ciL, f_rng, p_rng ) ); + + k = mpi_msb( X ); + if( k < nbits ) MPI_CHK( mpi_shift_l( X, nbits - k ) ); + if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits ) ); + + X->p[0] |= 3; + + if( dh_flag == 0 ) + { + while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 ) + { + if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE ) + goto cleanup; + + MPI_CHK( mpi_add_int( X, X, 2 ) ); + } + } + else + { + /* + * An necessary condition for Y and X = 2Y + 1 to be prime + * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3). + * Make sure it is satisfied, while keeping X = 3 mod 4 + */ + MPI_CHK( mpi_mod_int( &r, X, 3 ) ); + if( r == 0 ) + MPI_CHK( mpi_add_int( X, X, 8 ) ); + else if( r == 1 ) + MPI_CHK( mpi_add_int( X, X, 4 ) ); + + /* Set Y = (X-1) / 2, which is X / 2 because X is odd */ + MPI_CHK( mpi_copy( &Y, X ) ); + MPI_CHK( mpi_shift_r( &Y, 1 ) ); + + while( 1 ) + { + /* + * First, check small factors for X and Y + * before doing Miller-Rabin on any of them + */ + if( ( ret = mpi_check_small_factors( X ) ) == 0 && + ( ret = mpi_check_small_factors( &Y ) ) == 0 && + ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 && + ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 ) + { + break; + } + + if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE ) + goto cleanup; + + /* + * Next candidates. We want to preserve Y = (X-1) / 2 and + * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3) + * so up Y by 6 and X by 12. + */ + MPI_CHK( mpi_add_int( X, X, 12 ) ); + MPI_CHK( mpi_add_int( &Y, &Y, 6 ) ); + } + } + +cleanup: + + mpi_free( &Y ); + + return( ret ); +} + +#endif /* POLARSSL_GENPRIME */ + +#if defined(POLARSSL_SELF_TEST) + +#define GCD_PAIR_COUNT 3 + +static const int gcd_pairs[GCD_PAIR_COUNT][3] = +{ + { 693, 609, 21 }, + { 1764, 868, 28 }, + { 768454923, 542167814, 1 } +}; + +/* + * Checkup routine + */ +int mpi_self_test( int verbose ) +{ + int ret, i; + mpi A, E, N, X, Y, U, V; + + mpi_init( &A ); mpi_init( &E ); mpi_init( &N ); mpi_init( &X ); + mpi_init( &Y ); mpi_init( &U ); mpi_init( &V ); + + MPI_CHK( mpi_read_string( &A, 16, + "EFE021C2645FD1DC586E69184AF4A31E" \ + "D5F53E93B5F123FA41680867BA110131" \ + "944FE7952E2517337780CB0DB80E61AA" \ + "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) ); + + MPI_CHK( mpi_read_string( &E, 16, + "B2E7EFD37075B9F03FF989C7C5051C20" \ + "34D2A323810251127E7BF8625A4F49A5" \ + "F3E27F4DA8BD59C47D6DAABA4C8127BD" \ + "5B5C25763222FEFCCFC38B832366C29E" ) ); + + MPI_CHK( mpi_read_string( &N, 16, + "0066A198186C18C10B2F5ED9B522752A" \ + "9830B69916E535C8F047518A889A43A5" \ + "94B6BED27A168D31D4A52F88925AA8F5" ) ); + + MPI_CHK( mpi_mul_mpi( &X, &A, &N ) ); + + MPI_CHK( mpi_read_string( &U, 16, + "602AB7ECA597A3D6B56FF9829A5E8B85" \ + "9E857EA95A03512E2BAE7391688D264A" \ + "A5663B0341DB9CCFD2C4C5F421FEC814" \ + "8001B72E848A38CAE1C65F78E56ABDEF" \ + "E12D3C039B8A02D6BE593F0BBBDA56F1" \ + "ECF677152EF804370C1A305CAF3B5BF1" \ + "30879B56C61DE584A0F53A2447A51E" ) ); + + if( verbose != 0 ) + polarssl_printf( " MPI test #1 (mul_mpi): " ); + + if( mpi_cmp_mpi( &X, &U ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + + MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) ); + + MPI_CHK( mpi_read_string( &U, 16, + "256567336059E52CAE22925474705F39A94" ) ); + + MPI_CHK( mpi_read_string( &V, 16, + "6613F26162223DF488E9CD48CC132C7A" \ + "0AC93C701B001B092E4E5B9F73BCD27B" \ + "9EE50D0657C77F374E903CDFA4C642" ) ); + + if( verbose != 0 ) + polarssl_printf( " MPI test #2 (div_mpi): " ); + + if( mpi_cmp_mpi( &X, &U ) != 0 || + mpi_cmp_mpi( &Y, &V ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + + MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) ); + + MPI_CHK( mpi_read_string( &U, 16, + "36E139AEA55215609D2816998ED020BB" \ + "BD96C37890F65171D948E9BC7CBAA4D9" \ + "325D24D6A3C12710F10A09FA08AB87" ) ); + + if( verbose != 0 ) + polarssl_printf( " MPI test #3 (exp_mod): " ); + + if( mpi_cmp_mpi( &X, &U ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + + MPI_CHK( mpi_inv_mod( &X, &A, &N ) ); + + MPI_CHK( mpi_read_string( &U, 16, + "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \ + "C3DBA76456363A10869622EAC2DD84EC" \ + "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) ); + + if( verbose != 0 ) + polarssl_printf( " MPI test #4 (inv_mod): " ); + + if( mpi_cmp_mpi( &X, &U ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + + if( verbose != 0 ) + polarssl_printf( " MPI test #5 (simple gcd): " ); + + for( i = 0; i < GCD_PAIR_COUNT; i++ ) + { + MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) ); + MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) ); + + MPI_CHK( mpi_gcd( &A, &X, &Y ) ); + + if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed at %d\n", i ); + + ret = 1; + goto cleanup; + } + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + +cleanup: + + if( ret != 0 && verbose != 0 ) + polarssl_printf( "Unexpected error, return code = %08X\n", ret ); + + mpi_free( &A ); mpi_free( &E ); mpi_free( &N ); mpi_free( &X ); + mpi_free( &Y ); mpi_free( &U ); mpi_free( &V ); + + if( verbose != 0 ) + polarssl_printf( "\n" ); + + return( ret ); +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_BIGNUM_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/blowfish.c b/component/common/network/ssl/polarssl-1.3.8/library/blowfish.c new file mode 100644 index 0000000..87396dc --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/blowfish.c @@ -0,0 +1,658 @@ +/* + * Blowfish implementation + * + * Copyright (C) 2012-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * The Blowfish block cipher was designed by Bruce Schneier in 1993. + * http://www.schneier.com/blowfish.html + * http://en.wikipedia.org/wiki/Blowfish_%28cipher%29 + * + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_BLOWFISH_C) + +#include "polarssl/blowfish.h" + +#if !defined(POLARSSL_BLOWFISH_ALT) + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +static const uint32_t P[BLOWFISH_ROUNDS + 2] = { + 0x243F6A88L, 0x85A308D3L, 0x13198A2EL, 0x03707344L, + 0xA4093822L, 0x299F31D0L, 0x082EFA98L, 0xEC4E6C89L, + 0x452821E6L, 0x38D01377L, 0xBE5466CFL, 0x34E90C6CL, + 0xC0AC29B7L, 0xC97C50DDL, 0x3F84D5B5L, 0xB5470917L, + 0x9216D5D9L, 0x8979FB1BL +}; + +/* declarations of data at the end of this file */ +static const uint32_t S[4][256]; + +static uint32_t F( blowfish_context *ctx, uint32_t x ) +{ + unsigned short a, b, c, d; + uint32_t y; + + d = (unsigned short)(x & 0xFF); + x >>= 8; + c = (unsigned short)(x & 0xFF); + x >>= 8; + b = (unsigned short)(x & 0xFF); + x >>= 8; + a = (unsigned short)(x & 0xFF); + y = ctx->S[0][a] + ctx->S[1][b]; + y = y ^ ctx->S[2][c]; + y = y + ctx->S[3][d]; + + return( y ); +} + +static void blowfish_enc( blowfish_context *ctx, uint32_t *xl, uint32_t *xr ) +{ + uint32_t Xl, Xr, temp; + short i; + + Xl = *xl; + Xr = *xr; + + for( i = 0; i < BLOWFISH_ROUNDS; ++i ) + { + Xl = Xl ^ ctx->P[i]; + Xr = F( ctx, Xl ) ^ Xr; + + temp = Xl; + Xl = Xr; + Xr = temp; + } + + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ ctx->P[BLOWFISH_ROUNDS]; + Xl = Xl ^ ctx->P[BLOWFISH_ROUNDS + 1]; + + *xl = Xl; + *xr = Xr; +} + +static void blowfish_dec( blowfish_context *ctx, uint32_t *xl, uint32_t *xr ) +{ + uint32_t Xl, Xr, temp; + short i; + + Xl = *xl; + Xr = *xr; + + for( i = BLOWFISH_ROUNDS + 1; i > 1; --i ) + { + Xl = Xl ^ ctx->P[i]; + Xr = F( ctx, Xl ) ^ Xr; + + temp = Xl; + Xl = Xr; + Xr = temp; + } + + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ ctx->P[1]; + Xl = Xl ^ ctx->P[0]; + + *xl = Xl; + *xr = Xr; +} + +void blowfish_init( blowfish_context *ctx ) +{ + memset( ctx, 0, sizeof( blowfish_context ) ); +} + +void blowfish_free( blowfish_context *ctx ) +{ + if( ctx == NULL ) + return; + + polarssl_zeroize( ctx, sizeof( blowfish_context ) ); +} + +/* + * Blowfish key schedule + */ +int blowfish_setkey( blowfish_context *ctx, const unsigned char *key, + unsigned int keysize ) +{ + unsigned int i, j, k; + uint32_t data, datal, datar; + + if( keysize < BLOWFISH_MIN_KEY || keysize > BLOWFISH_MAX_KEY || + ( keysize % 8 ) ) + { + return( POLARSSL_ERR_BLOWFISH_INVALID_KEY_LENGTH ); + } + + keysize >>= 3; + + for( i = 0; i < 4; i++ ) + { + for( j = 0; j < 256; j++ ) + ctx->S[i][j] = S[i][j]; + } + + j = 0; + for( i = 0; i < BLOWFISH_ROUNDS + 2; ++i ) + { + data = 0x00000000; + for( k = 0; k < 4; ++k ) + { + data = ( data << 8 ) | key[j++]; + if( j >= keysize ) + j = 0; + } + ctx->P[i] = P[i] ^ data; + } + + datal = 0x00000000; + datar = 0x00000000; + + for( i = 0; i < BLOWFISH_ROUNDS + 2; i += 2 ) + { + blowfish_enc( ctx, &datal, &datar ); + ctx->P[i] = datal; + ctx->P[i + 1] = datar; + } + + for( i = 0; i < 4; i++ ) + { + for( j = 0; j < 256; j += 2 ) + { + blowfish_enc( ctx, &datal, &datar ); + ctx->S[i][j] = datal; + ctx->S[i][j + 1] = datar; + } + } + return( 0 ); +} + +/* + * Blowfish-ECB block encryption/decryption + */ +int blowfish_crypt_ecb( blowfish_context *ctx, + int mode, + const unsigned char input[BLOWFISH_BLOCKSIZE], + unsigned char output[BLOWFISH_BLOCKSIZE] ) +{ + uint32_t X0, X1; + + GET_UINT32_BE( X0, input, 0 ); + GET_UINT32_BE( X1, input, 4 ); + + if( mode == BLOWFISH_DECRYPT ) + { + blowfish_dec( ctx, &X0, &X1 ); + } + else /* BLOWFISH_ENCRYPT */ + { + blowfish_enc( ctx, &X0, &X1 ); + } + + PUT_UINT32_BE( X0, output, 0 ); + PUT_UINT32_BE( X1, output, 4 ); + + return( 0 ); +} + +#if defined(POLARSSL_CIPHER_MODE_CBC) +/* + * Blowfish-CBC buffer encryption/decryption + */ +int blowfish_crypt_cbc( blowfish_context *ctx, + int mode, + size_t length, + unsigned char iv[BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char temp[BLOWFISH_BLOCKSIZE]; + + if( length % BLOWFISH_BLOCKSIZE ) + return( POLARSSL_ERR_BLOWFISH_INVALID_INPUT_LENGTH ); + + if( mode == BLOWFISH_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, BLOWFISH_BLOCKSIZE ); + blowfish_crypt_ecb( ctx, mode, input, output ); + + for( i = 0; i < BLOWFISH_BLOCKSIZE;i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, BLOWFISH_BLOCKSIZE ); + + input += BLOWFISH_BLOCKSIZE; + output += BLOWFISH_BLOCKSIZE; + length -= BLOWFISH_BLOCKSIZE; + } + } + else + { + while( length > 0 ) + { + for( i = 0; i < BLOWFISH_BLOCKSIZE; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + blowfish_crypt_ecb( ctx, mode, output, output ); + memcpy( iv, output, BLOWFISH_BLOCKSIZE ); + + input += BLOWFISH_BLOCKSIZE; + output += BLOWFISH_BLOCKSIZE; + length -= BLOWFISH_BLOCKSIZE; + } + } + + return( 0 ); +} +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_CIPHER_MODE_CFB) +/* + * Blowfish CFB buffer encryption/decryption + */ +int blowfish_crypt_cfb64( blowfish_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + int c; + size_t n = *iv_off; + + if( mode == BLOWFISH_DECRYPT ) + { + while( length-- ) + { + if( n == 0 ) + blowfish_crypt_ecb( ctx, BLOWFISH_ENCRYPT, iv, iv ); + + c = *input++; + *output++ = (unsigned char)( c ^ iv[n] ); + iv[n] = (unsigned char) c; + + n = ( n + 1 ) % BLOWFISH_BLOCKSIZE; + } + } + else + { + while( length-- ) + { + if( n == 0 ) + blowfish_crypt_ecb( ctx, BLOWFISH_ENCRYPT, iv, iv ); + + iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); + + n = ( n + 1 ) % BLOWFISH_BLOCKSIZE; + } + } + + *iv_off = n; + + return( 0 ); +} +#endif /*POLARSSL_CIPHER_MODE_CFB */ + +#if defined(POLARSSL_CIPHER_MODE_CTR) +/* + * Blowfish CTR buffer encryption/decryption + */ +int blowfish_crypt_ctr( blowfish_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[BLOWFISH_BLOCKSIZE], + unsigned char stream_block[BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + int c, i; + size_t n = *nc_off; + + while( length-- ) + { + if( n == 0 ) { + blowfish_crypt_ecb( ctx, BLOWFISH_ENCRYPT, nonce_counter, + stream_block ); + + for( i = BLOWFISH_BLOCKSIZE; i > 0; i-- ) + if( ++nonce_counter[i - 1] != 0 ) + break; + } + c = *input++; + *output++ = (unsigned char)( c ^ stream_block[n] ); + + n = ( n + 1 ) % BLOWFISH_BLOCKSIZE; + } + + *nc_off = n; + + return( 0 ); +} +#endif /* POLARSSL_CIPHER_MODE_CTR */ + +static const uint32_t S[4][256] = { + { 0xD1310BA6L, 0x98DFB5ACL, 0x2FFD72DBL, 0xD01ADFB7L, + 0xB8E1AFEDL, 0x6A267E96L, 0xBA7C9045L, 0xF12C7F99L, + 0x24A19947L, 0xB3916CF7L, 0x0801F2E2L, 0x858EFC16L, + 0x636920D8L, 0x71574E69L, 0xA458FEA3L, 0xF4933D7EL, + 0x0D95748FL, 0x728EB658L, 0x718BCD58L, 0x82154AEEL, + 0x7B54A41DL, 0xC25A59B5L, 0x9C30D539L, 0x2AF26013L, + 0xC5D1B023L, 0x286085F0L, 0xCA417918L, 0xB8DB38EFL, + 0x8E79DCB0L, 0x603A180EL, 0x6C9E0E8BL, 0xB01E8A3EL, + 0xD71577C1L, 0xBD314B27L, 0x78AF2FDAL, 0x55605C60L, + 0xE65525F3L, 0xAA55AB94L, 0x57489862L, 0x63E81440L, + 0x55CA396AL, 0x2AAB10B6L, 0xB4CC5C34L, 0x1141E8CEL, + 0xA15486AFL, 0x7C72E993L, 0xB3EE1411L, 0x636FBC2AL, + 0x2BA9C55DL, 0x741831F6L, 0xCE5C3E16L, 0x9B87931EL, + 0xAFD6BA33L, 0x6C24CF5CL, 0x7A325381L, 0x28958677L, + 0x3B8F4898L, 0x6B4BB9AFL, 0xC4BFE81BL, 0x66282193L, + 0x61D809CCL, 0xFB21A991L, 0x487CAC60L, 0x5DEC8032L, + 0xEF845D5DL, 0xE98575B1L, 0xDC262302L, 0xEB651B88L, + 0x23893E81L, 0xD396ACC5L, 0x0F6D6FF3L, 0x83F44239L, + 0x2E0B4482L, 0xA4842004L, 0x69C8F04AL, 0x9E1F9B5EL, + 0x21C66842L, 0xF6E96C9AL, 0x670C9C61L, 0xABD388F0L, + 0x6A51A0D2L, 0xD8542F68L, 0x960FA728L, 0xAB5133A3L, + 0x6EEF0B6CL, 0x137A3BE4L, 0xBA3BF050L, 0x7EFB2A98L, + 0xA1F1651DL, 0x39AF0176L, 0x66CA593EL, 0x82430E88L, + 0x8CEE8619L, 0x456F9FB4L, 0x7D84A5C3L, 0x3B8B5EBEL, + 0xE06F75D8L, 0x85C12073L, 0x401A449FL, 0x56C16AA6L, + 0x4ED3AA62L, 0x363F7706L, 0x1BFEDF72L, 0x429B023DL, + 0x37D0D724L, 0xD00A1248L, 0xDB0FEAD3L, 0x49F1C09BL, + 0x075372C9L, 0x80991B7BL, 0x25D479D8L, 0xF6E8DEF7L, + 0xE3FE501AL, 0xB6794C3BL, 0x976CE0BDL, 0x04C006BAL, + 0xC1A94FB6L, 0x409F60C4L, 0x5E5C9EC2L, 0x196A2463L, + 0x68FB6FAFL, 0x3E6C53B5L, 0x1339B2EBL, 0x3B52EC6FL, + 0x6DFC511FL, 0x9B30952CL, 0xCC814544L, 0xAF5EBD09L, + 0xBEE3D004L, 0xDE334AFDL, 0x660F2807L, 0x192E4BB3L, + 0xC0CBA857L, 0x45C8740FL, 0xD20B5F39L, 0xB9D3FBDBL, + 0x5579C0BDL, 0x1A60320AL, 0xD6A100C6L, 0x402C7279L, + 0x679F25FEL, 0xFB1FA3CCL, 0x8EA5E9F8L, 0xDB3222F8L, + 0x3C7516DFL, 0xFD616B15L, 0x2F501EC8L, 0xAD0552ABL, + 0x323DB5FAL, 0xFD238760L, 0x53317B48L, 0x3E00DF82L, + 0x9E5C57BBL, 0xCA6F8CA0L, 0x1A87562EL, 0xDF1769DBL, + 0xD542A8F6L, 0x287EFFC3L, 0xAC6732C6L, 0x8C4F5573L, + 0x695B27B0L, 0xBBCA58C8L, 0xE1FFA35DL, 0xB8F011A0L, + 0x10FA3D98L, 0xFD2183B8L, 0x4AFCB56CL, 0x2DD1D35BL, + 0x9A53E479L, 0xB6F84565L, 0xD28E49BCL, 0x4BFB9790L, + 0xE1DDF2DAL, 0xA4CB7E33L, 0x62FB1341L, 0xCEE4C6E8L, + 0xEF20CADAL, 0x36774C01L, 0xD07E9EFEL, 0x2BF11FB4L, + 0x95DBDA4DL, 0xAE909198L, 0xEAAD8E71L, 0x6B93D5A0L, + 0xD08ED1D0L, 0xAFC725E0L, 0x8E3C5B2FL, 0x8E7594B7L, + 0x8FF6E2FBL, 0xF2122B64L, 0x8888B812L, 0x900DF01CL, + 0x4FAD5EA0L, 0x688FC31CL, 0xD1CFF191L, 0xB3A8C1ADL, + 0x2F2F2218L, 0xBE0E1777L, 0xEA752DFEL, 0x8B021FA1L, + 0xE5A0CC0FL, 0xB56F74E8L, 0x18ACF3D6L, 0xCE89E299L, + 0xB4A84FE0L, 0xFD13E0B7L, 0x7CC43B81L, 0xD2ADA8D9L, + 0x165FA266L, 0x80957705L, 0x93CC7314L, 0x211A1477L, + 0xE6AD2065L, 0x77B5FA86L, 0xC75442F5L, 0xFB9D35CFL, + 0xEBCDAF0CL, 0x7B3E89A0L, 0xD6411BD3L, 0xAE1E7E49L, + 0x00250E2DL, 0x2071B35EL, 0x226800BBL, 0x57B8E0AFL, + 0x2464369BL, 0xF009B91EL, 0x5563911DL, 0x59DFA6AAL, + 0x78C14389L, 0xD95A537FL, 0x207D5BA2L, 0x02E5B9C5L, + 0x83260376L, 0x6295CFA9L, 0x11C81968L, 0x4E734A41L, + 0xB3472DCAL, 0x7B14A94AL, 0x1B510052L, 0x9A532915L, + 0xD60F573FL, 0xBC9BC6E4L, 0x2B60A476L, 0x81E67400L, + 0x08BA6FB5L, 0x571BE91FL, 0xF296EC6BL, 0x2A0DD915L, + 0xB6636521L, 0xE7B9F9B6L, 0xFF34052EL, 0xC5855664L, + 0x53B02D5DL, 0xA99F8FA1L, 0x08BA4799L, 0x6E85076AL }, + { 0x4B7A70E9L, 0xB5B32944L, 0xDB75092EL, 0xC4192623L, + 0xAD6EA6B0L, 0x49A7DF7DL, 0x9CEE60B8L, 0x8FEDB266L, + 0xECAA8C71L, 0x699A17FFL, 0x5664526CL, 0xC2B19EE1L, + 0x193602A5L, 0x75094C29L, 0xA0591340L, 0xE4183A3EL, + 0x3F54989AL, 0x5B429D65L, 0x6B8FE4D6L, 0x99F73FD6L, + 0xA1D29C07L, 0xEFE830F5L, 0x4D2D38E6L, 0xF0255DC1L, + 0x4CDD2086L, 0x8470EB26L, 0x6382E9C6L, 0x021ECC5EL, + 0x09686B3FL, 0x3EBAEFC9L, 0x3C971814L, 0x6B6A70A1L, + 0x687F3584L, 0x52A0E286L, 0xB79C5305L, 0xAA500737L, + 0x3E07841CL, 0x7FDEAE5CL, 0x8E7D44ECL, 0x5716F2B8L, + 0xB03ADA37L, 0xF0500C0DL, 0xF01C1F04L, 0x0200B3FFL, + 0xAE0CF51AL, 0x3CB574B2L, 0x25837A58L, 0xDC0921BDL, + 0xD19113F9L, 0x7CA92FF6L, 0x94324773L, 0x22F54701L, + 0x3AE5E581L, 0x37C2DADCL, 0xC8B57634L, 0x9AF3DDA7L, + 0xA9446146L, 0x0FD0030EL, 0xECC8C73EL, 0xA4751E41L, + 0xE238CD99L, 0x3BEA0E2FL, 0x3280BBA1L, 0x183EB331L, + 0x4E548B38L, 0x4F6DB908L, 0x6F420D03L, 0xF60A04BFL, + 0x2CB81290L, 0x24977C79L, 0x5679B072L, 0xBCAF89AFL, + 0xDE9A771FL, 0xD9930810L, 0xB38BAE12L, 0xDCCF3F2EL, + 0x5512721FL, 0x2E6B7124L, 0x501ADDE6L, 0x9F84CD87L, + 0x7A584718L, 0x7408DA17L, 0xBC9F9ABCL, 0xE94B7D8CL, + 0xEC7AEC3AL, 0xDB851DFAL, 0x63094366L, 0xC464C3D2L, + 0xEF1C1847L, 0x3215D908L, 0xDD433B37L, 0x24C2BA16L, + 0x12A14D43L, 0x2A65C451L, 0x50940002L, 0x133AE4DDL, + 0x71DFF89EL, 0x10314E55L, 0x81AC77D6L, 0x5F11199BL, + 0x043556F1L, 0xD7A3C76BL, 0x3C11183BL, 0x5924A509L, + 0xF28FE6EDL, 0x97F1FBFAL, 0x9EBABF2CL, 0x1E153C6EL, + 0x86E34570L, 0xEAE96FB1L, 0x860E5E0AL, 0x5A3E2AB3L, + 0x771FE71CL, 0x4E3D06FAL, 0x2965DCB9L, 0x99E71D0FL, + 0x803E89D6L, 0x5266C825L, 0x2E4CC978L, 0x9C10B36AL, + 0xC6150EBAL, 0x94E2EA78L, 0xA5FC3C53L, 0x1E0A2DF4L, + 0xF2F74EA7L, 0x361D2B3DL, 0x1939260FL, 0x19C27960L, + 0x5223A708L, 0xF71312B6L, 0xEBADFE6EL, 0xEAC31F66L, + 0xE3BC4595L, 0xA67BC883L, 0xB17F37D1L, 0x018CFF28L, + 0xC332DDEFL, 0xBE6C5AA5L, 0x65582185L, 0x68AB9802L, + 0xEECEA50FL, 0xDB2F953BL, 0x2AEF7DADL, 0x5B6E2F84L, + 0x1521B628L, 0x29076170L, 0xECDD4775L, 0x619F1510L, + 0x13CCA830L, 0xEB61BD96L, 0x0334FE1EL, 0xAA0363CFL, + 0xB5735C90L, 0x4C70A239L, 0xD59E9E0BL, 0xCBAADE14L, + 0xEECC86BCL, 0x60622CA7L, 0x9CAB5CABL, 0xB2F3846EL, + 0x648B1EAFL, 0x19BDF0CAL, 0xA02369B9L, 0x655ABB50L, + 0x40685A32L, 0x3C2AB4B3L, 0x319EE9D5L, 0xC021B8F7L, + 0x9B540B19L, 0x875FA099L, 0x95F7997EL, 0x623D7DA8L, + 0xF837889AL, 0x97E32D77L, 0x11ED935FL, 0x16681281L, + 0x0E358829L, 0xC7E61FD6L, 0x96DEDFA1L, 0x7858BA99L, + 0x57F584A5L, 0x1B227263L, 0x9B83C3FFL, 0x1AC24696L, + 0xCDB30AEBL, 0x532E3054L, 0x8FD948E4L, 0x6DBC3128L, + 0x58EBF2EFL, 0x34C6FFEAL, 0xFE28ED61L, 0xEE7C3C73L, + 0x5D4A14D9L, 0xE864B7E3L, 0x42105D14L, 0x203E13E0L, + 0x45EEE2B6L, 0xA3AAABEAL, 0xDB6C4F15L, 0xFACB4FD0L, + 0xC742F442L, 0xEF6ABBB5L, 0x654F3B1DL, 0x41CD2105L, + 0xD81E799EL, 0x86854DC7L, 0xE44B476AL, 0x3D816250L, + 0xCF62A1F2L, 0x5B8D2646L, 0xFC8883A0L, 0xC1C7B6A3L, + 0x7F1524C3L, 0x69CB7492L, 0x47848A0BL, 0x5692B285L, + 0x095BBF00L, 0xAD19489DL, 0x1462B174L, 0x23820E00L, + 0x58428D2AL, 0x0C55F5EAL, 0x1DADF43EL, 0x233F7061L, + 0x3372F092L, 0x8D937E41L, 0xD65FECF1L, 0x6C223BDBL, + 0x7CDE3759L, 0xCBEE7460L, 0x4085F2A7L, 0xCE77326EL, + 0xA6078084L, 0x19F8509EL, 0xE8EFD855L, 0x61D99735L, + 0xA969A7AAL, 0xC50C06C2L, 0x5A04ABFCL, 0x800BCADCL, + 0x9E447A2EL, 0xC3453484L, 0xFDD56705L, 0x0E1E9EC9L, + 0xDB73DBD3L, 0x105588CDL, 0x675FDA79L, 0xE3674340L, + 0xC5C43465L, 0x713E38D8L, 0x3D28F89EL, 0xF16DFF20L, + 0x153E21E7L, 0x8FB03D4AL, 0xE6E39F2BL, 0xDB83ADF7L }, + { 0xE93D5A68L, 0x948140F7L, 0xF64C261CL, 0x94692934L, + 0x411520F7L, 0x7602D4F7L, 0xBCF46B2EL, 0xD4A20068L, + 0xD4082471L, 0x3320F46AL, 0x43B7D4B7L, 0x500061AFL, + 0x1E39F62EL, 0x97244546L, 0x14214F74L, 0xBF8B8840L, + 0x4D95FC1DL, 0x96B591AFL, 0x70F4DDD3L, 0x66A02F45L, + 0xBFBC09ECL, 0x03BD9785L, 0x7FAC6DD0L, 0x31CB8504L, + 0x96EB27B3L, 0x55FD3941L, 0xDA2547E6L, 0xABCA0A9AL, + 0x28507825L, 0x530429F4L, 0x0A2C86DAL, 0xE9B66DFBL, + 0x68DC1462L, 0xD7486900L, 0x680EC0A4L, 0x27A18DEEL, + 0x4F3FFEA2L, 0xE887AD8CL, 0xB58CE006L, 0x7AF4D6B6L, + 0xAACE1E7CL, 0xD3375FECL, 0xCE78A399L, 0x406B2A42L, + 0x20FE9E35L, 0xD9F385B9L, 0xEE39D7ABL, 0x3B124E8BL, + 0x1DC9FAF7L, 0x4B6D1856L, 0x26A36631L, 0xEAE397B2L, + 0x3A6EFA74L, 0xDD5B4332L, 0x6841E7F7L, 0xCA7820FBL, + 0xFB0AF54EL, 0xD8FEB397L, 0x454056ACL, 0xBA489527L, + 0x55533A3AL, 0x20838D87L, 0xFE6BA9B7L, 0xD096954BL, + 0x55A867BCL, 0xA1159A58L, 0xCCA92963L, 0x99E1DB33L, + 0xA62A4A56L, 0x3F3125F9L, 0x5EF47E1CL, 0x9029317CL, + 0xFDF8E802L, 0x04272F70L, 0x80BB155CL, 0x05282CE3L, + 0x95C11548L, 0xE4C66D22L, 0x48C1133FL, 0xC70F86DCL, + 0x07F9C9EEL, 0x41041F0FL, 0x404779A4L, 0x5D886E17L, + 0x325F51EBL, 0xD59BC0D1L, 0xF2BCC18FL, 0x41113564L, + 0x257B7834L, 0x602A9C60L, 0xDFF8E8A3L, 0x1F636C1BL, + 0x0E12B4C2L, 0x02E1329EL, 0xAF664FD1L, 0xCAD18115L, + 0x6B2395E0L, 0x333E92E1L, 0x3B240B62L, 0xEEBEB922L, + 0x85B2A20EL, 0xE6BA0D99L, 0xDE720C8CL, 0x2DA2F728L, + 0xD0127845L, 0x95B794FDL, 0x647D0862L, 0xE7CCF5F0L, + 0x5449A36FL, 0x877D48FAL, 0xC39DFD27L, 0xF33E8D1EL, + 0x0A476341L, 0x992EFF74L, 0x3A6F6EABL, 0xF4F8FD37L, + 0xA812DC60L, 0xA1EBDDF8L, 0x991BE14CL, 0xDB6E6B0DL, + 0xC67B5510L, 0x6D672C37L, 0x2765D43BL, 0xDCD0E804L, + 0xF1290DC7L, 0xCC00FFA3L, 0xB5390F92L, 0x690FED0BL, + 0x667B9FFBL, 0xCEDB7D9CL, 0xA091CF0BL, 0xD9155EA3L, + 0xBB132F88L, 0x515BAD24L, 0x7B9479BFL, 0x763BD6EBL, + 0x37392EB3L, 0xCC115979L, 0x8026E297L, 0xF42E312DL, + 0x6842ADA7L, 0xC66A2B3BL, 0x12754CCCL, 0x782EF11CL, + 0x6A124237L, 0xB79251E7L, 0x06A1BBE6L, 0x4BFB6350L, + 0x1A6B1018L, 0x11CAEDFAL, 0x3D25BDD8L, 0xE2E1C3C9L, + 0x44421659L, 0x0A121386L, 0xD90CEC6EL, 0xD5ABEA2AL, + 0x64AF674EL, 0xDA86A85FL, 0xBEBFE988L, 0x64E4C3FEL, + 0x9DBC8057L, 0xF0F7C086L, 0x60787BF8L, 0x6003604DL, + 0xD1FD8346L, 0xF6381FB0L, 0x7745AE04L, 0xD736FCCCL, + 0x83426B33L, 0xF01EAB71L, 0xB0804187L, 0x3C005E5FL, + 0x77A057BEL, 0xBDE8AE24L, 0x55464299L, 0xBF582E61L, + 0x4E58F48FL, 0xF2DDFDA2L, 0xF474EF38L, 0x8789BDC2L, + 0x5366F9C3L, 0xC8B38E74L, 0xB475F255L, 0x46FCD9B9L, + 0x7AEB2661L, 0x8B1DDF84L, 0x846A0E79L, 0x915F95E2L, + 0x466E598EL, 0x20B45770L, 0x8CD55591L, 0xC902DE4CL, + 0xB90BACE1L, 0xBB8205D0L, 0x11A86248L, 0x7574A99EL, + 0xB77F19B6L, 0xE0A9DC09L, 0x662D09A1L, 0xC4324633L, + 0xE85A1F02L, 0x09F0BE8CL, 0x4A99A025L, 0x1D6EFE10L, + 0x1AB93D1DL, 0x0BA5A4DFL, 0xA186F20FL, 0x2868F169L, + 0xDCB7DA83L, 0x573906FEL, 0xA1E2CE9BL, 0x4FCD7F52L, + 0x50115E01L, 0xA70683FAL, 0xA002B5C4L, 0x0DE6D027L, + 0x9AF88C27L, 0x773F8641L, 0xC3604C06L, 0x61A806B5L, + 0xF0177A28L, 0xC0F586E0L, 0x006058AAL, 0x30DC7D62L, + 0x11E69ED7L, 0x2338EA63L, 0x53C2DD94L, 0xC2C21634L, + 0xBBCBEE56L, 0x90BCB6DEL, 0xEBFC7DA1L, 0xCE591D76L, + 0x6F05E409L, 0x4B7C0188L, 0x39720A3DL, 0x7C927C24L, + 0x86E3725FL, 0x724D9DB9L, 0x1AC15BB4L, 0xD39EB8FCL, + 0xED545578L, 0x08FCA5B5L, 0xD83D7CD3L, 0x4DAD0FC4L, + 0x1E50EF5EL, 0xB161E6F8L, 0xA28514D9L, 0x6C51133CL, + 0x6FD5C7E7L, 0x56E14EC4L, 0x362ABFCEL, 0xDDC6C837L, + 0xD79A3234L, 0x92638212L, 0x670EFA8EL, 0x406000E0L }, + { 0x3A39CE37L, 0xD3FAF5CFL, 0xABC27737L, 0x5AC52D1BL, + 0x5CB0679EL, 0x4FA33742L, 0xD3822740L, 0x99BC9BBEL, + 0xD5118E9DL, 0xBF0F7315L, 0xD62D1C7EL, 0xC700C47BL, + 0xB78C1B6BL, 0x21A19045L, 0xB26EB1BEL, 0x6A366EB4L, + 0x5748AB2FL, 0xBC946E79L, 0xC6A376D2L, 0x6549C2C8L, + 0x530FF8EEL, 0x468DDE7DL, 0xD5730A1DL, 0x4CD04DC6L, + 0x2939BBDBL, 0xA9BA4650L, 0xAC9526E8L, 0xBE5EE304L, + 0xA1FAD5F0L, 0x6A2D519AL, 0x63EF8CE2L, 0x9A86EE22L, + 0xC089C2B8L, 0x43242EF6L, 0xA51E03AAL, 0x9CF2D0A4L, + 0x83C061BAL, 0x9BE96A4DL, 0x8FE51550L, 0xBA645BD6L, + 0x2826A2F9L, 0xA73A3AE1L, 0x4BA99586L, 0xEF5562E9L, + 0xC72FEFD3L, 0xF752F7DAL, 0x3F046F69L, 0x77FA0A59L, + 0x80E4A915L, 0x87B08601L, 0x9B09E6ADL, 0x3B3EE593L, + 0xE990FD5AL, 0x9E34D797L, 0x2CF0B7D9L, 0x022B8B51L, + 0x96D5AC3AL, 0x017DA67DL, 0xD1CF3ED6L, 0x7C7D2D28L, + 0x1F9F25CFL, 0xADF2B89BL, 0x5AD6B472L, 0x5A88F54CL, + 0xE029AC71L, 0xE019A5E6L, 0x47B0ACFDL, 0xED93FA9BL, + 0xE8D3C48DL, 0x283B57CCL, 0xF8D56629L, 0x79132E28L, + 0x785F0191L, 0xED756055L, 0xF7960E44L, 0xE3D35E8CL, + 0x15056DD4L, 0x88F46DBAL, 0x03A16125L, 0x0564F0BDL, + 0xC3EB9E15L, 0x3C9057A2L, 0x97271AECL, 0xA93A072AL, + 0x1B3F6D9BL, 0x1E6321F5L, 0xF59C66FBL, 0x26DCF319L, + 0x7533D928L, 0xB155FDF5L, 0x03563482L, 0x8ABA3CBBL, + 0x28517711L, 0xC20AD9F8L, 0xABCC5167L, 0xCCAD925FL, + 0x4DE81751L, 0x3830DC8EL, 0x379D5862L, 0x9320F991L, + 0xEA7A90C2L, 0xFB3E7BCEL, 0x5121CE64L, 0x774FBE32L, + 0xA8B6E37EL, 0xC3293D46L, 0x48DE5369L, 0x6413E680L, + 0xA2AE0810L, 0xDD6DB224L, 0x69852DFDL, 0x09072166L, + 0xB39A460AL, 0x6445C0DDL, 0x586CDECFL, 0x1C20C8AEL, + 0x5BBEF7DDL, 0x1B588D40L, 0xCCD2017FL, 0x6BB4E3BBL, + 0xDDA26A7EL, 0x3A59FF45L, 0x3E350A44L, 0xBCB4CDD5L, + 0x72EACEA8L, 0xFA6484BBL, 0x8D6612AEL, 0xBF3C6F47L, + 0xD29BE463L, 0x542F5D9EL, 0xAEC2771BL, 0xF64E6370L, + 0x740E0D8DL, 0xE75B1357L, 0xF8721671L, 0xAF537D5DL, + 0x4040CB08L, 0x4EB4E2CCL, 0x34D2466AL, 0x0115AF84L, + 0xE1B00428L, 0x95983A1DL, 0x06B89FB4L, 0xCE6EA048L, + 0x6F3F3B82L, 0x3520AB82L, 0x011A1D4BL, 0x277227F8L, + 0x611560B1L, 0xE7933FDCL, 0xBB3A792BL, 0x344525BDL, + 0xA08839E1L, 0x51CE794BL, 0x2F32C9B7L, 0xA01FBAC9L, + 0xE01CC87EL, 0xBCC7D1F6L, 0xCF0111C3L, 0xA1E8AAC7L, + 0x1A908749L, 0xD44FBD9AL, 0xD0DADECBL, 0xD50ADA38L, + 0x0339C32AL, 0xC6913667L, 0x8DF9317CL, 0xE0B12B4FL, + 0xF79E59B7L, 0x43F5BB3AL, 0xF2D519FFL, 0x27D9459CL, + 0xBF97222CL, 0x15E6FC2AL, 0x0F91FC71L, 0x9B941525L, + 0xFAE59361L, 0xCEB69CEBL, 0xC2A86459L, 0x12BAA8D1L, + 0xB6C1075EL, 0xE3056A0CL, 0x10D25065L, 0xCB03A442L, + 0xE0EC6E0EL, 0x1698DB3BL, 0x4C98A0BEL, 0x3278E964L, + 0x9F1F9532L, 0xE0D392DFL, 0xD3A0342BL, 0x8971F21EL, + 0x1B0A7441L, 0x4BA3348CL, 0xC5BE7120L, 0xC37632D8L, + 0xDF359F8DL, 0x9B992F2EL, 0xE60B6F47L, 0x0FE3F11DL, + 0xE54CDA54L, 0x1EDAD891L, 0xCE6279CFL, 0xCD3E7E6FL, + 0x1618B166L, 0xFD2C1D05L, 0x848FD2C5L, 0xF6FB2299L, + 0xF523F357L, 0xA6327623L, 0x93A83531L, 0x56CCCD02L, + 0xACF08162L, 0x5A75EBB5L, 0x6E163697L, 0x88D273CCL, + 0xDE966292L, 0x81B949D0L, 0x4C50901BL, 0x71C65614L, + 0xE6C6C7BDL, 0x327A140AL, 0x45E1D006L, 0xC3F27B9AL, + 0xC9AA53FDL, 0x62A80F00L, 0xBB25BFE2L, 0x35BDD2F6L, + 0x71126905L, 0xB2040222L, 0xB6CBCF7CL, 0xCD769C2BL, + 0x53113EC0L, 0x1640E3D3L, 0x38ABBD60L, 0x2547ADF0L, + 0xBA38209CL, 0xF746CE76L, 0x77AFA1C5L, 0x20756060L, + 0x85CBFE4EL, 0x8AE88DD8L, 0x7AAAF9B0L, 0x4CF9AA7EL, + 0x1948C25CL, 0x02FB8A8CL, 0x01C36AE4L, 0xD6EBE1F9L, + 0x90D4F869L, 0xA65CDEA0L, 0x3F09252DL, 0xC208E69FL, + 0xB74E6132L, 0xCE77E25BL, 0x578FDFE3L, 0x3AC372E6L } +}; + +#endif /* !POLARSSL_BLOWFISH_ALT */ +#endif /* POLARSSL_BLOWFISH_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/camellia.c b/component/common/network/ssl/polarssl-1.3.8/library/camellia.c new file mode 100644 index 0000000..a4968f4 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/camellia.c @@ -0,0 +1,1073 @@ +/* + * Camellia implementation + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * The Camellia block cipher was designed by NTT and Mitsubishi Electric + * Corporation. + * + * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/01espec.pdf + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_CAMELLIA_C) + +#include "polarssl/camellia.h" + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#define polarssl_printf printf +#endif + +#if !defined(POLARSSL_CAMELLIA_ALT) + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +static const unsigned char SIGMA_CHARS[6][8] = +{ + { 0xa0, 0x9e, 0x66, 0x7f, 0x3b, 0xcc, 0x90, 0x8b }, + { 0xb6, 0x7a, 0xe8, 0x58, 0x4c, 0xaa, 0x73, 0xb2 }, + { 0xc6, 0xef, 0x37, 0x2f, 0xe9, 0x4f, 0x82, 0xbe }, + { 0x54, 0xff, 0x53, 0xa5, 0xf1, 0xd3, 0x6f, 0x1c }, + { 0x10, 0xe5, 0x27, 0xfa, 0xde, 0x68, 0x2d, 0x1d }, + { 0xb0, 0x56, 0x88, 0xc2, 0xb3, 0xe6, 0xc1, 0xfd } +}; + +#if defined(POLARSSL_CAMELLIA_SMALL_MEMORY) + +static const unsigned char FSb[256] = +{ + 112,130, 44,236,179, 39,192,229,228,133, 87, 53,234, 12,174, 65, + 35,239,107,147, 69, 25,165, 33,237, 14, 79, 78, 29,101,146,189, + 134,184,175,143,124,235, 31,206, 62, 48,220, 95, 94,197, 11, 26, + 166,225, 57,202,213, 71, 93, 61,217, 1, 90,214, 81, 86,108, 77, + 139, 13,154,102,251,204,176, 45,116, 18, 43, 32,240,177,132,153, + 223, 76,203,194, 52,126,118, 5,109,183,169, 49,209, 23, 4,215, + 20, 88, 58, 97,222, 27, 17, 28, 50, 15,156, 22, 83, 24,242, 34, + 254, 68,207,178,195,181,122,145, 36, 8,232,168, 96,252,105, 80, + 170,208,160,125,161,137, 98,151, 84, 91, 30,149,224,255,100,210, + 16,196, 0, 72,163,247,117,219,138, 3,230,218, 9, 63,221,148, + 135, 92,131, 2,205, 74,144, 51,115,103,246,243,157,127,191,226, + 82,155,216, 38,200, 55,198, 59,129,150,111, 75, 19,190, 99, 46, + 233,121,167,140,159,110,188,142, 41,245,249,182, 47,253,180, 89, + 120,152, 6,106,231, 70,113,186,212, 37,171, 66,136,162,141,250, + 114, 7,185, 85,248,238,172, 10, 54, 73, 42,104, 60, 56,241,164, + 64, 40,211,123,187,201, 67,193, 21,227,173,244,119,199,128,158 +}; + +#define SBOX1(n) FSb[(n)] +#define SBOX2(n) (unsigned char)((FSb[(n)] >> 7 ^ FSb[(n)] << 1) & 0xff) +#define SBOX3(n) (unsigned char)((FSb[(n)] >> 1 ^ FSb[(n)] << 7) & 0xff) +#define SBOX4(n) FSb[((n) << 1 ^ (n) >> 7) &0xff] + +#else /* POLARSSL_CAMELLIA_SMALL_MEMORY */ + +static const unsigned char FSb[256] = +{ + 112, 130, 44, 236, 179, 39, 192, 229, 228, 133, 87, 53, 234, 12, 174, 65, + 35, 239, 107, 147, 69, 25, 165, 33, 237, 14, 79, 78, 29, 101, 146, 189, + 134, 184, 175, 143, 124, 235, 31, 206, 62, 48, 220, 95, 94, 197, 11, 26, + 166, 225, 57, 202, 213, 71, 93, 61, 217, 1, 90, 214, 81, 86, 108, 77, + 139, 13, 154, 102, 251, 204, 176, 45, 116, 18, 43, 32, 240, 177, 132, 153, + 223, 76, 203, 194, 52, 126, 118, 5, 109, 183, 169, 49, 209, 23, 4, 215, + 20, 88, 58, 97, 222, 27, 17, 28, 50, 15, 156, 22, 83, 24, 242, 34, + 254, 68, 207, 178, 195, 181, 122, 145, 36, 8, 232, 168, 96, 252, 105, 80, + 170, 208, 160, 125, 161, 137, 98, 151, 84, 91, 30, 149, 224, 255, 100, 210, + 16, 196, 0, 72, 163, 247, 117, 219, 138, 3, 230, 218, 9, 63, 221, 148, + 135, 92, 131, 2, 205, 74, 144, 51, 115, 103, 246, 243, 157, 127, 191, 226, + 82, 155, 216, 38, 200, 55, 198, 59, 129, 150, 111, 75, 19, 190, 99, 46, + 233, 121, 167, 140, 159, 110, 188, 142, 41, 245, 249, 182, 47, 253, 180, 89, + 120, 152, 6, 106, 231, 70, 113, 186, 212, 37, 171, 66, 136, 162, 141, 250, + 114, 7, 185, 85, 248, 238, 172, 10, 54, 73, 42, 104, 60, 56, 241, 164, + 64, 40, 211, 123, 187, 201, 67, 193, 21, 227, 173, 244, 119, 199, 128, 158 +}; + +static const unsigned char FSb2[256] = +{ + 224, 5, 88, 217, 103, 78, 129, 203, 201, 11, 174, 106, 213, 24, 93, 130, + 70, 223, 214, 39, 138, 50, 75, 66, 219, 28, 158, 156, 58, 202, 37, 123, + 13, 113, 95, 31, 248, 215, 62, 157, 124, 96, 185, 190, 188, 139, 22, 52, + 77, 195, 114, 149, 171, 142, 186, 122, 179, 2, 180, 173, 162, 172, 216, 154, + 23, 26, 53, 204, 247, 153, 97, 90, 232, 36, 86, 64, 225, 99, 9, 51, + 191, 152, 151, 133, 104, 252, 236, 10, 218, 111, 83, 98, 163, 46, 8, 175, + 40, 176, 116, 194, 189, 54, 34, 56, 100, 30, 57, 44, 166, 48, 229, 68, + 253, 136, 159, 101, 135, 107, 244, 35, 72, 16, 209, 81, 192, 249, 210, 160, + 85, 161, 65, 250, 67, 19, 196, 47, 168, 182, 60, 43, 193, 255, 200, 165, + 32, 137, 0, 144, 71, 239, 234, 183, 21, 6, 205, 181, 18, 126, 187, 41, + 15, 184, 7, 4, 155, 148, 33, 102, 230, 206, 237, 231, 59, 254, 127, 197, + 164, 55, 177, 76, 145, 110, 141, 118, 3, 45, 222, 150, 38, 125, 198, 92, + 211, 242, 79, 25, 63, 220, 121, 29, 82, 235, 243, 109, 94, 251, 105, 178, + 240, 49, 12, 212, 207, 140, 226, 117, 169, 74, 87, 132, 17, 69, 27, 245, + 228, 14, 115, 170, 241, 221, 89, 20, 108, 146, 84, 208, 120, 112, 227, 73, + 128, 80, 167, 246, 119, 147, 134, 131, 42, 199, 91, 233, 238, 143, 1, 61 +}; + +static const unsigned char FSb3[256] = +{ + 56, 65, 22, 118, 217, 147, 96, 242, 114, 194, 171, 154, 117, 6, 87, 160, + 145, 247, 181, 201, 162, 140, 210, 144, 246, 7, 167, 39, 142, 178, 73, 222, + 67, 92, 215, 199, 62, 245, 143, 103, 31, 24, 110, 175, 47, 226, 133, 13, + 83, 240, 156, 101, 234, 163, 174, 158, 236, 128, 45, 107, 168, 43, 54, 166, + 197, 134, 77, 51, 253, 102, 88, 150, 58, 9, 149, 16, 120, 216, 66, 204, + 239, 38, 229, 97, 26, 63, 59, 130, 182, 219, 212, 152, 232, 139, 2, 235, + 10, 44, 29, 176, 111, 141, 136, 14, 25, 135, 78, 11, 169, 12, 121, 17, + 127, 34, 231, 89, 225, 218, 61, 200, 18, 4, 116, 84, 48, 126, 180, 40, + 85, 104, 80, 190, 208, 196, 49, 203, 42, 173, 15, 202, 112, 255, 50, 105, + 8, 98, 0, 36, 209, 251, 186, 237, 69, 129, 115, 109, 132, 159, 238, 74, + 195, 46, 193, 1, 230, 37, 72, 153, 185, 179, 123, 249, 206, 191, 223, 113, + 41, 205, 108, 19, 100, 155, 99, 157, 192, 75, 183, 165, 137, 95, 177, 23, + 244, 188, 211, 70, 207, 55, 94, 71, 148, 250, 252, 91, 151, 254, 90, 172, + 60, 76, 3, 53, 243, 35, 184, 93, 106, 146, 213, 33, 68, 81, 198, 125, + 57, 131, 220, 170, 124, 119, 86, 5, 27, 164, 21, 52, 30, 28, 248, 82, + 32, 20, 233, 189, 221, 228, 161, 224, 138, 241, 214, 122, 187, 227, 64, 79 +}; + +static const unsigned char FSb4[256] = +{ + 112, 44, 179, 192, 228, 87, 234, 174, 35, 107, 69, 165, 237, 79, 29, 146, + 134, 175, 124, 31, 62, 220, 94, 11, 166, 57, 213, 93, 217, 90, 81, 108, + 139, 154, 251, 176, 116, 43, 240, 132, 223, 203, 52, 118, 109, 169, 209, 4, + 20, 58, 222, 17, 50, 156, 83, 242, 254, 207, 195, 122, 36, 232, 96, 105, + 170, 160, 161, 98, 84, 30, 224, 100, 16, 0, 163, 117, 138, 230, 9, 221, + 135, 131, 205, 144, 115, 246, 157, 191, 82, 216, 200, 198, 129, 111, 19, 99, + 233, 167, 159, 188, 41, 249, 47, 180, 120, 6, 231, 113, 212, 171, 136, 141, + 114, 185, 248, 172, 54, 42, 60, 241, 64, 211, 187, 67, 21, 173, 119, 128, + 130, 236, 39, 229, 133, 53, 12, 65, 239, 147, 25, 33, 14, 78, 101, 189, + 184, 143, 235, 206, 48, 95, 197, 26, 225, 202, 71, 61, 1, 214, 86, 77, + 13, 102, 204, 45, 18, 32, 177, 153, 76, 194, 126, 5, 183, 49, 23, 215, + 88, 97, 27, 28, 15, 22, 24, 34, 68, 178, 181, 145, 8, 168, 252, 80, + 208, 125, 137, 151, 91, 149, 255, 210, 196, 72, 247, 219, 3, 218, 63, 148, + 92, 2, 74, 51, 103, 243, 127, 226, 155, 38, 55, 59, 150, 75, 190, 46, + 121, 140, 110, 142, 245, 182, 253, 89, 152, 106, 70, 186, 37, 66, 162, 250, + 7, 85, 238, 10, 73, 104, 56, 164, 40, 123, 201, 193, 227, 244, 199, 158 +}; + +#define SBOX1(n) FSb[(n)] +#define SBOX2(n) FSb2[(n)] +#define SBOX3(n) FSb3[(n)] +#define SBOX4(n) FSb4[(n)] + +#endif /* POLARSSL_CAMELLIA_SMALL_MEMORY */ + +static const unsigned char shifts[2][4][4] = +{ + { + { 1, 1, 1, 1 }, /* KL */ + { 0, 0, 0, 0 }, /* KR */ + { 1, 1, 1, 1 }, /* KA */ + { 0, 0, 0, 0 } /* KB */ + }, + { + { 1, 0, 1, 1 }, /* KL */ + { 1, 1, 0, 1 }, /* KR */ + { 1, 1, 1, 0 }, /* KA */ + { 1, 1, 0, 1 } /* KB */ + } +}; + +static const signed char indexes[2][4][20] = +{ + { + { 0, 1, 2, 3, 8, 9, 10, 11, 38, 39, + 36, 37, 23, 20, 21, 22, 27, -1, -1, 26 }, /* KL -> RK */ + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* KR -> RK */ + { 4, 5, 6, 7, 12, 13, 14, 15, 16, 17, + 18, 19, -1, 24, 25, -1, 31, 28, 29, 30 }, /* KA -> RK */ + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } /* KB -> RK */ + }, + { + { 0, 1, 2, 3, 61, 62, 63, 60, -1, -1, + -1, -1, 27, 24, 25, 26, 35, 32, 33, 34 }, /* KL -> RK */ + { -1, -1, -1, -1, 8, 9, 10, 11, 16, 17, + 18, 19, -1, -1, -1, -1, 39, 36, 37, 38 }, /* KR -> RK */ + { -1, -1, -1, -1, 12, 13, 14, 15, 58, 59, + 56, 57, 31, 28, 29, 30, -1, -1, -1, -1 }, /* KA -> RK */ + { 4, 5, 6, 7, 65, 66, 67, 64, 20, 21, + 22, 23, -1, -1, -1, -1, 43, 40, 41, 42 } /* KB -> RK */ + } +}; + +static const signed char transposes[2][20] = +{ + { + 21, 22, 23, 20, + -1, -1, -1, -1, + 18, 19, 16, 17, + 11, 8, 9, 10, + 15, 12, 13, 14 + }, + { + 25, 26, 27, 24, + 29, 30, 31, 28, + 18, 19, 16, 17, + -1, -1, -1, -1, + -1, -1, -1, -1 + } +}; + +/* Shift macro for 128 bit strings with rotation smaller than 32 bits (!) */ +#define ROTL(DEST, SRC, SHIFT) \ +{ \ + (DEST)[0] = (SRC)[0] << (SHIFT) ^ (SRC)[1] >> (32 - (SHIFT)); \ + (DEST)[1] = (SRC)[1] << (SHIFT) ^ (SRC)[2] >> (32 - (SHIFT)); \ + (DEST)[2] = (SRC)[2] << (SHIFT) ^ (SRC)[3] >> (32 - (SHIFT)); \ + (DEST)[3] = (SRC)[3] << (SHIFT) ^ (SRC)[0] >> (32 - (SHIFT)); \ +} + +#define FL(XL, XR, KL, KR) \ +{ \ + (XR) = ((((XL) & (KL)) << 1) | (((XL) & (KL)) >> 31)) ^ (XR); \ + (XL) = ((XR) | (KR)) ^ (XL); \ +} + +#define FLInv(YL, YR, KL, KR) \ +{ \ + (YL) = ((YR) | (KR)) ^ (YL); \ + (YR) = ((((YL) & (KL)) << 1) | (((YL) & (KL)) >> 31)) ^ (YR); \ +} + +#define SHIFT_AND_PLACE(INDEX, OFFSET) \ +{ \ + TK[0] = KC[(OFFSET) * 4 + 0]; \ + TK[1] = KC[(OFFSET) * 4 + 1]; \ + TK[2] = KC[(OFFSET) * 4 + 2]; \ + TK[3] = KC[(OFFSET) * 4 + 3]; \ + \ + for( i = 1; i <= 4; i++ ) \ + if( shifts[(INDEX)][(OFFSET)][i -1] ) \ + ROTL(TK + i * 4, TK, ( 15 * i ) % 32); \ + \ + for( i = 0; i < 20; i++ ) \ + if( indexes[(INDEX)][(OFFSET)][i] != -1 ) { \ + RK[indexes[(INDEX)][(OFFSET)][i]] = TK[ i ]; \ + } \ +} + +static void camellia_feistel( const uint32_t x[2], const uint32_t k[2], + uint32_t z[2]) +{ + uint32_t I0, I1; + I0 = x[0] ^ k[0]; + I1 = x[1] ^ k[1]; + + I0 = (SBOX1((I0 >> 24) & 0xFF) << 24) | + (SBOX2((I0 >> 16) & 0xFF) << 16) | + (SBOX3((I0 >> 8) & 0xFF) << 8) | + (SBOX4((I0 ) & 0xFF) ); + I1 = (SBOX2((I1 >> 24) & 0xFF) << 24) | + (SBOX3((I1 >> 16) & 0xFF) << 16) | + (SBOX4((I1 >> 8) & 0xFF) << 8) | + (SBOX1((I1 ) & 0xFF) ); + + I0 ^= (I1 << 8) | (I1 >> 24); + I1 ^= (I0 << 16) | (I0 >> 16); + I0 ^= (I1 >> 8) | (I1 << 24); + I1 ^= (I0 >> 8) | (I0 << 24); + + z[0] ^= I1; + z[1] ^= I0; +} + +void camellia_init( camellia_context *ctx ) +{ + memset( ctx, 0, sizeof( camellia_context ) ); +} + +void camellia_free( camellia_context *ctx ) +{ + if( ctx == NULL ) + return; + + polarssl_zeroize( ctx, sizeof( camellia_context ) ); +} + +/* + * Camellia key schedule (encryption) + */ +int camellia_setkey_enc( camellia_context *ctx, const unsigned char *key, + unsigned int keysize ) +{ + int idx; + size_t i; + uint32_t *RK; + unsigned char t[64]; + uint32_t SIGMA[6][2]; + uint32_t KC[16]; + uint32_t TK[20]; + + RK = ctx->rk; + + memset( t, 0, 64 ); + memset( RK, 0, sizeof(ctx->rk) ); + + switch( keysize ) + { + case 128: ctx->nr = 3; idx = 0; break; + case 192: + case 256: ctx->nr = 4; idx = 1; break; + default : return( POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH ); + } + + for( i = 0; i < keysize / 8; ++i ) + t[i] = key[i]; + + if( keysize == 192 ) { + for( i = 0; i < 8; i++ ) + t[24 + i] = ~t[16 + i]; + } + + /* + * Prepare SIGMA values + */ + for( i = 0; i < 6; i++ ) { + GET_UINT32_BE( SIGMA[i][0], SIGMA_CHARS[i], 0 ); + GET_UINT32_BE( SIGMA[i][1], SIGMA_CHARS[i], 4 ); + } + + /* + * Key storage in KC + * Order: KL, KR, KA, KB + */ + memset( KC, 0, sizeof(KC) ); + + /* Store KL, KR */ + for( i = 0; i < 8; i++ ) + GET_UINT32_BE( KC[i], t, i * 4 ); + + /* Generate KA */ + for( i = 0; i < 4; ++i ) + KC[8 + i] = KC[i] ^ KC[4 + i]; + + camellia_feistel( KC + 8, SIGMA[0], KC + 10 ); + camellia_feistel( KC + 10, SIGMA[1], KC + 8 ); + + for( i = 0; i < 4; ++i ) + KC[8 + i] ^= KC[i]; + + camellia_feistel( KC + 8, SIGMA[2], KC + 10 ); + camellia_feistel( KC + 10, SIGMA[3], KC + 8 ); + + if( keysize > 128 ) { + /* Generate KB */ + for( i = 0; i < 4; ++i ) + KC[12 + i] = KC[4 + i] ^ KC[8 + i]; + + camellia_feistel( KC + 12, SIGMA[4], KC + 14 ); + camellia_feistel( KC + 14, SIGMA[5], KC + 12 ); + } + + /* + * Generating subkeys + */ + + /* Manipulating KL */ + SHIFT_AND_PLACE( idx, 0 ); + + /* Manipulating KR */ + if( keysize > 128 ) { + SHIFT_AND_PLACE( idx, 1 ); + } + + /* Manipulating KA */ + SHIFT_AND_PLACE( idx, 2 ); + + /* Manipulating KB */ + if( keysize > 128 ) { + SHIFT_AND_PLACE( idx, 3 ); + } + + /* Do transpositions */ + for( i = 0; i < 20; i++ ) { + if( transposes[idx][i] != -1 ) { + RK[32 + 12 * idx + i] = RK[transposes[idx][i]]; + } + } + + return( 0 ); +} + +/* + * Camellia key schedule (decryption) + */ +int camellia_setkey_dec( camellia_context *ctx, const unsigned char *key, + unsigned int keysize ) +{ + int idx, ret; + size_t i; + camellia_context cty; + uint32_t *RK; + uint32_t *SK; + + camellia_init( &cty ); + + /* Also checks keysize */ + if( ( ret = camellia_setkey_enc( &cty, key, keysize ) ) ) + goto exit; + + ctx->nr = cty.nr; + idx = ( ctx->nr == 4 ); + + RK = ctx->rk; + SK = cty.rk + 24 * 2 + 8 * idx * 2; + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + + for( i = 22 + 8 * idx, SK -= 6; i > 0; i--, SK -= 4 ) + { + *RK++ = *SK++; + *RK++ = *SK++; + } + + SK -= 2; + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + +exit: + camellia_free( &cty ); + + return( ret ); +} + +/* + * Camellia-ECB block encryption/decryption + */ +int camellia_crypt_ecb( camellia_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ) +{ + int NR; + uint32_t *RK, X[4]; + + ( (void) mode ); + + NR = ctx->nr; + RK = ctx->rk; + + GET_UINT32_BE( X[0], input, 0 ); + GET_UINT32_BE( X[1], input, 4 ); + GET_UINT32_BE( X[2], input, 8 ); + GET_UINT32_BE( X[3], input, 12 ); + + X[0] ^= *RK++; + X[1] ^= *RK++; + X[2] ^= *RK++; + X[3] ^= *RK++; + + while( NR ) { + --NR; + camellia_feistel( X, RK, X + 2 ); + RK += 2; + camellia_feistel( X + 2, RK, X ); + RK += 2; + camellia_feistel( X, RK, X + 2 ); + RK += 2; + camellia_feistel( X + 2, RK, X ); + RK += 2; + camellia_feistel( X, RK, X + 2 ); + RK += 2; + camellia_feistel( X + 2, RK, X ); + RK += 2; + + if( NR ) { + FL(X[0], X[1], RK[0], RK[1]); + RK += 2; + FLInv(X[2], X[3], RK[0], RK[1]); + RK += 2; + } + } + + X[2] ^= *RK++; + X[3] ^= *RK++; + X[0] ^= *RK++; + X[1] ^= *RK++; + + PUT_UINT32_BE( X[2], output, 0 ); + PUT_UINT32_BE( X[3], output, 4 ); + PUT_UINT32_BE( X[0], output, 8 ); + PUT_UINT32_BE( X[1], output, 12 ); + + return( 0 ); +} + +#if defined(POLARSSL_CIPHER_MODE_CBC) +/* + * Camellia-CBC buffer encryption/decryption + */ +int camellia_crypt_cbc( camellia_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char temp[16]; + + if( length % 16 ) + return( POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH ); + + if( mode == CAMELLIA_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, 16 ); + camellia_crypt_ecb( ctx, mode, input, output ); + + for( i = 0; i < 16; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + else + { + while( length > 0 ) + { + for( i = 0; i < 16; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + camellia_crypt_ecb( ctx, mode, output, output ); + memcpy( iv, output, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + + return( 0 ); +} +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_CIPHER_MODE_CFB) +/* + * Camellia-CFB128 buffer encryption/decryption + */ +int camellia_crypt_cfb128( camellia_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int c; + size_t n = *iv_off; + + if( mode == CAMELLIA_DECRYPT ) + { + while( length-- ) + { + if( n == 0 ) + camellia_crypt_ecb( ctx, CAMELLIA_ENCRYPT, iv, iv ); + + c = *input++; + *output++ = (unsigned char)( c ^ iv[n] ); + iv[n] = (unsigned char) c; + + n = ( n + 1 ) & 0x0F; + } + } + else + { + while( length-- ) + { + if( n == 0 ) + camellia_crypt_ecb( ctx, CAMELLIA_ENCRYPT, iv, iv ); + + iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); + + n = ( n + 1 ) & 0x0F; + } + } + + *iv_off = n; + + return( 0 ); +} +#endif /* POLARSSL_CIPHER_MODE_CFB */ + +#if defined(POLARSSL_CIPHER_MODE_CTR) +/* + * Camellia-CTR buffer encryption/decryption + */ +int camellia_crypt_ctr( camellia_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ) +{ + int c, i; + size_t n = *nc_off; + + while( length-- ) + { + if( n == 0 ) { + camellia_crypt_ecb( ctx, CAMELLIA_ENCRYPT, nonce_counter, + stream_block ); + + for( i = 16; i > 0; i-- ) + if( ++nonce_counter[i - 1] != 0 ) + break; + } + c = *input++; + *output++ = (unsigned char)( c ^ stream_block[n] ); + + n = ( n + 1 ) & 0x0F; + } + + *nc_off = n; + + return( 0 ); +} +#endif /* POLARSSL_CIPHER_MODE_CTR */ +#endif /* !POLARSSL_CAMELLIA_ALT */ + +#if defined(POLARSSL_SELF_TEST) + +#include + +/* + * Camellia test vectors from: + * + * http://info.isl.ntt.co.jp/crypt/eng/camellia/technology.html: + * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/intermediate.txt + * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/t_camellia.txt + * (For each bitlength: Key 0, Nr 39) + */ +#define CAMELLIA_TESTS_ECB 2 + +static const unsigned char camellia_test_ecb_key[3][CAMELLIA_TESTS_ECB][32] = +{ + { + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } + }, + { + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } + }, + { + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } + }, +}; + +static const unsigned char camellia_test_ecb_plain[CAMELLIA_TESTS_ECB][16] = +{ + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, + { 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}; + +static const unsigned char camellia_test_ecb_cipher[3][CAMELLIA_TESTS_ECB][16] = +{ + { + { 0x67, 0x67, 0x31, 0x38, 0x54, 0x96, 0x69, 0x73, + 0x08, 0x57, 0x06, 0x56, 0x48, 0xea, 0xbe, 0x43 }, + { 0x38, 0x3C, 0x6C, 0x2A, 0xAB, 0xEF, 0x7F, 0xDE, + 0x25, 0xCD, 0x47, 0x0B, 0xF7, 0x74, 0xA3, 0x31 } + }, + { + { 0xb4, 0x99, 0x34, 0x01, 0xb3, 0xe9, 0x96, 0xf8, + 0x4e, 0xe5, 0xce, 0xe7, 0xd7, 0x9b, 0x09, 0xb9 }, + { 0xD1, 0x76, 0x3F, 0xC0, 0x19, 0xD7, 0x7C, 0xC9, + 0x30, 0xBF, 0xF2, 0xA5, 0x6F, 0x7C, 0x93, 0x64 } + }, + { + { 0x9a, 0xcc, 0x23, 0x7d, 0xff, 0x16, 0xd7, 0x6c, + 0x20, 0xef, 0x7c, 0x91, 0x9e, 0x3a, 0x75, 0x09 }, + { 0x05, 0x03, 0xFB, 0x10, 0xAB, 0x24, 0x1E, 0x7C, + 0xF4, 0x5D, 0x8C, 0xDE, 0xEE, 0x47, 0x43, 0x35 } + } +}; + +#if defined(POLARSSL_CIPHER_MODE_CBC) +#define CAMELLIA_TESTS_CBC 3 + +static const unsigned char camellia_test_cbc_key[3][32] = +{ + { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, + 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C } + , + { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, + 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, + 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B } + , + { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, + 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, + 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, + 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } +}; + +static const unsigned char camellia_test_cbc_iv[16] = + + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F } +; + +static const unsigned char camellia_test_cbc_plain[CAMELLIA_TESTS_CBC][16] = +{ + { 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 } + +}; + +static const unsigned char camellia_test_cbc_cipher[3][CAMELLIA_TESTS_CBC][16] = +{ + { + { 0x16, 0x07, 0xCF, 0x49, 0x4B, 0x36, 0xBB, 0xF0, + 0x0D, 0xAE, 0xB0, 0xB5, 0x03, 0xC8, 0x31, 0xAB }, + { 0xA2, 0xF2, 0xCF, 0x67, 0x16, 0x29, 0xEF, 0x78, + 0x40, 0xC5, 0xA5, 0xDF, 0xB5, 0x07, 0x48, 0x87 }, + { 0x0F, 0x06, 0x16, 0x50, 0x08, 0xCF, 0x8B, 0x8B, + 0x5A, 0x63, 0x58, 0x63, 0x62, 0x54, 0x3E, 0x54 } + }, + { + { 0x2A, 0x48, 0x30, 0xAB, 0x5A, 0xC4, 0xA1, 0xA2, + 0x40, 0x59, 0x55, 0xFD, 0x21, 0x95, 0xCF, 0x93 }, + { 0x5D, 0x5A, 0x86, 0x9B, 0xD1, 0x4C, 0xE5, 0x42, + 0x64, 0xF8, 0x92, 0xA6, 0xDD, 0x2E, 0xC3, 0xD5 }, + { 0x37, 0xD3, 0x59, 0xC3, 0x34, 0x98, 0x36, 0xD8, + 0x84, 0xE3, 0x10, 0xAD, 0xDF, 0x68, 0xC4, 0x49 } + }, + { + { 0xE6, 0xCF, 0xA3, 0x5F, 0xC0, 0x2B, 0x13, 0x4A, + 0x4D, 0x2C, 0x0B, 0x67, 0x37, 0xAC, 0x3E, 0xDA }, + { 0x36, 0xCB, 0xEB, 0x73, 0xBD, 0x50, 0x4B, 0x40, + 0x70, 0xB1, 0xB7, 0xDE, 0x2B, 0x21, 0xEB, 0x50 }, + { 0xE3, 0x1A, 0x60, 0x55, 0x29, 0x7D, 0x96, 0xCA, + 0x33, 0x30, 0xCD, 0xF1, 0xB1, 0x86, 0x0A, 0x83 } + } +}; +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_CIPHER_MODE_CTR) +/* + * Camellia-CTR test vectors from: + * + * http://www.faqs.org/rfcs/rfc5528.html + */ + +static const unsigned char camellia_test_ctr_key[3][16] = +{ + { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC, + 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E }, + { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7, + 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 }, + { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8, + 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC } +}; + +static const unsigned char camellia_test_ctr_nonce_counter[3][16] = +{ + { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59, + 0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 }, + { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F, + 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 } +}; + +static const unsigned char camellia_test_ctr_pt[3][48] = +{ + { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62, + 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 }, + + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }, + + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x20, 0x21, 0x22, 0x23 } +}; + +static const unsigned char camellia_test_ctr_ct[3][48] = +{ + { 0xD0, 0x9D, 0xC2, 0x9A, 0x82, 0x14, 0x61, 0x9A, + 0x20, 0x87, 0x7C, 0x76, 0xDB, 0x1F, 0x0B, 0x3F }, + { 0xDB, 0xF3, 0xC7, 0x8D, 0xC0, 0x83, 0x96, 0xD4, + 0xDA, 0x7C, 0x90, 0x77, 0x65, 0xBB, 0xCB, 0x44, + 0x2B, 0x8E, 0x8E, 0x0F, 0x31, 0xF0, 0xDC, 0xA7, + 0x2C, 0x74, 0x17, 0xE3, 0x53, 0x60, 0xE0, 0x48 }, + { 0xB1, 0x9D, 0x1F, 0xCD, 0xCB, 0x75, 0xEB, 0x88, + 0x2F, 0x84, 0x9C, 0xE2, 0x4D, 0x85, 0xCF, 0x73, + 0x9C, 0xE6, 0x4B, 0x2B, 0x5C, 0x9D, 0x73, 0xF1, + 0x4F, 0x2D, 0x5D, 0x9D, 0xCE, 0x98, 0x89, 0xCD, + 0xDF, 0x50, 0x86, 0x96 } +}; + +static const int camellia_test_ctr_len[3] = + { 16, 32, 36 }; +#endif /* POLARSSL_CIPHER_MODE_CTR */ + +/* + * Checkup routine + */ +int camellia_self_test( int verbose ) +{ + int i, j, u, v; + unsigned char key[32]; + unsigned char buf[64]; + unsigned char src[16]; + unsigned char dst[16]; +#if defined(POLARSSL_CIPHER_MODE_CBC) + unsigned char iv[16]; +#endif +#if defined(POLARSSL_CIPHER_MODE_CTR) + size_t offset, len; + unsigned char nonce_counter[16]; + unsigned char stream_block[16]; +#endif + + camellia_context ctx; + + memset( key, 0, 32 ); + + for( j = 0; j < 6; j++ ) { + u = j >> 1; + v = j & 1; + + if( verbose != 0 ) + polarssl_printf( " CAMELLIA-ECB-%3d (%s): ", 128 + u * 64, + (v == CAMELLIA_DECRYPT) ? "dec" : "enc"); + + for( i = 0; i < CAMELLIA_TESTS_ECB; i++ ) { + memcpy( key, camellia_test_ecb_key[u][i], 16 + 8 * u ); + + if( v == CAMELLIA_DECRYPT ) { + camellia_setkey_dec( &ctx, key, 128 + u * 64 ); + memcpy( src, camellia_test_ecb_cipher[u][i], 16 ); + memcpy( dst, camellia_test_ecb_plain[i], 16 ); + } else { /* CAMELLIA_ENCRYPT */ + camellia_setkey_enc( &ctx, key, 128 + u * 64 ); + memcpy( src, camellia_test_ecb_plain[i], 16 ); + memcpy( dst, camellia_test_ecb_cipher[u][i], 16 ); + } + + camellia_crypt_ecb( &ctx, v, src, buf ); + + if( memcmp( buf, dst, 16 ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); + +#if defined(POLARSSL_CIPHER_MODE_CBC) + /* + * CBC mode + */ + for( j = 0; j < 6; j++ ) + { + u = j >> 1; + v = j & 1; + + if( verbose != 0 ) + polarssl_printf( " CAMELLIA-CBC-%3d (%s): ", 128 + u * 64, + ( v == CAMELLIA_DECRYPT ) ? "dec" : "enc" ); + + memcpy( src, camellia_test_cbc_iv, 16 ); + memcpy( dst, camellia_test_cbc_iv, 16 ); + memcpy( key, camellia_test_cbc_key[u], 16 + 8 * u ); + + if( v == CAMELLIA_DECRYPT ) { + camellia_setkey_dec( &ctx, key, 128 + u * 64 ); + } else { + camellia_setkey_enc( &ctx, key, 128 + u * 64 ); + } + + for( i = 0; i < CAMELLIA_TESTS_CBC; i++ ) { + + if( v == CAMELLIA_DECRYPT ) { + memcpy( iv , src, 16 ); + memcpy( src, camellia_test_cbc_cipher[u][i], 16 ); + memcpy( dst, camellia_test_cbc_plain[i], 16 ); + } else { /* CAMELLIA_ENCRYPT */ + memcpy( iv , dst, 16 ); + memcpy( src, camellia_test_cbc_plain[i], 16 ); + memcpy( dst, camellia_test_cbc_cipher[u][i], 16 ); + } + + camellia_crypt_cbc( &ctx, v, 16, iv, src, buf ); + + if( memcmp( buf, dst, 16 ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } +#endif /* POLARSSL_CIPHER_MODE_CBC */ + + if( verbose != 0 ) + polarssl_printf( "\n" ); + +#if defined(POLARSSL_CIPHER_MODE_CTR) + /* + * CTR mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + polarssl_printf( " CAMELLIA-CTR-128 (%s): ", + ( v == CAMELLIA_DECRYPT ) ? "dec" : "enc" ); + + memcpy( nonce_counter, camellia_test_ctr_nonce_counter[u], 16 ); + memcpy( key, camellia_test_ctr_key[u], 16 ); + + offset = 0; + camellia_setkey_enc( &ctx, key, 128 ); + + if( v == CAMELLIA_DECRYPT ) + { + len = camellia_test_ctr_len[u]; + memcpy( buf, camellia_test_ctr_ct[u], len ); + + camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, + buf, buf ); + + if( memcmp( buf, camellia_test_ctr_pt[u], len ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + } + else + { + len = camellia_test_ctr_len[u]; + memcpy( buf, camellia_test_ctr_pt[u], len ); + + camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, + buf, buf ); + + if( memcmp( buf, camellia_test_ctr_ct[u], len ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); +#endif /* POLARSSL_CIPHER_MODE_CTR */ + + return( 0 ); +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_CAMELLIA_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/ccm.c b/component/common/network/ssl/polarssl-1.3.8/library/ccm.c new file mode 100644 index 0000000..72d766b --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/ccm.c @@ -0,0 +1,456 @@ +/* + * NIST SP800-38C compliant CCM implementation + * + * Copyright (C) 2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* + * Definition of CCM: + * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf + * RFC 3610 "Counter with CBC-MAC (CCM)" + * + * Related: + * RFC 5116 "An Interface and Algorithms for Authenticated Encryption" + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_CCM_C) + +#include "polarssl/ccm.h" + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +#define CCM_ENCRYPT 0 +#define CCM_DECRYPT 1 + +/* + * Initialize context + */ +int ccm_init( ccm_context *ctx, cipher_id_t cipher, + const unsigned char *key, unsigned int keysize ) +{ + int ret; + const cipher_info_t *cipher_info; + + memset( ctx, 0, sizeof( ccm_context ) ); + + cipher_init( &ctx->cipher_ctx ); + + cipher_info = cipher_info_from_values( cipher, keysize, POLARSSL_MODE_ECB ); + if( cipher_info == NULL ) + return( POLARSSL_ERR_CCM_BAD_INPUT ); + + if( cipher_info->block_size != 16 ) + return( POLARSSL_ERR_CCM_BAD_INPUT ); + + if( ( ret = cipher_init_ctx( &ctx->cipher_ctx, cipher_info ) ) != 0 ) + return( ret ); + + if( ( ret = cipher_setkey( &ctx->cipher_ctx, key, keysize, + POLARSSL_ENCRYPT ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +/* + * Free context + */ +void ccm_free( ccm_context *ctx ) +{ + cipher_free( &ctx->cipher_ctx ); + polarssl_zeroize( ctx, sizeof( ccm_context ) ); +} + +/* + * Macros for common operations. + * Results in smaller compiled code than static inline functions. + */ + +/* + * Update the CBC-MAC state in y using a block in b + * (Always using b as the source helps the compiler optimise a bit better.) + */ +#define UPDATE_CBC_MAC \ + for( i = 0; i < 16; i++ ) \ + y[i] ^= b[i]; \ + \ + if( ( ret = cipher_update( &ctx->cipher_ctx, y, 16, y, &olen ) ) != 0 ) \ + return( ret ); + +/* + * Encrypt or decrypt a partial block with CTR + * Warning: using b for temporary storage! src and dst must not be b! + * This avoids allocating one more 16 bytes buffer while allowing src == dst. + */ +#define CTR_CRYPT( dst, src, len ) \ + if( ( ret = cipher_update( &ctx->cipher_ctx, ctr, 16, b, &olen ) ) != 0 ) \ + return( ret ); \ + \ + for( i = 0; i < len; i++ ) \ + dst[i] = src[i] ^ b[i]; + +/* + * Authenticated encryption or decryption + */ +static int ccm_auth_crypt( ccm_context *ctx, int mode, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len ) +{ + int ret; + unsigned char i; + unsigned char q = 16 - 1 - iv_len; + size_t len_left, olen; + unsigned char b[16]; + unsigned char y[16]; + unsigned char ctr[16]; + const unsigned char *src; + unsigned char *dst; + + /* + * Check length requirements: SP800-38C A.1 + * Additional requirement: a < 2^16 - 2^8 to simplify the code. + * 'length' checked later (when writing it to the first block) + */ + if( tag_len < 4 || tag_len > 16 || tag_len % 2 != 0 ) + return( POLARSSL_ERR_CCM_BAD_INPUT ); + + /* Also implies q is within bounds */ + if( iv_len < 7 || iv_len > 13 ) + return( POLARSSL_ERR_CCM_BAD_INPUT ); + + if( add_len > 0xFF00 ) + return( POLARSSL_ERR_CCM_BAD_INPUT ); + + /* + * First block B_0: + * 0 .. 0 flags + * 1 .. iv_len nonce (aka iv) + * iv_len+1 .. 15 length + * + * With flags as (bits): + * 7 0 + * 6 add present? + * 5 .. 3 (t - 2) / 2 + * 2 .. 0 q - 1 + */ + b[0] = 0; + b[0] |= ( add_len > 0 ) << 6; + b[0] |= ( ( tag_len - 2 ) / 2 ) << 3; + b[0] |= q - 1; + + memcpy( b + 1, iv, iv_len ); + + for( i = 0, len_left = length; i < q; i++, len_left >>= 8 ) + b[15-i] = (unsigned char)( len_left & 0xFF ); + + if( len_left > 0 ) + return( POLARSSL_ERR_CCM_BAD_INPUT ); + + + /* Start CBC-MAC with first block */ + memset( y, 0, 16 ); + UPDATE_CBC_MAC; + + /* + * If there is additional data, update CBC-MAC with + * add_len, add, 0 (padding to a block boundary) + */ + if( add_len > 0 ) + { + size_t use_len; + len_left = add_len; + src = add; + + memset( b, 0, 16 ); + b[0] = (unsigned char)( ( add_len >> 8 ) & 0xFF ); + b[1] = (unsigned char)( ( add_len ) & 0xFF ); + + use_len = len_left < 16 - 2 ? len_left : 16 - 2; + memcpy( b + 2, src, use_len ); + len_left -= use_len; + src += use_len; + + UPDATE_CBC_MAC; + + while( len_left > 0 ) + { + use_len = len_left > 16 ? 16 : len_left; + + memset( b, 0, 16 ); + memcpy( b, src, use_len ); + UPDATE_CBC_MAC; + + len_left -= use_len; + src += use_len; + } + } + + /* + * Prepare counter block for encryption: + * 0 .. 0 flags + * 1 .. iv_len nonce (aka iv) + * iv_len+1 .. 15 counter (initially 1) + * + * With flags as (bits): + * 7 .. 3 0 + * 2 .. 0 q - 1 + */ + ctr[0] = q - 1; + memcpy( ctr + 1, iv, iv_len ); + memset( ctr + 1 + iv_len, 0, q ); + ctr[15] = 1; + + /* + * Authenticate and {en,de}crypt the message. + * + * The only difference between encryption and decryption is + * the respective order of authentication and {en,de}cryption. + */ + len_left = length; + src = input; + dst = output; + + while( len_left > 0 ) + { + unsigned char use_len = len_left > 16 ? 16 : len_left; + + if( mode == CCM_ENCRYPT ) + { + memset( b, 0, 16 ); + memcpy( b, src, use_len ); + UPDATE_CBC_MAC; + } + + CTR_CRYPT( dst, src, use_len ); + + if( mode == CCM_DECRYPT ) + { + memset( b, 0, 16 ); + memcpy( b, dst, use_len ); + UPDATE_CBC_MAC; + } + + dst += use_len; + src += use_len; + len_left -= use_len; + + /* + * Increment counter. + * No need to check for overflow thanks to the length check above. + */ + for( i = 0; i < q; i++ ) + if( ++ctr[15-i] != 0 ) + break; + } + + /* + * Authentication: reset counter and crypt/mask internal tag + */ + for( i = 0; i < q; i++ ) + ctr[15-i] = 0; + + CTR_CRYPT( y, y, 16 ); + memcpy( tag, y, tag_len ); + + return( 0 ); +} + +/* + * Authenticated encryption + */ +int ccm_encrypt_and_tag( ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len ) +{ + return( ccm_auth_crypt( ctx, CCM_ENCRYPT, length, iv, iv_len, + add, add_len, input, output, tag, tag_len ) ); +} + +/* + * Authenticated decryption + */ +int ccm_auth_decrypt( ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + const unsigned char *tag, size_t tag_len ) +{ + int ret; + unsigned char check_tag[16]; + unsigned char i; + int diff; + + if( ( ret = ccm_auth_crypt( ctx, CCM_DECRYPT, length, + iv, iv_len, add, add_len, + input, output, check_tag, tag_len ) ) != 0 ) + { + return( ret ); + } + + /* Check tag in "constant-time" */ + for( diff = 0, i = 0; i < tag_len; i++ ) + diff |= tag[i] ^ check_tag[i]; + + if( diff != 0 ) + { + polarssl_zeroize( output, length ); + return( POLARSSL_ERR_CCM_AUTH_FAILED ); + } + + return( 0 ); +} + + +#if defined(POLARSSL_SELF_TEST) && defined(POLARSSL_AES_C) + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include +#define polarssl_printf printf +#endif + +/* + * Examples 1 to 3 from SP800-38C Appendix C + */ + +#define NB_TESTS 3 + +/* + * The data is the same for all tests, only the used length changes + */ +static const unsigned char key[] = { + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f +}; + +static const unsigned char iv[] = { + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b +}; + +static const unsigned char ad[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13 +}; + +static const unsigned char msg[] = { + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, +}; + +static const size_t iv_len [NB_TESTS] = { 7, 8, 12 }; +static const size_t add_len[NB_TESTS] = { 8, 16, 20 }; +static const size_t msg_len[NB_TESTS] = { 4, 16, 24 }; +static const size_t tag_len[NB_TESTS] = { 4, 6, 8 }; + +static const unsigned char res[NB_TESTS][32] = { + { 0x71, 0x62, 0x01, 0x5b, 0x4d, 0xac, 0x25, 0x5d }, + { 0xd2, 0xa1, 0xf0, 0xe0, 0x51, 0xea, 0x5f, 0x62, + 0x08, 0x1a, 0x77, 0x92, 0x07, 0x3d, 0x59, 0x3d, + 0x1f, 0xc6, 0x4f, 0xbf, 0xac, 0xcd }, + { 0xe3, 0xb2, 0x01, 0xa9, 0xf5, 0xb7, 0x1a, 0x7a, + 0x9b, 0x1c, 0xea, 0xec, 0xcd, 0x97, 0xe7, 0x0b, + 0x61, 0x76, 0xaa, 0xd9, 0xa4, 0x42, 0x8a, 0xa5, + 0x48, 0x43, 0x92, 0xfb, 0xc1, 0xb0, 0x99, 0x51 } +}; + +int ccm_self_test( int verbose ) +{ + ccm_context ctx; + unsigned char out[32]; + size_t i; + int ret; + + if( ccm_init( &ctx, POLARSSL_CIPHER_ID_AES, key, 8 * sizeof key ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( " CCM: setup failed" ); + + return( 1 ); + } + + for( i = 0; i < NB_TESTS; i++ ) + { + if( verbose != 0 ) + polarssl_printf( " CCM-AES #%u: ", (unsigned int) i + 1 ); + + ret = ccm_encrypt_and_tag( &ctx, msg_len[i], + iv, iv_len[i], ad, add_len[i], + msg, out, + out + msg_len[i], tag_len[i] ); + + if( ret != 0 || + memcmp( out, res[i], msg_len[i] + tag_len[i] ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + ret = ccm_auth_decrypt( &ctx, msg_len[i], + iv, iv_len[i], ad, add_len[i], + res[i], out, + res[i] + msg_len[i], tag_len[i] ); + + if( ret != 0 || + memcmp( out, msg, msg_len[i] ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + ccm_free( &ctx ); + + if( verbose != 0 ) + polarssl_printf( "\n" ); + + return( 0 ); +} + +#endif /* POLARSSL_SELF_TEST && POLARSSL_AES_C */ + +#endif /* POLARSSL_CCM_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/certs.c b/component/common/network/ssl/polarssl-1.3.8/library/certs.c new file mode 100644 index 0000000..a782bc1 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/certs.c @@ -0,0 +1,310 @@ +/* + * X.509 test certificates + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_CERTS_C) + +#if defined(POLARSSL_ECDSA_C) +#define TEST_CA_CRT_EC \ +"-----BEGIN CERTIFICATE-----\r\n" \ +"MIICUjCCAdegAwIBAgIJAMFD4n5iQ8zoMAoGCCqGSM49BAMCMD4xCzAJBgNVBAYT\r\n" \ +"Ak5MMREwDwYDVQQKEwhQb2xhclNTTDEcMBoGA1UEAxMTUG9sYXJzc2wgVGVzdCBF\r\n" \ +"QyBDQTAeFw0xMzA5MjQxNTQ5NDhaFw0yMzA5MjIxNTQ5NDhaMD4xCzAJBgNVBAYT\r\n" \ +"Ak5MMREwDwYDVQQKEwhQb2xhclNTTDEcMBoGA1UEAxMTUG9sYXJzc2wgVGVzdCBF\r\n" \ +"QyBDQTB2MBAGByqGSM49AgEGBSuBBAAiA2IABMPaKzRBN1gvh1b+/Im6KUNLTuBu\r\n" \ +"ww5XUzM5WNRStJGVOQsj318XJGJI/BqVKc4sLYfCiFKAr9ZqqyHduNMcbli4yuiy\r\n" \ +"aY7zQa0pw7RfdadHb9UZKVVpmlM7ILRmFmAzHqOBoDCBnTAdBgNVHQ4EFgQUnW0g\r\n" \ +"JEkBPyvLeLUZvH4kydv7NnwwbgYDVR0jBGcwZYAUnW0gJEkBPyvLeLUZvH4kydv7\r\n" \ +"NnyhQqRAMD4xCzAJBgNVBAYTAk5MMREwDwYDVQQKEwhQb2xhclNTTDEcMBoGA1UE\r\n" \ +"AxMTUG9sYXJzc2wgVGVzdCBFQyBDQYIJAMFD4n5iQ8zoMAwGA1UdEwQFMAMBAf8w\r\n" \ +"CgYIKoZIzj0EAwIDaQAwZgIxAMO0YnNWKJUAfXgSJtJxexn4ipg+kv4znuR50v56\r\n" \ +"t4d0PCu412mUC6Nnd7izvtE2MgIxAP1nnJQjZ8BWukszFQDG48wxCCyci9qpdSMv\r\n" \ +"uCjn8pwUOkABXK8Mss90fzCfCEOtIA==\r\n" \ +"-----END CERTIFICATE-----\r\n" +const char test_ca_crt_ec[] = TEST_CA_CRT_EC; + +const char test_ca_key_ec[] = +"-----BEGIN EC PRIVATE KEY-----\r\n" +"Proc-Type: 4,ENCRYPTED\r\n" +"DEK-Info: DES-EDE3-CBC,307EAB469933D64E\r\n" +"\r\n" +"IxbrRmKcAzctJqPdTQLA4SWyBYYGYJVkYEna+F7Pa5t5Yg/gKADrFKcm6B72e7DG\r\n" +"ihExtZI648s0zdYw6qSJ74vrPSuWDe5qm93BqsfVH9svtCzWHW0pm1p0KTBCFfUq\r\n" +"UsuWTITwJImcnlAs1gaRZ3sAWm7cOUidL0fo2G0fYUFNcYoCSLffCFTEHBuPnagb\r\n" +"a77x/sY1Bvii8S9/XhDTb6pTMx06wzrm\r\n" +"-----END EC PRIVATE KEY-----\r\n"; + +const char test_ca_pwd_ec[] = "PolarSSLTest"; + +const char test_srv_crt_ec[] = +"-----BEGIN CERTIFICATE-----\r\n" +"MIICHzCCAaWgAwIBAgIBCTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJOTDERMA8G\r\n" +"A1UEChMIUG9sYXJTU0wxHDAaBgNVBAMTE1BvbGFyc3NsIFRlc3QgRUMgQ0EwHhcN\r\n" +"MTMwOTI0MTU1MjA0WhcNMjMwOTIyMTU1MjA0WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n" +"A1UEChMIUG9sYXJTU0wxEjAQBgNVBAMTCWxvY2FsaG9zdDBZMBMGByqGSM49AgEG\r\n" +"CCqGSM49AwEHA0IABDfMVtl2CR5acj7HWS3/IG7ufPkGkXTQrRS192giWWKSTuUA\r\n" +"2CMR/+ov0jRdXRa9iojCa3cNVc2KKg76Aci07f+jgZ0wgZowCQYDVR0TBAIwADAd\r\n" +"BgNVHQ4EFgQUUGGlj9QH2deCAQzlZX+MY0anE74wbgYDVR0jBGcwZYAUnW0gJEkB\r\n" +"PyvLeLUZvH4kydv7NnyhQqRAMD4xCzAJBgNVBAYTAk5MMREwDwYDVQQKEwhQb2xh\r\n" +"clNTTDEcMBoGA1UEAxMTUG9sYXJzc2wgVGVzdCBFQyBDQYIJAMFD4n5iQ8zoMAoG\r\n" +"CCqGSM49BAMCA2gAMGUCMQCaLFzXptui5WQN8LlO3ddh1hMxx6tzgLvT03MTVK2S\r\n" +"C12r0Lz3ri/moSEpNZWqPjkCMCE2f53GXcYLqyfyJR078c/xNSUU5+Xxl7VZ414V\r\n" +"fGa5kHvHARBPc8YAIVIqDvHH1Q==\r\n" +"-----END CERTIFICATE-----\r\n"; + +const char test_srv_key_ec[] = +"-----BEGIN EC PRIVATE KEY-----\r\n" +"MHcCAQEEIPEqEyB2AnCoPL/9U/YDHvdqXYbIogTywwyp6/UfDw6noAoGCCqGSM49\r\n" +"AwEHoUQDQgAEN8xW2XYJHlpyPsdZLf8gbu58+QaRdNCtFLX3aCJZYpJO5QDYIxH/\r\n" +"6i/SNF1dFr2KiMJrdw1VzYoqDvoByLTt/w==\r\n" +"-----END EC PRIVATE KEY-----\r\n"; + +const char test_cli_crt_ec[] = +"-----BEGIN CERTIFICATE-----\r\n" +"MIICLDCCAbKgAwIBAgIBDTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJOTDERMA8G\r\n" +"A1UEChMIUG9sYXJTU0wxHDAaBgNVBAMTE1BvbGFyc3NsIFRlc3QgRUMgQ0EwHhcN\r\n" +"MTMwOTI0MTU1MjA0WhcNMjMwOTIyMTU1MjA0WjBBMQswCQYDVQQGEwJOTDERMA8G\r\n" +"A1UEChMIUG9sYXJTU0wxHzAdBgNVBAMTFlBvbGFyU1NMIFRlc3QgQ2xpZW50IDIw\r\n" +"WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARX5a6xc9/TrLuTuIH/Eq7u5lOszlVT\r\n" +"9jQOzC7jYyUL35ji81xgNpbA1RgUcOV/n9VLRRjlsGzVXPiWj4dwo+THo4GdMIGa\r\n" +"MAkGA1UdEwQCMAAwHQYDVR0OBBYEFHoAX4Zk/OBd5REQO7LmO8QmP8/iMG4GA1Ud\r\n" +"IwRnMGWAFJ1tICRJAT8ry3i1Gbx+JMnb+zZ8oUKkQDA+MQswCQYDVQQGEwJOTDER\r\n" +"MA8GA1UEChMIUG9sYXJTU0wxHDAaBgNVBAMTE1BvbGFyc3NsIFRlc3QgRUMgQ0GC\r\n" +"CQDBQ+J+YkPM6DAKBggqhkjOPQQDAgNoADBlAjBKZQ17IIOimbmoD/yN7o89u3BM\r\n" +"lgOsjnhw3fIOoLIWy2WOGsk/LGF++DzvrRzuNiACMQCd8iem1XS4JK7haj8xocpU\r\n" +"LwjQje5PDGHfd3h9tP38Qknu5bJqws0md2KOKHyeV0U=\r\n" +"-----END CERTIFICATE-----\r\n"; + +const char test_cli_key_ec[] = +"-----BEGIN EC PRIVATE KEY-----\r\n" +"MHcCAQEEIPb3hmTxZ3/mZI3vyk7p3U3wBf+WIop6hDhkFzJhmLcqoAoGCCqGSM49\r\n" +"AwEHoUQDQgAEV+WusXPf06y7k7iB/xKu7uZTrM5VU/Y0Dswu42MlC9+Y4vNcYDaW\r\n" +"wNUYFHDlf5/VS0UY5bBs1Vz4lo+HcKPkxw==\r\n" +"-----END EC PRIVATE KEY-----\r\n"; +#else +#define TEST_CA_CRT_EC +#endif /* POLARSSL_ECDSA_C */ + +#if defined(POLARSSL_RSA_C) +#define TEST_CA_CRT_RSA \ +"-----BEGIN CERTIFICATE-----\r\n" \ +"MIIDhzCCAm+gAwIBAgIBADANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" \ +"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \ +"MTEwMjEyMTQ0NDAwWhcNMjEwMjEyMTQ0NDAwWjA7MQswCQYDVQQGEwJOTDERMA8G\r\n" \ +"A1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwggEiMA0G\r\n" \ +"CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA3zf8F7vglp0/ht6WMn1EpRagzSHx\r\n" \ +"mdTs6st8GFgIlKXsm8WL3xoemTiZhx57wI053zhdcHgH057Zk+i5clHFzqMwUqny\r\n" \ +"50BwFMtEonILwuVA+T7lpg6z+exKY8C4KQB0nFc7qKUEkHHxvYPZP9al4jwqj+8n\r\n" \ +"YMPGn8u67GB9t+aEMr5P+1gmIgNb1LTV+/Xjli5wwOQuvfwu7uJBVcA0Ln0kcmnL\r\n" \ +"R7EUQIN9Z/SG9jGr8XmksrUuEvmEF/Bibyc+E1ixVA0hmnM3oTDPb5Lc9un8rNsu\r\n" \ +"KNF+AksjoBXyOGVkCeoMbo4bF6BxyLObyavpw/LPh5aPgAIynplYb6LVAgMBAAGj\r\n" \ +"gZUwgZIwDAYDVR0TBAUwAwEB/zAdBgNVHQ4EFgQUtFrkpbPe0lL2udWmlQ/rPrzH\r\n" \ +"/f8wYwYDVR0jBFwwWoAUtFrkpbPe0lL2udWmlQ/rPrzH/f+hP6Q9MDsxCzAJBgNV\r\n" \ +"BAYTAk5MMREwDwYDVQQKEwhQb2xhclNTTDEZMBcGA1UEAxMQUG9sYXJTU0wgVGVz\r\n" \ +"dCBDQYIBADANBgkqhkiG9w0BAQUFAAOCAQEAuP1U2ABUkIslsCfdlc2i94QHHYeJ\r\n" \ +"SsR4EdgHtdciUI5I62J6Mom+Y0dT/7a+8S6MVMCZP6C5NyNyXw1GWY/YR82XTJ8H\r\n" \ +"DBJiCTok5DbZ6SzaONBzdWHXwWwmi5vg1dxn7YxrM9d0IjxM27WNKs4sDQhZBQkF\r\n" \ +"pjmfs2cb4oPl4Y9T9meTx/lvdkRYEug61Jfn6cA+qHpyPYdTH+UshITnmp5/Ztkf\r\n" \ +"m/UTSLBNFNHesiTZeH31NcxYGdHSme9Nc/gfidRa0FLOCfWxRlFqAI47zG9jAQCZ\r\n" \ +"7Z2mCGDNMhjQc+BYcdnl0lPXjdDK6V0qCg1dVewhUBcW5gZKzV7e9+DpVA==\r\n" \ +"-----END CERTIFICATE-----\r\n" +const char test_ca_crt_rsa[] = TEST_CA_CRT_RSA; + +const char test_ca_key_rsa[] = +"-----BEGIN RSA PRIVATE KEY-----\r\n" +"Proc-Type: 4,ENCRYPTED\r\n" +"DEK-Info: DES-EDE3-CBC,A8A95B05D5B7206B\r\n" +"\r\n" +"9Qd9GeArejl1GDVh2lLV1bHt0cPtfbh5h/5zVpAVaFpqtSPMrElp50Rntn9et+JA\r\n" +"7VOyboR+Iy2t/HU4WvA687k3Bppe9GwKHjHhtl//8xFKwZr3Xb5yO5JUP8AUctQq\r\n" +"Nb8CLlZyuUC+52REAAthdWgsX+7dJO4yabzUcQ22Tp9JSD0hiL43BlkWYUNK3dAo\r\n" +"PZlmiptjnzVTjg1MxsBSydZinWOLBV8/JQgxSPo2yD4uEfig28qbvQ2wNIn0pnAb\r\n" +"GxnSAOazkongEGfvcjIIs+LZN9gXFhxcOh6kc4Q/c99B7QWETwLLkYgZ+z1a9VY9\r\n" +"gEU7CwCxYCD+h9hY6FPmsK0/lC4O7aeRKpYq00rPPxs6i7phiexg6ax6yTMmArQq\r\n" +"QmK3TAsJm8V/J5AWpLEV6jAFgRGymGGHnof0DXzVWZidrcZJWTNuGEX90nB3ee2w\r\n" +"PXJEFWKoD3K3aFcSLdHYr3mLGxP7H9ThQai9VsycxZKS5kwvBKQ//YMrmFfwPk8x\r\n" +"vTeY4KZMaUrveEel5tWZC94RSMKgxR6cyE1nBXyTQnDOGbfpNNgBKxyKbINWoOJU\r\n" +"WJZAwlsQn+QzCDwpri7+sV1mS3gBE6UY7aQmnmiiaC2V3Hbphxct/en5QsfDOt1X\r\n" +"JczSfpRWLlbPznZg8OQh/VgCMA58N5DjOzTIK7sJJ5r+94ZBTCpgAMbF588f0NTR\r\n" +"KCe4yrxGJR7X02M4nvD4IwOlpsQ8xQxZtOSgXv4LkxvdU9XJJKWZ/XNKJeWztxSe\r\n" +"Z1vdTc2YfsDBA2SEv33vxHx2g1vqtw8SjDRT2RaQSS0QuSaMJimdOX6mTOCBKk1J\r\n" +"9Q5mXTrER+/LnK0jEmXsBXWA5bqqVZIyahXSx4VYZ7l7w/PHiUDtDgyRhMMKi4n2\r\n" +"iQvQcWSQTjrpnlJbca1/DkpRt3YwrvJwdqb8asZU2VrNETh5x0QVefDRLFiVpif/\r\n" +"tUaeAe/P1F8OkS7OIZDs1SUbv/sD2vMbhNkUoCms3/PvNtdnvgL4F0zhaDpKCmlT\r\n" +"P8vx49E7v5CyRNmED9zZg4o3wmMqrQO93PtTug3Eu9oVx1zPQM1NVMyBa2+f29DL\r\n" +"1nuTCeXdo9+ni45xx+jAI4DCwrRdhJ9uzZyC6962H37H6D+5naNvClFR1s6li1Gb\r\n" +"nqPoiy/OBsEx9CaDGcqQBp5Wme/3XW+6z1ISOx+igwNTVCT14mHdBMbya0eIKft5\r\n" +"X+GnwtgEMyCYyyWuUct8g4RzErcY9+yW9Om5Hzpx4zOuW4NPZgPDTgK+t2RSL/Yq\r\n" +"rE1njrgeGYcVeG3f+OftH4s6fPbq7t1A5ZgUscbLMBqr9tK+OqygR4EgKBPsH6Cz\r\n" +"L6zlv/2RV0qAHvVuDJcIDIgwY5rJtINEm32rhOeFNJwZS5MNIC1czXZx5//ugX7l\r\n" +"I4sy5nbVhwSjtAk8Xg5dZbdTZ6mIrb7xqH+fdakZor1khG7bC2uIwibD3cSl2XkR\r\n" +"wN48lslbHnqqagr6Xm1nNOSVl8C/6kbJEsMpLhAezfRtGwvOucoaE+WbeUNolGde\r\n" +"P/eQiddSf0brnpiLJRh7qZrl9XuqYdpUqnoEdMAfotDOID8OtV7gt8a48ad8VPW2\r\n" +"-----END RSA PRIVATE KEY-----\r\n"; + +const char test_ca_pwd_rsa[] = "PolarSSLTest"; + +const char test_srv_crt_rsa[] = +"-----BEGIN CERTIFICATE-----\r\n" +"MIIDNzCCAh+gAwIBAgIBAjANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" +"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" +"MTEwMjEyMTQ0NDA2WhcNMjEwMjEyMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n" +"A1UEChMIUG9sYXJTU0wxEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN\r\n" +"AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN\r\n" +"owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz\r\n" +"NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM\r\n" +"tQCQ4dqCEGZ9rlQri2V5kaHiYcPNQEkI7mgM8YuG0ka/0LiqEQMef1aoGh5EGA8P\r\n" +"hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya\r\n" +"HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaNNMEswCQYD\r\n" +"VR0TBAIwADAdBgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwHwYDVR0jBBgw\r\n" +"FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDQYJKoZIhvcNAQEFBQADggEBAJxnXClY\r\n" +"oHkbp70cqBrsGXLybA74czbO5RdLEgFs7rHVS9r+c293luS/KdliLScZqAzYVylw\r\n" +"UfRWvKMoWhHYKp3dEIS4xTXk6/5zXxhv9Rw8SGc8qn6vITHk1S1mPevtekgasY5Y\r\n" +"iWQuM3h4YVlRH3HHEMAD1TnAexfXHHDFQGe+Bd1iAbz1/sH9H8l4StwX6egvTK3M\r\n" +"wXRwkKkvjKaEDA9ATbZx0mI8LGsxSuCqe9r9dyjmttd47J1p1Rulz3CLzaRcVIuS\r\n" +"RRQfaD8neM9c1S/iJ/amTVqJxA1KOdOS5780WhPfSArA+g4qAmSjelc3p4wWpha8\r\n" +"zhuYwjVuX6JHG0c=\r\n" +"-----END CERTIFICATE-----\r\n"; + +const char test_srv_key_rsa[] = +"-----BEGIN RSA PRIVATE KEY-----\r\n" +"MIIEpAIBAAKCAQEAwU2j3efNHdEE10lyuJmsDnjkOjxKzzoTFtBa5M2jAIin7h5r\r\n" +"lqdStJDvLXJ6PiSa/LY0rCT1d+AmZIycsCh9odrqjObJHJa8/sEEUrM21KP64bF2\r\n" +"2JDBYbRmUjaiJlOqq3ReB30Zgtsq2B+g2Q0cLUlm91slc0boC4pPaQy1AJDh2oIQ\r\n" +"Zn2uVCuLZXmRoeJhw81ASQjuaAzxi4bSRr/QuKoRAx5/VqgaHkQYDw+Fi9qLRF7i\r\n" +"GMZiL8dmjfpd2H3zJ4kpAcWQDj8n8TDISg7v1t7HxydrxwU9esQCPJodPg/oNJhb\r\n" +"y3NLUpbYEaIsgIhpOVrTD7DeWS8Rx/fqEgEwlwIDAQABAoIBAQCXR0S8EIHFGORZ\r\n" +"++AtOg6eENxD+xVs0f1IeGz57Tjo3QnXX7VBZNdj+p1ECvhCE/G7XnkgU5hLZX+G\r\n" +"Z0jkz/tqJOI0vRSdLBbipHnWouyBQ4e/A1yIJdlBtqXxJ1KE/ituHRbNc4j4kL8Z\r\n" +"/r6pvwnTI0PSx2Eqs048YdS92LT6qAv4flbNDxMn2uY7s4ycS4Q8w1JXnCeaAnYm\r\n" +"WYI5wxO+bvRELR2Mcz5DmVnL8jRyml6l6582bSv5oufReFIbyPZbQWlXgYnpu6He\r\n" +"GTc7E1zKYQGG/9+DQUl/1vQuCPqQwny0tQoX2w5tdYpdMdVm+zkLtbajzdTviJJa\r\n" +"TWzL6lt5AoGBAN86+SVeJDcmQJcv4Eq6UhtRr4QGMiQMz0Sod6ettYxYzMgxtw28\r\n" +"CIrgpozCc+UaZJLo7UxvC6an85r1b2nKPCLQFaggJ0H4Q0J/sZOhBIXaoBzWxveK\r\n" +"nupceKdVxGsFi8CDy86DBfiyFivfBj+47BbaQzPBj7C4rK7UlLjab2rDAoGBAN2u\r\n" +"AM2gchoFiu4v1HFL8D7lweEpi6ZnMJjnEu/dEgGQJFjwdpLnPbsj4c75odQ4Gz8g\r\n" +"sw9lao9VVzbusoRE/JGI4aTdO0pATXyG7eG1Qu+5Yc1YGXcCrliA2xM9xx+d7f+s\r\n" +"mPzN+WIEg5GJDYZDjAzHG5BNvi/FfM1C9dOtjv2dAoGAF0t5KmwbjWHBhcVqO4Ic\r\n" +"BVvN3BIlc1ue2YRXEDlxY5b0r8N4XceMgKmW18OHApZxfl8uPDauWZLXOgl4uepv\r\n" +"whZC3EuWrSyyICNhLY21Ah7hbIEBPF3L3ZsOwC+UErL+dXWLdB56Jgy3gZaBeW7b\r\n" +"vDrEnocJbqCm7IukhXHOBK8CgYEAwqdHB0hqyNSzIOGY7v9abzB6pUdA3BZiQvEs\r\n" +"3LjHVd4HPJ2x0N8CgrBIWOE0q8+0hSMmeE96WW/7jD3fPWwCR5zlXknxBQsfv0gP\r\n" +"3BC5PR0Qdypz+d+9zfMf625kyit4T/hzwhDveZUzHnk1Cf+IG7Q+TOEnLnWAWBED\r\n" +"ISOWmrUCgYAFEmRxgwAc/u+D6t0syCwAYh6POtscq9Y0i9GyWk89NzgC4NdwwbBH\r\n" +"4AgahOxIxXx2gxJnq3yfkJfIjwf0s2DyP0kY2y6Ua1OeomPeY9mrIS4tCuDQ6LrE\r\n" +"TB6l9VGoxJL4fyHnZb8L5gGvnB1bbD8cL6YPaDiOhcRseC9vBiEuVg==\r\n" +"-----END RSA PRIVATE KEY-----\r\n"; + + +const char test_cli_crt_rsa[] = +"-----BEGIN CERTIFICATE-----\r\n" +"MIIDPzCCAiegAwIBAgIBBDANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" +"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" +"MTEwMjEyMTQ0NDA3WhcNMjEwMjEyMTQ0NDA3WjA8MQswCQYDVQQGEwJOTDERMA8G\r\n" +"A1UEChMIUG9sYXJTU0wxGjAYBgNVBAMTEVBvbGFyU1NMIENsaWVudCAyMIIBIjAN\r\n" +"BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6f\r\n" +"M60Nj4o8VmXl3ETZzGaFB9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu\r\n" +"1C93KYRhTYJQj6eVSHD1bk2y1RPD0hrt5kPqQhTrdOrA7R/UV06p86jt0uDBMHEw\r\n" +"MjDV0/YI0FZPRo7yX/k9Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v\r\n" +"4Jv4EFbMs44TFeY0BGbH7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx/\r\n" +"/DZrtenNLQNiTrM9AM+vdqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQAB\r\n" +"o00wSzAJBgNVHRMEAjAAMB0GA1UdDgQWBBRxoQBzckAvVHZeM/xSj7zx3WtGITAf\r\n" +"BgNVHSMEGDAWgBS0WuSls97SUva51aaVD+s+vMf9/zANBgkqhkiG9w0BAQUFAAOC\r\n" +"AQEAAn86isAM8X+mVwJqeItt6E9slhEQbAofyk+diH1Lh8Y9iLlWQSKbw/UXYjx5\r\n" +"LLPZcniovxIcARC/BjyZR9g3UwTHNGNm+rwrqa15viuNOFBchykX/Orsk02EH7NR\r\n" +"Alw5WLPorYjED6cdVQgBl9ot93HdJogRiXCxErM7NC8/eP511mjq+uLDjLKH8ZPQ\r\n" +"8I4ekHJnroLsDkIwXKGIsvIBHQy2ac/NwHLCQOK6mfum1pRx52V4Utu5dLLjD5bM\r\n" +"xOBC7KU4xZKuMXXZM6/93Yb51K/J4ahf1TxJlTWXtnzDr9saEYdNy2SKY/6ZiDNH\r\n" +"D+stpAKiQLAWaAusIWKYEyw9MQ==\r\n" +"-----END CERTIFICATE-----\r\n"; + +const char test_cli_key_rsa[] = +"-----BEGIN RSA PRIVATE KEY-----\r\n" +"MIIEpAIBAAKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6fM60Nj4o8VmXl3ETZzGaF\r\n" +"B9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu1C93KYRhTYJQj6eVSHD1\r\n" +"bk2y1RPD0hrt5kPqQhTrdOrA7R/UV06p86jt0uDBMHEwMjDV0/YI0FZPRo7yX/k9\r\n" +"Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v4Jv4EFbMs44TFeY0BGbH\r\n" +"7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx//DZrtenNLQNiTrM9AM+v\r\n" +"dqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQABAoIBAGdNtfYDiap6bzst\r\n" +"yhCiI8m9TtrhZw4MisaEaN/ll3XSjaOG2dvV6xMZCMV+5TeXDHOAZnY18Yi18vzz\r\n" +"4Ut2TnNFzizCECYNaA2fST3WgInnxUkV3YXAyP6CNxJaCmv2aA0yFr2kFVSeaKGt\r\n" +"ymvljNp2NVkvm7Th8fBQBO7I7AXhz43k0mR7XmPgewe8ApZOG3hstkOaMvbWAvWA\r\n" +"zCZupdDjZYjOJqlA4eEA4H8/w7F83r5CugeBE8LgEREjLPiyejrU5H1fubEY+h0d\r\n" +"l5HZBJ68ybTXfQ5U9o/QKA3dd0toBEhhdRUDGzWtjvwkEQfqF1reGWj/tod/gCpf\r\n" +"DFi6X0ECgYEA4wOv/pjSC3ty6TuOvKX2rOUiBrLXXv2JSxZnMoMiWI5ipLQt+RYT\r\n" +"VPafL/m7Dn6MbwjayOkcZhBwk5CNz5A6Q4lJ64Mq/lqHznRCQQ2Mc1G8eyDF/fYL\r\n" +"Ze2pLvwP9VD5jTc2miDfw+MnvJhywRRLcemDFP8k4hQVtm8PMp3ZmNECgYEA4gz7\r\n" +"wzObR4gn8ibe617uQPZjWzUj9dUHYd+in1gwBCIrtNnaRn9I9U/Q6tegRYpii4ys\r\n" +"c176NmU+umy6XmuSKV5qD9bSpZWG2nLFnslrN15Lm3fhZxoeMNhBaEDTnLT26yoi\r\n" +"33gp0mSSWy94ZEqipms+ULF6sY1ZtFW6tpGFoy8CgYAQHhnnvJflIs2ky4q10B60\r\n" +"ZcxFp3rtDpkp0JxhFLhiizFrujMtZSjYNm5U7KkgPVHhLELEUvCmOnKTt4ap/vZ0\r\n" +"BxJNe1GZH3pW6SAvGDQpl9sG7uu/vTFP+lCxukmzxB0DrrDcvorEkKMom7ZCCRvW\r\n" +"KZsZ6YeH2Z81BauRj218kQKBgQCUV/DgKP2985xDTT79N08jUo3hTP5MVYCCuj/+\r\n" +"UeEw1TvZcx3LJby7P6Xad6a1/BqveaGyFKIfEFIaBUBItk801sDDpDaYc4gL00Xc\r\n" +"7lFuBHOZkxJYlss5QrGpuOEl9ZwUt5IrFLBdYaKqNHzNVC1pCPfb/JyH6Dr2HUxq\r\n" +"gxUwAQKBgQCcU6G2L8AG9d9c0UpOyL1tMvFe5Ttw0KjlQVdsh1MP6yigYo9DYuwu\r\n" +"bHFVW2r0dBTqegP2/KTOxKzaHfC1qf0RGDsUoJCNJrd1cwoCLG8P2EF4w3OBrKqv\r\n" +"8u4ytY0F+Vlanj5lm3TaoHSVF1+NWPyOTiwevIECGKwSxvlki4fDAA==\r\n" +"-----END RSA PRIVATE KEY-----\r\n"; +#else +#define TEST_CA_CRT_RSA +#endif /* POLARSSL_RSA_C */ + +#if defined(POLARSSL_DHM_C) +const char test_dhm_params[] = +"-----BEGIN DH PARAMETERS-----\r\n" +"MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n" +"1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n" +"9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n" +"-----END DH PARAMETERS-----\r\n"; +#endif + +/* Concatenation of all available CA certificates */ +const char test_ca_list[] = TEST_CA_CRT_RSA TEST_CA_CRT_EC; + +#if defined(POLARSSL_RSA_C) +const char *test_ca_crt = test_ca_crt_rsa; +const char *test_ca_key = test_ca_key_rsa; +const char *test_ca_pwd = test_ca_pwd_rsa; +const char *test_srv_crt = test_srv_crt_rsa; +const char *test_srv_key = test_srv_key_rsa; +const char *test_cli_crt = test_cli_crt_rsa; +const char *test_cli_key = test_cli_key_rsa; +#else /* ! POLARSSL_RSA_C, so POLARSSL_ECDSA_C */ +const char *test_ca_crt = test_ca_crt_ec; +const char *test_ca_key = test_ca_key_ec; +const char *test_ca_pwd = test_ca_pwd_ec; +const char *test_srv_crt = test_srv_crt_ec; +const char *test_srv_key = test_srv_key_ec; +const char *test_cli_crt = test_cli_crt_ec; +const char *test_cli_key = test_cli_key_ec; +#endif /* POLARSSL_RSA_C */ + +#endif /* POLARSSL_CERTS_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/cipher.c b/component/common/network/ssl/polarssl-1.3.8/library/cipher.c new file mode 100644 index 0000000..5cd30f8 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/cipher.c @@ -0,0 +1,917 @@ +/** + * \file cipher.c + * + * \brief Generic cipher wrapper for PolarSSL + * + * \author Adriaan de Jong + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_CIPHER_C) + +#include "polarssl/cipher.h" +#include "polarssl/cipher_wrap.h" + +#if defined(POLARSSL_GCM_C) +#include "polarssl/gcm.h" +#endif + +#if defined(POLARSSL_CCM_C) +#include "polarssl/ccm.h" +#endif + +#include + +#if defined(POLARSSL_ARC4_C) || defined(POLARSSL_CIPHER_NULL_CIPHER) +#define POLARSSL_CIPHER_MODE_STREAM +#endif + +#if defined(_MSC_VER) && !defined strcasecmp && !defined(EFIX64) && \ + !defined(EFI32) +#define strcasecmp _stricmp +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +static int supported_init = 0; + +const int *cipher_list( void ) +{ + const cipher_definition_t *def; + int *type; + + if( ! supported_init ) + { + def = cipher_definitions; + type = supported_ciphers; + + while( def->type != 0 ) + *type++ = (*def++).type; + + *type = 0; + + supported_init = 1; + } + + return( supported_ciphers ); +} + +const cipher_info_t *cipher_info_from_type( const cipher_type_t cipher_type ) +{ + const cipher_definition_t *def; + + for( def = cipher_definitions; def->info != NULL; def++ ) + if( def->type == cipher_type ) + return( def->info ); + + return( NULL ); +} + +const cipher_info_t *cipher_info_from_string( const char *cipher_name ) +{ + const cipher_definition_t *def; + + if( NULL == cipher_name ) + return( NULL ); + + for( def = cipher_definitions; def->info != NULL; def++ ) + if( ! strcasecmp( def->info->name, cipher_name ) ) + return( def->info ); + + return( NULL ); +} + +const cipher_info_t *cipher_info_from_values( const cipher_id_t cipher_id, + int key_length, + const cipher_mode_t mode ) +{ + const cipher_definition_t *def; + + for( def = cipher_definitions; def->info != NULL; def++ ) + if( def->info->base->cipher == cipher_id && + def->info->key_length == (unsigned) key_length && + def->info->mode == mode ) + return( def->info ); + + return( NULL ); +} + +void cipher_init( cipher_context_t *ctx ) +{ + memset( ctx, 0, sizeof( cipher_context_t ) ); +} + +void cipher_free( cipher_context_t *ctx ) +{ + if( ctx == NULL ) + return; + + if( ctx->cipher_ctx ) + ctx->cipher_info->base->ctx_free_func( ctx->cipher_ctx ); + + polarssl_zeroize( ctx, sizeof(cipher_context_t) ); +} + +int cipher_init_ctx( cipher_context_t *ctx, const cipher_info_t *cipher_info ) +{ + if( NULL == cipher_info || NULL == ctx ) + return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); + + memset( ctx, 0, sizeof( cipher_context_t ) ); + + if( NULL == ( ctx->cipher_ctx = cipher_info->base->ctx_alloc_func() ) ) + return( POLARSSL_ERR_CIPHER_ALLOC_FAILED ); + + ctx->cipher_info = cipher_info; + +#if defined(POLARSSL_CIPHER_MODE_WITH_PADDING) + /* + * Ignore possible errors caused by a cipher mode that doesn't use padding + */ +#if defined(POLARSSL_CIPHER_PADDING_PKCS7) + (void) cipher_set_padding_mode( ctx, POLARSSL_PADDING_PKCS7 ); +#else + (void) cipher_set_padding_mode( ctx, POLARSSL_PADDING_NONE ); +#endif +#endif /* POLARSSL_CIPHER_MODE_WITH_PADDING */ + + return( 0 ); +} + +/* Deprecated, redirects to cipher_free() */ +int cipher_free_ctx( cipher_context_t *ctx ) +{ + cipher_free( ctx ); + + return( 0 ); +} + +int cipher_setkey( cipher_context_t *ctx, const unsigned char *key, + int key_length, const operation_t operation ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); + + if( ( ctx->cipher_info->flags & POLARSSL_CIPHER_VARIABLE_KEY_LEN ) == 0 && + (int) ctx->cipher_info->key_length != key_length ) + { + return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); + } + + ctx->key_length = key_length; + ctx->operation = operation; + + /* + * For CFB and CTR mode always use the encryption key schedule + */ + if( POLARSSL_ENCRYPT == operation || + POLARSSL_MODE_CFB == ctx->cipher_info->mode || + POLARSSL_MODE_CTR == ctx->cipher_info->mode ) + { + return ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key, + ctx->key_length ); + } + + if( POLARSSL_DECRYPT == operation ) + return ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key, + ctx->key_length ); + + return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); +} + +int cipher_set_iv( cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len ) +{ + size_t actual_iv_size; + + if( NULL == ctx || NULL == ctx->cipher_info || NULL == iv ) + return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); + + /* avoid buffer overflow in ctx->iv */ + if( iv_len > POLARSSL_MAX_IV_LENGTH ) + return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE ); + + if( ( ctx->cipher_info->flags & POLARSSL_CIPHER_VARIABLE_IV_LEN ) != 0 ) + actual_iv_size = iv_len; + else + { + actual_iv_size = ctx->cipher_info->iv_size; + + /* avoid reading past the end of input buffer */ + if( actual_iv_size > iv_len ) + return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); + } + + memcpy( ctx->iv, iv, actual_iv_size ); + ctx->iv_size = actual_iv_size; + + return( 0 ); +} + +int cipher_reset( cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); + + ctx->unprocessed_len = 0; + + return( 0 ); +} + +#if defined(POLARSSL_GCM_C) +int cipher_update_ad( cipher_context_t *ctx, + const unsigned char *ad, size_t ad_len ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); + + if( POLARSSL_MODE_GCM == ctx->cipher_info->mode ) + { + return gcm_starts( (gcm_context *) ctx->cipher_ctx, ctx->operation, + ctx->iv, ctx->iv_size, ad, ad_len ); + } + + return( 0 ); +} +#endif /* POLARSSL_GCM_C */ + +int cipher_update( cipher_context_t *ctx, const unsigned char *input, + size_t ilen, unsigned char *output, size_t *olen ) +{ + int ret; + + if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen ) + { + return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); + } + + *olen = 0; + + if( ctx->cipher_info->mode == POLARSSL_MODE_ECB ) + { + if( ilen != cipher_get_block_size( ctx ) ) + return( POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED ); + + *olen = ilen; + + if( 0 != ( ret = ctx->cipher_info->base->ecb_func( ctx->cipher_ctx, + ctx->operation, input, output ) ) ) + { + return( ret ); + } + + return( 0 ); + } + +#if defined(POLARSSL_GCM_C) + if( ctx->cipher_info->mode == POLARSSL_MODE_GCM ) + { + *olen = ilen; + return gcm_update( (gcm_context *) ctx->cipher_ctx, ilen, input, + output ); + } +#endif + + if( input == output && + ( ctx->unprocessed_len != 0 || ilen % cipher_get_block_size( ctx ) ) ) + { + return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); + } + +#if defined(POLARSSL_CIPHER_MODE_CBC) + if( ctx->cipher_info->mode == POLARSSL_MODE_CBC ) + { + size_t copy_len = 0; + + /* + * If there is not enough data for a full block, cache it. + */ + if( ( ctx->operation == POLARSSL_DECRYPT && + ilen + ctx->unprocessed_len <= cipher_get_block_size( ctx ) ) || + ( ctx->operation == POLARSSL_ENCRYPT && + ilen + ctx->unprocessed_len < cipher_get_block_size( ctx ) ) ) + { + memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, + ilen ); + + ctx->unprocessed_len += ilen; + return( 0 ); + } + + /* + * Process cached data first + */ + if( ctx->unprocessed_len != 0 ) + { + copy_len = cipher_get_block_size( ctx ) - ctx->unprocessed_len; + + memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, + copy_len ); + + if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, + ctx->operation, cipher_get_block_size( ctx ), ctx->iv, + ctx->unprocessed_data, output ) ) ) + { + return( ret ); + } + + *olen += cipher_get_block_size( ctx ); + output += cipher_get_block_size( ctx ); + ctx->unprocessed_len = 0; + + input += copy_len; + ilen -= copy_len; + } + + /* + * Cache final, incomplete block + */ + if( 0 != ilen ) + { + copy_len = ilen % cipher_get_block_size( ctx ); + if( copy_len == 0 && ctx->operation == POLARSSL_DECRYPT ) + copy_len = cipher_get_block_size( ctx ); + + memcpy( ctx->unprocessed_data, &( input[ilen - copy_len] ), + copy_len ); + + ctx->unprocessed_len += copy_len; + ilen -= copy_len; + } + + /* + * Process remaining full blocks + */ + if( ilen ) + { + if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, + ctx->operation, ilen, ctx->iv, input, output ) ) ) + { + return( ret ); + } + + *olen += ilen; + } + + return( 0 ); + } +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_CIPHER_MODE_CFB) + if( ctx->cipher_info->mode == POLARSSL_MODE_CFB ) + { + if( 0 != ( ret = ctx->cipher_info->base->cfb_func( ctx->cipher_ctx, + ctx->operation, ilen, &ctx->unprocessed_len, ctx->iv, + input, output ) ) ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* POLARSSL_CIPHER_MODE_CFB */ + +#if defined(POLARSSL_CIPHER_MODE_CTR) + if( ctx->cipher_info->mode == POLARSSL_MODE_CTR ) + { + if( 0 != ( ret = ctx->cipher_info->base->ctr_func( ctx->cipher_ctx, + ilen, &ctx->unprocessed_len, ctx->iv, + ctx->unprocessed_data, input, output ) ) ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* POLARSSL_CIPHER_MODE_CTR */ + +#if defined(POLARSSL_CIPHER_MODE_STREAM) + if( ctx->cipher_info->mode == POLARSSL_MODE_STREAM ) + { + if( 0 != ( ret = ctx->cipher_info->base->stream_func( ctx->cipher_ctx, + ilen, input, output ) ) ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* POLARSSL_CIPHER_MODE_STREAM */ + + return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} + +#if defined(POLARSSL_CIPHER_MODE_WITH_PADDING) +#if defined(POLARSSL_CIPHER_PADDING_PKCS7) +/* + * PKCS7 (and PKCS5) padding: fill with ll bytes, with ll = padding_len + */ +static void add_pkcs_padding( unsigned char *output, size_t output_len, + size_t data_len ) +{ + size_t padding_len = output_len - data_len; + unsigned char i; + + for( i = 0; i < padding_len; i++ ) + output[data_len + i] = (unsigned char) padding_len; +} + +static int get_pkcs_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + size_t i, pad_idx; + unsigned char padding_len, bad = 0; + + if( NULL == input || NULL == data_len ) + return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); + + padding_len = input[input_len - 1]; + *data_len = input_len - padding_len; + + /* Avoid logical || since it results in a branch */ + bad |= padding_len > input_len; + bad |= padding_len == 0; + + /* The number of bytes checked must be independent of padding_len, + * so pick input_len, which is usually 8 or 16 (one block) */ + pad_idx = input_len - padding_len; + for( i = 0; i < input_len; i++ ) + bad |= ( input[i] ^ padding_len ) * ( i >= pad_idx ); + + return( POLARSSL_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); +} +#endif /* POLARSSL_CIPHER_PADDING_PKCS7 */ + +#if defined(POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS) +/* + * One and zeros padding: fill with 80 00 ... 00 + */ +static void add_one_and_zeros_padding( unsigned char *output, + size_t output_len, size_t data_len ) +{ + size_t padding_len = output_len - data_len; + unsigned char i = 0; + + output[data_len] = 0x80; + for( i = 1; i < padding_len; i++ ) + output[data_len + i] = 0x00; +} + +static int get_one_and_zeros_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + size_t i; + unsigned char done = 0, prev_done, bad; + + if( NULL == input || NULL == data_len ) + return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); + + bad = 0xFF; + *data_len = 0; + for( i = input_len; i > 0; i-- ) + { + prev_done = done; + done |= ( input[i-1] != 0 ); + *data_len |= ( i - 1 ) * ( done != prev_done ); + bad &= ( input[i-1] ^ 0x80 ) | ( done == prev_done ); + } + + return( POLARSSL_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); + +} +#endif /* POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS */ + +#if defined(POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN) +/* + * Zeros and len padding: fill with 00 ... 00 ll, where ll is padding length + */ +static void add_zeros_and_len_padding( unsigned char *output, + size_t output_len, size_t data_len ) +{ + size_t padding_len = output_len - data_len; + unsigned char i = 0; + + for( i = 1; i < padding_len; i++ ) + output[data_len + i - 1] = 0x00; + output[output_len - 1] = (unsigned char) padding_len; +} + +static int get_zeros_and_len_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + size_t i, pad_idx; + unsigned char padding_len, bad = 0; + + if( NULL == input || NULL == data_len ) + return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); + + padding_len = input[input_len - 1]; + *data_len = input_len - padding_len; + + /* Avoid logical || since it results in a branch */ + bad |= padding_len > input_len; + bad |= padding_len == 0; + + /* The number of bytes checked must be independent of padding_len */ + pad_idx = input_len - padding_len; + for( i = 0; i < input_len - 1; i++ ) + bad |= input[i] * ( i >= pad_idx ); + + return( POLARSSL_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); +} +#endif /* POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN */ + +#if defined(POLARSSL_CIPHER_PADDING_ZEROS) +/* + * Zero padding: fill with 00 ... 00 + */ +static void add_zeros_padding( unsigned char *output, + size_t output_len, size_t data_len ) +{ + size_t i; + + for( i = data_len; i < output_len; i++ ) + output[i] = 0x00; +} + +static int get_zeros_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + size_t i; + unsigned char done = 0, prev_done; + + if( NULL == input || NULL == data_len ) + return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); + + *data_len = 0; + for( i = input_len; i > 0; i-- ) + { + prev_done = done; + done |= ( input[i-1] != 0 ); + *data_len |= i * ( done != prev_done ); + } + + return( 0 ); +} +#endif /* POLARSSL_CIPHER_PADDING_ZEROS */ + +/* + * No padding: don't pad :) + * + * There is no add_padding function (check for NULL in cipher_finish) + * but a trivial get_padding function + */ +static int get_no_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + if( NULL == input || NULL == data_len ) + return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); + + *data_len = input_len; + + return( 0 ); +} +#endif /* POLARSSL_CIPHER_MODE_WITH_PADDING */ + +int cipher_finish( cipher_context_t *ctx, + unsigned char *output, size_t *olen ) +{ + if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen ) + return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); + + *olen = 0; + + if( POLARSSL_MODE_CFB == ctx->cipher_info->mode || + POLARSSL_MODE_CTR == ctx->cipher_info->mode || + POLARSSL_MODE_GCM == ctx->cipher_info->mode || + POLARSSL_MODE_STREAM == ctx->cipher_info->mode ) + { + return( 0 ); + } + + if( POLARSSL_MODE_ECB == ctx->cipher_info->mode ) + { + if( ctx->unprocessed_len != 0 ) + return( POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED ); + + return( 0 ); + } + +#if defined(POLARSSL_CIPHER_MODE_CBC) + if( POLARSSL_MODE_CBC == ctx->cipher_info->mode ) + { + int ret = 0; + + if( POLARSSL_ENCRYPT == ctx->operation ) + { + /* check for 'no padding' mode */ + if( NULL == ctx->add_padding ) + { + if( 0 != ctx->unprocessed_len ) + return( POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED ); + + return( 0 ); + } + + ctx->add_padding( ctx->unprocessed_data, cipher_get_iv_size( ctx ), + ctx->unprocessed_len ); + } + else if( cipher_get_block_size( ctx ) != ctx->unprocessed_len ) + { + /* + * For decrypt operations, expect a full block, + * or an empty block if no padding + */ + if( NULL == ctx->add_padding && 0 == ctx->unprocessed_len ) + return( 0 ); + + return( POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED ); + } + + /* cipher block */ + if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, + ctx->operation, cipher_get_block_size( ctx ), ctx->iv, + ctx->unprocessed_data, output ) ) ) + { + return( ret ); + } + + /* Set output size for decryption */ + if( POLARSSL_DECRYPT == ctx->operation ) + return ctx->get_padding( output, cipher_get_block_size( ctx ), + olen ); + + /* Set output size for encryption */ + *olen = cipher_get_block_size( ctx ); + return( 0 ); + } +#else + ((void) output); +#endif /* POLARSSL_CIPHER_MODE_CBC */ + + return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} + +#if defined(POLARSSL_CIPHER_MODE_WITH_PADDING) +int cipher_set_padding_mode( cipher_context_t *ctx, cipher_padding_t mode ) +{ + if( NULL == ctx || + POLARSSL_MODE_CBC != ctx->cipher_info->mode ) + { + return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); + } + + switch( mode ) + { +#if defined(POLARSSL_CIPHER_PADDING_PKCS7) + case POLARSSL_PADDING_PKCS7: + ctx->add_padding = add_pkcs_padding; + ctx->get_padding = get_pkcs_padding; + break; +#endif +#if defined(POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS) + case POLARSSL_PADDING_ONE_AND_ZEROS: + ctx->add_padding = add_one_and_zeros_padding; + ctx->get_padding = get_one_and_zeros_padding; + break; +#endif +#if defined(POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN) + case POLARSSL_PADDING_ZEROS_AND_LEN: + ctx->add_padding = add_zeros_and_len_padding; + ctx->get_padding = get_zeros_and_len_padding; + break; +#endif +#if defined(POLARSSL_CIPHER_PADDING_ZEROS) + case POLARSSL_PADDING_ZEROS: + ctx->add_padding = add_zeros_padding; + ctx->get_padding = get_zeros_padding; + break; +#endif + case POLARSSL_PADDING_NONE: + ctx->add_padding = NULL; + ctx->get_padding = get_no_padding; + break; + + default: + return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } + + return( 0 ); +} +#endif /* POLARSSL_CIPHER_MODE_WITH_PADDING */ + +#if defined(POLARSSL_GCM_C) +int cipher_write_tag( cipher_context_t *ctx, + unsigned char *tag, size_t tag_len ) +{ + if( NULL == ctx || NULL == ctx->cipher_info || NULL == tag ) + return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); + + if( POLARSSL_ENCRYPT != ctx->operation ) + return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); + + if( POLARSSL_MODE_GCM == ctx->cipher_info->mode ) + return gcm_finish( (gcm_context *) ctx->cipher_ctx, tag, tag_len ); + + return( 0 ); +} + +int cipher_check_tag( cipher_context_t *ctx, + const unsigned char *tag, size_t tag_len ) +{ + int ret; + + if( NULL == ctx || NULL == ctx->cipher_info || + POLARSSL_DECRYPT != ctx->operation ) + { + return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); + } + + if( POLARSSL_MODE_GCM == ctx->cipher_info->mode ) + { + unsigned char check_tag[16]; + size_t i; + int diff; + + if( tag_len > sizeof( check_tag ) ) + return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); + + if( 0 != ( ret = gcm_finish( (gcm_context *) ctx->cipher_ctx, + check_tag, tag_len ) ) ) + { + return( ret ); + } + + /* Check the tag in "constant-time" */ + for( diff = 0, i = 0; i < tag_len; i++ ) + diff |= tag[i] ^ check_tag[i]; + + if( diff != 0 ) + return( POLARSSL_ERR_CIPHER_AUTH_FAILED ); + + return( 0 ); + } + + return( 0 ); +} +#endif /* POLARSSL_GCM_C */ + +/* + * Packet-oriented wrapper for non-AEAD modes + */ +int cipher_crypt( cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen ) +{ + int ret; + size_t finish_olen; + + if( ( ret = cipher_set_iv( ctx, iv, iv_len ) ) != 0 ) + return( ret ); + + if( ( ret = cipher_reset( ctx ) ) != 0 ) + return( ret ); + + if( ( ret = cipher_update( ctx, input, ilen, output, olen ) ) != 0 ) + return( ret ); + + if( ( ret = cipher_finish( ctx, output + *olen, &finish_olen ) ) != 0 ) + return( ret ); + + *olen += finish_olen; + + return( 0 ); +} + +#if defined(POLARSSL_CIPHER_MODE_AEAD) +/* + * Packet-oriented encryption for AEAD modes + */ +int cipher_auth_encrypt( cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + unsigned char *tag, size_t tag_len ) +{ +#if defined(POLARSSL_GCM_C) + if( POLARSSL_MODE_GCM == ctx->cipher_info->mode ) + { + *olen = ilen; + return( gcm_crypt_and_tag( ctx->cipher_ctx, GCM_ENCRYPT, ilen, + iv, iv_len, ad, ad_len, input, output, + tag_len, tag ) ); + } +#endif /* POLARSSL_GCM_C */ +#if defined(POLARSSL_CCM_C) + if( POLARSSL_MODE_CCM == ctx->cipher_info->mode ) + { + *olen = ilen; + return( ccm_encrypt_and_tag( ctx->cipher_ctx, ilen, + iv, iv_len, ad, ad_len, input, output, + tag, tag_len ) ); + } +#endif /* POLARSSL_CCM_C */ + + return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} + +/* + * Packet-oriented decryption for AEAD modes + */ +int cipher_auth_decrypt( cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + const unsigned char *tag, size_t tag_len ) +{ +#if defined(POLARSSL_GCM_C) + if( POLARSSL_MODE_GCM == ctx->cipher_info->mode ) + { + int ret; + + *olen = ilen; + ret = gcm_auth_decrypt( ctx->cipher_ctx, ilen, + iv, iv_len, ad, ad_len, + tag, tag_len, input, output ); + + if( ret == POLARSSL_ERR_GCM_AUTH_FAILED ) + ret = POLARSSL_ERR_CIPHER_AUTH_FAILED; + + return( ret ); + } +#endif /* POLARSSL_GCM_C */ +#if defined(POLARSSL_CCM_C) + if( POLARSSL_MODE_CCM == ctx->cipher_info->mode ) + { + int ret; + + *olen = ilen; + ret = ccm_auth_decrypt( ctx->cipher_ctx, ilen, + iv, iv_len, ad, ad_len, + input, output, tag, tag_len ); + + if( ret == POLARSSL_ERR_CCM_AUTH_FAILED ) + ret = POLARSSL_ERR_CIPHER_AUTH_FAILED; + + return( ret ); + } +#endif /* POLARSSL_CCM_C */ + + return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} +#endif /* POLARSSL_CIPHER_MODE_AEAD */ + + +#if defined(POLARSSL_SELF_TEST) + +/* + * Checkup routine + */ +int cipher_self_test( int verbose ) +{ + ((void) verbose); + + return( 0 ); +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_CIPHER_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/cipher_wrap.c b/component/common/network/ssl/polarssl-1.3.8/library/cipher_wrap.c new file mode 100644 index 0000000..27aa3db --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/cipher_wrap.c @@ -0,0 +1,1451 @@ +/** + * \file cipher_wrap.c + * + * \brief Generic cipher wrapper for PolarSSL + * + * \author Adriaan de Jong + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_CIPHER_C) + +#include "polarssl/cipher_wrap.h" + +#if defined(POLARSSL_AES_C) +#include "polarssl/aes.h" +#endif + +#if defined(POLARSSL_ARC4_C) +#include "polarssl/arc4.h" +#endif + +#if defined(POLARSSL_CAMELLIA_C) +#include "polarssl/camellia.h" +#endif + +#if defined(POLARSSL_DES_C) +#include "polarssl/des.h" +#endif + +#if defined(POLARSSL_BLOWFISH_C) +#include "polarssl/blowfish.h" +#endif + +#if defined(POLARSSL_GCM_C) +#include "polarssl/gcm.h" +#endif + +#if defined(POLARSSL_CCM_C) +#include "polarssl/ccm.h" +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#define polarssl_malloc malloc +#define polarssl_free free +#endif + +#include + +#if defined(POLARSSL_GCM_C) +/* shared by all GCM ciphers */ +static void *gcm_ctx_alloc( void ) +{ + return polarssl_malloc( sizeof( gcm_context ) ); +} + +static void gcm_ctx_free( void *ctx ) +{ + gcm_free( ctx ); + polarssl_free( ctx ); +} +#endif /* POLARSSL_GCM_C */ + +#if defined(POLARSSL_CCM_C) +/* shared by all CCM ciphers */ +static void *ccm_ctx_alloc( void ) +{ + return polarssl_malloc( sizeof( ccm_context ) ); +} + +static void ccm_ctx_free( void *ctx ) +{ + ccm_free( ctx ); + polarssl_free( ctx ); +} +#endif /* POLARSSL_CCM_C */ + +#if defined(POLARSSL_AES_C) + +static int aes_crypt_ecb_wrap( void *ctx, operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + return aes_crypt_ecb( (aes_context *) ctx, operation, input, output ); +} + +static int aes_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length, + unsigned char *iv, const unsigned char *input, unsigned char *output ) +{ +#if defined(POLARSSL_CIPHER_MODE_CBC) + return aes_crypt_cbc( (aes_context *) ctx, operation, length, iv, input, + output ); +#else + ((void) ctx); + ((void) operation); + ((void) length); + ((void) iv); + ((void) input); + ((void) output); + + return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE ); +#endif /* POLARSSL_CIPHER_MODE_CBC */ +} + +static int aes_crypt_cfb128_wrap( void *ctx, operation_t operation, + size_t length, size_t *iv_off, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ +#if defined(POLARSSL_CIPHER_MODE_CFB) + return aes_crypt_cfb128( (aes_context *) ctx, operation, length, iv_off, iv, + input, output ); +#else + ((void) ctx); + ((void) operation); + ((void) length); + ((void) iv_off); + ((void) iv); + ((void) input); + ((void) output); + + return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE ); +#endif /* POLARSSL_CIPHER_MODE_CFB */ +} + +static int aes_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ) +{ +#if defined(POLARSSL_CIPHER_MODE_CTR) + return aes_crypt_ctr( (aes_context *) ctx, length, nc_off, nonce_counter, + stream_block, input, output ); +#else + ((void) ctx); + ((void) length); + ((void) nc_off); + ((void) nonce_counter); + ((void) stream_block); + ((void) input); + ((void) output); + + return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE ); +#endif /* POLARSSL_CIPHER_MODE_CTR */ +} + +static int aes_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_length ) +{ + return aes_setkey_dec( (aes_context *) ctx, key, key_length ); +} + +static int aes_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_length ) +{ + return aes_setkey_enc( (aes_context *) ctx, key, key_length ); +} + +static void * aes_ctx_alloc( void ) +{ + aes_context *aes = (aes_context *) polarssl_malloc( sizeof( aes_context ) ); + + if( aes == NULL ) + return( NULL ); + + aes_init( aes ); + + return( aes ); +} + +static void aes_ctx_free( void *ctx ) +{ + aes_free( (aes_context *) ctx ); + polarssl_free( ctx ); +} + +const cipher_base_t aes_info = { + POLARSSL_CIPHER_ID_AES, + aes_crypt_ecb_wrap, + aes_crypt_cbc_wrap, + aes_crypt_cfb128_wrap, + aes_crypt_ctr_wrap, + NULL, + aes_setkey_enc_wrap, + aes_setkey_dec_wrap, + aes_ctx_alloc, + aes_ctx_free +}; + +const cipher_info_t aes_128_ecb_info = { + POLARSSL_CIPHER_AES_128_ECB, + POLARSSL_MODE_ECB, + 128, + "AES-128-ECB", + 16, + 0, + 16, + &aes_info +}; + +const cipher_info_t aes_192_ecb_info = { + POLARSSL_CIPHER_AES_192_ECB, + POLARSSL_MODE_ECB, + 192, + "AES-192-ECB", + 16, + 0, + 16, + &aes_info +}; + +const cipher_info_t aes_256_ecb_info = { + POLARSSL_CIPHER_AES_256_ECB, + POLARSSL_MODE_ECB, + 256, + "AES-256-ECB", + 16, + 0, + 16, + &aes_info +}; + +#if defined(POLARSSL_CIPHER_MODE_CBC) +const cipher_info_t aes_128_cbc_info = { + POLARSSL_CIPHER_AES_128_CBC, + POLARSSL_MODE_CBC, + 128, + "AES-128-CBC", + 16, + 0, + 16, + &aes_info +}; + +const cipher_info_t aes_192_cbc_info = { + POLARSSL_CIPHER_AES_192_CBC, + POLARSSL_MODE_CBC, + 192, + "AES-192-CBC", + 16, + 0, + 16, + &aes_info +}; + +const cipher_info_t aes_256_cbc_info = { + POLARSSL_CIPHER_AES_256_CBC, + POLARSSL_MODE_CBC, + 256, + "AES-256-CBC", + 16, + 0, + 16, + &aes_info +}; +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_CIPHER_MODE_CFB) +const cipher_info_t aes_128_cfb128_info = { + POLARSSL_CIPHER_AES_128_CFB128, + POLARSSL_MODE_CFB, + 128, + "AES-128-CFB128", + 16, + 0, + 16, + &aes_info +}; + +const cipher_info_t aes_192_cfb128_info = { + POLARSSL_CIPHER_AES_192_CFB128, + POLARSSL_MODE_CFB, + 192, + "AES-192-CFB128", + 16, + 0, + 16, + &aes_info +}; + +const cipher_info_t aes_256_cfb128_info = { + POLARSSL_CIPHER_AES_256_CFB128, + POLARSSL_MODE_CFB, + 256, + "AES-256-CFB128", + 16, + 0, + 16, + &aes_info +}; +#endif /* POLARSSL_CIPHER_MODE_CFB */ + +#if defined(POLARSSL_CIPHER_MODE_CTR) +const cipher_info_t aes_128_ctr_info = { + POLARSSL_CIPHER_AES_128_CTR, + POLARSSL_MODE_CTR, + 128, + "AES-128-CTR", + 16, + 0, + 16, + &aes_info +}; + +const cipher_info_t aes_192_ctr_info = { + POLARSSL_CIPHER_AES_192_CTR, + POLARSSL_MODE_CTR, + 192, + "AES-192-CTR", + 16, + 0, + 16, + &aes_info +}; + +const cipher_info_t aes_256_ctr_info = { + POLARSSL_CIPHER_AES_256_CTR, + POLARSSL_MODE_CTR, + 256, + "AES-256-CTR", + 16, + 0, + 16, + &aes_info +}; +#endif /* POLARSSL_CIPHER_MODE_CTR */ + +#if defined(POLARSSL_GCM_C) +static int gcm_aes_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_length ) +{ + return gcm_init( (gcm_context *) ctx, POLARSSL_CIPHER_ID_AES, + key, key_length ); +} + +const cipher_base_t gcm_aes_info = { + POLARSSL_CIPHER_ID_AES, + NULL, + NULL, + NULL, + NULL, + NULL, + gcm_aes_setkey_wrap, + gcm_aes_setkey_wrap, + gcm_ctx_alloc, + gcm_ctx_free, +}; + +const cipher_info_t aes_128_gcm_info = { + POLARSSL_CIPHER_AES_128_GCM, + POLARSSL_MODE_GCM, + 128, + "AES-128-GCM", + 12, + POLARSSL_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aes_info +}; + +const cipher_info_t aes_192_gcm_info = { + POLARSSL_CIPHER_AES_192_GCM, + POLARSSL_MODE_GCM, + 192, + "AES-192-GCM", + 12, + POLARSSL_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aes_info +}; + +const cipher_info_t aes_256_gcm_info = { + POLARSSL_CIPHER_AES_256_GCM, + POLARSSL_MODE_GCM, + 256, + "AES-256-GCM", + 12, + POLARSSL_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aes_info +}; +#endif /* POLARSSL_GCM_C */ + +#if defined(POLARSSL_CCM_C) +static int ccm_aes_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_length ) +{ + return ccm_init( (ccm_context *) ctx, POLARSSL_CIPHER_ID_AES, + key, key_length ); +} + +const cipher_base_t ccm_aes_info = { + POLARSSL_CIPHER_ID_AES, + NULL, + NULL, + NULL, + NULL, + NULL, + ccm_aes_setkey_wrap, + ccm_aes_setkey_wrap, + ccm_ctx_alloc, + ccm_ctx_free, +}; + +const cipher_info_t aes_128_ccm_info = { + POLARSSL_CIPHER_AES_128_CCM, + POLARSSL_MODE_CCM, + 128, + "AES-128-CCM", + 12, + POLARSSL_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aes_info +}; + +const cipher_info_t aes_192_ccm_info = { + POLARSSL_CIPHER_AES_192_CCM, + POLARSSL_MODE_CCM, + 192, + "AES-192-CCM", + 12, + POLARSSL_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aes_info +}; + +const cipher_info_t aes_256_ccm_info = { + POLARSSL_CIPHER_AES_256_CCM, + POLARSSL_MODE_CCM, + 256, + "AES-256-CCM", + 12, + POLARSSL_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aes_info +}; +#endif /* POLARSSL_CCM_C */ + +#endif /* POLARSSL_AES_C */ + +#if defined(POLARSSL_CAMELLIA_C) + +static int camellia_crypt_ecb_wrap( void *ctx, operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + return camellia_crypt_ecb( (camellia_context *) ctx, operation, input, + output ); +} + +static int camellia_crypt_cbc_wrap( void *ctx, operation_t operation, + size_t length, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ +#if defined(POLARSSL_CIPHER_MODE_CBC) + return camellia_crypt_cbc( (camellia_context *) ctx, operation, length, iv, + input, output ); +#else + ((void) ctx); + ((void) operation); + ((void) length); + ((void) iv); + ((void) input); + ((void) output); + + return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE ); +#endif /* POLARSSL_CIPHER_MODE_CBC */ +} + +static int camellia_crypt_cfb128_wrap( void *ctx, operation_t operation, + size_t length, size_t *iv_off, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ +#if defined(POLARSSL_CIPHER_MODE_CFB) + return camellia_crypt_cfb128( (camellia_context *) ctx, operation, length, + iv_off, iv, input, output ); +#else + ((void) ctx); + ((void) operation); + ((void) length); + ((void) iv_off); + ((void) iv); + ((void) input); + ((void) output); + + return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE ); +#endif /* POLARSSL_CIPHER_MODE_CFB */ +} + +static int camellia_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ) +{ +#if defined(POLARSSL_CIPHER_MODE_CTR) + return camellia_crypt_ctr( (camellia_context *) ctx, length, nc_off, + nonce_counter, stream_block, input, output ); +#else + ((void) ctx); + ((void) length); + ((void) nc_off); + ((void) nonce_counter); + ((void) stream_block); + ((void) input); + ((void) output); + + return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE ); +#endif /* POLARSSL_CIPHER_MODE_CTR */ +} + +static int camellia_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_length ) +{ + return camellia_setkey_dec( (camellia_context *) ctx, key, key_length ); +} + +static int camellia_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_length ) +{ + return camellia_setkey_enc( (camellia_context *) ctx, key, key_length ); +} + +static void * camellia_ctx_alloc( void ) +{ + camellia_context *ctx; + ctx = (camellia_context *) polarssl_malloc( sizeof( camellia_context ) ); + + if( ctx == NULL ) + return( NULL ); + + camellia_init( ctx ); + + return( ctx ); +} + +static void camellia_ctx_free( void *ctx ) +{ + camellia_free( (camellia_context *) ctx ); + polarssl_free( ctx ); +} + +const cipher_base_t camellia_info = { + POLARSSL_CIPHER_ID_CAMELLIA, + camellia_crypt_ecb_wrap, + camellia_crypt_cbc_wrap, + camellia_crypt_cfb128_wrap, + camellia_crypt_ctr_wrap, + NULL, + camellia_setkey_enc_wrap, + camellia_setkey_dec_wrap, + camellia_ctx_alloc, + camellia_ctx_free +}; + +const cipher_info_t camellia_128_ecb_info = { + POLARSSL_CIPHER_CAMELLIA_128_ECB, + POLARSSL_MODE_ECB, + 128, + "CAMELLIA-128-ECB", + 16, + 0, + 16, + &camellia_info +}; + +const cipher_info_t camellia_192_ecb_info = { + POLARSSL_CIPHER_CAMELLIA_192_ECB, + POLARSSL_MODE_ECB, + 192, + "CAMELLIA-192-ECB", + 16, + 0, + 16, + &camellia_info +}; + +const cipher_info_t camellia_256_ecb_info = { + POLARSSL_CIPHER_CAMELLIA_256_ECB, + POLARSSL_MODE_ECB, + 256, + "CAMELLIA-256-ECB", + 16, + 0, + 16, + &camellia_info +}; + +#if defined(POLARSSL_CIPHER_MODE_CBC) +const cipher_info_t camellia_128_cbc_info = { + POLARSSL_CIPHER_CAMELLIA_128_CBC, + POLARSSL_MODE_CBC, + 128, + "CAMELLIA-128-CBC", + 16, + 0, + 16, + &camellia_info +}; + +const cipher_info_t camellia_192_cbc_info = { + POLARSSL_CIPHER_CAMELLIA_192_CBC, + POLARSSL_MODE_CBC, + 192, + "CAMELLIA-192-CBC", + 16, + 0, + 16, + &camellia_info +}; + +const cipher_info_t camellia_256_cbc_info = { + POLARSSL_CIPHER_CAMELLIA_256_CBC, + POLARSSL_MODE_CBC, + 256, + "CAMELLIA-256-CBC", + 16, + 0, + 16, + &camellia_info +}; +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_CIPHER_MODE_CFB) +const cipher_info_t camellia_128_cfb128_info = { + POLARSSL_CIPHER_CAMELLIA_128_CFB128, + POLARSSL_MODE_CFB, + 128, + "CAMELLIA-128-CFB128", + 16, + 0, + 16, + &camellia_info +}; + +const cipher_info_t camellia_192_cfb128_info = { + POLARSSL_CIPHER_CAMELLIA_192_CFB128, + POLARSSL_MODE_CFB, + 192, + "CAMELLIA-192-CFB128", + 16, + 0, + 16, + &camellia_info +}; + +const cipher_info_t camellia_256_cfb128_info = { + POLARSSL_CIPHER_CAMELLIA_256_CFB128, + POLARSSL_MODE_CFB, + 256, + "CAMELLIA-256-CFB128", + 16, + 0, + 16, + &camellia_info +}; +#endif /* POLARSSL_CIPHER_MODE_CFB */ + +#if defined(POLARSSL_CIPHER_MODE_CTR) +const cipher_info_t camellia_128_ctr_info = { + POLARSSL_CIPHER_CAMELLIA_128_CTR, + POLARSSL_MODE_CTR, + 128, + "CAMELLIA-128-CTR", + 16, + 0, + 16, + &camellia_info +}; + +const cipher_info_t camellia_192_ctr_info = { + POLARSSL_CIPHER_CAMELLIA_192_CTR, + POLARSSL_MODE_CTR, + 192, + "CAMELLIA-192-CTR", + 16, + 0, + 16, + &camellia_info +}; + +const cipher_info_t camellia_256_ctr_info = { + POLARSSL_CIPHER_CAMELLIA_256_CTR, + POLARSSL_MODE_CTR, + 256, + "CAMELLIA-256-CTR", + 16, + 0, + 16, + &camellia_info +}; +#endif /* POLARSSL_CIPHER_MODE_CTR */ + +#if defined(POLARSSL_GCM_C) +static int gcm_camellia_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_length ) +{ + return gcm_init( (gcm_context *) ctx, POLARSSL_CIPHER_ID_CAMELLIA, + key, key_length ); +} + +const cipher_base_t gcm_camellia_info = { + POLARSSL_CIPHER_ID_CAMELLIA, + NULL, + NULL, + NULL, + NULL, + NULL, + gcm_camellia_setkey_wrap, + gcm_camellia_setkey_wrap, + gcm_ctx_alloc, + gcm_ctx_free, +}; + +const cipher_info_t camellia_128_gcm_info = { + POLARSSL_CIPHER_CAMELLIA_128_GCM, + POLARSSL_MODE_GCM, + 128, + "CAMELLIA-128-GCM", + 12, + POLARSSL_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_camellia_info +}; + +const cipher_info_t camellia_192_gcm_info = { + POLARSSL_CIPHER_CAMELLIA_192_GCM, + POLARSSL_MODE_GCM, + 192, + "CAMELLIA-192-GCM", + 12, + POLARSSL_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_camellia_info +}; + +const cipher_info_t camellia_256_gcm_info = { + POLARSSL_CIPHER_CAMELLIA_256_GCM, + POLARSSL_MODE_GCM, + 256, + "CAMELLIA-256-GCM", + 12, + POLARSSL_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_camellia_info +}; +#endif /* POLARSSL_GCM_C */ + +#if defined(POLARSSL_CCM_C) +static int ccm_camellia_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_length ) +{ + return ccm_init( (ccm_context *) ctx, POLARSSL_CIPHER_ID_CAMELLIA, + key, key_length ); +} + +const cipher_base_t ccm_camellia_info = { + POLARSSL_CIPHER_ID_CAMELLIA, + NULL, + NULL, + NULL, + NULL, + NULL, + ccm_camellia_setkey_wrap, + ccm_camellia_setkey_wrap, + ccm_ctx_alloc, + ccm_ctx_free, +}; + +const cipher_info_t camellia_128_ccm_info = { + POLARSSL_CIPHER_CAMELLIA_128_CCM, + POLARSSL_MODE_CCM, + 128, + "CAMELLIA-128-CCM", + 12, + POLARSSL_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_camellia_info +}; + +const cipher_info_t camellia_192_ccm_info = { + POLARSSL_CIPHER_CAMELLIA_192_CCM, + POLARSSL_MODE_CCM, + 192, + "CAMELLIA-192-CCM", + 12, + POLARSSL_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_camellia_info +}; + +const cipher_info_t camellia_256_ccm_info = { + POLARSSL_CIPHER_CAMELLIA_256_CCM, + POLARSSL_MODE_CCM, + 256, + "CAMELLIA-256-CCM", + 12, + POLARSSL_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_camellia_info +}; +#endif /* POLARSSL_CCM_C */ + +#endif /* POLARSSL_CAMELLIA_C */ + +#if defined(POLARSSL_DES_C) + +static int des_crypt_ecb_wrap( void *ctx, operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + ((void) operation); + return des_crypt_ecb( (des_context *) ctx, input, output ); +} + +static int des3_crypt_ecb_wrap( void *ctx, operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + ((void) operation); + return des3_crypt_ecb( (des3_context *) ctx, input, output ); +} + +static int des_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length, + unsigned char *iv, const unsigned char *input, unsigned char *output ) +{ +#if defined(POLARSSL_CIPHER_MODE_CBC) + return des_crypt_cbc( (des_context *) ctx, operation, length, iv, input, + output ); +#else + ((void) ctx); + ((void) operation); + ((void) length); + ((void) iv); + ((void) input); + ((void) output); + + return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE ); +#endif /* POLARSSL_CIPHER_MODE_CBC */ +} + +static int des3_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length, + unsigned char *iv, const unsigned char *input, unsigned char *output ) +{ +#if defined(POLARSSL_CIPHER_MODE_CBC) + return des3_crypt_cbc( (des3_context *) ctx, operation, length, iv, input, + output ); +#else + ((void) ctx); + ((void) operation); + ((void) length); + ((void) iv); + ((void) input); + ((void) output); + + return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE ); +#endif /* POLARSSL_CIPHER_MODE_CBC */ +} + +static int des_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_length ) +{ + ((void) key_length); + + return des_setkey_dec( (des_context *) ctx, key ); +} + +static int des_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_length ) +{ + ((void) key_length); + + return des_setkey_enc( (des_context *) ctx, key ); +} + +static int des3_set2key_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_length ) +{ + ((void) key_length); + + return des3_set2key_dec( (des3_context *) ctx, key ); +} + +static int des3_set2key_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_length ) +{ + ((void) key_length); + + return des3_set2key_enc( (des3_context *) ctx, key ); +} + +static int des3_set3key_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_length ) +{ + ((void) key_length); + + return des3_set3key_dec( (des3_context *) ctx, key ); +} + +static int des3_set3key_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_length ) +{ + ((void) key_length); + + return des3_set3key_enc( (des3_context *) ctx, key ); +} + +static void * des_ctx_alloc( void ) +{ + des_context *des = (des_context *) polarssl_malloc( sizeof( des_context ) ); + + if( des == NULL ) + return( NULL ); + + des_init( des ); + + return( des ); +} + +static void des_ctx_free( void *ctx ) +{ + des_free( (des_context *) ctx ); + polarssl_free( ctx ); +} + +static void * des3_ctx_alloc( void ) +{ + des3_context *des3; + des3 = (des3_context *) polarssl_malloc( sizeof( des3_context ) ); + + if( des3 == NULL ) + return( NULL ); + + des3_init( des3 ); + + return( des3 ); +} + +static void des3_ctx_free( void *ctx ) +{ + des3_free( (des3_context *) ctx ); + polarssl_free( ctx ); +} + +const cipher_base_t des_info = { + POLARSSL_CIPHER_ID_DES, + des_crypt_ecb_wrap, + des_crypt_cbc_wrap, + NULL, + NULL, + NULL, + des_setkey_enc_wrap, + des_setkey_dec_wrap, + des_ctx_alloc, + des_ctx_free +}; + +const cipher_info_t des_ecb_info = { + POLARSSL_CIPHER_DES_ECB, + POLARSSL_MODE_ECB, + POLARSSL_KEY_LENGTH_DES, + "DES-ECB", + 8, + 0, + 8, + &des_info +}; + +#if defined(POLARSSL_CIPHER_MODE_CBC) +const cipher_info_t des_cbc_info = { + POLARSSL_CIPHER_DES_CBC, + POLARSSL_MODE_CBC, + POLARSSL_KEY_LENGTH_DES, + "DES-CBC", + 8, + 0, + 8, + &des_info +}; +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +const cipher_base_t des_ede_info = { + POLARSSL_CIPHER_ID_DES, + des3_crypt_ecb_wrap, + des3_crypt_cbc_wrap, + NULL, + NULL, + NULL, + des3_set2key_enc_wrap, + des3_set2key_dec_wrap, + des3_ctx_alloc, + des3_ctx_free +}; + +const cipher_info_t des_ede_ecb_info = { + POLARSSL_CIPHER_DES_EDE_ECB, + POLARSSL_MODE_ECB, + POLARSSL_KEY_LENGTH_DES_EDE, + "DES-EDE-ECB", + 8, + 0, + 8, + &des_ede_info +}; + +#if defined(POLARSSL_CIPHER_MODE_CBC) +const cipher_info_t des_ede_cbc_info = { + POLARSSL_CIPHER_DES_EDE_CBC, + POLARSSL_MODE_CBC, + POLARSSL_KEY_LENGTH_DES_EDE, + "DES-EDE-CBC", + 8, + 0, + 8, + &des_ede_info +}; +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +const cipher_base_t des_ede3_info = { + POLARSSL_CIPHER_ID_DES, + des3_crypt_ecb_wrap, + des3_crypt_cbc_wrap, + NULL, + NULL, + NULL, + des3_set3key_enc_wrap, + des3_set3key_dec_wrap, + des3_ctx_alloc, + des3_ctx_free +}; + +const cipher_info_t des_ede3_ecb_info = { + POLARSSL_CIPHER_DES_EDE3_ECB, + POLARSSL_MODE_ECB, + POLARSSL_KEY_LENGTH_DES_EDE3, + "DES-EDE3-ECB", + 8, + 0, + 8, + &des_ede3_info +}; +#if defined(POLARSSL_CIPHER_MODE_CBC) +const cipher_info_t des_ede3_cbc_info = { + POLARSSL_CIPHER_DES_EDE3_CBC, + POLARSSL_MODE_CBC, + POLARSSL_KEY_LENGTH_DES_EDE3, + "DES-EDE3-CBC", + 8, + 0, + 8, + &des_ede3_info +}; +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_DES_C */ + +#if defined(POLARSSL_BLOWFISH_C) + +static int blowfish_crypt_ecb_wrap( void *ctx, operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + return blowfish_crypt_ecb( (blowfish_context *) ctx, operation, input, + output ); +} + +static int blowfish_crypt_cbc_wrap( void *ctx, operation_t operation, + size_t length, unsigned char *iv, const unsigned char *input, + unsigned char *output ) +{ +#if defined(POLARSSL_CIPHER_MODE_CBC) + return blowfish_crypt_cbc( (blowfish_context *) ctx, operation, length, iv, + input, output ); +#else + ((void) ctx); + ((void) operation); + ((void) length); + ((void) iv); + ((void) input); + ((void) output); + + return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE ); +#endif /* POLARSSL_CIPHER_MODE_CBC */ +} + +static int blowfish_crypt_cfb64_wrap( void *ctx, operation_t operation, + size_t length, size_t *iv_off, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ +#if defined(POLARSSL_CIPHER_MODE_CFB) + return blowfish_crypt_cfb64( (blowfish_context *) ctx, operation, length, + iv_off, iv, input, output ); +#else + ((void) ctx); + ((void) operation); + ((void) length); + ((void) iv_off); + ((void) iv); + ((void) input); + ((void) output); + + return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE ); +#endif /* POLARSSL_CIPHER_MODE_CFB */ +} + +static int blowfish_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ) +{ +#if defined(POLARSSL_CIPHER_MODE_CTR) + return blowfish_crypt_ctr( (blowfish_context *) ctx, length, nc_off, + nonce_counter, stream_block, input, output ); +#else + ((void) ctx); + ((void) length); + ((void) nc_off); + ((void) nonce_counter); + ((void) stream_block); + ((void) input); + ((void) output); + + return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE ); +#endif /* POLARSSL_CIPHER_MODE_CTR */ +} + +static int blowfish_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_length ) +{ + return blowfish_setkey( (blowfish_context *) ctx, key, key_length ); +} + +static void * blowfish_ctx_alloc( void ) +{ + blowfish_context *ctx; + ctx = (blowfish_context *) polarssl_malloc( sizeof( blowfish_context ) ); + + if( ctx == NULL ) + return( NULL ); + + blowfish_init( ctx ); + + return( ctx ); +} + +static void blowfish_ctx_free( void *ctx ) +{ + blowfish_free( (blowfish_context *) ctx ); + polarssl_free( ctx ); +} + +const cipher_base_t blowfish_info = { + POLARSSL_CIPHER_ID_BLOWFISH, + blowfish_crypt_ecb_wrap, + blowfish_crypt_cbc_wrap, + blowfish_crypt_cfb64_wrap, + blowfish_crypt_ctr_wrap, + NULL, + blowfish_setkey_wrap, + blowfish_setkey_wrap, + blowfish_ctx_alloc, + blowfish_ctx_free +}; + +const cipher_info_t blowfish_ecb_info = { + POLARSSL_CIPHER_BLOWFISH_ECB, + POLARSSL_MODE_ECB, + 128, + "BLOWFISH-ECB", + 8, + POLARSSL_CIPHER_VARIABLE_KEY_LEN, + 8, + &blowfish_info +}; + +#if defined(POLARSSL_CIPHER_MODE_CBC) +const cipher_info_t blowfish_cbc_info = { + POLARSSL_CIPHER_BLOWFISH_CBC, + POLARSSL_MODE_CBC, + 128, + "BLOWFISH-CBC", + 8, + POLARSSL_CIPHER_VARIABLE_KEY_LEN, + 8, + &blowfish_info +}; +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_CIPHER_MODE_CFB) +const cipher_info_t blowfish_cfb64_info = { + POLARSSL_CIPHER_BLOWFISH_CFB64, + POLARSSL_MODE_CFB, + 128, + "BLOWFISH-CFB64", + 8, + POLARSSL_CIPHER_VARIABLE_KEY_LEN, + 8, + &blowfish_info +}; +#endif /* POLARSSL_CIPHER_MODE_CFB */ + +#if defined(POLARSSL_CIPHER_MODE_CTR) +const cipher_info_t blowfish_ctr_info = { + POLARSSL_CIPHER_BLOWFISH_CTR, + POLARSSL_MODE_CTR, + 128, + "BLOWFISH-CTR", + 8, + POLARSSL_CIPHER_VARIABLE_KEY_LEN, + 8, + &blowfish_info +}; +#endif /* POLARSSL_CIPHER_MODE_CTR */ +#endif /* POLARSSL_BLOWFISH_C */ + +#if defined(POLARSSL_ARC4_C) +static int arc4_crypt_stream_wrap( void *ctx, size_t length, + const unsigned char *input, + unsigned char *output ) +{ + return( arc4_crypt( (arc4_context *) ctx, length, input, output ) ); +} + +static int arc4_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_length ) +{ + /* we get key_length in bits, arc4 expects it in bytes */ + if( key_length % 8 != 0 ) + return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); + + arc4_setup( (arc4_context *) ctx, key, key_length / 8 ); + return( 0 ); +} + +static void * arc4_ctx_alloc( void ) +{ + arc4_context *ctx; + ctx = (arc4_context *) polarssl_malloc( sizeof( arc4_context ) ); + + if( ctx == NULL ) + return( NULL ); + + arc4_init( ctx ); + + return( ctx ); +} + +static void arc4_ctx_free( void *ctx ) +{ + arc4_free( (arc4_context *) ctx ); + polarssl_free( ctx ); +} + +const cipher_base_t arc4_base_info = { + POLARSSL_CIPHER_ID_ARC4, + NULL, + NULL, + NULL, + NULL, + arc4_crypt_stream_wrap, + arc4_setkey_wrap, + arc4_setkey_wrap, + arc4_ctx_alloc, + arc4_ctx_free +}; + +const cipher_info_t arc4_128_info = { + POLARSSL_CIPHER_ARC4_128, + POLARSSL_MODE_STREAM, + 128, + "ARC4-128", + 0, + 0, + 1, + &arc4_base_info +}; +#endif /* POLARSSL_ARC4_C */ + +#if defined(POLARSSL_CIPHER_NULL_CIPHER) +static int null_crypt_stream( void *ctx, size_t length, + const unsigned char *input, + unsigned char *output ) +{ + ((void) ctx); + memmove( output, input, length ); + return( 0 ); +} + +static int null_setkey( void *ctx, const unsigned char *key, + unsigned int key_length ) +{ + ((void) ctx); + ((void) key); + ((void) key_length); + + return( 0 ); +} + +static void * null_ctx_alloc( void ) +{ + return( (void *) 1 ) +} + +static void null_ctx_free( void *ctx ) +{ + ((void) ctx); +} + +const cipher_base_t null_base_info = { + POLARSSL_CIPHER_ID_NULL, + NULL, + NULL, + NULL, + NULL, + null_crypt_stream, + null_setkey, + null_setkey, + null_ctx_alloc, + null_ctx_free +}; + +const cipher_info_t null_cipher_info = { + POLARSSL_CIPHER_NULL, + POLARSSL_MODE_STREAM, + 0, + "NULL", + 0, + 0, + 1, + &null_base_info +}; +#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */ + +const cipher_definition_t cipher_definitions[] = +{ +#if defined(POLARSSL_AES_C) + { POLARSSL_CIPHER_AES_128_ECB, &aes_128_ecb_info }, + { POLARSSL_CIPHER_AES_192_ECB, &aes_192_ecb_info }, + { POLARSSL_CIPHER_AES_256_ECB, &aes_256_ecb_info }, +#if defined(POLARSSL_CIPHER_MODE_CBC) + { POLARSSL_CIPHER_AES_128_CBC, &aes_128_cbc_info }, + { POLARSSL_CIPHER_AES_192_CBC, &aes_192_cbc_info }, + { POLARSSL_CIPHER_AES_256_CBC, &aes_256_cbc_info }, +#endif +#if defined(POLARSSL_CIPHER_MODE_CFB) + { POLARSSL_CIPHER_AES_128_CFB128, &aes_128_cfb128_info }, + { POLARSSL_CIPHER_AES_192_CFB128, &aes_192_cfb128_info }, + { POLARSSL_CIPHER_AES_256_CFB128, &aes_256_cfb128_info }, +#endif +#if defined(POLARSSL_CIPHER_MODE_CTR) + { POLARSSL_CIPHER_AES_128_CTR, &aes_128_ctr_info }, + { POLARSSL_CIPHER_AES_192_CTR, &aes_192_ctr_info }, + { POLARSSL_CIPHER_AES_256_CTR, &aes_256_ctr_info }, +#endif +#if defined(POLARSSL_GCM_C) + { POLARSSL_CIPHER_AES_128_GCM, &aes_128_gcm_info }, + { POLARSSL_CIPHER_AES_192_GCM, &aes_192_gcm_info }, + { POLARSSL_CIPHER_AES_256_GCM, &aes_256_gcm_info }, +#endif +#if defined(POLARSSL_CCM_C) + { POLARSSL_CIPHER_AES_128_CCM, &aes_128_ccm_info }, + { POLARSSL_CIPHER_AES_192_CCM, &aes_192_ccm_info }, + { POLARSSL_CIPHER_AES_256_CCM, &aes_256_ccm_info }, +#endif +#endif /* POLARSSL_AES_C */ + +#if defined(POLARSSL_ARC4_C) + { POLARSSL_CIPHER_ARC4_128, &arc4_128_info }, +#endif + +#if defined(POLARSSL_BLOWFISH_C) + { POLARSSL_CIPHER_BLOWFISH_ECB, &blowfish_ecb_info }, +#if defined(POLARSSL_CIPHER_MODE_CBC) + { POLARSSL_CIPHER_BLOWFISH_CBC, &blowfish_cbc_info }, +#endif +#if defined(POLARSSL_CIPHER_MODE_CFB) + { POLARSSL_CIPHER_BLOWFISH_CFB64, &blowfish_cfb64_info }, +#endif +#if defined(POLARSSL_CIPHER_MODE_CTR) + { POLARSSL_CIPHER_BLOWFISH_CTR, &blowfish_ctr_info }, +#endif +#endif /* POLARSSL_BLOWFISH_C */ + +#if defined(POLARSSL_CAMELLIA_C) + { POLARSSL_CIPHER_CAMELLIA_128_ECB, &camellia_128_ecb_info }, + { POLARSSL_CIPHER_CAMELLIA_192_ECB, &camellia_192_ecb_info }, + { POLARSSL_CIPHER_CAMELLIA_256_ECB, &camellia_256_ecb_info }, +#if defined(POLARSSL_CIPHER_MODE_CBC) + { POLARSSL_CIPHER_CAMELLIA_128_CBC, &camellia_128_cbc_info }, + { POLARSSL_CIPHER_CAMELLIA_192_CBC, &camellia_192_cbc_info }, + { POLARSSL_CIPHER_CAMELLIA_256_CBC, &camellia_256_cbc_info }, +#endif +#if defined(POLARSSL_CIPHER_MODE_CFB) + { POLARSSL_CIPHER_CAMELLIA_128_CFB128, &camellia_128_cfb128_info }, + { POLARSSL_CIPHER_CAMELLIA_192_CFB128, &camellia_192_cfb128_info }, + { POLARSSL_CIPHER_CAMELLIA_256_CFB128, &camellia_256_cfb128_info }, +#endif +#if defined(POLARSSL_CIPHER_MODE_CTR) + { POLARSSL_CIPHER_CAMELLIA_128_CTR, &camellia_128_ctr_info }, + { POLARSSL_CIPHER_CAMELLIA_192_CTR, &camellia_192_ctr_info }, + { POLARSSL_CIPHER_CAMELLIA_256_CTR, &camellia_256_ctr_info }, +#endif +#if defined(POLARSSL_GCM_C) + { POLARSSL_CIPHER_CAMELLIA_128_GCM, &camellia_128_gcm_info }, + { POLARSSL_CIPHER_CAMELLIA_192_GCM, &camellia_192_gcm_info }, + { POLARSSL_CIPHER_CAMELLIA_256_GCM, &camellia_256_gcm_info }, +#endif +#if defined(POLARSSL_CCM_C) + { POLARSSL_CIPHER_CAMELLIA_128_CCM, &camellia_128_ccm_info }, + { POLARSSL_CIPHER_CAMELLIA_192_CCM, &camellia_192_ccm_info }, + { POLARSSL_CIPHER_CAMELLIA_256_CCM, &camellia_256_ccm_info }, +#endif +#endif /* POLARSSL_CAMELLIA_C */ + +#if defined(POLARSSL_DES_C) + { POLARSSL_CIPHER_DES_ECB, &des_ecb_info }, + { POLARSSL_CIPHER_DES_EDE_ECB, &des_ede_ecb_info }, + { POLARSSL_CIPHER_DES_EDE3_ECB, &des_ede3_ecb_info }, +#if defined(POLARSSL_CIPHER_MODE_CBC) + { POLARSSL_CIPHER_DES_CBC, &des_cbc_info }, + { POLARSSL_CIPHER_DES_EDE_CBC, &des_ede_cbc_info }, + { POLARSSL_CIPHER_DES_EDE3_CBC, &des_ede3_cbc_info }, +#endif +#endif /* POLARSSL_DES_C */ + +#if defined(POLARSSL_CIPHER_NULL_CIPHER) + { POLARSSL_CIPHER_NULL, &null_cipher_info }, +#endif /* POLARSSL_CIPHER_NULL_CIPHER */ + + { (cipher_type_t)0, NULL } +}; + +#define NUM_CIPHERS sizeof cipher_definitions / sizeof cipher_definitions[0] +int supported_ciphers[NUM_CIPHERS]; + +#endif /* POLARSSL_CIPHER_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/ctr_drbg.c b/component/common/network/ssl/polarssl-1.3.8/library/ctr_drbg.c new file mode 100644 index 0000000..96ee4f1 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/ctr_drbg.c @@ -0,0 +1,549 @@ +/* + * CTR_DRBG implementation based on AES-256 (NIST SP 800-90) + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * The NIST SP 800-90 DRBGs are described in the following publucation. + * + * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_CTR_DRBG_C) + +#include "polarssl/ctr_drbg.h" + +#if defined(POLARSSL_FS_IO) +#include +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#define polarssl_printf printf +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * Non-public function wrapped by ctr_crbg_init(). Necessary to allow NIST + * tests to succeed (which require known length fixed entropy) + */ +int ctr_drbg_init_entropy_len( + ctr_drbg_context *ctx, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len, + size_t entropy_len ) +{ + int ret; + unsigned char key[CTR_DRBG_KEYSIZE]; + + memset( ctx, 0, sizeof(ctr_drbg_context) ); + memset( key, 0, CTR_DRBG_KEYSIZE ); + + aes_init( &ctx->aes_ctx ); + + ctx->f_entropy = f_entropy; + ctx->p_entropy = p_entropy; + + ctx->entropy_len = entropy_len; + ctx->reseed_interval = CTR_DRBG_RESEED_INTERVAL; + + /* + * Initialize with an empty key + */ + aes_setkey_enc( &ctx->aes_ctx, key, CTR_DRBG_KEYBITS ); + + if( ( ret = ctr_drbg_reseed( ctx, custom, len ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +int ctr_drbg_init( ctr_drbg_context *ctx, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len ) +{ + return( ctr_drbg_init_entropy_len( ctx, f_entropy, p_entropy, custom, len, + CTR_DRBG_ENTROPY_LEN ) ); +} + +void ctr_drbg_free( ctr_drbg_context *ctx ) +{ + if( ctx == NULL ) + return; + + aes_free( &ctx->aes_ctx ); + polarssl_zeroize( ctx, sizeof( ctr_drbg_context ) ); +} + +void ctr_drbg_set_prediction_resistance( ctr_drbg_context *ctx, int resistance ) +{ + ctx->prediction_resistance = resistance; +} + +void ctr_drbg_set_entropy_len( ctr_drbg_context *ctx, size_t len ) +{ + ctx->entropy_len = len; +} + +void ctr_drbg_set_reseed_interval( ctr_drbg_context *ctx, int interval ) +{ + ctx->reseed_interval = interval; +} + +static int block_cipher_df( unsigned char *output, + const unsigned char *data, size_t data_len ) +{ + unsigned char buf[CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16]; + unsigned char tmp[CTR_DRBG_SEEDLEN]; + unsigned char key[CTR_DRBG_KEYSIZE]; + unsigned char chain[CTR_DRBG_BLOCKSIZE]; + unsigned char *p, *iv; + aes_context aes_ctx; + + int i, j; + size_t buf_len, use_len; + + memset( buf, 0, CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16 ); + aes_init( &aes_ctx ); + + /* + * Construct IV (16 bytes) and S in buffer + * IV = Counter (in 32-bits) padded to 16 with zeroes + * S = Length input string (in 32-bits) || Length of output (in 32-bits) || + * data || 0x80 + * (Total is padded to a multiple of 16-bytes with zeroes) + */ + p = buf + CTR_DRBG_BLOCKSIZE; + *p++ = ( data_len >> 24 ) & 0xff; + *p++ = ( data_len >> 16 ) & 0xff; + *p++ = ( data_len >> 8 ) & 0xff; + *p++ = ( data_len ) & 0xff; + p += 3; + *p++ = CTR_DRBG_SEEDLEN; + memcpy( p, data, data_len ); + p[data_len] = 0x80; + + buf_len = CTR_DRBG_BLOCKSIZE + 8 + data_len + 1; + + for( i = 0; i < CTR_DRBG_KEYSIZE; i++ ) + key[i] = i; + + aes_setkey_enc( &aes_ctx, key, CTR_DRBG_KEYBITS ); + + /* + * Reduce data to POLARSSL_CTR_DRBG_SEEDLEN bytes of data + */ + for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE ) + { + p = buf; + memset( chain, 0, CTR_DRBG_BLOCKSIZE ); + use_len = buf_len; + + while( use_len > 0 ) + { + for( i = 0; i < CTR_DRBG_BLOCKSIZE; i++ ) + chain[i] ^= p[i]; + p += CTR_DRBG_BLOCKSIZE; + use_len -= ( use_len >= CTR_DRBG_BLOCKSIZE ) ? + CTR_DRBG_BLOCKSIZE : use_len; + + aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, chain, chain ); + } + + memcpy( tmp + j, chain, CTR_DRBG_BLOCKSIZE ); + + /* + * Update IV + */ + buf[3]++; + } + + /* + * Do final encryption with reduced data + */ + aes_setkey_enc( &aes_ctx, tmp, CTR_DRBG_KEYBITS ); + iv = tmp + CTR_DRBG_KEYSIZE; + p = output; + + for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE ) + { + aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, iv, iv ); + memcpy( p, iv, CTR_DRBG_BLOCKSIZE ); + p += CTR_DRBG_BLOCKSIZE; + } + + aes_free( &aes_ctx ); + + return( 0 ); +} + +static int ctr_drbg_update_internal( ctr_drbg_context *ctx, + const unsigned char data[CTR_DRBG_SEEDLEN] ) +{ + unsigned char tmp[CTR_DRBG_SEEDLEN]; + unsigned char *p = tmp; + int i, j; + + memset( tmp, 0, CTR_DRBG_SEEDLEN ); + + for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE ) + { + /* + * Increase counter + */ + for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- ) + if( ++ctx->counter[i - 1] != 0 ) + break; + + /* + * Crypt counter block + */ + aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, p ); + + p += CTR_DRBG_BLOCKSIZE; + } + + for( i = 0; i < CTR_DRBG_SEEDLEN; i++ ) + tmp[i] ^= data[i]; + + /* + * Update key and counter + */ + aes_setkey_enc( &ctx->aes_ctx, tmp, CTR_DRBG_KEYBITS ); + memcpy( ctx->counter, tmp + CTR_DRBG_KEYSIZE, CTR_DRBG_BLOCKSIZE ); + + return( 0 ); +} + +void ctr_drbg_update( ctr_drbg_context *ctx, + const unsigned char *additional, size_t add_len ) +{ + unsigned char add_input[CTR_DRBG_SEEDLEN]; + + if( add_len > 0 ) + { + block_cipher_df( add_input, additional, add_len ); + ctr_drbg_update_internal( ctx, add_input ); + } +} + +int ctr_drbg_reseed( ctr_drbg_context *ctx, + const unsigned char *additional, size_t len ) +{ + unsigned char seed[CTR_DRBG_MAX_SEED_INPUT]; + size_t seedlen = 0; + + if( ctx->entropy_len + len > CTR_DRBG_MAX_SEED_INPUT ) + return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG ); + + memset( seed, 0, CTR_DRBG_MAX_SEED_INPUT ); + + /* + * Gather entropy_len bytes of entropy to seed state + */ + if( 0 != ctx->f_entropy( ctx->p_entropy, seed, + ctx->entropy_len ) ) + { + return( POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED ); + } + + seedlen += ctx->entropy_len; + + /* + * Add additional data + */ + if( additional && len ) + { + memcpy( seed + seedlen, additional, len ); + seedlen += len; + } + + /* + * Reduce to 384 bits + */ + block_cipher_df( seed, seed, seedlen ); + + /* + * Update state + */ + ctr_drbg_update_internal( ctx, seed ); + ctx->reseed_counter = 1; + + return( 0 ); +} + +int ctr_drbg_random_with_add( void *p_rng, + unsigned char *output, size_t output_len, + const unsigned char *additional, size_t add_len ) +{ + int ret = 0; + ctr_drbg_context *ctx = (ctr_drbg_context *) p_rng; + unsigned char add_input[CTR_DRBG_SEEDLEN]; + unsigned char *p = output; + unsigned char tmp[CTR_DRBG_BLOCKSIZE]; + int i; + size_t use_len; + + if( output_len > CTR_DRBG_MAX_REQUEST ) + return( POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG ); + + if( add_len > CTR_DRBG_MAX_INPUT ) + return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG ); + + memset( add_input, 0, CTR_DRBG_SEEDLEN ); + + if( ctx->reseed_counter > ctx->reseed_interval || + ctx->prediction_resistance ) + { + if( ( ret = ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 ) + return( ret ); + + add_len = 0; + } + + if( add_len > 0 ) + { + block_cipher_df( add_input, additional, add_len ); + ctr_drbg_update_internal( ctx, add_input ); + } + + while( output_len > 0 ) + { + /* + * Increase counter + */ + for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- ) + if( ++ctx->counter[i - 1] != 0 ) + break; + + /* + * Crypt counter block + */ + aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, tmp ); + + use_len = ( output_len > CTR_DRBG_BLOCKSIZE ) ? CTR_DRBG_BLOCKSIZE : + output_len; + /* + * Copy random block to destination + */ + memcpy( p, tmp, use_len ); + p += use_len; + output_len -= use_len; + } + + ctr_drbg_update_internal( ctx, add_input ); + + ctx->reseed_counter++; + + return( 0 ); +} + +int ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len ) +{ + return ctr_drbg_random_with_add( p_rng, output, output_len, NULL, 0 ); +} + +#if defined(POLARSSL_FS_IO) +int ctr_drbg_write_seed_file( ctr_drbg_context *ctx, const char *path ) +{ + int ret = POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR; + FILE *f; + unsigned char buf[ CTR_DRBG_MAX_INPUT ]; + + if( ( f = fopen( path, "wb" ) ) == NULL ) + return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR ); + + if( ( ret = ctr_drbg_random( ctx, buf, CTR_DRBG_MAX_INPUT ) ) != 0 ) + goto exit; + + if( fwrite( buf, 1, CTR_DRBG_MAX_INPUT, f ) != CTR_DRBG_MAX_INPUT ) + { + ret = POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR; + goto exit; + } + + ret = 0; + +exit: + fclose( f ); + return( ret ); +} + +int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path ) +{ + FILE *f; + size_t n; + unsigned char buf[ CTR_DRBG_MAX_INPUT ]; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR ); + + fseek( f, 0, SEEK_END ); + n = (size_t) ftell( f ); + fseek( f, 0, SEEK_SET ); + + if( n > CTR_DRBG_MAX_INPUT ) + { + fclose( f ); + return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG ); + } + + if( fread( buf, 1, n, f ) != n ) + { + fclose( f ); + return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR ); + } + + fclose( f ); + + ctr_drbg_update( ctx, buf, n ); + + return( ctr_drbg_write_seed_file( ctx, path ) ); +} +#endif /* POLARSSL_FS_IO */ + +#if defined(POLARSSL_SELF_TEST) + +#include + +static unsigned char entropy_source_pr[96] = + { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16, + 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02, + 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b, + 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb, + 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9, + 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95, + 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63, + 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3, + 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31, + 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4, + 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56, + 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 }; + +static unsigned char entropy_source_nopr[64] = + { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14, + 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe, + 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d, + 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20, + 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9, + 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46, + 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e, + 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e }; + +static const unsigned char nonce_pers_pr[16] = + { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2, + 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c }; + +static const unsigned char nonce_pers_nopr[16] = + { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5, + 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f }; + +static const unsigned char result_pr[16] = + { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f, + 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 }; + +static const unsigned char result_nopr[16] = + { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88, + 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f }; + +static size_t test_offset; +static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf, + size_t len ) +{ + const unsigned char *p = data; + memcpy( buf, p + test_offset, len ); + test_offset += len; + return( 0 ); +} + +#define CHK( c ) if( (c) != 0 ) \ + { \ + if( verbose != 0 ) \ + polarssl_printf( "failed\n" ); \ + return( 1 ); \ + } + +/* + * Checkup routine + */ +int ctr_drbg_self_test( int verbose ) +{ + ctr_drbg_context ctx; + unsigned char buf[16]; + + /* + * Based on a NIST CTR_DRBG test vector (PR = True) + */ + if( verbose != 0 ) + polarssl_printf( " CTR_DRBG (PR = TRUE) : " ); + + test_offset = 0; + CHK( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy, + entropy_source_pr, nonce_pers_pr, 16, 32 ) ); + ctr_drbg_set_prediction_resistance( &ctx, CTR_DRBG_PR_ON ); + CHK( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) ); + CHK( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) ); + CHK( memcmp( buf, result_pr, CTR_DRBG_BLOCKSIZE ) ); + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + + /* + * Based on a NIST CTR_DRBG test vector (PR = FALSE) + */ + if( verbose != 0 ) + polarssl_printf( " CTR_DRBG (PR = FALSE): " ); + + test_offset = 0; + CHK( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy, + entropy_source_nopr, nonce_pers_nopr, 16, 32 ) ); + CHK( ctr_drbg_random( &ctx, buf, 16 ) ); + CHK( ctr_drbg_reseed( &ctx, NULL, 0 ) ); + CHK( ctr_drbg_random( &ctx, buf, 16 ) ); + CHK( memcmp( buf, result_nopr, 16 ) ); + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + + if( verbose != 0 ) + polarssl_printf( "\n" ); + + return( 0 ); +} +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_CTR_DRBG_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/debug.c b/component/common/network/ssl/polarssl-1.3.8/library/debug.c new file mode 100644 index 0000000..a81f502 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/debug.c @@ -0,0 +1,351 @@ +/* + * Debugging routines + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_DEBUG_C) + +#include "polarssl/debug.h" + +#include +#include + +#if defined(EFIX64) || defined(EFI32) +#include +#endif + +#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32) +#if !defined snprintf +#define snprintf _snprintf +#endif + +#if !defined vsnprintf +#define vsnprintf _vsnprintf +#endif +#endif /* _MSC_VER */ + +static int debug_log_mode = POLARSSL_DEBUG_DFL_MODE; +static int debug_threshold = 0; + +void debug_set_log_mode( int log_mode ) +{ + debug_log_mode = log_mode; +} + +void debug_set_threshold( int threshold ) +{ + debug_threshold = threshold; +} + +char *debug_fmt( const char *format, ... ) +{ + va_list argp; + static char str[512]; + int maxlen = sizeof( str ) - 1; + + va_start( argp, format ); + vsnprintf( str, maxlen, format, argp ); + va_end( argp ); + + str[maxlen] = '\0'; + return( str ); +} + +void debug_print_msg( const ssl_context *ssl, int level, + const char *file, int line, const char *text ) +{ + char str[512]; + int maxlen = sizeof( str ) - 1; + + if( ssl->f_dbg == NULL || level > debug_threshold ) + return; + + if( debug_log_mode == POLARSSL_DEBUG_LOG_RAW ) + { + ssl->f_dbg( ssl->p_dbg, level, text ); + return; + } + + snprintf( str, maxlen, "%s(%04d): %s\n", file, line, text ); + str[maxlen] = '\0'; + ssl->f_dbg( ssl->p_dbg, level, str ); +} + +void debug_print_ret( const ssl_context *ssl, int level, + const char *file, int line, + const char *text, int ret ) +{ + char str[512]; + int maxlen = sizeof( str ) - 1; + size_t idx = 0; + + if( ssl->f_dbg == NULL || level > debug_threshold ) + return; + + if( debug_log_mode == POLARSSL_DEBUG_LOG_FULL ) + idx = snprintf( str, maxlen, "%s(%04d): ", file, line ); + + snprintf( str + idx, maxlen - idx, "%s() returned %d (-0x%04x)\n", + text, ret, -ret ); + + str[maxlen] = '\0'; + ssl->f_dbg( ssl->p_dbg, level, str ); +} + +void debug_print_buf( const ssl_context *ssl, int level, + const char *file, int line, const char *text, + unsigned char *buf, size_t len ) +{ + char str[512]; + size_t i, maxlen = sizeof( str ) - 1, idx = 0; + + if( ssl->f_dbg == NULL || level > debug_threshold ) + return; + + if( debug_log_mode == POLARSSL_DEBUG_LOG_FULL ) + idx = snprintf( str, maxlen, "%s(%04d): ", file, line ); + + snprintf( str + idx, maxlen - idx, "dumping '%s' (%u bytes)\n", + text, (unsigned int) len ); + + str[maxlen] = '\0'; + ssl->f_dbg( ssl->p_dbg, level, str ); + + idx = 0; + for( i = 0; i < len; i++ ) + { + if( i >= 4096 ) + break; + + if( i % 16 == 0 ) + { + if( i > 0 ) + { + snprintf( str + idx, maxlen - idx, "\n" ); + ssl->f_dbg( ssl->p_dbg, level, str ); + idx = 0; + } + + if( debug_log_mode == POLARSSL_DEBUG_LOG_FULL ) + idx = snprintf( str, maxlen, "%s(%04d): ", file, line ); + + idx += snprintf( str + idx, maxlen - idx, "%04x: ", + (unsigned int) i ); + + } + + idx += snprintf( str + idx, maxlen - idx, " %02x", + (unsigned int) buf[i] ); + } + + if( len > 0 ) + { + snprintf( str + idx, maxlen - idx, "\n" ); + ssl->f_dbg( ssl->p_dbg, level, str ); + } +} + +#if defined(POLARSSL_ECP_C) +void debug_print_ecp( const ssl_context *ssl, int level, + const char *file, int line, + const char *text, const ecp_point *X ) +{ + char str[512]; + int maxlen = sizeof( str ) - 1; + + if( ssl->f_dbg == NULL || level > debug_threshold ) + return; + + snprintf( str, maxlen, "%s(X)", text ); + str[maxlen] = '\0'; + debug_print_mpi( ssl, level, file, line, str, &X->X ); + + snprintf( str, maxlen, "%s(Y)", text ); + str[maxlen] = '\0'; + debug_print_mpi( ssl, level, file, line, str, &X->Y ); +} +#endif /* POLARSSL_ECP_C */ + +#if defined(POLARSSL_BIGNUM_C) +void debug_print_mpi( const ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mpi *X ) +{ + char str[512]; + int j, k, maxlen = sizeof( str ) - 1, zeros = 1; + size_t i, n, idx = 0; + + if( ssl->f_dbg == NULL || X == NULL || level > debug_threshold ) + return; + + for( n = X->n - 1; n > 0; n-- ) + if( X->p[n] != 0 ) + break; + + for( j = ( sizeof(t_uint) << 3 ) - 1; j >= 0; j-- ) + if( ( ( X->p[n] >> j ) & 1 ) != 0 ) + break; + + if( debug_log_mode == POLARSSL_DEBUG_LOG_FULL ) + idx = snprintf( str, maxlen, "%s(%04d): ", file, line ); + + snprintf( str + idx, maxlen - idx, "value of '%s' (%d bits) is:\n", + text, (int) ( ( n * ( sizeof(t_uint) << 3 ) ) + j + 1 ) ); + + str[maxlen] = '\0'; + ssl->f_dbg( ssl->p_dbg, level, str ); + + idx = 0; + for( i = n + 1, j = 0; i > 0; i-- ) + { + if( zeros && X->p[i - 1] == 0 ) + continue; + + for( k = sizeof( t_uint ) - 1; k >= 0; k-- ) + { + if( zeros && ( ( X->p[i - 1] >> ( k << 3 ) ) & 0xFF ) == 0 ) + continue; + else + zeros = 0; + + if( j % 16 == 0 ) + { + if( j > 0 ) + { + snprintf( str + idx, maxlen - idx, "\n" ); + ssl->f_dbg( ssl->p_dbg, level, str ); + idx = 0; + } + + if( debug_log_mode == POLARSSL_DEBUG_LOG_FULL ) + idx = snprintf( str, maxlen, "%s(%04d): ", file, line ); + } + + idx += snprintf( str + idx, maxlen - idx, " %02x", (unsigned int) + ( X->p[i - 1] >> ( k << 3 ) ) & 0xFF ); + + j++; + } + + } + + if( zeros == 1 ) + { + if( debug_log_mode == POLARSSL_DEBUG_LOG_FULL ) + { + idx = snprintf( str, maxlen, "%s(%04d): ", file, line ); + + } + idx += snprintf( str + idx, maxlen - idx, " 00" ); + } + + snprintf( str + idx, maxlen - idx, "\n" ); + ssl->f_dbg( ssl->p_dbg, level, str ); +} +#endif /* POLARSSL_BIGNUM_C */ + +#if defined(POLARSSL_X509_CRT_PARSE_C) +static void debug_print_pk( const ssl_context *ssl, int level, + const char *file, int line, + const char *text, const pk_context *pk ) +{ + size_t i; + pk_debug_item items[POLARSSL_PK_DEBUG_MAX_ITEMS]; + char name[16]; + + memset( items, 0, sizeof( items ) ); + + if( pk_debug( pk, items ) != 0 ) + { + debug_print_msg( ssl, level, file, line, "invalid PK context" ); + return; + } + + for( i = 0; i < POLARSSL_PK_DEBUG_MAX_ITEMS; i++ ) + { + if( items[i].type == POLARSSL_PK_DEBUG_NONE ) + return; + + snprintf( name, sizeof( name ), "%s%s", text, items[i].name ); + name[sizeof( name ) - 1] = '\0'; + + if( items[i].type == POLARSSL_PK_DEBUG_MPI ) + debug_print_mpi( ssl, level, file, line, name, items[i].value ); + else +#if defined(POLARSSL_ECP_C) + if( items[i].type == POLARSSL_PK_DEBUG_ECP ) + debug_print_ecp( ssl, level, file, line, name, items[i].value ); + else +#endif + debug_print_msg( ssl, level, file, line, "should not happen" ); + } +} + +void debug_print_crt( const ssl_context *ssl, int level, + const char *file, int line, + const char *text, const x509_crt *crt ) +{ + char str[1024], prefix[64]; + int i = 0, maxlen = sizeof( prefix ) - 1, idx = 0; + + if( ssl->f_dbg == NULL || crt == NULL || level > debug_threshold ) + return; + + if( debug_log_mode == POLARSSL_DEBUG_LOG_FULL ) + { + snprintf( prefix, maxlen, "%s(%04d): ", file, line ); + prefix[maxlen] = '\0'; + } + else + prefix[0] = '\0'; + + maxlen = sizeof( str ) - 1; + + while( crt != NULL ) + { + char buf[1024]; + x509_crt_info( buf, sizeof( buf ) - 1, prefix, crt ); + + if( debug_log_mode == POLARSSL_DEBUG_LOG_FULL ) + idx = snprintf( str, maxlen, "%s(%04d): ", file, line ); + + snprintf( str + idx, maxlen - idx, "%s #%d:\n%s", + text, ++i, buf ); + + str[maxlen] = '\0'; + ssl->f_dbg( ssl->p_dbg, level, str ); + + debug_print_pk( ssl, level, file, line, "crt->", &crt->pk ); + + crt = crt->next; + } +} +#endif /* POLARSSL_X509_CRT_PARSE_C */ + +#endif /* POLARSSL_DEBUG_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/des.c b/component/common/network/ssl/polarssl-1.3.8/library/des.c new file mode 100644 index 0000000..bbd7095 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/des.c @@ -0,0 +1,1156 @@ +/* + * FIPS-46-3 compliant Triple-DES implementation + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * DES, on which TDES is based, was originally designed by Horst Feistel + * at IBM in 1974, and was adopted as a standard by NIST (formerly NBS). + * + * http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif +#ifdef RTL_HW_CRYPTO +#include +#endif +#if defined(POLARSSL_DES_C) + +#include "polarssl/des.h" + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#define polarssl_printf printf +#endif + +#if !defined(POLARSSL_DES_ALT) + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +/* + * Expanded DES S-boxes + */ +static const uint32_t SB1[64] = +{ + 0x01010400, 0x00000000, 0x00010000, 0x01010404, + 0x01010004, 0x00010404, 0x00000004, 0x00010000, + 0x00000400, 0x01010400, 0x01010404, 0x00000400, + 0x01000404, 0x01010004, 0x01000000, 0x00000004, + 0x00000404, 0x01000400, 0x01000400, 0x00010400, + 0x00010400, 0x01010000, 0x01010000, 0x01000404, + 0x00010004, 0x01000004, 0x01000004, 0x00010004, + 0x00000000, 0x00000404, 0x00010404, 0x01000000, + 0x00010000, 0x01010404, 0x00000004, 0x01010000, + 0x01010400, 0x01000000, 0x01000000, 0x00000400, + 0x01010004, 0x00010000, 0x00010400, 0x01000004, + 0x00000400, 0x00000004, 0x01000404, 0x00010404, + 0x01010404, 0x00010004, 0x01010000, 0x01000404, + 0x01000004, 0x00000404, 0x00010404, 0x01010400, + 0x00000404, 0x01000400, 0x01000400, 0x00000000, + 0x00010004, 0x00010400, 0x00000000, 0x01010004 +}; + +static const uint32_t SB2[64] = +{ + 0x80108020, 0x80008000, 0x00008000, 0x00108020, + 0x00100000, 0x00000020, 0x80100020, 0x80008020, + 0x80000020, 0x80108020, 0x80108000, 0x80000000, + 0x80008000, 0x00100000, 0x00000020, 0x80100020, + 0x00108000, 0x00100020, 0x80008020, 0x00000000, + 0x80000000, 0x00008000, 0x00108020, 0x80100000, + 0x00100020, 0x80000020, 0x00000000, 0x00108000, + 0x00008020, 0x80108000, 0x80100000, 0x00008020, + 0x00000000, 0x00108020, 0x80100020, 0x00100000, + 0x80008020, 0x80100000, 0x80108000, 0x00008000, + 0x80100000, 0x80008000, 0x00000020, 0x80108020, + 0x00108020, 0x00000020, 0x00008000, 0x80000000, + 0x00008020, 0x80108000, 0x00100000, 0x80000020, + 0x00100020, 0x80008020, 0x80000020, 0x00100020, + 0x00108000, 0x00000000, 0x80008000, 0x00008020, + 0x80000000, 0x80100020, 0x80108020, 0x00108000 +}; + +static const uint32_t SB3[64] = +{ + 0x00000208, 0x08020200, 0x00000000, 0x08020008, + 0x08000200, 0x00000000, 0x00020208, 0x08000200, + 0x00020008, 0x08000008, 0x08000008, 0x00020000, + 0x08020208, 0x00020008, 0x08020000, 0x00000208, + 0x08000000, 0x00000008, 0x08020200, 0x00000200, + 0x00020200, 0x08020000, 0x08020008, 0x00020208, + 0x08000208, 0x00020200, 0x00020000, 0x08000208, + 0x00000008, 0x08020208, 0x00000200, 0x08000000, + 0x08020200, 0x08000000, 0x00020008, 0x00000208, + 0x00020000, 0x08020200, 0x08000200, 0x00000000, + 0x00000200, 0x00020008, 0x08020208, 0x08000200, + 0x08000008, 0x00000200, 0x00000000, 0x08020008, + 0x08000208, 0x00020000, 0x08000000, 0x08020208, + 0x00000008, 0x00020208, 0x00020200, 0x08000008, + 0x08020000, 0x08000208, 0x00000208, 0x08020000, + 0x00020208, 0x00000008, 0x08020008, 0x00020200 +}; + +static const uint32_t SB4[64] = +{ + 0x00802001, 0x00002081, 0x00002081, 0x00000080, + 0x00802080, 0x00800081, 0x00800001, 0x00002001, + 0x00000000, 0x00802000, 0x00802000, 0x00802081, + 0x00000081, 0x00000000, 0x00800080, 0x00800001, + 0x00000001, 0x00002000, 0x00800000, 0x00802001, + 0x00000080, 0x00800000, 0x00002001, 0x00002080, + 0x00800081, 0x00000001, 0x00002080, 0x00800080, + 0x00002000, 0x00802080, 0x00802081, 0x00000081, + 0x00800080, 0x00800001, 0x00802000, 0x00802081, + 0x00000081, 0x00000000, 0x00000000, 0x00802000, + 0x00002080, 0x00800080, 0x00800081, 0x00000001, + 0x00802001, 0x00002081, 0x00002081, 0x00000080, + 0x00802081, 0x00000081, 0x00000001, 0x00002000, + 0x00800001, 0x00002001, 0x00802080, 0x00800081, + 0x00002001, 0x00002080, 0x00800000, 0x00802001, + 0x00000080, 0x00800000, 0x00002000, 0x00802080 +}; + +static const uint32_t SB5[64] = +{ + 0x00000100, 0x02080100, 0x02080000, 0x42000100, + 0x00080000, 0x00000100, 0x40000000, 0x02080000, + 0x40080100, 0x00080000, 0x02000100, 0x40080100, + 0x42000100, 0x42080000, 0x00080100, 0x40000000, + 0x02000000, 0x40080000, 0x40080000, 0x00000000, + 0x40000100, 0x42080100, 0x42080100, 0x02000100, + 0x42080000, 0x40000100, 0x00000000, 0x42000000, + 0x02080100, 0x02000000, 0x42000000, 0x00080100, + 0x00080000, 0x42000100, 0x00000100, 0x02000000, + 0x40000000, 0x02080000, 0x42000100, 0x40080100, + 0x02000100, 0x40000000, 0x42080000, 0x02080100, + 0x40080100, 0x00000100, 0x02000000, 0x42080000, + 0x42080100, 0x00080100, 0x42000000, 0x42080100, + 0x02080000, 0x00000000, 0x40080000, 0x42000000, + 0x00080100, 0x02000100, 0x40000100, 0x00080000, + 0x00000000, 0x40080000, 0x02080100, 0x40000100 +}; + +static const uint32_t SB6[64] = +{ + 0x20000010, 0x20400000, 0x00004000, 0x20404010, + 0x20400000, 0x00000010, 0x20404010, 0x00400000, + 0x20004000, 0x00404010, 0x00400000, 0x20000010, + 0x00400010, 0x20004000, 0x20000000, 0x00004010, + 0x00000000, 0x00400010, 0x20004010, 0x00004000, + 0x00404000, 0x20004010, 0x00000010, 0x20400010, + 0x20400010, 0x00000000, 0x00404010, 0x20404000, + 0x00004010, 0x00404000, 0x20404000, 0x20000000, + 0x20004000, 0x00000010, 0x20400010, 0x00404000, + 0x20404010, 0x00400000, 0x00004010, 0x20000010, + 0x00400000, 0x20004000, 0x20000000, 0x00004010, + 0x20000010, 0x20404010, 0x00404000, 0x20400000, + 0x00404010, 0x20404000, 0x00000000, 0x20400010, + 0x00000010, 0x00004000, 0x20400000, 0x00404010, + 0x00004000, 0x00400010, 0x20004010, 0x00000000, + 0x20404000, 0x20000000, 0x00400010, 0x20004010 +}; + +static const uint32_t SB7[64] = +{ + 0x00200000, 0x04200002, 0x04000802, 0x00000000, + 0x00000800, 0x04000802, 0x00200802, 0x04200800, + 0x04200802, 0x00200000, 0x00000000, 0x04000002, + 0x00000002, 0x04000000, 0x04200002, 0x00000802, + 0x04000800, 0x00200802, 0x00200002, 0x04000800, + 0x04000002, 0x04200000, 0x04200800, 0x00200002, + 0x04200000, 0x00000800, 0x00000802, 0x04200802, + 0x00200800, 0x00000002, 0x04000000, 0x00200800, + 0x04000000, 0x00200800, 0x00200000, 0x04000802, + 0x04000802, 0x04200002, 0x04200002, 0x00000002, + 0x00200002, 0x04000000, 0x04000800, 0x00200000, + 0x04200800, 0x00000802, 0x00200802, 0x04200800, + 0x00000802, 0x04000002, 0x04200802, 0x04200000, + 0x00200800, 0x00000000, 0x00000002, 0x04200802, + 0x00000000, 0x00200802, 0x04200000, 0x00000800, + 0x04000002, 0x04000800, 0x00000800, 0x00200002 +}; + +static const uint32_t SB8[64] = +{ + 0x10001040, 0x00001000, 0x00040000, 0x10041040, + 0x10000000, 0x10001040, 0x00000040, 0x10000000, + 0x00040040, 0x10040000, 0x10041040, 0x00041000, + 0x10041000, 0x00041040, 0x00001000, 0x00000040, + 0x10040000, 0x10000040, 0x10001000, 0x00001040, + 0x00041000, 0x00040040, 0x10040040, 0x10041000, + 0x00001040, 0x00000000, 0x00000000, 0x10040040, + 0x10000040, 0x10001000, 0x00041040, 0x00040000, + 0x00041040, 0x00040000, 0x10041000, 0x00001000, + 0x00000040, 0x10040040, 0x00001000, 0x00041040, + 0x10001000, 0x00000040, 0x10000040, 0x10040000, + 0x10040040, 0x10000000, 0x00040000, 0x10001040, + 0x00000000, 0x10041040, 0x00040040, 0x10000040, + 0x10040000, 0x10001000, 0x10001040, 0x00000000, + 0x10041040, 0x00041000, 0x00041000, 0x00001040, + 0x00001040, 0x00040040, 0x10000000, 0x10041000 +}; + +/* + * PC1: left and right halves bit-swap + */ +static const uint32_t LHs[16] = +{ + 0x00000000, 0x00000001, 0x00000100, 0x00000101, + 0x00010000, 0x00010001, 0x00010100, 0x00010101, + 0x01000000, 0x01000001, 0x01000100, 0x01000101, + 0x01010000, 0x01010001, 0x01010100, 0x01010101 +}; + +static const uint32_t RHs[16] = +{ + 0x00000000, 0x01000000, 0x00010000, 0x01010000, + 0x00000100, 0x01000100, 0x00010100, 0x01010100, + 0x00000001, 0x01000001, 0x00010001, 0x01010001, + 0x00000101, 0x01000101, 0x00010101, 0x01010101, +}; + +/* + * Initial Permutation macro + */ +#define DES_IP(X,Y) \ +{ \ + T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \ + T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \ + T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \ + T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \ + Y = ((Y << 1) | (Y >> 31)) & 0xFFFFFFFF; \ + T = (X ^ Y) & 0xAAAAAAAA; Y ^= T; X ^= T; \ + X = ((X << 1) | (X >> 31)) & 0xFFFFFFFF; \ +} + +/* + * Final Permutation macro + */ +#define DES_FP(X,Y) \ +{ \ + X = ((X << 31) | (X >> 1)) & 0xFFFFFFFF; \ + T = (X ^ Y) & 0xAAAAAAAA; X ^= T; Y ^= T; \ + Y = ((Y << 31) | (Y >> 1)) & 0xFFFFFFFF; \ + T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \ + T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \ + T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \ + T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \ +} + +/* + * DES round macro + */ +#define DES_ROUND(X,Y) \ +{ \ + T = *SK++ ^ X; \ + Y ^= SB8[ (T ) & 0x3F ] ^ \ + SB6[ (T >> 8) & 0x3F ] ^ \ + SB4[ (T >> 16) & 0x3F ] ^ \ + SB2[ (T >> 24) & 0x3F ]; \ + \ + T = *SK++ ^ ((X << 28) | (X >> 4)); \ + Y ^= SB7[ (T ) & 0x3F ] ^ \ + SB5[ (T >> 8) & 0x3F ] ^ \ + SB3[ (T >> 16) & 0x3F ] ^ \ + SB1[ (T >> 24) & 0x3F ]; \ +} + +#define SWAP(a,b) { uint32_t t = a; a = b; b = t; t = 0; } + +void des_init( des_context *ctx ) +{ + memset( ctx, 0, sizeof( des_context ) ); +} + +void des_free( des_context *ctx ) +{ + if( ctx == NULL ) + return; + + polarssl_zeroize( ctx, sizeof( des_context ) ); +} + +void des3_init( des3_context *ctx ) +{ + memset( ctx, 0, sizeof( des3_context ) ); +} + +void des3_free( des3_context *ctx ) +{ + if( ctx == NULL ) + return; + + polarssl_zeroize( ctx, sizeof( des3_context ) ); +} + +static const unsigned char odd_parity_table[128] = { 1, 2, 4, 7, 8, + 11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31, 32, 35, 37, 38, 41, 42, 44, + 47, 49, 50, 52, 55, 56, 59, 61, 62, 64, 67, 69, 70, 73, 74, 76, 79, 81, + 82, 84, 87, 88, 91, 93, 94, 97, 98, 100, 103, 104, 107, 109, 110, 112, + 115, 117, 118, 121, 122, 124, 127, 128, 131, 133, 134, 137, 138, 140, + 143, 145, 146, 148, 151, 152, 155, 157, 158, 161, 162, 164, 167, 168, + 171, 173, 174, 176, 179, 181, 182, 185, 186, 188, 191, 193, 194, 196, + 199, 200, 203, 205, 206, 208, 211, 213, 214, 217, 218, 220, 223, 224, + 227, 229, 230, 233, 234, 236, 239, 241, 242, 244, 247, 248, 251, 253, + 254 }; + +void des_key_set_parity( unsigned char key[DES_KEY_SIZE] ) +{ + int i; + + for( i = 0; i < DES_KEY_SIZE; i++ ) + key[i] = odd_parity_table[key[i] / 2]; +} + +/* + * Check the given key's parity, returns 1 on failure, 0 on SUCCESS + */ +int des_key_check_key_parity( const unsigned char key[DES_KEY_SIZE] ) +{ + int i; + + for( i = 0; i < DES_KEY_SIZE; i++ ) + if( key[i] != odd_parity_table[key[i] / 2] ) + return( 1 ); + + return( 0 ); +} + +/* + * Table of weak and semi-weak keys + * + * Source: http://en.wikipedia.org/wiki/Weak_key + * + * Weak: + * Alternating ones + zeros (0x0101010101010101) + * Alternating 'F' + 'E' (0xFEFEFEFEFEFEFEFE) + * '0xE0E0E0E0F1F1F1F1' + * '0x1F1F1F1F0E0E0E0E' + * + * Semi-weak: + * 0x011F011F010E010E and 0x1F011F010E010E01 + * 0x01E001E001F101F1 and 0xE001E001F101F101 + * 0x01FE01FE01FE01FE and 0xFE01FE01FE01FE01 + * 0x1FE01FE00EF10EF1 and 0xE01FE01FF10EF10E + * 0x1FFE1FFE0EFE0EFE and 0xFE1FFE1FFE0EFE0E + * 0xE0FEE0FEF1FEF1FE and 0xFEE0FEE0FEF1FEF1 + * + */ + +#define WEAK_KEY_COUNT 16 + +static const unsigned char weak_key_table[WEAK_KEY_COUNT][DES_KEY_SIZE] = +{ + { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE }, + { 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E }, + { 0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1 }, + + { 0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E }, + { 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01 }, + { 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1 }, + { 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01 }, + { 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE }, + { 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01 }, + { 0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1 }, + { 0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E }, + { 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE }, + { 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E }, + { 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE }, + { 0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1 } +}; + +int des_key_check_weak( const unsigned char key[DES_KEY_SIZE] ) +{ + int i; + + for( i = 0; i < WEAK_KEY_COUNT; i++ ) + if( memcmp( weak_key_table[i], key, DES_KEY_SIZE) == 0 ) + return( 1 ); + + return( 0 ); +} + +static void des_setkey( uint32_t SK[32], const unsigned char key[DES_KEY_SIZE] ) +{ + int i; + uint32_t X, Y, T; + + GET_UINT32_BE( X, key, 0 ); + GET_UINT32_BE( Y, key, 4 ); + + /* + * Permuted Choice 1 + */ + T = ((Y >> 4) ^ X) & 0x0F0F0F0F; X ^= T; Y ^= (T << 4); + T = ((Y ) ^ X) & 0x10101010; X ^= T; Y ^= (T ); + + X = (LHs[ (X ) & 0xF] << 3) | (LHs[ (X >> 8) & 0xF ] << 2) + | (LHs[ (X >> 16) & 0xF] << 1) | (LHs[ (X >> 24) & 0xF ] ) + | (LHs[ (X >> 5) & 0xF] << 7) | (LHs[ (X >> 13) & 0xF ] << 6) + | (LHs[ (X >> 21) & 0xF] << 5) | (LHs[ (X >> 29) & 0xF ] << 4); + + Y = (RHs[ (Y >> 1) & 0xF] << 3) | (RHs[ (Y >> 9) & 0xF ] << 2) + | (RHs[ (Y >> 17) & 0xF] << 1) | (RHs[ (Y >> 25) & 0xF ] ) + | (RHs[ (Y >> 4) & 0xF] << 7) | (RHs[ (Y >> 12) & 0xF ] << 6) + | (RHs[ (Y >> 20) & 0xF] << 5) | (RHs[ (Y >> 28) & 0xF ] << 4); + + X &= 0x0FFFFFFF; + Y &= 0x0FFFFFFF; + + /* + * calculate subkeys + */ + for( i = 0; i < 16; i++ ) + { + if( i < 2 || i == 8 || i == 15 ) + { + X = ((X << 1) | (X >> 27)) & 0x0FFFFFFF; + Y = ((Y << 1) | (Y >> 27)) & 0x0FFFFFFF; + } + else + { + X = ((X << 2) | (X >> 26)) & 0x0FFFFFFF; + Y = ((Y << 2) | (Y >> 26)) & 0x0FFFFFFF; + } + + *SK++ = ((X << 4) & 0x24000000) | ((X << 28) & 0x10000000) + | ((X << 14) & 0x08000000) | ((X << 18) & 0x02080000) + | ((X << 6) & 0x01000000) | ((X << 9) & 0x00200000) + | ((X >> 1) & 0x00100000) | ((X << 10) & 0x00040000) + | ((X << 2) & 0x00020000) | ((X >> 10) & 0x00010000) + | ((Y >> 13) & 0x00002000) | ((Y >> 4) & 0x00001000) + | ((Y << 6) & 0x00000800) | ((Y >> 1) & 0x00000400) + | ((Y >> 14) & 0x00000200) | ((Y ) & 0x00000100) + | ((Y >> 5) & 0x00000020) | ((Y >> 10) & 0x00000010) + | ((Y >> 3) & 0x00000008) | ((Y >> 18) & 0x00000004) + | ((Y >> 26) & 0x00000002) | ((Y >> 24) & 0x00000001); + + *SK++ = ((X << 15) & 0x20000000) | ((X << 17) & 0x10000000) + | ((X << 10) & 0x08000000) | ((X << 22) & 0x04000000) + | ((X >> 2) & 0x02000000) | ((X << 1) & 0x01000000) + | ((X << 16) & 0x00200000) | ((X << 11) & 0x00100000) + | ((X << 3) & 0x00080000) | ((X >> 6) & 0x00040000) + | ((X << 15) & 0x00020000) | ((X >> 4) & 0x00010000) + | ((Y >> 2) & 0x00002000) | ((Y << 8) & 0x00001000) + | ((Y >> 14) & 0x00000808) | ((Y >> 9) & 0x00000400) + | ((Y ) & 0x00000200) | ((Y << 7) & 0x00000100) + | ((Y >> 7) & 0x00000020) | ((Y >> 3) & 0x00000011) + | ((Y << 2) & 0x00000004) | ((Y >> 21) & 0x00000002); + } +} + +/* + * DES key schedule (56-bit, encryption) + */ +int des_setkey_enc( des_context *ctx, const unsigned char key[DES_KEY_SIZE] ) +{ +#ifdef RTL_HW_CRYPTO + memcpy(ctx->enc_key, key, DES_KEY_SIZE); +#endif + des_setkey( ctx->sk, key ); + return( 0 ); +} + +/* + * DES key schedule (56-bit, decryption) + */ +int des_setkey_dec( des_context *ctx, const unsigned char key[DES_KEY_SIZE] ) +{ + int i; +#ifdef RTL_HW_CRYPTO + memcpy(ctx->dec_key, key, DES_KEY_SIZE); +#endif + des_setkey( ctx->sk, key ); + + for( i = 0; i < 16; i += 2 ) + { + SWAP( ctx->sk[i ], ctx->sk[30 - i] ); + SWAP( ctx->sk[i + 1], ctx->sk[31 - i] ); + } + + return( 0 ); +} + +static void des3_set2key( uint32_t esk[96], + uint32_t dsk[96], + const unsigned char key[DES_KEY_SIZE*2] ) +{ + int i; + + des_setkey( esk, key ); + des_setkey( dsk + 32, key + 8 ); + + for( i = 0; i < 32; i += 2 ) + { + dsk[i ] = esk[30 - i]; + dsk[i + 1] = esk[31 - i]; + + esk[i + 32] = dsk[62 - i]; + esk[i + 33] = dsk[63 - i]; + + esk[i + 64] = esk[i ]; + esk[i + 65] = esk[i + 1]; + + dsk[i + 64] = dsk[i ]; + dsk[i + 65] = dsk[i + 1]; + } +} + +/* + * Triple-DES key schedule (112-bit, encryption) + */ +int des3_set2key_enc( des3_context *ctx, + const unsigned char key[DES_KEY_SIZE * 2] ) +{ + uint32_t sk[96]; +#ifdef RTL_HW_CRYPTO + memcpy(ctx->enc_key, key, DES_KEY_SIZE * 2); + memcpy(ctx->enc_key + DES_KEY_SIZE * 2, key, DES_KEY_SIZE); +#endif + des3_set2key( ctx->sk, sk, key ); + polarssl_zeroize( sk, sizeof( sk ) ); + + return( 0 ); +} + +/* + * Triple-DES key schedule (112-bit, decryption) + */ +int des3_set2key_dec( des3_context *ctx, + const unsigned char key[DES_KEY_SIZE * 2] ) +{ + uint32_t sk[96]; +#ifdef RTL_HW_CRYPTO + memcpy(ctx->dec_key, key, DES_KEY_SIZE * 2); + memcpy(ctx->dec_key + DES_KEY_SIZE * 2, key, DES_KEY_SIZE); +#endif + des3_set2key( sk, ctx->sk, key ); + polarssl_zeroize( sk, sizeof( sk ) ); + + return( 0 ); +} + +static void des3_set3key( uint32_t esk[96], + uint32_t dsk[96], + const unsigned char key[24] ) +{ + int i; + + des_setkey( esk, key ); + des_setkey( dsk + 32, key + 8 ); + des_setkey( esk + 64, key + 16 ); + + for( i = 0; i < 32; i += 2 ) + { + dsk[i ] = esk[94 - i]; + dsk[i + 1] = esk[95 - i]; + + esk[i + 32] = dsk[62 - i]; + esk[i + 33] = dsk[63 - i]; + + dsk[i + 64] = esk[30 - i]; + dsk[i + 65] = esk[31 - i]; + } +} + +/* + * Triple-DES key schedule (168-bit, encryption) + */ +int des3_set3key_enc( des3_context *ctx, + const unsigned char key[DES_KEY_SIZE * 3] ) +{ + uint32_t sk[96]; +#ifdef RTL_HW_CRYPTO + memcpy(ctx->enc_key, key, DES_KEY_SIZE * 3); +#endif + des3_set3key( ctx->sk, sk, key ); + polarssl_zeroize( sk, sizeof( sk ) ); + + return( 0 ); +} + +/* + * Triple-DES key schedule (168-bit, decryption) + */ +int des3_set3key_dec( des3_context *ctx, + const unsigned char key[DES_KEY_SIZE * 3] ) +{ + uint32_t sk[96]; +#ifdef RTL_HW_CRYPTO + memcpy(ctx->dec_key, key, DES_KEY_SIZE * 3); +#endif + des3_set3key( sk, ctx->sk, key ); + polarssl_zeroize( sk, sizeof( sk ) ); + + return( 0 ); +} + +/* + * DES-ECB block encryption/decryption + */ +int des_crypt_ecb( des_context *ctx, + const unsigned char input[8], + unsigned char output[8] ) +{ + int i; + uint32_t X, Y, T, *SK; + + SK = ctx->sk; + + GET_UINT32_BE( X, input, 0 ); + GET_UINT32_BE( Y, input, 4 ); + + DES_IP( X, Y ); + + for( i = 0; i < 8; i++ ) + { + DES_ROUND( Y, X ); + DES_ROUND( X, Y ); + } + + DES_FP( Y, X ); + + PUT_UINT32_BE( Y, output, 0 ); + PUT_UINT32_BE( X, output, 4 ); + + return( 0 ); + +} + +#if defined(POLARSSL_CIPHER_MODE_CBC) +/* + * DES-CBC buffer encryption/decryption + */ +int des_crypt_cbc( des_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ) +{ +#ifdef RTL_HW_CRYPTO + unsigned char key_buf[8 + 4], *key_buf_aligned; + unsigned char iv_buf[8 + 4], *iv_buf_aligned, iv_tmp[8]; + unsigned char *output_buf, *output_buf_aligned; + + if(length % 8) + return(POLARSSL_ERR_DES_INVALID_INPUT_LENGTH); + + if(length > 0) + { + key_buf_aligned = (unsigned char *) (((unsigned int) key_buf + 4) / 4 * 4); + iv_buf_aligned = (unsigned char *) (((unsigned int) iv_buf + 4) / 4 * 4); + output_buf = polarssl_malloc(length + 4); + output_buf_aligned = (unsigned char *) (((unsigned int) output_buf + 4) / 4 * 4); + + memcpy(iv_buf_aligned, iv, 8); + memset(output_buf, 0, length + 4); + + if(mode == DES_DECRYPT) + { + memcpy(key_buf_aligned, ctx->dec_key, DES_KEY_SIZE); + memcpy(iv_tmp, (input + length - 8), 8); + rtl_crypto_des_cbc_init(key_buf_aligned, DES_KEY_SIZE); + rtl_crypto_des_cbc_decrypt(input, length, iv_buf_aligned, 8, output_buf_aligned); + memcpy(iv, iv_tmp, 8); + } + else + { + memcpy(key_buf_aligned, ctx->enc_key, DES_KEY_SIZE); + rtl_crypto_des_cbc_init(key_buf_aligned, DES_KEY_SIZE); + rtl_crypto_des_cbc_encrypt(input, length, iv_buf_aligned, 8, output_buf_aligned); + memcpy(iv, (output_buf_aligned + length - 8), 8); + } + + memcpy(output, output_buf_aligned, length); + polarssl_free(output_buf); + } + + return 0; +#else /* RTL_HW_CRYPTO */ + int i; + unsigned char temp[8]; + + if( length % 8 ) + return( POLARSSL_ERR_DES_INVALID_INPUT_LENGTH ); + + if( mode == DES_ENCRYPT ) + { + while( length > 0 ) + { + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + des_crypt_ecb( ctx, output, output ); + memcpy( iv, output, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + else /* DES_DECRYPT */ + { + while( length > 0 ) + { + memcpy( temp, input, 8 ); + des_crypt_ecb( ctx, input, output ); + + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + + return( 0 ); +#endif +} +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +/* + * 3DES-ECB block encryption/decryption + */ +int des3_crypt_ecb( des3_context *ctx, + const unsigned char input[8], + unsigned char output[8] ) +{ + int i; + uint32_t X, Y, T, *SK; + + SK = ctx->sk; + + GET_UINT32_BE( X, input, 0 ); + GET_UINT32_BE( Y, input, 4 ); + + DES_IP( X, Y ); + + for( i = 0; i < 8; i++ ) + { + DES_ROUND( Y, X ); + DES_ROUND( X, Y ); + } + + for( i = 0; i < 8; i++ ) + { + DES_ROUND( X, Y ); + DES_ROUND( Y, X ); + } + + for( i = 0; i < 8; i++ ) + { + DES_ROUND( Y, X ); + DES_ROUND( X, Y ); + } + + DES_FP( Y, X ); + + PUT_UINT32_BE( Y, output, 0 ); + PUT_UINT32_BE( X, output, 4 ); + + return( 0 ); +} + +#if defined(POLARSSL_CIPHER_MODE_CBC) +/* + * 3DES-CBC buffer encryption/decryption + */ +int des3_crypt_cbc( des3_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ) +{ +#ifdef RTL_HW_CRYPTO + unsigned char key_buf[24 + 4], *key_buf_aligned; + unsigned char iv_buf[8 + 4], *iv_buf_aligned, iv_tmp[8]; + unsigned char *output_buf, *output_buf_aligned; + + if(length % 8) + return(POLARSSL_ERR_DES_INVALID_INPUT_LENGTH); + + if(length > 0) + { + key_buf_aligned = (unsigned char *) (((unsigned int) key_buf + 4) / 4 * 4); + iv_buf_aligned = (unsigned char *) (((unsigned int) iv_buf + 4) / 4 * 4); + output_buf = polarssl_malloc(length + 4); + output_buf_aligned = (unsigned char *) (((unsigned int) output_buf + 4) / 4 * 4); + + memcpy(iv_buf_aligned, iv, 8); + memset(output_buf, 0, length + 4); + + if(mode == DES_DECRYPT) + { + memcpy(key_buf_aligned, ctx->dec_key, DES_KEY_SIZE * 3); + memcpy(iv_tmp, (input + length - 8), 8); + rtl_crypto_3des_cbc_init(key_buf_aligned, DES_KEY_SIZE * 3); + rtl_crypto_3des_cbc_decrypt(input, length, iv_buf_aligned, 8, output_buf_aligned); + memcpy(iv, iv_tmp, 8); + } + else + { + memcpy(key_buf_aligned, ctx->enc_key, DES_KEY_SIZE * 3); + rtl_crypto_3des_cbc_init(key_buf_aligned, DES_KEY_SIZE * 3); + rtl_crypto_3des_cbc_encrypt(input, length, iv_buf_aligned, 8, output_buf_aligned); + memcpy(iv, (output_buf_aligned + length - 8), 8); + } + + memcpy(output, output_buf_aligned, length); + polarssl_free(output_buf); + } + + return 0; +#else /* RTL_HW_CRYPTO */ + int i; + unsigned char temp[8]; + + if( length % 8 ) + return( POLARSSL_ERR_DES_INVALID_INPUT_LENGTH ); + + if( mode == DES_ENCRYPT ) + { + while( length > 0 ) + { + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + des3_crypt_ecb( ctx, output, output ); + memcpy( iv, output, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + else /* DES_DECRYPT */ + { + while( length > 0 ) + { + memcpy( temp, input, 8 ); + des3_crypt_ecb( ctx, input, output ); + + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + + return( 0 ); +#endif +} +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#endif /* !POLARSSL_DES_ALT */ + +#if defined(POLARSSL_SELF_TEST) + +#include + +/* + * DES and 3DES test vectors from: + * + * http://csrc.nist.gov/groups/STM/cavp/documents/des/tripledes-vectors.zip + */ +static const unsigned char des3_test_keys[24] = +{ + 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, + 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23 +}; + +static const unsigned char des3_test_buf[8] = +{ + 0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74 +}; + +static const unsigned char des3_test_ecb_dec[3][8] = +{ + { 0xCD, 0xD6, 0x4F, 0x2F, 0x94, 0x27, 0xC1, 0x5D }, + { 0x69, 0x96, 0xC8, 0xFA, 0x47, 0xA2, 0xAB, 0xEB }, + { 0x83, 0x25, 0x39, 0x76, 0x44, 0x09, 0x1A, 0x0A } +}; + +static const unsigned char des3_test_ecb_enc[3][8] = +{ + { 0x6A, 0x2A, 0x19, 0xF4, 0x1E, 0xCA, 0x85, 0x4B }, + { 0x03, 0xE6, 0x9F, 0x5B, 0xFA, 0x58, 0xEB, 0x42 }, + { 0xDD, 0x17, 0xE8, 0xB8, 0xB4, 0x37, 0xD2, 0x32 } +}; + +#if defined(POLARSSL_CIPHER_MODE_CBC) +static const unsigned char des3_test_iv[8] = +{ + 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, +}; + +static const unsigned char des3_test_cbc_dec[3][8] = +{ + { 0x12, 0x9F, 0x40, 0xB9, 0xD2, 0x00, 0x56, 0xB3 }, + { 0x47, 0x0E, 0xFC, 0x9A, 0x6B, 0x8E, 0xE3, 0x93 }, + { 0xC5, 0xCE, 0xCF, 0x63, 0xEC, 0xEC, 0x51, 0x4C } +}; + +static const unsigned char des3_test_cbc_enc[3][8] = +{ + { 0x54, 0xF1, 0x5A, 0xF6, 0xEB, 0xE3, 0xA4, 0xB4 }, + { 0x35, 0x76, 0x11, 0x56, 0x5F, 0xA1, 0x8E, 0x4D }, + { 0xCB, 0x19, 0x1F, 0x85, 0xD1, 0xED, 0x84, 0x39 } +}; +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +/* + * Checkup routine + */ +int des_self_test( int verbose ) +{ + int i, j, u, v, ret = 0; + des_context ctx; + des3_context ctx3; + unsigned char buf[8]; +#if defined(POLARSSL_CIPHER_MODE_CBC) + unsigned char prv[8]; + unsigned char iv[8]; +#endif + + des_init( &ctx ); + des3_init( &ctx3 ); + /* + * ECB mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + polarssl_printf( " DES%c-ECB-%3d (%s): ", + ( u == 0 ) ? ' ' : '3', 56 + u * 56, + ( v == DES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( buf, des3_test_buf, 8 ); + + switch( i ) + { + case 0: + des_setkey_dec( &ctx, des3_test_keys ); + break; + + case 1: + des_setkey_enc( &ctx, des3_test_keys ); + break; + + case 2: + des3_set2key_dec( &ctx3, des3_test_keys ); + break; + + case 3: + des3_set2key_enc( &ctx3, des3_test_keys ); + break; + + case 4: + des3_set3key_dec( &ctx3, des3_test_keys ); + break; + + case 5: + des3_set3key_enc( &ctx3, des3_test_keys ); + break; + + default: + return( 1 ); + } + + for( j = 0; j < 10000; j++ ) + { + if( u == 0 ) + des_crypt_ecb( &ctx, buf, buf ); + else + des3_crypt_ecb( &ctx3, buf, buf ); + } + + if( ( v == DES_DECRYPT && + memcmp( buf, des3_test_ecb_dec[u], 8 ) != 0 ) || + ( v != DES_DECRYPT && + memcmp( buf, des3_test_ecb_enc[u], 8 ) != 0 ) ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); + +#if defined(POLARSSL_CIPHER_MODE_CBC) + /* + * CBC mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + polarssl_printf( " DES%c-CBC-%3d (%s): ", + ( u == 0 ) ? ' ' : '3', 56 + u * 56, + ( v == DES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( iv, des3_test_iv, 8 ); + memcpy( prv, des3_test_iv, 8 ); + memcpy( buf, des3_test_buf, 8 ); + + switch( i ) + { + case 0: + des_setkey_dec( &ctx, des3_test_keys ); + break; + + case 1: + des_setkey_enc( &ctx, des3_test_keys ); + break; + + case 2: + des3_set2key_dec( &ctx3, des3_test_keys ); + break; + + case 3: + des3_set2key_enc( &ctx3, des3_test_keys ); + break; + + case 4: + des3_set3key_dec( &ctx3, des3_test_keys ); + break; + + case 5: + des3_set3key_enc( &ctx3, des3_test_keys ); + break; + + default: + return( 1 ); + } + + if( v == DES_DECRYPT ) + { + for( j = 0; j < 10000; j++ ) + { + if( u == 0 ) + des_crypt_cbc( &ctx, v, 8, iv, buf, buf ); + else + des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf ); + } + } + else + { + for( j = 0; j < 10000; j++ ) + { + unsigned char tmp[8]; + + if( u == 0 ) + des_crypt_cbc( &ctx, v, 8, iv, buf, buf ); + else + des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf ); + + memcpy( tmp, prv, 8 ); + memcpy( prv, buf, 8 ); + memcpy( buf, tmp, 8 ); + } + + memcpy( buf, prv, 8 ); + } + + if( ( v == DES_DECRYPT && + memcmp( buf, des3_test_cbc_dec[u], 8 ) != 0 ) || + ( v != DES_DECRYPT && + memcmp( buf, des3_test_cbc_enc[u], 8 ) != 0 ) ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } +#endif /* POLARSSL_CIPHER_MODE_CBC */ + + if( verbose != 0 ) + polarssl_printf( "\n" ); + +exit: + des_free( &ctx ); + des3_free( &ctx3 ); + + return( ret ); +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_DES_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/dhm.c b/component/common/network/ssl/polarssl-1.3.8/library/dhm.c new file mode 100644 index 0000000..089c11b --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/dhm.c @@ -0,0 +1,598 @@ +/* + * Diffie-Hellman-Merkle key exchange + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * Reference: + * + * http://www.cacr.math.uwaterloo.ca/hac/ (chapter 12) + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_DHM_C) + +#include "polarssl/dhm.h" + +#if defined(POLARSSL_PEM_PARSE_C) +#include "polarssl/pem.h" +#endif + +#if defined(POLARSSL_ASN1_PARSE_C) +#include "polarssl/asn1.h" +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include +#define polarssl_printf printf +#define polarssl_malloc malloc +#define polarssl_free free +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * helper to validate the mpi size and import it + */ +static int dhm_read_bignum( mpi *X, + unsigned char **p, + const unsigned char *end ) +{ + int ret, n; + + if( end - *p < 2 ) + return( POLARSSL_ERR_DHM_BAD_INPUT_DATA ); + + n = ( (*p)[0] << 8 ) | (*p)[1]; + (*p) += 2; + + if( (int)( end - *p ) < n ) + return( POLARSSL_ERR_DHM_BAD_INPUT_DATA ); + + if( ( ret = mpi_read_binary( X, *p, n ) ) != 0 ) + return( POLARSSL_ERR_DHM_READ_PARAMS_FAILED + ret ); + + (*p) += n; + + return( 0 ); +} + +/* + * Verify sanity of parameter with regards to P + * + * Parameter should be: 2 <= public_param <= P - 2 + * + * For more information on the attack, see: + * http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf + * http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643 + */ +static int dhm_check_range( const mpi *param, const mpi *P ) +{ + mpi L, U; + int ret = POLARSSL_ERR_DHM_BAD_INPUT_DATA; + + mpi_init( &L ); mpi_init( &U ); + + MPI_CHK( mpi_lset( &L, 2 ) ); + MPI_CHK( mpi_sub_int( &U, P, 2 ) ); + + if( mpi_cmp_mpi( param, &L ) >= 0 && + mpi_cmp_mpi( param, &U ) <= 0 ) + { + ret = 0; + } + +cleanup: + mpi_free( &L ); mpi_free( &U ); + return( ret ); +} + +void dhm_init( dhm_context *ctx ) +{ + memset( ctx, 0, sizeof( dhm_context ) ); +} + +/* + * Parse the ServerKeyExchange parameters + */ +int dhm_read_params( dhm_context *ctx, + unsigned char **p, + const unsigned char *end ) +{ + int ret; + + if( ( ret = dhm_read_bignum( &ctx->P, p, end ) ) != 0 || + ( ret = dhm_read_bignum( &ctx->G, p, end ) ) != 0 || + ( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 ) + return( ret ); + + if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 ) + return( ret ); + + ctx->len = mpi_size( &ctx->P ); + + return( 0 ); +} + +/* + * Setup and write the ServerKeyExchange parameters + */ +int dhm_make_params( dhm_context *ctx, int x_size, + unsigned char *output, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret, count = 0; + size_t n1, n2, n3; + unsigned char *p; + + if( mpi_cmp_int( &ctx->P, 0 ) == 0 ) + return( POLARSSL_ERR_DHM_BAD_INPUT_DATA ); + + /* + * Generate X as large as possible ( < P ) + */ + do + { + mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ); + + while( mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 ) + MPI_CHK( mpi_shift_r( &ctx->X, 1 ) ); + + if( count++ > 10 ) + return( POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED ); + } + while( dhm_check_range( &ctx->X, &ctx->P ) != 0 ); + + /* + * Calculate GX = G^X mod P + */ + MPI_CHK( mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X, + &ctx->P , &ctx->RP ) ); + + if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 ) + return( ret ); + + /* + * export P, G, GX + */ +#define DHM_MPI_EXPORT(X,n) \ + MPI_CHK( mpi_write_binary( X, p + 2, n ) ); \ + *p++ = (unsigned char)( n >> 8 ); \ + *p++ = (unsigned char)( n ); p += n; + + n1 = mpi_size( &ctx->P ); + n2 = mpi_size( &ctx->G ); + n3 = mpi_size( &ctx->GX ); + + p = output; + DHM_MPI_EXPORT( &ctx->P , n1 ); + DHM_MPI_EXPORT( &ctx->G , n2 ); + DHM_MPI_EXPORT( &ctx->GX, n3 ); + + *olen = p - output; + + ctx->len = n1; + +cleanup: + + if( ret != 0 ) + return( POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED + ret ); + + return( 0 ); +} + +/* + * Import the peer's public value G^Y + */ +int dhm_read_public( dhm_context *ctx, + const unsigned char *input, size_t ilen ) +{ + int ret; + + if( ctx == NULL || ilen < 1 || ilen > ctx->len ) + return( POLARSSL_ERR_DHM_BAD_INPUT_DATA ); + + if( ( ret = mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 ) + return( POLARSSL_ERR_DHM_READ_PUBLIC_FAILED + ret ); + + return( 0 ); +} + +/* + * Create own private value X and export G^X + */ +int dhm_make_public( dhm_context *ctx, int x_size, + unsigned char *output, size_t olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret, count = 0; + + if( ctx == NULL || olen < 1 || olen > ctx->len ) + return( POLARSSL_ERR_DHM_BAD_INPUT_DATA ); + + if( mpi_cmp_int( &ctx->P, 0 ) == 0 ) + return( POLARSSL_ERR_DHM_BAD_INPUT_DATA ); + + /* + * generate X and calculate GX = G^X mod P + */ + do + { + mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ); + + while( mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 ) + MPI_CHK( mpi_shift_r( &ctx->X, 1 ) ); + + if( count++ > 10 ) + return( POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED ); + } + while( dhm_check_range( &ctx->X, &ctx->P ) != 0 ); + + MPI_CHK( mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X, + &ctx->P , &ctx->RP ) ); + + if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 ) + return( ret ); + + MPI_CHK( mpi_write_binary( &ctx->GX, output, olen ) ); + +cleanup: + + if( ret != 0 ) + return( POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED + ret ); + + return( 0 ); +} + +/* + * Use the blinding method and optimisation suggested in section 10 of: + * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA, + * DSS, and other systems. In : Advances in Cryptology—CRYPTO’96. Springer + * Berlin Heidelberg, 1996. p. 104-113. + */ +static int dhm_update_blinding( dhm_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret, count; + + /* + * Don't use any blinding the first time a particular X is used, + * but remember it to use blinding next time. + */ + if( mpi_cmp_mpi( &ctx->X, &ctx->pX ) != 0 ) + { + MPI_CHK( mpi_copy( &ctx->pX, &ctx->X ) ); + MPI_CHK( mpi_lset( &ctx->Vi, 1 ) ); + MPI_CHK( mpi_lset( &ctx->Vf, 1 ) ); + + return( 0 ); + } + + /* + * Ok, we need blinding. Can we re-use existing values? + * If yes, just update them by squaring them. + */ + if( mpi_cmp_int( &ctx->Vi, 1 ) != 0 ) + { + MPI_CHK( mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) ); + MPI_CHK( mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->P ) ); + + MPI_CHK( mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) ); + MPI_CHK( mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) ); + + return( 0 ); + } + + /* + * We need to generate blinding values from scratch + */ + + /* Vi = random( 2, P-1 ) */ + count = 0; + do + { + mpi_fill_random( &ctx->Vi, mpi_size( &ctx->P ), f_rng, p_rng ); + + while( mpi_cmp_mpi( &ctx->Vi, &ctx->P ) >= 0 ) + MPI_CHK( mpi_shift_r( &ctx->Vi, 1 ) ); + + if( count++ > 10 ) + return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE ); + } + while( mpi_cmp_int( &ctx->Vi, 1 ) <= 0 ); + + /* Vf = Vi^-X mod P */ + MPI_CHK( mpi_inv_mod( &ctx->Vf, &ctx->Vi, &ctx->P ) ); + MPI_CHK( mpi_exp_mod( &ctx->Vf, &ctx->Vf, &ctx->X, &ctx->P, &ctx->RP ) ); + +cleanup: + return( ret ); +} + +/* + * Derive and export the shared secret (G^Y)^X mod P + */ +int dhm_calc_secret( dhm_context *ctx, + unsigned char *output, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + mpi GYb; + + if( ctx == NULL || *olen < ctx->len ) + return( POLARSSL_ERR_DHM_BAD_INPUT_DATA ); + + if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 ) + return( ret ); + + mpi_init( &GYb ); + + /* Blind peer's value */ + if( f_rng != NULL ) + { + MPI_CHK( dhm_update_blinding( ctx, f_rng, p_rng ) ); + MPI_CHK( mpi_mul_mpi( &GYb, &ctx->GY, &ctx->Vi ) ); + MPI_CHK( mpi_mod_mpi( &GYb, &GYb, &ctx->P ) ); + } + else + MPI_CHK( mpi_copy( &GYb, &ctx->GY ) ); + + /* Do modular exponentiation */ + MPI_CHK( mpi_exp_mod( &ctx->K, &GYb, &ctx->X, + &ctx->P, &ctx->RP ) ); + + /* Unblind secret value */ + if( f_rng != NULL ) + { + MPI_CHK( mpi_mul_mpi( &ctx->K, &ctx->K, &ctx->Vf ) ); + MPI_CHK( mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) ); + } + + *olen = mpi_size( &ctx->K ); + + MPI_CHK( mpi_write_binary( &ctx->K, output, *olen ) ); + +cleanup: + mpi_free( &GYb ); + + if( ret != 0 ) + return( POLARSSL_ERR_DHM_CALC_SECRET_FAILED + ret ); + + return( 0 ); +} + +/* + * Free the components of a DHM key + */ +void dhm_free( dhm_context *ctx ) +{ + mpi_free( &ctx->pX); mpi_free( &ctx->Vf ); mpi_free( &ctx->Vi ); + mpi_free( &ctx->RP ); mpi_free( &ctx->K ); mpi_free( &ctx->GY ); + mpi_free( &ctx->GX ); mpi_free( &ctx->X ); mpi_free( &ctx->G ); + mpi_free( &ctx->P ); + + polarssl_zeroize( ctx, sizeof( dhm_context ) ); +} + +#if defined(POLARSSL_ASN1_PARSE_C) +/* + * Parse DHM parameters + */ +int dhm_parse_dhm( dhm_context *dhm, const unsigned char *dhmin, + size_t dhminlen ) +{ + int ret; + size_t len; + unsigned char *p, *end; +#if defined(POLARSSL_PEM_PARSE_C) + pem_context pem; + + pem_init( &pem ); + + ret = pem_read_buffer( &pem, + "-----BEGIN DH PARAMETERS-----", + "-----END DH PARAMETERS-----", + dhmin, NULL, 0, &dhminlen ); + + if( ret == 0 ) + { + /* + * Was PEM encoded + */ + dhminlen = pem.buflen; + } + else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + goto exit; + + p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin; +#else + p = (unsigned char *) dhmin; +#endif /* POLARSSL_PEM_PARSE_C */ + end = p + dhminlen; + + /* + * DHParams ::= SEQUENCE { + * prime INTEGER, -- P + * generator INTEGER, -- g + * } + */ + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + ret = POLARSSL_ERR_DHM_INVALID_FORMAT + ret; + goto exit; + } + + end = p + len; + + if( ( ret = asn1_get_mpi( &p, end, &dhm->P ) ) != 0 || + ( ret = asn1_get_mpi( &p, end, &dhm->G ) ) != 0 ) + { + ret = POLARSSL_ERR_DHM_INVALID_FORMAT + ret; + goto exit; + } + + if( p != end ) + { + ret = POLARSSL_ERR_DHM_INVALID_FORMAT + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH; + goto exit; + } + + ret = 0; + + dhm->len = mpi_size( &dhm->P ); + +exit: +#if defined(POLARSSL_PEM_PARSE_C) + pem_free( &pem ); +#endif + if( ret != 0 ) + dhm_free( dhm ); + + return( ret ); +} + +#if defined(POLARSSL_FS_IO) +/* + * Load all data from a file into a given buffer. + */ +static int load_file( const char *path, unsigned char **buf, size_t *n ) +{ + FILE *f; + long size; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( POLARSSL_ERR_DHM_FILE_IO_ERROR ); + + fseek( f, 0, SEEK_END ); + if( ( size = ftell( f ) ) == -1 ) + { + fclose( f ); + return( POLARSSL_ERR_DHM_FILE_IO_ERROR ); + } + fseek( f, 0, SEEK_SET ); + + *n = (size_t) size; + + if( *n + 1 == 0 || + ( *buf = (unsigned char *) polarssl_malloc( *n + 1 ) ) == NULL ) + { + fclose( f ); + return( POLARSSL_ERR_DHM_MALLOC_FAILED ); + } + + if( fread( *buf, 1, *n, f ) != *n ) + { + fclose( f ); + polarssl_free( *buf ); + return( POLARSSL_ERR_DHM_FILE_IO_ERROR ); + } + + fclose( f ); + + (*buf)[*n] = '\0'; + + return( 0 ); +} + +/* + * Load and parse DHM parameters + */ +int dhm_parse_dhmfile( dhm_context *dhm, const char *path ) +{ + int ret; + size_t n; + unsigned char *buf; + + if( ( ret = load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = dhm_parse_dhm( dhm, buf, n ); + + polarssl_zeroize( buf, n + 1 ); + polarssl_free( buf ); + + return( ret ); +} +#endif /* POLARSSL_FS_IO */ +#endif /* POLARSSL_ASN1_PARSE_C */ + +#if defined(POLARSSL_SELF_TEST) + +#include "polarssl/certs.h" + +/* + * Checkup routine + */ +int dhm_self_test( int verbose ) +{ +#if defined(POLARSSL_CERTS_C) + int ret; + dhm_context dhm; + + dhm_init( &dhm ); + + if( verbose != 0 ) + polarssl_printf( " DHM parameter load: " ); + + if( ( ret = dhm_parse_dhm( &dhm, (const unsigned char *) test_dhm_params, + strlen( test_dhm_params ) ) ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + polarssl_printf( "passed\n\n" ); + +exit: + dhm_free( &dhm ); + + return( ret ); +#else + if( verbose != 0 ) + polarssl_printf( " DHM parameter load: skipped\n" ); + + return( 0 ); +#endif /* POLARSSL_CERTS_C */ +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_DHM_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/ecdh.c b/component/common/network/ssl/polarssl-1.3.8/library/ecdh.c new file mode 100644 index 0000000..b93d82e --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/ecdh.c @@ -0,0 +1,280 @@ +/* + * Elliptic curve Diffie-Hellman + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* + * References: + * + * SEC1 http://www.secg.org/index.php?action=secg,docs_secg + * RFC 4492 + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_ECDH_C) + +#include "polarssl/ecdh.h" + +/* + * Generate public key: simple wrapper around ecp_gen_keypair + */ +int ecdh_gen_public( ecp_group *grp, mpi *d, ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + return ecp_gen_keypair( grp, d, Q, f_rng, p_rng ); +} + +/* + * Compute shared secret (SEC1 3.3.1) + */ +int ecdh_compute_shared( ecp_group *grp, mpi *z, + const ecp_point *Q, const mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + ecp_point P; + + ecp_point_init( &P ); + + /* + * Make sure Q is a valid pubkey before using it + */ + MPI_CHK( ecp_check_pubkey( grp, Q ) ); + + MPI_CHK( ecp_mul( grp, &P, d, Q, f_rng, p_rng ) ); + + if( ecp_is_zero( &P ) ) + { + ret = POLARSSL_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + + MPI_CHK( mpi_copy( z, &P.X ) ); + +cleanup: + ecp_point_free( &P ); + + return( ret ); +} + +/* + * Initialize context + */ +void ecdh_init( ecdh_context *ctx ) +{ + memset( ctx, 0, sizeof( ecdh_context ) ); +} + +/* + * Free context + */ +void ecdh_free( ecdh_context *ctx ) +{ + if( ctx == NULL ) + return; + + ecp_group_free( &ctx->grp ); + ecp_point_free( &ctx->Q ); + ecp_point_free( &ctx->Qp ); + ecp_point_free( &ctx->Vi ); + ecp_point_free( &ctx->Vf ); + mpi_free( &ctx->d ); + mpi_free( &ctx->z ); + mpi_free( &ctx->_d ); +} + +/* + * Setup and write the ServerKeyExhange parameters (RFC 4492) + * struct { + * ECParameters curve_params; + * ECPoint public; + * } ServerECDHParams; + */ +int ecdh_make_params( ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + size_t grp_len, pt_len; + + if( ctx == NULL || ctx->grp.pbits == 0 ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) ) + != 0 ) + return( ret ); + + if( ( ret = ecp_tls_write_group( &ctx->grp, &grp_len, buf, blen ) ) + != 0 ) + return( ret ); + + buf += grp_len; + blen -= grp_len; + + if( ( ret = ecp_tls_write_point( &ctx->grp, &ctx->Q, ctx->point_format, + &pt_len, buf, blen ) ) != 0 ) + return( ret ); + + *olen = grp_len + pt_len; + return( 0 ); +} + +/* + * Read the ServerKeyExhange parameters (RFC 4492) + * struct { + * ECParameters curve_params; + * ECPoint public; + * } ServerECDHParams; + */ +int ecdh_read_params( ecdh_context *ctx, + const unsigned char **buf, const unsigned char *end ) +{ + int ret; + + if( ( ret = ecp_tls_read_group( &ctx->grp, buf, end - *buf ) ) != 0 ) + return( ret ); + + if( ( ret = ecp_tls_read_point( &ctx->grp, &ctx->Qp, buf, end - *buf ) ) + != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * Get parameters from a keypair + */ +int ecdh_get_params( ecdh_context *ctx, const ecp_keypair *key, + ecdh_side side ) +{ + int ret; + + if( ( ret = ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 ) + return( ret ); + + /* If it's not our key, just import the public part as Qp */ + if( side == POLARSSL_ECDH_THEIRS ) + return( ecp_copy( &ctx->Qp, &key->Q ) ); + + /* Our key: import public (as Q) and private parts */ + if( side != POLARSSL_ECDH_OURS ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = ecp_copy( &ctx->Q, &key->Q ) ) != 0 || + ( ret = mpi_copy( &ctx->d, &key->d ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * Setup and export the client public value + */ +int ecdh_make_public( ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + + if( ctx == NULL || ctx->grp.pbits == 0 ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) ) + != 0 ) + return( ret ); + + return ecp_tls_write_point( &ctx->grp, &ctx->Q, ctx->point_format, + olen, buf, blen ); +} + +/* + * Parse and import the client's public value + */ +int ecdh_read_public( ecdh_context *ctx, + const unsigned char *buf, size_t blen ) +{ + int ret; + const unsigned char *p = buf; + + if( ctx == NULL ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = ecp_tls_read_point( &ctx->grp, &ctx->Qp, &p, blen ) ) != 0 ) + return( ret ); + + if( (size_t)( p - buf ) != blen ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + return( 0 ); +} + +/* + * Derive and export the shared secret + */ +int ecdh_calc_secret( ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + + if( ctx == NULL ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp, &ctx->d, + f_rng, p_rng ) ) != 0 ) + { + return( ret ); + } + + if( mpi_size( &ctx->z ) > blen ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + *olen = ctx->grp.pbits / 8 + ( ( ctx->grp.pbits % 8 ) != 0 ); + return mpi_write_binary( &ctx->z, buf, *olen ); +} + + +#if defined(POLARSSL_SELF_TEST) + +/* + * Checkup routine + */ +int ecdh_self_test( int verbose ) +{ + ((void) verbose ); + return( 0 ); +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_ECDH_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/ecdsa.c b/component/common/network/ssl/polarssl-1.3.8/library/ecdsa.c new file mode 100644 index 0000000..5af7f6b --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/ecdsa.c @@ -0,0 +1,503 @@ +/* + * Elliptic curve DSA + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* + * References: + * + * SEC1 http://www.secg.org/index.php?action=secg,docs_secg + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_ECDSA_C) + +#include "polarssl/ecdsa.h" +#include "polarssl/asn1write.h" + +#if defined(POLARSSL_ECDSA_DETERMINISTIC) +#include "polarssl/hmac_drbg.h" +#endif + +#if defined(POLARSSL_ECDSA_DETERMINISTIC) +/* + * This a hopefully temporary compatibility function. + * + * Since we can't ensure the caller will pass a valid md_alg before the next + * interface change, try to pick up a decent md by size. + * + * Argument is the minimum size in bytes of the MD output. + */ +static const md_info_t *md_info_by_size( size_t min_size ) +{ + const md_info_t *md_cur, *md_picked = NULL; + const int *md_alg; + + for( md_alg = md_list(); *md_alg != 0; md_alg++ ) + { + if( ( md_cur = md_info_from_type( *md_alg ) ) == NULL || + (size_t) md_cur->size < min_size || + ( md_picked != NULL && md_cur->size > md_picked->size ) ) + continue; + + md_picked = md_cur; + } + + return( md_picked ); +} +#endif /* POLARSSL_ECDSA_DETERMINISTIC */ + +/* + * Derive a suitable integer for group grp from a buffer of length len + * SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3 + */ +static int derive_mpi( const ecp_group *grp, mpi *x, + const unsigned char *buf, size_t blen ) +{ + int ret; + size_t n_size = ( grp->nbits + 7 ) / 8; + size_t use_size = blen > n_size ? n_size : blen; + + MPI_CHK( mpi_read_binary( x, buf, use_size ) ); + if( use_size * 8 > grp->nbits ) + MPI_CHK( mpi_shift_r( x, use_size * 8 - grp->nbits ) ); + + /* While at it, reduce modulo N */ + if( mpi_cmp_mpi( x, &grp->N ) >= 0 ) + MPI_CHK( mpi_sub_mpi( x, x, &grp->N ) ); + +cleanup: + return( ret ); +} + +/* + * Compute ECDSA signature of a hashed message (SEC1 4.1.3) + * Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message) + */ +int ecdsa_sign( ecp_group *grp, mpi *r, mpi *s, + const mpi *d, const unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret, key_tries, sign_tries, blind_tries; + ecp_point R; + mpi k, e, t; + + /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ + if( grp->N.p == NULL ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + ecp_point_init( &R ); + mpi_init( &k ); mpi_init( &e ); mpi_init( &t ); + + sign_tries = 0; + do + { + /* + * Steps 1-3: generate a suitable ephemeral keypair + * and set r = xR mod n + */ + key_tries = 0; + do + { + MPI_CHK( ecp_gen_keypair( grp, &k, &R, f_rng, p_rng ) ); + MPI_CHK( mpi_mod_mpi( r, &R.X, &grp->N ) ); + + if( key_tries++ > 10 ) + { + ret = POLARSSL_ERR_ECP_RANDOM_FAILED; + goto cleanup; + } + } + while( mpi_cmp_int( r, 0 ) == 0 ); + + /* + * Step 5: derive MPI from hashed message + */ + MPI_CHK( derive_mpi( grp, &e, buf, blen ) ); + + /* + * Generate a random value to blind inv_mod in next step, + * avoiding a potential timing leak. + */ + blind_tries = 0; + do + { + size_t n_size = ( grp->nbits + 7 ) / 8; + MPI_CHK( mpi_fill_random( &t, n_size, f_rng, p_rng ) ); + MPI_CHK( mpi_shift_r( &t, 8 * n_size - grp->nbits ) ); + + /* See ecp_gen_keypair() */ + if( ++blind_tries > 30 ) + return( POLARSSL_ERR_ECP_RANDOM_FAILED ); + } + while( mpi_cmp_int( &t, 1 ) < 0 || + mpi_cmp_mpi( &t, &grp->N ) >= 0 ); + + /* + * Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n + */ + MPI_CHK( mpi_mul_mpi( s, r, d ) ); + MPI_CHK( mpi_add_mpi( &e, &e, s ) ); + MPI_CHK( mpi_mul_mpi( &e, &e, &t ) ); + MPI_CHK( mpi_mul_mpi( &k, &k, &t ) ); + MPI_CHK( mpi_inv_mod( s, &k, &grp->N ) ); + MPI_CHK( mpi_mul_mpi( s, s, &e ) ); + MPI_CHK( mpi_mod_mpi( s, s, &grp->N ) ); + + if( sign_tries++ > 10 ) + { + ret = POLARSSL_ERR_ECP_RANDOM_FAILED; + goto cleanup; + } + } + while( mpi_cmp_int( s, 0 ) == 0 ); + +cleanup: + ecp_point_free( &R ); + mpi_free( &k ); mpi_free( &e ); mpi_free( &t ); + + return( ret ); +} + +#if defined(POLARSSL_ECDSA_DETERMINISTIC) +/* + * Deterministic signature wrapper + */ +int ecdsa_sign_det( ecp_group *grp, mpi *r, mpi *s, + const mpi *d, const unsigned char *buf, size_t blen, + md_type_t md_alg ) +{ + int ret; + hmac_drbg_context rng_ctx; + unsigned char data[2 * POLARSSL_ECP_MAX_BYTES]; + size_t grp_len = ( grp->nbits + 7 ) / 8; + const md_info_t *md_info; + mpi h; + + /* Temporary fallback */ + if( md_alg == POLARSSL_MD_NONE ) + md_info = md_info_by_size( blen ); + else + md_info = md_info_from_type( md_alg ); + + if( md_info == NULL ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + mpi_init( &h ); + memset( &rng_ctx, 0, sizeof( hmac_drbg_context ) ); + + /* Use private key and message hash (reduced) to initialize HMAC_DRBG */ + MPI_CHK( mpi_write_binary( d, data, grp_len ) ); + MPI_CHK( derive_mpi( grp, &h, buf, blen ) ); + MPI_CHK( mpi_write_binary( &h, data + grp_len, grp_len ) ); + hmac_drbg_init_buf( &rng_ctx, md_info, data, 2 * grp_len ); + + ret = ecdsa_sign( grp, r, s, d, buf, blen, + hmac_drbg_random, &rng_ctx ); + +cleanup: + hmac_drbg_free( &rng_ctx ); + mpi_free( &h ); + + return( ret ); +} +#endif /* POLARSSL_ECDSA_DETERMINISTIC */ + +/* + * Verify ECDSA signature of hashed message (SEC1 4.1.4) + * Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message) + */ +int ecdsa_verify( ecp_group *grp, + const unsigned char *buf, size_t blen, + const ecp_point *Q, const mpi *r, const mpi *s) +{ + int ret; + mpi e, s_inv, u1, u2; + ecp_point R, P; + + ecp_point_init( &R ); ecp_point_init( &P ); + mpi_init( &e ); mpi_init( &s_inv ); mpi_init( &u1 ); mpi_init( &u2 ); + + /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ + if( grp->N.p == NULL ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + /* + * Step 1: make sure r and s are in range 1..n-1 + */ + if( mpi_cmp_int( r, 1 ) < 0 || mpi_cmp_mpi( r, &grp->N ) >= 0 || + mpi_cmp_int( s, 1 ) < 0 || mpi_cmp_mpi( s, &grp->N ) >= 0 ) + { + ret = POLARSSL_ERR_ECP_VERIFY_FAILED; + goto cleanup; + } + + /* + * Additional precaution: make sure Q is valid + */ + MPI_CHK( ecp_check_pubkey( grp, Q ) ); + + /* + * Step 3: derive MPI from hashed message + */ + MPI_CHK( derive_mpi( grp, &e, buf, blen ) ); + + /* + * Step 4: u1 = e / s mod n, u2 = r / s mod n + */ + MPI_CHK( mpi_inv_mod( &s_inv, s, &grp->N ) ); + + MPI_CHK( mpi_mul_mpi( &u1, &e, &s_inv ) ); + MPI_CHK( mpi_mod_mpi( &u1, &u1, &grp->N ) ); + + MPI_CHK( mpi_mul_mpi( &u2, r, &s_inv ) ); + MPI_CHK( mpi_mod_mpi( &u2, &u2, &grp->N ) ); + + /* + * Step 5: R = u1 G + u2 Q + * + * Since we're not using any secret data, no need to pass a RNG to + * ecp_mul() for countermesures. + */ + MPI_CHK( ecp_mul( grp, &R, &u1, &grp->G, NULL, NULL ) ); + MPI_CHK( ecp_mul( grp, &P, &u2, Q, NULL, NULL ) ); + MPI_CHK( ecp_add( grp, &R, &R, &P ) ); + + if( ecp_is_zero( &R ) ) + { + ret = POLARSSL_ERR_ECP_VERIFY_FAILED; + goto cleanup; + } + + /* + * Step 6: convert xR to an integer (no-op) + * Step 7: reduce xR mod n (gives v) + */ + MPI_CHK( mpi_mod_mpi( &R.X, &R.X, &grp->N ) ); + + /* + * Step 8: check if v (that is, R.X) is equal to r + */ + if( mpi_cmp_mpi( &R.X, r ) != 0 ) + { + ret = POLARSSL_ERR_ECP_VERIFY_FAILED; + goto cleanup; + } + +cleanup: + ecp_point_free( &R ); ecp_point_free( &P ); + mpi_free( &e ); mpi_free( &s_inv ); mpi_free( &u1 ); mpi_free( &u2 ); + + return( ret ); +} + +/* + * RFC 4492 page 20: + * + * Ecdsa-Sig-Value ::= SEQUENCE { + * r INTEGER, + * s INTEGER + * } + * + * Size is at most + * 1 (tag) + 1 (len) + 1 (initial 0) + ECP_MAX_BYTES for each of r and s, + * twice that + 1 (tag) + 2 (len) for the sequence + * (assuming ECP_MAX_BYTES is less than 126 for r and s, + * and less than 124 (total len <= 255) for the sequence) + */ +#if POLARSSL_ECP_MAX_BYTES > 124 +#error "POLARSSL_ECP_MAX_BYTES bigger than expected, please fix MAX_SIG_LEN" +#endif +#define MAX_SIG_LEN ( 3 + 2 * ( 2 + POLARSSL_ECP_MAX_BYTES ) ) + +/* + * Convert a signature (given by context) to ASN.1 + */ +static int ecdsa_signature_to_asn1( ecdsa_context *ctx, + unsigned char *sig, size_t *slen ) +{ + int ret; + unsigned char buf[MAX_SIG_LEN]; + unsigned char *p = buf + sizeof( buf ); + size_t len = 0; + + ASN1_CHK_ADD( len, asn1_write_mpi( &p, buf, &ctx->s ) ); + ASN1_CHK_ADD( len, asn1_write_mpi( &p, buf, &ctx->r ) ); + + ASN1_CHK_ADD( len, asn1_write_len( &p, buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &p, buf, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); + + memcpy( sig, p, len ); + *slen = len; + + return( 0 ); +} + +/* + * Compute and write signature + */ +int ecdsa_write_signature( ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + + if( ( ret = ecdsa_sign( &ctx->grp, &ctx->r, &ctx->s, &ctx->d, + hash, hlen, f_rng, p_rng ) ) != 0 ) + { + return( ret ); + } + + return( ecdsa_signature_to_asn1( ctx, sig, slen ) ); +} + +#if defined(POLARSSL_ECDSA_DETERMINISTIC) +/* + * Compute and write signature deterministically + */ +int ecdsa_write_signature_det( ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + md_type_t md_alg ) +{ + int ret; + + if( ( ret = ecdsa_sign_det( &ctx->grp, &ctx->r, &ctx->s, &ctx->d, + hash, hlen, md_alg ) ) != 0 ) + { + return( ret ); + } + + return( ecdsa_signature_to_asn1( ctx, sig, slen ) ); +} +#endif /* POLARSSL_ECDSA_DETERMINISTIC */ + +/* + * Read and check signature + */ +int ecdsa_read_signature( ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + const unsigned char *sig, size_t slen ) +{ + int ret; + unsigned char *p = (unsigned char *) sig; + const unsigned char *end = sig + slen; + size_t len; + + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA + ret ); + } + + if( p + len != end ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + if( ( ret = asn1_get_mpi( &p, end, &ctx->r ) ) != 0 || + ( ret = asn1_get_mpi( &p, end, &ctx->s ) ) != 0 ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA + ret ); + + if( ( ret = ecdsa_verify( &ctx->grp, hash, hlen, + &ctx->Q, &ctx->r, &ctx->s ) ) != 0 ) + return( ret ); + + if( p != end ) + return( POLARSSL_ERR_ECP_SIG_LEN_MISMATCH ); + + return( 0 ); +} + +/* + * Generate key pair + */ +int ecdsa_genkey( ecdsa_context *ctx, ecp_group_id gid, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + return( ecp_use_known_dp( &ctx->grp, gid ) || + ecp_gen_keypair( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) ); +} + +/* + * Set context from an ecp_keypair + */ +int ecdsa_from_keypair( ecdsa_context *ctx, const ecp_keypair *key ) +{ + int ret; + + if( ( ret = ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 || + ( ret = mpi_copy( &ctx->d, &key->d ) ) != 0 || + ( ret = ecp_copy( &ctx->Q, &key->Q ) ) != 0 ) + { + ecdsa_free( ctx ); + } + + return( ret ); +} + +/* + * Initialize context + */ +void ecdsa_init( ecdsa_context *ctx ) +{ + ecp_group_init( &ctx->grp ); + mpi_init( &ctx->d ); + ecp_point_init( &ctx->Q ); + mpi_init( &ctx->r ); + mpi_init( &ctx->s ); +} + +/* + * Free context + */ +void ecdsa_free( ecdsa_context *ctx ) +{ + ecp_group_free( &ctx->grp ); + mpi_free( &ctx->d ); + ecp_point_free( &ctx->Q ); + mpi_free( &ctx->r ); + mpi_free( &ctx->s ); +} + +#if defined(POLARSSL_SELF_TEST) + +/* + * Checkup routine + */ +int ecdsa_self_test( int verbose ) +{ + ((void) verbose ); + return( 0 ); +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_ECDSA_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/ecp.c b/component/common/network/ssl/polarssl-1.3.8/library/ecp.c new file mode 100644 index 0000000..afa7955 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/ecp.c @@ -0,0 +1,2029 @@ +/* + * Elliptic curves over GF(p): generic functions + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* + * References: + * + * SEC1 http://www.secg.org/index.php?action=secg,docs_secg + * GECC = Guide to Elliptic Curve Cryptography - Hankerson, Menezes, Vanstone + * FIPS 186-3 http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf + * RFC 4492 for the related TLS structures and constants + * + * [M255] http://cr.yp.to/ecdh/curve25519-20060209.pdf + * + * [2] CORON, Jean-Sébastien. Resistance against differential power analysis + * for elliptic curve cryptosystems. In : Cryptographic Hardware and + * Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302. + * + * + * [3] HEDABOU, Mustapha, PINEL, Pierre, et BÉNÉTEAU, Lucien. A comb method to + * render ECC resistant against Side Channel Attacks. IACR Cryptology + * ePrint Archive, 2004, vol. 2004, p. 342. + * + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_ECP_C) + +#include "polarssl/ecp.h" + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#define polarssl_printf printf +#define polarssl_malloc malloc +#define polarssl_free free +#endif + +#include + +#if defined(_MSC_VER) && !defined strcasecmp && !defined(EFIX64) && \ + !defined(EFI32) +#define strcasecmp _stricmp +#endif + +#if defined(_MSC_VER) && !defined(inline) +#define inline _inline +#else +#if defined(__ARMCC_VERSION) && !defined(inline) +#define inline __inline +#endif /* __ARMCC_VERSION */ +#endif /*_MSC_VER */ + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +#if defined(POLARSSL_SELF_TEST) +/* + * Counts of point addition and doubling, and field multiplications. + * Used to test resistance of point multiplication to simple timing attacks. + */ +static unsigned long add_count, dbl_count, mul_count; +#endif + +#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED) || \ + defined(POLARSSL_ECP_DP_SECP224R1_ENABLED) || \ + defined(POLARSSL_ECP_DP_SECP256R1_ENABLED) || \ + defined(POLARSSL_ECP_DP_SECP384R1_ENABLED) || \ + defined(POLARSSL_ECP_DP_SECP521R1_ENABLED) || \ + defined(POLARSSL_ECP_DP_BP256R1_ENABLED) || \ + defined(POLARSSL_ECP_DP_BP384R1_ENABLED) || \ + defined(POLARSSL_ECP_DP_BP512R1_ENABLED) || \ + defined(POLARSSL_ECP_DP_SECP192K1_ENABLED) || \ + defined(POLARSSL_ECP_DP_SECP224K1_ENABLED) || \ + defined(POLARSSL_ECP_DP_SECP256K1_ENABLED) +#define POLARSSL_ECP_SHORT_WEIERSTRASS +#endif + +#if defined(POLARSSL_ECP_DP_M221_ENABLED) || \ + defined(POLARSSL_ECP_DP_M255_ENABLED) || \ + defined(POLARSSL_ECP_DP_M383_ENABLED) || \ + defined(POLARSSL_ECP_DP_M511_ENABLED) +#define POLARSSL_ECP_MONTGOMERY +#endif + +/* + * Curve types: internal for now, might be exposed later + */ +typedef enum +{ + POLARSSL_ECP_TYPE_NONE = 0, + POLARSSL_ECP_TYPE_SHORT_WEIERSTRASS, /* y^2 = x^3 + a x + b */ + POLARSSL_ECP_TYPE_MONTGOMERY, /* y^2 = x^3 + a x^2 + x */ +} ecp_curve_type; + +/* + * List of supported curves: + * - internal ID + * - TLS NamedCurve ID (RFC 4492 sec. 5.1.1, RFC 7071 sec. 2) + * - size in bits + * - readable name + * + * Curves are listed in order: largest curves first, and for a given size, + * fastest curves first. This provides the default order for the SSL module. + */ +static const ecp_curve_info ecp_supported_curves[] = +{ +#if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED) + { POLARSSL_ECP_DP_SECP521R1, 25, 521, "secp521r1" }, +#endif +#if defined(POLARSSL_ECP_DP_BP512R1_ENABLED) + { POLARSSL_ECP_DP_BP512R1, 28, 512, "brainpoolP512r1" }, +#endif +#if defined(POLARSSL_ECP_DP_SECP384R1_ENABLED) + { POLARSSL_ECP_DP_SECP384R1, 24, 384, "secp384r1" }, +#endif +#if defined(POLARSSL_ECP_DP_BP384R1_ENABLED) + { POLARSSL_ECP_DP_BP384R1, 27, 384, "brainpoolP384r1" }, +#endif +#if defined(POLARSSL_ECP_DP_SECP256R1_ENABLED) + { POLARSSL_ECP_DP_SECP256R1, 23, 256, "secp256r1" }, +#endif +#if defined(POLARSSL_ECP_DP_SECP256K1_ENABLED) + { POLARSSL_ECP_DP_SECP256K1, 22, 256, "secp256k1" }, +#endif +#if defined(POLARSSL_ECP_DP_BP256R1_ENABLED) + { POLARSSL_ECP_DP_BP256R1, 26, 256, "brainpoolP256r1" }, +#endif +#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED) + { POLARSSL_ECP_DP_SECP224R1, 21, 224, "secp224r1" }, +#endif +#if defined(POLARSSL_ECP_DP_SECP224K1_ENABLED) + { POLARSSL_ECP_DP_SECP224K1, 20, 224, "secp224k1" }, +#endif +#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED) + { POLARSSL_ECP_DP_SECP192R1, 19, 192, "secp192r1" }, +#endif +#if defined(POLARSSL_ECP_DP_SECP192K1_ENABLED) + { POLARSSL_ECP_DP_SECP192K1, 18, 192, "secp192k1" }, +#endif + { POLARSSL_ECP_DP_NONE, 0, 0, NULL }, +}; + +#define ECP_NB_CURVES sizeof( ecp_supported_curves ) / \ + sizeof( ecp_supported_curves[0] ) + +static ecp_group_id ecp_supported_grp_id[ECP_NB_CURVES]; + +/* + * List of supported curves and associated info + */ +const ecp_curve_info *ecp_curve_list( void ) +{ + return( ecp_supported_curves ); +} + +/* + * List of supported curves, group ID only + */ +const ecp_group_id *ecp_grp_id_list( void ) +{ + static int init_done = 0; + + if( ! init_done ) + { + size_t i = 0; + const ecp_curve_info *curve_info; + + for( curve_info = ecp_curve_list(); + curve_info->grp_id != POLARSSL_ECP_DP_NONE; + curve_info++ ) + { + ecp_supported_grp_id[i++] = curve_info->grp_id; + } + ecp_supported_grp_id[i] = POLARSSL_ECP_DP_NONE; + + init_done = 1; + } + + return( ecp_supported_grp_id ); +} + +/* + * Get the curve info for the internal identifier + */ +const ecp_curve_info *ecp_curve_info_from_grp_id( ecp_group_id grp_id ) +{ + const ecp_curve_info *curve_info; + + for( curve_info = ecp_curve_list(); + curve_info->grp_id != POLARSSL_ECP_DP_NONE; + curve_info++ ) + { + if( curve_info->grp_id == grp_id ) + return( curve_info ); + } + + return( NULL ); +} + +/* + * Get the curve info from the TLS identifier + */ +const ecp_curve_info *ecp_curve_info_from_tls_id( uint16_t tls_id ) +{ + const ecp_curve_info *curve_info; + + for( curve_info = ecp_curve_list(); + curve_info->grp_id != POLARSSL_ECP_DP_NONE; + curve_info++ ) + { + if( curve_info->tls_id == tls_id ) + return( curve_info ); + } + + return( NULL ); +} + +/* + * Get the curve info from the name + */ +const ecp_curve_info *ecp_curve_info_from_name( const char *name ) +{ + const ecp_curve_info *curve_info; + + for( curve_info = ecp_curve_list(); + curve_info->grp_id != POLARSSL_ECP_DP_NONE; + curve_info++ ) + { + if( strcasecmp( curve_info->name, name ) == 0 ) + return( curve_info ); + } + + return( NULL ); +} + +/* + * Get the type of a curve + */ +static inline ecp_curve_type ecp_get_type( const ecp_group *grp ) +{ + if( grp->G.X.p == NULL ) + return( POLARSSL_ECP_TYPE_NONE ); + + if( grp->G.Y.p == NULL ) + return( POLARSSL_ECP_TYPE_MONTGOMERY ); + else + return( POLARSSL_ECP_TYPE_SHORT_WEIERSTRASS ); +} + +/* + * Initialize (the components of) a point + */ +void ecp_point_init( ecp_point *pt ) +{ + if( pt == NULL ) + return; + + mpi_init( &pt->X ); + mpi_init( &pt->Y ); + mpi_init( &pt->Z ); +} + +/* + * Initialize (the components of) a group + */ +void ecp_group_init( ecp_group *grp ) +{ + if( grp == NULL ) + return; + + memset( grp, 0, sizeof( ecp_group ) ); +} + +/* + * Initialize (the components of) a key pair + */ +void ecp_keypair_init( ecp_keypair *key ) +{ + if( key == NULL ) + return; + + ecp_group_init( &key->grp ); + mpi_init( &key->d ); + ecp_point_init( &key->Q ); +} + +/* + * Unallocate (the components of) a point + */ +void ecp_point_free( ecp_point *pt ) +{ + if( pt == NULL ) + return; + + mpi_free( &( pt->X ) ); + mpi_free( &( pt->Y ) ); + mpi_free( &( pt->Z ) ); +} + +/* + * Unallocate (the components of) a group + */ +void ecp_group_free( ecp_group *grp ) +{ + size_t i; + + if( grp == NULL ) + return; + + if( grp->h != 1 ) + { + mpi_free( &grp->P ); + mpi_free( &grp->A ); + mpi_free( &grp->B ); + ecp_point_free( &grp->G ); + mpi_free( &grp->N ); + } + + if( grp->T != NULL ) + { + for( i = 0; i < grp->T_size; i++ ) + ecp_point_free( &grp->T[i] ); + polarssl_free( grp->T ); + } + + polarssl_zeroize( grp, sizeof( ecp_group ) ); +} + +/* + * Unallocate (the components of) a key pair + */ +void ecp_keypair_free( ecp_keypair *key ) +{ + if( key == NULL ) + return; + + ecp_group_free( &key->grp ); + mpi_free( &key->d ); + ecp_point_free( &key->Q ); +} + +/* + * Copy the contents of a point + */ +int ecp_copy( ecp_point *P, const ecp_point *Q ) +{ + int ret; + + MPI_CHK( mpi_copy( &P->X, &Q->X ) ); + MPI_CHK( mpi_copy( &P->Y, &Q->Y ) ); + MPI_CHK( mpi_copy( &P->Z, &Q->Z ) ); + +cleanup: + return( ret ); +} + +/* + * Copy the contents of a group object + */ +int ecp_group_copy( ecp_group *dst, const ecp_group *src ) +{ + return ecp_use_known_dp( dst, src->id ); +} + +/* + * Set point to zero + */ +int ecp_set_zero( ecp_point *pt ) +{ + int ret; + + MPI_CHK( mpi_lset( &pt->X , 1 ) ); + MPI_CHK( mpi_lset( &pt->Y , 1 ) ); + MPI_CHK( mpi_lset( &pt->Z , 0 ) ); + +cleanup: + return( ret ); +} + +/* + * Tell if a point is zero + */ +int ecp_is_zero( ecp_point *pt ) +{ + return( mpi_cmp_int( &pt->Z, 0 ) == 0 ); +} + +/* + * Import a non-zero point from ASCII strings + */ +int ecp_point_read_string( ecp_point *P, int radix, + const char *x, const char *y ) +{ + int ret; + + MPI_CHK( mpi_read_string( &P->X, radix, x ) ); + MPI_CHK( mpi_read_string( &P->Y, radix, y ) ); + MPI_CHK( mpi_lset( &P->Z, 1 ) ); + +cleanup: + return( ret ); +} + +/* + * Export a point into unsigned binary data (SEC1 2.3.3) + */ +int ecp_point_write_binary( const ecp_group *grp, const ecp_point *P, + int format, size_t *olen, + unsigned char *buf, size_t buflen ) +{ + int ret = 0; + size_t plen; + + if( format != POLARSSL_ECP_PF_UNCOMPRESSED && + format != POLARSSL_ECP_PF_COMPRESSED ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + /* + * Common case: P == 0 + */ + if( mpi_cmp_int( &P->Z, 0 ) == 0 ) + { + if( buflen < 1 ) + return( POLARSSL_ERR_ECP_BUFFER_TOO_SMALL ); + + buf[0] = 0x00; + *olen = 1; + + return( 0 ); + } + + plen = mpi_size( &grp->P ); + + if( format == POLARSSL_ECP_PF_UNCOMPRESSED ) + { + *olen = 2 * plen + 1; + + if( buflen < *olen ) + return( POLARSSL_ERR_ECP_BUFFER_TOO_SMALL ); + + buf[0] = 0x04; + MPI_CHK( mpi_write_binary( &P->X, buf + 1, plen ) ); + MPI_CHK( mpi_write_binary( &P->Y, buf + 1 + plen, plen ) ); + } + else if( format == POLARSSL_ECP_PF_COMPRESSED ) + { + *olen = plen + 1; + + if( buflen < *olen ) + return( POLARSSL_ERR_ECP_BUFFER_TOO_SMALL ); + + buf[0] = 0x02 + mpi_get_bit( &P->Y, 0 ); + MPI_CHK( mpi_write_binary( &P->X, buf + 1, plen ) ); + } + +cleanup: + return( ret ); +} + +/* + * Import a point from unsigned binary data (SEC1 2.3.4) + */ +int ecp_point_read_binary( const ecp_group *grp, ecp_point *pt, + const unsigned char *buf, size_t ilen ) +{ + int ret; + size_t plen; + + if ( ilen < 1 ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + if( buf[0] == 0x00 ) + { + if( ilen == 1 ) + return( ecp_set_zero( pt ) ); + else + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + } + + plen = mpi_size( &grp->P ); + + if( buf[0] != 0x04 ) + return( POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE ); + + if( ilen != 2 * plen + 1 ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + MPI_CHK( mpi_read_binary( &pt->X, buf + 1, plen ) ); + MPI_CHK( mpi_read_binary( &pt->Y, buf + 1 + plen, plen ) ); + MPI_CHK( mpi_lset( &pt->Z, 1 ) ); + +cleanup: + return( ret ); +} + +/* + * Import a point from a TLS ECPoint record (RFC 4492) + * struct { + * opaque point <1..2^8-1>; + * } ECPoint; + */ +int ecp_tls_read_point( const ecp_group *grp, ecp_point *pt, + const unsigned char **buf, size_t buf_len ) +{ + unsigned char data_len; + const unsigned char *buf_start; + + /* + * We must have at least two bytes (1 for length, at least one for data) + */ + if( buf_len < 2 ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + data_len = *(*buf)++; + if( data_len < 1 || data_len > buf_len - 1 ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + /* + * Save buffer start for read_binary and update buf + */ + buf_start = *buf; + *buf += data_len; + + return ecp_point_read_binary( grp, pt, buf_start, data_len ); +} + +/* + * Export a point as a TLS ECPoint record (RFC 4492) + * struct { + * opaque point <1..2^8-1>; + * } ECPoint; + */ +int ecp_tls_write_point( const ecp_group *grp, const ecp_point *pt, + int format, size_t *olen, + unsigned char *buf, size_t blen ) +{ + int ret; + + /* + * buffer length must be at least one, for our length byte + */ + if( blen < 1 ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = ecp_point_write_binary( grp, pt, format, + olen, buf + 1, blen - 1) ) != 0 ) + return( ret ); + + /* + * write length to the first byte and update total length + */ + buf[0] = (unsigned char) *olen; + ++*olen; + + return( 0 ); +} + +/* + * Import an ECP group from ASCII strings, case A == -3 + */ +int ecp_group_read_string( ecp_group *grp, int radix, + const char *p, const char *b, + const char *gx, const char *gy, const char *n) +{ + int ret; + + MPI_CHK( mpi_read_string( &grp->P, radix, p ) ); + MPI_CHK( mpi_read_string( &grp->B, radix, b ) ); + MPI_CHK( ecp_point_read_string( &grp->G, radix, gx, gy ) ); + MPI_CHK( mpi_read_string( &grp->N, radix, n ) ); + + grp->pbits = mpi_msb( &grp->P ); + grp->nbits = mpi_msb( &grp->N ); + +cleanup: + if( ret != 0 ) + ecp_group_free( grp ); + + return( ret ); +} + +/* + * Set a group from an ECParameters record (RFC 4492) + */ +int ecp_tls_read_group( ecp_group *grp, const unsigned char **buf, size_t len ) +{ + uint16_t tls_id; + const ecp_curve_info *curve_info; + + /* + * We expect at least three bytes (see below) + */ + if( len < 3 ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + /* + * First byte is curve_type; only named_curve is handled + */ + if( *(*buf)++ != POLARSSL_ECP_TLS_NAMED_CURVE ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + /* + * Next two bytes are the namedcurve value + */ + tls_id = *(*buf)++; + tls_id <<= 8; + tls_id |= *(*buf)++; + + if( ( curve_info = ecp_curve_info_from_tls_id( tls_id ) ) == NULL ) + return( POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE ); + + return ecp_use_known_dp( grp, curve_info->grp_id ); +} + +/* + * Write the ECParameters record corresponding to a group (RFC 4492) + */ +int ecp_tls_write_group( const ecp_group *grp, size_t *olen, + unsigned char *buf, size_t blen ) +{ + const ecp_curve_info *curve_info; + + if( ( curve_info = ecp_curve_info_from_grp_id( grp->id ) ) == NULL ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + /* + * We are going to write 3 bytes (see below) + */ + *olen = 3; + if( blen < *olen ) + return( POLARSSL_ERR_ECP_BUFFER_TOO_SMALL ); + + /* + * First byte is curve_type, always named_curve + */ + *buf++ = POLARSSL_ECP_TLS_NAMED_CURVE; + + /* + * Next two bytes are the namedcurve value + */ + buf[0] = curve_info->tls_id >> 8; + buf[1] = curve_info->tls_id & 0xFF; + + return( 0 ); +} + +/* + * Wrapper around fast quasi-modp functions, with fall-back to mpi_mod_mpi. + * See the documentation of struct ecp_group. + * + * This function is in the critial loop for ecp_mul, so pay attention to perf. + */ +static int ecp_modp( mpi *N, const ecp_group *grp ) +{ + int ret; + + if( grp->modp == NULL ) + return( mpi_mod_mpi( N, N, &grp->P ) ); + + /* N->s < 0 is a much faster test, which fails only if N is 0 */ + if( ( N->s < 0 && mpi_cmp_int( N, 0 ) != 0 ) || + mpi_msb( N ) > 2 * grp->pbits ) + { + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + } + + MPI_CHK( grp->modp( N ) ); + + /* N->s < 0 is a much faster test, which fails only if N is 0 */ + while( N->s < 0 && mpi_cmp_int( N, 0 ) != 0 ) + MPI_CHK( mpi_add_mpi( N, N, &grp->P ) ); + + while( mpi_cmp_mpi( N, &grp->P ) >= 0 ) + /* we known P, N and the result are positive */ + MPI_CHK( mpi_sub_abs( N, N, &grp->P ) ); + +cleanup: + return( ret ); +} + +/* + * Fast mod-p functions expect their argument to be in the 0..p^2 range. + * + * In order to guarantee that, we need to ensure that operands of + * mpi_mul_mpi are in the 0..p range. So, after each operation we will + * bring the result back to this range. + * + * The following macros are shortcuts for doing that. + */ + +/* + * Reduce a mpi mod p in-place, general case, to use after mpi_mul_mpi + */ +#if defined(POLARSSL_SELF_TEST) +#define INC_MUL_COUNT mul_count++; +#else +#define INC_MUL_COUNT +#endif + +#define MOD_MUL( N ) do { MPI_CHK( ecp_modp( &N, grp ) ); INC_MUL_COUNT } \ + while( 0 ) + +/* + * Reduce a mpi mod p in-place, to use after mpi_sub_mpi + * N->s < 0 is a very fast test, which fails only if N is 0 + */ +#define MOD_SUB( N ) \ + while( N.s < 0 && mpi_cmp_int( &N, 0 ) != 0 ) \ + MPI_CHK( mpi_add_mpi( &N, &N, &grp->P ) ) + +/* + * Reduce a mpi mod p in-place, to use after mpi_add_mpi and mpi_mul_int. + * We known P, N and the result are positive, so sub_abs is correct, and + * a bit faster. + */ +#define MOD_ADD( N ) \ + while( mpi_cmp_mpi( &N, &grp->P ) >= 0 ) \ + MPI_CHK( mpi_sub_abs( &N, &N, &grp->P ) ) + +#if defined(POLARSSL_ECP_SHORT_WEIERSTRASS) +/* + * For curves in short Weierstrass form, we do all the internal operations in + * Jacobian coordinates. + * + * For multiplication, we'll use a comb method with coutermeasueres against + * SPA, hence timing attacks. + */ + +/* + * Normalize jacobian coordinates so that Z == 0 || Z == 1 (GECC 3.2.1) + * Cost: 1N := 1I + 3M + 1S + */ +static int ecp_normalize_jac( const ecp_group *grp, ecp_point *pt ) +{ + int ret; + mpi Zi, ZZi; + + if( mpi_cmp_int( &pt->Z, 0 ) == 0 ) + return( 0 ); + + mpi_init( &Zi ); mpi_init( &ZZi ); + + /* + * X = X / Z^2 mod p + */ + MPI_CHK( mpi_inv_mod( &Zi, &pt->Z, &grp->P ) ); + MPI_CHK( mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi ); + MPI_CHK( mpi_mul_mpi( &pt->X, &pt->X, &ZZi ) ); MOD_MUL( pt->X ); + + /* + * Y = Y / Z^3 mod p + */ + MPI_CHK( mpi_mul_mpi( &pt->Y, &pt->Y, &ZZi ) ); MOD_MUL( pt->Y ); + MPI_CHK( mpi_mul_mpi( &pt->Y, &pt->Y, &Zi ) ); MOD_MUL( pt->Y ); + + /* + * Z = 1 + */ + MPI_CHK( mpi_lset( &pt->Z, 1 ) ); + +cleanup: + + mpi_free( &Zi ); mpi_free( &ZZi ); + + return( ret ); +} + +/* + * Normalize jacobian coordinates of an array of (pointers to) points, + * using Montgomery's trick to perform only one inversion mod P. + * (See for example Cohen's "A Course in Computational Algebraic Number + * Theory", Algorithm 10.3.4.) + * + * Warning: fails (returning an error) if one of the points is zero! + * This should never happen, see choice of w in ecp_mul_comb(). + * + * Cost: 1N(t) := 1I + (6t - 3)M + 1S + */ +static int ecp_normalize_jac_many( const ecp_group *grp, + ecp_point *T[], size_t t_len ) +{ + int ret; + size_t i; + mpi *c, u, Zi, ZZi; + + if( t_len < 2 ) + return( ecp_normalize_jac( grp, *T ) ); + + if( ( c = (mpi *) polarssl_malloc( t_len * sizeof( mpi ) ) ) == NULL ) + return( POLARSSL_ERR_ECP_MALLOC_FAILED ); + + mpi_init( &u ); mpi_init( &Zi ); mpi_init( &ZZi ); + for( i = 0; i < t_len; i++ ) + mpi_init( &c[i] ); + + /* + * c[i] = Z_0 * ... * Z_i + */ + MPI_CHK( mpi_copy( &c[0], &T[0]->Z ) ); + for( i = 1; i < t_len; i++ ) + { + MPI_CHK( mpi_mul_mpi( &c[i], &c[i-1], &T[i]->Z ) ); + MOD_MUL( c[i] ); + } + + /* + * u = 1 / (Z_0 * ... * Z_n) mod P + */ + MPI_CHK( mpi_inv_mod( &u, &c[t_len-1], &grp->P ) ); + + for( i = t_len - 1; ; i-- ) + { + /* + * Zi = 1 / Z_i mod p + * u = 1 / (Z_0 * ... * Z_i) mod P + */ + if( i == 0 ) { + MPI_CHK( mpi_copy( &Zi, &u ) ); + } + else + { + MPI_CHK( mpi_mul_mpi( &Zi, &u, &c[i-1] ) ); MOD_MUL( Zi ); + MPI_CHK( mpi_mul_mpi( &u, &u, &T[i]->Z ) ); MOD_MUL( u ); + } + + /* + * proceed as in normalize() + */ + MPI_CHK( mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi ); + MPI_CHK( mpi_mul_mpi( &T[i]->X, &T[i]->X, &ZZi ) ); MOD_MUL( T[i]->X ); + MPI_CHK( mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &ZZi ) ); MOD_MUL( T[i]->Y ); + MPI_CHK( mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &Zi ) ); MOD_MUL( T[i]->Y ); + + /* + * Post-precessing: reclaim some memory by shrinking coordinates + * - not storing Z (always 1) + * - shrinking other coordinates, but still keeping the same number of + * limbs as P, as otherwise it will too likely be regrown too fast. + */ + MPI_CHK( mpi_shrink( &T[i]->X, grp->P.n ) ); + MPI_CHK( mpi_shrink( &T[i]->Y, grp->P.n ) ); + mpi_free( &T[i]->Z ); + + if( i == 0 ) + break; + } + +cleanup: + + mpi_free( &u ); mpi_free( &Zi ); mpi_free( &ZZi ); + for( i = 0; i < t_len; i++ ) + mpi_free( &c[i] ); + polarssl_free( c ); + + return( ret ); +} + +/* + * Conditional point inversion: Q -> -Q = (Q.X, -Q.Y, Q.Z) without leak. + * "inv" must be 0 (don't invert) or 1 (invert) or the result will be invalid + */ +static int ecp_safe_invert_jac( const ecp_group *grp, + ecp_point *Q, + unsigned char inv ) +{ + int ret; + unsigned char nonzero; + mpi mQY; + + mpi_init( &mQY ); + + /* Use the fact that -Q.Y mod P = P - Q.Y unless Q.Y == 0 */ + MPI_CHK( mpi_sub_mpi( &mQY, &grp->P, &Q->Y ) ); + nonzero = mpi_cmp_int( &Q->Y, 0 ) != 0; + MPI_CHK( mpi_safe_cond_assign( &Q->Y, &mQY, inv & nonzero ) ); + +cleanup: + mpi_free( &mQY ); + + return( ret ); +} + +/* + * Point doubling R = 2 P, Jacobian coordinates + * + * http://www.hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian/doubling/dbl-2007-bl.op3 + * with heavy variable renaming, some reordering and one minor modification + * (a = 2 * b, c = d - 2a replaced with c = d, c = c - b, c = c - b) + * in order to use a lot less intermediate variables (6 vs 25). + * + * Cost: 1D := 2M + 8S + */ +static int ecp_double_jac( const ecp_group *grp, ecp_point *R, + const ecp_point *P ) +{ + int ret; + mpi T1, T2, T3, X3, Y3, Z3; + +#if defined(POLARSSL_SELF_TEST) + dbl_count++; +#endif + + mpi_init( &T1 ); mpi_init( &T2 ); mpi_init( &T3 ); + mpi_init( &X3 ); mpi_init( &Y3 ); mpi_init( &Z3 ); + + MPI_CHK( mpi_mul_mpi( &T3, &P->X, &P->X ) ); MOD_MUL( T3 ); + MPI_CHK( mpi_mul_mpi( &T2, &P->Y, &P->Y ) ); MOD_MUL( T2 ); + MPI_CHK( mpi_mul_mpi( &Y3, &T2, &T2 ) ); MOD_MUL( Y3 ); + MPI_CHK( mpi_add_mpi( &X3, &P->X, &T2 ) ); MOD_ADD( X3 ); + MPI_CHK( mpi_mul_mpi( &X3, &X3, &X3 ) ); MOD_MUL( X3 ); + MPI_CHK( mpi_sub_mpi( &X3, &X3, &Y3 ) ); MOD_SUB( X3 ); + MPI_CHK( mpi_sub_mpi( &X3, &X3, &T3 ) ); MOD_SUB( X3 ); + MPI_CHK( mpi_mul_int( &T1, &X3, 2 ) ); MOD_ADD( T1 ); + MPI_CHK( mpi_mul_mpi( &Z3, &P->Z, &P->Z ) ); MOD_MUL( Z3 ); + MPI_CHK( mpi_mul_mpi( &X3, &Z3, &Z3 ) ); MOD_MUL( X3 ); + MPI_CHK( mpi_mul_int( &T3, &T3, 3 ) ); MOD_ADD( T3 ); + + /* Special case for A = -3 */ + if( grp->A.p == NULL ) + { + MPI_CHK( mpi_mul_int( &X3, &X3, 3 ) ); + X3.s = -1; /* mpi_mul_int doesn't handle negative numbers */ + MOD_SUB( X3 ); + } + else + MPI_CHK( mpi_mul_mpi( &X3, &X3, &grp->A ) ); MOD_MUL( X3 ); + + MPI_CHK( mpi_add_mpi( &T3, &T3, &X3 ) ); MOD_ADD( T3 ); + MPI_CHK( mpi_mul_mpi( &X3, &T3, &T3 ) ); MOD_MUL( X3 ); + MPI_CHK( mpi_sub_mpi( &X3, &X3, &T1 ) ); MOD_SUB( X3 ); + MPI_CHK( mpi_sub_mpi( &X3, &X3, &T1 ) ); MOD_SUB( X3 ); + MPI_CHK( mpi_sub_mpi( &T1, &T1, &X3 ) ); MOD_SUB( T1 ); + MPI_CHK( mpi_mul_mpi( &T1, &T3, &T1 ) ); MOD_MUL( T1 ); + MPI_CHK( mpi_mul_int( &T3, &Y3, 8 ) ); MOD_ADD( T3 ); + MPI_CHK( mpi_sub_mpi( &Y3, &T1, &T3 ) ); MOD_SUB( Y3 ); + MPI_CHK( mpi_add_mpi( &T1, &P->Y, &P->Z ) ); MOD_ADD( T1 ); + MPI_CHK( mpi_mul_mpi( &T1, &T1, &T1 ) ); MOD_MUL( T1 ); + MPI_CHK( mpi_sub_mpi( &T1, &T1, &T2 ) ); MOD_SUB( T1 ); + MPI_CHK( mpi_sub_mpi( &Z3, &T1, &Z3 ) ); MOD_SUB( Z3 ); + + MPI_CHK( mpi_copy( &R->X, &X3 ) ); + MPI_CHK( mpi_copy( &R->Y, &Y3 ) ); + MPI_CHK( mpi_copy( &R->Z, &Z3 ) ); + +cleanup: + mpi_free( &T1 ); mpi_free( &T2 ); mpi_free( &T3 ); + mpi_free( &X3 ); mpi_free( &Y3 ); mpi_free( &Z3 ); + + return( ret ); +} + +/* + * Addition: R = P + Q, mixed affine-Jacobian coordinates (GECC 3.22) + * + * The coordinates of Q must be normalized (= affine), + * but those of P don't need to. R is not normalized. + * + * Special cases: (1) P or Q is zero, (2) R is zero, (3) P == Q. + * None of these cases can happen as intermediate step in ecp_mul_comb(): + * - at each step, P, Q and R are multiples of the base point, the factor + * being less than its order, so none of them is zero; + * - Q is an odd multiple of the base point, P an even multiple, + * due to the choice of precomputed points in the modified comb method. + * So branches for these cases do not leak secret information. + * + * We accept Q->Z being unset (saving memory in tables) as meaning 1. + * + * Cost: 1A := 8M + 3S + */ +static int ecp_add_mixed( const ecp_group *grp, ecp_point *R, + const ecp_point *P, const ecp_point *Q ) +{ + int ret; + mpi T1, T2, T3, T4, X, Y, Z; + +#if defined(POLARSSL_SELF_TEST) + add_count++; +#endif + + /* + * Trivial cases: P == 0 or Q == 0 (case 1) + */ + if( mpi_cmp_int( &P->Z, 0 ) == 0 ) + return( ecp_copy( R, Q ) ); + + if( Q->Z.p != NULL && mpi_cmp_int( &Q->Z, 0 ) == 0 ) + return( ecp_copy( R, P ) ); + + /* + * Make sure Q coordinates are normalized + */ + if( Q->Z.p != NULL && mpi_cmp_int( &Q->Z, 1 ) != 0 ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + mpi_init( &T1 ); mpi_init( &T2 ); mpi_init( &T3 ); mpi_init( &T4 ); + mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z ); + + MPI_CHK( mpi_mul_mpi( &T1, &P->Z, &P->Z ) ); MOD_MUL( T1 ); + MPI_CHK( mpi_mul_mpi( &T2, &T1, &P->Z ) ); MOD_MUL( T2 ); + MPI_CHK( mpi_mul_mpi( &T1, &T1, &Q->X ) ); MOD_MUL( T1 ); + MPI_CHK( mpi_mul_mpi( &T2, &T2, &Q->Y ) ); MOD_MUL( T2 ); + MPI_CHK( mpi_sub_mpi( &T1, &T1, &P->X ) ); MOD_SUB( T1 ); + MPI_CHK( mpi_sub_mpi( &T2, &T2, &P->Y ) ); MOD_SUB( T2 ); + + /* Special cases (2) and (3) */ + if( mpi_cmp_int( &T1, 0 ) == 0 ) + { + if( mpi_cmp_int( &T2, 0 ) == 0 ) + { + ret = ecp_double_jac( grp, R, P ); + goto cleanup; + } + else + { + ret = ecp_set_zero( R ); + goto cleanup; + } + } + + MPI_CHK( mpi_mul_mpi( &Z, &P->Z, &T1 ) ); MOD_MUL( Z ); + MPI_CHK( mpi_mul_mpi( &T3, &T1, &T1 ) ); MOD_MUL( T3 ); + MPI_CHK( mpi_mul_mpi( &T4, &T3, &T1 ) ); MOD_MUL( T4 ); + MPI_CHK( mpi_mul_mpi( &T3, &T3, &P->X ) ); MOD_MUL( T3 ); + MPI_CHK( mpi_mul_int( &T1, &T3, 2 ) ); MOD_ADD( T1 ); + MPI_CHK( mpi_mul_mpi( &X, &T2, &T2 ) ); MOD_MUL( X ); + MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) ); MOD_SUB( X ); + MPI_CHK( mpi_sub_mpi( &X, &X, &T4 ) ); MOD_SUB( X ); + MPI_CHK( mpi_sub_mpi( &T3, &T3, &X ) ); MOD_SUB( T3 ); + MPI_CHK( mpi_mul_mpi( &T3, &T3, &T2 ) ); MOD_MUL( T3 ); + MPI_CHK( mpi_mul_mpi( &T4, &T4, &P->Y ) ); MOD_MUL( T4 ); + MPI_CHK( mpi_sub_mpi( &Y, &T3, &T4 ) ); MOD_SUB( Y ); + + MPI_CHK( mpi_copy( &R->X, &X ) ); + MPI_CHK( mpi_copy( &R->Y, &Y ) ); + MPI_CHK( mpi_copy( &R->Z, &Z ) ); + +cleanup: + + mpi_free( &T1 ); mpi_free( &T2 ); mpi_free( &T3 ); mpi_free( &T4 ); + mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z ); + + return( ret ); +} + +/* + * Addition: R = P + Q, result's coordinates normalized + */ +int ecp_add( const ecp_group *grp, ecp_point *R, + const ecp_point *P, const ecp_point *Q ) +{ + int ret; + + if( ecp_get_type( grp ) != POLARSSL_ECP_TYPE_SHORT_WEIERSTRASS ) + return( POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE ); + + MPI_CHK( ecp_add_mixed( grp, R, P, Q ) ); + MPI_CHK( ecp_normalize_jac( grp, R ) ); + +cleanup: + return( ret ); +} + +/* + * Subtraction: R = P - Q, result's coordinates normalized + */ +int ecp_sub( const ecp_group *grp, ecp_point *R, + const ecp_point *P, const ecp_point *Q ) +{ + int ret; + ecp_point mQ; + + ecp_point_init( &mQ ); + + if( ecp_get_type( grp ) != POLARSSL_ECP_TYPE_SHORT_WEIERSTRASS ) + return( POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE ); + + /* mQ = - Q */ + MPI_CHK( ecp_copy( &mQ, Q ) ); + if( mpi_cmp_int( &mQ.Y, 0 ) != 0 ) + MPI_CHK( mpi_sub_mpi( &mQ.Y, &grp->P, &mQ.Y ) ); + + MPI_CHK( ecp_add_mixed( grp, R, P, &mQ ) ); + MPI_CHK( ecp_normalize_jac( grp, R ) ); + +cleanup: + ecp_point_free( &mQ ); + + return( ret ); +} + +/* + * Randomize jacobian coordinates: + * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l + * This is sort of the reverse operation of ecp_normalize_jac(). + * + * This countermeasure was first suggested in [2]. + */ +static int ecp_randomize_jac( const ecp_group *grp, ecp_point *pt, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret; + mpi l, ll; + size_t p_size = ( grp->pbits + 7 ) / 8; + int count = 0; + + mpi_init( &l ); mpi_init( &ll ); + + /* Generate l such that 1 < l < p */ + do + { + mpi_fill_random( &l, p_size, f_rng, p_rng ); + + while( mpi_cmp_mpi( &l, &grp->P ) >= 0 ) + MPI_CHK( mpi_shift_r( &l, 1 ) ); + + if( count++ > 10 ) + return( POLARSSL_ERR_ECP_RANDOM_FAILED ); + } + while( mpi_cmp_int( &l, 1 ) <= 0 ); + + /* Z = l * Z */ + MPI_CHK( mpi_mul_mpi( &pt->Z, &pt->Z, &l ) ); MOD_MUL( pt->Z ); + + /* X = l^2 * X */ + MPI_CHK( mpi_mul_mpi( &ll, &l, &l ) ); MOD_MUL( ll ); + MPI_CHK( mpi_mul_mpi( &pt->X, &pt->X, &ll ) ); MOD_MUL( pt->X ); + + /* Y = l^3 * Y */ + MPI_CHK( mpi_mul_mpi( &ll, &ll, &l ) ); MOD_MUL( ll ); + MPI_CHK( mpi_mul_mpi( &pt->Y, &pt->Y, &ll ) ); MOD_MUL( pt->Y ); + +cleanup: + mpi_free( &l ); mpi_free( &ll ); + + return( ret ); +} + +/* + * Check and define parameters used by the comb method (see below for details) + */ +#if POLARSSL_ECP_WINDOW_SIZE < 2 || POLARSSL_ECP_WINDOW_SIZE > 7 +#error "POLARSSL_ECP_WINDOW_SIZE out of bounds" +#endif + +/* d = ceil( n / w ) */ +#define COMB_MAX_D ( POLARSSL_ECP_MAX_BITS + 1 ) / 2 + +/* number of precomputed points */ +#define COMB_MAX_PRE ( 1 << ( POLARSSL_ECP_WINDOW_SIZE - 1 ) ) + +/* + * Compute the representation of m that will be used with our comb method. + * + * The basic comb method is described in GECC 3.44 for example. We use a + * modified version that provides resistance to SPA by avoiding zero + * digits in the representation as in [3]. We modify the method further by + * requiring that all K_i be odd, which has the small cost that our + * representation uses one more K_i, due to carries. + * + * Also, for the sake of compactness, only the seven low-order bits of x[i] + * are used to represent K_i, and the msb of x[i] encodes the the sign (s_i in + * the paper): it is set if and only if if s_i == -1; + * + * Calling conventions: + * - x is an array of size d + 1 + * - w is the size, ie number of teeth, of the comb, and must be between + * 2 and 7 (in practice, between 2 and POLARSSL_ECP_WINDOW_SIZE) + * - m is the MPI, expected to be odd and such that bitlength(m) <= w * d + * (the result will be incorrect if these assumptions are not satisfied) + */ +static void ecp_comb_fixed( unsigned char x[], size_t d, + unsigned char w, const mpi *m ) +{ + size_t i, j; + unsigned char c, cc, adjust; + + memset( x, 0, d+1 ); + + /* First get the classical comb values (except for x_d = 0) */ + for( i = 0; i < d; i++ ) + for( j = 0; j < w; j++ ) + x[i] |= mpi_get_bit( m, i + d * j ) << j; + + /* Now make sure x_1 .. x_d are odd */ + c = 0; + for( i = 1; i <= d; i++ ) + { + /* Add carry and update it */ + cc = x[i] & c; + x[i] = x[i] ^ c; + c = cc; + + /* Adjust if needed, avoiding branches */ + adjust = 1 - ( x[i] & 0x01 ); + c |= x[i] & ( x[i-1] * adjust ); + x[i] = x[i] ^ ( x[i-1] * adjust ); + x[i-1] |= adjust << 7; + } +} + +/* + * Precompute points for the comb method + * + * If i = i_{w-1} ... i_1 is the binary representation of i, then + * T[i] = i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + P + * + * T must be able to hold 2^{w - 1} elements + * + * Cost: d(w-1) D + (2^{w-1} - 1) A + 1 N(w-1) + 1 N(2^{w-1} - 1) + */ +static int ecp_precompute_comb( const ecp_group *grp, + ecp_point T[], const ecp_point *P, + unsigned char w, size_t d ) +{ + int ret; + unsigned char i, k; + size_t j; + ecp_point *cur, *TT[COMB_MAX_PRE - 1]; + + /* + * Set T[0] = P and + * T[2^{l-1}] = 2^{dl} P for l = 1 .. w-1 (this is not the final value) + */ + MPI_CHK( ecp_copy( &T[0], P ) ); + + k = 0; + for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 ) + { + cur = T + i; + MPI_CHK( ecp_copy( cur, T + ( i >> 1 ) ) ); + for( j = 0; j < d; j++ ) + MPI_CHK( ecp_double_jac( grp, cur, cur ) ); + + TT[k++] = cur; + } + + MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) ); + + /* + * Compute the remaining ones using the minimal number of additions + * Be careful to update T[2^l] only after using it! + */ + k = 0; + for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 ) + { + j = i; + while( j-- ) + { + MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) ); + TT[k++] = &T[i + j]; + } + } + + MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) ); + +cleanup: + return( ret ); +} + +/* + * Select precomputed point: R = sign(i) * T[ abs(i) / 2 ] + */ +static int ecp_select_comb( const ecp_group *grp, ecp_point *R, + const ecp_point T[], unsigned char t_len, + unsigned char i ) +{ + int ret; + unsigned char ii, j; + + /* Ignore the "sign" bit and scale down */ + ii = ( i & 0x7Fu ) >> 1; + + /* Read the whole table to thwart cache-based timing attacks */ + for( j = 0; j < t_len; j++ ) + { + MPI_CHK( mpi_safe_cond_assign( &R->X, &T[j].X, j == ii ) ); + MPI_CHK( mpi_safe_cond_assign( &R->Y, &T[j].Y, j == ii ) ); + } + + /* Safely invert result if i is "negative" */ + MPI_CHK( ecp_safe_invert_jac( grp, R, i >> 7 ) ); + +cleanup: + return( ret ); +} + +/* + * Core multiplication algorithm for the (modified) comb method. + * This part is actually common with the basic comb method (GECC 3.44) + * + * Cost: d A + d D + 1 R + */ +static int ecp_mul_comb_core( const ecp_group *grp, ecp_point *R, + const ecp_point T[], unsigned char t_len, + const unsigned char x[], size_t d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + ecp_point Txi; + size_t i; + + ecp_point_init( &Txi ); + + /* Start with a non-zero point and randomize its coordinates */ + i = d; + MPI_CHK( ecp_select_comb( grp, R, T, t_len, x[i] ) ); + MPI_CHK( mpi_lset( &R->Z, 1 ) ); + if( f_rng != 0 ) + MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) ); + + while( i-- != 0 ) + { + MPI_CHK( ecp_double_jac( grp, R, R ) ); + MPI_CHK( ecp_select_comb( grp, &Txi, T, t_len, x[i] ) ); + MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) ); + } + +cleanup: + ecp_point_free( &Txi ); + + return( ret ); +} + +/* + * Multiplication using the comb method, + * for curves in short Weierstrass form + */ +static int ecp_mul_comb( ecp_group *grp, ecp_point *R, + const mpi *m, const ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + unsigned char w, m_is_odd, p_eq_g, pre_len, i; + size_t d; + unsigned char k[COMB_MAX_D + 1]; + ecp_point *T; + mpi M, mm; + + mpi_init( &M ); + mpi_init( &mm ); + + /* we need N to be odd to trnaform m in an odd number, check now */ + if( mpi_get_bit( &grp->N, 0 ) != 1 ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + /* + * Minimize the number of multiplications, that is minimize + * 10 * d * w + 18 * 2^(w-1) + 11 * d + 7 * w, with d = ceil( nbits / w ) + * (see costs of the various parts, with 1S = 1M) + */ + w = grp->nbits >= 384 ? 5 : 4; + + /* + * If P == G, pre-compute a bit more, since this may be re-used later. + * Just adding one avoids upping the cost of the first mul too much, + * and the memory cost too. + */ +#if POLARSSL_ECP_FIXED_POINT_OPTIM == 1 + p_eq_g = ( mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 && + mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 ); + if( p_eq_g ) + w++; +#else + p_eq_g = 0; +#endif + + /* + * Make sure w is within bounds. + * (The last test is useful only for very small curves in the test suite.) + */ + if( w > POLARSSL_ECP_WINDOW_SIZE ) + w = POLARSSL_ECP_WINDOW_SIZE; + if( w >= grp->nbits ) + w = 2; + + /* Other sizes that depend on w */ + pre_len = 1U << ( w - 1 ); + d = ( grp->nbits + w - 1 ) / w; + + /* + * Prepare precomputed points: if P == G we want to + * use grp->T if already initialized, or initialize it. + */ + T = p_eq_g ? grp->T : NULL; + + if( T == NULL ) + { + T = (ecp_point *) polarssl_malloc( pre_len * sizeof( ecp_point ) ); + if( T == NULL ) + { + ret = POLARSSL_ERR_ECP_MALLOC_FAILED; + goto cleanup; + } + + for( i = 0; i < pre_len; i++ ) + ecp_point_init( &T[i] ); + + MPI_CHK( ecp_precompute_comb( grp, T, P, w, d ) ); + + if( p_eq_g ) + { + grp->T = T; + grp->T_size = pre_len; + } + } + + /* + * Make sure M is odd (M = m or M = N - m, since N is odd) + * using the fact that m * P = - (N - m) * P + */ + m_is_odd = ( mpi_get_bit( m, 0 ) == 1 ); + MPI_CHK( mpi_copy( &M, m ) ); + MPI_CHK( mpi_sub_mpi( &mm, &grp->N, m ) ); + MPI_CHK( mpi_safe_cond_assign( &M, &mm, ! m_is_odd ) ); + + /* + * Go for comb multiplication, R = M * P + */ + ecp_comb_fixed( k, d, w, &M ); + MPI_CHK( ecp_mul_comb_core( grp, R, T, pre_len, k, d, f_rng, p_rng ) ); + + /* + * Now get m * P from M * P and normalize it + */ + MPI_CHK( ecp_safe_invert_jac( grp, R, ! m_is_odd ) ); + MPI_CHK( ecp_normalize_jac( grp, R ) ); + +cleanup: + + if( T != NULL && ! p_eq_g ) + { + for( i = 0; i < pre_len; i++ ) + ecp_point_free( &T[i] ); + polarssl_free( T ); + } + + mpi_free( &M ); + mpi_free( &mm ); + + if( ret != 0 ) + ecp_point_free( R ); + + return( ret ); +} + +#endif /* POLARSSL_ECP_SHORT_WEIERSTRASS */ + +#if defined(POLARSSL_ECP_MONTGOMERY) +/* + * For Montgomery curves, we do all the internal arithmetic in projective + * coordinates. Import/export of points uses only the x coordinates, which is + * internaly represented as X / Z. + * + * For scalar multiplication, we'll use a Montgomery ladder. + */ + +/* + * Normalize Montgomery x/z coordinates: X = X/Z, Z = 1 + * Cost: 1M + 1I + */ +static int ecp_normalize_mxz( const ecp_group *grp, ecp_point *P ) +{ + int ret; + + MPI_CHK( mpi_inv_mod( &P->Z, &P->Z, &grp->P ) ); + MPI_CHK( mpi_mul_mpi( &P->X, &P->X, &P->Z ) ); MOD_MUL( P->X ); + MPI_CHK( mpi_lset( &P->Z, 1 ) ); + +cleanup: + return( ret ); +} + +/* + * Randomize projective x/z coordinates: + * (X, Z) -> (l X, l Z) for random l + * This is sort of the reverse operation of ecp_normalize_mxz(). + * + * This countermeasure was first suggested in [2]. + * Cost: 2M + */ +static int ecp_randomize_mxz( const ecp_group *grp, ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret; + mpi l; + size_t p_size = ( grp->pbits + 7 ) / 8; + int count = 0; + + mpi_init( &l ); + + /* Generate l such that 1 < l < p */ + do + { + mpi_fill_random( &l, p_size, f_rng, p_rng ); + + while( mpi_cmp_mpi( &l, &grp->P ) >= 0 ) + MPI_CHK( mpi_shift_r( &l, 1 ) ); + + if( count++ > 10 ) + return( POLARSSL_ERR_ECP_RANDOM_FAILED ); + } + while( mpi_cmp_int( &l, 1 ) <= 0 ); + + MPI_CHK( mpi_mul_mpi( &P->X, &P->X, &l ) ); MOD_MUL( P->X ); + MPI_CHK( mpi_mul_mpi( &P->Z, &P->Z, &l ) ); MOD_MUL( P->Z ); + +cleanup: + mpi_free( &l ); + + return( ret ); +} + +/* + * Double-and-add: R = 2P, S = P + Q, with d = X(P - Q), + * for Montgomery curves in x/z coordinates. + * + * http://www.hyperelliptic.org/EFD/g1p/auto-code/montgom/xz/ladder/mladd-1987-m.op3 + * with + * d = X1 + * P = (X2, Z2) + * Q = (X3, Z3) + * R = (X4, Z4) + * S = (X5, Z5) + * and eliminating temporary variables tO, ..., t4. + * + * Cost: 5M + 4S + */ +static int ecp_double_add_mxz( const ecp_group *grp, + ecp_point *R, ecp_point *S, + const ecp_point *P, const ecp_point *Q, + const mpi *d ) +{ + int ret; + mpi A, AA, B, BB, E, C, D, DA, CB; + + mpi_init( &A ); mpi_init( &AA ); mpi_init( &B ); + mpi_init( &BB ); mpi_init( &E ); mpi_init( &C ); + mpi_init( &D ); mpi_init( &DA ); mpi_init( &CB ); + + MPI_CHK( mpi_add_mpi( &A, &P->X, &P->Z ) ); MOD_ADD( A ); + MPI_CHK( mpi_mul_mpi( &AA, &A, &A ) ); MOD_MUL( AA ); + MPI_CHK( mpi_sub_mpi( &B, &P->X, &P->Z ) ); MOD_SUB( B ); + MPI_CHK( mpi_mul_mpi( &BB, &B, &B ) ); MOD_MUL( BB ); + MPI_CHK( mpi_sub_mpi( &E, &AA, &BB ) ); MOD_SUB( E ); + MPI_CHK( mpi_add_mpi( &C, &Q->X, &Q->Z ) ); MOD_ADD( C ); + MPI_CHK( mpi_sub_mpi( &D, &Q->X, &Q->Z ) ); MOD_SUB( D ); + MPI_CHK( mpi_mul_mpi( &DA, &D, &A ) ); MOD_MUL( DA ); + MPI_CHK( mpi_mul_mpi( &CB, &C, &B ) ); MOD_MUL( CB ); + MPI_CHK( mpi_add_mpi( &S->X, &DA, &CB ) ); MOD_MUL( S->X ); + MPI_CHK( mpi_mul_mpi( &S->X, &S->X, &S->X ) ); MOD_MUL( S->X ); + MPI_CHK( mpi_sub_mpi( &S->Z, &DA, &CB ) ); MOD_SUB( S->Z ); + MPI_CHK( mpi_mul_mpi( &S->Z, &S->Z, &S->Z ) ); MOD_MUL( S->Z ); + MPI_CHK( mpi_mul_mpi( &S->Z, d, &S->Z ) ); MOD_MUL( S->Z ); + MPI_CHK( mpi_mul_mpi( &R->X, &AA, &BB ) ); MOD_MUL( R->X ); + MPI_CHK( mpi_mul_mpi( &R->Z, &grp->A, &E ) ); MOD_MUL( R->Z ); + MPI_CHK( mpi_add_mpi( &R->Z, &BB, &R->Z ) ); MOD_ADD( R->Z ); + MPI_CHK( mpi_mul_mpi( &R->Z, &E, &R->Z ) ); MOD_MUL( R->Z ); + +cleanup: + mpi_free( &A ); mpi_free( &AA ); mpi_free( &B ); + mpi_free( &BB ); mpi_free( &E ); mpi_free( &C ); + mpi_free( &D ); mpi_free( &DA ); mpi_free( &CB ); + + return( ret ); +} + +/* + * Multiplication with Montgomery ladder in x/z coordinates, + * for curves in Montgomery form + */ +static int ecp_mul_mxz( ecp_group *grp, ecp_point *R, + const mpi *m, const ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + size_t i; + unsigned char b; + ecp_point RP; + mpi PX; + + ecp_point_init( &RP ); mpi_init( &PX ); + + /* Save PX and read from P before writing to R, in case P == R */ + MPI_CHK( mpi_copy( &PX, &P->X ) ); + MPI_CHK( ecp_copy( &RP, P ) ); + + /* Set R to zero in modified x/z coordinates */ + MPI_CHK( mpi_lset( &R->X, 1 ) ); + MPI_CHK( mpi_lset( &R->Z, 0 ) ); + mpi_free( &R->Y ); + + /* RP.X might be sligtly larger than P, so reduce it */ + MOD_ADD( RP.X ); + + /* Randomize coordinates of the starting point */ + if( f_rng != NULL ) + MPI_CHK( ecp_randomize_mxz( grp, &RP, f_rng, p_rng ) ); + + /* Loop invariant: R = result so far, RP = R + P */ + i = mpi_msb( m ); /* one past the (zero-based) most significant bit */ + while( i-- > 0 ) + { + b = mpi_get_bit( m, i ); + /* + * if (b) R = 2R + P else R = 2R, + * which is: + * if (b) double_add( RP, R, RP, R ) + * else double_add( R, RP, R, RP ) + * but using safe conditional swaps to avoid leaks + */ + MPI_CHK( mpi_safe_cond_swap( &R->X, &RP.X, b ) ); + MPI_CHK( mpi_safe_cond_swap( &R->Z, &RP.Z, b ) ); + MPI_CHK( ecp_double_add_mxz( grp, R, &RP, R, &RP, &PX ) ); + MPI_CHK( mpi_safe_cond_swap( &R->X, &RP.X, b ) ); + MPI_CHK( mpi_safe_cond_swap( &R->Z, &RP.Z, b ) ); + } + + MPI_CHK( ecp_normalize_mxz( grp, R ) ); + +cleanup: + ecp_point_free( &RP ); mpi_free( &PX ); + + return( ret ); +} + +#endif /* POLARSSL_ECP_MONTGOMERY */ + +/* + * Multiplication R = m * P + */ +int ecp_mul( ecp_group *grp, ecp_point *R, + const mpi *m, const ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret; + + /* Common sanity checks */ + if( mpi_cmp_int( &P->Z, 1 ) != 0 ) + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = ecp_check_privkey( grp, m ) ) != 0 || + ( ret = ecp_check_pubkey( grp, P ) ) != 0 ) + return( ret ); + +#if defined(POLARSSL_ECP_MONTGOMERY) + if( ecp_get_type( grp ) == POLARSSL_ECP_TYPE_MONTGOMERY ) + return( ecp_mul_mxz( grp, R, m, P, f_rng, p_rng ) ); +#endif +#if defined(POLARSSL_ECP_SHORT_WEIERSTRASS) + if( ecp_get_type( grp ) == POLARSSL_ECP_TYPE_SHORT_WEIERSTRASS ) + return( ecp_mul_comb( grp, R, m, P, f_rng, p_rng ) ); +#endif + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); +} + +#if defined(POLARSSL_ECP_SHORT_WEIERSTRASS) +/* + * Check that an affine point is valid as a public key, + * short weierstrass curves (SEC1 3.2.3.1) + */ +static int ecp_check_pubkey_sw( const ecp_group *grp, const ecp_point *pt ) +{ + int ret; + mpi YY, RHS; + + /* pt coordinates must be normalized for our checks */ + if( mpi_cmp_int( &pt->X, 0 ) < 0 || + mpi_cmp_int( &pt->Y, 0 ) < 0 || + mpi_cmp_mpi( &pt->X, &grp->P ) >= 0 || + mpi_cmp_mpi( &pt->Y, &grp->P ) >= 0 ) + return( POLARSSL_ERR_ECP_INVALID_KEY ); + + mpi_init( &YY ); mpi_init( &RHS ); + + /* + * YY = Y^2 + * RHS = X (X^2 + A) + B = X^3 + A X + B + */ + MPI_CHK( mpi_mul_mpi( &YY, &pt->Y, &pt->Y ) ); MOD_MUL( YY ); + MPI_CHK( mpi_mul_mpi( &RHS, &pt->X, &pt->X ) ); MOD_MUL( RHS ); + + /* Special case for A = -3 */ + if( grp->A.p == NULL ) + { + MPI_CHK( mpi_sub_int( &RHS, &RHS, 3 ) ); MOD_SUB( RHS ); + } + else + { + MPI_CHK( mpi_add_mpi( &RHS, &RHS, &grp->A ) ); MOD_ADD( RHS ); + } + + MPI_CHK( mpi_mul_mpi( &RHS, &RHS, &pt->X ) ); MOD_MUL( RHS ); + MPI_CHK( mpi_add_mpi( &RHS, &RHS, &grp->B ) ); MOD_ADD( RHS ); + + if( mpi_cmp_mpi( &YY, &RHS ) != 0 ) + ret = POLARSSL_ERR_ECP_INVALID_KEY; + +cleanup: + + mpi_free( &YY ); mpi_free( &RHS ); + + return( ret ); +} +#endif /* POLARSSL_ECP_SHORT_WEIERSTRASS */ + + +#if defined(POLARSSL_ECP_MONTGOMERY) +/* + * Check validity of a public key for Montgomery curves with x-only schemes + */ +static int ecp_check_pubkey_mx( const ecp_group *grp, const ecp_point *pt ) +{ + /* [M255 p. 5] Just check X is the correct number of bytes */ + if( mpi_size( &pt->X ) > ( grp->nbits + 7 ) / 8 ) + return( POLARSSL_ERR_ECP_INVALID_KEY ); + + return( 0 ); +} +#endif /* POLARSSL_ECP_MONTGOMERY */ + +/* + * Check that a point is valid as a public key + */ +int ecp_check_pubkey( const ecp_group *grp, const ecp_point *pt ) +{ + /* Must use affine coordinates */ + if( mpi_cmp_int( &pt->Z, 1 ) != 0 ) + return( POLARSSL_ERR_ECP_INVALID_KEY ); + +#if defined(POLARSSL_ECP_MONTGOMERY) + if( ecp_get_type( grp ) == POLARSSL_ECP_TYPE_MONTGOMERY ) + return( ecp_check_pubkey_mx( grp, pt ) ); +#endif +#if defined(POLARSSL_ECP_SHORT_WEIERSTRASS) + if( ecp_get_type( grp ) == POLARSSL_ECP_TYPE_SHORT_WEIERSTRASS ) + return( ecp_check_pubkey_sw( grp, pt ) ); +#endif + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); +} + +/* + * Check that an mpi is valid as a private key + */ +int ecp_check_privkey( const ecp_group *grp, const mpi *d ) +{ +#if defined(POLARSSL_ECP_MONTGOMERY) + if( ecp_get_type( grp ) == POLARSSL_ECP_TYPE_MONTGOMERY ) + { + /* see [M255] page 5 */ + if( mpi_get_bit( d, 0 ) != 0 || + mpi_get_bit( d, 1 ) != 0 || + mpi_get_bit( d, 2 ) != 0 || + mpi_msb( d ) - 1 != grp->nbits ) /* mpi_msb is one-based! */ + return( POLARSSL_ERR_ECP_INVALID_KEY ); + else + return( 0 ); + } +#endif /* POLARSSL_ECP_MONTGOMERY */ +#if defined(POLARSSL_ECP_SHORT_WEIERSTRASS) + if( ecp_get_type( grp ) == POLARSSL_ECP_TYPE_SHORT_WEIERSTRASS ) + { + /* see SEC1 3.2 */ + if( mpi_cmp_int( d, 1 ) < 0 || + mpi_cmp_mpi( d, &grp->N ) >= 0 ) + return( POLARSSL_ERR_ECP_INVALID_KEY ); + else + return( 0 ); + } +#endif /* POLARSSL_ECP_SHORT_WEIERSTRASS */ + + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); +} + +/* + * Generate a keypair + */ +int ecp_gen_keypair( ecp_group *grp, mpi *d, ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + size_t n_size = ( grp->nbits + 7 ) / 8; + +#if defined(POLARSSL_ECP_MONTGOMERY) + if( ecp_get_type( grp ) == POLARSSL_ECP_TYPE_MONTGOMERY ) + { + /* [M225] page 5 */ + size_t b; + + MPI_CHK( mpi_fill_random( d, n_size, f_rng, p_rng ) ); + + /* Make sure the most significant bit is nbits */ + b = mpi_msb( d ) - 1; /* mpi_msb is one-based */ + if( b > grp->nbits ) + MPI_CHK( mpi_shift_r( d, b - grp->nbits ) ); + else + MPI_CHK( mpi_set_bit( d, grp->nbits, 1 ) ); + + /* Make sure the last three bits are unset */ + MPI_CHK( mpi_set_bit( d, 0, 0 ) ); + MPI_CHK( mpi_set_bit( d, 1, 0 ) ); + MPI_CHK( mpi_set_bit( d, 2, 0 ) ); + } + else +#endif /* POLARSSL_ECP_MONTGOMERY */ +#if defined(POLARSSL_ECP_SHORT_WEIERSTRASS) + if( ecp_get_type( grp ) == POLARSSL_ECP_TYPE_SHORT_WEIERSTRASS ) + { + /* SEC1 3.2.1: Generate d such that 1 <= n < N */ + int count = 0; + unsigned char rnd[POLARSSL_ECP_MAX_BYTES]; + + /* + * Match the procedure given in RFC 6979 (deterministic ECDSA): + * - use the same byte ordering; + * - keep the leftmost nbits bits of the generated octet string; + * - try until result is in the desired range. + * This also avoids any biais, which is especially important for ECDSA. + */ + do + { + MPI_CHK( f_rng( p_rng, rnd, n_size ) ); + MPI_CHK( mpi_read_binary( d, rnd, n_size ) ); + MPI_CHK( mpi_shift_r( d, 8 * n_size - grp->nbits ) ); + + /* + * Each try has at worst a probability 1/2 of failing (the msb has + * a probability 1/2 of being 0, and then the result will be < N), + * so after 30 tries failure probability is a most 2**(-30). + * + * For most curves, 1 try is enough with overwhelming probability, + * since N starts with a lot of 1s in binary, but some curves + * such as secp224k1 are actually very close to the worst case. + */ + if( ++count > 30 ) + return( POLARSSL_ERR_ECP_RANDOM_FAILED ); + } + while( mpi_cmp_int( d, 1 ) < 0 || + mpi_cmp_mpi( d, &grp->N ) >= 0 ); + } + else +#endif /* POLARSSL_ECP_SHORT_WEIERSTRASS */ + return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); + +cleanup: + if( ret != 0 ) + return( ret ); + + return( ecp_mul( grp, Q, d, &grp->G, f_rng, p_rng ) ); +} + +/* + * Generate a keypair, prettier wrapper + */ +int ecp_gen_key( ecp_group_id grp_id, ecp_keypair *key, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret; + + if( ( ret = ecp_use_known_dp( &key->grp, grp_id ) ) != 0 ) + return( ret ); + + return( ecp_gen_keypair( &key->grp, &key->d, &key->Q, f_rng, p_rng ) ); +} + +#if defined(POLARSSL_SELF_TEST) + +/* + * Checkup routine + */ +int ecp_self_test( int verbose ) +{ + int ret; + size_t i; + ecp_group grp; + ecp_point R, P; + mpi m; + unsigned long add_c_prev, dbl_c_prev, mul_c_prev; + /* exponents especially adapted for secp192r1 */ + const char *exponents[] = + { + "000000000000000000000000000000000000000000000001", /* one */ + "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22830", /* N - 1 */ + "5EA6F389A38B8BC81E767753B15AA5569E1782E30ABE7D25", /* random */ + "400000000000000000000000000000000000000000000000", /* one and zeros */ + "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", /* all ones */ + "555555555555555555555555555555555555555555555555", /* 101010... */ + }; + + ecp_group_init( &grp ); + ecp_point_init( &R ); + ecp_point_init( &P ); + mpi_init( &m ); + + /* Use secp192r1 if available, or any available curve */ +#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED) + MPI_CHK( ecp_use_known_dp( &grp, POLARSSL_ECP_DP_SECP192R1 ) ); +#else + MPI_CHK( ecp_use_known_dp( &grp, ecp_curve_list()->grp_id ) ); +#endif + + if( verbose != 0 ) + polarssl_printf( " ECP test #1 (constant op_count, base point G): " ); + + /* Do a dummy multiplication first to trigger precomputation */ + MPI_CHK( mpi_lset( &m, 2 ) ); + MPI_CHK( ecp_mul( &grp, &P, &m, &grp.G, NULL, NULL ) ); + + add_count = 0; + dbl_count = 0; + mul_count = 0; + MPI_CHK( mpi_read_string( &m, 16, exponents[0] ) ); + MPI_CHK( ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) ); + + for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ ) + { + add_c_prev = add_count; + dbl_c_prev = dbl_count; + mul_c_prev = mul_count; + add_count = 0; + dbl_count = 0; + mul_count = 0; + + MPI_CHK( mpi_read_string( &m, 16, exponents[i] ) ); + MPI_CHK( ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) ); + + if( add_count != add_c_prev || + dbl_count != dbl_c_prev || + mul_count != mul_c_prev ) + { + if( verbose != 0 ) + polarssl_printf( "failed (%u)\n", (unsigned int) i ); + + ret = 1; + goto cleanup; + } + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + + if( verbose != 0 ) + polarssl_printf( " ECP test #2 (constant op_count, other point): " ); + /* We computed P = 2G last time, use it */ + + add_count = 0; + dbl_count = 0; + mul_count = 0; + MPI_CHK( mpi_read_string( &m, 16, exponents[0] ) ); + MPI_CHK( ecp_mul( &grp, &R, &m, &P, NULL, NULL ) ); + + for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ ) + { + add_c_prev = add_count; + dbl_c_prev = dbl_count; + mul_c_prev = mul_count; + add_count = 0; + dbl_count = 0; + mul_count = 0; + + MPI_CHK( mpi_read_string( &m, 16, exponents[i] ) ); + MPI_CHK( ecp_mul( &grp, &R, &m, &P, NULL, NULL ) ); + + if( add_count != add_c_prev || + dbl_count != dbl_c_prev || + mul_count != mul_c_prev ) + { + if( verbose != 0 ) + polarssl_printf( "failed (%u)\n", (unsigned int) i ); + + ret = 1; + goto cleanup; + } + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + +cleanup: + + if( ret < 0 && verbose != 0 ) + polarssl_printf( "Unexpected error, return code = %08X\n", ret ); + + ecp_group_free( &grp ); + ecp_point_free( &R ); + ecp_point_free( &P ); + mpi_free( &m ); + + if( verbose != 0 ) + polarssl_printf( "\n" ); + + return( ret ); +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_ECP_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/ecp_curves.c b/component/common/network/ssl/polarssl-1.3.8/library/ecp_curves.c new file mode 100644 index 0000000..4c0018c --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/ecp_curves.c @@ -0,0 +1,1380 @@ +/* + * Elliptic curves over GF(p): curve-specific data and functions + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_ECP_C) + +#include "polarssl/ecp.h" + +#if defined(_MSC_VER) && !defined(inline) +#define inline _inline +#else +#if defined(__ARMCC_VERSION) && !defined(inline) +#define inline __inline +#endif /* __ARMCC_VERSION */ +#endif /*_MSC_VER */ + +/* + * Conversion macros for embedded constants: + * build lists of t_uint's from lists of unsigned char's grouped by 8, 4 or 2 + */ +#if defined(POLARSSL_HAVE_INT8) + +#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \ + a, b, c, d, e, f, g, h + +#define BYTES_TO_T_UINT_4( a, b, c, d ) \ + a, b, c, d + +#define BYTES_TO_T_UINT_2( a, b ) \ + a, b + +#elif defined(POLARSSL_HAVE_INT16) + +#define BYTES_TO_T_UINT_2( a, b ) \ + ( (t_uint) a << 0 ) | \ + ( (t_uint) b << 8 ) + +#define BYTES_TO_T_UINT_4( a, b, c, d ) \ + BYTES_TO_T_UINT_2( a, b ), \ + BYTES_TO_T_UINT_2( c, d ) + +#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \ + BYTES_TO_T_UINT_2( a, b ), \ + BYTES_TO_T_UINT_2( c, d ), \ + BYTES_TO_T_UINT_2( e, f ), \ + BYTES_TO_T_UINT_2( g, h ) + +#elif defined(POLARSSL_HAVE_INT32) + +#define BYTES_TO_T_UINT_4( a, b, c, d ) \ + ( (t_uint) a << 0 ) | \ + ( (t_uint) b << 8 ) | \ + ( (t_uint) c << 16 ) | \ + ( (t_uint) d << 24 ) + +#define BYTES_TO_T_UINT_2( a, b ) \ + BYTES_TO_T_UINT_4( a, b, 0, 0 ) + +#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \ + BYTES_TO_T_UINT_4( a, b, c, d ), \ + BYTES_TO_T_UINT_4( e, f, g, h ) + +#else /* 64-bits */ + +#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \ + ( (t_uint) a << 0 ) | \ + ( (t_uint) b << 8 ) | \ + ( (t_uint) c << 16 ) | \ + ( (t_uint) d << 24 ) | \ + ( (t_uint) e << 32 ) | \ + ( (t_uint) f << 40 ) | \ + ( (t_uint) g << 48 ) | \ + ( (t_uint) h << 56 ) + +#define BYTES_TO_T_UINT_4( a, b, c, d ) \ + BYTES_TO_T_UINT_8( a, b, c, d, 0, 0, 0, 0 ) + +#define BYTES_TO_T_UINT_2( a, b ) \ + BYTES_TO_T_UINT_8( a, b, 0, 0, 0, 0, 0, 0 ) + +#endif /* bits in t_uint */ + +/* + * Note: the constants are in little-endian order + * to be directly usable in MPIs + */ + +/* + * Domain parameters for secp192r1 + */ +#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED) +static const t_uint secp192r1_p[] = { + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const t_uint secp192r1_b[] = { + BYTES_TO_T_UINT_8( 0xB1, 0xB9, 0x46, 0xC1, 0xEC, 0xDE, 0xB8, 0xFE ), + BYTES_TO_T_UINT_8( 0x49, 0x30, 0x24, 0x72, 0xAB, 0xE9, 0xA7, 0x0F ), + BYTES_TO_T_UINT_8( 0xE7, 0x80, 0x9C, 0xE5, 0x19, 0x05, 0x21, 0x64 ), +}; +static const t_uint secp192r1_gx[] = { + BYTES_TO_T_UINT_8( 0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4 ), + BYTES_TO_T_UINT_8( 0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C ), + BYTES_TO_T_UINT_8( 0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18 ), +}; +static const t_uint secp192r1_gy[] = { + BYTES_TO_T_UINT_8( 0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73 ), + BYTES_TO_T_UINT_8( 0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63 ), + BYTES_TO_T_UINT_8( 0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07 ), +}; +static const t_uint secp192r1_n[] = { + BYTES_TO_T_UINT_8( 0x31, 0x28, 0xD2, 0xB4, 0xB1, 0xC9, 0x6B, 0x14 ), + BYTES_TO_T_UINT_8( 0x36, 0xF8, 0xDE, 0x99, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* POLARSSL_ECP_DP_SECP192R1_ENABLED */ + +/* + * Domain parameters for secp224r1 + */ +#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED) +static const t_uint secp224r1_p[] = { + BYTES_TO_T_UINT_8( 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ), +}; +static const t_uint secp224r1_b[] = { + BYTES_TO_T_UINT_8( 0xB4, 0xFF, 0x55, 0x23, 0x43, 0x39, 0x0B, 0x27 ), + BYTES_TO_T_UINT_8( 0xBA, 0xD8, 0xBF, 0xD7, 0xB7, 0xB0, 0x44, 0x50 ), + BYTES_TO_T_UINT_8( 0x56, 0x32, 0x41, 0xF5, 0xAB, 0xB3, 0x04, 0x0C ), + BYTES_TO_T_UINT_4( 0x85, 0x0A, 0x05, 0xB4 ), +}; +static const t_uint secp224r1_gx[] = { + BYTES_TO_T_UINT_8( 0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34 ), + BYTES_TO_T_UINT_8( 0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A ), + BYTES_TO_T_UINT_8( 0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B ), + BYTES_TO_T_UINT_4( 0xBD, 0x0C, 0x0E, 0xB7 ), +}; +static const t_uint secp224r1_gy[] = { + BYTES_TO_T_UINT_8( 0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44 ), + BYTES_TO_T_UINT_8( 0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD ), + BYTES_TO_T_UINT_8( 0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5 ), + BYTES_TO_T_UINT_4( 0x88, 0x63, 0x37, 0xBD ), +}; +static const t_uint secp224r1_n[] = { + BYTES_TO_T_UINT_8( 0x3D, 0x2A, 0x5C, 0x5C, 0x45, 0x29, 0xDD, 0x13 ), + BYTES_TO_T_UINT_8( 0x3E, 0xF0, 0xB8, 0xE0, 0xA2, 0x16, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_4( 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* POLARSSL_ECP_DP_SECP224R1_ENABLED */ + +/* + * Domain parameters for secp256r1 + */ +#if defined(POLARSSL_ECP_DP_SECP256R1_ENABLED) +static const t_uint secp256r1_p[] = { + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), + BYTES_TO_T_UINT_8( 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const t_uint secp256r1_b[] = { + BYTES_TO_T_UINT_8( 0x4B, 0x60, 0xD2, 0x27, 0x3E, 0x3C, 0xCE, 0x3B ), + BYTES_TO_T_UINT_8( 0xF6, 0xB0, 0x53, 0xCC, 0xB0, 0x06, 0x1D, 0x65 ), + BYTES_TO_T_UINT_8( 0xBC, 0x86, 0x98, 0x76, 0x55, 0xBD, 0xEB, 0xB3 ), + BYTES_TO_T_UINT_8( 0xE7, 0x93, 0x3A, 0xAA, 0xD8, 0x35, 0xC6, 0x5A ), +}; +static const t_uint secp256r1_gx[] = { + BYTES_TO_T_UINT_8( 0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4 ), + BYTES_TO_T_UINT_8( 0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77 ), + BYTES_TO_T_UINT_8( 0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8 ), + BYTES_TO_T_UINT_8( 0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B ), +}; +static const t_uint secp256r1_gy[] = { + BYTES_TO_T_UINT_8( 0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB ), + BYTES_TO_T_UINT_8( 0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B ), + BYTES_TO_T_UINT_8( 0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E ), + BYTES_TO_T_UINT_8( 0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F ), +}; +static const t_uint secp256r1_n[] = { + BYTES_TO_T_UINT_8( 0x51, 0x25, 0x63, 0xFC, 0xC2, 0xCA, 0xB9, 0xF3 ), + BYTES_TO_T_UINT_8( 0x84, 0x9E, 0x17, 0xA7, 0xAD, 0xFA, 0xE6, 0xBC ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* POLARSSL_ECP_DP_SECP256R1_ENABLED */ + +/* + * Domain parameters for secp384r1 + */ +#if defined(POLARSSL_ECP_DP_SECP384R1_ENABLED) +static const t_uint secp384r1_p[] = { + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const t_uint secp384r1_b[] = { + BYTES_TO_T_UINT_8( 0xEF, 0x2A, 0xEC, 0xD3, 0xED, 0xC8, 0x85, 0x2A ), + BYTES_TO_T_UINT_8( 0x9D, 0xD1, 0x2E, 0x8A, 0x8D, 0x39, 0x56, 0xC6 ), + BYTES_TO_T_UINT_8( 0x5A, 0x87, 0x13, 0x50, 0x8F, 0x08, 0x14, 0x03 ), + BYTES_TO_T_UINT_8( 0x12, 0x41, 0x81, 0xFE, 0x6E, 0x9C, 0x1D, 0x18 ), + BYTES_TO_T_UINT_8( 0x19, 0x2D, 0xF8, 0xE3, 0x6B, 0x05, 0x8E, 0x98 ), + BYTES_TO_T_UINT_8( 0xE4, 0xE7, 0x3E, 0xE2, 0xA7, 0x2F, 0x31, 0xB3 ), +}; +static const t_uint secp384r1_gx[] = { + BYTES_TO_T_UINT_8( 0xB7, 0x0A, 0x76, 0x72, 0x38, 0x5E, 0x54, 0x3A ), + BYTES_TO_T_UINT_8( 0x6C, 0x29, 0x55, 0xBF, 0x5D, 0xF2, 0x02, 0x55 ), + BYTES_TO_T_UINT_8( 0x38, 0x2A, 0x54, 0x82, 0xE0, 0x41, 0xF7, 0x59 ), + BYTES_TO_T_UINT_8( 0x98, 0x9B, 0xA7, 0x8B, 0x62, 0x3B, 0x1D, 0x6E ), + BYTES_TO_T_UINT_8( 0x74, 0xAD, 0x20, 0xF3, 0x1E, 0xC7, 0xB1, 0x8E ), + BYTES_TO_T_UINT_8( 0x37, 0x05, 0x8B, 0xBE, 0x22, 0xCA, 0x87, 0xAA ), +}; +static const t_uint secp384r1_gy[] = { + BYTES_TO_T_UINT_8( 0x5F, 0x0E, 0xEA, 0x90, 0x7C, 0x1D, 0x43, 0x7A ), + BYTES_TO_T_UINT_8( 0x9D, 0x81, 0x7E, 0x1D, 0xCE, 0xB1, 0x60, 0x0A ), + BYTES_TO_T_UINT_8( 0xC0, 0xB8, 0xF0, 0xB5, 0x13, 0x31, 0xDA, 0xE9 ), + BYTES_TO_T_UINT_8( 0x7C, 0x14, 0x9A, 0x28, 0xBD, 0x1D, 0xF4, 0xF8 ), + BYTES_TO_T_UINT_8( 0x29, 0xDC, 0x92, 0x92, 0xBF, 0x98, 0x9E, 0x5D ), + BYTES_TO_T_UINT_8( 0x6F, 0x2C, 0x26, 0x96, 0x4A, 0xDE, 0x17, 0x36 ), +}; +static const t_uint secp384r1_n[] = { + BYTES_TO_T_UINT_8( 0x73, 0x29, 0xC5, 0xCC, 0x6A, 0x19, 0xEC, 0xEC ), + BYTES_TO_T_UINT_8( 0x7A, 0xA7, 0xB0, 0x48, 0xB2, 0x0D, 0x1A, 0x58 ), + BYTES_TO_T_UINT_8( 0xDF, 0x2D, 0x37, 0xF4, 0x81, 0x4D, 0x63, 0xC7 ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* POLARSSL_ECP_DP_SECP384R1_ENABLED */ + +/* + * Domain parameters for secp521r1 + */ +#if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED) +static const t_uint secp521r1_p[] = { + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_2( 0xFF, 0x01 ), +}; +static const t_uint secp521r1_b[] = { + BYTES_TO_T_UINT_8( 0x00, 0x3F, 0x50, 0x6B, 0xD4, 0x1F, 0x45, 0xEF ), + BYTES_TO_T_UINT_8( 0xF1, 0x34, 0x2C, 0x3D, 0x88, 0xDF, 0x73, 0x35 ), + BYTES_TO_T_UINT_8( 0x07, 0xBF, 0xB1, 0x3B, 0xBD, 0xC0, 0x52, 0x16 ), + BYTES_TO_T_UINT_8( 0x7B, 0x93, 0x7E, 0xEC, 0x51, 0x39, 0x19, 0x56 ), + BYTES_TO_T_UINT_8( 0xE1, 0x09, 0xF1, 0x8E, 0x91, 0x89, 0xB4, 0xB8 ), + BYTES_TO_T_UINT_8( 0xF3, 0x15, 0xB3, 0x99, 0x5B, 0x72, 0xDA, 0xA2 ), + BYTES_TO_T_UINT_8( 0xEE, 0x40, 0x85, 0xB6, 0xA0, 0x21, 0x9A, 0x92 ), + BYTES_TO_T_UINT_8( 0x1F, 0x9A, 0x1C, 0x8E, 0x61, 0xB9, 0x3E, 0x95 ), + BYTES_TO_T_UINT_2( 0x51, 0x00 ), +}; +static const t_uint secp521r1_gx[] = { + BYTES_TO_T_UINT_8( 0x66, 0xBD, 0xE5, 0xC2, 0x31, 0x7E, 0x7E, 0xF9 ), + BYTES_TO_T_UINT_8( 0x9B, 0x42, 0x6A, 0x85, 0xC1, 0xB3, 0x48, 0x33 ), + BYTES_TO_T_UINT_8( 0xDE, 0xA8, 0xFF, 0xA2, 0x27, 0xC1, 0x1D, 0xFE ), + BYTES_TO_T_UINT_8( 0x28, 0x59, 0xE7, 0xEF, 0x77, 0x5E, 0x4B, 0xA1 ), + BYTES_TO_T_UINT_8( 0xBA, 0x3D, 0x4D, 0x6B, 0x60, 0xAF, 0x28, 0xF8 ), + BYTES_TO_T_UINT_8( 0x21, 0xB5, 0x3F, 0x05, 0x39, 0x81, 0x64, 0x9C ), + BYTES_TO_T_UINT_8( 0x42, 0xB4, 0x95, 0x23, 0x66, 0xCB, 0x3E, 0x9E ), + BYTES_TO_T_UINT_8( 0xCD, 0xE9, 0x04, 0x04, 0xB7, 0x06, 0x8E, 0x85 ), + BYTES_TO_T_UINT_2( 0xC6, 0x00 ), +}; +static const t_uint secp521r1_gy[] = { + BYTES_TO_T_UINT_8( 0x50, 0x66, 0xD1, 0x9F, 0x76, 0x94, 0xBE, 0x88 ), + BYTES_TO_T_UINT_8( 0x40, 0xC2, 0x72, 0xA2, 0x86, 0x70, 0x3C, 0x35 ), + BYTES_TO_T_UINT_8( 0x61, 0x07, 0xAD, 0x3F, 0x01, 0xB9, 0x50, 0xC5 ), + BYTES_TO_T_UINT_8( 0x40, 0x26, 0xF4, 0x5E, 0x99, 0x72, 0xEE, 0x97 ), + BYTES_TO_T_UINT_8( 0x2C, 0x66, 0x3E, 0x27, 0x17, 0xBD, 0xAF, 0x17 ), + BYTES_TO_T_UINT_8( 0x68, 0x44, 0x9B, 0x57, 0x49, 0x44, 0xF5, 0x98 ), + BYTES_TO_T_UINT_8( 0xD9, 0x1B, 0x7D, 0x2C, 0xB4, 0x5F, 0x8A, 0x5C ), + BYTES_TO_T_UINT_8( 0x04, 0xC0, 0x3B, 0x9A, 0x78, 0x6A, 0x29, 0x39 ), + BYTES_TO_T_UINT_2( 0x18, 0x01 ), +}; +static const t_uint secp521r1_n[] = { + BYTES_TO_T_UINT_8( 0x09, 0x64, 0x38, 0x91, 0x1E, 0xB7, 0x6F, 0xBB ), + BYTES_TO_T_UINT_8( 0xAE, 0x47, 0x9C, 0x89, 0xB8, 0xC9, 0xB5, 0x3B ), + BYTES_TO_T_UINT_8( 0xD0, 0xA5, 0x09, 0xF7, 0x48, 0x01, 0xCC, 0x7F ), + BYTES_TO_T_UINT_8( 0x6B, 0x96, 0x2F, 0xBF, 0x83, 0x87, 0x86, 0x51 ), + BYTES_TO_T_UINT_8( 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_2( 0xFF, 0x01 ), +}; +#endif /* POLARSSL_ECP_DP_SECP521R1_ENABLED */ + +#if defined(POLARSSL_ECP_DP_SECP192K1_ENABLED) +static const t_uint secp192k1_p[] = { + BYTES_TO_T_UINT_8( 0x37, 0xEE, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const t_uint secp192k1_a[] = { + BYTES_TO_T_UINT_2( 0x00, 0x00 ), +}; +static const t_uint secp192k1_b[] = { + BYTES_TO_T_UINT_2( 0x03, 0x00 ), +}; +static const t_uint secp192k1_gx[] = { + BYTES_TO_T_UINT_8( 0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D ), + BYTES_TO_T_UINT_8( 0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26 ), + BYTES_TO_T_UINT_8( 0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB ), +}; +static const t_uint secp192k1_gy[] = { + BYTES_TO_T_UINT_8( 0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40 ), + BYTES_TO_T_UINT_8( 0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84 ), + BYTES_TO_T_UINT_8( 0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B ), +}; +static const t_uint secp192k1_n[] = { + BYTES_TO_T_UINT_8( 0x8D, 0xFD, 0xDE, 0x74, 0x6A, 0x46, 0x69, 0x0F ), + BYTES_TO_T_UINT_8( 0x17, 0xFC, 0xF2, 0x26, 0xFE, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* POLARSSL_ECP_DP_SECP192K1_ENABLED */ + +#if defined(POLARSSL_ECP_DP_SECP224K1_ENABLED) +static const t_uint secp224k1_p[] = { + BYTES_TO_T_UINT_8( 0x6D, 0xE5, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_4( 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const t_uint secp224k1_a[] = { + BYTES_TO_T_UINT_2( 0x00, 0x00 ), +}; +static const t_uint secp224k1_b[] = { + BYTES_TO_T_UINT_2( 0x05, 0x00 ), +}; +static const t_uint secp224k1_gx[] = { + BYTES_TO_T_UINT_8( 0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F ), + BYTES_TO_T_UINT_8( 0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69 ), + BYTES_TO_T_UINT_8( 0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D ), + BYTES_TO_T_UINT_4( 0x33, 0x5B, 0x45, 0xA1 ), +}; +static const t_uint secp224k1_gy[] = { + BYTES_TO_T_UINT_8( 0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2 ), + BYTES_TO_T_UINT_8( 0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7 ), + BYTES_TO_T_UINT_8( 0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F ), + BYTES_TO_T_UINT_4( 0xED, 0x9F, 0x08, 0x7E ), +}; +static const t_uint secp224k1_n[] = { + BYTES_TO_T_UINT_8( 0xF7, 0xB1, 0x9F, 0x76, 0x71, 0xA9, 0xF0, 0xCA ), + BYTES_TO_T_UINT_8( 0x84, 0x61, 0xEC, 0xD2, 0xE8, 0xDC, 0x01, 0x00 ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ), +}; +#endif /* POLARSSL_ECP_DP_SECP224K1_ENABLED */ + +#if defined(POLARSSL_ECP_DP_SECP256K1_ENABLED) +static const t_uint secp256k1_p[] = { + BYTES_TO_T_UINT_8( 0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const t_uint secp256k1_a[] = { + BYTES_TO_T_UINT_2( 0x00, 0x00 ), +}; +static const t_uint secp256k1_b[] = { + BYTES_TO_T_UINT_2( 0x07, 0x00 ), +}; +static const t_uint secp256k1_gx[] = { + BYTES_TO_T_UINT_8( 0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59 ), + BYTES_TO_T_UINT_8( 0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02 ), + BYTES_TO_T_UINT_8( 0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55 ), + BYTES_TO_T_UINT_8( 0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79 ), +}; +static const t_uint secp256k1_gy[] = { + BYTES_TO_T_UINT_8( 0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C ), + BYTES_TO_T_UINT_8( 0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD ), + BYTES_TO_T_UINT_8( 0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D ), + BYTES_TO_T_UINT_8( 0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48 ), +}; +static const t_uint secp256k1_n[] = { + BYTES_TO_T_UINT_8( 0x41, 0x41, 0x36, 0xD0, 0x8C, 0x5E, 0xD2, 0xBF ), + BYTES_TO_T_UINT_8( 0x3B, 0xA0, 0x48, 0xAF, 0xE6, 0xDC, 0xAE, 0xBA ), + BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* POLARSSL_ECP_DP_SECP256K1_ENABLED */ + +/* + * Domain parameters for brainpoolP256r1 (RFC 5639 3.4) + */ +#if defined(POLARSSL_ECP_DP_BP256R1_ENABLED) +static const t_uint brainpoolP256r1_p[] = { + BYTES_TO_T_UINT_8( 0x77, 0x53, 0x6E, 0x1F, 0x1D, 0x48, 0x13, 0x20 ), + BYTES_TO_T_UINT_8( 0x28, 0x20, 0x26, 0xD5, 0x23, 0xF6, 0x3B, 0x6E ), + BYTES_TO_T_UINT_8( 0x72, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E ), + BYTES_TO_T_UINT_8( 0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9 ), +}; +static const t_uint brainpoolP256r1_a[] = { + BYTES_TO_T_UINT_8( 0xD9, 0xB5, 0x30, 0xF3, 0x44, 0x4B, 0x4A, 0xE9 ), + BYTES_TO_T_UINT_8( 0x6C, 0x5C, 0xDC, 0x26, 0xC1, 0x55, 0x80, 0xFB ), + BYTES_TO_T_UINT_8( 0xE7, 0xFF, 0x7A, 0x41, 0x30, 0x75, 0xF6, 0xEE ), + BYTES_TO_T_UINT_8( 0x57, 0x30, 0x2C, 0xFC, 0x75, 0x09, 0x5A, 0x7D ), +}; +static const t_uint brainpoolP256r1_b[] = { + BYTES_TO_T_UINT_8( 0xB6, 0x07, 0x8C, 0xFF, 0x18, 0xDC, 0xCC, 0x6B ), + BYTES_TO_T_UINT_8( 0xCE, 0xE1, 0xF7, 0x5C, 0x29, 0x16, 0x84, 0x95 ), + BYTES_TO_T_UINT_8( 0xBF, 0x7C, 0xD7, 0xBB, 0xD9, 0xB5, 0x30, 0xF3 ), + BYTES_TO_T_UINT_8( 0x44, 0x4B, 0x4A, 0xE9, 0x6C, 0x5C, 0xDC, 0x26 ), +}; +static const t_uint brainpoolP256r1_gx[] = { + BYTES_TO_T_UINT_8( 0x62, 0x32, 0xCE, 0x9A, 0xBD, 0x53, 0x44, 0x3A ), + BYTES_TO_T_UINT_8( 0xC2, 0x23, 0xBD, 0xE3, 0xE1, 0x27, 0xDE, 0xB9 ), + BYTES_TO_T_UINT_8( 0xAF, 0xB7, 0x81, 0xFC, 0x2F, 0x48, 0x4B, 0x2C ), + BYTES_TO_T_UINT_8( 0xCB, 0x57, 0x7E, 0xCB, 0xB9, 0xAE, 0xD2, 0x8B ), +}; +static const t_uint brainpoolP256r1_gy[] = { + BYTES_TO_T_UINT_8( 0x97, 0x69, 0x04, 0x2F, 0xC7, 0x54, 0x1D, 0x5C ), + BYTES_TO_T_UINT_8( 0x54, 0x8E, 0xED, 0x2D, 0x13, 0x45, 0x77, 0xC2 ), + BYTES_TO_T_UINT_8( 0xC9, 0x1D, 0x61, 0x14, 0x1A, 0x46, 0xF8, 0x97 ), + BYTES_TO_T_UINT_8( 0xFD, 0xC4, 0xDA, 0xC3, 0x35, 0xF8, 0x7E, 0x54 ), +}; +static const t_uint brainpoolP256r1_n[] = { + BYTES_TO_T_UINT_8( 0xA7, 0x56, 0x48, 0x97, 0x82, 0x0E, 0x1E, 0x90 ), + BYTES_TO_T_UINT_8( 0xF7, 0xA6, 0x61, 0xB5, 0xA3, 0x7A, 0x39, 0x8C ), + BYTES_TO_T_UINT_8( 0x71, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E ), + BYTES_TO_T_UINT_8( 0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9 ), +}; +#endif /* POLARSSL_ECP_DP_BP256R1_ENABLED */ + +/* + * Domain parameters for brainpoolP384r1 (RFC 5639 3.6) + */ +#if defined(POLARSSL_ECP_DP_BP384R1_ENABLED) +static const t_uint brainpoolP384r1_p[] = { + BYTES_TO_T_UINT_8( 0x53, 0xEC, 0x07, 0x31, 0x13, 0x00, 0x47, 0x87 ), + BYTES_TO_T_UINT_8( 0x71, 0x1A, 0x1D, 0x90, 0x29, 0xA7, 0xD3, 0xAC ), + BYTES_TO_T_UINT_8( 0x23, 0x11, 0xB7, 0x7F, 0x19, 0xDA, 0xB1, 0x12 ), + BYTES_TO_T_UINT_8( 0xB4, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15 ), + BYTES_TO_T_UINT_8( 0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F ), + BYTES_TO_T_UINT_8( 0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C ), +}; +static const t_uint brainpoolP384r1_a[] = { + BYTES_TO_T_UINT_8( 0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04 ), + BYTES_TO_T_UINT_8( 0xEB, 0xD4, 0x3A, 0x50, 0x4A, 0x81, 0xA5, 0x8A ), + BYTES_TO_T_UINT_8( 0x0F, 0xF9, 0x91, 0xBA, 0xEF, 0x65, 0x91, 0x13 ), + BYTES_TO_T_UINT_8( 0x87, 0x27, 0xB2, 0x4F, 0x8E, 0xA2, 0xBE, 0xC2 ), + BYTES_TO_T_UINT_8( 0xA0, 0xAF, 0x05, 0xCE, 0x0A, 0x08, 0x72, 0x3C ), + BYTES_TO_T_UINT_8( 0x0C, 0x15, 0x8C, 0x3D, 0xC6, 0x82, 0xC3, 0x7B ), +}; +static const t_uint brainpoolP384r1_b[] = { + BYTES_TO_T_UINT_8( 0x11, 0x4C, 0x50, 0xFA, 0x96, 0x86, 0xB7, 0x3A ), + BYTES_TO_T_UINT_8( 0x94, 0xC9, 0xDB, 0x95, 0x02, 0x39, 0xB4, 0x7C ), + BYTES_TO_T_UINT_8( 0xD5, 0x62, 0xEB, 0x3E, 0xA5, 0x0E, 0x88, 0x2E ), + BYTES_TO_T_UINT_8( 0xA6, 0xD2, 0xDC, 0x07, 0xE1, 0x7D, 0xB7, 0x2F ), + BYTES_TO_T_UINT_8( 0x7C, 0x44, 0xF0, 0x16, 0x54, 0xB5, 0x39, 0x8B ), + BYTES_TO_T_UINT_8( 0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04 ), +}; +static const t_uint brainpoolP384r1_gx[] = { + BYTES_TO_T_UINT_8( 0x1E, 0xAF, 0xD4, 0x47, 0xE2, 0xB2, 0x87, 0xEF ), + BYTES_TO_T_UINT_8( 0xAA, 0x46, 0xD6, 0x36, 0x34, 0xE0, 0x26, 0xE8 ), + BYTES_TO_T_UINT_8( 0xE8, 0x10, 0xBD, 0x0C, 0xFE, 0xCA, 0x7F, 0xDB ), + BYTES_TO_T_UINT_8( 0xE3, 0x4F, 0xF1, 0x7E, 0xE7, 0xA3, 0x47, 0x88 ), + BYTES_TO_T_UINT_8( 0x6B, 0x3F, 0xC1, 0xB7, 0x81, 0x3A, 0xA6, 0xA2 ), + BYTES_TO_T_UINT_8( 0xFF, 0x45, 0xCF, 0x68, 0xF0, 0x64, 0x1C, 0x1D ), +}; +static const t_uint brainpoolP384r1_gy[] = { + BYTES_TO_T_UINT_8( 0x15, 0x53, 0x3C, 0x26, 0x41, 0x03, 0x82, 0x42 ), + BYTES_TO_T_UINT_8( 0x11, 0x81, 0x91, 0x77, 0x21, 0x46, 0x46, 0x0E ), + BYTES_TO_T_UINT_8( 0x28, 0x29, 0x91, 0xF9, 0x4F, 0x05, 0x9C, 0xE1 ), + BYTES_TO_T_UINT_8( 0x64, 0x58, 0xEC, 0xFE, 0x29, 0x0B, 0xB7, 0x62 ), + BYTES_TO_T_UINT_8( 0x52, 0xD5, 0xCF, 0x95, 0x8E, 0xEB, 0xB1, 0x5C ), + BYTES_TO_T_UINT_8( 0xA4, 0xC2, 0xF9, 0x20, 0x75, 0x1D, 0xBE, 0x8A ), +}; +static const t_uint brainpoolP384r1_n[] = { + BYTES_TO_T_UINT_8( 0x65, 0x65, 0x04, 0xE9, 0x02, 0x32, 0x88, 0x3B ), + BYTES_TO_T_UINT_8( 0x10, 0xC3, 0x7F, 0x6B, 0xAF, 0xB6, 0x3A, 0xCF ), + BYTES_TO_T_UINT_8( 0xA7, 0x25, 0x04, 0xAC, 0x6C, 0x6E, 0x16, 0x1F ), + BYTES_TO_T_UINT_8( 0xB3, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15 ), + BYTES_TO_T_UINT_8( 0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F ), + BYTES_TO_T_UINT_8( 0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C ), +}; +#endif /* POLARSSL_ECP_DP_BP384R1_ENABLED */ + +/* + * Domain parameters for brainpoolP512r1 (RFC 5639 3.7) + */ +#if defined(POLARSSL_ECP_DP_BP512R1_ENABLED) +static const t_uint brainpoolP512r1_p[] = { + BYTES_TO_T_UINT_8( 0xF3, 0x48, 0x3A, 0x58, 0x56, 0x60, 0xAA, 0x28 ), + BYTES_TO_T_UINT_8( 0x85, 0xC6, 0x82, 0x2D, 0x2F, 0xFF, 0x81, 0x28 ), + BYTES_TO_T_UINT_8( 0xE6, 0x80, 0xA3, 0xE6, 0x2A, 0xA1, 0xCD, 0xAE ), + BYTES_TO_T_UINT_8( 0x42, 0x68, 0xC6, 0x9B, 0x00, 0x9B, 0x4D, 0x7D ), + BYTES_TO_T_UINT_8( 0x71, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6 ), + BYTES_TO_T_UINT_8( 0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB ), + BYTES_TO_T_UINT_8( 0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F ), + BYTES_TO_T_UINT_8( 0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA ), +}; +static const t_uint brainpoolP512r1_a[] = { + BYTES_TO_T_UINT_8( 0xCA, 0x94, 0xFC, 0x77, 0x4D, 0xAC, 0xC1, 0xE7 ), + BYTES_TO_T_UINT_8( 0xB9, 0xC7, 0xF2, 0x2B, 0xA7, 0x17, 0x11, 0x7F ), + BYTES_TO_T_UINT_8( 0xB5, 0xC8, 0x9A, 0x8B, 0xC9, 0xF1, 0x2E, 0x0A ), + BYTES_TO_T_UINT_8( 0xA1, 0x3A, 0x25, 0xA8, 0x5A, 0x5D, 0xED, 0x2D ), + BYTES_TO_T_UINT_8( 0xBC, 0x63, 0x98, 0xEA, 0xCA, 0x41, 0x34, 0xA8 ), + BYTES_TO_T_UINT_8( 0x10, 0x16, 0xF9, 0x3D, 0x8D, 0xDD, 0xCB, 0x94 ), + BYTES_TO_T_UINT_8( 0xC5, 0x4C, 0x23, 0xAC, 0x45, 0x71, 0x32, 0xE2 ), + BYTES_TO_T_UINT_8( 0x89, 0x3B, 0x60, 0x8B, 0x31, 0xA3, 0x30, 0x78 ), +}; +static const t_uint brainpoolP512r1_b[] = { + BYTES_TO_T_UINT_8( 0x23, 0xF7, 0x16, 0x80, 0x63, 0xBD, 0x09, 0x28 ), + BYTES_TO_T_UINT_8( 0xDD, 0xE5, 0xBA, 0x5E, 0xB7, 0x50, 0x40, 0x98 ), + BYTES_TO_T_UINT_8( 0x67, 0x3E, 0x08, 0xDC, 0xCA, 0x94, 0xFC, 0x77 ), + BYTES_TO_T_UINT_8( 0x4D, 0xAC, 0xC1, 0xE7, 0xB9, 0xC7, 0xF2, 0x2B ), + BYTES_TO_T_UINT_8( 0xA7, 0x17, 0x11, 0x7F, 0xB5, 0xC8, 0x9A, 0x8B ), + BYTES_TO_T_UINT_8( 0xC9, 0xF1, 0x2E, 0x0A, 0xA1, 0x3A, 0x25, 0xA8 ), + BYTES_TO_T_UINT_8( 0x5A, 0x5D, 0xED, 0x2D, 0xBC, 0x63, 0x98, 0xEA ), + BYTES_TO_T_UINT_8( 0xCA, 0x41, 0x34, 0xA8, 0x10, 0x16, 0xF9, 0x3D ), +}; +static const t_uint brainpoolP512r1_gx[] = { + BYTES_TO_T_UINT_8( 0x22, 0xF8, 0xB9, 0xBC, 0x09, 0x22, 0x35, 0x8B ), + BYTES_TO_T_UINT_8( 0x68, 0x5E, 0x6A, 0x40, 0x47, 0x50, 0x6D, 0x7C ), + BYTES_TO_T_UINT_8( 0x5F, 0x7D, 0xB9, 0x93, 0x7B, 0x68, 0xD1, 0x50 ), + BYTES_TO_T_UINT_8( 0x8D, 0xD4, 0xD0, 0xE2, 0x78, 0x1F, 0x3B, 0xFF ), + BYTES_TO_T_UINT_8( 0x8E, 0x09, 0xD0, 0xF4, 0xEE, 0x62, 0x3B, 0xB4 ), + BYTES_TO_T_UINT_8( 0xC1, 0x16, 0xD9, 0xB5, 0x70, 0x9F, 0xED, 0x85 ), + BYTES_TO_T_UINT_8( 0x93, 0x6A, 0x4C, 0x9C, 0x2E, 0x32, 0x21, 0x5A ), + BYTES_TO_T_UINT_8( 0x64, 0xD9, 0x2E, 0xD8, 0xBD, 0xE4, 0xAE, 0x81 ), +}; +static const t_uint brainpoolP512r1_gy[] = { + BYTES_TO_T_UINT_8( 0x92, 0x08, 0xD8, 0x3A, 0x0F, 0x1E, 0xCD, 0x78 ), + BYTES_TO_T_UINT_8( 0x06, 0x54, 0xF0, 0xA8, 0x2F, 0x2B, 0xCA, 0xD1 ), + BYTES_TO_T_UINT_8( 0xAE, 0x63, 0x27, 0x8A, 0xD8, 0x4B, 0xCA, 0x5B ), + BYTES_TO_T_UINT_8( 0x5E, 0x48, 0x5F, 0x4A, 0x49, 0xDE, 0xDC, 0xB2 ), + BYTES_TO_T_UINT_8( 0x11, 0x81, 0x1F, 0x88, 0x5B, 0xC5, 0x00, 0xA0 ), + BYTES_TO_T_UINT_8( 0x1A, 0x7B, 0xA5, 0x24, 0x00, 0xF7, 0x09, 0xF2 ), + BYTES_TO_T_UINT_8( 0xFD, 0x22, 0x78, 0xCF, 0xA9, 0xBF, 0xEA, 0xC0 ), + BYTES_TO_T_UINT_8( 0xEC, 0x32, 0x63, 0x56, 0x5D, 0x38, 0xDE, 0x7D ), +}; +static const t_uint brainpoolP512r1_n[] = { + BYTES_TO_T_UINT_8( 0x69, 0x00, 0xA9, 0x9C, 0x82, 0x96, 0x87, 0xB5 ), + BYTES_TO_T_UINT_8( 0xDD, 0xDA, 0x5D, 0x08, 0x81, 0xD3, 0xB1, 0x1D ), + BYTES_TO_T_UINT_8( 0x47, 0x10, 0xAC, 0x7F, 0x19, 0x61, 0x86, 0x41 ), + BYTES_TO_T_UINT_8( 0x19, 0x26, 0xA9, 0x4C, 0x41, 0x5C, 0x3E, 0x55 ), + BYTES_TO_T_UINT_8( 0x70, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6 ), + BYTES_TO_T_UINT_8( 0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB ), + BYTES_TO_T_UINT_8( 0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F ), + BYTES_TO_T_UINT_8( 0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA ), +}; +#endif /* POLARSSL_ECP_DP_BP512R1_ENABLED */ + +/* + * Create an MPI from embedded constants + * (assumes len is an exact multiple of sizeof t_uint) + */ +static inline void ecp_mpi_load( mpi *X, const t_uint *p, size_t len ) +{ + X->s = 1; + X->n = len / sizeof( t_uint ); + X->p = (t_uint *) p; +} + +/* + * Set an MPI to static value 1 + */ +static inline void ecp_mpi_set1( mpi *X ) +{ + static t_uint one[] = { 1 }; + X->s = 1; + X->n = 1; + X->p = one; +} + +/* + * Make group available from embedded constants + */ +static int ecp_group_load( ecp_group *grp, + const t_uint *p, size_t plen, + const t_uint *a, size_t alen, + const t_uint *b, size_t blen, + const t_uint *gx, size_t gxlen, + const t_uint *gy, size_t gylen, + const t_uint *n, size_t nlen) +{ + ecp_mpi_load( &grp->P, p, plen ); + if( a != NULL ) + ecp_mpi_load( &grp->A, a, alen ); + ecp_mpi_load( &grp->B, b, blen ); + ecp_mpi_load( &grp->N, n, nlen ); + + ecp_mpi_load( &grp->G.X, gx, gxlen ); + ecp_mpi_load( &grp->G.Y, gy, gylen ); + ecp_mpi_set1( &grp->G.Z ); + + grp->pbits = mpi_msb( &grp->P ); + grp->nbits = mpi_msb( &grp->N ); + + grp->h = 1; + + return( 0 ); +} + +#if defined(POLARSSL_ECP_NIST_OPTIM) +/* Forward declarations */ +#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED) +static int ecp_mod_p192( mpi * ); +#endif +#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED) +static int ecp_mod_p224( mpi * ); +#endif +#if defined(POLARSSL_ECP_DP_SECP256R1_ENABLED) +static int ecp_mod_p256( mpi * ); +#endif +#if defined(POLARSSL_ECP_DP_SECP384R1_ENABLED) +static int ecp_mod_p384( mpi * ); +#endif +#if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED) +static int ecp_mod_p521( mpi * ); +#endif + +#define NIST_MODP( P ) grp->modp = ecp_mod_ ## P; +#else +#define NIST_MODP( P ) +#endif /* POLARSSL_ECP_NIST_OPTIM */ + +/* Additional forward declarations */ +#if defined(POLARSSL_ECP_DP_M255_ENABLED) +static int ecp_mod_p255( mpi * ); +#endif +#if defined(POLARSSL_ECP_DP_SECP192K1_ENABLED) +static int ecp_mod_p192k1( mpi * ); +#endif +#if defined(POLARSSL_ECP_DP_SECP224K1_ENABLED) +static int ecp_mod_p224k1( mpi * ); +#endif +#if defined(POLARSSL_ECP_DP_SECP256K1_ENABLED) +static int ecp_mod_p256k1( mpi * ); +#endif + +#define LOAD_GROUP_A( G ) ecp_group_load( grp, \ + G ## _p, sizeof( G ## _p ), \ + G ## _a, sizeof( G ## _a ), \ + G ## _b, sizeof( G ## _b ), \ + G ## _gx, sizeof( G ## _gx ), \ + G ## _gy, sizeof( G ## _gy ), \ + G ## _n, sizeof( G ## _n ) ) + +#define LOAD_GROUP( G ) ecp_group_load( grp, \ + G ## _p, sizeof( G ## _p ), \ + NULL, 0, \ + G ## _b, sizeof( G ## _b ), \ + G ## _gx, sizeof( G ## _gx ), \ + G ## _gy, sizeof( G ## _gy ), \ + G ## _n, sizeof( G ## _n ) ) + +#if defined(POLARSSL_ECP_DP_M255_ENABLED) +/* + * Specialized function for creating the Curve25519 group + */ +static int ecp_use_curve25519( ecp_group *grp ) +{ + int ret; + + /* Actually ( A + 2 ) / 4 */ + MPI_CHK( mpi_read_string( &grp->A, 16, "01DB42" ) ); + + /* P = 2^255 - 19 */ + MPI_CHK( mpi_lset( &grp->P, 1 ) ); + MPI_CHK( mpi_shift_l( &grp->P, 255 ) ); + MPI_CHK( mpi_sub_int( &grp->P, &grp->P, 19 ) ); + grp->pbits = mpi_msb( &grp->P ); + + /* Y intentionaly not set, since we use x/z coordinates. + * This is used as a marker to identify Montgomery curves! */ + MPI_CHK( mpi_lset( &grp->G.X, 9 ) ); + MPI_CHK( mpi_lset( &grp->G.Z, 1 ) ); + mpi_free( &grp->G.Y ); + + /* Actually, the required msb for private keys */ + grp->nbits = 254; + +cleanup: + if( ret != 0 ) + ecp_group_free( grp ); + + return( ret ); +} +#endif /* POLARSSL_ECP_DP_M255_ENABLED */ + +/* + * Set a group using well-known domain parameters + */ +int ecp_use_known_dp( ecp_group *grp, ecp_group_id id ) +{ + ecp_group_free( grp ); + + grp->id = id; + + switch( id ) + { +#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED) + case POLARSSL_ECP_DP_SECP192R1: + NIST_MODP( p192 ); + return( LOAD_GROUP( secp192r1 ) ); +#endif /* POLARSSL_ECP_DP_SECP192R1_ENABLED */ + +#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED) + case POLARSSL_ECP_DP_SECP224R1: + NIST_MODP( p224 ); + return( LOAD_GROUP( secp224r1 ) ); +#endif /* POLARSSL_ECP_DP_SECP224R1_ENABLED */ + +#if defined(POLARSSL_ECP_DP_SECP256R1_ENABLED) + case POLARSSL_ECP_DP_SECP256R1: + NIST_MODP( p256 ); + return( LOAD_GROUP( secp256r1 ) ); +#endif /* POLARSSL_ECP_DP_SECP256R1_ENABLED */ + +#if defined(POLARSSL_ECP_DP_SECP384R1_ENABLED) + case POLARSSL_ECP_DP_SECP384R1: + NIST_MODP( p384 ); + return( LOAD_GROUP( secp384r1 ) ); +#endif /* POLARSSL_ECP_DP_SECP384R1_ENABLED */ + +#if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED) + case POLARSSL_ECP_DP_SECP521R1: + NIST_MODP( p521 ); + return( LOAD_GROUP( secp521r1 ) ); +#endif /* POLARSSL_ECP_DP_SECP521R1_ENABLED */ + +#if defined(POLARSSL_ECP_DP_SECP192K1_ENABLED) + case POLARSSL_ECP_DP_SECP192K1: + grp->modp = ecp_mod_p192k1; + return( LOAD_GROUP_A( secp192k1 ) ); +#endif /* POLARSSL_ECP_DP_SECP192K1_ENABLED */ + +#if defined(POLARSSL_ECP_DP_SECP224K1_ENABLED) + case POLARSSL_ECP_DP_SECP224K1: + grp->modp = ecp_mod_p224k1; + return( LOAD_GROUP_A( secp224k1 ) ); +#endif /* POLARSSL_ECP_DP_SECP224K1_ENABLED */ + +#if defined(POLARSSL_ECP_DP_SECP256K1_ENABLED) + case POLARSSL_ECP_DP_SECP256K1: + grp->modp = ecp_mod_p256k1; + return( LOAD_GROUP_A( secp256k1 ) ); +#endif /* POLARSSL_ECP_DP_SECP256K1_ENABLED */ + +#if defined(POLARSSL_ECP_DP_BP256R1_ENABLED) + case POLARSSL_ECP_DP_BP256R1: + return( LOAD_GROUP_A( brainpoolP256r1 ) ); +#endif /* POLARSSL_ECP_DP_BP256R1_ENABLED */ + +#if defined(POLARSSL_ECP_DP_BP384R1_ENABLED) + case POLARSSL_ECP_DP_BP384R1: + return( LOAD_GROUP_A( brainpoolP384r1 ) ); +#endif /* POLARSSL_ECP_DP_BP384R1_ENABLED */ + +#if defined(POLARSSL_ECP_DP_BP512R1_ENABLED) + case POLARSSL_ECP_DP_BP512R1: + return( LOAD_GROUP_A( brainpoolP512r1 ) ); +#endif /* POLARSSL_ECP_DP_BP512R1_ENABLED */ + +#if defined(POLARSSL_ECP_DP_M255_ENABLED) + case POLARSSL_ECP_DP_M255: + grp->modp = ecp_mod_p255; + return( ecp_use_curve25519( grp ) ); +#endif /* POLARSSL_ECP_DP_M255_ENABLED */ + + default: + ecp_group_free( grp ); + return( POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE ); + } +} + +#if defined(POLARSSL_ECP_NIST_OPTIM) +/* + * Fast reduction modulo the primes used by the NIST curves. + * + * These functions are critical for speed, but not needed for correct + * operations. So, we make the choice to heavily rely on the internals of our + * bignum library, which creates a tight coupling between these functions and + * our MPI implementation. However, the coupling between the ECP module and + * MPI remains loose, since these functions can be deactivated at will. + */ + +#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED) +/* + * Compared to the way things are presented in FIPS 186-3 D.2, + * we proceed in columns, from right (least significant chunk) to left, + * adding chunks to N in place, and keeping a carry for the next chunk. + * This avoids moving things around in memory, and uselessly adding zeros, + * compared to the more straightforward, line-oriented approach. + * + * For this prime we need to handle data in chunks of 64 bits. + * Since this is always a multiple of our basic t_uint, we can + * use a t_uint * to designate such a chunk, and small loops to handle it. + */ + +/* Add 64-bit chunks (dst += src) and update carry */ +static inline void add64( t_uint *dst, t_uint *src, t_uint *carry ) +{ + unsigned char i; + t_uint c = 0; + for( i = 0; i < 8 / sizeof( t_uint ); i++, dst++, src++ ) + { + *dst += c; c = ( *dst < c ); + *dst += *src; c += ( *dst < *src ); + } + *carry += c; +} + +/* Add carry to a 64-bit chunk and update carry */ +static inline void carry64( t_uint *dst, t_uint *carry ) +{ + unsigned char i; + for( i = 0; i < 8 / sizeof( t_uint ); i++, dst++ ) + { + *dst += *carry; + *carry = ( *dst < *carry ); + } +} + +#define WIDTH 8 / sizeof( t_uint ) +#define A( i ) N->p + i * WIDTH +#define ADD( i ) add64( p, A( i ), &c ) +#define NEXT p += WIDTH; carry64( p, &c ) +#define LAST p += WIDTH; *p = c; while( ++p < end ) *p = 0 + +/* + * Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1) + */ +static int ecp_mod_p192( mpi *N ) +{ + int ret; + t_uint c = 0; + t_uint *p, *end; + + /* Make sure we have enough blocks so that A(5) is legal */ + MPI_CHK( mpi_grow( N, 6 * WIDTH ) ); + + p = N->p; + end = p + N->n; + + ADD( 3 ); ADD( 5 ); NEXT; // A0 += A3 + A5 + ADD( 3 ); ADD( 4 ); ADD( 5 ); NEXT; // A1 += A3 + A4 + A5 + ADD( 4 ); ADD( 5 ); LAST; // A2 += A4 + A5 + +cleanup: + return( ret ); +} + +#undef WIDTH +#undef A +#undef ADD +#undef NEXT +#undef LAST +#endif /* POLARSSL_ECP_DP_SECP192R1_ENABLED */ + +#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED) || \ + defined(POLARSSL_ECP_DP_SECP256R1_ENABLED) || \ + defined(POLARSSL_ECP_DP_SECP384R1_ENABLED) +/* + * The reader is advised to first understand ecp_mod_p192() since the same + * general structure is used here, but with additional complications: + * (1) chunks of 32 bits, and (2) subtractions. + */ + +/* + * For these primes, we need to handle data in chunks of 32 bits. + * This makes it more complicated if we use 64 bits limbs in MPI, + * which prevents us from using a uniform access method as for p192. + * + * So, we define a mini abstraction layer to access 32 bit chunks, + * load them in 'cur' for work, and store them back from 'cur' when done. + * + * While at it, also define the size of N in terms of 32-bit chunks. + */ +#define LOAD32 cur = A( i ); + +#if defined(POLARSSL_HAVE_INT8) /* 8 bit */ + +#define MAX32 N->n / 4 +#define A( j ) (uint32_t)( N->p[4*j+0] ) | \ + ( N->p[4*j+1] << 8 ) | \ + ( N->p[4*j+2] << 16 ) | \ + ( N->p[4*j+3] << 24 ) +#define STORE32 N->p[4*i+0] = (t_uint)( cur ); \ + N->p[4*i+1] = (t_uint)( cur >> 8 ); \ + N->p[4*i+2] = (t_uint)( cur >> 16 ); \ + N->p[4*i+3] = (t_uint)( cur >> 24 ); + +#elif defined(POLARSSL_HAVE_INT16) /* 16 bit */ + +#define MAX32 N->n / 2 +#define A( j ) (uint32_t)( N->p[2*j] ) | ( N->p[2*j+1] << 16 ) +#define STORE32 N->p[2*i+0] = (t_uint)( cur ); \ + N->p[2*i+1] = (t_uint)( cur >> 16 ); + +#elif defined(POLARSSL_HAVE_INT32) /* 32 bit */ + +#define MAX32 N->n +#define A( j ) N->p[j] +#define STORE32 N->p[i] = cur; + +#else /* 64-bit */ + +#define MAX32 N->n * 2 +#define A( j ) j % 2 ? (uint32_t)( N->p[j/2] >> 32 ) : (uint32_t)( N->p[j/2] ) +#define STORE32 \ + if( i % 2 ) { \ + N->p[i/2] &= 0x00000000FFFFFFFF; \ + N->p[i/2] |= ((t_uint) cur) << 32; \ + } else { \ + N->p[i/2] &= 0xFFFFFFFF00000000; \ + N->p[i/2] |= (t_uint) cur; \ + } + +#endif /* sizeof( t_uint ) */ + +/* + * Helpers for addition and subtraction of chunks, with signed carry. + */ +static inline void add32( uint32_t *dst, uint32_t src, signed char *carry ) +{ + *dst += src; + *carry += ( *dst < src ); +} + +static inline void sub32( uint32_t *dst, uint32_t src, signed char *carry ) +{ + *carry -= ( *dst < src ); + *dst -= src; +} + +#define ADD( j ) add32( &cur, A( j ), &c ); +#define SUB( j ) sub32( &cur, A( j ), &c ); + +/* + * Helpers for the main 'loop' + * (see fix_negative for the motivation of C) + */ +#define INIT( b ) \ + int ret; \ + signed char c = 0, cc; \ + uint32_t cur; \ + size_t i = 0, bits = b; \ + mpi C; \ + t_uint Cp[ b / 8 / sizeof( t_uint) + 1 ]; \ + \ + C.s = 1; \ + C.n = b / 8 / sizeof( t_uint) + 1; \ + C.p = Cp; \ + memset( Cp, 0, C.n * sizeof( t_uint ) ); \ + \ + MPI_CHK( mpi_grow( N, b * 2 / 8 / sizeof( t_uint ) ) ); \ + LOAD32; + +#define NEXT \ + STORE32; i++; LOAD32; \ + cc = c; c = 0; \ + if( cc < 0 ) \ + sub32( &cur, -cc, &c ); \ + else \ + add32( &cur, cc, &c ); \ + +#define LAST \ + STORE32; i++; \ + cur = c > 0 ? c : 0; STORE32; \ + cur = 0; while( ++i < MAX32 ) { STORE32; } \ + if( c < 0 ) fix_negative( N, c, &C, bits ); + +/* + * If the result is negative, we get it in the form + * c * 2^(bits + 32) + N, with c negative and N positive shorter than 'bits' + */ +static inline int fix_negative( mpi *N, signed char c, mpi *C, size_t bits ) +{ + int ret; + + /* C = - c * 2^(bits + 32) */ +#if !defined(POLARSSL_HAVE_INT64) + ((void) bits); +#else + if( bits == 224 ) + C->p[ C->n - 1 ] = ((t_uint) -c) << 32; + else +#endif + C->p[ C->n - 1 ] = (t_uint) -c; + + /* N = - ( C - N ) */ + MPI_CHK( mpi_sub_abs( N, C, N ) ); + N->s = -1; + +cleanup: + + return( ret ); +} + +#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED) +/* + * Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2) + */ +static int ecp_mod_p224( mpi *N ) +{ + INIT( 224 ); + + SUB( 7 ); SUB( 11 ); NEXT; // A0 += -A7 - A11 + SUB( 8 ); SUB( 12 ); NEXT; // A1 += -A8 - A12 + SUB( 9 ); SUB( 13 ); NEXT; // A2 += -A9 - A13 + SUB( 10 ); ADD( 7 ); ADD( 11 ); NEXT; // A3 += -A10 + A7 + A11 + SUB( 11 ); ADD( 8 ); ADD( 12 ); NEXT; // A4 += -A11 + A8 + A12 + SUB( 12 ); ADD( 9 ); ADD( 13 ); NEXT; // A5 += -A12 + A9 + A13 + SUB( 13 ); ADD( 10 ); LAST; // A6 += -A13 + A10 + +cleanup: + return( ret ); +} +#endif /* POLARSSL_ECP_DP_SECP224R1_ENABLED */ + +#if defined(POLARSSL_ECP_DP_SECP256R1_ENABLED) +/* + * Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3) + */ +static int ecp_mod_p256( mpi *N ) +{ + INIT( 256 ); + + ADD( 8 ); ADD( 9 ); + SUB( 11 ); SUB( 12 ); SUB( 13 ); SUB( 14 ); NEXT; // A0 + + ADD( 9 ); ADD( 10 ); + SUB( 12 ); SUB( 13 ); SUB( 14 ); SUB( 15 ); NEXT; // A1 + + ADD( 10 ); ADD( 11 ); + SUB( 13 ); SUB( 14 ); SUB( 15 ); NEXT; // A2 + + ADD( 11 ); ADD( 11 ); ADD( 12 ); ADD( 12 ); ADD( 13 ); + SUB( 15 ); SUB( 8 ); SUB( 9 ); NEXT; // A3 + + ADD( 12 ); ADD( 12 ); ADD( 13 ); ADD( 13 ); ADD( 14 ); + SUB( 9 ); SUB( 10 ); NEXT; // A4 + + ADD( 13 ); ADD( 13 ); ADD( 14 ); ADD( 14 ); ADD( 15 ); + SUB( 10 ); SUB( 11 ); NEXT; // A5 + + ADD( 14 ); ADD( 14 ); ADD( 15 ); ADD( 15 ); ADD( 14 ); ADD( 13 ); + SUB( 8 ); SUB( 9 ); NEXT; // A6 + + ADD( 15 ); ADD( 15 ); ADD( 15 ); ADD( 8 ); + SUB( 10 ); SUB( 11 ); SUB( 12 ); SUB( 13 ); LAST; // A7 + +cleanup: + return( ret ); +} +#endif /* POLARSSL_ECP_DP_SECP256R1_ENABLED */ + +#if defined(POLARSSL_ECP_DP_SECP384R1_ENABLED) +/* + * Fast quasi-reduction modulo p384 (FIPS 186-3 D.2.4) + */ +static int ecp_mod_p384( mpi *N ) +{ + INIT( 384 ); + + ADD( 12 ); ADD( 21 ); ADD( 20 ); + SUB( 23 ); NEXT; // A0 + + ADD( 13 ); ADD( 22 ); ADD( 23 ); + SUB( 12 ); SUB( 20 ); NEXT; // A2 + + ADD( 14 ); ADD( 23 ); + SUB( 13 ); SUB( 21 ); NEXT; // A2 + + ADD( 15 ); ADD( 12 ); ADD( 20 ); ADD( 21 ); + SUB( 14 ); SUB( 22 ); SUB( 23 ); NEXT; // A3 + + ADD( 21 ); ADD( 21 ); ADD( 16 ); ADD( 13 ); ADD( 12 ); ADD( 20 ); ADD( 22 ); + SUB( 15 ); SUB( 23 ); SUB( 23 ); NEXT; // A4 + + ADD( 22 ); ADD( 22 ); ADD( 17 ); ADD( 14 ); ADD( 13 ); ADD( 21 ); ADD( 23 ); + SUB( 16 ); NEXT; // A5 + + ADD( 23 ); ADD( 23 ); ADD( 18 ); ADD( 15 ); ADD( 14 ); ADD( 22 ); + SUB( 17 ); NEXT; // A6 + + ADD( 19 ); ADD( 16 ); ADD( 15 ); ADD( 23 ); + SUB( 18 ); NEXT; // A7 + + ADD( 20 ); ADD( 17 ); ADD( 16 ); + SUB( 19 ); NEXT; // A8 + + ADD( 21 ); ADD( 18 ); ADD( 17 ); + SUB( 20 ); NEXT; // A9 + + ADD( 22 ); ADD( 19 ); ADD( 18 ); + SUB( 21 ); NEXT; // A10 + + ADD( 23 ); ADD( 20 ); ADD( 19 ); + SUB( 22 ); LAST; // A11 + +cleanup: + return( ret ); +} +#endif /* POLARSSL_ECP_DP_SECP384R1_ENABLED */ + +#undef A +#undef LOAD32 +#undef STORE32 +#undef MAX32 +#undef INIT +#undef NEXT +#undef LAST + +#endif /* POLARSSL_ECP_DP_SECP224R1_ENABLED || + POLARSSL_ECP_DP_SECP256R1_ENABLED || + POLARSSL_ECP_DP_SECP384R1_ENABLED */ + +#if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED) +/* + * Here we have an actual Mersenne prime, so things are more straightforward. + * However, chunks are aligned on a 'weird' boundary (521 bits). + */ + +/* Size of p521 in terms of t_uint */ +#define P521_WIDTH ( 521 / 8 / sizeof( t_uint ) + 1 ) + +/* Bits to keep in the most significant t_uint */ +#if defined(POLARSSL_HAVE_INT8) +#define P521_MASK 0x01 +#else +#define P521_MASK 0x01FF +#endif + +/* + * Fast quasi-reduction modulo p521 (FIPS 186-3 D.2.5) + * Write N as A1 + 2^521 A0, return A0 + A1 + */ +static int ecp_mod_p521( mpi *N ) +{ + int ret; + size_t i; + mpi M; + t_uint Mp[P521_WIDTH + 1]; + /* Worst case for the size of M is when t_uint is 16 bits: + * we need to hold bits 513 to 1056, which is 34 limbs, that is + * P521_WIDTH + 1. Otherwise P521_WIDTH is enough. */ + + if( N->n < P521_WIDTH ) + return( 0 ); + + /* M = A1 */ + M.s = 1; + M.n = N->n - ( P521_WIDTH - 1 ); + if( M.n > P521_WIDTH + 1 ) + M.n = P521_WIDTH + 1; + M.p = Mp; + memcpy( Mp, N->p + P521_WIDTH - 1, M.n * sizeof( t_uint ) ); + MPI_CHK( mpi_shift_r( &M, 521 % ( 8 * sizeof( t_uint ) ) ) ); + + /* N = A0 */ + N->p[P521_WIDTH - 1] &= P521_MASK; + for( i = P521_WIDTH; i < N->n; i++ ) + N->p[i] = 0; + + /* N = A0 + A1 */ + MPI_CHK( mpi_add_abs( N, N, &M ) ); + +cleanup: + return( ret ); +} + +#undef P521_WIDTH +#undef P521_MASK +#endif /* POLARSSL_ECP_DP_SECP521R1_ENABLED */ + +#endif /* POLARSSL_ECP_NIST_OPTIM */ + +#if defined(POLARSSL_ECP_DP_M255_ENABLED) + +/* Size of p255 in terms of t_uint */ +#define P255_WIDTH ( 255 / 8 / sizeof( t_uint ) + 1 ) + +/* + * Fast quasi-reduction modulo p255 = 2^255 - 19 + * Write N as A0 + 2^255 A1, return A0 + 19 * A1 + */ +static int ecp_mod_p255( mpi *N ) +{ + int ret; + size_t i; + mpi M; + t_uint Mp[P255_WIDTH + 2]; + + if( N->n < P255_WIDTH ) + return( 0 ); + + /* M = A1 */ + M.s = 1; + M.n = N->n - ( P255_WIDTH - 1 ); + if( M.n > P255_WIDTH + 1 ) + M.n = P255_WIDTH + 1; + M.p = Mp; + memset( Mp, 0, sizeof Mp ); + memcpy( Mp, N->p + P255_WIDTH - 1, M.n * sizeof( t_uint ) ); + MPI_CHK( mpi_shift_r( &M, 255 % ( 8 * sizeof( t_uint ) ) ) ); + M.n++; /* Make room for multiplication by 19 */ + + /* N = A0 */ + MPI_CHK( mpi_set_bit( N, 255, 0 ) ); + for( i = P255_WIDTH; i < N->n; i++ ) + N->p[i] = 0; + + /* N = A0 + 19 * A1 */ + MPI_CHK( mpi_mul_int( &M, &M, 19 ) ); + MPI_CHK( mpi_add_abs( N, N, &M ) ); + +cleanup: + return( ret ); +} +#endif /* POLARSSL_ECP_DP_M255_ENABLED */ + +#if defined(POLARSSL_ECP_DP_SECP192K1_ENABLED) || \ + defined(POLARSSL_ECP_DP_SECP224K1_ENABLED) || \ + defined(POLARSSL_ECP_DP_SECP256K1_ENABLED) +/* + * Fast quasi-reduction modulo P = 2^s - R, + * with R about 33 bits, used by the Koblitz curves. + * + * Write N as A0 + 2^224 A1, return A0 + R * A1. + * Actually do two passes, since R is big. + */ +#define P_KOBLITZ_MAX ( 256 / 8 / sizeof( t_uint ) ) // Max limbs in P +#define P_KOBLITZ_R ( 8 / sizeof( t_uint ) ) // Limbs in R +static inline int ecp_mod_koblitz( mpi *N, t_uint *Rp, size_t p_limbs, + size_t adjust, size_t shift, t_uint mask ) +{ + int ret; + size_t i; + mpi M, R; + t_uint Mp[P_KOBLITZ_MAX + P_KOBLITZ_R]; + + if( N->n < p_limbs ) + return( 0 ); + + /* Init R */ + R.s = 1; + R.p = Rp; + R.n = P_KOBLITZ_R; + + /* Common setup for M */ + M.s = 1; + M.p = Mp; + + /* M = A1 */ + M.n = N->n - ( p_limbs - adjust ); + if( M.n > p_limbs + adjust ) + M.n = p_limbs + adjust; + memset( Mp, 0, sizeof Mp ); + memcpy( Mp, N->p + p_limbs - adjust, M.n * sizeof( t_uint ) ); + if( shift != 0 ) + MPI_CHK( mpi_shift_r( &M, shift ) ); + M.n += R.n - adjust; /* Make room for multiplication by R */ + + /* N = A0 */ + if( mask != 0 ) + N->p[p_limbs - 1] &= mask; + for( i = p_limbs; i < N->n; i++ ) + N->p[i] = 0; + + /* N = A0 + R * A1 */ + MPI_CHK( mpi_mul_mpi( &M, &M, &R ) ); + MPI_CHK( mpi_add_abs( N, N, &M ) ); + + /* Second pass */ + + /* M = A1 */ + M.n = N->n - ( p_limbs - adjust ); + if( M.n > p_limbs + adjust ) + M.n = p_limbs + adjust; + memset( Mp, 0, sizeof Mp ); + memcpy( Mp, N->p + p_limbs - adjust, M.n * sizeof( t_uint ) ); + if( shift != 0 ) + MPI_CHK( mpi_shift_r( &M, shift ) ); + M.n += R.n - adjust; /* Make room for multiplication by R */ + + /* N = A0 */ + if( mask != 0 ) + N->p[p_limbs - 1] &= mask; + for( i = p_limbs; i < N->n; i++ ) + N->p[i] = 0; + + /* N = A0 + R * A1 */ + MPI_CHK( mpi_mul_mpi( &M, &M, &R ) ); + MPI_CHK( mpi_add_abs( N, N, &M ) ); + +cleanup: + return( ret ); +} +#endif /* POLARSSL_ECP_DP_SECP192K1_ENABLED) || + POLARSSL_ECP_DP_SECP224K1_ENABLED) || + POLARSSL_ECP_DP_SECP256K1_ENABLED) */ + +#if defined(POLARSSL_ECP_DP_SECP192K1_ENABLED) +/* + * Fast quasi-reduction modulo p192k1 = 2^192 - R, + * with R = 2^32 + 2^12 + 2^8 + 2^7 + 2^6 + 2^3 + 1 = 0x0100001119 + */ +static int ecp_mod_p192k1( mpi *N ) +{ + static t_uint Rp[] = { + BYTES_TO_T_UINT_8( 0xC9, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) }; + + return( ecp_mod_koblitz( N, Rp, 192 / 8 / sizeof( t_uint ), 0, 0, 0 ) ); +} +#endif /* POLARSSL_ECP_DP_SECP192K1_ENABLED */ + +#if defined(POLARSSL_ECP_DP_SECP224K1_ENABLED) +/* + * Fast quasi-reduction modulo p224k1 = 2^224 - R, + * with R = 2^32 + 2^12 + 2^11 + 2^9 + 2^7 + 2^4 + 2 + 1 = 0x0100001A93 + */ +static int ecp_mod_p224k1( mpi *N ) +{ + static t_uint Rp[] = { + BYTES_TO_T_UINT_8( 0x93, 0x1A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) }; + +#if defined(POLARSSL_HAVE_INT64) + return( ecp_mod_koblitz( N, Rp, 4, 1, 32, 0xFFFFFFFF ) ); +#else + return( ecp_mod_koblitz( N, Rp, 224 / 8 / sizeof( t_uint ), 0, 0, 0 ) ); +#endif +} + +#endif /* POLARSSL_ECP_DP_SECP224K1_ENABLED */ + +#if defined(POLARSSL_ECP_DP_SECP256K1_ENABLED) +/* + * Fast quasi-reduction modulo p256k1 = 2^256 - R, + * with R = 2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1 = 0x01000003D1 + */ +static int ecp_mod_p256k1( mpi *N ) +{ + static t_uint Rp[] = { + BYTES_TO_T_UINT_8( 0xD1, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) }; + return( ecp_mod_koblitz( N, Rp, 256 / 8 / sizeof( t_uint ), 0, 0, 0 ) ); +} +#endif /* POLARSSL_ECP_DP_SECP256K1_ENABLED */ + +#endif /* POLARSSL_ECP_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/entropy.c b/component/common/network/ssl/polarssl-1.3.8/library/entropy.c new file mode 100644 index 0000000..bc7fb0f --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/entropy.c @@ -0,0 +1,477 @@ +/* + * Entropy accumulator implementation + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_ENTROPY_C) + +#include "polarssl/entropy.h" +#include "polarssl/entropy_poll.h" + +#if defined(POLARSSL_FS_IO) +#include +#endif + +#if defined(POLARSSL_HAVEGE_C) +#include "polarssl/havege.h" +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +#define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */ + +void entropy_init( entropy_context *ctx ) +{ + memset( ctx, 0, sizeof(entropy_context) ); + +#if defined(POLARSSL_THREADING_C) + polarssl_mutex_init( &ctx->mutex ); +#endif + +#if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR) + sha512_starts( &ctx->accumulator, 0 ); +#else + sha256_starts( &ctx->accumulator, 0 ); +#endif +#if defined(POLARSSL_HAVEGE_C) + havege_init( &ctx->havege_data ); +#endif + +#if !defined(POLARSSL_NO_DEFAULT_ENTROPY_SOURCES) +#if !defined(POLARSSL_NO_PLATFORM_ENTROPY) + entropy_add_source( ctx, platform_entropy_poll, NULL, + ENTROPY_MIN_PLATFORM ); +#endif +#if defined(POLARSSL_TIMING_C) + entropy_add_source( ctx, hardclock_poll, NULL, ENTROPY_MIN_HARDCLOCK ); +#endif +#if defined(POLARSSL_HAVEGE_C) + entropy_add_source( ctx, havege_poll, &ctx->havege_data, + ENTROPY_MIN_HAVEGE ); +#endif +#endif /* POLARSSL_NO_DEFAULT_ENTROPY_SOURCES */ +} + +void entropy_free( entropy_context *ctx ) +{ +#if defined(POLARSSL_HAVEGE_C) + havege_free( &ctx->havege_data ); +#endif + polarssl_zeroize( ctx, sizeof( entropy_context ) ); +#if defined(POLARSSL_THREADING_C) + polarssl_mutex_free( &ctx->mutex ); +#endif +} + +int entropy_add_source( entropy_context *ctx, + f_source_ptr f_source, void *p_source, + size_t threshold ) +{ + int index, ret = 0; + +#if defined(POLARSSL_THREADING_C) + if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + index = ctx->source_count; + if( index >= ENTROPY_MAX_SOURCES ) + { + ret = POLARSSL_ERR_ENTROPY_MAX_SOURCES; + goto exit; + } + + ctx->source[index].f_source = f_source; + ctx->source[index].p_source = p_source; + ctx->source[index].threshold = threshold; + + ctx->source_count++; + +exit: +#if defined(POLARSSL_THREADING_C) + if( polarssl_mutex_unlock( &ctx->mutex ) != 0 ) + return( POLARSSL_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * Entropy accumulator update + */ +static int entropy_update( entropy_context *ctx, unsigned char source_id, + const unsigned char *data, size_t len ) +{ + unsigned char header[2]; + unsigned char tmp[ENTROPY_BLOCK_SIZE]; + size_t use_len = len; + const unsigned char *p = data; + + if( use_len > ENTROPY_BLOCK_SIZE ) + { +#if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR) + sha512( data, len, tmp, 0 ); +#else + sha256( data, len, tmp, 0 ); +#endif + p = tmp; + use_len = ENTROPY_BLOCK_SIZE; + } + + header[0] = source_id; + header[1] = use_len & 0xFF; + +#if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR) + sha512_update( &ctx->accumulator, header, 2 ); + sha512_update( &ctx->accumulator, p, use_len ); +#else + sha256_update( &ctx->accumulator, header, 2 ); + sha256_update( &ctx->accumulator, p, use_len ); +#endif + + return( 0 ); +} + +int entropy_update_manual( entropy_context *ctx, + const unsigned char *data, size_t len ) +{ + int ret; + +#if defined(POLARSSL_THREADING_C) + if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + ret = entropy_update( ctx, ENTROPY_SOURCE_MANUAL, data, len ); + +#if defined(POLARSSL_THREADING_C) + if( polarssl_mutex_unlock( &ctx->mutex ) != 0 ) + return( POLARSSL_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * Run through the different sources to add entropy to our accumulator + */ +static int entropy_gather_internal( entropy_context *ctx ) +{ + int ret, i; + unsigned char buf[ENTROPY_MAX_GATHER]; + size_t olen; + + if( ctx->source_count == 0 ) + return( POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED ); + + /* + * Run through our entropy sources + */ + for( i = 0; i < ctx->source_count; i++ ) + { + olen = 0; + if( ( ret = ctx->source[i].f_source( ctx->source[i].p_source, + buf, ENTROPY_MAX_GATHER, &olen ) ) != 0 ) + { + return( ret ); + } + + /* + * Add if we actually gathered something + */ + if( olen > 0 ) + { + entropy_update( ctx, (unsigned char) i, buf, olen ); + ctx->source[i].size += olen; + } + } + + return( 0 ); +} + +/* + * Thread-safe wrapper for entropy_gather_internal() + */ +int entropy_gather( entropy_context *ctx ) +{ + int ret; + +#if defined(POLARSSL_THREADING_C) + if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + ret = entropy_gather_internal( ctx ); + +#if defined(POLARSSL_THREADING_C) + if( polarssl_mutex_unlock( &ctx->mutex ) != 0 ) + return( POLARSSL_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +int entropy_func( void *data, unsigned char *output, size_t len ) +{ + int ret, count = 0, i, reached; + entropy_context *ctx = (entropy_context *) data; + unsigned char buf[ENTROPY_BLOCK_SIZE]; + + if( len > ENTROPY_BLOCK_SIZE ) + return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED ); + +#if defined(POLARSSL_THREADING_C) + if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + /* + * Always gather extra entropy before a call + */ + do + { + if( count++ > ENTROPY_MAX_LOOP ) + { + ret = POLARSSL_ERR_ENTROPY_SOURCE_FAILED; + goto exit; + } + + if( ( ret = entropy_gather_internal( ctx ) ) != 0 ) + goto exit; + + reached = 0; + + for( i = 0; i < ctx->source_count; i++ ) + if( ctx->source[i].size >= ctx->source[i].threshold ) + reached++; + } + while( reached != ctx->source_count ); + + memset( buf, 0, ENTROPY_BLOCK_SIZE ); + +#if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR) + sha512_finish( &ctx->accumulator, buf ); + + /* + * Reset accumulator and counters and recycle existing entropy + */ + memset( &ctx->accumulator, 0, sizeof( sha512_context ) ); + sha512_starts( &ctx->accumulator, 0 ); + sha512_update( &ctx->accumulator, buf, ENTROPY_BLOCK_SIZE ); + + /* + * Perform second SHA-512 on entropy + */ + sha512( buf, ENTROPY_BLOCK_SIZE, buf, 0 ); +#else /* POLARSSL_ENTROPY_SHA512_ACCUMULATOR */ + sha256_finish( &ctx->accumulator, buf ); + + /* + * Reset accumulator and counters and recycle existing entropy + */ + memset( &ctx->accumulator, 0, sizeof( sha256_context ) ); + sha256_starts( &ctx->accumulator, 0 ); + sha256_update( &ctx->accumulator, buf, ENTROPY_BLOCK_SIZE ); + + /* + * Perform second SHA-256 on entropy + */ + sha256( buf, ENTROPY_BLOCK_SIZE, buf, 0 ); +#endif /* POLARSSL_ENTROPY_SHA512_ACCUMULATOR */ + + for( i = 0; i < ctx->source_count; i++ ) + ctx->source[i].size = 0; + + memcpy( output, buf, len ); + + ret = 0; + +exit: +#if defined(POLARSSL_THREADING_C) + if( polarssl_mutex_unlock( &ctx->mutex ) != 0 ) + return( POLARSSL_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +#if defined(POLARSSL_FS_IO) +int entropy_write_seed_file( entropy_context *ctx, const char *path ) +{ + int ret = POLARSSL_ERR_ENTROPY_FILE_IO_ERROR; + FILE *f; + unsigned char buf[ENTROPY_BLOCK_SIZE]; + + if( ( f = fopen( path, "wb" ) ) == NULL ) + return( POLARSSL_ERR_ENTROPY_FILE_IO_ERROR ); + + if( ( ret = entropy_func( ctx, buf, ENTROPY_BLOCK_SIZE ) ) != 0 ) + goto exit; + + if( fwrite( buf, 1, ENTROPY_BLOCK_SIZE, f ) != ENTROPY_BLOCK_SIZE ) + { + ret = POLARSSL_ERR_ENTROPY_FILE_IO_ERROR; + goto exit; + } + + ret = 0; + +exit: + fclose( f ); + return( ret ); +} + +int entropy_update_seed_file( entropy_context *ctx, const char *path ) +{ + FILE *f; + size_t n; + unsigned char buf[ ENTROPY_MAX_SEED_SIZE ]; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( POLARSSL_ERR_ENTROPY_FILE_IO_ERROR ); + + fseek( f, 0, SEEK_END ); + n = (size_t) ftell( f ); + fseek( f, 0, SEEK_SET ); + + if( n > ENTROPY_MAX_SEED_SIZE ) + n = ENTROPY_MAX_SEED_SIZE; + + if( fread( buf, 1, n, f ) != n ) + { + fclose( f ); + return( POLARSSL_ERR_ENTROPY_FILE_IO_ERROR ); + } + + fclose( f ); + + entropy_update_manual( ctx, buf, n ); + + return( entropy_write_seed_file( ctx, path ) ); +} +#endif /* POLARSSL_FS_IO */ + +#if defined(POLARSSL_SELF_TEST) + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include +#define polarssl_printf printf +#endif + +/* + * Dummy source function + */ +static int entropy_dummy_source( void *data, unsigned char *output, + size_t len, size_t *olen ) +{ + ((void) data); + + memset( output, 0x2a, len ); + *olen = len; + + return( 0 ); +} + +/* + * The actual entropy quality is hard to test, but we can at least + * test that the functions don't cause errors and write the correct + * amount of data to buffers. + */ +int entropy_self_test( int verbose ) +{ + int ret = 0; + entropy_context ctx; + unsigned char buf[ENTROPY_BLOCK_SIZE] = { 0 }; + unsigned char acc[ENTROPY_BLOCK_SIZE] = { 0 }; + size_t i, j; + + if( verbose != 0 ) + polarssl_printf( " ENTROPY test: " ); + + entropy_init( &ctx ); + + ret = entropy_add_source( &ctx, entropy_dummy_source, NULL, 16 ); + if( ret != 0 ) + goto cleanup; + + if( ( ret = entropy_gather( &ctx ) ) != 0 ) + goto cleanup; + + if( ( ret = entropy_update_manual( &ctx, buf, sizeof buf ) ) != 0 ) + goto cleanup; + + /* + * To test that entropy_func writes correct number of bytes: + * - use the whole buffer and rely on ASan to detect overruns + * - collect entropy 8 times and OR the result in an accumulator: + * any byte should then be 0 with probably 2^(-64), so requiring + * each of the 32 or 64 bytes to be non-zero has a false failure rate + * of at most 2^(-58) which is acceptable. + */ + for( i = 0; i < 8; i++ ) + { + if( ( ret = entropy_func( &ctx, buf, sizeof( buf ) ) ) != 0 ) + goto cleanup; + + for( j = 0; j < sizeof( buf ); j++ ) + acc[j] |= buf[j]; + } + + for( j = 0; j < sizeof( buf ); j++ ) + { + if( acc[j] == 0 ) + { + ret = 1; + goto cleanup; + } + } + +cleanup: + entropy_free( &ctx ); + + if( verbose != 0 ) + { + if( ret != 0 ) + polarssl_printf( "failed\n" ); + else + polarssl_printf( "passed\n" ); + + polarssl_printf( "\n" ); + } + + return( ret != 0 ); +} +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_ENTROPY_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/entropy_poll.c b/component/common/network/ssl/polarssl-1.3.8/library/entropy_poll.c new file mode 100644 index 0000000..9ca9e95 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/entropy_poll.c @@ -0,0 +1,140 @@ +/* + * Platform-specific and custom entropy polling functions + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_ENTROPY_C) + +#include "polarssl/entropy.h" +#include "polarssl/entropy_poll.h" + +#if defined(POLARSSL_TIMING_C) +#include "polarssl/timing.h" +#endif +#if defined(POLARSSL_HAVEGE_C) +#include "polarssl/havege.h" +#endif + +#if !defined(POLARSSL_NO_PLATFORM_ENTROPY) +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + +#if !defined(_WIN32_WINNT) +#define _WIN32_WINNT 0x0400 +#endif +#include +#include + +int platform_entropy_poll( void *data, unsigned char *output, size_t len, + size_t *olen ) +{ + HCRYPTPROV provider; + ((void) data); + *olen = 0; + + if( CryptAcquireContext( &provider, NULL, NULL, + PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) == FALSE ) + { + return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED ); + } + + if( CryptGenRandom( provider, (DWORD) len, output ) == FALSE ) + return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED ); + + CryptReleaseContext( provider, 0 ); + *olen = len; + + return( 0 ); +} +#else /* _WIN32 && !EFIX64 && !EFI32 */ + +#include + +int platform_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + FILE *file; + size_t ret; + ((void) data); + + *olen = 0; + + file = fopen( "/dev/urandom", "rb" ); + if( file == NULL ) + return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED ); + + ret = fread( output, 1, len, file ); + if( ret != len ) + { + fclose( file ); + return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED ); + } + + fclose( file ); + *olen = len; + + return( 0 ); +} +#endif /* _WIN32 && !EFIX64 && !EFI32 */ +#endif /* !POLARSSL_NO_PLATFORM_ENTROPY */ + +#if defined(POLARSSL_TIMING_C) +int hardclock_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + unsigned long timer = hardclock(); + ((void) data); + *olen = 0; + + if( len < sizeof(unsigned long) ) + return( 0 ); + + memcpy( output, &timer, sizeof(unsigned long) ); + *olen = sizeof(unsigned long); + + return( 0 ); +} +#endif /* POLARSSL_TIMING_C */ + +#if defined(POLARSSL_HAVEGE_C) +int havege_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + havege_state *hs = (havege_state *) data; + *olen = 0; + + if( havege_random( hs, output, len ) != 0 ) + return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED ); + + *olen = len; + + return( 0 ); +} +#endif /* POLARSSL_HAVEGE_C */ + +#endif /* POLARSSL_ENTROPY_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/error.c b/component/common/network/ssl/polarssl-1.3.8/library/error.c new file mode 100644 index 0000000..22234cf --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/error.c @@ -0,0 +1,769 @@ +/* + * Error message information + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_ERROR_C) || defined(POLARSSL_ERROR_STRERROR_DUMMY) +#include "polarssl/error.h" +#endif + +#if defined(POLARSSL_ERROR_C) + +#if defined(POLARSSL_AES_C) +#include "polarssl/aes.h" +#endif + +#if defined(POLARSSL_BASE64_C) +#include "polarssl/base64.h" +#endif + +#if defined(POLARSSL_BIGNUM_C) +#include "polarssl/bignum.h" +#endif + +#if defined(POLARSSL_BLOWFISH_C) +#include "polarssl/blowfish.h" +#endif + +#if defined(POLARSSL_CAMELLIA_C) +#include "polarssl/camellia.h" +#endif + +#if defined(POLARSSL_CCM_C) +#include "polarssl/ccm.h" +#endif + +#if defined(POLARSSL_CIPHER_C) +#include "polarssl/cipher.h" +#endif + +#if defined(POLARSSL_CTR_DRBG_C) +#include "polarssl/ctr_drbg.h" +#endif + +#if defined(POLARSSL_DES_C) +#include "polarssl/des.h" +#endif + +#if defined(POLARSSL_DHM_C) +#include "polarssl/dhm.h" +#endif + +#if defined(POLARSSL_ECP_C) +#include "polarssl/ecp.h" +#endif + +#if defined(POLARSSL_ENTROPY_C) +#include "polarssl/entropy.h" +#endif + +#if defined(POLARSSL_GCM_C) +#include "polarssl/gcm.h" +#endif + +#if defined(POLARSSL_HMAC_DRBG_C) +#include "polarssl/hmac_drbg.h" +#endif + +#if defined(POLARSSL_MD_C) +#include "polarssl/md.h" +#endif + +#if defined(POLARSSL_MD2_C) +#include "polarssl/md2.h" +#endif + +#if defined(POLARSSL_MD4_C) +#include "polarssl/md4.h" +#endif + +#if defined(POLARSSL_MD5_C) +#include "polarssl/md5.h" +#endif + +#if defined(POLARSSL_NET_C) +#include "polarssl/net.h" +#endif + +#if defined(POLARSSL_OID_C) +#include "polarssl/oid.h" +#endif + +#if defined(POLARSSL_PADLOCK_C) +#include "polarssl/padlock.h" +#endif + +#if defined(POLARSSL_PBKDF2_C) +#include "polarssl/pbkdf2.h" +#endif + +#if defined(POLARSSL_PEM_PARSE_C) || defined(POLARSSL_PEM_WRITE_C) +#include "polarssl/pem.h" +#endif + +#if defined(POLARSSL_PK_C) +#include "polarssl/pk.h" +#endif + +#if defined(POLARSSL_PKCS12_C) +#include "polarssl/pkcs12.h" +#endif + +#if defined(POLARSSL_PKCS5_C) +#include "polarssl/pkcs5.h" +#endif + +#if defined(POLARSSL_RIPEMD160_C) +#include "polarssl/ripemd160.h" +#endif + +#if defined(POLARSSL_RSA_C) +#include "polarssl/rsa.h" +#endif + +#if defined(POLARSSL_SHA1_C) +#include "polarssl/sha1.h" +#endif + +#if defined(POLARSSL_SHA256_C) +#include "polarssl/sha256.h" +#endif + +#if defined(POLARSSL_SHA512_C) +#include "polarssl/sha512.h" +#endif + +#if defined(POLARSSL_SSL_TLS_C) +#include "polarssl/ssl.h" +#endif + +#if defined(POLARSSL_THREADING_C) +#include "polarssl/threading.h" +#endif + +#if defined(POLARSSL_X509_USE_C) || defined(POLARSSL_X509_CREATE_C) +#include "polarssl/x509.h" +#endif + +#if defined(POLARSSL_XTEA_C) +#include "polarssl/xtea.h" +#endif + + +#include + +#if defined(_MSC_VER) && !defined snprintf && !defined(EFIX64) && \ + !defined(EFI32) +#define snprintf _snprintf +#endif + +void polarssl_strerror( int ret, char *buf, size_t buflen ) +{ + size_t len; + int use_ret; + + if( buflen == 0 ) + return; + + memset( buf, 0x00, buflen ); + /* Reduce buflen to make sure MSVC _snprintf() ends with \0 as well */ + buflen -= 1; + + if( ret < 0 ) + ret = -ret; + + if( ret & 0xFF80 ) + { + use_ret = ret & 0xFF80; + + // High level error codes + // + // BEGIN generated code +#if defined(POLARSSL_CIPHER_C) + if( use_ret == -(POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE) ) + snprintf( buf, buflen, "CIPHER - The selected feature is not available" ); + if( use_ret == -(POLARSSL_ERR_CIPHER_BAD_INPUT_DATA) ) + snprintf( buf, buflen, "CIPHER - Bad input parameters to function" ); + if( use_ret == -(POLARSSL_ERR_CIPHER_ALLOC_FAILED) ) + snprintf( buf, buflen, "CIPHER - Failed to allocate memory" ); + if( use_ret == -(POLARSSL_ERR_CIPHER_INVALID_PADDING) ) + snprintf( buf, buflen, "CIPHER - Input data contains invalid padding and is rejected" ); + if( use_ret == -(POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED) ) + snprintf( buf, buflen, "CIPHER - Decryption of block requires a full block" ); + if( use_ret == -(POLARSSL_ERR_CIPHER_AUTH_FAILED) ) + snprintf( buf, buflen, "CIPHER - Authentication failed (for AEAD modes)" ); +#endif /* POLARSSL_CIPHER_C */ + +#if defined(POLARSSL_DHM_C) + if( use_ret == -(POLARSSL_ERR_DHM_BAD_INPUT_DATA) ) + snprintf( buf, buflen, "DHM - Bad input parameters to function" ); + if( use_ret == -(POLARSSL_ERR_DHM_READ_PARAMS_FAILED) ) + snprintf( buf, buflen, "DHM - Reading of the DHM parameters failed" ); + if( use_ret == -(POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED) ) + snprintf( buf, buflen, "DHM - Making of the DHM parameters failed" ); + if( use_ret == -(POLARSSL_ERR_DHM_READ_PUBLIC_FAILED) ) + snprintf( buf, buflen, "DHM - Reading of the public values failed" ); + if( use_ret == -(POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED) ) + snprintf( buf, buflen, "DHM - Making of the public value failed" ); + if( use_ret == -(POLARSSL_ERR_DHM_CALC_SECRET_FAILED) ) + snprintf( buf, buflen, "DHM - Calculation of the DHM secret failed" ); + if( use_ret == -(POLARSSL_ERR_DHM_INVALID_FORMAT) ) + snprintf( buf, buflen, "DHM - The ASN.1 data is not formatted correctly" ); + if( use_ret == -(POLARSSL_ERR_DHM_MALLOC_FAILED) ) + snprintf( buf, buflen, "DHM - Allocation of memory failed" ); + if( use_ret == -(POLARSSL_ERR_DHM_FILE_IO_ERROR) ) + snprintf( buf, buflen, "DHM - Read/write of file failed" ); +#endif /* POLARSSL_DHM_C */ + +#if defined(POLARSSL_ECP_C) + if( use_ret == -(POLARSSL_ERR_ECP_BAD_INPUT_DATA) ) + snprintf( buf, buflen, "ECP - Bad input parameters to function" ); + if( use_ret == -(POLARSSL_ERR_ECP_BUFFER_TOO_SMALL) ) + snprintf( buf, buflen, "ECP - The buffer is too small to write to" ); + if( use_ret == -(POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE) ) + snprintf( buf, buflen, "ECP - Requested curve not available" ); + if( use_ret == -(POLARSSL_ERR_ECP_VERIFY_FAILED) ) + snprintf( buf, buflen, "ECP - The signature is not valid" ); + if( use_ret == -(POLARSSL_ERR_ECP_MALLOC_FAILED) ) + snprintf( buf, buflen, "ECP - Memory allocation failed" ); + if( use_ret == -(POLARSSL_ERR_ECP_RANDOM_FAILED) ) + snprintf( buf, buflen, "ECP - Generation of random value, such as (ephemeral) key, failed" ); + if( use_ret == -(POLARSSL_ERR_ECP_INVALID_KEY) ) + snprintf( buf, buflen, "ECP - Invalid private or public key" ); + if( use_ret == -(POLARSSL_ERR_ECP_SIG_LEN_MISMATCH) ) + snprintf( buf, buflen, "ECP - Signature is valid but shorter than the user-supplied length" ); +#endif /* POLARSSL_ECP_C */ + +#if defined(POLARSSL_MD_C) + if( use_ret == -(POLARSSL_ERR_MD_FEATURE_UNAVAILABLE) ) + snprintf( buf, buflen, "MD - The selected feature is not available" ); + if( use_ret == -(POLARSSL_ERR_MD_BAD_INPUT_DATA) ) + snprintf( buf, buflen, "MD - Bad input parameters to function" ); + if( use_ret == -(POLARSSL_ERR_MD_ALLOC_FAILED) ) + snprintf( buf, buflen, "MD - Failed to allocate memory" ); + if( use_ret == -(POLARSSL_ERR_MD_FILE_IO_ERROR) ) + snprintf( buf, buflen, "MD - Opening or reading of file failed" ); +#endif /* POLARSSL_MD_C */ + +#if defined(POLARSSL_PEM_PARSE_C) || defined(POLARSSL_PEM_WRITE_C) + if( use_ret == -(POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT) ) + snprintf( buf, buflen, "PEM - No PEM header or footer found" ); + if( use_ret == -(POLARSSL_ERR_PEM_INVALID_DATA) ) + snprintf( buf, buflen, "PEM - PEM string is not as expected" ); + if( use_ret == -(POLARSSL_ERR_PEM_MALLOC_FAILED) ) + snprintf( buf, buflen, "PEM - Failed to allocate memory" ); + if( use_ret == -(POLARSSL_ERR_PEM_INVALID_ENC_IV) ) + snprintf( buf, buflen, "PEM - RSA IV is not in hex-format" ); + if( use_ret == -(POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG) ) + snprintf( buf, buflen, "PEM - Unsupported key encryption algorithm" ); + if( use_ret == -(POLARSSL_ERR_PEM_PASSWORD_REQUIRED) ) + snprintf( buf, buflen, "PEM - Private key password can't be empty" ); + if( use_ret == -(POLARSSL_ERR_PEM_PASSWORD_MISMATCH) ) + snprintf( buf, buflen, "PEM - Given private key password does not allow for correct decryption" ); + if( use_ret == -(POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE) ) + snprintf( buf, buflen, "PEM - Unavailable feature, e.g. hashing/encryption combination" ); + if( use_ret == -(POLARSSL_ERR_PEM_BAD_INPUT_DATA) ) + snprintf( buf, buflen, "PEM - Bad input parameters to function" ); +#endif /* POLARSSL_PEM_PARSE_C || POLARSSL_PEM_WRITE_C */ + +#if defined(POLARSSL_PK_C) + if( use_ret == -(POLARSSL_ERR_PK_MALLOC_FAILED) ) + snprintf( buf, buflen, "PK - Memory alloation failed" ); + if( use_ret == -(POLARSSL_ERR_PK_TYPE_MISMATCH) ) + snprintf( buf, buflen, "PK - Type mismatch, eg attempt to encrypt with an ECDSA key" ); + if( use_ret == -(POLARSSL_ERR_PK_BAD_INPUT_DATA) ) + snprintf( buf, buflen, "PK - Bad input parameters to function" ); + if( use_ret == -(POLARSSL_ERR_PK_FILE_IO_ERROR) ) + snprintf( buf, buflen, "PK - Read/write of file failed" ); + if( use_ret == -(POLARSSL_ERR_PK_KEY_INVALID_VERSION) ) + snprintf( buf, buflen, "PK - Unsupported key version" ); + if( use_ret == -(POLARSSL_ERR_PK_KEY_INVALID_FORMAT) ) + snprintf( buf, buflen, "PK - Invalid key tag or value" ); + if( use_ret == -(POLARSSL_ERR_PK_UNKNOWN_PK_ALG) ) + snprintf( buf, buflen, "PK - Key algorithm is unsupported (only RSA and EC are supported)" ); + if( use_ret == -(POLARSSL_ERR_PK_PASSWORD_REQUIRED) ) + snprintf( buf, buflen, "PK - Private key password can't be empty" ); + if( use_ret == -(POLARSSL_ERR_PK_PASSWORD_MISMATCH) ) + snprintf( buf, buflen, "PK - Given private key password does not allow for correct decryption" ); + if( use_ret == -(POLARSSL_ERR_PK_INVALID_PUBKEY) ) + snprintf( buf, buflen, "PK - The pubkey tag or value is invalid (only RSA and EC are supported)" ); + if( use_ret == -(POLARSSL_ERR_PK_INVALID_ALG) ) + snprintf( buf, buflen, "PK - The algorithm tag or value is invalid" ); + if( use_ret == -(POLARSSL_ERR_PK_UNKNOWN_NAMED_CURVE) ) + snprintf( buf, buflen, "PK - Elliptic curve is unsupported (only NIST curves are supported)" ); + if( use_ret == -(POLARSSL_ERR_PK_FEATURE_UNAVAILABLE) ) + snprintf( buf, buflen, "PK - Unavailable feature, e.g. RSA disabled for RSA key" ); + if( use_ret == -(POLARSSL_ERR_PK_SIG_LEN_MISMATCH) ) + snprintf( buf, buflen, "PK - The signature is valid but its length is less than expected" ); +#endif /* POLARSSL_PK_C */ + +#if defined(POLARSSL_PKCS12_C) + if( use_ret == -(POLARSSL_ERR_PKCS12_BAD_INPUT_DATA) ) + snprintf( buf, buflen, "PKCS12 - Bad input parameters to function" ); + if( use_ret == -(POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE) ) + snprintf( buf, buflen, "PKCS12 - Feature not available, e.g. unsupported encryption scheme" ); + if( use_ret == -(POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT) ) + snprintf( buf, buflen, "PKCS12 - PBE ASN.1 data not as expected" ); + if( use_ret == -(POLARSSL_ERR_PKCS12_PASSWORD_MISMATCH) ) + snprintf( buf, buflen, "PKCS12 - Given private key password does not allow for correct decryption" ); +#endif /* POLARSSL_PKCS12_C */ + +#if defined(POLARSSL_PKCS5_C) + if( use_ret == -(POLARSSL_ERR_PKCS5_BAD_INPUT_DATA) ) + snprintf( buf, buflen, "PKCS5 - Bad input parameters to function" ); + if( use_ret == -(POLARSSL_ERR_PKCS5_INVALID_FORMAT) ) + snprintf( buf, buflen, "PKCS5 - Unexpected ASN.1 data" ); + if( use_ret == -(POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE) ) + snprintf( buf, buflen, "PKCS5 - Requested encryption or digest alg not available" ); + if( use_ret == -(POLARSSL_ERR_PKCS5_PASSWORD_MISMATCH) ) + snprintf( buf, buflen, "PKCS5 - Given private key password does not allow for correct decryption" ); +#endif /* POLARSSL_PKCS5_C */ + +#if defined(POLARSSL_RSA_C) + if( use_ret == -(POLARSSL_ERR_RSA_BAD_INPUT_DATA) ) + snprintf( buf, buflen, "RSA - Bad input parameters to function" ); + if( use_ret == -(POLARSSL_ERR_RSA_INVALID_PADDING) ) + snprintf( buf, buflen, "RSA - Input data contains invalid padding and is rejected" ); + if( use_ret == -(POLARSSL_ERR_RSA_KEY_GEN_FAILED) ) + snprintf( buf, buflen, "RSA - Something failed during generation of a key" ); + if( use_ret == -(POLARSSL_ERR_RSA_KEY_CHECK_FAILED) ) + snprintf( buf, buflen, "RSA - Key failed to pass the libraries validity check" ); + if( use_ret == -(POLARSSL_ERR_RSA_PUBLIC_FAILED) ) + snprintf( buf, buflen, "RSA - The public key operation failed" ); + if( use_ret == -(POLARSSL_ERR_RSA_PRIVATE_FAILED) ) + snprintf( buf, buflen, "RSA - The private key operation failed" ); + if( use_ret == -(POLARSSL_ERR_RSA_VERIFY_FAILED) ) + snprintf( buf, buflen, "RSA - The PKCS#1 verification failed" ); + if( use_ret == -(POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE) ) + snprintf( buf, buflen, "RSA - The output buffer for decryption is not large enough" ); + if( use_ret == -(POLARSSL_ERR_RSA_RNG_FAILED) ) + snprintf( buf, buflen, "RSA - The random generator failed to generate non-zeros" ); +#endif /* POLARSSL_RSA_C */ + +#if defined(POLARSSL_SSL_TLS_C) + if( use_ret == -(POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE) ) + snprintf( buf, buflen, "SSL - The requested feature is not available" ); + if( use_ret == -(POLARSSL_ERR_SSL_BAD_INPUT_DATA) ) + snprintf( buf, buflen, "SSL - Bad input parameters to function" ); + if( use_ret == -(POLARSSL_ERR_SSL_INVALID_MAC) ) + snprintf( buf, buflen, "SSL - Verification of the message MAC failed" ); + if( use_ret == -(POLARSSL_ERR_SSL_INVALID_RECORD) ) + snprintf( buf, buflen, "SSL - An invalid SSL record was received" ); + if( use_ret == -(POLARSSL_ERR_SSL_CONN_EOF) ) + snprintf( buf, buflen, "SSL - The connection indicated an EOF" ); + if( use_ret == -(POLARSSL_ERR_SSL_UNKNOWN_CIPHER) ) + snprintf( buf, buflen, "SSL - An unknown cipher was received" ); + if( use_ret == -(POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN) ) + snprintf( buf, buflen, "SSL - The server has no ciphersuites in common with the client" ); + if( use_ret == -(POLARSSL_ERR_SSL_NO_RNG) ) + snprintf( buf, buflen, "SSL - No RNG was provided to the SSL module" ); + if( use_ret == -(POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE) ) + snprintf( buf, buflen, "SSL - No client certification received from the client, but required by the authentication mode" ); + if( use_ret == -(POLARSSL_ERR_SSL_CERTIFICATE_TOO_LARGE) ) + snprintf( buf, buflen, "SSL - DESCRIPTION MISSING" ); + if( use_ret == -(POLARSSL_ERR_SSL_CERTIFICATE_REQUIRED) ) + snprintf( buf, buflen, "SSL - The own certificate is not set, but needed by the server" ); + if( use_ret == -(POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED) ) + snprintf( buf, buflen, "SSL - The own private key or pre-shared key is not set, but needed" ); + if( use_ret == -(POLARSSL_ERR_SSL_CA_CHAIN_REQUIRED) ) + snprintf( buf, buflen, "SSL - No CA Chain is set, but required to operate" ); + if( use_ret == -(POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE) ) + snprintf( buf, buflen, "SSL - An unexpected message was received from our peer" ); + if( use_ret == -(POLARSSL_ERR_SSL_FATAL_ALERT_MESSAGE) ) + { + snprintf( buf, buflen, "SSL - A fatal alert message was received from our peer" ); + return; + } + if( use_ret == -(POLARSSL_ERR_SSL_PEER_VERIFY_FAILED) ) + snprintf( buf, buflen, "SSL - Verification of our peer failed" ); + if( use_ret == -(POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY) ) + snprintf( buf, buflen, "SSL - The peer notified us that the connection is going to be closed" ); + if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO) ) + snprintf( buf, buflen, "SSL - Processing of the ClientHello handshake message failed" ); + if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO) ) + snprintf( buf, buflen, "SSL - Processing of the ServerHello handshake message failed" ); + if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE) ) + snprintf( buf, buflen, "SSL - Processing of the Certificate handshake message failed" ); + if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST) ) + snprintf( buf, buflen, "SSL - Processing of the CertificateRequest handshake message failed" ); + if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE) ) + snprintf( buf, buflen, "SSL - Processing of the ServerKeyExchange handshake message failed" ); + if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO_DONE) ) + snprintf( buf, buflen, "SSL - Processing of the ServerHelloDone handshake message failed" ); + if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE) ) + snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed" ); + if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP) ) + snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Read Public" ); + if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS) ) + snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Calculate Secret" ); + if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY) ) + snprintf( buf, buflen, "SSL - Processing of the CertificateVerify handshake message failed" ); + if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC) ) + snprintf( buf, buflen, "SSL - Processing of the ChangeCipherSpec handshake message failed" ); + if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_FINISHED) ) + snprintf( buf, buflen, "SSL - Processing of the Finished handshake message failed" ); + if( use_ret == -(POLARSSL_ERR_SSL_MALLOC_FAILED) ) + snprintf( buf, buflen, "SSL - Memory allocation failed" ); + if( use_ret == -(POLARSSL_ERR_SSL_HW_ACCEL_FAILED) ) + snprintf( buf, buflen, "SSL - Hardware acceleration function returned with error" ); + if( use_ret == -(POLARSSL_ERR_SSL_HW_ACCEL_FALLTHROUGH) ) + snprintf( buf, buflen, "SSL - Hardware acceleration function skipped / left alone data" ); + if( use_ret == -(POLARSSL_ERR_SSL_COMPRESSION_FAILED) ) + snprintf( buf, buflen, "SSL - Processing of the compression / decompression failed" ); + if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_PROTOCOL_VERSION) ) + snprintf( buf, buflen, "SSL - Handshake protocol not within min/max boundaries" ); + if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_NEW_SESSION_TICKET) ) + snprintf( buf, buflen, "SSL - Processing of the NewSessionTicket handshake message failed" ); + if( use_ret == -(POLARSSL_ERR_SSL_SESSION_TICKET_EXPIRED) ) + snprintf( buf, buflen, "SSL - Session ticket has expired" ); + if( use_ret == -(POLARSSL_ERR_SSL_PK_TYPE_MISMATCH) ) + snprintf( buf, buflen, "SSL - Public key type mismatch (eg, asked for RSA key exchange and presented EC key)" ); + if( use_ret == -(POLARSSL_ERR_SSL_UNKNOWN_IDENTITY) ) + snprintf( buf, buflen, "SSL - Unknown identity received (eg, PSK identity)" ); + if( use_ret == -(POLARSSL_ERR_SSL_INTERNAL_ERROR) ) + snprintf( buf, buflen, "SSL - Internal error (eg, unexpected failure in lower-level module)" ); + if( use_ret == -(POLARSSL_ERR_SSL_COUNTER_WRAPPING) ) + snprintf( buf, buflen, "SSL - A counter would wrap (eg, too many messages exchanged)" ); +#endif /* POLARSSL_SSL_TLS_C */ + +#if defined(POLARSSL_X509_USE_C) || defined(POLARSSL_X509_CREATE_C) + if( use_ret == -(POLARSSL_ERR_X509_FEATURE_UNAVAILABLE) ) + snprintf( buf, buflen, "X509 - Unavailable feature, e.g. RSA hashing/encryption combination" ); + if( use_ret == -(POLARSSL_ERR_X509_UNKNOWN_OID) ) + snprintf( buf, buflen, "X509 - Requested OID is unknown" ); + if( use_ret == -(POLARSSL_ERR_X509_INVALID_FORMAT) ) + snprintf( buf, buflen, "X509 - The CRT/CRL/CSR format is invalid, e.g. different type expected" ); + if( use_ret == -(POLARSSL_ERR_X509_INVALID_VERSION) ) + snprintf( buf, buflen, "X509 - The CRT/CRL/CSR version element is invalid" ); + if( use_ret == -(POLARSSL_ERR_X509_INVALID_SERIAL) ) + snprintf( buf, buflen, "X509 - The serial tag or value is invalid" ); + if( use_ret == -(POLARSSL_ERR_X509_INVALID_ALG) ) + snprintf( buf, buflen, "X509 - The algorithm tag or value is invalid" ); + if( use_ret == -(POLARSSL_ERR_X509_INVALID_NAME) ) + snprintf( buf, buflen, "X509 - The name tag or value is invalid" ); + if( use_ret == -(POLARSSL_ERR_X509_INVALID_DATE) ) + snprintf( buf, buflen, "X509 - The date tag or value is invalid" ); + if( use_ret == -(POLARSSL_ERR_X509_INVALID_SIGNATURE) ) + snprintf( buf, buflen, "X509 - The signature tag or value invalid" ); + if( use_ret == -(POLARSSL_ERR_X509_INVALID_EXTENSIONS) ) + snprintf( buf, buflen, "X509 - The extension tag or value is invalid" ); + if( use_ret == -(POLARSSL_ERR_X509_UNKNOWN_VERSION) ) + snprintf( buf, buflen, "X509 - CRT/CRL/CSR has an unsupported version number" ); + if( use_ret == -(POLARSSL_ERR_X509_UNKNOWN_SIG_ALG) ) + snprintf( buf, buflen, "X509 - Signature algorithm (oid) is unsupported" ); + if( use_ret == -(POLARSSL_ERR_X509_SIG_MISMATCH) ) + snprintf( buf, buflen, "X509 - Signature algorithms do not match. (see \\c ::x509_crt sig_oid)" ); + if( use_ret == -(POLARSSL_ERR_X509_CERT_VERIFY_FAILED) ) + snprintf( buf, buflen, "X509 - Certificate verification failed, e.g. CRL, CA or signature check failed" ); + if( use_ret == -(POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT) ) + snprintf( buf, buflen, "X509 - Format not recognized as DER or PEM" ); + if( use_ret == -(POLARSSL_ERR_X509_BAD_INPUT_DATA) ) + snprintf( buf, buflen, "X509 - Input invalid" ); + if( use_ret == -(POLARSSL_ERR_X509_MALLOC_FAILED) ) + snprintf( buf, buflen, "X509 - Allocation of memory failed" ); + if( use_ret == -(POLARSSL_ERR_X509_FILE_IO_ERROR) ) + snprintf( buf, buflen, "X509 - Read/write of file failed" ); +#endif /* POLARSSL_X509_USE,X509_CREATE_C */ + // END generated code + + if( strlen( buf ) == 0 ) + snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", use_ret ); + } + + use_ret = ret & ~0xFF80; + + if( use_ret == 0 ) + return; + + // If high level code is present, make a concatenation between both + // error strings. + // + len = strlen( buf ); + + if( len > 0 ) + { + if( buflen - len < 5 ) + return; + + snprintf( buf + len, buflen - len, " : " ); + + buf += len + 3; + buflen -= len + 3; + } + + // Low level error codes + // + // BEGIN generated code +#if defined(POLARSSL_AES_C) + if( use_ret == -(POLARSSL_ERR_AES_INVALID_KEY_LENGTH) ) + snprintf( buf, buflen, "AES - Invalid key length" ); + if( use_ret == -(POLARSSL_ERR_AES_INVALID_INPUT_LENGTH) ) + snprintf( buf, buflen, "AES - Invalid data input length" ); +#endif /* POLARSSL_AES_C */ + +#if defined(POLARSSL_ASN1_PARSE_C) + if( use_ret == -(POLARSSL_ERR_ASN1_OUT_OF_DATA) ) + snprintf( buf, buflen, "ASN1 - Out of data when parsing an ASN1 data structure" ); + if( use_ret == -(POLARSSL_ERR_ASN1_UNEXPECTED_TAG) ) + snprintf( buf, buflen, "ASN1 - ASN1 tag was of an unexpected value" ); + if( use_ret == -(POLARSSL_ERR_ASN1_INVALID_LENGTH) ) + snprintf( buf, buflen, "ASN1 - Error when trying to determine the length or invalid length" ); + if( use_ret == -(POLARSSL_ERR_ASN1_LENGTH_MISMATCH) ) + snprintf( buf, buflen, "ASN1 - Actual length differs from expected length" ); + if( use_ret == -(POLARSSL_ERR_ASN1_INVALID_DATA) ) + snprintf( buf, buflen, "ASN1 - Data is invalid. (not used)" ); + if( use_ret == -(POLARSSL_ERR_ASN1_MALLOC_FAILED) ) + snprintf( buf, buflen, "ASN1 - Memory allocation failed" ); + if( use_ret == -(POLARSSL_ERR_ASN1_BUF_TOO_SMALL) ) + snprintf( buf, buflen, "ASN1 - Buffer too small when writing ASN.1 data structure" ); +#endif /* POLARSSL_ASN1_PARSE_C */ + +#if defined(POLARSSL_BASE64_C) + if( use_ret == -(POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL) ) + snprintf( buf, buflen, "BASE64 - Output buffer too small" ); + if( use_ret == -(POLARSSL_ERR_BASE64_INVALID_CHARACTER) ) + snprintf( buf, buflen, "BASE64 - Invalid character in input" ); +#endif /* POLARSSL_BASE64_C */ + +#if defined(POLARSSL_BIGNUM_C) + if( use_ret == -(POLARSSL_ERR_MPI_FILE_IO_ERROR) ) + snprintf( buf, buflen, "BIGNUM - An error occurred while reading from or writing to a file" ); + if( use_ret == -(POLARSSL_ERR_MPI_BAD_INPUT_DATA) ) + snprintf( buf, buflen, "BIGNUM - Bad input parameters to function" ); + if( use_ret == -(POLARSSL_ERR_MPI_INVALID_CHARACTER) ) + snprintf( buf, buflen, "BIGNUM - There is an invalid character in the digit string" ); + if( use_ret == -(POLARSSL_ERR_MPI_BUFFER_TOO_SMALL) ) + snprintf( buf, buflen, "BIGNUM - The buffer is too small to write to" ); + if( use_ret == -(POLARSSL_ERR_MPI_NEGATIVE_VALUE) ) + snprintf( buf, buflen, "BIGNUM - The input arguments are negative or result in illegal output" ); + if( use_ret == -(POLARSSL_ERR_MPI_DIVISION_BY_ZERO) ) + snprintf( buf, buflen, "BIGNUM - The input argument for division is zero, which is not allowed" ); + if( use_ret == -(POLARSSL_ERR_MPI_NOT_ACCEPTABLE) ) + snprintf( buf, buflen, "BIGNUM - The input arguments are not acceptable" ); + if( use_ret == -(POLARSSL_ERR_MPI_MALLOC_FAILED) ) + snprintf( buf, buflen, "BIGNUM - Memory allocation failed" ); +#endif /* POLARSSL_BIGNUM_C */ + +#if defined(POLARSSL_BLOWFISH_C) + if( use_ret == -(POLARSSL_ERR_BLOWFISH_INVALID_KEY_LENGTH) ) + snprintf( buf, buflen, "BLOWFISH - Invalid key length" ); + if( use_ret == -(POLARSSL_ERR_BLOWFISH_INVALID_INPUT_LENGTH) ) + snprintf( buf, buflen, "BLOWFISH - Invalid data input length" ); +#endif /* POLARSSL_BLOWFISH_C */ + +#if defined(POLARSSL_CAMELLIA_C) + if( use_ret == -(POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH) ) + snprintf( buf, buflen, "CAMELLIA - Invalid key length" ); + if( use_ret == -(POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH) ) + snprintf( buf, buflen, "CAMELLIA - Invalid data input length" ); +#endif /* POLARSSL_CAMELLIA_C */ + +#if defined(POLARSSL_CCM_C) + if( use_ret == -(POLARSSL_ERR_CCM_BAD_INPUT) ) + snprintf( buf, buflen, "CCM - Bad input parameters to function" ); + if( use_ret == -(POLARSSL_ERR_CCM_AUTH_FAILED) ) + snprintf( buf, buflen, "CCM - Authenticated decryption failed" ); +#endif /* POLARSSL_CCM_C */ + +#if defined(POLARSSL_CTR_DRBG_C) + if( use_ret == -(POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED) ) + snprintf( buf, buflen, "CTR_DRBG - The entropy source failed" ); + if( use_ret == -(POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG) ) + snprintf( buf, buflen, "CTR_DRBG - Too many random requested in single call" ); + if( use_ret == -(POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG) ) + snprintf( buf, buflen, "CTR_DRBG - Input too large (Entropy + additional)" ); + if( use_ret == -(POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR) ) + snprintf( buf, buflen, "CTR_DRBG - Read/write error in file" ); +#endif /* POLARSSL_CTR_DRBG_C */ + +#if defined(POLARSSL_DES_C) + if( use_ret == -(POLARSSL_ERR_DES_INVALID_INPUT_LENGTH) ) + snprintf( buf, buflen, "DES - The data input has an invalid length" ); +#endif /* POLARSSL_DES_C */ + +#if defined(POLARSSL_ENTROPY_C) + if( use_ret == -(POLARSSL_ERR_ENTROPY_SOURCE_FAILED) ) + snprintf( buf, buflen, "ENTROPY - Critical entropy source failure" ); + if( use_ret == -(POLARSSL_ERR_ENTROPY_MAX_SOURCES) ) + snprintf( buf, buflen, "ENTROPY - No more sources can be added" ); + if( use_ret == -(POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED) ) + snprintf( buf, buflen, "ENTROPY - No sources have been added to poll" ); + if( use_ret == -(POLARSSL_ERR_ENTROPY_FILE_IO_ERROR) ) + snprintf( buf, buflen, "ENTROPY - Read/write error in file" ); +#endif /* POLARSSL_ENTROPY_C */ + +#if defined(POLARSSL_GCM_C) + if( use_ret == -(POLARSSL_ERR_GCM_AUTH_FAILED) ) + snprintf( buf, buflen, "GCM - Authenticated decryption failed" ); + if( use_ret == -(POLARSSL_ERR_GCM_BAD_INPUT) ) + snprintf( buf, buflen, "GCM - Bad input parameters to function" ); +#endif /* POLARSSL_GCM_C */ + +#if defined(POLARSSL_HMAC_DRBG_C) + if( use_ret == -(POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG) ) + snprintf( buf, buflen, "HMAC_DRBG - Too many random requested in single call" ); + if( use_ret == -(POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG) ) + snprintf( buf, buflen, "HMAC_DRBG - Input too large (Entropy + additional)" ); + if( use_ret == -(POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR) ) + snprintf( buf, buflen, "HMAC_DRBG - Read/write error in file" ); + if( use_ret == -(POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED) ) + snprintf( buf, buflen, "HMAC_DRBG - The entropy source failed" ); +#endif /* POLARSSL_HMAC_DRBG_C */ + +#if defined(POLARSSL_MD2_C) + if( use_ret == -(POLARSSL_ERR_MD2_FILE_IO_ERROR) ) + snprintf( buf, buflen, "MD2 - Read/write error in file" ); +#endif /* POLARSSL_MD2_C */ + +#if defined(POLARSSL_MD4_C) + if( use_ret == -(POLARSSL_ERR_MD4_FILE_IO_ERROR) ) + snprintf( buf, buflen, "MD4 - Read/write error in file" ); +#endif /* POLARSSL_MD4_C */ + +#if defined(POLARSSL_MD5_C) + if( use_ret == -(POLARSSL_ERR_MD5_FILE_IO_ERROR) ) + snprintf( buf, buflen, "MD5 - Read/write error in file" ); +#endif /* POLARSSL_MD5_C */ + +#if defined(POLARSSL_NET_C) + if( use_ret == -(POLARSSL_ERR_NET_UNKNOWN_HOST) ) + snprintf( buf, buflen, "NET - Failed to get an IP address for the given hostname" ); + if( use_ret == -(POLARSSL_ERR_NET_SOCKET_FAILED) ) + snprintf( buf, buflen, "NET - Failed to open a socket" ); + if( use_ret == -(POLARSSL_ERR_NET_CONNECT_FAILED) ) + snprintf( buf, buflen, "NET - The connection to the given server / port failed" ); + if( use_ret == -(POLARSSL_ERR_NET_BIND_FAILED) ) + snprintf( buf, buflen, "NET - Binding of the socket failed" ); + if( use_ret == -(POLARSSL_ERR_NET_LISTEN_FAILED) ) + snprintf( buf, buflen, "NET - Could not listen on the socket" ); + if( use_ret == -(POLARSSL_ERR_NET_ACCEPT_FAILED) ) + snprintf( buf, buflen, "NET - Could not accept the incoming connection" ); + if( use_ret == -(POLARSSL_ERR_NET_RECV_FAILED) ) + snprintf( buf, buflen, "NET - Reading information from the socket failed" ); + if( use_ret == -(POLARSSL_ERR_NET_SEND_FAILED) ) + snprintf( buf, buflen, "NET - Sending information through the socket failed" ); + if( use_ret == -(POLARSSL_ERR_NET_CONN_RESET) ) + snprintf( buf, buflen, "NET - Connection was reset by peer" ); + if( use_ret == -(POLARSSL_ERR_NET_WANT_READ) ) + snprintf( buf, buflen, "NET - Connection requires a read call" ); + if( use_ret == -(POLARSSL_ERR_NET_WANT_WRITE) ) + snprintf( buf, buflen, "NET - Connection requires a write call" ); +#endif /* POLARSSL_NET_C */ + +#if defined(POLARSSL_OID_C) + if( use_ret == -(POLARSSL_ERR_OID_NOT_FOUND) ) + snprintf( buf, buflen, "OID - OID is not found" ); + if( use_ret == -(POLARSSL_ERR_OID_BUF_TOO_SMALL) ) + snprintf( buf, buflen, "OID - output buffer is too small" ); +#endif /* POLARSSL_OID_C */ + +#if defined(POLARSSL_PADLOCK_C) + if( use_ret == -(POLARSSL_ERR_PADLOCK_DATA_MISALIGNED) ) + snprintf( buf, buflen, "PADLOCK - Input data should be aligned" ); +#endif /* POLARSSL_PADLOCK_C */ + +#if defined(POLARSSL_PBKDF2_C) + if( use_ret == -(POLARSSL_ERR_PBKDF2_BAD_INPUT_DATA) ) + snprintf( buf, buflen, "PBKDF2 - Bad input parameters to function" ); +#endif /* POLARSSL_PBKDF2_C */ + +#if defined(POLARSSL_RIPEMD160_C) + if( use_ret == -(POLARSSL_ERR_RIPEMD160_FILE_IO_ERROR) ) + snprintf( buf, buflen, "RIPEMD160 - Read/write error in file" ); +#endif /* POLARSSL_RIPEMD160_C */ + +#if defined(POLARSSL_SHA1_C) + if( use_ret == -(POLARSSL_ERR_SHA1_FILE_IO_ERROR) ) + snprintf( buf, buflen, "SHA1 - Read/write error in file" ); +#endif /* POLARSSL_SHA1_C */ + +#if defined(POLARSSL_SHA256_C) + if( use_ret == -(POLARSSL_ERR_SHA256_FILE_IO_ERROR) ) + snprintf( buf, buflen, "SHA256 - Read/write error in file" ); +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA512_C) + if( use_ret == -(POLARSSL_ERR_SHA512_FILE_IO_ERROR) ) + snprintf( buf, buflen, "SHA512 - Read/write error in file" ); +#endif /* POLARSSL_SHA512_C */ + +#if defined(POLARSSL_THREADING_C) + if( use_ret == -(POLARSSL_ERR_THREADING_FEATURE_UNAVAILABLE) ) + snprintf( buf, buflen, "THREADING - The selected feature is not available" ); + if( use_ret == -(POLARSSL_ERR_THREADING_BAD_INPUT_DATA) ) + snprintf( buf, buflen, "THREADING - Bad input parameters to function" ); + if( use_ret == -(POLARSSL_ERR_THREADING_MUTEX_ERROR) ) + snprintf( buf, buflen, "THREADING - Locking / unlocking / free failed with error code" ); +#endif /* POLARSSL_THREADING_C */ + +#if defined(POLARSSL_XTEA_C) + if( use_ret == -(POLARSSL_ERR_XTEA_INVALID_INPUT_LENGTH) ) + snprintf( buf, buflen, "XTEA - The data input has an invalid length" ); +#endif /* POLARSSL_XTEA_C */ + // END generated code + + if( strlen( buf ) != 0 ) + return; + + snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", use_ret ); +} + +#if defined(POLARSSL_ERROR_STRERROR_BC) +void error_strerror( int ret, char *buf, size_t buflen ) +{ + polarssl_strerror( ret, buf, buflen ); +} +#endif /* POLARSSL_ERROR_STRERROR_BC */ + +#else /* POLARSSL_ERROR_C */ + +#if defined(POLARSSL_ERROR_STRERROR_DUMMY) + +#include + +/* + * Provide an non-function in case POLARSSL_ERROR_C is not defined + */ +void polarssl_strerror( int ret, char *buf, size_t buflen ) +{ + ((void) ret); + + if( buflen > 0 ) + buf[0] = '\0'; +} + +#if defined(POLARSSL_ERROR_STRERROR_BC) +void error_strerror( int ret, char *buf, size_t buflen ) +{ + polarssl_strerror( ret, buf, buflen ); +} +#endif /* POLARSSL_ERROR_STRERROR_BC */ +#endif /* POLARSSL_ERROR_STRERROR_DUMMY */ + +#endif /* POLARSSL_ERROR_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/gcm.c b/component/common/network/ssl/polarssl-1.3.8/library/gcm.c new file mode 100644 index 0000000..77b1e0f --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/gcm.c @@ -0,0 +1,948 @@ +/* + * NIST SP800-38D compliant GCM implementation + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* + * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf + * + * See also: + * [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf + * + * We use the algorithm described as Shoup's method with 4-bit tables in + * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_GCM_C) + +#include "polarssl/gcm.h" + +#if defined(POLARSSL_AESNI_C) +#include "polarssl/aesni.h" +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#define polarssl_printf printf +#endif + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * Precompute small multiples of H, that is set + * HH[i] || HL[i] = H times i, + * where i is seen as a field element as in [MGV], ie high-order bits + * correspond to low powers of P. The result is stored in the same way, that + * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL + * corresponds to P^127. + */ +static int gcm_gen_table( gcm_context *ctx ) +{ + int ret, i, j; + uint64_t hi, lo; + uint64_t vl, vh; + unsigned char h[16]; + size_t olen = 0; + + memset( h, 0, 16 ); + if( ( ret = cipher_update( &ctx->cipher_ctx, h, 16, h, &olen ) ) != 0 ) + return( ret ); + + /* pack h as two 64-bits ints, big-endian */ + GET_UINT32_BE( hi, h, 0 ); + GET_UINT32_BE( lo, h, 4 ); + vh = (uint64_t) hi << 32 | lo; + + GET_UINT32_BE( hi, h, 8 ); + GET_UINT32_BE( lo, h, 12 ); + vl = (uint64_t) hi << 32 | lo; + + /* 8 = 1000 corresponds to 1 in GF(2^128) */ + ctx->HL[8] = vl; + ctx->HH[8] = vh; + +#if defined(POLARSSL_AESNI_C) && defined(POLARSSL_HAVE_X86_64) + /* With CLMUL support, we need only h, not the rest of the table */ + if( aesni_supports( POLARSSL_AESNI_CLMUL ) ) + return( 0 ); +#endif + + /* 0 corresponds to 0 in GF(2^128) */ + ctx->HH[0] = 0; + ctx->HL[0] = 0; + + for( i = 4; i > 0; i >>= 1 ) + { + uint32_t T = ( vl & 1 ) * 0xe1000000U; + vl = ( vh << 63 ) | ( vl >> 1 ); + vh = ( vh >> 1 ) ^ ( (uint64_t) T << 32); + + ctx->HL[i] = vl; + ctx->HH[i] = vh; + } + + for( i = 2; i < 16; i <<= 1 ) + { + uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i; + vh = *HiH; + vl = *HiL; + for( j = 1; j < i; j++ ) + { + HiH[j] = vh ^ ctx->HH[j]; + HiL[j] = vl ^ ctx->HL[j]; + } + } + + return( 0 ); +} + +int gcm_init( gcm_context *ctx, cipher_id_t cipher, const unsigned char *key, + unsigned int keysize ) +{ + int ret; + const cipher_info_t *cipher_info; + + memset( ctx, 0, sizeof(gcm_context) ); + + cipher_init( &ctx->cipher_ctx ); + + cipher_info = cipher_info_from_values( cipher, keysize, POLARSSL_MODE_ECB ); + if( cipher_info == NULL ) + return( POLARSSL_ERR_GCM_BAD_INPUT ); + + if( cipher_info->block_size != 16 ) + return( POLARSSL_ERR_GCM_BAD_INPUT ); + + if( ( ret = cipher_init_ctx( &ctx->cipher_ctx, cipher_info ) ) != 0 ) + return( ret ); + + if( ( ret = cipher_setkey( &ctx->cipher_ctx, key, keysize, + POLARSSL_ENCRYPT ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = gcm_gen_table( ctx ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * Shoup's method for multiplication use this table with + * last4[x] = x times P^128 + * where x and last4[x] are seen as elements of GF(2^128) as in [MGV] + */ +static const uint64_t last4[16] = +{ + 0x0000, 0x1c20, 0x3840, 0x2460, + 0x7080, 0x6ca0, 0x48c0, 0x54e0, + 0xe100, 0xfd20, 0xd940, 0xc560, + 0x9180, 0x8da0, 0xa9c0, 0xb5e0 +}; + +/* + * Sets output to x times H using the precomputed tables. + * x and output are seen as elements of GF(2^128) as in [MGV]. + */ +static void gcm_mult( gcm_context *ctx, const unsigned char x[16], + unsigned char output[16] ) +{ + int i = 0; + unsigned char lo, hi, rem; + uint64_t zh, zl; + +#if defined(POLARSSL_AESNI_C) && defined(POLARSSL_HAVE_X86_64) + if( aesni_supports( POLARSSL_AESNI_CLMUL ) ) { + unsigned char h[16]; + + PUT_UINT32_BE( ctx->HH[8] >> 32, h, 0 ); + PUT_UINT32_BE( ctx->HH[8], h, 4 ); + PUT_UINT32_BE( ctx->HL[8] >> 32, h, 8 ); + PUT_UINT32_BE( ctx->HL[8], h, 12 ); + + aesni_gcm_mult( output, x, h ); + return; + } +#endif /* POLARSSL_AESNI_C && POLARSSL_HAVE_X86_64 */ + + lo = x[15] & 0xf; + hi = x[15] >> 4; + + zh = ctx->HH[lo]; + zl = ctx->HL[lo]; + + for( i = 15; i >= 0; i-- ) + { + lo = x[i] & 0xf; + hi = x[i] >> 4; + + if( i != 15 ) + { + rem = (unsigned char) zl & 0xf; + zl = ( zh << 60 ) | ( zl >> 4 ); + zh = ( zh >> 4 ); + zh ^= (uint64_t) last4[rem] << 48; + zh ^= ctx->HH[lo]; + zl ^= ctx->HL[lo]; + + } + + rem = (unsigned char) zl & 0xf; + zl = ( zh << 60 ) | ( zl >> 4 ); + zh = ( zh >> 4 ); + zh ^= (uint64_t) last4[rem] << 48; + zh ^= ctx->HH[hi]; + zl ^= ctx->HL[hi]; + } + + PUT_UINT32_BE( zh >> 32, output, 0 ); + PUT_UINT32_BE( zh, output, 4 ); + PUT_UINT32_BE( zl >> 32, output, 8 ); + PUT_UINT32_BE( zl, output, 12 ); +} + +int gcm_starts( gcm_context *ctx, + int mode, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len ) +{ + int ret; + unsigned char work_buf[16]; + size_t i; + const unsigned char *p; + size_t use_len, olen = 0; + + /* IV and AD are limited to 2^64 bits, so 2^61 bytes */ + if( ( (uint64_t) iv_len ) >> 61 != 0 || + ( (uint64_t) add_len ) >> 61 != 0 ) + { + return( POLARSSL_ERR_GCM_BAD_INPUT ); + } + + memset( ctx->y, 0x00, sizeof(ctx->y) ); + memset( ctx->buf, 0x00, sizeof(ctx->buf) ); + + ctx->mode = mode; + ctx->len = 0; + ctx->add_len = 0; + + if( iv_len == 12 ) + { + memcpy( ctx->y, iv, iv_len ); + ctx->y[15] = 1; + } + else + { + memset( work_buf, 0x00, 16 ); + PUT_UINT32_BE( iv_len * 8, work_buf, 12 ); + + p = iv; + while( iv_len > 0 ) + { + use_len = ( iv_len < 16 ) ? iv_len : 16; + + for( i = 0; i < use_len; i++ ) + ctx->y[i] ^= p[i]; + + gcm_mult( ctx, ctx->y, ctx->y ); + + iv_len -= use_len; + p += use_len; + } + + for( i = 0; i < 16; i++ ) + ctx->y[i] ^= work_buf[i]; + + gcm_mult( ctx, ctx->y, ctx->y ); + } + + if( ( ret = cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr, + &olen ) ) != 0 ) + { + return( ret ); + } + + ctx->add_len = add_len; + p = add; + while( add_len > 0 ) + { + use_len = ( add_len < 16 ) ? add_len : 16; + + for( i = 0; i < use_len; i++ ) + ctx->buf[i] ^= p[i]; + + gcm_mult( ctx, ctx->buf, ctx->buf ); + + add_len -= use_len; + p += use_len; + } + + return( 0 ); +} + +int gcm_update( gcm_context *ctx, + size_t length, + const unsigned char *input, + unsigned char *output ) +{ + int ret; + unsigned char ectr[16]; + size_t i; + const unsigned char *p; + unsigned char *out_p = output; + size_t use_len, olen = 0; + + if( output > input && (size_t) ( output - input ) < length ) + return( POLARSSL_ERR_GCM_BAD_INPUT ); + + /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes + * Also check for possible overflow */ + if( ctx->len + length < ctx->len || + (uint64_t) ctx->len + length > 0x03FFFFE0llu ) + { + return( POLARSSL_ERR_GCM_BAD_INPUT ); + } + + ctx->len += length; + + p = input; + while( length > 0 ) + { + use_len = ( length < 16 ) ? length : 16; + + for( i = 16; i > 12; i-- ) + if( ++ctx->y[i - 1] != 0 ) + break; + + if( ( ret = cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr, + &olen ) ) != 0 ) + { + return( ret ); + } + + for( i = 0; i < use_len; i++ ) + { + if( ctx->mode == GCM_DECRYPT ) + ctx->buf[i] ^= p[i]; + out_p[i] = ectr[i] ^ p[i]; + if( ctx->mode == GCM_ENCRYPT ) + ctx->buf[i] ^= out_p[i]; + } + + gcm_mult( ctx, ctx->buf, ctx->buf ); + + length -= use_len; + p += use_len; + out_p += use_len; + } + + return( 0 ); +} + +int gcm_finish( gcm_context *ctx, + unsigned char *tag, + size_t tag_len ) +{ + unsigned char work_buf[16]; + size_t i; + uint64_t orig_len = ctx->len * 8; + uint64_t orig_add_len = ctx->add_len * 8; + + if( tag_len > 16 || tag_len < 4 ) + return( POLARSSL_ERR_GCM_BAD_INPUT ); + + if( tag_len != 0 ) + memcpy( tag, ctx->base_ectr, tag_len ); + + if( orig_len || orig_add_len ) + { + memset( work_buf, 0x00, 16 ); + + PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0 ); + PUT_UINT32_BE( ( orig_add_len ), work_buf, 4 ); + PUT_UINT32_BE( ( orig_len >> 32 ), work_buf, 8 ); + PUT_UINT32_BE( ( orig_len ), work_buf, 12 ); + + for( i = 0; i < 16; i++ ) + ctx->buf[i] ^= work_buf[i]; + + gcm_mult( ctx, ctx->buf, ctx->buf ); + + for( i = 0; i < tag_len; i++ ) + tag[i] ^= ctx->buf[i]; + } + + return( 0 ); +} + +int gcm_crypt_and_tag( gcm_context *ctx, + int mode, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len, + const unsigned char *input, + unsigned char *output, + size_t tag_len, + unsigned char *tag ) +{ + int ret; + + if( ( ret = gcm_starts( ctx, mode, iv, iv_len, add, add_len ) ) != 0 ) + return( ret ); + + if( ( ret = gcm_update( ctx, length, input, output ) ) != 0 ) + return( ret ); + + if( ( ret = gcm_finish( ctx, tag, tag_len ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +int gcm_auth_decrypt( gcm_context *ctx, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len, + const unsigned char *tag, + size_t tag_len, + const unsigned char *input, + unsigned char *output ) +{ + int ret; + unsigned char check_tag[16]; + size_t i; + int diff; + + if( ( ret = gcm_crypt_and_tag( ctx, GCM_DECRYPT, length, + iv, iv_len, add, add_len, + input, output, tag_len, check_tag ) ) != 0 ) + { + return( ret ); + } + + /* Check tag in "constant-time" */ + for( diff = 0, i = 0; i < tag_len; i++ ) + diff |= tag[i] ^ check_tag[i]; + + if( diff != 0 ) + { + polarssl_zeroize( output, length ); + return( POLARSSL_ERR_GCM_AUTH_FAILED ); + } + + return( 0 ); +} + +void gcm_free( gcm_context *ctx ) +{ + cipher_free( &ctx->cipher_ctx ); + polarssl_zeroize( ctx, sizeof( gcm_context ) ); +} + +#if defined(POLARSSL_SELF_TEST) && defined(POLARSSL_AES_C) + +#include + +/* + * AES-GCM test vectors from: + * + * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip + */ +#define MAX_TESTS 6 + +int key_index[MAX_TESTS] = + { 0, 0, 1, 1, 1, 1 }; + +unsigned char key[MAX_TESTS][32] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 }, +}; + +size_t iv_len[MAX_TESTS] = + { 12, 12, 12, 12, 8, 60 }; + +int iv_index[MAX_TESTS] = + { 0, 0, 1, 1, 1, 2 }; + +unsigned char iv[MAX_TESTS][64] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }, + { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, + 0xde, 0xca, 0xf8, 0x88 }, + { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5, + 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa, + 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1, + 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28, + 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39, + 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54, + 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57, + 0xa6, 0x37, 0xb3, 0x9b }, +}; + +size_t add_len[MAX_TESTS] = + { 0, 0, 0, 20, 20, 20 }; + +int add_index[MAX_TESTS] = + { 0, 0, 0, 1, 1, 1 }; + +unsigned char additional[MAX_TESTS][64] = +{ + { 0x00 }, + { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xab, 0xad, 0xda, 0xd2 }, +}; + +size_t pt_len[MAX_TESTS] = + { 0, 16, 64, 60, 60, 60 }; + +int pt_index[MAX_TESTS] = + { 0, 0, 1, 1, 1, 1 }; + +unsigned char pt[MAX_TESTS][64] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, + 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, + 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, + 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, + 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, + 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, + 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, + 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 }, +}; + +unsigned char ct[MAX_TESTS * 3][64] = +{ + { 0x00 }, + { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, + 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 }, + { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, + 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, + 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, + 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, + 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, + 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, + 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, + 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 }, + { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, + 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, + 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, + 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, + 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, + 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, + 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, + 0x3d, 0x58, 0xe0, 0x91 }, + { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a, + 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55, + 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8, + 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23, + 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2, + 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42, + 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07, + 0xc2, 0x3f, 0x45, 0x98 }, + { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6, + 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94, + 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8, + 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7, + 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90, + 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f, + 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03, + 0x4c, 0x34, 0xae, 0xe5 }, + { 0x00 }, + { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41, + 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 }, + { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, + 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57, + 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, + 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c, + 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, + 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, + 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9, + 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 }, + { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, + 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57, + 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, + 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c, + 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, + 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, + 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9, + 0xcc, 0xda, 0x27, 0x10 }, + { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54, + 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8, + 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f, + 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57, + 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75, + 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9, + 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f, + 0xa0, 0xf0, 0x62, 0xf7 }, + { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c, + 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff, + 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef, + 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45, + 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9, + 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3, + 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7, + 0xe9, 0xb7, 0x37, 0x3b }, + { 0x00 }, + { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e, + 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 }, + { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, + 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, + 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, + 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, + 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, + 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, + 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, + 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad }, + { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, + 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, + 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, + 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, + 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, + 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, + 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, + 0xbc, 0xc9, 0xf6, 0x62 }, + { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32, + 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb, + 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa, + 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0, + 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0, + 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78, + 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99, + 0xf4, 0x7c, 0x9b, 0x1f }, + { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1, + 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20, + 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19, + 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4, + 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45, + 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde, + 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e, + 0x44, 0xae, 0x7e, 0x3f }, +}; + +unsigned char tag[MAX_TESTS * 3][16] = +{ + { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61, + 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a }, + { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd, + 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf }, + { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6, + 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 }, + { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb, + 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 }, + { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85, + 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb }, + { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa, + 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 }, + { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b, + 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 }, + { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab, + 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb }, + { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf, + 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 }, + { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f, + 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c }, + { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24, + 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 }, + { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb, + 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 }, + { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9, + 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b }, + { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0, + 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 }, + { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd, + 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c }, + { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68, + 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b }, + { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4, + 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 }, + { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0, + 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a }, +}; + +int gcm_self_test( int verbose ) +{ + gcm_context ctx; + unsigned char buf[64]; + unsigned char tag_buf[16]; + int i, j, ret; + cipher_id_t cipher = POLARSSL_CIPHER_ID_AES; + + for( j = 0; j < 3; j++ ) + { + int key_len = 128 + 64 * j; + + for( i = 0; i < MAX_TESTS; i++ ) + { + if( verbose != 0 ) + polarssl_printf( " AES-GCM-%3d #%d (%s): ", + key_len, i, "enc" ); + + gcm_init( &ctx, cipher, key[key_index[i]], key_len ); + + ret = gcm_crypt_and_tag( &ctx, GCM_ENCRYPT, + pt_len[i], + iv[iv_index[i]], iv_len[i], + additional[add_index[i]], add_len[i], + pt[pt_index[i]], buf, 16, tag_buf ); + + if( ret != 0 || + memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 || + memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + gcm_free( &ctx ); + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + + if( verbose != 0 ) + polarssl_printf( " AES-GCM-%3d #%d (%s): ", + key_len, i, "dec" ); + + gcm_init( &ctx, cipher, key[key_index[i]], key_len ); + + ret = gcm_crypt_and_tag( &ctx, GCM_DECRYPT, + pt_len[i], + iv[iv_index[i]], iv_len[i], + additional[add_index[i]], add_len[i], + ct[j * 6 + i], buf, 16, tag_buf ); + + if( ret != 0 || + memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 || + memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + gcm_free( &ctx ); + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + + if( verbose != 0 ) + polarssl_printf( " AES-GCM-%3d #%d split (%s): ", + key_len, i, "enc" ); + + gcm_init( &ctx, cipher, key[key_index[i]], key_len ); + + ret = gcm_starts( &ctx, GCM_ENCRYPT, + iv[iv_index[i]], iv_len[i], + additional[add_index[i]], add_len[i] ); + if( ret != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + if( pt_len[i] > 32 ) + { + size_t rest_len = pt_len[i] - 32; + ret = gcm_update( &ctx, 32, pt[pt_index[i]], buf ); + if( ret != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + ret = gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32, + buf + 32 ); + if( ret != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + } + else + { + ret = gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf ); + if( ret != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + } + + ret = gcm_finish( &ctx, tag_buf, 16 ); + if( ret != 0 || + memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 || + memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + gcm_free( &ctx ); + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + + if( verbose != 0 ) + polarssl_printf( " AES-GCM-%3d #%d split (%s): ", + key_len, i, "dec" ); + + gcm_init( &ctx, cipher, key[key_index[i]], key_len ); + + ret = gcm_starts( &ctx, GCM_DECRYPT, + iv[iv_index[i]], iv_len[i], + additional[add_index[i]], add_len[i] ); + if( ret != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + if( pt_len[i] > 32 ) + { + size_t rest_len = pt_len[i] - 32; + ret = gcm_update( &ctx, 32, ct[j * 6 + i], buf ); + if( ret != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + ret = gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32, + buf + 32 ); + if( ret != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + } + else + { + ret = gcm_update( &ctx, pt_len[i], ct[j * 6 + i], buf ); + if( ret != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + } + + ret = gcm_finish( &ctx, tag_buf, 16 ); + if( ret != 0 || + memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 || + memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + gcm_free( &ctx ); + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + + } + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); + + return( 0 ); +} + + + +#endif /* POLARSSL_SELF_TEST && POLARSSL_AES_C */ + +#endif /* POLARSSL_GCM_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/havege.c b/component/common/network/ssl/polarssl-1.3.8/library/havege.c new file mode 100644 index 0000000..3acd5bc --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/havege.c @@ -0,0 +1,247 @@ +/** + * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * The HAVEGE RNG was designed by Andre Seznec in 2002. + * + * http://www.irisa.fr/caps/projects/hipsor/publi.php + * + * Contact: seznec(at)irisa_dot_fr - orocheco(at)irisa_dot_fr + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_HAVEGE_C) + +#include "polarssl/havege.h" +#include "polarssl/timing.h" + +#include + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* ------------------------------------------------------------------------ + * On average, one iteration accesses two 8-word blocks in the havege WALK + * table, and generates 16 words in the RES array. + * + * The data read in the WALK table is updated and permuted after each use. + * The result of the hardware clock counter read is used for this update. + * + * 25 conditional tests are present. The conditional tests are grouped in + * two nested groups of 12 conditional tests and 1 test that controls the + * permutation; on average, there should be 6 tests executed and 3 of them + * should be mispredicted. + * ------------------------------------------------------------------------ + */ + +#define SWAP(X,Y) { int *T = X; X = Y; Y = T; } + +#define TST1_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1; +#define TST2_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1; + +#define TST1_LEAVE U1++; } +#define TST2_LEAVE U2++; } + +#define ONE_ITERATION \ + \ + PTEST = PT1 >> 20; \ + \ + TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ + TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ + TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ + \ + TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ + TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ + TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ + \ + PTX = (PT1 >> 18) & 7; \ + PT1 &= 0x1FFF; \ + PT2 &= 0x1FFF; \ + CLK = (int) hardclock(); \ + \ + i = 0; \ + A = &WALK[PT1 ]; RES[i++] ^= *A; \ + B = &WALK[PT2 ]; RES[i++] ^= *B; \ + C = &WALK[PT1 ^ 1]; RES[i++] ^= *C; \ + D = &WALK[PT2 ^ 4]; RES[i++] ^= *D; \ + \ + IN = (*A >> (1)) ^ (*A << (31)) ^ CLK; \ + *A = (*B >> (2)) ^ (*B << (30)) ^ CLK; \ + *B = IN ^ U1; \ + *C = (*C >> (3)) ^ (*C << (29)) ^ CLK; \ + *D = (*D >> (4)) ^ (*D << (28)) ^ CLK; \ + \ + A = &WALK[PT1 ^ 2]; RES[i++] ^= *A; \ + B = &WALK[PT2 ^ 2]; RES[i++] ^= *B; \ + C = &WALK[PT1 ^ 3]; RES[i++] ^= *C; \ + D = &WALK[PT2 ^ 6]; RES[i++] ^= *D; \ + \ + if( PTEST & 1 ) SWAP( A, C ); \ + \ + IN = (*A >> (5)) ^ (*A << (27)) ^ CLK; \ + *A = (*B >> (6)) ^ (*B << (26)) ^ CLK; \ + *B = IN; CLK = (int) hardclock(); \ + *C = (*C >> (7)) ^ (*C << (25)) ^ CLK; \ + *D = (*D >> (8)) ^ (*D << (24)) ^ CLK; \ + \ + A = &WALK[PT1 ^ 4]; \ + B = &WALK[PT2 ^ 1]; \ + \ + PTEST = PT2 >> 1; \ + \ + PT2 = (RES[(i - 8) ^ PTY] ^ WALK[PT2 ^ PTY ^ 7]); \ + PT2 = ((PT2 & 0x1FFF) & (~8)) ^ ((PT1 ^ 8) & 0x8); \ + PTY = (PT2 >> 10) & 7; \ + \ + TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ + TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ + TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ + \ + TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ + TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ + TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ + \ + C = &WALK[PT1 ^ 5]; \ + D = &WALK[PT2 ^ 5]; \ + \ + RES[i++] ^= *A; \ + RES[i++] ^= *B; \ + RES[i++] ^= *C; \ + RES[i++] ^= *D; \ + \ + IN = (*A >> ( 9)) ^ (*A << (23)) ^ CLK; \ + *A = (*B >> (10)) ^ (*B << (22)) ^ CLK; \ + *B = IN ^ U2; \ + *C = (*C >> (11)) ^ (*C << (21)) ^ CLK; \ + *D = (*D >> (12)) ^ (*D << (20)) ^ CLK; \ + \ + A = &WALK[PT1 ^ 6]; RES[i++] ^= *A; \ + B = &WALK[PT2 ^ 3]; RES[i++] ^= *B; \ + C = &WALK[PT1 ^ 7]; RES[i++] ^= *C; \ + D = &WALK[PT2 ^ 7]; RES[i++] ^= *D; \ + \ + IN = (*A >> (13)) ^ (*A << (19)) ^ CLK; \ + *A = (*B >> (14)) ^ (*B << (18)) ^ CLK; \ + *B = IN; \ + *C = (*C >> (15)) ^ (*C << (17)) ^ CLK; \ + *D = (*D >> (16)) ^ (*D << (16)) ^ CLK; \ + \ + PT1 = ( RES[( i - 8 ) ^ PTX] ^ \ + WALK[PT1 ^ PTX ^ 7] ) & (~1); \ + PT1 ^= (PT2 ^ 0x10) & 0x10; \ + \ + for( n++, i = 0; i < 16; i++ ) \ + hs->pool[n % COLLECT_SIZE] ^= RES[i]; + +/* + * Entropy gathering function + */ +static void havege_fill( havege_state *hs ) +{ + int i, n = 0; + int U1, U2, *A, *B, *C, *D; + int PT1, PT2, *WALK, RES[16]; + int PTX, PTY, CLK, PTEST, IN; + + WALK = hs->WALK; + PT1 = hs->PT1; + PT2 = hs->PT2; + + PTX = U1 = 0; + PTY = U2 = 0; + + memset( RES, 0, sizeof( RES ) ); + + while( n < COLLECT_SIZE * 4 ) + { + ONE_ITERATION + ONE_ITERATION + ONE_ITERATION + ONE_ITERATION + } + + hs->PT1 = PT1; + hs->PT2 = PT2; + + hs->offset[0] = 0; + hs->offset[1] = COLLECT_SIZE / 2; +} + +/* + * HAVEGE initialization + */ +void havege_init( havege_state *hs ) +{ + memset( hs, 0, sizeof( havege_state ) ); + + havege_fill( hs ); +} + +void havege_free( havege_state *hs ) +{ + if( hs == NULL ) + return; + + polarssl_zeroize( hs, sizeof( havege_state ) ); +} + +/* + * HAVEGE rand function + */ +int havege_random( void *p_rng, unsigned char *buf, size_t len ) +{ + int val; + size_t use_len; + havege_state *hs = (havege_state *) p_rng; + unsigned char *p = buf; + + while( len > 0 ) + { + use_len = len; + if( use_len > sizeof(int) ) + use_len = sizeof(int); + + if( hs->offset[1] >= COLLECT_SIZE ) + havege_fill( hs ); + + val = hs->pool[hs->offset[0]++]; + val ^= hs->pool[hs->offset[1]++]; + + memcpy( p, &val, use_len ); + + len -= use_len; + p += use_len; + } + + return( 0 ); +} + +#endif /* POLARSSL_HAVEGE_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/hmac_drbg.c b/component/common/network/ssl/polarssl-1.3.8/library/hmac_drbg.c new file mode 100644 index 0000000..d691be1 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/hmac_drbg.c @@ -0,0 +1,502 @@ +/* + * HMAC_DRBG implementation (NIST SP 800-90) + * + * Copyright (C) 2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* + * The NIST SP 800-90A DRBGs are described in the following publication. + * http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf + * References below are based on rev. 1 (January 2012). + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_HMAC_DRBG_C) + +#include "polarssl/hmac_drbg.h" + +#if defined(POLARSSL_FS_IO) +#include +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#define polarssl_printf printf +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * HMAC_DRBG update, using optional additional data (10.1.2.2) + */ +void hmac_drbg_update( hmac_drbg_context *ctx, + const unsigned char *additional, size_t add_len ) +{ + size_t md_len = ctx->md_ctx.md_info->size; + unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1; + unsigned char sep[1]; + unsigned char K[POLARSSL_MD_MAX_SIZE]; + + for( sep[0] = 0; sep[0] < rounds; sep[0]++ ) + { + /* Step 1 or 4 */ + md_hmac_reset( &ctx->md_ctx ); + md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); + md_hmac_update( &ctx->md_ctx, sep, 1 ); + if( rounds == 2 ) + md_hmac_update( &ctx->md_ctx, additional, add_len ); + md_hmac_finish( &ctx->md_ctx, K ); + + /* Step 2 or 5 */ + md_hmac_starts( &ctx->md_ctx, K, md_len ); + md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); + md_hmac_finish( &ctx->md_ctx, ctx->V ); + } +} + +/* + * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA) + */ +int hmac_drbg_init_buf( hmac_drbg_context *ctx, + const md_info_t * md_info, + const unsigned char *data, size_t data_len ) +{ + int ret; + + memset( ctx, 0, sizeof( hmac_drbg_context ) ); + + md_init( &ctx->md_ctx ); + + if( ( ret = md_init_ctx( &ctx->md_ctx, md_info ) ) != 0 ) + return( ret ); + + /* + * Set initial working state. + * Use the V memory location, which is currently all 0, to initialize the + * MD context with an all-zero key. Then set V to its initial value. + */ + md_hmac_starts( &ctx->md_ctx, ctx->V, md_info->size ); + memset( ctx->V, 0x01, md_info->size ); + + hmac_drbg_update( ctx, data, data_len ); + + return( 0 ); +} + +/* + * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman) + */ +int hmac_drbg_reseed( hmac_drbg_context *ctx, + const unsigned char *additional, size_t len ) +{ + unsigned char seed[POLARSSL_HMAC_DRBG_MAX_SEED_INPUT]; + size_t seedlen; + + /* III. Check input length */ + if( len > POLARSSL_HMAC_DRBG_MAX_INPUT || + ctx->entropy_len + len > POLARSSL_HMAC_DRBG_MAX_SEED_INPUT ) + { + return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG ); + } + + memset( seed, 0, POLARSSL_HMAC_DRBG_MAX_SEED_INPUT ); + + /* IV. Gather entropy_len bytes of entropy for the seed */ + if( ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) != 0 ) + return( POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED ); + + seedlen = ctx->entropy_len; + + /* 1. Concatenate entropy and additional data if any */ + if( additional != NULL && len != 0 ) + { + memcpy( seed + seedlen, additional, len ); + seedlen += len; + } + + /* 2. Update state */ + hmac_drbg_update( ctx, seed, seedlen ); + + /* 3. Reset reseed_counter */ + ctx->reseed_counter = 1; + + /* 4. Done */ + return( 0 ); +} + +/* + * HMAC_DRBG initialisation (10.1.2.3 + 9.1) + */ +int hmac_drbg_init( hmac_drbg_context *ctx, + const md_info_t * md_info, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len ) +{ + int ret; + size_t entropy_len; + + memset( ctx, 0, sizeof( hmac_drbg_context ) ); + + md_init( &ctx->md_ctx ); + + if( ( ret = md_init_ctx( &ctx->md_ctx, md_info ) ) != 0 ) + return( ret ); + + /* + * Set initial working state. + * Use the V memory location, which is currently all 0, to initialize the + * MD context with an all-zero key. Then set V to its initial value. + */ + md_hmac_starts( &ctx->md_ctx, ctx->V, md_info->size ); + memset( ctx->V, 0x01, md_info->size ); + + ctx->f_entropy = f_entropy; + ctx->p_entropy = p_entropy; + + ctx->reseed_interval = POLARSSL_HMAC_DRBG_RESEED_INTERVAL; + + /* + * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by + * each hash function, then according to SP800-90A rev1 10.1 table 2, + * min_entropy_len (in bits) is security_strength. + * + * (This also matches the sizes used in the NIST test vectors.) + */ + entropy_len = md_info->size <= 20 ? 16 : /* 160-bits hash -> 128 bits */ + md_info->size <= 28 ? 24 : /* 224-bits hash -> 192 bits */ + 32; /* better (256+) -> 256 bits */ + + /* + * For initialisation, use more entropy to emulate a nonce + * (Again, matches test vectors.) + */ + ctx->entropy_len = entropy_len * 3 / 2; + + if( ( ret = hmac_drbg_reseed( ctx, custom, len ) ) != 0 ) + return( ret ); + + ctx->entropy_len = entropy_len; + + return( 0 ); +} + +/* + * Set prediction resistance + */ +void hmac_drbg_set_prediction_resistance( hmac_drbg_context *ctx, + int resistance ) +{ + ctx->prediction_resistance = resistance; +} + +/* + * Set entropy length grabbed for reseeds + */ +void hmac_drbg_set_entropy_len( hmac_drbg_context *ctx, size_t len ) +{ + ctx->entropy_len = len; +} + +/* + * Set reseed interval + */ +void hmac_drbg_set_reseed_interval( hmac_drbg_context *ctx, int interval ) +{ + ctx->reseed_interval = interval; +} + +/* + * HMAC_DRBG random function with optional additional data: + * 10.1.2.5 (arabic) + 9.3 (Roman) + */ +int hmac_drbg_random_with_add( void *p_rng, + unsigned char *output, size_t out_len, + const unsigned char *additional, size_t add_len ) +{ + int ret; + hmac_drbg_context *ctx = (hmac_drbg_context *) p_rng; + size_t md_len = md_get_size( ctx->md_ctx.md_info ); + size_t left = out_len; + unsigned char *out = output; + + /* II. Check request length */ + if( out_len > POLARSSL_HMAC_DRBG_MAX_REQUEST ) + return( POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG ); + + /* III. Check input length */ + if( add_len > POLARSSL_HMAC_DRBG_MAX_INPUT ) + return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG ); + + /* 1. (aka VII and IX) Check reseed counter and PR */ + if( ctx->f_entropy != NULL && /* For no-reseeding instances */ + ( ctx->prediction_resistance == POLARSSL_HMAC_DRBG_PR_ON || + ctx->reseed_counter > ctx->reseed_interval ) ) + { + if( ( ret = hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 ) + return( ret ); + + add_len = 0; /* VII.4 */ + } + + /* 2. Use additional data if any */ + if( additional != NULL && add_len != 0 ) + hmac_drbg_update( ctx, additional, add_len ); + + /* 3, 4, 5. Generate bytes */ + while( left != 0 ) + { + size_t use_len = left > md_len ? md_len : left; + + md_hmac_reset( &ctx->md_ctx ); + md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); + md_hmac_finish( &ctx->md_ctx, ctx->V ); + + memcpy( out, ctx->V, use_len ); + out += use_len; + left -= use_len; + } + + /* 6. Update */ + hmac_drbg_update( ctx, additional, add_len ); + + /* 7. Update reseed counter */ + ctx->reseed_counter++; + + /* 8. Done */ + return( 0 ); +} + +/* + * HMAC_DRBG random function + */ +int hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len ) +{ + return( hmac_drbg_random_with_add( p_rng, output, out_len, NULL, 0 ) ); +} + +/* + * Free an HMAC_DRBG context + */ +void hmac_drbg_free( hmac_drbg_context *ctx ) +{ + if( ctx == NULL ) + return; + + md_free_ctx( &ctx->md_ctx ); + + polarssl_zeroize( ctx, sizeof( hmac_drbg_context ) ); +} + +#if defined(POLARSSL_FS_IO) +int hmac_drbg_write_seed_file( hmac_drbg_context *ctx, const char *path ) +{ + int ret; + FILE *f; + unsigned char buf[ POLARSSL_HMAC_DRBG_MAX_INPUT ]; + + if( ( f = fopen( path, "wb" ) ) == NULL ) + return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR ); + + if( ( ret = hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 ) + goto exit; + + if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) ) + { + ret = POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR; + goto exit; + } + + ret = 0; + +exit: + fclose( f ); + return( ret ); +} + +int hmac_drbg_update_seed_file( hmac_drbg_context *ctx, const char *path ) +{ + FILE *f; + size_t n; + unsigned char buf[ POLARSSL_HMAC_DRBG_MAX_INPUT ]; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR ); + + fseek( f, 0, SEEK_END ); + n = (size_t) ftell( f ); + fseek( f, 0, SEEK_SET ); + + if( n > POLARSSL_HMAC_DRBG_MAX_INPUT ) + { + fclose( f ); + return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG ); + } + + if( fread( buf, 1, n, f ) != n ) + { + fclose( f ); + return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR ); + } + + fclose( f ); + + hmac_drbg_update( ctx, buf, n ); + + return( hmac_drbg_write_seed_file( ctx, path ) ); +} +#endif /* POLARSSL_FS_IO */ + + +#if defined(POLARSSL_SELF_TEST) + +#include + +#if !defined(POLARSSL_SHA1_C) +/* Dummy checkup routine */ +int hmac_drbg_self_test( int verbose ) +{ + + if( verbose != 0 ) + polarssl_printf( "\n" ); + + return( 0 ); +} +#else + +#define OUTPUT_LEN 80 + +/* From a NIST PR=true test vector */ +static unsigned char entropy_pr[] = { + 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f, + 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11, + 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42, + 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3, + 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 }; +static const unsigned char result_pr[OUTPUT_LEN] = { + 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39, + 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94, + 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54, + 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e, + 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab, + 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3, + 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 }; + +/* From a NIST PR=false test vector */ +static unsigned char entropy_nopr[] = { + 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66, + 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8, + 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3, + 0xe9, 0x9d, 0xfe, 0xdf }; +static const unsigned char result_nopr[OUTPUT_LEN] = { + 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f, + 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6, + 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a, + 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec, + 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd, + 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49, + 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 }; + +/* "Entropy" from buffer */ +static size_t test_offset; +static int hmac_drbg_self_test_entropy( void *data, + unsigned char *buf, size_t len ) +{ + const unsigned char *p = data; + memcpy( buf, p + test_offset, len ); + test_offset += len; + return( 0 ); +} + +#define CHK( c ) if( (c) != 0 ) \ + { \ + if( verbose != 0 ) \ + polarssl_printf( "failed\n" ); \ + return( 1 ); \ + } + +/* + * Checkup routine for HMAC_DRBG with SHA-1 + */ +int hmac_drbg_self_test( int verbose ) +{ + hmac_drbg_context ctx; + unsigned char buf[OUTPUT_LEN]; + const md_info_t *md_info = md_info_from_type( POLARSSL_MD_SHA1 ); + + /* + * PR = True + */ + if( verbose != 0 ) + polarssl_printf( " HMAC_DRBG (PR = True) : " ); + + test_offset = 0; + CHK( hmac_drbg_init( &ctx, md_info, + hmac_drbg_self_test_entropy, entropy_pr, + NULL, 0 ) ); + hmac_drbg_set_prediction_resistance( &ctx, POLARSSL_HMAC_DRBG_PR_ON ); + CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); + CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); + CHK( memcmp( buf, result_pr, OUTPUT_LEN ) ); + hmac_drbg_free( &ctx ); + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + + /* + * PR = False + */ + if( verbose != 0 ) + polarssl_printf( " HMAC_DRBG (PR = False) : " ); + + test_offset = 0; + CHK( hmac_drbg_init( &ctx, md_info, + hmac_drbg_self_test_entropy, entropy_nopr, + NULL, 0 ) ); + CHK( hmac_drbg_reseed( &ctx, NULL, 0 ) ); + CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); + CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); + CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) ); + hmac_drbg_free( &ctx ); + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + + if( verbose != 0 ) + polarssl_printf( "\n" ); + + return( 0 ); +} +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_HMAC_DRBG_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/md.c b/component/common/network/ssl/polarssl-1.3.8/library/md.c new file mode 100644 index 0000000..7f9c5dc --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/md.c @@ -0,0 +1,341 @@ +/** + * \file md.c + * + * \brief Generic message digest wrapper for PolarSSL + * + * \author Adriaan de Jong + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_MD_C) + +#include "polarssl/md.h" +#include "polarssl/md_wrap.h" + +#include + +#if defined(_MSC_VER) && !defined strcasecmp && !defined(EFIX64) && \ + !defined(EFI32) +#define strcasecmp _stricmp +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +static const int supported_digests[] = { + +#if defined(POLARSSL_SHA512_C) + POLARSSL_MD_SHA384, + POLARSSL_MD_SHA512, +#endif + +#if defined(POLARSSL_SHA256_C) + POLARSSL_MD_SHA224, + POLARSSL_MD_SHA256, +#endif + +#if defined(POLARSSL_SHA1_C) + POLARSSL_MD_SHA1, +#endif + +#if defined(POLARSSL_RIPEMD160_C) + POLARSSL_MD_RIPEMD160, +#endif + +#if defined(POLARSSL_MD5_C) + POLARSSL_MD_MD5, +#endif + +#if defined(POLARSSL_MD4_C) + POLARSSL_MD_MD4, +#endif + +#if defined(POLARSSL_MD2_C) + POLARSSL_MD_MD2, +#endif + + POLARSSL_MD_NONE +}; + +const int *md_list( void ) +{ + return( supported_digests ); +} + +const md_info_t *md_info_from_string( const char *md_name ) +{ + if( NULL == md_name ) + return( NULL ); + + /* Get the appropriate digest information */ +#if defined(POLARSSL_MD2_C) + if( !strcasecmp( "MD2", md_name ) ) + return md_info_from_type( POLARSSL_MD_MD2 ); +#endif +#if defined(POLARSSL_MD4_C) + if( !strcasecmp( "MD4", md_name ) ) + return md_info_from_type( POLARSSL_MD_MD4 ); +#endif +#if defined(POLARSSL_MD5_C) + if( !strcasecmp( "MD5", md_name ) ) + return md_info_from_type( POLARSSL_MD_MD5 ); +#endif +#if defined(POLARSSL_RIPEMD160_C) + if( !strcasecmp( "RIPEMD160", md_name ) ) + return md_info_from_type( POLARSSL_MD_RIPEMD160 ); +#endif +#if defined(POLARSSL_SHA1_C) + if( !strcasecmp( "SHA1", md_name ) || !strcasecmp( "SHA", md_name ) ) + return md_info_from_type( POLARSSL_MD_SHA1 ); +#endif +#if defined(POLARSSL_SHA256_C) + if( !strcasecmp( "SHA224", md_name ) ) + return md_info_from_type( POLARSSL_MD_SHA224 ); + if( !strcasecmp( "SHA256", md_name ) ) + return md_info_from_type( POLARSSL_MD_SHA256 ); +#endif +#if defined(POLARSSL_SHA512_C) + if( !strcasecmp( "SHA384", md_name ) ) + return md_info_from_type( POLARSSL_MD_SHA384 ); + if( !strcasecmp( "SHA512", md_name ) ) + return md_info_from_type( POLARSSL_MD_SHA512 ); +#endif + return( NULL ); +} + +const md_info_t *md_info_from_type( md_type_t md_type ) +{ + switch( md_type ) + { +#if defined(POLARSSL_MD2_C) + case POLARSSL_MD_MD2: + return( &md2_info ); +#endif +#if defined(POLARSSL_MD4_C) + case POLARSSL_MD_MD4: + return( &md4_info ); +#endif +#if defined(POLARSSL_MD5_C) + case POLARSSL_MD_MD5: + return( &md5_info ); +#endif +#if defined(POLARSSL_RIPEMD160_C) + case POLARSSL_MD_RIPEMD160: + return( &ripemd160_info ); +#endif +#if defined(POLARSSL_SHA1_C) + case POLARSSL_MD_SHA1: + return( &sha1_info ); +#endif +#if defined(POLARSSL_SHA256_C) + case POLARSSL_MD_SHA224: + return( &sha224_info ); + case POLARSSL_MD_SHA256: + return( &sha256_info ); +#endif +#if defined(POLARSSL_SHA512_C) + case POLARSSL_MD_SHA384: + return( &sha384_info ); + case POLARSSL_MD_SHA512: + return( &sha512_info ); +#endif + default: + return( NULL ); + } +} + +void md_init( md_context_t *ctx ) +{ + memset( ctx, 0, sizeof( md_context_t ) ); +} + +void md_free( md_context_t *ctx ) +{ + if( ctx == NULL ) + return; + + if( ctx->md_ctx ) + ctx->md_info->ctx_free_func( ctx->md_ctx ); + + polarssl_zeroize( ctx, sizeof( md_context_t ) ); +} + +int md_init_ctx( md_context_t *ctx, const md_info_t *md_info ) +{ + if( md_info == NULL || ctx == NULL ) + return( POLARSSL_ERR_MD_BAD_INPUT_DATA ); + + memset( ctx, 0, sizeof( md_context_t ) ); + + if( ( ctx->md_ctx = md_info->ctx_alloc_func() ) == NULL ) + return( POLARSSL_ERR_MD_ALLOC_FAILED ); + + ctx->md_info = md_info; + + md_info->starts_func( ctx->md_ctx ); + + return( 0 ); +} + +int md_free_ctx( md_context_t *ctx ) +{ + md_free( ctx ); + + return( 0 ); +} + +int md_starts( md_context_t *ctx ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( POLARSSL_ERR_MD_BAD_INPUT_DATA ); + + ctx->md_info->starts_func( ctx->md_ctx ); + + return( 0 ); +} + +int md_update( md_context_t *ctx, const unsigned char *input, size_t ilen ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( POLARSSL_ERR_MD_BAD_INPUT_DATA ); + + ctx->md_info->update_func( ctx->md_ctx, input, ilen ); + + return( 0 ); +} + +int md_finish( md_context_t *ctx, unsigned char *output ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( POLARSSL_ERR_MD_BAD_INPUT_DATA ); + + ctx->md_info->finish_func( ctx->md_ctx, output ); + + return( 0 ); +} + +int md( const md_info_t *md_info, const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + if( md_info == NULL ) + return( POLARSSL_ERR_MD_BAD_INPUT_DATA ); + + md_info->digest_func( input, ilen, output ); + + return( 0 ); +} + +int md_file( const md_info_t *md_info, const char *path, unsigned char *output ) +{ +#if defined(POLARSSL_FS_IO) + int ret; +#endif + + if( md_info == NULL ) + return( POLARSSL_ERR_MD_BAD_INPUT_DATA ); + +#if defined(POLARSSL_FS_IO) + ret = md_info->file_func( path, output ); + if( ret != 0 ) + return( POLARSSL_ERR_MD_FILE_IO_ERROR + ret ); + + return( ret ); +#else + ((void) path); + ((void) output); + + return( POLARSSL_ERR_MD_FEATURE_UNAVAILABLE ); +#endif /* POLARSSL_FS_IO */ +} + +int md_hmac_starts( md_context_t *ctx, const unsigned char *key, size_t keylen ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( POLARSSL_ERR_MD_BAD_INPUT_DATA ); + + ctx->md_info->hmac_starts_func( ctx->md_ctx, key, keylen ); + + return( 0 ); +} + +int md_hmac_update( md_context_t *ctx, const unsigned char *input, size_t ilen ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( POLARSSL_ERR_MD_BAD_INPUT_DATA ); + + ctx->md_info->hmac_update_func( ctx->md_ctx, input, ilen ); + + return( 0 ); +} + +int md_hmac_finish( md_context_t *ctx, unsigned char *output ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( POLARSSL_ERR_MD_BAD_INPUT_DATA ); + + ctx->md_info->hmac_finish_func( ctx->md_ctx, output ); + + return( 0 ); +} + +int md_hmac_reset( md_context_t *ctx ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( POLARSSL_ERR_MD_BAD_INPUT_DATA ); + + ctx->md_info->hmac_reset_func( ctx->md_ctx ); + + return( 0 ); +} + +int md_hmac( const md_info_t *md_info, const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + if( md_info == NULL ) + return( POLARSSL_ERR_MD_BAD_INPUT_DATA ); + + md_info->hmac_func( key, keylen, input, ilen, output ); + + return( 0 ); +} + +int md_process( md_context_t *ctx, const unsigned char *data ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( POLARSSL_ERR_MD_BAD_INPUT_DATA ); + + ctx->md_info->process_func( ctx->md_ctx, data ); + + return( 0 ); +} + +#endif /* POLARSSL_MD_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/md2.c b/component/common/network/ssl/polarssl-1.3.8/library/md2.c new file mode 100644 index 0000000..45bce37 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/md2.c @@ -0,0 +1,398 @@ +/* + * RFC 1115/1319 compliant MD2 implementation + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * The MD2 algorithm was designed by Ron Rivest in 1989. + * + * http://www.ietf.org/rfc/rfc1115.txt + * http://www.ietf.org/rfc/rfc1319.txt + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_MD2_C) + +#include "polarssl/md2.h" + +#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST) +#include +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#define polarssl_printf printf +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +#if !defined(POLARSSL_MD2_ALT) + +static const unsigned char PI_SUBST[256] = +{ + 0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36, + 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13, 0x62, 0xA7, 0x05, 0xF3, + 0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, + 0x82, 0xCA, 0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16, + 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12, 0xBE, 0x4E, + 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E, + 0xBB, 0x2F, 0xEE, 0x7A, 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, + 0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21, + 0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E, + 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03, 0xFF, 0x19, 0x30, 0xB3, + 0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56, + 0xAA, 0xC6, 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6, + 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1, 0x45, 0x9D, + 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65, + 0xE6, 0x2D, 0xA8, 0x02, 0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0, + 0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F, + 0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C, + 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26, 0x2C, 0x53, 0x0D, 0x6E, + 0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, + 0x4D, 0x52, 0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA, + 0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A, 0x78, 0x88, + 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE, + 0x3B, 0x00, 0x1D, 0x39, 0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58, + 0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A, + 0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99, + 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14 +}; + +void md2_init( md2_context *ctx ) +{ + memset( ctx, 0, sizeof( md2_context ) ); +} + +void md2_free( md2_context *ctx ) +{ + if( ctx == NULL ) + return; + + polarssl_zeroize( ctx, sizeof( md2_context ) ); +} + +/* + * MD2 context setup + */ +void md2_starts( md2_context *ctx ) +{ + memset( ctx->cksum, 0, 16 ); + memset( ctx->state, 0, 46 ); + memset( ctx->buffer, 0, 16 ); + ctx->left = 0; +} + +void md2_process( md2_context *ctx ) +{ + int i, j; + unsigned char t = 0; + + for( i = 0; i < 16; i++ ) + { + ctx->state[i + 16] = ctx->buffer[i]; + ctx->state[i + 32] = + (unsigned char)( ctx->buffer[i] ^ ctx->state[i]); + } + + for( i = 0; i < 18; i++ ) + { + for( j = 0; j < 48; j++ ) + { + ctx->state[j] = (unsigned char) + ( ctx->state[j] ^ PI_SUBST[t] ); + t = ctx->state[j]; + } + + t = (unsigned char)( t + i ); + } + + t = ctx->cksum[15]; + + for( i = 0; i < 16; i++ ) + { + ctx->cksum[i] = (unsigned char) + ( ctx->cksum[i] ^ PI_SUBST[ctx->buffer[i] ^ t] ); + t = ctx->cksum[i]; + } +} + +/* + * MD2 process buffer + */ +void md2_update( md2_context *ctx, const unsigned char *input, size_t ilen ) +{ + size_t fill; + + while( ilen > 0 ) + { + if( ctx->left + ilen > 16 ) + fill = 16 - ctx->left; + else + fill = ilen; + + memcpy( ctx->buffer + ctx->left, input, fill ); + + ctx->left += fill; + input += fill; + ilen -= fill; + + if( ctx->left == 16 ) + { + ctx->left = 0; + md2_process( ctx ); + } + } +} + +/* + * MD2 final digest + */ +void md2_finish( md2_context *ctx, unsigned char output[16] ) +{ + size_t i; + unsigned char x; + + x = (unsigned char)( 16 - ctx->left ); + + for( i = ctx->left; i < 16; i++ ) + ctx->buffer[i] = x; + + md2_process( ctx ); + + memcpy( ctx->buffer, ctx->cksum, 16 ); + md2_process( ctx ); + + memcpy( output, ctx->state, 16 ); +} + +#endif /* !POLARSSL_MD2_ALT */ + +/* + * output = MD2( input buffer ) + */ +void md2( const unsigned char *input, size_t ilen, unsigned char output[16] ) +{ + md2_context ctx; + + md2_init( &ctx ); + md2_starts( &ctx ); + md2_update( &ctx, input, ilen ); + md2_finish( &ctx, output ); + md2_free( &ctx ); +} + +#if defined(POLARSSL_FS_IO) +/* + * output = MD2( file contents ) + */ +int md2_file( const char *path, unsigned char output[16] ) +{ + FILE *f; + size_t n; + md2_context ctx; + unsigned char buf[1024]; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( POLARSSL_ERR_MD2_FILE_IO_ERROR ); + + md2_init( &ctx ); + md2_starts( &ctx ); + + while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) + md2_update( &ctx, buf, n ); + + md2_finish( &ctx, output ); + md2_free( &ctx ); + + if( ferror( f ) != 0 ) + { + fclose( f ); + return( POLARSSL_ERR_MD2_FILE_IO_ERROR ); + } + + fclose( f ); + return( 0 ); +} +#endif /* POLARSSL_FS_IO */ + +/* + * MD2 HMAC context setup + */ +void md2_hmac_starts( md2_context *ctx, const unsigned char *key, + size_t keylen ) +{ + size_t i; + unsigned char sum[16]; + + if( keylen > 16 ) + { + md2( key, keylen, sum ); + keylen = 16; + key = sum; + } + + memset( ctx->ipad, 0x36, 16 ); + memset( ctx->opad, 0x5C, 16 ); + + for( i = 0; i < keylen; i++ ) + { + ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] ); + ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] ); + } + + md2_starts( ctx ); + md2_update( ctx, ctx->ipad, 16 ); + + polarssl_zeroize( sum, sizeof( sum ) ); +} + +/* + * MD2 HMAC process buffer + */ +void md2_hmac_update( md2_context *ctx, const unsigned char *input, + size_t ilen ) +{ + md2_update( ctx, input, ilen ); +} + +/* + * MD2 HMAC final digest + */ +void md2_hmac_finish( md2_context *ctx, unsigned char output[16] ) +{ + unsigned char tmpbuf[16]; + + md2_finish( ctx, tmpbuf ); + md2_starts( ctx ); + md2_update( ctx, ctx->opad, 16 ); + md2_update( ctx, tmpbuf, 16 ); + md2_finish( ctx, output ); + + polarssl_zeroize( tmpbuf, sizeof( tmpbuf ) ); +} + +/* + * MD2 HMAC context reset + */ +void md2_hmac_reset( md2_context *ctx ) +{ + md2_starts( ctx ); + md2_update( ctx, ctx->ipad, 16 ); +} + +/* + * output = HMAC-MD2( hmac key, input buffer ) + */ +void md2_hmac( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char output[16] ) +{ + md2_context ctx; + + md2_init( &ctx ); + md2_hmac_starts( &ctx, key, keylen ); + md2_hmac_update( &ctx, input, ilen ); + md2_hmac_finish( &ctx, output ); + md2_free( &ctx ); +} + +#if defined(POLARSSL_SELF_TEST) + +/* + * RFC 1319 test vectors + */ +static const char md2_test_str[7][81] = +{ + { "" }, + { "a" }, + { "abc" }, + { "message digest" }, + { "abcdefghijklmnopqrstuvwxyz" }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, + { "12345678901234567890123456789012345678901234567890123456789012" \ + "345678901234567890" } +}; + +static const unsigned char md2_test_sum[7][16] = +{ + { 0x83, 0x50, 0xE5, 0xA3, 0xE2, 0x4C, 0x15, 0x3D, + 0xF2, 0x27, 0x5C, 0x9F, 0x80, 0x69, 0x27, 0x73 }, + { 0x32, 0xEC, 0x01, 0xEC, 0x4A, 0x6D, 0xAC, 0x72, + 0xC0, 0xAB, 0x96, 0xFB, 0x34, 0xC0, 0xB5, 0xD1 }, + { 0xDA, 0x85, 0x3B, 0x0D, 0x3F, 0x88, 0xD9, 0x9B, + 0x30, 0x28, 0x3A, 0x69, 0xE6, 0xDE, 0xD6, 0xBB }, + { 0xAB, 0x4F, 0x49, 0x6B, 0xFB, 0x2A, 0x53, 0x0B, + 0x21, 0x9F, 0xF3, 0x30, 0x31, 0xFE, 0x06, 0xB0 }, + { 0x4E, 0x8D, 0xDF, 0xF3, 0x65, 0x02, 0x92, 0xAB, + 0x5A, 0x41, 0x08, 0xC3, 0xAA, 0x47, 0x94, 0x0B }, + { 0xDA, 0x33, 0xDE, 0xF2, 0xA4, 0x2D, 0xF1, 0x39, + 0x75, 0x35, 0x28, 0x46, 0xC3, 0x03, 0x38, 0xCD }, + { 0xD5, 0x97, 0x6F, 0x79, 0xD8, 0x3D, 0x3A, 0x0D, + 0xC9, 0x80, 0x6C, 0x3C, 0x66, 0xF3, 0xEF, 0xD8 } +}; + +/* + * Checkup routine + */ +int md2_self_test( int verbose ) +{ + int i; + unsigned char md2sum[16]; + + for( i = 0; i < 7; i++ ) + { + if( verbose != 0 ) + polarssl_printf( " MD2 test #%d: ", i + 1 ); + + md2( (unsigned char *) md2_test_str[i], + strlen( md2_test_str[i] ), md2sum ); + + if( memcmp( md2sum, md2_test_sum[i], 16 ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); + + return( 0 ); +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_MD2_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/md4.c b/component/common/network/ssl/polarssl-1.3.8/library/md4.c new file mode 100644 index 0000000..f6b71d5 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/md4.c @@ -0,0 +1,494 @@ +/* + * RFC 1186/1320 compliant MD4 implementation + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * The MD4 algorithm was designed by Ron Rivest in 1990. + * + * http://www.ietf.org/rfc/rfc1186.txt + * http://www.ietf.org/rfc/rfc1320.txt + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_MD4_C) + +#include "polarssl/md4.h" + +#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST) +#include +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#define polarssl_printf printf +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +#if !defined(POLARSSL_MD4_ALT) + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_UINT32_LE +#define GET_UINT32_LE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] ) \ + | ( (uint32_t) (b)[(i) + 1] << 8 ) \ + | ( (uint32_t) (b)[(i) + 2] << 16 ) \ + | ( (uint32_t) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_UINT32_LE +#define PUT_UINT32_LE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \ +} +#endif + +void md4_init( md4_context *ctx ) +{ + memset( ctx, 0, sizeof( md4_context ) ); +} + +void md4_free( md4_context *ctx ) +{ + if( ctx == NULL ) + return; + + polarssl_zeroize( ctx, sizeof( md4_context ) ); +} + +/* + * MD4 context setup + */ +void md4_starts( md4_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; +} + +void md4_process( md4_context *ctx, const unsigned char data[64] ) +{ + uint32_t X[16], A, B, C, D; + + GET_UINT32_LE( X[ 0], data, 0 ); + GET_UINT32_LE( X[ 1], data, 4 ); + GET_UINT32_LE( X[ 2], data, 8 ); + GET_UINT32_LE( X[ 3], data, 12 ); + GET_UINT32_LE( X[ 4], data, 16 ); + GET_UINT32_LE( X[ 5], data, 20 ); + GET_UINT32_LE( X[ 6], data, 24 ); + GET_UINT32_LE( X[ 7], data, 28 ); + GET_UINT32_LE( X[ 8], data, 32 ); + GET_UINT32_LE( X[ 9], data, 36 ); + GET_UINT32_LE( X[10], data, 40 ); + GET_UINT32_LE( X[11], data, 44 ); + GET_UINT32_LE( X[12], data, 48 ); + GET_UINT32_LE( X[13], data, 52 ); + GET_UINT32_LE( X[14], data, 56 ); + GET_UINT32_LE( X[15], data, 60 ); + +#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + +#define F(x, y, z) ((x & y) | ((~x) & z)) +#define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); } + + P( A, B, C, D, X[ 0], 3 ); + P( D, A, B, C, X[ 1], 7 ); + P( C, D, A, B, X[ 2], 11 ); + P( B, C, D, A, X[ 3], 19 ); + P( A, B, C, D, X[ 4], 3 ); + P( D, A, B, C, X[ 5], 7 ); + P( C, D, A, B, X[ 6], 11 ); + P( B, C, D, A, X[ 7], 19 ); + P( A, B, C, D, X[ 8], 3 ); + P( D, A, B, C, X[ 9], 7 ); + P( C, D, A, B, X[10], 11 ); + P( B, C, D, A, X[11], 19 ); + P( A, B, C, D, X[12], 3 ); + P( D, A, B, C, X[13], 7 ); + P( C, D, A, B, X[14], 11 ); + P( B, C, D, A, X[15], 19 ); + +#undef P +#undef F + +#define F(x,y,z) ((x & y) | (x & z) | (y & z)) +#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); } + + P( A, B, C, D, X[ 0], 3 ); + P( D, A, B, C, X[ 4], 5 ); + P( C, D, A, B, X[ 8], 9 ); + P( B, C, D, A, X[12], 13 ); + P( A, B, C, D, X[ 1], 3 ); + P( D, A, B, C, X[ 5], 5 ); + P( C, D, A, B, X[ 9], 9 ); + P( B, C, D, A, X[13], 13 ); + P( A, B, C, D, X[ 2], 3 ); + P( D, A, B, C, X[ 6], 5 ); + P( C, D, A, B, X[10], 9 ); + P( B, C, D, A, X[14], 13 ); + P( A, B, C, D, X[ 3], 3 ); + P( D, A, B, C, X[ 7], 5 ); + P( C, D, A, B, X[11], 9 ); + P( B, C, D, A, X[15], 13 ); + +#undef P +#undef F + +#define F(x,y,z) (x ^ y ^ z) +#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); } + + P( A, B, C, D, X[ 0], 3 ); + P( D, A, B, C, X[ 8], 9 ); + P( C, D, A, B, X[ 4], 11 ); + P( B, C, D, A, X[12], 15 ); + P( A, B, C, D, X[ 2], 3 ); + P( D, A, B, C, X[10], 9 ); + P( C, D, A, B, X[ 6], 11 ); + P( B, C, D, A, X[14], 15 ); + P( A, B, C, D, X[ 1], 3 ); + P( D, A, B, C, X[ 9], 9 ); + P( C, D, A, B, X[ 5], 11 ); + P( B, C, D, A, X[13], 15 ); + P( A, B, C, D, X[ 3], 3 ); + P( D, A, B, C, X[11], 9 ); + P( C, D, A, B, X[ 7], 11 ); + P( B, C, D, A, X[15], 15 ); + +#undef F +#undef P + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; +} + +/* + * MD4 process buffer + */ +void md4_update( md4_context *ctx, const unsigned char *input, size_t ilen ) +{ + size_t fill; + uint32_t left; + + if( ilen == 0 ) + return; + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), + (void *) input, fill ); + md4_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + md4_process( ctx, input ); + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + memcpy( (void *) (ctx->buffer + left), + (void *) input, ilen ); + } +} + +static const unsigned char md4_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * MD4 final digest + */ +void md4_finish( md4_context *ctx, unsigned char output[16] ) +{ + uint32_t last, padn; + uint32_t high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_LE( low, msglen, 0 ); + PUT_UINT32_LE( high, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + md4_update( ctx, (unsigned char *) md4_padding, padn ); + md4_update( ctx, msglen, 8 ); + + PUT_UINT32_LE( ctx->state[0], output, 0 ); + PUT_UINT32_LE( ctx->state[1], output, 4 ); + PUT_UINT32_LE( ctx->state[2], output, 8 ); + PUT_UINT32_LE( ctx->state[3], output, 12 ); +} + +#endif /* !POLARSSL_MD4_ALT */ + +/* + * output = MD4( input buffer ) + */ +void md4( const unsigned char *input, size_t ilen, unsigned char output[16] ) +{ + md4_context ctx; + + md4_init( &ctx ); + md4_starts( &ctx ); + md4_update( &ctx, input, ilen ); + md4_finish( &ctx, output ); + md4_free( &ctx ); +} + +#if defined(POLARSSL_FS_IO) +/* + * output = MD4( file contents ) + */ +int md4_file( const char *path, unsigned char output[16] ) +{ + FILE *f; + size_t n; + md4_context ctx; + unsigned char buf[1024]; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( POLARSSL_ERR_MD4_FILE_IO_ERROR ); + + md4_init( &ctx ); + md4_starts( &ctx ); + + while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) + md4_update( &ctx, buf, n ); + + md4_finish( &ctx, output ); + md4_free( &ctx ); + + if( ferror( f ) != 0 ) + { + fclose( f ); + return( POLARSSL_ERR_MD4_FILE_IO_ERROR ); + } + + fclose( f ); + return( 0 ); +} +#endif /* POLARSSL_FS_IO */ + +/* + * MD4 HMAC context setup + */ +void md4_hmac_starts( md4_context *ctx, const unsigned char *key, + size_t keylen ) +{ + size_t i; + unsigned char sum[16]; + + if( keylen > 64 ) + { + md4( key, keylen, sum ); + keylen = 16; + key = sum; + } + + memset( ctx->ipad, 0x36, 64 ); + memset( ctx->opad, 0x5C, 64 ); + + for( i = 0; i < keylen; i++ ) + { + ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] ); + ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] ); + } + + md4_starts( ctx ); + md4_update( ctx, ctx->ipad, 64 ); + + polarssl_zeroize( sum, sizeof( sum ) ); +} + +/* + * MD4 HMAC process buffer + */ +void md4_hmac_update( md4_context *ctx, const unsigned char *input, + size_t ilen ) +{ + md4_update( ctx, input, ilen ); +} + +/* + * MD4 HMAC final digest + */ +void md4_hmac_finish( md4_context *ctx, unsigned char output[16] ) +{ + unsigned char tmpbuf[16]; + + md4_finish( ctx, tmpbuf ); + md4_starts( ctx ); + md4_update( ctx, ctx->opad, 64 ); + md4_update( ctx, tmpbuf, 16 ); + md4_finish( ctx, output ); + + polarssl_zeroize( tmpbuf, sizeof( tmpbuf ) ); +} + +/* + * MD4 HMAC context reset + */ +void md4_hmac_reset( md4_context *ctx ) +{ + md4_starts( ctx ); + md4_update( ctx, ctx->ipad, 64 ); +} + +/* + * output = HMAC-MD4( hmac key, input buffer ) + */ +void md4_hmac( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char output[16] ) +{ + md4_context ctx; + + md4_init( &ctx ); + md4_hmac_starts( &ctx, key, keylen ); + md4_hmac_update( &ctx, input, ilen ); + md4_hmac_finish( &ctx, output ); + md4_free( &ctx ); +} + +#if defined(POLARSSL_SELF_TEST) + +/* + * RFC 1320 test vectors + */ +static const char md4_test_str[7][81] = +{ + { "" }, + { "a" }, + { "abc" }, + { "message digest" }, + { "abcdefghijklmnopqrstuvwxyz" }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, + { "12345678901234567890123456789012345678901234567890123456789012" \ + "345678901234567890" } +}; + +static const unsigned char md4_test_sum[7][16] = +{ + { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31, + 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 }, + { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46, + 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 }, + { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52, + 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D }, + { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8, + 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B }, + { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD, + 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 }, + { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35, + 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 }, + { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19, + 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 } +}; + +/* + * Checkup routine + */ +int md4_self_test( int verbose ) +{ + int i; + unsigned char md4sum[16]; + + for( i = 0; i < 7; i++ ) + { + if( verbose != 0 ) + polarssl_printf( " MD4 test #%d: ", i + 1 ); + + md4( (unsigned char *) md4_test_str[i], + strlen( md4_test_str[i] ), md4sum ); + + if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); + + return( 0 ); +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_MD4_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/md5.c b/component/common/network/ssl/polarssl-1.3.8/library/md5.c new file mode 100644 index 0000000..89354bc --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/md5.c @@ -0,0 +1,615 @@ +/* + * RFC 1321 compliant MD5 implementation + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * The MD5 algorithm was designed by Ron Rivest in 1991. + * + * http://www.ietf.org/rfc/rfc1321.txt + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_MD5_C) + +#include "polarssl/md5.h" + +#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST) +#include +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#define polarssl_printf printf +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +#if !defined(POLARSSL_MD5_ALT) + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_UINT32_LE +#define GET_UINT32_LE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] ) \ + | ( (uint32_t) (b)[(i) + 1] << 8 ) \ + | ( (uint32_t) (b)[(i) + 2] << 16 ) \ + | ( (uint32_t) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_UINT32_LE +#define PUT_UINT32_LE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \ +} +#endif + +void md5_init( md5_context *ctx ) +{ + memset( ctx, 0, sizeof( md5_context ) ); +} + +void md5_free( md5_context *ctx ) +{ + if( ctx == NULL ) + return; + + polarssl_zeroize( ctx, sizeof( md5_context ) ); +} + +/* + * MD5 context setup + */ +void md5_starts( md5_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; +} + +void md5_process( md5_context *ctx, const unsigned char data[64] ) +{ + uint32_t X[16], A, B, C, D; + + GET_UINT32_LE( X[ 0], data, 0 ); + GET_UINT32_LE( X[ 1], data, 4 ); + GET_UINT32_LE( X[ 2], data, 8 ); + GET_UINT32_LE( X[ 3], data, 12 ); + GET_UINT32_LE( X[ 4], data, 16 ); + GET_UINT32_LE( X[ 5], data, 20 ); + GET_UINT32_LE( X[ 6], data, 24 ); + GET_UINT32_LE( X[ 7], data, 28 ); + GET_UINT32_LE( X[ 8], data, 32 ); + GET_UINT32_LE( X[ 9], data, 36 ); + GET_UINT32_LE( X[10], data, 40 ); + GET_UINT32_LE( X[11], data, 44 ); + GET_UINT32_LE( X[12], data, 48 ); + GET_UINT32_LE( X[13], data, 52 ); + GET_UINT32_LE( X[14], data, 56 ); + GET_UINT32_LE( X[15], data, 60 ); + +#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) + +#define P(a,b,c,d,k,s,t) \ +{ \ + a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \ +} + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + +#define F(x,y,z) (z ^ (x & (y ^ z))) + + P( A, B, C, D, 0, 7, 0xD76AA478 ); + P( D, A, B, C, 1, 12, 0xE8C7B756 ); + P( C, D, A, B, 2, 17, 0x242070DB ); + P( B, C, D, A, 3, 22, 0xC1BDCEEE ); + P( A, B, C, D, 4, 7, 0xF57C0FAF ); + P( D, A, B, C, 5, 12, 0x4787C62A ); + P( C, D, A, B, 6, 17, 0xA8304613 ); + P( B, C, D, A, 7, 22, 0xFD469501 ); + P( A, B, C, D, 8, 7, 0x698098D8 ); + P( D, A, B, C, 9, 12, 0x8B44F7AF ); + P( C, D, A, B, 10, 17, 0xFFFF5BB1 ); + P( B, C, D, A, 11, 22, 0x895CD7BE ); + P( A, B, C, D, 12, 7, 0x6B901122 ); + P( D, A, B, C, 13, 12, 0xFD987193 ); + P( C, D, A, B, 14, 17, 0xA679438E ); + P( B, C, D, A, 15, 22, 0x49B40821 ); + +#undef F + +#define F(x,y,z) (y ^ (z & (x ^ y))) + + P( A, B, C, D, 1, 5, 0xF61E2562 ); + P( D, A, B, C, 6, 9, 0xC040B340 ); + P( C, D, A, B, 11, 14, 0x265E5A51 ); + P( B, C, D, A, 0, 20, 0xE9B6C7AA ); + P( A, B, C, D, 5, 5, 0xD62F105D ); + P( D, A, B, C, 10, 9, 0x02441453 ); + P( C, D, A, B, 15, 14, 0xD8A1E681 ); + P( B, C, D, A, 4, 20, 0xE7D3FBC8 ); + P( A, B, C, D, 9, 5, 0x21E1CDE6 ); + P( D, A, B, C, 14, 9, 0xC33707D6 ); + P( C, D, A, B, 3, 14, 0xF4D50D87 ); + P( B, C, D, A, 8, 20, 0x455A14ED ); + P( A, B, C, D, 13, 5, 0xA9E3E905 ); + P( D, A, B, C, 2, 9, 0xFCEFA3F8 ); + P( C, D, A, B, 7, 14, 0x676F02D9 ); + P( B, C, D, A, 12, 20, 0x8D2A4C8A ); + +#undef F + +#define F(x,y,z) (x ^ y ^ z) + + P( A, B, C, D, 5, 4, 0xFFFA3942 ); + P( D, A, B, C, 8, 11, 0x8771F681 ); + P( C, D, A, B, 11, 16, 0x6D9D6122 ); + P( B, C, D, A, 14, 23, 0xFDE5380C ); + P( A, B, C, D, 1, 4, 0xA4BEEA44 ); + P( D, A, B, C, 4, 11, 0x4BDECFA9 ); + P( C, D, A, B, 7, 16, 0xF6BB4B60 ); + P( B, C, D, A, 10, 23, 0xBEBFBC70 ); + P( A, B, C, D, 13, 4, 0x289B7EC6 ); + P( D, A, B, C, 0, 11, 0xEAA127FA ); + P( C, D, A, B, 3, 16, 0xD4EF3085 ); + P( B, C, D, A, 6, 23, 0x04881D05 ); + P( A, B, C, D, 9, 4, 0xD9D4D039 ); + P( D, A, B, C, 12, 11, 0xE6DB99E5 ); + P( C, D, A, B, 15, 16, 0x1FA27CF8 ); + P( B, C, D, A, 2, 23, 0xC4AC5665 ); + +#undef F + +#define F(x,y,z) (y ^ (x | ~z)) + + P( A, B, C, D, 0, 6, 0xF4292244 ); + P( D, A, B, C, 7, 10, 0x432AFF97 ); + P( C, D, A, B, 14, 15, 0xAB9423A7 ); + P( B, C, D, A, 5, 21, 0xFC93A039 ); + P( A, B, C, D, 12, 6, 0x655B59C3 ); + P( D, A, B, C, 3, 10, 0x8F0CCC92 ); + P( C, D, A, B, 10, 15, 0xFFEFF47D ); + P( B, C, D, A, 1, 21, 0x85845DD1 ); + P( A, B, C, D, 8, 6, 0x6FA87E4F ); + P( D, A, B, C, 15, 10, 0xFE2CE6E0 ); + P( C, D, A, B, 6, 15, 0xA3014314 ); + P( B, C, D, A, 13, 21, 0x4E0811A1 ); + P( A, B, C, D, 4, 6, 0xF7537E82 ); + P( D, A, B, C, 11, 10, 0xBD3AF235 ); + P( C, D, A, B, 2, 15, 0x2AD7D2BB ); + P( B, C, D, A, 9, 21, 0xEB86D391 ); + +#undef F + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; +} + +/* + * MD5 process buffer + */ +void md5_update( md5_context *ctx, const unsigned char *input, size_t ilen ) +{ + size_t fill; + uint32_t left; + + if( ilen == 0 ) + return; + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + md5_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + md5_process( ctx, input ); + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + memcpy( (void *) (ctx->buffer + left), input, ilen ); + } +} + +static const unsigned char md5_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * MD5 final digest + */ +void md5_finish( md5_context *ctx, unsigned char output[16] ) +{ + uint32_t last, padn; + uint32_t high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_LE( low, msglen, 0 ); + PUT_UINT32_LE( high, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + md5_update( ctx, md5_padding, padn ); + md5_update( ctx, msglen, 8 ); + + PUT_UINT32_LE( ctx->state[0], output, 0 ); + PUT_UINT32_LE( ctx->state[1], output, 4 ); + PUT_UINT32_LE( ctx->state[2], output, 8 ); + PUT_UINT32_LE( ctx->state[3], output, 12 ); +} + +#endif /* !POLARSSL_MD5_ALT */ + +/* + * output = MD5( input buffer ) + */ +void md5( const unsigned char *input, size_t ilen, unsigned char output[16] ) +{ + md5_context ctx; + + md5_init( &ctx ); + md5_starts( &ctx ); + md5_update( &ctx, input, ilen ); + md5_finish( &ctx, output ); + md5_free( &ctx ); +} + +#if defined(POLARSSL_FS_IO) +/* + * output = MD5( file contents ) + */ +int md5_file( const char *path, unsigned char output[16] ) +{ + FILE *f; + size_t n; + md5_context ctx; + unsigned char buf[1024]; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( POLARSSL_ERR_MD5_FILE_IO_ERROR ); + + md5_init( &ctx ); + md5_starts( &ctx ); + + while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) + md5_update( &ctx, buf, n ); + + md5_finish( &ctx, output ); + md5_free( &ctx ); + + if( ferror( f ) != 0 ) + { + fclose( f ); + return( POLARSSL_ERR_MD5_FILE_IO_ERROR ); + } + + fclose( f ); + return( 0 ); +} +#endif /* POLARSSL_FS_IO */ + +/* + * MD5 HMAC context setup + */ +void md5_hmac_starts( md5_context *ctx, const unsigned char *key, + size_t keylen ) +{ + size_t i; + unsigned char sum[16]; + + if( keylen > 64 ) + { + md5( key, keylen, sum ); + keylen = 16; + key = sum; + } + + memset( ctx->ipad, 0x36, 64 ); + memset( ctx->opad, 0x5C, 64 ); + + for( i = 0; i < keylen; i++ ) + { + ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] ); + ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] ); + } + + md5_starts( ctx ); + md5_update( ctx, ctx->ipad, 64 ); + + polarssl_zeroize( sum, sizeof( sum ) ); +} + +/* + * MD5 HMAC process buffer + */ +void md5_hmac_update( md5_context *ctx, const unsigned char *input, + size_t ilen ) +{ + md5_update( ctx, input, ilen ); +} + +/* + * MD5 HMAC final digest + */ +void md5_hmac_finish( md5_context *ctx, unsigned char output[16] ) +{ + unsigned char tmpbuf[16]; + + md5_finish( ctx, tmpbuf ); + md5_starts( ctx ); + md5_update( ctx, ctx->opad, 64 ); + md5_update( ctx, tmpbuf, 16 ); + md5_finish( ctx, output ); + + polarssl_zeroize( tmpbuf, sizeof( tmpbuf ) ); +} + +/* + * MD5 HMAC context reset + */ +void md5_hmac_reset( md5_context *ctx ) +{ + md5_starts( ctx ); + md5_update( ctx, ctx->ipad, 64 ); +} + +/* + * output = HMAC-MD5( hmac key, input buffer ) + */ +void md5_hmac( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char output[16] ) +{ + md5_context ctx; + + md5_init( &ctx ); + md5_hmac_starts( &ctx, key, keylen ); + md5_hmac_update( &ctx, input, ilen ); + md5_hmac_finish( &ctx, output ); + md5_free( &ctx ); +} + +#if defined(POLARSSL_SELF_TEST) +/* + * RFC 1321 test vectors + */ +static unsigned char md5_test_buf[7][81] = +{ + { "" }, + { "a" }, + { "abc" }, + { "message digest" }, + { "abcdefghijklmnopqrstuvwxyz" }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, + { "12345678901234567890123456789012345678901234567890123456789012" \ + "345678901234567890" } +}; + +static const int md5_test_buflen[7] = +{ + 0, 1, 3, 14, 26, 62, 80 +}; + +static const unsigned char md5_test_sum[7][16] = +{ + { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04, + 0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E }, + { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8, + 0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 }, + { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0, + 0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 }, + { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D, + 0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 }, + { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00, + 0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B }, + { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5, + 0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F }, + { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55, + 0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A } +}; + +/* + * RFC 2202 test vectors + */ +static unsigned char md5_hmac_test_key[7][26] = +{ + { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B" }, + { "Jefe" }, + { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" }, + { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10" + "\x11\x12\x13\x14\x15\x16\x17\x18\x19" }, + { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C" }, + { "" }, /* 0xAA 80 times */ + { "" } +}; + +static const int md5_hmac_test_keylen[7] = +{ + 16, 4, 16, 25, 16, 80, 80 +}; + +static unsigned char md5_hmac_test_buf[7][74] = +{ + { "Hi There" }, + { "what do ya want for nothing?" }, + { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" }, + { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" }, + { "Test With Truncation" }, + { "Test Using Larger Than Block-Size Key - Hash Key First" }, + { "Test Using Larger Than Block-Size Key and Larger" + " Than One Block-Size Data" } +}; + +static const int md5_hmac_test_buflen[7] = +{ + 8, 28, 50, 50, 20, 54, 73 +}; + +static const unsigned char md5_hmac_test_sum[7][16] = +{ + { 0x92, 0x94, 0x72, 0x7A, 0x36, 0x38, 0xBB, 0x1C, + 0x13, 0xF4, 0x8E, 0xF8, 0x15, 0x8B, 0xFC, 0x9D }, + { 0x75, 0x0C, 0x78, 0x3E, 0x6A, 0xB0, 0xB5, 0x03, + 0xEA, 0xA8, 0x6E, 0x31, 0x0A, 0x5D, 0xB7, 0x38 }, + { 0x56, 0xBE, 0x34, 0x52, 0x1D, 0x14, 0x4C, 0x88, + 0xDB, 0xB8, 0xC7, 0x33, 0xF0, 0xE8, 0xB3, 0xF6 }, + { 0x69, 0x7E, 0xAF, 0x0A, 0xCA, 0x3A, 0x3A, 0xEA, + 0x3A, 0x75, 0x16, 0x47, 0x46, 0xFF, 0xAA, 0x79 }, + { 0x56, 0x46, 0x1E, 0xF2, 0x34, 0x2E, 0xDC, 0x00, + 0xF9, 0xBA, 0xB9, 0x95 }, + { 0x6B, 0x1A, 0xB7, 0xFE, 0x4B, 0xD7, 0xBF, 0x8F, + 0x0B, 0x62, 0xE6, 0xCE, 0x61, 0xB9, 0xD0, 0xCD }, + { 0x6F, 0x63, 0x0F, 0xAD, 0x67, 0xCD, 0xA0, 0xEE, + 0x1F, 0xB1, 0xF5, 0x62, 0xDB, 0x3A, 0xA5, 0x3E } +}; + +/* + * Checkup routine + */ +int md5_self_test( int verbose ) +{ + int i, buflen; + unsigned char buf[1024]; + unsigned char md5sum[16]; + md5_context ctx; + + for( i = 0; i < 7; i++ ) + { + if( verbose != 0 ) + polarssl_printf( " MD5 test #%d: ", i + 1 ); + + md5( md5_test_buf[i], md5_test_buflen[i], md5sum ); + + if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); + + for( i = 0; i < 7; i++ ) + { + if( verbose != 0 ) + polarssl_printf( " HMAC-MD5 test #%d: ", i + 1 ); + + if( i == 5 || i == 6 ) + { + memset( buf, '\xAA', buflen = 80 ); + md5_hmac_starts( &ctx, buf, buflen ); + } + else + md5_hmac_starts( &ctx, md5_hmac_test_key[i], + md5_hmac_test_keylen[i] ); + + md5_hmac_update( &ctx, md5_hmac_test_buf[i], + md5_hmac_test_buflen[i] ); + + md5_hmac_finish( &ctx, md5sum ); + + buflen = ( i == 4 ) ? 12 : 16; + + if( memcmp( md5sum, md5_hmac_test_sum[i], buflen ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); + + return( 0 ); +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_MD5_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/md_wrap.c b/component/common/network/ssl/polarssl-1.3.8/library/md_wrap.c new file mode 100644 index 0000000..de701d3 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/md_wrap.c @@ -0,0 +1,955 @@ +/** + * \file md_wrap.c + + * \brief Generic message digest wrapper for PolarSSL + * + * \author Adriaan de Jong + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_MD_C) + +#include "polarssl/md_wrap.h" + +#if defined(POLARSSL_MD2_C) +#include "polarssl/md2.h" +#endif + +#if defined(POLARSSL_MD4_C) +#include "polarssl/md4.h" +#endif + +#if defined(POLARSSL_MD5_C) +#include "polarssl/md5.h" +#endif + +#if defined(POLARSSL_RIPEMD160_C) +#include "polarssl/ripemd160.h" +#endif + +#if defined(POLARSSL_SHA1_C) +#include "polarssl/sha1.h" +#endif + +#if defined(POLARSSL_SHA256_C) +#include "polarssl/sha256.h" +#endif + +#if defined(POLARSSL_SHA512_C) +#include "polarssl/sha512.h" +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#define polarssl_malloc malloc +#define polarssl_free free +#endif + +#include + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +#if defined(POLARSSL_MD2_C) + +static void md2_starts_wrap( void *ctx ) +{ + md2_starts( (md2_context *) ctx ); +} + +static void md2_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + md2_update( (md2_context *) ctx, input, ilen ); +} + +static void md2_finish_wrap( void *ctx, unsigned char *output ) +{ + md2_finish( (md2_context *) ctx, output ); +} + +static int md2_file_wrap( const char *path, unsigned char *output ) +{ +#if defined(POLARSSL_FS_IO) + return md2_file( path, output ); +#else + ((void) path); + ((void) output); + return( POLARSSL_ERR_MD_FEATURE_UNAVAILABLE ); +#endif +} + +static void md2_hmac_starts_wrap( void *ctx, const unsigned char *key, + size_t keylen ) +{ + md2_hmac_starts( (md2_context *) ctx, key, keylen ); +} + +static void md2_hmac_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + md2_hmac_update( (md2_context *) ctx, input, ilen ); +} + +static void md2_hmac_finish_wrap( void *ctx, unsigned char *output ) +{ + md2_hmac_finish( (md2_context *) ctx, output ); +} + +static void md2_hmac_reset_wrap( void *ctx ) +{ + md2_hmac_reset( (md2_context *) ctx ); +} + +static void * md2_ctx_alloc( void ) +{ + return polarssl_malloc( sizeof( md2_context ) ); +} + +static void md2_ctx_free( void *ctx ) +{ + polarssl_zeroize( ctx, sizeof( md2_context ) ); + polarssl_free( ctx ); +} + +static void md2_process_wrap( void *ctx, const unsigned char *data ) +{ + ((void) data); + + md2_process( (md2_context *) ctx ); +} + +const md_info_t md2_info = { + POLARSSL_MD_MD2, + "MD2", + 16, + md2_starts_wrap, + md2_update_wrap, + md2_finish_wrap, + md2, + md2_file_wrap, + md2_hmac_starts_wrap, + md2_hmac_update_wrap, + md2_hmac_finish_wrap, + md2_hmac_reset_wrap, + md2_hmac, + md2_ctx_alloc, + md2_ctx_free, + md2_process_wrap, +}; + +#endif /* POLARSSL_MD2_C */ + +#if defined(POLARSSL_MD4_C) + +static void md4_starts_wrap( void *ctx ) +{ + md4_starts( (md4_context *) ctx ); +} + +static void md4_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + md4_update( (md4_context *) ctx, input, ilen ); +} + +static void md4_finish_wrap( void *ctx, unsigned char *output ) +{ + md4_finish( (md4_context *) ctx, output ); +} + +static int md4_file_wrap( const char *path, unsigned char *output ) +{ +#if defined(POLARSSL_FS_IO) + return md4_file( path, output ); +#else + ((void) path); + ((void) output); + return( POLARSSL_ERR_MD_FEATURE_UNAVAILABLE ); +#endif +} + +static void md4_hmac_starts_wrap( void *ctx, const unsigned char *key, + size_t keylen ) +{ + md4_hmac_starts( (md4_context *) ctx, key, keylen ); +} + +static void md4_hmac_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + md4_hmac_update( (md4_context *) ctx, input, ilen ); +} + +static void md4_hmac_finish_wrap( void *ctx, unsigned char *output ) +{ + md4_hmac_finish( (md4_context *) ctx, output ); +} + +static void md4_hmac_reset_wrap( void *ctx ) +{ + md4_hmac_reset( (md4_context *) ctx ); +} + +static void *md4_ctx_alloc( void ) +{ + return polarssl_malloc( sizeof( md4_context ) ); +} + +static void md4_ctx_free( void *ctx ) +{ + polarssl_zeroize( ctx, sizeof( md4_context ) ); + polarssl_free( ctx ); +} + +static void md4_process_wrap( void *ctx, const unsigned char *data ) +{ + md4_process( (md4_context *) ctx, data ); +} + +const md_info_t md4_info = { + POLARSSL_MD_MD4, + "MD4", + 16, + md4_starts_wrap, + md4_update_wrap, + md4_finish_wrap, + md4, + md4_file_wrap, + md4_hmac_starts_wrap, + md4_hmac_update_wrap, + md4_hmac_finish_wrap, + md4_hmac_reset_wrap, + md4_hmac, + md4_ctx_alloc, + md4_ctx_free, + md4_process_wrap, +}; + +#endif /* POLARSSL_MD4_C */ + +#if defined(POLARSSL_MD5_C) + +static void md5_starts_wrap( void *ctx ) +{ + md5_starts( (md5_context *) ctx ); +} + +static void md5_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + md5_update( (md5_context *) ctx, input, ilen ); +} + +static void md5_finish_wrap( void *ctx, unsigned char *output ) +{ + md5_finish( (md5_context *) ctx, output ); +} + +static int md5_file_wrap( const char *path, unsigned char *output ) +{ +#if defined(POLARSSL_FS_IO) + return md5_file( path, output ); +#else + ((void) path); + ((void) output); + return( POLARSSL_ERR_MD_FEATURE_UNAVAILABLE ); +#endif +} + +static void md5_hmac_starts_wrap( void *ctx, const unsigned char *key, + size_t keylen ) +{ + md5_hmac_starts( (md5_context *) ctx, key, keylen ); +} + +static void md5_hmac_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + md5_hmac_update( (md5_context *) ctx, input, ilen ); +} + +static void md5_hmac_finish_wrap( void *ctx, unsigned char *output ) +{ + md5_hmac_finish( (md5_context *) ctx, output ); +} + +static void md5_hmac_reset_wrap( void *ctx ) +{ + md5_hmac_reset( (md5_context *) ctx ); +} + +static void * md5_ctx_alloc( void ) +{ + return polarssl_malloc( sizeof( md5_context ) ); +} + +static void md5_ctx_free( void *ctx ) +{ + polarssl_zeroize( ctx, sizeof( md5_context ) ); + polarssl_free( ctx ); +} + +static void md5_process_wrap( void *ctx, const unsigned char *data ) +{ + md5_process( (md5_context *) ctx, data ); +} + +const md_info_t md5_info = { + POLARSSL_MD_MD5, + "MD5", + 16, + md5_starts_wrap, + md5_update_wrap, + md5_finish_wrap, + md5, + md5_file_wrap, + md5_hmac_starts_wrap, + md5_hmac_update_wrap, + md5_hmac_finish_wrap, + md5_hmac_reset_wrap, + md5_hmac, + md5_ctx_alloc, + md5_ctx_free, + md5_process_wrap, +}; + +#endif /* POLARSSL_MD5_C */ + +#if defined(POLARSSL_RIPEMD160_C) + +static void ripemd160_starts_wrap( void *ctx ) +{ + ripemd160_starts( (ripemd160_context *) ctx ); +} + +static void ripemd160_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + ripemd160_update( (ripemd160_context *) ctx, input, ilen ); +} + +static void ripemd160_finish_wrap( void *ctx, unsigned char *output ) +{ + ripemd160_finish( (ripemd160_context *) ctx, output ); +} + +static int ripemd160_file_wrap( const char *path, unsigned char *output ) +{ +#if defined(POLARSSL_FS_IO) + return ripemd160_file( path, output ); +#else + ((void) path); + ((void) output); + return( POLARSSL_ERR_MD_FEATURE_UNAVAILABLE ); +#endif +} + +static void ripemd160_hmac_starts_wrap( void *ctx, const unsigned char *key, + size_t keylen ) +{ + ripemd160_hmac_starts( (ripemd160_context *) ctx, key, keylen ); +} + +static void ripemd160_hmac_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + ripemd160_hmac_update( (ripemd160_context *) ctx, input, ilen ); +} + +static void ripemd160_hmac_finish_wrap( void *ctx, unsigned char *output ) +{ + ripemd160_hmac_finish( (ripemd160_context *) ctx, output ); +} + +static void ripemd160_hmac_reset_wrap( void *ctx ) +{ + ripemd160_hmac_reset( (ripemd160_context *) ctx ); +} + +static void * ripemd160_ctx_alloc( void ) +{ + ripemd160_context *ctx; + ctx = (ripemd160_context *) polarssl_malloc( sizeof( ripemd160_context ) ); + + if( ctx == NULL ) + return( NULL ); + + ripemd160_init( ctx ); + + return( ctx ); +} + +static void ripemd160_ctx_free( void *ctx ) +{ + ripemd160_free( (ripemd160_context *) ctx ); + polarssl_free( ctx ); +} + +static void ripemd160_process_wrap( void *ctx, const unsigned char *data ) +{ + ripemd160_process( (ripemd160_context *) ctx, data ); +} + +const md_info_t ripemd160_info = { + POLARSSL_MD_RIPEMD160, + "RIPEMD160", + 20, + ripemd160_starts_wrap, + ripemd160_update_wrap, + ripemd160_finish_wrap, + ripemd160, + ripemd160_file_wrap, + ripemd160_hmac_starts_wrap, + ripemd160_hmac_update_wrap, + ripemd160_hmac_finish_wrap, + ripemd160_hmac_reset_wrap, + ripemd160_hmac, + ripemd160_ctx_alloc, + ripemd160_ctx_free, + ripemd160_process_wrap, +}; + +#endif /* POLARSSL_RIPEMD160_C */ + +#if defined(POLARSSL_SHA1_C) + +static void sha1_starts_wrap( void *ctx ) +{ + sha1_starts( (sha1_context *) ctx ); +} + +static void sha1_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + sha1_update( (sha1_context *) ctx, input, ilen ); +} + +static void sha1_finish_wrap( void *ctx, unsigned char *output ) +{ + sha1_finish( (sha1_context *) ctx, output ); +} + +static int sha1_file_wrap( const char *path, unsigned char *output ) +{ +#if defined(POLARSSL_FS_IO) + return sha1_file( path, output ); +#else + ((void) path); + ((void) output); + return( POLARSSL_ERR_MD_FEATURE_UNAVAILABLE ); +#endif +} + +static void sha1_hmac_starts_wrap( void *ctx, const unsigned char *key, + size_t keylen ) +{ + sha1_hmac_starts( (sha1_context *) ctx, key, keylen ); +} + +static void sha1_hmac_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + sha1_hmac_update( (sha1_context *) ctx, input, ilen ); +} + +static void sha1_hmac_finish_wrap( void *ctx, unsigned char *output ) +{ + sha1_hmac_finish( (sha1_context *) ctx, output ); +} + +static void sha1_hmac_reset_wrap( void *ctx ) +{ + sha1_hmac_reset( (sha1_context *) ctx ); +} + +static void * sha1_ctx_alloc( void ) +{ + sha1_context *ctx; + ctx = (sha1_context *) polarssl_malloc( sizeof( sha1_context ) ); + + if( ctx == NULL ) + return( NULL ); + + sha1_init( ctx ); + + return( ctx ); +} + +static void sha1_ctx_free( void *ctx ) +{ + sha1_free( (sha1_context *) ctx ); + polarssl_free( ctx ); +} + +static void sha1_process_wrap( void *ctx, const unsigned char *data ) +{ + sha1_process( (sha1_context *) ctx, data ); +} + +const md_info_t sha1_info = { + POLARSSL_MD_SHA1, + "SHA1", + 20, + sha1_starts_wrap, + sha1_update_wrap, + sha1_finish_wrap, + sha1, + sha1_file_wrap, + sha1_hmac_starts_wrap, + sha1_hmac_update_wrap, + sha1_hmac_finish_wrap, + sha1_hmac_reset_wrap, + sha1_hmac, + sha1_ctx_alloc, + sha1_ctx_free, + sha1_process_wrap, +}; + +#endif /* POLARSSL_SHA1_C */ + +/* + * Wrappers for generic message digests + */ +#if defined(POLARSSL_SHA256_C) + +static void sha224_starts_wrap( void *ctx ) +{ + sha256_starts( (sha256_context *) ctx, 1 ); +} + +static void sha224_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + sha256_update( (sha256_context *) ctx, input, ilen ); +} + +static void sha224_finish_wrap( void *ctx, unsigned char *output ) +{ + sha256_finish( (sha256_context *) ctx, output ); +} + +static void sha224_wrap( const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + sha256( input, ilen, output, 1 ); +} + +static int sha224_file_wrap( const char *path, unsigned char *output ) +{ +#if defined(POLARSSL_FS_IO) + return sha256_file( path, output, 1 ); +#else + ((void) path); + ((void) output); + return( POLARSSL_ERR_MD_FEATURE_UNAVAILABLE ); +#endif +} + +static void sha224_hmac_starts_wrap( void *ctx, const unsigned char *key, + size_t keylen ) +{ + sha256_hmac_starts( (sha256_context *) ctx, key, keylen, 1 ); +} + +static void sha224_hmac_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + sha256_hmac_update( (sha256_context *) ctx, input, ilen ); +} + +static void sha224_hmac_finish_wrap( void *ctx, unsigned char *output ) +{ + sha256_hmac_finish( (sha256_context *) ctx, output ); +} + +static void sha224_hmac_reset_wrap( void *ctx ) +{ + sha256_hmac_reset( (sha256_context *) ctx ); +} + +static void sha224_hmac_wrap( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + sha256_hmac( key, keylen, input, ilen, output, 1 ); +} + +static void * sha224_ctx_alloc( void ) +{ + return polarssl_malloc( sizeof( sha256_context ) ); +} + +static void sha224_ctx_free( void *ctx ) +{ + polarssl_zeroize( ctx, sizeof( sha256_context ) ); + polarssl_free( ctx ); +} + +static void sha224_process_wrap( void *ctx, const unsigned char *data ) +{ + sha256_process( (sha256_context *) ctx, data ); +} + +const md_info_t sha224_info = { + POLARSSL_MD_SHA224, + "SHA224", + 28, + sha224_starts_wrap, + sha224_update_wrap, + sha224_finish_wrap, + sha224_wrap, + sha224_file_wrap, + sha224_hmac_starts_wrap, + sha224_hmac_update_wrap, + sha224_hmac_finish_wrap, + sha224_hmac_reset_wrap, + sha224_hmac_wrap, + sha224_ctx_alloc, + sha224_ctx_free, + sha224_process_wrap, +}; + +static void sha256_starts_wrap( void *ctx ) +{ + sha256_starts( (sha256_context *) ctx, 0 ); +} + +static void sha256_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + sha256_update( (sha256_context *) ctx, input, ilen ); +} + +static void sha256_finish_wrap( void *ctx, unsigned char *output ) +{ + sha256_finish( (sha256_context *) ctx, output ); +} + +static void sha256_wrap( const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + sha256( input, ilen, output, 0 ); +} + +static int sha256_file_wrap( const char *path, unsigned char *output ) +{ +#if defined(POLARSSL_FS_IO) + return sha256_file( path, output, 0 ); +#else + ((void) path); + ((void) output); + return( POLARSSL_ERR_MD_FEATURE_UNAVAILABLE ); +#endif +} + +static void sha256_hmac_starts_wrap( void *ctx, const unsigned char *key, + size_t keylen ) +{ + sha256_hmac_starts( (sha256_context *) ctx, key, keylen, 0 ); +} + +static void sha256_hmac_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + sha256_hmac_update( (sha256_context *) ctx, input, ilen ); +} + +static void sha256_hmac_finish_wrap( void *ctx, unsigned char *output ) +{ + sha256_hmac_finish( (sha256_context *) ctx, output ); +} + +static void sha256_hmac_reset_wrap( void *ctx ) +{ + sha256_hmac_reset( (sha256_context *) ctx ); +} + +static void sha256_hmac_wrap( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + sha256_hmac( key, keylen, input, ilen, output, 0 ); +} + +static void * sha256_ctx_alloc( void ) +{ + sha256_context *ctx; + ctx = (sha256_context *) polarssl_malloc( sizeof( sha256_context ) ); + + if( ctx == NULL ) + return( NULL ); + + sha256_init( ctx ); + + return( ctx ); +} + +static void sha256_ctx_free( void *ctx ) +{ + sha256_free( (sha256_context *) ctx ); + polarssl_free( ctx ); +} + +static void sha256_process_wrap( void *ctx, const unsigned char *data ) +{ + sha256_process( (sha256_context *) ctx, data ); +} + +const md_info_t sha256_info = { + POLARSSL_MD_SHA256, + "SHA256", + 32, + sha256_starts_wrap, + sha256_update_wrap, + sha256_finish_wrap, + sha256_wrap, + sha256_file_wrap, + sha256_hmac_starts_wrap, + sha256_hmac_update_wrap, + sha256_hmac_finish_wrap, + sha256_hmac_reset_wrap, + sha256_hmac_wrap, + sha256_ctx_alloc, + sha256_ctx_free, + sha256_process_wrap, +}; + +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA512_C) + +static void sha384_starts_wrap( void *ctx ) +{ + sha512_starts( (sha512_context *) ctx, 1 ); +} + +static void sha384_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + sha512_update( (sha512_context *) ctx, input, ilen ); +} + +static void sha384_finish_wrap( void *ctx, unsigned char *output ) +{ + sha512_finish( (sha512_context *) ctx, output ); +} + +static void sha384_wrap( const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + sha512( input, ilen, output, 1 ); +} + +static int sha384_file_wrap( const char *path, unsigned char *output ) +{ +#if defined(POLARSSL_FS_IO) + return sha512_file( path, output, 1 ); +#else + ((void) path); + ((void) output); + return( POLARSSL_ERR_MD_FEATURE_UNAVAILABLE ); +#endif +} + +static void sha384_hmac_starts_wrap( void *ctx, const unsigned char *key, + size_t keylen ) +{ + sha512_hmac_starts( (sha512_context *) ctx, key, keylen, 1 ); +} + +static void sha384_hmac_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + sha512_hmac_update( (sha512_context *) ctx, input, ilen ); +} + +static void sha384_hmac_finish_wrap( void *ctx, unsigned char *output ) +{ + sha512_hmac_finish( (sha512_context *) ctx, output ); +} + +static void sha384_hmac_reset_wrap( void *ctx ) +{ + sha512_hmac_reset( (sha512_context *) ctx ); +} + +static void sha384_hmac_wrap( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + sha512_hmac( key, keylen, input, ilen, output, 1 ); +} + +static void * sha384_ctx_alloc( void ) +{ + return polarssl_malloc( sizeof( sha512_context ) ); +} + +static void sha384_ctx_free( void *ctx ) +{ + polarssl_zeroize( ctx, sizeof( sha512_context ) ); + polarssl_free( ctx ); +} + +static void sha384_process_wrap( void *ctx, const unsigned char *data ) +{ + sha512_process( (sha512_context *) ctx, data ); +} + +const md_info_t sha384_info = { + POLARSSL_MD_SHA384, + "SHA384", + 48, + sha384_starts_wrap, + sha384_update_wrap, + sha384_finish_wrap, + sha384_wrap, + sha384_file_wrap, + sha384_hmac_starts_wrap, + sha384_hmac_update_wrap, + sha384_hmac_finish_wrap, + sha384_hmac_reset_wrap, + sha384_hmac_wrap, + sha384_ctx_alloc, + sha384_ctx_free, + sha384_process_wrap, +}; + +static void sha512_starts_wrap( void *ctx ) +{ + sha512_starts( (sha512_context *) ctx, 0 ); +} + +static void sha512_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + sha512_update( (sha512_context *) ctx, input, ilen ); +} + +static void sha512_finish_wrap( void *ctx, unsigned char *output ) +{ + sha512_finish( (sha512_context *) ctx, output ); +} + +static void sha512_wrap( const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + sha512( input, ilen, output, 0 ); +} + +static int sha512_file_wrap( const char *path, unsigned char *output ) +{ +#if defined(POLARSSL_FS_IO) + return sha512_file( path, output, 0 ); +#else + ((void) path); + ((void) output); + return( POLARSSL_ERR_MD_FEATURE_UNAVAILABLE ); +#endif +} + +static void sha512_hmac_starts_wrap( void *ctx, const unsigned char *key, + size_t keylen ) +{ + sha512_hmac_starts( (sha512_context *) ctx, key, keylen, 0 ); +} + +static void sha512_hmac_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + sha512_hmac_update( (sha512_context *) ctx, input, ilen ); +} + +static void sha512_hmac_finish_wrap( void *ctx, unsigned char *output ) +{ + sha512_hmac_finish( (sha512_context *) ctx, output ); +} + +static void sha512_hmac_reset_wrap( void *ctx ) +{ + sha512_hmac_reset( (sha512_context *) ctx ); +} + +static void sha512_hmac_wrap( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + sha512_hmac( key, keylen, input, ilen, output, 0 ); +} + +static void * sha512_ctx_alloc( void ) +{ + sha512_context *ctx; + ctx = (sha512_context *) polarssl_malloc( sizeof( sha512_context ) ); + + if( ctx == NULL ) + return( NULL ); + + sha512_init( ctx ); + + return( ctx ); +} + +static void sha512_ctx_free( void *ctx ) +{ + sha512_free( (sha512_context *) ctx ); + polarssl_free( ctx ); +} + +static void sha512_process_wrap( void *ctx, const unsigned char *data ) +{ + sha512_process( (sha512_context *) ctx, data ); +} + +const md_info_t sha512_info = { + POLARSSL_MD_SHA512, + "SHA512", + 64, + sha512_starts_wrap, + sha512_update_wrap, + sha512_finish_wrap, + sha512_wrap, + sha512_file_wrap, + sha512_hmac_starts_wrap, + sha512_hmac_update_wrap, + sha512_hmac_finish_wrap, + sha512_hmac_reset_wrap, + sha512_hmac_wrap, + sha512_ctx_alloc, + sha512_ctx_free, + sha512_process_wrap, +}; + +#endif /* POLARSSL_SHA512_C */ + +#endif /* POLARSSL_MD_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/memory_buffer_alloc.c b/component/common/network/ssl/polarssl-1.3.8/library/memory_buffer_alloc.c new file mode 100644 index 0000000..7710ba5 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/memory_buffer_alloc.c @@ -0,0 +1,589 @@ +/* + * Buffer-based memory allocator + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_MEMORY_BUFFER_ALLOC_C) + +#include "polarssl/memory_buffer_alloc.h" + +#include + +#if defined(POLARSSL_MEMORY_DEBUG) +#include +#if defined(POLARSSL_MEMORY_BACKTRACE) +#include +#endif +#endif + +#if defined(POLARSSL_THREADING_C) +#include "polarssl/threading.h" +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#define polarssl_fprintf fprintf +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +#define MAGIC1 0xFF00AA55 +#define MAGIC2 0xEE119966 +#define MAX_BT 20 + +typedef struct _memory_header memory_header; +struct _memory_header +{ + size_t magic1; + size_t size; + size_t alloc; + memory_header *prev; + memory_header *next; + memory_header *prev_free; + memory_header *next_free; +#if defined(POLARSSL_MEMORY_BACKTRACE) + char **trace; + size_t trace_count; +#endif + size_t magic2; +}; + +typedef struct +{ + unsigned char *buf; + size_t len; + memory_header *first; + memory_header *first_free; + size_t current_alloc_size; + int verify; +#if defined(POLARSSL_MEMORY_DEBUG) + size_t malloc_count; + size_t free_count; + size_t total_used; + size_t maximum_used; + size_t header_count; + size_t maximum_header_count; +#endif +#if defined(POLARSSL_THREADING_C) + threading_mutex_t mutex; +#endif +} +buffer_alloc_ctx; + +static buffer_alloc_ctx heap; + +#if defined(POLARSSL_MEMORY_DEBUG) +static void debug_header( memory_header *hdr ) +{ +#if defined(POLARSSL_MEMORY_BACKTRACE) + size_t i; +#endif + + polarssl_fprintf( stderr, "HDR: PTR(%10u), PREV(%10u), NEXT(%10u), " + "ALLOC(%u), SIZE(%10u)\n", + (size_t) hdr, (size_t) hdr->prev, (size_t) hdr->next, + hdr->alloc, hdr->size ); + polarssl_fprintf( stderr, " FPREV(%10u), FNEXT(%10u)\n", + (size_t) hdr->prev_free, (size_t) hdr->next_free ); + +#if defined(POLARSSL_MEMORY_BACKTRACE) + polarssl_fprintf( stderr, "TRACE: \n" ); + for( i = 0; i < hdr->trace_count; i++ ) + polarssl_fprintf( stderr, "%s\n", hdr->trace[i] ); + polarssl_fprintf( stderr, "\n" ); +#endif +} + +static void debug_chain() +{ + memory_header *cur = heap.first; + + polarssl_fprintf( stderr, "\nBlock list\n" ); + while( cur != NULL ) + { + debug_header( cur ); + cur = cur->next; + } + + polarssl_fprintf( stderr, "Free list\n" ); + cur = heap.first_free; + + while( cur != NULL ) + { + debug_header( cur ); + cur = cur->next_free; + } +} +#endif /* POLARSSL_MEMORY_DEBUG */ + +static int verify_header( memory_header *hdr ) +{ + if( hdr->magic1 != MAGIC1 ) + { +#if defined(POLARSSL_MEMORY_DEBUG) + polarssl_fprintf( stderr, "FATAL: MAGIC1 mismatch\n" ); +#endif + return( 1 ); + } + + if( hdr->magic2 != MAGIC2 ) + { +#if defined(POLARSSL_MEMORY_DEBUG) + polarssl_fprintf( stderr, "FATAL: MAGIC2 mismatch\n" ); +#endif + return( 1 ); + } + + if( hdr->alloc > 1 ) + { +#if defined(POLARSSL_MEMORY_DEBUG) + polarssl_fprintf( stderr, "FATAL: alloc has illegal value\n" ); +#endif + return( 1 ); + } + + if( hdr->prev != NULL && hdr->prev == hdr->next ) + { +#if defined(POLARSSL_MEMORY_DEBUG) + polarssl_fprintf( stderr, "FATAL: prev == next\n" ); +#endif + return( 1 ); + } + + if( hdr->prev_free != NULL && hdr->prev_free == hdr->next_free ) + { +#if defined(POLARSSL_MEMORY_DEBUG) + polarssl_fprintf( stderr, "FATAL: prev_free == next_free\n" ); +#endif + return( 1 ); + } + + return( 0 ); +} + +static int verify_chain() +{ + memory_header *prv = heap.first, *cur = heap.first->next; + + if( verify_header( heap.first ) != 0 ) + { +#if defined(POLARSSL_MEMORY_DEBUG) + polarssl_fprintf( stderr, "FATAL: verification of first header " + "failed\n" ); +#endif + return( 1 ); + } + + if( heap.first->prev != NULL ) + { +#if defined(POLARSSL_MEMORY_DEBUG) + polarssl_fprintf( stderr, "FATAL: verification failed: " + "first->prev != NULL\n" ); +#endif + return( 1 ); + } + + while( cur != NULL ) + { + if( verify_header( cur ) != 0 ) + { +#if defined(POLARSSL_MEMORY_DEBUG) + polarssl_fprintf( stderr, "FATAL: verification of header " + "failed\n" ); +#endif + return( 1 ); + } + + if( cur->prev != prv ) + { +#if defined(POLARSSL_MEMORY_DEBUG) + polarssl_fprintf( stderr, "FATAL: verification failed: " + "cur->prev != prv\n" ); +#endif + return( 1 ); + } + + prv = cur; + cur = cur->next; + } + + return( 0 ); +} + +static void *buffer_alloc_malloc( size_t len ) +{ + memory_header *new, *cur = heap.first_free; + unsigned char *p; +#if defined(POLARSSL_MEMORY_BACKTRACE) + void *trace_buffer[MAX_BT]; + size_t trace_cnt; +#endif + + if( heap.buf == NULL || heap.first == NULL ) + return( NULL ); + + if( len % POLARSSL_MEMORY_ALIGN_MULTIPLE ) + { + len -= len % POLARSSL_MEMORY_ALIGN_MULTIPLE; + len += POLARSSL_MEMORY_ALIGN_MULTIPLE; + } + + // Find block that fits + // + while( cur != NULL ) + { + if( cur->size >= len ) + break; + + cur = cur->next_free; + } + + if( cur == NULL ) + return( NULL ); + + if( cur->alloc != 0 ) + { +#if defined(POLARSSL_MEMORY_DEBUG) + polarssl_fprintf( stderr, "FATAL: block in free_list but allocated " + "data\n" ); +#endif + exit( 1 ); + } + +#if defined(POLARSSL_MEMORY_DEBUG) + heap.malloc_count++; +#endif + + // Found location, split block if > memory_header + 4 room left + // + if( cur->size - len < sizeof(memory_header) + + POLARSSL_MEMORY_ALIGN_MULTIPLE ) + { + cur->alloc = 1; + + // Remove from free_list + // + if( cur->prev_free != NULL ) + cur->prev_free->next_free = cur->next_free; + else + heap.first_free = cur->next_free; + + if( cur->next_free != NULL ) + cur->next_free->prev_free = cur->prev_free; + + cur->prev_free = NULL; + cur->next_free = NULL; + +#if defined(POLARSSL_MEMORY_DEBUG) + heap.total_used += cur->size; + if( heap.total_used > heap.maximum_used ) + heap.maximum_used = heap.total_used; +#endif +#if defined(POLARSSL_MEMORY_BACKTRACE) + trace_cnt = backtrace( trace_buffer, MAX_BT ); + cur->trace = backtrace_symbols( trace_buffer, trace_cnt ); + cur->trace_count = trace_cnt; +#endif + + if( ( heap.verify & MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 ) + exit( 1 ); + + return( ( (unsigned char *) cur ) + sizeof(memory_header) ); + } + + p = ( (unsigned char *) cur ) + sizeof(memory_header) + len; + new = (memory_header *) p; + + new->size = cur->size - len - sizeof(memory_header); + new->alloc = 0; + new->prev = cur; + new->next = cur->next; +#if defined(POLARSSL_MEMORY_BACKTRACE) + new->trace = NULL; + new->trace_count = 0; +#endif + new->magic1 = MAGIC1; + new->magic2 = MAGIC2; + + if( new->next != NULL ) + new->next->prev = new; + + // Replace cur with new in free_list + // + new->prev_free = cur->prev_free; + new->next_free = cur->next_free; + if( new->prev_free != NULL ) + new->prev_free->next_free = new; + else + heap.first_free = new; + + if( new->next_free != NULL ) + new->next_free->prev_free = new; + + cur->alloc = 1; + cur->size = len; + cur->next = new; + cur->prev_free = NULL; + cur->next_free = NULL; + +#if defined(POLARSSL_MEMORY_DEBUG) + heap.header_count++; + if( heap.header_count > heap.maximum_header_count ) + heap.maximum_header_count = heap.header_count; + heap.total_used += cur->size; + if( heap.total_used > heap.maximum_used ) + heap.maximum_used = heap.total_used; +#endif +#if defined(POLARSSL_MEMORY_BACKTRACE) + trace_cnt = backtrace( trace_buffer, MAX_BT ); + cur->trace = backtrace_symbols( trace_buffer, trace_cnt ); + cur->trace_count = trace_cnt; +#endif + + if( ( heap.verify & MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 ) + exit( 1 ); + + return( ( (unsigned char *) cur ) + sizeof(memory_header) ); +} + +static void buffer_alloc_free( void *ptr ) +{ + memory_header *hdr, *old = NULL; + unsigned char *p = (unsigned char *) ptr; + + if( ptr == NULL || heap.buf == NULL || heap.first == NULL ) + return; + + if( p < heap.buf || p > heap.buf + heap.len ) + { +#if defined(POLARSSL_MEMORY_DEBUG) + polarssl_fprintf( stderr, "FATAL: polarssl_free() outside of managed " + "space\n" ); +#endif + exit( 1 ); + } + + p -= sizeof(memory_header); + hdr = (memory_header *) p; + + if( verify_header( hdr ) != 0 ) + exit( 1 ); + + if( hdr->alloc != 1 ) + { +#if defined(POLARSSL_MEMORY_DEBUG) + polarssl_fprintf( stderr, "FATAL: polarssl_free() on unallocated " + "data\n" ); +#endif + exit( 1 ); + } + + hdr->alloc = 0; + +#if defined(POLARSSL_MEMORY_DEBUG) + heap.free_count++; + heap.total_used -= hdr->size; +#endif + + // Regroup with block before + // + if( hdr->prev != NULL && hdr->prev->alloc == 0 ) + { +#if defined(POLARSSL_MEMORY_DEBUG) + heap.header_count--; +#endif + hdr->prev->size += sizeof(memory_header) + hdr->size; + hdr->prev->next = hdr->next; + old = hdr; + hdr = hdr->prev; + + if( hdr->next != NULL ) + hdr->next->prev = hdr; + +#if defined(POLARSSL_MEMORY_BACKTRACE) + free( old->trace ); +#endif + memset( old, 0, sizeof(memory_header) ); + } + + // Regroup with block after + // + if( hdr->next != NULL && hdr->next->alloc == 0 ) + { +#if defined(POLARSSL_MEMORY_DEBUG) + heap.header_count--; +#endif + hdr->size += sizeof(memory_header) + hdr->next->size; + old = hdr->next; + hdr->next = hdr->next->next; + + if( hdr->prev_free != NULL || hdr->next_free != NULL ) + { + if( hdr->prev_free != NULL ) + hdr->prev_free->next_free = hdr->next_free; + else + heap.first_free = hdr->next_free; + + if( hdr->next_free != NULL ) + hdr->next_free->prev_free = hdr->prev_free; + } + + hdr->prev_free = old->prev_free; + hdr->next_free = old->next_free; + + if( hdr->prev_free != NULL ) + hdr->prev_free->next_free = hdr; + else + heap.first_free = hdr; + + if( hdr->next_free != NULL ) + hdr->next_free->prev_free = hdr; + + if( hdr->next != NULL ) + hdr->next->prev = hdr; + +#if defined(POLARSSL_MEMORY_BACKTRACE) + free( old->trace ); +#endif + memset( old, 0, sizeof(memory_header) ); + } + + // Prepend to free_list if we have not merged + // (Does not have to stay in same order as prev / next list) + // + if( old == NULL ) + { + hdr->next_free = heap.first_free; + heap.first_free->prev_free = hdr; + heap.first_free = hdr; + } + +#if defined(POLARSSL_MEMORY_BACKTRACE) + hdr->trace = NULL; + hdr->trace_count = 0; +#endif + + if( ( heap.verify & MEMORY_VERIFY_FREE ) && verify_chain() != 0 ) + exit( 1 ); +} + +void memory_buffer_set_verify( int verify ) +{ + heap.verify = verify; +} + +int memory_buffer_alloc_verify() +{ + return verify_chain(); +} + +#if defined(POLARSSL_MEMORY_DEBUG) +void memory_buffer_alloc_status() +{ + polarssl_fprintf( stderr, + "Current use: %u blocks / %u bytes, max: %u blocks / " + "%u bytes (total %u bytes), malloc / free: %u / %u\n", + heap.header_count, heap.total_used, + heap.maximum_header_count, heap.maximum_used, + heap.maximum_header_count * sizeof( memory_header ) + + heap.maximum_used, + heap.malloc_count, heap.free_count ); + + if( heap.first->next == NULL ) + polarssl_fprintf( stderr, "All memory de-allocated in stack buffer\n" ); + else + { + polarssl_fprintf( stderr, "Memory currently allocated:\n" ); + debug_chain(); + } +} +#endif /* POLARSSL_MEMORY_DEBUG */ + +#if defined(POLARSSL_THREADING_C) +static void *buffer_alloc_malloc_mutexed( size_t len ) +{ + void *buf; + polarssl_mutex_lock( &heap.mutex ); + buf = buffer_alloc_malloc( len ); + polarssl_mutex_unlock( &heap.mutex ); + return( buf ); +} + +static void buffer_alloc_free_mutexed( void *ptr ) +{ + polarssl_mutex_lock( &heap.mutex ); + buffer_alloc_free( ptr ); + polarssl_mutex_unlock( &heap.mutex ); +} +#endif /* POLARSSL_THREADING_C */ + +int memory_buffer_alloc_init( unsigned char *buf, size_t len ) +{ + memset( &heap, 0, sizeof(buffer_alloc_ctx) ); + memset( buf, 0, len ); + +#if defined(POLARSSL_THREADING_C) + polarssl_mutex_init( &heap.mutex ); + platform_set_malloc_free( buffer_alloc_malloc_mutexed, + buffer_alloc_free_mutexed ); +#else + platform_set_malloc_free( buffer_alloc_malloc, buffer_alloc_free ); +#endif + + if( (size_t) buf % POLARSSL_MEMORY_ALIGN_MULTIPLE ) + { + buf += POLARSSL_MEMORY_ALIGN_MULTIPLE + - (size_t) buf % POLARSSL_MEMORY_ALIGN_MULTIPLE; + len -= (size_t) buf % POLARSSL_MEMORY_ALIGN_MULTIPLE; + } + + heap.buf = buf; + heap.len = len; + + heap.first = (memory_header *) buf; + heap.first->size = len - sizeof(memory_header); + heap.first->magic1 = MAGIC1; + heap.first->magic2 = MAGIC2; + heap.first_free = heap.first; + return( 0 ); +} + +void memory_buffer_alloc_free() +{ +#if defined(POLARSSL_THREADING_C) + polarssl_mutex_free( &heap.mutex ); +#endif + polarssl_zeroize( &heap, sizeof(buffer_alloc_ctx) ); +} + +#endif /* POLARSSL_MEMORY_BUFFER_ALLOC_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/net.c b/component/common/network/ssl/polarssl-1.3.8/library/net.c new file mode 100644 index 0000000..9971758 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/net.c @@ -0,0 +1,599 @@ +/* + * TCP networking functions + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_NET_C) + +#include "polarssl/net.h" + +#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \ + !defined(EFI32) + +#if defined(POLARSSL_HAVE_IPV6) +#ifdef _WIN32_WINNT +#undef _WIN32_WINNT +#endif +/* Enables getaddrinfo() & Co */ +#define _WIN32_WINNT 0x0501 +#include +#endif + +#include +#include + +#if defined(_MSC_VER) +#if defined(_WIN32_WCE) +#pragma comment( lib, "ws2.lib" ) +#else +#pragma comment( lib, "ws2_32.lib" ) +#endif +#endif /* _MSC_VER */ + +#define read(fd,buf,len) recv(fd,(char*)buf,(int) len,0) +#define write(fd,buf,len) send(fd,(char*)buf,(int) len,0) +#define close(fd) closesocket(fd) + +static int wsa_init_done = 0; + +#elif defined(__ICCARM__) || defined(__CC_ARM) + +#include "lwip/sockets.h" +#include "lwip/inet.h" +#if LWIP_DNS +#include "lwip/netdb.h" +#endif +#include + +#else /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ + +#include +#include +#include +#include +#if defined(POLARSSL_HAVE_TIME) +#include +#endif +#include +#include +#include +#include +#include + +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || \ + defined(__DragonFly__) +#include +#elif defined(__APPLE__) || defined(HAVE_MACHINE_ENDIAN_H) || \ + defined(EFIX64) || defined(EFI32) +#include +#elif defined(sun) +#include +#elif defined(_AIX) || defined(HAVE_ARPA_NAMESER_COMPAT_H) +#include +#else +#include +#endif + +#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ + +#include +#include + +#if defined(_MSC_VER) && !defined snprintf && !defined(EFIX64) && \ + !defined(EFI32) +#define snprintf _snprintf +#endif + +#if defined(POLARSSL_HAVE_TIME) +#include +#endif + +#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32) +#include +typedef UINT32 uint32_t; +#else +#include +#endif + +/* + * htons() is not always available. + * By default go for LITTLE_ENDIAN variant. Otherwise hope for _BYTE_ORDER and + * __BIG_ENDIAN to help determine endianness. + */ +#if defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \ + __BYTE_ORDER == __BIG_ENDIAN +#define POLARSSL_HTONS(n) (n) +#define POLARSSL_HTONL(n) (n) +#else +#define POLARSSL_HTONS(n) ((((unsigned short)(n) & 0xFF ) << 8 ) | \ + (((unsigned short)(n) & 0xFF00 ) >> 8 )) +#define POLARSSL_HTONL(n) ((((unsigned long )(n) & 0xFF ) << 24) | \ + (((unsigned long )(n) & 0xFF00 ) << 8 ) | \ + (((unsigned long )(n) & 0xFF0000 ) >> 8 ) | \ + (((unsigned long )(n) & 0xFF000000) >> 24)) +#endif + +unsigned short net_htons( unsigned short n ); +unsigned long net_htonl( unsigned long n ); +#define net_htons(n) POLARSSL_HTONS(n) +#define net_htonl(n) POLARSSL_HTONL(n) + +/* + * Prepare for using the sockets interface + */ +static int net_prepare( void ) +{ +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + WSADATA wsaData; + + if( wsa_init_done == 0 ) + { + if( WSAStartup( MAKEWORD(2,0), &wsaData ) != 0 ) + return( POLARSSL_ERR_NET_SOCKET_FAILED ); + + wsa_init_done = 1; + } +#else +#if !defined(EFIX64) && !defined(EFI32) && !defined(__ICCARM__) && !defined(__CC_ARM) + signal( SIGPIPE, SIG_IGN ); +#endif +#endif + return( 0 ); +} + +/* + * Initiate a TCP connection with host:port + */ +int net_connect( int *fd, const char *host, int port ) +{ +#if defined(POLARSSL_HAVE_IPV6) + int ret; + struct addrinfo hints, *addr_list, *cur; + char port_str[6]; + + if( ( ret = net_prepare() ) != 0 ) + return( ret ); + + /* getaddrinfo expects port as a string */ + memset( port_str, 0, sizeof( port_str ) ); + snprintf( port_str, sizeof( port_str ), "%d", port ); + + /* Do name resolution with both IPv6 and IPv4, but only TCP */ + memset( &hints, 0, sizeof( hints ) ); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + if( getaddrinfo( host, port_str, &hints, &addr_list ) != 0 ) + return( POLARSSL_ERR_NET_UNKNOWN_HOST ); + + /* Try the sockaddrs until a connection succeeds */ + ret = POLARSSL_ERR_NET_UNKNOWN_HOST; + for( cur = addr_list; cur != NULL; cur = cur->ai_next ) + { + *fd = (int) socket( cur->ai_family, cur->ai_socktype, + cur->ai_protocol ); + if( *fd < 0 ) + { + ret = POLARSSL_ERR_NET_SOCKET_FAILED; + continue; + } + + if( connect( *fd, cur->ai_addr, cur->ai_addrlen ) == 0 ) + { + ret = 0; + break; + } + + close( *fd ); + ret = POLARSSL_ERR_NET_CONNECT_FAILED; + } + + freeaddrinfo( addr_list ); + + return( ret ); + +#else + /* Legacy IPv4-only version */ + + int ret; + struct sockaddr_in server_addr; +#if LWIP_DNS + struct hostent *server_host; +#endif + if( ( ret = net_prepare() ) != 0 ) + return( ret ); +#if LWIP_DNS + if( ( server_host = gethostbyname( host ) ) == NULL ) + return( POLARSSL_ERR_NET_UNKNOWN_HOST ); + + if( ( *fd = (int) socket( AF_INET, SOCK_STREAM, IPPROTO_IP ) ) < 0 ) + return( POLARSSL_ERR_NET_SOCKET_FAILED ); + + memcpy( (void *) &server_addr.sin_addr, + (void *) server_host->h_addr, + server_host->h_length ); +#else + if( ( *fd = (int) socket( AF_INET, SOCK_STREAM, IPPROTO_IP ) ) < 0 ) + return( POLARSSL_ERR_NET_SOCKET_FAILED ); + + server_addr.sin_len = sizeof(server_addr); + server_addr.sin_addr.s_addr = inet_addr(host); +#endif + + server_addr.sin_family = AF_INET; + server_addr.sin_port = net_htons( port ); + + if( connect( *fd, (struct sockaddr *) &server_addr, + sizeof( server_addr ) ) < 0 ) + { + close( *fd ); + return( POLARSSL_ERR_NET_CONNECT_FAILED ); + } + + return( 0 ); +#endif /* POLARSSL_HAVE_IPV6 */ +} + +/* + * Create a listening socket on bind_ip:port + */ +int net_bind( int *fd, const char *bind_ip, int port ) +{ +#if defined(POLARSSL_HAVE_IPV6) + int n, ret; + struct addrinfo hints, *addr_list, *cur; + char port_str[6]; + + if( ( ret = net_prepare() ) != 0 ) + return( ret ); + + /* getaddrinfo expects port as a string */ + memset( port_str, 0, sizeof( port_str ) ); + snprintf( port_str, sizeof( port_str ), "%d", port ); + + /* Bind to IPv6 and/or IPv4, but only in TCP */ + memset( &hints, 0, sizeof( hints ) ); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + if( bind_ip == NULL ) + hints.ai_flags = AI_PASSIVE; + + if( getaddrinfo( bind_ip, port_str, &hints, &addr_list ) != 0 ) + return( POLARSSL_ERR_NET_UNKNOWN_HOST ); + + /* Try the sockaddrs until a binding succeeds */ + ret = POLARSSL_ERR_NET_UNKNOWN_HOST; + for( cur = addr_list; cur != NULL; cur = cur->ai_next ) + { + *fd = (int) socket( cur->ai_family, cur->ai_socktype, + cur->ai_protocol ); + if( *fd < 0 ) + { + ret = POLARSSL_ERR_NET_SOCKET_FAILED; + continue; + } + + n = 1; + if( setsockopt( *fd, SOL_SOCKET, SO_REUSEADDR, + (const char *) &n, sizeof( n ) ) != 0 ) + { + close( *fd ); + ret = POLARSSL_ERR_NET_SOCKET_FAILED; + continue; + } + + if( bind( *fd, cur->ai_addr, cur->ai_addrlen ) != 0 ) + { + close( *fd ); + ret = POLARSSL_ERR_NET_BIND_FAILED; + continue; + } + + if( listen( *fd, POLARSSL_NET_LISTEN_BACKLOG ) != 0 ) + { + close( *fd ); + ret = POLARSSL_ERR_NET_LISTEN_FAILED; + continue; + } + + /* I we ever get there, it's a success */ + ret = 0; + break; + } + + freeaddrinfo( addr_list ); + + return( ret ); + +#else + /* Legacy IPv4-only version */ + + int ret, n, c[4]; + struct sockaddr_in server_addr; + + if( ( ret = net_prepare() ) != 0 ) + return( ret ); + + if( ( *fd = (int) socket( AF_INET, SOCK_STREAM, IPPROTO_IP ) ) < 0 ) + return( POLARSSL_ERR_NET_SOCKET_FAILED ); + + n = 1; + setsockopt( *fd, SOL_SOCKET, SO_REUSEADDR, + (const char *) &n, sizeof( n ) ); + + server_addr.sin_addr.s_addr = net_htonl( INADDR_ANY ); + server_addr.sin_family = AF_INET; + server_addr.sin_port = net_htons( port ); + + if( bind_ip != NULL ) + { + memset( c, 0, sizeof( c ) ); + sscanf( bind_ip, "%d.%d.%d.%d", &c[0], &c[1], &c[2], &c[3] ); + + for( n = 0; n < 4; n++ ) + if( c[n] < 0 || c[n] > 255 ) + break; + + if( n == 4 ) + server_addr.sin_addr.s_addr = net_htonl( + ( (uint32_t) c[0] << 24 ) | + ( (uint32_t) c[1] << 16 ) | + ( (uint32_t) c[2] << 8 ) | + ( (uint32_t) c[3] ) ); + } + + if( bind( *fd, (struct sockaddr *) &server_addr, + sizeof( server_addr ) ) < 0 ) + { + close( *fd ); + return( POLARSSL_ERR_NET_BIND_FAILED ); + } + + if( listen( *fd, POLARSSL_NET_LISTEN_BACKLOG ) != 0 ) + { + close( *fd ); + return( POLARSSL_ERR_NET_LISTEN_FAILED ); + } + + return( 0 ); +#endif /* POLARSSL_HAVE_IPV6 */ +} + +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) +/* + * Check if the requested operation would be blocking on a non-blocking socket + * and thus 'failed' with a negative return value. + */ +static int net_would_block( int fd ) +{ + ((void) fd); + return( WSAGetLastError() == WSAEWOULDBLOCK ); +} +#else +/* + * Check if the requested operation would be blocking on a non-blocking socket + * and thus 'failed' with a negative return value. + * + * Note: on a blocking socket this function always returns 0! + */ +static int net_would_block( int fd ) +{ +#if 0 + /* + * Never return 'WOULD BLOCK' on a non-blocking socket + */ + if( ( fcntl( fd, F_GETFL ) & O_NONBLOCK ) != O_NONBLOCK ) + return( 0 ); + + switch( errno ) + { +#if defined EAGAIN + case EAGAIN: +#endif +#if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN + case EWOULDBLOCK: +#endif + return( 1 ); + } +#endif + return( 0 ); +} +#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ + +/* + * Accept a connection from a remote client + */ +int net_accept( int bind_fd, int *client_fd, void *client_ip ) +{ +#if defined(POLARSSL_HAVE_IPV6) + struct sockaddr_storage client_addr; +#else + struct sockaddr_in client_addr; +#endif + +#if defined(__socklen_t_defined) || defined(_SOCKLEN_T) || \ + defined(_SOCKLEN_T_DECLARED) + socklen_t n = (socklen_t) sizeof( client_addr ); +#else + int n = (int) sizeof( client_addr ); +#endif + + *client_fd = (int) accept( bind_fd, (struct sockaddr *) + &client_addr, &n ); + + if( *client_fd < 0 ) + { + if( net_would_block( *client_fd ) != 0 ) + return( POLARSSL_ERR_NET_WANT_READ ); + + return( POLARSSL_ERR_NET_ACCEPT_FAILED ); + } + + if( client_ip != NULL ) + { +#if defined(POLARSSL_HAVE_IPV6) + if( client_addr.ss_family == AF_INET ) + { + struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr; + memcpy( client_ip, &addr4->sin_addr.s_addr, + sizeof( addr4->sin_addr.s_addr ) ); + } + else + { + struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr; + memcpy( client_ip, &addr6->sin6_addr.s6_addr, + sizeof( addr6->sin6_addr.s6_addr ) ); + } +#else + memcpy( client_ip, &client_addr.sin_addr.s_addr, + sizeof( client_addr.sin_addr.s_addr ) ); +#endif /* POLARSSL_HAVE_IPV6 */ + } + + return( 0 ); +} + +/* + * Set the socket blocking or non-blocking + */ +int net_set_block( int fd ) +{ +#if ( defined(_WIN32) || defined(_WIN32_WCE) || defined(__ICCARM__) || defined(__CC_ARM)) && !defined(EFIX64) && \ + !defined(EFI32) + unsigned long n = 0; + return( ioctlsocket( fd, FIONBIO, &n ) ); +#else + return( fcntl( fd, F_SETFL, fcntl( fd, F_GETFL ) & ~O_NONBLOCK ) ); +#endif +} + +int net_set_nonblock( int fd ) +{ +#if ( defined(_WIN32) || defined(_WIN32_WCE) || defined(__ICCARM__) || defined(__CC_ARM)) && !defined(EFIX64) && \ + !defined(EFI32) + unsigned long n = 1; + return( ioctlsocket( fd, FIONBIO, &n ) ); +#else + return( fcntl( fd, F_SETFL, fcntl( fd, F_GETFL ) | O_NONBLOCK ) ); +#endif +} + +#if defined(POLARSSL_HAVE_TIME) +/* + * Portable usleep helper + */ +void net_usleep( unsigned long usec ) +{ + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = usec; + select( 0, NULL, NULL, NULL, &tv ); +} +#endif /* POLARSSL_HAVE_TIME */ + +/* + * Read at most 'len' characters + */ +int net_recv( void *ctx, unsigned char *buf, size_t len ) +{ + int fd = *((int *) ctx); + int ret = read( fd, buf, len ); + + if( ret < 0 ) + { + if( net_would_block( fd ) != 0 ) + return( POLARSSL_ERR_NET_WANT_READ ); + +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + if( WSAGetLastError() == WSAECONNRESET ) + return( POLARSSL_ERR_NET_CONN_RESET ); +#else +#ifdef ERRNO + if( errno == EPIPE || errno == ECONNRESET ) + return( POLARSSL_ERR_NET_CONN_RESET ); + + if( errno == EINTR ) + return( POLARSSL_ERR_NET_WANT_READ ); +#endif +#endif + + return( POLARSSL_ERR_NET_RECV_FAILED ); + } + + return( ret ); +} + +/* + * Write at most 'len' characters + */ +int net_send( void *ctx, const unsigned char *buf, size_t len ) +{ + int fd = *((int *) ctx); + int ret = write( fd, buf, len ); + + if( ret < 0 ) + { + if( net_would_block( fd ) != 0 ) + return( POLARSSL_ERR_NET_WANT_WRITE ); + +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + if( WSAGetLastError() == WSAECONNRESET ) + return( POLARSSL_ERR_NET_CONN_RESET ); +#else +#ifdef ERRNO + if( errno == EPIPE || errno == ECONNRESET ) + return( POLARSSL_ERR_NET_CONN_RESET ); + + if( errno == EINTR ) + return( POLARSSL_ERR_NET_WANT_WRITE ); +#endif +#endif + + return( POLARSSL_ERR_NET_SEND_FAILED ); + } + + return( ret ); +} + +/* + * Gracefully close the connection + */ +void net_close( int fd ) +{ + shutdown( fd, 2 ); + close( fd ); +} + +#endif /* POLARSSL_NET_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/oid.c b/component/common/network/ssl/polarssl-1.3.8/library/oid.c new file mode 100644 index 0000000..f0afafe --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/oid.c @@ -0,0 +1,684 @@ +/** + * \file oid.c + * + * \brief Object Identifier (OID) database + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_OID_C) + +#include "polarssl/oid.h" +#include "polarssl/rsa.h" + +#if defined(POLARSSL_X509_USE_C) || defined(POLARSSL_X509_CREATE_C) +#include "polarssl/x509.h" +#endif + +#include + +/* + * Macro to automatically add the size of #define'd OIDs + */ +#define ADD_LEN(s) s, OID_SIZE(s) + +/* + * Macro to generate an internal function for oid_XXX_from_asn1() (used by + * the other functions) + */ +#define FN_OID_TYPED_FROM_ASN1( TYPE_T, NAME, LIST ) \ +static const TYPE_T * oid_ ## NAME ## _from_asn1( const asn1_buf *oid ) \ +{ \ + const TYPE_T *p = LIST; \ + const oid_descriptor_t *cur = (const oid_descriptor_t *) p; \ + if( p == NULL || oid == NULL ) return( NULL ); \ + while( cur->asn1 != NULL ) { \ + if( cur->asn1_len == oid->len && \ + memcmp( cur->asn1, oid->p, oid->len ) == 0 ) { \ + return( p ); \ + } \ + p++; \ + cur = (const oid_descriptor_t *) p; \ + } \ + return( NULL ); \ +} + +/* + * Macro to generate a function for retrieving a single attribute from the + * descriptor of an oid_descriptor_t wrapper. + */ +#define FN_OID_GET_DESCRIPTOR_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ +int FN_NAME( const asn1_buf *oid, ATTR1_TYPE * ATTR1 ) \ +{ \ + const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ + if( data == NULL ) return( POLARSSL_ERR_OID_NOT_FOUND ); \ + *ATTR1 = data->descriptor.ATTR1; \ + return( 0 ); \ +} + +/* + * Macro to generate a function for retrieving a single attribute from an + * oid_descriptor_t wrapper. + */ +#define FN_OID_GET_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ +int FN_NAME( const asn1_buf *oid, ATTR1_TYPE * ATTR1 ) \ +{ \ + const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ + if( data == NULL ) return( POLARSSL_ERR_OID_NOT_FOUND ); \ + *ATTR1 = data->ATTR1; \ + return( 0 ); \ +} + +/* + * Macro to generate a function for retrieving two attributes from an + * oid_descriptor_t wrapper. + */ +#define FN_OID_GET_ATTR2(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1, \ + ATTR2_TYPE, ATTR2) \ +int FN_NAME( const asn1_buf *oid, ATTR1_TYPE * ATTR1, ATTR2_TYPE * ATTR2 ) \ +{ \ + const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ + if( data == NULL ) return( POLARSSL_ERR_OID_NOT_FOUND ); \ + *ATTR1 = data->ATTR1; \ + *ATTR2 = data->ATTR2; \ + return( 0 ); \ +} + +/* + * Macro to generate a function for retrieving the OID based on a single + * attribute from a oid_descriptor_t wrapper. + */ +#define FN_OID_GET_OID_BY_ATTR1(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1) \ +int FN_NAME( ATTR1_TYPE ATTR1, const char **oid, size_t *olen ) \ +{ \ + const TYPE_T *cur = LIST; \ + while( cur->descriptor.asn1 != NULL ) { \ + if( cur->ATTR1 == ATTR1 ) { \ + *oid = cur->descriptor.asn1; \ + *olen = cur->descriptor.asn1_len; \ + return( 0 ); \ + } \ + cur++; \ + } \ + return( POLARSSL_ERR_OID_NOT_FOUND ); \ +} + +/* + * Macro to generate a function for retrieving the OID based on two + * attributes from a oid_descriptor_t wrapper. + */ +#define FN_OID_GET_OID_BY_ATTR2(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1, \ + ATTR2_TYPE, ATTR2) \ +int FN_NAME( ATTR1_TYPE ATTR1, ATTR2_TYPE ATTR2, const char **oid , \ + size_t *olen ) \ +{ \ + const TYPE_T *cur = LIST; \ + while( cur->descriptor.asn1 != NULL ) { \ + if( cur->ATTR1 == ATTR1 && cur->ATTR2 == ATTR2 ) { \ + *oid = cur->descriptor.asn1; \ + *olen = cur->descriptor.asn1_len; \ + return( 0 ); \ + } \ + cur++; \ + } \ + return( POLARSSL_ERR_OID_NOT_FOUND ); \ +} + +/* + * For X520 attribute types + */ +typedef struct { + oid_descriptor_t descriptor; + const char *short_name; +} oid_x520_attr_t; + +static const oid_x520_attr_t oid_x520_attr_type[] = +{ + { + { ADD_LEN( OID_AT_CN ), "id-at-commonName", "Common Name" }, + "CN", + }, + { + { ADD_LEN( OID_AT_COUNTRY ), "id-at-countryName", "Country" }, + "C", + }, + { + { ADD_LEN( OID_AT_LOCALITY ), "id-at-locality", "Locality" }, + "L", + }, + { + { ADD_LEN( OID_AT_STATE ), "id-at-state", "State" }, + "ST", + }, + { + { ADD_LEN( OID_AT_ORGANIZATION ),"id-at-organizationName", "Organization" }, + "O", + }, + { + { ADD_LEN( OID_AT_ORG_UNIT ), "id-at-organizationalUnitName", "Org Unit" }, + "OU", + }, + { + { ADD_LEN( OID_PKCS9_EMAIL ), "emailAddress", "E-mail address" }, + "emailAddress", + }, + { + { ADD_LEN( OID_AT_SERIAL_NUMBER ),"id-at-serialNumber", "Serial number" }, + "serialNumber", + }, + { + { ADD_LEN( OID_AT_POSTAL_ADDRESS ),"id-at-postalAddress", "Postal address" }, + "postalAddress", + }, + { + { ADD_LEN( OID_AT_POSTAL_CODE ), "id-at-postalCode", "Postal code" }, + "postalCode", + }, + { + { ADD_LEN( OID_AT_SUR_NAME ), "id-at-surName", "Surname" }, + "SN", + }, + { + { ADD_LEN( OID_AT_GIVEN_NAME ), "id-at-givenName", "Given name" }, + "GN", + }, + { + { ADD_LEN( OID_AT_INITIALS ), "id-at-initials", "Initials" }, + "initials", + }, + { + { ADD_LEN( OID_AT_GENERATION_QUALIFIER ), "id-at-generationQualifier", "Generation qualifier" }, + "generationQualifier", + }, + { + { ADD_LEN( OID_AT_TITLE ), "id-at-title", "Title" }, + "title", + }, + { + { ADD_LEN( OID_AT_DN_QUALIFIER ),"id-at-dnQualifier", "Distinguished Name qualifier" }, + "dnQualifier", + }, + { + { ADD_LEN( OID_AT_PSEUDONYM ), "id-at-pseudonym", "Pseudonym" }, + "pseudonym", + }, + { + { ADD_LEN( OID_DOMAIN_COMPONENT ), "id-domainComponent", "Domain component" }, + "DC", + }, + { + { NULL, 0, NULL, NULL }, + NULL, + } +}; + +FN_OID_TYPED_FROM_ASN1(oid_x520_attr_t, x520_attr, oid_x520_attr_type); +FN_OID_GET_ATTR1(oid_get_attr_short_name, oid_x520_attr_t, x520_attr, const char *, short_name); + +#if defined(POLARSSL_X509_USE_C) || defined(POLARSSL_X509_CREATE_C) +/* + * For X509 extensions + */ +typedef struct { + oid_descriptor_t descriptor; + int ext_type; +} oid_x509_ext_t; + +static const oid_x509_ext_t oid_x509_ext[] = +{ + { + { ADD_LEN( OID_BASIC_CONSTRAINTS ), "id-ce-basicConstraints", "Basic Constraints" }, + EXT_BASIC_CONSTRAINTS, + }, + { + { ADD_LEN( OID_KEY_USAGE ), "id-ce-keyUsage", "Key Usage" }, + EXT_KEY_USAGE, + }, + { + { ADD_LEN( OID_EXTENDED_KEY_USAGE ), "id-ce-keyUsage", "Extended Key Usage" }, + EXT_EXTENDED_KEY_USAGE, + }, + { + { ADD_LEN( OID_SUBJECT_ALT_NAME ), "id-ce-subjectAltName", "Subject Alt Name" }, + EXT_SUBJECT_ALT_NAME, + }, + { + { ADD_LEN( OID_NS_CERT_TYPE ), "id-netscape-certtype", "Netscape Certificate Type" }, + EXT_NS_CERT_TYPE, + }, + { + { NULL, 0, NULL, NULL }, + 0, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_x509_ext_t, x509_ext, oid_x509_ext); +FN_OID_GET_ATTR1(oid_get_x509_ext_type, oid_x509_ext_t, x509_ext, int, ext_type); + +static const oid_descriptor_t oid_ext_key_usage[] = +{ + { ADD_LEN( OID_SERVER_AUTH ), "id-kp-serverAuth", "TLS Web Server Authentication" }, + { ADD_LEN( OID_CLIENT_AUTH ), "id-kp-clientAuth", "TLS Web Client Authentication" }, + { ADD_LEN( OID_CODE_SIGNING ), "id-kp-codeSigning", "Code Signing" }, + { ADD_LEN( OID_EMAIL_PROTECTION ), "id-kp-emailProtection", "E-mail Protection" }, + { ADD_LEN( OID_TIME_STAMPING ), "id-kp-timeStamping", "Time Stamping" }, + { ADD_LEN( OID_OCSP_SIGNING ), "id-kp-OCSPSigning", "OCSP Signing" }, + { NULL, 0, NULL, NULL }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_descriptor_t, ext_key_usage, oid_ext_key_usage); +FN_OID_GET_ATTR1(oid_get_extended_key_usage, oid_descriptor_t, ext_key_usage, const char *, description); +#endif /* POLARSSL_X509_USE_C || POLARSSL_X509_CREATE_C */ + +#if defined(POLARSSL_MD_C) +/* + * For SignatureAlgorithmIdentifier + */ +typedef struct { + oid_descriptor_t descriptor; + md_type_t md_alg; + pk_type_t pk_alg; +} oid_sig_alg_t; + +static const oid_sig_alg_t oid_sig_alg[] = +{ + { + { ADD_LEN( OID_PKCS1_MD2 ), "md2WithRSAEncryption", "RSA with MD2" }, + POLARSSL_MD_MD2, POLARSSL_PK_RSA, + }, + { + { ADD_LEN( OID_PKCS1_MD4 ), "md4WithRSAEncryption", "RSA with MD4" }, + POLARSSL_MD_MD4, POLARSSL_PK_RSA, + }, + { + { ADD_LEN( OID_PKCS1_MD5 ), "md5WithRSAEncryption", "RSA with MD5" }, + POLARSSL_MD_MD5, POLARSSL_PK_RSA, + }, + { + { ADD_LEN( OID_PKCS1_SHA1 ), "sha-1WithRSAEncryption", "RSA with SHA1" }, + POLARSSL_MD_SHA1, POLARSSL_PK_RSA, + }, + { + { ADD_LEN( OID_PKCS1_SHA224 ), "sha224WithRSAEncryption", "RSA with SHA-224" }, + POLARSSL_MD_SHA224, POLARSSL_PK_RSA, + }, + { + { ADD_LEN( OID_PKCS1_SHA256 ), "sha256WithRSAEncryption", "RSA with SHA-256" }, + POLARSSL_MD_SHA256, POLARSSL_PK_RSA, + }, + { + { ADD_LEN( OID_PKCS1_SHA384 ), "sha384WithRSAEncryption", "RSA with SHA-384" }, + POLARSSL_MD_SHA384, POLARSSL_PK_RSA, + }, + { + { ADD_LEN( OID_PKCS1_SHA512 ), "sha512WithRSAEncryption", "RSA with SHA-512" }, + POLARSSL_MD_SHA512, POLARSSL_PK_RSA, + }, + { + { ADD_LEN( OID_RSA_SHA_OBS ), "sha-1WithRSAEncryption", "RSA with SHA1" }, + POLARSSL_MD_SHA1, POLARSSL_PK_RSA, + }, + { + { ADD_LEN( OID_ECDSA_SHA1 ), "ecdsa-with-SHA1", "ECDSA with SHA1" }, + POLARSSL_MD_SHA1, POLARSSL_PK_ECDSA, + }, + { + { ADD_LEN( OID_ECDSA_SHA224 ), "ecdsa-with-SHA224", "ECDSA with SHA224" }, + POLARSSL_MD_SHA224, POLARSSL_PK_ECDSA, + }, + { + { ADD_LEN( OID_ECDSA_SHA256 ), "ecdsa-with-SHA256", "ECDSA with SHA256" }, + POLARSSL_MD_SHA256, POLARSSL_PK_ECDSA, + }, + { + { ADD_LEN( OID_ECDSA_SHA384 ), "ecdsa-with-SHA384", "ECDSA with SHA384" }, + POLARSSL_MD_SHA384, POLARSSL_PK_ECDSA, + }, + { + { ADD_LEN( OID_ECDSA_SHA512 ), "ecdsa-with-SHA512", "ECDSA with SHA512" }, + POLARSSL_MD_SHA512, POLARSSL_PK_ECDSA, + }, + { + { ADD_LEN( OID_RSASSA_PSS ), "RSASSA-PSS", "RSASSA-PSS" }, + POLARSSL_MD_NONE, POLARSSL_PK_RSASSA_PSS, + }, + { + { NULL, 0, NULL, NULL }, + (md_type_t)0, (pk_type_t)0, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_sig_alg_t, sig_alg, oid_sig_alg); +FN_OID_GET_DESCRIPTOR_ATTR1(oid_get_sig_alg_desc, oid_sig_alg_t, sig_alg, const char *, description); +FN_OID_GET_ATTR2(oid_get_sig_alg, oid_sig_alg_t, sig_alg, md_type_t, md_alg, pk_type_t, pk_alg); +FN_OID_GET_OID_BY_ATTR2(oid_get_oid_by_sig_alg, oid_sig_alg_t, oid_sig_alg, pk_type_t, pk_alg, md_type_t, md_alg); +#endif /* POLARSSL_MD_C */ + +/* + * For PublicKeyInfo (PKCS1, RFC 5480) + */ +typedef struct { + oid_descriptor_t descriptor; + pk_type_t pk_alg; +} oid_pk_alg_t; + +static const oid_pk_alg_t oid_pk_alg[] = +{ + { + { ADD_LEN( OID_PKCS1_RSA ), "rsaEncryption", "RSA" }, + POLARSSL_PK_RSA, + }, + { + { ADD_LEN( OID_EC_ALG_UNRESTRICTED ), "id-ecPublicKey", "Generic EC key" }, + POLARSSL_PK_ECKEY, + }, + { + { ADD_LEN( OID_EC_ALG_ECDH ), "id-ecDH", "EC key for ECDH" }, + POLARSSL_PK_ECKEY_DH, + }, + { + { NULL, 0, NULL, NULL }, + (pk_type_t)0, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_pk_alg_t, pk_alg, oid_pk_alg); +FN_OID_GET_ATTR1(oid_get_pk_alg, oid_pk_alg_t, pk_alg, pk_type_t, pk_alg); +FN_OID_GET_OID_BY_ATTR1(oid_get_oid_by_pk_alg, oid_pk_alg_t, oid_pk_alg, pk_type_t, pk_alg); + +#if defined(POLARSSL_ECP_C) +/* + * For namedCurve (RFC 5480) + */ +typedef struct { + oid_descriptor_t descriptor; + ecp_group_id grp_id; +} oid_ecp_grp_t; + +static const oid_ecp_grp_t oid_ecp_grp[] = +{ + { + { ADD_LEN( OID_EC_GRP_SECP192R1 ), "secp192r1", "secp192r1" }, + POLARSSL_ECP_DP_SECP192R1, + }, + { + { ADD_LEN( OID_EC_GRP_SECP224R1 ), "secp224r1", "secp224r1" }, + POLARSSL_ECP_DP_SECP224R1, + }, + { + { ADD_LEN( OID_EC_GRP_SECP256R1 ), "secp256r1", "secp256r1" }, + POLARSSL_ECP_DP_SECP256R1, + }, + { + { ADD_LEN( OID_EC_GRP_SECP384R1 ), "secp384r1", "secp384r1" }, + POLARSSL_ECP_DP_SECP384R1, + }, + { + { ADD_LEN( OID_EC_GRP_SECP521R1 ), "secp521r1", "secp521r1" }, + POLARSSL_ECP_DP_SECP521R1, + }, + { + { ADD_LEN( OID_EC_GRP_SECP192K1 ), "secp192k1", "secp192k1" }, + POLARSSL_ECP_DP_SECP192K1, + }, + { + { ADD_LEN( OID_EC_GRP_SECP224K1 ), "secp224k1", "secp224k1" }, + POLARSSL_ECP_DP_SECP224K1, + }, + { + { ADD_LEN( OID_EC_GRP_SECP256K1 ), "secp256k1", "secp256k1" }, + POLARSSL_ECP_DP_SECP256K1, + }, + { + { ADD_LEN( OID_EC_GRP_BP256R1 ), "brainpoolP256r1","brainpool256r1" }, + POLARSSL_ECP_DP_BP256R1, + }, + { + { ADD_LEN( OID_EC_GRP_BP384R1 ), "brainpoolP384r1","brainpool384r1" }, + POLARSSL_ECP_DP_BP384R1, + }, + { + { ADD_LEN( OID_EC_GRP_BP512R1 ), "brainpoolP512r1","brainpool512r1" }, + POLARSSL_ECP_DP_BP512R1, + }, + { + { NULL, 0, NULL, NULL }, + 0, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_ecp_grp_t, grp_id, oid_ecp_grp); +FN_OID_GET_ATTR1(oid_get_ec_grp, oid_ecp_grp_t, grp_id, ecp_group_id, grp_id); +FN_OID_GET_OID_BY_ATTR1(oid_get_oid_by_ec_grp, oid_ecp_grp_t, oid_ecp_grp, ecp_group_id, grp_id); +#endif /* POLARSSL_ECP_C */ + +#if defined(POLARSSL_CIPHER_C) +/* + * For PKCS#5 PBES2 encryption algorithm + */ +typedef struct { + oid_descriptor_t descriptor; + cipher_type_t cipher_alg; +} oid_cipher_alg_t; + +static const oid_cipher_alg_t oid_cipher_alg[] = +{ + { + { ADD_LEN( OID_DES_CBC ), "desCBC", "DES-CBC" }, + POLARSSL_CIPHER_DES_CBC, + }, + { + { ADD_LEN( OID_DES_EDE3_CBC ), "des-ede3-cbc", "DES-EDE3-CBC" }, + POLARSSL_CIPHER_DES_EDE3_CBC, + }, + { + { NULL, 0, NULL, NULL }, + (cipher_type_t)0, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_cipher_alg_t, cipher_alg, oid_cipher_alg); +FN_OID_GET_ATTR1(oid_get_cipher_alg, oid_cipher_alg_t, cipher_alg, cipher_type_t, cipher_alg); +#endif /* POLARSSL_CIPHER_C */ + +#if defined(POLARSSL_MD_C) +/* + * For digestAlgorithm + */ +typedef struct { + oid_descriptor_t descriptor; + md_type_t md_alg; +} oid_md_alg_t; + +static const oid_md_alg_t oid_md_alg[] = +{ + { + { ADD_LEN( OID_DIGEST_ALG_MD2 ), "id-md2", "MD2" }, + POLARSSL_MD_MD2, + }, + { + { ADD_LEN( OID_DIGEST_ALG_MD4 ), "id-md4", "MD4" }, + POLARSSL_MD_MD4, + }, + { + { ADD_LEN( OID_DIGEST_ALG_MD5 ), "id-md5", "MD5" }, + POLARSSL_MD_MD5, + }, + { + { ADD_LEN( OID_DIGEST_ALG_SHA1 ), "id-sha1", "SHA-1" }, + POLARSSL_MD_SHA1, + }, + { + { ADD_LEN( OID_DIGEST_ALG_SHA224 ), "id-sha224", "SHA-224" }, + POLARSSL_MD_SHA224, + }, + { + { ADD_LEN( OID_DIGEST_ALG_SHA256 ), "id-sha256", "SHA-256" }, + POLARSSL_MD_SHA256, + }, + { + { ADD_LEN( OID_DIGEST_ALG_SHA384 ), "id-sha384", "SHA-384" }, + POLARSSL_MD_SHA384, + }, + { + { ADD_LEN( OID_DIGEST_ALG_SHA512 ), "id-sha512", "SHA-512" }, + POLARSSL_MD_SHA512, + }, + { + { NULL, 0, NULL, NULL }, + (md_type_t)0, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_md_alg_t, md_alg, oid_md_alg); +FN_OID_GET_ATTR1(oid_get_md_alg, oid_md_alg_t, md_alg, md_type_t, md_alg); +FN_OID_GET_OID_BY_ATTR1(oid_get_oid_by_md, oid_md_alg_t, oid_md_alg, md_type_t, md_alg); +#endif /* POLARSSL_MD_C */ + +#if defined(POLARSSL_PKCS12_C) +/* + * For PKCS#12 PBEs + */ +typedef struct { + oid_descriptor_t descriptor; + md_type_t md_alg; + cipher_type_t cipher_alg; +} oid_pkcs12_pbe_alg_t; + +static const oid_pkcs12_pbe_alg_t oid_pkcs12_pbe_alg[] = +{ + { + { ADD_LEN( OID_PKCS12_PBE_SHA1_DES3_EDE_CBC ), "pbeWithSHAAnd3-KeyTripleDES-CBC", "PBE with SHA1 and 3-Key 3DES" }, + POLARSSL_MD_SHA1, POLARSSL_CIPHER_DES_EDE3_CBC, + }, + { + { ADD_LEN( OID_PKCS12_PBE_SHA1_DES2_EDE_CBC ), "pbeWithSHAAnd2-KeyTripleDES-CBC", "PBE with SHA1 and 2-Key 3DES" }, + POLARSSL_MD_SHA1, POLARSSL_CIPHER_DES_EDE_CBC, + }, + { + { NULL, 0, NULL, NULL }, + 0, 0, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, oid_pkcs12_pbe_alg); +FN_OID_GET_ATTR2(oid_get_pkcs12_pbe_alg, oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, md_type_t, md_alg, cipher_type_t, cipher_alg); +#endif /* POLARSSL_PKCS12_C */ + +#if defined(_MSC_VER) && !defined snprintf && !defined(EFIX64) && \ + !defined(EFI32) +#include + +#if !defined vsnprintf +#define vsnprintf _vsnprintf +#endif // vsnprintf + +/* + * Windows _snprintf and _vsnprintf are not compatible to linux versions. + * Result value is not size of buffer needed, but -1 if no fit is possible. + * + * This fuction tries to 'fix' this by at least suggesting enlarging the + * size by 20. + */ +static int compat_snprintf( char *str, size_t size, const char *format, ... ) +{ + va_list ap; + int res = -1; + + va_start( ap, format ); + + res = vsnprintf( str, size, format, ap ); + + va_end( ap ); + + // No quick fix possible + if( res < 0 ) + return( (int) size + 20 ); + + return( res ); +} + +#define snprintf compat_snprintf +#endif /* _MSC_VER && !snprintf && !EFIX64 && !EFI32 */ + +#define SAFE_SNPRINTF() \ +{ \ + if( ret == -1 ) \ + return( POLARSSL_ERR_OID_BUF_TOO_SMALL ); \ + \ + if( (unsigned int) ret >= n ) { \ + p[n - 1] = '\0'; \ + return( POLARSSL_ERR_OID_BUF_TOO_SMALL ); \ + } \ + \ + n -= (unsigned int) ret; \ + p += (unsigned int) ret; \ +} + +/* Return the x.y.z.... style numeric string for the given OID */ +int oid_get_numeric_string( char *buf, size_t size, + const asn1_buf *oid ) +{ + int ret; + size_t i, n; + unsigned int value; + char *p; + + p = buf; + n = size; + + /* First byte contains first two dots */ + if( oid->len > 0 ) + { + ret = snprintf( p, n, "%d.%d", oid->p[0] / 40, oid->p[0] % 40 ); + SAFE_SNPRINTF(); + } + + value = 0; + for( i = 1; i < oid->len; i++ ) + { + /* Prevent overflow in value. */ + if( ( ( value << 7 ) >> 7 ) != value ) + return( POLARSSL_ERR_OID_BUF_TOO_SMALL ); + + value <<= 7; + value += oid->p[i] & 0x7F; + + if( !( oid->p[i] & 0x80 ) ) + { + /* Last byte */ + ret = snprintf( p, n, ".%d", value ); + SAFE_SNPRINTF(); + value = 0; + } + } + + return( (int) ( size - n ) ); +} + +#endif /* POLARSSL_OID_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/padlock.c b/component/common/network/ssl/polarssl-1.3.8/library/padlock.c new file mode 100644 index 0000000..5d06390 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/padlock.c @@ -0,0 +1,168 @@ +/* + * VIA PadLock support functions + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * This implementation is based on the VIA PadLock Programming Guide: + * + * http://www.via.com.tw/en/downloads/whitepapers/initiatives/padlock/ + * programming_guide.pdf + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_PADLOCK_C) + +#include "polarssl/padlock.h" + +#if defined(POLARSSL_HAVE_X86) + +/* + * PadLock detection routine + */ +int padlock_supports( int feature ) +{ + static int flags = -1; + int ebx = 0, edx = 0; + + if( flags == -1 ) + { + asm( "movl %%ebx, %0 \n\t" + "movl $0xC0000000, %%eax \n\t" + "cpuid \n\t" + "cmpl $0xC0000001, %%eax \n\t" + "movl $0, %%edx \n\t" + "jb unsupported \n\t" + "movl $0xC0000001, %%eax \n\t" + "cpuid \n\t" + "unsupported: \n\t" + "movl %%edx, %1 \n\t" + "movl %2, %%ebx \n\t" + : "=m" (ebx), "=m" (edx) + : "m" (ebx) + : "eax", "ecx", "edx" ); + + flags = edx; + } + + return( flags & feature ); +} + +/* + * PadLock AES-ECB block en(de)cryption + */ +int padlock_xcryptecb( aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ) +{ + int ebx = 0; + uint32_t *rk; + uint32_t *blk; + uint32_t *ctrl; + unsigned char buf[256]; + + rk = ctx->rk; + blk = PADLOCK_ALIGN16( buf ); + memcpy( blk, input, 16 ); + + ctrl = blk + 4; + *ctrl = 0x80 | ctx->nr | ( ( ctx->nr + ( mode^1 ) - 10 ) << 9 ); + + asm( "pushfl \n\t" + "popfl \n\t" + "movl %%ebx, %0 \n\t" + "movl $1, %%ecx \n\t" + "movl %2, %%edx \n\t" + "movl %3, %%ebx \n\t" + "movl %4, %%esi \n\t" + "movl %4, %%edi \n\t" + ".byte 0xf3,0x0f,0xa7,0xc8 \n\t" + "movl %1, %%ebx \n\t" + : "=m" (ebx) + : "m" (ebx), "m" (ctrl), "m" (rk), "m" (blk) + : "ecx", "edx", "esi", "edi" ); + + memcpy( output, blk, 16 ); + + return( 0 ); +} + +/* + * PadLock AES-CBC buffer en(de)cryption + */ +int padlock_xcryptcbc( aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int ebx = 0; + size_t count; + uint32_t *rk; + uint32_t *iw; + uint32_t *ctrl; + unsigned char buf[256]; + + if( ( (long) input & 15 ) != 0 || + ( (long) output & 15 ) != 0 ) + return( POLARSSL_ERR_PADLOCK_DATA_MISALIGNED ); + + rk = ctx->rk; + iw = PADLOCK_ALIGN16( buf ); + memcpy( iw, iv, 16 ); + + ctrl = iw + 4; + *ctrl = 0x80 | ctx->nr | ( ( ctx->nr + ( mode ^ 1 ) - 10 ) << 9 ); + + count = ( length + 15 ) >> 4; + + asm( "pushfl \n\t" + "popfl \n\t" + "movl %%ebx, %0 \n\t" + "movl %2, %%ecx \n\t" + "movl %3, %%edx \n\t" + "movl %4, %%ebx \n\t" + "movl %5, %%esi \n\t" + "movl %6, %%edi \n\t" + "movl %7, %%eax \n\t" + ".byte 0xf3,0x0f,0xa7,0xd0 \n\t" + "movl %1, %%ebx \n\t" + : "=m" (ebx) + : "m" (ebx), "m" (count), "m" (ctrl), + "m" (rk), "m" (input), "m" (output), "m" (iw) + : "eax", "ecx", "edx", "esi", "edi" ); + + memcpy( iv, iw, 16 ); + + return( 0 ); +} + +#endif /* POLARSSL_HAVE_X86 */ + +#endif /* POLARSSL_PADLOCK_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/pbkdf2.c b/component/common/network/ssl/polarssl-1.3.8/library/pbkdf2.c new file mode 100644 index 0000000..e76f066 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/pbkdf2.c @@ -0,0 +1,64 @@ +/** + * \file pbkdf2.c + * + * \brief Password-Based Key Derivation Function 2 (from PKCS#5) + * DEPRECATED: Use pkcs5.c instead + * + * \author Mathias Olsson + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * PBKDF2 is part of PKCS#5 + * + * http://tools.ietf.org/html/rfc2898 (Specification) + * http://tools.ietf.org/html/rfc6070 (Test vectors) + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_PBKDF2_C) + +#include "polarssl/pbkdf2.h" +#include "polarssl/pkcs5.h" + +int pbkdf2_hmac( md_context_t *ctx, const unsigned char *password, size_t plen, + const unsigned char *salt, size_t slen, + unsigned int iteration_count, + uint32_t key_length, unsigned char *output ) +{ + return pkcs5_pbkdf2_hmac( ctx, password, plen, salt, slen, iteration_count, + key_length, output ); +} + +#if defined(POLARSSL_SELF_TEST) +int pbkdf2_self_test( int verbose ) +{ + return pkcs5_self_test( verbose ); +} +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_PBKDF2_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/pem.c b/component/common/network/ssl/polarssl-1.3.8/library/pem.c new file mode 100644 index 0000000..485d829 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/pem.c @@ -0,0 +1,445 @@ +/* + * Privacy Enhanced Mail (PEM) decoding + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_PEM_PARSE_C) || defined(POLARSSL_PEM_WRITE_C) +#include "polarssl/pem.h" +#include "polarssl/base64.h" +#include "polarssl/des.h" +#include "polarssl/aes.h" +#include "polarssl/md5.h" +#include "polarssl/cipher.h" + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#define polarssl_malloc malloc +#define polarssl_free free +#endif + +#include + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +#if defined(POLARSSL_PEM_PARSE_C) +void pem_init( pem_context *ctx ) +{ + memset( ctx, 0, sizeof( pem_context ) ); +} + +#if defined(POLARSSL_MD5_C) && defined(POLARSSL_CIPHER_MODE_CBC) && \ + ( defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C) ) +/* + * Read a 16-byte hex string and convert it to binary + */ +static int pem_get_iv( const unsigned char *s, unsigned char *iv, + size_t iv_len ) +{ + size_t i, j, k; + + memset( iv, 0, iv_len ); + + for( i = 0; i < iv_len * 2; i++, s++ ) + { + if( *s >= '0' && *s <= '9' ) j = *s - '0'; else + if( *s >= 'A' && *s <= 'F' ) j = *s - '7'; else + if( *s >= 'a' && *s <= 'f' ) j = *s - 'W'; else + return( POLARSSL_ERR_PEM_INVALID_ENC_IV ); + + k = ( ( i & 1 ) != 0 ) ? j : j << 4; + + iv[i >> 1] = (unsigned char)( iv[i >> 1] | k ); + } + + return( 0 ); +} + +static void pem_pbkdf1( unsigned char *key, size_t keylen, + unsigned char *iv, + const unsigned char *pwd, size_t pwdlen ) +{ + md5_context md5_ctx; + unsigned char md5sum[16]; + size_t use_len; + + md5_init( &md5_ctx ); + + /* + * key[ 0..15] = MD5(pwd || IV) + */ + md5_starts( &md5_ctx ); + md5_update( &md5_ctx, pwd, pwdlen ); + md5_update( &md5_ctx, iv, 8 ); + md5_finish( &md5_ctx, md5sum ); + + if( keylen <= 16 ) + { + memcpy( key, md5sum, keylen ); + + md5_free( &md5_ctx ); + polarssl_zeroize( md5sum, 16 ); + return; + } + + memcpy( key, md5sum, 16 ); + + /* + * key[16..23] = MD5(key[ 0..15] || pwd || IV]) + */ + md5_starts( &md5_ctx ); + md5_update( &md5_ctx, md5sum, 16 ); + md5_update( &md5_ctx, pwd, pwdlen ); + md5_update( &md5_ctx, iv, 8 ); + md5_finish( &md5_ctx, md5sum ); + + use_len = 16; + if( keylen < 32 ) + use_len = keylen - 16; + + memcpy( key + 16, md5sum, use_len ); + + md5_free( &md5_ctx ); + polarssl_zeroize( md5sum, 16 ); +} + +#if defined(POLARSSL_DES_C) +/* + * Decrypt with DES-CBC, using PBKDF1 for key derivation + */ +static void pem_des_decrypt( unsigned char des_iv[8], + unsigned char *buf, size_t buflen, + const unsigned char *pwd, size_t pwdlen ) +{ + des_context des_ctx; + unsigned char des_key[8]; + + des_init( &des_ctx ); + + pem_pbkdf1( des_key, 8, des_iv, pwd, pwdlen ); + + des_setkey_dec( &des_ctx, des_key ); + des_crypt_cbc( &des_ctx, DES_DECRYPT, buflen, + des_iv, buf, buf ); + + des_free( &des_ctx ); + polarssl_zeroize( des_key, 8 ); +} + +/* + * Decrypt with 3DES-CBC, using PBKDF1 for key derivation + */ +static void pem_des3_decrypt( unsigned char des3_iv[8], + unsigned char *buf, size_t buflen, + const unsigned char *pwd, size_t pwdlen ) +{ + des3_context des3_ctx; + unsigned char des3_key[24]; + + des3_init( &des3_ctx ); + + pem_pbkdf1( des3_key, 24, des3_iv, pwd, pwdlen ); + + des3_set3key_dec( &des3_ctx, des3_key ); + des3_crypt_cbc( &des3_ctx, DES_DECRYPT, buflen, + des3_iv, buf, buf ); + + des3_free( &des3_ctx ); + polarssl_zeroize( des3_key, 24 ); +} +#endif /* POLARSSL_DES_C */ + +#if defined(POLARSSL_AES_C) +/* + * Decrypt with AES-XXX-CBC, using PBKDF1 for key derivation + */ +static void pem_aes_decrypt( unsigned char aes_iv[16], unsigned int keylen, + unsigned char *buf, size_t buflen, + const unsigned char *pwd, size_t pwdlen ) +{ + aes_context aes_ctx; + unsigned char aes_key[32]; + + aes_init( &aes_ctx ); + + pem_pbkdf1( aes_key, keylen, aes_iv, pwd, pwdlen ); + + aes_setkey_dec( &aes_ctx, aes_key, keylen * 8 ); + aes_crypt_cbc( &aes_ctx, AES_DECRYPT, buflen, + aes_iv, buf, buf ); + + aes_free( &aes_ctx ); + polarssl_zeroize( aes_key, keylen ); +} +#endif /* POLARSSL_AES_C */ + +#endif /* POLARSSL_MD5_C && POLARSSL_CIPHER_MODE_CBC && + ( POLARSSL_AES_C || POLARSSL_DES_C ) */ + +int pem_read_buffer( pem_context *ctx, const char *header, const char *footer, + const unsigned char *data, const unsigned char *pwd, + size_t pwdlen, size_t *use_len ) +{ + int ret, enc; + size_t len; + unsigned char *buf; + const unsigned char *s1, *s2, *end; +#if defined(POLARSSL_MD5_C) && defined(POLARSSL_CIPHER_MODE_CBC) && \ + ( defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C) ) + unsigned char pem_iv[16]; + cipher_type_t enc_alg = POLARSSL_CIPHER_NONE; +#else + ((void) pwd); + ((void) pwdlen); +#endif /* POLARSSL_MD5_C && POLARSSL_CIPHER_MODE_CBC && + ( POLARSSL_AES_C || POLARSSL_DES_C ) */ + + if( ctx == NULL ) + return( POLARSSL_ERR_PEM_BAD_INPUT_DATA ); + + s1 = (unsigned char *) strstr( (const char *) data, header ); + + if( s1 == NULL ) + return( POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); + + s2 = (unsigned char *) strstr( (const char *) data, footer ); + + if( s2 == NULL || s2 <= s1 ) + return( POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); + + s1 += strlen( header ); + if( *s1 == '\r' ) s1++; + if( *s1 == '\n' ) s1++; + else return( POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); + + end = s2; + end += strlen( footer ); + if( *end == '\r' ) end++; + if( *end == '\n' ) end++; + *use_len = end - data; + + enc = 0; + + if( memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 ) + { +#if defined(POLARSSL_MD5_C) && defined(POLARSSL_CIPHER_MODE_CBC) && \ + ( defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C) ) + enc++; + + s1 += 22; + if( *s1 == '\r' ) s1++; + if( *s1 == '\n' ) s1++; + else return( POLARSSL_ERR_PEM_INVALID_DATA ); + + +#if defined(POLARSSL_DES_C) + if( memcmp( s1, "DEK-Info: DES-EDE3-CBC,", 23 ) == 0 ) + { + enc_alg = POLARSSL_CIPHER_DES_EDE3_CBC; + + s1 += 23; + if( pem_get_iv( s1, pem_iv, 8 ) != 0 ) + return( POLARSSL_ERR_PEM_INVALID_ENC_IV ); + + s1 += 16; + } + else if( memcmp( s1, "DEK-Info: DES-CBC,", 18 ) == 0 ) + { + enc_alg = POLARSSL_CIPHER_DES_CBC; + + s1 += 18; + if( pem_get_iv( s1, pem_iv, 8) != 0 ) + return( POLARSSL_ERR_PEM_INVALID_ENC_IV ); + + s1 += 16; + } +#endif /* POLARSSL_DES_C */ + +#if defined(POLARSSL_AES_C) + if( memcmp( s1, "DEK-Info: AES-", 14 ) == 0 ) + { + if( memcmp( s1, "DEK-Info: AES-128-CBC,", 22 ) == 0 ) + enc_alg = POLARSSL_CIPHER_AES_128_CBC; + else if( memcmp( s1, "DEK-Info: AES-192-CBC,", 22 ) == 0 ) + enc_alg = POLARSSL_CIPHER_AES_192_CBC; + else if( memcmp( s1, "DEK-Info: AES-256-CBC,", 22 ) == 0 ) + enc_alg = POLARSSL_CIPHER_AES_256_CBC; + else + return( POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG ); + + s1 += 22; + if( pem_get_iv( s1, pem_iv, 16 ) != 0 ) + return( POLARSSL_ERR_PEM_INVALID_ENC_IV ); + + s1 += 32; + } +#endif /* POLARSSL_AES_C */ + + if( enc_alg == POLARSSL_CIPHER_NONE ) + return( POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG ); + + if( *s1 == '\r' ) s1++; + if( *s1 == '\n' ) s1++; + else return( POLARSSL_ERR_PEM_INVALID_DATA ); +#else + return( POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE ); +#endif /* POLARSSL_MD5_C && POLARSSL_CIPHER_MODE_CBC && + ( POLARSSL_AES_C || POLARSSL_DES_C ) */ + } + + len = 0; + ret = base64_decode( NULL, &len, s1, s2 - s1 ); + + if( ret == POLARSSL_ERR_BASE64_INVALID_CHARACTER ) + return( POLARSSL_ERR_PEM_INVALID_DATA + ret ); + + if( ( buf = (unsigned char *) polarssl_malloc( len ) ) == NULL ) + return( POLARSSL_ERR_PEM_MALLOC_FAILED ); + + if( ( ret = base64_decode( buf, &len, s1, s2 - s1 ) ) != 0 ) + { + polarssl_free( buf ); + return( POLARSSL_ERR_PEM_INVALID_DATA + ret ); + } + + if( enc != 0 ) + { +#if defined(POLARSSL_MD5_C) && defined(POLARSSL_CIPHER_MODE_CBC) && \ + ( defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C) ) + if( pwd == NULL ) + { + polarssl_free( buf ); + return( POLARSSL_ERR_PEM_PASSWORD_REQUIRED ); + } + +#if defined(POLARSSL_DES_C) + if( enc_alg == POLARSSL_CIPHER_DES_EDE3_CBC ) + pem_des3_decrypt( pem_iv, buf, len, pwd, pwdlen ); + else if( enc_alg == POLARSSL_CIPHER_DES_CBC ) + pem_des_decrypt( pem_iv, buf, len, pwd, pwdlen ); +#endif /* POLARSSL_DES_C */ + +#if defined(POLARSSL_AES_C) + if( enc_alg == POLARSSL_CIPHER_AES_128_CBC ) + pem_aes_decrypt( pem_iv, 16, buf, len, pwd, pwdlen ); + else if( enc_alg == POLARSSL_CIPHER_AES_192_CBC ) + pem_aes_decrypt( pem_iv, 24, buf, len, pwd, pwdlen ); + else if( enc_alg == POLARSSL_CIPHER_AES_256_CBC ) + pem_aes_decrypt( pem_iv, 32, buf, len, pwd, pwdlen ); +#endif /* POLARSSL_AES_C */ + + /* + * The result will be ASN.1 starting with a SEQUENCE tag, with 1 to 3 + * length bytes (allow 4 to be sure) in all known use cases. + * + * Use that as heurisitic to try detecting password mismatchs. + */ + if( len <= 2 || buf[0] != 0x30 || buf[1] > 0x83 ) + { + polarssl_free( buf ); + return( POLARSSL_ERR_PEM_PASSWORD_MISMATCH ); + } +#else + polarssl_free( buf ); + return( POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE ); +#endif /* POLARSSL_MD5_C && POLARSSL_CIPHER_MODE_CBC && + ( POLARSSL_AES_C || POLARSSL_DES_C ) */ + } + + ctx->buf = buf; + ctx->buflen = len; + + return( 0 ); +} + +void pem_free( pem_context *ctx ) +{ + polarssl_free( ctx->buf ); + polarssl_free( ctx->info ); + + polarssl_zeroize( ctx, sizeof( pem_context ) ); +} +#endif /* POLARSSL_PEM_PARSE_C */ + +#if defined(POLARSSL_PEM_WRITE_C) +int pem_write_buffer( const char *header, const char *footer, + const unsigned char *der_data, size_t der_len, + unsigned char *buf, size_t buf_len, size_t *olen ) +{ + int ret; + unsigned char *encode_buf, *c, *p = buf; + size_t len = 0, use_len = 0, add_len = 0; + + base64_encode( NULL, &use_len, der_data, der_len ); + add_len = strlen( header ) + strlen( footer ) + ( use_len / 64 ) + 1; + + if( use_len + add_len > buf_len ) + { + *olen = use_len + add_len; + return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + if( ( encode_buf = polarssl_malloc( use_len ) ) == NULL ) + return( POLARSSL_ERR_PEM_MALLOC_FAILED ); + + if( ( ret = base64_encode( encode_buf, &use_len, der_data, + der_len ) ) != 0 ) + { + polarssl_free( encode_buf ); + return( ret ); + } + + memcpy( p, header, strlen( header ) ); + p += strlen( header ); + c = encode_buf; + + while( use_len ) + { + len = ( use_len > 64 ) ? 64 : use_len; + memcpy( p, c, len ); + use_len -= len; + p += len; + c += len; + *p++ = '\n'; + } + + memcpy( p, footer, strlen( footer ) ); + p += strlen( footer ); + + *p++ = '\0'; + *olen = p - buf; + + polarssl_free( encode_buf ); + return( 0 ); +} +#endif /* POLARSSL_PEM_WRITE_C */ +#endif /* POLARSSL_PEM_PARSE_C || POLARSSL_PEM_WRITE_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/pk.c b/component/common/network/ssl/polarssl-1.3.8/library/pk.c new file mode 100644 index 0000000..11faf3c --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/pk.c @@ -0,0 +1,351 @@ +/* + * Public Key abstraction layer + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_PK_C) + +#include "polarssl/pk.h" +#include "polarssl/pk_wrap.h" + +#if defined(POLARSSL_RSA_C) +#include "polarssl/rsa.h" +#endif +#if defined(POLARSSL_ECP_C) +#include "polarssl/ecp.h" +#endif +#if defined(POLARSSL_ECDSA_C) +#include "polarssl/ecdsa.h" +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * Initialise a pk_context + */ +void pk_init( pk_context *ctx ) +{ + if( ctx == NULL ) + return; + + ctx->pk_info = NULL; + ctx->pk_ctx = NULL; +} + +/* + * Free (the components of) a pk_context + */ +void pk_free( pk_context *ctx ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return; + + ctx->pk_info->ctx_free_func( ctx->pk_ctx ); + + polarssl_zeroize( ctx, sizeof( pk_context ) ); +} + +/* + * Get pk_info structure from type + */ +const pk_info_t * pk_info_from_type( pk_type_t pk_type ) +{ + switch( pk_type ) { +#if defined(POLARSSL_RSA_C) + case POLARSSL_PK_RSA: + return( &rsa_info ); +#endif +#if defined(POLARSSL_ECP_C) + case POLARSSL_PK_ECKEY: + return( &eckey_info ); + case POLARSSL_PK_ECKEY_DH: + return( &eckeydh_info ); +#endif +#if defined(POLARSSL_ECDSA_C) + case POLARSSL_PK_ECDSA: + return( &ecdsa_info ); +#endif + /* POLARSSL_PK_RSA_ALT omitted on purpose */ + default: + return( NULL ); + } +} + +/* + * Initialise context + */ +int pk_init_ctx( pk_context *ctx, const pk_info_t *info ) +{ + if( ctx == NULL || info == NULL || ctx->pk_info != NULL ) + return( POLARSSL_ERR_PK_BAD_INPUT_DATA ); + + if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL ) + return( POLARSSL_ERR_PK_MALLOC_FAILED ); + + ctx->pk_info = info; + + return( 0 ); +} + +/* + * Initialize an RSA-alt context + */ +int pk_init_ctx_rsa_alt( pk_context *ctx, void * key, + pk_rsa_alt_decrypt_func decrypt_func, + pk_rsa_alt_sign_func sign_func, + pk_rsa_alt_key_len_func key_len_func ) +{ + rsa_alt_context *rsa_alt; + const pk_info_t *info = &rsa_alt_info; + + if( ctx == NULL || ctx->pk_info != NULL ) + return( POLARSSL_ERR_PK_BAD_INPUT_DATA ); + + if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL ) + return( POLARSSL_ERR_PK_MALLOC_FAILED ); + + ctx->pk_info = info; + + rsa_alt = (rsa_alt_context *) ctx->pk_ctx; + + rsa_alt->key = key; + rsa_alt->decrypt_func = decrypt_func; + rsa_alt->sign_func = sign_func; + rsa_alt->key_len_func = key_len_func; + + return( 0 ); +} + +/* + * Tell if a PK can do the operations of the given type + */ +int pk_can_do( pk_context *ctx, pk_type_t type ) +{ + /* null or NONE context can't do anything */ + if( ctx == NULL || ctx->pk_info == NULL ) + return( 0 ); + + return( ctx->pk_info->can_do( type ) ); +} + +/* + * Helper for pk_sign and pk_verify + */ +static inline int pk_hashlen_helper( md_type_t md_alg, size_t *hash_len ) +{ + const md_info_t *md_info; + + if( *hash_len != 0 ) + return( 0 ); + + if( ( md_info = md_info_from_type( md_alg ) ) == NULL ) + return( -1 ); + + *hash_len = md_info->size; + return( 0 ); +} + +/* + * Verify a signature + */ +int pk_verify( pk_context *ctx, md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + if( ctx == NULL || ctx->pk_info == NULL || + pk_hashlen_helper( md_alg, &hash_len ) != 0 ) + return( POLARSSL_ERR_PK_BAD_INPUT_DATA ); + + if( ctx->pk_info->verify_func == NULL ) + return( POLARSSL_ERR_PK_TYPE_MISMATCH ); + + return( ctx->pk_info->verify_func( ctx->pk_ctx, md_alg, hash, hash_len, + sig, sig_len ) ); +} + +/* + * Verify a signature with options + */ +int pk_verify_ext( pk_type_t type, const void *options, + pk_context *ctx, md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( POLARSSL_ERR_PK_BAD_INPUT_DATA ); + + if( ! pk_can_do( ctx, type ) ) + return( POLARSSL_ERR_PK_TYPE_MISMATCH ); + + if( type == POLARSSL_PK_RSASSA_PSS ) + { +#if defined(POLARSSL_RSA_C) && defined(POLARSSL_PKCS1_V21) + int ret; + const pk_rsassa_pss_options *pss_opts; + + if( options == NULL ) + return( POLARSSL_ERR_PK_BAD_INPUT_DATA ); + + pss_opts = (const pk_rsassa_pss_options *) options; + + if( sig_len < pk_get_len( ctx ) ) + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + + ret = rsa_rsassa_pss_verify_ext( pk_rsa( *ctx ), + NULL, NULL, RSA_PUBLIC, + md_alg, hash_len, hash, + pss_opts->mgf1_hash_id, + pss_opts->expected_salt_len, + sig ); + if( ret != 0 ) + return( ret ); + + if( sig_len > pk_get_len( ctx ) ) + return( POLARSSL_ERR_PK_SIG_LEN_MISMATCH ); + + return( 0 ); +#else + return( POLARSSL_ERR_PK_FEATURE_UNAVAILABLE ); +#endif + } + + /* General case: no options */ + if( options != NULL ) + return( POLARSSL_ERR_PK_BAD_INPUT_DATA ); + + return( pk_verify( ctx, md_alg, hash, hash_len, sig, sig_len ) ); +} + +/* + * Make a signature + */ +int pk_sign( pk_context *ctx, md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + if( ctx == NULL || ctx->pk_info == NULL || + pk_hashlen_helper( md_alg, &hash_len ) != 0 ) + return( POLARSSL_ERR_PK_BAD_INPUT_DATA ); + + if( ctx->pk_info->sign_func == NULL ) + return( POLARSSL_ERR_PK_TYPE_MISMATCH ); + + return( ctx->pk_info->sign_func( ctx->pk_ctx, md_alg, hash, hash_len, + sig, sig_len, f_rng, p_rng ) ); +} + +/* + * Decrypt message + */ +int pk_decrypt( pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( POLARSSL_ERR_PK_BAD_INPUT_DATA ); + + if( ctx->pk_info->decrypt_func == NULL ) + return( POLARSSL_ERR_PK_TYPE_MISMATCH ); + + return( ctx->pk_info->decrypt_func( ctx->pk_ctx, input, ilen, + output, olen, osize, f_rng, p_rng ) ); +} + +/* + * Encrypt message + */ +int pk_encrypt( pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( POLARSSL_ERR_PK_BAD_INPUT_DATA ); + + if( ctx->pk_info->encrypt_func == NULL ) + return( POLARSSL_ERR_PK_TYPE_MISMATCH ); + + return( ctx->pk_info->encrypt_func( ctx->pk_ctx, input, ilen, + output, olen, osize, f_rng, p_rng ) ); +} + +/* + * Get key size in bits + */ +size_t pk_get_size( const pk_context *ctx ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( 0 ); + + return( ctx->pk_info->get_size( ctx->pk_ctx ) ); +} + +/* + * Export debug information + */ +int pk_debug( const pk_context *ctx, pk_debug_item *items ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( POLARSSL_ERR_PK_BAD_INPUT_DATA ); + + if( ctx->pk_info->debug_func == NULL ) + return( POLARSSL_ERR_PK_TYPE_MISMATCH ); + + ctx->pk_info->debug_func( ctx->pk_ctx, items ); + return( 0 ); +} + +/* + * Access the PK type name + */ +const char * pk_get_name( const pk_context *ctx ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( "invalid PK" ); + + return( ctx->pk_info->name ); +} + +/* + * Access the PK type + */ +pk_type_t pk_get_type( const pk_context *ctx ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( POLARSSL_PK_NONE ); + + return( ctx->pk_info->type ); +} + +#endif /* POLARSSL_PK_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/pk_wrap.c b/component/common/network/ssl/polarssl-1.3.8/library/pk_wrap.c new file mode 100644 index 0000000..5e9ff60 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/pk_wrap.c @@ -0,0 +1,452 @@ +/* + * Public Key abstraction layer: wrapper functions + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_PK_C) + +#include "polarssl/pk_wrap.h" + +/* Even if RSA not activated, for the sake of RSA-alt */ +#include "polarssl/rsa.h" + +#if defined(POLARSSL_ECP_C) +#include "polarssl/ecp.h" +#endif + +#if defined(POLARSSL_ECDSA_C) +#include "polarssl/ecdsa.h" +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include +#define polarssl_malloc malloc +#define polarssl_free free +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +#if defined(POLARSSL_RSA_C) +static int rsa_can_do( pk_type_t type ) +{ + return( type == POLARSSL_PK_RSA || + type == POLARSSL_PK_RSASSA_PSS ); +} + +static size_t rsa_get_size( const void *ctx ) +{ + return( 8 * ((const rsa_context *) ctx)->len ); +} + +static int rsa_verify_wrap( void *ctx, md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + int ret; + + if( sig_len < ((rsa_context *) ctx)->len ) + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + + if( ( ret = rsa_pkcs1_verify( (rsa_context *) ctx, NULL, NULL, + RSA_PUBLIC, md_alg, + (unsigned int) hash_len, hash, sig ) ) != 0 ) + return( ret ); + + if( sig_len > ((rsa_context *) ctx)->len ) + return( POLARSSL_ERR_PK_SIG_LEN_MISMATCH ); + + return( 0 ); +} + +static int rsa_sign_wrap( void *ctx, md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + *sig_len = ((rsa_context *) ctx)->len; + + return( rsa_pkcs1_sign( (rsa_context *) ctx, f_rng, p_rng, RSA_PRIVATE, + md_alg, (unsigned int) hash_len, hash, sig ) ); +} + +static int rsa_decrypt_wrap( void *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + if( ilen != ((rsa_context *) ctx)->len ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + return( rsa_pkcs1_decrypt( (rsa_context *) ctx, f_rng, p_rng, + RSA_PRIVATE, olen, input, output, osize ) ); +} + +static int rsa_encrypt_wrap( void *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + ((void) osize); + + *olen = ((rsa_context *) ctx)->len; + + return( rsa_pkcs1_encrypt( (rsa_context *) ctx, + f_rng, p_rng, RSA_PUBLIC, ilen, input, output ) ); +} + +static void *rsa_alloc_wrap( void ) +{ + void *ctx = polarssl_malloc( sizeof( rsa_context ) ); + + if( ctx != NULL ) + rsa_init( (rsa_context *) ctx, 0, 0 ); + + return( ctx ); +} + +static void rsa_free_wrap( void *ctx ) +{ + rsa_free( (rsa_context *) ctx ); + polarssl_free( ctx ); +} + +static void rsa_debug( const void *ctx, pk_debug_item *items ) +{ + items->type = POLARSSL_PK_DEBUG_MPI; + items->name = "rsa.N"; + items->value = &( ((rsa_context *) ctx)->N ); + + items++; + + items->type = POLARSSL_PK_DEBUG_MPI; + items->name = "rsa.E"; + items->value = &( ((rsa_context *) ctx)->E ); +} + +const pk_info_t rsa_info = { + POLARSSL_PK_RSA, + "RSA", + rsa_get_size, + rsa_can_do, + rsa_verify_wrap, + rsa_sign_wrap, + rsa_decrypt_wrap, + rsa_encrypt_wrap, + rsa_alloc_wrap, + rsa_free_wrap, + rsa_debug, +}; +#endif /* POLARSSL_RSA_C */ + +#if defined(POLARSSL_ECP_C) +/* + * Generic EC key + */ +static int eckey_can_do( pk_type_t type ) +{ + return( type == POLARSSL_PK_ECKEY || + type == POLARSSL_PK_ECKEY_DH || + type == POLARSSL_PK_ECDSA ); +} + +static size_t eckey_get_size( const void *ctx ) +{ + return( ((ecp_keypair *) ctx)->grp.pbits ); +} + +#if defined(POLARSSL_ECDSA_C) +/* Forward declarations */ +static int ecdsa_verify_wrap( void *ctx, md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + +static int ecdsa_sign_wrap( void *ctx, md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +static int eckey_verify_wrap( void *ctx, md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + int ret; + ecdsa_context ecdsa; + + ecdsa_init( &ecdsa ); + + if( ( ret = ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 ) + ret = ecdsa_verify_wrap( &ecdsa, md_alg, hash, hash_len, sig, sig_len ); + + ecdsa_free( &ecdsa ); + + return( ret ); +} + +static int eckey_sign_wrap( void *ctx, md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret; + ecdsa_context ecdsa; + + ecdsa_init( &ecdsa ); + + if( ( ret = ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 ) + ret = ecdsa_sign_wrap( &ecdsa, md_alg, hash, hash_len, sig, sig_len, + f_rng, p_rng ); + + ecdsa_free( &ecdsa ); + + return( ret ); +} + +#endif /* POLARSSL_ECDSA_C */ + +static void *eckey_alloc_wrap( void ) +{ + void *ctx = polarssl_malloc( sizeof( ecp_keypair ) ); + + if( ctx != NULL ) + ecp_keypair_init( ctx ); + + return( ctx ); +} + +static void eckey_free_wrap( void *ctx ) +{ + ecp_keypair_free( (ecp_keypair *) ctx ); + polarssl_free( ctx ); +} + +static void eckey_debug( const void *ctx, pk_debug_item *items ) +{ + items->type = POLARSSL_PK_DEBUG_ECP; + items->name = "eckey.Q"; + items->value = &( ((ecp_keypair *) ctx)->Q ); +} + +const pk_info_t eckey_info = { + POLARSSL_PK_ECKEY, + "EC", + eckey_get_size, + eckey_can_do, +#if defined(POLARSSL_ECDSA_C) + eckey_verify_wrap, + eckey_sign_wrap, +#else + NULL, + NULL, +#endif + NULL, + NULL, + eckey_alloc_wrap, + eckey_free_wrap, + eckey_debug, +}; + +/* + * EC key restricted to ECDH + */ +static int eckeydh_can_do( pk_type_t type ) +{ + return( type == POLARSSL_PK_ECKEY || + type == POLARSSL_PK_ECKEY_DH ); +} + +const pk_info_t eckeydh_info = { + POLARSSL_PK_ECKEY_DH, + "EC_DH", + eckey_get_size, /* Same underlying key structure */ + eckeydh_can_do, + NULL, + NULL, + NULL, + NULL, + eckey_alloc_wrap, /* Same underlying key structure */ + eckey_free_wrap, /* Same underlying key structure */ + eckey_debug, /* Same underlying key structure */ +}; +#endif /* POLARSSL_ECP_C */ + +#if defined(POLARSSL_ECDSA_C) +static int ecdsa_can_do( pk_type_t type ) +{ + return( type == POLARSSL_PK_ECDSA ); +} + +static int ecdsa_verify_wrap( void *ctx, md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + int ret; + ((void) md_alg); + + ret = ecdsa_read_signature( (ecdsa_context *) ctx, + hash, hash_len, sig, sig_len ); + + if( ret == POLARSSL_ERR_ECP_SIG_LEN_MISMATCH ) + return( POLARSSL_ERR_PK_SIG_LEN_MISMATCH ); + + return( ret ); +} + +static int ecdsa_sign_wrap( void *ctx, md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + /* Use deterministic ECDSA by default if available */ +#if defined(POLARSSL_ECDSA_DETERMINISTIC) + ((void) f_rng); + ((void) p_rng); + + return( ecdsa_write_signature_det( (ecdsa_context *) ctx, + hash, hash_len, sig, sig_len, md_alg ) ); +#else + ((void) md_alg); + + return( ecdsa_write_signature( (ecdsa_context *) ctx, + hash, hash_len, sig, sig_len, f_rng, p_rng ) ); +#endif /* POLARSSL_ECDSA_DETERMINISTIC */ +} + +static void *ecdsa_alloc_wrap( void ) +{ + void *ctx = polarssl_malloc( sizeof( ecdsa_context ) ); + + if( ctx != NULL ) + ecdsa_init( (ecdsa_context *) ctx ); + + return( ctx ); +} + +static void ecdsa_free_wrap( void *ctx ) +{ + ecdsa_free( (ecdsa_context *) ctx ); + polarssl_free( ctx ); +} + +const pk_info_t ecdsa_info = { + POLARSSL_PK_ECDSA, + "ECDSA", + eckey_get_size, /* Compatible key structures */ + ecdsa_can_do, + ecdsa_verify_wrap, + ecdsa_sign_wrap, + NULL, + NULL, + ecdsa_alloc_wrap, + ecdsa_free_wrap, + eckey_debug, /* Compatible key structures */ +}; +#endif /* POLARSSL_ECDSA_C */ + +/* + * Support for alternative RSA-private implementations + */ + +static int rsa_alt_can_do( pk_type_t type ) +{ + return( type == POLARSSL_PK_RSA ); +} + +static size_t rsa_alt_get_size( const void *ctx ) +{ + const rsa_alt_context *rsa_alt = (const rsa_alt_context *) ctx; + + return( 8 * rsa_alt->key_len_func( rsa_alt->key ) ); +} + +static int rsa_alt_sign_wrap( void *ctx, md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + rsa_alt_context *rsa_alt = (rsa_alt_context *) ctx; + + *sig_len = rsa_alt->key_len_func( rsa_alt->key ); + + return( rsa_alt->sign_func( rsa_alt->key, f_rng, p_rng, RSA_PRIVATE, + md_alg, (unsigned int) hash_len, hash, sig ) ); +} + +static int rsa_alt_decrypt_wrap( void *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + rsa_alt_context *rsa_alt = (rsa_alt_context *) ctx; + + ((void) f_rng); + ((void) p_rng); + + if( ilen != rsa_alt->key_len_func( rsa_alt->key ) ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + return( rsa_alt->decrypt_func( rsa_alt->key, + RSA_PRIVATE, olen, input, output, osize ) ); +} + +static void *rsa_alt_alloc_wrap( void ) +{ + void *ctx = polarssl_malloc( sizeof( rsa_alt_context ) ); + + if( ctx != NULL ) + memset( ctx, 0, sizeof( rsa_alt_context ) ); + + return( ctx ); +} + +static void rsa_alt_free_wrap( void *ctx ) +{ + polarssl_zeroize( ctx, sizeof( rsa_alt_context ) ); + polarssl_free( ctx ); +} + +const pk_info_t rsa_alt_info = { + POLARSSL_PK_RSA_ALT, + "RSA-alt", + rsa_alt_get_size, + rsa_alt_can_do, + NULL, + rsa_alt_sign_wrap, + rsa_alt_decrypt_wrap, + NULL, + rsa_alt_alloc_wrap, + rsa_alt_free_wrap, + NULL, +}; + +#endif /* POLARSSL_PK_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/pkcs11.c b/component/common/network/ssl/polarssl-1.3.8/library/pkcs11.c new file mode 100644 index 0000000..64e7ce3 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/pkcs11.c @@ -0,0 +1,236 @@ +/** + * \file pkcs11.c + * + * \brief Wrapper for PKCS#11 library libpkcs11-helper + * + * \author Adriaan de Jong + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "polarssl/pkcs11.h" + +#if defined(POLARSSL_PKCS11_C) +#include "polarssl/md.h" +#include "polarssl/oid.h" +#include "polarssl/x509_crt.h" + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include +#define polarssl_malloc malloc +#define polarssl_free free +#endif + +int pkcs11_x509_cert_init( x509_crt *cert, pkcs11h_certificate_t pkcs11_cert ) +{ + int ret = 1; + unsigned char *cert_blob = NULL; + size_t cert_blob_size = 0; + + if( cert == NULL ) + { + ret = 2; + goto cleanup; + } + + if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, NULL, + &cert_blob_size ) != CKR_OK ) + { + ret = 3; + goto cleanup; + } + + cert_blob = polarssl_malloc( cert_blob_size ); + if( NULL == cert_blob ) + { + ret = 4; + goto cleanup; + } + + if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, cert_blob, + &cert_blob_size ) != CKR_OK ) + { + ret = 5; + goto cleanup; + } + + if( 0 != x509_crt_parse( cert, cert_blob, cert_blob_size ) ) + { + ret = 6; + goto cleanup; + } + + ret = 0; + +cleanup: + if( NULL != cert_blob ) + polarssl_free( cert_blob ); + + return( ret ); +} + + +int pkcs11_priv_key_init( pkcs11_context *priv_key, + pkcs11h_certificate_t pkcs11_cert ) +{ + int ret = 1; + x509_crt cert; + + x509_crt_init( &cert ); + + if( priv_key == NULL ) + goto cleanup; + + if( 0 != pkcs11_x509_cert_init( &cert, pkcs11_cert ) ) + goto cleanup; + + priv_key->len = pk_get_len( &cert.pk ); + priv_key->pkcs11h_cert = pkcs11_cert; + + ret = 0; + +cleanup: + x509_crt_free( &cert ); + + return( ret ); +} + +void pkcs11_priv_key_free( pkcs11_context *priv_key ) +{ + if( NULL != priv_key ) + pkcs11h_certificate_freeCertificate( priv_key->pkcs11h_cert ); +} + +int pkcs11_decrypt( pkcs11_context *ctx, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ) +{ + size_t input_len, output_len; + + if( NULL == ctx ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + if( RSA_PRIVATE != mode ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + output_len = input_len = ctx->len; + + if( input_len < 16 || input_len > output_max_len ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + /* Determine size of output buffer */ + if( pkcs11h_certificate_decryptAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, input, + input_len, NULL, &output_len ) != CKR_OK ) + { + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + } + + if( output_len > output_max_len ) + return( POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE ); + + if( pkcs11h_certificate_decryptAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, input, + input_len, output, &output_len ) != CKR_OK ) + { + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + } + *olen = output_len; + return( 0 ); +} + +int pkcs11_sign( pkcs11_context *ctx, + int mode, + md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ) +{ + size_t sig_len = 0, asn_len = 0, oid_size = 0; + unsigned char *p = sig; + const char *oid; + + if( NULL == ctx ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + if( RSA_PRIVATE != mode ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + if( md_alg != POLARSSL_MD_NONE ) + { + const md_info_t *md_info = md_info_from_type( md_alg ); + if( md_info == NULL ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + if( oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + hashlen = md_get_size( md_info ); + asn_len = 10 + oid_size; + } + + sig_len = ctx->len; + if( hashlen > sig_len || asn_len > sig_len || + hashlen + asn_len > sig_len ) + { + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + } + + if( md_alg != POLARSSL_MD_NONE ) + { + /* + * DigestInfo ::= SEQUENCE { + * digestAlgorithm DigestAlgorithmIdentifier, + * digest Digest } + * + * DigestAlgorithmIdentifier ::= AlgorithmIdentifier + * + * Digest ::= OCTET STRING + */ + *p++ = ASN1_SEQUENCE | ASN1_CONSTRUCTED; + *p++ = (unsigned char) ( 0x08 + oid_size + hashlen ); + *p++ = ASN1_SEQUENCE | ASN1_CONSTRUCTED; + *p++ = (unsigned char) ( 0x04 + oid_size ); + *p++ = ASN1_OID; + *p++ = oid_size & 0xFF; + memcpy( p, oid, oid_size ); + p += oid_size; + *p++ = ASN1_NULL; + *p++ = 0x00; + *p++ = ASN1_OCTET_STRING; + *p++ = hashlen; + } + + memcpy( p, hash, hashlen ); + + if( pkcs11h_certificate_signAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, sig, + asn_len + hashlen, sig, &sig_len ) != CKR_OK ) + { + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + } + + return( 0 ); +} + +#endif /* defined(POLARSSL_PKCS11_C) */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/pkcs12.c b/component/common/network/ssl/polarssl-1.3.8/library/pkcs12.c new file mode 100644 index 0000000..0cf2edf --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/pkcs12.c @@ -0,0 +1,360 @@ +/* + * PKCS#12 Personal Information Exchange Syntax + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * The PKCS #12 Personal Information Exchange Syntax Standard v1.1 + * + * http://www.rsa.com/rsalabs/pkcs/files/h11301-wp-pkcs-12v1-1-personal-information-exchange-syntax.pdf + * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1-1.asn + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_PKCS12_C) + +#include "polarssl/pkcs12.h" +#include "polarssl/asn1.h" +#include "polarssl/cipher.h" + +#if defined(POLARSSL_ARC4_C) +#include "polarssl/arc4.h" +#endif + +#if defined(POLARSSL_DES_C) +#include "polarssl/des.h" +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +static int pkcs12_parse_pbe_params( asn1_buf *params, + asn1_buf *salt, int *iterations ) +{ + int ret; + unsigned char **p = ¶ms->p; + const unsigned char *end = params->p + params->len; + + /* + * pkcs-12PbeParams ::= SEQUENCE { + * salt OCTET STRING, + * iterations INTEGER + * } + * + */ + if( params->tag != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) + return( POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT + + POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); + + if( ( ret = asn1_get_tag( p, end, &salt->len, ASN1_OCTET_STRING ) ) != 0 ) + return( POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT + ret ); + + salt->p = *p; + *p += salt->len; + + if( ( ret = asn1_get_int( p, end, iterations ) ) != 0 ) + return( POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT + ret ); + + if( *p != end ) + return( POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +static int pkcs12_pbe_derive_key_iv( asn1_buf *pbe_params, md_type_t md_type, + const unsigned char *pwd, size_t pwdlen, + unsigned char *key, size_t keylen, + unsigned char *iv, size_t ivlen ) +{ + int ret, iterations; + asn1_buf salt; + size_t i; + unsigned char unipwd[258]; + + memset( &salt, 0, sizeof(asn1_buf) ); + memset( &unipwd, 0, sizeof(unipwd) ); + + if( ( ret = pkcs12_parse_pbe_params( pbe_params, &salt, + &iterations ) ) != 0 ) + return( ret ); + + for( i = 0; i < pwdlen; i++ ) + unipwd[i * 2 + 1] = pwd[i]; + + if( ( ret = pkcs12_derivation( key, keylen, unipwd, pwdlen * 2 + 2, + salt.p, salt.len, md_type, + PKCS12_DERIVE_KEY, iterations ) ) != 0 ) + { + return( ret ); + } + + if( iv == NULL || ivlen == 0 ) + return( 0 ); + + if( ( ret = pkcs12_derivation( iv, ivlen, unipwd, pwdlen * 2 + 2, + salt.p, salt.len, md_type, + PKCS12_DERIVE_IV, iterations ) ) != 0 ) + { + return( ret ); + } + return( 0 ); +} + +int pkcs12_pbe_sha1_rc4_128( asn1_buf *pbe_params, int mode, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *data, size_t len, + unsigned char *output ) +{ +#if !defined(POLARSSL_ARC4_C) + ((void) pbe_params); + ((void) mode); + ((void) pwd); + ((void) pwdlen); + ((void) data); + ((void) len); + ((void) output); + return( POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE ); +#else + int ret; + unsigned char key[16]; + arc4_context ctx; + ((void) mode); + + arc4_init( &ctx ); + + if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, POLARSSL_MD_SHA1, + pwd, pwdlen, + key, 16, NULL, 0 ) ) != 0 ) + { + return( ret ); + } + + arc4_setup( &ctx, key, 16 ); + if( ( ret = arc4_crypt( &ctx, len, data, output ) ) != 0 ) + goto exit; + +exit: + polarssl_zeroize( key, sizeof( key ) ); + arc4_free( &ctx ); + + return( ret ); +#endif /* POLARSSL_ARC4_C */ +} + +int pkcs12_pbe( asn1_buf *pbe_params, int mode, + cipher_type_t cipher_type, md_type_t md_type, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *data, size_t len, + unsigned char *output ) +{ + int ret, keylen = 0; + unsigned char key[32]; + unsigned char iv[16]; + const cipher_info_t *cipher_info; + cipher_context_t cipher_ctx; + size_t olen = 0; + + cipher_info = cipher_info_from_type( cipher_type ); + if( cipher_info == NULL ) + return( POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE ); + + keylen = cipher_info->key_length / 8; + + if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, md_type, pwd, pwdlen, + key, keylen, + iv, cipher_info->iv_size ) ) != 0 ) + { + return( ret ); + } + + cipher_init( &cipher_ctx ); + + if( ( ret = cipher_init_ctx( &cipher_ctx, cipher_info ) ) != 0 ) + goto exit; + + if( ( ret = cipher_setkey( &cipher_ctx, key, 8 * keylen, mode ) ) != 0 ) + goto exit; + + if( ( ret = cipher_set_iv( &cipher_ctx, iv, cipher_info->iv_size ) ) != 0 ) + goto exit; + + if( ( ret = cipher_reset( &cipher_ctx ) ) != 0 ) + goto exit; + + if( ( ret = cipher_update( &cipher_ctx, data, len, + output, &olen ) ) != 0 ) + { + goto exit; + } + + if( ( ret = cipher_finish( &cipher_ctx, output + olen, &olen ) ) != 0 ) + ret = POLARSSL_ERR_PKCS12_PASSWORD_MISMATCH; + +exit: + polarssl_zeroize( key, sizeof( key ) ); + polarssl_zeroize( iv, sizeof( iv ) ); + cipher_free( &cipher_ctx ); + + return( ret ); +} + +static void pkcs12_fill_buffer( unsigned char *data, size_t data_len, + const unsigned char *filler, size_t fill_len ) +{ + unsigned char *p = data; + size_t use_len; + + while( data_len > 0 ) + { + use_len = ( data_len > fill_len ) ? fill_len : data_len; + memcpy( p, filler, use_len ); + p += use_len; + data_len -= use_len; + } +} + +int pkcs12_derivation( unsigned char *data, size_t datalen, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *salt, size_t saltlen, + md_type_t md_type, int id, int iterations ) +{ + int ret; + unsigned int j; + + unsigned char diversifier[128]; + unsigned char salt_block[128], pwd_block[128], hash_block[128]; + unsigned char hash_output[POLARSSL_MD_MAX_SIZE]; + unsigned char *p; + unsigned char c; + + size_t hlen, use_len, v, i; + + const md_info_t *md_info; + md_context_t md_ctx; + + // This version only allows max of 64 bytes of password or salt + if( datalen > 128 || pwdlen > 64 || saltlen > 64 ) + return( POLARSSL_ERR_PKCS12_BAD_INPUT_DATA ); + + md_info = md_info_from_type( md_type ); + if( md_info == NULL ) + return( POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE ); + + md_init( &md_ctx ); + + if( ( ret = md_init_ctx( &md_ctx, md_info ) ) != 0 ) + return( ret ); + hlen = md_get_size( md_info ); + + if( hlen <= 32 ) + v = 64; + else + v = 128; + + memset( diversifier, (unsigned char) id, v ); + + pkcs12_fill_buffer( salt_block, v, salt, saltlen ); + pkcs12_fill_buffer( pwd_block, v, pwd, pwdlen ); + + p = data; + while( datalen > 0 ) + { + // Calculate hash( diversifier || salt_block || pwd_block ) + if( ( ret = md_starts( &md_ctx ) ) != 0 ) + goto exit; + + if( ( ret = md_update( &md_ctx, diversifier, v ) ) != 0 ) + goto exit; + + if( ( ret = md_update( &md_ctx, salt_block, v ) ) != 0 ) + goto exit; + + if( ( ret = md_update( &md_ctx, pwd_block, v ) ) != 0 ) + goto exit; + + if( ( ret = md_finish( &md_ctx, hash_output ) ) != 0 ) + goto exit; + + // Perform remaining ( iterations - 1 ) recursive hash calculations + for( i = 1; i < (size_t) iterations; i++ ) + { + if( ( ret = md( md_info, hash_output, hlen, hash_output ) ) != 0 ) + goto exit; + } + + use_len = ( datalen > hlen ) ? hlen : datalen; + memcpy( p, hash_output, use_len ); + datalen -= use_len; + p += use_len; + + if( datalen == 0 ) + break; + + // Concatenating copies of hash_output into hash_block (B) + pkcs12_fill_buffer( hash_block, v, hash_output, hlen ); + + // B += 1 + for( i = v; i > 0; i-- ) + if( ++hash_block[i - 1] != 0 ) + break; + + // salt_block += B + c = 0; + for( i = v; i > 0; i-- ) + { + j = salt_block[i - 1] + hash_block[i - 1] + c; + c = (unsigned char) (j >> 8); + salt_block[i - 1] = j & 0xFF; + } + + // pwd_block += B + c = 0; + for( i = v; i > 0; i-- ) + { + j = pwd_block[i - 1] + hash_block[i - 1] + c; + c = (unsigned char) (j >> 8); + pwd_block[i - 1] = j & 0xFF; + } + } + + ret = 0; + +exit: + polarssl_zeroize( salt_block, sizeof( salt_block ) ); + polarssl_zeroize( pwd_block, sizeof( pwd_block ) ); + polarssl_zeroize( hash_block, sizeof( hash_block ) ); + polarssl_zeroize( hash_output, sizeof( hash_output ) ); + + md_free( &md_ctx ); + + return( ret ); +} + +#endif /* POLARSSL_PKCS12_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/pkcs5.c b/component/common/network/ssl/polarssl-1.3.8/library/pkcs5.c new file mode 100644 index 0000000..e769783 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/pkcs5.c @@ -0,0 +1,417 @@ +/** + * \file pkcs5.c + * + * \brief PKCS#5 functions + * + * \author Mathias Olsson + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * PKCS#5 includes PBKDF2 and more + * + * http://tools.ietf.org/html/rfc2898 (Specification) + * http://tools.ietf.org/html/rfc6070 (Test vectors) + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_PKCS5_C) + +#include "polarssl/pkcs5.h" +#include "polarssl/asn1.h" +#include "polarssl/cipher.h" +#include "polarssl/oid.h" + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#define polarssl_printf printf +#endif + +static int pkcs5_parse_pbkdf2_params( const asn1_buf *params, + asn1_buf *salt, int *iterations, + int *keylen, md_type_t *md_type ) +{ + int ret; + asn1_buf prf_alg_oid; + unsigned char *p = params->p; + const unsigned char *end = params->p + params->len; + + if( params->tag != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) + return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + + POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); + /* + * PBKDF2-params ::= SEQUENCE { + * salt OCTET STRING, + * iterationCount INTEGER, + * keyLength INTEGER OPTIONAL + * prf AlgorithmIdentifier DEFAULT algid-hmacWithSHA1 + * } + * + */ + if( ( ret = asn1_get_tag( &p, end, &salt->len, ASN1_OCTET_STRING ) ) != 0 ) + return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret ); + + salt->p = p; + p += salt->len; + + if( ( ret = asn1_get_int( &p, end, iterations ) ) != 0 ) + return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret ); + + if( p == end ) + return( 0 ); + + if( ( ret = asn1_get_int( &p, end, keylen ) ) != 0 ) + { + if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) + return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret ); + } + + if( p == end ) + return( 0 ); + + if( ( ret = asn1_get_alg_null( &p, end, &prf_alg_oid ) ) != 0 ) + return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret ); + + if( !OID_CMP( OID_HMAC_SHA1, &prf_alg_oid ) ) + return( POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + *md_type = POLARSSL_MD_SHA1; + + if( p != end ) + return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +int pkcs5_pbes2( asn1_buf *pbe_params, int mode, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *data, size_t datalen, + unsigned char *output ) +{ + int ret, iterations = 0, keylen = 0; + unsigned char *p, *end; + asn1_buf kdf_alg_oid, enc_scheme_oid, kdf_alg_params, enc_scheme_params; + asn1_buf salt; + md_type_t md_type = POLARSSL_MD_SHA1; + unsigned char key[32], iv[32]; + size_t olen = 0; + const md_info_t *md_info; + const cipher_info_t *cipher_info; + md_context_t md_ctx; + cipher_type_t cipher_alg; + cipher_context_t cipher_ctx; + + p = pbe_params->p; + end = p + pbe_params->len; + + /* + * PBES2-params ::= SEQUENCE { + * keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}}, + * encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} + * } + */ + if( pbe_params->tag != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) + return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + + POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); + + if( ( ret = asn1_get_alg( &p, end, &kdf_alg_oid, &kdf_alg_params ) ) != 0 ) + return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret ); + + // Only PBKDF2 supported at the moment + // + if( !OID_CMP( OID_PKCS5_PBKDF2, &kdf_alg_oid ) ) + return( POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + if( ( ret = pkcs5_parse_pbkdf2_params( &kdf_alg_params, + &salt, &iterations, &keylen, + &md_type ) ) != 0 ) + { + return( ret ); + } + + md_info = md_info_from_type( md_type ); + if( md_info == NULL ) + return( POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + if( ( ret = asn1_get_alg( &p, end, &enc_scheme_oid, + &enc_scheme_params ) ) != 0 ) + { + return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret ); + } + + if( oid_get_cipher_alg( &enc_scheme_oid, &cipher_alg ) != 0 ) + return( POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + cipher_info = cipher_info_from_type( cipher_alg ); + if( cipher_info == NULL ) + return( POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + /* + * The value of keylen from pkcs5_parse_pbkdf2_params() is ignored + * since it is optional and we don't know if it was set or not + */ + keylen = cipher_info->key_length / 8; + + if( enc_scheme_params.tag != ASN1_OCTET_STRING || + enc_scheme_params.len != cipher_info->iv_size ) + { + return( POLARSSL_ERR_PKCS5_INVALID_FORMAT ); + } + + md_init( &md_ctx ); + cipher_init( &cipher_ctx ); + + memcpy( iv, enc_scheme_params.p, enc_scheme_params.len ); + + if( ( ret = md_init_ctx( &md_ctx, md_info ) ) != 0 ) + goto exit; + + if( ( ret = pkcs5_pbkdf2_hmac( &md_ctx, pwd, pwdlen, salt.p, salt.len, + iterations, keylen, key ) ) != 0 ) + { + goto exit; + } + + if( ( ret = cipher_init_ctx( &cipher_ctx, cipher_info ) ) != 0 ) + goto exit; + + if( ( ret = cipher_setkey( &cipher_ctx, key, 8 * keylen, mode ) ) != 0 ) + goto exit; + + if( ( ret = cipher_crypt( &cipher_ctx, iv, enc_scheme_params.len, + data, datalen, output, &olen ) ) != 0 ) + ret = POLARSSL_ERR_PKCS5_PASSWORD_MISMATCH; + +exit: + md_free( &md_ctx ); + cipher_free( &cipher_ctx ); + + return( ret ); +} + +int pkcs5_pbkdf2_hmac( md_context_t *ctx, const unsigned char *password, + size_t plen, const unsigned char *salt, size_t slen, + unsigned int iteration_count, + uint32_t key_length, unsigned char *output ) +{ + int ret, j; + unsigned int i; + unsigned char md1[POLARSSL_MD_MAX_SIZE]; + unsigned char work[POLARSSL_MD_MAX_SIZE]; + unsigned char md_size = md_get_size( ctx->md_info ); + size_t use_len; + unsigned char *out_p = output; + unsigned char counter[4]; + + memset( counter, 0, 4 ); + counter[3] = 1; + + if( iteration_count > 0xFFFFFFFF ) + return( POLARSSL_ERR_PKCS5_BAD_INPUT_DATA ); + + while( key_length ) + { + // U1 ends up in work + // + if( ( ret = md_hmac_starts( ctx, password, plen ) ) != 0 ) + return( ret ); + + if( ( ret = md_hmac_update( ctx, salt, slen ) ) != 0 ) + return( ret ); + + if( ( ret = md_hmac_update( ctx, counter, 4 ) ) != 0 ) + return( ret ); + + if( ( ret = md_hmac_finish( ctx, work ) ) != 0 ) + return( ret ); + + memcpy( md1, work, md_size ); + + for( i = 1; i < iteration_count; i++ ) + { + // U2 ends up in md1 + // + if( ( ret = md_hmac_starts( ctx, password, plen ) ) != 0 ) + return( ret ); + + if( ( ret = md_hmac_update( ctx, md1, md_size ) ) != 0 ) + return( ret ); + + if( ( ret = md_hmac_finish( ctx, md1 ) ) != 0 ) + return( ret ); + + // U1 xor U2 + // + for( j = 0; j < md_size; j++ ) + work[j] ^= md1[j]; + } + + use_len = ( key_length < md_size ) ? key_length : md_size; + memcpy( out_p, work, use_len ); + + key_length -= (uint32_t) use_len; + out_p += use_len; + + for( i = 4; i > 0; i-- ) + if( ++counter[i - 1] != 0 ) + break; + } + + return( 0 ); +} + +#if defined(POLARSSL_SELF_TEST) + +#if !defined(POLARSSL_SHA1_C) +int pkcs5_self_test( int verbose ) +{ + if( verbose != 0 ) + polarssl_printf( " PBKDF2 (SHA1): skipped\n\n" ); + + return( 0 ); +} +#else + +#include + +#define MAX_TESTS 6 + +size_t plen[MAX_TESTS] = + { 8, 8, 8, 8, 24, 9 }; + +unsigned char password[MAX_TESTS][32] = +{ + "password", + "password", + "password", + "password", + "passwordPASSWORDpassword", + "pass\0word", +}; + +size_t slen[MAX_TESTS] = + { 4, 4, 4, 4, 36, 5 }; + +unsigned char salt[MAX_TESTS][40] = +{ + "salt", + "salt", + "salt", + "salt", + "saltSALTsaltSALTsaltSALTsaltSALTsalt", + "sa\0lt", +}; + +uint32_t it_cnt[MAX_TESTS] = + { 1, 2, 4096, 16777216, 4096, 4096 }; + +uint32_t key_len[MAX_TESTS] = + { 20, 20, 20, 20, 25, 16 }; + + +unsigned char result_key[MAX_TESTS][32] = +{ + { 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71, + 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06, + 0x2f, 0xe0, 0x37, 0xa6 }, + { 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c, + 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0, + 0xd8, 0xde, 0x89, 0x57 }, + { 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a, + 0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0, + 0x65, 0xa4, 0x29, 0xc1 }, + { 0xee, 0xfe, 0x3d, 0x61, 0xcd, 0x4d, 0xa4, 0xe4, + 0xe9, 0x94, 0x5b, 0x3d, 0x6b, 0xa2, 0x15, 0x8c, + 0x26, 0x34, 0xe9, 0x84 }, + { 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b, + 0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a, + 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70, + 0x38 }, + { 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d, + 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3 }, +}; + +int pkcs5_self_test( int verbose ) +{ + md_context_t sha1_ctx; + const md_info_t *info_sha1; + int ret, i; + unsigned char key[64]; + + md_init( &sha1_ctx ); + + info_sha1 = md_info_from_type( POLARSSL_MD_SHA1 ); + if( info_sha1 == NULL ) + { + ret = 1; + goto exit; + } + + if( ( ret = md_init_ctx( &sha1_ctx, info_sha1 ) ) != 0 ) + { + ret = 1; + goto exit; + } + + if( verbose != 0 ) + polarssl_printf( " PBKDF2 note: test #3 may be slow!\n" ); + + for( i = 0; i < MAX_TESTS; i++ ) + { + if( verbose != 0 ) + polarssl_printf( " PBKDF2 (SHA1) #%d: ", i ); + + ret = pkcs5_pbkdf2_hmac( &sha1_ctx, password[i], plen[i], salt[i], + slen[i], it_cnt[i], key_len[i], key ); + if( ret != 0 || + memcmp( result_key[i], key, key_len[i] ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + polarssl_printf( "\n" ); + +exit: + md_free( &sha1_ctx ); + + return( 0 ); +} +#endif /* POLARSSL_SHA1_C */ + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_PKCS5_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/pkparse.c b/component/common/network/ssl/polarssl-1.3.8/library/pkparse.c new file mode 100644 index 0000000..29217a2 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/pkparse.c @@ -0,0 +1,1256 @@ +/* + * Public Key layer for parsing key files and structures + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_PK_PARSE_C) + +#include "polarssl/pk.h" +#include "polarssl/asn1.h" +#include "polarssl/oid.h" + +#if defined(POLARSSL_RSA_C) +#include "polarssl/rsa.h" +#endif +#if defined(POLARSSL_ECP_C) +#include "polarssl/ecp.h" +#endif +#if defined(POLARSSL_ECDSA_C) +#include "polarssl/ecdsa.h" +#endif +#if defined(POLARSSL_PEM_PARSE_C) +#include "polarssl/pem.h" +#endif +#if defined(POLARSSL_PKCS5_C) +#include "polarssl/pkcs5.h" +#endif +#if defined(POLARSSL_PKCS12_C) +#include "polarssl/pkcs12.h" +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include +#define polarssl_malloc malloc +#define polarssl_free free +#endif + +#if defined(POLARSSL_FS_IO) +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * Load all data from a file into a given buffer. + */ +static int load_file( const char *path, unsigned char **buf, size_t *n ) +{ + FILE *f; + long size; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( POLARSSL_ERR_PK_FILE_IO_ERROR ); + + fseek( f, 0, SEEK_END ); + if( ( size = ftell( f ) ) == -1 ) + { + fclose( f ); + return( POLARSSL_ERR_PK_FILE_IO_ERROR ); + } + fseek( f, 0, SEEK_SET ); + + *n = (size_t) size; + + if( *n + 1 == 0 || + ( *buf = (unsigned char *) polarssl_malloc( *n + 1 ) ) == NULL ) + { + fclose( f ); + return( POLARSSL_ERR_PK_MALLOC_FAILED ); + } + + if( fread( *buf, 1, *n, f ) != *n ) + { + fclose( f ); + polarssl_free( *buf ); + return( POLARSSL_ERR_PK_FILE_IO_ERROR ); + } + + fclose( f ); + + (*buf)[*n] = '\0'; + + return( 0 ); +} + +/* + * Load and parse a private key + */ +int pk_parse_keyfile( pk_context *ctx, + const char *path, const char *pwd ) +{ + int ret; + size_t n; + unsigned char *buf; + + if( ( ret = load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + if( pwd == NULL ) + ret = pk_parse_key( ctx, buf, n, NULL, 0 ); + else + ret = pk_parse_key( ctx, buf, n, + (const unsigned char *) pwd, strlen( pwd ) ); + + polarssl_zeroize( buf, n + 1 ); + polarssl_free( buf ); + + return( ret ); +} + +/* + * Load and parse a public key + */ +int pk_parse_public_keyfile( pk_context *ctx, const char *path ) +{ + int ret; + size_t n; + unsigned char *buf; + + if( ( ret = load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = pk_parse_public_key( ctx, buf, n ); + + polarssl_zeroize( buf, n + 1 ); + polarssl_free( buf ); + + return( ret ); +} +#endif /* POLARSSL_FS_IO */ + +#if defined(POLARSSL_ECP_C) +/* Minimally parse an ECParameters buffer to and asn1_buf + * + * ECParameters ::= CHOICE { + * namedCurve OBJECT IDENTIFIER + * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } + * -- implicitCurve NULL + * } + */ +static int pk_get_ecparams( unsigned char **p, const unsigned char *end, + asn1_buf *params ) +{ + int ret; + + /* Tag may be either OID or SEQUENCE */ + params->tag = **p; + if( params->tag != ASN1_OID +#if defined(POLARSSL_PK_PARSE_EC_EXTENDED) + && params->tag != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) +#endif + ) + { + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + + POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); + } + + if( ( ret = asn1_get_tag( p, end, ¶ms->len, params->tag ) ) != 0 ) + { + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + params->p = *p; + *p += params->len; + + if( *p != end ) + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +#if defined(POLARSSL_PK_PARSE_EC_EXTENDED) +/* + * Parse a SpecifiedECDomain (SEC 1 C.2) and (mostly) fill the group with it. + * WARNING: the resulting group should only be used with + * pk_group_id_from_specified(), since its base point may not be set correctly + * if it was encoded compressed. + * + * SpecifiedECDomain ::= SEQUENCE { + * version SpecifiedECDomainVersion(ecdpVer1 | ecdpVer2 | ecdpVer3, ...), + * fieldID FieldID {{FieldTypes}}, + * curve Curve, + * base ECPoint, + * order INTEGER, + * cofactor INTEGER OPTIONAL, + * hash HashAlgorithm OPTIONAL, + * ... + * } + * + * We only support prime-field as field type, and ignore hash and cofactor. + */ +static int pk_group_from_specified( const asn1_buf *params, ecp_group *grp ) +{ + int ret; + unsigned char *p = params->p; + const unsigned char * const end = params->p + params->len; + const unsigned char *end_field, *end_curve; + size_t len; + int ver; + + /* SpecifiedECDomainVersion ::= INTEGER { 1, 2, 3 } */ + if( ( ret = asn1_get_int( &p, end, &ver ) ) != 0 ) + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( ver < 1 || ver > 3 ) + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT ); + + /* + * FieldID { FIELD-ID:IOSet } ::= SEQUENCE { -- Finite field + * fieldType FIELD-ID.&id({IOSet}), + * parameters FIELD-ID.&Type({IOSet}{@fieldType}) + * } + */ + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + end_field = p + len; + + /* + * FIELD-ID ::= TYPE-IDENTIFIER + * FieldTypes FIELD-ID ::= { + * { Prime-p IDENTIFIED BY prime-field } | + * { Characteristic-two IDENTIFIED BY characteristic-two-field } + * } + * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } + */ + if( ( ret = asn1_get_tag( &p, end_field, &len, ASN1_OID ) ) != 0 ) + return( ret ); + + if( len != OID_SIZE( OID_ANSI_X9_62_PRIME_FIELD ) || + memcmp( p, OID_ANSI_X9_62_PRIME_FIELD, len ) != 0 ) + { + return( POLARSSL_ERR_PK_FEATURE_UNAVAILABLE ); + } + + p += len; + + /* Prime-p ::= INTEGER -- Field of size p. */ + if( ( ret = asn1_get_mpi( &p, end_field, &grp->P ) ) != 0 ) + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + + grp->pbits = mpi_msb( &grp->P ); + + if( p != end_field ) + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + /* + * Curve ::= SEQUENCE { + * a FieldElement, + * b FieldElement, + * seed BIT STRING OPTIONAL + * -- Shall be present if used in SpecifiedECDomain + * -- with version equal to ecdpVer2 or ecdpVer3 + * } + */ + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + end_curve = p + len; + + /* + * FieldElement ::= OCTET STRING + * containing an integer in the case of a prime field + */ + if( ( ret = asn1_get_tag( &p, end_curve, &len, ASN1_OCTET_STRING ) ) != 0 || + ( ret = mpi_read_binary( &grp->A, p, len ) ) != 0 ) + { + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + p += len; + + if( ( ret = asn1_get_tag( &p, end_curve, &len, ASN1_OCTET_STRING ) ) != 0 || + ( ret = mpi_read_binary( &grp->B, p, len ) ) != 0 ) + { + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + p += len; + + /* Ignore seed BIT STRING OPTIONAL */ + if( ( ret = asn1_get_tag( &p, end_curve, &len, ASN1_BIT_STRING ) ) == 0 ) + p += len; + + if( p != end_curve ) + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + /* + * ECPoint ::= OCTET STRING + */ + if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 ) + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( ( ret = ecp_point_read_binary( grp, &grp->G, + ( const unsigned char *) p, len ) ) != 0 ) + { + /* + * If we can't read the point because it's compressed, cheat by + * reading only the X coordinate and the parity bit of Y. + */ + if( ret != POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE || + ( p[0] != 0x02 && p[0] != 0x03 ) || + len != mpi_size( &grp->P ) + 1 || + mpi_read_binary( &grp->G.X, p + 1, len - 1 ) != 0 || + mpi_lset( &grp->G.Y, p[0] - 2 ) != 0 || + mpi_lset( &grp->G.Z, 1 ) != 0 ) + { + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT ); + } + } + + p += len; + + /* + * order INTEGER + */ + if( ( ret = asn1_get_mpi( &p, end, &grp->N ) ) ) + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + + grp->nbits = mpi_msb( &grp->N ); + + /* + * Allow optional elements by purposefully not enforcing p == end here. + */ + + return( 0 ); +} + +/* + * Find the group id associated with an (almost filled) group as generated by + * pk_group_from_specified(), or return an error if unknown. + */ +static int pk_group_id_from_group( const ecp_group *grp, ecp_group_id *grp_id ) +{ + int ret = 0; + ecp_group ref; + const ecp_group_id *id; + + ecp_group_init( &ref ); + + for( id = ecp_grp_id_list(); *id != POLARSSL_ECP_DP_NONE; id++ ) + { + /* Load the group associated to that id */ + ecp_group_free( &ref ); + MPI_CHK( ecp_use_known_dp( &ref, *id ) ); + + /* Compare to the group we were given, starting with easy tests */ + if( grp->pbits == ref.pbits && grp->nbits == ref.nbits && + mpi_cmp_mpi( &grp->P, &ref.P ) == 0 && + mpi_cmp_mpi( &grp->A, &ref.A ) == 0 && + mpi_cmp_mpi( &grp->B, &ref.B ) == 0 && + mpi_cmp_mpi( &grp->N, &ref.N ) == 0 && + mpi_cmp_mpi( &grp->G.X, &ref.G.X ) == 0 && + mpi_cmp_mpi( &grp->G.Z, &ref.G.Z ) == 0 && + /* For Y we may only know the parity bit, so compare only that */ + mpi_get_bit( &grp->G.Y, 0 ) == mpi_get_bit( &ref.G.Y, 0 ) ) + { + break; + } + + } + +cleanup: + ecp_group_free( &ref ); + + *grp_id = *id; + + if( ret == 0 && *id == POLARSSL_ECP_DP_NONE ) + ret = POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE; + + return( ret ); +} + +/* + * Parse a SpecifiedECDomain (SEC 1 C.2) and find the associated group ID + */ +static int pk_group_id_from_specified( const asn1_buf *params, + ecp_group_id *grp_id ) +{ + int ret; + ecp_group grp; + + ecp_group_init( &grp ); + + if( ( ret = pk_group_from_specified( params, &grp ) ) != 0 ) + goto cleanup; + + ret = pk_group_id_from_group( &grp, grp_id ); + +cleanup: + ecp_group_free( &grp ); + + return( ret ); +} +#endif /* POLARSSL_PK_PARSE_EC_EXTENDED */ + +/* + * Use EC parameters to initialise an EC group + * + * ECParameters ::= CHOICE { + * namedCurve OBJECT IDENTIFIER + * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } + * -- implicitCurve NULL + */ +static int pk_use_ecparams( const asn1_buf *params, ecp_group *grp ) +{ + int ret; + ecp_group_id grp_id; + + if( params->tag == ASN1_OID ) + { + if( oid_get_ec_grp( params, &grp_id ) != 0 ) + return( POLARSSL_ERR_PK_UNKNOWN_NAMED_CURVE ); + } + else + { +#if defined(POLARSSL_PK_PARSE_EC_EXTENDED) + if( ( ret = pk_group_id_from_specified( params, &grp_id ) ) != 0 ) + return( ret ); +#else + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT ); +#endif + } + + /* + * grp may already be initilialized; if so, make sure IDs match + */ + if( grp->id != POLARSSL_ECP_DP_NONE && grp->id != grp_id ) + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT ); + + if( ( ret = ecp_use_known_dp( grp, grp_id ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * EC public key is an EC point + * + * The caller is responsible for clearing the structure upon failure if + * desired. Take care to pass along the possible ECP_FEATURE_UNAVAILABLE + * return code of ecp_point_read_binary() and leave p in a usable state. + */ +static int pk_get_ecpubkey( unsigned char **p, const unsigned char *end, + ecp_keypair *key ) +{ + int ret; + + if( ( ret = ecp_point_read_binary( &key->grp, &key->Q, + (const unsigned char *) *p, end - *p ) ) == 0 ) + { + ret = ecp_check_pubkey( &key->grp, &key->Q ); + } + + /* + * We know ecp_point_read_binary consumed all bytes or failed + */ + *p = (unsigned char *) end; + + return( ret ); +} +#endif /* POLARSSL_ECP_C */ + +#if defined(POLARSSL_RSA_C) +/* + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER -- e + * } + */ +static int pk_get_rsapubkey( unsigned char **p, + const unsigned char *end, + rsa_context *rsa ) +{ + int ret; + size_t len; + + if( ( ret = asn1_get_tag( p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + return( POLARSSL_ERR_PK_INVALID_PUBKEY + ret ); + + if( *p + len != end ) + return( POLARSSL_ERR_PK_INVALID_PUBKEY + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + if( ( ret = asn1_get_mpi( p, end, &rsa->N ) ) != 0 || + ( ret = asn1_get_mpi( p, end, &rsa->E ) ) != 0 ) + return( POLARSSL_ERR_PK_INVALID_PUBKEY + ret ); + + if( *p != end ) + return( POLARSSL_ERR_PK_INVALID_PUBKEY + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + if( ( ret = rsa_check_pubkey( rsa ) ) != 0 ) + return( POLARSSL_ERR_PK_INVALID_PUBKEY ); + + rsa->len = mpi_size( &rsa->N ); + + return( 0 ); +} +#endif /* POLARSSL_RSA_C */ + +/* Get a PK algorithm identifier + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + */ +static int pk_get_pk_alg( unsigned char **p, + const unsigned char *end, + pk_type_t *pk_alg, asn1_buf *params ) +{ + int ret; + asn1_buf alg_oid; + + memset( params, 0, sizeof(asn1_buf) ); + + if( ( ret = asn1_get_alg( p, end, &alg_oid, params ) ) != 0 ) + return( POLARSSL_ERR_PK_INVALID_ALG + ret ); + + if( oid_get_pk_alg( &alg_oid, pk_alg ) != 0 ) + return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG ); + + /* + * No parameters with RSA (only for EC) + */ + if( *pk_alg == POLARSSL_PK_RSA && + ( ( params->tag != ASN1_NULL && params->tag != 0 ) || + params->len != 0 ) ) + { + return( POLARSSL_ERR_PK_INVALID_ALG ); + } + + return( 0 ); +} + +/* + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } + */ +int pk_parse_subpubkey( unsigned char **p, const unsigned char *end, + pk_context *pk ) +{ + int ret; + size_t len; + asn1_buf alg_params; + pk_type_t pk_alg = POLARSSL_PK_NONE; + const pk_info_t *pk_info; + + if( ( ret = asn1_get_tag( p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + end = *p + len; + + if( ( ret = pk_get_pk_alg( p, end, &pk_alg, &alg_params ) ) != 0 ) + return( ret ); + + if( ( ret = asn1_get_bitstring_null( p, end, &len ) ) != 0 ) + return( POLARSSL_ERR_PK_INVALID_PUBKEY + ret ); + + if( *p + len != end ) + return( POLARSSL_ERR_PK_INVALID_PUBKEY + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + if( ( pk_info = pk_info_from_type( pk_alg ) ) == NULL ) + return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = pk_init_ctx( pk, pk_info ) ) != 0 ) + return( ret ); + +#if defined(POLARSSL_RSA_C) + if( pk_alg == POLARSSL_PK_RSA ) + { + ret = pk_get_rsapubkey( p, end, pk_rsa( *pk ) ); + } else +#endif /* POLARSSL_RSA_C */ +#if defined(POLARSSL_ECP_C) + if( pk_alg == POLARSSL_PK_ECKEY_DH || pk_alg == POLARSSL_PK_ECKEY ) + { + ret = pk_use_ecparams( &alg_params, &pk_ec( *pk )->grp ); + if( ret == 0 ) + ret = pk_get_ecpubkey( p, end, pk_ec( *pk ) ); + } else +#endif /* POLARSSL_ECP_C */ + ret = POLARSSL_ERR_PK_UNKNOWN_PK_ALG; + + if( ret == 0 && *p != end ) + ret = POLARSSL_ERR_PK_INVALID_PUBKEY + POLARSSL_ERR_ASN1_LENGTH_MISMATCH; + + if( ret != 0 ) + pk_free( pk ); + + return( ret ); +} + +#if defined(POLARSSL_RSA_C) +/* + * Parse a PKCS#1 encoded private RSA key + */ +static int pk_parse_key_pkcs1_der( rsa_context *rsa, + const unsigned char *key, + size_t keylen ) +{ + int ret; + size_t len; + unsigned char *p, *end; + + p = (unsigned char *) key; + end = p + keylen; + + /* + * This function parses the RSAPrivateKey (PKCS#1) + * + * RSAPrivateKey ::= SEQUENCE { + * version Version, + * modulus INTEGER, -- n + * publicExponent INTEGER, -- e + * privateExponent INTEGER, -- d + * prime1 INTEGER, -- p + * prime2 INTEGER, -- q + * exponent1 INTEGER, -- d mod (p-1) + * exponent2 INTEGER, -- d mod (q-1) + * coefficient INTEGER, -- (inverse of q) mod p + * otherPrimeInfos OtherPrimeInfos OPTIONAL + * } + */ + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + end = p + len; + + if( ( ret = asn1_get_int( &p, end, &rsa->ver ) ) != 0 ) + { + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + if( rsa->ver != 0 ) + { + return( POLARSSL_ERR_PK_KEY_INVALID_VERSION ); + } + + if( ( ret = asn1_get_mpi( &p, end, &rsa->N ) ) != 0 || + ( ret = asn1_get_mpi( &p, end, &rsa->E ) ) != 0 || + ( ret = asn1_get_mpi( &p, end, &rsa->D ) ) != 0 || + ( ret = asn1_get_mpi( &p, end, &rsa->P ) ) != 0 || + ( ret = asn1_get_mpi( &p, end, &rsa->Q ) ) != 0 || + ( ret = asn1_get_mpi( &p, end, &rsa->DP ) ) != 0 || + ( ret = asn1_get_mpi( &p, end, &rsa->DQ ) ) != 0 || + ( ret = asn1_get_mpi( &p, end, &rsa->QP ) ) != 0 ) + { + rsa_free( rsa ); + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + rsa->len = mpi_size( &rsa->N ); + + if( p != end ) + { + rsa_free( rsa ); + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + } + + if( ( ret = rsa_check_privkey( rsa ) ) != 0 ) + { + rsa_free( rsa ); + return( ret ); + } + + return( 0 ); +} +#endif /* POLARSSL_RSA_C */ + +#if defined(POLARSSL_ECP_C) +/* + * Parse a SEC1 encoded private EC key + */ +static int pk_parse_key_sec1_der( ecp_keypair *eck, + const unsigned char *key, + size_t keylen ) +{ + int ret; + int version, pubkey_done; + size_t len; + asn1_buf params; + unsigned char *p = (unsigned char *) key; + unsigned char *end = p + keylen; + unsigned char *end2; + + /* + * RFC 5915, or SEC1 Appendix C.4 + * + * ECPrivateKey ::= SEQUENCE { + * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), + * privateKey OCTET STRING, + * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, + * publicKey [1] BIT STRING OPTIONAL + * } + */ + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + end = p + len; + + if( ( ret = asn1_get_int( &p, end, &version ) ) != 0 ) + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( version != 1 ) + return( POLARSSL_ERR_PK_KEY_INVALID_VERSION ); + + if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 ) + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( ( ret = mpi_read_binary( &eck->d, p, len ) ) != 0 ) + { + ecp_keypair_free( eck ); + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + p += len; + + /* + * Is 'parameters' present? + */ + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ) == 0 ) + { + if( ( ret = pk_get_ecparams( &p, p + len, ¶ms) ) != 0 || + ( ret = pk_use_ecparams( ¶ms, &eck->grp ) ) != 0 ) + { + ecp_keypair_free( eck ); + return( ret ); + } + } + else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) + { + ecp_keypair_free( eck ); + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + /* + * Is 'publickey' present? If not, or if we can't read it (eg because it + * is compressed), create it from the private key. + */ + pubkey_done = 0; + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1 ) ) == 0 ) + { + end2 = p + len; + + if( ( ret = asn1_get_bitstring_null( &p, end2, &len ) ) != 0 ) + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( p + len != end2 ) + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + if( ( ret = pk_get_ecpubkey( &p, end2, eck ) ) == 0 ) + pubkey_done = 1; + else + { + /* + * The only acceptable failure mode of pk_get_ecpubkey() above + * is if the point format is not recognized. + */ + if( ret != POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE ) + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT ); + } + } + else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) + { + ecp_keypair_free( eck ); + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + if( ! pubkey_done && + ( ret = ecp_mul( &eck->grp, &eck->Q, &eck->d, &eck->grp.G, + NULL, NULL ) ) != 0 ) + { + ecp_keypair_free( eck ); + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + if( ( ret = ecp_check_privkey( &eck->grp, &eck->d ) ) != 0 ) + { + ecp_keypair_free( eck ); + return( ret ); + } + + return( 0 ); +} +#endif /* POLARSSL_ECP_C */ + +/* + * Parse an unencrypted PKCS#8 encoded private key + */ +static int pk_parse_key_pkcs8_unencrypted_der( + pk_context *pk, + const unsigned char* key, + size_t keylen ) +{ + int ret, version; + size_t len; + asn1_buf params; + unsigned char *p = (unsigned char *) key; + unsigned char *end = p + keylen; + pk_type_t pk_alg = POLARSSL_PK_NONE; + const pk_info_t *pk_info; + + /* + * This function parses the PrivatKeyInfo object (PKCS#8 v1.2 = RFC 5208) + * + * PrivateKeyInfo ::= SEQUENCE { + * version Version, + * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + * privateKey PrivateKey, + * attributes [0] IMPLICIT Attributes OPTIONAL } + * + * Version ::= INTEGER + * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier + * PrivateKey ::= OCTET STRING + * + * The PrivateKey OCTET STRING is a SEC1 ECPrivateKey + */ + + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + end = p + len; + + if( ( ret = asn1_get_int( &p, end, &version ) ) != 0 ) + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( version != 0 ) + return( POLARSSL_ERR_PK_KEY_INVALID_VERSION + ret ); + + if( ( ret = pk_get_pk_alg( &p, end, &pk_alg, ¶ms ) ) != 0 ) + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 ) + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( len < 1 ) + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + + POLARSSL_ERR_ASN1_OUT_OF_DATA ); + + if( ( pk_info = pk_info_from_type( pk_alg ) ) == NULL ) + return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = pk_init_ctx( pk, pk_info ) ) != 0 ) + return( ret ); + +#if defined(POLARSSL_RSA_C) + if( pk_alg == POLARSSL_PK_RSA ) + { + if( ( ret = pk_parse_key_pkcs1_der( pk_rsa( *pk ), p, len ) ) != 0 ) + { + pk_free( pk ); + return( ret ); + } + } else +#endif /* POLARSSL_RSA_C */ +#if defined(POLARSSL_ECP_C) + if( pk_alg == POLARSSL_PK_ECKEY || pk_alg == POLARSSL_PK_ECKEY_DH ) + { + if( ( ret = pk_use_ecparams( ¶ms, &pk_ec( *pk )->grp ) ) != 0 || + ( ret = pk_parse_key_sec1_der( pk_ec( *pk ), p, len ) ) != 0 ) + { + pk_free( pk ); + return( ret ); + } + } else +#endif /* POLARSSL_ECP_C */ + return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG ); + + return( 0 ); +} + +/* + * Parse an encrypted PKCS#8 encoded private key + */ +static int pk_parse_key_pkcs8_encrypted_der( + pk_context *pk, + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen ) +{ + int ret, decrypted = 0; + size_t len; + unsigned char buf[2048]; + unsigned char *p, *end; + asn1_buf pbe_alg_oid, pbe_params; +#if defined(POLARSSL_PKCS12_C) + cipher_type_t cipher_alg; + md_type_t md_alg; +#endif + + memset( buf, 0, sizeof( buf ) ); + + p = (unsigned char *) key; + end = p + keylen; + + if( pwdlen == 0 ) + return( POLARSSL_ERR_PK_PASSWORD_REQUIRED ); + + /* + * This function parses the EncryptedPrivatKeyInfo object (PKCS#8) + * + * EncryptedPrivateKeyInfo ::= SEQUENCE { + * encryptionAlgorithm EncryptionAlgorithmIdentifier, + * encryptedData EncryptedData + * } + * + * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier + * + * EncryptedData ::= OCTET STRING + * + * The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo + */ + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + end = p + len; + + if( ( ret = asn1_get_alg( &p, end, &pbe_alg_oid, &pbe_params ) ) != 0 ) + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 ) + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( len > sizeof( buf ) ) + return( POLARSSL_ERR_PK_BAD_INPUT_DATA ); + + /* + * Decrypt EncryptedData with appropriate PDE + */ +#if defined(POLARSSL_PKCS12_C) + if( oid_get_pkcs12_pbe_alg( &pbe_alg_oid, &md_alg, &cipher_alg ) == 0 ) + { + if( ( ret = pkcs12_pbe( &pbe_params, PKCS12_PBE_DECRYPT, + cipher_alg, md_alg, + pwd, pwdlen, p, len, buf ) ) != 0 ) + { + if( ret == POLARSSL_ERR_PKCS12_PASSWORD_MISMATCH ) + return( POLARSSL_ERR_PK_PASSWORD_MISMATCH ); + + return( ret ); + } + + decrypted = 1; + } + else if( OID_CMP( OID_PKCS12_PBE_SHA1_RC4_128, &pbe_alg_oid ) ) + { + if( ( ret = pkcs12_pbe_sha1_rc4_128( &pbe_params, + PKCS12_PBE_DECRYPT, + pwd, pwdlen, + p, len, buf ) ) != 0 ) + { + return( ret ); + } + + // Best guess for password mismatch when using RC4. If first tag is + // not ASN1_CONSTRUCTED | ASN1_SEQUENCE + // + if( *buf != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) + return( POLARSSL_ERR_PK_PASSWORD_MISMATCH ); + + decrypted = 1; + } + else +#endif /* POLARSSL_PKCS12_C */ +#if defined(POLARSSL_PKCS5_C) + if( OID_CMP( OID_PKCS5_PBES2, &pbe_alg_oid ) ) + { + if( ( ret = pkcs5_pbes2( &pbe_params, PKCS5_DECRYPT, pwd, pwdlen, + p, len, buf ) ) != 0 ) + { + if( ret == POLARSSL_ERR_PKCS5_PASSWORD_MISMATCH ) + return( POLARSSL_ERR_PK_PASSWORD_MISMATCH ); + + return( ret ); + } + + decrypted = 1; + } + else +#endif /* POLARSSL_PKCS5_C */ + { + ((void) pwd); + } + + if( decrypted == 0 ) + return( POLARSSL_ERR_PK_FEATURE_UNAVAILABLE ); + + return( pk_parse_key_pkcs8_unencrypted_der( pk, buf, len ) ); +} + +/* + * Parse a private key + */ +int pk_parse_key( pk_context *pk, + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen ) +{ + int ret; + const pk_info_t *pk_info; + +#if defined(POLARSSL_PEM_PARSE_C) + size_t len; + pem_context pem; + + pem_init( &pem ); + +#if defined(POLARSSL_RSA_C) + ret = pem_read_buffer( &pem, + "-----BEGIN RSA PRIVATE KEY-----", + "-----END RSA PRIVATE KEY-----", + key, pwd, pwdlen, &len ); + if( ret == 0 ) + { + if( ( pk_info = pk_info_from_type( POLARSSL_PK_RSA ) ) == NULL ) + return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = pk_init_ctx( pk, pk_info ) ) != 0 || + ( ret = pk_parse_key_pkcs1_der( pk_rsa( *pk ), + pem.buf, pem.buflen ) ) != 0 ) + { + pk_free( pk ); + } + + pem_free( &pem ); + return( ret ); + } + else if( ret == POLARSSL_ERR_PEM_PASSWORD_MISMATCH ) + return( POLARSSL_ERR_PK_PASSWORD_MISMATCH ); + else if( ret == POLARSSL_ERR_PEM_PASSWORD_REQUIRED ) + return( POLARSSL_ERR_PK_PASSWORD_REQUIRED ); + else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); +#endif /* POLARSSL_RSA_C */ + +#if defined(POLARSSL_ECP_C) + ret = pem_read_buffer( &pem, + "-----BEGIN EC PRIVATE KEY-----", + "-----END EC PRIVATE KEY-----", + key, pwd, pwdlen, &len ); + if( ret == 0 ) + { + if( ( pk_info = pk_info_from_type( POLARSSL_PK_ECKEY ) ) == NULL ) + return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = pk_init_ctx( pk, pk_info ) ) != 0 || + ( ret = pk_parse_key_sec1_der( pk_ec( *pk ), + pem.buf, pem.buflen ) ) != 0 ) + { + pk_free( pk ); + } + + pem_free( &pem ); + return( ret ); + } + else if( ret == POLARSSL_ERR_PEM_PASSWORD_MISMATCH ) + return( POLARSSL_ERR_PK_PASSWORD_MISMATCH ); + else if( ret == POLARSSL_ERR_PEM_PASSWORD_REQUIRED ) + return( POLARSSL_ERR_PK_PASSWORD_REQUIRED ); + else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); +#endif /* POLARSSL_ECP_C */ + + ret = pem_read_buffer( &pem, + "-----BEGIN PRIVATE KEY-----", + "-----END PRIVATE KEY-----", + key, NULL, 0, &len ); + if( ret == 0 ) + { + if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk, + pem.buf, pem.buflen ) ) != 0 ) + { + pk_free( pk ); + } + + pem_free( &pem ); + return( ret ); + } + else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); + + ret = pem_read_buffer( &pem, + "-----BEGIN ENCRYPTED PRIVATE KEY-----", + "-----END ENCRYPTED PRIVATE KEY-----", + key, NULL, 0, &len ); + if( ret == 0 ) + { + if( ( ret = pk_parse_key_pkcs8_encrypted_der( pk, + pem.buf, pem.buflen, + pwd, pwdlen ) ) != 0 ) + { + pk_free( pk ); + } + + pem_free( &pem ); + return( ret ); + } + else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); +#else + ((void) pwd); + ((void) pwdlen); +#endif /* POLARSSL_PEM_PARSE_C */ + + /* + * At this point we only know it's not a PEM formatted key. Could be any + * of the known DER encoded private key formats + * + * We try the different DER format parsers to see if one passes without + * error + */ + if( ( ret = pk_parse_key_pkcs8_encrypted_der( pk, key, keylen, + pwd, pwdlen ) ) == 0 ) + { + return( 0 ); + } + + pk_free( pk ); + + if( ret == POLARSSL_ERR_PK_PASSWORD_MISMATCH ) + { + return( ret ); + } + + if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk, key, keylen ) ) == 0 ) + return( 0 ); + + pk_free( pk ); + +#if defined(POLARSSL_RSA_C) + if( ( pk_info = pk_info_from_type( POLARSSL_PK_RSA ) ) == NULL ) + return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = pk_init_ctx( pk, pk_info ) ) != 0 || + ( ret = pk_parse_key_pkcs1_der( pk_rsa( *pk ), key, keylen ) ) == 0 ) + { + return( 0 ); + } + + pk_free( pk ); +#endif /* POLARSSL_RSA_C */ + +#if defined(POLARSSL_ECP_C) + if( ( pk_info = pk_info_from_type( POLARSSL_PK_ECKEY ) ) == NULL ) + return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = pk_init_ctx( pk, pk_info ) ) != 0 || + ( ret = pk_parse_key_sec1_der( pk_ec( *pk ), key, keylen ) ) == 0 ) + { + return( 0 ); + } + + pk_free( pk ); +#endif /* POLARSSL_ECP_C */ + + return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT ); +} + +/* + * Parse a public key + */ +int pk_parse_public_key( pk_context *ctx, + const unsigned char *key, size_t keylen ) +{ + int ret; + unsigned char *p; +#if defined(POLARSSL_PEM_PARSE_C) + size_t len; + pem_context pem; + + pem_init( &pem ); + ret = pem_read_buffer( &pem, + "-----BEGIN PUBLIC KEY-----", + "-----END PUBLIC KEY-----", + key, NULL, 0, &len ); + + if( ret == 0 ) + { + /* + * Was PEM encoded + */ + key = pem.buf; + keylen = pem.buflen; + } + else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + pem_free( &pem ); + return( ret ); + } +#endif /* POLARSSL_PEM_PARSE_C */ + p = (unsigned char *) key; + + ret = pk_parse_subpubkey( &p, p + keylen, ctx ); + +#if defined(POLARSSL_PEM_PARSE_C) + pem_free( &pem ); +#endif + + return( ret ); +} + +#endif /* POLARSSL_PK_PARSE_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/pkwrite.c b/component/common/network/ssl/polarssl-1.3.8/library/pkwrite.c new file mode 100644 index 0000000..3b0bbdb --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/pkwrite.c @@ -0,0 +1,358 @@ +/* + * Public Key layer for writing key files and structures + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_PK_WRITE_C) + +#include "polarssl/pk.h" +#include "polarssl/asn1write.h" +#include "polarssl/oid.h" + +#if defined(POLARSSL_RSA_C) +#include "polarssl/rsa.h" +#endif +#if defined(POLARSSL_ECP_C) +#include "polarssl/ecp.h" +#endif +#if defined(POLARSSL_ECDSA_C) +#include "polarssl/ecdsa.h" +#endif +#if defined(POLARSSL_PEM_WRITE_C) +#include "polarssl/pem.h" +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include +#define polarssl_malloc malloc +#define polarssl_free free +#endif + +#if defined(POLARSSL_RSA_C) +/* + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER -- e + * } + */ +static int pk_write_rsa_pubkey( unsigned char **p, unsigned char *start, + rsa_context *rsa ) +{ + int ret; + size_t len = 0; + + ASN1_CHK_ADD( len, asn1_write_mpi( p, start, &rsa->E ) ); + ASN1_CHK_ADD( len, asn1_write_mpi( p, start, &rsa->N ) ); + + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | + ASN1_SEQUENCE ) ); + + return( (int) len ); +} +#endif /* POLARSSL_RSA_C */ + +#if defined(POLARSSL_ECP_C) +/* + * EC public key is an EC point + */ +static int pk_write_ec_pubkey( unsigned char **p, unsigned char *start, + ecp_keypair *ec ) +{ + int ret; + size_t len = 0; + unsigned char buf[POLARSSL_ECP_MAX_PT_LEN]; + + if( ( ret = ecp_point_write_binary( &ec->grp, &ec->Q, + POLARSSL_ECP_PF_UNCOMPRESSED, + &len, buf, sizeof( buf ) ) ) != 0 ) + { + return( ret ); + } + + if( *p - start < (int) len ) + return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + + *p -= len; + memcpy( *p, buf, len ); + + return( (int) len ); +} + +/* + * ECParameters ::= CHOICE { + * namedCurve OBJECT IDENTIFIER + * } + */ +static int pk_write_ec_param( unsigned char **p, unsigned char *start, + ecp_keypair *ec ) +{ + int ret; + size_t len = 0; + const char *oid; + size_t oid_len; + + if( ( ret = oid_get_oid_by_ec_grp( ec->grp.id, &oid, &oid_len ) ) != 0 ) + return( ret ); + + ASN1_CHK_ADD( len, asn1_write_oid( p, start, oid, oid_len ) ); + + return( (int) len ); +} +#endif /* POLARSSL_ECP_C */ + +int pk_write_pubkey( unsigned char **p, unsigned char *start, + const pk_context *key ) +{ + int ret; + size_t len = 0; + +#if defined(POLARSSL_RSA_C) + if( pk_get_type( key ) == POLARSSL_PK_RSA ) + ASN1_CHK_ADD( len, pk_write_rsa_pubkey( p, start, pk_rsa( *key ) ) ); + else +#endif +#if defined(POLARSSL_ECP_C) + if( pk_get_type( key ) == POLARSSL_PK_ECKEY ) + ASN1_CHK_ADD( len, pk_write_ec_pubkey( p, start, pk_ec( *key ) ) ); + else +#endif + return( POLARSSL_ERR_PK_FEATURE_UNAVAILABLE ); + + return( (int) len ); +} + +int pk_write_pubkey_der( pk_context *key, unsigned char *buf, size_t size ) +{ + int ret; + unsigned char *c; + size_t len = 0, par_len = 0, oid_len; + const char *oid; + + c = buf + size; + + ASN1_CHK_ADD( len, pk_write_pubkey( &c, buf, key ) ); + + if( c - buf < 1 ) + return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + + /* + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } + */ + *--c = 0; + len += 1; + + ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_BIT_STRING ) ); + + if( ( ret = oid_get_oid_by_pk_alg( pk_get_type( key ), + &oid, &oid_len ) ) != 0 ) + { + return( ret ); + } + +#if defined(POLARSSL_ECP_C) + if( pk_get_type( key ) == POLARSSL_PK_ECKEY ) + { + ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, pk_ec( *key ) ) ); + } +#endif + + ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, buf, oid, oid_len, + par_len ) ); + + ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | + ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +int pk_write_key_der( pk_context *key, unsigned char *buf, size_t size ) +{ + int ret; + unsigned char *c = buf + size; + size_t len = 0; + +#if defined(POLARSSL_RSA_C) + if( pk_get_type( key ) == POLARSSL_PK_RSA ) + { + rsa_context *rsa = pk_rsa( *key ); + + ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->QP ) ); + ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DQ ) ); + ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DP ) ); + ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->Q ) ); + ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->P ) ); + ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->D ) ); + ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->E ) ); + ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->N ) ); + ASN1_CHK_ADD( len, asn1_write_int( &c, buf, 0 ) ); + + ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | + ASN1_SEQUENCE ) ); + } + else +#endif /* POLARSSL_RSA_C */ +#if defined(POLARSSL_ECP_C) + if( pk_get_type( key ) == POLARSSL_PK_ECKEY ) + { + ecp_keypair *ec = pk_ec( *key ); + size_t pub_len = 0, par_len = 0; + + /* + * RFC 5915, or SEC1 Appendix C.4 + * + * ECPrivateKey ::= SEQUENCE { + * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), + * privateKey OCTET STRING, + * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, + * publicKey [1] BIT STRING OPTIONAL + * } + */ + + /* publicKey */ + ASN1_CHK_ADD( pub_len, pk_write_ec_pubkey( &c, buf, ec ) ); + + if( c - buf < 1 ) + return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + *--c = 0; + pub_len += 1; + + ASN1_CHK_ADD( pub_len, asn1_write_len( &c, buf, pub_len ) ); + ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, buf, ASN1_BIT_STRING ) ); + + ASN1_CHK_ADD( pub_len, asn1_write_len( &c, buf, pub_len ) ); + ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, buf, + ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1 ) ); + len += pub_len; + + /* parameters */ + ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, ec ) ); + + ASN1_CHK_ADD( par_len, asn1_write_len( &c, buf, par_len ) ); + ASN1_CHK_ADD( par_len, asn1_write_tag( &c, buf, + ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ); + len += par_len; + + /* privateKey: write as MPI then fix tag */ + ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &ec->d ) ); + *c = ASN1_OCTET_STRING; + + /* version */ + ASN1_CHK_ADD( len, asn1_write_int( &c, buf, 1 ) ); + + ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | + ASN1_SEQUENCE ) ); + } + else +#endif /* POLARSSL_ECP_C */ + return( POLARSSL_ERR_PK_FEATURE_UNAVAILABLE ); + + return( (int) len ); +} + +#if defined(POLARSSL_PEM_WRITE_C) + +#define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n" +#define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n" + +#define PEM_BEGIN_PRIVATE_KEY_RSA "-----BEGIN RSA PRIVATE KEY-----\n" +#define PEM_END_PRIVATE_KEY_RSA "-----END RSA PRIVATE KEY-----\n" +#define PEM_BEGIN_PRIVATE_KEY_EC "-----BEGIN EC PRIVATE KEY-----\n" +#define PEM_END_PRIVATE_KEY_EC "-----END EC PRIVATE KEY-----\n" + +int pk_write_pubkey_pem( pk_context *key, unsigned char *buf, size_t size ) +{ + int ret; + unsigned char output_buf[4096]; + size_t olen = 0; + + if( ( ret = pk_write_pubkey_der( key, output_buf, + sizeof(output_buf) ) ) < 0 ) + { + return( ret ); + } + + if( ( ret = pem_write_buffer( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY, + output_buf + sizeof(output_buf) - ret, + ret, buf, size, &olen ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +int pk_write_key_pem( pk_context *key, unsigned char *buf, size_t size ) +{ + int ret; + unsigned char output_buf[4096]; + const char *begin, *end; + size_t olen = 0; + + if( ( ret = pk_write_key_der( key, output_buf, sizeof(output_buf) ) ) < 0 ) + return( ret ); + +#if defined(POLARSSL_RSA_C) + if( pk_get_type( key ) == POLARSSL_PK_RSA ) + { + begin = PEM_BEGIN_PRIVATE_KEY_RSA; + end = PEM_END_PRIVATE_KEY_RSA; + } + else +#endif +#if defined(POLARSSL_ECP_C) + if( pk_get_type( key ) == POLARSSL_PK_ECKEY ) + { + begin = PEM_BEGIN_PRIVATE_KEY_EC; + end = PEM_END_PRIVATE_KEY_EC; + } + else +#endif + return( POLARSSL_ERR_PK_FEATURE_UNAVAILABLE ); + + if( ( ret = pem_write_buffer( begin, end, + output_buf + sizeof(output_buf) - ret, + ret, buf, size, &olen ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} +#endif /* POLARSSL_PEM_WRITE_C */ + +#endif /* POLARSSL_PK_WRITE_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/platform.c b/component/common/network/ssl/polarssl-1.3.8/library/platform.c new file mode 100644 index 0000000..d57cbc8 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/platform.c @@ -0,0 +1,116 @@ +/* + * Platform abstraction layer + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_PLATFORM_C) + +#include "polarssl/platform.h" + +#if defined(POLARSSL_PLATFORM_MEMORY) +#if !defined(POLARSSL_PLATFORM_STD_MALLOC) +static void *platform_malloc_uninit( size_t len ) +{ + ((void) len); + return( NULL ); +} + +#define POLARSSL_PLATFORM_STD_MALLOC platform_malloc_uninit +#endif /* !POLARSSL_PLATFORM_STD_MALLOC */ + +#if !defined(POLARSSL_PLATFORM_STD_FREE) +static void platform_free_uninit( void *ptr ) +{ + ((void) ptr); +} + +#define POLARSSL_PLATFORM_STD_FREE platform_free_uninit +#endif /* !POLARSSL_PLATFORM_STD_FREE */ + +void * (*polarssl_malloc)( size_t ) = POLARSSL_PLATFORM_STD_MALLOC; +void (*polarssl_free)( void * ) = POLARSSL_PLATFORM_STD_FREE; + +int platform_set_malloc_free( void * (*malloc_func)( size_t ), + void (*free_func)( void * ) ) +{ + polarssl_malloc = malloc_func; + polarssl_free = free_func; + return( 0 ); +} +#endif /* POLARSSL_PLATFORM_MEMORY */ + +#if defined(POLARSSL_PLATFORM_PRINTF_ALT) +#if !defined(POLARSSL_PLATFORM_STD_PRINTF) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_printf_uninit( const char *format, ... ) +{ + ((void) format); + return( 0 ); +} + +#define POLARSSL_PLATFORM_STD_PRINTF platform_printf_uninit +#endif /* !POLARSSL_PLATFORM_STD_PRINTF */ + +int (*polarssl_printf)( const char *, ... ) = POLARSSL_PLATFORM_STD_PRINTF; + +int platform_set_printf( int (*printf_func)( const char *, ... ) ) +{ + polarssl_printf = printf_func; + return( 0 ); +} +#endif /* POLARSSL_PLATFORM_PRINTF_ALT */ + +#if defined(POLARSSL_PLATFORM_FPRINTF_ALT) +#if !defined(POLARSSL_PLATFORM_STD_FPRINTF) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_fprintf_uninit( FILE *stream, const char *format, ... ) +{ + ((void) stream); + ((void) format); + return( 0 ); +} + +#define POLARSSL_PLATFORM_STD_FPRINTF platform_fprintf_uninit +#endif /* !POLARSSL_PLATFORM_STD_FPRINTF */ + +int (*polarssl_fprintf)( FILE *, const char *, ... ) = + POLARSSL_PLATFORM_STD_FPRINTF; + +int platform_set_fprintf( int (*fprintf_func)( FILE *, const char *, ... ) ) +{ + polarssl_fprintf = fprintf_func; + return( 0 ); +} +#endif /* POLARSSL_PLATFORM_FPRINTF_ALT */ + +#endif /* POLARSSL_PLATFORM_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/ripemd160.c b/component/common/network/ssl/polarssl-1.3.8/library/ripemd160.c new file mode 100644 index 0000000..fcd7760 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/ripemd160.c @@ -0,0 +1,653 @@ +/* + * RIPE MD-160 implementation + * + * Copyright (C) 2014-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* + * The RIPEMD-160 algorithm was designed by RIPE in 1996 + * http://homes.esat.kuleuven.be/~bosselae/ripemd160.html + * http://ehash.iaik.tugraz.at/wiki/RIPEMD-160 + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_RIPEMD160_C) + +#include "polarssl/ripemd160.h" + +#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST) +#include +#endif + +#if defined(POLARSSL_SELF_TEST) +#include +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#define polarssl_printf printf +#endif + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_UINT32_LE +#define GET_UINT32_LE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] ) \ + | ( (uint32_t) (b)[(i) + 1] << 8 ) \ + | ( (uint32_t) (b)[(i) + 2] << 16 ) \ + | ( (uint32_t) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_UINT32_LE +#define PUT_UINT32_LE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \ +} +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +void ripemd160_init( ripemd160_context *ctx ) +{ + memset( ctx, 0, sizeof( ripemd160_context ) ); +} + +void ripemd160_free( ripemd160_context *ctx ) +{ + if( ctx == NULL ) + return; + + polarssl_zeroize( ctx, sizeof( ripemd160_context ) ); +} + +/* + * RIPEMD-160 context setup + */ +void ripemd160_starts( ripemd160_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + ctx->state[4] = 0xC3D2E1F0; +} + +/* + * Process one block + */ +void ripemd160_process( ripemd160_context *ctx, const unsigned char data[64] ) +{ + uint32_t A, B, C, D, E, Ap, Bp, Cp, Dp, Ep, X[16]; + + GET_UINT32_LE( X[ 0], data, 0 ); + GET_UINT32_LE( X[ 1], data, 4 ); + GET_UINT32_LE( X[ 2], data, 8 ); + GET_UINT32_LE( X[ 3], data, 12 ); + GET_UINT32_LE( X[ 4], data, 16 ); + GET_UINT32_LE( X[ 5], data, 20 ); + GET_UINT32_LE( X[ 6], data, 24 ); + GET_UINT32_LE( X[ 7], data, 28 ); + GET_UINT32_LE( X[ 8], data, 32 ); + GET_UINT32_LE( X[ 9], data, 36 ); + GET_UINT32_LE( X[10], data, 40 ); + GET_UINT32_LE( X[11], data, 44 ); + GET_UINT32_LE( X[12], data, 48 ); + GET_UINT32_LE( X[13], data, 52 ); + GET_UINT32_LE( X[14], data, 56 ); + GET_UINT32_LE( X[15], data, 60 ); + + A = Ap = ctx->state[0]; + B = Bp = ctx->state[1]; + C = Cp = ctx->state[2]; + D = Dp = ctx->state[3]; + E = Ep = ctx->state[4]; + +#define F1( x, y, z ) ( x ^ y ^ z ) +#define F2( x, y, z ) ( ( x & y ) | ( ~x & z ) ) +#define F3( x, y, z ) ( ( x | ~y ) ^ z ) +#define F4( x, y, z ) ( ( x & z ) | ( y & ~z ) ) +#define F5( x, y, z ) ( x ^ ( y | ~z ) ) + +#define S( x, n ) ( ( x << n ) | ( x >> (32 - n) ) ) + +#define P( a, b, c, d, e, r, s, f, k ) \ + a += f( b, c, d ) + X[r] + k; \ + a = S( a, s ) + e; \ + c = S( c, 10 ); + +#define P2( a, b, c, d, e, r, s, rp, sp ) \ + P( a, b, c, d, e, r, s, F, K ); \ + P( a ## p, b ## p, c ## p, d ## p, e ## p, rp, sp, Fp, Kp ); + +#define F F1 +#define K 0x00000000 +#define Fp F5 +#define Kp 0x50A28BE6 + P2( A, B, C, D, E, 0, 11, 5, 8 ); + P2( E, A, B, C, D, 1, 14, 14, 9 ); + P2( D, E, A, B, C, 2, 15, 7, 9 ); + P2( C, D, E, A, B, 3, 12, 0, 11 ); + P2( B, C, D, E, A, 4, 5, 9, 13 ); + P2( A, B, C, D, E, 5, 8, 2, 15 ); + P2( E, A, B, C, D, 6, 7, 11, 15 ); + P2( D, E, A, B, C, 7, 9, 4, 5 ); + P2( C, D, E, A, B, 8, 11, 13, 7 ); + P2( B, C, D, E, A, 9, 13, 6, 7 ); + P2( A, B, C, D, E, 10, 14, 15, 8 ); + P2( E, A, B, C, D, 11, 15, 8, 11 ); + P2( D, E, A, B, C, 12, 6, 1, 14 ); + P2( C, D, E, A, B, 13, 7, 10, 14 ); + P2( B, C, D, E, A, 14, 9, 3, 12 ); + P2( A, B, C, D, E, 15, 8, 12, 6 ); +#undef F +#undef K +#undef Fp +#undef Kp + +#define F F2 +#define K 0x5A827999 +#define Fp F4 +#define Kp 0x5C4DD124 + P2( E, A, B, C, D, 7, 7, 6, 9 ); + P2( D, E, A, B, C, 4, 6, 11, 13 ); + P2( C, D, E, A, B, 13, 8, 3, 15 ); + P2( B, C, D, E, A, 1, 13, 7, 7 ); + P2( A, B, C, D, E, 10, 11, 0, 12 ); + P2( E, A, B, C, D, 6, 9, 13, 8 ); + P2( D, E, A, B, C, 15, 7, 5, 9 ); + P2( C, D, E, A, B, 3, 15, 10, 11 ); + P2( B, C, D, E, A, 12, 7, 14, 7 ); + P2( A, B, C, D, E, 0, 12, 15, 7 ); + P2( E, A, B, C, D, 9, 15, 8, 12 ); + P2( D, E, A, B, C, 5, 9, 12, 7 ); + P2( C, D, E, A, B, 2, 11, 4, 6 ); + P2( B, C, D, E, A, 14, 7, 9, 15 ); + P2( A, B, C, D, E, 11, 13, 1, 13 ); + P2( E, A, B, C, D, 8, 12, 2, 11 ); +#undef F +#undef K +#undef Fp +#undef Kp + +#define F F3 +#define K 0x6ED9EBA1 +#define Fp F3 +#define Kp 0x6D703EF3 + P2( D, E, A, B, C, 3, 11, 15, 9 ); + P2( C, D, E, A, B, 10, 13, 5, 7 ); + P2( B, C, D, E, A, 14, 6, 1, 15 ); + P2( A, B, C, D, E, 4, 7, 3, 11 ); + P2( E, A, B, C, D, 9, 14, 7, 8 ); + P2( D, E, A, B, C, 15, 9, 14, 6 ); + P2( C, D, E, A, B, 8, 13, 6, 6 ); + P2( B, C, D, E, A, 1, 15, 9, 14 ); + P2( A, B, C, D, E, 2, 14, 11, 12 ); + P2( E, A, B, C, D, 7, 8, 8, 13 ); + P2( D, E, A, B, C, 0, 13, 12, 5 ); + P2( C, D, E, A, B, 6, 6, 2, 14 ); + P2( B, C, D, E, A, 13, 5, 10, 13 ); + P2( A, B, C, D, E, 11, 12, 0, 13 ); + P2( E, A, B, C, D, 5, 7, 4, 7 ); + P2( D, E, A, B, C, 12, 5, 13, 5 ); +#undef F +#undef K +#undef Fp +#undef Kp + +#define F F4 +#define K 0x8F1BBCDC +#define Fp F2 +#define Kp 0x7A6D76E9 + P2( C, D, E, A, B, 1, 11, 8, 15 ); + P2( B, C, D, E, A, 9, 12, 6, 5 ); + P2( A, B, C, D, E, 11, 14, 4, 8 ); + P2( E, A, B, C, D, 10, 15, 1, 11 ); + P2( D, E, A, B, C, 0, 14, 3, 14 ); + P2( C, D, E, A, B, 8, 15, 11, 14 ); + P2( B, C, D, E, A, 12, 9, 15, 6 ); + P2( A, B, C, D, E, 4, 8, 0, 14 ); + P2( E, A, B, C, D, 13, 9, 5, 6 ); + P2( D, E, A, B, C, 3, 14, 12, 9 ); + P2( C, D, E, A, B, 7, 5, 2, 12 ); + P2( B, C, D, E, A, 15, 6, 13, 9 ); + P2( A, B, C, D, E, 14, 8, 9, 12 ); + P2( E, A, B, C, D, 5, 6, 7, 5 ); + P2( D, E, A, B, C, 6, 5, 10, 15 ); + P2( C, D, E, A, B, 2, 12, 14, 8 ); +#undef F +#undef K +#undef Fp +#undef Kp + +#define F F5 +#define K 0xA953FD4E +#define Fp F1 +#define Kp 0x00000000 + P2( B, C, D, E, A, 4, 9, 12, 8 ); + P2( A, B, C, D, E, 0, 15, 15, 5 ); + P2( E, A, B, C, D, 5, 5, 10, 12 ); + P2( D, E, A, B, C, 9, 11, 4, 9 ); + P2( C, D, E, A, B, 7, 6, 1, 12 ); + P2( B, C, D, E, A, 12, 8, 5, 5 ); + P2( A, B, C, D, E, 2, 13, 8, 14 ); + P2( E, A, B, C, D, 10, 12, 7, 6 ); + P2( D, E, A, B, C, 14, 5, 6, 8 ); + P2( C, D, E, A, B, 1, 12, 2, 13 ); + P2( B, C, D, E, A, 3, 13, 13, 6 ); + P2( A, B, C, D, E, 8, 14, 14, 5 ); + P2( E, A, B, C, D, 11, 11, 0, 15 ); + P2( D, E, A, B, C, 6, 8, 3, 13 ); + P2( C, D, E, A, B, 15, 5, 9, 11 ); + P2( B, C, D, E, A, 13, 6, 11, 11 ); +#undef F +#undef K +#undef Fp +#undef Kp + + C = ctx->state[1] + C + Dp; + ctx->state[1] = ctx->state[2] + D + Ep; + ctx->state[2] = ctx->state[3] + E + Ap; + ctx->state[3] = ctx->state[4] + A + Bp; + ctx->state[4] = ctx->state[0] + B + Cp; + ctx->state[0] = C; +} + +/* + * RIPEMD-160 process buffer + */ +void ripemd160_update( ripemd160_context *ctx, + const unsigned char *input, size_t ilen ) +{ + size_t fill; + uint32_t left; + + if( ilen == 0 ) + return; + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + ripemd160_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + ripemd160_process( ctx, input ); + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + memcpy( (void *) (ctx->buffer + left), input, ilen ); + } +} + +static const unsigned char ripemd160_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * RIPEMD-160 final digest + */ +void ripemd160_finish( ripemd160_context *ctx, unsigned char output[20] ) +{ + uint32_t last, padn; + uint32_t high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_LE( low, msglen, 0 ); + PUT_UINT32_LE( high, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + ripemd160_update( ctx, ripemd160_padding, padn ); + ripemd160_update( ctx, msglen, 8 ); + + PUT_UINT32_LE( ctx->state[0], output, 0 ); + PUT_UINT32_LE( ctx->state[1], output, 4 ); + PUT_UINT32_LE( ctx->state[2], output, 8 ); + PUT_UINT32_LE( ctx->state[3], output, 12 ); + PUT_UINT32_LE( ctx->state[4], output, 16 ); +} + +/* + * output = RIPEMD-160( input buffer ) + */ +void ripemd160( const unsigned char *input, size_t ilen, + unsigned char output[20] ) +{ + ripemd160_context ctx; + + ripemd160_init( &ctx ); + ripemd160_starts( &ctx ); + ripemd160_update( &ctx, input, ilen ); + ripemd160_finish( &ctx, output ); + ripemd160_free( &ctx ); +} + +#if defined(POLARSSL_FS_IO) +/* + * output = RIPEMD-160( file contents ) + */ +int ripemd160_file( const char *path, unsigned char output[20] ) +{ + FILE *f; + size_t n; + ripemd160_context ctx; + unsigned char buf[1024]; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( POLARSSL_ERR_RIPEMD160_FILE_IO_ERROR ); + + ripemd160_init( &ctx ); + ripemd160_starts( &ctx ); + + while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) + ripemd160_update( &ctx, buf, n ); + + ripemd160_finish( &ctx, output ); + ripemd160_free( &ctx ); + + if( ferror( f ) != 0 ) + { + fclose( f ); + return( POLARSSL_ERR_RIPEMD160_FILE_IO_ERROR ); + } + + fclose( f ); + return( 0 ); +} +#endif /* POLARSSL_FS_IO */ + +/* + * RIPEMD-160 HMAC context setup + */ +void ripemd160_hmac_starts( ripemd160_context *ctx, + const unsigned char *key, size_t keylen ) +{ + size_t i; + unsigned char sum[20]; + + if( keylen > 64 ) + { + ripemd160( key, keylen, sum ); + keylen = 20; + key = sum; + } + + memset( ctx->ipad, 0x36, 64 ); + memset( ctx->opad, 0x5C, 64 ); + + for( i = 0; i < keylen; i++ ) + { + ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] ); + ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] ); + } + + ripemd160_starts( ctx ); + ripemd160_update( ctx, ctx->ipad, 64 ); + + polarssl_zeroize( sum, sizeof( sum ) ); +} + +/* + * RIPEMD-160 HMAC process buffer + */ +void ripemd160_hmac_update( ripemd160_context *ctx, + const unsigned char *input, size_t ilen ) +{ + ripemd160_update( ctx, input, ilen ); +} + +/* + * RIPEMD-160 HMAC final digest + */ +void ripemd160_hmac_finish( ripemd160_context *ctx, unsigned char output[20] ) +{ + unsigned char tmpbuf[20]; + + ripemd160_finish( ctx, tmpbuf ); + ripemd160_starts( ctx ); + ripemd160_update( ctx, ctx->opad, 64 ); + ripemd160_update( ctx, tmpbuf, 20 ); + ripemd160_finish( ctx, output ); + + polarssl_zeroize( tmpbuf, sizeof( tmpbuf ) ); +} + +/* + * RIPEMD-160 HMAC context reset + */ +void ripemd160_hmac_reset( ripemd160_context *ctx ) +{ + ripemd160_starts( ctx ); + ripemd160_update( ctx, ctx->ipad, 64 ); +} + +/* + * output = HMAC-RIPEMD-160( hmac key, input buffer ) + */ +void ripemd160_hmac( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char output[20] ) +{ + ripemd160_context ctx; + + ripemd160_init( &ctx ); + ripemd160_hmac_starts( &ctx, key, keylen ); + ripemd160_hmac_update( &ctx, input, ilen ); + ripemd160_hmac_finish( &ctx, output ); + ripemd160_free( &ctx ); +} + + +#if defined(POLARSSL_SELF_TEST) +/* + * Test vectors from the RIPEMD-160 paper and + * http://homes.esat.kuleuven.be/~bosselae/ripemd160.html#HMAC + */ +#define TESTS 8 +#define KEYS 2 +static const char *ripemd160_test_input[TESTS] = +{ + "", + "a", + "abc", + "message digest", + "abcdefghijklmnopqrstuvwxyz", + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + "1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890", +}; + +static const unsigned char ripemd160_test_md[TESTS][20] = +{ + { 0x9c, 0x11, 0x85, 0xa5, 0xc5, 0xe9, 0xfc, 0x54, 0x61, 0x28, + 0x08, 0x97, 0x7e, 0xe8, 0xf5, 0x48, 0xb2, 0x25, 0x8d, 0x31 }, + { 0x0b, 0xdc, 0x9d, 0x2d, 0x25, 0x6b, 0x3e, 0xe9, 0xda, 0xae, + 0x34, 0x7b, 0xe6, 0xf4, 0xdc, 0x83, 0x5a, 0x46, 0x7f, 0xfe }, + { 0x8e, 0xb2, 0x08, 0xf7, 0xe0, 0x5d, 0x98, 0x7a, 0x9b, 0x04, + 0x4a, 0x8e, 0x98, 0xc6, 0xb0, 0x87, 0xf1, 0x5a, 0x0b, 0xfc }, + { 0x5d, 0x06, 0x89, 0xef, 0x49, 0xd2, 0xfa, 0xe5, 0x72, 0xb8, + 0x81, 0xb1, 0x23, 0xa8, 0x5f, 0xfa, 0x21, 0x59, 0x5f, 0x36 }, + { 0xf7, 0x1c, 0x27, 0x10, 0x9c, 0x69, 0x2c, 0x1b, 0x56, 0xbb, + 0xdc, 0xeb, 0x5b, 0x9d, 0x28, 0x65, 0xb3, 0x70, 0x8d, 0xbc }, + { 0x12, 0xa0, 0x53, 0x38, 0x4a, 0x9c, 0x0c, 0x88, 0xe4, 0x05, + 0xa0, 0x6c, 0x27, 0xdc, 0xf4, 0x9a, 0xda, 0x62, 0xeb, 0x2b }, + { 0xb0, 0xe2, 0x0b, 0x6e, 0x31, 0x16, 0x64, 0x02, 0x86, 0xed, + 0x3a, 0x87, 0xa5, 0x71, 0x30, 0x79, 0xb2, 0x1f, 0x51, 0x89 }, + { 0x9b, 0x75, 0x2e, 0x45, 0x57, 0x3d, 0x4b, 0x39, 0xf4, 0xdb, + 0xd3, 0x32, 0x3c, 0xab, 0x82, 0xbf, 0x63, 0x32, 0x6b, 0xfb }, +}; + +static const unsigned char ripemd160_test_hmac[KEYS][TESTS][20] = +{ + { + { 0xcf, 0x38, 0x76, 0x77, 0xbf, 0xda, 0x84, 0x83, 0xe6, 0x3b, + 0x57, 0xe0, 0x6c, 0x3b, 0x5e, 0xcd, 0x8b, 0x7f, 0xc0, 0x55 }, + { 0x0d, 0x35, 0x1d, 0x71, 0xb7, 0x8e, 0x36, 0xdb, 0xb7, 0x39, + 0x1c, 0x81, 0x0a, 0x0d, 0x2b, 0x62, 0x40, 0xdd, 0xba, 0xfc }, + { 0xf7, 0xef, 0x28, 0x8c, 0xb1, 0xbb, 0xcc, 0x61, 0x60, 0xd7, + 0x65, 0x07, 0xe0, 0xa3, 0xbb, 0xf7, 0x12, 0xfb, 0x67, 0xd6 }, + { 0xf8, 0x36, 0x62, 0xcc, 0x8d, 0x33, 0x9c, 0x22, 0x7e, 0x60, + 0x0f, 0xcd, 0x63, 0x6c, 0x57, 0xd2, 0x57, 0x1b, 0x1c, 0x34 }, + { 0x84, 0x3d, 0x1c, 0x4e, 0xb8, 0x80, 0xac, 0x8a, 0xc0, 0xc9, + 0xc9, 0x56, 0x96, 0x50, 0x79, 0x57, 0xd0, 0x15, 0x5d, 0xdb }, + { 0x60, 0xf5, 0xef, 0x19, 0x8a, 0x2d, 0xd5, 0x74, 0x55, 0x45, + 0xc1, 0xf0, 0xc4, 0x7a, 0xa3, 0xfb, 0x57, 0x76, 0xf8, 0x81 }, + { 0xe4, 0x9c, 0x13, 0x6a, 0x9e, 0x56, 0x27, 0xe0, 0x68, 0x1b, + 0x80, 0x8a, 0x3b, 0x97, 0xe6, 0xa6, 0xe6, 0x61, 0xae, 0x79 }, + { 0x31, 0xbe, 0x3c, 0xc9, 0x8c, 0xee, 0x37, 0xb7, 0x9b, 0x06, + 0x19, 0xe3, 0xe1, 0xc2, 0xbe, 0x4f, 0x1a, 0xa5, 0x6e, 0x6c }, + }, + { + { 0xfe, 0x69, 0xa6, 0x6c, 0x74, 0x23, 0xee, 0xa9, 0xc8, 0xfa, + 0x2e, 0xff, 0x8d, 0x9d, 0xaf, 0xb4, 0xf1, 0x7a, 0x62, 0xf5 }, + { 0x85, 0x74, 0x3e, 0x89, 0x9b, 0xc8, 0x2d, 0xbf, 0xa3, 0x6f, + 0xaa, 0xa7, 0xa2, 0x5b, 0x7c, 0xfd, 0x37, 0x24, 0x32, 0xcd }, + { 0x6e, 0x4a, 0xfd, 0x50, 0x1f, 0xa6, 0xb4, 0xa1, 0x82, 0x3c, + 0xa3, 0xb1, 0x0b, 0xd9, 0xaa, 0x0b, 0xa9, 0x7b, 0xa1, 0x82 }, + { 0x2e, 0x06, 0x6e, 0x62, 0x4b, 0xad, 0xb7, 0x6a, 0x18, 0x4c, + 0x8f, 0x90, 0xfb, 0xa0, 0x53, 0x33, 0x0e, 0x65, 0x0e, 0x92 }, + { 0x07, 0xe9, 0x42, 0xaa, 0x4e, 0x3c, 0xd7, 0xc0, 0x4d, 0xed, + 0xc1, 0xd4, 0x6e, 0x2e, 0x8c, 0xc4, 0xc7, 0x41, 0xb3, 0xd9 }, + { 0xb6, 0x58, 0x23, 0x18, 0xdd, 0xcf, 0xb6, 0x7a, 0x53, 0xa6, + 0x7d, 0x67, 0x6b, 0x8a, 0xd8, 0x69, 0xad, 0xed, 0x62, 0x9a }, + { 0xf1, 0xbe, 0x3e, 0xe8, 0x77, 0x70, 0x31, 0x40, 0xd3, 0x4f, + 0x97, 0xea, 0x1a, 0xb3, 0xa0, 0x7c, 0x14, 0x13, 0x33, 0xe2 }, + { 0x85, 0xf1, 0x64, 0x70, 0x3e, 0x61, 0xa6, 0x31, 0x31, 0xbe, + 0x7e, 0x45, 0x95, 0x8e, 0x07, 0x94, 0x12, 0x39, 0x04, 0xf9 }, + }, +}; + +static const unsigned char ripemd160_test_key[KEYS][20] = +{ + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, + 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x01, 0x23, 0x45, 0x67 }, + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, + 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x00, 0x11, 0x22, 0x33 }, +}; + +/* + * Checkup routine + */ +int ripemd160_self_test( int verbose ) +{ + int i, j; + unsigned char output[20]; + + memset( output, 0, sizeof output ); + + for( i = 0; i < TESTS; i++ ) + { + if( verbose != 0 ) + polarssl_printf( " RIPEMD-160 test #%d: ", i + 1 ); + + ripemd160( (const unsigned char *) ripemd160_test_input[i], + strlen( ripemd160_test_input[i] ), + output ); + + if( memcmp( output, ripemd160_test_md[i], 20 ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + + for( j = 0; j < KEYS; j++ ) + { + if( verbose != 0 ) + polarssl_printf( " HMAC-RIPEMD-160 test #%d, key #%d: ", + i + 1, j + 1 ); + + ripemd160_hmac( ripemd160_test_key[j], 20, + (const unsigned char *) ripemd160_test_input[i], + strlen( ripemd160_test_input[i] ), + output ); + + if( memcmp( output, ripemd160_test_hmac[j][i], 20 ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); + } + + return( 0 ); +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_RIPEMD160_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/rsa.c b/component/common/network/ssl/polarssl-1.3.8/library/rsa.c new file mode 100644 index 0000000..0fd5199 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/rsa.c @@ -0,0 +1,1657 @@ +/* + * The RSA public-key cryptosystem + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * RSA was designed by Ron Rivest, Adi Shamir and Len Adleman. + * + * http://theory.lcs.mit.edu/~rivest/rsapaper.pdf + * http://www.cacr.math.uwaterloo.ca/hac/about/chap8.pdf + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_RSA_C) + +#include "polarssl/rsa.h" +#include "polarssl/oid.h" + +#if defined(POLARSSL_PKCS1_V21) +#include "polarssl/md.h" +#endif + +#include +#include + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#define polarssl_printf printf +#endif + +/* + * Initialize an RSA context + */ +void rsa_init( rsa_context *ctx, + int padding, + int hash_id ) +{ + memset( ctx, 0, sizeof( rsa_context ) ); + + rsa_set_padding( ctx, padding, hash_id ); + +#if defined(POLARSSL_THREADING_C) + polarssl_mutex_init( &ctx->mutex ); +#endif +} + +/* + * Set padding for an existing RSA context + */ +void rsa_set_padding( rsa_context *ctx, int padding, int hash_id ) +{ + ctx->padding = padding; + ctx->hash_id = hash_id; +} + +#if defined(POLARSSL_GENPRIME) + +/* + * Generate an RSA keypair + */ +int rsa_gen_key( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + unsigned int nbits, int exponent ) +{ + int ret; + mpi P1, Q1, H, G; + + if( f_rng == NULL || nbits < 128 || exponent < 3 ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + mpi_init( &P1 ); mpi_init( &Q1 ); mpi_init( &H ); mpi_init( &G ); + + /* + * find primes P and Q with Q < P so that: + * GCD( E, (P-1)*(Q-1) ) == 1 + */ + MPI_CHK( mpi_lset( &ctx->E, exponent ) ); + + do + { + MPI_CHK( mpi_gen_prime( &ctx->P, ( nbits + 1 ) >> 1, 0, + f_rng, p_rng ) ); + + MPI_CHK( mpi_gen_prime( &ctx->Q, ( nbits + 1 ) >> 1, 0, + f_rng, p_rng ) ); + + if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 ) + mpi_swap( &ctx->P, &ctx->Q ); + + if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) == 0 ) + continue; + + MPI_CHK( mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) ); + if( mpi_msb( &ctx->N ) != nbits ) + continue; + + MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) ); + MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) ); + MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) ); + MPI_CHK( mpi_gcd( &G, &ctx->E, &H ) ); + } + while( mpi_cmp_int( &G, 1 ) != 0 ); + + /* + * D = E^-1 mod ((P-1)*(Q-1)) + * DP = D mod (P - 1) + * DQ = D mod (Q - 1) + * QP = Q^-1 mod P + */ + MPI_CHK( mpi_inv_mod( &ctx->D , &ctx->E, &H ) ); + MPI_CHK( mpi_mod_mpi( &ctx->DP, &ctx->D, &P1 ) ); + MPI_CHK( mpi_mod_mpi( &ctx->DQ, &ctx->D, &Q1 ) ); + MPI_CHK( mpi_inv_mod( &ctx->QP, &ctx->Q, &ctx->P ) ); + + ctx->len = ( mpi_msb( &ctx->N ) + 7 ) >> 3; + +cleanup: + + mpi_free( &P1 ); mpi_free( &Q1 ); mpi_free( &H ); mpi_free( &G ); + + if( ret != 0 ) + { + rsa_free( ctx ); + return( POLARSSL_ERR_RSA_KEY_GEN_FAILED + ret ); + } + + return( 0 ); +} + +#endif /* POLARSSL_GENPRIME */ + +/* + * Check a public RSA key + */ +int rsa_check_pubkey( const rsa_context *ctx ) +{ + if( !ctx->N.p || !ctx->E.p ) + return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); + + if( ( ctx->N.p[0] & 1 ) == 0 || + ( ctx->E.p[0] & 1 ) == 0 ) + return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); + + if( mpi_msb( &ctx->N ) < 128 || + mpi_msb( &ctx->N ) > POLARSSL_MPI_MAX_BITS ) + return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); + + if( mpi_msb( &ctx->E ) < 2 || + mpi_cmp_mpi( &ctx->E, &ctx->N ) >= 0 ) + return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); + + return( 0 ); +} + +/* + * Check a private RSA key + */ +int rsa_check_privkey( const rsa_context *ctx ) +{ + int ret; + mpi PQ, DE, P1, Q1, H, I, G, G2, L1, L2, DP, DQ, QP; + + if( ( ret = rsa_check_pubkey( ctx ) ) != 0 ) + return( ret ); + + if( !ctx->P.p || !ctx->Q.p || !ctx->D.p ) + return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); + + mpi_init( &PQ ); mpi_init( &DE ); mpi_init( &P1 ); mpi_init( &Q1 ); + mpi_init( &H ); mpi_init( &I ); mpi_init( &G ); mpi_init( &G2 ); + mpi_init( &L1 ); mpi_init( &L2 ); mpi_init( &DP ); mpi_init( &DQ ); + mpi_init( &QP ); + + MPI_CHK( mpi_mul_mpi( &PQ, &ctx->P, &ctx->Q ) ); + MPI_CHK( mpi_mul_mpi( &DE, &ctx->D, &ctx->E ) ); + MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) ); + MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) ); + MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) ); + MPI_CHK( mpi_gcd( &G, &ctx->E, &H ) ); + + MPI_CHK( mpi_gcd( &G2, &P1, &Q1 ) ); + MPI_CHK( mpi_div_mpi( &L1, &L2, &H, &G2 ) ); + MPI_CHK( mpi_mod_mpi( &I, &DE, &L1 ) ); + + MPI_CHK( mpi_mod_mpi( &DP, &ctx->D, &P1 ) ); + MPI_CHK( mpi_mod_mpi( &DQ, &ctx->D, &Q1 ) ); + MPI_CHK( mpi_inv_mod( &QP, &ctx->Q, &ctx->P ) ); + /* + * Check for a valid PKCS1v2 private key + */ + if( mpi_cmp_mpi( &PQ, &ctx->N ) != 0 || + mpi_cmp_mpi( &DP, &ctx->DP ) != 0 || + mpi_cmp_mpi( &DQ, &ctx->DQ ) != 0 || + mpi_cmp_mpi( &QP, &ctx->QP ) != 0 || + mpi_cmp_int( &L2, 0 ) != 0 || + mpi_cmp_int( &I, 1 ) != 0 || + mpi_cmp_int( &G, 1 ) != 0 ) + { + ret = POLARSSL_ERR_RSA_KEY_CHECK_FAILED; + } + +cleanup: + mpi_free( &PQ ); mpi_free( &DE ); mpi_free( &P1 ); mpi_free( &Q1 ); + mpi_free( &H ); mpi_free( &I ); mpi_free( &G ); mpi_free( &G2 ); + mpi_free( &L1 ); mpi_free( &L2 ); mpi_free( &DP ); mpi_free( &DQ ); + mpi_free( &QP ); + + if( ret == POLARSSL_ERR_RSA_KEY_CHECK_FAILED ) + return( ret ); + + if( ret != 0 ) + return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED + ret ); + + return( 0 ); +} + +/* + * Do an RSA public key operation + */ +int rsa_public( rsa_context *ctx, + const unsigned char *input, + unsigned char *output ) +{ + int ret; + size_t olen; + mpi T; + + mpi_init( &T ); + + MPI_CHK( mpi_read_binary( &T, input, ctx->len ) ); + + if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) + { + mpi_free( &T ); + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + } + + olen = ctx->len; + MPI_CHK( mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) ); + MPI_CHK( mpi_write_binary( &T, output, olen ) ); + +cleanup: + + mpi_free( &T ); + + if( ret != 0 ) + return( POLARSSL_ERR_RSA_PUBLIC_FAILED + ret ); + + return( 0 ); +} + +#if !defined(POLARSSL_RSA_NO_CRT) +/* + * Generate or update blinding values, see section 10 of: + * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA, + * DSS, and other systems. In : Advances in Cryptology—CRYPTO’96. Springer + * Berlin Heidelberg, 1996. p. 104-113. + */ +static int rsa_prepare_blinding( rsa_context *ctx, mpi *Vi, mpi *Vf, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret, count = 0; + +#if defined(POLARSSL_THREADING_C) + polarssl_mutex_lock( &ctx->mutex ); +#endif + + if( ctx->Vf.p != NULL ) + { + /* We already have blinding values, just update them by squaring */ + MPI_CHK( mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) ); + MPI_CHK( mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) ); + MPI_CHK( mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) ); + MPI_CHK( mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->N ) ); + + goto done; + } + + /* Unblinding value: Vf = random number, invertible mod N */ + do { + if( count++ > 10 ) + return( POLARSSL_ERR_RSA_RNG_FAILED ); + + MPI_CHK( mpi_fill_random( &ctx->Vf, ctx->len - 1, f_rng, p_rng ) ); + MPI_CHK( mpi_gcd( &ctx->Vi, &ctx->Vf, &ctx->N ) ); + } while( mpi_cmp_int( &ctx->Vi, 1 ) != 0 ); + + /* Blinding value: Vi = Vf^(-e) mod N */ + MPI_CHK( mpi_inv_mod( &ctx->Vi, &ctx->Vf, &ctx->N ) ); + MPI_CHK( mpi_exp_mod( &ctx->Vi, &ctx->Vi, &ctx->E, &ctx->N, &ctx->RN ) ); + +done: + if( Vi != &ctx->Vi ) + { + MPI_CHK( mpi_copy( Vi, &ctx->Vi ) ); + MPI_CHK( mpi_copy( Vf, &ctx->Vf ) ); + } + +cleanup: +#if defined(POLARSSL_THREADING_C) + polarssl_mutex_unlock( &ctx->mutex ); +#endif + + return( ret ); +} +#endif /* !POLARSSL_RSA_NO_CRT */ + +/* + * Do an RSA private key operation + */ +int rsa_private( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + const unsigned char *input, + unsigned char *output ) +{ + int ret; + size_t olen; + mpi T, T1, T2; +#if !defined(POLARSSL_RSA_NO_CRT) + mpi *Vi, *Vf; + + /* + * When using the Chinese Remainder Theorem, we use blinding values. + * Without threading, we just read them directly from the context, + * otherwise we make a local copy in order to reduce locking contention. + */ +#if defined(POLARSSL_THREADING_C) + mpi Vi_copy, Vf_copy; + + mpi_init( &Vi_copy ); mpi_init( &Vf_copy ); + Vi = &Vi_copy; + Vf = &Vf_copy; +#else + Vi = &ctx->Vi; + Vf = &ctx->Vf; +#endif +#endif /* !POLARSSL_RSA_NO_CRT */ + + mpi_init( &T ); mpi_init( &T1 ); mpi_init( &T2 ); + + MPI_CHK( mpi_read_binary( &T, input, ctx->len ) ); + if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) + { + mpi_free( &T ); + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + } + +#if defined(POLARSSL_RSA_NO_CRT) + ((void) f_rng); + ((void) p_rng); + MPI_CHK( mpi_exp_mod( &T, &T, &ctx->D, &ctx->N, &ctx->RN ) ); +#else + if( f_rng != NULL ) + { + /* + * Blinding + * T = T * Vi mod N + */ + MPI_CHK( rsa_prepare_blinding( ctx, Vi, Vf, f_rng, p_rng ) ); + MPI_CHK( mpi_mul_mpi( &T, &T, Vi ) ); + MPI_CHK( mpi_mod_mpi( &T, &T, &ctx->N ) ); + } + + /* + * faster decryption using the CRT + * + * T1 = input ^ dP mod P + * T2 = input ^ dQ mod Q + */ + MPI_CHK( mpi_exp_mod( &T1, &T, &ctx->DP, &ctx->P, &ctx->RP ) ); + MPI_CHK( mpi_exp_mod( &T2, &T, &ctx->DQ, &ctx->Q, &ctx->RQ ) ); + + /* + * T = (T1 - T2) * (Q^-1 mod P) mod P + */ + MPI_CHK( mpi_sub_mpi( &T, &T1, &T2 ) ); + MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->QP ) ); + MPI_CHK( mpi_mod_mpi( &T, &T1, &ctx->P ) ); + + /* + * T = T2 + T * Q + */ + MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->Q ) ); + MPI_CHK( mpi_add_mpi( &T, &T2, &T1 ) ); + + if( f_rng != NULL ) + { + /* + * Unblind + * T = T * Vf mod N + */ + MPI_CHK( mpi_mul_mpi( &T, &T, Vf ) ); + MPI_CHK( mpi_mod_mpi( &T, &T, &ctx->N ) ); + } +#endif /* POLARSSL_RSA_NO_CRT */ + + olen = ctx->len; + MPI_CHK( mpi_write_binary( &T, output, olen ) ); + +cleanup: + mpi_free( &T ); mpi_free( &T1 ); mpi_free( &T2 ); +#if !defined(POLARSSL_RSA_NO_CRT) && defined(POLARSSL_THREADING_C) + mpi_free( &Vi_copy ); mpi_free( &Vf_copy ); +#endif + + if( ret != 0 ) + return( POLARSSL_ERR_RSA_PRIVATE_FAILED + ret ); + + return( 0 ); +} + +#if defined(POLARSSL_PKCS1_V21) +/** + * Generate and apply the MGF1 operation (from PKCS#1 v2.1) to a buffer. + * + * \param dst buffer to mask + * \param dlen length of destination buffer + * \param src source of the mask generation + * \param slen length of the source buffer + * \param md_ctx message digest context to use + */ +static void mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src, + size_t slen, md_context_t *md_ctx ) +{ + unsigned char mask[POLARSSL_MD_MAX_SIZE]; + unsigned char counter[4]; + unsigned char *p; + unsigned int hlen; + size_t i, use_len; + + memset( mask, 0, POLARSSL_MD_MAX_SIZE ); + memset( counter, 0, 4 ); + + hlen = md_ctx->md_info->size; + + // Generate and apply dbMask + // + p = dst; + + while( dlen > 0 ) + { + use_len = hlen; + if( dlen < hlen ) + use_len = dlen; + + md_starts( md_ctx ); + md_update( md_ctx, src, slen ); + md_update( md_ctx, counter, 4 ); + md_finish( md_ctx, mask ); + + for( i = 0; i < use_len; ++i ) + *p++ ^= mask[i]; + + counter[3]++; + + dlen -= use_len; + } +} +#endif /* POLARSSL_PKCS1_V21 */ + +#if defined(POLARSSL_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSAES-OAEP-ENCRYPT function + */ +int rsa_rsaes_oaep_encrypt( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + const unsigned char *label, size_t label_len, + size_t ilen, + const unsigned char *input, + unsigned char *output ) +{ + size_t olen; + int ret; + unsigned char *p = output; + unsigned int hlen; + const md_info_t *md_info; + md_context_t md_ctx; + + if( mode == RSA_PRIVATE && ctx->padding != RSA_PKCS_V21 ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + if( f_rng == NULL ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + md_info = md_info_from_type( ctx->hash_id ); + if( md_info == NULL ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + olen = ctx->len; + hlen = md_get_size( md_info ); + + if( olen < ilen + 2 * hlen + 2 ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + memset( output, 0, olen ); + + *p++ = 0; + + // Generate a random octet string seed + // + if( ( ret = f_rng( p_rng, p, hlen ) ) != 0 ) + return( POLARSSL_ERR_RSA_RNG_FAILED + ret ); + + p += hlen; + + // Construct DB + // + md( md_info, label, label_len, p ); + p += hlen; + p += olen - 2 * hlen - 2 - ilen; + *p++ = 1; + memcpy( p, input, ilen ); + + md_init( &md_ctx ); + md_init_ctx( &md_ctx, md_info ); + + // maskedDB: Apply dbMask to DB + // + mgf_mask( output + hlen + 1, olen - hlen - 1, output + 1, hlen, + &md_ctx ); + + // maskedSeed: Apply seedMask to seed + // + mgf_mask( output + 1, hlen, output + hlen + 1, olen - hlen - 1, + &md_ctx ); + + md_free( &md_ctx ); + + return( ( mode == RSA_PUBLIC ) + ? rsa_public( ctx, output, output ) + : rsa_private( ctx, f_rng, p_rng, output, output ) ); +} +#endif /* POLARSSL_PKCS1_V21 */ + +#if defined(POLARSSL_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-ENCRYPT function + */ +int rsa_rsaes_pkcs1_v15_encrypt( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t ilen, + const unsigned char *input, + unsigned char *output ) +{ + size_t nb_pad, olen; + int ret; + unsigned char *p = output; + + if( mode == RSA_PRIVATE && ctx->padding != RSA_PKCS_V15 ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + if( f_rng == NULL ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + olen = ctx->len; + + if( olen < ilen + 11 ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + nb_pad = olen - 3 - ilen; + + *p++ = 0; + if( mode == RSA_PUBLIC ) + { + *p++ = RSA_CRYPT; + + while( nb_pad-- > 0 ) + { + int rng_dl = 100; + + do { + ret = f_rng( p_rng, p, 1 ); + } while( *p == 0 && --rng_dl && ret == 0 ); + + // Check if RNG failed to generate data + // + if( rng_dl == 0 || ret != 0 ) + return( POLARSSL_ERR_RSA_RNG_FAILED + ret ); + + p++; + } + } + else + { + *p++ = RSA_SIGN; + + while( nb_pad-- > 0 ) + *p++ = 0xFF; + } + + *p++ = 0; + memcpy( p, input, ilen ); + + return( ( mode == RSA_PUBLIC ) + ? rsa_public( ctx, output, output ) + : rsa_private( ctx, f_rng, p_rng, output, output ) ); +} +#endif /* POLARSSL_PKCS1_V15 */ + +/* + * Add the message padding, then do an RSA operation + */ +int rsa_pkcs1_encrypt( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t ilen, + const unsigned char *input, + unsigned char *output ) +{ + switch( ctx->padding ) + { +#if defined(POLARSSL_PKCS1_V15) + case RSA_PKCS_V15: + return rsa_rsaes_pkcs1_v15_encrypt( ctx, f_rng, p_rng, mode, ilen, + input, output ); +#endif + +#if defined(POLARSSL_PKCS1_V21) + case RSA_PKCS_V21: + return rsa_rsaes_oaep_encrypt( ctx, f_rng, p_rng, mode, NULL, 0, + ilen, input, output ); +#endif + + default: + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + } +} + +#if defined(POLARSSL_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSAES-OAEP-DECRYPT function + */ +int rsa_rsaes_oaep_decrypt( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + const unsigned char *label, size_t label_len, + size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ) +{ + int ret; + size_t ilen, i, pad_len; + unsigned char *p, bad, pad_done; + unsigned char buf[POLARSSL_MPI_MAX_SIZE]; + unsigned char lhash[POLARSSL_MD_MAX_SIZE]; + unsigned int hlen; + const md_info_t *md_info; + md_context_t md_ctx; + + /* + * Parameters sanity checks + */ + if( mode == RSA_PRIVATE && ctx->padding != RSA_PKCS_V21 ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + ilen = ctx->len; + + if( ilen < 16 || ilen > sizeof( buf ) ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + md_info = md_info_from_type( ctx->hash_id ); + if( md_info == NULL ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + /* + * RSA operation + */ + ret = ( mode == RSA_PUBLIC ) + ? rsa_public( ctx, input, buf ) + : rsa_private( ctx, f_rng, p_rng, input, buf ); + + if( ret != 0 ) + return( ret ); + + /* + * Unmask data and generate lHash + */ + hlen = md_get_size( md_info ); + + md_init( &md_ctx ); + md_init_ctx( &md_ctx, md_info ); + + /* Generate lHash */ + md( md_info, label, label_len, lhash ); + + /* seed: Apply seedMask to maskedSeed */ + mgf_mask( buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1, + &md_ctx ); + + /* DB: Apply dbMask to maskedDB */ + mgf_mask( buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen, + &md_ctx ); + + md_free( &md_ctx ); + + /* + * Check contents, in "constant-time" + */ + p = buf; + bad = 0; + + bad |= *p++; /* First byte must be 0 */ + + p += hlen; /* Skip seed */ + + /* Check lHash */ + for( i = 0; i < hlen; i++ ) + bad |= lhash[i] ^ *p++; + + /* Get zero-padding len, but always read till end of buffer + * (minus one, for the 01 byte) */ + pad_len = 0; + pad_done = 0; + for( i = 0; i < ilen - 2 * hlen - 2; i++ ) + { + pad_done |= p[i]; + pad_len += ( pad_done == 0 ); + } + + p += pad_len; + bad |= *p++ ^ 0x01; + + /* + * The only information "leaked" is whether the padding was correct or not + * (eg, no data is copied if it was not correct). This meets the + * recommendations in PKCS#1 v2.2: an opponent cannot distinguish between + * the different error conditions. + */ + if( bad != 0 ) + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + + if( ilen - ( p - buf ) > output_max_len ) + return( POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE ); + + *olen = ilen - (p - buf); + memcpy( output, p, *olen ); + + return( 0 ); +} +#endif /* POLARSSL_PKCS1_V21 */ + +#if defined(POLARSSL_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-DECRYPT function + */ +int rsa_rsaes_pkcs1_v15_decrypt( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len) +{ + int ret; + size_t ilen, pad_count = 0, i; + unsigned char *p, bad, pad_done = 0; + unsigned char buf[POLARSSL_MPI_MAX_SIZE]; + + if( mode == RSA_PRIVATE && ctx->padding != RSA_PKCS_V15 ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + ilen = ctx->len; + + if( ilen < 16 || ilen > sizeof( buf ) ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + ret = ( mode == RSA_PUBLIC ) + ? rsa_public( ctx, input, buf ) + : rsa_private( ctx, f_rng, p_rng, input, buf ); + + if( ret != 0 ) + return( ret ); + + p = buf; + bad = 0; + + /* + * Check and get padding len in "constant-time" + */ + bad |= *p++; /* First byte must be 0 */ + + /* This test does not depend on secret data */ + if( mode == RSA_PRIVATE ) + { + bad |= *p++ ^ RSA_CRYPT; + + /* Get padding len, but always read till end of buffer + * (minus one, for the 00 byte) */ + for( i = 0; i < ilen - 3; i++ ) + { + pad_done |= ( p[i] == 0 ); + pad_count += ( pad_done == 0 ); + } + + p += pad_count; + bad |= *p++; /* Must be zero */ + } + else + { + bad |= *p++ ^ RSA_SIGN; + + /* Get padding len, but always read till end of buffer + * (minus one, for the 00 byte) */ + for( i = 0; i < ilen - 3; i++ ) + { + pad_done |= ( p[i] != 0xFF ); + pad_count += ( pad_done == 0 ); + } + + p += pad_count; + bad |= *p++; /* Must be zero */ + } + + if( bad ) + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + + if( ilen - ( p - buf ) > output_max_len ) + return( POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE ); + + *olen = ilen - (p - buf); + memcpy( output, p, *olen ); + + return( 0 ); +} +#endif /* POLARSSL_PKCS1_V15 */ + +/* + * Do an RSA operation, then remove the message padding + */ +int rsa_pkcs1_decrypt( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len) +{ + switch( ctx->padding ) + { +#if defined(POLARSSL_PKCS1_V15) + case RSA_PKCS_V15: + return rsa_rsaes_pkcs1_v15_decrypt( ctx, f_rng, p_rng, mode, olen, + input, output, output_max_len ); +#endif + +#if defined(POLARSSL_PKCS1_V21) + case RSA_PKCS_V21: + return rsa_rsaes_oaep_decrypt( ctx, f_rng, p_rng, mode, NULL, 0, + olen, input, output, + output_max_len ); +#endif + + default: + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + } +} + +#if defined(POLARSSL_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function + */ +int rsa_rsassa_pss_sign( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ) +{ + size_t olen; + unsigned char *p = sig; + unsigned char salt[POLARSSL_MD_MAX_SIZE]; + unsigned int slen, hlen, offset = 0; + int ret; + size_t msb; + const md_info_t *md_info; + md_context_t md_ctx; + + if( mode == RSA_PRIVATE && ctx->padding != RSA_PKCS_V21 ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + if( f_rng == NULL ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + olen = ctx->len; + + if( md_alg != POLARSSL_MD_NONE ) + { + // Gather length of hash to sign + // + md_info = md_info_from_type( md_alg ); + if( md_info == NULL ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + hashlen = md_get_size( md_info ); + } + + md_info = md_info_from_type( ctx->hash_id ); + if( md_info == NULL ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + hlen = md_get_size( md_info ); + slen = hlen; + + if( olen < hlen + slen + 2 ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + memset( sig, 0, olen ); + + // Generate salt of length slen + // + if( ( ret = f_rng( p_rng, salt, slen ) ) != 0 ) + return( POLARSSL_ERR_RSA_RNG_FAILED + ret ); + + // Note: EMSA-PSS encoding is over the length of N - 1 bits + // + msb = mpi_msb( &ctx->N ) - 1; + p += olen - hlen * 2 - 2; + *p++ = 0x01; + memcpy( p, salt, slen ); + p += slen; + + md_init( &md_ctx ); + md_init_ctx( &md_ctx, md_info ); + + // Generate H = Hash( M' ) + // + md_starts( &md_ctx ); + md_update( &md_ctx, p, 8 ); + md_update( &md_ctx, hash, hashlen ); + md_update( &md_ctx, salt, slen ); + md_finish( &md_ctx, p ); + + // Compensate for boundary condition when applying mask + // + if( msb % 8 == 0 ) + offset = 1; + + // maskedDB: Apply dbMask to DB + // + mgf_mask( sig + offset, olen - hlen - 1 - offset, p, hlen, &md_ctx ); + + md_free( &md_ctx ); + + msb = mpi_msb( &ctx->N ) - 1; + sig[0] &= 0xFF >> ( olen * 8 - msb ); + + p += hlen; + *p++ = 0xBC; + + return( ( mode == RSA_PUBLIC ) + ? rsa_public( ctx, sig, sig ) + : rsa_private( ctx, f_rng, p_rng, sig, sig ) ); +} +#endif /* POLARSSL_PKCS1_V21 */ + +#if defined(POLARSSL_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-V1_5-SIGN function + */ +/* + * Do an RSA operation to sign the message digest + */ +int rsa_rsassa_pkcs1_v15_sign( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ) +{ + size_t nb_pad, olen, oid_size = 0; + unsigned char *p = sig; + const char *oid; + + if( mode == RSA_PRIVATE && ctx->padding != RSA_PKCS_V15 ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + olen = ctx->len; + nb_pad = olen - 3; + + if( md_alg != POLARSSL_MD_NONE ) + { + const md_info_t *md_info = md_info_from_type( md_alg ); + if( md_info == NULL ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + if( oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + nb_pad -= 10 + oid_size; + + hashlen = md_get_size( md_info ); + } + + nb_pad -= hashlen; + + if( ( nb_pad < 8 ) || ( nb_pad > olen ) ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + *p++ = 0; + *p++ = RSA_SIGN; + memset( p, 0xFF, nb_pad ); + p += nb_pad; + *p++ = 0; + + if( md_alg == POLARSSL_MD_NONE ) + { + memcpy( p, hash, hashlen ); + } + else + { + /* + * DigestInfo ::= SEQUENCE { + * digestAlgorithm DigestAlgorithmIdentifier, + * digest Digest } + * + * DigestAlgorithmIdentifier ::= AlgorithmIdentifier + * + * Digest ::= OCTET STRING + */ + *p++ = ASN1_SEQUENCE | ASN1_CONSTRUCTED; + *p++ = (unsigned char) ( 0x08 + oid_size + hashlen ); + *p++ = ASN1_SEQUENCE | ASN1_CONSTRUCTED; + *p++ = (unsigned char) ( 0x04 + oid_size ); + *p++ = ASN1_OID; + *p++ = oid_size & 0xFF; + memcpy( p, oid, oid_size ); + p += oid_size; + *p++ = ASN1_NULL; + *p++ = 0x00; + *p++ = ASN1_OCTET_STRING; + *p++ = hashlen; + memcpy( p, hash, hashlen ); + } + + return( ( mode == RSA_PUBLIC ) + ? rsa_public( ctx, sig, sig ) + : rsa_private( ctx, f_rng, p_rng, sig, sig ) ); +} +#endif /* POLARSSL_PKCS1_V15 */ + +/* + * Do an RSA operation to sign the message digest + */ +int rsa_pkcs1_sign( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ) +{ + switch( ctx->padding ) + { +#if defined(POLARSSL_PKCS1_V15) + case RSA_PKCS_V15: + return rsa_rsassa_pkcs1_v15_sign( ctx, f_rng, p_rng, mode, md_alg, + hashlen, hash, sig ); +#endif + +#if defined(POLARSSL_PKCS1_V21) + case RSA_PKCS_V21: + return rsa_rsassa_pss_sign( ctx, f_rng, p_rng, mode, md_alg, + hashlen, hash, sig ); +#endif + + default: + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + } +} + +#if defined(POLARSSL_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PSS-VERIFY function + */ +int rsa_rsassa_pss_verify_ext( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + md_type_t mgf1_hash_id, + int expected_salt_len, + const unsigned char *sig ) +{ + int ret; + size_t siglen; + unsigned char *p; + unsigned char buf[POLARSSL_MPI_MAX_SIZE]; + unsigned char result[POLARSSL_MD_MAX_SIZE]; + unsigned char zeros[8]; + unsigned int hlen; + size_t slen, msb; + const md_info_t *md_info; + md_context_t md_ctx; + + if( mode == RSA_PRIVATE && ctx->padding != RSA_PKCS_V21 ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + siglen = ctx->len; + + if( siglen < 16 || siglen > sizeof( buf ) ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + ret = ( mode == RSA_PUBLIC ) + ? rsa_public( ctx, sig, buf ) + : rsa_private( ctx, f_rng, p_rng, sig, buf ); + + if( ret != 0 ) + return( ret ); + + p = buf; + + if( buf[siglen - 1] != 0xBC ) + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + + if( md_alg != POLARSSL_MD_NONE ) + { + // Gather length of hash to sign + // + md_info = md_info_from_type( md_alg ); + if( md_info == NULL ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + hashlen = md_get_size( md_info ); + } + + md_info = md_info_from_type( mgf1_hash_id ); + if( md_info == NULL ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + hlen = md_get_size( md_info ); + slen = siglen - hlen - 1; /* Currently length of salt + padding */ + + memset( zeros, 0, 8 ); + + // Note: EMSA-PSS verification is over the length of N - 1 bits + // + msb = mpi_msb( &ctx->N ) - 1; + + // Compensate for boundary condition when applying mask + // + if( msb % 8 == 0 ) + { + p++; + siglen -= 1; + } + if( buf[0] >> ( 8 - siglen * 8 + msb ) ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + md_init( &md_ctx ); + md_init_ctx( &md_ctx, md_info ); + + mgf_mask( p, siglen - hlen - 1, p + siglen - hlen - 1, hlen, &md_ctx ); + + buf[0] &= 0xFF >> ( siglen * 8 - msb ); + + while( p < buf + siglen && *p == 0 ) + p++; + + if( p == buf + siglen || + *p++ != 0x01 ) + { + md_free( &md_ctx ); + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + } + + /* Actual salt len */ + slen -= p - buf; + + if( expected_salt_len != RSA_SALT_LEN_ANY && + slen != (size_t) expected_salt_len ) + { + md_free( &md_ctx ); + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + } + + // Generate H = Hash( M' ) + // + md_starts( &md_ctx ); + md_update( &md_ctx, zeros, 8 ); + md_update( &md_ctx, hash, hashlen ); + md_update( &md_ctx, p, slen ); + md_finish( &md_ctx, result ); + + md_free( &md_ctx ); + + if( memcmp( p + slen, result, hlen ) == 0 ) + return( 0 ); + else + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); +} + +/* + * Simplified PKCS#1 v2.1 RSASSA-PSS-VERIFY function + */ +int rsa_rsassa_pss_verify( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ) +{ + md_type_t mgf1_hash_id = ( ctx->hash_id != POLARSSL_MD_NONE ) + ? (md_type_t) ctx->hash_id + : md_alg; + + return( rsa_rsassa_pss_verify_ext( ctx, f_rng, p_rng, mode, + md_alg, hashlen, hash, + mgf1_hash_id, RSA_SALT_LEN_ANY, + sig ) ); + +} +#endif /* POLARSSL_PKCS1_V21 */ + +#if defined(POLARSSL_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-v1_5-VERIFY function + */ +int rsa_rsassa_pkcs1_v15_verify( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ) +{ + int ret; + size_t len, siglen, asn1_len; + unsigned char *p, *end; + unsigned char buf[POLARSSL_MPI_MAX_SIZE]; + md_type_t msg_md_alg; + const md_info_t *md_info; + asn1_buf oid; + + if( mode == RSA_PRIVATE && ctx->padding != RSA_PKCS_V15 ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + siglen = ctx->len; + + if( siglen < 16 || siglen > sizeof( buf ) ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + ret = ( mode == RSA_PUBLIC ) + ? rsa_public( ctx, sig, buf ) + : rsa_private( ctx, f_rng, p_rng, sig, buf ); + + if( ret != 0 ) + return( ret ); + + p = buf; + + if( *p++ != 0 || *p++ != RSA_SIGN ) + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + + while( *p != 0 ) + { + if( p >= buf + siglen - 1 || *p != 0xFF ) + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + p++; + } + p++; + + len = siglen - ( p - buf ); + + if( len == hashlen && md_alg == POLARSSL_MD_NONE ) + { + if( memcmp( p, hash, hashlen ) == 0 ) + return( 0 ); + else + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + } + + md_info = md_info_from_type( md_alg ); + if( md_info == NULL ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + hashlen = md_get_size( md_info ); + + end = p + len; + + // Parse the ASN.1 structure inside the PKCS#1 v1.5 structure + // + if( ( ret = asn1_get_tag( &p, end, &asn1_len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + + if( asn1_len + 2 != len ) + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + + if( ( ret = asn1_get_tag( &p, end, &asn1_len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + + if( asn1_len + 6 + hashlen != len ) + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + + if( ( ret = asn1_get_tag( &p, end, &oid.len, ASN1_OID ) ) != 0 ) + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + + oid.p = p; + p += oid.len; + + if( oid_get_md_alg( &oid, &msg_md_alg ) != 0 ) + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + + if( md_alg != msg_md_alg ) + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + + /* + * assume the algorithm parameters must be NULL + */ + if( ( ret = asn1_get_tag( &p, end, &asn1_len, ASN1_NULL ) ) != 0 ) + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + + if( ( ret = asn1_get_tag( &p, end, &asn1_len, ASN1_OCTET_STRING ) ) != 0 ) + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + + if( asn1_len != hashlen ) + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + + if( memcmp( p, hash, hashlen ) != 0 ) + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + + p += hashlen; + + if( p != end ) + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + + return( 0 ); +} +#endif /* POLARSSL_PKCS1_V15 */ + +/* + * Do an RSA operation and check the message digest + */ +int rsa_pkcs1_verify( rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ) +{ + switch( ctx->padding ) + { +#if defined(POLARSSL_PKCS1_V15) + case RSA_PKCS_V15: + return rsa_rsassa_pkcs1_v15_verify( ctx, f_rng, p_rng, mode, md_alg, + hashlen, hash, sig ); +#endif + +#if defined(POLARSSL_PKCS1_V21) + case RSA_PKCS_V21: + return rsa_rsassa_pss_verify( ctx, f_rng, p_rng, mode, md_alg, + hashlen, hash, sig ); +#endif + + default: + return( POLARSSL_ERR_RSA_INVALID_PADDING ); + } +} + +/* + * Copy the components of an RSA key + */ +int rsa_copy( rsa_context *dst, const rsa_context *src ) +{ + int ret; + + dst->ver = src->ver; + dst->len = src->len; + + MPI_CHK( mpi_copy( &dst->N, &src->N ) ); + MPI_CHK( mpi_copy( &dst->E, &src->E ) ); + + MPI_CHK( mpi_copy( &dst->D, &src->D ) ); + MPI_CHK( mpi_copy( &dst->P, &src->P ) ); + MPI_CHK( mpi_copy( &dst->Q, &src->Q ) ); + MPI_CHK( mpi_copy( &dst->DP, &src->DP ) ); + MPI_CHK( mpi_copy( &dst->DQ, &src->DQ ) ); + MPI_CHK( mpi_copy( &dst->QP, &src->QP ) ); + + MPI_CHK( mpi_copy( &dst->RN, &src->RN ) ); + MPI_CHK( mpi_copy( &dst->RP, &src->RP ) ); + MPI_CHK( mpi_copy( &dst->RQ, &src->RQ ) ); + +#if !defined(POLARSSL_RSA_NO_CRT) + MPI_CHK( mpi_copy( &dst->Vi, &src->Vi ) ); + MPI_CHK( mpi_copy( &dst->Vf, &src->Vf ) ); +#endif + + dst->padding = src->padding; + dst->hash_id = src->hash_id; + +cleanup: + if( ret != 0 ) + rsa_free( dst ); + + return( ret ); +} + +/* + * Free the components of an RSA key + */ +void rsa_free( rsa_context *ctx ) +{ +#if !defined(POLARSSL_RSA_NO_CRT) + mpi_free( &ctx->Vi ); mpi_free( &ctx->Vf ); +#endif + mpi_free( &ctx->RQ ); mpi_free( &ctx->RP ); mpi_free( &ctx->RN ); + mpi_free( &ctx->QP ); mpi_free( &ctx->DQ ); mpi_free( &ctx->DP ); + mpi_free( &ctx->Q ); mpi_free( &ctx->P ); mpi_free( &ctx->D ); + mpi_free( &ctx->E ); mpi_free( &ctx->N ); + +#if defined(POLARSSL_THREADING_C) + polarssl_mutex_free( &ctx->mutex ); +#endif +} + +#if defined(POLARSSL_SELF_TEST) + +#include "polarssl/sha1.h" + +/* + * Example RSA-1024 keypair, for test purposes + */ +#define KEY_LEN 128 + +#define RSA_N "9292758453063D803DD603D5E777D788" \ + "8ED1D5BF35786190FA2F23EBC0848AEA" \ + "DDA92CA6C3D80B32C4D109BE0F36D6AE" \ + "7130B9CED7ACDF54CFC7555AC14EEBAB" \ + "93A89813FBF3C4F8066D2D800F7C38A8" \ + "1AE31942917403FF4946B0A83D3D3E05" \ + "EE57C6F5F5606FB5D4BC6CD34EE0801A" \ + "5E94BB77B07507233A0BC7BAC8F90F79" + +#define RSA_E "10001" + +#define RSA_D "24BF6185468786FDD303083D25E64EFC" \ + "66CA472BC44D253102F8B4A9D3BFA750" \ + "91386C0077937FE33FA3252D28855837" \ + "AE1B484A8A9A45F7EE8C0C634F99E8CD" \ + "DF79C5CE07EE72C7F123142198164234" \ + "CABB724CF78B8173B9F880FC86322407" \ + "AF1FEDFDDE2BEB674CA15F3E81A1521E" \ + "071513A1E85B5DFA031F21ECAE91A34D" + +#define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \ + "2C01CAD19EA484A87EA4377637E75500" \ + "FCB2005C5C7DD6EC4AC023CDA285D796" \ + "C3D9E75E1EFC42488BB4F1D13AC30A57" + +#define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \ + "E211C2B9E5DB1ED0BF61D0D9899620F4" \ + "910E4168387E3C30AA1E00C339A79508" \ + "8452DD96A9A5EA5D9DCA68DA636032AF" + +#define RSA_DP "C1ACF567564274FB07A0BBAD5D26E298" \ + "3C94D22288ACD763FD8E5600ED4A702D" \ + "F84198A5F06C2E72236AE490C93F07F8" \ + "3CC559CD27BC2D1CA488811730BB5725" + +#define RSA_DQ "4959CBF6F8FEF750AEE6977C155579C7" \ + "D8AAEA56749EA28623272E4F7D0592AF" \ + "7C1F1313CAC9471B5C523BFE592F517B" \ + "407A1BD76C164B93DA2D32A383E58357" + +#define RSA_QP "9AE7FBC99546432DF71896FC239EADAE" \ + "F38D18D2B2F0E2DD275AA977E2BF4411" \ + "F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \ + "A74206CEC169D74BF5A8C50D6F48EA08" + +#define PT_LEN 24 +#define RSA_PT "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \ + "\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD" + +#if defined(POLARSSL_PKCS1_V15) +static int myrand( void *rng_state, unsigned char *output, size_t len ) +{ +#if !defined(__OpenBSD__) + size_t i; + + if( rng_state != NULL ) + rng_state = NULL; + + for( i = 0; i < len; ++i ) + output[i] = rand(); +#else + if( rng_state != NULL ) + rng_state = NULL; + + arc4random_buf( output, len ); +#endif /* !OpenBSD */ + + return( 0 ); +} +#endif /* POLARSSL_PKCS1_V15 */ + +/* + * Checkup routine + */ +int rsa_self_test( int verbose ) +{ + int ret = 0; +#if defined(POLARSSL_PKCS1_V15) + size_t len; + rsa_context rsa; + unsigned char rsa_plaintext[PT_LEN]; + unsigned char rsa_decrypted[PT_LEN]; + unsigned char rsa_ciphertext[KEY_LEN]; +#if defined(POLARSSL_SHA1_C) + unsigned char sha1sum[20]; +#endif + + rsa_init( &rsa, RSA_PKCS_V15, 0 ); + + rsa.len = KEY_LEN; + MPI_CHK( mpi_read_string( &rsa.N , 16, RSA_N ) ); + MPI_CHK( mpi_read_string( &rsa.E , 16, RSA_E ) ); + MPI_CHK( mpi_read_string( &rsa.D , 16, RSA_D ) ); + MPI_CHK( mpi_read_string( &rsa.P , 16, RSA_P ) ); + MPI_CHK( mpi_read_string( &rsa.Q , 16, RSA_Q ) ); + MPI_CHK( mpi_read_string( &rsa.DP, 16, RSA_DP ) ); + MPI_CHK( mpi_read_string( &rsa.DQ, 16, RSA_DQ ) ); + MPI_CHK( mpi_read_string( &rsa.QP, 16, RSA_QP ) ); + + if( verbose != 0 ) + polarssl_printf( " RSA key validation: " ); + + if( rsa_check_pubkey( &rsa ) != 0 || + rsa_check_privkey( &rsa ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + polarssl_printf( "passed\n PKCS#1 encryption : " ); + + memcpy( rsa_plaintext, RSA_PT, PT_LEN ); + + if( rsa_pkcs1_encrypt( &rsa, myrand, NULL, RSA_PUBLIC, PT_LEN, + rsa_plaintext, rsa_ciphertext ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + polarssl_printf( "passed\n PKCS#1 decryption : " ); + + if( rsa_pkcs1_decrypt( &rsa, myrand, NULL, RSA_PRIVATE, &len, + rsa_ciphertext, rsa_decrypted, + sizeof(rsa_decrypted) ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + +#if defined(POLARSSL_SHA1_C) + if( verbose != 0 ) + polarssl_printf( "passed\n PKCS#1 data sign : " ); + + sha1( rsa_plaintext, PT_LEN, sha1sum ); + + if( rsa_pkcs1_sign( &rsa, myrand, NULL, RSA_PRIVATE, POLARSSL_MD_SHA1, 0, + sha1sum, rsa_ciphertext ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + polarssl_printf( "passed\n PKCS#1 sig. verify: " ); + + if( rsa_pkcs1_verify( &rsa, NULL, NULL, RSA_PUBLIC, POLARSSL_MD_SHA1, 0, + sha1sum, rsa_ciphertext ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + polarssl_printf( "passed\n\n" ); +#endif /* POLARSSL_SHA1_C */ + +cleanup: + rsa_free( &rsa ); +#else /* POLARSSL_PKCS1_V15 */ + ((void) verbose); +#endif /* POLARSSL_PKCS1_V15 */ + return( ret ); +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_RSA_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/sha1.c b/component/common/network/ssl/polarssl-1.3.8/library/sha1.c new file mode 100644 index 0000000..20408c7 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/sha1.c @@ -0,0 +1,661 @@ +/* + * FIPS-180-1 compliant SHA-1 implementation + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * The SHA-1 standard was published by NIST in 1993. + * + * http://www.itl.nist.gov/fipspubs/fip180-1.htm + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_SHA1_C) + +#include "polarssl/sha1.h" + +#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST) +#include +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#define polarssl_printf printf +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +#if !defined(POLARSSL_SHA1_ALT) + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +void sha1_init( sha1_context *ctx ) +{ + memset( ctx, 0, sizeof( sha1_context ) ); +} + +void sha1_free( sha1_context *ctx ) +{ + if( ctx == NULL ) + return; + + polarssl_zeroize( ctx, sizeof( sha1_context ) ); +} + +/* + * SHA-1 context setup + */ +void sha1_starts( sha1_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + ctx->state[4] = 0xC3D2E1F0; +} + +void sha1_process( sha1_context *ctx, const unsigned char data[64] ) +{ + uint32_t temp, W[16], A, B, C, D, E; + + GET_UINT32_BE( W[ 0], data, 0 ); + GET_UINT32_BE( W[ 1], data, 4 ); + GET_UINT32_BE( W[ 2], data, 8 ); + GET_UINT32_BE( W[ 3], data, 12 ); + GET_UINT32_BE( W[ 4], data, 16 ); + GET_UINT32_BE( W[ 5], data, 20 ); + GET_UINT32_BE( W[ 6], data, 24 ); + GET_UINT32_BE( W[ 7], data, 28 ); + GET_UINT32_BE( W[ 8], data, 32 ); + GET_UINT32_BE( W[ 9], data, 36 ); + GET_UINT32_BE( W[10], data, 40 ); + GET_UINT32_BE( W[11], data, 44 ); + GET_UINT32_BE( W[12], data, 48 ); + GET_UINT32_BE( W[13], data, 52 ); + GET_UINT32_BE( W[14], data, 56 ); + GET_UINT32_BE( W[15], data, 60 ); + +#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) + +#define R(t) \ +( \ + temp = W[( t - 3 ) & 0x0F] ^ W[( t - 8 ) & 0x0F] ^ \ + W[( t - 14 ) & 0x0F] ^ W[ t & 0x0F], \ + ( W[t & 0x0F] = S(temp,1) ) \ +) + +#define P(a,b,c,d,e,x) \ +{ \ + e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \ +} + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + E = ctx->state[4]; + +#define F(x,y,z) (z ^ (x & (y ^ z))) +#define K 0x5A827999 + + P( A, B, C, D, E, W[0] ); + P( E, A, B, C, D, W[1] ); + P( D, E, A, B, C, W[2] ); + P( C, D, E, A, B, W[3] ); + P( B, C, D, E, A, W[4] ); + P( A, B, C, D, E, W[5] ); + P( E, A, B, C, D, W[6] ); + P( D, E, A, B, C, W[7] ); + P( C, D, E, A, B, W[8] ); + P( B, C, D, E, A, W[9] ); + P( A, B, C, D, E, W[10] ); + P( E, A, B, C, D, W[11] ); + P( D, E, A, B, C, W[12] ); + P( C, D, E, A, B, W[13] ); + P( B, C, D, E, A, W[14] ); + P( A, B, C, D, E, W[15] ); + P( E, A, B, C, D, R(16) ); + P( D, E, A, B, C, R(17) ); + P( C, D, E, A, B, R(18) ); + P( B, C, D, E, A, R(19) ); + +#undef K +#undef F + +#define F(x,y,z) (x ^ y ^ z) +#define K 0x6ED9EBA1 + + P( A, B, C, D, E, R(20) ); + P( E, A, B, C, D, R(21) ); + P( D, E, A, B, C, R(22) ); + P( C, D, E, A, B, R(23) ); + P( B, C, D, E, A, R(24) ); + P( A, B, C, D, E, R(25) ); + P( E, A, B, C, D, R(26) ); + P( D, E, A, B, C, R(27) ); + P( C, D, E, A, B, R(28) ); + P( B, C, D, E, A, R(29) ); + P( A, B, C, D, E, R(30) ); + P( E, A, B, C, D, R(31) ); + P( D, E, A, B, C, R(32) ); + P( C, D, E, A, B, R(33) ); + P( B, C, D, E, A, R(34) ); + P( A, B, C, D, E, R(35) ); + P( E, A, B, C, D, R(36) ); + P( D, E, A, B, C, R(37) ); + P( C, D, E, A, B, R(38) ); + P( B, C, D, E, A, R(39) ); + +#undef K +#undef F + +#define F(x,y,z) ((x & y) | (z & (x | y))) +#define K 0x8F1BBCDC + + P( A, B, C, D, E, R(40) ); + P( E, A, B, C, D, R(41) ); + P( D, E, A, B, C, R(42) ); + P( C, D, E, A, B, R(43) ); + P( B, C, D, E, A, R(44) ); + P( A, B, C, D, E, R(45) ); + P( E, A, B, C, D, R(46) ); + P( D, E, A, B, C, R(47) ); + P( C, D, E, A, B, R(48) ); + P( B, C, D, E, A, R(49) ); + P( A, B, C, D, E, R(50) ); + P( E, A, B, C, D, R(51) ); + P( D, E, A, B, C, R(52) ); + P( C, D, E, A, B, R(53) ); + P( B, C, D, E, A, R(54) ); + P( A, B, C, D, E, R(55) ); + P( E, A, B, C, D, R(56) ); + P( D, E, A, B, C, R(57) ); + P( C, D, E, A, B, R(58) ); + P( B, C, D, E, A, R(59) ); + +#undef K +#undef F + +#define F(x,y,z) (x ^ y ^ z) +#define K 0xCA62C1D6 + + P( A, B, C, D, E, R(60) ); + P( E, A, B, C, D, R(61) ); + P( D, E, A, B, C, R(62) ); + P( C, D, E, A, B, R(63) ); + P( B, C, D, E, A, R(64) ); + P( A, B, C, D, E, R(65) ); + P( E, A, B, C, D, R(66) ); + P( D, E, A, B, C, R(67) ); + P( C, D, E, A, B, R(68) ); + P( B, C, D, E, A, R(69) ); + P( A, B, C, D, E, R(70) ); + P( E, A, B, C, D, R(71) ); + P( D, E, A, B, C, R(72) ); + P( C, D, E, A, B, R(73) ); + P( B, C, D, E, A, R(74) ); + P( A, B, C, D, E, R(75) ); + P( E, A, B, C, D, R(76) ); + P( D, E, A, B, C, R(77) ); + P( C, D, E, A, B, R(78) ); + P( B, C, D, E, A, R(79) ); + +#undef K +#undef F + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; + ctx->state[4] += E; +} + +/* + * SHA-1 process buffer + */ +void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen ) +{ + size_t fill; + uint32_t left; + + if( ilen == 0 ) + return; + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + sha1_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + sha1_process( ctx, input ); + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + memcpy( (void *) (ctx->buffer + left), input, ilen ); +} + +static const unsigned char sha1_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * SHA-1 final digest + */ +void sha1_finish( sha1_context *ctx, unsigned char output[20] ) +{ + uint32_t last, padn; + uint32_t high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_BE( high, msglen, 0 ); + PUT_UINT32_BE( low, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + sha1_update( ctx, sha1_padding, padn ); + sha1_update( ctx, msglen, 8 ); + + PUT_UINT32_BE( ctx->state[0], output, 0 ); + PUT_UINT32_BE( ctx->state[1], output, 4 ); + PUT_UINT32_BE( ctx->state[2], output, 8 ); + PUT_UINT32_BE( ctx->state[3], output, 12 ); + PUT_UINT32_BE( ctx->state[4], output, 16 ); +} + +#endif /* !POLARSSL_SHA1_ALT */ + +/* + * output = SHA-1( input buffer ) + */ +void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] ) +{ + sha1_context ctx; + + sha1_init( &ctx ); + sha1_starts( &ctx ); + sha1_update( &ctx, input, ilen ); + sha1_finish( &ctx, output ); + sha1_free( &ctx ); +} + +#if defined(POLARSSL_FS_IO) +/* + * output = SHA-1( file contents ) + */ +int sha1_file( const char *path, unsigned char output[20] ) +{ + FILE *f; + size_t n; + sha1_context ctx; + unsigned char buf[1024]; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( POLARSSL_ERR_SHA1_FILE_IO_ERROR ); + + sha1_init( &ctx ); + sha1_starts( &ctx ); + + while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) + sha1_update( &ctx, buf, n ); + + sha1_finish( &ctx, output ); + sha1_free( &ctx ); + + if( ferror( f ) != 0 ) + { + fclose( f ); + return( POLARSSL_ERR_SHA1_FILE_IO_ERROR ); + } + + fclose( f ); + return( 0 ); +} +#endif /* POLARSSL_FS_IO */ + +/* + * SHA-1 HMAC context setup + */ +void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key, + size_t keylen ) +{ + size_t i; + unsigned char sum[20]; + + if( keylen > 64 ) + { + sha1( key, keylen, sum ); + keylen = 20; + key = sum; + } + + memset( ctx->ipad, 0x36, 64 ); + memset( ctx->opad, 0x5C, 64 ); + + for( i = 0; i < keylen; i++ ) + { + ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] ); + ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] ); + } + + sha1_starts( ctx ); + sha1_update( ctx, ctx->ipad, 64 ); + + polarssl_zeroize( sum, sizeof( sum ) ); +} + +/* + * SHA-1 HMAC process buffer + */ +void sha1_hmac_update( sha1_context *ctx, const unsigned char *input, + size_t ilen ) +{ + sha1_update( ctx, input, ilen ); +} + +/* + * SHA-1 HMAC final digest + */ +void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] ) +{ + unsigned char tmpbuf[20]; + + sha1_finish( ctx, tmpbuf ); + sha1_starts( ctx ); + sha1_update( ctx, ctx->opad, 64 ); + sha1_update( ctx, tmpbuf, 20 ); + sha1_finish( ctx, output ); + + polarssl_zeroize( tmpbuf, sizeof( tmpbuf ) ); +} + +/* + * SHA1 HMAC context reset + */ +void sha1_hmac_reset( sha1_context *ctx ) +{ + sha1_starts( ctx ); + sha1_update( ctx, ctx->ipad, 64 ); +} + +/* + * output = HMAC-SHA-1( hmac key, input buffer ) + */ +void sha1_hmac( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char output[20] ) +{ + sha1_context ctx; + + sha1_init( &ctx ); + sha1_hmac_starts( &ctx, key, keylen ); + sha1_hmac_update( &ctx, input, ilen ); + sha1_hmac_finish( &ctx, output ); + sha1_free( &ctx ); +} + +#if defined(POLARSSL_SELF_TEST) +/* + * FIPS-180-1 test vectors + */ +static unsigned char sha1_test_buf[3][57] = +{ + { "abc" }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + { "" } +}; + +static const int sha1_test_buflen[3] = +{ + 3, 56, 1000 +}; + +static const unsigned char sha1_test_sum[3][20] = +{ + { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E, + 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D }, + { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE, + 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 }, + { 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E, + 0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F } +}; + +/* + * RFC 2202 test vectors + */ +static unsigned char sha1_hmac_test_key[7][26] = +{ + { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B" + "\x0B\x0B\x0B\x0B" }, + { "Jefe" }, + { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA" }, + { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10" + "\x11\x12\x13\x14\x15\x16\x17\x18\x19" }, + { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C" + "\x0C\x0C\x0C\x0C" }, + { "" }, /* 0xAA 80 times */ + { "" } +}; + +static const int sha1_hmac_test_keylen[7] = +{ + 20, 4, 20, 25, 20, 80, 80 +}; + +static unsigned char sha1_hmac_test_buf[7][74] = +{ + { "Hi There" }, + { "what do ya want for nothing?" }, + { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" }, + { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" }, + { "Test With Truncation" }, + { "Test Using Larger Than Block-Size Key - Hash Key First" }, + { "Test Using Larger Than Block-Size Key and Larger" + " Than One Block-Size Data" } +}; + +static const int sha1_hmac_test_buflen[7] = +{ + 8, 28, 50, 50, 20, 54, 73 +}; + +static const unsigned char sha1_hmac_test_sum[7][20] = +{ + { 0xB6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, 0xE2, 0x8B, + 0xC0, 0xB6, 0xFB, 0x37, 0x8C, 0x8E, 0xF1, 0x46, 0xBE, 0x00 }, + { 0xEF, 0xFC, 0xDF, 0x6A, 0xE5, 0xEB, 0x2F, 0xA2, 0xD2, 0x74, + 0x16, 0xD5, 0xF1, 0x84, 0xDF, 0x9C, 0x25, 0x9A, 0x7C, 0x79 }, + { 0x12, 0x5D, 0x73, 0x42, 0xB9, 0xAC, 0x11, 0xCD, 0x91, 0xA3, + 0x9A, 0xF4, 0x8A, 0xA1, 0x7B, 0x4F, 0x63, 0xF1, 0x75, 0xD3 }, + { 0x4C, 0x90, 0x07, 0xF4, 0x02, 0x62, 0x50, 0xC6, 0xBC, 0x84, + 0x14, 0xF9, 0xBF, 0x50, 0xC8, 0x6C, 0x2D, 0x72, 0x35, 0xDA }, + { 0x4C, 0x1A, 0x03, 0x42, 0x4B, 0x55, 0xE0, 0x7F, 0xE7, 0xF2, + 0x7B, 0xE1 }, + { 0xAA, 0x4A, 0xE5, 0xE1, 0x52, 0x72, 0xD0, 0x0E, 0x95, 0x70, + 0x56, 0x37, 0xCE, 0x8A, 0x3B, 0x55, 0xED, 0x40, 0x21, 0x12 }, + { 0xE8, 0xE9, 0x9D, 0x0F, 0x45, 0x23, 0x7D, 0x78, 0x6D, 0x6B, + 0xBA, 0xA7, 0x96, 0x5C, 0x78, 0x08, 0xBB, 0xFF, 0x1A, 0x91 } +}; + +/* + * Checkup routine + */ +int sha1_self_test( int verbose ) +{ + int i, j, buflen, ret = 0; + unsigned char buf[1024]; + unsigned char sha1sum[20]; + sha1_context ctx; + + sha1_init( &ctx ); + + /* + * SHA-1 + */ + for( i = 0; i < 3; i++ ) + { + if( verbose != 0 ) + polarssl_printf( " SHA-1 test #%d: ", i + 1 ); + + sha1_starts( &ctx ); + + if( i == 2 ) + { + memset( buf, 'a', buflen = 1000 ); + + for( j = 0; j < 1000; j++ ) + sha1_update( &ctx, buf, buflen ); + } + else + sha1_update( &ctx, sha1_test_buf[i], + sha1_test_buflen[i] ); + + sha1_finish( &ctx, sha1sum ); + + if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); + + for( i = 0; i < 7; i++ ) + { + if( verbose != 0 ) + polarssl_printf( " HMAC-SHA-1 test #%d: ", i + 1 ); + + if( i == 5 || i == 6 ) + { + memset( buf, '\xAA', buflen = 80 ); + sha1_hmac_starts( &ctx, buf, buflen ); + } + else + sha1_hmac_starts( &ctx, sha1_hmac_test_key[i], + sha1_hmac_test_keylen[i] ); + + sha1_hmac_update( &ctx, sha1_hmac_test_buf[i], + sha1_hmac_test_buflen[i] ); + + sha1_hmac_finish( &ctx, sha1sum ); + + buflen = ( i == 4 ) ? 12 : 20; + + if( memcmp( sha1sum, sha1_hmac_test_sum[i], buflen ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); + +exit: + sha1_free( &ctx ); + + return( ret ); +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_SHA1_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/sha256.c b/component/common/network/ssl/polarssl-1.3.8/library/sha256.c new file mode 100644 index 0000000..4fc6698 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/sha256.c @@ -0,0 +1,742 @@ +/* + * FIPS-180-2 compliant SHA-256 implementation + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * The SHA-256 Secure Hash Standard was published by NIST in 2002. + * + * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_SHA256_C) + +#include "polarssl/sha256.h" + +#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST) +#include +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#define polarssl_printf printf +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +#if !defined(POLARSSL_SHA256_ALT) + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +void sha256_init( sha256_context *ctx ) +{ + memset( ctx, 0, sizeof( sha256_context ) ); +} + +void sha256_free( sha256_context *ctx ) +{ + if( ctx == NULL ) + return; + + polarssl_zeroize( ctx, sizeof( sha256_context ) ); +} + +/* + * SHA-256 context setup + */ +void sha256_starts( sha256_context *ctx, int is224 ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + if( is224 == 0 ) + { + /* SHA-256 */ + ctx->state[0] = 0x6A09E667; + ctx->state[1] = 0xBB67AE85; + ctx->state[2] = 0x3C6EF372; + ctx->state[3] = 0xA54FF53A; + ctx->state[4] = 0x510E527F; + ctx->state[5] = 0x9B05688C; + ctx->state[6] = 0x1F83D9AB; + ctx->state[7] = 0x5BE0CD19; + } + else + { + /* SHA-224 */ + ctx->state[0] = 0xC1059ED8; + ctx->state[1] = 0x367CD507; + ctx->state[2] = 0x3070DD17; + ctx->state[3] = 0xF70E5939; + ctx->state[4] = 0xFFC00B31; + ctx->state[5] = 0x68581511; + ctx->state[6] = 0x64F98FA7; + ctx->state[7] = 0xBEFA4FA4; + } + + ctx->is224 = is224; +} + +void sha256_process( sha256_context *ctx, const unsigned char data[64] ) +{ + uint32_t temp1, temp2, W[64]; + uint32_t A, B, C, D, E, F, G, H; + + GET_UINT32_BE( W[ 0], data, 0 ); + GET_UINT32_BE( W[ 1], data, 4 ); + GET_UINT32_BE( W[ 2], data, 8 ); + GET_UINT32_BE( W[ 3], data, 12 ); + GET_UINT32_BE( W[ 4], data, 16 ); + GET_UINT32_BE( W[ 5], data, 20 ); + GET_UINT32_BE( W[ 6], data, 24 ); + GET_UINT32_BE( W[ 7], data, 28 ); + GET_UINT32_BE( W[ 8], data, 32 ); + GET_UINT32_BE( W[ 9], data, 36 ); + GET_UINT32_BE( W[10], data, 40 ); + GET_UINT32_BE( W[11], data, 44 ); + GET_UINT32_BE( W[12], data, 48 ); + GET_UINT32_BE( W[13], data, 52 ); + GET_UINT32_BE( W[14], data, 56 ); + GET_UINT32_BE( W[15], data, 60 ); + +#define SHR(x,n) ((x & 0xFFFFFFFF) >> n) +#define ROTR(x,n) (SHR(x,n) | (x << (32 - n))) + +#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3)) +#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10)) + +#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22)) +#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25)) + +#define F0(x,y,z) ((x & y) | (z & (x | y))) +#define F1(x,y,z) (z ^ (x & (y ^ z))) + +#define R(t) \ +( \ + W[t] = S1(W[t - 2]) + W[t - 7] + \ + S0(W[t - 15]) + W[t - 16] \ +) + +#define P(a,b,c,d,e,f,g,h,x,K) \ +{ \ + temp1 = h + S3(e) + F1(e,f,g) + K + x; \ + temp2 = S2(a) + F0(a,b,c); \ + d += temp1; h = temp1 + temp2; \ +} + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + E = ctx->state[4]; + F = ctx->state[5]; + G = ctx->state[6]; + H = ctx->state[7]; + + P( A, B, C, D, E, F, G, H, W[ 0], 0x428A2F98 ); + P( H, A, B, C, D, E, F, G, W[ 1], 0x71374491 ); + P( G, H, A, B, C, D, E, F, W[ 2], 0xB5C0FBCF ); + P( F, G, H, A, B, C, D, E, W[ 3], 0xE9B5DBA5 ); + P( E, F, G, H, A, B, C, D, W[ 4], 0x3956C25B ); + P( D, E, F, G, H, A, B, C, W[ 5], 0x59F111F1 ); + P( C, D, E, F, G, H, A, B, W[ 6], 0x923F82A4 ); + P( B, C, D, E, F, G, H, A, W[ 7], 0xAB1C5ED5 ); + P( A, B, C, D, E, F, G, H, W[ 8], 0xD807AA98 ); + P( H, A, B, C, D, E, F, G, W[ 9], 0x12835B01 ); + P( G, H, A, B, C, D, E, F, W[10], 0x243185BE ); + P( F, G, H, A, B, C, D, E, W[11], 0x550C7DC3 ); + P( E, F, G, H, A, B, C, D, W[12], 0x72BE5D74 ); + P( D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE ); + P( C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7 ); + P( B, C, D, E, F, G, H, A, W[15], 0xC19BF174 ); + P( A, B, C, D, E, F, G, H, R(16), 0xE49B69C1 ); + P( H, A, B, C, D, E, F, G, R(17), 0xEFBE4786 ); + P( G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6 ); + P( F, G, H, A, B, C, D, E, R(19), 0x240CA1CC ); + P( E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F ); + P( D, E, F, G, H, A, B, C, R(21), 0x4A7484AA ); + P( C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC ); + P( B, C, D, E, F, G, H, A, R(23), 0x76F988DA ); + P( A, B, C, D, E, F, G, H, R(24), 0x983E5152 ); + P( H, A, B, C, D, E, F, G, R(25), 0xA831C66D ); + P( G, H, A, B, C, D, E, F, R(26), 0xB00327C8 ); + P( F, G, H, A, B, C, D, E, R(27), 0xBF597FC7 ); + P( E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3 ); + P( D, E, F, G, H, A, B, C, R(29), 0xD5A79147 ); + P( C, D, E, F, G, H, A, B, R(30), 0x06CA6351 ); + P( B, C, D, E, F, G, H, A, R(31), 0x14292967 ); + P( A, B, C, D, E, F, G, H, R(32), 0x27B70A85 ); + P( H, A, B, C, D, E, F, G, R(33), 0x2E1B2138 ); + P( G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC ); + P( F, G, H, A, B, C, D, E, R(35), 0x53380D13 ); + P( E, F, G, H, A, B, C, D, R(36), 0x650A7354 ); + P( D, E, F, G, H, A, B, C, R(37), 0x766A0ABB ); + P( C, D, E, F, G, H, A, B, R(38), 0x81C2C92E ); + P( B, C, D, E, F, G, H, A, R(39), 0x92722C85 ); + P( A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1 ); + P( H, A, B, C, D, E, F, G, R(41), 0xA81A664B ); + P( G, H, A, B, C, D, E, F, R(42), 0xC24B8B70 ); + P( F, G, H, A, B, C, D, E, R(43), 0xC76C51A3 ); + P( E, F, G, H, A, B, C, D, R(44), 0xD192E819 ); + P( D, E, F, G, H, A, B, C, R(45), 0xD6990624 ); + P( C, D, E, F, G, H, A, B, R(46), 0xF40E3585 ); + P( B, C, D, E, F, G, H, A, R(47), 0x106AA070 ); + P( A, B, C, D, E, F, G, H, R(48), 0x19A4C116 ); + P( H, A, B, C, D, E, F, G, R(49), 0x1E376C08 ); + P( G, H, A, B, C, D, E, F, R(50), 0x2748774C ); + P( F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5 ); + P( E, F, G, H, A, B, C, D, R(52), 0x391C0CB3 ); + P( D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A ); + P( C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F ); + P( B, C, D, E, F, G, H, A, R(55), 0x682E6FF3 ); + P( A, B, C, D, E, F, G, H, R(56), 0x748F82EE ); + P( H, A, B, C, D, E, F, G, R(57), 0x78A5636F ); + P( G, H, A, B, C, D, E, F, R(58), 0x84C87814 ); + P( F, G, H, A, B, C, D, E, R(59), 0x8CC70208 ); + P( E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA ); + P( D, E, F, G, H, A, B, C, R(61), 0xA4506CEB ); + P( C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7 ); + P( B, C, D, E, F, G, H, A, R(63), 0xC67178F2 ); + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; + ctx->state[4] += E; + ctx->state[5] += F; + ctx->state[6] += G; + ctx->state[7] += H; +} + +/* + * SHA-256 process buffer + */ +void sha256_update( sha256_context *ctx, const unsigned char *input, + size_t ilen ) +{ + size_t fill; + uint32_t left; + + if( ilen == 0 ) + return; + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + sha256_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + sha256_process( ctx, input ); + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + memcpy( (void *) (ctx->buffer + left), input, ilen ); +} + +static const unsigned char sha256_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * SHA-256 final digest + */ +void sha256_finish( sha256_context *ctx, unsigned char output[32] ) +{ + uint32_t last, padn; + uint32_t high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_BE( high, msglen, 0 ); + PUT_UINT32_BE( low, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + sha256_update( ctx, sha256_padding, padn ); + sha256_update( ctx, msglen, 8 ); + + PUT_UINT32_BE( ctx->state[0], output, 0 ); + PUT_UINT32_BE( ctx->state[1], output, 4 ); + PUT_UINT32_BE( ctx->state[2], output, 8 ); + PUT_UINT32_BE( ctx->state[3], output, 12 ); + PUT_UINT32_BE( ctx->state[4], output, 16 ); + PUT_UINT32_BE( ctx->state[5], output, 20 ); + PUT_UINT32_BE( ctx->state[6], output, 24 ); + + if( ctx->is224 == 0 ) + PUT_UINT32_BE( ctx->state[7], output, 28 ); +} + +#endif /* !POLARSSL_SHA256_ALT */ + +/* + * output = SHA-256( input buffer ) + */ +void sha256( const unsigned char *input, size_t ilen, + unsigned char output[32], int is224 ) +{ + sha256_context ctx; + + sha256_init( &ctx ); + sha256_starts( &ctx, is224 ); + sha256_update( &ctx, input, ilen ); + sha256_finish( &ctx, output ); + sha256_free( &ctx ); +} + +#if defined(POLARSSL_FS_IO) +/* + * output = SHA-256( file contents ) + */ +int sha256_file( const char *path, unsigned char output[32], int is224 ) +{ + FILE *f; + size_t n; + sha256_context ctx; + unsigned char buf[1024]; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( POLARSSL_ERR_SHA256_FILE_IO_ERROR ); + + sha256_init( &ctx ); + sha256_starts( &ctx, is224 ); + + while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) + sha256_update( &ctx, buf, n ); + + sha256_finish( &ctx, output ); + sha256_free( &ctx ); + + if( ferror( f ) != 0 ) + { + fclose( f ); + return( POLARSSL_ERR_SHA256_FILE_IO_ERROR ); + } + + fclose( f ); + return( 0 ); +} +#endif /* POLARSSL_FS_IO */ + +/* + * SHA-256 HMAC context setup + */ +void sha256_hmac_starts( sha256_context *ctx, const unsigned char *key, + size_t keylen, int is224 ) +{ + size_t i; + unsigned char sum[32]; + + if( keylen > 64 ) + { + sha256( key, keylen, sum, is224 ); + keylen = ( is224 ) ? 28 : 32; + key = sum; + } + + memset( ctx->ipad, 0x36, 64 ); + memset( ctx->opad, 0x5C, 64 ); + + for( i = 0; i < keylen; i++ ) + { + ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] ); + ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] ); + } + + sha256_starts( ctx, is224 ); + sha256_update( ctx, ctx->ipad, 64 ); + + polarssl_zeroize( sum, sizeof( sum ) ); +} + +/* + * SHA-256 HMAC process buffer + */ +void sha256_hmac_update( sha256_context *ctx, const unsigned char *input, + size_t ilen ) +{ + sha256_update( ctx, input, ilen ); +} + +/* + * SHA-256 HMAC final digest + */ +void sha256_hmac_finish( sha256_context *ctx, unsigned char output[32] ) +{ + int is224, hlen; + unsigned char tmpbuf[32]; + + is224 = ctx->is224; + hlen = ( is224 == 0 ) ? 32 : 28; + + sha256_finish( ctx, tmpbuf ); + sha256_starts( ctx, is224 ); + sha256_update( ctx, ctx->opad, 64 ); + sha256_update( ctx, tmpbuf, hlen ); + sha256_finish( ctx, output ); + + polarssl_zeroize( tmpbuf, sizeof( tmpbuf ) ); +} + +/* + * SHA-256 HMAC context reset + */ +void sha256_hmac_reset( sha256_context *ctx ) +{ + sha256_starts( ctx, ctx->is224 ); + sha256_update( ctx, ctx->ipad, 64 ); +} + +/* + * output = HMAC-SHA-256( hmac key, input buffer ) + */ +void sha256_hmac( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char output[32], int is224 ) +{ + sha256_context ctx; + + sha256_init( &ctx ); + sha256_hmac_starts( &ctx, key, keylen, is224 ); + sha256_hmac_update( &ctx, input, ilen ); + sha256_hmac_finish( &ctx, output ); + sha256_free( &ctx ); +} + +#if defined(POLARSSL_SELF_TEST) +/* + * FIPS-180-2 test vectors + */ +static unsigned char sha256_test_buf[3][57] = +{ + { "abc" }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + { "" } +}; + +static const int sha256_test_buflen[3] = +{ + 3, 56, 1000 +}; + +static const unsigned char sha256_test_sum[6][32] = +{ + /* + * SHA-224 test vectors + */ + { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22, + 0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3, + 0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7, + 0xE3, 0x6C, 0x9D, 0xA7 }, + { 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC, + 0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50, + 0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19, + 0x52, 0x52, 0x25, 0x25 }, + { 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8, + 0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B, + 0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE, + 0x4E, 0xE7, 0xAD, 0x67 }, + + /* + * SHA-256 test vectors + */ + { 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA, + 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23, + 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C, + 0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD }, + { 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8, + 0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39, + 0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67, + 0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 }, + { 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92, + 0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67, + 0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E, + 0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 } +}; + +/* + * RFC 4231 test vectors + */ +static unsigned char sha256_hmac_test_key[7][26] = +{ + { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B" + "\x0B\x0B\x0B\x0B" }, + { "Jefe" }, + { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA" }, + { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10" + "\x11\x12\x13\x14\x15\x16\x17\x18\x19" }, + { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C" + "\x0C\x0C\x0C\x0C" }, + { "" }, /* 0xAA 131 times */ + { "" } +}; + +static const int sha256_hmac_test_keylen[7] = +{ + 20, 4, 20, 25, 20, 131, 131 +}; + +static unsigned char sha256_hmac_test_buf[7][153] = +{ + { "Hi There" }, + { "what do ya want for nothing?" }, + { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" }, + { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" }, + { "Test With Truncation" }, + { "Test Using Larger Than Block-Size Key - Hash Key First" }, + { "This is a test using a larger than block-size key " + "and a larger than block-size data. The key needs to " + "be hashed before being used by the HMAC algorithm." } +}; + +static const int sha256_hmac_test_buflen[7] = +{ + 8, 28, 50, 50, 20, 54, 152 +}; + +static const unsigned char sha256_hmac_test_sum[14][32] = +{ + /* + * HMAC-SHA-224 test vectors + */ + { 0x89, 0x6F, 0xB1, 0x12, 0x8A, 0xBB, 0xDF, 0x19, + 0x68, 0x32, 0x10, 0x7C, 0xD4, 0x9D, 0xF3, 0x3F, + 0x47, 0xB4, 0xB1, 0x16, 0x99, 0x12, 0xBA, 0x4F, + 0x53, 0x68, 0x4B, 0x22 }, + { 0xA3, 0x0E, 0x01, 0x09, 0x8B, 0xC6, 0xDB, 0xBF, + 0x45, 0x69, 0x0F, 0x3A, 0x7E, 0x9E, 0x6D, 0x0F, + 0x8B, 0xBE, 0xA2, 0xA3, 0x9E, 0x61, 0x48, 0x00, + 0x8F, 0xD0, 0x5E, 0x44 }, + { 0x7F, 0xB3, 0xCB, 0x35, 0x88, 0xC6, 0xC1, 0xF6, + 0xFF, 0xA9, 0x69, 0x4D, 0x7D, 0x6A, 0xD2, 0x64, + 0x93, 0x65, 0xB0, 0xC1, 0xF6, 0x5D, 0x69, 0xD1, + 0xEC, 0x83, 0x33, 0xEA }, + { 0x6C, 0x11, 0x50, 0x68, 0x74, 0x01, 0x3C, 0xAC, + 0x6A, 0x2A, 0xBC, 0x1B, 0xB3, 0x82, 0x62, 0x7C, + 0xEC, 0x6A, 0x90, 0xD8, 0x6E, 0xFC, 0x01, 0x2D, + 0xE7, 0xAF, 0xEC, 0x5A }, + { 0x0E, 0x2A, 0xEA, 0x68, 0xA9, 0x0C, 0x8D, 0x37, + 0xC9, 0x88, 0xBC, 0xDB, 0x9F, 0xCA, 0x6F, 0xA8 }, + { 0x95, 0xE9, 0xA0, 0xDB, 0x96, 0x20, 0x95, 0xAD, + 0xAE, 0xBE, 0x9B, 0x2D, 0x6F, 0x0D, 0xBC, 0xE2, + 0xD4, 0x99, 0xF1, 0x12, 0xF2, 0xD2, 0xB7, 0x27, + 0x3F, 0xA6, 0x87, 0x0E }, + { 0x3A, 0x85, 0x41, 0x66, 0xAC, 0x5D, 0x9F, 0x02, + 0x3F, 0x54, 0xD5, 0x17, 0xD0, 0xB3, 0x9D, 0xBD, + 0x94, 0x67, 0x70, 0xDB, 0x9C, 0x2B, 0x95, 0xC9, + 0xF6, 0xF5, 0x65, 0xD1 }, + + /* + * HMAC-SHA-256 test vectors + */ + { 0xB0, 0x34, 0x4C, 0x61, 0xD8, 0xDB, 0x38, 0x53, + 0x5C, 0xA8, 0xAF, 0xCE, 0xAF, 0x0B, 0xF1, 0x2B, + 0x88, 0x1D, 0xC2, 0x00, 0xC9, 0x83, 0x3D, 0xA7, + 0x26, 0xE9, 0x37, 0x6C, 0x2E, 0x32, 0xCF, 0xF7 }, + { 0x5B, 0xDC, 0xC1, 0x46, 0xBF, 0x60, 0x75, 0x4E, + 0x6A, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xC7, + 0x5A, 0x00, 0x3F, 0x08, 0x9D, 0x27, 0x39, 0x83, + 0x9D, 0xEC, 0x58, 0xB9, 0x64, 0xEC, 0x38, 0x43 }, + { 0x77, 0x3E, 0xA9, 0x1E, 0x36, 0x80, 0x0E, 0x46, + 0x85, 0x4D, 0xB8, 0xEB, 0xD0, 0x91, 0x81, 0xA7, + 0x29, 0x59, 0x09, 0x8B, 0x3E, 0xF8, 0xC1, 0x22, + 0xD9, 0x63, 0x55, 0x14, 0xCE, 0xD5, 0x65, 0xFE }, + { 0x82, 0x55, 0x8A, 0x38, 0x9A, 0x44, 0x3C, 0x0E, + 0xA4, 0xCC, 0x81, 0x98, 0x99, 0xF2, 0x08, 0x3A, + 0x85, 0xF0, 0xFA, 0xA3, 0xE5, 0x78, 0xF8, 0x07, + 0x7A, 0x2E, 0x3F, 0xF4, 0x67, 0x29, 0x66, 0x5B }, + { 0xA3, 0xB6, 0x16, 0x74, 0x73, 0x10, 0x0E, 0xE0, + 0x6E, 0x0C, 0x79, 0x6C, 0x29, 0x55, 0x55, 0x2B }, + { 0x60, 0xE4, 0x31, 0x59, 0x1E, 0xE0, 0xB6, 0x7F, + 0x0D, 0x8A, 0x26, 0xAA, 0xCB, 0xF5, 0xB7, 0x7F, + 0x8E, 0x0B, 0xC6, 0x21, 0x37, 0x28, 0xC5, 0x14, + 0x05, 0x46, 0x04, 0x0F, 0x0E, 0xE3, 0x7F, 0x54 }, + { 0x9B, 0x09, 0xFF, 0xA7, 0x1B, 0x94, 0x2F, 0xCB, + 0x27, 0x63, 0x5F, 0xBC, 0xD5, 0xB0, 0xE9, 0x44, + 0xBF, 0xDC, 0x63, 0x64, 0x4F, 0x07, 0x13, 0x93, + 0x8A, 0x7F, 0x51, 0x53, 0x5C, 0x3A, 0x35, 0xE2 } +}; + +/* + * Checkup routine + */ +int sha256_self_test( int verbose ) +{ + int i, j, k, buflen, ret = 0; + unsigned char buf[1024]; + unsigned char sha256sum[32]; + sha256_context ctx; + + sha256_init( &ctx ); + + for( i = 0; i < 6; i++ ) + { + j = i % 3; + k = i < 3; + + if( verbose != 0 ) + polarssl_printf( " SHA-%d test #%d: ", 256 - k * 32, j + 1 ); + + sha256_starts( &ctx, k ); + + if( j == 2 ) + { + memset( buf, 'a', buflen = 1000 ); + + for( j = 0; j < 1000; j++ ) + sha256_update( &ctx, buf, buflen ); + } + else + sha256_update( &ctx, sha256_test_buf[j], + sha256_test_buflen[j] ); + + sha256_finish( &ctx, sha256sum ); + + if( memcmp( sha256sum, sha256_test_sum[i], 32 - k * 4 ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); + + for( i = 0; i < 14; i++ ) + { + j = i % 7; + k = i < 7; + + if( verbose != 0 ) + polarssl_printf( " HMAC-SHA-%d test #%d: ", 256 - k * 32, j + 1 ); + + if( j == 5 || j == 6 ) + { + memset( buf, '\xAA', buflen = 131 ); + sha256_hmac_starts( &ctx, buf, buflen, k ); + } + else + sha256_hmac_starts( &ctx, sha256_hmac_test_key[j], + sha256_hmac_test_keylen[j], k ); + + sha256_hmac_update( &ctx, sha256_hmac_test_buf[j], + sha256_hmac_test_buflen[j] ); + + sha256_hmac_finish( &ctx, sha256sum ); + + buflen = ( j == 4 ) ? 16 : 32 - k * 4; + + if( memcmp( sha256sum, sha256_hmac_test_sum[i], buflen ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); + +exit: + sha256_free( &ctx ); + + return( ret ); +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_SHA256_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/sha512.c b/component/common/network/ssl/polarssl-1.3.8/library/sha512.c new file mode 100644 index 0000000..f1d1525 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/sha512.c @@ -0,0 +1,796 @@ +/* + * FIPS-180-2 compliant SHA-384/512 implementation + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * The SHA-512 Secure Hash Standard was published by NIST in 2002. + * + * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_SHA512_C) + +#include "polarssl/sha512.h" + +#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST) +#include +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#define polarssl_printf printf +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +#if !defined(POLARSSL_SHA512_ALT) + +/* + * 64-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT64_BE +#define GET_UINT64_BE(n,b,i) \ +{ \ + (n) = ( (uint64_t) (b)[(i) ] << 56 ) \ + | ( (uint64_t) (b)[(i) + 1] << 48 ) \ + | ( (uint64_t) (b)[(i) + 2] << 40 ) \ + | ( (uint64_t) (b)[(i) + 3] << 32 ) \ + | ( (uint64_t) (b)[(i) + 4] << 24 ) \ + | ( (uint64_t) (b)[(i) + 5] << 16 ) \ + | ( (uint64_t) (b)[(i) + 6] << 8 ) \ + | ( (uint64_t) (b)[(i) + 7] ); \ +} +#endif /* GET_UINT64_BE */ + +#ifndef PUT_UINT64_BE +#define PUT_UINT64_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 56 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 48 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 40 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) >> 32 ); \ + (b)[(i) + 4] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 5] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 6] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 7] = (unsigned char) ( (n) ); \ +} +#endif /* PUT_UINT64_BE */ + +/* + * Round constants + */ +static const uint64_t K[80] = +{ + UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD), + UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC), + UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019), + UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118), + UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE), + UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2), + UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1), + UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694), + UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3), + UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65), + UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483), + UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5), + UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210), + UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4), + UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725), + UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70), + UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926), + UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF), + UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8), + UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B), + UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001), + UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30), + UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910), + UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8), + UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53), + UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8), + UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB), + UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3), + UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60), + UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC), + UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9), + UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B), + UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207), + UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178), + UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6), + UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B), + UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493), + UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C), + UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A), + UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817) +}; + +void sha512_init( sha512_context *ctx ) +{ + memset( ctx, 0, sizeof( sha512_context ) ); +} + +void sha512_free( sha512_context *ctx ) +{ + if( ctx == NULL ) + return; + + polarssl_zeroize( ctx, sizeof( sha512_context ) ); +} + +/* + * SHA-512 context setup + */ +void sha512_starts( sha512_context *ctx, int is384 ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + if( is384 == 0 ) + { + /* SHA-512 */ + ctx->state[0] = UL64(0x6A09E667F3BCC908); + ctx->state[1] = UL64(0xBB67AE8584CAA73B); + ctx->state[2] = UL64(0x3C6EF372FE94F82B); + ctx->state[3] = UL64(0xA54FF53A5F1D36F1); + ctx->state[4] = UL64(0x510E527FADE682D1); + ctx->state[5] = UL64(0x9B05688C2B3E6C1F); + ctx->state[6] = UL64(0x1F83D9ABFB41BD6B); + ctx->state[7] = UL64(0x5BE0CD19137E2179); + } + else + { + /* SHA-384 */ + ctx->state[0] = UL64(0xCBBB9D5DC1059ED8); + ctx->state[1] = UL64(0x629A292A367CD507); + ctx->state[2] = UL64(0x9159015A3070DD17); + ctx->state[3] = UL64(0x152FECD8F70E5939); + ctx->state[4] = UL64(0x67332667FFC00B31); + ctx->state[5] = UL64(0x8EB44A8768581511); + ctx->state[6] = UL64(0xDB0C2E0D64F98FA7); + ctx->state[7] = UL64(0x47B5481DBEFA4FA4); + } + + ctx->is384 = is384; +} + +void sha512_process( sha512_context *ctx, const unsigned char data[128] ) +{ + int i; + uint64_t temp1, temp2, W[80]; + uint64_t A, B, C, D, E, F, G, H; + +#define SHR(x,n) (x >> n) +#define ROTR(x,n) (SHR(x,n) | (x << (64 - n))) + +#define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7)) +#define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x, 6)) + +#define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39)) +#define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41)) + +#define F0(x,y,z) ((x & y) | (z & (x | y))) +#define F1(x,y,z) (z ^ (x & (y ^ z))) + +#define P(a,b,c,d,e,f,g,h,x,K) \ +{ \ + temp1 = h + S3(e) + F1(e,f,g) + K + x; \ + temp2 = S2(a) + F0(a,b,c); \ + d += temp1; h = temp1 + temp2; \ +} + + for( i = 0; i < 16; i++ ) + { + GET_UINT64_BE( W[i], data, i << 3 ); + } + + for( ; i < 80; i++ ) + { + W[i] = S1(W[i - 2]) + W[i - 7] + + S0(W[i - 15]) + W[i - 16]; + } + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + E = ctx->state[4]; + F = ctx->state[5]; + G = ctx->state[6]; + H = ctx->state[7]; + i = 0; + + do + { + P( A, B, C, D, E, F, G, H, W[i], K[i] ); i++; + P( H, A, B, C, D, E, F, G, W[i], K[i] ); i++; + P( G, H, A, B, C, D, E, F, W[i], K[i] ); i++; + P( F, G, H, A, B, C, D, E, W[i], K[i] ); i++; + P( E, F, G, H, A, B, C, D, W[i], K[i] ); i++; + P( D, E, F, G, H, A, B, C, W[i], K[i] ); i++; + P( C, D, E, F, G, H, A, B, W[i], K[i] ); i++; + P( B, C, D, E, F, G, H, A, W[i], K[i] ); i++; + } + while( i < 80 ); + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; + ctx->state[4] += E; + ctx->state[5] += F; + ctx->state[6] += G; + ctx->state[7] += H; +} + +/* + * SHA-512 process buffer + */ +void sha512_update( sha512_context *ctx, const unsigned char *input, + size_t ilen ) +{ + size_t fill; + unsigned int left; + + if( ilen == 0 ) + return; + + left = (unsigned int) (ctx->total[0] & 0x7F); + fill = 128 - left; + + ctx->total[0] += (uint64_t) ilen; + + if( ctx->total[0] < (uint64_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + sha512_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 128 ) + { + sha512_process( ctx, input ); + input += 128; + ilen -= 128; + } + + if( ilen > 0 ) + memcpy( (void *) (ctx->buffer + left), input, ilen ); +} + +static const unsigned char sha512_padding[128] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * SHA-512 final digest + */ +void sha512_finish( sha512_context *ctx, unsigned char output[64] ) +{ + size_t last, padn; + uint64_t high, low; + unsigned char msglen[16]; + + high = ( ctx->total[0] >> 61 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT64_BE( high, msglen, 0 ); + PUT_UINT64_BE( low, msglen, 8 ); + + last = (size_t)( ctx->total[0] & 0x7F ); + padn = ( last < 112 ) ? ( 112 - last ) : ( 240 - last ); + + sha512_update( ctx, sha512_padding, padn ); + sha512_update( ctx, msglen, 16 ); + + PUT_UINT64_BE( ctx->state[0], output, 0 ); + PUT_UINT64_BE( ctx->state[1], output, 8 ); + PUT_UINT64_BE( ctx->state[2], output, 16 ); + PUT_UINT64_BE( ctx->state[3], output, 24 ); + PUT_UINT64_BE( ctx->state[4], output, 32 ); + PUT_UINT64_BE( ctx->state[5], output, 40 ); + + if( ctx->is384 == 0 ) + { + PUT_UINT64_BE( ctx->state[6], output, 48 ); + PUT_UINT64_BE( ctx->state[7], output, 56 ); + } +} + +#endif /* !POLARSSL_SHA512_ALT */ + +/* + * output = SHA-512( input buffer ) + */ +void sha512( const unsigned char *input, size_t ilen, + unsigned char output[64], int is384 ) +{ + sha512_context ctx; + + sha512_init( &ctx ); + sha512_starts( &ctx, is384 ); + sha512_update( &ctx, input, ilen ); + sha512_finish( &ctx, output ); + sha512_free( &ctx ); +} + +#if defined(POLARSSL_FS_IO) +/* + * output = SHA-512( file contents ) + */ +int sha512_file( const char *path, unsigned char output[64], int is384 ) +{ + FILE *f; + size_t n; + sha512_context ctx; + unsigned char buf[1024]; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( POLARSSL_ERR_SHA512_FILE_IO_ERROR ); + + sha512_init( &ctx ); + sha512_starts( &ctx, is384 ); + + while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) + sha512_update( &ctx, buf, n ); + + sha512_finish( &ctx, output ); + sha512_free( &ctx ); + + if( ferror( f ) != 0 ) + { + fclose( f ); + return( POLARSSL_ERR_SHA512_FILE_IO_ERROR ); + } + + fclose( f ); + return( 0 ); +} +#endif /* POLARSSL_FS_IO */ + +/* + * SHA-512 HMAC context setup + */ +void sha512_hmac_starts( sha512_context *ctx, const unsigned char *key, + size_t keylen, int is384 ) +{ + size_t i; + unsigned char sum[64]; + + if( keylen > 128 ) + { + sha512( key, keylen, sum, is384 ); + keylen = ( is384 ) ? 48 : 64; + key = sum; + } + + memset( ctx->ipad, 0x36, 128 ); + memset( ctx->opad, 0x5C, 128 ); + + for( i = 0; i < keylen; i++ ) + { + ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] ); + ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] ); + } + + sha512_starts( ctx, is384 ); + sha512_update( ctx, ctx->ipad, 128 ); + + polarssl_zeroize( sum, sizeof( sum ) ); +} + +/* + * SHA-512 HMAC process buffer + */ +void sha512_hmac_update( sha512_context *ctx, + const unsigned char *input, size_t ilen ) +{ + sha512_update( ctx, input, ilen ); +} + +/* + * SHA-512 HMAC final digest + */ +void sha512_hmac_finish( sha512_context *ctx, unsigned char output[64] ) +{ + int is384, hlen; + unsigned char tmpbuf[64]; + + is384 = ctx->is384; + hlen = ( is384 == 0 ) ? 64 : 48; + + sha512_finish( ctx, tmpbuf ); + sha512_starts( ctx, is384 ); + sha512_update( ctx, ctx->opad, 128 ); + sha512_update( ctx, tmpbuf, hlen ); + sha512_finish( ctx, output ); + + polarssl_zeroize( tmpbuf, sizeof( tmpbuf ) ); +} + +/* + * SHA-512 HMAC context reset + */ +void sha512_hmac_reset( sha512_context *ctx ) +{ + sha512_starts( ctx, ctx->is384 ); + sha512_update( ctx, ctx->ipad, 128 ); +} + +/* + * output = HMAC-SHA-512( hmac key, input buffer ) + */ +void sha512_hmac( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char output[64], int is384 ) +{ + sha512_context ctx; + + sha512_init( &ctx ); + sha512_hmac_starts( &ctx, key, keylen, is384 ); + sha512_hmac_update( &ctx, input, ilen ); + sha512_hmac_finish( &ctx, output ); + sha512_free( &ctx ); +} + +#if defined(POLARSSL_SELF_TEST) + +/* + * FIPS-180-2 test vectors + */ +static unsigned char sha512_test_buf[3][113] = +{ + { "abc" }, + { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" + "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" }, + { "" } +}; + +static const int sha512_test_buflen[3] = +{ + 3, 112, 1000 +}; + +static const unsigned char sha512_test_sum[6][64] = +{ + /* + * SHA-384 test vectors + */ + { 0xCB, 0x00, 0x75, 0x3F, 0x45, 0xA3, 0x5E, 0x8B, + 0xB5, 0xA0, 0x3D, 0x69, 0x9A, 0xC6, 0x50, 0x07, + 0x27, 0x2C, 0x32, 0xAB, 0x0E, 0xDE, 0xD1, 0x63, + 0x1A, 0x8B, 0x60, 0x5A, 0x43, 0xFF, 0x5B, 0xED, + 0x80, 0x86, 0x07, 0x2B, 0xA1, 0xE7, 0xCC, 0x23, + 0x58, 0xBA, 0xEC, 0xA1, 0x34, 0xC8, 0x25, 0xA7 }, + { 0x09, 0x33, 0x0C, 0x33, 0xF7, 0x11, 0x47, 0xE8, + 0x3D, 0x19, 0x2F, 0xC7, 0x82, 0xCD, 0x1B, 0x47, + 0x53, 0x11, 0x1B, 0x17, 0x3B, 0x3B, 0x05, 0xD2, + 0x2F, 0xA0, 0x80, 0x86, 0xE3, 0xB0, 0xF7, 0x12, + 0xFC, 0xC7, 0xC7, 0x1A, 0x55, 0x7E, 0x2D, 0xB9, + 0x66, 0xC3, 0xE9, 0xFA, 0x91, 0x74, 0x60, 0x39 }, + { 0x9D, 0x0E, 0x18, 0x09, 0x71, 0x64, 0x74, 0xCB, + 0x08, 0x6E, 0x83, 0x4E, 0x31, 0x0A, 0x4A, 0x1C, + 0xED, 0x14, 0x9E, 0x9C, 0x00, 0xF2, 0x48, 0x52, + 0x79, 0x72, 0xCE, 0xC5, 0x70, 0x4C, 0x2A, 0x5B, + 0x07, 0xB8, 0xB3, 0xDC, 0x38, 0xEC, 0xC4, 0xEB, + 0xAE, 0x97, 0xDD, 0xD8, 0x7F, 0x3D, 0x89, 0x85 }, + + /* + * SHA-512 test vectors + */ + { 0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA, + 0xCC, 0x41, 0x73, 0x49, 0xAE, 0x20, 0x41, 0x31, + 0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2, + 0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A, + 0x21, 0x92, 0x99, 0x2A, 0x27, 0x4F, 0xC1, 0xA8, + 0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD, + 0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E, + 0x2A, 0x9A, 0xC9, 0x4F, 0xA5, 0x4C, 0xA4, 0x9F }, + { 0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA, + 0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F, + 0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1, + 0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18, + 0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4, + 0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A, + 0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54, + 0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09 }, + { 0xE7, 0x18, 0x48, 0x3D, 0x0C, 0xE7, 0x69, 0x64, + 0x4E, 0x2E, 0x42, 0xC7, 0xBC, 0x15, 0xB4, 0x63, + 0x8E, 0x1F, 0x98, 0xB1, 0x3B, 0x20, 0x44, 0x28, + 0x56, 0x32, 0xA8, 0x03, 0xAF, 0xA9, 0x73, 0xEB, + 0xDE, 0x0F, 0xF2, 0x44, 0x87, 0x7E, 0xA6, 0x0A, + 0x4C, 0xB0, 0x43, 0x2C, 0xE5, 0x77, 0xC3, 0x1B, + 0xEB, 0x00, 0x9C, 0x5C, 0x2C, 0x49, 0xAA, 0x2E, + 0x4E, 0xAD, 0xB2, 0x17, 0xAD, 0x8C, 0xC0, 0x9B } +}; + +/* + * RFC 4231 test vectors + */ +static unsigned char sha512_hmac_test_key[7][26] = +{ + { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B" + "\x0B\x0B\x0B\x0B" }, + { "Jefe" }, + { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA\xAA" }, + { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10" + "\x11\x12\x13\x14\x15\x16\x17\x18\x19" }, + { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C" + "\x0C\x0C\x0C\x0C" }, + { "" }, /* 0xAA 131 times */ + { "" } +}; + +static const int sha512_hmac_test_keylen[7] = +{ + 20, 4, 20, 25, 20, 131, 131 +}; + +static unsigned char sha512_hmac_test_buf[7][153] = +{ + { "Hi There" }, + { "what do ya want for nothing?" }, + { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" + "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" }, + { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" + "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" }, + { "Test With Truncation" }, + { "Test Using Larger Than Block-Size Key - Hash Key First" }, + { "This is a test using a larger than block-size key " + "and a larger than block-size data. The key needs to " + "be hashed before being used by the HMAC algorithm." } +}; + +static const int sha512_hmac_test_buflen[7] = +{ + 8, 28, 50, 50, 20, 54, 152 +}; + +static const unsigned char sha512_hmac_test_sum[14][64] = +{ + /* + * HMAC-SHA-384 test vectors + */ + { 0xAF, 0xD0, 0x39, 0x44, 0xD8, 0x48, 0x95, 0x62, + 0x6B, 0x08, 0x25, 0xF4, 0xAB, 0x46, 0x90, 0x7F, + 0x15, 0xF9, 0xDA, 0xDB, 0xE4, 0x10, 0x1E, 0xC6, + 0x82, 0xAA, 0x03, 0x4C, 0x7C, 0xEB, 0xC5, 0x9C, + 0xFA, 0xEA, 0x9E, 0xA9, 0x07, 0x6E, 0xDE, 0x7F, + 0x4A, 0xF1, 0x52, 0xE8, 0xB2, 0xFA, 0x9C, 0xB6 }, + { 0xAF, 0x45, 0xD2, 0xE3, 0x76, 0x48, 0x40, 0x31, + 0x61, 0x7F, 0x78, 0xD2, 0xB5, 0x8A, 0x6B, 0x1B, + 0x9C, 0x7E, 0xF4, 0x64, 0xF5, 0xA0, 0x1B, 0x47, + 0xE4, 0x2E, 0xC3, 0x73, 0x63, 0x22, 0x44, 0x5E, + 0x8E, 0x22, 0x40, 0xCA, 0x5E, 0x69, 0xE2, 0xC7, + 0x8B, 0x32, 0x39, 0xEC, 0xFA, 0xB2, 0x16, 0x49 }, + { 0x88, 0x06, 0x26, 0x08, 0xD3, 0xE6, 0xAD, 0x8A, + 0x0A, 0xA2, 0xAC, 0xE0, 0x14, 0xC8, 0xA8, 0x6F, + 0x0A, 0xA6, 0x35, 0xD9, 0x47, 0xAC, 0x9F, 0xEB, + 0xE8, 0x3E, 0xF4, 0xE5, 0x59, 0x66, 0x14, 0x4B, + 0x2A, 0x5A, 0xB3, 0x9D, 0xC1, 0x38, 0x14, 0xB9, + 0x4E, 0x3A, 0xB6, 0xE1, 0x01, 0xA3, 0x4F, 0x27 }, + { 0x3E, 0x8A, 0x69, 0xB7, 0x78, 0x3C, 0x25, 0x85, + 0x19, 0x33, 0xAB, 0x62, 0x90, 0xAF, 0x6C, 0xA7, + 0x7A, 0x99, 0x81, 0x48, 0x08, 0x50, 0x00, 0x9C, + 0xC5, 0x57, 0x7C, 0x6E, 0x1F, 0x57, 0x3B, 0x4E, + 0x68, 0x01, 0xDD, 0x23, 0xC4, 0xA7, 0xD6, 0x79, + 0xCC, 0xF8, 0xA3, 0x86, 0xC6, 0x74, 0xCF, 0xFB }, + { 0x3A, 0xBF, 0x34, 0xC3, 0x50, 0x3B, 0x2A, 0x23, + 0xA4, 0x6E, 0xFC, 0x61, 0x9B, 0xAE, 0xF8, 0x97 }, + { 0x4E, 0xCE, 0x08, 0x44, 0x85, 0x81, 0x3E, 0x90, + 0x88, 0xD2, 0xC6, 0x3A, 0x04, 0x1B, 0xC5, 0xB4, + 0x4F, 0x9E, 0xF1, 0x01, 0x2A, 0x2B, 0x58, 0x8F, + 0x3C, 0xD1, 0x1F, 0x05, 0x03, 0x3A, 0xC4, 0xC6, + 0x0C, 0x2E, 0xF6, 0xAB, 0x40, 0x30, 0xFE, 0x82, + 0x96, 0x24, 0x8D, 0xF1, 0x63, 0xF4, 0x49, 0x52 }, + { 0x66, 0x17, 0x17, 0x8E, 0x94, 0x1F, 0x02, 0x0D, + 0x35, 0x1E, 0x2F, 0x25, 0x4E, 0x8F, 0xD3, 0x2C, + 0x60, 0x24, 0x20, 0xFE, 0xB0, 0xB8, 0xFB, 0x9A, + 0xDC, 0xCE, 0xBB, 0x82, 0x46, 0x1E, 0x99, 0xC5, + 0xA6, 0x78, 0xCC, 0x31, 0xE7, 0x99, 0x17, 0x6D, + 0x38, 0x60, 0xE6, 0x11, 0x0C, 0x46, 0x52, 0x3E }, + + /* + * HMAC-SHA-512 test vectors + */ + { 0x87, 0xAA, 0x7C, 0xDE, 0xA5, 0xEF, 0x61, 0x9D, + 0x4F, 0xF0, 0xB4, 0x24, 0x1A, 0x1D, 0x6C, 0xB0, + 0x23, 0x79, 0xF4, 0xE2, 0xCE, 0x4E, 0xC2, 0x78, + 0x7A, 0xD0, 0xB3, 0x05, 0x45, 0xE1, 0x7C, 0xDE, + 0xDA, 0xA8, 0x33, 0xB7, 0xD6, 0xB8, 0xA7, 0x02, + 0x03, 0x8B, 0x27, 0x4E, 0xAE, 0xA3, 0xF4, 0xE4, + 0xBE, 0x9D, 0x91, 0x4E, 0xEB, 0x61, 0xF1, 0x70, + 0x2E, 0x69, 0x6C, 0x20, 0x3A, 0x12, 0x68, 0x54 }, + { 0x16, 0x4B, 0x7A, 0x7B, 0xFC, 0xF8, 0x19, 0xE2, + 0xE3, 0x95, 0xFB, 0xE7, 0x3B, 0x56, 0xE0, 0xA3, + 0x87, 0xBD, 0x64, 0x22, 0x2E, 0x83, 0x1F, 0xD6, + 0x10, 0x27, 0x0C, 0xD7, 0xEA, 0x25, 0x05, 0x54, + 0x97, 0x58, 0xBF, 0x75, 0xC0, 0x5A, 0x99, 0x4A, + 0x6D, 0x03, 0x4F, 0x65, 0xF8, 0xF0, 0xE6, 0xFD, + 0xCA, 0xEA, 0xB1, 0xA3, 0x4D, 0x4A, 0x6B, 0x4B, + 0x63, 0x6E, 0x07, 0x0A, 0x38, 0xBC, 0xE7, 0x37 }, + { 0xFA, 0x73, 0xB0, 0x08, 0x9D, 0x56, 0xA2, 0x84, + 0xEF, 0xB0, 0xF0, 0x75, 0x6C, 0x89, 0x0B, 0xE9, + 0xB1, 0xB5, 0xDB, 0xDD, 0x8E, 0xE8, 0x1A, 0x36, + 0x55, 0xF8, 0x3E, 0x33, 0xB2, 0x27, 0x9D, 0x39, + 0xBF, 0x3E, 0x84, 0x82, 0x79, 0xA7, 0x22, 0xC8, + 0x06, 0xB4, 0x85, 0xA4, 0x7E, 0x67, 0xC8, 0x07, + 0xB9, 0x46, 0xA3, 0x37, 0xBE, 0xE8, 0x94, 0x26, + 0x74, 0x27, 0x88, 0x59, 0xE1, 0x32, 0x92, 0xFB }, + { 0xB0, 0xBA, 0x46, 0x56, 0x37, 0x45, 0x8C, 0x69, + 0x90, 0xE5, 0xA8, 0xC5, 0xF6, 0x1D, 0x4A, 0xF7, + 0xE5, 0x76, 0xD9, 0x7F, 0xF9, 0x4B, 0x87, 0x2D, + 0xE7, 0x6F, 0x80, 0x50, 0x36, 0x1E, 0xE3, 0xDB, + 0xA9, 0x1C, 0xA5, 0xC1, 0x1A, 0xA2, 0x5E, 0xB4, + 0xD6, 0x79, 0x27, 0x5C, 0xC5, 0x78, 0x80, 0x63, + 0xA5, 0xF1, 0x97, 0x41, 0x12, 0x0C, 0x4F, 0x2D, + 0xE2, 0xAD, 0xEB, 0xEB, 0x10, 0xA2, 0x98, 0xDD }, + { 0x41, 0x5F, 0xAD, 0x62, 0x71, 0x58, 0x0A, 0x53, + 0x1D, 0x41, 0x79, 0xBC, 0x89, 0x1D, 0x87, 0xA6 }, + { 0x80, 0xB2, 0x42, 0x63, 0xC7, 0xC1, 0xA3, 0xEB, + 0xB7, 0x14, 0x93, 0xC1, 0xDD, 0x7B, 0xE8, 0xB4, + 0x9B, 0x46, 0xD1, 0xF4, 0x1B, 0x4A, 0xEE, 0xC1, + 0x12, 0x1B, 0x01, 0x37, 0x83, 0xF8, 0xF3, 0x52, + 0x6B, 0x56, 0xD0, 0x37, 0xE0, 0x5F, 0x25, 0x98, + 0xBD, 0x0F, 0xD2, 0x21, 0x5D, 0x6A, 0x1E, 0x52, + 0x95, 0xE6, 0x4F, 0x73, 0xF6, 0x3F, 0x0A, 0xEC, + 0x8B, 0x91, 0x5A, 0x98, 0x5D, 0x78, 0x65, 0x98 }, + { 0xE3, 0x7B, 0x6A, 0x77, 0x5D, 0xC8, 0x7D, 0xBA, + 0xA4, 0xDF, 0xA9, 0xF9, 0x6E, 0x5E, 0x3F, 0xFD, + 0xDE, 0xBD, 0x71, 0xF8, 0x86, 0x72, 0x89, 0x86, + 0x5D, 0xF5, 0xA3, 0x2D, 0x20, 0xCD, 0xC9, 0x44, + 0xB6, 0x02, 0x2C, 0xAC, 0x3C, 0x49, 0x82, 0xB1, + 0x0D, 0x5E, 0xEB, 0x55, 0xC3, 0xE4, 0xDE, 0x15, + 0x13, 0x46, 0x76, 0xFB, 0x6D, 0xE0, 0x44, 0x60, + 0x65, 0xC9, 0x74, 0x40, 0xFA, 0x8C, 0x6A, 0x58 } +}; + +/* + * Checkup routine + */ +int sha512_self_test( int verbose ) +{ + int i, j, k, buflen, ret = 0; + unsigned char buf[1024]; + unsigned char sha512sum[64]; + sha512_context ctx; + + sha512_init( &ctx ); + + for( i = 0; i < 6; i++ ) + { + j = i % 3; + k = i < 3; + + if( verbose != 0 ) + polarssl_printf( " SHA-%d test #%d: ", 512 - k * 128, j + 1 ); + + sha512_starts( &ctx, k ); + + if( j == 2 ) + { + memset( buf, 'a', buflen = 1000 ); + + for( j = 0; j < 1000; j++ ) + sha512_update( &ctx, buf, buflen ); + } + else + sha512_update( &ctx, sha512_test_buf[j], + sha512_test_buflen[j] ); + + sha512_finish( &ctx, sha512sum ); + + if( memcmp( sha512sum, sha512_test_sum[i], 64 - k * 16 ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); + + for( i = 0; i < 14; i++ ) + { + j = i % 7; + k = i < 7; + + if( verbose != 0 ) + polarssl_printf( " HMAC-SHA-%d test #%d: ", 512 - k * 128, j + 1 ); + + if( j == 5 || j == 6 ) + { + memset( buf, '\xAA', buflen = 131 ); + sha512_hmac_starts( &ctx, buf, buflen, k ); + } + else + sha512_hmac_starts( &ctx, sha512_hmac_test_key[j], + sha512_hmac_test_keylen[j], k ); + + sha512_hmac_update( &ctx, sha512_hmac_test_buf[j], + sha512_hmac_test_buflen[j] ); + + sha512_hmac_finish( &ctx, sha512sum ); + + buflen = ( j == 4 ) ? 16 : 64 - k * 16; + + if( memcmp( sha512sum, sha512_hmac_test_sum[i], buflen ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); + +exit: + sha512_free( &ctx ); + + return( ret ); +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_SHA512_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/ssl_cache.c b/component/common/network/ssl/polarssl-1.3.8/library/ssl_cache.c new file mode 100644 index 0000000..836b685 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/ssl_cache.c @@ -0,0 +1,335 @@ +/* + * SSL session cache implementation + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * These session callbacks use a simple chained list + * to store and retrieve the session information. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_SSL_CACHE_C) + +#include "polarssl/ssl_cache.h" + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#define polarssl_malloc malloc +#define polarssl_free free +#endif + +#include + +void ssl_cache_init( ssl_cache_context *cache ) +{ + memset( cache, 0, sizeof( ssl_cache_context ) ); + + cache->timeout = SSL_CACHE_DEFAULT_TIMEOUT; + cache->max_entries = SSL_CACHE_DEFAULT_MAX_ENTRIES; + +#if defined(POLARSSL_THREADING_C) + polarssl_mutex_init( &cache->mutex ); +#endif +} + +int ssl_cache_get( void *data, ssl_session *session ) +{ + int ret = 1; +#if defined(POLARSSL_HAVE_TIME) + time_t t = time( NULL ); +#endif + ssl_cache_context *cache = (ssl_cache_context *) data; + ssl_cache_entry *cur, *entry; + +#if defined(POLARSSL_THREADING_C) + if( polarssl_mutex_lock( &cache->mutex ) != 0 ) + return( 1 ); +#endif + + cur = cache->chain; + entry = NULL; + + while( cur != NULL ) + { + entry = cur; + cur = cur->next; + +#if defined(POLARSSL_HAVE_TIME) + if( cache->timeout != 0 && + (int) ( t - entry->timestamp ) > cache->timeout ) + continue; +#endif + + if( session->ciphersuite != entry->session.ciphersuite || + session->compression != entry->session.compression || + session->length != entry->session.length ) + continue; + + if( memcmp( session->id, entry->session.id, + entry->session.length ) != 0 ) + continue; + + memcpy( session->master, entry->session.master, 48 ); + + session->verify_result = entry->session.verify_result; + +#if defined(POLARSSL_X509_CRT_PARSE_C) + /* + * Restore peer certificate (without rest of the original chain) + */ + if( entry->peer_cert.p != NULL ) + { + session->peer_cert = + (x509_crt *) polarssl_malloc( sizeof(x509_crt) ); + + if( session->peer_cert == NULL ) + { + ret = 1; + goto exit; + } + + x509_crt_init( session->peer_cert ); + if( x509_crt_parse( session->peer_cert, entry->peer_cert.p, + entry->peer_cert.len ) != 0 ) + { + polarssl_free( session->peer_cert ); + session->peer_cert = NULL; + ret = 1; + goto exit; + } + } +#endif /* POLARSSL_X509_CRT_PARSE_C */ + + ret = 0; + goto exit; + } + +exit: +#if defined(POLARSSL_THREADING_C) + if( polarssl_mutex_unlock( &cache->mutex ) != 0 ) + ret = 1; +#endif + + return( ret ); +} + +int ssl_cache_set( void *data, const ssl_session *session ) +{ + int ret = 1; +#if defined(POLARSSL_HAVE_TIME) + time_t t = time( NULL ), oldest = 0; + ssl_cache_entry *old = NULL; +#endif + ssl_cache_context *cache = (ssl_cache_context *) data; + ssl_cache_entry *cur, *prv; + int count = 0; + +#if defined(POLARSSL_THREADING_C) + if( ( ret = polarssl_mutex_lock( &cache->mutex ) ) != 0 ) + return( ret ); +#endif + + cur = cache->chain; + prv = NULL; + + while( cur != NULL ) + { + count++; + +#if defined(POLARSSL_HAVE_TIME) + if( cache->timeout != 0 && + (int) ( t - cur->timestamp ) > cache->timeout ) + { + cur->timestamp = t; + break; /* expired, reuse this slot, update timestamp */ + } +#endif + + if( memcmp( session->id, cur->session.id, cur->session.length ) == 0 ) + break; /* client reconnected, keep timestamp for session id */ + +#if defined(POLARSSL_HAVE_TIME) + if( oldest == 0 || cur->timestamp < oldest ) + { + oldest = cur->timestamp; + old = cur; + } +#endif + + prv = cur; + cur = cur->next; + } + + if( cur == NULL ) + { +#if defined(POLARSSL_HAVE_TIME) + /* + * Reuse oldest entry if max_entries reached + */ + if( count >= cache->max_entries ) + { + if( old == NULL ) + { + ret = 1; + goto exit; + } + + cur = old; + } +#else /* POLARSSL_HAVE_TIME */ + /* + * Reuse first entry in chain if max_entries reached, + * but move to last place + */ + if( count >= cache->max_entries ) + { + if( cache->chain == NULL ) + { + ret = 1; + goto exit; + } + + cur = cache->chain; + cache->chain = cur->next; + cur->next = NULL; + prv->next = cur; + } +#endif /* POLARSSL_HAVE_TIME */ + else + { + /* + * max_entries not reached, create new entry + */ + cur = (ssl_cache_entry *) + polarssl_malloc( sizeof(ssl_cache_entry) ); + if( cur == NULL ) + { + ret = 1; + goto exit; + } + + memset( cur, 0, sizeof(ssl_cache_entry) ); + + if( prv == NULL ) + cache->chain = cur; + else + prv->next = cur; + } + +#if defined(POLARSSL_HAVE_TIME) + cur->timestamp = t; +#endif + } + + memcpy( &cur->session, session, sizeof( ssl_session ) ); + +#if defined(POLARSSL_X509_CRT_PARSE_C) + /* + * If we're reusing an entry, free its certificate first + */ + if( cur->peer_cert.p != NULL ) + { + polarssl_free( cur->peer_cert.p ); + memset( &cur->peer_cert, 0, sizeof(x509_buf) ); + } + + /* + * Store peer certificate + */ + if( session->peer_cert != NULL ) + { + cur->peer_cert.p = (unsigned char *) + polarssl_malloc( session->peer_cert->raw.len ); + if( cur->peer_cert.p == NULL ) + { + ret = 1; + goto exit; + } + + memcpy( cur->peer_cert.p, session->peer_cert->raw.p, + session->peer_cert->raw.len ); + cur->peer_cert.len = session->peer_cert->raw.len; + + cur->session.peer_cert = NULL; + } +#endif /* POLARSSL_X509_CRT_PARSE_C */ + + ret = 0; + +exit: +#if defined(POLARSSL_THREADING_C) + if( polarssl_mutex_unlock( &cache->mutex ) != 0 ) + ret = 1; +#endif + + return( ret ); +} + +#if defined(POLARSSL_HAVE_TIME) +void ssl_cache_set_timeout( ssl_cache_context *cache, int timeout ) +{ + if( timeout < 0 ) timeout = 0; + + cache->timeout = timeout; +} +#endif /* POLARSSL_HAVE_TIME */ + +void ssl_cache_set_max_entries( ssl_cache_context *cache, int max ) +{ + if( max < 0 ) max = 0; + + cache->max_entries = max; +} + +void ssl_cache_free( ssl_cache_context *cache ) +{ + ssl_cache_entry *cur, *prv; + + cur = cache->chain; + + while( cur != NULL ) + { + prv = cur; + cur = cur->next; + + ssl_session_free( &prv->session ); + +#if defined(POLARSSL_X509_CRT_PARSE_C) + polarssl_free( prv->peer_cert.p ); +#endif /* POLARSSL_X509_CRT_PARSE_C */ + + polarssl_free( prv ); + } + +#if defined(POLARSSL_THREADING_C) + polarssl_mutex_free( &cache->mutex ); +#endif +} + +#endif /* POLARSSL_SSL_CACHE_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/ssl_ciphersuites.c b/component/common/network/ssl/polarssl-1.3.8/library/ssl_ciphersuites.c new file mode 100644 index 0000000..df838e2 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/ssl_ciphersuites.c @@ -0,0 +1,1843 @@ +/** + * \file ssl_ciphersuites.c + * + * \brief SSL ciphersuites for PolarSSL + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_SSL_TLS_C) + +#include "polarssl/ssl_ciphersuites.h" +#include "polarssl/ssl.h" + +#include + +#if defined(_MSC_VER) && !defined strcasecmp && !defined(EFIX64) && \ + !defined(EFI32) +#define strcasecmp _stricmp +#endif + +/* + * Ordered from most preferred to least preferred in terms of security. + * + * Current rule (except rc4, weak and null which come last): + * 1. By key exchange: + * Forward-secure non-PSK > forward-secure PSK > other non-PSK > other PSK + * 2. By key length and cipher: + * AES-256 > Camellia-256 > AES-128 > Camellia-128 > 3DES + * 3. By cipher mode when relevant GCM > CCM > CBC > CCM_8 + * 4. By hash function used when relevant + * 5. By key exchange/auth again: EC > non-EC + */ +static const int ciphersuite_preference[] = +{ +#if defined(SSL_CIPHERSUITES) + SSL_CIPHERSUITES, +#else + /* All AES-256 ephemeral suites */ + TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, + TLS_ECDHE_ECDSA_WITH_AES_256_CCM, + TLS_DHE_RSA_WITH_AES_256_CCM, + TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, + TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, + TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, + TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, + TLS_DHE_RSA_WITH_AES_256_CBC_SHA, + TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, + TLS_DHE_RSA_WITH_AES_256_CCM_8, + + /* All CAMELLIA-256 ephemeral suites */ + TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, + TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, + TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, + TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, + TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, + TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, + TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, + + /* All AES-128 ephemeral suites */ + TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, + TLS_ECDHE_ECDSA_WITH_AES_128_CCM, + TLS_DHE_RSA_WITH_AES_128_CCM, + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, + TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, + TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + TLS_DHE_RSA_WITH_AES_128_CBC_SHA, + TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, + TLS_DHE_RSA_WITH_AES_128_CCM_8, + + /* All CAMELLIA-128 ephemeral suites */ + TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, + TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, + TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, + TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, + TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, + TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, + TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, + + /* All remaining >= 128-bit ephemeral suites */ + TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, + TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, + TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, + + /* The PSK ephemeral suites */ + TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, + TLS_DHE_PSK_WITH_AES_256_CCM, + TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, + TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, + TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, + TLS_DHE_PSK_WITH_AES_256_CBC_SHA, + TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384, + TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, + TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, + TLS_DHE_PSK_WITH_AES_256_CCM_8, + + TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, + TLS_DHE_PSK_WITH_AES_128_CCM, + TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, + TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, + TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, + TLS_DHE_PSK_WITH_AES_128_CBC_SHA, + TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256, + TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, + TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, + TLS_DHE_PSK_WITH_AES_128_CCM_8, + + TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, + TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, + + /* All AES-256 suites */ + TLS_RSA_WITH_AES_256_GCM_SHA384, + TLS_RSA_WITH_AES_256_CCM, + TLS_RSA_WITH_AES_256_CBC_SHA256, + TLS_RSA_WITH_AES_256_CBC_SHA, + TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, + TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, + TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, + TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, + TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, + TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, + TLS_RSA_WITH_AES_256_CCM_8, + + /* All CAMELLIA-256 suites */ + TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384, + TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, + TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, + TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384, + TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384, + TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, + TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, + + /* All AES-128 suites */ + TLS_RSA_WITH_AES_128_GCM_SHA256, + TLS_RSA_WITH_AES_128_CCM, + TLS_RSA_WITH_AES_128_CBC_SHA256, + TLS_RSA_WITH_AES_128_CBC_SHA, + TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, + TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, + TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, + TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, + TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, + TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, + TLS_RSA_WITH_AES_128_CCM_8, + + /* All CAMELLIA-128 suites */ + TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256, + TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, + TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, + TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256, + TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256, + TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, + TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, + + /* All remaining >= 128-bit suites */ + TLS_RSA_WITH_3DES_EDE_CBC_SHA, + TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, + TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, + + /* The RSA PSK suites */ + TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, + TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, + TLS_RSA_PSK_WITH_AES_256_CBC_SHA, + TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384, + TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, + + TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, + TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, + TLS_RSA_PSK_WITH_AES_128_CBC_SHA, + TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256, + TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, + + TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, + + /* The PSK suites */ + TLS_PSK_WITH_AES_256_GCM_SHA384, + TLS_PSK_WITH_AES_256_CCM, + TLS_PSK_WITH_AES_256_CBC_SHA384, + TLS_PSK_WITH_AES_256_CBC_SHA, + TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384, + TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, + TLS_PSK_WITH_AES_256_CCM_8, + + TLS_PSK_WITH_AES_128_GCM_SHA256, + TLS_PSK_WITH_AES_128_CCM, + TLS_PSK_WITH_AES_128_CBC_SHA256, + TLS_PSK_WITH_AES_128_CBC_SHA, + TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256, + TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, + TLS_PSK_WITH_AES_128_CCM_8, + + TLS_PSK_WITH_3DES_EDE_CBC_SHA, + + /* RC4 suites */ + TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, + TLS_ECDHE_RSA_WITH_RC4_128_SHA, + TLS_ECDHE_PSK_WITH_RC4_128_SHA, + TLS_DHE_PSK_WITH_RC4_128_SHA, + TLS_RSA_WITH_RC4_128_SHA, + TLS_RSA_WITH_RC4_128_MD5, + TLS_ECDH_RSA_WITH_RC4_128_SHA, + TLS_ECDH_ECDSA_WITH_RC4_128_SHA, + TLS_RSA_PSK_WITH_RC4_128_SHA, + TLS_PSK_WITH_RC4_128_SHA, + + /* Weak suites */ + TLS_DHE_RSA_WITH_DES_CBC_SHA, + TLS_RSA_WITH_DES_CBC_SHA, + + /* NULL suites */ + TLS_ECDHE_ECDSA_WITH_NULL_SHA, + TLS_ECDHE_RSA_WITH_NULL_SHA, + TLS_ECDHE_PSK_WITH_NULL_SHA384, + TLS_ECDHE_PSK_WITH_NULL_SHA256, + TLS_ECDHE_PSK_WITH_NULL_SHA, + TLS_DHE_PSK_WITH_NULL_SHA384, + TLS_DHE_PSK_WITH_NULL_SHA256, + TLS_DHE_PSK_WITH_NULL_SHA, + + TLS_RSA_WITH_NULL_SHA256, + TLS_RSA_WITH_NULL_SHA, + TLS_RSA_WITH_NULL_MD5, + TLS_ECDH_RSA_WITH_NULL_SHA, + TLS_ECDH_ECDSA_WITH_NULL_SHA, + TLS_RSA_PSK_WITH_NULL_SHA384, + TLS_RSA_PSK_WITH_NULL_SHA256, + TLS_RSA_PSK_WITH_NULL_SHA, + TLS_PSK_WITH_NULL_SHA384, + TLS_PSK_WITH_NULL_SHA256, + TLS_PSK_WITH_NULL_SHA, + +#endif + 0 +}; + +static const ssl_ciphersuite_t ciphersuite_definitions[] = +{ +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +#if defined(POLARSSL_AES_C) +#if defined(POLARSSL_SHA1_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) + { TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + { TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_SHA1_C */ +#if defined(POLARSSL_SHA256_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) + { TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#if defined(POLARSSL_GCM_C) + { TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, "TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256", + POLARSSL_CIPHER_AES_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_GCM_C */ +#endif /* POLARSSL_SHA256_C */ +#if defined(POLARSSL_SHA512_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) + { TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#if defined(POLARSSL_GCM_C) + { TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, "TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384", + POLARSSL_CIPHER_AES_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_GCM_C */ +#endif /* POLARSSL_SHA512_C */ +#if defined(POLARSSL_CCM_C) + { TLS_ECDHE_ECDSA_WITH_AES_256_CCM, "TLS-ECDHE-ECDSA-WITH-AES-256-CCM", + POLARSSL_CIPHER_AES_256_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + { TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, "TLS-ECDHE-ECDSA-WITH-AES-256-CCM-8", + POLARSSL_CIPHER_AES_256_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_SHORT_TAG }, + { TLS_ECDHE_ECDSA_WITH_AES_128_CCM, "TLS-ECDHE-ECDSA-WITH-AES-128-CCM", + POLARSSL_CIPHER_AES_128_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + { TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, "TLS-ECDHE-ECDSA-WITH-AES-128-CCM-8", + POLARSSL_CIPHER_AES_128_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_SHORT_TAG }, +#endif /* POLARSSL_CCM_C */ +#endif /* POLARSSL_AES_C */ + +#if defined(POLARSSL_CAMELLIA_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA256_C) + { TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-CBC-SHA256", + POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ +#if defined(POLARSSL_SHA512_C) + { TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-CBC-SHA384", + POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_GCM_C) +#if defined(POLARSSL_SHA256_C) + { TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-GCM-SHA256", + POLARSSL_CIPHER_CAMELLIA_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ +#if defined(POLARSSL_SHA512_C) + { TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-GCM-SHA384", + POLARSSL_CIPHER_CAMELLIA_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_GCM_C */ +#endif /* POLARSSL_CAMELLIA_C */ + +#if defined(POLARSSL_DES_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA1_C) + { TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-3DES-EDE-CBC-SHA", + POLARSSL_CIPHER_DES_EDE3_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_DES_C */ + +#if defined(POLARSSL_ARC4_C) +#if defined(POLARSSL_SHA1_C) + { TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, "TLS-ECDHE-ECDSA-WITH-RC4-128-SHA", + POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_ARC4_C */ + +#if defined(POLARSSL_CIPHER_NULL_CIPHER) +#if defined(POLARSSL_SHA1_C) + { TLS_ECDHE_ECDSA_WITH_NULL_SHA, "TLS-ECDHE-ECDSA-WITH-NULL-SHA", + POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_NULL_CIPHER */ +#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) +#if defined(POLARSSL_AES_C) +#if defined(POLARSSL_SHA1_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) + { TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + { TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_SHA1_C */ +#if defined(POLARSSL_SHA256_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) + { TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#if defined(POLARSSL_GCM_C) + { TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, "TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256", + POLARSSL_CIPHER_AES_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_GCM_C */ +#endif /* POLARSSL_SHA256_C */ +#if defined(POLARSSL_SHA512_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) + { TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#if defined(POLARSSL_GCM_C) + { TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, "TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384", + POLARSSL_CIPHER_AES_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_GCM_C */ +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_AES_C */ + +#if defined(POLARSSL_CAMELLIA_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA256_C) + { TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-RSA-WITH-CAMELLIA-128-CBC-SHA256", + POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ +#if defined(POLARSSL_SHA512_C) + { TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-RSA-WITH-CAMELLIA-256-CBC-SHA384", + POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_GCM_C) +#if defined(POLARSSL_SHA256_C) + { TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDHE-RSA-WITH-CAMELLIA-128-GCM-SHA256", + POLARSSL_CIPHER_CAMELLIA_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ +#if defined(POLARSSL_SHA512_C) + { TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDHE-RSA-WITH-CAMELLIA-256-GCM-SHA384", + POLARSSL_CIPHER_CAMELLIA_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_GCM_C */ +#endif /* POLARSSL_CAMELLIA_C */ + +#if defined(POLARSSL_DES_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA1_C) + { TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA", + POLARSSL_CIPHER_DES_EDE3_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_DES_C */ + +#if defined(POLARSSL_ARC4_C) +#if defined(POLARSSL_SHA1_C) + { TLS_ECDHE_RSA_WITH_RC4_128_SHA, "TLS-ECDHE-RSA-WITH-RC4-128-SHA", + POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_ARC4_C */ + +#if defined(POLARSSL_CIPHER_NULL_CIPHER) +#if defined(POLARSSL_SHA1_C) + { TLS_ECDHE_RSA_WITH_NULL_SHA, "TLS-ECDHE-RSA-WITH-NULL-SHA", + POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_NULL_CIPHER */ +#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) +#if defined(POLARSSL_AES_C) +#if defined(POLARSSL_SHA512_C) && defined(POLARSSL_GCM_C) + { TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384", + POLARSSL_CIPHER_AES_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_DHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C && POLARSSL_GCM_C */ + +#if defined(POLARSSL_SHA256_C) +#if defined(POLARSSL_GCM_C) + { TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256", + POLARSSL_CIPHER_AES_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_GCM_C */ + +#if defined(POLARSSL_CIPHER_MODE_CBC) + { TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + + { TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA256", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA1_C) + { TLS_DHE_RSA_WITH_AES_128_CBC_SHA, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + + { TLS_DHE_RSA_WITH_AES_256_CBC_SHA, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#if defined(POLARSSL_CCM_C) + { TLS_DHE_RSA_WITH_AES_256_CCM, "TLS-DHE-RSA-WITH-AES-256-CCM", + POLARSSL_CIPHER_AES_256_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + { TLS_DHE_RSA_WITH_AES_256_CCM_8, "TLS-DHE-RSA-WITH-AES-256-CCM-8", + POLARSSL_CIPHER_AES_256_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_SHORT_TAG }, + { TLS_DHE_RSA_WITH_AES_128_CCM, "TLS-DHE-RSA-WITH-AES-128-CCM", + POLARSSL_CIPHER_AES_128_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + { TLS_DHE_RSA_WITH_AES_128_CCM_8, "TLS-DHE-RSA-WITH-AES-128-CCM-8", + POLARSSL_CIPHER_AES_128_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_SHORT_TAG }, +#endif /* POLARSSL_CCM_C */ +#endif /* POLARSSL_AES_C */ + +#if defined(POLARSSL_CAMELLIA_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA256_C) + { TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256", + POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + + { TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256", + POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA1_C) + { TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA", + POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + + { TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA", + POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#if defined(POLARSSL_GCM_C) +#if defined(POLARSSL_SHA256_C) + { TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-128-GCM-SHA256", + POLARSSL_CIPHER_CAMELLIA_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA512_C) + { TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-DHE-RSA-WITH-CAMELLIA-256-GCM-SHA384", + POLARSSL_CIPHER_CAMELLIA_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_DHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_GCM_C */ +#endif /* POLARSSL_CAMELLIA_C */ + +#if defined(POLARSSL_DES_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA1_C) + { TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA", + POLARSSL_CIPHER_DES_EDE3_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_DES_C */ +#endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) +#if defined(POLARSSL_AES_C) +#if defined(POLARSSL_SHA512_C) && defined(POLARSSL_GCM_C) + { TLS_RSA_WITH_AES_256_GCM_SHA384, "TLS-RSA-WITH-AES-256-GCM-SHA384", + POLARSSL_CIPHER_AES_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C && POLARSSL_GCM_C */ + +#if defined(POLARSSL_SHA256_C) +#if defined(POLARSSL_GCM_C) + { TLS_RSA_WITH_AES_128_GCM_SHA256, "TLS-RSA-WITH-AES-128-GCM-SHA256", + POLARSSL_CIPHER_AES_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_GCM_C */ + +#if defined(POLARSSL_CIPHER_MODE_CBC) + { TLS_RSA_WITH_AES_128_CBC_SHA256, "TLS-RSA-WITH-AES-128-CBC-SHA256", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + + { TLS_RSA_WITH_AES_256_CBC_SHA256, "TLS-RSA-WITH-AES-256-CBC-SHA256", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA1_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) + { TLS_RSA_WITH_AES_128_CBC_SHA, "TLS-RSA-WITH-AES-128-CBC-SHA", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + + { TLS_RSA_WITH_AES_256_CBC_SHA, "TLS-RSA-WITH-AES-256-CBC-SHA", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_SHA1_C */ +#if defined(POLARSSL_CCM_C) + { TLS_RSA_WITH_AES_256_CCM, "TLS-RSA-WITH-AES-256-CCM", + POLARSSL_CIPHER_AES_256_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + { TLS_RSA_WITH_AES_256_CCM_8, "TLS-RSA-WITH-AES-256-CCM-8", + POLARSSL_CIPHER_AES_256_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_SHORT_TAG }, + { TLS_RSA_WITH_AES_128_CCM, "TLS-RSA-WITH-AES-128-CCM", + POLARSSL_CIPHER_AES_128_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + { TLS_RSA_WITH_AES_128_CCM_8, "TLS-RSA-WITH-AES-128-CCM-8", + POLARSSL_CIPHER_AES_128_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_SHORT_TAG }, +#endif /* POLARSSL_CCM_C */ +#endif /* POLARSSL_AES_C */ + +#if defined(POLARSSL_CAMELLIA_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA256_C) + { TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256", + POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + + { TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256", + POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA1_C) + { TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA", + POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + + { TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA", + POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_GCM_C) +#if defined(POLARSSL_SHA256_C) + { TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-RSA-WITH-CAMELLIA-128-GCM-SHA256", + POLARSSL_CIPHER_CAMELLIA_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA1_C) + { TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-RSA-WITH-CAMELLIA-256-GCM-SHA384", + POLARSSL_CIPHER_CAMELLIA_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_GCM_C */ +#endif /* POLARSSL_CAMELLIA_C */ + +#if defined(POLARSSL_DES_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA1_C) + { TLS_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-RSA-WITH-3DES-EDE-CBC-SHA", + POLARSSL_CIPHER_DES_EDE3_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_DES_C */ + +#if defined(POLARSSL_ARC4_C) +#if defined(POLARSSL_MD5_C) + { TLS_RSA_WITH_RC4_128_MD5, "TLS-RSA-WITH-RC4-128-MD5", + POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_MD5, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif + +#if defined(POLARSSL_SHA1_C) + { TLS_RSA_WITH_RC4_128_SHA, "TLS-RSA-WITH-RC4-128-SHA", + POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif +#endif /* POLARSSL_ARC4_C */ +#endif /* POLARSSL_KEY_EXCHANGE_RSA_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) +#if defined(POLARSSL_AES_C) +#if defined(POLARSSL_SHA1_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) + { TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDH_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + { TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDH_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_SHA1_C */ +#if defined(POLARSSL_SHA256_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) + { TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA256", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDH_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#if defined(POLARSSL_GCM_C) + { TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-AES-128-GCM-SHA256", + POLARSSL_CIPHER_AES_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDH_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_GCM_C */ +#endif /* POLARSSL_SHA256_C */ +#if defined(POLARSSL_SHA512_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) + { TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA384", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDH_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#if defined(POLARSSL_GCM_C) + { TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-AES-256-GCM-SHA384", + POLARSSL_CIPHER_AES_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDH_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_GCM_C */ +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_AES_C */ + +#if defined(POLARSSL_CAMELLIA_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA256_C) + { TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-CAMELLIA-128-CBC-SHA256", + POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDH_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ +#if defined(POLARSSL_SHA512_C) + { TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-CAMELLIA-256-CBC-SHA384", + POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDH_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_GCM_C) +#if defined(POLARSSL_SHA256_C) + { TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-CAMELLIA-128-GCM-SHA256", + POLARSSL_CIPHER_CAMELLIA_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDH_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ +#if defined(POLARSSL_SHA512_C) + { TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-CAMELLIA-256-GCM-SHA384", + POLARSSL_CIPHER_CAMELLIA_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDH_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_GCM_C */ +#endif /* POLARSSL_CAMELLIA_C */ + +#if defined(POLARSSL_DES_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA1_C) + { TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDH-RSA-WITH-3DES-EDE-CBC-SHA", + POLARSSL_CIPHER_DES_EDE3_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDH_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_DES_C */ + +#if defined(POLARSSL_ARC4_C) +#if defined(POLARSSL_SHA1_C) + { TLS_ECDH_RSA_WITH_RC4_128_SHA, "TLS-ECDH-RSA-WITH-RC4-128-SHA", + POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDH_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_ARC4_C */ + +#if defined(POLARSSL_CIPHER_NULL_CIPHER) +#if defined(POLARSSL_SHA1_C) + { TLS_ECDH_RSA_WITH_NULL_SHA, "TLS-ECDH-RSA-WITH-NULL-SHA", + POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDH_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_NULL_CIPHER */ +#endif /* POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +#if defined(POLARSSL_AES_C) +#if defined(POLARSSL_SHA1_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) + { TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + { TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_SHA1_C */ +#if defined(POLARSSL_SHA256_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) + { TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA256", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#if defined(POLARSSL_GCM_C) + { TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-AES-128-GCM-SHA256", + POLARSSL_CIPHER_AES_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_GCM_C */ +#endif /* POLARSSL_SHA256_C */ +#if defined(POLARSSL_SHA512_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) + { TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA384", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#if defined(POLARSSL_GCM_C) + { TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-AES-256-GCM-SHA384", + POLARSSL_CIPHER_AES_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_GCM_C */ +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_AES_C */ + +#if defined(POLARSSL_CAMELLIA_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA256_C) + { TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-CBC-SHA256", + POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ +#if defined(POLARSSL_SHA512_C) + { TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA384", + POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_GCM_C) +#if defined(POLARSSL_SHA256_C) + { TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-GCM-SHA256", + POLARSSL_CIPHER_CAMELLIA_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ +#if defined(POLARSSL_SHA512_C) + { TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-GCM-SHA384", + POLARSSL_CIPHER_CAMELLIA_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_GCM_C */ +#endif /* POLARSSL_CAMELLIA_C */ + +#if defined(POLARSSL_DES_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA1_C) + { TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDH-ECDSA-WITH-3DES-EDE-CBC-SHA", + POLARSSL_CIPHER_DES_EDE3_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_DES_C */ + +#if defined(POLARSSL_ARC4_C) +#if defined(POLARSSL_SHA1_C) + { TLS_ECDH_ECDSA_WITH_RC4_128_SHA, "TLS-ECDH-ECDSA-WITH-RC4-128-SHA", + POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_ARC4_C */ + +#if defined(POLARSSL_CIPHER_NULL_CIPHER) +#if defined(POLARSSL_SHA1_C) + { TLS_ECDH_ECDSA_WITH_NULL_SHA, "TLS-ECDH-ECDSA-WITH-NULL-SHA", + POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_NULL_CIPHER */ +#endif /* POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) +#if defined(POLARSSL_AES_C) +#if defined(POLARSSL_GCM_C) +#if defined(POLARSSL_SHA256_C) + { TLS_PSK_WITH_AES_128_GCM_SHA256, "TLS-PSK-WITH-AES-128-GCM-SHA256", + POLARSSL_CIPHER_AES_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA512_C) + { TLS_PSK_WITH_AES_256_GCM_SHA384, "TLS-PSK-WITH-AES-256-GCM-SHA384", + POLARSSL_CIPHER_AES_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_GCM_C */ + +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA256_C) + { TLS_PSK_WITH_AES_128_CBC_SHA256, "TLS-PSK-WITH-AES-128-CBC-SHA256", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA512_C) + { TLS_PSK_WITH_AES_256_CBC_SHA384, "TLS-PSK-WITH-AES-256-CBC-SHA384", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ + +#if defined(POLARSSL_SHA1_C) + { TLS_PSK_WITH_AES_128_CBC_SHA, "TLS-PSK-WITH-AES-128-CBC-SHA", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + + { TLS_PSK_WITH_AES_256_CBC_SHA, "TLS-PSK-WITH-AES-256-CBC-SHA", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#if defined(POLARSSL_CCM_C) + { TLS_PSK_WITH_AES_256_CCM, "TLS-PSK-WITH-AES-256-CCM", + POLARSSL_CIPHER_AES_256_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + { TLS_PSK_WITH_AES_256_CCM_8, "TLS-PSK-WITH-AES-256-CCM-8", + POLARSSL_CIPHER_AES_256_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_SHORT_TAG }, + { TLS_PSK_WITH_AES_128_CCM, "TLS-PSK-WITH-AES-128-CCM", + POLARSSL_CIPHER_AES_128_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + { TLS_PSK_WITH_AES_128_CCM_8, "TLS-PSK-WITH-AES-128-CCM-8", + POLARSSL_CIPHER_AES_128_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_SHORT_TAG }, +#endif /* POLARSSL_CCM_C */ +#endif /* POLARSSL_AES_C */ + +#if defined(POLARSSL_CAMELLIA_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA256_C) + { TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-PSK-WITH-CAMELLIA-128-CBC-SHA256", + POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA512_C) + { TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-PSK-WITH-CAMELLIA-256-CBC-SHA384", + POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_GCM_C) +#if defined(POLARSSL_SHA256_C) + { TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-PSK-WITH-CAMELLIA-128-GCM-SHA256", + POLARSSL_CIPHER_CAMELLIA_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA512_C) + { TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-PSK-WITH-CAMELLIA-256-GCM-SHA384", + POLARSSL_CIPHER_CAMELLIA_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_GCM_C */ +#endif /* POLARSSL_CAMELLIA_C */ + +#if defined(POLARSSL_DES_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA1_C) + { TLS_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-PSK-WITH-3DES-EDE-CBC-SHA", + POLARSSL_CIPHER_DES_EDE3_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_DES_C */ + +#if defined(POLARSSL_ARC4_C) +#if defined(POLARSSL_SHA1_C) + { TLS_PSK_WITH_RC4_128_SHA, "TLS-PSK-WITH-RC4-128-SHA", + POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_ARC4_C */ +#endif /* POLARSSL_KEY_EXCHANGE_PSK_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) +#if defined(POLARSSL_AES_C) +#if defined(POLARSSL_GCM_C) +#if defined(POLARSSL_SHA256_C) + { TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, "TLS-DHE-PSK-WITH-AES-128-GCM-SHA256", + POLARSSL_CIPHER_AES_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA512_C) + { TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, "TLS-DHE-PSK-WITH-AES-256-GCM-SHA384", + POLARSSL_CIPHER_AES_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_GCM_C */ + +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA256_C) + { TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, "TLS-DHE-PSK-WITH-AES-128-CBC-SHA256", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA512_C) + { TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, "TLS-DHE-PSK-WITH-AES-256-CBC-SHA384", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ + +#if defined(POLARSSL_SHA1_C) + { TLS_DHE_PSK_WITH_AES_128_CBC_SHA, "TLS-DHE-PSK-WITH-AES-128-CBC-SHA", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + + { TLS_DHE_PSK_WITH_AES_256_CBC_SHA, "TLS-DHE-PSK-WITH-AES-256-CBC-SHA", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#if defined(POLARSSL_CCM_C) + { TLS_DHE_PSK_WITH_AES_256_CCM, "TLS-DHE-PSK-WITH-AES-256-CCM", + POLARSSL_CIPHER_AES_256_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + { TLS_DHE_PSK_WITH_AES_256_CCM_8, "TLS-DHE-PSK-WITH-AES-256-CCM-8", + POLARSSL_CIPHER_AES_256_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_SHORT_TAG }, + { TLS_DHE_PSK_WITH_AES_128_CCM, "TLS-DHE-PSK-WITH-AES-128-CCM", + POLARSSL_CIPHER_AES_128_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + { TLS_DHE_PSK_WITH_AES_128_CCM_8, "TLS-DHE-PSK-WITH-AES-128-CCM-8", + POLARSSL_CIPHER_AES_128_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_SHORT_TAG }, +#endif /* POLARSSL_CCM_C */ +#endif /* POLARSSL_AES_C */ + +#if defined(POLARSSL_CAMELLIA_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA256_C) + { TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-DHE-PSK-WITH-CAMELLIA-128-CBC-SHA256", + POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA512_C) + { TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-DHE-PSK-WITH-CAMELLIA-256-CBC-SHA384", + POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_GCM_C) +#if defined(POLARSSL_SHA256_C) + { TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-DHE-PSK-WITH-CAMELLIA-128-GCM-SHA256", + POLARSSL_CIPHER_CAMELLIA_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA512_C) + { TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-DHE-PSK-WITH-CAMELLIA-256-GCM-SHA384", + POLARSSL_CIPHER_CAMELLIA_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_GCM_C */ +#endif /* POLARSSL_CAMELLIA_C */ + +#if defined(POLARSSL_DES_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA1_C) + { TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-DHE-PSK-WITH-3DES-EDE-CBC-SHA", + POLARSSL_CIPHER_DES_EDE3_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_DES_C */ + +#if defined(POLARSSL_ARC4_C) +#if defined(POLARSSL_SHA1_C) + { TLS_DHE_PSK_WITH_RC4_128_SHA, "TLS-DHE-PSK-WITH-RC4-128-SHA", + POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_ARC4_C */ +#endif /* POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#if defined(POLARSSL_AES_C) + +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA256_C) + { TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA256", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA512_C) + { TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA384", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ + +#if defined(POLARSSL_SHA1_C) + { TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + + { TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, "TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_AES_C */ + +#if defined(POLARSSL_CAMELLIA_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA256_C) + { TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-CAMELLIA-128-CBC-SHA256", + POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA512_C) + { TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-CAMELLIA-256-CBC-SHA384", + POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_CAMELLIA_C */ + +#if defined(POLARSSL_DES_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA1_C) + { TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-PSK-WITH-3DES-EDE-CBC-SHA", + POLARSSL_CIPHER_DES_EDE3_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_DES_C */ + +#if defined(POLARSSL_ARC4_C) +#if defined(POLARSSL_SHA1_C) + { TLS_ECDHE_PSK_WITH_RC4_128_SHA, "TLS-ECDHE-PSK-WITH-RC4-128-SHA", + POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_ARC4_C */ +#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) +#if defined(POLARSSL_AES_C) +#if defined(POLARSSL_GCM_C) +#if defined(POLARSSL_SHA256_C) + { TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, "TLS-RSA-PSK-WITH-AES-128-GCM-SHA256", + POLARSSL_CIPHER_AES_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA512_C) + { TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, "TLS-RSA-PSK-WITH-AES-256-GCM-SHA384", + POLARSSL_CIPHER_AES_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_RSA_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_GCM_C */ + +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA256_C) + { TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, "TLS-RSA-PSK-WITH-AES-128-CBC-SHA256", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA512_C) + { TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, "TLS-RSA-PSK-WITH-AES-256-CBC-SHA384", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_RSA_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ + +#if defined(POLARSSL_SHA1_C) + { TLS_RSA_PSK_WITH_AES_128_CBC_SHA, "TLS-RSA-PSK-WITH-AES-128-CBC-SHA", + POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, + + { TLS_RSA_PSK_WITH_AES_256_CBC_SHA, "TLS-RSA-PSK-WITH-AES-256-CBC-SHA", + POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_AES_C */ + +#if defined(POLARSSL_CAMELLIA_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA256_C) + { TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-RSA-PSK-WITH-CAMELLIA-128-CBC-SHA256", + POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA512_C) + { TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-RSA-PSK-WITH-CAMELLIA-256-CBC-SHA384", + POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_RSA_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ + +#if defined(POLARSSL_GCM_C) +#if defined(POLARSSL_SHA256_C) + { TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-RSA-PSK-WITH-CAMELLIA-128-GCM-SHA256", + POLARSSL_CIPHER_CAMELLIA_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA512_C) + { TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-RSA-PSK-WITH-CAMELLIA-256-GCM-SHA384", + POLARSSL_CIPHER_CAMELLIA_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_RSA_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_GCM_C */ +#endif /* POLARSSL_CAMELLIA_C */ + +#if defined(POLARSSL_DES_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_SHA1_C) + { TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-RSA-PSK-WITH-3DES-EDE-CBC-SHA", + POLARSSL_CIPHER_DES_EDE3_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_DES_C */ + +#if defined(POLARSSL_ARC4_C) +#if defined(POLARSSL_SHA1_C) + { TLS_RSA_PSK_WITH_RC4_128_SHA, "TLS-RSA-PSK-WITH-RC4-128-SHA", + POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + 0 }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_ARC4_C */ +#endif /* POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED */ + +#if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES) +#if defined(POLARSSL_CIPHER_NULL_CIPHER) +#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) +#if defined(POLARSSL_MD5_C) + { TLS_RSA_WITH_NULL_MD5, "TLS-RSA-WITH-NULL-MD5", + POLARSSL_CIPHER_NULL, POLARSSL_MD_MD5, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif + +#if defined(POLARSSL_SHA1_C) + { TLS_RSA_WITH_NULL_SHA, "TLS-RSA-WITH-NULL-SHA", + POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif + +#if defined(POLARSSL_SHA256_C) + { TLS_RSA_WITH_NULL_SHA256, "TLS-RSA-WITH-NULL-SHA256", + POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif +#endif /* POLARSSL_KEY_EXCHANGE_RSA_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) +#if defined(POLARSSL_SHA1_C) + { TLS_PSK_WITH_NULL_SHA, "TLS-PSK-WITH-NULL-SHA", + POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif /* POLARSSL_SHA1_C */ + +#if defined(POLARSSL_SHA256_C) + { TLS_PSK_WITH_NULL_SHA256, "TLS-PSK-WITH-NULL-SHA256", + POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif + +#if defined(POLARSSL_SHA512_C) + { TLS_PSK_WITH_NULL_SHA384, "TLS-PSK-WITH-NULL-SHA384", + POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif +#endif /* POLARSSL_KEY_EXCHANGE_PSK_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) +#if defined(POLARSSL_SHA1_C) + { TLS_DHE_PSK_WITH_NULL_SHA, "TLS-DHE-PSK-WITH-NULL-SHA", + POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif /* POLARSSL_SHA1_C */ + +#if defined(POLARSSL_SHA256_C) + { TLS_DHE_PSK_WITH_NULL_SHA256, "TLS-DHE-PSK-WITH-NULL-SHA256", + POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif + +#if defined(POLARSSL_SHA512_C) + { TLS_DHE_PSK_WITH_NULL_SHA384, "TLS-DHE-PSK-WITH-NULL-SHA384", + POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_DHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif +#endif /* POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#if defined(POLARSSL_SHA1_C) + { TLS_ECDHE_PSK_WITH_NULL_SHA, "TLS-ECDHE-PSK-WITH-NULL-SHA", + POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif /* POLARSSL_SHA1_C */ + +#if defined(POLARSSL_SHA256_C) + { TLS_ECDHE_PSK_WITH_NULL_SHA256, "TLS-ECDHE-PSK-WITH-NULL-SHA256", + POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif + +#if defined(POLARSSL_SHA512_C) + { TLS_ECDHE_PSK_WITH_NULL_SHA384, "TLS-ECDHE-PSK-WITH-NULL-SHA384", + POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDHE_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif +#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) +#if defined(POLARSSL_SHA1_C) + { TLS_RSA_PSK_WITH_NULL_SHA, "TLS-RSA-PSK-WITH-NULL-SHA", + POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif /* POLARSSL_SHA1_C */ + +#if defined(POLARSSL_SHA256_C) + { TLS_RSA_PSK_WITH_NULL_SHA256, "TLS-RSA-PSK-WITH-NULL-SHA256", + POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif + +#if defined(POLARSSL_SHA512_C) + { TLS_RSA_PSK_WITH_NULL_SHA384, "TLS-RSA-PSK-WITH-NULL-SHA384", + POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_RSA_PSK, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif +#endif /* POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#endif /* POLARSSL_CIPHER_NULL_CIPHER */ + +#if defined(POLARSSL_DES_C) +#if defined(POLARSSL_CIPHER_MODE_CBC) +#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) +#if defined(POLARSSL_SHA1_C) + { TLS_DHE_RSA_WITH_DES_CBC_SHA, "TLS-DHE-RSA-WITH-DES-CBC-SHA", + POLARSSL_CIPHER_DES_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) +#if defined(POLARSSL_SHA1_C) + { TLS_RSA_WITH_DES_CBC_SHA, "TLS-RSA-WITH-DES-CBC-SHA", + POLARSSL_CIPHER_DES_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0, + SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3, + POLARSSL_CIPHERSUITE_WEAK }, +#endif /* POLARSSL_SHA1_C */ +#endif /* POLARSSL_KEY_EXCHANGE_RSA_ENABLED */ +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* POLARSSL_DES_C */ +#endif /* POLARSSL_ENABLE_WEAK_CIPHERSUITES */ + + { 0, "", 0, 0, 0, 0, 0, 0, 0, 0 } +}; + +#if defined(SSL_CIPHERSUITES) +const int *ssl_list_ciphersuites( void ) +{ + return( ciphersuite_preference ); +} +#else +#define MAX_CIPHERSUITES sizeof( ciphersuite_definitions ) / \ + sizeof( ciphersuite_definitions[0] ) +static int supported_ciphersuites[MAX_CIPHERSUITES]; +static int supported_init = 0; + +const int *ssl_list_ciphersuites( void ) +{ + /* + * On initial call filter out all ciphersuites not supported by current + * build based on presence in the ciphersuite_definitions. + */ + if( supported_init == 0 ) + { + const int *p; + int *q; + + for( p = ciphersuite_preference, q = supported_ciphersuites; + *p != 0 && q < supported_ciphersuites + MAX_CIPHERSUITES - 1; + p++ ) + { +#if defined(POLARSSL_REMOVE_ARC4_CIPHERSUITES) + const ssl_ciphersuite_t *cs_info; + if( ( cs_info = ssl_ciphersuite_from_id( *p ) ) != NULL && + cs_info->cipher != POLARSSL_CIPHER_ARC4_128 ) +#else + if( ssl_ciphersuite_from_id( *p ) != NULL ) +#endif + *(q++) = *p; + } + *q = 0; + + supported_init = 1; + } + + return( supported_ciphersuites ); +}; +#endif /* SSL_CIPHERSUITES */ + +const ssl_ciphersuite_t *ssl_ciphersuite_from_string( + const char *ciphersuite_name ) +{ + const ssl_ciphersuite_t *cur = ciphersuite_definitions; + + if( NULL == ciphersuite_name ) + return( NULL ); + + while( cur->id != 0 ) + { + if( 0 == strcasecmp( cur->name, ciphersuite_name ) ) + return( cur ); + + cur++; + } + + return( NULL ); +} + +const ssl_ciphersuite_t *ssl_ciphersuite_from_id( int ciphersuite ) +{ + const ssl_ciphersuite_t *cur = ciphersuite_definitions; + + while( cur->id != 0 ) + { + if( cur->id == ciphersuite ) + return( cur ); + + cur++; + } + + return( NULL ); +} + +const char *ssl_get_ciphersuite_name( const int ciphersuite_id ) +{ + const ssl_ciphersuite_t *cur; + + cur = ssl_ciphersuite_from_id( ciphersuite_id ); + + if( cur == NULL ) + return( "unknown" ); + + return( cur->name ); +} + +int ssl_get_ciphersuite_id( const char *ciphersuite_name ) +{ + const ssl_ciphersuite_t *cur; + + cur = ssl_ciphersuite_from_string( ciphersuite_name ); + + if( cur == NULL ) + return( 0 ); + + return( cur->id ); +} + +#if defined(POLARSSL_PK_C) +pk_type_t ssl_get_ciphersuite_sig_pk_alg( const ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case POLARSSL_KEY_EXCHANGE_RSA: + case POLARSSL_KEY_EXCHANGE_DHE_RSA: + case POLARSSL_KEY_EXCHANGE_ECDHE_RSA: + case POLARSSL_KEY_EXCHANGE_RSA_PSK: + return( POLARSSL_PK_RSA ); + + case POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA: + return( POLARSSL_PK_ECDSA ); + + case POLARSSL_KEY_EXCHANGE_ECDH_RSA: + case POLARSSL_KEY_EXCHANGE_ECDH_ECDSA: + return( POLARSSL_PK_ECKEY ); + + default: + return( POLARSSL_PK_NONE ); + } +} +#endif /* POLARSSL_PK_C */ + +#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C) +int ssl_ciphersuite_uses_ec( const ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case POLARSSL_KEY_EXCHANGE_ECDHE_RSA: + case POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA: + case POLARSSL_KEY_EXCHANGE_ECDHE_PSK: + case POLARSSL_KEY_EXCHANGE_ECDH_RSA: + case POLARSSL_KEY_EXCHANGE_ECDH_ECDSA: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* POLARSSL_ECDH_C || POLARSSL_ECDSA_C */ + +#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED) +int ssl_ciphersuite_uses_psk( const ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case POLARSSL_KEY_EXCHANGE_PSK: + case POLARSSL_KEY_EXCHANGE_RSA_PSK: + case POLARSSL_KEY_EXCHANGE_DHE_PSK: + case POLARSSL_KEY_EXCHANGE_ECDHE_PSK: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#endif /* POLARSSL_SSL_TLS_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/ssl_cli.c b/component/common/network/ssl/polarssl-1.3.8/library/ssl_cli.c new file mode 100644 index 0000000..d38d769 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/ssl_cli.c @@ -0,0 +1,2635 @@ +/* + * SSLv3/TLSv1 client-side functions + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_SSL_CLI_C) + +#include "polarssl/debug.h" +#include "polarssl/ssl.h" + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#define polarssl_malloc malloc +#define polarssl_free free +#endif + +#include +#include + +#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32) +#include +typedef UINT32 uint32_t; +#else +#include +#endif + +#if defined(POLARSSL_HAVE_TIME) +#include +#endif + +#if defined(POLARSSL_SSL_SESSION_TICKETS) +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} +#endif + +#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION) +static void ssl_write_hostname_ext( ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + *olen = 0; + + if( ssl->hostname == NULL ) + return; + + SSL_DEBUG_MSG( 3, ( "client hello, adding server name extension: %s", + ssl->hostname ) ); + + /* + * struct { + * NameType name_type; + * select (name_type) { + * case host_name: HostName; + * } name; + * } ServerName; + * + * enum { + * host_name(0), (255) + * } NameType; + * + * opaque HostName<1..2^16-1>; + * + * struct { + * ServerName server_name_list<1..2^16-1> + * } ServerNameList; + */ + *p++ = (unsigned char)( ( TLS_EXT_SERVERNAME >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( TLS_EXT_SERVERNAME ) & 0xFF ); + + *p++ = (unsigned char)( ( (ssl->hostname_len + 5) >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( (ssl->hostname_len + 5) ) & 0xFF ); + + *p++ = (unsigned char)( ( (ssl->hostname_len + 3) >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( (ssl->hostname_len + 3) ) & 0xFF ); + + *p++ = (unsigned char)( ( TLS_EXT_SERVERNAME_HOSTNAME ) & 0xFF ); + *p++ = (unsigned char)( ( ssl->hostname_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ssl->hostname_len ) & 0xFF ); + + memcpy( p, ssl->hostname, ssl->hostname_len ); + + *olen = ssl->hostname_len + 9; +} +#endif /* POLARSSL_SSL_SERVER_NAME_INDICATION */ + +static void ssl_write_renegotiation_ext( ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + *olen = 0; + + if( ssl->renegotiation != SSL_RENEGOTIATION ) + return; + + SSL_DEBUG_MSG( 3, ( "client hello, adding renegotiation extension" ) ); + + /* + * Secure renegotiation + */ + *p++ = (unsigned char)( ( TLS_EXT_RENEGOTIATION_INFO >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( TLS_EXT_RENEGOTIATION_INFO ) & 0xFF ); + + *p++ = 0x00; + *p++ = ( ssl->verify_data_len + 1 ) & 0xFF; + *p++ = ssl->verify_data_len & 0xFF; + + memcpy( p, ssl->own_verify_data, ssl->verify_data_len ); + + *olen = 5 + ssl->verify_data_len; +} + +#if defined(POLARSSL_SSL_PROTO_TLS1_2) +static void ssl_write_signature_algorithms_ext( ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + size_t sig_alg_len = 0; +#if defined(POLARSSL_RSA_C) || defined(POLARSSL_ECDSA_C) + unsigned char *sig_alg_list = buf + 6; +#endif + + *olen = 0; + + if( ssl->max_minor_ver != SSL_MINOR_VERSION_3 ) + return; + + SSL_DEBUG_MSG( 3, ( "client hello, adding signature_algorithms extension" ) ); + + /* + * Prepare signature_algorithms extension (TLS 1.2) + */ +#if defined(POLARSSL_RSA_C) +#if defined(POLARSSL_SHA512_C) + sig_alg_list[sig_alg_len++] = SSL_HASH_SHA512; + sig_alg_list[sig_alg_len++] = SSL_SIG_RSA; + sig_alg_list[sig_alg_len++] = SSL_HASH_SHA384; + sig_alg_list[sig_alg_len++] = SSL_SIG_RSA; +#endif +#if defined(POLARSSL_SHA256_C) + sig_alg_list[sig_alg_len++] = SSL_HASH_SHA256; + sig_alg_list[sig_alg_len++] = SSL_SIG_RSA; + sig_alg_list[sig_alg_len++] = SSL_HASH_SHA224; + sig_alg_list[sig_alg_len++] = SSL_SIG_RSA; +#endif +#if defined(POLARSSL_SHA1_C) + sig_alg_list[sig_alg_len++] = SSL_HASH_SHA1; + sig_alg_list[sig_alg_len++] = SSL_SIG_RSA; +#endif +#if defined(POLARSSL_MD5_C) + sig_alg_list[sig_alg_len++] = SSL_HASH_MD5; + sig_alg_list[sig_alg_len++] = SSL_SIG_RSA; +#endif +#endif /* POLARSSL_RSA_C */ +#if defined(POLARSSL_ECDSA_C) +#if defined(POLARSSL_SHA512_C) + sig_alg_list[sig_alg_len++] = SSL_HASH_SHA512; + sig_alg_list[sig_alg_len++] = SSL_SIG_ECDSA; + sig_alg_list[sig_alg_len++] = SSL_HASH_SHA384; + sig_alg_list[sig_alg_len++] = SSL_SIG_ECDSA; +#endif +#if defined(POLARSSL_SHA256_C) + sig_alg_list[sig_alg_len++] = SSL_HASH_SHA256; + sig_alg_list[sig_alg_len++] = SSL_SIG_ECDSA; + sig_alg_list[sig_alg_len++] = SSL_HASH_SHA224; + sig_alg_list[sig_alg_len++] = SSL_SIG_ECDSA; +#endif +#if defined(POLARSSL_SHA1_C) + sig_alg_list[sig_alg_len++] = SSL_HASH_SHA1; + sig_alg_list[sig_alg_len++] = SSL_SIG_ECDSA; +#endif +#if defined(POLARSSL_MD5_C) + sig_alg_list[sig_alg_len++] = SSL_HASH_MD5; + sig_alg_list[sig_alg_len++] = SSL_SIG_ECDSA; +#endif +#endif /* POLARSSL_ECDSA_C */ + + /* + * enum { + * none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5), + * sha512(6), (255) + * } HashAlgorithm; + * + * enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) } + * SignatureAlgorithm; + * + * struct { + * HashAlgorithm hash; + * SignatureAlgorithm signature; + * } SignatureAndHashAlgorithm; + * + * SignatureAndHashAlgorithm + * supported_signature_algorithms<2..2^16-2>; + */ + *p++ = (unsigned char)( ( TLS_EXT_SIG_ALG >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( TLS_EXT_SIG_ALG ) & 0xFF ); + + *p++ = (unsigned char)( ( ( sig_alg_len + 2 ) >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ( sig_alg_len + 2 ) ) & 0xFF ); + + *p++ = (unsigned char)( ( sig_alg_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( sig_alg_len ) & 0xFF ); + + *olen = 6 + sig_alg_len; +} +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ + +#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C) +static void ssl_write_supported_elliptic_curves_ext( ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + unsigned char *elliptic_curve_list = p + 6; + size_t elliptic_curve_len = 0; + const ecp_curve_info *info; +#if defined(POLARSSL_SSL_SET_CURVES) + const ecp_group_id *grp_id; +#else + ((void) ssl); +#endif + + *olen = 0; + + SSL_DEBUG_MSG( 3, ( "client hello, adding supported_elliptic_curves extension" ) ); + +#if defined(POLARSSL_SSL_SET_CURVES) + for( grp_id = ssl->curve_list; *grp_id != POLARSSL_ECP_DP_NONE; grp_id++ ) + { + info = ecp_curve_info_from_grp_id( *grp_id ); +#else + for( info = ecp_curve_list(); info->grp_id != POLARSSL_ECP_DP_NONE; info++ ) + { +#endif + + elliptic_curve_list[elliptic_curve_len++] = info->tls_id >> 8; + elliptic_curve_list[elliptic_curve_len++] = info->tls_id & 0xFF; + } + + if( elliptic_curve_len == 0 ) + return; + + *p++ = (unsigned char)( ( TLS_EXT_SUPPORTED_ELLIPTIC_CURVES >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( TLS_EXT_SUPPORTED_ELLIPTIC_CURVES ) & 0xFF ); + + *p++ = (unsigned char)( ( ( elliptic_curve_len + 2 ) >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ( elliptic_curve_len + 2 ) ) & 0xFF ); + + *p++ = (unsigned char)( ( ( elliptic_curve_len ) >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ( elliptic_curve_len ) ) & 0xFF ); + + *olen = 6 + elliptic_curve_len; +} + +static void ssl_write_supported_point_formats_ext( ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + ((void) ssl); + + *olen = 0; + + SSL_DEBUG_MSG( 3, ( "client hello, adding supported_point_formats extension" ) ); + + *p++ = (unsigned char)( ( TLS_EXT_SUPPORTED_POINT_FORMATS >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( TLS_EXT_SUPPORTED_POINT_FORMATS ) & 0xFF ); + + *p++ = 0x00; + *p++ = 2; + + *p++ = 1; + *p++ = POLARSSL_ECP_PF_UNCOMPRESSED; + + *olen = 6; +} +#endif /* POLARSSL_ECDH_C || POLARSSL_ECDSA_C */ + +#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH) +static void ssl_write_max_fragment_length_ext( ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->mfl_code == SSL_MAX_FRAG_LEN_NONE ) { + *olen = 0; + return; + } + + SSL_DEBUG_MSG( 3, ( "client hello, adding max_fragment_length extension" ) ); + + *p++ = (unsigned char)( ( TLS_EXT_MAX_FRAGMENT_LENGTH >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( TLS_EXT_MAX_FRAGMENT_LENGTH ) & 0xFF ); + + *p++ = 0x00; + *p++ = 1; + + *p++ = ssl->mfl_code; + + *olen = 5; +} +#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(POLARSSL_SSL_TRUNCATED_HMAC) +static void ssl_write_truncated_hmac_ext( ssl_context *ssl, + unsigned char *buf, size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->trunc_hmac == SSL_TRUNC_HMAC_DISABLED ) + { + *olen = 0; + return; + } + + SSL_DEBUG_MSG( 3, ( "client hello, adding truncated_hmac extension" ) ); + + *p++ = (unsigned char)( ( TLS_EXT_TRUNCATED_HMAC >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( TLS_EXT_TRUNCATED_HMAC ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* POLARSSL_SSL_TRUNCATED_HMAC */ + +#if defined(POLARSSL_SSL_SESSION_TICKETS) +static void ssl_write_session_ticket_ext( ssl_context *ssl, + unsigned char *buf, size_t *olen ) +{ + unsigned char *p = buf; + size_t tlen = ssl->session_negotiate->ticket_len; + + if( ssl->session_tickets == SSL_SESSION_TICKETS_DISABLED ) + { + *olen = 0; + return; + } + + SSL_DEBUG_MSG( 3, ( "client hello, adding session ticket extension" ) ); + + *p++ = (unsigned char)( ( TLS_EXT_SESSION_TICKET >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( TLS_EXT_SESSION_TICKET ) & 0xFF ); + + *p++ = (unsigned char)( ( tlen >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( tlen ) & 0xFF ); + + *olen = 4; + + if( ssl->session_negotiate->ticket == NULL || + ssl->session_negotiate->ticket_len == 0 ) + { + return; + } + + SSL_DEBUG_MSG( 3, ( "sending session ticket of length %d", tlen ) ); + + memcpy( p, ssl->session_negotiate->ticket, tlen ); + + *olen += tlen; +} +#endif /* POLARSSL_SSL_SESSION_TICKETS */ + +#if defined(POLARSSL_SSL_ALPN) +static void ssl_write_alpn_ext( ssl_context *ssl, + unsigned char *buf, size_t *olen ) +{ + unsigned char *p = buf; + const char **cur; + + if( ssl->alpn_list == NULL ) + { + *olen = 0; + return; + } + + SSL_DEBUG_MSG( 3, ( "client hello, adding alpn extension" ) ); + + *p++ = (unsigned char)( ( TLS_EXT_ALPN >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( TLS_EXT_ALPN ) & 0xFF ); + + /* + * opaque ProtocolName<1..2^8-1>; + * + * struct { + * ProtocolName protocol_name_list<2..2^16-1> + * } ProtocolNameList; + */ + + /* Skip writing extension and list length for now */ + p += 4; + + for( cur = ssl->alpn_list; *cur != NULL; cur++ ) + { + *p = (unsigned char)( strlen( *cur ) & 0xFF ); + memcpy( p + 1, *cur, *p ); + p += 1 + *p; + } + + *olen = p - buf; + + /* List length = olen - 2 (ext_type) - 2 (ext_len) - 2 (list_len) */ + buf[4] = (unsigned char)( ( ( *olen - 6 ) >> 8 ) & 0xFF ); + buf[5] = (unsigned char)( ( ( *olen - 6 ) ) & 0xFF ); + + /* Extension length = olen - 2 (ext_type) - 2 (ext_len) */ + buf[2] = (unsigned char)( ( ( *olen - 4 ) >> 8 ) & 0xFF ); + buf[3] = (unsigned char)( ( ( *olen - 4 ) ) & 0xFF ); +} +#endif /* POLARSSL_SSL_ALPN */ + +static int ssl_write_client_hello( ssl_context *ssl ) +{ + int ret; + size_t i, n, olen, ext_len = 0; + unsigned char *buf; + unsigned char *p, *q; +#if defined(POLARSSL_HAVE_TIME) + time_t t; +#endif + const int *ciphersuites; + const ssl_ciphersuite_t *ciphersuite_info; + + SSL_DEBUG_MSG( 2, ( "=> write client hello" ) ); + + if( ssl->f_rng == NULL ) + { + SSL_DEBUG_MSG( 1, ( "no RNG provided") ); + return( POLARSSL_ERR_SSL_NO_RNG ); + } + + if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE ) + { + ssl->major_ver = ssl->min_major_ver; + ssl->minor_ver = ssl->min_minor_ver; + } + + if( ssl->max_major_ver == 0 && ssl->max_minor_ver == 0 ) + { + ssl->max_major_ver = SSL_MAX_MAJOR_VERSION; + ssl->max_minor_ver = SSL_MAX_MINOR_VERSION; + } + + /* + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 5 highest version supported + * 6 . 9 current UNIX time + * 10 . 37 random bytes + */ + buf = ssl->out_msg; + p = buf + 4; + + *p++ = (unsigned char) ssl->max_major_ver; + *p++ = (unsigned char) ssl->max_minor_ver; + + SSL_DEBUG_MSG( 3, ( "client hello, max version: [%d:%d]", + buf[4], buf[5] ) ); + +#if defined(POLARSSL_HAVE_TIME) + t = time( NULL ); + *p++ = (unsigned char)( t >> 24 ); + *p++ = (unsigned char)( t >> 16 ); + *p++ = (unsigned char)( t >> 8 ); + *p++ = (unsigned char)( t ); + + SSL_DEBUG_MSG( 3, ( "client hello, current time: %lu", t ) ); +#else + if( ( ret = ssl->f_rng( ssl->p_rng, p, 4 ) ) != 0 ) + return( ret ); + + p += 4; +#endif /* POLARSSL_HAVE_TIME */ + + if( ( ret = ssl->f_rng( ssl->p_rng, p, 28 ) ) != 0 ) + return( ret ); + + p += 28; + + memcpy( ssl->handshake->randbytes, buf + 6, 32 ); + + SSL_DEBUG_BUF( 3, "client hello, random bytes", buf + 6, 32 ); + + /* + * 38 . 38 session id length + * 39 . 39+n session id + * 40+n . 41+n ciphersuitelist length + * 42+n . .. ciphersuitelist + * .. . .. compression methods length + * .. . .. compression methods + * .. . .. extensions length + * .. . .. extensions + */ + n = ssl->session_negotiate->length; + + if( ssl->renegotiation != SSL_INITIAL_HANDSHAKE || n < 16 || n > 32 || + ssl->handshake->resume == 0 ) + { + n = 0; + } + +#if defined(POLARSSL_SSL_SESSION_TICKETS) + /* + * RFC 5077 section 3.4: "When presenting a ticket, the client MAY + * generate and include a Session ID in the TLS ClientHello." + */ + if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE && + ssl->session_negotiate->ticket != NULL && + ssl->session_negotiate->ticket_len != 0 ) + { + ret = ssl->f_rng( ssl->p_rng, ssl->session_negotiate->id, 32 ); + + if( ret != 0 ) + return( ret ); + + ssl->session_negotiate->length = n = 32; + } +#endif /* POLARSSL_SSL_SESSION_TICKETS */ + + *p++ = (unsigned char) n; + + for( i = 0; i < n; i++ ) + *p++ = ssl->session_negotiate->id[i]; + + SSL_DEBUG_MSG( 3, ( "client hello, session id len.: %d", n ) ); + SSL_DEBUG_BUF( 3, "client hello, session id", buf + 39, n ); + + ciphersuites = ssl->ciphersuite_list[ssl->minor_ver]; + n = 0; + q = p; + + // Skip writing ciphersuite length for now + p += 2; + + /* + * Add TLS_EMPTY_RENEGOTIATION_INFO_SCSV + */ + if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE ) + { + *p++ = (unsigned char)( SSL_EMPTY_RENEGOTIATION_INFO >> 8 ); + *p++ = (unsigned char)( SSL_EMPTY_RENEGOTIATION_INFO ); + n++; + } + + for( i = 0; ciphersuites[i] != 0; i++ ) + { + ciphersuite_info = ssl_ciphersuite_from_id( ciphersuites[i] ); + + if( ciphersuite_info == NULL ) + continue; + + if( ciphersuite_info->min_minor_ver > ssl->max_minor_ver || + ciphersuite_info->max_minor_ver < ssl->min_minor_ver ) + continue; + + SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %2d", + ciphersuites[i] ) ); + + n++; + *p++ = (unsigned char)( ciphersuites[i] >> 8 ); + *p++ = (unsigned char)( ciphersuites[i] ); + } + + *q++ = (unsigned char)( n >> 7 ); + *q++ = (unsigned char)( n << 1 ); + + SSL_DEBUG_MSG( 3, ( "client hello, got %d ciphersuites", n ) ); + + +#if defined(POLARSSL_ZLIB_SUPPORT) + SSL_DEBUG_MSG( 3, ( "client hello, compress len.: %d", 2 ) ); + SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d %d", + SSL_COMPRESS_DEFLATE, SSL_COMPRESS_NULL ) ); + + *p++ = 2; + *p++ = SSL_COMPRESS_DEFLATE; + *p++ = SSL_COMPRESS_NULL; +#else + SSL_DEBUG_MSG( 3, ( "client hello, compress len.: %d", 1 ) ); + SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d", SSL_COMPRESS_NULL ) ); + + *p++ = 1; + *p++ = SSL_COMPRESS_NULL; +#endif /* POLARSSL_ZLIB_SUPPORT */ + + // First write extensions, then the total length + // +#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION) + ssl_write_hostname_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + + ssl_write_renegotiation_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; + +#if defined(POLARSSL_SSL_PROTO_TLS1_2) + ssl_write_signature_algorithms_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C) + ssl_write_supported_elliptic_curves_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; + + ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH) + ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(POLARSSL_SSL_TRUNCATED_HMAC) + ssl_write_truncated_hmac_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(POLARSSL_SSL_SESSION_TICKETS) + ssl_write_session_ticket_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(POLARSSL_SSL_ALPN) + ssl_write_alpn_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + + SSL_DEBUG_MSG( 3, ( "client hello, total extension length: %d", + ext_len ) ); + + if( ext_len > 0 ) + { + *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ext_len ) & 0xFF ); + p += ext_len; + } + + ssl->out_msglen = p - buf; + ssl->out_msgtype = SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = SSL_HS_CLIENT_HELLO; + + ssl->state++; + + if( ( ret = ssl_write_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_write_record", ret ); + return( ret ); + } + + SSL_DEBUG_MSG( 2, ( "<= write client hello" ) ); + + return( 0 ); +} + +static int ssl_parse_renegotiation_info( ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + int ret; + + if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE ) + { + if( len != 1 || buf[0] != 0x0 ) + { + SSL_DEBUG_MSG( 1, ( "non-zero length renegotiated connection field" ) ); + + if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) + return( ret ); + + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ssl->secure_renegotiation = SSL_SECURE_RENEGOTIATION; + } + else + { + /* Check verify-data in constant-time. The length OTOH is no secret */ + if( len != 1 + ssl->verify_data_len * 2 || + buf[0] != ssl->verify_data_len * 2 || + safer_memcmp( buf + 1, + ssl->own_verify_data, ssl->verify_data_len ) != 0 || + safer_memcmp( buf + 1 + ssl->verify_data_len, + ssl->peer_verify_data, ssl->verify_data_len ) != 0 ) + { + SSL_DEBUG_MSG( 1, ( "non-matching renegotiated connection field" ) ); + + if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) + return( ret ); + + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + } + + return( 0 ); +} + +#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH) +static int ssl_parse_max_fragment_length_ext( ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + /* + * server should use the extension only if we did, + * and if so the server's value should match ours (and len is always 1) + */ + if( ssl->mfl_code == SSL_MAX_FRAG_LEN_NONE || + len != 1 || + buf[0] != ssl->mfl_code ) + { + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + return( 0 ); +} +#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(POLARSSL_SSL_TRUNCATED_HMAC) +static int ssl_parse_truncated_hmac_ext( ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( ssl->trunc_hmac == SSL_TRUNC_HMAC_DISABLED || + len != 0 ) + { + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ((void) buf); + + ssl->session_negotiate->trunc_hmac = SSL_TRUNC_HMAC_ENABLED; + + return( 0 ); +} +#endif /* POLARSSL_SSL_TRUNCATED_HMAC */ + +#if defined(POLARSSL_SSL_SESSION_TICKETS) +static int ssl_parse_session_ticket_ext( ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( ssl->session_tickets == SSL_SESSION_TICKETS_DISABLED || + len != 0 ) + { + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ((void) buf); + + ssl->handshake->new_session_ticket = 1; + + return( 0 ); +} +#endif /* POLARSSL_SSL_SESSION_TICKETS */ + +#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C) +static int ssl_parse_supported_point_formats_ext( ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + size_t list_size; + const unsigned char *p; + + list_size = buf[0]; + if( list_size + 1 != len ) + { + SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + p = buf + 1; + while( list_size > 0 ) + { + if( p[0] == POLARSSL_ECP_PF_UNCOMPRESSED || + p[0] == POLARSSL_ECP_PF_COMPRESSED ) + { + ssl->handshake->ecdh_ctx.point_format = p[0]; + SSL_DEBUG_MSG( 4, ( "point format selected: %d", p[0] ) ); + return( 0 ); + } + + list_size--; + p++; + } + + SSL_DEBUG_MSG( 1, ( "no point format in common" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); +} +#endif /* POLARSSL_ECDH_C || POLARSSL_ECDSA_C */ + +#if defined(POLARSSL_SSL_ALPN) +static int ssl_parse_alpn_ext( ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + size_t list_len, name_len; + const char **p; + + /* If we didn't send it, the server shouldn't send it */ + if( ssl->alpn_list == NULL ) + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + + /* + * opaque ProtocolName<1..2^8-1>; + * + * struct { + * ProtocolName protocol_name_list<2..2^16-1> + * } ProtocolNameList; + * + * the "ProtocolNameList" MUST contain exactly one "ProtocolName" + */ + + /* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */ + if( len < 4 ) + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + + list_len = ( buf[0] << 8 ) | buf[1]; + if( list_len != len - 2 ) + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + + name_len = buf[2]; + if( name_len != list_len - 1 ) + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + + /* Check that the server chosen protocol was in our list and save it */ + for( p = ssl->alpn_list; *p != NULL; p++ ) + { + if( name_len == strlen( *p ) && + memcmp( buf + 3, *p, name_len ) == 0 ) + { + ssl->alpn_chosen = *p; + return( 0 ); + } + } + + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); +} +#endif /* POLARSSL_SSL_ALPN */ + +static int ssl_parse_server_hello( ssl_context *ssl ) +{ + int ret, i, comp; + size_t n; + size_t ext_len = 0; + unsigned char *buf, *ext; + int renegotiation_info_seen = 0; + int handshake_failure = 0; +#if defined(POLARSSL_DEBUG_C) + uint32_t t; +#endif + + SSL_DEBUG_MSG( 2, ( "=> parse server hello" ) ); + + /* + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 5 protocol version + * 6 . 9 UNIX time() + * 10 . 37 random bytes + */ + buf = ssl->in_msg; + + if( ( ret = ssl_read_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != SSL_MSG_HANDSHAKE ) + { + SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + SSL_DEBUG_MSG( 3, ( "server hello, chosen version: [%d:%d]", + buf[4], buf[5] ) ); + + if( ssl->in_hslen < 42 || + buf[0] != SSL_HS_SERVER_HELLO || + buf[4] != SSL_MAJOR_VERSION_3 ) + { + SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + if( buf[5] > ssl->max_minor_ver ) + { + SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ssl->minor_ver = buf[5]; + + if( ssl->minor_ver < ssl->min_minor_ver ) + { + SSL_DEBUG_MSG( 1, ( "server only supports ssl smaller than minimum" + " [%d:%d] < [%d:%d]", ssl->major_ver, + ssl->minor_ver, buf[4], buf[5] ) ); + + ssl_send_alert_message( ssl, SSL_ALERT_LEVEL_FATAL, + SSL_ALERT_MSG_PROTOCOL_VERSION ); + + return( POLARSSL_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); + } + +#if defined(POLARSSL_DEBUG_C) + t = ( (uint32_t) buf[6] << 24 ) + | ( (uint32_t) buf[7] << 16 ) + | ( (uint32_t) buf[8] << 8 ) + | ( (uint32_t) buf[9] ); + SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", t ) ); +#endif + + memcpy( ssl->handshake->randbytes + 32, buf + 6, 32 ); + + n = buf[38]; + + SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 6, 32 ); + + if( n > 32 ) + { + SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + /* + * 38 . 38 session id length + * 39 . 38+n session id + * 39+n . 40+n chosen ciphersuite + * 41+n . 41+n chosen compression alg. + * 42+n . 43+n extensions length + * 44+n . 44+n+m extensions + */ + if( ssl->in_hslen > 42 + n ) + { + ext_len = ( ( buf[42 + n] << 8 ) + | ( buf[43 + n] ) ); + + if( ( ext_len > 0 && ext_len < 4 ) || + ssl->in_hslen != 44 + n + ext_len ) + { + SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + } + + i = ( buf[39 + n] << 8 ) | buf[40 + n]; + comp = buf[41 + n]; + + /* + * Initialize update checksum functions + */ + ssl->transform_negotiate->ciphersuite_info = ssl_ciphersuite_from_id( i ); + + if( ssl->transform_negotiate->ciphersuite_info == NULL ) + { + SSL_DEBUG_MSG( 1, ( "ciphersuite info for %04x not found", i ) ); + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + } + + ssl_optimize_checksum( ssl, ssl->transform_negotiate->ciphersuite_info ); + + SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) ); + SSL_DEBUG_BUF( 3, "server hello, session id", buf + 39, n ); + + /* + * Check if the session can be resumed + */ + if( ssl->renegotiation != SSL_INITIAL_HANDSHAKE || + ssl->handshake->resume == 0 || n == 0 || + ssl->session_negotiate->ciphersuite != i || + ssl->session_negotiate->compression != comp || + ssl->session_negotiate->length != n || + memcmp( ssl->session_negotiate->id, buf + 39, n ) != 0 ) + { + ssl->state++; + ssl->handshake->resume = 0; +#if defined(POLARSSL_HAVE_TIME) + ssl->session_negotiate->start = time( NULL ); +#endif + ssl->session_negotiate->ciphersuite = i; + ssl->session_negotiate->compression = comp; + ssl->session_negotiate->length = n; + memcpy( ssl->session_negotiate->id, buf + 39, n ); + } + else + { + ssl->state = SSL_SERVER_CHANGE_CIPHER_SPEC; + + if( ( ret = ssl_derive_keys( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_derive_keys", ret ); + return( ret ); + } + } + + SSL_DEBUG_MSG( 3, ( "%s session has been resumed", + ssl->handshake->resume ? "a" : "no" ) ); + + SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %d", i ) ); + SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d", buf[41 + n] ) ); + + i = 0; + while( 1 ) + { + if( ssl->ciphersuite_list[ssl->minor_ver][i] == 0 ) + { + SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + if( ssl->ciphersuite_list[ssl->minor_ver][i++] == + ssl->session_negotiate->ciphersuite ) + { + break; + } + } + + if( comp != SSL_COMPRESS_NULL +#if defined(POLARSSL_ZLIB_SUPPORT) + && comp != SSL_COMPRESS_DEFLATE +#endif + ) + { + SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + ssl->session_negotiate->compression = comp; + + ext = buf + 44 + n; + + SSL_DEBUG_MSG( 2, ( "server hello, total extension length: %d", ext_len ) ); + + while( ext_len ) + { + unsigned int ext_id = ( ( ext[0] << 8 ) + | ( ext[1] ) ); + unsigned int ext_size = ( ( ext[2] << 8 ) + | ( ext[3] ) ); + + if( ext_size + 4 > ext_len ) + { + SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + switch( ext_id ) + { + case TLS_EXT_RENEGOTIATION_INFO: + SSL_DEBUG_MSG( 3, ( "found renegotiation extension" ) ); + renegotiation_info_seen = 1; + + if( ( ret = ssl_parse_renegotiation_info( ssl, ext + 4, + ext_size ) ) != 0 ) + return( ret ); + + break; + +#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH) + case TLS_EXT_MAX_FRAGMENT_LENGTH: + SSL_DEBUG_MSG( 3, ( "found max_fragment_length extension" ) ); + + if( ( ret = ssl_parse_max_fragment_length_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(POLARSSL_SSL_TRUNCATED_HMAC) + case TLS_EXT_TRUNCATED_HMAC: + SSL_DEBUG_MSG( 3, ( "found truncated_hmac extension" ) ); + + if( ( ret = ssl_parse_truncated_hmac_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* POLARSSL_SSL_TRUNCATED_HMAC */ + +#if defined(POLARSSL_SSL_SESSION_TICKETS) + case TLS_EXT_SESSION_TICKET: + SSL_DEBUG_MSG( 3, ( "found session_ticket extension" ) ); + + if( ( ret = ssl_parse_session_ticket_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* POLARSSL_SSL_SESSION_TICKETS */ + +#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C) + case TLS_EXT_SUPPORTED_POINT_FORMATS: + SSL_DEBUG_MSG( 3, ( "found supported_point_formats extension" ) ); + + if( ( ret = ssl_parse_supported_point_formats_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* POLARSSL_ECDH_C || POLARSSL_ECDSA_C */ + +#if defined(POLARSSL_SSL_ALPN) + case TLS_EXT_ALPN: + SSL_DEBUG_MSG( 3, ( "found alpn extension" ) ); + + if( ( ret = ssl_parse_alpn_ext( ssl, ext + 4, ext_size ) ) != 0 ) + return( ret ); + + break; +#endif /* POLARSSL_SSL_ALPN */ + + default: + SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)", + ext_id ) ); + } + + ext_len -= 4 + ext_size; + ext += 4 + ext_size; + + if( ext_len > 0 && ext_len < 4 ) + { + SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + } + + /* + * Renegotiation security checks + */ + if( ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION && + ssl->allow_legacy_renegotiation == SSL_LEGACY_BREAK_HANDSHAKE ) + { + SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) ); + handshake_failure = 1; + } + else if( ssl->renegotiation == SSL_RENEGOTIATION && + ssl->secure_renegotiation == SSL_SECURE_RENEGOTIATION && + renegotiation_info_seen == 0 ) + { + SSL_DEBUG_MSG( 1, ( "renegotiation_info extension missing (secure)" ) ); + handshake_failure = 1; + } + else if( ssl->renegotiation == SSL_RENEGOTIATION && + ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION && + ssl->allow_legacy_renegotiation == SSL_LEGACY_NO_RENEGOTIATION ) + { + SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) ); + handshake_failure = 1; + } + else if( ssl->renegotiation == SSL_RENEGOTIATION && + ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION && + renegotiation_info_seen == 1 ) + { + SSL_DEBUG_MSG( 1, ( "renegotiation_info extension present (legacy)" ) ); + handshake_failure = 1; + } + + if( handshake_failure == 1 ) + { + if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) + return( ret ); + + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + SSL_DEBUG_MSG( 2, ( "<= parse server hello" ) ); + + return( 0 ); +} + +#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) +static int ssl_parse_server_dh_params( ssl_context *ssl, unsigned char **p, + unsigned char *end ) +{ + int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE; + + /* + * Ephemeral DH parameters: + * + * struct { + * opaque dh_p<1..2^16-1>; + * opaque dh_g<1..2^16-1>; + * opaque dh_Ys<1..2^16-1>; + * } ServerDHParams; + */ + if( ( ret = dhm_read_params( &ssl->handshake->dhm_ctx, p, end ) ) != 0 ) + { + SSL_DEBUG_RET( 2, ( "dhm_read_params" ), ret ); + return( ret ); + } + + if( ssl->handshake->dhm_ctx.len < 64 || + ssl->handshake->dhm_ctx.len > 512 ) + { + SSL_DEBUG_MSG( 1, ( "bad server key exchange message (DHM length)" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P ); + SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->handshake->dhm_ctx.G ); + SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->handshake->dhm_ctx.GY ); + + return( ret ); +} +#endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED || + POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +static int ssl_check_server_ecdh_params( const ssl_context *ssl ) +{ + const ecp_curve_info *curve_info; + + curve_info = ecp_curve_info_from_grp_id( ssl->handshake->ecdh_ctx.grp.id ); + if( curve_info == NULL ) + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + + SSL_DEBUG_MSG( 2, ( "ECDH curve: %s", curve_info->name ) ); + +#if defined(POLARSSL_SSL_ECP_SET_CURVES) + if( ! ssl_curve_is_acceptable( ssl, ssl->handshake->ecdh_ctx.grp.id ) ) +#else + if( ssl->handshake->ecdh_ctx.grp.nbits < 163 || + ssl->handshake->ecdh_ctx.grp.nbits > 521 ) +#endif + return( -1 ); + + SSL_DEBUG_ECP( 3, "ECDH: Qp", &ssl->handshake->ecdh_ctx.Qp ); + + return( 0 ); +} +#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +static int ssl_parse_server_ecdh_params( ssl_context *ssl, + unsigned char **p, + unsigned char *end ) +{ + int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE; + + /* + * Ephemeral ECDH parameters: + * + * struct { + * ECParameters curve_params; + * ECPoint public; + * } ServerECDHParams; + */ + if( ( ret = ecdh_read_params( &ssl->handshake->ecdh_ctx, + (const unsigned char **) p, end ) ) != 0 ) + { + SSL_DEBUG_RET( 1, ( "ecdh_read_params" ), ret ); + return( ret ); + } + + if( ssl_check_server_ecdh_params( ssl ) != 0 ) + { + SSL_DEBUG_MSG( 1, ( "bad server key exchange message (ECDHE curve)" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + return( ret ); +} +#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED) +static int ssl_parse_server_psk_hint( ssl_context *ssl, + unsigned char **p, + unsigned char *end ) +{ + int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE; + size_t len; + ((void) ssl); + + /* + * PSK parameters: + * + * opaque psk_identity_hint<0..2^16-1>; + */ + len = (*p)[0] << 8 | (*p)[1]; + *p += 2; + + if( (*p) + len > end ) + { + SSL_DEBUG_MSG( 1, ( "bad server key exchange message (psk_identity_hint length)" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + // TODO: Retrieve PSK identity hint and callback to app + // + *p += len; + ret = 0; + + return( ret ); +} +#endif /* POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) +/* + * Generate a pre-master secret and encrypt it with the server's RSA key + */ +static int ssl_write_encrypted_pms( ssl_context *ssl, + size_t offset, size_t *olen, + size_t pms_offset ) +{ + int ret; + size_t len_bytes = ssl->minor_ver == SSL_MINOR_VERSION_0 ? 0 : 2; + unsigned char *p = ssl->handshake->premaster + pms_offset; + + /* + * Generate (part of) the pre-master as + * struct { + * ProtocolVersion client_version; + * opaque random[46]; + * } PreMasterSecret; + */ + p[0] = (unsigned char) ssl->max_major_ver; + p[1] = (unsigned char) ssl->max_minor_ver; + + if( ( ret = ssl->f_rng( ssl->p_rng, p + 2, 46 ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "f_rng", ret ); + return( ret ); + } + + ssl->handshake->pmslen = 48; + + /* + * Now write it out, encrypted + */ + if( ! pk_can_do( &ssl->session_negotiate->peer_cert->pk, + POLARSSL_PK_RSA ) ) + { + SSL_DEBUG_MSG( 1, ( "certificate key type mismatch" ) ); + return( POLARSSL_ERR_SSL_PK_TYPE_MISMATCH ); + } + + if( ( ret = pk_encrypt( &ssl->session_negotiate->peer_cert->pk, + p, ssl->handshake->pmslen, + ssl->out_msg + offset + len_bytes, olen, + SSL_MAX_CONTENT_LEN - offset - len_bytes, + ssl->f_rng, ssl->p_rng ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "rsa_pkcs1_encrypt", ret ); + return( ret ); + } + +#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_2) + if( len_bytes == 2 ) + { + ssl->out_msg[offset+0] = (unsigned char)( *olen >> 8 ); + ssl->out_msg[offset+1] = (unsigned char)( *olen ); + *olen += 2; + } +#endif + + return( 0 ); +} +#endif /* POLARSSL_KEY_EXCHANGE_RSA_ENABLED || + POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED */ + +#if defined(POLARSSL_SSL_PROTO_TLS1_2) +#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +static int ssl_parse_signature_algorithm( ssl_context *ssl, + unsigned char **p, + unsigned char *end, + md_type_t *md_alg, + pk_type_t *pk_alg ) +{ + ((void) ssl); + *md_alg = POLARSSL_MD_NONE; + *pk_alg = POLARSSL_PK_NONE; + + /* Only in TLS 1.2 */ + if( ssl->minor_ver != SSL_MINOR_VERSION_3 ) + { + return( 0 ); + } + + if( (*p) + 2 > end ) + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + + /* + * Get hash algorithm + */ + if( ( *md_alg = ssl_md_alg_from_hash( (*p)[0] ) ) == POLARSSL_MD_NONE ) + { + SSL_DEBUG_MSG( 2, ( "Server used unsupported " + "HashAlgorithm %d", *(p)[0] ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + /* + * Get signature algorithm + */ + if( ( *pk_alg = ssl_pk_alg_from_sig( (*p)[1] ) ) == POLARSSL_PK_NONE ) + { + SSL_DEBUG_MSG( 2, ( "server used unsupported " + "SignatureAlgorithm %d", (*p)[1] ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + SSL_DEBUG_MSG( 2, ( "Server used SignatureAlgorithm %d", (*p)[1] ) ); + SSL_DEBUG_MSG( 2, ( "Server used HashAlgorithm %d", (*p)[0] ) ); + *p += 2; + + return( 0 ); +} +#endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ + + +#if defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +static int ssl_get_ecdh_params_from_cert( ssl_context *ssl ) +{ + int ret; + const ecp_keypair *peer_key; + + if( ! pk_can_do( &ssl->session_negotiate->peer_cert->pk, + POLARSSL_PK_ECKEY ) ) + { + SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) ); + return( POLARSSL_ERR_SSL_PK_TYPE_MISMATCH ); + } + + peer_key = pk_ec( ssl->session_negotiate->peer_cert->pk ); + + if( ( ret = ecdh_get_params( &ssl->handshake->ecdh_ctx, peer_key, + POLARSSL_ECDH_THEIRS ) ) != 0 ) + { + SSL_DEBUG_RET( 1, ( "ecdh_get_params" ), ret ); + return( ret ); + } + + if( ssl_check_server_ecdh_params( ssl ) != 0 ) + { + SSL_DEBUG_MSG( 1, ( "bad server certificate (ECDH curve)" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + return( ret ); +} +#endif /* POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) || + POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +static int ssl_parse_server_key_exchange( ssl_context *ssl ) +{ + int ret; + const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + unsigned char *p, *end; +#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + size_t sig_len, params_len; + unsigned char hash[64]; + md_type_t md_alg = POLARSSL_MD_NONE; + size_t hashlen; + pk_type_t pk_alg = POLARSSL_PK_NONE; +#endif + + SSL_DEBUG_MSG( 2, ( "=> parse server key exchange" ) ); + +#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA ) + { + SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) ); + ssl->state++; + return( 0 ); + } + ((void) p); + ((void) end); +#endif + +#if defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDH_RSA || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDH_ECDSA ) + { + if( ( ret = ssl_get_ecdh_params_from_cert( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_get_ecdh_params_from_cert", ret ); + return( ret ); + } + + SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) ); + ssl->state++; + return( 0 ); + } + ((void) p); + ((void) end); +#endif /* POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + + if( ( ret = ssl_read_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != SSL_MSG_HANDSHAKE ) + { + SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + /* + * ServerKeyExchange may be skipped with PSK and RSA-PSK when the server + * doesn't use a psk_identity_hint + */ + if( ssl->in_msg[0] != SSL_HS_SERVER_KEY_EXCHANGE ) + { + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK ) + { + ssl->record_read = 1; + goto exit; + } + + SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + p = ssl->in_msg + 4; + end = ssl->in_msg + ssl->in_hslen; + SSL_DEBUG_BUF( 3, "server key exchange", p, ssl->in_hslen - 4 ); + +#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) + { + if( ssl_parse_server_psk_hint( ssl, &p, end ) != 0 ) + { + SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } /* FALLTROUGH */ +#endif /* POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK ) + ; /* nothing more to do */ + else +#endif /* POLARSSL_KEY_EXCHANGE_PSK_ENABLED || + POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_RSA || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK ) + { + if( ssl_parse_server_dh_params( ssl, &p, end ) != 0 ) + { + SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } + else +#endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED || + POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA ) + { + if( ssl_parse_server_ecdh_params( ssl, &p, end ) != 0 ) + { + SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } + else +#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_RSA || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA ) + { + params_len = p - ( ssl->in_msg + 4 ); + + /* + * Handle the digitally-signed structure + */ +#if defined(POLARSSL_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == SSL_MINOR_VERSION_3 ) + { + if( ssl_parse_signature_algorithm( ssl, &p, end, + &md_alg, &pk_alg ) != 0 ) + { + SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + if( pk_alg != ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ) ) + { + SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } + else +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ +#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_1) + if( ssl->minor_ver < SSL_MINOR_VERSION_3 ) + { + pk_alg = ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ); + + /* Default hash for ECDSA is SHA-1 */ + if( pk_alg == POLARSSL_PK_ECDSA && md_alg == POLARSSL_MD_NONE ) + md_alg = POLARSSL_MD_SHA1; + } + else +#endif + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + + /* + * Read signature + */ + sig_len = ( p[0] << 8 ) | p[1]; + p += 2; + + if( end != p + sig_len ) + { + SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + SSL_DEBUG_BUF( 3, "signature", p, sig_len ); + + /* + * Compute the hash that has been signed + */ +#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_1) + if( md_alg == POLARSSL_MD_NONE ) + { + md5_context md5; + sha1_context sha1; + + md5_init( &md5 ); + sha1_init( &sha1 ); + + hashlen = 36; + + /* + * digitally-signed struct { + * opaque md5_hash[16]; + * opaque sha_hash[20]; + * }; + * + * md5_hash + * MD5(ClientHello.random + ServerHello.random + * + ServerParams); + * sha_hash + * SHA(ClientHello.random + ServerHello.random + * + ServerParams); + */ + md5_starts( &md5 ); + md5_update( &md5, ssl->handshake->randbytes, 64 ); + md5_update( &md5, ssl->in_msg + 4, params_len ); + md5_finish( &md5, hash ); + + sha1_starts( &sha1 ); + sha1_update( &sha1, ssl->handshake->randbytes, 64 ); + sha1_update( &sha1, ssl->in_msg + 4, params_len ); + sha1_finish( &sha1, hash + 16 ); + + md5_free( &md5 ); + sha1_free( &sha1 ); + } + else +#endif /* POLARSSL_SSL_PROTO_SSL3 || POLARSSL_SSL_PROTO_TLS1 || \ + POLARSSL_SSL_PROTO_TLS1_1 */ +#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_2) + if( md_alg != POLARSSL_MD_NONE ) + { + md_context_t ctx; + + md_init( &ctx ); + + /* Info from md_alg will be used instead */ + hashlen = 0; + + /* + * digitally-signed struct { + * opaque client_random[32]; + * opaque server_random[32]; + * ServerDHParams params; + * }; + */ + if( ( ret = md_init_ctx( &ctx, + md_info_from_type( md_alg ) ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "md_init_ctx", ret ); + return( ret ); + } + + md_starts( &ctx ); + md_update( &ctx, ssl->handshake->randbytes, 64 ); + md_update( &ctx, ssl->in_msg + 4, params_len ); + md_finish( &ctx, hash ); + md_free( &ctx ); + } + else +#endif /* POLARSSL_SSL_PROTO_TLS1 || POLARSSL_SSL_PROTO_TLS1_1 || \ + POLARSSL_SSL_PROTO_TLS1_2 */ + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + + SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen != 0 ? hashlen : + (unsigned int) ( md_info_from_type( md_alg ) )->size ); + + /* + * Verify signature + */ + if( ! pk_can_do( &ssl->session_negotiate->peer_cert->pk, pk_alg ) ) + { + SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + return( POLARSSL_ERR_SSL_PK_TYPE_MISMATCH ); + } + + if( ( ret = pk_verify( &ssl->session_negotiate->peer_cert->pk, + md_alg, hash, hashlen, p, sig_len ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "pk_verify", ret ); + return( ret ); + } + } +#endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + +exit: + ssl->state++; + + SSL_DEBUG_MSG( 2, ( "<= parse server key exchange" ) ); + + return( 0 ); +} + +#if !defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) && \ + !defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ + !defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ + !defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +static int ssl_parse_certificate_request( ssl_context *ssl ) +{ + const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) ); + + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) + { + SSL_DEBUG_MSG( 2, ( "<= skip parse certificate request" ) ); + ssl->state++; + return( 0 ); + } + + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); +} +#else +static int ssl_parse_certificate_request( ssl_context *ssl ) +{ + int ret; + unsigned char *buf, *p; + size_t n = 0, m = 0; + size_t cert_type_len = 0, dn_len = 0; + const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) ); + + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) + { + SSL_DEBUG_MSG( 2, ( "<= skip parse certificate request" ) ); + ssl->state++; + return( 0 ); + } + + /* + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 4 cert type count + * 5 .. m-1 cert types + * m .. m+1 sig alg length (TLS 1.2 only) + * m+1 .. n-1 SignatureAndHashAlgorithms (TLS 1.2 only) + * n .. n+1 length of all DNs + * n+2 .. n+3 length of DN 1 + * n+4 .. ... Distinguished Name #1 + * ... .. ... length of DN 2, etc. + */ + if( ssl->record_read == 0 ) + { + if( ( ret = ssl_read_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != SSL_MSG_HANDSHAKE ) + { + SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + ssl->record_read = 1; + } + + ssl->client_auth = 0; + ssl->state++; + + if( ssl->in_msg[0] == SSL_HS_CERTIFICATE_REQUEST ) + ssl->client_auth++; + + SSL_DEBUG_MSG( 3, ( "got %s certificate request", + ssl->client_auth ? "a" : "no" ) ); + + if( ssl->client_auth == 0 ) + goto exit; + + ssl->record_read = 0; + + // TODO: handshake_failure alert for an anonymous server to request + // client authentication + + buf = ssl->in_msg; + + // Retrieve cert types + // + cert_type_len = buf[4]; + n = cert_type_len; + + if( ssl->in_hslen < 6 + n ) + { + SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); + } + + p = buf + 5; + while( cert_type_len > 0 ) + { +#if defined(POLARSSL_RSA_C) + if( *p == SSL_CERT_TYPE_RSA_SIGN && + pk_can_do( ssl_own_key( ssl ), POLARSSL_PK_RSA ) ) + { + ssl->handshake->cert_type = SSL_CERT_TYPE_RSA_SIGN; + break; + } + else +#endif +#if defined(POLARSSL_ECDSA_C) + if( *p == SSL_CERT_TYPE_ECDSA_SIGN && + pk_can_do( ssl_own_key( ssl ), POLARSSL_PK_ECDSA ) ) + { + ssl->handshake->cert_type = SSL_CERT_TYPE_ECDSA_SIGN; + break; + } + else +#endif + { + ; /* Unsupported cert type, ignore */ + } + + cert_type_len--; + p++; + } + +#if defined(POLARSSL_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == SSL_MINOR_VERSION_3 ) + { + /* Ignored, see comments about hash in write_certificate_verify */ + // TODO: should check the signature part against our pk_key though + size_t sig_alg_len = ( ( buf[5 + n] << 8 ) + | ( buf[6 + n] ) ); + + p = buf + 7 + n; + m += 2; + n += sig_alg_len; + + if( ssl->in_hslen < 6 + n ) + { + SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); + } + } +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ + + /* Ignore certificate_authorities, we only have one cert anyway */ + // TODO: should not send cert if no CA matches + dn_len = ( ( buf[5 + m + n] << 8 ) + | ( buf[6 + m + n] ) ); + + n += dn_len; + if( ssl->in_hslen != 7 + m + n ) + { + SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); + } + +exit: + SSL_DEBUG_MSG( 2, ( "<= parse certificate request" ) ); + + return( 0 ); +} +#endif /* !POLARSSL_KEY_EXCHANGE_RSA_ENABLED && + !POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED && + !POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED && + !POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + +static int ssl_parse_server_hello_done( ssl_context *ssl ) +{ + int ret; + + SSL_DEBUG_MSG( 2, ( "=> parse server hello done" ) ); + + if( ssl->record_read == 0 ) + { + if( ( ret = ssl_read_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != SSL_MSG_HANDSHAKE ) + { + SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) ); + return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ); + } + } + ssl->record_read = 0; + + if( ssl->in_hslen != 4 || + ssl->in_msg[0] != SSL_HS_SERVER_HELLO_DONE ) + { + SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO_DONE ); + } + + ssl->state++; + + SSL_DEBUG_MSG( 2, ( "<= parse server hello done" ) ); + + return( 0 ); +} + +static int ssl_write_client_key_exchange( ssl_context *ssl ) +{ + int ret; + size_t i, n; + const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + SSL_DEBUG_MSG( 2, ( "=> write client key exchange" ) ); + +#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_RSA ) + { + /* + * DHM key exchange -- send G^X mod P + */ + n = ssl->handshake->dhm_ctx.len; + + ssl->out_msg[4] = (unsigned char)( n >> 8 ); + ssl->out_msg[5] = (unsigned char)( n ); + i = 6; + + ret = dhm_make_public( &ssl->handshake->dhm_ctx, + (int) mpi_size( &ssl->handshake->dhm_ctx.P ), + &ssl->out_msg[i], n, + ssl->f_rng, ssl->p_rng ); + if( ret != 0 ) + { + SSL_DEBUG_RET( 1, "dhm_make_public", ret ); + return( ret ); + } + + SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X ); + SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX ); + + ssl->handshake->pmslen = POLARSSL_PREMASTER_SIZE; + + if( ( ret = dhm_calc_secret( &ssl->handshake->dhm_ctx, + ssl->handshake->premaster, + &ssl->handshake->pmslen, + ssl->f_rng, ssl->p_rng ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "dhm_calc_secret", ret ); + return( ret ); + } + + SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K ); + } + else +#endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDH_RSA || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDH_ECDSA ) + { + /* + * ECDH key exchange -- send client public value + */ + i = 4; + + ret = ecdh_make_public( &ssl->handshake->ecdh_ctx, + &n, + &ssl->out_msg[i], 1000, + ssl->f_rng, ssl->p_rng ); + if( ret != 0 ) + { + SSL_DEBUG_RET( 1, "ecdh_make_public", ret ); + return( ret ); + } + + SSL_DEBUG_ECP( 3, "ECDH: Q", &ssl->handshake->ecdh_ctx.Q ); + + if( ( ret = ecdh_calc_secret( &ssl->handshake->ecdh_ctx, + &ssl->handshake->pmslen, + ssl->handshake->premaster, + POLARSSL_MPI_MAX_SIZE, + ssl->f_rng, ssl->p_rng ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ecdh_calc_secret", ret ); + return( ret ); + } + + SSL_DEBUG_MPI( 3, "ECDH: z", &ssl->handshake->ecdh_ctx.z ); + } + else +#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) + { + /* + * opaque psk_identity<0..2^16-1>; + */ + if( ssl->psk == NULL || ssl->psk_identity == NULL ) + return( POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED ); + + i = 4; + n = ssl->psk_identity_len; + ssl->out_msg[i++] = (unsigned char)( n >> 8 ); + ssl->out_msg[i++] = (unsigned char)( n ); + + memcpy( ssl->out_msg + i, ssl->psk_identity, ssl->psk_identity_len ); + i += ssl->psk_identity_len; + +#if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK ) + { + n = 0; + } + else +#endif +#if defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK ) + { + if( ( ret = ssl_write_encrypted_pms( ssl, i, &n, 2 ) ) != 0 ) + return( ret ); + } + else +#endif +#if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK ) + { + /* + * ClientDiffieHellmanPublic public (DHM send G^X mod P) + */ + n = ssl->handshake->dhm_ctx.len; + ssl->out_msg[i++] = (unsigned char)( n >> 8 ); + ssl->out_msg[i++] = (unsigned char)( n ); + + ret = dhm_make_public( &ssl->handshake->dhm_ctx, + (int) mpi_size( &ssl->handshake->dhm_ctx.P ), + &ssl->out_msg[i], n, + ssl->f_rng, ssl->p_rng ); + if( ret != 0 ) + { + SSL_DEBUG_RET( 1, "dhm_make_public", ret ); + return( ret ); + } + } + else +#endif /* POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) + { + /* + * ClientECDiffieHellmanPublic public; + */ + ret = ecdh_make_public( &ssl->handshake->ecdh_ctx, &n, + &ssl->out_msg[i], SSL_MAX_CONTENT_LEN - i, + ssl->f_rng, ssl->p_rng ); + if( ret != 0 ) + { + SSL_DEBUG_RET( 1, "ecdh_make_public", ret ); + return( ret ); + } + + SSL_DEBUG_ECP( 3, "ECDH: Q", &ssl->handshake->ecdh_ctx.Q ); + } + else +#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + + if( ( ret = ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA ) + { + i = 4; + if( ( ret = ssl_write_encrypted_pms( ssl, i, &n, 0 ) ) != 0 ) + return( ret ); + } + else +#endif /* POLARSSL_KEY_EXCHANGE_RSA_ENABLED */ + { + ((void) ciphersuite_info); + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + + if( ( ret = ssl_derive_keys( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_derive_keys", ret ); + return( ret ); + } + + ssl->out_msglen = i + n; + ssl->out_msgtype = SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = SSL_HS_CLIENT_KEY_EXCHANGE; + + ssl->state++; + + if( ( ret = ssl_write_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_write_record", ret ); + return( ret ); + } + + SSL_DEBUG_MSG( 2, ( "<= write client key exchange" ) ); + + return( 0 ); +} + +#if !defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) && \ + !defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ + !defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ + !defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +static int ssl_write_certificate_verify( ssl_context *ssl ) +{ + const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) ); + + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK ) + { + SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); +} +#else +static int ssl_write_certificate_verify( ssl_context *ssl ) +{ + int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE; + const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + size_t n = 0, offset = 0; + unsigned char hash[48]; + unsigned char *hash_start = hash; + md_type_t md_alg = POLARSSL_MD_NONE; + unsigned int hashlen; + + SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) ); + + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK ) + { + SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + if( ssl->client_auth == 0 || ssl_own_cert( ssl ) == NULL ) + { + SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + if( ssl_own_key( ssl ) == NULL ) + { + SSL_DEBUG_MSG( 1, ( "got no private key" ) ); + return( POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + /* + * Make an RSA signature of the handshake digests + */ + ssl->handshake->calc_verify( ssl, hash ); + +#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_1) + if( ssl->minor_ver != SSL_MINOR_VERSION_3 ) + { + /* + * digitally-signed struct { + * opaque md5_hash[16]; + * opaque sha_hash[20]; + * }; + * + * md5_hash + * MD5(handshake_messages); + * + * sha_hash + * SHA(handshake_messages); + */ + hashlen = 36; + md_alg = POLARSSL_MD_NONE; + + /* + * For ECDSA, default hash is SHA-1 only + */ + if( pk_can_do( ssl_own_key( ssl ), POLARSSL_PK_ECDSA ) ) + { + hash_start += 16; + hashlen -= 16; + md_alg = POLARSSL_MD_SHA1; + } + } + else +#endif /* POLARSSL_SSL_PROTO_SSL3 || POLARSSL_SSL_PROTO_TLS1 || \ + POLARSSL_SSL_PROTO_TLS1_1 */ +#if defined(POLARSSL_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == SSL_MINOR_VERSION_3 ) + { + /* + * digitally-signed struct { + * opaque handshake_messages[handshake_messages_length]; + * }; + * + * Taking shortcut here. We assume that the server always allows the + * PRF Hash function and has sent it in the allowed signature + * algorithms list received in the Certificate Request message. + * + * Until we encounter a server that does not, we will take this + * shortcut. + * + * Reason: Otherwise we should have running hashes for SHA512 and SHA224 + * in order to satisfy 'weird' needs from the server side. + */ + if( ssl->transform_negotiate->ciphersuite_info->mac == + POLARSSL_MD_SHA384 ) + { + md_alg = POLARSSL_MD_SHA384; + ssl->out_msg[4] = SSL_HASH_SHA384; + } + else + { + md_alg = POLARSSL_MD_SHA256; + ssl->out_msg[4] = SSL_HASH_SHA256; + } + ssl->out_msg[5] = ssl_sig_from_pk( ssl_own_key( ssl ) ); + + /* Info from md_alg will be used instead */ + hashlen = 0; + offset = 2; + } + else +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + + if( ( ret = pk_sign( ssl_own_key( ssl ), md_alg, hash_start, hashlen, + ssl->out_msg + 6 + offset, &n, + ssl->f_rng, ssl->p_rng ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "pk_sign", ret ); + return( ret ); + } + + ssl->out_msg[4 + offset] = (unsigned char)( n >> 8 ); + ssl->out_msg[5 + offset] = (unsigned char)( n ); + + ssl->out_msglen = 6 + n + offset; + ssl->out_msgtype = SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = SSL_HS_CERTIFICATE_VERIFY; + + ssl->state++; + + if( ( ret = ssl_write_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_write_record", ret ); + return( ret ); + } + + SSL_DEBUG_MSG( 2, ( "<= write certificate verify" ) ); + + return( ret ); +} +#endif /* !POLARSSL_KEY_EXCHANGE_RSA_ENABLED && + !POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED && + !POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ + +#if defined(POLARSSL_SSL_SESSION_TICKETS) +static int ssl_parse_new_session_ticket( ssl_context *ssl ) +{ + int ret; + uint32_t lifetime; + size_t ticket_len; + unsigned char *ticket; + + SSL_DEBUG_MSG( 2, ( "=> parse new session ticket" ) ); + + if( ( ret = ssl_read_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != SSL_MSG_HANDSHAKE ) + { + SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); + return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + /* + * struct { + * uint32 ticket_lifetime_hint; + * opaque ticket<0..2^16-1>; + * } NewSessionTicket; + * + * 0 . 0 handshake message type + * 1 . 3 handshake message length + * 4 . 7 ticket_lifetime_hint + * 8 . 9 ticket_len (n) + * 10 . 9+n ticket content + */ + if( ssl->in_msg[0] != SSL_HS_NEW_SESSION_TICKET || + ssl->in_hslen < 10 ) + { + SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_NEW_SESSION_TICKET ); + } + + lifetime = ( ssl->in_msg[4] << 24 ) | ( ssl->in_msg[5] << 16 ) | + ( ssl->in_msg[6] << 8 ) | ( ssl->in_msg[7] ); + + ticket_len = ( ssl->in_msg[8] << 8 ) | ( ssl->in_msg[9] ); + + if( ticket_len + 10 != ssl->in_hslen ) + { + SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_NEW_SESSION_TICKET ); + } + + SSL_DEBUG_MSG( 3, ( "ticket length: %d", ticket_len ) ); + + /* We're not waiting for a NewSessionTicket message any more */ + ssl->handshake->new_session_ticket = 0; + + /* + * Zero-length ticket means the server changed his mind and doesn't want + * to send a ticket after all, so just forget it + */ + if( ticket_len == 0 ) + return( 0 ); + + polarssl_zeroize( ssl->session_negotiate->ticket, + ssl->session_negotiate->ticket_len ); + polarssl_free( ssl->session_negotiate->ticket ); + ssl->session_negotiate->ticket = NULL; + ssl->session_negotiate->ticket_len = 0; + + if( ( ticket = polarssl_malloc( ticket_len ) ) == NULL ) + { + SSL_DEBUG_MSG( 1, ( "ticket malloc failed" ) ); + return( POLARSSL_ERR_SSL_MALLOC_FAILED ); + } + + memcpy( ticket, ssl->in_msg + 10, ticket_len ); + + ssl->session_negotiate->ticket = ticket; + ssl->session_negotiate->ticket_len = ticket_len; + ssl->session_negotiate->ticket_lifetime = lifetime; + + /* + * RFC 5077 section 3.4: + * "If the client receives a session ticket from the server, then it + * discards any Session ID that was sent in the ServerHello." + */ + SSL_DEBUG_MSG( 3, ( "ticket in use, discarding session id" ) ); + ssl->session_negotiate->length = 0; + + SSL_DEBUG_MSG( 2, ( "<= parse new session ticket" ) ); + + return( 0 ); +} +#endif /* POLARSSL_SSL_SESSION_TICKETS */ + +/* + * SSL handshake -- client side -- single step + */ +int ssl_handshake_client_step( ssl_context *ssl ) +{ + int ret = 0; + + if( ssl->state == SSL_HANDSHAKE_OVER ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + SSL_DEBUG_MSG( 2, ( "client state: %d", ssl->state ) ); + + if( ( ret = ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + + switch( ssl->state ) + { + case SSL_HELLO_REQUEST: + ssl->state = SSL_CLIENT_HELLO; + break; + + /* + * ==> ClientHello + */ + case SSL_CLIENT_HELLO: + ret = ssl_write_client_hello( ssl ); + break; + + /* + * <== ServerHello + * Certificate + * ( ServerKeyExchange ) + * ( CertificateRequest ) + * ServerHelloDone + */ + case SSL_SERVER_HELLO: + ret = ssl_parse_server_hello( ssl ); + break; + + case SSL_SERVER_CERTIFICATE: + ret = ssl_parse_certificate( ssl ); + break; + + case SSL_SERVER_KEY_EXCHANGE: + ret = ssl_parse_server_key_exchange( ssl ); + break; + + case SSL_CERTIFICATE_REQUEST: + ret = ssl_parse_certificate_request( ssl ); + break; + + case SSL_SERVER_HELLO_DONE: + ret = ssl_parse_server_hello_done( ssl ); + break; + + /* + * ==> ( Certificate/Alert ) + * ClientKeyExchange + * ( CertificateVerify ) + * ChangeCipherSpec + * Finished + */ + case SSL_CLIENT_CERTIFICATE: + ret = ssl_write_certificate( ssl ); + break; + + case SSL_CLIENT_KEY_EXCHANGE: + ret = ssl_write_client_key_exchange( ssl ); + break; + + case SSL_CERTIFICATE_VERIFY: + ret = ssl_write_certificate_verify( ssl ); + break; + + case SSL_CLIENT_CHANGE_CIPHER_SPEC: + ret = ssl_write_change_cipher_spec( ssl ); + break; + + case SSL_CLIENT_FINISHED: + ret = ssl_write_finished( ssl ); + break; + + /* + * <== ( NewSessionTicket ) + * ChangeCipherSpec + * Finished + */ + case SSL_SERVER_CHANGE_CIPHER_SPEC: +#if defined(POLARSSL_SSL_SESSION_TICKETS) + if( ssl->handshake->new_session_ticket != 0 ) + ret = ssl_parse_new_session_ticket( ssl ); + else +#endif + ret = ssl_parse_change_cipher_spec( ssl ); + break; + + case SSL_SERVER_FINISHED: + ret = ssl_parse_finished( ssl ); + break; + + case SSL_FLUSH_BUFFERS: + SSL_DEBUG_MSG( 2, ( "handshake: done" ) ); + ssl->state = SSL_HANDSHAKE_WRAPUP; + break; + + case SSL_HANDSHAKE_WRAPUP: + ssl_handshake_wrapup( ssl ); + break; + + default: + SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) ); + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + } + + return( ret ); +} +#endif /* POLARSSL_SSL_CLI_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/ssl_srv.c b/component/common/network/ssl/polarssl-1.3.8/library/ssl_srv.c new file mode 100644 index 0000000..25be988 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/ssl_srv.c @@ -0,0 +1,3269 @@ +/* + * SSLv3/TLSv1 server-side functions + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_SSL_SRV_C) + +#include "polarssl/debug.h" +#include "polarssl/ssl.h" +#if defined(POLARSSL_ECP_C) +#include "polarssl/ecp.h" +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#define polarssl_malloc malloc +#define polarssl_free free +#endif + +#include +#include + +#if defined(POLARSSL_HAVE_TIME) +#include +#endif + +#if defined(POLARSSL_SSL_SESSION_TICKETS) +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * Serialize a session in the following format: + * 0 . n-1 session structure, n = sizeof(ssl_session) + * n . n+2 peer_cert length = m (0 if no certificate) + * n+3 . n+2+m peer cert ASN.1 + * + * Assumes ticket is NULL (always true on server side). + */ +static int ssl_save_session( const ssl_session *session, + unsigned char *buf, size_t buf_len, + size_t *olen ) +{ + unsigned char *p = buf; + size_t left = buf_len; +#if defined(POLARSSL_X509_CRT_PARSE_C) + size_t cert_len; +#endif /* POLARSSL_X509_CRT_PARSE_C */ + + if( left < sizeof( ssl_session ) ) + return( -1 ); + + memcpy( p, session, sizeof( ssl_session ) ); + p += sizeof( ssl_session ); + left -= sizeof( ssl_session ); + +#if defined(POLARSSL_X509_CRT_PARSE_C) + if( session->peer_cert == NULL ) + cert_len = 0; + else + cert_len = session->peer_cert->raw.len; + + if( left < 3 + cert_len ) + return( -1 ); + + *p++ = (unsigned char)( cert_len >> 16 & 0xFF ); + *p++ = (unsigned char)( cert_len >> 8 & 0xFF ); + *p++ = (unsigned char)( cert_len & 0xFF ); + + if( session->peer_cert != NULL ) + memcpy( p, session->peer_cert->raw.p, cert_len ); + + p += cert_len; +#endif /* POLARSSL_X509_CRT_PARSE_C */ + + *olen = p - buf; + + return( 0 ); +} + +/* + * Unserialise session, see ssl_save_session() + */ +static int ssl_load_session( ssl_session *session, + const unsigned char *buf, size_t len ) +{ + const unsigned char *p = buf; + const unsigned char * const end = buf + len; +#if defined(POLARSSL_X509_CRT_PARSE_C) + size_t cert_len; +#endif /* POLARSSL_X509_CRT_PARSE_C */ + + if( p + sizeof( ssl_session ) > end ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + memcpy( session, p, sizeof( ssl_session ) ); + p += sizeof( ssl_session ); + +#if defined(POLARSSL_X509_CRT_PARSE_C) + if( p + 3 > end ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + cert_len = ( p[0] << 16 ) | ( p[1] << 8 ) | p[2]; + p += 3; + + if( cert_len == 0 ) + { + session->peer_cert = NULL; + } + else + { + int ret; + + if( p + cert_len > end ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + session->peer_cert = polarssl_malloc( sizeof( x509_crt ) ); + + if( session->peer_cert == NULL ) + return( POLARSSL_ERR_SSL_MALLOC_FAILED ); + + x509_crt_init( session->peer_cert ); + + if( ( ret = x509_crt_parse_der( session->peer_cert, + p, cert_len ) ) != 0 ) + { + x509_crt_free( session->peer_cert ); + polarssl_free( session->peer_cert ); + session->peer_cert = NULL; + return( ret ); + } + + p += cert_len; + } +#endif /* POLARSSL_X509_CRT_PARSE_C */ + + if( p != end ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + return( 0 ); +} + +/* + * Create session ticket, secured as recommended in RFC 5077 section 4: + * + * struct { + * opaque key_name[16]; + * opaque iv[16]; + * opaque encrypted_state<0..2^16-1>; + * opaque mac[32]; + * } ticket; + * + * (the internal state structure differs, however). + */ +static int ssl_write_ticket( ssl_context *ssl, size_t *tlen ) +{ + int ret; + unsigned char * const start = ssl->out_msg + 10; + unsigned char *p = start; + unsigned char *state; + unsigned char iv[16]; + size_t clear_len, enc_len, pad_len, i; + + *tlen = 0; + + if( ssl->ticket_keys == NULL ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + /* Write key name */ + memcpy( p, ssl->ticket_keys->key_name, 16 ); + p += 16; + + /* Generate and write IV (with a copy for aes_crypt) */ + if( ( ret = ssl->f_rng( ssl->p_rng, p, 16 ) ) != 0 ) + return( ret ); + memcpy( iv, p, 16 ); + p += 16; + + /* + * Dump session state + * + * After the session state itself, we still need room for 16 bytes of + * padding and 32 bytes of MAC, so there's only so much room left + */ + state = p + 2; + if( ssl_save_session( ssl->session_negotiate, state, + SSL_MAX_CONTENT_LEN - ( state - ssl->out_ctr ) - 48, + &clear_len ) != 0 ) + { + return( POLARSSL_ERR_SSL_CERTIFICATE_TOO_LARGE ); + } + SSL_DEBUG_BUF( 3, "session ticket cleartext", state, clear_len ); + + /* Apply PKCS padding */ + pad_len = 16 - clear_len % 16; + enc_len = clear_len + pad_len; + for( i = clear_len; i < enc_len; i++ ) + state[i] = (unsigned char) pad_len; + + /* Encrypt */ + if( ( ret = aes_crypt_cbc( &ssl->ticket_keys->enc, AES_ENCRYPT, + enc_len, iv, state, state ) ) != 0 ) + { + return( ret ); + } + + /* Write length */ + *p++ = (unsigned char)( ( enc_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( enc_len ) & 0xFF ); + p = state + enc_len; + + /* Compute and write MAC( key_name + iv + enc_state_len + enc_state ) */ + sha256_hmac( ssl->ticket_keys->mac_key, 16, start, p - start, p, 0 ); + p += 32; + + *tlen = p - start; + + SSL_DEBUG_BUF( 3, "session ticket structure", start, *tlen ); + + return( 0 ); +} + +/* + * Load session ticket (see ssl_write_ticket for structure) + */ +static int ssl_parse_ticket( ssl_context *ssl, + unsigned char *buf, + size_t len ) +{ + int ret; + ssl_session session; + unsigned char *key_name = buf; + unsigned char *iv = buf + 16; + unsigned char *enc_len_p = iv + 16; + unsigned char *ticket = enc_len_p + 2; + unsigned char *mac; + unsigned char computed_mac[32]; + size_t enc_len, clear_len, i; + unsigned char pad_len, diff; + + SSL_DEBUG_BUF( 3, "session ticket structure", buf, len ); + + if( len < 34 || ssl->ticket_keys == NULL ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + enc_len = ( enc_len_p[0] << 8 ) | enc_len_p[1]; + mac = ticket + enc_len; + + if( len != enc_len + 66 ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + /* Check name, in constant time though it's not a big secret */ + diff = 0; + for( i = 0; i < 16; i++ ) + diff |= key_name[i] ^ ssl->ticket_keys->key_name[i]; + /* don't return yet, check the MAC anyway */ + + /* Check mac, with constant-time buffer comparison */ + sha256_hmac( ssl->ticket_keys->mac_key, 16, buf, len - 32, + computed_mac, 0 ); + + for( i = 0; i < 32; i++ ) + diff |= mac[i] ^ computed_mac[i]; + + /* Now return if ticket is not authentic, since we want to avoid + * decrypting arbitrary attacker-chosen data */ + if( diff != 0 ) + return( POLARSSL_ERR_SSL_INVALID_MAC ); + + /* Decrypt */ + if( ( ret = aes_crypt_cbc( &ssl->ticket_keys->dec, AES_DECRYPT, + enc_len, iv, ticket, ticket ) ) != 0 ) + { + return( ret ); + } + + /* Check PKCS padding */ + pad_len = ticket[enc_len - 1]; + + ret = 0; + for( i = 2; i < pad_len; i++ ) + if( ticket[enc_len - i] != pad_len ) + ret = POLARSSL_ERR_SSL_BAD_INPUT_DATA; + if( ret != 0 ) + return( ret ); + + clear_len = enc_len - pad_len; + + SSL_DEBUG_BUF( 3, "session ticket cleartext", ticket, clear_len ); + + /* Actually load session */ + if( ( ret = ssl_load_session( &session, ticket, clear_len ) ) != 0 ) + { + SSL_DEBUG_MSG( 1, ( "failed to parse ticket content" ) ); + ssl_session_free( &session ); + return( ret ); + } + +#if defined(POLARSSL_HAVE_TIME) + /* Check if still valid */ + if( (int) ( time( NULL) - session.start ) > ssl->ticket_lifetime ) + { + SSL_DEBUG_MSG( 1, ( "session ticket expired" ) ); + ssl_session_free( &session ); + return( POLARSSL_ERR_SSL_SESSION_TICKET_EXPIRED ); + } +#endif + + /* + * Keep the session ID sent by the client, since we MUST send it back to + * inform him we're accepting the ticket (RFC 5077 section 3.4) + */ + session.length = ssl->session_negotiate->length; + memcpy( &session.id, ssl->session_negotiate->id, session.length ); + + ssl_session_free( ssl->session_negotiate ); + memcpy( ssl->session_negotiate, &session, sizeof( ssl_session ) ); + + /* Zeroize instead of free as we copied the content */ + polarssl_zeroize( &session, sizeof( ssl_session ) ); + + return( 0 ); +} +#endif /* POLARSSL_SSL_SESSION_TICKETS */ + +#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION) +/* + * Wrapper around f_sni, allowing use of ssl_set_own_cert() but + * making it act on ssl->hanshake->sni_key_cert instead. + */ +static int ssl_sni_wrapper( ssl_context *ssl, + const unsigned char* name, size_t len ) +{ + int ret; + ssl_key_cert *key_cert_ori = ssl->key_cert; + + ssl->key_cert = NULL; + ret = ssl->f_sni( ssl->p_sni, ssl, name, len ); + ssl->handshake->sni_key_cert = ssl->key_cert; + + ssl->key_cert = key_cert_ori; + + return( ret ); +} + +static int ssl_parse_servername_ext( ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + int ret; + size_t servername_list_size, hostname_len; + const unsigned char *p; + + SSL_DEBUG_MSG( 3, ( "parse ServerName extension" ) ); + + servername_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); + if( servername_list_size + 2 != len ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + p = buf + 2; + while( servername_list_size > 0 ) + { + hostname_len = ( ( p[1] << 8 ) | p[2] ); + if( hostname_len + 3 > servername_list_size ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + if( p[0] == TLS_EXT_SERVERNAME_HOSTNAME ) + { + ret = ssl_sni_wrapper( ssl, p + 3, hostname_len ); + if( ret != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_sni_wrapper", ret ); + ssl_send_alert_message( ssl, SSL_ALERT_LEVEL_FATAL, + SSL_ALERT_MSG_UNRECOGNIZED_NAME ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + return( 0 ); + } + + servername_list_size -= hostname_len + 3; + p += hostname_len + 3; + } + + if( servername_list_size != 0 ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + return( 0 ); +} +#endif /* POLARSSL_SSL_SERVER_NAME_INDICATION */ + +static int ssl_parse_renegotiation_info( ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + int ret; + + if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE ) + { + if( len != 1 || buf[0] != 0x0 ) + { + SSL_DEBUG_MSG( 1, ( "non-zero length renegotiated connection field" ) ); + + if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) + return( ret ); + + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->secure_renegotiation = SSL_SECURE_RENEGOTIATION; + } + else + { + /* Check verify-data in constant-time. The length OTOH is no secret */ + if( len != 1 + ssl->verify_data_len || + buf[0] != ssl->verify_data_len || + safer_memcmp( buf + 1, ssl->peer_verify_data, + ssl->verify_data_len ) != 0 ) + { + SSL_DEBUG_MSG( 1, ( "non-matching renegotiated connection field" ) ); + + if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) + return( ret ); + + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + } + + return( 0 ); +} + +#if defined(POLARSSL_SSL_PROTO_TLS1_2) +static int ssl_parse_signature_algorithms_ext( ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + size_t sig_alg_list_size; + const unsigned char *p; + const unsigned char *end = buf + len; + const int *md_cur; + + + sig_alg_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); + if( sig_alg_list_size + 2 != len || + sig_alg_list_size % 2 != 0 ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* + * For now, ignore the SignatureAlgorithm part and rely on offered + * ciphersuites only for that part. To be fixed later. + * + * So, just look at the HashAlgorithm part. + */ + for( md_cur = md_list(); *md_cur != POLARSSL_MD_NONE; md_cur++ ) { + for( p = buf + 2; p < end; p += 2 ) { + if( *md_cur == (int) ssl_md_alg_from_hash( p[0] ) ) { + ssl->handshake->sig_alg = p[0]; + break; + } + } + } + + SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext: %d", + ssl->handshake->sig_alg ) ); + + return( 0 ); +} +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ + +#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C) +static int ssl_parse_supported_elliptic_curves( ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + size_t list_size, our_size; + const unsigned char *p; + const ecp_curve_info *curve_info, **curves; + + list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); + if( list_size + 2 != len || + list_size % 2 != 0 ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* Don't allow our peer to make us allocate too much memory, + * and leave room for a final 0 */ + our_size = list_size / 2 + 1; + if( our_size > POLARSSL_ECP_DP_MAX ) + our_size = POLARSSL_ECP_DP_MAX; + + if( ( curves = polarssl_malloc( our_size * sizeof( *curves ) ) ) == NULL ) + return( POLARSSL_ERR_SSL_MALLOC_FAILED ); + + /* explicit void pointer cast for buggy MS compiler */ + memset( (void *) curves, 0, our_size * sizeof( *curves ) ); + ssl->handshake->curves = curves; + + p = buf + 2; + while( list_size > 0 && our_size > 1 ) + { + curve_info = ecp_curve_info_from_tls_id( ( p[0] << 8 ) | p[1] ); + + if( curve_info != NULL ) + { + *curves++ = curve_info; + our_size--; + } + + list_size -= 2; + p += 2; + } + + return( 0 ); +} + +static int ssl_parse_supported_point_formats( ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + size_t list_size; + const unsigned char *p; + + list_size = buf[0]; + if( list_size + 1 != len ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + p = buf + 2; + while( list_size > 0 ) + { + if( p[0] == POLARSSL_ECP_PF_UNCOMPRESSED || + p[0] == POLARSSL_ECP_PF_COMPRESSED ) + { + ssl->handshake->ecdh_ctx.point_format = p[0]; + SSL_DEBUG_MSG( 4, ( "point format selected: %d", p[0] ) ); + return( 0 ); + } + + list_size--; + p++; + } + + return( 0 ); +} +#endif /* POLARSSL_ECDH_C || POLARSSL_ECDSA_C */ + +#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH) +static int ssl_parse_max_fragment_length_ext( ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( len != 1 || buf[0] >= SSL_MAX_FRAG_LEN_INVALID ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->session_negotiate->mfl_code = buf[0]; + + return( 0 ); +} +#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(POLARSSL_SSL_TRUNCATED_HMAC) +static int ssl_parse_truncated_hmac_ext( ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( len != 0 ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ((void) buf); + + ssl->session_negotiate->trunc_hmac = SSL_TRUNC_HMAC_ENABLED; + + return( 0 ); +} +#endif /* POLARSSL_SSL_TRUNCATED_HMAC */ + +#if defined(POLARSSL_SSL_SESSION_TICKETS) +static int ssl_parse_session_ticket_ext( ssl_context *ssl, + unsigned char *buf, + size_t len ) +{ + int ret; + + if( ssl->session_tickets == SSL_SESSION_TICKETS_DISABLED ) + return( 0 ); + + /* Remember the client asked us to send a new ticket */ + ssl->handshake->new_session_ticket = 1; + + SSL_DEBUG_MSG( 3, ( "ticket length: %d", len ) ); + + if( len == 0 ) + return( 0 ); + + if( ssl->renegotiation != SSL_INITIAL_HANDSHAKE ) + { + SSL_DEBUG_MSG( 3, ( "ticket rejected: renegotiating" ) ); + return( 0 ); + } + + /* + * Failures are ok: just ignore the ticket and proceed. + */ + if( ( ret = ssl_parse_ticket( ssl, buf, len ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_parse_ticket", ret ); + return( 0 ); + } + + SSL_DEBUG_MSG( 3, ( "session successfully restored from ticket" ) ); + + ssl->handshake->resume = 1; + + /* Don't send a new ticket after all, this one is OK */ + ssl->handshake->new_session_ticket = 0; + + return( 0 ); +} +#endif /* POLARSSL_SSL_SESSION_TICKETS */ + +#if defined(POLARSSL_SSL_ALPN) +static int ssl_parse_alpn_ext( ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + size_t list_len, cur_len, ours_len; + const unsigned char *theirs, *start, *end; + const char **ours; + + /* If ALPN not configured, just ignore the extension */ + if( ssl->alpn_list == NULL ) + return( 0 ); + + /* + * opaque ProtocolName<1..2^8-1>; + * + * struct { + * ProtocolName protocol_name_list<2..2^16-1> + * } ProtocolNameList; + */ + + /* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */ + if( len < 4 ) + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + + list_len = ( buf[0] << 8 ) | buf[1]; + if( list_len != len - 2 ) + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + + /* + * Use our order of preference + */ + start = buf + 2; + end = buf + len; + for( ours = ssl->alpn_list; *ours != NULL; ours++ ) + { + ours_len = strlen( *ours ); + for( theirs = start; theirs != end; theirs += cur_len ) + { + /* If the list is well formed, we should get equality first */ + if( theirs > end ) + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + + cur_len = *theirs++; + + /* Empty strings MUST NOT be included */ + if( cur_len == 0 ) + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + + if( cur_len == ours_len && + memcmp( theirs, *ours, cur_len ) == 0 ) + { + ssl->alpn_chosen = *ours; + return( 0 ); + } + } + } + + /* If we get there, no match was found */ + ssl_send_alert_message( ssl, SSL_ALERT_LEVEL_FATAL, + SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); +} +#endif /* POLARSSL_SSL_ALPN */ + +/* + * Auxiliary functions for ServerHello parsing and related actions + */ + +#if defined(POLARSSL_X509_CRT_PARSE_C) +/* + * Return 1 if the given EC key uses the given curve, 0 otherwise + */ +#if defined(POLARSSL_ECDSA_C) +static int ssl_key_matches_curves( pk_context *pk, + const ecp_curve_info **curves ) +{ + const ecp_curve_info **crv = curves; + ecp_group_id grp_id = pk_ec( *pk )->grp.id; + + while( *crv != NULL ) + { + if( (*crv)->grp_id == grp_id ) + return( 1 ); + crv++; + } + + return( 0 ); +} +#endif /* POLARSSL_ECDSA_C */ + +/* + * Try picking a certificate for this ciphersuite, + * return 0 on success and -1 on failure. + */ +static int ssl_pick_cert( ssl_context *ssl, + const ssl_ciphersuite_t * ciphersuite_info ) +{ + ssl_key_cert *cur, *list; + pk_type_t pk_alg = ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ); + +#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION) + if( ssl->handshake->sni_key_cert != NULL ) + list = ssl->handshake->sni_key_cert; + else +#endif + list = ssl->handshake->key_cert; + + if( pk_alg == POLARSSL_PK_NONE ) + return( 0 ); + + for( cur = list; cur != NULL; cur = cur->next ) + { + if( ! pk_can_do( cur->key, pk_alg ) ) + continue; + + /* + * This avoids sending the client a cert it'll reject based on + * keyUsage or other extensions. + * + * It also allows the user to provision different certificates for + * different uses based on keyUsage, eg if they want to avoid signing + * and decrypting with the same RSA key. + */ + if( ssl_check_cert_usage( cur->cert, ciphersuite_info, + SSL_IS_SERVER ) != 0 ) + { + continue; + } + +#if defined(POLARSSL_ECDSA_C) + if( pk_alg == POLARSSL_PK_ECDSA ) + { + if( ssl_key_matches_curves( cur->key, ssl->handshake->curves ) ) + break; + } + else +#endif + break; + } + + if( cur == NULL ) + return( -1 ); + + ssl->handshake->key_cert = cur; + return( 0 ); +} +#endif /* POLARSSL_X509_CRT_PARSE_C */ + +/* + * Check if a given ciphersuite is suitable for use with our config/keys/etc + * Sets ciphersuite_info only if the suite matches. + */ +static int ssl_ciphersuite_match( ssl_context *ssl, int suite_id, + const ssl_ciphersuite_t **ciphersuite_info ) +{ + const ssl_ciphersuite_t *suite_info; + + suite_info = ssl_ciphersuite_from_id( suite_id ); + if( suite_info == NULL ) + { + SSL_DEBUG_MSG( 1, ( "ciphersuite info for %04x not found", suite_id ) ); + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + } + + if( suite_info->min_minor_ver > ssl->minor_ver || + suite_info->max_minor_ver < ssl->minor_ver ) + return( 0 ); + +#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C) + if( ssl_ciphersuite_uses_ec( suite_info ) && + ( ssl->handshake->curves == NULL || + ssl->handshake->curves[0] == NULL ) ) + return( 0 ); +#endif + +#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED) + /* If the ciphersuite requires a pre-shared key and we don't + * have one, skip it now rather than failing later */ + if( ssl_ciphersuite_uses_psk( suite_info ) && + ssl->f_psk == NULL && + ( ssl->psk == NULL || ssl->psk_identity == NULL || + ssl->psk_identity_len == 0 || ssl->psk_len == 0 ) ) + return( 0 ); +#endif + +#if defined(POLARSSL_X509_CRT_PARSE_C) + /* + * Final check: if ciphersuite requires us to have a + * certificate/key of a particular type: + * - select the appropriate certificate if we have one, or + * - try the next ciphersuite if we don't + * This must be done last since we modify the key_cert list. + */ + if( ssl_pick_cert( ssl, suite_info ) != 0 ) + return( 0 ); +#endif + + *ciphersuite_info = suite_info; + return( 0 ); +} + +#if defined(POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) +static int ssl_parse_client_hello_v2( ssl_context *ssl ) +{ + int ret; + unsigned int i, j; + size_t n; + unsigned int ciph_len, sess_len, chal_len; + unsigned char *buf, *p; + const int *ciphersuites; + const ssl_ciphersuite_t *ciphersuite_info; + + SSL_DEBUG_MSG( 2, ( "=> parse client hello v2" ) ); + + if( ssl->renegotiation != SSL_INITIAL_HANDSHAKE ) + { + SSL_DEBUG_MSG( 1, ( "client hello v2 illegal for renegotiation" ) ); + + if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) + return( ret ); + + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + buf = ssl->in_hdr; + + SSL_DEBUG_BUF( 4, "record header", buf, 5 ); + + SSL_DEBUG_MSG( 3, ( "client hello v2, message type: %d", + buf[2] ) ); + SSL_DEBUG_MSG( 3, ( "client hello v2, message len.: %d", + ( ( buf[0] & 0x7F ) << 8 ) | buf[1] ) ); + SSL_DEBUG_MSG( 3, ( "client hello v2, max. version: [%d:%d]", + buf[3], buf[4] ) ); + + /* + * SSLv2 Client Hello + * + * Record layer: + * 0 . 1 message length + * + * SSL layer: + * 2 . 2 message type + * 3 . 4 protocol version + */ + if( buf[2] != SSL_HS_CLIENT_HELLO || + buf[3] != SSL_MAJOR_VERSION_3 ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + n = ( ( buf[0] << 8 ) | buf[1] ) & 0x7FFF; + + if( n < 17 || n > 512 ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->major_ver = SSL_MAJOR_VERSION_3; + ssl->minor_ver = ( buf[4] <= ssl->max_minor_ver ) + ? buf[4] : ssl->max_minor_ver; + + if( ssl->minor_ver < ssl->min_minor_ver ) + { + SSL_DEBUG_MSG( 1, ( "client only supports ssl smaller than minimum" + " [%d:%d] < [%d:%d]", + ssl->major_ver, ssl->minor_ver, + ssl->min_major_ver, ssl->min_minor_ver ) ); + + ssl_send_alert_message( ssl, SSL_ALERT_LEVEL_FATAL, + SSL_ALERT_MSG_PROTOCOL_VERSION ); + return( POLARSSL_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); + } + + ssl->handshake->max_major_ver = buf[3]; + ssl->handshake->max_minor_ver = buf[4]; + + if( ( ret = ssl_fetch_input( ssl, 2 + n ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_fetch_input", ret ); + return( ret ); + } + + ssl->handshake->update_checksum( ssl, buf + 2, n ); + + buf = ssl->in_msg; + n = ssl->in_left - 5; + + /* + * 0 . 1 ciphersuitelist length + * 2 . 3 session id length + * 4 . 5 challenge length + * 6 . .. ciphersuitelist + * .. . .. session id + * .. . .. challenge + */ + SSL_DEBUG_BUF( 4, "record contents", buf, n ); + + ciph_len = ( buf[0] << 8 ) | buf[1]; + sess_len = ( buf[2] << 8 ) | buf[3]; + chal_len = ( buf[4] << 8 ) | buf[5]; + + SSL_DEBUG_MSG( 3, ( "ciph_len: %d, sess_len: %d, chal_len: %d", + ciph_len, sess_len, chal_len ) ); + + /* + * Make sure each parameter length is valid + */ + if( ciph_len < 3 || ( ciph_len % 3 ) != 0 ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + if( sess_len > 32 ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + if( chal_len < 8 || chal_len > 32 ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + if( n != 6 + ciph_len + sess_len + chal_len ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + SSL_DEBUG_BUF( 3, "client hello, ciphersuitelist", + buf + 6, ciph_len ); + SSL_DEBUG_BUF( 3, "client hello, session id", + buf + 6 + ciph_len, sess_len ); + SSL_DEBUG_BUF( 3, "client hello, challenge", + buf + 6 + ciph_len + sess_len, chal_len ); + + p = buf + 6 + ciph_len; + ssl->session_negotiate->length = sess_len; + memset( ssl->session_negotiate->id, 0, + sizeof( ssl->session_negotiate->id ) ); + memcpy( ssl->session_negotiate->id, p, ssl->session_negotiate->length ); + + p += sess_len; + memset( ssl->handshake->randbytes, 0, 64 ); + memcpy( ssl->handshake->randbytes + 32 - chal_len, p, chal_len ); + + /* + * Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV + */ + for( i = 0, p = buf + 6; i < ciph_len; i += 3, p += 3 ) + { + if( p[0] == 0 && p[1] == 0 && p[2] == SSL_EMPTY_RENEGOTIATION_INFO ) + { + SSL_DEBUG_MSG( 3, ( "received TLS_EMPTY_RENEGOTIATION_INFO " ) ); + if( ssl->renegotiation == SSL_RENEGOTIATION ) + { + SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV during renegotiation" ) ); + + if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) + return( ret ); + + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + ssl->secure_renegotiation = SSL_SECURE_RENEGOTIATION; + break; + } + } + + ciphersuites = ssl->ciphersuite_list[ssl->minor_ver]; + ciphersuite_info = NULL; +#if defined(POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE) + for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 ) + { + for( i = 0; ciphersuites[i] != 0; i++ ) +#else + for( i = 0; ciphersuites[i] != 0; i++ ) + { + for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 ) +#endif + { + if( p[0] != 0 || + p[1] != ( ( ciphersuites[i] >> 8 ) & 0xFF ) || + p[2] != ( ( ciphersuites[i] ) & 0xFF ) ) + continue; + + if( ( ret = ssl_ciphersuite_match( ssl, ciphersuites[i], + &ciphersuite_info ) ) != 0 ) + return( ret ); + + if( ciphersuite_info != NULL ) + goto have_ciphersuite_v2; + } + } + + SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) ); + + return( POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN ); + +have_ciphersuite_v2: + ssl->session_negotiate->ciphersuite = ciphersuites[i]; + ssl->transform_negotiate->ciphersuite_info = ciphersuite_info; + ssl_optimize_checksum( ssl, ssl->transform_negotiate->ciphersuite_info ); + + /* + * SSLv2 Client Hello relevant renegotiation security checks + */ + if( ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION && + ssl->allow_legacy_renegotiation == SSL_LEGACY_BREAK_HANDSHAKE ) + { + SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) ); + + if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) + return( ret ); + + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->in_left = 0; + ssl->state++; + + SSL_DEBUG_MSG( 2, ( "<= parse client hello v2" ) ); + + return( 0 ); +} +#endif /* POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */ + +static int ssl_parse_client_hello( ssl_context *ssl ) +{ + int ret; + unsigned int i, j; + size_t n; + unsigned int ciph_len, sess_len; + unsigned int comp_len; + unsigned int ext_len = 0; + unsigned char *buf, *p, *ext; + int renegotiation_info_seen = 0; + int handshake_failure = 0; + const int *ciphersuites; + const ssl_ciphersuite_t *ciphersuite_info; + + SSL_DEBUG_MSG( 2, ( "=> parse client hello" ) ); + + if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE && + ( ret = ssl_fetch_input( ssl, 5 ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_fetch_input", ret ); + return( ret ); + } + + buf = ssl->in_hdr; + +#if defined(POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) + if( ( buf[0] & 0x80 ) != 0 ) + return ssl_parse_client_hello_v2( ssl ); +#endif + + SSL_DEBUG_BUF( 4, "record header", buf, 5 ); + + SSL_DEBUG_MSG( 3, ( "client hello v3, message type: %d", + buf[0] ) ); + SSL_DEBUG_MSG( 3, ( "client hello v3, message len.: %d", + ( buf[3] << 8 ) | buf[4] ) ); + SSL_DEBUG_MSG( 3, ( "client hello v3, protocol ver: [%d:%d]", + buf[1], buf[2] ) ); + + /* + * SSLv3/TLS Client Hello + * + * Record layer: + * 0 . 0 message type + * 1 . 2 protocol version + * 3 . 4 message length + */ + + /* According to RFC 5246 Appendix E.1, the version here is typically + * "{03,00}, the lowest version number supported by the client, [or] the + * value of ClientHello.client_version", so the only meaningful check here + * is the major version shouldn't be less than 3 */ + if( buf[0] != SSL_MSG_HANDSHAKE || + buf[1] < SSL_MAJOR_VERSION_3 ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + n = ( buf[3] << 8 ) | buf[4]; + + if( n < 45 || n > SSL_MAX_CONTENT_LEN ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE && + ( ret = ssl_fetch_input( ssl, 5 + n ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_fetch_input", ret ); + return( ret ); + } + + buf = ssl->in_msg; + if( !ssl->renegotiation ) + n = ssl->in_left - 5; + else + n = ssl->in_msglen; + + ssl->handshake->update_checksum( ssl, buf, n ); + + /* + * SSL layer: + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 5 protocol version + * 6 . 9 UNIX time() + * 10 . 37 random bytes + * 38 . 38 session id length + * 39 . 38+x session id + * 39+x . 40+x ciphersuitelist length + * 41+x . 40+y ciphersuitelist + * 41+y . 41+y compression alg length + * 42+y . 41+z compression algs + * .. . .. extensions + */ + SSL_DEBUG_BUF( 4, "record contents", buf, n ); + + SSL_DEBUG_MSG( 3, ( "client hello v3, handshake type: %d", + buf[0] ) ); + SSL_DEBUG_MSG( 3, ( "client hello v3, handshake len.: %d", + ( buf[1] << 16 ) | ( buf[2] << 8 ) | buf[3] ) ); + SSL_DEBUG_MSG( 3, ( "client hello v3, max. version: [%d:%d]", + buf[4], buf[5] ) ); + + /* + * Check the handshake type and protocol version + */ + if( buf[0] != SSL_HS_CLIENT_HELLO ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->major_ver = buf[4]; + ssl->minor_ver = buf[5]; + + ssl->handshake->max_major_ver = ssl->major_ver; + ssl->handshake->max_minor_ver = ssl->minor_ver; + + if( ssl->major_ver < ssl->min_major_ver || + ssl->minor_ver < ssl->min_minor_ver ) + { + SSL_DEBUG_MSG( 1, ( "client only supports ssl smaller than minimum" + " [%d:%d] < [%d:%d]", + ssl->major_ver, ssl->minor_ver, + ssl->min_major_ver, ssl->min_minor_ver ) ); + + ssl_send_alert_message( ssl, SSL_ALERT_LEVEL_FATAL, + SSL_ALERT_MSG_PROTOCOL_VERSION ); + + return( POLARSSL_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); + } + + if( ssl->major_ver > ssl->max_major_ver ) + { + ssl->major_ver = ssl->max_major_ver; + ssl->minor_ver = ssl->max_minor_ver; + } + else if( ssl->minor_ver > ssl->max_minor_ver ) + ssl->minor_ver = ssl->max_minor_ver; + + memcpy( ssl->handshake->randbytes, buf + 6, 32 ); + + /* + * Check the handshake message length + */ + if( buf[1] != 0 || n != (unsigned int) 4 + ( ( buf[2] << 8 ) | buf[3] ) ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* + * Check the session length + */ + sess_len = buf[38]; + + if( sess_len > 32 || sess_len > n - 42 ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->session_negotiate->length = sess_len; + memset( ssl->session_negotiate->id, 0, + sizeof( ssl->session_negotiate->id ) ); + memcpy( ssl->session_negotiate->id, buf + 39, + ssl->session_negotiate->length ); + + /* + * Check the ciphersuitelist length + */ + ciph_len = ( buf[39 + sess_len] << 8 ) + | ( buf[40 + sess_len] ); + + if( ciph_len < 2 || ( ciph_len % 2 ) != 0 || ciph_len > n - 42 - sess_len ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* + * Check the compression algorithms length + */ + comp_len = buf[41 + sess_len + ciph_len]; + + if( comp_len < 1 || comp_len > 16 || + comp_len > n - 42 - sess_len - ciph_len ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* + * Check the extension length + */ + if( n > 42 + sess_len + ciph_len + comp_len ) + { + ext_len = ( buf[42 + sess_len + ciph_len + comp_len] << 8 ) + | ( buf[43 + sess_len + ciph_len + comp_len] ); + + if( ( ext_len > 0 && ext_len < 4 ) || + n != 44 + sess_len + ciph_len + comp_len + ext_len ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + SSL_DEBUG_BUF( 3, "Ext", buf + 44 + sess_len + ciph_len + comp_len, ext_len); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + } + + ssl->session_negotiate->compression = SSL_COMPRESS_NULL; +#if defined(POLARSSL_ZLIB_SUPPORT) + for( i = 0; i < comp_len; ++i ) + { + if( buf[42 + sess_len + ciph_len + i] == SSL_COMPRESS_DEFLATE ) + { + ssl->session_negotiate->compression = SSL_COMPRESS_DEFLATE; + break; + } + } +#endif + + SSL_DEBUG_BUF( 3, "client hello, random bytes", + buf + 6, 32 ); + SSL_DEBUG_BUF( 3, "client hello, session id", + buf + 38, sess_len ); + SSL_DEBUG_BUF( 3, "client hello, ciphersuitelist", + buf + 41 + sess_len, ciph_len ); + SSL_DEBUG_BUF( 3, "client hello, compression", + buf + 42 + sess_len + ciph_len, comp_len ); + + /* + * Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV + */ + for( i = 0, p = buf + 41 + sess_len; i < ciph_len; i += 2, p += 2 ) + { + if( p[0] == 0 && p[1] == SSL_EMPTY_RENEGOTIATION_INFO ) + { + SSL_DEBUG_MSG( 3, ( "received TLS_EMPTY_RENEGOTIATION_INFO " ) ); + if( ssl->renegotiation == SSL_RENEGOTIATION ) + { + SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV during renegotiation" ) ); + + if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) + return( ret ); + + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + ssl->secure_renegotiation = SSL_SECURE_RENEGOTIATION; + break; + } + } + + ext = buf + 44 + sess_len + ciph_len + comp_len; + + while( ext_len ) + { + unsigned int ext_id = ( ( ext[0] << 8 ) + | ( ext[1] ) ); + unsigned int ext_size = ( ( ext[2] << 8 ) + | ( ext[3] ) ); + + if( ext_size + 4 > ext_len ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + switch( ext_id ) + { +#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION) + case TLS_EXT_SERVERNAME: + SSL_DEBUG_MSG( 3, ( "found ServerName extension" ) ); + if( ssl->f_sni == NULL ) + break; + + ret = ssl_parse_servername_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* POLARSSL_SSL_SERVER_NAME_INDICATION */ + + case TLS_EXT_RENEGOTIATION_INFO: + SSL_DEBUG_MSG( 3, ( "found renegotiation extension" ) ); + renegotiation_info_seen = 1; + + ret = ssl_parse_renegotiation_info( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; + +#if defined(POLARSSL_SSL_PROTO_TLS1_2) + case TLS_EXT_SIG_ALG: + SSL_DEBUG_MSG( 3, ( "found signature_algorithms extension" ) ); + if( ssl->renegotiation == SSL_RENEGOTIATION ) + break; + + ret = ssl_parse_signature_algorithms_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ + +#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C) + case TLS_EXT_SUPPORTED_ELLIPTIC_CURVES: + SSL_DEBUG_MSG( 3, ( "found supported elliptic curves extension" ) ); + + ret = ssl_parse_supported_elliptic_curves( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; + + case TLS_EXT_SUPPORTED_POINT_FORMATS: + SSL_DEBUG_MSG( 3, ( "found supported point formats extension" ) ); + ssl->handshake->cli_exts |= TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT; + + ret = ssl_parse_supported_point_formats( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* POLARSSL_ECDH_C || POLARSSL_ECDSA_C */ + +#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH) + case TLS_EXT_MAX_FRAGMENT_LENGTH: + SSL_DEBUG_MSG( 3, ( "found max fragment length extension" ) ); + + ret = ssl_parse_max_fragment_length_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(POLARSSL_SSL_TRUNCATED_HMAC) + case TLS_EXT_TRUNCATED_HMAC: + SSL_DEBUG_MSG( 3, ( "found truncated hmac extension" ) ); + + ret = ssl_parse_truncated_hmac_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* POLARSSL_SSL_TRUNCATED_HMAC */ + +#if defined(POLARSSL_SSL_SESSION_TICKETS) + case TLS_EXT_SESSION_TICKET: + SSL_DEBUG_MSG( 3, ( "found session ticket extension" ) ); + + ret = ssl_parse_session_ticket_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* POLARSSL_SSL_SESSION_TICKETS */ + +#if defined(POLARSSL_SSL_ALPN) + case TLS_EXT_ALPN: + SSL_DEBUG_MSG( 3, ( "found alpn extension" ) ); + + ret = ssl_parse_alpn_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* POLARSSL_SSL_SESSION_TICKETS */ + + default: + SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)", + ext_id ) ); + } + + ext_len -= 4 + ext_size; + ext += 4 + ext_size; + + if( ext_len > 0 && ext_len < 4 ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + } + + /* + * Renegotiation security checks + */ + if( ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION && + ssl->allow_legacy_renegotiation == SSL_LEGACY_BREAK_HANDSHAKE ) + { + SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) ); + handshake_failure = 1; + } + else if( ssl->renegotiation == SSL_RENEGOTIATION && + ssl->secure_renegotiation == SSL_SECURE_RENEGOTIATION && + renegotiation_info_seen == 0 ) + { + SSL_DEBUG_MSG( 1, ( "renegotiation_info extension missing (secure)" ) ); + handshake_failure = 1; + } + else if( ssl->renegotiation == SSL_RENEGOTIATION && + ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION && + ssl->allow_legacy_renegotiation == SSL_LEGACY_NO_RENEGOTIATION ) + { + SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) ); + handshake_failure = 1; + } + else if( ssl->renegotiation == SSL_RENEGOTIATION && + ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION && + renegotiation_info_seen == 1 ) + { + SSL_DEBUG_MSG( 1, ( "renegotiation_info extension present (legacy)" ) ); + handshake_failure = 1; + } + + if( handshake_failure == 1 ) + { + if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) + return( ret ); + + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* + * Search for a matching ciphersuite + * (At the end because we need information from the EC-based extensions + * and certificate from the SNI callback triggered by the SNI extension.) + */ + ciphersuites = ssl->ciphersuite_list[ssl->minor_ver]; + ciphersuite_info = NULL; +#if defined(POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE) + for( j = 0, p = buf + 41 + sess_len; j < ciph_len; j += 2, p += 2 ) + { + for( i = 0; ciphersuites[i] != 0; i++ ) +#else + for( i = 0; ciphersuites[i] != 0; i++ ) + { + for( j = 0, p = buf + 41 + sess_len; j < ciph_len; j += 2, p += 2 ) +#endif + { + if( p[0] != ( ( ciphersuites[i] >> 8 ) & 0xFF ) || + p[1] != ( ( ciphersuites[i] ) & 0xFF ) ) + continue; + + if( ( ret = ssl_ciphersuite_match( ssl, ciphersuites[i], + &ciphersuite_info ) ) != 0 ) + return( ret ); + + if( ciphersuite_info != NULL ) + goto have_ciphersuite; + } + } + + SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) ); + + if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) + return( ret ); + + return( POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN ); + +have_ciphersuite: + ssl->session_negotiate->ciphersuite = ciphersuites[i]; + ssl->transform_negotiate->ciphersuite_info = ciphersuite_info; + ssl_optimize_checksum( ssl, ssl->transform_negotiate->ciphersuite_info ); + + ssl->in_left = 0; + ssl->state++; + + SSL_DEBUG_MSG( 2, ( "<= parse client hello" ) ); + + return( 0 ); +} + +#if defined(POLARSSL_SSL_TRUNCATED_HMAC) +static void ssl_write_truncated_hmac_ext( ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->session_negotiate->trunc_hmac == SSL_TRUNC_HMAC_DISABLED ) + { + *olen = 0; + return; + } + + SSL_DEBUG_MSG( 3, ( "server hello, adding truncated hmac extension" ) ); + + *p++ = (unsigned char)( ( TLS_EXT_TRUNCATED_HMAC >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( TLS_EXT_TRUNCATED_HMAC ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* POLARSSL_SSL_TRUNCATED_HMAC */ + +#if defined(POLARSSL_SSL_SESSION_TICKETS) +static void ssl_write_session_ticket_ext( ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->handshake->new_session_ticket == 0 ) + { + *olen = 0; + return; + } + + SSL_DEBUG_MSG( 3, ( "server hello, adding session ticket extension" ) ); + + *p++ = (unsigned char)( ( TLS_EXT_SESSION_TICKET >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( TLS_EXT_SESSION_TICKET ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* POLARSSL_SSL_SESSION_TICKETS */ + +static void ssl_write_renegotiation_ext( ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->secure_renegotiation != SSL_SECURE_RENEGOTIATION ) + { + *olen = 0; + return; + } + + SSL_DEBUG_MSG( 3, ( "server hello, secure renegotiation extension" ) ); + + *p++ = (unsigned char)( ( TLS_EXT_RENEGOTIATION_INFO >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( TLS_EXT_RENEGOTIATION_INFO ) & 0xFF ); + + *p++ = 0x00; + *p++ = ( ssl->verify_data_len * 2 + 1 ) & 0xFF; + *p++ = ssl->verify_data_len * 2 & 0xFF; + + memcpy( p, ssl->peer_verify_data, ssl->verify_data_len ); + p += ssl->verify_data_len; + memcpy( p, ssl->own_verify_data, ssl->verify_data_len ); + p += ssl->verify_data_len; + + *olen = 5 + ssl->verify_data_len * 2; +} + +#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH) +static void ssl_write_max_fragment_length_ext( ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->session_negotiate->mfl_code == SSL_MAX_FRAG_LEN_NONE ) + { + *olen = 0; + return; + } + + SSL_DEBUG_MSG( 3, ( "server hello, max_fragment_length extension" ) ); + + *p++ = (unsigned char)( ( TLS_EXT_MAX_FRAGMENT_LENGTH >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( TLS_EXT_MAX_FRAGMENT_LENGTH ) & 0xFF ); + + *p++ = 0x00; + *p++ = 1; + + *p++ = ssl->session_negotiate->mfl_code; + + *olen = 5; +} +#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C) +static void ssl_write_supported_point_formats_ext( ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + ((void) ssl); + + if( ( ssl->handshake->cli_exts & + TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT ) == 0 ) + { + *olen = 0; + return; + } + + SSL_DEBUG_MSG( 3, ( "server hello, supported_point_formats extension" ) ); + + *p++ = (unsigned char)( ( TLS_EXT_SUPPORTED_POINT_FORMATS >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( TLS_EXT_SUPPORTED_POINT_FORMATS ) & 0xFF ); + + *p++ = 0x00; + *p++ = 2; + + *p++ = 1; + *p++ = POLARSSL_ECP_PF_UNCOMPRESSED; + + *olen = 6; +} +#endif /* POLARSSL_ECDH_C || POLARSSL_ECDSA_C */ + +#if defined(POLARSSL_SSL_ALPN ) +static void ssl_write_alpn_ext( ssl_context *ssl, + unsigned char *buf, size_t *olen ) +{ + if( ssl->alpn_chosen == NULL ) + { + *olen = 0; + return; + } + + SSL_DEBUG_MSG( 3, ( "server hello, adding alpn extension" ) ); + + /* + * 0 . 1 ext identifier + * 2 . 3 ext length + * 4 . 5 protocol list length + * 6 . 6 protocol name length + * 7 . 7+n protocol name + */ + buf[0] = (unsigned char)( ( TLS_EXT_ALPN >> 8 ) & 0xFF ); + buf[1] = (unsigned char)( ( TLS_EXT_ALPN ) & 0xFF ); + + *olen = 7 + strlen( ssl->alpn_chosen ); + + buf[2] = (unsigned char)( ( ( *olen - 4 ) >> 8 ) & 0xFF ); + buf[3] = (unsigned char)( ( ( *olen - 4 ) ) & 0xFF ); + + buf[4] = (unsigned char)( ( ( *olen - 6 ) >> 8 ) & 0xFF ); + buf[5] = (unsigned char)( ( ( *olen - 6 ) ) & 0xFF ); + + buf[6] = (unsigned char)( ( ( *olen - 7 ) ) & 0xFF ); + + memcpy( buf + 7, ssl->alpn_chosen, *olen - 7 ); +} +#endif /* POLARSSL_ECDH_C || POLARSSL_ECDSA_C */ + +static int ssl_write_server_hello( ssl_context *ssl ) +{ +#if defined(POLARSSL_HAVE_TIME) + time_t t; +#endif + int ret; + size_t olen, ext_len = 0, n; + unsigned char *buf, *p; + + SSL_DEBUG_MSG( 2, ( "=> write server hello" ) ); + + if( ssl->f_rng == NULL ) + { + SSL_DEBUG_MSG( 1, ( "no RNG provided") ); + return( POLARSSL_ERR_SSL_NO_RNG ); + } + + /* + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 5 protocol version + * 6 . 9 UNIX time() + * 10 . 37 random bytes + */ + buf = ssl->out_msg; + p = buf + 4; + + *p++ = (unsigned char) ssl->major_ver; + *p++ = (unsigned char) ssl->minor_ver; + + SSL_DEBUG_MSG( 3, ( "server hello, chosen version: [%d:%d]", + buf[4], buf[5] ) ); + +#if defined(POLARSSL_HAVE_TIME) + t = time( NULL ); + *p++ = (unsigned char)( t >> 24 ); + *p++ = (unsigned char)( t >> 16 ); + *p++ = (unsigned char)( t >> 8 ); + *p++ = (unsigned char)( t ); + + SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", t ) ); +#else + if( ( ret = ssl->f_rng( ssl->p_rng, p, 4 ) ) != 0 ) + return( ret ); + + p += 4; +#endif /* POLARSSL_HAVE_TIME */ + + if( ( ret = ssl->f_rng( ssl->p_rng, p, 28 ) ) != 0 ) + return( ret ); + + p += 28; + + memcpy( ssl->handshake->randbytes + 32, buf + 6, 32 ); + + SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 6, 32 ); + + /* + * Resume is 0 by default, see ssl_handshake_init(). + * It may be already set to 1 by ssl_parse_session_ticket_ext(). + * If not, try looking up session ID in our cache. + */ + if( ssl->handshake->resume == 0 && + ssl->renegotiation == SSL_INITIAL_HANDSHAKE && + ssl->session_negotiate->length != 0 && + ssl->f_get_cache != NULL && + ssl->f_get_cache( ssl->p_get_cache, ssl->session_negotiate ) == 0 ) + { + SSL_DEBUG_MSG( 3, ( "session successfully restored from cache" ) ); + ssl->handshake->resume = 1; + } + + if( ssl->handshake->resume == 0 ) + { + /* + * New session, create a new session id, + * unless we're about to issue a session ticket + */ + ssl->state++; + +#if defined(POLARSSL_HAVE_TIME) + ssl->session_negotiate->start = time( NULL ); +#endif + +#if defined(POLARSSL_SSL_SESSION_TICKETS) + if( ssl->handshake->new_session_ticket != 0 ) + { + ssl->session_negotiate->length = n = 0; + memset( ssl->session_negotiate->id, 0, 32 ); + } + else +#endif /* POLARSSL_SSL_SESSION_TICKETS */ + { + ssl->session_negotiate->length = n = 32; + if( ( ret = ssl->f_rng( ssl->p_rng, ssl->session_negotiate->id, + n ) ) != 0 ) + return( ret ); + } + } + else + { + /* + * Resuming a session + */ + n = ssl->session_negotiate->length; + ssl->state = SSL_SERVER_CHANGE_CIPHER_SPEC; + + if( ( ret = ssl_derive_keys( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_derive_keys", ret ); + return( ret ); + } + } + + /* + * 38 . 38 session id length + * 39 . 38+n session id + * 39+n . 40+n chosen ciphersuite + * 41+n . 41+n chosen compression alg. + * 42+n . 43+n extensions length + * 44+n . 43+n+m extensions + */ + *p++ = (unsigned char) ssl->session_negotiate->length; + memcpy( p, ssl->session_negotiate->id, ssl->session_negotiate->length ); + p += ssl->session_negotiate->length; + + SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) ); + SSL_DEBUG_BUF( 3, "server hello, session id", buf + 39, n ); + SSL_DEBUG_MSG( 3, ( "%s session has been resumed", + ssl->handshake->resume ? "a" : "no" ) ); + + *p++ = (unsigned char)( ssl->session_negotiate->ciphersuite >> 8 ); + *p++ = (unsigned char)( ssl->session_negotiate->ciphersuite ); + *p++ = (unsigned char)( ssl->session_negotiate->compression ); + + SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s", + ssl_get_ciphersuite_name( ssl->session_negotiate->ciphersuite ) ) ); + SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: 0x%02X", + ssl->session_negotiate->compression ) ); + + /* + * First write extensions, then the total length + */ + ssl_write_renegotiation_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; + +#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH) + ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(POLARSSL_SSL_TRUNCATED_HMAC) + ssl_write_truncated_hmac_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(POLARSSL_SSL_SESSION_TICKETS) + ssl_write_session_ticket_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C) + ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(POLARSSL_SSL_ALPN) + ssl_write_alpn_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + + SSL_DEBUG_MSG( 3, ( "server hello, total extension length: %d", ext_len ) ); + + if( ext_len > 0 ) + { + *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ext_len ) & 0xFF ); + p += ext_len; + } + + ssl->out_msglen = p - buf; + ssl->out_msgtype = SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = SSL_HS_SERVER_HELLO; + + ret = ssl_write_record( ssl ); + + SSL_DEBUG_MSG( 2, ( "<= write server hello" ) ); + + return( ret ); +} + +#if !defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) && \ + !defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ + !defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ + !defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +static int ssl_write_certificate_request( ssl_context *ssl ) +{ + const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) ); + + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) + { + SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) ); + ssl->state++; + return( 0 ); + } + + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); +} +#else +static int ssl_write_certificate_request( ssl_context *ssl ) +{ + int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE; + const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + size_t dn_size, total_dn_size; /* excluding length bytes */ + size_t ct_len, sa_len; /* including length bytes */ + unsigned char *buf, *p; + const x509_crt *crt; + + SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) ); + + ssl->state++; + + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK || + ssl->authmode == SSL_VERIFY_NONE ) + { + SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) ); + return( 0 ); + } + + /* + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 4 cert type count + * 5 .. m-1 cert types + * m .. m+1 sig alg length (TLS 1.2 only) + * m+1 .. n-1 SignatureAndHashAlgorithms (TLS 1.2 only) + * n .. n+1 length of all DNs + * n+2 .. n+3 length of DN 1 + * n+4 .. ... Distinguished Name #1 + * ... .. ... length of DN 2, etc. + */ + buf = ssl->out_msg; + p = buf + 4; + + /* + * Supported certificate types + * + * ClientCertificateType certificate_types<1..2^8-1>; + * enum { (255) } ClientCertificateType; + */ + ct_len = 0; + +#if defined(POLARSSL_RSA_C) + p[1 + ct_len++] = SSL_CERT_TYPE_RSA_SIGN; +#endif +#if defined(POLARSSL_ECDSA_C) + p[1 + ct_len++] = SSL_CERT_TYPE_ECDSA_SIGN; +#endif + + p[0] = (unsigned char) ct_len++; + p += ct_len; + + sa_len = 0; +#if defined(POLARSSL_SSL_PROTO_TLS1_2) + /* + * Add signature_algorithms for verify (TLS 1.2) + * + * SignatureAndHashAlgorithm supported_signature_algorithms<2..2^16-2>; + * + * struct { + * HashAlgorithm hash; + * SignatureAlgorithm signature; + * } SignatureAndHashAlgorithm; + * + * enum { (255) } HashAlgorithm; + * enum { (255) } SignatureAlgorithm; + */ + if( ssl->minor_ver == SSL_MINOR_VERSION_3 ) + { + /* + * Only use current running hash algorithm that is already required + * for requested ciphersuite. + */ + ssl->handshake->verify_sig_alg = SSL_HASH_SHA256; + + if( ssl->transform_negotiate->ciphersuite_info->mac == + POLARSSL_MD_SHA384 ) + { + ssl->handshake->verify_sig_alg = SSL_HASH_SHA384; + } + + /* + * Supported signature algorithms + */ +#if defined(POLARSSL_RSA_C) + p[2 + sa_len++] = ssl->handshake->verify_sig_alg; + p[2 + sa_len++] = SSL_SIG_RSA; +#endif +#if defined(POLARSSL_ECDSA_C) + p[2 + sa_len++] = ssl->handshake->verify_sig_alg; + p[2 + sa_len++] = SSL_SIG_ECDSA; +#endif + + p[0] = (unsigned char)( sa_len >> 8 ); + p[1] = (unsigned char)( sa_len ); + sa_len += 2; + p += sa_len; + } +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ + + /* + * DistinguishedName certificate_authorities<0..2^16-1>; + * opaque DistinguishedName<1..2^16-1>; + */ + p += 2; + crt = ssl->ca_chain; + + total_dn_size = 0; + while( crt != NULL && crt->version != 0 ) + { + if( p - buf > 4096 ) + break; + + dn_size = crt->subject_raw.len; + *p++ = (unsigned char)( dn_size >> 8 ); + *p++ = (unsigned char)( dn_size ); + memcpy( p, crt->subject_raw.p, dn_size ); + p += dn_size; + + SSL_DEBUG_BUF( 3, "requested DN", p, dn_size ); + + total_dn_size += 2 + dn_size; + crt = crt->next; + } + + ssl->out_msglen = p - buf; + ssl->out_msgtype = SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = SSL_HS_CERTIFICATE_REQUEST; + ssl->out_msg[4 + ct_len + sa_len] = (unsigned char)( total_dn_size >> 8 ); + ssl->out_msg[5 + ct_len + sa_len] = (unsigned char)( total_dn_size ); + + ret = ssl_write_record( ssl ); + + SSL_DEBUG_MSG( 2, ( "<= write certificate request" ) ); + + return( ret ); +} +#endif /* !POLARSSL_KEY_EXCHANGE_RSA_ENABLED && + !POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED && + !POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED && + !POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +static int ssl_get_ecdh_params_from_cert( ssl_context *ssl ) +{ + int ret; + + if( ! pk_can_do( ssl_own_key( ssl ), POLARSSL_PK_ECKEY ) ) + { + SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) ); + return( POLARSSL_ERR_SSL_PK_TYPE_MISMATCH ); + } + + if( ( ret = ecdh_get_params( &ssl->handshake->ecdh_ctx, + pk_ec( *ssl_own_key( ssl ) ), + POLARSSL_ECDH_OURS ) ) != 0 ) + { + SSL_DEBUG_RET( 1, ( "ecdh_get_params" ), ret ); + return( ret ); + } + + return( 0 ); +} +#endif /* POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) || + POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +static int ssl_write_server_key_exchange( ssl_context *ssl ) +{ + int ret; + size_t n = 0; + const ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; + +#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + unsigned char *p = ssl->out_msg + 4; + unsigned char *dig_signed = p; + size_t dig_signed_len = 0, len; + ((void) dig_signed); + ((void) dig_signed_len); +#endif + + SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) ); + +#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK ) + { + SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) ); + ssl->state++; + return( 0 ); + } +#endif + +#if defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDH_RSA || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDH_ECDSA ) + { + ssl_get_ecdh_params_from_cert( ssl ); + + SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) ); + ssl->state++; + return( 0 ); + } +#endif + +#if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) + { + /* TODO: Support identity hints */ + *(p++) = 0x00; + *(p++) = 0x00; + + n += 2; + } +#endif /* POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_RSA || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK ) + { + /* + * Ephemeral DH parameters: + * + * struct { + * opaque dh_p<1..2^16-1>; + * opaque dh_g<1..2^16-1>; + * opaque dh_Ys<1..2^16-1>; + * } ServerDHParams; + */ + if( ( ret = mpi_copy( &ssl->handshake->dhm_ctx.P, &ssl->dhm_P ) ) != 0 || + ( ret = mpi_copy( &ssl->handshake->dhm_ctx.G, &ssl->dhm_G ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "mpi_copy", ret ); + return( ret ); + } + + if( ( ret = dhm_make_params( &ssl->handshake->dhm_ctx, + (int) mpi_size( &ssl->handshake->dhm_ctx.P ), + p, &len, ssl->f_rng, ssl->p_rng ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "dhm_make_params", ret ); + return( ret ); + } + + dig_signed = p; + dig_signed_len = len; + + p += len; + n += len; + + SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X ); + SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P ); + SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->handshake->dhm_ctx.G ); + SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX ); + } +#endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED || + POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE__SOME__ECDHE_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) + { + /* + * Ephemeral ECDH parameters: + * + * struct { + * ECParameters curve_params; + * ECPoint public; + * } ServerECDHParams; + */ + const ecp_curve_info **curve = NULL; +#if defined(POLARSSL_SSL_SET_CURVES) + const ecp_group_id *gid; + + /* Match our preference list against the offered curves */ + for( gid = ssl->curve_list; *gid != POLARSSL_ECP_DP_NONE; gid++ ) + for( curve = ssl->handshake->curves; *curve != NULL; curve++ ) + if( (*curve)->grp_id == *gid ) + goto curve_matching_done; + +curve_matching_done: +#else + curve = ssl->handshake->curves; +#endif + + if( *curve == NULL ) + { + SSL_DEBUG_MSG( 1, ( "no matching curve for ECDHE" ) ); + return( POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN ); + } + + SSL_DEBUG_MSG( 2, ( "ECDHE curve: %s", (*curve)->name ) ); + + if( ( ret = ecp_use_known_dp( &ssl->handshake->ecdh_ctx.grp, + (*curve)->grp_id ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ecp_use_known_dp", ret ); + return( ret ); + } + + if( ( ret = ecdh_make_params( &ssl->handshake->ecdh_ctx, &len, + p, SSL_MAX_CONTENT_LEN - n, + ssl->f_rng, ssl->p_rng ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ecdh_make_params", ret ); + return( ret ); + } + + dig_signed = p; + dig_signed_len = len; + + p += len; + n += len; + + SSL_DEBUG_ECP( 3, "ECDH: Q ", &ssl->handshake->ecdh_ctx.Q ); + } +#endif /* POLARSSL_KEY_EXCHANGE__SOME__ECDHE_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_RSA || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA ) + { + size_t signature_len = 0; + unsigned int hashlen = 0; + unsigned char hash[64]; + md_type_t md_alg = POLARSSL_MD_NONE; + + /* + * Choose hash algorithm. NONE means MD5 + SHA1 here. + */ +#if defined(POLARSSL_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == SSL_MINOR_VERSION_3 ) + { + md_alg = ssl_md_alg_from_hash( ssl->handshake->sig_alg ); + + if( md_alg == POLARSSL_MD_NONE ) + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + } + else +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ +#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_1) + if( ciphersuite_info->key_exchange == + POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA ) + { + md_alg = POLARSSL_MD_SHA1; + } + else +#endif + { + md_alg = POLARSSL_MD_NONE; + } + + /* + * Compute the hash to be signed + */ +#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_1) + if( md_alg == POLARSSL_MD_NONE ) + { + md5_context md5; + sha1_context sha1; + + md5_init( &md5 ); + sha1_init( &sha1 ); + + /* + * digitally-signed struct { + * opaque md5_hash[16]; + * opaque sha_hash[20]; + * }; + * + * md5_hash + * MD5(ClientHello.random + ServerHello.random + * + ServerParams); + * sha_hash + * SHA(ClientHello.random + ServerHello.random + * + ServerParams); + */ + md5_starts( &md5 ); + md5_update( &md5, ssl->handshake->randbytes, 64 ); + md5_update( &md5, dig_signed, dig_signed_len ); + md5_finish( &md5, hash ); + + sha1_starts( &sha1 ); + sha1_update( &sha1, ssl->handshake->randbytes, 64 ); + sha1_update( &sha1, dig_signed, dig_signed_len ); + sha1_finish( &sha1, hash + 16 ); + + hashlen = 36; + + md5_free( &md5 ); + sha1_free( &sha1 ); + } + else +#endif /* POLARSSL_SSL_PROTO_SSL3 || POLARSSL_SSL_PROTO_TLS1 || \ + POLARSSL_SSL_PROTO_TLS1_1 */ +#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_2) + if( md_alg != POLARSSL_MD_NONE ) + { + md_context_t ctx; + const md_info_t *md_info = md_info_from_type( md_alg ); + + md_init( &ctx ); + + /* Info from md_alg will be used instead */ + hashlen = 0; + + /* + * digitally-signed struct { + * opaque client_random[32]; + * opaque server_random[32]; + * ServerDHParams params; + * }; + */ + if( ( ret = md_init_ctx( &ctx, md_info ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "md_init_ctx", ret ); + return( ret ); + } + + md_starts( &ctx ); + md_update( &ctx, ssl->handshake->randbytes, 64 ); + md_update( &ctx, dig_signed, dig_signed_len ); + md_finish( &ctx, hash ); + md_free( &ctx ); + } + else +#endif /* POLARSSL_SSL_PROTO_TLS1 || POLARSSL_SSL_PROTO_TLS1_1 || \ + POLARSSL_SSL_PROTO_TLS1_2 */ + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + + SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen != 0 ? hashlen : + (unsigned int) ( md_info_from_type( md_alg ) )->size ); + + /* + * Make the signature + */ + if( ssl_own_key( ssl ) == NULL ) + { + SSL_DEBUG_MSG( 1, ( "got no private key" ) ); + return( POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + +#if defined(POLARSSL_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == SSL_MINOR_VERSION_3 ) + { + *(p++) = ssl->handshake->sig_alg; + *(p++) = ssl_sig_from_pk( ssl_own_key( ssl ) ); + + n += 2; + } +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ + + if( ( ret = pk_sign( ssl_own_key( ssl ), md_alg, hash, hashlen, + p + 2 , &signature_len, + ssl->f_rng, ssl->p_rng ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "pk_sign", ret ); + return( ret ); + } + + *(p++) = (unsigned char)( signature_len >> 8 ); + *(p++) = (unsigned char)( signature_len ); + n += 2; + + SSL_DEBUG_BUF( 3, "my signature", p, signature_len ); + + p += signature_len; + n += signature_len; + } +#endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) || + POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + + ssl->out_msglen = 4 + n; + ssl->out_msgtype = SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = SSL_HS_SERVER_KEY_EXCHANGE; + + ssl->state++; + + if( ( ret = ssl_write_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_write_record", ret ); + return( ret ); + } + + SSL_DEBUG_MSG( 2, ( "<= write server key exchange" ) ); + + return( 0 ); +} + +static int ssl_write_server_hello_done( ssl_context *ssl ) +{ + int ret; + + SSL_DEBUG_MSG( 2, ( "=> write server hello done" ) ); + + ssl->out_msglen = 4; + ssl->out_msgtype = SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = SSL_HS_SERVER_HELLO_DONE; + + ssl->state++; + + if( ( ret = ssl_write_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_write_record", ret ); + return( ret ); + } + + SSL_DEBUG_MSG( 2, ( "<= write server hello done" ) ); + + return( 0 ); +} + +#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) +static int ssl_parse_client_dh_public( ssl_context *ssl, unsigned char **p, + const unsigned char *end ) +{ + int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE; + size_t n; + + /* + * Receive G^Y mod P, premaster = (G^Y)^X mod P + */ + if( *p + 2 > end ) + { + SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + n = ( (*p)[0] << 8 ) | (*p)[1]; + *p += 2; + + if( *p + n > end ) + { + SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ( ret = dhm_read_public( &ssl->handshake->dhm_ctx, *p, n ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "dhm_read_public", ret ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); + } + + *p += n; + + SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->handshake->dhm_ctx.GY ); + + return( ret ); +} +#endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED || + POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) +static int ssl_parse_encrypted_pms( ssl_context *ssl, + const unsigned char *p, + const unsigned char *end, + size_t pms_offset ) +{ + int ret; + size_t len = pk_get_len( ssl_own_key( ssl ) ); + unsigned char *pms = ssl->handshake->premaster + pms_offset; + + if( ! pk_can_do( ssl_own_key( ssl ), POLARSSL_PK_RSA ) ) + { + SSL_DEBUG_MSG( 1, ( "got no RSA private key" ) ); + return( POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + /* + * Decrypt the premaster using own private RSA key + */ +#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_2) + if( ssl->minor_ver != SSL_MINOR_VERSION_0 ) + { + if( *p++ != ( ( len >> 8 ) & 0xFF ) || + *p++ != ( ( len ) & 0xFF ) ) + { + SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + } +#endif + + if( p + len != end ) + { + SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + ret = pk_decrypt( ssl_own_key( ssl ), p, len, + pms, &ssl->handshake->pmslen, + sizeof( ssl->handshake->premaster ) - pms_offset, + ssl->f_rng, ssl->p_rng ); + + if( ret != 0 || ssl->handshake->pmslen != 48 || + pms[0] != ssl->handshake->max_major_ver || + pms[1] != ssl->handshake->max_minor_ver ) + { + SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + + /* + * Protection against Bleichenbacher's attack: + * invalid PKCS#1 v1.5 padding must not cause + * the connection to end immediately; instead, + * send a bad_record_mac later in the handshake. + */ + ssl->handshake->pmslen = 48; + + ret = ssl->f_rng( ssl->p_rng, pms, ssl->handshake->pmslen ); + if( ret != 0 ) + return( ret ); + } + + return( ret ); +} +#endif /* POLARSSL_KEY_EXCHANGE_RSA_ENABLED || + POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED */ + +#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED) +static int ssl_parse_client_psk_identity( ssl_context *ssl, unsigned char **p, + const unsigned char *end ) +{ + int ret = 0; + size_t n; + + if( ssl->f_psk == NULL && + ( ssl->psk == NULL || ssl->psk_identity == NULL || + ssl->psk_identity_len == 0 || ssl->psk_len == 0 ) ) + { + SSL_DEBUG_MSG( 1, ( "got no pre-shared key" ) ); + return( POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + /* + * Receive client pre-shared key identity name + */ + if( *p + 2 > end ) + { + SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + n = ( (*p)[0] << 8 ) | (*p)[1]; + *p += 2; + + if( n < 1 || n > 65535 || *p + n > end ) + { + SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ssl->f_psk != NULL ) + { + if( ssl->f_psk( ssl->p_psk, ssl, *p, n ) != 0 ) + ret = POLARSSL_ERR_SSL_UNKNOWN_IDENTITY; + } + else + { + /* Identity is not a big secret since clients send it in the clear, + * but treat it carefully anyway, just in case */ + if( n != ssl->psk_identity_len || + safer_memcmp( ssl->psk_identity, *p, n ) != 0 ) + { + ret = POLARSSL_ERR_SSL_UNKNOWN_IDENTITY; + } + } + + if( ret == POLARSSL_ERR_SSL_UNKNOWN_IDENTITY ) + { + SSL_DEBUG_BUF( 3, "Unknown PSK identity", *p, n ); + if( ( ret = ssl_send_alert_message( ssl, + SSL_ALERT_LEVEL_FATAL, + SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY ) ) != 0 ) + { + return( ret ); + } + + return( POLARSSL_ERR_SSL_UNKNOWN_IDENTITY ); + } + + *p += n; + + return( 0 ); +} +#endif /* POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +static int ssl_parse_client_key_exchange( ssl_context *ssl ) +{ + int ret; + const ssl_ciphersuite_t *ciphersuite_info; + + ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + SSL_DEBUG_MSG( 2, ( "=> parse client key exchange" ) ); + + if( ( ret = ssl_read_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != SSL_MSG_HANDSHAKE ) + { + SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ssl->in_msg[0] != SSL_HS_CLIENT_KEY_EXCHANGE ) + { + SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + +#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_RSA ) + { + unsigned char *p = ssl->in_msg + 4; + unsigned char *end = ssl->in_msg + ssl->in_hslen; + + if( ( ret = ssl_parse_client_dh_public( ssl, &p, end ) ) != 0 ) + { + SSL_DEBUG_RET( 1, ( "ssl_parse_client_dh_public" ), ret ); + return( ret ); + } + + if( p != end ) + { + SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + ssl->handshake->pmslen = POLARSSL_PREMASTER_SIZE; + + if( ( ret = dhm_calc_secret( &ssl->handshake->dhm_ctx, + ssl->handshake->premaster, + &ssl->handshake->pmslen, + ssl->f_rng, ssl->p_rng ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "dhm_calc_secret", ret ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS ); + } + + SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K ); + } + else +#endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDH_RSA || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDH_ECDSA ) + { + if( ( ret = ecdh_read_public( &ssl->handshake->ecdh_ctx, + ssl->in_msg + 4, ssl->in_hslen - 4 ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ecdh_read_public", ret ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); + } + + SSL_DEBUG_ECP( 3, "ECDH: Qp ", &ssl->handshake->ecdh_ctx.Qp ); + + if( ( ret = ecdh_calc_secret( &ssl->handshake->ecdh_ctx, + &ssl->handshake->pmslen, + ssl->handshake->premaster, + POLARSSL_MPI_MAX_SIZE, + ssl->f_rng, ssl->p_rng ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ecdh_calc_secret", ret ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS ); + } + + SSL_DEBUG_MPI( 3, "ECDH: z ", &ssl->handshake->ecdh_ctx.z ); + } + else +#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED || + POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK ) + { + unsigned char *p = ssl->in_msg + 4; + unsigned char *end = ssl->in_msg + ssl->in_hslen; + + if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) + { + SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); + return( ret ); + } + + if( p != end ) + { + SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ( ret = ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* POLARSSL_KEY_EXCHANGE_PSK_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK ) + { + unsigned char *p = ssl->in_msg + 4; + unsigned char *end = ssl->in_msg + ssl->in_hslen; + + if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) + { + SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); + return( ret ); + } + + if( ( ret = ssl_parse_encrypted_pms( ssl, p, end, 2 ) ) != 0 ) + { + SSL_DEBUG_RET( 1, ( "ssl_parse_encrypted_pms" ), ret ); + return( ret ); + } + + if( ( ret = ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK ) + { + unsigned char *p = ssl->in_msg + 4; + unsigned char *end = ssl->in_msg + ssl->in_hslen; + + if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) + { + SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); + return( ret ); + } + if( ( ret = ssl_parse_client_dh_public( ssl, &p, end ) ) != 0 ) + { + SSL_DEBUG_RET( 1, ( "ssl_parse_client_dh_public" ), ret ); + return( ret ); + } + + if( p != end ) + { + SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ( ret = ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) + { + unsigned char *p = ssl->in_msg + 4; + unsigned char *end = ssl->in_msg + ssl->in_hslen; + + if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) + { + SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); + return( ret ); + } + + if( ( ret = ecdh_read_public( &ssl->handshake->ecdh_ctx, + p, end - p ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ecdh_read_public", ret ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); + } + + SSL_DEBUG_ECP( 3, "ECDH: Qp ", &ssl->handshake->ecdh_ctx.Qp ); + + if( ( ret = ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA ) + { + if( ( ret = ssl_parse_encrypted_pms( ssl, + ssl->in_msg + 4, + ssl->in_msg + ssl->in_hslen, + 0 ) ) != 0 ) + { + SSL_DEBUG_RET( 1, ( "ssl_parse_parse_encrypted_pms_secret" ), ret ); + return( ret ); + } + } + else +#endif /* POLARSSL_KEY_EXCHANGE_RSA_ENABLED */ + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + + if( ( ret = ssl_derive_keys( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_derive_keys", ret ); + return( ret ); + } + + ssl->state++; + + SSL_DEBUG_MSG( 2, ( "<= parse client key exchange" ) ); + + return( 0 ); +} + +#if !defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) && \ + !defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ + !defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ + !defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +static int ssl_parse_certificate_verify( ssl_context *ssl ) +{ + const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) ); + + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK ) + { + SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); +} +#else +static int ssl_parse_certificate_verify( ssl_context *ssl ) +{ + int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE; + size_t sa_len, sig_len; + unsigned char hash[48]; + unsigned char *hash_start = hash; + size_t hashlen; +#if defined(POLARSSL_SSL_PROTO_TLS1_2) + pk_type_t pk_alg; +#endif + md_type_t md_alg; + const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) ); + + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK ) + { + SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + if( ssl->session_negotiate->peer_cert == NULL ) + { + SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + ssl->handshake->calc_verify( ssl, hash ); + + if( ( ret = ssl_read_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_read_record", ret ); + return( ret ); + } + + ssl->state++; + + if( ssl->in_msgtype != SSL_MSG_HANDSHAKE ) + { + SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + if( ssl->in_msg[0] != SSL_HS_CERTIFICATE_VERIFY ) + { + SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + /* + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 5 sig alg (TLS 1.2 only) + * 4+n . 5+n signature length (n = sa_len) + * 6+n . 6+n+m signature (m = sig_len) + */ + +#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_1) + if( ssl->minor_ver != SSL_MINOR_VERSION_3 ) + { + sa_len = 0; + + md_alg = POLARSSL_MD_NONE; + hashlen = 36; + + /* For ECDSA, use SHA-1, not MD-5 + SHA-1 */ + if( pk_can_do( &ssl->session_negotiate->peer_cert->pk, + POLARSSL_PK_ECDSA ) ) + { + hash_start += 16; + hashlen -= 16; + md_alg = POLARSSL_MD_SHA1; + } + } + else +#endif /* POLARSSL_SSL_PROTO_SSL3 || POLARSSL_SSL_PROTO_TLS1 || + POLARSSL_SSL_PROTO_TLS1_1 */ +#if defined(POLARSSL_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == SSL_MINOR_VERSION_3 ) + { + sa_len = 2; + + /* + * Hash + */ + if( ssl->in_msg[4] != ssl->handshake->verify_sig_alg ) + { + SSL_DEBUG_MSG( 1, ( "peer not adhering to requested sig_alg" + " for verify message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + md_alg = ssl_md_alg_from_hash( ssl->handshake->verify_sig_alg ); + + /* Info from md_alg will be used instead */ + hashlen = 0; + + /* + * Signature + */ + if( ( pk_alg = ssl_pk_alg_from_sig( ssl->in_msg[5] ) ) + == POLARSSL_PK_NONE ) + { + SSL_DEBUG_MSG( 1, ( "peer not adhering to requested sig_alg" + " for verify message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + /* + * Check the certificate's key type matches the signature alg + */ + if( ! pk_can_do( &ssl->session_negotiate->peer_cert->pk, pk_alg ) ) + { + SSL_DEBUG_MSG( 1, ( "sig_alg doesn't match cert key" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + } + else +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + + sig_len = ( ssl->in_msg[4 + sa_len] << 8 ) | ssl->in_msg[5 + sa_len]; + + if( sa_len + sig_len + 6 != ssl->in_hslen ) + { + SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + if( ( ret = pk_verify( &ssl->session_negotiate->peer_cert->pk, + md_alg, hash_start, hashlen, + ssl->in_msg + 6 + sa_len, sig_len ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "pk_verify", ret ); + return( ret ); + } + + SSL_DEBUG_MSG( 2, ( "<= parse certificate verify" ) ); + + return( ret ); +} +#endif /* !POLARSSL_KEY_EXCHANGE_RSA_ENABLED && + !POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED && + !POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ + +#if defined(POLARSSL_SSL_SESSION_TICKETS) +static int ssl_write_new_session_ticket( ssl_context *ssl ) +{ + int ret; + size_t tlen; + uint32_t lifetime = (uint32_t) ssl->ticket_lifetime; + + SSL_DEBUG_MSG( 2, ( "=> write new session ticket" ) ); + + ssl->out_msgtype = SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = SSL_HS_NEW_SESSION_TICKET; + + /* + * struct { + * uint32 ticket_lifetime_hint; + * opaque ticket<0..2^16-1>; + * } NewSessionTicket; + * + * 4 . 7 ticket_lifetime_hint (0 = unspecified) + * 8 . 9 ticket_len (n) + * 10 . 9+n ticket content + */ + + ssl->out_msg[4] = ( lifetime >> 24 ) & 0xFF; + ssl->out_msg[5] = ( lifetime >> 16 ) & 0xFF; + ssl->out_msg[6] = ( lifetime >> 8 ) & 0xFF; + ssl->out_msg[7] = ( lifetime ) & 0xFF; + + if( ( ret = ssl_write_ticket( ssl, &tlen ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_write_ticket", ret ); + tlen = 0; + } + + ssl->out_msg[8] = (unsigned char)( ( tlen >> 8 ) & 0xFF ); + ssl->out_msg[9] = (unsigned char)( ( tlen ) & 0xFF ); + + ssl->out_msglen = 10 + tlen; + + /* + * Morally equivalent to updating ssl->state, but NewSessionTicket and + * ChangeCipherSpec share the same state. + */ + ssl->handshake->new_session_ticket = 0; + + if( ( ret = ssl_write_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_write_record", ret ); + return( ret ); + } + + SSL_DEBUG_MSG( 2, ( "<= write new session ticket" ) ); + + return( 0 ); +} +#endif /* POLARSSL_SSL_SESSION_TICKETS */ + +/* + * SSL handshake -- server side -- single step + */ +int ssl_handshake_server_step( ssl_context *ssl ) +{ + int ret = 0; + + if( ssl->state == SSL_HANDSHAKE_OVER ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + SSL_DEBUG_MSG( 2, ( "server state: %d", ssl->state ) ); + + if( ( ret = ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + + switch( ssl->state ) + { + case SSL_HELLO_REQUEST: + ssl->state = SSL_CLIENT_HELLO; + break; + + /* + * <== ClientHello + */ + case SSL_CLIENT_HELLO: + ret = ssl_parse_client_hello( ssl ); + break; + + /* + * ==> ServerHello + * Certificate + * ( ServerKeyExchange ) + * ( CertificateRequest ) + * ServerHelloDone + */ + case SSL_SERVER_HELLO: + ret = ssl_write_server_hello( ssl ); + break; + + case SSL_SERVER_CERTIFICATE: + ret = ssl_write_certificate( ssl ); + break; + + case SSL_SERVER_KEY_EXCHANGE: + ret = ssl_write_server_key_exchange( ssl ); + break; + + case SSL_CERTIFICATE_REQUEST: + ret = ssl_write_certificate_request( ssl ); + break; + + case SSL_SERVER_HELLO_DONE: + ret = ssl_write_server_hello_done( ssl ); + break; + + /* + * <== ( Certificate/Alert ) + * ClientKeyExchange + * ( CertificateVerify ) + * ChangeCipherSpec + * Finished + */ + case SSL_CLIENT_CERTIFICATE: + ret = ssl_parse_certificate( ssl ); + break; + + case SSL_CLIENT_KEY_EXCHANGE: + ret = ssl_parse_client_key_exchange( ssl ); + break; + + case SSL_CERTIFICATE_VERIFY: + ret = ssl_parse_certificate_verify( ssl ); + break; + + case SSL_CLIENT_CHANGE_CIPHER_SPEC: + ret = ssl_parse_change_cipher_spec( ssl ); + break; + + case SSL_CLIENT_FINISHED: + ret = ssl_parse_finished( ssl ); + break; + + /* + * ==> ( NewSessionTicket ) + * ChangeCipherSpec + * Finished + */ + case SSL_SERVER_CHANGE_CIPHER_SPEC: +#if defined(POLARSSL_SSL_SESSION_TICKETS) + if( ssl->handshake->new_session_ticket != 0 ) + ret = ssl_write_new_session_ticket( ssl ); + else +#endif + ret = ssl_write_change_cipher_spec( ssl ); + break; + + case SSL_SERVER_FINISHED: + ret = ssl_write_finished( ssl ); + break; + + case SSL_FLUSH_BUFFERS: + SSL_DEBUG_MSG( 2, ( "handshake: done" ) ); + ssl->state = SSL_HANDSHAKE_WRAPUP; + break; + + case SSL_HANDSHAKE_WRAPUP: + ssl_handshake_wrapup( ssl ); + break; + + default: + SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) ); + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + } + + return( ret ); +} +#endif /* POLARSSL_SSL_SRV_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/ssl_tls.c b/component/common/network/ssl/polarssl-1.3.8/library/ssl_tls.c new file mode 100644 index 0000000..20a220d --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/ssl_tls.c @@ -0,0 +1,4873 @@ +/* + * SSLv3/TLSv1 shared functions + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * The SSL 3.0 specification was drafted by Netscape in 1996, + * and became an IETF standard in 1999. + * + * http://wp.netscape.com/eng/ssl3/ + * http://www.ietf.org/rfc/rfc2246.txt + * http://www.ietf.org/rfc/rfc4346.txt + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_SSL_TLS_C) + +#include "polarssl/debug.h" +#include "polarssl/ssl.h" + +#if defined(POLARSSL_X509_CRT_PARSE_C) && \ + defined(POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE) +#include "polarssl/oid.h" +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#define polarssl_malloc malloc +#define polarssl_free free +#endif + +#include + +#if defined(_MSC_VER) && !defined strcasecmp && !defined(EFIX64) && \ + !defined(EFI32) +#define strcasecmp _stricmp +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH) +/* + * Convert max_fragment_length codes to length. + * RFC 6066 says: + * enum{ + * 2^9(1), 2^10(2), 2^11(3), 2^12(4), (255) + * } MaxFragmentLength; + * and we add 0 -> extension unused + */ +static unsigned int mfl_code_to_length[SSL_MAX_FRAG_LEN_INVALID] = +{ + SSL_MAX_CONTENT_LEN, /* SSL_MAX_FRAG_LEN_NONE */ + 512, /* SSL_MAX_FRAG_LEN_512 */ + 1024, /* SSL_MAX_FRAG_LEN_1024 */ + 2048, /* SSL_MAX_FRAG_LEN_2048 */ + 4096, /* SSL_MAX_FRAG_LEN_4096 */ +}; +#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */ + +static int ssl_session_copy( ssl_session *dst, const ssl_session *src ) +{ + ssl_session_free( dst ); + memcpy( dst, src, sizeof( ssl_session ) ); + +#if defined(POLARSSL_X509_CRT_PARSE_C) + if( src->peer_cert != NULL ) + { + int ret; + + dst->peer_cert = (x509_crt *) polarssl_malloc( sizeof(x509_crt) ); + if( dst->peer_cert == NULL ) + return( POLARSSL_ERR_SSL_MALLOC_FAILED ); + + x509_crt_init( dst->peer_cert ); + + if( ( ret = x509_crt_parse_der( dst->peer_cert, src->peer_cert->raw.p, + src->peer_cert->raw.len ) ) != 0 ) + { + polarssl_free( dst->peer_cert ); + dst->peer_cert = NULL; + return( ret ); + } + } +#endif /* POLARSSL_X509_CRT_PARSE_C */ + +#if defined(POLARSSL_SSL_SESSION_TICKETS) + if( src->ticket != NULL ) + { + dst->ticket = (unsigned char *) polarssl_malloc( src->ticket_len ); + if( dst->ticket == NULL ) + return( POLARSSL_ERR_SSL_MALLOC_FAILED ); + + memcpy( dst->ticket, src->ticket, src->ticket_len ); + } +#endif /* POLARSSL_SSL_SESSION_TICKETS */ + + return( 0 ); +} + +#if defined(POLARSSL_SSL_HW_RECORD_ACCEL) +int (*ssl_hw_record_init)( ssl_context *ssl, + const unsigned char *key_enc, const unsigned char *key_dec, + size_t keylen, + const unsigned char *iv_enc, const unsigned char *iv_dec, + size_t ivlen, + const unsigned char *mac_enc, const unsigned char *mac_dec, + size_t maclen ) = NULL; +int (*ssl_hw_record_activate)( ssl_context *ssl, int direction) = NULL; +int (*ssl_hw_record_reset)( ssl_context *ssl ) = NULL; +int (*ssl_hw_record_write)( ssl_context *ssl ) = NULL; +int (*ssl_hw_record_read)( ssl_context *ssl ) = NULL; +int (*ssl_hw_record_finish)( ssl_context *ssl ) = NULL; +#endif /* POLARSSL_SSL_HW_RECORD_ACCEL */ + +/* + * Key material generation + */ +#if defined(POLARSSL_SSL_PROTO_SSL3) +static int ssl3_prf( const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + size_t i; + md5_context md5; + sha1_context sha1; + unsigned char padding[16]; + unsigned char sha1sum[20]; + ((void)label); + + md5_init( &md5 ); + sha1_init( &sha1 ); + + /* + * SSLv3: + * block = + * MD5( secret + SHA1( 'A' + secret + random ) ) + + * MD5( secret + SHA1( 'BB' + secret + random ) ) + + * MD5( secret + SHA1( 'CCC' + secret + random ) ) + + * ... + */ + for( i = 0; i < dlen / 16; i++ ) + { + memset( padding, (unsigned char) ('A' + i), 1 + i ); + + sha1_starts( &sha1 ); + sha1_update( &sha1, padding, 1 + i ); + sha1_update( &sha1, secret, slen ); + sha1_update( &sha1, random, rlen ); + sha1_finish( &sha1, sha1sum ); + + md5_starts( &md5 ); + md5_update( &md5, secret, slen ); + md5_update( &md5, sha1sum, 20 ); + md5_finish( &md5, dstbuf + i * 16 ); + } + + md5_free( &md5 ); + sha1_free( &sha1 ); + + polarssl_zeroize( padding, sizeof( padding ) ); + polarssl_zeroize( sha1sum, sizeof( sha1sum ) ); + + return( 0 ); +} +#endif /* POLARSSL_SSL_PROTO_SSL3 */ + +#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) +static int tls1_prf( const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + size_t nb, hs; + size_t i, j, k; + const unsigned char *S1, *S2; + unsigned char tmp[128]; + unsigned char h_i[20]; + + if( sizeof( tmp ) < 20 + strlen( label ) + rlen ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + hs = ( slen + 1 ) / 2; + S1 = secret; + S2 = secret + slen - hs; + + nb = strlen( label ); + memcpy( tmp + 20, label, nb ); + memcpy( tmp + 20 + nb, random, rlen ); + nb += rlen; + + /* + * First compute P_md5(secret,label+random)[0..dlen] + */ + md5_hmac( S1, hs, tmp + 20, nb, 4 + tmp ); + + for( i = 0; i < dlen; i += 16 ) + { + md5_hmac( S1, hs, 4 + tmp, 16 + nb, h_i ); + md5_hmac( S1, hs, 4 + tmp, 16, 4 + tmp ); + + k = ( i + 16 > dlen ) ? dlen % 16 : 16; + + for( j = 0; j < k; j++ ) + dstbuf[i + j] = h_i[j]; + } + + /* + * XOR out with P_sha1(secret,label+random)[0..dlen] + */ + sha1_hmac( S2, hs, tmp + 20, nb, tmp ); + + for( i = 0; i < dlen; i += 20 ) + { + sha1_hmac( S2, hs, tmp, 20 + nb, h_i ); + sha1_hmac( S2, hs, tmp, 20, tmp ); + + k = ( i + 20 > dlen ) ? dlen % 20 : 20; + + for( j = 0; j < k; j++ ) + dstbuf[i + j] = (unsigned char)( dstbuf[i + j] ^ h_i[j] ); + } + + polarssl_zeroize( tmp, sizeof( tmp ) ); + polarssl_zeroize( h_i, sizeof( h_i ) ); + + return( 0 ); +} +#endif /* POLARSSL_SSL_PROTO_TLS1) || POLARSSL_SSL_PROTO_TLS1_1 */ + +#if defined(POLARSSL_SSL_PROTO_TLS1_2) +#if defined(POLARSSL_SHA256_C) +static int tls_prf_sha256( const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + size_t nb; + size_t i, j, k; + unsigned char tmp[128]; + unsigned char h_i[32]; + + if( sizeof( tmp ) < 32 + strlen( label ) + rlen ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + nb = strlen( label ); + memcpy( tmp + 32, label, nb ); + memcpy( tmp + 32 + nb, random, rlen ); + nb += rlen; + + /* + * Compute P_(secret, label + random)[0..dlen] + */ + sha256_hmac( secret, slen, tmp + 32, nb, tmp, 0 ); + + for( i = 0; i < dlen; i += 32 ) + { + sha256_hmac( secret, slen, tmp, 32 + nb, h_i, 0 ); + sha256_hmac( secret, slen, tmp, 32, tmp, 0 ); + + k = ( i + 32 > dlen ) ? dlen % 32 : 32; + + for( j = 0; j < k; j++ ) + dstbuf[i + j] = h_i[j]; + } + + polarssl_zeroize( tmp, sizeof( tmp ) ); + polarssl_zeroize( h_i, sizeof( h_i ) ); + + return( 0 ); +} +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA512_C) +static int tls_prf_sha384( const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + size_t nb; + size_t i, j, k; + unsigned char tmp[128]; + unsigned char h_i[48]; + + if( sizeof( tmp ) < 48 + strlen( label ) + rlen ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + nb = strlen( label ); + memcpy( tmp + 48, label, nb ); + memcpy( tmp + 48 + nb, random, rlen ); + nb += rlen; + + /* + * Compute P_(secret, label + random)[0..dlen] + */ + sha512_hmac( secret, slen, tmp + 48, nb, tmp, 1 ); + + for( i = 0; i < dlen; i += 48 ) + { + sha512_hmac( secret, slen, tmp, 48 + nb, h_i, 1 ); + sha512_hmac( secret, slen, tmp, 48, tmp, 1 ); + + k = ( i + 48 > dlen ) ? dlen % 48 : 48; + + for( j = 0; j < k; j++ ) + dstbuf[i + j] = h_i[j]; + } + + polarssl_zeroize( tmp, sizeof( tmp ) ); + polarssl_zeroize( h_i, sizeof( h_i ) ); + + return( 0 ); +} +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ + +static void ssl_update_checksum_start( ssl_context *, const unsigned char *, size_t ); + +#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_1) +static void ssl_update_checksum_md5sha1( ssl_context *, const unsigned char *, size_t ); +#endif + +#if defined(POLARSSL_SSL_PROTO_SSL3) +static void ssl_calc_verify_ssl( ssl_context *, unsigned char * ); +static void ssl_calc_finished_ssl( ssl_context *, unsigned char *, int ); +#endif + +#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) +static void ssl_calc_verify_tls( ssl_context *, unsigned char * ); +static void ssl_calc_finished_tls( ssl_context *, unsigned char *, int ); +#endif + +#if defined(POLARSSL_SSL_PROTO_TLS1_2) +#if defined(POLARSSL_SHA256_C) +static void ssl_update_checksum_sha256( ssl_context *, const unsigned char *, size_t ); +static void ssl_calc_verify_tls_sha256( ssl_context *,unsigned char * ); +static void ssl_calc_finished_tls_sha256( ssl_context *,unsigned char *, int ); +#endif + +#if defined(POLARSSL_SHA512_C) +static void ssl_update_checksum_sha384( ssl_context *, const unsigned char *, size_t ); +static void ssl_calc_verify_tls_sha384( ssl_context *, unsigned char * ); +static void ssl_calc_finished_tls_sha384( ssl_context *, unsigned char *, int ); +#endif +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ + +int ssl_derive_keys( ssl_context *ssl ) +{ + int ret = 0; + unsigned char tmp[64]; + unsigned char keyblk[256]; + unsigned char *key1; + unsigned char *key2; + unsigned char *mac_enc; + unsigned char *mac_dec; + size_t iv_copy_len; + const cipher_info_t *cipher_info; + const md_info_t *md_info; + + ssl_session *session = ssl->session_negotiate; + ssl_transform *transform = ssl->transform_negotiate; + ssl_handshake_params *handshake = ssl->handshake; + + SSL_DEBUG_MSG( 2, ( "=> derive keys" ) ); + + cipher_info = cipher_info_from_type( transform->ciphersuite_info->cipher ); + if( cipher_info == NULL ) + { + SSL_DEBUG_MSG( 1, ( "cipher info for %d not found", + transform->ciphersuite_info->cipher ) ); + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + } + + md_info = md_info_from_type( transform->ciphersuite_info->mac ); + if( md_info == NULL ) + { + SSL_DEBUG_MSG( 1, ( "md info for %d not found", + transform->ciphersuite_info->mac ) ); + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + } + + /* + * Set appropriate PRF function and other SSL / TLS / TLS1.2 functions + */ +#if defined(POLARSSL_SSL_PROTO_SSL3) + if( ssl->minor_ver == SSL_MINOR_VERSION_0 ) + { + handshake->tls_prf = ssl3_prf; + handshake->calc_verify = ssl_calc_verify_ssl; + handshake->calc_finished = ssl_calc_finished_ssl; + } + else +#endif +#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) + if( ssl->minor_ver < SSL_MINOR_VERSION_3 ) + { + handshake->tls_prf = tls1_prf; + handshake->calc_verify = ssl_calc_verify_tls; + handshake->calc_finished = ssl_calc_finished_tls; + } + else +#endif +#if defined(POLARSSL_SSL_PROTO_TLS1_2) +#if defined(POLARSSL_SHA512_C) + if( ssl->minor_ver == SSL_MINOR_VERSION_3 && + transform->ciphersuite_info->mac == POLARSSL_MD_SHA384 ) + { + handshake->tls_prf = tls_prf_sha384; + handshake->calc_verify = ssl_calc_verify_tls_sha384; + handshake->calc_finished = ssl_calc_finished_tls_sha384; + } + else +#endif +#if defined(POLARSSL_SHA256_C) + if( ssl->minor_ver == SSL_MINOR_VERSION_3 ) + { + handshake->tls_prf = tls_prf_sha256; + handshake->calc_verify = ssl_calc_verify_tls_sha256; + handshake->calc_finished = ssl_calc_finished_tls_sha256; + } + else +#endif +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + + /* + * SSLv3: + * master = + * MD5( premaster + SHA1( 'A' + premaster + randbytes ) ) + + * MD5( premaster + SHA1( 'BB' + premaster + randbytes ) ) + + * MD5( premaster + SHA1( 'CCC' + premaster + randbytes ) ) + * + * TLSv1+: + * master = PRF( premaster, "master secret", randbytes )[0..47] + */ + if( handshake->resume == 0 ) + { + SSL_DEBUG_BUF( 3, "premaster secret", handshake->premaster, + handshake->pmslen ); + + handshake->tls_prf( handshake->premaster, handshake->pmslen, + "master secret", + handshake->randbytes, 64, session->master, 48 ); + + polarssl_zeroize( handshake->premaster, sizeof(handshake->premaster) ); + } + else + SSL_DEBUG_MSG( 3, ( "no premaster (session resumed)" ) ); + + /* + * Swap the client and server random values. + */ + memcpy( tmp, handshake->randbytes, 64 ); + memcpy( handshake->randbytes, tmp + 32, 32 ); + memcpy( handshake->randbytes + 32, tmp, 32 ); + polarssl_zeroize( tmp, sizeof( tmp ) ); + + /* + * SSLv3: + * key block = + * MD5( master + SHA1( 'A' + master + randbytes ) ) + + * MD5( master + SHA1( 'BB' + master + randbytes ) ) + + * MD5( master + SHA1( 'CCC' + master + randbytes ) ) + + * MD5( master + SHA1( 'DDDD' + master + randbytes ) ) + + * ... + * + * TLSv1: + * key block = PRF( master, "key expansion", randbytes ) + */ + handshake->tls_prf( session->master, 48, "key expansion", + handshake->randbytes, 64, keyblk, 256 ); + + SSL_DEBUG_MSG( 3, ( "ciphersuite = %s", + ssl_get_ciphersuite_name( session->ciphersuite ) ) ); + SSL_DEBUG_BUF( 3, "master secret", session->master, 48 ); + SSL_DEBUG_BUF( 4, "random bytes", handshake->randbytes, 64 ); + SSL_DEBUG_BUF( 4, "key block", keyblk, 256 ); + + polarssl_zeroize( handshake->randbytes, sizeof( handshake->randbytes ) ); + + /* + * Determine the appropriate key, IV and MAC length. + */ + + transform->keylen = cipher_info->key_length / 8; + + if( cipher_info->mode == POLARSSL_MODE_GCM || + cipher_info->mode == POLARSSL_MODE_CCM ) + { + transform->maclen = 0; + + transform->ivlen = 12; + transform->fixed_ivlen = 4; + + /* Minimum length is expicit IV + tag */ + transform->minlen = transform->ivlen - transform->fixed_ivlen + + ( transform->ciphersuite_info->flags & + POLARSSL_CIPHERSUITE_SHORT_TAG ? 8 : 16 ); + } + else + { + int ret; + + /* Initialize HMAC contexts */ + if( ( ret = md_init_ctx( &transform->md_ctx_enc, md_info ) ) != 0 || + ( ret = md_init_ctx( &transform->md_ctx_dec, md_info ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "md_init_ctx", ret ); + return( ret ); + } + + /* Get MAC length */ + transform->maclen = md_get_size( md_info ); + +#if defined(POLARSSL_SSL_TRUNCATED_HMAC) + /* + * If HMAC is to be truncated, we shall keep the leftmost bytes, + * (rfc 6066 page 13 or rfc 2104 section 4), + * so we only need to adjust the length here. + */ + if( session->trunc_hmac == SSL_TRUNC_HMAC_ENABLED ) + transform->maclen = SSL_TRUNCATED_HMAC_LEN; +#endif /* POLARSSL_SSL_TRUNCATED_HMAC */ + + /* IV length */ + transform->ivlen = cipher_info->iv_size; + + /* Minimum length */ + if( cipher_info->mode == POLARSSL_MODE_STREAM ) + transform->minlen = transform->maclen; + else + { + /* + * GenericBlockCipher: + * first multiple of blocklen greater than maclen + * + IV except for SSL3 and TLS 1.0 + */ + transform->minlen = transform->maclen + + cipher_info->block_size + - transform->maclen % cipher_info->block_size; + +#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) + if( ssl->minor_ver == SSL_MINOR_VERSION_0 || + ssl->minor_ver == SSL_MINOR_VERSION_1 ) + ; /* No need to adjust minlen */ + else +#endif +#if defined(POLARSSL_SSL_PROTO_TLS1_1) || defined(POLARSSL_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == SSL_MINOR_VERSION_2 || + ssl->minor_ver == SSL_MINOR_VERSION_3 ) + { + transform->minlen += transform->ivlen; + } + else +#endif + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + } + } + + SSL_DEBUG_MSG( 3, ( "keylen: %d, minlen: %d, ivlen: %d, maclen: %d", + transform->keylen, transform->minlen, transform->ivlen, + transform->maclen ) ); + + /* + * Finally setup the cipher contexts, IVs and MAC secrets. + */ + if( ssl->endpoint == SSL_IS_CLIENT ) + { + key1 = keyblk + transform->maclen * 2; + key2 = keyblk + transform->maclen * 2 + transform->keylen; + + mac_enc = keyblk; + mac_dec = keyblk + transform->maclen; + + /* + * This is not used in TLS v1.1. + */ + iv_copy_len = ( transform->fixed_ivlen ) ? + transform->fixed_ivlen : transform->ivlen; + memcpy( transform->iv_enc, key2 + transform->keylen, iv_copy_len ); + memcpy( transform->iv_dec, key2 + transform->keylen + iv_copy_len, + iv_copy_len ); + } + else + { + key1 = keyblk + transform->maclen * 2 + transform->keylen; + key2 = keyblk + transform->maclen * 2; + + mac_enc = keyblk + transform->maclen; + mac_dec = keyblk; + + /* + * This is not used in TLS v1.1. + */ + iv_copy_len = ( transform->fixed_ivlen ) ? + transform->fixed_ivlen : transform->ivlen; + memcpy( transform->iv_dec, key1 + transform->keylen, iv_copy_len ); + memcpy( transform->iv_enc, key1 + transform->keylen + iv_copy_len, + iv_copy_len ); + } + +#if defined(POLARSSL_SSL_PROTO_SSL3) + if( ssl->minor_ver == SSL_MINOR_VERSION_0 ) + { + if( transform->maclen > sizeof transform->mac_enc ) + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + + memcpy( transform->mac_enc, mac_enc, transform->maclen ); + memcpy( transform->mac_dec, mac_dec, transform->maclen ); + } + else +#endif /* POLARSSL_SSL_PROTO_SSL3 */ +#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_2) + if( ssl->minor_ver >= SSL_MINOR_VERSION_1 ) + { + md_hmac_starts( &transform->md_ctx_enc, mac_enc, transform->maclen ); + md_hmac_starts( &transform->md_ctx_dec, mac_dec, transform->maclen ); + } + else +#endif + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(POLARSSL_SSL_HW_RECORD_ACCEL) + if( ssl_hw_record_init != NULL ) + { + int ret = 0; + + SSL_DEBUG_MSG( 2, ( "going for ssl_hw_record_init()" ) ); + + if( ( ret = ssl_hw_record_init( ssl, key1, key2, transform->keylen, + transform->iv_enc, transform->iv_dec, + iv_copy_len, + mac_enc, mac_dec, + transform->maclen ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_hw_record_init", ret ); + return( POLARSSL_ERR_SSL_HW_ACCEL_FAILED ); + } + } +#endif /* POLARSSL_SSL_HW_RECORD_ACCEL */ + + if( ( ret = cipher_init_ctx( &transform->cipher_ctx_enc, + cipher_info ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "cipher_init_ctx", ret ); + return( ret ); + } + + if( ( ret = cipher_init_ctx( &transform->cipher_ctx_dec, + cipher_info ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "cipher_init_ctx", ret ); + return( ret ); + } + + if( ( ret = cipher_setkey( &transform->cipher_ctx_enc, key1, + cipher_info->key_length, + POLARSSL_ENCRYPT ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "cipher_setkey", ret ); + return( ret ); + } + + if( ( ret = cipher_setkey( &transform->cipher_ctx_dec, key2, + cipher_info->key_length, + POLARSSL_DECRYPT ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "cipher_setkey", ret ); + return( ret ); + } + +#if defined(POLARSSL_CIPHER_MODE_CBC) + if( cipher_info->mode == POLARSSL_MODE_CBC ) + { + if( ( ret = cipher_set_padding_mode( &transform->cipher_ctx_enc, + POLARSSL_PADDING_NONE ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "cipher_set_padding_mode", ret ); + return( ret ); + } + + if( ( ret = cipher_set_padding_mode( &transform->cipher_ctx_dec, + POLARSSL_PADDING_NONE ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "cipher_set_padding_mode", ret ); + return( ret ); + } + } +#endif /* POLARSSL_CIPHER_MODE_CBC */ + + polarssl_zeroize( keyblk, sizeof( keyblk ) ); + +#if defined(POLARSSL_ZLIB_SUPPORT) + // Initialize compression + // + if( session->compression == SSL_COMPRESS_DEFLATE ) + { + if( ssl->compress_buf == NULL ) + { + SSL_DEBUG_MSG( 3, ( "Allocating compression buffer" ) ); + ssl->compress_buf = polarssl_malloc( SSL_BUFFER_LEN ); + if( ssl->compress_buf == NULL ) + { + SSL_DEBUG_MSG( 1, ( "malloc(%d bytes) failed", + SSL_BUFFER_LEN ) ); + return( POLARSSL_ERR_SSL_MALLOC_FAILED ); + } + } + + SSL_DEBUG_MSG( 3, ( "Initializing zlib states" ) ); + + memset( &transform->ctx_deflate, 0, sizeof( transform->ctx_deflate ) ); + memset( &transform->ctx_inflate, 0, sizeof( transform->ctx_inflate ) ); + + if( deflateInit( &transform->ctx_deflate, + Z_DEFAULT_COMPRESSION ) != Z_OK || + inflateInit( &transform->ctx_inflate ) != Z_OK ) + { + SSL_DEBUG_MSG( 1, ( "Failed to initialize compression" ) ); + return( POLARSSL_ERR_SSL_COMPRESSION_FAILED ); + } + } +#endif /* POLARSSL_ZLIB_SUPPORT */ + + SSL_DEBUG_MSG( 2, ( "<= derive keys" ) ); + + return( 0 ); +} + +#if defined(POLARSSL_SSL_PROTO_SSL3) +void ssl_calc_verify_ssl( ssl_context *ssl, unsigned char hash[36] ) +{ + md5_context md5; + sha1_context sha1; + unsigned char pad_1[48]; + unsigned char pad_2[48]; + + SSL_DEBUG_MSG( 2, ( "=> calc verify ssl" ) ); + + memcpy( &md5 , &ssl->handshake->fin_md5 , sizeof(md5_context) ); + memcpy( &sha1, &ssl->handshake->fin_sha1, sizeof(sha1_context) ); + + memset( pad_1, 0x36, 48 ); + memset( pad_2, 0x5C, 48 ); + + md5_update( &md5, ssl->session_negotiate->master, 48 ); + md5_update( &md5, pad_1, 48 ); + md5_finish( &md5, hash ); + + md5_starts( &md5 ); + md5_update( &md5, ssl->session_negotiate->master, 48 ); + md5_update( &md5, pad_2, 48 ); + md5_update( &md5, hash, 16 ); + md5_finish( &md5, hash ); + + sha1_update( &sha1, ssl->session_negotiate->master, 48 ); + sha1_update( &sha1, pad_1, 40 ); + sha1_finish( &sha1, hash + 16 ); + + sha1_starts( &sha1 ); + sha1_update( &sha1, ssl->session_negotiate->master, 48 ); + sha1_update( &sha1, pad_2, 40 ); + sha1_update( &sha1, hash + 16, 20 ); + sha1_finish( &sha1, hash + 16 ); + + SSL_DEBUG_BUF( 3, "calculated verify result", hash, 36 ); + SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); + + md5_free( &md5 ); + sha1_free( &sha1 ); + + return; +} +#endif /* POLARSSL_SSL_PROTO_SSL3 */ + +#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) +void ssl_calc_verify_tls( ssl_context *ssl, unsigned char hash[36] ) +{ + md5_context md5; + sha1_context sha1; + + SSL_DEBUG_MSG( 2, ( "=> calc verify tls" ) ); + + memcpy( &md5 , &ssl->handshake->fin_md5 , sizeof(md5_context) ); + memcpy( &sha1, &ssl->handshake->fin_sha1, sizeof(sha1_context) ); + + md5_finish( &md5, hash ); + sha1_finish( &sha1, hash + 16 ); + + SSL_DEBUG_BUF( 3, "calculated verify result", hash, 36 ); + SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); + + md5_free( &md5 ); + sha1_free( &sha1 ); + + return; +} +#endif /* POLARSSL_SSL_PROTO_TLS1 || POLARSSL_SSL_PROTO_TLS1_1 */ + +#if defined(POLARSSL_SSL_PROTO_TLS1_2) +#if defined(POLARSSL_SHA256_C) +void ssl_calc_verify_tls_sha256( ssl_context *ssl, unsigned char hash[32] ) +{ + sha256_context sha256; + + SSL_DEBUG_MSG( 2, ( "=> calc verify sha256" ) ); + + memcpy( &sha256, &ssl->handshake->fin_sha256, sizeof(sha256_context) ); + sha256_finish( &sha256, hash ); + + SSL_DEBUG_BUF( 3, "calculated verify result", hash, 32 ); + SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); + + sha256_free( &sha256 ); + + return; +} +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA512_C) +void ssl_calc_verify_tls_sha384( ssl_context *ssl, unsigned char hash[48] ) +{ + sha512_context sha512; + + SSL_DEBUG_MSG( 2, ( "=> calc verify sha384" ) ); + + memcpy( &sha512, &ssl->handshake->fin_sha512, sizeof(sha512_context) ); + sha512_finish( &sha512, hash ); + + SSL_DEBUG_BUF( 3, "calculated verify result", hash, 48 ); + SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); + + sha512_free( &sha512 ); + + return; +} +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ + +#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED) +int ssl_psk_derive_premaster( ssl_context *ssl, key_exchange_type_t key_ex ) +{ + unsigned char *p = ssl->handshake->premaster; + unsigned char *end = p + sizeof( ssl->handshake->premaster ); + + /* + * PMS = struct { + * opaque other_secret<0..2^16-1>; + * opaque psk<0..2^16-1>; + * }; + * with "other_secret" depending on the particular key exchange + */ +#if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) + if( key_ex == POLARSSL_KEY_EXCHANGE_PSK ) + { + if( end - p < 2 + (int) ssl->psk_len ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + *(p++) = (unsigned char)( ssl->psk_len >> 8 ); + *(p++) = (unsigned char)( ssl->psk_len ); + p += ssl->psk_len; + } + else +#endif /* POLARSSL_KEY_EXCHANGE_PSK_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( key_ex == POLARSSL_KEY_EXCHANGE_RSA_PSK ) + { + /* + * other_secret already set by the ClientKeyExchange message, + * and is 48 bytes long + */ + *p++ = 0; + *p++ = 48; + p += 48; + } + else +#endif /* POLARSSL_KEY_EXCHANGE_RSA_PKS_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) + if( key_ex == POLARSSL_KEY_EXCHANGE_DHE_PSK ) + { + int ret; + size_t len = end - ( p + 2 ); + + /* Write length only when we know the actual value */ + if( ( ret = dhm_calc_secret( &ssl->handshake->dhm_ctx, + p + 2, &len, + ssl->f_rng, ssl->p_rng ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "dhm_calc_secret", ret ); + return( ret ); + } + *(p++) = (unsigned char)( len >> 8 ); + *(p++) = (unsigned char)( len ); + p += len; + + SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K ); + } + else +#endif /* POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( key_ex == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) + { + int ret; + size_t zlen; + + if( ( ret = ecdh_calc_secret( &ssl->handshake->ecdh_ctx, &zlen, + p + 2, end - ( p + 2 ), + ssl->f_rng, ssl->p_rng ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ecdh_calc_secret", ret ); + return( ret ); + } + + *(p++) = (unsigned char)( zlen >> 8 ); + *(p++) = (unsigned char)( zlen ); + p += zlen; + + SSL_DEBUG_MPI( 3, "ECDH: z", &ssl->handshake->ecdh_ctx.z ); + } + else +#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + + /* opaque psk<0..2^16-1>; */ + if( end - p < 2 + (int) ssl->psk_len ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + *(p++) = (unsigned char)( ssl->psk_len >> 8 ); + *(p++) = (unsigned char)( ssl->psk_len ); + memcpy( p, ssl->psk, ssl->psk_len ); + p += ssl->psk_len; + + ssl->handshake->pmslen = p - ssl->handshake->premaster; + + return( 0 ); +} +#endif /* POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#if defined(POLARSSL_SSL_PROTO_SSL3) +/* + * SSLv3.0 MAC functions + */ +static void ssl_mac( md_context_t *md_ctx, unsigned char *secret, + unsigned char *buf, size_t len, + unsigned char *ctr, int type ) +{ + unsigned char header[11]; + unsigned char padding[48]; + int padlen = 0; + int md_size = md_get_size( md_ctx->md_info ); + int md_type = md_get_type( md_ctx->md_info ); + + if( md_type == POLARSSL_MD_MD5 ) + padlen = 48; + else if( md_type == POLARSSL_MD_SHA1 ) + padlen = 40; + else if( md_type == POLARSSL_MD_SHA256 ) + padlen = 32; + else if( md_type == POLARSSL_MD_SHA384 ) + padlen = 16; + + memcpy( header, ctr, 8 ); + header[ 8] = (unsigned char) type; + header[ 9] = (unsigned char)( len >> 8 ); + header[10] = (unsigned char)( len ); + + memset( padding, 0x36, padlen ); + md_starts( md_ctx ); + md_update( md_ctx, secret, md_size ); + md_update( md_ctx, padding, padlen ); + md_update( md_ctx, header, 11 ); + md_update( md_ctx, buf, len ); + md_finish( md_ctx, buf + len ); + + memset( padding, 0x5C, padlen ); + md_starts( md_ctx ); + md_update( md_ctx, secret, md_size ); + md_update( md_ctx, padding, padlen ); + md_update( md_ctx, buf + len, md_size ); + md_finish( md_ctx, buf + len ); +} +#endif /* POLARSSL_SSL_PROTO_SSL3 */ + +/* + * Encryption/decryption functions + */ +static int ssl_encrypt_buf( ssl_context *ssl ) +{ + size_t i; + const cipher_mode_t mode = cipher_get_cipher_mode( + &ssl->transform_out->cipher_ctx_enc ); + + SSL_DEBUG_MSG( 2, ( "=> encrypt buf" ) ); + + /* + * Add MAC before encrypt, except for AEAD modes + */ +#if defined(POLARSSL_ARC4_C) || defined(POLARSSL_CIPHER_NULL_CIPHER) || \ + ( defined(POLARSSL_CIPHER_MODE_CBC) && \ + ( defined(POLARSSL_AES_C) || defined(POLARSSL_CAMELLIA_C) || defined(POLARSSL_DES_C) ) ) + if( mode != POLARSSL_MODE_GCM && + mode != POLARSSL_MODE_CCM ) + { +#if defined(POLARSSL_SSL_PROTO_SSL3) + if( ssl->minor_ver == SSL_MINOR_VERSION_0 ) + { + ssl_mac( &ssl->transform_out->md_ctx_enc, + ssl->transform_out->mac_enc, + ssl->out_msg, ssl->out_msglen, + ssl->out_ctr, ssl->out_msgtype ); + } + else +#endif +#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_2) + if( ssl->minor_ver >= SSL_MINOR_VERSION_1 ) + { + md_hmac_update( &ssl->transform_out->md_ctx_enc, ssl->out_ctr, 13 ); + md_hmac_update( &ssl->transform_out->md_ctx_enc, + ssl->out_msg, ssl->out_msglen ); + md_hmac_finish( &ssl->transform_out->md_ctx_enc, + ssl->out_msg + ssl->out_msglen ); + md_hmac_reset( &ssl->transform_out->md_ctx_enc ); + } + else +#endif + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + + SSL_DEBUG_BUF( 4, "computed mac", + ssl->out_msg + ssl->out_msglen, + ssl->transform_out->maclen ); + + ssl->out_msglen += ssl->transform_out->maclen; + } +#endif /* AEAD not the only option */ + + /* + * Encrypt + */ +#if defined(POLARSSL_ARC4_C) || defined(POLARSSL_CIPHER_NULL_CIPHER) + if( mode == POLARSSL_MODE_STREAM ) + { + int ret; + size_t olen = 0; + + SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " + "including %d bytes of padding", + ssl->out_msglen, 0 ) ); + + SSL_DEBUG_BUF( 4, "before encrypt: output payload", + ssl->out_msg, ssl->out_msglen ); + + if( ( ret = cipher_crypt( &ssl->transform_out->cipher_ctx_enc, + ssl->transform_out->iv_enc, + ssl->transform_out->ivlen, + ssl->out_msg, ssl->out_msglen, + ssl->out_msg, &olen ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "cipher_crypt", ret ); + return( ret ); + } + + if( ssl->out_msglen != olen ) + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + } + else +#endif /* POLARSSL_ARC4_C || POLARSSL_CIPHER_NULL_CIPHER */ +#if defined(POLARSSL_GCM_C) || defined(POLARSSL_CCM_C) + if( mode == POLARSSL_MODE_GCM || + mode == POLARSSL_MODE_CCM ) + { + int ret; + size_t enc_msglen, olen; + unsigned char *enc_msg; + unsigned char add_data[13]; + unsigned char taglen = ssl->transform_out->ciphersuite_info->flags & + POLARSSL_CIPHERSUITE_SHORT_TAG ? 8 : 16; + + memcpy( add_data, ssl->out_ctr, 8 ); + add_data[8] = ssl->out_msgtype; + add_data[9] = ssl->major_ver; + add_data[10] = ssl->minor_ver; + add_data[11] = ( ssl->out_msglen >> 8 ) & 0xFF; + add_data[12] = ssl->out_msglen & 0xFF; + + SSL_DEBUG_BUF( 4, "additional data used for AEAD", + add_data, 13 ); + + /* + * Generate IV + */ + ret = ssl->f_rng( ssl->p_rng, + ssl->transform_out->iv_enc + ssl->transform_out->fixed_ivlen, + ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen ); + if( ret != 0 ) + return( ret ); + + memcpy( ssl->out_iv, + ssl->transform_out->iv_enc + ssl->transform_out->fixed_ivlen, + ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen ); + + SSL_DEBUG_BUF( 4, "IV used", ssl->out_iv, + ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen ); + + /* + * Fix pointer positions and message length with added IV + */ + enc_msg = ssl->out_msg; + enc_msglen = ssl->out_msglen; + ssl->out_msglen += ssl->transform_out->ivlen - + ssl->transform_out->fixed_ivlen; + + SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " + "including %d bytes of padding", + ssl->out_msglen, 0 ) ); + + SSL_DEBUG_BUF( 4, "before encrypt: output payload", + ssl->out_msg, ssl->out_msglen ); + + /* + * Encrypt and authenticate + */ + if( ( ret = cipher_auth_encrypt( &ssl->transform_out->cipher_ctx_enc, + ssl->transform_out->iv_enc, + ssl->transform_out->ivlen, + add_data, 13, + enc_msg, enc_msglen, + enc_msg, &olen, + enc_msg + enc_msglen, taglen ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "cipher_auth_encrypt", ret ); + return( ret ); + } + + if( olen != enc_msglen ) + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + + ssl->out_msglen += taglen; + + SSL_DEBUG_BUF( 4, "after encrypt: tag", enc_msg + enc_msglen, taglen ); + } + else +#endif /* POLARSSL_GCM_C || POLARSSL_CCM_C */ +#if defined(POLARSSL_CIPHER_MODE_CBC) && \ + ( defined(POLARSSL_AES_C) || defined(POLARSSL_CAMELLIA_C) || defined(POLARSSL_DES_C) ) + if( mode == POLARSSL_MODE_CBC ) + { + int ret; + unsigned char *enc_msg; + size_t enc_msglen, padlen, olen = 0; + + padlen = ssl->transform_out->ivlen - ( ssl->out_msglen + 1 ) % + ssl->transform_out->ivlen; + if( padlen == ssl->transform_out->ivlen ) + padlen = 0; + + for( i = 0; i <= padlen; i++ ) + ssl->out_msg[ssl->out_msglen + i] = (unsigned char) padlen; + + ssl->out_msglen += padlen + 1; + + enc_msglen = ssl->out_msglen; + enc_msg = ssl->out_msg; + +#if defined(POLARSSL_SSL_PROTO_TLS1_1) || defined(POLARSSL_SSL_PROTO_TLS1_2) + /* + * Prepend per-record IV for block cipher in TLS v1.1 and up as per + * Method 1 (6.2.3.2. in RFC4346 and RFC5246) + */ + if( ssl->minor_ver >= SSL_MINOR_VERSION_2 ) + { + /* + * Generate IV + */ + int ret = ssl->f_rng( ssl->p_rng, ssl->transform_out->iv_enc, + ssl->transform_out->ivlen ); + if( ret != 0 ) + return( ret ); + + memcpy( ssl->out_iv, ssl->transform_out->iv_enc, + ssl->transform_out->ivlen ); + + /* + * Fix pointer positions and message length with added IV + */ + enc_msg = ssl->out_msg; + enc_msglen = ssl->out_msglen; + ssl->out_msglen += ssl->transform_out->ivlen; + } +#endif /* POLARSSL_SSL_PROTO_TLS1_1 || POLARSSL_SSL_PROTO_TLS1_2 */ + + SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " + "including %d bytes of IV and %d bytes of padding", + ssl->out_msglen, ssl->transform_out->ivlen, + padlen + 1 ) ); + + SSL_DEBUG_BUF( 4, "before encrypt: output payload", + ssl->out_iv, ssl->out_msglen ); + + if( ( ret = cipher_crypt( &ssl->transform_out->cipher_ctx_enc, + ssl->transform_out->iv_enc, + ssl->transform_out->ivlen, + enc_msg, enc_msglen, + enc_msg, &olen ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "cipher_crypt", ret ); + return( ret ); + } + + if( enc_msglen != olen ) + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) + if( ssl->minor_ver < SSL_MINOR_VERSION_2 ) + { + /* + * Save IV in SSL3 and TLS1 + */ + memcpy( ssl->transform_out->iv_enc, + ssl->transform_out->cipher_ctx_enc.iv, + ssl->transform_out->ivlen ); + } +#endif + } + else +#endif /* POLARSSL_CIPHER_MODE_CBC && + ( POLARSSL_AES_C || POLARSSL_CAMELLIA_C ) */ + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + + for( i = 8; i > 0; i-- ) + if( ++ssl->out_ctr[i - 1] != 0 ) + break; + + /* The loops goes to its end iff the counter is wrapping */ + if( i == 0 ) + { + SSL_DEBUG_MSG( 1, ( "outgoing message counter would wrap" ) ); + return( POLARSSL_ERR_SSL_COUNTER_WRAPPING ); + } + + SSL_DEBUG_MSG( 2, ( "<= encrypt buf" ) ); + + return( 0 ); +} + +#define POLARSSL_SSL_MAX_MAC_SIZE 48 + +static int ssl_decrypt_buf( ssl_context *ssl ) +{ + size_t i; + const cipher_mode_t mode = cipher_get_cipher_mode( + &ssl->transform_in->cipher_ctx_dec ); +#if defined(POLARSSL_ARC4_C) || defined(POLARSSL_CIPHER_NULL_CIPHER) || \ + ( defined(POLARSSL_CIPHER_MODE_CBC) && \ + ( defined(POLARSSL_AES_C) || defined(POLARSSL_CAMELLIA_C) || defined(POLARSSL_DES_C) ) ) + size_t padlen = 0, correct = 1; +#endif + + SSL_DEBUG_MSG( 2, ( "=> decrypt buf" ) ); + + if( ssl->in_msglen < ssl->transform_in->minlen ) + { + SSL_DEBUG_MSG( 1, ( "in_msglen (%d) < minlen (%d)", + ssl->in_msglen, ssl->transform_in->minlen ) ); + return( POLARSSL_ERR_SSL_INVALID_MAC ); + } + +#if defined(POLARSSL_ARC4_C) || defined(POLARSSL_CIPHER_NULL_CIPHER) + if( mode == POLARSSL_MODE_STREAM ) + { + int ret; + size_t olen = 0; + + padlen = 0; + + if( ( ret = cipher_crypt( &ssl->transform_in->cipher_ctx_dec, + ssl->transform_in->iv_dec, + ssl->transform_in->ivlen, + ssl->in_msg, ssl->in_msglen, + ssl->in_msg, &olen ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "cipher_crypt", ret ); + return( ret ); + } + + if( ssl->in_msglen != olen ) + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + } + else +#endif /* POLARSSL_ARC4_C || POLARSSL_CIPHER_NULL_CIPHER */ +#if defined(POLARSSL_GCM_C) || defined(POLARSSL_CCM_C) + if( mode == POLARSSL_MODE_GCM || + mode == POLARSSL_MODE_CCM ) + { + int ret; + size_t dec_msglen, olen; + unsigned char *dec_msg; + unsigned char *dec_msg_result; + unsigned char add_data[13]; + unsigned char taglen = ssl->transform_in->ciphersuite_info->flags & + POLARSSL_CIPHERSUITE_SHORT_TAG ? 8 : 16; + unsigned char explicit_iv_len = ssl->transform_in->ivlen - + ssl->transform_in->fixed_ivlen; + + if( ssl->in_msglen < explicit_iv_len + taglen ) + { + SSL_DEBUG_MSG( 1, ( "msglen (%d) < explicit_iv_len (%d) " + "+ taglen (%d)", ssl->in_msglen, + explicit_iv_len, taglen ) ); + return( POLARSSL_ERR_SSL_INVALID_MAC ); + } + dec_msglen = ssl->in_msglen - explicit_iv_len - taglen; + + dec_msg = ssl->in_msg; + dec_msg_result = ssl->in_msg; + ssl->in_msglen = dec_msglen; + + memcpy( add_data, ssl->in_ctr, 8 ); + add_data[8] = ssl->in_msgtype; + add_data[9] = ssl->major_ver; + add_data[10] = ssl->minor_ver; + add_data[11] = ( ssl->in_msglen >> 8 ) & 0xFF; + add_data[12] = ssl->in_msglen & 0xFF; + + SSL_DEBUG_BUF( 4, "additional data used for AEAD", + add_data, 13 ); + + memcpy( ssl->transform_in->iv_dec + ssl->transform_in->fixed_ivlen, + ssl->in_iv, + ssl->transform_in->ivlen - ssl->transform_in->fixed_ivlen ); + + SSL_DEBUG_BUF( 4, "IV used", ssl->transform_in->iv_dec, + ssl->transform_in->ivlen ); + SSL_DEBUG_BUF( 4, "TAG used", dec_msg + dec_msglen, taglen ); + + /* + * Decrypt and authenticate + */ + if( ( ret = cipher_auth_decrypt( &ssl->transform_in->cipher_ctx_dec, + ssl->transform_in->iv_dec, + ssl->transform_in->ivlen, + add_data, 13, + dec_msg, dec_msglen, + dec_msg_result, &olen, + dec_msg + dec_msglen, taglen ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "cipher_auth_decrypt", ret ); + + if( ret == POLARSSL_ERR_CIPHER_AUTH_FAILED ) + return( POLARSSL_ERR_SSL_INVALID_MAC ); + + return( ret ); + } + + if( olen != dec_msglen ) + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + } + else +#endif /* POLARSSL_GCM_C || POLARSSL_CCM_C */ +#if defined(POLARSSL_CIPHER_MODE_CBC) && \ + ( defined(POLARSSL_AES_C) || defined(POLARSSL_CAMELLIA_C) || defined(POLARSSL_DES_C) ) + if( mode == POLARSSL_MODE_CBC ) + { + /* + * Decrypt and check the padding + */ + int ret; + unsigned char *dec_msg; + unsigned char *dec_msg_result; + size_t dec_msglen; + size_t minlen = 0; + size_t olen = 0; + + /* + * Check immediate ciphertext sanity + */ + if( ssl->in_msglen % ssl->transform_in->ivlen != 0 ) + { + SSL_DEBUG_MSG( 1, ( "msglen (%d) %% ivlen (%d) != 0", + ssl->in_msglen, ssl->transform_in->ivlen ) ); + return( POLARSSL_ERR_SSL_INVALID_MAC ); + } + +#if defined(POLARSSL_SSL_PROTO_TLS1_1) || defined(POLARSSL_SSL_PROTO_TLS1_2) + if( ssl->minor_ver >= SSL_MINOR_VERSION_2 ) + minlen += ssl->transform_in->ivlen; +#endif + + if( ssl->in_msglen < minlen + ssl->transform_in->ivlen || + ssl->in_msglen < minlen + ssl->transform_in->maclen + 1 ) + { + SSL_DEBUG_MSG( 1, ( "msglen (%d) < max( ivlen(%d), maclen (%d) " + "+ 1 ) ( + expl IV )", ssl->in_msglen, + ssl->transform_in->ivlen, + ssl->transform_in->maclen ) ); + return( POLARSSL_ERR_SSL_INVALID_MAC ); + } + + dec_msglen = ssl->in_msglen; + dec_msg = ssl->in_msg; + dec_msg_result = ssl->in_msg; + +#if defined(POLARSSL_SSL_PROTO_TLS1_1) || defined(POLARSSL_SSL_PROTO_TLS1_2) + /* + * Initialize for prepended IV for block cipher in TLS v1.1 and up + */ + if( ssl->minor_ver >= SSL_MINOR_VERSION_2 ) + { + dec_msglen -= ssl->transform_in->ivlen; + ssl->in_msglen -= ssl->transform_in->ivlen; + + for( i = 0; i < ssl->transform_in->ivlen; i++ ) + ssl->transform_in->iv_dec[i] = ssl->in_iv[i]; + } +#endif /* POLARSSL_SSL_PROTO_TLS1_1 || POLARSSL_SSL_PROTO_TLS1_2 */ + + if( ( ret = cipher_crypt( &ssl->transform_in->cipher_ctx_dec, + ssl->transform_in->iv_dec, + ssl->transform_in->ivlen, + dec_msg, dec_msglen, + dec_msg_result, &olen ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "cipher_crypt", ret ); + return( ret ); + } + + if( dec_msglen != olen ) + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) + if( ssl->minor_ver < SSL_MINOR_VERSION_2 ) + { + /* + * Save IV in SSL3 and TLS1 + */ + memcpy( ssl->transform_in->iv_dec, + ssl->transform_in->cipher_ctx_dec.iv, + ssl->transform_in->ivlen ); + } +#endif + + padlen = 1 + ssl->in_msg[ssl->in_msglen - 1]; + + if( ssl->in_msglen < ssl->transform_in->maclen + padlen ) + { +#if defined(POLARSSL_SSL_DEBUG_ALL) + SSL_DEBUG_MSG( 1, ( "msglen (%d) < maclen (%d) + padlen (%d)", + ssl->in_msglen, ssl->transform_in->maclen, padlen ) ); +#endif + padlen = 0; + correct = 0; + } + +#if defined(POLARSSL_SSL_PROTO_SSL3) + if( ssl->minor_ver == SSL_MINOR_VERSION_0 ) + { + if( padlen > ssl->transform_in->ivlen ) + { +#if defined(POLARSSL_SSL_DEBUG_ALL) + SSL_DEBUG_MSG( 1, ( "bad padding length: is %d, " + "should be no more than %d", + padlen, ssl->transform_in->ivlen ) ); +#endif + correct = 0; + } + } + else +#endif /* POLARSSL_SSL_PROTO_SSL3 */ +#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_2) + if( ssl->minor_ver > SSL_MINOR_VERSION_0 ) + { + /* + * TLSv1+: always check the padding up to the first failure + * and fake check up to 256 bytes of padding + */ + size_t pad_count = 0, real_count = 1; + size_t padding_idx = ssl->in_msglen - padlen - 1; + + /* + * Padding is guaranteed to be incorrect if: + * 1. padlen >= ssl->in_msglen + * + * 2. padding_idx >= SSL_MAX_CONTENT_LEN + + * ssl->transform_in->maclen + * + * In both cases we reset padding_idx to a safe value (0) to + * prevent out-of-buffer reads. + */ + correct &= ( ssl->in_msglen >= padlen + 1 ); + correct &= ( padding_idx < SSL_MAX_CONTENT_LEN + + ssl->transform_in->maclen ); + + padding_idx *= correct; + + for( i = 1; i <= 256; i++ ) + { + real_count &= ( i <= padlen ); + pad_count += real_count * + ( ssl->in_msg[padding_idx + i] == padlen - 1 ); + } + + correct &= ( pad_count == padlen ); /* Only 1 on correct padding */ + +#if defined(POLARSSL_SSL_DEBUG_ALL) + if( padlen > 0 && correct == 0 ) + SSL_DEBUG_MSG( 1, ( "bad padding byte detected" ) ); +#endif + padlen &= correct * 0x1FF; + } + else +#endif /* POLARSSL_SSL_PROTO_TLS1 || POLARSSL_SSL_PROTO_TLS1_1 || \ + POLARSSL_SSL_PROTO_TLS1_2 */ + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + } + else +#endif /* POLARSSL_CIPHER_MODE_CBC && + ( POLARSSL_AES_C || POLARSSL_CAMELLIA_C ) */ + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + + SSL_DEBUG_BUF( 4, "raw buffer after decryption", + ssl->in_msg, ssl->in_msglen ); + + /* + * Always compute the MAC (RFC4346, CBCTIME), except for AEAD of course + */ +#if defined(POLARSSL_ARC4_C) || defined(POLARSSL_CIPHER_NULL_CIPHER) || \ + ( defined(POLARSSL_CIPHER_MODE_CBC) && \ + ( defined(POLARSSL_AES_C) || defined(POLARSSL_CAMELLIA_C) || defined(POLARSSL_DES_C) ) ) + if( mode != POLARSSL_MODE_GCM && + mode != POLARSSL_MODE_CCM ) + { + unsigned char tmp[POLARSSL_SSL_MAX_MAC_SIZE]; + + ssl->in_msglen -= ( ssl->transform_in->maclen + padlen ); + + ssl->in_hdr[3] = (unsigned char)( ssl->in_msglen >> 8 ); + ssl->in_hdr[4] = (unsigned char)( ssl->in_msglen ); + + memcpy( tmp, ssl->in_msg + ssl->in_msglen, ssl->transform_in->maclen ); + +#if defined(POLARSSL_SSL_PROTO_SSL3) + if( ssl->minor_ver == SSL_MINOR_VERSION_0 ) + { + ssl_mac( &ssl->transform_in->md_ctx_dec, + ssl->transform_in->mac_dec, + ssl->in_msg, ssl->in_msglen, + ssl->in_ctr, ssl->in_msgtype ); + } + else +#endif /* POLARSSL_SSL_PROTO_SSL3 */ +#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_2) + if( ssl->minor_ver > SSL_MINOR_VERSION_0 ) + { + /* + * Process MAC and always update for padlen afterwards to make + * total time independent of padlen + * + * extra_run compensates MAC check for padlen + * + * Known timing attacks: + * - Lucky Thirteen (http://www.isg.rhul.ac.uk/tls/TLStiming.pdf) + * + * We use ( ( Lx + 8 ) / 64 ) to handle 'negative Lx' values + * correctly. (We round down instead of up, so -56 is the correct + * value for our calculations instead of -55) + */ + size_t j, extra_run = 0; + extra_run = ( 13 + ssl->in_msglen + padlen + 8 ) / 64 - + ( 13 + ssl->in_msglen + 8 ) / 64; + + extra_run &= correct * 0xFF; + + md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_ctr, 13 ); + md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_msg, + ssl->in_msglen ); + md_hmac_finish( &ssl->transform_in->md_ctx_dec, + ssl->in_msg + ssl->in_msglen ); + for( j = 0; j < extra_run; j++ ) + md_process( &ssl->transform_in->md_ctx_dec, ssl->in_msg ); + + md_hmac_reset( &ssl->transform_in->md_ctx_dec ); + } + else +#endif /* POLARSSL_SSL_PROTO_TLS1 || POLARSSL_SSL_PROTO_TLS1_1 || \ + POLARSSL_SSL_PROTO_TLS1_2 */ + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + + SSL_DEBUG_BUF( 4, "message mac", tmp, ssl->transform_in->maclen ); + SSL_DEBUG_BUF( 4, "computed mac", ssl->in_msg + ssl->in_msglen, + ssl->transform_in->maclen ); + + if( safer_memcmp( tmp, ssl->in_msg + ssl->in_msglen, + ssl->transform_in->maclen ) != 0 ) + { +#if defined(POLARSSL_SSL_DEBUG_ALL) + SSL_DEBUG_MSG( 1, ( "message mac does not match" ) ); +#endif + correct = 0; + } + + /* + * Finally check the correct flag + */ + if( correct == 0 ) + return( POLARSSL_ERR_SSL_INVALID_MAC ); + } +#endif /* AEAD not the only option */ + + if( ssl->in_msglen == 0 ) + { + ssl->nb_zero++; + + /* + * Three or more empty messages may be a DoS attack + * (excessive CPU consumption). + */ + if( ssl->nb_zero > 3 ) + { + SSL_DEBUG_MSG( 1, ( "received four consecutive empty " + "messages, possible DoS attack" ) ); + return( POLARSSL_ERR_SSL_INVALID_MAC ); + } + } + else + ssl->nb_zero = 0; + + for( i = 8; i > 0; i-- ) + if( ++ssl->in_ctr[i - 1] != 0 ) + break; + + /* The loops goes to its end iff the counter is wrapping */ + if( i == 0 ) + { + SSL_DEBUG_MSG( 1, ( "incoming message counter would wrap" ) ); + return( POLARSSL_ERR_SSL_COUNTER_WRAPPING ); + } + + SSL_DEBUG_MSG( 2, ( "<= decrypt buf" ) ); + + return( 0 ); +} + +#if defined(POLARSSL_ZLIB_SUPPORT) +/* + * Compression/decompression functions + */ +static int ssl_compress_buf( ssl_context *ssl ) +{ + int ret; + unsigned char *msg_post = ssl->out_msg; + size_t len_pre = ssl->out_msglen; + unsigned char *msg_pre = ssl->compress_buf; + + SSL_DEBUG_MSG( 2, ( "=> compress buf" ) ); + + if( len_pre == 0 ) + return( 0 ); + + memcpy( msg_pre, ssl->out_msg, len_pre ); + + SSL_DEBUG_MSG( 3, ( "before compression: msglen = %d, ", + ssl->out_msglen ) ); + + SSL_DEBUG_BUF( 4, "before compression: output payload", + ssl->out_msg, ssl->out_msglen ); + + ssl->transform_out->ctx_deflate.next_in = msg_pre; + ssl->transform_out->ctx_deflate.avail_in = len_pre; + ssl->transform_out->ctx_deflate.next_out = msg_post; + ssl->transform_out->ctx_deflate.avail_out = SSL_BUFFER_LEN; + + ret = deflate( &ssl->transform_out->ctx_deflate, Z_SYNC_FLUSH ); + if( ret != Z_OK ) + { + SSL_DEBUG_MSG( 1, ( "failed to perform compression (%d)", ret ) ); + return( POLARSSL_ERR_SSL_COMPRESSION_FAILED ); + } + + ssl->out_msglen = SSL_BUFFER_LEN - + ssl->transform_out->ctx_deflate.avail_out; + + SSL_DEBUG_MSG( 3, ( "after compression: msglen = %d, ", + ssl->out_msglen ) ); + + SSL_DEBUG_BUF( 4, "after compression: output payload", + ssl->out_msg, ssl->out_msglen ); + + SSL_DEBUG_MSG( 2, ( "<= compress buf" ) ); + + return( 0 ); +} + +static int ssl_decompress_buf( ssl_context *ssl ) +{ + int ret; + unsigned char *msg_post = ssl->in_msg; + size_t len_pre = ssl->in_msglen; + unsigned char *msg_pre = ssl->compress_buf; + + SSL_DEBUG_MSG( 2, ( "=> decompress buf" ) ); + + if( len_pre == 0 ) + return( 0 ); + + memcpy( msg_pre, ssl->in_msg, len_pre ); + + SSL_DEBUG_MSG( 3, ( "before decompression: msglen = %d, ", + ssl->in_msglen ) ); + + SSL_DEBUG_BUF( 4, "before decompression: input payload", + ssl->in_msg, ssl->in_msglen ); + + ssl->transform_in->ctx_inflate.next_in = msg_pre; + ssl->transform_in->ctx_inflate.avail_in = len_pre; + ssl->transform_in->ctx_inflate.next_out = msg_post; + ssl->transform_in->ctx_inflate.avail_out = SSL_MAX_CONTENT_LEN; + + ret = inflate( &ssl->transform_in->ctx_inflate, Z_SYNC_FLUSH ); + if( ret != Z_OK ) + { + SSL_DEBUG_MSG( 1, ( "failed to perform decompression (%d)", ret ) ); + return( POLARSSL_ERR_SSL_COMPRESSION_FAILED ); + } + + ssl->in_msglen = SSL_MAX_CONTENT_LEN - + ssl->transform_in->ctx_inflate.avail_out; + + SSL_DEBUG_MSG( 3, ( "after decompression: msglen = %d, ", + ssl->in_msglen ) ); + + SSL_DEBUG_BUF( 4, "after decompression: input payload", + ssl->in_msg, ssl->in_msglen ); + + SSL_DEBUG_MSG( 2, ( "<= decompress buf" ) ); + + return( 0 ); +} +#endif /* POLARSSL_ZLIB_SUPPORT */ + +/* + * Fill the input message buffer + */ +int ssl_fetch_input( ssl_context *ssl, size_t nb_want ) +{ + int ret; + size_t len; + + SSL_DEBUG_MSG( 2, ( "=> fetch input" ) ); + + if( nb_want > SSL_BUFFER_LEN - 8 ) + { + SSL_DEBUG_MSG( 1, ( "requesting more data than fits" ) ); + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + } + + while( ssl->in_left < nb_want ) + { + len = nb_want - ssl->in_left; + ret = ssl->f_recv( ssl->p_recv, ssl->in_hdr + ssl->in_left, len ); + + SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d", + ssl->in_left, nb_want ) ); + SSL_DEBUG_RET( 2, "ssl->f_recv", ret ); + + if( ret == 0 ) + return( POLARSSL_ERR_SSL_CONN_EOF ); + + if( ret < 0 ) + return( ret ); + + ssl->in_left += ret; + } + + SSL_DEBUG_MSG( 2, ( "<= fetch input" ) ); + + return( 0 ); +} + +/* + * Flush any data not yet written + */ +int ssl_flush_output( ssl_context *ssl ) +{ + int ret; + unsigned char *buf; + + SSL_DEBUG_MSG( 2, ( "=> flush output" ) ); + + while( ssl->out_left > 0 ) + { + SSL_DEBUG_MSG( 2, ( "message length: %d, out_left: %d", + 5 + ssl->out_msglen, ssl->out_left ) ); + + buf = ssl->out_hdr + 5 + ssl->out_msglen - ssl->out_left; + ret = ssl->f_send( ssl->p_send, buf, ssl->out_left ); + + SSL_DEBUG_RET( 2, "ssl->f_send", ret ); + + if( ret <= 0 ) + return( ret ); + + ssl->out_left -= ret; + } + + SSL_DEBUG_MSG( 2, ( "<= flush output" ) ); + + return( 0 ); +} + +/* + * Record layer functions + */ +int ssl_write_record( ssl_context *ssl ) +{ + int ret, done = 0; + size_t len = ssl->out_msglen; + + SSL_DEBUG_MSG( 2, ( "=> write record" ) ); + + if( ssl->out_msgtype == SSL_MSG_HANDSHAKE ) + { + ssl->out_msg[1] = (unsigned char)( ( len - 4 ) >> 16 ); + ssl->out_msg[2] = (unsigned char)( ( len - 4 ) >> 8 ); + ssl->out_msg[3] = (unsigned char)( ( len - 4 ) ); + + if( ssl->out_msg[0] != SSL_HS_HELLO_REQUEST ) + ssl->handshake->update_checksum( ssl, ssl->out_msg, len ); + } + +#if defined(POLARSSL_ZLIB_SUPPORT) + if( ssl->transform_out != NULL && + ssl->session_out->compression == SSL_COMPRESS_DEFLATE ) + { + if( ( ret = ssl_compress_buf( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_compress_buf", ret ); + return( ret ); + } + + len = ssl->out_msglen; + } +#endif /*POLARSSL_ZLIB_SUPPORT */ + +#if defined(POLARSSL_SSL_HW_RECORD_ACCEL) + if( ssl_hw_record_write != NULL ) + { + SSL_DEBUG_MSG( 2, ( "going for ssl_hw_record_write()" ) ); + + ret = ssl_hw_record_write( ssl ); + if( ret != 0 && ret != POLARSSL_ERR_SSL_HW_ACCEL_FALLTHROUGH ) + { + SSL_DEBUG_RET( 1, "ssl_hw_record_write", ret ); + return( POLARSSL_ERR_SSL_HW_ACCEL_FAILED ); + } + + if( ret == 0 ) + done = 1; + } +#endif /* POLARSSL_SSL_HW_RECORD_ACCEL */ + if( !done ) + { + ssl->out_hdr[0] = (unsigned char) ssl->out_msgtype; + ssl->out_hdr[1] = (unsigned char) ssl->major_ver; + ssl->out_hdr[2] = (unsigned char) ssl->minor_ver; + ssl->out_hdr[3] = (unsigned char)( len >> 8 ); + ssl->out_hdr[4] = (unsigned char)( len ); + + if( ssl->transform_out != NULL ) + { + if( ( ret = ssl_encrypt_buf( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_encrypt_buf", ret ); + return( ret ); + } + + len = ssl->out_msglen; + ssl->out_hdr[3] = (unsigned char)( len >> 8 ); + ssl->out_hdr[4] = (unsigned char)( len ); + } + + ssl->out_left = 5 + ssl->out_msglen; + + SSL_DEBUG_MSG( 3, ( "output record: msgtype = %d, " + "version = [%d:%d], msglen = %d", + ssl->out_hdr[0], ssl->out_hdr[1], ssl->out_hdr[2], + ( ssl->out_hdr[3] << 8 ) | ssl->out_hdr[4] ) ); + + SSL_DEBUG_BUF( 4, "output record sent to network", + ssl->out_hdr, 5 + ssl->out_msglen ); + } + + if( ( ret = ssl_flush_output( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_flush_output", ret ); + return( ret ); + } + + SSL_DEBUG_MSG( 2, ( "<= write record" ) ); + + return( 0 ); +} + +int ssl_read_record( ssl_context *ssl ) +{ + int ret, done = 0; + + SSL_DEBUG_MSG( 2, ( "=> read record" ) ); + + if( ssl->in_hslen != 0 && + ssl->in_hslen < ssl->in_msglen ) + { + /* + * Get next Handshake message in the current record + */ + ssl->in_msglen -= ssl->in_hslen; + + memmove( ssl->in_msg, ssl->in_msg + ssl->in_hslen, + ssl->in_msglen ); + + ssl->in_hslen = 4; + ssl->in_hslen += ( ssl->in_msg[2] << 8 ) | ssl->in_msg[3]; + + SSL_DEBUG_MSG( 3, ( "handshake message: msglen =" + " %d, type = %d, hslen = %d", + ssl->in_msglen, ssl->in_msg[0], ssl->in_hslen ) ); + + if( ssl->in_msglen < 4 || ssl->in_msg[1] != 0 ) + { + SSL_DEBUG_MSG( 1, ( "bad handshake length" ) ); + return( POLARSSL_ERR_SSL_INVALID_RECORD ); + } + + if( ssl->in_msglen < ssl->in_hslen ) + { + SSL_DEBUG_MSG( 1, ( "bad handshake length" ) ); + return( POLARSSL_ERR_SSL_INVALID_RECORD ); + } + + if( ssl->state != SSL_HANDSHAKE_OVER ) + ssl->handshake->update_checksum( ssl, ssl->in_msg, ssl->in_hslen ); + + return( 0 ); + } + + ssl->in_hslen = 0; + + /* + * Read the record header and validate it + */ + if( ( ret = ssl_fetch_input( ssl, 5 ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_fetch_input", ret ); + return( ret ); + } + + ssl->in_msgtype = ssl->in_hdr[0]; + ssl->in_msglen = ( ssl->in_hdr[3] << 8 ) | ssl->in_hdr[4]; + + SSL_DEBUG_MSG( 3, ( "input record: msgtype = %d, " + "version = [%d:%d], msglen = %d", + ssl->in_hdr[0], ssl->in_hdr[1], ssl->in_hdr[2], + ( ssl->in_hdr[3] << 8 ) | ssl->in_hdr[4] ) ); + + if( ssl->in_hdr[1] != ssl->major_ver ) + { + SSL_DEBUG_MSG( 1, ( "major version mismatch" ) ); + return( POLARSSL_ERR_SSL_INVALID_RECORD ); + } + + if( ssl->in_hdr[2] > ssl->max_minor_ver ) + { + SSL_DEBUG_MSG( 1, ( "minor version mismatch" ) ); + return( POLARSSL_ERR_SSL_INVALID_RECORD ); + } + + /* Sanity check (outer boundaries) */ + if( ssl->in_msglen < 1 || ssl->in_msglen > SSL_BUFFER_LEN - 13 ) + { + SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( POLARSSL_ERR_SSL_INVALID_RECORD ); + } + + /* + * Make sure the message length is acceptable for the current transform + * and protocol version. + */ + if( ssl->transform_in == NULL ) + { + if( ssl->in_msglen > SSL_MAX_CONTENT_LEN ) + { + SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( POLARSSL_ERR_SSL_INVALID_RECORD ); + } + } + else + { + if( ssl->in_msglen < ssl->transform_in->minlen ) + { + SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( POLARSSL_ERR_SSL_INVALID_RECORD ); + } + +#if defined(POLARSSL_SSL_PROTO_SSL3) + if( ssl->minor_ver == SSL_MINOR_VERSION_0 && + ssl->in_msglen > ssl->transform_in->minlen + SSL_MAX_CONTENT_LEN ) + { + SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( POLARSSL_ERR_SSL_INVALID_RECORD ); + } +#endif + +#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_2) + /* + * TLS encrypted messages can have up to 256 bytes of padding + */ + if( ssl->minor_ver >= SSL_MINOR_VERSION_1 && + ssl->in_msglen > ssl->transform_in->minlen + + SSL_MAX_CONTENT_LEN + 256 ) + { + SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( POLARSSL_ERR_SSL_INVALID_RECORD ); + } +#endif + } + + /* + * Read and optionally decrypt the message contents + */ + if( ( ret = ssl_fetch_input( ssl, 5 + ssl->in_msglen ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_fetch_input", ret ); + return( ret ); + } + + SSL_DEBUG_BUF( 4, "input record from network", + ssl->in_hdr, 5 + ssl->in_msglen ); + +#if defined(POLARSSL_SSL_HW_RECORD_ACCEL) + if( ssl_hw_record_read != NULL ) + { + SSL_DEBUG_MSG( 2, ( "going for ssl_hw_record_read()" ) ); + + ret = ssl_hw_record_read( ssl ); + if( ret != 0 && ret != POLARSSL_ERR_SSL_HW_ACCEL_FALLTHROUGH ) + { + SSL_DEBUG_RET( 1, "ssl_hw_record_read", ret ); + return( POLARSSL_ERR_SSL_HW_ACCEL_FAILED ); + } + + if( ret == 0 ) + done = 1; + } +#endif /* POLARSSL_SSL_HW_RECORD_ACCEL */ + if( !done && ssl->transform_in != NULL ) + { + if( ( ret = ssl_decrypt_buf( ssl ) ) != 0 ) + { +#if defined(POLARSSL_SSL_ALERT_MESSAGES) + if( ret == POLARSSL_ERR_SSL_INVALID_MAC ) + { + ssl_send_alert_message( ssl, + SSL_ALERT_LEVEL_FATAL, + SSL_ALERT_MSG_BAD_RECORD_MAC ); + } +#endif + SSL_DEBUG_RET( 1, "ssl_decrypt_buf", ret ); + return( ret ); + } + + SSL_DEBUG_BUF( 4, "input payload after decrypt", + ssl->in_msg, ssl->in_msglen ); + + if( ssl->in_msglen > SSL_MAX_CONTENT_LEN ) + { + SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( POLARSSL_ERR_SSL_INVALID_RECORD ); + } + } + +#if defined(POLARSSL_ZLIB_SUPPORT) + if( ssl->transform_in != NULL && + ssl->session_in->compression == SSL_COMPRESS_DEFLATE ) + { + if( ( ret = ssl_decompress_buf( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_decompress_buf", ret ); + return( ret ); + } + + ssl->in_hdr[3] = (unsigned char)( ssl->in_msglen >> 8 ); + ssl->in_hdr[4] = (unsigned char)( ssl->in_msglen ); + } +#endif /* POLARSSL_ZLIB_SUPPORT */ + + if( ssl->in_msgtype != SSL_MSG_HANDSHAKE && + ssl->in_msgtype != SSL_MSG_ALERT && + ssl->in_msgtype != SSL_MSG_CHANGE_CIPHER_SPEC && + ssl->in_msgtype != SSL_MSG_APPLICATION_DATA ) + { + SSL_DEBUG_MSG( 1, ( "unknown record type" ) ); + + if( ( ret = ssl_send_alert_message( ssl, + SSL_ALERT_LEVEL_FATAL, + SSL_ALERT_MSG_UNEXPECTED_MESSAGE ) ) != 0 ) + { + return( ret ); + } + + return( POLARSSL_ERR_SSL_INVALID_RECORD ); + } + + if( ssl->in_msgtype == SSL_MSG_HANDSHAKE ) + { + ssl->in_hslen = 4; + ssl->in_hslen += ( ssl->in_msg[2] << 8 ) | ssl->in_msg[3]; + + SSL_DEBUG_MSG( 3, ( "handshake message: msglen =" + " %d, type = %d, hslen = %d", + ssl->in_msglen, ssl->in_msg[0], ssl->in_hslen ) ); + + /* + * Additional checks to validate the handshake header + */ + if( ssl->in_msglen < 4 || ssl->in_msg[1] != 0 ) + { + SSL_DEBUG_MSG( 1, ( "bad handshake length" ) ); + return( POLARSSL_ERR_SSL_INVALID_RECORD ); + } + + if( ssl->in_msglen < ssl->in_hslen ) + { + SSL_DEBUG_MSG( 1, ( "bad handshake length" ) ); + return( POLARSSL_ERR_SSL_INVALID_RECORD ); + } + + if( ssl->state != SSL_HANDSHAKE_OVER ) + ssl->handshake->update_checksum( ssl, ssl->in_msg, ssl->in_hslen ); + } + + if( ssl->in_msgtype == SSL_MSG_ALERT ) + { + SSL_DEBUG_MSG( 2, ( "got an alert message, type: [%d:%d]", + ssl->in_msg[0], ssl->in_msg[1] ) ); + + /* + * Ignore non-fatal alerts, except close_notify + */ + if( ssl->in_msg[0] == SSL_ALERT_LEVEL_FATAL ) + { + SSL_DEBUG_MSG( 1, ( "is a fatal alert message (msg %d)", + ssl->in_msg[1] ) ); + /** + * Subtract from error code as ssl->in_msg[1] is 7-bit positive + * error identifier. + */ + return( POLARSSL_ERR_SSL_FATAL_ALERT_MESSAGE ); + } + + if( ssl->in_msg[0] == SSL_ALERT_LEVEL_WARNING && + ssl->in_msg[1] == SSL_ALERT_MSG_CLOSE_NOTIFY ) + { + SSL_DEBUG_MSG( 2, ( "is a close notify message" ) ); + return( POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY ); + } + } + + ssl->in_left = 0; + + SSL_DEBUG_MSG( 2, ( "<= read record" ) ); + + return( 0 ); +} + +int ssl_send_fatal_handshake_failure( ssl_context *ssl ) +{ + int ret; + + if( ( ret = ssl_send_alert_message( ssl, + SSL_ALERT_LEVEL_FATAL, + SSL_ALERT_MSG_HANDSHAKE_FAILURE ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +int ssl_send_alert_message( ssl_context *ssl, + unsigned char level, + unsigned char message ) +{ + int ret; + + SSL_DEBUG_MSG( 2, ( "=> send alert message" ) ); + + ssl->out_msgtype = SSL_MSG_ALERT; + ssl->out_msglen = 2; + ssl->out_msg[0] = level; + ssl->out_msg[1] = message; + + if( ( ret = ssl_write_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_write_record", ret ); + return( ret ); + } + + SSL_DEBUG_MSG( 2, ( "<= send alert message" ) ); + + return( 0 ); +} + +/* + * Handshake functions + */ +#if !defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) && \ + !defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) && \ + !defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ + !defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ + !defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \ + !defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ + !defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +int ssl_write_certificate( ssl_context *ssl ) +{ + const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + SSL_DEBUG_MSG( 2, ( "=> write certificate" ) ); + + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) + { + SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); + ssl->state++; + return( 0 ); + } + + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); +} + +int ssl_parse_certificate( ssl_context *ssl ) +{ + const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) ); + + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) + { + SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); + ssl->state++; + return( 0 ); + } + + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); +} +#else +int ssl_write_certificate( ssl_context *ssl ) +{ + int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE; + size_t i, n; + const x509_crt *crt; + const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + SSL_DEBUG_MSG( 2, ( "=> write certificate" ) ); + + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) + { + SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); + ssl->state++; + return( 0 ); + } + + if( ssl->endpoint == SSL_IS_CLIENT ) + { + if( ssl->client_auth == 0 ) + { + SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); + ssl->state++; + return( 0 ); + } + +#if defined(POLARSSL_SSL_PROTO_SSL3) + /* + * If using SSLv3 and got no cert, send an Alert message + * (otherwise an empty Certificate message will be sent). + */ + if( ssl_own_cert( ssl ) == NULL && + ssl->minor_ver == SSL_MINOR_VERSION_0 ) + { + ssl->out_msglen = 2; + ssl->out_msgtype = SSL_MSG_ALERT; + ssl->out_msg[0] = SSL_ALERT_LEVEL_WARNING; + ssl->out_msg[1] = SSL_ALERT_MSG_NO_CERT; + + SSL_DEBUG_MSG( 2, ( "got no certificate to send" ) ); + goto write_msg; + } +#endif /* POLARSSL_SSL_PROTO_SSL3 */ + } + else /* SSL_IS_SERVER */ + { + if( ssl_own_cert( ssl ) == NULL ) + { + SSL_DEBUG_MSG( 1, ( "got no certificate to send" ) ); + return( POLARSSL_ERR_SSL_CERTIFICATE_REQUIRED ); + } + } + + SSL_DEBUG_CRT( 3, "own certificate", ssl_own_cert( ssl ) ); + + /* + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 6 length of all certs + * 7 . 9 length of cert. 1 + * 10 . n-1 peer certificate + * n . n+2 length of cert. 2 + * n+3 . ... upper level cert, etc. + */ + i = 7; + crt = ssl_own_cert( ssl ); + + while( crt != NULL ) + { + n = crt->raw.len; + if( n > SSL_MAX_CONTENT_LEN - 3 - i ) + { + SSL_DEBUG_MSG( 1, ( "certificate too large, %d > %d", + i + 3 + n, SSL_MAX_CONTENT_LEN ) ); + return( POLARSSL_ERR_SSL_CERTIFICATE_TOO_LARGE ); + } + + ssl->out_msg[i ] = (unsigned char)( n >> 16 ); + ssl->out_msg[i + 1] = (unsigned char)( n >> 8 ); + ssl->out_msg[i + 2] = (unsigned char)( n ); + + i += 3; memcpy( ssl->out_msg + i, crt->raw.p, n ); + i += n; crt = crt->next; + } + + ssl->out_msg[4] = (unsigned char)( ( i - 7 ) >> 16 ); + ssl->out_msg[5] = (unsigned char)( ( i - 7 ) >> 8 ); + ssl->out_msg[6] = (unsigned char)( ( i - 7 ) ); + + ssl->out_msglen = i; + ssl->out_msgtype = SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = SSL_HS_CERTIFICATE; + +#if defined(POLARSSL_SSL_PROTO_SSL3) +write_msg: +#endif + + ssl->state++; + + if( ( ret = ssl_write_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_write_record", ret ); + return( ret ); + } + + SSL_DEBUG_MSG( 2, ( "<= write certificate" ) ); + + return( ret ); +} + +int ssl_parse_certificate( ssl_context *ssl ) +{ + int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE; + size_t i, n; + const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) ); + + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ) + { + SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); + ssl->state++; + return( 0 ); + } + + if( ssl->endpoint == SSL_IS_SERVER && + ( ssl->authmode == SSL_VERIFY_NONE || + ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK ) ) + { + ssl->session_negotiate->verify_result = BADCERT_SKIP_VERIFY; + SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); + ssl->state++; + return( 0 ); + } + + if( ( ret = ssl_read_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_read_record", ret ); + return( ret ); + } + + ssl->state++; + +#if defined(POLARSSL_SSL_PROTO_SSL3) + /* + * Check if the client sent an empty certificate + */ + if( ssl->endpoint == SSL_IS_SERVER && + ssl->minor_ver == SSL_MINOR_VERSION_0 ) + { + if( ssl->in_msglen == 2 && + ssl->in_msgtype == SSL_MSG_ALERT && + ssl->in_msg[0] == SSL_ALERT_LEVEL_WARNING && + ssl->in_msg[1] == SSL_ALERT_MSG_NO_CERT ) + { + SSL_DEBUG_MSG( 1, ( "SSLv3 client has no certificate" ) ); + + ssl->session_negotiate->verify_result = BADCERT_MISSING; + if( ssl->authmode == SSL_VERIFY_OPTIONAL ) + return( 0 ); + else + return( POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE ); + } + } +#endif /* POLARSSL_SSL_PROTO_SSL3 */ + +#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_2) + if( ssl->endpoint == SSL_IS_SERVER && + ssl->minor_ver != SSL_MINOR_VERSION_0 ) + { + if( ssl->in_hslen == 7 && + ssl->in_msgtype == SSL_MSG_HANDSHAKE && + ssl->in_msg[0] == SSL_HS_CERTIFICATE && + memcmp( ssl->in_msg + 4, "\0\0\0", 3 ) == 0 ) + { + SSL_DEBUG_MSG( 1, ( "TLSv1 client has no certificate" ) ); + + ssl->session_negotiate->verify_result = BADCERT_MISSING; + if( ssl->authmode == SSL_VERIFY_REQUIRED ) + return( POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE ); + else + return( 0 ); + } + } +#endif /* POLARSSL_SSL_PROTO_TLS1 || POLARSSL_SSL_PROTO_TLS1_1 || \ + POLARSSL_SSL_PROTO_TLS1_2 */ + + if( ssl->in_msgtype != SSL_MSG_HANDSHAKE ) + { + SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + if( ssl->in_msg[0] != SSL_HS_CERTIFICATE || ssl->in_hslen < 10 ) + { + SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + /* + * Same message structure as in ssl_write_certificate() + */ + n = ( ssl->in_msg[5] << 8 ) | ssl->in_msg[6]; + + if( ssl->in_msg[4] != 0 || ssl->in_hslen != 7 + n ) + { + SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + /* In case we tried to reuse a session but it failed */ + if( ssl->session_negotiate->peer_cert != NULL ) + { + x509_crt_free( ssl->session_negotiate->peer_cert ); + polarssl_free( ssl->session_negotiate->peer_cert ); + } + + if( ( ssl->session_negotiate->peer_cert = (x509_crt *) polarssl_malloc( + sizeof( x509_crt ) ) ) == NULL ) + { + SSL_DEBUG_MSG( 1, ( "malloc(%d bytes) failed", + sizeof( x509_crt ) ) ); + return( POLARSSL_ERR_SSL_MALLOC_FAILED ); + } + + x509_crt_init( ssl->session_negotiate->peer_cert ); + + i = 7; + + while( i < ssl->in_hslen ) + { + if( ssl->in_msg[i] != 0 ) + { + SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + n = ( (unsigned int) ssl->in_msg[i + 1] << 8 ) + | (unsigned int) ssl->in_msg[i + 2]; + i += 3; + + if( n < 128 || i + n > ssl->in_hslen ) + { + SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + ret = x509_crt_parse_der( ssl->session_negotiate->peer_cert, + ssl->in_msg + i, n ); + if( ret != 0 ) + { + SSL_DEBUG_RET( 1, " x509_crt_parse_der", ret ); + return( ret ); + } + + i += n; + } + + SSL_DEBUG_CRT( 3, "peer certificate", ssl->session_negotiate->peer_cert ); + + /* + * On client, make sure the server cert doesn't change during renego to + * avoid "triple handshake" attack: https://secure-resumption.com/ + */ + if( ssl->endpoint == SSL_IS_CLIENT && + ssl->renegotiation == SSL_RENEGOTIATION ) + { + if( ssl->session->peer_cert == NULL ) + { + SSL_DEBUG_MSG( 1, ( "new server cert during renegotiation" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + if( ssl->session->peer_cert->raw.len != + ssl->session_negotiate->peer_cert->raw.len || + memcmp( ssl->session->peer_cert->raw.p, + ssl->session_negotiate->peer_cert->raw.p, + ssl->session->peer_cert->raw.len ) != 0 ) + { + SSL_DEBUG_MSG( 1, ( "server cert changed during renegotiation" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE ); + } + } + + if( ssl->authmode != SSL_VERIFY_NONE ) + { + if( ssl->ca_chain == NULL ) + { + SSL_DEBUG_MSG( 1, ( "got no CA chain" ) ); + return( POLARSSL_ERR_SSL_CA_CHAIN_REQUIRED ); + } + + /* + * Main check: verify certificate + */ + ret = x509_crt_verify( ssl->session_negotiate->peer_cert, + ssl->ca_chain, ssl->ca_crl, ssl->peer_cn, + &ssl->session_negotiate->verify_result, + ssl->f_vrfy, ssl->p_vrfy ); + + if( ret != 0 ) + { + SSL_DEBUG_RET( 1, "x509_verify_cert", ret ); + } + + /* + * Secondary checks: always done, but change 'ret' only if it was 0 + */ + +#if defined(POLARSSL_SSL_SET_CURVES) + { + pk_context *pk = &ssl->session_negotiate->peer_cert->pk; + + /* If certificate uses an EC key, make sure the curve is OK */ + if( pk_can_do( pk, POLARSSL_PK_ECKEY ) && + ! ssl_curve_is_acceptable( ssl, pk_ec( *pk )->grp.id ) ) + { + SSL_DEBUG_MSG( 1, ( "bad certificate (EC key curve)" ) ); + if( ret == 0 ) + ret = POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE; + } + } +#endif /* POLARSSL_SSL_SET_CURVES */ + + if( ssl_check_cert_usage( ssl->session_negotiate->peer_cert, + ciphersuite_info, + ! ssl->endpoint ) != 0 ) + { + SSL_DEBUG_MSG( 1, ( "bad certificate (usage extensions)" ) ); + if( ret == 0 ) + ret = POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE; + } + + if( ssl->authmode != SSL_VERIFY_REQUIRED ) + ret = 0; + } + + SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) ); + + return( ret ); +} +#endif /* !POLARSSL_KEY_EXCHANGE_RSA_ENABLED + !POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED + !POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED + !POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED + !POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + !POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED + !POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +int ssl_write_change_cipher_spec( ssl_context *ssl ) +{ + int ret; + + SSL_DEBUG_MSG( 2, ( "=> write change cipher spec" ) ); + + ssl->out_msgtype = SSL_MSG_CHANGE_CIPHER_SPEC; + ssl->out_msglen = 1; + ssl->out_msg[0] = 1; + + ssl->state++; + + if( ( ret = ssl_write_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_write_record", ret ); + return( ret ); + } + + SSL_DEBUG_MSG( 2, ( "<= write change cipher spec" ) ); + + return( 0 ); +} + +int ssl_parse_change_cipher_spec( ssl_context *ssl ) +{ + int ret; + + SSL_DEBUG_MSG( 2, ( "=> parse change cipher spec" ) ); + + if( ( ret = ssl_read_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != SSL_MSG_CHANGE_CIPHER_SPEC ) + { + SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) ); + return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + if( ssl->in_msglen != 1 || ssl->in_msg[0] != 1 ) + { + SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC ); + } + + ssl->state++; + + SSL_DEBUG_MSG( 2, ( "<= parse change cipher spec" ) ); + + return( 0 ); +} + +void ssl_optimize_checksum( ssl_context *ssl, + const ssl_ciphersuite_t *ciphersuite_info ) +{ + ((void) ciphersuite_info); + +#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_1) + if( ssl->minor_ver < SSL_MINOR_VERSION_3 ) + ssl->handshake->update_checksum = ssl_update_checksum_md5sha1; + else +#endif +#if defined(POLARSSL_SSL_PROTO_TLS1_2) +#if defined(POLARSSL_SHA512_C) + if( ciphersuite_info->mac == POLARSSL_MD_SHA384 ) + ssl->handshake->update_checksum = ssl_update_checksum_sha384; + else +#endif +#if defined(POLARSSL_SHA256_C) + if( ciphersuite_info->mac != POLARSSL_MD_SHA384 ) + ssl->handshake->update_checksum = ssl_update_checksum_sha256; + else +#endif +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return; + } +} + +static void ssl_update_checksum_start( ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ +#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_1) + md5_update( &ssl->handshake->fin_md5 , buf, len ); + sha1_update( &ssl->handshake->fin_sha1, buf, len ); +#endif +#if defined(POLARSSL_SSL_PROTO_TLS1_2) +#if defined(POLARSSL_SHA256_C) + sha256_update( &ssl->handshake->fin_sha256, buf, len ); +#endif +#if defined(POLARSSL_SHA512_C) + sha512_update( &ssl->handshake->fin_sha512, buf, len ); +#endif +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ +} + +#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_1) +static void ssl_update_checksum_md5sha1( ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + md5_update( &ssl->handshake->fin_md5 , buf, len ); + sha1_update( &ssl->handshake->fin_sha1, buf, len ); +} +#endif + +#if defined(POLARSSL_SSL_PROTO_TLS1_2) +#if defined(POLARSSL_SHA256_C) +static void ssl_update_checksum_sha256( ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + sha256_update( &ssl->handshake->fin_sha256, buf, len ); +} +#endif + +#if defined(POLARSSL_SHA512_C) +static void ssl_update_checksum_sha384( ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + sha512_update( &ssl->handshake->fin_sha512, buf, len ); +} +#endif +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ + +#if defined(POLARSSL_SSL_PROTO_SSL3) +static void ssl_calc_finished_ssl( + ssl_context *ssl, unsigned char *buf, int from ) +{ + const char *sender; + md5_context md5; + sha1_context sha1; + + unsigned char padbuf[48]; + unsigned char md5sum[16]; + unsigned char sha1sum[20]; + + ssl_session *session = ssl->session_negotiate; + if( !session ) + session = ssl->session; + + SSL_DEBUG_MSG( 2, ( "=> calc finished ssl" ) ); + + memcpy( &md5 , &ssl->handshake->fin_md5 , sizeof(md5_context) ); + memcpy( &sha1, &ssl->handshake->fin_sha1, sizeof(sha1_context) ); + + /* + * SSLv3: + * hash = + * MD5( master + pad2 + + * MD5( handshake + sender + master + pad1 ) ) + * + SHA1( master + pad2 + + * SHA1( handshake + sender + master + pad1 ) ) + */ + +#if !defined(POLARSSL_MD5_ALT) + SSL_DEBUG_BUF( 4, "finished md5 state", (unsigned char *) + md5.state, sizeof( md5.state ) ); +#endif + +#if !defined(POLARSSL_SHA1_ALT) + SSL_DEBUG_BUF( 4, "finished sha1 state", (unsigned char *) + sha1.state, sizeof( sha1.state ) ); +#endif + + sender = ( from == SSL_IS_CLIENT ) ? "CLNT" + : "SRVR"; + + memset( padbuf, 0x36, 48 ); + + md5_update( &md5, (const unsigned char *) sender, 4 ); + md5_update( &md5, session->master, 48 ); + md5_update( &md5, padbuf, 48 ); + md5_finish( &md5, md5sum ); + + sha1_update( &sha1, (const unsigned char *) sender, 4 ); + sha1_update( &sha1, session->master, 48 ); + sha1_update( &sha1, padbuf, 40 ); + sha1_finish( &sha1, sha1sum ); + + memset( padbuf, 0x5C, 48 ); + + md5_starts( &md5 ); + md5_update( &md5, session->master, 48 ); + md5_update( &md5, padbuf, 48 ); + md5_update( &md5, md5sum, 16 ); + md5_finish( &md5, buf ); + + sha1_starts( &sha1 ); + sha1_update( &sha1, session->master, 48 ); + sha1_update( &sha1, padbuf , 40 ); + sha1_update( &sha1, sha1sum, 20 ); + sha1_finish( &sha1, buf + 16 ); + + SSL_DEBUG_BUF( 3, "calc finished result", buf, 36 ); + + md5_free( &md5 ); + sha1_free( &sha1 ); + + polarssl_zeroize( padbuf, sizeof( padbuf ) ); + polarssl_zeroize( md5sum, sizeof( md5sum ) ); + polarssl_zeroize( sha1sum, sizeof( sha1sum ) ); + + SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); +} +#endif /* POLARSSL_SSL_PROTO_SSL3 */ + +#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) +static void ssl_calc_finished_tls( + ssl_context *ssl, unsigned char *buf, int from ) +{ + int len = 12; + const char *sender; + md5_context md5; + sha1_context sha1; + unsigned char padbuf[36]; + + ssl_session *session = ssl->session_negotiate; + if( !session ) + session = ssl->session; + + SSL_DEBUG_MSG( 2, ( "=> calc finished tls" ) ); + + memcpy( &md5 , &ssl->handshake->fin_md5 , sizeof(md5_context) ); + memcpy( &sha1, &ssl->handshake->fin_sha1, sizeof(sha1_context) ); + + /* + * TLSv1: + * hash = PRF( master, finished_label, + * MD5( handshake ) + SHA1( handshake ) )[0..11] + */ + +#if !defined(POLARSSL_MD5_ALT) + SSL_DEBUG_BUF( 4, "finished md5 state", (unsigned char *) + md5.state, sizeof( md5.state ) ); +#endif + +#if !defined(POLARSSL_SHA1_ALT) + SSL_DEBUG_BUF( 4, "finished sha1 state", (unsigned char *) + sha1.state, sizeof( sha1.state ) ); +#endif + + sender = ( from == SSL_IS_CLIENT ) + ? "client finished" + : "server finished"; + + md5_finish( &md5, padbuf ); + sha1_finish( &sha1, padbuf + 16 ); + + ssl->handshake->tls_prf( session->master, 48, sender, + padbuf, 36, buf, len ); + + SSL_DEBUG_BUF( 3, "calc finished result", buf, len ); + + md5_free( &md5 ); + sha1_free( &sha1 ); + + polarssl_zeroize( padbuf, sizeof( padbuf ) ); + + SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); +} +#endif /* POLARSSL_SSL_PROTO_TLS1 || POLARSSL_SSL_PROTO_TLS1_1 */ + +#if defined(POLARSSL_SSL_PROTO_TLS1_2) +#if defined(POLARSSL_SHA256_C) +static void ssl_calc_finished_tls_sha256( + ssl_context *ssl, unsigned char *buf, int from ) +{ + int len = 12; + const char *sender; + sha256_context sha256; + unsigned char padbuf[32]; + + ssl_session *session = ssl->session_negotiate; + if( !session ) + session = ssl->session; + + SSL_DEBUG_MSG( 2, ( "=> calc finished tls sha256" ) ); + + memcpy( &sha256, &ssl->handshake->fin_sha256, sizeof(sha256_context) ); + + /* + * TLSv1.2: + * hash = PRF( master, finished_label, + * Hash( handshake ) )[0.11] + */ + +#if !defined(POLARSSL_SHA256_ALT) + SSL_DEBUG_BUF( 4, "finished sha2 state", (unsigned char *) + sha256.state, sizeof( sha256.state ) ); +#endif + + sender = ( from == SSL_IS_CLIENT ) + ? "client finished" + : "server finished"; + + sha256_finish( &sha256, padbuf ); + + ssl->handshake->tls_prf( session->master, 48, sender, + padbuf, 32, buf, len ); + + SSL_DEBUG_BUF( 3, "calc finished result", buf, len ); + + sha256_free( &sha256 ); + + polarssl_zeroize( padbuf, sizeof( padbuf ) ); + + SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); +} +#endif /* POLARSSL_SHA256_C */ + +#if defined(POLARSSL_SHA512_C) +static void ssl_calc_finished_tls_sha384( + ssl_context *ssl, unsigned char *buf, int from ) +{ + int len = 12; + const char *sender; + sha512_context sha512; + unsigned char padbuf[48]; + + ssl_session *session = ssl->session_negotiate; + if( !session ) + session = ssl->session; + + SSL_DEBUG_MSG( 2, ( "=> calc finished tls sha384" ) ); + + memcpy( &sha512, &ssl->handshake->fin_sha512, sizeof(sha512_context) ); + + /* + * TLSv1.2: + * hash = PRF( master, finished_label, + * Hash( handshake ) )[0.11] + */ + +#if !defined(POLARSSL_SHA512_ALT) + SSL_DEBUG_BUF( 4, "finished sha512 state", (unsigned char *) + sha512.state, sizeof( sha512.state ) ); +#endif + + sender = ( from == SSL_IS_CLIENT ) + ? "client finished" + : "server finished"; + + sha512_finish( &sha512, padbuf ); + + ssl->handshake->tls_prf( session->master, 48, sender, + padbuf, 48, buf, len ); + + SSL_DEBUG_BUF( 3, "calc finished result", buf, len ); + + sha512_free( &sha512 ); + + polarssl_zeroize( padbuf, sizeof( padbuf ) ); + + SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); +} +#endif /* POLARSSL_SHA512_C */ +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ + +void ssl_handshake_wrapup( ssl_context *ssl ) +{ + int resume = ssl->handshake->resume; + + SSL_DEBUG_MSG( 3, ( "=> handshake wrapup" ) ); + + /* + * Free our handshake params + */ + ssl_handshake_free( ssl->handshake ); + polarssl_free( ssl->handshake ); + ssl->handshake = NULL; + + if( ssl->renegotiation == SSL_RENEGOTIATION ) + { + ssl->renegotiation = SSL_RENEGOTIATION_DONE; + ssl->renego_records_seen = 0; + } + + /* + * Switch in our now active transform context + */ + if( ssl->transform ) + { + ssl_transform_free( ssl->transform ); + polarssl_free( ssl->transform ); + } + ssl->transform = ssl->transform_negotiate; + ssl->transform_negotiate = NULL; + + if( ssl->session ) + { + ssl_session_free( ssl->session ); + polarssl_free( ssl->session ); + } + ssl->session = ssl->session_negotiate; + ssl->session_negotiate = NULL; + + /* + * Add cache entry + */ + if( ssl->f_set_cache != NULL && + ssl->session->length != 0 && + resume == 0 ) + { + if( ssl->f_set_cache( ssl->p_set_cache, ssl->session ) != 0 ) + SSL_DEBUG_MSG( 1, ( "cache did not store session" ) ); + } + + ssl->state++; + + SSL_DEBUG_MSG( 3, ( "<= handshake wrapup" ) ); +} + +int ssl_write_finished( ssl_context *ssl ) +{ + int ret, hash_len; + + SSL_DEBUG_MSG( 2, ( "=> write finished" ) ); + + /* + * Set the out_msg pointer to the correct location based on IV length + */ + if( ssl->minor_ver >= SSL_MINOR_VERSION_2 ) + { + ssl->out_msg = ssl->out_iv + ssl->transform_negotiate->ivlen - + ssl->transform_negotiate->fixed_ivlen; + } + else + ssl->out_msg = ssl->out_iv; + + ssl->handshake->calc_finished( ssl, ssl->out_msg + 4, ssl->endpoint ); + + // TODO TLS/1.2 Hash length is determined by cipher suite (Page 63) + hash_len = ( ssl->minor_ver == SSL_MINOR_VERSION_0 ) ? 36 : 12; + + ssl->verify_data_len = hash_len; + memcpy( ssl->own_verify_data, ssl->out_msg + 4, hash_len ); + + ssl->out_msglen = 4 + hash_len; + ssl->out_msgtype = SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = SSL_HS_FINISHED; + + /* + * In case of session resuming, invert the client and server + * ChangeCipherSpec messages order. + */ + if( ssl->handshake->resume != 0 ) + { + if( ssl->endpoint == SSL_IS_CLIENT ) + ssl->state = SSL_HANDSHAKE_WRAPUP; + else + ssl->state = SSL_CLIENT_CHANGE_CIPHER_SPEC; + } + else + ssl->state++; + + /* + * Switch to our negotiated transform and session parameters for outbound + * data. + */ + SSL_DEBUG_MSG( 3, ( "switching to new transform spec for outbound data" ) ); + ssl->transform_out = ssl->transform_negotiate; + ssl->session_out = ssl->session_negotiate; + memset( ssl->out_ctr, 0, 8 ); + +#if defined(POLARSSL_SSL_HW_RECORD_ACCEL) + if( ssl_hw_record_activate != NULL ) + { + if( ( ret = ssl_hw_record_activate( ssl, SSL_CHANNEL_OUTBOUND ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_hw_record_activate", ret ); + return( POLARSSL_ERR_SSL_HW_ACCEL_FAILED ); + } + } +#endif + + if( ( ret = ssl_write_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_write_record", ret ); + return( ret ); + } + + SSL_DEBUG_MSG( 2, ( "<= write finished" ) ); + + return( 0 ); +} + +int ssl_parse_finished( ssl_context *ssl ) +{ + int ret; + unsigned int hash_len; + unsigned char buf[36]; + + SSL_DEBUG_MSG( 2, ( "=> parse finished" ) ); + + ssl->handshake->calc_finished( ssl, buf, ssl->endpoint ^ 1 ); + + /* + * Switch to our negotiated transform and session parameters for inbound + * data. + */ + SSL_DEBUG_MSG( 3, ( "switching to new transform spec for inbound data" ) ); + ssl->transform_in = ssl->transform_negotiate; + ssl->session_in = ssl->session_negotiate; + memset( ssl->in_ctr, 0, 8 ); + + /* + * Set the in_msg pointer to the correct location based on IV length + */ + if( ssl->minor_ver >= SSL_MINOR_VERSION_2 ) + { + ssl->in_msg = ssl->in_iv + ssl->transform_negotiate->ivlen - + ssl->transform_negotiate->fixed_ivlen; + } + else + ssl->in_msg = ssl->in_iv; + +#if defined(POLARSSL_SSL_HW_RECORD_ACCEL) + if( ssl_hw_record_activate != NULL ) + { + if( ( ret = ssl_hw_record_activate( ssl, SSL_CHANNEL_INBOUND ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_hw_record_activate", ret ); + return( POLARSSL_ERR_SSL_HW_ACCEL_FAILED ); + } + } +#endif + + if( ( ret = ssl_read_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != SSL_MSG_HANDSHAKE ) + { + SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); + return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + // TODO TLS/1.2 Hash length is determined by cipher suite (Page 63) + hash_len = ( ssl->minor_ver == SSL_MINOR_VERSION_0 ) ? 36 : 12; + + if( ssl->in_msg[0] != SSL_HS_FINISHED || + ssl->in_hslen != 4 + hash_len ) + { + SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_FINISHED ); + } + + if( safer_memcmp( ssl->in_msg + 4, buf, hash_len ) != 0 ) + { + SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_FINISHED ); + } + + ssl->verify_data_len = hash_len; + memcpy( ssl->peer_verify_data, buf, hash_len ); + + if( ssl->handshake->resume != 0 ) + { + if( ssl->endpoint == SSL_IS_CLIENT ) + ssl->state = SSL_CLIENT_CHANGE_CIPHER_SPEC; + + if( ssl->endpoint == SSL_IS_SERVER ) + ssl->state = SSL_HANDSHAKE_WRAPUP; + } + else + ssl->state++; + + SSL_DEBUG_MSG( 2, ( "<= parse finished" ) ); + + return( 0 ); +} + +static void ssl_handshake_params_init( ssl_handshake_params *handshake ) +{ + memset( handshake, 0, sizeof( ssl_handshake_params ) ); + +#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_1) + md5_init( &handshake->fin_md5 ); + sha1_init( &handshake->fin_sha1 ); + md5_starts( &handshake->fin_md5 ); + sha1_starts( &handshake->fin_sha1 ); +#endif +#if defined(POLARSSL_SSL_PROTO_TLS1_2) +#if defined(POLARSSL_SHA256_C) + sha256_init( &handshake->fin_sha256 ); + sha256_starts( &handshake->fin_sha256, 0 ); +#endif +#if defined(POLARSSL_SHA512_C) + sha512_init( &handshake->fin_sha512 ); + sha512_starts( &handshake->fin_sha512, 1 ); +#endif +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ + + handshake->update_checksum = ssl_update_checksum_start; + handshake->sig_alg = SSL_HASH_SHA1; + +#if defined(POLARSSL_DHM_C) + dhm_init( &handshake->dhm_ctx ); +#endif +#if defined(POLARSSL_ECDH_C) + ecdh_init( &handshake->ecdh_ctx ); +#endif +} + +static void ssl_transform_init( ssl_transform *transform ) +{ + memset( transform, 0, sizeof(ssl_transform) ); + + cipher_init( &transform->cipher_ctx_enc ); + cipher_init( &transform->cipher_ctx_dec ); + + md_init( &transform->md_ctx_enc ); + md_init( &transform->md_ctx_dec ); +} + +void ssl_session_init( ssl_session *session ) +{ + memset( session, 0, sizeof(ssl_session) ); +} + +static int ssl_handshake_init( ssl_context *ssl ) +{ + /* Clear old handshake information if present */ + if( ssl->transform_negotiate ) + ssl_transform_free( ssl->transform_negotiate ); + if( ssl->session_negotiate ) + ssl_session_free( ssl->session_negotiate ); + if( ssl->handshake ) + ssl_handshake_free( ssl->handshake ); + + /* + * Either the pointers are now NULL or cleared properly and can be freed. + * Now allocate missing structures. + */ + if( ssl->transform_negotiate == NULL ) + { + ssl->transform_negotiate = + (ssl_transform *) polarssl_malloc( sizeof(ssl_transform) ); + } + + if( ssl->session_negotiate == NULL ) + { + ssl->session_negotiate = + (ssl_session *) polarssl_malloc( sizeof(ssl_session) ); + } + + if( ssl->handshake == NULL) + { + ssl->handshake = (ssl_handshake_params *) + polarssl_malloc( sizeof(ssl_handshake_params) ); + } + + /* All pointers should exist and can be directly freed without issue */ + if( ssl->handshake == NULL || + ssl->transform_negotiate == NULL || + ssl->session_negotiate == NULL ) + { + SSL_DEBUG_MSG( 1, ( "malloc() of ssl sub-contexts failed" ) ); + + polarssl_free( ssl->handshake ); + polarssl_free( ssl->transform_negotiate ); + polarssl_free( ssl->session_negotiate ); + + ssl->handshake = NULL; + ssl->transform_negotiate = NULL; + ssl->session_negotiate = NULL; + + return( POLARSSL_ERR_SSL_MALLOC_FAILED ); + } + + /* Initialize structures */ + ssl_session_init( ssl->session_negotiate ); + ssl_transform_init( ssl->transform_negotiate ); + ssl_handshake_params_init( ssl->handshake ); + +#if defined(POLARSSL_X509_CRT_PARSE_C) + ssl->handshake->key_cert = ssl->key_cert; +#endif + + return( 0 ); +} + +/* + * Initialize an SSL context + */ +int ssl_init( ssl_context *ssl ) +{ + int ret; + int len = SSL_BUFFER_LEN; + + memset( ssl, 0, sizeof( ssl_context ) ); + + /* + * Sane defaults + */ + ssl->min_major_ver = SSL_MIN_MAJOR_VERSION; + ssl->min_minor_ver = SSL_MIN_MINOR_VERSION; + ssl->max_major_ver = SSL_MAX_MAJOR_VERSION; + ssl->max_minor_ver = SSL_MAX_MINOR_VERSION; + + ssl_set_ciphersuites( ssl, ssl_list_ciphersuites() ); + + ssl->renego_max_records = SSL_RENEGO_MAX_RECORDS_DEFAULT; + +#if defined(POLARSSL_DHM_C) + if( ( ret = mpi_read_string( &ssl->dhm_P, 16, + POLARSSL_DHM_RFC5114_MODP_1024_P) ) != 0 || + ( ret = mpi_read_string( &ssl->dhm_G, 16, + POLARSSL_DHM_RFC5114_MODP_1024_G) ) != 0 ) + { + SSL_DEBUG_RET( 1, "mpi_read_string", ret ); + return( ret ); + } +#endif + + /* + * Prepare base structures + */ + ssl->in_ctr = (unsigned char *) polarssl_malloc( len ); + ssl->in_hdr = ssl->in_ctr + 8; + ssl->in_iv = ssl->in_ctr + 13; + ssl->in_msg = ssl->in_ctr + 13; + + if( ssl->in_ctr == NULL ) + { + SSL_DEBUG_MSG( 1, ( "malloc(%d bytes) failed", len ) ); + return( POLARSSL_ERR_SSL_MALLOC_FAILED ); + } + + ssl->out_ctr = (unsigned char *) polarssl_malloc( len ); + ssl->out_hdr = ssl->out_ctr + 8; + ssl->out_iv = ssl->out_ctr + 13; + ssl->out_msg = ssl->out_ctr + 13; + + if( ssl->out_ctr == NULL ) + { + SSL_DEBUG_MSG( 1, ( "malloc(%d bytes) failed", len ) ); + polarssl_free( ssl->in_ctr ); + ssl->in_ctr = NULL; + return( POLARSSL_ERR_SSL_MALLOC_FAILED ); + } + + memset( ssl-> in_ctr, 0, SSL_BUFFER_LEN ); + memset( ssl->out_ctr, 0, SSL_BUFFER_LEN ); + +#if defined(POLARSSL_SSL_SESSION_TICKETS) + ssl->ticket_lifetime = SSL_DEFAULT_TICKET_LIFETIME; +#endif + +#if defined(POLARSSL_SSL_SET_CURVES) + ssl->curve_list = ecp_grp_id_list( ); +#endif + + if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * Reset an initialized and used SSL context for re-use while retaining + * all application-set variables, function pointers and data. + */ +int ssl_session_reset( ssl_context *ssl ) +{ + int ret; + + ssl->state = SSL_HELLO_REQUEST; + ssl->renegotiation = SSL_INITIAL_HANDSHAKE; + ssl->secure_renegotiation = SSL_LEGACY_RENEGOTIATION; + + ssl->verify_data_len = 0; + memset( ssl->own_verify_data, 0, 36 ); + memset( ssl->peer_verify_data, 0, 36 ); + + ssl->in_offt = NULL; + + ssl->in_msg = ssl->in_ctr + 13; + ssl->in_msgtype = 0; + ssl->in_msglen = 0; + ssl->in_left = 0; + + ssl->in_hslen = 0; + ssl->nb_zero = 0; + ssl->record_read = 0; + + ssl->out_msg = ssl->out_ctr + 13; + ssl->out_msgtype = 0; + ssl->out_msglen = 0; + ssl->out_left = 0; + + ssl->transform_in = NULL; + ssl->transform_out = NULL; + + ssl->renego_records_seen = 0; + + memset( ssl->out_ctr, 0, SSL_BUFFER_LEN ); + memset( ssl->in_ctr, 0, SSL_BUFFER_LEN ); + +#if defined(POLARSSL_SSL_HW_RECORD_ACCEL) + if( ssl_hw_record_reset != NULL ) + { + SSL_DEBUG_MSG( 2, ( "going for ssl_hw_record_reset()" ) ); + if( ( ret = ssl_hw_record_reset( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_hw_record_reset", ret ); + return( POLARSSL_ERR_SSL_HW_ACCEL_FAILED ); + } + } +#endif + + if( ssl->transform ) + { + ssl_transform_free( ssl->transform ); + polarssl_free( ssl->transform ); + ssl->transform = NULL; + } + + if( ssl->session ) + { + ssl_session_free( ssl->session ); + polarssl_free( ssl->session ); + ssl->session = NULL; + } + +#if defined(POLARSSL_SSL_ALPN) + ssl->alpn_chosen = NULL; +#endif + + if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +#if defined(POLARSSL_SSL_SESSION_TICKETS) +static void ssl_ticket_keys_free( ssl_ticket_keys *tkeys ) +{ + aes_free( &tkeys->enc ); + aes_free( &tkeys->dec ); + + polarssl_zeroize( tkeys, sizeof(ssl_ticket_keys) ); +} + +/* + * Allocate and initialize ticket keys + */ +static int ssl_ticket_keys_init( ssl_context *ssl ) +{ + int ret; + ssl_ticket_keys *tkeys; + unsigned char buf[16]; + + if( ssl->ticket_keys != NULL ) + return( 0 ); + + tkeys = (ssl_ticket_keys *) polarssl_malloc( sizeof(ssl_ticket_keys) ); + if( tkeys == NULL ) + return( POLARSSL_ERR_SSL_MALLOC_FAILED ); + + aes_init( &tkeys->enc ); + aes_init( &tkeys->dec ); + + if( ( ret = ssl->f_rng( ssl->p_rng, tkeys->key_name, 16 ) ) != 0 ) + { + ssl_ticket_keys_free( tkeys ); + polarssl_free( tkeys ); + return( ret ); + } + + if( ( ret = ssl->f_rng( ssl->p_rng, buf, 16 ) ) != 0 || + ( ret = aes_setkey_enc( &tkeys->enc, buf, 128 ) ) != 0 || + ( ret = aes_setkey_dec( &tkeys->dec, buf, 128 ) ) != 0 ) + { + ssl_ticket_keys_free( tkeys ); + polarssl_free( tkeys ); + return( ret ); + } + + if( ( ret = ssl->f_rng( ssl->p_rng, tkeys->mac_key, 16 ) ) != 0 ) + { + ssl_ticket_keys_free( tkeys ); + polarssl_free( tkeys ); + return( ret ); + } + + ssl->ticket_keys = tkeys; + + return( 0 ); +} +#endif /* POLARSSL_SSL_SESSION_TICKETS */ + +/* + * SSL set accessors + */ +void ssl_set_endpoint( ssl_context *ssl, int endpoint ) +{ + ssl->endpoint = endpoint; + +#if defined(POLARSSL_SSL_SESSION_TICKETS) + if( endpoint == SSL_IS_CLIENT ) + ssl->session_tickets = SSL_SESSION_TICKETS_ENABLED; +#endif +} + +void ssl_set_authmode( ssl_context *ssl, int authmode ) +{ + ssl->authmode = authmode; +} + +#if defined(POLARSSL_X509_CRT_PARSE_C) +void ssl_set_verify( ssl_context *ssl, + int (*f_vrfy)(void *, x509_crt *, int, int *), + void *p_vrfy ) +{ + ssl->f_vrfy = f_vrfy; + ssl->p_vrfy = p_vrfy; +} +#endif /* POLARSSL_X509_CRT_PARSE_C */ + +void ssl_set_rng( ssl_context *ssl, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + ssl->f_rng = f_rng; + ssl->p_rng = p_rng; +} + +void ssl_set_dbg( ssl_context *ssl, + void (*f_dbg)(void *, int, const char *), + void *p_dbg ) +{ + ssl->f_dbg = f_dbg; + ssl->p_dbg = p_dbg; +} + +void ssl_set_bio( ssl_context *ssl, + int (*f_recv)(void *, unsigned char *, size_t), void *p_recv, + int (*f_send)(void *, const unsigned char *, size_t), void *p_send ) +{ + ssl->f_recv = f_recv; + ssl->f_send = f_send; + ssl->p_recv = p_recv; + ssl->p_send = p_send; +} + +void ssl_set_session_cache( ssl_context *ssl, + int (*f_get_cache)(void *, ssl_session *), void *p_get_cache, + int (*f_set_cache)(void *, const ssl_session *), void *p_set_cache ) +{ + ssl->f_get_cache = f_get_cache; + ssl->p_get_cache = p_get_cache; + ssl->f_set_cache = f_set_cache; + ssl->p_set_cache = p_set_cache; +} + +int ssl_set_session( ssl_context *ssl, const ssl_session *session ) +{ + int ret; + + if( ssl == NULL || + session == NULL || + ssl->session_negotiate == NULL || + ssl->endpoint != SSL_IS_CLIENT ) + { + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + } + + if( ( ret = ssl_session_copy( ssl->session_negotiate, session ) ) != 0 ) + return( ret ); + + ssl->handshake->resume = 1; + + return( 0 ); +} + +void ssl_set_ciphersuites( ssl_context *ssl, const int *ciphersuites ) +{ + ssl->ciphersuite_list[SSL_MINOR_VERSION_0] = ciphersuites; + ssl->ciphersuite_list[SSL_MINOR_VERSION_1] = ciphersuites; + ssl->ciphersuite_list[SSL_MINOR_VERSION_2] = ciphersuites; + ssl->ciphersuite_list[SSL_MINOR_VERSION_3] = ciphersuites; +} + +void ssl_set_ciphersuites_for_version( ssl_context *ssl, + const int *ciphersuites, + int major, int minor ) +{ + if( major != SSL_MAJOR_VERSION_3 ) + return; + + if( minor < SSL_MINOR_VERSION_0 || minor > SSL_MINOR_VERSION_3 ) + return; + + ssl->ciphersuite_list[minor] = ciphersuites; +} + +#if defined(POLARSSL_X509_CRT_PARSE_C) +/* Add a new (empty) key_cert entry an return a pointer to it */ +static ssl_key_cert *ssl_add_key_cert( ssl_context *ssl ) +{ + ssl_key_cert *key_cert, *last; + + key_cert = (ssl_key_cert *) polarssl_malloc( sizeof(ssl_key_cert) ); + if( key_cert == NULL ) + return( NULL ); + + memset( key_cert, 0, sizeof( ssl_key_cert ) ); + + /* Append the new key_cert to the (possibly empty) current list */ + if( ssl->key_cert == NULL ) + { + ssl->key_cert = key_cert; + if( ssl->handshake != NULL ) + ssl->handshake->key_cert = key_cert; + } + else + { + last = ssl->key_cert; + while( last->next != NULL ) + last = last->next; + last->next = key_cert; + } + + return( key_cert ); +} + +void ssl_set_ca_chain( ssl_context *ssl, x509_crt *ca_chain, + x509_crl *ca_crl, const char *peer_cn ) +{ + ssl->ca_chain = ca_chain; + ssl->ca_crl = ca_crl; + ssl->peer_cn = peer_cn; +} + +int ssl_set_own_cert( ssl_context *ssl, x509_crt *own_cert, + pk_context *pk_key ) +{ + ssl_key_cert *key_cert = ssl_add_key_cert( ssl ); + + if( key_cert == NULL ) + return( POLARSSL_ERR_SSL_MALLOC_FAILED ); + + key_cert->cert = own_cert; + key_cert->key = pk_key; + + return( 0 ); +} + +#if defined(POLARSSL_RSA_C) +int ssl_set_own_cert_rsa( ssl_context *ssl, x509_crt *own_cert, + rsa_context *rsa_key ) +{ + int ret; + ssl_key_cert *key_cert = ssl_add_key_cert( ssl ); + + if( key_cert == NULL ) + return( POLARSSL_ERR_SSL_MALLOC_FAILED ); + + key_cert->key = (pk_context *) polarssl_malloc( sizeof(pk_context) ); + if( key_cert->key == NULL ) + return( POLARSSL_ERR_SSL_MALLOC_FAILED ); + + pk_init( key_cert->key ); + + ret = pk_init_ctx( key_cert->key, pk_info_from_type( POLARSSL_PK_RSA ) ); + if( ret != 0 ) + return( ret ); + + if( ( ret = rsa_copy( pk_rsa( *key_cert->key ), rsa_key ) ) != 0 ) + return( ret ); + + key_cert->cert = own_cert; + key_cert->key_own_alloc = 1; + + return( 0 ); +} +#endif /* POLARSSL_RSA_C */ + +int ssl_set_own_cert_alt( ssl_context *ssl, x509_crt *own_cert, + void *rsa_key, + rsa_decrypt_func rsa_decrypt, + rsa_sign_func rsa_sign, + rsa_key_len_func rsa_key_len ) +{ + int ret; + ssl_key_cert *key_cert = ssl_add_key_cert( ssl ); + + if( key_cert == NULL ) + return( POLARSSL_ERR_SSL_MALLOC_FAILED ); + + key_cert->key = (pk_context *) polarssl_malloc( sizeof(pk_context) ); + if( key_cert->key == NULL ) + return( POLARSSL_ERR_SSL_MALLOC_FAILED ); + + pk_init( key_cert->key ); + + if( ( ret = pk_init_ctx_rsa_alt( key_cert->key, rsa_key, + rsa_decrypt, rsa_sign, rsa_key_len ) ) != 0 ) + return( ret ); + + key_cert->cert = own_cert; + key_cert->key_own_alloc = 1; + + return( 0 ); +} +#endif /* POLARSSL_X509_CRT_PARSE_C */ + +#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED) +int ssl_set_psk( ssl_context *ssl, const unsigned char *psk, size_t psk_len, + const unsigned char *psk_identity, size_t psk_identity_len ) +{ + if( psk == NULL || psk_identity == NULL ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + if( psk_len > POLARSSL_PSK_MAX_LEN ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + if( ssl->psk != NULL ) + { + polarssl_free( ssl->psk ); + polarssl_free( ssl->psk_identity ); + } + + ssl->psk_len = psk_len; + ssl->psk_identity_len = psk_identity_len; + + ssl->psk = (unsigned char *) polarssl_malloc( ssl->psk_len ); + ssl->psk_identity = (unsigned char *) + polarssl_malloc( ssl->psk_identity_len ); + + if( ssl->psk == NULL || ssl->psk_identity == NULL ) + return( POLARSSL_ERR_SSL_MALLOC_FAILED ); + + memcpy( ssl->psk, psk, ssl->psk_len ); + memcpy( ssl->psk_identity, psk_identity, ssl->psk_identity_len ); + + return( 0 ); +} + +void ssl_set_psk_cb( ssl_context *ssl, + int (*f_psk)(void *, ssl_context *, const unsigned char *, + size_t), + void *p_psk ) +{ + ssl->f_psk = f_psk; + ssl->p_psk = p_psk; +} +#endif /* POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#if defined(POLARSSL_DHM_C) +int ssl_set_dh_param( ssl_context *ssl, const char *dhm_P, const char *dhm_G ) +{ + int ret; + + if( ( ret = mpi_read_string( &ssl->dhm_P, 16, dhm_P ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "mpi_read_string", ret ); + return( ret ); + } + + if( ( ret = mpi_read_string( &ssl->dhm_G, 16, dhm_G ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "mpi_read_string", ret ); + return( ret ); + } + + return( 0 ); +} + +int ssl_set_dh_param_ctx( ssl_context *ssl, dhm_context *dhm_ctx ) +{ + int ret; + + if( ( ret = mpi_copy( &ssl->dhm_P, &dhm_ctx->P ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "mpi_copy", ret ); + return( ret ); + } + + if( ( ret = mpi_copy( &ssl->dhm_G, &dhm_ctx->G ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "mpi_copy", ret ); + return( ret ); + } + + return( 0 ); +} +#endif /* POLARSSL_DHM_C */ + +#if defined(POLARSSL_SSL_SET_CURVES) +/* + * Set the allowed elliptic curves + */ +void ssl_set_curves( ssl_context *ssl, const ecp_group_id *curve_list ) +{ + ssl->curve_list = curve_list; +} +#endif + +#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION) +int ssl_set_hostname( ssl_context *ssl, const char *hostname ) +{ + if( hostname == NULL ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + ssl->hostname_len = strlen( hostname ); + + if( ssl->hostname_len + 1 == 0 ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + ssl->hostname = (unsigned char *) polarssl_malloc( ssl->hostname_len + 1 ); + + if( ssl->hostname == NULL ) + return( POLARSSL_ERR_SSL_MALLOC_FAILED ); + + memcpy( ssl->hostname, (const unsigned char *) hostname, + ssl->hostname_len ); + + ssl->hostname[ssl->hostname_len] = '\0'; + + return( 0 ); +} + +void ssl_set_sni( ssl_context *ssl, + int (*f_sni)(void *, ssl_context *, + const unsigned char *, size_t), + void *p_sni ) +{ + ssl->f_sni = f_sni; + ssl->p_sni = p_sni; +} +#endif /* POLARSSL_SSL_SERVER_NAME_INDICATION */ + +#if defined(POLARSSL_SSL_ALPN) +int ssl_set_alpn_protocols( ssl_context *ssl, const char **protos ) +{ + size_t cur_len, tot_len; + const char **p; + + /* + * "Empty strings MUST NOT be included and byte strings MUST NOT be + * truncated". Check lengths now rather than later. + */ + tot_len = 0; + for( p = protos; *p != NULL; p++ ) + { + cur_len = strlen( *p ); + tot_len += cur_len; + + if( cur_len == 0 || cur_len > 255 || tot_len > 65535 ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + } + + ssl->alpn_list = protos; + + return( 0 ); +} + +const char *ssl_get_alpn_protocol( const ssl_context *ssl ) +{ + return( ssl->alpn_chosen ); +} +#endif /* POLARSSL_SSL_ALPN */ + +void ssl_set_max_version( ssl_context *ssl, int major, int minor ) +{ + if( major >= SSL_MIN_MAJOR_VERSION && major <= SSL_MAX_MAJOR_VERSION && + minor >= SSL_MIN_MINOR_VERSION && minor <= SSL_MAX_MINOR_VERSION ) + { + ssl->max_major_ver = major; + ssl->max_minor_ver = minor; + } +} + +void ssl_set_min_version( ssl_context *ssl, int major, int minor ) +{ + if( major >= SSL_MIN_MAJOR_VERSION && major <= SSL_MAX_MAJOR_VERSION && + minor >= SSL_MIN_MINOR_VERSION && minor <= SSL_MAX_MINOR_VERSION ) + { + ssl->min_major_ver = major; + ssl->min_minor_ver = minor; + } +} + +#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH) +int ssl_set_max_frag_len( ssl_context *ssl, unsigned char mfl_code ) +{ + if( mfl_code >= SSL_MAX_FRAG_LEN_INVALID || + mfl_code_to_length[mfl_code] > SSL_MAX_CONTENT_LEN ) + { + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + } + + ssl->mfl_code = mfl_code; + + return( 0 ); +} +#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(POLARSSL_SSL_TRUNCATED_HMAC) +int ssl_set_truncated_hmac( ssl_context *ssl, int truncate ) +{ + if( ssl->endpoint != SSL_IS_CLIENT ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + ssl->trunc_hmac = truncate; + + return( 0 ); +} +#endif /* POLARSSL_SSL_TRUNCATED_HMAC */ + +void ssl_set_renegotiation( ssl_context *ssl, int renegotiation ) +{ + ssl->disable_renegotiation = renegotiation; +} + +void ssl_legacy_renegotiation( ssl_context *ssl, int allow_legacy ) +{ + ssl->allow_legacy_renegotiation = allow_legacy; +} + +void ssl_set_renegotiation_enforced( ssl_context *ssl, int max_records ) +{ + ssl->renego_max_records = max_records; +} + +#if defined(POLARSSL_SSL_SESSION_TICKETS) +int ssl_set_session_tickets( ssl_context *ssl, int use_tickets ) +{ + ssl->session_tickets = use_tickets; + + if( ssl->endpoint == SSL_IS_CLIENT ) + return( 0 ); + + if( ssl->f_rng == NULL ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + return( ssl_ticket_keys_init( ssl ) ); +} + +void ssl_set_session_ticket_lifetime( ssl_context *ssl, int lifetime ) +{ + ssl->ticket_lifetime = lifetime; +} +#endif /* POLARSSL_SSL_SESSION_TICKETS */ + +/* + * SSL get accessors + */ +size_t ssl_get_bytes_avail( const ssl_context *ssl ) +{ + return( ssl->in_offt == NULL ? 0 : ssl->in_msglen ); +} + +int ssl_get_verify_result( const ssl_context *ssl ) +{ + return( ssl->session->verify_result ); +} + +const char *ssl_get_ciphersuite( const ssl_context *ssl ) +{ + if( ssl == NULL || ssl->session == NULL ) + return( NULL ); + + return ssl_get_ciphersuite_name( ssl->session->ciphersuite ); +} + +const char *ssl_get_version( const ssl_context *ssl ) +{ + switch( ssl->minor_ver ) + { + case SSL_MINOR_VERSION_0: + return( "SSLv3.0" ); + + case SSL_MINOR_VERSION_1: + return( "TLSv1.0" ); + + case SSL_MINOR_VERSION_2: + return( "TLSv1.1" ); + + case SSL_MINOR_VERSION_3: + return( "TLSv1.2" ); + + default: + break; + } + return( "unknown" ); +} + +#if defined(POLARSSL_X509_CRT_PARSE_C) +const x509_crt *ssl_get_peer_cert( const ssl_context *ssl ) +{ + if( ssl == NULL || ssl->session == NULL ) + return( NULL ); + + return( ssl->session->peer_cert ); +} +#endif /* POLARSSL_X509_CRT_PARSE_C */ + +int ssl_get_session( const ssl_context *ssl, ssl_session *dst ) +{ + if( ssl == NULL || + dst == NULL || + ssl->session == NULL || + ssl->endpoint != SSL_IS_CLIENT ) + { + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + } + + return( ssl_session_copy( dst, ssl->session ) ); +} + +/* + * Perform a single step of the SSL handshake + */ +int ssl_handshake_step( ssl_context *ssl ) +{ + int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE; + +#if defined(POLARSSL_SSL_CLI_C) + if( ssl->endpoint == SSL_IS_CLIENT ) + ret = ssl_handshake_client_step( ssl ); +#endif + +#if defined(POLARSSL_SSL_SRV_C) + if( ssl->endpoint == SSL_IS_SERVER ) + ret = ssl_handshake_server_step( ssl ); +#endif + + return( ret ); +} + +/* + * Perform the SSL handshake + */ +int ssl_handshake( ssl_context *ssl ) +{ + int ret = 0; + + SSL_DEBUG_MSG( 2, ( "=> handshake" ) ); + + while( ssl->state != SSL_HANDSHAKE_OVER ) + { + ret = ssl_handshake_step( ssl ); + + if( ret != 0 ) + break; + } + + SSL_DEBUG_MSG( 2, ( "<= handshake" ) ); + + return( ret ); +} + +#if defined(POLARSSL_SSL_SRV_C) +/* + * Write HelloRequest to request renegotiation on server + */ +static int ssl_write_hello_request( ssl_context *ssl ) +{ + int ret; + + SSL_DEBUG_MSG( 2, ( "=> write hello request" ) ); + + ssl->out_msglen = 4; + ssl->out_msgtype = SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = SSL_HS_HELLO_REQUEST; + + if( ( ret = ssl_write_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_write_record", ret ); + return( ret ); + } + + ssl->renegotiation = SSL_RENEGOTIATION_PENDING; + + SSL_DEBUG_MSG( 2, ( "<= write hello request" ) ); + + return( 0 ); +} +#endif /* POLARSSL_SSL_SRV_C */ + +/* + * Actually renegotiate current connection, triggered by either: + * - calling ssl_renegotiate() on client, + * - receiving a HelloRequest on client during ssl_read(), + * - receiving any handshake message on server during ssl_read() after the + * initial handshake is completed + * If the handshake doesn't complete due to waiting for I/O, it will continue + * during the next calls to ssl_renegotiate() or ssl_read() respectively. + */ +static int ssl_start_renegotiation( ssl_context *ssl ) +{ + int ret; + + SSL_DEBUG_MSG( 2, ( "=> renegotiate" ) ); + + if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) + return( ret ); + + ssl->state = SSL_HELLO_REQUEST; + ssl->renegotiation = SSL_RENEGOTIATION; + + if( ( ret = ssl_handshake( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_handshake", ret ); + return( ret ); + } + + SSL_DEBUG_MSG( 2, ( "<= renegotiate" ) ); + + return( 0 ); +} + +/* + * Renegotiate current connection on client, + * or request renegotiation on server + */ +int ssl_renegotiate( ssl_context *ssl ) +{ + int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE; + +#if defined(POLARSSL_SSL_SRV_C) + /* On server, just send the request */ + if( ssl->endpoint == SSL_IS_SERVER ) + { + if( ssl->state != SSL_HANDSHAKE_OVER ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + return( ssl_write_hello_request( ssl ) ); + } +#endif /* POLARSSL_SSL_SRV_C */ + +#if defined(POLARSSL_SSL_CLI_C) + /* + * On client, either start the renegotiation process or, + * if already in progress, continue the handshake + */ + if( ssl->renegotiation != SSL_RENEGOTIATION ) + { + if( ssl->state != SSL_HANDSHAKE_OVER ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + if( ( ret = ssl_start_renegotiation( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_start_renegotiation", ret ); + return( ret ); + } + } + else + { + if( ( ret = ssl_handshake( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_handshake", ret ); + return( ret ); + } + } +#endif /* POLARSSL_SSL_CLI_C */ + + return( ret ); +} + +/* + * Receive application data decrypted from the SSL layer + */ +int ssl_read( ssl_context *ssl, unsigned char *buf, size_t len ) +{ + int ret; + size_t n; + + SSL_DEBUG_MSG( 2, ( "=> read" ) ); + + if( ssl->state != SSL_HANDSHAKE_OVER ) + { + if( ( ret = ssl_handshake( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_handshake", ret ); + return( ret ); + } + } + + if( ssl->in_offt == NULL ) + { + if( ( ret = ssl_read_record( ssl ) ) != 0 ) + { + if( ret == POLARSSL_ERR_SSL_CONN_EOF ) + return( 0 ); + + SSL_DEBUG_RET( 1, "ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msglen == 0 && + ssl->in_msgtype == SSL_MSG_APPLICATION_DATA ) + { + /* + * OpenSSL sends empty messages to randomize the IV + */ + if( ( ret = ssl_read_record( ssl ) ) != 0 ) + { + if( ret == POLARSSL_ERR_SSL_CONN_EOF ) + return( 0 ); + + SSL_DEBUG_RET( 1, "ssl_read_record", ret ); + return( ret ); + } + } + + if( ssl->in_msgtype == SSL_MSG_HANDSHAKE ) + { + SSL_DEBUG_MSG( 1, ( "received handshake message" ) ); + + if( ssl->endpoint == SSL_IS_CLIENT && + ( ssl->in_msg[0] != SSL_HS_HELLO_REQUEST || + ssl->in_hslen != 4 ) ) + { + SSL_DEBUG_MSG( 1, ( "handshake received (not HelloRequest)" ) ); + return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + if( ssl->disable_renegotiation == SSL_RENEGOTIATION_DISABLED || + ( ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION && + ssl->allow_legacy_renegotiation == + SSL_LEGACY_NO_RENEGOTIATION ) ) + { + SSL_DEBUG_MSG( 3, ( "ignoring renegotiation, sending alert" ) ); + +#if defined(POLARSSL_SSL_PROTO_SSL3) + if( ssl->minor_ver == SSL_MINOR_VERSION_0 ) + { + /* + * SSLv3 does not have a "no_renegotiation" alert + */ + if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) + return( ret ); + } + else +#endif /* POLARSSL_SSL_PROTO_SSL3 */ +#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \ + defined(POLARSSL_SSL_PROTO_TLS1_2) + if( ssl->minor_ver >= SSL_MINOR_VERSION_1 ) + { + if( ( ret = ssl_send_alert_message( ssl, + SSL_ALERT_LEVEL_WARNING, + SSL_ALERT_MSG_NO_RENEGOTIATION ) ) != 0 ) + { + return( ret ); + } + } + else +#endif /* POLARSSL_SSL_PROTO_TLS1 || POLARSSL_SSL_PROTO_TLS1_1 || + POLARSSL_SSL_PROTO_TLS1_2 */ + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + } + else + { + if( ( ret = ssl_start_renegotiation( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_start_renegotiation", ret ); + return( ret ); + } + + return( POLARSSL_ERR_NET_WANT_READ ); + } + } + else if( ssl->renegotiation == SSL_RENEGOTIATION_PENDING ) + { + ssl->renego_records_seen++; + + if( ssl->renego_max_records >= 0 && + ssl->renego_records_seen > ssl->renego_max_records ) + { + SSL_DEBUG_MSG( 1, ( "renegotiation requested, " + "but not honored by client" ) ); + return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ); + } + } + else if( ssl->in_msgtype != SSL_MSG_APPLICATION_DATA ) + { + SSL_DEBUG_MSG( 1, ( "bad application data message" ) ); + return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + ssl->in_offt = ssl->in_msg; + } + + n = ( len < ssl->in_msglen ) + ? len : ssl->in_msglen; + + memcpy( buf, ssl->in_offt, n ); + ssl->in_msglen -= n; + + if( ssl->in_msglen == 0 ) + /* all bytes consumed */ + ssl->in_offt = NULL; + else + /* more data available */ + ssl->in_offt += n; + + SSL_DEBUG_MSG( 2, ( "<= read" ) ); + + return( (int) n ); +} + +/* + * Send application data to be encrypted by the SSL layer + */ +int ssl_write( ssl_context *ssl, const unsigned char *buf, size_t len ) +{ + int ret; + size_t n; + unsigned int max_len = SSL_MAX_CONTENT_LEN; + + SSL_DEBUG_MSG( 2, ( "=> write" ) ); + + if( ssl->state != SSL_HANDSHAKE_OVER ) + { + if( ( ret = ssl_handshake( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_handshake", ret ); + return( ret ); + } + } + +#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH) + /* + * Assume mfl_code is correct since it was checked when set + */ + max_len = mfl_code_to_length[ssl->mfl_code]; + + /* + * Check if a smaller max length was negotiated + */ + if( ssl->session_out != NULL && + mfl_code_to_length[ssl->session_out->mfl_code] < max_len ) + { + max_len = mfl_code_to_length[ssl->session_out->mfl_code]; + } +#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */ + + n = ( len < max_len) ? len : max_len; + + if( ssl->out_left != 0 ) + { + if( ( ret = ssl_flush_output( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_flush_output", ret ); + return( ret ); + } + } + else + { + ssl->out_msglen = n; + ssl->out_msgtype = SSL_MSG_APPLICATION_DATA; + memcpy( ssl->out_msg, buf, n ); + + if( ( ret = ssl_write_record( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_write_record", ret ); + return( ret ); + } + } + + SSL_DEBUG_MSG( 2, ( "<= write" ) ); + + return( (int) n ); +} + +/* + * Notify the peer that the connection is being closed + */ +int ssl_close_notify( ssl_context *ssl ) +{ + int ret; + + SSL_DEBUG_MSG( 2, ( "=> write close notify" ) ); + + if( ( ret = ssl_flush_output( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_flush_output", ret ); + return( ret ); + } + + if( ssl->state == SSL_HANDSHAKE_OVER ) + { + if( ( ret = ssl_send_alert_message( ssl, + SSL_ALERT_LEVEL_WARNING, + SSL_ALERT_MSG_CLOSE_NOTIFY ) ) != 0 ) + { + return( ret ); + } + } + + SSL_DEBUG_MSG( 2, ( "<= write close notify" ) ); + + return( ret ); +} + +void ssl_transform_free( ssl_transform *transform ) +{ + if( transform == NULL ) + return; + +#if defined(POLARSSL_ZLIB_SUPPORT) + deflateEnd( &transform->ctx_deflate ); + inflateEnd( &transform->ctx_inflate ); +#endif + + cipher_free( &transform->cipher_ctx_enc ); + cipher_free( &transform->cipher_ctx_dec ); + + md_free( &transform->md_ctx_enc ); + md_free( &transform->md_ctx_dec ); + + polarssl_zeroize( transform, sizeof( ssl_transform ) ); +} + +#if defined(POLARSSL_X509_CRT_PARSE_C) +static void ssl_key_cert_free( ssl_key_cert *key_cert ) +{ + ssl_key_cert *cur = key_cert, *next; + + while( cur != NULL ) + { + next = cur->next; + + if( cur->key_own_alloc ) + { + pk_free( cur->key ); + polarssl_free( cur->key ); + } + polarssl_free( cur ); + + cur = next; + } +} +#endif /* POLARSSL_X509_CRT_PARSE_C */ + +void ssl_handshake_free( ssl_handshake_params *handshake ) +{ + if( handshake == NULL ) + return; + +#if defined(POLARSSL_DHM_C) + dhm_free( &handshake->dhm_ctx ); +#endif +#if defined(POLARSSL_ECDH_C) + ecdh_free( &handshake->ecdh_ctx ); +#endif + +#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C) + /* explicit void pointer cast for buggy MS compiler */ + polarssl_free( (void *) handshake->curves ); +#endif + +#if defined(POLARSSL_X509_CRT_PARSE_C) && \ + defined(POLARSSL_SSL_SERVER_NAME_INDICATION) + /* + * Free only the linked list wrapper, not the keys themselves + * since the belong to the SNI callback + */ + if( handshake->sni_key_cert != NULL ) + { + ssl_key_cert *cur = handshake->sni_key_cert, *next; + + while( cur != NULL ) + { + next = cur->next; + polarssl_free( cur ); + cur = next; + } + } +#endif /* POLARSSL_X509_CRT_PARSE_C && POLARSSL_SSL_SERVER_NAME_INDICATION */ + + polarssl_zeroize( handshake, sizeof( ssl_handshake_params ) ); +} + +void ssl_session_free( ssl_session *session ) +{ + if( session == NULL ) + return; + +#if defined(POLARSSL_X509_CRT_PARSE_C) + if( session->peer_cert != NULL ) + { + x509_crt_free( session->peer_cert ); + polarssl_free( session->peer_cert ); + } +#endif + +#if defined(POLARSSL_SSL_SESSION_TICKETS) + polarssl_free( session->ticket ); +#endif + + polarssl_zeroize( session, sizeof( ssl_session ) ); +} + +/* + * Free an SSL context + */ +void ssl_free( ssl_context *ssl ) +{ + if( ssl == NULL ) + return; + + SSL_DEBUG_MSG( 2, ( "=> free" ) ); + + if( ssl->out_ctr != NULL ) + { + polarssl_zeroize( ssl->out_ctr, SSL_BUFFER_LEN ); + polarssl_free( ssl->out_ctr ); + } + + if( ssl->in_ctr != NULL ) + { + polarssl_zeroize( ssl->in_ctr, SSL_BUFFER_LEN ); + polarssl_free( ssl->in_ctr ); + } + +#if defined(POLARSSL_ZLIB_SUPPORT) + if( ssl->compress_buf != NULL ) + { + polarssl_zeroize( ssl->compress_buf, SSL_BUFFER_LEN ); + polarssl_free( ssl->compress_buf ); + } +#endif + +#if defined(POLARSSL_DHM_C) + mpi_free( &ssl->dhm_P ); + mpi_free( &ssl->dhm_G ); +#endif + + if( ssl->transform ) + { + ssl_transform_free( ssl->transform ); + polarssl_free( ssl->transform ); + } + + if( ssl->handshake ) + { + ssl_handshake_free( ssl->handshake ); + ssl_transform_free( ssl->transform_negotiate ); + ssl_session_free( ssl->session_negotiate ); + + polarssl_free( ssl->handshake ); + polarssl_free( ssl->transform_negotiate ); + polarssl_free( ssl->session_negotiate ); + } + + if( ssl->session ) + { + ssl_session_free( ssl->session ); + polarssl_free( ssl->session ); + } + +#if defined(POLARSSL_SSL_SESSION_TICKETS) + if( ssl->ticket_keys ) + { + ssl_ticket_keys_free( ssl->ticket_keys ); + polarssl_free( ssl->ticket_keys ); + } +#endif + +#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION) + if( ssl->hostname != NULL ) + { + polarssl_zeroize( ssl->hostname, ssl->hostname_len ); + polarssl_free( ssl->hostname ); + ssl->hostname_len = 0; + } +#endif + +#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED) + if( ssl->psk != NULL ) + { + polarssl_zeroize( ssl->psk, ssl->psk_len ); + polarssl_zeroize( ssl->psk_identity, ssl->psk_identity_len ); + polarssl_free( ssl->psk ); + polarssl_free( ssl->psk_identity ); + ssl->psk_len = 0; + ssl->psk_identity_len = 0; + } +#endif + +#if defined(POLARSSL_X509_CRT_PARSE_C) + ssl_key_cert_free( ssl->key_cert ); +#endif + +#if defined(POLARSSL_SSL_HW_RECORD_ACCEL) + if( ssl_hw_record_finish != NULL ) + { + SSL_DEBUG_MSG( 2, ( "going for ssl_hw_record_finish()" ) ); + ssl_hw_record_finish( ssl ); + } +#endif + + SSL_DEBUG_MSG( 2, ( "<= free" ) ); + + /* Actually clear after last debug message */ + polarssl_zeroize( ssl, sizeof( ssl_context ) ); +} + +#if defined(POLARSSL_PK_C) +/* + * Convert between POLARSSL_PK_XXX and SSL_SIG_XXX + */ +unsigned char ssl_sig_from_pk( pk_context *pk ) +{ +#if defined(POLARSSL_RSA_C) + if( pk_can_do( pk, POLARSSL_PK_RSA ) ) + return( SSL_SIG_RSA ); +#endif +#if defined(POLARSSL_ECDSA_C) + if( pk_can_do( pk, POLARSSL_PK_ECDSA ) ) + return( SSL_SIG_ECDSA ); +#endif + return( SSL_SIG_ANON ); +} + +pk_type_t ssl_pk_alg_from_sig( unsigned char sig ) +{ + switch( sig ) + { +#if defined(POLARSSL_RSA_C) + case SSL_SIG_RSA: + return( POLARSSL_PK_RSA ); +#endif +#if defined(POLARSSL_ECDSA_C) + case SSL_SIG_ECDSA: + return( POLARSSL_PK_ECDSA ); +#endif + default: + return( POLARSSL_PK_NONE ); + } +} +#endif /* POLARSSL_PK_C */ + +/* + * Convert between SSL_HASH_XXX and POLARSSL_MD_XXX + */ +md_type_t ssl_md_alg_from_hash( unsigned char hash ) +{ + switch( hash ) + { +#if defined(POLARSSL_MD5_C) + case SSL_HASH_MD5: + return( POLARSSL_MD_MD5 ); +#endif +#if defined(POLARSSL_SHA1_C) + case SSL_HASH_SHA1: + return( POLARSSL_MD_SHA1 ); +#endif +#if defined(POLARSSL_SHA256_C) + case SSL_HASH_SHA224: + return( POLARSSL_MD_SHA224 ); + case SSL_HASH_SHA256: + return( POLARSSL_MD_SHA256 ); +#endif +#if defined(POLARSSL_SHA512_C) + case SSL_HASH_SHA384: + return( POLARSSL_MD_SHA384 ); + case SSL_HASH_SHA512: + return( POLARSSL_MD_SHA512 ); +#endif + default: + return( POLARSSL_MD_NONE ); + } +} + +#if defined(POLARSSL_SSL_SET_CURVES) +/* + * Check is a curve proposed by the peer is in our list. + * Return 1 if we're willing to use it, 0 otherwise. + */ +int ssl_curve_is_acceptable( const ssl_context *ssl, ecp_group_id grp_id ) +{ + const ecp_group_id *gid; + + for( gid = ssl->curve_list; *gid != POLARSSL_ECP_DP_NONE; gid++ ) + if( *gid == grp_id ) + return( 1 ); + + return( 0 ); +} +#endif /* POLARSSL_SSL_SET_CURVES */ + +#if defined(POLARSSL_X509_CRT_PARSE_C) +int ssl_check_cert_usage( const x509_crt *cert, + const ssl_ciphersuite_t *ciphersuite, + int cert_endpoint ) +{ +#if defined(POLARSSL_X509_CHECK_KEY_USAGE) + int usage = 0; +#endif +#if defined(POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE) + const char *ext_oid; + size_t ext_len; +#endif + +#if !defined(POLARSSL_X509_CHECK_KEY_USAGE) && \ + !defined(POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE) + ((void) cert); + ((void) cert_endpoint); +#endif + +#if defined(POLARSSL_X509_CHECK_KEY_USAGE) + if( cert_endpoint == SSL_IS_SERVER ) + { + /* Server part of the key exchange */ + switch( ciphersuite->key_exchange ) + { + case POLARSSL_KEY_EXCHANGE_RSA: + case POLARSSL_KEY_EXCHANGE_RSA_PSK: + usage = KU_KEY_ENCIPHERMENT; + break; + + case POLARSSL_KEY_EXCHANGE_DHE_RSA: + case POLARSSL_KEY_EXCHANGE_ECDHE_RSA: + case POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA: + usage = KU_DIGITAL_SIGNATURE; + break; + + case POLARSSL_KEY_EXCHANGE_ECDH_RSA: + case POLARSSL_KEY_EXCHANGE_ECDH_ECDSA: + usage = KU_KEY_AGREEMENT; + break; + + /* Don't use default: we want warnings when adding new values */ + case POLARSSL_KEY_EXCHANGE_NONE: + case POLARSSL_KEY_EXCHANGE_PSK: + case POLARSSL_KEY_EXCHANGE_DHE_PSK: + case POLARSSL_KEY_EXCHANGE_ECDHE_PSK: + usage = 0; + } + } + else + { + /* Client auth: we only implement rsa_sign and ecdsa_sign for now */ + usage = KU_DIGITAL_SIGNATURE; + } + + if( x509_crt_check_key_usage( cert, usage ) != 0 ) + return( -1 ); +#else + ((void) ciphersuite); +#endif /* POLARSSL_X509_CHECK_KEY_USAGE */ + +#if defined(POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE) + if( cert_endpoint == SSL_IS_SERVER ) + { + ext_oid = OID_SERVER_AUTH; + ext_len = OID_SIZE( OID_SERVER_AUTH ); + } + else + { + ext_oid = OID_CLIENT_AUTH; + ext_len = OID_SIZE( OID_CLIENT_AUTH ); + } + + if( x509_crt_check_extended_key_usage( cert, ext_oid, ext_len ) != 0 ) + return( -1 ); +#endif /* POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE */ + + return( 0 ); +} +#endif /* POLARSSL_X509_CRT_PARSE_C */ + +#endif /* POLARSSL_SSL_TLS_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/threading.c b/component/common/network/ssl/polarssl-1.3.8/library/threading.c new file mode 100644 index 0000000..522c70f --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/threading.c @@ -0,0 +1,113 @@ +/* + * Threading abstraction layer + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_THREADING_C) + +#include "polarssl/threading.h" + +#if defined(POLARSSL_THREADING_PTHREAD) +static int threading_mutex_init_pthread( threading_mutex_t *mutex ) +{ + if( mutex == NULL ) + return( POLARSSL_ERR_THREADING_BAD_INPUT_DATA ); + + if( pthread_mutex_init( mutex, NULL ) != 0 ) + return( POLARSSL_ERR_THREADING_MUTEX_ERROR ); + + return( 0 ); +} + +static int threading_mutex_free_pthread( threading_mutex_t *mutex ) +{ + if( mutex == NULL ) + return( POLARSSL_ERR_THREADING_BAD_INPUT_DATA ); + + if( pthread_mutex_destroy( mutex ) != 0 ) + return( POLARSSL_ERR_THREADING_MUTEX_ERROR ); + + return( 0 ); +} + +static int threading_mutex_lock_pthread( threading_mutex_t *mutex ) +{ + if( mutex == NULL ) + return( POLARSSL_ERR_THREADING_BAD_INPUT_DATA ); + + if( pthread_mutex_lock( mutex ) != 0 ) + return( POLARSSL_ERR_THREADING_MUTEX_ERROR ); + + return( 0 ); +} + +static int threading_mutex_unlock_pthread( threading_mutex_t *mutex ) +{ + if( mutex == NULL ) + return( POLARSSL_ERR_THREADING_BAD_INPUT_DATA ); + + if( pthread_mutex_unlock( mutex ) != 0 ) + return( POLARSSL_ERR_THREADING_MUTEX_ERROR ); + + return( 0 ); +} + +int (*polarssl_mutex_init)( threading_mutex_t * ) = threading_mutex_init_pthread; +int (*polarssl_mutex_free)( threading_mutex_t * ) = threading_mutex_free_pthread; +int (*polarssl_mutex_lock)( threading_mutex_t * ) = threading_mutex_lock_pthread; +int (*polarssl_mutex_unlock)( threading_mutex_t * ) = threading_mutex_unlock_pthread; +#endif /* POLARSSL_THREADING_PTHREAD */ + +#if defined(POLARSSL_THREADING_ALT) +static int threading_mutex_fail( threading_mutex_t *mutex ) +{ + ((void) mutex ); + return( POLARSSL_ERR_THREADING_BAD_INPUT_DATA ); +} + +int (*polarssl_mutex_init)( threading_mutex_t * ) = threading_mutex_fail; +int (*polarssl_mutex_free)( threading_mutex_t * ) = threading_mutex_fail; +int (*polarssl_mutex_lock)( threading_mutex_t * ) = threading_mutex_fail; +int (*polarssl_mutex_unlock)( threading_mutex_t * ) = threading_mutex_fail; + +int threading_set_alt( int (*mutex_init)( threading_mutex_t * ), + int (*mutex_free)( threading_mutex_t * ), + int (*mutex_lock)( threading_mutex_t * ), + int (*mutex_unlock)( threading_mutex_t * ) ) +{ + polarssl_mutex_init = mutex_init; + polarssl_mutex_free = mutex_free; + polarssl_mutex_lock = mutex_lock; + polarssl_mutex_unlock = mutex_unlock; + + return( 0 ); +} +#endif /* POLARSSL_THREADING_ALT_C */ + +#endif /* POLARSSL_THREADING_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/timing.c b/component/common/network/ssl/polarssl-1.3.8/library/timing.c new file mode 100644 index 0000000..6c1dfa4 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/timing.c @@ -0,0 +1,500 @@ +/* + * Portable interface to the CPU cycle counter + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_SELF_TEST) && defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include +#define polarssl_printf printf +#endif + +#if defined(POLARSSL_TIMING_C) && !defined(POLARSSL_TIMING_ALT) + +#include "polarssl/timing.h" + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + +#include +#include + +struct _hr_time +{ + LARGE_INTEGER start; +}; + +#else + +#include +#include +#include +#include +#include + +struct _hr_time +{ + struct timeval start; +}; + +#endif /* _WIN32 && !EFIX64 && !EFI32 */ + +#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \ + ( defined(_MSC_VER) && defined(_M_IX86) ) || defined(__WATCOMC__) + +#define POLARSSL_HAVE_HARDCLOCK + +unsigned long hardclock( void ) +{ + unsigned long tsc; + __asm rdtsc + __asm mov [tsc], eax + return( tsc ); +} +#endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM && + ( _MSC_VER && _M_IX86 ) || __WATCOMC__ */ + +#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \ + defined(__GNUC__) && defined(__i386__) + +#define POLARSSL_HAVE_HARDCLOCK + +unsigned long hardclock( void ) +{ + unsigned long lo, hi; + asm volatile( "rdtsc" : "=a" (lo), "=d" (hi) ); + return( lo ); +} +#endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM && + __GNUC__ && __i386__ */ + +#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \ + defined(__GNUC__) && ( defined(__amd64__) || defined(__x86_64__) ) + +#define POLARSSL_HAVE_HARDCLOCK + +unsigned long hardclock( void ) +{ + unsigned long lo, hi; + asm volatile( "rdtsc" : "=a" (lo), "=d" (hi) ); + return( lo | ( hi << 32 ) ); +} +#endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM && + __GNUC__ && ( __amd64__ || __x86_64__ ) */ + +#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \ + defined(__GNUC__) && ( defined(__powerpc__) || defined(__ppc__) ) + +#define POLARSSL_HAVE_HARDCLOCK + +unsigned long hardclock( void ) +{ + unsigned long tbl, tbu0, tbu1; + + do + { + asm volatile( "mftbu %0" : "=r" (tbu0) ); + asm volatile( "mftb %0" : "=r" (tbl ) ); + asm volatile( "mftbu %0" : "=r" (tbu1) ); + } + while( tbu0 != tbu1 ); + + return( tbl ); +} +#endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM && + __GNUC__ && ( __powerpc__ || __ppc__ ) */ + +#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \ + defined(__GNUC__) && defined(__sparc64__) + +#if defined(__OpenBSD__) +#warning OpenBSD does not allow access to tick register using software version instead +#else +#define POLARSSL_HAVE_HARDCLOCK + +unsigned long hardclock( void ) +{ + unsigned long tick; + asm volatile( "rdpr %%tick, %0;" : "=&r" (tick) ); + return( tick ); +} +#endif /* __OpenBSD__ */ +#endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM && + __GNUC__ && __sparc64__ */ + +#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \ + defined(__GNUC__) && defined(__sparc__) && !defined(__sparc64__) + +#define POLARSSL_HAVE_HARDCLOCK + +unsigned long hardclock( void ) +{ + unsigned long tick; + asm volatile( ".byte 0x83, 0x41, 0x00, 0x00" ); + asm volatile( "mov %%g1, %0" : "=r" (tick) ); + return( tick ); +} +#endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM && + __GNUC__ && __sparc__ && !__sparc64__ */ + +#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \ + defined(__GNUC__) && defined(__alpha__) + +#define POLARSSL_HAVE_HARDCLOCK + +unsigned long hardclock( void ) +{ + unsigned long cc; + asm volatile( "rpcc %0" : "=r" (cc) ); + return( cc & 0xFFFFFFFF ); +} +#endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM && + __GNUC__ && __alpha__ */ + +#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \ + defined(__GNUC__) && defined(__ia64__) + +#define POLARSSL_HAVE_HARDCLOCK + +unsigned long hardclock( void ) +{ + unsigned long itc; + asm volatile( "mov %0 = ar.itc" : "=r" (itc) ); + return( itc ); +} +#endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM && + __GNUC__ && __ia64__ */ + +#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(_MSC_VER) && \ + !defined(EFIX64) && !defined(EFI32) + +#define POLARSSL_HAVE_HARDCLOCK + +unsigned long hardclock( void ) +{ + LARGE_INTEGER offset; + + QueryPerformanceCounter( &offset ); + + return( (unsigned long)( offset.QuadPart ) ); +} +#endif /* !POLARSSL_HAVE_HARDCLOCK && _MSC_VER && !EFIX64 && !EFI32 */ + +#if !defined(POLARSSL_HAVE_HARDCLOCK) + +#define POLARSSL_HAVE_HARDCLOCK + +static int hardclock_init = 0; +static struct timeval tv_init; + +unsigned long hardclock( void ) +{ + struct timeval tv_cur; + + if( hardclock_init == 0 ) + { + gettimeofday( &tv_init, NULL ); + hardclock_init = 1; + } + + gettimeofday( &tv_cur, NULL ); + return( ( tv_cur.tv_sec - tv_init.tv_sec ) * 1000000 + + ( tv_cur.tv_usec - tv_init.tv_usec ) ); +} +#endif /* !POLARSSL_HAVE_HARDCLOCK */ + +volatile int alarmed = 0; + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + +unsigned long get_timer( struct hr_time *val, int reset ) +{ + unsigned long delta; + LARGE_INTEGER offset, hfreq; + struct _hr_time *t = (struct _hr_time *) val; + + QueryPerformanceCounter( &offset ); + QueryPerformanceFrequency( &hfreq ); + + delta = (unsigned long)( ( 1000 * + ( offset.QuadPart - t->start.QuadPart ) ) / + hfreq.QuadPart ); + + if( reset ) + QueryPerformanceCounter( &t->start ); + + return( delta ); +} + +DWORD WINAPI TimerProc( LPVOID uElapse ) +{ + Sleep( (DWORD) uElapse ); + alarmed = 1; + return( TRUE ); +} + +void set_alarm( int seconds ) +{ + DWORD ThreadId; + + alarmed = 0; + CloseHandle( CreateThread( NULL, 0, TimerProc, + (LPVOID) ( seconds * 1000 ), 0, &ThreadId ) ); +} + +void m_sleep( int milliseconds ) +{ + Sleep( milliseconds ); +} + +#else /* _WIN32 && !EFIX64 && !EFI32 */ + +unsigned long get_timer( struct hr_time *val, int reset ) +{ + unsigned long delta; + struct timeval offset; + struct _hr_time *t = (struct _hr_time *) val; + + gettimeofday( &offset, NULL ); + + delta = ( offset.tv_sec - t->start.tv_sec ) * 1000 + + ( offset.tv_usec - t->start.tv_usec ) / 1000; + + if( reset ) + { + t->start.tv_sec = offset.tv_sec; + t->start.tv_usec = offset.tv_usec; + } + + return( delta ); +} + +#if defined(INTEGRITY) +void m_sleep( int milliseconds ) +{ + usleep( milliseconds * 1000 ); +} + +#else /* INTEGRITY */ + +static void sighandler( int signum ) +{ + alarmed = 1; + signal( signum, sighandler ); +} + +void set_alarm( int seconds ) +{ + alarmed = 0; + signal( SIGALRM, sighandler ); + alarm( seconds ); +} + +void m_sleep( int milliseconds ) +{ + struct timeval tv; + + tv.tv_sec = milliseconds / 1000; + tv.tv_usec = ( milliseconds % 1000 ) * 1000; + + select( 0, NULL, NULL, NULL, &tv ); +} +#endif /* INTEGRITY */ + +#endif /* _WIN32 && !EFIX64 && !EFI32 */ + +#if defined(POLARSSL_SELF_TEST) + +/* To test net_usleep against our functions */ +#if defined(POLARSSL_NET_C) +#include "polarssl/net.h" +#endif + +/* + * Busy-waits for the given number of milliseconds. + * Used for testing hardclock. + */ +static void busy_msleep( unsigned long msec ) +{ + struct hr_time hires; + unsigned long i = 0; /* for busy-waiting */ + volatile unsigned long j; /* to prevent optimisation */ + + (void) get_timer( &hires, 1 ); + + while( get_timer( &hires, 0 ) < msec ) + i++; + + j = i; + (void) j; +} + +/* + * Checkup routine + * + * Warning: this is work in progress, some tests may not be reliable enough + * yet! False positives may happen. + */ +int timing_self_test( int verbose ) +{ + unsigned long cycles, ratio; + unsigned long millisecs, secs; + int hardfail; + struct hr_time hires; + + if( verbose != 0 ) + polarssl_printf( " TIMING tests note: will take some time!\n" ); + + if( verbose != 0 ) + polarssl_printf( " TIMING test #1 (m_sleep / get_timer): " ); + + for( secs = 1; secs <= 3; secs++ ) + { + (void) get_timer( &hires, 1 ); + + m_sleep( 500 * secs ); + + millisecs = get_timer( &hires, 0 ); + + if( millisecs < 450 * secs || millisecs > 550 * secs ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + + if( verbose != 0 ) + polarssl_printf( " TIMING test #2 (set_alarm / get_timer): " ); + + for( secs = 1; secs <= 3; secs++ ) + { + (void) get_timer( &hires, 1 ); + + set_alarm( secs ); + while( !alarmed ) + ; + + millisecs = get_timer( &hires, 0 ); + + if( millisecs < 900 * secs || millisecs > 1100 * secs ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + + if( verbose != 0 ) + polarssl_printf( " TIMING test #3 (hardclock / get_timer): " ); + + /* + * Allow one failure for possible counter wrapping. + * On a 4Ghz 32-bit machine the cycle counter wraps about once per second; + * since the whole test is about 10ms, it shouldn't happen twice in a row. + */ + hardfail = 0; + +hard_test: + if( hardfail > 1 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + /* Get a reference ratio cycles/ms */ + millisecs = 1; + cycles = hardclock(); + busy_msleep( millisecs ); + cycles = hardclock() - cycles; + ratio = cycles / millisecs; + + /* Check that the ratio is mostly constant */ + for( millisecs = 2; millisecs <= 4; millisecs++ ) + { + cycles = hardclock(); + busy_msleep( millisecs ); + cycles = hardclock() - cycles; + + /* Allow variation up to 20% */ + if( cycles / millisecs < ratio - ratio / 5 || + cycles / millisecs > ratio + ratio / 5 ) + { + hardfail++; + goto hard_test; + } + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + +#if defined(POLARSSL_NET_C) + if( verbose != 0 ) + polarssl_printf( " TIMING test #4 (net_usleep/ get_timer): " ); + + for( secs = 1; secs <= 3; secs++ ) + { + (void) get_timer( &hires, 1 ); + + net_usleep( 500000 * secs ); + + millisecs = get_timer( &hires, 0 ); + + if( millisecs < 450 * secs || millisecs > 550 * secs ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); +#endif /* POLARSSL_NET_C */ + + if( verbose != 0 ) + polarssl_printf( "\n" ); + + return( 0 ); +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_TIMING_C && !POLARSSL_TIMING_ALT */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/version.c b/component/common/network/ssl/polarssl-1.3.8/library/version.c new file mode 100644 index 0000000..c3c708a --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/version.c @@ -0,0 +1,56 @@ +/* + * Version information + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_VERSION_C) + +#include "polarssl/version.h" +#include + +const char version[] = POLARSSL_VERSION_STRING; + +unsigned int version_get_number() +{ + return( POLARSSL_VERSION_NUMBER ); +} + +void version_get_string( char *string ) +{ + memcpy( string, POLARSSL_VERSION_STRING, + sizeof( POLARSSL_VERSION_STRING ) ); +} + +void version_get_string_full( char *string ) +{ + memcpy( string, POLARSSL_VERSION_STRING_FULL, + sizeof( POLARSSL_VERSION_STRING_FULL ) ); +} + +#endif /* POLARSSL_VERSION_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/version_features.c b/component/common/network/ssl/polarssl-1.3.8/library/version_features.c new file mode 100644 index 0000000..1023198 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/version_features.c @@ -0,0 +1,560 @@ +/* + * Version feature information + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_VERSION_C) + +#include "polarssl/version.h" + +#include + +#if defined(_MSC_VER) && !defined strcasecmp && !defined(EFIX64) && \ + !defined(EFI32) +#define strcasecmp _stricmp +#endif + +const char *features[] = { +#if defined(POLARSSL_VERSION_FEATURES) +#if defined(POLARSSL_HAVE_INT8) + "POLARSSL_HAVE_INT8", +#endif /* POLARSSL_HAVE_INT8 */ +#if defined(POLARSSL_HAVE_INT16) + "POLARSSL_HAVE_INT16", +#endif /* POLARSSL_HAVE_INT16 */ +#if defined(POLARSSL_HAVE_LONGLONG) + "POLARSSL_HAVE_LONGLONG", +#endif /* POLARSSL_HAVE_LONGLONG */ +#if defined(POLARSSL_HAVE_ASM) + "POLARSSL_HAVE_ASM", +#endif /* POLARSSL_HAVE_ASM */ +#if defined(POLARSSL_HAVE_SSE2) + "POLARSSL_HAVE_SSE2", +#endif /* POLARSSL_HAVE_SSE2 */ +#if defined(POLARSSL_HAVE_TIME) + "POLARSSL_HAVE_TIME", +#endif /* POLARSSL_HAVE_TIME */ +#if defined(POLARSSL_HAVE_IPV6) + "POLARSSL_HAVE_IPV6", +#endif /* POLARSSL_HAVE_IPV6 */ +#if defined(POLARSSL_PLATFORM_MEMORY) + "POLARSSL_PLATFORM_MEMORY", +#endif /* POLARSSL_PLATFORM_MEMORY */ +#if defined(POLARSSL_PLATFORM_NO_STD_FUNCTIONS) + "POLARSSL_PLATFORM_NO_STD_FUNCTIONS", +#endif /* POLARSSL_PLATFORM_NO_STD_FUNCTIONS */ +#if defined(POLARSSL_PLATFORM_PRINTF_ALT) + "POLARSSL_PLATFORM_PRINTF_ALT", +#endif /* POLARSSL_PLATFORM_PRINTF_ALT */ +#if defined(POLARSSL_PLATFORM_FPRINTF_ALT) + "POLARSSL_PLATFORM_FPRINTF_ALT", +#endif /* POLARSSL_PLATFORM_FPRINTF_ALT */ +#if defined(POLARSSL_TIMING_ALT) + "POLARSSL_TIMING_ALT", +#endif /* POLARSSL_TIMING_ALT */ +#if defined(POLARSSL_AES_ALT) + "POLARSSL_AES_ALT", +#endif /* POLARSSL_AES_ALT */ +#if defined(POLARSSL_ARC4_ALT) + "POLARSSL_ARC4_ALT", +#endif /* POLARSSL_ARC4_ALT */ +#if defined(POLARSSL_BLOWFISH_ALT) + "POLARSSL_BLOWFISH_ALT", +#endif /* POLARSSL_BLOWFISH_ALT */ +#if defined(POLARSSL_CAMELLIA_ALT) + "POLARSSL_CAMELLIA_ALT", +#endif /* POLARSSL_CAMELLIA_ALT */ +#if defined(POLARSSL_DES_ALT) + "POLARSSL_DES_ALT", +#endif /* POLARSSL_DES_ALT */ +#if defined(POLARSSL_XTEA_ALT) + "POLARSSL_XTEA_ALT", +#endif /* POLARSSL_XTEA_ALT */ +#if defined(POLARSSL_MD2_ALT) + "POLARSSL_MD2_ALT", +#endif /* POLARSSL_MD2_ALT */ +#if defined(POLARSSL_MD4_ALT) + "POLARSSL_MD4_ALT", +#endif /* POLARSSL_MD4_ALT */ +#if defined(POLARSSL_MD5_ALT) + "POLARSSL_MD5_ALT", +#endif /* POLARSSL_MD5_ALT */ +#if defined(POLARSSL_RIPEMD160_ALT) + "POLARSSL_RIPEMD160_ALT", +#endif /* POLARSSL_RIPEMD160_ALT */ +#if defined(POLARSSL_SHA1_ALT) + "POLARSSL_SHA1_ALT", +#endif /* POLARSSL_SHA1_ALT */ +#if defined(POLARSSL_SHA256_ALT) + "POLARSSL_SHA256_ALT", +#endif /* POLARSSL_SHA256_ALT */ +#if defined(POLARSSL_SHA512_ALT) + "POLARSSL_SHA512_ALT", +#endif /* POLARSSL_SHA512_ALT */ +#if defined(POLARSSL_AES_ROM_TABLES) + "POLARSSL_AES_ROM_TABLES", +#endif /* POLARSSL_AES_ROM_TABLES */ +#if defined(POLARSSL_CIPHER_MODE_CBC) + "POLARSSL_CIPHER_MODE_CBC", +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#if defined(POLARSSL_CIPHER_MODE_CFB) + "POLARSSL_CIPHER_MODE_CFB", +#endif /* POLARSSL_CIPHER_MODE_CFB */ +#if defined(POLARSSL_CIPHER_MODE_CTR) + "POLARSSL_CIPHER_MODE_CTR", +#endif /* POLARSSL_CIPHER_MODE_CTR */ +#if defined(POLARSSL_CIPHER_NULL_CIPHER) + "POLARSSL_CIPHER_NULL_CIPHER", +#endif /* POLARSSL_CIPHER_NULL_CIPHER */ +#if defined(POLARSSL_CIPHER_PADDING_PKCS7) + "POLARSSL_CIPHER_PADDING_PKCS7", +#endif /* POLARSSL_CIPHER_PADDING_PKCS7 */ +#if defined(POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS) + "POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS", +#endif /* POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS */ +#if defined(POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN) + "POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN", +#endif /* POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN */ +#if defined(POLARSSL_CIPHER_PADDING_ZEROS) + "POLARSSL_CIPHER_PADDING_ZEROS", +#endif /* POLARSSL_CIPHER_PADDING_ZEROS */ +#if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES) + "POLARSSL_ENABLE_WEAK_CIPHERSUITES", +#endif /* POLARSSL_ENABLE_WEAK_CIPHERSUITES */ +#if defined(POLARSSL_REMOVE_ARC4_CIPHERSUITES) + "POLARSSL_REMOVE_ARC4_CIPHERSUITES", +#endif /* POLARSSL_REMOVE_ARC4_CIPHERSUITES */ +#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED) + "POLARSSL_ECP_DP_SECP192R1_ENABLED", +#endif /* POLARSSL_ECP_DP_SECP192R1_ENABLED */ +#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED) + "POLARSSL_ECP_DP_SECP224R1_ENABLED", +#endif /* POLARSSL_ECP_DP_SECP224R1_ENABLED */ +#if defined(POLARSSL_ECP_DP_SECP256R1_ENABLED) + "POLARSSL_ECP_DP_SECP256R1_ENABLED", +#endif /* POLARSSL_ECP_DP_SECP256R1_ENABLED */ +#if defined(POLARSSL_ECP_DP_SECP384R1_ENABLED) + "POLARSSL_ECP_DP_SECP384R1_ENABLED", +#endif /* POLARSSL_ECP_DP_SECP384R1_ENABLED */ +#if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED) + "POLARSSL_ECP_DP_SECP521R1_ENABLED", +#endif /* POLARSSL_ECP_DP_SECP521R1_ENABLED */ +#if defined(POLARSSL_ECP_DP_SECP192K1_ENABLED) + "POLARSSL_ECP_DP_SECP192K1_ENABLED", +#endif /* POLARSSL_ECP_DP_SECP192K1_ENABLED */ +#if defined(POLARSSL_ECP_DP_SECP224K1_ENABLED) + "POLARSSL_ECP_DP_SECP224K1_ENABLED", +#endif /* POLARSSL_ECP_DP_SECP224K1_ENABLED */ +#if defined(POLARSSL_ECP_DP_SECP256K1_ENABLED) + "POLARSSL_ECP_DP_SECP256K1_ENABLED", +#endif /* POLARSSL_ECP_DP_SECP256K1_ENABLED */ +#if defined(POLARSSL_ECP_DP_BP256R1_ENABLED) + "POLARSSL_ECP_DP_BP256R1_ENABLED", +#endif /* POLARSSL_ECP_DP_BP256R1_ENABLED */ +#if defined(POLARSSL_ECP_DP_BP384R1_ENABLED) + "POLARSSL_ECP_DP_BP384R1_ENABLED", +#endif /* POLARSSL_ECP_DP_BP384R1_ENABLED */ +#if defined(POLARSSL_ECP_DP_BP512R1_ENABLED) + "POLARSSL_ECP_DP_BP512R1_ENABLED", +#endif /* POLARSSL_ECP_DP_BP512R1_ENABLED */ +#if defined(POLARSSL_ECP_DP_M221_ENABLED) + "POLARSSL_ECP_DP_M221_ENABLED", +#endif /* POLARSSL_ECP_DP_M221_ENABLED */ +#if defined(POLARSSL_ECP_DP_M255_ENABLED) + "POLARSSL_ECP_DP_M255_ENABLED", +#endif /* POLARSSL_ECP_DP_M255_ENABLED */ +#if defined(POLARSSL_ECP_DP_M383_ENABLED) + "POLARSSL_ECP_DP_M383_ENABLED", +#endif /* POLARSSL_ECP_DP_M383_ENABLED */ +#if defined(POLARSSL_ECP_DP_M511_ENABLED) + "POLARSSL_ECP_DP_M511_ENABLED", +#endif /* POLARSSL_ECP_DP_M511_ENABLED */ +#if defined(POLARSSL_ECP_NIST_OPTIM) + "POLARSSL_ECP_NIST_OPTIM", +#endif /* POLARSSL_ECP_NIST_OPTIM */ +#if defined(POLARSSL_ECDSA_DETERMINISTIC) + "POLARSSL_ECDSA_DETERMINISTIC", +#endif /* POLARSSL_ECDSA_DETERMINISTIC */ +#if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) + "POLARSSL_KEY_EXCHANGE_PSK_ENABLED", +#endif /* POLARSSL_KEY_EXCHANGE_PSK_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) + "POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED", +#endif /* POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + "POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED", +#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) + "POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED", +#endif /* POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) + "POLARSSL_KEY_EXCHANGE_RSA_ENABLED", +#endif /* POLARSSL_KEY_EXCHANGE_RSA_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) + "POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED", +#endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) + "POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED", +#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + "POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED", +#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + "POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED", +#endif /* POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ +#if defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) + "POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED", +#endif /* POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED */ +#if defined(POLARSSL_PK_PARSE_EC_EXTENDED) + "POLARSSL_PK_PARSE_EC_EXTENDED", +#endif /* POLARSSL_PK_PARSE_EC_EXTENDED */ +#if defined(POLARSSL_ERROR_STRERROR_BC) + "POLARSSL_ERROR_STRERROR_BC", +#endif /* POLARSSL_ERROR_STRERROR_BC */ +#if defined(POLARSSL_ERROR_STRERROR_DUMMY) + "POLARSSL_ERROR_STRERROR_DUMMY", +#endif /* POLARSSL_ERROR_STRERROR_DUMMY */ +#if defined(POLARSSL_GENPRIME) + "POLARSSL_GENPRIME", +#endif /* POLARSSL_GENPRIME */ +#if defined(POLARSSL_FS_IO) + "POLARSSL_FS_IO", +#endif /* POLARSSL_FS_IO */ +#if defined(POLARSSL_NO_DEFAULT_ENTROPY_SOURCES) + "POLARSSL_NO_DEFAULT_ENTROPY_SOURCES", +#endif /* POLARSSL_NO_DEFAULT_ENTROPY_SOURCES */ +#if defined(POLARSSL_NO_PLATFORM_ENTROPY) + "POLARSSL_NO_PLATFORM_ENTROPY", +#endif /* POLARSSL_NO_PLATFORM_ENTROPY */ +#if defined(POLARSSL_ENTROPY_FORCE_SHA256) + "POLARSSL_ENTROPY_FORCE_SHA256", +#endif /* POLARSSL_ENTROPY_FORCE_SHA256 */ +#if defined(POLARSSL_MEMORY_DEBUG) + "POLARSSL_MEMORY_DEBUG", +#endif /* POLARSSL_MEMORY_DEBUG */ +#if defined(POLARSSL_MEMORY_BACKTRACE) + "POLARSSL_MEMORY_BACKTRACE", +#endif /* POLARSSL_MEMORY_BACKTRACE */ +#if defined(POLARSSL_PKCS1_V15) + "POLARSSL_PKCS1_V15", +#endif /* POLARSSL_PKCS1_V15 */ +#if defined(POLARSSL_PKCS1_V21) + "POLARSSL_PKCS1_V21", +#endif /* POLARSSL_PKCS1_V21 */ +#if defined(POLARSSL_RSA_NO_CRT) + "POLARSSL_RSA_NO_CRT", +#endif /* POLARSSL_RSA_NO_CRT */ +#if defined(POLARSSL_SELF_TEST) + "POLARSSL_SELF_TEST", +#endif /* POLARSSL_SELF_TEST */ +#if defined(POLARSSL_SSL_ALERT_MESSAGES) + "POLARSSL_SSL_ALERT_MESSAGES", +#endif /* POLARSSL_SSL_ALERT_MESSAGES */ +#if defined(POLARSSL_SSL_DEBUG_ALL) + "POLARSSL_SSL_DEBUG_ALL", +#endif /* POLARSSL_SSL_DEBUG_ALL */ +#if defined(POLARSSL_SSL_HW_RECORD_ACCEL) + "POLARSSL_SSL_HW_RECORD_ACCEL", +#endif /* POLARSSL_SSL_HW_RECORD_ACCEL */ +#if defined(POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) + "POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO", +#endif /* POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */ +#if defined(POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE) + "POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE", +#endif /* POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE */ +#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH) + "POLARSSL_SSL_MAX_FRAGMENT_LENGTH", +#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */ +#if defined(POLARSSL_SSL_PROTO_SSL3) + "POLARSSL_SSL_PROTO_SSL3", +#endif /* POLARSSL_SSL_PROTO_SSL3 */ +#if defined(POLARSSL_SSL_PROTO_TLS1) + "POLARSSL_SSL_PROTO_TLS1", +#endif /* POLARSSL_SSL_PROTO_TLS1 */ +#if defined(POLARSSL_SSL_PROTO_TLS1_1) + "POLARSSL_SSL_PROTO_TLS1_1", +#endif /* POLARSSL_SSL_PROTO_TLS1_1 */ +#if defined(POLARSSL_SSL_PROTO_TLS1_2) + "POLARSSL_SSL_PROTO_TLS1_2", +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ +#if defined(POLARSSL_SSL_ALPN) + "POLARSSL_SSL_ALPN", +#endif /* POLARSSL_SSL_ALPN */ +#if defined(POLARSSL_SSL_SESSION_TICKETS) + "POLARSSL_SSL_SESSION_TICKETS", +#endif /* POLARSSL_SSL_SESSION_TICKETS */ +#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION) + "POLARSSL_SSL_SERVER_NAME_INDICATION", +#endif /* POLARSSL_SSL_SERVER_NAME_INDICATION */ +#if defined(POLARSSL_SSL_TRUNCATED_HMAC) + "POLARSSL_SSL_TRUNCATED_HMAC", +#endif /* POLARSSL_SSL_TRUNCATED_HMAC */ +#if defined(POLARSSL_SSL_SET_CURVES) + "POLARSSL_SSL_SET_CURVES", +#endif /* POLARSSL_SSL_SET_CURVES */ +#if defined(POLARSSL_THREADING_ALT) + "POLARSSL_THREADING_ALT", +#endif /* POLARSSL_THREADING_ALT */ +#if defined(POLARSSL_THREADING_PTHREAD) + "POLARSSL_THREADING_PTHREAD", +#endif /* POLARSSL_THREADING_PTHREAD */ +#if defined(POLARSSL_VERSION_FEATURES) + "POLARSSL_VERSION_FEATURES", +#endif /* POLARSSL_VERSION_FEATURES */ +#if defined(POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3) + "POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3", +#endif /* POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3 */ +#if defined(POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION) + "POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION", +#endif /* POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION */ +#if defined(POLARSSL_X509_CHECK_KEY_USAGE) + "POLARSSL_X509_CHECK_KEY_USAGE", +#endif /* POLARSSL_X509_CHECK_KEY_USAGE */ +#if defined(POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE) + "POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE", +#endif /* POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE */ +#if defined(POLARSSL_X509_RSASSA_PSS_SUPPORT) + "POLARSSL_X509_RSASSA_PSS_SUPPORT", +#endif /* POLARSSL_X509_RSASSA_PSS_SUPPORT */ +#if defined(POLARSSL_ZLIB_SUPPORT) + "POLARSSL_ZLIB_SUPPORT", +#endif /* POLARSSL_ZLIB_SUPPORT */ +#if defined(POLARSSL_AESNI_C) + "POLARSSL_AESNI_C", +#endif /* POLARSSL_AESNI_C */ +#if defined(POLARSSL_AES_C) + "POLARSSL_AES_C", +#endif /* POLARSSL_AES_C */ +#if defined(POLARSSL_ARC4_C) + "POLARSSL_ARC4_C", +#endif /* POLARSSL_ARC4_C */ +#if defined(POLARSSL_ASN1_PARSE_C) + "POLARSSL_ASN1_PARSE_C", +#endif /* POLARSSL_ASN1_PARSE_C */ +#if defined(POLARSSL_ASN1_WRITE_C) + "POLARSSL_ASN1_WRITE_C", +#endif /* POLARSSL_ASN1_WRITE_C */ +#if defined(POLARSSL_BASE64_C) + "POLARSSL_BASE64_C", +#endif /* POLARSSL_BASE64_C */ +#if defined(POLARSSL_BIGNUM_C) + "POLARSSL_BIGNUM_C", +#endif /* POLARSSL_BIGNUM_C */ +#if defined(POLARSSL_BLOWFISH_C) + "POLARSSL_BLOWFISH_C", +#endif /* POLARSSL_BLOWFISH_C */ +#if defined(POLARSSL_CAMELLIA_C) + "POLARSSL_CAMELLIA_C", +#endif /* POLARSSL_CAMELLIA_C */ +#if defined(POLARSSL_CCM_C) + "POLARSSL_CCM_C", +#endif /* POLARSSL_CCM_C */ +#if defined(POLARSSL_CERTS_C) + "POLARSSL_CERTS_C", +#endif /* POLARSSL_CERTS_C */ +#if defined(POLARSSL_CIPHER_C) + "POLARSSL_CIPHER_C", +#endif /* POLARSSL_CIPHER_C */ +#if defined(POLARSSL_CTR_DRBG_C) + "POLARSSL_CTR_DRBG_C", +#endif /* POLARSSL_CTR_DRBG_C */ +#if defined(POLARSSL_DEBUG_C) + "POLARSSL_DEBUG_C", +#endif /* POLARSSL_DEBUG_C */ +#if defined(POLARSSL_DES_C) + "POLARSSL_DES_C", +#endif /* POLARSSL_DES_C */ +#if defined(POLARSSL_DHM_C) + "POLARSSL_DHM_C", +#endif /* POLARSSL_DHM_C */ +#if defined(POLARSSL_ECDH_C) + "POLARSSL_ECDH_C", +#endif /* POLARSSL_ECDH_C */ +#if defined(POLARSSL_ECDSA_C) + "POLARSSL_ECDSA_C", +#endif /* POLARSSL_ECDSA_C */ +#if defined(POLARSSL_ECP_C) + "POLARSSL_ECP_C", +#endif /* POLARSSL_ECP_C */ +#if defined(POLARSSL_ENTROPY_C) + "POLARSSL_ENTROPY_C", +#endif /* POLARSSL_ENTROPY_C */ +#if defined(POLARSSL_ERROR_C) + "POLARSSL_ERROR_C", +#endif /* POLARSSL_ERROR_C */ +#if defined(POLARSSL_GCM_C) + "POLARSSL_GCM_C", +#endif /* POLARSSL_GCM_C */ +#if defined(POLARSSL_HAVEGE_C) + "POLARSSL_HAVEGE_C", +#endif /* POLARSSL_HAVEGE_C */ +#if defined(POLARSSL_HMAC_DRBG_C) + "POLARSSL_HMAC_DRBG_C", +#endif /* POLARSSL_HMAC_DRBG_C */ +#if defined(POLARSSL_MD_C) + "POLARSSL_MD_C", +#endif /* POLARSSL_MD_C */ +#if defined(POLARSSL_MD2_C) + "POLARSSL_MD2_C", +#endif /* POLARSSL_MD2_C */ +#if defined(POLARSSL_MD4_C) + "POLARSSL_MD4_C", +#endif /* POLARSSL_MD4_C */ +#if defined(POLARSSL_MD5_C) + "POLARSSL_MD5_C", +#endif /* POLARSSL_MD5_C */ +#if defined(POLARSSL_MEMORY_C) + "POLARSSL_MEMORY_C", +#endif /* POLARSSL_MEMORY_C */ +#if defined(POLARSSL_MEMORY_BUFFER_ALLOC_C) + "POLARSSL_MEMORY_BUFFER_ALLOC_C", +#endif /* POLARSSL_MEMORY_BUFFER_ALLOC_C */ +#if defined(POLARSSL_NET_C) + "POLARSSL_NET_C", +#endif /* POLARSSL_NET_C */ +#if defined(POLARSSL_OID_C) + "POLARSSL_OID_C", +#endif /* POLARSSL_OID_C */ +#if defined(POLARSSL_PADLOCK_C) + "POLARSSL_PADLOCK_C", +#endif /* POLARSSL_PADLOCK_C */ +#if defined(POLARSSL_PBKDF2_C) + "POLARSSL_PBKDF2_C", +#endif /* POLARSSL_PBKDF2_C */ +#if defined(POLARSSL_PEM_PARSE_C) + "POLARSSL_PEM_PARSE_C", +#endif /* POLARSSL_PEM_PARSE_C */ +#if defined(POLARSSL_PEM_WRITE_C) + "POLARSSL_PEM_WRITE_C", +#endif /* POLARSSL_PEM_WRITE_C */ +#if defined(POLARSSL_PK_C) + "POLARSSL_PK_C", +#endif /* POLARSSL_PK_C */ +#if defined(POLARSSL_PK_PARSE_C) + "POLARSSL_PK_PARSE_C", +#endif /* POLARSSL_PK_PARSE_C */ +#if defined(POLARSSL_PK_WRITE_C) + "POLARSSL_PK_WRITE_C", +#endif /* POLARSSL_PK_WRITE_C */ +#if defined(POLARSSL_PKCS5_C) + "POLARSSL_PKCS5_C", +#endif /* POLARSSL_PKCS5_C */ +#if defined(POLARSSL_PKCS11_C) + "POLARSSL_PKCS11_C", +#endif /* POLARSSL_PKCS11_C */ +#if defined(POLARSSL_PKCS12_C) + "POLARSSL_PKCS12_C", +#endif /* POLARSSL_PKCS12_C */ +#if defined(POLARSSL_PLATFORM_C) + "POLARSSL_PLATFORM_C", +#endif /* POLARSSL_PLATFORM_C */ +#if defined(POLARSSL_RIPEMD160_C) + "POLARSSL_RIPEMD160_C", +#endif /* POLARSSL_RIPEMD160_C */ +#if defined(POLARSSL_RSA_C) + "POLARSSL_RSA_C", +#endif /* POLARSSL_RSA_C */ +#if defined(POLARSSL_SHA1_C) + "POLARSSL_SHA1_C", +#endif /* POLARSSL_SHA1_C */ +#if defined(POLARSSL_SHA256_C) + "POLARSSL_SHA256_C", +#endif /* POLARSSL_SHA256_C */ +#if defined(POLARSSL_SHA512_C) + "POLARSSL_SHA512_C", +#endif /* POLARSSL_SHA512_C */ +#if defined(POLARSSL_SSL_CACHE_C) + "POLARSSL_SSL_CACHE_C", +#endif /* POLARSSL_SSL_CACHE_C */ +#if defined(POLARSSL_SSL_CLI_C) + "POLARSSL_SSL_CLI_C", +#endif /* POLARSSL_SSL_CLI_C */ +#if defined(POLARSSL_SSL_SRV_C) + "POLARSSL_SSL_SRV_C", +#endif /* POLARSSL_SSL_SRV_C */ +#if defined(POLARSSL_SSL_TLS_C) + "POLARSSL_SSL_TLS_C", +#endif /* POLARSSL_SSL_TLS_C */ +#if defined(POLARSSL_THREADING_C) + "POLARSSL_THREADING_C", +#endif /* POLARSSL_THREADING_C */ +#if defined(POLARSSL_TIMING_C) + "POLARSSL_TIMING_C", +#endif /* POLARSSL_TIMING_C */ +#if defined(POLARSSL_VERSION_C) + "POLARSSL_VERSION_C", +#endif /* POLARSSL_VERSION_C */ +#if defined(POLARSSL_X509_USE_C) + "POLARSSL_X509_USE_C", +#endif /* POLARSSL_X509_USE_C */ +#if defined(POLARSSL_X509_CRT_PARSE_C) + "POLARSSL_X509_CRT_PARSE_C", +#endif /* POLARSSL_X509_CRT_PARSE_C */ +#if defined(POLARSSL_X509_CRL_PARSE_C) + "POLARSSL_X509_CRL_PARSE_C", +#endif /* POLARSSL_X509_CRL_PARSE_C */ +#if defined(POLARSSL_X509_CSR_PARSE_C) + "POLARSSL_X509_CSR_PARSE_C", +#endif /* POLARSSL_X509_CSR_PARSE_C */ +#if defined(POLARSSL_X509_CREATE_C) + "POLARSSL_X509_CREATE_C", +#endif /* POLARSSL_X509_CREATE_C */ +#if defined(POLARSSL_X509_CRT_WRITE_C) + "POLARSSL_X509_CRT_WRITE_C", +#endif /* POLARSSL_X509_CRT_WRITE_C */ +#if defined(POLARSSL_X509_CSR_WRITE_C) + "POLARSSL_X509_CSR_WRITE_C", +#endif /* POLARSSL_X509_CSR_WRITE_C */ +#if defined(POLARSSL_XTEA_C) + "POLARSSL_XTEA_C", +#endif /* POLARSSL_XTEA_C */ +#endif /* POLARSSL_VERSION_FEATURES */ + NULL +}; + +int version_check_feature( const char *feature ) +{ + const char **idx = features; + + if( *idx == NULL ) + return( -2 ); + + if( feature == NULL ) + return( -1 ); + + while( *idx != NULL ) + { + if( !strcasecmp( *idx, feature ) ) + return( 0 ); + idx++; + } + return( -1 ); +} + +#endif /* POLARSSL_VERSION_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/x509.c b/component/common/network/ssl/polarssl-1.3.8/library/x509.c new file mode 100644 index 0000000..17c7a7d --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/x509.c @@ -0,0 +1,1102 @@ +/* + * X.509 common functions for parsing and verification + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * The ITU-T X.509 standard defines a certificate format for PKI. + * + * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) + * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) + * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) + * + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_X509_USE_C) + +#include "polarssl/x509.h" +#include "polarssl/asn1.h" +#include "polarssl/oid.h" +#if defined(POLARSSL_PEM_PARSE_C) +#include "polarssl/pem.h" +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#define polarssl_printf printf +#define polarssl_malloc malloc +#define polarssl_free free +#endif + +#include +#include +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) +#include +#else +#include +#endif + +#if defined(EFIX64) || defined(EFI32) +#include +#endif + +#if defined(POLARSSL_FS_IO) +#include +#if !defined(_WIN32) +#include +#include +#include +#endif +#endif + +/* + * CertificateSerialNumber ::= INTEGER + */ +int x509_get_serial( unsigned char **p, const unsigned char *end, + x509_buf *serial ) +{ + int ret; + + if( ( end - *p ) < 1 ) + return( POLARSSL_ERR_X509_INVALID_SERIAL + + POLARSSL_ERR_ASN1_OUT_OF_DATA ); + + if( **p != ( ASN1_CONTEXT_SPECIFIC | ASN1_PRIMITIVE | 2 ) && + **p != ASN1_INTEGER ) + return( POLARSSL_ERR_X509_INVALID_SERIAL + + POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); + + serial->tag = *(*p)++; + + if( ( ret = asn1_get_len( p, end, &serial->len ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_SERIAL + ret ); + + serial->p = *p; + *p += serial->len; + + return( 0 ); +} + +/* Get an algorithm identifier without parameters (eg for signatures) + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + */ +int x509_get_alg_null( unsigned char **p, const unsigned char *end, + x509_buf *alg ) +{ + int ret; + + if( ( ret = asn1_get_alg_null( p, end, alg ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_ALG + ret ); + + return( 0 ); +} + +/* + * Parse an algorithm identifier with (optional) paramaters + */ +int x509_get_alg( unsigned char **p, const unsigned char *end, + x509_buf *alg, x509_buf *params ) +{ + int ret; + + if( ( ret = asn1_get_alg( p, end, alg, params ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_ALG + ret ); + + return( 0 ); +} + +#if defined(POLARSSL_X509_RSASSA_PSS_SUPPORT) +/* + * HashAlgorithm ::= AlgorithmIdentifier + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + * + * For HashAlgorithm, parameters MUST be NULL or absent. + */ +static int x509_get_hash_alg( const x509_buf *alg, md_type_t *md_alg ) +{ + int ret; + unsigned char *p; + const unsigned char *end; + x509_buf md_oid; + size_t len; + + /* Make sure we got a SEQUENCE and setup bounds */ + if( alg->tag != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) + return( POLARSSL_ERR_X509_INVALID_ALG + + POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); + + p = (unsigned char *) alg->p; + end = p + alg->len; + + if( p >= end ) + return( POLARSSL_ERR_X509_INVALID_ALG + + POLARSSL_ERR_ASN1_OUT_OF_DATA ); + + /* Parse md_oid */ + md_oid.tag = *p; + + if( ( ret = asn1_get_tag( &p, end, &md_oid.len, ASN1_OID ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_ALG + ret ); + + md_oid.p = p; + p += md_oid.len; + + /* Get md_alg from md_oid */ + if( ( ret = oid_get_md_alg( &md_oid, md_alg ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_ALG + ret ); + + /* Make sure params is absent of NULL */ + if( p == end ) + return( 0 ); + + if( ( ret = asn1_get_tag( &p, end, &len, ASN1_NULL ) ) != 0 || len != 0 ) + return( POLARSSL_ERR_X509_INVALID_ALG + ret ); + + if( p != end ) + return( POLARSSL_ERR_X509_INVALID_ALG + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * RSASSA-PSS-params ::= SEQUENCE { + * hashAlgorithm [0] HashAlgorithm DEFAULT sha1Identifier, + * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier, + * saltLength [2] INTEGER DEFAULT 20, + * trailerField [3] INTEGER DEFAULT 1 } + * -- Note that the tags in this Sequence are explicit. + * + * RFC 4055 (which defines use of RSASSA-PSS in PKIX) states that the value + * of trailerField MUST be 1, and PKCS#1 v2.2 doesn't even define any other + * option. Enfore this at parsing time. + */ +int x509_get_rsassa_pss_params( const x509_buf *params, + md_type_t *md_alg, md_type_t *mgf_md, + int *salt_len ) +{ + int ret; + unsigned char *p; + const unsigned char *end, *end2; + size_t len; + x509_buf alg_id, alg_params; + + /* First set everything to defaults */ + *md_alg = POLARSSL_MD_SHA1; + *mgf_md = POLARSSL_MD_SHA1; + *salt_len = 20; + + /* Make sure params is a SEQUENCE and setup bounds */ + if( params->tag != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) + return( POLARSSL_ERR_X509_INVALID_ALG + + POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); + + p = (unsigned char *) params->p; + end = p + params->len; + + if( p == end ) + return( 0 ); + + /* + * HashAlgorithm + */ + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ) == 0 ) + { + end2 = p + len; + + /* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */ + if( ( ret = x509_get_alg_null( &p, end2, &alg_id ) ) != 0 ) + return( ret ); + + if( ( ret = oid_get_md_alg( &alg_id, md_alg ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_ALG + ret ); + + if( p != end2 ) + return( POLARSSL_ERR_X509_INVALID_ALG + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + } + else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) + return( POLARSSL_ERR_X509_INVALID_ALG + ret ); + + if( p == end ) + return( 0 ); + + /* + * MaskGenAlgorithm + */ + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1 ) ) == 0 ) + { + end2 = p + len; + + /* MaskGenAlgorithm ::= AlgorithmIdentifier (params = HashAlgorithm) */ + if( ( ret = x509_get_alg( &p, end2, &alg_id, &alg_params ) ) != 0 ) + return( ret ); + + /* Only MFG1 is recognised for now */ + if( ! OID_CMP( OID_MGF1, &alg_id ) ) + return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE + + POLARSSL_ERR_OID_NOT_FOUND ); + + /* Parse HashAlgorithm */ + if( ( ret = x509_get_hash_alg( &alg_params, mgf_md ) ) != 0 ) + return( ret ); + + if( p != end2 ) + return( POLARSSL_ERR_X509_INVALID_ALG + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + } + else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) + return( POLARSSL_ERR_X509_INVALID_ALG + ret ); + + if( p == end ) + return( 0 ); + + /* + * salt_len + */ + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 2 ) ) == 0 ) + { + end2 = p + len; + + if( ( ret = asn1_get_int( &p, end2, salt_len ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_ALG + ret ); + + if( p != end2 ) + return( POLARSSL_ERR_X509_INVALID_ALG + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + } + else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) + return( POLARSSL_ERR_X509_INVALID_ALG + ret ); + + if( p == end ) + return( 0 ); + + /* + * trailer_field (if present, must be 1) + */ + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3 ) ) == 0 ) + { + int trailer_field; + + end2 = p + len; + + if( ( ret = asn1_get_int( &p, end2, &trailer_field ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_ALG + ret ); + + if( p != end2 ) + return( POLARSSL_ERR_X509_INVALID_ALG + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + if( trailer_field != 1 ) + return( POLARSSL_ERR_X509_INVALID_ALG ); + } + else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) + return( POLARSSL_ERR_X509_INVALID_ALG + ret ); + + if( p != end ) + return( POLARSSL_ERR_X509_INVALID_ALG + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} +#endif /* POLARSSL_X509_RSASSA_PSS_SUPPORT */ + +/* + * AttributeTypeAndValue ::= SEQUENCE { + * type AttributeType, + * value AttributeValue } + * + * AttributeType ::= OBJECT IDENTIFIER + * + * AttributeValue ::= ANY DEFINED BY AttributeType + */ +static int x509_get_attr_type_value( unsigned char **p, + const unsigned char *end, + x509_name *cur ) +{ + int ret; + size_t len; + x509_buf *oid; + x509_buf *val; + + if( ( ret = asn1_get_tag( p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_NAME + ret ); + + if( ( end - *p ) < 1 ) + return( POLARSSL_ERR_X509_INVALID_NAME + + POLARSSL_ERR_ASN1_OUT_OF_DATA ); + + oid = &cur->oid; + oid->tag = **p; + + if( ( ret = asn1_get_tag( p, end, &oid->len, ASN1_OID ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_NAME + ret ); + + oid->p = *p; + *p += oid->len; + + if( ( end - *p ) < 1 ) + return( POLARSSL_ERR_X509_INVALID_NAME + + POLARSSL_ERR_ASN1_OUT_OF_DATA ); + + if( **p != ASN1_BMP_STRING && **p != ASN1_UTF8_STRING && + **p != ASN1_T61_STRING && **p != ASN1_PRINTABLE_STRING && + **p != ASN1_IA5_STRING && **p != ASN1_UNIVERSAL_STRING ) + return( POLARSSL_ERR_X509_INVALID_NAME + + POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); + + val = &cur->val; + val->tag = *(*p)++; + + if( ( ret = asn1_get_len( p, end, &val->len ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_NAME + ret ); + + val->p = *p; + *p += val->len; + + cur->next = NULL; + + return( 0 ); +} + +/* + * RelativeDistinguishedName ::= + * SET OF AttributeTypeAndValue + * + * AttributeTypeAndValue ::= SEQUENCE { + * type AttributeType, + * value AttributeValue } + * + * AttributeType ::= OBJECT IDENTIFIER + * + * AttributeValue ::= ANY DEFINED BY AttributeType + */ +int x509_get_name( unsigned char **p, const unsigned char *end, + x509_name *cur ) +{ + int ret; + size_t len; + const unsigned char *end2; + x509_name *use; + + if( ( ret = asn1_get_tag( p, end, &len, + ASN1_CONSTRUCTED | ASN1_SET ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_NAME + ret ); + + end2 = end; + end = *p + len; + use = cur; + + do + { + if( ( ret = x509_get_attr_type_value( p, end, use ) ) != 0 ) + return( ret ); + + if( *p != end ) + { + use->next = (x509_name *) polarssl_malloc( + sizeof( x509_name ) ); + + if( use->next == NULL ) + return( POLARSSL_ERR_X509_MALLOC_FAILED ); + + memset( use->next, 0, sizeof( x509_name ) ); + + use = use->next; + } + } + while( *p != end ); + + /* + * recurse until end of SEQUENCE is reached + */ + if( *p == end2 ) + return( 0 ); + + cur->next = (x509_name *) polarssl_malloc( + sizeof( x509_name ) ); + + if( cur->next == NULL ) + return( POLARSSL_ERR_X509_MALLOC_FAILED ); + + memset( cur->next, 0, sizeof( x509_name ) ); + + return( x509_get_name( p, end2, cur->next ) ); +} + +/* + * Time ::= CHOICE { + * utcTime UTCTime, + * generalTime GeneralizedTime } + */ +int x509_get_time( unsigned char **p, const unsigned char *end, + x509_time *time ) +{ + int ret; + size_t len; + char date[64]; + unsigned char tag; + + if( ( end - *p ) < 1 ) + return( POLARSSL_ERR_X509_INVALID_DATE + + POLARSSL_ERR_ASN1_OUT_OF_DATA ); + + tag = **p; + + if( tag == ASN1_UTC_TIME ) + { + (*p)++; + ret = asn1_get_len( p, end, &len ); + + if( ret != 0 ) + return( POLARSSL_ERR_X509_INVALID_DATE + ret ); + + memset( date, 0, sizeof( date ) ); + memcpy( date, *p, ( len < sizeof( date ) - 1 ) ? + len : sizeof( date ) - 1 ); + + if( sscanf( date, "%2d%2d%2d%2d%2d%2dZ", + &time->year, &time->mon, &time->day, + &time->hour, &time->min, &time->sec ) < 5 ) + return( POLARSSL_ERR_X509_INVALID_DATE ); + + time->year += 100 * ( time->year < 50 ); + time->year += 1900; + + *p += len; + + return( 0 ); + } + else if( tag == ASN1_GENERALIZED_TIME ) + { + (*p)++; + ret = asn1_get_len( p, end, &len ); + + if( ret != 0 ) + return( POLARSSL_ERR_X509_INVALID_DATE + ret ); + + memset( date, 0, sizeof( date ) ); + memcpy( date, *p, ( len < sizeof( date ) - 1 ) ? + len : sizeof( date ) - 1 ); + + if( sscanf( date, "%4d%2d%2d%2d%2d%2dZ", + &time->year, &time->mon, &time->day, + &time->hour, &time->min, &time->sec ) < 5 ) + return( POLARSSL_ERR_X509_INVALID_DATE ); + + *p += len; + + return( 0 ); + } + else + return( POLARSSL_ERR_X509_INVALID_DATE + + POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); +} + +int x509_get_sig( unsigned char **p, const unsigned char *end, x509_buf *sig ) +{ + int ret; + size_t len; + + if( ( end - *p ) < 1 ) + return( POLARSSL_ERR_X509_INVALID_SIGNATURE + + POLARSSL_ERR_ASN1_OUT_OF_DATA ); + + sig->tag = **p; + + if( ( ret = asn1_get_bitstring_null( p, end, &len ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_SIGNATURE + ret ); + + sig->len = len; + sig->p = *p; + + *p += len; + + return( 0 ); +} + +/* + * Get signature algorithm from alg OID and optional parameters + */ +int x509_get_sig_alg( const x509_buf *sig_oid, const x509_buf *sig_params, + md_type_t *md_alg, pk_type_t *pk_alg, + void **sig_opts ) +{ + int ret; + + if( *sig_opts != NULL ) + return( POLARSSL_ERR_X509_BAD_INPUT_DATA ); + + if( ( ret = oid_get_sig_alg( sig_oid, md_alg, pk_alg ) ) != 0 ) + return( POLARSSL_ERR_X509_UNKNOWN_SIG_ALG + ret ); + +#if defined(POLARSSL_X509_RSASSA_PSS_SUPPORT) + if( *pk_alg == POLARSSL_PK_RSASSA_PSS ) + { + pk_rsassa_pss_options *pss_opts; + + pss_opts = polarssl_malloc( sizeof( pk_rsassa_pss_options ) ); + if( pss_opts == NULL ) + return( POLARSSL_ERR_X509_MALLOC_FAILED ); + + ret = x509_get_rsassa_pss_params( sig_params, + md_alg, + &pss_opts->mgf1_hash_id, + &pss_opts->expected_salt_len ); + if( ret != 0 ) + { + polarssl_free( pss_opts ); + return( ret ); + } + + *sig_opts = (void *) pss_opts; + } + else +#endif /* POLARSSL_X509_RSASSA_PSS_SUPPORT */ + { + /* Make sure parameters are absent or NULL */ + if( ( sig_params->tag != ASN1_NULL && sig_params->tag != 0 ) || + sig_params->len != 0 ) + return( POLARSSL_ERR_X509_INVALID_ALG ); + } + + return( 0 ); +} + +/* + * X.509 Extensions (No parsing of extensions, pointer should + * be either manually updated or extensions should be parsed! + */ +int x509_get_ext( unsigned char **p, const unsigned char *end, + x509_buf *ext, int tag ) +{ + int ret; + size_t len; + + if( *p == end ) + return( 0 ); + + ext->tag = **p; + + if( ( ret = asn1_get_tag( p, end, &ext->len, + ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | tag ) ) != 0 ) + return( ret ); + + ext->p = *p; + end = *p + ext->len; + + /* + * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension + * + * Extension ::= SEQUENCE { + * extnID OBJECT IDENTIFIER, + * critical BOOLEAN DEFAULT FALSE, + * extnValue OCTET STRING } + */ + if( ( ret = asn1_get_tag( p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( end != *p + len ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +#if defined(POLARSSL_FS_IO) +/* + * Load all data from a file into a given buffer. + */ +int x509_load_file( const char *path, unsigned char **buf, size_t *n ) +{ + FILE *f; + long size; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( POLARSSL_ERR_X509_FILE_IO_ERROR ); + + fseek( f, 0, SEEK_END ); + if( ( size = ftell( f ) ) == -1 ) + { + fclose( f ); + return( POLARSSL_ERR_X509_FILE_IO_ERROR ); + } + fseek( f, 0, SEEK_SET ); + + *n = (size_t) size; + + if( *n + 1 == 0 || + ( *buf = (unsigned char *) polarssl_malloc( *n + 1 ) ) == NULL ) + { + fclose( f ); + return( POLARSSL_ERR_X509_MALLOC_FAILED ); + } + + if( fread( *buf, 1, *n, f ) != *n ) + { + fclose( f ); + polarssl_free( *buf ); + return( POLARSSL_ERR_X509_FILE_IO_ERROR ); + } + + fclose( f ); + + (*buf)[*n] = '\0'; + + return( 0 ); +} +#endif /* POLARSSL_FS_IO */ + +#if defined(_MSC_VER) && !defined snprintf && !defined(EFIX64) && \ + !defined(EFI32) +#include + +#if !defined vsnprintf +#define vsnprintf _vsnprintf +#endif // vsnprintf + +/* + * Windows _snprintf and _vsnprintf are not compatible to linux versions. + * Result value is not size of buffer needed, but -1 if no fit is possible. + * + * This fuction tries to 'fix' this by at least suggesting enlarging the + * size by 20. + */ +static int compat_snprintf( char *str, size_t size, const char *format, ... ) +{ + va_list ap; + int res = -1; + + va_start( ap, format ); + + res = vsnprintf( str, size, format, ap ); + + va_end( ap ); + + // No quick fix possible + if( res < 0 ) + return( (int) size + 20 ); + + return( res ); +} + +#define snprintf compat_snprintf +#endif /* _MSC_VER && !snprintf && !EFIX64 && !EFI32 */ + +#define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL -2 + +#define SAFE_SNPRINTF() \ +{ \ + if( ret == -1 ) \ + return( -1 ); \ + \ + if( (unsigned int) ret > n ) { \ + p[n - 1] = '\0'; \ + return( POLARSSL_ERR_DEBUG_BUF_TOO_SMALL ); \ + } \ + \ + n -= (unsigned int) ret; \ + p += (unsigned int) ret; \ +} + +/* + * Store the name in printable form into buf; no more + * than size characters will be written + */ +int x509_dn_gets( char *buf, size_t size, const x509_name *dn ) +{ + int ret; + size_t i, n; + unsigned char c; + const x509_name *name; + const char *short_name = NULL; + char s[128], *p; + + memset( s, 0, sizeof( s ) ); + + name = dn; + p = buf; + n = size; + + while( name != NULL ) + { + if( !name->oid.p ) + { + name = name->next; + continue; + } + + if( name != dn ) + { + ret = snprintf( p, n, ", " ); + SAFE_SNPRINTF(); + } + + ret = oid_get_attr_short_name( &name->oid, &short_name ); + + if( ret == 0 ) + ret = snprintf( p, n, "%s=", short_name ); + else + ret = snprintf( p, n, "\?\?=" ); + SAFE_SNPRINTF(); + + for( i = 0; i < name->val.len; i++ ) + { + if( i >= sizeof( s ) - 1 ) + break; + + c = name->val.p[i]; + if( c < 32 || c == 127 || ( c > 128 && c < 160 ) ) + s[i] = '?'; + else s[i] = c; + } + s[i] = '\0'; + ret = snprintf( p, n, "%s", s ); + SAFE_SNPRINTF(); + name = name->next; + } + + return( (int) ( size - n ) ); +} + +/* + * Store the serial in printable form into buf; no more + * than size characters will be written + */ +int x509_serial_gets( char *buf, size_t size, const x509_buf *serial ) +{ + int ret; + size_t i, n, nr; + char *p; + + p = buf; + n = size; + + nr = ( serial->len <= 32 ) + ? serial->len : 28; + + for( i = 0; i < nr; i++ ) + { + if( i == 0 && nr > 1 && serial->p[i] == 0x0 ) + continue; + + ret = snprintf( p, n, "%02X%s", + serial->p[i], ( i < nr - 1 ) ? ":" : "" ); + SAFE_SNPRINTF(); + } + + if( nr != serial->len ) + { + ret = snprintf( p, n, "...." ); + SAFE_SNPRINTF(); + } + + return( (int) ( size - n ) ); +} + +/* + * Helper for writing signature algorithms + */ +int x509_sig_alg_gets( char *buf, size_t size, const x509_buf *sig_oid, + pk_type_t pk_alg, md_type_t md_alg, + const void *sig_opts ) +{ + int ret; + char *p = buf; + size_t n = size; + const char *desc = NULL; + + ret = oid_get_sig_alg_desc( sig_oid, &desc ); + if( ret != 0 ) + ret = snprintf( p, n, "???" ); + else + ret = snprintf( p, n, "%s", desc ); + SAFE_SNPRINTF(); + +#if defined(POLARSSL_X509_RSASSA_PSS_SUPPORT) + if( pk_alg == POLARSSL_PK_RSASSA_PSS ) + { + const pk_rsassa_pss_options *pss_opts; + const md_info_t *md_info, *mgf_md_info; + + pss_opts = (const pk_rsassa_pss_options *) sig_opts; + + md_info = md_info_from_type( md_alg ); + mgf_md_info = md_info_from_type( pss_opts->mgf1_hash_id ); + + ret = snprintf( p, n, " (%s, MGF1-%s, 0x%02X)", + md_info ? md_info->name : "???", + mgf_md_info ? mgf_md_info->name : "???", + pss_opts->expected_salt_len ); + SAFE_SNPRINTF(); + } +#else + ((void) pk_alg); + ((void) md_alg); + ((void) sig_opts); +#endif /* POLARSSL_X509_RSASSA_PSS_SUPPORT */ + + return( (int) size - n ); +} + +/* + * Helper for writing "RSA key size", "EC key size", etc + */ +int x509_key_size_helper( char *buf, size_t size, const char *name ) +{ + char *p = buf; + size_t n = size; + int ret; + + if( strlen( name ) + sizeof( " key size" ) > size ) + return( POLARSSL_ERR_DEBUG_BUF_TOO_SMALL ); + + ret = snprintf( p, n, "%s key size", name ); + SAFE_SNPRINTF(); + + return( 0 ); +} + +/* + * Return an informational string describing the given OID + */ +const char *x509_oid_get_description( x509_buf *oid ) +{ + const char *desc = NULL; + int ret; + + ret = oid_get_extended_key_usage( oid, &desc ); + + if( ret != 0 ) + return( NULL ); + + return( desc ); +} + +/* Return the x.y.z.... style numeric string for the given OID */ +int x509_oid_get_numeric_string( char *buf, size_t size, x509_buf *oid ) +{ + return oid_get_numeric_string( buf, size, oid ); +} + +/* + * Return 0 if the x509_time is still valid, or 1 otherwise. + */ +#if defined(POLARSSL_HAVE_TIME) + +static void x509_get_current_time( x509_time *now ) +{ +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + SYSTEMTIME st; + + GetSystemTime( &st ); + + now->year = st.wYear; + now->mon = st.wMonth; + now->day = st.wDay; + now->hour = st.wHour; + now->min = st.wMinute; + now->sec = st.wSecond; +#else + struct tm lt; + time_t tt; + + tt = time( NULL ); + gmtime_r( &tt, < ); + + now->year = lt.tm_year + 1900; + now->mon = lt.tm_mon + 1; + now->day = lt.tm_mday; + now->hour = lt.tm_hour; + now->min = lt.tm_min; + now->sec = lt.tm_sec; +#endif /* _WIN32 && !EFIX64 && !EFI32 */ +} + +/* + * Return 0 if before <= after, 1 otherwise + */ +static int x509_check_time( const x509_time *before, const x509_time *after ) +{ + if( before->year > after->year ) + return( 1 ); + + if( before->year == after->year && + before->mon > after->mon ) + return( 1 ); + + if( before->year == after->year && + before->mon == after->mon && + before->day > after->day ) + return( 1 ); + + if( before->year == after->year && + before->mon == after->mon && + before->day == after->day && + before->hour > after->hour ) + return( 1 ); + + if( before->year == after->year && + before->mon == after->mon && + before->day == after->day && + before->hour == after->hour && + before->min > after->min ) + return( 1 ); + + if( before->year == after->year && + before->mon == after->mon && + before->day == after->day && + before->hour == after->hour && + before->min == after->min && + before->sec > after->sec ) + return( 1 ); + + return( 0 ); +} + +int x509_time_expired( const x509_time *to ) +{ + x509_time now; + + x509_get_current_time( &now ); + + return( x509_check_time( &now, to ) ); +} + +int x509_time_future( const x509_time *from ) +{ + x509_time now; + + x509_get_current_time( &now ); + + return( x509_check_time( from, &now ) ); +} + +#else /* POLARSSL_HAVE_TIME */ + +int x509_time_expired( const x509_time *to ) +{ + ((void) to); + return( 0 ); +} + +int x509_time_future( const x509_time *from ) +{ + ((void) from); + return( 0 ); +} +#endif /* POLARSSL_HAVE_TIME */ + +#if defined(POLARSSL_SELF_TEST) + +#include "polarssl/x509_crt.h" +#include "polarssl/certs.h" + +/* + * Checkup routine + */ +int x509_self_test( int verbose ) +{ +#if defined(POLARSSL_CERTS_C) && defined(POLARSSL_SHA1_C) + int ret; + int flags; + x509_crt cacert; + x509_crt clicert; + + if( verbose != 0 ) + polarssl_printf( " X.509 certificate load: " ); + + x509_crt_init( &clicert ); + + ret = x509_crt_parse( &clicert, (const unsigned char *) test_cli_crt, + strlen( test_cli_crt ) ); + if( ret != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( ret ); + } + + x509_crt_init( &cacert ); + + ret = x509_crt_parse( &cacert, (const unsigned char *) test_ca_crt, + strlen( test_ca_crt ) ); + if( ret != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( ret ); + } + + if( verbose != 0 ) + polarssl_printf( "passed\n X.509 signature verify: "); + + ret = x509_crt_verify( &clicert, &cacert, NULL, NULL, &flags, NULL, NULL ); + if( ret != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + polarssl_printf( "ret = %d, &flags = %04x\n", ret, flags ); + + return( ret ); + } + + if( verbose != 0 ) + polarssl_printf( "passed\n\n"); + + x509_crt_free( &cacert ); + x509_crt_free( &clicert ); + + return( 0 ); +#else + ((void) verbose); + return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE ); +#endif /* POLARSSL_CERTS_C && POLARSSL_SHA1_C */ +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_X509_USE_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/x509_create.c b/component/common/network/ssl/polarssl-1.3.8/library/x509_create.c new file mode 100644 index 0000000..1019313 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/x509_create.c @@ -0,0 +1,318 @@ +/* + * X.509 base functions for creating certificates / CSRs + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_X509_CREATE_C) + +#include "polarssl/x509.h" +#include "polarssl/asn1write.h" +#include "polarssl/oid.h" + +#if defined(_MSC_VER) && !defined strncasecmp && !defined(EFIX64) && \ + !defined(EFI32) +#define strncasecmp _strnicmp +#endif + +typedef struct { + const char *name; + size_t name_len; + const char*oid; +} x509_attr_descriptor_t; + +#define ADD_STRLEN( s ) s, sizeof( s ) - 1 + +static const x509_attr_descriptor_t x509_attrs[] = +{ + { ADD_STRLEN( "CN" ), OID_AT_CN }, + { ADD_STRLEN( "commonName" ), OID_AT_CN }, + { ADD_STRLEN( "C" ), OID_AT_COUNTRY }, + { ADD_STRLEN( "countryName" ), OID_AT_COUNTRY }, + { ADD_STRLEN( "O" ), OID_AT_ORGANIZATION }, + { ADD_STRLEN( "organizationName" ), OID_AT_ORGANIZATION }, + { ADD_STRLEN( "L" ), OID_AT_LOCALITY }, + { ADD_STRLEN( "locality" ), OID_AT_LOCALITY }, + { ADD_STRLEN( "R" ), OID_PKCS9_EMAIL }, + { ADD_STRLEN( "OU" ), OID_AT_ORG_UNIT }, + { ADD_STRLEN( "organizationalUnitName" ), OID_AT_ORG_UNIT }, + { ADD_STRLEN( "ST" ), OID_AT_STATE }, + { ADD_STRLEN( "stateOrProvinceName" ), OID_AT_STATE }, + { ADD_STRLEN( "emailAddress" ), OID_PKCS9_EMAIL }, + { ADD_STRLEN( "serialNumber" ), OID_AT_SERIAL_NUMBER }, + { ADD_STRLEN( "postalAddress" ), OID_AT_POSTAL_ADDRESS }, + { ADD_STRLEN( "postalCode" ), OID_AT_POSTAL_CODE }, + { ADD_STRLEN( "dnQualifier" ), OID_AT_DN_QUALIFIER }, + { ADD_STRLEN( "title" ), OID_AT_TITLE }, + { ADD_STRLEN( "surName" ), OID_AT_SUR_NAME }, + { ADD_STRLEN( "SN" ), OID_AT_SUR_NAME }, + { ADD_STRLEN( "givenName" ), OID_AT_GIVEN_NAME }, + { ADD_STRLEN( "GN" ), OID_AT_GIVEN_NAME }, + { ADD_STRLEN( "initials" ), OID_AT_INITIALS }, + { ADD_STRLEN( "pseudonym" ), OID_AT_PSEUDONYM }, + { ADD_STRLEN( "generationQualifier" ), OID_AT_GENERATION_QUALIFIER }, + { ADD_STRLEN( "domainComponent" ), OID_DOMAIN_COMPONENT }, + { ADD_STRLEN( "DC" ), OID_DOMAIN_COMPONENT }, + { NULL, 0, NULL } +}; + +static const char *x509_at_oid_from_name( const char *name, size_t name_len ) +{ + const x509_attr_descriptor_t *cur; + + for( cur = x509_attrs; cur->name != NULL; cur++ ) + if( cur->name_len == name_len && + strncasecmp( cur->name, name, name_len ) == 0 ) + break; + + return( cur->oid ); +} + +int x509_string_to_names( asn1_named_data **head, const char *name ) +{ + int ret = 0; + const char *s = name, *c = s; + const char *end = s + strlen( s ); + const char *oid = NULL; + int in_tag = 1; + + /* Clear existing chain if present */ + asn1_free_named_data_list( head ); + + while( c <= end ) + { + if( in_tag && *c == '=' ) + { + if( ( oid = x509_at_oid_from_name( s, c - s ) ) == NULL ) + { + ret = POLARSSL_ERR_X509_UNKNOWN_OID; + goto exit; + } + + s = c + 1; + in_tag = 0; + } + + if( !in_tag && ( *c == ',' || c == end ) ) + { + if( asn1_store_named_data( head, oid, strlen( oid ), + (unsigned char *) s, + c - s ) == NULL ) + { + return( POLARSSL_ERR_X509_MALLOC_FAILED ); + } + + while( c < end && *(c + 1) == ' ' ) + c++; + + s = c + 1; + in_tag = 1; + } + c++; + } + +exit: + + return( ret ); +} + +/* The first byte of the value in the asn1_named_data structure is reserved + * to store the critical boolean for us + */ +int x509_set_extension( asn1_named_data **head, const char *oid, size_t oid_len, + int critical, const unsigned char *val, size_t val_len ) +{ + asn1_named_data *cur; + + if( ( cur = asn1_store_named_data( head, oid, oid_len, + NULL, val_len + 1 ) ) == NULL ) + { + return( POLARSSL_ERR_X509_MALLOC_FAILED ); + } + + cur->val.p[0] = critical; + memcpy( cur->val.p + 1, val, val_len ); + + return( 0 ); +} + +/* + * RelativeDistinguishedName ::= + * SET OF AttributeTypeAndValue + * + * AttributeTypeAndValue ::= SEQUENCE { + * type AttributeType, + * value AttributeValue } + * + * AttributeType ::= OBJECT IDENTIFIER + * + * AttributeValue ::= ANY DEFINED BY AttributeType + */ +static int x509_write_name( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len, + const unsigned char *name, size_t name_len ) +{ + int ret; + size_t len = 0; + + // Write PrintableString for all except OID_PKCS9_EMAIL + // + if( OID_SIZE( OID_PKCS9_EMAIL ) == oid_len && + memcmp( oid, OID_PKCS9_EMAIL, oid_len ) == 0 ) + { + ASN1_CHK_ADD( len, asn1_write_ia5_string( p, start, + (const char *) name, + name_len ) ); + } + else + { + ASN1_CHK_ADD( len, asn1_write_printable_string( p, start, + (const char *) name, + name_len ) ); + } + + // Write OID + // + ASN1_CHK_ADD( len, asn1_write_oid( p, start, oid, oid_len ) ); + + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | + ASN1_SEQUENCE ) ); + + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | + ASN1_SET ) ); + + return( (int) len ); +} + +int x509_write_names( unsigned char **p, unsigned char *start, + asn1_named_data *first ) +{ + int ret; + size_t len = 0; + asn1_named_data *cur = first; + + while( cur != NULL ) + { + ASN1_CHK_ADD( len, x509_write_name( p, start, (char *) cur->oid.p, + cur->oid.len, + cur->val.p, cur->val.len ) ); + cur = cur->next; + } + + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | + ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +int x509_write_sig( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len, + unsigned char *sig, size_t size ) +{ + int ret; + size_t len = 0; + + if( *p - start < (int) size + 1 ) + return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + + len = size; + (*p) -= len; + memcpy( *p, sig, len ); + + *--(*p) = 0; + len += 1; + + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_BIT_STRING ) ); + + // Write OID + // + ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( p, start, oid, + oid_len, 0 ) ); + + return( (int) len ); +} + +static int x509_write_extension( unsigned char **p, unsigned char *start, + asn1_named_data *ext ) +{ + int ret; + size_t len = 0; + + ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->val.p + 1, + ext->val.len - 1 ) ); + ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->val.len - 1 ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OCTET_STRING ) ); + + if( ext->val.p[0] != 0 ) + { + ASN1_CHK_ADD( len, asn1_write_bool( p, start, 1 ) ); + } + + ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->oid.p, + ext->oid.len ) ); + ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->oid.len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OID ) ); + + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | + ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +/* + * Extension ::= SEQUENCE { + * extnID OBJECT IDENTIFIER, + * critical BOOLEAN DEFAULT FALSE, + * extnValue OCTET STRING + * -- contains the DER encoding of an ASN.1 value + * -- corresponding to the extension type identified + * -- by extnID + * } + */ +int x509_write_extensions( unsigned char **p, unsigned char *start, + asn1_named_data *first ) +{ + int ret; + size_t len = 0; + asn1_named_data *cur_ext = first; + + while( cur_ext != NULL ) + { + ASN1_CHK_ADD( len, x509_write_extension( p, start, cur_ext ) ); + cur_ext = cur_ext->next; + } + + return( (int) len ); +} + +#endif /* POLARSSL_X509_CREATE_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/x509_crl.c b/component/common/network/ssl/polarssl-1.3.8/library/x509_crl.c new file mode 100644 index 0000000..7dd53c2 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/x509_crl.c @@ -0,0 +1,768 @@ +/* + * X.509 Certidicate Revocation List (CRL) parsing + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * The ITU-T X.509 standard defines a certificate format for PKI. + * + * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) + * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) + * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) + * + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_X509_CRL_PARSE_C) + +#include "polarssl/x509_crl.h" +#include "polarssl/oid.h" +#if defined(POLARSSL_PEM_PARSE_C) +#include "polarssl/pem.h" +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#define polarssl_malloc malloc +#define polarssl_free free +#endif + +#include +#include +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + +#include +#else +#include +#endif + +#if defined(POLARSSL_FS_IO) || defined(EFIX64) || defined(EFI32) +#include +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * Version ::= INTEGER { v1(0), v2(1) } + */ +static int x509_crl_get_version( unsigned char **p, + const unsigned char *end, + int *ver ) +{ + int ret; + + if( ( ret = asn1_get_int( p, end, ver ) ) != 0 ) + { + if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) + { + *ver = 0; + return( 0 ); + } + + return( POLARSSL_ERR_X509_INVALID_VERSION + ret ); + } + + return( 0 ); +} + +/* + * X.509 CRL v2 extensions (no extensions parsed yet.) + */ +static int x509_get_crl_ext( unsigned char **p, + const unsigned char *end, + x509_buf *ext ) +{ + int ret; + size_t len = 0; + + /* Get explicit tag */ + if( ( ret = x509_get_ext( p, end, ext, 0) ) != 0 ) + { + if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) + return( 0 ); + + return( ret ); + } + + while( *p < end ) + { + if( ( ret = asn1_get_tag( p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret ); + + *p += len; + } + + if( *p != end ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * X.509 CRL v2 entry extensions (no extensions parsed yet.) + */ +static int x509_get_crl_entry_ext( unsigned char **p, + const unsigned char *end, + x509_buf *ext ) +{ + int ret; + size_t len = 0; + + /* OPTIONAL */ + if( end <= *p ) + return( 0 ); + + ext->tag = **p; + ext->p = *p; + + /* + * Get CRL-entry extension sequence header + * crlEntryExtensions Extensions OPTIONAL -- if present, MUST be v2 + */ + if( ( ret = asn1_get_tag( p, end, &ext->len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) + { + ext->p = NULL; + return( 0 ); + } + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret ); + } + + end = *p + ext->len; + + if( end != *p + ext->len ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + while( *p < end ) + { + if( ( ret = asn1_get_tag( p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret ); + + *p += len; + } + + if( *p != end ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * X.509 CRL Entries + */ +static int x509_get_entries( unsigned char **p, + const unsigned char *end, + x509_crl_entry *entry ) +{ + int ret; + size_t entry_len; + x509_crl_entry *cur_entry = entry; + + if( *p == end ) + return( 0 ); + + if( ( ret = asn1_get_tag( p, end, &entry_len, + ASN1_SEQUENCE | ASN1_CONSTRUCTED ) ) != 0 ) + { + if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) + return( 0 ); + + return( ret ); + } + + end = *p + entry_len; + + while( *p < end ) + { + size_t len2; + const unsigned char *end2; + + if( ( ret = asn1_get_tag( p, end, &len2, + ASN1_SEQUENCE | ASN1_CONSTRUCTED ) ) != 0 ) + { + return( ret ); + } + + cur_entry->raw.tag = **p; + cur_entry->raw.p = *p; + cur_entry->raw.len = len2; + end2 = *p + len2; + + if( ( ret = x509_get_serial( p, end2, &cur_entry->serial ) ) != 0 ) + return( ret ); + + if( ( ret = x509_get_time( p, end2, + &cur_entry->revocation_date ) ) != 0 ) + return( ret ); + + if( ( ret = x509_get_crl_entry_ext( p, end2, + &cur_entry->entry_ext ) ) != 0 ) + return( ret ); + + if( *p < end ) + { + cur_entry->next = polarssl_malloc( sizeof( x509_crl_entry ) ); + + if( cur_entry->next == NULL ) + return( POLARSSL_ERR_X509_MALLOC_FAILED ); + + cur_entry = cur_entry->next; + memset( cur_entry, 0, sizeof( x509_crl_entry ) ); + } + } + + return( 0 ); +} + +/* + * Parse one or more CRLs and add them to the chained list + */ +int x509_crl_parse( x509_crl *chain, const unsigned char *buf, size_t buflen ) +{ + int ret; + size_t len; + unsigned char *p, *end; + x509_crl *crl; + x509_buf sig_params1, sig_params2; + +#if defined(POLARSSL_PEM_PARSE_C) + size_t use_len; + pem_context pem; +#endif + + memset( &sig_params1, 0, sizeof( x509_buf ) ); + memset( &sig_params2, 0, sizeof( x509_buf ) ); + + crl = chain; + + /* + * Check for valid input + */ + if( crl == NULL || buf == NULL ) + return( POLARSSL_ERR_X509_BAD_INPUT_DATA ); + + while( crl->version != 0 && crl->next != NULL ) + crl = crl->next; + + /* + * Add new CRL on the end of the chain if needed. + */ + if( crl->version != 0 && crl->next == NULL ) + { + crl->next = (x509_crl *) polarssl_malloc( sizeof( x509_crl ) ); + + if( crl->next == NULL ) + { + x509_crl_free( crl ); + return( POLARSSL_ERR_X509_MALLOC_FAILED ); + } + + crl = crl->next; + x509_crl_init( crl ); + } + +#if defined(POLARSSL_PEM_PARSE_C) + pem_init( &pem ); + ret = pem_read_buffer( &pem, + "-----BEGIN X509 CRL-----", + "-----END X509 CRL-----", + buf, NULL, 0, &use_len ); + + if( ret == 0 ) + { + /* + * Was PEM encoded + */ + buflen -= use_len; + buf += use_len; + + /* + * Steal PEM buffer + */ + p = pem.buf; + pem.buf = NULL; + len = pem.buflen; + pem_free( &pem ); + } + else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + pem_free( &pem ); + return( ret ); + } + else +#endif /* POLARSSL_PEM_PARSE_C */ + { + /* + * nope, copy the raw DER data + */ + p = (unsigned char *) polarssl_malloc( len = buflen ); + + if( p == NULL ) + return( POLARSSL_ERR_X509_MALLOC_FAILED ); + + memcpy( p, buf, buflen ); + + buflen = 0; + } + + crl->raw.p = p; + crl->raw.len = len; + end = p + len; + + /* + * CertificateList ::= SEQUENCE { + * tbsCertList TBSCertList, + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING } + */ + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + x509_crl_free( crl ); + return( POLARSSL_ERR_X509_INVALID_FORMAT ); + } + + if( len != (size_t) ( end - p ) ) + { + x509_crl_free( crl ); + return( POLARSSL_ERR_X509_INVALID_FORMAT + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + } + + /* + * TBSCertList ::= SEQUENCE { + */ + crl->tbs.p = p; + + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + x509_crl_free( crl ); + return( POLARSSL_ERR_X509_INVALID_FORMAT + ret ); + } + + end = p + len; + crl->tbs.len = end - crl->tbs.p; + + /* + * Version ::= INTEGER OPTIONAL { v1(0), v2(1) } + * -- if present, MUST be v2 + * + * signature AlgorithmIdentifier + */ + if( ( ret = x509_crl_get_version( &p, end, &crl->version ) ) != 0 || + ( ret = x509_get_alg( &p, end, &crl->sig_oid1, &sig_params1 ) ) != 0 ) + { + x509_crl_free( crl ); + return( ret ); + } + + crl->version++; + + if( crl->version > 2 ) + { + x509_crl_free( crl ); + return( POLARSSL_ERR_X509_UNKNOWN_VERSION ); + } + + if( ( ret = x509_get_sig_alg( &crl->sig_oid1, &sig_params1, + &crl->sig_md, &crl->sig_pk, + &crl->sig_opts ) ) != 0 ) + { + x509_crl_free( crl ); + return( POLARSSL_ERR_X509_UNKNOWN_SIG_ALG ); + } + + /* + * issuer Name + */ + crl->issuer_raw.p = p; + + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + x509_crl_free( crl ); + return( POLARSSL_ERR_X509_INVALID_FORMAT + ret ); + } + + if( ( ret = x509_get_name( &p, p + len, &crl->issuer ) ) != 0 ) + { + x509_crl_free( crl ); + return( ret ); + } + + crl->issuer_raw.len = p - crl->issuer_raw.p; + + /* + * thisUpdate Time + * nextUpdate Time OPTIONAL + */ + if( ( ret = x509_get_time( &p, end, &crl->this_update ) ) != 0 ) + { + x509_crl_free( crl ); + return( ret ); + } + + if( ( ret = x509_get_time( &p, end, &crl->next_update ) ) != 0 ) + { + if( ret != ( POLARSSL_ERR_X509_INVALID_DATE + + POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) && + ret != ( POLARSSL_ERR_X509_INVALID_DATE + + POLARSSL_ERR_ASN1_OUT_OF_DATA ) ) + { + x509_crl_free( crl ); + return( ret ); + } + } + + /* + * revokedCertificates SEQUENCE OF SEQUENCE { + * userCertificate CertificateSerialNumber, + * revocationDate Time, + * crlEntryExtensions Extensions OPTIONAL + * -- if present, MUST be v2 + * } OPTIONAL + */ + if( ( ret = x509_get_entries( &p, end, &crl->entry ) ) != 0 ) + { + x509_crl_free( crl ); + return( ret ); + } + + /* + * crlExtensions EXPLICIT Extensions OPTIONAL + * -- if present, MUST be v2 + */ + if( crl->version == 2 ) + { + ret = x509_get_crl_ext( &p, end, &crl->crl_ext ); + + if( ret != 0 ) + { + x509_crl_free( crl ); + return( ret ); + } + } + + if( p != end ) + { + x509_crl_free( crl ); + return( POLARSSL_ERR_X509_INVALID_FORMAT + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + } + + end = crl->raw.p + crl->raw.len; + + /* + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING + */ + if( ( ret = x509_get_alg( &p, end, &crl->sig_oid2, &sig_params2 ) ) != 0 ) + { + x509_crl_free( crl ); + return( ret ); + } + + if( crl->sig_oid1.len != crl->sig_oid2.len || + memcmp( crl->sig_oid1.p, crl->sig_oid2.p, crl->sig_oid1.len ) != 0 || + sig_params1.len != sig_params2.len || + memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) + { + x509_crl_free( crl ); + return( POLARSSL_ERR_X509_SIG_MISMATCH ); + } + + if( ( ret = x509_get_sig( &p, end, &crl->sig ) ) != 0 ) + { + x509_crl_free( crl ); + return( ret ); + } + + if( p != end ) + { + x509_crl_free( crl ); + return( POLARSSL_ERR_X509_INVALID_FORMAT + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + } + + if( buflen > 0 ) + { + crl->next = (x509_crl *) polarssl_malloc( sizeof( x509_crl ) ); + + if( crl->next == NULL ) + { + x509_crl_free( crl ); + return( POLARSSL_ERR_X509_MALLOC_FAILED ); + } + + crl = crl->next; + x509_crl_init( crl ); + + return( x509_crl_parse( crl, buf, buflen ) ); + } + + return( 0 ); +} + +#if defined(POLARSSL_FS_IO) +/* + * Load one or more CRLs and add them to the chained list + */ +int x509_crl_parse_file( x509_crl *chain, const char *path ) +{ + int ret; + size_t n; + unsigned char *buf; + + if( ( ret = x509_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = x509_crl_parse( chain, buf, n ); + + polarssl_zeroize( buf, n + 1 ); + polarssl_free( buf ); + + return( ret ); +} +#endif /* POLARSSL_FS_IO */ + +#if defined(_MSC_VER) && !defined snprintf && !defined(EFIX64) && \ + !defined(EFI32) +#include + +#if !defined vsnprintf +#define vsnprintf _vsnprintf +#endif // vsnprintf + +/* + * Windows _snprintf and _vsnprintf are not compatible to linux versions. + * Result value is not size of buffer needed, but -1 if no fit is possible. + * + * This fuction tries to 'fix' this by at least suggesting enlarging the + * size by 20. + */ +static int compat_snprintf( char *str, size_t size, const char *format, ... ) +{ + va_list ap; + int res = -1; + + va_start( ap, format ); + + res = vsnprintf( str, size, format, ap ); + + va_end( ap ); + + // No quick fix possible + if( res < 0 ) + return( (int) size + 20 ); + + return( res ); +} + +#define snprintf compat_snprintf +#endif /* _MSC_VER && !snprintf && !EFIX64 && !EFI32 */ + +#define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL -2 + +#define SAFE_SNPRINTF() \ +{ \ + if( ret == -1 ) \ + return( -1 ); \ + \ + if( (unsigned int) ret > n ) { \ + p[n - 1] = '\0'; \ + return( POLARSSL_ERR_DEBUG_BUF_TOO_SMALL ); \ + } \ + \ + n -= (unsigned int) ret; \ + p += (unsigned int) ret; \ +} + +/* + * Return an informational string about the certificate. + */ +#define BEFORE_COLON 14 +#define BC "14" +/* + * Return an informational string about the CRL. + */ +int x509_crl_info( char *buf, size_t size, const char *prefix, + const x509_crl *crl ) +{ + int ret; + size_t n; + char *p; + const x509_crl_entry *entry; + + p = buf; + n = size; + + ret = snprintf( p, n, "%sCRL version : %d", + prefix, crl->version ); + SAFE_SNPRINTF(); + + ret = snprintf( p, n, "\n%sissuer name : ", prefix ); + SAFE_SNPRINTF(); + ret = x509_dn_gets( p, n, &crl->issuer ); + SAFE_SNPRINTF(); + + ret = snprintf( p, n, "\n%sthis update : " \ + "%04d-%02d-%02d %02d:%02d:%02d", prefix, + crl->this_update.year, crl->this_update.mon, + crl->this_update.day, crl->this_update.hour, + crl->this_update.min, crl->this_update.sec ); + SAFE_SNPRINTF(); + + ret = snprintf( p, n, "\n%snext update : " \ + "%04d-%02d-%02d %02d:%02d:%02d", prefix, + crl->next_update.year, crl->next_update.mon, + crl->next_update.day, crl->next_update.hour, + crl->next_update.min, crl->next_update.sec ); + SAFE_SNPRINTF(); + + entry = &crl->entry; + + ret = snprintf( p, n, "\n%sRevoked certificates:", + prefix ); + SAFE_SNPRINTF(); + + while( entry != NULL && entry->raw.len != 0 ) + { + ret = snprintf( p, n, "\n%sserial number: ", + prefix ); + SAFE_SNPRINTF(); + + ret = x509_serial_gets( p, n, &entry->serial ); + SAFE_SNPRINTF(); + + ret = snprintf( p, n, " revocation date: " \ + "%04d-%02d-%02d %02d:%02d:%02d", + entry->revocation_date.year, entry->revocation_date.mon, + entry->revocation_date.day, entry->revocation_date.hour, + entry->revocation_date.min, entry->revocation_date.sec ); + SAFE_SNPRINTF(); + + entry = entry->next; + } + + ret = snprintf( p, n, "\n%ssigned using : ", prefix ); + SAFE_SNPRINTF(); + + ret = x509_sig_alg_gets( p, n, &crl->sig_oid1, crl->sig_pk, crl->sig_md, + crl->sig_opts ); + SAFE_SNPRINTF(); + + ret = snprintf( p, n, "\n" ); + SAFE_SNPRINTF(); + + return( (int) ( size - n ) ); +} + +/* + * Initialize a CRL chain + */ +void x509_crl_init( x509_crl *crl ) +{ + memset( crl, 0, sizeof(x509_crl) ); +} + +/* + * Unallocate all CRL data + */ +void x509_crl_free( x509_crl *crl ) +{ + x509_crl *crl_cur = crl; + x509_crl *crl_prv; + x509_name *name_cur; + x509_name *name_prv; + x509_crl_entry *entry_cur; + x509_crl_entry *entry_prv; + + if( crl == NULL ) + return; + + do + { +#if defined(POLARSSL_X509_RSASSA_PSS_SUPPORT) + polarssl_free( crl_cur->sig_opts ); +#endif + + name_cur = crl_cur->issuer.next; + while( name_cur != NULL ) + { + name_prv = name_cur; + name_cur = name_cur->next; + polarssl_zeroize( name_prv, sizeof( x509_name ) ); + polarssl_free( name_prv ); + } + + entry_cur = crl_cur->entry.next; + while( entry_cur != NULL ) + { + entry_prv = entry_cur; + entry_cur = entry_cur->next; + polarssl_zeroize( entry_prv, sizeof( x509_crl_entry ) ); + polarssl_free( entry_prv ); + } + + if( crl_cur->raw.p != NULL ) + { + polarssl_zeroize( crl_cur->raw.p, crl_cur->raw.len ); + polarssl_free( crl_cur->raw.p ); + } + + crl_cur = crl_cur->next; + } + while( crl_cur != NULL ); + + crl_cur = crl; + do + { + crl_prv = crl_cur; + crl_cur = crl_cur->next; + + polarssl_zeroize( crl_prv, sizeof( x509_crl ) ); + if( crl_prv != crl ) + polarssl_free( crl_prv ); + } + while( crl_cur != NULL ); +} + +#endif /* POLARSSL_X509_CRL_PARSE_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/x509_crt.c b/component/common/network/ssl/polarssl-1.3.8/library/x509_crt.c new file mode 100644 index 0000000..03cdda8 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/x509_crt.c @@ -0,0 +1,2018 @@ +/* + * X.509 certificate parsing and verification + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * The ITU-T X.509 standard defines a certificate format for PKI. + * + * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) + * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) + * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) + * + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_X509_CRT_PARSE_C) + +#include "polarssl/x509_crt.h" +#include "polarssl/oid.h" +#if defined(POLARSSL_PEM_PARSE_C) +#include "polarssl/pem.h" +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#define polarssl_malloc malloc +#define polarssl_free free +#endif + +#if defined(POLARSSL_THREADING_C) +#include "polarssl/threading.h" +#endif + +#include +#include +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) +#include +#else +#include +#endif + +#if defined(EFIX64) || defined(EFI32) +#include +#endif + +#if defined(POLARSSL_FS_IO) +#include +#if !defined(_WIN32) || defined(EFIX64) || defined(EFI32) +#include +#include +#include +#endif +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + */ +static int x509_get_version( unsigned char **p, + const unsigned char *end, + int *ver ) +{ + int ret; + size_t len; + + if( ( ret = asn1_get_tag( p, end, &len, + ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ) != 0 ) + { + if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) + { + *ver = 0; + return( 0 ); + } + + return( ret ); + } + + end = *p + len; + + if( ( ret = asn1_get_int( p, end, ver ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_VERSION + ret ); + + if( *p != end ) + return( POLARSSL_ERR_X509_INVALID_VERSION + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * Validity ::= SEQUENCE { + * notBefore Time, + * notAfter Time } + */ +static int x509_get_dates( unsigned char **p, + const unsigned char *end, + x509_time *from, + x509_time *to ) +{ + int ret; + size_t len; + + if( ( ret = asn1_get_tag( p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_DATE + ret ); + + end = *p + len; + + if( ( ret = x509_get_time( p, end, from ) ) != 0 ) + return( ret ); + + if( ( ret = x509_get_time( p, end, to ) ) != 0 ) + return( ret ); + + if( *p != end ) + return( POLARSSL_ERR_X509_INVALID_DATE + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * X.509 v2/v3 unique identifier (not parsed) + */ +static int x509_get_uid( unsigned char **p, + const unsigned char *end, + x509_buf *uid, int n ) +{ + int ret; + + if( *p == end ) + return( 0 ); + + uid->tag = **p; + + if( ( ret = asn1_get_tag( p, end, &uid->len, + ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | n ) ) != 0 ) + { + if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) + return( 0 ); + + return( ret ); + } + + uid->p = *p; + *p += uid->len; + + return( 0 ); +} + +static int x509_get_basic_constraints( unsigned char **p, + const unsigned char *end, + int *ca_istrue, + int *max_pathlen ) +{ + int ret; + size_t len; + + /* + * BasicConstraints ::= SEQUENCE { + * cA BOOLEAN DEFAULT FALSE, + * pathLenConstraint INTEGER (0..MAX) OPTIONAL } + */ + *ca_istrue = 0; /* DEFAULT FALSE */ + *max_pathlen = 0; /* endless */ + + if( ( ret = asn1_get_tag( p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( *p == end ) + return( 0 ); + + if( ( ret = asn1_get_bool( p, end, ca_istrue ) ) != 0 ) + { + if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) + ret = asn1_get_int( p, end, ca_istrue ); + + if( ret != 0 ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( *ca_istrue != 0 ) + *ca_istrue = 1; + } + + if( *p == end ) + return( 0 ); + + if( ( ret = asn1_get_int( p, end, max_pathlen ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( *p != end ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + (*max_pathlen)++; + + return( 0 ); +} + +static int x509_get_ns_cert_type( unsigned char **p, + const unsigned char *end, + unsigned char *ns_cert_type) +{ + int ret; + x509_bitstring bs = { 0, 0, NULL }; + + if( ( ret = asn1_get_bitstring( p, end, &bs ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( bs.len != 1 ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + + POLARSSL_ERR_ASN1_INVALID_LENGTH ); + + /* Get actual bitstring */ + *ns_cert_type = *bs.p; + return( 0 ); +} + +static int x509_get_key_usage( unsigned char **p, + const unsigned char *end, + unsigned char *key_usage) +{ + int ret; + x509_bitstring bs = { 0, 0, NULL }; + + if( ( ret = asn1_get_bitstring( p, end, &bs ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( bs.len < 1 ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + + POLARSSL_ERR_ASN1_INVALID_LENGTH ); + + /* Get actual bitstring */ + *key_usage = *bs.p; + return( 0 ); +} + +/* + * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId + * + * KeyPurposeId ::= OBJECT IDENTIFIER + */ +static int x509_get_ext_key_usage( unsigned char **p, + const unsigned char *end, + x509_sequence *ext_key_usage) +{ + int ret; + + if( ( ret = asn1_get_sequence_of( p, end, ext_key_usage, ASN1_OID ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret ); + + /* Sequence length must be >= 1 */ + if( ext_key_usage->buf.p == NULL ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + + POLARSSL_ERR_ASN1_INVALID_LENGTH ); + + return( 0 ); +} + +/* + * SubjectAltName ::= GeneralNames + * + * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName + * + * GeneralName ::= CHOICE { + * otherName [0] OtherName, + * rfc822Name [1] IA5String, + * dNSName [2] IA5String, + * x400Address [3] ORAddress, + * directoryName [4] Name, + * ediPartyName [5] EDIPartyName, + * uniformResourceIdentifier [6] IA5String, + * iPAddress [7] OCTET STRING, + * registeredID [8] OBJECT IDENTIFIER } + * + * OtherName ::= SEQUENCE { + * type-id OBJECT IDENTIFIER, + * value [0] EXPLICIT ANY DEFINED BY type-id } + * + * EDIPartyName ::= SEQUENCE { + * nameAssigner [0] DirectoryString OPTIONAL, + * partyName [1] DirectoryString } + * + * NOTE: PolarSSL only parses and uses dNSName at this point. + */ +static int x509_get_subject_alt_name( unsigned char **p, + const unsigned char *end, + x509_sequence *subject_alt_name ) +{ + int ret; + size_t len, tag_len; + asn1_buf *buf; + unsigned char tag; + asn1_sequence *cur = subject_alt_name; + + /* Get main sequence tag */ + if( ( ret = asn1_get_tag( p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( *p + len != end ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + while( *p < end ) + { + if( ( end - *p ) < 1 ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + + POLARSSL_ERR_ASN1_OUT_OF_DATA ); + + tag = **p; + (*p)++; + if( ( ret = asn1_get_len( p, end, &tag_len ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( ( tag & ASN1_CONTEXT_SPECIFIC ) != ASN1_CONTEXT_SPECIFIC ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + + POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); + + /* Skip everything but DNS name */ + if( tag != ( ASN1_CONTEXT_SPECIFIC | 2 ) ) + { + *p += tag_len; + continue; + } + + /* Allocate and assign next pointer */ + if( cur->buf.p != NULL ) + { + cur->next = (asn1_sequence *) polarssl_malloc( + sizeof( asn1_sequence ) ); + + if( cur->next == NULL ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + + POLARSSL_ERR_ASN1_MALLOC_FAILED ); + + memset( cur->next, 0, sizeof( asn1_sequence ) ); + cur = cur->next; + } + + buf = &(cur->buf); + buf->tag = tag; + buf->p = *p; + buf->len = tag_len; + *p += buf->len; + } + + /* Set final sequence entry's next pointer to NULL */ + cur->next = NULL; + + if( *p != end ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * X.509 v3 extensions + * + * TODO: Perform all of the basic constraints tests required by the RFC + * TODO: Set values for undetected extensions to a sane default? + * + */ +static int x509_get_crt_ext( unsigned char **p, + const unsigned char *end, + x509_crt *crt ) +{ + int ret; + size_t len; + unsigned char *end_ext_data, *end_ext_octet; + + if( ( ret = x509_get_ext( p, end, &crt->v3_ext, 3 ) ) != 0 ) + { + if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) + return( 0 ); + + return( ret ); + } + + while( *p < end ) + { + /* + * Extension ::= SEQUENCE { + * extnID OBJECT IDENTIFIER, + * critical BOOLEAN DEFAULT FALSE, + * extnValue OCTET STRING } + */ + x509_buf extn_oid = {0, 0, NULL}; + int is_critical = 0; /* DEFAULT FALSE */ + int ext_type = 0; + + if( ( ret = asn1_get_tag( p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret ); + + end_ext_data = *p + len; + + /* Get extension ID */ + extn_oid.tag = **p; + + if( ( ret = asn1_get_tag( p, end, &extn_oid.len, ASN1_OID ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret ); + + extn_oid.p = *p; + *p += extn_oid.len; + + if( ( end - *p ) < 1 ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + + POLARSSL_ERR_ASN1_OUT_OF_DATA ); + + /* Get optional critical */ + if( ( ret = asn1_get_bool( p, end_ext_data, &is_critical ) ) != 0 && + ( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret ); + + /* Data should be octet string type */ + if( ( ret = asn1_get_tag( p, end_ext_data, &len, + ASN1_OCTET_STRING ) ) != 0 ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret ); + + end_ext_octet = *p + len; + + if( end_ext_octet != end_ext_data ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + /* + * Detect supported extensions + */ + ret = oid_get_x509_ext_type( &extn_oid, &ext_type ); + + if( ret != 0 ) + { + /* No parser found, skip extension */ + *p = end_ext_octet; + +#if !defined(POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION) + if( is_critical ) + { + /* Data is marked as critical: fail */ + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + + POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); + } +#endif + continue; + } + + crt->ext_types |= ext_type; + + switch( ext_type ) + { + case EXT_BASIC_CONSTRAINTS: + /* Parse basic constraints */ + if( ( ret = x509_get_basic_constraints( p, end_ext_octet, + &crt->ca_istrue, &crt->max_pathlen ) ) != 0 ) + return( ret ); + break; + + case EXT_KEY_USAGE: + /* Parse key usage */ + if( ( ret = x509_get_key_usage( p, end_ext_octet, + &crt->key_usage ) ) != 0 ) + return( ret ); + break; + + case EXT_EXTENDED_KEY_USAGE: + /* Parse extended key usage */ + if( ( ret = x509_get_ext_key_usage( p, end_ext_octet, + &crt->ext_key_usage ) ) != 0 ) + return( ret ); + break; + + case EXT_SUBJECT_ALT_NAME: + /* Parse subject alt name */ + if( ( ret = x509_get_subject_alt_name( p, end_ext_octet, + &crt->subject_alt_names ) ) != 0 ) + return( ret ); + break; + + case EXT_NS_CERT_TYPE: + /* Parse netscape certificate type */ + if( ( ret = x509_get_ns_cert_type( p, end_ext_octet, + &crt->ns_cert_type ) ) != 0 ) + return( ret ); + break; + + default: + return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE ); + } + } + + if( *p != end ) + return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * Parse and fill a single X.509 certificate in DER format + */ +static int x509_crt_parse_der_core( x509_crt *crt, const unsigned char *buf, + size_t buflen ) +{ + int ret; + size_t len; + unsigned char *p, *end, *crt_end; + x509_buf sig_params1, sig_params2; + + memset( &sig_params1, 0, sizeof( x509_buf ) ); + memset( &sig_params2, 0, sizeof( x509_buf ) ); + + /* + * Check for valid input + */ + if( crt == NULL || buf == NULL ) + return( POLARSSL_ERR_X509_BAD_INPUT_DATA ); + + p = (unsigned char *) polarssl_malloc( len = buflen ); + + if( p == NULL ) + return( POLARSSL_ERR_X509_MALLOC_FAILED ); + + memcpy( p, buf, buflen ); + + crt->raw.p = p; + crt->raw.len = len; + end = p + len; + + /* + * Certificate ::= SEQUENCE { + * tbsCertificate TBSCertificate, + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING } + */ + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + x509_crt_free( crt ); + return( POLARSSL_ERR_X509_INVALID_FORMAT ); + } + + if( len > (size_t) ( end - p ) ) + { + x509_crt_free( crt ); + return( POLARSSL_ERR_X509_INVALID_FORMAT + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + } + crt_end = p + len; + + /* + * TBSCertificate ::= SEQUENCE { + */ + crt->tbs.p = p; + + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + x509_crt_free( crt ); + return( POLARSSL_ERR_X509_INVALID_FORMAT + ret ); + } + + end = p + len; + crt->tbs.len = end - crt->tbs.p; + + /* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + * + * CertificateSerialNumber ::= INTEGER + * + * signature AlgorithmIdentifier + */ + if( ( ret = x509_get_version( &p, end, &crt->version ) ) != 0 || + ( ret = x509_get_serial( &p, end, &crt->serial ) ) != 0 || + ( ret = x509_get_alg( &p, end, &crt->sig_oid1, + &sig_params1 ) ) != 0 ) + { + x509_crt_free( crt ); + return( ret ); + } + + crt->version++; + + if( crt->version > 3 ) + { + x509_crt_free( crt ); + return( POLARSSL_ERR_X509_UNKNOWN_VERSION ); + } + + if( ( ret = x509_get_sig_alg( &crt->sig_oid1, &sig_params1, + &crt->sig_md, &crt->sig_pk, + &crt->sig_opts ) ) != 0 ) + { + x509_crt_free( crt ); + return( ret ); + } + + /* + * issuer Name + */ + crt->issuer_raw.p = p; + + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + x509_crt_free( crt ); + return( POLARSSL_ERR_X509_INVALID_FORMAT + ret ); + } + + if( ( ret = x509_get_name( &p, p + len, &crt->issuer ) ) != 0 ) + { + x509_crt_free( crt ); + return( ret ); + } + + crt->issuer_raw.len = p - crt->issuer_raw.p; + + /* + * Validity ::= SEQUENCE { + * notBefore Time, + * notAfter Time } + * + */ + if( ( ret = x509_get_dates( &p, end, &crt->valid_from, + &crt->valid_to ) ) != 0 ) + { + x509_crt_free( crt ); + return( ret ); + } + + /* + * subject Name + */ + crt->subject_raw.p = p; + + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + x509_crt_free( crt ); + return( POLARSSL_ERR_X509_INVALID_FORMAT + ret ); + } + + if( len && ( ret = x509_get_name( &p, p + len, &crt->subject ) ) != 0 ) + { + x509_crt_free( crt ); + return( ret ); + } + + crt->subject_raw.len = p - crt->subject_raw.p; + + /* + * SubjectPublicKeyInfo + */ + if( ( ret = pk_parse_subpubkey( &p, end, &crt->pk ) ) != 0 ) + { + x509_crt_free( crt ); + return( ret ); + } + + /* + * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, + * -- If present, version shall be v2 or v3 + * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, + * -- If present, version shall be v2 or v3 + * extensions [3] EXPLICIT Extensions OPTIONAL + * -- If present, version shall be v3 + */ + if( crt->version == 2 || crt->version == 3 ) + { + ret = x509_get_uid( &p, end, &crt->issuer_id, 1 ); + if( ret != 0 ) + { + x509_crt_free( crt ); + return( ret ); + } + } + + if( crt->version == 2 || crt->version == 3 ) + { + ret = x509_get_uid( &p, end, &crt->subject_id, 2 ); + if( ret != 0 ) + { + x509_crt_free( crt ); + return( ret ); + } + } + +#if !defined(POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3) + if( crt->version == 3 ) + { +#endif + ret = x509_get_crt_ext( &p, end, crt ); + if( ret != 0 ) + { + x509_crt_free( crt ); + return( ret ); + } +#if !defined(POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3) + } +#endif + + if( p != end ) + { + x509_crt_free( crt ); + return( POLARSSL_ERR_X509_INVALID_FORMAT + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + } + + end = crt_end; + + /* + * } + * -- end of TBSCertificate + * + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING + */ + if( ( ret = x509_get_alg( &p, end, &crt->sig_oid2, &sig_params2 ) ) != 0 ) + { + x509_crt_free( crt ); + return( ret ); + } + + if( crt->sig_oid1.len != crt->sig_oid2.len || + memcmp( crt->sig_oid1.p, crt->sig_oid2.p, crt->sig_oid1.len ) != 0 || + sig_params1.len != sig_params2.len || + memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) + { + x509_crt_free( crt ); + return( POLARSSL_ERR_X509_SIG_MISMATCH ); + } + + if( ( ret = x509_get_sig( &p, end, &crt->sig ) ) != 0 ) + { + x509_crt_free( crt ); + return( ret ); + } + + if( p != end ) + { + x509_crt_free( crt ); + return( POLARSSL_ERR_X509_INVALID_FORMAT + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + } + + return( 0 ); +} + +/* + * Parse one X.509 certificate in DER format from a buffer and add them to a + * chained list + */ +int x509_crt_parse_der( x509_crt *chain, const unsigned char *buf, + size_t buflen ) +{ + int ret; + x509_crt *crt = chain, *prev = NULL; + + /* + * Check for valid input + */ + if( crt == NULL || buf == NULL ) + return( POLARSSL_ERR_X509_BAD_INPUT_DATA ); + + while( crt->version != 0 && crt->next != NULL ) + { + prev = crt; + crt = crt->next; + } + + /* + * Add new certificate on the end of the chain if needed. + */ + if( crt->version != 0 && crt->next == NULL ) + { + crt->next = (x509_crt *) polarssl_malloc( sizeof( x509_crt ) ); + + if( crt->next == NULL ) + return( POLARSSL_ERR_X509_MALLOC_FAILED ); + + prev = crt; + crt = crt->next; + x509_crt_init( crt ); + } + + if( ( ret = x509_crt_parse_der_core( crt, buf, buflen ) ) != 0 ) + { + if( prev ) + prev->next = NULL; + + if( crt != chain ) + polarssl_free( crt ); + + return( ret ); + } + + return( 0 ); +} + +/* + * Parse one or more PEM certificates from a buffer and add them to the chained + * list + */ +int x509_crt_parse( x509_crt *chain, const unsigned char *buf, size_t buflen ) +{ + int success = 0, first_error = 0, total_failed = 0; + int buf_format = X509_FORMAT_DER; + + /* + * Check for valid input + */ + if( chain == NULL || buf == NULL ) + return( POLARSSL_ERR_X509_BAD_INPUT_DATA ); + + /* + * Determine buffer content. Buffer contains either one DER certificate or + * one or more PEM certificates. + */ +#if defined(POLARSSL_PEM_PARSE_C) + if( strstr( (const char *) buf, "-----BEGIN CERTIFICATE-----" ) != NULL ) + buf_format = X509_FORMAT_PEM; +#endif + + if( buf_format == X509_FORMAT_DER ) + return x509_crt_parse_der( chain, buf, buflen ); + +#if defined(POLARSSL_PEM_PARSE_C) + if( buf_format == X509_FORMAT_PEM ) + { + int ret; + pem_context pem; + + while( buflen > 0 ) + { + size_t use_len; + pem_init( &pem ); + + ret = pem_read_buffer( &pem, + "-----BEGIN CERTIFICATE-----", + "-----END CERTIFICATE-----", + buf, NULL, 0, &use_len ); + + if( ret == 0 ) + { + /* + * Was PEM encoded + */ + buflen -= use_len; + buf += use_len; + } + else if( ret == POLARSSL_ERR_PEM_BAD_INPUT_DATA ) + { + return( ret ); + } + else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + pem_free( &pem ); + + /* + * PEM header and footer were found + */ + buflen -= use_len; + buf += use_len; + + if( first_error == 0 ) + first_error = ret; + + continue; + } + else + break; + + ret = x509_crt_parse_der( chain, pem.buf, pem.buflen ); + + pem_free( &pem ); + + if( ret != 0 ) + { + /* + * Quit parsing on a memory error + */ + if( ret == POLARSSL_ERR_X509_MALLOC_FAILED ) + return( ret ); + + if( first_error == 0 ) + first_error = ret; + + total_failed++; + continue; + } + + success = 1; + } + } +#endif /* POLARSSL_PEM_PARSE_C */ + + if( success ) + return( total_failed ); + else if( first_error ) + return( first_error ); + else + return( POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT ); +} + +#if defined(POLARSSL_FS_IO) +/* + * Load one or more certificates and add them to the chained list + */ +int x509_crt_parse_file( x509_crt *chain, const char *path ) +{ + int ret; + size_t n; + unsigned char *buf; + + if( ( ret = x509_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = x509_crt_parse( chain, buf, n ); + + polarssl_zeroize( buf, n + 1 ); + polarssl_free( buf ); + + return( ret ); +} + +#if defined(POLARSSL_THREADING_PTHREAD) +static threading_mutex_t readdir_mutex = PTHREAD_MUTEX_INITIALIZER; +#endif + +int x509_crt_parse_path( x509_crt *chain, const char *path ) +{ + int ret = 0; +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + int w_ret; + WCHAR szDir[MAX_PATH]; + char filename[MAX_PATH]; + char *p; + int len = (int) strlen( path ); + + WIN32_FIND_DATAW file_data; + HANDLE hFind; + + if( len > MAX_PATH - 3 ) + return( POLARSSL_ERR_X509_BAD_INPUT_DATA ); + + memset( szDir, 0, sizeof(szDir) ); + memset( filename, 0, MAX_PATH ); + memcpy( filename, path, len ); + filename[len++] = '\\'; + p = filename + len; + filename[len++] = '*'; + + w_ret = MultiByteToWideChar( CP_ACP, 0, filename, len, szDir, + MAX_PATH - 3 ); + + hFind = FindFirstFileW( szDir, &file_data ); + if( hFind == INVALID_HANDLE_VALUE ) + return( POLARSSL_ERR_X509_FILE_IO_ERROR ); + + len = MAX_PATH - len; + do + { + memset( p, 0, len ); + + if( file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) + continue; + + w_ret = WideCharToMultiByte( CP_ACP, 0, file_data.cFileName, + lstrlenW( file_data.cFileName ), + p, len - 1, + NULL, NULL ); + + w_ret = x509_crt_parse_file( chain, filename ); + if( w_ret < 0 ) + ret++; + else + ret += w_ret; + } + while( FindNextFileW( hFind, &file_data ) != 0 ); + + if( GetLastError() != ERROR_NO_MORE_FILES ) + ret = POLARSSL_ERR_X509_FILE_IO_ERROR; + + FindClose( hFind ); +#else /* _WIN32 */ + int t_ret; + struct stat sb; + struct dirent *entry; + char entry_name[255]; + DIR *dir = opendir( path ); + + if( dir == NULL ) + return( POLARSSL_ERR_X509_FILE_IO_ERROR ); + +#if defined(POLARSSL_THREADING_PTHREAD) + if( ( ret = polarssl_mutex_lock( &readdir_mutex ) ) != 0 ) + return( ret ); +#endif + + while( ( entry = readdir( dir ) ) != NULL ) + { + snprintf( entry_name, sizeof entry_name, "%s/%s", path, entry->d_name ); + + if( stat( entry_name, &sb ) == -1 ) + { + closedir( dir ); + ret = POLARSSL_ERR_X509_FILE_IO_ERROR; + goto cleanup; + } + + if( !S_ISREG( sb.st_mode ) ) + continue; + + // Ignore parse errors + // + t_ret = x509_crt_parse_file( chain, entry_name ); + if( t_ret < 0 ) + ret++; + else + ret += t_ret; + } + closedir( dir ); + +cleanup: +#if defined(POLARSSL_THREADING_PTHREAD) + if( polarssl_mutex_unlock( &readdir_mutex ) != 0 ) + ret = POLARSSL_ERR_THREADING_MUTEX_ERROR; +#endif + +#endif /* _WIN32 */ + + return( ret ); +} +#endif /* POLARSSL_FS_IO */ + +#if defined(_MSC_VER) && !defined snprintf && !defined(EFIX64) && \ + !defined(EFI32) +#include + +#if !defined vsnprintf +#define vsnprintf _vsnprintf +#endif // vsnprintf + +/* + * Windows _snprintf and _vsnprintf are not compatible to linux versions. + * Result value is not size of buffer needed, but -1 if no fit is possible. + * + * This fuction tries to 'fix' this by at least suggesting enlarging the + * size by 20. + */ +static int compat_snprintf( char *str, size_t size, const char *format, ... ) +{ + va_list ap; + int res = -1; + + va_start( ap, format ); + + res = vsnprintf( str, size, format, ap ); + + va_end( ap ); + + // No quick fix possible + if( res < 0 ) + return( (int) size + 20 ); + + return( res ); +} + +#define snprintf compat_snprintf +#endif /* _MSC_VER && !snprintf && !EFIX64 && !EFI32 */ + +#define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL -2 + +#define SAFE_SNPRINTF() \ +{ \ + if( ret == -1 ) \ + return( -1 ); \ + \ + if( (unsigned int) ret > n ) { \ + p[n - 1] = '\0'; \ + return( POLARSSL_ERR_DEBUG_BUF_TOO_SMALL ); \ + } \ + \ + n -= (unsigned int) ret; \ + p += (unsigned int) ret; \ +} + +static int x509_info_subject_alt_name( char **buf, size_t *size, + const x509_sequence *subject_alt_name ) +{ + size_t i; + size_t n = *size; + char *p = *buf; + const x509_sequence *cur = subject_alt_name; + const char *sep = ""; + size_t sep_len = 0; + + while( cur != NULL ) + { + if( cur->buf.len + sep_len >= n ) + { + *p = '\0'; + return( POLARSSL_ERR_DEBUG_BUF_TOO_SMALL ); + } + + n -= cur->buf.len + sep_len; + for( i = 0; i < sep_len; i++ ) + *p++ = sep[i]; + for( i = 0; i < cur->buf.len; i++ ) + *p++ = cur->buf.p[i]; + + sep = ", "; + sep_len = 2; + + cur = cur->next; + } + + *p = '\0'; + + *size = n; + *buf = p; + + return( 0 ); +} + +#define PRINT_ITEM(i) \ + { \ + ret = snprintf( p, n, "%s" i, sep ); \ + SAFE_SNPRINTF(); \ + sep = ", "; \ + } + +#define CERT_TYPE(type,name) \ + if( ns_cert_type & type ) \ + PRINT_ITEM( name ); + +static int x509_info_cert_type( char **buf, size_t *size, + unsigned char ns_cert_type ) +{ + int ret; + size_t n = *size; + char *p = *buf; + const char *sep = ""; + + CERT_TYPE( NS_CERT_TYPE_SSL_CLIENT, "SSL Client" ); + CERT_TYPE( NS_CERT_TYPE_SSL_SERVER, "SSL Server" ); + CERT_TYPE( NS_CERT_TYPE_EMAIL, "Email" ); + CERT_TYPE( NS_CERT_TYPE_OBJECT_SIGNING, "Object Signing" ); + CERT_TYPE( NS_CERT_TYPE_RESERVED, "Reserved" ); + CERT_TYPE( NS_CERT_TYPE_SSL_CA, "SSL CA" ); + CERT_TYPE( NS_CERT_TYPE_EMAIL_CA, "Email CA" ); + CERT_TYPE( NS_CERT_TYPE_OBJECT_SIGNING_CA, "Object Signing CA" ); + + *size = n; + *buf = p; + + return( 0 ); +} + +#define KEY_USAGE(code,name) \ + if( key_usage & code ) \ + PRINT_ITEM( name ); + +static int x509_info_key_usage( char **buf, size_t *size, + unsigned char key_usage ) +{ + int ret; + size_t n = *size; + char *p = *buf; + const char *sep = ""; + + KEY_USAGE( KU_DIGITAL_SIGNATURE, "Digital Signature" ); + KEY_USAGE( KU_NON_REPUDIATION, "Non Repudiation" ); + KEY_USAGE( KU_KEY_ENCIPHERMENT, "Key Encipherment" ); + KEY_USAGE( KU_DATA_ENCIPHERMENT, "Data Encipherment" ); + KEY_USAGE( KU_KEY_AGREEMENT, "Key Agreement" ); + KEY_USAGE( KU_KEY_CERT_SIGN, "Key Cert Sign" ); + KEY_USAGE( KU_CRL_SIGN, "CRL Sign" ); + + *size = n; + *buf = p; + + return( 0 ); +} + +static int x509_info_ext_key_usage( char **buf, size_t *size, + const x509_sequence *extended_key_usage ) +{ + int ret; + const char *desc; + size_t n = *size; + char *p = *buf; + const x509_sequence *cur = extended_key_usage; + const char *sep = ""; + + while( cur != NULL ) + { + if( oid_get_extended_key_usage( &cur->buf, &desc ) != 0 ) + desc = "???"; + + ret = snprintf( p, n, "%s%s", sep, desc ); + SAFE_SNPRINTF(); + + sep = ", "; + + cur = cur->next; + } + + *size = n; + *buf = p; + + return( 0 ); +} + +/* + * Return an informational string about the certificate. + */ +#define BEFORE_COLON 18 +#define BC "18" +int x509_crt_info( char *buf, size_t size, const char *prefix, + const x509_crt *crt ) +{ + int ret; + size_t n; + char *p; + char key_size_str[BEFORE_COLON]; + + p = buf; + n = size; + + ret = snprintf( p, n, "%scert. version : %d\n", + prefix, crt->version ); + SAFE_SNPRINTF(); + ret = snprintf( p, n, "%sserial number : ", + prefix ); + SAFE_SNPRINTF(); + + ret = x509_serial_gets( p, n, &crt->serial ); + SAFE_SNPRINTF(); + + ret = snprintf( p, n, "\n%sissuer name : ", prefix ); + SAFE_SNPRINTF(); + ret = x509_dn_gets( p, n, &crt->issuer ); + SAFE_SNPRINTF(); + + ret = snprintf( p, n, "\n%ssubject name : ", prefix ); + SAFE_SNPRINTF(); + ret = x509_dn_gets( p, n, &crt->subject ); + SAFE_SNPRINTF(); + + ret = snprintf( p, n, "\n%sissued on : " \ + "%04d-%02d-%02d %02d:%02d:%02d", prefix, + crt->valid_from.year, crt->valid_from.mon, + crt->valid_from.day, crt->valid_from.hour, + crt->valid_from.min, crt->valid_from.sec ); + SAFE_SNPRINTF(); + + ret = snprintf( p, n, "\n%sexpires on : " \ + "%04d-%02d-%02d %02d:%02d:%02d", prefix, + crt->valid_to.year, crt->valid_to.mon, + crt->valid_to.day, crt->valid_to.hour, + crt->valid_to.min, crt->valid_to.sec ); + SAFE_SNPRINTF(); + + ret = snprintf( p, n, "\n%ssigned using : ", prefix ); + SAFE_SNPRINTF(); + + ret = x509_sig_alg_gets( p, n, &crt->sig_oid1, crt->sig_pk, + crt->sig_md, crt->sig_opts ); + SAFE_SNPRINTF(); + + /* Key size */ + if( ( ret = x509_key_size_helper( key_size_str, BEFORE_COLON, + pk_get_name( &crt->pk ) ) ) != 0 ) + { + return( ret ); + } + + ret = snprintf( p, n, "\n%s%-" BC "s: %d bits", prefix, key_size_str, + (int) pk_get_size( &crt->pk ) ); + SAFE_SNPRINTF(); + + /* + * Optional extensions + */ + + if( crt->ext_types & EXT_BASIC_CONSTRAINTS ) + { + ret = snprintf( p, n, "\n%sbasic constraints : CA=%s", prefix, + crt->ca_istrue ? "true" : "false" ); + SAFE_SNPRINTF(); + + if( crt->max_pathlen > 0 ) + { + ret = snprintf( p, n, ", max_pathlen=%d", crt->max_pathlen - 1 ); + SAFE_SNPRINTF(); + } + } + + if( crt->ext_types & EXT_SUBJECT_ALT_NAME ) + { + ret = snprintf( p, n, "\n%ssubject alt name : ", prefix ); + SAFE_SNPRINTF(); + + if( ( ret = x509_info_subject_alt_name( &p, &n, + &crt->subject_alt_names ) ) != 0 ) + return( ret ); + } + + if( crt->ext_types & EXT_NS_CERT_TYPE ) + { + ret = snprintf( p, n, "\n%scert. type : ", prefix ); + SAFE_SNPRINTF(); + + if( ( ret = x509_info_cert_type( &p, &n, crt->ns_cert_type ) ) != 0 ) + return( ret ); + } + + if( crt->ext_types & EXT_KEY_USAGE ) + { + ret = snprintf( p, n, "\n%skey usage : ", prefix ); + SAFE_SNPRINTF(); + + if( ( ret = x509_info_key_usage( &p, &n, crt->key_usage ) ) != 0 ) + return( ret ); + } + + if( crt->ext_types & EXT_EXTENDED_KEY_USAGE ) + { + ret = snprintf( p, n, "\n%sext key usage : ", prefix ); + SAFE_SNPRINTF(); + + if( ( ret = x509_info_ext_key_usage( &p, &n, + &crt->ext_key_usage ) ) != 0 ) + return( ret ); + } + + ret = snprintf( p, n, "\n" ); + SAFE_SNPRINTF(); + + return( (int) ( size - n ) ); +} + +#if defined(POLARSSL_X509_CHECK_KEY_USAGE) +int x509_crt_check_key_usage( const x509_crt *crt, int usage ) +{ + if( ( crt->ext_types & EXT_KEY_USAGE ) != 0 && + ( crt->key_usage & usage ) != usage ) + return( POLARSSL_ERR_X509_BAD_INPUT_DATA ); + + return( 0 ); +} +#endif + +#if defined(POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE) +int x509_crt_check_extended_key_usage( const x509_crt *crt, + const char *usage_oid, + size_t usage_len ) +{ + const x509_sequence *cur; + + /* Extension is not mandatory, absent means no restriction */ + if( ( crt->ext_types & EXT_EXTENDED_KEY_USAGE ) == 0 ) + return( 0 ); + + /* + * Look for the requested usage (or wildcard ANY) in our list + */ + for( cur = &crt->ext_key_usage; cur != NULL; cur = cur->next ) + { + const x509_buf *cur_oid = &cur->buf; + + if( cur_oid->len == usage_len && + memcmp( cur_oid->p, usage_oid, usage_len ) == 0 ) + { + return( 0 ); + } + + if( OID_CMP( OID_ANY_EXTENDED_KEY_USAGE, cur_oid ) ) + return( 0 ); + } + + return( POLARSSL_ERR_X509_BAD_INPUT_DATA ); +} +#endif /* POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE */ + +#if defined(POLARSSL_X509_CRL_PARSE_C) +/* + * Return 1 if the certificate is revoked, or 0 otherwise. + */ +int x509_crt_revoked( const x509_crt *crt, const x509_crl *crl ) +{ + const x509_crl_entry *cur = &crl->entry; + + while( cur != NULL && cur->serial.len != 0 ) + { + if( crt->serial.len == cur->serial.len && + memcmp( crt->serial.p, cur->serial.p, crt->serial.len ) == 0 ) + { + if( x509_time_expired( &cur->revocation_date ) ) + return( 1 ); + } + + cur = cur->next; + } + + return( 0 ); +} + +/* + * Check that the given certificate is valid according to the CRL. + */ +static int x509_crt_verifycrl( x509_crt *crt, x509_crt *ca, + x509_crl *crl_list) +{ + int flags = 0; + unsigned char hash[POLARSSL_MD_MAX_SIZE]; + const md_info_t *md_info; + + if( ca == NULL ) + return( flags ); + + /* + * TODO: What happens if no CRL is present? + * Suggestion: Revocation state should be unknown if no CRL is present. + * For backwards compatibility this is not yet implemented. + */ + + while( crl_list != NULL ) + { + if( crl_list->version == 0 || + crl_list->issuer_raw.len != ca->subject_raw.len || + memcmp( crl_list->issuer_raw.p, ca->subject_raw.p, + crl_list->issuer_raw.len ) != 0 ) + { + crl_list = crl_list->next; + continue; + } + + /* + * Check if the CA is configured to sign CRLs + */ +#if defined(POLARSSL_X509_CHECK_KEY_USAGE) + if( x509_crt_check_key_usage( ca, KU_CRL_SIGN ) != 0 ) + { + flags |= BADCRL_NOT_TRUSTED; + break; + } +#endif + + /* + * Check if CRL is correctly signed by the trusted CA + */ + md_info = md_info_from_type( crl_list->sig_md ); + if( md_info == NULL ) + { + /* + * Cannot check 'unknown' hash + */ + flags |= BADCRL_NOT_TRUSTED; + break; + } + + md( md_info, crl_list->tbs.p, crl_list->tbs.len, hash ); + + if( pk_verify_ext( crl_list->sig_pk, crl_list->sig_opts, &ca->pk, + crl_list->sig_md, hash, md_info->size, + crl_list->sig.p, crl_list->sig.len ) != 0 ) + { + flags |= BADCRL_NOT_TRUSTED; + break; + } + + /* + * Check for validity of CRL (Do not drop out) + */ + if( x509_time_expired( &crl_list->next_update ) ) + flags |= BADCRL_EXPIRED; + + if( x509_time_future( &crl_list->this_update ) ) + flags |= BADCRL_FUTURE; + + /* + * Check if certificate is revoked + */ + if( x509_crt_revoked( crt, crl_list ) ) + { + flags |= BADCERT_REVOKED; + break; + } + + crl_list = crl_list->next; + } + return( flags ); +} +#endif /* POLARSSL_X509_CRL_PARSE_C */ + +// Equal == 0, inequal == 1 +static int x509_name_cmp( const void *s1, const void *s2, size_t len ) +{ + size_t i; + unsigned char diff; + const unsigned char *n1 = s1, *n2 = s2; + + for( i = 0; i < len; i++ ) + { + diff = n1[i] ^ n2[i]; + + if( diff == 0 ) + continue; + + if( diff == 32 && + ( ( n1[i] >= 'a' && n1[i] <= 'z' ) || + ( n1[i] >= 'A' && n1[i] <= 'Z' ) ) ) + { + continue; + } + + return( 1 ); + } + + return( 0 ); +} + +static int x509_wildcard_verify( const char *cn, x509_buf *name ) +{ + size_t i; + size_t cn_idx = 0, cn_len = strlen( cn ); + + if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' ) + return( 0 ); + + for( i = 0; i < cn_len; ++i ) + { + if( cn[i] == '.' ) + { + cn_idx = i; + break; + } + } + + if( cn_idx == 0 ) + return( 0 ); + + if( cn_len - cn_idx == name->len - 1 && + x509_name_cmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 ) + { + return( 1 ); + } + + return( 0 ); +} + +/* + * Check if 'parent' is a suitable parent (signing CA) for 'child'. + * Return 0 if yes, -1 if not. + * + * top means parent is a locally-trusted certificate + * bottom means child is the end entity cert + */ +static int x509_crt_check_parent( const x509_crt *child, + const x509_crt *parent, + int top, int bottom ) +{ + int need_ca_bit; + + /* Parent must be the issuer */ + if( child->issuer_raw.len != parent->subject_raw.len || + memcmp( child->issuer_raw.p, parent->subject_raw.p, + child->issuer_raw.len ) != 0 ) + { + return( -1 ); + } + + /* Parent must have the basicConstraints CA bit set as a general rule */ + need_ca_bit = 1; + + /* Exception: v1/v2 certificates that are locally trusted. */ + if( top && parent->version < 3 ) + need_ca_bit = 0; + + /* Exception: self-signed end-entity certs that are locally trusted. */ + if( top && bottom && + child->raw.len == parent->raw.len && + memcmp( child->raw.p, parent->raw.p, child->raw.len ) == 0 ) + { + need_ca_bit = 0; + } + + if( need_ca_bit && ! parent->ca_istrue ) + return( -1 ); + +#if defined(POLARSSL_X509_CHECK_KEY_USAGE) + if( need_ca_bit && + x509_crt_check_key_usage( parent, KU_KEY_CERT_SIGN ) != 0 ) + { + return( -1 ); + } +#endif + + return( 0 ); +} + +static int x509_crt_verify_top( + x509_crt *child, x509_crt *trust_ca, + x509_crl *ca_crl, int path_cnt, int *flags, + int (*f_vrfy)(void *, x509_crt *, int, int *), + void *p_vrfy ) +{ + int ret; + int ca_flags = 0, check_path_cnt = path_cnt + 1; + unsigned char hash[POLARSSL_MD_MAX_SIZE]; + const md_info_t *md_info; + + if( x509_time_expired( &child->valid_to ) ) + *flags |= BADCERT_EXPIRED; + + if( x509_time_future( &child->valid_from ) ) + *flags |= BADCERT_FUTURE; + + /* + * Child is the top of the chain. Check against the trust_ca list. + */ + *flags |= BADCERT_NOT_TRUSTED; + + md_info = md_info_from_type( child->sig_md ); + if( md_info == NULL ) + { + /* + * Cannot check 'unknown', no need to try any CA + */ + trust_ca = NULL; + } + else + md( md_info, child->tbs.p, child->tbs.len, hash ); + + for( /* trust_ca */ ; trust_ca != NULL; trust_ca = trust_ca->next ) + { + if( x509_crt_check_parent( child, trust_ca, 1, path_cnt == 0 ) != 0 ) + continue; + + /* + * Reduce path_len to check against if top of the chain is + * the same as the trusted CA + */ + if( child->subject_raw.len == trust_ca->subject_raw.len && + memcmp( child->subject_raw.p, trust_ca->subject_raw.p, + child->issuer_raw.len ) == 0 ) + { + check_path_cnt--; + } + + if( trust_ca->max_pathlen > 0 && + trust_ca->max_pathlen < check_path_cnt ) + { + continue; + } + + if( pk_verify_ext( child->sig_pk, child->sig_opts, &trust_ca->pk, + child->sig_md, hash, md_info->size, + child->sig.p, child->sig.len ) != 0 ) + { + continue; + } + + /* + * Top of chain is signed by a trusted CA + */ + *flags &= ~BADCERT_NOT_TRUSTED; + break; + } + + /* + * If top of chain is not the same as the trusted CA send a verify request + * to the callback for any issues with validity and CRL presence for the + * trusted CA certificate. + */ + if( trust_ca != NULL && + ( child->subject_raw.len != trust_ca->subject_raw.len || + memcmp( child->subject_raw.p, trust_ca->subject_raw.p, + child->issuer_raw.len ) != 0 ) ) + { +#if defined(POLARSSL_X509_CRL_PARSE_C) + /* Check trusted CA's CRL for the chain's top crt */ + *flags |= x509_crt_verifycrl( child, trust_ca, ca_crl ); +#else + ((void) ca_crl); +#endif + + if( x509_time_expired( &trust_ca->valid_to ) ) + ca_flags |= BADCERT_EXPIRED; + + if( x509_time_future( &trust_ca->valid_from ) ) + ca_flags |= BADCERT_FUTURE; + + if( NULL != f_vrfy ) + { + if( ( ret = f_vrfy( p_vrfy, trust_ca, path_cnt + 1, + &ca_flags ) ) != 0 ) + { + return( ret ); + } + } + } + + /* Call callback on top cert */ + if( NULL != f_vrfy ) + { + if( ( ret = f_vrfy( p_vrfy, child, path_cnt, flags ) ) != 0 ) + return( ret ); + } + + *flags |= ca_flags; + + return( 0 ); +} + +static int x509_crt_verify_child( + x509_crt *child, x509_crt *parent, x509_crt *trust_ca, + x509_crl *ca_crl, int path_cnt, int *flags, + int (*f_vrfy)(void *, x509_crt *, int, int *), + void *p_vrfy ) +{ + int ret; + int parent_flags = 0; + unsigned char hash[POLARSSL_MD_MAX_SIZE]; + x509_crt *grandparent; + const md_info_t *md_info; + + if( x509_time_expired( &child->valid_to ) ) + *flags |= BADCERT_EXPIRED; + + if( x509_time_future( &child->valid_from ) ) + *flags |= BADCERT_FUTURE; + + md_info = md_info_from_type( child->sig_md ); + if( md_info == NULL ) + { + /* + * Cannot check 'unknown' hash + */ + *flags |= BADCERT_NOT_TRUSTED; + } + else + { + md( md_info, child->tbs.p, child->tbs.len, hash ); + + if( pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk, + child->sig_md, hash, md_info->size, + child->sig.p, child->sig.len ) != 0 ) + { + *flags |= BADCERT_NOT_TRUSTED; + } + } + +#if defined(POLARSSL_X509_CRL_PARSE_C) + /* Check trusted CA's CRL for the given crt */ + *flags |= x509_crt_verifycrl(child, parent, ca_crl); +#endif + + /* Look for a grandparent upwards the chain */ + for( grandparent = parent->next; + grandparent != NULL; + grandparent = grandparent->next ) + { + if( x509_crt_check_parent( parent, grandparent, + 0, path_cnt == 0 ) == 0 ) + break; + } + + /* Is our parent part of the chain or at the top? */ + if( grandparent != NULL ) + { + ret = x509_crt_verify_child( parent, grandparent, trust_ca, ca_crl, + path_cnt + 1, &parent_flags, f_vrfy, p_vrfy ); + if( ret != 0 ) + return( ret ); + } + else + { + ret = x509_crt_verify_top( parent, trust_ca, ca_crl, + path_cnt + 1, &parent_flags, f_vrfy, p_vrfy ); + if( ret != 0 ) + return( ret ); + } + + /* child is verified to be a child of the parent, call verify callback */ + if( NULL != f_vrfy ) + if( ( ret = f_vrfy( p_vrfy, child, path_cnt, flags ) ) != 0 ) + return( ret ); + + *flags |= parent_flags; + + return( 0 ); +} + +/* + * Verify the certificate validity + */ +int x509_crt_verify( x509_crt *crt, + x509_crt *trust_ca, + x509_crl *ca_crl, + const char *cn, int *flags, + int (*f_vrfy)(void *, x509_crt *, int, int *), + void *p_vrfy ) +{ + size_t cn_len; + int ret; + int pathlen = 0; + x509_crt *parent; + x509_name *name; + x509_sequence *cur = NULL; + + *flags = 0; + + if( cn != NULL ) + { + name = &crt->subject; + cn_len = strlen( cn ); + + if( crt->ext_types & EXT_SUBJECT_ALT_NAME ) + { + cur = &crt->subject_alt_names; + + while( cur != NULL ) + { + if( cur->buf.len == cn_len && + x509_name_cmp( cn, cur->buf.p, cn_len ) == 0 ) + break; + + if( cur->buf.len > 2 && + memcmp( cur->buf.p, "*.", 2 ) == 0 && + x509_wildcard_verify( cn, &cur->buf ) ) + break; + + cur = cur->next; + } + + if( cur == NULL ) + *flags |= BADCERT_CN_MISMATCH; + } + else + { + while( name != NULL ) + { + if( OID_CMP( OID_AT_CN, &name->oid ) ) + { + if( name->val.len == cn_len && + x509_name_cmp( name->val.p, cn, cn_len ) == 0 ) + break; + + if( name->val.len > 2 && + memcmp( name->val.p, "*.", 2 ) == 0 && + x509_wildcard_verify( cn, &name->val ) ) + break; + } + + name = name->next; + } + + if( name == NULL ) + *flags |= BADCERT_CN_MISMATCH; + } + } + + /* Look for a parent upwards the chain */ + for( parent = crt->next; parent != NULL; parent = parent->next ) + { + if( x509_crt_check_parent( crt, parent, 0, pathlen == 0 ) == 0 ) + break; + } + + /* Are we part of the chain or at the top? */ + if( parent != NULL ) + { + ret = x509_crt_verify_child( crt, parent, trust_ca, ca_crl, + pathlen, flags, f_vrfy, p_vrfy ); + if( ret != 0 ) + return( ret ); + } + else + { + ret = x509_crt_verify_top( crt, trust_ca, ca_crl, + pathlen, flags, f_vrfy, p_vrfy ); + if( ret != 0 ) + return( ret ); + } + + if( *flags != 0 ) + return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED ); + + return( 0 ); +} + +/* + * Initialize a certificate chain + */ +void x509_crt_init( x509_crt *crt ) +{ + memset( crt, 0, sizeof(x509_crt) ); +} + +/* + * Unallocate all certificate data + */ +void x509_crt_free( x509_crt *crt ) +{ + x509_crt *cert_cur = crt; + x509_crt *cert_prv; + x509_name *name_cur; + x509_name *name_prv; + x509_sequence *seq_cur; + x509_sequence *seq_prv; + + if( crt == NULL ) + return; + + do + { + pk_free( &cert_cur->pk ); + +#if defined(POLARSSL_X509_RSASSA_PSS_SUPPORT) + polarssl_free( cert_cur->sig_opts ); +#endif + + name_cur = cert_cur->issuer.next; + while( name_cur != NULL ) + { + name_prv = name_cur; + name_cur = name_cur->next; + polarssl_zeroize( name_prv, sizeof( x509_name ) ); + polarssl_free( name_prv ); + } + + name_cur = cert_cur->subject.next; + while( name_cur != NULL ) + { + name_prv = name_cur; + name_cur = name_cur->next; + polarssl_zeroize( name_prv, sizeof( x509_name ) ); + polarssl_free( name_prv ); + } + + seq_cur = cert_cur->ext_key_usage.next; + while( seq_cur != NULL ) + { + seq_prv = seq_cur; + seq_cur = seq_cur->next; + polarssl_zeroize( seq_prv, sizeof( x509_sequence ) ); + polarssl_free( seq_prv ); + } + + seq_cur = cert_cur->subject_alt_names.next; + while( seq_cur != NULL ) + { + seq_prv = seq_cur; + seq_cur = seq_cur->next; + polarssl_zeroize( seq_prv, sizeof( x509_sequence ) ); + polarssl_free( seq_prv ); + } + + if( cert_cur->raw.p != NULL ) + { + polarssl_zeroize( cert_cur->raw.p, cert_cur->raw.len ); + polarssl_free( cert_cur->raw.p ); + } + + cert_cur = cert_cur->next; + } + while( cert_cur != NULL ); + + cert_cur = crt; + do + { + cert_prv = cert_cur; + cert_cur = cert_cur->next; + + polarssl_zeroize( cert_prv, sizeof( x509_crt ) ); + if( cert_prv != crt ) + polarssl_free( cert_prv ); + } + while( cert_cur != NULL ); +} + +#endif /* POLARSSL_X509_CRT_PARSE_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/x509_csr.c b/component/common/network/ssl/polarssl-1.3.8/library/x509_csr.c new file mode 100644 index 0000000..0b4f771 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/x509_csr.c @@ -0,0 +1,465 @@ +/* + * X.509 Certificate Signing Request (CSR) parsing + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * The ITU-T X.509 standard defines a certificate format for PKI. + * + * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) + * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) + * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) + * + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_X509_CSR_PARSE_C) + +#include "polarssl/x509_csr.h" +#include "polarssl/oid.h" +#if defined(POLARSSL_PEM_PARSE_C) +#include "polarssl/pem.h" +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#define polarssl_malloc malloc +#define polarssl_free free +#endif + +#include +#include + +#if defined(POLARSSL_FS_IO) || defined(EFIX64) || defined(EFI32) +#include +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * Version ::= INTEGER { v1(0) } + */ +static int x509_csr_get_version( unsigned char **p, + const unsigned char *end, + int *ver ) +{ + int ret; + + if( ( ret = asn1_get_int( p, end, ver ) ) != 0 ) + { + if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) + { + *ver = 0; + return( 0 ); + } + + return( POLARSSL_ERR_X509_INVALID_VERSION + ret ); + } + + return( 0 ); +} + +/* + * Parse a CSR in DER format + */ +int x509_csr_parse_der( x509_csr *csr, + const unsigned char *buf, size_t buflen ) +{ + int ret; + size_t len; + unsigned char *p, *end; + x509_buf sig_params; + + memset( &sig_params, 0, sizeof( x509_buf ) ); + + /* + * Check for valid input + */ + if( csr == NULL || buf == NULL ) + return( POLARSSL_ERR_X509_BAD_INPUT_DATA ); + + x509_csr_init( csr ); + + /* + * first copy the raw DER data + */ + p = (unsigned char *) polarssl_malloc( len = buflen ); + + if( p == NULL ) + return( POLARSSL_ERR_X509_MALLOC_FAILED ); + + memcpy( p, buf, buflen ); + + csr->raw.p = p; + csr->raw.len = len; + end = p + len; + + /* + * CertificationRequest ::= SEQUENCE { + * certificationRequestInfo CertificationRequestInfo, + * signatureAlgorithm AlgorithmIdentifier, + * signature BIT STRING + * } + */ + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + x509_csr_free( csr ); + return( POLARSSL_ERR_X509_INVALID_FORMAT ); + } + + if( len != (size_t) ( end - p ) ) + { + x509_csr_free( csr ); + return( POLARSSL_ERR_X509_INVALID_FORMAT + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + } + + /* + * CertificationRequestInfo ::= SEQUENCE { + */ + csr->cri.p = p; + + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + x509_csr_free( csr ); + return( POLARSSL_ERR_X509_INVALID_FORMAT + ret ); + } + + end = p + len; + csr->cri.len = end - csr->cri.p; + + /* + * Version ::= INTEGER { v1(0) } + */ + if( ( ret = x509_csr_get_version( &p, end, &csr->version ) ) != 0 ) + { + x509_csr_free( csr ); + return( ret ); + } + + csr->version++; + + if( csr->version != 1 ) + { + x509_csr_free( csr ); + return( POLARSSL_ERR_X509_UNKNOWN_VERSION ); + } + + /* + * subject Name + */ + csr->subject_raw.p = p; + + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + x509_csr_free( csr ); + return( POLARSSL_ERR_X509_INVALID_FORMAT + ret ); + } + + if( ( ret = x509_get_name( &p, p + len, &csr->subject ) ) != 0 ) + { + x509_csr_free( csr ); + return( ret ); + } + + csr->subject_raw.len = p - csr->subject_raw.p; + + /* + * subjectPKInfo SubjectPublicKeyInfo + */ + if( ( ret = pk_parse_subpubkey( &p, end, &csr->pk ) ) != 0 ) + { + x509_csr_free( csr ); + return( ret ); + } + + /* + * attributes [0] Attributes + */ + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC ) ) != 0 ) + { + x509_csr_free( csr ); + return( POLARSSL_ERR_X509_INVALID_FORMAT + ret ); + } + // TODO Parse Attributes / extension requests + + p += len; + + end = csr->raw.p + csr->raw.len; + + /* + * signatureAlgorithm AlgorithmIdentifier, + * signature BIT STRING + */ + if( ( ret = x509_get_alg( &p, end, &csr->sig_oid, &sig_params ) ) != 0 ) + { + x509_csr_free( csr ); + return( ret ); + } + + if( ( ret = x509_get_sig_alg( &csr->sig_oid, &sig_params, + &csr->sig_md, &csr->sig_pk, + &csr->sig_opts ) ) != 0 ) + { + x509_csr_free( csr ); + return( POLARSSL_ERR_X509_UNKNOWN_SIG_ALG ); + } + + if( ( ret = x509_get_sig( &p, end, &csr->sig ) ) != 0 ) + { + x509_csr_free( csr ); + return( ret ); + } + + if( p != end ) + { + x509_csr_free( csr ); + return( POLARSSL_ERR_X509_INVALID_FORMAT + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + } + + return( 0 ); +} + +/* + * Parse a CSR, allowing for PEM or raw DER encoding + */ +int x509_csr_parse( x509_csr *csr, const unsigned char *buf, size_t buflen ) +{ + int ret; +#if defined(POLARSSL_PEM_PARSE_C) + size_t use_len; + pem_context pem; +#endif + + /* + * Check for valid input + */ + if( csr == NULL || buf == NULL ) + return( POLARSSL_ERR_X509_BAD_INPUT_DATA ); + +#if defined(POLARSSL_PEM_PARSE_C) + pem_init( &pem ); + ret = pem_read_buffer( &pem, + "-----BEGIN CERTIFICATE REQUEST-----", + "-----END CERTIFICATE REQUEST-----", + buf, NULL, 0, &use_len ); + + if( ret == 0 ) + { + /* + * Was PEM encoded, parse the result + */ + if( ( ret = x509_csr_parse_der( csr, pem.buf, pem.buflen ) ) != 0 ) + return( ret ); + + pem_free( &pem ); + return( 0 ); + } + else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + pem_free( &pem ); + return( ret ); + } + else +#endif /* POLARSSL_PEM_PARSE_C */ + return( x509_csr_parse_der( csr, buf, buflen ) ); +} + +#if defined(POLARSSL_FS_IO) +/* + * Load a CSR into the structure + */ +int x509_csr_parse_file( x509_csr *csr, const char *path ) +{ + int ret; + size_t n; + unsigned char *buf; + + if( ( ret = x509_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = x509_csr_parse( csr, buf, n ); + + polarssl_zeroize( buf, n + 1 ); + polarssl_free( buf ); + + return( ret ); +} +#endif /* POLARSSL_FS_IO */ + +#if defined(_MSC_VER) && !defined snprintf && !defined(EFIX64) && \ + !defined(EFI32) +#include + +#if !defined vsnprintf +#define vsnprintf _vsnprintf +#endif // vsnprintf + +/* + * Windows _snprintf and _vsnprintf are not compatible to linux versions. + * Result value is not size of buffer needed, but -1 if no fit is possible. + * + * This fuction tries to 'fix' this by at least suggesting enlarging the + * size by 20. + */ +static int compat_snprintf( char *str, size_t size, const char *format, ... ) +{ + va_list ap; + int res = -1; + + va_start( ap, format ); + + res = vsnprintf( str, size, format, ap ); + + va_end( ap ); + + // No quick fix possible + if( res < 0 ) + return( (int) size + 20 ); + + return( res ); +} + +#define snprintf compat_snprintf +#endif /* _MSC_VER && !snprintf && !EFIX64 && !EFI32 */ + +#define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL -2 + +#define SAFE_SNPRINTF() \ +{ \ + if( ret == -1 ) \ + return( -1 ); \ + \ + if( (unsigned int) ret > n ) { \ + p[n - 1] = '\0'; \ + return( POLARSSL_ERR_DEBUG_BUF_TOO_SMALL ); \ + } \ + \ + n -= (unsigned int) ret; \ + p += (unsigned int) ret; \ +} + +#define BEFORE_COLON 14 +#define BC "14" +/* + * Return an informational string about the CSR. + */ +int x509_csr_info( char *buf, size_t size, const char *prefix, + const x509_csr *csr ) +{ + int ret; + size_t n; + char *p; + char key_size_str[BEFORE_COLON]; + + p = buf; + n = size; + + ret = snprintf( p, n, "%sCSR version : %d", + prefix, csr->version ); + SAFE_SNPRINTF(); + + ret = snprintf( p, n, "\n%ssubject name : ", prefix ); + SAFE_SNPRINTF(); + ret = x509_dn_gets( p, n, &csr->subject ); + SAFE_SNPRINTF(); + + ret = snprintf( p, n, "\n%ssigned using : ", prefix ); + SAFE_SNPRINTF(); + + ret = x509_sig_alg_gets( p, n, &csr->sig_oid, csr->sig_pk, csr->sig_md, + csr->sig_opts ); + SAFE_SNPRINTF(); + + if( ( ret = x509_key_size_helper( key_size_str, BEFORE_COLON, + pk_get_name( &csr->pk ) ) ) != 0 ) + { + return( ret ); + } + + ret = snprintf( p, n, "\n%s%-" BC "s: %d bits\n", prefix, key_size_str, + (int) pk_get_size( &csr->pk ) ); + SAFE_SNPRINTF(); + + return( (int) ( size - n ) ); +} + +/* + * Initialize a CSR + */ +void x509_csr_init( x509_csr *csr ) +{ + memset( csr, 0, sizeof(x509_csr) ); +} + +/* + * Unallocate all CSR data + */ +void x509_csr_free( x509_csr *csr ) +{ + x509_name *name_cur; + x509_name *name_prv; + + if( csr == NULL ) + return; + + pk_free( &csr->pk ); + +#if defined(POLARSSL_X509_RSASSA_PSS_SUPPORT) + polarssl_free( csr->sig_opts ); +#endif + + name_cur = csr->subject.next; + while( name_cur != NULL ) + { + name_prv = name_cur; + name_cur = name_cur->next; + polarssl_zeroize( name_prv, sizeof( x509_name ) ); + polarssl_free( name_prv ); + } + + if( csr->raw.p != NULL ) + { + polarssl_zeroize( csr->raw.p, csr->raw.len ); + polarssl_free( csr->raw.p ); + } + + polarssl_zeroize( csr, sizeof( x509_csr ) ); +} + +#endif /* POLARSSL_X509_CSR_PARSE_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/x509write_crt.c b/component/common/network/ssl/polarssl-1.3.8/library/x509write_crt.c new file mode 100644 index 0000000..e298c24 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/x509write_crt.c @@ -0,0 +1,452 @@ +/* + * X.509 certificate writing + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * References: + * - certificates: RFC 5280, updated by RFC 6818 + * - CSRs: PKCS#10 v1.7 aka RFC 2986 + * - attributes: PKCS#9 v2.0 aka RFC 2985 + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_X509_CRT_WRITE_C) + +#include "polarssl/x509_crt.h" +#include "polarssl/oid.h" +#include "polarssl/asn1write.h" +#include "polarssl/sha1.h" + +#if defined(POLARSSL_PEM_WRITE_C) +#include "polarssl/pem.h" +#endif /* POLARSSL_PEM_WRITE_C */ + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +void x509write_crt_init( x509write_cert *ctx ) +{ + memset( ctx, 0, sizeof(x509write_cert) ); + + mpi_init( &ctx->serial ); + ctx->version = X509_CRT_VERSION_3; +} + +void x509write_crt_free( x509write_cert *ctx ) +{ + mpi_free( &ctx->serial ); + + asn1_free_named_data_list( &ctx->subject ); + asn1_free_named_data_list( &ctx->issuer ); + asn1_free_named_data_list( &ctx->extensions ); + + polarssl_zeroize( ctx, sizeof(x509write_cert) ); +} + +void x509write_crt_set_version( x509write_cert *ctx, int version ) +{ + ctx->version = version; +} + +void x509write_crt_set_md_alg( x509write_cert *ctx, md_type_t md_alg ) +{ + ctx->md_alg = md_alg; +} + +void x509write_crt_set_subject_key( x509write_cert *ctx, pk_context *key ) +{ + ctx->subject_key = key; +} + +void x509write_crt_set_issuer_key( x509write_cert *ctx, pk_context *key ) +{ + ctx->issuer_key = key; +} + +int x509write_crt_set_subject_name( x509write_cert *ctx, + const char *subject_name ) +{ + return x509_string_to_names( &ctx->subject, subject_name ); +} + +int x509write_crt_set_issuer_name( x509write_cert *ctx, + const char *issuer_name ) +{ + return x509_string_to_names( &ctx->issuer, issuer_name ); +} + +int x509write_crt_set_serial( x509write_cert *ctx, const mpi *serial ) +{ + int ret; + + if( ( ret = mpi_copy( &ctx->serial, serial ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +int x509write_crt_set_validity( x509write_cert *ctx, const char *not_before, + const char *not_after ) +{ + if( strlen( not_before ) != X509_RFC5280_UTC_TIME_LEN - 1 || + strlen( not_after ) != X509_RFC5280_UTC_TIME_LEN - 1 ) + { + return( POLARSSL_ERR_X509_BAD_INPUT_DATA ); + } + strncpy( ctx->not_before, not_before, X509_RFC5280_UTC_TIME_LEN ); + strncpy( ctx->not_after , not_after , X509_RFC5280_UTC_TIME_LEN ); + ctx->not_before[X509_RFC5280_UTC_TIME_LEN - 1] = 'Z'; + ctx->not_after[X509_RFC5280_UTC_TIME_LEN - 1] = 'Z'; + + return( 0 ); +} + +int x509write_crt_set_extension( x509write_cert *ctx, + const char *oid, size_t oid_len, + int critical, + const unsigned char *val, size_t val_len ) +{ + return x509_set_extension( &ctx->extensions, oid, oid_len, + critical, val, val_len ); +} + +int x509write_crt_set_basic_constraints( x509write_cert *ctx, + int is_ca, int max_pathlen ) +{ + int ret; + unsigned char buf[9]; + unsigned char *c = buf + sizeof(buf); + size_t len = 0; + + memset( buf, 0, sizeof(buf) ); + + if( is_ca && max_pathlen > 127 ) + return( POLARSSL_ERR_X509_BAD_INPUT_DATA ); + + if( is_ca ) + { + if( max_pathlen >= 0 ) + { + ASN1_CHK_ADD( len, asn1_write_int( &c, buf, max_pathlen ) ); + } + ASN1_CHK_ADD( len, asn1_write_bool( &c, buf, 1 ) ); + } + + ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | + ASN1_SEQUENCE ) ); + + return x509write_crt_set_extension( ctx, OID_BASIC_CONSTRAINTS, + OID_SIZE( OID_BASIC_CONSTRAINTS ), + 0, buf + sizeof(buf) - len, len ); +} + +#if defined(POLARSSL_SHA1_C) +int x509write_crt_set_subject_key_identifier( x509write_cert *ctx ) +{ + int ret; + unsigned char buf[POLARSSL_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */ + unsigned char *c = buf + sizeof(buf); + size_t len = 0; + + memset( buf, 0, sizeof(buf) ); + ASN1_CHK_ADD( len, pk_write_pubkey( &c, buf, ctx->subject_key ) ); + + sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 ); + c = buf + sizeof(buf) - 20; + len = 20; + + ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_OCTET_STRING ) ); + + return x509write_crt_set_extension( ctx, OID_SUBJECT_KEY_IDENTIFIER, + OID_SIZE( OID_SUBJECT_KEY_IDENTIFIER ), + 0, buf + sizeof(buf) - len, len ); +} + +int x509write_crt_set_authority_key_identifier( x509write_cert *ctx ) +{ + int ret; + unsigned char buf[POLARSSL_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */ + unsigned char *c = buf + sizeof(buf); + size_t len = 0; + + memset( buf, 0, sizeof(buf) ); + ASN1_CHK_ADD( len, pk_write_pubkey( &c, buf, ctx->issuer_key ) ); + + sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 ); + c = buf + sizeof(buf) - 20; + len = 20; + + ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONTEXT_SPECIFIC | 0 ) ); + + ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | + ASN1_SEQUENCE ) ); + + return x509write_crt_set_extension( ctx, OID_AUTHORITY_KEY_IDENTIFIER, + OID_SIZE( OID_AUTHORITY_KEY_IDENTIFIER ), + 0, buf + sizeof(buf) - len, len ); +} +#endif /* POLARSSL_SHA1_C */ + +int x509write_crt_set_key_usage( x509write_cert *ctx, unsigned char key_usage ) +{ + unsigned char buf[4]; + unsigned char *c; + int ret; + + c = buf + 4; + + if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 ) + return( ret ); + + ret = x509write_crt_set_extension( ctx, OID_KEY_USAGE, + OID_SIZE( OID_KEY_USAGE ), + 1, buf, 4 ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +int x509write_crt_set_ns_cert_type( x509write_cert *ctx, + unsigned char ns_cert_type ) +{ + unsigned char buf[4]; + unsigned char *c; + int ret; + + c = buf + 4; + + if( ( ret = asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 ) + return( ret ); + + ret = x509write_crt_set_extension( ctx, OID_NS_CERT_TYPE, + OID_SIZE( OID_NS_CERT_TYPE ), + 0, buf, 4 ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +static int x509_write_time( unsigned char **p, unsigned char *start, + const char *time, size_t size ) +{ + int ret; + size_t len = 0; + + /* + * write ASN1_UTC_TIME if year < 2050 (2 bytes shorter) + */ + if( time[0] == '2' && time[1] == '0' && time [2] < '5' ) + { + ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, + (const unsigned char *) time + 2, + size - 2 ) ); + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_UTC_TIME ) ); + } + else + { + ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, + (const unsigned char *) time, + size ) ); + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_GENERALIZED_TIME ) ); + } + + return( (int) len ); +} + +int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + const char *sig_oid; + size_t sig_oid_len = 0; + unsigned char *c, *c2; + unsigned char hash[64]; + unsigned char sig[POLARSSL_MPI_MAX_SIZE]; + unsigned char tmp_buf[2048]; + size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len; + size_t len = 0; + pk_type_t pk_alg; + + /* + * Prepare data to be signed in tmp_buf + */ + c = tmp_buf + sizeof( tmp_buf ); + + /* Signature algorithm needed in TBS, and later for actual signature */ + pk_alg = pk_get_type( ctx->issuer_key ); + if( pk_alg == POLARSSL_PK_ECKEY ) + pk_alg = POLARSSL_PK_ECDSA; + + if( ( ret = oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg, + &sig_oid, &sig_oid_len ) ) != 0 ) + { + return( ret ); + } + + /* + * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension + */ + ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) ); + ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | + ASN1_SEQUENCE ) ); + ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | + ASN1_CONSTRUCTED | 3 ) ); + + /* + * SubjectPublicKeyInfo + */ + ASN1_CHK_ADD( pub_len, pk_write_pubkey_der( ctx->subject_key, + tmp_buf, c - tmp_buf ) ); + c -= pub_len; + len += pub_len; + + /* + * Subject ::= Name + */ + ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) ); + + /* + * Validity ::= SEQUENCE { + * notBefore Time, + * notAfter Time } + */ + sub_len = 0; + + ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_after, + X509_RFC5280_UTC_TIME_LEN ) ); + + ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_before, + X509_RFC5280_UTC_TIME_LEN ) ); + + len += sub_len; + ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | + ASN1_SEQUENCE ) ); + + /* + * Issuer ::= Name + */ + ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->issuer ) ); + + /* + * Signature ::= AlgorithmIdentifier + */ + ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, tmp_buf, + sig_oid, strlen( sig_oid ), 0 ) ); + + /* + * Serial ::= INTEGER + */ + ASN1_CHK_ADD( len, asn1_write_mpi( &c, tmp_buf, &ctx->serial ) ); + + /* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + */ + sub_len = 0; + ASN1_CHK_ADD( sub_len, asn1_write_int( &c, tmp_buf, ctx->version ) ); + len += sub_len; + ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | + ASN1_CONSTRUCTED | 0 ) ); + + ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | + ASN1_SEQUENCE ) ); + + /* + * Make signature + */ + md( md_info_from_type( ctx->md_alg ), c, len, hash ); + + if( ( ret = pk_sign( ctx->issuer_key, ctx->md_alg, hash, 0, sig, &sig_len, + f_rng, p_rng ) ) != 0 ) + { + return( ret ); + } + + /* + * Write data to output buffer + */ + c2 = buf + size; + ASN1_CHK_ADD( sig_and_oid_len, x509_write_sig( &c2, buf, + sig_oid, sig_oid_len, sig, sig_len ) ); + + c2 -= len; + memcpy( c2, c, len ); + + len += sig_and_oid_len; + ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | + ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +#define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n" +#define PEM_END_CRT "-----END CERTIFICATE-----\n" + +#if defined(POLARSSL_PEM_WRITE_C) +int x509write_crt_pem( x509write_cert *crt, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + unsigned char output_buf[4096]; + size_t olen = 0; + + if( ( ret = x509write_crt_der( crt, output_buf, sizeof(output_buf), + f_rng, p_rng ) ) < 0 ) + { + return( ret ); + } + + if( ( ret = pem_write_buffer( PEM_BEGIN_CRT, PEM_END_CRT, + output_buf + sizeof(output_buf) - ret, + ret, buf, size, &olen ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} +#endif /* POLARSSL_PEM_WRITE_C */ + +#endif /* POLARSSL_X509_CRT_WRITE_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/x509write_csr.c b/component/common/network/ssl/polarssl-1.3.8/library/x509write_csr.c new file mode 100644 index 0000000..53ae9c6 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/x509write_csr.c @@ -0,0 +1,260 @@ +/* + * X.509 Certificate Signing Request writing + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * References: + * - CSRs: PKCS#10 v1.7 aka RFC 2986 + * - attributes: PKCS#9 v2.0 aka RFC 2985 + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_X509_CSR_WRITE_C) + +#include "polarssl/x509_csr.h" +#include "polarssl/oid.h" +#include "polarssl/asn1write.h" + +#if defined(POLARSSL_PEM_WRITE_C) +#include "polarssl/pem.h" +#endif + +#include +#include + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +void x509write_csr_init( x509write_csr *ctx ) +{ + memset( ctx, 0, sizeof(x509write_csr) ); +} + +void x509write_csr_free( x509write_csr *ctx ) +{ + asn1_free_named_data_list( &ctx->subject ); + asn1_free_named_data_list( &ctx->extensions ); + + polarssl_zeroize( ctx, sizeof(x509write_csr) ); +} + +void x509write_csr_set_md_alg( x509write_csr *ctx, md_type_t md_alg ) +{ + ctx->md_alg = md_alg; +} + +void x509write_csr_set_key( x509write_csr *ctx, pk_context *key ) +{ + ctx->key = key; +} + +int x509write_csr_set_subject_name( x509write_csr *ctx, + const char *subject_name ) +{ + return x509_string_to_names( &ctx->subject, subject_name ); +} + +int x509write_csr_set_extension( x509write_csr *ctx, + const char *oid, size_t oid_len, + const unsigned char *val, size_t val_len ) +{ + return x509_set_extension( &ctx->extensions, oid, oid_len, + 0, val, val_len ); +} + +int x509write_csr_set_key_usage( x509write_csr *ctx, unsigned char key_usage ) +{ + unsigned char buf[4]; + unsigned char *c; + int ret; + + c = buf + 4; + + if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 ) + return( ret ); + + ret = x509write_csr_set_extension( ctx, OID_KEY_USAGE, + OID_SIZE( OID_KEY_USAGE ), + buf, 4 ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +int x509write_csr_set_ns_cert_type( x509write_csr *ctx, + unsigned char ns_cert_type ) +{ + unsigned char buf[4]; + unsigned char *c; + int ret; + + c = buf + 4; + + if( ( ret = asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 ) + return( ret ); + + ret = x509write_csr_set_extension( ctx, OID_NS_CERT_TYPE, + OID_SIZE( OID_NS_CERT_TYPE ), + buf, 4 ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + const char *sig_oid; + size_t sig_oid_len = 0; + unsigned char *c, *c2; + unsigned char hash[64]; + unsigned char sig[POLARSSL_MPI_MAX_SIZE]; + unsigned char tmp_buf[2048]; + size_t pub_len = 0, sig_and_oid_len = 0, sig_len; + size_t len = 0; + pk_type_t pk_alg; + + /* + * Prepare data to be signed in tmp_buf + */ + c = tmp_buf + sizeof( tmp_buf ); + + ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) ); + + if( len ) + { + ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | + ASN1_SEQUENCE ) ); + + ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | + ASN1_SET ) ); + + ASN1_CHK_ADD( len, asn1_write_oid( &c, tmp_buf, OID_PKCS9_CSR_EXT_REQ, + OID_SIZE( OID_PKCS9_CSR_EXT_REQ ) ) ); + + ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | + ASN1_SEQUENCE ) ); + } + + ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | + ASN1_CONTEXT_SPECIFIC ) ); + + ASN1_CHK_ADD( pub_len, pk_write_pubkey_der( ctx->key, + tmp_buf, c - tmp_buf ) ); + c -= pub_len; + len += pub_len; + + /* + * Subject ::= Name + */ + ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) ); + + /* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + */ + ASN1_CHK_ADD( len, asn1_write_int( &c, tmp_buf, 0 ) ); + + ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | + ASN1_SEQUENCE ) ); + + /* + * Prepare signature + */ + md( md_info_from_type( ctx->md_alg ), c, len, hash ); + + pk_alg = pk_get_type( ctx->key ); + if( pk_alg == POLARSSL_PK_ECKEY ) + pk_alg = POLARSSL_PK_ECDSA; + + if( ( ret = pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len, + f_rng, p_rng ) ) != 0 || + ( ret = oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg, + &sig_oid, &sig_oid_len ) ) != 0 ) + { + return( ret ); + } + + /* + * Write data to output buffer + */ + c2 = buf + size; + ASN1_CHK_ADD( sig_and_oid_len, x509_write_sig( &c2, buf, + sig_oid, sig_oid_len, sig, sig_len ) ); + + c2 -= len; + memcpy( c2, c, len ); + + len += sig_and_oid_len; + ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | + ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +#define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n" +#define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n" + +#if defined(POLARSSL_PEM_WRITE_C) +int x509write_csr_pem( x509write_csr *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + unsigned char output_buf[4096]; + size_t olen = 0; + + if( ( ret = x509write_csr_der( ctx, output_buf, sizeof(output_buf), + f_rng, p_rng ) ) < 0 ) + { + return( ret ); + } + + if( ( ret = pem_write_buffer( PEM_BEGIN_CSR, PEM_END_CSR, + output_buf + sizeof(output_buf) - ret, + ret, buf, size, &olen ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} +#endif /* POLARSSL_PEM_WRITE_C */ + +#endif /* POLARSSL_X509_CSR_WRITE_C */ diff --git a/component/common/network/ssl/polarssl-1.3.8/library/xtea.c b/component/common/network/ssl/polarssl-1.3.8/library/xtea.c new file mode 100644 index 0000000..75215c5 --- /dev/null +++ b/component/common/network/ssl/polarssl-1.3.8/library/xtea.c @@ -0,0 +1,283 @@ +/* + * An 32-bit implementation of the XTEA algorithm + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl/config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_XTEA_C) + +#include "polarssl/xtea.h" + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#define polarssl_printf printf +#endif + +#if !defined(POLARSSL_XTEA_ALT) + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +void xtea_init( xtea_context *ctx ) +{ + memset( ctx, 0, sizeof( xtea_context ) ); +} + +void xtea_free( xtea_context *ctx ) +{ + if( ctx == NULL ) + return; + + polarssl_zeroize( ctx, sizeof( xtea_context ) ); +} + +/* + * XTEA key schedule + */ +void xtea_setup( xtea_context *ctx, const unsigned char key[16] ) +{ + int i; + + memset( ctx, 0, sizeof(xtea_context) ); + + for( i = 0; i < 4; i++ ) + { + GET_UINT32_BE( ctx->k[i], key, i << 2 ); + } +} + +/* + * XTEA encrypt function + */ +int xtea_crypt_ecb( xtea_context *ctx, int mode, + const unsigned char input[8], unsigned char output[8]) +{ + uint32_t *k, v0, v1, i; + + k = ctx->k; + + GET_UINT32_BE( v0, input, 0 ); + GET_UINT32_BE( v1, input, 4 ); + + if( mode == XTEA_ENCRYPT ) + { + uint32_t sum = 0, delta = 0x9E3779B9; + + for( i = 0; i < 32; i++ ) + { + v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]); + sum += delta; + v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]); + } + } + else /* XTEA_DECRYPT */ + { + uint32_t delta = 0x9E3779B9, sum = delta * 32; + + for( i = 0; i < 32; i++ ) + { + v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]); + sum -= delta; + v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]); + } + } + + PUT_UINT32_BE( v0, output, 0 ); + PUT_UINT32_BE( v1, output, 4 ); + + return( 0 ); +} + +#if defined(POLARSSL_CIPHER_MODE_CBC) +/* + * XTEA-CBC buffer encryption/decryption + */ +int xtea_crypt_cbc( xtea_context *ctx, int mode, size_t length, + unsigned char iv[8], const unsigned char *input, + unsigned char *output) +{ + int i; + unsigned char temp[8]; + + if( length % 8 ) + return( POLARSSL_ERR_XTEA_INVALID_INPUT_LENGTH ); + + if( mode == XTEA_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, 8 ); + xtea_crypt_ecb( ctx, mode, input, output ); + + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + else + { + while( length > 0 ) + { + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + xtea_crypt_ecb( ctx, mode, output, output ); + memcpy( iv, output, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + + return( 0 ); +} +#endif /* POLARSSL_CIPHER_MODE_CBC */ +#endif /* !POLARSSL_XTEA_ALT */ + +#if defined(POLARSSL_SELF_TEST) + +#include +#include + +/* + * XTEA tests vectors (non-official) + */ + +static const unsigned char xtea_test_key[6][16] = +{ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 } +}; + +static const unsigned char xtea_test_pt[6][8] = +{ + { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 }, + { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, + { 0x5a, 0x5b, 0x6e, 0x27, 0x89, 0x48, 0xd7, 0x7f }, + { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 }, + { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, + { 0x70, 0xe1, 0x22, 0x5d, 0x6e, 0x4e, 0x76, 0x55 } +}; + +static const unsigned char xtea_test_ct[6][8] = +{ + { 0x49, 0x7d, 0xf3, 0xd0, 0x72, 0x61, 0x2c, 0xb5 }, + { 0xe7, 0x8f, 0x2d, 0x13, 0x74, 0x43, 0x41, 0xd8 }, + { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, + { 0xa0, 0x39, 0x05, 0x89, 0xf8, 0xb8, 0xef, 0xa5 }, + { 0xed, 0x23, 0x37, 0x5a, 0x82, 0x1a, 0x8c, 0x2d }, + { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 } +}; + +/* + * Checkup routine + */ +int xtea_self_test( int verbose ) +{ + int i, ret = 0; + unsigned char buf[8]; + xtea_context ctx; + + xtea_init( &ctx ); + for( i = 0; i < 6; i++ ) + { + if( verbose != 0 ) + polarssl_printf( " XTEA test #%d: ", i + 1 ); + + memcpy( buf, xtea_test_pt[i], 8 ); + + xtea_setup( &ctx, xtea_test_key[i] ); + xtea_crypt_ecb( &ctx, XTEA_ENCRYPT, buf, buf ); + + if( memcmp( buf, xtea_test_ct[i], 8 ) != 0 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); + +exit: + xtea_free( &ctx ); + + return( ret ); +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_XTEA_C */ diff --git a/component/common/test/wlan/wlan_test_inc.h b/component/common/test/wlan/wlan_test_inc.h new file mode 100644 index 0000000..de1e156 --- /dev/null +++ b/component/common/test/wlan/wlan_test_inc.h @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------// +#ifndef __MAIN_TEST_H +#define __MAIN_TEST_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Exported test functions ------------------------------------------------------- */ +void do_ping_test(char *ip, int size, int count, int interval); +void do_ping_call(char *ip, int loop, int count); +void do_deinit_test(int mode, int ap_started); +void interactive_question(char *question, char *choice, char *buf, int buf_size); +void start_interactive_mode(void); +void post_init(unsigned int config_start_ap); + +#ifdef __cplusplus + } +#endif + +#endif // __MAIN_TEST_H + +//----------------------------------------------------------------------------// diff --git a/component/common/utilities/cJSON.c b/component/common/utilities/cJSON.c new file mode 100644 index 0000000..1e2f8e1 --- /dev/null +++ b/component/common/utilities/cJSON.c @@ -0,0 +1,596 @@ +/* + Copyright (c) 2009 Dave Gamble + + 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. +*/ + +/* cJSON */ +/* JSON parser in C. */ + +#include +#include +#include +#include +#include +#include +#include +#include "cJSON.h" + +static const char *ep; + +const char *cJSON_GetErrorPtr(void) {return ep;} + +static int cJSON_strcasecmp(const char *s1,const char *s2) +{ + if (!s1) return (s1==s2)?0:1;if (!s2) return 1; + for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0) return 0; + return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2); +} + +static void *(*cJSON_malloc)(size_t sz) = malloc; +static void (*cJSON_free)(void *ptr) = free; + +static char* cJSON_strdup(const char* str) +{ + size_t len; + char* copy; + + len = strlen(str) + 1; + if (!(copy = (char*)cJSON_malloc(len))) return 0; + memcpy(copy,str,len); + return copy; +} + +void cJSON_InitHooks(cJSON_Hooks* hooks) +{ + if (!hooks) { /* Reset hooks */ + cJSON_malloc = malloc; + cJSON_free = free; + return; + } + + cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc; + cJSON_free = (hooks->free_fn)?hooks->free_fn:free; +} + +/* Internal constructor. */ +static cJSON *cJSON_New_Item(void) +{ + cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON)); + if (node) memset(node,0,sizeof(cJSON)); + return node; +} + +/* Delete a cJSON structure. */ +void cJSON_Delete(cJSON *c) +{ + cJSON *next; + while (c) + { + next=c->next; + if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child); + if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring); + if (c->string) cJSON_free(c->string); + cJSON_free(c); + c=next; + } +} + +/* Parse the input text to generate a number, and populate the result into item. */ +static const char *parse_number(cJSON *item,const char *num) +{ + double n=0,sign=1,scale=0;int subscale=0,signsubscale=1; + + if (*num=='-') sign=-1,num++; /* Has sign? */ + if (*num=='0') num++; /* is zero */ + if (*num>='1' && *num<='9') do n=(n*10.0)+(*num++ -'0'); while (*num>='0' && *num<='9'); /* Number? */ + if (*num=='.' && num[1]>='0' && num[1]<='9') {num++; do n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');} /* Fractional part? */ + if (*num=='e' || *num=='E') /* Exponent? */ + { num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; /* With sign? */ + while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0'); /* Number? */ + } + + n=sign*n*pow(10.0,(scale+subscale*signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */ + + item->valuedouble=n; + item->valueint=(int)n; + item->type=cJSON_Number; + return num; +} + +/* Render the number nicely from the given item into a string. */ +static char *print_number(cJSON *item) +{ + char *str; + double d=item->valuedouble; + if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN) + { + str=(char*)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */ + if (str) sprintf(str,"%d",item->valueint); + } + else + { + str=(char*)cJSON_malloc(64); /* This is a nice tradeoff. */ + if (str) + { + if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)sprintf(str,"%.0f",d); + else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d); + else sprintf(str,"%f",d); + } + } + return str; +} + +static unsigned parse_hex4(const char *str) +{ + unsigned h=0; + if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; + h=h<<4;str++; + if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; + h=h<<4;str++; + if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; + h=h<<4;str++; + if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; + return h; +} + +/* Parse the input text into an unescaped cstring, and populate item. */ +static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; +static const char *parse_string(cJSON *item,const char *str) +{ + const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2; + if (*str!='\"') {ep=str;return 0;} /* not a string! */ + + while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */ + + out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */ + if (!out) return 0; + + ptr=str+1;ptr2=out; + while (*ptr!='\"' && *ptr) + { + if (*ptr!='\\') *ptr2++=*ptr++; + else + { + ptr++; + switch (*ptr) + { + case 'b': *ptr2++='\b'; break; + case 'f': *ptr2++='\f'; break; + case 'n': *ptr2++='\n'; break; + case 'r': *ptr2++='\r'; break; + case 't': *ptr2++='\t'; break; + case 'u': /* transcode utf16 to utf8. */ + uc=parse_hex4(ptr+1);ptr+=4; /* get the unicode char. */ + + if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) break; /* check for invalid. */ + + if (uc>=0xD800 && uc<=0xDBFF) /* UTF16 surrogate pairs. */ + { + if (ptr[1]!='\\' || ptr[2]!='u') break; /* missing second-half of surrogate. */ + uc2=parse_hex4(ptr+3);ptr+=6; + if (uc2<0xDC00 || uc2>0xDFFF) break; /* invalid second-half of surrogate. */ + uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF)); + } + + len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len; + + switch (len) { + case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; + case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; + case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; + case 1: *--ptr2 =(uc | firstByteMark[len]); + } + ptr2+=len; + break; + default: *ptr2++=*ptr; break; + } + ptr++; + } + } + *ptr2=0; + if (*ptr=='\"') ptr++; + item->valuestring=out; + item->type=cJSON_String; + return ptr; +} + +/* Render the cstring provided to an escaped version that can be printed. */ +static char *print_string_ptr(const char *str) +{ + const char *ptr;char *ptr2,*out;int len=0;unsigned char token; + + if (!str) return cJSON_strdup(""); + ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;} + + out=(char*)cJSON_malloc(len+3); + if (!out) return 0; + + ptr2=out;ptr=str; + *ptr2++='\"'; + while (*ptr) + { + if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++; + else + { + *ptr2++='\\'; + switch (token=*ptr++) + { + case '\\': *ptr2++='\\'; break; + case '\"': *ptr2++='\"'; break; + case '\b': *ptr2++='b'; break; + case '\f': *ptr2++='f'; break; + case '\n': *ptr2++='n'; break; + case '\r': *ptr2++='r'; break; + case '\t': *ptr2++='t'; break; + default: sprintf(ptr2,"u%04x",token);ptr2+=5; break; /* escape and print */ + } + } + } + *ptr2++='\"';*ptr2++=0; + return out; +} +/* Invote print_string_ptr (which is useful) on an item. */ +static char *print_string(cJSON *item) {return print_string_ptr(item->valuestring);} + +/* Predeclare these prototypes. */ +static const char *parse_value(cJSON *item,const char *value); +static char *print_value(cJSON *item,int depth,int fmt); +static const char *parse_array(cJSON *item,const char *value); +static char *print_array(cJSON *item,int depth,int fmt); +static const char *parse_object(cJSON *item,const char *value); +static char *print_object(cJSON *item,int depth,int fmt); + +/* Utility to jump whitespace and cr/lf */ +static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;} + +/* Parse an object - create a new root, and populate. */ +cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated) +{ + const char *end=0; + cJSON *c=cJSON_New_Item(); + ep=0; + if (!c) return 0; /* memory fail */ + + end=parse_value(c,skip(value)); + if (!end) {cJSON_Delete(c);return 0;} /* parse failure. ep is set. */ + + /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ + if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);ep=end;return 0;}} + if (return_parse_end) *return_parse_end=end; + return c; +} +/* Default options for cJSON_Parse */ +cJSON *cJSON_Parse(const char *value) {return cJSON_ParseWithOpts(value,0,0);} + +/* Render a cJSON item/entity/structure to text. */ +char *cJSON_Print(cJSON *item) {return print_value(item,0,1);} +char *cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0);} + +/* Parser core - when encountering text, process appropriately. */ +static const char *parse_value(cJSON *item,const char *value) +{ + if (!value) return 0; /* Fail on null. */ + if (!strncmp(value,"null",4)) { item->type=cJSON_NULL; return value+4; } + if (!strncmp(value,"false",5)) { item->type=cJSON_False; return value+5; } + if (!strncmp(value,"true",4)) { item->type=cJSON_True; item->valueint=1; return value+4; } + if (*value=='\"') { return parse_string(item,value); } + if (*value=='-' || (*value>='0' && *value<='9')) { return parse_number(item,value); } + if (*value=='[') { return parse_array(item,value); } + if (*value=='{') { return parse_object(item,value); } + + ep=value;return 0; /* failure. */ +} + +/* Render a value to text. */ +static char *print_value(cJSON *item,int depth,int fmt) +{ + char *out=0; + if (!item) return 0; + switch ((item->type)&255) + { + case cJSON_NULL: out=cJSON_strdup("null"); break; + case cJSON_False: out=cJSON_strdup("false");break; + case cJSON_True: out=cJSON_strdup("true"); break; + case cJSON_Number: out=print_number(item);break; + case cJSON_String: out=print_string(item);break; + case cJSON_Array: out=print_array(item,depth,fmt);break; + case cJSON_Object: out=print_object(item,depth,fmt);break; + } + return out; +} + +/* Build an array from input text. */ +static const char *parse_array(cJSON *item,const char *value) +{ + cJSON *child; + if (*value!='[') {ep=value;return 0;} /* not an array! */ + + item->type=cJSON_Array; + value=skip(value+1); + if (*value==']') return value+1; /* empty array. */ + + item->child=child=cJSON_New_Item(); + if (!item->child) return 0; /* memory fail */ + value=skip(parse_value(child,skip(value))); /* skip any spacing, get the value. */ + if (!value) return 0; + + while (*value==',') + { + cJSON *new_item; + if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */ + child->next=new_item;new_item->prev=child;child=new_item; + value=skip(parse_value(child,skip(value+1))); + if (!value) return 0; /* memory fail */ + } + + if (*value==']') return value+1; /* end of array */ + ep=value;return 0; /* malformed. */ +} + +/* Render an array to text */ +static char *print_array(cJSON *item,int depth,int fmt) +{ + char **entries; + char *out=0,*ptr,*ret;int len=5; + cJSON *child=item->child; + int numentries=0,i=0,fail=0; + + /* How many entries in the array? */ + while (child) numentries++,child=child->next; + /* Explicitly handle numentries==0 */ + if (!numentries) + { + out=(char*)cJSON_malloc(3); + if (out) strcpy(out,"[]"); + return out; + } + /* Allocate an array to hold the values for each */ + entries=(char**)cJSON_malloc(numentries*sizeof(char*)); + if (!entries) return 0; + memset(entries,0,numentries*sizeof(char*)); + /* Retrieve all the results: */ + child=item->child; + while (child && !fail) + { + ret=print_value(child,depth+1,fmt); + entries[i++]=ret; + if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1; + child=child->next; + } + + /* If we didn't fail, try to malloc the output string */ + if (!fail) out=(char*)cJSON_malloc(len); + /* If that fails, we fail. */ + if (!out) fail=1; + + /* Handle failure. */ + if (fail) + { + for (i=0;itype=cJSON_Object; + value=skip(value+1); + if (*value=='}') return value+1; /* empty array. */ + + item->child=child=cJSON_New_Item(); + if (!item->child) return 0; + value=skip(parse_string(child,skip(value))); + if (!value) return 0; + child->string=child->valuestring;child->valuestring=0; + if (*value!=':') {ep=value;return 0;} /* fail! */ + value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ + if (!value) return 0; + + while (*value==',') + { + cJSON *new_item; + if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */ + child->next=new_item;new_item->prev=child;child=new_item; + value=skip(parse_string(child,skip(value+1))); + if (!value) return 0; + child->string=child->valuestring;child->valuestring=0; + if (*value!=':') {ep=value;return 0;} /* fail! */ + value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ + if (!value) return 0; + } + + if (*value=='}') return value+1; /* end of array */ + ep=value;return 0; /* malformed. */ +} + +/* Render an object to text. */ +static char *print_object(cJSON *item,int depth,int fmt) +{ + char **entries=0,**names=0; + char *out=0,*ptr,*ret,*str;int len=7,i=0,j; + cJSON *child=item->child; + int numentries=0,fail=0; + /* Count the number of entries. */ + while (child) numentries++,child=child->next; + /* Explicitly handle empty object case */ + if (!numentries) + { + out=(char*)cJSON_malloc(fmt?depth+4:3); + if (!out) return 0; + ptr=out;*ptr++='{'; + if (fmt) {*ptr++='\n';for (i=0;ichild;depth++;if (fmt) len+=depth; + while (child) + { + names[i]=str=print_string_ptr(child->string); + entries[i++]=ret=print_value(child,depth,fmt); + if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1; + child=child->next; + } + + /* Try to allocate the output string */ + if (!fail) out=(char*)cJSON_malloc(len); + if (!out) fail=1; + + /* Handle failure */ + if (fail) + { + for (i=0;ichild;int i=0;while(c)i++,c=c->next;return i;} +cJSON *cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c;} +cJSON *cJSON_GetObjectItem(cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;} + +/* Utility for array list handling. */ +static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;} +/* Utility for handling references. */ +static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return 0;memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;} + +/* Add item to array/object. */ +void cJSON_AddItemToArray(cJSON *array, cJSON *item) {cJSON *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}} +void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);} +void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {cJSON_AddItemToArray(array,create_reference(item));} +void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));} + +cJSON *cJSON_DetachItemFromArray(cJSON *array,int which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0; + if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;} +void cJSON_DeleteItemFromArray(cJSON *array,int which) {cJSON_Delete(cJSON_DetachItemFromArray(array,which));} +cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;} +void cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));} + +/* Replace array/object items with new ones. */ +void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return; + newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem; + if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);} +void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){if(newitem->string) cJSON_free(newitem->string);newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}} + +/* Create basic types: */ +cJSON *cJSON_CreateNull(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;} +cJSON *cJSON_CreateTrue(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;} +cJSON *cJSON_CreateFalse(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;} +cJSON *cJSON_CreateBool(int b) {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;} +cJSON *cJSON_CreateNumber(double num) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;}return item;} +cJSON *cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;} +cJSON *cJSON_CreateArray(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;} +cJSON *cJSON_CreateObject(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;} + +/* Create Arrays: */ +cJSON *cJSON_CreateIntArray(const int *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} +cJSON *cJSON_CreateFloatArray(const float *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} +cJSON *cJSON_CreateDoubleArray(const double *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} +cJSON *cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} + +/* Duplication */ +cJSON *cJSON_Duplicate(cJSON *item,int recurse) +{ + cJSON *newitem,*cptr,*nptr=0,*newchild; + /* Bail on bad ptr */ + if (!item) return 0; + /* Create new item */ + newitem=cJSON_New_Item(); + if (!newitem) return 0; + /* Copy over all vars */ + newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble; + if (item->valuestring) {newitem->valuestring=cJSON_strdup(item->valuestring); if (!newitem->valuestring) {cJSON_Delete(newitem);return 0;}} + if (item->string) {newitem->string=cJSON_strdup(item->string); if (!newitem->string) {cJSON_Delete(newitem);return 0;}} + /* If non-recursive, then we're done! */ + if (!recurse) return newitem; + /* Walk the ->next chain for the child. */ + cptr=item->child; + while (cptr) + { + newchild=cJSON_Duplicate(cptr,1); /* Duplicate (with recurse) each item in the ->next chain */ + if (!newchild) {cJSON_Delete(newitem);return 0;} + if (nptr) {nptr->next=newchild,newchild->prev=nptr;nptr=newchild;} /* If newitem->child already set, then crosswire ->prev and ->next and move on */ + else {newitem->child=newchild;nptr=newchild;} /* Set newitem->child and move to it */ + cptr=cptr->next; + } + return newitem; +} + +void cJSON_Minify(char *json) +{ + char *into=json; + while (*json) + { + if (*json==' ') json++; + else if (*json=='\t') json++; // Whitespace characters. + else if (*json=='\r') json++; + else if (*json=='\n') json++; + else if (*json=='/' && json[1]=='/') while (*json && *json!='\n') json++; // double-slash comments, to end of line. + else if (*json=='/' && json[1]=='*') {while (*json && !(*json=='*' && json[1]=='/')) json++;json+=2;} // multiline comments. + else if (*json=='\"'){*into++=*json++;while (*json && *json!='\"'){if (*json=='\\') *into++=*json++;*into++=*json++;}*into++=*json++;} // string literals, which are \" sensitive. + else *into++=*json++; // All other characters. + } + *into=0; // and null-terminate. +} diff --git a/component/common/utilities/cJSON.h b/component/common/utilities/cJSON.h new file mode 100644 index 0000000..0d886d6 --- /dev/null +++ b/component/common/utilities/cJSON.h @@ -0,0 +1,145 @@ +/* + Copyright (c) 2009 Dave Gamble + + 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 cJSON__h +#define cJSON__h + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include + +/* cJSON Types: */ +#define cJSON_False 0 +#define cJSON_True 1 +#define cJSON_NULL 2 +#define cJSON_Number 3 +#define cJSON_String 4 +#define cJSON_Array 5 +#define cJSON_Object 6 + +#define cJSON_IsReference 256 + +/* The cJSON structure: */ +typedef struct cJSON { + struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ + struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ + + int type; /* The type of the item, as above. */ + + char *valuestring; /* The item's string, if type==cJSON_String */ + int valueint; /* The item's number, if type==cJSON_Number */ + double valuedouble; /* The item's number, if type==cJSON_Number */ + + char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ +} cJSON; + +typedef struct cJSON_Hooks { + void *(*malloc_fn)(size_t sz); + void (*free_fn)(void *ptr); +} cJSON_Hooks; + +/* Supply malloc, realloc and free functions to cJSON */ +extern void cJSON_InitHooks(cJSON_Hooks* hooks); + + +/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */ +extern cJSON *cJSON_Parse(const char *value); +/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */ +extern char *cJSON_Print(cJSON *item); +/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */ +extern char *cJSON_PrintUnformatted(cJSON *item); +/* Delete a cJSON entity and all subentities. */ +extern void cJSON_Delete(cJSON *c); + +/* Returns the number of items in an array (or object). */ +extern int cJSON_GetArraySize(cJSON *array); +/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */ +extern cJSON *cJSON_GetArrayItem(cJSON *array,int item); +/* Get item "string" from object. Case insensitive. */ +extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string); + +/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ +extern const char *cJSON_GetErrorPtr(void); + +/* These calls create a cJSON item of the appropriate type. */ +extern cJSON *cJSON_CreateNull(void); +extern cJSON *cJSON_CreateTrue(void); +extern cJSON *cJSON_CreateFalse(void); +extern cJSON *cJSON_CreateBool(int b); +extern cJSON *cJSON_CreateNumber(double num); +extern cJSON *cJSON_CreateString(const char *string); +extern cJSON *cJSON_CreateArray(void); +extern cJSON *cJSON_CreateObject(void); + +/* These utilities create an Array of count items. */ +extern cJSON *cJSON_CreateIntArray(const int *numbers,int count); +extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count); +extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count); +extern cJSON *cJSON_CreateStringArray(const char **strings,int count); + +/* Append item to the specified array/object. */ +extern void cJSON_AddItemToArray(cJSON *array, cJSON *item); +extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item); +/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */ +extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); +extern void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item); + +/* Remove/Detatch items from Arrays/Objects. */ +extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which); +extern void cJSON_DeleteItemFromArray(cJSON *array,int which); +extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string); +extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string); + +/* Update array items. */ +extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem); +extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); + +/* Duplicate a cJSON item */ +extern cJSON *cJSON_Duplicate(cJSON *item,int recurse); +/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will +need to be released. With recurse!=0, it will duplicate any children connected to the item. +The item->next and ->prev pointers are always zero on return from Duplicate. */ + +/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ +extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated); + +extern void cJSON_Minify(char *json); + +/* Macros for creating things quickly. */ +#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull()) +#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue()) +#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse()) +#define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b)) +#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n)) +#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s)) + +/* When assigning an integer value, it needs to be propagated to valuedouble too. */ +#define cJSON_SetIntValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val)) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/component/common/utilities/ssl_client.c b/component/common/utilities/ssl_client.c new file mode 100644 index 0000000..be24a2c --- /dev/null +++ b/component/common/utilities/ssl_client.c @@ -0,0 +1,283 @@ +#include "FreeRTOS.h" +#include "task.h" +#include "polarssl/config.h" + +#include +#include + +#include "polarssl/net.h" +#include "polarssl/ssl.h" +#include "polarssl/error.h" +#include "polarssl/memory.h" + +#define SERVER_PORT 443 +#define SERVER_HOST "192.168.13.15" +#define GET_REQUEST "GET / HTTP/1.0\r\n\r\n" +#define DEBUG_LEVEL 0 +#define SSL_USE_SRP 0 +#define STACKSIZE 1150 + +static int is_task = 0; +char server_host[16]; +#if SSL_USE_SRP +char srp_username[16]; +char srp_password[16]; +#endif + +static void my_debug(void *ctx, int level, const char *str) +{ + if(level <= DEBUG_LEVEL) { + printf("\n\r%s", str); + } +} + +static unsigned int arc4random(void) +{ + unsigned int res = xTaskGetTickCount(); + static unsigned int seed = 0xDEADB00B; + + seed = ((seed & 0x007F00FF) << 7) ^ + ((seed & 0x0F80FF00) >> 8) ^ // be sure to stir those low bits + (res << 13) ^ (res >> 9); // using the clock too! + + return seed; +} + +static void get_random_bytes(void *buf, size_t len) +{ + unsigned int ranbuf; + unsigned int *lp; + int i, count; + count = len / sizeof(unsigned int); + lp = (unsigned int *) buf; + + for(i = 0; i < count; i ++) { + lp[i] = arc4random(); + len -= sizeof(unsigned int); + } + + if(len > 0) { + ranbuf = arc4random(); + memcpy(&lp[i], &ranbuf, len); + } +} + +static int my_random(void *p_rng, unsigned char *output, size_t output_len) +{ + get_random_bytes(output, output_len); + return 0; +} + +#ifdef POLARSSL_MEMORY_C +static size_t min_heap_size = 0; + +void* my_malloc(size_t size) +{ + void *ptr = pvPortMalloc(size); + size_t current_heap_size = xPortGetFreeHeapSize(); + + if((current_heap_size < min_heap_size) || (min_heap_size == 0)) + min_heap_size = current_heap_size; + + return ptr; +} + +#define my_free vPortFree + +#endif + +static void ssl_client(void *param) +{ + int ret, len, server_fd = -1; + unsigned char buf[512]; + ssl_context ssl; + +#ifdef POLARSSL_MEMORY_C + memory_set_own(my_malloc, my_free); +#endif + /* + * 0. Initialize the session data + */ + memset(&ssl, 0, sizeof(ssl_context)); + + /* + * 1. Start the connection + */ + printf("\n\r . Connecting to tcp/%s/%d...", server_host, SERVER_PORT); + + if((ret = net_connect(&server_fd, server_host, SERVER_PORT)) != 0) { + printf(" failed\n\r ! net_connect returned %d\n", ret); + goto exit; + } + + printf(" ok\n"); + + /* + * 2. Setup stuff + */ + printf("\n\r . Setting up the SSL/TLS structure..." ); + + if((ret = ssl_init(&ssl)) != 0) { + printf(" failed\n\r ! ssl_init returned %d\n", ret); + goto exit; + } + + printf(" ok\n"); + + ssl_set_endpoint(&ssl, SSL_IS_CLIENT); + ssl_set_authmode(&ssl, SSL_VERIFY_NONE); + ssl_set_rng(&ssl, my_random, NULL); +#ifdef POLARSSL_DEBUG_C + debug_set_threshold(DEBUG_LEVEL); +#endif + ssl_set_dbg(&ssl, my_debug, NULL); + ssl_set_bio(&ssl, net_recv, &server_fd, net_send, &server_fd); +#if SSL_USE_SRP + if(strlen(srp_username)) + ssl_set_srp(&ssl, srp_username, strlen(srp_username), srp_password, strlen(srp_password)); +#endif + /* + * 3. Handshake + */ + printf("\n\r . Performing the SSL/TLS handshake..."); + + while((ret = ssl_handshake(&ssl)) != 0) { + if(ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE) { + printf(" failed\n\r ! ssl_handshake returned -0x%x\n", -ret); + goto exit; + } + } + + printf(" ok\n"); + printf("\n\r . Use ciphersuite %s\n", ssl_get_ciphersuite(&ssl)); + + /* + * 4. Write the GET request + */ + printf("\n\r > Write to server:"); + + len = sprintf((char *) buf, GET_REQUEST); + + while((ret = ssl_write(&ssl, buf, len)) <= 0) { + if(ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE) { + printf(" failed\n\r ! ssl_write returned %d\n", ret); + goto exit; + } + } + + len = ret; + printf(" %d bytes written\n\r\n\r%s\n", len, (char *) buf); + + /* + * 5. Read the HTTP response + */ + printf("\n\r < Read from server:"); + + do { + len = sizeof(buf) - 1; + memset(buf, 0, sizeof(buf)); + ret = ssl_read(&ssl, buf, len); + + if(ret == POLARSSL_ERR_NET_WANT_READ || ret == POLARSSL_ERR_NET_WANT_WRITE) + continue; + + if(ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY) + break; + + if(ret < 0) { + printf(" failed\n\r ! ssl_read returned %d\n", ret); + break; + } + + if(ret == 0) { + printf("\n\rEOF\n"); + break; + } + + len = ret; + printf(" %d bytes read\n\r\n\r%s\n", len, (char *) buf); + } + while(1); + + ssl_close_notify(&ssl); + +exit: + +#ifdef POLARSSL_ERROR_C + if(ret != 0) { + char error_buf[100]; + polarssl_strerror(ret, error_buf, 100); + printf("\n\rLast error was: %d - %s\n", ret, error_buf); + } +#endif + + net_close(server_fd); + ssl_free(&ssl); + + if(is_task) { +#if defined(INCLUDE_uxTaskGetStackHighWaterMark) && (INCLUDE_uxTaskGetStackHighWaterMark == 1) + printf("\n\rMin available stack size of %s = %d * %d bytes\n\r", __FUNCTION__, uxTaskGetStackHighWaterMark(NULL), sizeof(portBASE_TYPE)); +#endif +#ifdef POLARSSL_MEMORY_C + if(min_heap_size > 0) + printf("\n\rMin available heap size = %d bytes during %s\n\r", min_heap_size, __FUNCTION__); +#endif + vTaskDelete(NULL); + } + + if(param != NULL) + *((int *) param) = ret; +} + +void start_ssl_client(void) +{ + is_task = 1; + //strcpy(server_host, SERVER_HOST); + + if(xTaskCreate(ssl_client, "ssl_client", STACKSIZE, NULL, tskIDLE_PRIORITY + 1, NULL) != pdPASS) + printf("\n\r%s xTaskCreate failed", __FUNCTION__); +} + +void do_ssl_connect(void) +{ + int ret; + static int success = 0; + static int fail = 0; + + is_task = 0; + strcpy(server_host, SERVER_HOST); + ssl_client(&ret); + + if(ret != 0) + printf("\n\r%s fail (success %d times, fail %d times)\n\r", __FUNCTION__, success, ++ fail); + else + printf("\n\r%s success (success %d times, fail %d times)\n\r", __FUNCTION__, ++ success, fail); +} + +void cmd_ssl_client(int argc, char **argv) +{ + if(argc == 2) { + strcpy(server_host, argv[1]); +#if SSL_USE_SRP + strcpy(srp_username, ""); + strcpy(srp_password, ""); +#endif + } +#if SSL_USE_SRP + else if(argc == 4) { + strcpy(server_host, argv[1]); + strcpy(srp_username, argv[2]); + strcpy(srp_password, argv[3]); + } +#endif + else { +#if SSL_USE_SRP + printf("\n\rUsage: %s SSL_SERVER_HOST [SRP_USER_NAME SRP_PASSWORD]", argv[0]); +#else + printf("\n\rUsage: %s SSL_SERVER_HOST", argv[0]); +#endif + return; + } + + start_ssl_client(); +} diff --git a/component/common/utilities/tcpecho.c b/component/common/utilities/tcpecho.c new file mode 100644 index 0000000..69d2124 --- /dev/null +++ b/component/common/utilities/tcpecho.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + + +#include "lwip/opt.h" + +#if LWIP_NETCONN + +#include "lwip/sys.h" +#include "lwip/api.h" + +#define TCPECHO_THREAD_PRIO ( tskIDLE_PRIORITY + 3 ) + + + +/*-----------------------------------------------------------------------------------*/ +static void tcpecho_thread(void *arg) +{ + struct netconn *conn, *newconn; + err_t err; + + LWIP_UNUSED_ARG(arg); + + /* Create a new connection identifier. */ + conn = netconn_new(NETCONN_TCP); + + if (conn!=NULL) + { + /* Bind connection to well known port number 7. */ + err = netconn_bind(conn, NULL, 7); + + if (err == ERR_OK) + { + /* Tell connection to go into listening mode. */ + netconn_listen(conn); + + while (1) + { + /* Grab new connection. */ + newconn = netconn_accept(conn); + + /* Process the new connection. */ + if (newconn) + { + struct netbuf *buf; + void *data; + u16_t len; + + while ((buf = netconn_recv(newconn)) != NULL) + { + do + { + netbuf_data(buf, &data, &len); + netconn_write(newconn, data, len, NETCONN_COPY); + + } + while (netbuf_next(buf) >= 0); + + netbuf_delete(buf); + } + + /* Close connection and discard connection identifier. */ + netconn_close(newconn); + netconn_delete(newconn); + } + } + } + else + { + printf(" can not bind TCP netconn"); + } + } + else + { + printf("can not create TCP netconn"); + } +} +/*-----------------------------------------------------------------------------------*/ + +void tcpecho_init(void) +{ + sys_thread_new("tcpecho_thread", tcpecho_thread, NULL, DEFAULT_THREAD_STACKSIZE, TCPECHO_THREAD_PRIO); +} +/*-----------------------------------------------------------------------------------*/ + +void cmd_tcpecho(int argc, char **argv) +{ + printf("\n\rInit TCP ECHO Server ..."); + tcpecho_init(); + printf("\n\r\nPlease use echotool to connect to this echo server. ex. echotool 192.168.0.1 /p tcp /r 7 /n 0"); +} +#endif /* LWIP_NETCONN */ diff --git a/component/common/utilities/tcptest.c b/component/common/utilities/tcptest.c new file mode 100644 index 0000000..5095aa0 --- /dev/null +++ b/component/common/utilities/tcptest.c @@ -0,0 +1,534 @@ +#include "FreeRTOS.h" +#include "task.h" +#include "main.h" + +#include +#include +#include +#include +#include + +#define TCP_PACKET_COUNT 10000 +#define BSD_STACK_SIZE 256 + +#define HOST_IP "192.168.1.101" +#define REMOTE_IP ((u32_t)0xc0a80165UL) /*192.168.1.101*/ +#define LOCAL_IP ((u32_t)0xc0a80164UL) /*192.168.1.100*/ + +unsigned int g_srv_buf_size = 1500; +unsigned int g_cli_buf_size = 1500; +xTaskHandle g_server_task = NULL; +xTaskHandle g_client_task = NULL; + +xTaskHandle udpcllient_task = NULL; +xTaskHandle udpserver_task = NULL; + +unsigned char g_start_server = 0; +unsigned char g_start_client = 0; +unsigned char g_terminate = 0; + +unsigned char udp_start_server = 0; +unsigned char udp_start_client= 0; +char g_server_ip[16]; +unsigned long g_ulPacketCount = TCP_PACKET_COUNT; + +int BsdTcpClient(const char *host_ip, unsigned short usPort) +{ + int iCounter; + short sTestBufLen; + struct sockaddr_in sAddr; + int iAddrSize; + int iSockFD; + int iStatus; + long lLoopCount = 0; + char *cBsdBuf = NULL; + + if(g_cli_buf_size > 4300) + g_cli_buf_size = 4300; + else if (g_cli_buf_size == 0) + g_cli_buf_size = 1500; + + cBsdBuf = pvPortMalloc(g_cli_buf_size); + if(NULL == cBsdBuf){ + printf("\n\rTCP: Allocate client buffer failed.\n"); + return -1; + } + + // filling the buffer + for (iCounter = 0; iCounter < g_cli_buf_size; iCounter++) { + cBsdBuf[iCounter] = (char)(iCounter % 10); + } + sTestBufLen = g_cli_buf_size; + + //filling the TCP server socket address + FD_ZERO(&sAddr); + sAddr.sin_family = AF_INET; + sAddr.sin_port = htons(usPort); + sAddr.sin_addr.s_addr = inet_addr(host_ip); + + iAddrSize = sizeof(struct sockaddr_in); + + // creating a TCP socket + iSockFD = socket(AF_INET, SOCK_STREAM, 0); + if( iSockFD < 0 ) { + printf("\n\rTCP ERROR: create tcp client socket fd error!"); + goto Exit1; + } + + printf("\n\rTCP: ServerIP=%s port=%d.", host_ip, usPort); + printf("\n\rTCP: Create socket %d.", iSockFD); + // connecting to TCP server + iStatus = connect(iSockFD, (struct sockaddr *)&sAddr, iAddrSize); + if (iStatus < 0) { + printf("\n\rTCP ERROR: tcp client connect server error! "); + goto Exit; + } + + printf("\n\rTCP: Connect server successfully."); + // sending multiple packets to the TCP server + while (lLoopCount < g_ulPacketCount && !g_terminate) { + // sending packet + iStatus = send(iSockFD, cBsdBuf, sTestBufLen, 0 ); + if( iStatus <= 0 ) { + printf("\r\nTCP ERROR: tcp client send data error! iStatus:%d", iStatus); + goto Exit; + } + lLoopCount++; + //printf("BsdTcpClient:: send data count:%ld iStatus:%d \n\r", lLoopCount, iStatus); + } + + printf("\n\rTCP: Sent %u packets successfully.",g_ulPacketCount); + +Exit: + //closing the socket after sending 1000 packets + close(iSockFD); + +Exit1: + //free buffer + vPortFree(cBsdBuf); + + return 0; +} + +int BsdTcpServer(unsigned short usPort) +{ + struct sockaddr_in sAddr; + struct sockaddr_in sLocalAddr; + int iCounter; + int iAddrSize; + int iSockFD; + int iStatus; + int iNewSockFD; + long lLoopCount = 0; + //long lNonBlocking = 1; + int iTestBufLen; + int n; + char *cBsdBuf = NULL; + + if(g_srv_buf_size > 5000) + g_srv_buf_size = 5000; + else if (g_srv_buf_size == 0) + g_srv_buf_size = 1500; + + cBsdBuf = pvPortMalloc(g_srv_buf_size); + if(NULL == cBsdBuf){ + printf("\n\rTCP: Allocate server buffer failed.\n"); + return -1; + } + + // filling the buffer + for (iCounter = 0; iCounter < g_srv_buf_size; iCounter++) { + cBsdBuf[iCounter] = (char)(iCounter % 10); + } + iTestBufLen = g_srv_buf_size; + + // creating a TCP socket + iSockFD = socket(AF_INET, SOCK_STREAM, 0); + if( iSockFD < 0 ) { + goto Exit2; + } + + printf("\n\rTCP: Create server socket %d\n\r", iSockFD); + n = 1; + setsockopt( iSockFD, SOL_SOCKET, SO_REUSEADDR, + (const char *) &n, sizeof( n ) ); + + //filling the TCP server socket address + memset((char *)&sLocalAddr, 0, sizeof(sLocalAddr)); + sLocalAddr.sin_family = AF_INET; + sLocalAddr.sin_len = sizeof(sLocalAddr); + sLocalAddr.sin_port = htons(usPort); + sLocalAddr.sin_addr.s_addr = htonl(INADDR_ANY); + + iAddrSize = sizeof(sLocalAddr); + + // binding the TCP socket to the TCP server address + iStatus = bind(iSockFD, (struct sockaddr *)&sLocalAddr, iAddrSize); + if( iStatus < 0 ) { + printf("\n\rTCP ERROR: bind tcp server socket fd error! "); + goto Exit1; + } + printf("\n\rTCP: Bind successfully."); + + // putting the socket for listening to the incoming TCP connection + iStatus = listen(iSockFD, 20); + if( iStatus != 0 ) { + printf("\n\rTCP ERROR: listen tcp server socket fd error! "); + goto Exit1; + } + printf("\n\rTCP: Listen port %d", usPort); + + // setting socket option to make the socket as non blocking + //iStatus = setsockopt(iSockFD, SOL_SOCKET, SO_NONBLOCKING, + // &lNonBlocking, sizeof(lNonBlocking)); + //if( iStatus < 0 ) { + // return -1; + //} +Restart: + iNewSockFD = -1; + lLoopCount = 0; + + // waiting for an incoming TCP connection + while( iNewSockFD < 0 ) { + // accepts a connection form a TCP client, if there is any + // otherwise returns SL_EAGAIN + int addrlen=sizeof(sAddr); + iNewSockFD = accept(iSockFD, ( struct sockaddr *)&sAddr, + (socklen_t*)&addrlen); + if( iNewSockFD < 0 ) { + printf("\n\rTCP ERROR: Accept tcp client socket fd error! "); + goto Exit1; + } + printf("\n\rTCP: Accept socket %d successfully.", iNewSockFD); + } + + // waits packets from the connected TCP client + while (!g_terminate) { + iStatus = recv(iNewSockFD, cBsdBuf, iTestBufLen, 0); //MSG_DONTWAIT MSG_WAITALL + if( iStatus < 0 ) { + printf("\n\rTCP ERROR: server recv data error iStatus:%d ", iStatus); + goto Exit; + } else if (iStatus == 0) { + printf("\n\rTCP: Recieved %u packets successfully.", lLoopCount); + close(iNewSockFD); + goto Restart; + } + lLoopCount++; + } + +Exit: + // close the connected socket after receiving from connected TCP client + close(iNewSockFD); + +Exit1: + // close the listening socket + close(iSockFD); + +Exit2: + //free buffer + vPortFree(cBsdBuf); + + return 0; +} + +static void TcpServerHandler(void *param) +{ + unsigned short port = 5001; + + printf("\n\rTCP: Start tcp Server!"); + if(g_start_server) + BsdTcpServer(port); + +#if defined(INCLUDE_uxTaskGetStackHighWaterMark) && (INCLUDE_uxTaskGetStackHighWaterMark == 1) + printf("\n\rMin available stack size of %s = %d * %d bytes\n\r", __FUNCTION__, uxTaskGetStackHighWaterMark(NULL), sizeof(portBASE_TYPE)); +#endif + printf("\n\rTCP: Tcp server stopped!"); + g_server_task = NULL; + vTaskDelete(NULL); +} + +static void TcpClientHandler(void *param) +{ + unsigned short port = 5001; + + printf("\n\rTCP: Start tcp client!"); + if(g_start_client) + BsdTcpClient(g_server_ip, port); + +#if defined(INCLUDE_uxTaskGetStackHighWaterMark) && (INCLUDE_uxTaskGetStackHighWaterMark == 1) + printf("\n\rMin available stack size of %s = %d * %d bytes\n\r", __FUNCTION__, uxTaskGetStackHighWaterMark(NULL), sizeof(portBASE_TYPE)); +#endif + printf("\n\rTCP: Tcp client stopped!"); + g_client_task = NULL; + vTaskDelete(NULL); +} + + +/***************************udp related*********************************/ +int udpclient() +{ + int cli_sockfd; + socklen_t addrlen; + struct sockaddr_in cli_addr; + int loop= 0; + char *buffer ; +// int delay = 2; + + + if(!g_ulPacketCount) + g_ulPacketCount = 100; + + if(!g_cli_buf_size) + g_cli_buf_size = 1500; + + buffer = (char*)pvPortMalloc(g_cli_buf_size); + + if(NULL == buffer){ + printf("\n\rudpclient: Allocate buffer failed.\n"); + return -1; + } + + /*create socket*/ + memset(buffer, 0, g_cli_buf_size); + cli_sockfd=socket(AF_INET,SOCK_DGRAM,0); + if (cli_sockfd<0) { + printf("create socket failed\r\n\n"); + return 1; + } + + /* fill sockaddr_in*/ + addrlen=sizeof(struct sockaddr_in); + memset(&cli_addr, 0, addrlen); + + cli_addr.sin_family=AF_INET; + cli_addr.sin_addr.s_addr=inet_addr(g_server_ip); + cli_addr.sin_port=htons(5001); + + /* send data to server*/ + while(loop < g_ulPacketCount && !g_terminate) { + if(sendto(cli_sockfd, buffer, g_cli_buf_size, 0,(struct sockaddr*)&cli_addr, addrlen) < 0) { +// Dynamic delay to prevent send fail due to limited skb, this will degrade throughtput +// if(delay < 100) +// delay += 2; + } + +// vTaskDelay(delay); + loop++; + } + close(cli_sockfd); + //free buffer + vPortFree(buffer); + return 0; +} + +int udpserver() +{ + int ser_sockfd; + socklen_t addrlen; + struct sockaddr_in ser_addr, peer_addr; + uint32_t start_time, end_time; + unsigned char *buffer; + int total_size = 0, report_interval = 1; + + if (g_srv_buf_size == 0) + g_srv_buf_size = 1500; + + buffer = pvPortMalloc(g_srv_buf_size); + + if(NULL == buffer){ + printf("\n\rudpclient: Allocate buffer failed.\n"); + return -1; + } + + /*create socket*/ + ser_sockfd=socket(AF_INET,SOCK_DGRAM,0); + if (ser_sockfd<0) { + printf("\n\rudp server success"); + return 1; + } + + /*fill the socket in*/ + addrlen=sizeof(ser_addr); + memset(&ser_addr, 0,addrlen); + ser_addr.sin_family=AF_INET; + ser_addr.sin_addr.s_addr=htonl(INADDR_ANY); + ser_addr.sin_port=htons(5001); + + /*bind*/ + if (bind(ser_sockfd,(struct sockaddr *)&ser_addr,addrlen)<0) { + printf("bind failed\r\n"); + return 1; + } + + start_time = xTaskGetTickCount(); + total_size = 0; + + while(1) { + int read_size = 0; + addrlen = sizeof(peer_addr); + read_size=recvfrom(ser_sockfd,buffer,g_srv_buf_size,0,(struct sockaddr *) &peer_addr,&addrlen); + if(read_size < 0){ + printf("%s recv error\r\n", __FUNCTION__); + goto Exit; + } + + end_time = xTaskGetTickCount(); + total_size += read_size; + if((end_time - start_time) >= (configTICK_RATE_HZ * report_interval)) { + printf("\nUDP recv %d bytes in %d ticks, %d Kbits/sec\n", + total_size, end_time - start_time, total_size * 8 / 1024 / ((end_time - start_time) / configTICK_RATE_HZ)); + start_time = end_time; + total_size = 0; + } + + /*ack data to client*/ +// Not send ack to prevent send fail due to limited skb, but it will have warning at iperf client +// sendto(ser_sockfd,buffer,read_size,0,(struct sockaddr*)&peer_addr,sizeof(peer_addr)); + } + +Exit: + close(ser_sockfd); + //free buffer + vPortFree(buffer); + return 0; +} + +void Udpclienthandler(void *param) +{ + /*here gives the udp demo code*/ + printf("\n\rUdp client test"); + + udpclient(); +#if defined(INCLUDE_uxTaskGetStackHighWaterMark) && (INCLUDE_uxTaskGetStackHighWaterMark == 1) + printf("\n\rMin available stack size of %s = %d * %d bytes", __FUNCTION__, uxTaskGetStackHighWaterMark(NULL), sizeof(portBASE_TYPE)); +#endif + printf("\n\rUDP: udp client stopped!"); + udpcllient_task = NULL; + vTaskDelete(NULL); +} + +void Udpserverhandler(void *param) +{ + /*here gives the udp demo code*/ + printf("\n\rUdp server test"); + + udpserver(); +#if defined(INCLUDE_uxTaskGetStackHighWaterMark) && (INCLUDE_uxTaskGetStackHighWaterMark == 1) + printf("\n\rMin available stack size of %s = %d * %d bytes", __FUNCTION__, uxTaskGetStackHighWaterMark(NULL), sizeof(portBASE_TYPE)); +#endif + printf("\n\rUDP: udp client stopped!"); + udpserver_task = NULL; + vTaskDelete(NULL); +} + +/***************************end of udp*********************************/ +void cmd_tcp(int argc, char **argv) +{ + g_terminate = g_start_server = g_start_client = 0; + g_ulPacketCount = 10000; + memset(g_server_ip, 0, 16); + + if(argc < 2) + goto Exit; + + if(strcmp(argv[1], "-s") == 0 ||strcmp(argv[1], "s") == 0) { + if(g_server_task){ + printf("\n\rTCP: Tcp Server is already running."); + return; + }else{ + g_start_server = 1; + if(argc == 3) + g_srv_buf_size = atoi(argv[2]); + } + }else if(strcmp(argv[1], "-c") == 0 || strcmp(argv[1], "c") == 0) { + if(g_client_task){ + printf("\n\rTCP: Tcp client is already running. Please enter \"tcp stop\" to stop it."); + return; + }else{ + if(argc < 4) + goto Exit; + g_start_client = 1; + strncpy(g_server_ip, argv[2], (strlen(argv[2])>16)?16:strlen(argv[2])); + g_cli_buf_size = atoi(argv[3]); + if(argc == 5) + g_ulPacketCount = atoi(argv[4]); + } + + }else if(strcmp(argv[1], "stop") == 0){ + g_terminate = 1; + }else + goto Exit; + + if(g_start_server && (NULL == g_server_task)){ + if(xTaskCreate(TcpServerHandler, "tcp_server", BSD_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1 + PRIORITIE_OFFSET, &g_server_task) != pdPASS) + printf("\n\rTCP ERROR: Create tcp server task failed."); + } + if(g_start_client && (NULL == g_client_task)){ + if(xTaskCreate(TcpClientHandler, "tcp_client", BSD_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1 + PRIORITIE_OFFSET, &g_client_task) != pdPASS) + printf("\n\rTCP ERROR: Create tcp client task failed."); + } + + return; +Exit: + printf("\n\rTCP: Tcp test command format error!"); + printf("\n\rPlease Enter: \"tcp -s\" to start tcp server or \"tcp <-c *.*.*.*> [count]]\" to start tcp client\n\r"); + return; +} + +void cmd_udp(int argc, char **argv) +{ + g_terminate = udp_start_server = udp_start_client = 0; + g_ulPacketCount = 10000; + if(argc == 2){ + if(strcmp(argv[1], "-s") == 0 ||strcmp(argv[1], "s") == 0){ + if(udpserver_task){ + printf("\r\nUDP: UDP Server is already running."); + return; + }else{ + udp_start_server = 1; + } + }else if(strcmp(argv[1], "-c") == 0 || strcmp(argv[1], "c") == 0){ + if(udpcllient_task){ + printf("\r\nUDP: UDP Server is already running."); + return; + }else{ + udp_start_client= 1; + } + }else if(strcmp(argv[1], "stop") == 0){ + g_terminate = 1; + }else + goto Exit; + }else if(strcmp(argv[1], "-c") == 0 || strcmp(argv[1], "c") == 0) { + if(udpcllient_task){ + printf("\n\nUDP: UDP client is already running. Please enter \"udp stop\" to stop it."); + return; + }else{ + if(argc < 4) + goto Exit; + udp_start_client = 1; + strncpy(g_server_ip, argv[2], (strlen(argv[2])>16)?16:strlen(argv[2])); + g_cli_buf_size = atoi(argv[3]); + if(argc == 5) + g_ulPacketCount = atoi(argv[4]); + } + + }else + goto Exit; + + if(udp_start_server && (NULL == udpserver_task)){ + if(xTaskCreate(Udpserverhandler, "udp_server", BSD_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, &udpserver_task) != pdPASS) + printf("\r\nUDP ERROR: Create udp server task failed."); + } + + if(udp_start_client && (NULL == udpcllient_task)){ + if(xTaskCreate(Udpclienthandler, "udp_client", BSD_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, &udpcllient_task) != pdPASS) + printf("\r\nUDP ERROR: Create udp client task failed."); + } + + return; +Exit: + printf("\r\nUDP: udp test command format error!"); + printf("\r\nPlease Enter: \"udp -s\" to start udp server or \"udp -c to start udp client\r\n"); + return; +} + diff --git a/component/common/utilities/udpecho.c b/component/common/utilities/udpecho.c new file mode 100644 index 0000000..57674a0 --- /dev/null +++ b/component/common/utilities/udpecho.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + + +#include "lwip/opt.h" + +#if LWIP_NETCONN + +#include "lwip/api.h" +#include "lwip/sys.h" + + +#define UDPECHO_THREAD_PRIO ( tskIDLE_PRIORITY + 3 ) + +static struct netconn *conn; +static struct netbuf *buf; +static struct ip_addr *addr; +static unsigned short port; +/*-----------------------------------------------------------------------------------*/ +static void udpecho_thread(void *arg) +{ + err_t err; + + LWIP_UNUSED_ARG(arg); + + conn = netconn_new(NETCONN_UDP); + if (conn!= NULL) + { + err = netconn_bind(conn, IP_ADDR_ANY, 7); + if (err == ERR_OK) + { + while (1) + { + buf = netconn_recv(conn); + + if (buf!= NULL) + { + addr = netbuf_fromaddr(buf); + port = netbuf_fromport(buf); + netconn_connect(conn, addr, port); + buf->addr = NULL; + netconn_send(conn,buf); + netbuf_delete(buf); + } + } + } + else + { + printf("can not bind netconn"); + } + } + else + { + printf("can create new UDP netconn"); + } +} +/*-----------------------------------------------------------------------------------*/ +void udpecho_init(void) +{ + sys_thread_new("udpecho_thread", udpecho_thread, NULL, DEFAULT_THREAD_STACKSIZE,UDPECHO_THREAD_PRIO ); +} + +#endif /* LWIP_NETCONN */ diff --git a/component/common/utilities/update.c b/component/common/utilities/update.c new file mode 100644 index 0000000..0df7bf2 --- /dev/null +++ b/component/common/utilities/update.c @@ -0,0 +1,971 @@ +#include +#include +#include +#include +#include +#include + +#if !defined(CONFIG_PLATFORM_8195A) && !defined(CONFIG_PLATFORM_8711B) +#include +#if defined(STM32F2XX) +#include +#elif defined(STM32F4XX) +#include +#elif defined(STM32f1xx) +#include +#endif +#include "cloud_updater.h" +#else +#include "flash_api.h" +#endif +#include "update.h" +#if defined(CONFIG_PLATFORM_8195A) || defined(CONFIG_PLATFORM_8711B) +#define OFFSET_DATA FLASH_SYSTEM_DATA_ADDR +#define IMAGE_2 0x0000B000 +#define WRITE_OTA_ADDR 0 +#define CONFIG_CUSTOM_SIGNATURE 1 +#define SWAP_UPDATE 0 + +#if WRITE_OTA_ADDR +#define BACKUP_SECTOR (FLASH_SYSTEM_DATA_ADDR - 0x1000) +#endif + +#if CONFIG_CUSTOM_SIGNATURE +/* --------------------------------------------------- + * Customized Signature + * ---------------------------------------------------*/ +// This signature can be used to verify the correctness of the image +// It will be located in fixed location in application image +#pragma location=".custom.validate.rodata" +const unsigned char cus_sig[32] = "Customer Signature-modelxxx"; +#endif + +#else +#define CONFIG_SECTOR FLASH_Sector_1 +#define APPLICATION_SECTOR FLASH_Sector_2 +#define UPDATE_SECTOR FLASH_Sector_8 +#endif +#define STACK_SIZE 1024 +#define TASK_PRIORITY tskIDLE_PRIORITY + 1 +#define BUF_SIZE 512 +#define ETH_ALEN 6 + +#define SERVER_LOCAL 1 +#define SERVER_CLOUD 2 +#define SERVER_TYPE SERVER_LOCAL +#define UPDATE_DBG 1 + +#if (SERVER_TYPE == SERVER_LOCAL) +typedef struct +{ + uint32_t ip_addr; + uint16_t port; +}update_cfg_local_t; +#endif + +#if (SERVER_TYPE == SERVER_CLOUD) +#define REPOSITORY_LEN 16 +#define FILE_PATH_LEN 64 +typedef struct +{ + uint8_t repository[REPOSITORY_LEN]; + uint8_t file_path[FILE_PATH_LEN]; +}update_cfg_cloud_t; +#endif + +sys_thread_t TaskOTA = NULL; +//--------------------------------------------------------------------- +static void* update_malloc(unsigned int size) +{ + return pvPortMalloc(size); +} + +//--------------------------------------------------------------------- +static void update_free(void *buf) +{ + vPortFree(buf); +} + +//--------------------------------------------------------------------- +#if (SERVER_TYPE == SERVER_LOCAL) +#if defined(STM32F2XX) ||(STM32F4XX) +static void update_ota_local_task(void *param) +{ + int server_socket = 0; + struct sockaddr_in server_addr; + char *buf; + int read_bytes, size = 0, i; + update_cfg_local_t *cfg = (update_cfg_local_t*)param; + uint32_t address, checksum = 0; +#if CONFIG_WRITE_MAC_TO_FLASH + char mac[ETH_ALEN]; +#endif + printf("\n\r[%s] Update task start", __FUNCTION__); + buf = update_malloc(BUF_SIZE); + if(!buf){ + printf("\n\r[%s] Alloc buffer failed", __FUNCTION__); + goto update_ota_exit; + } + // Connect socket + server_socket = socket(AF_INET, SOCK_STREAM, 0); + if(server_socket < 0){ + printf("\n\r[%s] Create socket failed", __FUNCTION__); + goto update_ota_exit; + } + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = cfg->ip_addr; + server_addr.sin_port = cfg->port; + + if(connect(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1){ + printf("\n\r[%s] socket connect failed", __FUNCTION__); + goto update_ota_exit; + } + // Erase config sectors + if(flash_EraseSector(CONFIG_SECTOR) < 0){ + printf("\n\r[%s] Erase sector failed", __FUNCTION__); + goto update_ota_exit; + } +#if CONFIG_WRITE_MAC_TO_FLASH + // Read MAC address + if(flash_Read(FLASH_ADD_STORE_MAC, mac, ETH_ALEN) < 0){ + printf("\n\r[%s] Read MAC error", __FUNCTION__); + goto update_ota_exit; + } +#endif + // Erase update sectors + for(i = UPDATE_SECTOR; i <= FLASH_Sector_11; i += 8){ + if(flash_EraseSector(i) < 0){ + printf("\n\r[%s] Erase sector failed", __FUNCTION__); + goto update_ota_exit; + } + } + // Write update sectors + address = flash_SectorAddress(UPDATE_SECTOR); + printf("\n\r"); + while(1){ + read_bytes = read(server_socket, buf, BUF_SIZE); + if(read_bytes == 0) break; // Read end + if(read_bytes < 0){ + printf("\n\r[%s] Read socket failed", __FUNCTION__); + goto update_ota_exit; + } + if(flash_Wrtie(address + size, buf, read_bytes) < 0){ + printf("\n\r[%s] Write sector failed", __FUNCTION__); + goto update_ota_exit; + } + size += read_bytes; + for(i = 0; i < read_bytes; i ++) + checksum += buf[i]; + printf("\rUpdate file size = %d ", size); + } +#if CONFIG_WRITE_MAC_TO_FLASH + //Write MAC address + if(!(mac[0]==0xff&&mac[1]==0xff&&mac[2]==0xff&&mac[3]==0xff&&mac[4]==0xff&&mac[5]==0xff)){ + if(flash_Wrtie(FLASH_ADD_STORE_MAC, mac, ETH_ALEN) < 0){ + printf("\n\r[%s] Write MAC failed", __FUNCTION__); + goto update_ota_exit; + } + } +#endif + // Write config sectors + address = flash_SectorAddress(CONFIG_SECTOR); + if( (flash_Wrtie(address, (char*)&size, 4) < 0) || + (flash_Wrtie(address+4, (char*)&checksum, 4) < 0) ){ + printf("\n\r[%s] Write sector failed", __FUNCTION__); + goto update_ota_exit; + } + printf("\n\r[%s] Update OTA success!", __FUNCTION__); +update_ota_exit: + if(buf) + update_free(buf); + if(server_socket >= 0) + close(server_socket); + if(param) + update_free(param); + TaskOTA = NULL; + printf("\n\r[%s] Update task exit", __FUNCTION__); + vTaskDelete(NULL); + return; +} +#elif defined(STM32f1xx) +static void update_ota_local_task(void *param) +{ + int server_socket; + struct sockaddr_in server_addr; + char *buf, flag_a = 0; + int read_bytes, size = 0, i; + update_cfg_local_t *cfg = (update_cfg_local_t*)param; + uint32_t address, checksum = 0; + uint16_t a = 0; +#if CONFIG_WRITE_MAC_TO_FLASH + char mac[ETH_ALEN]; +#endif + + printf("\n\r[%s] Update task start", __FUNCTION__); + buf = update_malloc(BUF_SIZE); + if(!buf){ + printf("\n\r[%s] Alloc buffer failed", __FUNCTION__); + goto update_ota_exit; + } + // Connect socket + server_socket = socket(AF_INET, SOCK_STREAM, 0); + if(server_socket < 0){ + printf("\n\r[%s] Create socket failed", __FUNCTION__); + goto update_ota_exit; + } + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = cfg->ip_addr; + server_addr.sin_port = cfg->port; + + if(connect(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1){ + printf("\n\r[%s] socket connect failed", __FUNCTION__); + goto update_ota_exit; + } + // Erase config sectors + for(i = CONFIG_SECTOR; i < APPLICATION_SECTOR; i += FLASH_PAGE_SIZE){ + if(flash_EraseSector(i) < 0){ + printf("\n\r[%s] Erase sector failed", __FUNCTION__); + goto update_ota_exit; + } + } +#if CONFIG_WRITE_MAC_TO_FLASH + // Read MAC address + if(flash_Read(FLASH_ADD_STORE_MAC, mac, ETH_ALEN) < 0){ + printf("\n\r[%s] Read MAC error", __FUNCTION__); + goto update_ota_exit; + } +#endif + + // Erase update sectors + for(i = UPDATE_SECTOR; i < FLASH_Sector_0 + FLASH_SIZE; i += FLASH_PAGE_SIZE){ + if(flash_EraseSector(i) < 0){ + printf("\n\r[%s] Erase sector failed", __FUNCTION__); + goto update_ota_exit; + } + } + // Write update sectors + address = UPDATE_SECTOR; + printf("\n\r"); + while(1){ + read_bytes = read(server_socket, buf, BUF_SIZE); + if(read_bytes == 0) break; // Read end + if(read_bytes < 0){ + printf("\n\r[%s] Read socket failed", __FUNCTION__); + goto update_ota_exit; + } + if(flag_a == 0){ + if(read_bytes % 2 != 0){ + a = buf[read_bytes - 1]; + flag_a = 1; + if(flash_Wrtie(address + size, buf, read_bytes - 1) < 0){ + printf("\n\r[%s] Write sector failed", __FUNCTION__); + goto update_ota_exit; + } + size += read_bytes - 1; + } + else{ + if(flash_Wrtie(address + size, buf, read_bytes) < 0){ + printf("\n\r[%s] Write sector failed", __FUNCTION__); + goto update_ota_exit; + } + size += read_bytes; + } + } + else{ + a = buf[0] << 8 | a; + if(flash_Wrtie(address + size, (char*)(&a), 2) < 0){ + printf("\n\r[%s] Write sector failed", __FUNCTION__); + goto update_ota_exit; + } + size += 2; + a = 0; + flag_a = 0; + if((read_bytes - 1) % 2 != 0){ + a = buf[read_bytes - 1]; + flag_a = 1; + if(flash_Wrtie(address + size, buf + 1, read_bytes - 2) < 0){ + printf("\n\r[%s] Write sector failed", __FUNCTION__); + goto update_ota_exit; + } + size += read_bytes - 2; + } + else{ + if(flash_Wrtie(address + size, buf + 1, read_bytes - 1) < 0){ + printf("\n\r[%s] Write sector failed", __FUNCTION__); + goto update_ota_exit; + } + size += read_bytes - 1; + } + } + for(i = 0; i < read_bytes; i ++) + checksum += buf[i]; + printf("\rUpdate file size = %d ", size); + } + if(flag_a){ + if(flash_Wrtie(address + size, (char*)(&a), 2) < 0){ + printf("\n\r[%s] Write sector failed", __FUNCTION__); + goto update_ota_exit; + } + size += 1; + } +#if CONFIG_WRITE_MAC_TO_FLASH + //Write MAC address + if(!(mac[0]==0xff&&mac[1]==0xff&&mac[2]==0xff&&mac[3]==0xff&&mac[4]==0xff&&mac[5]==0xff)){ + if(flash_Wrtie(FLASH_ADD_STORE_MAC, mac, ETH_ALEN) < 0){ + printf("\n\r[%s] Write MAC failed", __FUNCTION__); + goto update_ota_exit; + } + } +#endif + + // Write config sectors + address = CONFIG_SECTOR; + if( (flash_Wrtie(address, (char*)&size, 4) < 0) || + (flash_Wrtie(address+4, (char*)&checksum, 4) < 0) ){ + printf("\n\r[%s] Write sector failed", __FUNCTION__); + goto update_ota_exit; + } + printf("\n\r[%s] Update OTA success!", __FUNCTION__); +update_ota_exit: + if(buf) + update_free(buf); + if(server_socket >= 0) + close(server_socket); + if(param) + update_free(param); + TaskOTA = NULL; + printf("\n\r[%s] Update task exit", __FUNCTION__); + vTaskDelete(NULL); + return; +} + +#elif defined(CONFIG_PLATFORM_8195A) || defined(CONFIG_PLATFORM_8711B) + +void ota_platform_reset(void) +{ + //wifi_off(); + + // Set processor clock to default before system reset + HAL_WRITE32(SYSTEM_CTRL_BASE, 0x14, 0x00000021); + osDelay(100); + + // Cortex-M3 SCB->AIRCR + HAL_WRITE32(0xE000ED00, 0x0C, (0x5FA << 16) | // VECTKEY + (HAL_READ32(0xE000ED00, 0x0C) & (7 << 8)) | // PRIGROUP + (1 << 2)); // SYSRESETREQ + while(1) osDelay(1000); +} +#if WRITE_OTA_ADDR +int write_ota_addr_to_system_data(flash_t *flash, uint32_t ota_addr) +{ + uint32_t data, i = 0; + //Get upgraded image 2 addr from offset + flash_read_word(flash, OFFSET_DATA, &data); + printf("\n\r[%s] data 0x%x ota_addr 0x%x", __FUNCTION__, data, ota_addr); + if(data == ~0x0){ + flash_write_word(flash, OFFSET_DATA, ota_addr); + }else{ + //erase backup sector + flash_erase_sector(flash, BACKUP_SECTOR); + //backup system data to backup sector + for(i = 0; i < 0x1000; i+= 4){ + flash_read_word(flash, OFFSET_DATA + i, &data); + if(i == 0) + data = ota_addr; + flash_write_word(flash, BACKUP_SECTOR + i,data); + } + //erase system data + flash_erase_sector(flash, OFFSET_DATA); + //write data back to system data + for(i = 0; i < 0x1000; i+= 4){ + flash_read_word(flash, BACKUP_SECTOR + i, &data); + flash_write_word(flash, OFFSET_DATA + i,data); + } + //erase backup sector + flash_erase_sector(flash, BACKUP_SECTOR); + } + return 0; +} +#endif +static void update_ota_local_task(void *param) +{ + int server_socket; + struct sockaddr_in server_addr; + unsigned char *buf; + int read_bytes = 0, size = 0, i = 0; + update_cfg_local_t *cfg = (update_cfg_local_t *)param; + uint32_t address, checksum = 0; + flash_t flash; + uint32_t NewImg2BlkSize = 0, NewImg2Len = 0, NewImg2Addr = 0, file_checksum[3]; + uint32_t Img2Len = 0; + int ret = -1 ; + //uint8_t signature[8] = {0x38,0x31,0x39,0x35,0x38,0x37,0x31,0x31}; + uint32_t IMAGE_x = 0, ImgxLen = 0, ImgxAddr = 0; +#if WRITE_OTA_ADDR + uint32_t ota_addr = 0x80000; +#endif +#if CONFIG_CUSTOM_SIGNATURE + char custom_sig[32] = "Customer Signature-modelxxx"; + uint32_t read_custom_sig[8]; +#endif + printf("\n\r[%s] Update task start", __FUNCTION__); + buf = update_malloc(BUF_SIZE); + if(!buf){ + printf("\n\r[%s] Alloc buffer failed", __FUNCTION__); + goto update_ota_exit; + } + // Connect socket + server_socket = socket(AF_INET, SOCK_STREAM, 0); + if(server_socket < 0){ + printf("\n\r[%s] Create socket failed", __FUNCTION__); + goto update_ota_exit; + } + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = cfg->ip_addr; + server_addr.sin_port = cfg->port; + + if(connect(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1){ + printf("\n\r[%s] socket connect failed", __FUNCTION__); + goto update_ota_exit; + } + DBG_INFO_MSG_OFF(_DBG_SPI_FLASH_); + +#if 1 + // The upgraded image2 pointer must 4K aligned and should not overlap with Default Image2 + flash_read_word(&flash, IMAGE_2, &Img2Len); + IMAGE_x = IMAGE_2 + Img2Len + 0x10; + flash_read_word(&flash, IMAGE_x, &ImgxLen); + flash_read_word(&flash, IMAGE_x+4, &ImgxAddr); + if(ImgxAddr==0x30000000){ + printf("\n\r[%s] IMAGE_3 0x%x Img3Len 0x%x", __FUNCTION__, IMAGE_x, ImgxLen); + }else{ + printf("\n\r[%s] no IMAGE_3", __FUNCTION__); + // no image3 + IMAGE_x = IMAGE_2; + ImgxLen = Img2Len; + } +#if WRITE_OTA_ADDR + if((ota_addr > IMAGE_x) && ((ota_addr < (IMAGE_x+ImgxLen))) || + (ota_addr < IMAGE_x) || + ((ota_addr & 0xfff) != 0)|| + (ota_addr == ~0x0)){ + printf("\n\r[%s] illegal ota addr 0x%x", __FUNCTION__, ota_addr); + goto update_ota_exit; + }else + write_ota_addr_to_system_data( &flash, ota_addr); +#endif + //Get upgraded image 2 addr from offset + flash_read_word(&flash, OFFSET_DATA, &NewImg2Addr); + if((NewImg2Addr > IMAGE_x) && ((NewImg2Addr < (IMAGE_x+ImgxLen))) || + (NewImg2Addr < IMAGE_x) || + ((NewImg2Addr & 0xfff) != 0)|| + (NewImg2Addr == ~0x0)){ + printf("\n\r[%s] after read, NewImg2Addr 0x%x, Img2Len 0x%x", __FUNCTION__, NewImg2Addr, Img2Len); + goto update_ota_exit; + } +#else + //For test, hard code addr + NewImg2Addr = 0x80000; +#endif + + //Clear file_checksum + memset(file_checksum, 0, sizeof(file_checksum)); + + if(file_checksum[0] == 0){ + printf("\n\r[%s] Read chechsum first", __FUNCTION__); + read_bytes = read(server_socket, file_checksum, sizeof(file_checksum)); + // !X!X!X!X!X!X!X!X!X!X!X!X!X!X!X!X!X!X!X!X + // !W checksum !W padding 0 !W file size !W + // !X!X!X!X!X!X!X!X!X!X!X!X!X!X!X!X!X!X!X!X + printf("\n\r[%s] chechsum read_bytes %d", __FUNCTION__, read_bytes); + printf("\n\r[%s] chechsum 0x%x, file size 0x%x", __FUNCTION__, file_checksum[0],file_checksum[2]); + if(file_checksum[2] == 0){ + printf("\n\r[%s] No checksum and file size", __FUNCTION__); + goto update_ota_exit; + } + } + +#if SWAP_UPDATE + uint32_t SigImage0,SigImage1; + uint32_t Part1Addr=0xFFFFFFFF, Part2Addr=0xFFFFFFFF; + uint32_t OldImg2Addr; + flash_read_word(&flash, 0x18, &Part1Addr); + Part1Addr = (Part1Addr&0xFFFF)*1024; // first partition + Part2Addr = NewImg2Addr; + + // read Part1/Part2 signature + flash_read_word(&flash, Part1Addr+8, &SigImage0); + flash_read_word(&flash, Part1Addr+12, &SigImage1); + printf("\n\r[%s] Part1 Sig %x", __FUNCTION__, SigImage0); + if(SigImage0==0x35393138 && SigImage1==0x31313738) + OldImg2Addr = Part1Addr; // newer version, change to older version + else + NewImg2Addr = Part1Addr; // update to older version + flash_read_word(&flash, Part2Addr+8, &SigImage0); + flash_read_word(&flash, Part2Addr+12, &SigImage1); + printf("\n\r[%s] Part2 Sig %x", __FUNCTION__, SigImage0); + if(SigImage0==0x35393138 && SigImage1==0x31313738) + OldImg2Addr = Part2Addr; + else + NewImg2Addr = Part2Addr; + + printf("\n\r[%s] New %x, Old %x", __FUNCTION__, NewImg2Addr, OldImg2Addr); + + if( NewImg2Addr==Part1Addr ){ + if( file_checksum[2] > (Part2Addr-Part1Addr) ){ // firmware size too large + printf("\n\r[%s] Part1 size < OTA size", __FUNCTION__); + goto update_ota_exit; + // or update to partition2 + // NewImg2Addr = Part2Addr; + } + } + +#endif + + //Erase upgraded image 2 region + if(NewImg2Len == 0){ + NewImg2Len = file_checksum[2]; + printf("\n\r[%s] NewImg2Len %d ", __FUNCTION__, NewImg2Len); + if((int)NewImg2Len > 0){ + NewImg2BlkSize = ((NewImg2Len - 1)/4096) + 1; + printf("\n\r[%s] NewImg2BlkSize %d 0x%8x", __FUNCTION__, NewImg2BlkSize, NewImg2BlkSize); + for( i = 0; i < NewImg2BlkSize; i++) + flash_erase_sector(&flash, NewImg2Addr + i * 4096); + }else{ + printf("\n\r[%s] Size INVALID", __FUNCTION__); + goto update_ota_exit; + } + } + + printf("\n\r[%s] NewImg2Addr 0x%x", __FUNCTION__, NewImg2Addr); + // Write New Image 2 sector + if(NewImg2Addr != ~0x0){ + address = NewImg2Addr; + printf("\n\r"); + while(1){ + memset(buf, 0, BUF_SIZE); + read_bytes = read(server_socket, buf, BUF_SIZE); + if(read_bytes == 0) break; // Read end + if(read_bytes < 0){ + printf("\n\r[%s] Read socket failed", __FUNCTION__); + goto update_ota_exit; + } + //printf("\n\r[%s] read_bytes %d", __FUNCTION__, read_bytes); + + #if 1 + if(flash_stream_write(&flash, address + size, read_bytes, buf) < 0){ + printf("\n\r[%s] Write sector failed", __FUNCTION__); + goto update_ota_exit; + } + size += read_bytes; + for(i = 0; i < read_bytes; i ++) + checksum += buf[i]; + #else + size += read_bytes; + for(i = 0; i < read_bytes; i ++){ + checksum += buf[i]; + } + #endif + } + printf("\n\r"); + printf("\n\rUpdate file size = %d checksum 0x%x ", size, checksum); +#if CONFIG_WRITE_MAC_TO_FLASH + //Write MAC address + if(!(mac[0]==0xff&&mac[1]==0xff&&mac[2]==0xff&&mac[3]==0xff&&mac[4]==0xff&&mac[5]==0xff)){ + if(flash_write_word(&flash, FLASH_ADD_STORE_MAC, mac, ETH_ALEN) < 0){ + printf("\n\r[%s] Write MAC failed", __FUNCTION__); + goto update_ota_exit; + } + } +#endif + printf("\n\r checksum 0x%x file_checksum 0x%x ", checksum, *(file_checksum)); +#if CONFIG_CUSTOM_SIGNATURE + for(i = 0; i < 8; i ++){ + flash_read_word(&flash, NewImg2Addr + 0x28 + i *4, read_custom_sig + i); + } + printf("\n\r[%s] read_custom_sig %s", __FUNCTION__ , (char*)read_custom_sig); +#endif + // compare checksum with received checksum + if(!memcmp(&checksum,file_checksum,sizeof(checksum)) +#if CONFIG_CUSTOM_SIGNATURE + && !strcmp((char*)read_custom_sig,custom_sig) +#endif + ){ + + //Set signature in New Image 2 addr + 8 and + 12 + uint32_t sig_readback0,sig_readback1; + flash_write_word(&flash,NewImg2Addr + 8, 0x35393138); + flash_write_word(&flash,NewImg2Addr + 12, 0x31313738); + flash_read_word(&flash, NewImg2Addr + 8, &sig_readback0); + flash_read_word(&flash, NewImg2Addr + 12, &sig_readback1); + printf("\n\r[%s] signature %x,%x, checksum 0x%x", __FUNCTION__ , sig_readback0, sig_readback1, checksum); +#if SWAP_UPDATE + flash_write_word(&flash,OldImg2Addr + 8, 0x35393130); + flash_write_word(&flash,OldImg2Addr + 12, 0x31313738); + flash_read_word(&flash, OldImg2Addr + 8, &sig_readback0); + flash_read_word(&flash, OldImg2Addr + 12, &sig_readback1); + printf("\n\r[%s] old signature %x,%x", __FUNCTION__ , sig_readback0, sig_readback1); +#endif + printf("\n\r[%s] Update OTA success!", __FUNCTION__); + + ret = 0; + } + } +update_ota_exit: + if(buf) + update_free(buf); + if(server_socket >= 0) + close(server_socket); + if(param) + update_free(param); + TaskOTA = NULL; + printf("\n\r[%s] Update task exit", __FUNCTION__); + if(!ret){ + printf("\n\r[%s] Ready to reboot", __FUNCTION__); + ota_platform_reset(); + } + vTaskDelete(NULL); + return; + +} +#endif + +//--------------------------------------------------------------------- +int update_ota_local(char *ip, int port) +{ + update_cfg_local_t *pUpdateCfg; + + if(TaskOTA){ + printf("\n\r[%s] Update task has created.", __FUNCTION__); + return 0; + } + pUpdateCfg = update_malloc(sizeof(update_cfg_local_t)); + if(pUpdateCfg == NULL){ + printf("\n\r[%s] Alloc update cfg failed", __FUNCTION__); + return -1; + } + pUpdateCfg->ip_addr = inet_addr(ip); + pUpdateCfg->port = ntohs(port); + + TaskOTA = sys_thread_new("OTA_server", update_ota_local_task, pUpdateCfg, STACK_SIZE, TASK_PRIORITY); + if(TaskOTA == NULL){ + update_free(pUpdateCfg); + printf("\n\r[%s] Create update task failed", __FUNCTION__); + } + return 0; +} +#endif // #if (SERVER_TYPE == SERVER_LOCAL) + +//--------------------------------------------------------------------- +#if (SERVER_TYPE == SERVER_CLOUD) +#if defined(STM32F2XX) ||(STM32F4XX) +static void update_ota_cloud_task(void *param) +{ + struct updater_ctx ctx; + char *buf; + int read_bytes, size = 0, i; + uint32_t address, checksum = 0; + update_cfg_cloud_t *cfg = (update_cfg_cloud_t*)param; +#if CONFIG_WRITE_MAC_TO_FLASH + char mac[ETH_ALEN]; +#endif + printf("\n\r[%s] Update task start", __FUNCTION__); + buf = update_malloc(BUF_SIZE); + if(!buf){ + printf("\n\r[%s] Alloc buffer failed", __FUNCTION__); + goto update_ota_exit_1; + } + // Init ctx + if(updater_init_ctx(&ctx, (char*)cfg->repository, (char*)cfg->file_path) != 0) { + printf("\n\r[%s] Cloud ctx init failed", __FUNCTION__); + goto update_ota_exit_1; + } + printf("\n\r[%s] Firmware link: %s, size = %d bytes, checksum = 0x%08x, version = %s\n", __FUNCTION__, + ctx.link, ctx.size, ctx.checksum, ctx.version); + + // Erase config sectors + if(flash_EraseSector(CONFIG_SECTOR) < 0){ + printf("\n\r[%s] Erase sector failed", __FUNCTION__); + goto update_ota_exit; + } +#if CONFIG_WRITE_MAC_TO_FLASH + // Read MAC address + if(flash_Read(FLASH_ADD_STORE_MAC, mac, ETH_ALEN) < 0){ + printf("\n\r[%s] Read MAC error", __FUNCTION__); + goto update_ota_exit; + } +#endif + // Erase update sectors + for(i = UPDATE_SECTOR; i <= FLASH_Sector_11; i += 8){ + if(flash_EraseSector(i) < 0){ + printf("\n\r[%s] Erase sector failed", __FUNCTION__); + goto update_ota_exit; + } + } + // Write update sectors + address = flash_SectorAddress(UPDATE_SECTOR); + printf("\n\r"); + while(ctx.bytes < ctx.size){ + read_bytes = updater_read_bytes(&ctx, (unsigned char*)buf, BUF_SIZE); + if(read_bytes == 0) break; // Read end + if(read_bytes < 0){ + printf("\n\r[%s] Read socket failed", __FUNCTION__); + goto update_ota_exit; + } + if(flash_Wrtie(address + size, buf, read_bytes) < 0){ + printf("\n\r[%s] Write sector failed", __FUNCTION__); + goto update_ota_exit; + } + size += read_bytes; + for(i = 0; i < read_bytes; i ++) + checksum += buf[i]; + printf("\rUpdate file size = %d/%d bytes ", ctx.bytes, ctx.size); + } + printf("\n\r[%s] ctx checksum = %08x, computed checksum = %08x\n", __FUNCTION__, ctx.checksum, checksum); + if(checksum != ctx.checksum){ + printf("\n\r[%s] Checksum error", __FUNCTION__); + goto update_ota_exit; + } +#if CONFIG_WRITE_MAC_TO_FLASH + //Write MAC address + if(!(mac[0]==0xff&&mac[1]==0xff&&mac[2]==0xff&&mac[3]==0xff&&mac[4]==0xff&&mac[5]==0xff)){ + if(flash_Wrtie(FLASH_ADD_STORE_MAC, mac, ETH_ALEN) < 0){ + printf("\n\r[%s] Write MAC failed", __FUNCTION__); + goto update_ota_exit; + } + } +#endif + // Write config sectors + address = flash_SectorAddress(CONFIG_SECTOR); + if( (flash_Wrtie(address, (char*)&size, 4) < 0) || + (flash_Wrtie(address+4, (char*)&checksum, 4) < 0) ){ + printf("\n\r[%s] Write sector failed", __FUNCTION__); + goto update_ota_exit; + } + printf("\n\r[%s] Update OTA success!", __FUNCTION__); + +update_ota_exit: + updater_free_ctx(&ctx); +update_ota_exit_1: + if(buf) + update_free(buf); + if(param) + update_free(param); + TaskOTA = NULL; + printf("\n\r[%s] Update task exit", __FUNCTION__); + vTaskDelete(NULL); + return; +} +#elif defined(STM32f1xx) +static void update_ota_cloud_task(void *param) +{ + struct updater_ctx ctx; + char *buf, flag_a = 0; + int read_bytes, size = 0, i; + uint32_t address, checksum = 0; + update_cfg_cloud_t *cfg = (update_cfg_cloud_t*)param; + uint16_t a = 0; +#if CONFIG_WRITE_MAC_TO_FLASH + char mac[ETH_ALEN]; +#endif + printf("\n\r[%s] Update task start", __FUNCTION__); + buf = update_malloc(BUF_SIZE); + if(!buf){ + printf("\n\r[%s] Alloc buffer failed", __FUNCTION__); + goto update_ota_exit_1; + } + // Init ctx + if(updater_init_ctx(&ctx, (char*)cfg->repository, (char*)cfg->file_path) != 0) { + printf("\n\r[%s] Cloud ctx init failed", __FUNCTION__); + goto update_ota_exit_1; + } + printf("\n\r[%s] Firmware link: %s, size = %d bytes, checksum = 0x%08x, version = %s\n", __FUNCTION__, + ctx.link, ctx.size, ctx.checksum, ctx.version); + + // Erase config sectors + for(i = CONFIG_SECTOR; i < APPLICATION_SECTOR; i += FLASH_PAGE_SIZE){ + if(flash_EraseSector(i) < 0){ + printf("\n\r[%s] Erase sector failed", __FUNCTION__); + goto update_ota_exit; + } + } +#if CONFIG_WRITE_MAC_TO_FLASH + // Read MAC address + if(flash_Read(FLASH_ADD_STORE_MAC, mac, ETH_ALEN) < 0){ + printf("\n\r[%s] Read MAC error", __FUNCTION__); + goto update_ota_exit; + } +#endif + + // Erase update sectors + for(i = UPDATE_SECTOR; i < FLASH_Sector_0 + FLASH_SIZE; i += FLASH_PAGE_SIZE){ + if(flash_EraseSector(i) < 0){ + printf("\n\r[%s] Erase sector failed", __FUNCTION__); + goto update_ota_exit; + } + } + // Write update sectors + address = UPDATE_SECTOR; + printf("\n\r"); + while(ctx.bytes < ctx.size){ + read_bytes = updater_read_bytes(&ctx, (unsigned char*)buf, BUF_SIZE); + if(read_bytes == 0) break; // Read end + if(read_bytes < 0){ + printf("\n\r[%s] Read socket failed", __FUNCTION__); + goto update_ota_exit; + } + if(flag_a == 0){ + if(read_bytes % 2 != 0){ + a = buf[read_bytes - 1]; + flag_a = 1; + if(flash_Wrtie(address + size, buf, read_bytes - 1) < 0){ + printf("\n\r[%s] Write sector failed", __FUNCTION__); + goto update_ota_exit; + } + size += read_bytes - 1; + } + else{ + if(flash_Wrtie(address + size, buf, read_bytes) < 0){ + printf("\n\r[%s] Write sector failed", __FUNCTION__); + goto update_ota_exit; + } + size += read_bytes; + } + } + else{ + a = buf[0]<< 8 |a; + if(flash_Wrtie(address + size, (char*)(&a), 2) < 0){ + printf("\n\r[%s] Write sector failed", __FUNCTION__); + goto update_ota_exit; + } + size += 2; + a = 0; + flag_a = 0; + if((read_bytes - 1) % 2 != 0){ + a = buf[read_bytes - 1]; + flag_a = 1; + if(flash_Wrtie(address + size, buf + 1, read_bytes - 2) < 0){ + printf("\n\r[%s] Write sector failed", __FUNCTION__); + goto update_ota_exit; + } + size += read_bytes - 2; + } + else{ + if(flash_Wrtie(address + size, buf + 1, read_bytes - 1) < 0){ + printf("\n\r[%s] Write sector failed", __FUNCTION__); + goto update_ota_exit; + } + size += read_bytes - 1; + } + } + for(i = 0; i < read_bytes; i ++) + checksum += buf[i]; + printf("\rUpdate file size = %d/%d bytes ", ctx.bytes, ctx.size); + } + if(flag_a){ + if(flash_Wrtie(address + size, (char*)(&a), 2) < 0){ + printf("\n\r[%s] Write sector failed", __FUNCTION__); + goto update_ota_exit; + } + size += 1; + } + printf("\n\r[%s] ctx checksum = %08x, computed checksum = %08x\n", __FUNCTION__, ctx.checksum, checksum); + if(checksum != ctx.checksum){ + printf("\n\r[%s] Checksum error", __FUNCTION__); + goto update_ota_exit; + } +#if CONFIG_WRITE_MAC_TO_FLASH + //Write MAC address + if(!(mac[0]==0xff&&mac[1]==0xff&&mac[2]==0xff&&mac[3]==0xff&&mac[4]==0xff&&mac[5]==0xff)){ + if(flash_Wrtie(FLASH_ADD_STORE_MAC, mac, ETH_ALEN) < 0){ + printf("\n\r[%s] Write MAC failed", __FUNCTION__); + goto update_ota_exit; + } + } +#endif + + // Write config sectors + address = CONFIG_SECTOR; + if( (flash_Wrtie(address, (char*)&size, 4) < 0) || + (flash_Wrtie(address+4, (char*)&checksum, 4) < 0) ){ + printf("\n\r[%s] Write sector failed", __FUNCTION__); + goto update_ota_exit; + } + printf("\n\r[%s] Update OTA success!", __FUNCTION__); + +update_ota_exit: + updater_free_ctx(&ctx); +update_ota_exit_1: + if(buf) + update_free(buf); + if(param) + update_free(param); + TaskOTA = NULL; + printf("\n\r[%s] Update task exit", __FUNCTION__); + vTaskDelete(NULL); + return; +} + +#endif + +//--------------------------------------------------------------------- +int update_ota_cloud(char *repository, char *file_path) +{ + update_cfg_cloud_t *pUpdateCfg; + + if(TaskOTA){ + printf("\n\r[%s] Update task has created.", __FUNCTION__); + return 0; + } + pUpdateCfg = update_malloc(sizeof(update_cfg_cloud_t)); + if(pUpdateCfg == NULL){ + printf("\n\r[%s] Alloc update cfg failed.", __FUNCTION__); + goto exit; + } + if(strlen(repository) > (REPOSITORY_LEN-1)){ + printf("\n\r[%s] Repository length is too long.", __FUNCTION__); + goto exit; + } + if(strlen(file_path) > (FILE_PATH_LEN-1)){ + printf("\n\r[%s] File path length is too long.", __FUNCTION__); + goto exit; + } + strcpy((char*)pUpdateCfg->repository, repository); + strcpy((char*)pUpdateCfg->file_path, file_path); + + TaskOTA = sys_thread_new("OTA_server", update_ota_cloud_task, pUpdateCfg, STACK_SIZE, TASK_PRIORITY); + if(TaskOTA == NULL){ + printf("\n\r[%s] Create update task failed", __FUNCTION__); + goto exit; + } + +exit: + update_free(pUpdateCfg); + return 0; +} +#endif // #if (SERVER_TYPE == SERVER_CLOUD) + +//--------------------------------------------------------------------- +void cmd_update(int argc, char **argv) +{ +// printf("\n\r[%s] Firmware A", __FUNCTION__); +#if (SERVER_TYPE == SERVER_LOCAL) + int port; + if(argc != 3){ + printf("\n\r[%s] Usage: update IP PORT", __FUNCTION__); + return; + } + port = atoi(argv[2]); + update_ota_local(argv[1], port); +#endif +#if (SERVER_TYPE == SERVER_CLOUD) + if(argc != 3){ + printf("\n\r[%s] Usage: update REPOSITORY FILE_PATH", __FUNCTION__); + return; + } + update_ota_cloud(argv[1], argv[2]); +#endif +} + +//--------------------------------------------------------------------- + diff --git a/component/common/utilities/update.h b/component/common/utilities/update.h new file mode 100644 index 0000000..64c965a --- /dev/null +++ b/component/common/utilities/update.h @@ -0,0 +1,10 @@ +#ifndef UPDATE_H +#define UPDATE_H + +//-------------------------------------------------------------------------- +int update_ota_local(char *ip, int port); +int update_ota_cloud(char *repository, char *file_path); +void cmd_update(int argc, char **argv); + +//---------------------------------------------------------------------------- +#endif diff --git a/component/common/utilities/webserver.c b/component/common/utilities/webserver.c new file mode 100644 index 0000000..3f44ab2 --- /dev/null +++ b/component/common/utilities/webserver.c @@ -0,0 +1,1197 @@ +/* + FreeRTOS V6.0.4 - Copyright (C) 2010 Real Time Engineers Ltd. + + *************************************************************************** + * * + * If you are: * + * * + * + New to FreeRTOS, * + * + Wanting to learn FreeRTOS or multitasking in general quickly * + * + Looking for basic training, * + * + Wanting to improve your FreeRTOS skills and productivity * + * * + * then take a look at the FreeRTOS eBook * + * * + * "Using the FreeRTOS Real Time Kernel - a Practical Guide" * + * http://www.FreeRTOS.org/Documentation * + * * + * A pdf reference manual is also available. Both are usually delivered * + * to your inbox within 20 minutes to two hours when purchased between 8am * + * and 8pm GMT (although please allow up to 24 hours in case of * + * exceptional circumstances). Thank you for your support! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation AND MODIFIED BY the FreeRTOS exception. + ***NOTE*** The exception to the GPL is included to allow you to distribute + a combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. You should have received a copy of the GNU General Public + License and the FreeRTOS license exception along with FreeRTOS; if not it + can be viewed here: http://www.freertos.org/a00114.html and also obtained + by writing to Richard Barry, contact details for whom are available on the + FreeRTOS WEB site. + + 1 tab == 4 spaces! + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +/* + Implements a simplistic WEB server. Every time a connection is made and + data is received a dynamic page that shows the current TCP/IP statistics + is generated and returned. The connection is then closed. + + This file was adapted from a FreeRTOS lwIP slip demo supplied by a third + party. +*/ + +/* ------------------------ System includes ------------------------------- */ + + +/* ------------------------ FreeRTOS includes ----------------------------- */ +#include "FreeRTOS.h" +#include "task.h" +#include "semphr.h" + +/* ------------------------ lwIP includes --------------------------------- */ +#include "lwip/api.h" +#include "lwip/tcpip.h" +#include "lwip/memp.h" +#include "lwip/stats.h" +#include "netif/loopif.h" + +/* ------------------------ Project includes ------------------------------ */ +#include +#include "main.h" + +#include "webserver.h" +#include "wlan_intf.h" + + + +#include "cJSON.h" + + + +#define CONFIG_READ_FLASH 1 + + +#ifdef CONFIG_READ_FLASH + +#ifndef CONFIG_PLATFORM_8195A + +#include +#if defined(STM32F2XX) +#include +#elif defined(STM32F4XX) +#include +#elif defined(STM32f1xx) +#include +#endif + +#else +#include "flash_api.h" +#define DATA_SECTOR (0x000FE000) +#define BACKUP_SECTOR (0x00008000) + +#endif +#endif +/* ------------------------ Defines --------------------------------------- */ +/* The size of the buffer in which the dynamic WEB page is created. */ +#define webMAX_PAGE_SIZE ( 2800 ) /*FSL: buffer containing array*/ +#define LOCAL_BUF_SIZE 800 +#define AP_SETTING_ADDR 0x000FE000; +/* Standard GET response. */ +#define webHTTP_OK "HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n" + +/* The port on which we listen. */ +#define webHTTP_PORT ( 80 ) + +/* Delay on close error. */ +#define webSHORT_DELAY ( 10 ) + + +/* Format of the dynamic page that is returned on each connection. */ +#define webHTML_HEAD_START \ +"\ +\ +\ +" +/* +\ +\ +\ +*/ + +#define webHTML_BODY_START \ +"\ +\ +\r\n\r\n
\ +\ +\ +\ +" + +#define webHTML_END \ +"\ +\ +\ +\ +\ +\ +
\ +

Realtek SoftAP Configuration

\ +
\ +
\ +Copyright ?realtek.com
\ +\r\n
" \ +"\r\n" \ +"" + +#define webWaitHTML_START \ +"\ +\ +" +#define webWaitHTML_END \ +"\ +\ +

\ +

SoftAP is now restarting!

\ +

Please wait a moment and reconnect!

\ +

"\ +"\r\n" \ +"" + +#define onChangeSecType \ +"" + +#define onSubmitForm \ +"" + +/* +alert(\"Please enter your password!\");\ +return false;\ +}\ +if(z.value.length < 8)\ +{\ +alert(\"Your password is too short!(8-32)\");\ +return false;\ +}\ +if(z.value.length>32)\ +{\ +alert(\"Your password is too long!(8-32)\");\ +*/ + +#define MAX_SOFTAP_SSID_LEN 32 +#define MAX_PASSWORD_LEN 32 +#define MAX_CHANNEL_NUM 13 + +#if INCLUDE_uxTaskGetStackHighWaterMark + static volatile unsigned portBASE_TYPE uxHighWaterMark_web = 0; +#endif + +/* ------------------------ Prototypes ------------------------------------ */ +static void vProcessConnection( struct netconn *pxNetCon ); + +/*------------------------------------------------------------------------------*/ +/* GLOBALS */ +/*------------------------------------------------------------------------------*/ +rtw_wifi_setting_t wifi_setting = {RTW_MODE_NONE, {0}, 0, RTW_SECURITY_OPEN, {0}}; + +#ifndef WLAN0_NAME + #define WLAN0_NAME "wlan0" +#endif + +#ifndef WLAN1_NAME + #define WLAN1_NAME "wlan1" +#endif + + + +#define STRCMP(a,b) (strcmp(a,b) == 0) + + + +static void LoadWifiSetting() +{ + const char *ifname = WLAN0_NAME; + + if(rltk_wlan_running(WLAN1_IDX)) + {//STA_AP_MODE + ifname = WLAN1_NAME; + } + + wifi_get_setting(ifname, &wifi_setting); + + //printf("\r\nLoadWifiSetting(): wifi_setting.ssid=%s\n", wifi_setting.ssid); + //printf("\r\nLoadWifiSetting(): wifi_setting.channel=%d\n", wifi_setting.channel); + //printf("\r\nLoadWifiSetting(): wifi_setting.security_type=%d\n", wifi_setting.security_type); + //printf("\r\nLoadWifiSetting(): wifi_setting.password=%s\n", wifi_setting.password); +} + +#if CONFIG_READ_FLASH +#ifndef CONFIG_PLATFORM_8195A +void LoadWifiConfig() +{ + rtw_wifi_config_t local_config; + uint32_t address; +#ifdef STM32F10X_XL + address = 0x08080000; //bank2 domain +#else + uint16_t sector_nb = FLASH_Sector_11; + address = flash_SectorAddress(sector_nb); +#endif + printf("\r\nLoadWifiConfig(): Read from FLASH!\n"); + flash_Read(address, (char *)&local_config, sizeof(local_config)); + + printf("\r\nLoadWifiConfig(): local_config.boot_mode=0x%x\n", local_config.boot_mode); + printf("\r\nLoadWifiConfig(): local_config.ssid=%s\n", local_config.ssid); + printf("\r\nLoadWifiConfig(): local_config.channel=%d\n", local_config.channel); + printf("\r\nLoadWifiConfig(): local_config.security_type=%d\n", local_config.security_type); + printf("\r\nLoadWifiConfig(): local_config.password=%s\n", local_config.password); + + if(local_config.boot_mode == 0x77665502) + { + wifi_setting.mode = RTW_MODE_AP; + if(local_config.ssid_len > 32) + local_config.ssid_len = 32; + memcpy(wifi_setting.ssid, local_config.ssid, local_config.ssid_len); + wifi_setting.ssid[local_config.ssid_len] = '\0'; + wifi_setting.channel = local_config.channel; + wifi_setting.security_type = local_config.security_type; + if(local_config.password_len > 32) + local_config.password_len = 32; + memcpy(wifi_setting.password, local_config.password, local_config.password_len); + wifi_setting.password[local_config.password_len] = '\0'; + } + else + { + LoadWifiSetting(); + } +} + +int StoreApInfo() +{ + rtw_wifi_config_t wifi_config; + uint32_t address; +#ifdef STM32F10X_XL + address = 0x08080000; //bank2 domain +#else + uint16_t sector_nb = FLASH_Sector_11; + address = flash_SectorAddress(sector_nb); +#endif + wifi_config.boot_mode = 0x77665502; + memcpy(wifi_config.ssid, wifi_setting.ssid, strlen((char*)wifi_setting.ssid)); + wifi_config.ssid_len = strlen((char*)wifi_setting.ssid); + wifi_config.security_type = wifi_setting.security_type; + memcpy(wifi_config.password, wifi_setting.password, strlen((char*)wifi_setting.password)); + wifi_config.password_len= strlen((char*)wifi_setting.password); + wifi_config.channel = wifi_setting.channel; + + printf("\n\rWritting boot mode 0x77665502 and Wi-Fi setting to flash ..."); +#ifdef STM32F10X_XL + FLASH_ErasePage(address); +#else + flash_EraseSector(sector_nb); +#endif + flash_Wrtie(address, (char *)&wifi_config, sizeof(rtw_wifi_config_t)); + + return 0; +} + + +#else + +void LoadWifiConfig() +{ + + + flash_t flash; + + rtw_wifi_config_t local_config; + uint32_t address; + + address = DATA_SECTOR; + + + //memset(&local_config,0,sizeof(rtw_wifi_config_t)); + printf("\r\nLoadWifiConfig(): Read from FLASH!\n"); + // flash_Read(address, &local_config, sizeof(local_config)); + + flash_stream_read(&flash, address, sizeof(rtw_wifi_config_t),(uint8_t *)(&local_config)); + + + printf("\r\nLoadWifiConfig(): local_config.boot_mode=0x%x\n", local_config.boot_mode); + printf("\r\nLoadWifiConfig(): local_config.ssid=%s\n", local_config.ssid); + printf("\r\nLoadWifiConfig(): local_config.channel=%d\n", local_config.channel); + printf("\r\nLoadWifiConfig(): local_config.security_type=%d\n", local_config.security_type); + printf("\r\nLoadWifiConfig(): local_config.password=%s\n", local_config.password); + + if(local_config.boot_mode == 0x77665502) + { + wifi_setting.mode = RTW_MODE_AP; + if(local_config.ssid_len > 32) + local_config.ssid_len = 32; + memcpy(wifi_setting.ssid, local_config.ssid, local_config.ssid_len); + wifi_setting.ssid[local_config.ssid_len] = '\0'; + wifi_setting.channel = local_config.channel; + if(local_config.security_type == 1) + wifi_setting.security_type = RTW_SECURITY_WPA2_AES_PSK; + else + wifi_setting.security_type = RTW_SECURITY_OPEN; + if(local_config.password_len > 32) + local_config.password_len = 32; + memcpy(wifi_setting.password, local_config.password, local_config.password_len); + wifi_setting.password[local_config.password_len] = '\0'; + } + else + { + LoadWifiSetting(); + } + +} + +int StoreApInfo() +{ + + flash_t flash; + + rtw_wifi_config_t wifi_config; + uint32_t address; + uint32_t data,i = 0; + + + address = DATA_SECTOR; + + wifi_config.boot_mode = 0x77665502; + memcpy(wifi_config.ssid, wifi_setting.ssid, strlen((char*)wifi_setting.ssid)); + wifi_config.ssid_len = strlen((char*)wifi_setting.ssid); + wifi_config.security_type = wifi_setting.security_type; + if(wifi_setting.security_type !=0) + wifi_config.security_type = 1; + else + wifi_config.security_type = 0; + memcpy(wifi_config.password, wifi_setting.password, strlen((char*)wifi_setting.password)); + wifi_config.password_len= strlen((char*)wifi_setting.password); + wifi_config.channel = wifi_setting.channel; + printf("\n\rWritting boot mode 0x77665502 and Wi-Fi setting to flash ..."); + //printf("\n\r &wifi_config = 0x%x",&wifi_config); + + flash_read_word(&flash,address,&data); + + + if(data == ~0x0) + + flash_stream_write(&flash, address,sizeof(rtw_wifi_config_t), (uint8_t *)&wifi_config); + + else{ + //flash_EraseSector(sector_nb); + + + flash_erase_sector(&flash,BACKUP_SECTOR); + for(i = 0; i < 0x1000; i+= 4){ + flash_read_word(&flash, DATA_SECTOR + i, &data); + if(i < sizeof(rtw_wifi_config_t)) + { + memcpy(&data,(char *)(&wifi_config) + i,4); + //printf("\n\r Wifi_config + %d = 0x%x",i,(void *)(&wifi_config + i)); + //printf("\n\r Data = %d",data); + } + flash_write_word(&flash, BACKUP_SECTOR + i,data); + } + flash_read_word(&flash,BACKUP_SECTOR + 68,&data); + //printf("\n\r Base + BACKUP_SECTOR + 68 wifi channel = %d",data); + //erase system data + flash_erase_sector(&flash, DATA_SECTOR); + //write data back to system data + for(i = 0; i < 0x1000; i+= 4){ + flash_read_word(&flash, BACKUP_SECTOR + i, &data); + flash_write_word(&flash, DATA_SECTOR + i,data); + } + //erase backup sector + flash_erase_sector(&flash, BACKUP_SECTOR); + } + + //flash_Wrtie(address, (char *)&wifi_config, sizeof(rtw_wifi_config_t)); + //flash_stream_write(&flash, address,sizeof(rtw_wifi_config_t), (uint8_t *)&wifi_config); + //flash_stream_read(&flash, address, sizeof(rtw_wifi_config_t),data); + //flash_stream_read(&flash, address, sizeof(rtw_wifi_config_t),data); + //printf("\n\r Base + 0x000FF000 +4 wifi config = %s",data[4]); + //printf("\n\r Base + 0x000FF000 +71 wifi channel = %d",data[71]); + + return 0; +} +#endif + + +static void RestartSoftAP() +{ + //printf("\r\nRestartAP: ssid=%s", wifi_setting.ssid); + //printf("\r\nRestartAP: ssid_len=%d", strlen((char*)wifi_setting.ssid)); + //printf("\r\nRestartAP: security_type=%d", wifi_setting.security_type); + //printf("\r\nRestartAP: password=%s", wifi_setting.password); + //printf("\r\nRestartAP: password_len=%d", strlen((char*)wifi_setting.password)); + //printf("\r\nRestartAP: channel=%d\n", wifi_setting.channel); + wifi_restart_ap(wifi_setting.ssid, + wifi_setting.security_type, + wifi_setting.password, + strlen((char*)wifi_setting.ssid), + strlen((char*)wifi_setting.password), + wifi_setting.channel); +} +#endif + + +u32 web_atoi(char* s) +{ + int num=0,flag=0; + int i; + + for(i=0;i<=strlen(s);i++) + { + if(s[i] >= '0' && s[i] <= '9') + num = num * 10 + s[i] -'0'; + else if(s[0] == '-' && i==0) + flag =1; + else + break; + } + + if(flag == 1) + num = num * -1; + + return(num); +} + +static void CreateSsidTableItem(char *pbuf, u8_t *ssid, u8_t ssid_len) +{ + char local_ssid[MAX_SOFTAP_SSID_LEN+1]; + + if(ssid_len > MAX_SOFTAP_SSID_LEN) + ssid_len = MAX_SOFTAP_SSID_LEN; + memcpy(local_ssid, ssid, ssid_len); + local_ssid[ssid_len] = '\0'; + sprintf(pbuf, "" + "" + "SoftAP SSID:
" + "" + "" + "
" + "" + "", + local_ssid); + //printf("\r\nstrlen(SsidTableItem)=%d\n", strlen(pbuf)); +} + +static void CreateSecTypeTableItem(char *pbuf, u32_t sectype) +{ + u8_t flag[2] = {0, 0}; + + if(sectype == RTW_SECURITY_OPEN) + flag[0] = 1; + else if(sectype == RTW_SECURITY_WPA2_AES_PSK) + flag[1] = 1; + else + return; + + sprintf(pbuf, "" + "" + "Security Type:
" + "" + "" + "" + "" + "", + flag[0]?"selected":"", + flag[1]?"selected":""); + //printf("\r\nstrlen(SecTypeTableItem)=%d\n", strlen(pbuf)); +} + +static void CreatePasswdTableItem(char *pbuf, u8_t *password, u8_t passwd_len) +{ + char local_passwd[MAX_PASSWORD_LEN+1]; + + if(passwd_len > MAX_PASSWORD_LEN) + passwd_len = MAX_PASSWORD_LEN; + if(passwd_len > 0) + { + memcpy(local_passwd, password, passwd_len); + local_passwd[passwd_len] = '\0'; + } + sprintf(pbuf, "" + "" + "Password:
" + "" + "" + "
" + "" + "", + passwd_len?local_passwd:""); + //printf("\r\nstrlen(passwordTableItem)=%d\n", strlen(pbuf)); +} + +static void CreateChannelTableItem(char *pbuf, u8_t channel) +{ + u8_t flag[MAX_CHANNEL_NUM+1] = {0}; + + if(channel > MAX_CHANNEL_NUM){ + printf("Channel(%d) is out of range!\n", channel); + channel = 1; + } + flag[channel] = 1; + + sprintf(pbuf, "" + "" + "Channel:
" + "" + "" + "" + "" + "", + flag[1]?"selected":"", + flag[2]?"selected":"", + flag[3]?"selected":"", + flag[4]?"selected":"", + flag[5]?"selected":"", + flag[6]?"selected":"", + flag[7]?"selected":"", + flag[8]?"selected":"", + flag[9]?"selected":"", + flag[10]?"selected":"", + flag[11]?"selected":""); + //printf("\r\nstrlen(ChannelTableItem)=%d\n", strlen(pbuf)); +} + +static void GenerateIndexHtmlPage(portCHAR* cDynamicPage, portCHAR *LocalBuf) +{ + /* Generate the page index.html... + ... First the page header. */ + strcpy( cDynamicPage, webHTML_HEAD_START ); + + /* Add script */ + strcat( cDynamicPage, onChangeSecType ); + strcat( cDynamicPage, onSubmitForm); + + /* Add Body start */ + strcat( cDynamicPage, webHTML_BODY_START ); + + /* Add SSID */ + CreateSsidTableItem(LocalBuf, wifi_setting.ssid, strlen((char*)wifi_setting.ssid)); + strcat( cDynamicPage, LocalBuf ); + + /* Add SECURITY TYPE */ + CreateSecTypeTableItem(LocalBuf, wifi_setting.security_type); + strcat( cDynamicPage, LocalBuf ); + + /* Add PASSWORD */ + CreatePasswdTableItem(LocalBuf, wifi_setting.password, strlen((char*)wifi_setting.password)); + strcat( cDynamicPage, LocalBuf ); + + /* Add CHANNEL */ + CreateChannelTableItem(LocalBuf, wifi_setting.channel); + strcat( cDynamicPage, LocalBuf ); + + /* ... Finally the page footer. */ + strcat( cDynamicPage, webHTML_END ); + //printf("\r\nGenerateIndexHtmlPage(): %s\n", cDynamicPage); + printf("\r\nGenerateIndexHtmlPage Len: %d\n", strlen( cDynamicPage )); +} + +static void GenerateWaitHtmlPage(portCHAR* cDynamicPage) +{ + /* Generate the dynamic page... + ... First the page header. */ + strcpy( cDynamicPage, webWaitHTML_START ); + + /* ... Finally the page footer. */ + strcat( cDynamicPage, webWaitHTML_END); + + //printf("\r\nGenerateWaitHtmlPage(): %s\n", cDynamicPage); + //printf("\r\nGenerateWaitHtmlPage Len: %d\n", strlen( cDynamicPage )); +} + +static u8_t ProcessPostMessage(struct netbuf *pxRxBuffer, portCHAR *LocalBuf) +{ + struct pbuf *p; + portCHAR *pcRxString, *ptr; + unsigned portSHORT usLength; + u8_t bChanged = 0; + rtw_security_t secType; + u8_t channel; + u8_t len = 0; + + pcRxString = LocalBuf; + p = pxRxBuffer->p; + usLength = p->tot_len; + //printf("\r\n !!!!!!!!!POST!p->tot_len =%d p->len=%d\n", p->tot_len, p->len); + while(p) + { + memcpy(pcRxString, p->payload, p->len); + pcRxString += p->len; + p = p->next; + } + pcRxString = LocalBuf; + pcRxString[usLength] = '\0'; + //printf("\r\n usLength=%d pcRxString = %s\n", usLength, pcRxString); + + ptr = (char*)strstr(pcRxString, "Ssid="); + if(ptr) + { + pcRxString = (char*)strstr(ptr, "&"); + *pcRxString++ = '\0'; + ptr += 5; + if(strcmp((char*)wifi_setting.ssid, ptr)) + { + bChanged = 1; + len = strlen(ptr); + if(len > MAX_SOFTAP_SSID_LEN){ + len = MAX_SOFTAP_SSID_LEN; + ptr[len] = '\0'; + } + strcpy((char*)wifi_setting.ssid, ptr); + } + } + + //printf("\r\n wifi_config.ssid = %s\n", wifi_setting.ssid); + ptr = (char*)strstr(pcRxString, "Security+Type="); + if(ptr) + { + pcRxString = (char*)strstr(ptr, "&"); + *pcRxString++ = '\0'; + ptr += 14; + if(!strcmp(ptr, "open")) + secType = RTW_SECURITY_OPEN; + else if(!strcmp(ptr, "wpa2-aes")) + secType = RTW_SECURITY_WPA2_AES_PSK; + else + secType = RTW_SECURITY_OPEN; + if(wifi_setting.security_type != secType) + { + bChanged = 1; + wifi_setting.security_type = secType; + } + } + + //printf("\r\n wifi_config.security_type = %d\n", wifi_setting.security_type); + if(wifi_setting.security_type > RTW_SECURITY_OPEN) + { + ptr = (char*)strstr(pcRxString, "Password="); + if(ptr) + { + pcRxString = (char*)strstr(ptr, "&"); + *pcRxString++ = '\0'; + ptr += 9; + if(strcmp((char*)wifi_setting.password, ptr)) + { + bChanged = 1; + len = strlen(ptr); + if(len > MAX_PASSWORD_LEN){ + len = MAX_PASSWORD_LEN; + ptr[len] = '\0'; + } + strcpy((char*)wifi_setting.password, ptr); + } + } + //printf("\r\n wifi_config.password = %s\n", wifi_setting.password); + } + ptr = (char*)strstr(pcRxString, "Channel="); + if(ptr) + { + ptr += 8; + channel = web_atoi(ptr); + if((channel>MAX_CHANNEL_NUM)||(channel < 1)) + channel = 1; + if(wifi_setting.channel !=channel) + { + bChanged = 1; + wifi_setting.channel = channel; + } + } + //printf("\r\n wifi_config.channel = %d\n", wifi_setting.channel); + + return bChanged; +} + +struct netconn *pxHTTPListener = NULL; +static void vProcessConnection( struct netconn *pxNetCon ) +{ + static portCHAR cDynamicPage[webMAX_PAGE_SIZE]; + struct netbuf *pxRxBuffer; + portCHAR *pcRxString; + unsigned portSHORT usLength; + static portCHAR LocalBuf[LOCAL_BUF_SIZE]; + u8_t bChanged = 0; + int ret_recv = ERR_OK; + int ret_accept = ERR_OK; + + /* Load WiFi Setting*/ + LoadWifiSetting(); + + /* We expect to immediately get data. */ + // Evan mopdified for adapt two version lwip api diff + port_netconn_recv( pxNetCon , pxRxBuffer, ret_recv); + + if( pxRxBuffer != NULL && ret_recv == ERR_OK) + { + /* Where is the data? */ + netbuf_data( pxRxBuffer, ( void * )&pcRxString, &usLength ); + + /* Is this a GET? We don't handle anything else. */ + if( !strncmp( pcRxString, "GET", 3 ) ) + { + //printf("\r\nusLength=%d pcRxString=%s \n", usLength, pcRxString); + pcRxString = cDynamicPage; + + /* Write out the HTTP OK header. */ + netconn_write( pxNetCon, webHTTP_OK, ( u16_t ) strlen( webHTTP_OK ), NETCONN_COPY ); + + /* Generate index.html page. */ + GenerateIndexHtmlPage(cDynamicPage, LocalBuf); + + /* Write out the dynamically generated page. */ + netconn_write( pxNetCon, cDynamicPage, ( u16_t ) strlen( cDynamicPage ), NETCONN_COPY ); + } + else if(!strncmp( pcRxString, "POST", 4 ) ) + { + /* Write out the HTTP OK header. */ + netconn_write( pxNetCon, webHTTP_OK, ( u16_t ) strlen( webHTTP_OK ), NETCONN_COPY ); + bChanged = ProcessPostMessage(pxRxBuffer, LocalBuf); + if(bChanged) + { + GenerateWaitHtmlPage(cDynamicPage); + + /* Write out the generated page. */ + netconn_write( pxNetCon, cDynamicPage, ( u16_t ) strlen( cDynamicPage ), NETCONN_COPY ); + +#if CONFIG_READ_FLASH + StoreApInfo(); +#endif + } + else + { + /* Generate index.html page. */ + GenerateIndexHtmlPage(cDynamicPage, LocalBuf); + + /* Write out the generated page. */ + netconn_write( pxNetCon, cDynamicPage, ( u16_t ) strlen( cDynamicPage ), NETCONN_COPY ); + } + } + netbuf_delete( pxRxBuffer ); + } + netconn_close( pxNetCon ); + + if(bChanged) + { + struct netconn *pxNewConnection; + vTaskDelay(200/portTICK_RATE_MS); + //printf("\r\n%d:before restart ap\n", xTaskGetTickCount()); + RestartSoftAP(); + //printf("\r\n%d:after restart ap\n", xTaskGetTickCount()); + pxHTTPListener->recv_timeout = 1; + // Evan mopdified for adapt two version lwip api diff + port_netconn_accept( pxHTTPListener , pxNewConnection, ret_accept); + if( pxNewConnection != NULL && ret_accept == ERR_OK) + { + //printf("\r\n%d: got a conn\n", xTaskGetTickCount()); + netconn_close( pxNewConnection ); + while( netconn_delete( pxNewConnection ) != ERR_OK ) + { + vTaskDelay( webSHORT_DELAY ); + } + } + //printf("\r\n%d:end\n", xTaskGetTickCount()); + pxHTTPListener->recv_timeout = 0; + } +} + + + + + + +/*************************************************************** +** PROSCEND implement +***************************************************************/ + + +#define HTTP_OK_JSON "HTTP/1.0 200 OK\r\nContent-type: application/json\r\n\r\n" +#define STRNCMP(a,b,c) (strncmp(a,b,c) == 0) + + + + + + +cJSON_Hooks memoryHook; + + + + + + +void rgb_mode_handle_off() { + + Ai_WS2811_setColor(0, 0, 0); + sendLEDs(); + +} + + + + +void rgb_mode_handle_on(int r, int g, int b) { + + Ai_WS2811_setColor(r, g, b); + sendLEDs(); + +} + + + + +static void _handle_post_rgb_json(char *j) { + + extern u16 Blink_ms; + extern u8 Config_r, Config_g, Config_b; + extern u8 IsBlink; + extern u8 IsMeteor; + + cJSON *obj = cJSON_Parse(j); + if (obj) { + cJSON *R = cJSON_GetObjectItem(obj, "R"); + cJSON *G = cJSON_GetObjectItem(obj, "G"); + cJSON *B = cJSON_GetObjectItem(obj, "B"); + + cJSON *Mode = cJSON_GetObjectItem(obj, "Mode"); + cJSON *Speed = cJSON_GetObjectItem(obj, "Speed"); + + printf("R: %d\n", R->valueint); + printf("G: %d\n", G->valueint); + printf("B: %d\n", B->valueint); + + printf("Mode: %s\n", Mode->valuestring); + printf("Speed: %d\n", Speed->valueint); + + Config_r = R->valueint; + Config_g = G->valueint; + Config_b = B->valueint; + + if (Speed->valueint < 10) { + Blink_ms = 10; + } else { + Blink_ms = Speed->valueint; + } + + if (STRCMP(Mode->valuestring, "OFF")) { + printf("rgb_mode_handle_off\n"); + rgb_mode_handle_off(); + } + + if (STRCMP(Mode->valuestring, "ON")) { + printf("rgb_mode_handle_on\n"); + rgb_mode_handle_on(R->valueint, G->valueint, B->valueint); + } + + if (STRCMP(Mode->valuestring, "Blink")) { + printf("rgb_mode_handle_blink\n"); + IsBlink = 1; + } else { + IsBlink = 0; + } + + if (STRCMP(Mode->valuestring, "Meteor")) { + printf("rgb_mode_handle_meteor\n"); + IsMeteor = 1; + } else { + IsMeteor = 0; + } + + + + // wait for implementing + + + + cJSON_Delete(obj); + } +} + + + +void _handle_post_rgb(struct netbuf *netbuf, char *localbuf) { + struct pbuf *p; + portCHAR *pcRxString, *ptr; + unsigned portSHORT usLength; + u8_t bChanged = 0; + rtw_security_t secType; + u8_t channel; + u8_t len = 0; + + pcRxString = localbuf; + p = netbuf->p; + usLength = p->tot_len; + + while (p) { + memcpy(pcRxString, p->payload, p->len); + pcRxString += p->len; + p = p->next; + } + pcRxString = localbuf; + pcRxString[usLength] = '\0'; + + ptr = (char*)strstr(pcRxString, "\r\n\r\n"); + if (ptr) { + ptr += 4; + _handle_post_rgb_json(ptr); + } + +} + + +/* +** set the configuration about the smart lighting +** POST /rgb/ HTTP/1.1 +** +** { + "R" : 0, + "G" : 255, + "B" : 27, + "Speed" : 50, + "Mode" : "ON" + } +** +** HTTP/1.1 200 OK +** +** +*/ +static void _handle_post(struct netconn *netconn, const char *data, struct netbuf *netbuf) { + + static char buf[LOCAL_BUF_SIZE]; + + netconn_write(netconn, HTTP_OK_JSON, strlen(HTTP_OK_JSON), NETCONN_COPY); + if (strstr(data, "/rgb")) { + printf("POST /rgb\n"); + _handle_post_rgb(netbuf, buf); + } else { + printf("POST Unknown\n"); + printf("pcRxString: %s\n", data); + } + +} + + + +void restful_api_handler(struct netconn *netconn) { + struct netbuf *netbuf; + char *data; + u16_t len; + int ret = ERR_OK; + + port_netconn_recv(netconn, netbuf, ret); + + if (netbuf != NULL && ret == ERR_OK) { + netbuf_data(netbuf, (void *)&data, &len); + if (STRNCMP(data, "POST", 4)) _handle_post(netconn, data, netbuf); + netbuf_delete(netbuf); + } + + netconn_close(netconn); +} + + + +static void _cjson_init(void) { + memoryHook.malloc_fn = malloc; + memoryHook.free_fn = free; + cJSON_InitHooks(&memoryHook); +} + + + + + + +/*------------------------------------------------------------*/ +xTaskHandle webs_task = NULL; +xSemaphoreHandle webs_sema = NULL; +u8_t webs_terminate = 0; +void vBasicWEBServer( void *pvParameters ) +{ + struct netconn *pxNewConnection; + //struct ip_addr xIpAddr, xNetMast, xGateway; + extern err_t ethernetif_init( struct netif *netif ); + int ret = ERR_OK; + /* Parameters are not used - suppress compiler error. */ + ( void )pvParameters; + + /* Create a new tcp connection handle */ + pxHTTPListener = netconn_new( NETCONN_TCP ); + netconn_bind( pxHTTPListener, NULL, webHTTP_PORT ); + netconn_listen( pxHTTPListener ); + +#if CONFIG_READ_FLASH + /* Load wifi_config */ + LoadWifiConfig(); + RestartSoftAP(); +#endif + //printf("\r\n-0\n"); + + + + /* init once */ + _cjson_init(); + + + + /* Loop forever */ + for( ;; ) + { + if(webs_terminate) + break; + + //printf("\r\n%d:-1\n", xTaskGetTickCount()); + /* Wait for connection. */ + // Evan mopdified for adapt two version lwip api diff + port_netconn_accept( pxHTTPListener , pxNewConnection, ret); + //printf("\r\n%d:-2\n", xTaskGetTickCount()); + + if( pxNewConnection != NULL && ret == ERR_OK) + { + /* Service connection. */ + + #if 0 + vProcessConnection( pxNewConnection ); + #else // RESTful + restful_api_handler(pxNewConnection); + #endif + + while( netconn_delete( pxNewConnection ) != ERR_OK ) + { + vTaskDelay( webSHORT_DELAY ); + } + } + //printf("\r\n%d:-3\n", xTaskGetTickCount()); + } + //printf("\r\n-4\n"); + if(pxHTTPListener) + { + netconn_close(pxHTTPListener); + netconn_delete(pxHTTPListener); + pxHTTPListener = NULL; + } + + //printf("\r\nExit Web Server Thread!\n"); + xSemaphoreGive(webs_sema); +} + +#define STACKSIZE 512 +void start_web_server() +{ + printf("\r\nWEB:Enter start web server!\n"); + webs_terminate = 0; + if(webs_task == NULL) + { + if(xTaskCreate(vBasicWEBServer, (const char *)"web_server", STACKSIZE, NULL, tskIDLE_PRIORITY + 1, &webs_task) != pdPASS) + printf("\n\rWEB: Create webserver task failed!\n"); + } + if(webs_sema == NULL) + { + webs_sema = xSemaphoreCreateCounting(0xffffffff, 0); //Set max count 0xffffffff + } + //printf("\r\nWEB:Exit start web server!\n"); +} + +void stop_web_server() +{ + //printf("\r\nWEB:Enter stop web server!\n"); + webs_terminate = 1; + if(pxHTTPListener) + netconn_abort(pxHTTPListener); + if(webs_sema) + { + if(xSemaphoreTake(webs_sema, 15 * configTICK_RATE_HZ) != pdTRUE) + { + if(pxHTTPListener) + { + netconn_close(pxHTTPListener); + netconn_delete(pxHTTPListener); + pxHTTPListener = NULL; + } + printf("\r\nWEB: Take webs sema(%p) failed!!!!!!!!!!!\n", webs_sema); + } + vSemaphoreDelete(webs_sema); + webs_sema = NULL; + } + if(webs_task) + { + vTaskDelete(webs_task); + webs_task = NULL; + } + printf("\r\nWEB:Exit stop web server!\n"); +} diff --git a/component/common/utilities/webserver.h b/component/common/utilities/webserver.h new file mode 100644 index 0000000..46b1cce --- /dev/null +++ b/component/common/utilities/webserver.h @@ -0,0 +1,71 @@ +/* + FreeRTOS V6.0.4 - Copyright (C) 2010 Real Time Engineers Ltd. + + *************************************************************************** + * * + * If you are: * + * * + * + New to FreeRTOS, * + * + Wanting to learn FreeRTOS or multitasking in general quickly * + * + Looking for basic training, * + * + Wanting to improve your FreeRTOS skills and productivity * + * * + * then take a look at the FreeRTOS eBook * + * * + * "Using the FreeRTOS Real Time Kernel - a Practical Guide" * + * http://www.FreeRTOS.org/Documentation * + * * + * A pdf reference manual is also available. Both are usually delivered * + * to your inbox within 20 minutes to two hours when purchased between 8am * + * and 8pm GMT (although please allow up to 24 hours in case of * + * exceptional circumstances). Thank you for your support! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation AND MODIFIED BY the FreeRTOS exception. + ***NOTE*** The exception to the GPL is included to allow you to distribute + a combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. You should have received a copy of the GNU General Public + License and the FreeRTOS license exception along with FreeRTOS; if not it + can be viewed here: http://www.freertos.org/a00114.html and also obtained + by writing to Richard Barry, contact details for whom are available on the + FreeRTOS WEB site. + + 1 tab == 4 spaces! + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef BASIC_WEB_SERVER_H +#define BASIC_WEB_SERVER_H +#include +/*------------------------------------------------------------------------------*/ +/* MACROS */ +/*------------------------------------------------------------------------------*/ +#define basicwebWEBSERVER_PRIORITY ( tskIDLE_PRIORITY + 2 ) + +#define lwipBASIC_SERVER_STACK_SIZE 256 + +/*------------------------------------------------------------------------------*/ + +/* The function that implements the WEB server task. */ +extern void start_web_server(void); + +#endif /* + */ + diff --git a/component/os/freertos/cmsis_os.c b/component/os/freertos/cmsis_os.c new file mode 100644 index 0000000..5ceea59 --- /dev/null +++ b/component/os/freertos/cmsis_os.c @@ -0,0 +1,1394 @@ + + +#include "cmsis_os.h" +#include "diag.h" + +#define CMSIS_OS_ERR(fmt, args...) DBG_8195A("\n\r%s: " fmt, __FUNCTION__, ## args) + +extern void *_memset( void *s, int c, SIZE_T n ); +#define os_memset _memset + +#if configSignalManagementSupport // the older FreeRTOS version didn't support Signal Management functions +#if 0 +#define THREAD_SIGNAL_MAP_SIZE 32 +typedef struct thread_signal_map { + uint8_t is_in_use; + osThreadId thread_id; + EventGroupHandle_t signals; +} ThreadSignalEntity; + + +ThreadSignalEntity ThreadSignalMapTable[THREAD_SIGNAL_MAP_SIZE]={0}; +#endif + +typedef struct thread_signal_map { + osThreadId thread_id; + EventGroupHandle_t signals; + void *pnext; +} ThreadSignalRec, *pThreadSignalRec; + +ThreadSignalRec *pThreadSignalMapHead; +ThreadSignalRec *pThreadSignalMapTail; +#endif + +/* Convert from CMSIS type osPriority to FreeRTOS priority number */ +static unsigned portBASE_TYPE makeFreeRtosPriority (osPriority priority) +{ + unsigned portBASE_TYPE fpriority = tskIDLE_PRIORITY; + + if (priority != osPriorityError) { + fpriority += (priority - osPriorityIdle); + } + + return fpriority; +} + + +/* Convert from FreeRTOS priority number to CMSIS type osPriority */ +static osPriority makeCmsisPriority (unsigned portBASE_TYPE fpriority) +{ + osPriority priority = osPriorityError; + + if ((fpriority - tskIDLE_PRIORITY) <= (osPriorityRealtime - osPriorityIdle)) { + priority = (osPriority)((int)osPriorityIdle + (int)(fpriority - tskIDLE_PRIORITY)); + } + + return priority; +} + + +/* Determine whether we are in thread mode or handler mode. */ +static int inHandlerMode (void) +{ + return __get_IPSR() != 0; +} + +#if configSignalManagementSupport // the older FreeRTOS version didn't support Signal Management functions +static void add_thread_signal_map (osThreadId thread_id, EventGroupHandle_t signals) +{ + int dummy; +// uint32_t i; + ThreadSignalRec *prec_entity; + + if (inHandlerMode()) { + dummy = portSET_INTERRUPT_MASK_FROM_ISR(); + } + else { + vPortEnterCritical(); + } + + prec_entity = (ThreadSignalRec*) malloc(sizeof(ThreadSignalRec)); + + if (prec_entity != NULL) { + prec_entity->thread_id = thread_id; + prec_entity->signals = signals; + prec_entity->pnext = NULL; + if (pThreadSignalMapHead == NULL) { + pThreadSignalMapHead = prec_entity; + pThreadSignalMapTail = prec_entity; + } + else { + pThreadSignalMapTail->pnext = prec_entity; + pThreadSignalMapTail = prec_entity; + } + } + else { + CMSIS_OS_ERR("No Free Thread-Signal entity\n"); + } + +#if 0 + for (i=0;i= THREAD_SIGNAL_MAP_SIZE) { + // No free Thread-Signals map entity + CMSIS_OS_ERR("No Free Thread-Signal entity\n"); + } + +#endif + + if (inHandlerMode()) { + portCLEAR_INTERRUPT_MASK_FROM_ISR(dummy); + } + else { + vPortExitCritical(); + } + +} + +static EventGroupHandle_t find_signal_by_thread (osThreadId thread_id) +{ + EventGroupHandle_t signals_hdl=NULL; +// uint32_t i; + int dummy; + ThreadSignalRec *prec_entity; + + if (inHandlerMode()) { + dummy = portSET_INTERRUPT_MASK_FROM_ISR(); + } + else { + vPortEnterCritical(); + } + + prec_entity = pThreadSignalMapHead; + while (prec_entity != NULL) { + if (prec_entity->thread_id == thread_id) { + signals_hdl = prec_entity->signals; + break; + } + else { + prec_entity = prec_entity->pnext; + } + } + +#if 0 + for (i=0;ithread_id == thread_id) { + signals_hdl = prec_entity->signals; + if (prec_entity == pThreadSignalMapHead) { + if (prec_entity->pnext != NULL) { + pThreadSignalMapHead = prec_entity->pnext; + } + else { + pThreadSignalMapHead = NULL; + pThreadSignalMapTail = NULL; + } + } + else if (prec_entity == pThreadSignalMapTail) { + pprev_entity->pnext = NULL; + pThreadSignalMapTail = pprev_entity; + } + else { + pprev_entity->pnext = prec_entity->pnext; + } + free((void *)prec_entity); + break; + } + else { + pprev_entity = prec_entity; + prec_entity = prec_entity->pnext; + } + } + +#if 0 + for (i=0;ipthread, + (const portCHAR *)thread_def->name, + (thread_def->stacksize/4), + argument, + makeFreeRtosPriority(thread_def->tpriority), + &handle); + if (pdPASS == result) { +#if configSignalManagementSupport + EventGroupHandle_t signals; + + signals = xEventGroupCreate(); + if (signals == NULL) { + /* The event group was not created because there was insufficient + FreeRTOS heap available. */ + CMSIS_OS_ERR("Create a EventGroup for a new thread failed\n"); + } + else + { + add_thread_signal_map(handle, signals); + } +#endif + } + else + { + CMSIS_OS_ERR("Create a new thread(%s) failed\r\n", thread_def->name); + } + + return handle; +} + + +/// Return the thread ID of the current running thread. +/// \return thread ID for reference by other functions or NULL in case of error. +/// \note MUST REMAIN UNCHANGED: \b osThreadGetId shall be consistent in every CMSIS-RTOS. +osThreadId osThreadGetId (void) +{ + return xTaskGetCurrentTaskHandle(); +} + + +/// Terminate execution of a thread and remove it from Active Threads. +/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osThreadTerminate shall be consistent in every CMSIS-RTOS. +osStatus osThreadTerminate (osThreadId thread_id) +{ +#if configSignalManagementSupport + EventGroupHandle_t EventHandle; + + EventHandle = remove_thread_signal_map (thread_id); + if (EventHandle) { + vEventGroupDelete (EventHandle); + } +#endif + + vTaskDelete(thread_id); + + return osOK; +} + + +/// Pass control to next thread that is in state \b READY. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osThreadYield shall be consistent in every CMSIS-RTOS. +osStatus osThreadYield (void) +{ + taskYIELD(); + + return osOK; +} + + +/// Change priority of an active thread. +/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId. +/// \param[in] priority new priority value for the thread function. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osThreadSetPriority shall be consistent in every CMSIS-RTOS. +osStatus osThreadSetPriority (osThreadId thread_id, osPriority priority) +{ + vTaskPrioritySet(thread_id, makeFreeRtosPriority(priority)); + + return osOK; +} + + +/// Get current priority of an active thread. +/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId. +/// \return current priority value of the thread function. +/// \note MUST REMAIN UNCHANGED: \b osThreadGetPriority shall be consistent in every CMSIS-RTOS. +osPriority osThreadGetPriority (osThreadId thread_id) +{ + return makeCmsisPriority(uxTaskPriorityGet(thread_id)); +} + + + +// ==== Generic Wait Functions ==== + +/// Wait for Timeout (Time Delay) +/// \param[in] millisec time delay value +/// \return status code that indicates the execution status of the function. +osStatus osDelay (uint32_t millisec) +{ +#if INCLUDE_vTaskDelay + portTickType ticks = (millisec * configTICK_RATE_HZ) / 1000; + + vTaskDelay(ticks ? ticks : 1); /* Minimum delay = 1 tick */ + + return osOK; +#else + (void) millisec; + + return osErrorResource; +#endif +} + + +#if (defined (osFeature_Wait) && (osFeature_Wait != 0)) // Generic Wait available + +/// Wait for Signal, Message, Mail, or Timeout +/// \param[in] millisec timeout value or 0 in case of no time-out +/// \return event that contains signal, message, or mail information or error code. +/// \note MUST REMAIN UNCHANGED: \b osWait shall be consistent in every CMSIS-RTOS. +osEvent osWait (uint32_t millisec); + +#endif // Generic Wait available + + +// ==== Timer Management Functions ==== + +static void _osTimerCallbackFreeRTOS (xTimerHandle handle) +{ + osTimerDef_t *timer = (osTimerDef_t *)(pvTimerGetTimerID(handle)); + + timer->ptimer(timer->custom->argument); +} + + +/// Create a timer. +/// \param[in] timer_def timer object referenced with \ref osTimer. +/// \param[in] type osTimerOnce for one-shot or osTimerPeriodic for periodic behavior. +/// \param[in] argument argument to the timer call back function. +/// \return timer ID for reference by other functions or NULL in case of error. +/// \note MUST REMAIN UNCHANGED: \b osTimerCreate shall be consistent in every CMSIS-RTOS. +osTimerId osTimerCreate (const osTimerDef_t *timer_def, os_timer_type type, void *argument) +{ + timer_def->custom->argument = argument; + + return xTimerCreate((const portCHAR *)"", + 1, //Set later when timer is started + (type == osTimerPeriodic) ? pdTRUE : pdFALSE, + (void *)timer_def, + _osTimerCallbackFreeRTOS + ); +} + + + +/// Start or restart a timer. +/// \param[in] timer_id timer ID obtained by \ref osTimerCreate. +/// \param[in] millisec time delay value of the timer. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osTimerStart shall be consistent in every CMSIS-RTOS. +osStatus osTimerStart (osTimerId timer_id, uint32_t millisec) +{ + portBASE_TYPE taskWoken = pdFALSE; + osStatus result = osOK; + portTickType ticks = millisec / portTICK_RATE_MS; + if (ticks == 0) { + ticks = 1; + } + + if (inHandlerMode()) { + if (xTimerChangePeriodFromISR(timer_id, ticks, &taskWoken) == pdPASS) { + xTimerStartFromISR(timer_id, &taskWoken); + portEND_SWITCHING_ISR(taskWoken); + } + } + else { + //TODO: add timeout support + if (xTimerChangePeriod(timer_id, ticks, 0) != pdPASS) { + result = osErrorOS; + } + else { + if (xTimerStart(timer_id, 0) != pdPASS) { + result = osErrorOS; + } + } + } + + return result; +} + + + +/// Stop the timer. +/// \param[in] timer_id timer ID obtained by \ref osTimerCreate. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osTimerStop shall be consistent in every CMSIS-RTOS. +osStatus osTimerStop (osTimerId timer_id) +{ + portBASE_TYPE taskWoken = pdFALSE; + osStatus result = osOK; + + if (inHandlerMode()) { + xTimerStopFromISR(timer_id, &taskWoken); + portEND_SWITCHING_ISR(taskWoken); + } + else { + if (xTimerStop(timer_id, 0) != pdPASS) { //TODO: add timeout support + result = osErrorOS; + } + } + + return result; +} + + +/// Delete a timer that was created by \ref osTimerCreate. +/// \param[in] timer_id timer ID obtained by \ref osTimerCreate. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osTimerDelete shall be consistent in every CMSIS-RTOS. +osStatus osTimerDelete (osTimerId timer_id) +{ + osStatus result = osOK; + + /* try to delete the soft timer and wait max RTL_TIMER_API_MAX_BLOCK_TICKS + to send the delete command to the timer command queue */ + if (xTimerDelete(timer_id, portMAX_DELAY ) != pdPASS) { + result = osErrorOS; + } + + return result; +} + +// ==== Signal Management ==== +#if configSignalManagementSupport +/// Set the specified Signal Flags of an active thread. +/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId. +/// \param[in] signals specifies the signal flags of the thread that should be set. +/// \return previous signal flags of the specified thread or 0x80000000 in case of incorrect parameters. +/// \note MUST REMAIN UNCHANGED: \b osSignalSet shall be consistent in every CMSIS-RTOS. +int32_t osSignalSet (osThreadId thread_id, int32_t signals) +{ + EventGroupHandle_t event_handle; + portBASE_TYPE taskWoken = pdFALSE; + portBASE_TYPE xResult; + EventBits_t uxBits_ret=0x80000000; +#ifdef CHECK_VALUE_OF_EVENT_GROUP + EventBits_t uxBits; +#endif + + if (signals & (0xFFFFFFFF << osFeature_Signals)) { + return 0x80000000; + } + + event_handle = find_signal_by_thread(thread_id); + if (event_handle) { + if (inHandlerMode()) { + uxBits_ret = xEventGroupGetBitsFromISR(event_handle); + xResult = xEventGroupSetBitsFromISR( + event_handle, /* The event group being updated. */ + signals, /* The bits being set. */ + &taskWoken ); + if( xResult != pdFAIL ) + { + portYIELD_FROM_ISR(taskWoken); + } + } + else { + uxBits_ret = xEventGroupGetBits(event_handle); +#ifdef CHECK_VALUE_OF_EVENT_GROUP + uxBits = +#endif + xEventGroupSetBits( + event_handle, /* The event group being updated. */ + signals );/* The bits being set. */ + } + } + + return uxBits_ret; +} + +/// Clear the specified Signal Flags of an active thread. +/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId. +/// \param[in] signals specifies the signal flags of the thread that shall be cleared. +/// \return previous signal flags of the specified thread or 0x80000000 in case of incorrect parameters. +/// \note MUST REMAIN UNCHANGED: \b osSignalClear shall be consistent in every CMSIS-RTOS. +int32_t osSignalClear (osThreadId thread_id, int32_t signals) +{ + EventGroupHandle_t event_handle; + //portBASE_TYPE taskWoken = pdFALSE; + EventBits_t uxBits_ret=0x80000000; +#ifdef CHECK_VALUE_OF_EVENT_GROUP + EventBits_t uxBits; +#endif + + if (signals & (0xFFFFFFFF << osFeature_Signals)) { + return 0x80000000; + } + + event_handle = find_signal_by_thread(thread_id); + if (event_handle) { + if (inHandlerMode()) { + uxBits_ret = xEventGroupGetBitsFromISR(event_handle); +#ifdef CHECK_VALUE_OF_EVENT_GROUP + uxBits = +#endif + xEventGroupClearBitsFromISR( + event_handle, /* The event group being updated. */ + signals);/* The bits being cleared. */ + } + else { + uxBits_ret = xEventGroupGetBits(event_handle); +#ifdef CHECK_VALUE_OF_EVENT_GROUP + uxBits = +#endif + xEventGroupClearBits( + event_handle, /* The event group being updated. */ + signals);/* The bits being cleared. */ + } + } + + return uxBits_ret; +} + + +/// Wait for one or more Signal Flags to become signaled for the current \b RUNNING thread. +/// \param[in] signals wait until all specified signal flags set or 0 for any single signal flag. +/// \param[in] millisec timeout value or 0 in case of no time-out. +/// \return event flag information or error code. +/// \note MUST REMAIN UNCHANGED: \b osSignalWait shall be consistent in every CMSIS-RTOS. +osEvent osSignalWait (int32_t signals, uint32_t millisec) +{ + TaskHandle_t thread_id; + EventGroupHandle_t event_handle; + EventBits_t uxBits=0x80000000; + osEvent ret; + uint32_t wait_ticks; + + if (signals & (0xFFFFFFFF << osFeature_Signals)) { + ret.status = osErrorValue; + ret.value.signals = 0; + return ret; + } + + thread_id = xTaskGetCurrentTaskHandle(); + event_handle = find_signal_by_thread(thread_id); + if (event_handle) { + if (signals == 0) { + // if signals is 0, then wait any signal + signals = (1 << osFeature_Signals) - 1; + } + + wait_ticks = millisec_to_ticks(millisec); + uxBits = xEventGroupWaitBits( + event_handle, /* The event group being tested. */ + signals, /* The bits within the event group to wait for. */ + pdTRUE, /* the signals should be cleared before returning. */ + pdFALSE, /* Don't wait for both bits, either bit will do. */ + wait_ticks );/* Wait for either bit to be set. */ + if (uxBits == 0) { + ret.status = millisec ? osEventTimeout : osOK; + ret.value.signals = 0; + } + else { + ret.status = osEventSignal; + ret.value.signals = uxBits; + } + } + + return ret; +} +#else +// The older FreeRTOS version didn't support Signal Management functions + +int32_t osSignalSet (osThreadId thread_id, int32_t signals) +{ + return 0; +} + +int32_t osSignalClear (osThreadId thread_id, int32_t signals) +{ + return 0; +} + +osEvent osSignalWait (int32_t signals, uint32_t millisec) +{ + osEvent ret; + + ret.status = osErrorOS; + return ret; +} + +#endif // end of "else of #if configSignalManagementSupport + +// ==== Mutex Management ==== + + +/// Create and Initialize a Mutex object +/// \param[in] mutex_def mutex definition referenced with \ref osMutex. +/// \return mutex ID for reference by other functions or NULL in case of error. +/// \note MUST REMAIN UNCHANGED: \b osMutexCreate shall be consistent in every CMSIS-RTOS. +osMutexId osMutexCreate (const osMutexDef_t *mutex_def) +{ + (void) mutex_def; + + return xSemaphoreCreateMutex(); +} + + + +/// Wait until a Mutex becomes available +/// \param[in] mutex_id mutex ID obtained by \ref osMutexCreate. +/// \param[in] millisec timeout value or 0 in case of no time-out. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osMutexWait shall be consistent in every CMSIS-RTOS. +osStatus osMutexWait (osMutexId mutex_id, uint32_t millisec) +{ + portTickType ticks; + + + if (mutex_id == NULL) { + return osErrorParameter; + } + + if (inHandlerMode()) { + return osErrorISR; + } + + ticks = millisec_to_ticks(millisec); + + if (xSemaphoreTake(mutex_id, ticks) != pdTRUE) { + return osErrorOS; + } + + return osOK; +} + + + +/// Release a Mutex that was obtained by \ref osMutexWait +/// \param[in] mutex_id mutex ID obtained by \ref osMutexCreate. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osMutexRelease shall be consistent in every CMSIS-RTOS. +osStatus osMutexRelease (osMutexId mutex_id) +{ + osStatus result = osOK; + portBASE_TYPE taskWoken = pdFALSE; + + + if (inHandlerMode()) { + if (xSemaphoreGiveFromISR(mutex_id, &taskWoken) != pdTRUE) { + result = osErrorOS; + } + portEND_SWITCHING_ISR(taskWoken); + } + else { + if (xSemaphoreGive(mutex_id) != pdTRUE) { + result = osErrorOS; + } + } + + return result; +} + +/// Delete a Mutex that was created by \ref osMutexCreate. +/// \param[in] mutex_id mutex ID obtained by \ref osMutexCreate. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osMutexDelete shall be consistent in every CMSIS-RTOS. +osStatus osMutexDelete (osMutexId mutex_id) +{ + if (!mutex_id) { + return osErrorValue; + } + + vSemaphoreDelete(mutex_id); + return osOK; +} + + +// ==== Semaphore Management Functions ==== + +#if (defined (osFeature_Semaphore) && (osFeature_Semaphore != 0)) // Semaphore available + +/// Create and Initialize a Semaphore object used for managing resources +/// \param[in] semaphore_def semaphore definition referenced with \ref osSemaphore. +/// \param[in] count number of available resources. +/// \return semaphore ID for reference by other functions or NULL in case of error. +/// \note MUST REMAIN UNCHANGED: \b osSemaphoreCreate shall be consistent in every CMSIS-RTOS. +osSemaphoreId osSemaphoreCreate (const osSemaphoreDef_t *semaphore_def, int32_t count) +{ + (void) semaphore_def; + osSemaphoreId sema; + + if (count == 1) { + vSemaphoreCreateBinary(sema); + return sema; + } + + return xSemaphoreCreateCounting(count, count); +} + + + +/// Wait until a Semaphore token becomes available +/// \param[in] semaphore_id semaphore object referenced with \ref osSemaphore. +/// \param[in] millisec timeout value or 0 in case of no time-out. +/// \return number of available tokens, or -1 in case of incorrect parameters. +/// \note MUST REMAIN UNCHANGED: \b osSemaphoreWait shall be consistent in every CMSIS-RTOS. +int32_t osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec) +{ + portTickType ticks; + + + if (semaphore_id == NULL) { + return osErrorParameter; + } + + ticks = millisec_to_ticks(millisec); + + if (inHandlerMode()) { + return osErrorISR; + } + + if (xSemaphoreTake(semaphore_id, ticks) != pdTRUE) { + return osErrorOS; + } + + return osOK; +} + + +/// Release a Semaphore token +/// \param[in] semaphore_id semaphore object referenced with \ref osSemaphore. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osSemaphoreRelease shall be consistent in every CMSIS-RTOS. +osStatus osSemaphoreRelease (osSemaphoreId semaphore_id) +{ + osStatus result = osOK; + portBASE_TYPE taskWoken = pdFALSE; + + + if (inHandlerMode()) { + if (xSemaphoreGiveFromISR(semaphore_id, &taskWoken) != pdTRUE) { + result = osErrorOS; + } + portEND_SWITCHING_ISR(taskWoken); + } + else { + if (xSemaphoreGive(semaphore_id) != pdTRUE) { + result = osErrorOS; + } + } + + return result; +} + + +/// Delete a Semaphore that was created by \ref osSemaphoreCreate. +/// \param[in] semaphore_id semaphore object referenced with \ref osSemaphoreCreate. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osSemaphoreDelete shall be consistent in every CMSIS-RTOS. +osStatus osSemaphoreDelete (osSemaphoreId semaphore_id) +{ + if (!semaphore_id) { + return osErrorValue; + } + + vSemaphoreDelete(semaphore_id); + return osOK; +} + + +#endif // Semaphore available + +// ==== Memory Pool Management Functions ==== + +#if (defined (osFeature_Pool) && (osFeature_Pool != 0)) // Memory Pool Management available + +#if 0 +/// \brief Define a Memory Pool. +/// \param name name of the memory pool. +/// \param no maximum number of objects (elements) in the memory pool. +/// \param type data type of a single object (element). +/// \note CAN BE CHANGED: The parameter to \b osPoolDef shall be consistent but the +/// macro body is implementation specific in every CMSIS-RTOS. +#if defined (osObjectsExternal) // object is external +#define osPoolDef(name, no, type) \ +extern osPoolDef_t os_pool_def_##name; +#else // define the object +#define osPoolDef(name, no, type) \ +osPoolDef_t os_pool_def_##name = \ +{ (no), sizeof(type), NULL }; +#endif +#endif + +//TODO +//This is a primitive and inefficient wrapper around the existing FreeRTOS memory management. +//A better implementation will have to modify heap_x.c! + + +typedef struct os_pool_cb { + void *pool; + uint8_t *markers; + uint32_t pool_sz; + uint32_t item_sz; + uint32_t currentIndex; +} os_pool_cb_t; + +#if 0 +/// \brief Access a Memory Pool definition. +/// \param name name of the memory pool +/// \note CAN BE CHANGED: The parameter to \b osPool shall be consistent but the +/// macro body is implementation specific in every CMSIS-RTOS. +#define osPool(name) \ +&os_pool_def_##name +#endif + +/// Create and Initialize a memory pool +/// \param[in] pool_def memory pool definition referenced with \ref osPool. +/// \return memory pool ID for reference by other functions or NULL in case of error. +/// \note MUST REMAIN UNCHANGED: \b osPoolCreate shall be consistent in every CMSIS-RTOS. +osPoolId osPoolCreate (const osPoolDef_t *pool_def) +{ + osPoolId thePool; + int itemSize = 4 * ((pool_def->item_sz + 3) / 4); + uint32_t i; + + /* First have to allocate memory for the pool control block. */ + thePool = pvPortMalloc(sizeof(os_pool_cb_t)); + if (thePool) { + thePool->pool_sz = pool_def->pool_sz; + thePool->item_sz = itemSize; + thePool->currentIndex = 0; + + /* Memory for markers */ + thePool->markers = pvPortMalloc(pool_def->pool_sz); + if (thePool->markers) { + /* Now allocate the pool itself. */ + thePool->pool = pvPortMalloc(pool_def->pool_sz * itemSize); + + if (thePool->pool) { + for (i = 0; i < pool_def->pool_sz; i++) { + thePool->markers[i] = 0; + } + } + else { + vPortFree(thePool->markers); + vPortFree(thePool); + thePool = NULL; + } + } + else { + vPortFree(thePool); + thePool = NULL; + } + } + + return thePool; +} + + +/// Allocate a memory block from a memory pool +/// \param[in] pool_id memory pool ID obtain referenced with \ref osPoolCreate. +/// \return address of the allocated memory block or NULL in case of no memory available. +/// \note MUST REMAIN UNCHANGED: \b osPoolAlloc shall be consistent in every CMSIS-RTOS. +void *osPoolAlloc (osPoolId pool_id) +{ + int dummy; + void *p = NULL; + uint32_t i; + uint32_t index; + + if (inHandlerMode()) { + dummy = portSET_INTERRUPT_MASK_FROM_ISR(); + } + else { + vPortEnterCritical(); + } + + for (i = 0; i < pool_id->pool_sz; i++) { + index = pool_id->currentIndex + i; + if (index >= pool_id->pool_sz) { + index = 0; + } + + if (pool_id->markers[index] == 0) { + pool_id->markers[index] = 1; + p = (void *)((uint32_t)(pool_id->pool) + (index * pool_id->item_sz)); + pool_id->currentIndex = index; + break; + } + } + + if (inHandlerMode()) { + portCLEAR_INTERRUPT_MASK_FROM_ISR(dummy); + } + else { + vPortExitCritical(); + } + + return p; +} + + +/// Allocate a memory block from a memory pool and set memory block to zero +/// \param[in] pool_id memory pool ID obtain referenced with \ref osPoolCreate. +/// \return address of the allocated memory block or NULL in case of no memory available. +/// \note MUST REMAIN UNCHANGED: \b osPoolCAlloc shall be consistent in every CMSIS-RTOS. +void *osPoolCAlloc (osPoolId pool_id) +{ + void *p = osPoolAlloc(pool_id); + + os_memset(p, 0, pool_id->item_sz); + + return p; +} + + +/// Return an allocated memory block back to a specific memory pool +/// \param[in] pool_id memory pool ID obtain referenced with \ref osPoolCreate. +/// \param[in] block address of the allocated memory block that is returned to the memory pool. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osPoolFree shall be consistent in every CMSIS-RTOS. +osStatus osPoolFree (osPoolId pool_id, void *block) +{ + int dummy; + uint32_t index; + + if (pool_id == NULL) { + return osErrorParameter; + } + + if (block == NULL) { + return osErrorParameter; + } + + if (block < pool_id->pool) { + return osErrorParameter; + } + + index = (uint32_t)block - (uint32_t)(pool_id->pool); + if (index % pool_id->item_sz) { + return osErrorParameter; + } + index = index / pool_id->item_sz; + if (index >= pool_id->pool_sz) { + return osErrorParameter; + } + + if (inHandlerMode()) { + dummy = portSET_INTERRUPT_MASK_FROM_ISR(); + } + else { + vPortEnterCritical(); + } + + pool_id->markers[index] = 0; + + if (inHandlerMode()) { + portCLEAR_INTERRUPT_MASK_FROM_ISR(dummy); + } + else { + vPortExitCritical(); + } + + return osOK; +} + + +#endif // Memory Pool Management available + + +// ==== Message Queue Management Functions ==== + +#if (defined (osFeature_MessageQ) && (osFeature_MessageQ != 0)) // Message Queues available + +/// Create and Initialize a Message Queue. +/// \param[in] queue_def queue definition referenced with \ref osMessageQ. +/// \param[in] thread_id thread ID (obtained by \ref osThreadCreate or \ref osThreadGetId) or NULL. +/// \return message queue ID for reference by other functions or NULL in case of error. +/// \note MUST REMAIN UNCHANGED: \b osMessageCreate shall be consistent in every CMSIS-RTOS. +osMessageQId osMessageCreate (const osMessageQDef_t *queue_def, osThreadId thread_id) +{ + (void) thread_id; + + return xQueueCreate(queue_def->queue_sz, queue_def->item_sz); +} + + +/// Put a Message to a Queue. +/// \param[in] queue_id message queue ID obtained with \ref osMessageCreate. +/// \param[in] info message information. +/// \param[in] millisec timeout value or 0 in case of no time-out. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osMessagePut shall be consistent in every CMSIS-RTOS. +osStatus osMessagePut (osMessageQId queue_id, uint32_t info, uint32_t millisec) +{ + portBASE_TYPE taskWoken = pdFALSE; + portTickType ticks; + + if (inHandlerMode()) { + if (xQueueSendFromISR(queue_id, (const void *)info, &taskWoken) != pdTRUE) { + return osErrorOS; + } + portEND_SWITCHING_ISR(taskWoken); + } + else { + ticks = millisec_to_ticks(millisec); + + if (xQueueSend(queue_id, (const void *)info, ticks) != pdTRUE) { + return osErrorOS; + } + } + + return osOK; +} + + + +/// Get a Message or Wait for a Message from a Queue. +/// \param[in] queue_id message queue ID obtained with \ref osMessageCreate. +/// \param[in] millisec timeout value or 0 in case of no time-out. +/// \return event information that includes status code. +/// \note MUST REMAIN UNCHANGED: \b osMessageGet shall be consistent in every CMSIS-RTOS. +osEvent osMessageGet (osMessageQId queue_id, uint32_t millisec) +{ + portBASE_TYPE taskWoken = pdFALSE; + portTickType ticks; + osEvent retEvent; + + retEvent.def.message_id = queue_id; + if (inHandlerMode()) { + if (xQueueReceiveFromISR(queue_id, (void *)retEvent.value.p, &taskWoken) != pdTRUE) { + retEvent.status = osErrorOS; + return retEvent; + } + portEND_SWITCHING_ISR(taskWoken); + } + else { + ticks = millisec_to_ticks(millisec); + + if (xQueueReceive(queue_id, (void *)retEvent.value.p, ticks) != pdTRUE) { + retEvent.status = osErrorOS; + return retEvent; + } + } + + retEvent.status = osOK; + + return retEvent; +} + +#endif // Message Queues available + + +// ==== Mail Queue Management Functions ==== + +#if (defined (osFeature_MailQ) && (osFeature_MailQ != 0)) // Mail Queues available + + +typedef struct os_mailQ_cb { + osMailQDef_t *queue_def; + xQueueHandle handle; + osPoolId pool; +} os_mailQ_cb_t; + + +/// Create and Initialize mail queue +/// \param[in] queue_def reference to the mail queue definition obtain with \ref osMailQ +/// \param[in] thread_id thread ID (obtained by \ref osThreadCreate or \ref osThreadGetId) or NULL. +/// \return mail queue ID for reference by other functions or NULL in case of error. +/// \note MUST REMAIN UNCHANGED: \b osMailCreate shall be consistent in every CMSIS-RTOS. +osMailQId osMailCreate (const osMailQDef_t *queue_def, osThreadId thread_id) +{ + (void) thread_id; + + osPoolDef_t pool_def = {queue_def->queue_sz, queue_def->item_sz}; + + + /* Create a mail queue control block */ + *(queue_def->cb) = pvPortMalloc(sizeof(struct os_mailQ_cb)); + if (*(queue_def->cb) == NULL) { + return NULL; + } + (*(queue_def->cb))->queue_def = (osMailQDef_t *)queue_def; + + /* Create a queue in FreeRTOS */ + (*(queue_def->cb))->handle = xQueueCreate(queue_def->queue_sz, sizeof(void *)); + if ((*(queue_def->cb))->handle == NULL) { + vPortFree(*(queue_def->cb)); + return NULL; + } + + /* Create a mail pool */ + (*(queue_def->cb))->pool = osPoolCreate(&pool_def); + if ((*(queue_def->cb))->pool == NULL) { + vQueueDelete((*(queue_def->cb))->handle); + vPortFree(*(queue_def->cb)); + return NULL; + } + + return *(queue_def->cb); +} + + + +/// Allocate a memory block from a mail +/// \param[in] queue_id mail queue ID obtained with \ref osMailCreate. +/// \param[in] millisec timeout value or 0 in case of no time-out +/// \return pointer to memory block that can be filled with mail or NULL in case error. +/// \note MUST REMAIN UNCHANGED: \b osMailAlloc shall be consistent in every CMSIS-RTOS. +void *osMailAlloc (osMailQId queue_id, uint32_t millisec) +{ + (void) millisec; + void *p; + uint32_t retried=0; + + + if (queue_id == NULL) { + return NULL; + } + + do { + p = osPoolAlloc(queue_id->pool); + if (NULL == p) { + // sleep a while and then try again + if (millisec == osWaitForever) { + osDelay(2); + } + else { + if (!retried) { + osDelay(millisec); + retried = 1; + } + else { + break; + } + } + } + } while (NULL == p); + + + return p; +} + + + +/// Allocate a memory block from a mail and set memory block to zero +/// \param[in] queue_id mail queue ID obtained with \ref osMailCreate. +/// \param[in] millisec timeout value or 0 in case of no time-out +/// \return pointer to memory block that can shall filled with mail or NULL in case error. +/// \note MUST REMAIN UNCHANGED: \b osMailCAlloc shall be consistent in every CMSIS-RTOS. +void *osMailCAlloc (osMailQId queue_id, uint32_t millisec) +{ +// uint32_t i; + void *p = osMailAlloc(queue_id, millisec); + + if (p) { + os_memset(p, 0, queue_id->queue_def->item_sz); + } + + return p; +} + + + +/// Put a mail to a queue +/// \param[in] queue_id mail queue ID obtained with \ref osMailCreate. +/// \param[in] mail memory block previously allocated with \ref osMailAlloc or \ref osMailCAlloc. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osMailPut shall be consistent in every CMSIS-RTOS. +osStatus osMailPut (osMailQId queue_id, void *mail) +{ + portBASE_TYPE taskWoken; + portTickType ticks=1000/portTICK_RATE_MS; // No timeout is defined for this function, so we just wait 1 sec + + + if (queue_id == NULL) { + return osErrorParameter; + } + + taskWoken = pdFALSE; + + if (inHandlerMode()) { + if (xQueueSendFromISR(queue_id->handle, &mail, &taskWoken) != pdTRUE) { + return osErrorOS; + } + portEND_SWITCHING_ISR(taskWoken); + } + else { + if (xQueueSend(queue_id->handle, &mail, ticks) != pdTRUE) { //TODO where to get timeout value? + return osErrorOS; + } + } + + return osOK; +} + + + +/// Get a mail from a queue +/// \param[in] queue_id mail queue ID obtained with \ref osMailCreate. +/// \param[in] millisec timeout value or 0 in case of no time-out +/// \return event that contains mail information or error code. +/// \note MUST REMAIN UNCHANGED: \b osMailGet shall be consistent in every CMSIS-RTOS. +osEvent osMailGet (osMailQId queue_id, uint32_t millisec) +{ + portBASE_TYPE taskWoken; + portTickType ticks; + osEvent event; + + event.def.mail_id = queue_id; + + if (queue_id == NULL) { + event.status = osErrorParameter; + return event; + } + + taskWoken = pdFALSE; + + ticks = millisec_to_ticks(millisec); + + if (inHandlerMode()) { + if (xQueueReceiveFromISR(queue_id->handle, &event.value.p, &taskWoken) == pdTRUE) { + /* We have mail */ + event.status = osEventMail; + } + else { + event.status = osOK; + } + portEND_SWITCHING_ISR(taskWoken); + } + else { + if (xQueueReceive(queue_id->handle, &event.value.p, ticks) == pdTRUE) { + /* We have mail */ + event.status = osEventMail; + } + else { + event.status = (ticks == 0) ? osOK : osEventTimeout; + } + } + + return event; +} + + + +/// Free a memory block from a mail +/// \param[in] queue_id mail queue ID obtained with \ref osMailCreate. +/// \param[in] mail pointer to the memory block that was obtained with \ref osMailGet. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osMailFree shall be consistent in every CMSIS-RTOS. +osStatus osMailFree (osMailQId queue_id, void *mail) +{ + if (queue_id == NULL) { + return osErrorParameter; + } + + osPoolFree(queue_id->pool, mail); + + return osOK; +} + + +void *calloc_freertos(size_t nelements, size_t elementSize) +{ + void *pbuf; + uint32_t size; + + size = nelements*elementSize; + pbuf = pvPortMalloc(size); + os_memset(pbuf, 0, size); + + return pbuf; +} +#endif // Mail Queues available + + diff --git a/component/os/freertos/cmsis_os.h b/component/os/freertos/cmsis_os.h new file mode 100644 index 0000000..11e8112 --- /dev/null +++ b/component/os/freertos/cmsis_os.h @@ -0,0 +1,816 @@ +/* ---------------------------------------------------------------------- + * $Date: 5. February 2013 + * $Revision: V1.02 + * + * Project: CMSIS-RTOS API + * Title: cmsis_os.h template header file + * + * Version 0.02 + * Initial Proposal Phase + * Version 0.03 + * osKernelStart added, optional feature: main started as thread + * osSemaphores have standard behavior + * osTimerCreate does not start the timer, added osTimerStart + * osThreadPass is renamed to osThreadYield + * Version 1.01 + * Support for C++ interface + * - const attribute removed from the osXxxxDef_t typedef's + * - const attribute added to the osXxxxDef macros + * Added: osTimerDelete, osMutexDelete, osSemaphoreDelete + * Added: osKernelInitialize + * Version 1.02 + * Control functions for short timeouts in microsecond resolution: + * Added: osKernelSysTick, osKernelSysTickFrequency, osKernelSysTickMicroSec + * Removed: osSignalGet + *---------------------------------------------------------------------------- + * + * Copyright (c) 2013 ARM LIMITED + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - 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. + * - Neither the name of ARM 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 HOLDERS 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 COPYRIGHT HOLDERS AND 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. + *---------------------------------------------------------------------------*/ + +#include "FreeRTOS.h" +#include "task.h" +#include "timers.h" +#include "queue.h" +#include "semphr.h" + + +#define FREERTOS_VERSION 0x00080001 // bits[31:16] main version, bits[15:0] sub-version + +#if FREERTOS_VERSION >= 0x00080000 +#define configSignalManagementSupport 1 +#else +#define configSignalManagementSupport 0 +#endif + +#if configSignalManagementSupport +#include "event_groups.h" +#endif + +/** +\page cmsis_os_h Header File Template: cmsis_os.h + +The file \b cmsis_os.h is a template header file for a CMSIS-RTOS compliant Real-Time Operating System (RTOS). +Each RTOS that is compliant with CMSIS-RTOS shall provide a specific \b cmsis_os.h header file that represents +its implementation. + +The file cmsis_os.h contains: + - CMSIS-RTOS API function definitions + - struct definitions for parameters and return types + - status and priority values used by CMSIS-RTOS API functions + - macros for defining threads and other kernel objects + + +Name conventions and header file modifications + +All definitions are prefixed with \b os to give an unique name space for CMSIS-RTOS functions. +Definitions that are prefixed \b os_ are not used in the application code but local to this header file. +All definitions and functions that belong to a module are grouped and have a common prefix, i.e. \b osThread. + +Definitions that are marked with CAN BE CHANGED can be adapted towards the needs of the actual CMSIS-RTOS implementation. +These definitions can be specific to the underlying RTOS kernel. + +Definitions that are marked with MUST REMAIN UNCHANGED cannot be altered. Otherwise the CMSIS-RTOS implementation is no longer +compliant to the standard. Note that some functions are optional and need not to be provided by every CMSIS-RTOS implementation. + + +Function calls from interrupt service routines + +The following CMSIS-RTOS functions can be called from threads and interrupt service routines (ISR): + - \ref osSignalSet + - \ref osSemaphoreRelease + - \ref osPoolAlloc, \ref osPoolCAlloc, \ref osPoolFree + - \ref osMessagePut, \ref osMessageGet + - \ref osMailAlloc, \ref osMailCAlloc, \ref osMailGet, \ref osMailPut, \ref osMailFree + +Functions that cannot be called from an ISR are verifying the interrupt status and return in case that they are called +from an ISR context the status code \b osErrorISR. In some implementations this condition might be caught using the HARD FAULT vector. + +Some CMSIS-RTOS implementations support CMSIS-RTOS function calls from multiple ISR at the same time. +If this is impossible, the CMSIS-RTOS rejects calls by nested ISR functions with the status code \b osErrorISRRecursive. + + +Define and reference object definitions + +With \#define osObjectsExternal objects are defined as external symbols. This allows to create a consistent header file +that is used throughout a project as shown below: + +Header File +\code +#include // CMSIS RTOS header file + +// Thread definition +extern void thread_sample (void const *argument); // function prototype +osThreadDef (thread_sample, osPriorityBelowNormal, 1, 100); + +// Pool definition +osPoolDef(MyPool, 10, long); +\endcode + + +This header file defines all objects when included in a C/C++ source file. When \#define osObjectsExternal is +present before the header file, the objects are defined as external symbols. A single consistent header file can therefore be +used throughout the whole project. + +Example +\code +#include "osObjects.h" // Definition of the CMSIS-RTOS objects +\endcode + +\code +#define osObjectExternal // Objects will be defined as external symbols +#include "osObjects.h" // Reference to the CMSIS-RTOS objects +\endcode + +*/ + +#ifndef _CMSIS_OS_H +#define _CMSIS_OS_H + +/// \note MUST REMAIN UNCHANGED: \b osCMSIS identifies the CMSIS-RTOS API version. +#define osCMSIS 0x10002 ///< API version (main [31:16] .sub [15:0]) + +/// \note CAN BE CHANGED: \b osCMSIS_KERNEL identifies the underlying RTOS kernel and version number. +#define osCMSIS_KERNEL 0x10000 ///< RTOS identification and version (main [31:16] .sub [15:0]) + +/// \note MUST REMAIN UNCHANGED: \b osKernelSystemId shall be consistent in every CMSIS-RTOS. +#define osKernelSystemId "KERNEL V1.00" ///< RTOS identification string + +/// \note MUST REMAIN UNCHANGED: \b osFeature_xxx shall be consistent in every CMSIS-RTOS. +#define osFeature_MainThread 1 ///< main thread 1=main can be thread, 0=not available +#define osFeature_Pool 1 ///< Memory Pools: 1=available, 0=not available +#define osFeature_MailQ 1 ///< Mail Queues: 1=available, 0=not available +#define osFeature_MessageQ 1 ///< Message Queues: 1=available, 0=not available +#define osFeature_Signals 8 ///< maximum number of Signal Flags available per thread +#define osFeature_Semaphore 30 ///< maximum count for \ref osSemaphoreCreate function +#define osFeature_Wait 1 ///< osWait function: 1=available, 0=not available +#define osFeature_SysTick 1 ///< osKernelSysTick functions: 1=available, 0=not available + +//#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + +// ==== Enumeration, structures, defines ==== + +/// Priority used for thread control. +/// \note MUST REMAIN UNCHANGED: \b osPriority shall be consistent in every CMSIS-RTOS. +typedef enum { + osPriorityIdle = -3, ///< priority: idle (lowest) + osPriorityLow = -2, ///< priority: low + osPriorityBelowNormal = -1, ///< priority: below normal + osPriorityNormal = 0, ///< priority: normal (default) + osPriorityAboveNormal = +1, ///< priority: above normal + osPriorityHigh = +2, ///< priority: high + osPriorityRealtime = +3, ///< priority: realtime (highest) + osPriorityError = 0x84 ///< system cannot determine priority or thread has illegal priority +} osPriority; + +/// Timeout value. +/// \note MUST REMAIN UNCHANGED: \b osWaitForever shall be consistent in every CMSIS-RTOS. +#define osWaitForever 0xFFFFFFFF ///< wait forever timeout value + +/// Status code values returned by CMSIS-RTOS functions. +/// \note MUST REMAIN UNCHANGED: \b osStatus shall be consistent in every CMSIS-RTOS. +typedef enum { + osOK = 0, ///< function completed; no error or event occurred. + osEventSignal = 0x08, ///< function completed; signal event occurred. + osEventMessage = 0x10, ///< function completed; message event occurred. + osEventMail = 0x20, ///< function completed; mail event occurred. + osEventTimeout = 0x40, ///< function completed; timeout occurred. + osErrorParameter = 0x80, ///< parameter error: a mandatory parameter was missing or specified an incorrect object. + osErrorResource = 0x81, ///< resource not available: a specified resource was not available. + osErrorTimeoutResource = 0xC1, ///< resource not available within given time: a specified resource was not available within the timeout period. + osErrorISR = 0x82, ///< not allowed in ISR context: the function cannot be called from interrupt service routines. + osErrorISRRecursive = 0x83, ///< function called multiple times from ISR with same object. + osErrorPriority = 0x84, ///< system cannot determine priority or thread has illegal priority. + osErrorNoMemory = 0x85, ///< system is out of memory: it was impossible to allocate or reserve memory for the operation. + osErrorValue = 0x86, ///< value of a parameter is out of range. + osErrorOS = 0xFF, ///< unspecified RTOS error: run-time error but no other error message fits. + os_status_reserved = 0x7FFFFFFF ///< prevent from enum down-size compiler optimization. +} osStatus; + + +/// Timer type value for the timer definition. +/// \note MUST REMAIN UNCHANGED: \b os_timer_type shall be consistent in every CMSIS-RTOS. +typedef enum { + osTimerOnce = 0, ///< one-shot timer + osTimerPeriodic = 1 ///< repeating timer +} os_timer_type; + +/// Entry point of a thread. +/// \note MUST REMAIN UNCHANGED: \b os_pthread shall be consistent in every CMSIS-RTOS. +typedef void (*os_pthread) (void const *argument); + +/// Entry point of a timer call back function. +/// \note MUST REMAIN UNCHANGED: \b os_ptimer shall be consistent in every CMSIS-RTOS. +typedef void (*os_ptimer) (void const *argument); + +// >>> the following data type definitions may shall adapted towards a specific RTOS + +/// Thread ID identifies the thread (pointer to a thread control block). +/// \note CAN BE CHANGED: \b os_thread_cb is implementation specific in every CMSIS-RTOS. +typedef xTaskHandle osThreadId; + +/// Timer ID identifies the timer (pointer to a timer control block). +/// \note CAN BE CHANGED: \b os_timer_cb is implementation specific in every CMSIS-RTOS. +typedef xTimerHandle osTimerId; + +/// Mutex ID identifies the mutex (pointer to a mutex control block). +/// \note CAN BE CHANGED: \b os_mutex_cb is implementation specific in every CMSIS-RTOS. +typedef xSemaphoreHandle osMutexId; + +/// Semaphore ID identifies the semaphore (pointer to a semaphore control block). +/// \note CAN BE CHANGED: \b os_semaphore_cb is implementation specific in every CMSIS-RTOS. +typedef xSemaphoreHandle osSemaphoreId; + +/// Pool ID identifies the memory pool (pointer to a memory pool control block). +/// \note CAN BE CHANGED: \b os_pool_cb is implementation specific in every CMSIS-RTOS. +typedef struct os_pool_cb *osPoolId; + +/// Message ID identifies the message queue (pointer to a message queue control block). +/// \note CAN BE CHANGED: \b os_messageQ_cb is implementation specific in every CMSIS-RTOS. +typedef xQueueHandle osMessageQId; + +/// Mail ID identifies the mail queue (pointer to a mail queue control block). +/// \note CAN BE CHANGED: \b os_mailQ_cb is implementation specific in every CMSIS-RTOS. +typedef struct os_mailQ_cb *osMailQId; + + +/// Thread Definition structure contains startup information of a thread. +/// \note CAN BE CHANGED: \b os_thread_def is implementation specific in every CMSIS-RTOS. +typedef struct os_thread_def { + os_pthread pthread; ///< start address of thread function + osPriority tpriority; ///< initial thread priority + uint32_t instances; ///< maximum number of instances of that thread function + uint32_t stacksize; ///< stack size requirements in bytes; 0 is default stack size + char * name; +} osThreadDef_t; + +/// Timer Definition structure contains timer parameters. +/// \note CAN BE CHANGED: \b os_timer_def is implementation specific in every CMSIS-RTOS. +struct os_timer_custom { + void *argument; +}; + +typedef struct os_timer_def { + os_ptimer ptimer; ///< start address of a timer function + struct os_timer_custom *custom; +} osTimerDef_t; + +/// Mutex Definition structure contains setup information for a mutex. +/// \note CAN BE CHANGED: \b os_mutex_def is implementation specific in every CMSIS-RTOS. +typedef struct os_mutex_def { + uint32_t dummy; ///< dummy value. +} osMutexDef_t; + +/// Semaphore Definition structure contains setup information for a semaphore. +/// \note CAN BE CHANGED: \b os_semaphore_def is implementation specific in every CMSIS-RTOS. +typedef struct os_semaphore_def { + uint32_t dummy; ///< dummy value. +} osSemaphoreDef_t; + +/// Definition structure for memory block allocation +/// \note CAN BE CHANGED: \b os_pool_def is implementation specific in every CMSIS-RTOS. +typedef struct os_pool_def { + uint32_t pool_sz; ///< number of items (elements) in the pool + uint32_t item_sz; ///< size of an item + void *pool; ///< pointer to memory for pool +} osPoolDef_t; + +/// Definition structure for message queue. +/// \note CAN BE CHANGED: \b os_messageQ_def is implementation specific in every CMSIS-RTOS. +typedef struct os_messageQ_def { + uint32_t queue_sz; ///< number of elements in the queue + uint32_t item_sz; ///< size of an item + void *pool; ///< memory array for messages +} osMessageQDef_t; + +/// Definition structure for mail queue +/// \note CAN BE CHANGED: \b os_mailQ_def is implementation specific in every CMSIS-RTOS. +typedef struct os_mailQ_def { + uint32_t queue_sz; ///< number of elements in the queue + uint32_t item_sz; ///< size of an item + struct os_mailQ_cb **cb; +} osMailQDef_t; + +/// Event structure contains detailed information about an event. +/// \note MUST REMAIN UNCHANGED: \b os_event shall be consistent in every CMSIS-RTOS. +/// However the struct may be extended at the end. +typedef struct { + osStatus status; ///< status code: event or error information + union { + uint32_t v; ///< message as 32-bit value + void *p; ///< message or mail as void pointer + int32_t signals; ///< signal flags + } value; ///< event value + union { + osMailQId mail_id; ///< mail id obtained by \ref osMailCreate + osMessageQId message_id; ///< message id obtained by \ref osMessageCreate + } def; ///< event definition +} osEvent; + + +// ==== Kernel Control Functions ==== + +/// Initialize the RTOS Kernel for creating objects. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osKernelInitialize shall be consistent in every CMSIS-RTOS. +osStatus osKernelInitialize (void); + +/// Start the RTOS Kernel. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osKernelStart shall be consistent in every CMSIS-RTOS. +osStatus osKernelStart (void); + +/// Check if the RTOS kernel is already started. +/// \note MUST REMAIN UNCHANGED: \b osKernelRunning shall be consistent in every CMSIS-RTOS. +/// \return 0 RTOS is not started, 1 RTOS is started. +int32_t osKernelRunning(void); + +#if (defined (osFeature_SysTick) && (osFeature_SysTick != 0)) // System Timer available + +/// Get the RTOS kernel system timer counter +/// \note MUST REMAIN UNCHANGED: \b osKernelSysTick shall be consistent in every CMSIS-RTOS. +/// \return RTOS kernel system timer as 32-bit value +uint32_t osKernelSysTick (void); + +/// The RTOS kernel system timer frequency in Hz +/// \note Reflects the system timer setting and is typically defined in a configuration file. +#define osKernelSysTickFrequency configTICK_RATE_HZ + +/// Convert a microseconds value to a RTOS kernel system timer value. +/// \param microsec time value in microseconds. +/// \return time value normalized to the \ref osKernelSysTickFrequency +#define osKernelSysTickMicroSec(microsec) (((uint64_t)microsec * (osKernelSysTickFrequency)) / 1000000) + +#endif // System Timer available + +// ==== Thread Management ==== + +/// Create a Thread Definition with function, priority, and stack requirements. +/// \param name name of the thread function. +/// \param priority initial priority of the thread function. +/// \param instances number of possible thread instances. +/// \param stacksz stack size (in bytes) requirements for the thread function. +/// \note CAN BE CHANGED: The parameters to \b osThreadDef shall be consistent but the +/// macro body is implementation specific in every CMSIS-RTOS. +#if defined (osObjectsExternal) // object is external +#define osThreadDef(name, priority, instances, stacksz) \ +extern const osThreadDef_t os_thread_def_##name +#else // define the object +#define osThreadDef(name, priority, instances, stacksz) \ +const osThreadDef_t os_thread_def_##name = \ +{ (name), (priority), (instances), (stacksz), #name } +#endif + +/// Access a Thread definition. +/// \param name name of the thread definition object. +/// \note CAN BE CHANGED: The parameter to \b osThread shall be consistent but the +/// macro body is implementation specific in every CMSIS-RTOS. +#define osThread(name) \ +&os_thread_def_##name + +/// Create a thread and add it to Active Threads and set it to state READY. +/// \param[in] thread_def thread definition referenced with \ref osThread. +/// \param[in] argument pointer that is passed to the thread function as start argument. +/// \return thread ID for reference by other functions or NULL in case of error. +/// \note MUST REMAIN UNCHANGED: \b osThreadCreate shall be consistent in every CMSIS-RTOS. +osThreadId osThreadCreate (const osThreadDef_t *thread_def, void *argument); + +/// Return the thread ID of the current running thread. +/// \return thread ID for reference by other functions or NULL in case of error. +/// \note MUST REMAIN UNCHANGED: \b osThreadGetId shall be consistent in every CMSIS-RTOS. +osThreadId osThreadGetId (void); + +/// Terminate execution of a thread and remove it from Active Threads. +/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osThreadTerminate shall be consistent in every CMSIS-RTOS. +osStatus osThreadTerminate (osThreadId thread_id); + +/// Pass control to next thread that is in state \b READY. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osThreadYield shall be consistent in every CMSIS-RTOS. +osStatus osThreadYield (void); + +/// Change priority of an active thread. +/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId. +/// \param[in] priority new priority value for the thread function. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osThreadSetPriority shall be consistent in every CMSIS-RTOS. +osStatus osThreadSetPriority (osThreadId thread_id, osPriority priority); + +/// Get current priority of an active thread. +/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId. +/// \return current priority value of the thread function. +/// \note MUST REMAIN UNCHANGED: \b osThreadGetPriority shall be consistent in every CMSIS-RTOS. +osPriority osThreadGetPriority (osThreadId thread_id); + + +// ==== Generic Wait Functions ==== + +/// Wait for Timeout (Time Delay). +/// \param[in] millisec time delay value +/// \return status code that indicates the execution status of the function. +osStatus osDelay (uint32_t millisec); + +#if (defined (osFeature_Wait) && (osFeature_Wait != 0)) // Generic Wait available + +/// Wait for Signal, Message, Mail, or Timeout. +/// \param[in] millisec timeout value or 0 in case of no time-out +/// \return event that contains signal, message, or mail information or error code. +/// \note MUST REMAIN UNCHANGED: \b osWait shall be consistent in every CMSIS-RTOS. +osEvent osWait (uint32_t millisec); + +#endif // Generic Wait available + + +// ==== Timer Management Functions ==== +/// Define a Timer object. +/// \param name name of the timer object. +/// \param function name of the timer call back function. +/// \note CAN BE CHANGED: The parameter to \b osTimerDef shall be consistent but the +/// macro body is implementation specific in every CMSIS-RTOS. +#if defined (osObjectsExternal) // object is external +#define osTimerDef(name, function) \ +extern const osTimerDef_t os_timer_def_##name; \ +extern struct os_timer_custom os_timer_custome_##name +#else // define the object +#define osTimerDef(name, function) \ +struct os_timer_custom os_timer_custom_##name; \ +const osTimerDef_t os_timer_def_##name = \ +{ (function), (&os_timer_custom_##name) } +#endif + +/// Access a Timer definition. +/// \param name name of the timer object. +/// \note CAN BE CHANGED: The parameter to \b osTimer shall be consistent but the +/// macro body is implementation specific in every CMSIS-RTOS. +#define osTimer(name) \ +&os_timer_def_##name + +/// Create a timer. +/// \param[in] timer_def timer object referenced with \ref osTimer. +/// \param[in] type osTimerOnce for one-shot or osTimerPeriodic for periodic behavior. +/// \param[in] argument argument to the timer call back function. +/// \return timer ID for reference by other functions or NULL in case of error. +/// \note MUST REMAIN UNCHANGED: \b osTimerCreate shall be consistent in every CMSIS-RTOS. +osTimerId osTimerCreate (const osTimerDef_t *timer_def, os_timer_type type, void *argument); + +/// Start or restart a timer. +/// \param[in] timer_id timer ID obtained by \ref osTimerCreate. +/// \param[in] millisec time delay value of the timer. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osTimerStart shall be consistent in every CMSIS-RTOS. +osStatus osTimerStart (osTimerId timer_id, uint32_t millisec); + +/// Stop the timer. +/// \param[in] timer_id timer ID obtained by \ref osTimerCreate. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osTimerStop shall be consistent in every CMSIS-RTOS. +osStatus osTimerStop (osTimerId timer_id); + +/// Delete a timer that was created by \ref osTimerCreate. +/// \param[in] timer_id timer ID obtained by \ref osTimerCreate. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osTimerDelete shall be consistent in every CMSIS-RTOS. +osStatus osTimerDelete (osTimerId timer_id); + + +// ==== Signal Management ==== + +/// Set the specified Signal Flags of an active thread. +/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId. +/// \param[in] signals specifies the signal flags of the thread that should be set. +/// \return previous signal flags of the specified thread or 0x80000000 in case of incorrect parameters. +/// \note MUST REMAIN UNCHANGED: \b osSignalSet shall be consistent in every CMSIS-RTOS. +int32_t osSignalSet (osThreadId thread_id, int32_t signals); + +/// Clear the specified Signal Flags of an active thread. +/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId. +/// \param[in] signals specifies the signal flags of the thread that shall be cleared. +/// \return previous signal flags of the specified thread or 0x80000000 in case of incorrect parameters. +/// \note MUST REMAIN UNCHANGED: \b osSignalClear shall be consistent in every CMSIS-RTOS. +int32_t osSignalClear (osThreadId thread_id, int32_t signals); + +/// Wait for one or more Signal Flags to become signaled for the current \b RUNNING thread. +/// \param[in] signals wait until all specified signal flags set or 0 for any single signal flag. +/// \param[in] millisec timeout value or 0 in case of no time-out. +/// \return event flag information or error code. +/// \note MUST REMAIN UNCHANGED: \b osSignalWait shall be consistent in every CMSIS-RTOS. +osEvent osSignalWait (int32_t signals, uint32_t millisec); + + +// ==== Mutex Management ==== + +/// Define a Mutex. +/// \param name name of the mutex object. +/// \note CAN BE CHANGED: The parameter to \b osMutexDef shall be consistent but the +/// macro body is implementation specific in every CMSIS-RTOS. +#if defined (osObjectsExternal) // object is external +#define osMutexDef(name) \ +extern const osMutexDef_t os_mutex_def_##name +#else // define the object +#define osMutexDef(name) \ +const osMutexDef_t os_mutex_def_##name = { 0 } +#endif + +/// Access a Mutex definition. +/// \param name name of the mutex object. +/// \note CAN BE CHANGED: The parameter to \b osMutex shall be consistent but the +/// macro body is implementation specific in every CMSIS-RTOS. +#define osMutex(name) \ +&os_mutex_def_##name + +/// Create and Initialize a Mutex object. +/// \param[in] mutex_def mutex definition referenced with \ref osMutex. +/// \return mutex ID for reference by other functions or NULL in case of error. +/// \note MUST REMAIN UNCHANGED: \b osMutexCreate shall be consistent in every CMSIS-RTOS. +osMutexId osMutexCreate (const osMutexDef_t *mutex_def); + +/// Wait until a Mutex becomes available. +/// \param[in] mutex_id mutex ID obtained by \ref osMutexCreate. +/// \param[in] millisec timeout value or 0 in case of no time-out. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osMutexWait shall be consistent in every CMSIS-RTOS. +osStatus osMutexWait (osMutexId mutex_id, uint32_t millisec); + +/// Release a Mutex that was obtained by \ref osMutexWait. +/// \param[in] mutex_id mutex ID obtained by \ref osMutexCreate. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osMutexRelease shall be consistent in every CMSIS-RTOS. +osStatus osMutexRelease (osMutexId mutex_id); + +/// Delete a Mutex that was created by \ref osMutexCreate. +/// \param[in] mutex_id mutex ID obtained by \ref osMutexCreate. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osMutexDelete shall be consistent in every CMSIS-RTOS. +osStatus osMutexDelete (osMutexId mutex_id); + + +// ==== Semaphore Management Functions ==== + +#if (defined (osFeature_Semaphore) && (osFeature_Semaphore != 0)) // Semaphore available + +/// Define a Semaphore object. +/// \param name name of the semaphore object. +/// \note CAN BE CHANGED: The parameter to \b osSemaphoreDef shall be consistent but the +/// macro body is implementation specific in every CMSIS-RTOS. +#if defined (osObjectsExternal) // object is external +#define osSemaphoreDef(name) \ +extern const osSemaphoreDef_t os_semaphore_def_##name +#else // define the object +#define osSemaphoreDef(name) \ +const osSemaphoreDef_t os_semaphore_def_##name = { 0 } +#endif + +/// Access a Semaphore definition. +/// \param name name of the semaphore object. +/// \note CAN BE CHANGED: The parameter to \b osSemaphore shall be consistent but the +/// macro body is implementation specific in every CMSIS-RTOS. +#define osSemaphore(name) \ +&os_semaphore_def_##name + +/// Create and Initialize a Semaphore object used for managing resources. +/// \param[in] semaphore_def semaphore definition referenced with \ref osSemaphore. +/// \param[in] count number of available resources. +/// \return semaphore ID for reference by other functions or NULL in case of error. +/// \note MUST REMAIN UNCHANGED: \b osSemaphoreCreate shall be consistent in every CMSIS-RTOS. +osSemaphoreId osSemaphoreCreate (const osSemaphoreDef_t *semaphore_def, int32_t count); + +/// Wait until a Semaphore token becomes available. +/// \param[in] semaphore_id semaphore object referenced with \ref osSemaphoreCreate. +/// \param[in] millisec timeout value or 0 in case of no time-out. +/// \return number of available tokens, or -1 in case of incorrect parameters. +/// \note MUST REMAIN UNCHANGED: \b osSemaphoreWait shall be consistent in every CMSIS-RTOS. +int32_t osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec); + +/// Release a Semaphore token. +/// \param[in] semaphore_id semaphore object referenced with \ref osSemaphoreCreate. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osSemaphoreRelease shall be consistent in every CMSIS-RTOS. +osStatus osSemaphoreRelease (osSemaphoreId semaphore_id); + +/// Delete a Semaphore that was created by \ref osSemaphoreCreate. +/// \param[in] semaphore_id semaphore object referenced with \ref osSemaphoreCreate. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osSemaphoreDelete shall be consistent in every CMSIS-RTOS. +osStatus osSemaphoreDelete (osSemaphoreId semaphore_id); + +#endif // Semaphore available + + +// ==== Memory Pool Management Functions ==== + +#if (defined (osFeature_Pool) && (osFeature_Pool != 0)) // Memory Pool Management available + +/// \brief Define a Memory Pool. +/// \param name name of the memory pool. +/// \param no maximum number of blocks (objects) in the memory pool. +/// \param type data type of a single block (object). +/// \note CAN BE CHANGED: The parameter to \b osPoolDef shall be consistent but the +/// macro body is implementation specific in every CMSIS-RTOS. +#if defined (osObjectsExternal) // object is external +#define osPoolDef(name, no, type) \ +extern const osPoolDef_t os_pool_def_##name +#else // define the object +#define osPoolDef(name, no, type) \ +const osPoolDef_t os_pool_def_##name = \ +{ (no), sizeof(type), NULL } +#endif + +/// \brief Access a Memory Pool definition. +/// \param name name of the memory pool +/// \note CAN BE CHANGED: The parameter to \b osPool shall be consistent but the +/// macro body is implementation specific in every CMSIS-RTOS. +#define osPool(name) \ +&os_pool_def_##name + +/// Create and Initialize a memory pool. +/// \param[in] pool_def memory pool definition referenced with \ref osPool. +/// \return memory pool ID for reference by other functions or NULL in case of error. +/// \note MUST REMAIN UNCHANGED: \b osPoolCreate shall be consistent in every CMSIS-RTOS. +osPoolId osPoolCreate (const osPoolDef_t *pool_def); + +/// Allocate a memory block from a memory pool. +/// \param[in] pool_id memory pool ID obtain referenced with \ref osPoolCreate. +/// \return address of the allocated memory block or NULL in case of no memory available. +/// \note MUST REMAIN UNCHANGED: \b osPoolAlloc shall be consistent in every CMSIS-RTOS. +void *osPoolAlloc (osPoolId pool_id); + +/// Allocate a memory block from a memory pool and set memory block to zero. +/// \param[in] pool_id memory pool ID obtain referenced with \ref osPoolCreate. +/// \return address of the allocated memory block or NULL in case of no memory available. +/// \note MUST REMAIN UNCHANGED: \b osPoolCAlloc shall be consistent in every CMSIS-RTOS. +void *osPoolCAlloc (osPoolId pool_id); + +/// Return an allocated memory block back to a specific memory pool. +/// \param[in] pool_id memory pool ID obtain referenced with \ref osPoolCreate. +/// \param[in] block address of the allocated memory block that is returned to the memory pool. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osPoolFree shall be consistent in every CMSIS-RTOS. +osStatus osPoolFree (osPoolId pool_id, void *block); + +#endif // Memory Pool Management available + + +// ==== Message Queue Management Functions ==== + +#if (defined (osFeature_MessageQ) && (osFeature_MessageQ != 0)) // Message Queues available + +/// \brief Create a Message Queue Definition. +/// \param name name of the queue. +/// \param queue_sz maximum number of messages in the queue. +/// \param type data type of a single message element (for debugger). +/// \note CAN BE CHANGED: The parameter to \b osMessageQDef shall be consistent but the +/// macro body is implementation specific in every CMSIS-RTOS. +#if defined (osObjectsExternal) // object is external +#define osMessageQDef(name, queue_sz, type) \ +extern const osMessageQDef_t os_messageQ_def_##name +#else // define the object +#define osMessageQDef(name, queue_sz, type) \ +const osMessageQDef_t os_messageQ_def_##name = \ +{ (queue_sz), sizeof (type) } +#endif + +/// \brief Access a Message Queue Definition. +/// \param name name of the queue +/// \note CAN BE CHANGED: The parameter to \b osMessageQ shall be consistent but the +/// macro body is implementation specific in every CMSIS-RTOS. +#define osMessageQ(name) \ +&os_messageQ_def_##name + +/// Create and Initialize a Message Queue. +/// \param[in] queue_def queue definition referenced with \ref osMessageQ. +/// \param[in] thread_id thread ID (obtained by \ref osThreadCreate or \ref osThreadGetId) or NULL. +/// \return message queue ID for reference by other functions or NULL in case of error. +/// \note MUST REMAIN UNCHANGED: \b osMessageCreate shall be consistent in every CMSIS-RTOS. +osMessageQId osMessageCreate (const osMessageQDef_t *queue_def, osThreadId thread_id); + +/// Put a Message to a Queue. +/// \param[in] queue_id message queue ID obtained with \ref osMessageCreate. +/// \param[in] info message information. +/// \param[in] millisec timeout value or 0 in case of no time-out. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osMessagePut shall be consistent in every CMSIS-RTOS. +osStatus osMessagePut (osMessageQId queue_id, uint32_t info, uint32_t millisec); + +/// Get a Message or Wait for a Message from a Queue. +/// \param[in] queue_id message queue ID obtained with \ref osMessageCreate. +/// \param[in] millisec timeout value or 0 in case of no time-out. +/// \return event information that includes status code. +/// \note MUST REMAIN UNCHANGED: \b osMessageGet shall be consistent in every CMSIS-RTOS. +osEvent osMessageGet (osMessageQId queue_id, uint32_t millisec); + +#endif // Message Queues available + + +// ==== Mail Queue Management Functions ==== + +#if (defined (osFeature_MailQ) && (osFeature_MailQ != 0)) // Mail Queues available + +/// \brief Create a Mail Queue Definition. +/// \param name name of the queue +/// \param queue_sz maximum number of messages in queue +/// \param type data type of a single message element +/// \note CAN BE CHANGED: The parameter to \b osMailQDef shall be consistent but the +/// macro body is implementation specific in every CMSIS-RTOS. +#if defined (osObjectsExternal) // object is external +#define osMailQDef(name, queue_sz, type) \ +extern struct os_mailQ_cb *os_mailQ_cb_##name; \ +extern const osMailQDef_t os_mailQ_def_##name; +#else // define the object +#define osMailQDef(name, queue_sz, type) \ +struct os_mailQ_cb *os_mailQ_cb_##name; \ +const osMailQDef_t os_mailQ_def_##name = \ +{ (queue_sz), sizeof (type), (&os_mailQ_cb_##name) } +#endif + +/// \brief Access a Mail Queue Definition. +/// \param name name of the queue +/// \note CAN BE CHANGED: The parameter to \b osMailQ shall be consistent but the +/// macro body is implementation specific in every CMSIS-RTOS. +#define osMailQ(name) \ +&os_mailQ_def_##name + +/// Create and Initialize mail queue. +/// \param[in] queue_def reference to the mail queue definition obtain with \ref osMailQ +/// \param[in] thread_id thread ID (obtained by \ref osThreadCreate or \ref osThreadGetId) or NULL. +/// \return mail queue ID for reference by other functions or NULL in case of error. +/// \note MUST REMAIN UNCHANGED: \b osMailCreate shall be consistent in every CMSIS-RTOS. +osMailQId osMailCreate (const osMailQDef_t *queue_def, osThreadId thread_id); + +/// Allocate a memory block from a mail. +/// \param[in] queue_id mail queue ID obtained with \ref osMailCreate. +/// \param[in] millisec timeout value or 0 in case of no time-out +/// \return pointer to memory block that can be filled with mail or NULL in case of error. +/// \note MUST REMAIN UNCHANGED: \b osMailAlloc shall be consistent in every CMSIS-RTOS. +void *osMailAlloc (osMailQId queue_id, uint32_t millisec); + +/// Allocate a memory block from a mail and set memory block to zero. +/// \param[in] queue_id mail queue ID obtained with \ref osMailCreate. +/// \param[in] millisec timeout value or 0 in case of no time-out +/// \return pointer to memory block that can be filled with mail or NULL in case of error. +/// \note MUST REMAIN UNCHANGED: \b osMailCAlloc shall be consistent in every CMSIS-RTOS. +void *osMailCAlloc (osMailQId queue_id, uint32_t millisec); + +/// Put a mail to a queue. +/// \param[in] queue_id mail queue ID obtained with \ref osMailCreate. +/// \param[in] mail memory block previously allocated with \ref osMailAlloc or \ref osMailCAlloc. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osMailPut shall be consistent in every CMSIS-RTOS. +osStatus osMailPut (osMailQId queue_id, void *mail); + +/// Get a mail from a queue. +/// \param[in] queue_id mail queue ID obtained with \ref osMailCreate. +/// \param[in] millisec timeout value or 0 in case of no time-out +/// \return event that contains mail information or error code. +/// \note MUST REMAIN UNCHANGED: \b osMailGet shall be consistent in every CMSIS-RTOS. +osEvent osMailGet (osMailQId queue_id, uint32_t millisec); + +/// Free a memory block from a mail. +/// \param[in] queue_id mail queue ID obtained with \ref osMailCreate. +/// \param[in] mail pointer to the memory block that was obtained with \ref osMailGet. +/// \return status code that indicates the execution status of the function. +/// \note MUST REMAIN UNCHANGED: \b osMailFree shall be consistent in every CMSIS-RTOS. +osStatus osMailFree (osMailQId queue_id, void *mail); + +#endif // Mail Queues available + +#define malloc(size) pvPortMalloc(size) +#define free(pbuf) vPortFree(pbuf) +extern void *calloc_freertos(size_t nelements, size_t elementSize); +#define calloc(nelements, elementSize) calloc_freertos(nelements, elementSize) + +#ifdef __cplusplus +} +#endif + +#endif // _CMSIS_OS_H diff --git a/component/os/freertos/freertos_pmu.c b/component/os/freertos/freertos_pmu.c new file mode 100644 index 0000000..2b80fe2 --- /dev/null +++ b/component/os/freertos/freertos_pmu.c @@ -0,0 +1,96 @@ +#include "FreeRTOS.h" + +#include "freertos_pmu.h" + +#include "platform_autoconf.h" +#include "sleep_ex_api.h" +#include "wlan_intf.h" + +static uint32_t wakelock = DEFAULT_WAKELOCK; +static uint32_t wakeup_event = DEFAULT_WAKEUP_EVENT; + +_WEAK void rltk_wlan_pre_sleep_processing (void) { + // Add dummy function for MP +} + +_WEAK void rltk_wlan_post_sleep_processing (void) { + // Add dummy function for MP +} + +/* ++++++++ FreeRTOS macro implementation ++++++++ */ + +/* + * It is called in idle task. + * + * @return true : System is ready to check conditions that if it can enter sleep. + * false : System keep awake. + **/ +int freertos_ready_to_sleep() { + return wakelock == 0; +} + +/* + * It is called when freertos is going to sleep. + * At this moment, all sleep conditons are satisfied. All freertos' sleep pre-processing are done. + * + * @param expected_idle_time : The time that FreeRTOS expect to sleep. + * If we set this value to 0 then FreeRTOS will do nothing in its sleep function. + **/ +void freertos_pre_sleep_processing(unsigned int *expected_idle_time) { + +#ifdef CONFIG_SOC_PS_MODULE + + unsigned int stime; + + /* To disable freertos sleep function and use our sleep function, + * we can set original expected idle time to 0. */ + stime = *expected_idle_time; + *expected_idle_time = 0; + +#ifdef CONFIG_LITTLE_WIFI_MCU_FUNCTION_THREAD +#ifdef CONFIG_POWER_SAVING + if (wakeup_event & SLEEP_WAKEUP_BY_WLAN) { + rltk_wlan_pre_sleep_processing(); + } +#endif +#endif + + sleep_ex(wakeup_event, stime); + +#ifdef CONFIG_LITTLE_WIFI_MCU_FUNCTION_THREAD +#ifdef CONFIG_POWER_SAVING + if (wakeup_event & SLEEP_WAKEUP_BY_WLAN) { + rltk_wlan_post_sleep_processing(); + } +#endif +#endif + +#else + // If PS is not enabled, then use freertos sleep function +#endif +} + +/* -------- FreeRTOS macro implementation -------- */ + +void acquire_wakelock(uint32_t lock_id) { + wakelock |= lock_id; +} + +void release_wakelock(uint32_t lock_id) { + wakelock &= ~lock_id; +} + +uint32_t get_wakelock_status() { + return wakelock; +} + +void add_wakeup_event(uint32_t event) { + wakeup_event |= event; +} + +void del_wakeup_event(uint32_t event) { + wakeup_event &= ~event; + // To fulfill tickless design, system timer is required to be wakeup event + wakeup_event |= SLEEP_WAKEUP_BY_STIMER; +} + diff --git a/component/os/freertos/freertos_pmu.h b/component/os/freertos/freertos_pmu.h new file mode 100644 index 0000000..7e74e90 --- /dev/null +++ b/component/os/freertos/freertos_pmu.h @@ -0,0 +1,25 @@ +#ifndef __FREERTOS_PMU_H_ +#define __FREERTOS_PMU_H_ + +#include "sleep_ex_api.h" + +#define BIT(n) (1<>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/** + * Creates six tasks that operate on three queues as follows: + * + * The first two tasks send and receive an incrementing number to/from a queue. + * One task acts as a producer and the other as the consumer. The consumer is a + * higher priority than the producer and is set to block on queue reads. The queue + * only has space for one item - as soon as the producer posts a message on the + * queue the consumer will unblock, pre-empt the producer, and remove the item. + * + * The second two tasks work the other way around. Again the queue used only has + * enough space for one item. This time the consumer has a lower priority than the + * producer. The producer will try to post on the queue blocking when the queue is + * full. When the consumer wakes it will remove the item from the queue, causing + * the producer to unblock, pre-empt the consumer, and immediately re-fill the + * queue. + * + * The last two tasks use the same queue producer and consumer functions. This time the queue has + * enough space for lots of items and the tasks operate at the same priority. The + * producer will execute, placing items into the queue. The consumer will start + * executing when either the queue becomes full (causing the producer to block) or + * a context switch occurs (tasks of the same priority will time slice). + * + * \page BlockQC blockQ.c + * \ingroup DemoFiles + *
+ */ + +/* +Changes from V1.00: + + + Reversed the priority and block times of the second two demo tasks so + they operate as per the description above. + +Changes from V2.0.0 + + + Delay periods are now specified using variables and constants of + TickType_t rather than unsigned long. + +Changes from V4.0.2 + + + The second set of tasks were created the wrong way around. This has been + corrected. +*/ + + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +/* Demo program include files. */ +#include "BlockQ.h" +#include "print.h" + +#define blckqSTACK_SIZE ( ( unsigned short ) configMINIMAL_STACK_SIZE ) +#define blckqNUM_TASK_SETS ( 3 ) + +/* Structure used to pass parameters to the blocking queue tasks. */ +typedef struct BLOCKING_QUEUE_PARAMETERS +{ + QueueHandle_t xQueue; /*< The queue to be used by the task. */ + TickType_t xBlockTime; /*< The block time to use on queue reads/writes. */ + volatile short *psCheckVariable; /*< Incremented on each successful cycle to check the task is still running. */ +} xBlockingQueueParameters; + +/* Task function that creates an incrementing number and posts it on a queue. */ +static void vBlockingQueueProducer( void *pvParameters ); + +/* Task function that removes the incrementing number from a queue and checks that +it is the expected number. */ +static void vBlockingQueueConsumer( void *pvParameters ); + +/* Variables which are incremented each time an item is removed from a queue, and +found to be the expected value. +These are used to check that the tasks are still running. */ +static volatile short sBlockingConsumerCount[ blckqNUM_TASK_SETS ] = { ( short ) 0, ( short ) 0, ( short ) 0 }; + +/* Variable which are incremented each time an item is posted on a queue. These +are used to check that the tasks are still running. */ +static volatile short sBlockingProducerCount[ blckqNUM_TASK_SETS ] = { ( short ) 0, ( short ) 0, ( short ) 0 }; + +/*-----------------------------------------------------------*/ + +void vStartBlockingQueueTasks( unsigned portBASE_TYPE uxPriority ) +{ +xBlockingQueueParameters *pxQueueParameters1, *pxQueueParameters2; +xBlockingQueueParameters *pxQueueParameters3, *pxQueueParameters4; +xBlockingQueueParameters *pxQueueParameters5, *pxQueueParameters6; +const unsigned portBASE_TYPE uxQueueSize1 = 1, uxQueueSize5 = 5; +const TickType_t xBlockTime = ( TickType_t ) 1000 / portTICK_PERIOD_MS; +const TickType_t xDontBlock = ( TickType_t ) 0; + + /* Create the first two tasks as described at the top of the file. */ + + /* First create the structure used to pass parameters to the consumer tasks. */ + pxQueueParameters1 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + + /* Create the queue used by the first two tasks to pass the incrementing number. + Pass a pointer to the queue in the parameter structure. */ + pxQueueParameters1->xQueue = xQueueCreate( uxQueueSize1, ( unsigned portBASE_TYPE ) sizeof( unsigned short ) ); + + /* The consumer is created first so gets a block time as described above. */ + pxQueueParameters1->xBlockTime = xBlockTime; + + /* Pass in the variable that this task is going to increment so we can check it + is still running. */ + pxQueueParameters1->psCheckVariable = &( sBlockingConsumerCount[ 0 ] ); + + /* Create the structure used to pass parameters to the producer task. */ + pxQueueParameters2 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + + /* Pass the queue to this task also, using the parameter structure. */ + pxQueueParameters2->xQueue = pxQueueParameters1->xQueue; + + /* The producer is not going to block - as soon as it posts the consumer will + wake and remove the item so the producer should always have room to post. */ + pxQueueParameters2->xBlockTime = xDontBlock; + + /* Pass in the variable that this task is going to increment so we can check + it is still running. */ + pxQueueParameters2->psCheckVariable = &( sBlockingProducerCount[ 0 ] ); + + + /* Note the producer has a lower priority than the consumer when the tasks are + spawned. */ + xTaskCreate( vBlockingQueueConsumer, "QConsB1", blckqSTACK_SIZE, ( void * ) pxQueueParameters1, uxPriority, NULL ); + xTaskCreate( vBlockingQueueProducer, "QProdB2", blckqSTACK_SIZE, ( void * ) pxQueueParameters2, tskIDLE_PRIORITY, NULL ); + + + + /* Create the second two tasks as described at the top of the file. This uses + the same mechanism but reverses the task priorities. */ + + pxQueueParameters3 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + pxQueueParameters3->xQueue = xQueueCreate( uxQueueSize1, ( unsigned portBASE_TYPE ) sizeof( unsigned short ) ); + pxQueueParameters3->xBlockTime = xDontBlock; + pxQueueParameters3->psCheckVariable = &( sBlockingProducerCount[ 1 ] ); + + pxQueueParameters4 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + pxQueueParameters4->xQueue = pxQueueParameters3->xQueue; + pxQueueParameters4->xBlockTime = xBlockTime; + pxQueueParameters4->psCheckVariable = &( sBlockingConsumerCount[ 1 ] ); + + xTaskCreate( vBlockingQueueProducer, "QProdB3", blckqSTACK_SIZE, ( void * ) pxQueueParameters3, tskIDLE_PRIORITY, NULL ); + xTaskCreate( vBlockingQueueConsumer, "QConsB4", blckqSTACK_SIZE, ( void * ) pxQueueParameters4, uxPriority, NULL ); + + + + /* Create the last two tasks as described above. The mechanism is again just + the same. This time both parameter structures are given a block time. */ + pxQueueParameters5 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + pxQueueParameters5->xQueue = xQueueCreate( uxQueueSize5, ( unsigned portBASE_TYPE ) sizeof( unsigned short ) ); + pxQueueParameters5->xBlockTime = xBlockTime; + pxQueueParameters5->psCheckVariable = &( sBlockingProducerCount[ 2 ] ); + + pxQueueParameters6 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + pxQueueParameters6->xQueue = pxQueueParameters5->xQueue; + pxQueueParameters6->xBlockTime = xBlockTime; + pxQueueParameters6->psCheckVariable = &( sBlockingConsumerCount[ 2 ] ); + + xTaskCreate( vBlockingQueueProducer, "QProdB5", blckqSTACK_SIZE, ( void * ) pxQueueParameters5, tskIDLE_PRIORITY, NULL ); + xTaskCreate( vBlockingQueueConsumer, "QConsB6", blckqSTACK_SIZE, ( void * ) pxQueueParameters6, tskIDLE_PRIORITY, NULL ); +} +/*-----------------------------------------------------------*/ + +static void vBlockingQueueProducer( void *pvParameters ) +{ +unsigned short usValue = 0; +xBlockingQueueParameters *pxQueueParameters; +const char * const pcTaskStartMsg = "Blocking queue producer started.\r\n"; +const char * const pcTaskErrorMsg = "Could not post on blocking queue\r\n"; +short sErrorEverOccurred = pdFALSE; + + pxQueueParameters = ( xBlockingQueueParameters * ) pvParameters; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + for( ;; ) + { + if( xQueueSendToBack( pxQueueParameters->xQueue, ( void * ) &usValue, pxQueueParameters->xBlockTime ) != pdPASS ) + { + vPrintDisplayMessage( &pcTaskErrorMsg ); + sErrorEverOccurred = pdTRUE; + } + else + { + /* We have successfully posted a message, so increment the variable + used to check we are still running. */ + if( sErrorEverOccurred == pdFALSE ) + { + ( *pxQueueParameters->psCheckVariable )++; + } + + /* Increment the variable we are going to post next time round. The + consumer will expect the numbers to follow in numerical order. */ + ++usValue; + } + } +} +/*-----------------------------------------------------------*/ + +static void vBlockingQueueConsumer( void *pvParameters ) +{ +unsigned short usData, usExpectedValue = 0; +xBlockingQueueParameters *pxQueueParameters; +const char * const pcTaskStartMsg = "Blocking queue consumer started.\r\n"; +const char * const pcTaskErrorMsg = "Incorrect value received on blocking queue.\r\n"; +short sErrorEverOccurred = pdFALSE; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + pxQueueParameters = ( xBlockingQueueParameters * ) pvParameters; + + for( ;; ) + { + if( xQueueReceive( pxQueueParameters->xQueue, &usData, pxQueueParameters->xBlockTime ) == pdPASS ) + { + if( usData != usExpectedValue ) + { + vPrintDisplayMessage( &pcTaskErrorMsg ); + + /* Catch-up. */ + usExpectedValue = usData; + + sErrorEverOccurred = pdTRUE; + } + else + { + /* We have successfully received a message, so increment the + variable used to check we are still running. */ + if( sErrorEverOccurred == pdFALSE ) + { + ( *pxQueueParameters->psCheckVariable )++; + } + + /* Increment the value we expect to remove from the queue next time + round. */ + ++usExpectedValue; + } + } + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +portBASE_TYPE xAreBlockingQueuesStillRunning( void ) +{ +static short sLastBlockingConsumerCount[ blckqNUM_TASK_SETS ] = { ( short ) 0, ( short ) 0, ( short ) 0 }; +static short sLastBlockingProducerCount[ blckqNUM_TASK_SETS ] = { ( short ) 0, ( short ) 0, ( short ) 0 }; +portBASE_TYPE xReturn = pdPASS, xTasks; + + /* Not too worried about mutual exclusion on these variables as they are 16 + bits and we are only reading them. We also only care to see if they have + changed or not. + + Loop through each check variable and return pdFALSE if any are found not + to have changed since the last call. */ + + for( xTasks = 0; xTasks < blckqNUM_TASK_SETS; xTasks++ ) + { + if( sBlockingConsumerCount[ xTasks ] == sLastBlockingConsumerCount[ xTasks ] ) + { + xReturn = pdFALSE; + } + sLastBlockingConsumerCount[ xTasks ] = sBlockingConsumerCount[ xTasks ]; + + + if( sBlockingProducerCount[ xTasks ] == sLastBlockingProducerCount[ xTasks ] ) + { + xReturn = pdFALSE; + } + sLastBlockingProducerCount[ xTasks ] = sBlockingProducerCount[ xTasks ]; + } + + return xReturn; +} + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/PollQ.c b/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/PollQ.c new file mode 100644 index 0000000..6148a80 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/PollQ.c @@ -0,0 +1,258 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +/** + * This is a very simple queue test. See the BlockQ. c documentation for a more + * comprehensive version. + * + * Creates two tasks that communicate over a single queue. One task acts as a + * producer, the other a consumer. + * + * The producer loops for three iteration, posting an incrementing number onto the + * queue each cycle. It then delays for a fixed period before doing exactly the + * same again. + * + * The consumer loops emptying the queue. Each item removed from the queue is + * checked to ensure it contains the expected value. When the queue is empty it + * blocks for a fixed period, then does the same again. + * + * All queue access is performed without blocking. The consumer completely empties + * the queue each time it runs so the producer should never find the queue full. + * + * An error is flagged if the consumer obtains an unexpected value or the producer + * find the queue is full. + * + * \page PollQC pollQ.c + * \ingroup DemoFiles + *
+ */ + +/* +Changes from V2.0.0 + + + Delay periods are now specified using variables and constants of + TickType_t rather than unsigned long. +*/ + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "print.h" + +/* Demo program include files. */ +#include "PollQ.h" + +#define pollqSTACK_SIZE ( ( unsigned short ) configMINIMAL_STACK_SIZE ) + +/* The task that posts the incrementing number onto the queue. */ +static void vPolledQueueProducer( void *pvParameters ); + +/* The task that empties the queue. */ +static void vPolledQueueConsumer( void *pvParameters ); + +/* Variables that are used to check that the tasks are still running with no errors. */ +static volatile short sPollingConsumerCount = 0, sPollingProducerCount = 0; +/*-----------------------------------------------------------*/ + +void vStartPolledQueueTasks( unsigned portBASE_TYPE uxPriority ) +{ +static QueueHandle_t xPolledQueue; +const unsigned portBASE_TYPE uxQueueSize = 10; + + /* Create the queue used by the producer and consumer. */ + xPolledQueue = xQueueCreate( uxQueueSize, ( unsigned portBASE_TYPE ) sizeof( unsigned short ) ); + + /* Spawn the producer and consumer. */ + xTaskCreate( vPolledQueueConsumer, "QConsNB", pollqSTACK_SIZE, ( void * ) &xPolledQueue, uxPriority, NULL ); + xTaskCreate( vPolledQueueProducer, "QProdNB", pollqSTACK_SIZE, ( void * ) &xPolledQueue, uxPriority, NULL ); +} +/*-----------------------------------------------------------*/ + +static void vPolledQueueProducer( void *pvParameters ) +{ +unsigned short usValue = 0, usLoop; +QueueHandle_t *pxQueue; +const TickType_t xDelay = ( TickType_t ) 200 / portTICK_PERIOD_MS; +const unsigned short usNumToProduce = 3; +const char * const pcTaskStartMsg = "Polled queue producer started.\r\n"; +const char * const pcTaskErrorMsg = "Could not post on polled queue.\r\n"; +short sError = pdFALSE; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + /* The queue being used is passed in as the parameter. */ + pxQueue = ( QueueHandle_t * ) pvParameters; + + for( ;; ) + { + for( usLoop = 0; usLoop < usNumToProduce; ++usLoop ) + { + /* Send an incrementing number on the queue without blocking. */ + if( xQueueSendToBack( *pxQueue, ( void * ) &usValue, ( TickType_t ) 0 ) != pdPASS ) + { + /* We should never find the queue full - this is an error. */ + vPrintDisplayMessage( &pcTaskErrorMsg ); + sError = pdTRUE; + } + else + { + if( sError == pdFALSE ) + { + /* If an error has ever been recorded we stop incrementing the + check variable. */ + ++sPollingProducerCount; + } + + /* Update the value we are going to post next time around. */ + ++usValue; + } + } + + /* Wait before we start posting again to ensure the consumer runs and + empties the queue. */ + vTaskDelay( xDelay ); + } +} +/*-----------------------------------------------------------*/ + +static void vPolledQueueConsumer( void *pvParameters ) +{ +unsigned short usData, usExpectedValue = 0; +QueueHandle_t *pxQueue; +const TickType_t xDelay = ( TickType_t ) 200 / portTICK_PERIOD_MS; +const char * const pcTaskStartMsg = "Polled queue consumer started.\r\n"; +const char * const pcTaskErrorMsg = "Incorrect value received on polled queue.\r\n"; +short sError = pdFALSE; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + /* The queue being used is passed in as the parameter. */ + pxQueue = ( QueueHandle_t * ) pvParameters; + + for( ;; ) + { + /* Loop until the queue is empty. */ + while( uxQueueMessagesWaiting( *pxQueue ) ) + { + if( xQueueReceive( *pxQueue, &usData, ( TickType_t ) 0 ) == pdPASS ) + { + if( usData != usExpectedValue ) + { + /* This is not what we expected to receive so an error has + occurred. */ + vPrintDisplayMessage( &pcTaskErrorMsg ); + sError = pdTRUE; + /* Catch-up to the value we received so our next expected value + should again be correct. */ + usExpectedValue = usData; + } + else + { + if( sError == pdFALSE ) + { + /* Only increment the check variable if no errors have + occurred. */ + ++sPollingConsumerCount; + } + } + ++usExpectedValue; + } + } + + /* Now the queue is empty we block, allowing the producer to place more + items in the queue. */ + vTaskDelay( xDelay ); + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running with no errors. */ +portBASE_TYPE xArePollingQueuesStillRunning( void ) +{ +static short sLastPollingConsumerCount = 0, sLastPollingProducerCount = 0; +portBASE_TYPE xReturn; + + if( ( sLastPollingConsumerCount == sPollingConsumerCount ) || + ( sLastPollingProducerCount == sPollingProducerCount ) + ) + { + xReturn = pdFALSE; + } + else + { + xReturn = pdTRUE; + } + + sLastPollingConsumerCount = sPollingConsumerCount; + sLastPollingProducerCount = sPollingProducerCount; + + return xReturn; +} diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/comtest.c b/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/comtest.c new file mode 100644 index 0000000..92c1e5d --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/comtest.c @@ -0,0 +1,384 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/** + * Creates two tasks that operate on an interrupt driven serial port. A loopback + * connector should be used so that everything that is transmitted is also received. + * The serial port does not use any flow control. On a standard 9way 'D' connector + * pins two and three should be connected together. + * + * The first task repeatedly sends a string to a queue, character at a time. The + * serial port interrupt will empty the queue and transmit the characters. The + * task blocks for a pseudo random period before resending the string. + * + * The second task blocks on a queue waiting for a character to be received. + * Characters received by the serial port interrupt routine are posted onto the + * queue - unblocking the task making it ready to execute. If this is then the + * highest priority task ready to run it will run immediately - with a context + * switch occurring at the end of the interrupt service routine. The task + * receiving characters is spawned with a higher priority than the task + * transmitting the characters. + * + * With the loop back connector in place, one task will transmit a string and the + * other will immediately receive it. The receiving task knows the string it + * expects to receive so can detect an error. + * + * This also creates a third task. This is used to test semaphore usage from an + * ISR and does nothing interesting. + * + * \page ComTestC comtest.c + * \ingroup DemoFiles + *
+ */ + +/* +Changes from V1.00: + + + The priority of the Rx task has been lowered. Received characters are + now processed (read from the queue) at the idle priority, allowing low + priority tasks to run evenly at times of a high communications overhead. + +Changes from V1.01: + + + The Tx task now waits a pseudo random time between transissions. + Previously a fixed period was used but this was not such a good test as + interrupts fired at regular intervals. + +Changes From V1.2.0: + + + Use vSerialPutString() instead of single character puts. + + Only stop the check variable incrementing after two consecutive errors. + +Changed from V1.2.5 + + + Made the Rx task 2 priorities higher than the Tx task. Previously it was + only 1. This is done to tie in better with the other demo application + tasks. + +Changes from V2.0.0 + + + Delay periods are now specified using variables and constants of + TickType_t rather than unsigned long. + + Slight modification to task priorities. + +*/ + + +/* Scheduler include files. */ +#include +#include +#include "FreeRTOS.h" +#include "task.h" + +/* Demo program include files. */ +#include "serial.h" +#include "comtest.h" +#include "print.h" + +/* The Tx task will transmit the sequence of characters at a pseudo random +interval. This is the maximum and minimum block time between sends. */ +#define comTX_MAX_BLOCK_TIME ( ( TickType_t ) 0x15e ) +#define comTX_MIN_BLOCK_TIME ( ( TickType_t ) 0xc8 ) + +#define comMAX_CONSECUTIVE_ERRORS ( 2 ) + +#define comSTACK_SIZE ( ( unsigned short ) 256 ) + +#define comRX_RELATIVE_PRIORITY ( 1 ) + +/* Handle to the com port used by both tasks. */ +static xComPortHandle xPort; + +/* The transmit function as described at the top of the file. */ +static void vComTxTask( void *pvParameters ); + +/* The receive function as described at the top of the file. */ +static void vComRxTask( void *pvParameters ); + +/* The semaphore test function as described at the top of the file. */ +static void vSemTestTask( void * pvParameters ); + +/* The string that is repeatedly transmitted. */ +const char * const pcMessageToExchange = "Send this message over and over again to check communications interrupts. " + "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\r\n"; + +/* Variables that are incremented on each cycle of each task. These are used to +check that both tasks are still executing. */ +volatile short sTxCount = 0, sRxCount = 0, sSemCount = 0; + +/* The handle to the semaphore test task. */ +static TaskHandle_t xSemTestTaskHandle = NULL; + +/*-----------------------------------------------------------*/ + +void vStartComTestTasks( unsigned portBASE_TYPE uxPriority, eCOMPort ePort, eBaud eBaudRate ) +{ +const unsigned portBASE_TYPE uxBufferLength = 255; + + /* Initialise the com port then spawn both tasks. */ + xPort = xSerialPortInit( ePort, eBaudRate, serNO_PARITY, serBITS_8, serSTOP_1, uxBufferLength ); + xTaskCreate( vComTxTask, "COMTx", comSTACK_SIZE, NULL, uxPriority, NULL ); + xTaskCreate( vComRxTask, "COMRx", comSTACK_SIZE, NULL, uxPriority + comRX_RELATIVE_PRIORITY, NULL ); + xTaskCreate( vSemTestTask, "ISRSem", comSTACK_SIZE, NULL, tskIDLE_PRIORITY, &xSemTestTaskHandle ); +} +/*-----------------------------------------------------------*/ + +static void vComTxTask( void *pvParameters ) +{ +const char * const pcTaskStartMsg = "COM Tx task started.\r\n"; +TickType_t xTimeToWait; + + /* Stop warnings. */ + ( void ) pvParameters; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + for( ;; ) + { + /* Send the string to the serial port. */ + vSerialPutString( xPort, pcMessageToExchange, strlen( pcMessageToExchange ) ); + + /* We have posted all the characters in the string - increment the variable + used to check that this task is still running, then wait before re-sending + the string. */ + sTxCount++; + + xTimeToWait = xTaskGetTickCount(); + + /* Make sure we don't wait too long... */ + xTimeToWait %= comTX_MAX_BLOCK_TIME; + + /* ...but we do want to wait. */ + if( xTimeToWait < comTX_MIN_BLOCK_TIME ) + { + xTimeToWait = comTX_MIN_BLOCK_TIME; + } + + vTaskDelay( xTimeToWait ); + } +} /*lint !e715 !e818 pvParameters is required for a task function even if it is not referenced. */ +/*-----------------------------------------------------------*/ + +static void vComRxTask( void *pvParameters ) +{ +const char * const pcTaskStartMsg = "COM Rx task started.\r\n"; +const char * const pcTaskErrorMsg = "COM read error\r\n"; +const char * const pcTaskRestartMsg = "COM resynced\r\n"; +const char * const pcTaskTimeoutMsg = "COM Rx timed out\r\n"; +const TickType_t xBlockTime = ( TickType_t ) 0xffff / portTICK_PERIOD_MS; +const char *pcExpectedChar; +portBASE_TYPE xGotChar; +char cRxedChar; +short sResyncRequired, sConsecutiveErrors, sLatchedError; + + /* Stop warnings. */ + ( void ) pvParameters; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + /* The first expected character is the first character in the string. */ + pcExpectedChar = pcMessageToExchange; + sResyncRequired = pdFALSE; + sConsecutiveErrors = 0; + sLatchedError = pdFALSE; + + for( ;; ) + { + /* Receive a message from the com port interrupt routine. If a message is + not yet available the call will block the task. */ + xGotChar = xSerialGetChar( xPort, &cRxedChar, xBlockTime ); + if( xGotChar == pdTRUE ) + { + if( sResyncRequired == pdTRUE ) + { + /* We got out of sequence and are waiting for the start of the next + transmission of the string. */ + if( cRxedChar == '\n' ) + { + /* This is the end of the message so we can start again - with + the first character in the string being the next thing we expect + to receive. */ + pcExpectedChar = pcMessageToExchange; + sResyncRequired = pdFALSE; + + /* Queue a message for printing to say that we are going to try + again. */ + vPrintDisplayMessage( &pcTaskRestartMsg ); + + /* Stop incrementing the check variable, if consecutive errors occur. */ + sConsecutiveErrors++; + if( sConsecutiveErrors >= comMAX_CONSECUTIVE_ERRORS ) + { + sLatchedError = pdTRUE; + } + } + } + else + { + /* We have received a character, but is it the expected character? */ + if( cRxedChar != *pcExpectedChar ) + { + /* This was not the expected character so post a message for + printing to say that an error has occurred. We will then wait + to resynchronise. */ + vPrintDisplayMessage( &pcTaskErrorMsg ); + sResyncRequired = pdTRUE; + } + else + { + /* This was the expected character so next time we will expect + the next character in the string. Wrap back to the beginning + of the string when the null terminator has been reached. */ + pcExpectedChar++; + if( *pcExpectedChar == '\0' ) + { + pcExpectedChar = pcMessageToExchange; + + /* We have got through the entire string without error. */ + sConsecutiveErrors = 0; + } + } + } + + /* Increment the count that is used to check that this task is still + running. This is only done if an error has never occurred. */ + if( sLatchedError == pdFALSE ) + { + sRxCount++; + } + } + else + { + vPrintDisplayMessage( &pcTaskTimeoutMsg ); + } + } +} /*lint !e715 !e818 pvParameters is required for a task function even if it is not referenced. */ +/*-----------------------------------------------------------*/ + +static void vSemTestTask( void * pvParameters ) +{ +const char * const pcTaskStartMsg = "ISR Semaphore test started.\r\n"; +portBASE_TYPE xError = pdFALSE; + + /* Stop warnings. */ + ( void ) pvParameters; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + for( ;; ) + { + if( xSerialWaitForSemaphore( xPort ) ) + { + if( xError == pdFALSE ) + { + sSemCount++; + } + } + else + { + xError = pdTRUE; + } + } +} /*lint !e715 !e830 !e818 pvParameters not used but function prototype must be standard for task function. */ +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +portBASE_TYPE xAreComTestTasksStillRunning( void ) +{ +static short sLastTxCount = 0, sLastRxCount = 0, sLastSemCount = 0; +portBASE_TYPE xReturn; + + /* Not too worried about mutual exclusion on these variables as they are 16 + bits and we are only reading them. We also only care to see if they have + changed or not. */ + + if( ( sTxCount == sLastTxCount ) || ( sRxCount == sLastRxCount ) || ( sSemCount == sLastSemCount ) ) + { + xReturn = pdFALSE; + } + else + { + xReturn = pdTRUE; + } + + sLastTxCount = sTxCount; + sLastRxCount = sRxCount; + sLastSemCount = sSemCount; + + return xReturn; +} +/*-----------------------------------------------------------*/ + +void vComTestUnsuspendTask( void ) +{ + /* The task that is suspended on the semaphore will be referenced from the + Suspended list as it is blocking indefinitely. This call just checks that + the kernel correctly detects this and does not attempt to unsuspend the + task. */ + xTaskResumeFromISR( xSemTestTaskHandle ); +} diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/death.c b/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/death.c new file mode 100644 index 0000000..aaf4cff --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/death.c @@ -0,0 +1,241 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/** + * Create a single persistent task which periodically dynamically creates another + * four tasks. The original task is called the creator task, the four tasks it + * creates are called suicidal tasks. + * + * Two of the created suicidal tasks kill one other suicidal task before killing + * themselves - leaving just the original task remaining. + * + * The creator task must be spawned after all of the other demo application tasks + * as it keeps a check on the number of tasks under the scheduler control. The + * number of tasks it expects to see running should never be greater than the + * number of tasks that were in existence when the creator task was spawned, plus + * one set of four suicidal tasks. If this number is exceeded an error is flagged. + * + * \page DeathC death.c + * \ingroup DemoFiles + *
+ */ + +/* +Changes from V2.0.0 + + + Delay periods are now specified using variables and constants of + TickType_t rather than unsigned long. +*/ + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Demo program include files. */ +#include "death.h" +#include "print.h" + +#define deathSTACK_SIZE ( ( unsigned short ) 512 ) + +/* The task originally created which is responsible for periodically dynamically +creating another four tasks. */ +static void vCreateTasks( void *pvParameters ); + +/* The task function of the dynamically created tasks. */ +static void vSuicidalTask( void *pvParameters ); + +/* A variable which is incremented every time the dynamic tasks are created. This +is used to check that the task is still running. */ +static volatile short sCreationCount = 0; + +/* Used to store the number of tasks that were originally running so the creator +task can tell if any of the suicidal tasks have failed to die. */ +static volatile unsigned portBASE_TYPE uxTasksRunningAtStart = 0; +static const unsigned portBASE_TYPE uxMaxNumberOfExtraTasksRunning = 5; + +/* Used to store a handle to the tasks that should be killed by a suicidal task, +before it kills itself. */ +TaskHandle_t xCreatedTask1, xCreatedTask2; + +/*-----------------------------------------------------------*/ + +void vCreateSuicidalTasks( unsigned portBASE_TYPE uxPriority ) +{ +unsigned portBASE_TYPE *puxPriority; + + /* Create the Creator tasks - passing in as a parameter the priority at which + the suicidal tasks should be created. */ + puxPriority = ( unsigned portBASE_TYPE * ) pvPortMalloc( sizeof( unsigned portBASE_TYPE ) ); + *puxPriority = uxPriority; + + xTaskCreate( vCreateTasks, "CREATOR", deathSTACK_SIZE, ( void * ) puxPriority, uxPriority, NULL ); + + /* Record the number of tasks that are running now so we know if any of the + suicidal tasks have failed to be killed. */ + uxTasksRunningAtStart = uxTaskGetNumberOfTasks(); +} +/*-----------------------------------------------------------*/ + +static void vSuicidalTask( void *pvParameters ) +{ +portDOUBLE d1, d2; +TaskHandle_t xTaskToKill; +const TickType_t xDelay = ( TickType_t ) 500 / portTICK_PERIOD_MS; + + if( pvParameters != NULL ) + { + /* This task is periodically created four times. Tow created tasks are + passed a handle to the other task so it can kill it before killing itself. + The other task is passed in null. */ + xTaskToKill = *( TaskHandle_t* )pvParameters; + } + else + { + xTaskToKill = NULL; + } + + for( ;; ) + { + /* Do something random just to use some stack and registers. */ + d1 = 2.4; + d2 = 89.2; + d2 *= d1; + vTaskDelay( xDelay ); + + if( xTaskToKill != NULL ) + { + /* Make sure the other task has a go before we delete it. */ + vTaskDelay( ( TickType_t ) 0 ); + /* Kill the other task that was created by vCreateTasks(). */ + vTaskDelete( xTaskToKill ); + /* Kill ourselves. */ + vTaskDelete( NULL ); + } + } +}/*lint !e818 !e550 Function prototype must be as per standard for task functions. */ +/*-----------------------------------------------------------*/ + +static void vCreateTasks( void *pvParameters ) +{ +const TickType_t xDelay = ( TickType_t ) 1000 / portTICK_PERIOD_MS; +unsigned portBASE_TYPE uxPriority; +const char * const pcTaskStartMsg = "Create task started.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + uxPriority = *( unsigned portBASE_TYPE * ) pvParameters; + vPortFree( pvParameters ); + + for( ;; ) + { + /* Just loop round, delaying then creating the four suicidal tasks. */ + vTaskDelay( xDelay ); + + xTaskCreate( vSuicidalTask, "SUICIDE1", deathSTACK_SIZE, NULL, uxPriority, &xCreatedTask1 ); + xTaskCreate( vSuicidalTask, "SUICIDE2", deathSTACK_SIZE, &xCreatedTask1, uxPriority, NULL ); + + xTaskCreate( vSuicidalTask, "SUICIDE1", deathSTACK_SIZE, NULL, uxPriority, &xCreatedTask2 ); + xTaskCreate( vSuicidalTask, "SUICIDE2", deathSTACK_SIZE, &xCreatedTask2, uxPriority, NULL ); + + ++sCreationCount; + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that the creator task is still running and that there +are not any more than four extra tasks. */ +portBASE_TYPE xIsCreateTaskStillRunning( void ) +{ +static short sLastCreationCount = 0; +short sReturn = pdTRUE; +unsigned portBASE_TYPE uxTasksRunningNow; + + if( sLastCreationCount == sCreationCount ) + { + sReturn = pdFALSE; + } + + uxTasksRunningNow = uxTaskGetNumberOfTasks(); + + if( uxTasksRunningNow < uxTasksRunningAtStart ) + { + sReturn = pdFALSE; + } + else if( ( uxTasksRunningNow - uxTasksRunningAtStart ) > uxMaxNumberOfExtraTasksRunning ) + { + sReturn = pdFALSE; + } + else + { + /* Everything is okay. */ + } + + return sReturn; +} + + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/dynamic.c b/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/dynamic.c new file mode 100644 index 0000000..294743d --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/dynamic.c @@ -0,0 +1,616 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/** + * The first test creates three tasks - two counter tasks (one continuous count + * and one limited count) and one controller. A "count" variable is shared + * between all three tasks. The two counter tasks should never be in a "ready" + * state at the same time. The controller task runs at the same priority as + * the continuous count task, and at a lower priority than the limited count + * task. + * + * One counter task loops indefinitely, incrementing the shared count variable + * on each iteration. To ensure it has exclusive access to the variable it + * raises it's priority above that of the controller task before each + * increment, lowering it again to it's original priority before starting the + * next iteration. + * + * The other counter task increments the shared count variable on each + * iteration of it's loop until the count has reached a limit of 0xff - at + * which point it suspends itself. It will not start a new loop until the + * controller task has made it "ready" again by calling vTaskResume (). + * This second counter task operates at a higher priority than controller + * task so does not need to worry about mutual exclusion of the counter + * variable. + * + * The controller task is in two sections. The first section controls and + * monitors the continuous count task. When this section is operational the + * limited count task is suspended. Likewise, the second section controls + * and monitors the limited count task. When this section is operational the + * continuous count task is suspended. + * + * In the first section the controller task first takes a copy of the shared + * count variable. To ensure mutual exclusion on the count variable it + * suspends the continuous count task, resuming it again when the copy has been + * taken. The controller task then sleeps for a fixed period - during which + * the continuous count task will execute and increment the shared variable. + * When the controller task wakes it checks that the continuous count task + * has executed by comparing the copy of the shared variable with its current + * value. This time, to ensure mutual exclusion, the scheduler itself is + * suspended with a call to vTaskSuspendAll (). This is for demonstration + * purposes only and is not a recommended technique due to its inefficiency. + * + * After a fixed number of iterations the controller task suspends the + * continuous count task, and moves on to its second section. + * + * At the start of the second section the shared variable is cleared to zero. + * The limited count task is then woken from it's suspension by a call to + * vTaskResume (). As this counter task operates at a higher priority than + * the controller task the controller task should not run again until the + * shared variable has been counted up to the limited value causing the counter + * task to suspend itself. The next line after vTaskResume () is therefore + * a check on the shared variable to ensure everything is as expected. + * + * + * The second test consists of a couple of very simple tasks that post onto a + * queue while the scheduler is suspended. This test was added to test parts + * of the scheduler not exercised by the first test. + * + * + * The final set of two tasks implements a third test. This simply raises the + * priority of a task while the scheduler is suspended. Again this test was + * added to exercise parts of the code not covered by the first test. + * + * \page Priorities dynamic.c + * \ingroup DemoFiles + *
+ */ + +/* +Changes from V2.0.0 + + + Delay periods are now specified using variables and constants of + TickType_t rather than unsigned long. + + Added a second, simple test that uses the functions + vQueueReceiveWhenSuspendedTask() and vQueueSendWhenSuspendedTask(). + +Changes from V3.1.1 + + + Added a third simple test that uses the vTaskPrioritySet() function + while the scheduler is suspended. + + Modified the controller task slightly to test the calling of + vTaskResumeAll() while the scheduler is suspended. +*/ + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "semphr.h" + +/* Demo app include files. */ +#include "dynamic.h" +#include "print.h" + +/* Function that implements the "limited count" task as described above. */ +static void vLimitedIncrementTask( void * pvParameters ); + +/* Function that implements the "continuous count" task as described above. */ +static void vContinuousIncrementTask( void * pvParameters ); + +/* Function that implements the controller task as described above. */ +static void vCounterControlTask( void * pvParameters ); + +/* The simple test functions that check sending and receiving while the +scheduler is suspended. */ +static void vQueueReceiveWhenSuspendedTask( void *pvParameters ); +static void vQueueSendWhenSuspendedTask( void *pvParameters ); + +/* The simple test functions that check raising and lowering of task priorities +while the scheduler is suspended. */ +static void prvChangePriorityWhenSuspendedTask( void *pvParameters ); +static void prvChangePriorityHelperTask( void *pvParameters ); + + +/* Demo task specific constants. */ +#define priSTACK_SIZE ( ( unsigned short ) configMINIMAL_STACK_SIZE ) +#define priSLEEP_TIME ( ( TickType_t ) 50 ) +#define priLOOPS ( 5 ) +#define priMAX_COUNT ( ( unsigned long ) 0xff ) +#define priNO_BLOCK ( ( TickType_t ) 0 ) +#define priSUSPENDED_QUEUE_LENGTH ( 1 ) + +/*-----------------------------------------------------------*/ + +/* Handles to the two counter tasks. These could be passed in as parameters +to the controller task to prevent them having to be file scope. */ +static TaskHandle_t xContinuousIncrementHandle, xLimitedIncrementHandle, xChangePriorityWhenSuspendedHandle; + +/* The shared counter variable. This is passed in as a parameter to the two +counter variables for demonstration purposes. */ +static unsigned long ulCounter; + +/* Variable used in a similar way by the test that checks the raising and +lowering of task priorities while the scheduler is suspended. */ +static unsigned long ulPrioritySetCounter; + +/* Variables used to check that the tasks are still operating without error. +Each complete iteration of the controller task increments this variable +provided no errors have been found. The variable maintaining the same value +is therefore indication of an error. */ +static unsigned short usCheckVariable = ( unsigned short ) 0; +static portBASE_TYPE xSuspendedQueueSendError = pdFALSE; +static portBASE_TYPE xSuspendedQueueReceiveError = pdFALSE; +static portBASE_TYPE xPriorityRaiseWhenSuspendedError = pdFALSE; + +/* Queue used by the second test. */ +QueueHandle_t xSuspendedTestQueue; + +/*-----------------------------------------------------------*/ +/* + * Start the seven tasks as described at the top of the file. + * Note that the limited count task is given a higher priority. + */ +void vStartDynamicPriorityTasks( void ) +{ + xSuspendedTestQueue = xQueueCreate( priSUSPENDED_QUEUE_LENGTH, sizeof( unsigned long ) ); + xTaskCreate( vContinuousIncrementTask, "CONT_INC", priSTACK_SIZE, ( void * ) &ulCounter, tskIDLE_PRIORITY, &xContinuousIncrementHandle ); + xTaskCreate( vLimitedIncrementTask, "LIM_INC", priSTACK_SIZE, ( void * ) &ulCounter, tskIDLE_PRIORITY + 1, &xLimitedIncrementHandle ); + xTaskCreate( vCounterControlTask, "C_CTRL", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); + xTaskCreate( vQueueSendWhenSuspendedTask, "SUSP_SEND", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); + xTaskCreate( vQueueReceiveWhenSuspendedTask, "SUSP_RECV", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); + xTaskCreate( prvChangePriorityWhenSuspendedTask, "1st_P_CHANGE", priSTACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL ); + xTaskCreate( prvChangePriorityHelperTask, "2nd_P_CHANGE", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, &xChangePriorityWhenSuspendedHandle ); +} +/*-----------------------------------------------------------*/ + +/* + * Just loops around incrementing the shared variable until the limit has been + * reached. Once the limit has been reached it suspends itself. + */ +static void vLimitedIncrementTask( void * pvParameters ) +{ +unsigned long *pulCounter; + + /* Take a pointer to the shared variable from the parameters passed into + the task. */ + pulCounter = ( unsigned long * ) pvParameters; + + /* This will run before the control task, so the first thing it does is + suspend - the control task will resume it when ready. */ + vTaskSuspend( NULL ); + + for( ;; ) + { + /* Just count up to a value then suspend. */ + ( *pulCounter )++; + + if( *pulCounter >= priMAX_COUNT ) + { + vTaskSuspend( NULL ); + } + } +} +/*-----------------------------------------------------------*/ + +/* + * Just keep counting the shared variable up. The control task will suspend + * this task when it wants. + */ +static void vContinuousIncrementTask( void * pvParameters ) +{ +unsigned long *pulCounter; +unsigned portBASE_TYPE uxOurPriority; + + /* Take a pointer to the shared variable from the parameters passed into + the task. */ + pulCounter = ( unsigned long * ) pvParameters; + + /* Query our priority so we can raise it when exclusive access to the + shared variable is required. */ + uxOurPriority = uxTaskPriorityGet( NULL ); + + for( ;; ) + { + /* Raise our priority above the controller task to ensure a context + switch does not occur while we are accessing this variable. */ + vTaskPrioritySet( NULL, uxOurPriority + 1 ); + ( *pulCounter )++; + vTaskPrioritySet( NULL, uxOurPriority ); + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + } +} +/*-----------------------------------------------------------*/ + +/* + * Controller task as described above. + */ +static void vCounterControlTask( void * pvParameters ) +{ +unsigned long ulLastCounter; +short sLoops; +short sError = pdFALSE; +const char * const pcTaskStartMsg = "Priority manipulation tasks started.\r\n"; +const char * const pcTaskFailMsg = "Priority manipulation Task Failed\r\n"; + + /* Just to stop warning messages. */ + ( void ) pvParameters; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + for( ;; ) + { + /* Start with the counter at zero. */ + ulCounter = ( unsigned long ) 0; + + /* First section : */ + + /* Check the continuous count task is running. */ + for( sLoops = 0; sLoops < priLOOPS; sLoops++ ) + { + /* Suspend the continuous count task so we can take a mirror of the + shared variable without risk of corruption. */ + vTaskSuspend( xContinuousIncrementHandle ); + ulLastCounter = ulCounter; + vTaskResume( xContinuousIncrementHandle ); + + /* Now delay to ensure the other task has processor time. */ + vTaskDelay( priSLEEP_TIME ); + + /* Check the shared variable again. This time to ensure mutual + exclusion the whole scheduler will be locked. This is just for + demo purposes! */ + vTaskSuspendAll(); + { + if( ulLastCounter == ulCounter ) + { + /* The shared variable has not changed. There is a problem + with the continuous count task so flag an error. */ + sError = pdTRUE; + xTaskResumeAll(); + vPrintDisplayMessage( &pcTaskFailMsg ); + vTaskSuspendAll(); + } + } + xTaskResumeAll(); + } + + + /* Second section: */ + + /* Suspend the continuous counter task so it stops accessing the shared variable. */ + vTaskSuspend( xContinuousIncrementHandle ); + + /* Reset the variable. */ + ulCounter = ( unsigned long ) 0; + + /* Resume the limited count task which has a higher priority than us. + We should therefore not return from this call until the limited count + task has suspended itself with a known value in the counter variable. + The scheduler suspension is not necessary but is included for test + purposes. */ + vTaskSuspendAll(); + vTaskResume( xLimitedIncrementHandle ); + xTaskResumeAll(); + + /* Does the counter variable have the expected value? */ + if( ulCounter != priMAX_COUNT ) + { + sError = pdTRUE; + vPrintDisplayMessage( &pcTaskFailMsg ); + } + + if( sError == pdFALSE ) + { + /* If no errors have occurred then increment the check variable. */ + portENTER_CRITICAL(); + usCheckVariable++; + portEXIT_CRITICAL(); + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* Resume the continuous count task and do it all again. */ + vTaskResume( xContinuousIncrementHandle ); + } +} +/*-----------------------------------------------------------*/ + +static void vQueueSendWhenSuspendedTask( void *pvParameters ) +{ +static unsigned long ulValueToSend = ( unsigned long ) 0; +const char * const pcTaskStartMsg = "Queue send while suspended task started.\r\n"; +const char * const pcTaskFailMsg = "Queue send while suspended failed.\r\n"; + + /* Just to stop warning messages. */ + ( void ) pvParameters; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + for( ;; ) + { + vTaskSuspendAll(); + { + /* We must not block while the scheduler is suspended! */ + if( xQueueSend( xSuspendedTestQueue, ( void * ) &ulValueToSend, priNO_BLOCK ) != pdTRUE ) + { + if( xSuspendedQueueSendError == pdFALSE ) + { + xTaskResumeAll(); + vPrintDisplayMessage( &pcTaskFailMsg ); + vTaskSuspendAll(); + } + + xSuspendedQueueSendError = pdTRUE; + } + } + xTaskResumeAll(); + + vTaskDelay( priSLEEP_TIME ); + + ++ulValueToSend; + } +} +/*-----------------------------------------------------------*/ + +static void vQueueReceiveWhenSuspendedTask( void *pvParameters ) +{ +static unsigned long ulExpectedValue = ( unsigned long ) 0, ulReceivedValue; +const char * const pcTaskStartMsg = "Queue receive while suspended task started.\r\n"; +const char * const pcTaskFailMsg = "Queue receive while suspended failed.\r\n"; +portBASE_TYPE xGotValue; + + /* Just to stop warning messages. */ + ( void ) pvParameters; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + for( ;; ) + { + do + { + /* Suspending the scheduler here is fairly pointless and + undesirable for a normal application. It is done here purely + to test the scheduler. The inner xTaskResumeAll() should + never return pdTRUE as the scheduler is still locked by the + outer call. */ + vTaskSuspendAll(); + { + vTaskSuspendAll(); + { + xGotValue = xQueueReceive( xSuspendedTestQueue, ( void * ) &ulReceivedValue, priNO_BLOCK ); + } + if( xTaskResumeAll() ) + { + xSuspendedQueueReceiveError = pdTRUE; + } + } + xTaskResumeAll(); + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + } while( xGotValue == pdFALSE ); + + if( ulReceivedValue != ulExpectedValue ) + { + if( xSuspendedQueueReceiveError == pdFALSE ) + { + vPrintDisplayMessage( &pcTaskFailMsg ); + } + xSuspendedQueueReceiveError = pdTRUE; + } + + ++ulExpectedValue; + } +} +/*-----------------------------------------------------------*/ + +static void prvChangePriorityWhenSuspendedTask( void *pvParameters ) +{ +const char * const pcTaskStartMsg = "Priority change when suspended task started.\r\n"; +const char * const pcTaskFailMsg = "Priority change when suspended task failed.\r\n"; + + /* Just to stop warning messages. */ + ( void ) pvParameters; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + for( ;; ) + { + /* Start with the counter at 0 so we know what the counter should be + when we check it next. */ + ulPrioritySetCounter = ( unsigned long ) 0; + + /* Resume the helper task. At this time it has a priority lower than + ours so no context switch should occur. */ + vTaskResume( xChangePriorityWhenSuspendedHandle ); + + /* Check to ensure the task just resumed has not executed. */ + portENTER_CRITICAL(); + { + if( ulPrioritySetCounter != ( unsigned long ) 0 ) + { + xPriorityRaiseWhenSuspendedError = pdTRUE; + vPrintDisplayMessage( &pcTaskFailMsg ); + } + } + portEXIT_CRITICAL(); + + /* Now try raising the priority while the scheduler is suspended. */ + vTaskSuspendAll(); + { + vTaskPrioritySet( xChangePriorityWhenSuspendedHandle, ( configMAX_PRIORITIES - 1 ) ); + + /* Again, even though the helper task has a priority greater than + ours, it should not have executed yet because the scheduler is + suspended. */ + portENTER_CRITICAL(); + { + if( ulPrioritySetCounter != ( unsigned long ) 0 ) + { + xPriorityRaiseWhenSuspendedError = pdTRUE; + vPrintDisplayMessage( &pcTaskFailMsg ); + } + } + portEXIT_CRITICAL(); + } + xTaskResumeAll(); + + /* Now the scheduler has been resumed the helper task should + immediately preempt us and execute. When it executes it will increment + the ulPrioritySetCounter exactly once before suspending itself. + + We should now always find the counter set to 1. */ + portENTER_CRITICAL(); + { + if( ulPrioritySetCounter != ( unsigned long ) 1 ) + { + xPriorityRaiseWhenSuspendedError = pdTRUE; + vPrintDisplayMessage( &pcTaskFailMsg ); + } + } + portEXIT_CRITICAL(); + + /* Delay until we try this again. */ + vTaskDelay( priSLEEP_TIME * 2 ); + + /* Set the priority of the helper task back ready for the next + execution of this task. */ + vTaskSuspendAll(); + vTaskPrioritySet( xChangePriorityWhenSuspendedHandle, tskIDLE_PRIORITY ); + xTaskResumeAll(); + } +} +/*-----------------------------------------------------------*/ + +static void prvChangePriorityHelperTask( void *pvParameters ) +{ + /* Just to stop warning messages. */ + ( void ) pvParameters; + + for( ;; ) + { + /* This is the helper task for prvChangePriorityWhenSuspendedTask(). + It has it's priority raised and lowered. When it runs it simply + increments the counter then suspends itself again. This allows + prvChangePriorityWhenSuspendedTask() to know how many times it has + executed. */ + ulPrioritySetCounter++; + vTaskSuspend( NULL ); + } +} +/*-----------------------------------------------------------*/ + +/* Called to check that all the created tasks are still running without error. */ +portBASE_TYPE xAreDynamicPriorityTasksStillRunning( void ) +{ +/* Keep a history of the check variables so we know if it has been incremented +since the last call. */ +static unsigned short usLastTaskCheck = ( unsigned short ) 0; +portBASE_TYPE xReturn = pdTRUE; + + /* Check the tasks are still running by ensuring the check variable + is still incrementing. */ + + if( usCheckVariable == usLastTaskCheck ) + { + /* The check has not incremented so an error exists. */ + xReturn = pdFALSE; + } + + if( xSuspendedQueueSendError == pdTRUE ) + { + xReturn = pdFALSE; + } + + if( xSuspendedQueueReceiveError == pdTRUE ) + { + xReturn = pdFALSE; + } + + if( xPriorityRaiseWhenSuspendedError == pdTRUE ) + { + xReturn = pdFALSE; + } + + usLastTaskCheck = usCheckVariable; + return xReturn; +} + + + + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/events.c b/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/events.c new file mode 100644 index 0000000..307568e --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/events.c @@ -0,0 +1,406 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/** + * This file exercises the event mechanism whereby more than one task is + * blocked waiting for the same event. + * + * The demo creates five tasks - four 'event' tasks, and a controlling task. + * The event tasks have various different priorities and all block on reading + * the same queue. The controlling task writes data to the queue, then checks + * to see which of the event tasks read the data from the queue. The + * controlling task has the lowest priority of all the tasks so is guaranteed + * to always get preempted immediately upon writing to the queue. + * + * By selectively suspending and resuming the event tasks the controlling task + * can check that the highest priority task that is blocked on the queue is the + * task that reads the posted data from the queue. + * + * Two of the event tasks share the same priority. When neither of these tasks + * are suspended they should alternate - one reading one message from the queue, + * the other the next message, etc. + */ + +/* Standard includes. */ +#include +#include +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +/* Demo program include files. */ +#include "mevents.h" +#include "print.h" + +/* Demo specific constants. */ +#define evtSTACK_SIZE ( ( unsigned portBASE_TYPE ) configMINIMAL_STACK_SIZE ) +#define evtNUM_TASKS ( 4 ) +#define evtQUEUE_LENGTH ( ( unsigned portBASE_TYPE ) 3 ) +#define evtNO_DELAY 0 + +/* Just indexes used to uniquely identify the tasks. Note that two tasks are +'highest' priority. */ +#define evtHIGHEST_PRIORITY_INDEX_2 3 +#define evtHIGHEST_PRIORITY_INDEX_1 2 +#define evtMEDIUM_PRIORITY_INDEX 1 +#define evtLOWEST_PRIORITY_INDEX 0 + +/* Each event task increments one of these counters each time it reads data +from the queue. */ +static volatile portBASE_TYPE xTaskCounters[ evtNUM_TASKS ] = { 0, 0, 0, 0 }; + +/* Each time the controlling task posts onto the queue it increments the +expected count of the task that it expected to read the data from the queue +(i.e. the task with the highest priority that should be blocked on the queue). + +xExpectedTaskCounters are incremented from the controlling task, and +xTaskCounters are incremented from the individual event tasks - therefore +comparing xTaskCounters to xExpectedTaskCounters shows whether or not the +correct task was unblocked by the post. */ +static portBASE_TYPE xExpectedTaskCounters[ evtNUM_TASKS ] = { 0, 0, 0, 0 }; + +/* Handles to the four event tasks. These are required to suspend and resume +the tasks. */ +static TaskHandle_t xCreatedTasks[ evtNUM_TASKS ]; + +/* The single queue onto which the controlling task posts, and the four event +tasks block. */ +static QueueHandle_t xQueue; + +/* Flag used to indicate whether or not an error has occurred at any time. +An error is either the queue being full when not expected, or an unexpected +task reading data from the queue. */ +static portBASE_TYPE xHealthStatus = pdPASS; + +/*-----------------------------------------------------------*/ + +/* Function that implements the event task. This is created four times. */ +static void prvMultiEventTask( void *pvParameters ); + +/* Function that implements the controlling task. */ +static void prvEventControllerTask( void *pvParameters ); + +/* This is a utility function that posts data to the queue, then compares +xExpectedTaskCounters with xTaskCounters to ensure everything worked as +expected. + +The event tasks all have higher priorities the controlling task. Therefore +the controlling task will always get preempted between writhing to the queue +and checking the task counters. + +@param xExpectedTask The index to the task that the controlling task thinks + should be the highest priority task waiting for data, and + therefore the task that will unblock. + +@param xIncrement The number of items that should be written to the queue. +*/ +static void prvCheckTaskCounters( portBASE_TYPE xExpectedTask, portBASE_TYPE xIncrement ); + +/* This is just incremented each cycle of the controlling tasks function so +the main application can ensure the test is still running. */ +static portBASE_TYPE xCheckVariable = 0; + +/*-----------------------------------------------------------*/ + +void vStartMultiEventTasks( void ) +{ + /* Create the queue to be used for all the communications. */ + xQueue = xQueueCreate( evtQUEUE_LENGTH, ( unsigned portBASE_TYPE ) sizeof( unsigned portBASE_TYPE ) ); + + /* Start the controlling task. This has the idle priority to ensure it is + always preempted by the event tasks. */ + xTaskCreate( prvEventControllerTask, "EvntCTRL", evtSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); + + /* Start the four event tasks. Note that two have priority 3, one + priority 2 and the other priority 1. */ + xTaskCreate( prvMultiEventTask, "Event0", evtSTACK_SIZE, ( void * ) &( xTaskCounters[ 0 ] ), 1, &( xCreatedTasks[ evtLOWEST_PRIORITY_INDEX ] ) ); + xTaskCreate( prvMultiEventTask, "Event1", evtSTACK_SIZE, ( void * ) &( xTaskCounters[ 1 ] ), 2, &( xCreatedTasks[ evtMEDIUM_PRIORITY_INDEX ] ) ); + xTaskCreate( prvMultiEventTask, "Event2", evtSTACK_SIZE, ( void * ) &( xTaskCounters[ 2 ] ), 3, &( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] ) ); + xTaskCreate( prvMultiEventTask, "Event3", evtSTACK_SIZE, ( void * ) &( xTaskCounters[ 3 ] ), 3, &( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_2 ] ) ); +} +/*-----------------------------------------------------------*/ + +static void prvMultiEventTask( void *pvParameters ) +{ +portBASE_TYPE *pxCounter; +unsigned portBASE_TYPE uxDummy; +const char * const pcTaskStartMsg = "Multi event task started.\r\n"; + + /* The variable this task will increment is passed in as a parameter. */ + pxCounter = ( portBASE_TYPE * ) pvParameters; + + vPrintDisplayMessage( &pcTaskStartMsg ); + + for( ;; ) + { + /* Block on the queue. */ + if( xQueueReceive( xQueue, &uxDummy, portMAX_DELAY ) ) + { + /* We unblocked by reading the queue - so simply increment + the counter specific to this task instance. */ + ( *pxCounter )++; + } + else + { + xHealthStatus = pdFAIL; + } + } +} +/*-----------------------------------------------------------*/ + +static void prvEventControllerTask( void *pvParameters ) +{ +const char * const pcTaskStartMsg = "Multi event controller task started.\r\n"; +portBASE_TYPE xDummy = 0; + + /* Just to stop warnings. */ + ( void ) pvParameters; + + vPrintDisplayMessage( &pcTaskStartMsg ); + + for( ;; ) + { + /* All tasks are blocked on the queue. When a message is posted one of + the two tasks that share the highest priority should unblock to read + the queue. The next message written should unblock the other task with + the same high priority, and so on in order. No other task should + unblock to read data as they have lower priorities. */ + + prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_1, 1 ); + prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_2, 1 ); + prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_1, 1 ); + prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_2, 1 ); + prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_1, 1 ); + + /* For the rest of these tests we don't need the second 'highest' + priority task - so it is suspended. */ + vTaskSuspend( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_2 ] ); + + + + /* Now suspend the other highest priority task. The medium priority + task will then be the task with the highest priority that remains + blocked on the queue. */ + vTaskSuspend( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] ); + + /* This time, when we post onto the queue we will expect the medium + priority task to unblock and preempt us. */ + prvCheckTaskCounters( evtMEDIUM_PRIORITY_INDEX, 1 ); + + /* Now try resuming the highest priority task while the scheduler is + suspended. The task should start executing as soon as the scheduler + is resumed - therefore when we post to the queue again, the highest + priority task should again preempt us. */ + vTaskSuspendAll(); + vTaskResume( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] ); + xTaskResumeAll(); + prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_1, 1 ); + + /* Now we are going to suspend the high and medium priority tasks. The + low priority task should then preempt us. Again the task suspension is + done with the whole scheduler suspended just for test purposes. */ + vTaskSuspendAll(); + vTaskSuspend( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] ); + vTaskSuspend( xCreatedTasks[ evtMEDIUM_PRIORITY_INDEX ] ); + xTaskResumeAll(); + prvCheckTaskCounters( evtLOWEST_PRIORITY_INDEX, 1 ); + + /* Do the same basic test another few times - selectively suspending + and resuming tasks and each time calling prvCheckTaskCounters() passing + to the function the number of the task we expected to be unblocked by + the post. */ + + vTaskResume( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] ); + prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_1, 1 ); + + vTaskSuspendAll(); /* Just for test. */ + vTaskSuspendAll(); /* Just for test. */ + vTaskSuspendAll(); /* Just for even more test. */ + vTaskSuspend( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] ); + xTaskResumeAll(); + xTaskResumeAll(); + xTaskResumeAll(); + prvCheckTaskCounters( evtLOWEST_PRIORITY_INDEX, 1 ); + + vTaskResume( xCreatedTasks[ evtMEDIUM_PRIORITY_INDEX ] ); + prvCheckTaskCounters( evtMEDIUM_PRIORITY_INDEX, 1 ); + + vTaskResume( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] ); + prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_1, 1 ); + + /* Now a slight change, first suspend all tasks. */ + vTaskSuspend( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] ); + vTaskSuspend( xCreatedTasks[ evtMEDIUM_PRIORITY_INDEX ] ); + vTaskSuspend( xCreatedTasks[ evtLOWEST_PRIORITY_INDEX ] ); + + /* Now when we resume the low priority task and write to the queue 3 + times. We expect the low priority task to service the queue three + times. */ + vTaskResume( xCreatedTasks[ evtLOWEST_PRIORITY_INDEX ] ); + prvCheckTaskCounters( evtLOWEST_PRIORITY_INDEX, evtQUEUE_LENGTH ); + + /* Again suspend all tasks (only the low priority task is not suspended + already). */ + vTaskSuspend( xCreatedTasks[ evtLOWEST_PRIORITY_INDEX ] ); + + /* This time we are going to suspend the scheduler, resume the low + priority task, then resume the high priority task. In this state we + will write to the queue three times. When the scheduler is resumed + we expect the high priority task to service all three messages. */ + vTaskSuspendAll(); + { + vTaskResume( xCreatedTasks[ evtLOWEST_PRIORITY_INDEX ] ); + vTaskResume( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] ); + + for( xDummy = 0; xDummy < evtQUEUE_LENGTH; xDummy++ ) + { + if( xQueueSend( xQueue, &xDummy, evtNO_DELAY ) != pdTRUE ) + { + xHealthStatus = pdFAIL; + } + } + + /* The queue should not have been serviced yet!. The scheduler + is still suspended. */ + if( memcmp( ( void * ) xExpectedTaskCounters, ( void * ) xTaskCounters, sizeof( xExpectedTaskCounters ) ) ) + { + xHealthStatus = pdFAIL; + } + } + xTaskResumeAll(); + + /* We should have been preempted by resuming the scheduler - so by the + time we are running again we expect the high priority task to have + removed three items from the queue. */ + xExpectedTaskCounters[ evtHIGHEST_PRIORITY_INDEX_1 ] += evtQUEUE_LENGTH; + if( memcmp( ( void * ) xExpectedTaskCounters, ( void * ) xTaskCounters, sizeof( xExpectedTaskCounters ) ) ) + { + xHealthStatus = pdFAIL; + } + + /* The medium priority and second high priority tasks are still + suspended. Make sure to resume them before starting again. */ + vTaskResume( xCreatedTasks[ evtMEDIUM_PRIORITY_INDEX ] ); + vTaskResume( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_2 ] ); + + /* Just keep incrementing to show the task is still executing. */ + xCheckVariable++; + } +} +/*-----------------------------------------------------------*/ + +static void prvCheckTaskCounters( portBASE_TYPE xExpectedTask, portBASE_TYPE xIncrement ) +{ +portBASE_TYPE xDummy = 0; + + /* Write to the queue the requested number of times. The data written is + not important. */ + for( xDummy = 0; xDummy < xIncrement; xDummy++ ) + { + if( xQueueSend( xQueue, &xDummy, evtNO_DELAY ) != pdTRUE ) + { + /* Did not expect to ever find the queue full. */ + xHealthStatus = pdFAIL; + } + } + + /* All the tasks blocked on the queue have a priority higher than the + controlling task. Writing to the queue will therefore have caused this + task to be preempted. By the time this line executes the event task will + have executed and incremented its counter. Increment the expected counter + to the same value. */ + ( xExpectedTaskCounters[ xExpectedTask ] ) += xIncrement; + + /* Check the actual counts and expected counts really are the same. */ + if( memcmp( ( void * ) xExpectedTaskCounters, ( void * ) xTaskCounters, sizeof( xExpectedTaskCounters ) ) ) + { + /* The counters were not the same. This means a task we did not expect + to unblock actually did unblock. */ + xHealthStatus = pdFAIL; + } +} +/*-----------------------------------------------------------*/ + +portBASE_TYPE xAreMultiEventTasksStillRunning( void ) +{ +static portBASE_TYPE xPreviousCheckVariable = 0; + + /* Called externally to periodically check that this test is still + operational. */ + + if( xPreviousCheckVariable == xCheckVariable ) + { + xHealthStatus = pdFAIL; + } + + xPreviousCheckVariable = xCheckVariable; + + return xHealthStatus; +} + + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/flash.c b/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/flash.c new file mode 100644 index 0000000..db94755 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/flash.c @@ -0,0 +1,166 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +/** + * Creates eight tasks, each of which flash an LED at a different rate. The first + * LED flashes every 125ms, the second every 250ms, the third every 375ms, etc. + * + * The LED flash tasks provide instant visual feedback. They show that the scheduler + * is still operational. + * + * The PC port uses the standard parallel port for outputs, the Flashlite 186 port + * uses IO port F. + * + * \page flashC flash.c + * \ingroup DemoFiles + *
+ */ + +/* +Changes from V2.0.0 + + + Delay periods are now specified using variables and constants of + TickType_t rather than unsigned long. + +Changes from V2.1.1 + + + The stack size now uses configMINIMAL_STACK_SIZE. + + String constants made file scope to decrease stack depth on 8051 port. +*/ + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Demo program include files. */ +#include "partest.h" +#include "flash.h" +#include "print.h" + +#define ledSTACK_SIZE configMINIMAL_STACK_SIZE + +/* Structure used to pass parameters to the LED tasks. */ +typedef struct LED_PARAMETERS +{ + unsigned portBASE_TYPE uxLED; /*< The output the task should use. */ + TickType_t xFlashRate; /*< The rate at which the LED should flash. */ +} xLEDParameters; + +/* The task that is created eight times - each time with a different xLEDParaemtes +structure passed in as the parameter. */ +static void vLEDFlashTask( void *pvParameters ); + +/* String to print if USE_STDIO is defined. */ +const char * const pcTaskStartMsg = "LED flash task started.\r\n"; + +/*-----------------------------------------------------------*/ + +void vStartLEDFlashTasks( unsigned portBASE_TYPE uxPriority ) +{ +unsigned portBASE_TYPE uxLEDTask; +xLEDParameters *pxLEDParameters; +const unsigned portBASE_TYPE uxNumOfLEDs = 8; +const TickType_t xFlashRate = 125; + + /* Create the eight tasks. */ + for( uxLEDTask = 0; uxLEDTask < uxNumOfLEDs; ++uxLEDTask ) + { + /* Create and complete the structure used to pass parameters to the next + created task. */ + pxLEDParameters = ( xLEDParameters * ) pvPortMalloc( sizeof( xLEDParameters ) ); + pxLEDParameters->uxLED = uxLEDTask; + pxLEDParameters->xFlashRate = ( xFlashRate + ( xFlashRate * ( TickType_t ) uxLEDTask ) ); + pxLEDParameters->xFlashRate /= portTICK_PERIOD_MS; + + /* Spawn the task. */ + xTaskCreate( vLEDFlashTask, "LEDx", ledSTACK_SIZE, ( void * ) pxLEDParameters, uxPriority, ( TaskHandle_t * ) NULL ); + } +} +/*-----------------------------------------------------------*/ + +static void vLEDFlashTask( void *pvParameters ) +{ +xLEDParameters *pxParameters; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + pxParameters = ( xLEDParameters * ) pvParameters; + + for(;;) + { + /* Delay for half the flash period then turn the LED on. */ + vTaskDelay( pxParameters->xFlashRate / ( TickType_t ) 2 ); + vParTestToggleLED( pxParameters->uxLED ); + + /* Delay for half the flash period then turn the LED off. */ + vTaskDelay( pxParameters->xFlashRate / ( TickType_t ) 2 ); + vParTestToggleLED( pxParameters->uxLED ); + } +} + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/flop.c b/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/flop.c new file mode 100644 index 0000000..c516ff6 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/flop.c @@ -0,0 +1,369 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* +Changes from V1.2.3 + + + The created tasks now include calls to tskYIELD(), allowing them to be used + with the cooperative scheduler. +*/ + +/** + * Creates eight tasks, each of which loops continuously performing an (emulated) + * floating point calculation. + * + * All the tasks run at the idle priority and never block or yield. This causes + * all eight tasks to time slice with the idle task. Running at the idle priority + * means that these tasks will get pre-empted any time another task is ready to run + * or a time slice occurs. More often than not the pre-emption will occur mid + * calculation, creating a good test of the schedulers context switch mechanism - a + * calculation producing an unexpected result could be a symptom of a corruption in + * the context of a task. + * + * \page FlopC flop.c + * \ingroup DemoFiles + *
+ */ + +#include +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "print.h" + +/* Demo program include files. */ +#include "flop.h" + +#define mathSTACK_SIZE ( ( unsigned short ) 512 ) +#define mathNUMBER_OF_TASKS ( 8 ) + +/* Four tasks, each of which performs a different floating point calculation. +Each of the four is created twice. */ +static void vCompetingMathTask1( void *pvParameters ); +static void vCompetingMathTask2( void *pvParameters ); +static void vCompetingMathTask3( void *pvParameters ); +static void vCompetingMathTask4( void *pvParameters ); + +/* These variables are used to check that all the tasks are still running. If a +task gets a calculation wrong it will +stop incrementing its check variable. */ +static volatile unsigned short usTaskCheck[ mathNUMBER_OF_TASKS ] = { ( unsigned short ) 0 }; + +/*-----------------------------------------------------------*/ + +void vStartMathTasks( unsigned portBASE_TYPE uxPriority ) +{ + xTaskCreate( vCompetingMathTask1, "Math1", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 0 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask2, "Math2", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 1 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask3, "Math3", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 2 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask4, "Math4", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 3 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask1, "Math5", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 4 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask2, "Math6", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 5 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask3, "Math7", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 6 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask4, "Math8", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 7 ] ), uxPriority, NULL ); +} +/*-----------------------------------------------------------*/ + +static void vCompetingMathTask1( void *pvParameters ) +{ +portDOUBLE d1, d2, d3, d4; +volatile unsigned short *pusTaskCheckVariable; +const portDOUBLE dAnswer = ( 123.4567 + 2345.6789 ) * -918.222; +const char * const pcTaskStartMsg = "Math task 1 started.\r\n"; +const char * const pcTaskFailMsg = "Math task 1 failed.\r\n"; +short sError = pdFALSE; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( unsigned short * ) pvParameters; + + /* Keep performing a calculation and checking the result against a constant. */ + for(;;) + { + d1 = 123.4567; + d2 = 2345.6789; + d3 = -918.222; + + d4 = ( d1 + d2 ) * d3; + + taskYIELD(); + + /* If the calculation does not match the expected constant, stop the + increment of the check variable. */ + if( fabs( d4 - dAnswer ) > 0.001 ) + { + vPrintDisplayMessage( &pcTaskFailMsg ); + sError = pdTRUE; + } + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct, increment the check + variable so we know this task is still running okay. */ + ( *pusTaskCheckVariable )++; + } + + taskYIELD(); + } +} +/*-----------------------------------------------------------*/ + +static void vCompetingMathTask2( void *pvParameters ) +{ +portDOUBLE d1, d2, d3, d4; +volatile unsigned short *pusTaskCheckVariable; +const portDOUBLE dAnswer = ( -389.38 / 32498.2 ) * -2.0001; +const char * const pcTaskStartMsg = "Math task 2 started.\r\n"; +const char * const pcTaskFailMsg = "Math task 2 failed.\r\n"; +short sError = pdFALSE; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( unsigned short * ) pvParameters; + + /* Keep performing a calculation and checking the result against a constant. */ + for( ;; ) + { + d1 = -389.38; + d2 = 32498.2; + d3 = -2.0001; + + d4 = ( d1 / d2 ) * d3; + + taskYIELD(); + + /* If the calculation does not match the expected constant, stop the + increment of the check variable. */ + if( fabs( d4 - dAnswer ) > 0.001 ) + { + vPrintDisplayMessage( &pcTaskFailMsg ); + sError = pdTRUE; + } + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct, increment the check + variable so we know + this task is still running okay. */ + ( *pusTaskCheckVariable )++; + } + + taskYIELD(); + } +} +/*-----------------------------------------------------------*/ + +static void vCompetingMathTask3( void *pvParameters ) +{ +portDOUBLE *pdArray, dTotal1, dTotal2, dDifference; +volatile unsigned short *pusTaskCheckVariable; +const unsigned short usArraySize = 250; +unsigned short usPosition; +const char * const pcTaskStartMsg = "Math task 3 started.\r\n"; +const char * const pcTaskFailMsg = "Math task 3 failed.\r\n"; +short sError = pdFALSE; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( unsigned short * ) pvParameters; + + pdArray = ( portDOUBLE * ) pvPortMalloc( ( size_t ) 250 * sizeof( portDOUBLE ) ); + + /* Keep filling an array, keeping a running total of the values placed in the + array. Then run through the array adding up all the values. If the two totals + do not match, stop the check variable from incrementing. */ + for( ;; ) + { + dTotal1 = 0.0; + dTotal2 = 0.0; + + for( usPosition = 0; usPosition < usArraySize; usPosition++ ) + { + pdArray[ usPosition ] = ( portDOUBLE ) usPosition + 5.5; + dTotal1 += ( portDOUBLE ) usPosition + 5.5; + } + + taskYIELD(); + + for( usPosition = 0; usPosition < usArraySize; usPosition++ ) + { + dTotal2 += pdArray[ usPosition ]; + } + + dDifference = dTotal1 - dTotal2; + if( fabs( dDifference ) > 0.001 ) + { + vPrintDisplayMessage( &pcTaskFailMsg ); + sError = pdTRUE; + } + + taskYIELD(); + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct, increment the check + variable so we know this task is still running okay. */ + ( *pusTaskCheckVariable )++; + } + } +} +/*-----------------------------------------------------------*/ + +static void vCompetingMathTask4( void *pvParameters ) +{ +portDOUBLE *pdArray, dTotal1, dTotal2, dDifference; +volatile unsigned short *pusTaskCheckVariable; +const unsigned short usArraySize = 250; +unsigned short usPosition; +const char * const pcTaskStartMsg = "Math task 4 started.\r\n"; +const char * const pcTaskFailMsg = "Math task 4 failed.\r\n"; +short sError = pdFALSE; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( unsigned short * ) pvParameters; + + pdArray = ( portDOUBLE * ) pvPortMalloc( ( size_t ) 250 * sizeof( portDOUBLE ) ); + + /* Keep filling an array, keeping a running total of the values placed in the + array. Then run through the array adding up all the values. If the two totals + do not match, stop the check variable from incrementing. */ + for( ;; ) + { + dTotal1 = 0.0; + dTotal2 = 0.0; + + for( usPosition = 0; usPosition < usArraySize; usPosition++ ) + { + pdArray[ usPosition ] = ( portDOUBLE ) usPosition * 12.123; + dTotal1 += ( portDOUBLE ) usPosition * 12.123; + } + + taskYIELD(); + + for( usPosition = 0; usPosition < usArraySize; usPosition++ ) + { + dTotal2 += pdArray[ usPosition ]; + } + + dDifference = dTotal1 - dTotal2; + if( fabs( dDifference ) > 0.001 ) + { + vPrintDisplayMessage( &pcTaskFailMsg ); + sError = pdTRUE; + } + + taskYIELD(); + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct, increment the check + variable so we know this task is still running okay. */ + ( *pusTaskCheckVariable )++; + } + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +portBASE_TYPE xAreMathsTaskStillRunning( void ) +{ +/* Keep a history of the check variables so we know if they have been incremented +since the last call. */ +static unsigned short usLastTaskCheck[ mathNUMBER_OF_TASKS ] = { ( unsigned short ) 0 }; +portBASE_TYPE xReturn = pdTRUE, xTask; + + /* Check the maths tasks are still running by ensuring their check variables + are still incrementing. */ + for( xTask = 0; xTask < mathNUMBER_OF_TASKS; xTask++ ) + { + if( usTaskCheck[ xTask ] == usLastTaskCheck[ xTask ] ) + { + /* The check has not incremented so an error exists. */ + xReturn = pdFALSE; + } + + usLastTaskCheck[ xTask ] = usTaskCheck[ xTask ]; + } + + return xReturn; +} + + + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/integer.c b/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/integer.c new file mode 100644 index 0000000..8a16e04 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/integer.c @@ -0,0 +1,365 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* +Changes from V1.2.3 + + + The created tasks now include calls to tskYIELD(), allowing them to be used + with the cooperative scheduler. +*/ + +/** + * This does the same as flop. c, but uses variables of type long instead of + * type double. + * + * As with flop. c, the tasks created in this file are a good test of the + * scheduler context switch mechanism. The processor has to access 32bit + * variables in two or four chunks (depending on the processor). The low + * priority of these tasks means there is a high probability that a context + * switch will occur mid calculation. See the flop. c documentation for + * more information. + * + * \page IntegerC integer.c + * \ingroup DemoFiles + *
+ */ + +/* +Changes from V1.2.1 + + + The constants used in the calculations are larger to ensure the + optimiser does not truncate them to 16 bits. +*/ + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "print.h" + +/* Demo program include files. */ +#include "integer.h" + +#define intgSTACK_SIZE ( ( unsigned short ) 256 ) +#define intgNUMBER_OF_TASKS ( 8 ) + +/* Four tasks, each of which performs a different calculation on four byte +variables. Each of the four is created twice. */ +static void vCompeteingIntMathTask1( void *pvParameters ); +static void vCompeteingIntMathTask2( void *pvParameters ); +static void vCompeteingIntMathTask3( void *pvParameters ); +static void vCompeteingIntMathTask4( void *pvParameters ); + +/* These variables are used to check that all the tasks are still running. If a +task gets a calculation wrong it will stop incrementing its check variable. */ +static volatile unsigned short usTaskCheck[ intgNUMBER_OF_TASKS ] = { ( unsigned short ) 0 }; +/*-----------------------------------------------------------*/ + +void vStartIntegerMathTasks( unsigned portBASE_TYPE uxPriority ) +{ + xTaskCreate( vCompeteingIntMathTask1, "IntMath1", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 0 ] ), uxPriority, NULL ); + xTaskCreate( vCompeteingIntMathTask2, "IntMath2", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 1 ] ), uxPriority, NULL ); + xTaskCreate( vCompeteingIntMathTask3, "IntMath3", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 2 ] ), uxPriority, NULL ); + xTaskCreate( vCompeteingIntMathTask4, "IntMath4", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 3 ] ), uxPriority, NULL ); + xTaskCreate( vCompeteingIntMathTask1, "IntMath5", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 4 ] ), uxPriority, NULL ); + xTaskCreate( vCompeteingIntMathTask2, "IntMath6", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 5 ] ), uxPriority, NULL ); + xTaskCreate( vCompeteingIntMathTask3, "IntMath7", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 6 ] ), uxPriority, NULL ); + xTaskCreate( vCompeteingIntMathTask4, "IntMath8", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 7 ] ), uxPriority, NULL ); +} +/*-----------------------------------------------------------*/ + +static void vCompeteingIntMathTask1( void *pvParameters ) +{ +long l1, l2, l3, l4; +short sError = pdFALSE; +volatile unsigned short *pusTaskCheckVariable; +const long lAnswer = ( ( long ) 74565L + ( long ) 1234567L ) * ( long ) -918L; +const char * const pcTaskStartMsg = "Integer math task 1 started.\r\n"; +const char * const pcTaskFailMsg = "Integer math task 1 failed.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( unsigned short * ) pvParameters; + + /* Keep performing a calculation and checking the result against a constant. */ + for(;;) + { + l1 = ( long ) 74565L; + l2 = ( long ) 1234567L; + l3 = ( long ) -918L; + + l4 = ( l1 + l2 ) * l3; + + taskYIELD(); + + /* If the calculation does not match the expected constant, stop the + increment of the check variable. */ + if( l4 != lAnswer ) + { + vPrintDisplayMessage( &pcTaskFailMsg ); + sError = pdTRUE; + } + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct, increment the check + variable so we know this task is still running okay. */ + ( *pusTaskCheckVariable )++; + } + } +} +/*-----------------------------------------------------------*/ + +static void vCompeteingIntMathTask2( void *pvParameters ) +{ +long l1, l2, l3, l4; +short sError = pdFALSE; +volatile unsigned short *pusTaskCheckVariable; +const long lAnswer = ( ( long ) -389000L / ( long ) 329999L ) * ( long ) -89L; +const char * const pcTaskStartMsg = "Integer math task 2 started.\r\n"; +const char * const pcTaskFailMsg = "Integer math task 2 failed.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( unsigned short * ) pvParameters; + + /* Keep performing a calculation and checking the result against a constant. */ + for( ;; ) + { + l1 = -389000L; + l2 = 329999L; + l3 = -89L; + + l4 = ( l1 / l2 ) * l3; + + taskYIELD(); + + /* If the calculation does not match the expected constant, stop the + increment of the check variable. */ + if( l4 != lAnswer ) + { + vPrintDisplayMessage( &pcTaskFailMsg ); + sError = pdTRUE; + } + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct, increment the check + variable so we know this task is still running okay. */ + ( *pusTaskCheckVariable )++; + } + } +} +/*-----------------------------------------------------------*/ + +static void vCompeteingIntMathTask3( void *pvParameters ) +{ +long *plArray, lTotal1, lTotal2; +short sError = pdFALSE; +volatile unsigned short *pusTaskCheckVariable; +const unsigned short usArraySize = ( unsigned short ) 250; +unsigned short usPosition; +const char * const pcTaskStartMsg = "Integer math task 3 started.\r\n"; +const char * const pcTaskFailMsg = "Integer math task 3 failed.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( unsigned short * ) pvParameters; + + /* Create the array we are going to use for our check calculation. */ + plArray = ( long * ) pvPortMalloc( ( size_t ) 250 * sizeof( long ) ); + + /* Keep filling the array, keeping a running total of the values placed in the + array. Then run through the array adding up all the values. If the two totals + do not match, stop the check variable from incrementing. */ + for( ;; ) + { + lTotal1 = ( long ) 0; + lTotal2 = ( long ) 0; + + for( usPosition = 0; usPosition < usArraySize; usPosition++ ) + { + plArray[ usPosition ] = ( long ) usPosition + ( long ) 5; + lTotal1 += ( long ) usPosition + ( long ) 5; + } + + taskYIELD(); + + for( usPosition = 0; usPosition < usArraySize; usPosition++ ) + { + lTotal2 += plArray[ usPosition ]; + } + + if( lTotal1 != lTotal2 ) + { + vPrintDisplayMessage( &pcTaskFailMsg ); + sError = pdTRUE; + } + + taskYIELD(); + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct, increment the check + variable so we know this task is still running okay. */ + ( *pusTaskCheckVariable )++; + } + } +} +/*-----------------------------------------------------------*/ + +static void vCompeteingIntMathTask4( void *pvParameters ) +{ +long *plArray, lTotal1, lTotal2; +short sError = pdFALSE; +volatile unsigned short *pusTaskCheckVariable; +const unsigned short usArraySize = 250; +unsigned short usPosition; +const char * const pcTaskStartMsg = "Integer math task 4 started.\r\n"; +const char * const pcTaskFailMsg = "Integer math task 4 failed.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( unsigned short * ) pvParameters; + + /* Create the array we are going to use for our check calculation. */ + plArray = ( long * ) pvPortMalloc( ( size_t ) 250 * sizeof( long ) ); + + /* Keep filling the array, keeping a running total of the values placed in the + array. Then run through the array adding up all the values. If the two totals + do not match, stop the check variable from incrementing. */ + for( ;; ) + { + lTotal1 = ( long ) 0; + lTotal2 = ( long ) 0; + + for( usPosition = 0; usPosition < usArraySize; usPosition++ ) + { + plArray[ usPosition ] = ( long ) usPosition * ( long ) 12; + lTotal1 += ( long ) usPosition * ( long ) 12; + } + + taskYIELD(); + + for( usPosition = 0; usPosition < usArraySize; usPosition++ ) + { + lTotal2 += plArray[ usPosition ]; + } + + + if( lTotal1 != lTotal2 ) + { + vPrintDisplayMessage( &pcTaskFailMsg ); + sError = pdTRUE; + } + + taskYIELD(); + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct, increment the check + variable so we know this task is still running okay. */ + ( *pusTaskCheckVariable )++; + } + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +portBASE_TYPE xAreIntegerMathsTaskStillRunning( void ) +{ +/* Keep a history of the check variables so we know if they have been incremented +since the last call. */ +static unsigned short usLastTaskCheck[ intgNUMBER_OF_TASKS ] = { ( unsigned short ) 0 }; +portBASE_TYPE xReturn = pdTRUE, xTask; + + /* Check the maths tasks are still running by ensuring their check variables + are still incrementing. */ + for( xTask = 0; xTask < intgNUMBER_OF_TASKS; xTask++ ) + { + if( usTaskCheck[ xTask ] == usLastTaskCheck[ xTask ] ) + { + /* The check has not incremented so an error exists. */ + xReturn = pdFALSE; + } + + usLastTaskCheck[ xTask ] = usTaskCheck[ xTask ]; + } + + return xReturn; +} diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/print.c b/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/print.c new file mode 100644 index 0000000..3d554a1 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/print.c @@ -0,0 +1,144 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/** + * Manages a queue of strings that are waiting to be displayed. This is used to + * ensure mutual exclusion of console output. + * + * A task wishing to display a message will call vPrintDisplayMessage (), with a + * pointer to the string as the parameter. The pointer is posted onto the + * xPrintQueue queue. + * + * The task spawned in main. c blocks on xPrintQueue. When a message becomes + * available it calls pcPrintGetNextMessage () to obtain a pointer to the next + * string, then uses the functions defined in the portable layer FileIO. c to + * display the message. + * + * NOTE: + * Using console IO can disrupt real time performance - depending on the port. + * Standard C IO routines are not designed for real time applications. While + * standard IO is useful for demonstration and debugging an alternative method + * should be used if you actually require console IO as part of your application. + * + * \page PrintC print.c + * \ingroup DemoFiles + *
+ */ + +/* +Changes from V2.0.0 + + + Delay periods are now specified using variables and constants of + TickType_t rather than unsigned long. +*/ + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "queue.h" + +/* Demo program include files. */ +#include "print.h" + +static QueueHandle_t xPrintQueue; + +/*-----------------------------------------------------------*/ + +void vPrintInitialise( void ) +{ +const unsigned portBASE_TYPE uxQueueSize = 20; + + /* Create the queue on which errors will be reported. */ + xPrintQueue = xQueueCreate( uxQueueSize, ( unsigned portBASE_TYPE ) sizeof( char * ) ); +} +/*-----------------------------------------------------------*/ + +void vPrintDisplayMessage( const char * const * ppcMessageToSend ) +{ + #ifdef USE_STDIO + xQueueSend( xPrintQueue, ( void * ) ppcMessageToSend, ( TickType_t ) 0 ); + #else + /* Stop warnings. */ + ( void ) ppcMessageToSend; + #endif +} +/*-----------------------------------------------------------*/ + +const char *pcPrintGetNextMessage( TickType_t xPrintRate ) +{ +char *pcMessage; + + if( xQueueReceive( xPrintQueue, &pcMessage, xPrintRate ) == pdPASS ) + { + return pcMessage; + } + else + { + return NULL; + } +} + + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/semtest.c b/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/semtest.c new file mode 100644 index 0000000..f874162 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/Full/semtest.c @@ -0,0 +1,323 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/** + * Creates two sets of two tasks. The tasks within a set share a variable, access + * to which is guarded by a semaphore. + * + * Each task starts by attempting to obtain the semaphore. On obtaining a + * semaphore a task checks to ensure that the guarded variable has an expected + * value. It then clears the variable to zero before counting it back up to the + * expected value in increments of 1. After each increment the variable is checked + * to ensure it contains the value to which it was just set. When the starting + * value is again reached the task releases the semaphore giving the other task in + * the set a chance to do exactly the same thing. The starting value is high + * enough to ensure that a tick is likely to occur during the incrementing loop. + * + * An error is flagged if at any time during the process a shared variable is + * found to have a value other than that expected. Such an occurrence would + * suggest an error in the mutual exclusion mechanism by which access to the + * variable is restricted. + * + * The first set of two tasks poll their semaphore. The second set use blocking + * calls. + * + * \page SemTestC semtest.c + * \ingroup DemoFiles + *
+ */ + +/* +Changes from V1.2.0: + + + The tasks that operate at the idle priority now use a lower expected + count than those running at a higher priority. This prevents the low + priority tasks from signaling an error because they have not been + scheduled enough time for each of them to count the shared variable to + the high value. + +Changes from V2.0.0 + + + Delay periods are now specified using variables and constants of + TickType_t rather than unsigned long. + +Changes from V2.1.1 + + + The stack size now uses configMINIMAL_STACK_SIZE. + + String constants made file scope to decrease stack depth on 8051 port. +*/ + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "semphr.h" + +/* Demo app include files. */ +#include "semtest.h" +#include "print.h" + +/* The value to which the shared variables are counted. */ +#define semtstBLOCKING_EXPECTED_VALUE ( ( unsigned long ) 0xfff ) +#define semtstNON_BLOCKING_EXPECTED_VALUE ( ( unsigned long ) 0xff ) + +#define semtstSTACK_SIZE configMINIMAL_STACK_SIZE + +#define semtstNUM_TASKS ( 4 ) + +#define semtstDELAY_FACTOR ( ( TickType_t ) 10 ) + +/* The task function as described at the top of the file. */ +static void prvSemaphoreTest( void *pvParameters ); + +/* Structure used to pass parameters to each task. */ +typedef struct SEMAPHORE_PARAMETERS +{ + SemaphoreHandle_t xSemaphore; + volatile unsigned long *pulSharedVariable; + TickType_t xBlockTime; +} xSemaphoreParameters; + +/* Variables used to check that all the tasks are still running without errors. */ +static volatile short sCheckVariables[ semtstNUM_TASKS ] = { 0 }; +static volatile short sNextCheckVariable = 0; + +/* Strings to print if USE_STDIO is defined. */ +const char * const pcPollingSemaphoreTaskError = "Guarded shared variable in unexpected state.\r\n"; +const char * const pcSemaphoreTaskStart = "Guarded shared variable task started.\r\n"; + +/*-----------------------------------------------------------*/ + +void vStartSemaphoreTasks( unsigned portBASE_TYPE uxPriority ) +{ +xSemaphoreParameters *pxFirstSemaphoreParameters, *pxSecondSemaphoreParameters; +const TickType_t xBlockTime = ( TickType_t ) 100; + + /* Create the structure used to pass parameters to the first two tasks. */ + pxFirstSemaphoreParameters = ( xSemaphoreParameters * ) pvPortMalloc( sizeof( xSemaphoreParameters ) ); + + if( pxFirstSemaphoreParameters != NULL ) + { + /* Create the semaphore used by the first two tasks. */ + vSemaphoreCreateBinary( pxFirstSemaphoreParameters->xSemaphore ); + + if( pxFirstSemaphoreParameters->xSemaphore != NULL ) + { + /* Create the variable which is to be shared by the first two tasks. */ + pxFirstSemaphoreParameters->pulSharedVariable = ( unsigned long * ) pvPortMalloc( sizeof( unsigned long ) ); + + /* Initialise the share variable to the value the tasks expect. */ + *( pxFirstSemaphoreParameters->pulSharedVariable ) = semtstNON_BLOCKING_EXPECTED_VALUE; + + /* The first two tasks do not block on semaphore calls. */ + pxFirstSemaphoreParameters->xBlockTime = ( TickType_t ) 0; + + /* Spawn the first two tasks. As they poll they operate at the idle priority. */ + xTaskCreate( prvSemaphoreTest, "PolSEM1", semtstSTACK_SIZE, ( void * ) pxFirstSemaphoreParameters, tskIDLE_PRIORITY, ( TaskHandle_t * ) NULL ); + xTaskCreate( prvSemaphoreTest, "PolSEM2", semtstSTACK_SIZE, ( void * ) pxFirstSemaphoreParameters, tskIDLE_PRIORITY, ( TaskHandle_t * ) NULL ); + } + } + + /* Do exactly the same to create the second set of tasks, only this time + provide a block time for the semaphore calls. */ + pxSecondSemaphoreParameters = ( xSemaphoreParameters * ) pvPortMalloc( sizeof( xSemaphoreParameters ) ); + if( pxSecondSemaphoreParameters != NULL ) + { + vSemaphoreCreateBinary( pxSecondSemaphoreParameters->xSemaphore ); + + if( pxSecondSemaphoreParameters->xSemaphore != NULL ) + { + pxSecondSemaphoreParameters->pulSharedVariable = ( unsigned long * ) pvPortMalloc( sizeof( unsigned long ) ); + *( pxSecondSemaphoreParameters->pulSharedVariable ) = semtstBLOCKING_EXPECTED_VALUE; + pxSecondSemaphoreParameters->xBlockTime = xBlockTime / portTICK_PERIOD_MS; + + xTaskCreate( prvSemaphoreTest, "BlkSEM1", semtstSTACK_SIZE, ( void * ) pxSecondSemaphoreParameters, uxPriority, ( TaskHandle_t * ) NULL ); + xTaskCreate( prvSemaphoreTest, "BlkSEM2", semtstSTACK_SIZE, ( void * ) pxSecondSemaphoreParameters, uxPriority, ( TaskHandle_t * ) NULL ); + } + } +} +/*-----------------------------------------------------------*/ + +static void prvSemaphoreTest( void *pvParameters ) +{ +xSemaphoreParameters *pxParameters; +volatile unsigned long *pulSharedVariable, ulExpectedValue; +unsigned long ulCounter; +short sError = pdFALSE, sCheckVariableToUse; + + /* See which check variable to use. sNextCheckVariable is not semaphore + protected! */ + portENTER_CRITICAL(); + sCheckVariableToUse = sNextCheckVariable; + sNextCheckVariable++; + portEXIT_CRITICAL(); + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcSemaphoreTaskStart ); + + /* A structure is passed in as the parameter. This contains the shared + variable being guarded. */ + pxParameters = ( xSemaphoreParameters * ) pvParameters; + pulSharedVariable = pxParameters->pulSharedVariable; + + /* If we are blocking we use a much higher count to ensure loads of context + switches occur during the count. */ + if( pxParameters->xBlockTime > ( TickType_t ) 0 ) + { + ulExpectedValue = semtstBLOCKING_EXPECTED_VALUE; + } + else + { + ulExpectedValue = semtstNON_BLOCKING_EXPECTED_VALUE; + } + + for( ;; ) + { + /* Try to obtain the semaphore. */ + if( xSemaphoreTake( pxParameters->xSemaphore, pxParameters->xBlockTime ) == pdPASS ) + { + /* We have the semaphore and so expect any other tasks using the + shared variable to have left it in the state we expect to find + it. */ + if( *pulSharedVariable != ulExpectedValue ) + { + vPrintDisplayMessage( &pcPollingSemaphoreTaskError ); + sError = pdTRUE; + } + + /* Clear the variable, then count it back up to the expected value + before releasing the semaphore. Would expect a context switch or + two during this time. */ + for( ulCounter = ( unsigned long ) 0; ulCounter <= ulExpectedValue; ulCounter++ ) + { + *pulSharedVariable = ulCounter; + if( *pulSharedVariable != ulCounter ) + { + if( sError == pdFALSE ) + { + vPrintDisplayMessage( &pcPollingSemaphoreTaskError ); + } + sError = pdTRUE; + } + } + + /* Release the semaphore, and if no errors have occurred increment the check + variable. */ + if( xSemaphoreGive( pxParameters->xSemaphore ) == pdFALSE ) + { + vPrintDisplayMessage( &pcPollingSemaphoreTaskError ); + sError = pdTRUE; + } + + if( sError == pdFALSE ) + { + if( sCheckVariableToUse < semtstNUM_TASKS ) + { + ( sCheckVariables[ sCheckVariableToUse ] )++; + } + } + + /* If we have a block time then we are running at a priority higher + than the idle priority. This task takes a long time to complete + a cycle (deliberately so to test the guarding) so will be starving + out lower priority tasks. Block for some time to allow give lower + priority tasks some processor time. */ + vTaskDelay( pxParameters->xBlockTime * semtstDELAY_FACTOR ); + } + else + { + if( pxParameters->xBlockTime == ( TickType_t ) 0 ) + { + /* We have not got the semaphore yet, so no point using the + processor. We are not blocking when attempting to obtain the + semaphore. */ + taskYIELD(); + } + } + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +portBASE_TYPE xAreSemaphoreTasksStillRunning( void ) +{ +static short sLastCheckVariables[ semtstNUM_TASKS ] = { 0 }; +portBASE_TYPE xTask, xReturn = pdTRUE; + + for( xTask = 0; xTask < semtstNUM_TASKS; xTask++ ) + { + if( sLastCheckVariables[ xTask ] == sCheckVariables[ xTask ] ) + { + xReturn = pdFALSE; + } + + sLastCheckVariables[ xTask ] = sCheckVariables[ xTask ]; + } + + return xReturn; +} + + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/AltBlckQ.c b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/AltBlckQ.c new file mode 100644 index 0000000..a1d2cd0 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/AltBlckQ.c @@ -0,0 +1,332 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* + * This is a version of BlockQ.c that uses the alternative (Alt) API. + * + * Creates six tasks that operate on three queues as follows: + * + * The first two tasks send and receive an incrementing number to/from a queue. + * One task acts as a producer and the other as the consumer. The consumer is a + * higher priority than the producer and is set to block on queue reads. The queue + * only has space for one item - as soon as the producer posts a message on the + * queue the consumer will unblock, pre-empt the producer, and remove the item. + * + * The second two tasks work the other way around. Again the queue used only has + * enough space for one item. This time the consumer has a lower priority than the + * producer. The producer will try to post on the queue blocking when the queue is + * full. When the consumer wakes it will remove the item from the queue, causing + * the producer to unblock, pre-empt the consumer, and immediately re-fill the + * queue. + * + * The last two tasks use the same queue producer and consumer functions. This time the queue has + * enough space for lots of items and the tasks operate at the same priority. The + * producer will execute, placing items into the queue. The consumer will start + * executing when either the queue becomes full (causing the producer to block) or + * a context switch occurs (tasks of the same priority will time slice). + * + */ + + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +/* Demo program include files. */ +#include "AltBlckQ.h" + +#define blckqSTACK_SIZE configMINIMAL_STACK_SIZE +#define blckqNUM_TASK_SETS ( 3 ) + +/* Structure used to pass parameters to the blocking queue tasks. */ +typedef struct BLOCKING_QUEUE_PARAMETERS +{ + QueueHandle_t xQueue; /*< The queue to be used by the task. */ + TickType_t xBlockTime; /*< The block time to use on queue reads/writes. */ + volatile short *psCheckVariable; /*< Incremented on each successful cycle to check the task is still running. */ +} xBlockingQueueParameters; + +/* Task function that creates an incrementing number and posts it on a queue. */ +static portTASK_FUNCTION_PROTO( vBlockingQueueProducer, pvParameters ); + +/* Task function that removes the incrementing number from a queue and checks that +it is the expected number. */ +static portTASK_FUNCTION_PROTO( vBlockingQueueConsumer, pvParameters ); + +/* Variables which are incremented each time an item is removed from a queue, and +found to be the expected value. +These are used to check that the tasks are still running. */ +static volatile short sBlockingConsumerCount[ blckqNUM_TASK_SETS ] = { ( uint16_t ) 0, ( uint16_t ) 0, ( uint16_t ) 0 }; + +/* Variable which are incremented each time an item is posted on a queue. These +are used to check that the tasks are still running. */ +static volatile short sBlockingProducerCount[ blckqNUM_TASK_SETS ] = { ( uint16_t ) 0, ( uint16_t ) 0, ( uint16_t ) 0 }; + +/*-----------------------------------------------------------*/ + +void vStartAltBlockingQueueTasks( UBaseType_t uxPriority ) +{ +xBlockingQueueParameters *pxQueueParameters1, *pxQueueParameters2; +xBlockingQueueParameters *pxQueueParameters3, *pxQueueParameters4; +xBlockingQueueParameters *pxQueueParameters5, *pxQueueParameters6; +const UBaseType_t uxQueueSize1 = 1, uxQueueSize5 = 5; +const TickType_t xBlockTime = ( TickType_t ) 1000 / portTICK_PERIOD_MS; +const TickType_t xDontBlock = ( TickType_t ) 0; + + /* Create the first two tasks as described at the top of the file. */ + + /* First create the structure used to pass parameters to the consumer tasks. */ + pxQueueParameters1 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + + /* Create the queue used by the first two tasks to pass the incrementing number. + Pass a pointer to the queue in the parameter structure. */ + pxQueueParameters1->xQueue = xQueueCreate( uxQueueSize1, ( UBaseType_t ) sizeof( uint16_t ) ); + + /* The consumer is created first so gets a block time as described above. */ + pxQueueParameters1->xBlockTime = xBlockTime; + + /* Pass in the variable that this task is going to increment so we can check it + is still running. */ + pxQueueParameters1->psCheckVariable = &( sBlockingConsumerCount[ 0 ] ); + + /* Create the structure used to pass parameters to the producer task. */ + pxQueueParameters2 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + + /* Pass the queue to this task also, using the parameter structure. */ + pxQueueParameters2->xQueue = pxQueueParameters1->xQueue; + + /* The producer is not going to block - as soon as it posts the consumer will + wake and remove the item so the producer should always have room to post. */ + pxQueueParameters2->xBlockTime = xDontBlock; + + /* Pass in the variable that this task is going to increment so we can check + it is still running. */ + pxQueueParameters2->psCheckVariable = &( sBlockingProducerCount[ 0 ] ); + + + /* Note the producer has a lower priority than the consumer when the tasks are + spawned. */ + xTaskCreate( vBlockingQueueConsumer, "QConsB1", blckqSTACK_SIZE, ( void * ) pxQueueParameters1, uxPriority, NULL ); + xTaskCreate( vBlockingQueueProducer, "QProdB2", blckqSTACK_SIZE, ( void * ) pxQueueParameters2, tskIDLE_PRIORITY, NULL ); + + + + /* Create the second two tasks as described at the top of the file. This uses + the same mechanism but reverses the task priorities. */ + + pxQueueParameters3 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + pxQueueParameters3->xQueue = xQueueCreate( uxQueueSize1, ( UBaseType_t ) sizeof( uint16_t ) ); + pxQueueParameters3->xBlockTime = xDontBlock; + pxQueueParameters3->psCheckVariable = &( sBlockingProducerCount[ 1 ] ); + + pxQueueParameters4 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + pxQueueParameters4->xQueue = pxQueueParameters3->xQueue; + pxQueueParameters4->xBlockTime = xBlockTime; + pxQueueParameters4->psCheckVariable = &( sBlockingConsumerCount[ 1 ] ); + + xTaskCreate( vBlockingQueueConsumer, "QProdB3", blckqSTACK_SIZE, ( void * ) pxQueueParameters3, tskIDLE_PRIORITY, NULL ); + xTaskCreate( vBlockingQueueProducer, "QConsB4", blckqSTACK_SIZE, ( void * ) pxQueueParameters4, uxPriority, NULL ); + + + + /* Create the last two tasks as described above. The mechanism is again just + the same. This time both parameter structures are given a block time. */ + pxQueueParameters5 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + pxQueueParameters5->xQueue = xQueueCreate( uxQueueSize5, ( UBaseType_t ) sizeof( uint16_t ) ); + pxQueueParameters5->xBlockTime = xBlockTime; + pxQueueParameters5->psCheckVariable = &( sBlockingProducerCount[ 2 ] ); + + pxQueueParameters6 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + pxQueueParameters6->xQueue = pxQueueParameters5->xQueue; + pxQueueParameters6->xBlockTime = xBlockTime; + pxQueueParameters6->psCheckVariable = &( sBlockingConsumerCount[ 2 ] ); + + xTaskCreate( vBlockingQueueProducer, "QProdB5", blckqSTACK_SIZE, ( void * ) pxQueueParameters5, tskIDLE_PRIORITY, NULL ); + xTaskCreate( vBlockingQueueConsumer, "QConsB6", blckqSTACK_SIZE, ( void * ) pxQueueParameters6, tskIDLE_PRIORITY, NULL ); +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vBlockingQueueProducer, pvParameters ) +{ +uint16_t usValue = 0; +xBlockingQueueParameters *pxQueueParameters; +short sErrorEverOccurred = pdFALSE; + + #ifdef USE_STDIO + void vPrintDisplayMessage( const char * const * ppcMessageToSend ); + + const char * const pcTaskStartMsg = "Alt blocking queue producer task started.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + #endif + + pxQueueParameters = ( xBlockingQueueParameters * ) pvParameters; + + for( ;; ) + { + if( xQueueAltSendToBack( pxQueueParameters->xQueue, ( void * ) &usValue, pxQueueParameters->xBlockTime ) != pdPASS ) + { + sErrorEverOccurred = pdTRUE; + } + else + { + /* We have successfully posted a message, so increment the variable + used to check we are still running. */ + if( sErrorEverOccurred == pdFALSE ) + { + ( *pxQueueParameters->psCheckVariable )++; + } + + /* Increment the variable we are going to post next time round. The + consumer will expect the numbers to follow in numerical order. */ + ++usValue; + } + } +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vBlockingQueueConsumer, pvParameters ) +{ +uint16_t usData, usExpectedValue = 0; +xBlockingQueueParameters *pxQueueParameters; +short sErrorEverOccurred = pdFALSE; + + #ifdef USE_STDIO + void vPrintDisplayMessage( const char * const * ppcMessageToSend ); + + const char * const pcTaskStartMsg = "Alt blocking queue consumer task started.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + #endif + + pxQueueParameters = ( xBlockingQueueParameters * ) pvParameters; + + for( ;; ) + { + if( xQueueAltReceive( pxQueueParameters->xQueue, &usData, pxQueueParameters->xBlockTime ) == pdPASS ) + { + if( usData != usExpectedValue ) + { + /* Catch-up. */ + usExpectedValue = usData; + + sErrorEverOccurred = pdTRUE; + } + else + { + /* We have successfully received a message, so increment the + variable used to check we are still running. */ + if( sErrorEverOccurred == pdFALSE ) + { + ( *pxQueueParameters->psCheckVariable )++; + } + + /* Increment the value we expect to remove from the queue next time + round. */ + ++usExpectedValue; + } + } + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +BaseType_t xAreAltBlockingQueuesStillRunning( void ) +{ +static short sLastBlockingConsumerCount[ blckqNUM_TASK_SETS ] = { ( uint16_t ) 0, ( uint16_t ) 0, ( uint16_t ) 0 }; +static short sLastBlockingProducerCount[ blckqNUM_TASK_SETS ] = { ( uint16_t ) 0, ( uint16_t ) 0, ( uint16_t ) 0 }; +BaseType_t xReturn = pdPASS, xTasks; + + /* Not too worried about mutual exclusion on these variables as they are 16 + bits and we are only reading them. We also only care to see if they have + changed or not. + + Loop through each check variable to and return pdFALSE if any are found not + to have changed since the last call. */ + + for( xTasks = 0; xTasks < blckqNUM_TASK_SETS; xTasks++ ) + { + if( sBlockingConsumerCount[ xTasks ] == sLastBlockingConsumerCount[ xTasks ] ) + { + xReturn = pdFALSE; + } + sLastBlockingConsumerCount[ xTasks ] = sBlockingConsumerCount[ xTasks ]; + + + if( sBlockingProducerCount[ xTasks ] == sLastBlockingProducerCount[ xTasks ] ) + { + xReturn = pdFALSE; + } + sLastBlockingProducerCount[ xTasks ] = sBlockingProducerCount[ xTasks ]; + } + + return xReturn; +} + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/AltBlock.c b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/AltBlock.c new file mode 100644 index 0000000..f19e3f4 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/AltBlock.c @@ -0,0 +1,549 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* + * This is a version of BlockTim.c that uses the light weight API. + * + * This file contains some test scenarios that ensure tasks do not exit queue + * send or receive functions prematurely. A description of the tests is + * included within the code. + */ + +/* Kernel includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +/* Demo includes. */ +#include "AltBlock.h" + +/* Task priorities. */ +#define bktPRIMARY_PRIORITY ( 3 ) +#define bktSECONDARY_PRIORITY ( 2 ) + +/* Task behaviour. */ +#define bktQUEUE_LENGTH ( 5 ) +#define bktSHORT_WAIT ( ( ( TickType_t ) 20 ) / portTICK_PERIOD_MS ) +#define bktPRIMARY_BLOCK_TIME ( 10 ) +#define bktALLOWABLE_MARGIN ( 12 ) +#define bktTIME_TO_BLOCK ( 175 ) +#define bktDONT_BLOCK ( ( TickType_t ) 0 ) +#define bktRUN_INDICATOR ( ( UBaseType_t ) 0x55 ) + +/* The queue on which the tasks block. */ +static QueueHandle_t xTestQueue; + +/* Handle to the secondary task is required by the primary task for calls +to vTaskSuspend/Resume(). */ +static TaskHandle_t xSecondary; + +/* Used to ensure that tasks are still executing without error. */ +static BaseType_t xPrimaryCycles = 0, xSecondaryCycles = 0; +static BaseType_t xErrorOccurred = pdFALSE; + +/* Provides a simple mechanism for the primary task to know when the +secondary task has executed. */ +static volatile UBaseType_t xRunIndicator; + +/* The two test tasks. Their behaviour is commented within the files. */ +static void vPrimaryBlockTimeTestTask( void *pvParameters ); +static void vSecondaryBlockTimeTestTask( void *pvParameters ); + +/*-----------------------------------------------------------*/ + +void vCreateAltBlockTimeTasks( void ) +{ + /* Create the queue on which the two tasks block. */ + xTestQueue = xQueueCreate( bktQUEUE_LENGTH, sizeof( BaseType_t ) ); + + /* vQueueAddToRegistry() adds the queue to the queue registry, if one is + in use. The queue registry is provided as a means for kernel aware + debuggers to locate queues and has no purpose if a kernel aware debugger + is not being used. The call to vQueueAddToRegistry() will be removed + by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is + defined to be less than 1. */ + vQueueAddToRegistry( xTestQueue, "AltBlockQueue" ); + + + /* Create the two test tasks. */ + xTaskCreate( vPrimaryBlockTimeTestTask, "FBTest1", configMINIMAL_STACK_SIZE, NULL, bktPRIMARY_PRIORITY, NULL ); + xTaskCreate( vSecondaryBlockTimeTestTask, "FBTest2", configMINIMAL_STACK_SIZE, NULL, bktSECONDARY_PRIORITY, &xSecondary ); +} +/*-----------------------------------------------------------*/ + +static void vPrimaryBlockTimeTestTask( void *pvParameters ) +{ +BaseType_t xItem, xData; +TickType_t xTimeWhenBlocking; +TickType_t xTimeToBlock, xBlockedTime; + + #ifdef USE_STDIO + void vPrintDisplayMessage( const char * const * ppcMessageToSend ); + + const char * const pcTaskStartMsg = "Alt primary block time test started.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + #endif + + ( void ) pvParameters; + + for( ;; ) + { + /********************************************************************* + Test 1 + + Simple block time wakeup test on queue receives. */ + for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ ) + { + /* The queue is empty. Attempt to read from the queue using a block + time. When we wake, ensure the delta in time is as expected. */ + xTimeToBlock = bktPRIMARY_BLOCK_TIME << xItem; + + /* A critical section is used to minimise the jitter in the time + measurements. */ + portENTER_CRITICAL(); + { + xTimeWhenBlocking = xTaskGetTickCount(); + + /* We should unblock after xTimeToBlock having not received + anything on the queue. */ + if( xQueueAltReceive( xTestQueue, &xData, xTimeToBlock ) != errQUEUE_EMPTY ) + { + xErrorOccurred = pdTRUE; + } + + /* How long were we blocked for? */ + xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking; + } + portEXIT_CRITICAL(); + + if( xBlockedTime < xTimeToBlock ) + { + /* Should not have blocked for less than we requested. */ + xErrorOccurred = pdTRUE; + } + + if( xBlockedTime > ( xTimeToBlock + bktALLOWABLE_MARGIN ) ) + { + /* Should not have blocked for longer than we requested, + although we would not necessarily run as soon as we were + unblocked so a margin is allowed. */ + xErrorOccurred = pdTRUE; + } + } + + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + + /********************************************************************* + Test 2 + + Simple block time wakeup test on queue sends. + + First fill the queue. It should be empty so all sends should pass. */ + for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ ) + { + if( xQueueAltSendToBack( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + } + + for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ ) + { + /* The queue is full. Attempt to write to the queue using a block + time. When we wake, ensure the delta in time is as expected. */ + xTimeToBlock = bktPRIMARY_BLOCK_TIME << xItem; + + portENTER_CRITICAL(); + { + xTimeWhenBlocking = xTaskGetTickCount(); + + /* We should unblock after xTimeToBlock having not received + anything on the queue. */ + if( xQueueAltSendToBack( xTestQueue, &xItem, xTimeToBlock ) != errQUEUE_FULL ) + { + xErrorOccurred = pdTRUE; + } + + /* How long were we blocked for? */ + xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking; + } + portEXIT_CRITICAL(); + + if( xBlockedTime < xTimeToBlock ) + { + /* Should not have blocked for less than we requested. */ + xErrorOccurred = pdTRUE; + } + + if( xBlockedTime > ( xTimeToBlock + bktALLOWABLE_MARGIN ) ) + { + /* Should not have blocked for longer than we requested, + although we would not necessarily run as soon as we were + unblocked so a margin is allowed. */ + xErrorOccurred = pdTRUE; + } + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + + /********************************************************************* + Test 3 + + Wake the other task, it will block attempting to post to the queue. + When we read from the queue the other task will wake, but before it + can run we will post to the queue again. When the other task runs it + will find the queue still full, even though it was woken. It should + recognise that its block time has not expired and return to block for + the remains of its block time. + + Wake the other task so it blocks attempting to post to the already + full queue. */ + xRunIndicator = 0; + vTaskResume( xSecondary ); + + /* We need to wait a little to ensure the other task executes. */ + while( xRunIndicator != bktRUN_INDICATOR ) + { + /* The other task has not yet executed. */ + vTaskDelay( bktSHORT_WAIT ); + } + /* Make sure the other task is blocked on the queue. */ + vTaskDelay( bktSHORT_WAIT ); + xRunIndicator = 0; + + for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ ) + { + /* Now when we make space on the queue the other task should wake + but not execute as this task has higher priority. */ + if( xQueueAltReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + + /* Now fill the queue again before the other task gets a chance to + execute. If the other task had executed we would find the queue + full ourselves, and the other task have set xRunIndicator. */ + if( xQueueAltSendToBack( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + + if( xRunIndicator == bktRUN_INDICATOR ) + { + /* The other task should not have executed. */ + xErrorOccurred = pdTRUE; + } + + /* Raise the priority of the other task so it executes and blocks + on the queue again. */ + vTaskPrioritySet( xSecondary, bktPRIMARY_PRIORITY + 2 ); + + /* The other task should now have re-blocked without exiting the + queue function. */ + if( xRunIndicator == bktRUN_INDICATOR ) + { + /* The other task should not have executed outside of the + queue function. */ + xErrorOccurred = pdTRUE; + } + + /* Set the priority back down. */ + vTaskPrioritySet( xSecondary, bktSECONDARY_PRIORITY ); + } + + /* Let the other task timeout. When it unblockes it will check that it + unblocked at the correct time, then suspend itself. */ + while( xRunIndicator != bktRUN_INDICATOR ) + { + vTaskDelay( bktSHORT_WAIT ); + } + vTaskDelay( bktSHORT_WAIT ); + xRunIndicator = 0; + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /********************************************************************* + Test 4 + + As per test 3 - but with the send and receive the other way around. + The other task blocks attempting to read from the queue. + + Empty the queue. We should find that it is full. */ + for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ ) + { + if( xQueueAltReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + } + + /* Wake the other task so it blocks attempting to read from the + already empty queue. */ + vTaskResume( xSecondary ); + + /* We need to wait a little to ensure the other task executes. */ + while( xRunIndicator != bktRUN_INDICATOR ) + { + vTaskDelay( bktSHORT_WAIT ); + } + vTaskDelay( bktSHORT_WAIT ); + xRunIndicator = 0; + + for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ ) + { + /* Now when we place an item on the queue the other task should + wake but not execute as this task has higher priority. */ + if( xQueueAltSendToBack( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + + /* Now empty the queue again before the other task gets a chance to + execute. If the other task had executed we would find the queue + empty ourselves, and the other task would be suspended. */ + if( xQueueAltReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + + if( xRunIndicator == bktRUN_INDICATOR ) + { + /* The other task should not have executed. */ + xErrorOccurred = pdTRUE; + } + + /* Raise the priority of the other task so it executes and blocks + on the queue again. */ + vTaskPrioritySet( xSecondary, bktPRIMARY_PRIORITY + 2 ); + + /* The other task should now have re-blocked without exiting the + queue function. */ + if( xRunIndicator == bktRUN_INDICATOR ) + { + /* The other task should not have executed outside of the + queue function. */ + xErrorOccurred = pdTRUE; + } + vTaskPrioritySet( xSecondary, bktSECONDARY_PRIORITY ); + } + + /* Let the other task timeout. When it unblockes it will check that it + unblocked at the correct time, then suspend itself. */ + while( xRunIndicator != bktRUN_INDICATOR ) + { + vTaskDelay( bktSHORT_WAIT ); + } + vTaskDelay( bktSHORT_WAIT ); + + xPrimaryCycles++; + } +} +/*-----------------------------------------------------------*/ + +static void vSecondaryBlockTimeTestTask( void *pvParameters ) +{ +TickType_t xTimeWhenBlocking, xBlockedTime; +BaseType_t xData; + + #ifdef USE_STDIO + void vPrintDisplayMessage( const char * const * ppcMessageToSend ); + + const char * const pcTaskStartMsg = "Alt secondary block time test started.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + #endif + + ( void ) pvParameters; + + for( ;; ) + { + /********************************************************************* + Test 1 and 2 + + This task does does not participate in these tests. */ + vTaskSuspend( NULL ); + + /********************************************************************* + Test 3 + + The first thing we do is attempt to read from the queue. It should be + full so we block. Note the time before we block so we can check the + wake time is as per that expected. */ + portENTER_CRITICAL(); + { + xTimeWhenBlocking = xTaskGetTickCount(); + + /* We should unblock after bktTIME_TO_BLOCK having not received + anything on the queue. */ + xData = 0; + xRunIndicator = bktRUN_INDICATOR; + if( xQueueAltSendToBack( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_FULL ) + { + xErrorOccurred = pdTRUE; + } + + /* How long were we inside the send function? */ + xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking; + } + portEXIT_CRITICAL(); + + /* We should not have blocked for less time than bktTIME_TO_BLOCK. */ + if( xBlockedTime < bktTIME_TO_BLOCK ) + { + xErrorOccurred = pdTRUE; + } + + /* We should of not blocked for much longer than bktALLOWABLE_MARGIN + either. A margin is permitted as we would not necessarily run as + soon as we unblocked. */ + if( xBlockedTime > ( bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN ) ) + { + xErrorOccurred = pdTRUE; + } + + /* Suspend ready for test 3. */ + xRunIndicator = bktRUN_INDICATOR; + vTaskSuspend( NULL ); + + /********************************************************************* + Test 4 + + As per test three, but with the send and receive reversed. */ + portENTER_CRITICAL(); + { + xTimeWhenBlocking = xTaskGetTickCount(); + + /* We should unblock after bktTIME_TO_BLOCK having not received + anything on the queue. */ + xRunIndicator = bktRUN_INDICATOR; + if( xQueueAltReceive( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_EMPTY ) + { + xErrorOccurred = pdTRUE; + } + + xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking; + } + portEXIT_CRITICAL(); + + /* We should not have blocked for less time than bktTIME_TO_BLOCK. */ + if( xBlockedTime < bktTIME_TO_BLOCK ) + { + xErrorOccurred = pdTRUE; + } + + /* We should of not blocked for much longer than bktALLOWABLE_MARGIN + either. A margin is permitted as we would not necessarily run as soon + as we unblocked. */ + if( xBlockedTime > ( bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN ) ) + { + xErrorOccurred = pdTRUE; + } + + xRunIndicator = bktRUN_INDICATOR; + + xSecondaryCycles++; + } +} +/*-----------------------------------------------------------*/ + +BaseType_t xAreAltBlockTimeTestTasksStillRunning( void ) +{ +static BaseType_t xLastPrimaryCycleCount = 0, xLastSecondaryCycleCount = 0; +BaseType_t xReturn = pdPASS; + + /* Have both tasks performed at least one cycle since this function was + last called? */ + if( xPrimaryCycles == xLastPrimaryCycleCount ) + { + xReturn = pdFAIL; + } + + if( xSecondaryCycles == xLastSecondaryCycleCount ) + { + xReturn = pdFAIL; + } + + if( xErrorOccurred == pdTRUE ) + { + xReturn = pdFAIL; + } + + xLastSecondaryCycleCount = xSecondaryCycles; + xLastPrimaryCycleCount = xPrimaryCycles; + + return xReturn; +} diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/AltPollQ.c b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/AltPollQ.c new file mode 100644 index 0000000..57b7322 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/AltPollQ.c @@ -0,0 +1,275 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* + * This is a version of PollQ.c that uses the alternative (Alt) API. + * + * Creates two tasks that communicate over a single queue. One task acts as a + * producer, the other a consumer. + * + * The producer loops for three iteration, posting an incrementing number onto the + * queue each cycle. It then delays for a fixed period before doing exactly the + * same again. + * + * The consumer loops emptying the queue. Each item removed from the queue is + * checked to ensure it contains the expected value. When the queue is empty it + * blocks for a fixed period, then does the same again. + * + * All queue access is performed without blocking. The consumer completely empties + * the queue each time it runs so the producer should never find the queue full. + * + * An error is flagged if the consumer obtains an unexpected value or the producer + * find the queue is full. + */ + +/* +Changes from V2.0.0 + + + Delay periods are now specified using variables and constants of + TickType_t rather than uint32_t. +*/ + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +/* Demo program include files. */ +#include "AltPollQ.h" + +#define pollqSTACK_SIZE configMINIMAL_STACK_SIZE +#define pollqQUEUE_SIZE ( 10 ) +#define pollqPRODUCER_DELAY ( ( TickType_t ) 200 / portTICK_PERIOD_MS ) +#define pollqCONSUMER_DELAY ( pollqPRODUCER_DELAY - ( TickType_t ) ( 20 / portTICK_PERIOD_MS ) ) +#define pollqNO_DELAY ( ( TickType_t ) 0 ) +#define pollqVALUES_TO_PRODUCE ( ( BaseType_t ) 3 ) +#define pollqINITIAL_VALUE ( ( BaseType_t ) 0 ) + +/* The task that posts the incrementing number onto the queue. */ +static portTASK_FUNCTION_PROTO( vPolledQueueProducer, pvParameters ); + +/* The task that empties the queue. */ +static portTASK_FUNCTION_PROTO( vPolledQueueConsumer, pvParameters ); + +/* Variables that are used to check that the tasks are still running with no +errors. */ +static volatile BaseType_t xPollingConsumerCount = pollqINITIAL_VALUE, xPollingProducerCount = pollqINITIAL_VALUE; + +/*-----------------------------------------------------------*/ + +void vStartAltPolledQueueTasks( UBaseType_t uxPriority ) +{ +static QueueHandle_t xPolledQueue; + + /* Create the queue used by the producer and consumer. */ + xPolledQueue = xQueueCreate( pollqQUEUE_SIZE, ( UBaseType_t ) sizeof( uint16_t ) ); + + /* vQueueAddToRegistry() adds the queue to the queue registry, if one is + in use. The queue registry is provided as a means for kernel aware + debuggers to locate queues and has no purpose if a kernel aware debugger + is not being used. The call to vQueueAddToRegistry() will be removed + by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is + defined to be less than 1. */ + vQueueAddToRegistry( xPolledQueue, "AltPollQueue" ); + + + /* Spawn the producer and consumer. */ + xTaskCreate( vPolledQueueConsumer, "QConsNB", pollqSTACK_SIZE, ( void * ) &xPolledQueue, uxPriority, ( TaskHandle_t * ) NULL ); + xTaskCreate( vPolledQueueProducer, "QProdNB", pollqSTACK_SIZE, ( void * ) &xPolledQueue, uxPriority, ( TaskHandle_t * ) NULL ); +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vPolledQueueProducer, pvParameters ) +{ +uint16_t usValue = ( uint16_t ) 0; +BaseType_t xError = pdFALSE, xLoop; + + #ifdef USE_STDIO + void vPrintDisplayMessage( const char * const * ppcMessageToSend ); + + const char * const pcTaskStartMsg = "Alt polling queue producer task started.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + #endif + + for( ;; ) + { + for( xLoop = 0; xLoop < pollqVALUES_TO_PRODUCE; xLoop++ ) + { + /* Send an incrementing number on the queue without blocking. */ + if( xQueueAltSendToBack( *( ( QueueHandle_t * ) pvParameters ), ( void * ) &usValue, pollqNO_DELAY ) != pdPASS ) + { + /* We should never find the queue full so if we get here there + has been an error. */ + xError = pdTRUE; + } + else + { + if( xError == pdFALSE ) + { + /* If an error has ever been recorded we stop incrementing the + check variable. */ + portENTER_CRITICAL(); + xPollingProducerCount++; + portEXIT_CRITICAL(); + } + + /* Update the value we are going to post next time around. */ + usValue++; + } + } + + /* Wait before we start posting again to ensure the consumer runs and + empties the queue. */ + vTaskDelay( pollqPRODUCER_DELAY ); + } +} /*lint !e818 Function prototype must conform to API. */ +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vPolledQueueConsumer, pvParameters ) +{ +uint16_t usData, usExpectedValue = ( uint16_t ) 0; +BaseType_t xError = pdFALSE; + + #ifdef USE_STDIO + void vPrintDisplayMessage( const char * const * ppcMessageToSend ); + + const char * const pcTaskStartMsg = "Alt blocking queue consumer task started.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + #endif + + for( ;; ) + { + /* Loop until the queue is empty. */ + while( uxQueueMessagesWaiting( *( ( QueueHandle_t * ) pvParameters ) ) ) + { + if( xQueueAltReceive( *( ( QueueHandle_t * ) pvParameters ), &usData, pollqNO_DELAY ) == pdPASS ) + { + if( usData != usExpectedValue ) + { + /* This is not what we expected to receive so an error has + occurred. */ + xError = pdTRUE; + + /* Catch-up to the value we received so our next expected + value should again be correct. */ + usExpectedValue = usData; + } + else + { + if( xError == pdFALSE ) + { + /* Only increment the check variable if no errors have + occurred. */ + portENTER_CRITICAL(); + xPollingConsumerCount++; + portEXIT_CRITICAL(); + } + } + + /* Next time round we would expect the number to be one higher. */ + usExpectedValue++; + } + } + + /* Now the queue is empty we block, allowing the producer to place more + items in the queue. */ + vTaskDelay( pollqCONSUMER_DELAY ); + } +} /*lint !e818 Function prototype must conform to API. */ +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running with no errors. */ +BaseType_t xAreAltPollingQueuesStillRunning( void ) +{ +BaseType_t xReturn; + + /* Check both the consumer and producer poll count to check they have both + been changed since out last trip round. We do not need a critical section + around the check variables as this is called from a higher priority than + the other tasks that access the same variables. */ + if( ( xPollingConsumerCount == pollqINITIAL_VALUE ) || + ( xPollingProducerCount == pollqINITIAL_VALUE ) + ) + { + xReturn = pdFALSE; + } + else + { + xReturn = pdTRUE; + } + + /* Set the check variables back down so we know if they have been + incremented the next time around. */ + xPollingConsumerCount = pollqINITIAL_VALUE; + xPollingProducerCount = pollqINITIAL_VALUE; + + return xReturn; +} diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/AltQTest.c b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/AltQTest.c new file mode 100644 index 0000000..188d3b0 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/AltQTest.c @@ -0,0 +1,587 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +/* + * This file implements the same demo and test as GenQTest.c, but uses the + * light weight API in place of the fully featured API. + * + * See the comments at the top of GenQTest.c for a description. + */ + + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "semphr.h" + +/* Demo program include files. */ +#include "AltQTest.h" + +#define genqQUEUE_LENGTH ( 5 ) +#define genqNO_BLOCK ( 0 ) + +#define genqMUTEX_LOW_PRIORITY ( tskIDLE_PRIORITY ) +#define genqMUTEX_TEST_PRIORITY ( tskIDLE_PRIORITY + 1 ) +#define genqMUTEX_MEDIUM_PRIORITY ( tskIDLE_PRIORITY + 2 ) +#define genqMUTEX_HIGH_PRIORITY ( tskIDLE_PRIORITY + 3 ) + +/*-----------------------------------------------------------*/ + +/* + * Tests the behaviour of the xQueueAltSendToFront() and xQueueAltSendToBack() + * macros by using both to fill a queue, then reading from the queue to + * check the resultant queue order is as expected. Queue data is also + * peeked. + */ +static void prvSendFrontAndBackTest( void *pvParameters ); + +/* + * The following three tasks are used to demonstrate the mutex behaviour. + * Each task is given a different priority to demonstrate the priority + * inheritance mechanism. + * + * The low priority task obtains a mutex. After this a high priority task + * attempts to obtain the same mutex, causing its priority to be inherited + * by the low priority task. The task with the inherited high priority then + * resumes a medium priority task to ensure it is not blocked by the medium + * priority task while it holds the inherited high priority. Once the mutex + * is returned the task with the inherited priority returns to its original + * low priority, and is therefore immediately preempted by first the high + * priority task and then the medium prioroity task before it can continue. + */ +static void prvLowPriorityMutexTask( void *pvParameters ); +static void prvMediumPriorityMutexTask( void *pvParameters ); +static void prvHighPriorityMutexTask( void *pvParameters ); + +/*-----------------------------------------------------------*/ + +/* Flag that will be latched to pdTRUE should any unexpected behaviour be +detected in any of the tasks. */ +static BaseType_t xErrorDetected = pdFALSE; + +/* Counters that are incremented on each cycle of a test. This is used to +detect a stalled task - a test that is no longer running. */ +static volatile uint32_t ulLoopCounter = 0; +static volatile uint32_t ulLoopCounter2 = 0; + +/* The variable that is guarded by the mutex in the mutex demo tasks. */ +static volatile uint32_t ulGuardedVariable = 0; + +/* Handles used in the mutext test to suspend and resume the high and medium +priority mutex test tasks. */ +static TaskHandle_t xHighPriorityMutexTask, xMediumPriorityMutexTask; + +/*-----------------------------------------------------------*/ + +void vStartAltGenericQueueTasks( UBaseType_t uxPriority ) +{ +QueueHandle_t xQueue; +SemaphoreHandle_t xMutex; + + /* Create the queue that we are going to use for the + prvSendFrontAndBackTest demo. */ + xQueue = xQueueCreate( genqQUEUE_LENGTH, sizeof( uint32_t ) ); + + /* vQueueAddToRegistry() adds the queue to the queue registry, if one is + in use. The queue registry is provided as a means for kernel aware + debuggers to locate queues and has no purpose if a kernel aware debugger + is not being used. The call to vQueueAddToRegistry() will be removed + by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is + defined to be less than 1. */ + vQueueAddToRegistry( xQueue, "Alt_Gen_Test_Queue" ); + + /* Create the demo task and pass it the queue just created. We are + passing the queue handle by value so it does not matter that it is + declared on the stack here. */ + xTaskCreate( prvSendFrontAndBackTest, "FGenQ", configMINIMAL_STACK_SIZE, ( void * ) xQueue, uxPriority, NULL ); + + /* Create the mutex used by the prvMutexTest task. */ + xMutex = xSemaphoreCreateMutex(); + + /* vQueueAddToRegistry() adds the mutex to the registry, if one is + in use. The registry is provided as a means for kernel aware + debuggers to locate mutex and has no purpose if a kernel aware debugger + is not being used. The call to vQueueAddToRegistry() will be removed + by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is + defined to be less than 1. */ + vQueueAddToRegistry( ( QueueHandle_t ) xMutex, "Alt_Q_Mutex" ); + + /* Create the mutex demo tasks and pass it the mutex just created. We are + passing the mutex handle by value so it does not matter that it is declared + on the stack here. */ + xTaskCreate( prvLowPriorityMutexTask, "FMuLow", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_LOW_PRIORITY, NULL ); + xTaskCreate( prvMediumPriorityMutexTask, "FMuMed", configMINIMAL_STACK_SIZE, NULL, genqMUTEX_MEDIUM_PRIORITY, &xMediumPriorityMutexTask ); + xTaskCreate( prvHighPriorityMutexTask, "FMuHigh", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_HIGH_PRIORITY, &xHighPriorityMutexTask ); +} +/*-----------------------------------------------------------*/ + +static void prvSendFrontAndBackTest( void *pvParameters ) +{ +uint32_t ulData, ulData2; +QueueHandle_t xQueue; + + #ifdef USE_STDIO + void vPrintDisplayMessage( const char * const * ppcMessageToSend ); + + const char * const pcTaskStartMsg = "Alt queue SendToFront/SendToBack/Peek test started.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + #endif + + xQueue = ( QueueHandle_t ) pvParameters; + + for( ;; ) + { + /* The queue is empty, so sending an item to the back of the queue + should have the same efect as sending it to the front of the queue. + + First send to the front and check everything is as expected. */ + xQueueAltSendToFront( xQueue, ( void * ) &ulLoopCounter, genqNO_BLOCK ); + + if( uxQueueMessagesWaiting( xQueue ) != 1 ) + { + xErrorDetected = pdTRUE; + } + + if( xQueueAltReceive( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + /* The data we sent to the queue should equal the data we just received + from the queue. */ + if( ulLoopCounter != ulData ) + { + xErrorDetected = pdTRUE; + } + + /* Then do the same, sending the data to the back, checking everything + is as expected. */ + if( uxQueueMessagesWaiting( xQueue ) != 0 ) + { + xErrorDetected = pdTRUE; + } + + xQueueAltSendToBack( xQueue, ( void * ) &ulLoopCounter, genqNO_BLOCK ); + + if( uxQueueMessagesWaiting( xQueue ) != 1 ) + { + xErrorDetected = pdTRUE; + } + + if( xQueueAltReceive( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + if( uxQueueMessagesWaiting( xQueue ) != 0 ) + { + xErrorDetected = pdTRUE; + } + + /* The data we sent to the queue should equal the data we just received + from the queue. */ + if( ulLoopCounter != ulData ) + { + xErrorDetected = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + + + /* Place 2, 3, 4 into the queue, adding items to the back of the queue. */ + for( ulData = 2; ulData < 5; ulData++ ) + { + xQueueAltSendToBack( xQueue, ( void * ) &ulData, genqNO_BLOCK ); + } + + /* Now the order in the queue should be 2, 3, 4, with 2 being the first + thing to be read out. Now add 1 then 0 to the front of the queue. */ + if( uxQueueMessagesWaiting( xQueue ) != 3 ) + { + xErrorDetected = pdTRUE; + } + ulData = 1; + xQueueAltSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ); + ulData = 0; + xQueueAltSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ); + + /* Now the queue should be full, and when we read the data out we + should receive 0, 1, 2, 3, 4. */ + if( uxQueueMessagesWaiting( xQueue ) != 5 ) + { + xErrorDetected = pdTRUE; + } + + if( xQueueAltSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL ) + { + xErrorDetected = pdTRUE; + } + + if( xQueueAltSendToBack( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL ) + { + xErrorDetected = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* Check the data we read out is in the expected order. */ + for( ulData = 0; ulData < genqQUEUE_LENGTH; ulData++ ) + { + /* Try peeking the data first. */ + if( xQueueAltPeek( xQueue, &ulData2, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + if( ulData != ulData2 ) + { + xErrorDetected = pdTRUE; + } + + + /* Now try receiving the data for real. The value should be the + same. Clobber the value first so we know we really received it. */ + ulData2 = ~ulData2; + if( xQueueAltReceive( xQueue, &ulData2, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + if( ulData != ulData2 ) + { + xErrorDetected = pdTRUE; + } + } + + /* The queue should now be empty again. */ + if( uxQueueMessagesWaiting( xQueue ) != 0 ) + { + xErrorDetected = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + + /* Our queue is empty once more, add 10, 11 to the back. */ + ulData = 10; + if( xQueueAltSendToBack( xQueue, &ulData, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + ulData = 11; + if( xQueueAltSendToBack( xQueue, &ulData, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + if( uxQueueMessagesWaiting( xQueue ) != 2 ) + { + xErrorDetected = pdTRUE; + } + + /* Now we should have 10, 11 in the queue. Add 7, 8, 9 to the + front. */ + for( ulData = 9; ulData >= 7; ulData-- ) + { + if( xQueueAltSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + } + + /* Now check that the queue is full, and that receiving data provides + the expected sequence of 7, 8, 9, 10, 11. */ + if( uxQueueMessagesWaiting( xQueue ) != 5 ) + { + xErrorDetected = pdTRUE; + } + + if( xQueueAltSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL ) + { + xErrorDetected = pdTRUE; + } + + if( xQueueAltSendToBack( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL ) + { + xErrorDetected = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* Check the data we read out is in the expected order. */ + for( ulData = 7; ulData < ( 7 + genqQUEUE_LENGTH ); ulData++ ) + { + if( xQueueAltReceive( xQueue, &ulData2, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + if( ulData != ulData2 ) + { + xErrorDetected = pdTRUE; + } + } + + if( uxQueueMessagesWaiting( xQueue ) != 0 ) + { + xErrorDetected = pdTRUE; + } + + ulLoopCounter++; + } +} +/*-----------------------------------------------------------*/ + +static void prvLowPriorityMutexTask( void *pvParameters ) +{ +SemaphoreHandle_t xMutex = ( SemaphoreHandle_t ) pvParameters; + + #ifdef USE_STDIO + void vPrintDisplayMessage( const char * const * ppcMessageToSend ); + + const char * const pcTaskStartMsg = "Fast mutex with priority inheritance test started.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + #endif + + ( void ) pvParameters; + + + for( ;; ) + { + /* Take the mutex. It should be available now. */ + if( xSemaphoreAltTake( xMutex, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + /* Set our guarded variable to a known start value. */ + ulGuardedVariable = 0; + + /* Our priority should be as per that assigned when the task was + created. */ + if( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY ) + { + xErrorDetected = pdTRUE; + } + + /* Now unsuspend the high priority task. This will attempt to take the + mutex, and block when it finds it cannot obtain it. */ + vTaskResume( xHighPriorityMutexTask ); + + /* We should now have inherited the prioritoy of the high priority task, + as by now it will have attempted to get the mutex. */ + if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY ) + { + xErrorDetected = pdTRUE; + } + + /* We can attempt to set our priority to the test priority - between the + idle priority and the medium/high test priorities, but our actual + prioroity should remain at the high priority. */ + vTaskPrioritySet( NULL, genqMUTEX_TEST_PRIORITY ); + if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY ) + { + xErrorDetected = pdTRUE; + } + + /* Now unsuspend the medium priority task. This should not run as our + inherited priority is above that of the medium priority task. */ + vTaskResume( xMediumPriorityMutexTask ); + + /* If the did run then it will have incremented our guarded variable. */ + if( ulGuardedVariable != 0 ) + { + xErrorDetected = pdTRUE; + } + + /* When we give back the semaphore our priority should be disinherited + back to the priority to which we attempted to set ourselves. This means + that when the high priority task next blocks, the medium priority task + should execute and increment the guarded variable. When we next run + both the high and medium priority tasks will have been suspended again. */ + if( xSemaphoreAltGive( xMutex ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + /* Check that the guarded variable did indeed increment... */ + if( ulGuardedVariable != 1 ) + { + xErrorDetected = pdTRUE; + } + + /* ... and that our priority has been disinherited to + genqMUTEX_TEST_PRIORITY. */ + if( uxTaskPriorityGet( NULL ) != genqMUTEX_TEST_PRIORITY ) + { + xErrorDetected = pdTRUE; + } + + /* Set our priority back to our original priority ready for the next + loop around this test. */ + vTaskPrioritySet( NULL, genqMUTEX_LOW_PRIORITY ); + + /* Just to show we are still running. */ + ulLoopCounter2++; + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + } +} +/*-----------------------------------------------------------*/ + +static void prvMediumPriorityMutexTask( void *pvParameters ) +{ + ( void ) pvParameters; + + for( ;; ) + { + /* The medium priority task starts by suspending itself. The low + priority task will unsuspend this task when required. */ + vTaskSuspend( NULL ); + + /* When this task unsuspends all it does is increment the guarded + variable, this is so the low priority task knows that it has + executed. */ + ulGuardedVariable++; + } +} +/*-----------------------------------------------------------*/ + +static void prvHighPriorityMutexTask( void *pvParameters ) +{ +SemaphoreHandle_t xMutex = ( SemaphoreHandle_t ) pvParameters; + + ( void ) pvParameters; + + for( ;; ) + { + /* The high priority task starts by suspending itself. The low + priority task will unsuspend this task when required. */ + vTaskSuspend( NULL ); + + /* When this task unsuspends all it does is attempt to obtain + the mutex. It should find the mutex is not available so a + block time is specified. */ + if( xSemaphoreAltTake( xMutex, portMAX_DELAY ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + /* When we eventually obtain the mutex we just give it back then + return to suspend ready for the next test. */ + if( xSemaphoreAltGive( xMutex ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +BaseType_t xAreAltGenericQueueTasksStillRunning( void ) +{ +static uint32_t ulLastLoopCounter = 0, ulLastLoopCounter2 = 0; + + /* If the demo task is still running then we expect the loopcounters to + have incremented since this function was last called. */ + if( ulLastLoopCounter == ulLoopCounter ) + { + xErrorDetected = pdTRUE; + } + + if( ulLastLoopCounter2 == ulLoopCounter2 ) + { + xErrorDetected = pdTRUE; + } + + ulLastLoopCounter = ulLoopCounter; + ulLastLoopCounter2 = ulLoopCounter2; + + /* Errors detected in the task itself will have latched xErrorDetected + to true. */ + + return !xErrorDetected; +} + + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/BlockQ.c b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/BlockQ.c new file mode 100644 index 0000000..b8db390 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/BlockQ.c @@ -0,0 +1,324 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* + * Creates six tasks that operate on three queues as follows: + * + * The first two tasks send and receive an incrementing number to/from a queue. + * One task acts as a producer and the other as the consumer. The consumer is a + * higher priority than the producer and is set to block on queue reads. The queue + * only has space for one item - as soon as the producer posts a message on the + * queue the consumer will unblock, pre-empt the producer, and remove the item. + * + * The second two tasks work the other way around. Again the queue used only has + * enough space for one item. This time the consumer has a lower priority than the + * producer. The producer will try to post on the queue blocking when the queue is + * full. When the consumer wakes it will remove the item from the queue, causing + * the producer to unblock, pre-empt the consumer, and immediately re-fill the + * queue. + * + * The last two tasks use the same queue producer and consumer functions. This time the queue has + * enough space for lots of items and the tasks operate at the same priority. The + * producer will execute, placing items into the queue. The consumer will start + * executing when either the queue becomes full (causing the producer to block) or + * a context switch occurs (tasks of the same priority will time slice). + * + */ + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +/* Demo program include files. */ +#include "BlockQ.h" + +#define blckqSTACK_SIZE configMINIMAL_STACK_SIZE +#define blckqNUM_TASK_SETS ( 3 ) + +/* Structure used to pass parameters to the blocking queue tasks. */ +typedef struct BLOCKING_QUEUE_PARAMETERS +{ + QueueHandle_t xQueue; /*< The queue to be used by the task. */ + TickType_t xBlockTime; /*< The block time to use on queue reads/writes. */ + volatile short *psCheckVariable; /*< Incremented on each successful cycle to check the task is still running. */ +} xBlockingQueueParameters; + +/* Task function that creates an incrementing number and posts it on a queue. */ +static portTASK_FUNCTION_PROTO( vBlockingQueueProducer, pvParameters ); + +/* Task function that removes the incrementing number from a queue and checks that +it is the expected number. */ +static portTASK_FUNCTION_PROTO( vBlockingQueueConsumer, pvParameters ); + +/* Variables which are incremented each time an item is removed from a queue, and +found to be the expected value. +These are used to check that the tasks are still running. */ +static volatile short sBlockingConsumerCount[ blckqNUM_TASK_SETS ] = { ( uint16_t ) 0, ( uint16_t ) 0, ( uint16_t ) 0 }; + +/* Variable which are incremented each time an item is posted on a queue. These +are used to check that the tasks are still running. */ +static volatile short sBlockingProducerCount[ blckqNUM_TASK_SETS ] = { ( uint16_t ) 0, ( uint16_t ) 0, ( uint16_t ) 0 }; + +/*-----------------------------------------------------------*/ + +void vStartBlockingQueueTasks( UBaseType_t uxPriority ) +{ +xBlockingQueueParameters *pxQueueParameters1, *pxQueueParameters2; +xBlockingQueueParameters *pxQueueParameters3, *pxQueueParameters4; +xBlockingQueueParameters *pxQueueParameters5, *pxQueueParameters6; +const UBaseType_t uxQueueSize1 = 1, uxQueueSize5 = 5; +const TickType_t xBlockTime = ( TickType_t ) 1000 / portTICK_PERIOD_MS; +const TickType_t xDontBlock = ( TickType_t ) 0; + + /* Create the first two tasks as described at the top of the file. */ + + /* First create the structure used to pass parameters to the consumer tasks. */ + pxQueueParameters1 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + + /* Create the queue used by the first two tasks to pass the incrementing number. + Pass a pointer to the queue in the parameter structure. */ + pxQueueParameters1->xQueue = xQueueCreate( uxQueueSize1, ( UBaseType_t ) sizeof( uint16_t ) ); + + /* The consumer is created first so gets a block time as described above. */ + pxQueueParameters1->xBlockTime = xBlockTime; + + /* Pass in the variable that this task is going to increment so we can check it + is still running. */ + pxQueueParameters1->psCheckVariable = &( sBlockingConsumerCount[ 0 ] ); + + /* Create the structure used to pass parameters to the producer task. */ + pxQueueParameters2 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + + /* Pass the queue to this task also, using the parameter structure. */ + pxQueueParameters2->xQueue = pxQueueParameters1->xQueue; + + /* The producer is not going to block - as soon as it posts the consumer will + wake and remove the item so the producer should always have room to post. */ + pxQueueParameters2->xBlockTime = xDontBlock; + + /* Pass in the variable that this task is going to increment so we can check + it is still running. */ + pxQueueParameters2->psCheckVariable = &( sBlockingProducerCount[ 0 ] ); + + + /* Note the producer has a lower priority than the consumer when the tasks are + spawned. */ + xTaskCreate( vBlockingQueueConsumer, "QConsB1", blckqSTACK_SIZE, ( void * ) pxQueueParameters1, uxPriority, NULL ); + xTaskCreate( vBlockingQueueProducer, "QProdB2", blckqSTACK_SIZE, ( void * ) pxQueueParameters2, tskIDLE_PRIORITY, NULL ); + + + + /* Create the second two tasks as described at the top of the file. This uses + the same mechanism but reverses the task priorities. */ + + pxQueueParameters3 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + pxQueueParameters3->xQueue = xQueueCreate( uxQueueSize1, ( UBaseType_t ) sizeof( uint16_t ) ); + pxQueueParameters3->xBlockTime = xDontBlock; + pxQueueParameters3->psCheckVariable = &( sBlockingProducerCount[ 1 ] ); + + pxQueueParameters4 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + pxQueueParameters4->xQueue = pxQueueParameters3->xQueue; + pxQueueParameters4->xBlockTime = xBlockTime; + pxQueueParameters4->psCheckVariable = &( sBlockingConsumerCount[ 1 ] ); + + xTaskCreate( vBlockingQueueConsumer, "QConsB3", blckqSTACK_SIZE, ( void * ) pxQueueParameters3, tskIDLE_PRIORITY, NULL ); + xTaskCreate( vBlockingQueueProducer, "QProdB4", blckqSTACK_SIZE, ( void * ) pxQueueParameters4, uxPriority, NULL ); + + + + /* Create the last two tasks as described above. The mechanism is again just + the same. This time both parameter structures are given a block time. */ + pxQueueParameters5 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + pxQueueParameters5->xQueue = xQueueCreate( uxQueueSize5, ( UBaseType_t ) sizeof( uint16_t ) ); + pxQueueParameters5->xBlockTime = xBlockTime; + pxQueueParameters5->psCheckVariable = &( sBlockingProducerCount[ 2 ] ); + + pxQueueParameters6 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + pxQueueParameters6->xQueue = pxQueueParameters5->xQueue; + pxQueueParameters6->xBlockTime = xBlockTime; + pxQueueParameters6->psCheckVariable = &( sBlockingConsumerCount[ 2 ] ); + + xTaskCreate( vBlockingQueueProducer, "QProdB5", blckqSTACK_SIZE, ( void * ) pxQueueParameters5, tskIDLE_PRIORITY, NULL ); + xTaskCreate( vBlockingQueueConsumer, "QConsB6", blckqSTACK_SIZE, ( void * ) pxQueueParameters6, tskIDLE_PRIORITY, NULL ); +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vBlockingQueueProducer, pvParameters ) +{ +uint16_t usValue = 0; +xBlockingQueueParameters *pxQueueParameters; +short sErrorEverOccurred = pdFALSE; + + pxQueueParameters = ( xBlockingQueueParameters * ) pvParameters; + + for( ;; ) + { + if( xQueueSend( pxQueueParameters->xQueue, ( void * ) &usValue, pxQueueParameters->xBlockTime ) != pdPASS ) + { + sErrorEverOccurred = pdTRUE; + } + else + { + /* We have successfully posted a message, so increment the variable + used to check we are still running. */ + if( sErrorEverOccurred == pdFALSE ) + { + ( *pxQueueParameters->psCheckVariable )++; + } + + /* Increment the variable we are going to post next time round. The + consumer will expect the numbers to follow in numerical order. */ + ++usValue; + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + } + } +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vBlockingQueueConsumer, pvParameters ) +{ +uint16_t usData, usExpectedValue = 0; +xBlockingQueueParameters *pxQueueParameters; +short sErrorEverOccurred = pdFALSE; + + pxQueueParameters = ( xBlockingQueueParameters * ) pvParameters; + + for( ;; ) + { + if( xQueueReceive( pxQueueParameters->xQueue, &usData, pxQueueParameters->xBlockTime ) == pdPASS ) + { + if( usData != usExpectedValue ) + { + /* Catch-up. */ + usExpectedValue = usData; + + sErrorEverOccurred = pdTRUE; + } + else + { + /* We have successfully received a message, so increment the + variable used to check we are still running. */ + if( sErrorEverOccurred == pdFALSE ) + { + ( *pxQueueParameters->psCheckVariable )++; + } + + /* Increment the value we expect to remove from the queue next time + round. */ + ++usExpectedValue; + } + + #if configUSE_PREEMPTION == 0 + { + if( pxQueueParameters->xBlockTime == 0 ) + { + taskYIELD(); + } + } + #endif + } + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +BaseType_t xAreBlockingQueuesStillRunning( void ) +{ +static short sLastBlockingConsumerCount[ blckqNUM_TASK_SETS ] = { ( uint16_t ) 0, ( uint16_t ) 0, ( uint16_t ) 0 }; +static short sLastBlockingProducerCount[ blckqNUM_TASK_SETS ] = { ( uint16_t ) 0, ( uint16_t ) 0, ( uint16_t ) 0 }; +BaseType_t xReturn = pdPASS, xTasks; + + /* Not too worried about mutual exclusion on these variables as they are 16 + bits and we are only reading them. We also only care to see if they have + changed or not. + + Loop through each check variable to and return pdFALSE if any are found not + to have changed since the last call. */ + + for( xTasks = 0; xTasks < blckqNUM_TASK_SETS; xTasks++ ) + { + if( sBlockingConsumerCount[ xTasks ] == sLastBlockingConsumerCount[ xTasks ] ) + { + xReturn = pdFALSE; + } + sLastBlockingConsumerCount[ xTasks ] = sBlockingConsumerCount[ xTasks ]; + + + if( sBlockingProducerCount[ xTasks ] == sLastBlockingProducerCount[ xTasks ] ) + { + xReturn = pdFALSE; + } + sLastBlockingProducerCount[ xTasks ] = sBlockingProducerCount[ xTasks ]; + } + + return xReturn; +} + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/EventGroupsDemo.c b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/EventGroupsDemo.c new file mode 100644 index 0000000..64d7430 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/EventGroupsDemo.c @@ -0,0 +1,1074 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + + +/* +* This file contains fairly comprehensive checks on the behaviour of event +* groups. It is not intended to be a user friendly demonstration of the +* event groups API. +* +* NOTE: The tests implemented in this file are informal 'sanity' tests +* only and are not part of the module tests that make use of the +* mtCOVERAGE_TEST_MARKER macro within the event groups implementation. +*/ + + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "event_groups.h" + +/* Demo app includes. */ +#include "EventGroupsDemo.h" + +#if( INCLUDE_eTaskGetState != 1 ) + #error INCLUDE_eTaskGetState must be set to 1 in FreeRTOSConfig.h to use this demo file. +#endif + +/* Priorities used by the tasks. */ +#define ebSET_BIT_TASK_PRIORITY ( tskIDLE_PRIORITY ) +#define ebWAIT_BIT_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 ) + +/* Generic bit definitions. */ +#define ebBIT_0 ( 0x01UL ) +#define ebBIT_1 ( 0x02UL ) +#define ebBIT_2 ( 0x04UL ) +#define ebBIT_3 ( 0x08UL ) +#define ebBIT_4 ( 0x10UL ) +#define ebBIT_5 ( 0x20UL ) +#define ebBIT_6 ( 0x40UL ) +#define ebBIT_7 ( 0x80UL ) + +/* Combinations of bits used in the demo. */ +#define ebCOMBINED_BITS ( ebBIT_1 | ebBIT_5 | ebBIT_7 ) +#define ebALL_BITS ( ebBIT_0 | ebBIT_1 | ebBIT_2 | ebBIT_3 | ebBIT_4 | ebBIT_5 | ebBIT_6 | ebBIT_7 ) + +/* Associate a bit to each task. These bits are used to identify all the tasks +that synchronise with the xEventGroupSync() function. */ +#define ebSET_BIT_TASK_SYNC_BIT ebBIT_0 +#define ebWAIT_BIT_TASK_SYNC_BIT ebBIT_1 +#define ebRENDESVOUS_TASK_1_SYNC_BIT ebBIT_2 +#define ebRENDESVOUS_TASK_2_SYNC_BIT ebBIT_3 +#define ebALL_SYNC_BITS ( ebSET_BIT_TASK_SYNC_BIT | ebWAIT_BIT_TASK_SYNC_BIT | ebRENDESVOUS_TASK_1_SYNC_BIT | ebRENDESVOUS_TASK_2_SYNC_BIT ) + +/* A block time of zero simply means "don't block". */ +#define ebDONT_BLOCK ( 0 ) + +/* A 5ms delay. */ +#define ebSHORT_DELAY ( 5 / portTICK_PERIOD_MS ) + +/* Used in the selective bits test which checks no, one or both tasks blocked on +event bits in a group are unblocked as appropriate as different bits get set. */ +#define ebSELECTIVE_BITS_1 0x03 +#define ebSELECTIVE_BITS_2 0x05 + +/*-----------------------------------------------------------*/ + +/* + * NOTE: The tests implemented in this function are informal 'sanity' tests + * only and are not part of the module tests that make use of the + * mtCOVERAGE_TEST_MARKER macro within the event groups implementation. + * + * The master test task. This task: + * + * 1) Calls prvSelectiveBitsTestMasterFunction() to test the behaviour when two + * tasks are blocked on different bits in an event group. The counterpart of + * this test is implemented by the prvSelectiveBitsTestSlaveFunction() + * function (which is called by the two tasks that block on the event group). + * + * 2) Calls prvBitCombinationTestMasterFunction() to test the behaviour when + * just one task is blocked on various combinations of bits within an event + * group. The counterpart of this test is implemented within the 'test + * slave' task. + * + * 3) Calls prvPerformTaskSyncTests() to test task synchronisation behaviour. + */ +static void prvTestMasterTask( void *pvParameters ); + +/* + * A helper task that enables the 'test master' task to perform several + * behavioural tests. See the comments above the prvTestMasterTask() prototype + * above. + */ +static void prvTestSlaveTask( void *pvParameters ); + +/* + * The part of the test that is performed between the 'test master' task and the + * 'test slave' task to test the behaviour when the slave blocks on various + * event bit combinations. + */ +static BaseType_t prvBitCombinationTestMasterFunction( BaseType_t xError, TaskHandle_t xTestSlaveTaskHandle ); + +/* + * The part of the test that uses all the tasks to test the task synchronisation + * behaviour. + */ +static BaseType_t prvPerformTaskSyncTests( BaseType_t xError, TaskHandle_t xTestSlaveTaskHandle ); + +/* + * Two instances of prvSyncTask() are created. They start by calling + * prvSelectiveBitsTestSlaveFunction() to act as slaves when the test master is + * executing the prvSelectiveBitsTestMasterFunction() function. They then loop + * to test the task synchronisation (rendezvous) behaviour. + */ +static void prvSyncTask( void *pvParameters ); + +/* + * Functions used in a test that blocks two tasks on various different bits + * within an event group - then sets each bit in turn and checks that the + * correct tasks unblock at the correct times. + */ +static BaseType_t prvSelectiveBitsTestMasterFunction( void ); +static void prvSelectiveBitsTestSlaveFunction( void ); + +/*-----------------------------------------------------------*/ + +/* Variables that are incremented by the tasks on each cycle provided no errors +have been found. Used to detect an error or stall in the test cycling. */ +static volatile uint32_t ulTestMasterCycles = 0, ulTestSlaveCycles = 0, ulISRCycles = 0; + +/* The event group used by all the task based tests. */ +static EventGroupHandle_t xEventGroup = NULL; + +/* The event group used by the interrupt based tests. */ +static EventGroupHandle_t xISREventGroup = NULL; + +/* Handles to the tasks that only take part in the synchronisation calls. */ +static TaskHandle_t xSyncTask1 = NULL, xSyncTask2 = NULL; + +/*-----------------------------------------------------------*/ + +void vStartEventGroupTasks( void ) +{ +TaskHandle_t xTestSlaveTaskHandle; + + /* + * This file contains fairly comprehensive checks on the behaviour of event + * groups. It is not intended to be a user friendly demonstration of the + * event groups API. + * + * NOTE: The tests implemented in this file are informal 'sanity' tests + * only and are not part of the module tests that make use of the + * mtCOVERAGE_TEST_MARKER macro within the event groups implementation. + * + * Create the test tasks as described at the top of this file. + */ + xTaskCreate( prvTestSlaveTask, "WaitO", configMINIMAL_STACK_SIZE, NULL, ebWAIT_BIT_TASK_PRIORITY, &xTestSlaveTaskHandle ); + xTaskCreate( prvTestMasterTask, "SetB", configMINIMAL_STACK_SIZE, ( void * ) xTestSlaveTaskHandle, ebSET_BIT_TASK_PRIORITY, NULL ); + xTaskCreate( prvSyncTask, "Rndv", configMINIMAL_STACK_SIZE, ( void * ) ebRENDESVOUS_TASK_1_SYNC_BIT, ebWAIT_BIT_TASK_PRIORITY, &xSyncTask1 ); + xTaskCreate( prvSyncTask, "Rndv", configMINIMAL_STACK_SIZE, ( void * ) ebRENDESVOUS_TASK_2_SYNC_BIT, ebWAIT_BIT_TASK_PRIORITY, &xSyncTask2 ); + + /* If the last task was created then the others will have been too. */ + configASSERT( xSyncTask2 ); + + /* Create the event group used by the ISR tests. The event group used by + the tasks is created by the tasks themselves. */ + xISREventGroup = xEventGroupCreate(); + configASSERT( xISREventGroup ); +} +/*-----------------------------------------------------------*/ + +static void prvTestMasterTask( void *pvParameters ) +{ +BaseType_t xError; + +/* The handle to the slave task is passed in as the task parameter. */ +TaskHandle_t xTestSlaveTaskHandle = ( TaskHandle_t ) pvParameters; + + /* Avoid compiler warnings. */ + ( void ) pvParameters; + + /* Create the event group used by the tasks ready for the initial tests. */ + xEventGroup = xEventGroupCreate(); + configASSERT( xEventGroup ); + + /* Perform the tests that block two tasks on different combinations of bits, + then set each bit in turn and check the correct tasks unblock at the correct + times. */ + xError = prvSelectiveBitsTestMasterFunction(); + + for( ;; ) + { + /* Recreate the event group ready for the next cycle. */ + xEventGroup = xEventGroupCreate(); + configASSERT( xEventGroup ); + + /* Perform the tests that check the behaviour when a single task is + blocked on various combinations of event bits. */ + xError = prvBitCombinationTestMasterFunction( xError, xTestSlaveTaskHandle ); + + /* Perform the task synchronisation tests. */ + xError = prvPerformTaskSyncTests( xError, xTestSlaveTaskHandle ); + + /* Delete the event group. */ + vEventGroupDelete( xEventGroup ); + + /* Now all the other tasks should have completed and suspended + themselves ready for the next go around the loop. */ + if( eTaskGetState( xTestSlaveTaskHandle ) != eSuspended ) + { + xError = pdTRUE; + } + + if( eTaskGetState( xSyncTask1 ) != eSuspended ) + { + xError = pdTRUE; + } + + if( eTaskGetState( xSyncTask2 ) != eSuspended ) + { + xError = pdTRUE; + } + + /* Only increment the cycle variable if no errors have been detected. */ + if( xError == pdFALSE ) + { + ulTestMasterCycles++; + } + + configASSERT( xError == pdFALSE ); + } +} +/*-----------------------------------------------------------*/ + +static void prvSyncTask( void *pvParameters ) +{ +EventBits_t uxSynchronisationBit, uxReturned; + + /* A few tests that check the behaviour when two tasks are blocked on + various different bits within an event group are performed before this task + enters its infinite loop to carry out its main demo function. */ + prvSelectiveBitsTestSlaveFunction(); + + /* The bit to use to indicate this task is at the synchronisation point is + passed in as the task parameter. */ + uxSynchronisationBit = ( EventBits_t ) pvParameters; + + for( ;; ) + { + /* Now this task takes part in a task synchronisation - sometimes known + as a 'rendezvous'. Its execution pattern is controlled by the 'test + master' task, which is responsible for taking this task out of the + Suspended state when it is time to test the synchronisation behaviour. + See: http://www.freertos.org/xEventGroupSync.html. */ + vTaskSuspend( NULL ); + + /* Set the bit that indicates this task is at the synchronisation + point. The first time this is done the 'test master' task has a lower + priority than this task so this task will get to the sync point before + the set bits task. */ + uxReturned = xEventGroupSync( xEventGroup, /* The event group used for the synchronisation. */ + uxSynchronisationBit, /* The bit to set in the event group to indicate this task is at the sync point. */ + ebALL_SYNC_BITS,/* The bits to wait for - these bits are set by the other tasks taking part in the sync. */ + portMAX_DELAY );/* The maximum time to wait for the sync condition to be met before giving up. */ + + /* A max delay was used, so this task should only exit the above + function call when the sync condition is met. Check this is the + case. */ + configASSERT( ( uxReturned & ebALL_SYNC_BITS ) == ebALL_SYNC_BITS ); + + /* Remove compiler warning if configASSERT() is not defined. */ + ( void ) uxReturned; + + /* Wait until the 'test master' task unsuspends this task again. */ + vTaskSuspend( NULL ); + + /* Set the bit that indicates this task is at the synchronisation + point again. This time the 'test master' task has a higher priority + than this task so will get to the sync point before this task. */ + uxReturned = xEventGroupSync( xEventGroup, uxSynchronisationBit, ebALL_SYNC_BITS, portMAX_DELAY ); + + /* Again a max delay was used, so this task should only exit the above + function call when the sync condition is met. Check this is the + case. */ + configASSERT( ( uxReturned & ebALL_SYNC_BITS ) == ebALL_SYNC_BITS ); + + /* Block on the event group again. This time the event group is going + to be deleted while this task is blocked on it so it is expected that 0 + be returned. */ + uxReturned = xEventGroupWaitBits( xEventGroup, ebALL_SYNC_BITS, pdFALSE, pdTRUE, portMAX_DELAY ); + configASSERT( uxReturned == 0 ); + } +} +/*-----------------------------------------------------------*/ + +static void prvTestSlaveTask( void *pvParameters ) +{ +EventBits_t uxReturned; +BaseType_t xError = pdFALSE; + + /* Avoid compiler warnings. */ + ( void ) pvParameters; + + for( ;; ) + { + /********************************************************************** + * Part 1: This section is the counterpart to the + * prvBitCombinationTestMasterFunction() function which is called by the + * test master task. + *********************************************************************** + + This task is controller by the 'test master' task (which is + implemented by prvTestMasterTask()). Suspend until resumed by the + 'test master' task. */ + vTaskSuspend( NULL ); + + /* Wait indefinitely for one of the bits in ebCOMBINED_BITS to get + set. Clear the bit on exit. */ + uxReturned = xEventGroupWaitBits( xEventGroup, /* The event group that contains the event bits being queried. */ + ebBIT_1, /* The bit to wait for. */ + pdTRUE, /* Clear the bit on exit. */ + pdTRUE, /* Wait for all the bits (only one in this case anyway). */ + portMAX_DELAY ); /* Block indefinitely to wait for the condition to be met. */ + + /* The 'test master' task set all the bits defined by ebCOMBINED_BITS, + only one of which was being waited for by this task. The return value + shows the state of the event bits when the task was unblocked, however + because the task was waiting for ebBIT_1 and 'clear on exit' was set to + the current state of the event bits will have ebBIT_1 clear. */ + if( uxReturned != ebCOMBINED_BITS ) + { + xError = pdTRUE; + } + + /* Now call xEventGroupWaitBits() again, this time waiting for all the + bits in ebCOMBINED_BITS to be set. This call should block until the + 'test master' task sets ebBIT_1 - which was the bit cleared in the call + to xEventGroupWaitBits() above. */ + uxReturned = xEventGroupWaitBits( xEventGroup, + ebCOMBINED_BITS, /* The bits being waited on. */ + pdFALSE, /* Don't clear the bits on exit. */ + pdTRUE, /* All the bits must be set to unblock. */ + portMAX_DELAY ); + + /* Were all the bits set? */ + if( ( uxReturned & ebCOMBINED_BITS ) != ebCOMBINED_BITS ) + { + xError = pdTRUE; + } + + /* Suspend again to wait for the 'test master' task. */ + vTaskSuspend( NULL ); + + /* Now call xEventGroupWaitBits() again, again waiting for all the bits + in ebCOMBINED_BITS to be set, but this time clearing the bits when the + task is unblocked. */ + uxReturned = xEventGroupWaitBits( xEventGroup, + ebCOMBINED_BITS, /* The bits being waited on. */ + pdTRUE, /* Clear the bits on exit. */ + pdTRUE, /* All the bits must be set to unblock. */ + portMAX_DELAY ); + + /* The 'test master' task set all the bits in the event group, so that + is the value that should have been returned. The bits defined by + ebCOMBINED_BITS will have been clear again in the current value though + as 'clear on exit' was set to pdTRUE. */ + if( uxReturned != ebALL_BITS ) + { + xError = pdTRUE; + } + + + + + + /********************************************************************** + * Part 2: This section is the counterpart to the + * prvPerformTaskSyncTests() function which is called by the + * test master task. + *********************************************************************** + + + Once again wait for the 'test master' task to unsuspend this task + when it is time for the next test. */ + vTaskSuspend( NULL ); + + /* Now peform a synchronisation with all the other tasks. At this point + the 'test master' task has the lowest priority so will get to the sync + point after all the other synchronising tasks. */ + uxReturned = xEventGroupSync( xEventGroup, /* The event group used for the sync. */ + ebWAIT_BIT_TASK_SYNC_BIT, /* The bit in the event group used to indicate this task is at the sync point. */ + ebALL_SYNC_BITS, /* The bits to wait for. These bits are set by the other tasks taking part in the sync. */ + portMAX_DELAY ); /* The maximum time to wait for the sync condition to be met before giving up. */ + + /* A sync with a max delay should only exit when all the synchronisation + bits are set... */ + if( ( uxReturned & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS ) + { + xError = pdTRUE; + } + + /* ...but now the synchronisation bits should be clear again. Read back + the current value of the bits within the event group to check that is + the case. Setting the bits to zero will return the bits previous value + then leave all the bits clear. */ + if( xEventGroupSetBits( xEventGroup, 0x00 ) != 0 ) + { + xError = pdTRUE; + } + + /* Check the bits are indeed 0 now by simply reading then. */ + if( xEventGroupGetBits( xEventGroup ) != 0 ) + { + xError = pdTRUE; + } + + if( xError == pdFALSE ) + { + /* This task is still cycling without finding an error. */ + ulTestSlaveCycles++; + } + + vTaskSuspend( NULL ); + + /* This time sync when the 'test master' task has the highest priority + at the point where it sets its sync bit - so this time the 'test master' + task will get to the sync point before this task. */ + uxReturned = xEventGroupSync( xEventGroup, ebWAIT_BIT_TASK_SYNC_BIT, ebALL_SYNC_BITS, portMAX_DELAY ); + + /* A sync with a max delay should only exit when all the synchronisation + bits are set... */ + if( ( uxReturned & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS ) + { + xError = pdTRUE; + } + + /* ...but now the sync bits should be clear again. */ + if( xEventGroupSetBits( xEventGroup, 0x00 ) != 0 ) + { + xError = pdTRUE; + } + + /* Block on the event group again. This time the event group is going + to be deleted while this task is blocked on it, so it is expected that 0 + will be returned. */ + uxReturned = xEventGroupWaitBits( xEventGroup, ebALL_SYNC_BITS, pdFALSE, pdTRUE, portMAX_DELAY ); + + if( uxReturned != 0 ) + { + xError = pdTRUE; + } + + if( xError == pdFALSE ) + { + /* This task is still cycling without finding an error. */ + ulTestSlaveCycles++; + } + + configASSERT( xError == pdFALSE ); + } +} +/*-----------------------------------------------------------*/ + +static BaseType_t prvPerformTaskSyncTests( BaseType_t xError, TaskHandle_t xTestSlaveTaskHandle ) +{ +EventBits_t uxBits; + + /* The three tasks that take part in the synchronisation (rendezvous) are + expected to be in the suspended state at the start of the test. */ + if( eTaskGetState( xTestSlaveTaskHandle ) != eSuspended ) + { + xError = pdTRUE; + } + + if( eTaskGetState( xSyncTask1 ) != eSuspended ) + { + xError = pdTRUE; + } + + if( eTaskGetState( xSyncTask2 ) != eSuspended ) + { + xError = pdTRUE; + } + + /* Try a synch with no other tasks involved. First set all the bits other + than this task's bit. */ + xEventGroupSetBits( xEventGroup, ( ebALL_SYNC_BITS & ~ebSET_BIT_TASK_SYNC_BIT ) ); + + /* Then wait on just one bit - the bit that is being set. */ + uxBits = xEventGroupSync( xEventGroup, /* The event group used for the synchronisation. */ + ebSET_BIT_TASK_SYNC_BIT,/* The bit set by this task when it reaches the sync point. */ + ebSET_BIT_TASK_SYNC_BIT,/* The bits to wait for - in this case it is just waiting for itself. */ + portMAX_DELAY ); /* The maximum time to wait for the sync condition to be met. */ + + /* A sync with a max delay should only exit when all the synchronise + bits are set...check that is the case. In this case there is only one + sync bit anyway. */ + if( ( uxBits & ebSET_BIT_TASK_SYNC_BIT ) != ebSET_BIT_TASK_SYNC_BIT ) + { + xError = pdTRUE; + } + + /* ...but now the sync bits should be clear again, leaving all the other + bits set (as only one bit was being waited for). */ + if( xEventGroupGetBits( xEventGroup ) != ( ebALL_SYNC_BITS & ~ebSET_BIT_TASK_SYNC_BIT ) ) + { + xError = pdTRUE; + } + + /* Clear all the bits to zero again. */ + xEventGroupClearBits( xEventGroup, ( ebALL_SYNC_BITS & ~ebSET_BIT_TASK_SYNC_BIT ) ); + if( xEventGroupGetBits( xEventGroup ) != 0 ) + { + xError = pdTRUE; + } + + /* Unsuspend the other tasks then check they have executed up to the + synchronisation point. */ + vTaskResume( xTestSlaveTaskHandle ); + vTaskResume( xSyncTask1 ); + vTaskResume( xSyncTask2 ); + + if( eTaskGetState( xTestSlaveTaskHandle ) != eBlocked ) + { + xError = pdTRUE; + } + + if( eTaskGetState( xSyncTask1 ) != eBlocked ) + { + xError = pdTRUE; + } + + if( eTaskGetState( xSyncTask2 ) != eBlocked ) + { + xError = pdTRUE; + } + + /* Set this task's sync bit. */ + uxBits = xEventGroupSync( xEventGroup, /* The event group used for the synchronisation. */ + ebSET_BIT_TASK_SYNC_BIT,/* The bit set by this task when it reaches the sync point. */ + ebALL_SYNC_BITS, /* The bits to wait for - these bits are set by the other tasks that take part in the sync. */ + portMAX_DELAY ); /* The maximum time to wait for the sync condition to be met. */ + + /* A sync with a max delay should only exit when all the synchronise + bits are set...check that is the case. */ + if( ( uxBits & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS ) + { + xError = pdTRUE; + } + + /* ...but now the sync bits should be clear again. */ + if( xEventGroupGetBits( xEventGroup ) != 0 ) + { + xError = pdTRUE; + } + + + /* The other tasks should now all be suspended again, ready for the next + synchronisation. */ + if( eTaskGetState( xTestSlaveTaskHandle ) != eSuspended ) + { + xError = pdTRUE; + } + + if( eTaskGetState( xSyncTask1 ) != eSuspended ) + { + xError = pdTRUE; + } + + if( eTaskGetState( xSyncTask2 ) != eSuspended ) + { + xError = pdTRUE; + } + + + /* Sync again - but this time set the last necessary bit as the + highest priority task, rather than the lowest priority task. Unsuspend + the other tasks then check they have executed up to the synchronisation + point. */ + vTaskResume( xTestSlaveTaskHandle ); + vTaskResume( xSyncTask1 ); + vTaskResume( xSyncTask2 ); + + if( eTaskGetState( xTestSlaveTaskHandle ) != eBlocked ) + { + xError = pdTRUE; + } + + if( eTaskGetState( xSyncTask1 ) != eBlocked ) + { + xError = pdTRUE; + } + + if( eTaskGetState( xSyncTask2 ) != eBlocked ) + { + xError = pdTRUE; + } + + /* Raise the priority of this task above that of the other tasks. */ + vTaskPrioritySet( NULL, ebWAIT_BIT_TASK_PRIORITY + 1 ); + + /* Set this task's sync bit. */ + uxBits = xEventGroupSync( xEventGroup, ebSET_BIT_TASK_SYNC_BIT, ebALL_SYNC_BITS, portMAX_DELAY ); + + /* A sync with a max delay should only exit when all the synchronisation + bits are set... */ + if( ( uxBits & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS ) + { + xError = pdTRUE; + } + + /* ...but now the sync bits should be clear again. */ + if( xEventGroupGetBits( xEventGroup ) != 0 ) + { + xError = pdTRUE; + } + + + /* The other tasks should now all be in the ready state again, but not + executed yet as this task still has a higher relative priority. */ + if( eTaskGetState( xTestSlaveTaskHandle ) != eReady ) + { + xError = pdTRUE; + } + + if( eTaskGetState( xSyncTask1 ) != eReady ) + { + xError = pdTRUE; + } + + if( eTaskGetState( xSyncTask2 ) != eReady ) + { + xError = pdTRUE; + } + + + /* Reset the priority of this task back to its original value. */ + vTaskPrioritySet( NULL, ebSET_BIT_TASK_PRIORITY ); + + /* Now all the other tasks should have reblocked on the event bits + to test the behaviour when the event bits are deleted. */ + if( eTaskGetState( xTestSlaveTaskHandle ) != eBlocked ) + { + xError = pdTRUE; + } + + if( eTaskGetState( xSyncTask1 ) != eBlocked ) + { + xError = pdTRUE; + } + + if( eTaskGetState( xSyncTask2 ) != eBlocked ) + { + xError = pdTRUE; + } + + return xError; +} +/*-----------------------------------------------------------*/ + +static BaseType_t prvBitCombinationTestMasterFunction( BaseType_t xError, TaskHandle_t xTestSlaveTaskHandle ) +{ +EventBits_t uxBits; + + /* Resume the other task. It will block, pending a single bit from + within ebCOMBINED_BITS. */ + vTaskResume( xTestSlaveTaskHandle ); + + /* Ensure the other task is blocked on the task. */ + if( eTaskGetState( xTestSlaveTaskHandle ) != eBlocked ) + { + xError = pdTRUE; + } + + /* Set all the bits in ebCOMBINED_BITS - the 'test slave' task is only + blocked waiting for one of them. */ + xEventGroupSetBits( xEventGroup, ebCOMBINED_BITS ); + + /* The 'test slave' task should now have executed, clearing ebBIT_1 (the + bit it was blocked on), then re-entered the Blocked state to wait for + all the other bits in ebCOMBINED_BITS to be set again. First check + ebBIT_1 is clear. */ + uxBits = xEventGroupWaitBits( xEventGroup, ebALL_BITS, pdFALSE, pdFALSE, ebDONT_BLOCK ); + + if( uxBits != ( ebCOMBINED_BITS & ~ebBIT_1 ) ) + { + xError = pdTRUE; + } + + /* Ensure the other task is still in the blocked state. */ + if( eTaskGetState( xTestSlaveTaskHandle ) != eBlocked ) + { + xError = pdTRUE; + } + + /* Set all the bits other than ebBIT_1 - which is the bit that must be + set before the other task unblocks. */ + xEventGroupSetBits( xEventGroup, ebALL_BITS & ~ebBIT_1 ); + + /* Ensure all the expected bits are still set. */ + uxBits = xEventGroupWaitBits( xEventGroup, ebALL_BITS, pdFALSE, pdFALSE, ebDONT_BLOCK ); + + if( uxBits != ( ebALL_BITS & ~ebBIT_1 ) ) + { + xError = pdTRUE; + } + + /* Ensure the other task is still in the blocked state. */ + if( eTaskGetState( xTestSlaveTaskHandle ) != eBlocked ) + { + xError = pdTRUE; + } + + /* Now also set ebBIT_1, which should unblock the other task, which will + then suspend itself. */ + xEventGroupSetBits( xEventGroup, ebBIT_1 ); + + /* Ensure the other task is suspended. */ + if( eTaskGetState( xTestSlaveTaskHandle ) != eSuspended ) + { + xError = pdTRUE; + } + + /* The other task should not have cleared the bits - so all the bits + should still be set. */ + if( xEventGroupSetBits( xEventGroup, 0x00 ) != ebALL_BITS ) + { + xError = pdTRUE; + } + + /* Clear ebBIT_1 again. */ + if( xEventGroupClearBits( xEventGroup, ebBIT_1 ) != ebALL_BITS ) + { + xError = pdTRUE; + } + + /* Resume the other task - which will wait on all the ebCOMBINED_BITS + again - this time clearing the bits when it is unblocked. */ + vTaskResume( xTestSlaveTaskHandle ); + + /* Ensure the other task is blocked once again. */ + if( eTaskGetState( xTestSlaveTaskHandle ) != eBlocked ) + { + xError = pdTRUE; + } + + /* Set the bit the other task is waiting for. */ + xEventGroupSetBits( xEventGroup, ebBIT_1 ); + + /* Ensure the other task is suspended once again. */ + if( eTaskGetState( xTestSlaveTaskHandle ) != eSuspended ) + { + xError = pdTRUE; + } + + /* The other task should have cleared the bits in ebCOMBINED_BITS. + Clear the remaining bits. */ + uxBits = xEventGroupWaitBits( xEventGroup, ebALL_BITS, pdFALSE, pdFALSE, ebDONT_BLOCK ); + + if( uxBits != ( ebALL_BITS & ~ebCOMBINED_BITS ) ) + { + xError = pdTRUE; + } + + /* Clear all bits ready for the sync with the other three tasks. The + value returned is the value prior to the bits being cleared. */ + if( xEventGroupClearBits( xEventGroup, ebALL_BITS ) != ( ebALL_BITS & ~ebCOMBINED_BITS ) ) + { + xError = pdTRUE; + } + + /* The bits should be clear now. */ + if( xEventGroupGetBits( xEventGroup ) != 0x00 ) + { + xError = pdTRUE; + } + + return xError; +} +/*-----------------------------------------------------------*/ + +static void prvSelectiveBitsTestSlaveFunction( void ) +{ +EventBits_t uxPendBits, uxReturned; + + /* Used in a test that blocks two tasks on various different bits within an + event group - then sets each bit in turn and checks that the correct tasks + unblock at the correct times. + + This function is called by two different tasks - each of which will use a + different bit. Check the task handle to see which task the function was + called by. */ + if( xTaskGetCurrentTaskHandle() == xSyncTask1 ) + { + uxPendBits = ebSELECTIVE_BITS_1; + } + else + { + uxPendBits = ebSELECTIVE_BITS_2; + } + + for( ;; ) + { + /* Wait until it is time to perform the next cycle of the test. The + task is unsuspended by the tests implemented in the + prvSelectiveBitsTestMasterFunction() function. */ + vTaskSuspend( NULL ); + uxReturned = xEventGroupWaitBits( xEventGroup, uxPendBits, pdTRUE, pdFALSE, portMAX_DELAY ); + + if( uxReturned == ( EventBits_t ) 0 ) + { + break; + } + } +} +/*-----------------------------------------------------------*/ + +static BaseType_t prvSelectiveBitsTestMasterFunction( void ) +{ +BaseType_t xError = pdFALSE; +EventBits_t uxBit; + + /* Used in a test that blocks two tasks on various different bits within an + event group - then sets each bit in turn and checks that the correct tasks + unblock at the correct times. The two other tasks (xSyncTask1 and + xSyncTask2) call prvSelectiveBitsTestSlaveFunction() to perform their parts in + this test. + + Both other tasks should start in the suspended state. */ + if( eTaskGetState( xSyncTask1 ) != eSuspended ) + { + xError = pdTRUE; + } + + if( eTaskGetState( xSyncTask2 ) != eSuspended ) + { + xError = pdTRUE; + } + + /* Test each bit in the byte individually. */ + for( uxBit = 0x01; uxBit < 0x100; uxBit <<= 1 ) + { + /* Resume both tasks. */ + vTaskResume( xSyncTask1 ); + vTaskResume( xSyncTask2 ); + + /* Now both tasks should be blocked on the event group. */ + if( eTaskGetState( xSyncTask1 ) != eBlocked ) + { + xError = pdTRUE; + } + + if( eTaskGetState( xSyncTask2 ) != eBlocked ) + { + xError = pdTRUE; + } + + /* Set one bit. */ + xEventGroupSetBits( xEventGroup, uxBit ); + + /* Is the bit set in the first set of selective bits? If so the first + sync task should have unblocked and returned to the suspended state. */ + if( ( uxBit & ebSELECTIVE_BITS_1 ) == 0 ) + { + /* Task should not have unblocked. */ + if( eTaskGetState( xSyncTask1 ) != eBlocked ) + { + xError = pdTRUE; + } + } + else + { + /* Task should have unblocked and returned to the suspended state. */ + if( eTaskGetState( xSyncTask1 ) != eSuspended ) + { + xError = pdTRUE; + } + } + + /* Same checks for the second sync task. */ + if( ( uxBit & ebSELECTIVE_BITS_2 ) == 0 ) + { + /* Task should not have unblocked. */ + if( eTaskGetState( xSyncTask2 ) != eBlocked ) + { + xError = pdTRUE; + } + } + else + { + /* Task should have unblocked and returned to the suspended state. */ + if( eTaskGetState( xSyncTask2 ) != eSuspended ) + { + xError = pdTRUE; + } + } + } + + /* Ensure both tasks are blocked on the event group again, then delete the + event group so the other tasks leave this portion of the test. */ + vTaskResume( xSyncTask1 ); + vTaskResume( xSyncTask2 ); + + /* Deleting the event group is the signal that the two other tasks should + leave the prvSelectiveBitsTestSlaveFunction() function and continue to the main + part of their functionality. */ + vEventGroupDelete( xEventGroup ); + + return xError; +} +/*-----------------------------------------------------------*/ + +void vPeriodicEventGroupsProcessing( void ) +{ +static BaseType_t xCallCount = 0, xISRTestError = pdFALSE; +const BaseType_t xSetBitCount = 100, xGetBitsCount = 200, xClearBitsCount = 300; +const EventBits_t uxBitsToSet = 0x12U; +EventBits_t uxReturned; +BaseType_t xMessagePosted; + + /* Called periodically from the tick hook to exercise the "FromISR" + functions. */ + + xCallCount++; + + if( xCallCount == xSetBitCount ) + { + /* All the event bits should start clear. */ + uxReturned = xEventGroupGetBitsFromISR( xISREventGroup ); + if( uxReturned != 0x00 ) + { + xISRTestError = pdTRUE; + } + else + { + /* Set the bits. This is called from the tick hook so it is not + necessary to use the last parameter to ensure a context switch + occurs immediately. */ + xMessagePosted = xEventGroupSetBitsFromISR( xISREventGroup, uxBitsToSet, NULL ); + if( xMessagePosted != pdPASS ) + { + xISRTestError = pdTRUE; + } + } + } + else if( xCallCount == xGetBitsCount ) + { + /* Check the bits were set as expected. */ + uxReturned = xEventGroupGetBitsFromISR( xISREventGroup ); + if( uxReturned != uxBitsToSet ) + { + xISRTestError = pdTRUE; + } + } + else if( xCallCount == xClearBitsCount ) + { + /* Clear the bits again. */ + uxReturned = xEventGroupClearBitsFromISR( xISREventGroup, uxBitsToSet ); + + /* Check the message was posted. */ + if( uxReturned != pdPASS ) + { + xISRTestError = pdTRUE; + } + + /* Go back to the start. */ + xCallCount = 0; + + /* If no errors have been detected then increment the count of test + cycles. */ + if( xISRTestError == pdFALSE ) + { + ulISRCycles++; + } + } + else + { + /* Nothing else to do. */ + } +} + +/*-----------------------------------------------------------*/ +/* This is called to check that all the created tasks are still running. */ +BaseType_t xAreEventGroupTasksStillRunning( void ) +{ +static uint32_t ulPreviousWaitBitCycles = 0, ulPreviousSetBitCycles = 0, ulPreviousISRCycles = 0; +BaseType_t xStatus = pdPASS; + + /* Check the tasks are still cycling without finding any errors. */ + if( ulPreviousSetBitCycles == ulTestMasterCycles ) + { + xStatus = pdFAIL; + } + ulPreviousSetBitCycles = ulTestMasterCycles; + + if( ulPreviousWaitBitCycles == ulTestSlaveCycles ) + { + xStatus = pdFAIL; + } + ulPreviousWaitBitCycles = ulTestSlaveCycles; + + if( ulPreviousISRCycles == ulISRCycles ) + { + xStatus = pdFAIL; + } + ulPreviousISRCycles = ulISRCycles; + + return xStatus; +} + + + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/GenQTest.c b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/GenQTest.c new file mode 100644 index 0000000..3da052a --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/GenQTest.c @@ -0,0 +1,857 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +/* + * Tests the extra queue functionality introduced in FreeRTOS.org V4.5.0 - + * including xQueueSendToFront(), xQueueSendToBack(), xQueuePeek() and + * mutex behaviour. + * + * See the comments above the prvSendFrontAndBackTest() and + * prvLowPriorityMutexTask() prototypes below for more information. + */ + + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "semphr.h" + +/* Demo program include files. */ +#include "GenQTest.h" + +#define genqQUEUE_LENGTH ( 5 ) +#define genqNO_BLOCK ( 0 ) + +#define genqMUTEX_LOW_PRIORITY ( tskIDLE_PRIORITY ) +#define genqMUTEX_TEST_PRIORITY ( tskIDLE_PRIORITY + 1 ) +#define genqMUTEX_MEDIUM_PRIORITY ( tskIDLE_PRIORITY + 2 ) +#define genqMUTEX_HIGH_PRIORITY ( tskIDLE_PRIORITY + 3 ) + +#define genqINTERRUPT_MUTEX_GIVE_PERIOD_MS ( 100 ) +/*-----------------------------------------------------------*/ + +/* + * Tests the behaviour of the xQueueSendToFront() and xQueueSendToBack() + * macros by using both to fill a queue, then reading from the queue to + * check the resultant queue order is as expected. Queue data is also + * peeked. + */ +static void prvSendFrontAndBackTest( void *pvParameters ); + +/* + * The following three tasks are used to demonstrate the mutex behaviour. + * Each task is given a different priority to demonstrate the priority + * inheritance mechanism. + * + * The low priority task obtains a mutex. After this a high priority task + * attempts to obtain the same mutex, causing its priority to be inherited + * by the low priority task. The task with the inherited high priority then + * resumes a medium priority task to ensure it is not blocked by the medium + * priority task while it holds the inherited high priority. Once the mutex + * is returned the task with the inherited priority returns to its original + * low priority, and is therefore immediately preempted by first the high + * priority task and then the medium prioroity task before it can continue. + */ +static void prvLowPriorityMutexTask( void *pvParameters ); +static void prvMediumPriorityMutexTask( void *pvParameters ); +static void prvHighPriorityMutexTask( void *pvParameters ); + +/* + * Exercises the priority inheritance when a task takes two mutexes, returning + * them in a different order to which they were taken. + */ +static void prvTakeTwoMutexesReturnInDifferentOrder( SemaphoreHandle_t xMutex, SemaphoreHandle_t xLocalMutex ); + +/* + * Exercises the priority inheritance when a task takes two mutexes, returning + * them in the same order in which they were taken. + */ +static void prvTakeTwoMutexesReturnInSameOrder( SemaphoreHandle_t xMutex, SemaphoreHandle_t xLocalMutex ); + +/* + * Task that receives an a mutex that is given from an interrupt - although + * generally mutexes should not be used given in interrupts (and definitely + * never taken in an interrupt) there are some circumstances when it may be + * desirable. NOTE: This function is not declared static to prevent compiler + * warnings being generated in demos where the function is declared but not + * used. + */ +void vInterruptMutexTask( void *pvParameters ); + +/*-----------------------------------------------------------*/ + +/* Flag that will be latched to pdTRUE should any unexpected behaviour be +detected in any of the tasks. */ +static volatile BaseType_t xErrorDetected = pdFALSE; + +/* Counters that are incremented on each cycle of a test. This is used to +detect a stalled task - a test that is no longer running. */ +static volatile uint32_t ulLoopCounter = 0; +static volatile uint32_t ulLoopCounter2 = 0; + +/* The variable that is guarded by the mutex in the mutex demo tasks. */ +static volatile uint32_t ulGuardedVariable = 0; + +/* Handles used in the mutext test to suspend and resume the high and medium +priority mutex test tasks. */ +static TaskHandle_t xHighPriorityMutexTask, xMediumPriorityMutexTask; + +/* A mutex which is given from an interrupt - although generally mutexes should +not be used given in interrupts (and definitely never taken in an interrupt) +there are some circumstances when it may be desirable. */ +static SemaphoreHandle_t xISRMutex = NULL; + +/*-----------------------------------------------------------*/ + +void vStartGenericQueueTasks( UBaseType_t uxPriority ) +{ +QueueHandle_t xQueue; +SemaphoreHandle_t xMutex; + + xISRMutex = xSemaphoreCreateMutex(); + configASSERT( xISRMutex ); + + /* Create the queue that we are going to use for the + prvSendFrontAndBackTest demo. */ + xQueue = xQueueCreate( genqQUEUE_LENGTH, sizeof( uint32_t ) ); + + /* vQueueAddToRegistry() adds the queue to the queue registry, if one is + in use. The queue registry is provided as a means for kernel aware + debuggers to locate queues and has no purpose if a kernel aware debugger + is not being used. The call to vQueueAddToRegistry() will be removed + by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is + defined to be less than 1. */ + vQueueAddToRegistry( xQueue, "Gen_Queue_Test" ); + + /* Create the demo task and pass it the queue just created. We are + passing the queue handle by value so it does not matter that it is + declared on the stack here. */ + xTaskCreate( prvSendFrontAndBackTest, "GenQ", configMINIMAL_STACK_SIZE, ( void * ) xQueue, uxPriority, NULL ); + + /* Create the mutex used by the prvMutexTest task. */ + xMutex = xSemaphoreCreateMutex(); + + /* vQueueAddToRegistry() adds the mutex to the registry, if one is + in use. The registry is provided as a means for kernel aware + debuggers to locate mutexes and has no purpose if a kernel aware debugger + is not being used. The call to vQueueAddToRegistry() will be removed + by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is + defined to be less than 1. */ + vQueueAddToRegistry( ( QueueHandle_t ) xMutex, "Gen_Queue_Mutex" ); + + /* Create the mutex demo tasks and pass it the mutex just created. We are + passing the mutex handle by value so it does not matter that it is declared + on the stack here. */ + xTaskCreate( prvLowPriorityMutexTask, "MuLow", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_LOW_PRIORITY, NULL ); + xTaskCreate( prvMediumPriorityMutexTask, "MuMed", configMINIMAL_STACK_SIZE, NULL, genqMUTEX_MEDIUM_PRIORITY, &xMediumPriorityMutexTask ); + xTaskCreate( prvHighPriorityMutexTask, "MuHigh", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_HIGH_PRIORITY, &xHighPriorityMutexTask ); + + /* Only when the windows simulator is being used - create the task that + receives a mutex from an interrupt. */ + #ifdef _WINDOWS_ + { + xTaskCreate( vInterruptMutexTask, "IntMu", configMINIMAL_STACK_SIZE, NULL, genqMUTEX_MEDIUM_PRIORITY, NULL ); + } + #endif /* __WINDOWS__ */ +} +/*-----------------------------------------------------------*/ + +static void prvSendFrontAndBackTest( void *pvParameters ) +{ +uint32_t ulData, ulData2; +QueueHandle_t xQueue; + + #ifdef USE_STDIO + void vPrintDisplayMessage( const char * const * ppcMessageToSend ); + + const char * const pcTaskStartMsg = "Queue SendToFront/SendToBack/Peek test started.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + #endif + + xQueue = ( QueueHandle_t ) pvParameters; + + for( ;; ) + { + /* The queue is empty, so sending an item to the back of the queue + should have the same efect as sending it to the front of the queue. + + First send to the front and check everything is as expected. */ + xQueueSendToFront( xQueue, ( void * ) &ulLoopCounter, genqNO_BLOCK ); + + if( uxQueueMessagesWaiting( xQueue ) != 1 ) + { + xErrorDetected = pdTRUE; + } + + if( xQueueReceive( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + /* The data we sent to the queue should equal the data we just received + from the queue. */ + if( ulLoopCounter != ulData ) + { + xErrorDetected = pdTRUE; + } + + /* Then do the same, sending the data to the back, checking everything + is as expected. */ + if( uxQueueMessagesWaiting( xQueue ) != 0 ) + { + xErrorDetected = pdTRUE; + } + + xQueueSendToBack( xQueue, ( void * ) &ulLoopCounter, genqNO_BLOCK ); + + if( uxQueueMessagesWaiting( xQueue ) != 1 ) + { + xErrorDetected = pdTRUE; + } + + if( xQueueReceive( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + if( uxQueueMessagesWaiting( xQueue ) != 0 ) + { + xErrorDetected = pdTRUE; + } + + /* The data we sent to the queue should equal the data we just received + from the queue. */ + if( ulLoopCounter != ulData ) + { + xErrorDetected = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + + + /* Place 2, 3, 4 into the queue, adding items to the back of the queue. */ + for( ulData = 2; ulData < 5; ulData++ ) + { + xQueueSendToBack( xQueue, ( void * ) &ulData, genqNO_BLOCK ); + } + + /* Now the order in the queue should be 2, 3, 4, with 2 being the first + thing to be read out. Now add 1 then 0 to the front of the queue. */ + if( uxQueueMessagesWaiting( xQueue ) != 3 ) + { + xErrorDetected = pdTRUE; + } + ulData = 1; + xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ); + ulData = 0; + xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ); + + /* Now the queue should be full, and when we read the data out we + should receive 0, 1, 2, 3, 4. */ + if( uxQueueMessagesWaiting( xQueue ) != 5 ) + { + xErrorDetected = pdTRUE; + } + + if( xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL ) + { + xErrorDetected = pdTRUE; + } + + if( xQueueSendToBack( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL ) + { + xErrorDetected = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* Check the data we read out is in the expected order. */ + for( ulData = 0; ulData < genqQUEUE_LENGTH; ulData++ ) + { + /* Try peeking the data first. */ + if( xQueuePeek( xQueue, &ulData2, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + if( ulData != ulData2 ) + { + xErrorDetected = pdTRUE; + } + + + /* Now try receiving the data for real. The value should be the + same. Clobber the value first so we know we really received it. */ + ulData2 = ~ulData2; + if( xQueueReceive( xQueue, &ulData2, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + if( ulData != ulData2 ) + { + xErrorDetected = pdTRUE; + } + } + + /* The queue should now be empty again. */ + if( uxQueueMessagesWaiting( xQueue ) != 0 ) + { + xErrorDetected = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + + /* Our queue is empty once more, add 10, 11 to the back. */ + ulData = 10; + if( xQueueSend( xQueue, &ulData, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + ulData = 11; + if( xQueueSend( xQueue, &ulData, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + if( uxQueueMessagesWaiting( xQueue ) != 2 ) + { + xErrorDetected = pdTRUE; + } + + /* Now we should have 10, 11 in the queue. Add 7, 8, 9 to the + front. */ + for( ulData = 9; ulData >= 7; ulData-- ) + { + if( xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + } + + /* Now check that the queue is full, and that receiving data provides + the expected sequence of 7, 8, 9, 10, 11. */ + if( uxQueueMessagesWaiting( xQueue ) != 5 ) + { + xErrorDetected = pdTRUE; + } + + if( xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL ) + { + xErrorDetected = pdTRUE; + } + + if( xQueueSendToBack( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL ) + { + xErrorDetected = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* Check the data we read out is in the expected order. */ + for( ulData = 7; ulData < ( 7 + genqQUEUE_LENGTH ); ulData++ ) + { + if( xQueueReceive( xQueue, &ulData2, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + if( ulData != ulData2 ) + { + xErrorDetected = pdTRUE; + } + } + + if( uxQueueMessagesWaiting( xQueue ) != 0 ) + { + xErrorDetected = pdTRUE; + } + + ulLoopCounter++; + } +} +/*-----------------------------------------------------------*/ + +static void prvTakeTwoMutexesReturnInDifferentOrder( SemaphoreHandle_t xMutex, SemaphoreHandle_t xLocalMutex ) +{ + /* Take the mutex. It should be available now. */ + if( xSemaphoreTake( xMutex, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + /* Set the guarded variable to a known start value. */ + ulGuardedVariable = 0; + + /* This task's priority should be as per that assigned when the task was + created. */ + if( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY ) + { + xErrorDetected = pdTRUE; + } + + /* Now unsuspend the high priority task. This will attempt to take the + mutex, and block when it finds it cannot obtain it. */ + vTaskResume( xHighPriorityMutexTask ); + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* Ensure the task is reporting its priority as blocked and not + suspended (as it would have done in versions up to V7.5.3). */ + #if( INCLUDE_eTaskGetState == 1 ) + { + configASSERT( eTaskGetState( xHighPriorityMutexTask ) == eBlocked ); + } + #endif /* INCLUDE_eTaskGetState */ + + /* The priority of the high priority task should now have been inherited + as by now it will have attempted to get the mutex. */ + if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY ) + { + xErrorDetected = pdTRUE; + } + + /* Attempt to set the priority of this task to the test priority - + between the idle priority and the medium/high test priorities, but the + actual priority should remain at the high priority. */ + vTaskPrioritySet( NULL, genqMUTEX_TEST_PRIORITY ); + if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY ) + { + xErrorDetected = pdTRUE; + } + + /* Now unsuspend the medium priority task. This should not run as the + inherited priority of this task is above that of the medium priority + task. */ + vTaskResume( xMediumPriorityMutexTask ); + + /* If the medium priority task did run then it will have incremented the + guarded variable. */ + if( ulGuardedVariable != 0 ) + { + xErrorDetected = pdTRUE; + } + + /* Take the local mutex too, so two mutexes are now held. */ + if( xSemaphoreTake( xLocalMutex, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + /* When the semaphore is given back the priority of this task should not + yet be disinherited because the local mutex is still held. This is a + simplification to allow FreeRTOS to be integrated with middleware that + attempts to hold multiple mutexes without bloating the code with complex + algorithms. It is possible that the high priority mutex task will + execute as it shares a priority with this task. */ + if( xSemaphoreGive( xMutex ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* The guarded variable is only incremented by the medium priority task, + which still should not have executed as this task should remain at the + higher priority, ensure this is the case. */ + if( ulGuardedVariable != 0 ) + { + xErrorDetected = pdTRUE; + } + + if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY ) + { + xErrorDetected = pdTRUE; + } + + /* Now also give back the local mutex, taking the held count back to 0. + This time the priority of this task should be disinherited back to the + priority to which it was set while the mutex was held. This means + the medium priority task should execute and increment the guarded + variable. When this task next runs both the high and medium priority + tasks will have been suspended again. */ + if( xSemaphoreGive( xLocalMutex ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* Check the guarded variable did indeed increment... */ + if( ulGuardedVariable != 1 ) + { + xErrorDetected = pdTRUE; + } + + /* ... and that the priority of this task has been disinherited to + genqMUTEX_TEST_PRIORITY. */ + if( uxTaskPriorityGet( NULL ) != genqMUTEX_TEST_PRIORITY ) + { + xErrorDetected = pdTRUE; + } + + /* Set the priority of this task back to its original value, ready for + the next loop around this test. */ + vTaskPrioritySet( NULL, genqMUTEX_LOW_PRIORITY ); +} +/*-----------------------------------------------------------*/ + +static void prvTakeTwoMutexesReturnInSameOrder( SemaphoreHandle_t xMutex, SemaphoreHandle_t xLocalMutex ) +{ + /* Take the mutex. It should be available now. */ + if( xSemaphoreTake( xMutex, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + /* Set the guarded variable to a known start value. */ + ulGuardedVariable = 0; + + /* This task's priority should be as per that assigned when the task was + created. */ + if( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY ) + { + xErrorDetected = pdTRUE; + } + + /* Now unsuspend the high priority task. This will attempt to take the + mutex, and block when it finds it cannot obtain it. */ + vTaskResume( xHighPriorityMutexTask ); + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* Ensure the task is reporting its priority as blocked and not + suspended (as it would have done in versions up to V7.5.3). */ + #if( INCLUDE_eTaskGetState == 1 ) + { + configASSERT( eTaskGetState( xHighPriorityMutexTask ) == eBlocked ); + } + #endif /* INCLUDE_eTaskGetState */ + + /* The priority of the high priority task should now have been inherited + as by now it will have attempted to get the mutex. */ + if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY ) + { + xErrorDetected = pdTRUE; + } + + /* Now unsuspend the medium priority task. This should not run as the + inherited priority of this task is above that of the medium priority + task. */ + vTaskResume( xMediumPriorityMutexTask ); + + /* If the medium priority task did run then it will have incremented the + guarded variable. */ + if( ulGuardedVariable != 0 ) + { + xErrorDetected = pdTRUE; + } + + /* Take the local mutex too, so two mutexes are now held. */ + if( xSemaphoreTake( xLocalMutex, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + /* When the local semaphore is given back the priority of this task should + not yet be disinherited because the shared mutex is still held. This is a + simplification to allow FreeRTOS to be integrated with middleware that + attempts to hold multiple mutexes without bloating the code with complex + algorithms. It is possible that the high priority mutex task will + execute as it shares a priority with this task. */ + if( xSemaphoreGive( xLocalMutex ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* The guarded variable is only incremented by the medium priority task, + which still should not have executed as this task should remain at the + higher priority, ensure this is the case. */ + if( ulGuardedVariable != 0 ) + { + xErrorDetected = pdTRUE; + } + + if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY ) + { + xErrorDetected = pdTRUE; + } + + /* Now also give back the shared mutex, taking the held count back to 0. + This time the priority of this task should be disinherited back to the + priority at which it was created. This means the medium priority task + should execute and increment the guarded variable. When this task next runs + both the high and medium priority tasks will have been suspended again. */ + if( xSemaphoreGive( xMutex ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* Check the guarded variable did indeed increment... */ + if( ulGuardedVariable != 1 ) + { + xErrorDetected = pdTRUE; + } + + /* ... and that the priority of this task has been disinherited to + genqMUTEX_LOW_PRIORITY. */ + if( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY ) + { + xErrorDetected = pdTRUE; + } +} +/*-----------------------------------------------------------*/ + +static void prvLowPriorityMutexTask( void *pvParameters ) +{ +SemaphoreHandle_t xMutex = ( SemaphoreHandle_t ) pvParameters, xLocalMutex; + + #ifdef USE_STDIO + void vPrintDisplayMessage( const char * const * ppcMessageToSend ); + + const char * const pcTaskStartMsg = "Mutex with priority inheritance test started.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + #endif + + /* The local mutex is used to check the 'mutexs held' count. */ + xLocalMutex = xSemaphoreCreateMutex(); + configASSERT( xLocalMutex ); + + for( ;; ) + { + /* The first tests exercise the priority inheritance when two mutexes + are taken then returned in a different order to which they were + taken. */ + prvTakeTwoMutexesReturnInDifferentOrder( xMutex, xLocalMutex ); + + /* Just to show this task is still running. */ + ulLoopCounter2++; + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* The second tests exercise the priority inheritance when two mutexes + are taken then returned in the same order in which they were taken. */ + prvTakeTwoMutexesReturnInSameOrder( xMutex, xLocalMutex ); + + /* Just to show this task is still running. */ + ulLoopCounter2++; + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + } +} +/*-----------------------------------------------------------*/ + +static void prvMediumPriorityMutexTask( void *pvParameters ) +{ + ( void ) pvParameters; + + for( ;; ) + { + /* The medium priority task starts by suspending itself. The low + priority task will unsuspend this task when required. */ + vTaskSuspend( NULL ); + + /* When this task unsuspends all it does is increment the guarded + variable, this is so the low priority task knows that it has + executed. */ + ulGuardedVariable++; + } +} +/*-----------------------------------------------------------*/ + +static void prvHighPriorityMutexTask( void *pvParameters ) +{ +SemaphoreHandle_t xMutex = ( SemaphoreHandle_t ) pvParameters; + + for( ;; ) + { + /* The high priority task starts by suspending itself. The low + priority task will unsuspend this task when required. */ + vTaskSuspend( NULL ); + + /* When this task unsuspends all it does is attempt to obtain + the mutex. It should find the mutex is not available so a + block time is specified. */ + if( xSemaphoreTake( xMutex, portMAX_DELAY ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + /* When the mutex is eventually obtained it is just given back before + returning to suspend ready for the next cycle. */ + if( xSemaphoreGive( xMutex ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + } +} +/*-----------------------------------------------------------*/ + +/* NOTE: This function is not declared static to prevent compiler warnings in +demos where the function is declared but not used. */ +void vInterruptMutexTask( void *pvParameters ) +{ +const TickType_t xInterruptGivePeriod = pdMS_TO_TICKS( genqINTERRUPT_MUTEX_GIVE_PERIOD_MS ); +volatile uint32_t ulLoops = 0; + + /* Just to avoid compiler warnings. */ + ( void ) pvParameters; + + for( ;; ) + { + /* Has to wait longer than the time between gives to make sure it + should definitely have received the mutex. */ + if( xSemaphoreTake( xISRMutex, ( xInterruptGivePeriod * 2 ) ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + else + { + ulLoops++; + } + } +} +/*-----------------------------------------------------------*/ + +void vMutexISRInteractionTest( void ) +{ +static TickType_t xLastGiveTime = 0; +TickType_t xTimeNow; + + xTimeNow = xTaskGetTickCountFromISR(); + if( ( xTimeNow - xLastGiveTime ) >= pdMS_TO_TICKS( genqINTERRUPT_MUTEX_GIVE_PERIOD_MS ) ) + { + configASSERT( xISRMutex ); + xSemaphoreGiveFromISR( xISRMutex, NULL ); + xLastGiveTime = xTimeNow; + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +BaseType_t xAreGenericQueueTasksStillRunning( void ) +{ +static uint32_t ulLastLoopCounter = 0, ulLastLoopCounter2 = 0; + + /* If the demo task is still running then we expect the loop counters to + have incremented since this function was last called. */ + if( ulLastLoopCounter == ulLoopCounter ) + { + xErrorDetected = pdTRUE; + } + + if( ulLastLoopCounter2 == ulLoopCounter2 ) + { + xErrorDetected = pdTRUE; + } + + ulLastLoopCounter = ulLoopCounter; + ulLastLoopCounter2 = ulLoopCounter2; + + /* Errors detected in the task itself will have latched xErrorDetected + to true. */ + + return ( BaseType_t ) !xErrorDetected; +} + + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/IntQueue.c b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/IntQueue.c new file mode 100644 index 0000000..fcb7157 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/IntQueue.c @@ -0,0 +1,760 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* + * This file defines one of the more complex set of demo/test tasks. They are + * designed to stress test the queue implementation though pseudo simultaneous + * multiple reads and multiple writes from both tasks of varying priority and + * interrupts. The interrupts are prioritised such to ensure that nesting + * occurs (for those ports that support it). + * + * The test ensures that, while being accessed from three tasks and two + * interrupts, all the data sent to the queues is also received from + * the same queue, and that no duplicate items are either sent or received. + * The tests also ensure that a low priority task is never able to successfully + * read from or write to a queue when a task of higher priority is attempting + * the same operation. + */ + +/* Standard includes. */ +#include + +/* SafeRTOS includes. */ +#include "FreeRTOS.h" +#include "queue.h" +#include "task.h" + +/* Demo app includes. */ +#include "IntQueue.h" +#include "IntQueueTimer.h" + +#if( INCLUDE_eTaskGetState != 1 ) + #error INCLUDE_eTaskGetState must be set to 1 in FreeRTOSConfig.h to use this demo file. +#endif + +/* Priorities used by test tasks. */ +#ifndef intqHIGHER_PRIORITY + #define intqHIGHER_PRIORITY ( configMAX_PRIORITIES - 2 ) +#endif +#define intqLOWER_PRIORITY ( tskIDLE_PRIORITY ) + +/* The number of values to send/receive before checking that all values were +processed as expected. */ +#define intqNUM_VALUES_TO_LOG ( 200 ) +#define intqSHORT_DELAY ( 140 ) + +/* The value by which the value being sent to or received from a queue should +increment past intqNUM_VALUES_TO_LOG before we check that all values have been +sent/received correctly. This is done to ensure that all tasks and interrupts +accessing the queue have completed their accesses with the +intqNUM_VALUES_TO_LOG range. */ +#define intqVALUE_OVERRUN ( 50 ) + +/* The delay used by the polling task. A short delay is used for code +coverage. */ +#define intqONE_TICK_DELAY ( 1 ) + +/* Each task and interrupt is given a unique identifier. This value is used to +identify which task sent or received each value. The identifier is also used +to distinguish between two tasks that are running the same task function. */ +#define intqHIGH_PRIORITY_TASK1 ( ( UBaseType_t ) 1 ) +#define intqHIGH_PRIORITY_TASK2 ( ( UBaseType_t ) 2 ) +#define intqLOW_PRIORITY_TASK ( ( UBaseType_t ) 3 ) +#define intqFIRST_INTERRUPT ( ( UBaseType_t ) 4 ) +#define intqSECOND_INTERRUPT ( ( UBaseType_t ) 5 ) +#define intqQUEUE_LENGTH ( ( UBaseType_t ) 10 ) + +/* At least intqMIN_ACCEPTABLE_TASK_COUNT values should be sent to/received +from each queue by each task, otherwise an error is detected. */ +#define intqMIN_ACCEPTABLE_TASK_COUNT ( 5 ) + +/* Send the next value to the queue that is normally empty. This is called +from within the interrupts. */ +#define timerNORMALLY_EMPTY_TX() \ + if( xQueueIsQueueFullFromISR( xNormallyEmptyQueue ) != pdTRUE ) \ + { \ + UBaseType_t uxSavedInterruptStatus; \ + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); \ + { \ + uxValueForNormallyEmptyQueue++; \ + xQueueSendFromISR( xNormallyEmptyQueue, ( void * ) &uxValueForNormallyEmptyQueue, &xHigherPriorityTaskWoken ); \ + } \ + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \ + } \ + +/* Send the next value to the queue that is normally full. This is called +from within the interrupts. */ +#define timerNORMALLY_FULL_TX() \ + if( xQueueIsQueueFullFromISR( xNormallyFullQueue ) != pdTRUE ) \ + { \ + UBaseType_t uxSavedInterruptStatus; \ + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); \ + { \ + uxValueForNormallyFullQueue++; \ + xQueueSendFromISR( xNormallyFullQueue, ( void * ) &uxValueForNormallyFullQueue, &xHigherPriorityTaskWoken ); \ + } \ + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \ + } \ + +/* Receive a value from the normally empty queue. This is called from within +an interrupt. */ +#define timerNORMALLY_EMPTY_RX() \ + if( xQueueReceiveFromISR( xNormallyEmptyQueue, &uxRxedValue, &xHigherPriorityTaskWoken ) != pdPASS ) \ + { \ + prvQueueAccessLogError( __LINE__ ); \ + } \ + else \ + { \ + prvRecordValue_NormallyEmpty( uxRxedValue, intqSECOND_INTERRUPT ); \ + } + +/* Receive a value from the normally full queue. This is called from within +an interrupt. */ +#define timerNORMALLY_FULL_RX() \ + if( xQueueReceiveFromISR( xNormallyFullQueue, &uxRxedValue, &xHigherPriorityTaskWoken ) == pdPASS ) \ + { \ + prvRecordValue_NormallyFull( uxRxedValue, intqSECOND_INTERRUPT ); \ + } \ + + +/*-----------------------------------------------------------*/ + +/* The two queues used by the test. */ +static QueueHandle_t xNormallyEmptyQueue, xNormallyFullQueue; + +/* Variables used to detect a stall in one of the tasks. */ +static UBaseType_t uxHighPriorityLoops1 = 0, uxHighPriorityLoops2 = 0, uxLowPriorityLoops1 = 0, uxLowPriorityLoops2 = 0; + +/* Any unexpected behaviour sets xErrorStatus to fail and log the line that +caused the error in xErrorLine. */ +static BaseType_t xErrorStatus = pdPASS; +static volatile UBaseType_t xErrorLine = ( UBaseType_t ) 0; + +/* Used for sequencing between tasks. */ +static BaseType_t xWasSuspended = pdFALSE; + +/* The values that are sent to the queues. An incremented value is sent each +time to each queue. */ +volatile UBaseType_t uxValueForNormallyEmptyQueue = 0, uxValueForNormallyFullQueue = 0; + +/* A handle to some of the tasks is required so they can be suspended/resumed. */ +TaskHandle_t xHighPriorityNormallyEmptyTask1, xHighPriorityNormallyEmptyTask2, xHighPriorityNormallyFullTask1, xHighPriorityNormallyFullTask2; + +/* When a value is received in a queue the value is ticked off in the array +the array position of the value is set to a the identifier of the task or +interrupt that accessed the queue. This way missing or duplicate values can be +detected. */ +static uint8_t ucNormallyEmptyReceivedValues[ intqNUM_VALUES_TO_LOG ] = { 0 }; +static uint8_t ucNormallyFullReceivedValues[ intqNUM_VALUES_TO_LOG ] = { 0 }; + +/* The test tasks themselves. */ +static void prvLowerPriorityNormallyEmptyTask( void *pvParameters ); +static void prvLowerPriorityNormallyFullTask( void *pvParameters ); +static void prvHigherPriorityNormallyEmptyTask( void *pvParameters ); +static void prv1stHigherPriorityNormallyFullTask( void *pvParameters ); +static void prv2ndHigherPriorityNormallyFullTask( void *pvParameters ); + +/* Used to mark the positions within the ucNormallyEmptyReceivedValues and +ucNormallyFullReceivedValues arrays, while checking for duplicates. */ +static void prvRecordValue_NormallyEmpty( UBaseType_t uxValue, UBaseType_t uxSource ); +static void prvRecordValue_NormallyFull( UBaseType_t uxValue, UBaseType_t uxSource ); + +/* Logs the line on which an error occurred. */ +static void prvQueueAccessLogError( UBaseType_t uxLine ); + +/*-----------------------------------------------------------*/ + +void vStartInterruptQueueTasks( void ) +{ + /* Start the test tasks. */ + xTaskCreate( prvHigherPriorityNormallyEmptyTask, "H1QRx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK1, intqHIGHER_PRIORITY, &xHighPriorityNormallyEmptyTask1 ); + xTaskCreate( prvHigherPriorityNormallyEmptyTask, "H2QRx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK2, intqHIGHER_PRIORITY, &xHighPriorityNormallyEmptyTask2 ); + xTaskCreate( prvLowerPriorityNormallyEmptyTask, "L1QRx", configMINIMAL_STACK_SIZE, NULL, intqLOWER_PRIORITY, NULL ); + xTaskCreate( prv1stHigherPriorityNormallyFullTask, "H1QTx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK1, intqHIGHER_PRIORITY, &xHighPriorityNormallyFullTask1 ); + xTaskCreate( prv2ndHigherPriorityNormallyFullTask, "H2QTx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK2, intqHIGHER_PRIORITY, &xHighPriorityNormallyFullTask2 ); + xTaskCreate( prvLowerPriorityNormallyFullTask, "L2QRx", configMINIMAL_STACK_SIZE, NULL, intqLOWER_PRIORITY, NULL ); + + /* Create the queues that are accessed by multiple tasks and multiple + interrupts. */ + xNormallyFullQueue = xQueueCreate( intqQUEUE_LENGTH, ( UBaseType_t ) sizeof( UBaseType_t ) ); + xNormallyEmptyQueue = xQueueCreate( intqQUEUE_LENGTH, ( UBaseType_t ) sizeof( UBaseType_t ) ); + + /* vQueueAddToRegistry() adds the queue to the queue registry, if one is + in use. The queue registry is provided as a means for kernel aware + debuggers to locate queues and has no purpose if a kernel aware debugger + is not being used. The call to vQueueAddToRegistry() will be removed + by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is + defined to be less than 1. */ + vQueueAddToRegistry( xNormallyFullQueue, "NormallyFull" ); + vQueueAddToRegistry( xNormallyEmptyQueue, "NormallyEmpty" ); +} +/*-----------------------------------------------------------*/ + +static void prvRecordValue_NormallyFull( UBaseType_t uxValue, UBaseType_t uxSource ) +{ + if( uxValue < intqNUM_VALUES_TO_LOG ) + { + /* We don't expect to receive the same value twice, so if the value + has already been marked as received an error has occurred. */ + if( ucNormallyFullReceivedValues[ uxValue ] != 0x00 ) + { + prvQueueAccessLogError( __LINE__ ); + } + + /* Log that this value has been received. */ + ucNormallyFullReceivedValues[ uxValue ] = ( uint8_t ) uxSource; + } +} +/*-----------------------------------------------------------*/ + +static void prvRecordValue_NormallyEmpty( UBaseType_t uxValue, UBaseType_t uxSource ) +{ + if( uxValue < intqNUM_VALUES_TO_LOG ) + { + /* We don't expect to receive the same value twice, so if the value + has already been marked as received an error has occurred. */ + if( ucNormallyEmptyReceivedValues[ uxValue ] != 0x00 ) + { + prvQueueAccessLogError( __LINE__ ); + } + + /* Log that this value has been received. */ + ucNormallyEmptyReceivedValues[ uxValue ] = ( uint8_t ) uxSource; + } +} +/*-----------------------------------------------------------*/ + +static void prvQueueAccessLogError( UBaseType_t uxLine ) +{ + /* Latch the line number that caused the error. */ + xErrorLine = uxLine; + xErrorStatus = pdFAIL; +} +/*-----------------------------------------------------------*/ + +static void prvHigherPriorityNormallyEmptyTask( void *pvParameters ) +{ +UBaseType_t uxRxed, ux, uxTask1, uxTask2, uxInterrupts, uxErrorCount1 = 0, uxErrorCount2 = 0; + + /* The timer should not be started until after the scheduler has started. + More than one task is running this code so we check the parameter value + to determine which task should start the timer. */ + if( ( UBaseType_t ) pvParameters == intqHIGH_PRIORITY_TASK1 ) + { + vInitialiseTimerForIntQueueTest(); + } + + for( ;; ) + { + /* Block waiting to receive a value from the normally empty queue. + Interrupts will write to the queue so we should receive a value. */ + if( xQueueReceive( xNormallyEmptyQueue, &uxRxed, intqSHORT_DELAY ) != pdPASS ) + { + prvQueueAccessLogError( __LINE__ ); + } + else + { + /* Note which value was received so we can check all expected + values are received and no values are duplicated. */ + prvRecordValue_NormallyEmpty( uxRxed, ( UBaseType_t ) pvParameters ); + } + + /* Ensure the other task running this code gets a chance to execute. */ + taskYIELD(); + + if( ( UBaseType_t ) pvParameters == intqHIGH_PRIORITY_TASK1 ) + { + /* Have we received all the expected values? */ + if( uxValueForNormallyEmptyQueue > ( intqNUM_VALUES_TO_LOG + intqVALUE_OVERRUN ) ) + { + vTaskSuspend( xHighPriorityNormallyEmptyTask2 ); + + uxTask1 = 0; + uxTask2 = 0; + uxInterrupts = 0; + + /* Loop through the array, checking that both tasks have + placed values into the array, and that no values are missing. + Start at 1 as we expect position 0 to be unused. */ + for( ux = 1; ux < intqNUM_VALUES_TO_LOG; ux++ ) + { + if( ucNormallyEmptyReceivedValues[ ux ] == 0 ) + { + /* A value is missing. */ + prvQueueAccessLogError( __LINE__ ); + } + else + { + if( ucNormallyEmptyReceivedValues[ ux ] == intqHIGH_PRIORITY_TASK1 ) + { + /* Value was placed into the array by task 1. */ + uxTask1++; + } + else if( ucNormallyEmptyReceivedValues[ ux ] == intqHIGH_PRIORITY_TASK2 ) + { + /* Value was placed into the array by task 2. */ + uxTask2++; + } + else if( ucNormallyEmptyReceivedValues[ ux ] == intqSECOND_INTERRUPT ) + { + uxInterrupts++; + } + } + } + + if( uxTask1 < intqMIN_ACCEPTABLE_TASK_COUNT ) + { + /* Only task 2 seemed to log any values. */ + uxErrorCount1++; + if( uxErrorCount1 > 2 ) + { + prvQueueAccessLogError( __LINE__ ); + } + } + else + { + uxErrorCount1 = 0; + } + + if( uxTask2 < intqMIN_ACCEPTABLE_TASK_COUNT ) + { + /* Only task 1 seemed to log any values. */ + uxErrorCount2++; + if( uxErrorCount2 > 2 ) + { + prvQueueAccessLogError( __LINE__ ); + } + } + else + { + uxErrorCount2 = 0; + } + + if( uxInterrupts == 0 ) + { + prvQueueAccessLogError( __LINE__ ); + } + + /* Clear the array again, ready to start a new cycle. */ + memset( ucNormallyEmptyReceivedValues, 0x00, sizeof( ucNormallyEmptyReceivedValues ) ); + + uxHighPriorityLoops1++; + uxValueForNormallyEmptyQueue = 0; + + /* Suspend ourselves, allowing the lower priority task to + actually receive something from the queue. Until now it + will have been prevented from doing so by the higher + priority tasks. The lower priority task will resume us + if it receives something. We will then resume the other + higher priority task. */ + vTaskSuspend( NULL ); + vTaskResume( xHighPriorityNormallyEmptyTask2 ); + } + } + } +} +/*-----------------------------------------------------------*/ + +static void prvLowerPriorityNormallyEmptyTask( void *pvParameters ) +{ +UBaseType_t uxValue, uxRxed; + + /* The parameters are not being used so avoid compiler warnings. */ + ( void ) pvParameters; + + for( ;; ) + { + if( xQueueReceive( xNormallyEmptyQueue, &uxRxed, intqONE_TICK_DELAY ) != errQUEUE_EMPTY ) + { + /* A value should only be obtained when the high priority task is + suspended. */ + if( eTaskGetState( xHighPriorityNormallyEmptyTask1 ) != eSuspended ) + { + prvQueueAccessLogError( __LINE__ ); + } + + prvRecordValue_NormallyEmpty( uxRxed, intqLOW_PRIORITY_TASK ); + + /* Wake the higher priority task again. */ + vTaskResume( xHighPriorityNormallyEmptyTask1 ); + uxLowPriorityLoops1++; + } + else + { + /* Raise our priority while we send so we can preempt the higher + priority task, and ensure we get the Tx value into the queue. */ + vTaskPrioritySet( NULL, intqHIGHER_PRIORITY + 1 ); + + portENTER_CRITICAL(); + { + uxValueForNormallyEmptyQueue++; + uxValue = uxValueForNormallyEmptyQueue; + } + portEXIT_CRITICAL(); + + if( xQueueSend( xNormallyEmptyQueue, &uxValue, portMAX_DELAY ) != pdPASS ) + { + prvQueueAccessLogError( __LINE__ ); + } + + vTaskPrioritySet( NULL, intqLOWER_PRIORITY ); + } + } +} +/*-----------------------------------------------------------*/ + +static void prv1stHigherPriorityNormallyFullTask( void *pvParameters ) +{ +UBaseType_t uxValueToTx, ux, uxInterrupts; + + /* The parameters are not being used so avoid compiler warnings. */ + ( void ) pvParameters; + + /* Make sure the queue starts full or near full. >> 1 as there are two + high priority tasks. */ + for( ux = 0; ux < ( intqQUEUE_LENGTH >> 1 ); ux++ ) + { + portENTER_CRITICAL(); + { + uxValueForNormallyFullQueue++; + uxValueToTx = uxValueForNormallyFullQueue; + } + portEXIT_CRITICAL(); + + xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY ); + } + + for( ;; ) + { + portENTER_CRITICAL(); + { + uxValueForNormallyFullQueue++; + uxValueToTx = uxValueForNormallyFullQueue; + } + portEXIT_CRITICAL(); + + if( xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY ) != pdPASS ) + { + /* intqHIGH_PRIORITY_TASK2 is never suspended so we would not + expect it to ever time out. */ + prvQueueAccessLogError( __LINE__ ); + } + + /* Allow the other task running this code to run. */ + taskYIELD(); + + /* Have all the expected values been sent to the queue? */ + if( uxValueToTx > ( intqNUM_VALUES_TO_LOG + intqVALUE_OVERRUN ) ) + { + /* Make sure the other high priority task completes its send of + any values below intqNUM_VALUE_TO_LOG. */ + vTaskDelay( intqSHORT_DELAY ); + + vTaskSuspend( xHighPriorityNormallyFullTask2 ); + + if( xWasSuspended == pdTRUE ) + { + /* We would have expected the other high priority task to have + set this back to false by now. */ + prvQueueAccessLogError( __LINE__ ); + } + + /* Set the suspended flag so an error is not logged if the other + task recognises a time out when it is unsuspended. */ + xWasSuspended = pdTRUE; + + /* Check interrupts are also sending. */ + uxInterrupts = 0U; + + /* Start at 1 as we expect position 0 to be unused. */ + for( ux = 1; ux < intqNUM_VALUES_TO_LOG; ux++ ) + { + if( ucNormallyFullReceivedValues[ ux ] == 0 ) + { + /* A value was missing. */ + prvQueueAccessLogError( __LINE__ ); + } + else if( ucNormallyFullReceivedValues[ ux ] == intqSECOND_INTERRUPT ) + { + uxInterrupts++; + } + } + + if( uxInterrupts == 0 ) + { + /* No writes from interrupts were found. Are interrupts + actually running? */ + prvQueueAccessLogError( __LINE__ ); + } + + /* Reset the array ready for the next cycle. */ + memset( ucNormallyFullReceivedValues, 0x00, sizeof( ucNormallyFullReceivedValues ) ); + + uxHighPriorityLoops2++; + uxValueForNormallyFullQueue = 0; + + /* Suspend ourselves, allowing the lower priority task to + actually receive something from the queue. Until now it + will have been prevented from doing so by the higher + priority tasks. The lower priority task will resume us + if it receives something. We will then resume the other + higher priority task. */ + vTaskSuspend( NULL ); + vTaskResume( xHighPriorityNormallyFullTask2 ); + } + } +} +/*-----------------------------------------------------------*/ + +static void prv2ndHigherPriorityNormallyFullTask( void *pvParameters ) +{ +UBaseType_t uxValueToTx, ux; + + /* The parameters are not being used so avoid compiler warnings. */ + ( void ) pvParameters; + + /* Make sure the queue starts full or near full. >> 1 as there are two + high priority tasks. */ + for( ux = 0; ux < ( intqQUEUE_LENGTH >> 1 ); ux++ ) + { + portENTER_CRITICAL(); + { + uxValueForNormallyFullQueue++; + uxValueToTx = uxValueForNormallyFullQueue; + } + portEXIT_CRITICAL(); + + xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY ); + } + + for( ;; ) + { + portENTER_CRITICAL(); + { + uxValueForNormallyFullQueue++; + uxValueToTx = uxValueForNormallyFullQueue; + } + portEXIT_CRITICAL(); + + if( xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY ) != pdPASS ) + { + if( xWasSuspended != pdTRUE ) + { + /* It is ok to time out if the task has been suspended. */ + prvQueueAccessLogError( __LINE__ ); + } + } + + xWasSuspended = pdFALSE; + + taskYIELD(); + } +} +/*-----------------------------------------------------------*/ + +static void prvLowerPriorityNormallyFullTask( void *pvParameters ) +{ +UBaseType_t uxValue, uxTxed = 9999; + + /* The parameters are not being used so avoid compiler warnings. */ + ( void ) pvParameters; + + for( ;; ) + { + if( xQueueSend( xNormallyFullQueue, &uxTxed, intqONE_TICK_DELAY ) != errQUEUE_FULL ) + { + /* Should only succeed when the higher priority task is suspended */ + if( eTaskGetState( xHighPriorityNormallyFullTask1 ) != eSuspended ) + { + prvQueueAccessLogError( __LINE__ ); + } + + vTaskResume( xHighPriorityNormallyFullTask1 ); + uxLowPriorityLoops2++; + } + else + { + /* Raise our priority while we receive so we can preempt the higher + priority task, and ensure we get the value from the queue. */ + vTaskPrioritySet( NULL, intqHIGHER_PRIORITY + 1 ); + + if( xQueueReceive( xNormallyFullQueue, &uxValue, portMAX_DELAY ) != pdPASS ) + { + prvQueueAccessLogError( __LINE__ ); + } + else + { + prvRecordValue_NormallyFull( uxValue, intqLOW_PRIORITY_TASK ); + } + + vTaskPrioritySet( NULL, intqLOWER_PRIORITY ); + } + } +} +/*-----------------------------------------------------------*/ + +BaseType_t xFirstTimerHandler( void ) +{ +BaseType_t xHigherPriorityTaskWoken = pdFALSE; +UBaseType_t uxRxedValue; +static UBaseType_t uxNextOperation = 0; + + /* Called from a timer interrupt. Perform various read and write + accesses on the queues. */ + + uxNextOperation++; + + if( uxNextOperation & ( UBaseType_t ) 0x01 ) + { + timerNORMALLY_EMPTY_TX(); + timerNORMALLY_EMPTY_TX(); + timerNORMALLY_EMPTY_TX(); + } + else + { + timerNORMALLY_FULL_RX(); + timerNORMALLY_FULL_RX(); + timerNORMALLY_FULL_RX(); + } + + return xHigherPriorityTaskWoken; +} +/*-----------------------------------------------------------*/ + +BaseType_t xSecondTimerHandler( void ) +{ +UBaseType_t uxRxedValue; +BaseType_t xHigherPriorityTaskWoken = pdFALSE; +static UBaseType_t uxNextOperation = 0; + + /* Called from a timer interrupt. Perform various read and write + accesses on the queues. */ + + uxNextOperation++; + + if( uxNextOperation & ( UBaseType_t ) 0x01 ) + { + timerNORMALLY_EMPTY_TX(); + timerNORMALLY_EMPTY_TX(); + + timerNORMALLY_EMPTY_RX(); + timerNORMALLY_EMPTY_RX(); + } + else + { + timerNORMALLY_FULL_RX(); + timerNORMALLY_FULL_TX(); + timerNORMALLY_FULL_TX(); + timerNORMALLY_FULL_TX(); + timerNORMALLY_FULL_TX(); + } + + return xHigherPriorityTaskWoken; +} +/*-----------------------------------------------------------*/ + + +BaseType_t xAreIntQueueTasksStillRunning( void ) +{ +static UBaseType_t uxLastHighPriorityLoops1 = 0, uxLastHighPriorityLoops2 = 0, uxLastLowPriorityLoops1 = 0, uxLastLowPriorityLoops2 = 0; + + /* xErrorStatus can be set outside of this function. This function just + checks that all the tasks are still cycling. */ + + if( uxHighPriorityLoops1 == uxLastHighPriorityLoops1 ) + { + /* The high priority 1 task has stalled. */ + prvQueueAccessLogError( __LINE__ ); + } + + uxLastHighPriorityLoops1 = uxHighPriorityLoops1; + + if( uxHighPriorityLoops2 == uxLastHighPriorityLoops2 ) + { + /* The high priority 2 task has stalled. */ + prvQueueAccessLogError( __LINE__ ); + } + + uxLastHighPriorityLoops2 = uxHighPriorityLoops2; + + if( uxLowPriorityLoops1 == uxLastLowPriorityLoops1 ) + { + /* The low priority 1 task has stalled. */ + prvQueueAccessLogError( __LINE__ ); + } + + uxLastLowPriorityLoops1 = uxLowPriorityLoops1; + + if( uxLowPriorityLoops2 == uxLastLowPriorityLoops2 ) + { + /* The low priority 2 task has stalled. */ + prvQueueAccessLogError( __LINE__ ); + } + + uxLastLowPriorityLoops2 = uxLowPriorityLoops2; + + return xErrorStatus; +} + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/PollQ.c b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/PollQ.c new file mode 100644 index 0000000..4782f61 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/PollQ.c @@ -0,0 +1,258 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* + * This version of PollQ. c is for use on systems that have limited stack + * space and no display facilities. The complete version can be found in + * the Demo/Common/Full directory. + * + * Creates two tasks that communicate over a single queue. One task acts as a + * producer, the other a consumer. + * + * The producer loops for three iteration, posting an incrementing number onto the + * queue each cycle. It then delays for a fixed period before doing exactly the + * same again. + * + * The consumer loops emptying the queue. Each item removed from the queue is + * checked to ensure it contains the expected value. When the queue is empty it + * blocks for a fixed period, then does the same again. + * + * All queue access is performed without blocking. The consumer completely empties + * the queue each time it runs so the producer should never find the queue full. + * + * An error is flagged if the consumer obtains an unexpected value or the producer + * find the queue is full. + */ + +/* +Changes from V2.0.0 + + + Delay periods are now specified using variables and constants of + TickType_t rather than uint32_t. +*/ + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +/* Demo program include files. */ +#include "PollQ.h" + +#define pollqSTACK_SIZE configMINIMAL_STACK_SIZE +#define pollqQUEUE_SIZE ( 10 ) +#define pollqPRODUCER_DELAY ( ( TickType_t ) 200 / portTICK_PERIOD_MS ) +#define pollqCONSUMER_DELAY ( pollqPRODUCER_DELAY - ( TickType_t ) ( 20 / portTICK_PERIOD_MS ) ) +#define pollqNO_DELAY ( ( TickType_t ) 0 ) +#define pollqVALUES_TO_PRODUCE ( ( BaseType_t ) 3 ) +#define pollqINITIAL_VALUE ( ( BaseType_t ) 0 ) + +/* The task that posts the incrementing number onto the queue. */ +static portTASK_FUNCTION_PROTO( vPolledQueueProducer, pvParameters ); + +/* The task that empties the queue. */ +static portTASK_FUNCTION_PROTO( vPolledQueueConsumer, pvParameters ); + +/* Variables that are used to check that the tasks are still running with no +errors. */ +static volatile BaseType_t xPollingConsumerCount = pollqINITIAL_VALUE, xPollingProducerCount = pollqINITIAL_VALUE; + +/*-----------------------------------------------------------*/ + +void vStartPolledQueueTasks( UBaseType_t uxPriority ) +{ +static QueueHandle_t xPolledQueue; + + /* Create the queue used by the producer and consumer. */ + xPolledQueue = xQueueCreate( pollqQUEUE_SIZE, ( UBaseType_t ) sizeof( uint16_t ) ); + + /* vQueueAddToRegistry() adds the queue to the queue registry, if one is + in use. The queue registry is provided as a means for kernel aware + debuggers to locate queues and has no purpose if a kernel aware debugger + is not being used. The call to vQueueAddToRegistry() will be removed + by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is + defined to be less than 1. */ + vQueueAddToRegistry( xPolledQueue, "Poll_Test_Queue" ); + + /* Spawn the producer and consumer. */ + xTaskCreate( vPolledQueueConsumer, "QConsNB", pollqSTACK_SIZE, ( void * ) &xPolledQueue, uxPriority, ( TaskHandle_t * ) NULL ); + xTaskCreate( vPolledQueueProducer, "QProdNB", pollqSTACK_SIZE, ( void * ) &xPolledQueue, uxPriority, ( TaskHandle_t * ) NULL ); +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vPolledQueueProducer, pvParameters ) +{ +uint16_t usValue = ( uint16_t ) 0; +BaseType_t xError = pdFALSE, xLoop; + + for( ;; ) + { + for( xLoop = 0; xLoop < pollqVALUES_TO_PRODUCE; xLoop++ ) + { + /* Send an incrementing number on the queue without blocking. */ + if( xQueueSend( *( ( QueueHandle_t * ) pvParameters ), ( void * ) &usValue, pollqNO_DELAY ) != pdPASS ) + { + /* We should never find the queue full so if we get here there + has been an error. */ + xError = pdTRUE; + } + else + { + if( xError == pdFALSE ) + { + /* If an error has ever been recorded we stop incrementing the + check variable. */ + portENTER_CRITICAL(); + xPollingProducerCount++; + portEXIT_CRITICAL(); + } + + /* Update the value we are going to post next time around. */ + usValue++; + } + } + + /* Wait before we start posting again to ensure the consumer runs and + empties the queue. */ + vTaskDelay( pollqPRODUCER_DELAY ); + } +} /*lint !e818 Function prototype must conform to API. */ +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vPolledQueueConsumer, pvParameters ) +{ +uint16_t usData, usExpectedValue = ( uint16_t ) 0; +BaseType_t xError = pdFALSE; + + for( ;; ) + { + /* Loop until the queue is empty. */ + while( uxQueueMessagesWaiting( *( ( QueueHandle_t * ) pvParameters ) ) ) + { + if( xQueueReceive( *( ( QueueHandle_t * ) pvParameters ), &usData, pollqNO_DELAY ) == pdPASS ) + { + if( usData != usExpectedValue ) + { + /* This is not what we expected to receive so an error has + occurred. */ + xError = pdTRUE; + + /* Catch-up to the value we received so our next expected + value should again be correct. */ + usExpectedValue = usData; + } + else + { + if( xError == pdFALSE ) + { + /* Only increment the check variable if no errors have + occurred. */ + portENTER_CRITICAL(); + xPollingConsumerCount++; + portEXIT_CRITICAL(); + } + } + + /* Next time round we would expect the number to be one higher. */ + usExpectedValue++; + } + } + + /* Now the queue is empty we block, allowing the producer to place more + items in the queue. */ + vTaskDelay( pollqCONSUMER_DELAY ); + } +} /*lint !e818 Function prototype must conform to API. */ +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running with no errors. */ +BaseType_t xArePollingQueuesStillRunning( void ) +{ +BaseType_t xReturn; + + /* Check both the consumer and producer poll count to check they have both + been changed since out last trip round. We do not need a critical section + around the check variables as this is called from a higher priority than + the other tasks that access the same variables. */ + if( ( xPollingConsumerCount == pollqINITIAL_VALUE ) || + ( xPollingProducerCount == pollqINITIAL_VALUE ) + ) + { + xReturn = pdFALSE; + } + else + { + xReturn = pdTRUE; + } + + /* Set the check variables back down so we know if they have been + incremented the next time around. */ + xPollingConsumerCount = pollqINITIAL_VALUE; + xPollingProducerCount = pollqINITIAL_VALUE; + + return xReturn; +} diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/QPeek.c b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/QPeek.c new file mode 100644 index 0000000..4f4caa9 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/QPeek.c @@ -0,0 +1,474 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +/* + * Tests the behaviour when data is peeked from a queue when there are + * multiple tasks blocked on the queue. + */ + + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "semphr.h" + +/* Demo program include files. */ +#include "QPeek.h" + +#define qpeekQUEUE_LENGTH ( 5 ) +#define qpeekNO_BLOCK ( 0 ) +#define qpeekSHORT_DELAY ( 10 ) + +#define qpeekLOW_PRIORITY ( tskIDLE_PRIORITY + 0 ) +#define qpeekMEDIUM_PRIORITY ( tskIDLE_PRIORITY + 1 ) +#define qpeekHIGH_PRIORITY ( tskIDLE_PRIORITY + 2 ) +#define qpeekHIGHEST_PRIORITY ( tskIDLE_PRIORITY + 3 ) + +/*-----------------------------------------------------------*/ + +/* + * The following three tasks are used to demonstrate the peeking behaviour. + * Each task is given a different priority to demonstrate the order in which + * tasks are woken as data is peeked from a queue. + */ +static void prvLowPriorityPeekTask( void *pvParameters ); +static void prvMediumPriorityPeekTask( void *pvParameters ); +static void prvHighPriorityPeekTask( void *pvParameters ); +static void prvHighestPriorityPeekTask( void *pvParameters ); + +/*-----------------------------------------------------------*/ + +/* Flag that will be latched to pdTRUE should any unexpected behaviour be +detected in any of the tasks. */ +static volatile BaseType_t xErrorDetected = pdFALSE; + +/* Counter that is incremented on each cycle of a test. This is used to +detect a stalled task - a test that is no longer running. */ +static volatile uint32_t ulLoopCounter = 0; + +/* Handles to the test tasks. */ +TaskHandle_t xMediumPriorityTask, xHighPriorityTask, xHighestPriorityTask; +/*-----------------------------------------------------------*/ + +void vStartQueuePeekTasks( void ) +{ +QueueHandle_t xQueue; + + /* Create the queue that we are going to use for the test/demo. */ + xQueue = xQueueCreate( qpeekQUEUE_LENGTH, sizeof( uint32_t ) ); + + /* vQueueAddToRegistry() adds the queue to the queue registry, if one is + in use. The queue registry is provided as a means for kernel aware + debuggers to locate queues and has no purpose if a kernel aware debugger + is not being used. The call to vQueueAddToRegistry() will be removed + by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is + defined to be less than 1. */ + vQueueAddToRegistry( xQueue, "QPeek_Test_Queue" ); + + /* Create the demo tasks and pass it the queue just created. We are + passing the queue handle by value so it does not matter that it is declared + on the stack here. */ + xTaskCreate( prvLowPriorityPeekTask, "PeekL", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekLOW_PRIORITY, NULL ); + xTaskCreate( prvMediumPriorityPeekTask, "PeekM", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekMEDIUM_PRIORITY, &xMediumPriorityTask ); + xTaskCreate( prvHighPriorityPeekTask, "PeekH1", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekHIGH_PRIORITY, &xHighPriorityTask ); + xTaskCreate( prvHighestPriorityPeekTask, "PeekH2", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekHIGHEST_PRIORITY, &xHighestPriorityTask ); +} +/*-----------------------------------------------------------*/ + +static void prvHighestPriorityPeekTask( void *pvParameters ) +{ +QueueHandle_t xQueue = ( QueueHandle_t ) pvParameters; +uint32_t ulValue; + + #ifdef USE_STDIO + { + void vPrintDisplayMessage( const char * const * ppcMessageToSend ); + + const char * const pcTaskStartMsg = "Queue peek test started.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + } + #endif + + for( ;; ) + { + /* Try peeking from the queue. The queue should be empty so we will + block, allowing the high priority task to execute. */ + if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS ) + { + /* We expected to have received something by the time we unblock. */ + xErrorDetected = pdTRUE; + } + + /* When we reach here the high and medium priority tasks should still + be blocked on the queue. We unblocked because the low priority task + wrote a value to the queue, which we should have peeked. Peeking the + data (rather than receiving it) will leave the data on the queue, so + the high priority task should then have also been unblocked, but not + yet executed. */ + if( ulValue != 0x11223344 ) + { + /* We did not receive the expected value. */ + xErrorDetected = pdTRUE; + } + + if( uxQueueMessagesWaiting( xQueue ) != 1 ) + { + /* The message should have been left on the queue. */ + xErrorDetected = pdTRUE; + } + + /* Now we are going to actually receive the data, so when the high + priority task runs it will find the queue empty and return to the + blocked state. */ + ulValue = 0; + if( xQueueReceive( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS ) + { + /* We expected to receive the value. */ + xErrorDetected = pdTRUE; + } + + if( ulValue != 0x11223344 ) + { + /* We did not receive the expected value - which should have been + the same value as was peeked. */ + xErrorDetected = pdTRUE; + } + + /* Now we will block again as the queue is once more empty. The low + priority task can then execute again. */ + if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS ) + { + /* We expected to have received something by the time we unblock. */ + xErrorDetected = pdTRUE; + } + + /* When we get here the low priority task should have again written to the + queue. */ + if( ulValue != 0x01234567 ) + { + /* We did not receive the expected value. */ + xErrorDetected = pdTRUE; + } + + if( uxQueueMessagesWaiting( xQueue ) != 1 ) + { + /* The message should have been left on the queue. */ + xErrorDetected = pdTRUE; + } + + /* We only peeked the data, so suspending ourselves now should enable + the high priority task to also peek the data. The high priority task + will have been unblocked when we peeked the data as we left the data + in the queue. */ + vTaskSuspend( NULL ); + + + + /* This time we are going to do the same as the above test, but the + high priority task is going to receive the data, rather than peek it. + This means that the medium priority task should never peek the value. */ + if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + if( ulValue != 0xaabbaabb ) + { + xErrorDetected = pdTRUE; + } + + vTaskSuspend( NULL ); + } +} +/*-----------------------------------------------------------*/ + +static void prvHighPriorityPeekTask( void *pvParameters ) +{ +QueueHandle_t xQueue = ( QueueHandle_t ) pvParameters; +uint32_t ulValue; + + for( ;; ) + { + /* Try peeking from the queue. The queue should be empty so we will + block, allowing the medium priority task to execute. Both the high + and highest priority tasks will then be blocked on the queue. */ + if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS ) + { + /* We expected to have received something by the time we unblock. */ + xErrorDetected = pdTRUE; + } + + /* When we get here the highest priority task should have peeked the data + (unblocking this task) then suspended (allowing this task to also peek + the data). */ + if( ulValue != 0x01234567 ) + { + /* We did not receive the expected value. */ + xErrorDetected = pdTRUE; + } + + if( uxQueueMessagesWaiting( xQueue ) != 1 ) + { + /* The message should have been left on the queue. */ + xErrorDetected = pdTRUE; + } + + /* We only peeked the data, so suspending ourselves now should enable + the medium priority task to also peek the data. The medium priority task + will have been unblocked when we peeked the data as we left the data + in the queue. */ + vTaskSuspend( NULL ); + + + /* This time we are going actually receive the value, so the medium + priority task will never peek the data - we removed it from the queue. */ + if( xQueueReceive( xQueue, &ulValue, portMAX_DELAY ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + if( ulValue != 0xaabbaabb ) + { + xErrorDetected = pdTRUE; + } + + vTaskSuspend( NULL ); + } +} +/*-----------------------------------------------------------*/ + +static void prvMediumPriorityPeekTask( void *pvParameters ) +{ +QueueHandle_t xQueue = ( QueueHandle_t ) pvParameters; +uint32_t ulValue; + + for( ;; ) + { + /* Try peeking from the queue. The queue should be empty so we will + block, allowing the low priority task to execute. The highest, high + and medium priority tasks will then all be blocked on the queue. */ + if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS ) + { + /* We expected to have received something by the time we unblock. */ + xErrorDetected = pdTRUE; + } + + /* When we get here the high priority task should have peeked the data + (unblocking this task) then suspended (allowing this task to also peek + the data). */ + if( ulValue != 0x01234567 ) + { + /* We did not receive the expected value. */ + xErrorDetected = pdTRUE; + } + + if( uxQueueMessagesWaiting( xQueue ) != 1 ) + { + /* The message should have been left on the queue. */ + xErrorDetected = pdTRUE; + } + + /* Just so we know the test is still running. */ + ulLoopCounter++; + + /* Now we can suspend ourselves so the low priority task can execute + again. */ + vTaskSuspend( NULL ); + } +} +/*-----------------------------------------------------------*/ + +static void prvLowPriorityPeekTask( void *pvParameters ) +{ +QueueHandle_t xQueue = ( QueueHandle_t ) pvParameters; +uint32_t ulValue; + + for( ;; ) + { + /* Write some data to the queue. This should unblock the highest + priority task that is waiting to peek data from the queue. */ + ulValue = 0x11223344; + if( xQueueSendToBack( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS ) + { + /* We were expecting the queue to be empty so we should not of + had a problem writing to the queue. */ + xErrorDetected = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* By the time we get here the data should have been removed from + the queue. */ + if( uxQueueMessagesWaiting( xQueue ) != 0 ) + { + xErrorDetected = pdTRUE; + } + + /* Write another value to the queue, again waking the highest priority + task that is blocked on the queue. */ + ulValue = 0x01234567; + if( xQueueSendToBack( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS ) + { + /* We were expecting the queue to be empty so we should not of + had a problem writing to the queue. */ + xErrorDetected = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* All the other tasks should now have successfully peeked the data. + The data is still in the queue so we should be able to receive it. */ + ulValue = 0; + if( xQueueReceive( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS ) + { + /* We expected to receive the data. */ + xErrorDetected = pdTRUE; + } + + if( ulValue != 0x01234567 ) + { + /* We did not receive the expected value. */ + } + + /* Lets just delay a while as this is an intensive test as we don't + want to starve other tests of processing time. */ + vTaskDelay( qpeekSHORT_DELAY ); + + /* Unsuspend the other tasks so we can repeat the test - this time + however not all the other tasks will peek the data as the high + priority task is actually going to remove it from the queue. Send + to front is used just to be different. As the queue is empty it + makes no difference to the result. */ + vTaskResume( xMediumPriorityTask ); + vTaskResume( xHighPriorityTask ); + vTaskResume( xHighestPriorityTask ); + + #if( configUSE_PREEMPTION == 0 ) + taskYIELD(); + #endif + + ulValue = 0xaabbaabb; + if( xQueueSendToFront( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS ) + { + /* We were expecting the queue to be empty so we should not of + had a problem writing to the queue. */ + xErrorDetected = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* This time we should find that the queue is empty. The high priority + task actually removed the data rather than just peeking it. */ + if( xQueuePeek( xQueue, &ulValue, qpeekNO_BLOCK ) != errQUEUE_EMPTY ) + { + /* We expected to receive the data. */ + xErrorDetected = pdTRUE; + } + + /* Unsuspend the highest and high priority tasks so we can go back + and repeat the whole thing. The medium priority task should not be + suspended as it was not able to peek the data in this last case. */ + vTaskResume( xHighPriorityTask ); + vTaskResume( xHighestPriorityTask ); + + /* Lets just delay a while as this is an intensive test as we don't + want to starve other tests of processing time. */ + vTaskDelay( qpeekSHORT_DELAY ); + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +BaseType_t xAreQueuePeekTasksStillRunning( void ) +{ +static uint32_t ulLastLoopCounter = 0; + + /* If the demo task is still running then we expect the loopcounter to + have incremented since this function was last called. */ + if( ulLastLoopCounter == ulLoopCounter ) + { + xErrorDetected = pdTRUE; + } + + ulLastLoopCounter = ulLoopCounter; + + /* Errors detected in the task itself will have latched xErrorDetected + to true. */ + + return ( BaseType_t ) !xErrorDetected; +} + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/QueueOverwrite.c b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/QueueOverwrite.c new file mode 100644 index 0000000..15ffb34 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/QueueOverwrite.c @@ -0,0 +1,268 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* + * Basic task to demonstrate the xQueueOverwrite() function. See the comments + * in the function itself. + */ + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +/* Demo program include files. */ +#include "QueueOverwrite.h" + +/* A block time of 0 just means "don't block". */ +#define qoDONT_BLOCK 0 + +/* Number of times to overwrite the value in the queue. */ +#define qoLOOPS 5 + +/* The task that uses the queue. */ +static void prvQueueOverwriteTask( void *pvParameters ); + +/* Variable that is incremented on each loop of prvQueueOverwriteTask() provided +prvQueueOverwriteTask() has not found any errors. */ +static uint32_t ulLoopCounter = 0; + +/* Set to pdFALSE if an error is discovered by the +vQueueOverwritePeriodicISRDemo() function. */ +static BaseType_t xISRTestStatus = pdPASS; + +/* The queue that is accessed from the ISR. The queue accessed by the task is +created inside the task itself. */ +static QueueHandle_t xISRQueue = NULL; + +/*-----------------------------------------------------------*/ + +void vStartQueueOverwriteTask( UBaseType_t uxPriority ) +{ +const UBaseType_t uxQueueLength = 1; + + /* Create the queue used by the ISR. xQueueOverwriteFromISR() should only + be used on queues that have a length of 1. */ + xISRQueue = xQueueCreate( uxQueueLength, ( UBaseType_t ) sizeof( uint32_t ) ); + + /* Create the test task. The queue used by the test task is created inside + the task itself. */ + xTaskCreate( prvQueueOverwriteTask, "QOver", configMINIMAL_STACK_SIZE, NULL, uxPriority, ( TaskHandle_t * ) NULL ); +} +/*-----------------------------------------------------------*/ + +static void prvQueueOverwriteTask( void *pvParameters ) +{ +QueueHandle_t xTaskQueue; +const UBaseType_t uxQueueLength = 1; +uint32_t ulValue, ulStatus = pdPASS, x; + + /* The parameter is not used. */ + ( void ) pvParameters; + + /* Create the queue. xQueueOverwrite() should only be used on queues that + have a length of 1. */ + xTaskQueue = xQueueCreate( uxQueueLength, ( UBaseType_t ) sizeof( uint32_t ) ); + configASSERT( xTaskQueue ); + + for( ;; ) + { + /* The queue is empty. Writing to the queue then reading from the queue + should return the item written. */ + ulValue = 10; + xQueueOverwrite( xTaskQueue, &ulValue ); + + ulValue = 0; + xQueueReceive( xTaskQueue, &ulValue, qoDONT_BLOCK ); + + if( ulValue != 10 ) + { + ulStatus = pdFAIL; + } + + /* Now try writing to the queue several times. Each time the value + in the queue should get overwritten. */ + for( x = 0; x < qoLOOPS; x++ ) + { + /* Write to the queue. */ + xQueueOverwrite( xTaskQueue, &x ); + + /* Check the value in the queue is that written, even though the + queue was not necessarily empty. */ + xQueuePeek( xTaskQueue, &ulValue, qoDONT_BLOCK ); + if( ulValue != x ) + { + ulStatus = pdFAIL; + } + + /* There should always be one item in the queue. */ + if( uxQueueMessagesWaiting( xTaskQueue ) != uxQueueLength ) + { + ulStatus = pdFAIL; + } + } + + /* Empty the queue again. */ + xQueueReceive( xTaskQueue, &ulValue, qoDONT_BLOCK ); + + if( uxQueueMessagesWaiting( xTaskQueue ) != 0 ) + { + ulStatus = pdFAIL; + } + + if( ulStatus != pdFAIL ) + { + /* Increment a counter to show this task is still running without + error. */ + ulLoopCounter++; + } + + #if( configUSE_PREEMPTION == 0 ) + taskYIELD(); + #endif + } +} +/*-----------------------------------------------------------*/ + +BaseType_t xIsQueueOverwriteTaskStillRunning( void ) +{ +BaseType_t xReturn; + + if( xISRTestStatus != pdPASS ) + { + xReturn = pdFAIL; + } + else if( ulLoopCounter > 0 ) + { + xReturn = pdPASS; + } + else + { + /* The task has either stalled of discovered an error. */ + xReturn = pdFAIL; + } + + ulLoopCounter = 0; + + return xReturn; +} +/*-----------------------------------------------------------*/ + +void vQueueOverwritePeriodicISRDemo( void ) +{ +static uint32_t ulCallCount = 0; +const uint32_t ulTx1 = 10UL, ulTx2 = 20UL, ulNumberOfSwitchCases = 3UL; +uint32_t ulRx; + + /* This function should be called from an interrupt, such as the tick hook + function vApplicationTickHook(). */ + + configASSERT( xISRQueue ); + + switch( ulCallCount ) + { + case 0: + /* The queue is empty. Write ulTx1 to the queue. In this demo the + last parameter is not used because there are no tasks blocked on + this queue. */ + xQueueOverwriteFromISR( xISRQueue, &ulTx1, NULL ); + + /* Peek the queue to check it holds the expected value. */ + xQueuePeekFromISR( xISRQueue, &ulRx ); + if( ulRx != ulTx1 ) + { + xISRTestStatus = pdFAIL; + } + break; + + case 1: + /* The queue already holds ulTx1. Overwrite the value in the queue + with ulTx2. */ + xQueueOverwriteFromISR( xISRQueue, &ulTx2, NULL ); + break; + + case 2: + /* Read from the queue to empty the queue again. The value read + should be ulTx2. */ + xQueueReceiveFromISR( xISRQueue, &ulRx, NULL ); + + if( ulRx != ulTx2 ) + { + xISRTestStatus = pdFAIL; + } + break; + } + + /* Run the next case in the switch statement above next time this function + is called. */ + ulCallCount++; + + if( ulCallCount >= ulNumberOfSwitchCases ) + { + /* Go back to the start. */ + ulCallCount = 0; + } +} + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/QueueSet.c b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/QueueSet.c new file mode 100644 index 0000000..bc8f0e7 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/QueueSet.c @@ -0,0 +1,715 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* + * Tests the use of queue sets. + * + * A receive task creates a number of queues and adds them to a queue set before + * blocking on the queue set receive. A transmit task and (optionally) an + * interrupt repeatedly unblocks the receive task by sending messages to the + * queues in a pseudo random order. The receive task removes the messages from + * the queues and flags an error if the received message does not match that + * expected. The task sends values in the range 0 to + * queuesetINITIAL_ISR_TX_VALUE, and the ISR sends value in the range + * queuesetINITIAL_ISR_TX_VALUE to ULONG_MAX. + */ + + +/* Standard includes. */ +#include +#include + +/* Kernel includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +/* Demo includes. */ +#include "QueueSet.h" + +/* The number of queues that are created and added to the queue set. */ +#define queuesetNUM_QUEUES_IN_SET 3 + +/* The length of each created queue. */ +#define queuesetQUEUE_LENGTH 3 + +/* Block times used in this demo. A block time or 0 means "don't block". */ +#define queuesetSHORT_DELAY 200 +#define queuesetDONT_BLOCK 0 + +/* Messages are sent in incrementing order from both a task and an interrupt. +The task sends values in the range 0 to 0xfffe, and the interrupt sends values +in the range of 0xffff to ULONG_MAX. */ +#define queuesetINITIAL_ISR_TX_VALUE 0xffffUL + +/* The priorities used in this demo. */ +#define queuesetLOW_PRIORITY ( tskIDLE_PRIORITY ) +#define queuesetMEDIUM_PRIORITY ( queuesetLOW_PRIORITY + 1 ) + +/* For test purposes the priority of the sending task is changed after every +queuesetPRIORITY_CHANGE_LOOPS number of values are sent to a queue. */ +#define queuesetPRIORITY_CHANGE_LOOPS ( ( queuesetNUM_QUEUES_IN_SET * queuesetQUEUE_LENGTH ) * 2 ) + +/* The ISR sends to the queue every queuesetISR_TX_PERIOD ticks. */ +#define queuesetISR_TX_PERIOD ( 100UL ) + +/* A delay inserted when the Tx task changes its priority to be above the idle +task priority to ensure the idle priority tasks get some CPU time before the +next iteration of the queue set Tx task. */ +#define queuesetTX_LOOP_DELAY ( 200 / portTICK_PERIOD_MS ) + +/* The allowable maximum deviation between a received value and the expected +received value. A deviation will occur when data is received from a queue +inside an ISR in between a task receiving from a queue and the task checking +the received value. */ +#define queuesetALLOWABLE_RX_DEVIATION 3 + +/* Ignore values that are at the boundaries of allowable values to make the +testing of limits easier (don't have to deal with wrapping values). */ +#define queuesetIGNORED_BOUNDARY ( queuesetALLOWABLE_RX_DEVIATION * 2 ) + +typedef enum +{ + eEqualPriority = 0, /* Tx and Rx tasks have the same priority. */ + eTxHigherPriority, /* The priority of the Tx task is above that of the Rx task. */ + eTxLowerPriority /* The priority of the Tx task is below that of the Rx task. */ +} eRelativePriorities; + +/* + * The task that periodically sends to the queue set. + */ +static void prvQueueSetSendingTask( void *pvParameters ); + +/* + * The task that reads from the queue set. + */ +static void prvQueueSetReceivingTask( void *pvParameters ); + +/* + * Check the value received from a queue is the expected value. Some values + * originate from the send task, some values originate from the ISR, with the + * range of the value being used to distinguish between the two message + * sources. + */ +static void prvCheckReceivedValue( uint32_t ulReceived ); + +/* + * For purposes of test coverage, functions that read from and write to a + * queue set from an ISR respectively. + */ +static void prvReceiveFromQueueInSetFromISR( void ); +static void prvSendToQueueInSetFromISR( void ); + +/* + * Create the queues and add them to a queue set before resuming the Tx + * task. + */ +static void prvSetupTest( void ); + +/* + * Checks a value received from a queue falls within the range of expected + * values. + */ +static BaseType_t prvCheckReceivedValueWithinExpectedRange( uint32_t ulReceived, uint32_t ulExpectedReceived ); + +/* + * Increase test coverage by occasionally change the priorities of the two tasks + * relative to each other. */ +static void prvChangeRelativePriorities( void ); + +/* + * Local pseudo random number seed and return functions. Used to avoid calls + * to the standard library. + */ +static uint32_t prvRand( void ); +static void prvSRand( uint32_t ulSeed ); + +/*-----------------------------------------------------------*/ + +/* The queues that are added to the set. */ +static QueueHandle_t xQueues[ queuesetNUM_QUEUES_IN_SET ] = { 0 }; + +/* Counts how many times each queue in the set is used to ensure all the +queues are used. */ +static uint32_t ulQueueUsedCounter[ queuesetNUM_QUEUES_IN_SET ] = { 0 }; + +/* The handle of the queue set to which the queues are added. */ +static QueueSetHandle_t xQueueSet; + +/* If the prvQueueSetReceivingTask() task has not detected any errors then +it increments ulCycleCounter on each iteration. +xAreQueueSetTasksStillRunning() returns pdPASS if the value of +ulCycleCounter has changed between consecutive calls, and pdFALSE if +ulCycleCounter has stopped incrementing (indicating an error condition). */ +static volatile uint32_t ulCycleCounter = 0UL; + +/* Set to pdFAIL if an error is detected by any queue set task. +ulCycleCounter will only be incremented if xQueueSetTasksSatus equals pdPASS. */ +static volatile BaseType_t xQueueSetTasksStatus = pdPASS; + +/* Just a flag to let the function that writes to a queue from an ISR know that +the queues are setup and can be used. */ +static volatile BaseType_t xSetupComplete = pdFALSE; + +/* The value sent to the queue from the ISR is file scope so the +xAreQueeuSetTasksStillRunning() function can check it is incrementing as +expected. */ +static volatile uint32_t ulISRTxValue = queuesetINITIAL_ISR_TX_VALUE; + +/* Used by the pseudo random number generator. */ +static uint32_t ulNextRand = 0; + +/* The task handles are stored so their priorities can be changed. */ +TaskHandle_t xQueueSetSendingTask, xQueueSetReceivingTask; + +/*-----------------------------------------------------------*/ + +void vStartQueueSetTasks( void ) +{ + /* Create the tasks. */ + xTaskCreate( prvQueueSetSendingTask, "SetTx", configMINIMAL_STACK_SIZE, NULL, queuesetMEDIUM_PRIORITY, &xQueueSetSendingTask ); + xTaskCreate( prvQueueSetReceivingTask, "SetRx", configMINIMAL_STACK_SIZE, ( void * ) xQueueSetSendingTask, queuesetMEDIUM_PRIORITY, &xQueueSetReceivingTask ); + + /* It is important that the sending task does not attempt to write to a + queue before the queue has been created. It is therefore placed into the + suspended state before the scheduler has started. It is resumed by the + receiving task after the receiving task has created the queues and added the + queues to the queue set. */ + vTaskSuspend( xQueueSetSendingTask ); +} +/*-----------------------------------------------------------*/ + +BaseType_t xAreQueueSetTasksStillRunning( void ) +{ +static uint32_t ulLastCycleCounter, ulLastISRTxValue = 0; +static uint32_t ulLastQueueUsedCounter[ queuesetNUM_QUEUES_IN_SET ] = { 0 }; +BaseType_t xReturn = pdPASS, x; + + if( ulLastCycleCounter == ulCycleCounter ) + { + /* The cycle counter is no longer being incremented. Either one of the + tasks is stalled or an error has been detected. */ + xReturn = pdFAIL; + } + + ulLastCycleCounter = ulCycleCounter; + + /* Ensure that all the queues in the set have been used. This ensures the + test is working as intended and guards against the rand() in the Tx task + missing some values. */ + for( x = 0; x < queuesetNUM_QUEUES_IN_SET; x++ ) + { + if( ulLastQueueUsedCounter[ x ] == ulQueueUsedCounter[ x ] ) + { + xReturn = pdFAIL; + } + + ulLastQueueUsedCounter[ x ] = ulQueueUsedCounter[ x ]; + } + + /* Check the global status flag. */ + if( xQueueSetTasksStatus != pdPASS ) + { + xReturn = pdFAIL; + } + + /* Check that the ISR is still sending values to the queues too. */ + if( ulISRTxValue == ulLastISRTxValue ) + { + xReturn = pdFAIL; + } + else + { + ulLastISRTxValue = ulISRTxValue; + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +static void prvQueueSetSendingTask( void *pvParameters ) +{ +uint32_t ulTaskTxValue = 0, ulQueueToWriteTo; +QueueHandle_t xQueueInUse; + + /* Remove compiler warning about the unused parameter. */ + ( void ) pvParameters; + + /* Seed mini pseudo random number generator. */ + prvSRand( ( uint32_t ) &ulTaskTxValue ); + + for( ;; ) + { + /* Generate the index for the queue to which a value is to be sent. */ + ulQueueToWriteTo = prvRand() % queuesetNUM_QUEUES_IN_SET; + xQueueInUse = xQueues[ ulQueueToWriteTo ]; + + /* Note which index is being written to to ensure all the queues are + used. */ + ( ulQueueUsedCounter[ ulQueueToWriteTo ] )++; + + /* Send to the queue to unblock the task that is waiting for data to + arrive on a queue within the queue set to which this queue belongs. */ + if( xQueueSendToBack( xQueueInUse, &ulTaskTxValue, portMAX_DELAY ) != pdPASS ) + { + /* The send should always pass as an infinite block time was + used. */ + xQueueSetTasksStatus = pdFAIL; + } + + #if( configUSE_PREEMPTION == 0 ) + taskYIELD(); + #endif + + ulTaskTxValue++; + + /* If the Tx value has reached the range used by the ISR then set it + back to 0. */ + if( ulTaskTxValue == queuesetINITIAL_ISR_TX_VALUE ) + { + ulTaskTxValue = 0; + } + + /* Increase test coverage by occasionally change the priorities of the + two tasks relative to each other. */ + prvChangeRelativePriorities(); + } +} +/*-----------------------------------------------------------*/ + +static void prvChangeRelativePriorities( void ) +{ +static UBaseType_t ulLoops = 0; +static eRelativePriorities ePriorities = eEqualPriority; + + /* Occasionally change the task priority relative to the priority of + the receiving task. */ + ulLoops++; + if( ulLoops >= queuesetPRIORITY_CHANGE_LOOPS ) + { + ulLoops = 0; + + switch( ePriorities ) + { + case eEqualPriority: + /* Both tasks are running with medium priority. Now lower the + priority of the receiving task so the Tx task has the higher + relative priority. */ + vTaskPrioritySet( xQueueSetReceivingTask, queuesetLOW_PRIORITY ); + ePriorities = eTxHigherPriority; + break; + + case eTxHigherPriority: + /* The Tx task is running with a higher priority than the Rx + task. Switch the priorities around so the Rx task has the + higher relative priority. */ + vTaskPrioritySet( xQueueSetReceivingTask, queuesetMEDIUM_PRIORITY ); + vTaskPrioritySet( xQueueSetSendingTask, queuesetLOW_PRIORITY ); + ePriorities = eTxLowerPriority; + break; + + case eTxLowerPriority: + /* The Tx task is running with a lower priority than the Rx + task. Make the priorities equal again. */ + vTaskPrioritySet( xQueueSetSendingTask, queuesetMEDIUM_PRIORITY ); + ePriorities = eEqualPriority; + + /* When both tasks are using a non-idle priority the queue set + tasks will starve idle priority tasks of execution time - so + relax a bit before the next iteration to minimise the impact. */ + vTaskDelay( queuesetTX_LOOP_DELAY ); + + break; + } + } +} +/*-----------------------------------------------------------*/ + +static void prvQueueSetReceivingTask( void *pvParameters ) +{ +uint32_t ulReceived; +QueueHandle_t xActivatedQueue; + + /* Remove compiler warnings. */ + ( void ) pvParameters; + + /* Create the queues and add them to the queue set before resuming the Tx + task. */ + prvSetupTest(); + + for( ;; ) + { + /* Wait for a message to arrive on one of the queues in the set. */ + xActivatedQueue = xQueueSelectFromSet( xQueueSet, portMAX_DELAY ); + configASSERT( xActivatedQueue ); + + if( xActivatedQueue == NULL ) + { + /* This should not happen as an infinite delay was used. */ + xQueueSetTasksStatus = pdFAIL; + } + else + { + /* Reading from the queue should pass with a zero block time as + this task will only run when something has been posted to a task + in the queue set. */ + if( xQueueReceive( xActivatedQueue, &ulReceived, queuesetDONT_BLOCK ) != pdPASS ) + { + xQueueSetTasksStatus = pdFAIL; + } + + /* Ensure the value received was the value expected. This function + manipulates file scope data and is also called from an ISR, hence + the critical section. */ + taskENTER_CRITICAL(); + { + prvCheckReceivedValue( ulReceived ); + } + taskEXIT_CRITICAL(); + } + + if( xQueueSetTasksStatus == pdPASS ) + { + ulCycleCounter++; + } + } +} +/*-----------------------------------------------------------*/ + +void vQueueSetAccessQueueSetFromISR( void ) +{ +static uint32_t ulCallCount = 0; + + /* xSetupComplete is set to pdTRUE when the queues have been created and + are available for use. */ + if( xSetupComplete == pdTRUE ) + { + /* It is intended that this function is called from the tick hook + function, so each call is one tick period apart. */ + ulCallCount++; + if( ulCallCount > queuesetISR_TX_PERIOD ) + { + ulCallCount = 0; + + /* First attempt to read from the queue set. */ + prvReceiveFromQueueInSetFromISR(); + + /* Then write to the queue set. */ + prvSendToQueueInSetFromISR(); + } + } +} +/*-----------------------------------------------------------*/ + +static void prvCheckReceivedValue( uint32_t ulReceived ) +{ +static uint32_t ulExpectedReceivedFromTask = 0, ulExpectedReceivedFromISR = queuesetINITIAL_ISR_TX_VALUE; + + /* Values are received in tasks and interrupts. It is likely that the + receiving task will sometimes get preempted by the receiving interrupt + between reading a value from the queue and calling this function. When + that happens, if the receiving interrupt calls this function the values + will get passed into this function slightly out of order. For that + reason the value passed in is tested against a small range of expected + values, rather than a single absolute value. To make the range testing + easier values in the range limits are ignored. */ + + /* If the received value is equal to or greater than + queuesetINITIAL_ISR_TX_VALUE then it was sent by an ISR. */ + if( ulReceived >= queuesetINITIAL_ISR_TX_VALUE ) + { + /* The value was sent from the ISR. */ + if( ( ulReceived - queuesetINITIAL_ISR_TX_VALUE ) < queuesetIGNORED_BOUNDARY ) + { + /* The value received is at the lower limit of the expected range. + Don't test it and expect to receive one higher next time. */ + } + else if( ( ULONG_MAX - ulReceived ) <= queuesetIGNORED_BOUNDARY ) + { + /* The value received is at the higher limit of the expected range. + Don't test it and expect to wrap soon. */ + } + else + { + /* Check the value against its expected value range. */ + if( prvCheckReceivedValueWithinExpectedRange( ulReceived, ulExpectedReceivedFromISR ) != pdPASS ) + { + xQueueSetTasksStatus = pdFAIL; + } + } + + configASSERT( xQueueSetTasksStatus ); + + /* It is expected to receive an incrementing number. */ + ulExpectedReceivedFromISR++; + if( ulExpectedReceivedFromISR == 0 ) + { + ulExpectedReceivedFromISR = queuesetINITIAL_ISR_TX_VALUE; + } + } + else + { + /* The value was sent from the Tx task. */ + if( ulReceived < queuesetIGNORED_BOUNDARY ) + { + /* The value received is at the lower limit of the expected range. + Don't test it, and expect to receive one higher next time. */ + } + else if( ( ( queuesetINITIAL_ISR_TX_VALUE - 1 ) - ulReceived ) <= queuesetIGNORED_BOUNDARY ) + { + /* The value received is at the higher limit of the expected range. + Don't test it and expect to wrap soon. */ + } + else + { + /* Check the value against its expected value range. */ + if( prvCheckReceivedValueWithinExpectedRange( ulReceived, ulExpectedReceivedFromTask ) != pdPASS ) + { + xQueueSetTasksStatus = pdFAIL; + } + } + + configASSERT( xQueueSetTasksStatus ); + + /* It is expected to receive an incrementing number. */ + ulExpectedReceivedFromTask++; + if( ulExpectedReceivedFromTask >= queuesetINITIAL_ISR_TX_VALUE ) + { + ulExpectedReceivedFromTask = 0; + } + } +} +/*-----------------------------------------------------------*/ + +static BaseType_t prvCheckReceivedValueWithinExpectedRange( uint32_t ulReceived, uint32_t ulExpectedReceived ) +{ +BaseType_t xReturn = pdPASS; + + if( ulReceived > ulExpectedReceived ) + { + configASSERT( ( ulReceived - ulExpectedReceived ) <= queuesetALLOWABLE_RX_DEVIATION ); + if( ( ulReceived - ulExpectedReceived ) > queuesetALLOWABLE_RX_DEVIATION ) + { + xReturn = pdFALSE; + } + } + else + { + configASSERT( ( ulExpectedReceived - ulReceived ) <= queuesetALLOWABLE_RX_DEVIATION ); + if( ( ulExpectedReceived - ulReceived ) > queuesetALLOWABLE_RX_DEVIATION ) + { + xReturn = pdFALSE; + } + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +static void prvReceiveFromQueueInSetFromISR( void ) +{ +QueueSetMemberHandle_t xActivatedQueue; +uint32_t ulReceived; + + /* See if any of the queues in the set contain data. */ + xActivatedQueue = xQueueSelectFromSetFromISR( xQueueSet ); + + if( xActivatedQueue != NULL ) + { + /* Reading from the queue for test purposes only. */ + if( xQueueReceiveFromISR( xActivatedQueue, &ulReceived, NULL ) != pdPASS ) + { + /* Data should have been available as the handle was returned from + xQueueSelectFromSetFromISR(). */ + xQueueSetTasksStatus = pdFAIL; + } + + /* Ensure the value received was the value expected. */ + prvCheckReceivedValue( ulReceived ); + } +} +/*-----------------------------------------------------------*/ + +static void prvSendToQueueInSetFromISR( void ) +{ +static BaseType_t xQueueToWriteTo = 0; + + if( xQueueSendFromISR( xQueues[ xQueueToWriteTo ], ( void * ) &ulISRTxValue, NULL ) == pdPASS ) + { + ulISRTxValue++; + + /* If the Tx value has wrapped then set it back to its + initial value. */ + if( ulISRTxValue == 0UL ) + { + ulISRTxValue = queuesetINITIAL_ISR_TX_VALUE; + } + + /* Use a different queue next time. */ + xQueueToWriteTo++; + if( xQueueToWriteTo >= queuesetNUM_QUEUES_IN_SET ) + { + xQueueToWriteTo = 0; + } + } +} +/*-----------------------------------------------------------*/ + +static void prvSetupTest( void ) +{ +BaseType_t x; +uint32_t ulValueToSend = 0; + + /* Ensure the queues are created and the queue set configured before the + sending task is unsuspended. + + First Create the queue set such that it will be able to hold a message for + every space in every queue in the set. */ + xQueueSet = xQueueCreateSet( queuesetNUM_QUEUES_IN_SET * queuesetQUEUE_LENGTH ); + + for( x = 0; x < queuesetNUM_QUEUES_IN_SET; x++ ) + { + /* Create the queue and add it to the set. The queue is just holding + uint32_t value. */ + xQueues[ x ] = xQueueCreate( queuesetQUEUE_LENGTH, sizeof( uint32_t ) ); + configASSERT( xQueues[ x ] ); + if( xQueueAddToSet( xQueues[ x ], xQueueSet ) != pdPASS ) + { + xQueueSetTasksStatus = pdFAIL; + } + else + { + /* The queue has now been added to the queue set and cannot be added to + another. */ + if( xQueueAddToSet( xQueues[ x ], xQueueSet ) != pdFAIL ) + { + xQueueSetTasksStatus = pdFAIL; + } + } + } + + /* Attempt to remove a queue from a queue set it does not belong + to (NULL being passed as the queue set in this case). */ + if( xQueueRemoveFromSet( xQueues[ 0 ], NULL ) != pdFAIL ) + { + /* It is not possible to successfully remove a queue from a queue + set it does not belong to. */ + xQueueSetTasksStatus = pdFAIL; + } + + /* Attempt to remove a queue from the queue set it does belong to. */ + if( xQueueRemoveFromSet( xQueues[ 0 ], xQueueSet ) != pdPASS ) + { + /* It should be possible to remove the queue from the queue set it + does belong to. */ + xQueueSetTasksStatus = pdFAIL; + } + + /* Add an item to the queue before attempting to add it back into the + set. */ + xQueueSend( xQueues[ 0 ], ( void * ) &ulValueToSend, 0 ); + if( xQueueAddToSet( xQueues[ 0 ], xQueueSet ) != pdFAIL ) + { + /* Should not be able to add a non-empty queue to a set. */ + xQueueSetTasksStatus = pdFAIL; + } + + /* Remove the item from the queue before adding the queue back into the + set so the dynamic tests can begin. */ + xQueueReceive( xQueues[ 0 ], &ulValueToSend, 0 ); + if( xQueueAddToSet( xQueues[ 0 ], xQueueSet ) != pdPASS ) + { + /* If the queue was successfully removed from the queue set then it + should be possible to add it back in again. */ + xQueueSetTasksStatus = pdFAIL; + } + + /* The task that sends to the queues is not running yet, so attempting to + read from the queue set should fail. */ + if( xQueueSelectFromSet( xQueueSet, queuesetSHORT_DELAY ) != NULL ) + { + xQueueSetTasksStatus = pdFAIL; + } + + /* Resume the task that writes to the queues. */ + vTaskResume( xQueueSetSendingTask ); + + /* Let the ISR access the queues also. */ + xSetupComplete = pdTRUE; +} +/*-----------------------------------------------------------*/ + +static uint32_t prvRand( void ) +{ + ulNextRand = ( ulNextRand * 1103515245UL ) + 12345UL; + return ( ulNextRand / 65536UL ) % 32768UL; +} +/*-----------------------------------------------------------*/ + +static void prvSRand( uint32_t ulSeed ) +{ + ulNextRand = ulSeed; +} + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/TimerDemo.c b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/TimerDemo.c new file mode 100644 index 0000000..68ece37 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/TimerDemo.c @@ -0,0 +1,1079 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +/* + * Tests the behaviour of timers. Some timers are created before the scheduler + * is started, and some after. + */ + +/* Standard includes. */ +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "timers.h" + +/* Demo program include files. */ +#include "TimerDemo.h" + +#if ( configTIMER_TASK_PRIORITY < 1 ) + #error configTIMER_TASK_PRIORITY must be set to at least 1 for this test/demo to function correctly. +#endif + +#define tmrdemoDONT_BLOCK ( ( TickType_t ) 0 ) +#define tmrdemoONE_SHOT_TIMER_PERIOD ( xBasePeriod * ( TickType_t ) 3 ) +#define trmdemoNUM_TIMER_RESETS ( ( uint8_t ) 10 ) + +/*-----------------------------------------------------------*/ + +/* The callback functions used by the timers. These each increment a counter +to indicate which timer has expired. The auto-reload timers that are used by +the test task (as opposed to being used from an ISR) all share the same +prvAutoReloadTimerCallback() callback function, and use the ID of the +pxExpiredTimer parameter passed into that function to know which counter to +increment. The other timers all have their own unique callback function and +simply increment their counters without using the callback function parameter. */ +static void prvAutoReloadTimerCallback( TimerHandle_t pxExpiredTimer ); +static void prvOneShotTimerCallback( TimerHandle_t pxExpiredTimer ); +static void prvTimerTestTask( void *pvParameters ); +static void prvISRAutoReloadTimerCallback( TimerHandle_t pxExpiredTimer ); +static void prvISROneShotTimerCallback( TimerHandle_t pxExpiredTimer ); + +/* The test functions used by the timer test task. These manipulate the auto +reload and one shot timers in various ways, then delay, then inspect the timers +to ensure they have behaved as expected. */ +static void prvTest1_CreateTimersWithoutSchedulerRunning( void ); +static void prvTest2_CheckTaskAndTimersInitialState( void ); +static void prvTest3_CheckAutoReloadExpireRates( void ); +static void prvTest4_CheckAutoReloadTimersCanBeStopped( void ); +static void prvTest5_CheckBasicOneShotTimerBehaviour( void ); +static void prvTest6_CheckAutoReloadResetBehaviour( void ); +static void prvResetStartConditionsForNextIteration( void ); + +/*-----------------------------------------------------------*/ + +/* Flag that will be latched to pdFAIL should any unexpected behaviour be +detected in any of the demo tests. */ +static volatile BaseType_t xTestStatus = pdPASS; + +/* Counter that is incremented on each cycle of a test. This is used to +detect a stalled task - a test that is no longer running. */ +static volatile uint32_t ulLoopCounter = 0; + +/* A set of auto reload timers - each of which use the same callback function. +The callback function uses the timer ID to index into, and then increment, a +counter in the ucAutoReloadTimerCounters[] array. The auto reload timers +referenced from xAutoReloadTimers[] are used by the prvTimerTestTask task. */ +static TimerHandle_t xAutoReloadTimers[ configTIMER_QUEUE_LENGTH + 1 ] = { 0 }; +static uint8_t ucAutoReloadTimerCounters[ configTIMER_QUEUE_LENGTH + 1 ] = { 0 }; + +/* The one shot timer is configured to use a callback function that increments +ucOneShotTimerCounter each time it gets called. */ +static TimerHandle_t xOneShotTimer = NULL; +static uint8_t ucOneShotTimerCounter = ( uint8_t ) 0; + +/* The ISR reload timer is controlled from the tick hook to exercise the timer +API functions that can be used from an ISR. It is configured to increment +ucISRReloadTimerCounter each time its callback function is executed. */ +static TimerHandle_t xISRAutoReloadTimer = NULL; +static uint8_t ucISRAutoReloadTimerCounter = ( uint8_t ) 0; + +/* The ISR one shot timer is controlled from the tick hook to exercise the timer +API functions that can be used from an ISR. It is configured to increment +ucISRReloadTimerCounter each time its callback function is executed. */ +static TimerHandle_t xISROneShotTimer = NULL; +static uint8_t ucISROneShotTimerCounter = ( uint8_t ) 0; + +/* The period of all the timers are a multiple of the base period. The base +period is configured by the parameter to vStartTimerDemoTask(). */ +static TickType_t xBasePeriod = 0; + +/*-----------------------------------------------------------*/ + +void vStartTimerDemoTask( TickType_t xBasePeriodIn ) +{ + /* Start with the timer and counter arrays clear - this is only necessary + where the compiler does not clear them automatically on start up. */ + memset( ucAutoReloadTimerCounters, 0x00, sizeof( ucAutoReloadTimerCounters ) ); + memset( xAutoReloadTimers, 0x00, sizeof( xAutoReloadTimers ) ); + + /* Store the period from which all the timer periods will be generated from + (multiples of). */ + xBasePeriod = xBasePeriodIn; + + /* Create a set of timers for use by this demo/test. */ + prvTest1_CreateTimersWithoutSchedulerRunning(); + + /* Create the task that will control and monitor the timers. This is + created at a lower priority than the timer service task to ensure, as + far as it is concerned, commands on timers are actioned immediately + (sending a command to the timer service task will unblock the timer service + task, which will then preempt this task). */ + if( xTestStatus != pdFAIL ) + { + xTaskCreate( prvTimerTestTask, "Tmr Tst", configMINIMAL_STACK_SIZE, NULL, configTIMER_TASK_PRIORITY - 1, NULL ); + } +} +/*-----------------------------------------------------------*/ + +static void prvTimerTestTask( void *pvParameters ) +{ + ( void ) pvParameters; + + /* Create a one-shot timer for use later on in this test. */ + xOneShotTimer = xTimerCreate( "Oneshot Timer", /* Text name to facilitate debugging. The kernel does not use this itself. */ + tmrdemoONE_SHOT_TIMER_PERIOD, /* The period for the timer. */ + pdFALSE, /* Don't auto-reload - hence a one shot timer. */ + ( void * ) 0, /* The timer identifier. In this case this is not used as the timer has its own callback. */ + prvOneShotTimerCallback ); /* The callback to be called when the timer expires. */ + + if( xOneShotTimer == NULL ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + + /* Ensure all the timers are in their expected initial state. This + depends on the timer service task having a higher priority than this task. */ + prvTest2_CheckTaskAndTimersInitialState(); + + for( ;; ) + { + /* Check the auto reload timers expire at the expected/correct rates. */ + prvTest3_CheckAutoReloadExpireRates(); + + /* Check the auto reload timers can be stopped correctly, and correctly + report their state. */ + prvTest4_CheckAutoReloadTimersCanBeStopped(); + + /* Check the one shot timer only calls its callback once after it has been + started, and that it reports its state correctly. */ + prvTest5_CheckBasicOneShotTimerBehaviour(); + + /* Check timer reset behaviour. */ + prvTest6_CheckAutoReloadResetBehaviour(); + + /* Start the timers again to restart all the tests over again. */ + prvResetStartConditionsForNextIteration(); + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that the created task is still running and has not +detected any errors. */ +BaseType_t xAreTimerDemoTasksStillRunning( TickType_t xCycleFrequency ) +{ +static uint32_t ulLastLoopCounter = 0UL; +TickType_t xMaxBlockTimeUsedByTheseTests, xLoopCounterIncrementTimeMax; +static TickType_t xIterationsWithoutCounterIncrement = ( TickType_t ) 0, xLastCycleFrequency; + + if( xLastCycleFrequency != xCycleFrequency ) + { + /* The cycle frequency has probably become much faster due to an error + elsewhere. Start counting Iterations again. */ + xIterationsWithoutCounterIncrement = ( TickType_t ) 0; + xLastCycleFrequency = xCycleFrequency; + } + + /* Calculate the maximum number of times that it is permissible for this + function to be called without ulLoopCounter being incremented. This is + necessary because the tests in this file block for extended periods, and the + block period might be longer than the time between calls to this function. */ + xMaxBlockTimeUsedByTheseTests = ( ( TickType_t ) configTIMER_QUEUE_LENGTH ) * xBasePeriod; + xLoopCounterIncrementTimeMax = ( xMaxBlockTimeUsedByTheseTests / xCycleFrequency ) + 1; + + /* If the demo task is still running then the loop counter is expected to + have incremented every xLoopCounterIncrementTimeMax calls. */ + if( ulLastLoopCounter == ulLoopCounter ) + { + xIterationsWithoutCounterIncrement++; + if( xIterationsWithoutCounterIncrement > xLoopCounterIncrementTimeMax ) + { + /* The tests appear to be no longer running (stalled). */ + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + } + else + { + /* ulLoopCounter changed, so the count of times this function was called + without a change can be reset to zero. */ + xIterationsWithoutCounterIncrement = ( TickType_t ) 0; + } + + ulLastLoopCounter = ulLoopCounter; + + /* Errors detected in the task itself will have latched xTestStatus + to pdFAIL. */ + + return xTestStatus; +} +/*-----------------------------------------------------------*/ + +static void prvTest1_CreateTimersWithoutSchedulerRunning( void ) +{ +UBaseType_t xTimer; + + for( xTimer = 0; xTimer < configTIMER_QUEUE_LENGTH; xTimer++ ) + { + /* As the timer queue is not yet full, it should be possible to both create + and start a timer. These timers are being started before the scheduler has + been started, so their block times should get set to zero within the timer + API itself. */ + xAutoReloadTimers[ xTimer ] = xTimerCreate( "FR Timer", /* Text name to facilitate debugging. The kernel does not use this itself. */ + ( ( xTimer + ( TickType_t ) 1 ) * xBasePeriod ),/* The period for the timer. The plus 1 ensures a period of zero is not specified. */ + pdTRUE, /* Auto-reload is set to true. */ + ( void * ) xTimer, /* An identifier for the timer as all the auto reload timers use the same callback. */ + prvAutoReloadTimerCallback ); /* The callback to be called when the timer expires. */ + + configASSERT( strcmp( pcTimerGetTimerName( xAutoReloadTimers[ xTimer ] ), "FR Timer" ) == 0 ); + + if( xAutoReloadTimers[ xTimer ] == NULL ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + else + { + /* The scheduler has not yet started, so the block period of + portMAX_DELAY should just get set to zero in xTimerStart(). Also, + the timer queue is not yet full so xTimerStart() should return + pdPASS. */ + if( xTimerStart( xAutoReloadTimers[ xTimer ], portMAX_DELAY ) != pdPASS ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + } + } + + /* The timers queue should now be full, so it should be possible to create + another timer, but not possible to start it (the timer queue will not get + drained until the scheduler has been started. */ + xAutoReloadTimers[ configTIMER_QUEUE_LENGTH ] = xTimerCreate( "FR Timer", /* Text name to facilitate debugging. The kernel does not use this itself. */ + ( configTIMER_QUEUE_LENGTH * xBasePeriod ), /* The period for the timer. */ + pdTRUE, /* Auto-reload is set to true. */ + ( void * ) xTimer, /* An identifier for the timer as all the auto reload timers use the same callback. */ + prvAutoReloadTimerCallback ); /* The callback executed when the timer expires. */ + + if( xAutoReloadTimers[ configTIMER_QUEUE_LENGTH ] == NULL ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + else + { + if( xTimerStart( xAutoReloadTimers[ xTimer ], portMAX_DELAY ) == pdPASS ) + { + /* This time it would not be expected that the timer could be + started at this point. */ + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + } + + /* Create the timers that are used from the tick interrupt to test the timer + API functions that can be called from an ISR. */ + xISRAutoReloadTimer = xTimerCreate( "ISR AR", /* The text name given to the timer. */ + 0xffff, /* The timer is not given a period yet - this will be done from the tick hook, but a period of 0 is invalid. */ + pdTRUE, /* This is an auto reload timer. */ + ( void * ) NULL, /* The identifier is not required. */ + prvISRAutoReloadTimerCallback ); /* The callback that is executed when the timer expires. */ + + xISROneShotTimer = xTimerCreate( "ISR OS", /* The text name given to the timer. */ + 0xffff, /* The timer is not given a period yet - this will be done from the tick hook, but a period of 0 is invalid. */ + pdFALSE, /* This is a one shot timer. */ + ( void * ) NULL, /* The identifier is not required. */ + prvISROneShotTimerCallback ); /* The callback that is executed when the timer expires. */ + + if( ( xISRAutoReloadTimer == NULL ) || ( xISROneShotTimer == NULL ) ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } +} +/*-----------------------------------------------------------*/ + +static void prvTest2_CheckTaskAndTimersInitialState( void ) +{ +uint8_t ucTimer; + + /* Ensure all the timers are in their expected initial state. This depends + on the timer service task having a higher priority than this task. + + auto reload timers 0 to ( configTIMER_QUEUE_LENGTH - 1 ) should now be active, + and auto reload timer configTIMER_QUEUE_LENGTH should not yet be active (it + could not be started prior to the scheduler being started when it was + created). */ + for( ucTimer = 0; ucTimer < ( uint8_t ) configTIMER_QUEUE_LENGTH; ucTimer++ ) + { + if( xTimerIsTimerActive( xAutoReloadTimers[ ucTimer ] ) == pdFALSE ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + } + + if( xTimerIsTimerActive( xAutoReloadTimers[ configTIMER_QUEUE_LENGTH ] ) != pdFALSE ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } +} +/*-----------------------------------------------------------*/ + +static void prvTest3_CheckAutoReloadExpireRates( void ) +{ +uint8_t ucMaxAllowableValue, ucMinAllowableValue, ucTimer; +TickType_t xBlockPeriod, xTimerPeriod, xExpectedNumber; + + /* Check the auto reload timers expire at the expected rates. */ + + + /* Delaying for configTIMER_QUEUE_LENGTH * xBasePeriod ticks should allow + all the auto reload timers to expire at least once. */ + xBlockPeriod = ( ( TickType_t ) configTIMER_QUEUE_LENGTH ) * xBasePeriod; + vTaskDelay( xBlockPeriod ); + + /* Check that all the auto reload timers have called their callback + function the expected number of times. */ + for( ucTimer = 0; ucTimer < ( uint8_t ) configTIMER_QUEUE_LENGTH; ucTimer++ ) + { + /* The expected number of expiries is equal to the block period divided + by the timer period. */ + xTimerPeriod = ( ( ( TickType_t ) ucTimer + ( TickType_t ) 1 ) * xBasePeriod ); + xExpectedNumber = xBlockPeriod / xTimerPeriod; + + ucMaxAllowableValue = ( ( uint8_t ) xExpectedNumber ) ; + ucMinAllowableValue = ( uint8_t ) ( ( uint8_t ) xExpectedNumber - ( uint8_t ) 1 ); /* Weird casting to try and please all compilers. */ + + if( ( ucAutoReloadTimerCounters[ ucTimer ] < ucMinAllowableValue ) || + ( ucAutoReloadTimerCounters[ ucTimer ] > ucMaxAllowableValue ) + ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + } + + if( xTestStatus == pdPASS ) + { + /* No errors have been reported so increment the loop counter so the + check task knows this task is still running. */ + ulLoopCounter++; + } +} +/*-----------------------------------------------------------*/ + +static void prvTest4_CheckAutoReloadTimersCanBeStopped( void ) +{ +uint8_t ucTimer; + + /* Check the auto reload timers can be stopped correctly, and correctly + report their state. */ + + /* Stop all the active timers. */ + for( ucTimer = 0; ucTimer < ( uint8_t ) configTIMER_QUEUE_LENGTH; ucTimer++ ) + { + /* The timer has not been stopped yet! */ + if( xTimerIsTimerActive( xAutoReloadTimers[ ucTimer ] ) == pdFALSE ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + /* Now stop the timer. This will appear to happen immediately to + this task because this task is running at a priority below the + timer service task. */ + xTimerStop( xAutoReloadTimers[ ucTimer ], tmrdemoDONT_BLOCK ); + + /* The timer should now be inactive. */ + if( xTimerIsTimerActive( xAutoReloadTimers[ ucTimer ] ) != pdFALSE ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + } + + taskENTER_CRITICAL(); + { + /* The timer in array position configTIMER_QUEUE_LENGTH should not + be active. The critical section is used to ensure the timer does + not call its callback between the next line running and the array + being cleared back to zero, as that would mask an error condition. */ + if( ucAutoReloadTimerCounters[ configTIMER_QUEUE_LENGTH ] != ( uint8_t ) 0 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + /* Clear the timer callback count. */ + memset( ( void * ) ucAutoReloadTimerCounters, 0, sizeof( ucAutoReloadTimerCounters ) ); + } + taskEXIT_CRITICAL(); + + /* The timers are now all inactive, so this time, after delaying, none + of the callback counters should have incremented. */ + vTaskDelay( ( ( TickType_t ) configTIMER_QUEUE_LENGTH ) * xBasePeriod ); + for( ucTimer = 0; ucTimer < ( uint8_t ) configTIMER_QUEUE_LENGTH; ucTimer++ ) + { + if( ucAutoReloadTimerCounters[ ucTimer ] != ( uint8_t ) 0 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + } + + if( xTestStatus == pdPASS ) + { + /* No errors have been reported so increment the loop counter so + the check task knows this task is still running. */ + ulLoopCounter++; + } +} +/*-----------------------------------------------------------*/ + +static void prvTest5_CheckBasicOneShotTimerBehaviour( void ) +{ + /* Check the one shot timer only calls its callback once after it has been + started, and that it reports its state correctly. */ + + /* The one shot timer should not be active yet. */ + if( xTimerIsTimerActive( xOneShotTimer ) != pdFALSE ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + if( ucOneShotTimerCounter != ( uint8_t ) 0 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + /* Start the one shot timer and check that it reports its state correctly. */ + xTimerStart( xOneShotTimer, tmrdemoDONT_BLOCK ); + if( xTimerIsTimerActive( xOneShotTimer ) == pdFALSE ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + /* Delay for three times as long as the one shot timer period, then check + to ensure it has only called its callback once, and is now not in the + active state. */ + vTaskDelay( tmrdemoONE_SHOT_TIMER_PERIOD * ( TickType_t ) 3 ); + + if( xTimerIsTimerActive( xOneShotTimer ) != pdFALSE ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + if( ucOneShotTimerCounter != ( uint8_t ) 1 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + else + { + /* Reset the one shot timer callback count. */ + ucOneShotTimerCounter = ( uint8_t ) 0; + } + + if( xTestStatus == pdPASS ) + { + /* No errors have been reported so increment the loop counter so the + check task knows this task is still running. */ + ulLoopCounter++; + } +} +/*-----------------------------------------------------------*/ + +static void prvTest6_CheckAutoReloadResetBehaviour( void ) +{ +uint8_t ucTimer; + + /* Check timer reset behaviour. */ + + /* Restart the one shot timer and check it reports its status correctly. */ + xTimerStart( xOneShotTimer, tmrdemoDONT_BLOCK ); + if( xTimerIsTimerActive( xOneShotTimer ) == pdFALSE ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + /* Restart one of the auto reload timers and check that it reports its + status correctly. */ + xTimerStart( xAutoReloadTimers[ configTIMER_QUEUE_LENGTH - 1 ], tmrdemoDONT_BLOCK ); + if( xTimerIsTimerActive( xAutoReloadTimers[ configTIMER_QUEUE_LENGTH - 1 ] ) == pdFALSE ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + for( ucTimer = 0; ucTimer < trmdemoNUM_TIMER_RESETS; ucTimer++ ) + { + /* Delay for half as long as the one shot timer period, then reset it. + It should never expire while this is done, so its callback count should + never increment. */ + vTaskDelay( tmrdemoONE_SHOT_TIMER_PERIOD / 2 ); + + /* Check both running timers are still active, but have not called their + callback functions. */ + if( xTimerIsTimerActive( xOneShotTimer ) == pdFALSE ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + if( ucOneShotTimerCounter != ( uint8_t ) 0 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + if( xTimerIsTimerActive( xAutoReloadTimers[ configTIMER_QUEUE_LENGTH - 1 ] ) == pdFALSE ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + if( ucAutoReloadTimerCounters[ configTIMER_QUEUE_LENGTH - 1 ] != ( uint8_t ) 0 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + /* Reset both running timers. */ + xTimerReset( xOneShotTimer, tmrdemoDONT_BLOCK ); + xTimerReset( xAutoReloadTimers[ configTIMER_QUEUE_LENGTH - 1 ], tmrdemoDONT_BLOCK ); + + if( xTestStatus == pdPASS ) + { + /* No errors have been reported so increment the loop counter so + the check task knows this task is still running. */ + ulLoopCounter++; + } + } + + /* Finally delay long enough for both running timers to expire. */ + vTaskDelay( ( ( TickType_t ) configTIMER_QUEUE_LENGTH ) * xBasePeriod ); + + /* The timers were not reset during the above delay period so should now + both have called their callback functions. */ + if( ucOneShotTimerCounter != ( uint8_t ) 1 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + if( ucAutoReloadTimerCounters[ configTIMER_QUEUE_LENGTH - 1 ] == 0 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + /* The one shot timer should no longer be active, while the auto reload + timer should still be active. */ + if( xTimerIsTimerActive( xAutoReloadTimers[ configTIMER_QUEUE_LENGTH - 1 ] ) == pdFALSE ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + if( xTimerIsTimerActive( xOneShotTimer ) == pdTRUE ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + /* Stop the auto reload timer again. */ + xTimerStop( xAutoReloadTimers[ configTIMER_QUEUE_LENGTH - 1 ], tmrdemoDONT_BLOCK ); + + if( xTimerIsTimerActive( xAutoReloadTimers[ configTIMER_QUEUE_LENGTH - 1 ] ) != pdFALSE ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + /* Clear the timer callback counts, ready for another iteration of these + tests. */ + ucAutoReloadTimerCounters[ configTIMER_QUEUE_LENGTH - 1 ] = ( uint8_t ) 0; + ucOneShotTimerCounter = ( uint8_t ) 0; + + if( xTestStatus == pdPASS ) + { + /* No errors have been reported so increment the loop counter so the check + task knows this task is still running. */ + ulLoopCounter++; + } +} +/*-----------------------------------------------------------*/ + +static void prvResetStartConditionsForNextIteration( void ) +{ +uint8_t ucTimer; + + /* Start the timers again to start all the tests over again. */ + + /* Start the timers again. */ + for( ucTimer = 0; ucTimer < ( uint8_t ) configTIMER_QUEUE_LENGTH; ucTimer++ ) + { + /* The timer has not been started yet! */ + if( xTimerIsTimerActive( xAutoReloadTimers[ ucTimer ] ) != pdFALSE ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + /* Now start the timer. This will appear to happen immediately to + this task because this task is running at a priority below the timer + service task. */ + xTimerStart( xAutoReloadTimers[ ucTimer ], tmrdemoDONT_BLOCK ); + + /* The timer should now be active. */ + if( xTimerIsTimerActive( xAutoReloadTimers[ ucTimer ] ) == pdFALSE ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + } + + if( xTestStatus == pdPASS ) + { + /* No errors have been reported so increment the loop counter so the + check task knows this task is still running. */ + ulLoopCounter++; + } +} +/*-----------------------------------------------------------*/ + +void vTimerPeriodicISRTests( void ) +{ +static TickType_t uxTick = ( TickType_t ) -1; + +#if( configTIMER_TASK_PRIORITY != ( configMAX_PRIORITIES - 1 ) ) + /* The timer service task is not the highest priority task, so it cannot + be assumed that timings will be exact. Timers should never call their + callback before their expiry time, but a margin is permissible for calling + their callback after their expiry time. If exact timing is required then + configTIMER_TASK_PRIORITY must be set to ensure the timer service task + is the highest priority task in the system. + + This function is called from the tick hook. The tick hook is called + even when the scheduler is suspended. Therefore it is possible that the + uxTick count maintained in this function is temporarily ahead of the tick + count maintained by the kernel. When this is the case a message posted from + this function will assume a time stamp in advance of the real time stamp, + which can result in a timer being processed before this function expects it + to. For example, if the kernel's tick count was 100, and uxTick was 102, + then this function will not expect the timer to have expired until the + kernel's tick count is (102 + xBasePeriod), whereas in reality the timer + will expire when the kernel's tick count is (100 + xBasePeriod). For this + reason xMargin is used as an allowable margin for premature timer expiries + as well as late timer expiries. */ + const TickType_t xMargin = 6; +#else + #ifdef _WINDOWS_ + /* Windows is not real real time. */ + const TickType_t xMargin = 8; + #else + const TickType_t xMargin = 4; + #endif /* _WINDOWS_ */ +#endif + + + uxTick++; + + if( uxTick == 0 ) + { + /* The timers will have been created, but not started. Start them now + by setting their period. */ + ucISRAutoReloadTimerCounter = 0; + ucISROneShotTimerCounter = 0; + + /* It is possible that the timer task has not yet made room in the + timer queue. If the timers cannot be started then reset uxTick so + another attempt is made later. */ + uxTick = ( TickType_t ) -1; + + /* Try starting first timer. */ + if( xTimerChangePeriodFromISR( xISRAutoReloadTimer, xBasePeriod, NULL ) == pdPASS ) + { + /* First timer was started, try starting the second timer. */ + if( xTimerChangePeriodFromISR( xISROneShotTimer, xBasePeriod, NULL ) == pdPASS ) + { + /* Both timers were started, so set the uxTick back to its + proper value. */ + uxTick = 0; + } + else + { + /* Second timer could not be started, so stop the first one + again. */ + xTimerStopFromISR( xISRAutoReloadTimer, NULL ); + } + } + } + else if( uxTick == ( xBasePeriod - xMargin ) ) + { + /* Neither timer should have expired yet. */ + if( ( ucISRAutoReloadTimerCounter != 0 ) || ( ucISROneShotTimerCounter != 0 ) ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + } + else if( uxTick == ( xBasePeriod + xMargin ) ) + { + /* Both timers should now have expired once. The auto reload timer will + still be active, but the one shot timer should now have stopped. */ + if( ( ucISRAutoReloadTimerCounter != 1 ) || ( ucISROneShotTimerCounter != 1 ) ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + } + else if( uxTick == ( ( 2 * xBasePeriod ) - xMargin ) ) + { + /* The auto reload timer will still be active, but the one shot timer + should now have stopped - however, at this time neither of the timers + should have expired again since the last test. */ + if( ( ucISRAutoReloadTimerCounter != 1 ) || ( ucISROneShotTimerCounter != 1 ) ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + } + else if( uxTick == ( ( 2 * xBasePeriod ) + xMargin ) ) + { + /* The auto reload timer will still be active, but the one shot timer + should now have stopped. At this time the auto reload timer should have + expired again, but the one shot timer count should not have changed. */ + if( ucISRAutoReloadTimerCounter != 2 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + if( ucISROneShotTimerCounter != 1 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + } + else if( uxTick == ( ( 2 * xBasePeriod ) + ( xBasePeriod >> ( TickType_t ) 2U ) ) ) + { + /* The auto reload timer will still be active, but the one shot timer + should now have stopped. Again though, at this time, neither timer call + back should have been called since the last test. */ + if( ucISRAutoReloadTimerCounter != 2 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + if( ucISROneShotTimerCounter != 1 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + } + else if( uxTick == ( 3 * xBasePeriod ) ) + { + /* Start the one shot timer again. */ + xTimerStartFromISR( xISROneShotTimer, NULL ); + } + else if( uxTick == ( ( 3 * xBasePeriod ) + xMargin ) ) + { + /* The auto reload timer and one shot timer will be active. At + this time the auto reload timer should have expired again, but the one + shot timer count should not have changed yet. */ + if( ucISRAutoReloadTimerCounter != 3 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + if( ucISROneShotTimerCounter != 1 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + /* Now stop the auto reload timer. The one shot timer was started + a few ticks ago. */ + xTimerStopFromISR( xISRAutoReloadTimer, NULL ); + } + else if( uxTick == ( 4 * ( xBasePeriod - xMargin ) ) ) + { + /* The auto reload timer is now stopped, and the one shot timer is + active, but at this time neither timer should have expired since the + last test. */ + if( ucISRAutoReloadTimerCounter != 3 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + if( ucISROneShotTimerCounter != 1 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + } + else if( uxTick == ( ( 4 * xBasePeriod ) + xMargin ) ) + { + /* The auto reload timer is now stopped, and the one shot timer is + active. The one shot timer should have expired again, but the auto + reload timer should not have executed its callback. */ + if( ucISRAutoReloadTimerCounter != 3 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + if( ucISROneShotTimerCounter != 2 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + } + else if( uxTick == ( 8 * xBasePeriod ) ) + { + /* The auto reload timer is now stopped, and the one shot timer has + already expired and then stopped itself. Both callback counters should + not have incremented since the last test. */ + if( ucISRAutoReloadTimerCounter != 3 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + if( ucISROneShotTimerCounter != 2 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + /* Now reset the one shot timer. */ + xTimerResetFromISR( xISROneShotTimer, NULL ); + } + else if( uxTick == ( ( 9 * xBasePeriod ) - xMargin ) ) + { + /* Only the one shot timer should be running, but it should not have + expired since the last test. Check the callback counters have not + incremented, then reset the one shot timer again. */ + if( ucISRAutoReloadTimerCounter != 3 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + if( ucISROneShotTimerCounter != 2 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + xTimerResetFromISR( xISROneShotTimer, NULL ); + } + else if( uxTick == ( ( 10 * xBasePeriod ) - ( 2 * xMargin ) ) ) + { + /* Only the one shot timer should be running, but it should not have + expired since the last test. Check the callback counters have not + incremented, then reset the one shot timer again. */ + if( ucISRAutoReloadTimerCounter != 3 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + if( ucISROneShotTimerCounter != 2 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + xTimerResetFromISR( xISROneShotTimer, NULL ); + } + else if( uxTick == ( ( 11 * xBasePeriod ) - ( 3 * xMargin ) ) ) + { + /* Only the one shot timer should be running, but it should not have + expired since the last test. Check the callback counters have not + incremented, then reset the one shot timer once again. */ + if( ucISRAutoReloadTimerCounter != 3 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + if( ucISROneShotTimerCounter != 2 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + xTimerResetFromISR( xISROneShotTimer, NULL ); + } + else if( uxTick == ( ( 12 * xBasePeriod ) - ( 2 * xMargin ) ) ) + { + /* Only the one shot timer should have been running and this time it + should have expired. Check its callback count has been incremented. + The auto reload timer is still not running so should still have the same + count value. This time the one shot timer is not reset so should not + restart from its expiry period again. */ + if( ucISRAutoReloadTimerCounter != 3 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + if( ucISROneShotTimerCounter != 3 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + } + else if( uxTick == ( 15 * xBasePeriod ) ) + { + /* Neither timer should be running now. Check neither callback count + has incremented, then go back to the start to run these tests all + over again. */ + if( ucISRAutoReloadTimerCounter != 3 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + if( ucISROneShotTimerCounter != 3 ) + { + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } + + uxTick = ( TickType_t ) -1; + } +} +/*-----------------------------------------------------------*/ + +/*** Timer callback functions are defined below here. ***/ + +static void prvAutoReloadTimerCallback( TimerHandle_t pxExpiredTimer ) +{ +uint32_t ulTimerID; + + ulTimerID = ( uint32_t ) pvTimerGetTimerID( pxExpiredTimer ); + if( ulTimerID <= ( configTIMER_QUEUE_LENGTH + 1 ) ) + { + ( ucAutoReloadTimerCounters[ ulTimerID ] )++; + } + else + { + /* The timer ID appears to be unexpected (invalid). */ + xTestStatus = pdFAIL; + configASSERT( xTestStatus ); + } +} +/*-----------------------------------------------------------*/ + +static void prvOneShotTimerCallback( TimerHandle_t pxExpiredTimer ) +{ + /* The parameter is not used in this case as only one timer uses this + callback function. */ + ( void ) pxExpiredTimer; + + ucOneShotTimerCounter++; +} +/*-----------------------------------------------------------*/ + +static void prvISRAutoReloadTimerCallback( TimerHandle_t pxExpiredTimer ) +{ + /* The parameter is not used in this case as only one timer uses this + callback function. */ + ( void ) pxExpiredTimer; + + ucISRAutoReloadTimerCounter++; +} +/*-----------------------------------------------------------*/ + +static void prvISROneShotTimerCallback( TimerHandle_t pxExpiredTimer ) +{ + /* The parameter is not used in this case as only one timer uses this + callback function. */ + ( void ) pxExpiredTimer; + + ucISROneShotTimerCounter++; +} +/*-----------------------------------------------------------*/ + + + + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/blocktim.c b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/blocktim.c new file mode 100644 index 0000000..2528317 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/blocktim.c @@ -0,0 +1,505 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* + * This file contains some test scenarios that ensure tasks do not exit queue + * send or receive functions prematurely. A description of the tests is + * included within the code. + */ + +/* Kernel includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +/* Demo includes. */ +#include "blocktim.h" + +/* Task priorities. Allow these to be overridden. */ +#ifndef bktPRIMARY_PRIORITY + #define bktPRIMARY_PRIORITY ( configMAX_PRIORITIES - 3 ) +#endif + +#ifndef bktSECONDARY_PRIORITY + #define bktSECONDARY_PRIORITY ( configMAX_PRIORITIES - 4 ) +#endif + +/* Task behaviour. */ +#define bktQUEUE_LENGTH ( 5 ) +#define bktSHORT_WAIT ( ( ( TickType_t ) 20 ) / portTICK_PERIOD_MS ) +#define bktPRIMARY_BLOCK_TIME ( 10 ) +#define bktALLOWABLE_MARGIN ( 15 ) +#define bktTIME_TO_BLOCK ( 175 ) +#define bktDONT_BLOCK ( ( TickType_t ) 0 ) +#define bktRUN_INDICATOR ( ( UBaseType_t ) 0x55 ) + +/* The queue on which the tasks block. */ +static QueueHandle_t xTestQueue; + +/* Handle to the secondary task is required by the primary task for calls +to vTaskSuspend/Resume(). */ +static TaskHandle_t xSecondary; + +/* Used to ensure that tasks are still executing without error. */ +static volatile BaseType_t xPrimaryCycles = 0, xSecondaryCycles = 0; +static volatile BaseType_t xErrorOccurred = pdFALSE; + +/* Provides a simple mechanism for the primary task to know when the +secondary task has executed. */ +static volatile UBaseType_t xRunIndicator; + +/* The two test tasks. Their behaviour is commented within the files. */ +static void vPrimaryBlockTimeTestTask( void *pvParameters ); +static void vSecondaryBlockTimeTestTask( void *pvParameters ); + +/*-----------------------------------------------------------*/ + +void vCreateBlockTimeTasks( void ) +{ + /* Create the queue on which the two tasks block. */ + xTestQueue = xQueueCreate( bktQUEUE_LENGTH, sizeof( BaseType_t ) ); + + /* vQueueAddToRegistry() adds the queue to the queue registry, if one is + in use. The queue registry is provided as a means for kernel aware + debuggers to locate queues and has no purpose if a kernel aware debugger + is not being used. The call to vQueueAddToRegistry() will be removed + by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is + defined to be less than 1. */ + vQueueAddToRegistry( xTestQueue, "Block_Time_Queue" ); + + /* Create the two test tasks. */ + xTaskCreate( vPrimaryBlockTimeTestTask, "BTest1", configMINIMAL_STACK_SIZE, NULL, bktPRIMARY_PRIORITY, NULL ); + xTaskCreate( vSecondaryBlockTimeTestTask, "BTest2", configMINIMAL_STACK_SIZE, NULL, bktSECONDARY_PRIORITY, &xSecondary ); +} +/*-----------------------------------------------------------*/ + +static void vPrimaryBlockTimeTestTask( void *pvParameters ) +{ +BaseType_t xItem, xData; +TickType_t xTimeWhenBlocking; +TickType_t xTimeToBlock, xBlockedTime; + + ( void ) pvParameters; + + for( ;; ) + { + /********************************************************************* + Test 1 + + Simple block time wakeup test on queue receives. */ + for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ ) + { + /* The queue is empty. Attempt to read from the queue using a block + time. When we wake, ensure the delta in time is as expected. */ + xTimeToBlock = ( TickType_t ) ( bktPRIMARY_BLOCK_TIME << xItem ); + + xTimeWhenBlocking = xTaskGetTickCount(); + + /* We should unblock after xTimeToBlock having not received + anything on the queue. */ + if( xQueueReceive( xTestQueue, &xData, xTimeToBlock ) != errQUEUE_EMPTY ) + { + xErrorOccurred = pdTRUE; + } + + /* How long were we blocked for? */ + xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking; + + if( xBlockedTime < xTimeToBlock ) + { + /* Should not have blocked for less than we requested. */ + xErrorOccurred = pdTRUE; + } + + if( xBlockedTime > ( xTimeToBlock + bktALLOWABLE_MARGIN ) ) + { + /* Should not have blocked for longer than we requested, + although we would not necessarily run as soon as we were + unblocked so a margin is allowed. */ + xErrorOccurred = pdTRUE; + } + } + + /********************************************************************* + Test 2 + + Simple block time wakeup test on queue sends. + + First fill the queue. It should be empty so all sends should pass. */ + for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ ) + { + if( xQueueSend( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + } + + for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ ) + { + /* The queue is full. Attempt to write to the queue using a block + time. When we wake, ensure the delta in time is as expected. */ + xTimeToBlock = ( TickType_t ) ( bktPRIMARY_BLOCK_TIME << xItem ); + + xTimeWhenBlocking = xTaskGetTickCount(); + + /* We should unblock after xTimeToBlock having not received + anything on the queue. */ + if( xQueueSend( xTestQueue, &xItem, xTimeToBlock ) != errQUEUE_FULL ) + { + xErrorOccurred = pdTRUE; + } + + /* How long were we blocked for? */ + xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking; + + if( xBlockedTime < xTimeToBlock ) + { + /* Should not have blocked for less than we requested. */ + xErrorOccurred = pdTRUE; + } + + if( xBlockedTime > ( xTimeToBlock + bktALLOWABLE_MARGIN ) ) + { + /* Should not have blocked for longer than we requested, + although we would not necessarily run as soon as we were + unblocked so a margin is allowed. */ + xErrorOccurred = pdTRUE; + } + } + + /********************************************************************* + Test 3 + + Wake the other task, it will block attempting to post to the queue. + When we read from the queue the other task will wake, but before it + can run we will post to the queue again. When the other task runs it + will find the queue still full, even though it was woken. It should + recognise that its block time has not expired and return to block for + the remains of its block time. + + Wake the other task so it blocks attempting to post to the already + full queue. */ + xRunIndicator = 0; + vTaskResume( xSecondary ); + + /* We need to wait a little to ensure the other task executes. */ + while( xRunIndicator != bktRUN_INDICATOR ) + { + /* The other task has not yet executed. */ + vTaskDelay( bktSHORT_WAIT ); + } + /* Make sure the other task is blocked on the queue. */ + vTaskDelay( bktSHORT_WAIT ); + xRunIndicator = 0; + + for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ ) + { + /* Now when we make space on the queue the other task should wake + but not execute as this task has higher priority. */ + if( xQueueReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + + /* Now fill the queue again before the other task gets a chance to + execute. If the other task had executed we would find the queue + full ourselves, and the other task have set xRunIndicator. */ + if( xQueueSend( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + + if( xRunIndicator == bktRUN_INDICATOR ) + { + /* The other task should not have executed. */ + xErrorOccurred = pdTRUE; + } + + /* Raise the priority of the other task so it executes and blocks + on the queue again. */ + vTaskPrioritySet( xSecondary, bktPRIMARY_PRIORITY + 2 ); + + /* The other task should now have re-blocked without exiting the + queue function. */ + if( xRunIndicator == bktRUN_INDICATOR ) + { + /* The other task should not have executed outside of the + queue function. */ + xErrorOccurred = pdTRUE; + } + + /* Set the priority back down. */ + vTaskPrioritySet( xSecondary, bktSECONDARY_PRIORITY ); + } + + /* Let the other task timeout. When it unblockes it will check that it + unblocked at the correct time, then suspend itself. */ + while( xRunIndicator != bktRUN_INDICATOR ) + { + vTaskDelay( bktSHORT_WAIT ); + } + vTaskDelay( bktSHORT_WAIT ); + xRunIndicator = 0; + + + /********************************************************************* + Test 4 + + As per test 3 - but with the send and receive the other way around. + The other task blocks attempting to read from the queue. + + Empty the queue. We should find that it is full. */ + for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ ) + { + if( xQueueReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + } + + /* Wake the other task so it blocks attempting to read from the + already empty queue. */ + vTaskResume( xSecondary ); + + /* We need to wait a little to ensure the other task executes. */ + while( xRunIndicator != bktRUN_INDICATOR ) + { + vTaskDelay( bktSHORT_WAIT ); + } + vTaskDelay( bktSHORT_WAIT ); + xRunIndicator = 0; + + for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ ) + { + /* Now when we place an item on the queue the other task should + wake but not execute as this task has higher priority. */ + if( xQueueSend( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + + /* Now empty the queue again before the other task gets a chance to + execute. If the other task had executed we would find the queue + empty ourselves, and the other task would be suspended. */ + if( xQueueReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + + if( xRunIndicator == bktRUN_INDICATOR ) + { + /* The other task should not have executed. */ + xErrorOccurred = pdTRUE; + } + + /* Raise the priority of the other task so it executes and blocks + on the queue again. */ + vTaskPrioritySet( xSecondary, bktPRIMARY_PRIORITY + 2 ); + + /* The other task should now have re-blocked without exiting the + queue function. */ + if( xRunIndicator == bktRUN_INDICATOR ) + { + /* The other task should not have executed outside of the + queue function. */ + xErrorOccurred = pdTRUE; + } + vTaskPrioritySet( xSecondary, bktSECONDARY_PRIORITY ); + } + + /* Let the other task timeout. When it unblockes it will check that it + unblocked at the correct time, then suspend itself. */ + while( xRunIndicator != bktRUN_INDICATOR ) + { + vTaskDelay( bktSHORT_WAIT ); + } + vTaskDelay( bktSHORT_WAIT ); + + xPrimaryCycles++; + } +} +/*-----------------------------------------------------------*/ + +static void vSecondaryBlockTimeTestTask( void *pvParameters ) +{ +TickType_t xTimeWhenBlocking, xBlockedTime; +BaseType_t xData; + + ( void ) pvParameters; + + for( ;; ) + { + /********************************************************************* + Test 1 and 2 + + This task does does not participate in these tests. */ + vTaskSuspend( NULL ); + + /********************************************************************* + Test 3 + + The first thing we do is attempt to read from the queue. It should be + full so we block. Note the time before we block so we can check the + wake time is as per that expected. */ + xTimeWhenBlocking = xTaskGetTickCount(); + + /* We should unblock after bktTIME_TO_BLOCK having not sent + anything to the queue. */ + xData = 0; + xRunIndicator = bktRUN_INDICATOR; + if( xQueueSend( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_FULL ) + { + xErrorOccurred = pdTRUE; + } + + /* How long were we inside the send function? */ + xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking; + + /* We should not have blocked for less time than bktTIME_TO_BLOCK. */ + if( xBlockedTime < bktTIME_TO_BLOCK ) + { + xErrorOccurred = pdTRUE; + } + + /* We should of not blocked for much longer than bktALLOWABLE_MARGIN + either. A margin is permitted as we would not necessarily run as + soon as we unblocked. */ + if( xBlockedTime > ( bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN ) ) + { + xErrorOccurred = pdTRUE; + } + + /* Suspend ready for test 3. */ + xRunIndicator = bktRUN_INDICATOR; + vTaskSuspend( NULL ); + + /********************************************************************* + Test 4 + + As per test three, but with the send and receive reversed. */ + xTimeWhenBlocking = xTaskGetTickCount(); + + /* We should unblock after bktTIME_TO_BLOCK having not received + anything on the queue. */ + xRunIndicator = bktRUN_INDICATOR; + if( xQueueReceive( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_EMPTY ) + { + xErrorOccurred = pdTRUE; + } + + xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking; + + /* We should not have blocked for less time than bktTIME_TO_BLOCK. */ + if( xBlockedTime < bktTIME_TO_BLOCK ) + { + xErrorOccurred = pdTRUE; + } + + /* We should of not blocked for much longer than bktALLOWABLE_MARGIN + either. A margin is permitted as we would not necessarily run as soon + as we unblocked. */ + if( xBlockedTime > ( bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN ) ) + { + xErrorOccurred = pdTRUE; + } + + xRunIndicator = bktRUN_INDICATOR; + + xSecondaryCycles++; + } +} +/*-----------------------------------------------------------*/ + +BaseType_t xAreBlockTimeTestTasksStillRunning( void ) +{ +static BaseType_t xLastPrimaryCycleCount = 0, xLastSecondaryCycleCount = 0; +BaseType_t xReturn = pdPASS; + + /* Have both tasks performed at least one cycle since this function was + last called? */ + if( xPrimaryCycles == xLastPrimaryCycleCount ) + { + xReturn = pdFAIL; + } + + if( xSecondaryCycles == xLastSecondaryCycleCount ) + { + xReturn = pdFAIL; + } + + if( xErrorOccurred == pdTRUE ) + { + xReturn = pdFAIL; + } + + xLastSecondaryCycleCount = xSecondaryCycles; + xLastPrimaryCycleCount = xPrimaryCycles; + + return xReturn; +} diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/comtest.c b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/comtest.c new file mode 100644 index 0000000..2a1542a --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/comtest.c @@ -0,0 +1,303 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +/* + * This version of comtest. c is for use on systems that have limited stack + * space and no display facilities. The complete version can be found in + * the Demo/Common/Full directory. + * + * Creates two tasks that operate on an interrupt driven serial port. A + * loopback connector should be used so that everything that is transmitted is + * also received. The serial port does not use any flow control. On a + * standard 9way 'D' connector pins two and three should be connected together. + * + * The first task posts a sequence of characters to the Tx queue, toggling an + * LED on each successful post. At the end of the sequence it sleeps for a + * pseudo-random period before resending the same sequence. + * + * The UART Tx end interrupt is enabled whenever data is available in the Tx + * queue. The Tx end ISR removes a single character from the Tx queue and + * passes it to the UART for transmission. + * + * The second task blocks on the Rx queue waiting for a character to become + * available. When the UART Rx end interrupt receives a character it places + * it in the Rx queue, waking the second task. The second task checks that the + * characters removed from the Rx queue form the same sequence as those posted + * to the Tx queue, and toggles an LED for each correct character. + * + * The receiving task is spawned with a higher priority than the transmitting + * task. The receiver will therefore wake every time a character is + * transmitted so neither the Tx or Rx queue should ever hold more than a few + * characters. + * + */ + +/* Scheduler include files. */ +#include +#include "FreeRTOS.h" +#include "task.h" + +/* Demo program include files. */ +#include "serial.h" +#include "comtest.h" +#include "partest.h" + +#define comSTACK_SIZE configMINIMAL_STACK_SIZE +#define comTX_LED_OFFSET ( 0 ) +#define comRX_LED_OFFSET ( 1 ) +#define comTOTAL_PERMISSIBLE_ERRORS ( 2 ) + +/* The Tx task will transmit the sequence of characters at a pseudo random +interval. This is the maximum and minimum block time between sends. */ +#define comTX_MAX_BLOCK_TIME ( ( TickType_t ) 0x96 ) +#define comTX_MIN_BLOCK_TIME ( ( TickType_t ) 0x32 ) +#define comOFFSET_TIME ( ( TickType_t ) 3 ) + +/* We should find that each character can be queued for Tx immediately and we +don't have to block to send. */ +#define comNO_BLOCK ( ( TickType_t ) 0 ) + +/* The Rx task will block on the Rx queue for a long period. */ +#define comRX_BLOCK_TIME ( ( TickType_t ) 0xffff ) + +/* The sequence transmitted is from comFIRST_BYTE to and including comLAST_BYTE. */ +#define comFIRST_BYTE ( 'A' ) +#define comLAST_BYTE ( 'X' ) + +#define comBUFFER_LEN ( ( UBaseType_t ) ( comLAST_BYTE - comFIRST_BYTE ) + ( UBaseType_t ) 1 ) +#define comINITIAL_RX_COUNT_VALUE ( 0 ) + +/* Handle to the com port used by both tasks. */ +static xComPortHandle xPort = NULL; + +/* The transmit task as described at the top of the file. */ +static portTASK_FUNCTION_PROTO( vComTxTask, pvParameters ); + +/* The receive task as described at the top of the file. */ +static portTASK_FUNCTION_PROTO( vComRxTask, pvParameters ); + +/* The LED that should be toggled by the Rx and Tx tasks. The Rx task will +toggle LED ( uxBaseLED + comRX_LED_OFFSET). The Tx task will toggle LED +( uxBaseLED + comTX_LED_OFFSET ). */ +static UBaseType_t uxBaseLED = 0; + +/* Check variable used to ensure no error have occurred. The Rx task will +increment this variable after every successfully received sequence. If at any +time the sequence is incorrect the the variable will stop being incremented. */ +static volatile UBaseType_t uxRxLoops = comINITIAL_RX_COUNT_VALUE; + +/*-----------------------------------------------------------*/ + +void vAltStartComTestTasks( UBaseType_t uxPriority, uint32_t ulBaudRate, UBaseType_t uxLED ) +{ + /* Initialise the com port then spawn the Rx and Tx tasks. */ + uxBaseLED = uxLED; + xSerialPortInitMinimal( ulBaudRate, comBUFFER_LEN ); + + /* The Tx task is spawned with a lower priority than the Rx task. */ + xTaskCreate( vComTxTask, "COMTx", comSTACK_SIZE, NULL, uxPriority - 1, ( TaskHandle_t * ) NULL ); + xTaskCreate( vComRxTask, "COMRx", comSTACK_SIZE, NULL, uxPriority, ( TaskHandle_t * ) NULL ); +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vComTxTask, pvParameters ) +{ +char cByteToSend; +TickType_t xTimeToWait; + + /* Just to stop compiler warnings. */ + ( void ) pvParameters; + + for( ;; ) + { + /* Simply transmit a sequence of characters from comFIRST_BYTE to + comLAST_BYTE. */ + for( cByteToSend = comFIRST_BYTE; cByteToSend <= comLAST_BYTE; cByteToSend++ ) + { + if( xSerialPutChar( xPort, cByteToSend, comNO_BLOCK ) == pdPASS ) + { + vParTestToggleLED( uxBaseLED + comTX_LED_OFFSET ); + } + } + + /* Turn the LED off while we are not doing anything. */ + vParTestSetLED( uxBaseLED + comTX_LED_OFFSET, pdFALSE ); + + /* We have posted all the characters in the string - wait before + re-sending. Wait a pseudo-random time as this will provide a better + test. */ + xTimeToWait = xTaskGetTickCount() + comOFFSET_TIME; + + /* Make sure we don't wait too long... */ + xTimeToWait %= comTX_MAX_BLOCK_TIME; + + /* ...but we do want to wait. */ + if( xTimeToWait < comTX_MIN_BLOCK_TIME ) + { + xTimeToWait = comTX_MIN_BLOCK_TIME; + } + + vTaskDelay( xTimeToWait ); + } +} /*lint !e715 !e818 pvParameters is required for a task function even if it is not referenced. */ +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vComRxTask, pvParameters ) +{ +signed char cExpectedByte, cByteRxed; +BaseType_t xResyncRequired = pdFALSE, xErrorOccurred = pdFALSE; + + /* Just to stop compiler warnings. */ + ( void ) pvParameters; + + for( ;; ) + { + /* We expect to receive the characters from comFIRST_BYTE to + comLAST_BYTE in an incrementing order. Loop to receive each byte. */ + for( cExpectedByte = comFIRST_BYTE; cExpectedByte <= comLAST_BYTE; cExpectedByte++ ) + { + /* Block on the queue that contains received bytes until a byte is + available. */ + if( xSerialGetChar( xPort, &cByteRxed, comRX_BLOCK_TIME ) ) + { + /* Was this the byte we were expecting? If so, toggle the LED, + otherwise we are out on sync and should break out of the loop + until the expected character sequence is about to restart. */ + if( cByteRxed == cExpectedByte ) + { + vParTestToggleLED( uxBaseLED + comRX_LED_OFFSET ); + } + else + { + xResyncRequired = pdTRUE; + break; /*lint !e960 Non-switch break allowed. */ + } + } + } + + /* Turn the LED off while we are not doing anything. */ + vParTestSetLED( uxBaseLED + comRX_LED_OFFSET, pdFALSE ); + + /* Did we break out of the loop because the characters were received in + an unexpected order? If so wait here until the character sequence is + about to restart. */ + if( xResyncRequired == pdTRUE ) + { + while( cByteRxed != comLAST_BYTE ) + { + /* Block until the next char is available. */ + xSerialGetChar( xPort, &cByteRxed, comRX_BLOCK_TIME ); + } + + /* Note that an error occurred which caused us to have to resync. + We use this to stop incrementing the loop counter so + sAreComTestTasksStillRunning() will return false - indicating an + error. */ + xErrorOccurred++; + + /* We have now resynced with the Tx task and can continue. */ + xResyncRequired = pdFALSE; + } + else + { + if( xErrorOccurred < comTOTAL_PERMISSIBLE_ERRORS ) + { + /* Increment the count of successful loops. As error + occurring (i.e. an unexpected character being received) will + prevent this counter being incremented for the rest of the + execution. Don't worry about mutual exclusion on this + variable - it doesn't really matter as we just want it + to change. */ + uxRxLoops++; + } + } + } +} /*lint !e715 !e818 pvParameters is required for a task function even if it is not referenced. */ +/*-----------------------------------------------------------*/ + +BaseType_t xAreComTestTasksStillRunning( void ) +{ +BaseType_t xReturn; + + /* If the count of successful reception loops has not changed than at + some time an error occurred (i.e. a character was received out of sequence) + and we will return false. */ + if( uxRxLoops == comINITIAL_RX_COUNT_VALUE ) + { + xReturn = pdFALSE; + } + else + { + xReturn = pdTRUE; + } + + /* Reset the count of successful Rx loops. When this function is called + again we expect this to have been incremented. */ + uxRxLoops = comINITIAL_RX_COUNT_VALUE; + + return xReturn; +} + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/comtest_strings.c b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/comtest_strings.c new file mode 100644 index 0000000..0e84b12 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/comtest_strings.c @@ -0,0 +1,349 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +/* + * Creates a task and a timer that operate on an interrupt driven serial port. + * This demo assumes that the characters transmitted on a port will also be + * received on the same port. Therefore, the UART must either be connected to + * an echo server, or the uart connector must have a loopback connector fitted. + * See http://www.serialporttool.com/CommEcho.htm for a suitable echo server + * for Windows hosts. + * + * The timer sends a string to the UART, toggles an LED, then resets itself by + * changing its own period. The period is calculated as a pseudo random number + * between comTX_MAX_BLOCK_TIME and comTX_MIN_BLOCK_TIME. + * + * The task blocks on an Rx queue waiting for a character to become available. + * Received characters are checked to ensure they match those transmitted by the + * Tx timer. An error is latched if characters are missing, incorrect, or + * arrive too slowly. + * + * How characters are actually transmitted and received is port specific. Demos + * that include this test/demo file will provide example drivers. The Tx timer + * executes in the context of the timer service (daemon) task, and must + * therefore never attempt to block. + * + */ + +/* Scheduler include files. */ +#include +#include +#include "FreeRTOS.h" +#include "task.h" +#include "timers.h" + +#ifndef configUSE_TIMERS + #error This demo uses timers. configUSE_TIMERS must be set to 1 in FreeRTOSConfig.h. +#endif + +#if configUSE_TIMERS != 1 + #error This demo uses timers. configUSE_TIMERS must be set to 1 in FreeRTOSConfig.h. +#endif + + +/* Demo program include files. */ +#include "serial.h" +#include "comtest_strings.h" +#include "partest.h" + +/* The size of the stack given to the Rx task. */ +#define comSTACK_SIZE configMINIMAL_STACK_SIZE + +/* See the comment above the declaraction of the uxBaseLED variable. */ +#define comTX_LED_OFFSET ( 0 ) +#define comRX_LED_OFFSET ( 1 ) + +/* The Tx timer transmits the sequence of characters at a pseudo random +interval that is capped between comTX_MAX_BLOCK_TIME and +comTX_MIN_BLOCK_TIME. */ +#define comTX_MAX_BLOCK_TIME ( ( TickType_t ) 0x96 ) +#define comTX_MIN_BLOCK_TIME ( ( TickType_t ) 0x32 ) +#define comOFFSET_TIME ( ( TickType_t ) 3 ) + +/* States for the simple state machine implemented in the Rx task. */ +#define comtstWAITING_START_OF_STRING 0 +#define comtstWAITING_END_OF_STRING 1 + +/* A short delay in ticks - this delay is used to allow the Rx queue to fill up +a bit so more than one character can be processed at a time. This is relative +to comTX_MIN_BLOCK_TIME to ensure it is never longer than the shortest gap +between transmissions. It could be worked out more scientifically from the +baud rate being used. */ +#define comSHORT_DELAY ( comTX_MIN_BLOCK_TIME >> ( TickType_t ) 2 ) + +/* The string that is transmitted and received. */ +#define comTRANSACTED_STRING "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890" + +/* A block time of 0 simply means "don't block". */ +#define comtstDONT_BLOCK ( TickType_t ) 0 + +/* Handle to the com port used by both tasks. */ +static xComPortHandle xPort = NULL; + +/* The callback function allocated to the transmit timer, as described in the +comments at the top of this file. */ +static void prvComTxTimerCallback( TimerHandle_t xTimer ); + +/* The receive task as described in the comments at the top of this file. */ +static void vComRxTask( void *pvParameters ); + +/* The Rx task will toggle LED ( uxBaseLED + comRX_LED_OFFSET). The Tx task +will toggle LED ( uxBaseLED + comTX_LED_OFFSET ). */ +static UBaseType_t uxBaseLED = 0; + +/* The Rx task toggles uxRxLoops on each successful iteration of its defined +function - provided no errors have ever been latched. If this variable stops +incrementing, then an error has occurred. */ +static volatile UBaseType_t uxRxLoops = 0UL; + +/* The timer used to periodically transmit the string. This is the timer that +has prvComTxTimerCallback allocated to it as its callback function. */ +static TimerHandle_t xTxTimer = NULL; + +/* The string length is held at file scope so the Tx timer does not need to +calculate it each time it executes. */ +static size_t xStringLength = 0U; + +/*-----------------------------------------------------------*/ + +void vStartComTestStringsTasks( UBaseType_t uxPriority, uint32_t ulBaudRate, UBaseType_t uxLED ) +{ + /* Store values that are used at run time. */ + uxBaseLED = uxLED; + + /* Calculate the string length here, rather than each time the Tx timer + executes. */ + xStringLength = strlen( comTRANSACTED_STRING ); + + /* Include the null terminator in the string length as this is used to + detect the end of the string in the Rx task. */ + xStringLength++; + + /* Initialise the com port, then spawn the Rx task and create the Tx + timer. */ + xSerialPortInitMinimal( ulBaudRate, ( xStringLength * 2U ) ); + + /* Create the Rx task and the Tx timer. The timer is started from the + Rx task. */ + xTaskCreate( vComRxTask, "COMRx", comSTACK_SIZE, NULL, uxPriority, ( TaskHandle_t * ) NULL ); + xTxTimer = xTimerCreate( "TxTimer", comTX_MIN_BLOCK_TIME, pdFALSE, NULL, prvComTxTimerCallback ); + configASSERT( xTxTimer ); +} +/*-----------------------------------------------------------*/ + +static void prvComTxTimerCallback( TimerHandle_t xTimer ) +{ +TickType_t xTimeToWait; + + /* The parameter is not used in this case. */ + ( void ) xTimer; + + /* Send the string. How this is actually performed depends on the + sample driver provided with this demo. However - as this is a timer, + it executes in the context of the timer task and therefore must not + block. */ + vSerialPutString( xPort, comTRANSACTED_STRING, xStringLength ); + + /* Toggle an LED to give a visible indication that another transmission + has been performed. */ + vParTestToggleLED( uxBaseLED + comTX_LED_OFFSET ); + + /* Wait a pseudo random time before sending the string again. */ + xTimeToWait = xTaskGetTickCount() + comOFFSET_TIME; + + /* Ensure the time to wait is not greater than comTX_MAX_BLOCK_TIME. */ + xTimeToWait %= comTX_MAX_BLOCK_TIME; + + /* Ensure the time to wait is not less than comTX_MIN_BLOCK_TIME. */ + if( xTimeToWait < comTX_MIN_BLOCK_TIME ) + { + xTimeToWait = comTX_MIN_BLOCK_TIME; + } + + /* Reset the timer to run again xTimeToWait ticks from now. This function + is called from the context of the timer task, so the block time must not + be anything other than zero. */ + xTimerChangePeriod( xTxTimer, xTimeToWait, comtstDONT_BLOCK ); +} +/*-----------------------------------------------------------*/ + +static void vComRxTask( void *pvParameters ) +{ +BaseType_t xState = comtstWAITING_START_OF_STRING, xErrorOccurred = pdFALSE; +char *pcExpectedByte, cRxedChar; +const xComPortHandle xPort = NULL; + + /* The parameter is not used in this example. */ + ( void ) pvParameters; + + /* Start the Tx timer. This only needs to be started once, as it will + reset itself thereafter. */ + xTimerStart( xTxTimer, portMAX_DELAY ); + + /* The first expected Rx character is the first in the string that is + transmitted. */ + pcExpectedByte = comTRANSACTED_STRING; + + for( ;; ) + { + /* Wait for the next character. */ + if( xSerialGetChar( xPort, &cRxedChar, ( comTX_MAX_BLOCK_TIME * 2 ) ) == pdFALSE ) + { + /* A character definitely should have been received by now. As a + character was not received an error must have occurred (which might + just be that the loopback connector is not fitted). */ + xErrorOccurred = pdTRUE; + } + + switch( xState ) + { + case comtstWAITING_START_OF_STRING: + if( cRxedChar == *pcExpectedByte ) + { + /* The received character was the first character of the + string. Move to the next state to check each character + as it comes in until the entire string has been received. */ + xState = comtstWAITING_END_OF_STRING; + pcExpectedByte++; + + /* Block for a short period. This just allows the Rx queue + to contain more than one character, and therefore prevent + thrashing reads to the queue, and repetitive context + switches as each character is received. */ + vTaskDelay( comSHORT_DELAY ); + } + break; + + case comtstWAITING_END_OF_STRING: + if( cRxedChar == *pcExpectedByte ) + { + /* The received character was the expected character. Was + it the last character in the string - i.e. the null + terminator? */ + if( cRxedChar == 0x00 ) + { + /* The entire string has been received. If no errors + have been latched, then increment the loop counter to + show this task is still healthy. */ + if( xErrorOccurred == pdFALSE ) + { + uxRxLoops++; + + /* Toggle an LED to give a visible sign that a + complete string has been received. */ + vParTestToggleLED( uxBaseLED + comRX_LED_OFFSET ); + } + + /* Go back to wait for the start of the next string. */ + pcExpectedByte = comTRANSACTED_STRING; + xState = comtstWAITING_START_OF_STRING; + } + else + { + /* Wait for the next character in the string. */ + pcExpectedByte++; + } + } + else + { + /* The character received was not that expected. */ + xErrorOccurred = pdTRUE; + } + break; + + default: + /* Should not get here. Stop the Rx loop counter from + incrementing to latch the error. */ + xErrorOccurred = pdTRUE; + break; + } + } +} +/*-----------------------------------------------------------*/ + +BaseType_t xAreComTestTasksStillRunning( void ) +{ +BaseType_t xReturn; + + /* If the count of successful reception loops has not changed than at + some time an error occurred (i.e. a character was received out of sequence) + and false is returned. */ + if( uxRxLoops == 0UL ) + { + xReturn = pdFALSE; + } + else + { + xReturn = pdTRUE; + } + + /* Reset the count of successful Rx loops. When this function is called + again it should have been incremented again. */ + uxRxLoops = 0UL; + + return xReturn; +} + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/countsem.c b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/countsem.c new file mode 100644 index 0000000..aa33933 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/countsem.c @@ -0,0 +1,322 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +/* + * Simple demonstration of the usage of counting semaphore. + */ + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "semphr.h" + +/* Demo program include files. */ +#include "countsem.h" + +/* The maximum count value that the semaphore used for the demo can hold. */ +#define countMAX_COUNT_VALUE ( 200 ) + +/* Constants used to indicate whether or not the semaphore should have been +created with its maximum count value, or its minimum count value. These +numbers are used to ensure that the pointers passed in as the task parameters +are valid. */ +#define countSTART_AT_MAX_COUNT ( 0xaa ) +#define countSTART_AT_ZERO ( 0x55 ) + +/* Two tasks are created for the test. One uses a semaphore created with its +count value set to the maximum, and one with the count value set to zero. */ +#define countNUM_TEST_TASKS ( 2 ) +#define countDONT_BLOCK ( 0 ) + +/*-----------------------------------------------------------*/ + +/* Flag that will be latched to pdTRUE should any unexpected behaviour be +detected in any of the tasks. */ +static volatile BaseType_t xErrorDetected = pdFALSE; + +/*-----------------------------------------------------------*/ + +/* + * The demo task. This simply counts the semaphore up to its maximum value, + * the counts it back down again. The result of each semaphore 'give' and + * 'take' is inspected, with an error being flagged if it is found not to be + * the expected result. + */ +static void prvCountingSemaphoreTask( void *pvParameters ); + +/* + * Utility function to increment the semaphore count value up from zero to + * countMAX_COUNT_VALUE. + */ +static void prvIncrementSemaphoreCount( SemaphoreHandle_t xSemaphore, UBaseType_t *puxLoopCounter ); + +/* + * Utility function to decrement the semaphore count value up from + * countMAX_COUNT_VALUE to zero. + */ +static void prvDecrementSemaphoreCount( SemaphoreHandle_t xSemaphore, UBaseType_t *puxLoopCounter ); + +/*-----------------------------------------------------------*/ + +/* The structure that is passed into the task as the task parameter. */ +typedef struct COUNT_SEM_STRUCT +{ + /* The semaphore to be used for the demo. */ + SemaphoreHandle_t xSemaphore; + + /* Set to countSTART_AT_MAX_COUNT if the semaphore should be created with + its count value set to its max count value, or countSTART_AT_ZERO if it + should have been created with its count value set to 0. */ + UBaseType_t uxExpectedStartCount; + + /* Incremented on each cycle of the demo task. Used to detect a stalled + task. */ + UBaseType_t uxLoopCounter; +} xCountSemStruct; + +/* Two structures are defined, one is passed to each test task. */ +static volatile xCountSemStruct xParameters[ countNUM_TEST_TASKS ]; + +/*-----------------------------------------------------------*/ + +void vStartCountingSemaphoreTasks( void ) +{ + /* Create the semaphores that we are going to use for the test/demo. The + first should be created such that it starts at its maximum count value, + the second should be created such that it starts with a count value of zero. */ + xParameters[ 0 ].xSemaphore = xSemaphoreCreateCounting( countMAX_COUNT_VALUE, countMAX_COUNT_VALUE ); + xParameters[ 0 ].uxExpectedStartCount = countSTART_AT_MAX_COUNT; + xParameters[ 0 ].uxLoopCounter = 0; + + xParameters[ 1 ].xSemaphore = xSemaphoreCreateCounting( countMAX_COUNT_VALUE, 0 ); + xParameters[ 1 ].uxExpectedStartCount = 0; + xParameters[ 1 ].uxLoopCounter = 0; + + /* vQueueAddToRegistry() adds the semaphore to the registry, if one is + in use. The registry is provided as a means for kernel aware + debuggers to locate semaphores and has no purpose if a kernel aware debugger + is not being used. The call to vQueueAddToRegistry() will be removed + by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is + defined to be less than 1. */ + vQueueAddToRegistry( ( QueueHandle_t ) xParameters[ 0 ].xSemaphore, "Counting_Sem_1" ); + vQueueAddToRegistry( ( QueueHandle_t ) xParameters[ 1 ].xSemaphore, "Counting_Sem_2" ); + + + /* Were the semaphores created? */ + if( ( xParameters[ 0 ].xSemaphore != NULL ) || ( xParameters[ 1 ].xSemaphore != NULL ) ) + { + /* Create the demo tasks, passing in the semaphore to use as the parameter. */ + xTaskCreate( prvCountingSemaphoreTask, "CNT1", configMINIMAL_STACK_SIZE, ( void * ) &( xParameters[ 0 ] ), tskIDLE_PRIORITY, NULL ); + xTaskCreate( prvCountingSemaphoreTask, "CNT2", configMINIMAL_STACK_SIZE, ( void * ) &( xParameters[ 1 ] ), tskIDLE_PRIORITY, NULL ); + } +} +/*-----------------------------------------------------------*/ + +static void prvDecrementSemaphoreCount( SemaphoreHandle_t xSemaphore, UBaseType_t *puxLoopCounter ) +{ +UBaseType_t ux; + + /* If the semaphore count is at its maximum then we should not be able to + 'give' the semaphore. */ + if( xSemaphoreGive( xSemaphore ) == pdPASS ) + { + xErrorDetected = pdTRUE; + } + + /* We should be able to 'take' the semaphore countMAX_COUNT_VALUE times. */ + for( ux = 0; ux < countMAX_COUNT_VALUE; ux++ ) + { + if( xSemaphoreTake( xSemaphore, countDONT_BLOCK ) != pdPASS ) + { + /* We expected to be able to take the semaphore. */ + xErrorDetected = pdTRUE; + } + + ( *puxLoopCounter )++; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* If the semaphore count is zero then we should not be able to 'take' + the semaphore. */ + if( xSemaphoreTake( xSemaphore, countDONT_BLOCK ) == pdPASS ) + { + xErrorDetected = pdTRUE; + } +} +/*-----------------------------------------------------------*/ + +static void prvIncrementSemaphoreCount( SemaphoreHandle_t xSemaphore, UBaseType_t *puxLoopCounter ) +{ +UBaseType_t ux; + + /* If the semaphore count is zero then we should not be able to 'take' + the semaphore. */ + if( xSemaphoreTake( xSemaphore, countDONT_BLOCK ) == pdPASS ) + { + xErrorDetected = pdTRUE; + } + + /* We should be able to 'give' the semaphore countMAX_COUNT_VALUE times. */ + for( ux = 0; ux < countMAX_COUNT_VALUE; ux++ ) + { + if( xSemaphoreGive( xSemaphore ) != pdPASS ) + { + /* We expected to be able to take the semaphore. */ + xErrorDetected = pdTRUE; + } + + ( *puxLoopCounter )++; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* If the semaphore count is at its maximum then we should not be able to + 'give' the semaphore. */ + if( xSemaphoreGive( xSemaphore ) == pdPASS ) + { + xErrorDetected = pdTRUE; + } +} +/*-----------------------------------------------------------*/ + +static void prvCountingSemaphoreTask( void *pvParameters ) +{ +xCountSemStruct *pxParameter; + + #ifdef USE_STDIO + void vPrintDisplayMessage( const char * const * ppcMessageToSend ); + + const char * const pcTaskStartMsg = "Counting semaphore demo started.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + #endif + + /* The semaphore to be used was passed as the parameter. */ + pxParameter = ( xCountSemStruct * ) pvParameters; + + /* Did we expect to find the semaphore already at its max count value, or + at zero? */ + if( pxParameter->uxExpectedStartCount == countSTART_AT_MAX_COUNT ) + { + prvDecrementSemaphoreCount( pxParameter->xSemaphore, &( pxParameter->uxLoopCounter ) ); + } + + /* Now we expect the semaphore count to be 0, so this time there is an + error if we can take the semaphore. */ + if( xSemaphoreTake( pxParameter->xSemaphore, 0 ) == pdPASS ) + { + xErrorDetected = pdTRUE; + } + + for( ;; ) + { + prvIncrementSemaphoreCount( pxParameter->xSemaphore, &( pxParameter->uxLoopCounter ) ); + prvDecrementSemaphoreCount( pxParameter->xSemaphore, &( pxParameter->uxLoopCounter ) ); + } +} +/*-----------------------------------------------------------*/ + +BaseType_t xAreCountingSemaphoreTasksStillRunning( void ) +{ +static UBaseType_t uxLastCount0 = 0, uxLastCount1 = 0; +BaseType_t xReturn = pdPASS; + + /* Return fail if any 'give' or 'take' did not result in the expected + behaviour. */ + if( xErrorDetected != pdFALSE ) + { + xReturn = pdFAIL; + } + + /* Return fail if either task is not still incrementing its loop counter. */ + if( uxLastCount0 == xParameters[ 0 ].uxLoopCounter ) + { + xReturn = pdFAIL; + } + else + { + uxLastCount0 = xParameters[ 0 ].uxLoopCounter; + } + + if( uxLastCount1 == xParameters[ 1 ].uxLoopCounter ) + { + xReturn = pdFAIL; + } + else + { + uxLastCount1 = xParameters[ 1 ].uxLoopCounter; + } + + return xReturn; +} + + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/crflash.c b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/crflash.c new file mode 100644 index 0000000..4507f1c --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/crflash.c @@ -0,0 +1,246 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* + * This demo application file demonstrates the use of queues to pass data + * between co-routines. + * + * N represents the number of 'fixed delay' co-routines that are created and + * is set during initialisation. + * + * N 'fixed delay' co-routines are created that just block for a fixed + * period then post the number of an LED onto a queue. Each such co-routine + * uses a different block period. A single 'flash' co-routine is also created + * that blocks on the same queue, waiting for the number of the next LED it + * should flash. Upon receiving a number it simply toggle the instructed LED + * then blocks on the queue once more. In this manner each LED from LED 0 to + * LED N-1 is caused to flash at a different rate. + * + * The 'fixed delay' co-routines are created with co-routine priority 0. The + * flash co-routine is created with co-routine priority 1. This means that + * the queue should never contain more than a single item. This is because + * posting to the queue will unblock the 'flash' co-routine, and as this has + * a priority greater than the tasks posting to the queue it is guaranteed to + * have emptied the queue and blocked once again before the queue can contain + * any more date. An error is indicated if an attempt to post data to the + * queue fails - indicating that the queue is already full. + * + */ + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "croutine.h" +#include "queue.h" + +/* Demo application includes. */ +#include "partest.h" +#include "crflash.h" + +/* The queue should only need to be of length 1. See the description at the +top of the file. */ +#define crfQUEUE_LENGTH 1 + +#define crfFIXED_DELAY_PRIORITY 0 +#define crfFLASH_PRIORITY 1 + +/* Only one flash co-routine is created so the index is not significant. */ +#define crfFLASH_INDEX 0 + +/* Don't allow more than crfMAX_FLASH_TASKS 'fixed delay' co-routines to be +created. */ +#define crfMAX_FLASH_TASKS 8 + +/* We don't want to block when posting to the queue. */ +#define crfPOSTING_BLOCK_TIME 0 + +/* + * The 'fixed delay' co-routine as described at the top of the file. + */ +static void prvFixedDelayCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex ); + +/* + * The 'flash' co-routine as described at the top of the file. + */ +static void prvFlashCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex ); + +/* The queue used to pass data between the 'fixed delay' co-routines and the +'flash' co-routine. */ +static QueueHandle_t xFlashQueue; + +/* This will be set to pdFALSE if we detect an error. */ +static BaseType_t xCoRoutineFlashStatus = pdPASS; + +/*-----------------------------------------------------------*/ + +/* + * See the header file for details. + */ +void vStartFlashCoRoutines( UBaseType_t uxNumberToCreate ) +{ +UBaseType_t uxIndex; + + if( uxNumberToCreate > crfMAX_FLASH_TASKS ) + { + uxNumberToCreate = crfMAX_FLASH_TASKS; + } + + /* Create the queue used to pass data between the co-routines. */ + xFlashQueue = xQueueCreate( crfQUEUE_LENGTH, sizeof( UBaseType_t ) ); + + if( xFlashQueue ) + { + /* Create uxNumberToCreate 'fixed delay' co-routines. */ + for( uxIndex = 0; uxIndex < uxNumberToCreate; uxIndex++ ) + { + xCoRoutineCreate( prvFixedDelayCoRoutine, crfFIXED_DELAY_PRIORITY, uxIndex ); + } + + /* Create the 'flash' co-routine. */ + xCoRoutineCreate( prvFlashCoRoutine, crfFLASH_PRIORITY, crfFLASH_INDEX ); + } +} +/*-----------------------------------------------------------*/ + +static void prvFixedDelayCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex ) +{ +/* Even though this is a co-routine the xResult variable does not need to be +static as we do not need it to maintain its state between blocks. */ +BaseType_t xResult; +/* The uxIndex parameter of the co-routine function is used as an index into +the xFlashRates array to obtain the delay period to use. */ +static const TickType_t xFlashRates[ crfMAX_FLASH_TASKS ] = { 150 / portTICK_PERIOD_MS, + 200 / portTICK_PERIOD_MS, + 250 / portTICK_PERIOD_MS, + 300 / portTICK_PERIOD_MS, + 350 / portTICK_PERIOD_MS, + 400 / portTICK_PERIOD_MS, + 450 / portTICK_PERIOD_MS, + 500 / portTICK_PERIOD_MS }; + + /* Co-routines MUST start with a call to crSTART. */ + crSTART( xHandle ); + + for( ;; ) + { + /* Post our uxIndex value onto the queue. This is used as the LED to + flash. */ + crQUEUE_SEND( xHandle, xFlashQueue, ( void * ) &uxIndex, crfPOSTING_BLOCK_TIME, &xResult ); + + if( xResult != pdPASS ) + { + /* For the reasons stated at the top of the file we should always + find that we can post to the queue. If we could not then an error + has occurred. */ + xCoRoutineFlashStatus = pdFAIL; + } + + crDELAY( xHandle, xFlashRates[ uxIndex ] ); + } + + /* Co-routines MUST end with a call to crEND. */ + crEND(); +} +/*-----------------------------------------------------------*/ + +static void prvFlashCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex ) +{ +/* Even though this is a co-routine the variable do not need to be +static as we do not need it to maintain their state between blocks. */ +BaseType_t xResult; +UBaseType_t uxLEDToFlash; + + /* Co-routines MUST start with a call to crSTART. */ + crSTART( xHandle ); + ( void ) uxIndex; + + for( ;; ) + { + /* Block to wait for the number of the LED to flash. */ + crQUEUE_RECEIVE( xHandle, xFlashQueue, &uxLEDToFlash, portMAX_DELAY, &xResult ); + + if( xResult != pdPASS ) + { + /* We would not expect to wake unless we received something. */ + xCoRoutineFlashStatus = pdFAIL; + } + else + { + /* We received the number of an LED to flash - flash it! */ + vParTestToggleLED( uxLEDToFlash ); + } + } + + /* Co-routines MUST end with a call to crEND. */ + crEND(); +} +/*-----------------------------------------------------------*/ + +BaseType_t xAreFlashCoRoutinesStillRunning( void ) +{ + /* Return pdPASS or pdFAIL depending on whether an error has been detected + or not. */ + return xCoRoutineFlashStatus; +} + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/crhook.c b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/crhook.c new file mode 100644 index 0000000..1e3a18e --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/crhook.c @@ -0,0 +1,270 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* + * This demo file demonstrates how to send data between an ISR and a + * co-routine. A tick hook function is used to periodically pass data between + * the RTOS tick and a set of 'hook' co-routines. + * + * hookNUM_HOOK_CO_ROUTINES co-routines are created. Each co-routine blocks + * to wait for a character to be received on a queue from the tick ISR, checks + * to ensure the character received was that expected, then sends the number + * back to the tick ISR on a different queue. + * + * The tick ISR checks the numbers received back from the 'hook' co-routines + * matches the number previously sent. + * + * If at any time a queue function returns unexpectedly, or an incorrect value + * is received either by the tick hook or a co-routine then an error is + * latched. + * + * This demo relies on each 'hook' co-routine to execute between each + * hookTICK_CALLS_BEFORE_POST tick interrupts. This and the heavy use of + * queues from within an interrupt may result in an error being detected on + * slower targets simply due to timing. + */ + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "croutine.h" +#include "queue.h" + +/* Demo application includes. */ +#include "crhook.h" + +/* The number of 'hook' co-routines that are to be created. */ +#define hookNUM_HOOK_CO_ROUTINES ( 4 ) + +/* The number of times the tick hook should be called before a character is +posted to the 'hook' co-routines. */ +#define hookTICK_CALLS_BEFORE_POST ( 500 ) + +/* There should never be more than one item in any queue at any time. */ +#define hookHOOK_QUEUE_LENGTH ( 1 ) + +/* Don't block when initially posting to the queue. */ +#define hookNO_BLOCK_TIME ( 0 ) + +/* The priority relative to other co-routines (rather than tasks) that the +'hook' co-routines should take. */ +#define mainHOOK_CR_PRIORITY ( 1 ) +/*-----------------------------------------------------------*/ + +/* + * The co-routine function itself. + */ +static void prvHookCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex ); + + +/* + * The tick hook function. This receives a number from each 'hook' co-routine + * then sends a number to each co-routine. An error is flagged if a send or + * receive fails, or an unexpected number is received. + */ +void vApplicationTickHook( void ); + +/*-----------------------------------------------------------*/ + +/* Queues used to send data FROM a co-routine TO the tick hook function. +The hook functions received (Rx's) on these queues. One queue per +'hook' co-routine. */ +static QueueHandle_t xHookRxQueues[ hookNUM_HOOK_CO_ROUTINES ]; + +/* Queues used to send data FROM the tick hook TO a co-routine function. +The hood function transmits (Tx's) on these queues. One queue per +'hook' co-routine. */ +static QueueHandle_t xHookTxQueues[ hookNUM_HOOK_CO_ROUTINES ]; + +/* Set to true if an error is detected at any time. */ +static BaseType_t xCoRoutineErrorDetected = pdFALSE; + +/*-----------------------------------------------------------*/ + +void vStartHookCoRoutines( void ) +{ +UBaseType_t uxIndex, uxValueToPost = 0; + + for( uxIndex = 0; uxIndex < hookNUM_HOOK_CO_ROUTINES; uxIndex++ ) + { + /* Create a queue to transmit to and receive from each 'hook' + co-routine. */ + xHookRxQueues[ uxIndex ] = xQueueCreate( hookHOOK_QUEUE_LENGTH, sizeof( UBaseType_t ) ); + xHookTxQueues[ uxIndex ] = xQueueCreate( hookHOOK_QUEUE_LENGTH, sizeof( UBaseType_t ) ); + + /* To start things off the tick hook function expects the queue it + uses to receive data to contain a value. */ + xQueueSend( xHookRxQueues[ uxIndex ], &uxValueToPost, hookNO_BLOCK_TIME ); + + /* Create the 'hook' co-routine itself. */ + xCoRoutineCreate( prvHookCoRoutine, mainHOOK_CR_PRIORITY, uxIndex ); + } +} +/*-----------------------------------------------------------*/ + +static UBaseType_t uxCallCounter = 0, uxNumberToPost = 0; +void vApplicationTickHook( void ) +{ +UBaseType_t uxReceivedNumber; +BaseType_t xIndex, xCoRoutineWoken; + + /* Is it time to talk to the 'hook' co-routines again? */ + uxCallCounter++; + if( uxCallCounter >= hookTICK_CALLS_BEFORE_POST ) + { + uxCallCounter = 0; + + for( xIndex = 0; xIndex < hookNUM_HOOK_CO_ROUTINES; xIndex++ ) + { + xCoRoutineWoken = pdFALSE; + if( crQUEUE_RECEIVE_FROM_ISR( xHookRxQueues[ xIndex ], &uxReceivedNumber, &xCoRoutineWoken ) != pdPASS ) + { + /* There is no reason why we would not expect the queue to + contain a value. */ + xCoRoutineErrorDetected = pdTRUE; + } + else + { + /* Each queue used to receive data from the 'hook' co-routines + should contain the number we last posted to the same co-routine. */ + if( uxReceivedNumber != uxNumberToPost ) + { + xCoRoutineErrorDetected = pdTRUE; + } + + /* Nothing should be blocked waiting to post to the queue. */ + if( xCoRoutineWoken != pdFALSE ) + { + xCoRoutineErrorDetected = pdTRUE; + } + } + } + + /* Start the next cycle by posting the next number onto each Tx queue. */ + uxNumberToPost++; + + for( xIndex = 0; xIndex < hookNUM_HOOK_CO_ROUTINES; xIndex++ ) + { + if( crQUEUE_SEND_FROM_ISR( xHookTxQueues[ xIndex ], &uxNumberToPost, pdFALSE ) != pdTRUE ) + { + /* Posting to the queue should have woken the co-routine that + was blocked on the queue. */ + xCoRoutineErrorDetected = pdTRUE; + } + } + } +} +/*-----------------------------------------------------------*/ + +static void prvHookCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex ) +{ +static UBaseType_t uxReceivedValue[ hookNUM_HOOK_CO_ROUTINES ]; +BaseType_t xResult; + + /* Each co-routine MUST start with a call to crSTART(); */ + crSTART( xHandle ); + + for( ;; ) + { + /* Wait to receive a value from the tick hook. */ + xResult = pdFAIL; + crQUEUE_RECEIVE( xHandle, xHookTxQueues[ uxIndex ], &( uxReceivedValue[ uxIndex ] ), portMAX_DELAY, &xResult ); + + /* There is no reason why we should not have received something on + the queue. */ + if( xResult != pdPASS ) + { + xCoRoutineErrorDetected = pdTRUE; + } + + /* Send the same number back to the idle hook so it can verify it. */ + xResult = pdFAIL; + crQUEUE_SEND( xHandle, xHookRxQueues[ uxIndex ], &( uxReceivedValue[ uxIndex ] ), hookNO_BLOCK_TIME, &xResult ); + if( xResult != pdPASS ) + { + /* There is no reason why we should not have been able to post to + the queue. */ + xCoRoutineErrorDetected = pdTRUE; + } + } + + /* Each co-routine MUST end with a call to crEND(). */ + crEND(); +} +/*-----------------------------------------------------------*/ + +BaseType_t xAreHookCoRoutinesStillRunning( void ) +{ + if( xCoRoutineErrorDetected ) + { + return pdFALSE; + } + else + { + return pdTRUE; + } +} + + + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/death.c b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/death.c new file mode 100644 index 0000000..d567971 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/death.c @@ -0,0 +1,254 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/** + * Create a single persistent task which periodically dynamically creates another + * two tasks. The original task is called the creator task, the two tasks it + * creates are called suicidal tasks. + * + * One of the created suicidal tasks kill one other suicidal task before killing + * itself - leaving just the original task remaining. + * + * The creator task must be spawned after all of the other demo application tasks + * as it keeps a check on the number of tasks under the scheduler control. The + * number of tasks it expects to see running should never be greater than the + * number of tasks that were in existence when the creator task was spawned, plus + * one set of four suicidal tasks. If this number is exceeded an error is flagged. + * + * \page DeathC death.c + * \ingroup DemoFiles + *
+ */ + + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Demo program include files. */ +#include "death.h" + +#define deathSTACK_SIZE ( configMINIMAL_STACK_SIZE + 60 ) + +/* The task originally created which is responsible for periodically dynamically +creating another four tasks. */ +static portTASK_FUNCTION_PROTO( vCreateTasks, pvParameters ); + +/* The task function of the dynamically created tasks. */ +static portTASK_FUNCTION_PROTO( vSuicidalTask, pvParameters ); + +/* A variable which is incremented every time the dynamic tasks are created. This +is used to check that the task is still running. */ +static volatile uint16_t usCreationCount = 0; + +/* Used to store the number of tasks that were originally running so the creator +task can tell if any of the suicidal tasks have failed to die. +*/ +static volatile UBaseType_t uxTasksRunningAtStart = 0; + +/* Tasks are deleted by the idle task. Under heavy load the idle task might +not get much processing time, so it would be legitimate for several tasks to +remain undeleted for a short period. */ +static const UBaseType_t uxMaxNumberOfExtraTasksRunning = 3; + +/* Used to store a handle to the task that should be killed by a suicidal task, +before it kills itself. */ +TaskHandle_t xCreatedTask; + +/*-----------------------------------------------------------*/ + +void vCreateSuicidalTasks( UBaseType_t uxPriority ) +{ +UBaseType_t *puxPriority; + + /* Create the Creator tasks - passing in as a parameter the priority at which + the suicidal tasks should be created. */ + puxPriority = ( UBaseType_t * ) pvPortMalloc( sizeof( UBaseType_t ) ); + *puxPriority = uxPriority; + + xTaskCreate( vCreateTasks, "CREATOR", deathSTACK_SIZE, ( void * ) puxPriority, uxPriority, NULL ); + + /* Record the number of tasks that are running now so we know if any of the + suicidal tasks have failed to be killed. */ + uxTasksRunningAtStart = ( UBaseType_t ) uxTaskGetNumberOfTasks(); + + /* FreeRTOS.org versions before V3.0 started the idle-task as the very + first task. The idle task was then already included in uxTasksRunningAtStart. + From FreeRTOS V3.0 on, the idle task is started when the scheduler is + started. Therefore the idle task is not yet accounted for. We correct + this by increasing uxTasksRunningAtStart by 1. */ + uxTasksRunningAtStart++; + + /* From FreeRTOS version 7.0.0 can optionally create a timer service task. + If this is done, then uxTasksRunningAtStart needs incrementing again as that + too is created when the scheduler is started. */ + #if configUSE_TIMERS == 1 + uxTasksRunningAtStart++; + #endif +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vSuicidalTask, pvParameters ) +{ +volatile long l1, l2; +TaskHandle_t xTaskToKill; +const TickType_t xDelay = ( TickType_t ) 200 / portTICK_PERIOD_MS; + + if( pvParameters != NULL ) + { + /* This task is periodically created four times. Two created tasks are + passed a handle to the other task so it can kill it before killing itself. + The other task is passed in null. */ + xTaskToKill = *( TaskHandle_t* )pvParameters; + } + else + { + xTaskToKill = NULL; + } + + for( ;; ) + { + /* Do something random just to use some stack and registers. */ + l1 = 2; + l2 = 89; + l2 *= l1; + vTaskDelay( xDelay ); + + if( xTaskToKill != NULL ) + { + /* Make sure the other task has a go before we delete it. */ + vTaskDelay( ( TickType_t ) 0 ); + + /* Kill the other task that was created by vCreateTasks(). */ + vTaskDelete( xTaskToKill ); + + /* Kill ourselves. */ + vTaskDelete( NULL ); + } + } +}/*lint !e818 !e550 Function prototype must be as per standard for task functions. */ +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vCreateTasks, pvParameters ) +{ +const TickType_t xDelay = ( TickType_t ) 1000 / portTICK_PERIOD_MS; +UBaseType_t uxPriority; + + uxPriority = *( UBaseType_t * ) pvParameters; + vPortFree( pvParameters ); + + for( ;; ) + { + /* Just loop round, delaying then creating the four suicidal tasks. */ + vTaskDelay( xDelay ); + + xCreatedTask = NULL; + + xTaskCreate( vSuicidalTask, "SUICID1", configMINIMAL_STACK_SIZE, NULL, uxPriority, &xCreatedTask ); + xTaskCreate( vSuicidalTask, "SUICID2", configMINIMAL_STACK_SIZE, &xCreatedTask, uxPriority, NULL ); + + ++usCreationCount; + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that the creator task is still running and that there +are not any more than four extra tasks. */ +BaseType_t xIsCreateTaskStillRunning( void ) +{ +static uint16_t usLastCreationCount = 0xfff; +BaseType_t xReturn = pdTRUE; +static UBaseType_t uxTasksRunningNow; + + if( usLastCreationCount == usCreationCount ) + { + xReturn = pdFALSE; + } + else + { + usLastCreationCount = usCreationCount; + } + + uxTasksRunningNow = ( UBaseType_t ) uxTaskGetNumberOfTasks(); + + if( uxTasksRunningNow < uxTasksRunningAtStart ) + { + xReturn = pdFALSE; + } + else if( ( uxTasksRunningNow - uxTasksRunningAtStart ) > uxMaxNumberOfExtraTasksRunning ) + { + xReturn = pdFALSE; + } + else + { + /* Everything is okay. */ + } + + return xReturn; +} + + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/dynamic.c b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/dynamic.c new file mode 100644 index 0000000..29ef3ef --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/dynamic.c @@ -0,0 +1,511 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* + * The first test creates three tasks - two counter tasks (one continuous count + * and one limited count) and one controller. A "count" variable is shared + * between all three tasks. The two counter tasks should never be in a "ready" + * state at the same time. The controller task runs at the same priority as + * the continuous count task, and at a lower priority than the limited count + * task. + * + * One counter task loops indefinitely, incrementing the shared count variable + * on each iteration. To ensure it has exclusive access to the variable it + * raises its priority above that of the controller task before each + * increment, lowering it again to its original priority before starting the + * next iteration. + * + * The other counter task increments the shared count variable on each + * iteration of its loop until the count has reached a limit of 0xff - at + * which point it suspends itself. It will not start a new loop until the + * controller task has made it "ready" again by calling vTaskResume(). + * This second counter task operates at a higher priority than controller + * task so does not need to worry about mutual exclusion of the counter + * variable. + * + * The controller task is in two sections. The first section controls and + * monitors the continuous count task. When this section is operational the + * limited count task is suspended. Likewise, the second section controls + * and monitors the limited count task. When this section is operational the + * continuous count task is suspended. + * + * In the first section the controller task first takes a copy of the shared + * count variable. To ensure mutual exclusion on the count variable it + * suspends the continuous count task, resuming it again when the copy has been + * taken. The controller task then sleeps for a fixed period - during which + * the continuous count task will execute and increment the shared variable. + * When the controller task wakes it checks that the continuous count task + * has executed by comparing the copy of the shared variable with its current + * value. This time, to ensure mutual exclusion, the scheduler itself is + * suspended with a call to vTaskSuspendAll (). This is for demonstration + * purposes only and is not a recommended technique due to its inefficiency. + * + * After a fixed number of iterations the controller task suspends the + * continuous count task, and moves on to its second section. + * + * At the start of the second section the shared variable is cleared to zero. + * The limited count task is then woken from its suspension by a call to + * vTaskResume (). As this counter task operates at a higher priority than + * the controller task the controller task should not run again until the + * shared variable has been counted up to the limited value causing the counter + * task to suspend itself. The next line after vTaskResume () is therefore + * a check on the shared variable to ensure everything is as expected. + * + * + * The second test consists of a couple of very simple tasks that post onto a + * queue while the scheduler is suspended. This test was added to test parts + * of the scheduler not exercised by the first test. + * + */ + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "semphr.h" + +/* Demo app include files. */ +#include "dynamic.h" + +/* Function that implements the "limited count" task as described above. */ +static portTASK_FUNCTION_PROTO( vLimitedIncrementTask, pvParameters ); + +/* Function that implements the "continuous count" task as described above. */ +static portTASK_FUNCTION_PROTO( vContinuousIncrementTask, pvParameters ); + +/* Function that implements the controller task as described above. */ +static portTASK_FUNCTION_PROTO( vCounterControlTask, pvParameters ); + +static portTASK_FUNCTION_PROTO( vQueueReceiveWhenSuspendedTask, pvParameters ); +static portTASK_FUNCTION_PROTO( vQueueSendWhenSuspendedTask, pvParameters ); + +/* Demo task specific constants. */ +#define priSTACK_SIZE ( configMINIMAL_STACK_SIZE ) +#define priSLEEP_TIME ( ( TickType_t ) 128 / portTICK_PERIOD_MS ) +#define priLOOPS ( 5 ) +#define priMAX_COUNT ( ( uint32_t ) 0xff ) +#define priNO_BLOCK ( ( TickType_t ) 0 ) +#define priSUSPENDED_QUEUE_LENGTH ( 1 ) + +/*-----------------------------------------------------------*/ + +/* Handles to the two counter tasks. These could be passed in as parameters +to the controller task to prevent them having to be file scope. */ +static TaskHandle_t xContinuousIncrementHandle, xLimitedIncrementHandle; + +/* The shared counter variable. This is passed in as a parameter to the two +counter variables for demonstration purposes. */ +static volatile uint32_t ulCounter; + +/* Variables used to check that the tasks are still operating without error. +Each complete iteration of the controller task increments this variable +provided no errors have been found. The variable maintaining the same value +is therefore indication of an error. */ +static volatile uint16_t usCheckVariable = ( uint16_t ) 0; +static volatile BaseType_t xSuspendedQueueSendError = pdFALSE; +static volatile BaseType_t xSuspendedQueueReceiveError = pdFALSE; + +/* Queue used by the second test. */ +QueueHandle_t xSuspendedTestQueue; + +/* The value the queue receive task expects to receive next. This is file +scope so xAreDynamicPriorityTasksStillRunning() can ensure it is still +incrementing. */ +static uint32_t ulExpectedValue = ( uint32_t ) 0; + +/*-----------------------------------------------------------*/ +/* + * Start the three tasks as described at the top of the file. + * Note that the limited count task is given a higher priority. + */ +void vStartDynamicPriorityTasks( void ) +{ + xSuspendedTestQueue = xQueueCreate( priSUSPENDED_QUEUE_LENGTH, sizeof( uint32_t ) ); + + /* vQueueAddToRegistry() adds the queue to the queue registry, if one is + in use. The queue registry is provided as a means for kernel aware + debuggers to locate queues and has no purpose if a kernel aware debugger + is not being used. The call to vQueueAddToRegistry() will be removed + by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is + defined to be less than 1. */ + vQueueAddToRegistry( xSuspendedTestQueue, "Suspended_Test_Queue" ); + + xTaskCreate( vContinuousIncrementTask, "CNT_INC", priSTACK_SIZE, ( void * ) &ulCounter, tskIDLE_PRIORITY, &xContinuousIncrementHandle ); + xTaskCreate( vLimitedIncrementTask, "LIM_INC", priSTACK_SIZE, ( void * ) &ulCounter, tskIDLE_PRIORITY + 1, &xLimitedIncrementHandle ); + xTaskCreate( vCounterControlTask, "C_CTRL", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); + xTaskCreate( vQueueSendWhenSuspendedTask, "SUSP_TX", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); + xTaskCreate( vQueueReceiveWhenSuspendedTask, "SUSP_RX", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); +} +/*-----------------------------------------------------------*/ + +/* + * Just loops around incrementing the shared variable until the limit has been + * reached. Once the limit has been reached it suspends itself. + */ +static portTASK_FUNCTION( vLimitedIncrementTask, pvParameters ) +{ +uint32_t *pulCounter; + + /* Take a pointer to the shared variable from the parameters passed into + the task. */ + pulCounter = ( uint32_t * ) pvParameters; + + /* This will run before the control task, so the first thing it does is + suspend - the control task will resume it when ready. */ + vTaskSuspend( NULL ); + + for( ;; ) + { + /* Just count up to a value then suspend. */ + ( *pulCounter )++; + + if( *pulCounter >= priMAX_COUNT ) + { + vTaskSuspend( NULL ); + } + } +} +/*-----------------------------------------------------------*/ + +/* + * Just keep counting the shared variable up. The control task will suspend + * this task when it wants. + */ +static portTASK_FUNCTION( vContinuousIncrementTask, pvParameters ) +{ +volatile uint32_t *pulCounter; +UBaseType_t uxOurPriority; + + /* Take a pointer to the shared variable from the parameters passed into + the task. */ + pulCounter = ( uint32_t * ) pvParameters; + + /* Query our priority so we can raise it when exclusive access to the + shared variable is required. */ + uxOurPriority = uxTaskPriorityGet( NULL ); + + for( ;; ) + { + /* Raise the priority above the controller task to ensure a context + switch does not occur while the variable is being accessed. */ + vTaskPrioritySet( NULL, uxOurPriority + 1 ); + { + configASSERT( ( uxTaskPriorityGet( NULL ) == ( uxOurPriority + 1 ) ) ); + ( *pulCounter )++; + } + vTaskPrioritySet( NULL, uxOurPriority ); + + #if( configUSE_PREEMPTION == 0 ) + taskYIELD(); + #endif + + configASSERT( ( uxTaskPriorityGet( NULL ) == uxOurPriority ) ); + } +} +/*-----------------------------------------------------------*/ + +/* + * Controller task as described above. + */ +static portTASK_FUNCTION( vCounterControlTask, pvParameters ) +{ +uint32_t ulLastCounter; +short sLoops; +short sError = pdFALSE; + + /* Just to stop warning messages. */ + ( void ) pvParameters; + + for( ;; ) + { + /* Start with the counter at zero. */ + ulCounter = ( uint32_t ) 0; + + /* First section : */ + + /* Check the continuous count task is running. */ + for( sLoops = 0; sLoops < priLOOPS; sLoops++ ) + { + /* Suspend the continuous count task so we can take a mirror of the + shared variable without risk of corruption. This is not really + needed as the other task raises its priority above this task's + priority. */ + vTaskSuspend( xContinuousIncrementHandle ); + { + #if( INCLUDE_eTaskGetState == 1 ) + { + configASSERT( eTaskGetState( xContinuousIncrementHandle ) == eSuspended ); + } + #endif /* INCLUDE_eTaskGetState */ + + ulLastCounter = ulCounter; + } + vTaskResume( xContinuousIncrementHandle ); + + #if( configUSE_PREEMPTION == 0 ) + taskYIELD(); + #endif + + #if( INCLUDE_eTaskGetState == 1 ) + { + configASSERT( eTaskGetState( xContinuousIncrementHandle ) == eReady ); + } + #endif /* INCLUDE_eTaskGetState */ + + /* Now delay to ensure the other task has processor time. */ + vTaskDelay( priSLEEP_TIME ); + + /* Check the shared variable again. This time to ensure mutual + exclusion the whole scheduler will be locked. This is just for + demo purposes! */ + vTaskSuspendAll(); + { + if( ulLastCounter == ulCounter ) + { + /* The shared variable has not changed. There is a problem + with the continuous count task so flag an error. */ + sError = pdTRUE; + } + } + xTaskResumeAll(); + } + + /* Second section: */ + + /* Suspend the continuous counter task so it stops accessing the shared + variable. */ + vTaskSuspend( xContinuousIncrementHandle ); + + /* Reset the variable. */ + ulCounter = ( uint32_t ) 0; + + #if( INCLUDE_eTaskGetState == 1 ) + { + configASSERT( eTaskGetState( xLimitedIncrementHandle ) == eSuspended ); + } + #endif /* INCLUDE_eTaskGetState */ + + /* Resume the limited count task which has a higher priority than us. + We should therefore not return from this call until the limited count + task has suspended itself with a known value in the counter variable. */ + vTaskResume( xLimitedIncrementHandle ); + + #if( configUSE_PREEMPTION == 0 ) + taskYIELD(); + #endif + + /* This task should not run again until xLimitedIncrementHandle has + suspended itself. */ + #if( INCLUDE_eTaskGetState == 1 ) + { + configASSERT( eTaskGetState( xLimitedIncrementHandle ) == eSuspended ); + } + #endif /* INCLUDE_eTaskGetState */ + + /* Does the counter variable have the expected value? */ + if( ulCounter != priMAX_COUNT ) + { + sError = pdTRUE; + } + + if( sError == pdFALSE ) + { + /* If no errors have occurred then increment the check variable. */ + portENTER_CRITICAL(); + usCheckVariable++; + portEXIT_CRITICAL(); + } + + /* Resume the continuous count task and do it all again. */ + vTaskResume( xContinuousIncrementHandle ); + + #if( configUSE_PREEMPTION == 0 ) + taskYIELD(); + #endif + } +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vQueueSendWhenSuspendedTask, pvParameters ) +{ +static uint32_t ulValueToSend = ( uint32_t ) 0; + + /* Just to stop warning messages. */ + ( void ) pvParameters; + + for( ;; ) + { + vTaskSuspendAll(); + { + /* We must not block while the scheduler is suspended! */ + if( xQueueSend( xSuspendedTestQueue, ( void * ) &ulValueToSend, priNO_BLOCK ) != pdTRUE ) + { + xSuspendedQueueSendError = pdTRUE; + } + } + xTaskResumeAll(); + + vTaskDelay( priSLEEP_TIME ); + + ++ulValueToSend; + } +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vQueueReceiveWhenSuspendedTask, pvParameters ) +{ +uint32_t ulReceivedValue; +BaseType_t xGotValue; + + /* Just to stop warning messages. */ + ( void ) pvParameters; + + for( ;; ) + { + do + { + /* Suspending the scheduler here is fairly pointless and + undesirable for a normal application. It is done here purely + to test the scheduler. The inner xTaskResumeAll() should + never return pdTRUE as the scheduler is still locked by the + outer call. */ + vTaskSuspendAll(); + { + vTaskSuspendAll(); + { + xGotValue = xQueueReceive( xSuspendedTestQueue, ( void * ) &ulReceivedValue, priNO_BLOCK ); + } + if( xTaskResumeAll() != pdFALSE ) + { + xSuspendedQueueReceiveError = pdTRUE; + } + } + xTaskResumeAll(); + + #if configUSE_PREEMPTION == 0 + { + taskYIELD(); + } + #endif + + } while( xGotValue == pdFALSE ); + + if( ulReceivedValue != ulExpectedValue ) + { + xSuspendedQueueReceiveError = pdTRUE; + } + + if( xSuspendedQueueReceiveError != pdTRUE ) + { + /* Only increment the variable if an error has not occurred. This + allows xAreDynamicPriorityTasksStillRunning() to check for stalled + tasks as well as explicit errors. */ + ++ulExpectedValue; + } + } +} +/*-----------------------------------------------------------*/ + +/* Called to check that all the created tasks are still running without error. */ +BaseType_t xAreDynamicPriorityTasksStillRunning( void ) +{ +/* Keep a history of the check variables so we know if it has been incremented +since the last call. */ +static uint16_t usLastTaskCheck = ( uint16_t ) 0; +static uint32_t ulLastExpectedValue = ( uint32_t ) 0U; +BaseType_t xReturn = pdTRUE; + + /* Check the tasks are still running by ensuring the check variable + is still incrementing. */ + + if( usCheckVariable == usLastTaskCheck ) + { + /* The check has not incremented so an error exists. */ + xReturn = pdFALSE; + } + + if( ulExpectedValue == ulLastExpectedValue ) + { + /* The value being received by the queue receive task has not + incremented so an error exists. */ + xReturn = pdFALSE; + } + + if( xSuspendedQueueSendError == pdTRUE ) + { + xReturn = pdFALSE; + } + + if( xSuspendedQueueReceiveError == pdTRUE ) + { + xReturn = pdFALSE; + } + + usLastTaskCheck = usCheckVariable; + ulLastExpectedValue = ulExpectedValue; + + return xReturn; +} diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/flash.c b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/flash.c new file mode 100644 index 0000000..8689707 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/flash.c @@ -0,0 +1,157 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/** + * This version of flash .c is for use on systems that have limited stack space + * and no display facilities. The complete version can be found in the + * Demo/Common/Full directory. + * + * Three tasks are created, each of which flash an LED at a different rate. The first + * LED flashes every 200ms, the second every 400ms, the third every 600ms. + * + * The LED flash tasks provide instant visual feedback. They show that the scheduler + * is still operational. + * + */ + + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Demo program include files. */ +#include "partest.h" +#include "flash.h" + +#define ledSTACK_SIZE configMINIMAL_STACK_SIZE +#define ledNUMBER_OF_LEDS ( 3 ) +#define ledFLASH_RATE_BASE ( ( TickType_t ) 333 ) + +/* Variable used by the created tasks to calculate the LED number to use, and +the rate at which they should flash the LED. */ +static volatile UBaseType_t uxFlashTaskNumber = 0; + +/* The task that is created three times. */ +static portTASK_FUNCTION_PROTO( vLEDFlashTask, pvParameters ); + +/*-----------------------------------------------------------*/ + +void vStartLEDFlashTasks( UBaseType_t uxPriority ) +{ +BaseType_t xLEDTask; + + /* Create the three tasks. */ + for( xLEDTask = 0; xLEDTask < ledNUMBER_OF_LEDS; ++xLEDTask ) + { + /* Spawn the task. */ + xTaskCreate( vLEDFlashTask, "LEDx", ledSTACK_SIZE, NULL, uxPriority, ( TaskHandle_t * ) NULL ); + } +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vLEDFlashTask, pvParameters ) +{ +TickType_t xFlashRate, xLastFlashTime; +UBaseType_t uxLED; + + /* The parameters are not used. */ + ( void ) pvParameters; + + /* Calculate the LED and flash rate. */ + portENTER_CRITICAL(); + { + /* See which of the eight LED's we should use. */ + uxLED = uxFlashTaskNumber; + + /* Update so the next task uses the next LED. */ + uxFlashTaskNumber++; + } + portEXIT_CRITICAL(); + + xFlashRate = ledFLASH_RATE_BASE + ( ledFLASH_RATE_BASE * ( TickType_t ) uxLED ); + xFlashRate /= portTICK_PERIOD_MS; + + /* We will turn the LED on and off again in the delay period, so each + delay is only half the total period. */ + xFlashRate /= ( TickType_t ) 2; + + /* We need to initialise xLastFlashTime prior to the first call to + vTaskDelayUntil(). */ + xLastFlashTime = xTaskGetTickCount(); + + for(;;) + { + /* Delay for half the flash period then turn the LED on. */ + vTaskDelayUntil( &xLastFlashTime, xFlashRate ); + vParTestToggleLED( uxLED ); + + /* Delay for half the flash period then turn the LED off. */ + vTaskDelayUntil( &xLastFlashTime, xFlashRate ); + vParTestToggleLED( uxLED ); + } +} /*lint !e715 !e818 !e830 Function definition must be standard for task creation. */ + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/flash_timer.c b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/flash_timer.c new file mode 100644 index 0000000..b54a866 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/flash_timer.c @@ -0,0 +1,136 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/** + * Repeatedly toggles one or more LEDs using software timers - one timer per + * LED. + */ + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "timers.h" + +/* Demo program include files. */ +#include "partest.h" +#include "flash_timer.h" + +/* The toggle rates are all a multple of ledFLASH_RATE_BASE. */ +#define ledFLASH_RATE_BASE ( ( ( TickType_t ) 333 ) / portTICK_PERIOD_MS ) + +/* A block time of zero simple means "don't block". */ +#define ledDONT_BLOCK ( ( TickType_t ) 0 ) + +/*-----------------------------------------------------------*/ + +/* + * The callback function used by each LED flashing timer. All the timers use + * this function, and the timer ID is used within the function to determine + * which timer has actually expired. + */ +static void prvLEDTimerCallback( TimerHandle_t xTimer ); + +/*-----------------------------------------------------------*/ + +void vStartLEDFlashTimers( UBaseType_t uxNumberOfLEDs ) +{ +UBaseType_t uxLEDTimer; +TimerHandle_t xTimer; + + /* Create and start the requested number of timers. */ + for( uxLEDTimer = 0; uxLEDTimer < uxNumberOfLEDs; ++uxLEDTimer ) + { + /* Create the timer. */ + xTimer = xTimerCreate( "Flasher", /* A text name, purely to help debugging. */ + ledFLASH_RATE_BASE * ( uxLEDTimer + 1 ),/* The timer period, which is a multiple of ledFLASH_RATE_BASE. */ + pdTRUE, /* This is an auto-reload timer, so xAutoReload is set to pdTRUE. */ + ( void * ) uxLEDTimer, /* The ID is used to identify the timer within the timer callback function, as each timer uses the same callback. */ + prvLEDTimerCallback /* Each timer uses the same callback. */ + ); + + /* If the timer was created successfully, attempt to start it. If the + scheduler has not yet been started then the timer command queue must + be long enough to hold each command sent to it until such time that the + scheduler is started. The timer command queue length is set by + configTIMER_QUEUE_LENGTH in FreeRTOSConfig.h. */ + if( xTimer != NULL ) + { + xTimerStart( xTimer, ledDONT_BLOCK ); + } + } +} +/*-----------------------------------------------------------*/ + +static void prvLEDTimerCallback( TimerHandle_t xTimer ) +{ +BaseType_t xTimerID; + + /* The timer ID is used to identify the timer that has actually expired as + each timer uses the same callback. The ID is then also used as the number + of the LED that is to be toggled. */ + xTimerID = ( BaseType_t ) pvTimerGetTimerID( xTimer ); + vParTestToggleLED( xTimerID ); +} + + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/flop.c b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/flop.c new file mode 100644 index 0000000..438cf02 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/flop.c @@ -0,0 +1,383 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* + * Creates eight tasks, each of which loops continuously performing a floating + * point calculation. + * + * All the tasks run at the idle priority and never block or yield. This causes + * all eight tasks to time slice with the idle task. Running at the idle + * priority means that these tasks will get pre-empted any time another task is + * ready to run or a time slice occurs. More often than not the pre-emption + * will occur mid calculation, creating a good test of the schedulers context + * switch mechanism - a calculation producing an unexpected result could be a + * symptom of a corruption in the context of a task. + */ + +#include +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Demo program include files. */ +#include "flop.h" + +#define mathSTACK_SIZE configMINIMAL_STACK_SIZE +#define mathNUMBER_OF_TASKS ( 4 ) + +/* Four tasks, each of which performs a different floating point calculation. +Each of the four is created twice. */ +static portTASK_FUNCTION_PROTO( vCompetingMathTask1, pvParameters ); +static portTASK_FUNCTION_PROTO( vCompetingMathTask2, pvParameters ); +static portTASK_FUNCTION_PROTO( vCompetingMathTask3, pvParameters ); +static portTASK_FUNCTION_PROTO( vCompetingMathTask4, pvParameters ); + +/* These variables are used to check that all the tasks are still running. If a +task gets a calculation wrong it will stop setting its check variable. */ +static volatile uint16_t usTaskCheck[ mathNUMBER_OF_TASKS ] = { ( uint16_t ) 0 }; + +/*-----------------------------------------------------------*/ + +void vStartMathTasks( UBaseType_t uxPriority ) +{ + xTaskCreate( vCompetingMathTask1, "Math1", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 0 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask2, "Math2", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 1 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask3, "Math3", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 2 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask4, "Math4", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 3 ] ), uxPriority, NULL ); +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vCompetingMathTask1, pvParameters ) +{ +volatile portDOUBLE d1, d2, d3, d4; +volatile uint16_t *pusTaskCheckVariable; +volatile portDOUBLE dAnswer; +short sError = pdFALSE; + + /* Some ports require that tasks that use a hardware floating point unit + tell the kernel that they require a floating point context before any + floating point instructions are executed. */ + portTASK_USES_FLOATING_POINT(); + + d1 = 123.4567; + d2 = 2345.6789; + d3 = -918.222; + + dAnswer = ( d1 + d2 ) * d3; + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( uint16_t * ) pvParameters; + + /* Keep performing a calculation and checking the result against a constant. */ + for(;;) + { + d1 = 123.4567; + d2 = 2345.6789; + d3 = -918.222; + + d4 = ( d1 + d2 ) * d3; + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* If the calculation does not match the expected constant, stop the + increment of the check variable. */ + if( fabs( d4 - dAnswer ) > 0.001 ) + { + sError = pdTRUE; + } + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct then set set the check + variable. The check variable will get set to pdFALSE each time + xAreMathsTaskStillRunning() is executed. */ + ( *pusTaskCheckVariable ) = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + } +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vCompetingMathTask2, pvParameters ) +{ +volatile portDOUBLE d1, d2, d3, d4; +volatile uint16_t *pusTaskCheckVariable; +volatile portDOUBLE dAnswer; +short sError = pdFALSE; + + /* Some ports require that tasks that use a hardware floating point unit + tell the kernel that they require a floating point context before any + floating point instructions are executed. */ + portTASK_USES_FLOATING_POINT(); + + d1 = -389.38; + d2 = 32498.2; + d3 = -2.0001; + + dAnswer = ( d1 / d2 ) * d3; + + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( uint16_t * ) pvParameters; + + /* Keep performing a calculation and checking the result against a constant. */ + for( ;; ) + { + d1 = -389.38; + d2 = 32498.2; + d3 = -2.0001; + + d4 = ( d1 / d2 ) * d3; + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* If the calculation does not match the expected constant, stop the + increment of the check variable. */ + if( fabs( d4 - dAnswer ) > 0.001 ) + { + sError = pdTRUE; + } + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct then set set the check + variable. The check variable will get set to pdFALSE each time + xAreMathsTaskStillRunning() is executed. */ + ( *pusTaskCheckVariable ) = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + } +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vCompetingMathTask3, pvParameters ) +{ +volatile portDOUBLE *pdArray, dTotal1, dTotal2, dDifference; +volatile uint16_t *pusTaskCheckVariable; +const size_t xArraySize = 10; +size_t xPosition; +short sError = pdFALSE; + + /* Some ports require that tasks that use a hardware floating point unit + tell the kernel that they require a floating point context before any + floating point instructions are executed. */ + portTASK_USES_FLOATING_POINT(); + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( uint16_t * ) pvParameters; + + pdArray = ( portDOUBLE * ) pvPortMalloc( xArraySize * sizeof( portDOUBLE ) ); + + /* Keep filling an array, keeping a running total of the values placed in the + array. Then run through the array adding up all the values. If the two totals + do not match, stop the check variable from incrementing. */ + for( ;; ) + { + dTotal1 = 0.0; + dTotal2 = 0.0; + + for( xPosition = 0; xPosition < xArraySize; xPosition++ ) + { + pdArray[ xPosition ] = ( portDOUBLE ) xPosition + 5.5; + dTotal1 += ( portDOUBLE ) xPosition + 5.5; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + for( xPosition = 0; xPosition < xArraySize; xPosition++ ) + { + dTotal2 += pdArray[ xPosition ]; + } + + dDifference = dTotal1 - dTotal2; + if( fabs( dDifference ) > 0.001 ) + { + sError = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct then set set the check + variable. The check variable will get set to pdFALSE each time + xAreMathsTaskStillRunning() is executed. */ + ( *pusTaskCheckVariable ) = pdTRUE; + } + } +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vCompetingMathTask4, pvParameters ) +{ +volatile portDOUBLE *pdArray, dTotal1, dTotal2, dDifference; +volatile uint16_t *pusTaskCheckVariable; +const size_t xArraySize = 10; +size_t xPosition; +short sError = pdFALSE; + + /* Some ports require that tasks that use a hardware floating point unit + tell the kernel that they require a floating point context before any + floating point instructions are executed. */ + portTASK_USES_FLOATING_POINT(); + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( uint16_t * ) pvParameters; + + pdArray = ( portDOUBLE * ) pvPortMalloc( xArraySize * sizeof( portDOUBLE ) ); + + /* Keep filling an array, keeping a running total of the values placed in the + array. Then run through the array adding up all the values. If the two totals + do not match, stop the check variable from incrementing. */ + for( ;; ) + { + dTotal1 = 0.0; + dTotal2 = 0.0; + + for( xPosition = 0; xPosition < xArraySize; xPosition++ ) + { + pdArray[ xPosition ] = ( portDOUBLE ) xPosition * 12.123; + dTotal1 += ( portDOUBLE ) xPosition * 12.123; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + for( xPosition = 0; xPosition < xArraySize; xPosition++ ) + { + dTotal2 += pdArray[ xPosition ]; + } + + dDifference = dTotal1 - dTotal2; + if( fabs( dDifference ) > 0.001 ) + { + sError = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct then set set the check + variable. The check variable will get set to pdFALSE each time + xAreMathsTaskStillRunning() is executed. */ + ( *pusTaskCheckVariable ) = pdTRUE; + } + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +BaseType_t xAreMathsTaskStillRunning( void ) +{ +BaseType_t xReturn = pdPASS, xTask; + + /* Check the maths tasks are still running by ensuring their check variables + have been set to pdPASS. */ + for( xTask = 0; xTask < mathNUMBER_OF_TASKS; xTask++ ) + { + if( usTaskCheck[ xTask ] != pdTRUE ) + { + /* The check has not been set so the associated task has either + stalled or detected an error. */ + xReturn = pdFAIL; + } + else + { + /* Reset the variable so it can be checked again the next time this + function is executed. */ + usTaskCheck[ xTask ] = pdFALSE; + } + } + + return xReturn; +} + + + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/integer.c b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/integer.c new file mode 100644 index 0000000..a276613 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/integer.c @@ -0,0 +1,201 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* + * Creates one or more tasks that repeatedly perform a set of integer + * calculations. The result of each run-time calculation is compared to the + * known expected result - with a mismatch being indicative of an error in the + * context switch mechanism. + */ + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Demo program include files. */ +#include "integer.h" + +/* The constants used in the calculation. */ +#define intgCONST1 ( ( long ) 123 ) +#define intgCONST2 ( ( long ) 234567 ) +#define intgCONST3 ( ( long ) -3 ) +#define intgCONST4 ( ( long ) 7 ) +#define intgEXPECTED_ANSWER ( ( ( intgCONST1 + intgCONST2 ) * intgCONST3 ) / intgCONST4 ) + +#define intgSTACK_SIZE configMINIMAL_STACK_SIZE + +/* As this is the minimal version, we will only create one task. */ +#define intgNUMBER_OF_TASKS ( 1 ) + +/* The task function. Repeatedly performs a 32 bit calculation, checking the +result against the expected result. If the result is incorrect then the +context switch must have caused some corruption. */ +static portTASK_FUNCTION_PROTO( vCompeteingIntMathTask, pvParameters ); + +/* Variables that are set to true within the calculation task to indicate +that the task is still executing. The check task sets the variable back to +false, flagging an error if the variable is still false the next time it +is called. */ +static volatile BaseType_t xTaskCheck[ intgNUMBER_OF_TASKS ] = { ( BaseType_t ) pdFALSE }; + +/*-----------------------------------------------------------*/ + +void vStartIntegerMathTasks( UBaseType_t uxPriority ) +{ +short sTask; + + for( sTask = 0; sTask < intgNUMBER_OF_TASKS; sTask++ ) + { + xTaskCreate( vCompeteingIntMathTask, "IntMath", intgSTACK_SIZE, ( void * ) &( xTaskCheck[ sTask ] ), uxPriority, ( TaskHandle_t * ) NULL ); + } +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vCompeteingIntMathTask, pvParameters ) +{ +/* These variables are all effectively set to constants so they are volatile to +ensure the compiler does not just get rid of them. */ +volatile long lValue; +short sError = pdFALSE; +volatile BaseType_t *pxTaskHasExecuted; + + /* Set a pointer to the variable we are going to set to true each + iteration. This is also a good test of the parameter passing mechanism + within each port. */ + pxTaskHasExecuted = ( volatile BaseType_t * ) pvParameters; + + /* Keep performing a calculation and checking the result against a constant. */ + for( ;; ) + { + /* Perform the calculation. This will store partial value in + registers, resulting in a good test of the context switch mechanism. */ + lValue = intgCONST1; + lValue += intgCONST2; + + /* Yield in case cooperative scheduling is being used. */ + #if configUSE_PREEMPTION == 0 + { + taskYIELD(); + } + #endif + + /* Finish off the calculation. */ + lValue *= intgCONST3; + lValue /= intgCONST4; + + /* If the calculation is found to be incorrect we stop setting the + TaskHasExecuted variable so the check task can see an error has + occurred. */ + if( lValue != intgEXPECTED_ANSWER ) /*lint !e774 volatile used to prevent this being optimised out. */ + { + sError = pdTRUE; + } + + if( sError == pdFALSE ) + { + /* We have not encountered any errors, so set the flag that show + we are still executing. This will be periodically cleared by + the check task. */ + portENTER_CRITICAL(); + *pxTaskHasExecuted = pdTRUE; + portEXIT_CRITICAL(); + } + + /* Yield in case cooperative scheduling is being used. */ + #if configUSE_PREEMPTION == 0 + { + taskYIELD(); + } + #endif + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +BaseType_t xAreIntegerMathsTaskStillRunning( void ) +{ +BaseType_t xReturn = pdTRUE; +short sTask; + + /* Check the maths tasks are still running by ensuring their check variables + are still being set to true. */ + for( sTask = 0; sTask < intgNUMBER_OF_TASKS; sTask++ ) + { + if( xTaskCheck[ sTask ] == pdFALSE ) + { + /* The check has not incremented so an error exists. */ + xReturn = pdFALSE; + } + + /* Reset the check variable so we can tell if it has been set by + the next time around. */ + xTaskCheck[ sTask ] = pdFALSE; + } + + return xReturn; +} + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/recmutex.c b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/recmutex.c new file mode 100644 index 0000000..69a6f9d --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/recmutex.c @@ -0,0 +1,440 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* + The tasks defined on this page demonstrate the use of recursive mutexes. + + For recursive mutex functionality the created mutex should be created using + xSemaphoreCreateRecursiveMutex(), then be manipulated + using the xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() API + functions. + + This demo creates three tasks all of which access the same recursive mutex: + + prvRecursiveMutexControllingTask() has the highest priority so executes + first and grabs the mutex. It then performs some recursive accesses - + between each of which it sleeps for a short period to let the lower + priority tasks execute. When it has completed its demo functionality + it gives the mutex back before suspending itself. + + prvRecursiveMutexBlockingTask() attempts to access the mutex by performing + a blocking 'take'. The blocking task has a lower priority than the + controlling task so by the time it executes the mutex has already been + taken by the controlling task, causing the blocking task to block. It + does not unblock until the controlling task has given the mutex back, + and it does not actually run until the controlling task has suspended + itself (due to the relative priorities). When it eventually does obtain + the mutex all it does is give the mutex back prior to also suspending + itself. At this point both the controlling task and the blocking task are + suspended. + + prvRecursiveMutexPollingTask() runs at the idle priority. It spins round + a tight loop attempting to obtain the mutex with a non-blocking call. As + the lowest priority task it will not successfully obtain the mutex until + both the controlling and blocking tasks are suspended. Once it eventually + does obtain the mutex it first unsuspends both the controlling task and + blocking task prior to giving the mutex back - resulting in the polling + task temporarily inheriting the controlling tasks priority. +*/ + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "semphr.h" + +/* Demo app include files. */ +#include "recmutex.h" + +/* Priorities assigned to the three tasks. recmuCONTROLLING_TASK_PRIORITY can +be overridden by a definition in FreeRTOSConfig.h. */ +#ifndef recmuCONTROLLING_TASK_PRIORITY + #define recmuCONTROLLING_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 ) +#endif +#define recmuBLOCKING_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 ) +#define recmuPOLLING_TASK_PRIORITY ( tskIDLE_PRIORITY + 0 ) + +/* The recursive call depth. */ +#define recmuMAX_COUNT ( 10 ) + +/* Misc. */ +#define recmuSHORT_DELAY ( 20 / portTICK_PERIOD_MS ) +#define recmuNO_DELAY ( ( TickType_t ) 0 ) +#define recmuEIGHT_TICK_DELAY ( ( TickType_t ) 8 ) + +/* The three tasks as described at the top of this file. */ +static void prvRecursiveMutexControllingTask( void *pvParameters ); +static void prvRecursiveMutexBlockingTask( void *pvParameters ); +static void prvRecursiveMutexPollingTask( void *pvParameters ); + +/* The mutex used by the demo. */ +static SemaphoreHandle_t xMutex; + +/* Variables used to detect and latch errors. */ +static volatile BaseType_t xErrorOccurred = pdFALSE, xControllingIsSuspended = pdFALSE, xBlockingIsSuspended = pdFALSE; +static volatile UBaseType_t uxControllingCycles = 0, uxBlockingCycles = 0, uxPollingCycles = 0; + +/* Handles of the two higher priority tasks, required so they can be resumed +(unsuspended). */ +static TaskHandle_t xControllingTaskHandle, xBlockingTaskHandle; + +/*-----------------------------------------------------------*/ + +void vStartRecursiveMutexTasks( void ) +{ + /* Just creates the mutex and the three tasks. */ + + xMutex = xSemaphoreCreateRecursiveMutex(); + + /* vQueueAddToRegistry() adds the mutex to the registry, if one is + in use. The registry is provided as a means for kernel aware + debuggers to locate mutex and has no purpose if a kernel aware debugger + is not being used. The call to vQueueAddToRegistry() will be removed + by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is + defined to be less than 1. */ + vQueueAddToRegistry( ( QueueHandle_t ) xMutex, "Recursive_Mutex" ); + + + if( xMutex != NULL ) + { + xTaskCreate( prvRecursiveMutexControllingTask, "Rec1", configMINIMAL_STACK_SIZE, NULL, recmuCONTROLLING_TASK_PRIORITY, &xControllingTaskHandle ); + xTaskCreate( prvRecursiveMutexBlockingTask, "Rec2", configMINIMAL_STACK_SIZE, NULL, recmuBLOCKING_TASK_PRIORITY, &xBlockingTaskHandle ); + xTaskCreate( prvRecursiveMutexPollingTask, "Rec3", configMINIMAL_STACK_SIZE, NULL, recmuPOLLING_TASK_PRIORITY, NULL ); + } +} +/*-----------------------------------------------------------*/ + +static void prvRecursiveMutexControllingTask( void *pvParameters ) +{ +UBaseType_t ux; + + /* Just to remove compiler warning. */ + ( void ) pvParameters; + + for( ;; ) + { + /* Should not be able to 'give' the mutex, as we have not yet 'taken' + it. The first time through, the mutex will not have been used yet, + subsequent times through, at this point the mutex will be held by the + polling task. */ + if( xSemaphoreGiveRecursive( xMutex ) == pdPASS ) + { + xErrorOccurred = pdTRUE; + } + + for( ux = 0; ux < recmuMAX_COUNT; ux++ ) + { + /* We should now be able to take the mutex as many times as + we like. + + The first time through the mutex will be immediately available, on + subsequent times through the mutex will be held by the polling task + at this point and this Take will cause the polling task to inherit + the priority of this task. In this case the block time must be + long enough to ensure the polling task will execute again before the + block time expires. If the block time does expire then the error + flag will be set here. */ + if( xSemaphoreTakeRecursive( xMutex, recmuEIGHT_TICK_DELAY ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + + /* Ensure the other task attempting to access the mutex (and the + other demo tasks) are able to execute to ensure they either block + (where a block time is specified) or return an error (where no + block time is specified) as the mutex is held by this task. */ + vTaskDelay( recmuSHORT_DELAY ); + } + + /* For each time we took the mutex, give it back. */ + for( ux = 0; ux < recmuMAX_COUNT; ux++ ) + { + /* Ensure the other task attempting to access the mutex (and the + other demo tasks) are able to execute. */ + vTaskDelay( recmuSHORT_DELAY ); + + /* We should now be able to give the mutex as many times as we + took it. When the mutex is available again the Blocking task + should be unblocked but not run because it has a lower priority + than this task. The polling task should also not run at this point + as it too has a lower priority than this task. */ + if( xSemaphoreGiveRecursive( xMutex ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + } + + /* Having given it back the same number of times as it was taken, we + should no longer be the mutex owner, so the next give should fail. */ + if( xSemaphoreGiveRecursive( xMutex ) == pdPASS ) + { + xErrorOccurred = pdTRUE; + } + + /* Keep count of the number of cycles this task has performed so a + stall can be detected. */ + uxControllingCycles++; + + /* Suspend ourselves so the blocking task can execute. */ + xControllingIsSuspended = pdTRUE; + vTaskSuspend( NULL ); + xControllingIsSuspended = pdFALSE; + } +} +/*-----------------------------------------------------------*/ + +static void prvRecursiveMutexBlockingTask( void *pvParameters ) +{ + /* Just to remove compiler warning. */ + ( void ) pvParameters; + + for( ;; ) + { + /* This task will run while the controlling task is blocked, and the + controlling task will block only once it has the mutex - therefore + this call should block until the controlling task has given up the + mutex, and not actually execute past this call until the controlling + task is suspended. portMAX_DELAY - 1 is used instead of portMAX_DELAY + to ensure the task's state is reported as Blocked and not Suspended in + a later call to configASSERT() (within the polling task). */ + if( xSemaphoreTakeRecursive( xMutex, ( portMAX_DELAY - 1 ) ) == pdPASS ) + { + if( xControllingIsSuspended != pdTRUE ) + { + /* Did not expect to execute until the controlling task was + suspended. */ + xErrorOccurred = pdTRUE; + } + else + { + /* Give the mutex back before suspending ourselves to allow + the polling task to obtain the mutex. */ + if( xSemaphoreGiveRecursive( xMutex ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + + xBlockingIsSuspended = pdTRUE; + vTaskSuspend( NULL ); + xBlockingIsSuspended = pdFALSE; + } + } + else + { + /* We should not leave the xSemaphoreTakeRecursive() function + until the mutex was obtained. */ + xErrorOccurred = pdTRUE; + } + + /* The controlling and blocking tasks should be in lock step. */ + if( uxControllingCycles != ( uxBlockingCycles + 1 ) ) + { + xErrorOccurred = pdTRUE; + } + + /* Keep count of the number of cycles this task has performed so a + stall can be detected. */ + uxBlockingCycles++; + } +} +/*-----------------------------------------------------------*/ + +static void prvRecursiveMutexPollingTask( void *pvParameters ) +{ + /* Just to remove compiler warning. */ + ( void ) pvParameters; + + for( ;; ) + { + /* Keep attempting to obtain the mutex. We should only obtain it when + the blocking task has suspended itself, which in turn should only + happen when the controlling task is also suspended. */ + if( xSemaphoreTakeRecursive( xMutex, recmuNO_DELAY ) == pdPASS ) + { + #if( INCLUDE_eTaskGetState == 1 ) + { + configASSERT( eTaskGetState( xControllingTaskHandle ) == eSuspended ); + configASSERT( eTaskGetState( xBlockingTaskHandle ) == eSuspended ); + } + #endif /* INCLUDE_eTaskGetState */ + + /* Is the blocking task suspended? */ + if( ( xBlockingIsSuspended != pdTRUE ) || ( xControllingIsSuspended != pdTRUE ) ) + { + xErrorOccurred = pdTRUE; + } + else + { + /* Keep count of the number of cycles this task has performed + so a stall can be detected. */ + uxPollingCycles++; + + /* We can resume the other tasks here even though they have a + higher priority than the polling task. When they execute they + will attempt to obtain the mutex but fail because the polling + task is still the mutex holder. The polling task (this task) + will then inherit the higher priority. The Blocking task will + block indefinitely when it attempts to obtain the mutex, the + Controlling task will only block for a fixed period and an + error will be latched if the polling task has not returned the + mutex by the time this fixed period has expired. */ + vTaskResume( xBlockingTaskHandle ); + vTaskResume( xControllingTaskHandle ); + + /* The other two tasks should now have executed and no longer + be suspended. */ + if( ( xBlockingIsSuspended == pdTRUE ) || ( xControllingIsSuspended == pdTRUE ) ) + { + xErrorOccurred = pdTRUE; + } + + #if( INCLUDE_uxTaskPriorityGet == 1 ) + { + /* Check priority inherited. */ + configASSERT( uxTaskPriorityGet( NULL ) == recmuCONTROLLING_TASK_PRIORITY ); + } + #endif /* INCLUDE_uxTaskPriorityGet */ + + #if( INCLUDE_eTaskGetState == 1 ) + { + configASSERT( eTaskGetState( xControllingTaskHandle ) == eBlocked ); + configASSERT( eTaskGetState( xBlockingTaskHandle ) == eBlocked ); + } + #endif /* INCLUDE_eTaskGetState */ + + /* Release the mutex, disinheriting the higher priority again. */ + if( xSemaphoreGiveRecursive( xMutex ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + + #if( INCLUDE_uxTaskPriorityGet == 1 ) + { + /* Check priority disinherited. */ + configASSERT( uxTaskPriorityGet( NULL ) == recmuPOLLING_TASK_PRIORITY ); + } + #endif /* INCLUDE_uxTaskPriorityGet */ + } + } + + #if configUSE_PREEMPTION == 0 + { + taskYIELD(); + } + #endif + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +BaseType_t xAreRecursiveMutexTasksStillRunning( void ) +{ +BaseType_t xReturn; +static UBaseType_t uxLastControllingCycles = 0, uxLastBlockingCycles = 0, uxLastPollingCycles = 0; + + /* Is the controlling task still cycling? */ + if( uxLastControllingCycles == uxControllingCycles ) + { + xErrorOccurred = pdTRUE; + } + else + { + uxLastControllingCycles = uxControllingCycles; + } + + /* Is the blocking task still cycling? */ + if( uxLastBlockingCycles == uxBlockingCycles ) + { + xErrorOccurred = pdTRUE; + } + else + { + uxLastBlockingCycles = uxBlockingCycles; + } + + /* Is the polling task still cycling? */ + if( uxLastPollingCycles == uxPollingCycles ) + { + xErrorOccurred = pdTRUE; + } + else + { + uxLastPollingCycles = uxPollingCycles; + } + + if( xErrorOccurred == pdTRUE ) + { + xReturn = pdFAIL; + } + else + { + xReturn = pdTRUE; + } + + return xReturn; +} + + + + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/semtest.c b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/semtest.c new file mode 100644 index 0000000..5e43e4a --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/semtest.c @@ -0,0 +1,298 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* + * Creates two sets of two tasks. The tasks within a set share a variable, access + * to which is guarded by a semaphore. + * + * Each task starts by attempting to obtain the semaphore. On obtaining a + * semaphore a task checks to ensure that the guarded variable has an expected + * value. It then clears the variable to zero before counting it back up to the + * expected value in increments of 1. After each increment the variable is checked + * to ensure it contains the value to which it was just set. When the starting + * value is again reached the task releases the semaphore giving the other task in + * the set a chance to do exactly the same thing. The starting value is high + * enough to ensure that a tick is likely to occur during the incrementing loop. + * + * An error is flagged if at any time during the process a shared variable is + * found to have a value other than that expected. Such an occurrence would + * suggest an error in the mutual exclusion mechanism by which access to the + * variable is restricted. + * + * The first set of two tasks poll their semaphore. The second set use blocking + * calls. + * + */ + + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "semphr.h" + +/* Demo app include files. */ +#include "semtest.h" + +/* The value to which the shared variables are counted. */ +#define semtstBLOCKING_EXPECTED_VALUE ( ( uint32_t ) 0xfff ) +#define semtstNON_BLOCKING_EXPECTED_VALUE ( ( uint32_t ) 0xff ) + +#define semtstSTACK_SIZE configMINIMAL_STACK_SIZE + +#define semtstNUM_TASKS ( 4 ) + +#define semtstDELAY_FACTOR ( ( TickType_t ) 10 ) + +/* The task function as described at the top of the file. */ +static portTASK_FUNCTION_PROTO( prvSemaphoreTest, pvParameters ); + +/* Structure used to pass parameters to each task. */ +typedef struct SEMAPHORE_PARAMETERS +{ + SemaphoreHandle_t xSemaphore; + volatile uint32_t *pulSharedVariable; + TickType_t xBlockTime; +} xSemaphoreParameters; + +/* Variables used to check that all the tasks are still running without errors. */ +static volatile short sCheckVariables[ semtstNUM_TASKS ] = { 0 }; +static volatile short sNextCheckVariable = 0; + +/*-----------------------------------------------------------*/ + +void vStartSemaphoreTasks( UBaseType_t uxPriority ) +{ +xSemaphoreParameters *pxFirstSemaphoreParameters, *pxSecondSemaphoreParameters; +const TickType_t xBlockTime = ( TickType_t ) 100; + + /* Create the structure used to pass parameters to the first two tasks. */ + pxFirstSemaphoreParameters = ( xSemaphoreParameters * ) pvPortMalloc( sizeof( xSemaphoreParameters ) ); + + if( pxFirstSemaphoreParameters != NULL ) + { + /* Create the semaphore used by the first two tasks. */ + pxFirstSemaphoreParameters->xSemaphore = xSemaphoreCreateBinary(); + xSemaphoreGive( pxFirstSemaphoreParameters->xSemaphore ); + + if( pxFirstSemaphoreParameters->xSemaphore != NULL ) + { + /* Create the variable which is to be shared by the first two tasks. */ + pxFirstSemaphoreParameters->pulSharedVariable = ( uint32_t * ) pvPortMalloc( sizeof( uint32_t ) ); + + /* Initialise the share variable to the value the tasks expect. */ + *( pxFirstSemaphoreParameters->pulSharedVariable ) = semtstNON_BLOCKING_EXPECTED_VALUE; + + /* The first two tasks do not block on semaphore calls. */ + pxFirstSemaphoreParameters->xBlockTime = ( TickType_t ) 0; + + /* Spawn the first two tasks. As they poll they operate at the idle priority. */ + xTaskCreate( prvSemaphoreTest, "PolSEM1", semtstSTACK_SIZE, ( void * ) pxFirstSemaphoreParameters, tskIDLE_PRIORITY, ( TaskHandle_t * ) NULL ); + xTaskCreate( prvSemaphoreTest, "PolSEM2", semtstSTACK_SIZE, ( void * ) pxFirstSemaphoreParameters, tskIDLE_PRIORITY, ( TaskHandle_t * ) NULL ); + } + } + + /* Do exactly the same to create the second set of tasks, only this time + provide a block time for the semaphore calls. */ + pxSecondSemaphoreParameters = ( xSemaphoreParameters * ) pvPortMalloc( sizeof( xSemaphoreParameters ) ); + if( pxSecondSemaphoreParameters != NULL ) + { + pxSecondSemaphoreParameters->xSemaphore = xSemaphoreCreateBinary(); + xSemaphoreGive( pxSecondSemaphoreParameters->xSemaphore ); + + if( pxSecondSemaphoreParameters->xSemaphore != NULL ) + { + pxSecondSemaphoreParameters->pulSharedVariable = ( uint32_t * ) pvPortMalloc( sizeof( uint32_t ) ); + *( pxSecondSemaphoreParameters->pulSharedVariable ) = semtstBLOCKING_EXPECTED_VALUE; + pxSecondSemaphoreParameters->xBlockTime = xBlockTime / portTICK_PERIOD_MS; + + xTaskCreate( prvSemaphoreTest, "BlkSEM1", semtstSTACK_SIZE, ( void * ) pxSecondSemaphoreParameters, uxPriority, ( TaskHandle_t * ) NULL ); + xTaskCreate( prvSemaphoreTest, "BlkSEM2", semtstSTACK_SIZE, ( void * ) pxSecondSemaphoreParameters, uxPriority, ( TaskHandle_t * ) NULL ); + } + } + + /* vQueueAddToRegistry() adds the semaphore to the registry, if one is + in use. The registry is provided as a means for kernel aware + debuggers to locate semaphores and has no purpose if a kernel aware debugger + is not being used. The call to vQueueAddToRegistry() will be removed + by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is + defined to be less than 1. */ + vQueueAddToRegistry( ( QueueHandle_t ) pxFirstSemaphoreParameters->xSemaphore, "Counting_Sem_1" ); + vQueueAddToRegistry( ( QueueHandle_t ) pxSecondSemaphoreParameters->xSemaphore, "Counting_Sem_2" ); +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( prvSemaphoreTest, pvParameters ) +{ +xSemaphoreParameters *pxParameters; +volatile uint32_t *pulSharedVariable, ulExpectedValue; +uint32_t ulCounter; +short sError = pdFALSE, sCheckVariableToUse; + + /* See which check variable to use. sNextCheckVariable is not semaphore + protected! */ + portENTER_CRITICAL(); + sCheckVariableToUse = sNextCheckVariable; + sNextCheckVariable++; + portEXIT_CRITICAL(); + + /* A structure is passed in as the parameter. This contains the shared + variable being guarded. */ + pxParameters = ( xSemaphoreParameters * ) pvParameters; + pulSharedVariable = pxParameters->pulSharedVariable; + + /* If we are blocking we use a much higher count to ensure loads of context + switches occur during the count. */ + if( pxParameters->xBlockTime > ( TickType_t ) 0 ) + { + ulExpectedValue = semtstBLOCKING_EXPECTED_VALUE; + } + else + { + ulExpectedValue = semtstNON_BLOCKING_EXPECTED_VALUE; + } + + for( ;; ) + { + /* Try to obtain the semaphore. */ + if( xSemaphoreTake( pxParameters->xSemaphore, pxParameters->xBlockTime ) == pdPASS ) + { + /* We have the semaphore and so expect any other tasks using the + shared variable to have left it in the state we expect to find + it. */ + if( *pulSharedVariable != ulExpectedValue ) + { + sError = pdTRUE; + } + + /* Clear the variable, then count it back up to the expected value + before releasing the semaphore. Would expect a context switch or + two during this time. */ + for( ulCounter = ( uint32_t ) 0; ulCounter <= ulExpectedValue; ulCounter++ ) + { + *pulSharedVariable = ulCounter; + if( *pulSharedVariable != ulCounter ) + { + sError = pdTRUE; + } + } + + /* Release the semaphore, and if no errors have occurred increment the check + variable. */ + if( xSemaphoreGive( pxParameters->xSemaphore ) == pdFALSE ) + { + sError = pdTRUE; + } + + if( sError == pdFALSE ) + { + if( sCheckVariableToUse < semtstNUM_TASKS ) + { + ( sCheckVariables[ sCheckVariableToUse ] )++; + } + } + + /* If we have a block time then we are running at a priority higher + than the idle priority. This task takes a long time to complete + a cycle (deliberately so to test the guarding) so will be starving + out lower priority tasks. Block for some time to allow give lower + priority tasks some processor time. */ + vTaskDelay( pxParameters->xBlockTime * semtstDELAY_FACTOR ); + } + else + { + if( pxParameters->xBlockTime == ( TickType_t ) 0 ) + { + /* We have not got the semaphore yet, so no point using the + processor. We are not blocking when attempting to obtain the + semaphore. */ + taskYIELD(); + } + } + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +BaseType_t xAreSemaphoreTasksStillRunning( void ) +{ +static short sLastCheckVariables[ semtstNUM_TASKS ] = { 0 }; +BaseType_t xTask, xReturn = pdTRUE; + + for( xTask = 0; xTask < semtstNUM_TASKS; xTask++ ) + { + if( sLastCheckVariables[ xTask ] == sCheckVariables[ xTask ] ) + { + xReturn = pdFALSE; + } + + sLastCheckVariables[ xTask ] = sCheckVariables[ xTask ]; + } + + return xReturn; +} + + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/sp_flop.c b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/sp_flop.c new file mode 100644 index 0000000..44cdd6f --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/Minimal/sp_flop.c @@ -0,0 +1,365 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* + * Creates eight tasks, each of which loops continuously performing a floating + * point calculation - using single precision variables. + * + * All the tasks run at the idle priority and never block or yield. This causes + * all eight tasks to time slice with the idle task. Running at the idle priority + * means that these tasks will get pre-empted any time another task is ready to run + * or a time slice occurs. More often than not the pre-emption will occur mid + * calculation, creating a good test of the schedulers context switch mechanism - a + * calculation producing an unexpected result could be a symptom of a corruption in + * the context of a task. + */ + +#include +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Demo program include files. */ +#include "flop.h" + +#define mathSTACK_SIZE configMINIMAL_STACK_SIZE +#define mathNUMBER_OF_TASKS ( 8 ) + +/* Four tasks, each of which performs a different floating point calculation. +Each of the four is created twice. */ +static portTASK_FUNCTION_PROTO( vCompetingMathTask1, pvParameters ); +static portTASK_FUNCTION_PROTO( vCompetingMathTask2, pvParameters ); +static portTASK_FUNCTION_PROTO( vCompetingMathTask3, pvParameters ); +static portTASK_FUNCTION_PROTO( vCompetingMathTask4, pvParameters ); + +/* These variables are used to check that all the tasks are still running. If a +task gets a calculation wrong it will +stop incrementing its check variable. */ +static volatile uint16_t usTaskCheck[ mathNUMBER_OF_TASKS ] = { ( uint16_t ) 0 }; + +/*-----------------------------------------------------------*/ + +void vStartMathTasks( UBaseType_t uxPriority ) +{ + xTaskCreate( vCompetingMathTask1, "Math1", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 0 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask2, "Math2", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 1 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask3, "Math3", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 2 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask4, "Math4", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 3 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask1, "Math5", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 4 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask2, "Math6", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 5 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask3, "Math7", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 6 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask4, "Math8", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 7 ] ), uxPriority, NULL ); +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vCompetingMathTask1, pvParameters ) +{ +volatile float f1, f2, f3, f4; +volatile uint16_t *pusTaskCheckVariable; +volatile float fAnswer; +short sError = pdFALSE; + + f1 = 123.4567F; + f2 = 2345.6789F; + f3 = -918.222F; + + fAnswer = ( f1 + f2 ) * f3; + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( uint16_t * ) pvParameters; + + /* Keep performing a calculation and checking the result against a constant. */ + for(;;) + { + f1 = 123.4567F; + f2 = 2345.6789F; + f3 = -918.222F; + + f4 = ( f1 + f2 ) * f3; + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* If the calculation does not match the expected constant, stop the + increment of the check variable. */ + if( fabs( f4 - fAnswer ) > 0.001F ) + { + sError = pdTRUE; + } + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct, increment the check + variable so we know this task is still running okay. */ + ( *pusTaskCheckVariable )++; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + } +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vCompetingMathTask2, pvParameters ) +{ +volatile float f1, f2, f3, f4; +volatile uint16_t *pusTaskCheckVariable; +volatile float fAnswer; +short sError = pdFALSE; + + f1 = -389.38F; + f2 = 32498.2F; + f3 = -2.0001F; + + fAnswer = ( f1 / f2 ) * f3; + + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( uint16_t * ) pvParameters; + + /* Keep performing a calculation and checking the result against a constant. */ + for( ;; ) + { + f1 = -389.38F; + f2 = 32498.2F; + f3 = -2.0001F; + + f4 = ( f1 / f2 ) * f3; + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* If the calculation does not match the expected constant, stop the + increment of the check variable. */ + if( fabs( f4 - fAnswer ) > 0.001F ) + { + sError = pdTRUE; + } + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct, increment the check + variable so we know + this task is still running okay. */ + ( *pusTaskCheckVariable )++; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + } +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vCompetingMathTask3, pvParameters ) +{ +volatile float *pfArray, fTotal1, fTotal2, fDifference, fPosition; +volatile uint16_t *pusTaskCheckVariable; +const size_t xArraySize = 10; +size_t xPosition; +short sError = pdFALSE; + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( uint16_t * ) pvParameters; + + pfArray = ( float * ) pvPortMalloc( xArraySize * sizeof( float ) ); + + /* Keep filling an array, keeping a running total of the values placed in the + array. Then run through the array adding up all the values. If the two totals + do not match, stop the check variable from incrementing. */ + for( ;; ) + { + fTotal1 = 0.0F; + fTotal2 = 0.0F; + fPosition = 0.0F; + + for( xPosition = 0; xPosition < xArraySize; xPosition++ ) + { + pfArray[ xPosition ] = fPosition + 5.5F; + fTotal1 += fPosition + 5.5F; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + for( xPosition = 0; xPosition < xArraySize; xPosition++ ) + { + fTotal2 += pfArray[ xPosition ]; + } + + fDifference = fTotal1 - fTotal2; + if( fabs( fDifference ) > 0.001F ) + { + sError = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct, increment the check + variable so we know this task is still running okay. */ + ( *pusTaskCheckVariable )++; + } + } +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vCompetingMathTask4, pvParameters ) +{ +volatile float *pfArray, fTotal1, fTotal2, fDifference, fPosition; +volatile uint16_t *pusTaskCheckVariable; +const size_t xArraySize = 10; +size_t xPosition; +short sError = pdFALSE; + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( uint16_t * ) pvParameters; + + pfArray = ( float * ) pvPortMalloc( xArraySize * sizeof( float ) ); + + /* Keep filling an array, keeping a running total of the values placed in the + array. Then run through the array adding up all the values. If the two totals + do not match, stop the check variable from incrementing. */ + for( ;; ) + { + fTotal1 = 0.0F; + fTotal2 = 0.0F; + fPosition = 0.0F; + + for( xPosition = 0; xPosition < xArraySize; xPosition++ ) + { + pfArray[ xPosition ] = fPosition * 12.123F; + fTotal1 += fPosition * 12.123F; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + for( xPosition = 0; xPosition < xArraySize; xPosition++ ) + { + fTotal2 += pfArray[ xPosition ]; + } + + fDifference = fTotal1 - fTotal2; + if( fabs( fDifference ) > 0.001F ) + { + sError = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct, increment the check + variable so we know this task is still running okay. */ + ( *pusTaskCheckVariable )++; + } + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +BaseType_t xAreMathsTaskStillRunning( void ) +{ +/* Keep a history of the check variables so we know if they have been incremented +since the last call. */ +static uint16_t usLastTaskCheck[ mathNUMBER_OF_TASKS ] = { ( uint16_t ) 0 }; +BaseType_t xReturn = pdTRUE, xTask; + + /* Check the maths tasks are still running by ensuring their check variables + are still incrementing. */ + for( xTask = 0; xTask < mathNUMBER_OF_TASKS; xTask++ ) + { + if( usTaskCheck[ xTask ] == usLastTaskCheck[ xTask ] ) + { + /* The check has not incremented so an error exists. */ + xReturn = pdFALSE; + } + + usLastTaskCheck[ xTask ] = usTaskCheck[ xTask ]; + } + + return xReturn; +} + + + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/AltBlckQ.h b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/AltBlckQ.h new file mode 100644 index 0000000..5e5eb3f --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/AltBlckQ.h @@ -0,0 +1,74 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef ALT_BLOCK_Q_H +#define ALT_BLOCK_Q_H + +void vStartAltBlockingQueueTasks( UBaseType_t uxPriority ); +BaseType_t xAreAltBlockingQueuesStillRunning( void ); + +#endif + + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/AltBlock.h b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/AltBlock.h new file mode 100644 index 0000000..7946734 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/AltBlock.h @@ -0,0 +1,74 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef FAST_BLOCK_TIME_TEST_H +#define FAST_BLOCK_TIME_TEST_H + +void vCreateAltBlockTimeTasks( void ); +BaseType_t xAreAltBlockTimeTestTasksStillRunning( void ); + +#endif + + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/AltPollQ.h b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/AltPollQ.h new file mode 100644 index 0000000..ce6af62 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/AltPollQ.h @@ -0,0 +1,74 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef ALT_POLLED_Q_H +#define ALT_POLLED_Q_H + +void vStartAltPolledQueueTasks( UBaseType_t uxPriority ); +BaseType_t xAreAltPollingQueuesStillRunning( void ); + +#endif + + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/AltQTest.h b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/AltQTest.h new file mode 100644 index 0000000..cf50026 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/AltQTest.h @@ -0,0 +1,75 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef FAST_GEN_Q_TEST_H +#define FAST_GEN_Q_TEST_H + +void vStartAltGenericQueueTasks( UBaseType_t uxPriority ); +BaseType_t xAreAltGenericQueueTasksStillRunning( void ); + +#endif /* GEN_Q_TEST_H */ + + + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/BlockQ.h b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/BlockQ.h new file mode 100644 index 0000000..7a6ea01 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/BlockQ.h @@ -0,0 +1,74 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef BLOCK_Q_H +#define BLOCK_Q_H + +void vStartBlockingQueueTasks( UBaseType_t uxPriority ); +BaseType_t xAreBlockingQueuesStillRunning( void ); + +#endif + + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/EventGroupsDemo.h b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/EventGroupsDemo.h new file mode 100644 index 0000000..1b5c49c --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/EventGroupsDemo.h @@ -0,0 +1,82 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + + +/* + * This file contains fairly comprehensive checks on the behaviour of event + * groups. It is not intended to be a user friendly demonstration of the event + * groups API. + */ + +#ifndef EVENT_GROUPS_DEMO_H +#define EVENT_GROUPS_DEMO_H + +void vStartEventGroupTasks( void ); +BaseType_t xAreEventGroupTasksStillRunning( void ); +void vPeriodicEventGroupsProcessing( void ); + +#endif /* EVENT_GROUPS_DEMO_H */ + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/GenQTest.h b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/GenQTest.h new file mode 100644 index 0000000..a832900 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/GenQTest.h @@ -0,0 +1,76 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef GEN_Q_TEST_H +#define GEN_Q_TEST_H + +void vStartGenericQueueTasks( UBaseType_t uxPriority ); +BaseType_t xAreGenericQueueTasksStillRunning( void ); +void vMutexISRInteractionTest( void ); + +#endif /* GEN_Q_TEST_H */ + + + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/IntQueue.h b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/IntQueue.h new file mode 100644 index 0000000..77fae82 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/IntQueue.h @@ -0,0 +1,80 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef QUEUE_ACCESS_TEST +#define QUEUE_ACCESS_TEST + +void vStartInterruptQueueTasks( void ); +BaseType_t xAreIntQueueTasksStillRunning( void ); +BaseType_t xFirstTimerHandler( void ); +BaseType_t xSecondTimerHandler( void ); + +#endif /* QUEUE_ACCESS_TEST */ + + + + + + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/PollQ.h b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/PollQ.h new file mode 100644 index 0000000..5a6dc8e --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/PollQ.h @@ -0,0 +1,74 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef POLLED_Q_H +#define POLLED_Q_H + +void vStartPolledQueueTasks( UBaseType_t uxPriority ); +BaseType_t xArePollingQueuesStillRunning( void ); + +#endif + + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/QPeek.h b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/QPeek.h new file mode 100644 index 0000000..b9b8525 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/QPeek.h @@ -0,0 +1,75 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef Q_PEEK_TEST_H +#define Q_PEEK_TEST_H + +void vStartQueuePeekTasks( void ); +BaseType_t xAreQueuePeekTasksStillRunning( void ); + +#endif /* Q_PEEK_TEST_H */ + + + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/QueueOverwrite.h b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/QueueOverwrite.h new file mode 100644 index 0000000..1d79247 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/QueueOverwrite.h @@ -0,0 +1,75 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef QUEUE_OVERWRITE_H +#define QUEUE_OVERWRITE_H + +void vStartQueueOverwriteTask( UBaseType_t uxPriority ); +BaseType_t xIsQueueOverwriteTaskStillRunning( void ); +void vQueueOverwritePeriodicISRDemo( void ); + +#endif /* QUEUE_OVERWRITE_H */ + + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/QueueSet.h b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/QueueSet.h new file mode 100644 index 0000000..16c4623 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/QueueSet.h @@ -0,0 +1,75 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef QUEUE_WAIT_MULTIPLE_H +#define QUEUE_WAIT_MULTIPLE_H + +void vStartQueueSetTasks( void ); +BaseType_t xAreQueueSetTasksStillRunning( void ); +void vQueueSetAccessQueueSetFromISR( void ); + +#endif /* QUEUE_WAIT_MULTIPLE_H */ + + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/TimerDemo.h b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/TimerDemo.h new file mode 100644 index 0000000..d005a64 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/TimerDemo.h @@ -0,0 +1,76 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef TIMER_DEMO_H +#define TIMER_DEMO_H + +void vStartTimerDemoTask( TickType_t xBaseFrequencyIn ); +BaseType_t xAreTimerDemoTasksStillRunning( TickType_t xCycleFrequency ); +void vTimerPeriodicISRTests( void ); + +#endif /* TIMER_DEMO_H */ + + + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/blocktim.h b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/blocktim.h new file mode 100644 index 0000000..fb56df4 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/blocktim.h @@ -0,0 +1,74 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef BLOCK_TIME_TEST_H +#define BLOCK_TIME_TEST_H + +void vCreateBlockTimeTasks( void ); +BaseType_t xAreBlockTimeTestTasksStillRunning( void ); + +#endif + + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/comtest.h b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/comtest.h new file mode 100644 index 0000000..43d92c8 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/comtest.h @@ -0,0 +1,75 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef COMTEST_H +#define COMTEST_H + +void vAltStartComTestTasks( UBaseType_t uxPriority, uint32_t ulBaudRate, UBaseType_t uxLED ); +void vStartComTestTasks( UBaseType_t uxPriority, eCOMPort ePort, eBaud eBaudRate ); +BaseType_t xAreComTestTasksStillRunning( void ); +void vComTestUnsuspendTask( void ); + +#endif + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/comtest2.h b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/comtest2.h new file mode 100644 index 0000000..43e9993 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/comtest2.h @@ -0,0 +1,73 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef COMTEST_H +#define COMTEST_H + +void vAltStartComTestTasks( UBaseType_t uxPriority, uint32_t ulBaudRate, UBaseType_t uxLED ); +BaseType_t xAreComTestTasksStillRunning( void ); + +#endif + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/comtest_strings.h b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/comtest_strings.h new file mode 100644 index 0000000..0d72615 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/comtest_strings.h @@ -0,0 +1,73 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef COMTEST_STRINGS_H +#define COMTEST_STRINGS_H + +void vStartComTestStringsTasks( UBaseType_t uxPriority, uint32_t ulBaudRate, UBaseType_t uxLED ); +BaseType_t xAreComTestTasksStillRunning( void ); + +#endif + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/countsem.h b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/countsem.h new file mode 100644 index 0000000..484a23a --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/countsem.h @@ -0,0 +1,73 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef COUNT_SEMAPHORE_TEST_H +#define COUNT_SEMAPHORE_TEST_H + +void vStartCountingSemaphoreTasks( void ); +BaseType_t xAreCountingSemaphoreTasksStillRunning( void ); + +#endif + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/crflash.h b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/crflash.h new file mode 100644 index 0000000..3d51635 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/crflash.h @@ -0,0 +1,85 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef CRFLASH_LED_H +#define CRFLASH_LED_H + +/* + * Create the co-routines used to flash the LED's at different rates. + * + * @param uxPriority The number of 'fixed delay' co-routines to create. This + * also effects the number of LED's that will be utilised. For example, + * passing in 3 will cause LED's 0 to 2 to be utilised. + */ +void vStartFlashCoRoutines( UBaseType_t uxPriority ); + +/* + * Return pdPASS or pdFAIL depending on whether an error has been detected + * or not. + */ +BaseType_t xAreFlashCoRoutinesStillRunning( void ); + +#endif + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/crhook.h b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/crhook.h new file mode 100644 index 0000000..d56ee65 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/crhook.h @@ -0,0 +1,81 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef CRHOOK_H +#define CRHOOK_H + +/* + * Create the co-routines used to communicate wit the tick hook. + */ +void vStartHookCoRoutines( void ); + +/* + * Return pdPASS or pdFAIL depending on whether an error has been detected + * or not. + */ +BaseType_t xAreHookCoRoutinesStillRunning( void ); + +#endif + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/death.h b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/death.h new file mode 100644 index 0000000..5d08038 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/death.h @@ -0,0 +1,74 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef SUICIDE_TASK_H +#define SUICIDE_TASK_H + +void vCreateSuicidalTasks( UBaseType_t uxPriority ); +BaseType_t xIsCreateTaskStillRunning( void ); + +#endif + + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/dynamic.h b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/dynamic.h new file mode 100644 index 0000000..a923c20 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/dynamic.h @@ -0,0 +1,74 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef DYNAMIC_MANIPULATION_H +#define DYNAMIC_MANIPULATION_H + +void vStartDynamicPriorityTasks( void ); +BaseType_t xAreDynamicPriorityTasksStillRunning( void ); + +#endif + + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/fileIO.h b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/fileIO.h new file mode 100644 index 0000000..afcf005 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/fileIO.h @@ -0,0 +1,74 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef FILE_IO_H +#define FILE_OI_H + +void vDisplayMessage( const char * const pcMessageToPrint ); +void vWriteMessageToDisk( const char * const pcMessage ); +void vWriteBufferToDisk( const char * const pcBuffer, uint32_t ulBufferLength ); + +#endif + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/flash.h b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/flash.h new file mode 100644 index 0000000..41ea2f6 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/flash.h @@ -0,0 +1,72 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef FLASH_LED_H +#define FLASH_LED_H + +void vStartLEDFlashTasks( UBaseType_t uxPriority ); + +#endif + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/flash_timer.h b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/flash_timer.h new file mode 100644 index 0000000..2e7a230 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/flash_timer.h @@ -0,0 +1,79 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef FLASH_TIMER_H +#define FLASH_TIMER_H + +/* + * Creates the LED flashing timers. xNumberOfLEDs specifies how many timers to + * create, with each timer toggling a different LED. The first LED to be + * toggled is LED 0, with subsequent LEDs following on in numerical order. Each + * timer uses the exact same callback function, with the timer ID being used + * within the callback function to determine which timer has actually expired + * (and therefore which LED to toggle). + */ +void vStartLEDFlashTimers( UBaseType_t uxNumberOfLEDs ); + +#endif /* FLASH_TIMER_H */ diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/flop.h b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/flop.h new file mode 100644 index 0000000..ef6fe64 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/flop.h @@ -0,0 +1,74 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef FLOP_TASKS_H +#define FLOP_TASKS_H + +void vStartMathTasks( UBaseType_t uxPriority ); +BaseType_t xAreMathsTaskStillRunning( void ); + +#endif + + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/integer.h b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/integer.h new file mode 100644 index 0000000..8b0d960 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/integer.h @@ -0,0 +1,74 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef INTEGER_TASKS_H +#define INTEGER_TASKS_H + +void vStartIntegerMathTasks( UBaseType_t uxPriority ); +BaseType_t xAreIntegerMathsTaskStillRunning( void ); + +#endif + + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/mevents.h b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/mevents.h new file mode 100644 index 0000000..fed650e --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/mevents.h @@ -0,0 +1,74 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef EVENTS_TEST_H +#define EVENTS_TEST_H + +void vStartMultiEventTasks( void ); +BaseType_t xAreMultiEventTasksStillRunning( void ); + +#endif + + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/partest.h b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/partest.h new file mode 100644 index 0000000..0886481 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/partest.h @@ -0,0 +1,76 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef PARTEST_H +#define PARTEST_H + +#define partstDEFAULT_PORT_ADDRESS ( ( uint16_t ) 0x378 ) + +void vParTestInitialise( void ); +void vParTestSetLED( UBaseType_t uxLED, BaseType_t xValue ); +void vParTestToggleLED( UBaseType_t uxLED ); + +#endif + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/print.h b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/print.h new file mode 100644 index 0000000..562b1e7 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/print.h @@ -0,0 +1,75 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef PRINT_H +#define PRINT_H + +void vPrintInitialise( void ); +void vPrintDisplayMessage( const char * const * pcMessageToSend ); +const char *pcPrintGetNextMessage( TickType_t xPrintRate ); + +#endif + + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/recmutex.h b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/recmutex.h new file mode 100644 index 0000000..82eee1f --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/recmutex.h @@ -0,0 +1,73 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef RECURSIVE_MUTEX_TEST_H +#define RECURSIVE_MUTEX_TEST_H + +void vStartRecursiveMutexTasks( void ); +BaseType_t xAreRecursiveMutexTasksStillRunning( void ); + +#endif + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/semtest.h b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/semtest.h new file mode 100644 index 0000000..4c7ffb3 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/semtest.h @@ -0,0 +1,73 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef SEMAPHORE_TEST_H +#define SEMAPHORE_TEST_H + +void vStartSemaphoreTasks( UBaseType_t uxPriority ); +BaseType_t xAreSemaphoreTasksStillRunning( void ); + +#endif + diff --git a/component/os/freertos/freertos_v8.1.2/Demo/Common/include/serial.h b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/serial.h new file mode 100644 index 0000000..838ccd3 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Demo/Common/include/serial.h @@ -0,0 +1,136 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef SERIAL_COMMS_H +#define SERIAL_COMMS_H + +typedef void * xComPortHandle; + +typedef enum +{ + serCOM1, + serCOM2, + serCOM3, + serCOM4, + serCOM5, + serCOM6, + serCOM7, + serCOM8 +} eCOMPort; + +typedef enum +{ + serNO_PARITY, + serODD_PARITY, + serEVEN_PARITY, + serMARK_PARITY, + serSPACE_PARITY +} eParity; + +typedef enum +{ + serSTOP_1, + serSTOP_2 +} eStopBits; + +typedef enum +{ + serBITS_5, + serBITS_6, + serBITS_7, + serBITS_8 +} eDataBits; + +typedef enum +{ + ser50, + ser75, + ser110, + ser134, + ser150, + ser200, + ser300, + ser600, + ser1200, + ser1800, + ser2400, + ser4800, + ser9600, + ser19200, + ser38400, + ser57600, + ser115200 +} eBaud; + +xComPortHandle xSerialPortInitMinimal( unsigned long ulWantedBaud, unsigned portBASE_TYPE uxQueueLength ); +xComPortHandle xSerialPortInit( eCOMPort ePort, eBaud eWantedBaud, eParity eWantedParity, eDataBits eWantedDataBits, eStopBits eWantedStopBits, unsigned portBASE_TYPE uxBufferLength ); +void vSerialPutString( xComPortHandle pxPort, const signed char * const pcString, unsigned short usStringLength ); +signed portBASE_TYPE xSerialGetChar( xComPortHandle pxPort, signed char *pcRxedChar, TickType_t xBlockTime ); +signed portBASE_TYPE xSerialPutChar( xComPortHandle pxPort, signed char cOutChar, TickType_t xBlockTime ); +portBASE_TYPE xSerialWaitForSemaphore( xComPortHandle xPort ); +void vSerialClose( xComPortHandle xPort ); + +#endif + diff --git a/component/os/freertos/freertos_v8.1.2/License/license.txt b/component/os/freertos/freertos_v8.1.2/License/license.txt new file mode 100644 index 0000000..be959bb --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/License/license.txt @@ -0,0 +1,394 @@ +The FreeRTOS source code is licensed by a *modified* GNU General Public +License (GPL). The modification is provided in the form of an exception. + +NOTE: The modification to the GPL is included to allow you to distribute a +combined work that includes FreeRTOS without being obliged to provide the source +code for proprietary components outside of the FreeRTOS kernel. + + + +---------------------------------------------------------------------------- + +The FreeRTOS GPL Exception Text: + +Any FreeRTOS source code, whether modified or in it's original release form, +or whether in whole or in part, can only be distributed by you under the terms +of the GNU General Public License plus this exception. An independent module is +a module which is not derived from or based on FreeRTOS. + +Clause 1: + +Linking FreeRTOS statically or dynamically with other modules is making a +combined work based on FreeRTOS. Thus, the terms and conditions of the GNU +General Public License cover the whole combination. + +As a special exception, the copyright holder of FreeRTOS gives you permission +to link FreeRTOS with independent modules that communicate with FreeRTOS +solely through the FreeRTOS API interface, regardless of the license terms of +these independent modules, and to copy and distribute the resulting combined +work under terms of your choice, provided that + + + Every copy of the combined work is accompanied by a written statement that + details to the recipient the version of FreeRTOS used and an offer by yourself + to provide the FreeRTOS source code (including any modifications you may have + made) should the recipient request it. + + + The combined work is not itself an RTOS, scheduler, kernel or related product. + + + The independent modules add significant and primary functionality to FreeRTOS + and do not merely extend the existing functionality already present in FreeRTOS. + +Clause 2: + +FreeRTOS may not be used for any competitive or comparative purpose, including the +publication of any form of run time or compile time metric, without the express +permission of Real Time Engineers Ltd. (this is the norm within the industry and +is intended to ensure information accuracy). + + +-------------------------------------------------------------------- + +The standard GPL exception text: + + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License** as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + diff --git a/component/os/freertos/freertos_v8.1.2/Source/Makefile b/component/os/freertos/freertos_v8.1.2/Source/Makefile new file mode 100644 index 0000000..85694d5 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/Makefile @@ -0,0 +1,54 @@ + +include $(MAKE_INCLUDE_GEN) + +.PHONY: all clean + +MODULE_IFLAGS = -I./include + + +#*****************************************************************************# +# Object FILE LIST # +#*****************************************************************************# +OBJS = tasks.o list.o croutine.o queue.o timers.o event_groups.o +ifeq ($(CONFIG_RELEASE_BUILD),y) + OBJS = +else +endif + + +#*****************************************************************************# +# RULES TO GENERATE TARGETS # +#*****************************************************************************# + +# Define the Rules to build the core targets +#all: CORE_TARGETS COPY_RAM_OBJS +all: CORE_TARGETS COPY_RAM_OBJS + make -C portable/MemMang all + make -C portable/GCC/ARM_CM3 all + + + +#*****************************************************************************# +# GENERATE OBJECT FILE +#*****************************************************************************# +CORE_TARGETS: $(OBJS) + + +#*****************************************************************************# +# RULES TO CLEAN TARGETS # +#*****************************************************************************# +clean: + $(REMOVE) portable/MemMang/*.o + $(REMOVE) portable/MemMang/*.i + $(REMOVE) portable/MemMang/*.s + $(REMOVE) portable/MemMang/*.d + $(REMOVE) portable/GCC/ARM_CM3/*.o + $(REMOVE) portable/GCC/ARM_CM3/*.i + $(REMOVE) portable/GCC/ARM_CM3/*.s + $(REMOVE) portable/GCC/ARM_CM3/*.d + $(REMOVE) *.o + $(REMOVE) *.i + $(REMOVE) *.s + $(REMOVE) *.d + +-include $(DEPS) diff --git a/component/os/freertos/freertos_v8.1.2/Source/croutine.c b/component/os/freertos/freertos_v8.1.2/Source/croutine.c new file mode 100644 index 0000000..3c5bd6f --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/croutine.c @@ -0,0 +1,386 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#include "FreeRTOS.h" +#include "task.h" +#include "croutine.h" + +/* + * Some kernel aware debuggers require data to be viewed to be global, rather + * than file scope. + */ +#ifdef portREMOVE_STATIC_QUALIFIER + #define static +#endif + + +/* Lists for ready and blocked co-routines. --------------------*/ +static List_t pxReadyCoRoutineLists[ configMAX_CO_ROUTINE_PRIORITIES ]; /*< Prioritised ready co-routines. */ +static List_t xDelayedCoRoutineList1; /*< Delayed co-routines. */ +static List_t xDelayedCoRoutineList2; /*< Delayed co-routines (two lists are used - one for delays that have overflowed the current tick count. */ +static List_t * pxDelayedCoRoutineList; /*< Points to the delayed co-routine list currently being used. */ +static List_t * pxOverflowDelayedCoRoutineList; /*< Points to the delayed co-routine list currently being used to hold co-routines that have overflowed the current tick count. */ +static List_t xPendingReadyCoRoutineList; /*< Holds co-routines that have been readied by an external event. They cannot be added directly to the ready lists as the ready lists cannot be accessed by interrupts. */ + +/* Other file private variables. --------------------------------*/ +CRCB_t * pxCurrentCoRoutine = NULL; +static UBaseType_t uxTopCoRoutineReadyPriority = 0; +static TickType_t xCoRoutineTickCount = 0, xLastTickCount = 0, xPassedTicks = 0; + +/* The initial state of the co-routine when it is created. */ +#define corINITIAL_STATE ( 0 ) + +/* + * Place the co-routine represented by pxCRCB into the appropriate ready queue + * for the priority. It is inserted at the end of the list. + * + * This macro accesses the co-routine ready lists and therefore must not be + * used from within an ISR. + */ +#define prvAddCoRoutineToReadyQueue( pxCRCB ) \ +{ \ + if( pxCRCB->uxPriority > uxTopCoRoutineReadyPriority ) \ + { \ + uxTopCoRoutineReadyPriority = pxCRCB->uxPriority; \ + } \ + vListInsertEnd( ( List_t * ) &( pxReadyCoRoutineLists[ pxCRCB->uxPriority ] ), &( pxCRCB->xGenericListItem ) ); \ +} + +/* + * Utility to ready all the lists used by the scheduler. This is called + * automatically upon the creation of the first co-routine. + */ +static void prvInitialiseCoRoutineLists( void ); + +/* + * Co-routines that are readied by an interrupt cannot be placed directly into + * the ready lists (there is no mutual exclusion). Instead they are placed in + * in the pending ready list in order that they can later be moved to the ready + * list by the co-routine scheduler. + */ +static void prvCheckPendingReadyList( void ); + +/* + * Macro that looks at the list of co-routines that are currently delayed to + * see if any require waking. + * + * Co-routines are stored in the queue in the order of their wake time - + * meaning once one co-routine has been found whose timer has not expired + * we need not look any further down the list. + */ +static void prvCheckDelayedList( void ); + +/*-----------------------------------------------------------*/ + +BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, UBaseType_t uxPriority, UBaseType_t uxIndex ) +{ +BaseType_t xReturn; +CRCB_t *pxCoRoutine; + + /* Allocate the memory that will store the co-routine control block. */ + pxCoRoutine = ( CRCB_t * ) pvPortMalloc( sizeof( CRCB_t ) ); + if( pxCoRoutine ) + { + /* If pxCurrentCoRoutine is NULL then this is the first co-routine to + be created and the co-routine data structures need initialising. */ + if( pxCurrentCoRoutine == NULL ) + { + pxCurrentCoRoutine = pxCoRoutine; + prvInitialiseCoRoutineLists(); + } + + /* Check the priority is within limits. */ + if( uxPriority >= configMAX_CO_ROUTINE_PRIORITIES ) + { + uxPriority = configMAX_CO_ROUTINE_PRIORITIES - 1; + } + + /* Fill out the co-routine control block from the function parameters. */ + pxCoRoutine->uxState = corINITIAL_STATE; + pxCoRoutine->uxPriority = uxPriority; + pxCoRoutine->uxIndex = uxIndex; + pxCoRoutine->pxCoRoutineFunction = pxCoRoutineCode; + + /* Initialise all the other co-routine control block parameters. */ + vListInitialiseItem( &( pxCoRoutine->xGenericListItem ) ); + vListInitialiseItem( &( pxCoRoutine->xEventListItem ) ); + + /* Set the co-routine control block as a link back from the ListItem_t. + This is so we can get back to the containing CRCB from a generic item + in a list. */ + listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xGenericListItem ), pxCoRoutine ); + listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xEventListItem ), pxCoRoutine ); + + /* Event lists are always in priority order. */ + listSET_LIST_ITEM_VALUE( &( pxCoRoutine->xEventListItem ), ( ( TickType_t ) configMAX_CO_ROUTINE_PRIORITIES - ( TickType_t ) uxPriority ) ); + + /* Now the co-routine has been initialised it can be added to the ready + list at the correct priority. */ + prvAddCoRoutineToReadyQueue( pxCoRoutine ); + + xReturn = pdPASS; + } + else + { + xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay, List_t *pxEventList ) +{ +TickType_t xTimeToWake; + + /* Calculate the time to wake - this may overflow but this is + not a problem. */ + xTimeToWake = xCoRoutineTickCount + xTicksToDelay; + + /* We must remove ourselves from the ready list before adding + ourselves to the blocked list as the same list item is used for + both lists. */ + ( void ) uxListRemove( ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) ); + + /* The list item will be inserted in wake time order. */ + listSET_LIST_ITEM_VALUE( &( pxCurrentCoRoutine->xGenericListItem ), xTimeToWake ); + + if( xTimeToWake < xCoRoutineTickCount ) + { + /* Wake time has overflowed. Place this item in the + overflow list. */ + vListInsert( ( List_t * ) pxOverflowDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) ); + } + else + { + /* The wake time has not overflowed, so we can use the + current block list. */ + vListInsert( ( List_t * ) pxDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) ); + } + + if( pxEventList ) + { + /* Also add the co-routine to an event list. If this is done then the + function must be called with interrupts disabled. */ + vListInsert( pxEventList, &( pxCurrentCoRoutine->xEventListItem ) ); + } +} +/*-----------------------------------------------------------*/ + +static void prvCheckPendingReadyList( void ) +{ + /* Are there any co-routines waiting to get moved to the ready list? These + are co-routines that have been readied by an ISR. The ISR cannot access + the ready lists itself. */ + while( listLIST_IS_EMPTY( &xPendingReadyCoRoutineList ) == pdFALSE ) + { + CRCB_t *pxUnblockedCRCB; + + /* The pending ready list can be accessed by an ISR. */ + portDISABLE_INTERRUPTS(); + { + pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( (&xPendingReadyCoRoutineList) ); + ( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) ); + } + portENABLE_INTERRUPTS(); + + ( void ) uxListRemove( &( pxUnblockedCRCB->xGenericListItem ) ); + prvAddCoRoutineToReadyQueue( pxUnblockedCRCB ); + } +} +/*-----------------------------------------------------------*/ + +static void prvCheckDelayedList( void ) +{ +CRCB_t *pxCRCB; + + xPassedTicks = xTaskGetTickCount() - xLastTickCount; + while( xPassedTicks ) + { + xCoRoutineTickCount++; + xPassedTicks--; + + /* If the tick count has overflowed we need to swap the ready lists. */ + if( xCoRoutineTickCount == 0 ) + { + List_t * pxTemp; + + /* Tick count has overflowed so we need to swap the delay lists. If there are + any items in pxDelayedCoRoutineList here then there is an error! */ + pxTemp = pxDelayedCoRoutineList; + pxDelayedCoRoutineList = pxOverflowDelayedCoRoutineList; + pxOverflowDelayedCoRoutineList = pxTemp; + } + + /* See if this tick has made a timeout expire. */ + while( listLIST_IS_EMPTY( pxDelayedCoRoutineList ) == pdFALSE ) + { + pxCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedCoRoutineList ); + + if( xCoRoutineTickCount < listGET_LIST_ITEM_VALUE( &( pxCRCB->xGenericListItem ) ) ) + { + /* Timeout not yet expired. */ + break; + } + + portDISABLE_INTERRUPTS(); + { + /* The event could have occurred just before this critical + section. If this is the case then the generic list item will + have been moved to the pending ready list and the following + line is still valid. Also the pvContainer parameter will have + been set to NULL so the following lines are also valid. */ + ( void ) uxListRemove( &( pxCRCB->xGenericListItem ) ); + + /* Is the co-routine waiting on an event also? */ + if( pxCRCB->xEventListItem.pvContainer ) + { + ( void ) uxListRemove( &( pxCRCB->xEventListItem ) ); + } + } + portENABLE_INTERRUPTS(); + + prvAddCoRoutineToReadyQueue( pxCRCB ); + } + } + + xLastTickCount = xCoRoutineTickCount; +} +/*-----------------------------------------------------------*/ + +void vCoRoutineSchedule( void ) +{ + /* See if any co-routines readied by events need moving to the ready lists. */ + prvCheckPendingReadyList(); + + /* See if any delayed co-routines have timed out. */ + prvCheckDelayedList(); + + /* Find the highest priority queue that contains ready co-routines. */ + while( listLIST_IS_EMPTY( &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) ) ) + { + if( uxTopCoRoutineReadyPriority == 0 ) + { + /* No more co-routines to check. */ + return; + } + --uxTopCoRoutineReadyPriority; + } + + /* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the co-routines + of the same priority get an equal share of the processor time. */ + listGET_OWNER_OF_NEXT_ENTRY( pxCurrentCoRoutine, &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) ); + + /* Call the co-routine. */ + ( pxCurrentCoRoutine->pxCoRoutineFunction )( pxCurrentCoRoutine, pxCurrentCoRoutine->uxIndex ); + + return; +} +/*-----------------------------------------------------------*/ + +static void prvInitialiseCoRoutineLists( void ) +{ +UBaseType_t uxPriority; + + for( uxPriority = 0; uxPriority < configMAX_CO_ROUTINE_PRIORITIES; uxPriority++ ) + { + vListInitialise( ( List_t * ) &( pxReadyCoRoutineLists[ uxPriority ] ) ); + } + + vListInitialise( ( List_t * ) &xDelayedCoRoutineList1 ); + vListInitialise( ( List_t * ) &xDelayedCoRoutineList2 ); + vListInitialise( ( List_t * ) &xPendingReadyCoRoutineList ); + + /* Start with pxDelayedCoRoutineList using list1 and the + pxOverflowDelayedCoRoutineList using list2. */ + pxDelayedCoRoutineList = &xDelayedCoRoutineList1; + pxOverflowDelayedCoRoutineList = &xDelayedCoRoutineList2; +} +/*-----------------------------------------------------------*/ + +BaseType_t xCoRoutineRemoveFromEventList( const List_t *pxEventList ) +{ +CRCB_t *pxUnblockedCRCB; +BaseType_t xReturn; + + /* This function is called from within an interrupt. It can only access + event lists and the pending ready list. This function assumes that a + check has already been made to ensure pxEventList is not empty. */ + pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); + ( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) ); + vListInsertEnd( ( List_t * ) &( xPendingReadyCoRoutineList ), &( pxUnblockedCRCB->xEventListItem ) ); + + if( pxUnblockedCRCB->uxPriority >= pxCurrentCoRoutine->uxPriority ) + { + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + + return xReturn; +} + diff --git a/component/os/freertos/freertos_v8.1.2/Source/event_groups.c b/component/os/freertos/freertos_v8.1.2/Source/event_groups.c new file mode 100644 index 0000000..caecbbb --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/event_groups.c @@ -0,0 +1,676 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* Standard includes. */ +#include + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +/* FreeRTOS includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "timers.h" +#include "event_groups.h" + +/* Lint e961 and e750 are suppressed as a MISRA exception justified because the +MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the +header files above, but not in this file, in order to generate the correct +privileged Vs unprivileged linkage and placement. */ +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */ + +#if ( INCLUDE_xEventGroupSetBitFromISR == 1 ) && ( configUSE_TIMERS == 0 ) + #error configUSE_TIMERS must be set to 1 to make the xEventGroupSetBitFromISR() function available. +#endif + +#if ( INCLUDE_xEventGroupSetBitFromISR == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 0 ) + #error INCLUDE_xTimerPendFunctionCall must also be set to one to make the xEventGroupSetBitFromISR() function available. +#endif + +/* The following bit fields convey control information in a task's event list +item value. It is important they don't clash with the +taskEVENT_LIST_ITEM_VALUE_IN_USE definition. */ +#if configUSE_16_BIT_TICKS == 1 + #define eventCLEAR_EVENTS_ON_EXIT_BIT 0x0100U + #define eventUNBLOCKED_DUE_TO_BIT_SET 0x0200U + #define eventWAIT_FOR_ALL_BITS 0x0400U + #define eventEVENT_BITS_CONTROL_BYTES 0xff00U +#else + #define eventCLEAR_EVENTS_ON_EXIT_BIT 0x01000000UL + #define eventUNBLOCKED_DUE_TO_BIT_SET 0x02000000UL + #define eventWAIT_FOR_ALL_BITS 0x04000000UL + #define eventEVENT_BITS_CONTROL_BYTES 0xff000000UL +#endif + +typedef struct xEventGroupDefinition +{ + EventBits_t uxEventBits; + List_t xTasksWaitingForBits; /*< List of tasks waiting for a bit to be set. */ + + #if( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxEventGroupNumber; + #endif + +} EventGroup_t; + +/*-----------------------------------------------------------*/ + +/* + * Test the bits set in uxCurrentEventBits to see if the wait condition is met. + * The wait condition is defined by xWaitForAllBits. If xWaitForAllBits is + * pdTRUE then the wait condition is met if all the bits set in uxBitsToWaitFor + * are also set in uxCurrentEventBits. If xWaitForAllBits is pdFALSE then the + * wait condition is met if any of the bits set in uxBitsToWait for are also set + * in uxCurrentEventBits. + */ +static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits ); + +/*-----------------------------------------------------------*/ + +EventGroupHandle_t xEventGroupCreate( void ) +{ +EventGroup_t *pxEventBits; + + pxEventBits = pvPortMalloc( sizeof( EventGroup_t ) ); + if( pxEventBits != NULL ) + { + pxEventBits->uxEventBits = 0; + vListInitialise( &( pxEventBits->xTasksWaitingForBits ) ); + traceEVENT_GROUP_CREATE( pxEventBits ); + } + else + { + traceEVENT_GROUP_CREATE_FAILED(); + } + + return ( EventGroupHandle_t ) pxEventBits; +} +/*-----------------------------------------------------------*/ + +EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait ) +{ +EventBits_t uxOriginalBitValue, uxReturn; +EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup; +BaseType_t xAlreadyYielded; +BaseType_t xTimeoutOccurred = pdFALSE; + + configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); + configASSERT( uxBitsToWaitFor != 0 ); + #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) + { + configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); + } + #endif + + vTaskSuspendAll(); + { + uxOriginalBitValue = pxEventBits->uxEventBits; + + ( void ) xEventGroupSetBits( xEventGroup, uxBitsToSet ); + + if( ( ( uxOriginalBitValue | uxBitsToSet ) & uxBitsToWaitFor ) == uxBitsToWaitFor ) + { + /* All the rendezvous bits are now set - no need to block. */ + uxReturn = ( uxOriginalBitValue | uxBitsToSet ); + + /* Rendezvous always clear the bits. They will have been cleared + already unless this is the only task in the rendezvous. */ + pxEventBits->uxEventBits &= ~uxBitsToWaitFor; + + xTicksToWait = 0; + } + else + { + if( xTicksToWait != ( TickType_t ) 0 ) + { + traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor ); + + /* Store the bits that the calling task is waiting for in the + task's event list item so the kernel knows when a match is + found. Then enter the blocked state. */ + vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | eventCLEAR_EVENTS_ON_EXIT_BIT | eventWAIT_FOR_ALL_BITS ), xTicksToWait ); + + /* This assignment is obsolete as uxReturn will get set after + the task unblocks, but some compilers mistakenly generate a + warning about uxReturn being returned without being set if the + assignment is omitted. */ + uxReturn = 0; + } + else + { + /* The rendezvous bits were not set, but no block time was + specified - just return the current event bit value. */ + uxReturn = pxEventBits->uxEventBits; + } + } + } + xAlreadyYielded = xTaskResumeAll(); + + if( xTicksToWait != ( TickType_t ) 0 ) + { + if( xAlreadyYielded == pdFALSE ) + { + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* The task blocked to wait for its required bits to be set - at this + point either the required bits were set or the block time expired. If + the required bits were set they will have been stored in the task's + event list item, and they should now be retrieved then cleared. */ + uxReturn = uxTaskResetEventItemValue(); + + if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 ) + { + /* The task timed out, just return the current event bit value. */ + taskENTER_CRITICAL(); + { + uxReturn = pxEventBits->uxEventBits; + + /* Although the task got here because it timed out before the + bits it was waiting for were set, it is possible that since it + unblocked another task has set the bits. If this is the case + then it needs to clear the bits before exiting. */ + if( ( uxReturn & uxBitsToWaitFor ) == uxBitsToWaitFor ) + { + pxEventBits->uxEventBits &= ~uxBitsToWaitFor; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + taskEXIT_CRITICAL(); + + xTimeoutOccurred = pdTRUE; + } + else + { + /* The task unblocked because the bits were set. */ + } + + /* Control bits might be set as the task had blocked should not be + returned. */ + uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES; + } + + traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred ); + + return uxReturn; +} +/*-----------------------------------------------------------*/ + +EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait ) +{ +EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup; +EventBits_t uxReturn, uxControlBits = 0; +BaseType_t xWaitConditionMet, xAlreadyYielded; +BaseType_t xTimeoutOccurred = pdFALSE; + + /* Check the user is not attempting to wait on the bits used by the kernel + itself, and that at least one bit is being requested. */ + configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); + configASSERT( uxBitsToWaitFor != 0 ); + #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) + { + configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); + } + #endif + + vTaskSuspendAll(); + { + const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits; + + /* Check to see if the wait condition is already met or not. */ + xWaitConditionMet = prvTestWaitCondition( uxCurrentEventBits, uxBitsToWaitFor, xWaitForAllBits ); + + if( xWaitConditionMet != pdFALSE ) + { + /* The wait condition has already been met so there is no need to + block. */ + uxReturn = uxCurrentEventBits; + xTicksToWait = ( TickType_t ) 0; + + /* Clear the wait bits if requested to do so. */ + if( xClearOnExit != pdFALSE ) + { + pxEventBits->uxEventBits &= ~uxBitsToWaitFor; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else if( xTicksToWait == ( TickType_t ) 0 ) + { + /* The wait condition has not been met, but no block time was + specified, so just return the current value. */ + uxReturn = uxCurrentEventBits; + } + else + { + /* The task is going to block to wait for its required bits to be + set. uxControlBits are used to remember the specified behaviour of + this call to xEventGroupWaitBits() - for use when the event bits + unblock the task. */ + if( xClearOnExit != pdFALSE ) + { + uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + if( xWaitForAllBits != pdFALSE ) + { + uxControlBits |= eventWAIT_FOR_ALL_BITS; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Store the bits that the calling task is waiting for in the + task's event list item so the kernel knows when a match is + found. Then enter the blocked state. */ + vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait ); + + /* This is obsolete as it will get set after the task unblocks, but + some compilers mistakenly generate a warning about the variable + being returned without being set if it is not done. */ + uxReturn = 0; + + traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor ); + } + } + xAlreadyYielded = xTaskResumeAll(); + + if( xTicksToWait != ( TickType_t ) 0 ) + { + if( xAlreadyYielded == pdFALSE ) + { + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* The task blocked to wait for its required bits to be set - at this + point either the required bits were set or the block time expired. If + the required bits were set they will have been stored in the task's + event list item, and they should now be retrieved then cleared. */ + uxReturn = uxTaskResetEventItemValue(); + + if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 ) + { + taskENTER_CRITICAL(); + { + /* The task timed out, just return the current event bit value. */ + uxReturn = pxEventBits->uxEventBits; + + /* It is possible that the event bits were updated between this + task leaving the Blocked state and running again. */ + if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE ) + { + if( xClearOnExit != pdFALSE ) + { + pxEventBits->uxEventBits &= ~uxBitsToWaitFor; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + taskEXIT_CRITICAL(); + + /* Prevent compiler warnings when trace macros are not used. */ + xTimeoutOccurred = pdFALSE; + } + else + { + /* The task unblocked because the bits were set. */ + } + + /* The task blocked so control bits may have been set. */ + uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES; + } + traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred ); + + return uxReturn; +} +/*-----------------------------------------------------------*/ + +EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ) +{ +EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup; +EventBits_t uxReturn; + + /* Check the user is not attempting to clear the bits used by the kernel + itself. */ + configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); + + taskENTER_CRITICAL(); + { + traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear ); + + /* The value returned is the event group value prior to the bits being + cleared. */ + uxReturn = pxEventBits->uxEventBits; + + /* Clear the bits. */ + pxEventBits->uxEventBits &= ~uxBitsToClear; + } + taskEXIT_CRITICAL(); + + return uxReturn; +} +/*-----------------------------------------------------------*/ + +#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) + + BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ) + { + BaseType_t xReturn; + + traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear ); + xReturn = xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL ); + + return xReturn; + } + +#endif +/*-----------------------------------------------------------*/ + +EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ) +{ +UBaseType_t uxSavedInterruptStatus; +EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup; +EventBits_t uxReturn; + + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + { + uxReturn = pxEventBits->uxEventBits; + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + + return uxReturn; +} +/*-----------------------------------------------------------*/ + +EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ) +{ +ListItem_t *pxListItem, *pxNext; +ListItem_t const *pxListEnd; +List_t *pxList; +EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits; +EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup; +BaseType_t xMatchFound = pdFALSE; + + /* Check the user is not attempting to set the bits used by the kernel + itself. */ + configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); + + pxList = &( pxEventBits->xTasksWaitingForBits ); + pxListEnd = listGET_END_MARKER( pxList ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */ + vTaskSuspendAll(); + { + traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet ); + + pxListItem = listGET_HEAD_ENTRY( pxList ); + + /* Set the bits. */ + pxEventBits->uxEventBits |= uxBitsToSet; + + /* See if the new bit value should unblock any tasks. */ + while( pxListItem != pxListEnd ) + { + pxNext = listGET_NEXT( pxListItem ); + uxBitsWaitedFor = listGET_LIST_ITEM_VALUE( pxListItem ); + xMatchFound = pdFALSE; + + /* Split the bits waited for from the control bits. */ + uxControlBits = uxBitsWaitedFor & eventEVENT_BITS_CONTROL_BYTES; + uxBitsWaitedFor &= ~eventEVENT_BITS_CONTROL_BYTES; + + if( ( uxControlBits & eventWAIT_FOR_ALL_BITS ) == ( EventBits_t ) 0 ) + { + /* Just looking for single bit being set. */ + if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) != ( EventBits_t ) 0 ) + { + xMatchFound = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) == uxBitsWaitedFor ) + { + /* All bits are set. */ + xMatchFound = pdTRUE; + } + else + { + /* Need all bits to be set, but not all the bits were set. */ + } + + if( xMatchFound != pdFALSE ) + { + /* The bits match. Should the bits be cleared on exit? */ + if( ( uxControlBits & eventCLEAR_EVENTS_ON_EXIT_BIT ) != ( EventBits_t ) 0 ) + { + uxBitsToClear |= uxBitsWaitedFor; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Store the actual event flag value in the task's event list + item before removing the task from the event list. The + eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows + that is was unblocked due to its required bits matching, rather + than because it timed out. */ + ( void ) xTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET ); + } + + /* Move onto the next list item. Note pxListItem->pxNext is not + used here as the list item may have been removed from the event list + and inserted into the ready/pending reading list. */ + pxListItem = pxNext; + } + + /* Clear any bits that matched when the eventCLEAR_EVENTS_ON_EXIT_BIT + bit was set in the control word. */ + pxEventBits->uxEventBits &= ~uxBitsToClear; + } + ( void ) xTaskResumeAll(); + + return pxEventBits->uxEventBits; +} +/*-----------------------------------------------------------*/ + +void vEventGroupDelete( EventGroupHandle_t xEventGroup ) +{ +EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup; +const List_t *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits ); + + vTaskSuspendAll(); + { + traceEVENT_GROUP_DELETE( xEventGroup ); + + while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 ) + { + /* Unblock the task, returning 0 as the event list is being deleted + and cannot therefore have any bits set. */ + configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) ); + ( void ) xTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET ); + } + + vPortFree( pxEventBits ); + } + ( void ) xTaskResumeAll(); +} +/*-----------------------------------------------------------*/ + +/* For internal use only - execute a 'set bits' command that was pended from +an interrupt. */ +void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet ) +{ + ( void ) xEventGroupSetBits( pvEventGroup, ( EventBits_t ) ulBitsToSet ); +} +/*-----------------------------------------------------------*/ + +/* For internal use only - execute a 'clear bits' command that was pended from +an interrupt. */ +void vEventGroupClearBitsCallback( void *pvEventGroup, const uint32_t ulBitsToClear ) +{ + ( void ) xEventGroupClearBits( pvEventGroup, ( EventBits_t ) ulBitsToClear ); +} +/*-----------------------------------------------------------*/ + +static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits ) +{ +BaseType_t xWaitConditionMet = pdFALSE; + + if( xWaitForAllBits == pdFALSE ) + { + /* Task only has to wait for one bit within uxBitsToWaitFor to be + set. Is one already set? */ + if( ( uxCurrentEventBits & uxBitsToWaitFor ) != ( EventBits_t ) 0 ) + { + xWaitConditionMet = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* Task has to wait for all the bits in uxBitsToWaitFor to be set. + Are they set already? */ + if( ( uxCurrentEventBits & uxBitsToWaitFor ) == uxBitsToWaitFor ) + { + xWaitConditionMet = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + return xWaitConditionMet; +} +/*-----------------------------------------------------------*/ + +#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) + + BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken ) + { + BaseType_t xReturn; + + traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet ); + xReturn = xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken ); + + return xReturn; + } + +#endif +/*-----------------------------------------------------------*/ + +#if (configUSE_TRACE_FACILITY == 1) + + UBaseType_t uxEventGroupGetNumber( void* xEventGroup ) + { + UBaseType_t xReturn; + EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup; + + if( xEventGroup == NULL ) + { + xReturn = 0; + } + else + { + xReturn = pxEventBits->uxEventGroupNumber; + } + + return xReturn; + } + +#endif + diff --git a/component/os/freertos/freertos_v8.1.2/Source/include/FreeRTOS.h b/component/os/freertos/freertos_v8.1.2/Source/include/FreeRTOS.h new file mode 100644 index 0000000..eaa41cb --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/include/FreeRTOS.h @@ -0,0 +1,762 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef INC_FREERTOS_H +#define INC_FREERTOS_H + +/* + * Include the generic headers required for the FreeRTOS port being used. + */ +#include + +/* + * If stdint.h cannot be located then: + * + If using GCC ensure the -nostdint options is *not* being used. + * + Ensure the project's include path includes the directory in which your + * compiler stores stdint.h. + * + Set any compiler options necessary for it to support C99, as technically + * stdint.h is only mandatory with C99 (FreeRTOS does not require C99 in any + * other way). + * + The FreeRTOS download includes a simple stdint.h definition that can be + * used in cases where none is provided by the compiler. The files only + * contains the typedefs required to build FreeRTOS. Read the instructions + * in FreeRTOS/source/stdint.readme for more information. + */ +#include /* READ COMMENT ABOVE. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Application specific configuration options. */ +#include "FreeRTOSConfig.h" + +/* Basic FreeRTOS definitions. */ +#include "projdefs.h" + +/* Definitions specific to the port being used. */ +#include "portable.h" + +/* + * Check all the required application specific macros have been defined. + * These macros are application specific and (as downloaded) are defined + * within FreeRTOSConfig.h. + */ + +#ifndef configMINIMAL_STACK_SIZE + #error Missing definition: configMINIMAL_STACK_SIZE must be defined in FreeRTOSConfig.h. configMINIMAL_STACK_SIZE defines the size (in words) of the stack allocated to the idle task. Refer to the demo project provided for your port for a suitable value. +#endif + +#ifndef configMAX_PRIORITIES + #error Missing definition: configMAX_PRIORITIES must be defined in FreeRTOSConfig.h. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef configUSE_PREEMPTION + #error Missing definition: configUSE_PREEMPTION must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef configUSE_IDLE_HOOK + #error Missing definition: configUSE_IDLE_HOOK must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef configUSE_TICK_HOOK + #error Missing definition: configUSE_TICK_HOOK must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef configUSE_CO_ROUTINES + #error Missing definition: configUSE_CO_ROUTINES must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef INCLUDE_vTaskPrioritySet + #error Missing definition: INCLUDE_vTaskPrioritySet must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef INCLUDE_uxTaskPriorityGet + #error Missing definition: INCLUDE_uxTaskPriorityGet must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef INCLUDE_vTaskDelete + #error Missing definition: INCLUDE_vTaskDelete must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef INCLUDE_vTaskSuspend + #error Missing definition: INCLUDE_vTaskSuspend must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef INCLUDE_vTaskDelayUntil + #error Missing definition: INCLUDE_vTaskDelayUntil must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef INCLUDE_vTaskDelay + #error Missing definition: INCLUDE_vTaskDelay must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef configUSE_16_BIT_TICKS + #error Missing definition: configUSE_16_BIT_TICKS must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#if configUSE_CO_ROUTINES != 0 + #ifndef configMAX_CO_ROUTINE_PRIORITIES + #error configMAX_CO_ROUTINE_PRIORITIES must be greater than or equal to 1. + #endif +#endif + +#ifndef configMAX_PRIORITIES + #error configMAX_PRIORITIES must be defined to be greater than or equal to 1. +#endif + +#ifndef INCLUDE_xTaskGetIdleTaskHandle + #define INCLUDE_xTaskGetIdleTaskHandle 0 +#endif + +#ifndef INCLUDE_xTimerGetTimerDaemonTaskHandle + #define INCLUDE_xTimerGetTimerDaemonTaskHandle 0 +#endif + +#ifndef INCLUDE_xQueueGetMutexHolder + #define INCLUDE_xQueueGetMutexHolder 0 +#endif + +#ifndef INCLUDE_xSemaphoreGetMutexHolder + #define INCLUDE_xSemaphoreGetMutexHolder INCLUDE_xQueueGetMutexHolder +#endif + +#ifndef INCLUDE_pcTaskGetTaskName + #define INCLUDE_pcTaskGetTaskName 0 +#endif + +#ifndef configUSE_APPLICATION_TASK_TAG + #define configUSE_APPLICATION_TASK_TAG 0 +#endif + +#ifndef INCLUDE_uxTaskGetStackHighWaterMark + #define INCLUDE_uxTaskGetStackHighWaterMark 0 +#endif + +#ifndef INCLUDE_eTaskGetState + #define INCLUDE_eTaskGetState 0 +#endif + +#ifndef configUSE_RECURSIVE_MUTEXES + #define configUSE_RECURSIVE_MUTEXES 0 +#endif + +#ifndef configUSE_MUTEXES + #define configUSE_MUTEXES 0 +#endif + +#ifndef configUSE_TIMERS + #define configUSE_TIMERS 0 +#endif + +#ifndef configUSE_COUNTING_SEMAPHORES + #define configUSE_COUNTING_SEMAPHORES 0 +#endif + +#ifndef configUSE_ALTERNATIVE_API + #define configUSE_ALTERNATIVE_API 0 +#endif + +#ifndef portCRITICAL_NESTING_IN_TCB + #define portCRITICAL_NESTING_IN_TCB 0 +#endif + +#ifndef configMAX_TASK_NAME_LEN + #define configMAX_TASK_NAME_LEN 16 +#endif + +#ifndef configIDLE_SHOULD_YIELD + #define configIDLE_SHOULD_YIELD 1 +#endif + +#if configMAX_TASK_NAME_LEN < 1 + #error configMAX_TASK_NAME_LEN must be set to a minimum of 1 in FreeRTOSConfig.h +#endif + +#ifndef INCLUDE_xTaskResumeFromISR + #define INCLUDE_xTaskResumeFromISR 1 +#endif + +#ifndef INCLUDE_xEventGroupSetBitFromISR + #define INCLUDE_xEventGroupSetBitFromISR 0 +#endif + +#ifndef INCLUDE_xTimerPendFunctionCall + #define INCLUDE_xTimerPendFunctionCall 0 +#endif + +#ifndef configASSERT + #define configASSERT( x ) + #define configASSERT_DEFINED 0 +#else + #define configASSERT_DEFINED 1 +#endif + +/* The timers module relies on xTaskGetSchedulerState(). */ +#if configUSE_TIMERS == 1 + + #ifndef configTIMER_TASK_PRIORITY + #error If configUSE_TIMERS is set to 1 then configTIMER_TASK_PRIORITY must also be defined. + #endif /* configTIMER_TASK_PRIORITY */ + + #ifndef configTIMER_QUEUE_LENGTH + #error If configUSE_TIMERS is set to 1 then configTIMER_QUEUE_LENGTH must also be defined. + #endif /* configTIMER_QUEUE_LENGTH */ + + #ifndef configTIMER_TASK_STACK_DEPTH + #error If configUSE_TIMERS is set to 1 then configTIMER_TASK_STACK_DEPTH must also be defined. + #endif /* configTIMER_TASK_STACK_DEPTH */ + +#endif /* configUSE_TIMERS */ + +#ifndef INCLUDE_xTaskGetSchedulerState + #define INCLUDE_xTaskGetSchedulerState 0 +#endif + +#ifndef INCLUDE_xTaskGetCurrentTaskHandle + #define INCLUDE_xTaskGetCurrentTaskHandle 0 +#endif + + +#ifndef portSET_INTERRUPT_MASK_FROM_ISR + #define portSET_INTERRUPT_MASK_FROM_ISR() 0 +#endif + +#ifndef portCLEAR_INTERRUPT_MASK_FROM_ISR + #define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) ( void ) uxSavedStatusValue +#endif + +#ifndef portCLEAN_UP_TCB + #define portCLEAN_UP_TCB( pxTCB ) ( void ) pxTCB +#endif + +#ifndef portPRE_TASK_DELETE_HOOK + #define portPRE_TASK_DELETE_HOOK( pvTaskToDelete, pxYieldPending ) +#endif + +#ifndef portSETUP_TCB + #define portSETUP_TCB( pxTCB ) ( void ) pxTCB +#endif + +#ifndef configQUEUE_REGISTRY_SIZE + #define configQUEUE_REGISTRY_SIZE 0U +#endif + +#if ( configQUEUE_REGISTRY_SIZE < 1 ) + #define vQueueAddToRegistry( xQueue, pcName ) + #define vQueueUnregisterQueue( xQueue ) +#endif + +#ifndef portPOINTER_SIZE_TYPE + #define portPOINTER_SIZE_TYPE uint32_t +#endif + +/* Remove any unused trace macros. */ +#ifndef traceSTART + /* Used to perform any necessary initialisation - for example, open a file + into which trace is to be written. */ + #define traceSTART() +#endif + +#ifndef traceEND + /* Use to close a trace, for example close a file into which trace has been + written. */ + #define traceEND() +#endif + +#ifndef traceTASK_SWITCHED_IN + /* Called after a task has been selected to run. pxCurrentTCB holds a pointer + to the task control block of the selected task. */ + #define traceTASK_SWITCHED_IN() +#endif + +#ifndef traceINCREASE_TICK_COUNT + /* Called before stepping the tick count after waking from tickless idle + sleep. */ + #define traceINCREASE_TICK_COUNT( x ) +#endif + +#ifndef traceLOW_POWER_IDLE_BEGIN + /* Called immediately before entering tickless idle. */ + #define traceLOW_POWER_IDLE_BEGIN() +#endif + +#ifndef traceLOW_POWER_IDLE_END + /* Called when returning to the Idle task after a tickless idle. */ + #define traceLOW_POWER_IDLE_END() +#endif + +#ifndef traceTASK_SWITCHED_OUT + /* Called before a task has been selected to run. pxCurrentTCB holds a pointer + to the task control block of the task being switched out. */ + #define traceTASK_SWITCHED_OUT() +#endif + +#ifndef traceTASK_PRIORITY_INHERIT + /* Called when a task attempts to take a mutex that is already held by a + lower priority task. pxTCBOfMutexHolder is a pointer to the TCB of the task + that holds the mutex. uxInheritedPriority is the priority the mutex holder + will inherit (the priority of the task that is attempting to obtain the + muted. */ + #define traceTASK_PRIORITY_INHERIT( pxTCBOfMutexHolder, uxInheritedPriority ) +#endif + +#ifndef traceTASK_PRIORITY_DISINHERIT + /* Called when a task releases a mutex, the holding of which had resulted in + the task inheriting the priority of a higher priority task. + pxTCBOfMutexHolder is a pointer to the TCB of the task that is releasing the + mutex. uxOriginalPriority is the task's configured (base) priority. */ + #define traceTASK_PRIORITY_DISINHERIT( pxTCBOfMutexHolder, uxOriginalPriority ) +#endif + +#ifndef traceBLOCKING_ON_QUEUE_RECEIVE + /* Task is about to block because it cannot read from a + queue/mutex/semaphore. pxQueue is a pointer to the queue/mutex/semaphore + upon which the read was attempted. pxCurrentTCB points to the TCB of the + task that attempted the read. */ + #define traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ) +#endif + +#ifndef traceBLOCKING_ON_QUEUE_SEND + /* Task is about to block because it cannot write to a + queue/mutex/semaphore. pxQueue is a pointer to the queue/mutex/semaphore + upon which the write was attempted. pxCurrentTCB points to the TCB of the + task that attempted the write. */ + #define traceBLOCKING_ON_QUEUE_SEND( pxQueue ) +#endif + +#ifndef configCHECK_FOR_STACK_OVERFLOW + #define configCHECK_FOR_STACK_OVERFLOW 0 +#endif + +/* The following event macros are embedded in the kernel API calls. */ + +#ifndef traceMOVED_TASK_TO_READY_STATE + #define traceMOVED_TASK_TO_READY_STATE( pxTCB ) +#endif + +#ifndef traceQUEUE_CREATE + #define traceQUEUE_CREATE( pxNewQueue ) +#endif + +#ifndef traceQUEUE_CREATE_FAILED + #define traceQUEUE_CREATE_FAILED( ucQueueType ) +#endif + +#ifndef traceCREATE_MUTEX + #define traceCREATE_MUTEX( pxNewQueue ) +#endif + +#ifndef traceCREATE_MUTEX_FAILED + #define traceCREATE_MUTEX_FAILED() +#endif + +#ifndef traceGIVE_MUTEX_RECURSIVE + #define traceGIVE_MUTEX_RECURSIVE( pxMutex ) +#endif + +#ifndef traceGIVE_MUTEX_RECURSIVE_FAILED + #define traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex ) +#endif + +#ifndef traceTAKE_MUTEX_RECURSIVE + #define traceTAKE_MUTEX_RECURSIVE( pxMutex ) +#endif + +#ifndef traceTAKE_MUTEX_RECURSIVE_FAILED + #define traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex ) +#endif + +#ifndef traceCREATE_COUNTING_SEMAPHORE + #define traceCREATE_COUNTING_SEMAPHORE() +#endif + +#ifndef traceCREATE_COUNTING_SEMAPHORE_FAILED + #define traceCREATE_COUNTING_SEMAPHORE_FAILED() +#endif + +#ifndef traceQUEUE_SEND + #define traceQUEUE_SEND( pxQueue ) +#endif + +#ifndef traceQUEUE_SEND_FAILED + #define traceQUEUE_SEND_FAILED( pxQueue ) +#endif + +#ifndef traceQUEUE_RECEIVE + #define traceQUEUE_RECEIVE( pxQueue ) +#endif + +#ifndef traceQUEUE_PEEK + #define traceQUEUE_PEEK( pxQueue ) +#endif + +#ifndef traceQUEUE_PEEK_FROM_ISR + #define traceQUEUE_PEEK_FROM_ISR( pxQueue ) +#endif + +#ifndef traceQUEUE_RECEIVE_FAILED + #define traceQUEUE_RECEIVE_FAILED( pxQueue ) +#endif + +#ifndef traceQUEUE_SEND_FROM_ISR + #define traceQUEUE_SEND_FROM_ISR( pxQueue ) +#endif + +#ifndef traceQUEUE_SEND_FROM_ISR_FAILED + #define traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ) +#endif + +#ifndef traceQUEUE_RECEIVE_FROM_ISR + #define traceQUEUE_RECEIVE_FROM_ISR( pxQueue ) +#endif + +#ifndef traceQUEUE_RECEIVE_FROM_ISR_FAILED + #define traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue ) +#endif + +#ifndef traceQUEUE_PEEK_FROM_ISR_FAILED + #define traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue ) +#endif + +#ifndef traceQUEUE_DELETE + #define traceQUEUE_DELETE( pxQueue ) +#endif + +#ifndef traceTASK_CREATE + #define traceTASK_CREATE( pxNewTCB ) +#endif + +#ifndef traceTASK_CREATE_FAILED + #define traceTASK_CREATE_FAILED() +#endif + +#ifndef traceTASK_DELETE + #define traceTASK_DELETE( pxTaskToDelete ) +#endif + +#ifndef traceTASK_DELAY_UNTIL + #define traceTASK_DELAY_UNTIL() +#endif + +#ifndef traceTASK_DELAY + #define traceTASK_DELAY() +#endif + +#ifndef traceTASK_PRIORITY_SET + #define traceTASK_PRIORITY_SET( pxTask, uxNewPriority ) +#endif + +#ifndef traceTASK_SUSPEND + #define traceTASK_SUSPEND( pxTaskToSuspend ) +#endif + +#ifndef traceTASK_RESUME + #define traceTASK_RESUME( pxTaskToResume ) +#endif + +#ifndef traceTASK_RESUME_FROM_ISR + #define traceTASK_RESUME_FROM_ISR( pxTaskToResume ) +#endif + +#ifndef traceTASK_INCREMENT_TICK + #define traceTASK_INCREMENT_TICK( xTickCount ) +#endif + +#ifndef traceTIMER_CREATE + #define traceTIMER_CREATE( pxNewTimer ) +#endif + +#ifndef traceTIMER_CREATE_FAILED + #define traceTIMER_CREATE_FAILED() +#endif + +#ifndef traceTIMER_COMMAND_SEND + #define traceTIMER_COMMAND_SEND( xTimer, xMessageID, xMessageValueValue, xReturn ) +#endif + +#ifndef traceTIMER_EXPIRED + #define traceTIMER_EXPIRED( pxTimer ) +#endif + +#ifndef traceTIMER_COMMAND_RECEIVED + #define traceTIMER_COMMAND_RECEIVED( pxTimer, xMessageID, xMessageValue ) +#endif + +#ifndef traceMALLOC + #define traceMALLOC( pvAddress, uiSize ) +#endif + +#ifndef traceFREE + #define traceFREE( pvAddress, uiSize ) +#endif + +#ifndef traceEVENT_GROUP_CREATE + #define traceEVENT_GROUP_CREATE( xEventGroup ) +#endif + +#ifndef traceEVENT_GROUP_CREATE_FAILED + #define traceEVENT_GROUP_CREATE_FAILED() +#endif + +#ifndef traceEVENT_GROUP_SYNC_BLOCK + #define traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor ) +#endif + +#ifndef traceEVENT_GROUP_SYNC_END + #define traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred ) ( void ) xTimeoutOccurred +#endif + +#ifndef traceEVENT_GROUP_WAIT_BITS_BLOCK + #define traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor ) +#endif + +#ifndef traceEVENT_GROUP_WAIT_BITS_END + #define traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred ) ( void ) xTimeoutOccurred +#endif + +#ifndef traceEVENT_GROUP_CLEAR_BITS + #define traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear ) +#endif + +#ifndef traceEVENT_GROUP_CLEAR_BITS_FROM_ISR + #define traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear ) +#endif + +#ifndef traceEVENT_GROUP_SET_BITS + #define traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet ) +#endif + +#ifndef traceEVENT_GROUP_SET_BITS_FROM_ISR + #define traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet ) +#endif + +#ifndef traceEVENT_GROUP_DELETE + #define traceEVENT_GROUP_DELETE( xEventGroup ) +#endif + +#ifndef tracePEND_FUNC_CALL + #define tracePEND_FUNC_CALL(xFunctionToPend, pvParameter1, ulParameter2, ret) +#endif + +#ifndef tracePEND_FUNC_CALL_FROM_ISR + #define tracePEND_FUNC_CALL_FROM_ISR(xFunctionToPend, pvParameter1, ulParameter2, ret) +#endif + +#ifndef traceQUEUE_REGISTRY_ADD + #define traceQUEUE_REGISTRY_ADD(xQueue, pcQueueName) +#endif + +#ifndef configGENERATE_RUN_TIME_STATS + #define configGENERATE_RUN_TIME_STATS 0 +#endif + +#if ( configGENERATE_RUN_TIME_STATS == 1 ) + + #ifndef configUSE_STATS_FORMATTING_FUNCTIONS + #define configUSE_STATS_FORMATTING_FUNCTIONS 1 + #endif + + #ifndef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS + #error If configGENERATE_RUN_TIME_STATS is defined then portCONFIGURE_TIMER_FOR_RUN_TIME_STATS must also be defined. portCONFIGURE_TIMER_FOR_RUN_TIME_STATS should call a port layer function to setup a peripheral timer/counter that can then be used as the run time counter time base. + #endif /* portCONFIGURE_TIMER_FOR_RUN_TIME_STATS */ + + #ifndef portGET_RUN_TIME_COUNTER_VALUE + #ifndef portALT_GET_RUN_TIME_COUNTER_VALUE + #error If configGENERATE_RUN_TIME_STATS is defined then either portGET_RUN_TIME_COUNTER_VALUE or portALT_GET_RUN_TIME_COUNTER_VALUE must also be defined. See the examples provided and the FreeRTOS web site for more information. + #endif /* portALT_GET_RUN_TIME_COUNTER_VALUE */ + #endif /* portGET_RUN_TIME_COUNTER_VALUE */ + +#endif /* configGENERATE_RUN_TIME_STATS */ + +#ifndef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS + #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() +#endif + +#ifndef configUSE_MALLOC_FAILED_HOOK + #define configUSE_MALLOC_FAILED_HOOK 0 +#endif + +#ifndef portPRIVILEGE_BIT + #define portPRIVILEGE_BIT ( ( UBaseType_t ) 0x00 ) +#endif + +#ifndef portYIELD_WITHIN_API + #define portYIELD_WITHIN_API portYIELD +#endif + +#ifndef pvPortMallocAligned + #define pvPortMallocAligned( x, puxStackBuffer ) ( ( ( puxStackBuffer ) == NULL ) ? ( pvPortMalloc( ( x ) ) ) : ( puxStackBuffer ) ) +#endif + +#ifndef vPortFreeAligned + #define vPortFreeAligned( pvBlockToFree ) vPortFree( pvBlockToFree ) +#endif + +#ifndef portSUPPRESS_TICKS_AND_SLEEP + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) +#endif + +#ifndef configEXPECTED_IDLE_TIME_BEFORE_SLEEP + #define configEXPECTED_IDLE_TIME_BEFORE_SLEEP 2 +#endif + +#if configEXPECTED_IDLE_TIME_BEFORE_SLEEP < 2 + #error configEXPECTED_IDLE_TIME_BEFORE_SLEEP must not be less than 2 +#endif + +#ifndef configUSE_TICKLESS_IDLE + #define configUSE_TICKLESS_IDLE 0 +#endif + +#ifndef configPRE_SLEEP_PROCESSING + #define configPRE_SLEEP_PROCESSING( x ) +#endif + +#ifndef configPOST_SLEEP_PROCESSING + #define configPOST_SLEEP_PROCESSING( x ) +#endif + +#ifndef configUSE_QUEUE_SETS + #define configUSE_QUEUE_SETS 0 +#endif + +#ifndef portTASK_USES_FLOATING_POINT + #define portTASK_USES_FLOATING_POINT() +#endif + +#ifndef configUSE_TIME_SLICING + #define configUSE_TIME_SLICING 1 +#endif + +#ifndef configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS + #define configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS 0 +#endif + +#ifndef configUSE_NEWLIB_REENTRANT + #define configUSE_NEWLIB_REENTRANT 0 +#endif + +#ifndef configUSE_STATS_FORMATTING_FUNCTIONS + #define configUSE_STATS_FORMATTING_FUNCTIONS 0 +#endif + +#ifndef portASSERT_IF_INTERRUPT_PRIORITY_INVALID + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() +#endif + +#ifndef configUSE_TRACE_FACILITY + #define configUSE_TRACE_FACILITY 0 +#endif + +#ifndef mtCOVERAGE_TEST_MARKER + #define mtCOVERAGE_TEST_MARKER() +#endif + +#ifndef portASSERT_IF_IN_ISR + #define portASSERT_IF_IN_ISR() +#endif + +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#endif + +/* Definitions to allow backward compatibility with FreeRTOS versions prior to +V8 if desired. */ +#ifndef configENABLE_BACKWARD_COMPATIBILITY + #define configENABLE_BACKWARD_COMPATIBILITY 1 +#endif + +#if configENABLE_BACKWARD_COMPATIBILITY == 1 + #define eTaskStateGet eTaskGetState + #define portTickType TickType_t + #define xTaskHandle TaskHandle_t + #define xQueueHandle QueueHandle_t + #define xSemaphoreHandle SemaphoreHandle_t + #define xQueueSetHandle QueueSetHandle_t + #define xQueueSetMemberHandle QueueSetMemberHandle_t + #define xTimeOutType TimeOut_t + #define xMemoryRegion MemoryRegion_t + #define xTaskParameters TaskParameters_t + #define xTaskStatusType TaskStatus_t + #define xTimerHandle TimerHandle_t + #define xCoRoutineHandle CoRoutineHandle_t + #define pdTASK_HOOK_CODE TaskHookFunction_t + #define portTICK_RATE_MS portTICK_PERIOD_MS + + /* Backward compatibility within the scheduler code only - these definitions + are not really required but are included for completeness. */ + #define tmrTIMER_CALLBACK TimerCallbackFunction_t + #define pdTASK_CODE TaskFunction_t + #define xListItem ListItem_t + #define xList List_t +#endif /* configENABLE_BACKWARD_COMPATIBILITY */ + +#ifdef __cplusplus +} +#endif + +#endif /* INC_FREERTOS_H */ + diff --git a/component/os/freertos/freertos_v8.1.2/Source/include/StackMacros.h b/component/os/freertos/freertos_v8.1.2/Source/include/StackMacros.h new file mode 100644 index 0000000..c7cfb28 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/include/StackMacros.h @@ -0,0 +1,180 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef STACK_MACROS_H +#define STACK_MACROS_H + +/* + * Call the stack overflow hook function if the stack of the task being swapped + * out is currently overflowed, or looks like it might have overflowed in the + * past. + * + * Setting configCHECK_FOR_STACK_OVERFLOW to 1 will cause the macro to check + * the current stack state only - comparing the current top of stack value to + * the stack limit. Setting configCHECK_FOR_STACK_OVERFLOW to greater than 1 + * will also cause the last few stack bytes to be checked to ensure the value + * to which the bytes were set when the task was created have not been + * overwritten. Note this second test does not guarantee that an overflowed + * stack will always be recognised. + */ + +/*-----------------------------------------------------------*/ + +#if( configCHECK_FOR_STACK_OVERFLOW == 0 ) + + /* FreeRTOSConfig.h is not set to check for stack overflows. */ + #define taskFIRST_CHECK_FOR_STACK_OVERFLOW() + #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() + +#endif /* configCHECK_FOR_STACK_OVERFLOW == 0 */ +/*-----------------------------------------------------------*/ + +#if( configCHECK_FOR_STACK_OVERFLOW == 1 ) + + /* FreeRTOSConfig.h is only set to use the first method of + overflow checking. */ + #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() + +#endif +/*-----------------------------------------------------------*/ + +#if( ( configCHECK_FOR_STACK_OVERFLOW > 0 ) && ( portSTACK_GROWTH < 0 ) ) + + /* Only the current stack state is to be checked. */ + #define taskFIRST_CHECK_FOR_STACK_OVERFLOW() \ + { \ + /* Is the currently saved stack pointer within the stack limit? */ \ + if( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack ) \ + { \ + vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ + } \ + } + +#endif /* configCHECK_FOR_STACK_OVERFLOW > 0 */ +/*-----------------------------------------------------------*/ + +#if( ( configCHECK_FOR_STACK_OVERFLOW > 0 ) && ( portSTACK_GROWTH > 0 ) ) + + /* Only the current stack state is to be checked. */ + #define taskFIRST_CHECK_FOR_STACK_OVERFLOW() \ + { \ + \ + /* Is the currently saved stack pointer within the stack limit? */ \ + if( pxCurrentTCB->pxTopOfStack >= pxCurrentTCB->pxEndOfStack ) \ + { \ + vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ + } \ + } + +#endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */ +/*-----------------------------------------------------------*/ + +#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH < 0 ) ) + + #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() \ + { \ + static const uint8_t ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \ + \ + \ + /* Has the extremity of the task stack ever been written over? */ \ + if( memcmp( ( void * ) pxCurrentTCB->pxStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \ + { \ + vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ + } \ + } + +#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */ +/*-----------------------------------------------------------*/ + +#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH > 0 ) ) + + #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() \ + { \ + int8_t *pcEndOfStack = ( int8_t * ) pxCurrentTCB->pxEndOfStack; \ + static const uint8_t ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \ + \ + \ + pcEndOfStack -= sizeof( ucExpectedStackBytes ); \ + \ + /* Has the extremity of the task stack ever been written over? */ \ + if( memcmp( ( void * ) pcEndOfStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \ + { \ + vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ + } \ + } + +#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */ +/*-----------------------------------------------------------*/ + +#endif /* STACK_MACROS_H */ + diff --git a/component/os/freertos/freertos_v8.1.2/Source/include/croutine.h b/component/os/freertos/freertos_v8.1.2/Source/include/croutine.h new file mode 100644 index 0000000..e9a86d0 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/include/croutine.h @@ -0,0 +1,758 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef CO_ROUTINE_H +#define CO_ROUTINE_H + +#ifndef INC_FREERTOS_H + #error "include FreeRTOS.h must appear in source files before include croutine.h" +#endif + +#include "list.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Used to hide the implementation of the co-routine control block. The +control block structure however has to be included in the header due to +the macro implementation of the co-routine functionality. */ +typedef void * CoRoutineHandle_t; + +/* Defines the prototype to which co-routine functions must conform. */ +typedef void (*crCOROUTINE_CODE)( CoRoutineHandle_t, UBaseType_t ); + +typedef struct corCoRoutineControlBlock +{ + crCOROUTINE_CODE pxCoRoutineFunction; + ListItem_t xGenericListItem; /*< List item used to place the CRCB in ready and blocked queues. */ + ListItem_t xEventListItem; /*< List item used to place the CRCB in event lists. */ + UBaseType_t uxPriority; /*< The priority of the co-routine in relation to other co-routines. */ + UBaseType_t uxIndex; /*< Used to distinguish between co-routines when multiple co-routines use the same co-routine function. */ + uint16_t uxState; /*< Used internally by the co-routine implementation. */ +} CRCB_t; /* Co-routine control block. Note must be identical in size down to uxPriority with TCB_t. */ + +/** + * croutine. h + *
+ BaseType_t xCoRoutineCreate(
+                                 crCOROUTINE_CODE pxCoRoutineCode,
+                                 UBaseType_t uxPriority,
+                                 UBaseType_t uxIndex
+                               );
+ * + * Create a new co-routine and add it to the list of co-routines that are + * ready to run. + * + * @param pxCoRoutineCode Pointer to the co-routine function. Co-routine + * functions require special syntax - see the co-routine section of the WEB + * documentation for more information. + * + * @param uxPriority The priority with respect to other co-routines at which + * the co-routine will run. + * + * @param uxIndex Used to distinguish between different co-routines that + * execute the same function. See the example below and the co-routine section + * of the WEB documentation for further information. + * + * @return pdPASS if the co-routine was successfully created and added to a ready + * list, otherwise an error code defined with ProjDefs.h. + * + * Example usage: +
+ // Co-routine to be created.
+ void vFlashCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ // This may not be necessary for const variables.
+ static const char cLedToFlash[ 2 ] = { 5, 6 };
+ static const TickType_t uxFlashRates[ 2 ] = { 200, 400 };
+
+     // Must start every co-routine with a call to crSTART();
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+         // This co-routine just delays for a fixed period, then toggles
+         // an LED.  Two co-routines are created using this function, so
+         // the uxIndex parameter is used to tell the co-routine which
+         // LED to flash and how int32_t to delay.  This assumes xQueue has
+         // already been created.
+         vParTestToggleLED( cLedToFlash[ uxIndex ] );
+         crDELAY( xHandle, uxFlashRates[ uxIndex ] );
+     }
+
+     // Must end every co-routine with a call to crEND();
+     crEND();
+ }
+
+ // Function that creates two co-routines.
+ void vOtherFunction( void )
+ {
+ uint8_t ucParameterToPass;
+ TaskHandle_t xHandle;
+
+     // Create two co-routines at priority 0.  The first is given index 0
+     // so (from the code above) toggles LED 5 every 200 ticks.  The second
+     // is given index 1 so toggles LED 6 every 400 ticks.
+     for( uxIndex = 0; uxIndex < 2; uxIndex++ )
+     {
+         xCoRoutineCreate( vFlashCoRoutine, 0, uxIndex );
+     }
+ }
+   
+ * \defgroup xCoRoutineCreate xCoRoutineCreate + * \ingroup Tasks + */ +BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, UBaseType_t uxPriority, UBaseType_t uxIndex ); + + +/** + * croutine. h + *
+ void vCoRoutineSchedule( void );
+ * + * Run a co-routine. + * + * vCoRoutineSchedule() executes the highest priority co-routine that is able + * to run. The co-routine will execute until it either blocks, yields or is + * preempted by a task. Co-routines execute cooperatively so one + * co-routine cannot be preempted by another, but can be preempted by a task. + * + * If an application comprises of both tasks and co-routines then + * vCoRoutineSchedule should be called from the idle task (in an idle task + * hook). + * + * Example usage: +
+ // This idle task hook will schedule a co-routine each time it is called.
+ // The rest of the idle task will execute between co-routine calls.
+ void vApplicationIdleHook( void )
+ {
+	vCoRoutineSchedule();
+ }
+
+ // Alternatively, if you do not require any other part of the idle task to
+ // execute, the idle task hook can call vCoRoutineScheduler() within an
+ // infinite loop.
+ void vApplicationIdleHook( void )
+ {
+    for( ;; )
+    {
+        vCoRoutineSchedule();
+    }
+ }
+ 
+ * \defgroup vCoRoutineSchedule vCoRoutineSchedule + * \ingroup Tasks + */ +void vCoRoutineSchedule( void ); + +/** + * croutine. h + *
+ crSTART( CoRoutineHandle_t xHandle );
+ * + * This macro MUST always be called at the start of a co-routine function. + * + * Example usage: +
+ // Co-routine to be created.
+ void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ static int32_t ulAVariable;
+
+     // Must start every co-routine with a call to crSTART();
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+          // Co-routine functionality goes here.
+     }
+
+     // Must end every co-routine with a call to crEND();
+     crEND();
+ }
+ * \defgroup crSTART crSTART + * \ingroup Tasks + */ +#define crSTART( pxCRCB ) switch( ( ( CRCB_t * )( pxCRCB ) )->uxState ) { case 0: + +/** + * croutine. h + *
+ crEND();
+ * + * This macro MUST always be called at the end of a co-routine function. + * + * Example usage: +
+ // Co-routine to be created.
+ void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ static int32_t ulAVariable;
+
+     // Must start every co-routine with a call to crSTART();
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+          // Co-routine functionality goes here.
+     }
+
+     // Must end every co-routine with a call to crEND();
+     crEND();
+ }
+ * \defgroup crSTART crSTART + * \ingroup Tasks + */ +#define crEND() } + +/* + * These macros are intended for internal use by the co-routine implementation + * only. The macros should not be used directly by application writers. + */ +#define crSET_STATE0( xHandle ) ( ( CRCB_t * )( xHandle ) )->uxState = (__LINE__ * 2); return; case (__LINE__ * 2): +#define crSET_STATE1( xHandle ) ( ( CRCB_t * )( xHandle ) )->uxState = ((__LINE__ * 2)+1); return; case ((__LINE__ * 2)+1): + +/** + * croutine. h + *
+ crDELAY( CoRoutineHandle_t xHandle, TickType_t xTicksToDelay );
+ * + * Delay a co-routine for a fixed period of time. + * + * crDELAY can only be called from the co-routine function itself - not + * from within a function called by the co-routine function. This is because + * co-routines do not maintain their own stack. + * + * @param xHandle The handle of the co-routine to delay. This is the xHandle + * parameter of the co-routine function. + * + * @param xTickToDelay The number of ticks that the co-routine should delay + * for. The actual amount of time this equates to is defined by + * configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant portTICK_PERIOD_MS + * can be used to convert ticks to milliseconds. + * + * Example usage: +
+ // Co-routine to be created.
+ void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ // This may not be necessary for const variables.
+ // We are to delay for 200ms.
+ static const xTickType xDelayTime = 200 / portTICK_PERIOD_MS;
+
+     // Must start every co-routine with a call to crSTART();
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+        // Delay for 200ms.
+        crDELAY( xHandle, xDelayTime );
+
+        // Do something here.
+     }
+
+     // Must end every co-routine with a call to crEND();
+     crEND();
+ }
+ * \defgroup crDELAY crDELAY + * \ingroup Tasks + */ +#define crDELAY( xHandle, xTicksToDelay ) \ + if( ( xTicksToDelay ) > 0 ) \ + { \ + vCoRoutineAddToDelayedList( ( xTicksToDelay ), NULL ); \ + } \ + crSET_STATE0( ( xHandle ) ); + +/** + *
+ crQUEUE_SEND(
+                  CoRoutineHandle_t xHandle,
+                  QueueHandle_t pxQueue,
+                  void *pvItemToQueue,
+                  TickType_t xTicksToWait,
+                  BaseType_t *pxResult
+             )
+ * + * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine + * equivalent to the xQueueSend() and xQueueReceive() functions used by tasks. + * + * crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas + * xQueueSend() and xQueueReceive() can only be used from tasks. + * + * crQUEUE_SEND can only be called from the co-routine function itself - not + * from within a function called by the co-routine function. This is because + * co-routines do not maintain their own stack. + * + * See the co-routine section of the WEB documentation for information on + * passing data between tasks and co-routines and between ISR's and + * co-routines. + * + * @param xHandle The handle of the calling co-routine. This is the xHandle + * parameter of the co-routine function. + * + * @param pxQueue The handle of the queue on which the data will be posted. + * The handle is obtained as the return value when the queue is created using + * the xQueueCreate() API function. + * + * @param pvItemToQueue A pointer to the data being posted onto the queue. + * The number of bytes of each queued item is specified when the queue is + * created. This number of bytes is copied from pvItemToQueue into the queue + * itself. + * + * @param xTickToDelay The number of ticks that the co-routine should block + * to wait for space to become available on the queue, should space not be + * available immediately. The actual amount of time this equates to is defined + * by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant + * portTICK_PERIOD_MS can be used to convert ticks to milliseconds (see example + * below). + * + * @param pxResult The variable pointed to by pxResult will be set to pdPASS if + * data was successfully posted onto the queue, otherwise it will be set to an + * error defined within ProjDefs.h. + * + * Example usage: +
+ // Co-routine function that blocks for a fixed period then posts a number onto
+ // a queue.
+ static void prvCoRoutineFlashTask( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ static BaseType_t xNumberToPost = 0;
+ static BaseType_t xResult;
+
+    // Co-routines must begin with a call to crSTART().
+    crSTART( xHandle );
+
+    for( ;; )
+    {
+        // This assumes the queue has already been created.
+        crQUEUE_SEND( xHandle, xCoRoutineQueue, &xNumberToPost, NO_DELAY, &xResult );
+
+        if( xResult != pdPASS )
+        {
+            // The message was not posted!
+        }
+
+        // Increment the number to be posted onto the queue.
+        xNumberToPost++;
+
+        // Delay for 100 ticks.
+        crDELAY( xHandle, 100 );
+    }
+
+    // Co-routines must end with a call to crEND().
+    crEND();
+ }
+ * \defgroup crQUEUE_SEND crQUEUE_SEND + * \ingroup Tasks + */ +#define crQUEUE_SEND( xHandle, pxQueue, pvItemToQueue, xTicksToWait, pxResult ) \ +{ \ + *( pxResult ) = xQueueCRSend( ( pxQueue) , ( pvItemToQueue) , ( xTicksToWait ) ); \ + if( *( pxResult ) == errQUEUE_BLOCKED ) \ + { \ + crSET_STATE0( ( xHandle ) ); \ + *pxResult = xQueueCRSend( ( pxQueue ), ( pvItemToQueue ), 0 ); \ + } \ + if( *pxResult == errQUEUE_YIELD ) \ + { \ + crSET_STATE1( ( xHandle ) ); \ + *pxResult = pdPASS; \ + } \ +} + +/** + * croutine. h + *
+  crQUEUE_RECEIVE(
+                     CoRoutineHandle_t xHandle,
+                     QueueHandle_t pxQueue,
+                     void *pvBuffer,
+                     TickType_t xTicksToWait,
+                     BaseType_t *pxResult
+                 )
+ * + * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine + * equivalent to the xQueueSend() and xQueueReceive() functions used by tasks. + * + * crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas + * xQueueSend() and xQueueReceive() can only be used from tasks. + * + * crQUEUE_RECEIVE can only be called from the co-routine function itself - not + * from within a function called by the co-routine function. This is because + * co-routines do not maintain their own stack. + * + * See the co-routine section of the WEB documentation for information on + * passing data between tasks and co-routines and between ISR's and + * co-routines. + * + * @param xHandle The handle of the calling co-routine. This is the xHandle + * parameter of the co-routine function. + * + * @param pxQueue The handle of the queue from which the data will be received. + * The handle is obtained as the return value when the queue is created using + * the xQueueCreate() API function. + * + * @param pvBuffer The buffer into which the received item is to be copied. + * The number of bytes of each queued item is specified when the queue is + * created. This number of bytes is copied into pvBuffer. + * + * @param xTickToDelay The number of ticks that the co-routine should block + * to wait for data to become available from the queue, should data not be + * available immediately. The actual amount of time this equates to is defined + * by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant + * portTICK_PERIOD_MS can be used to convert ticks to milliseconds (see the + * crQUEUE_SEND example). + * + * @param pxResult The variable pointed to by pxResult will be set to pdPASS if + * data was successfully retrieved from the queue, otherwise it will be set to + * an error code as defined within ProjDefs.h. + * + * Example usage: +
+ // A co-routine receives the number of an LED to flash from a queue.  It
+ // blocks on the queue until the number is received.
+ static void prvCoRoutineFlashWorkTask( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ static BaseType_t xResult;
+ static UBaseType_t uxLEDToFlash;
+
+    // All co-routines must start with a call to crSTART().
+    crSTART( xHandle );
+
+    for( ;; )
+    {
+        // Wait for data to become available on the queue.
+        crQUEUE_RECEIVE( xHandle, xCoRoutineQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
+
+        if( xResult == pdPASS )
+        {
+            // We received the LED to flash - flash it!
+            vParTestToggleLED( uxLEDToFlash );
+        }
+    }
+
+    crEND();
+ }
+ * \defgroup crQUEUE_RECEIVE crQUEUE_RECEIVE + * \ingroup Tasks + */ +#define crQUEUE_RECEIVE( xHandle, pxQueue, pvBuffer, xTicksToWait, pxResult ) \ +{ \ + *( pxResult ) = xQueueCRReceive( ( pxQueue) , ( pvBuffer ), ( xTicksToWait ) ); \ + if( *( pxResult ) == errQUEUE_BLOCKED ) \ + { \ + crSET_STATE0( ( xHandle ) ); \ + *( pxResult ) = xQueueCRReceive( ( pxQueue) , ( pvBuffer ), 0 ); \ + } \ + if( *( pxResult ) == errQUEUE_YIELD ) \ + { \ + crSET_STATE1( ( xHandle ) ); \ + *( pxResult ) = pdPASS; \ + } \ +} + +/** + * croutine. h + *
+  crQUEUE_SEND_FROM_ISR(
+                            QueueHandle_t pxQueue,
+                            void *pvItemToQueue,
+                            BaseType_t xCoRoutinePreviouslyWoken
+                       )
+ * + * The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the + * co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR() + * functions used by tasks. + * + * crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to + * pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and + * xQueueReceiveFromISR() can only be used to pass data between a task and and + * ISR. + * + * crQUEUE_SEND_FROM_ISR can only be called from an ISR to send data to a queue + * that is being used from within a co-routine. + * + * See the co-routine section of the WEB documentation for information on + * passing data between tasks and co-routines and between ISR's and + * co-routines. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param xCoRoutinePreviouslyWoken This is included so an ISR can post onto + * the same queue multiple times from a single interrupt. The first call + * should always pass in pdFALSE. Subsequent calls should pass in + * the value returned from the previous call. + * + * @return pdTRUE if a co-routine was woken by posting onto the queue. This is + * used by the ISR to determine if a context switch may be required following + * the ISR. + * + * Example usage: +
+ // A co-routine that blocks on a queue waiting for characters to be received.
+ static void vReceivingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+ {
+ char cRxedChar;
+ BaseType_t xResult;
+
+     // All co-routines must start with a call to crSTART().
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+         // Wait for data to become available on the queue.  This assumes the
+         // queue xCommsRxQueue has already been created!
+         crQUEUE_RECEIVE( xHandle, xCommsRxQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
+
+         // Was a character received?
+         if( xResult == pdPASS )
+         {
+             // Process the character here.
+         }
+     }
+
+     // All co-routines must end with a call to crEND().
+     crEND();
+ }
+
+ // An ISR that uses a queue to send characters received on a serial port to
+ // a co-routine.
+ void vUART_ISR( void )
+ {
+ char cRxedChar;
+ BaseType_t xCRWokenByPost = pdFALSE;
+
+     // We loop around reading characters until there are none left in the UART.
+     while( UART_RX_REG_NOT_EMPTY() )
+     {
+         // Obtain the character from the UART.
+         cRxedChar = UART_RX_REG;
+
+         // Post the character onto a queue.  xCRWokenByPost will be pdFALSE
+         // the first time around the loop.  If the post causes a co-routine
+         // to be woken (unblocked) then xCRWokenByPost will be set to pdTRUE.
+         // In this manner we can ensure that if more than one co-routine is
+         // blocked on the queue only one is woken by this ISR no matter how
+         // many characters are posted to the queue.
+         xCRWokenByPost = crQUEUE_SEND_FROM_ISR( xCommsRxQueue, &cRxedChar, xCRWokenByPost );
+     }
+ }
+ * \defgroup crQUEUE_SEND_FROM_ISR crQUEUE_SEND_FROM_ISR + * \ingroup Tasks + */ +#define crQUEUE_SEND_FROM_ISR( pxQueue, pvItemToQueue, xCoRoutinePreviouslyWoken ) xQueueCRSendFromISR( ( pxQueue ), ( pvItemToQueue ), ( xCoRoutinePreviouslyWoken ) ) + + +/** + * croutine. h + *
+  crQUEUE_SEND_FROM_ISR(
+                            QueueHandle_t pxQueue,
+                            void *pvBuffer,
+                            BaseType_t * pxCoRoutineWoken
+                       )
+ * + * The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the + * co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR() + * functions used by tasks. + * + * crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to + * pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and + * xQueueReceiveFromISR() can only be used to pass data between a task and and + * ISR. + * + * crQUEUE_RECEIVE_FROM_ISR can only be called from an ISR to receive data + * from a queue that is being used from within a co-routine (a co-routine + * posted to the queue). + * + * See the co-routine section of the WEB documentation for information on + * passing data between tasks and co-routines and between ISR's and + * co-routines. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvBuffer A pointer to a buffer into which the received item will be + * placed. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from the queue into + * pvBuffer. + * + * @param pxCoRoutineWoken A co-routine may be blocked waiting for space to become + * available on the queue. If crQUEUE_RECEIVE_FROM_ISR causes such a + * co-routine to unblock *pxCoRoutineWoken will get set to pdTRUE, otherwise + * *pxCoRoutineWoken will remain unchanged. + * + * @return pdTRUE an item was successfully received from the queue, otherwise + * pdFALSE. + * + * Example usage: +
+ // A co-routine that posts a character to a queue then blocks for a fixed
+ // period.  The character is incremented each time.
+ static void vSendingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+ {
+ // cChar holds its value while this co-routine is blocked and must therefore
+ // be declared static.
+ static char cCharToTx = 'a';
+ BaseType_t xResult;
+
+     // All co-routines must start with a call to crSTART().
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+         // Send the next character to the queue.
+         crQUEUE_SEND( xHandle, xCoRoutineQueue, &cCharToTx, NO_DELAY, &xResult );
+
+         if( xResult == pdPASS )
+         {
+             // The character was successfully posted to the queue.
+         }
+		 else
+		 {
+			// Could not post the character to the queue.
+		 }
+
+         // Enable the UART Tx interrupt to cause an interrupt in this
+		 // hypothetical UART.  The interrupt will obtain the character
+		 // from the queue and send it.
+		 ENABLE_RX_INTERRUPT();
+
+		 // Increment to the next character then block for a fixed period.
+		 // cCharToTx will maintain its value across the delay as it is
+		 // declared static.
+		 cCharToTx++;
+		 if( cCharToTx > 'x' )
+		 {
+			cCharToTx = 'a';
+		 }
+		 crDELAY( 100 );
+     }
+
+     // All co-routines must end with a call to crEND().
+     crEND();
+ }
+
+ // An ISR that uses a queue to receive characters to send on a UART.
+ void vUART_ISR( void )
+ {
+ char cCharToTx;
+ BaseType_t xCRWokenByPost = pdFALSE;
+
+     while( UART_TX_REG_EMPTY() )
+     {
+         // Are there any characters in the queue waiting to be sent?
+		 // xCRWokenByPost will automatically be set to pdTRUE if a co-routine
+		 // is woken by the post - ensuring that only a single co-routine is
+		 // woken no matter how many times we go around this loop.
+         if( crQUEUE_RECEIVE_FROM_ISR( pxQueue, &cCharToTx, &xCRWokenByPost ) )
+		 {
+			 SEND_CHARACTER( cCharToTx );
+		 }
+     }
+ }
+ * \defgroup crQUEUE_RECEIVE_FROM_ISR crQUEUE_RECEIVE_FROM_ISR + * \ingroup Tasks + */ +#define crQUEUE_RECEIVE_FROM_ISR( pxQueue, pvBuffer, pxCoRoutineWoken ) xQueueCRReceiveFromISR( ( pxQueue ), ( pvBuffer ), ( pxCoRoutineWoken ) ) + +/* + * This function is intended for internal use by the co-routine macros only. + * The macro nature of the co-routine implementation requires that the + * prototype appears here. The function should not be used by application + * writers. + * + * Removes the current co-routine from its ready list and places it in the + * appropriate delayed list. + */ +void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay, List_t *pxEventList ); + +/* + * This function is intended for internal use by the queue implementation only. + * The function should not be used by application writers. + * + * Removes the highest priority co-routine from the event list and places it in + * the pending ready list. + */ +BaseType_t xCoRoutineRemoveFromEventList( const List_t *pxEventList ); + +#ifdef __cplusplus +} +#endif + +#endif /* CO_ROUTINE_H */ diff --git a/component/os/freertos/freertos_v8.1.2/Source/include/event_groups.h b/component/os/freertos/freertos_v8.1.2/Source/include/event_groups.h new file mode 100644 index 0000000..51e7ea2 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/include/event_groups.h @@ -0,0 +1,726 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef EVENT_GROUPS_H +#define EVENT_GROUPS_H + +#ifndef INC_FREERTOS_H + #error "include FreeRTOS.h" must appear in source files before "include event_groups.h" +#endif + +#include "timers.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * An event group is a collection of bits to which an application can assign a + * meaning. For example, an application may create an event group to convey + * the status of various CAN bus related events in which bit 0 might mean "A CAN + * message has been received and is ready for processing", bit 1 might mean "The + * application has queued a message that is ready for sending onto the CAN + * network", and bit 2 might mean "It is time to send a SYNC message onto the + * CAN network" etc. A task can then test the bit values to see which events + * are active, and optionally enter the Blocked state to wait for a specified + * bit or a group of specified bits to be active. To continue the CAN bus + * example, a CAN controlling task can enter the Blocked state (and therefore + * not consume any processing time) until either bit 0, bit 1 or bit 2 are + * active, at which time the bit that was actually active would inform the task + * which action it had to take (process a received message, send a message, or + * send a SYNC). + * + * The event groups implementation contains intelligence to avoid race + * conditions that would otherwise occur were an application to use a simple + * variable for the same purpose. This is particularly important with respect + * to when a bit within an event group is to be cleared, and when bits have to + * be set and then tested atomically - as is the case where event groups are + * used to create a synchronisation point between multiple tasks (a + * 'rendezvous'). + * + * \defgroup EventGroup + */ + + + +/** + * event_groups.h + * + * Type by which event groups are referenced. For example, a call to + * xEventGroupCreate() returns an EventGroupHandle_t variable that can then + * be used as a parameter to other event group functions. + * + * \defgroup EventGroupHandle_t EventGroupHandle_t + * \ingroup EventGroup + */ +typedef void * EventGroupHandle_t; + +/* + * The type that holds event bits always matches TickType_t - therefore the + * number of bits it holds is set by configUSE_16_BIT_TICKS (16 bits if set to 1, + * 32 bits if set to 0. + * + * \defgroup EventBits_t EventBits_t + * \ingroup EventGroup + */ +typedef TickType_t EventBits_t; + +/** + * event_groups.h + *
+ EventGroupHandle_t xEventGroupCreate( void );
+ 
+ * + * Create a new event group. This function cannot be called from an interrupt. + * + * Although event groups are not related to ticks, for internal implementation + * reasons the number of bits available for use in an event group is dependent + * on the configUSE_16_BIT_TICKS setting in FreeRTOSConfig.h. If + * configUSE_16_BIT_TICKS is 1 then each event group contains 8 usable bits (bit + * 0 to bit 7). If configUSE_16_BIT_TICKS is set to 0 then each event group has + * 24 usable bits (bit 0 to bit 23). The EventBits_t type is used to store + * event bits within an event group. + * + * @return If the event group was created then a handle to the event group is + * returned. If there was insufficient FreeRTOS heap available to create the + * event group then NULL is returned. See http://www.freertos.org/a00111.html + * + * Example usage: +
+	// Declare a variable to hold the created event group.
+	EventGroupHandle_t xCreatedEventGroup;
+
+	// Attempt to create the event group.
+	xCreatedEventGroup = xEventGroupCreate();
+
+	// Was the event group created successfully?
+	if( xCreatedEventGroup == NULL )
+	{
+		// The event group was not created because there was insufficient
+		// FreeRTOS heap available.
+	}
+	else
+	{
+		// The event group was created.
+	}
+   
+ * \defgroup xEventGroupCreate xEventGroupCreate + * \ingroup EventGroup + */ +EventGroupHandle_t xEventGroupCreate( void ) PRIVILEGED_FUNCTION; + +/** + * event_groups.h + *
+	EventBits_t xEventGroupWaitBits( 	EventGroupHandle_t xEventGroup,
+										const EventBits_t uxBitsToWaitFor,
+										const BaseType_t xClearOnExit,
+										const BaseType_t xWaitForAllBits,
+										const TickType_t xTicksToWait );
+ 
+ * + * [Potentially] block to wait for one or more bits to be set within a + * previously created event group. + * + * This function cannot be called from an interrupt. + * + * @param xEventGroup The event group in which the bits are being tested. The + * event group must have previously been created using a call to + * xEventGroupCreate(). + * + * @param uxBitsToWaitFor A bitwise value that indicates the bit or bits to test + * inside the event group. For example, to wait for bit 0 and/or bit 2 set + * uxBitsToWaitFor to 0x05. To wait for bits 0 and/or bit 1 and/or bit 2 set + * uxBitsToWaitFor to 0x07. Etc. + * + * @param xClearOnExit If xClearOnExit is set to pdTRUE then any bits within + * uxBitsToWaitFor that are set within the event group will be cleared before + * xEventGroupWaitBits() returns if the wait condition was met (if the function + * returns for a reason other than a timeout). If xClearOnExit is set to + * pdFALSE then the bits set in the event group are not altered when the call to + * xEventGroupWaitBits() returns. + * + * @param xWaitForAllBits If xWaitForAllBits is set to pdTRUE then + * xEventGroupWaitBits() will return when either all the bits in uxBitsToWaitFor + * are set or the specified block time expires. If xWaitForAllBits is set to + * pdFALSE then xEventGroupWaitBits() will return when any one of the bits set + * in uxBitsToWaitFor is set or the specified block time expires. The block + * time is specified by the xTicksToWait parameter. + * + * @param xTicksToWait The maximum amount of time (specified in 'ticks') to wait + * for one/all (depending on the xWaitForAllBits value) of the bits specified by + * uxBitsToWaitFor to become set. + * + * @return The value of the event group at the time either the bits being waited + * for became set, or the block time expired. Test the return value to know + * which bits were set. If xEventGroupWaitBits() returned because its timeout + * expired then not all the bits being waited for will be set. If + * xEventGroupWaitBits() returned because the bits it was waiting for were set + * then the returned value is the event group value before any bits were + * automatically cleared in the case that xClearOnExit parameter was set to + * pdTRUE. + * + * Example usage: +
+   #define BIT_0	( 1 << 0 )
+   #define BIT_4	( 1 << 4 )
+
+   void aFunction( EventGroupHandle_t xEventGroup )
+   {
+   EventBits_t uxBits;
+   const TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;
+
+		// Wait a maximum of 100ms for either bit 0 or bit 4 to be set within
+		// the event group.  Clear the bits before exiting.
+		uxBits = xEventGroupWaitBits(
+					xEventGroup,	// The event group being tested.
+					BIT_0 | BIT_4,	// The bits within the event group to wait for.
+					pdTRUE,			// BIT_0 and BIT_4 should be cleared before returning.
+					pdFALSE,		// Don't wait for both bits, either bit will do.
+					xTicksToWait );	// Wait a maximum of 100ms for either bit to be set.
+
+		if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
+		{
+			// xEventGroupWaitBits() returned because both bits were set.
+		}
+		else if( ( uxBits & BIT_0 ) != 0 )
+		{
+			// xEventGroupWaitBits() returned because just BIT_0 was set.
+		}
+		else if( ( uxBits & BIT_4 ) != 0 )
+		{
+			// xEventGroupWaitBits() returned because just BIT_4 was set.
+		}
+		else
+		{
+			// xEventGroupWaitBits() returned because xTicksToWait ticks passed
+			// without either BIT_0 or BIT_4 becoming set.
+		}
+   }
+   
+ * \defgroup xEventGroupWaitBits xEventGroupWaitBits + * \ingroup EventGroup + */ +EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; + +/** + * event_groups.h + *
+	EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear );
+ 
+ * + * Clear bits within an event group. This function cannot be called from an + * interrupt. + * + * @param xEventGroup The event group in which the bits are to be cleared. + * + * @param uxBitsToClear A bitwise value that indicates the bit or bits to clear + * in the event group. For example, to clear bit 3 only, set uxBitsToClear to + * 0x08. To clear bit 3 and bit 0 set uxBitsToClear to 0x09. + * + * @return The value of the event group before the specified bits were cleared. + * + * Example usage: +
+   #define BIT_0	( 1 << 0 )
+   #define BIT_4	( 1 << 4 )
+
+   void aFunction( EventGroupHandle_t xEventGroup )
+   {
+   EventBits_t uxBits;
+
+		// Clear bit 0 and bit 4 in xEventGroup.
+		uxBits = xEventGroupClearBits(
+								xEventGroup,	// The event group being updated.
+								BIT_0 | BIT_4 );// The bits being cleared.
+
+		if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
+		{
+			// Both bit 0 and bit 4 were set before xEventGroupClearBits() was
+			// called.  Both will now be clear (not set).
+		}
+		else if( ( uxBits & BIT_0 ) != 0 )
+		{
+			// Bit 0 was set before xEventGroupClearBits() was called.  It will
+			// now be clear.
+		}
+		else if( ( uxBits & BIT_4 ) != 0 )
+		{
+			// Bit 4 was set before xEventGroupClearBits() was called.  It will
+			// now be clear.
+		}
+		else
+		{
+			// Neither bit 0 nor bit 4 were set in the first place.
+		}
+   }
+   
+ * \defgroup xEventGroupClearBits xEventGroupClearBits + * \ingroup EventGroup + */ +EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION; + +/** + * event_groups.h + *
+	BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
+ 
+ * + * A version of xEventGroupClearBits() that can be called from an interrupt. + * + * Setting bits in an event group is not a deterministic operation because there + * are an unknown number of tasks that may be waiting for the bit or bits being + * set. FreeRTOS does not allow nondeterministic operations to be performed + * while interrupts are disabled, so protects event groups that are accessed + * from tasks by suspending the scheduler rather than disabling interrupts. As + * a result event groups cannot be accessed directly from an interrupt service + * routine. Therefore xEventGroupClearBitsFromISR() sends a message to the + * timer task to have the clear operation performed in the context of the timer + * task. + * + * @param xEventGroup The event group in which the bits are to be cleared. + * + * @param uxBitsToClear A bitwise value that indicates the bit or bits to clear. + * For example, to clear bit 3 only, set uxBitsToClear to 0x08. To clear bit 3 + * and bit 0 set uxBitsToClear to 0x09. + * + * @return If the request to execute the function was posted successfully then + * pdPASS is returned, otherwise pdFALSE is returned. pdFALSE will be returned + * if the timer service queue was full. + * + * Example usage: +
+   #define BIT_0	( 1 << 0 )
+   #define BIT_4	( 1 << 4 )
+
+   // An event group which it is assumed has already been created by a call to
+   // xEventGroupCreate().
+   EventGroupHandle_t xEventGroup;
+
+   void anInterruptHandler( void )
+   {
+		// Clear bit 0 and bit 4 in xEventGroup.
+		xResult = xEventGroupClearBitsFromISR(
+							xEventGroup,	 // The event group being updated.
+							BIT_0 | BIT_4 ); // The bits being set.
+
+		if( xResult == pdPASS )
+		{
+			// The message was posted successfully.
+		}
+  }
+   
+ * \defgroup xEventGroupSetBitsFromISR xEventGroupSetBitsFromISR + * \ingroup EventGroup + */ +#if( configUSE_TRACE_FACILITY == 1 ) + BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ); +#else + #define xEventGroupClearBitsFromISR( xEventGroup, uxBitsToClear ) xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL ) +#endif + +/** + * event_groups.h + *
+	EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
+ 
+ * + * Set bits within an event group. + * This function cannot be called from an interrupt. xEventGroupSetBitsFromISR() + * is a version that can be called from an interrupt. + * + * Setting bits in an event group will automatically unblock tasks that are + * blocked waiting for the bits. + * + * @param xEventGroup The event group in which the bits are to be set. + * + * @param uxBitsToSet A bitwise value that indicates the bit or bits to set. + * For example, to set bit 3 only, set uxBitsToSet to 0x08. To set bit 3 + * and bit 0 set uxBitsToSet to 0x09. + * + * @return The value of the event group at the time the call to + * xEventGroupSetBits() returns. There are two reasons why the returned value + * might have the bits specified by the uxBitsToSet parameter cleared. First, + * if setting a bit results in a task that was waiting for the bit leaving the + * blocked state then it is possible the bit will be cleared automatically + * (see the xClearBitOnExit parameter of xEventGroupWaitBits()). Second, any + * unblocked (or otherwise Ready state) task that has a priority above that of + * the task that called xEventGroupSetBits() will execute and may change the + * event group value before the call to xEventGroupSetBits() returns. + * + * Example usage: +
+   #define BIT_0	( 1 << 0 )
+   #define BIT_4	( 1 << 4 )
+
+   void aFunction( EventGroupHandle_t xEventGroup )
+   {
+   EventBits_t uxBits;
+
+		// Set bit 0 and bit 4 in xEventGroup.
+		uxBits = xEventGroupSetBits(
+							xEventGroup,	// The event group being updated.
+							BIT_0 | BIT_4 );// The bits being set.
+
+		if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
+		{
+			// Both bit 0 and bit 4 remained set when the function returned.
+		}
+		else if( ( uxBits & BIT_0 ) != 0 )
+		{
+			// Bit 0 remained set when the function returned, but bit 4 was
+			// cleared.  It might be that bit 4 was cleared automatically as a
+			// task that was waiting for bit 4 was removed from the Blocked
+			// state.
+		}
+		else if( ( uxBits & BIT_4 ) != 0 )
+		{
+			// Bit 4 remained set when the function returned, but bit 0 was
+			// cleared.  It might be that bit 0 was cleared automatically as a
+			// task that was waiting for bit 0 was removed from the Blocked
+			// state.
+		}
+		else
+		{
+			// Neither bit 0 nor bit 4 remained set.  It might be that a task
+			// was waiting for both of the bits to be set, and the bits were
+			// cleared as the task left the Blocked state.
+		}
+   }
+   
+ * \defgroup xEventGroupSetBits xEventGroupSetBits + * \ingroup EventGroup + */ +EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ) PRIVILEGED_FUNCTION; + +/** + * event_groups.h + *
+	BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken );
+ 
+ * + * A version of xEventGroupSetBits() that can be called from an interrupt. + * + * Setting bits in an event group is not a deterministic operation because there + * are an unknown number of tasks that may be waiting for the bit or bits being + * set. FreeRTOS does not allow nondeterministic operations to be performed in + * interrupts or from critical sections. Therefore xEventGroupSetBitFromISR() + * sends a message to the timer task to have the set operation performed in the + * context of the timer task - where a scheduler lock is used in place of a + * critical section. + * + * @param xEventGroup The event group in which the bits are to be set. + * + * @param uxBitsToSet A bitwise value that indicates the bit or bits to set. + * For example, to set bit 3 only, set uxBitsToSet to 0x08. To set bit 3 + * and bit 0 set uxBitsToSet to 0x09. + * + * @param pxHigherPriorityTaskWoken As mentioned above, calling this function + * will result in a message being sent to the timer daemon task. If the + * priority of the timer daemon task is higher than the priority of the + * currently running task (the task the interrupt interrupted) then + * *pxHigherPriorityTaskWoken will be set to pdTRUE by + * xEventGroupSetBitsFromISR(), indicating that a context switch should be + * requested before the interrupt exits. For that reason + * *pxHigherPriorityTaskWoken must be initialised to pdFALSE. See the + * example code below. + * + * @return If the request to execute the function was posted successfully then + * pdPASS is returned, otherwise pdFALSE is returned. pdFALSE will be returned + * if the timer service queue was full. + * + * Example usage: +
+   #define BIT_0	( 1 << 0 )
+   #define BIT_4	( 1 << 4 )
+
+   // An event group which it is assumed has already been created by a call to
+   // xEventGroupCreate().
+   EventGroupHandle_t xEventGroup;
+
+   void anInterruptHandler( void )
+   {
+   BaseType_t xHigherPriorityTaskWoken, xResult;
+
+		// xHigherPriorityTaskWoken must be initialised to pdFALSE.
+		xHigherPriorityTaskWoken = pdFALSE;
+
+		// Set bit 0 and bit 4 in xEventGroup.
+		xResult = xEventGroupSetBitsFromISR(
+							xEventGroup,	// The event group being updated.
+							BIT_0 | BIT_4   // The bits being set.
+							&xHigherPriorityTaskWoken );
+
+		// Was the message posted successfully?
+		if( xResult == pdPASS )
+		{
+			// If xHigherPriorityTaskWoken is now set to pdTRUE then a context
+			// switch should be requested.  The macro used is port specific and 
+			// will be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() - 
+			// refer to the documentation page for the port being used.
+			portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
+		}
+  }
+   
+ * \defgroup xEventGroupSetBitsFromISR xEventGroupSetBitsFromISR + * \ingroup EventGroup + */ +#if( configUSE_TRACE_FACILITY == 1 ) + BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken ); +#else + #define xEventGroupSetBitsFromISR( xEventGroup, uxBitsToSet, pxHigherPriorityTaskWoken ) xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken ) +#endif + +/** + * event_groups.h + *
+	EventBits_t xEventGroupSync(	EventGroupHandle_t xEventGroup,
+									const EventBits_t uxBitsToSet,
+									const EventBits_t uxBitsToWaitFor,
+									TickType_t xTicksToWait );
+ 
+ * + * Atomically set bits within an event group, then wait for a combination of + * bits to be set within the same event group. This functionality is typically + * used to synchronise multiple tasks, where each task has to wait for the other + * tasks to reach a synchronisation point before proceeding. + * + * This function cannot be used from an interrupt. + * + * The function will return before its block time expires if the bits specified + * by the uxBitsToWait parameter are set, or become set within that time. In + * this case all the bits specified by uxBitsToWait will be automatically + * cleared before the function returns. + * + * @param xEventGroup The event group in which the bits are being tested. The + * event group must have previously been created using a call to + * xEventGroupCreate(). + * + * @param uxBitsToSet The bits to set in the event group before determining + * if, and possibly waiting for, all the bits specified by the uxBitsToWait + * parameter are set. + * + * @param uxBitsToWaitFor A bitwise value that indicates the bit or bits to test + * inside the event group. For example, to wait for bit 0 and bit 2 set + * uxBitsToWaitFor to 0x05. To wait for bits 0 and bit 1 and bit 2 set + * uxBitsToWaitFor to 0x07. Etc. + * + * @param xTicksToWait The maximum amount of time (specified in 'ticks') to wait + * for all of the bits specified by uxBitsToWaitFor to become set. + * + * @return The value of the event group at the time either the bits being waited + * for became set, or the block time expired. Test the return value to know + * which bits were set. If xEventGroupSync() returned because its timeout + * expired then not all the bits being waited for will be set. If + * xEventGroupSync() returned because all the bits it was waiting for were + * set then the returned value is the event group value before any bits were + * automatically cleared. + * + * Example usage: +
+ // Bits used by the three tasks.
+ #define TASK_0_BIT		( 1 << 0 )
+ #define TASK_1_BIT		( 1 << 1 )
+ #define TASK_2_BIT		( 1 << 2 )
+
+ #define ALL_SYNC_BITS ( TASK_0_BIT | TASK_1_BIT | TASK_2_BIT )
+
+ // Use an event group to synchronise three tasks.  It is assumed this event
+ // group has already been created elsewhere.
+ EventGroupHandle_t xEventBits;
+
+ void vTask0( void *pvParameters )
+ {
+ EventBits_t uxReturn;
+ TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;
+
+	 for( ;; )
+	 {
+		// Perform task functionality here.
+
+		// Set bit 0 in the event flag to note this task has reached the
+		// sync point.  The other two tasks will set the other two bits defined
+		// by ALL_SYNC_BITS.  All three tasks have reached the synchronisation
+		// point when all the ALL_SYNC_BITS are set.  Wait a maximum of 100ms
+		// for this to happen.
+		uxReturn = xEventGroupSync( xEventBits, TASK_0_BIT, ALL_SYNC_BITS, xTicksToWait );
+
+		if( ( uxReturn & ALL_SYNC_BITS ) == ALL_SYNC_BITS )
+		{
+			// All three tasks reached the synchronisation point before the call
+			// to xEventGroupSync() timed out.
+		}
+	}
+ }
+
+ void vTask1( void *pvParameters )
+ {
+	 for( ;; )
+	 {
+		// Perform task functionality here.
+
+		// Set bit 1 in the event flag to note this task has reached the
+		// synchronisation point.  The other two tasks will set the other two
+		// bits defined by ALL_SYNC_BITS.  All three tasks have reached the
+		// synchronisation point when all the ALL_SYNC_BITS are set.  Wait
+		// indefinitely for this to happen.
+		xEventGroupSync( xEventBits, TASK_1_BIT, ALL_SYNC_BITS, portMAX_DELAY );
+
+		// xEventGroupSync() was called with an indefinite block time, so
+		// this task will only reach here if the syncrhonisation was made by all
+		// three tasks, so there is no need to test the return value.
+	 }
+ }
+
+ void vTask2( void *pvParameters )
+ {
+	 for( ;; )
+	 {
+		// Perform task functionality here.
+
+		// Set bit 2 in the event flag to note this task has reached the
+		// synchronisation point.  The other two tasks will set the other two
+		// bits defined by ALL_SYNC_BITS.  All three tasks have reached the
+		// synchronisation point when all the ALL_SYNC_BITS are set.  Wait
+		// indefinitely for this to happen.
+		xEventGroupSync( xEventBits, TASK_2_BIT, ALL_SYNC_BITS, portMAX_DELAY );
+
+		// xEventGroupSync() was called with an indefinite block time, so
+		// this task will only reach here if the syncrhonisation was made by all
+		// three tasks, so there is no need to test the return value.
+	}
+ }
+
+ 
+ * \defgroup xEventGroupSync xEventGroupSync + * \ingroup EventGroup + */ +EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; + + +/** + * event_groups.h + *
+	EventBits_t xEventGroupGetBits( EventGroupHandle_t xEventGroup );
+ 
+ * + * Returns the current value of the bits in an event group. This function + * cannot be used from an interrupt. + * + * @param xEventGroup The event group being queried. + * + * @return The event group bits at the time xEventGroupGetBits() was called. + * + * \defgroup xEventGroupGetBits xEventGroupGetBits + * \ingroup EventGroup + */ +#define xEventGroupGetBits( xEventGroup ) xEventGroupClearBits( xEventGroup, 0 ) + +/** + * event_groups.h + *
+	EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup );
+ 
+ * + * A version of xEventGroupGetBits() that can be called from an ISR. + * + * @param xEventGroup The event group being queried. + * + * @return The event group bits at the time xEventGroupGetBitsFromISR() was called. + * + * \defgroup xEventGroupGetBitsFromISR xEventGroupGetBitsFromISR + * \ingroup EventGroup + */ +EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ); + +/** + * event_groups.h + *
+	void xEventGroupDelete( EventGroupHandle_t xEventGroup );
+ 
+ * + * Delete an event group that was previously created by a call to + * xEventGroupCreate(). Tasks that are blocked on the event group will be + * unblocked and obtain 0 as the event group's value. + * + * @param xEventGroup The event group being deleted. + */ +void vEventGroupDelete( EventGroupHandle_t xEventGroup ); + +/* For internal use only. */ +void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet ); +void vEventGroupClearBitsCallback( void *pvEventGroup, const uint32_t ulBitsToClear ); + +#if (configUSE_TRACE_FACILITY == 1) + UBaseType_t uxEventGroupGetNumber( void* xEventGroup ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* EVENT_GROUPS_H */ + + diff --git a/component/os/freertos/freertos_v8.1.2/Source/include/list.h b/component/os/freertos/freertos_v8.1.2/Source/include/list.h new file mode 100644 index 0000000..c08b11d --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/include/list.h @@ -0,0 +1,403 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* + * This is the list implementation used by the scheduler. While it is tailored + * heavily for the schedulers needs, it is also available for use by + * application code. + * + * list_ts can only store pointers to list_item_ts. Each ListItem_t contains a + * numeric value (xItemValue). Most of the time the lists are sorted in + * descending item value order. + * + * Lists are created already containing one list item. The value of this + * item is the maximum possible that can be stored, it is therefore always at + * the end of the list and acts as a marker. The list member pxHead always + * points to this marker - even though it is at the tail of the list. This + * is because the tail contains a wrap back pointer to the true head of + * the list. + * + * In addition to it's value, each list item contains a pointer to the next + * item in the list (pxNext), a pointer to the list it is in (pxContainer) + * and a pointer to back to the object that contains it. These later two + * pointers are included for efficiency of list manipulation. There is + * effectively a two way link between the object containing the list item and + * the list item itself. + * + * + * \page ListIntroduction List Implementation + * \ingroup FreeRTOSIntro + */ + + +#ifndef LIST_H +#define LIST_H + +/* + * The list structure members are modified from within interrupts, and therefore + * by rights should be declared volatile. However, they are only modified in a + * functionally atomic way (within critical sections of with the scheduler + * suspended) and are either passed by reference into a function or indexed via + * a volatile variable. Therefore, in all use cases tested so far, the volatile + * qualifier can be omitted in order to provide a moderate performance + * improvement without adversely affecting functional behaviour. The assembly + * instructions generated by the IAR, ARM and GCC compilers when the respective + * compiler's options were set for maximum optimisation has been inspected and + * deemed to be as intended. That said, as compiler technology advances, and + * especially if aggressive cross module optimisation is used (a use case that + * has not been exercised to any great extend) then it is feasible that the + * volatile qualifier will be needed for correct optimisation. It is expected + * that a compiler removing essential code because, without the volatile + * qualifier on the list structure members and with aggressive cross module + * optimisation, the compiler deemed the code unnecessary will result in + * complete and obvious failure of the scheduler. If this is ever experienced + * then the volatile qualifier can be inserted in the relevant places within the + * list structures by simply defining configLIST_VOLATILE to volatile in + * FreeRTOSConfig.h (as per the example at the bottom of this comment block). + * If configLIST_VOLATILE is not defined then the preprocessor directives below + * will simply #define configLIST_VOLATILE away completely. + * + * To use volatile list structure members then add the following line to + * FreeRTOSConfig.h (without the quotes): + * "#define configLIST_VOLATILE volatile" + */ +#ifndef configLIST_VOLATILE + #define configLIST_VOLATILE +#endif /* configSUPPORT_CROSS_MODULE_OPTIMISATION */ + +#ifdef __cplusplus +extern "C" { +#endif +/* + * Definition of the only type of object that a list can contain. + */ +struct xLIST_ITEM +{ + configLIST_VOLATILE TickType_t xItemValue; /*< The value being listed. In most cases this is used to sort the list in descending order. */ + struct xLIST_ITEM * configLIST_VOLATILE pxNext; /*< Pointer to the next ListItem_t in the list. */ + struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; /*< Pointer to the previous ListItem_t in the list. */ + void * pvOwner; /*< Pointer to the object (normally a TCB) that contains the list item. There is therefore a two way link between the object containing the list item and the list item itself. */ + void * configLIST_VOLATILE pvContainer; /*< Pointer to the list in which this list item is placed (if any). */ +}; +typedef struct xLIST_ITEM ListItem_t; /* For some reason lint wants this as two separate definitions. */ + +struct xMINI_LIST_ITEM +{ + configLIST_VOLATILE TickType_t xItemValue; + struct xLIST_ITEM * configLIST_VOLATILE pxNext; + struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; +}; +typedef struct xMINI_LIST_ITEM MiniListItem_t; + +/* + * Definition of the type of queue used by the scheduler. + */ +typedef struct xLIST +{ + configLIST_VOLATILE UBaseType_t uxNumberOfItems; + ListItem_t * configLIST_VOLATILE pxIndex; /*< Used to walk through the list. Points to the last item returned by a call to listGET_OWNER_OF_NEXT_ENTRY (). */ + MiniListItem_t xListEnd; /*< List item that contains the maximum possible item value meaning it is always at the end of the list and is therefore used as a marker. */ +} List_t; + +/* + * Access macro to set the owner of a list item. The owner of a list item + * is the object (usually a TCB) that contains the list item. + * + * \page listSET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER + * \ingroup LinkedList + */ +#define listSET_LIST_ITEM_OWNER( pxListItem, pxOwner ) ( ( pxListItem )->pvOwner = ( void * ) ( pxOwner ) ) + +/* + * Access macro to get the owner of a list item. The owner of a list item + * is the object (usually a TCB) that contains the list item. + * + * \page listSET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER + * \ingroup LinkedList + */ +#define listGET_LIST_ITEM_OWNER( pxListItem ) ( ( pxListItem )->pvOwner ) + +/* + * Access macro to set the value of the list item. In most cases the value is + * used to sort the list in descending order. + * + * \page listSET_LIST_ITEM_VALUE listSET_LIST_ITEM_VALUE + * \ingroup LinkedList + */ +#define listSET_LIST_ITEM_VALUE( pxListItem, xValue ) ( ( pxListItem )->xItemValue = ( xValue ) ) + +/* + * Access macro to retrieve the value of the list item. The value can + * represent anything - for example the priority of a task, or the time at + * which a task should be unblocked. + * + * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE + * \ingroup LinkedList + */ +#define listGET_LIST_ITEM_VALUE( pxListItem ) ( ( pxListItem )->xItemValue ) + +/* + * Access macro to retrieve the value of the list item at the head of a given + * list. + * + * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE + * \ingroup LinkedList + */ +#define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext->xItemValue ) + +/* + * Return the list item at the head of the list. + * + * \page listGET_HEAD_ENTRY listGET_HEAD_ENTRY + * \ingroup LinkedList + */ +#define listGET_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext ) + +/* + * Return the list item at the head of the list. + * + * \page listGET_NEXT listGET_NEXT + * \ingroup LinkedList + */ +#define listGET_NEXT( pxListItem ) ( ( pxListItem )->pxNext ) + +/* + * Return the list item that marks the end of the list + * + * \page listGET_END_MARKER listGET_END_MARKER + * \ingroup LinkedList + */ +#define listGET_END_MARKER( pxList ) ( ( ListItem_t const * ) ( &( ( pxList )->xListEnd ) ) ) + +/* + * Access macro to determine if a list contains any items. The macro will + * only have the value true if the list is empty. + * + * \page listLIST_IS_EMPTY listLIST_IS_EMPTY + * \ingroup LinkedList + */ +#define listLIST_IS_EMPTY( pxList ) ( ( BaseType_t ) ( ( pxList )->uxNumberOfItems == ( UBaseType_t ) 0 ) ) + +/* + * Access macro to return the number of items in the list. + */ +#define listCURRENT_LIST_LENGTH( pxList ) ( ( pxList )->uxNumberOfItems ) + +/* + * Access function to obtain the owner of the next entry in a list. + * + * The list member pxIndex is used to walk through a list. Calling + * listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list + * and returns that entry's pxOwner parameter. Using multiple calls to this + * function it is therefore possible to move through every item contained in + * a list. + * + * The pxOwner parameter of a list item is a pointer to the object that owns + * the list item. In the scheduler this is normally a task control block. + * The pxOwner parameter effectively creates a two way link between the list + * item and its owner. + * + * @param pxTCB pxTCB is set to the address of the owner of the next list item. + * @param pxList The list from which the next item owner is to be returned. + * + * \page listGET_OWNER_OF_NEXT_ENTRY listGET_OWNER_OF_NEXT_ENTRY + * \ingroup LinkedList + */ +#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList ) \ +{ \ +List_t * const pxConstList = ( pxList ); \ + /* Increment the index to the next item and return the item, ensuring */ \ + /* we don't return the marker used at the end of the list. */ \ + ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \ + if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) ) \ + { \ + ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \ + } \ + ( pxTCB ) = ( pxConstList )->pxIndex->pvOwner; \ +} + + +/* + * Access function to obtain the owner of the first entry in a list. Lists + * are normally sorted in ascending item value order. + * + * This function returns the pxOwner member of the first item in the list. + * The pxOwner parameter of a list item is a pointer to the object that owns + * the list item. In the scheduler this is normally a task control block. + * The pxOwner parameter effectively creates a two way link between the list + * item and its owner. + * + * @param pxList The list from which the owner of the head item is to be + * returned. + * + * \page listGET_OWNER_OF_HEAD_ENTRY listGET_OWNER_OF_HEAD_ENTRY + * \ingroup LinkedList + */ +#define listGET_OWNER_OF_HEAD_ENTRY( pxList ) ( (&( ( pxList )->xListEnd ))->pxNext->pvOwner ) + +/* + * Check to see if a list item is within a list. The list item maintains a + * "container" pointer that points to the list it is in. All this macro does + * is check to see if the container and the list match. + * + * @param pxList The list we want to know if the list item is within. + * @param pxListItem The list item we want to know if is in the list. + * @return pdTRUE if the list item is in the list, otherwise pdFALSE. + */ +#define listIS_CONTAINED_WITHIN( pxList, pxListItem ) ( ( BaseType_t ) ( ( pxListItem )->pvContainer == ( void * ) ( pxList ) ) ) + +/* + * Return the list a list item is contained within (referenced from). + * + * @param pxListItem The list item being queried. + * @return A pointer to the List_t object that references the pxListItem + */ +#define listLIST_ITEM_CONTAINER( pxListItem ) ( ( pxListItem )->pvContainer ) + +/* + * This provides a crude means of knowing if a list has been initialised, as + * pxList->xListEnd.xItemValue is set to portMAX_DELAY by the vListInitialise() + * function. + */ +#define listLIST_IS_INITIALISED( pxList ) ( ( pxList )->xListEnd.xItemValue == portMAX_DELAY ) + +/* + * Must be called before a list is used! This initialises all the members + * of the list structure and inserts the xListEnd item into the list as a + * marker to the back of the list. + * + * @param pxList Pointer to the list being initialised. + * + * \page vListInitialise vListInitialise + * \ingroup LinkedList + */ +void vListInitialise( List_t * const pxList ); + +/* + * Must be called before a list item is used. This sets the list container to + * null so the item does not think that it is already contained in a list. + * + * @param pxItem Pointer to the list item being initialised. + * + * \page vListInitialiseItem vListInitialiseItem + * \ingroup LinkedList + */ +void vListInitialiseItem( ListItem_t * const pxItem ); + +/* + * Insert a list item into a list. The item will be inserted into the list in + * a position determined by its item value (descending item value order). + * + * @param pxList The list into which the item is to be inserted. + * + * @param pxNewListItem The item that is to be placed in the list. + * + * \page vListInsert vListInsert + * \ingroup LinkedList + */ +void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem ); + +/* + * Insert a list item into a list. The item will be inserted in a position + * such that it will be the last item within the list returned by multiple + * calls to listGET_OWNER_OF_NEXT_ENTRY. + * + * The list member pvIndex is used to walk through a list. Calling + * listGET_OWNER_OF_NEXT_ENTRY increments pvIndex to the next item in the list. + * Placing an item in a list using vListInsertEnd effectively places the item + * in the list position pointed to by pvIndex. This means that every other + * item within the list will be returned by listGET_OWNER_OF_NEXT_ENTRY before + * the pvIndex parameter again points to the item being inserted. + * + * @param pxList The list into which the item is to be inserted. + * + * @param pxNewListItem The list item to be inserted into the list. + * + * \page vListInsertEnd vListInsertEnd + * \ingroup LinkedList + */ +void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem ); + +/* + * Remove an item from a list. The list item has a pointer to the list that + * it is in, so only the list item need be passed into the function. + * + * @param uxListRemove The item to be removed. The item will remove itself from + * the list pointed to by it's pxContainer parameter. + * + * @return The number of items that remain in the list after the list item has + * been removed. + * + * \page uxListRemove uxListRemove + * \ingroup LinkedList + */ +UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/os/freertos/freertos_v8.1.2/Source/include/mpu_wrappers.h b/component/os/freertos/freertos_v8.1.2/Source/include/mpu_wrappers.h new file mode 100644 index 0000000..6777be5 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/include/mpu_wrappers.h @@ -0,0 +1,153 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef MPU_WRAPPERS_H +#define MPU_WRAPPERS_H + +/* This file redefines API functions to be called through a wrapper macro, but +only for ports that are using the MPU. */ +#ifdef portUSING_MPU_WRAPPERS + + /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE will be defined when this file is + included from queue.c or task.c to prevent it from having an effect within + those files. */ + #ifndef MPU_WRAPPERS_INCLUDED_FROM_API_FILE + + #define xTaskGenericCreate MPU_xTaskGenericCreate + #define vTaskAllocateMPURegions MPU_vTaskAllocateMPURegions + #define vTaskDelete MPU_vTaskDelete + #define vTaskDelayUntil MPU_vTaskDelayUntil + #define vTaskDelay MPU_vTaskDelay + #define uxTaskPriorityGet MPU_uxTaskPriorityGet + #define vTaskPrioritySet MPU_vTaskPrioritySet + #define eTaskGetState MPU_eTaskGetState + #define vTaskSuspend MPU_vTaskSuspend + #define vTaskResume MPU_vTaskResume + #define vTaskSuspendAll MPU_vTaskSuspendAll + #define xTaskResumeAll MPU_xTaskResumeAll + #define xTaskGetTickCount MPU_xTaskGetTickCount + #define uxTaskGetNumberOfTasks MPU_uxTaskGetNumberOfTasks + #define vTaskList MPU_vTaskList + #define vTaskGetRunTimeStats MPU_vTaskGetRunTimeStats + #define vTaskSetApplicationTaskTag MPU_vTaskSetApplicationTaskTag + #define xTaskGetApplicationTaskTag MPU_xTaskGetApplicationTaskTag + #define xTaskCallApplicationTaskHook MPU_xTaskCallApplicationTaskHook + #define uxTaskGetStackHighWaterMark MPU_uxTaskGetStackHighWaterMark + #define xTaskGetCurrentTaskHandle MPU_xTaskGetCurrentTaskHandle + #define xTaskGetSchedulerState MPU_xTaskGetSchedulerState + #define xTaskGetIdleTaskHandle MPU_xTaskGetIdleTaskHandle + #define uxTaskGetSystemState MPU_uxTaskGetSystemState + + #define xQueueGenericCreate MPU_xQueueGenericCreate + #define xQueueCreateMutex MPU_xQueueCreateMutex + #define xQueueGiveMutexRecursive MPU_xQueueGiveMutexRecursive + #define xQueueTakeMutexRecursive MPU_xQueueTakeMutexRecursive + #define xQueueCreateCountingSemaphore MPU_xQueueCreateCountingSemaphore + #define xQueueGenericSend MPU_xQueueGenericSend + #define xQueueAltGenericSend MPU_xQueueAltGenericSend + #define xQueueAltGenericReceive MPU_xQueueAltGenericReceive + #define xQueueGenericReceive MPU_xQueueGenericReceive + #define uxQueueMessagesWaiting MPU_uxQueueMessagesWaiting + #define vQueueDelete MPU_vQueueDelete + #define xQueueGenericReset MPU_xQueueGenericReset + #define xQueueCreateSet MPU_xQueueCreateSet + #define xQueueSelectFromSet MPU_xQueueSelectFromSet + #define xQueueAddToSet MPU_xQueueAddToSet + #define xQueueRemoveFromSet MPU_xQueueRemoveFromSet + #define xQueuePeekFromISR MPU_xQueuePeekFromISR + #define xQueueGetMutexHolder MPU_xQueueGetMutexHolder + + #define pvPortMalloc MPU_pvPortMalloc + #define vPortFree MPU_vPortFree + #define xPortGetFreeHeapSize MPU_xPortGetFreeHeapSize + #define vPortInitialiseBlocks MPU_vPortInitialiseBlocks + + #if configQUEUE_REGISTRY_SIZE > 0 + #define vQueueAddToRegistry MPU_vQueueAddToRegistry + #define vQueueUnregisterQueue MPU_vQueueUnregisterQueue + #endif + + /* Remove the privileged function macro. */ + #define PRIVILEGED_FUNCTION + + #else /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */ + + /* Ensure API functions go in the privileged execution section. */ + #define PRIVILEGED_FUNCTION __attribute__((section("privileged_functions"))) + #define PRIVILEGED_DATA __attribute__((section("privileged_data"))) + + #endif /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */ + +#else /* portUSING_MPU_WRAPPERS */ + + #define PRIVILEGED_FUNCTION + #define PRIVILEGED_DATA + #define portUSING_MPU_WRAPPERS 0 + +#endif /* portUSING_MPU_WRAPPERS */ + + +#endif /* MPU_WRAPPERS_H */ + diff --git a/component/os/freertos/freertos_v8.1.2/Source/include/portable.h b/component/os/freertos/freertos_v8.1.2/Source/include/portable.h new file mode 100644 index 0000000..f63e99f --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/include/portable.h @@ -0,0 +1,426 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/*----------------------------------------------------------- + * Portable layer API. Each function must be defined for each port. + *----------------------------------------------------------*/ + +#ifndef PORTABLE_H +#define PORTABLE_H + +/* Include the macro file relevant to the port being used. +NOTE: The following definitions are *DEPRECATED* as it is preferred to instead +just add the path to the correct portmacro.h header file to the compiler's +include path. */ +#ifdef OPEN_WATCOM_INDUSTRIAL_PC_PORT + #include "..\..\Source\portable\owatcom\16bitdos\pc\portmacro.h" + typedef void ( __interrupt __far *pxISR )(); +#endif + +#ifdef OPEN_WATCOM_FLASH_LITE_186_PORT + #include "..\..\Source\portable\owatcom\16bitdos\flsh186\portmacro.h" + typedef void ( __interrupt __far *pxISR )(); +#endif + +#ifdef GCC_MEGA_AVR + #include "../portable/GCC/ATMega323/portmacro.h" +#endif + +#ifdef IAR_MEGA_AVR + #include "../portable/IAR/ATMega323/portmacro.h" +#endif + +#ifdef MPLAB_PIC24_PORT + #include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h" +#endif + +#ifdef MPLAB_DSPIC_PORT + #include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h" +#endif + +#ifdef MPLAB_PIC18F_PORT + #include "../../Source/portable/MPLAB/PIC18F/portmacro.h" +#endif + +#ifdef MPLAB_PIC32MX_PORT + #include "../../Source/portable/MPLAB/PIC32MX/portmacro.h" +#endif + +#ifdef _FEDPICC + #include "libFreeRTOS/Include/portmacro.h" +#endif + +#ifdef SDCC_CYGNAL + #include "../../Source/portable/SDCC/Cygnal/portmacro.h" +#endif + +#ifdef GCC_ARM7 + #include "../../Source/portable/GCC/ARM7_LPC2000/portmacro.h" +#endif + +#ifdef GCC_ARM7_ECLIPSE + #include "portmacro.h" +#endif + +#ifdef ROWLEY_LPC23xx + #include "../../Source/portable/GCC/ARM7_LPC23xx/portmacro.h" +#endif + +#ifdef IAR_MSP430 + #include "..\..\Source\portable\IAR\MSP430\portmacro.h" +#endif + +#ifdef GCC_MSP430 + #include "../../Source/portable/GCC/MSP430F449/portmacro.h" +#endif + +#ifdef ROWLEY_MSP430 + #include "../../Source/portable/Rowley/MSP430F449/portmacro.h" +#endif + +#ifdef ARM7_LPC21xx_KEIL_RVDS + #include "..\..\Source\portable\RVDS\ARM7_LPC21xx\portmacro.h" +#endif + +#ifdef SAM7_GCC + #include "../../Source/portable/GCC/ARM7_AT91SAM7S/portmacro.h" +#endif + +#ifdef SAM7_IAR + #include "..\..\Source\portable\IAR\AtmelSAM7S64\portmacro.h" +#endif + +#ifdef SAM9XE_IAR + #include "..\..\Source\portable\IAR\AtmelSAM9XE\portmacro.h" +#endif + +#ifdef LPC2000_IAR + #include "..\..\Source\portable\IAR\LPC2000\portmacro.h" +#endif + +#ifdef STR71X_IAR + #include "..\..\Source\portable\IAR\STR71x\portmacro.h" +#endif + +#ifdef STR75X_IAR + #include "..\..\Source\portable\IAR\STR75x\portmacro.h" +#endif + +#ifdef STR75X_GCC + #include "..\..\Source\portable\GCC\STR75x\portmacro.h" +#endif + +#ifdef STR91X_IAR + #include "..\..\Source\portable\IAR\STR91x\portmacro.h" +#endif + +#ifdef GCC_H8S + #include "../../Source/portable/GCC/H8S2329/portmacro.h" +#endif + +#ifdef GCC_AT91FR40008 + #include "../../Source/portable/GCC/ARM7_AT91FR40008/portmacro.h" +#endif + +#ifdef RVDS_ARMCM3_LM3S102 + #include "../../Source/portable/RVDS/ARM_CM3/portmacro.h" +#endif + +#ifdef GCC_ARMCM3_LM3S102 + #include "../../Source/portable/GCC/ARM_CM3/portmacro.h" +#endif + +#ifdef GCC_ARMCM3 + #include "../../Source/portable/GCC/ARM_CM3/portmacro.h" +#endif + +#ifdef IAR_ARM_CM3 + #include "../../Source/portable/IAR/ARM_CM3/portmacro.h" +#endif + +#ifdef IAR_ARMCM3_LM + #include "../../Source/portable/IAR/ARM_CM3/portmacro.h" +#endif + +#ifdef HCS12_CODE_WARRIOR + #include "../../Source/portable/CodeWarrior/HCS12/portmacro.h" +#endif + +#ifdef MICROBLAZE_GCC + #include "../../Source/portable/GCC/MicroBlaze/portmacro.h" +#endif + +#ifdef TERN_EE + #include "..\..\Source\portable\Paradigm\Tern_EE\small\portmacro.h" +#endif + +#ifdef GCC_HCS12 + #include "../../Source/portable/GCC/HCS12/portmacro.h" +#endif + +#ifdef GCC_MCF5235 + #include "../../Source/portable/GCC/MCF5235/portmacro.h" +#endif + +#ifdef COLDFIRE_V2_GCC + #include "../../../Source/portable/GCC/ColdFire_V2/portmacro.h" +#endif + +#ifdef COLDFIRE_V2_CODEWARRIOR + #include "../../Source/portable/CodeWarrior/ColdFire_V2/portmacro.h" +#endif + +#ifdef GCC_PPC405 + #include "../../Source/portable/GCC/PPC405_Xilinx/portmacro.h" +#endif + +#ifdef GCC_PPC440 + #include "../../Source/portable/GCC/PPC440_Xilinx/portmacro.h" +#endif + +#ifdef _16FX_SOFTUNE + #include "..\..\Source\portable\Softune\MB96340\portmacro.h" +#endif + +#ifdef BCC_INDUSTRIAL_PC_PORT + /* A short file name has to be used in place of the normal + FreeRTOSConfig.h when using the Borland compiler. */ + #include "frconfig.h" + #include "..\portable\BCC\16BitDOS\PC\prtmacro.h" + typedef void ( __interrupt __far *pxISR )(); +#endif + +#ifdef BCC_FLASH_LITE_186_PORT + /* A short file name has to be used in place of the normal + FreeRTOSConfig.h when using the Borland compiler. */ + #include "frconfig.h" + #include "..\portable\BCC\16BitDOS\flsh186\prtmacro.h" + typedef void ( __interrupt __far *pxISR )(); +#endif + +#ifdef __GNUC__ + #ifdef __AVR32_AVR32A__ + #include "portmacro.h" + #endif +#endif + +#ifdef __ICCAVR32__ + #ifdef __CORE__ + #if __CORE__ == __AVR32A__ + #include "portmacro.h" + #endif + #endif +#endif + +#ifdef __91467D + #include "portmacro.h" +#endif + +#ifdef __96340 + #include "portmacro.h" +#endif + + +#ifdef __IAR_V850ES_Fx3__ + #include "../../Source/portable/IAR/V850ES/portmacro.h" +#endif + +#ifdef __IAR_V850ES_Jx3__ + #include "../../Source/portable/IAR/V850ES/portmacro.h" +#endif + +#ifdef __IAR_V850ES_Jx3_L__ + #include "../../Source/portable/IAR/V850ES/portmacro.h" +#endif + +#ifdef __IAR_V850ES_Jx2__ + #include "../../Source/portable/IAR/V850ES/portmacro.h" +#endif + +#ifdef __IAR_V850ES_Hx2__ + #include "../../Source/portable/IAR/V850ES/portmacro.h" +#endif + +#ifdef __IAR_78K0R_Kx3__ + #include "../../Source/portable/IAR/78K0R/portmacro.h" +#endif + +#ifdef __IAR_78K0R_Kx3L__ + #include "../../Source/portable/IAR/78K0R/portmacro.h" +#endif + +/* Catch all to ensure portmacro.h is included in the build. Newer demos +have the path as part of the project options, rather than as relative from +the project location. If portENTER_CRITICAL() has not been defined then +portmacro.h has not yet been included - as every portmacro.h provides a +portENTER_CRITICAL() definition. Check the demo application for your demo +to find the path to the correct portmacro.h file. */ +#ifndef portENTER_CRITICAL + #include "portmacro.h" +#endif + +#if portBYTE_ALIGNMENT == 8 + #define portBYTE_ALIGNMENT_MASK ( 0x0007U ) +#endif + +#if portBYTE_ALIGNMENT == 4 + #define portBYTE_ALIGNMENT_MASK ( 0x0003 ) +#endif + +#if portBYTE_ALIGNMENT == 2 + #define portBYTE_ALIGNMENT_MASK ( 0x0001 ) +#endif + +#if portBYTE_ALIGNMENT == 1 + #define portBYTE_ALIGNMENT_MASK ( 0x0000 ) +#endif + +#ifndef portBYTE_ALIGNMENT_MASK + #error "Invalid portBYTE_ALIGNMENT definition" +#endif + +#ifndef portNUM_CONFIGURABLE_REGIONS + #define portNUM_CONFIGURABLE_REGIONS 1 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mpu_wrappers.h" + +/* + * Setup the stack of a new task so it is ready to be placed under the + * scheduler control. The registers have to be placed on the stack in + * the order that the port expects to find them. + * + */ +#if( portUSING_MPU_WRAPPERS == 1 ) + StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged ) PRIVILEGED_FUNCTION; +#else + StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) PRIVILEGED_FUNCTION; +#endif + +/* Used by heap_5.c. */ +typedef struct HeapRegion +{ + uint8_t *pucStartAddress; + size_t xSizeInBytes; +} HeapRegion_t; + +/* + * Used to define multiple heap regions for use by heap_5.c. This function + * must be called before any calls to pvPortMalloc() - not creating a task, + * queue, semaphore, mutex, software timer, event group, etc. will result in + * pvPortMalloc being called. + * + * pxHeapRegions passes in an array of HeapRegion_t structures - each of which + * defines a region of memory that can be used as the heap. The array is + * terminated by a HeapRegions_t structure that has a size of 0. The region + * with the lowest start address must appear first in the array. + */ +void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions ); + + +/* + * Map to the memory management routines required for the port. + */ +void *pvPortMalloc( size_t xSize ) PRIVILEGED_FUNCTION; +void vPortFree( void *pv ) PRIVILEGED_FUNCTION; +void vPortInitialiseBlocks( void ) PRIVILEGED_FUNCTION; +size_t xPortGetFreeHeapSize( void ) PRIVILEGED_FUNCTION; +size_t xPortGetMinimumEverFreeHeapSize( void ) PRIVILEGED_FUNCTION; + +/* + * Setup the hardware ready for the scheduler to take control. This generally + * sets up a tick interrupt and sets timers for the correct tick frequency. + */ +BaseType_t xPortStartScheduler( void ) PRIVILEGED_FUNCTION; + +/* + * Undo any hardware/ISR setup that was performed by xPortStartScheduler() so + * the hardware is left in its original condition after the scheduler stops + * executing. + */ +void vPortEndScheduler( void ) PRIVILEGED_FUNCTION; + +/* + * The structures and methods of manipulating the MPU are contained within the + * port layer. + * + * Fills the xMPUSettings structure with the memory region information + * contained in xRegions. + */ +#if( portUSING_MPU_WRAPPERS == 1 ) + struct xMEMORY_REGION; + void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, StackType_t *pxBottomOfStack, uint16_t usStackDepth ) PRIVILEGED_FUNCTION; +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* PORTABLE_H */ + diff --git a/component/os/freertos/freertos_v8.1.2/Source/include/projdefs.h b/component/os/freertos/freertos_v8.1.2/Source/include/projdefs.h new file mode 100644 index 0000000..9eccedf --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/include/projdefs.h @@ -0,0 +1,94 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef PROJDEFS_H +#define PROJDEFS_H + +/* + * Defines the prototype to which task functions must conform. Defined in this + * file to ensure the type is known before portable.h is included. + */ +typedef void (*TaskFunction_t)( void * ); + +/* Converts a time in milliseconds to a time in ticks. */ +#define pdMS_TO_TICKS( xTimeInMs ) ( ( ( TickType_t ) ( xTimeInMs ) * configTICK_RATE_HZ ) / ( TickType_t ) 1000 ) + +#define pdFALSE ( ( BaseType_t ) 0 ) +#define pdTRUE ( ( BaseType_t ) 1 ) + +#define pdPASS ( pdTRUE ) +#define pdFAIL ( pdFALSE ) +#define errQUEUE_EMPTY ( ( BaseType_t ) 0 ) +#define errQUEUE_FULL ( ( BaseType_t ) 0 ) + +/* Error definitions. */ +#define errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY ( -1 ) +#define errQUEUE_BLOCKED ( -4 ) +#define errQUEUE_YIELD ( -5 ) + +#endif /* PROJDEFS_H */ + + + diff --git a/component/os/freertos/freertos_v8.1.2/Source/include/queue.h b/component/os/freertos/freertos_v8.1.2/Source/include/queue.h new file mode 100644 index 0000000..a728a7c --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/include/queue.h @@ -0,0 +1,1687 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +#ifndef QUEUE_H +#define QUEUE_H + +#ifndef INC_FREERTOS_H + #error "include FreeRTOS.h" must appear in source files before "include queue.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Type by which queues are referenced. For example, a call to xQueueCreate() + * returns an QueueHandle_t variable that can then be used as a parameter to + * xQueueSend(), xQueueReceive(), etc. + */ +typedef void * QueueHandle_t; + +/** + * Type by which queue sets are referenced. For example, a call to + * xQueueCreateSet() returns an xQueueSet variable that can then be used as a + * parameter to xQueueSelectFromSet(), xQueueAddToSet(), etc. + */ +typedef void * QueueSetHandle_t; + +/** + * Queue sets can contain both queues and semaphores, so the + * QueueSetMemberHandle_t is defined as a type to be used where a parameter or + * return value can be either an QueueHandle_t or an SemaphoreHandle_t. + */ +typedef void * QueueSetMemberHandle_t; + +/* For internal use only. */ +#define queueSEND_TO_BACK ( ( BaseType_t ) 0 ) +#define queueSEND_TO_FRONT ( ( BaseType_t ) 1 ) +#define queueOVERWRITE ( ( BaseType_t ) 2 ) + +/* For internal use only. These definitions *must* match those in queue.c. */ +#define queueQUEUE_TYPE_BASE ( ( uint8_t ) 0U ) +#define queueQUEUE_TYPE_SET ( ( uint8_t ) 0U ) +#define queueQUEUE_TYPE_MUTEX ( ( uint8_t ) 1U ) +#define queueQUEUE_TYPE_COUNTING_SEMAPHORE ( ( uint8_t ) 2U ) +#define queueQUEUE_TYPE_BINARY_SEMAPHORE ( ( uint8_t ) 3U ) +#define queueQUEUE_TYPE_RECURSIVE_MUTEX ( ( uint8_t ) 4U ) + +/** + * queue. h + *
+ QueueHandle_t xQueueCreate(
+							  UBaseType_t uxQueueLength,
+							  UBaseType_t uxItemSize
+						  );
+ * 
+ * + * Creates a new queue instance. This allocates the storage required by the + * new queue and returns a handle for the queue. + * + * @param uxQueueLength The maximum number of items that the queue can contain. + * + * @param uxItemSize The number of bytes each item in the queue will require. + * Items are queued by copy, not by reference, so this is the number of bytes + * that will be copied for each posted item. Each item on the queue must be + * the same size. + * + * @return If the queue is successfully create then a handle to the newly + * created queue is returned. If the queue cannot be created then 0 is + * returned. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ };
+
+ void vATask( void *pvParameters )
+ {
+ QueueHandle_t xQueue1, xQueue2;
+
+	// Create a queue capable of containing 10 uint32_t values.
+	xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
+	if( xQueue1 == 0 )
+	{
+		// Queue was not created and must not be used.
+	}
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+	if( xQueue2 == 0 )
+	{
+		// Queue was not created and must not be used.
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueCreate xQueueCreate + * \ingroup QueueManagement + */ +#define xQueueCreate( uxQueueLength, uxItemSize ) xQueueGenericCreate( uxQueueLength, uxItemSize, queueQUEUE_TYPE_BASE ) + +/** + * queue. h + *
+ BaseType_t xQueueSendToToFront(
+								   QueueHandle_t	xQueue,
+								   const void		*pvItemToQueue,
+								   TickType_t		xTicksToWait
+							   );
+ * 
+ * + * This is a macro that calls xQueueGenericSend(). + * + * Post an item to the front of a queue. The item is queued by copy, not by + * reference. This function must not be called from an interrupt service + * routine. See xQueueSendFromISR () for an alternative which may be used + * in an ISR. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for space to become available on the queue, should it already + * be full. The call will return immediately if this is set to 0 and the + * queue is full. The time is defined in tick periods so the constant + * portTICK_PERIOD_MS should be used to convert to real time if this is required. + * + * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ uint32_t ulVar = 10UL;
+
+ void vATask( void *pvParameters )
+ {
+ QueueHandle_t xQueue1, xQueue2;
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 uint32_t values.
+	xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+
+	// ...
+
+	if( xQueue1 != 0 )
+	{
+		// Send an uint32_t.  Wait for 10 ticks for space to become
+		// available if necessary.
+		if( xQueueSendToFront( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10 ) != pdPASS )
+		{
+			// Failed to post the message, even after 10 ticks.
+		}
+	}
+
+	if( xQueue2 != 0 )
+	{
+		// Send a pointer to a struct AMessage object.  Don't block if the
+		// queue is already full.
+		pxMessage = & xMessage;
+		xQueueSendToFront( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0 );
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueSend xQueueSend + * \ingroup QueueManagement + */ +#define xQueueSendToFront( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_FRONT ) + +/** + * queue. h + *
+ BaseType_t xQueueSendToBack(
+								   QueueHandle_t	xQueue,
+								   const void		*pvItemToQueue,
+								   TickType_t		xTicksToWait
+							   );
+ * 
+ * + * This is a macro that calls xQueueGenericSend(). + * + * Post an item to the back of a queue. The item is queued by copy, not by + * reference. This function must not be called from an interrupt service + * routine. See xQueueSendFromISR () for an alternative which may be used + * in an ISR. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for space to become available on the queue, should it already + * be full. The call will return immediately if this is set to 0 and the queue + * is full. The time is defined in tick periods so the constant + * portTICK_PERIOD_MS should be used to convert to real time if this is required. + * + * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ uint32_t ulVar = 10UL;
+
+ void vATask( void *pvParameters )
+ {
+ QueueHandle_t xQueue1, xQueue2;
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 uint32_t values.
+	xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+
+	// ...
+
+	if( xQueue1 != 0 )
+	{
+		// Send an uint32_t.  Wait for 10 ticks for space to become
+		// available if necessary.
+		if( xQueueSendToBack( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10 ) != pdPASS )
+		{
+			// Failed to post the message, even after 10 ticks.
+		}
+	}
+
+	if( xQueue2 != 0 )
+	{
+		// Send a pointer to a struct AMessage object.  Don't block if the
+		// queue is already full.
+		pxMessage = & xMessage;
+		xQueueSendToBack( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0 );
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueSend xQueueSend + * \ingroup QueueManagement + */ +#define xQueueSendToBack( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK ) + +/** + * queue. h + *
+ BaseType_t xQueueSend(
+							  QueueHandle_t xQueue,
+							  const void * pvItemToQueue,
+							  TickType_t xTicksToWait
+						 );
+ * 
+ * + * This is a macro that calls xQueueGenericSend(). It is included for + * backward compatibility with versions of FreeRTOS.org that did not + * include the xQueueSendToFront() and xQueueSendToBack() macros. It is + * equivalent to xQueueSendToBack(). + * + * Post an item on a queue. The item is queued by copy, not by reference. + * This function must not be called from an interrupt service routine. + * See xQueueSendFromISR () for an alternative which may be used in an ISR. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for space to become available on the queue, should it already + * be full. The call will return immediately if this is set to 0 and the + * queue is full. The time is defined in tick periods so the constant + * portTICK_PERIOD_MS should be used to convert to real time if this is required. + * + * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ uint32_t ulVar = 10UL;
+
+ void vATask( void *pvParameters )
+ {
+ QueueHandle_t xQueue1, xQueue2;
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 uint32_t values.
+	xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+
+	// ...
+
+	if( xQueue1 != 0 )
+	{
+		// Send an uint32_t.  Wait for 10 ticks for space to become
+		// available if necessary.
+		if( xQueueSend( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10 ) != pdPASS )
+		{
+			// Failed to post the message, even after 10 ticks.
+		}
+	}
+
+	if( xQueue2 != 0 )
+	{
+		// Send a pointer to a struct AMessage object.  Don't block if the
+		// queue is already full.
+		pxMessage = & xMessage;
+		xQueueSend( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0 );
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueSend xQueueSend + * \ingroup QueueManagement + */ +#define xQueueSend( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK ) + +/** + * queue. h + *
+ BaseType_t xQueueOverwrite(
+							  QueueHandle_t xQueue,
+							  const void * pvItemToQueue
+						 );
+ * 
+ * + * Only for use with queues that have a length of one - so the queue is either + * empty or full. + * + * Post an item on a queue. If the queue is already full then overwrite the + * value held in the queue. The item is queued by copy, not by reference. + * + * This function must not be called from an interrupt service routine. + * See xQueueOverwriteFromISR () for an alternative which may be used in an ISR. + * + * @param xQueue The handle of the queue to which the data is being sent. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @return xQueueOverwrite() is a macro that calls xQueueGenericSend(), and + * therefore has the same return values as xQueueSendToFront(). However, pdPASS + * is the only value that can be returned because xQueueOverwrite() will write + * to the queue even when the queue is already full. + * + * Example usage: +
+
+ void vFunction( void *pvParameters )
+ {
+ QueueHandle_t xQueue;
+ uint32_t ulVarToSend, ulValReceived;
+
+	// Create a queue to hold one uint32_t value.  It is strongly
+	// recommended *not* to use xQueueOverwrite() on queues that can
+	// contain more than one value, and doing so will trigger an assertion
+	// if configASSERT() is defined.
+	xQueue = xQueueCreate( 1, sizeof( uint32_t ) );
+
+	// Write the value 10 to the queue using xQueueOverwrite().
+	ulVarToSend = 10;
+	xQueueOverwrite( xQueue, &ulVarToSend );
+
+	// Peeking the queue should now return 10, but leave the value 10 in
+	// the queue.  A block time of zero is used as it is known that the
+	// queue holds a value.
+	ulValReceived = 0;
+	xQueuePeek( xQueue, &ulValReceived, 0 );
+
+	if( ulValReceived != 10 )
+	{
+		// Error unless the item was removed by a different task.
+	}
+
+	// The queue is still full.  Use xQueueOverwrite() to overwrite the
+	// value held in the queue with 100.
+	ulVarToSend = 100;
+	xQueueOverwrite( xQueue, &ulVarToSend );
+
+	// This time read from the queue, leaving the queue empty once more.
+	// A block time of 0 is used again.
+	xQueueReceive( xQueue, &ulValReceived, 0 );
+
+	// The value read should be the last value written, even though the
+	// queue was already full when the value was written.
+	if( ulValReceived != 100 )
+	{
+		// Error!
+	}
+
+	// ...
+}
+ 
+ * \defgroup xQueueOverwrite xQueueOverwrite + * \ingroup QueueManagement + */ +#define xQueueOverwrite( xQueue, pvItemToQueue ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), 0, queueOVERWRITE ) + + +/** + * queue. h + *
+ BaseType_t xQueueGenericSend(
+									QueueHandle_t xQueue,
+									const void * pvItemToQueue,
+									TickType_t xTicksToWait
+									BaseType_t xCopyPosition
+								);
+ * 
+ * + * It is preferred that the macros xQueueSend(), xQueueSendToFront() and + * xQueueSendToBack() are used in place of calling this function directly. + * + * Post an item on a queue. The item is queued by copy, not by reference. + * This function must not be called from an interrupt service routine. + * See xQueueSendFromISR () for an alternative which may be used in an ISR. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for space to become available on the queue, should it already + * be full. The call will return immediately if this is set to 0 and the + * queue is full. The time is defined in tick periods so the constant + * portTICK_PERIOD_MS should be used to convert to real time if this is required. + * + * @param xCopyPosition Can take the value queueSEND_TO_BACK to place the + * item at the back of the queue, or queueSEND_TO_FRONT to place the item + * at the front of the queue (for high priority messages). + * + * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ uint32_t ulVar = 10UL;
+
+ void vATask( void *pvParameters )
+ {
+ QueueHandle_t xQueue1, xQueue2;
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 uint32_t values.
+	xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+
+	// ...
+
+	if( xQueue1 != 0 )
+	{
+		// Send an uint32_t.  Wait for 10 ticks for space to become
+		// available if necessary.
+		if( xQueueGenericSend( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10, queueSEND_TO_BACK ) != pdPASS )
+		{
+			// Failed to post the message, even after 10 ticks.
+		}
+	}
+
+	if( xQueue2 != 0 )
+	{
+		// Send a pointer to a struct AMessage object.  Don't block if the
+		// queue is already full.
+		pxMessage = & xMessage;
+		xQueueGenericSend( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0, queueSEND_TO_BACK );
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueSend xQueueSend + * \ingroup QueueManagement + */ +BaseType_t xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, const BaseType_t xCopyPosition ) PRIVILEGED_FUNCTION; + +/** + * queue. h + *
+ BaseType_t xQueuePeek(
+							 QueueHandle_t xQueue,
+							 void *pvBuffer,
+							 TickType_t xTicksToWait
+						 );
+ * + * This is a macro that calls the xQueueGenericReceive() function. + * + * Receive an item from a queue without removing the item from the queue. + * The item is received by copy so a buffer of adequate size must be + * provided. The number of bytes copied into the buffer was defined when + * the queue was created. + * + * Successfully received items remain on the queue so will be returned again + * by the next call, or a call to xQueueReceive(). + * + * This macro must not be used in an interrupt service routine. See + * xQueuePeekFromISR() for an alternative that can be called from an interrupt + * service routine. + * + * @param xQueue The handle to the queue from which the item is to be + * received. + * + * @param pvBuffer Pointer to the buffer into which the received item will + * be copied. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for an item to receive should the queue be empty at the time + * of the call. The time is defined in tick periods so the constant + * portTICK_PERIOD_MS should be used to convert to real time if this is required. + * xQueuePeek() will return immediately if xTicksToWait is 0 and the queue + * is empty. + * + * @return pdTRUE if an item was successfully received from the queue, + * otherwise pdFALSE. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ QueueHandle_t xQueue;
+
+ // Task to create a queue and post a value.
+ void vATask( void *pvParameters )
+ {
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
+	if( xQueue == 0 )
+	{
+		// Failed to create the queue.
+	}
+
+	// ...
+
+	// Send a pointer to a struct AMessage object.  Don't block if the
+	// queue is already full.
+	pxMessage = & xMessage;
+	xQueueSend( xQueue, ( void * ) &pxMessage, ( TickType_t ) 0 );
+
+	// ... Rest of task code.
+ }
+
+ // Task to peek the data from the queue.
+ void vADifferentTask( void *pvParameters )
+ {
+ struct AMessage *pxRxedMessage;
+
+	if( xQueue != 0 )
+	{
+		// Peek a message on the created queue.  Block for 10 ticks if a
+		// message is not immediately available.
+		if( xQueuePeek( xQueue, &( pxRxedMessage ), ( TickType_t ) 10 ) )
+		{
+			// pcRxedMessage now points to the struct AMessage variable posted
+			// by vATask, but the item still remains on the queue.
+		}
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueReceive xQueueReceive + * \ingroup QueueManagement + */ +#define xQueuePeek( xQueue, pvBuffer, xTicksToWait ) xQueueGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), pdTRUE ) + +/** + * queue. h + *
+ BaseType_t xQueuePeekFromISR(
+									QueueHandle_t xQueue,
+									void *pvBuffer,
+								);
+ * + * A version of xQueuePeek() that can be called from an interrupt service + * routine (ISR). + * + * Receive an item from a queue without removing the item from the queue. + * The item is received by copy so a buffer of adequate size must be + * provided. The number of bytes copied into the buffer was defined when + * the queue was created. + * + * Successfully received items remain on the queue so will be returned again + * by the next call, or a call to xQueueReceive(). + * + * @param xQueue The handle to the queue from which the item is to be + * received. + * + * @param pvBuffer Pointer to the buffer into which the received item will + * be copied. + * + * @return pdTRUE if an item was successfully received from the queue, + * otherwise pdFALSE. + * + * \defgroup xQueuePeekFromISR xQueuePeekFromISR + * \ingroup QueueManagement + */ +BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, void * const pvBuffer ) PRIVILEGED_FUNCTION; + +/** + * queue. h + *
+ BaseType_t xQueueReceive(
+								 QueueHandle_t xQueue,
+								 void *pvBuffer,
+								 TickType_t xTicksToWait
+							);
+ * + * This is a macro that calls the xQueueGenericReceive() function. + * + * Receive an item from a queue. The item is received by copy so a buffer of + * adequate size must be provided. The number of bytes copied into the buffer + * was defined when the queue was created. + * + * Successfully received items are removed from the queue. + * + * This function must not be used in an interrupt service routine. See + * xQueueReceiveFromISR for an alternative that can. + * + * @param xQueue The handle to the queue from which the item is to be + * received. + * + * @param pvBuffer Pointer to the buffer into which the received item will + * be copied. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for an item to receive should the queue be empty at the time + * of the call. xQueueReceive() will return immediately if xTicksToWait + * is zero and the queue is empty. The time is defined in tick periods so the + * constant portTICK_PERIOD_MS should be used to convert to real time if this is + * required. + * + * @return pdTRUE if an item was successfully received from the queue, + * otherwise pdFALSE. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ QueueHandle_t xQueue;
+
+ // Task to create a queue and post a value.
+ void vATask( void *pvParameters )
+ {
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
+	if( xQueue == 0 )
+	{
+		// Failed to create the queue.
+	}
+
+	// ...
+
+	// Send a pointer to a struct AMessage object.  Don't block if the
+	// queue is already full.
+	pxMessage = & xMessage;
+	xQueueSend( xQueue, ( void * ) &pxMessage, ( TickType_t ) 0 );
+
+	// ... Rest of task code.
+ }
+
+ // Task to receive from the queue.
+ void vADifferentTask( void *pvParameters )
+ {
+ struct AMessage *pxRxedMessage;
+
+	if( xQueue != 0 )
+	{
+		// Receive a message on the created queue.  Block for 10 ticks if a
+		// message is not immediately available.
+		if( xQueueReceive( xQueue, &( pxRxedMessage ), ( TickType_t ) 10 ) )
+		{
+			// pcRxedMessage now points to the struct AMessage variable posted
+			// by vATask.
+		}
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueReceive xQueueReceive + * \ingroup QueueManagement + */ +#define xQueueReceive( xQueue, pvBuffer, xTicksToWait ) xQueueGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), pdFALSE ) + + +/** + * queue. h + *
+ BaseType_t xQueueGenericReceive(
+									   QueueHandle_t	xQueue,
+									   void	*pvBuffer,
+									   TickType_t	xTicksToWait
+									   BaseType_t	xJustPeek
+									);
+ * + * It is preferred that the macro xQueueReceive() be used rather than calling + * this function directly. + * + * Receive an item from a queue. The item is received by copy so a buffer of + * adequate size must be provided. The number of bytes copied into the buffer + * was defined when the queue was created. + * + * This function must not be used in an interrupt service routine. See + * xQueueReceiveFromISR for an alternative that can. + * + * @param xQueue The handle to the queue from which the item is to be + * received. + * + * @param pvBuffer Pointer to the buffer into which the received item will + * be copied. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for an item to receive should the queue be empty at the time + * of the call. The time is defined in tick periods so the constant + * portTICK_PERIOD_MS should be used to convert to real time if this is required. + * xQueueGenericReceive() will return immediately if the queue is empty and + * xTicksToWait is 0. + * + * @param xJustPeek When set to true, the item received from the queue is not + * actually removed from the queue - meaning a subsequent call to + * xQueueReceive() will return the same item. When set to false, the item + * being received from the queue is also removed from the queue. + * + * @return pdTRUE if an item was successfully received from the queue, + * otherwise pdFALSE. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ QueueHandle_t xQueue;
+
+ // Task to create a queue and post a value.
+ void vATask( void *pvParameters )
+ {
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
+	if( xQueue == 0 )
+	{
+		// Failed to create the queue.
+	}
+
+	// ...
+
+	// Send a pointer to a struct AMessage object.  Don't block if the
+	// queue is already full.
+	pxMessage = & xMessage;
+	xQueueSend( xQueue, ( void * ) &pxMessage, ( TickType_t ) 0 );
+
+	// ... Rest of task code.
+ }
+
+ // Task to receive from the queue.
+ void vADifferentTask( void *pvParameters )
+ {
+ struct AMessage *pxRxedMessage;
+
+	if( xQueue != 0 )
+	{
+		// Receive a message on the created queue.  Block for 10 ticks if a
+		// message is not immediately available.
+		if( xQueueGenericReceive( xQueue, &( pxRxedMessage ), ( TickType_t ) 10 ) )
+		{
+			// pcRxedMessage now points to the struct AMessage variable posted
+			// by vATask.
+		}
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueReceive xQueueReceive + * \ingroup QueueManagement + */ +BaseType_t xQueueGenericReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait, const BaseType_t xJustPeek ) PRIVILEGED_FUNCTION; + +/** + * queue. h + *
UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue );
+ * + * Return the number of messages stored in a queue. + * + * @param xQueue A handle to the queue being queried. + * + * @return The number of messages available in the queue. + * + * \defgroup uxQueueMessagesWaiting uxQueueMessagesWaiting + * \ingroup QueueManagement + */ +UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; + +/** + * queue. h + *
UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue );
+ * + * Return the number of free spaces available in a queue. This is equal to the + * number of items that can be sent to the queue before the queue becomes full + * if no items are removed. + * + * @param xQueue A handle to the queue being queried. + * + * @return The number of spaces available in the queue. + * + * \defgroup uxQueueMessagesWaiting uxQueueMessagesWaiting + * \ingroup QueueManagement + */ +UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; + +/** + * queue. h + *
void vQueueDelete( QueueHandle_t xQueue );
+ * + * Delete a queue - freeing all the memory allocated for storing of items + * placed on the queue. + * + * @param xQueue A handle to the queue to be deleted. + * + * \defgroup vQueueDelete vQueueDelete + * \ingroup QueueManagement + */ +void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; + +/** + * queue. h + *
+ BaseType_t xQueueSendToFrontFromISR(
+										 QueueHandle_t xQueue,
+										 const void *pvItemToQueue,
+										 BaseType_t *pxHigherPriorityTaskWoken
+									  );
+ 
+ * + * This is a macro that calls xQueueGenericSendFromISR(). + * + * Post an item to the front of a queue. It is safe to use this macro from + * within an interrupt service routine. + * + * Items are queued by copy not reference so it is preferable to only + * queue small items, especially when called from an ISR. In most cases + * it would be preferable to store a pointer to the item being queued. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param pxHigherPriorityTaskWoken xQueueSendToFrontFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xQueueSendToFromFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @return pdTRUE if the data was successfully sent to the queue, otherwise + * errQUEUE_FULL. + * + * Example usage for buffered IO (where the ISR can obtain more than one value + * per call): +
+ void vBufferISR( void )
+ {
+ char cIn;
+ BaseType_t xHigherPrioritTaskWoken;
+
+	// We have not woken a task at the start of the ISR.
+	xHigherPriorityTaskWoken = pdFALSE;
+
+	// Loop until the buffer is empty.
+	do
+	{
+		// Obtain a byte from the buffer.
+		cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
+
+		// Post the byte.
+		xQueueSendToFrontFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );
+
+	} while( portINPUT_BYTE( BUFFER_COUNT ) );
+
+	// Now the buffer is empty we can switch context if necessary.
+	if( xHigherPriorityTaskWoken )
+	{
+		taskYIELD ();
+	}
+ }
+ 
+ * + * \defgroup xQueueSendFromISR xQueueSendFromISR + * \ingroup QueueManagement + */ +#define xQueueSendToFrontFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_FRONT ) + + +/** + * queue. h + *
+ BaseType_t xQueueSendToBackFromISR(
+										 QueueHandle_t xQueue,
+										 const void *pvItemToQueue,
+										 BaseType_t *pxHigherPriorityTaskWoken
+									  );
+ 
+ * + * This is a macro that calls xQueueGenericSendFromISR(). + * + * Post an item to the back of a queue. It is safe to use this macro from + * within an interrupt service routine. + * + * Items are queued by copy not reference so it is preferable to only + * queue small items, especially when called from an ISR. In most cases + * it would be preferable to store a pointer to the item being queued. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param pxHigherPriorityTaskWoken xQueueSendToBackFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xQueueSendToBackFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @return pdTRUE if the data was successfully sent to the queue, otherwise + * errQUEUE_FULL. + * + * Example usage for buffered IO (where the ISR can obtain more than one value + * per call): +
+ void vBufferISR( void )
+ {
+ char cIn;
+ BaseType_t xHigherPriorityTaskWoken;
+
+	// We have not woken a task at the start of the ISR.
+	xHigherPriorityTaskWoken = pdFALSE;
+
+	// Loop until the buffer is empty.
+	do
+	{
+		// Obtain a byte from the buffer.
+		cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
+
+		// Post the byte.
+		xQueueSendToBackFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );
+
+	} while( portINPUT_BYTE( BUFFER_COUNT ) );
+
+	// Now the buffer is empty we can switch context if necessary.
+	if( xHigherPriorityTaskWoken )
+	{
+		taskYIELD ();
+	}
+ }
+ 
+ * + * \defgroup xQueueSendFromISR xQueueSendFromISR + * \ingroup QueueManagement + */ +#define xQueueSendToBackFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK ) + +/** + * queue. h + *
+ BaseType_t xQueueOverwriteFromISR(
+							  QueueHandle_t xQueue,
+							  const void * pvItemToQueue,
+							  BaseType_t *pxHigherPriorityTaskWoken
+						 );
+ * 
+ * + * A version of xQueueOverwrite() that can be used in an interrupt service + * routine (ISR). + * + * Only for use with queues that can hold a single item - so the queue is either + * empty or full. + * + * Post an item on a queue. If the queue is already full then overwrite the + * value held in the queue. The item is queued by copy, not by reference. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param pxHigherPriorityTaskWoken xQueueOverwriteFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xQueueOverwriteFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @return xQueueOverwriteFromISR() is a macro that calls + * xQueueGenericSendFromISR(), and therefore has the same return values as + * xQueueSendToFrontFromISR(). However, pdPASS is the only value that can be + * returned because xQueueOverwriteFromISR() will write to the queue even when + * the queue is already full. + * + * Example usage: +
+
+ QueueHandle_t xQueue;
+
+ void vFunction( void *pvParameters )
+ {
+ 	// Create a queue to hold one uint32_t value.  It is strongly
+	// recommended *not* to use xQueueOverwriteFromISR() on queues that can
+	// contain more than one value, and doing so will trigger an assertion
+	// if configASSERT() is defined.
+	xQueue = xQueueCreate( 1, sizeof( uint32_t ) );
+}
+
+void vAnInterruptHandler( void )
+{
+// xHigherPriorityTaskWoken must be set to pdFALSE before it is used.
+BaseType_t xHigherPriorityTaskWoken = pdFALSE;
+uint32_t ulVarToSend, ulValReceived;
+
+	// Write the value 10 to the queue using xQueueOverwriteFromISR().
+	ulVarToSend = 10;
+	xQueueOverwriteFromISR( xQueue, &ulVarToSend, &xHigherPriorityTaskWoken );
+
+	// The queue is full, but calling xQueueOverwriteFromISR() again will still
+	// pass because the value held in the queue will be overwritten with the
+	// new value.
+	ulVarToSend = 100;
+	xQueueOverwriteFromISR( xQueue, &ulVarToSend, &xHigherPriorityTaskWoken );
+
+	// Reading from the queue will now return 100.
+
+	// ...
+
+	if( xHigherPrioritytaskWoken == pdTRUE )
+	{
+		// Writing to the queue caused a task to unblock and the unblocked task
+		// has a priority higher than or equal to the priority of the currently
+		// executing task (the task this interrupt interrupted).  Perform a context
+		// switch so this interrupt returns directly to the unblocked task.
+		portYIELD_FROM_ISR(); // or portEND_SWITCHING_ISR() depending on the port.
+	}
+}
+ 
+ * \defgroup xQueueOverwriteFromISR xQueueOverwriteFromISR + * \ingroup QueueManagement + */ +#define xQueueOverwriteFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueOVERWRITE ) + +/** + * queue. h + *
+ BaseType_t xQueueSendFromISR(
+									 QueueHandle_t xQueue,
+									 const void *pvItemToQueue,
+									 BaseType_t *pxHigherPriorityTaskWoken
+								);
+ 
+ * + * This is a macro that calls xQueueGenericSendFromISR(). It is included + * for backward compatibility with versions of FreeRTOS.org that did not + * include the xQueueSendToBackFromISR() and xQueueSendToFrontFromISR() + * macros. + * + * Post an item to the back of a queue. It is safe to use this function from + * within an interrupt service routine. + * + * Items are queued by copy not reference so it is preferable to only + * queue small items, especially when called from an ISR. In most cases + * it would be preferable to store a pointer to the item being queued. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param pxHigherPriorityTaskWoken xQueueSendFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xQueueSendFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @return pdTRUE if the data was successfully sent to the queue, otherwise + * errQUEUE_FULL. + * + * Example usage for buffered IO (where the ISR can obtain more than one value + * per call): +
+ void vBufferISR( void )
+ {
+ char cIn;
+ BaseType_t xHigherPriorityTaskWoken;
+
+	// We have not woken a task at the start of the ISR.
+	xHigherPriorityTaskWoken = pdFALSE;
+
+	// Loop until the buffer is empty.
+	do
+	{
+		// Obtain a byte from the buffer.
+		cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
+
+		// Post the byte.
+		xQueueSendFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );
+
+	} while( portINPUT_BYTE( BUFFER_COUNT ) );
+
+	// Now the buffer is empty we can switch context if necessary.
+	if( xHigherPriorityTaskWoken )
+	{
+		// Actual macro used here is port specific.
+		portYIELD_FROM_ISR ();
+	}
+ }
+ 
+ * + * \defgroup xQueueSendFromISR xQueueSendFromISR + * \ingroup QueueManagement + */ +#define xQueueSendFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK ) + +/** + * queue. h + *
+ BaseType_t xQueueGenericSendFromISR(
+										   QueueHandle_t		xQueue,
+										   const	void	*pvItemToQueue,
+										   BaseType_t	*pxHigherPriorityTaskWoken,
+										   BaseType_t	xCopyPosition
+									   );
+ 
+ * + * It is preferred that the macros xQueueSendFromISR(), + * xQueueSendToFrontFromISR() and xQueueSendToBackFromISR() be used in place + * of calling this function directly. + * + * Post an item on a queue. It is safe to use this function from within an + * interrupt service routine. + * + * Items are queued by copy not reference so it is preferable to only + * queue small items, especially when called from an ISR. In most cases + * it would be preferable to store a pointer to the item being queued. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param pxHigherPriorityTaskWoken xQueueGenericSendFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xQueueGenericSendFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @param xCopyPosition Can take the value queueSEND_TO_BACK to place the + * item at the back of the queue, or queueSEND_TO_FRONT to place the item + * at the front of the queue (for high priority messages). + * + * @return pdTRUE if the data was successfully sent to the queue, otherwise + * errQUEUE_FULL. + * + * Example usage for buffered IO (where the ISR can obtain more than one value + * per call): +
+ void vBufferISR( void )
+ {
+ char cIn;
+ BaseType_t xHigherPriorityTaskWokenByPost;
+
+	// We have not woken a task at the start of the ISR.
+	xHigherPriorityTaskWokenByPost = pdFALSE;
+
+	// Loop until the buffer is empty.
+	do
+	{
+		// Obtain a byte from the buffer.
+		cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
+
+		// Post each byte.
+		xQueueGenericSendFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWokenByPost, queueSEND_TO_BACK );
+
+	} while( portINPUT_BYTE( BUFFER_COUNT ) );
+
+	// Now the buffer is empty we can switch context if necessary.  Note that the
+	// name of the yield function required is port specific.
+	if( xHigherPriorityTaskWokenByPost )
+	{
+		taskYIELD_YIELD_FROM_ISR();
+	}
+ }
+ 
+ * + * \defgroup xQueueSendFromISR xQueueSendFromISR + * \ingroup QueueManagement + */ +BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, const void * const pvItemToQueue, BaseType_t * const pxHigherPriorityTaskWoken, const BaseType_t xCopyPosition ) PRIVILEGED_FUNCTION; + +/** + * queue. h + *
+ BaseType_t xQueueReceiveFromISR(
+									   QueueHandle_t	xQueue,
+									   void	*pvBuffer,
+									   BaseType_t *pxTaskWoken
+								   );
+ * 
+ * + * Receive an item from a queue. It is safe to use this function from within an + * interrupt service routine. + * + * @param xQueue The handle to the queue from which the item is to be + * received. + * + * @param pvBuffer Pointer to the buffer into which the received item will + * be copied. + * + * @param pxTaskWoken A task may be blocked waiting for space to become + * available on the queue. If xQueueReceiveFromISR causes such a task to + * unblock *pxTaskWoken will get set to pdTRUE, otherwise *pxTaskWoken will + * remain unchanged. + * + * @return pdTRUE if an item was successfully received from the queue, + * otherwise pdFALSE. + * + * Example usage: +
+
+ QueueHandle_t xQueue;
+
+ // Function to create a queue and post some values.
+ void vAFunction( void *pvParameters )
+ {
+ char cValueToPost;
+ const TickType_t xTicksToWait = ( TickType_t )0xff;
+
+	// Create a queue capable of containing 10 characters.
+	xQueue = xQueueCreate( 10, sizeof( char ) );
+	if( xQueue == 0 )
+	{
+		// Failed to create the queue.
+	}
+
+	// ...
+
+	// Post some characters that will be used within an ISR.  If the queue
+	// is full then this task will block for xTicksToWait ticks.
+	cValueToPost = 'a';
+	xQueueSend( xQueue, ( void * ) &cValueToPost, xTicksToWait );
+	cValueToPost = 'b';
+	xQueueSend( xQueue, ( void * ) &cValueToPost, xTicksToWait );
+
+	// ... keep posting characters ... this task may block when the queue
+	// becomes full.
+
+	cValueToPost = 'c';
+	xQueueSend( xQueue, ( void * ) &cValueToPost, xTicksToWait );
+ }
+
+ // ISR that outputs all the characters received on the queue.
+ void vISR_Routine( void )
+ {
+ BaseType_t xTaskWokenByReceive = pdFALSE;
+ char cRxedChar;
+
+	while( xQueueReceiveFromISR( xQueue, ( void * ) &cRxedChar, &xTaskWokenByReceive) )
+	{
+		// A character was received.  Output the character now.
+		vOutputCharacter( cRxedChar );
+
+		// If removing the character from the queue woke the task that was
+		// posting onto the queue cTaskWokenByReceive will have been set to
+		// pdTRUE.  No matter how many times this loop iterates only one
+		// task will be woken.
+	}
+
+	if( cTaskWokenByPost != ( char ) pdFALSE;
+	{
+		taskYIELD ();
+	}
+ }
+ 
+ * \defgroup xQueueReceiveFromISR xQueueReceiveFromISR + * \ingroup QueueManagement + */ +BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, void * const pvBuffer, BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; + +/* + * Utilities to query queues that are safe to use from an ISR. These utilities + * should be used only from witin an ISR, or within a critical section. + */ +BaseType_t xQueueIsQueueEmptyFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; +BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; +UBaseType_t uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; + + +/* + * xQueueAltGenericSend() is an alternative version of xQueueGenericSend(). + * Likewise xQueueAltGenericReceive() is an alternative version of + * xQueueGenericReceive(). + * + * The source code that implements the alternative (Alt) API is much + * simpler because it executes everything from within a critical section. + * This is the approach taken by many other RTOSes, but FreeRTOS.org has the + * preferred fully featured API too. The fully featured API has more + * complex code that takes longer to execute, but makes much less use of + * critical sections. Therefore the alternative API sacrifices interrupt + * responsiveness to gain execution speed, whereas the fully featured API + * sacrifices execution speed to ensure better interrupt responsiveness. + */ +BaseType_t xQueueAltGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, BaseType_t xCopyPosition ); +BaseType_t xQueueAltGenericReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait, BaseType_t xJustPeeking ); +#define xQueueAltSendToFront( xQueue, pvItemToQueue, xTicksToWait ) xQueueAltGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_FRONT ) +#define xQueueAltSendToBack( xQueue, pvItemToQueue, xTicksToWait ) xQueueAltGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK ) +#define xQueueAltReceive( xQueue, pvBuffer, xTicksToWait ) xQueueAltGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), pdFALSE ) +#define xQueueAltPeek( xQueue, pvBuffer, xTicksToWait ) xQueueAltGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), pdTRUE ) + +/* + * The functions defined above are for passing data to and from tasks. The + * functions below are the equivalents for passing data to and from + * co-routines. + * + * These functions are called from the co-routine macro implementation and + * should not be called directly from application code. Instead use the macro + * wrappers defined within croutine.h. + */ +BaseType_t xQueueCRSendFromISR( QueueHandle_t xQueue, const void *pvItemToQueue, BaseType_t xCoRoutinePreviouslyWoken ); +BaseType_t xQueueCRReceiveFromISR( QueueHandle_t xQueue, void *pvBuffer, BaseType_t *pxTaskWoken ); +BaseType_t xQueueCRSend( QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait ); +BaseType_t xQueueCRReceive( QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait ); + +/* + * For internal use only. Use xSemaphoreCreateMutex(), + * xSemaphoreCreateCounting() or xSemaphoreGetMutexHolder() instead of calling + * these functions directly. + */ +QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType ) PRIVILEGED_FUNCTION; +QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount ) PRIVILEGED_FUNCTION; +void* xQueueGetMutexHolder( QueueHandle_t xSemaphore ) PRIVILEGED_FUNCTION; + +/* + * For internal use only. Use xSemaphoreTakeMutexRecursive() or + * xSemaphoreGiveMutexRecursive() instead of calling these functions directly. + */ +BaseType_t xQueueTakeMutexRecursive( QueueHandle_t xMutex, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; +BaseType_t xQueueGiveMutexRecursive( QueueHandle_t pxMutex ) PRIVILEGED_FUNCTION; + +/* + * Reset a queue back to its original empty state. pdPASS is returned if the + * queue is successfully reset. pdFAIL is returned if the queue could not be + * reset because there are tasks blocked on the queue waiting to either + * receive from the queue or send to the queue. + */ +#define xQueueReset( xQueue ) xQueueGenericReset( xQueue, pdFALSE ) + +/* + * The registry is provided as a means for kernel aware debuggers to + * locate queues, semaphores and mutexes. Call vQueueAddToRegistry() add + * a queue, semaphore or mutex handle to the registry if you want the handle + * to be available to a kernel aware debugger. If you are not using a kernel + * aware debugger then this function can be ignored. + * + * configQUEUE_REGISTRY_SIZE defines the maximum number of handles the + * registry can hold. configQUEUE_REGISTRY_SIZE must be greater than 0 + * within FreeRTOSConfig.h for the registry to be available. Its value + * does not effect the number of queues, semaphores and mutexes that can be + * created - just the number that the registry can hold. + * + * @param xQueue The handle of the queue being added to the registry. This + * is the handle returned by a call to xQueueCreate(). Semaphore and mutex + * handles can also be passed in here. + * + * @param pcName The name to be associated with the handle. This is the + * name that the kernel aware debugger will display. The queue registry only + * stores a pointer to the string - so the string must be persistent (global or + * preferably in ROM/Flash), not on the stack. + */ +#if configQUEUE_REGISTRY_SIZE > 0 + void vQueueAddToRegistry( QueueHandle_t xQueue, const char *pcName ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ +#endif + +/* + * The registry is provided as a means for kernel aware debuggers to + * locate queues, semaphores and mutexes. Call vQueueAddToRegistry() add + * a queue, semaphore or mutex handle to the registry if you want the handle + * to be available to a kernel aware debugger, and vQueueUnregisterQueue() to + * remove the queue, semaphore or mutex from the register. If you are not using + * a kernel aware debugger then this function can be ignored. + * + * @param xQueue The handle of the queue being removed from the registry. + */ +#if configQUEUE_REGISTRY_SIZE > 0 + void vQueueUnregisterQueue( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; +#endif + +/* + * Generic version of the queue creation function, which is in turn called by + * any queue, semaphore or mutex creation function or macro. + */ +QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType ) PRIVILEGED_FUNCTION; + +/* + * Queue sets provide a mechanism to allow a task to block (pend) on a read + * operation from multiple queues or semaphores simultaneously. + * + * See FreeRTOS/Source/Demo/Common/Minimal/QueueSet.c for an example using this + * function. + * + * A queue set must be explicitly created using a call to xQueueCreateSet() + * before it can be used. Once created, standard FreeRTOS queues and semaphores + * can be added to the set using calls to xQueueAddToSet(). + * xQueueSelectFromSet() is then used to determine which, if any, of the queues + * or semaphores contained in the set is in a state where a queue read or + * semaphore take operation would be successful. + * + * Note 1: See the documentation on http://wwwFreeRTOS.org/RTOS-queue-sets.html + * for reasons why queue sets are very rarely needed in practice as there are + * simpler methods of blocking on multiple objects. + * + * Note 2: Blocking on a queue set that contains a mutex will not cause the + * mutex holder to inherit the priority of the blocked task. + * + * Note 3: An additional 4 bytes of RAM is required for each space in a every + * queue added to a queue set. Therefore counting semaphores that have a high + * maximum count value should not be added to a queue set. + * + * Note 4: A receive (in the case of a queue) or take (in the case of a + * semaphore) operation must not be performed on a member of a queue set unless + * a call to xQueueSelectFromSet() has first returned a handle to that set member. + * + * @param uxEventQueueLength Queue sets store events that occur on + * the queues and semaphores contained in the set. uxEventQueueLength specifies + * the maximum number of events that can be queued at once. To be absolutely + * certain that events are not lost uxEventQueueLength should be set to the + * total sum of the length of the queues added to the set, where binary + * semaphores and mutexes have a length of 1, and counting semaphores have a + * length set by their maximum count value. Examples: + * + If a queue set is to hold a queue of length 5, another queue of length 12, + * and a binary semaphore, then uxEventQueueLength should be set to + * (5 + 12 + 1), or 18. + * + If a queue set is to hold three binary semaphores then uxEventQueueLength + * should be set to (1 + 1 + 1 ), or 3. + * + If a queue set is to hold a counting semaphore that has a maximum count of + * 5, and a counting semaphore that has a maximum count of 3, then + * uxEventQueueLength should be set to (5 + 3), or 8. + * + * @return If the queue set is created successfully then a handle to the created + * queue set is returned. Otherwise NULL is returned. + */ +QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength ) PRIVILEGED_FUNCTION; + +/* + * Adds a queue or semaphore to a queue set that was previously created by a + * call to xQueueCreateSet(). + * + * See FreeRTOS/Source/Demo/Common/Minimal/QueueSet.c for an example using this + * function. + * + * Note 1: A receive (in the case of a queue) or take (in the case of a + * semaphore) operation must not be performed on a member of a queue set unless + * a call to xQueueSelectFromSet() has first returned a handle to that set member. + * + * @param xQueueOrSemaphore The handle of the queue or semaphore being added to + * the queue set (cast to an QueueSetMemberHandle_t type). + * + * @param xQueueSet The handle of the queue set to which the queue or semaphore + * is being added. + * + * @return If the queue or semaphore was successfully added to the queue set + * then pdPASS is returned. If the queue could not be successfully added to the + * queue set because it is already a member of a different queue set then pdFAIL + * is returned. + */ +BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION; + +/* + * Removes a queue or semaphore from a queue set. A queue or semaphore can only + * be removed from a set if the queue or semaphore is empty. + * + * See FreeRTOS/Source/Demo/Common/Minimal/QueueSet.c for an example using this + * function. + * + * @param xQueueOrSemaphore The handle of the queue or semaphore being removed + * from the queue set (cast to an QueueSetMemberHandle_t type). + * + * @param xQueueSet The handle of the queue set in which the queue or semaphore + * is included. + * + * @return If the queue or semaphore was successfully removed from the queue set + * then pdPASS is returned. If the queue was not in the queue set, or the + * queue (or semaphore) was not empty, then pdFAIL is returned. + */ +BaseType_t xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION; + +/* + * xQueueSelectFromSet() selects from the members of a queue set a queue or + * semaphore that either contains data (in the case of a queue) or is available + * to take (in the case of a semaphore). xQueueSelectFromSet() effectively + * allows a task to block (pend) on a read operation on all the queues and + * semaphores in a queue set simultaneously. + * + * See FreeRTOS/Source/Demo/Common/Minimal/QueueSet.c for an example using this + * function. + * + * Note 1: See the documentation on http://wwwFreeRTOS.org/RTOS-queue-sets.html + * for reasons why queue sets are very rarely needed in practice as there are + * simpler methods of blocking on multiple objects. + * + * Note 2: Blocking on a queue set that contains a mutex will not cause the + * mutex holder to inherit the priority of the blocked task. + * + * Note 3: A receive (in the case of a queue) or take (in the case of a + * semaphore) operation must not be performed on a member of a queue set unless + * a call to xQueueSelectFromSet() has first returned a handle to that set member. + * + * @param xQueueSet The queue set on which the task will (potentially) block. + * + * @param xTicksToWait The maximum time, in ticks, that the calling task will + * remain in the Blocked state (with other tasks executing) to wait for a member + * of the queue set to be ready for a successful queue read or semaphore take + * operation. + * + * @return xQueueSelectFromSet() will return the handle of a queue (cast to + * a QueueSetMemberHandle_t type) contained in the queue set that contains data, + * or the handle of a semaphore (cast to a QueueSetMemberHandle_t type) contained + * in the queue set that is available, or NULL if no such queue or semaphore + * exists before before the specified block time expires. + */ +QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet, const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; + +/* + * A version of xQueueSelectFromSet() that can be used from an ISR. + */ +QueueSetMemberHandle_t xQueueSelectFromSetFromISR( QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION; + +/* Not public API functions. */ +void vQueueWaitForMessageRestricted( QueueHandle_t xQueue, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; +BaseType_t xQueueGenericReset( QueueHandle_t xQueue, BaseType_t xNewQueue ) PRIVILEGED_FUNCTION; +void vQueueSetQueueNumber( QueueHandle_t xQueue, UBaseType_t uxQueueNumber ) PRIVILEGED_FUNCTION; +UBaseType_t uxQueueGetQueueNumber( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; +uint8_t ucQueueGetQueueType( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; + + +#ifdef __cplusplus +} +#endif + +#endif /* QUEUE_H */ + diff --git a/component/os/freertos/freertos_v8.1.2/Source/include/semphr.h b/component/os/freertos/freertos_v8.1.2/Source/include/semphr.h new file mode 100644 index 0000000..5275895 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/include/semphr.h @@ -0,0 +1,840 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef SEMAPHORE_H +#define SEMAPHORE_H + +#ifndef INC_FREERTOS_H + #error "include FreeRTOS.h" must appear in source files before "include semphr.h" +#endif + +#include "queue.h" + +typedef QueueHandle_t SemaphoreHandle_t; + +#define semBINARY_SEMAPHORE_QUEUE_LENGTH ( ( uint8_t ) 1U ) +#define semSEMAPHORE_QUEUE_ITEM_LENGTH ( ( uint8_t ) 0U ) +#define semGIVE_BLOCK_TIME ( ( TickType_t ) 0U ) + + +/** + * semphr. h + *
vSemaphoreCreateBinary( SemaphoreHandle_t xSemaphore )
+ * + * This old vSemaphoreCreateBinary() macro is now deprecated in favour of the + * xSemaphoreCreateBinary() function. Note that binary semaphores created using + * the vSemaphoreCreateBinary() macro are created in a state such that the + * first call to 'take' the semaphore would pass, whereas binary semaphores + * created using xSemaphoreCreateBinary() are created in a state such that the + * the semaphore must first be 'given' before it can be 'taken'. + * + * Macro that implements a semaphore by using the existing queue mechanism. + * The queue length is 1 as this is a binary semaphore. The data size is 0 + * as we don't want to actually store any data - we just want to know if the + * queue is empty or full. + * + * This type of semaphore can be used for pure synchronisation between tasks or + * between an interrupt and a task. The semaphore need not be given back once + * obtained, so one task/interrupt can continuously 'give' the semaphore while + * another continuously 'takes' the semaphore. For this reason this type of + * semaphore does not use a priority inheritance mechanism. For an alternative + * that does use priority inheritance see xSemaphoreCreateMutex(). + * + * @param xSemaphore Handle to the created semaphore. Should be of type SemaphoreHandle_t. + * + * Example usage: +
+ SemaphoreHandle_t xSemaphore = NULL;
+
+ void vATask( void * pvParameters )
+ {
+    // Semaphore cannot be used before a call to vSemaphoreCreateBinary ().
+    // This is a macro so pass the variable in directly.
+    vSemaphoreCreateBinary( xSemaphore );
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.
+    }
+ }
+ 
+ * \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary + * \ingroup Semaphores + */ +#define vSemaphoreCreateBinary( xSemaphore ) \ + { \ + ( xSemaphore ) = xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ); \ + if( ( xSemaphore ) != NULL ) \ + { \ + ( void ) xSemaphoreGive( ( xSemaphore ) ); \ + } \ + } + +/** + * semphr. h + *
SemaphoreHandle_t xSemaphoreCreateBinary( void )
+ * + * The old vSemaphoreCreateBinary() macro is now deprecated in favour of this + * xSemaphoreCreateBinary() function. Note that binary semaphores created using + * the vSemaphoreCreateBinary() macro are created in a state such that the + * first call to 'take' the semaphore would pass, whereas binary semaphores + * created using xSemaphoreCreateBinary() are created in a state such that the + * the semaphore must first be 'given' before it can be 'taken'. + * + * Function that creates a semaphore by using the existing queue mechanism. + * The queue length is 1 as this is a binary semaphore. The data size is 0 + * as nothing is actually stored - all that is important is whether the queue is + * empty or full (the binary semaphore is available or not). + * + * This type of semaphore can be used for pure synchronisation between tasks or + * between an interrupt and a task. The semaphore need not be given back once + * obtained, so one task/interrupt can continuously 'give' the semaphore while + * another continuously 'takes' the semaphore. For this reason this type of + * semaphore does not use a priority inheritance mechanism. For an alternative + * that does use priority inheritance see xSemaphoreCreateMutex(). + * + * @return Handle to the created semaphore. + * + * Example usage: +
+ SemaphoreHandle_t xSemaphore = NULL;
+
+ void vATask( void * pvParameters )
+ {
+    // Semaphore cannot be used before a call to vSemaphoreCreateBinary ().
+    // This is a macro so pass the variable in directly.
+    xSemaphore = xSemaphoreCreateBinary();
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.
+    }
+ }
+ 
+ * \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary + * \ingroup Semaphores + */ +#define xSemaphoreCreateBinary() xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ) + +/** + * semphr. h + *
xSemaphoreTake(
+ *                   SemaphoreHandle_t xSemaphore,
+ *                   TickType_t xBlockTime
+ *               )
+ * + * Macro to obtain a semaphore. The semaphore must have previously been + * created with a call to vSemaphoreCreateBinary(), xSemaphoreCreateMutex() or + * xSemaphoreCreateCounting(). + * + * @param xSemaphore A handle to the semaphore being taken - obtained when + * the semaphore was created. + * + * @param xBlockTime The time in ticks to wait for the semaphore to become + * available. The macro portTICK_PERIOD_MS can be used to convert this to a + * real time. A block time of zero can be used to poll the semaphore. A block + * time of portMAX_DELAY can be used to block indefinitely (provided + * INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h). + * + * @return pdTRUE if the semaphore was obtained. pdFALSE + * if xBlockTime expired without the semaphore becoming available. + * + * Example usage: +
+ SemaphoreHandle_t xSemaphore = NULL;
+
+ // A task that creates a semaphore.
+ void vATask( void * pvParameters )
+ {
+    // Create the semaphore to guard a shared resource.
+    vSemaphoreCreateBinary( xSemaphore );
+ }
+
+ // A task that uses the semaphore.
+ void vAnotherTask( void * pvParameters )
+ {
+    // ... Do other things.
+
+    if( xSemaphore != NULL )
+    {
+        // See if we can obtain the semaphore.  If the semaphore is not available
+        // wait 10 ticks to see if it becomes free.
+        if( xSemaphoreTake( xSemaphore, ( TickType_t ) 10 ) == pdTRUE )
+        {
+            // We were able to obtain the semaphore and can now access the
+            // shared resource.
+
+            // ...
+
+            // We have finished accessing the shared resource.  Release the
+            // semaphore.
+            xSemaphoreGive( xSemaphore );
+        }
+        else
+        {
+            // We could not obtain the semaphore and can therefore not access
+            // the shared resource safely.
+        }
+    }
+ }
+ 
+ * \defgroup xSemaphoreTake xSemaphoreTake + * \ingroup Semaphores + */ +#define xSemaphoreTake( xSemaphore, xBlockTime ) xQueueGenericReceive( ( QueueHandle_t ) ( xSemaphore ), NULL, ( xBlockTime ), pdFALSE ) + +/** + * semphr. h + * xSemaphoreTakeRecursive( + * SemaphoreHandle_t xMutex, + * TickType_t xBlockTime + * ) + * + * Macro to recursively obtain, or 'take', a mutex type semaphore. + * The mutex must have previously been created using a call to + * xSemaphoreCreateRecursiveMutex(); + * + * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this + * macro to be available. + * + * This macro must not be used on mutexes created using xSemaphoreCreateMutex(). + * + * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex + * doesn't become available again until the owner has called + * xSemaphoreGiveRecursive() for each successful 'take' request. For example, + * if a task successfully 'takes' the same mutex 5 times then the mutex will + * not be available to any other task until it has also 'given' the mutex back + * exactly five times. + * + * @param xMutex A handle to the mutex being obtained. This is the + * handle returned by xSemaphoreCreateRecursiveMutex(); + * + * @param xBlockTime The time in ticks to wait for the semaphore to become + * available. The macro portTICK_PERIOD_MS can be used to convert this to a + * real time. A block time of zero can be used to poll the semaphore. If + * the task already owns the semaphore then xSemaphoreTakeRecursive() will + * return immediately no matter what the value of xBlockTime. + * + * @return pdTRUE if the semaphore was obtained. pdFALSE if xBlockTime + * expired without the semaphore becoming available. + * + * Example usage: +
+ SemaphoreHandle_t xMutex = NULL;
+
+ // A task that creates a mutex.
+ void vATask( void * pvParameters )
+ {
+    // Create the mutex to guard a shared resource.
+    xMutex = xSemaphoreCreateRecursiveMutex();
+ }
+
+ // A task that uses the mutex.
+ void vAnotherTask( void * pvParameters )
+ {
+    // ... Do other things.
+
+    if( xMutex != NULL )
+    {
+        // See if we can obtain the mutex.  If the mutex is not available
+        // wait 10 ticks to see if it becomes free.
+        if( xSemaphoreTakeRecursive( xSemaphore, ( TickType_t ) 10 ) == pdTRUE )
+        {
+            // We were able to obtain the mutex and can now access the
+            // shared resource.
+
+            // ...
+            // For some reason due to the nature of the code further calls to
+			// xSemaphoreTakeRecursive() are made on the same mutex.  In real
+			// code these would not be just sequential calls as this would make
+			// no sense.  Instead the calls are likely to be buried inside
+			// a more complex call structure.
+            xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
+            xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
+
+            // The mutex has now been 'taken' three times, so will not be
+			// available to another task until it has also been given back
+			// three times.  Again it is unlikely that real code would have
+			// these calls sequentially, but instead buried in a more complex
+			// call structure.  This is just for illustrative purposes.
+            xSemaphoreGiveRecursive( xMutex );
+			xSemaphoreGiveRecursive( xMutex );
+			xSemaphoreGiveRecursive( xMutex );
+
+			// Now the mutex can be taken by other tasks.
+        }
+        else
+        {
+            // We could not obtain the mutex and can therefore not access
+            // the shared resource safely.
+        }
+    }
+ }
+ 
+ * \defgroup xSemaphoreTakeRecursive xSemaphoreTakeRecursive + * \ingroup Semaphores + */ +#define xSemaphoreTakeRecursive( xMutex, xBlockTime ) xQueueTakeMutexRecursive( ( xMutex ), ( xBlockTime ) ) + + +/* + * xSemaphoreAltTake() is an alternative version of xSemaphoreTake(). + * + * The source code that implements the alternative (Alt) API is much + * simpler because it executes everything from within a critical section. + * This is the approach taken by many other RTOSes, but FreeRTOS.org has the + * preferred fully featured API too. The fully featured API has more + * complex code that takes longer to execute, but makes much less use of + * critical sections. Therefore the alternative API sacrifices interrupt + * responsiveness to gain execution speed, whereas the fully featured API + * sacrifices execution speed to ensure better interrupt responsiveness. + */ +#define xSemaphoreAltTake( xSemaphore, xBlockTime ) xQueueAltGenericReceive( ( QueueHandle_t ) ( xSemaphore ), NULL, ( xBlockTime ), pdFALSE ) + +/** + * semphr. h + *
xSemaphoreGive( SemaphoreHandle_t xSemaphore )
+ * + * Macro to release a semaphore. The semaphore must have previously been + * created with a call to vSemaphoreCreateBinary(), xSemaphoreCreateMutex() or + * xSemaphoreCreateCounting(). and obtained using sSemaphoreTake(). + * + * This macro must not be used from an ISR. See xSemaphoreGiveFromISR () for + * an alternative which can be used from an ISR. + * + * This macro must also not be used on semaphores created using + * xSemaphoreCreateRecursiveMutex(). + * + * @param xSemaphore A handle to the semaphore being released. This is the + * handle returned when the semaphore was created. + * + * @return pdTRUE if the semaphore was released. pdFALSE if an error occurred. + * Semaphores are implemented using queues. An error can occur if there is + * no space on the queue to post a message - indicating that the + * semaphore was not first obtained correctly. + * + * Example usage: +
+ SemaphoreHandle_t xSemaphore = NULL;
+
+ void vATask( void * pvParameters )
+ {
+    // Create the semaphore to guard a shared resource.
+    vSemaphoreCreateBinary( xSemaphore );
+
+    if( xSemaphore != NULL )
+    {
+        if( xSemaphoreGive( xSemaphore ) != pdTRUE )
+        {
+            // We would expect this call to fail because we cannot give
+            // a semaphore without first "taking" it!
+        }
+
+        // Obtain the semaphore - don't block if the semaphore is not
+        // immediately available.
+        if( xSemaphoreTake( xSemaphore, ( TickType_t ) 0 ) )
+        {
+            // We now have the semaphore and can access the shared resource.
+
+            // ...
+
+            // We have finished accessing the shared resource so can free the
+            // semaphore.
+            if( xSemaphoreGive( xSemaphore ) != pdTRUE )
+            {
+                // We would not expect this call to fail because we must have
+                // obtained the semaphore to get here.
+            }
+        }
+    }
+ }
+ 
+ * \defgroup xSemaphoreGive xSemaphoreGive + * \ingroup Semaphores + */ +#define xSemaphoreGive( xSemaphore ) xQueueGenericSend( ( QueueHandle_t ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK ) + +/** + * semphr. h + *
xSemaphoreGiveRecursive( SemaphoreHandle_t xMutex )
+ * + * Macro to recursively release, or 'give', a mutex type semaphore. + * The mutex must have previously been created using a call to + * xSemaphoreCreateRecursiveMutex(); + * + * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this + * macro to be available. + * + * This macro must not be used on mutexes created using xSemaphoreCreateMutex(). + * + * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex + * doesn't become available again until the owner has called + * xSemaphoreGiveRecursive() for each successful 'take' request. For example, + * if a task successfully 'takes' the same mutex 5 times then the mutex will + * not be available to any other task until it has also 'given' the mutex back + * exactly five times. + * + * @param xMutex A handle to the mutex being released, or 'given'. This is the + * handle returned by xSemaphoreCreateMutex(); + * + * @return pdTRUE if the semaphore was given. + * + * Example usage: +
+ SemaphoreHandle_t xMutex = NULL;
+
+ // A task that creates a mutex.
+ void vATask( void * pvParameters )
+ {
+    // Create the mutex to guard a shared resource.
+    xMutex = xSemaphoreCreateRecursiveMutex();
+ }
+
+ // A task that uses the mutex.
+ void vAnotherTask( void * pvParameters )
+ {
+    // ... Do other things.
+
+    if( xMutex != NULL )
+    {
+        // See if we can obtain the mutex.  If the mutex is not available
+        // wait 10 ticks to see if it becomes free.
+        if( xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ) == pdTRUE )
+        {
+            // We were able to obtain the mutex and can now access the
+            // shared resource.
+
+            // ...
+            // For some reason due to the nature of the code further calls to
+			// xSemaphoreTakeRecursive() are made on the same mutex.  In real
+			// code these would not be just sequential calls as this would make
+			// no sense.  Instead the calls are likely to be buried inside
+			// a more complex call structure.
+            xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
+            xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
+
+            // The mutex has now been 'taken' three times, so will not be
+			// available to another task until it has also been given back
+			// three times.  Again it is unlikely that real code would have
+			// these calls sequentially, it would be more likely that the calls
+			// to xSemaphoreGiveRecursive() would be called as a call stack
+			// unwound.  This is just for demonstrative purposes.
+            xSemaphoreGiveRecursive( xMutex );
+			xSemaphoreGiveRecursive( xMutex );
+			xSemaphoreGiveRecursive( xMutex );
+
+			// Now the mutex can be taken by other tasks.
+        }
+        else
+        {
+            // We could not obtain the mutex and can therefore not access
+            // the shared resource safely.
+        }
+    }
+ }
+ 
+ * \defgroup xSemaphoreGiveRecursive xSemaphoreGiveRecursive + * \ingroup Semaphores + */ +#define xSemaphoreGiveRecursive( xMutex ) xQueueGiveMutexRecursive( ( xMutex ) ) + +/* + * xSemaphoreAltGive() is an alternative version of xSemaphoreGive(). + * + * The source code that implements the alternative (Alt) API is much + * simpler because it executes everything from within a critical section. + * This is the approach taken by many other RTOSes, but FreeRTOS.org has the + * preferred fully featured API too. The fully featured API has more + * complex code that takes longer to execute, but makes much less use of + * critical sections. Therefore the alternative API sacrifices interrupt + * responsiveness to gain execution speed, whereas the fully featured API + * sacrifices execution speed to ensure better interrupt responsiveness. + */ +#define xSemaphoreAltGive( xSemaphore ) xQueueAltGenericSend( ( QueueHandle_t ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK ) + +/** + * semphr. h + *
+ xSemaphoreGiveFromISR(
+                          SemaphoreHandle_t xSemaphore,
+                          BaseType_t *pxHigherPriorityTaskWoken
+                      )
+ * + * Macro to release a semaphore. The semaphore must have previously been + * created with a call to vSemaphoreCreateBinary() or xSemaphoreCreateCounting(). + * + * Mutex type semaphores (those created using a call to xSemaphoreCreateMutex()) + * must not be used with this macro. + * + * This macro can be used from an ISR. + * + * @param xSemaphore A handle to the semaphore being released. This is the + * handle returned when the semaphore was created. + * + * @param pxHigherPriorityTaskWoken xSemaphoreGiveFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if giving the semaphore caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xSemaphoreGiveFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @return pdTRUE if the semaphore was successfully given, otherwise errQUEUE_FULL. + * + * Example usage: +
+ \#define LONG_TIME 0xffff
+ \#define TICKS_TO_WAIT	10
+ SemaphoreHandle_t xSemaphore = NULL;
+
+ // Repetitive task.
+ void vATask( void * pvParameters )
+ {
+    for( ;; )
+    {
+        // We want this task to run every 10 ticks of a timer.  The semaphore
+        // was created before this task was started.
+
+        // Block waiting for the semaphore to become available.
+        if( xSemaphoreTake( xSemaphore, LONG_TIME ) == pdTRUE )
+        {
+            // It is time to execute.
+
+            // ...
+
+            // We have finished our task.  Return to the top of the loop where
+            // we will block on the semaphore until it is time to execute
+            // again.  Note when using the semaphore for synchronisation with an
+			// ISR in this manner there is no need to 'give' the semaphore back.
+        }
+    }
+ }
+
+ // Timer ISR
+ void vTimerISR( void * pvParameters )
+ {
+ static uint8_t ucLocalTickCount = 0;
+ static BaseType_t xHigherPriorityTaskWoken;
+
+    // A timer tick has occurred.
+
+    // ... Do other time functions.
+
+    // Is it time for vATask () to run?
+	xHigherPriorityTaskWoken = pdFALSE;
+    ucLocalTickCount++;
+    if( ucLocalTickCount >= TICKS_TO_WAIT )
+    {
+        // Unblock the task by releasing the semaphore.
+        xSemaphoreGiveFromISR( xSemaphore, &xHigherPriorityTaskWoken );
+
+        // Reset the count so we release the semaphore again in 10 ticks time.
+        ucLocalTickCount = 0;
+    }
+
+    if( xHigherPriorityTaskWoken != pdFALSE )
+    {
+        // We can force a context switch here.  Context switching from an
+        // ISR uses port specific syntax.  Check the demo task for your port
+        // to find the syntax required.
+    }
+ }
+ 
+ * \defgroup xSemaphoreGiveFromISR xSemaphoreGiveFromISR + * \ingroup Semaphores + */ +#define xSemaphoreGiveFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( QueueHandle_t ) ( xSemaphore ), NULL, ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK ) + +/** + * semphr. h + *
+ xSemaphoreTakeFromISR(
+                          SemaphoreHandle_t xSemaphore,
+                          BaseType_t *pxHigherPriorityTaskWoken
+                      )
+ * + * Macro to take a semaphore from an ISR. The semaphore must have + * previously been created with a call to vSemaphoreCreateBinary() or + * xSemaphoreCreateCounting(). + * + * Mutex type semaphores (those created using a call to xSemaphoreCreateMutex()) + * must not be used with this macro. + * + * This macro can be used from an ISR, however taking a semaphore from an ISR + * is not a common operation. It is likely to only be useful when taking a + * counting semaphore when an interrupt is obtaining an object from a resource + * pool (when the semaphore count indicates the number of resources available). + * + * @param xSemaphore A handle to the semaphore being taken. This is the + * handle returned when the semaphore was created. + * + * @param pxHigherPriorityTaskWoken xSemaphoreTakeFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if taking the semaphore caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xSemaphoreTakeFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @return pdTRUE if the semaphore was successfully taken, otherwise + * pdFALSE + */ +#define xSemaphoreTakeFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueReceiveFromISR( ( QueueHandle_t ) ( xSemaphore ), NULL, ( pxHigherPriorityTaskWoken ) ) + +/** + * semphr. h + *
SemaphoreHandle_t xSemaphoreCreateMutex( void )
+ * + * Macro that implements a mutex semaphore by using the existing queue + * mechanism. + * + * Mutexes created using this macro can be accessed using the xSemaphoreTake() + * and xSemaphoreGive() macros. The xSemaphoreTakeRecursive() and + * xSemaphoreGiveRecursive() macros should not be used. + * + * This type of semaphore uses a priority inheritance mechanism so a task + * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the + * semaphore it is no longer required. + * + * Mutex type semaphores cannot be used from within interrupt service routines. + * + * See vSemaphoreCreateBinary() for an alternative implementation that can be + * used for pure synchronisation (where one task or interrupt always 'gives' the + * semaphore and another always 'takes' the semaphore) and from within interrupt + * service routines. + * + * @return xSemaphore Handle to the created mutex semaphore. Should be of type + * SemaphoreHandle_t. + * + * Example usage: +
+ SemaphoreHandle_t xSemaphore;
+
+ void vATask( void * pvParameters )
+ {
+    // Semaphore cannot be used before a call to xSemaphoreCreateMutex().
+    // This is a macro so pass the variable in directly.
+    xSemaphore = xSemaphoreCreateMutex();
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.
+    }
+ }
+ 
+ * \defgroup vSemaphoreCreateMutex vSemaphoreCreateMutex + * \ingroup Semaphores + */ +#define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX ) + + +/** + * semphr. h + *
SemaphoreHandle_t xSemaphoreCreateRecursiveMutex( void )
+ * + * Macro that implements a recursive mutex by using the existing queue + * mechanism. + * + * Mutexes created using this macro can be accessed using the + * xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() macros. The + * xSemaphoreTake() and xSemaphoreGive() macros should not be used. + * + * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex + * doesn't become available again until the owner has called + * xSemaphoreGiveRecursive() for each successful 'take' request. For example, + * if a task successfully 'takes' the same mutex 5 times then the mutex will + * not be available to any other task until it has also 'given' the mutex back + * exactly five times. + * + * This type of semaphore uses a priority inheritance mechanism so a task + * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the + * semaphore it is no longer required. + * + * Mutex type semaphores cannot be used from within interrupt service routines. + * + * See vSemaphoreCreateBinary() for an alternative implementation that can be + * used for pure synchronisation (where one task or interrupt always 'gives' the + * semaphore and another always 'takes' the semaphore) and from within interrupt + * service routines. + * + * @return xSemaphore Handle to the created mutex semaphore. Should be of type + * SemaphoreHandle_t. + * + * Example usage: +
+ SemaphoreHandle_t xSemaphore;
+
+ void vATask( void * pvParameters )
+ {
+    // Semaphore cannot be used before a call to xSemaphoreCreateMutex().
+    // This is a macro so pass the variable in directly.
+    xSemaphore = xSemaphoreCreateRecursiveMutex();
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.
+    }
+ }
+ 
+ * \defgroup vSemaphoreCreateMutex vSemaphoreCreateMutex + * \ingroup Semaphores + */ +#define xSemaphoreCreateRecursiveMutex() xQueueCreateMutex( queueQUEUE_TYPE_RECURSIVE_MUTEX ) + +/** + * semphr. h + *
SemaphoreHandle_t xSemaphoreCreateCounting( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount )
+ * + * Macro that creates a counting semaphore by using the existing + * queue mechanism. + * + * Counting semaphores are typically used for two things: + * + * 1) Counting events. + * + * In this usage scenario an event handler will 'give' a semaphore each time + * an event occurs (incrementing the semaphore count value), and a handler + * task will 'take' a semaphore each time it processes an event + * (decrementing the semaphore count value). The count value is therefore + * the difference between the number of events that have occurred and the + * number that have been processed. In this case it is desirable for the + * initial count value to be zero. + * + * 2) Resource management. + * + * In this usage scenario the count value indicates the number of resources + * available. To obtain control of a resource a task must first obtain a + * semaphore - decrementing the semaphore count value. When the count value + * reaches zero there are no free resources. When a task finishes with the + * resource it 'gives' the semaphore back - incrementing the semaphore count + * value. In this case it is desirable for the initial count value to be + * equal to the maximum count value, indicating that all resources are free. + * + * @param uxMaxCount The maximum count value that can be reached. When the + * semaphore reaches this value it can no longer be 'given'. + * + * @param uxInitialCount The count value assigned to the semaphore when it is + * created. + * + * @return Handle to the created semaphore. Null if the semaphore could not be + * created. + * + * Example usage: +
+ SemaphoreHandle_t xSemaphore;
+
+ void vATask( void * pvParameters )
+ {
+ SemaphoreHandle_t xSemaphore = NULL;
+
+    // Semaphore cannot be used before a call to xSemaphoreCreateCounting().
+    // The max value to which the semaphore can count should be 10, and the
+    // initial value assigned to the count should be 0.
+    xSemaphore = xSemaphoreCreateCounting( 10, 0 );
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.
+    }
+ }
+ 
+ * \defgroup xSemaphoreCreateCounting xSemaphoreCreateCounting + * \ingroup Semaphores + */ +#define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) ) + +/** + * semphr. h + *
void vSemaphoreDelete( SemaphoreHandle_t xSemaphore );
+ * + * Delete a semaphore. This function must be used with care. For example, + * do not delete a mutex type semaphore if the mutex is held by a task. + * + * @param xSemaphore A handle to the semaphore to be deleted. + * + * \defgroup vSemaphoreDelete vSemaphoreDelete + * \ingroup Semaphores + */ +#define vSemaphoreDelete( xSemaphore ) vQueueDelete( ( QueueHandle_t ) ( xSemaphore ) ) + +/** + * semphr.h + *
TaskHandle_t xSemaphoreGetMutexHolder( SemaphoreHandle_t xMutex );
+ * + * If xMutex is indeed a mutex type semaphore, return the current mutex holder. + * If xMutex is not a mutex type semaphore, or the mutex is available (not held + * by a task), return NULL. + * + * Note: This is a good way of determining if the calling task is the mutex + * holder, but not a good way of determining the identity of the mutex holder as + * the holder may change between the function exiting and the returned value + * being tested. + */ +#define xSemaphoreGetMutexHolder( xSemaphore ) xQueueGetMutexHolder( ( xSemaphore ) ) + +#endif /* SEMAPHORE_H */ + + diff --git a/component/os/freertos/freertos_v8.1.2/Source/include/stdint.readme b/component/os/freertos/freertos_v8.1.2/Source/include/stdint.readme new file mode 100644 index 0000000..4414c29 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/include/stdint.readme @@ -0,0 +1,27 @@ + +#ifndef FREERTOS_STDINT +#define FREERTOS_STDINT + +/******************************************************************************* + * THIS IS NOT A FULL stdint.h IMPLEMENTATION - It only contains the definitions + * necessary to build the FreeRTOS code. It is provided to allow FreeRTOS to be + * built using compilers that do not provide their own stdint.h definition. + * + * To use this file: + * + * 1) Copy this file into the directory that contains your FreeRTOSConfig.h + * header file, as that directory will already be in the compilers include + * path. + * + * 2) Rename the copied file stdint.h. + * + */ + +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef short int16_t; +typedef unsigned short uint16_t; +typedef long int32_t; +typedef unsigned long uint32_t; + +#endif /* FREERTOS_STDINT */ diff --git a/component/os/freertos/freertos_v8.1.2/Source/include/task.h b/component/os/freertos/freertos_v8.1.2/Source/include/task.h new file mode 100644 index 0000000..ca71024 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/include/task.h @@ -0,0 +1,1570 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +#ifndef INC_TASK_H +#define INC_TASK_H + +#ifndef INC_FREERTOS_H + #error "include FreeRTOS.h must appear in source files before include task.h" +#endif + +#include "list.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*----------------------------------------------------------- + * MACROS AND DEFINITIONS + *----------------------------------------------------------*/ + +#define tskKERNEL_VERSION_NUMBER "V8.1.2" +#define tskKERNEL_VERSION_MAJOR 8 +#define tskKERNEL_VERSION_MINOR 1 +#define tskKERNEL_VERSION_BUILD 2 + +/** + * task. h + * + * Type by which tasks are referenced. For example, a call to xTaskCreate + * returns (via a pointer parameter) an TaskHandle_t variable that can then + * be used as a parameter to vTaskDelete to delete the task. + * + * \defgroup TaskHandle_t TaskHandle_t + * \ingroup Tasks + */ +typedef void * TaskHandle_t; + +/* + * Defines the prototype to which the application task hook function must + * conform. + */ +typedef BaseType_t (*TaskHookFunction_t)( void * ); + +/* Task states returned by eTaskGetState. */ +typedef enum +{ + eRunning = 0, /* A task is querying the state of itself, so must be running. */ + eReady, /* The task being queried is in a read or pending ready list. */ + eBlocked, /* The task being queried is in the Blocked state. */ + eSuspended, /* The task being queried is in the Suspended state, or is in the Blocked state with an infinite time out. */ + eDeleted /* The task being queried has been deleted, but its TCB has not yet been freed. */ +} eTaskState; + +/* + * Used internally only. + */ +typedef struct xTIME_OUT +{ + BaseType_t xOverflowCount; + TickType_t xTimeOnEntering; +} TimeOut_t; + +/* + * Defines the memory ranges allocated to the task when an MPU is used. + */ +typedef struct xMEMORY_REGION +{ + void *pvBaseAddress; + uint32_t ulLengthInBytes; + uint32_t ulParameters; +} MemoryRegion_t; + +/* + * Parameters required to create an MPU protected task. + */ +typedef struct xTASK_PARAMETERS +{ + TaskFunction_t pvTaskCode; + const char * const pcName; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + uint16_t usStackDepth; + void *pvParameters; + UBaseType_t uxPriority; + StackType_t *puxStackBuffer; + MemoryRegion_t xRegions[ portNUM_CONFIGURABLE_REGIONS ]; +} TaskParameters_t; + +/* Used with the uxTaskGetSystemState() function to return the state of each task +in the system. */ +typedef struct xTASK_STATUS +{ + TaskHandle_t xHandle; /* The handle of the task to which the rest of the information in the structure relates. */ + const char *pcTaskName; /* A pointer to the task's name. This value will be invalid if the task was deleted since the structure was populated! */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + UBaseType_t xTaskNumber; /* A number unique to the task. */ + eTaskState eCurrentState; /* The state in which the task existed when the structure was populated. */ + UBaseType_t uxCurrentPriority; /* The priority at which the task was running (may be inherited) when the structure was populated. */ + UBaseType_t uxBasePriority; /* The priority to which the task will return if the task's current priority has been inherited to avoid unbounded priority inversion when obtaining a mutex. Only valid if configUSE_MUTEXES is defined as 1 in FreeRTOSConfig.h. */ + uint32_t ulRunTimeCounter; /* The total run time allocated to the task so far, as defined by the run time stats clock. See http://www.freertos.org/rtos-run-time-stats.html. Only valid when configGENERATE_RUN_TIME_STATS is defined as 1 in FreeRTOSConfig.h. */ +#if ( configGENERATE_RUN_TIME_STATS == 1 ) + uint32_t ulDelataRunTimeCounterOfPeroid;/* The delta run time counter in a sample peroid*/ +#endif + uint16_t usStackHighWaterMark; /* The minimum amount of stack space that has remained for the task since the task was created. The closer this value is to zero the closer the task has come to overflowing its stack. */ +} TaskStatus_t; + +/* Possible return values for eTaskConfirmSleepModeStatus(). */ +typedef enum +{ + eAbortSleep = 0, /* A task has been made ready or a context switch pended since portSUPPORESS_TICKS_AND_SLEEP() was called - abort entering a sleep mode. */ + eStandardSleep, /* Enter a sleep mode that will not last any longer than the expected idle time. */ + eNoTasksWaitingTimeout /* No tasks are waiting for a timeout so it is safe to enter a sleep mode that can only be exited by an external interrupt. */ +} eSleepModeStatus; + + +/** + * Defines the priority used by the idle task. This must not be modified. + * + * \ingroup TaskUtils + */ +#define tskIDLE_PRIORITY ( ( UBaseType_t ) 0U ) + +/** + * task. h + * + * Macro for forcing a context switch. + * + * \defgroup taskYIELD taskYIELD + * \ingroup SchedulerControl + */ +#define taskYIELD() portYIELD() + +/** + * task. h + * + * Macro to mark the start of a critical code region. Preemptive context + * switches cannot occur when in a critical region. + * + * NOTE: This may alter the stack (depending on the portable implementation) + * so must be used with care! + * + * \defgroup taskENTER_CRITICAL taskENTER_CRITICAL + * \ingroup SchedulerControl + */ +#define taskENTER_CRITICAL() portENTER_CRITICAL() + +/** + * task. h + * + * Macro to mark the end of a critical code region. Preemptive context + * switches cannot occur when in a critical region. + * + * NOTE: This may alter the stack (depending on the portable implementation) + * so must be used with care! + * + * \defgroup taskEXIT_CRITICAL taskEXIT_CRITICAL + * \ingroup SchedulerControl + */ +#define taskEXIT_CRITICAL() portEXIT_CRITICAL() + +/** + * task. h + * + * Macro to disable all maskable interrupts. + * + * \defgroup taskDISABLE_INTERRUPTS taskDISABLE_INTERRUPTS + * \ingroup SchedulerControl + */ +#define taskDISABLE_INTERRUPTS() portDISABLE_INTERRUPTS() + +/** + * task. h + * + * Macro to enable microcontroller interrupts. + * + * \defgroup taskENABLE_INTERRUPTS taskENABLE_INTERRUPTS + * \ingroup SchedulerControl + */ +#define taskENABLE_INTERRUPTS() portENABLE_INTERRUPTS() + +/* Definitions returned by xTaskGetSchedulerState(). taskSCHEDULER_SUSPENDED is +0 to generate more optimal code when configASSERT() is defined as the constant +is used in assert() statements. */ +#define taskSCHEDULER_SUSPENDED ( ( BaseType_t ) 0 ) +#define taskSCHEDULER_NOT_STARTED ( ( BaseType_t ) 1 ) +#define taskSCHEDULER_RUNNING ( ( BaseType_t ) 2 ) + + +/*----------------------------------------------------------- + * TASK CREATION API + *----------------------------------------------------------*/ + +/** + * task. h + *
+ BaseType_t xTaskCreate(
+							  TaskFunction_t pvTaskCode,
+							  const char * const pcName,
+							  uint16_t usStackDepth,
+							  void *pvParameters,
+							  UBaseType_t uxPriority,
+							  TaskHandle_t *pvCreatedTask
+						  );
+ * + * Create a new task and add it to the list of tasks that are ready to run. + * + * xTaskCreate() can only be used to create a task that has unrestricted + * access to the entire microcontroller memory map. Systems that include MPU + * support can alternatively create an MPU constrained task using + * xTaskCreateRestricted(). + * + * @param pvTaskCode Pointer to the task entry function. Tasks + * must be implemented to never return (i.e. continuous loop). + * + * @param pcName A descriptive name for the task. This is mainly used to + * facilitate debugging. Max length defined by configMAX_TASK_NAME_LEN - default + * is 16. + * + * @param usStackDepth The size of the task stack specified as the number of + * variables the stack can hold - not the number of bytes. For example, if + * the stack is 16 bits wide and usStackDepth is defined as 100, 200 bytes + * will be allocated for stack storage. + * + * @param pvParameters Pointer that will be used as the parameter for the task + * being created. + * + * @param uxPriority The priority at which the task should run. Systems that + * include MPU support can optionally create tasks in a privileged (system) + * mode by setting bit portPRIVILEGE_BIT of the priority parameter. For + * example, to create a privileged task at priority 2 the uxPriority parameter + * should be set to ( 2 | portPRIVILEGE_BIT ). + * + * @param pvCreatedTask Used to pass back a handle by which the created task + * can be referenced. + * + * @return pdPASS if the task was successfully created and added to a ready + * list, otherwise an error code defined in the file projdefs.h + * + * Example usage: +
+ // Task to be created.
+ void vTaskCode( void * pvParameters )
+ {
+	 for( ;; )
+	 {
+		 // Task code goes here.
+	 }
+ }
+
+ // Function that creates a task.
+ void vOtherFunction( void )
+ {
+ static uint8_t ucParameterToPass;
+ TaskHandle_t xHandle = NULL;
+
+	 // Create the task, storing the handle.  Note that the passed parameter ucParameterToPass
+	 // must exist for the lifetime of the task, so in this case is declared static.  If it was just an
+	 // an automatic stack variable it might no longer exist, or at least have been corrupted, by the time
+	 // the new task attempts to access it.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, &ucParameterToPass, tskIDLE_PRIORITY, &xHandle );
+     configASSERT( xHandle );
+
+	 // Use the handle to delete the task.
+     if( xHandle != NULL )
+     {
+	     vTaskDelete( xHandle );
+     }
+ }
+   
+ * \defgroup xTaskCreate xTaskCreate + * \ingroup Tasks + */ +#define xTaskCreate( pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask ) xTaskGenericCreate( ( pvTaskCode ), ( pcName ), ( usStackDepth ), ( pvParameters ), ( uxPriority ), ( pxCreatedTask ), ( NULL ), ( NULL ) ) + +/** + * task. h + *
+ BaseType_t xTaskCreateRestricted( TaskParameters_t *pxTaskDefinition, TaskHandle_t *pxCreatedTask );
+ * + * xTaskCreateRestricted() should only be used in systems that include an MPU + * implementation. + * + * Create a new task and add it to the list of tasks that are ready to run. + * The function parameters define the memory regions and associated access + * permissions allocated to the task. + * + * @param pxTaskDefinition Pointer to a structure that contains a member + * for each of the normal xTaskCreate() parameters (see the xTaskCreate() API + * documentation) plus an optional stack buffer and the memory region + * definitions. + * + * @param pxCreatedTask Used to pass back a handle by which the created task + * can be referenced. + * + * @return pdPASS if the task was successfully created and added to a ready + * list, otherwise an error code defined in the file projdefs.h + * + * Example usage: +
+// Create an TaskParameters_t structure that defines the task to be created.
+static const TaskParameters_t xCheckTaskParameters =
+{
+	vATask,		// pvTaskCode - the function that implements the task.
+	"ATask",	// pcName - just a text name for the task to assist debugging.
+	100,		// usStackDepth	- the stack size DEFINED IN WORDS.
+	NULL,		// pvParameters - passed into the task function as the function parameters.
+	( 1UL | portPRIVILEGE_BIT ),// uxPriority - task priority, set the portPRIVILEGE_BIT if the task should run in a privileged state.
+	cStackBuffer,// puxStackBuffer - the buffer to be used as the task stack.
+
+	// xRegions - Allocate up to three separate memory regions for access by
+	// the task, with appropriate access permissions.  Different processors have
+	// different memory alignment requirements - refer to the FreeRTOS documentation
+	// for full information.
+	{
+		// Base address					Length	Parameters
+        { cReadWriteArray,				32,		portMPU_REGION_READ_WRITE },
+        { cReadOnlyArray,				32,		portMPU_REGION_READ_ONLY },
+        { cPrivilegedOnlyAccessArray,	128,	portMPU_REGION_PRIVILEGED_READ_WRITE }
+	}
+};
+
+int main( void )
+{
+TaskHandle_t xHandle;
+
+	// Create a task from the const structure defined above.  The task handle
+	// is requested (the second parameter is not NULL) but in this case just for
+	// demonstration purposes as its not actually used.
+	xTaskCreateRestricted( &xRegTest1Parameters, &xHandle );
+
+	// Start the scheduler.
+	vTaskStartScheduler();
+
+	// Will only get here if there was insufficient memory to create the idle
+	// and/or timer task.
+	for( ;; );
+}
+   
+ * \defgroup xTaskCreateRestricted xTaskCreateRestricted + * \ingroup Tasks + */ +#define xTaskCreateRestricted( x, pxCreatedTask ) xTaskGenericCreate( ((x)->pvTaskCode), ((x)->pcName), ((x)->usStackDepth), ((x)->pvParameters), ((x)->uxPriority), (pxCreatedTask), ((x)->puxStackBuffer), ((x)->xRegions) ) + +/** + * task. h + *
+ void vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const pxRegions );
+ * + * Memory regions are assigned to a restricted task when the task is created by + * a call to xTaskCreateRestricted(). These regions can be redefined using + * vTaskAllocateMPURegions(). + * + * @param xTask The handle of the task being updated. + * + * @param xRegions A pointer to an MemoryRegion_t structure that contains the + * new memory region definitions. + * + * Example usage: +
+// Define an array of MemoryRegion_t structures that configures an MPU region
+// allowing read/write access for 1024 bytes starting at the beginning of the
+// ucOneKByte array.  The other two of the maximum 3 definable regions are
+// unused so set to zero.
+static const MemoryRegion_t xAltRegions[ portNUM_CONFIGURABLE_REGIONS ] =
+{
+	// Base address		Length		Parameters
+	{ ucOneKByte,		1024,		portMPU_REGION_READ_WRITE },
+	{ 0,				0,			0 },
+	{ 0,				0,			0 }
+};
+
+void vATask( void *pvParameters )
+{
+	// This task was created such that it has access to certain regions of
+	// memory as defined by the MPU configuration.  At some point it is
+	// desired that these MPU regions are replaced with that defined in the
+	// xAltRegions const struct above.  Use a call to vTaskAllocateMPURegions()
+	// for this purpose.  NULL is used as the task handle to indicate that this
+	// function should modify the MPU regions of the calling task.
+	vTaskAllocateMPURegions( NULL, xAltRegions );
+
+	// Now the task can continue its function, but from this point on can only
+	// access its stack and the ucOneKByte array (unless any other statically
+	// defined or shared regions have been declared elsewhere).
+}
+   
+ * \defgroup xTaskCreateRestricted xTaskCreateRestricted + * \ingroup Tasks + */ +void vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const pxRegions ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskDelete( TaskHandle_t xTask );
+ * + * INCLUDE_vTaskDelete must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Remove a task from the RTOS real time kernel's management. The task being + * deleted will be removed from all ready, blocked, suspended and event lists. + * + * NOTE: The idle task is responsible for freeing the kernel allocated + * memory from tasks that have been deleted. It is therefore important that + * the idle task is not starved of microcontroller processing time if your + * application makes any calls to vTaskDelete (). Memory allocated by the + * task code is not automatically freed, and should be freed before the task + * is deleted. + * + * See the demo application file death.c for sample code that utilises + * vTaskDelete (). + * + * @param xTask The handle of the task to be deleted. Passing NULL will + * cause the calling task to be deleted. + * + * Example usage: +
+ void vOtherFunction( void )
+ {
+ TaskHandle_t xHandle;
+
+	 // Create the task, storing the handle.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+	 // Use the handle to delete the task.
+	 vTaskDelete( xHandle );
+ }
+   
+ * \defgroup vTaskDelete vTaskDelete + * \ingroup Tasks + */ +void vTaskDelete( TaskHandle_t xTaskToDelete ) PRIVILEGED_FUNCTION; + +/*----------------------------------------------------------- + * TASK CONTROL API + *----------------------------------------------------------*/ + +/** + * task. h + *
void vTaskDelay( const TickType_t xTicksToDelay );
+ * + * Delay a task for a given number of ticks. The actual time that the + * task remains blocked depends on the tick rate. The constant + * portTICK_PERIOD_MS can be used to calculate real time from the tick + * rate - with the resolution of one tick period. + * + * INCLUDE_vTaskDelay must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * + * vTaskDelay() specifies a time at which the task wishes to unblock relative to + * the time at which vTaskDelay() is called. For example, specifying a block + * period of 100 ticks will cause the task to unblock 100 ticks after + * vTaskDelay() is called. vTaskDelay() does not therefore provide a good method + * of controlling the frequency of a periodic task as the path taken through the + * code, as well as other task and interrupt activity, will effect the frequency + * at which vTaskDelay() gets called and therefore the time at which the task + * next executes. See vTaskDelayUntil() for an alternative API function designed + * to facilitate fixed frequency execution. It does this by specifying an + * absolute time (rather than a relative time) at which the calling task should + * unblock. + * + * @param xTicksToDelay The amount of time, in tick periods, that + * the calling task should block. + * + * Example usage: + + void vTaskFunction( void * pvParameters ) + { + // Block for 500ms. + const TickType_t xDelay = 500 / portTICK_PERIOD_MS; + + for( ;; ) + { + // Simply toggle the LED every 500ms, blocking between each toggle. + vToggleLED(); + vTaskDelay( xDelay ); + } + } + + * \defgroup vTaskDelay vTaskDelay + * \ingroup TaskCtrl + */ +void vTaskDelay( const TickType_t xTicksToDelay ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskDelayUntil( TickType_t *pxPreviousWakeTime, const TickType_t xTimeIncrement );
+ * + * INCLUDE_vTaskDelayUntil must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Delay a task until a specified time. This function can be used by periodic + * tasks to ensure a constant execution frequency. + * + * This function differs from vTaskDelay () in one important aspect: vTaskDelay () will + * cause a task to block for the specified number of ticks from the time vTaskDelay () is + * called. It is therefore difficult to use vTaskDelay () by itself to generate a fixed + * execution frequency as the time between a task starting to execute and that task + * calling vTaskDelay () may not be fixed [the task may take a different path though the + * code between calls, or may get interrupted or preempted a different number of times + * each time it executes]. + * + * Whereas vTaskDelay () specifies a wake time relative to the time at which the function + * is called, vTaskDelayUntil () specifies the absolute (exact) time at which it wishes to + * unblock. + * + * The constant portTICK_PERIOD_MS can be used to calculate real time from the tick + * rate - with the resolution of one tick period. + * + * @param pxPreviousWakeTime Pointer to a variable that holds the time at which the + * task was last unblocked. The variable must be initialised with the current time + * prior to its first use (see the example below). Following this the variable is + * automatically updated within vTaskDelayUntil (). + * + * @param xTimeIncrement The cycle time period. The task will be unblocked at + * time *pxPreviousWakeTime + xTimeIncrement. Calling vTaskDelayUntil with the + * same xTimeIncrement parameter value will cause the task to execute with + * a fixed interface period. + * + * Example usage: +
+ // Perform an action every 10 ticks.
+ void vTaskFunction( void * pvParameters )
+ {
+ TickType_t xLastWakeTime;
+ const TickType_t xFrequency = 10;
+
+	 // Initialise the xLastWakeTime variable with the current time.
+	 xLastWakeTime = xTaskGetTickCount ();
+	 for( ;; )
+	 {
+		 // Wait for the next cycle.
+		 vTaskDelayUntil( &xLastWakeTime, xFrequency );
+
+		 // Perform action here.
+	 }
+ }
+   
+ * \defgroup vTaskDelayUntil vTaskDelayUntil + * \ingroup TaskCtrl + */ +void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask );
+ * + * INCLUDE_uxTaskPriorityGet must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Obtain the priority of any task. + * + * @param xTask Handle of the task to be queried. Passing a NULL + * handle results in the priority of the calling task being returned. + * + * @return The priority of xTask. + * + * Example usage: +
+ void vAFunction( void )
+ {
+ TaskHandle_t xHandle;
+
+	 // Create a task, storing the handle.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+	 // ...
+
+	 // Use the handle to obtain the priority of the created task.
+	 // It was created with tskIDLE_PRIORITY, but may have changed
+	 // it itself.
+	 if( uxTaskPriorityGet( xHandle ) != tskIDLE_PRIORITY )
+	 {
+		 // The task has changed it's priority.
+	 }
+
+	 // ...
+
+	 // Is our priority higher than the created task?
+	 if( uxTaskPriorityGet( xHandle ) < uxTaskPriorityGet( NULL ) )
+	 {
+		 // Our priority (obtained using NULL handle) is higher.
+	 }
+ }
+   
+ * \defgroup uxTaskPriorityGet uxTaskPriorityGet + * \ingroup TaskCtrl + */ +UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
eTaskState eTaskGetState( TaskHandle_t xTask );
+ * + * INCLUDE_eTaskGetState must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Obtain the state of any task. States are encoded by the eTaskState + * enumerated type. + * + * @param xTask Handle of the task to be queried. + * + * @return The state of xTask at the time the function was called. Note the + * state of the task might change between the function being called, and the + * functions return value being tested by the calling task. + */ +eTaskState eTaskGetState( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority );
+ * + * INCLUDE_vTaskPrioritySet must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Set the priority of any task. + * + * A context switch will occur before the function returns if the priority + * being set is higher than the currently executing task. + * + * @param xTask Handle to the task for which the priority is being set. + * Passing a NULL handle results in the priority of the calling task being set. + * + * @param uxNewPriority The priority to which the task will be set. + * + * Example usage: +
+ void vAFunction( void )
+ {
+ TaskHandle_t xHandle;
+
+	 // Create a task, storing the handle.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+	 // ...
+
+	 // Use the handle to raise the priority of the created task.
+	 vTaskPrioritySet( xHandle, tskIDLE_PRIORITY + 1 );
+
+	 // ...
+
+	 // Use a NULL handle to raise our priority to the same value.
+	 vTaskPrioritySet( NULL, tskIDLE_PRIORITY + 1 );
+ }
+   
+ * \defgroup vTaskPrioritySet vTaskPrioritySet + * \ingroup TaskCtrl + */ +void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskSuspend( TaskHandle_t xTaskToSuspend );
+ * + * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Suspend any task. When suspended a task will never get any microcontroller + * processing time, no matter what its priority. + * + * Calls to vTaskSuspend are not accumulative - + * i.e. calling vTaskSuspend () twice on the same task still only requires one + * call to vTaskResume () to ready the suspended task. + * + * @param xTaskToSuspend Handle to the task being suspended. Passing a NULL + * handle will cause the calling task to be suspended. + * + * Example usage: +
+ void vAFunction( void )
+ {
+ TaskHandle_t xHandle;
+
+	 // Create a task, storing the handle.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+	 // ...
+
+	 // Use the handle to suspend the created task.
+	 vTaskSuspend( xHandle );
+
+	 // ...
+
+	 // The created task will not run during this period, unless
+	 // another task calls vTaskResume( xHandle ).
+
+	 //...
+
+
+	 // Suspend ourselves.
+	 vTaskSuspend( NULL );
+
+	 // We cannot get here unless another task calls vTaskResume
+	 // with our handle as the parameter.
+ }
+   
+ * \defgroup vTaskSuspend vTaskSuspend + * \ingroup TaskCtrl + */ +void vTaskSuspend( TaskHandle_t xTaskToSuspend ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskResume( TaskHandle_t xTaskToResume );
+ * + * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Resumes a suspended task. + * + * A task that has been suspended by one or more calls to vTaskSuspend () + * will be made available for running again by a single call to + * vTaskResume (). + * + * @param xTaskToResume Handle to the task being readied. + * + * Example usage: +
+ void vAFunction( void )
+ {
+ TaskHandle_t xHandle;
+
+	 // Create a task, storing the handle.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+	 // ...
+
+	 // Use the handle to suspend the created task.
+	 vTaskSuspend( xHandle );
+
+	 // ...
+
+	 // The created task will not run during this period, unless
+	 // another task calls vTaskResume( xHandle ).
+
+	 //...
+
+
+	 // Resume the suspended task ourselves.
+	 vTaskResume( xHandle );
+
+	 // The created task will once again get microcontroller processing
+	 // time in accordance with its priority within the system.
+ }
+   
+ * \defgroup vTaskResume vTaskResume + * \ingroup TaskCtrl + */ +void vTaskResume( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void xTaskResumeFromISR( TaskHandle_t xTaskToResume );
+ * + * INCLUDE_xTaskResumeFromISR must be defined as 1 for this function to be + * available. See the configuration section for more information. + * + * An implementation of vTaskResume() that can be called from within an ISR. + * + * A task that has been suspended by one or more calls to vTaskSuspend () + * will be made available for running again by a single call to + * xTaskResumeFromISR (). + * + * xTaskResumeFromISR() should not be used to synchronise a task with an + * interrupt if there is a chance that the interrupt could arrive prior to the + * task being suspended - as this can lead to interrupts being missed. Use of a + * semaphore as a synchronisation mechanism would avoid this eventuality. + * + * @param xTaskToResume Handle to the task being readied. + * + * @return pdTRUE if resuming the task should result in a context switch, + * otherwise pdFALSE. This is used by the ISR to determine if a context switch + * may be required following the ISR. + * + * \defgroup vTaskResumeFromISR vTaskResumeFromISR + * \ingroup TaskCtrl + */ +BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION; + +/*----------------------------------------------------------- + * SCHEDULER CONTROL + *----------------------------------------------------------*/ + +/** + * task. h + *
void vTaskStartScheduler( void );
+ * + * Starts the real time kernel tick processing. After calling the kernel + * has control over which tasks are executed and when. + * + * See the demo application file main.c for an example of creating + * tasks and starting the kernel. + * + * Example usage: +
+ void vAFunction( void )
+ {
+	 // Create at least one task before starting the kernel.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
+
+	 // Start the real time kernel with preemption.
+	 vTaskStartScheduler ();
+
+	 // Will not get here unless a task calls vTaskEndScheduler ()
+ }
+   
+ * + * \defgroup vTaskStartScheduler vTaskStartScheduler + * \ingroup SchedulerControl + */ +void vTaskStartScheduler( void ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskEndScheduler( void );
+ * + * NOTE: At the time of writing only the x86 real mode port, which runs on a PC + * in place of DOS, implements this function. + * + * Stops the real time kernel tick. All created tasks will be automatically + * deleted and multitasking (either preemptive or cooperative) will + * stop. Execution then resumes from the point where vTaskStartScheduler () + * was called, as if vTaskStartScheduler () had just returned. + * + * See the demo application file main. c in the demo/PC directory for an + * example that uses vTaskEndScheduler (). + * + * vTaskEndScheduler () requires an exit function to be defined within the + * portable layer (see vPortEndScheduler () in port. c for the PC port). This + * performs hardware specific operations such as stopping the kernel tick. + * + * vTaskEndScheduler () will cause all of the resources allocated by the + * kernel to be freed - but will not free resources allocated by application + * tasks. + * + * Example usage: +
+ void vTaskCode( void * pvParameters )
+ {
+	 for( ;; )
+	 {
+		 // Task code goes here.
+
+		 // At some point we want to end the real time kernel processing
+		 // so call ...
+		 vTaskEndScheduler ();
+	 }
+ }
+
+ void vAFunction( void )
+ {
+	 // Create at least one task before starting the kernel.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
+
+	 // Start the real time kernel with preemption.
+	 vTaskStartScheduler ();
+
+	 // Will only get here when the vTaskCode () task has called
+	 // vTaskEndScheduler ().  When we get here we are back to single task
+	 // execution.
+ }
+   
+ * + * \defgroup vTaskEndScheduler vTaskEndScheduler + * \ingroup SchedulerControl + */ +void vTaskEndScheduler( void ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskSuspendAll( void );
+ * + * Suspends the scheduler without disabling interrupts. Context switches will + * not occur while the scheduler is suspended. + * + * After calling vTaskSuspendAll () the calling task will continue to execute + * without risk of being swapped out until a call to xTaskResumeAll () has been + * made. + * + * API functions that have the potential to cause a context switch (for example, + * vTaskDelayUntil(), xQueueSend(), etc.) must not be called while the scheduler + * is suspended. + * + * Example usage: +
+ void vTask1( void * pvParameters )
+ {
+	 for( ;; )
+	 {
+		 // Task code goes here.
+
+		 // ...
+
+		 // At some point the task wants to perform a long operation during
+		 // which it does not want to get swapped out.  It cannot use
+		 // taskENTER_CRITICAL ()/taskEXIT_CRITICAL () as the length of the
+		 // operation may cause interrupts to be missed - including the
+		 // ticks.
+
+		 // Prevent the real time kernel swapping out the task.
+		 vTaskSuspendAll ();
+
+		 // Perform the operation here.  There is no need to use critical
+		 // sections as we have all the microcontroller processing time.
+		 // During this time interrupts will still operate and the kernel
+		 // tick count will be maintained.
+
+		 // ...
+
+		 // The operation is complete.  Restart the kernel.
+		 xTaskResumeAll ();
+	 }
+ }
+   
+ * \defgroup vTaskSuspendAll vTaskSuspendAll + * \ingroup SchedulerControl + */ +void vTaskSuspendAll( void ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
BaseType_t xTaskResumeAll( void );
+ * + * Resumes scheduler activity after it was suspended by a call to + * vTaskSuspendAll(). + * + * xTaskResumeAll() only resumes the scheduler. It does not unsuspend tasks + * that were previously suspended by a call to vTaskSuspend(). + * + * @return If resuming the scheduler caused a context switch then pdTRUE is + * returned, otherwise pdFALSE is returned. + * + * Example usage: +
+ void vTask1( void * pvParameters )
+ {
+	 for( ;; )
+	 {
+		 // Task code goes here.
+
+		 // ...
+
+		 // At some point the task wants to perform a long operation during
+		 // which it does not want to get swapped out.  It cannot use
+		 // taskENTER_CRITICAL ()/taskEXIT_CRITICAL () as the length of the
+		 // operation may cause interrupts to be missed - including the
+		 // ticks.
+
+		 // Prevent the real time kernel swapping out the task.
+		 vTaskSuspendAll ();
+
+		 // Perform the operation here.  There is no need to use critical
+		 // sections as we have all the microcontroller processing time.
+		 // During this time interrupts will still operate and the real
+		 // time kernel tick count will be maintained.
+
+		 // ...
+
+		 // The operation is complete.  Restart the kernel.  We want to force
+		 // a context switch - but there is no point if resuming the scheduler
+		 // caused a context switch already.
+		 if( !xTaskResumeAll () )
+		 {
+			  taskYIELD ();
+		 }
+	 }
+ }
+   
+ * \defgroup xTaskResumeAll xTaskResumeAll + * \ingroup SchedulerControl + */ +BaseType_t xTaskResumeAll( void ) PRIVILEGED_FUNCTION; + +/*----------------------------------------------------------- + * TASK UTILITIES + *----------------------------------------------------------*/ + +/** + * task. h + *
TickType_t xTaskGetTickCount( void );
+ * + * @return The count of ticks since vTaskStartScheduler was called. + * + * \defgroup xTaskGetTickCount xTaskGetTickCount + * \ingroup TaskUtils + */ +TickType_t xTaskGetTickCount( void ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
TickType_t xTaskGetTickCountFromISR( void );
+ * + * @return The count of ticks since vTaskStartScheduler was called. + * + * This is a version of xTaskGetTickCount() that is safe to be called from an + * ISR - provided that TickType_t is the natural word size of the + * microcontroller being used or interrupt nesting is either not supported or + * not being used. + * + * \defgroup xTaskGetTickCountFromISR xTaskGetTickCountFromISR + * \ingroup TaskUtils + */ +TickType_t xTaskGetTickCountFromISR( void ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
uint16_t uxTaskGetNumberOfTasks( void );
+ * + * @return The number of tasks that the real time kernel is currently managing. + * This includes all ready, blocked and suspended tasks. A task that + * has been deleted but not yet freed by the idle task will also be + * included in the count. + * + * \defgroup uxTaskGetNumberOfTasks uxTaskGetNumberOfTasks + * \ingroup TaskUtils + */ +UBaseType_t uxTaskGetNumberOfTasks( void ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
char *pcTaskGetTaskName( TaskHandle_t xTaskToQuery );
+ * + * @return The text (human readable) name of the task referenced by the handle + * xTaskToQuery. A task can query its own name by either passing in its own + * handle, or by setting xTaskToQuery to NULL. INCLUDE_pcTaskGetTaskName must be + * set to 1 in FreeRTOSConfig.h for pcTaskGetTaskName() to be available. + * + * \defgroup pcTaskGetTaskName pcTaskGetTaskName + * \ingroup TaskUtils + */ +char *pcTaskGetTaskName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + +/** + * task.h + *
UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask );
+ * + * INCLUDE_uxTaskGetStackHighWaterMark must be set to 1 in FreeRTOSConfig.h for + * this function to be available. + * + * Returns the high water mark of the stack associated with xTask. That is, + * the minimum free stack space there has been (in words, so on a 32 bit machine + * a value of 1 means 4 bytes) since the task started. The smaller the returned + * number the closer the task has come to overflowing its stack. + * + * @param xTask Handle of the task associated with the stack to be checked. + * Set xTask to NULL to check the stack of the calling task. + * + * @return The smallest amount of free stack space there has been (in words, so + * actual spaces on the stack rather than bytes) since the task referenced by + * xTask was created. + */ +UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; + +/* When using trace macros it is sometimes necessary to include task.h before +FreeRTOS.h. When this is done TaskHookFunction_t will not yet have been defined, +so the following two prototypes will cause a compilation error. This can be +fixed by simply guarding against the inclusion of these two prototypes unless +they are explicitly required by the configUSE_APPLICATION_TASK_TAG configuration +constant. */ +#ifdef configUSE_APPLICATION_TASK_TAG + #if configUSE_APPLICATION_TASK_TAG == 1 + /** + * task.h + *
void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction );
+ * + * Sets pxHookFunction to be the task hook function used by the task xTask. + * Passing xTask as NULL has the effect of setting the calling tasks hook + * function. + */ + void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction ) PRIVILEGED_FUNCTION; + + /** + * task.h + *
void xTaskGetApplicationTaskTag( TaskHandle_t xTask );
+ * + * Returns the pxHookFunction value assigned to the task xTask. + */ + TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; + #endif /* configUSE_APPLICATION_TASK_TAG ==1 */ +#endif /* ifdef configUSE_APPLICATION_TASK_TAG */ + +/** + * task.h + *
BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter );
+ * + * Calls the hook function associated with xTask. Passing xTask as NULL has + * the effect of calling the Running tasks (the calling task) hook function. + * + * pvParameter is passed to the hook function for the task to interpret as it + * wants. The return value is the value returned by the task hook function + * registered by the user. + */ +BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter ) PRIVILEGED_FUNCTION; + +/** + * xTaskGetIdleTaskHandle() is only available if + * INCLUDE_xTaskGetIdleTaskHandle is set to 1 in FreeRTOSConfig.h. + * + * Simply returns the handle of the idle task. It is not valid to call + * xTaskGetIdleTaskHandle() before the scheduler has been started. + */ +TaskHandle_t xTaskGetIdleTaskHandle( void ); + +/** + * configUSE_TRACE_FACILITY must be defined as 1 in FreeRTOSConfig.h for + * uxTaskGetSystemState() to be available. + * + * uxTaskGetSystemState() populates an TaskStatus_t structure for each task in + * the system. TaskStatus_t structures contain, among other things, members + * for the task handle, task name, task priority, task state, and total amount + * of run time consumed by the task. See the TaskStatus_t structure + * definition in this file for the full member list. + * + * NOTE: This function is intended for debugging use only as its use results in + * the scheduler remaining suspended for an extended period. + * + * @param pxTaskStatusArray A pointer to an array of TaskStatus_t structures. + * The array must contain at least one TaskStatus_t structure for each task + * that is under the control of the RTOS. The number of tasks under the control + * of the RTOS can be determined using the uxTaskGetNumberOfTasks() API function. + * + * @param uxArraySize The size of the array pointed to by the pxTaskStatusArray + * parameter. The size is specified as the number of indexes in the array, or + * the number of TaskStatus_t structures contained in the array, not by the + * number of bytes in the array. + * + * @param pulTotalRunTime If configGENERATE_RUN_TIME_STATS is set to 1 in + * FreeRTOSConfig.h then *pulTotalRunTime is set by uxTaskGetSystemState() to the + * total run time (as defined by the run time stats clock, see + * http://www.freertos.org/rtos-run-time-stats.html) since the target booted. + * pulTotalRunTime can be set to NULL to omit the total run time information. + * + * @return The number of TaskStatus_t structures that were populated by + * uxTaskGetSystemState(). This should equal the number returned by the + * uxTaskGetNumberOfTasks() API function, but will be zero if the value passed + * in the uxArraySize parameter was too small. + * + * Example usage: +
+    // This example demonstrates how a human readable table of run time stats
+	// information is generated from raw data provided by uxTaskGetSystemState().
+	// The human readable table is written to pcWriteBuffer
+	void vTaskGetRunTimeStats( char *pcWriteBuffer )
+	{
+	TaskStatus_t *pxTaskStatusArray;
+	volatile UBaseType_t uxArraySize, x;
+	uint32_t ulTotalRunTime, ulStatsAsPercentage;
+
+		// Make sure the write buffer does not contain a string.
+		*pcWriteBuffer = 0x00;
+
+		// Take a snapshot of the number of tasks in case it changes while this
+		// function is executing.
+		uxArraySize = uxTaskGetNumberOfTasks();
+
+		// Allocate a TaskStatus_t structure for each task.  An array could be
+		// allocated statically at compile time.
+		pxTaskStatusArray = pvPortMalloc( uxArraySize * sizeof( TaskStatus_t ) );
+
+		if( pxTaskStatusArray != NULL )
+		{
+			// Generate raw status information about each task.
+			uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalRunTime );
+
+			// For percentage calculations.
+			ulTotalRunTime /= 100UL;
+
+			// Avoid divide by zero errors.
+			if( ulTotalRunTime > 0 )
+			{
+				// For each populated position in the pxTaskStatusArray array,
+				// format the raw data as human readable ASCII data
+				for( x = 0; x < uxArraySize; x++ )
+				{
+					// What percentage of the total run time has the task used?
+					// This will always be rounded down to the nearest integer.
+					// ulTotalRunTimeDiv100 has already been divided by 100.
+					ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalRunTime;
+
+					if( ulStatsAsPercentage > 0UL )
+					{
+						sprintf( pcWriteBuffer, "%s\t\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage );
+					}
+					else
+					{
+						// If the percentage is zero here then the task has
+						// consumed less than 1% of the total run time.
+						sprintf( pcWriteBuffer, "%s\t\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter );
+					}
+
+					pcWriteBuffer += strlen( ( char * ) pcWriteBuffer );
+				}
+			}
+
+			// The array is no longer needed, free the memory it consumes.
+			vPortFree( pxTaskStatusArray );
+		}
+	}
+	
+ */ +UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, uint32_t * const pulTotalRunTime ); + +/** + * task. h + *
void vTaskList( char *pcWriteBuffer );
+ * + * configUSE_TRACE_FACILITY and configUSE_STATS_FORMATTING_FUNCTIONS must + * both be defined as 1 for this function to be available. See the + * configuration section of the FreeRTOS.org website for more information. + * + * NOTE 1: This function will disable interrupts for its duration. It is + * not intended for normal application runtime use but as a debug aid. + * + * Lists all the current tasks, along with their current state and stack + * usage high water mark. + * + * Tasks are reported as blocked ('B'), ready ('R'), deleted ('D') or + * suspended ('S'). + * + * PLEASE NOTE: + * + * This function is provided for convenience only, and is used by many of the + * demo applications. Do not consider it to be part of the scheduler. + * + * vTaskList() calls uxTaskGetSystemState(), then formats part of the + * uxTaskGetSystemState() output into a human readable table that displays task + * names, states and stack usage. + * + * vTaskList() has a dependency on the sprintf() C library function that might + * bloat the code size, use a lot of stack, and provide different results on + * different platforms. An alternative, tiny, third party, and limited + * functionality implementation of sprintf() is provided in many of the + * FreeRTOS/Demo sub-directories in a file called printf-stdarg.c (note + * printf-stdarg.c does not provide a full snprintf() implementation!). + * + * It is recommended that production systems call uxTaskGetSystemState() + * directly to get access to raw stats data, rather than indirectly through a + * call to vTaskList(). + * + * @param pcWriteBuffer A buffer into which the above mentioned details + * will be written, in ASCII form. This buffer is assumed to be large + * enough to contain the generated report. Approximately 40 bytes per + * task should be sufficient. + * + * \defgroup vTaskList vTaskList + * \ingroup TaskUtils + */ +void vTaskList( char * pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + +/** + * task. h + *
void vTaskGetRunTimeStats( char *pcWriteBuffer );
+ * + * configGENERATE_RUN_TIME_STATS and configUSE_STATS_FORMATTING_FUNCTIONS + * must both be defined as 1 for this function to be available. The application + * must also then provide definitions for + * portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and portGET_RUN_TIME_COUNTER_VALUE() + * to configure a peripheral timer/counter and return the timers current count + * value respectively. The counter should be at least 10 times the frequency of + * the tick count. + * + * NOTE 1: This function will disable interrupts for its duration. It is + * not intended for normal application runtime use but as a debug aid. + * + * Setting configGENERATE_RUN_TIME_STATS to 1 will result in a total + * accumulated execution time being stored for each task. The resolution + * of the accumulated time value depends on the frequency of the timer + * configured by the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() macro. + * Calling vTaskGetRunTimeStats() writes the total execution time of each + * task into a buffer, both as an absolute count value and as a percentage + * of the total system execution time. + * + * NOTE 2: + * + * This function is provided for convenience only, and is used by many of the + * demo applications. Do not consider it to be part of the scheduler. + * + * vTaskGetRunTimeStats() calls uxTaskGetSystemState(), then formats part of the + * uxTaskGetSystemState() output into a human readable table that displays the + * amount of time each task has spent in the Running state in both absolute and + * percentage terms. + * + * vTaskGetRunTimeStats() has a dependency on the sprintf() C library function + * that might bloat the code size, use a lot of stack, and provide different + * results on different platforms. An alternative, tiny, third party, and + * limited functionality implementation of sprintf() is provided in many of the + * FreeRTOS/Demo sub-directories in a file called printf-stdarg.c (note + * printf-stdarg.c does not provide a full snprintf() implementation!). + * + * It is recommended that production systems call uxTaskGetSystemState() directly + * to get access to raw stats data, rather than indirectly through a call to + * vTaskGetRunTimeStats(). + * + * @param pcWriteBuffer A buffer into which the execution times will be + * written, in ASCII form. This buffer is assumed to be large enough to + * contain the generated report. Approximately 40 bytes per task should + * be sufficient. + * + * \defgroup vTaskGetRunTimeStats vTaskGetRunTimeStats + * \ingroup TaskUtils + */ +void vTaskGetRunTimeStats( char *pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + +/*----------------------------------------------------------- + * SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES + *----------------------------------------------------------*/ + +/* + * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS ONLY + * INTENDED FOR USE WHEN IMPLEMENTING A PORT OF THE SCHEDULER AND IS + * AN INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. + * + * Called from the real time kernel tick (either preemptive or cooperative), + * this increments the tick count and checks if any tasks that are blocked + * for a finite period required removing from a blocked list and placing on + * a ready list. If a non-zero value is returned then a context switch is + * required because either: + * + A task was removed from a blocked list because its timeout had expired, + * or + * + Time slicing is in use and there is a task of equal priority to the + * currently running task. + */ +BaseType_t xTaskIncrementTick( void ) PRIVILEGED_FUNCTION; + +/* + * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN + * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. + * + * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED. + * + * Removes the calling task from the ready list and places it both + * on the list of tasks waiting for a particular event, and the + * list of delayed tasks. The task will be removed from both lists + * and replaced on the ready list should either the event occur (and + * there be no higher priority tasks waiting on the same event) or + * the delay period expires. + * + * The 'unordered' version replaces the event list item value with the + * xItemValue value, and inserts the list item at the end of the list. + * + * The 'ordered' version uses the existing event list item value (which is the + * owning tasks priority) to insert the list item into the event list is task + * priority order. + * + * @param pxEventList The list containing tasks that are blocked waiting + * for the event to occur. + * + * @param xItemValue The item value to use for the event list item when the + * event list is not ordered by task priority. + * + * @param xTicksToWait The maximum amount of time that the task should wait + * for the event to occur. This is specified in kernel ticks,the constant + * portTICK_PERIOD_MS can be used to convert kernel ticks into a real time + * period. + */ +void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; +void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xItemValue, const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; + +/* + * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN + * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. + * + * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED. + * + * This function performs nearly the same function as vTaskPlaceOnEventList(). + * The difference being that this function does not permit tasks to block + * indefinitely, whereas vTaskPlaceOnEventList() does. + * + */ +void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; + +/* + * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN + * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. + * + * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED. + * + * Removes a task from both the specified event list and the list of blocked + * tasks, and places it on a ready queue. + * + * xTaskRemoveFromEventList()/xTaskRemoveFromUnorderedEventList() will be called + * if either an event occurs to unblock a task, or the block timeout period + * expires. + * + * xTaskRemoveFromEventList() is used when the event list is in task priority + * order. It removes the list item from the head of the event list as that will + * have the highest priority owning task of all the tasks on the event list. + * xTaskRemoveFromUnorderedEventList() is used when the event list is not + * ordered and the event list items hold something other than the owning tasks + * priority. In this case the event list item value is updated to the value + * passed in the xItemValue parameter. + * + * @return pdTRUE if the task being removed has a higher priority than the task + * making the call, otherwise pdFALSE. + */ +BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList ) PRIVILEGED_FUNCTION; +BaseType_t xTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, const TickType_t xItemValue ) PRIVILEGED_FUNCTION; + +/* + * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS ONLY + * INTENDED FOR USE WHEN IMPLEMENTING A PORT OF THE SCHEDULER AND IS + * AN INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. + * + * Sets the pointer to the current TCB to the TCB of the highest priority task + * that is ready to run. + */ +void vTaskSwitchContext( void ) PRIVILEGED_FUNCTION; + +/* + * THESE FUNCTIONS MUST NOT BE USED FROM APPLICATION CODE. THEY ARE USED BY + * THE EVENT BITS MODULE. + */ +TickType_t uxTaskResetEventItemValue( void ) PRIVILEGED_FUNCTION; + +/* + * Return the handle of the calling task. + */ +TaskHandle_t xTaskGetCurrentTaskHandle( void ) PRIVILEGED_FUNCTION; + +/* + * Capture the current time status for future reference. + */ +void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNCTION; + +/* + * Compare the time status now with that previously captured to see if the + * timeout has expired. + */ +BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait ) PRIVILEGED_FUNCTION; + +/* + * Shortcut used by the queue implementation to prevent unnecessary call to + * taskYIELD(); + */ +void vTaskMissedYield( void ) PRIVILEGED_FUNCTION; + +/* + * Returns the scheduler state as taskSCHEDULER_RUNNING, + * taskSCHEDULER_NOT_STARTED or taskSCHEDULER_SUSPENDED. + */ +BaseType_t xTaskGetSchedulerState( void ) PRIVILEGED_FUNCTION; + +/* + * Raises the priority of the mutex holder to that of the calling task should + * the mutex holder have a priority less than the calling task. + */ +void vTaskPriorityInherit( TaskHandle_t const pxMutexHolder ) PRIVILEGED_FUNCTION; + +/* + * Set the priority of a task back to its proper priority in the case that it + * inherited a higher priority while it was holding a semaphore. + */ +BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder ) PRIVILEGED_FUNCTION; + +/* + * Generic version of the task creation function which is in turn called by the + * xTaskCreate() and xTaskCreateRestricted() macros. + */ +BaseType_t xTaskGenericCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask, StackType_t * const puxStackBuffer, const MemoryRegion_t * const xRegions ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + +/* + * Get the uxTCBNumber assigned to the task referenced by the xTask parameter. + */ +UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; + +/* + * Set the uxTaskNumber of the task referenced by the xTask parameter to + * uxHandle. + */ +void vTaskSetTaskNumber( TaskHandle_t xTask, const UBaseType_t uxHandle ) PRIVILEGED_FUNCTION; + +/* + * Only available when configUSE_TICKLESS_IDLE is set to 1. + * If tickless mode is being used, or a low power mode is implemented, then + * the tick interrupt will not execute during idle periods. When this is the + * case, the tick count value maintained by the scheduler needs to be kept up + * to date with the actual execution time by being skipped forward by a time + * equal to the idle period. + */ +void vTaskStepTick( const TickType_t xTicksToJump ) PRIVILEGED_FUNCTION; + +/* + * Only avilable when configUSE_TICKLESS_IDLE is set to 1. + * Provided for use within portSUPPRESS_TICKS_AND_SLEEP() to allow the port + * specific sleep function to determine if it is ok to proceed with the sleep, + * and if it is ok to proceed, if it is ok to sleep indefinitely. + * + * This function is necessary because portSUPPRESS_TICKS_AND_SLEEP() is only + * called with the scheduler suspended, not from within a critical section. It + * is therefore possible for an interrupt to request a context switch between + * portSUPPRESS_TICKS_AND_SLEEP() and the low power mode actually being + * entered. eTaskConfirmSleepModeStatus() should be called from a short + * critical section between the timer being stopped and the sleep mode being + * entered to ensure it is ok to proceed into the sleep mode. + */ +eSleepModeStatus eTaskConfirmSleepModeStatus( void ) PRIVILEGED_FUNCTION; + +/* + * For internal use only. Increment the mutex held count when a mutex is + * taken and return the handle of the task that has taken the mutex. + */ +void *pvTaskIncrementMutexHeldCount( void ); + +#ifdef __cplusplus +} +#endif +#endif /* INC_TASK_H */ + + + diff --git a/component/os/freertos/freertos_v8.1.2/Source/include/timers.h b/component/os/freertos/freertos_v8.1.2/Source/include/timers.h new file mode 100644 index 0000000..3949135 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/include/timers.h @@ -0,0 +1,1121 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +#ifndef TIMERS_H +#define TIMERS_H + +#ifndef INC_FREERTOS_H + #error "include FreeRTOS.h must appear in source files before include timers.h" +#endif + +/*lint -e537 This headers are only multiply included if the application code +happens to also be including task.h. */ +#include "task.h" +/*lint +e956 */ + +#ifdef __cplusplus +extern "C" { +#endif + +/*----------------------------------------------------------- + * MACROS AND DEFINITIONS + *----------------------------------------------------------*/ + +/* IDs for commands that can be sent/received on the timer queue. These are to +be used solely through the macros that make up the public software timer API, +as defined below. The commands that are sent from interrupts must use the +highest numbers as tmrFIRST_FROM_ISR_COMMAND is used to determine if the task +or interrupt version of the queue send function should be used. */ +#define tmrCOMMAND_EXECUTE_CALLBACK_FROM_ISR ( ( BaseType_t ) -2 ) +#define tmrCOMMAND_EXECUTE_CALLBACK ( ( BaseType_t ) -1 ) +#define tmrCOMMAND_START_DONT_TRACE ( ( BaseType_t ) 0 ) +#define tmrCOMMAND_START ( ( BaseType_t ) 1 ) +#define tmrCOMMAND_RESET ( ( BaseType_t ) 2 ) +#define tmrCOMMAND_STOP ( ( BaseType_t ) 3 ) +#define tmrCOMMAND_CHANGE_PERIOD ( ( BaseType_t ) 4 ) +#define tmrCOMMAND_DELETE ( ( BaseType_t ) 5 ) + +#define tmrFIRST_FROM_ISR_COMMAND ( ( BaseType_t ) 6 ) +#define tmrCOMMAND_START_FROM_ISR ( ( BaseType_t ) 6 ) +#define tmrCOMMAND_RESET_FROM_ISR ( ( BaseType_t ) 7 ) +#define tmrCOMMAND_STOP_FROM_ISR ( ( BaseType_t ) 8 ) +#define tmrCOMMAND_CHANGE_PERIOD_FROM_ISR ( ( BaseType_t ) 9 ) + + +/** + * Type by which software timers are referenced. For example, a call to + * xTimerCreate() returns an TimerHandle_t variable that can then be used to + * reference the subject timer in calls to other software timer API functions + * (for example, xTimerStart(), xTimerReset(), etc.). + */ +typedef void * TimerHandle_t; + +/* + * Defines the prototype to which timer callback functions must conform. + */ +typedef void (*TimerCallbackFunction_t)( TimerHandle_t xTimer ); + +/* + * Defines the prototype to which functions used with the + * xTimerPendFunctionCallFromISR() function must conform. + */ +typedef void (*PendedFunction_t)( void *, uint32_t ); + +/** + * TimerHandle_t xTimerCreate( const char * const pcTimerName, + * TickType_t xTimerPeriodInTicks, + * UBaseType_t uxAutoReload, + * void * pvTimerID, + * TimerCallbackFunction_t pxCallbackFunction ); + * + * Creates a new software timer instance. This allocates the storage required + * by the new timer, initialises the new timers internal state, and returns a + * handle by which the new timer can be referenced. + * + * Timers are created in the dormant state. The xTimerStart(), xTimerReset(), + * xTimerStartFromISR(), xTimerResetFromISR(), xTimerChangePeriod() and + * xTimerChangePeriodFromISR() API functions can all be used to transition a + * timer into the active state. + * + * @param pcTimerName A text name that is assigned to the timer. This is done + * purely to assist debugging. The kernel itself only ever references a timer + * by its handle, and never by its name. + * + * @param xTimerPeriodInTicks The timer period. The time is defined in tick + * periods so the constant portTICK_PERIOD_MS can be used to convert a time that + * has been specified in milliseconds. For example, if the timer must expire + * after 100 ticks, then xTimerPeriodInTicks should be set to 100. + * Alternatively, if the timer must expire after 500ms, then xPeriod can be set + * to ( 500 / portTICK_PERIOD_MS ) provided configTICK_RATE_HZ is less than or + * equal to 1000. + * + * @param uxAutoReload If uxAutoReload is set to pdTRUE then the timer will + * expire repeatedly with a frequency set by the xTimerPeriodInTicks parameter. + * If uxAutoReload is set to pdFALSE then the timer will be a one-shot timer and + * enter the dormant state after it expires. + * + * @param pvTimerID An identifier that is assigned to the timer being created. + * Typically this would be used in the timer callback function to identify which + * timer expired when the same callback function is assigned to more than one + * timer. + * + * @param pxCallbackFunction The function to call when the timer expires. + * Callback functions must have the prototype defined by TimerCallbackFunction_t, + * which is "void vCallbackFunction( TimerHandle_t xTimer );". + * + * @return If the timer is successfully created then a handle to the newly + * created timer is returned. If the timer cannot be created (because either + * there is insufficient FreeRTOS heap remaining to allocate the timer + * structures, or the timer period was set to 0) then NULL is returned. + * + * Example usage: + * @verbatim + * #define NUM_TIMERS 5 + * + * // An array to hold handles to the created timers. + * TimerHandle_t xTimers[ NUM_TIMERS ]; + * + * // An array to hold a count of the number of times each timer expires. + * int32_t lExpireCounters[ NUM_TIMERS ] = { 0 }; + * + * // Define a callback function that will be used by multiple timer instances. + * // The callback function does nothing but count the number of times the + * // associated timer expires, and stop the timer once the timer has expired + * // 10 times. + * void vTimerCallback( TimerHandle_t pxTimer ) + * { + * int32_t lArrayIndex; + * const int32_t xMaxExpiryCountBeforeStopping = 10; + * + * // Optionally do something if the pxTimer parameter is NULL. + * configASSERT( pxTimer ); + * + * // Which timer expired? + * lArrayIndex = ( int32_t ) pvTimerGetTimerID( pxTimer ); + * + * // Increment the number of times that pxTimer has expired. + * lExpireCounters[ lArrayIndex ] += 1; + * + * // If the timer has expired 10 times then stop it from running. + * if( lExpireCounters[ lArrayIndex ] == xMaxExpiryCountBeforeStopping ) + * { + * // Do not use a block time if calling a timer API function from a + * // timer callback function, as doing so could cause a deadlock! + * xTimerStop( pxTimer, 0 ); + * } + * } + * + * void main( void ) + * { + * int32_t x; + * + * // Create then start some timers. Starting the timers before the scheduler + * // has been started means the timers will start running immediately that + * // the scheduler starts. + * for( x = 0; x < NUM_TIMERS; x++ ) + * { + * xTimers[ x ] = xTimerCreate( "Timer", // Just a text name, not used by the kernel. + * ( 100 * x ), // The timer period in ticks. + * pdTRUE, // The timers will auto-reload themselves when they expire. + * ( void * ) x, // Assign each timer a unique id equal to its array index. + * vTimerCallback // Each timer calls the same callback when it expires. + * ); + * + * if( xTimers[ x ] == NULL ) + * { + * // The timer was not created. + * } + * else + * { + * // Start the timer. No block time is specified, and even if one was + * // it would be ignored because the scheduler has not yet been + * // started. + * if( xTimerStart( xTimers[ x ], 0 ) != pdPASS ) + * { + * // The timer could not be set into the Active state. + * } + * } + * } + * + * // ... + * // Create tasks here. + * // ... + * + * // Starting the scheduler will start the timers running as they have already + * // been set into the active state. + * xTaskStartScheduler(); + * + * // Should not reach here. + * for( ;; ); + * } + * @endverbatim + */ +TimerHandle_t xTimerCreate( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, const UBaseType_t uxAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + +/** + * void *pvTimerGetTimerID( TimerHandle_t xTimer ); + * + * Returns the ID assigned to the timer. + * + * IDs are assigned to timers using the pvTimerID parameter of the call to + * xTimerCreated() that was used to create the timer. + * + * If the same callback function is assigned to multiple timers then the timer + * ID can be used within the callback function to identify which timer actually + * expired. + * + * @param xTimer The timer being queried. + * + * @return The ID assigned to the timer being queried. + * + * Example usage: + * + * See the xTimerCreate() API function example usage scenario. + */ +void *pvTimerGetTimerID( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; + +/** + * BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer ); + * + * Queries a timer to see if it is active or dormant. + * + * A timer will be dormant if: + * 1) It has been created but not started, or + * 2) It is an expired one-shot timer that has not been restarted. + * + * Timers are created in the dormant state. The xTimerStart(), xTimerReset(), + * xTimerStartFromISR(), xTimerResetFromISR(), xTimerChangePeriod() and + * xTimerChangePeriodFromISR() API functions can all be used to transition a timer into the + * active state. + * + * @param xTimer The timer being queried. + * + * @return pdFALSE will be returned if the timer is dormant. A value other than + * pdFALSE will be returned if the timer is active. + * + * Example usage: + * @verbatim + * // This function assumes xTimer has already been created. + * void vAFunction( TimerHandle_t xTimer ) + * { + * if( xTimerIsTimerActive( xTimer ) != pdFALSE ) // or more simply and equivalently "if( xTimerIsTimerActive( xTimer ) )" + * { + * // xTimer is active, do something. + * } + * else + * { + * // xTimer is not active, do something else. + * } + * } + * @endverbatim + */ +BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; + +/** + * TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ); + * + * xTimerGetTimerDaemonTaskHandle() is only available if + * INCLUDE_xTimerGetTimerDaemonTaskHandle is set to 1 in FreeRTOSConfig.h. + * + * Simply returns the handle of the timer service/daemon task. It it not valid + * to call xTimerGetTimerDaemonTaskHandle() before the scheduler has been started. + */ +TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ); + +/** + * BaseType_t xTimerStart( TimerHandle_t xTimer, TickType_t xTicksToWait ); + * + * Timer functionality is provided by a timer service/daemon task. Many of the + * public FreeRTOS timer API functions send commands to the timer service task + * through a queue called the timer command queue. The timer command queue is + * private to the kernel itself and is not directly accessible to application + * code. The length of the timer command queue is set by the + * configTIMER_QUEUE_LENGTH configuration constant. + * + * xTimerStart() starts a timer that was previously created using the + * xTimerCreate() API function. If the timer had already been started and was + * already in the active state, then xTimerStart() has equivalent functionality + * to the xTimerReset() API function. + * + * Starting a timer ensures the timer is in the active state. If the timer + * is not stopped, deleted, or reset in the mean time, the callback function + * associated with the timer will get called 'n' ticks after xTimerStart() was + * called, where 'n' is the timers defined period. + * + * It is valid to call xTimerStart() before the scheduler has been started, but + * when this is done the timer will not actually start until the scheduler is + * started, and the timers expiry time will be relative to when the scheduler is + * started, not relative to when xTimerStart() was called. + * + * The configUSE_TIMERS configuration constant must be set to 1 for xTimerStart() + * to be available. + * + * @param xTimer The handle of the timer being started/restarted. + * + * @param xTicksToWait Specifies the time, in ticks, that the calling task should + * be held in the Blocked state to wait for the start command to be successfully + * sent to the timer command queue, should the queue already be full when + * xTimerStart() was called. xTicksToWait is ignored if xTimerStart() is called + * before the scheduler is started. + * + * @return pdFAIL will be returned if the start command could not be sent to + * the timer command queue even after xTicksToWait ticks had passed. pdPASS will + * be returned if the command was successfully sent to the timer command queue. + * When the command is actually processed will depend on the priority of the + * timer service/daemon task relative to other tasks in the system, although the + * timers expiry time is relative to when xTimerStart() is actually called. The + * timer service/daemon task priority is set by the configTIMER_TASK_PRIORITY + * configuration constant. + * + * Example usage: + * + * See the xTimerCreate() API function example usage scenario. + * + */ +#define xTimerStart( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCount() ), NULL, ( xTicksToWait ) ) + +/** + * BaseType_t xTimerStop( TimerHandle_t xTimer, TickType_t xTicksToWait ); + * + * Timer functionality is provided by a timer service/daemon task. Many of the + * public FreeRTOS timer API functions send commands to the timer service task + * through a queue called the timer command queue. The timer command queue is + * private to the kernel itself and is not directly accessible to application + * code. The length of the timer command queue is set by the + * configTIMER_QUEUE_LENGTH configuration constant. + * + * xTimerStop() stops a timer that was previously started using either of the + * The xTimerStart(), xTimerReset(), xTimerStartFromISR(), xTimerResetFromISR(), + * xTimerChangePeriod() or xTimerChangePeriodFromISR() API functions. + * + * Stopping a timer ensures the timer is not in the active state. + * + * The configUSE_TIMERS configuration constant must be set to 1 for xTimerStop() + * to be available. + * + * @param xTimer The handle of the timer being stopped. + * + * @param xTicksToWait Specifies the time, in ticks, that the calling task should + * be held in the Blocked state to wait for the stop command to be successfully + * sent to the timer command queue, should the queue already be full when + * xTimerStop() was called. xTicksToWait is ignored if xTimerStop() is called + * before the scheduler is started. + * + * @return pdFAIL will be returned if the stop command could not be sent to + * the timer command queue even after xTicksToWait ticks had passed. pdPASS will + * be returned if the command was successfully sent to the timer command queue. + * When the command is actually processed will depend on the priority of the + * timer service/daemon task relative to other tasks in the system. The timer + * service/daemon task priority is set by the configTIMER_TASK_PRIORITY + * configuration constant. + * + * Example usage: + * + * See the xTimerCreate() API function example usage scenario. + * + */ +#define xTimerStop( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP, 0U, NULL, ( xTicksToWait ) ) + +/** + * BaseType_t xTimerChangePeriod( TimerHandle_t xTimer, + * TickType_t xNewPeriod, + * TickType_t xTicksToWait ); + * + * Timer functionality is provided by a timer service/daemon task. Many of the + * public FreeRTOS timer API functions send commands to the timer service task + * through a queue called the timer command queue. The timer command queue is + * private to the kernel itself and is not directly accessible to application + * code. The length of the timer command queue is set by the + * configTIMER_QUEUE_LENGTH configuration constant. + * + * xTimerChangePeriod() changes the period of a timer that was previously + * created using the xTimerCreate() API function. + * + * xTimerChangePeriod() can be called to change the period of an active or + * dormant state timer. + * + * The configUSE_TIMERS configuration constant must be set to 1 for + * xTimerChangePeriod() to be available. + * + * @param xTimer The handle of the timer that is having its period changed. + * + * @param xNewPeriod The new period for xTimer. Timer periods are specified in + * tick periods, so the constant portTICK_PERIOD_MS can be used to convert a time + * that has been specified in milliseconds. For example, if the timer must + * expire after 100 ticks, then xNewPeriod should be set to 100. Alternatively, + * if the timer must expire after 500ms, then xNewPeriod can be set to + * ( 500 / portTICK_PERIOD_MS ) provided configTICK_RATE_HZ is less than + * or equal to 1000. + * + * @param xTicksToWait Specifies the time, in ticks, that the calling task should + * be held in the Blocked state to wait for the change period command to be + * successfully sent to the timer command queue, should the queue already be + * full when xTimerChangePeriod() was called. xTicksToWait is ignored if + * xTimerChangePeriod() is called before the scheduler is started. + * + * @return pdFAIL will be returned if the change period command could not be + * sent to the timer command queue even after xTicksToWait ticks had passed. + * pdPASS will be returned if the command was successfully sent to the timer + * command queue. When the command is actually processed will depend on the + * priority of the timer service/daemon task relative to other tasks in the + * system. The timer service/daemon task priority is set by the + * configTIMER_TASK_PRIORITY configuration constant. + * + * Example usage: + * @verbatim + * // This function assumes xTimer has already been created. If the timer + * // referenced by xTimer is already active when it is called, then the timer + * // is deleted. If the timer referenced by xTimer is not active when it is + * // called, then the period of the timer is set to 500ms and the timer is + * // started. + * void vAFunction( TimerHandle_t xTimer ) + * { + * if( xTimerIsTimerActive( xTimer ) != pdFALSE ) // or more simply and equivalently "if( xTimerIsTimerActive( xTimer ) )" + * { + * // xTimer is already active - delete it. + * xTimerDelete( xTimer ); + * } + * else + * { + * // xTimer is not active, change its period to 500ms. This will also + * // cause the timer to start. Block for a maximum of 100 ticks if the + * // change period command cannot immediately be sent to the timer + * // command queue. + * if( xTimerChangePeriod( xTimer, 500 / portTICK_PERIOD_MS, 100 ) == pdPASS ) + * { + * // The command was successfully sent. + * } + * else + * { + * // The command could not be sent, even after waiting for 100 ticks + * // to pass. Take appropriate action here. + * } + * } + * } + * @endverbatim + */ + #define xTimerChangePeriod( xTimer, xNewPeriod, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_CHANGE_PERIOD, ( xNewPeriod ), NULL, ( xTicksToWait ) ) + +/** + * BaseType_t xTimerDelete( TimerHandle_t xTimer, TickType_t xTicksToWait ); + * + * Timer functionality is provided by a timer service/daemon task. Many of the + * public FreeRTOS timer API functions send commands to the timer service task + * through a queue called the timer command queue. The timer command queue is + * private to the kernel itself and is not directly accessible to application + * code. The length of the timer command queue is set by the + * configTIMER_QUEUE_LENGTH configuration constant. + * + * xTimerDelete() deletes a timer that was previously created using the + * xTimerCreate() API function. + * + * The configUSE_TIMERS configuration constant must be set to 1 for + * xTimerDelete() to be available. + * + * @param xTimer The handle of the timer being deleted. + * + * @param xTicksToWait Specifies the time, in ticks, that the calling task should + * be held in the Blocked state to wait for the delete command to be + * successfully sent to the timer command queue, should the queue already be + * full when xTimerDelete() was called. xTicksToWait is ignored if xTimerDelete() + * is called before the scheduler is started. + * + * @return pdFAIL will be returned if the delete command could not be sent to + * the timer command queue even after xTicksToWait ticks had passed. pdPASS will + * be returned if the command was successfully sent to the timer command queue. + * When the command is actually processed will depend on the priority of the + * timer service/daemon task relative to other tasks in the system. The timer + * service/daemon task priority is set by the configTIMER_TASK_PRIORITY + * configuration constant. + * + * Example usage: + * + * See the xTimerChangePeriod() API function example usage scenario. + */ +#define xTimerDelete( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_DELETE, 0U, NULL, ( xTicksToWait ) ) + +/** + * BaseType_t xTimerReset( TimerHandle_t xTimer, TickType_t xTicksToWait ); + * + * Timer functionality is provided by a timer service/daemon task. Many of the + * public FreeRTOS timer API functions send commands to the timer service task + * through a queue called the timer command queue. The timer command queue is + * private to the kernel itself and is not directly accessible to application + * code. The length of the timer command queue is set by the + * configTIMER_QUEUE_LENGTH configuration constant. + * + * xTimerReset() re-starts a timer that was previously created using the + * xTimerCreate() API function. If the timer had already been started and was + * already in the active state, then xTimerReset() will cause the timer to + * re-evaluate its expiry time so that it is relative to when xTimerReset() was + * called. If the timer was in the dormant state then xTimerReset() has + * equivalent functionality to the xTimerStart() API function. + * + * Resetting a timer ensures the timer is in the active state. If the timer + * is not stopped, deleted, or reset in the mean time, the callback function + * associated with the timer will get called 'n' ticks after xTimerReset() was + * called, where 'n' is the timers defined period. + * + * It is valid to call xTimerReset() before the scheduler has been started, but + * when this is done the timer will not actually start until the scheduler is + * started, and the timers expiry time will be relative to when the scheduler is + * started, not relative to when xTimerReset() was called. + * + * The configUSE_TIMERS configuration constant must be set to 1 for xTimerReset() + * to be available. + * + * @param xTimer The handle of the timer being reset/started/restarted. + * + * @param xTicksToWait Specifies the time, in ticks, that the calling task should + * be held in the Blocked state to wait for the reset command to be successfully + * sent to the timer command queue, should the queue already be full when + * xTimerReset() was called. xTicksToWait is ignored if xTimerReset() is called + * before the scheduler is started. + * + * @return pdFAIL will be returned if the reset command could not be sent to + * the timer command queue even after xTicksToWait ticks had passed. pdPASS will + * be returned if the command was successfully sent to the timer command queue. + * When the command is actually processed will depend on the priority of the + * timer service/daemon task relative to other tasks in the system, although the + * timers expiry time is relative to when xTimerStart() is actually called. The + * timer service/daemon task priority is set by the configTIMER_TASK_PRIORITY + * configuration constant. + * + * Example usage: + * @verbatim + * // When a key is pressed, an LCD back-light is switched on. If 5 seconds pass + * // without a key being pressed, then the LCD back-light is switched off. In + * // this case, the timer is a one-shot timer. + * + * TimerHandle_t xBacklightTimer = NULL; + * + * // The callback function assigned to the one-shot timer. In this case the + * // parameter is not used. + * void vBacklightTimerCallback( TimerHandle_t pxTimer ) + * { + * // The timer expired, therefore 5 seconds must have passed since a key + * // was pressed. Switch off the LCD back-light. + * vSetBacklightState( BACKLIGHT_OFF ); + * } + * + * // The key press event handler. + * void vKeyPressEventHandler( char cKey ) + * { + * // Ensure the LCD back-light is on, then reset the timer that is + * // responsible for turning the back-light off after 5 seconds of + * // key inactivity. Wait 10 ticks for the command to be successfully sent + * // if it cannot be sent immediately. + * vSetBacklightState( BACKLIGHT_ON ); + * if( xTimerReset( xBacklightTimer, 100 ) != pdPASS ) + * { + * // The reset command was not executed successfully. Take appropriate + * // action here. + * } + * + * // Perform the rest of the key processing here. + * } + * + * void main( void ) + * { + * int32_t x; + * + * // Create then start the one-shot timer that is responsible for turning + * // the back-light off if no keys are pressed within a 5 second period. + * xBacklightTimer = xTimerCreate( "BacklightTimer", // Just a text name, not used by the kernel. + * ( 5000 / portTICK_PERIOD_MS), // The timer period in ticks. + * pdFALSE, // The timer is a one-shot timer. + * 0, // The id is not used by the callback so can take any value. + * vBacklightTimerCallback // The callback function that switches the LCD back-light off. + * ); + * + * if( xBacklightTimer == NULL ) + * { + * // The timer was not created. + * } + * else + * { + * // Start the timer. No block time is specified, and even if one was + * // it would be ignored because the scheduler has not yet been + * // started. + * if( xTimerStart( xBacklightTimer, 0 ) != pdPASS ) + * { + * // The timer could not be set into the Active state. + * } + * } + * + * // ... + * // Create tasks here. + * // ... + * + * // Starting the scheduler will start the timer running as it has already + * // been set into the active state. + * xTaskStartScheduler(); + * + * // Should not reach here. + * for( ;; ); + * } + * @endverbatim + */ +#define xTimerReset( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_RESET, ( xTaskGetTickCount() ), NULL, ( xTicksToWait ) ) + +/** + * BaseType_t xTimerStartFromISR( TimerHandle_t xTimer, + * BaseType_t *pxHigherPriorityTaskWoken ); + * + * A version of xTimerStart() that can be called from an interrupt service + * routine. + * + * @param xTimer The handle of the timer being started/restarted. + * + * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most + * of its time in the Blocked state, waiting for messages to arrive on the timer + * command queue. Calling xTimerStartFromISR() writes a message to the timer + * command queue, so has the potential to transition the timer service/daemon + * task out of the Blocked state. If calling xTimerStartFromISR() causes the + * timer service/daemon task to leave the Blocked state, and the timer service/ + * daemon task has a priority equal to or greater than the currently executing + * task (the task that was interrupted), then *pxHigherPriorityTaskWoken will + * get set to pdTRUE internally within the xTimerStartFromISR() function. If + * xTimerStartFromISR() sets this value to pdTRUE then a context switch should + * be performed before the interrupt exits. + * + * @return pdFAIL will be returned if the start command could not be sent to + * the timer command queue. pdPASS will be returned if the command was + * successfully sent to the timer command queue. When the command is actually + * processed will depend on the priority of the timer service/daemon task + * relative to other tasks in the system, although the timers expiry time is + * relative to when xTimerStartFromISR() is actually called. The timer + * service/daemon task priority is set by the configTIMER_TASK_PRIORITY + * configuration constant. + * + * Example usage: + * @verbatim + * // This scenario assumes xBacklightTimer has already been created. When a + * // key is pressed, an LCD back-light is switched on. If 5 seconds pass + * // without a key being pressed, then the LCD back-light is switched off. In + * // this case, the timer is a one-shot timer, and unlike the example given for + * // the xTimerReset() function, the key press event handler is an interrupt + * // service routine. + * + * // The callback function assigned to the one-shot timer. In this case the + * // parameter is not used. + * void vBacklightTimerCallback( TimerHandle_t pxTimer ) + * { + * // The timer expired, therefore 5 seconds must have passed since a key + * // was pressed. Switch off the LCD back-light. + * vSetBacklightState( BACKLIGHT_OFF ); + * } + * + * // The key press interrupt service routine. + * void vKeyPressEventInterruptHandler( void ) + * { + * BaseType_t xHigherPriorityTaskWoken = pdFALSE; + * + * // Ensure the LCD back-light is on, then restart the timer that is + * // responsible for turning the back-light off after 5 seconds of + * // key inactivity. This is an interrupt service routine so can only + * // call FreeRTOS API functions that end in "FromISR". + * vSetBacklightState( BACKLIGHT_ON ); + * + * // xTimerStartFromISR() or xTimerResetFromISR() could be called here + * // as both cause the timer to re-calculate its expiry time. + * // xHigherPriorityTaskWoken was initialised to pdFALSE when it was + * // declared (in this function). + * if( xTimerStartFromISR( xBacklightTimer, &xHigherPriorityTaskWoken ) != pdPASS ) + * { + * // The start command was not executed successfully. Take appropriate + * // action here. + * } + * + * // Perform the rest of the key processing here. + * + * // If xHigherPriorityTaskWoken equals pdTRUE, then a context switch + * // should be performed. The syntax required to perform a context switch + * // from inside an ISR varies from port to port, and from compiler to + * // compiler. Inspect the demos for the port you are using to find the + * // actual syntax required. + * if( xHigherPriorityTaskWoken != pdFALSE ) + * { + * // Call the interrupt safe yield function here (actual function + * // depends on the FreeRTOS port being used). + * } + * } + * @endverbatim + */ +#define xTimerStartFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START_FROM_ISR, ( xTaskGetTickCountFromISR() ), ( pxHigherPriorityTaskWoken ), 0U ) + +/** + * BaseType_t xTimerStopFromISR( TimerHandle_t xTimer, + * BaseType_t *pxHigherPriorityTaskWoken ); + * + * A version of xTimerStop() that can be called from an interrupt service + * routine. + * + * @param xTimer The handle of the timer being stopped. + * + * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most + * of its time in the Blocked state, waiting for messages to arrive on the timer + * command queue. Calling xTimerStopFromISR() writes a message to the timer + * command queue, so has the potential to transition the timer service/daemon + * task out of the Blocked state. If calling xTimerStopFromISR() causes the + * timer service/daemon task to leave the Blocked state, and the timer service/ + * daemon task has a priority equal to or greater than the currently executing + * task (the task that was interrupted), then *pxHigherPriorityTaskWoken will + * get set to pdTRUE internally within the xTimerStopFromISR() function. If + * xTimerStopFromISR() sets this value to pdTRUE then a context switch should + * be performed before the interrupt exits. + * + * @return pdFAIL will be returned if the stop command could not be sent to + * the timer command queue. pdPASS will be returned if the command was + * successfully sent to the timer command queue. When the command is actually + * processed will depend on the priority of the timer service/daemon task + * relative to other tasks in the system. The timer service/daemon task + * priority is set by the configTIMER_TASK_PRIORITY configuration constant. + * + * Example usage: + * @verbatim + * // This scenario assumes xTimer has already been created and started. When + * // an interrupt occurs, the timer should be simply stopped. + * + * // The interrupt service routine that stops the timer. + * void vAnExampleInterruptServiceRoutine( void ) + * { + * BaseType_t xHigherPriorityTaskWoken = pdFALSE; + * + * // The interrupt has occurred - simply stop the timer. + * // xHigherPriorityTaskWoken was set to pdFALSE where it was defined + * // (within this function). As this is an interrupt service routine, only + * // FreeRTOS API functions that end in "FromISR" can be used. + * if( xTimerStopFromISR( xTimer, &xHigherPriorityTaskWoken ) != pdPASS ) + * { + * // The stop command was not executed successfully. Take appropriate + * // action here. + * } + * + * // If xHigherPriorityTaskWoken equals pdTRUE, then a context switch + * // should be performed. The syntax required to perform a context switch + * // from inside an ISR varies from port to port, and from compiler to + * // compiler. Inspect the demos for the port you are using to find the + * // actual syntax required. + * if( xHigherPriorityTaskWoken != pdFALSE ) + * { + * // Call the interrupt safe yield function here (actual function + * // depends on the FreeRTOS port being used). + * } + * } + * @endverbatim + */ +#define xTimerStopFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP_FROM_ISR, 0, ( pxHigherPriorityTaskWoken ), 0U ) + +/** + * BaseType_t xTimerChangePeriodFromISR( TimerHandle_t xTimer, + * TickType_t xNewPeriod, + * BaseType_t *pxHigherPriorityTaskWoken ); + * + * A version of xTimerChangePeriod() that can be called from an interrupt + * service routine. + * + * @param xTimer The handle of the timer that is having its period changed. + * + * @param xNewPeriod The new period for xTimer. Timer periods are specified in + * tick periods, so the constant portTICK_PERIOD_MS can be used to convert a time + * that has been specified in milliseconds. For example, if the timer must + * expire after 100 ticks, then xNewPeriod should be set to 100. Alternatively, + * if the timer must expire after 500ms, then xNewPeriod can be set to + * ( 500 / portTICK_PERIOD_MS ) provided configTICK_RATE_HZ is less than + * or equal to 1000. + * + * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most + * of its time in the Blocked state, waiting for messages to arrive on the timer + * command queue. Calling xTimerChangePeriodFromISR() writes a message to the + * timer command queue, so has the potential to transition the timer service/ + * daemon task out of the Blocked state. If calling xTimerChangePeriodFromISR() + * causes the timer service/daemon task to leave the Blocked state, and the + * timer service/daemon task has a priority equal to or greater than the + * currently executing task (the task that was interrupted), then + * *pxHigherPriorityTaskWoken will get set to pdTRUE internally within the + * xTimerChangePeriodFromISR() function. If xTimerChangePeriodFromISR() sets + * this value to pdTRUE then a context switch should be performed before the + * interrupt exits. + * + * @return pdFAIL will be returned if the command to change the timers period + * could not be sent to the timer command queue. pdPASS will be returned if the + * command was successfully sent to the timer command queue. When the command + * is actually processed will depend on the priority of the timer service/daemon + * task relative to other tasks in the system. The timer service/daemon task + * priority is set by the configTIMER_TASK_PRIORITY configuration constant. + * + * Example usage: + * @verbatim + * // This scenario assumes xTimer has already been created and started. When + * // an interrupt occurs, the period of xTimer should be changed to 500ms. + * + * // The interrupt service routine that changes the period of xTimer. + * void vAnExampleInterruptServiceRoutine( void ) + * { + * BaseType_t xHigherPriorityTaskWoken = pdFALSE; + * + * // The interrupt has occurred - change the period of xTimer to 500ms. + * // xHigherPriorityTaskWoken was set to pdFALSE where it was defined + * // (within this function). As this is an interrupt service routine, only + * // FreeRTOS API functions that end in "FromISR" can be used. + * if( xTimerChangePeriodFromISR( xTimer, &xHigherPriorityTaskWoken ) != pdPASS ) + * { + * // The command to change the timers period was not executed + * // successfully. Take appropriate action here. + * } + * + * // If xHigherPriorityTaskWoken equals pdTRUE, then a context switch + * // should be performed. The syntax required to perform a context switch + * // from inside an ISR varies from port to port, and from compiler to + * // compiler. Inspect the demos for the port you are using to find the + * // actual syntax required. + * if( xHigherPriorityTaskWoken != pdFALSE ) + * { + * // Call the interrupt safe yield function here (actual function + * // depends on the FreeRTOS port being used). + * } + * } + * @endverbatim + */ +#define xTimerChangePeriodFromISR( xTimer, xNewPeriod, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_CHANGE_PERIOD_FROM_ISR, ( xNewPeriod ), ( pxHigherPriorityTaskWoken ), 0U ) + +/** + * BaseType_t xTimerResetFromISR( TimerHandle_t xTimer, + * BaseType_t *pxHigherPriorityTaskWoken ); + * + * A version of xTimerReset() that can be called from an interrupt service + * routine. + * + * @param xTimer The handle of the timer that is to be started, reset, or + * restarted. + * + * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most + * of its time in the Blocked state, waiting for messages to arrive on the timer + * command queue. Calling xTimerResetFromISR() writes a message to the timer + * command queue, so has the potential to transition the timer service/daemon + * task out of the Blocked state. If calling xTimerResetFromISR() causes the + * timer service/daemon task to leave the Blocked state, and the timer service/ + * daemon task has a priority equal to or greater than the currently executing + * task (the task that was interrupted), then *pxHigherPriorityTaskWoken will + * get set to pdTRUE internally within the xTimerResetFromISR() function. If + * xTimerResetFromISR() sets this value to pdTRUE then a context switch should + * be performed before the interrupt exits. + * + * @return pdFAIL will be returned if the reset command could not be sent to + * the timer command queue. pdPASS will be returned if the command was + * successfully sent to the timer command queue. When the command is actually + * processed will depend on the priority of the timer service/daemon task + * relative to other tasks in the system, although the timers expiry time is + * relative to when xTimerResetFromISR() is actually called. The timer service/daemon + * task priority is set by the configTIMER_TASK_PRIORITY configuration constant. + * + * Example usage: + * @verbatim + * // This scenario assumes xBacklightTimer has already been created. When a + * // key is pressed, an LCD back-light is switched on. If 5 seconds pass + * // without a key being pressed, then the LCD back-light is switched off. In + * // this case, the timer is a one-shot timer, and unlike the example given for + * // the xTimerReset() function, the key press event handler is an interrupt + * // service routine. + * + * // The callback function assigned to the one-shot timer. In this case the + * // parameter is not used. + * void vBacklightTimerCallback( TimerHandle_t pxTimer ) + * { + * // The timer expired, therefore 5 seconds must have passed since a key + * // was pressed. Switch off the LCD back-light. + * vSetBacklightState( BACKLIGHT_OFF ); + * } + * + * // The key press interrupt service routine. + * void vKeyPressEventInterruptHandler( void ) + * { + * BaseType_t xHigherPriorityTaskWoken = pdFALSE; + * + * // Ensure the LCD back-light is on, then reset the timer that is + * // responsible for turning the back-light off after 5 seconds of + * // key inactivity. This is an interrupt service routine so can only + * // call FreeRTOS API functions that end in "FromISR". + * vSetBacklightState( BACKLIGHT_ON ); + * + * // xTimerStartFromISR() or xTimerResetFromISR() could be called here + * // as both cause the timer to re-calculate its expiry time. + * // xHigherPriorityTaskWoken was initialised to pdFALSE when it was + * // declared (in this function). + * if( xTimerResetFromISR( xBacklightTimer, &xHigherPriorityTaskWoken ) != pdPASS ) + * { + * // The reset command was not executed successfully. Take appropriate + * // action here. + * } + * + * // Perform the rest of the key processing here. + * + * // If xHigherPriorityTaskWoken equals pdTRUE, then a context switch + * // should be performed. The syntax required to perform a context switch + * // from inside an ISR varies from port to port, and from compiler to + * // compiler. Inspect the demos for the port you are using to find the + * // actual syntax required. + * if( xHigherPriorityTaskWoken != pdFALSE ) + * { + * // Call the interrupt safe yield function here (actual function + * // depends on the FreeRTOS port being used). + * } + * } + * @endverbatim + */ +#define xTimerResetFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_RESET_FROM_ISR, ( xTaskGetTickCountFromISR() ), ( pxHigherPriorityTaskWoken ), 0U ) + + +/** + * BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, + * void *pvParameter1, + * uint32_t ulParameter2, + * BaseType_t *pxHigherPriorityTaskWoken ); + * + * + * Used from application interrupt service routines to defer the execution of a + * function to the RTOS daemon task (the timer service task, hence this function + * is implemented in timers.c and is prefixed with 'Timer'). + * + * Ideally an interrupt service routine (ISR) is kept as short as possible, but + * sometimes an ISR either has a lot of processing to do, or needs to perform + * processing that is not deterministic. In these cases + * xTimerPendFunctionCallFromISR() can be used to defer processing of a function + * to the RTOS daemon task. + * + * A mechanism is provided that allows the interrupt to return directly to the + * task that will subsequently execute the pended callback function. This + * allows the callback function to execute contiguously in time with the + * interrupt - just as if the callback had executed in the interrupt itself. + * + * @param xFunctionToPend The function to execute from the timer service/ + * daemon task. The function must conform to the PendedFunction_t + * prototype. + * + * @param pvParameter1 The value of the callback function's first parameter. + * The parameter has a void * type to allow it to be used to pass any type. + * For example, unsigned longs can be cast to a void *, or the void * can be + * used to point to a structure. + * + * @param ulParameter2 The value of the callback function's second parameter. + * + * @param pxHigherPriorityTaskWoken As mentioned above, calling this function + * will result in a message being sent to the timer daemon task. If the + * priority of the timer daemon task (which is set using + * configTIMER_TASK_PRIORITY in FreeRTOSConfig.h) is higher than the priority of + * the currently running task (the task the interrupt interrupted) then + * *pxHigherPriorityTaskWoken will be set to pdTRUE within + * xTimerPendFunctionCallFromISR(), indicating that a context switch should be + * requested before the interrupt exits. For that reason + * *pxHigherPriorityTaskWoken must be initialised to pdFALSE. See the + * example code below. + * + * @return pdPASS is returned if the message was successfully sent to the + * timer daemon task, otherwise pdFALSE is returned. + * + * Example usage: + * @verbatim + * + * // The callback function that will execute in the context of the daemon task. + * // Note callback functions must all use this same prototype. + * void vProcessInterface( void *pvParameter1, uint32_t ulParameter2 ) + * { + * BaseType_t xInterfaceToService; + * + * // The interface that requires servicing is passed in the second + * // parameter. The first parameter is not used in this case. + * xInterfaceToService = ( BaseType_t ) ulParameter2; + * + * // ...Perform the processing here... + * } + * + * // An ISR that receives data packets from multiple interfaces + * void vAnISR( void ) + * { + * BaseType_t xInterfaceToService, xHigherPriorityTaskWoken; + * + * // Query the hardware to determine which interface needs processing. + * xInterfaceToService = prvCheckInterfaces(); + * + * // The actual processing is to be deferred to a task. Request the + * // vProcessInterface() callback function is executed, passing in the + * // number of the interface that needs processing. The interface to + * // service is passed in the second parameter. The first parameter is + * // not used in this case. + * xHigherPriorityTaskWoken = pdFALSE; + * xTimerPendFunctionCallFromISR( vProcessInterface, NULL, ( uint32_t ) xInterfaceToService, &xHigherPriorityTaskWoken ); + * + * // If xHigherPriorityTaskWoken is now set to pdTRUE then a context + * // switch should be requested. The macro used is port specific and will + * // be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() - refer to + * // the documentation page for the port being used. + * portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); + * + * } + * @endverbatim + */ +BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, BaseType_t *pxHigherPriorityTaskWoken ); + + /** + * BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, + * void *pvParameter1, + * uint32_t ulParameter2, + * TickType_t xTicksToWait ); + * + * + * Used to defer the execution of a function to the RTOS daemon task (the timer + * service task, hence this function is implemented in timers.c and is prefixed + * with 'Timer'). + * + * @param xFunctionToPend The function to execute from the timer service/ + * daemon task. The function must conform to the PendedFunction_t + * prototype. + * + * @param pvParameter1 The value of the callback function's first parameter. + * The parameter has a void * type to allow it to be used to pass any type. + * For example, unsigned longs can be cast to a void *, or the void * can be + * used to point to a structure. + * + * @param ulParameter2 The value of the callback function's second parameter. + * + * @param xTicksToWait Calling this function will result in a message being + * sent to the timer daemon task on a queue. xTicksToWait is the amount of + * time the calling task should remain in the Blocked state (so not using any + * processing time) for space to become available on the timer queue if the + * queue is found to be full. + * + * @return pdPASS is returned if the message was successfully sent to the + * timer daemon task, otherwise pdFALSE is returned. + * + */ +BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, TickType_t xTicksToWait ); + +/** + * const char * const pcTimerGetTimerName( TimerHandle_t xTimer ); + * + * Returns the name that was assigned to a timer when the timer was created. + * + * @param xTimer The handle of the timer being queried. + * + * @return The name assigned to the timer specified by the xTimer parameter. + */ +const char * pcTimerGetTimerName( TimerHandle_t xTimer ); /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + +/* + * Functions beyond this part are not part of the public API and are intended + * for use by the kernel only. + */ +BaseType_t xTimerCreateTimerTask( void ) PRIVILEGED_FUNCTION; +BaseType_t xTimerGenericCommand( TimerHandle_t xTimer, const BaseType_t xCommandID, const TickType_t xOptionalValue, BaseType_t * const pxHigherPriorityTaskWoken, const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; + +#ifdef __cplusplus +} +#endif +#endif /* TIMERS_H */ + + + diff --git a/component/os/freertos/freertos_v8.1.2/Source/list.c b/component/os/freertos/freertos_v8.1.2/Source/list.c new file mode 100644 index 0000000..701472a --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/list.c @@ -0,0 +1,204 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +#include +#include "FreeRTOS.h" +#include "list.h" + +/*----------------------------------------------------------- + * PUBLIC LIST API documented in list.h + *----------------------------------------------------------*/ + +void vListInitialise( List_t * const pxList ) +{ + /* The list structure contains a list item which is used to mark the + end of the list. To initialise the list the list end is inserted + as the only list entry. */ + pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */ + + /* The list end value is the highest possible value in the list to + ensure it remains at the end of the list. */ + pxList->xListEnd.xItemValue = portMAX_DELAY; + + /* The list end next and previous pointers point to itself so we know + when the list is empty. */ + pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */ + pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );/*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */ + + pxList->uxNumberOfItems = ( UBaseType_t ) 0U; +} +/*-----------------------------------------------------------*/ + +void vListInitialiseItem( ListItem_t * const pxItem ) +{ + /* Make sure the list item is not recorded as being on a list. */ + pxItem->pvContainer = NULL; +} +/*-----------------------------------------------------------*/ + +void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem ) +{ +ListItem_t * const pxIndex = pxList->pxIndex; + + /* Insert a new list item into pxList, but rather than sort the list, + makes the new list item the last item to be removed by a call to + listGET_OWNER_OF_NEXT_ENTRY(). */ + pxNewListItem->pxNext = pxIndex; + pxNewListItem->pxPrevious = pxIndex->pxPrevious; + pxIndex->pxPrevious->pxNext = pxNewListItem; + pxIndex->pxPrevious = pxNewListItem; + + /* Remember which list the item is in. */ + pxNewListItem->pvContainer = ( void * ) pxList; + + ( pxList->uxNumberOfItems )++; +} +/*-----------------------------------------------------------*/ + +void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem ) +{ +ListItem_t *pxIterator; +const TickType_t xValueOfInsertion = pxNewListItem->xItemValue; + + /* Insert the new list item into the list, sorted in xItemValue order. + + If the list already contains a list item with the same item value then + the new list item should be placed after it. This ensures that TCB's which + are stored in ready lists (all of which have the same xItemValue value) + get an equal share of the CPU. However, if the xItemValue is the same as + the back marker the iteration loop below will not end. This means we need + to guard against this by checking the value first and modifying the + algorithm slightly if necessary. */ + if( xValueOfInsertion == portMAX_DELAY ) + { + pxIterator = pxList->xListEnd.pxPrevious; + } + else + { + /* *** NOTE *********************************************************** + If you find your application is crashing here then likely causes are: + 1) Stack overflow - + see http://www.freertos.org/Stacks-and-stack-overflow-checking.html + 2) Incorrect interrupt priority assignment, especially on Cortex-M3 + parts where numerically high priority values denote low actual + interrupt priorities, which can seem counter intuitive. See + configMAX_SYSCALL_INTERRUPT_PRIORITY on http://www.freertos.org/a00110.html + 3) Calling an API function from within a critical section or when + the scheduler is suspended, or calling an API function that does + not end in "FromISR" from an interrupt. + 4) Using a queue or semaphore before it has been initialised or + before the scheduler has been started (are interrupts firing + before vTaskStartScheduler() has been called?). + See http://www.freertos.org/FAQHelp.html for more tips, and ensure + configASSERT() is defined! http://www.freertos.org/a00110.html#configASSERT + **********************************************************************/ + + for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */ + { + /* There is nothing to do here, we are just iterating to the + wanted insertion position. */ + } + } + + pxNewListItem->pxNext = pxIterator->pxNext; + pxNewListItem->pxNext->pxPrevious = pxNewListItem; + pxNewListItem->pxPrevious = pxIterator; + pxIterator->pxNext = pxNewListItem; + + /* Remember which list the item is in. This allows fast removal of the + item later. */ + pxNewListItem->pvContainer = ( void * ) pxList; + + ( pxList->uxNumberOfItems )++; +} +/*-----------------------------------------------------------*/ + +UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) +{ +/* The list item knows which list it is in. Obtain the list from the list +item. */ +List_t * const pxList = ( List_t * ) pxItemToRemove->pvContainer; + + pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious; + pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext; + + /* Make sure the index is left pointing to a valid item. */ + if( pxList->pxIndex == pxItemToRemove ) + { + pxList->pxIndex = pxItemToRemove->pxPrevious; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + pxItemToRemove->pvContainer = NULL; + ( pxList->uxNumberOfItems )--; + + return pxList->uxNumberOfItems; +} +/*-----------------------------------------------------------*/ + diff --git a/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM3/Makefile b/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM3/Makefile new file mode 100644 index 0000000..ce6da82 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM3/Makefile @@ -0,0 +1,32 @@ + +include $(MAKE_INCLUDE_GEN) + +.PHONY: all clean + +MODULE_IFLAGS = + + +#*****************************************************************************# +# Object FILE LIST # +#*****************************************************************************# +OBJS = port.o +ifeq ($(CONFIG_RELEASE_BUILD),y) + OBJS = +else +endif + + +#*****************************************************************************# +# RULES TO GENERATE TARGETS # +#*****************************************************************************# + +# Define the Rules to build the core targets +all: CORE_TARGETS COPY_RAM_OBJS + + +#*****************************************************************************# +# GENERATE OBJECT FILE +#*****************************************************************************# +CORE_TARGETS: $(OBJS) + +-include $(DEPS) diff --git a/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM3/port.c b/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM3/port.c new file mode 100644 index 0000000..972668f --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM3/port.c @@ -0,0 +1,745 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/*----------------------------------------------------------- + * Implementation of functions defined in portable.h for the ARM CM3 port. + *----------------------------------------------------------*/ + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "task.h" + +/* For backward compatibility, ensure configKERNEL_INTERRUPT_PRIORITY is +defined. The value should also ensure backward compatibility. +FreeRTOS.org versions prior to V4.4.0 did not include this definition. */ +#ifndef configKERNEL_INTERRUPT_PRIORITY + #define configKERNEL_INTERRUPT_PRIORITY 255 +#endif + +#ifndef configSYSTICK_CLOCK_HZ + #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ + /* Ensure the SysTick is clocked at the same frequency as the core. */ + #define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) +#else + /* The way the SysTick is clocked is not modified in case it is not the same + as the core. */ + #define portNVIC_SYSTICK_CLK_BIT ( 0 ) +#endif + +/* Constants required to manipulate the core. Registers first... */ +#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) ) +#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) ) +#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) ) +#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) ) +/* ...then bits in the registers. */ +#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL ) +#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL ) +#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL ) +#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL ) +#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL ) + +#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL ) +#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL ) + +/* Constants required to check the validity of an interrupt priority. */ +#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) +#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) +#define portAIRCR_REG ( * ( ( volatile uint32_t * ) 0xE000ED0C ) ) +#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff ) +#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 ) +#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 ) +#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) +#define portPRIGROUP_SHIFT ( 8UL ) + +/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */ +#define portVECTACTIVE_MASK ( 0x1FUL ) + +/* Constants required to set up the initial stack. */ +#define portINITIAL_XPSR ( 0x01000000UL ) + +/* The systick is a 24-bit counter. */ +#define portMAX_24_BIT_NUMBER ( 0xffffffUL ) + +/* A fiddle factor to estimate the number of SysTick counts that would have +occurred while the SysTick counter is stopped during tickless idle +calculations. */ +#define portMISSED_COUNTS_FACTOR ( 45UL ) + +/* Let the user override the pre-loading of the initial LR with the address of +prvTaskExitError() in case is messes up unwinding of the stack in the +debugger. */ +#ifdef configTASK_RETURN_ADDRESS + #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS +#else + #define portTASK_RETURN_ADDRESS prvTaskExitError +#endif + +/* Each task maintains its own interrupt status in the critical nesting +variable. */ +static UBaseType_t uxCriticalNesting = 0xaaaaaaaa; + +/* + * Setup the timer to generate the tick interrupts. The implementation in this + * file is weak to allow application writers to change the timer used to + * generate the tick interrupt. + */ +void vPortSetupTimerInterrupt( void ); + +/* + * Exception handlers. + */ +void xPortPendSVHandler( void ) __attribute__ (( naked )); +void xPortSysTickHandler( void ); +void vPortSVCHandler( void ) __attribute__ (( naked )); + +/* + * Start first task is a separate function so it can be tested in isolation. + */ +static void prvPortStartFirstTask( void ) __attribute__ (( naked )); + +/* + * Used to catch tasks that attempt to return from their implementing function. + */ +static void prvTaskExitError( void ); + +/*-----------------------------------------------------------*/ + +/* + * The number of SysTick increments that make up one tick period. + */ +#if configUSE_TICKLESS_IDLE == 1 + static uint32_t ulTimerCountsForOneTick = 0; +#endif /* configUSE_TICKLESS_IDLE */ + +/* + * The maximum number of tick periods that can be suppressed is limited by the + * 24 bit resolution of the SysTick timer. + */ +#if configUSE_TICKLESS_IDLE == 1 + static uint32_t xMaximumPossibleSuppressedTicks = 0; +#endif /* configUSE_TICKLESS_IDLE */ + +/* + * Compensate for the CPU cycles that pass while the SysTick is stopped (low + * power functionality only. + */ +#if configUSE_TICKLESS_IDLE == 1 + static uint32_t ulStoppedTimerCompensation = 0; +#endif /* configUSE_TICKLESS_IDLE */ + +/* + * Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure + * FreeRTOS API functions are not called from interrupts that have been assigned + * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY. + */ +#if ( configASSERT_DEFINED == 1 ) + static uint8_t ucMaxSysCallPriority = 0; + static uint32_t ulMaxPRIGROUPValue = 0; + static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * const ) portNVIC_IP_REGISTERS_OFFSET_16; +#endif /* configASSERT_DEFINED */ + +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) +{ + /* Simulate the stack frame as it would be created by a context switch + interrupt. */ + pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */ + *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) pxCode; /* PC */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */ + pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ + *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ + pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ + + return pxTopOfStack; +} +/*-----------------------------------------------------------*/ + +static void prvTaskExitError( void ) +{ + /* A function that implements a task must not exit or attempt to return to + its caller as there is nothing to return to. If a task wants to exit it + should instead call vTaskDelete( NULL ). + + Artificially force an assert() to be triggered if configASSERT() is + defined, then stop here so application writers can catch the error. */ + configASSERT( uxCriticalNesting == ~0UL ); + portDISABLE_INTERRUPTS(); + for( ;; ); +} +/*-----------------------------------------------------------*/ + +void vPortSVCHandler( void ) +{ + __asm volatile ( + " ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */ + " ldr r1, [r3] \n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ + " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ + " ldmia r0!, {r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ + " msr psp, r0 \n" /* Restore the task stack pointer. */ + " isb \n" + " mov r0, #0 \n" + " msr basepri, r0 \n" + " orr r14, #0xd \n" + " bx r14 \n" + " \n" + " .align 2 \n" + "pxCurrentTCBConst2: .word pxCurrentTCB \n" + ); +} +/*-----------------------------------------------------------*/ + +static void prvPortStartFirstTask( void ) +{ + __asm volatile( + " ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */ + " ldr r0, [r0] \n" + " ldr r0, [r0] \n" + " msr msp, r0 \n" /* Set the msp back to the start of the stack. */ + " cpsie i \n" /* Globally enable interrupts. */ + " cpsie f \n" + " dsb \n" + " isb \n" + " svc 0 \n" /* System call to start first task. */ + " nop \n" + ); +} +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +BaseType_t xPortStartScheduler( void ) +{ + /* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. + See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ + configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY ); + + #if( configASSERT_DEFINED == 1 ) + { + volatile uint32_t ulOriginalPriority; + volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); + volatile uint8_t ucMaxPriorityValue; + + /* Determine the maximum priority from which ISR safe FreeRTOS API + functions can be called. ISR safe functions are those that end in + "FromISR". FreeRTOS maintains separate thread and ISR API functions to + ensure interrupt entry is as fast and simple as possible. + + Save the interrupt priority value that is about to be clobbered. */ + ulOriginalPriority = *pucFirstUserPriorityRegister; + + /* Determine the number of priority bits available. First write to all + possible bits. */ + *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE; + + /* Read the value back to see how many bits stuck. */ + ucMaxPriorityValue = *pucFirstUserPriorityRegister; + + /* Use the same mask on the maximum system call priority. */ + ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; + + /* Calculate the maximum acceptable priority group value for the number + of bits read back. */ + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS; + while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) + { + ulMaxPRIGROUPValue--; + ucMaxPriorityValue <<= ( uint8_t ) 0x01; + } + + /* Shift the priority group value back to its position within the AIRCR + register. */ + ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; + ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; + + /* Restore the clobbered interrupt priority register to its original + value. */ + *pucFirstUserPriorityRegister = ulOriginalPriority; + } + #endif /* conifgASSERT_DEFINED */ + + /* Make PendSV and SysTick the lowest priority interrupts. */ + portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI; + portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI; + + /* Start the timer that generates the tick ISR. Interrupts are disabled + here already. */ + vPortSetupTimerInterrupt(); + + /* Initialise the critical nesting count ready for the first task. */ + uxCriticalNesting = 0; + + /* Start the first task. */ + prvPortStartFirstTask(); + + /* Should never get here as the tasks will now be executing! Call the task + exit error function to prevent compiler warnings about a static function + not being called in the case that the application writer overrides this + functionality by defining configTASK_RETURN_ADDRESS. */ + prvTaskExitError(); + + /* Should not get here! */ + return 0; +} +/*-----------------------------------------------------------*/ + +void vPortEndScheduler( void ) +{ + /* Not implemented in ports where there is nothing to return to. + Artificially force an assert. */ + configASSERT( uxCriticalNesting == 1000UL ); +} +/*-----------------------------------------------------------*/ + +void vPortYield( void ) +{ + /* Set a PendSV to request a context switch. */ + portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; + + /* Barriers are normally not required but do ensure the code is completely + within the specified behaviour for the architecture. */ + __asm volatile( "dsb" ); + __asm volatile( "isb" ); +} +/*-----------------------------------------------------------*/ + +void vPortEnterCritical( void ) +{ + portDISABLE_INTERRUPTS(); + uxCriticalNesting++; + __asm volatile( "dsb" ); + __asm volatile( "isb" ); + + /* This is not the interrupt safe version of the enter critical function so + assert() if it is being called from an interrupt context. Only API + functions that end in "FromISR" can be used in an interrupt. Only assert if + the critical nesting count is 1 to protect against recursive calls if the + assert function also uses a critical section. */ + if( uxCriticalNesting == 1 ) + { + configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 ); + } +} +/*-----------------------------------------------------------*/ + +void vPortExitCritical( void ) +{ + configASSERT( uxCriticalNesting ); + uxCriticalNesting--; + if( uxCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } +} +/*-----------------------------------------------------------*/ + +__attribute__(( naked )) uint32_t ulPortSetInterruptMask( void ) +{ + __asm volatile \ + ( \ + " mrs r0, basepri \n" \ + " mov r1, %0 \n" \ + " msr basepri, r1 \n" \ + " bx lr \n" \ + :: "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "r0", "r1" \ + ); + + /* This return will not be reached but is necessary to prevent compiler + warnings. */ + return 0; +} +/*-----------------------------------------------------------*/ + +__attribute__(( naked )) void vPortClearInterruptMask( uint32_t ulNewMaskValue ) +{ + __asm volatile \ + ( \ + " msr basepri, r0 \n" \ + " bx lr \n" \ + :::"r0" \ + ); + + /* Just to avoid compiler warnings. */ + ( void ) ulNewMaskValue; +} +/*-----------------------------------------------------------*/ + +void xPortPendSVHandler( void ) +{ + /* This is a naked function. */ + + __asm volatile + ( + " mrs r0, psp \n" + " isb \n" + " \n" + " ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */ + " ldr r2, [r3] \n" + " \n" + " stmdb r0!, {r4-r11} \n" /* Save the remaining registers. */ + " str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */ + " \n" + " stmdb sp!, {r3, r14} \n" + " mov r0, %0 \n" + " msr basepri, r0 \n" + " bl vTaskSwitchContext \n" + " mov r0, #0 \n" + " msr basepri, r0 \n" + " ldmia sp!, {r3, r14} \n" + " \n" /* Restore the context, including the critical nesting count. */ + " ldr r1, [r3] \n" + " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ + " ldmia r0!, {r4-r11} \n" /* Pop the registers. */ + " msr psp, r0 \n" + " isb \n" + " bx r14 \n" + " \n" + " .align 2 \n" + "pxCurrentTCBConst: .word pxCurrentTCB \n" + ::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY) + ); +} +/*-----------------------------------------------------------*/ + +void xPortSysTickHandler( void ) +{ + /* The SysTick runs at the lowest interrupt priority, so when this interrupt + executes all interrupts must be unmasked. There is therefore no need to + save and then restore the interrupt mask value as its value is already + known. */ + ( void ) portSET_INTERRUPT_MASK_FROM_ISR(); + { + /* Increment the RTOS tick. */ + if( xTaskIncrementTick() != pdFALSE ) + { + /* A context switch is required. Context switching is performed in + the PendSV interrupt. Pend the PendSV interrupt. */ + portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 ); +} +/*-----------------------------------------------------------*/ + +#if configUSE_TICKLESS_IDLE == 1 + + __attribute__((weak)) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) + { + uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL; + TickType_t xModifiableIdleTime; + + /* Make sure the SysTick reload value does not overflow the counter. */ + if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks ) + { + xExpectedIdleTime = xMaximumPossibleSuppressedTicks; + } + + /* Stop the SysTick momentarily. The time the SysTick is stopped for + is accounted for as best it can be, but using the tickless mode will + inevitably result in some tiny drift of the time maintained by the + kernel with respect to calendar time. */ + portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT; + + /* Calculate the reload value required to wait xExpectedIdleTime + tick periods. -1 is used because this code will execute part way + through one of the tick periods. */ + ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) ); + if( ulReloadValue > ulStoppedTimerCompensation ) + { + ulReloadValue -= ulStoppedTimerCompensation; + } + + /* Enter a critical section but don't use the taskENTER_CRITICAL() + method as that will mask interrupts that should exit sleep mode. */ + __asm volatile( "cpsid i" ); + + /* If a context switch is pending or a task is waiting for the scheduler + to be unsuspended then abandon the low power entry. */ + if( eTaskConfirmSleepModeStatus() == eAbortSleep ) + { + /* Restart from whatever is left in the count register to complete + this tick period. */ + portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG; + + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + + /* Reset the reload register to the value required for normal tick + periods. */ + portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + + /* Re-enable interrupts - see comments above the cpsid instruction() + above. */ + __asm volatile( "cpsie i" ); + } + else + { + /* Set the new reload value. */ + portNVIC_SYSTICK_LOAD_REG = ulReloadValue; + + /* Clear the SysTick count flag and set the count value back to + zero. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + + /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can + set its parameter to 0 to indicate that its implementation contains + its own wait for interrupt or wait for event instruction, and so wfi + should not be executed again. However, the original expected idle + time variable must remain unmodified, so a copy is taken. */ + xModifiableIdleTime = xExpectedIdleTime; + configPRE_SLEEP_PROCESSING( xModifiableIdleTime ); + if( xModifiableIdleTime > 0 ) + { + __asm volatile( "dsb" ); + __asm volatile( "wfi" ); + __asm volatile( "isb" ); + } + configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); + + /* Stop SysTick. Again, the time the SysTick is stopped for is + accounted for as best it can be, but using the tickless mode will + inevitably result in some tiny drift of the time maintained by the + kernel with respect to calendar time. */ + ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG; + portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT ); + + /* Re-enable interrupts - see comments above the cpsid instruction() + above. */ + __asm volatile( "cpsie i" ); + + if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + { + uint32_t ulCalculatedLoadValue; + + /* The tick interrupt has already executed, and the SysTick + count reloaded with ulReloadValue. Reset the + portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick + period. */ + ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG ); + + /* Don't allow a tiny value, or values that have somehow + underflowed because the post sleep hook did something + that took too long. */ + if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) ) + { + ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ); + } + + portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue; + + /* The tick interrupt handler will already have pended the tick + processing in the kernel. As the pending tick will be + processed as soon as this function exits, the tick value + maintained by the tick is stepped forward by one less than the + time spent waiting. */ + ulCompleteTickPeriods = xExpectedIdleTime - 1UL; + } + else + { + /* Something other than the tick interrupt ended the sleep. + Work out how long the sleep lasted rounded to complete tick + periods (not the ulReload value which accounted for part + ticks). */ + ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG; + + /* How many complete tick periods passed while the processor + was waiting? */ + ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick; + + /* The reload value is set to whatever fraction of a single tick + period remains. */ + portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; + } + + /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG + again, then set portNVIC_SYSTICK_LOAD_REG back to its standard + value. The critical section is used to ensure the tick interrupt + can only execute once in the case that the reload register is near + zero. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + portENTER_CRITICAL(); + { + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + vTaskStepTick( ulCompleteTickPeriods ); + portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + } + portEXIT_CRITICAL(); + } + } + +#endif /* #if configUSE_TICKLESS_IDLE */ +/*-----------------------------------------------------------*/ + +/* + * Setup the systick timer to generate the tick interrupts at the required + * frequency. + */ +__attribute__(( weak )) void vPortSetupTimerInterrupt( void ) +{ + /* Calculate the constants required to configure the tick interrupt. */ + #if configUSE_TICKLESS_IDLE == 1 + { + ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ); + xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick; + ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ ); + } + #endif /* configUSE_TICKLESS_IDLE */ + + /* Configure SysTick to interrupt at the requested rate. */ + portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; + portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT ); +} +/*-----------------------------------------------------------*/ + +#if( configASSERT_DEFINED == 1 ) + + void vPortValidateInterruptPriority( void ) + { + uint32_t ulCurrentInterrupt; + uint8_t ucCurrentPriority; + + /* Obtain the number of the currently executing interrupt. */ + __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) ); + + /* Is the interrupt number a user defined interrupt? */ + if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER ) + { + /* Look up the interrupt's priority. */ + ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; + + /* The following assertion will fail if a service routine (ISR) for + an interrupt that has been assigned a priority above + configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API + function. ISR safe FreeRTOS API functions must *only* be called + from interrupts that have been assigned a priority at or below + configMAX_SYSCALL_INTERRUPT_PRIORITY. + + Numerically low interrupt priority numbers represent logically high + interrupt priorities, therefore the priority of the interrupt must + be set to a value equal to or numerically *higher* than + configMAX_SYSCALL_INTERRUPT_PRIORITY. + + Interrupts that use the FreeRTOS API must not be left at their + default priority of zero as that is the highest possible priority, + which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, + and therefore also guaranteed to be invalid. + + FreeRTOS maintains separate thread and ISR API functions to ensure + interrupt entry is as fast and simple as possible. + + The following links provide detailed information: + http://www.freertos.org/RTOS-Cortex-M3-M4.html + http://www.freertos.org/FAQHelp.html */ + configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); + } + + /* Priority grouping: The interrupt controller (NVIC) allows the bits + that define each interrupt's priority to be split between bits that + define the interrupt's pre-emption priority bits and bits that define + the interrupt's sub-priority. For simplicity all bits must be defined + to be pre-emption priority bits. The following assertion will fail if + this is not the case (if some bits represent a sub-priority). + + If the application only uses CMSIS libraries for interrupt + configuration then the correct setting can be achieved on all Cortex-M + devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the + scheduler. Note however that some vendor specific peripheral libraries + assume a non-zero priority group setting, in which cases using a value + of zero will result in unpredicable behaviour. */ + configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); + } + +#endif /* configASSERT_DEFINED */ + + + + + + + + + + + + + + + + + + + + + diff --git a/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM3/portmacro.h b/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM3/portmacro.h new file mode 100644 index 0000000..8f51cfb --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM3/portmacro.h @@ -0,0 +1,195 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +#ifndef PORTMACRO_H +#define PORTMACRO_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*----------------------------------------------------------- + * Port specific definitions. + * + * The settings in this file configure FreeRTOS correctly for the + * given hardware and compiler. + * + * These settings should not be altered. + *----------------------------------------------------------- + */ + +/* Type definitions. */ +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#if( configUSE_16_BIT_TICKS == 1 ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff +#else + typedef uint32_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffffffffUL +#endif +/*-----------------------------------------------------------*/ + +/* Architecture specifics. */ +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +/*-----------------------------------------------------------*/ + + +/* Scheduler utilities. */ +extern void vPortYield( void ); +#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) ) +#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) +#define portYIELD() vPortYield() +#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT +#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) +/*-----------------------------------------------------------*/ + +/* Critical section management. */ +extern void vPortEnterCritical( void ); +extern void vPortExitCritical( void ); +extern uint32_t ulPortSetInterruptMask( void ); +extern void vPortClearInterruptMask( uint32_t ulNewMaskValue ); +#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x) +#define portDISABLE_INTERRUPTS() ulPortSetInterruptMask() +#define portENABLE_INTERRUPTS() vPortClearInterruptMask(0) +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() +/*-----------------------------------------------------------*/ + +/* Task function macros as described on the FreeRTOS.org WEB site. These are +not necessary for to use this port. They are defined so the common demo files +(which build with all the ports) will build. */ +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +/*-----------------------------------------------------------*/ + +/* Tickless idle/low power functionality. */ +#ifndef portSUPPRESS_TICKS_AND_SLEEP + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) +#endif +/*-----------------------------------------------------------*/ + +/* Architecture specific optimisations. */ +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 +#endif + +#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 + + /* Generic helper function. */ + __attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap ) + { + uint8_t ucReturn; + + __asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) ); + return ucReturn; + } + + /* Check the configuration. */ + #if( configMAX_PRIORITIES > 32 ) + #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice. + #endif + + /* Store/clear the ready priorities in a bit map. */ + #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) + #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) + + /*-----------------------------------------------------------*/ + + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - ucPortCountLeadingZeros( ( uxReadyPriorities ) ) ) + +#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ + +/*-----------------------------------------------------------*/ + +#ifdef configASSERT + void vPortValidateInterruptPriority( void ); + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() +#endif + +/* portNOP() is not required by this port. */ +#define portNOP() + +#ifdef __cplusplus +} +#endif + +#endif /* PORTMACRO_H */ + diff --git a/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM3_MPU/port.c b/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM3_MPU/port.c new file mode 100644 index 0000000..1e1aa88 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM3_MPU/port.c @@ -0,0 +1,1246 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/*----------------------------------------------------------- + * Implementation of functions defined in portable.h for the ARM CM3 port. + *----------------------------------------------------------*/ + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +/* Constants required to access and manipulate the NVIC. */ +#define portNVIC_SYSTICK_CTRL ( ( volatile uint32_t * ) 0xe000e010 ) +#define portNVIC_SYSTICK_LOAD ( ( volatile uint32_t * ) 0xe000e014 ) +#define portNVIC_SYSPRI2 ( ( volatile uint32_t * ) 0xe000ed20 ) +#define portNVIC_SYSPRI1 ( ( volatile uint32_t * ) 0xe000ed1c ) +#define portNVIC_SYS_CTRL_STATE ( ( volatile uint32_t * ) 0xe000ed24 ) +#define portNVIC_MEM_FAULT_ENABLE ( 1UL << 16UL ) + +/* Constants required to access and manipulate the MPU. */ +#define portMPU_TYPE ( ( volatile uint32_t * ) 0xe000ed90 ) +#define portMPU_REGION_BASE_ADDRESS ( ( volatile uint32_t * ) 0xe000ed9C ) +#define portMPU_REGION_ATTRIBUTE ( ( volatile uint32_t * ) 0xe000edA0 ) +#define portMPU_CTRL ( ( volatile uint32_t * ) 0xe000ed94 ) +#define portEXPECTED_MPU_TYPE_VALUE ( 8UL << 8UL ) /* 8 regions, unified. */ +#define portMPU_ENABLE ( 0x01UL ) +#define portMPU_BACKGROUND_ENABLE ( 1UL << 2UL ) +#define portPRIVILEGED_EXECUTION_START_ADDRESS ( 0UL ) +#define portMPU_REGION_VALID ( 0x10UL ) +#define portMPU_REGION_ENABLE ( 0x01UL ) +#define portPERIPHERALS_START_ADDRESS 0x40000000UL +#define portPERIPHERALS_END_ADDRESS 0x5FFFFFFFUL + +/* Constants required to access and manipulate the SysTick. */ +#define portNVIC_SYSTICK_CLK ( 0x00000004UL ) +#define portNVIC_SYSTICK_INT ( 0x00000002UL ) +#define portNVIC_SYSTICK_ENABLE ( 0x00000001UL ) +#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL ) +#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL ) +#define portNVIC_SVC_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL ) + +/* Constants required to set up the initial stack. */ +#define portINITIAL_XPSR ( 0x01000000 ) +#define portINITIAL_CONTROL_IF_UNPRIVILEGED ( 0x03 ) +#define portINITIAL_CONTROL_IF_PRIVILEGED ( 0x02 ) + +/* Offsets in the stack to the parameters when inside the SVC handler. */ +#define portOFFSET_TO_PC ( 6 ) + +/* Set the privilege level to user mode if xRunningPrivileged is false. */ +#define portRESET_PRIVILEGE( xRunningPrivileged ) if( xRunningPrivileged != pdTRUE ) __asm volatile ( " mrs r0, control \n orr r0, #1 \n msr control, r0" :::"r0" ) + +/* Each task maintains its own interrupt status in the critical nesting +variable. Note this is not saved as part of the task context as context +switches can only occur when uxCriticalNesting is zero. */ +static UBaseType_t uxCriticalNesting = 0xaaaaaaaa; + +/* + * Setup the timer to generate the tick interrupts. + */ +static void prvSetupTimerInterrupt( void ) PRIVILEGED_FUNCTION; + +/* + * Configure a number of standard MPU regions that are used by all tasks. + */ +static void prvSetupMPU( void ) PRIVILEGED_FUNCTION; + +/* + * Return the smallest MPU region size that a given number of bytes will fit + * into. The region size is returned as the value that should be programmed + * into the region attribute register for that region. + */ +static uint32_t prvGetMPURegionSizeSetting( uint32_t ulActualSizeInBytes ) PRIVILEGED_FUNCTION; + +/* + * Checks to see if being called from the context of an unprivileged task, and + * if so raises the privilege level and returns false - otherwise does nothing + * other than return true. + */ +static BaseType_t prvRaisePrivilege( void ) __attribute__(( naked )); + +/* + * Standard FreeRTOS exception handlers. + */ +void xPortPendSVHandler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; +void xPortSysTickHandler( void ) __attribute__ ((optimize("3"))) PRIVILEGED_FUNCTION; +void vPortSVCHandler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; + +/* + * Starts the scheduler by restoring the context of the first task to run. + */ +static void prvRestoreContextOfFirstTask( void ) __attribute__(( naked )) PRIVILEGED_FUNCTION; + +/* + * C portion of the SVC handler. The SVC handler is split between an asm entry + * and a C wrapper for simplicity of coding and maintenance. + */ +static void prvSVCHandler( uint32_t *pulRegisters ) __attribute__(( noinline )) PRIVILEGED_FUNCTION; + +/* + * Prototypes for all the MPU wrappers. + */ +BaseType_t MPU_xTaskGenericCreate( TaskFunction_t pvTaskCode, const char * const pcName, uint16_t usStackDepth, void *pvParameters, UBaseType_t uxPriority, TaskHandle_t *pxCreatedTask, StackType_t *puxStackBuffer, const MemoryRegion_t * const xRegions ); +void MPU_vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const xRegions ); +void MPU_vTaskDelete( TaskHandle_t pxTaskToDelete ); +void MPU_vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, TickType_t xTimeIncrement ); +void MPU_vTaskDelay( TickType_t xTicksToDelay ); +UBaseType_t MPU_uxTaskPriorityGet( TaskHandle_t pxTask ); +void MPU_vTaskPrioritySet( TaskHandle_t pxTask, UBaseType_t uxNewPriority ); +eTaskState MPU_eTaskGetState( TaskHandle_t pxTask ); +void MPU_vTaskSuspend( TaskHandle_t pxTaskToSuspend ); +void MPU_vTaskResume( TaskHandle_t pxTaskToResume ); +void MPU_vTaskSuspendAll( void ); +BaseType_t MPU_xTaskResumeAll( void ); +TickType_t MPU_xTaskGetTickCount( void ); +UBaseType_t MPU_uxTaskGetNumberOfTasks( void ); +void MPU_vTaskList( char *pcWriteBuffer ); +void MPU_vTaskGetRunTimeStats( char *pcWriteBuffer ); +void MPU_vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxTagValue ); +TaskHookFunction_t MPU_xTaskGetApplicationTaskTag( TaskHandle_t xTask ); +BaseType_t MPU_xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter ); +UBaseType_t MPU_uxTaskGetStackHighWaterMark( TaskHandle_t xTask ); +TaskHandle_t MPU_xTaskGetCurrentTaskHandle( void ); +BaseType_t MPU_xTaskGetSchedulerState( void ); +TaskHandle_t MPU_xTaskGetIdleTaskHandle( void ); +UBaseType_t MPU_uxTaskGetSystemState( TaskStatus_t *pxTaskStatusArray, UBaseType_t uxArraySize, uint32_t *pulTotalRunTime ); +QueueHandle_t MPU_xQueueGenericCreate( UBaseType_t uxQueueLength, UBaseType_t uxItemSize, uint8_t ucQueueType ); +BaseType_t MPU_xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, BaseType_t xCopyPosition ); +BaseType_t MPU_xQueueGenericReset( QueueHandle_t pxQueue, BaseType_t xNewQueue ); +UBaseType_t MPU_uxQueueMessagesWaiting( const QueueHandle_t pxQueue ); +BaseType_t MPU_xQueueGenericReceive( QueueHandle_t pxQueue, void * const pvBuffer, TickType_t xTicksToWait, BaseType_t xJustPeeking ); +QueueHandle_t MPU_xQueueCreateMutex( void ); +QueueHandle_t MPU_xQueueCreateCountingSemaphore( UBaseType_t uxCountValue, UBaseType_t uxInitialCount ); +BaseType_t MPU_xQueueTakeMutexRecursive( QueueHandle_t xMutex, TickType_t xBlockTime ); +BaseType_t MPU_xQueueGiveMutexRecursive( QueueHandle_t xMutex ); +BaseType_t MPU_xQueueAltGenericSend( QueueHandle_t pxQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, BaseType_t xCopyPosition ); +BaseType_t MPU_xQueueAltGenericReceive( QueueHandle_t pxQueue, void * const pvBuffer, TickType_t xTicksToWait, BaseType_t xJustPeeking ); +void MPU_vQueueAddToRegistry( QueueHandle_t xQueue, char *pcName ); +void MPU_vQueueDelete( QueueHandle_t xQueue ); +void *MPU_pvPortMalloc( size_t xSize ); +void MPU_vPortFree( void *pv ); +void MPU_vPortInitialiseBlocks( void ); +size_t MPU_xPortGetFreeHeapSize( void ); +QueueSetHandle_t MPU_xQueueCreateSet( UBaseType_t uxEventQueueLength ); +QueueSetMemberHandle_t MPU_xQueueSelectFromSet( QueueSetHandle_t xQueueSet, TickType_t xBlockTimeTicks ); +BaseType_t MPU_xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ); +BaseType_t MPU_xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ); +BaseType_t MPU_xQueuePeekFromISR( QueueHandle_t xQueue, void * const pvBuffer ); +void* MPU_xQueueGetMutexHolder( QueueHandle_t xSemaphore ); + +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged ) +{ + /* Simulate the stack frame as it would be created by a context switch + interrupt. */ + pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */ + *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) pxCode; /* PC */ + pxTopOfStack--; + *pxTopOfStack = 0; /* LR */ + pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ + *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ + pxTopOfStack -= 9; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ + + if( xRunPrivileged == pdTRUE ) + { + *pxTopOfStack = portINITIAL_CONTROL_IF_PRIVILEGED; + } + else + { + *pxTopOfStack = portINITIAL_CONTROL_IF_UNPRIVILEGED; + } + + return pxTopOfStack; +} +/*-----------------------------------------------------------*/ + +void vPortSVCHandler( void ) +{ + /* Assumes psp was in use. */ + __asm volatile + ( + #ifndef USE_PROCESS_STACK /* Code should not be required if a main() is using the process stack. */ + " tst lr, #4 \n" + " ite eq \n" + " mrseq r0, msp \n" + " mrsne r0, psp \n" + #else + " mrs r0, psp \n" + #endif + " b %0 \n" + ::"i"(prvSVCHandler):"r0" + ); +} +/*-----------------------------------------------------------*/ + +static void prvSVCHandler( uint32_t *pulParam ) +{ +uint8_t ucSVCNumber; + + /* The stack contains: r0, r1, r2, r3, r12, r14, the return address and + xPSR. The first argument (r0) is pulParam[ 0 ]. */ + ucSVCNumber = ( ( uint8_t * ) pulParam[ portOFFSET_TO_PC ] )[ -2 ]; + switch( ucSVCNumber ) + { + case portSVC_START_SCHEDULER : *(portNVIC_SYSPRI1) |= portNVIC_SVC_PRI; + prvRestoreContextOfFirstTask(); + break; + + case portSVC_YIELD : *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET; + /* Barriers are normally not required + but do ensure the code is completely + within the specified behaviour for the + architecture. */ + __asm volatile( "dsb" ); + __asm volatile( "isb" ); + + break; + + case portSVC_RAISE_PRIVILEGE : __asm volatile + ( + " mrs r1, control \n" /* Obtain current control value. */ + " bic r1, #1 \n" /* Set privilege bit. */ + " msr control, r1 \n" /* Write back new control value. */ + :::"r1" + ); + break; + + default : /* Unknown SVC call. */ + break; + } +} +/*-----------------------------------------------------------*/ + +static void prvRestoreContextOfFirstTask( void ) +{ + __asm volatile + ( + " ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */ + " ldr r0, [r0] \n" + " ldr r0, [r0] \n" + " msr msp, r0 \n" /* Set the msp back to the start of the stack. */ + " ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */ + " ldr r1, [r3] \n" + " ldr r0, [r1] \n" /* The first item in the TCB is the task top of stack. */ + " add r1, r1, #4 \n" /* Move onto the second item in the TCB... */ + " ldr r2, =0xe000ed9c \n" /* Region Base Address register. */ + " ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers. */ + " stmia r2!, {r4-r11} \n" /* Write 4 sets of MPU registers. */ + " ldmia r0!, {r3, r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry. */ + " msr control, r3 \n" + " msr psp, r0 \n" /* Restore the task stack pointer. */ + " mov r0, #0 \n" + " msr basepri, r0 \n" + " ldr r14, =0xfffffffd \n" /* Load exec return code. */ + " bx r14 \n" + " \n" + " .align 2 \n" + "pxCurrentTCBConst2: .word pxCurrentTCB \n" + ); +} +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +BaseType_t xPortStartScheduler( void ) +{ + /* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See + http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ + configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) ); + + /* Make PendSV and SysTick the same priority as the kernel. */ + *(portNVIC_SYSPRI2) |= portNVIC_PENDSV_PRI; + *(portNVIC_SYSPRI2) |= portNVIC_SYSTICK_PRI; + + /* Configure the regions in the MPU that are common to all tasks. */ + prvSetupMPU(); + + /* Start the timer that generates the tick ISR. Interrupts are disabled + here already. */ + prvSetupTimerInterrupt(); + + /* Initialise the critical nesting count ready for the first task. */ + uxCriticalNesting = 0; + + /* Start the first task. */ + __asm volatile( " svc %0 \n" + :: "i" (portSVC_START_SCHEDULER) ); + + /* Should not get here! */ + return 0; +} +/*-----------------------------------------------------------*/ + +void vPortEndScheduler( void ) +{ + /* Not implemented in ports where there is nothing to return to. + Artificially force an assert. */ + configASSERT( uxCriticalNesting == 1000UL ); +} +/*-----------------------------------------------------------*/ + +void vPortEnterCritical( void ) +{ +BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + portDISABLE_INTERRUPTS(); + uxCriticalNesting++; + + portRESET_PRIVILEGE( xRunningPrivileged ); +} +/*-----------------------------------------------------------*/ + +void vPortExitCritical( void ) +{ +BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + configASSERT( uxCriticalNesting ); + uxCriticalNesting--; + if( uxCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } + portRESET_PRIVILEGE( xRunningPrivileged ); +} +/*-----------------------------------------------------------*/ + +void xPortPendSVHandler( void ) +{ + /* This is a naked function. */ + + __asm volatile + ( + " mrs r0, psp \n" + " \n" + " ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */ + " ldr r2, [r3] \n" + " \n" + " mrs r1, control \n" + " stmdb r0!, {r1, r4-r11} \n" /* Save the remaining registers. */ + " str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */ + " \n" + " stmdb sp!, {r3, r14} \n" + " mov r0, %0 \n" + " msr basepri, r0 \n" + " bl vTaskSwitchContext \n" + " mov r0, #0 \n" + " msr basepri, r0 \n" + " ldmia sp!, {r3, r14} \n" + " \n" /* Restore the context. */ + " ldr r1, [r3] \n" + " ldr r0, [r1] \n" /* The first item in the TCB is the task top of stack. */ + " add r1, r1, #4 \n" /* Move onto the second item in the TCB... */ + " ldr r2, =0xe000ed9c \n" /* Region Base Address register. */ + " ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers. */ + " stmia r2!, {r4-r11} \n" /* Write 4 sets of MPU registers. */ + " ldmia r0!, {r3, r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry. */ + " msr control, r3 \n" + " \n" + " msr psp, r0 \n" + " bx r14 \n" + " \n" + " .align 2 \n" + "pxCurrentTCBConst: .word pxCurrentTCB \n" + ::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY) + ); +} +/*-----------------------------------------------------------*/ + +void xPortSysTickHandler( void ) +{ +uint32_t ulDummy; + + ulDummy = portSET_INTERRUPT_MASK_FROM_ISR(); + { + /* Increment the RTOS tick. */ + if( xTaskIncrementTick() != pdFALSE ) + { + /* Pend a context switch. */ + *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET; + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy ); +} +/*-----------------------------------------------------------*/ + +/* + * Setup the systick timer to generate the tick interrupts at the required + * frequency. + */ +static void prvSetupTimerInterrupt( void ) +{ + /* Configure SysTick to interrupt at the requested rate. */ + *(portNVIC_SYSTICK_LOAD) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; + *(portNVIC_SYSTICK_CTRL) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE; +} +/*-----------------------------------------------------------*/ + +static void prvSetupMPU( void ) +{ +extern uint32_t __privileged_functions_end__[]; +extern uint32_t __FLASH_segment_start__[]; +extern uint32_t __FLASH_segment_end__[]; +extern uint32_t __privileged_data_start__[]; +extern uint32_t __privileged_data_end__[]; + + /* Check the expected MPU is present. */ + if( *portMPU_TYPE == portEXPECTED_MPU_TYPE_VALUE ) + { + /* First setup the entire flash for unprivileged read only access. */ + *portMPU_REGION_BASE_ADDRESS = ( ( uint32_t ) __FLASH_segment_start__ ) | /* Base address. */ + ( portMPU_REGION_VALID ) | + ( portUNPRIVILEGED_FLASH_REGION ); + + *portMPU_REGION_ATTRIBUTE = ( portMPU_REGION_READ_ONLY ) | + ( portMPU_REGION_CACHEABLE_BUFFERABLE ) | + ( prvGetMPURegionSizeSetting( ( uint32_t ) __FLASH_segment_end__ - ( uint32_t ) __FLASH_segment_start__ ) ) | + ( portMPU_REGION_ENABLE ); + + /* Setup the first 16K for privileged only access (even though less + than 10K is actually being used). This is where the kernel code is + placed. */ + *portMPU_REGION_BASE_ADDRESS = ( ( uint32_t ) __FLASH_segment_start__ ) | /* Base address. */ + ( portMPU_REGION_VALID ) | + ( portPRIVILEGED_FLASH_REGION ); + + *portMPU_REGION_ATTRIBUTE = ( portMPU_REGION_PRIVILEGED_READ_ONLY ) | + ( portMPU_REGION_CACHEABLE_BUFFERABLE ) | + ( prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_functions_end__ - ( uint32_t ) __FLASH_segment_start__ ) ) | + ( portMPU_REGION_ENABLE ); + + /* Setup the privileged data RAM region. This is where the kernel data + is placed. */ + *portMPU_REGION_BASE_ADDRESS = ( ( uint32_t ) __privileged_data_start__ ) | /* Base address. */ + ( portMPU_REGION_VALID ) | + ( portPRIVILEGED_RAM_REGION ); + + *portMPU_REGION_ATTRIBUTE = ( portMPU_REGION_PRIVILEGED_READ_WRITE ) | + ( portMPU_REGION_CACHEABLE_BUFFERABLE ) | + prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_data_end__ - ( uint32_t ) __privileged_data_start__ ) | + ( portMPU_REGION_ENABLE ); + + /* By default allow everything to access the general peripherals. The + system peripherals and registers are protected. */ + *portMPU_REGION_BASE_ADDRESS = ( portPERIPHERALS_START_ADDRESS ) | + ( portMPU_REGION_VALID ) | + ( portGENERAL_PERIPHERALS_REGION ); + + *portMPU_REGION_ATTRIBUTE = ( portMPU_REGION_READ_WRITE | portMPU_REGION_EXECUTE_NEVER ) | + ( prvGetMPURegionSizeSetting( portPERIPHERALS_END_ADDRESS - portPERIPHERALS_START_ADDRESS ) ) | + ( portMPU_REGION_ENABLE ); + + /* Enable the memory fault exception. */ + *portNVIC_SYS_CTRL_STATE |= portNVIC_MEM_FAULT_ENABLE; + + /* Enable the MPU with the background region configured. */ + *portMPU_CTRL |= ( portMPU_ENABLE | portMPU_BACKGROUND_ENABLE ); + } +} +/*-----------------------------------------------------------*/ + +static uint32_t prvGetMPURegionSizeSetting( uint32_t ulActualSizeInBytes ) +{ +uint32_t ulRegionSize, ulReturnValue = 4; + + /* 32 is the smallest region size, 31 is the largest valid value for + ulReturnValue. */ + for( ulRegionSize = 32UL; ulReturnValue < 31UL; ( ulRegionSize <<= 1UL ) ) + { + if( ulActualSizeInBytes <= ulRegionSize ) + { + break; + } + else + { + ulReturnValue++; + } + } + + /* Shift the code by one before returning so it can be written directly + into the the correct bit position of the attribute register. */ + return ( ulReturnValue << 1UL ); +} +/*-----------------------------------------------------------*/ + +static BaseType_t prvRaisePrivilege( void ) +{ + __asm volatile + ( + " mrs r0, control \n" + " tst r0, #1 \n" /* Is the task running privileged? */ + " itte ne \n" + " movne r0, #0 \n" /* CONTROL[0]!=0, return false. */ + " svcne %0 \n" /* Switch to privileged. */ + " moveq r0, #1 \n" /* CONTROL[0]==0, return true. */ + " bx lr \n" + :: "i" (portSVC_RAISE_PRIVILEGE) : "r0" + ); + + return 0; +} +/*-----------------------------------------------------------*/ + +void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, StackType_t *pxBottomOfStack, uint16_t usStackDepth ) +{ +extern uint32_t __SRAM_segment_start__[]; +extern uint32_t __SRAM_segment_end__[]; +extern uint32_t __privileged_data_start__[]; +extern uint32_t __privileged_data_end__[]; +int32_t lIndex; +uint32_t ul; + + if( xRegions == NULL ) + { + /* No MPU regions are specified so allow access to all RAM. */ + xMPUSettings->xRegion[ 0 ].ulRegionBaseAddress = + ( ( uint32_t ) __SRAM_segment_start__ ) | /* Base address. */ + ( portMPU_REGION_VALID ) | + ( portSTACK_REGION ); + + xMPUSettings->xRegion[ 0 ].ulRegionAttribute = + ( portMPU_REGION_READ_WRITE ) | + ( portMPU_REGION_CACHEABLE_BUFFERABLE ) | + ( prvGetMPURegionSizeSetting( ( uint32_t ) __SRAM_segment_end__ - ( uint32_t ) __SRAM_segment_start__ ) ) | + ( portMPU_REGION_ENABLE ); + + /* Re-instate the privileged only RAM region as xRegion[ 0 ] will have + just removed the privileged only parameters. */ + xMPUSettings->xRegion[ 1 ].ulRegionBaseAddress = + ( ( uint32_t ) __privileged_data_start__ ) | /* Base address. */ + ( portMPU_REGION_VALID ) | + ( portSTACK_REGION + 1 ); + + xMPUSettings->xRegion[ 1 ].ulRegionAttribute = + ( portMPU_REGION_PRIVILEGED_READ_WRITE ) | + ( portMPU_REGION_CACHEABLE_BUFFERABLE ) | + prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_data_end__ - ( uint32_t ) __privileged_data_start__ ) | + ( portMPU_REGION_ENABLE ); + + /* Invalidate all other regions. */ + for( ul = 2; ul <= portNUM_CONFIGURABLE_REGIONS; ul++ ) + { + xMPUSettings->xRegion[ ul ].ulRegionBaseAddress = ( portSTACK_REGION + ul ) | portMPU_REGION_VALID; + xMPUSettings->xRegion[ ul ].ulRegionAttribute = 0UL; + } + } + else + { + /* This function is called automatically when the task is created - in + which case the stack region parameters will be valid. At all other + times the stack parameters will not be valid and it is assumed that the + stack region has already been configured. */ + if( usStackDepth > 0 ) + { + /* Define the region that allows access to the stack. */ + xMPUSettings->xRegion[ 0 ].ulRegionBaseAddress = + ( ( uint32_t ) pxBottomOfStack ) | + ( portMPU_REGION_VALID ) | + ( portSTACK_REGION ); /* Region number. */ + + xMPUSettings->xRegion[ 0 ].ulRegionAttribute = + ( portMPU_REGION_READ_WRITE ) | /* Read and write. */ + ( prvGetMPURegionSizeSetting( ( uint32_t ) usStackDepth * ( uint32_t ) sizeof( StackType_t ) ) ) | + ( portMPU_REGION_CACHEABLE_BUFFERABLE ) | + ( portMPU_REGION_ENABLE ); + } + + lIndex = 0; + + for( ul = 1; ul <= portNUM_CONFIGURABLE_REGIONS; ul++ ) + { + if( ( xRegions[ lIndex ] ).ulLengthInBytes > 0UL ) + { + /* Translate the generic region definition contained in + xRegions into the CM3 specific MPU settings that are then + stored in xMPUSettings. */ + xMPUSettings->xRegion[ ul ].ulRegionBaseAddress = + ( ( uint32_t ) xRegions[ lIndex ].pvBaseAddress ) | + ( portMPU_REGION_VALID ) | + ( portSTACK_REGION + ul ); /* Region number. */ + + xMPUSettings->xRegion[ ul ].ulRegionAttribute = + ( prvGetMPURegionSizeSetting( xRegions[ lIndex ].ulLengthInBytes ) ) | + ( xRegions[ lIndex ].ulParameters ) | + ( portMPU_REGION_ENABLE ); + } + else + { + /* Invalidate the region. */ + xMPUSettings->xRegion[ ul ].ulRegionBaseAddress = ( portSTACK_REGION + ul ) | portMPU_REGION_VALID; + xMPUSettings->xRegion[ ul ].ulRegionAttribute = 0UL; + } + + lIndex++; + } + } +} +/*-----------------------------------------------------------*/ + +BaseType_t MPU_xTaskGenericCreate( TaskFunction_t pvTaskCode, const char * const pcName, uint16_t usStackDepth, void *pvParameters, UBaseType_t uxPriority, TaskHandle_t *pxCreatedTask, StackType_t *puxStackBuffer, const MemoryRegion_t * const xRegions ) +{ +BaseType_t xReturn; +BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xTaskGenericCreate( pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask, puxStackBuffer, xRegions ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; +} +/*-----------------------------------------------------------*/ + +void MPU_vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const xRegions ) +{ +BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + vTaskAllocateMPURegions( xTask, xRegions ); + portRESET_PRIVILEGE( xRunningPrivileged ); +} +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskDelete == 1 ) + void MPU_vTaskDelete( TaskHandle_t pxTaskToDelete ) + { + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + vTaskDelete( pxTaskToDelete ); + portRESET_PRIVILEGE( xRunningPrivileged ); + } +#endif +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskDelayUntil == 1 ) + void MPU_vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, TickType_t xTimeIncrement ) + { + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + vTaskDelayUntil( pxPreviousWakeTime, xTimeIncrement ); + portRESET_PRIVILEGE( xRunningPrivileged ); + } +#endif +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskDelay == 1 ) + void MPU_vTaskDelay( TickType_t xTicksToDelay ) + { + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + vTaskDelay( xTicksToDelay ); + portRESET_PRIVILEGE( xRunningPrivileged ); + } +#endif +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_uxTaskPriorityGet == 1 ) + UBaseType_t MPU_uxTaskPriorityGet( TaskHandle_t pxTask ) + { + UBaseType_t uxReturn; + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + uxReturn = uxTaskPriorityGet( pxTask ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return uxReturn; + } +#endif +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskPrioritySet == 1 ) + void MPU_vTaskPrioritySet( TaskHandle_t pxTask, UBaseType_t uxNewPriority ) + { + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + vTaskPrioritySet( pxTask, uxNewPriority ); + portRESET_PRIVILEGE( xRunningPrivileged ); + } +#endif +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_eTaskGetState == 1 ) + eTaskState MPU_eTaskGetState( TaskHandle_t pxTask ) + { + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + eTaskState eReturn; + + eReturn = eTaskGetState( pxTask ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return eReturn; + } +#endif +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) + TaskHandle_t MPU_xTaskGetIdleTaskHandle( void ) + { + TaskHandle_t xReturn; + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xTaskGetIdleTaskHandle(); + portRESET_PRIVILEGE( xRunningPrivileged ); + return eReturn; + } +#endif +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskSuspend == 1 ) + void MPU_vTaskSuspend( TaskHandle_t pxTaskToSuspend ) + { + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + vTaskSuspend( pxTaskToSuspend ); + portRESET_PRIVILEGE( xRunningPrivileged ); + } +#endif +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskSuspend == 1 ) + void MPU_vTaskResume( TaskHandle_t pxTaskToResume ) + { + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + vTaskResume( pxTaskToResume ); + portRESET_PRIVILEGE( xRunningPrivileged ); + } +#endif +/*-----------------------------------------------------------*/ + +void MPU_vTaskSuspendAll( void ) +{ +BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + vTaskSuspendAll(); + portRESET_PRIVILEGE( xRunningPrivileged ); +} +/*-----------------------------------------------------------*/ + +BaseType_t MPU_xTaskResumeAll( void ) +{ +BaseType_t xReturn; +BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xTaskResumeAll(); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; +} +/*-----------------------------------------------------------*/ + +TickType_t MPU_xTaskGetTickCount( void ) +{ +TickType_t xReturn; +BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xTaskGetTickCount(); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; +} +/*-----------------------------------------------------------*/ + +UBaseType_t MPU_uxTaskGetNumberOfTasks( void ) +{ +UBaseType_t uxReturn; +BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + uxReturn = uxTaskGetNumberOfTasks(); + portRESET_PRIVILEGE( xRunningPrivileged ); + return uxReturn; +} +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + void MPU_vTaskList( char *pcWriteBuffer ) + { + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + vTaskList( pcWriteBuffer ); + portRESET_PRIVILEGE( xRunningPrivileged ); + } +#endif +/*-----------------------------------------------------------*/ + +#if ( configGENERATE_RUN_TIME_STATS == 1 ) + void MPU_vTaskGetRunTimeStats( char *pcWriteBuffer ) + { + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + vTaskGetRunTimeStats( pcWriteBuffer ); + portRESET_PRIVILEGE( xRunningPrivileged ); + } +#endif +/*-----------------------------------------------------------*/ + +#if ( configUSE_APPLICATION_TASK_TAG == 1 ) + void MPU_vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxTagValue ) + { + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + vTaskSetApplicationTaskTag( xTask, pxTagValue ); + portRESET_PRIVILEGE( xRunningPrivileged ); + } +#endif +/*-----------------------------------------------------------*/ + +#if ( configUSE_APPLICATION_TASK_TAG == 1 ) + TaskHookFunction_t MPU_xTaskGetApplicationTaskTag( TaskHandle_t xTask ) + { + TaskHookFunction_t xReturn; + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xTaskGetApplicationTaskTag( xTask ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; + } +#endif +/*-----------------------------------------------------------*/ + +#if ( configUSE_APPLICATION_TASK_TAG == 1 ) + BaseType_t MPU_xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter ) + { + BaseType_t xReturn; + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xTaskCallApplicationTaskHook( xTask, pvParameter ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; + } +#endif +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t MPU_uxTaskGetSystemState( TaskStatus_t *pxTaskStatusArray, UBaseType_t uxArraySize, uint32_t *pulTotalRunTime ) + { + UBaseType_t uxReturn; + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + uxReturn = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, pulTotalRunTime ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; + } +#endif +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) + UBaseType_t MPU_uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) + { + UBaseType_t uxReturn; + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + uxReturn = uxTaskGetStackHighWaterMark( xTask ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return uxReturn; + } +#endif +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) + TaskHandle_t MPU_xTaskGetCurrentTaskHandle( void ) + { + TaskHandle_t xReturn; + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xTaskGetCurrentTaskHandle(); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; + } +#endif +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_xTaskGetSchedulerState == 1 ) + BaseType_t MPU_xTaskGetSchedulerState( void ) + { + BaseType_t xReturn; + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xTaskGetSchedulerState(); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; + } +#endif +/*-----------------------------------------------------------*/ + +QueueHandle_t MPU_xQueueGenericCreate( UBaseType_t uxQueueLength, UBaseType_t uxItemSize, uint8_t ucQueueType ) +{ +QueueHandle_t xReturn; +BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xQueueGenericCreate( uxQueueLength, uxItemSize, ucQueueType ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; +} +/*-----------------------------------------------------------*/ + +BaseType_t MPU_xQueueGenericReset( QueueHandle_t pxQueue, BaseType_t xNewQueue ) +{ +BaseType_t xReturn; +BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xQueueGenericReset( pxQueue, xNewQueue ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; +} +/*-----------------------------------------------------------*/ + +BaseType_t MPU_xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, BaseType_t xCopyPosition ) +{ +BaseType_t xReturn; +BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xQueueGenericSend( xQueue, pvItemToQueue, xTicksToWait, xCopyPosition ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; +} +/*-----------------------------------------------------------*/ + +UBaseType_t MPU_uxQueueMessagesWaiting( const QueueHandle_t pxQueue ) +{ +BaseType_t xRunningPrivileged = prvRaisePrivilege(); +UBaseType_t uxReturn; + + uxReturn = uxQueueMessagesWaiting( pxQueue ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return uxReturn; +} +/*-----------------------------------------------------------*/ + +BaseType_t MPU_xQueueGenericReceive( QueueHandle_t pxQueue, void * const pvBuffer, TickType_t xTicksToWait, BaseType_t xJustPeeking ) +{ +BaseType_t xRunningPrivileged = prvRaisePrivilege(); +BaseType_t xReturn; + + xReturn = xQueueGenericReceive( pxQueue, pvBuffer, xTicksToWait, xJustPeeking ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; +} +/*-----------------------------------------------------------*/ + +BaseType_t MPU_xQueuePeekFromISR( QueueHandle_t pxQueue, void * const pvBuffer ) +{ +BaseType_t xRunningPrivileged = prvRaisePrivilege(); +BaseType_t xReturn; + + xReturn = xQueuePeekFromISR( pxQueue, pvBuffer ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; +} +/*-----------------------------------------------------------*/ + +void* MPU_xQueueGetMutexHolder( QueueHandle_t xSemaphore ) +{ +BaseType_t xRunningPrivileged = prvRaisePrivilege(); +void * xReturn; + + xReturn = ( void * ) xQueueGetMutexHolder( xSemaphore ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; +} +/*-----------------------------------------------------------*/ + +#if ( configUSE_MUTEXES == 1 ) + QueueHandle_t MPU_xQueueCreateMutex( void ) + { + QueueHandle_t xReturn; + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xQueueCreateMutex( queueQUEUE_TYPE_MUTEX ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; + } +#endif +/*-----------------------------------------------------------*/ + +#if configUSE_COUNTING_SEMAPHORES == 1 + QueueHandle_t MPU_xQueueCreateCountingSemaphore( UBaseType_t uxCountValue, UBaseType_t uxInitialCount ) + { + QueueHandle_t xReturn; + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xQueueCreateCountingSemaphore( uxCountValue, uxInitialCount ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; + } +#endif +/*-----------------------------------------------------------*/ + +#if ( configUSE_MUTEXES == 1 ) + BaseType_t MPU_xQueueTakeMutexRecursive( QueueHandle_t xMutex, TickType_t xBlockTime ) + { + BaseType_t xReturn; + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xQueueTakeMutexRecursive( xMutex, xBlockTime ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; + } +#endif +/*-----------------------------------------------------------*/ + +#if ( configUSE_MUTEXES == 1 ) + BaseType_t MPU_xQueueGiveMutexRecursive( QueueHandle_t xMutex ) + { + BaseType_t xReturn; + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xQueueGiveMutexRecursive( xMutex ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; + } +#endif +/*-----------------------------------------------------------*/ + +#if ( configUSE_QUEUE_SETS == 1 ) + QueueSetHandle_t MPU_xQueueCreateSet( UBaseType_t uxEventQueueLength ) + { + QueueSetHandle_t xReturn; + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xQueueCreateSet( uxEventQueueLength ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; + } +#endif +/*-----------------------------------------------------------*/ + +#if ( configUSE_QUEUE_SETS == 1 ) + QueueSetMemberHandle_t MPU_xQueueSelectFromSet( QueueSetHandle_t xQueueSet, TickType_t xBlockTimeTicks ) + { + QueueSetMemberHandle_t xReturn; + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xQueueSelectFromSet( xQueueSet, xBlockTimeTicks ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; + } +#endif +/*-----------------------------------------------------------*/ + +#if ( configUSE_QUEUE_SETS == 1 ) + BaseType_t MPU_xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ) + { + BaseType_t xReturn; + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xQueueAddToSet( xQueueOrSemaphore, xQueueSet ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; + } +#endif +/*-----------------------------------------------------------*/ + +#if ( configUSE_QUEUE_SETS == 1 ) + BaseType_t MPU_xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ) + { + BaseType_t xReturn; + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xQueueRemoveFromSet( xQueueOrSemaphore, xQueueSet ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; + } +#endif +/*-----------------------------------------------------------*/ + +#if configUSE_ALTERNATIVE_API == 1 + BaseType_t MPU_xQueueAltGenericSend( QueueHandle_t pxQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, BaseType_t xCopyPosition ) + { + BaseType_t xReturn; + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = BaseType_t xQueueAltGenericSend( pxQueue, pvItemToQueue, xTicksToWait, xCopyPosition ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; + } +#endif +/*-----------------------------------------------------------*/ + +#if configUSE_ALTERNATIVE_API == 1 + BaseType_t MPU_xQueueAltGenericReceive( QueueHandle_t pxQueue, void * const pvBuffer, TickType_t xTicksToWait, BaseType_t xJustPeeking ) + { + BaseType_t xReturn; + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xQueueAltGenericReceive( pxQueue, pvBuffer, xTicksToWait, xJustPeeking ); + portRESET_PRIVILEGE( xRunningPrivileged ); + return xReturn; + } +#endif +/*-----------------------------------------------------------*/ + +#if configQUEUE_REGISTRY_SIZE > 0 + void MPU_vQueueAddToRegistry( QueueHandle_t xQueue, char *pcName ) + { + BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + vQueueAddToRegistry( xQueue, pcName ); + + portRESET_PRIVILEGE( xRunningPrivileged ); + } +#endif +/*-----------------------------------------------------------*/ + +void MPU_vQueueDelete( QueueHandle_t xQueue ) +{ +BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + vQueueDelete( xQueue ); + + portRESET_PRIVILEGE( xRunningPrivileged ); +} +/*-----------------------------------------------------------*/ + +void *MPU_pvPortMalloc( size_t xSize ) +{ +void *pvReturn; +BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + pvReturn = pvPortMalloc( xSize ); + + portRESET_PRIVILEGE( xRunningPrivileged ); + + return pvReturn; +} +/*-----------------------------------------------------------*/ + +void MPU_vPortFree( void *pv ) +{ +BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + vPortFree( pv ); + + portRESET_PRIVILEGE( xRunningPrivileged ); +} +/*-----------------------------------------------------------*/ + +void MPU_vPortInitialiseBlocks( void ) +{ +BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + vPortInitialiseBlocks(); + + portRESET_PRIVILEGE( xRunningPrivileged ); +} +/*-----------------------------------------------------------*/ + +size_t MPU_xPortGetFreeHeapSize( void ) +{ +size_t xReturn; +BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + xReturn = xPortGetFreeHeapSize(); + + portRESET_PRIVILEGE( xRunningPrivileged ); + + return xReturn; +} + +/* Functions that the application writer wants to execute in privileged mode +can be defined in application_defined_privileged_functions.h. The functions +must take the same format as those above whereby the privilege state on exit +equals the privilege state on entry. For example: + +void MPU_FunctionName( [parameters ] ) +{ +BaseType_t xRunningPrivileged = prvRaisePrivilege(); + + FunctionName( [parameters ] ); + + portRESET_PRIVILEGE( xRunningPrivileged ); +} +*/ + +#if configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS == 1 + #include "application_defined_privileged_functions.h" +#endif + diff --git a/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM3_MPU/portmacro.h b/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM3_MPU/portmacro.h new file mode 100644 index 0000000..ee06be9 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM3_MPU/portmacro.h @@ -0,0 +1,218 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +#ifndef PORTMACRO_H +#define PORTMACRO_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*----------------------------------------------------------- + * Port specific definitions. + * + * The settings in this file configure FreeRTOS correctly for the + * given hardware and compiler. + * + * These settings should not be altered. + *----------------------------------------------------------- + */ + +/* Type definitions. */ +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#if( configUSE_16_BIT_TICKS == 1 ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff +#else + typedef uint32_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffffffffUL +#endif +/*-----------------------------------------------------------*/ + +/* MPU specific constants. */ +#define portUSING_MPU_WRAPPERS 1 +#define portPRIVILEGE_BIT ( 0x80000000UL ) + +#define portMPU_REGION_READ_WRITE ( 0x03UL << 24UL ) +#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 0x05UL << 24UL ) +#define portMPU_REGION_READ_ONLY ( 0x06UL << 24UL ) +#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0x01UL << 24UL ) +#define portMPU_REGION_CACHEABLE_BUFFERABLE ( 0x07UL << 16UL ) +#define portMPU_REGION_EXECUTE_NEVER ( 0x01UL << 28UL ) + +#define portUNPRIVILEGED_FLASH_REGION ( 0UL ) +#define portPRIVILEGED_FLASH_REGION ( 1UL ) +#define portPRIVILEGED_RAM_REGION ( 2UL ) +#define portGENERAL_PERIPHERALS_REGION ( 3UL ) +#define portSTACK_REGION ( 4UL ) +#define portFIRST_CONFIGURABLE_REGION ( 5UL ) +#define portLAST_CONFIGURABLE_REGION ( 7UL ) +#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) +#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ + +#define portSWITCH_TO_USER_MODE() __asm volatile ( " mrs r0, control \n orr r0, #1 \n msr control, r0 " :::"r0" ) + +typedef struct MPU_REGION_REGISTERS +{ + uint32_t ulRegionBaseAddress; + uint32_t ulRegionAttribute; +} xMPU_REGION_REGISTERS; + +/* Plus 1 to create space for the stack region. */ +typedef struct MPU_SETTINGS +{ + xMPU_REGION_REGISTERS xRegion[ portTOTAL_NUM_REGIONS ]; +} xMPU_SETTINGS; + +/* Architecture specifics. */ +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +/*-----------------------------------------------------------*/ + +/* SVC numbers for various services. */ +#define portSVC_START_SCHEDULER 0 +#define portSVC_YIELD 1 +#define portSVC_RAISE_PRIVILEGE 2 + +/* Scheduler utilities. */ + +#define portYIELD() __asm volatile ( " SVC %0 \n" :: "i" (portSVC_YIELD) ) +#define portYIELD_WITHIN_API() *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET + +#define portNVIC_INT_CTRL ( ( volatile uint32_t *) 0xe000ed04 ) +#define portNVIC_PENDSVSET 0x10000000 +#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET +#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) +/*-----------------------------------------------------------*/ + + +/* Critical section management. */ + +/* + * Set basepri to portMAX_SYSCALL_INTERRUPT_PRIORITY without effecting other + * registers. r0 is clobbered. + */ +#define portSET_INTERRUPT_MASK() \ + __asm volatile \ + ( \ + " mov r0, %0 \n" \ + " msr basepri, r0 \n" \ + ::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY):"r0" \ + ) + +/* + * Set basepri back to 0 without effective other registers. + * r0 is clobbered. FAQ: Setting BASEPRI to 0 is not a bug. Please see + * http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html before disagreeing. + */ +#define portCLEAR_INTERRUPT_MASK() \ + __asm volatile \ + ( \ + " mov r0, #0 \n" \ + " msr basepri, r0 \n" \ + :::"r0" \ + ) + +/* FAQ: Setting BASEPRI to 0 is not a bug. Please see +http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html before disagreeing. */ +#define portSET_INTERRUPT_MASK_FROM_ISR() 0;portSET_INTERRUPT_MASK() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) portCLEAR_INTERRUPT_MASK();(void)x + + +extern void vPortEnterCritical( void ); +extern void vPortExitCritical( void ); + +#define portDISABLE_INTERRUPTS() portSET_INTERRUPT_MASK() +#define portENABLE_INTERRUPTS() portCLEAR_INTERRUPT_MASK() +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() +/*-----------------------------------------------------------*/ + +/* Task function macros as described on the FreeRTOS.org WEB site. */ +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) + +#define portNOP() + + +#ifdef __cplusplus +} +#endif + +#endif /* PORTMACRO_H */ + diff --git a/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM4F/port.c b/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM4F/port.c new file mode 100644 index 0000000..90f07d2 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM4F/port.c @@ -0,0 +1,784 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/*----------------------------------------------------------- + * Implementation of functions defined in portable.h for the ARM CM4F port. + *----------------------------------------------------------*/ + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "task.h" + +#ifndef __VFP_FP__ + #error This port can only be used when the project options are configured to enable hardware floating point support. +#endif + +#ifndef configSYSTICK_CLOCK_HZ + #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ + /* Ensure the SysTick is clocked at the same frequency as the core. */ + #define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) +#else + /* The way the SysTick is clocked is not modified in case it is not the same + as the core. */ + #define portNVIC_SYSTICK_CLK_BIT ( 0 ) +#endif + +/* Constants required to manipulate the core. Registers first... */ +#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) ) +#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) ) +#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) ) +#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) ) +/* ...then bits in the registers. */ +#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL ) +#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL ) +#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL ) +#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL ) +#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL ) + +#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL ) +#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL ) + +/* Constants required to check the validity of an interrupt priority. */ +#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) +#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) +#define portAIRCR_REG ( * ( ( volatile uint32_t * ) 0xE000ED0C ) ) +#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff ) +#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 ) +#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 ) +#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) +#define portPRIGROUP_SHIFT ( 8UL ) + +/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */ +#define portVECTACTIVE_MASK ( 0x1FUL ) + +/* Constants required to manipulate the VFP. */ +#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating point context control register. */ +#define portASPEN_AND_LSPEN_BITS ( 0x3UL << 30UL ) + +/* Constants required to set up the initial stack. */ +#define portINITIAL_XPSR ( 0x01000000 ) +#define portINITIAL_EXEC_RETURN ( 0xfffffffd ) + +/* The systick is a 24-bit counter. */ +#define portMAX_24_BIT_NUMBER ( 0xffffffUL ) + +/* A fiddle factor to estimate the number of SysTick counts that would have +occurred while the SysTick counter is stopped during tickless idle +calculations. */ +#define portMISSED_COUNTS_FACTOR ( 45UL ) + +/* Let the user override the pre-loading of the initial LR with the address of +prvTaskExitError() in case is messes up unwinding of the stack in the +debugger. */ +#ifdef configTASK_RETURN_ADDRESS + #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS +#else + #define portTASK_RETURN_ADDRESS prvTaskExitError +#endif + +/* Each task maintains its own interrupt status in the critical nesting +variable. */ +static UBaseType_t uxCriticalNesting = 0xaaaaaaaa; + +/* + * Setup the timer to generate the tick interrupts. The implementation in this + * file is weak to allow application writers to change the timer used to + * generate the tick interrupt. + */ +void vPortSetupTimerInterrupt( void ); + +/* + * Exception handlers. + */ +void xPortPendSVHandler( void ) __attribute__ (( naked )); +void xPortSysTickHandler( void ); +void vPortSVCHandler( void ) __attribute__ (( naked )); + +/* + * Start first task is a separate function so it can be tested in isolation. + */ +static void prvPortStartFirstTask( void ) __attribute__ (( naked )); + +/* + * Function to enable the VFP. + */ + static void vPortEnableVFP( void ) __attribute__ (( naked )); + +/* + * Used to catch tasks that attempt to return from their implementing function. + */ +static void prvTaskExitError( void ); + +/*-----------------------------------------------------------*/ + +/* + * The number of SysTick increments that make up one tick period. + */ +#if configUSE_TICKLESS_IDLE == 1 + static uint32_t ulTimerCountsForOneTick = 0; +#endif /* configUSE_TICKLESS_IDLE */ + +/* + * The maximum number of tick periods that can be suppressed is limited by the + * 24 bit resolution of the SysTick timer. + */ +#if configUSE_TICKLESS_IDLE == 1 + static uint32_t xMaximumPossibleSuppressedTicks = 0; +#endif /* configUSE_TICKLESS_IDLE */ + +/* + * Compensate for the CPU cycles that pass while the SysTick is stopped (low + * power functionality only. + */ +#if configUSE_TICKLESS_IDLE == 1 + static uint32_t ulStoppedTimerCompensation = 0; +#endif /* configUSE_TICKLESS_IDLE */ + +/* + * Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure + * FreeRTOS API functions are not called from interrupts that have been assigned + * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY. + */ +#if ( configASSERT_DEFINED == 1 ) + static uint8_t ucMaxSysCallPriority = 0; + static uint32_t ulMaxPRIGROUPValue = 0; + static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * const ) portNVIC_IP_REGISTERS_OFFSET_16; +#endif /* configASSERT_DEFINED */ + +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) +{ + /* Simulate the stack frame as it would be created by a context switch + interrupt. */ + + /* Offset added to account for the way the MCU uses the stack on entry/exit + of interrupts, and to ensure alignment. */ + pxTopOfStack--; + + *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) pxCode; /* PC */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */ + + /* Save code space by skipping register initialisation. */ + pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ + *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ + + /* A save method is being used that requires each task to maintain its + own exec return value. */ + pxTopOfStack--; + *pxTopOfStack = portINITIAL_EXEC_RETURN; + + pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ + + return pxTopOfStack; +} +/*-----------------------------------------------------------*/ + +static void prvTaskExitError( void ) +{ + /* A function that implements a task must not exit or attempt to return to + its caller as there is nothing to return to. If a task wants to exit it + should instead call vTaskDelete( NULL ). + + Artificially force an assert() to be triggered if configASSERT() is + defined, then stop here so application writers can catch the error. */ + configASSERT( uxCriticalNesting == ~0UL ); + portDISABLE_INTERRUPTS(); + for( ;; ); +} +/*-----------------------------------------------------------*/ + +void vPortSVCHandler( void ) +{ + __asm volatile ( + " ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */ + " ldr r1, [r3] \n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ + " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ + " ldmia r0!, {r4-r11, r14} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ + " msr psp, r0 \n" /* Restore the task stack pointer. */ + " isb \n" + " mov r0, #0 \n" + " msr basepri, r0 \n" + " bx r14 \n" + " \n" + " .align 2 \n" + "pxCurrentTCBConst2: .word pxCurrentTCB \n" + ); +} +/*-----------------------------------------------------------*/ + +static void prvPortStartFirstTask( void ) +{ + __asm volatile( + " ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */ + " ldr r0, [r0] \n" + " ldr r0, [r0] \n" + " msr msp, r0 \n" /* Set the msp back to the start of the stack. */ + " cpsie i \n" /* Globally enable interrupts. */ + " cpsie f \n" + " dsb \n" + " isb \n" + " svc 0 \n" /* System call to start first task. */ + " nop \n" + ); +} +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +BaseType_t xPortStartScheduler( void ) +{ + /* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. + See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ + configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY ); + + #if( configASSERT_DEFINED == 1 ) + { + volatile uint32_t ulOriginalPriority; + volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); + volatile uint8_t ucMaxPriorityValue; + + /* Determine the maximum priority from which ISR safe FreeRTOS API + functions can be called. ISR safe functions are those that end in + "FromISR". FreeRTOS maintains separate thread and ISR API functions to + ensure interrupt entry is as fast and simple as possible. + + Save the interrupt priority value that is about to be clobbered. */ + ulOriginalPriority = *pucFirstUserPriorityRegister; + + /* Determine the number of priority bits available. First write to all + possible bits. */ + *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE; + + /* Read the value back to see how many bits stuck. */ + ucMaxPriorityValue = *pucFirstUserPriorityRegister; + + /* Use the same mask on the maximum system call priority. */ + ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; + + /* Calculate the maximum acceptable priority group value for the number + of bits read back. */ + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS; + while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) + { + ulMaxPRIGROUPValue--; + ucMaxPriorityValue <<= ( uint8_t ) 0x01; + } + + /* Shift the priority group value back to its position within the AIRCR + register. */ + ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; + ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; + + /* Restore the clobbered interrupt priority register to its original + value. */ + *pucFirstUserPriorityRegister = ulOriginalPriority; + } + #endif /* conifgASSERT_DEFINED */ + + /* Make PendSV and SysTick the lowest priority interrupts. */ + portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI; + portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI; + + /* Start the timer that generates the tick ISR. Interrupts are disabled + here already. */ + vPortSetupTimerInterrupt(); + + /* Initialise the critical nesting count ready for the first task. */ + uxCriticalNesting = 0; + + /* Ensure the VFP is enabled - it should be anyway. */ + vPortEnableVFP(); + + /* Lazy save always. */ + *( portFPCCR ) |= portASPEN_AND_LSPEN_BITS; + + /* Start the first task. */ + prvPortStartFirstTask(); + + /* Should never get here as the tasks will now be executing! Call the task + exit error function to prevent compiler warnings about a static function + not being called in the case that the application writer overrides this + functionality by defining configTASK_RETURN_ADDRESS. */ + prvTaskExitError(); + + /* Should not get here! */ + return 0; +} +/*-----------------------------------------------------------*/ + +void vPortEndScheduler( void ) +{ + /* Not implemented in ports where there is nothing to return to. + Artificially force an assert. */ + configASSERT( uxCriticalNesting == 1000UL ); +} +/*-----------------------------------------------------------*/ + +void vPortYield( void ) +{ + /* Set a PendSV to request a context switch. */ + portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; + + /* Barriers are normally not required but do ensure the code is completely + within the specified behaviour for the architecture. */ + __asm volatile( "dsb" ); + __asm volatile( "isb" ); +} +/*-----------------------------------------------------------*/ + +void vPortEnterCritical( void ) +{ + portDISABLE_INTERRUPTS(); + uxCriticalNesting++; + __asm volatile( "dsb" ); + __asm volatile( "isb" ); + + /* This is not the interrupt safe version of the enter critical function so + assert() if it is being called from an interrupt context. Only API + functions that end in "FromISR" can be used in an interrupt. Only assert if + the critical nesting count is 1 to protect against recursive calls if the + assert function also uses a critical section. */ + if( uxCriticalNesting == 1 ) + { + configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 ); + } +} +/*-----------------------------------------------------------*/ + +void vPortExitCritical( void ) +{ + configASSERT( uxCriticalNesting ); + uxCriticalNesting--; + if( uxCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } +} +/*-----------------------------------------------------------*/ + +__attribute__(( naked )) uint32_t ulPortSetInterruptMask( void ) +{ + __asm volatile \ + ( \ + " mrs r0, basepri \n" \ + " mov r1, %0 \n" \ + " msr basepri, r1 \n" \ + " bx lr \n" \ + :: "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "r0", "r1" \ + ); + + /* This return will not be reached but is necessary to prevent compiler + warnings. */ + return 0; +} +/*-----------------------------------------------------------*/ + +__attribute__(( naked )) void vPortClearInterruptMask( uint32_t ulNewMaskValue ) +{ + __asm volatile \ + ( \ + " msr basepri, r0 \n" \ + " bx lr \n" \ + :::"r0" \ + ); + + /* Just to avoid compiler warnings. */ + ( void ) ulNewMaskValue; +} +/*-----------------------------------------------------------*/ + +void xPortPendSVHandler( void ) +{ + /* This is a naked function. */ + + __asm volatile + ( + " mrs r0, psp \n" + " isb \n" + " \n" + " ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */ + " ldr r2, [r3] \n" + " \n" + " tst r14, #0x10 \n" /* Is the task using the FPU context? If so, push high vfp registers. */ + " it eq \n" + " vstmdbeq r0!, {s16-s31} \n" + " \n" + " stmdb r0!, {r4-r11, r14} \n" /* Save the core registers. */ + " \n" + " str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */ + " \n" + " stmdb sp!, {r3} \n" + " mov r0, %0 \n" + " msr basepri, r0 \n" + " bl vTaskSwitchContext \n" + " mov r0, #0 \n" + " msr basepri, r0 \n" + " ldmia sp!, {r3} \n" + " \n" + " ldr r1, [r3] \n" /* The first item in pxCurrentTCB is the task top of stack. */ + " ldr r0, [r1] \n" + " \n" + " ldmia r0!, {r4-r11, r14} \n" /* Pop the core registers. */ + " \n" + " tst r14, #0x10 \n" /* Is the task using the FPU context? If so, pop the high vfp registers too. */ + " it eq \n" + " vldmiaeq r0!, {s16-s31} \n" + " \n" + " msr psp, r0 \n" + " isb \n" + " \n" + #ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata workaround. */ + #if WORKAROUND_PMU_CM001 == 1 + " push { r14 } \n" + " pop { pc } \n" + #endif + #endif + " \n" + " bx r14 \n" + " \n" + " .align 2 \n" + "pxCurrentTCBConst: .word pxCurrentTCB \n" + ::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY) + ); +} +/*-----------------------------------------------------------*/ + +void xPortSysTickHandler( void ) +{ + /* The SysTick runs at the lowest interrupt priority, so when this interrupt + executes all interrupts must be unmasked. There is therefore no need to + save and then restore the interrupt mask value as its value is already + known. */ + ( void ) portSET_INTERRUPT_MASK_FROM_ISR(); + { + /* Increment the RTOS tick. */ + if( xTaskIncrementTick() != pdFALSE ) + { + /* A context switch is required. Context switching is performed in + the PendSV interrupt. Pend the PendSV interrupt. */ + portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 ); +} +/*-----------------------------------------------------------*/ + +#if configUSE_TICKLESS_IDLE == 1 + + __attribute__((weak)) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) + { + uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL; + TickType_t xModifiableIdleTime; + + /* Make sure the SysTick reload value does not overflow the counter. */ + if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks ) + { + xExpectedIdleTime = xMaximumPossibleSuppressedTicks; + } + + /* Stop the SysTick momentarily. The time the SysTick is stopped for + is accounted for as best it can be, but using the tickless mode will + inevitably result in some tiny drift of the time maintained by the + kernel with respect to calendar time. */ + portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT; + + /* Calculate the reload value required to wait xExpectedIdleTime + tick periods. -1 is used because this code will execute part way + through one of the tick periods. */ + ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) ); + if( ulReloadValue > ulStoppedTimerCompensation ) + { + ulReloadValue -= ulStoppedTimerCompensation; + } + + /* Enter a critical section but don't use the taskENTER_CRITICAL() + method as that will mask interrupts that should exit sleep mode. */ + __asm volatile( "cpsid i" ); + + /* If a context switch is pending or a task is waiting for the scheduler + to be unsuspended then abandon the low power entry. */ + if( eTaskConfirmSleepModeStatus() == eAbortSleep ) + { + /* Restart from whatever is left in the count register to complete + this tick period. */ + portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG; + + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + + /* Reset the reload register to the value required for normal tick + periods. */ + portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + + /* Re-enable interrupts - see comments above the cpsid instruction() + above. */ + __asm volatile( "cpsie i" ); + } + else + { + /* Set the new reload value. */ + portNVIC_SYSTICK_LOAD_REG = ulReloadValue; + + /* Clear the SysTick count flag and set the count value back to + zero. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + + /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can + set its parameter to 0 to indicate that its implementation contains + its own wait for interrupt or wait for event instruction, and so wfi + should not be executed again. However, the original expected idle + time variable must remain unmodified, so a copy is taken. */ + xModifiableIdleTime = xExpectedIdleTime; + configPRE_SLEEP_PROCESSING( xModifiableIdleTime ); + if( xModifiableIdleTime > 0 ) + { + __asm volatile( "dsb" ); + __asm volatile( "wfi" ); + __asm volatile( "isb" ); + } + configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); + + /* Stop SysTick. Again, the time the SysTick is stopped for is + accounted for as best it can be, but using the tickless mode will + inevitably result in some tiny drift of the time maintained by the + kernel with respect to calendar time. */ + ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG; + portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT ); + + /* Re-enable interrupts - see comments above the cpsid instruction() + above. */ + __asm volatile( "cpsie i" ); + + if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + { + uint32_t ulCalculatedLoadValue; + + /* The tick interrupt has already executed, and the SysTick + count reloaded with ulReloadValue. Reset the + portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick + period. */ + ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG ); + + /* Don't allow a tiny value, or values that have somehow + underflowed because the post sleep hook did something + that took too long. */ + if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) ) + { + ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ); + } + + portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue; + + /* The tick interrupt handler will already have pended the tick + processing in the kernel. As the pending tick will be + processed as soon as this function exits, the tick value + maintained by the tick is stepped forward by one less than the + time spent waiting. */ + ulCompleteTickPeriods = xExpectedIdleTime - 1UL; + } + else + { + /* Something other than the tick interrupt ended the sleep. + Work out how long the sleep lasted rounded to complete tick + periods (not the ulReload value which accounted for part + ticks). */ + ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG; + + /* How many complete tick periods passed while the processor + was waiting? */ + ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick; + + /* The reload value is set to whatever fraction of a single tick + period remains. */ + portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; + } + + /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG + again, then set portNVIC_SYSTICK_LOAD_REG back to its standard + value. The critical section is used to ensure the tick interrupt + can only execute once in the case that the reload register is near + zero. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + portENTER_CRITICAL(); + { + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + vTaskStepTick( ulCompleteTickPeriods ); + portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + } + portEXIT_CRITICAL(); + } + } + +#endif /* #if configUSE_TICKLESS_IDLE */ +/*-----------------------------------------------------------*/ + +/* + * Setup the systick timer to generate the tick interrupts at the required + * frequency. + */ +__attribute__(( weak )) void vPortSetupTimerInterrupt( void ) +{ + /* Calculate the constants required to configure the tick interrupt. */ + #if configUSE_TICKLESS_IDLE == 1 + { + ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ); + xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick; + ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ ); + } + #endif /* configUSE_TICKLESS_IDLE */ + + /* Configure SysTick to interrupt at the requested rate. */ + portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; + portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT ); +} +/*-----------------------------------------------------------*/ + +/* This is a naked function. */ +static void vPortEnableVFP( void ) +{ + __asm volatile + ( + " ldr.w r0, =0xE000ED88 \n" /* The FPU enable bits are in the CPACR. */ + " ldr r1, [r0] \n" + " \n" + " orr r1, r1, #( 0xf << 20 ) \n" /* Enable CP10 and CP11 coprocessors, then save back. */ + " str r1, [r0] \n" + " bx r14 " + ); +} +/*-----------------------------------------------------------*/ + +#if( configASSERT_DEFINED == 1 ) + + void vPortValidateInterruptPriority( void ) + { + uint32_t ulCurrentInterrupt; + uint8_t ucCurrentPriority; + + /* Obtain the number of the currently executing interrupt. */ + __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) ); + + /* Is the interrupt number a user defined interrupt? */ + if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER ) + { + /* Look up the interrupt's priority. */ + ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; + + /* The following assertion will fail if a service routine (ISR) for + an interrupt that has been assigned a priority above + configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API + function. ISR safe FreeRTOS API functions must *only* be called + from interrupts that have been assigned a priority at or below + configMAX_SYSCALL_INTERRUPT_PRIORITY. + + Numerically low interrupt priority numbers represent logically high + interrupt priorities, therefore the priority of the interrupt must + be set to a value equal to or numerically *higher* than + configMAX_SYSCALL_INTERRUPT_PRIORITY. + + Interrupts that use the FreeRTOS API must not be left at their + default priority of zero as that is the highest possible priority, + which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, + and therefore also guaranteed to be invalid. + + FreeRTOS maintains separate thread and ISR API functions to ensure + interrupt entry is as fast and simple as possible. + + The following links provide detailed information: + http://www.freertos.org/RTOS-Cortex-M3-M4.html + http://www.freertos.org/FAQHelp.html */ + configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); + } + + /* Priority grouping: The interrupt controller (NVIC) allows the bits + that define each interrupt's priority to be split between bits that + define the interrupt's pre-emption priority bits and bits that define + the interrupt's sub-priority. For simplicity all bits must be defined + to be pre-emption priority bits. The following assertion will fail if + this is not the case (if some bits represent a sub-priority). + + If the application only uses CMSIS libraries for interrupt + configuration then the correct setting can be achieved on all Cortex-M + devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the + scheduler. Note however that some vendor specific peripheral libraries + assume a non-zero priority group setting, in which cases using a value + of zero will result in unpredicable behaviour. */ + configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); + } + +#endif /* configASSERT_DEFINED */ + + diff --git a/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM4F/portmacro.h b/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM4F/portmacro.h new file mode 100644 index 0000000..ea4a54d --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM4F/portmacro.h @@ -0,0 +1,196 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +#ifndef PORTMACRO_H +#define PORTMACRO_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*----------------------------------------------------------- + * Port specific definitions. + * + * The settings in this file configure FreeRTOS correctly for the + * given hardware and compiler. + * + * These settings should not be altered. + *----------------------------------------------------------- + */ + +/* Type definitions. */ +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#if( configUSE_16_BIT_TICKS == 1 ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff +#else + typedef uint32_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffffffffUL +#endif +/*-----------------------------------------------------------*/ + +/* Architecture specifics. */ +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +/*-----------------------------------------------------------*/ + + +/* Scheduler utilities. */ +extern void vPortYield( void ); +#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) ) +#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) +#define portYIELD() vPortYield() +#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT +#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) +/*-----------------------------------------------------------*/ + +/* Critical section management. */ +extern void vPortEnterCritical( void ); +extern void vPortExitCritical( void ); +extern uint32_t ulPortSetInterruptMask( void ); +extern void vPortClearInterruptMask( uint32_t ulNewMaskValue ); +#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x) +#define portDISABLE_INTERRUPTS() ulPortSetInterruptMask() +#define portENABLE_INTERRUPTS() vPortClearInterruptMask(0) +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() + +/*-----------------------------------------------------------*/ + +/* Task function macros as described on the FreeRTOS.org WEB site. These are +not necessary for to use this port. They are defined so the common demo files +(which build with all the ports) will build. */ +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +/*-----------------------------------------------------------*/ + +/* Tickless idle/low power functionality. */ +#ifndef portSUPPRESS_TICKS_AND_SLEEP + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) +#endif +/*-----------------------------------------------------------*/ + +/* Architecture specific optimisations. */ +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 +#endif + +#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 + + /* Generic helper function. */ + __attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap ) + { + uint8_t ucReturn; + + __asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) ); + return ucReturn; + } + + /* Check the configuration. */ + #if( configMAX_PRIORITIES > 32 ) + #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice. + #endif + + /* Store/clear the ready priorities in a bit map. */ + #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) + #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) + + /*-----------------------------------------------------------*/ + + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - ucPortCountLeadingZeros( ( uxReadyPriorities ) ) ) + +#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ + +/*-----------------------------------------------------------*/ + +#ifdef configASSERT + void vPortValidateInterruptPriority( void ); + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() +#endif + +/* portNOP() is not required by this port. */ +#define portNOP() + +#ifdef __cplusplus +} +#endif + +#endif /* PORTMACRO_H */ + diff --git a/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM3/port.c b/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM3/port.c new file mode 100644 index 0000000..ed4050a --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM3/port.c @@ -0,0 +1,648 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/*----------------------------------------------------------- + * Implementation of functions defined in portable.h for the ARM CM3 port. + *----------------------------------------------------------*/ + +/* IAR includes. */ +#include + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "task.h" + +#if configMAX_SYSCALL_INTERRUPT_PRIORITY == 0 + #error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html +#endif + +#ifndef configSYSTICK_CLOCK_HZ + #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ + /* Ensure the SysTick is clocked at the same frequency as the core. */ + #define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) +#else + /* The way the SysTick is clocked is not modified in case it is not the same + as the core. */ + #define portNVIC_SYSTICK_CLK_BIT ( 0 ) +#endif + +/* Constants required to manipulate the core. Registers first... */ +#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) ) +#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) ) +#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) ) +#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) ) +/* ...then bits in the registers. */ +#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL ) +#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL ) +#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL ) +#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL ) +#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL ) + +#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL ) +#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL ) + +/* Constants required to check the validity of an interrupt priority. */ +#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) +#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) +#define portAIRCR_REG ( * ( ( volatile uint32_t * ) 0xE000ED0C ) ) +#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff ) +#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 ) +#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 ) +#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) +#define portPRIGROUP_SHIFT ( 8UL ) + +/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */ +#define portVECTACTIVE_MASK ( 0x1FUL ) + +/* Constants required to set up the initial stack. */ +#define portINITIAL_XPSR ( 0x01000000 ) + +/* The systick is a 24-bit counter. */ +#define portMAX_24_BIT_NUMBER ( 0xffffffUL ) + +/* A fiddle factor to estimate the number of SysTick counts that would have +occurred while the SysTick counter is stopped during tickless idle +calculations. */ +#define portMISSED_COUNTS_FACTOR ( 45UL ) + +/* For backward compatibility, ensure configKERNEL_INTERRUPT_PRIORITY is +defined. The value 255 should also ensure backward compatibility. +FreeRTOS.org versions prior to V4.3.0 did not include this definition. */ +#ifndef configKERNEL_INTERRUPT_PRIORITY + #define configKERNEL_INTERRUPT_PRIORITY 255 +#endif + +/* Each task maintains its own interrupt status in the critical nesting +variable. */ +static UBaseType_t uxCriticalNesting = 0xaaaaaaaa; + +/* + * Setup the timer to generate the tick interrupts. The implementation in this + * file is weak to allow application writers to change the timer used to + * generate the tick interrupt. + */ +void vPortSetupTimerInterrupt( void ); + +/* + * Exception handlers. + */ +void xPortSysTickHandler( void ); + +/* + * Start first task is a separate function so it can be tested in isolation. + */ +extern void vPortStartFirstTask( void ); + +/* + * Used to catch tasks that attempt to return from their implementing function. + */ +static void prvTaskExitError( void ); + +/*-----------------------------------------------------------*/ + +/* + * The number of SysTick increments that make up one tick period. + */ +#if configUSE_TICKLESS_IDLE == 1 + static uint32_t ulTimerCountsForOneTick = 0; +#endif /* configUSE_TICKLESS_IDLE */ + +/* + * The maximum number of tick periods that can be suppressed is limited by the + * 24 bit resolution of the SysTick timer. + */ +#if configUSE_TICKLESS_IDLE == 1 + static uint32_t xMaximumPossibleSuppressedTicks = 0; +#endif /* configUSE_TICKLESS_IDLE */ + +/* + * Compensate for the CPU cycles that pass while the SysTick is stopped (low + * power functionality only. + */ +#if configUSE_TICKLESS_IDLE == 1 + static uint32_t ulStoppedTimerCompensation = 0; +#endif /* configUSE_TICKLESS_IDLE */ + +/* + * Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure + * FreeRTOS API functions are not called from interrupts that have been assigned + * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY. + */ +#if ( configASSERT_DEFINED == 1 ) + static uint8_t ucMaxSysCallPriority = 0; + static uint32_t ulMaxPRIGROUPValue = 0; + static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * const ) portNVIC_IP_REGISTERS_OFFSET_16; +#endif /* configASSERT_DEFINED */ + +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) +{ + /* Simulate the stack frame as it would be created by a context switch + interrupt. */ + pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */ + *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) pxCode; /* PC */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) prvTaskExitError; /* LR */ + pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ + *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ + pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ + + return pxTopOfStack; +} +/*-----------------------------------------------------------*/ + +static void prvTaskExitError( void ) +{ + /* A function that implements a task must not exit or attempt to return to + its caller as there is nothing to return to. If a task wants to exit it + should instead call vTaskDelete( NULL ). + + Artificially force an assert() to be triggered if configASSERT() is + defined, then stop here so application writers can catch the error. */ + configASSERT( uxCriticalNesting == ~0UL ); + portDISABLE_INTERRUPTS(); + for( ;; ); +} +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +BaseType_t xPortStartScheduler( void ) +{ + #if( configASSERT_DEFINED == 1 ) + { + volatile uint32_t ulOriginalPriority; + volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); + volatile uint8_t ucMaxPriorityValue; + + /* Determine the maximum priority from which ISR safe FreeRTOS API + functions can be called. ISR safe functions are those that end in + "FromISR". FreeRTOS maintains separate thread and ISR API functions to + ensure interrupt entry is as fast and simple as possible. + + Save the interrupt priority value that is about to be clobbered. */ + ulOriginalPriority = *pucFirstUserPriorityRegister; + + /* Determine the number of priority bits available. First write to all + possible bits. */ + *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE; + + /* Read the value back to see how many bits stuck. */ + ucMaxPriorityValue = *pucFirstUserPriorityRegister; + + /* Use the same mask on the maximum system call priority. */ + ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; + + /* Calculate the maximum acceptable priority group value for the number + of bits read back. */ + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS; + while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) + { + ulMaxPRIGROUPValue--; + ucMaxPriorityValue <<= ( uint8_t ) 0x01; + } + + /* Shift the priority group value back to its position within the AIRCR + register. */ + ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; + ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; + + /* Restore the clobbered interrupt priority register to its original + value. */ + *pucFirstUserPriorityRegister = ulOriginalPriority; + } + #endif /* conifgASSERT_DEFINED */ + + /* Make PendSV and SysTick the lowest priority interrupts. */ + portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI; + portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI; + + /* Start the timer that generates the tick ISR. Interrupts are disabled + here already. */ + vPortSetupTimerInterrupt(); + + /* Initialise the critical nesting count ready for the first task. */ + uxCriticalNesting = 0; + + /* Start the first task. */ + vPortStartFirstTask(); + + /* Should not get here! */ + return 0; +} +/*-----------------------------------------------------------*/ + +void vPortEndScheduler( void ) +{ + /* Not implemented in ports where there is nothing to return to. + Artificially force an assert. */ + configASSERT( uxCriticalNesting == 1000UL ); +} +/*-----------------------------------------------------------*/ + +void vPortYield( void ) +{ + /* Set a PendSV to request a context switch. */ + portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; + + /* Barriers are normally not required but do ensure the code is completely + within the specified behaviour for the architecture. */ + __DSB(); + __ISB(); +} +/*-----------------------------------------------------------*/ + +void vPortEnterCritical( void ) +{ + portDISABLE_INTERRUPTS(); + uxCriticalNesting++; + __DSB(); + __ISB(); + + /* This is not the interrupt safe version of the enter critical function so + assert() if it is being called from an interrupt context. Only API + functions that end in "FromISR" can be used in an interrupt. Only assert if + the critical nesting count is 1 to protect against recursive calls if the + assert function also uses a critical section. */ + if( uxCriticalNesting == 1 ) + { + configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 ); + } +} +/*-----------------------------------------------------------*/ + +void vPortExitCritical( void ) +{ + configASSERT( uxCriticalNesting ); + uxCriticalNesting--; + if( uxCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } +} +/*-----------------------------------------------------------*/ + +void xPortSysTickHandler( void ) +{ + /* The SysTick runs at the lowest interrupt priority, so when this interrupt + executes all interrupts must be unmasked. There is therefore no need to + save and then restore the interrupt mask value as its value is already + known. */ + ( void ) portSET_INTERRUPT_MASK_FROM_ISR(); + { + /* Increment the RTOS tick. */ + if( xTaskIncrementTick() != pdFALSE ) + { + /* A context switch is required. Context switching is performed in + the PendSV interrupt. Pend the PendSV interrupt. */ + portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 ); +} +/*-----------------------------------------------------------*/ + +#if configUSE_TICKLESS_IDLE == 1 + + __weak void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) + { + uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL; + TickType_t xModifiableIdleTime; + + /* Make sure the SysTick reload value does not overflow the counter. */ + if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks ) + { + xExpectedIdleTime = xMaximumPossibleSuppressedTicks; + } + + /* Stop the SysTick momentarily. The time the SysTick is stopped for + is accounted for as best it can be, but using the tickless mode will + inevitably result in some tiny drift of the time maintained by the + kernel with respect to calendar time. */ + portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT; + + /* Calculate the reload value required to wait xExpectedIdleTime + tick periods. -1 is used because this code will execute part way + through one of the tick periods. */ + ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) ); + if( ulReloadValue > ulStoppedTimerCompensation ) + { + ulReloadValue -= ulStoppedTimerCompensation; + } + + /* Enter a critical section but don't use the taskENTER_CRITICAL() + method as that will mask interrupts that should exit sleep mode. */ + __disable_interrupt(); + + /* If a context switch is pending or a task is waiting for the scheduler + to be unsuspended then abandon the low power entry. */ + if( eTaskConfirmSleepModeStatus() == eAbortSleep ) + { + /* Restart from whatever is left in the count register to complete + this tick period. */ + portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG; + + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + + /* Reset the reload register to the value required for normal tick + periods. */ + portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + + /* Re-enable interrupts - see comments above __disable_interrupt() + call above. */ + __enable_interrupt(); + } + else + { + /* Set the new reload value. */ + portNVIC_SYSTICK_LOAD_REG = ulReloadValue; + + /* Clear the SysTick count flag and set the count value back to + zero. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + + /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can + set its parameter to 0 to indicate that its implementation contains + its own wait for interrupt or wait for event instruction, and so wfi + should not be executed again. However, the original expected idle + time variable must remain unmodified, so a copy is taken. */ + xModifiableIdleTime = xExpectedIdleTime; + configPRE_SLEEP_PROCESSING( xModifiableIdleTime ); + if( xModifiableIdleTime > 0 ) + { + __DSB(); + __WFI(); + __ISB(); + } + configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); + + /* Stop SysTick. Again, the time the SysTick is stopped for is + accounted for as best it can be, but using the tickless mode will + inevitably result in some tiny drift of the time maintained by the + kernel with respect to calendar time. */ + ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG; + portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT ); + + /* Re-enable interrupts - see comments above __disable_interrupt() + call above. */ + __enable_interrupt(); + + if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + { + uint32_t ulCalculatedLoadValue; + + /* The tick interrupt has already executed, and the SysTick + count reloaded with ulReloadValue. Reset the + portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick + period. */ + ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG ); + + /* Don't allow a tiny value, or values that have somehow + underflowed because the post sleep hook did something + that took too long. */ + if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) ) + { + ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ); + } + + portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue; + + /* The tick interrupt handler will already have pended the tick + processing in the kernel. As the pending tick will be + processed as soon as this function exits, the tick value + maintained by the tick is stepped forward by one less than the + time spent waiting. */ + ulCompleteTickPeriods = xExpectedIdleTime - 1UL; + } + else + { + /* Something other than the tick interrupt ended the sleep. + Work out how long the sleep lasted rounded to complete tick + periods (not the ulReload value which accounted for part + ticks). */ + ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG; + + /* How many complete tick periods passed while the processor + was waiting? */ + ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick; + + /* The reload value is set to whatever fraction of a single tick + period remains. */ + portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; + } + + /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG + again, then set portNVIC_SYSTICK_LOAD_REG back to its standard + value. The critical section is used to ensure the tick interrupt + can only execute once in the case that the reload register is near + zero. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + portENTER_CRITICAL(); + { + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + vTaskStepTick( ulCompleteTickPeriods ); + portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + } + portEXIT_CRITICAL(); + } + } + +#endif /* #if configUSE_TICKLESS_IDLE */ +/*-----------------------------------------------------------*/ + +/* + * Setup the systick timer to generate the tick interrupts at the required + * frequency. + */ +__weak void vPortSetupTimerInterrupt( void ) +{ + /* Calculate the constants required to configure the tick interrupt. */ + #if configUSE_TICKLESS_IDLE == 1 + { + ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ); + xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick; + ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ ); + } + #endif /* configUSE_TICKLESS_IDLE */ + + /* Configure SysTick to interrupt at the requested rate. */ + portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; + portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT ); +} +/*-----------------------------------------------------------*/ + +#if( configASSERT_DEFINED == 1 ) + + void vPortValidateInterruptPriority( void ) + { + uint32_t ulCurrentInterrupt; + uint8_t ucCurrentPriority; + + /* Obtain the number of the currently executing interrupt. */ + __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) ); + + /* Is the interrupt number a user defined interrupt? */ + if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER ) + { + /* Look up the interrupt's priority. */ + ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; + + /* The following assertion will fail if a service routine (ISR) for + an interrupt that has been assigned a priority above + configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API + function. ISR safe FreeRTOS API functions must *only* be called + from interrupts that have been assigned a priority at or below + configMAX_SYSCALL_INTERRUPT_PRIORITY. + + Numerically low interrupt priority numbers represent logically high + interrupt priorities, therefore the priority of the interrupt must + be set to a value equal to or numerically *higher* than + configMAX_SYSCALL_INTERRUPT_PRIORITY. + + Interrupts that use the FreeRTOS API must not be left at their + default priority of zero as that is the highest possible priority, + which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, + and therefore also guaranteed to be invalid. + + FreeRTOS maintains separate thread and ISR API functions to ensure + interrupt entry is as fast and simple as possible. + + The following links provide detailed information: + http://www.freertos.org/RTOS-Cortex-M3-M4.html + http://www.freertos.org/FAQHelp.html */ + configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); + } + + /* Priority grouping: The interrupt controller (NVIC) allows the bits + that define each interrupt's priority to be split between bits that + define the interrupt's pre-emption priority bits and bits that define + the interrupt's sub-priority. For simplicity all bits must be defined + to be pre-emption priority bits. The following assertion will fail if + this is not the case (if some bits represent a sub-priority). + + If the application only uses CMSIS libraries for interrupt + configuration then the correct setting can be achieved on all Cortex-M + devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the + scheduler. Note however that some vendor specific peripheral libraries + assume a non-zero priority group setting, in which cases using a value + of zero will result in unpredicable behaviour. */ + configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); + } + +#endif /* configASSERT_DEFINED */ + +/*-----------------------------------------------------------*/ +void vApplicationIdleHook( void ) +{ + /* Use the idle task to place the CPU into a low power mode. Greater power + saving could be achieved by not including any demo tasks that never block. */ +} + +#include "diag.h" +void vApplicationStackOverflowHook( xTaskHandle pxTask, signed char *pcTaskName ) +{ + /* This function will be called if a task overflows its stack, if + configCHECK_FOR_STACK_OVERFLOW != 0. It might be that the function + parameters have been corrupted, depending on the severity of the stack + overflow. When this is the case pxCurrentTCB can be inspected in the + debugger to find the offending task. */ + DiagPrintf("\n\r[%s] STACK OVERFLOW - TaskName(%s)\n\r", __FUNCTION__, pcTaskName); + for( ;; ); +} + +/*-----------------------------------------------------------*/ + + + + + + + + + + + + + + + + + + + + + + diff --git a/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM3/portasm.s b/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM3/portasm.s new file mode 100644 index 0000000..e98645c --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM3/portasm.s @@ -0,0 +1,155 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#include + + RSEG CODE:CODE(2) + thumb + + EXTERN pxCurrentTCB + EXTERN vTaskSwitchContext + + PUBLIC xPortPendSVHandler + PUBLIC ulPortSetInterruptMask + PUBLIC vPortClearInterruptMask + PUBLIC vPortSVCHandler + PUBLIC vPortStartFirstTask + + + +/*-----------------------------------------------------------*/ + +xPortPendSVHandler: + mrs r0, psp + isb + ldr r3, =pxCurrentTCB /* Get the location of the current TCB. */ + ldr r2, [r3] + + stmdb r0!, {r4-r11} /* Save the remaining registers. */ + str r0, [r2] /* Save the new top of stack into the first member of the TCB. */ + + stmdb sp!, {r3, r14} + mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY + msr basepri, r0 + bl vTaskSwitchContext + mov r0, #0 + msr basepri, r0 + ldmia sp!, {r3, r14} + + ldr r1, [r3] + ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */ + ldmia r0!, {r4-r11} /* Pop the registers. */ + msr psp, r0 + isb + bx r14 + + +/*-----------------------------------------------------------*/ + +ulPortSetInterruptMask: + mrs r0, basepri + mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY + msr basepri, r1 + bx r14 + +/*-----------------------------------------------------------*/ + +vPortClearInterruptMask: + msr basepri, r0 + bx r14 + +/*-----------------------------------------------------------*/ + +vPortSVCHandler: + /* Get the location of the current TCB. */ + ldr r3, =pxCurrentTCB + ldr r1, [r3] + ldr r0, [r1] + /* Pop the core registers. */ + ldmia r0!, {r4-r11} + msr psp, r0 + isb + mov r0, #0 + msr basepri, r0 + orr r14, r14, #13 + bx r14 + +/*-----------------------------------------------------------*/ + +vPortStartFirstTask + /* Use the NVIC offset register to locate the stack. */ + ldr r0, =0xE000ED08 + ldr r0, [r0] + ldr r0, [r0] + /* Set the msp back to the start of the stack. */ + msr msp, r0 + /* Call SVC to start the first task, ensuring interrupts are enabled. */ + cpsie i + cpsie f + dsb + isb + svc 0 + + END diff --git a/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM3/portmacro.h b/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM3/portmacro.h new file mode 100644 index 0000000..b4011df --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM3/portmacro.h @@ -0,0 +1,208 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +#ifndef PORTMACRO_H +#define PORTMACRO_H + +#ifdef __cplusplus +extern "C" { +#endif + +// to prevent marco define use in standard header file +#define _NO_DEFINITIONS_IN_HEADER_FILES +#include +//#include "basic_types.h" +#include "hal_misc.h" +#if !defined(__IARSTDLIB__) +#ifndef memcmp +#define memcmp(dst, src, sz) _memcmp(dst, src, sz) +#endif +#ifndef memset +#define memset(dst, val, sz) _memset(dst, val, sz) +#endif +#ifndef memcpy +#define memcpy(dst, src, sz) _memcpy(dst, src, sz) +#endif +#endif +/*----------------------------------------------------------- + * Port specific definitions. + * + * The settings in this file configure FreeRTOS correctly for the + * given hardware and compiler. + * + * These settings should not be altered. + *----------------------------------------------------------- + */ + +/* Type definitions. */ +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#if( configUSE_16_BIT_TICKS == 1 ) + typedef uint16_t TickType_t; + #define portMAX_DELAY 0xffff +#else + typedef uint32_t TickType_t; + #define portMAX_DELAY 0xffffffffUL +#endif +/*-----------------------------------------------------------*/ + +/* Architecture specifics. */ +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +/*-----------------------------------------------------------*/ + +/* Scheduler utilities. */ +extern void vPortYield( void ); +#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04UL ) ) +#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) +#define portYIELD() vPortYield() +#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT +#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) +/*-----------------------------------------------------------*/ + +/* Architecture specific optimisations. */ +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 +#endif + +#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 + + /* Check the configuration. */ + #if( configMAX_PRIORITIES > 32 ) + #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice. + #endif + + /* Store/clear the ready priorities in a bit map. */ + #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) ) + #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) ) + + /*-----------------------------------------------------------*/ + + #include + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __CLZ( ( uxReadyPriorities ) ) ) + +#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ +/*-----------------------------------------------------------*/ + +/* Critical section management. */ +extern void vPortEnterCritical( void ); +extern void vPortExitCritical( void ); +extern uint32_t ulPortSetInterruptMask( void ); +extern void vPortClearInterruptMask( uint32_t ulNewMask ); + +#define portDISABLE_INTERRUPTS() ulPortSetInterruptMask() +#define portENABLE_INTERRUPTS() vPortClearInterruptMask( 0 ) +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() +#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask( x ) +/*-----------------------------------------------------------*/ + +/* Tickless idle/low power functionality. */ +#ifndef portSUPPRESS_TICKS_AND_SLEEP + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) +#endif +/*-----------------------------------------------------------*/ + +/* Task function macros as described on the FreeRTOS.org WEB site. These are +not necessary for to use this port. They are defined so the common demo files +(which build with all the ports) will build. */ +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +/*-----------------------------------------------------------*/ + +#ifdef configASSERT + void vPortValidateInterruptPriority( void ); + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() +#endif + +/* portNOP() is not required by this port. */ +#define portNOP() + +/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in +the source code because to do so would cause other compilers to generate +warnings. */ +#pragma diag_suppress=Pe191 +#pragma diag_suppress=Pa082 + +#ifdef __cplusplus +} +#endif + +#endif /* PORTMACRO_H */ + diff --git a/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM4F/port.c b/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM4F/port.c new file mode 100644 index 0000000..101ed94 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM4F/port.c @@ -0,0 +1,652 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/*----------------------------------------------------------- + * Implementation of functions defined in portable.h for the ARM CM4F port. + *----------------------------------------------------------*/ + +/* Compiler includes. */ +#include + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "task.h" + +#ifndef __ARMVFP__ + #error This port can only be used when the project options are configured to enable hardware floating point support. +#endif + +#if configMAX_SYSCALL_INTERRUPT_PRIORITY == 0 + #error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html +#endif + +#ifndef configSYSTICK_CLOCK_HZ + #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ + /* Ensure the SysTick is clocked at the same frequency as the core. */ + #define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) +#else + /* The way the SysTick is clocked is not modified in case it is not the same + as the core. */ + #define portNVIC_SYSTICK_CLK_BIT ( 0 ) +#endif + +/* Constants required to manipulate the core. Registers first... */ +#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) ) +#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) ) +#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) ) +#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) ) +/* ...then bits in the registers. */ +#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL ) +#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL ) +#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL ) +#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL ) +#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL ) + +#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL ) +#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL ) + +/* Constants required to check the validity of an interrupt priority. */ +#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) +#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) +#define portAIRCR_REG ( * ( ( volatile uint32_t * ) 0xE000ED0C ) ) +#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff ) +#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 ) +#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 ) +#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) +#define portPRIGROUP_SHIFT ( 8UL ) + +/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */ +#define portVECTACTIVE_MASK ( 0x1FUL ) + +/* Constants required to manipulate the VFP. */ +#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating point context control register. */ +#define portASPEN_AND_LSPEN_BITS ( 0x3UL << 30UL ) + +/* Constants required to set up the initial stack. */ +#define portINITIAL_XPSR ( 0x01000000 ) +#define portINITIAL_EXEC_RETURN ( 0xfffffffd ) + +/* The systick is a 24-bit counter. */ +#define portMAX_24_BIT_NUMBER ( 0xffffffUL ) + +/* A fiddle factor to estimate the number of SysTick counts that would have +occurred while the SysTick counter is stopped during tickless idle +calculations. */ +#define portMISSED_COUNTS_FACTOR ( 45UL ) + + +/* Each task maintains its own interrupt status in the critical nesting +variable. */ +static UBaseType_t uxCriticalNesting = 0xaaaaaaaa; + +/* + * Setup the timer to generate the tick interrupts. The implementation in this + * file is weak to allow application writers to change the timer used to + * generate the tick interrupt. + */ +void vPortSetupTimerInterrupt( void ); + +/* + * Exception handlers. + */ +void xPortSysTickHandler( void ); + +/* + * Start first task is a separate function so it can be tested in isolation. + */ +extern void vPortStartFirstTask( void ); + +/* + * Turn the VFP on. + */ +extern void vPortEnableVFP( void ); + +/* + * Used to catch tasks that attempt to return from their implementing function. + */ +static void prvTaskExitError( void ); + +/*-----------------------------------------------------------*/ + +/* + * The number of SysTick increments that make up one tick period. + */ +#if configUSE_TICKLESS_IDLE == 1 + static uint32_t ulTimerCountsForOneTick = 0; +#endif /* configUSE_TICKLESS_IDLE */ + +/* + * The maximum number of tick periods that can be suppressed is limited by the + * 24 bit resolution of the SysTick timer. + */ +#if configUSE_TICKLESS_IDLE == 1 + static uint32_t xMaximumPossibleSuppressedTicks = 0; +#endif /* configUSE_TICKLESS_IDLE */ + +/* + * Compensate for the CPU cycles that pass while the SysTick is stopped (low + * power functionality only. + */ +#if configUSE_TICKLESS_IDLE == 1 + static uint32_t ulStoppedTimerCompensation = 0; +#endif /* configUSE_TICKLESS_IDLE */ + +/* + * Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure + * FreeRTOS API functions are not called from interrupts that have been assigned + * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY. + */ +#if ( configASSERT_DEFINED == 1 ) + static uint8_t ucMaxSysCallPriority = 0; + static uint32_t ulMaxPRIGROUPValue = 0; + static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * const ) portNVIC_IP_REGISTERS_OFFSET_16; +#endif /* configASSERT_DEFINED */ + +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) +{ + /* Simulate the stack frame as it would be created by a context switch + interrupt. */ + + /* Offset added to account for the way the MCU uses the stack on entry/exit + of interrupts, and to ensure alignment. */ + pxTopOfStack--; + + *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) pxCode; /* PC */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) prvTaskExitError; /* LR */ + + /* Save code space by skipping register initialisation. */ + pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ + *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ + + /* A save method is being used that requires each task to maintain its + own exec return value. */ + pxTopOfStack--; + *pxTopOfStack = portINITIAL_EXEC_RETURN; + + pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ + + return pxTopOfStack; +} +/*-----------------------------------------------------------*/ + +static void prvTaskExitError( void ) +{ + /* A function that implements a task must not exit or attempt to return to + its caller as there is nothing to return to. If a task wants to exit it + should instead call vTaskDelete( NULL ). + + Artificially force an assert() to be triggered if configASSERT() is + defined, then stop here so application writers can catch the error. */ + configASSERT( uxCriticalNesting == ~0UL ); + portDISABLE_INTERRUPTS(); + for( ;; ); +} +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +BaseType_t xPortStartScheduler( void ) +{ + #if( configASSERT_DEFINED == 1 ) + { + volatile uint32_t ulOriginalPriority; + volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); + volatile uint8_t ucMaxPriorityValue; + + /* Determine the maximum priority from which ISR safe FreeRTOS API + functions can be called. ISR safe functions are those that end in + "FromISR". FreeRTOS maintains separate thread and ISR API functions to + ensure interrupt entry is as fast and simple as possible. + + Save the interrupt priority value that is about to be clobbered. */ + ulOriginalPriority = *pucFirstUserPriorityRegister; + + /* Determine the number of priority bits available. First write to all + possible bits. */ + *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE; + + /* Read the value back to see how many bits stuck. */ + ucMaxPriorityValue = *pucFirstUserPriorityRegister; + + /* Use the same mask on the maximum system call priority. */ + ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; + + /* Calculate the maximum acceptable priority group value for the number + of bits read back. */ + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS; + while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) + { + ulMaxPRIGROUPValue--; + ucMaxPriorityValue <<= ( uint8_t ) 0x01; + } + + /* Shift the priority group value back to its position within the AIRCR + register. */ + ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; + ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; + + /* Restore the clobbered interrupt priority register to its original + value. */ + *pucFirstUserPriorityRegister = ulOriginalPriority; + } + #endif /* conifgASSERT_DEFINED */ + + /* Make PendSV and SysTick the lowest priority interrupts. */ + portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI; + portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI; + + /* Start the timer that generates the tick ISR. Interrupts are disabled + here already. */ + vPortSetupTimerInterrupt(); + + /* Initialise the critical nesting count ready for the first task. */ + uxCriticalNesting = 0; + + /* Ensure the VFP is enabled - it should be anyway. */ + vPortEnableVFP(); + + /* Lazy save always. */ + *( portFPCCR ) |= portASPEN_AND_LSPEN_BITS; + + /* Start the first task. */ + vPortStartFirstTask(); + + /* Should not get here! */ + return 0; +} +/*-----------------------------------------------------------*/ + +void vPortEndScheduler( void ) +{ + /* Not implemented in ports where there is nothing to return to. + Artificially force an assert. */ + configASSERT( uxCriticalNesting == 1000UL ); +} +/*-----------------------------------------------------------*/ + +void vPortYield( void ) +{ + /* Set a PendSV to request a context switch. */ + portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; + + /* Barriers are normally not required but do ensure the code is completely + within the specified behaviour for the architecture. */ + __DSB(); + __ISB(); +} +/*-----------------------------------------------------------*/ + +void vPortEnterCritical( void ) +{ + portDISABLE_INTERRUPTS(); + uxCriticalNesting++; + __DSB(); + __ISB(); + + /* This is not the interrupt safe version of the enter critical function so + assert() if it is being called from an interrupt context. Only API + functions that end in "FromISR" can be used in an interrupt. Only assert if + the critical nesting count is 1 to protect against recursive calls if the + assert function also uses a critical section. */ + if( uxCriticalNesting == 1 ) + { + configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 ); + } +} +/*-----------------------------------------------------------*/ + +void vPortExitCritical( void ) +{ + configASSERT( uxCriticalNesting ); + uxCriticalNesting--; + if( uxCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } +} +/*-----------------------------------------------------------*/ + +void xPortSysTickHandler( void ) +{ + /* The SysTick runs at the lowest interrupt priority, so when this interrupt + executes all interrupts must be unmasked. There is therefore no need to + save and then restore the interrupt mask value as its value is already + known. */ + ( void ) portSET_INTERRUPT_MASK_FROM_ISR(); + { + /* Increment the RTOS tick. */ + if( xTaskIncrementTick() != pdFALSE ) + { + /* A context switch is required. Context switching is performed in + the PendSV interrupt. Pend the PendSV interrupt. */ + portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 ); +} +/*-----------------------------------------------------------*/ + +#if configUSE_TICKLESS_IDLE == 1 + + __weak void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) + { + uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL; + TickType_t xModifiableIdleTime; + + /* Make sure the SysTick reload value does not overflow the counter. */ + if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks ) + { + xExpectedIdleTime = xMaximumPossibleSuppressedTicks; + } + + /* Stop the SysTick momentarily. The time the SysTick is stopped for + is accounted for as best it can be, but using the tickless mode will + inevitably result in some tiny drift of the time maintained by the + kernel with respect to calendar time. */ + portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT; + + /* Calculate the reload value required to wait xExpectedIdleTime + tick periods. -1 is used because this code will execute part way + through one of the tick periods. */ + ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) ); + if( ulReloadValue > ulStoppedTimerCompensation ) + { + ulReloadValue -= ulStoppedTimerCompensation; + } + + /* Enter a critical section but don't use the taskENTER_CRITICAL() + method as that will mask interrupts that should exit sleep mode. */ + __disable_interrupt(); + + /* If a context switch is pending or a task is waiting for the scheduler + to be unsuspended then abandon the low power entry. */ + if( eTaskConfirmSleepModeStatus() == eAbortSleep ) + { + /* Restart from whatever is left in the count register to complete + this tick period. */ + portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG; + + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + + /* Reset the reload register to the value required for normal tick + periods. */ + portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + + /* Re-enable interrupts - see comments above __disable_interrupt() + call above. */ + __enable_interrupt(); + } + else + { + /* Set the new reload value. */ + portNVIC_SYSTICK_LOAD_REG = ulReloadValue; + + /* Clear the SysTick count flag and set the count value back to + zero. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + + /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can + set its parameter to 0 to indicate that its implementation contains + its own wait for interrupt or wait for event instruction, and so wfi + should not be executed again. However, the original expected idle + time variable must remain unmodified, so a copy is taken. */ + xModifiableIdleTime = xExpectedIdleTime; + configPRE_SLEEP_PROCESSING( xModifiableIdleTime ); + if( xModifiableIdleTime > 0 ) + { + __DSB(); + __WFI(); + __ISB(); + } + configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); + + /* Stop SysTick. Again, the time the SysTick is stopped for is + accounted for as best it can be, but using the tickless mode will + inevitably result in some tiny drift of the time maintained by the + kernel with respect to calendar time. */ + ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG; + portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT ); + + /* Re-enable interrupts - see comments above __disable_interrupt() + call above. */ + __enable_interrupt(); + + if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + { + uint32_t ulCalculatedLoadValue; + + /* The tick interrupt has already executed, and the SysTick + count reloaded with ulReloadValue. Reset the + portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick + period. */ + ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG ); + + /* Don't allow a tiny value, or values that have somehow + underflowed because the post sleep hook did something + that took too long. */ + if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) ) + { + ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ); + } + + portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue; + + /* The tick interrupt handler will already have pended the tick + processing in the kernel. As the pending tick will be + processed as soon as this function exits, the tick value + maintained by the tick is stepped forward by one less than the + time spent waiting. */ + ulCompleteTickPeriods = xExpectedIdleTime - 1UL; + } + else + { + /* Something other than the tick interrupt ended the sleep. + Work out how long the sleep lasted rounded to complete tick + periods (not the ulReload value which accounted for part + ticks). */ + ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG; + + /* How many complete tick periods passed while the processor + was waiting? */ + ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick; + + /* The reload value is set to whatever fraction of a single tick + period remains. */ + portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; + } + + /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG + again, then set portNVIC_SYSTICK_LOAD_REG back to its standard + value. The critical section is used to ensure the tick interrupt + can only execute once in the case that the reload register is near + zero. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + portENTER_CRITICAL(); + { + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + vTaskStepTick( ulCompleteTickPeriods ); + portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + } + portEXIT_CRITICAL(); + } + } + +#endif /* #if configUSE_TICKLESS_IDLE */ +/*-----------------------------------------------------------*/ + +/* + * Setup the systick timer to generate the tick interrupts at the required + * frequency. + */ +__weak void vPortSetupTimerInterrupt( void ) +{ + /* Calculate the constants required to configure the tick interrupt. */ + #if configUSE_TICKLESS_IDLE == 1 + { + ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ); + xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick; + ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ ); + } + #endif /* configUSE_TICKLESS_IDLE */ + + /* Configure SysTick to interrupt at the requested rate. */ + portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; + portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT ); +} +/*-----------------------------------------------------------*/ + +#if( configASSERT_DEFINED == 1 ) + + void vPortValidateInterruptPriority( void ) + { + uint32_t ulCurrentInterrupt; + uint8_t ucCurrentPriority; + + /* Obtain the number of the currently executing interrupt. */ + __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) ); + + /* Is the interrupt number a user defined interrupt? */ + if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER ) + { + /* Look up the interrupt's priority. */ + ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; + + /* The following assertion will fail if a service routine (ISR) for + an interrupt that has been assigned a priority above + configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API + function. ISR safe FreeRTOS API functions must *only* be called + from interrupts that have been assigned a priority at or below + configMAX_SYSCALL_INTERRUPT_PRIORITY. + + Numerically low interrupt priority numbers represent logically high + interrupt priorities, therefore the priority of the interrupt must + be set to a value equal to or numerically *higher* than + configMAX_SYSCALL_INTERRUPT_PRIORITY. + + Interrupts that use the FreeRTOS API must not be left at their + default priority of zero as that is the highest possible priority, + which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, + and therefore also guaranteed to be invalid. + + FreeRTOS maintains separate thread and ISR API functions to ensure + interrupt entry is as fast and simple as possible. + + The following links provide detailed information: + http://www.freertos.org/RTOS-Cortex-M3-M4.html + http://www.freertos.org/FAQHelp.html */ + configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); + } + + /* Priority grouping: The interrupt controller (NVIC) allows the bits + that define each interrupt's priority to be split between bits that + define the interrupt's pre-emption priority bits and bits that define + the interrupt's sub-priority. For simplicity all bits must be defined + to be pre-emption priority bits. The following assertion will fail if + this is not the case (if some bits represent a sub-priority). + + If the application only uses CMSIS libraries for interrupt + configuration then the correct setting can be achieved on all Cortex-M + devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the + scheduler. Note however that some vendor specific peripheral libraries + assume a non-zero priority group setting, in which cases using a value + of zero will result in unpredicable behaviour. */ + configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); + } + +#endif /* configASSERT_DEFINED */ + + + + + + + + + + + + + + + + + + + + + diff --git a/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM4F/portasm.s b/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM4F/portasm.s new file mode 100644 index 0000000..d67bc5e --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM4F/portasm.s @@ -0,0 +1,195 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#include + + RSEG CODE:CODE(2) + thumb + + EXTERN pxCurrentTCB + EXTERN vTaskSwitchContext + + PUBLIC xPortPendSVHandler + PUBLIC ulPortSetInterruptMask + PUBLIC vPortClearInterruptMask + PUBLIC vPortSVCHandler + PUBLIC vPortStartFirstTask + PUBLIC vPortEnableVFP + + +/*-----------------------------------------------------------*/ + +xPortPendSVHandler: + mrs r0, psp + isb + /* Get the location of the current TCB. */ + ldr r3, =pxCurrentTCB + ldr r2, [r3] + + /* Is the task using the FPU context? If so, push high vfp registers. */ + tst r14, #0x10 + it eq + vstmdbeq r0!, {s16-s31} + + /* Save the core registers. */ + stmdb r0!, {r4-r11, r14} + + /* Save the new top of stack into the first member of the TCB. */ + str r0, [r2] + + stmdb sp!, {r3} + mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY + msr basepri, r0 + bl vTaskSwitchContext + mov r0, #0 + msr basepri, r0 + ldmia sp!, {r3} + + /* The first item in pxCurrentTCB is the task top of stack. */ + ldr r1, [r3] + ldr r0, [r1] + + /* Pop the core registers. */ + ldmia r0!, {r4-r11, r14} + + /* Is the task using the FPU context? If so, pop the high vfp registers + too. */ + tst r14, #0x10 + it eq + vldmiaeq r0!, {s16-s31} + + msr psp, r0 + isb + #ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata */ + #if WORKAROUND_PMU_CM001 == 1 + push { r14 } + pop { pc } + #endif + #endif + + bx r14 + + +/*-----------------------------------------------------------*/ + +ulPortSetInterruptMask: + mrs r0, basepri + mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY + msr basepri, r1 + bx r14 + +/*-----------------------------------------------------------*/ + +vPortClearInterruptMask: + msr basepri, r0 + bx r14 + +/*-----------------------------------------------------------*/ + +vPortSVCHandler: + /* Get the location of the current TCB. */ + ldr r3, =pxCurrentTCB + ldr r1, [r3] + ldr r0, [r1] + /* Pop the core registers. */ + ldmia r0!, {r4-r11, r14} + msr psp, r0 + isb + mov r0, #0 + msr basepri, r0 + bx r14 + +/*-----------------------------------------------------------*/ + +vPortStartFirstTask + /* Use the NVIC offset register to locate the stack. */ + ldr r0, =0xE000ED08 + ldr r0, [r0] + ldr r0, [r0] + /* Set the msp back to the start of the stack. */ + msr msp, r0 + /* Call SVC to start the first task. */ + cpsie i + cpsie f + dsb + isb + svc 0 + +/*-----------------------------------------------------------*/ + +vPortEnableVFP: + /* The FPU enable bits are in the CPACR. */ + ldr.w r0, =0xE000ED88 + ldr r1, [r0] + + /* Enable CP10 and CP11 coprocessors, then save back. */ + orr r1, r1, #( 0xf << 20 ) + str r1, [r0] + bx r14 + + + + END + diff --git a/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM4F/portmacro.h b/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM4F/portmacro.h new file mode 100644 index 0000000..24599a1 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/portable/IAR/ARM_CM4F/portmacro.h @@ -0,0 +1,193 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +#ifndef PORTMACRO_H +#define PORTMACRO_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*----------------------------------------------------------- + * Port specific definitions. + * + * The settings in this file configure FreeRTOS correctly for the + * given hardware and compiler. + * + * These settings should not be altered. + *----------------------------------------------------------- + */ + +/* Type definitions. */ +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#if( configUSE_16_BIT_TICKS == 1 ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff +#else + typedef uint32_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffffffffUL +#endif +/*-----------------------------------------------------------*/ + +/* Architecture specifics. */ +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +/*-----------------------------------------------------------*/ + +/* Scheduler utilities. */ +extern void vPortYield( void ); +#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) ) +#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) +#define portYIELD() vPortYield() +#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT +#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) +/*-----------------------------------------------------------*/ + +/* Architecture specific optimisations. */ +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 +#endif + +#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 + + /* Check the configuration. */ + #if( configMAX_PRIORITIES > 32 ) + #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice. + #endif + + /* Store/clear the ready priorities in a bit map. */ + #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) + #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) + + /*-----------------------------------------------------------*/ + + #include + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __CLZ( ( uxReadyPriorities ) ) ) + +#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ +/*-----------------------------------------------------------*/ + +/* Critical section management. */ +extern void vPortEnterCritical( void ); +extern void vPortExitCritical( void ); +extern uint32_t ulPortSetInterruptMask( void ); +extern void vPortClearInterruptMask( uint32_t ulNewMask ); + +#define portDISABLE_INTERRUPTS() ulPortSetInterruptMask() +#define portENABLE_INTERRUPTS() vPortClearInterruptMask( 0 ) +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() +#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask( x ) +/*-----------------------------------------------------------*/ + +/* Tickless idle/low power functionality. */ +#ifndef portSUPPRESS_TICKS_AND_SLEEP + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) +#endif + +/*-----------------------------------------------------------*/ + +/* Task function macros as described on the FreeRTOS.org WEB site. These are +not necessary for to use this port. They are defined so the common demo files +(which build with all the ports) will build. */ +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +/*-----------------------------------------------------------*/ + +#ifdef configASSERT + void vPortValidateInterruptPriority( void ); + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() +#endif + +/* portNOP() is not required by this port. */ +#define portNOP() + +/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in +the source code because to do so would cause other compilers to generate +warnings. */ +#pragma diag_suppress=Pe191 +#pragma diag_suppress=Pa082 + +#ifdef __cplusplus +} +#endif + +#endif /* PORTMACRO_H */ + diff --git a/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/Makefile b/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/Makefile new file mode 100644 index 0000000..fcc7b3a --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/Makefile @@ -0,0 +1,32 @@ + +include $(MAKE_INCLUDE_GEN) + +.PHONY: all clean + +MODULE_IFLAGS = -I../../include + + +#*****************************************************************************# +# Object FILE LIST # +#*****************************************************************************# +OBJS = heap_4.o +ifeq ($(CONFIG_RELEASE_BUILD),y) + OBJS = +else +endif + + +#*****************************************************************************# +# RULES TO GENERATE TARGETS # +#*****************************************************************************# + +# Define the Rules to build the core targets +all: CORE_TARGETS COPY_RAM_OBJS + + +#*****************************************************************************# +# GENERATE OBJECT FILE +#*****************************************************************************# +CORE_TARGETS: $(OBJS) + +-include $(DEPS) diff --git a/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/heap_1.c b/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/heap_1.c new file mode 100644 index 0000000..65d4f37 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/heap_1.c @@ -0,0 +1,170 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +/* + * The simplest possible implementation of pvPortMalloc(). Note that this + * implementation does NOT allow allocated memory to be freed again. + * + * See heap_2.c, heap_3.c and heap_4.c for alternative implementations, and the + * memory management pages of http://www.FreeRTOS.org for more information. + */ +#include + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +#include "FreeRTOS.h" +#include "task.h" + +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +/* A few bytes might be lost to byte aligning the heap start address. */ +#define configADJUSTED_HEAP_SIZE ( configTOTAL_HEAP_SIZE - portBYTE_ALIGNMENT ) + +/* Allocate the memory for the heap. */ +static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]; +static size_t xNextFreeByte = ( size_t ) 0; + +/*-----------------------------------------------------------*/ + +void *pvPortMalloc( size_t xWantedSize ) +{ +void *pvReturn = NULL; +static uint8_t *pucAlignedHeap = NULL; + + /* Ensure that blocks are always aligned to the required number of bytes. */ + #if portBYTE_ALIGNMENT != 1 + if( xWantedSize & portBYTE_ALIGNMENT_MASK ) + { + /* Byte alignment required. */ + xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ); + } + #endif + + vTaskSuspendAll(); + { + if( pucAlignedHeap == NULL ) + { + /* Ensure the heap starts on a correctly aligned boundary. */ + pucAlignedHeap = ( uint8_t * ) ( ( ( portPOINTER_SIZE_TYPE ) &ucHeap[ portBYTE_ALIGNMENT ] ) & ( ( portPOINTER_SIZE_TYPE ) ~portBYTE_ALIGNMENT_MASK ) ); + } + + /* Check there is enough room left for the allocation. */ + if( ( ( xNextFreeByte + xWantedSize ) < configADJUSTED_HEAP_SIZE ) && + ( ( xNextFreeByte + xWantedSize ) > xNextFreeByte ) )/* Check for overflow. */ + { + /* Return the next free byte then increment the index past this + block. */ + pvReturn = pucAlignedHeap + xNextFreeByte; + xNextFreeByte += xWantedSize; + } + + traceMALLOC( pvReturn, xWantedSize ); + } + ( void ) xTaskResumeAll(); + + #if( configUSE_MALLOC_FAILED_HOOK == 1 ) + { + if( pvReturn == NULL ) + { + extern void vApplicationMallocFailedHook( void ); + vApplicationMallocFailedHook(); + } + } + #endif + + return pvReturn; +} +/*-----------------------------------------------------------*/ + +void vPortFree( void *pv ) +{ + /* Memory cannot be freed using this scheme. See heap_2.c, heap_3.c and + heap_4.c for alternative implementations, and the memory management pages of + http://www.FreeRTOS.org for more information. */ + ( void ) pv; + + /* Force an assert as it is invalid to call this function. */ + configASSERT( pv == NULL ); +} +/*-----------------------------------------------------------*/ + +void vPortInitialiseBlocks( void ) +{ + /* Only required when static memory is not cleared. */ + xNextFreeByte = ( size_t ) 0; +} +/*-----------------------------------------------------------*/ + +size_t xPortGetFreeHeapSize( void ) +{ + return ( configADJUSTED_HEAP_SIZE - xNextFreeByte ); +} + + + diff --git a/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/heap_2.c b/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/heap_2.c new file mode 100644 index 0000000..a28a560 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/heap_2.c @@ -0,0 +1,299 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* + * A sample implementation of pvPortMalloc() and vPortFree() that permits + * allocated blocks to be freed, but does not combine adjacent free blocks + * into a single larger block (and so will fragment memory). See heap_4.c for + * an equivalent that does combine adjacent blocks into single larger blocks. + * + * See heap_1.c, heap_3.c and heap_4.c for alternative implementations, and the + * memory management pages of http://www.FreeRTOS.org for more information. + */ +#include + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +#include "FreeRTOS.h" +#include "task.h" + +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +/* A few bytes might be lost to byte aligning the heap start address. */ +#define configADJUSTED_HEAP_SIZE ( configTOTAL_HEAP_SIZE - portBYTE_ALIGNMENT ) + +/* + * Initialises the heap structures before their first use. + */ +static void prvHeapInit( void ); + +/* Allocate the memory for the heap. */ +static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]; + +/* Define the linked list structure. This is used to link free blocks in order +of their size. */ +typedef struct A_BLOCK_LINK +{ + struct A_BLOCK_LINK *pxNextFreeBlock; /*<< The next free block in the list. */ + size_t xBlockSize; /*<< The size of the free block. */ +} BlockLink_t; + + +static const uint16_t heapSTRUCT_SIZE = ( ( sizeof ( BlockLink_t ) + ( portBYTE_ALIGNMENT - 1 ) ) & ~portBYTE_ALIGNMENT_MASK ); +#define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( heapSTRUCT_SIZE * 2 ) ) + +/* Create a couple of list links to mark the start and end of the list. */ +static BlockLink_t xStart, xEnd; + +/* Keeps track of the number of free bytes remaining, but says nothing about +fragmentation. */ +static size_t xFreeBytesRemaining = configADJUSTED_HEAP_SIZE; + +/* STATIC FUNCTIONS ARE DEFINED AS MACROS TO MINIMIZE THE FUNCTION CALL DEPTH. */ + +/* + * Insert a block into the list of free blocks - which is ordered by size of + * the block. Small blocks at the start of the list and large blocks at the end + * of the list. + */ +#define prvInsertBlockIntoFreeList( pxBlockToInsert ) \ +{ \ +BlockLink_t *pxIterator; \ +size_t xBlockSize; \ + \ + xBlockSize = pxBlockToInsert->xBlockSize; \ + \ + /* Iterate through the list until a block is found that has a larger size */ \ + /* than the block we are inserting. */ \ + for( pxIterator = &xStart; pxIterator->pxNextFreeBlock->xBlockSize < xBlockSize; pxIterator = pxIterator->pxNextFreeBlock ) \ + { \ + /* There is nothing to do here - just iterate to the correct position. */ \ + } \ + \ + /* Update the list to include the block being inserted in the correct */ \ + /* position. */ \ + pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock; \ + pxIterator->pxNextFreeBlock = pxBlockToInsert; \ +} +/*-----------------------------------------------------------*/ + +void *pvPortMalloc( size_t xWantedSize ) +{ +BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink; +static BaseType_t xHeapHasBeenInitialised = pdFALSE; +void *pvReturn = NULL; + + vTaskSuspendAll(); + { + /* If this is the first call to malloc then the heap will require + initialisation to setup the list of free blocks. */ + if( xHeapHasBeenInitialised == pdFALSE ) + { + prvHeapInit(); + xHeapHasBeenInitialised = pdTRUE; + } + + /* The wanted size is increased so it can contain a BlockLink_t + structure in addition to the requested amount of bytes. */ + if( xWantedSize > 0 ) + { + xWantedSize += heapSTRUCT_SIZE; + + /* Ensure that blocks are always aligned to the required number of bytes. */ + if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0 ) + { + /* Byte alignment required. */ + xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ); + } + } + + if( ( xWantedSize > 0 ) && ( xWantedSize < configADJUSTED_HEAP_SIZE ) ) + { + /* Blocks are stored in byte order - traverse the list from the start + (smallest) block until one of adequate size is found. */ + pxPreviousBlock = &xStart; + pxBlock = xStart.pxNextFreeBlock; + while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) ) + { + pxPreviousBlock = pxBlock; + pxBlock = pxBlock->pxNextFreeBlock; + } + + /* If we found the end marker then a block of adequate size was not found. */ + if( pxBlock != &xEnd ) + { + /* Return the memory space - jumping over the BlockLink_t structure + at its start. */ + pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + heapSTRUCT_SIZE ); + + /* This block is being returned for use so must be taken out of the + list of free blocks. */ + pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock; + + /* If the block is larger than required it can be split into two. */ + if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE ) + { + /* This block is to be split into two. Create a new block + following the number of bytes requested. The void cast is + used to prevent byte alignment warnings from the compiler. */ + pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize ); + + /* Calculate the sizes of two blocks split from the single + block. */ + pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize; + pxBlock->xBlockSize = xWantedSize; + + /* Insert the new block into the list of free blocks. */ + prvInsertBlockIntoFreeList( ( pxNewBlockLink ) ); + } + + xFreeBytesRemaining -= pxBlock->xBlockSize; + } + } + + traceMALLOC( pvReturn, xWantedSize ); + } + ( void ) xTaskResumeAll(); + + #if( configUSE_MALLOC_FAILED_HOOK == 1 ) + { + if( pvReturn == NULL ) + { + extern void vApplicationMallocFailedHook( void ); + vApplicationMallocFailedHook(); + } + } + #endif + + return pvReturn; +} +/*-----------------------------------------------------------*/ + +void vPortFree( void *pv ) +{ +uint8_t *puc = ( uint8_t * ) pv; +BlockLink_t *pxLink; + + if( pv != NULL ) + { + /* The memory being freed will have an BlockLink_t structure immediately + before it. */ + puc -= heapSTRUCT_SIZE; + + /* This unexpected casting is to keep some compilers from issuing + byte alignment warnings. */ + pxLink = ( void * ) puc; + + vTaskSuspendAll(); + { + /* Add this block to the list of free blocks. */ + prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) ); + xFreeBytesRemaining += pxLink->xBlockSize; + traceFREE( pv, pxLink->xBlockSize ); + } + ( void ) xTaskResumeAll(); + } +} +/*-----------------------------------------------------------*/ + +size_t xPortGetFreeHeapSize( void ) +{ + return xFreeBytesRemaining; +} +/*-----------------------------------------------------------*/ + +void vPortInitialiseBlocks( void ) +{ + /* This just exists to keep the linker quiet. */ +} +/*-----------------------------------------------------------*/ + +static void prvHeapInit( void ) +{ +BlockLink_t *pxFirstFreeBlock; +uint8_t *pucAlignedHeap; + + /* Ensure the heap starts on a correctly aligned boundary. */ + pucAlignedHeap = ( uint8_t * ) ( ( ( portPOINTER_SIZE_TYPE ) &ucHeap[ portBYTE_ALIGNMENT ] ) & ( ( portPOINTER_SIZE_TYPE ) ~portBYTE_ALIGNMENT_MASK ) ); + + /* xStart is used to hold a pointer to the first item in the list of free + blocks. The void cast is used to prevent compiler warnings. */ + xStart.pxNextFreeBlock = ( void * ) pucAlignedHeap; + xStart.xBlockSize = ( size_t ) 0; + + /* xEnd is used to mark the end of the list of free blocks. */ + xEnd.xBlockSize = configADJUSTED_HEAP_SIZE; + xEnd.pxNextFreeBlock = NULL; + + /* To start with there is a single free block that is sized to take up the + entire heap space. */ + pxFirstFreeBlock = ( void * ) pucAlignedHeap; + pxFirstFreeBlock->xBlockSize = configADJUSTED_HEAP_SIZE; + pxFirstFreeBlock->pxNextFreeBlock = &xEnd; +} +/*-----------------------------------------------------------*/ diff --git a/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/heap_3.c b/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/heap_3.c new file mode 100644 index 0000000..8b948bf --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/heap_3.c @@ -0,0 +1,131 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +/* + * Implementation of pvPortMalloc() and vPortFree() that relies on the + * compilers own malloc() and free() implementations. + * + * This file can only be used if the linker is configured to to generate + * a heap memory area. + * + * See heap_1.c, heap_2.c and heap_4.c for alternative implementations, and the + * memory management pages of http://www.FreeRTOS.org for more information. + */ + +#include + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +#include "FreeRTOS.h" +#include "task.h" + +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +/*-----------------------------------------------------------*/ + +void *pvPortMalloc( size_t xWantedSize ) +{ +void *pvReturn; + + vTaskSuspendAll(); + { + pvReturn = malloc( xWantedSize ); + traceMALLOC( pvReturn, xWantedSize ); + } + ( void ) xTaskResumeAll(); + + #if( configUSE_MALLOC_FAILED_HOOK == 1 ) + { + if( pvReturn == NULL ) + { + extern void vApplicationMallocFailedHook( void ); + vApplicationMallocFailedHook(); + } + } + #endif + + return pvReturn; +} +/*-----------------------------------------------------------*/ + +void vPortFree( void *pv ) +{ + if( pv ) + { + vTaskSuspendAll(); + { + free( pv ); + traceFREE( pv, 0 ); + } + ( void ) xTaskResumeAll(); + } +} + + + diff --git a/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/heap_4.c b/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/heap_4.c new file mode 100644 index 0000000..beed365 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/heap_4.c @@ -0,0 +1,489 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* + * A sample implementation of pvPortMalloc() and vPortFree() that combines + * (coalescences) adjacent memory blocks as they are freed, and in so doing + * limits memory fragmentation. + * + * See heap_1.c, heap_2.c and heap_3.c for alternative implementations, and the + * memory management pages of http://www.FreeRTOS.org for more information. + */ +#include + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +#include "FreeRTOS.h" +#include "task.h" + +//TODO: remove section when combine BD and BF +#include "section_config.h" + +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +/* Block sizes must not get too small. */ +#define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( xHeapStructSize * 2 ) ) + +/* Assumes 8bit bytes! */ +#define heapBITS_PER_BYTE ( ( size_t ) 8 ) + +/* Allocate the memory for the heap. */ +SRAM_BF_DATA_SECTION +static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]; + +/* Define the linked list structure. This is used to link free blocks in order +of their memory address. */ +typedef struct A_BLOCK_LINK +{ + struct A_BLOCK_LINK *pxNextFreeBlock; /*<< The next free block in the list. */ + size_t xBlockSize; /*<< The size of the free block. */ +} BlockLink_t; + +/*-----------------------------------------------------------*/ + +/* + * Inserts a block of memory that is being freed into the correct position in + * the list of free memory blocks. The block being freed will be merged with + * the block in front it and/or the block behind it if the memory blocks are + * adjacent to each other. + */ +static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert ); + +/* + * Called automatically to setup the required heap structures the first time + * pvPortMalloc() is called. + */ +static void prvHeapInit( void ); + +/*-----------------------------------------------------------*/ + +/* The size of the structure placed at the beginning of each allocated memory +block must by correctly byte aligned. */ +static const size_t xHeapStructSize = ( ( sizeof( BlockLink_t ) + ( portBYTE_ALIGNMENT - 1 ) ) & ~portBYTE_ALIGNMENT_MASK ); + +/* Create a couple of list links to mark the start and end of the list. */ +static BlockLink_t xStart, *pxEnd = NULL; + +/* Keeps track of the number of free bytes remaining, but says nothing about +fragmentation. */ +static size_t xFreeBytesRemaining = 0U; +static size_t xMinimumEverFreeBytesRemaining = 0U; + +/* Gets set to the top bit of an size_t type. When this bit in the xBlockSize +member of an BlockLink_t structure is set then the block belongs to the +application. When the bit is free the block is still part of the free heap +space. */ +static size_t xBlockAllocatedBit = 0; + +/*-----------------------------------------------------------*/ + +void *pvPortMalloc( size_t xWantedSize ) +{ +BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink; +void *pvReturn = NULL; + + vTaskSuspendAll(); + { + /* If this is the first call to malloc then the heap will require + initialisation to setup the list of free blocks. */ + if( pxEnd == NULL ) + { + prvHeapInit(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Check the requested block size is not so large that the top bit is + set. The top bit of the block size member of the BlockLink_t structure + is used to determine who owns the block - the application or the + kernel, so it must be free. */ + if( ( xWantedSize & xBlockAllocatedBit ) == 0 ) + { + /* The wanted size is increased so it can contain a BlockLink_t + structure in addition to the requested amount of bytes. */ + if( xWantedSize > 0 ) + { + xWantedSize += xHeapStructSize; + + /* Ensure that blocks are always aligned to the required number + of bytes. */ + if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 ) + { + /* Byte alignment required. */ + xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ); + configASSERT( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) == 0 ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) ) + { + /* Traverse the list from the start (lowest address) block until + one of adequate size is found. */ + pxPreviousBlock = &xStart; + pxBlock = xStart.pxNextFreeBlock; + while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) ) + { + pxPreviousBlock = pxBlock; + pxBlock = pxBlock->pxNextFreeBlock; + } + + /* If the end marker was reached then a block of adequate size + was not found. */ + if( pxBlock != pxEnd ) + { + /* Return the memory space pointed to - jumping over the + BlockLink_t structure at its start. */ + pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + xHeapStructSize ); + + /* This block is being returned for use so must be taken out + of the list of free blocks. */ + pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock; + + /* If the block is larger than required it can be split into + two. */ + if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE ) + { + /* This block is to be split into two. Create a new + block following the number of bytes requested. The void + cast is used to prevent byte alignment warnings from the + compiler. */ + pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize ); + configASSERT( ( ( ( uint32_t ) pxNewBlockLink ) & portBYTE_ALIGNMENT_MASK ) == 0 ); + + /* Calculate the sizes of two blocks split from the + single block. */ + pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize; + pxBlock->xBlockSize = xWantedSize; + + /* Insert the new block into the list of free blocks. */ + prvInsertBlockIntoFreeList( ( pxNewBlockLink ) ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + xFreeBytesRemaining -= pxBlock->xBlockSize; + + if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining ) + { + xMinimumEverFreeBytesRemaining = xFreeBytesRemaining; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* The block is being returned - it is allocated and owned + by the application and has no "next" block. */ + pxBlock->xBlockSize |= xBlockAllocatedBit; + pxBlock->pxNextFreeBlock = NULL; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + traceMALLOC( pvReturn, xWantedSize ); + } + ( void ) xTaskResumeAll(); + + #if( configUSE_MALLOC_FAILED_HOOK == 1 ) + { + if( pvReturn == NULL ) + { + extern void vApplicationMallocFailedHook( void ); + vApplicationMallocFailedHook(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif + + configASSERT( ( ( ( uint32_t ) pvReturn ) & portBYTE_ALIGNMENT_MASK ) == 0 ); + return pvReturn; +} +/*-----------------------------------------------------------*/ + +void __vPortFree( void *pv ) +{ +uint8_t *puc = ( uint8_t * ) pv; +BlockLink_t *pxLink; + + if( pv != NULL ) + { + /* The memory being freed will have an BlockLink_t structure immediately + before it. */ + puc -= xHeapStructSize; + + /* This casting is to keep the compiler from issuing warnings. */ + pxLink = ( void * ) puc; + + /* Check the block is actually allocated. */ + configASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ); + configASSERT( pxLink->pxNextFreeBlock == NULL ); + + if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ) + { + if( pxLink->pxNextFreeBlock == NULL ) + { + /* The block is being returned to the heap - it is no longer + allocated. */ + pxLink->xBlockSize &= ~xBlockAllocatedBit; + + vTaskSuspendAll(); + { + /* Add this block to the list of free blocks. */ + xFreeBytesRemaining += pxLink->xBlockSize; + traceFREE( pv, pxLink->xBlockSize ); + prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) ); + } + ( void ) xTaskResumeAll(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } +} +/*-----------------------------------------------------------*/ +/* Add by Alfa 2015/02/04 -----------------------------------*/ +static void (*ext_free)( void *p ) = NULL; +static uint32_t ext_upper = 0; +static uint32_t ext_lower = 0; +void vPortSetExtFree( void (*free)( void *p ), uint32_t upper, uint32_t lower ) +{ + ext_free = free; + ext_upper = upper; + ext_lower = lower; +} + +void vPortFree( void *pv ) +{ + if( ((uint32_t)pv >= ext_lower) && ((uint32_t)pv < ext_upper) ){ + // use external free function + if( ext_free ) ext_free( pv ); + }else + __vPortFree( pv ); +} + +/*-----------------------------------------------------------*/ + +size_t xPortGetFreeHeapSize( void ) +{ + return xFreeBytesRemaining; +} +/*-----------------------------------------------------------*/ + +size_t xPortGetMinimumEverFreeHeapSize( void ) +{ + return xMinimumEverFreeBytesRemaining; +} +/*-----------------------------------------------------------*/ + +void vPortInitialiseBlocks( void ) +{ + /* This just exists to keep the linker quiet. */ +} +/*-----------------------------------------------------------*/ + +static void prvHeapInit( void ) +{ +BlockLink_t *pxFirstFreeBlock; +uint8_t *pucAlignedHeap; +uint32_t ulAddress; +size_t xTotalHeapSize = configTOTAL_HEAP_SIZE; + + /* Ensure the heap starts on a correctly aligned boundary. */ + ulAddress = ( uint32_t ) ucHeap; + + if( ( ulAddress & portBYTE_ALIGNMENT_MASK ) != 0 ) + { + ulAddress += ( portBYTE_ALIGNMENT - 1 ); + ulAddress &= ~portBYTE_ALIGNMENT_MASK; + xTotalHeapSize -= ulAddress - ( uint32_t ) ucHeap; + } + + pucAlignedHeap = ( uint8_t * ) ulAddress; + + /* xStart is used to hold a pointer to the first item in the list of free + blocks. The void cast is used to prevent compiler warnings. */ + xStart.pxNextFreeBlock = ( void * ) pucAlignedHeap; + xStart.xBlockSize = ( size_t ) 0; + + /* pxEnd is used to mark the end of the list of free blocks and is inserted + at the end of the heap space. */ + ulAddress = ( ( uint32_t ) pucAlignedHeap ) + xTotalHeapSize; + ulAddress -= xHeapStructSize; + ulAddress &= ~portBYTE_ALIGNMENT_MASK; + pxEnd = ( void * ) ulAddress; + pxEnd->xBlockSize = 0; + pxEnd->pxNextFreeBlock = NULL; + + /* To start with there is a single free block that is sized to take up the + entire heap space, minus the space taken by pxEnd. */ + pxFirstFreeBlock = ( void * ) pucAlignedHeap; + pxFirstFreeBlock->xBlockSize = ulAddress - ( uint32_t ) pxFirstFreeBlock; + pxFirstFreeBlock->pxNextFreeBlock = pxEnd; + + /* Only one block exists - and it covers the entire usable heap space. */ + xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; + xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; + + /* Work out the position of the top bit in a size_t variable. */ + xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 ); +} +/*-----------------------------------------------------------*/ + +static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert ) +{ +BlockLink_t *pxIterator; +uint8_t *puc; + + /* Iterate through the list until a block is found that has a higher address + than the block being inserted. */ + for( pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock ) + { + /* Nothing to do here, just iterate to the right position. */ + } + + /* Do the block being inserted, and the block it is being inserted after + make a contiguous block of memory? */ + puc = ( uint8_t * ) pxIterator; + if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert ) + { + pxIterator->xBlockSize += pxBlockToInsert->xBlockSize; + pxBlockToInsert = pxIterator; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Do the block being inserted, and the block it is being inserted before + make a contiguous block of memory? */ + puc = ( uint8_t * ) pxBlockToInsert; + if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) pxIterator->pxNextFreeBlock ) + { + if( pxIterator->pxNextFreeBlock != pxEnd ) + { + /* Form one big block from the two blocks. */ + pxBlockToInsert->xBlockSize += pxIterator->pxNextFreeBlock->xBlockSize; + pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock; + } + else + { + pxBlockToInsert->pxNextFreeBlock = pxEnd; + } + } + else + { + pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock; + } + + /* If the block being inserted plugged a gab, so was merged with the block + before and the block after, then it's pxNextFreeBlock pointer will have + already been set, and should not be set here as that would make it point + to itself. */ + if( pxIterator != pxBlockToInsert ) + { + pxIterator->pxNextFreeBlock = pxBlockToInsert; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } +} + diff --git a/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/heap_5.c b/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/heap_5.c new file mode 100644 index 0000000..76e56df --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/portable/MemMang/heap_5.c @@ -0,0 +1,567 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* + * A sample implementation of pvPortMalloc() that allows the heap to be defined + * across multiple non-contigous blocks and combines (coalescences) adjacent + * memory blocks as they are freed. + * + * See heap_1.c, heap_2.c, heap_3.c and heap_4.c for alternative + * implementations, and the memory management pages of http://www.FreeRTOS.org + * for more information. + * + * Usage notes: + * + * vPortDefineHeapRegions() ***must*** be called before pvPortMalloc(). + * pvPortMalloc() will be called if any task objects (tasks, queues, event + * groups, etc.) are created, therefore vPortDefineHeapRegions() ***must*** be + * called before any other objects are defined. + * + * vPortDefineHeapRegions() takes a single parameter. The parameter is an array + * of HeapRegion_t structures. HeapRegion_t is defined in portable.h as + * + * typedef struct HeapRegion + * { + * uint8_t *pucStartAddress; << Start address of a block of memory that will be part of the heap. + * size_t xSizeInBytes; << Size of the block of memory. + * } HeapRegion_t; + * + * The array is terminated using a NULL zero sized region definition, and the + * memory regions defined in the array ***must*** appear in address order from + * low address to high address. So the following is a valid example of how + * to use the function. + * + * HeapRegion_t xHeapRegions[] = + * { + * { ( uint8_t * ) 0x80000000UL, 0x10000 }, << Defines a block of 0x10000 bytes starting at address 0x80000000 + * { ( uint8_t * ) 0x90000000UL, 0xa0000 }, << Defines a block of 0xa0000 bytes starting at address of 0x90000000 + * { NULL, 0 } << Terminates the array. + * }; + * + * vPortDefineHeapRegions( xHeapRegions ); << Pass the array into vPortDefineHeapRegions(). + * + * Note 0x80000000 is the lower address so appears in the array first. + * + */ +#include + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +#include "FreeRTOS.h" +#include "task.h" + +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +/* Block sizes must not get too small. */ +#define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( uxHeapStructSize << 1 ) ) + +/* Assumes 8bit bytes! */ +#define heapBITS_PER_BYTE ( ( size_t ) 8 ) + +/* Define the linked list structure. This is used to link free blocks in order +of their memory address. */ +typedef struct A_BLOCK_LINK +{ + struct A_BLOCK_LINK *pxNextFreeBlock; /*<< The next free block in the list. */ + size_t xBlockSize; /*<< The size of the free block. */ +} BlockLink_t; + +/*-----------------------------------------------------------*/ + +/* + * Inserts a block of memory that is being freed into the correct position in + * the list of free memory blocks. The block being freed will be merged with + * the block in front it and/or the block behind it if the memory blocks are + * adjacent to each other. + */ +static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert ); + +/*-----------------------------------------------------------*/ + +/* The size of the structure placed at the beginning of each allocated memory +block must by correctly byte aligned. */ +static const uint32_t uxHeapStructSize = ( ( sizeof ( BlockLink_t ) + ( portBYTE_ALIGNMENT - 1 ) ) & ~portBYTE_ALIGNMENT_MASK ); + +/* Create a couple of list links to mark the start and end of the list. */ +static BlockLink_t xStart, *pxEnd = NULL; + +/* Keeps track of the number of free bytes remaining, but says nothing about +fragmentation. */ +static size_t xFreeBytesRemaining = 0; +static size_t xMinimumEverFreeBytesRemaining = 0; + +/* Gets set to the top bit of an size_t type. When this bit in the xBlockSize +member of an BlockLink_t structure is set then the block belongs to the +application. When the bit is free the block is still part of the free heap +space. */ +static size_t xBlockAllocatedBit = 0; + +/* Realtek test code start */ +//TODO: remove section when combine BD and BF +#include "section_config.h" +SRAM_BF_DATA_SECTION +static unsigned char ucHeap[ configTOTAL_HEAP_SIZE ]; + +HeapRegion_t xHeapRegions[] = +{ + { NULL, 0 }, // Defines a block from ucHeap + { NULL, 0 }, + { NULL, 0 } // Terminates the array. +}; +/* Realtek test code end */ + +/*-----------------------------------------------------------*/ + +void *pvPortMalloc( size_t xWantedSize ) +{ +BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink; +void *pvReturn = NULL; + + /* Realtek test code start */ + if(pxEnd == NULL) + { + // lower StartAddress must put in lower index of array, must sort by address + xHeapRegions[0].pucStartAddress = (uint8_t*)0x10002100; // released image1 text + xHeapRegions[0].xSizeInBytes = 0x1F00; + xHeapRegions[1].pucStartAddress = ucHeap; + xHeapRegions[1].xSizeInBytes = sizeof(ucHeap); + vPortDefineHeapRegions( xHeapRegions ); + } + /* Realtek test code end */ + + /* The heap must be initialised before the first call to + prvPortMalloc(). */ + configASSERT( pxEnd ); + + vTaskSuspendAll(); + { + /* Check the requested block size is not so large that the top bit is + set. The top bit of the block size member of the BlockLink_t structure + is used to determine who owns the block - the application or the + kernel, so it must be free. */ + if( ( xWantedSize & xBlockAllocatedBit ) == 0 ) + { + /* The wanted size is increased so it can contain a BlockLink_t + structure in addition to the requested amount of bytes. */ + if( xWantedSize > 0 ) + { + xWantedSize += uxHeapStructSize; + + /* Ensure that blocks are always aligned to the required number + of bytes. */ + if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 ) + { + /* Byte alignment required. */ + xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) ) + { + /* Traverse the list from the start (lowest address) block until + one of adequate size is found. */ + pxPreviousBlock = &xStart; + pxBlock = xStart.pxNextFreeBlock; + while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) ) + { + pxPreviousBlock = pxBlock; + pxBlock = pxBlock->pxNextFreeBlock; + } + + /* If the end marker was reached then a block of adequate size + was not found. */ + if( pxBlock != pxEnd ) + { + /* Return the memory space pointed to - jumping over the + BlockLink_t structure at its start. */ + pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + uxHeapStructSize ); + + /* This block is being returned for use so must be taken out + of the list of free blocks. */ + pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock; + + /* If the block is larger than required it can be split into + two. */ + if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE ) + { + /* This block is to be split into two. Create a new + block following the number of bytes requested. The void + cast is used to prevent byte alignment warnings from the + compiler. */ + pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize ); + + /* Calculate the sizes of two blocks split from the + single block. */ + pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize; + pxBlock->xBlockSize = xWantedSize; + + /* Insert the new block into the list of free blocks. */ + prvInsertBlockIntoFreeList( ( pxNewBlockLink ) ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + xFreeBytesRemaining -= pxBlock->xBlockSize; + + if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining ) + { + xMinimumEverFreeBytesRemaining = xFreeBytesRemaining; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* The block is being returned - it is allocated and owned + by the application and has no "next" block. */ + pxBlock->xBlockSize |= xBlockAllocatedBit; + pxBlock->pxNextFreeBlock = NULL; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + traceMALLOC( pvReturn, xWantedSize ); + } + ( void ) xTaskResumeAll(); + + #if( configUSE_MALLOC_FAILED_HOOK == 1 ) + { + if( pvReturn == NULL ) + { + extern void vApplicationMallocFailedHook( void ); + vApplicationMallocFailedHook(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif + + return pvReturn; +} +/*-----------------------------------------------------------*/ + +void __vPortFree( void *pv ) +{ +uint8_t *puc = ( uint8_t * ) pv; +BlockLink_t *pxLink; + + if( pv != NULL ) + { + /* The memory being freed will have an BlockLink_t structure immediately + before it. */ + puc -= uxHeapStructSize; + + /* This casting is to keep the compiler from issuing warnings. */ + pxLink = ( void * ) puc; + + /* Check the block is actually allocated. */ + configASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ); + configASSERT( pxLink->pxNextFreeBlock == NULL ); + + if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ) + { + if( pxLink->pxNextFreeBlock == NULL ) + { + /* The block is being returned to the heap - it is no longer + allocated. */ + pxLink->xBlockSize &= ~xBlockAllocatedBit; + + vTaskSuspendAll(); + { + /* Add this block to the list of free blocks. */ + xFreeBytesRemaining += pxLink->xBlockSize; + traceFREE( pv, pxLink->xBlockSize ); + prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) ); + } + ( void ) xTaskResumeAll(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } +} + +/*-----------------------------------------------------------*/ +/* Add by Alfa 2015/02/04 -----------------------------------*/ +static void (*ext_free)( void *p ) = NULL; +static uint32_t ext_upper = 0; +static uint32_t ext_lower = 0; +void vPortSetExtFree( void (*free)( void *p ), uint32_t upper, uint32_t lower ) +{ + ext_free = free; + ext_upper = upper; + ext_lower = lower; +} + +void vPortFree( void *pv ) +{ + if( ((uint32_t)pv >= ext_lower) && ((uint32_t)pv < ext_upper) ){ + // use external free function + if( ext_free ) ext_free( pv ); + }else + __vPortFree( pv ); +} + +/*-----------------------------------------------------------*/ + +size_t xPortGetFreeHeapSize( void ) +{ + return xFreeBytesRemaining; +} +/*-----------------------------------------------------------*/ + +size_t xPortGetMinimumEverFreeHeapSize( void ) +{ + return xMinimumEverFreeBytesRemaining; +} +/*-----------------------------------------------------------*/ + +static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert ) +{ +BlockLink_t *pxIterator; +uint8_t *puc; + + /* Iterate through the list until a block is found that has a higher address + than the block being inserted. */ + for( pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock ) + { + /* Nothing to do here, just iterate to the right position. */ + } + + /* Do the block being inserted, and the block it is being inserted after + make a contiguous block of memory? */ + puc = ( uint8_t * ) pxIterator; + if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert ) + { + pxIterator->xBlockSize += pxBlockToInsert->xBlockSize; + pxBlockToInsert = pxIterator; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Do the block being inserted, and the block it is being inserted before + make a contiguous block of memory? */ + puc = ( uint8_t * ) pxBlockToInsert; + if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) pxIterator->pxNextFreeBlock ) + { + if( pxIterator->pxNextFreeBlock != pxEnd ) + { + /* Form one big block from the two blocks. */ + pxBlockToInsert->xBlockSize += pxIterator->pxNextFreeBlock->xBlockSize; + pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock; + } + else + { + pxBlockToInsert->pxNextFreeBlock = pxEnd; + } + } + else + { + pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock; + } + + /* If the block being inserted plugged a gab, so was merged with the block + before and the block after, then it's pxNextFreeBlock pointer will have + already been set, and should not be set here as that would make it point + to itself. */ + if( pxIterator != pxBlockToInsert ) + { + pxIterator->pxNextFreeBlock = pxBlockToInsert; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } +} +/*-----------------------------------------------------------*/ + +void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions ) +{ +BlockLink_t *pxFirstFreeBlockInRegion = NULL, *pxPreviousFreeBlock; +uint8_t *pucAlignedHeap; +size_t xTotalRegionSize, xTotalHeapSize = 0; +BaseType_t xDefinedRegions = 0; +uint32_t ulAddress; +const HeapRegion_t *pxHeapRegion; + + /* Can only call once! */ + configASSERT( pxEnd == NULL ); + + pxHeapRegion = &( pxHeapRegions[ xDefinedRegions ] ); + + while( pxHeapRegion->xSizeInBytes > 0 ) + { + xTotalRegionSize = pxHeapRegion->xSizeInBytes; + + /* Ensure the heap region starts on a correctly aligned boundary. */ + ulAddress = ( uint32_t ) pxHeapRegion->pucStartAddress; + if( ( ulAddress & portBYTE_ALIGNMENT_MASK ) != 0 ) + { + ulAddress += ( portBYTE_ALIGNMENT - 1 ); + ulAddress &= ~portBYTE_ALIGNMENT_MASK; + + /* Adjust the size for the bytes lost to alignment. */ + xTotalRegionSize -= ulAddress - ( uint32_t ) pxHeapRegion->pucStartAddress; + } + + pucAlignedHeap = ( uint8_t * ) ulAddress; + + /* Set xStart if it has not already been set. */ + if( xDefinedRegions == 0 ) + { + /* xStart is used to hold a pointer to the first item in the list of + free blocks. The void cast is used to prevent compiler warnings. */ + xStart.pxNextFreeBlock = ( BlockLink_t * ) pucAlignedHeap; + xStart.xBlockSize = ( size_t ) 0; + } + else + { + /* Should only get here if one region has already been added to the + heap. */ + configASSERT( pxEnd != NULL ); + + /* Check blocks are passed in with increasing start addresses. */ + configASSERT( ulAddress > ( uint32_t ) pxEnd ); + } + + /* Remember the location of the end marker in the previous region, if + any. */ + pxPreviousFreeBlock = pxEnd; + + /* pxEnd is used to mark the end of the list of free blocks and is + inserted at the end of the region space. */ + ulAddress = ( ( uint32_t ) pucAlignedHeap ) + xTotalRegionSize; + ulAddress -= uxHeapStructSize; + ulAddress &= ~portBYTE_ALIGNMENT_MASK; + pxEnd = ( BlockLink_t * ) ulAddress; + pxEnd->xBlockSize = 0; + pxEnd->pxNextFreeBlock = NULL; + + /* To start with there is a single free block in this region that is + sized to take up the entire heap region minus the space taken by the + free block structure. */ + pxFirstFreeBlockInRegion = ( BlockLink_t * ) pucAlignedHeap; + pxFirstFreeBlockInRegion->xBlockSize = ulAddress - ( uint32_t ) pxFirstFreeBlockInRegion; + pxFirstFreeBlockInRegion->pxNextFreeBlock = pxEnd; + + /* If this is not the first region that makes up the entire heap space + then link the previous region to this region. */ + if( pxPreviousFreeBlock != NULL ) + { + pxPreviousFreeBlock->pxNextFreeBlock = pxFirstFreeBlockInRegion; + } + + xTotalHeapSize += pxFirstFreeBlockInRegion->xBlockSize; + + /* Move onto the next HeapRegion_t structure. */ + xDefinedRegions++; + pxHeapRegion = &( pxHeapRegions[ xDefinedRegions ] ); + } + + xMinimumEverFreeBytesRemaining = xTotalHeapSize; + xFreeBytesRemaining = xTotalHeapSize; + + /* Check something was actually defined before it is accessed. */ + configASSERT( xTotalHeapSize ); + + /* Work out the position of the top bit in a size_t variable. */ + xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 ); +} + diff --git a/component/os/freertos/freertos_v8.1.2/Source/portable/RVDS/ARM_CM3/port.c b/component/os/freertos/freertos_v8.1.2/Source/portable/RVDS/ARM_CM3/port.c new file mode 100644 index 0000000..ccd2511 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/portable/RVDS/ARM_CM3/port.c @@ -0,0 +1,724 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/*----------------------------------------------------------- + * Implementation of functions defined in portable.h for the ARM CM3 port. + *----------------------------------------------------------*/ + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "task.h" + +#ifndef configKERNEL_INTERRUPT_PRIORITY + #define configKERNEL_INTERRUPT_PRIORITY 255 +#endif + +#if configMAX_SYSCALL_INTERRUPT_PRIORITY == 0 + #error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html +#endif + +#ifndef configSYSTICK_CLOCK_HZ + #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ + /* Ensure the SysTick is clocked at the same frequency as the core. */ + #define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) +#else + /* The way the SysTick is clocked is not modified in case it is not the same + as the core. */ + #define portNVIC_SYSTICK_CLK_BIT ( 0 ) +#endif + +/* The __weak attribute does not work as you might expect with the Keil tools +so the configOVERRIDE_DEFAULT_TICK_CONFIGURATION constant must be set to 1 if +the application writer wants to provide their own implementation of +vPortSetupTimerInterrupt(). Ensure configOVERRIDE_DEFAULT_TICK_CONFIGURATION +is defined. */ +#ifndef configOVERRIDE_DEFAULT_TICK_CONFIGURATION + #define configOVERRIDE_DEFAULT_TICK_CONFIGURATION 0 +#endif + +/* Constants required to manipulate the core. Registers first... */ +#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) ) +#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) ) +#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) ) +#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) ) +/* ...then bits in the registers. */ +#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL ) +#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL ) +#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL ) +#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL ) +#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL ) + +/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */ +#define portVECTACTIVE_MASK ( 0x1FUL ) + +#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL ) +#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL ) + +/* Constants required to check the validity of an interrupt priority. */ +#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) +#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) +#define portAIRCR_REG ( * ( ( volatile uint32_t * ) 0xE000ED0C ) ) +#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff ) +#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 ) +#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 ) +#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) +#define portPRIGROUP_SHIFT ( 8UL ) + +/* Constants required to set up the initial stack. */ +#define portINITIAL_XPSR ( 0x01000000 ) + +/* Constants used with memory barrier intrinsics. */ +#define portSY_FULL_READ_WRITE ( 15 ) + +/* The systick is a 24-bit counter. */ +#define portMAX_24_BIT_NUMBER ( 0xffffffUL ) + +/* A fiddle factor to estimate the number of SysTick counts that would have +occurred while the SysTick counter is stopped during tickless idle +calculations. */ +#define portMISSED_COUNTS_FACTOR ( 45UL ) + +/* Each task maintains its own interrupt status in the critical nesting +variable. */ +static UBaseType_t uxCriticalNesting = 0xaaaaaaaa; + +/* + * Setup the timer to generate the tick interrupts. The implementation in this + * file is weak to allow application writers to change the timer used to + * generate the tick interrupt. + */ +void vPortSetupTimerInterrupt( void ); + +/* + * Exception handlers. + */ +void xPortPendSVHandler( void ); +void xPortSysTickHandler( void ); +void vPortSVCHandler( void ); + +/* + * Start first task is a separate function so it can be tested in isolation. + */ +static void prvStartFirstTask( void ); + +/* + * Used to catch tasks that attempt to return from their implementing function. + */ +static void prvTaskExitError( void ); + +/*-----------------------------------------------------------*/ + +/* + * The number of SysTick increments that make up one tick period. + */ +#if configUSE_TICKLESS_IDLE == 1 + static uint32_t ulTimerCountsForOneTick = 0; +#endif /* configUSE_TICKLESS_IDLE */ + +/* + * The maximum number of tick periods that can be suppressed is limited by the + * 24 bit resolution of the SysTick timer. + */ +#if configUSE_TICKLESS_IDLE == 1 + static uint32_t xMaximumPossibleSuppressedTicks = 0; +#endif /* configUSE_TICKLESS_IDLE */ + +/* + * Compensate for the CPU cycles that pass while the SysTick is stopped (low + * power functionality only. + */ +#if configUSE_TICKLESS_IDLE == 1 + static uint32_t ulStoppedTimerCompensation = 0; +#endif /* configUSE_TICKLESS_IDLE */ + +/* + * Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure + * FreeRTOS API functions are not called from interrupts that have been assigned + * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY. + */ +#if ( configASSERT_DEFINED == 1 ) + static uint8_t ucMaxSysCallPriority = 0; + static uint32_t ulMaxPRIGROUPValue = 0; + static const volatile uint8_t * const pcInterruptPriorityRegisters = ( uint8_t * ) portNVIC_IP_REGISTERS_OFFSET_16; +#endif /* configASSERT_DEFINED */ + +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) +{ + /* Simulate the stack frame as it would be created by a context switch + interrupt. */ + pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */ + *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) pxCode; /* PC */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) prvTaskExitError; /* LR */ + + pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ + *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ + pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ + + return pxTopOfStack; +} +/*-----------------------------------------------------------*/ + +static void prvTaskExitError( void ) +{ + /* A function that implements a task must not exit or attempt to return to + its caller as there is nothing to return to. If a task wants to exit it + should instead call vTaskDelete( NULL ). + + Artificially force an assert() to be triggered if configASSERT() is + defined, then stop here so application writers can catch the error. */ + configASSERT( uxCriticalNesting == ~0UL ); + portDISABLE_INTERRUPTS(); + for( ;; ); +} +/*-----------------------------------------------------------*/ + +__asm void vPortSVCHandler( void ) +{ + PRESERVE8 + + ldr r3, =pxCurrentTCB /* Restore the context. */ + ldr r1, [r3] /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ + ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */ + ldmia r0!, {r4-r11} /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ + msr psp, r0 /* Restore the task stack pointer. */ + isb + mov r0, #0 + msr basepri, r0 + orr r14, #0xd + bx r14 +} +/*-----------------------------------------------------------*/ + +__asm void prvStartFirstTask( void ) +{ + PRESERVE8 + + /* Use the NVIC offset register to locate the stack. */ + ldr r0, =0xE000ED08 + ldr r0, [r0] + ldr r0, [r0] + /* Set the msp back to the start of the stack. */ + msr msp, r0 + /* Globally enable interrupts. */ + cpsie i + cpsie f + dsb + isb + /* Call SVC to start the first task. */ + svc 0 + nop + nop +} +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +BaseType_t xPortStartScheduler( void ) +{ + #if( configASSERT_DEFINED == 1 ) + { + volatile uint32_t ulOriginalPriority; + volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); + volatile uint8_t ucMaxPriorityValue; + + /* Determine the maximum priority from which ISR safe FreeRTOS API + functions can be called. ISR safe functions are those that end in + "FromISR". FreeRTOS maintains separate thread and ISR API functions to + ensure interrupt entry is as fast and simple as possible. + + Save the interrupt priority value that is about to be clobbered. */ + ulOriginalPriority = *pucFirstUserPriorityRegister; + + /* Determine the number of priority bits available. First write to all + possible bits. */ + *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE; + + /* Read the value back to see how many bits stuck. */ + ucMaxPriorityValue = *pucFirstUserPriorityRegister; + + /* Use the same mask on the maximum system call priority. */ + ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; + + /* Calculate the maximum acceptable priority group value for the number + of bits read back. */ + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS; + while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) + { + ulMaxPRIGROUPValue--; + ucMaxPriorityValue <<= ( uint8_t ) 0x01; + } + + /* Shift the priority group value back to its position within the AIRCR + register. */ + ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; + ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; + + /* Restore the clobbered interrupt priority register to its original + value. */ + *pucFirstUserPriorityRegister = ulOriginalPriority; + } + #endif /* conifgASSERT_DEFINED */ + + /* Make PendSV and SysTick the lowest priority interrupts. */ + portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI; + portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI; + + /* Start the timer that generates the tick ISR. Interrupts are disabled + here already. */ + vPortSetupTimerInterrupt(); + + /* Initialise the critical nesting count ready for the first task. */ + uxCriticalNesting = 0; + + /* Start the first task. */ + prvStartFirstTask(); + + /* Should not get here! */ + return 0; +} +/*-----------------------------------------------------------*/ + +void vPortEndScheduler( void ) +{ + /* Not implemented in ports where there is nothing to return to. + Artificially force an assert. */ + configASSERT( uxCriticalNesting == 1000UL ); +} +/*-----------------------------------------------------------*/ + +void vPortYield( void ) +{ + /* Set a PendSV to request a context switch. */ + portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; + + /* Barriers are normally not required but do ensure the code is completely + within the specified behaviour for the architecture. */ + __dsb( portSY_FULL_READ_WRITE ); + __isb( portSY_FULL_READ_WRITE ); +} +/*-----------------------------------------------------------*/ + +void vPortEnterCritical( void ) +{ + portDISABLE_INTERRUPTS(); + uxCriticalNesting++; + __dsb( portSY_FULL_READ_WRITE ); + __isb( portSY_FULL_READ_WRITE ); + + /* This is not the interrupt safe version of the enter critical function so + assert() if it is being called from an interrupt context. Only API + functions that end in "FromISR" can be used in an interrupt. Only assert if + the critical nesting count is 1 to protect against recursive calls if the + assert function also uses a critical section. */ + if( uxCriticalNesting == 1 ) + { + configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 ); + } +} +/*-----------------------------------------------------------*/ + +void vPortExitCritical( void ) +{ + configASSERT( uxCriticalNesting ); + uxCriticalNesting--; + if( uxCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } +} +/*-----------------------------------------------------------*/ + +__asm void xPortPendSVHandler( void ) +{ + extern uxCriticalNesting; + extern pxCurrentTCB; + extern vTaskSwitchContext; + + PRESERVE8 + + mrs r0, psp + isb + + ldr r3, =pxCurrentTCB /* Get the location of the current TCB. */ + ldr r2, [r3] + + stmdb r0!, {r4-r11} /* Save the remaining registers. */ + str r0, [r2] /* Save the new top of stack into the first member of the TCB. */ + + stmdb sp!, {r3, r14} + mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY + msr basepri, r0 + bl vTaskSwitchContext + mov r0, #0 + msr basepri, r0 + ldmia sp!, {r3, r14} + + ldr r1, [r3] + ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */ + ldmia r0!, {r4-r11} /* Pop the registers and the critical nesting count. */ + msr psp, r0 + isb + bx r14 + nop +} +/*-----------------------------------------------------------*/ + +void xPortSysTickHandler( void ) +{ + /* The SysTick runs at the lowest interrupt priority, so when this interrupt + executes all interrupts must be unmasked. There is therefore no need to + save and then restore the interrupt mask value as its value is already + known. */ + ( void ) portSET_INTERRUPT_MASK_FROM_ISR(); + { + /* Increment the RTOS tick. */ + if( xTaskIncrementTick() != pdFALSE ) + { + /* A context switch is required. Context switching is performed in + the PendSV interrupt. Pend the PendSV interrupt. */ + portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 ); +} +/*-----------------------------------------------------------*/ + +#if configUSE_TICKLESS_IDLE == 1 + + __weak void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) + { + uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL; + TickType_t xModifiableIdleTime; + + /* Make sure the SysTick reload value does not overflow the counter. */ + if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks ) + { + xExpectedIdleTime = xMaximumPossibleSuppressedTicks; + } + + /* Stop the SysTick momentarily. The time the SysTick is stopped for + is accounted for as best it can be, but using the tickless mode will + inevitably result in some tiny drift of the time maintained by the + kernel with respect to calendar time. */ + portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT; + + /* Calculate the reload value required to wait xExpectedIdleTime + tick periods. -1 is used because this code will execute part way + through one of the tick periods. */ + ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) ); + if( ulReloadValue > ulStoppedTimerCompensation ) + { + ulReloadValue -= ulStoppedTimerCompensation; + } + + /* Enter a critical section but don't use the taskENTER_CRITICAL() + method as that will mask interrupts that should exit sleep mode. */ + __disable_irq(); + + /* If a context switch is pending or a task is waiting for the scheduler + to be unsuspended then abandon the low power entry. */ + if( eTaskConfirmSleepModeStatus() == eAbortSleep ) + { + /* Restart from whatever is left in the count register to complete + this tick period. */ + portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG; + + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + + /* Reset the reload register to the value required for normal tick + periods. */ + portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + + /* Re-enable interrupts - see comments above __disable_irq() call + above. */ + __enable_irq(); + } + else + { + /* Set the new reload value. */ + portNVIC_SYSTICK_LOAD_REG = ulReloadValue; + + /* Clear the SysTick count flag and set the count value back to + zero. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + + /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can + set its parameter to 0 to indicate that its implementation contains + its own wait for interrupt or wait for event instruction, and so wfi + should not be executed again. However, the original expected idle + time variable must remain unmodified, so a copy is taken. */ + xModifiableIdleTime = xExpectedIdleTime; + configPRE_SLEEP_PROCESSING( xModifiableIdleTime ); + if( xModifiableIdleTime > 0 ) + { + __dsb( portSY_FULL_READ_WRITE ); + __wfi(); + __isb( portSY_FULL_READ_WRITE ); + } + configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); + + /* Stop SysTick. Again, the time the SysTick is stopped for is + accounted for as best it can be, but using the tickless mode will + inevitably result in some tiny drift of the time maintained by the + kernel with respect to calendar time. */ + ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG; + portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT ); + + /* Re-enable interrupts - see comments above __disable_irq() call + above. */ + __enable_irq(); + + if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + { + uint32_t ulCalculatedLoadValue; + + /* The tick interrupt has already executed, and the SysTick + count reloaded with ulReloadValue. Reset the + portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick + period. */ + ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG ); + + /* Don't allow a tiny value, or values that have somehow + underflowed because the post sleep hook did something + that took too long. */ + if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) ) + { + ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ); + } + + portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue; + + /* The tick interrupt handler will already have pended the tick + processing in the kernel. As the pending tick will be + processed as soon as this function exits, the tick value + maintained by the tick is stepped forward by one less than the + time spent waiting. */ + ulCompleteTickPeriods = xExpectedIdleTime - 1UL; + } + else + { + /* Something other than the tick interrupt ended the sleep. + Work out how long the sleep lasted rounded to complete tick + periods (not the ulReload value which accounted for part + ticks). */ + ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG; + + /* How many complete tick periods passed while the processor + was waiting? */ + ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick; + + /* The reload value is set to whatever fraction of a single tick + period remains. */ + portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; + } + + /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG + again, then set portNVIC_SYSTICK_LOAD_REG back to its standard + value. The critical section is used to ensure the tick interrupt + can only execute once in the case that the reload register is near + zero. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + portENTER_CRITICAL(); + { + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + vTaskStepTick( ulCompleteTickPeriods ); + portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + } + portEXIT_CRITICAL(); + } + } + +#endif /* #if configUSE_TICKLESS_IDLE */ + +/*-----------------------------------------------------------*/ + +/* + * Setup the SysTick timer to generate the tick interrupts at the required + * frequency. + */ +#if configOVERRIDE_DEFAULT_TICK_CONFIGURATION == 0 + + void vPortSetupTimerInterrupt( void ) + { + /* Calculate the constants required to configure the tick interrupt. */ + #if configUSE_TICKLESS_IDLE == 1 + { + ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ); + xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick; + ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ ); + } + #endif /* configUSE_TICKLESS_IDLE */ + + /* Configure SysTick to interrupt at the requested rate. */ + portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; + portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT ); + } + +#endif /* configOVERRIDE_DEFAULT_TICK_CONFIGURATION */ +/*-----------------------------------------------------------*/ + +__asm uint32_t ulPortSetInterruptMask( void ) +{ + PRESERVE8 + + mrs r0, basepri + mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY + msr basepri, r1 + bx r14 +} +/*-----------------------------------------------------------*/ + +__asm void vPortClearInterruptMask( uint32_t ulNewMask ) +{ + PRESERVE8 + + msr basepri, r0 + bx r14 +} +/*-----------------------------------------------------------*/ + +__asm uint32_t vPortGetIPSR( void ) +{ + PRESERVE8 + + mrs r0, ipsr + bx r14 +} +/*-----------------------------------------------------------*/ + +#if( configASSERT_DEFINED == 1 ) + + void vPortValidateInterruptPriority( void ) + { + uint32_t ulCurrentInterrupt; + uint8_t ucCurrentPriority; + + /* Obtain the number of the currently executing interrupt. */ + ulCurrentInterrupt = vPortGetIPSR(); + + /* Is the interrupt number a user defined interrupt? */ + if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER ) + { + /* Look up the interrupt's priority. */ + ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; + + /* The following assertion will fail if a service routine (ISR) for + an interrupt that has been assigned a priority above + configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API + function. ISR safe FreeRTOS API functions must *only* be called + from interrupts that have been assigned a priority at or below + configMAX_SYSCALL_INTERRUPT_PRIORITY. + + Numerically low interrupt priority numbers represent logically high + interrupt priorities, therefore the priority of the interrupt must + be set to a value equal to or numerically *higher* than + configMAX_SYSCALL_INTERRUPT_PRIORITY. + + Interrupts that use the FreeRTOS API must not be left at their + default priority of zero as that is the highest possible priority, + which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, + and therefore also guaranteed to be invalid. + + FreeRTOS maintains separate thread and ISR API functions to ensure + interrupt entry is as fast and simple as possible. + + The following links provide detailed information: + http://www.freertos.org/RTOS-Cortex-M3-M4.html + http://www.freertos.org/FAQHelp.html */ + configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); + } + + /* Priority grouping: The interrupt controller (NVIC) allows the bits + that define each interrupt's priority to be split between bits that + define the interrupt's pre-emption priority bits and bits that define + the interrupt's sub-priority. For simplicity all bits must be defined + to be pre-emption priority bits. The following assertion will fail if + this is not the case (if some bits represent a sub-priority). + + If the application only uses CMSIS libraries for interrupt + configuration then the correct setting can be achieved on all Cortex-M + devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the + scheduler. Note however that some vendor specific peripheral libraries + assume a non-zero priority group setting, in which cases using a value + of zero will result in unpredicable behaviour. */ + configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); + } + +#endif /* configASSERT_DEFINED */ + + diff --git a/component/os/freertos/freertos_v8.1.2/Source/portable/RVDS/ARM_CM3/portmacro.h b/component/os/freertos/freertos_v8.1.2/Source/portable/RVDS/ARM_CM3/portmacro.h new file mode 100644 index 0000000..1e97c3e --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/portable/RVDS/ARM_CM3/portmacro.h @@ -0,0 +1,185 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +#ifndef PORTMACRO_H +#define PORTMACRO_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*----------------------------------------------------------- + * Port specific definitions. + * + * The settings in this file configure FreeRTOS correctly for the + * given hardware and compiler. + * + * These settings should not be altered. + *----------------------------------------------------------- + */ + +/* Type definitions. */ +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#if( configUSE_16_BIT_TICKS == 1 ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff +#else + typedef uint32_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffffffffUL +#endif +/*-----------------------------------------------------------*/ + +/* Architecture specifics. */ +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +/*-----------------------------------------------------------*/ + +/* Scheduler utilities. */ +extern void vPortYield( void ); +#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) ) +#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) +#define portYIELD() vPortYield() +#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT +#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) +/*-----------------------------------------------------------*/ + +/* Critical section management. */ +extern uint32_t ulPortSetInterruptMask( void ); +extern void vPortClearInterruptMask( uint32_t ulNewMask ); +extern void vPortEnterCritical( void ); +extern void vPortExitCritical( void ); + +#define portDISABLE_INTERRUPTS() ulPortSetInterruptMask() +#define portENABLE_INTERRUPTS() vPortClearInterruptMask( 0 ) +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() +#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x) +/*-----------------------------------------------------------*/ + +/* Tickless idle/low power functionality. */ +#ifndef portSUPPRESS_TICKS_AND_SLEEP + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) +#endif +/*-----------------------------------------------------------*/ + +/* Port specific optimisations. */ +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 +#endif + +#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 + + /* Check the configuration. */ + #if( configMAX_PRIORITIES > 32 ) + #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice. + #endif + + /* Store/clear the ready priorities in a bit map. */ + #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) + #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) + + /*-----------------------------------------------------------*/ + + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __clz( ( uxReadyPriorities ) ) ) + +#endif /* taskRECORD_READY_PRIORITY */ +/*-----------------------------------------------------------*/ + +/* Task function macros as described on the FreeRTOS.org WEB site. These are +not necessary for to use this port. They are defined so the common demo files +(which build with all the ports) will build. */ +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +/*-----------------------------------------------------------*/ + +#ifdef configASSERT + void vPortValidateInterruptPriority( void ); + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() +#endif + +/* portNOP() is not required by this port. */ +#define portNOP() + +#ifdef __cplusplus +} +#endif + +#endif /* PORTMACRO_H */ + diff --git a/component/os/freertos/freertos_v8.1.2/Source/portable/RVDS/ARM_CM4F/port.c b/component/os/freertos/freertos_v8.1.2/Source/portable/RVDS/ARM_CM4F/port.c new file mode 100644 index 0000000..939522b --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/portable/RVDS/ARM_CM4F/port.c @@ -0,0 +1,803 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/*----------------------------------------------------------- + * Implementation of functions defined in portable.h for the ARM CM4F port. + *----------------------------------------------------------*/ + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "task.h" + +#ifndef __TARGET_FPU_VFP + #error This port can only be used when the project options are configured to enable hardware floating point support. +#endif + +#if configMAX_SYSCALL_INTERRUPT_PRIORITY == 0 + #error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html +#endif + +#ifndef configSYSTICK_CLOCK_HZ + #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ + /* Ensure the SysTick is clocked at the same frequency as the core. */ + #define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) +#else + /* The way the SysTick is clocked is not modified in case it is not the same + as the core. */ + #define portNVIC_SYSTICK_CLK_BIT ( 0 ) +#endif + +/* The __weak attribute does not work as you might expect with the Keil tools +so the configOVERRIDE_DEFAULT_TICK_CONFIGURATION constant must be set to 1 if +the application writer wants to provide their own implementation of +vPortSetupTimerInterrupt(). Ensure configOVERRIDE_DEFAULT_TICK_CONFIGURATION +is defined. */ +#ifndef configOVERRIDE_DEFAULT_TICK_CONFIGURATION + #define configOVERRIDE_DEFAULT_TICK_CONFIGURATION 0 +#endif + +/* Constants required to manipulate the core. Registers first... */ +#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) ) +#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) ) +#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) ) +#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) ) +/* ...then bits in the registers. */ +#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL ) +#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL ) +#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL ) +#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL ) +#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL ) + +#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL ) +#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL ) + +/* Constants required to check the validity of an interrupt priority. */ +#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) +#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) +#define portAIRCR_REG ( * ( ( volatile uint32_t * ) 0xE000ED0C ) ) +#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff ) +#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 ) +#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 ) +#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) +#define portPRIGROUP_SHIFT ( 8UL ) + +/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */ +#define portVECTACTIVE_MASK ( 0x1FUL ) + +/* Constants required to manipulate the VFP. */ +#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating point context control register. */ +#define portASPEN_AND_LSPEN_BITS ( 0x3UL << 30UL ) + +/* Constants required to set up the initial stack. */ +#define portINITIAL_XPSR ( 0x01000000 ) +#define portINITIAL_EXEC_RETURN ( 0xfffffffd ) + +/* Constants used with memory barrier intrinsics. */ +#define portSY_FULL_READ_WRITE ( 15 ) + +/* The systick is a 24-bit counter. */ +#define portMAX_24_BIT_NUMBER ( 0xffffffUL ) + +/* A fiddle factor to estimate the number of SysTick counts that would have +occurred while the SysTick counter is stopped during tickless idle +calculations. */ +#define portMISSED_COUNTS_FACTOR ( 45UL ) + +/* Each task maintains its own interrupt status in the critical nesting +variable. */ +static UBaseType_t uxCriticalNesting = 0xaaaaaaaa; + +/* + * Setup the timer to generate the tick interrupts. The implementation in this + * file is weak to allow application writers to change the timer used to + * generate the tick interrupt. + */ +void vPortSetupTimerInterrupt( void ); + +/* + * Exception handlers. + */ +void xPortPendSVHandler( void ); +void xPortSysTickHandler( void ); +void vPortSVCHandler( void ); + +/* + * Start first task is a separate function so it can be tested in isolation. + */ +static void prvStartFirstTask( void ); + +/* + * Functions defined in portasm.s to enable the VFP. + */ +static void prvEnableVFP( void ); + +/* + * Used to catch tasks that attempt to return from their implementing function. + */ +static void prvTaskExitError( void ); + +/*-----------------------------------------------------------*/ + +/* + * The number of SysTick increments that make up one tick period. + */ +#if configUSE_TICKLESS_IDLE == 1 + static uint32_t ulTimerCountsForOneTick = 0; +#endif /* configUSE_TICKLESS_IDLE */ + +/* + * The maximum number of tick periods that can be suppressed is limited by the + * 24 bit resolution of the SysTick timer. + */ +#if configUSE_TICKLESS_IDLE == 1 + static uint32_t xMaximumPossibleSuppressedTicks = 0; +#endif /* configUSE_TICKLESS_IDLE */ + +/* + * Compensate for the CPU cycles that pass while the SysTick is stopped (low + * power functionality only. + */ +#if configUSE_TICKLESS_IDLE == 1 + static uint32_t ulStoppedTimerCompensation = 0; +#endif /* configUSE_TICKLESS_IDLE */ + +/* + * Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure + * FreeRTOS API functions are not called from interrupts that have been assigned + * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY. + */ +#if ( configASSERT_DEFINED == 1 ) + static uint8_t ucMaxSysCallPriority = 0; + static uint32_t ulMaxPRIGROUPValue = 0; + static const volatile uint8_t * const pcInterruptPriorityRegisters = ( uint8_t * ) portNVIC_IP_REGISTERS_OFFSET_16; +#endif /* configASSERT_DEFINED */ + +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) +{ + /* Simulate the stack frame as it would be created by a context switch + interrupt. */ + + /* Offset added to account for the way the MCU uses the stack on entry/exit + of interrupts, and to ensure alignment. */ + pxTopOfStack--; + + *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) pxCode; /* PC */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) prvTaskExitError; /* LR */ + + /* Save code space by skipping register initialisation. */ + pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ + *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ + + /* A save method is being used that requires each task to maintain its + own exec return value. */ + pxTopOfStack--; + *pxTopOfStack = portINITIAL_EXEC_RETURN; + + pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ + + return pxTopOfStack; +} +/*-----------------------------------------------------------*/ + +static void prvTaskExitError( void ) +{ + /* A function that implements a task must not exit or attempt to return to + its caller as there is nothing to return to. If a task wants to exit it + should instead call vTaskDelete( NULL ). + + Artificially force an assert() to be triggered if configASSERT() is + defined, then stop here so application writers can catch the error. */ + configASSERT( uxCriticalNesting == ~0UL ); + portDISABLE_INTERRUPTS(); + for( ;; ); +} +/*-----------------------------------------------------------*/ + +__asm void vPortSVCHandler( void ) +{ + PRESERVE8 + + /* Get the location of the current TCB. */ + ldr r3, =pxCurrentTCB + ldr r1, [r3] + ldr r0, [r1] + /* Pop the core registers. */ + ldmia r0!, {r4-r11, r14} + msr psp, r0 + isb + mov r0, #0 + msr basepri, r0 + bx r14 +} +/*-----------------------------------------------------------*/ + +__asm void prvStartFirstTask( void ) +{ + PRESERVE8 + + /* Use the NVIC offset register to locate the stack. */ + ldr r0, =0xE000ED08 + ldr r0, [r0] + ldr r0, [r0] + /* Set the msp back to the start of the stack. */ + msr msp, r0 + /* Globally enable interrupts. */ + cpsie i + cpsie f + dsb + isb + /* Call SVC to start the first task. */ + svc 0 + nop + nop +} +/*-----------------------------------------------------------*/ + +__asm void prvEnableVFP( void ) +{ + PRESERVE8 + + /* The FPU enable bits are in the CPACR. */ + ldr.w r0, =0xE000ED88 + ldr r1, [r0] + + /* Enable CP10 and CP11 coprocessors, then save back. */ + orr r1, r1, #( 0xf << 20 ) + str r1, [r0] + bx r14 + nop +} +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +BaseType_t xPortStartScheduler( void ) +{ + #if( configASSERT_DEFINED == 1 ) + { + volatile uint32_t ulOriginalPriority; + volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); + volatile uint8_t ucMaxPriorityValue; + + /* Determine the maximum priority from which ISR safe FreeRTOS API + functions can be called. ISR safe functions are those that end in + "FromISR". FreeRTOS maintains separate thread and ISR API functions to + ensure interrupt entry is as fast and simple as possible. + + Save the interrupt priority value that is about to be clobbered. */ + ulOriginalPriority = *pucFirstUserPriorityRegister; + + /* Determine the number of priority bits available. First write to all + possible bits. */ + *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE; + + /* Read the value back to see how many bits stuck. */ + ucMaxPriorityValue = *pucFirstUserPriorityRegister; + + /* Use the same mask on the maximum system call priority. */ + ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; + + /* Calculate the maximum acceptable priority group value for the number + of bits read back. */ + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS; + while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) + { + ulMaxPRIGROUPValue--; + ucMaxPriorityValue <<= ( uint8_t ) 0x01; + } + + /* Shift the priority group value back to its position within the AIRCR + register. */ + ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; + ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; + + /* Restore the clobbered interrupt priority register to its original + value. */ + *pucFirstUserPriorityRegister = ulOriginalPriority; + } + #endif /* conifgASSERT_DEFINED */ + + /* Make PendSV and SysTick the lowest priority interrupts. */ + portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI; + portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI; + + /* Start the timer that generates the tick ISR. Interrupts are disabled + here already. */ + vPortSetupTimerInterrupt(); + + /* Initialise the critical nesting count ready for the first task. */ + uxCriticalNesting = 0; + + /* Ensure the VFP is enabled - it should be anyway. */ + prvEnableVFP(); + + /* Lazy save always. */ + *( portFPCCR ) |= portASPEN_AND_LSPEN_BITS; + + /* Start the first task. */ + prvStartFirstTask(); + + /* Should not get here! */ + return 0; +} +/*-----------------------------------------------------------*/ + +void vPortEndScheduler( void ) +{ + /* Not implemented in ports where there is nothing to return to. + Artificially force an assert. */ + configASSERT( uxCriticalNesting == 1000UL ); +} +/*-----------------------------------------------------------*/ + +void vPortYield( void ) +{ + /* Set a PendSV to request a context switch. */ + portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; + + /* Barriers are normally not required but do ensure the code is completely + within the specified behaviour for the architecture. */ + __dsb( portSY_FULL_READ_WRITE ); + __isb( portSY_FULL_READ_WRITE ); +} +/*-----------------------------------------------------------*/ + +void vPortEnterCritical( void ) +{ + portDISABLE_INTERRUPTS(); + uxCriticalNesting++; + __dsb( portSY_FULL_READ_WRITE ); + __isb( portSY_FULL_READ_WRITE ); + + /* This is not the interrupt safe version of the enter critical function so + assert() if it is being called from an interrupt context. Only API + functions that end in "FromISR" can be used in an interrupt. Only assert if + the critical nesting count is 1 to protect against recursive calls if the + assert function also uses a critical section. */ + if( uxCriticalNesting == 1 ) + { + configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 ); + } +} +/*-----------------------------------------------------------*/ + +void vPortExitCritical( void ) +{ + configASSERT( uxCriticalNesting ); + uxCriticalNesting--; + if( uxCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } +} +/*-----------------------------------------------------------*/ + +__asm void xPortPendSVHandler( void ) +{ + extern uxCriticalNesting; + extern pxCurrentTCB; + extern vTaskSwitchContext; + + PRESERVE8 + + mrs r0, psp + isb + /* Get the location of the current TCB. */ + ldr r3, =pxCurrentTCB + ldr r2, [r3] + + /* Is the task using the FPU context? If so, push high vfp registers. */ + tst r14, #0x10 + it eq + vstmdbeq r0!, {s16-s31} + + /* Save the core registers. */ + stmdb r0!, {r4-r11, r14} + + /* Save the new top of stack into the first member of the TCB. */ + str r0, [r2] + + stmdb sp!, {r3} + mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY + msr basepri, r0 + bl vTaskSwitchContext + mov r0, #0 + msr basepri, r0 + ldmia sp!, {r3} + + /* The first item in pxCurrentTCB is the task top of stack. */ + ldr r1, [r3] + ldr r0, [r1] + + /* Pop the core registers. */ + ldmia r0!, {r4-r11, r14} + + /* Is the task using the FPU context? If so, pop the high vfp registers + too. */ + tst r14, #0x10 + it eq + vldmiaeq r0!, {s16-s31} + + msr psp, r0 + isb + #ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata */ + #if WORKAROUND_PMU_CM001 == 1 + push { r14 } + pop { pc } + nop + #endif + #endif + + bx r14 + nop +} +/*-----------------------------------------------------------*/ + +void xPortSysTickHandler( void ) +{ + /* The SysTick runs at the lowest interrupt priority, so when this interrupt + executes all interrupts must be unmasked. There is therefore no need to + save and then restore the interrupt mask value as its value is already + known. */ + ( void ) portSET_INTERRUPT_MASK_FROM_ISR(); + { + /* Increment the RTOS tick. */ + if( xTaskIncrementTick() != pdFALSE ) + { + /* A context switch is required. Context switching is performed in + the PendSV interrupt. Pend the PendSV interrupt. */ + portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 ); +} +/*-----------------------------------------------------------*/ + +#if configUSE_TICKLESS_IDLE == 1 + + __weak void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) + { + uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL; + TickType_t xModifiableIdleTime; + + /* Make sure the SysTick reload value does not overflow the counter. */ + if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks ) + { + xExpectedIdleTime = xMaximumPossibleSuppressedTicks; + } + + /* Stop the SysTick momentarily. The time the SysTick is stopped for + is accounted for as best it can be, but using the tickless mode will + inevitably result in some tiny drift of the time maintained by the + kernel with respect to calendar time. */ + portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT; + + /* Calculate the reload value required to wait xExpectedIdleTime + tick periods. -1 is used because this code will execute part way + through one of the tick periods. */ + ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) ); + if( ulReloadValue > ulStoppedTimerCompensation ) + { + ulReloadValue -= ulStoppedTimerCompensation; + } + + /* Enter a critical section but don't use the taskENTER_CRITICAL() + method as that will mask interrupts that should exit sleep mode. */ + __disable_irq(); + + /* If a context switch is pending or a task is waiting for the scheduler + to be unsuspended then abandon the low power entry. */ + if( eTaskConfirmSleepModeStatus() == eAbortSleep ) + { + /* Restart from whatever is left in the count register to complete + this tick period. */ + portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG; + + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + + /* Reset the reload register to the value required for normal tick + periods. */ + portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + + /* Re-enable interrupts - see comments above __disable_irq() call + above. */ + __enable_irq(); + } + else + { + /* Set the new reload value. */ + portNVIC_SYSTICK_LOAD_REG = ulReloadValue; + + /* Clear the SysTick count flag and set the count value back to + zero. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + + /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can + set its parameter to 0 to indicate that its implementation contains + its own wait for interrupt or wait for event instruction, and so wfi + should not be executed again. However, the original expected idle + time variable must remain unmodified, so a copy is taken. */ + xModifiableIdleTime = xExpectedIdleTime; + configPRE_SLEEP_PROCESSING( xModifiableIdleTime ); + if( xModifiableIdleTime > 0 ) + { + __dsb( portSY_FULL_READ_WRITE ); + __wfi(); + __isb( portSY_FULL_READ_WRITE ); + } + configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); + + /* Stop SysTick. Again, the time the SysTick is stopped for is + accounted for as best it can be, but using the tickless mode will + inevitably result in some tiny drift of the time maintained by the + kernel with respect to calendar time. */ + ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG; + portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT ); + + /* Re-enable interrupts - see comments above __disable_irq() call + above. */ + __enable_irq(); + + if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + { + uint32_t ulCalculatedLoadValue; + + /* The tick interrupt has already executed, and the SysTick + count reloaded with ulReloadValue. Reset the + portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick + period. */ + ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG ); + + /* Don't allow a tiny value, or values that have somehow + underflowed because the post sleep hook did something + that took too long. */ + if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) ) + { + ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ); + } + + portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue; + + /* The tick interrupt handler will already have pended the tick + processing in the kernel. As the pending tick will be + processed as soon as this function exits, the tick value + maintained by the tick is stepped forward by one less than the + time spent waiting. */ + ulCompleteTickPeriods = xExpectedIdleTime - 1UL; + } + else + { + /* Something other than the tick interrupt ended the sleep. + Work out how long the sleep lasted rounded to complete tick + periods (not the ulReload value which accounted for part + ticks). */ + ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG; + + /* How many complete tick periods passed while the processor + was waiting? */ + ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick; + + /* The reload value is set to whatever fraction of a single tick + period remains. */ + portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; + } + + /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG + again, then set portNVIC_SYSTICK_LOAD_REG back to its standard + value. The critical section is used to ensure the tick interrupt + can only execute once in the case that the reload register is near + zero. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + portENTER_CRITICAL(); + { + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + vTaskStepTick( ulCompleteTickPeriods ); + portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + } + portEXIT_CRITICAL(); + } + } + +#endif /* #if configUSE_TICKLESS_IDLE */ + +/*-----------------------------------------------------------*/ + +/* + * Setup the SysTick timer to generate the tick interrupts at the required + * frequency. + */ +#if configOVERRIDE_DEFAULT_TICK_CONFIGURATION == 0 + + void vPortSetupTimerInterrupt( void ) + { + /* Calculate the constants required to configure the tick interrupt. */ + #if configUSE_TICKLESS_IDLE == 1 + { + ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ); + xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick; + ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ ); + } + #endif /* configUSE_TICKLESS_IDLE */ + + /* Configure SysTick to interrupt at the requested rate. */ + portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; + portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT ); + } + +#endif /* configOVERRIDE_DEFAULT_TICK_CONFIGURATION */ +/*-----------------------------------------------------------*/ + +__asm uint32_t ulPortSetInterruptMask( void ) +{ + PRESERVE8 + + mrs r0, basepri + mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY + msr basepri, r1 + bx r14 +} +/*-----------------------------------------------------------*/ + +__asm void vPortClearInterruptMask( uint32_t ulNewMask ) +{ + PRESERVE8 + + msr basepri, r0 + bx r14 +} +/*-----------------------------------------------------------*/ + +__asm uint32_t vPortGetIPSR( void ) +{ + PRESERVE8 + + mrs r0, ipsr + bx r14 +} +/*-----------------------------------------------------------*/ + +#if( configASSERT_DEFINED == 1 ) + + void vPortValidateInterruptPriority( void ) + { + uint32_t ulCurrentInterrupt; + uint8_t ucCurrentPriority; + + /* Obtain the number of the currently executing interrupt. */ + ulCurrentInterrupt = vPortGetIPSR(); + + /* Is the interrupt number a user defined interrupt? */ + if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER ) + { + /* Look up the interrupt's priority. */ + ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; + + /* The following assertion will fail if a service routine (ISR) for + an interrupt that has been assigned a priority above + configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API + function. ISR safe FreeRTOS API functions must *only* be called + from interrupts that have been assigned a priority at or below + configMAX_SYSCALL_INTERRUPT_PRIORITY. + + Numerically low interrupt priority numbers represent logically high + interrupt priorities, therefore the priority of the interrupt must + be set to a value equal to or numerically *higher* than + configMAX_SYSCALL_INTERRUPT_PRIORITY. + + Interrupts that use the FreeRTOS API must not be left at their + default priority of zero as that is the highest possible priority, + which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, + and therefore also guaranteed to be invalid. + + FreeRTOS maintains separate thread and ISR API functions to ensure + interrupt entry is as fast and simple as possible. + + The following links provide detailed information: + http://www.freertos.org/RTOS-Cortex-M3-M4.html + http://www.freertos.org/FAQHelp.html */ + configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); + } + + /* Priority grouping: The interrupt controller (NVIC) allows the bits + that define each interrupt's priority to be split between bits that + define the interrupt's pre-emption priority bits and bits that define + the interrupt's sub-priority. For simplicity all bits must be defined + to be pre-emption priority bits. The following assertion will fail if + this is not the case (if some bits represent a sub-priority). + + If the application only uses CMSIS libraries for interrupt + configuration then the correct setting can be achieved on all Cortex-M + devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the + scheduler. Note however that some vendor specific peripheral libraries + assume a non-zero priority group setting, in which cases using a value + of zero will result in unpredicable behaviour. */ + configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); + } + +#endif /* configASSERT_DEFINED */ + +void vApplicationStackOverflowHook( xTaskHandle pxTask, signed char *pcTaskName ) +{ + /* This function will be called if a task overflows its stack, if + configCHECK_FOR_STACK_OVERFLOW != 0. It might be that the function + parameters have been corrupted, depending on the severity of the stack + overflow. When this is the case pxCurrentTCB can be inspected in the + debugger to find the offending task. */ + printf("\n\r[%s] STACK OVERFLOW - TaskName(%s)\n\r", __FUNCTION__, pcTaskName); + for( ;; ); +} diff --git a/component/os/freertos/freertos_v8.1.2/Source/portable/RVDS/ARM_CM4F/portmacro.h b/component/os/freertos/freertos_v8.1.2/Source/portable/RVDS/ARM_CM4F/portmacro.h new file mode 100644 index 0000000..91dfb7f --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/portable/RVDS/ARM_CM4F/portmacro.h @@ -0,0 +1,186 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +#ifndef PORTMACRO_H +#define PORTMACRO_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*----------------------------------------------------------- + * Port specific definitions. + * + * The settings in this file configure FreeRTOS correctly for the + * given hardware and compiler. + * + * These settings should not be altered. + *----------------------------------------------------------- + */ + +/* Type definitions. */ +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#if( configUSE_16_BIT_TICKS == 1 ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff +#else + typedef uint32_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffffffffUL +#endif +/*-----------------------------------------------------------*/ + +/* Architecture specifics. */ +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +/*-----------------------------------------------------------*/ + +/* Scheduler utilities. */ +extern void vPortYield( void ); +#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) ) +#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) +#define portYIELD() vPortYield() +#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT +#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) +/*-----------------------------------------------------------*/ + +/* Critical section management. */ +extern uint32_t ulPortSetInterruptMask( void ); +extern void vPortClearInterruptMask( uint32_t ulNewMask ); +extern void vPortEnterCritical( void ); +extern void vPortExitCritical( void ); + +#define portDISABLE_INTERRUPTS() ulPortSetInterruptMask() +#define portENABLE_INTERRUPTS() vPortClearInterruptMask( 0 ) +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() +#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x) + +/*-----------------------------------------------------------*/ + +/* Tickless idle/low power functionality. */ +#ifndef portSUPPRESS_TICKS_AND_SLEEP + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) +#endif +/*-----------------------------------------------------------*/ + +/* Port specific optimisations. */ +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 +#endif + +#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 + + /* Check the configuration. */ + #if 0//( configMAX_PRIORITIES > 32 ) + #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice. + #endif + + /* Store/clear the ready priorities in a bit map. */ + #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) + #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) + + /*-----------------------------------------------------------*/ + + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __clz( ( uxReadyPriorities ) ) ) + +#endif /* taskRECORD_READY_PRIORITY */ +/*-----------------------------------------------------------*/ + +/* Task function macros as described on the FreeRTOS.org WEB site. These are +not necessary for to use this port. They are defined so the common demo files +(which build with all the ports) will build. */ +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +/*-----------------------------------------------------------*/ + +#ifdef configASSERT + void vPortValidateInterruptPriority( void ); + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() +#endif + +/* portNOP() is not required by this port. */ +#define portNOP() + +#ifdef __cplusplus +} +#endif + +#endif /* PORTMACRO_H */ + diff --git a/component/os/freertos/freertos_v8.1.2/Source/queue.c b/component/os/freertos/freertos_v8.1.2/Source/queue.c new file mode 100644 index 0000000..9bc9b4a --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/queue.c @@ -0,0 +1,2439 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#include +#include +#include + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +#if ( configUSE_CO_ROUTINES == 1 ) + #include "croutine.h" +#endif + +/* Lint e961 and e750 are suppressed as a MISRA exception justified because the +MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the +header files above, but not in this file, in order to generate the correct +privileged Vs unprivileged linkage and placement. */ +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */ + + +/* Constants used with the xRxLock and xTxLock structure members. */ +#define queueUNLOCKED ( ( BaseType_t ) -1 ) +#define queueLOCKED_UNMODIFIED ( ( BaseType_t ) 0 ) + +/* When the Queue_t structure is used to represent a base queue its pcHead and +pcTail members are used as pointers into the queue storage area. When the +Queue_t structure is used to represent a mutex pcHead and pcTail pointers are +not necessary, and the pcHead pointer is set to NULL to indicate that the +pcTail pointer actually points to the mutex holder (if any). Map alternative +names to the pcHead and pcTail structure members to ensure the readability of +the code is maintained despite this dual use of two structure members. An +alternative implementation would be to use a union, but use of a union is +against the coding standard (although an exception to the standard has been +permitted where the dual use also significantly changes the type of the +structure member). */ +#define pxMutexHolder pcTail +#define uxQueueType pcHead +#define queueQUEUE_IS_MUTEX NULL + +/* Semaphores do not actually store or copy data, so have an item size of +zero. */ +#define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( ( UBaseType_t ) 0 ) +#define queueMUTEX_GIVE_BLOCK_TIME ( ( TickType_t ) 0U ) + +#if( configUSE_PREEMPTION == 0 ) + /* If the cooperative scheduler is being used then a yield should not be + performed just because a higher priority task has been woken. */ + #define queueYIELD_IF_USING_PREEMPTION() +#else + #define queueYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API() +#endif + +/* + * Definition of the queue used by the scheduler. + * Items are queued by copy, not reference. + */ +typedef struct QueueDefinition +{ + int8_t *pcHead; /*< Points to the beginning of the queue storage area. */ + int8_t *pcTail; /*< Points to the byte at the end of the queue storage area. Once more byte is allocated than necessary to store the queue items, this is used as a marker. */ + int8_t *pcWriteTo; /*< Points to the free next place in the storage area. */ + + union /* Use of a union is an exception to the coding standard to ensure two mutually exclusive structure members don't appear simultaneously (wasting RAM). */ + { + int8_t *pcReadFrom; /*< Points to the last place that a queued item was read from when the structure is used as a queue. */ + UBaseType_t uxRecursiveCallCount;/*< Maintains a count of the number of times a recursive mutex has been recursively 'taken' when the structure is used as a mutex. */ + } u; + + List_t xTasksWaitingToSend; /*< List of tasks that are blocked waiting to post onto this queue. Stored in priority order. */ + List_t xTasksWaitingToReceive; /*< List of tasks that are blocked waiting to read from this queue. Stored in priority order. */ + + volatile UBaseType_t uxMessagesWaiting;/*< The number of items currently in the queue. */ + UBaseType_t uxLength; /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */ + UBaseType_t uxItemSize; /*< The size of each items that the queue will hold. */ + + volatile BaseType_t xRxLock; /*< Stores the number of items received from the queue (removed from the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */ + volatile BaseType_t xTxLock; /*< Stores the number of items transmitted to the queue (added to the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */ + + #if ( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxQueueNumber; + uint8_t ucQueueType; + #endif + + #if ( configUSE_QUEUE_SETS == 1 ) + struct QueueDefinition *pxQueueSetContainer; + #endif + +} xQUEUE; + +/* The old xQUEUE name is maintained above then typedefed to the new Queue_t +name below to enable the use of older kernel aware debuggers. */ +typedef xQUEUE Queue_t; + +/*-----------------------------------------------------------*/ + +/* + * The queue registry is just a means for kernel aware debuggers to locate + * queue structures. It has no other purpose so is an optional component. + */ +#if ( configQUEUE_REGISTRY_SIZE > 0 ) + + /* The type stored within the queue registry array. This allows a name + to be assigned to each queue making kernel aware debugging a little + more user friendly. */ + typedef struct QUEUE_REGISTRY_ITEM + { + const char *pcQueueName; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + QueueHandle_t xHandle; + } xQueueRegistryItem; + + /* The old xQueueRegistryItem name is maintained above then typedefed to the + new xQueueRegistryItem name below to enable the use of older kernel aware + debuggers. */ + typedef xQueueRegistryItem QueueRegistryItem_t; + + /* The queue registry is simply an array of QueueRegistryItem_t structures. + The pcQueueName member of a structure being NULL is indicative of the + array position being vacant. */ + QueueRegistryItem_t xQueueRegistry[ configQUEUE_REGISTRY_SIZE ]; + +#endif /* configQUEUE_REGISTRY_SIZE */ + +/* + * Unlocks a queue locked by a call to prvLockQueue. Locking a queue does not + * prevent an ISR from adding or removing items to the queue, but does prevent + * an ISR from removing tasks from the queue event lists. If an ISR finds a + * queue is locked it will instead increment the appropriate queue lock count + * to indicate that a task may require unblocking. When the queue in unlocked + * these lock counts are inspected, and the appropriate action taken. + */ +static void prvUnlockQueue( Queue_t * const pxQueue ) PRIVILEGED_FUNCTION; + +/* + * Uses a critical section to determine if there is any data in a queue. + * + * @return pdTRUE if the queue contains no items, otherwise pdFALSE. + */ +static BaseType_t prvIsQueueEmpty( const Queue_t *pxQueue ) PRIVILEGED_FUNCTION; + +/* + * Uses a critical section to determine if there is any space in a queue. + * + * @return pdTRUE if there is no space, otherwise pdFALSE; + */ +static BaseType_t prvIsQueueFull( const Queue_t *pxQueue ) PRIVILEGED_FUNCTION; + +/* + * Copies an item into the queue, either at the front of the queue or the + * back of the queue. + */ +static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue, const void *pvItemToQueue, const BaseType_t xPosition ) PRIVILEGED_FUNCTION; + +/* + * Copies an item out of a queue. + */ +static void prvCopyDataFromQueue( Queue_t * const pxQueue, void * const pvBuffer ) PRIVILEGED_FUNCTION; + +#if ( configUSE_QUEUE_SETS == 1 ) + /* + * Checks to see if a queue is a member of a queue set, and if so, notifies + * the queue set that the queue contains data. + */ + static BaseType_t prvNotifyQueueSetContainer( const Queue_t * const pxQueue, const BaseType_t xCopyPosition ) PRIVILEGED_FUNCTION; +#endif + +/*-----------------------------------------------------------*/ + +/* + * Macro to mark a queue as locked. Locking a queue prevents an ISR from + * accessing the queue event lists. + */ +#define prvLockQueue( pxQueue ) \ + taskENTER_CRITICAL(); \ + { \ + if( ( pxQueue )->xRxLock == queueUNLOCKED ) \ + { \ + ( pxQueue )->xRxLock = queueLOCKED_UNMODIFIED; \ + } \ + if( ( pxQueue )->xTxLock == queueUNLOCKED ) \ + { \ + ( pxQueue )->xTxLock = queueLOCKED_UNMODIFIED; \ + } \ + } \ + taskEXIT_CRITICAL() +/*-----------------------------------------------------------*/ + +BaseType_t xQueueGenericReset( QueueHandle_t xQueue, BaseType_t xNewQueue ) +{ +Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + configASSERT( pxQueue ); + + taskENTER_CRITICAL(); + { + pxQueue->pcTail = pxQueue->pcHead + ( pxQueue->uxLength * pxQueue->uxItemSize ); + pxQueue->uxMessagesWaiting = ( UBaseType_t ) 0U; + pxQueue->pcWriteTo = pxQueue->pcHead; + pxQueue->u.pcReadFrom = pxQueue->pcHead + ( ( pxQueue->uxLength - ( UBaseType_t ) 1U ) * pxQueue->uxItemSize ); + pxQueue->xRxLock = queueUNLOCKED; + pxQueue->xTxLock = queueUNLOCKED; + + if( xNewQueue == pdFALSE ) + { + /* If there are tasks blocked waiting to read from the queue, then + the tasks will remain blocked as after this function exits the queue + will still be empty. If there are tasks blocked waiting to write to + the queue, then one should be unblocked as after this function exits + it will be possible to write to it. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE ) + { + queueYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* Ensure the event queues start in the correct state. */ + vListInitialise( &( pxQueue->xTasksWaitingToSend ) ); + vListInitialise( &( pxQueue->xTasksWaitingToReceive ) ); + } + } + taskEXIT_CRITICAL(); + + /* A value is returned for calling semantic consistency with previous + versions. */ + return pdPASS; +} +/*-----------------------------------------------------------*/ + +QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType ) +{ +Queue_t *pxNewQueue; +size_t xQueueSizeInBytes; +QueueHandle_t xReturn = NULL; + + /* Remove compiler warnings about unused parameters should + configUSE_TRACE_FACILITY not be set to 1. */ + ( void ) ucQueueType; + + /* Allocate the new queue structure. */ + if( uxQueueLength > ( UBaseType_t ) 0 ) + { + pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) ); + if( pxNewQueue != NULL ) + { + /* Create the list of pointers to queue items. The queue is one byte + longer than asked for to make wrap checking easier/faster. */ + xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ) + ( size_t ) 1; /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + + pxNewQueue->pcHead = ( int8_t * ) pvPortMalloc( xQueueSizeInBytes ); + if( pxNewQueue->pcHead != NULL ) + { + /* Initialise the queue members as described above where the + queue type is defined. */ + pxNewQueue->uxLength = uxQueueLength; + pxNewQueue->uxItemSize = uxItemSize; + ( void ) xQueueGenericReset( pxNewQueue, pdTRUE ); + + #if ( configUSE_TRACE_FACILITY == 1 ) + { + pxNewQueue->ucQueueType = ucQueueType; + } + #endif /* configUSE_TRACE_FACILITY */ + + #if( configUSE_QUEUE_SETS == 1 ) + { + pxNewQueue->pxQueueSetContainer = NULL; + } + #endif /* configUSE_QUEUE_SETS */ + + traceQUEUE_CREATE( pxNewQueue ); + xReturn = pxNewQueue; + } + else + { + traceQUEUE_CREATE_FAILED( ucQueueType ); + vPortFree( pxNewQueue ); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + configASSERT( xReturn ); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +#if ( configUSE_MUTEXES == 1 ) + + QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType ) + { + Queue_t *pxNewQueue; + + /* Prevent compiler warnings about unused parameters if + configUSE_TRACE_FACILITY does not equal 1. */ + ( void ) ucQueueType; + + /* Allocate the new queue structure. */ + pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) ); + if( pxNewQueue != NULL ) + { + /* Information required for priority inheritance. */ + pxNewQueue->pxMutexHolder = NULL; + pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX; + + /* Queues used as a mutex no data is actually copied into or out + of the queue. */ + pxNewQueue->pcWriteTo = NULL; + pxNewQueue->u.pcReadFrom = NULL; + + /* Each mutex has a length of 1 (like a binary semaphore) and + an item size of 0 as nothing is actually copied into or out + of the mutex. */ + pxNewQueue->uxMessagesWaiting = ( UBaseType_t ) 0U; + pxNewQueue->uxLength = ( UBaseType_t ) 1U; + pxNewQueue->uxItemSize = ( UBaseType_t ) 0U; + pxNewQueue->xRxLock = queueUNLOCKED; + pxNewQueue->xTxLock = queueUNLOCKED; + + #if ( configUSE_TRACE_FACILITY == 1 ) + { + pxNewQueue->ucQueueType = ucQueueType; + } + #endif + + #if ( configUSE_QUEUE_SETS == 1 ) + { + pxNewQueue->pxQueueSetContainer = NULL; + } + #endif + + /* Ensure the event queues start with the correct state. */ + vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) ); + vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) ); + + traceCREATE_MUTEX( pxNewQueue ); + + /* Start with the semaphore in the expected state. */ + ( void ) xQueueGenericSend( pxNewQueue, NULL, ( TickType_t ) 0U, queueSEND_TO_BACK ); + } + else + { + traceCREATE_MUTEX_FAILED(); + } + + configASSERT( pxNewQueue ); + return pxNewQueue; + } + +#endif /* configUSE_MUTEXES */ +/*-----------------------------------------------------------*/ + +#if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) ) + + void* xQueueGetMutexHolder( QueueHandle_t xSemaphore ) + { + void *pxReturn; + + /* This function is called by xSemaphoreGetMutexHolder(), and should not + be called directly. Note: This is a good way of determining if the + calling task is the mutex holder, but not a good way of determining the + identity of the mutex holder, as the holder may change between the + following critical section exiting and the function returning. */ + taskENTER_CRITICAL(); + { + if( ( ( Queue_t * ) xSemaphore )->uxQueueType == queueQUEUE_IS_MUTEX ) + { + pxReturn = ( void * ) ( ( Queue_t * ) xSemaphore )->pxMutexHolder; + } + else + { + pxReturn = NULL; + } + } + taskEXIT_CRITICAL(); + + return pxReturn; + } /*lint !e818 xSemaphore cannot be a pointer to const because it is a typedef. */ + +#endif +/*-----------------------------------------------------------*/ + +#if ( configUSE_RECURSIVE_MUTEXES == 1 ) + + BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex ) + { + BaseType_t xReturn; + Queue_t * const pxMutex = ( Queue_t * ) xMutex; + + configASSERT( pxMutex ); + + /* If this is the task that holds the mutex then pxMutexHolder will not + change outside of this task. If this task does not hold the mutex then + pxMutexHolder can never coincidentally equal the tasks handle, and as + this is the only condition we are interested in it does not matter if + pxMutexHolder is accessed simultaneously by another task. Therefore no + mutual exclusion is required to test the pxMutexHolder variable. */ + if( pxMutex->pxMutexHolder == ( void * ) xTaskGetCurrentTaskHandle() ) /*lint !e961 Not a redundant cast as TaskHandle_t is a typedef. */ + { + traceGIVE_MUTEX_RECURSIVE( pxMutex ); + + /* uxRecursiveCallCount cannot be zero if pxMutexHolder is equal to + the task handle, therefore no underflow check is required. Also, + uxRecursiveCallCount is only modified by the mutex holder, and as + there can only be one, no mutual exclusion is required to modify the + uxRecursiveCallCount member. */ + ( pxMutex->u.uxRecursiveCallCount )--; + + /* Have we unwound the call count? */ + if( pxMutex->u.uxRecursiveCallCount == ( UBaseType_t ) 0 ) + { + /* Return the mutex. This will automatically unblock any other + task that might be waiting to access the mutex. */ + ( void ) xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + xReturn = pdPASS; + } + else + { + /* The mutex cannot be given because the calling task is not the + holder. */ + xReturn = pdFAIL; + + traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex ); + } + + return xReturn; + } + +#endif /* configUSE_RECURSIVE_MUTEXES */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_RECURSIVE_MUTEXES == 1 ) + + BaseType_t xQueueTakeMutexRecursive( QueueHandle_t xMutex, TickType_t xTicksToWait ) + { + BaseType_t xReturn; + Queue_t * const pxMutex = ( Queue_t * ) xMutex; + + configASSERT( pxMutex ); + + /* Comments regarding mutual exclusion as per those within + xQueueGiveMutexRecursive(). */ + + traceTAKE_MUTEX_RECURSIVE( pxMutex ); + + if( pxMutex->pxMutexHolder == ( void * ) xTaskGetCurrentTaskHandle() ) /*lint !e961 Cast is not redundant as TaskHandle_t is a typedef. */ + { + ( pxMutex->u.uxRecursiveCallCount )++; + xReturn = pdPASS; + } + else + { + xReturn = xQueueGenericReceive( pxMutex, NULL, xTicksToWait, pdFALSE ); + + /* pdPASS will only be returned if the mutex was successfully + obtained. The calling task may have entered the Blocked state + before reaching here. */ + if( xReturn == pdPASS ) + { + ( pxMutex->u.uxRecursiveCallCount )++; + } + else + { + traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex ); + } + } + + return xReturn; + } + +#endif /* configUSE_RECURSIVE_MUTEXES */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_COUNTING_SEMAPHORES == 1 ) + + QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount ) + { + QueueHandle_t xHandle; + + configASSERT( uxMaxCount != 0 ); + configASSERT( uxInitialCount <= uxMaxCount ); + + xHandle = xQueueGenericCreate( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_COUNTING_SEMAPHORE ); + + if( xHandle != NULL ) + { + ( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount; + + traceCREATE_COUNTING_SEMAPHORE(); + } + else + { + traceCREATE_COUNTING_SEMAPHORE_FAILED(); + } + + configASSERT( xHandle ); + return xHandle; + } + +#endif /* configUSE_COUNTING_SEMAPHORES */ +/*-----------------------------------------------------------*/ + +BaseType_t xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, const BaseType_t xCopyPosition ) +{ +BaseType_t xEntryTimeSet = pdFALSE, xYieldRequired; +TimeOut_t xTimeOut; +Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + configASSERT( pxQueue ); + configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); + configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) ); + #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) + { + configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); + } + #endif + + + /* This function relaxes the coding standard somewhat to allow return + statements within the function itself. This is done in the interest + of execution time efficiency. */ + for( ;; ) + { + taskENTER_CRITICAL(); + { + /* Is there room on the queue now? The running task must be + the highest priority task wanting to access the queue. If + the head item in the queue is to be overwritten then it does + not matter if the queue is full. */ + if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) ) + { + traceQUEUE_SEND( pxQueue ); + xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); + + #if ( configUSE_QUEUE_SETS == 1 ) + { + if( pxQueue->pxQueueSetContainer != NULL ) + { + if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) == pdTRUE ) + { + /* The queue is a member of a queue set, and posting + to the queue set caused a higher priority task to + unblock. A context switch is required. */ + queueYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* If there was a task waiting for data to arrive on the + queue then unblock it now. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE ) + { + /* The unblocked task has a priority higher than + our own so yield immediately. Yes it is ok to + do this from within the critical section - the + kernel takes care of that. */ + queueYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else if( xYieldRequired != pdFALSE ) + { + /* This path is a special case that will only get + executed if the task was holding multiple mutexes + and the mutexes were given back in an order that is + different to that in which they were taken. */ + queueYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + #else /* configUSE_QUEUE_SETS */ + { + /* If there was a task waiting for data to arrive on the + queue then unblock it now. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE ) + { + /* The unblocked task has a priority higher than + our own so yield immediately. Yes it is ok to do + this from within the critical section - the kernel + takes care of that. */ + queueYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else if( xYieldRequired != pdFALSE ) + { + /* This path is a special case that will only get + executed if the task was holding multiple mutexes and + the mutexes were given back in an order that is + different to that in which they were taken. */ + queueYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_QUEUE_SETS */ + + taskEXIT_CRITICAL(); + return pdPASS; + } + else + { + if( xTicksToWait == ( TickType_t ) 0 ) + { + /* The queue was full and no block time is specified (or + the block time has expired) so leave now. */ + taskEXIT_CRITICAL(); + + /* Return to the original privilege level before exiting + the function. */ + traceQUEUE_SEND_FAILED( pxQueue ); + return errQUEUE_FULL; + } + else if( xEntryTimeSet == pdFALSE ) + { + /* The queue was full and a block time was specified so + configure the timeout structure. */ + vTaskSetTimeOutState( &xTimeOut ); + xEntryTimeSet = pdTRUE; + } + else + { + /* Entry time was already set. */ + mtCOVERAGE_TEST_MARKER(); + } + } + } + taskEXIT_CRITICAL(); + + /* Interrupts and other tasks can send to and receive from the queue + now the critical section has been exited. */ + + vTaskSuspendAll(); + prvLockQueue( pxQueue ); + + /* Update the timeout state to see if it has expired yet. */ + if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) + { + if( prvIsQueueFull( pxQueue ) != pdFALSE ) + { + traceBLOCKING_ON_QUEUE_SEND( pxQueue ); + vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait ); + + /* Unlocking the queue means queue events can effect the + event list. It is possible that interrupts occurring now + remove this task from the event list again - but as the + scheduler is suspended the task will go onto the pending + ready last instead of the actual ready list. */ + prvUnlockQueue( pxQueue ); + + /* Resuming the scheduler will move tasks from the pending + ready list into the ready list - so it is feasible that this + task is already in a ready list before it yields - in which + case the yield will not cause a context switch unless there + is also a higher priority task in the pending ready list. */ + if( xTaskResumeAll() == pdFALSE ) + { + portYIELD_WITHIN_API(); + } + } + else + { + /* Try again. */ + prvUnlockQueue( pxQueue ); + ( void ) xTaskResumeAll(); + } + } + else + { + /* The timeout has expired. */ + prvUnlockQueue( pxQueue ); + ( void ) xTaskResumeAll(); + + /* Return to the original privilege level before exiting the + function. */ + traceQUEUE_SEND_FAILED( pxQueue ); + return errQUEUE_FULL; + } + } +} +/*-----------------------------------------------------------*/ + +#if ( configUSE_ALTERNATIVE_API == 1 ) + + BaseType_t xQueueAltGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, BaseType_t xCopyPosition ) + { + BaseType_t xEntryTimeSet = pdFALSE; + TimeOut_t xTimeOut; + Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + configASSERT( pxQueue ); + configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); + + for( ;; ) + { + taskENTER_CRITICAL(); + { + /* Is there room on the queue now? To be running we must be + the highest priority task wanting to access the queue. */ + if( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) + { + traceQUEUE_SEND( pxQueue ); + prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); + + /* If there was a task waiting for data to arrive on the + queue then unblock it now. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE ) + { + /* The unblocked task has a priority higher than + our own so yield immediately. */ + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + taskEXIT_CRITICAL(); + return pdPASS; + } + else + { + if( xTicksToWait == ( TickType_t ) 0 ) + { + taskEXIT_CRITICAL(); + return errQUEUE_FULL; + } + else if( xEntryTimeSet == pdFALSE ) + { + vTaskSetTimeOutState( &xTimeOut ); + xEntryTimeSet = pdTRUE; + } + } + } + taskEXIT_CRITICAL(); + + taskENTER_CRITICAL(); + { + if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) + { + if( prvIsQueueFull( pxQueue ) != pdFALSE ) + { + traceBLOCKING_ON_QUEUE_SEND( pxQueue ); + vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait ); + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + taskEXIT_CRITICAL(); + traceQUEUE_SEND_FAILED( pxQueue ); + return errQUEUE_FULL; + } + } + taskEXIT_CRITICAL(); + } + } + +#endif /* configUSE_ALTERNATIVE_API */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_ALTERNATIVE_API == 1 ) + + BaseType_t xQueueAltGenericReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait, BaseType_t xJustPeeking ) + { + BaseType_t xEntryTimeSet = pdFALSE; + TimeOut_t xTimeOut; + int8_t *pcOriginalReadPosition; + Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + configASSERT( pxQueue ); + configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); + + for( ;; ) + { + taskENTER_CRITICAL(); + { + if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 ) + { + /* Remember our read position in case we are just peeking. */ + pcOriginalReadPosition = pxQueue->u.pcReadFrom; + + prvCopyDataFromQueue( pxQueue, pvBuffer ); + + if( xJustPeeking == pdFALSE ) + { + traceQUEUE_RECEIVE( pxQueue ); + + /* Data is actually being removed (not just peeked). */ + --( pxQueue->uxMessagesWaiting ); + + #if ( configUSE_MUTEXES == 1 ) + { + if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) + { + /* Record the information required to implement + priority inheritance should it become necessary. */ + pxQueue->pxMutexHolder = ( int8_t * ) xTaskGetCurrentTaskHandle(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif + + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE ) + { + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + else + { + traceQUEUE_PEEK( pxQueue ); + + /* We are not removing the data, so reset our read + pointer. */ + pxQueue->u.pcReadFrom = pcOriginalReadPosition; + + /* The data is being left in the queue, so see if there are + any other tasks waiting for the data. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + /* Tasks that are removed from the event list will get added to + the pending ready list as the scheduler is still suspended. */ + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority than this task. */ + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + taskEXIT_CRITICAL(); + return pdPASS; + } + else + { + if( xTicksToWait == ( TickType_t ) 0 ) + { + taskEXIT_CRITICAL(); + traceQUEUE_RECEIVE_FAILED( pxQueue ); + return errQUEUE_EMPTY; + } + else if( xEntryTimeSet == pdFALSE ) + { + vTaskSetTimeOutState( &xTimeOut ); + xEntryTimeSet = pdTRUE; + } + } + } + taskEXIT_CRITICAL(); + + taskENTER_CRITICAL(); + { + if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) + { + if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) + { + traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ); + + #if ( configUSE_MUTEXES == 1 ) + { + if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) + { + taskENTER_CRITICAL(); + { + vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder ); + } + taskEXIT_CRITICAL(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif + + vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + taskEXIT_CRITICAL(); + traceQUEUE_RECEIVE_FAILED( pxQueue ); + return errQUEUE_EMPTY; + } + } + taskEXIT_CRITICAL(); + } + } + + +#endif /* configUSE_ALTERNATIVE_API */ +/*-----------------------------------------------------------*/ + +BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, const void * const pvItemToQueue, BaseType_t * const pxHigherPriorityTaskWoken, const BaseType_t xCopyPosition ) +{ +BaseType_t xReturn; +UBaseType_t uxSavedInterruptStatus; +Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + configASSERT( pxQueue ); + configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); + configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) ); + + /* RTOS ports that support interrupt nesting have the concept of a maximum + system call (or maximum API call) interrupt priority. Interrupts that are + above the maximum system call priority are kept permanently enabled, even + when the RTOS kernel is in a critical section, but cannot make any calls to + FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h + then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + failure if a FreeRTOS API function is called from an interrupt that has been + assigned a priority above the configured maximum system call priority. + Only FreeRTOS functions that end in FromISR can be called from interrupts + that have been assigned a priority at or (logically) below the maximum + system call interrupt priority. FreeRTOS maintains a separate interrupt + safe API to ensure interrupt entry is as fast and as simple as possible. + More information (albeit Cortex-M specific) is provided on the following + link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ + portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + + /* Similar to xQueueGenericSend, except without blocking if there is no room + in the queue. Also don't directly wake a task that was blocked on a queue + read, instead return a flag to say whether a context switch is required or + not (i.e. has a task with a higher priority than us been woken by this + post). */ + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + { + if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) ) + { + traceQUEUE_SEND_FROM_ISR( pxQueue ); + + if( prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ) != pdFALSE ) + { + /* This is a special case that can only be executed if a task + holds multiple mutexes and then gives the mutexes back in an + order that is different to that in which they were taken. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + /* The event list is not altered if the queue is locked. This will + be done when the queue is unlocked later. */ + if( pxQueue->xTxLock == queueUNLOCKED ) + { + #if ( configUSE_QUEUE_SETS == 1 ) + { + if( pxQueue->pxQueueSetContainer != NULL ) + { + if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) == pdTRUE ) + { + /* The queue is a member of a queue set, and posting + to the queue set caused a higher priority task to + unblock. A context switch is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority so + record that a context switch is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + #else /* configUSE_QUEUE_SETS */ + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority so record that a + context switch is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_QUEUE_SETS */ + } + else + { + /* Increment the lock count so the task that unlocks the queue + knows that data was posted while it was locked. */ + ++( pxQueue->xTxLock ); + } + + xReturn = pdPASS; + } + else + { + traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ); + xReturn = errQUEUE_FULL; + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +BaseType_t xQueueGenericReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait, const BaseType_t xJustPeeking ) +{ +BaseType_t xEntryTimeSet = pdFALSE; +TimeOut_t xTimeOut; +int8_t *pcOriginalReadPosition; +Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + configASSERT( pxQueue ); + configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); + #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) + { + configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); + } + #endif + + /* This function relaxes the coding standard somewhat to allow return + statements within the function itself. This is done in the interest + of execution time efficiency. */ + + for( ;; ) + { + taskENTER_CRITICAL(); + { + /* Is there data in the queue now? To be running we must be + the highest priority task wanting to access the queue. */ + if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 ) + { + /* Remember the read position in case the queue is only being + peeked. */ + pcOriginalReadPosition = pxQueue->u.pcReadFrom; + + prvCopyDataFromQueue( pxQueue, pvBuffer ); + + if( xJustPeeking == pdFALSE ) + { + traceQUEUE_RECEIVE( pxQueue ); + + /* Actually removing data, not just peeking. */ + --( pxQueue->uxMessagesWaiting ); + + #if ( configUSE_MUTEXES == 1 ) + { + if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) + { + /* Record the information required to implement + priority inheritance should it become necessary. */ + pxQueue->pxMutexHolder = ( int8_t * ) pvTaskIncrementMutexHeldCount(); /*lint !e961 Cast is not redundant as TaskHandle_t is a typedef. */ + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_MUTEXES */ + + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE ) + { + queueYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + traceQUEUE_PEEK( pxQueue ); + + /* The data is not being removed, so reset the read + pointer. */ + pxQueue->u.pcReadFrom = pcOriginalReadPosition; + + /* The data is being left in the queue, so see if there are + any other tasks waiting for the data. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + /* Tasks that are removed from the event list will get added to + the pending ready list as the scheduler is still suspended. */ + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority than this task. */ + queueYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + taskEXIT_CRITICAL(); + return pdPASS; + } + else + { + if( xTicksToWait == ( TickType_t ) 0 ) + { + /* The queue was empty and no block time is specified (or + the block time has expired) so leave now. */ + taskEXIT_CRITICAL(); + traceQUEUE_RECEIVE_FAILED( pxQueue ); + return errQUEUE_EMPTY; + } + else if( xEntryTimeSet == pdFALSE ) + { + /* The queue was empty and a block time was specified so + configure the timeout structure. */ + vTaskSetTimeOutState( &xTimeOut ); + xEntryTimeSet = pdTRUE; + } + else + { + /* Entry time was already set. */ + mtCOVERAGE_TEST_MARKER(); + } + } + } + taskEXIT_CRITICAL(); + + /* Interrupts and other tasks can send to and receive from the queue + now the critical section has been exited. */ + + vTaskSuspendAll(); + prvLockQueue( pxQueue ); + + /* Update the timeout state to see if it has expired yet. */ + if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) + { + if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) + { + traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ); + + #if ( configUSE_MUTEXES == 1 ) + { + if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) + { + taskENTER_CRITICAL(); + { + vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder ); + } + taskEXIT_CRITICAL(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif + + vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); + prvUnlockQueue( pxQueue ); + if( xTaskResumeAll() == pdFALSE ) + { + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* Try again. */ + prvUnlockQueue( pxQueue ); + ( void ) xTaskResumeAll(); + } + } + else + { + prvUnlockQueue( pxQueue ); + ( void ) xTaskResumeAll(); + traceQUEUE_RECEIVE_FAILED( pxQueue ); + return errQUEUE_EMPTY; + } + } +} +/*-----------------------------------------------------------*/ + +BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, void * const pvBuffer, BaseType_t * const pxHigherPriorityTaskWoken ) +{ +BaseType_t xReturn; +UBaseType_t uxSavedInterruptStatus; +Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + configASSERT( pxQueue ); + configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); + + /* RTOS ports that support interrupt nesting have the concept of a maximum + system call (or maximum API call) interrupt priority. Interrupts that are + above the maximum system call priority are kept permanently enabled, even + when the RTOS kernel is in a critical section, but cannot make any calls to + FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h + then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + failure if a FreeRTOS API function is called from an interrupt that has been + assigned a priority above the configured maximum system call priority. + Only FreeRTOS functions that end in FromISR can be called from interrupts + that have been assigned a priority at or (logically) below the maximum + system call interrupt priority. FreeRTOS maintains a separate interrupt + safe API to ensure interrupt entry is as fast and as simple as possible. + More information (albeit Cortex-M specific) is provided on the following + link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ + portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + { + /* Cannot block in an ISR, so check there is data available. */ + if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 ) + { + traceQUEUE_RECEIVE_FROM_ISR( pxQueue ); + + prvCopyDataFromQueue( pxQueue, pvBuffer ); + --( pxQueue->uxMessagesWaiting ); + + /* If the queue is locked the event list will not be modified. + Instead update the lock count so the task that unlocks the queue + will know that an ISR has removed data while the queue was + locked. */ + if( pxQueue->xRxLock == queueUNLOCKED ) + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + { + /* The task waiting has a higher priority than us so + force a context switch. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* Increment the lock count so the task that unlocks the queue + knows that data was removed while it was locked. */ + ++( pxQueue->xRxLock ); + } + + xReturn = pdPASS; + } + else + { + xReturn = pdFAIL; + traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue ); + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, void * const pvBuffer ) +{ +BaseType_t xReturn; +UBaseType_t uxSavedInterruptStatus; +int8_t *pcOriginalReadPosition; +Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + configASSERT( pxQueue ); + configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); + + /* RTOS ports that support interrupt nesting have the concept of a maximum + system call (or maximum API call) interrupt priority. Interrupts that are + above the maximum system call priority are kept permanently enabled, even + when the RTOS kernel is in a critical section, but cannot make any calls to + FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h + then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + failure if a FreeRTOS API function is called from an interrupt that has been + assigned a priority above the configured maximum system call priority. + Only FreeRTOS functions that end in FromISR can be called from interrupts + that have been assigned a priority at or (logically) below the maximum + system call interrupt priority. FreeRTOS maintains a separate interrupt + safe API to ensure interrupt entry is as fast and as simple as possible. + More information (albeit Cortex-M specific) is provided on the following + link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ + portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + { + /* Cannot block in an ISR, so check there is data available. */ + if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 ) + { + traceQUEUE_PEEK_FROM_ISR( pxQueue ); + + /* Remember the read position so it can be reset as nothing is + actually being removed from the queue. */ + pcOriginalReadPosition = pxQueue->u.pcReadFrom; + prvCopyDataFromQueue( pxQueue, pvBuffer ); + pxQueue->u.pcReadFrom = pcOriginalReadPosition; + + xReturn = pdPASS; + } + else + { + xReturn = pdFAIL; + traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue ); + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue ) +{ +UBaseType_t uxReturn; + + configASSERT( xQueue ); + + taskENTER_CRITICAL(); + { + uxReturn = ( ( Queue_t * ) xQueue )->uxMessagesWaiting; + } + taskEXIT_CRITICAL(); + + return uxReturn; +} /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */ +/*-----------------------------------------------------------*/ + +UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue ) +{ +UBaseType_t uxReturn; +Queue_t *pxQueue; + + pxQueue = ( Queue_t * ) xQueue; + configASSERT( pxQueue ); + + taskENTER_CRITICAL(); + { + uxReturn = pxQueue->uxLength - pxQueue->uxMessagesWaiting; + } + taskEXIT_CRITICAL(); + + return uxReturn; +} /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */ +/*-----------------------------------------------------------*/ + +UBaseType_t uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue ) +{ +UBaseType_t uxReturn; + + configASSERT( xQueue ); + + uxReturn = ( ( Queue_t * ) xQueue )->uxMessagesWaiting; + + return uxReturn; +} /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */ +/*-----------------------------------------------------------*/ + +void vQueueDelete( QueueHandle_t xQueue ) +{ +Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + configASSERT( pxQueue ); + + traceQUEUE_DELETE( pxQueue ); + #if ( configQUEUE_REGISTRY_SIZE > 0 ) + { + vQueueUnregisterQueue( pxQueue ); + } + #endif + if( pxQueue->pcHead != NULL ) + { + vPortFree( pxQueue->pcHead ); + } + vPortFree( pxQueue ); +} +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + + UBaseType_t uxQueueGetQueueNumber( QueueHandle_t xQueue ) + { + return ( ( Queue_t * ) xQueue )->uxQueueNumber; + } + +#endif /* configUSE_TRACE_FACILITY */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + + void vQueueSetQueueNumber( QueueHandle_t xQueue, UBaseType_t uxQueueNumber ) + { + ( ( Queue_t * ) xQueue )->uxQueueNumber = uxQueueNumber; + } + +#endif /* configUSE_TRACE_FACILITY */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + + uint8_t ucQueueGetQueueType( QueueHandle_t xQueue ) + { + return ( ( Queue_t * ) xQueue )->ucQueueType; + } + +#endif /* configUSE_TRACE_FACILITY */ +/*-----------------------------------------------------------*/ + +static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue, const void *pvItemToQueue, const BaseType_t xPosition ) +{ +BaseType_t xReturn = pdFALSE; + + if( pxQueue->uxItemSize == ( UBaseType_t ) 0 ) + { + #if ( configUSE_MUTEXES == 1 ) + { + if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) + { + /* The mutex is no longer being held. */ + xReturn = xTaskPriorityDisinherit( ( void * ) pxQueue->pxMutexHolder ); + pxQueue->pxMutexHolder = NULL; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_MUTEXES */ + } + else if( xPosition == queueSEND_TO_BACK ) + { + ( void ) memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e418 MISRA exception as the casts are only redundant for some ports, plus previous logic ensures a null pointer can only be passed to memcpy() if the copy size is 0. */ + pxQueue->pcWriteTo += pxQueue->uxItemSize; + if( pxQueue->pcWriteTo >= pxQueue->pcTail ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */ + { + pxQueue->pcWriteTo = pxQueue->pcHead; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + ( void ) memcpy( ( void * ) pxQueue->u.pcReadFrom, pvItemToQueue, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + pxQueue->u.pcReadFrom -= pxQueue->uxItemSize; + if( pxQueue->u.pcReadFrom < pxQueue->pcHead ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */ + { + pxQueue->u.pcReadFrom = ( pxQueue->pcTail - pxQueue->uxItemSize ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + if( xPosition == queueOVERWRITE ) + { + if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 ) + { + /* An item is not being added but overwritten, so subtract + one from the recorded number of items in the queue so when + one is added again below the number of recorded items remains + correct. */ + --( pxQueue->uxMessagesWaiting ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + ++( pxQueue->uxMessagesWaiting ); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +static void prvCopyDataFromQueue( Queue_t * const pxQueue, void * const pvBuffer ) +{ + if( pxQueue->uxItemSize != ( UBaseType_t ) 0 ) + { + pxQueue->u.pcReadFrom += pxQueue->uxItemSize; + if( pxQueue->u.pcReadFrom >= pxQueue->pcTail ) /*lint !e946 MISRA exception justified as use of the relational operator is the cleanest solutions. */ + { + pxQueue->u.pcReadFrom = pxQueue->pcHead; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e418 MISRA exception as the casts are only redundant for some ports. Also previous logic ensures a null pointer can only be passed to memcpy() when the count is 0. */ + } +} +/*-----------------------------------------------------------*/ + +static void prvUnlockQueue( Queue_t * const pxQueue ) +{ + /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */ + + /* The lock counts contains the number of extra data items placed or + removed from the queue while the queue was locked. When a queue is + locked items can be added or removed, but the event lists cannot be + updated. */ + taskENTER_CRITICAL(); + { + /* See if data was added to the queue while it was locked. */ + while( pxQueue->xTxLock > queueLOCKED_UNMODIFIED ) + { + /* Data was posted while the queue was locked. Are any tasks + blocked waiting for data to become available? */ + #if ( configUSE_QUEUE_SETS == 1 ) + { + if( pxQueue->pxQueueSetContainer != NULL ) + { + if( prvNotifyQueueSetContainer( pxQueue, queueSEND_TO_BACK ) == pdTRUE ) + { + /* The queue is a member of a queue set, and posting to + the queue set caused a higher priority task to unblock. + A context switch is required. */ + vTaskMissedYield(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* Tasks that are removed from the event list will get added to + the pending ready list as the scheduler is still suspended. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority so record that a + context switch is required. */ + vTaskMissedYield(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + break; + } + } + } + #else /* configUSE_QUEUE_SETS */ + { + /* Tasks that are removed from the event list will get added to + the pending ready list as the scheduler is still suspended. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority so record that a + context switch is required. */ + vTaskMissedYield(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + break; + } + } + #endif /* configUSE_QUEUE_SETS */ + + --( pxQueue->xTxLock ); + } + + pxQueue->xTxLock = queueUNLOCKED; + } + taskEXIT_CRITICAL(); + + /* Do the same for the Rx lock. */ + taskENTER_CRITICAL(); + { + while( pxQueue->xRxLock > queueLOCKED_UNMODIFIED ) + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + { + vTaskMissedYield(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + --( pxQueue->xRxLock ); + } + else + { + break; + } + } + + pxQueue->xRxLock = queueUNLOCKED; + } + taskEXIT_CRITICAL(); +} +/*-----------------------------------------------------------*/ + +static BaseType_t prvIsQueueEmpty( const Queue_t *pxQueue ) +{ +BaseType_t xReturn; + + taskENTER_CRITICAL(); + { + if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0 ) + { + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + } + taskEXIT_CRITICAL(); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +BaseType_t xQueueIsQueueEmptyFromISR( const QueueHandle_t xQueue ) +{ +BaseType_t xReturn; + + configASSERT( xQueue ); + if( ( ( Queue_t * ) xQueue )->uxMessagesWaiting == ( UBaseType_t ) 0 ) + { + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + + return xReturn; +} /*lint !e818 xQueue could not be pointer to const because it is a typedef. */ +/*-----------------------------------------------------------*/ + +static BaseType_t prvIsQueueFull( const Queue_t *pxQueue ) +{ +BaseType_t xReturn; + + taskENTER_CRITICAL(); + { + if( pxQueue->uxMessagesWaiting == pxQueue->uxLength ) + { + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + } + taskEXIT_CRITICAL(); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) +{ +BaseType_t xReturn; + + configASSERT( xQueue ); + if( ( ( Queue_t * ) xQueue )->uxMessagesWaiting == ( ( Queue_t * ) xQueue )->uxLength ) + { + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + + return xReturn; +} /*lint !e818 xQueue could not be pointer to const because it is a typedef. */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_CO_ROUTINES == 1 ) + + BaseType_t xQueueCRSend( QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait ) + { + BaseType_t xReturn; + Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + /* If the queue is already full we may have to block. A critical section + is required to prevent an interrupt removing something from the queue + between the check to see if the queue is full and blocking on the queue. */ + portDISABLE_INTERRUPTS(); + { + if( prvIsQueueFull( pxQueue ) != pdFALSE ) + { + /* The queue is full - do we want to block or just leave without + posting? */ + if( xTicksToWait > ( TickType_t ) 0 ) + { + /* As this is called from a coroutine we cannot block directly, but + return indicating that we need to block. */ + vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) ); + portENABLE_INTERRUPTS(); + return errQUEUE_BLOCKED; + } + else + { + portENABLE_INTERRUPTS(); + return errQUEUE_FULL; + } + } + } + portENABLE_INTERRUPTS(); + + portDISABLE_INTERRUPTS(); + { + if( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) + { + /* There is room in the queue, copy the data into the queue. */ + prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK ); + xReturn = pdPASS; + + /* Were any co-routines waiting for data to become available? */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + /* In this instance the co-routine could be placed directly + into the ready list as we are within a critical section. + Instead the same pending ready list mechanism is used as if + the event were caused from within an interrupt. */ + if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The co-routine waiting has a higher priority so record + that a yield might be appropriate. */ + xReturn = errQUEUE_YIELD; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + xReturn = errQUEUE_FULL; + } + } + portENABLE_INTERRUPTS(); + + return xReturn; + } + +#endif /* configUSE_CO_ROUTINES */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_CO_ROUTINES == 1 ) + + BaseType_t xQueueCRReceive( QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait ) + { + BaseType_t xReturn; + Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + /* If the queue is already empty we may have to block. A critical section + is required to prevent an interrupt adding something to the queue + between the check to see if the queue is empty and blocking on the queue. */ + portDISABLE_INTERRUPTS(); + { + if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0 ) + { + /* There are no messages in the queue, do we want to block or just + leave with nothing? */ + if( xTicksToWait > ( TickType_t ) 0 ) + { + /* As this is a co-routine we cannot block directly, but return + indicating that we need to block. */ + vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToReceive ) ); + portENABLE_INTERRUPTS(); + return errQUEUE_BLOCKED; + } + else + { + portENABLE_INTERRUPTS(); + return errQUEUE_FULL; + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + portENABLE_INTERRUPTS(); + + portDISABLE_INTERRUPTS(); + { + if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 ) + { + /* Data is available from the queue. */ + pxQueue->u.pcReadFrom += pxQueue->uxItemSize; + if( pxQueue->u.pcReadFrom >= pxQueue->pcTail ) + { + pxQueue->u.pcReadFrom = pxQueue->pcHead; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + --( pxQueue->uxMessagesWaiting ); + ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( unsigned ) pxQueue->uxItemSize ); + + xReturn = pdPASS; + + /* Were any co-routines waiting for space to become available? */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + /* In this instance the co-routine could be placed directly + into the ready list as we are within a critical section. + Instead the same pending ready list mechanism is used as if + the event were caused from within an interrupt. */ + if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + { + xReturn = errQUEUE_YIELD; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + xReturn = pdFAIL; + } + } + portENABLE_INTERRUPTS(); + + return xReturn; + } + +#endif /* configUSE_CO_ROUTINES */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_CO_ROUTINES == 1 ) + + BaseType_t xQueueCRSendFromISR( QueueHandle_t xQueue, const void *pvItemToQueue, BaseType_t xCoRoutinePreviouslyWoken ) + { + Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + /* Cannot block within an ISR so if there is no space on the queue then + exit without doing anything. */ + if( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) + { + prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK ); + + /* We only want to wake one co-routine per ISR, so check that a + co-routine has not already been woken. */ + if( xCoRoutinePreviouslyWoken == pdFALSE ) + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + return pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + return xCoRoutinePreviouslyWoken; + } + +#endif /* configUSE_CO_ROUTINES */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_CO_ROUTINES == 1 ) + + BaseType_t xQueueCRReceiveFromISR( QueueHandle_t xQueue, void *pvBuffer, BaseType_t *pxCoRoutineWoken ) + { + BaseType_t xReturn; + Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + /* We cannot block from an ISR, so check there is data available. If + not then just leave without doing anything. */ + if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 ) + { + /* Copy the data from the queue. */ + pxQueue->u.pcReadFrom += pxQueue->uxItemSize; + if( pxQueue->u.pcReadFrom >= pxQueue->pcTail ) + { + pxQueue->u.pcReadFrom = pxQueue->pcHead; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + --( pxQueue->uxMessagesWaiting ); + ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( unsigned ) pxQueue->uxItemSize ); + + if( ( *pxCoRoutineWoken ) == pdFALSE ) + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + { + *pxCoRoutineWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + xReturn = pdPASS; + } + else + { + xReturn = pdFAIL; + } + + return xReturn; + } + +#endif /* configUSE_CO_ROUTINES */ +/*-----------------------------------------------------------*/ + +#if ( configQUEUE_REGISTRY_SIZE > 0 ) + + void vQueueAddToRegistry( QueueHandle_t xQueue, const char *pcQueueName ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + { + UBaseType_t ux; + + /* See if there is an empty space in the registry. A NULL name denotes + a free slot. */ + for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ ) + { + if( xQueueRegistry[ ux ].pcQueueName == NULL ) + { + /* Store the information on this queue. */ + xQueueRegistry[ ux ].pcQueueName = pcQueueName; + xQueueRegistry[ ux ].xHandle = xQueue; + + traceQUEUE_REGISTRY_ADD( xQueue, pcQueueName ); + break; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + +#endif /* configQUEUE_REGISTRY_SIZE */ +/*-----------------------------------------------------------*/ + +#if ( configQUEUE_REGISTRY_SIZE > 0 ) + + void vQueueUnregisterQueue( QueueHandle_t xQueue ) + { + UBaseType_t ux; + + /* See if the handle of the queue being unregistered in actually in the + registry. */ + for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ ) + { + if( xQueueRegistry[ ux ].xHandle == xQueue ) + { + /* Set the name to NULL to show that this slot if free again. */ + xQueueRegistry[ ux ].pcQueueName = NULL; + break; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */ + +#endif /* configQUEUE_REGISTRY_SIZE */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_TIMERS == 1 ) + + void vQueueWaitForMessageRestricted( QueueHandle_t xQueue, TickType_t xTicksToWait ) + { + Queue_t * const pxQueue = ( Queue_t * ) xQueue; + + /* This function should not be called by application code hence the + 'Restricted' in its name. It is not part of the public API. It is + designed for use by kernel code, and has special calling requirements. + It can result in vListInsert() being called on a list that can only + possibly ever have one item in it, so the list will be fast, but even + so it should be called with the scheduler locked and not from a critical + section. */ + + /* Only do anything if there are no messages in the queue. This function + will not actually cause the task to block, just place it on a blocked + list. It will not block until the scheduler is unlocked - at which + time a yield will be performed. If an item is added to the queue while + the queue is locked, and the calling task blocks on the queue, then the + calling task will be immediately unblocked when the queue is unlocked. */ + prvLockQueue( pxQueue ); + if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0U ) + { + /* There is nothing in the queue, block for the specified period. */ + vTaskPlaceOnEventListRestricted( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + prvUnlockQueue( pxQueue ); + } + +#endif /* configUSE_TIMERS */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_QUEUE_SETS == 1 ) + + QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength ) + { + QueueSetHandle_t pxQueue; + + pxQueue = xQueueGenericCreate( uxEventQueueLength, sizeof( Queue_t * ), queueQUEUE_TYPE_SET ); + + return pxQueue; + } + +#endif /* configUSE_QUEUE_SETS */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_QUEUE_SETS == 1 ) + + BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ) + { + BaseType_t xReturn; + + taskENTER_CRITICAL(); + { + if( ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer != NULL ) + { + /* Cannot add a queue/semaphore to more than one queue set. */ + xReturn = pdFAIL; + } + else if( ( ( Queue_t * ) xQueueOrSemaphore )->uxMessagesWaiting != ( UBaseType_t ) 0 ) + { + /* Cannot add a queue/semaphore to a queue set if there are already + items in the queue/semaphore. */ + xReturn = pdFAIL; + } + else + { + ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer = xQueueSet; + xReturn = pdPASS; + } + } + taskEXIT_CRITICAL(); + + return xReturn; + } + +#endif /* configUSE_QUEUE_SETS */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_QUEUE_SETS == 1 ) + + BaseType_t xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ) + { + BaseType_t xReturn; + Queue_t * const pxQueueOrSemaphore = ( Queue_t * ) xQueueOrSemaphore; + + if( pxQueueOrSemaphore->pxQueueSetContainer != xQueueSet ) + { + /* The queue was not a member of the set. */ + xReturn = pdFAIL; + } + else if( pxQueueOrSemaphore->uxMessagesWaiting != ( UBaseType_t ) 0 ) + { + /* It is dangerous to remove a queue from a set when the queue is + not empty because the queue set will still hold pending events for + the queue. */ + xReturn = pdFAIL; + } + else + { + taskENTER_CRITICAL(); + { + /* The queue is no longer contained in the set. */ + pxQueueOrSemaphore->pxQueueSetContainer = NULL; + } + taskEXIT_CRITICAL(); + xReturn = pdPASS; + } + + return xReturn; + } /*lint !e818 xQueueSet could not be declared as pointing to const as it is a typedef. */ + +#endif /* configUSE_QUEUE_SETS */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_QUEUE_SETS == 1 ) + + QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet, TickType_t const xTicksToWait ) + { + QueueSetMemberHandle_t xReturn = NULL; + + ( void ) xQueueGenericReceive( ( QueueHandle_t ) xQueueSet, &xReturn, xTicksToWait, pdFALSE ); /*lint !e961 Casting from one typedef to another is not redundant. */ + return xReturn; + } + +#endif /* configUSE_QUEUE_SETS */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_QUEUE_SETS == 1 ) + + QueueSetMemberHandle_t xQueueSelectFromSetFromISR( QueueSetHandle_t xQueueSet ) + { + QueueSetMemberHandle_t xReturn = NULL; + + ( void ) xQueueReceiveFromISR( ( QueueHandle_t ) xQueueSet, &xReturn, NULL ); /*lint !e961 Casting from one typedef to another is not redundant. */ + return xReturn; + } + +#endif /* configUSE_QUEUE_SETS */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_QUEUE_SETS == 1 ) + + static BaseType_t prvNotifyQueueSetContainer( const Queue_t * const pxQueue, const BaseType_t xCopyPosition ) + { + Queue_t *pxQueueSetContainer = pxQueue->pxQueueSetContainer; + BaseType_t xReturn = pdFALSE; + + /* This function must be called form a critical section. */ + + configASSERT( pxQueueSetContainer ); + configASSERT( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength ); + + if( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength ) + { + traceQUEUE_SEND( pxQueueSetContainer ); + /* The data copied is the handle of the queue that contains data. */ + xReturn = prvCopyDataToQueue( pxQueueSetContainer, &pxQueue, xCopyPosition ); + + if( listLIST_IS_EMPTY( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority */ + xReturn = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + return xReturn; + } + +#endif /* configUSE_QUEUE_SETS */ + + + + + + + + + + + + diff --git a/component/os/freertos/freertos_v8.1.2/Source/readme.txt b/component/os/freertos/freertos_v8.1.2/Source/readme.txt new file mode 100644 index 0000000..58480c5 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/readme.txt @@ -0,0 +1,17 @@ +Each real time kernel port consists of three files that contain the core kernel +components and are common to every port, and one or more files that are +specific to a particular microcontroller and or compiler. + ++ The FreeRTOS/Source directory contains the three files that are common to +every port - list.c, queue.c and tasks.c. The kernel is contained within these +three files. croutine.c implements the optional co-routine functionality - which +is normally only used on very memory limited systems. + ++ The FreeRTOS/Source/Portable directory contains the files that are specific to +a particular microcontroller and or compiler. + ++ The FreeRTOS/Source/include directory contains the real time kernel header +files. + +See the readme file in the FreeRTOS/Source/Portable directory for more +information. \ No newline at end of file diff --git a/component/os/freertos/freertos_v8.1.2/Source/tasks.c b/component/os/freertos/freertos_v8.1.2/Source/tasks.c new file mode 100644 index 0000000..c8b0ede --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/tasks.c @@ -0,0 +1,3729 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* Standard includes. */ +#include +#include +#include + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +/* FreeRTOS includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "timers.h" +#include "StackMacros.h" + +/* Lint e961 and e750 are suppressed as a MISRA exception justified because the +MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the +header files above, but not in this file, in order to generate the correct +privileged Vs unprivileged linkage and placement. */ +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */ + +#if ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) + /* At the bottom of this file are two optional functions that can be used + to generate human readable text from the raw data generated by the + uxTaskGetSystemState() function. Note the formatting functions are provided + for convenience only, and are NOT considered part of the kernel. */ + #include +#endif /* configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) */ + +/* Sanity check the configuration. */ +#if configUSE_TICKLESS_IDLE != 0 + #if INCLUDE_vTaskSuspend != 1 + #error INCLUDE_vTaskSuspend must be set to 1 if configUSE_TICKLESS_IDLE is not set to 0 + #endif /* INCLUDE_vTaskSuspend */ +#endif /* configUSE_TICKLESS_IDLE */ + +/* + * Defines the size, in words, of the stack allocated to the idle task. + */ +#define tskIDLE_STACK_SIZE configMINIMAL_STACK_SIZE + +#if( configUSE_PREEMPTION == 0 ) + /* If the cooperative scheduler is being used then a yield should not be + performed just because a higher priority task has been woken. */ + #define taskYIELD_IF_USING_PREEMPTION() +#else + #define taskYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API() +#endif + +/* + * Task control block. A task control block (TCB) is allocated for each task, + * and stores task state information, including a pointer to the task's context + * (the task's run time environment, including register values) + */ +typedef struct tskTaskControlBlock +{ + volatile StackType_t *pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */ + + #if ( portUSING_MPU_WRAPPERS == 1 ) + xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */ + #endif + + ListItem_t xGenericListItem; /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */ + ListItem_t xEventListItem; /*< Used to reference a task from an event list. */ + UBaseType_t uxPriority; /*< The priority of the task. 0 is the lowest priority. */ + StackType_t *pxStack; /*< Points to the start of the stack. */ + char pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + + #if ( portSTACK_GROWTH > 0 ) + StackType_t *pxEndOfStack; /*< Points to the end of the stack on architectures where the stack grows up from low memory. */ + #endif + + #if ( portCRITICAL_NESTING_IN_TCB == 1 ) + UBaseType_t uxCriticalNesting; /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */ + #endif + + #if ( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxTCBNumber; /*< Stores a number that increments each time a TCB is created. It allows debuggers to determine when a task has been deleted and then recreated. */ + UBaseType_t uxTaskNumber; /*< Stores a number specifically for use by third party trace code. */ + #endif + + #if ( configUSE_MUTEXES == 1 ) + UBaseType_t uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */ + UBaseType_t uxMutexesHeld; + #endif + + #if ( configUSE_APPLICATION_TASK_TAG == 1 ) + TaskHookFunction_t pxTaskTag; + #endif + + #if ( configGENERATE_RUN_TIME_STATS == 1 ) + uint32_t ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */ + uint32_t ulStartRunTimeCounterOfPeroid; /*< Stores the amount of time the task has spent in the Running state during a peroid start. */ + uint32_t ulEndRunTimeCounterOfPeroid; /*< Stores the amount of time the task has spent in the Running state when a peroid end */ + #endif + + #if ( configUSE_NEWLIB_REENTRANT == 1 ) + /* Allocate a Newlib reent structure that is specific to this task. + Note Newlib support has been included by popular demand, but is not + used by the FreeRTOS maintainers themselves. FreeRTOS is not + responsible for resulting newlib operation. User must be familiar with + newlib and must provide system-wide implementations of the necessary + stubs. Be warned that (at the time of writing) the current newlib design + implements a system-wide malloc() that must be provided with locks. */ + struct _reent xNewLib_reent; + #endif + +} tskTCB; + +/* The old tskTCB name is maintained above then typedefed to the new TCB_t name +below to enable the use of older kernel aware debuggers. */ +typedef tskTCB TCB_t; + +/* + * Some kernel aware debuggers require the data the debugger needs access to to + * be global, rather than file scope. + */ +#ifdef portREMOVE_STATIC_QUALIFIER + #define static +#endif + +/*lint -e956 A manual analysis and inspection has been used to determine which +static variables must be declared volatile. */ + +PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB = NULL; + +/* Lists for ready and blocked tasks. --------------------*/ +PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ];/*< Prioritised ready tasks. */ +PRIVILEGED_DATA static List_t xDelayedTaskList1; /*< Delayed tasks. */ +PRIVILEGED_DATA static List_t xDelayedTaskList2; /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */ +PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList; /*< Points to the delayed task list currently being used. */ +PRIVILEGED_DATA static List_t * volatile pxOverflowDelayedTaskList; /*< Points to the delayed task list currently being used to hold tasks that have overflowed the current tick count. */ +PRIVILEGED_DATA static List_t xPendingReadyList; /*< Tasks that have been readied while the scheduler was suspended. They will be moved to the ready list when the scheduler is resumed. */ + +#if ( INCLUDE_vTaskDelete == 1 ) + + PRIVILEGED_DATA static List_t xTasksWaitingTermination; /*< Tasks that have been deleted - but their memory not yet freed. */ + PRIVILEGED_DATA static volatile UBaseType_t uxTasksDeleted = ( UBaseType_t ) 0U; + +#endif + +#if ( INCLUDE_vTaskSuspend == 1 ) + + PRIVILEGED_DATA static List_t xSuspendedTaskList; /*< Tasks that are currently suspended. */ + +#endif + +#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) + + PRIVILEGED_DATA static TaskHandle_t xIdleTaskHandle = NULL; /*< Holds the handle of the idle task. The idle task is created automatically when the scheduler is started. */ + +#endif + +/* Other file private variables. --------------------------------*/ +PRIVILEGED_DATA static volatile UBaseType_t uxCurrentNumberOfTasks = ( UBaseType_t ) 0U; +PRIVILEGED_DATA static volatile TickType_t xTickCount = ( TickType_t ) 0U; +PRIVILEGED_DATA static volatile UBaseType_t uxTopReadyPriority = tskIDLE_PRIORITY; +PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning = pdFALSE; +PRIVILEGED_DATA static volatile UBaseType_t uxPendedTicks = ( UBaseType_t ) 0U; +PRIVILEGED_DATA static volatile BaseType_t xYieldPending = pdFALSE; +PRIVILEGED_DATA static volatile BaseType_t xNumOfOverflows = ( BaseType_t ) 0; +PRIVILEGED_DATA static UBaseType_t uxTaskNumber = ( UBaseType_t ) 0U; +PRIVILEGED_DATA static volatile TickType_t xNextTaskUnblockTime = portMAX_DELAY; + +/* Context switches are held pending while the scheduler is suspended. Also, +interrupts must not manipulate the xStateListItem of a TCB, or any of the +lists the xStateListItem can be referenced from, if the scheduler is suspended. +If an interrupt needs to unblock a task while the scheduler is suspended then it +moves the task's event list item into the xPendingReadyList, ready for the +kernel to move the task from the pending ready list into the real ready list +when the scheduler is unsuspended. The pending ready list itself can only be +accessed from a critical section. */ +PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended = ( UBaseType_t ) pdFALSE; + +#if ( configGENERATE_RUN_TIME_STATS == 1 ) + + PRIVILEGED_DATA static uint32_t ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */ + PRIVILEGED_DATA static uint32_t ulTotalRunTime = 0UL; /*< Holds the total amount of execution time as defined by the run time counter clock. */ + PRIVILEGED_DATA static uint32_t ulDeltaTotalRunTime = 0UL; /*< Holds the delta total amount of execution time*/ +#endif + +/*lint +e956 */ + +/* Debugging and trace facilities private variables and macros. ------------*/ + +/* + * The value used to fill the stack of a task when the task is created. This + * is used purely for checking the high water mark for tasks. + */ +#define tskSTACK_FILL_BYTE ( 0xa5U ) + +/* + * Macros used by vListTask to indicate which state a task is in. + */ +#define tskBLOCKED_CHAR ( 'B' ) +#define tskREADY_CHAR ( 'R' ) +#define tskDELETED_CHAR ( 'D' ) +#define tskSUSPENDED_CHAR ( 'S' ) + +/*-----------------------------------------------------------*/ + +#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 ) + + /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 0 then task selection is + performed in a generic way that is not optimised to any particular + microcontroller architecture. */ + + /* uxTopReadyPriority holds the priority of the highest priority ready + state task. */ + #define taskRECORD_READY_PRIORITY( uxPriority ) \ + { \ + if( ( uxPriority ) > uxTopReadyPriority ) \ + { \ + uxTopReadyPriority = ( uxPriority ); \ + } \ + } /* taskRECORD_READY_PRIORITY */ + + /*-----------------------------------------------------------*/ + + #define taskSELECT_HIGHEST_PRIORITY_TASK() \ + { \ + /* Find the highest priority queue that contains ready tasks. */ \ + while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) ) \ + { \ + configASSERT( uxTopReadyPriority ); \ + --uxTopReadyPriority; \ + } \ + \ + /* listGET_OWNER_OF_NEXT_ENTRY indexes through the list, so the tasks of \ + the same priority get an equal share of the processor time. */ \ + listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) ); \ + } /* taskSELECT_HIGHEST_PRIORITY_TASK */ + + /*-----------------------------------------------------------*/ + + /* Define away taskRESET_READY_PRIORITY() and portRESET_READY_PRIORITY() as + they are only required when a port optimised method of task selection is + being used. */ + #define taskRESET_READY_PRIORITY( uxPriority ) + #define portRESET_READY_PRIORITY( uxPriority, uxTopReadyPriority ) + +#else /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ + + /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 1 then task selection is + performed in a way that is tailored to the particular microcontroller + architecture being used. */ + + /* A port optimised version is provided. Call the port defined macros. */ + #define taskRECORD_READY_PRIORITY( uxPriority ) portRECORD_READY_PRIORITY( uxPriority, uxTopReadyPriority ) + + /*-----------------------------------------------------------*/ + + #define taskSELECT_HIGHEST_PRIORITY_TASK() \ + { \ + UBaseType_t uxTopPriority; \ + \ + /* Find the highest priority queue that contains ready tasks. */ \ + portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ); \ + configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 ); \ + listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \ + } /* taskSELECT_HIGHEST_PRIORITY_TASK() */ + + /*-----------------------------------------------------------*/ + + /* A port optimised version is provided, call it only if the TCB being reset + is being referenced from a ready list. If it is referenced from a delayed + or suspended list then it won't be in a ready list. */ + #define taskRESET_READY_PRIORITY( uxPriority ) \ + { \ + if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ ( uxPriority ) ] ) ) == ( UBaseType_t ) 0 ) \ + { \ + portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) ); \ + } \ + } + +#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ + +/*-----------------------------------------------------------*/ + +/* pxDelayedTaskList and pxOverflowDelayedTaskList are switched when the tick +count overflows. */ +#define taskSWITCH_DELAYED_LISTS() \ +{ \ + List_t *pxTemp; \ + \ + /* The delayed tasks list should be empty when the lists are switched. */ \ + configASSERT( ( listLIST_IS_EMPTY( pxDelayedTaskList ) ) ); \ + \ + pxTemp = pxDelayedTaskList; \ + pxDelayedTaskList = pxOverflowDelayedTaskList; \ + pxOverflowDelayedTaskList = pxTemp; \ + xNumOfOverflows++; \ + prvResetNextTaskUnblockTime(); \ +} + +/*-----------------------------------------------------------*/ + +/* + * Place the task represented by pxTCB into the appropriate ready list for + * the task. It is inserted at the end of the list. + */ +#define prvAddTaskToReadyList( pxTCB ) \ + traceMOVED_TASK_TO_READY_STATE( pxTCB ) \ + taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \ + vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xGenericListItem ) ) +/*-----------------------------------------------------------*/ + +/* + * Several functions take an TaskHandle_t parameter that can optionally be NULL, + * where NULL is used to indicate that the handle of the currently executing + * task should be used in place of the parameter. This macro simply checks to + * see if the parameter is NULL and returns a pointer to the appropriate TCB. + */ +#define prvGetTCBFromHandle( pxHandle ) ( ( ( pxHandle ) == NULL ) ? ( TCB_t * ) pxCurrentTCB : ( TCB_t * ) ( pxHandle ) ) + +/* The item value of the event list item is normally used to hold the priority +of the task to which it belongs (coded to allow it to be held in reverse +priority order). However, it is occasionally borrowed for other purposes. It +is important its value is not updated due to a task priority change while it is +being used for another purpose. The following bit definition is used to inform +the scheduler that the value should not be changed - in which case it is the +responsibility of whichever module is using the value to ensure it gets set back +to its original value when it is released. */ +#if configUSE_16_BIT_TICKS == 1 + #define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x8000U +#else + #define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x80000000UL +#endif + +/* Callback function prototypes. --------------------------*/ +#if configCHECK_FOR_STACK_OVERFLOW > 0 + extern void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName ); +#endif + +#if configUSE_TICK_HOOK > 0 + extern void vApplicationTickHook( void ); +#endif + +/* File private functions. --------------------------------*/ + +/* + * Utility to ready a TCB for a given task. Mainly just copies the parameters + * into the TCB structure. + */ +static void prvInitialiseTCBVariables( TCB_t * const pxTCB, const char * const pcName, UBaseType_t uxPriority, const MemoryRegion_t * const xRegions, const uint16_t usStackDepth ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + +/** + * Utility task that simply returns pdTRUE if the task referenced by xTask is + * currently in the Suspended state, or pdFALSE if the task referenced by xTask + * is in any other state. + */ +static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION; + +/* + * Utility to ready all the lists used by the scheduler. This is called + * automatically upon the creation of the first task. + */ +static void prvInitialiseTaskLists( void ) PRIVILEGED_FUNCTION; + +/* + * The idle task, which as all tasks is implemented as a never ending loop. + * The idle task is automatically created and added to the ready lists upon + * creation of the first user task. + * + * The portTASK_FUNCTION_PROTO() macro is used to allow port/compiler specific + * language extensions. The equivalent prototype for this function is: + * + * void prvIdleTask( void *pvParameters ); + * + */ +static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters ); + +/* + * Utility to free all memory allocated by the scheduler to hold a TCB, + * including the stack pointed to by the TCB. + * + * This does not free memory allocated by the task itself (i.e. memory + * allocated by calls to pvPortMalloc from within the tasks application code). + */ +#if ( INCLUDE_vTaskDelete == 1 ) + + static void prvDeleteTCB( TCB_t *pxTCB ) PRIVILEGED_FUNCTION; + +#endif + +/* + * Used only by the idle task. This checks to see if anything has been placed + * in the list of tasks waiting to be deleted. If so the task is cleaned up + * and its TCB deleted. + */ +static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION; + +/* + * The currently executing task is entering the Blocked state. Add the task to + * either the current or the overflow delayed task list. + */ +static void prvAddCurrentTaskToDelayedList( const TickType_t xTimeToWake ) PRIVILEGED_FUNCTION; + +/* + * Allocates memory from the heap for a TCB and associated stack. Checks the + * allocation was successful. + */ +static TCB_t *prvAllocateTCBAndStack( const uint16_t usStackDepth, StackType_t * const puxStackBuffer ) PRIVILEGED_FUNCTION; + +/* + * Fills an TaskStatus_t structure with information on each task that is + * referenced from the pxList list (which may be a ready list, a delayed list, + * a suspended list, etc.). + * + * THIS FUNCTION IS INTENDED FOR DEBUGGING ONLY, AND SHOULD NOT BE CALLED FROM + * NORMAL APPLICATION CODE. + */ +#if ( configUSE_TRACE_FACILITY == 1 ) + + static UBaseType_t prvListTaskWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState ) PRIVILEGED_FUNCTION; + +#endif + +/* + * When a task is created, the stack of the task is filled with a known value. + * This function determines the 'high water mark' of the task stack by + * determining how much of the stack remains at the original preset value. + */ +#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) + + static uint16_t prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte ) PRIVILEGED_FUNCTION; + +#endif + +/* + * Return the amount of time, in ticks, that will pass before the kernel will + * next move a task from the Blocked state to the Running state. + * + * This conditional compilation should use inequality to 0, not equality to 1. + * This is to ensure portSUPPRESS_TICKS_AND_SLEEP() can be called when user + * defined low power mode implementations require configUSE_TICKLESS_IDLE to be + * set to a value other than 1. + */ +#if ( configUSE_TICKLESS_IDLE != 0 ) + + static TickType_t prvGetExpectedIdleTime( void ) PRIVILEGED_FUNCTION; + +#endif + +/* + * Set xNextTaskUnblockTime to the time at which the next Blocked state task + * will exit the Blocked state. + */ +static void prvResetNextTaskUnblockTime( void ); + +/*-----------------------------------------------------------*/ + +BaseType_t xTaskGenericCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask, StackType_t * const puxStackBuffer, const MemoryRegion_t * const xRegions ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ +{ +BaseType_t xReturn; +TCB_t * pxNewTCB; + + configASSERT( pxTaskCode ); + configASSERT( ( ( uxPriority & ( ~portPRIVILEGE_BIT ) ) < configMAX_PRIORITIES ) ); + + /* Allocate the memory required by the TCB and stack for the new task, + checking that the allocation was successful. */ + pxNewTCB = prvAllocateTCBAndStack( usStackDepth, puxStackBuffer ); + + if( pxNewTCB != NULL ) + { + StackType_t *pxTopOfStack; + + #if( portUSING_MPU_WRAPPERS == 1 ) + /* Should the task be created in privileged mode? */ + BaseType_t xRunPrivileged; + if( ( uxPriority & portPRIVILEGE_BIT ) != 0U ) + { + xRunPrivileged = pdTRUE; + } + else + { + xRunPrivileged = pdFALSE; + } + uxPriority &= ~portPRIVILEGE_BIT; + #endif /* portUSING_MPU_WRAPPERS == 1 */ + + /* Calculate the top of stack address. This depends on whether the + stack grows from high memory to low (as per the 80x86) or vice versa. + portSTACK_GROWTH is used to make the result positive or negative as + required by the port. */ + #if( portSTACK_GROWTH < 0 ) + { + pxTopOfStack = pxNewTCB->pxStack + ( usStackDepth - ( uint16_t ) 1 ); + pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ( portPOINTER_SIZE_TYPE ) ~portBYTE_ALIGNMENT_MASK ) ); /*lint !e923 MISRA exception. Avoiding casts between pointers and integers is not practical. Size differences accounted for using portPOINTER_SIZE_TYPE type. */ + + /* Check the alignment of the calculated top of stack is correct. */ + configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) ); + } + #else /* portSTACK_GROWTH */ + { + pxTopOfStack = pxNewTCB->pxStack; + + /* Check the alignment of the stack buffer is correct. */ + configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxNewTCB->pxStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) ); + + /* If we want to use stack checking on architectures that use + a positive stack growth direction then we also need to store the + other extreme of the stack space. */ + pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( usStackDepth - 1 ); + } + #endif /* portSTACK_GROWTH */ + + /* Setup the newly allocated TCB with the initial state of the task. */ + prvInitialiseTCBVariables( pxNewTCB, pcName, uxPriority, xRegions, usStackDepth ); + + /* Initialize the TCB stack to look as if the task was already running, + but had been interrupted by the scheduler. The return address is set + to the start of the task function. Once the stack has been initialised + the top of stack variable is updated. */ + #if( portUSING_MPU_WRAPPERS == 1 ) + { + pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged ); + } + #else /* portUSING_MPU_WRAPPERS */ + { + pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters ); + } + #endif /* portUSING_MPU_WRAPPERS */ + + if( ( void * ) pxCreatedTask != NULL ) + { + /* Pass the TCB out - in an anonymous way. The calling function/ + task can use this as a handle to delete the task later if + required.*/ + *pxCreatedTask = ( TaskHandle_t ) pxNewTCB; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Ensure interrupts don't access the task lists while they are being + updated. */ + taskENTER_CRITICAL(); + { + uxCurrentNumberOfTasks++; + if( pxCurrentTCB == NULL ) + { + /* There are no other tasks, or all the other tasks are in + the suspended state - make this the current task. */ + pxCurrentTCB = pxNewTCB; + + if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 ) + { + /* This is the first task to be created so do the preliminary + initialisation required. We will not recover if this call + fails, but we will report the failure. */ + prvInitialiseTaskLists(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* If the scheduler is not already running, make this task the + current task if it is the highest priority task to be created + so far. */ + if( xSchedulerRunning == pdFALSE ) + { + if( pxCurrentTCB->uxPriority <= uxPriority ) + { + pxCurrentTCB = pxNewTCB; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + uxTaskNumber++; + + #if ( configUSE_TRACE_FACILITY == 1 ) + { + /* Add a counter into the TCB for tracing only. */ + pxNewTCB->uxTCBNumber = uxTaskNumber; + } + #endif /* configUSE_TRACE_FACILITY */ + traceTASK_CREATE( pxNewTCB ); + + prvAddTaskToReadyList( pxNewTCB ); + + xReturn = pdPASS; + portSETUP_TCB( pxNewTCB ); + } + taskEXIT_CRITICAL(); + } + else + { + xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; + traceTASK_CREATE_FAILED(); + } + + if( xReturn == pdPASS ) + { + if( xSchedulerRunning != pdFALSE ) + { + /* If the created task is of a higher priority than the current task + then it should run now. */ + if( pxCurrentTCB->uxPriority < uxPriority ) + { + taskYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskDelete == 1 ) + + void vTaskDelete( TaskHandle_t xTaskToDelete ) + { + TCB_t *pxTCB; + + taskENTER_CRITICAL(); + { + /* If null is passed in here then it is the calling task that is + being deleted. */ + pxTCB = prvGetTCBFromHandle( xTaskToDelete ); + + /* Remove task from the ready list and place in the termination list. + This will stop the task from be scheduled. The idle task will check + the termination list and free up any memory allocated by the + scheduler for the TCB and stack. */ + if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 ) + { + taskRESET_READY_PRIORITY( pxTCB->uxPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Is the task waiting on an event also? */ + if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) + { + ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xGenericListItem ) ); + + /* Increment the ucTasksDeleted variable so the idle task knows + there is a task that has been deleted and that it should therefore + check the xTasksWaitingTermination list. */ + ++uxTasksDeleted; + + /* Increment the uxTaskNumberVariable also so kernel aware debuggers + can detect that the task lists need re-generating. */ + uxTaskNumber++; + + traceTASK_DELETE( pxTCB ); + } + taskEXIT_CRITICAL(); + + /* Force a reschedule if it is the currently running task that has just + been deleted. */ + if( xSchedulerRunning != pdFALSE ) + { + if( pxTCB == pxCurrentTCB ) + { + configASSERT( uxSchedulerSuspended == 0 ); + + /* The pre-delete hook is primarily for the Windows simulator, + in which Windows specific clean up operations are performed, + after which it is not possible to yield away from this task - + hence xYieldPending is used to latch that a context switch is + required. */ + portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending ); + portYIELD_WITHIN_API(); + } + else + { + /* Reset the next expected unblock time in case it referred to + the task that has just been deleted. */ + taskENTER_CRITICAL(); + { + prvResetNextTaskUnblockTime(); + } + taskEXIT_CRITICAL(); + } + } + } + +#endif /* INCLUDE_vTaskDelete */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskDelayUntil == 1 ) + + void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement ) + { + TickType_t xTimeToWake; + BaseType_t xAlreadyYielded, xShouldDelay = pdFALSE; + + configASSERT( pxPreviousWakeTime ); + configASSERT( ( xTimeIncrement > 0U ) ); + configASSERT( uxSchedulerSuspended == 0 ); + + vTaskSuspendAll(); + { + /* Minor optimisation. The tick count cannot change in this + block. */ + const TickType_t xConstTickCount = xTickCount; + + /* Generate the tick time at which the task wants to wake. */ + xTimeToWake = *pxPreviousWakeTime + xTimeIncrement; + + if( xConstTickCount < *pxPreviousWakeTime ) + { + /* The tick count has overflowed since this function was + lasted called. In this case the only time we should ever + actually delay is if the wake time has also overflowed, + and the wake time is greater than the tick time. When this + is the case it is as if neither time had overflowed. */ + if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xConstTickCount ) ) + { + xShouldDelay = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* The tick time has not overflowed. In this case we will + delay if either the wake time has overflowed, and/or the + tick time is less than the wake time. */ + if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xConstTickCount ) ) + { + xShouldDelay = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + /* Update the wake time ready for the next call. */ + *pxPreviousWakeTime = xTimeToWake; + + if( xShouldDelay != pdFALSE ) + { + traceTASK_DELAY_UNTIL(); + + /* Remove the task from the ready list before adding it to the + blocked list as the same list item is used for both lists. */ + if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 ) + { + /* The current task must be in a ready list, so there is + no need to check, and the port reset macro can be called + directly. */ + portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + prvAddCurrentTaskToDelayedList( xTimeToWake ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + xAlreadyYielded = xTaskResumeAll(); + + /* Force a reschedule if xTaskResumeAll has not already done so, we may + have put ourselves to sleep. */ + if( xAlreadyYielded == pdFALSE ) + { + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + +#endif /* INCLUDE_vTaskDelayUntil */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskDelay == 1 ) + + void vTaskDelay( const TickType_t xTicksToDelay ) + { + TickType_t xTimeToWake; + BaseType_t xAlreadyYielded = pdFALSE; + + + /* A delay time of zero just forces a reschedule. */ + if( xTicksToDelay > ( TickType_t ) 0U ) + { + configASSERT( uxSchedulerSuspended == 0 ); + vTaskSuspendAll(); + { + traceTASK_DELAY(); + + /* A task that is removed from the event list while the + scheduler is suspended will not get placed in the ready + list or removed from the blocked list until the scheduler + is resumed. + + This task cannot be in an event list as it is the currently + executing task. */ + + /* Calculate the time to wake - this may overflow but this is + not a problem. */ + xTimeToWake = xTickCount + xTicksToDelay; + + /* We must remove ourselves from the ready list before adding + ourselves to the blocked list as the same list item is used for + both lists. */ + if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 ) + { + /* The current task must be in a ready list, so there is + no need to check, and the port reset macro can be called + directly. */ + portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + prvAddCurrentTaskToDelayedList( xTimeToWake ); + } + xAlreadyYielded = xTaskResumeAll(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Force a reschedule if xTaskResumeAll has not already done so, we may + have put ourselves to sleep. */ + if( xAlreadyYielded == pdFALSE ) + { + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + +#endif /* INCLUDE_vTaskDelay */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_eTaskGetState == 1 ) + + eTaskState eTaskGetState( TaskHandle_t xTask ) + { + eTaskState eReturn; + List_t *pxStateList; + const TCB_t * const pxTCB = ( TCB_t * ) xTask; + + configASSERT( pxTCB ); + + if( pxTCB == pxCurrentTCB ) + { + /* The task calling this function is querying its own state. */ + eReturn = eRunning; + } + else + { + taskENTER_CRITICAL(); + { + pxStateList = ( List_t * ) listLIST_ITEM_CONTAINER( &( pxTCB->xGenericListItem ) ); + } + taskEXIT_CRITICAL(); + + if( ( pxStateList == pxDelayedTaskList ) || ( pxStateList == pxOverflowDelayedTaskList ) ) + { + /* The task being queried is referenced from one of the Blocked + lists. */ + eReturn = eBlocked; + } + + #if ( INCLUDE_vTaskSuspend == 1 ) + else if( pxStateList == &xSuspendedTaskList ) + { + /* The task being queried is referenced from the suspended + list. Is it genuinely suspended or is it block + indefinitely? */ + if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL ) + { + eReturn = eSuspended; + } + else + { + eReturn = eBlocked; + } + } + #endif + + #if ( INCLUDE_vTaskDelete == 1 ) + else if( pxStateList == &xTasksWaitingTermination ) + { + /* The task being queried is referenced from the deleted + tasks list. */ + eReturn = eDeleted; + } + #endif + + else + { + /* If the task is not in any other state, it must be in the + Ready (including pending ready) state. */ + eReturn = eReady; + } + } + + return eReturn; + } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */ + +#endif /* INCLUDE_eTaskGetState */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_uxTaskPriorityGet == 1 ) + + UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask ) + { + TCB_t *pxTCB; + UBaseType_t uxReturn; + + taskENTER_CRITICAL(); + { + /* If null is passed in here then we are changing the + priority of the calling function. */ + pxTCB = prvGetTCBFromHandle( xTask ); + uxReturn = pxTCB->uxPriority; + } + taskEXIT_CRITICAL(); + + return uxReturn; + } + +#endif /* INCLUDE_uxTaskPriorityGet */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskPrioritySet == 1 ) + + void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority ) + { + TCB_t *pxTCB; + UBaseType_t uxCurrentBasePriority, uxPriorityUsedOnEntry; + BaseType_t xYieldRequired = pdFALSE; + + configASSERT( ( uxNewPriority < configMAX_PRIORITIES ) ); + + /* Ensure the new priority is valid. */ + if( uxNewPriority >= ( UBaseType_t ) configMAX_PRIORITIES ) + { + uxNewPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + taskENTER_CRITICAL(); + { + /* If null is passed in here then it is the priority of the calling + task that is being changed. */ + pxTCB = prvGetTCBFromHandle( xTask ); + + traceTASK_PRIORITY_SET( pxTCB, uxNewPriority ); + + #if ( configUSE_MUTEXES == 1 ) + { + uxCurrentBasePriority = pxTCB->uxBasePriority; + } + #else + { + uxCurrentBasePriority = pxTCB->uxPriority; + } + #endif + + if( uxCurrentBasePriority != uxNewPriority ) + { + /* The priority change may have readied a task of higher + priority than the calling task. */ + if( uxNewPriority > uxCurrentBasePriority ) + { + if( pxTCB != pxCurrentTCB ) + { + /* The priority of a task other than the currently + running task is being raised. Is the priority being + raised above that of the running task? */ + if( uxNewPriority >= pxCurrentTCB->uxPriority ) + { + xYieldRequired = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* The priority of the running task is being raised, + but the running task must already be the highest + priority task able to run so no yield is required. */ + } + } + else if( pxTCB == pxCurrentTCB ) + { + /* Setting the priority of the running task down means + there may now be another task of higher priority that + is ready to execute. */ + xYieldRequired = pdTRUE; + } + else + { + /* Setting the priority of any other task down does not + require a yield as the running task must be above the + new priority of the task being modified. */ + } + + /* Remember the ready list the task might be referenced from + before its uxPriority member is changed so the + taskRESET_READY_PRIORITY() macro can function correctly. */ + uxPriorityUsedOnEntry = pxTCB->uxPriority; + + #if ( configUSE_MUTEXES == 1 ) + { + /* Only change the priority being used if the task is not + currently using an inherited priority. */ + if( pxTCB->uxBasePriority == pxTCB->uxPriority ) + { + pxTCB->uxPriority = uxNewPriority; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* The base priority gets set whatever. */ + pxTCB->uxBasePriority = uxNewPriority; + } + #else + { + pxTCB->uxPriority = uxNewPriority; + } + #endif + + /* Only reset the event list item value if the value is not + being used for anything else. */ + if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL ) + { + listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxNewPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* If the task is in the blocked or suspended list we need do + nothing more than change it's priority variable. However, if + the task is in a ready list it needs to be removed and placed + in the list appropriate to its new priority. */ + if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xGenericListItem ) ) != pdFALSE ) + { + /* The task is currently in its ready list - remove before adding + it to it's new ready list. As we are in a critical section we + can do this even if the scheduler is suspended. */ + if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 ) + { + /* It is known that the task is in its ready list so + there is no need to check again and the port level + reset macro can be called directly. */ + portRESET_READY_PRIORITY( uxPriorityUsedOnEntry, uxTopReadyPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + prvAddTaskToReadyList( pxTCB ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + if( xYieldRequired == pdTRUE ) + { + taskYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Remove compiler warning about unused variables when the port + optimised task selection is not being used. */ + ( void ) uxPriorityUsedOnEntry; + } + } + taskEXIT_CRITICAL(); + } + +#endif /* INCLUDE_vTaskPrioritySet */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskSuspend == 1 ) + + void vTaskSuspend( TaskHandle_t xTaskToSuspend ) + { + TCB_t *pxTCB; + + taskENTER_CRITICAL(); + { + /* If null is passed in here then it is the running task that is + being suspended. */ + pxTCB = prvGetTCBFromHandle( xTaskToSuspend ); + + traceTASK_SUSPEND( pxTCB ); + + /* Remove task from the ready/delayed list and place in the + suspended list. */ + if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 ) + { + taskRESET_READY_PRIORITY( pxTCB->uxPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Is the task waiting on an event also? */ + if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) + { + ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ); + } + taskEXIT_CRITICAL(); + + if( pxTCB == pxCurrentTCB ) + { + if( xSchedulerRunning != pdFALSE ) + { + /* The current task has just been suspended. */ + configASSERT( uxSchedulerSuspended == 0 ); + portYIELD_WITHIN_API(); + } + else + { + /* The scheduler is not running, but the task that was pointed + to by pxCurrentTCB has just been suspended and pxCurrentTCB + must be adjusted to point to a different task. */ + if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks ) + { + /* No other tasks are ready, so set pxCurrentTCB back to + NULL so when the next task is created pxCurrentTCB will + be set to point to it no matter what its relative priority + is. */ + pxCurrentTCB = NULL; + } + else + { + vTaskSwitchContext(); + } + } + } + else + { + if( xSchedulerRunning != pdFALSE ) + { + /* A task other than the currently running task was suspended, + reset the next expected unblock time in case it referred to the + task that is now in the Suspended state. */ + taskENTER_CRITICAL(); + { + prvResetNextTaskUnblockTime(); + } + taskEXIT_CRITICAL(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + +#endif /* INCLUDE_vTaskSuspend */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskSuspend == 1 ) + + static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ) + { + BaseType_t xReturn = pdFALSE; + const TCB_t * const pxTCB = ( TCB_t * ) xTask; + + /* Accesses xPendingReadyList so must be called from a critical + section. */ + + /* It does not make sense to check if the calling task is suspended. */ + configASSERT( xTask ); + + /* Is the task being resumed actually in the suspended list? */ + if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ) != pdFALSE ) + { + /* Has the task already been resumed from within an ISR? */ + if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) == pdFALSE ) + { + /* Is it in the suspended list because it is in the Suspended + state, or because is is blocked with no timeout? */ + if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE ) + { + xReturn = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + return xReturn; + } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */ + +#endif /* INCLUDE_vTaskSuspend */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskSuspend == 1 ) + + void vTaskResume( TaskHandle_t xTaskToResume ) + { + TCB_t * const pxTCB = ( TCB_t * ) xTaskToResume; + + /* It does not make sense to resume the calling task. */ + configASSERT( xTaskToResume ); + + /* The parameter cannot be NULL as it is impossible to resume the + currently executing task. */ + if( ( pxTCB != NULL ) && ( pxTCB != pxCurrentTCB ) ) + { + taskENTER_CRITICAL(); + { + if( prvTaskIsTaskSuspended( pxTCB ) == pdTRUE ) + { + traceTASK_RESUME( pxTCB ); + + /* As we are in a critical section we can access the ready + lists even if the scheduler is suspended. */ + ( void ) uxListRemove( &( pxTCB->xGenericListItem ) ); + prvAddTaskToReadyList( pxTCB ); + + /* We may have just resumed a higher priority task. */ + if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ) + { + /* This yield may not cause the task just resumed to run, + but will leave the lists in the correct state for the + next yield. */ + taskYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + taskEXIT_CRITICAL(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + +#endif /* INCLUDE_vTaskSuspend */ + +/*-----------------------------------------------------------*/ + +#if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) + + BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume ) + { + BaseType_t xYieldRequired = pdFALSE; + TCB_t * const pxTCB = ( TCB_t * ) xTaskToResume; + UBaseType_t uxSavedInterruptStatus; + + configASSERT( xTaskToResume ); + + /* RTOS ports that support interrupt nesting have the concept of a + maximum system call (or maximum API call) interrupt priority. + Interrupts that are above the maximum system call priority are keep + permanently enabled, even when the RTOS kernel is in a critical section, + but cannot make any calls to FreeRTOS API functions. If configASSERT() + is defined in FreeRTOSConfig.h then + portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + failure if a FreeRTOS API function is called from an interrupt that has + been assigned a priority above the configured maximum system call + priority. Only FreeRTOS functions that end in FromISR can be called + from interrupts that have been assigned a priority at or (logically) + below the maximum system call interrupt priority. FreeRTOS maintains a + separate interrupt safe API to ensure interrupt entry is as fast and as + simple as possible. More information (albeit Cortex-M specific) is + provided on the following link: + http://www.freertos.org/RTOS-Cortex-M3-M4.html */ + portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + { + if( prvTaskIsTaskSuspended( pxTCB ) == pdTRUE ) + { + traceTASK_RESUME_FROM_ISR( pxTCB ); + + /* Check the ready lists can be accessed. */ + if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) + { + /* Ready lists can be accessed so move the task from the + suspended list to the ready list directly. */ + if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ) + { + xYieldRequired = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + ( void ) uxListRemove( &( pxTCB->xGenericListItem ) ); + prvAddTaskToReadyList( pxTCB ); + } + else + { + /* The delayed or ready lists cannot be accessed so the task + is held in the pending ready list until the scheduler is + unsuspended. */ + vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) ); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + + return xYieldRequired; + } + +#endif /* ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) */ +/*-----------------------------------------------------------*/ + +void vTaskStartScheduler( void ) +{ +BaseType_t xReturn; + + /* Add the idle task at the lowest priority. */ + #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) + { + /* Create the idle task, storing its handle in xIdleTaskHandle so it can + be returned by the xTaskGetIdleTaskHandle() function. */ + xReturn = xTaskCreate( prvIdleTask, "IDLE", tskIDLE_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), &xIdleTaskHandle ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */ + } + #else + { + /* Create the idle task without storing its handle. */ + xReturn = xTaskCreate( prvIdleTask, "IDLE", tskIDLE_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), NULL ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */ + } + #endif /* INCLUDE_xTaskGetIdleTaskHandle */ + + #if ( configUSE_TIMERS == 1 ) + { + if( xReturn == pdPASS ) + { + xReturn = xTimerCreateTimerTask(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_TIMERS */ + + if( xReturn == pdPASS ) + { + /* Interrupts are turned off here, to ensure a tick does not occur + before or during the call to xPortStartScheduler(). The stacks of + the created tasks contain a status word with interrupts switched on + so interrupts will automatically get re-enabled when the first task + starts to run. */ + portDISABLE_INTERRUPTS(); + + #if ( configUSE_NEWLIB_REENTRANT == 1 ) + { + /* Switch Newlib's _impure_ptr variable to point to the _reent + structure specific to the task that will run first. */ + _impure_ptr = &( pxCurrentTCB->xNewLib_reent ); + } + #endif /* configUSE_NEWLIB_REENTRANT */ + + xSchedulerRunning = pdTRUE; + xTickCount = ( TickType_t ) 0U; + + /* If configGENERATE_RUN_TIME_STATS is defined then the following + macro must be defined to configure the timer/counter used to generate + the run time counter time base. */ + portCONFIGURE_TIMER_FOR_RUN_TIME_STATS(); + + /* Setting up the timer tick is hardware specific and thus in the + portable interface. */ + if( xPortStartScheduler() != pdFALSE ) + { + /* Should not reach here as if the scheduler is running the + function will not return. */ + } + else + { + /* Should only reach here if a task calls xTaskEndScheduler(). */ + } + } + else + { + /* This line will only be reached if the kernel could not be started, + because there was not enough FreeRTOS heap to create the idle task + or the timer task. */ + configASSERT( xReturn ); + } +} +/*-----------------------------------------------------------*/ + +void vTaskEndScheduler( void ) +{ + /* Stop the scheduler interrupts and call the portable scheduler end + routine so the original ISRs can be restored if necessary. The port + layer must ensure interrupts enable bit is left in the correct state. */ + portDISABLE_INTERRUPTS(); + xSchedulerRunning = pdFALSE; + vPortEndScheduler(); +} +/*----------------------------------------------------------*/ + +void vTaskSuspendAll( void ) +{ + /* A critical section is not required as the variable is of type + BaseType_t. Please read Richard Barry's reply in the following link to a + post in the FreeRTOS support forum before reporting this as a bug! - + http://goo.gl/wu4acr */ + ++uxSchedulerSuspended; +} +/*----------------------------------------------------------*/ + +#if ( configUSE_TICKLESS_IDLE != 0 ) + + static TickType_t prvGetExpectedIdleTime( void ) + { + TickType_t xReturn; + + if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY ) + { + xReturn = 0; + } + else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1 ) + { + /* There are other idle priority tasks in the ready state. If + time slicing is used then the very next tick interrupt must be + processed. */ + xReturn = 0; + } + else + { + xReturn = xNextTaskUnblockTime - xTickCount; + } + + return xReturn; + } + +#endif /* configUSE_TICKLESS_IDLE */ +/*----------------------------------------------------------*/ + +BaseType_t xTaskResumeAll( void ) +{ +TCB_t *pxTCB; +BaseType_t xAlreadyYielded = pdFALSE; + + /* If uxSchedulerSuspended is zero then this function does not match a + previous call to vTaskSuspendAll(). */ + configASSERT( uxSchedulerSuspended ); + + /* It is possible that an ISR caused a task to be removed from an event + list while the scheduler was suspended. If this was the case then the + removed task will have been added to the xPendingReadyList. Once the + scheduler has been resumed it is safe to move all the pending ready + tasks from this list into their appropriate ready list. */ + taskENTER_CRITICAL(); + { + --uxSchedulerSuspended; + + if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) + { + if( uxCurrentNumberOfTasks > ( UBaseType_t ) 0U ) + { + /* Move any readied tasks from the pending list into the + appropriate ready list. */ + while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE ) + { + pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList ) ); + ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); + ( void ) uxListRemove( &( pxTCB->xGenericListItem ) ); + prvAddTaskToReadyList( pxTCB ); + + /* If we have moved a task that has a priority higher than + the current task then we should yield. */ + if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ) + { + xYieldPending = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + /* If any ticks occurred while the scheduler was suspended then + they should be processed now. This ensures the tick count does + not slip, and that any delayed tasks are resumed at the correct + time. */ + if( uxPendedTicks > ( UBaseType_t ) 0U ) + { + while( uxPendedTicks > ( UBaseType_t ) 0U ) + { + if( xTaskIncrementTick() != pdFALSE ) + { + xYieldPending = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + --uxPendedTicks; + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + if( xYieldPending == pdTRUE ) + { + #if( configUSE_PREEMPTION != 0 ) + { + xAlreadyYielded = pdTRUE; + } + #endif + taskYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + taskEXIT_CRITICAL(); + + return xAlreadyYielded; +} +/*-----------------------------------------------------------*/ + +TickType_t xTaskGetTickCount( void ) +{ +TickType_t xTicks; + + /* Critical section required if running on a 16 bit processor. */ + taskENTER_CRITICAL(); + { + xTicks = xTickCount; + } + taskEXIT_CRITICAL(); + + return xTicks; +} +/*-----------------------------------------------------------*/ + +TickType_t xTaskGetTickCountFromISR( void ) +{ +TickType_t xReturn; +UBaseType_t uxSavedInterruptStatus; + + /* RTOS ports that support interrupt nesting have the concept of a maximum + system call (or maximum API call) interrupt priority. Interrupts that are + above the maximum system call priority are kept permanently enabled, even + when the RTOS kernel is in a critical section, but cannot make any calls to + FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h + then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + failure if a FreeRTOS API function is called from an interrupt that has been + assigned a priority above the configured maximum system call priority. + Only FreeRTOS functions that end in FromISR can be called from interrupts + that have been assigned a priority at or (logically) below the maximum + system call interrupt priority. FreeRTOS maintains a separate interrupt + safe API to ensure interrupt entry is as fast and as simple as possible. + More information (albeit Cortex-M specific) is provided on the following + link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ + portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + { + xReturn = xTickCount; + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +UBaseType_t uxTaskGetNumberOfTasks( void ) +{ + /* A critical section is not required because the variables are of type + BaseType_t. */ + return uxCurrentNumberOfTasks; +} +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_pcTaskGetTaskName == 1 ) + + char *pcTaskGetTaskName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + { + TCB_t *pxTCB; + + /* If null is passed in here then the name of the calling task is being queried. */ + pxTCB = prvGetTCBFromHandle( xTaskToQuery ); + configASSERT( pxTCB ); + return &( pxTCB->pcTaskName[ 0 ] ); + } + +#endif /* INCLUDE_pcTaskGetTaskName */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + + UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, uint32_t * const pulTotalRunTime ) + { + UBaseType_t uxTask = 0, uxQueue = configMAX_PRIORITIES; + + vTaskSuspendAll(); + { + /* Is there a space in the array for each task in the system? */ +#if ( configGENERATE_RUN_TIME_STATS == 1 ) + ulDeltaTotalRunTime = 0; +#endif + if( uxArraySize >= uxCurrentNumberOfTasks ) + { + /* Fill in an TaskStatus_t structure with information on each + task in the Ready state. */ + do + { + uxQueue--; + uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[ uxQueue ] ), eReady ); + + } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + + /* Fill in an TaskStatus_t structure with information on each + task in the Blocked state. */ + uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxDelayedTaskList, eBlocked ); + uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxOverflowDelayedTaskList, eBlocked ); + + #if( INCLUDE_vTaskDelete == 1 ) + { + /* Fill in an TaskStatus_t structure with information on + each task that has been deleted but not yet cleaned up. */ + uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xTasksWaitingTermination, eDeleted ); + } + #endif + + #if ( INCLUDE_vTaskSuspend == 1 ) + { + /* Fill in an TaskStatus_t structure with information on + each task in the Suspended state. */ + uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xSuspendedTaskList, eSuspended ); + } + #endif + + #if ( configGENERATE_RUN_TIME_STATS == 1) + { + if( pulTotalRunTime != NULL ) + { + #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE + portALT_GET_RUN_TIME_COUNTER_VALUE( ( *pulTotalRunTime ) ); + #else + *pulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE(); + #endif + } + } + #else + { + if( pulTotalRunTime != NULL ) + { + *pulTotalRunTime = 0; + } + } + #endif + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + ( void ) xTaskResumeAll(); + + return uxTask; + } + +#endif /* configUSE_TRACE_FACILITY */ +/*----------------------------------------------------------*/ + +#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) + + TaskHandle_t xTaskGetIdleTaskHandle( void ) + { + /* If xTaskGetIdleTaskHandle() is called before the scheduler has been + started, then xIdleTaskHandle will be NULL. */ + configASSERT( ( xIdleTaskHandle != NULL ) ); + return xIdleTaskHandle; + } + +#endif /* INCLUDE_xTaskGetIdleTaskHandle */ +/*----------------------------------------------------------*/ + +/* This conditional compilation should use inequality to 0, not equality to 1. +This is to ensure vTaskStepTick() is available when user defined low power mode +implementations require configUSE_TICKLESS_IDLE to be set to a value other than +1. */ +#if ( configUSE_TICKLESS_IDLE != 0 ) + + void vTaskStepTick( const TickType_t xTicksToJump ) + { + /* Correct the tick count value after a period during which the tick + was suppressed. Note this does *not* call the tick hook function for + each stepped tick. */ + configASSERT( ( xTickCount + xTicksToJump ) <= xNextTaskUnblockTime ); + xTickCount += xTicksToJump; + traceINCREASE_TICK_COUNT( xTicksToJump ); + } + +#endif /* configUSE_TICKLESS_IDLE */ +/*----------------------------------------------------------*/ + +#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) ) + static void prvGenerateRunTimeOfPeroid(xList *pxList, portTickType tickTmp) + { + volatile tskTCB *pxNextTCB, *pxFirstTCB; + + /* Write the run time stats of all the TCB's in pxList into the buffer. */ + listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); + do + { + /* Get next TCB in from the list. */ + listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); + + /* Record start&end run time counter. */ + if (tickTmp%(2*portCONFIGURE_STATS_PEROID_VALUE)) + pxNextTCB->ulStartRunTimeCounterOfPeroid = pxNextTCB->ulRunTimeCounter; + else + pxNextTCB->ulEndRunTimeCounterOfPeroid = pxNextTCB->ulRunTimeCounter; + + } while( pxNextTCB != pxFirstTCB ); + } + + static void prvGetRunTimeStatsOfPeroidForTasksInList(portTickType tickTmp) + { + unsigned portBASE_TYPE uxQueue; + + if (tickTmp%portCONFIGURE_STATS_PEROID_VALUE){ + return;//only portCONFIGURE_STATS_PEROID_VALUE + } + + uxQueue = configMAX_PRIORITIES; + + do + { + uxQueue--; + + if( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxQueue ] ) ) == pdFALSE ) + { + prvGenerateRunTimeOfPeroid(( xList * ) &( pxReadyTasksLists[ uxQueue ] ), tickTmp ); + } + }while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); + + if( listLIST_IS_EMPTY( pxDelayedTaskList ) == pdFALSE ) + { + prvGenerateRunTimeOfPeroid(( xList * ) pxDelayedTaskList, tickTmp ); + } + + if( listLIST_IS_EMPTY( pxOverflowDelayedTaskList ) == pdFALSE ) + { + prvGenerateRunTimeOfPeroid(( xList * ) pxOverflowDelayedTaskList, tickTmp ); + } + +#if ( INCLUDE_vTaskDelete == 1 ) + { + if( listLIST_IS_EMPTY( &xTasksWaitingTermination ) == pdFALSE ) + { + prvGenerateRunTimeOfPeroid(&xTasksWaitingTermination, tickTmp ); + } + } +#endif + +#if ( INCLUDE_vTaskSuspend == 1 ) + { + if( listLIST_IS_EMPTY( &xSuspendedTaskList ) == pdFALSE ) + { + prvGenerateRunTimeOfPeroid(&xSuspendedTaskList, tickTmp ); + } + } +#endif + } +#endif + +BaseType_t xTaskIncrementTick( void ) +{ +TCB_t * pxTCB; +TickType_t xItemValue; +BaseType_t xSwitchRequired = pdFALSE; + + /* Called by the portable layer each time a tick interrupt occurs. + Increments the tick then checks to see if the new tick value will cause any + tasks to be unblocked. */ + traceTASK_INCREMENT_TICK( xTickCount ); + if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) + { + /* Increment the RTOS tick, switching the delayed and overflowed + delayed lists if it wraps to 0. */ + ++xTickCount; + + { + /* Minor optimisation. The tick count cannot change in this + block. */ + const TickType_t xConstTickCount = xTickCount; + + if( xConstTickCount == ( TickType_t ) 0U ) + { + taskSWITCH_DELAYED_LISTS(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* See if this tick has made a timeout expire. Tasks are stored in + the queue in the order of their wake time - meaning once one task + has been found whose block time has not expired there is no need to + look any further down the list. */ + if( xConstTickCount >= xNextTaskUnblockTime ) + { + for( ;; ) + { + if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ) + { + /* The delayed list is empty. Set xNextTaskUnblockTime + to the maximum possible value so it is extremely + unlikely that the + if( xTickCount >= xNextTaskUnblockTime ) test will pass + next time through. */ + xNextTaskUnblockTime = portMAX_DELAY; + break; + } + else + { + /* The delayed list is not empty, get the value of the + item at the head of the delayed list. This is the time + at which the task at the head of the delayed list must + be removed from the Blocked state. */ + pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); + xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) ); + + if( xConstTickCount < xItemValue ) + { + /* It is not time to unblock this item yet, but the + item value is the time at which the task at the head + of the blocked list must be removed from the Blocked + state - so record the item value in + xNextTaskUnblockTime. */ + xNextTaskUnblockTime = xItemValue; + break; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* It is time to remove the item from the Blocked state. */ + ( void ) uxListRemove( &( pxTCB->xGenericListItem ) ); + + /* Is the task waiting on an event also? If so remove + it from the event list. */ + if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) + { + ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Place the unblocked task into the appropriate ready + list. */ + prvAddTaskToReadyList( pxTCB ); + + /* A task being unblocked cannot cause an immediate + context switch if preemption is turned off. */ + #if ( configUSE_PREEMPTION == 1 ) + { + /* Preemption is on, but a context switch should + only be performed if the unblocked task has a + priority that is equal to or higher than the + currently executing task. */ + if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ) + { + xSwitchRequired = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_PREEMPTION */ + } + } + } + } + + /* Tasks of equal priority to the currently running task will share + processing time (time slice) if preemption is on, and the application + writer has not explicitly turned time slicing off. */ + #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) + { + if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > ( UBaseType_t ) 1 ) + { + xSwitchRequired = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */ + + #if ( configUSE_TICK_HOOK == 1 ) + { + /* Guard against the tick hook being called when the pended tick + count is being unwound (when the scheduler is being unlocked). */ + if( uxPendedTicks == ( UBaseType_t ) 0U ) + { + vApplicationTickHook(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_TICK_HOOK */ + } + else + { + ++uxPendedTicks; + + /* The tick hook gets called at regular intervals, even if the + scheduler is locked. */ + #if ( configUSE_TICK_HOOK == 1 ) + { + vApplicationTickHook(); + } + #endif + } + #if ( configGENERATE_RUN_TIME_STATS == 1 ) + prvGetRunTimeStatsOfPeroidForTasksInList(xTickCount); + #endif + + #if ( configUSE_PREEMPTION == 1 ) + { + if( xYieldPending != pdFALSE ) + { + xSwitchRequired = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_PREEMPTION */ + + return xSwitchRequired; +} +/*-----------------------------------------------------------*/ + +#if ( configUSE_APPLICATION_TASK_TAG == 1 ) + + void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction ) + { + TCB_t *xTCB; + + /* If xTask is NULL then it is the task hook of the calling task that is + getting set. */ + if( xTask == NULL ) + { + xTCB = ( TCB_t * ) pxCurrentTCB; + } + else + { + xTCB = ( TCB_t * ) xTask; + } + + /* Save the hook function in the TCB. A critical section is required as + the value can be accessed from an interrupt. */ + taskENTER_CRITICAL(); + xTCB->pxTaskTag = pxHookFunction; + taskEXIT_CRITICAL(); + } + +#endif /* configUSE_APPLICATION_TASK_TAG */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_APPLICATION_TASK_TAG == 1 ) + + TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask ) + { + TCB_t *xTCB; + TaskHookFunction_t xReturn; + + /* If xTask is NULL then we are setting our own task hook. */ + if( xTask == NULL ) + { + xTCB = ( TCB_t * ) pxCurrentTCB; + } + else + { + xTCB = ( TCB_t * ) xTask; + } + + /* Save the hook function in the TCB. A critical section is required as + the value can be accessed from an interrupt. */ + taskENTER_CRITICAL(); + { + xReturn = xTCB->pxTaskTag; + } + taskEXIT_CRITICAL(); + + return xReturn; + } + +#endif /* configUSE_APPLICATION_TASK_TAG */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_APPLICATION_TASK_TAG == 1 ) + + BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter ) + { + TCB_t *xTCB; + BaseType_t xReturn; + + /* If xTask is NULL then we are calling our own task hook. */ + if( xTask == NULL ) + { + xTCB = ( TCB_t * ) pxCurrentTCB; + } + else + { + xTCB = ( TCB_t * ) xTask; + } + + if( xTCB->pxTaskTag != NULL ) + { + xReturn = xTCB->pxTaskTag( pvParameter ); + } + else + { + xReturn = pdFAIL; + } + + return xReturn; + } + +#endif /* configUSE_APPLICATION_TASK_TAG */ +/*-----------------------------------------------------------*/ + +void vTaskSwitchContext( void ) +{ + if( uxSchedulerSuspended != ( UBaseType_t ) pdFALSE ) + { + /* The scheduler is currently suspended - do not allow a context + switch. */ + xYieldPending = pdTRUE; + } + else + { + xYieldPending = pdFALSE; + traceTASK_SWITCHED_OUT(); + + #if ( configGENERATE_RUN_TIME_STATS == 1 ) + { + #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE + portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime ); + #else + ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE(); + #endif + + /* Add the amount of time the task has been running to the + accumulated time so far. The time the task started running was + stored in ulTaskSwitchedInTime. Note that there is no overflow + protection here so count values are only valid until the timer + overflows. The guard against negative values is to protect + against suspect run time stat counter implementations - which + are provided by the application, not the kernel. */ + if( ulTotalRunTime > ulTaskSwitchedInTime ) + { + pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime - ulTaskSwitchedInTime ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + ulTaskSwitchedInTime = ulTotalRunTime; + } + #endif /* configGENERATE_RUN_TIME_STATS */ + + /* Check for stack overflow, if configured. */ + taskFIRST_CHECK_FOR_STACK_OVERFLOW(); + taskSECOND_CHECK_FOR_STACK_OVERFLOW(); + + /* Select a new task to run using either the generic C or port + optimised asm code. */ + taskSELECT_HIGHEST_PRIORITY_TASK(); + traceTASK_SWITCHED_IN(); + + #if ( configUSE_NEWLIB_REENTRANT == 1 ) + { + /* Switch Newlib's _impure_ptr variable to point to the _reent + structure specific to this task. */ + _impure_ptr = &( pxCurrentTCB->xNewLib_reent ); + } + #endif /* configUSE_NEWLIB_REENTRANT */ + } +} +/*-----------------------------------------------------------*/ + +void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksToWait ) +{ +TickType_t xTimeToWake; + + configASSERT( pxEventList ); + + /* THIS FUNCTION MUST BE CALLED WITH EITHER INTERRUPTS DISABLED OR THE + SCHEDULER SUSPENDED AND THE QUEUE BEING ACCESSED LOCKED. */ + + /* Place the event list item of the TCB in the appropriate event list. + This is placed in the list in priority order so the highest priority task + is the first to be woken by the event. The queue that contains the event + list is locked, preventing simultaneous access from interrupts. */ + vListInsert( pxEventList, &( pxCurrentTCB->xEventListItem ) ); + + /* The task must be removed from from the ready list before it is added to + the blocked list as the same list item is used for both lists. Exclusive + access to the ready lists guaranteed because the scheduler is locked. */ + if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 ) + { + /* The current task must be in a ready list, so there is no need to + check, and the port reset macro can be called directly. */ + portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + #if ( INCLUDE_vTaskSuspend == 1 ) + { + if( xTicksToWait == portMAX_DELAY ) + { + /* Add the task to the suspended task list instead of a delayed task + list to ensure the task is not woken by a timing event. It will + block indefinitely. */ + vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) ); + } + else + { + /* Calculate the time at which the task should be woken if the event + does not occur. This may overflow but this doesn't matter, the + scheduler will handle it. */ + xTimeToWake = xTickCount + xTicksToWait; + prvAddCurrentTaskToDelayedList( xTimeToWake ); + } + } + #else /* INCLUDE_vTaskSuspend */ + { + /* Calculate the time at which the task should be woken if the event does + not occur. This may overflow but this doesn't matter, the scheduler + will handle it. */ + xTimeToWake = xTickCount + xTicksToWait; + prvAddCurrentTaskToDelayedList( xTimeToWake ); + } + #endif /* INCLUDE_vTaskSuspend */ +} +/*-----------------------------------------------------------*/ + +void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xItemValue, const TickType_t xTicksToWait ) +{ +TickType_t xTimeToWake; + + configASSERT( pxEventList ); + + /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by + the event groups implementation. */ + configASSERT( uxSchedulerSuspended != 0 ); + + /* Store the item value in the event list item. It is safe to access the + event list item here as interrupts won't access the event list item of a + task that is not in the Blocked state. */ + listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE ); + + /* Place the event list item of the TCB at the end of the appropriate event + list. It is safe to access the event list here because it is part of an + event group implementation - and interrupts don't access event groups + directly (instead they access them indirectly by pending function calls to + the task level). */ + vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) ); + + /* The task must be removed from the ready list before it is added to the + blocked list. Exclusive access can be assured to the ready list as the + scheduler is locked. */ + if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 ) + { + /* The current task must be in a ready list, so there is no need to + check, and the port reset macro can be called directly. */ + portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + #if ( INCLUDE_vTaskSuspend == 1 ) + { + if( xTicksToWait == portMAX_DELAY ) + { + /* Add the task to the suspended task list instead of a delayed task + list to ensure it is not woken by a timing event. It will block + indefinitely. */ + vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) ); + } + else + { + /* Calculate the time at which the task should be woken if the event + does not occur. This may overflow but this doesn't matter, the + kernel will manage it correctly. */ + xTimeToWake = xTickCount + xTicksToWait; + prvAddCurrentTaskToDelayedList( xTimeToWake ); + } + } + #else /* INCLUDE_vTaskSuspend */ + { + /* Calculate the time at which the task should be woken if the event does + not occur. This may overflow but this doesn't matter, the kernel + will manage it correctly. */ + xTimeToWake = xTickCount + xTicksToWait; + prvAddCurrentTaskToDelayedList( xTimeToWake ); + } + #endif /* INCLUDE_vTaskSuspend */ +} +/*-----------------------------------------------------------*/ + +#if configUSE_TIMERS == 1 + + void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, const TickType_t xTicksToWait ) + { + TickType_t xTimeToWake; + + configASSERT( pxEventList ); + + /* This function should not be called by application code hence the + 'Restricted' in its name. It is not part of the public API. It is + designed for use by kernel code, and has special calling requirements - + it should be called from a critical section. */ + + + /* Place the event list item of the TCB in the appropriate event list. + In this case it is assume that this is the only task that is going to + be waiting on this event list, so the faster vListInsertEnd() function + can be used in place of vListInsert. */ + vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) ); + + /* We must remove this task from the ready list before adding it to the + blocked list as the same list item is used for both lists. This + function is called form a critical section. */ + if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 ) + { + /* The current task must be in a ready list, so there is no need to + check, and the port reset macro can be called directly. */ + portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Calculate the time at which the task should be woken if the event does + not occur. This may overflow but this doesn't matter. */ + xTimeToWake = xTickCount + xTicksToWait; + + traceTASK_DELAY_UNTIL(); + prvAddCurrentTaskToDelayedList( xTimeToWake ); + } + +#endif /* configUSE_TIMERS */ +/*-----------------------------------------------------------*/ + +BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList ) +{ +TCB_t *pxUnblockedTCB; +BaseType_t xReturn; + + /* THIS FUNCTION MUST BE CALLED FROM A CRITICAL SECTION. It can also be + called from a critical section within an ISR. */ + + /* The event list is sorted in priority order, so the first in the list can + be removed as it is known to be the highest priority. Remove the TCB from + the delayed list, and add it to the ready list. + + If an event is for a queue that is locked then this function will never + get called - the lock count on the queue will get modified instead. This + means exclusive access to the event list is guaranteed here. + + This function assumes that a check has already been made to ensure that + pxEventList is not empty. */ + pxUnblockedTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); + configASSERT( pxUnblockedTCB ); + ( void ) uxListRemove( &( pxUnblockedTCB->xEventListItem ) ); + + if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) + { + ( void ) uxListRemove( &( pxUnblockedTCB->xGenericListItem ) ); + prvAddTaskToReadyList( pxUnblockedTCB ); + } + else + { + /* The delayed and ready lists cannot be accessed, so hold this task + pending until the scheduler is resumed. */ + vListInsertEnd( &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) ); + } + + if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority ) + { + /* Return true if the task removed from the event list has a higher + priority than the calling task. This allows the calling task to know if + it should force a context switch now. */ + xReturn = pdTRUE; + + /* Mark that a yield is pending in case the user is not using the + "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */ + xYieldPending = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +BaseType_t xTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, const TickType_t xItemValue ) +{ +TCB_t *pxUnblockedTCB; +BaseType_t xReturn; + + /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by + the event flags implementation. */ + configASSERT( uxSchedulerSuspended != pdFALSE ); + + /* Store the new item value in the event list. */ + listSET_LIST_ITEM_VALUE( pxEventListItem, xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE ); + + /* Remove the event list form the event flag. Interrupts do not access + event flags. */ + pxUnblockedTCB = ( TCB_t * ) listGET_LIST_ITEM_OWNER( pxEventListItem ); + configASSERT( pxUnblockedTCB ); + ( void ) uxListRemove( pxEventListItem ); + + /* Remove the task from the delayed list and add it to the ready list. The + scheduler is suspended so interrupts will not be accessing the ready + lists. */ + ( void ) uxListRemove( &( pxUnblockedTCB->xGenericListItem ) ); + prvAddTaskToReadyList( pxUnblockedTCB ); + + if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority ) + { + /* Return true if the task removed from the event list has + a higher priority than the calling task. This allows + the calling task to know if it should force a context + switch now. */ + xReturn = pdTRUE; + + /* Mark that a yield is pending in case the user is not using the + "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */ + xYieldPending = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) +{ + configASSERT( pxTimeOut ); + pxTimeOut->xOverflowCount = xNumOfOverflows; + pxTimeOut->xTimeOnEntering = xTickCount; +} +/*-----------------------------------------------------------*/ + +BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait ) +{ +BaseType_t xReturn; + + configASSERT( pxTimeOut ); + configASSERT( pxTicksToWait ); + + taskENTER_CRITICAL(); + { + /* Minor optimisation. The tick count cannot change in this block. */ + const TickType_t xConstTickCount = xTickCount; + + #if ( INCLUDE_vTaskSuspend == 1 ) + /* If INCLUDE_vTaskSuspend is set to 1 and the block time specified is + the maximum block time then the task should block indefinitely, and + therefore never time out. */ + if( *pxTicksToWait == portMAX_DELAY ) + { + xReturn = pdFALSE; + } + else /* We are not blocking indefinitely, perform the checks below. */ + #endif + + if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xConstTickCount >= pxTimeOut->xTimeOnEntering ) ) /*lint !e525 Indentation preferred as is to make code within pre-processor directives clearer. */ + { + /* The tick count is greater than the time at which vTaskSetTimeout() + was called, but has also overflowed since vTaskSetTimeOut() was called. + It must have wrapped all the way around and gone past us again. This + passed since vTaskSetTimeout() was called. */ + xReturn = pdTRUE; + } + else if( ( xConstTickCount - pxTimeOut->xTimeOnEntering ) < *pxTicksToWait ) + { + /* Not a genuine timeout. Adjust parameters for time remaining. */ + *pxTicksToWait -= ( xConstTickCount - pxTimeOut->xTimeOnEntering ); + vTaskSetTimeOutState( pxTimeOut ); + xReturn = pdFALSE; + } + else + { + xReturn = pdTRUE; + } + } + taskEXIT_CRITICAL(); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +void vTaskMissedYield( void ) +{ + xYieldPending = pdTRUE; +} +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + + UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask ) + { + UBaseType_t uxReturn; + TCB_t *pxTCB; + + if( xTask != NULL ) + { + pxTCB = ( TCB_t * ) xTask; + uxReturn = pxTCB->uxTaskNumber; + } + else + { + uxReturn = 0U; + } + + return uxReturn; + } + +#endif /* configUSE_TRACE_FACILITY */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + + void vTaskSetTaskNumber( TaskHandle_t xTask, const UBaseType_t uxHandle ) + { + TCB_t *pxTCB; + + if( xTask != NULL ) + { + pxTCB = ( TCB_t * ) xTask; + pxTCB->uxTaskNumber = uxHandle; + } + } + +#endif /* configUSE_TRACE_FACILITY */ + +/* + * ----------------------------------------------------------- + * The Idle task. + * ---------------------------------------------------------- + * + * The portTASK_FUNCTION() macro is used to allow port/compiler specific + * language extensions. The equivalent prototype for this function is: + * + * void prvIdleTask( void *pvParameters ); + * + */ +static portTASK_FUNCTION( prvIdleTask, pvParameters ) +{ + /* Stop warnings. */ + ( void ) pvParameters; + + for( ;; ) + { + /* See if any tasks have been deleted. */ + prvCheckTasksWaitingTermination(); + + #if ( configUSE_PREEMPTION == 0 ) + { + /* If we are not using preemption we keep forcing a task switch to + see if any other task has become available. If we are using + preemption we don't need to do this as any task becoming available + will automatically get the processor anyway. */ + taskYIELD(); + } + #endif /* configUSE_PREEMPTION */ + + #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) + { + /* When using preemption tasks of equal priority will be + timesliced. If a task that is sharing the idle priority is ready + to run then the idle task should yield before the end of the + timeslice. + + A critical region is not required here as we are just reading from + the list, and an occasional incorrect value will not matter. If + the ready list at the idle priority contains more than one task + then a task other than the idle task is ready to execute. */ + if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) 1 ) + { + taskYIELD(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */ + + #if ( configUSE_IDLE_HOOK == 1 ) + { + extern void vApplicationIdleHook( void ); + + /* Call the user defined function from within the idle task. This + allows the application designer to add background functionality + without the overhead of a separate task. + NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES, + CALL A FUNCTION THAT MIGHT BLOCK. */ + vApplicationIdleHook(); + } + #endif /* configUSE_IDLE_HOOK */ + + /* This conditional compilation should use inequality to 0, not equality + to 1. This is to ensure portSUPPRESS_TICKS_AND_SLEEP() is called when + user defined low power mode implementations require + configUSE_TICKLESS_IDLE to be set to a value other than 1. */ + #if ( configUSE_TICKLESS_IDLE != 0 ) + { + TickType_t xExpectedIdleTime; + + /* It is not desirable to suspend then resume the scheduler on + each iteration of the idle task. Therefore, a preliminary + test of the expected idle time is performed without the + scheduler suspended. The result here is not necessarily + valid. */ + xExpectedIdleTime = prvGetExpectedIdleTime(); + + if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP ) + { + vTaskSuspendAll(); + { + /* Now the scheduler is suspended, the expected idle + time can be sampled again, and this time its value can + be used. */ + configASSERT( xNextTaskUnblockTime >= xTickCount ); + xExpectedIdleTime = prvGetExpectedIdleTime(); + + if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP ) + { + traceLOW_POWER_IDLE_BEGIN(); + portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ); + traceLOW_POWER_IDLE_END(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + ( void ) xTaskResumeAll(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_TICKLESS_IDLE */ + } +} +/*-----------------------------------------------------------*/ + +#if configUSE_TICKLESS_IDLE != 0 + + eSleepModeStatus eTaskConfirmSleepModeStatus( void ) + { + eSleepModeStatus eReturn = eStandardSleep; + + if( listCURRENT_LIST_LENGTH( &xPendingReadyList ) != 0 ) + { + /* A task was made ready while the scheduler was suspended. */ + eReturn = eAbortSleep; + } + else if( xYieldPending != pdFALSE ) + { + /* A yield was pended while the scheduler was suspended. */ + eReturn = eAbortSleep; + } + else + { + #if configUSE_TIMERS == 0 + { + /* The idle task exists in addition to the application tasks. */ + const UBaseType_t uxNonApplicationTasks = 1; + + /* If timers are not being used and all the tasks are in the + suspended list (which might mean they have an infinite block + time rather than actually being suspended) then it is safe to + turn all clocks off and just wait for external interrupts. */ + if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) ) + { + eReturn = eNoTasksWaitingTimeout; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_TIMERS */ + } + + return eReturn; + } +#endif /* configUSE_TICKLESS_IDLE */ +/*-----------------------------------------------------------*/ + +static void prvInitialiseTCBVariables( TCB_t * const pxTCB, const char * const pcName, UBaseType_t uxPriority, const MemoryRegion_t * const xRegions, const uint16_t usStackDepth ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ +{ +UBaseType_t x; + + /* Store the task name in the TCB. */ + for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ ) + { + pxTCB->pcTaskName[ x ] = pcName[ x ]; + + /* Don't copy all configMAX_TASK_NAME_LEN if the string is shorter than + configMAX_TASK_NAME_LEN characters just in case the memory after the + string is not accessible (extremely unlikely). */ + if( pcName[ x ] == 0x00 ) + { + break; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + /* Ensure the name string is terminated in the case that the string length + was greater or equal to configMAX_TASK_NAME_LEN. */ + pxTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = '\0'; + + /* This is used as an array index so must ensure it's not too large. First + remove the privilege bit if one is present. */ + if( uxPriority >= ( UBaseType_t ) configMAX_PRIORITIES ) + { + uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + pxTCB->uxPriority = uxPriority; + #if ( configUSE_MUTEXES == 1 ) + { + pxTCB->uxBasePriority = uxPriority; + pxTCB->uxMutexesHeld = 0; + } + #endif /* configUSE_MUTEXES */ + + vListInitialiseItem( &( pxTCB->xGenericListItem ) ); + vListInitialiseItem( &( pxTCB->xEventListItem ) ); + + /* Set the pxTCB as a link back from the ListItem_t. This is so we can get + back to the containing TCB from a generic item in a list. */ + listSET_LIST_ITEM_OWNER( &( pxTCB->xGenericListItem ), pxTCB ); + + /* Event lists are always in priority order. */ + listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + listSET_LIST_ITEM_OWNER( &( pxTCB->xEventListItem ), pxTCB ); + + #if ( portCRITICAL_NESTING_IN_TCB == 1 ) + { + pxTCB->uxCriticalNesting = ( UBaseType_t ) 0U; + } + #endif /* portCRITICAL_NESTING_IN_TCB */ + + #if ( configUSE_APPLICATION_TASK_TAG == 1 ) + { + pxTCB->pxTaskTag = NULL; + } + #endif /* configUSE_APPLICATION_TASK_TAG */ + + #if ( configGENERATE_RUN_TIME_STATS == 1 ) + { + pxTCB->ulRunTimeCounter = 0UL; + pxTCB->ulStartRunTimeCounterOfPeroid = 0UL; + pxTCB->ulEndRunTimeCounterOfPeroid = 0UL; + } + #endif /* configGENERATE_RUN_TIME_STATS */ + + #if ( portUSING_MPU_WRAPPERS == 1 ) + { + vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, pxTCB->pxStack, usStackDepth ); + } + #else /* portUSING_MPU_WRAPPERS */ + { + ( void ) xRegions; + ( void ) usStackDepth; + } + #endif /* portUSING_MPU_WRAPPERS */ + + #if ( configUSE_NEWLIB_REENTRANT == 1 ) + { + /* Initialise this task's Newlib reent structure. */ + _REENT_INIT_PTR( ( &( pxTCB->xNewLib_reent ) ) ); + } + #endif /* configUSE_NEWLIB_REENTRANT */ +} +/*-----------------------------------------------------------*/ + +#if ( portUSING_MPU_WRAPPERS == 1 ) + + void vTaskAllocateMPURegions( TaskHandle_t xTaskToModify, const MemoryRegion_t * const xRegions ) + { + TCB_t *pxTCB; + + /* If null is passed in here then we are deleting ourselves. */ + pxTCB = prvGetTCBFromHandle( xTaskToModify ); + + vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 ); + } + +#endif /* portUSING_MPU_WRAPPERS */ +/*-----------------------------------------------------------*/ + +static void prvInitialiseTaskLists( void ) +{ +UBaseType_t uxPriority; + + for( uxPriority = ( UBaseType_t ) 0U; uxPriority < ( UBaseType_t ) configMAX_PRIORITIES; uxPriority++ ) + { + vListInitialise( &( pxReadyTasksLists[ uxPriority ] ) ); + } + + vListInitialise( &xDelayedTaskList1 ); + vListInitialise( &xDelayedTaskList2 ); + vListInitialise( &xPendingReadyList ); + + #if ( INCLUDE_vTaskDelete == 1 ) + { + vListInitialise( &xTasksWaitingTermination ); + } + #endif /* INCLUDE_vTaskDelete */ + + #if ( INCLUDE_vTaskSuspend == 1 ) + { + vListInitialise( &xSuspendedTaskList ); + } + #endif /* INCLUDE_vTaskSuspend */ + + /* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList + using list2. */ + pxDelayedTaskList = &xDelayedTaskList1; + pxOverflowDelayedTaskList = &xDelayedTaskList2; +} +/*-----------------------------------------------------------*/ + +static void prvCheckTasksWaitingTermination( void ) +{ + #if ( INCLUDE_vTaskDelete == 1 ) + { + BaseType_t xListIsEmpty; + + /* ucTasksDeleted is used to prevent vTaskSuspendAll() being called + too often in the idle task. */ + while( uxTasksDeleted > ( UBaseType_t ) 0U ) + { + vTaskSuspendAll(); + { + xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination ); + } + ( void ) xTaskResumeAll(); + + if( xListIsEmpty == pdFALSE ) + { + TCB_t *pxTCB; + + taskENTER_CRITICAL(); + { + pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) ); + ( void ) uxListRemove( &( pxTCB->xGenericListItem ) ); + --uxCurrentNumberOfTasks; + --uxTasksDeleted; + } + taskEXIT_CRITICAL(); + + prvDeleteTCB( pxTCB ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + #endif /* vTaskDelete */ +} +/*-----------------------------------------------------------*/ + +static void prvAddCurrentTaskToDelayedList( const TickType_t xTimeToWake ) +{ + /* The list item will be inserted in wake time order. */ + listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake ); + + if( xTimeToWake < xTickCount ) + { + /* Wake time has overflowed. Place this item in the overflow list. */ + vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xGenericListItem ) ); + } + else + { + /* The wake time has not overflowed, so the current block list is used. */ + vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xGenericListItem ) ); + + /* If the task entering the blocked state was placed at the head of the + list of blocked tasks then xNextTaskUnblockTime needs to be updated + too. */ + if( xTimeToWake < xNextTaskUnblockTime ) + { + xNextTaskUnblockTime = xTimeToWake; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } +} +/*-----------------------------------------------------------*/ + +static TCB_t *prvAllocateTCBAndStack( const uint16_t usStackDepth, StackType_t * const puxStackBuffer ) +{ +TCB_t *pxNewTCB; + + /* Allocate space for the TCB. Where the memory comes from depends on + the implementation of the port malloc function. */ + pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); + + if( pxNewTCB != NULL ) + { + /* Allocate space for the stack used by the task being created. + The base of the stack memory stored in the TCB so the task can + be deleted later if required. */ + pxNewTCB->pxStack = ( StackType_t * ) pvPortMallocAligned( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ), puxStackBuffer ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + + if( pxNewTCB->pxStack == NULL ) + { + /* Could not allocate the stack. Delete the allocated TCB. */ + vPortFree( pxNewTCB ); + pxNewTCB = NULL; + } + else + { + /* Avoid dependency on memset() if it is not required. */ + #if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) + { + /* Just to help debugging. */ + ( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) usStackDepth * sizeof( StackType_t ) ); + } + #endif /* ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) ) */ + } + } + + return pxNewTCB; +} +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + + static UBaseType_t prvListTaskWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState ) + { + volatile TCB_t *pxNextTCB, *pxFirstTCB; + UBaseType_t uxTask = 0; + + if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 ) + { + listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); + + /* Populate an TaskStatus_t structure within the + pxTaskStatusArray array for each task that is referenced from + pxList. See the definition of TaskStatus_t in task.h for the + meaning of each TaskStatus_t structure member. */ + do + { + listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); + + pxTaskStatusArray[ uxTask ].xHandle = ( TaskHandle_t ) pxNextTCB; + pxTaskStatusArray[ uxTask ].pcTaskName = ( const char * ) &( pxNextTCB->pcTaskName [ 0 ] ); + pxTaskStatusArray[ uxTask ].xTaskNumber = pxNextTCB->uxTCBNumber; + pxTaskStatusArray[ uxTask ].eCurrentState = eState; + pxTaskStatusArray[ uxTask ].uxCurrentPriority = pxNextTCB->uxPriority; + + #if ( INCLUDE_vTaskSuspend == 1 ) + { + /* If the task is in the suspended list then there is a chance + it is actually just blocked indefinitely - so really it should + be reported as being in the Blocked state. */ + if( eState == eSuspended ) + { + if( listLIST_ITEM_CONTAINER( &( pxNextTCB->xEventListItem ) ) != NULL ) + { + pxTaskStatusArray[ uxTask ].eCurrentState = eBlocked; + } + } + } + #endif /* INCLUDE_vTaskSuspend */ + + #if ( configUSE_MUTEXES == 1 ) + { + pxTaskStatusArray[ uxTask ].uxBasePriority = pxNextTCB->uxBasePriority; + } + #else + { + pxTaskStatusArray[ uxTask ].uxBasePriority = 0; + } + #endif + + #if ( configGENERATE_RUN_TIME_STATS == 1 ) + { + pxTaskStatusArray[ uxTask ].ulRunTimeCounter = pxNextTCB->ulRunTimeCounter; + if (pxNextTCB->ulEndRunTimeCounterOfPeroid > pxNextTCB->ulStartRunTimeCounterOfPeroid) + pxTaskStatusArray[ uxTask ].ulDelataRunTimeCounterOfPeroid = pxNextTCB->ulEndRunTimeCounterOfPeroid - pxNextTCB->ulStartRunTimeCounterOfPeroid; + else + pxTaskStatusArray[ uxTask ].ulDelataRunTimeCounterOfPeroid = pxNextTCB->ulStartRunTimeCounterOfPeroid - pxNextTCB->ulEndRunTimeCounterOfPeroid; + ulDeltaTotalRunTime += pxTaskStatusArray[ uxTask ].ulDelataRunTimeCounterOfPeroid; + } + #else + { + pxTaskStatusArray[ uxTask ].ulRunTimeCounter = 0; + } + #endif + + #if ( portSTACK_GROWTH > 0 ) + { + pxTaskStatusArray[ uxTask ].usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxNextTCB->pxEndOfStack ); + } + #else + { + pxTaskStatusArray[ uxTask ].usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxNextTCB->pxStack ); + } + #endif + + uxTask++; + + } while( pxNextTCB != pxFirstTCB ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + return uxTask; + } + +#endif /* configUSE_TRACE_FACILITY */ +/*-----------------------------------------------------------*/ + +#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) + + static uint16_t prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte ) + { + uint32_t ulCount = 0U; + + while( *pucStackByte == ( uint8_t ) tskSTACK_FILL_BYTE ) + { + pucStackByte -= portSTACK_GROWTH; + ulCount++; + } + + ulCount /= ( uint32_t ) sizeof( StackType_t ); /*lint !e961 Casting is not redundant on smaller architectures. */ + + return ( uint16_t ) ulCount; + } + +#endif /* ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) + + UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) + { + TCB_t *pxTCB; + uint8_t *pucEndOfStack; + UBaseType_t uxReturn; + + pxTCB = prvGetTCBFromHandle( xTask ); + + #if portSTACK_GROWTH < 0 + { + pucEndOfStack = ( uint8_t * ) pxTCB->pxStack; + } + #else + { + pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack; + } + #endif + + uxReturn = ( UBaseType_t ) prvTaskCheckFreeStackSpace( pucEndOfStack ); + + return uxReturn; + } + +#endif /* INCLUDE_uxTaskGetStackHighWaterMark */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskDelete == 1 ) + + static void prvDeleteTCB( TCB_t *pxTCB ) + { + /* This call is required specifically for the TriCore port. It must be + above the vPortFree() calls. The call is also used by ports/demos that + want to allocate and clean RAM statically. */ + portCLEAN_UP_TCB( pxTCB ); + + /* Free up the memory allocated by the scheduler for the task. It is up + to the task to free any memory allocated at the application level. */ + #if ( configUSE_NEWLIB_REENTRANT == 1 ) + { + _reclaim_reent( &( pxTCB->xNewLib_reent ) ); + } + #endif /* configUSE_NEWLIB_REENTRANT */ + vPortFreeAligned( pxTCB->pxStack ); + vPortFree( pxTCB ); + } + +#endif /* INCLUDE_vTaskDelete */ +/*-----------------------------------------------------------*/ + +static void prvResetNextTaskUnblockTime( void ) +{ +TCB_t *pxTCB; + + if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ) + { + /* The new current delayed list is empty. Set + xNextTaskUnblockTime to the maximum possible value so it is + extremely unlikely that the + if( xTickCount >= xNextTaskUnblockTime ) test will pass until + there is an item in the delayed list. */ + xNextTaskUnblockTime = portMAX_DELAY; + } + else + { + /* The new current delayed list is not empty, get the value of + the item at the head of the delayed list. This is the time at + which the task at the head of the delayed list should be removed + from the Blocked state. */ + ( pxTCB ) = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); + xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( ( pxTCB )->xGenericListItem ) ); + } +} +/*-----------------------------------------------------------*/ + +#if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) + + TaskHandle_t xTaskGetCurrentTaskHandle( void ) + { + TaskHandle_t xReturn; + + /* A critical section is not required as this is not called from + an interrupt and the current TCB will always be the same for any + individual execution thread. */ + xReturn = pxCurrentTCB; + + return xReturn; + } + +#endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */ +/*-----------------------------------------------------------*/ + +#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) + + BaseType_t xTaskGetSchedulerState( void ) + { + BaseType_t xReturn; + + if( xSchedulerRunning == pdFALSE ) + { + xReturn = taskSCHEDULER_NOT_STARTED; + } + else + { + if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) + { + xReturn = taskSCHEDULER_RUNNING; + } + else + { + xReturn = taskSCHEDULER_SUSPENDED; + } + } + + return xReturn; + } + +#endif /* ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_MUTEXES == 1 ) + + void vTaskPriorityInherit( TaskHandle_t const pxMutexHolder ) + { + TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder; + + /* If the mutex was given back by an interrupt while the queue was + locked then the mutex holder might now be NULL. */ + if( pxMutexHolder != NULL ) + { + if( pxTCB->uxPriority < pxCurrentTCB->uxPriority ) + { + /* Adjust the mutex holder state to account for its new + priority. Only reset the event list item value if the value is + not being used for anything else. */ + if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL ) + { + listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* If the task being modified is in the ready state it will need to + be moved into a new list. */ + if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ) != pdFALSE ) + { + if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 ) + { + taskRESET_READY_PRIORITY( pxTCB->uxPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Inherit the priority before being moved into the new list. */ + pxTCB->uxPriority = pxCurrentTCB->uxPriority; + prvAddTaskToReadyList( pxTCB ); + } + else + { + /* Just inherit the priority. */ + pxTCB->uxPriority = pxCurrentTCB->uxPriority; + } + + traceTASK_PRIORITY_INHERIT( pxTCB, pxCurrentTCB->uxPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + +#endif /* configUSE_MUTEXES */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_MUTEXES == 1 ) + + BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder ) + { + TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder; + BaseType_t xReturn = pdFALSE; + + if( pxMutexHolder != NULL ) + { + configASSERT( pxTCB->uxMutexesHeld ); + ( pxTCB->uxMutexesHeld )--; + + if( pxTCB->uxPriority != pxTCB->uxBasePriority ) + { + /* Only disinherit if no other mutexes are held. */ + if( pxTCB->uxMutexesHeld == ( UBaseType_t ) 0 ) + { + /* The holding task must be the running task to be able to give + the mutex back. Remove the holding task from the ready list. */ + if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 ) + { + taskRESET_READY_PRIORITY( pxTCB->uxPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Disinherit the priority before adding the task into the new + ready list. */ + traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority ); + pxTCB->uxPriority = pxTCB->uxBasePriority; + + /* Reset the event list item value. It cannot be in use for + any other purpose if this task is running, and it must be + running to give back the mutex. */ + listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + prvAddTaskToReadyList( pxTCB ); + + /* Return true to indicate that a context switch is required. + This is only actually required in the corner case whereby + multiple mutexes were held and the mutexes were given back + in an order different to that in which they were taken. */ + xReturn = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + return xReturn; + } + +#endif /* configUSE_MUTEXES */ +/*-----------------------------------------------------------*/ + +#if ( portCRITICAL_NESTING_IN_TCB == 1 ) + + void vTaskEnterCritical( void ) + { + portDISABLE_INTERRUPTS(); + + if( xSchedulerRunning != pdFALSE ) + { + ( pxCurrentTCB->uxCriticalNesting )++; + + /* This is not the interrupt safe version of the enter critical + function so assert() if it is being called from an interrupt + context. Only API functions that end in "FromISR" can be used in an + interrupt. Only assert if the critical nesting count is 1 to + protect against recursive calls if the assert function also uses a + critical section. */ + if( pxCurrentTCB->uxCriticalNesting == 1 ) + { + portASSERT_IF_IN_ISR(); + } + + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + +#endif /* portCRITICAL_NESTING_IN_TCB */ +/*-----------------------------------------------------------*/ + +#if ( portCRITICAL_NESTING_IN_TCB == 1 ) + + void vTaskExitCritical( void ) + { + if( xSchedulerRunning != pdFALSE ) + { + if( pxCurrentTCB->uxCriticalNesting > 0U ) + { + ( pxCurrentTCB->uxCriticalNesting )--; + + if( pxCurrentTCB->uxCriticalNesting == 0U ) + { + portENABLE_INTERRUPTS(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + +#endif /* portCRITICAL_NESTING_IN_TCB */ +/*-----------------------------------------------------------*/ + +#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) ) + + void vTaskList( char * pcWriteBuffer ) + { + TaskStatus_t *pxTaskStatusArray; + volatile UBaseType_t uxArraySize, x; + char cStatus; + + /* + * PLEASE NOTE: + * + * This function is provided for convenience only, and is used by many + * of the demo applications. Do not consider it to be part of the + * scheduler. + * + * vTaskList() calls uxTaskGetSystemState(), then formats part of the + * uxTaskGetSystemState() output into a human readable table that + * displays task names, states and stack usage. + * + * vTaskList() has a dependency on the sprintf() C library function that + * might bloat the code size, use a lot of stack, and provide different + * results on different platforms. An alternative, tiny, third party, + * and limited functionality implementation of sprintf() is provided in + * many of the FreeRTOS/Demo sub-directories in a file called + * printf-stdarg.c (note printf-stdarg.c does not provide a full + * snprintf() implementation!). + * + * It is recommended that production systems call uxTaskGetSystemState() + * directly to get access to raw stats data, rather than indirectly + * through a call to vTaskList(). + */ + + + /* Make sure the write buffer does not contain a string. */ + *pcWriteBuffer = 0x00; + + /* Take a snapshot of the number of tasks in case it changes while this + function is executing. */ + uxArraySize = uxCurrentNumberOfTasks; + + /* Allocate an array index for each task. */ + pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) ); + + if( pxTaskStatusArray != NULL ) + { + /* Generate the (binary) data. */ + uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, NULL ); + + /* Create a human readable table from the binary data. */ + for( x = 0; x < uxArraySize; x++ ) + { + switch( pxTaskStatusArray[ x ].eCurrentState ) + { + case eReady: cStatus = tskREADY_CHAR; + break; + + case eBlocked: cStatus = tskBLOCKED_CHAR; + break; + + case eSuspended: cStatus = tskSUSPENDED_CHAR; + break; + + case eDeleted: cStatus = tskDELETED_CHAR; + break; + + default: /* Should not get here, but it is included + to prevent static checking errors. */ + cStatus = 0x00; + break; + } + + sprintf( pcWriteBuffer, "%s\t\t%c\t%u\t%u\t%u\r\n", pxTaskStatusArray[ x ].pcTaskName, cStatus, ( unsigned int ) pxTaskStatusArray[ x ].uxCurrentPriority, ( unsigned int ) pxTaskStatusArray[ x ].usStackHighWaterMark, ( unsigned int ) pxTaskStatusArray[ x ].xTaskNumber ); + pcWriteBuffer += strlen( pcWriteBuffer ); + } + + /* Free the array again. */ + vPortFree( pxTaskStatusArray ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + +#endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) ) */ +/*----------------------------------------------------------*/ + +#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) ) + + void vTaskGetRunTimeStats( char *pcWriteBuffer ) + { + TaskStatus_t *pxTaskStatusArray; + volatile UBaseType_t uxArraySize, x; + uint32_t ulTotalTime, ulStatsAsPercentage, ulDeltaRunTimeCounter; + + #if( configUSE_TRACE_FACILITY != 1 ) + { + #error configUSE_TRACE_FACILITY must also be set to 1 in FreeRTOSConfig.h to use vTaskGetRunTimeStats(). + } + #endif + + /* + * PLEASE NOTE: + * + * This function is provided for convenience only, and is used by many + * of the demo applications. Do not consider it to be part of the + * scheduler. + * + * vTaskGetRunTimeStats() calls uxTaskGetSystemState(), then formats part + * of the uxTaskGetSystemState() output into a human readable table that + * displays the amount of time each task has spent in the Running state + * in both absolute and percentage terms. + * + * vTaskGetRunTimeStats() has a dependency on the sprintf() C library + * function that might bloat the code size, use a lot of stack, and + * provide different results on different platforms. An alternative, + * tiny, third party, and limited functionality implementation of + * sprintf() is provided in many of the FreeRTOS/Demo sub-directories in + * a file called printf-stdarg.c (note printf-stdarg.c does not provide + * a full snprintf() implementation!). + * + * It is recommended that production systems call uxTaskGetSystemState() + * directly to get access to raw stats data, rather than indirectly + * through a call to vTaskGetRunTimeStats(). + */ + + /* Make sure the write buffer does not contain a string. */ + *pcWriteBuffer = 0x00; + + /* Take a snapshot of the number of tasks in case it changes while this + function is executing. */ + uxArraySize = uxCurrentNumberOfTasks; + + /* Allocate an array index for each task. */ + pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) ); + + if( pxTaskStatusArray != NULL ) + { + /* Generate the (binary) data. */ + uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalTime ); + printf("\n\rCPU total run time is %u", ulTotalTime); + printf("\n\rTaskName\tDeltaRunTime\tpercentage\r\n"); + + /* For percentage calculations. */ + ulTotalTime /= 100UL; + + /* Avoid divide by zero errors. */ + if( ulTotalTime > 0 ) + { + /* Create a human readable table from the binary data. */ + for( x = 0; x < uxArraySize; x++ ) + { + /* What percentage of the total run time has the task used? + This will always be rounded down to the nearest integer. + ulTotalRunTimeDiv100 has already been divided by 100. */ +#if 0 + ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalTime; +#else + ulStatsAsPercentage = (100*pxTaskStatusArray[ x ].ulDelataRunTimeCounterOfPeroid) / ulDeltaTotalRunTime; + /* just make run time counter looks like more precise*/ + if (100*(100*pxTaskStatusArray[ x ].ulDelataRunTimeCounterOfPeroid) % ulDeltaTotalRunTime >=50) + ulDeltaRunTimeCounter = portCONFIGURE_STATS_PEROID_VALUE*(ulStatsAsPercentage+1)/100; + else + ulDeltaRunTimeCounter = portCONFIGURE_STATS_PEROID_VALUE*ulStatsAsPercentage/100; +#endif + + if( ulStatsAsPercentage > 0UL ) + { + #ifdef portLU_PRINTF_SPECIFIER_REQUIRED + { +#if 0 + sprintf( pcWriteBuffer, "%s\t\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage ); +#else + sprintf( pcWriteBuffer, "%s\t\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].pcTaskName, ulDeltaRunTimeCounter, ulStatsAsPercentage ); +#endif + } + #else + { + /* sizeof( int ) == sizeof( long ) so a smaller + printf() library can be used. */ +#if 0 + sprintf( pcWriteBuffer, "%s\t\t%u\t\t%u%%\r\n", pxTaskStatusArray[ x ].pcTaskName, ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage ); +#else + sprintf( pcWriteBuffer, "%s\t\t%u\t\t%u%%\r\n", pxTaskStatusArray[ x ].pcTaskName, ( unsigned int ) ulDeltaRunTimeCounter, ( unsigned int ) ulStatsAsPercentage ); +#endif + } + #endif + } + else + { + /* If the percentage is zero here then the task has + consumed less than 1% of the total run time. */ + #ifdef portLU_PRINTF_SPECIFIER_REQUIRED + { +#if 0 + sprintf( pcWriteBuffer, "%s\t\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter ); +#else + sprintf( pcWriteBuffer, "%s\t\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, ulDeltaRunTimeCounter ); +#endif + } + #else + { + /* sizeof( int ) == sizeof( long ) so a smaller + printf() library can be used. */ +#if 0 + sprintf( pcWriteBuffer, "%s\t\t%u\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter ); +#else + sprintf( pcWriteBuffer, "%s\t\t%u\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, ( unsigned int ) ulDeltaRunTimeCounter ); +#endif + } + #endif + } + + pcWriteBuffer += strlen( pcWriteBuffer ); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Free the array again. */ + vPortFree( pxTaskStatusArray ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + +#endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) ) */ +/*-----------------------------------------------------------*/ + +TickType_t uxTaskResetEventItemValue( void ) +{ +TickType_t uxReturn; + + uxReturn = listGET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ) ); + + /* Reset the event list item to its normal value - so it can be used with + queues and semaphores. */ + listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB->uxPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + + return uxReturn; +} +/*-----------------------------------------------------------*/ + +#if ( configUSE_MUTEXES == 1 ) + + void *pvTaskIncrementMutexHeldCount( void ) + { + /* If xSemaphoreCreateMutex() is called before any tasks have been created + then pxCurrentTCB will be NULL. */ + if( pxCurrentTCB != NULL ) + { + ( pxCurrentTCB->uxMutexesHeld )++; + } + + return pxCurrentTCB; + } + +#endif /* configUSE_MUTEXES */ + +/*-----------------------------------------------------------*/ +void * vTaskGetCurrentTCB( void ) +{ + return (void*)pxCurrentTCB; +} + +#ifdef FREERTOS_MODULE_TEST + #include "tasks_test_access_functions.h" +#endif + diff --git a/component/os/freertos/freertos_v8.1.2/Source/timers.c b/component/os/freertos/freertos_v8.1.2/Source/timers.c new file mode 100644 index 0000000..7a34343 --- /dev/null +++ b/component/os/freertos/freertos_v8.1.2/Source/timers.c @@ -0,0 +1,885 @@ +/* + FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* Standard includes. */ +#include + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "timers.h" + +#if ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 0 ) + #error configUSE_TIMERS must be set to 1 to make the xTimerPendFunctionCall() function available. +#endif + +/* Lint e961 and e750 are suppressed as a MISRA exception justified because the +MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the +header files above, but not in this file, in order to generate the correct +privileged Vs unprivileged linkage and placement. */ +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */ + + +/* This entire source file will be skipped if the application is not configured +to include software timer functionality. This #if is closed at the very bottom +of this file. If you want to include software timer functionality then ensure +configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */ +#if ( configUSE_TIMERS == 1 ) + +/* Misc definitions. */ +#define tmrNO_DELAY ( TickType_t ) 0U + +/* The definition of the timers themselves. */ +typedef struct tmrTimerControl +{ + const char *pcTimerName; /*<< Text name. This is not used by the kernel, it is included simply to make debugging easier. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + ListItem_t xTimerListItem; /*<< Standard linked list item as used by all kernel features for event management. */ + TickType_t xTimerPeriodInTicks;/*<< How quickly and often the timer expires. */ + UBaseType_t uxAutoReload; /*<< Set to pdTRUE if the timer should be automatically restarted once expired. Set to pdFALSE if the timer is, in effect, a one-shot timer. */ + void *pvTimerID; /*<< An ID to identify the timer. This allows the timer to be identified when the same callback is used for multiple timers. */ + TimerCallbackFunction_t pxCallbackFunction; /*<< The function that will be called when the timer expires. */ + #if( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxTimerNumber; /*<< An ID assigned by trace tools such as FreeRTOS+Trace */ + #endif +} xTIMER; + +/* The old xTIMER name is maintained above then typedefed to the new Timer_t +name below to enable the use of older kernel aware debuggers. */ +typedef xTIMER Timer_t; + +/* The definition of messages that can be sent and received on the timer queue. +Two types of message can be queued - messages that manipulate a software timer, +and messages that request the execution of a non-timer related callback. The +two message types are defined in two separate structures, xTimerParametersType +and xCallbackParametersType respectively. */ +typedef struct tmrTimerParameters +{ + TickType_t xMessageValue; /*<< An optional value used by a subset of commands, for example, when changing the period of a timer. */ + Timer_t * pxTimer; /*<< The timer to which the command will be applied. */ +} TimerParameter_t; + + +typedef struct tmrCallbackParameters +{ + PendedFunction_t pxCallbackFunction; /* << The callback function to execute. */ + void *pvParameter1; /* << The value that will be used as the callback functions first parameter. */ + uint32_t ulParameter2; /* << The value that will be used as the callback functions second parameter. */ +} CallbackParameters_t; + +/* The structure that contains the two message types, along with an identifier +that is used to determine which message type is valid. */ +typedef struct tmrTimerQueueMessage +{ + BaseType_t xMessageID; /*<< The command being sent to the timer service task. */ + union + { + TimerParameter_t xTimerParameters; + + /* Don't include xCallbackParameters if it is not going to be used as + it makes the structure (and therefore the timer queue) larger. */ + #if ( INCLUDE_xTimerPendFunctionCall == 1 ) + CallbackParameters_t xCallbackParameters; + #endif /* INCLUDE_xTimerPendFunctionCall */ + } u; +} DaemonTaskMessage_t; + +/*lint -e956 A manual analysis and inspection has been used to determine which +static variables must be declared volatile. */ + +/* The list in which active timers are stored. Timers are referenced in expire +time order, with the nearest expiry time at the front of the list. Only the +timer service task is allowed to access these lists. */ +PRIVILEGED_DATA static List_t xActiveTimerList1; +PRIVILEGED_DATA static List_t xActiveTimerList2; +PRIVILEGED_DATA static List_t *pxCurrentTimerList; +PRIVILEGED_DATA static List_t *pxOverflowTimerList; + +/* A queue that is used to send commands to the timer service task. */ +PRIVILEGED_DATA static QueueHandle_t xTimerQueue = NULL; + +#if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 ) + + PRIVILEGED_DATA static TaskHandle_t xTimerTaskHandle = NULL; + +#endif + +/*lint +e956 */ + +/*-----------------------------------------------------------*/ + +/* + * Initialise the infrastructure used by the timer service task if it has not + * been initialised already. + */ +static void prvCheckForValidListAndQueue( void ) PRIVILEGED_FUNCTION; + +/* + * The timer service task (daemon). Timer functionality is controlled by this + * task. Other tasks communicate with the timer service task using the + * xTimerQueue queue. + */ +static void prvTimerTask( void *pvParameters ) PRIVILEGED_FUNCTION; + +/* + * Called by the timer service task to interpret and process a command it + * received on the timer queue. + */ +static void prvProcessReceivedCommands( void ) PRIVILEGED_FUNCTION; + +/* + * Insert the timer into either xActiveTimerList1, or xActiveTimerList2, + * depending on if the expire time causes a timer counter overflow. + */ +static BaseType_t prvInsertTimerInActiveList( Timer_t * const pxTimer, const TickType_t xNextExpiryTime, const TickType_t xTimeNow, const TickType_t xCommandTime ) PRIVILEGED_FUNCTION; + +/* + * An active timer has reached its expire time. Reload the timer if it is an + * auto reload timer, then call its callback. + */ +static void prvProcessExpiredTimer( const TickType_t xNextExpireTime, const TickType_t xTimeNow ) PRIVILEGED_FUNCTION; + +/* + * The tick count has overflowed. Switch the timer lists after ensuring the + * current timer list does not still reference some timers. + */ +static void prvSwitchTimerLists( void ) PRIVILEGED_FUNCTION; + +/* + * Obtain the current tick count, setting *pxTimerListsWereSwitched to pdTRUE + * if a tick count overflow occurred since prvSampleTimeNow() was last called. + */ +static TickType_t prvSampleTimeNow( BaseType_t * const pxTimerListsWereSwitched ) PRIVILEGED_FUNCTION; + +/* + * If the timer list contains any active timers then return the expire time of + * the timer that will expire first and set *pxListWasEmpty to false. If the + * timer list does not contain any timers then return 0 and set *pxListWasEmpty + * to pdTRUE. + */ +static TickType_t prvGetNextExpireTime( BaseType_t * const pxListWasEmpty ) PRIVILEGED_FUNCTION; + +/* + * If a timer has expired, process it. Otherwise, block the timer service task + * until either a timer does expire or a command is received. + */ +static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, const BaseType_t xListWasEmpty ) PRIVILEGED_FUNCTION; + +/*-----------------------------------------------------------*/ + +BaseType_t xTimerCreateTimerTask( void ) +{ +BaseType_t xReturn = pdFAIL; + + /* This function is called when the scheduler is started if + configUSE_TIMERS is set to 1. Check that the infrastructure used by the + timer service task has been created/initialised. If timers have already + been created then the initialisation will already have been performed. */ + prvCheckForValidListAndQueue(); + + if( xTimerQueue != NULL ) + { + #if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 ) + { + /* Create the timer task, storing its handle in xTimerTaskHandle so + it can be returned by the xTimerGetTimerDaemonTaskHandle() function. */ + xReturn = xTaskCreate( prvTimerTask, "Tmr Svc", ( uint16_t ) configTIMER_TASK_STACK_DEPTH, NULL, (( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT) + PRIORITIE_OFFSET, &xTimerTaskHandle ); + } + #else + { + /* Create the timer task without storing its handle. */ + xReturn = xTaskCreate( prvTimerTask, "Tmr Svc", ( uint16_t ) configTIMER_TASK_STACK_DEPTH, NULL, (( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT ) + PRIORITIE_OFFSET, NULL); + } + #endif + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + configASSERT( xReturn ); + return xReturn; +} +/*-----------------------------------------------------------*/ + +TimerHandle_t xTimerCreate( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, const UBaseType_t uxAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ +{ +Timer_t *pxNewTimer; + + /* Allocate the timer structure. */ + if( xTimerPeriodInTicks == ( TickType_t ) 0U ) + { + pxNewTimer = NULL; + } + else + { + pxNewTimer = ( Timer_t * ) pvPortMalloc( sizeof( Timer_t ) ); + if( pxNewTimer != NULL ) + { + /* Ensure the infrastructure used by the timer service task has been + created/initialised. */ + prvCheckForValidListAndQueue(); + + /* Initialise the timer structure members using the function parameters. */ + pxNewTimer->pcTimerName = pcTimerName; + pxNewTimer->xTimerPeriodInTicks = xTimerPeriodInTicks; + pxNewTimer->uxAutoReload = uxAutoReload; + pxNewTimer->pvTimerID = pvTimerID; + pxNewTimer->pxCallbackFunction = pxCallbackFunction; + vListInitialiseItem( &( pxNewTimer->xTimerListItem ) ); + + traceTIMER_CREATE( pxNewTimer ); + } + else + { + traceTIMER_CREATE_FAILED(); + } + } + + /* 0 is not a valid value for xTimerPeriodInTicks. */ + configASSERT( ( xTimerPeriodInTicks > 0 ) ); + + return ( TimerHandle_t ) pxNewTimer; +} +/*-----------------------------------------------------------*/ + +BaseType_t xTimerGenericCommand( TimerHandle_t xTimer, const BaseType_t xCommandID, const TickType_t xOptionalValue, BaseType_t * const pxHigherPriorityTaskWoken, const TickType_t xTicksToWait ) +{ +BaseType_t xReturn = pdFAIL; +DaemonTaskMessage_t xMessage; + + /* Send a message to the timer service task to perform a particular action + on a particular timer definition. */ + if( xTimerQueue != NULL ) + { + /* Send a command to the timer service task to start the xTimer timer. */ + xMessage.xMessageID = xCommandID; + xMessage.u.xTimerParameters.xMessageValue = xOptionalValue; + xMessage.u.xTimerParameters.pxTimer = ( Timer_t * ) xTimer; + + if( xCommandID < tmrFIRST_FROM_ISR_COMMAND ) + { + if( xTaskGetSchedulerState() == taskSCHEDULER_RUNNING ) + { + xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xTicksToWait ); + } + else + { + xReturn = xQueueSendToBack( xTimerQueue, &xMessage, tmrNO_DELAY ); + } + } + else + { + xReturn = xQueueSendToBackFromISR( xTimerQueue, &xMessage, pxHigherPriorityTaskWoken ); + } + + traceTIMER_COMMAND_SEND( xTimer, xCommandID, xOptionalValue, xReturn ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_xTimerGetTimerDaemonTaskHandle == 1 ) + + TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) + { + /* If xTimerGetTimerDaemonTaskHandle() is called before the scheduler has been + started, then xTimerTaskHandle will be NULL. */ + configASSERT( ( xTimerTaskHandle != NULL ) ); + return xTimerTaskHandle; + } + +#endif +/*-----------------------------------------------------------*/ + +const char * pcTimerGetTimerName( TimerHandle_t xTimer ) +{ +Timer_t *pxTimer = ( Timer_t * ) xTimer; + + return pxTimer->pcTimerName; +} +/*-----------------------------------------------------------*/ + +static void prvProcessExpiredTimer( const TickType_t xNextExpireTime, const TickType_t xTimeNow ) +{ +BaseType_t xResult; +Timer_t * const pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList ); + + /* Remove the timer from the list of active timers. A check has already + been performed to ensure the list is not empty. */ + ( void ) uxListRemove( &( pxTimer->xTimerListItem ) ); + traceTIMER_EXPIRED( pxTimer ); + + /* If the timer is an auto reload timer then calculate the next + expiry time and re-insert the timer in the list of active timers. */ + if( pxTimer->uxAutoReload == ( UBaseType_t ) pdTRUE ) + { + /* The timer is inserted into a list using a time relative to anything + other than the current time. It will therefore be inserted into the + correct list relative to the time this task thinks it is now. */ + if( prvInsertTimerInActiveList( pxTimer, ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ), xTimeNow, xNextExpireTime ) == pdTRUE ) + { + /* The timer expired before it was added to the active timer + list. Reload it now. */ + xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xNextExpireTime, NULL, tmrNO_DELAY ); + configASSERT( xResult ); + ( void ) xResult; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Call the timer callback. */ + pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer ); +} +/*-----------------------------------------------------------*/ + +static void prvTimerTask( void *pvParameters ) +{ +TickType_t xNextExpireTime; +BaseType_t xListWasEmpty; + + /* Just to avoid compiler warnings. */ + ( void ) pvParameters; + + for( ;; ) + { + /* Query the timers list to see if it contains any timers, and if so, + obtain the time at which the next timer will expire. */ + xNextExpireTime = prvGetNextExpireTime( &xListWasEmpty ); + + /* If a timer has expired, process it. Otherwise, block this task + until either a timer does expire, or a command is received. */ + prvProcessTimerOrBlockTask( xNextExpireTime, xListWasEmpty ); + + /* Empty the command queue. */ + prvProcessReceivedCommands(); + } +} +/*-----------------------------------------------------------*/ + +static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, const BaseType_t xListWasEmpty ) +{ +TickType_t xTimeNow; +BaseType_t xTimerListsWereSwitched; + + vTaskSuspendAll(); + { + /* Obtain the time now to make an assessment as to whether the timer + has expired or not. If obtaining the time causes the lists to switch + then don't process this timer as any timers that remained in the list + when the lists were switched will have been processed within the + prvSampleTimeNow() function. */ + xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched ); + if( xTimerListsWereSwitched == pdFALSE ) + { + /* The tick count has not overflowed, has the timer expired? */ + if( ( xListWasEmpty == pdFALSE ) && ( xNextExpireTime <= xTimeNow ) ) + { + ( void ) xTaskResumeAll(); + prvProcessExpiredTimer( xNextExpireTime, xTimeNow ); + } + else + { + /* The tick count has not overflowed, and the next expire + time has not been reached yet. This task should therefore + block to wait for the next expire time or a command to be + received - whichever comes first. The following line cannot + be reached unless xNextExpireTime > xTimeNow, except in the + case when the current timer list is empty. */ + vQueueWaitForMessageRestricted( xTimerQueue, ( xNextExpireTime - xTimeNow ) ); + + if( xTaskResumeAll() == pdFALSE ) + { + /* Yield to wait for either a command to arrive, or the block time + to expire. If a command arrived between the critical section being + exited and this yield then the yield will not cause the task + to block. */ + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + else + { + ( void ) xTaskResumeAll(); + } + } +} +/*-----------------------------------------------------------*/ + +static TickType_t prvGetNextExpireTime( BaseType_t * const pxListWasEmpty ) +{ +TickType_t xNextExpireTime; + + /* Timers are listed in expiry time order, with the head of the list + referencing the task that will expire first. Obtain the time at which + the timer with the nearest expiry time will expire. If there are no + active timers then just set the next expire time to 0. That will cause + this task to unblock when the tick count overflows, at which point the + timer lists will be switched and the next expiry time can be + re-assessed. */ + *pxListWasEmpty = listLIST_IS_EMPTY( pxCurrentTimerList ); + if( *pxListWasEmpty == pdFALSE ) + { + xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxCurrentTimerList ); + } + else + { + /* Ensure the task unblocks when the tick count rolls over. */ + xNextExpireTime = ( TickType_t ) 0U; + } + + return xNextExpireTime; +} +/*-----------------------------------------------------------*/ + +static TickType_t prvSampleTimeNow( BaseType_t * const pxTimerListsWereSwitched ) +{ +TickType_t xTimeNow; +PRIVILEGED_DATA static TickType_t xLastTime = ( TickType_t ) 0U; /*lint !e956 Variable is only accessible to one task. */ + + xTimeNow = xTaskGetTickCount(); + + if( xTimeNow < xLastTime ) + { + prvSwitchTimerLists(); + *pxTimerListsWereSwitched = pdTRUE; + } + else + { + *pxTimerListsWereSwitched = pdFALSE; + } + + xLastTime = xTimeNow; + + return xTimeNow; +} +/*-----------------------------------------------------------*/ + +static BaseType_t prvInsertTimerInActiveList( Timer_t * const pxTimer, const TickType_t xNextExpiryTime, const TickType_t xTimeNow, const TickType_t xCommandTime ) +{ +BaseType_t xProcessTimerNow = pdFALSE; + + listSET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ), xNextExpiryTime ); + listSET_LIST_ITEM_OWNER( &( pxTimer->xTimerListItem ), pxTimer ); + + if( xNextExpiryTime <= xTimeNow ) + { + /* Has the expiry time elapsed between the command to start/reset a + timer was issued, and the time the command was processed? */ + if( ( xTimeNow - xCommandTime ) >= pxTimer->xTimerPeriodInTicks ) + { + /* The time between a command being issued and the command being + processed actually exceeds the timers period. */ + xProcessTimerNow = pdTRUE; + } + else + { + vListInsert( pxOverflowTimerList, &( pxTimer->xTimerListItem ) ); + } + } + else + { + if( ( xTimeNow < xCommandTime ) && ( xNextExpiryTime >= xCommandTime ) ) + { + /* If, since the command was issued, the tick count has overflowed + but the expiry time has not, then the timer must have already passed + its expiry time and should be processed immediately. */ + xProcessTimerNow = pdTRUE; + } + else + { + vListInsert( pxCurrentTimerList, &( pxTimer->xTimerListItem ) ); + } + } + + return xProcessTimerNow; +} +/*-----------------------------------------------------------*/ + +static void prvProcessReceivedCommands( void ) +{ +DaemonTaskMessage_t xMessage; +Timer_t *pxTimer; +BaseType_t xTimerListsWereSwitched, xResult; +TickType_t xTimeNow; + + while( xQueueReceive( xTimerQueue, &xMessage, tmrNO_DELAY ) != pdFAIL ) /*lint !e603 xMessage does not have to be initialised as it is passed out, not in, and it is not used unless xQueueReceive() returns pdTRUE. */ + { + #if ( INCLUDE_xTimerPendFunctionCall == 1 ) + { + /* Negative commands are pended function calls rather than timer + commands. */ + if( xMessage.xMessageID < ( BaseType_t ) 0 ) + { + const CallbackParameters_t * const pxCallback = &( xMessage.u.xCallbackParameters ); + + /* The timer uses the xCallbackParameters member to request a + callback be executed. Check the callback is not NULL. */ + configASSERT( pxCallback ); + + /* Call the function. */ + pxCallback->pxCallbackFunction( pxCallback->pvParameter1, pxCallback->ulParameter2 ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* INCLUDE_xTimerPendFunctionCall */ + + /* Commands that are positive are timer commands rather than pended + function calls. */ + if( xMessage.xMessageID >= ( BaseType_t ) 0 ) + { + /* The messages uses the xTimerParameters member to work on a + software timer. */ + pxTimer = xMessage.u.xTimerParameters.pxTimer; + + if( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) == pdFALSE ) + { + /* The timer is in a list, remove it. */ + ( void ) uxListRemove( &( pxTimer->xTimerListItem ) ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + traceTIMER_COMMAND_RECEIVED( pxTimer, xMessage.xMessageID, xMessage.u.xTimerParameters.xMessageValue ); + + /* In this case the xTimerListsWereSwitched parameter is not used, but + it must be present in the function call. prvSampleTimeNow() must be + called after the message is received from xTimerQueue so there is no + possibility of a higher priority task adding a message to the message + queue with a time that is ahead of the timer daemon task (because it + pre-empted the timer daemon task after the xTimeNow value was set). */ + xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched ); + + switch( xMessage.xMessageID ) + { + case tmrCOMMAND_START : + case tmrCOMMAND_START_FROM_ISR : + case tmrCOMMAND_RESET : + case tmrCOMMAND_RESET_FROM_ISR : + case tmrCOMMAND_START_DONT_TRACE : + /* Start or restart a timer. */ + if( prvInsertTimerInActiveList( pxTimer, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, xTimeNow, xMessage.u.xTimerParameters.xMessageValue ) == pdTRUE ) + { + /* The timer expired before it was added to the active + timer list. Process it now. */ + pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer ); + traceTIMER_EXPIRED( pxTimer ); + + if( pxTimer->uxAutoReload == ( UBaseType_t ) pdTRUE ) + { + xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, NULL, tmrNO_DELAY ); + configASSERT( xResult ); + ( void ) xResult; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + break; + + case tmrCOMMAND_STOP : + case tmrCOMMAND_STOP_FROM_ISR : + /* The timer has already been removed from the active list. + There is nothing to do here. */ + break; + + case tmrCOMMAND_CHANGE_PERIOD : + case tmrCOMMAND_CHANGE_PERIOD_FROM_ISR : + pxTimer->xTimerPeriodInTicks = xMessage.u.xTimerParameters.xMessageValue; + configASSERT( ( pxTimer->xTimerPeriodInTicks > 0 ) ); + + /* The new period does not really have a reference, and can be + longer or shorter than the old one. The command time is + therefore set to the current time, and as the period cannot be + zero the next expiry time can only be in the future, meaning + (unlike for the xTimerStart() case above) there is no fail case + that needs to be handled here. */ + ( void ) prvInsertTimerInActiveList( pxTimer, ( xTimeNow + pxTimer->xTimerPeriodInTicks ), xTimeNow, xTimeNow ); + break; + + case tmrCOMMAND_DELETE : + /* The timer has already been removed from the active list, + just free up the memory. */ + vPortFree( pxTimer ); + break; + + default : + /* Don't expect to get here. */ + break; + } + } + } +} +/*-----------------------------------------------------------*/ + +static void prvSwitchTimerLists( void ) +{ +TickType_t xNextExpireTime, xReloadTime; +List_t *pxTemp; +Timer_t *pxTimer; +BaseType_t xResult; + + /* The tick count has overflowed. The timer lists must be switched. + If there are any timers still referenced from the current timer list + then they must have expired and should be processed before the lists + are switched. */ + while( listLIST_IS_EMPTY( pxCurrentTimerList ) == pdFALSE ) + { + xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxCurrentTimerList ); + + /* Remove the timer from the list. */ + pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList ); + ( void ) uxListRemove( &( pxTimer->xTimerListItem ) ); + traceTIMER_EXPIRED( pxTimer ); + + /* Execute its callback, then send a command to restart the timer if + it is an auto-reload timer. It cannot be restarted here as the lists + have not yet been switched. */ + pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer ); + + if( pxTimer->uxAutoReload == ( UBaseType_t ) pdTRUE ) + { + /* Calculate the reload value, and if the reload value results in + the timer going into the same timer list then it has already expired + and the timer should be re-inserted into the current list so it is + processed again within this loop. Otherwise a command should be sent + to restart the timer to ensure it is only inserted into a list after + the lists have been swapped. */ + xReloadTime = ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ); + if( xReloadTime > xNextExpireTime ) + { + listSET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ), xReloadTime ); + listSET_LIST_ITEM_OWNER( &( pxTimer->xTimerListItem ), pxTimer ); + vListInsert( pxCurrentTimerList, &( pxTimer->xTimerListItem ) ); + } + else + { + xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xNextExpireTime, NULL, tmrNO_DELAY ); + configASSERT( xResult ); + ( void ) xResult; + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + pxTemp = pxCurrentTimerList; + pxCurrentTimerList = pxOverflowTimerList; + pxOverflowTimerList = pxTemp; +} +/*-----------------------------------------------------------*/ + +static void prvCheckForValidListAndQueue( void ) +{ + /* Check that the list from which active timers are referenced, and the + queue used to communicate with the timer service, have been + initialised. */ + taskENTER_CRITICAL(); + { + if( xTimerQueue == NULL ) + { + vListInitialise( &xActiveTimerList1 ); + vListInitialise( &xActiveTimerList2 ); + pxCurrentTimerList = &xActiveTimerList1; + pxOverflowTimerList = &xActiveTimerList2; + xTimerQueue = xQueueCreate( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, sizeof( DaemonTaskMessage_t ) ); + configASSERT( xTimerQueue ); + + #if ( configQUEUE_REGISTRY_SIZE > 0 ) + { + if( xTimerQueue != NULL ) + { + vQueueAddToRegistry( xTimerQueue, "TmrQ" ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configQUEUE_REGISTRY_SIZE */ + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + taskEXIT_CRITICAL(); +} +/*-----------------------------------------------------------*/ + +BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer ) +{ +BaseType_t xTimerIsInActiveList; +Timer_t *pxTimer = ( Timer_t * ) xTimer; + + /* Is the timer in the list of active timers? */ + taskENTER_CRITICAL(); + { + /* Checking to see if it is in the NULL list in effect checks to see if + it is referenced from either the current or the overflow timer lists in + one go, but the logic has to be reversed, hence the '!'. */ + xTimerIsInActiveList = ( BaseType_t ) !( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) ); + } + taskEXIT_CRITICAL(); + + return xTimerIsInActiveList; +} /*lint !e818 Can't be pointer to const due to the typedef. */ +/*-----------------------------------------------------------*/ + +void *pvTimerGetTimerID( const TimerHandle_t xTimer ) +{ +Timer_t * const pxTimer = ( Timer_t * ) xTimer; + + return pxTimer->pvTimerID; +} +/*-----------------------------------------------------------*/ + +#if( INCLUDE_xTimerPendFunctionCall == 1 ) + + BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, BaseType_t *pxHigherPriorityTaskWoken ) + { + DaemonTaskMessage_t xMessage; + BaseType_t xReturn; + + /* Complete the message with the function parameters and post it to the + daemon task. */ + xMessage.xMessageID = tmrCOMMAND_EXECUTE_CALLBACK_FROM_ISR; + xMessage.u.xCallbackParameters.pxCallbackFunction = xFunctionToPend; + xMessage.u.xCallbackParameters.pvParameter1 = pvParameter1; + xMessage.u.xCallbackParameters.ulParameter2 = ulParameter2; + + xReturn = xQueueSendFromISR( xTimerQueue, &xMessage, pxHigherPriorityTaskWoken ); + + tracePEND_FUNC_CALL_FROM_ISR( xFunctionToPend, pvParameter1, ulParameter2, xReturn ); + + return xReturn; + } + +#endif /* INCLUDE_xTimerPendFunctionCall */ +/*-----------------------------------------------------------*/ + +#if( INCLUDE_xTimerPendFunctionCall == 1 ) + + BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, TickType_t xTicksToWait ) + { + DaemonTaskMessage_t xMessage; + BaseType_t xReturn; + + /* Complete the message with the function parameters and post it to the + daemon task. */ + xMessage.xMessageID = tmrCOMMAND_EXECUTE_CALLBACK; + xMessage.u.xCallbackParameters.pxCallbackFunction = xFunctionToPend; + xMessage.u.xCallbackParameters.pvParameter1 = pvParameter1; + xMessage.u.xCallbackParameters.ulParameter2 = ulParameter2; + + xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xTicksToWait ); + + tracePEND_FUNC_CALL( xFunctionToPend, pvParameter1, ulParameter2, xReturn ); + + return xReturn; + } + +#endif /* INCLUDE_xTimerPendFunctionCall */ +/*-----------------------------------------------------------*/ + +/* This entire source file will be skipped if the application is not configured +to include software timer functionality. If you want to include software timer +functionality then ensure configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */ +#endif /* configUSE_TIMERS == 1 */ + + + diff --git a/component/os/os_dep/include/mailbox.h b/component/os/os_dep/include/mailbox.h new file mode 100644 index 0000000..e3b5f47 --- /dev/null +++ b/component/os/os_dep/include/mailbox.h @@ -0,0 +1,127 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * + ******************************************************************************/ +#ifndef __MAILBOX_H_ +#define __MAILBOX_H_ + +#include "hal_api.h" +#include "osdep_api.h" +#include "hal_util.h" +#ifdef CONFIG_FREERTOS +#include "queue.h" +#endif + +#define MBOX_WAIT_NO_TIMEOUT 0xffffffff // waiting for send/receive message with no timeout +#define MBOX_WAIT_NONE 0 // No wait for send/receive message + +typedef enum _MAILBOX_ID_ { + MBOX_ID_WLAN = 0, + MBOX_ID_UART = 1, + MBOX_ID_I2C = 2, + MBOX_ID_I2S = 3, + MBOX_ID_SPI = 4, + MBOX_ID_SDIO = 5, + MBOX_ID_SDIO_MP = 6, + + MBOX_ID_MAX = 0xff +} MAILBOX_ID; + +#if defined(CONFIG_SDIO_DEVICE_EN) && defined(CONFIG_SDIO_DEVICE_NORMAL) +typedef enum _MSG_TYPE_SDIO { + MSG_SDIO_RX_PKT=1, // request to send a SDIO RX packet to the host side + MSG_SDIO_C2H=2, // request to send a C2H message + MSG_SDIO_RPWM=3, // request to set the RPWM + MSG_SDIO_MP_LOOP_TXPKT=4, // request to loopback this TX packet + + MSG_SDIO_MAX=0xff +} MSG_TYPE_SDIO; +#endif // end of "#ifdef CONFIG_SDIO_DEVICE_EN" + +/* the data structure of a MailBox to deliver message blocks */ +typedef struct _RTL_MAILBOX_ { + void *mbox_hdl; // the mailbox handle which return from OS create queue API + _Sema *pWakeSema; // the semaphore to wakeup the message receiving task + _LIST mbox_list; // the link list to chain all created mailbox + u8 mbox_id; /* the ID of this Mailbox, this ID is + used to locate the MBox for send/get message */ +} RTL_MAILBOX, *PRTL_MAILBOX; + +/* the data structure of a message block */ +typedef struct _RTL_MSG_BLK { + u8 MsgType; // the message type + u8 Reserved; // reserved + u16 DateLen; // the vaild data length of the pBuf + u32 Para; // the optional parameters associated with this message type + u8 *pBuf; // point to a data buffer associated with this message type +} MSG_BLK, *PMSG_BLK; + +/* the data structure for system level message block management */ +typedef struct _RTL_MBOX_ROOT_ { + _LIST mbox_list; // the link list of all created mailbox + _Mutex Mutex; // the Mutex to protect the mailbox create/delete procedure + u8 isInitialed; // is this Mailbox link-list initialed +} RTL_MBOX_ROOT, *PRTL_MBOX_ROOT; + +// Export Funcction API +extern PRTL_MAILBOX RtlMailboxCreate( + IN u8 MboxID, + IN u32 MboxSize, + IN _Sema *pWakeSema +); + +extern VOID RtlMailboxDel( + IN PRTL_MAILBOX MboxHdl +); + +extern u8 RtlMailboxSendToBack( + IN u8 MboxID, + IN MSG_BLK *pMsg, + IN u32 MSToWait, + IN u8 IsFromISR +); + +extern u8 RtlMailboxSendToFront( + IN u8 MboxID, + IN MSG_BLK *pMsg, + IN u32 MSToWait, + IN u8 IsFromISR +); + +extern u8 RtlMailboxReceive( + IN u8 MboxID, + OUT MSG_BLK *pMsg, + IN u32 MSToWait, + IN u8 IsFromISR +); + +extern u8 RtlMailboxPeek( + IN u8 MboxID, + OUT MSG_BLK *pMsg, + IN u32 MSToWait, + IN u8 IsFromISR +); + +extern u32 RtlMailboxMsgWaiting( + IN u8 MboxID, + IN u8 IsFromISR +); + + +#endif // #ifndef __MAILBOX_H_ + diff --git a/component/os/os_dep/include/os_support.h b/component/os/os_dep/include/os_support.h new file mode 100644 index 0000000..6020062 --- /dev/null +++ b/component/os/os_dep/include/os_support.h @@ -0,0 +1,344 @@ + /****************************************************************************** + * + * Name: sys-support.h - System type support for Linux + * $Revision: 1.1.1.1 $ + * + *****************************************************************************/ + +#ifndef __OS_SUPPORT_H__ +#define __OS_SUPPORT_H__ + + +#include +#include +#include "os_support.h" +//#include "diag.h" + + + +#if 0 +#define __init +#define __exit +#define __devinit +#define __devexit +#endif +#define RTL_HZ 100 + +#define SemaInit(sem, value) vSemaphoreCreateBinary(sem) +#define SemaPost(sem) xSemaphoreGive(sem) +#define SemaWait(sem, block_time) xSemaphoreTake(sem, block_time) +//#define printk DiagPrintf + +#define SpinLockInit(lock) do { } while (0) +#define SpinLock(x) do { } while (0) +#define SpinUnlock(x) do { } while (0) +#define SpinLockBh(x) do { } while (0) +#define SpinUnlockBh(x) do { } while (0) +#ifdef PLATFORM_FREERTOS +#define RestoreFlags() portEXIT_CRITICAL() +#define SaveAndCli() portENTER_CRITICAL() +#define SpinLockIrqSave(lock, flags) SaveAndCli() +#define SpinUnlockIrqRestore(l, f) RestoreFlags() +#else +#define RestoreFlags(x) portENABLE_INTERRUPTS() +#define SaveAndCli(x) portDISABLE_INTERRUPTS() +#define SpinLockIrqSave(lock, flags) SaveAndCli(flags) +#define SpinUnlockIrqRestore(l, f) RestoreFlags(f) +#endif + + +//#define RtlKmalloc(size, flag) pvPortMallocAligned(size, 0) +#define RtlKmalloc(size, flag) pvPortMalloc(size) +#define RtlKfree(pv) vPortFreeAligned(pv) + + + +#ifdef CONFIG_TIMER_MODULE +extern _LONG_CALL_ u32 HalDelayUs(u32 us); +#define __Delay(t) HalDelayUs(t) +#else +static __inline__ u32 __Delay(u32 us) +{ + DBG_8195A("No Delay: please enable hardware Timer\n"); +} +#endif + + +#define Mdelay(t) __Delay(t*1000) +#define Udelay(t) __Delay(t) + + +#define ASSERT(_bool_) do { } while (0) + +//#define panic_printk DiagPrintf +//#define sprintf DiagPrintf +//#define diag_sprintf DiagPrintf + + +//1TODO: Need check again; the below just for compile ok ; chris + +/* + * ATOMIC_READ - read atomic variable + * @v: pointer of type atomic_t + * + * Atomically reads the value of @v. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +//#define AtomicRead(v) ((*v)) + +extern __inline__ u32 +AtomicRead( + IN atomic_t * v +) +{ +#ifdef PLATFORM_FREERTOS + u32 Temp; + + SaveAndCli(); + Temp = v->counter; + RestoreFlags(); + + return Temp; + +#else + u32 Temp, Flags; + + SaveAndCli(Flags); + Temp = v->counter; + RestoreFlags(Flags); + + return Temp; +#endif +} + +/* + * ATOMIC_SET - set atomic variable + * @v: pointer of type atomic_t + * @i: required value + * + * Atomically sets the value of @v to @i. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +//#define AtomicSet(v,i) ((v)->counter = (i)) + +extern __inline__ VOID +AtomicSet( + IN u32 i, + IN atomic_t * v +) +{ +#ifdef PLATFORM_FREERTOS + SaveAndCli(); + v->counter = i; + RestoreFlags(); +#else + u32 Flags; + + SaveAndCli(Flags); + v->counter = i; + RestoreFlags(Flags); +#endif +} + +/* + * The MIPS I implementation is only atomic with respect to + * interrupts. R3000 based multiprocessor machines are rare anyway ... + * + * AtomicAdd - add integer to atomic variable + * @i: integer value to add + * @v: pointer of type atomic_t + * + * Atomically adds @i to @v. Note that the guaranteed useful range + * of an atomic_t is only 24 bits. + */ +extern __inline__ VOID +AtomicAdd( + IN u32 i, + IN atomic_t * v +) +{ +#ifdef PLATFORM_FREERTOS + SaveAndCli(); + v->counter += i; + RestoreFlags(); +#else + u32 Flags; + + SaveAndCli(Flags); + v->counter += i; + RestoreFlags(Flags); +#endif +} + +/* + * AtomicSub - subtract the atomic variable + * @i: integer value to subtract + * @v: pointer of type atomic_t + * + * Atomically subtracts @i from @v. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +extern __inline__ void +AtomicSub( + IN u32 i, + IN atomic_t * v +) +{ +#ifdef PLATFORM_FREERTOS + SaveAndCli(); + v->counter -= i; + RestoreFlags(); +#else + u32 Flags; + + SaveAndCli(Flags); + v->counter -= i; + RestoreFlags(Flags); +#endif +} + +extern __inline__ u32 +AtomicAddReturn( + IN u32 i, + IN atomic_t * v +) +{ +#ifdef PLATFORM_FREERTOS + u32 Temp; + + SaveAndCli(); + Temp = v->counter; + Temp += i; + v->counter = Temp; + RestoreFlags(); + + return Temp; + +#else + u32 Temp, Flags; + + SaveAndCli(Flags); + Temp = v->counter; + Temp += i; + v->counter = Temp; + RestoreFlags(Flags); + + return Temp; +#endif +} + +extern __inline__ u32 +AtomicSubReturn( + IN u32 i, + IN atomic_t * v +) +{ +#ifdef PLATFORM_FREERTOS + u32 Temp; + + SaveAndCli(); + Temp = v->counter; + Temp -= i; + v->counter = Temp; + RestoreFlags(); + + return Temp; + +#else + + u32 Temp, Flags; + + SaveAndCli(Flags); + Temp = v->counter; + Temp -= i; + v->counter = Temp; + RestoreFlags(Flags); + + return Temp; +#endif +} + +/* + * ATOMIC_INC - increment atomic variable + * @v: pointer of type atomic_t + * + * Atomically increments @v by 1. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +#define AtomicInc(v) AtomicAdd(1,(v)) + +#define AtomicIncReturn(v) AtomicAddReturn(1,(v)) + +/* + * ATOMIC_DEC - decrement and test + * @v: pointer of type atomic_t + * + * Atomically decrements @v by 1. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +#define AtomicDec(v) AtomicSub(1,(v)) + +#define AtomicDecReturn(v) AtomicSubReturn(1,(v)) + +/* + * ATOMIC_DEC_AND_TEST - decrement by 1 and test + * @v: pointer of type atomic_t + * + * Atomically decrements @v by 1 and + * returns true if the result is 0, or false for all other + * cases. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +#define AtomicDecAndTest(v) (AtomicSubReturn(1, (v)) == 0) + +/* Not needed on 64bit architectures */ +static __inline__ u32 +__Div64_32( + IN __uint64_t *n, + IN u32 base +) +{ + __uint64_t rem = *n; + __uint64_t b = base; + __uint64_t res, d = 1; + u32 high = rem >> 32; + + /* Reduce the thing a bit first */ + res = 0; + if (high >= base) { + high /= base; + res = (__uint64_t) high << 32; + rem -= (__uint64_t) (high*base) << 32; + } + + while ((__int64_t)b > 0 && b < rem) { + b = b+b; + d = d+d; + } + + do { + if (rem >= b) { + rem -= b; + res += d; + } + b >>= 1; + d >>= 1; + } while (d); + + *n = res; + return rem; +} + +#define DO_DIV(n,base) ({ \ + unsigned int __base = (base); \ + unsigned int __rem; \ + (void)(((typeof((n)) *)0) == ((__uint64_t *)0)); \ + if (((n) >> 32) == 0) { \ + __rem = (unsigned int)(n) % __base; \ + (n) = (unsigned int)(n) / __base; \ + } else \ + __rem = __Div64_32(&(n), __base); \ + __rem; \ + }) + +#endif /* __SYS_SUPPORT_H__ */ diff --git a/component/os/os_dep/include/os_timer.h b/component/os/os_dep/include/os_timer.h new file mode 100644 index 0000000..b2a6529 --- /dev/null +++ b/component/os/os_dep/include/os_timer.h @@ -0,0 +1,215 @@ +/****************************************************************************** + * + * Name: sys-support.h - System type support for Linux + * $Revision: 1.1.1.1 $ + * + *****************************************************************************/ + +#ifndef __OS_TIMER_H__ +#define __OS_TIMER_H__ + +#include "diag.h" +#include "os_support.h" +#include "timers.h" + + +#define JIFFIES xTaskGetTickCount() + +enum { + TIMER_NO_INIT = 0, + TIMER_INIT = 1, + TIMER_START = 2, + TIMER_DISABLE = 3 +}; + +struct TIMER_LIST { + xTimerHandle TimeHdl; + u32 Flag; + unsigned long Data; + VOID (*Function)(void *); + u32 TimerID; +}; + +static inline VOID +InitTimer( + IN struct TIMER_LIST *Timer +) +{ +#ifdef RTK_MODE_TIMER + u32 data = Timer->Data; +#endif +#ifndef PLATFORM_FREERTOS + u32 Flags; +#endif + u32 TimerID = Timer->TimerID; + VOID (*Function)(VOID *) = Timer->Function; +// xTimerHandle timer_handle; + + +#ifdef PLATFORM_FREERTOS + SaveAndCli(); +#else + SaveAndCli(Flags); +#endif + + if (Timer->Flag != TIMER_DISABLE) { + if (Timer->Flag == TIMER_NO_INIT) { + Timer->TimeHdl = xTimerCreate( (const char *)"Timer", // Just a test name, not used by the kernel. + ( 100 ), // The timer period in ticks. + pdFALSE, // The timers will auto-reload themselves when they expire. + ( void * ) TimerID, // Assign each timer a unique id equal to its array index. + Function + #ifdef RTK_MODE_TIMER + ,data // Each timer calls the same callback when it expires. + #endif + ); + if (NULL == Timer->TimeHdl) { + DBG_ERROR_LOG("\rInitial Timer fail !!!!!!!!!\n"); + } + else { + TimerID++; + } + + Timer->Flag = TIMER_INIT; + } + else if (Timer->Flag == TIMER_START) { + xTimerStop(Timer->TimeHdl,0); + Timer->Flag = TIMER_DISABLE; + } + } + +#ifdef PLATFORM_FREERTOS + RestoreFlags(); +#else + RestoreFlags(Flags); +#endif +} + +static inline void +ModTimer( + IN struct TIMER_LIST *Timer, + IN u32 TimeoutTicks +) +{ +#ifndef PLATFORM_FREERTOS + u32 Flags; +#endif + + void (*Function)(void *) = Timer->Function; + +#ifdef PLATFORM_FREERTOS + SaveAndCli(); +#else + SaveAndCli(Flags); +#endif + + if (Timer->Flag == TIMER_NO_INIT) { + if (Timer->Function) { + Timer->TimeHdl = xTimerCreate((const char *)"Timer", // Just a text name, not used by the kernel. + ( 100 ), // The timer period in ticks. + pdFALSE, // The timers will auto-reload themselves when they expire. + ( void * ) Timer->TimerID, // Assign each timer a unique id equal to its array index. + Function + #ifdef RTK_MODE_TIMER + ,Timer->Data // Each timer calls the same callback when it expires. + #endif + ); + if (NULL == Timer->TimeHdl) { + DBG_ERROR_LOG("\rInitial Timer fail !!!!!!!!!\n"); + } + else { + Timer->TimerID++; + } + + Timer->Flag = TIMER_INIT; + } + else { + //printf("###mod_timer() not initilized, timer->flag=%d timer->function=%p timeout_ticks=%llu###\n", timer->flag, timer->function, timeout_ticks); +#ifdef PLATFORM_FREERTOS + RestoreFlags(); +#else + RestoreFlags(Flags); +#endif + return; + } + } + else if (Timer->Flag == TIMER_START) { + xTimerStop(Timer->TimeHdl,0); + Timer->Flag = TIMER_DISABLE; + } + + TimeoutTicks -= xTaskGetTickCount(); + if (TimeoutTicks <= 0) + TimeoutTicks = 2; + + if (xTimerStart(Timer->TimeHdl, TimeoutTicks )) + Timer->Flag = TIMER_START; + else + DBG_ERROR_LOG("\r###mod_timer() - no slots available###\n"); +#ifdef PLATFORM_FREERTOS + RestoreFlags(); +#else + RestoreFlags(Flags); +#endif +} + + +static inline int +TimerPending ( + IN const struct TIMER_LIST *Timer +) +{ + if (Timer->TimeHdl && Timer->Flag != TIMER_NO_INIT) + return 1; + else + return 0; +} + +static inline void +DelTimerSync( + IN struct TIMER_LIST *Timer +) +{ +#ifdef PLATFORM_FREERTOS + SaveAndCli(); +#else + u32 Flags; + SaveAndCli(Flags); +#endif + if (Timer->TimeHdl && Timer->Flag != TIMER_INIT) { + if (Timer->Flag == TIMER_START) + xTimerStop(Timer->TimeHdl, 0); + + xTimerDelete(Timer->TimeHdl, 0); + Timer->Flag = TIMER_NO_INIT; + } + +#ifdef PLATFORM_FREERTOS + RestoreFlags(); +#else + RestoreFlags(Flags); +#endif +} + + /* + * These inlines deal with timer wrapping correctly. You are + * strongly encouraged to use them + * 1. Because people otherwise forget + * 2. Because if the timer wrap changes in future you wont have to + * alter your driver code. + * + * time_after(a,b) returns true if the time a is after time b. + * + * Do this with "<0" and ">=0" to only test the sign of the result. A + * good compiler would generate better code (and a really good compiler + * wouldn't care). Gcc is currently neither. + */ + #define TIME_AFTER(a,b) ((long)(b) - (long)(a) < 0) + #define TIMER_BEFORE(a,b) TIME_AFTER(b,a) + + #define TIME_AFTER_EQ(a,b) ((long)(a) - (long)(b) >= 0) + #define TIMER_BEFORE_EQ(a,b) TIME_AFTER_EQ(b,a) + + + +#endif //__OS_TIMER_H__ \ No newline at end of file diff --git a/component/os/os_dep/include/osdep_api.h b/component/os/os_dep/include/osdep_api.h new file mode 100644 index 0000000..058bccf --- /dev/null +++ b/component/os/os_dep/include/osdep_api.h @@ -0,0 +1,561 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * + ******************************************************************************/ +#ifndef __OSDEP_API_H_ +#define __OSDEP_API_H_ + +#include "os_timer.h" +#include "os_support.h" +#include "semphr.h" + +#if 0 +/* Structure used to pass parameters to each task. */ +typedef struct SEMAPHORE_PARAMETERS +{ + xSemaphoreHandle xSemaphore; +// volatile unsigned long *pulSharedVariable; + portTickType xBlockTime; +} xSemaphoreParameters; +#endif + +//#define RTW_STATUS_TIMEDOUT -110 + + +#define MAX_SEMA_COUNT 32 /* the maximum count of a semaphore */ + +typedef xSemaphoreHandle _Sema; +typedef xSemaphoreHandle _Mutex; +typedef u32 _Lock; +typedef struct TIMER_LIST _Timer; + +//typedef unsigned char _buffer; + +typedef unsigned long _IRQL; +//typedef struct net_device * _nic_hdl; +typedef xTaskHandle _THREAD_HDL_; +typedef VOID THREAD_RETURN; +typedef VOID* THREAD_CONTEXT; + + +#ifndef mdelay +#define mdelay(t) ((t/portTICK_RATE_MS)>0)?(vTaskDelay(t/portTICK_RATE_MS)):(vTaskDelay(1)) +#endif + +#ifndef udelay +#define udelay(t) ((t/(portTICK_RATE_MS*1000))>0)?vTaskDelay(t/(portTICK_RATE_MS*1000)):(vTaskDelay(1)) +#endif + +/* to delete/start/stop a timer it will send a message to the timer task through a message queue, + so we define the max wait time for message sending */ +#define RTL_TIMER_API_MAX_BLOCK_TIME 1000 // unit is ms +#define RTL_TIMER_API_MAX_BLOCK_TICKS (RTL_TIMER_API_MAX_BLOCK_TIME/portTICK_RATE_MS) + +typedef VOID +(*RTL_TIMER_CALL_BACK)( + void *pContext +); + +typedef struct _RTL_TIMER{ +#ifdef PLATFORM_FREERTOS + xTimerHandle TimerHandle; // the timer handle of created FreeRTOS soft-timer +#endif + RTL_TIMER_CALL_BACK CallBackFunc; // Callback function of this timer + u32 msPeriod; // The period of this timer + void *Context; // Timer specific context. + u8 isPeriodical; // is a periodical timer + u8 TimerName[35]; // the Name of timer +}RTL_TIMER, *PRTL_TIMER; + +__inline static VOID +RtlEnterCritical(VOID) +{ + portENTER_CRITICAL(); +} + +__inline static VOID +RtlExitCritical(VOID) +{ + portEXIT_CRITICAL(); +} + +__inline static VOID +RtlEnterCriticalBh( + IN _Lock *plock, + IN _IRQL *pirqL +) +{ + SpinLockBh(plock); +} + +__inline static VOID +RtlExitCriticalBh( + IN _Lock *plock, + IN _IRQL *pirqL +) +{ + SpinUnlockBh(plock); +} +__inline static u32 +RtlEnterCriticalMutex( + IN _Mutex *pmutex, + IN _IRQL *pirqL +) +{ + u32 ret = 0; + xSemaphoreTake(*pmutex, portMAX_DELAY); + return ret; +} + + +__inline static VOID +RtlExitCriticalMutex( + IN _Mutex *pmutex, + IN _IRQL *pirqL +) +{ + xSemaphoreGive(*pmutex); +} + +__inline static VOID +RtlInitTimer( + IN _Timer *ptimer, + IN VOID *Data, + IN VOID (*pfunc)(VOID *), + IN VOID* cntx +) +{ + ptimer->Function = pfunc; + ptimer->Data = (unsigned long)cntx; + InitTimer(ptimer); +} + +__inline static VOID +RtlSetTimer( + IN _Timer *ptimer, + IN u32 delay_time +) +{ + ModTimer(ptimer , (JIFFIES+(delay_time*RTL_HZ/1000))); +} + +__inline static VOID +RtlCancelTimer( + IN _Timer *ptimer, + IN u8 *bcancelled +) +{ + DelTimerSync(ptimer); + *bcancelled= _TRUE;//TRUE ==1; FALSE==0 +} + +__inline static u32 +RtlSystime2Ms( + IN u32 systime +) +{ + return systime * 1000 / RTL_HZ; +} + + + +__inline static u32 +RtlMs2Systime( + IN u32 ms +) +{ + return ms * RTL_HZ / 1000; +} + +extern u8* RtlZmalloc(u32 sz); +extern u8* RtlMalloc(u32 sz); +extern VOID RtlMfree(u8 *pbuf, u32 sz); + +extern VOID* RtlMalloc2d(u32 h, u32 w, u32 size); +extern VOID RtlMfree2d(VOID *pbuf, u32 h, u32 w, u32 size); + +extern VOID RtlInitSema(_Sema *sema, u32 init_val); +extern VOID RtlFreeSema(_Sema *sema); +extern VOID RtlUpSema(_Sema *sema); +extern VOID RtlUpSemaFromISR(_Sema *sema); +extern u32 RtlDownSema(_Sema *sema); +extern u32 RtlDownSemaWithTimeout(_Sema *sema, u32 ms); + +extern VOID RtlMutexInit(_Mutex *pmutex); +extern VOID RtlMutexFree(_Mutex *pmutex); + +extern VOID RtlSpinlockInit(_Lock *plock); +extern VOID RtlSpinlockFree(_Lock *plock); +extern VOID RtlSpinlock(_Lock *plock); +extern VOID RtlSpinunlock(_Lock *plock); +extern VOID RtlSpinlockEx(_Lock *plock); +extern VOID RtlSpinunlockEx(_Lock *plock); + +extern VOID RtlSleepSchedulable(u32 ms); + +extern VOID RtlMsleepOS(u32 ms); +extern VOID RtlUsleepOS(u32 us); +extern VOID RtlMdelayOS(u32 ms); +extern VOID RtlUdelayOS(u32 us); + +//extern VOID rtw_mdelay_os(u32 ms); +//extern VOID rtw_udelay_os(u32 us); + +//1TODO: Need Check if we need add this api +extern VOID RtlYieldOS(VOID); + +#define RtlUpMutex(mutex) RtlUpSema(mutex) +#define RtlDownMutex(mutex) RtlDownSema(mutex) + +__inline static u8 +RtlCancelTimerEx( + IN _Timer *ptimer +) +{ + DelTimerSync(ptimer); + return 0; +} + + +static __inline VOID +ThreadEnter( + IN char *name +) +{ + DBG_8195A("\rRTKTHREAD_enter %s\n", name); +} + + + +#define ThreadExit() do{DBG_8195A("\rRTKTHREAD_exit %s\n", __FUNCTION__);}while(0) + +__inline static VOID +FlushSignalsThread(VOID) +{ +#ifdef PLATFORM_LINUX + if (signal_pending (current)) + { + flush_signals(current); + } +#endif +} + + +#define RTL_RND(sz, r) ((((sz)+((r)-1))/(r))*(r)) +#define RTL_RND4(x) (((x >> 2) + (((x & 3) == 0) ? 0: 1)) << 2) + +__inline static u32 +RtlRnd4( + IN u32 sz +) +{ + + u32 val; + + val = ((sz >> 2) + ((sz & 3) ? 1: 0)) << 2; + + return val; + +} + +__inline static u32 +RtlRnd8( + IN u32 sz +) +{ + + u32 val; + + val = ((sz >> 3) + ((sz & 7) ? 1: 0)) << 3; + + return val; + +} + +__inline static u32 +RtlRnd128( + IN u32 sz +) +{ + + u32 val; + + val = ((sz >> 7) + ((sz & 127) ? 1: 0)) << 7; + + return val; + +} + +__inline +static u32 RtlRnd256( + IN u32 sz +) +{ + + u32 val; + + val = ((sz >> 8) + ((sz & 255) ? 1: 0)) << 8; + + return val; + +} + +__inline static u32 +RtlRnd512( + IN u32 sz +) +{ + + u32 val; + + val = ((sz >> 9) + ((sz & 511) ? 1: 0)) << 9; + + return val; + +} + +__inline static u32 +BitShift( + IN u32 BitMask +) +{ + u32 i; + + for (i = 0; i <= 31; i++) + if (((BitMask>>i) & 0x1) == 1) break; + + return i; +} + + +//#ifdef __GNUC__ +#ifdef PLATFORM_LINUX +#define STRUCT_PACKED __attribute__ ((packed)) +#else +#define STRUCT_PACKED +#endif + + + + + + +//Atomic integer operations +#define RTL_ATOMIC_T atomic_t + + + +extern inline VOID +RTL_ATOMIC_SET( + IN RTL_ATOMIC_T *v, + IN u32 i +) +{ + AtomicSet(i,v); +} + +extern inline uint32_t +RTL_ATOMIC_READ( + IN RTL_ATOMIC_T *v +) +{ + return AtomicRead(v); +} + +extern inline VOID +RTL_ATOMIC_ADD( + IN RTL_ATOMIC_T *v, + IN u32 i +) +{ + AtomicAdd(i,v); +} +extern inline VOID +RTL_ATOMIC_SUB( + IN RTL_ATOMIC_T *v, + IN u32 i +) +{ + AtomicSub(i,v); +} + +extern inline VOID +RTL_ATOMIC_INC( + IN RTL_ATOMIC_T *v +) +{ + AtomicInc(v); +} + +extern inline VOID +RTL_ATOMIC_DEC( + IN RTL_ATOMIC_T *v +) +{ + AtomicDec(v); +} + +extern inline u32 +RTL_ATOMIC_ADD_RETURN( + IN RTL_ATOMIC_T *v, + IN u32 i +) +{ + return AtomicAddReturn(i,v); +} + +extern inline u32 +RTL_ATOMIC_SUB_RETURN( + IN RTL_ATOMIC_T *v, + IN u32 i +) +{ + return AtomicSubReturn(i,v); +} + +extern inline u32 +RTL_ATOMIC_INC_RETURN( + IN RTL_ATOMIC_T *v +) +{ + return AtomicIncReturn(v); +} + +extern inline u32 +RTL_ATOMIC_DEC_RETURN( + IN RTL_ATOMIC_T *v +) +{ + return AtomicDecReturn(v); +} + + + + +extern u64 RtlModular64(u64 x, u64 y); + + +/* Macros for handling unaligned memory accesses */ +#if 0 +#define RTW_GET_BE16(a) ((u16) (((a)[0] << 8) | (a)[1])) +#define RTW_PUT_BE16(a, val) \ + do { \ + (a)[0] = ((u16) (val)) >> 8; \ + (a)[1] = ((u16) (val)) & 0xff; \ + } while (0) + +#define RTW_GET_LE16(a) ((u16) (((a)[1] << 8) | (a)[0])) +#define RTW_PUT_LE16(a, val) \ + do { \ + (a)[1] = ((u16) (val)) >> 8; \ + (a)[0] = ((u16) (val)) & 0xff; \ + } while (0) + +#define RTW_GET_BE24(a) ((((u32) (a)[0]) << 16) | (((u32) (a)[1]) << 8) | \ + ((u32) (a)[2])) +#define RTW_PUT_BE24(a, val) \ + do { \ + (a)[0] = (u8) ((((u32) (val)) >> 16) & 0xff); \ + (a)[1] = (u8) ((((u32) (val)) >> 8) & 0xff); \ + (a)[2] = (u8) (((u32) (val)) & 0xff); \ + } while (0) + +#define RTW_GET_BE32(a) ((((u32) (a)[0]) << 24) | (((u32) (a)[1]) << 16) | \ + (((u32) (a)[2]) << 8) | ((u32) (a)[3])) +#define RTW_PUT_BE32(a, val) \ + do { \ + (a)[0] = (u8) ((((u32) (val)) >> 24) & 0xff); \ + (a)[1] = (u8) ((((u32) (val)) >> 16) & 0xff); \ + (a)[2] = (u8) ((((u32) (val)) >> 8) & 0xff); \ + (a)[3] = (u8) (((u32) (val)) & 0xff); \ + } while (0) + +#define RTW_GET_LE32(a) ((((u32) (a)[3]) << 24) | (((u32) (a)[2]) << 16) | \ + (((u32) (a)[1]) << 8) | ((u32) (a)[0])) +#define RTW_PUT_LE32(a, val) \ + do { \ + (a)[3] = (u8) ((((u32) (val)) >> 24) & 0xff); \ + (a)[2] = (u8) ((((u32) (val)) >> 16) & 0xff); \ + (a)[1] = (u8) ((((u32) (val)) >> 8) & 0xff); \ + (a)[0] = (u8) (((u32) (val)) & 0xff); \ + } while (0) + +#define RTW_GET_BE64(a) ((((u64) (a)[0]) << 56) | (((u64) (a)[1]) << 48) | \ + (((u64) (a)[2]) << 40) | (((u64) (a)[3]) << 32) | \ + (((u64) (a)[4]) << 24) | (((u64) (a)[5]) << 16) | \ + (((u64) (a)[6]) << 8) | ((u64) (a)[7])) +#define RTW_PUT_BE64(a, val) \ + do { \ + (a)[0] = (u8) (((u64) (val)) >> 56); \ + (a)[1] = (u8) (((u64) (val)) >> 48); \ + (a)[2] = (u8) (((u64) (val)) >> 40); \ + (a)[3] = (u8) (((u64) (val)) >> 32); \ + (a)[4] = (u8) (((u64) (val)) >> 24); \ + (a)[5] = (u8) (((u64) (val)) >> 16); \ + (a)[6] = (u8) (((u64) (val)) >> 8); \ + (a)[7] = (u8) (((u64) (val)) & 0xff); \ + } while (0) + +#define RTW_GET_LE64(a) ((((u64) (a)[7]) << 56) | (((u64) (a)[6]) << 48) | \ + (((u64) (a)[5]) << 40) | (((u64) (a)[4]) << 32) | \ + (((u64) (a)[3]) << 24) | (((u64) (a)[2]) << 16) | \ + (((u64) (a)[1]) << 8) | ((u64) (a)[0])) +#endif + +extern PRTL_TIMER +RtlTimerCreate( + IN char *pTimerName, + IN u32 TimerPeriodMS, + IN RTL_TIMER_CALL_BACK CallbckFunc, + IN void *pContext, + IN u8 isPeriodical +); + +extern VOID +RtlTimerDelete( + IN PRTL_TIMER pTimerHdl +); + +extern u8 +RtlTimerStart( + IN PRTL_TIMER pTimerHdl, + IN u8 isFromISR +); + +extern u8 +RtlTimerStop( + IN PRTL_TIMER pTimerHdl, + IN u8 isFromISR +); + +extern u8 +RtlTimerReset( + IN PRTL_TIMER pTimerHdl, + IN u8 isFromISR +); + +extern u8 +RtlTimerChangePeriod( + IN PRTL_TIMER pTimerHdl, + IN u32 NewPeriodMS, + IN u8 isFromISR +); + +#endif //#ifndef __OSDEP_API_H_ + + diff --git a/component/os/os_dep/mailbox.c b/component/os/os_dep/mailbox.c new file mode 100644 index 0000000..5d09f48 --- /dev/null +++ b/component/os/os_dep/mailbox.c @@ -0,0 +1,574 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * + ******************************************************************************/ + + +#define _MAILBOX_C_ + +#include "mailbox.h" + +/****************************************************************************** + * Function Prototype Declaration + ******************************************************************************/ +static PRTL_MAILBOX RtlMBoxIdToHdl( + IN u8 MBoxId +); + +PRTL_MAILBOX RtlMailboxCreate( + IN u8 MboxID, + IN u32 MboxSize, + IN _Sema *pWakeSema +); + +VOID RtlMailboxDel( + IN PRTL_MAILBOX MboxHdl +); + +u8 RtlMailboxSendToBack( + IN u8 MboxID, + IN MSG_BLK *pMsg, + IN u32 MSToWait, + IN u8 IsFromISR +); + +u8 RtlMailboxSendToFront( + IN u8 MboxID, + IN MSG_BLK *pMsg, + IN u32 MSToWait, + IN u8 IsFromISR +); + +u8 RtlMailboxReceive( + IN u8 MboxID, + OUT MSG_BLK *pMsg, + IN u32 MSToWait, + IN u8 IsFromISR +); + +u8 RtlMailboxPeek( + IN u8 MboxID, + OUT MSG_BLK *pMsg, + IN u32 MSToWait, + IN u8 IsFromISR +); + +u32 RtlMailboxMsgWaiting( + IN u8 MboxID, + IN u8 IsFromISR +); + +/****************************************************************************** + * Global Variable Declaration + ******************************************************************************/ +static RTL_MBOX_ROOT MBox_Entry={0}; + +/****************************************************************************** + * External Function & Variable Declaration + ******************************************************************************/ + + +/****************************************************************************** + * Function: RtlMBoxIdToHdl + * Desc: Map a mailbox ID to the mailbox pointer. + * Para: + * MBoxId: The Mailbox ID + * Return: The pointer of the mailbox. If didn't found match mailbox, + * return NULL. + * + ******************************************************************************/ +static PRTL_MAILBOX RtlMBoxIdToHdl( + IN u8 MBoxId +) +{ + RTL_MAILBOX *pMbox=NULL; + RTL_MAILBOX *pTmpMbox; + _LIST *pHead; + _LIST *pList; + + // if the Mailbox root entry initialed ? if not, initial it + if (!MBox_Entry.isInitialed) { + RtlMutexInit(&MBox_Entry.Mutex); // Init the Mutex for the mailbox add/delete procedure protection + RtlInitListhead(&MBox_Entry.mbox_list); // Init the link list head to chain all created mailbox + MBox_Entry.isInitialed = 1; + MSG_MBOX_INFO("MBox Entry Initial...\n"); + } + + pHead = &MBox_Entry.mbox_list; + RtlDownMutex(&MBox_Entry.Mutex); + pList = RtlListGetNext(&MBox_Entry.mbox_list); + while (pList != pHead) { + pTmpMbox = CONTAINER_OF(pList, RTL_MAILBOX, mbox_list); + if (MBoxId == pTmpMbox->mbox_id) { + pMbox = pTmpMbox; + break; + } + pList = RtlListGetNext(pList); + } + RtlUpMutex(&MBox_Entry.Mutex); + + return pMbox; +} + +/****************************************************************************** + * Function: RtlMailboxCreate + * Desc: To create a mailbox with a given mailbox ID and size + * Para: + * MboxID: A number to identify this created mailbox. A message block can + * be send to a mailbox by a given MboxID. The MboxID must be unique + * in the whole system. If this MboxID is conflict with a created + * mailbox, the mailbox creation will fail and return NULL. + * MboxSize: The size of this mailbox to be created. It means maximum number + * of message blocks can be stored in this mailbox. + * pWakeSema: The semaphore to wake up the receiving task to receive the new + * message. If the receiving task doesn't need a semaphore to wakeup + * it, then just let this pointer is NULL. + * Return: The created mailbox pointer. If it failed, return NULL. + ******************************************************************************/ +PRTL_MAILBOX RtlMailboxCreate( + IN u8 MboxID, + IN u32 MboxSize, + IN _Sema *pWakeSema +) +{ + PRTL_MAILBOX pMBox=NULL; + + // if the Mailbox root entry initialed ? if not, initial it + if (!MBox_Entry.isInitialed) { + RtlMutexInit(&MBox_Entry.Mutex); // Init the Mutex for the mailbox add/delete procedure protection + RtlInitListhead(&MBox_Entry.mbox_list); // Init the link list head to chain all created mailbox + MBox_Entry.isInitialed = 1; + MSG_MBOX_INFO("MBox Entry Initial...\n"); + } + + // check if this mailbox ID is ocupied ? + pMBox = RtlMBoxIdToHdl(MboxID); + if (NULL != pMBox) { + MSG_MBOX_ERR("RtlMailboxCreate: The Mailbox ID %d is used by someone!!\n", MboxID); + return NULL; + } + + pMBox = (RTL_MAILBOX *)RtlZmalloc(sizeof(RTL_MAILBOX)); + if (NULL==pMBox) { + MSG_MBOX_ERR("RtlMailboxCreate: MAlloc Failed\n"); + return NULL; + } + + RtlInitListhead(&pMBox->mbox_list); // Init the link list to be chained into the created mailbox list + pMBox->mbox_id = MboxID; + pMBox->pWakeSema = pWakeSema; +#ifdef PLATFORM_FREERTOS + pMBox->mbox_hdl = xQueueCreate(MboxSize, sizeof(MSG_BLK)); + if (NULL == pMBox->mbox_hdl) { + MSG_MBOX_ERR("RtlMailboxCreate: xQueueCreate Failed\n"); + RtlMfree((void *)pMBox, sizeof(RTL_MAILBOX)); + return NULL; + } +#endif +#ifdef PLATFORM_ECOS +// TODO: Create mailbox +#endif + + // Add this mailbox to the link list of created mailbox + RtlDownMutex(&MBox_Entry.Mutex); + RtlListInsertTail(&pMBox->mbox_list, &MBox_Entry.mbox_list); + RtlUpMutex(&MBox_Entry.Mutex); + + MSG_MBOX_INFO("A Mailbox Created: Size=%d\n", MboxSize); + + return pMBox; +} + +/****************************************************************************** + * Function: RtlMailboxDel + * Desc: To delete a mailbox by a given mailbox handle. + * Para: + * MboxHdl: The handle of the mailbox to be deleted. + * Return: None. + ******************************************************************************/ +VOID RtlMailboxDel( + IN PRTL_MAILBOX MboxHdl +) +{ + if (NULL == MboxHdl) { + MSG_MBOX_ERR("RtlMailboxDel: Try to delete a NULL mailbox\n"); + return; + } + + // Remove this mailbox from the link list of created mailbox + RtlDownMutex(&MBox_Entry.Mutex); + RtlListDelete(&MboxHdl->mbox_list); + RtlUpMutex(&MBox_Entry.Mutex); + + // delete the Queue/Mailbox +#ifdef PLATFORM_FREERTOS + vQueueDelete((xQueueHandle)(MboxHdl->mbox_hdl)); +#endif +#ifdef PLATFORM_ECOS + // TODO: Delete mailbox +#endif + + RtlMfree((void *)MboxHdl, sizeof(RTL_MAILBOX)); +} + +/****************************************************************************** + * Function: RtlMailboxSendToBack + * Desc: To put a message block to the tail of a given mailbox. + * Para: + * MboxID: The identifier of the target mailbox. + * pMsg: The pointer of the message block to be put into the mailbox. + * MSToWait: If the mailbox is full, this value gives a time to wait to put + * this message. The time unit is millisecond. + * The special values are: + * 0: no waiting; + * 0xffffffff: wait without timeout. + * If the waiting is timeout, the message sending is failed and + * return _FAIL. + * IsFromISR: Is this function is called from an ISR ? + * Return: _SUCCESS or _FAIL. + ******************************************************************************/ +u8 RtlMailboxSendToBack( + IN u8 MboxID, + IN MSG_BLK *pMsg, + IN u32 MSToWait, + IN u8 IsFromISR +) +{ + RTL_MAILBOX *pMbox=NULL; + u32 wait_ticks; +#ifdef PLATFORM_FREERTOS + portBASE_TYPE ret; +#endif + + pMbox = RtlMBoxIdToHdl(MboxID); + + if (NULL == pMbox) { + MSG_MBOX_ERR("RtlMailboxSendToBack: Didn't find matched MBoxID=%d\n", MboxID); + return _FAIL; + } + +#ifdef PLATFORM_FREERTOS + if (MBOX_WAIT_NO_TIMEOUT == MSToWait) { + wait_ticks = portMAX_DELAY; + } + else if (MBOX_WAIT_NONE == MSToWait) { + wait_ticks = 0; + } + else { + wait_ticks = ((MSToWait/portTICK_RATE_MS)>0)?(MSToWait/portTICK_RATE_MS):(1); + } + + if (IsFromISR) { + ret = xQueueSendToBackFromISR(pMbox->mbox_hdl, (void *)pMsg, NULL);//(portTickType) wait_ticks); + } + else { + ret = xQueueSendToBack(pMbox->mbox_hdl, (void *)pMsg, (portTickType) wait_ticks); + } + + if(ret != pdPASS ) { + // send message to the queue failed + MSG_MBOX_ERR("RtlMailboxSendToBack: Put Msg to Queue Failed, MBoxID=%d\n", MboxID); + ret = _FAIL; + } + else { + // try to give a semaphore to wake up the receiving task + if (pMbox->pWakeSema) { + RtlUpSema(pMbox->pWakeSema); + } + ret = _SUCCESS; + } + + return ret; +#endif + +#ifdef PLATFORM_ECOS + // TODO: Put the message to a mailbox +#endif + +} + + +/****************************************************************************** + * Function: RtlMailboxSendToFront + * Desc: To put a message block to the head of a mailbox. + * Para: + * MboxID: The identifier of the target mailbox. + * pMsg: The pointer of the message block to be put into the mailbox. + * MSToWait: If the mailbox is full, this value gives a time to wait to put + * this message. The time unit is millisecond. + * The special values are: + * 0: no waiting; + * 0xffffffff: wait without timeout. + * If the waiting is timeout, the message sending is failed and + * return _FAIL. + * IsFromISR: Is this function is called from an ISR ? + * Return: _SUCCESS or _FAIL. + ******************************************************************************/ +u8 RtlMailboxSendToFront( + IN u8 MboxID, + IN MSG_BLK *pMsg, + IN u32 MSToWait, + IN u8 IsFromISR +) +{ + RTL_MAILBOX *pMbox=NULL; + u32 wait_ticks; +#ifdef PLATFORM_FREERTOS + portBASE_TYPE ret; +#endif + + pMbox = RtlMBoxIdToHdl(MboxID); + + if (NULL == pMbox) { + MSG_MBOX_ERR("RtlMailboxSendToBack: Didn't find matched MBoxID=%d\n", MboxID); + return _FAIL; + } + +#ifdef PLATFORM_FREERTOS + if (MBOX_WAIT_NO_TIMEOUT == MSToWait) { + wait_ticks = portMAX_DELAY; + } + else if (MBOX_WAIT_NONE == MSToWait) { + wait_ticks = 0; + } + else { + wait_ticks = ((MSToWait/portTICK_RATE_MS)>0)?(MSToWait/portTICK_RATE_MS):(1); + } + + if (IsFromISR) { + ret = xQueueSendToFrontFromISR(pMbox->mbox_hdl, (void *)pMsg, NULL);//(portTickType) wait_ticks); + } + else { + ret = xQueueSendToFront(pMbox->mbox_hdl, (void *)pMsg, (portTickType) wait_ticks); + } + + if(ret != pdPASS ) { + // send message to the queue failed + MSG_MBOX_ERR("RtlMailboxSendToBack: Put Msg to Queue Failed, MBoxID=%d\n", MboxID); + ret = _FAIL; + } + else { + // try to give a semaphore to wake up the receiving task + if (pMbox->pWakeSema) { + RtlUpSema(pMbox->pWakeSema); + } + ret = _SUCCESS; + } + + return ret; +#endif + +#ifdef PLATFORM_ECOS + // TODO: eCos has no API to put message to the head of a mailbox +#endif + +} + +/****************************************************************************** + * Function: RtlMailboxSendToFront + * Desc: To get a message block from a given mailbox. + * Para: + * MboxID: The identifier of the target mailbox. + * pMsg: The message block to store the gotten message. + * MSToWait: If the mailbox is full, this value gives a time to wait to put + * this message. The time unit is millisecond. + * The special values are: + * 0: no waiting; + * 0xffffffff: wait without timeout. + * If the waiting is timeout, the message sending is failed and + * return _FAIL. + * IsFromISR: Is this function is called from an ISR ? + * Return: _SUCCESS or _FAIL. + ******************************************************************************/ +u8 RtlMailboxReceive( + IN u8 MboxID, + OUT MSG_BLK *pMsg, + IN u32 MSToWait, + IN u8 IsFromISR +) +{ + RTL_MAILBOX *pMbox=NULL; + u32 wait_ticks; +#ifdef PLATFORM_FREERTOS + portBASE_TYPE ret; +#endif + + pMbox = RtlMBoxIdToHdl(MboxID); + + if (NULL == pMbox) { + MSG_MBOX_ERR("RtlMailboxReceive: Didn't find the MBox with ID=%d\n", MboxID); + return _FAIL; + } + +#ifdef PLATFORM_FREERTOS + if (MBOX_WAIT_NONE == MSToWait) { + wait_ticks = 0; + } + else if (MBOX_WAIT_NO_TIMEOUT == MSToWait) { + wait_ticks = portMAX_DELAY; + } + else { + wait_ticks = ((MSToWait/portTICK_RATE_MS)>0)?(MSToWait/portTICK_RATE_MS):(1); + } + + if (IsFromISR) { + ret = xQueueReceiveFromISR(pMbox->mbox_hdl, (void *)pMsg, NULL);//( portTickType ) wait_ticks); + } + else { + ret = xQueueReceive(pMbox->mbox_hdl, (void *)pMsg, ( portTickType ) wait_ticks); + + } + + if(ret != pdTRUE ) { + // receive message failed + if (0 != MSToWait) { + MSG_MBOX_ERR("RtlMailboxReceive: Receive Msg Failed, MBoxID=%d\n", MboxID); + } + ret = _FAIL; + } + else { + ret = _SUCCESS; + } + + return ret; +#endif + +#ifdef PLATFORM_ECOS + // TODO: Get a message from the mailbox +#endif + +} + +/****************************************************************************** + * Function: RtlMailboxPeek + * Desc: To copy the head message from a given mailbox without move this + * message block out from the mailbox. + * Para: + * MboxID: The identifier of the target mailbox. + * pMsg: The message block to store the gotten message. + * MSToWait: If the mailbox is full, this value gives a time to wait to put + * this message. The time unit is millisecond. + * The special values are: + * 0: no waiting; + * 0xffffffff: wait without timeout. + * If the waiting is timeout, the message sending is failed and + * return _FAIL. + * IsFromISR: Is this function is called from an ISR ? + * Return: _SUCCESS or _FAIL. + ******************************************************************************/ +u8 RtlMailboxPeek( + IN u8 MboxID, + OUT MSG_BLK *pMsg, + IN u32 MSToWait, + IN u8 IsFromISR +) +{ + RTL_MAILBOX *pMbox=NULL; + u32 wait_ticks; +#ifdef PLATFORM_FREERTOS + portBASE_TYPE ret; +#endif + + pMbox = RtlMBoxIdToHdl(MboxID); + + if (NULL == pMbox) { + MSG_MBOX_ERR("RtlMailboxPeek: Didn't find the MBox with ID=%d\n", MboxID); + return _FAIL; + } + +#ifdef PLATFORM_FREERTOS + if (MBOX_WAIT_NONE == MSToWait) { + wait_ticks = 0; + } + else if (MBOX_WAIT_NO_TIMEOUT == MSToWait) { + wait_ticks = portMAX_DELAY; + } + else { + wait_ticks = ((MSToWait/portTICK_RATE_MS)>0)?(MSToWait/portTICK_RATE_MS):(1); + } + + if (IsFromISR) { +// ret = xQueuePeekFromISR(pMbox->mbox_hdl, (void *)pMsg, ( portTickType ) wait_ticks); + // TODO: check why we have no "xQueuePeekFromISR" + MSG_MBOX_ERR("RtlMailboxPeek: Current version has no 'xQueuePeekFromISR'\n"); + ret = pdFALSE; + } + else { + ret = xQueuePeek(pMbox->mbox_hdl, (void *)pMsg, ( portTickType ) wait_ticks); + + } + + if(ret != pdTRUE ) { + // receive message failed + MSG_MBOX_ERR("RtlMailboxReceive: Receive Msg Failed, MBoxID=%d\n", MboxID); + ret = _FAIL; + } + else { + ret = _SUCCESS; + } + + return ret; +#endif + +#ifdef PLATFORM_ECOS + // TODO: Get a message from the mailbox +#endif + +} + + +/****************************************************************************** + * Function: RtlMailboxMsgWaiting + * Desc: To get the number of message blocks are storing in a given mailbox. + * Para: + * MboxID: The identifier of the target mailbox. + * IsFromISR: Is this function is called from an ISR ? + * Return: The number of message blocks are storing in this mailbox. + ******************************************************************************/ +u32 RtlMailboxMsgWaiting( + IN u8 MboxID, + IN u8 IsFromISR +) +{ + RTL_MAILBOX *pMbox=NULL; + u32 msg_num=0; + + pMbox = RtlMBoxIdToHdl(MboxID); + + if (NULL == pMbox) { + MSG_MBOX_ERR("RtlMailboxMsgWaiting: Didn't find the MBox with ID=%d\n", MboxID); + return 0; + } + +#ifdef PLATFORM_FREERTOS + if (IsFromISR) { + msg_num = uxQueueMessagesWaitingFromISR(pMbox->mbox_hdl); + } + else { + msg_num = uxQueueMessagesWaiting(pMbox->mbox_hdl); + } +#endif + +#ifdef PLATFORM_ECOS + // TODO: call eCos API to implement this function +#endif + + return msg_num; + +} + diff --git a/component/os/os_dep/osdep_api.c b/component/os/os_dep/osdep_api.c new file mode 100644 index 0000000..334ee51 --- /dev/null +++ b/component/os/os_dep/osdep_api.c @@ -0,0 +1,836 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * + ******************************************************************************/ + + +#define _OSDEP_API_C_ + +#include + + + + + + +u8* +RtlMalloc( + IN u32 sz +) +{ + u8 *pbuf=NULL; +#ifndef PLATFORM_FREERTOS + u32 v32=0; +#endif + +#ifdef PLATFORM_FREERTOS + SaveAndCli( ); +#else + SaveAndCli(v32); +#endif + + pbuf = RtlKmalloc(sz, GFP_ATOMIC); + +#ifdef PLATFORM_FREERTOS + RestoreFlags( ); +#else + RestoreFlags(v32); +#endif + + return pbuf; + +} + + +u8* +RtlZmalloc( + IN u32 sz +) +{ +#ifdef PLATFORM_FREERTOS + u8 *pbuf; + + pbuf= RtlMalloc(sz); + + if (pbuf != NULL) { + _memset(pbuf, 0, sz); + } + + return pbuf; +#else + u8 *pbuf; + + pbuf= RtlMalloc(sz); + + if (pbuf != NULL) { + _memset(pbuf, 0, sz); + } + + return pbuf; +#endif +} + +VOID +RtlMfree( + IN u8 *pbuf, + IN u32 sz +) +{ + RtlKfree(pbuf); +} + + +VOID* +RtlMalloc2d( + IN u32 h, + IN u32 w, + IN u32 size +) +{ + u32 j; + + VOID **a = (VOID **) RtlZmalloc( h*sizeof(VOID *) + h*w*size ); + if(a == NULL) + { + DBG_ERROR_LOG("%s: alloc memory fail!\n", __FUNCTION__); + return NULL; + } + + for( j=0; jQueue)); + + RtlSpinlockInit(&(pqueue->Lock)); + +} + +u32 +RtlQueueEmpty( + IN _QUEUE *pqueue +) +{ + return (RtlIsListEmpty(&(pqueue->Queue))); +} + + +u32 +RtlendOfQueueSearch( + IN _LIST *head, + IN _LIST *plist) +{ + if (head == plist) + return _TRUE; + else + return _FALSE; +} +#endif + +u32 +RtlGetCurrentTime(VOID) +{ + return JIFFIES; +} + + + +VOID +RtlSleepSchedulable( + IN u32 ms +) +{ + +#ifdef PLATFORM_LINUX + + u32 delta; + + delta = (ms * HZ)/1000;//(ms) + if (delta == 0) { + delta = 1;// 1 ms + } + set_current_state(TASK_INTERRUPTIBLE); + if (schedule_timeout(delta) != 0) { + return ; + } + return; + +#endif +#ifdef PLATFORM_FREEBSD + DELAY(ms*1000); + return ; +#endif + +#ifdef PLATFORM_WINDOWS + + NdisMSleep(ms*1000); //(us)*1000=(ms) + +#endif + +} + + + +VOID +RtlMsleepOS( + IN u32 ms +) +{ +#ifdef PLATFORM_FREERTOS + u32 Dealycount = ms/portTICK_RATE_MS; + if (Dealycount > 0) { + vTaskDelay(Dealycount); + } + else { + vTaskDelay(1); + } + +#endif +} + + +VOID +RtlUsleepOS( + IN u32 us +) +{ +#ifdef PLATFORM_FREERTOS + u32 Dealycount = us/portTICK_RATE_MS*1000; + if (Dealycount > 0) { + vTaskDelay(Dealycount); + } + else { + vTaskDelay(1); + } +#endif +} + + +VOID +RtlMdelayOS( + IN u32 ms +) +{ + Mdelay((unsigned long)ms); +} + +VOID +RtlUdelayOS( + IN u32 us +) +{ + Udelay((unsigned long)us); +} + + +VOID +RtlYieldOS(VOID) +{ +} + + +#if defined(__ICCARM__) +u64 +RtlModular64( + IN u64 n, + IN u64 base +) +{ + unsigned int __base = (base); + unsigned int __rem; + //(void)(((typeof((n)) *)0) == ((__uint64_t *)0)); + if (((n) >> 32) == 0) { + __rem = (unsigned int)(n) % __base; + (n) = (unsigned int)(n) / __base; + } else + __rem = __Div64_32(&(n), __base); + return __rem; + +} +#else +u64 +RtlModular64( + IN u64 x, + IN u64 y +) +{ + return DO_DIV(x, y); +} +#endif + +/****************************************************************************** + * Function: RtlTimerCallbckEntry + * Desc: This function is a timer callback wrapper. All OS timer callback + * will call this function and then call the real callback function inside + * this function. + * + * Para: + * pxTimer: The FreeRTOS timer handle which is expired and call this callback. + * + * Return: None + * + ******************************************************************************/ +#ifdef PLATFORM_FREERTOS +void +RtlTimerCallbckEntry ( + IN xTimerHandle pxTimer +) +{ + PRTL_TIMER pTimer; + + if (NULL == pxTimer) { + MSG_TIMER_ERR("RtlTimerCallbckEntry: NULL Timer Handle Err!\n"); + return; + } + + pTimer = (PRTL_TIMER) pvTimerGetTimerID( pxTimer ); + pTimer->CallBackFunc(pTimer->Context); +} +#endif // end of "#ifdef PLATFORM_FREERTOS" + +/****************************************************************************** + * Function: RtlTimerCreate + * Desc: To create a software timer. + * + * Para: + * pTimerName: A string for the timer name. + * TimerPeriodMS: The timer period, the unit is milli-second. + * CallbckFunc: The callback function of this timer. + * pContext: A pointer will be used as the parameter to call the timer + * callback function. + * isPeriodical: Is this timer periodical ? (Auto reload after expired) + * Return: The created timer handle, a pointer. It can be used to delete the + * timer. If timer createion failed, return NULL. + * + ******************************************************************************/ +PRTL_TIMER +RtlTimerCreate( + IN char *pTimerName, + IN u32 TimerPeriodMS, + IN RTL_TIMER_CALL_BACK CallbckFunc, + IN void *pContext, + IN u8 isPeriodical +) +{ + PRTL_TIMER pTimer; + u32 timer_ticks; + int i; + + pTimer = (PRTL_TIMER)RtlZmalloc(sizeof(RTL_TIMER)); + if (NULL == pTimer) { + MSG_TIMER_ERR("RtlTimerCreate: Alloc Mem Err!\n"); + return NULL; + } + + if (portTICK_RATE_MS >= TimerPeriodMS) { + timer_ticks = 1; // at least 1 system tick + } + else { + timer_ticks = TimerPeriodMS/portTICK_RATE_MS; + } + +#ifdef PLATFORM_FREERTOS + pTimer->TimerHandle = xTimerCreate (pTimer->TimerName, timer_ticks, + (portBASE_TYPE)isPeriodical, (void *) pTimer, RtlTimerCallbckEntry); +#endif +#ifdef PLATFORM_ECOS +// TODO: create a timer +#endif + +#ifdef PLATFORM_FREERTOS // if any RTOS is used + if (pTimer->TimerHandle) { + pTimer->msPeriod = TimerPeriodMS; + pTimer->CallBackFunc = CallbckFunc; + pTimer->Context = pContext; + pTimer->isPeriodical = isPeriodical; + // copy the timer name + if (NULL != pTimerName) { + for(i = 0; i < sizeof(pTimer->TimerName); i++) + { + pTimer->TimerName[i] = pTimerName[i]; + if(pTimerName[i] == '\0') + { + break; + } + } + } + else { + _strcpy(pTimer->TimerName, "None"); + } + } + else +#endif + { + RtlMfree((u8 *)pTimer, sizeof(RTL_TIMER)); + pTimer = NULL; + MSG_TIMER_ERR("RtlTimerCreate: OS Create Timer Failed!\n"); + } + + MSG_TIMER_INFO("RtlTimerCreate: SW Timer Created: Name=%s Period=%d isPeriodical=%d\n", \ + pTimer->TimerName, pTimer->msPeriod, pTimer->isPeriodical); + + return (pTimer); +} + +/****************************************************************************** + * Function: RtlTimerDelete + * Desc: To delete a created software timer. + * + * Para: + * pTimerHdl: The timer to be deleted + * + * Return: None + * + ******************************************************************************/ +VOID +RtlTimerDelete( + IN PRTL_TIMER pTimerHdl +) +{ +#ifdef PLATFORM_FREERTOS + portBASE_TYPE ret; +#endif + + MSG_TIMER_INFO("RtlTimerDelete: Name=%s\n", pTimerHdl->TimerName); + + if (NULL == pTimerHdl) { + MSG_TIMER_ERR("RtlTimerDelete: NULL Timer Handle!\n"); + } + +#ifdef PLATFORM_FREERTOS + /* try to delete the soft timer and wait max RTL_TIMER_API_MAX_BLOCK_TICKS + to send the delete command to the timer command queue */ + ret = xTimerDelete(pTimerHdl->TimerHandle, RTL_TIMER_API_MAX_BLOCK_TICKS); + if (pdPASS != ret) { + MSG_TIMER_ERR("RtlTimerDelete: Delete OS Timer Failed!\n"); + } +#endif + +#ifdef PLATFORM_ECOS + // TODO: call OS delete timer +#endif + RtlMfree((u8 *)pTimerHdl, sizeof(RTL_TIMER)); + +} + +/****************************************************************************** + * Function: RtlTimerStart + * Desc: To start a created timer.. + * + * Para: + * pTimerHdl: The timer to be started. + * isFromISR: The flag to indicate that is this function is called from an ISR. + * + * Return: _SUCCESS or _FAIL + * + ******************************************************************************/ +u8 +RtlTimerStart( + IN PRTL_TIMER pTimerHdl, + IN u8 isFromISR +) +{ +#ifdef PLATFORM_FREERTOS + u8 ret=_FAIL; + portBASE_TYPE HigherPriorityTaskWoken=pdFALSE; + + if (isFromISR) { + if (pdPASS == xTimerStartFromISR(pTimerHdl->TimerHandle,&HigherPriorityTaskWoken)) + { + // start OS timer successful + if (pdFALSE != HigherPriorityTaskWoken) { + taskYIELD(); + } + ret = _SUCCESS; + } + else { + MSG_TIMER_ERR("RtlTimerStart: Start Timer(%s) from ISR failed\n", pTimerHdl->TimerName); + } + } + else { + if (pdPASS == xTimerStart(pTimerHdl->TimerHandle, RTL_TIMER_API_MAX_BLOCK_TICKS)) { + ret = _SUCCESS; + } + else { + MSG_TIMER_ERR("RtlTimerStart: Start Timer(%s) failed\n", pTimerHdl->TimerName); + } + } + + MSG_TIMER_INFO("RtlTimerStart: SW Timer %s Started\n", pTimerHdl->TimerName); + + return ret; +#endif +} + +/****************************************************************************** + * Function: RtlTimerStop + * Desc: To stop a running timer.. + * + * Para: + * pTimerHdl: The timer to be stoped. + * isFromISR: The flag to indicate that is this function is called from an ISR. + * + * Return: _SUCCESS or _FAIL + * + ******************************************************************************/ +u8 +RtlTimerStop( + IN PRTL_TIMER pTimerHdl, + IN u8 isFromISR +) +{ +#ifdef PLATFORM_FREERTOS + u8 ret=_FAIL; + portBASE_TYPE HigherPriorityTaskWoken=pdFALSE; + + if (isFromISR) { + if (pdPASS == xTimerStopFromISR(pTimerHdl->TimerHandle,&HigherPriorityTaskWoken)) + { + // start OS timer successful + if (pdFALSE != HigherPriorityTaskWoken) { + taskYIELD(); + } + ret = _SUCCESS; + } + } + else { + if (pdPASS == xTimerStop(pTimerHdl->TimerHandle, RTL_TIMER_API_MAX_BLOCK_TICKS)) { + ret = _SUCCESS; + } + } + + if (_FAIL == ret) { + MSG_TIMER_ERR("RtlTimerStop: Stop Timer(%s) Failed, IsFromISR=%d\n", pTimerHdl->TimerName, isFromISR); + } + + MSG_TIMER_INFO("RtlTimerStop: SW Timer %s Stoped\n", pTimerHdl->TimerName); + + return ret; +#endif +} + +/****************************************************************************** + * Function: RtlTimerReset + * Desc: To reset a timer. A reset will get a re-start and reset + * the timer ticks counting. A running timer expired time is relative + * to the time when Reset function be called. Please ensure the timer + * is in active state (Started). A stopped timer also will be started + * when this function is called. + * + * Para: + * pTimerHdl: The timer to be reset. + * isFromISR: The flag to indicate that is this function is called from an ISR. + * + * Return: _SUCCESS or _FAIL + * + ******************************************************************************/ +u8 +RtlTimerReset( + IN PRTL_TIMER pTimerHdl, + IN u8 isFromISR +) +{ +#ifdef PLATFORM_FREERTOS + u8 ret=_FAIL; + portBASE_TYPE HigherPriorityTaskWoken=pdFALSE; + + if (isFromISR) { + if (pdPASS == xTimerResetFromISR(pTimerHdl->TimerHandle,&HigherPriorityTaskWoken)) + { + // start OS timer successful + if (pdFALSE != HigherPriorityTaskWoken) { + taskYIELD(); + } + ret = _SUCCESS; + } + } + else { + if (pdPASS == xTimerReset(pTimerHdl->TimerHandle, RTL_TIMER_API_MAX_BLOCK_TICKS)) { + ret = _SUCCESS; + } + } + + if (_FAIL == ret) { + MSG_TIMER_ERR("RtlTimerReset: Reset Timer(%s) Failed, IsFromISR=%d\n", pTimerHdl->TimerName, isFromISR); + } + + MSG_TIMER_INFO("RtlTimerReset: SW Timer %s Reset\n", pTimerHdl->TimerName); + + return ret; +#endif +} + +/****************************************************************************** + * Function: RtlTimerChangePeriod + * Desc: To change the period of a timer that was created previously. + * + * Para: + * pTimerHdl: The timer handle to be changed the priod. + * NewPeriodMS: The new timer period, in milli-second. + * isFromISR: The flag to indicate that is this function is called from an ISR. + * + * Return: _SUCCESS or _FAIL + * + ******************************************************************************/ +u8 +RtlTimerChangePeriod( + IN PRTL_TIMER pTimerHdl, + IN u32 NewPeriodMS, + IN u8 isFromISR +) +{ +#ifdef PLATFORM_FREERTOS + u32 timer_ticks; + u8 ret=_FAIL; + portBASE_TYPE HigherPriorityTaskWoken=pdFALSE; + + if (portTICK_RATE_MS >= NewPeriodMS) { + timer_ticks = 1; // at least 1 system tick + } + else { + timer_ticks = NewPeriodMS/portTICK_RATE_MS; + } + + if (isFromISR) { + if (pdPASS == xTimerChangePeriodFromISR(pTimerHdl->TimerHandle, timer_ticks, &HigherPriorityTaskWoken)) + { + // start OS timer successful + if (pdFALSE != HigherPriorityTaskWoken) { + taskYIELD(); + } + ret = _SUCCESS; + } + } + else { + if (pdPASS == xTimerChangePeriod(pTimerHdl->TimerHandle, timer_ticks, RTL_TIMER_API_MAX_BLOCK_TICKS)) { + ret = _SUCCESS; + } + } + + if (_FAIL == ret) { + MSG_TIMER_ERR("RtlTimerChangePeriod: Change Timer(%s) Period Failed, IsFromISR=%d\n", pTimerHdl->TimerName, isFromISR); + } + else { + pTimerHdl->msPeriod = NewPeriodMS; + MSG_TIMER_INFO("RtlTimerChangePeriod: SW Timer %s change period to %d\n", pTimerHdl->TimerName, pTimerHdl->msPeriod); + } + + + return ret; +#endif +} + diff --git a/component/soc/realtek/8195a/cmsis/core_cm3.h b/component/soc/realtek/8195a/cmsis/core_cm3.h new file mode 100644 index 0000000..64db5c7 --- /dev/null +++ b/component/soc/realtek/8195a/cmsis/core_cm3.h @@ -0,0 +1,1661 @@ +/**************************************************************************//** + * @file core_cm3.h + * @brief CMSIS Cortex-M3 Core Peripheral Access Layer Header File + * @version V3.20 + * @date 25. February 2013 + * + * @note + * + ******************************************************************************/ +/* Copyright (c) 2009 - 2013 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - 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. + - Neither the name of ARM 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 HOLDERS 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 COPYRIGHT HOLDERS AND 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. + ---------------------------------------------------------------------------*/ + + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef __CORE_CM3_H_GENERIC +#define __CORE_CM3_H_GENERIC + +/** \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** \ingroup Cortex_M3 + @{ + */ + +/* CMSIS CM3 definitions */ +#define __CM3_CMSIS_VERSION_MAIN (0x03) /*!< [31:16] CMSIS HAL main version */ +#define __CM3_CMSIS_VERSION_SUB (0x20) /*!< [15:0] CMSIS HAL sub version */ +#define __CM3_CMSIS_VERSION ((__CM3_CMSIS_VERSION_MAIN << 16) | \ + __CM3_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + +#define __CORTEX_M (0x03) /*!< Cortex-M Core */ + + + +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ + #define __STATIC_INLINE static inline + +#elif defined ( __TMS470__ ) + #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + #define __STATIC_INLINE static inline + +#endif + +/** __FPU_USED indicates whether an FPU is used or not. This core does not support an FPU at all +*/ +#define __FPU_USED 0 + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TMS470__ ) + #if defined __TI__VFP_SUPPORT____ + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif +#endif + +#include /* standard types definitions */ +//#include /* rlx basic types definitions */ +#include /* Core Instruction Access */ +#include /* Core Function Access */ +//#include "hal_irqn.h" + +#endif /* __CORE_CM3_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM3_H_DEPENDANT +#define __CORE_CM3_H_DEPENDANT + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM3_REV + #define __CM3_REV 0x0200 + #warning "__CM3_REV not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0 + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 4 + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0 + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/*@} end of group Cortex_M3 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + ******************************************************************************/ +/** \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { +#if (__CORTEX_M != 0x04) + uint32_t _reserved0:27; /*!< bit: 0..26 Reserved */ +#else + uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ +#endif + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + + +/** \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + + +/** \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ +#if (__CORTEX_M != 0x04) + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ +#else + uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ +#endif + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + + +/** \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */ + uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/*@} end of group CMSIS_CORE */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IO uint32_t ISER[8]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[24]; + __IO uint32_t ICER[8]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[24]; + __IO uint32_t ISPR[8]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[24]; + __IO uint32_t ICPR[8]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[24]; + __IO uint32_t IABR[8]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[56]; + __IO uint8_t IP[240]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED5[644]; + __O uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0 /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL << NVIC_STIR_INTID_Pos) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __I uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IO uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IO uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IO uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IO uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IO uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IO uint8_t SHP[12]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IO uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IO uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IO uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IO uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IO uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IO uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IO uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __I uint32_t PFR[2]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __I uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __I uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __I uint32_t MMFR[4]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __I uint32_t ISAR[5]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + uint32_t RESERVED0[5]; + __IO uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24 /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20 /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16 /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4 /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0 /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL << SCB_CPUID_REVISION_Pos) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31 /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28 /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27 /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26 /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25 /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23 /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22 /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12 /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11 /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0 /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL << SCB_ICSR_VECTACTIVE_Pos) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#if (__CM3_REV < 0x0201) /* core r2p1 */ +#define SCB_VTOR_TBLBASE_Pos 29 /*!< SCB VTOR: TBLBASE Position */ +#define SCB_VTOR_TBLBASE_Msk (1UL << SCB_VTOR_TBLBASE_Pos) /*!< SCB VTOR: TBLBASE Mask */ + +#define SCB_VTOR_TBLOFF_Pos 7 /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x3FFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ +#else +#define SCB_VTOR_TBLOFF_Pos 7 /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ +#endif + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16 /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16 /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15 /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8 /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2 /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1 /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +#define SCB_AIRCR_VECTRESET_Pos 0 /*!< SCB AIRCR: VECTRESET Position */ +#define SCB_AIRCR_VECTRESET_Msk (1UL << SCB_AIRCR_VECTRESET_Pos) /*!< SCB AIRCR: VECTRESET Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4 /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2 /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1 /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9 /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8 /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4 /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3 /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1 /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +#define SCB_CCR_NONBASETHRDENA_Pos 0 /*!< SCB CCR: NONBASETHRDENA Position */ +#define SCB_CCR_NONBASETHRDENA_Msk (1UL << SCB_CCR_NONBASETHRDENA_Pos) /*!< SCB CCR: NONBASETHRDENA Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_USGFAULTENA_Pos 18 /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17 /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16 /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15 /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14 /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13 /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12 /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11 /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10 /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8 /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7 /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3 /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1 /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0 /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL << SCB_SHCSR_MEMFAULTACT_Pos) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Registers Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16 /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8 /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0 /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL << SCB_CFSR_MEMFAULTSR_Pos) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* SCB Hard Fault Status Registers Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31 /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30 /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1 /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4 /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3 /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2 /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1 /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0 /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL << SCB_DFSR_HALTED_Pos) /*!< SCB DFSR: HALTED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1]; + __I uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ +#if ((defined __CM3_REV) && (__CM3_REV >= 0x200)) + __IO uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ +#else + uint32_t RESERVED1[1]; +#endif +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0 /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL << SCnSCB_ICTR_INTLINESNUM_Pos) /*!< ICTR: INTLINESNUM Mask */ + +/* Auxiliary Control Register Definitions */ + +#define SCnSCB_ACTLR_DISFOLD_Pos 2 /*!< ACTLR: DISFOLD Position */ +#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ + +#define SCnSCB_ACTLR_DISDEFWBUF_Pos 1 /*!< ACTLR: DISDEFWBUF Position */ +#define SCnSCB_ACTLR_DISDEFWBUF_Msk (1UL << SCnSCB_ACTLR_DISDEFWBUF_Pos) /*!< ACTLR: DISDEFWBUF Mask */ + +#define SCnSCB_ACTLR_DISMCYCINT_Pos 0 /*!< ACTLR: DISMCYCINT Position */ +#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL << SCnSCB_ACTLR_DISMCYCINT_Pos) /*!< ACTLR: DISMCYCINT Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IO uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IO uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __I uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16 /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2 /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1 /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0 /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL << SysTick_CTRL_ENABLE_Pos) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0 /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL << SysTick_LOAD_RELOAD_Pos) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0 /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31 /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30 /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0 /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __O union + { + __O uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __O uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __O uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864]; + __IO uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15]; + __IO uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15]; + __IO uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[29]; + __O uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ + __I uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ + __IO uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ + uint32_t RESERVED4[43]; + __O uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __I uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[6]; + __I uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __I uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __I uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __I uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __I uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __I uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __I uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __I uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __I uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __I uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __I uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __I uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0 /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFUL << ITM_TPR_PRIVMASK_Pos) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23 /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TraceBusID_Pos 16 /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10 /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPrescale_Pos 8 /*!< ITM TCR: TSPrescale Position */ +#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ + +#define ITM_TCR_SWOENA_Pos 4 /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3 /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2 /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1 /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0 /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL << ITM_TCR_ITMENA_Pos) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Integration Write Register Definitions */ +#define ITM_IWR_ATVALIDM_Pos 0 /*!< ITM IWR: ATVALIDM Position */ +#define ITM_IWR_ATVALIDM_Msk (1UL << ITM_IWR_ATVALIDM_Pos) /*!< ITM IWR: ATVALIDM Mask */ + +/* ITM Integration Read Register Definitions */ +#define ITM_IRR_ATREADYM_Pos 0 /*!< ITM IRR: ATREADYM Position */ +#define ITM_IRR_ATREADYM_Msk (1UL << ITM_IRR_ATREADYM_Pos) /*!< ITM IRR: ATREADYM Mask */ + +/* ITM Integration Mode Control Register Definitions */ +#define ITM_IMCR_INTEGRATION_Pos 0 /*!< ITM IMCR: INTEGRATION Position */ +#define ITM_IMCR_INTEGRATION_Msk (1UL << ITM_IMCR_INTEGRATION_Pos) /*!< ITM IMCR: INTEGRATION Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2 /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1 /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0 /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL << ITM_LSR_Present_Pos) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IO uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IO uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IO uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IO uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IO uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IO uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __I uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IO uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + __IO uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ + __IO uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED0[1]; + __IO uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + __IO uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ + __IO uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED1[1]; + __IO uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + __IO uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ + __IO uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED2[1]; + __IO uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + __IO uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ + __IO uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28 /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27 /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26 /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25 /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24 /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22 /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21 /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20 /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19 /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18 /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17 /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16 /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12 /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10 /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9 /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5 /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1 /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0 /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL << DWT_CTRL_CYCCNTENA_Pos) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0 /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL << DWT_CPICNT_CPICNT_Pos) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0 /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL << DWT_EXCCNT_EXCCNT_Pos) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0 /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL << DWT_SLEEPCNT_SLEEPCNT_Pos) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0 /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL << DWT_LSUCNT_LSUCNT_Pos) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0 /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL << DWT_FOLDCNT_FOLDCNT_Pos) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Mask Register Definitions */ +#define DWT_MASK_MASK_Pos 0 /*!< DWT MASK: MASK Position */ +#define DWT_MASK_MASK_Msk (0x1FUL << DWT_MASK_MASK_Pos) /*!< DWT MASK: MASK Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_MATCHED_Pos 24 /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVADDR1_Pos 16 /*!< DWT FUNCTION: DATAVADDR1 Position */ +#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ + +#define DWT_FUNCTION_DATAVADDR0_Pos 12 /*!< DWT FUNCTION: DATAVADDR0 Position */ +#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10 /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_LNK1ENA_Pos 9 /*!< DWT FUNCTION: LNK1ENA Position */ +#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ + +#define DWT_FUNCTION_DATAVMATCH_Pos 8 /*!< DWT FUNCTION: DATAVMATCH Position */ +#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ + +#define DWT_FUNCTION_CYCMATCH_Pos 7 /*!< DWT FUNCTION: CYCMATCH Position */ +#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ + +#define DWT_FUNCTION_EMITRANGE_Pos 5 /*!< DWT FUNCTION: EMITRANGE Position */ +#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ + +#define DWT_FUNCTION_FUNCTION_Pos 0 /*!< DWT FUNCTION: FUNCTION Position */ +#define DWT_FUNCTION_FUNCTION_Msk (0xFUL << DWT_FUNCTION_FUNCTION_Pos) /*!< DWT FUNCTION: FUNCTION Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IO uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IO uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2]; + __IO uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55]; + __IO uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131]; + __I uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IO uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __I uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759]; + __I uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ + __I uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __I uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1]; + __I uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __I uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IO uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39]; + __IO uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IO uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8]; + __I uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __I uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0 /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL << TPI_ACPR_PRESCALER_Pos) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0 /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL << TPI_SPPR_TXMODE_Pos) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3 /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2 /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1 /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0 /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL << TPI_FFSR_FlInProg_Pos) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8 /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_EnFCont_Pos 1 /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0 /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL << TPI_TRIGGER_TRIGGER_Pos) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration ETM Data Register Definitions (FIFO0) */ +#define TPI_FIFO0_ITM_ATVALID_Pos 29 /*!< TPI FIFO0: ITM_ATVALID Position */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ + +#define TPI_FIFO0_ITM_bytecount_Pos 27 /*!< TPI FIFO0: ITM_bytecount Position */ +#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ + +#define TPI_FIFO0_ETM_ATVALID_Pos 26 /*!< TPI FIFO0: ETM_ATVALID Position */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ + +#define TPI_FIFO0_ETM_bytecount_Pos 24 /*!< TPI FIFO0: ETM_bytecount Position */ +#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ + +#define TPI_FIFO0_ETM2_Pos 16 /*!< TPI FIFO0: ETM2 Position */ +#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ + +#define TPI_FIFO0_ETM1_Pos 8 /*!< TPI FIFO0: ETM1 Position */ +#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ + +#define TPI_FIFO0_ETM0_Pos 0 /*!< TPI FIFO0: ETM0 Position */ +#define TPI_FIFO0_ETM0_Msk (0xFFUL << TPI_FIFO0_ETM0_Pos) /*!< TPI FIFO0: ETM0 Mask */ + +/* TPI ITATBCTR2 Register Definitions */ +#define TPI_ITATBCTR2_ATREADY_Pos 0 /*!< TPI ITATBCTR2: ATREADY Position */ +#define TPI_ITATBCTR2_ATREADY_Msk (0x1UL << TPI_ITATBCTR2_ATREADY_Pos) /*!< TPI ITATBCTR2: ATREADY Mask */ + +/* TPI Integration ITM Data Register Definitions (FIFO1) */ +#define TPI_FIFO1_ITM_ATVALID_Pos 29 /*!< TPI FIFO1: ITM_ATVALID Position */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ + +#define TPI_FIFO1_ITM_bytecount_Pos 27 /*!< TPI FIFO1: ITM_bytecount Position */ +#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ + +#define TPI_FIFO1_ETM_ATVALID_Pos 26 /*!< TPI FIFO1: ETM_ATVALID Position */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ + +#define TPI_FIFO1_ETM_bytecount_Pos 24 /*!< TPI FIFO1: ETM_bytecount Position */ +#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ + +#define TPI_FIFO1_ITM2_Pos 16 /*!< TPI FIFO1: ITM2 Position */ +#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ + +#define TPI_FIFO1_ITM1_Pos 8 /*!< TPI FIFO1: ITM1 Position */ +#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ + +#define TPI_FIFO1_ITM0_Pos 0 /*!< TPI FIFO1: ITM0 Position */ +#define TPI_FIFO1_ITM0_Msk (0xFFUL << TPI_FIFO1_ITM0_Pos) /*!< TPI FIFO1: ITM0 Mask */ + +/* TPI ITATBCTR0 Register Definitions */ +#define TPI_ITATBCTR0_ATREADY_Pos 0 /*!< TPI ITATBCTR0: ATREADY Position */ +#define TPI_ITATBCTR0_ATREADY_Msk (0x1UL << TPI_ITATBCTR0_ATREADY_Pos) /*!< TPI ITATBCTR0: ATREADY Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0 /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x1UL << TPI_ITCTRL_Mode_Pos) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11 /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10 /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9 /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_MinBufSz_Pos 6 /*!< TPI DEVID: MinBufSz Position */ +#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ + +#define TPI_DEVID_AsynClkIn_Pos 5 /*!< TPI DEVID: AsynClkIn Position */ +#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0 /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x1FUL << TPI_DEVID_NrTraceInput_Pos) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_SubType_Pos 0 /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL << TPI_DEVTYPE_SubType_Pos) /*!< TPI DEVTYPE: SubType Mask */ + +#define TPI_DEVTYPE_MajorType_Pos 4 /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if (__MPU_PRESENT == 1) +/** \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __I uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IO uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IO uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IO uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IO uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ + __IO uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ + __IO uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ + __IO uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ + __IO uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ + __IO uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ + __IO uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ +} MPU_Type; + +/* MPU Type Register */ +#define MPU_TYPE_IREGION_Pos 16 /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8 /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0 /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL << MPU_TYPE_SEPARATE_Pos) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register */ +#define MPU_CTRL_PRIVDEFENA_Pos 2 /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1 /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0 /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL << MPU_CTRL_ENABLE_Pos) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register */ +#define MPU_RNR_REGION_Pos 0 /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL << MPU_RNR_REGION_Pos) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register */ +#define MPU_RBAR_ADDR_Pos 5 /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4 /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0 /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL << MPU_RBAR_REGION_Pos) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register */ +#define MPU_RASR_ATTRS_Pos 16 /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28 /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24 /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19 /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18 /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17 /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16 /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8 /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1 /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0 /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL << MPU_RASR_ENABLE_Pos) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IO uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __O uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IO uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IO uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16 /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25 /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24 /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19 /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18 /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17 /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16 /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5 /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3 /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2 /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1 /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0 /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL << CoreDebug_DHCSR_C_DEBUGEN_Pos) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register */ +#define CoreDebug_DCRSR_REGWnR_Pos 16 /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0 /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL << CoreDebug_DCRSR_REGSEL_Pos) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register */ +#define CoreDebug_DEMCR_TRCENA_Pos 24 /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19 /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18 /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17 /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16 /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10 /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9 /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8 /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7 /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6 /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5 /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4 /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0 /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL << CoreDebug_DEMCR_VC_CORERESET_Pos) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Cortex-M3 Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ +#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ +#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ +#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ +#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ + +#if (__MPU_PRESENT == 1) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +/** \brief Set Priority Grouping + + The function sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FA << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << 8)); /* Insert write key and priorty group */ + SCB->AIRCR = reg_value; +} + + +/** \brief Get Priority Grouping + + The function reads the priority grouping field from the NVIC Interrupt Controller. + + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t NVIC_GetPriorityGrouping(void) +{ + return ((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos); /* read priority grouping field */ +} + + +/** \brief Enable External Interrupt + + The function enables a device-specific interrupt in the NVIC interrupt controller. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ + NVIC->ISER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* enable interrupt */ +} + + +/** \brief Disable External Interrupt + + The function disables a device-specific interrupt in the NVIC interrupt controller. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->ICER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* disable interrupt */ +} + + +/** \brief Get Pending Interrupt + + The function reads the pending register in the NVIC and returns the pending bit + for the specified interrupt. + + \param [in] IRQn Interrupt number. + + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t) ((NVIC->ISPR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); /* Return 1 if pending else 0 */ +} + + +/** \brief Set Pending Interrupt + + The function sets the pending bit of an external interrupt. + + \param [in] IRQn Interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ISPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* set interrupt pending */ +} + + +/** \brief Clear Pending Interrupt + + The function clears the pending bit of an external interrupt. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ICPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* Clear pending interrupt */ +} + + +/** \brief Get Active Interrupt + + The function reads the active register in NVIC and returns the active bit. + + \param [in] IRQn Interrupt number. + + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + */ +__STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn) +{ + return((uint32_t)((NVIC->IABR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); /* Return 1 if active else 0 */ +} + + +/** \brief Set Interrupt Priority + + The function sets the priority of an interrupt. + + \note The priority cannot be set for every core interrupt. + + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + */ +__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if(IRQn < 0) { + SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for Cortex-M System Interrupts */ + else { + NVIC->IP[(uint32_t)(IRQn)] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for device specific Interrupts */ +} + + +/** \brief Get Interrupt Priority + + The function reads the priority of an interrupt. The interrupt + number can be positive to specify an external (device specific) + interrupt, or negative to specify an internal (core) interrupt. + + + \param [in] IRQn Interrupt number. + \return Interrupt Priority. Value is aligned automatically to the implemented + priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +{ + + if(IRQn < 0) { + return((uint32_t)(SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] >> (8 - __NVIC_PRIO_BITS))); } /* get priority for Cortex-M system interrupts */ + else { + return((uint32_t)(NVIC->IP[(uint32_t)(IRQn)] >> (8 - __NVIC_PRIO_BITS))); } /* get priority for device specific interrupts */ +} + + +/** \brief Encode Priority + + The function encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the samllest possible priority group is set. + + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & 0x07); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp; + SubPriorityBits = ((PriorityGroupTmp + __NVIC_PRIO_BITS) < 7) ? 0 : PriorityGroupTmp - 7 + __NVIC_PRIO_BITS; + + return ( + ((PreemptPriority & ((1 << (PreemptPriorityBits)) - 1)) << SubPriorityBits) | + ((SubPriority & ((1 << (SubPriorityBits )) - 1))) + ); +} + + +/** \brief Decode Priority + + The function decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the samllest possible priority group is set. + + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* pPreemptPriority, uint32_t* pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & 0x07); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp; + SubPriorityBits = ((PriorityGroupTmp + __NVIC_PRIO_BITS) < 7) ? 0 : PriorityGroupTmp - 7 + __NVIC_PRIO_BITS; + + *pPreemptPriority = (Priority >> SubPriorityBits) & ((1 << (PreemptPriorityBits)) - 1); + *pSubPriority = (Priority ) & ((1 << (SubPriorityBits )) - 1); +} + + +/** \brief System Reset + + The function initiates a system reset request to reset the MCU. + */ +__STATIC_INLINE void NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = ((0x5FA << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + while(1); /* wait until reset */ +} + + +/** \brief Set Vector Table Offset + + + The function sets Vector Table Offset register. + + \param [in] TableAddress Vector table address. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_SetVectorTable(uint32_t TableAddress) +{ + SCB->VTOR = TableAddress; +} + + +/** \brief Set Vector Table Offset + + + The function sets Vector Table Offset register. + + \param [in] TableAddress Vector table address. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_SetCCR(void) +{ + uint32_t reg_value; + + reg_value = SCB->CCR; + reg_value |= SCB_CCR_DIV_0_TRP_Msk | SCB_CCR_UNALIGN_TRP_Msk; + SCB->CCR = reg_value; +} + + +/*@} end of CMSIS_Core_NVICFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if (__Vendor_SysTickConfig == 0) + +/** \brief System Tick Configuration + + The function initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + + \param [in] ticks Number of ticks between two interrupts. + + \return 0 Function succeeded. + \return 1 Function failed. + + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */ + + SysTick->LOAD = ticks - 1; /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY 0x5AA55AA5 /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** \brief ITM Send Character + + The function transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + + \param [in] ch Character to transmit. + + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if ((ITM->TCR & ITM_TCR_ITMENA_Msk) && /* ITM enabled */ + (ITM->TER & (1UL << 0) ) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0].u32 == 0); + ITM->PORT[0].u8 = (uint8_t) ch; + } + return (ch); +} + + +/** \brief ITM Receive Character + + The function inputs a character via the external variable \ref ITM_RxBuffer. + + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) { + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** \brief ITM Check Character + + The function checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) { + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) { + return (0); /* no character available */ + } else { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + +#endif /* __CORE_CM3_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ + +#ifdef __cplusplus +} +#endif diff --git a/component/soc/realtek/8195a/cmsis/core_cmFunc.h b/component/soc/realtek/8195a/cmsis/core_cmFunc.h new file mode 100644 index 0000000..0a18faf --- /dev/null +++ b/component/soc/realtek/8195a/cmsis/core_cmFunc.h @@ -0,0 +1,636 @@ +/**************************************************************************//** + * @file core_cmFunc.h + * @brief CMSIS Cortex-M Core Function Access Header File + * @version V3.20 + * @date 25. February 2013 + * + * @note + * + ******************************************************************************/ +/* Copyright (c) 2009 - 2013 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - 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. + - Neither the name of ARM 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 HOLDERS 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 COPYRIGHT HOLDERS AND 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 __CORE_CMFUNC_H +#define __CORE_CMFUNC_H + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ +/* ARM armcc specific functions */ + +#if (__ARMCC_VERSION < 400677) + #error "Please use ARM Compiler Toolchain V4.0.677 or later!" +#endif + +/* intrinsic void __enable_irq(); */ +/* intrinsic void __disable_irq(); */ + +/** \brief Get Control Register + + This function returns the content of the Control Register. + + \return Control Register value + */ +__STATIC_INLINE uint32_t __get_CONTROL(void) +{ + register uint32_t __regControl __ASM("control"); + return(__regControl); +} + + +/** \brief Set Control Register + + This function writes the given value to the Control Register. + + \param [in] control Control Register value to set + */ +__STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + register uint32_t __regControl __ASM("control"); + __regControl = control; +} + + +/** \brief Get IPSR Register + + This function returns the content of the IPSR Register. + + \return IPSR Register value + */ +__STATIC_INLINE uint32_t __get_IPSR(void) +{ + register uint32_t __regIPSR __ASM("ipsr"); + return(__regIPSR); +} + + +/** \brief Get APSR Register + + This function returns the content of the APSR Register. + + \return APSR Register value + */ +__STATIC_INLINE uint32_t __get_APSR(void) +{ + register uint32_t __regAPSR __ASM("apsr"); + return(__regAPSR); +} + + +/** \brief Get xPSR Register + + This function returns the content of the xPSR Register. + + \return xPSR Register value + */ +__STATIC_INLINE uint32_t __get_xPSR(void) +{ + register uint32_t __regXPSR __ASM("xpsr"); + return(__regXPSR); +} + + +/** \brief Get Process Stack Pointer + + This function returns the current value of the Process Stack Pointer (PSP). + + \return PSP Register value + */ +__STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + return(__regProcessStackPointer); +} + + +/** \brief Set Process Stack Pointer + + This function assigns the given value to the Process Stack Pointer (PSP). + + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + __regProcessStackPointer = topOfProcStack; +} + + +/** \brief Get Main Stack Pointer + + This function returns the current value of the Main Stack Pointer (MSP). + + \return MSP Register value + */ +__STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + return(__regMainStackPointer); +} + + +/** \brief Set Main Stack Pointer + + This function assigns the given value to the Main Stack Pointer (MSP). + + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + __regMainStackPointer = topOfMainStack; +} + + +/** \brief Get Priority Mask + + This function returns the current state of the priority mask bit from the Priority Mask Register. + + \return Priority Mask value + */ +__STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + register uint32_t __regPriMask __ASM("primask"); + return(__regPriMask); +} + + +/** \brief Set Priority Mask + + This function assigns the given value to the Priority Mask Register. + + \param [in] priMask Priority Mask + */ +__STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + register uint32_t __regPriMask __ASM("primask"); + __regPriMask = (priMask); +} + + +#if (__CORTEX_M >= 0x03) + +/** \brief Enable FIQ + + This function enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __enable_fault_irq __enable_fiq + + +/** \brief Disable FIQ + + This function disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __disable_fault_irq __disable_fiq + + +/** \brief Get Base Priority + + This function returns the current value of the Base Priority register. + + \return Base Priority register value + */ +__STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + register uint32_t __regBasePri __ASM("basepri"); + return(__regBasePri); +} + + +/** \brief Set Base Priority + + This function assigns the given value to the Base Priority register. + + \param [in] basePri Base Priority value to set + */ +__STATIC_INLINE void __set_BASEPRI(uint32_t basePri) +{ + register uint32_t __regBasePri __ASM("basepri"); + __regBasePri = (basePri & 0xff); +} + + +/** \brief Get Fault Mask + + This function returns the current value of the Fault Mask register. + + \return Fault Mask register value + */ +__STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + return(__regFaultMask); +} + + +/** \brief Set Fault Mask + + This function assigns the given value to the Fault Mask register. + + \param [in] faultMask Fault Mask value to set + */ +__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + __regFaultMask = (faultMask & (uint32_t)1); +} + +#endif /* (__CORTEX_M >= 0x03) */ + + +#if (__CORTEX_M == 0x04) + +/** \brief Get FPSCR + + This function returns the current value of the Floating Point Status/Control register. + + \return Floating Point Status/Control register value + */ +__STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + register uint32_t __regfpscr __ASM("fpscr"); + return(__regfpscr); +#else + return(0); +#endif +} + + +/** \brief Set FPSCR + + This function assigns the given value to the Floating Point Status/Control register. + + \param [in] fpscr Floating Point Status/Control value to set + */ +__STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + register uint32_t __regfpscr __ASM("fpscr"); + __regfpscr = (fpscr); +#endif +} + +#endif /* (__CORTEX_M == 0x04) */ + + +#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/ +/* IAR iccarm specific functions */ + +#include + + +#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/ +/* TI CCS specific functions */ + +#include + + +#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ +/* GNU gcc specific functions */ + +/** \brief Enable IRQ Interrupts + + This function enables IRQ interrupts by clearing the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void) +{ + __ASM volatile ("cpsie i" : : : "memory"); +} + + +/** \brief Disable IRQ Interrupts + + This function disables IRQ interrupts by setting the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void) +{ + __ASM volatile ("cpsid i" : : : "memory"); +} + + +/** \brief Get Control Register + + This function returns the content of the Control Register. + + \return Control Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + + +/** \brief Set Control Register + + This function writes the given value to the Control Register. + + \param [in] control Control Register value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); +} + + +/** \brief Get IPSR Register + + This function returns the content of the IPSR Register. + + \return IPSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get APSR Register + + This function returns the content of the APSR Register. + + \return APSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_APSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get xPSR Register + + This function returns the content of the xPSR Register. + + \return xPSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get Process Stack Pointer + + This function returns the current value of the Process Stack Pointer (PSP). + + \return PSP Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, psp\n" : "=r" (result) ); + return(result); +} + + +/** \brief Set Process Stack Pointer + + This function assigns the given value to the Process Stack Pointer (PSP). + + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0\n" : : "r" (topOfProcStack) : "sp"); +} + + +/** \brief Get Main Stack Pointer + + This function returns the current value of the Main Stack Pointer (MSP). + + \return MSP Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, msp\n" : "=r" (result) ); + return(result); +} + + +/** \brief Set Main Stack Pointer + + This function assigns the given value to the Main Stack Pointer (MSP). + + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack) : "sp"); +} + + +/** \brief Get Priority Mask + + This function returns the current state of the priority mask bit from the Priority Mask Register. + + \return Priority Mask value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask" : "=r" (result) ); + return(result); +} + + +/** \brief Set Priority Mask + + This function assigns the given value to the Priority Mask Register. + + \param [in] priMask Priority Mask + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); +} + + +#if (__CORTEX_M >= 0x03) + +/** \brief Enable FIQ + + This function enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_fault_irq(void) +{ + __ASM volatile ("cpsie f" : : : "memory"); +} + + +/** \brief Disable FIQ + + This function disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_fault_irq(void) +{ + __ASM volatile ("cpsid f" : : : "memory"); +} + + +/** \brief Get Base Priority + + This function returns the current value of the Base Priority register. + + \return Base Priority register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri_max" : "=r" (result) ); + return(result); +} + + +/** \brief Set Base Priority + + This function assigns the given value to the Base Priority register. + + \param [in] basePri Base Priority value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI(uint32_t value) +{ + __ASM volatile ("MSR basepri, %0" : : "r" (value) : "memory"); +} + + +/** \brief Get Fault Mask + + This function returns the current value of the Fault Mask register. + + \return Fault Mask register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); +} + + +/** \brief Set Fault Mask + + This function assigns the given value to the Fault Mask register. + + \param [in] faultMask Fault Mask value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); +} + +#endif /* (__CORTEX_M >= 0x03) */ + + +#if (__CORTEX_M == 0x04) + +/** \brief Get FPSCR + + This function returns the current value of the Floating Point Status/Control register. + + \return Floating Point Status/Control register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + uint32_t result; + + /* Empty asm statement works as a scheduling barrier */ + __ASM volatile (""); + __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); + __ASM volatile (""); + return(result); +#else + return(0); +#endif +} + + +/** \brief Set FPSCR + + This function assigns the given value to the Floating Point Status/Control register. + + \param [in] fpscr Floating Point Status/Control value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + /* Empty asm statement works as a scheduling barrier */ + __ASM volatile (""); + __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc"); + __ASM volatile (""); +#endif +} + +#endif /* (__CORTEX_M == 0x04) */ + + +#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ +/* TASKING carm specific functions */ + +/* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all instrinsics, + * Including the CMSIS ones. + */ + +#endif + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +#endif /* __CORE_CMFUNC_H */ diff --git a/component/soc/realtek/8195a/cmsis/core_cmInstr.h b/component/soc/realtek/8195a/cmsis/core_cmInstr.h new file mode 100644 index 0000000..d213f0e --- /dev/null +++ b/component/soc/realtek/8195a/cmsis/core_cmInstr.h @@ -0,0 +1,688 @@ +/**************************************************************************//** + * @file core_cmInstr.h + * @brief CMSIS Cortex-M Core Instruction Access Header File + * @version V3.20 + * @date 05. March 2013 + * + * @note + * + ******************************************************************************/ +/* Copyright (c) 2009 - 2013 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - 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. + - Neither the name of ARM 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 HOLDERS 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 COPYRIGHT HOLDERS AND 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 __CORE_CMINSTR_H +#define __CORE_CMINSTR_H + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ +/* ARM armcc specific functions */ + +#if (__ARMCC_VERSION < 400677) + #error "Please use ARM Compiler Toolchain V4.0.677 or later!" +#endif + + +/** \brief No Operation + + No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP __nop + + +/** \brief Wait For Interrupt + + Wait For Interrupt is a hint instruction that suspends execution + until one of a number of events occurs. + */ +#define __WFI __wfi + + +/** \brief Wait For Event + + Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE __wfe + + +/** \brief Send Event + + Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV __sev + + +/** \brief Instruction Synchronization Barrier + + Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or + memory, after the instruction has been completed. + */ +#define __ISB() __isb(0xF) + + +/** \brief Data Synchronization Barrier + + This function acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +#define __DSB() __dsb(0xF) + + +/** \brief Data Memory Barrier + + This function ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +#define __DMB() __dmb(0xF) + + +/** \brief Reverse byte order (32 bit) + + This function reverses the byte order in integer value. + + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV __rev + + +/** \brief Reverse byte order (16 bit) + + This function reverses the byte order in two unsigned short values. + + \param [in] value Value to reverse + \return Reversed value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value) +{ + rev16 r0, r0 + bx lr +} +#endif + +/** \brief Reverse byte order in signed short value + + This function reverses the byte order in a signed short value with sign extension to integer. + + \param [in] value Value to reverse + \return Reversed value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value) +{ + revsh r0, r0 + bx lr +} +#endif + + +/** \brief Rotate Right in unsigned value (32 bit) + + This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + + \param [in] value Value to rotate + \param [in] value Number of Bits to rotate + \return Rotated value + */ +#define __ROR __ror + + +/** \brief Breakpoint + + This function causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __breakpoint(value) + + +#if (__CORTEX_M >= 0x03) + +/** \brief Reverse bit order of value + + This function reverses the bit order of the given value. + + \param [in] value Value to reverse + \return Reversed value + */ +#define __RBIT __rbit + + +/** \brief LDR Exclusive (8 bit) + + This function performs a exclusive LDR command for 8 bit value. + + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr)) + + +/** \brief LDR Exclusive (16 bit) + + This function performs a exclusive LDR command for 16 bit values. + + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDREXH(ptr) ((uint16_t) __ldrex(ptr)) + + +/** \brief LDR Exclusive (32 bit) + + This function performs a exclusive LDR command for 32 bit values. + + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr)) + + +/** \brief STR Exclusive (8 bit) + + This function performs a exclusive STR command for 8 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXB(value, ptr) __strex(value, ptr) + + +/** \brief STR Exclusive (16 bit) + + This function performs a exclusive STR command for 16 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXH(value, ptr) __strex(value, ptr) + + +/** \brief STR Exclusive (32 bit) + + This function performs a exclusive STR command for 32 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXW(value, ptr) __strex(value, ptr) + + +/** \brief Remove the exclusive lock + + This function removes the exclusive lock which is created by LDREX. + + */ +#define __CLREX __clrex + + +/** \brief Signed Saturate + + This function saturates a signed value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT __ssat + + +/** \brief Unsigned Saturate + + This function saturates an unsigned value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT __usat + + +/** \brief Count leading zeros + + This function counts the number of leading zeros of a data value. + + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +#define __CLZ __clz + +#endif /* (__CORTEX_M >= 0x03) */ + + + +#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/ +/* IAR iccarm specific functions */ + +#include + + +#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/ +/* TI CCS specific functions */ + +#include + + +#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ +/* GNU gcc specific functions */ + +/* Define macros for porting to both thumb1 and thumb2. + * For thumb1, use low register (r0-r7), specified by constrant "l" + * Otherwise, use general registers, specified by constrant "r" */ +#if defined (__thumb__) && !defined (__thumb2__) +#define __CMSIS_GCC_OUT_REG(r) "=l" (r) +#define __CMSIS_GCC_USE_REG(r) "l" (r) +#else +#define __CMSIS_GCC_OUT_REG(r) "=r" (r) +#define __CMSIS_GCC_USE_REG(r) "r" (r) +#endif + +/** \brief No Operation + + No Operation does nothing. This instruction can be used for code alignment purposes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __NOP(void) +{ + __ASM volatile ("nop"); +} + + +/** \brief Wait For Interrupt + + Wait For Interrupt is a hint instruction that suspends execution + until one of a number of events occurs. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFI(void) +{ + __ASM volatile ("wfi"); +} + + +/** \brief Wait For Event + + Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFE(void) +{ + __ASM volatile ("wfe"); +} + + +/** \brief Send Event + + Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __SEV(void) +{ + __ASM volatile ("sev"); +} + + +/** \brief Instruction Synchronization Barrier + + Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or + memory, after the instruction has been completed. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __ISB(void) +{ + __ASM volatile ("isb"); +} + + +/** \brief Data Synchronization Barrier + + This function acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __DSB(void) +{ + __ASM volatile ("dsb"); +} + + +/** \brief Data Memory Barrier + + This function ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __DMB(void) +{ + __ASM volatile ("dmb"); +} + + +/** \brief Reverse byte order (32 bit) + + This function reverses the byte order in integer value. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV(uint32_t value) +{ +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) + return __builtin_bswap32(value); +#else + uint32_t result; + + __ASM volatile ("rev %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +#endif +} + + +/** \brief Reverse byte order (16 bit) + + This function reverses the byte order in two unsigned short values. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV16(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} + + +/** \brief Reverse byte order in signed short value + + This function reverses the byte order in a signed short value with sign extension to integer. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __REVSH(int32_t value) +{ +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + return (short)__builtin_bswap16(value); +#else + uint32_t result; + + __ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +#endif +} + + +/** \brief Rotate Right in unsigned value (32 bit) + + This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + + \param [in] value Value to rotate + \param [in] value Number of Bits to rotate + \return Rotated value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + return (op1 >> op2) | (op1 << (32 - op2)); +} + + +/** \brief Breakpoint + + This function causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __ASM volatile ("bkpt "#value) + + +#if (__CORTEX_M >= 0x03) + +/** \brief Reverse bit order of value + + This function reverses the bit order of the given value. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + + +/** \brief LDR Exclusive (8 bit) + + This function performs a exclusive LDR command for 8 bit value. + + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __LDREXB(volatile uint8_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return(result); +} + + +/** \brief LDR Exclusive (16 bit) + + This function performs a exclusive LDR command for 16 bit values. + + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint16_t __LDREXH(volatile uint16_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return(result); +} + + +/** \brief LDR Exclusive (32 bit) + + This function performs a exclusive LDR command for 32 bit values. + + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __LDREXW(volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("ldrex %0, %1" : "=r" (result) : "Q" (*addr) ); + return(result); +} + + +/** \brief STR Exclusive (8 bit) + + This function performs a exclusive STR command for 8 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) ); + return(result); +} + + +/** \brief STR Exclusive (16 bit) + + This function performs a exclusive STR command for 16 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) ); + return(result); +} + + +/** \brief STR Exclusive (32 bit) + + This function performs a exclusive STR command for 32 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("strex %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) ); + return(result); +} + + +/** \brief Remove the exclusive lock + + This function removes the exclusive lock which is created by LDREX. + + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __CLREX(void) +{ + __ASM volatile ("clrex" ::: "memory"); +} + + +/** \brief Signed Saturate + + This function saturates a signed value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** \brief Unsigned Saturate + + This function saturates an unsigned value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** \brief Count leading zeros + + This function counts the number of leading zeros of a data value. + + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __CLZ(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("clz %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + +#endif /* (__CORTEX_M >= 0x03) */ + + + + +#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ +/* TASKING carm specific functions */ + +/* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all intrinsics, + * Including the CMSIS ones. + */ + +#endif + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + +#endif /* __CORE_CMINSTR_H */ diff --git a/component/soc/realtek/8195a/cmsis/device/app_start.c b/component/soc/realtek/8195a/cmsis/device/app_start.c new file mode 100644 index 0000000..64f9bbf --- /dev/null +++ b/component/soc/realtek/8195a/cmsis/device/app_start.c @@ -0,0 +1,192 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#include "rtl8195a.h" +#include "build_info.h" +#ifdef PLATFORM_FREERTOS +#include "FreeRTOS.h" +#include "task.h" +#endif + +#if defined (CONFIG_USB_EN) && defined(CONFIG_USB_HOST_ONLY) + extern void _usb_init(void); +#endif + +#if defined(CONFIG_SDIO_DEVICE_EN) && defined(CONFIG_SDIO_DEVICE_NORMAL) +extern VOID HalSdioInit(VOID); +#endif + +#if defined(CONFIG_WIFI_NORMAL) && defined(CONFIG_NETWORK) +extern void init_rom_wlan_ram_map(void); +extern VOID wlan_network(VOID); +#endif + +//3 Monitor App Function +extern VOID RtlConsolInitRam(u32 Boot, u32 TBLSz, VOID *pTBL); +#ifndef CONFIG_KERNEL +extern VOID RtlConsolTaskRom(VOID *Data); +#endif + +#ifndef CONFIG_WITHOUT_MONITOR +extern COMMAND_TABLE UartLogRamCmdTable[]; +extern u32 GetRamCmdNum(VOID); +extern VOID UartLogIrqHandleRam(VOID * Data); +#endif + +#ifdef CONFIG_APP_DEMO +#define MAIN_APP_DEFAULT_STACK_SIZE 2048 +#define MAIN_APP_DEFAULT_PRIORITY (tskIDLE_PRIORITY + 1) +#endif + +#ifdef CONFIG_MBED_ENABLED +extern void __libc_fini_array (void); +extern void __libc_init_array (void); +extern void SVC_Handler (void); +extern void PendSV_Handler (void); +extern void SysTick_Handler (void); +#endif + +#ifndef CONFIG_WITHOUT_MONITOR +static +VOID +ReRegisterPlatformLogUart( + VOID +) +{ + IRQ_HANDLE UartIrqHandle; + + //4 Register Log Uart Callback function + UartIrqHandle.Data = NULL;//(u32)&UartAdapter; + UartIrqHandle.IrqNum = UART_LOG_IRQ; + UartIrqHandle.IrqFun = (IRQ_FUN) UartLogIrqHandleRam; + UartIrqHandle.Priority = 0; + + + //4 Register Isr handle + InterruptUnRegister(&UartIrqHandle); + InterruptRegister(&UartIrqHandle); +#if !TASK_SCHEDULER_DISABLED + RtlConsolInitRam((u32)RAM_STAGE,(u32)GetRamCmdNum(),(VOID*)&UartLogRamCmdTable); +#else + RtlConsolInitRam((u32)ROM_STAGE,(u32)GetRamCmdNum(),(VOID*)&UartLogRamCmdTable); +#endif +} +#endif // end of "#ifndef CONFIG_WITHOUT_MONITOR" + + +VOID ShowRamBuildInfo(VOID) +{ + /* + DBG_8195A("=========================================================\n\n"); + //DBG_8195A("Build Time: "UTS_VERSION"\n"); + DBG_8195A("Build Time: "RTL8195AFW_COMPILE_TIME"\n"); + DBG_8195A("Build Author: "RTL8195AFW_COMPILE_BY"\n"); + DBG_8195A("Build Host: "RTL8195AFW_COMPILE_HOST"\n"); + DBG_8195A("Build ToolChain Version: "RTL195AFW_COMPILER"\n\n"); + DBG_8195A("=========================================================\n"); + */ +} + +#ifdef CONFIG_APP_DEMO +#include "device.h" +#include "gpio_api.h" // mbed + +_WEAK void main(void) +{ + gpio_t gpio_led; + +#ifndef CONFIG_WITHOUT_MONITOR + ReRegisterPlatformLogUart(); +#endif + + // Init LED control pin + gpio_init(&gpio_led, PC_5); + gpio_dir(&gpio_led, PIN_OUTPUT); // Direction: Output + gpio_mode(&gpio_led, PullNone); // No pull + while(1){ + gpio_write(&gpio_led, !gpio_read(&gpio_led)); + RtlMsleepOS(1000); + } +} +#else +//default main +_WEAK void main(void) +{ + // Init SDIO +#if defined(CONFIG_SDIO_DEVICE_EN) && defined(CONFIG_SDIO_DEVICE_NORMAL) + HalSdioInit(); +#endif + +#ifndef CONFIG_WITHOUT_MONITOR + ReRegisterPlatformLogUart(); +#endif + +#if defined(CONFIG_WIFI_NORMAL) && defined(CONFIG_NETWORK) + wlan_network(); +#else + +#if defined (CONFIG_USB_EN) && defined(CONFIG_USB_HOST_ONLY) + _usb_init(); +#endif + +#endif // end of else of "#if defined(CONFIG_WIFI_NORMAL) && defined(CONFIG_NETWORK)" + + //3 4)Enable Schedule +#if defined(CONFIG_KERNEL) && !TASK_SCHEDULER_DISABLED + #ifdef PLATFORM_FREERTOS + vTaskStartScheduler(); + #endif +#else + RtlConsolTaskRom(NULL); +#endif + +} +#endif // end of #if CONFIG_APP_DEMO + +// The Main App entry point +void _AppStart(void) +{ +#ifdef CONFIG_MBED_ENABLED + InterruptForOSInit((VOID*)SVC_Handler, + (VOID*)PendSV_Handler, + (VOID*)SysTick_Handler); + __asm ( + "ldr r0, =SystemInit\n" + "blx r0\n" + "ldr r0, =_start\n" + "bx r0\n" + ); + + for(;;); +#else + // It's Not Mbed BSP +#ifdef CONFIG_KERNEL +#endif + + // Disable debug info log of spiflash + DBG_INFO_MSG_OFF(_DBG_SPI_FLASH_); + +#ifdef CONFIG_APP_DEMO +#ifdef PLATFORM_FREERTOS + xTaskCreate( (TaskFunction_t)main, "MAIN_APP__TASK", (MAIN_APP_DEFAULT_STACK_SIZE/4), (void *)NULL, MAIN_APP_DEFAULT_PRIORITY, NULL); + vTaskStartScheduler(); +#endif +#else + // force SP align to 8 byte not 4 byte (initial SP is 4 byte align) + __asm( + "mov r0, sp\n" + "bic r0, r0, #7\n" + "mov sp, r0\n" + ); + + main(); +#endif // end of #if CONFIG_APP_DEMO + +#endif // end of else of "#ifdef CONFIG_MBED_ENABLED" +} diff --git a/component/soc/realtek/8195a/cmsis/device/cmsis.h b/component/soc/realtek/8195a/cmsis/device/cmsis.h new file mode 100644 index 0000000..420fd53 --- /dev/null +++ b/component/soc/realtek/8195a/cmsis/device/cmsis.h @@ -0,0 +1,38 @@ +/* mbed Microcontroller Library + * A generic CMSIS include header + ******************************************************************************* + * Copyright (c) 2014, STMicroelectronics + * 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 STMicroelectronics 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 HOLDERS 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 MBED_CMSIS_H +#define MBED_CMSIS_H + +#include "rtl8195a.h" +#include "cmsis_nvic.h" + +#endif diff --git a/component/soc/realtek/8195a/cmsis/device/cmsis_nvic.c b/component/soc/realtek/8195a/cmsis/device/cmsis_nvic.c new file mode 100644 index 0000000..e89187b --- /dev/null +++ b/component/soc/realtek/8195a/cmsis/device/cmsis_nvic.c @@ -0,0 +1,55 @@ +/* mbed Microcontroller Library + * CMSIS-style functionality to support dynamic vectors + ******************************************************************************* + * Copyright (c) 2014, STMicroelectronics + * 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 STMicroelectronics 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 HOLDERS 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. + ******************************************************************************* + */ +#include "cmsis_nvic.h" + +#define NVIC_RAM_VECTOR_ADDRESS (0x10000000) // Vectors positioned at start of RAM +#define NVIC_ROM_VECTOR_ADDRESS (0x00000000) // Initial vector position at start of ROM + +void NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) { + uint32_t *vectors = (uint32_t *)SCB->VTOR; + uint32_t i; + + // Copy and switch to dynamic vectors if the first time called + if (SCB->VTOR != NVIC_RAM_VECTOR_ADDRESS) { + uint32_t *old_vectors = vectors; + vectors = (uint32_t*)NVIC_RAM_VECTOR_ADDRESS; + for (i=0; iVTOR = (uint32_t)NVIC_RAM_VECTOR_ADDRESS; + } + vectors[IRQn + NVIC_USER_IRQ_OFFSET] = vector; +} + +uint32_t NVIC_GetVector(IRQn_Type IRQn) { + uint32_t *vectors = (uint32_t*)SCB->VTOR; + return vectors[IRQn + NVIC_USER_IRQ_OFFSET]; +} diff --git a/component/soc/realtek/8195a/cmsis/device/cmsis_nvic.h b/component/soc/realtek/8195a/cmsis/device/cmsis_nvic.h new file mode 100644 index 0000000..ca0b5b9 --- /dev/null +++ b/component/soc/realtek/8195a/cmsis/device/cmsis_nvic.h @@ -0,0 +1,54 @@ +/* mbed Microcontroller Library + * CMSIS-style functionality to support dynamic vectors + ******************************************************************************* + * Copyright (c) 2014, STMicroelectronics + * 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 STMicroelectronics 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 HOLDERS 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 MBED_CMSIS_NVIC_H +#define MBED_CMSIS_NVIC_H + +// CORE: 64 vectors = 64 bytes from 0x00 to 0x3F +// MCU Peripherals: 85 vectors = 340 bytes from 0x40 to ... +// Total: 128 vectors = 512 bytes (0x200) to be reserved in RAM +#define NVIC_NUM_VECTORS 128 +#define NVIC_USER_IRQ_OFFSET 64 + +#include "cmsis.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void NVIC_SetVector(IRQn_Type IRQn, uint32_t vector); +uint32_t NVIC_GetVector(IRQn_Type IRQn); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/component/soc/realtek/8195a/cmsis/device/diag.h b/component/soc/realtek/8195a/cmsis/device/diag.h new file mode 100644 index 0000000..c3dbf8e --- /dev/null +++ b/component/soc/realtek/8195a/cmsis/device/diag.h @@ -0,0 +1,808 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#ifndef _DIAG_H_ +#define _DIAG_H_ + +#include "platform_autoconf.h" +#include "basic_types.h" + +#include /* for size_t */ + +extern u32 ConfigDebugErr; +extern u32 ConfigDebugInfo; +extern u32 ConfigDebugWarn; + +extern u32 CfgSysDebugErr; +extern u32 CfgSysDebugInfo; +extern u32 CfgSysDebugWarn; + +#define DBG_ERR_MSG_ON(x) (ConfigDebugErr |= (x)) +#define DBG_WARN_MSG_ON(x) (ConfigDebugWarn |= (x)) +#define DBG_INFO_MSG_ON(x) (ConfigDebugInfo |= (x)) + +#define DBG_ERR_MSG_OFF(x) (ConfigDebugErr &= ~(x)) +#define DBG_WARN_MSG_OFF(x) (ConfigDebugWarn &= ~(x)) +#define DBG_INFO_MSG_OFF(x) (ConfigDebugInfo &= ~(x)) + +// Define debug group +#define _DBG_BOOT_ 0x00000001 +#define _DBG_GDMA_ 0x00000002 +#define _DBG_GPIO_ 0x00000004 +#define _DBG_TIMER_ 0x00000008 +#define _DBG_I2C_ 0x00000010 +#define _DBG_I2S_ 0x00000020 +#define _DBG_MII_ 0x00000040 +#define _DBG_NFC_ 0x00000080 +#define _DBG_PCM_ 0x00000100 +#define _DBG_PWM_ 0x00000200 +#define _DBG_SDIO_ 0x00000400 +#define _DBG_SSI_ 0x00000800 +#define _DBG_SPI_FLASH_ 0x00001000 +#define _DBG_SDR_ 0x00002000 +#define _DBG_UART_ 0x00004000 +#define _DBG_USB_OTG_ 0x00008000 +#define _DBG_USB_CORE_ 0x00010000 +#define _DBG_CRYPTO_ 0x00020000 +#define _DBG_ADC_ 0x00040000 +#define _DBG_DAC_ 0x00080000 + +#define _DBG_MISC_ 0x40000000 +#define _DBG_FAULT_ 0x80000000 + +typedef enum _SYSTEM_DBG_DEFINE_ { + _SYSDBG_MISC_ = 1<<0, + _SYSDBG_MAILBOX_ = 1<<1, + _SYSDBG_TIMER_ = 1<<2 + +} SYSTEM_DBG; + +extern +_LONG_CALL_ u32 +DiagPrintf( + IN const char *fmt, ... +); + +u32 +DiagSPrintf( + IN u8 *buf, + IN const char *fmt, ... +); + +int +prvDiagPrintf( + IN const char *fmt, ... +); + +int +prvDiagSPrintf( + IN char *buf, + IN const char *fmt, ... +); + + +#define _DbgDump DiagPrintf + +#define DRIVER_PREFIX "RTL8195A[Driver]: " +#define HAL_PREFIX "RTL8195A[HAL]: " +#define DMA_PREFIX "RTL8195A[DMA]: " +#define SDIO_PREFIX "RTL8195A[SDIO]" +#define MBOX_PREFIX "[OS-MBOX]" +#define TIMER_PREFIX "[OS-TMR]" + +#define BOOT_ERR_PREFIX "[BOOT Err]" +#define BOOT_WARN_PREFIX "[BOOT Wrn]" +#define BOOT_INFO_PREFIX "[BOOT Inf]" + +#define GDMA_ERR_PREFIX "[GDMA Err]" +#define GDMA_WARN_PREFIX "[GDMA Wrn]" +#define GDMA_INFO_PREFIX "[GDMA Inf]" + +#define GPIO_ERR_PREFIX "[GPIO Err]" +#define GPIO_WARN_PREFIX "[GPIO Wrn]" +#define GPIO_INFO_PREFIX "[GPIO Inf]" + +#define TIMER_ERR_PREFIX "[TIMR Err]" +#define TIMER_WARN_PREFIX "[TIMR Wrn]" +#define TIMER_INFO_PREFIX "[TIMR Inf]" + +#define I2C_ERR_PREFIX "[I2C Err]" +#define I2C_WARN_PREFIX "[I2C Wrn]" +#define I2C_INFO_PREFIX "[I2C Inf]" + +#define I2S_ERR_PREFIX "[I2S Err]" +#define I2S_WARN_PREFIX "[I2S Wrn]" +#define I2S_INFO_PREFIX "[I2S Inf]" + +#define MII_ERR_PREFIX "[MII Err]" +#define MII_WARN_PREFIX "[MII Wrn]" +#define MII_INFO_PREFIX "[MII Inf]" + +#define NFC_ERR_PREFIX "[NFC Err]" +#define NFC_WARN_PREFIX "[NFC Wrn]" +#define NFC_INFO_PREFIX "[NFC Inf]" + +#define PCM_ERR_PREFIX "[PCM Err]" +#define PCM_WARN_PREFIX "[PCM Wrn]" +#define PCM_INFO_PREFIX "[PCM Inf]" + +#define PWM_ERR_PREFIX "[PWM Err]" +#define PWM_WARN_PREFIX "[PWM Wrn]" +#define PWM_INFO_PREFIX "[PWM Inf]" + +#define SSI_ERR_PREFIX "[SSI Err]" +#define SSI_WARN_PREFIX "[SSI Wrn]" +#define SSI_INFO_PREFIX "[SSI Inf]" + +#define SDIO_ERR_PREFIX "[SDIO Err]" +#define SDIO_WARN_PREFIX "[SDIO Wrn]" +#define SDIO_INFO_PREFIX "[SDIO Inf]" + +#define SPIF_ERR_PREFIX "[SPIF Err]" +#define SPIF_WARN_PREFIX "[SPIF Wrn]" +#define SPIF_INFO_PREFIX "[SPIF Inf]" + +#define SDR_ERR_PREFIX "[SDR Err]" +#define SDR_WARN_PREFIX "[SDR Wrn]" +#define SDR_INFO_PREFIX "[SDR Inf]" + +#define UART_ERR_PREFIX "[UART Err]" +#define UART_WARN_PREFIX "[UART Wrn]" +#define UART_INFO_PREFIX "[UART Inf]" + +#define USB_ERR_PREFIX "[USB Err]" +#define USB_WARN_PREFIX "[USB Wrn]" +#define USB_INFO_PREFIX "[USB Inf]" + +#define IPSEC_ERR_PREFIX "[CRYP Err]" +#define IPSEC_WARN_PREFIX "[CRYP Wrn]" +#define IPSEC_INFO_PREFIX "[CRYP Inf]" + +#define ADC_ERR_PREFIX "[ADC Err]" +#define ADC_WARN_PREFIX "[ADC Wrn]" +#define ADC_INFO_PREFIX "[ADC Inf]" + +#define DAC_ERR_PREFIX "[DAC Err]" +#define DAC_WARN_PREFIX "[DAC Wrn]" +#define DAC_INFO_PREFIX "[DAC Inf]" + +#define MISC_ERR_PREFIX "[MISC Err]" +#define MISC_WARN_PREFIX "[MISC Wrn]" +#define MISC_INFO_PREFIX "[MISC Inf]" + +#define OTG_ERR_PREFIX "[OTG Err]" +#define OTG_WARN_PREFIX "[OTG Wrn]" +#define OTG_INFO_PREFIX "[OTG Inf]" + +#define OTG_PREFIX "RTL8195A[OTG]: " +#define OTG_PREFIX_LVL "RTL8195A[OTG_LVL_%2x]: " + +//#ifdef +#define CONFIG_DEBUG_ERROR 1 +#define CONFIG_DEBUG_WARN 1 +#define CONFIG_DEBUG_INFO 1 + +#ifndef likely +#define likely(x) (x) +#define unlikely(x) (x) +#endif + +#ifdef CONFIG_DEBUG_LOG + +#if CONFIG_DEBUG_ERROR // if Build-In Debug Error Message + +#define DBG_BOOT_ERR(...) do {\ + if (likely(ConfigDebugErr & _DBG_BOOT_)) \ + _DbgDump("\r"BOOT_ERR_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_GDMA_ERR(...) do {\ + if (likely(ConfigDebugErr & _DBG_GDMA_)) \ + _DbgDump("\r"GDMA_ERR_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_GPIO_ERR(...) do {\ + if (likely(ConfigDebugErr & _DBG_GPIO_)) \ + _DbgDump("\r"GPIO_ERR_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_TIMER_ERR(...) do {\ + if (likely(ConfigDebugErr & _DBG_TIMER_)) \ + _DbgDump("\r"TIMER_ERR_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_I2C_ERR(...) do {\ + if (likely(ConfigDebugErr & _DBG_I2C_)) \ + _DbgDump("\r"I2C_ERR_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_I2S_ERR(...) do {\ + if (likely(ConfigDebugErr & _DBG_I2S_)) \ + _DbgDump("\r"I2S_ERR_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_MII_ERR(...) do {\ + if (likely(ConfigDebugErr & _DBG_MII_)) \ + _DbgDump("\r"MII_ERR_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_NFC_ERR(...) do {\ + if (likely(ConfigDebugErr & _DBG_NFC_)) \ + _DbgDump("\r"NFC_ERR_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_PCM_ERR(...) do {\ + if (likely(ConfigDebugErr & _DBG_PCM_)) \ + _DbgDump("\r"PCM_ERR_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_PWM_ERR(...) do {\ + if (likely(ConfigDebugErr & _DBG_PWM_)) \ + _DbgDump("\r"PWM_ERR_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_SSI_ERR(...) do {\ + if (likely(ConfigDebugErr & _DBG_SSI_)) \ + _DbgDump("\r"SSI_ERR_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_SDIO_ERR(...) do {\ + if (likely(ConfigDebugErr & _DBG_SDIO_)) \ + _DbgDump("\r"SDIO_ERR_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_SPIF_ERR(...) do {\ + if (likely(ConfigDebugErr & _DBG_SPI_FLASH_)) \ + _DbgDump("\r"SPIF_ERR_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_SDR_ERR(...) do {\ + if (likely(ConfigDebugErr & _DBG_SDR_)) \ + _DbgDump("\r"SDR_ERR_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_UART_ERR(...) do {\ + if (likely(ConfigDebugErr & _DBG_UART_)) \ + _DbgDump("\r"UART_ERR_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_USBOTG_ERR(...) do {\ + if (likely(ConfigDebugErr & _DBG_USB_OTG_)) \ + _DbgDump("\r" __VA_ARGS__);\ +}while(0) + +#define DBG_USBCOR_ERR(...) do {\ + if (likely(ConfigDebugErr & _DBG_USB_CORE_)) \ + _DbgDump("\r"USB_ERR_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_CRYPTO_ERR(...) do {\ + if (likely(ConfigDebugErr & _DBG_CRYPTO_)) \ + _DbgDump("\r"IPSEC_ERR_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_ADC_ERR(...) do {\ + if (likely(ConfigDebugErr & _DBG_ADC_)) \ + _DbgDump("\r"ADC_ERR_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_DAC_ERR(...) do {\ + if (likely(ConfigDebugErr & _DBG_DAC_)) \ + _DbgDump("\r"DAC_ERR_PREFIX __VA_ARGS__);\ +}while(0) + +#define MSG_MBOX_ERR(...) do {\ + if (likely(CfgSysDebugErr & _SYSDBG_MAILBOX_)) \ + _DbgDump("\r"MBOX_PREFIX __VA_ARGS__);\ +}while(0) + +#define MSG_TIMER_ERR(...) do {\ + if (likely(CfgSysDebugErr & _SYSDBG_TIMER_)) \ + _DbgDump("\r"TIMER_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_8195A_OTG(...) do{\ + if (unlikely(ConfigDebugInfo & _DBG_USB_OTG_)) \ + _DbgDump("\r"OTG_PREFIX __VA_ARGS__);\ + }while(0) + + +#define DBG_8195A_OTG_LVL(LVL,...) do{\ + if (unlikely(ConfigDebugInfo & _DBG_USB_OTG_)){ \ + _DbgDump("\r"OTG_PREFIX_LVL,LVL);\ + _DbgDump(__VA_ARGS__);\ + }\ + }while(0) + +#else // else of "#if CONFIG_DEBUG_ERROR" + +#define DBG_BOOT_ERR(...) +#define DBG_GDMA_ERR(...) +#define DBG_GPIO_ERR(...) +#define DBG_TIMER_ERR(...) +#define DBG_I2C_ERR(...) +#define DBG_I2S_ERR(...) +#define DBG_MII_ERR(...) +#define DBG_NFC_ERR(...) +#define DBG_PCM_ERR(...) +#define DBG_PWM_ERR(...) +#define DBG_SSI_ERR(...) +#define DBG_SDIO_ERR(...) +#define DBG_SPIF_ERR(...) +#define DBG_SDR_ERR(...) +#define DBG_UART_ERR(...) +#define DBG_USBOTG_ERR(...) +#define DBG_USBCOR_ERR(...) +#define DBG_CRYPTO_ERR(...) +#define DBG_ADC_ERR(...) +#define DBG_DAC_ERR(...) + +#define MSG_MBOX_ERR(...) +#define MSG_TIMER_ERR(...) +#define DBG_8195A_OTG(...) +#define DBG_8195A_OTG_LVL(LVL,...) + +#endif // end of else of "#if CONFIG_DEBUG_ERROR" + +// ============================================================= + +#if CONFIG_DEBUG_WARN // if Build-In Debug Warring Message + +#define DBG_BOOT_WARN(...) do {\ + if (unlikely(ConfigDebugWarn& _DBG_BOOT_)) \ + _DbgDump("\r"BOOT_WARN_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_GDMA_WARN(...) do {\ + if (unlikely(ConfigDebugWarn & _DBG_GDMA_)) \ + _DbgDump("\r"GDMA_WARN_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_GPIO_WARN(...) do {\ + if (unlikely(ConfigDebugWarn & _DBG_GPIO_)) \ + _DbgDump("\r"GPIO_WARN_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_TIMER_WARN(...) do {\ + if (unlikely(ConfigDebugWarn & _DBG_TIMER_)) \ + _DbgDump("\r"TIMER_WARN_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_I2C_WARN(...) do {\ + if (unlikely(ConfigDebugWarn & _DBG_I2C_)) \ + _DbgDump("\r"I2C_WARN_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_I2S_WARN(...) do {\ + if (unlikely(ConfigDebugWarn & _DBG_I2S_)) \ + _DbgDump("\r"I2S_WARN_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_MII_WARN(...) do {\ + if (unlikely(ConfigDebugWarn & _DBG_MII_)) \ + _DbgDump("\r"MII_WARN_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_NFC_WARN(...) do {\ + if (unlikely(ConfigDebugWarn & _DBG_NFC_)) \ + _DbgDump("\r"NFC_WARN_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_PCM_WARN(...) do {\ + if (unlikely(ConfigDebugWarn & _DBG_PCM_)) \ + _DbgDump("\r"PCM_WARN_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_PWM_WARN(...) do {\ + if (unlikely(ConfigDebugWarn & _DBG_PWM_)) \ + _DbgDump("\r"PWM_WARN_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_SSI_WARN(...) do {\ + if (unlikely(ConfigDebugWarn & _DBG_SSI_)) \ + _DbgDump("\r"SSI_WARN_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_SDIO_WARN(...) do {\ + if (unlikely(ConfigDebugWarn & _DBG_SDIO_)) \ + _DbgDump("\r"SDIO_WARN_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_SPIF_WARN(...) do {\ + if (unlikely(ConfigDebugWarn & _DBG_SPI_FLASH_)) \ + _DbgDump("\r"SPIF_WARN_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_SDR_WARN(...) do {\ + if (unlikely(ConfigDebugWarn & _DBG_SDR_)) \ + _DbgDump("\r"SDR_WARN_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_UART_WARN(...) do {\ + if (unlikely(ConfigDebugWarn & _DBG_UART_)) \ + _DbgDump("\r"UART_WARN_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_USBOTG_WARN(...) do {\ + if (unlikely(ConfigDebugWarn & _DBG_USB_OTG_)) \ + _DbgDump("\r" __VA_ARGS__);\ +}while(0) + +#define DBG_USBCOR_WARN(...) do {\ + if (unlikely(ConfigDebugWarn & _DBG_USB_CORE_)) \ + _DbgDump("\r"USB_WARN_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_CRYPTO_WARN(...) do {\ + if (unlikely(ConfigDebugWarn & _DBG_CRYPTO_)) \ + _DbgDump("\r"IPSEC_WARN_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_ADC_WARN(...) do {\ + if (unlikely(ConfigDebugWarn & _DBG_ADC_)) \ + _DbgDump("\r"ADC_WARN_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_DAC_WARN(...) do {\ + if (unlikely(ConfigDebugWarn & _DBG_DAC_)) \ + _DbgDump("\r"DAC_WARN_PREFIX __VA_ARGS__);\ +}while(0) + +#define MSG_MBOX_WARN(...) do {\ + if (unlikely(CfgSysDebugWarn& _SYSDBG_MAILBOX_)) \ + _DbgDump("\r"MBOX_PREFIX __VA_ARGS__);\ +}while(0) + +#define MSG_TIMER_WARN(...) do {\ + if (unlikely(CfgSysDebugWarn & _SYSDBG_TIMER_)) \ + _DbgDump("\r"TIMER_PREFIX __VA_ARGS__);\ +}while(0) + +#else // else of "#if CONFIG_DEBUG_WARN" + +#define DBG_BOOT_WARN(...) +#define DBG_GDMA_WARN(...) +#define DBG_GPIO_WARN(...) +#define DBG_TIMER_WARN(...) +#define DBG_I2C_WARN(...) +#define DBG_I2S_WARN(...) +#define DBG_MII_WARN(...) +#define DBG_NFC_WARN(...) +#define DBG_PCM_WARN(...) +#define DBG_PWM_WARN(...) +#define DBG_SSI_WARN(...) +#define DBG_SDIO_WARN(...) +#define DBG_SPIF_WARN(...) +#define DBG_SDR_WARN(...) +#define DBG_UART_WARN(...) +#define DBG_USBOTG_WARN(...) +#define DBG_USBCOR_WARN(...) +#define DBG_CRYPTO_WARN(...) +#define DBG_ADC_WARN(...) +#define DBG_DAC_WARN(...) + +#define MSG_MBOX_WARN(...) +#define MSG_TIMER_WARN(...) + +#endif // end of else of "#if CONFIG_DEBUG_WARN" + +// ============================================================= + +#if CONFIG_DEBUG_INFO // if Build-In Debug Information Message + +#define DBG_BOOT_INFO(...) do {\ + if (unlikely(ConfigDebugInfo & _DBG_BOOT_)) \ + _DbgDump("\r"BOOT_INFO_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_GDMA_INFO(...) do {\ + if (unlikely(ConfigDebugInfo & _DBG_GDMA_)) \ + _DbgDump("\r"GDMA_INFO_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_GPIO_INFO(...) do {\ + if (unlikely(ConfigDebugInfo & _DBG_GPIO_)) \ + _DbgDump("\r"GPIO_INFO_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_TIMER_INFO(...) do {\ + if (unlikely(ConfigDebugInfo & _DBG_TIMER_)) \ + _DbgDump("\r"TIMER_INFO_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_I2C_INFO(...) do {\ + if (unlikely(ConfigDebugInfo & _DBG_I2C_)) \ + _DbgDump("\r"I2C_INFO_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_I2S_INFO(...) do {\ + if (unlikely(ConfigDebugInfo & _DBG_I2S_)) \ + _DbgDump("\r"I2S_INFO_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_MII_INFO(...) do {\ + if (unlikely(ConfigDebugInfo & _DBG_MII_)) \ + _DbgDump("\r"MII_INFO_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_NFC_INFO(...) do {\ + if (unlikely(ConfigDebugInfo & _DBG_NFC_)) \ + _DbgDump("\r"NFC_INFO_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_PCM_INFO(...) do {\ + if (unlikely(ConfigDebugInfo & _DBG_PCM_)) \ + _DbgDump("\r"PCM_INFO_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_PWM_INFO(...) do {\ + if (unlikely(ConfigDebugInfo & _DBG_PWM_)) \ + _DbgDump("\r"PWM_INFO_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_SSI_INFO(...) do {\ + if (unlikely(ConfigDebugInfo & _DBG_SSI_)) \ + _DbgDump("\r"SSI_INFO_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_SDIO_INFO(...) do {\ + if (unlikely(ConfigDebugInfo & _DBG_SDIO_)) \ + _DbgDump("\r"SDIO_INFO_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_SPIF_INFO(...) do {\ + if (unlikely(ConfigDebugInfo & _DBG_SPI_FLASH_)) \ + _DbgDump("\r"SPIF_INFO_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_SDR_INFO(...) do {\ + if (unlikely(ConfigDebugInfo & _DBG_SDR_)) \ + _DbgDump("\r"SDR_INFO_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_UART_INFO(...) do {\ + if (unlikely(ConfigDebugInfo & _DBG_UART_)) \ + _DbgDump("\r"UART_INFO_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_USBOTG_INFO(...) do {\ + if (unlikely(ConfigDebugInfo & _DBG_USB_OTG_)) \ + _DbgDump("\r" __VA_ARGS__);\ +}while(0) + +#define DBG_USBCOR_INFO(...) do {\ + if (unlikely(ConfigDebugInfo & _DBG_USB_CORE_)) \ + _DbgDump("\r"USB_INFO_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_CRYPTO_INFO(...) do {\ + if (unlikely(ConfigDebugInfo & _DBG_CRYPTO_)) \ + _DbgDump("\r"IPSEC_INFO_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_ADC_INFO(...) do {\ + if (unlikely(ConfigDebugInfo & _DBG_ADC_)) \ + _DbgDump("\r"ADC_INFO_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_DAC_INFO(...) do {\ + if (unlikely(ConfigDebugInfo & _DBG_DAC_)) \ + _DbgDump("\r"DAC_INFO_PREFIX __VA_ARGS__);\ +}while(0) + +#define MSG_MBOX_INFO(...) do {\ + if (unlikely(CfgSysDebugInfo & _SYSDBG_MAILBOX_)) \ + _DbgDump("\r"MBOX_PREFIX __VA_ARGS__);\ +}while(0) + +#define MSG_TIMER_INFO(...) do {\ + if (unlikely(CfgSysDebugInfo & _SYSDBG_TIMER_)) \ + _DbgDump("\r"TIMER_PREFIX __VA_ARGS__);\ +}while(0) + +#else // else of "#if CONFIG_DEBUG_INFO" + +#define DBG_BOOT_INFO(...) +#define DBG_GDMA_INFO(...) +#define DBG_GPIO_INFO(...) +#define DBG_TIMER_INFO(...) +#define DBG_I2C_INFO(...) +#define DBG_I2S_INFO(...) +#define DBG_MII_INFO(...) +#define DBG_NFC_INFO(...) +#define DBG_PCM_INFO(...) +#define DBG_PWM_INFO(...) +#define DBG_SSI_INFO(...) +#define DBG_SDIO_INFO(...) +#define DBG_SPIF_INFO(...) +#define DBG_SDR_INFO(...) +#define DBG_UART_INFO(...) +#define DBG_USBOTG_INFO(...) +#define DBG_USBCOR_INFO(...) +#define DBG_CRYPTO_INFO(...) +#define DBG_ADC_INFO(...) +#define DBG_DAC_INFO(...) + +#define MSG_MBOX_INFO(...) +#define MSG_TIMER_INFO(...) + +#endif // end of else of "#if CONFIG_DEBUG_INFO" + +#define DBG_8195A_DRIVER(...) do {\ + if (unlikely(ConfigDebugErr & (_DBG_I2S_|_DBG_PCM_|_DBG_TIMER_))) \ + _DbgDump("\r"DRIVER_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_8195A_HAL(...) do {\ + if (unlikely(ConfigDebugErr & (_DBG_SDR_|_DBG_MISC_))) \ + _DbgDump("\r"HAL_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_8195A_DMA(...) do {\ + if (unlikely(ConfigDebugErr & _DBG_GDMA_)) \ + _DbgDump("\r"DMA_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_8195A_SDIO(...) do {\ + if (unlikely(ConfigDebugErr & _DBG_SDIO_)) \ + _DbgDump("\r"SDIO_PREFIX __VA_ARGS__);\ +}while(0) + +#define DBG_8195A(...) do {\ + if (unlikely(ConfigDebugErr & _DBG_MISC_)) \ + _DbgDump("\r" __VA_ARGS__);\ +}while(0) + +#define MONITOR_LOG(...) do {\ + if (unlikely(ConfigDebugErr & _DBG_MISC_)) \ + _DbgDump( __VA_ARGS__);\ +}while(0) + +#define DBG_ERROR_LOG(...) do {\ + if (unlikely(ConfigDebugErr & _DBG_FAULT_)) \ + _DbgDump( __VA_ARGS__);\ +}while(0) + +#ifdef __GNUC__ +#define DBG_ASSERT(x) do {\ + if (unlikely(!(x))) \ + _DbgDump("Assertion: %s:%s, %d\n", __FILE__, __func__, __LINE__);\ + }while(0) +#endif + +#ifdef __ICCARM__ +#define DBG_ASSERT(x) do {\ + if (unlikely(!(x))) \ + _DbgDump("Assertion: %s:%s, %d\n", __FILE__, __func__, __LINE__);\ + }while(0) +#endif + +#else // else of "#if CONFIG_DEBUG_LOG" +#define DBG_8195A_DRIVER(...) + +#define DBG_8195A_HAL(...) + +#define DBG_8195A(...) + +#define DBG_8195A_DMA(...) + +#define MONITOR_LOG(...) + +#define DBG_ERROR_LOG(...) + +#define DBG_8195A_SDIO(...) + +#define DBG_BOOT_ERR(...) +#define DBG_GDMA_ERR(...) +#define DBG_GPIO_ERR(...) +#define DBG_TIMER_ERR(...) +#define DBG_I2C_ERR(...) +#define DBG_I2S_ERR(...) +#define DBG_MII_ERR(...) +#define DBG_NFC_ERR(...) +#define DBG_PCM_ERR(...) +#define DBG_PWM_ERR(...) +#define DBG_SSI_ERR(...) +#define DBG_SDIO_ERR(...) +#define DBG_SPIF_ERR(...) +#define DBG_SDR_ERR(...) +#define DBG_UART_ERR(...) +#define DBG_USBOTG_ERR(...) +#define DBG_USBCOR_ERR(...) +#define DBG_CRYPTO_ERR(...) +#define DBG_ADC_ERR(...) +#define DBG_DAC_ERR(...) +#define MSG_MBOX_ERR(...) +#define MSG_TIMER_ERR(...) + +#define DBG_BOOT_WARN(...) +#define DBG_GDMA_WARN(...) +#define DBG_GPIO_WARN(...) +#define DBG_TIMER_WARN(...) +#define DBG_I2C_WARN(...) +#define DBG_I2S_WARN(...) +#define DBG_MII_WARN(...) +#define DBG_NFC_WARN(...) +#define DBG_PCM_WARN(...) +#define DBG_PWM_WARN(...) +#define DBG_SSI_WARN(...) +#define DBG_SDIO_WARN(...) +#define DBG_SPIF_WARN(...) +#define DBG_SDR_WARN(...) +#define DBG_UART_WARN(...) +#define DBG_USBOTG_WARN(...) +#define DBG_USBCOR_WARN(...) +#define DBG_CRYPTO_WARN(...) +#define DBG_ADC_WARN(...) +#define DBG_DAC_WARN(...) +#define MSG_MBOX_WARN(...) +#define MSG_TIMER_WARN(...) + +#define DBG_BOOT_INFO(...) +#define DBG_GDMA_INFO(...) +#define DBG_GPIO_INFO(...) +#define DBG_TIMER_INFO(...) +#define DBG_I2C_INFO(...) +#define DBG_I2S_INFO(...) +#define DBG_MII_INFO(...) +#define DBG_NFC_INFO(...) +#define DBG_PCM_INFO(...) +#define DBG_PWM_INFO(...) +#define DBG_SSI_INFO(...) +#define DBG_SDIO_INFO(...) +#define DBG_SPIF_INFO(...) +#define DBG_SDR_INFO(...) +#define DBG_UART_INFO(...) +#define DBG_USBOTG_INFO(...) +#define DBG_USBCOR_INFO(...) +#define DBG_CRYPTO_INFO(...) +#define DBG_ADC_INFO(...) +#define DBG_DAC_INFO(...) + +#define MSG_MBOX_INFO(...) +#define MSG_TIMER_INFO(...) + +#define DBG_ASSERT(x) + +#endif + +#define ANSI_COLOR_GREEN "\x1b[32m" +#define ANSI_COLOR_CYAN "\x1b[36m" +#define ANSI_COLOR_YELLOW "\x1b[33m" +#define ANSI_COLOR_MAGENTA "\x1b[35m" +#define ANSI_COLOR_RED "\x1b[31m" +#define ANSI_COLOR_BLUE "\x1b[34m" +#define ANSI_COLOR_RESET "\x1b[0m" + +#define IDENT_ONE_SPACE " " +#define IDENT_TWO_SPACE " " +#define IDENT_FOUR_SPACE " " +#define IDENT_SIX_SPACE " " +#define IDENT_EIGHT_SPACE " " + +#ifdef CONFIG_DEBUG_LOG +typedef enum _DBG_CFG_TYPE_ { + DBG_CFG_ERR=0, + DBG_CFG_WARN=1, + DBG_CFG_INFO=2 +} DBG_CFG_TYPE; + +typedef struct _DBG_CFG_CMD_ { + u8 cmd_name[16]; + u32 cmd_type; +} DBG_CFG_CMD, *PDBG_CFG_CMD; + +#endif + +typedef enum _CONSOLE_OP_STAGE_ { + ROM_STAGE = 0, + RAM_STAGE = 1 +}CONSOLE_OP_STAGE; + +#endif //_DIAG_H_ diff --git a/component/soc/realtek/8195a/cmsis/device/rand.h b/component/soc/realtek/8195a/cmsis/device/rand.h new file mode 100644 index 0000000..47ac51e --- /dev/null +++ b/component/soc/realtek/8195a/cmsis/device/rand.h @@ -0,0 +1,15 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +u32 +Rand ( + VOID +); + + diff --git a/component/soc/realtek/8195a/cmsis/device/rtl_stdlib.h b/component/soc/realtek/8195a/cmsis/device/rtl_stdlib.h new file mode 100644 index 0000000..36c0d67 --- /dev/null +++ b/component/soc/realtek/8195a/cmsis/device/rtl_stdlib.h @@ -0,0 +1,41 @@ +/* + * Routines for standard lib access + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#ifndef _RTL_STDLIB_H_ +#define _RTL_STDLIB_H_ + +#include +#include +#include + +// +// string operation +// +#define strlen(str) prvStrLen((const u8*)str) +#define strcmp(str1, str2) prvStrCmp((const u8*)str1, (const u8*)str2) +#define sscanf(src, format...) //TODO +#define strtok(str, delim) prvStrTok(str, delim) +#define strcpy(dst, src) prvStrCpy((u8 *)dst, (const u8*)src) +#define atoi(str) prvAtoi(str) +#define strstr(str1, str2) prvStrStr(str1, str2) + +// +// standard i/o +// +#define snprintf DiagSnPrintf +#define sprintf prvDiagSPrintf +#define printf prvDiagPrintf + +// +// memory management +// +#define malloc pvPortMalloc +#define free vPortFree + +#endif //_RTL_STDLIB_H_ diff --git a/component/soc/realtek/8195a/cmsis/device/rtl_utility.h b/component/soc/realtek/8195a/cmsis/device/rtl_utility.h new file mode 100644 index 0000000..6fa22ff --- /dev/null +++ b/component/soc/realtek/8195a/cmsis/device/rtl_utility.h @@ -0,0 +1,70 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * + ******************************************************************************/ +#ifndef __RTL_UTILITY_H_ +#define __RTL_UTILITY_H_ + +VOID RtlMemcpy(VOID* dec, VOID* sour, u32 sz); +u32 RtlMemcmp(VOID *dst, VOID *src, u32 sz); +VOID RtlMemset(VOID *pbuf, u32 c, u32 sz); + +s8 * +RtlStrncpy( + IN s8 *dest, + IN const s8 *src, + IN SIZE_T count +); + +s8 * +RtlStrcpy( + IN s8 *dest, + IN const s8 *src +); + + +SIZE_T +RtlStrlen( + IN const s8 *s +); + + +SIZE_T +RtlStrnlen( + IN const s8 *s, + IN SIZE_T count +); + + +int +RtlStrcmp( + IN const s8 *cs, + IN const s8 *ct + +); + +int +RtlStrncmp( + IN const s8 *cs, + IN const s8 *ct, + IN SIZE_T count +); + +#endif + + diff --git a/component/soc/realtek/8195a/cmsis/device/strproc.h b/component/soc/realtek/8195a/cmsis/device/strproc.h new file mode 100644 index 0000000..127a23d --- /dev/null +++ b/component/soc/realtek/8195a/cmsis/device/strproc.h @@ -0,0 +1,104 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#ifndef _STRPROC_H_ +#define _STRPROC_H_ + +#include /* for size_t */ +#include "va_list.h" + +#ifndef isprint +#define in_range(c, lo, up) ((u8)c >= lo && (u8)c <= up) +#define isprint(c) in_range(c, 0x20, 0x7f) +#define isdigit(c) in_range(c, '0', '9') +#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F')) +#define islower(c) in_range(c, 'a', 'z') +#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v' || c == ',') +#endif + + +extern _LONG_CALL_ char *_strncpy(char *dest, const char *src, size_t count); +extern _LONG_CALL_ char *_strcpy(char *dest, const char *src); +extern _LONG_CALL_ size_t _strlen(const char *s); +extern _LONG_CALL_ size_t _strnlen(const char *s, size_t count); +extern _LONG_CALL_ int _strcmp(const char *cs, const char *ct); +extern _LONG_CALL_ int _strncmp(const char *cs, const char *ct, size_t count); +extern _LONG_CALL_ int _sscanf(const char *buf, const char *fmt, ...); +extern _LONG_CALL_ char *_strsep(char **s, const char *ct); +extern _LONG_CALL_ char *skip_spaces(const char *str); +extern _LONG_CALL_ int skip_atoi(const char **s); +extern _LONG_CALL_ int _vsscanf(const char *buf, const char *fmt, va_list args); +extern _LONG_CALL_ unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base); +extern _LONG_CALL_ long simple_strtol(const char *cp, char **endp, unsigned int base); +extern _LONG_CALL_ long long simple_strtoll(const char *cp, char **endp, unsigned int base); +extern _LONG_CALL_ unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base); +extern _LONG_CALL_ const char *_parse_integer_fixup_radix(const char *s, unsigned int *base); +extern _LONG_CALL_ unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long *p); +extern _LONG_CALL_ u64 div_u64(u64 dividend, u32 divisor); +extern _LONG_CALL_ s64 div_s64(s64 dividend, s32 divisor); +extern _LONG_CALL_ u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder); +extern _LONG_CALL_ s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder); +extern _LONG_CALL_ char *_strpbrk(const char *cs, const char *ct); +extern _LONG_CALL_ char *_strchr(const char *s, int c); + + +extern _LONG_CALL_ VOID +prvStrCpy( + IN u8 *pDES, + IN const u8 *pSRC +); + +extern _LONG_CALL_ u32 +prvStrLen( + IN const u8 *pSRC +); + +extern _LONG_CALL_ u8 +prvStrCmp( + IN const u8 *string1, + IN const u8 *string2 +); + +extern _LONG_CALL_ u8* +StrUpr( + IN u8 *string +); + +extern _LONG_CALL_ int prvAtoi( + IN const char * s +); + +extern _LONG_CALL_ const char * prvStrStr( + IN const char * str1, + IN const char * str2 +); + + +/* + * Fast implementation of tolower() for internal usage. Do not use in your + * code. + */ +static inline char _tolower(const char c) +{ + return c | 0x20; +} + +/* Fast check for octal digit */ +static inline int isodigit(const char c) +{ + return c >= '0' && c <= '7'; +} +#ifndef strtoul +#define strtoul(str, endp, base) simple_strtoul(str, endp, base) +#endif +#ifndef strtol +#define strtol(str, endp, base) simple_strtol(str, endp, base) +#endif + +#endif diff --git a/component/soc/realtek/8195a/cmsis/device/system_8195a.c b/component/soc/realtek/8195a/cmsis/device/system_8195a.c new file mode 100644 index 0000000..a4a8c50 --- /dev/null +++ b/component/soc/realtek/8195a/cmsis/device/system_8195a.c @@ -0,0 +1,139 @@ +/**************************************************************************//** + * @file system_ARMCM3.c + * @brief CMSIS Device System Source File for + * ARMCM3 Device Series + * @version V1.08 + * @date 23. November 2012 + * + * @note + * + ******************************************************************************/ +/* Copyright (c) 2011 - 2012 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - 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. + - Neither the name of ARM 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 HOLDERS 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 COPYRIGHT HOLDERS AND 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. + ---------------------------------------------------------------------------*/ + + +#include "basic_types.h" +#include "rtl8195a.h" + +/*---------------------------------------------------------------------------- + Define clocks + *----------------------------------------------------------------------------*/ +#define __HSI ( 8000000UL) +#define __XTAL ( 5000000UL) /* Oscillator frequency */ + +//#define __SYSTEM_CLOCK (5*__XTAL) +#define __SYSTEM_CLOCK (200000000UL/6*5) + +extern unsigned int rand_x; +extern u32 HalGetCpuClk(VOID); + +#if CONFIG_CHIP_A_CUT +const u32 SysCpkClkTbl[]= { + 200000000, + 100000000, + 50000000, + 25000000, + 12500000, + 4000000 +}; +#endif + +u32 Rand2(void) +{ + static unsigned int y = 362436; + static unsigned int z = 521288629; + static unsigned int c = 7654321; + + unsigned long long t, a= 698769069; + + rand_x = 69069 * rand_x + 12345; + y ^= (y << 13); y ^= (y >> 17); y ^= (y << 5); + t = a * z + c; c = (t >> 32); z = t; + + return rand_x + y + z; +} + +/*---------------------------------------------------------------------------- + Clock Variable definitions + *----------------------------------------------------------------------------*/ +uint32_t SystemCoreClock = __SYSTEM_CLOCK;/*!< System Clock Frequency (Core Clock)*/ + + +u32 +SystemGetCpuClk(void) +{ +#if CONFIG_CHIP_A_CUT + + u32 CpuType = 0, CpuClk = 0, FreqDown = 0; + + CpuType = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_CLK_CTRL1) & (0x70)) >> 4); + FreqDown = HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_SYSPLL_CTRL1) & BIT17; + + CpuClk = SysCpkClkTbl[CpuType]; + + if ( !FreqDown ) { + if ( CpuClk > 4000000 ){ + CpuClk = (CpuClk*5/6); + } + } + + return CpuClk; +#else + return HalGetCpuClk(); +#endif +} + +/*---------------------------------------------------------------------------- + Clock functions + *----------------------------------------------------------------------------*/ +void SystemCoreClockUpdate (void) /* Get Core Clock Frequency */ +{ +// SystemCoreClock = __SYSTEM_CLOCK; + + SystemCoreClock = SystemGetCpuClk(); +} + +/** + * Initialize the system + * + * @param none + * @return none + * + * @brief Setup the microcontroller system. + * Initialize the System. + */ +void SystemInit (void) +{ + // TODO: Hardware initial +#ifdef UNALIGNED_SUPPORT_DISABLE + SCB->CCR |= SCB_CCR_UNALIGN_TRP_Msk; +#endif + + //SystemCoreClock = __SYSTEM_CLOCK; + //SystemCoreClock = HalGetCpuClk(); + SystemCoreClockUpdate(); +} diff --git a/component/soc/realtek/8195a/cmsis/device/system_8195a.h b/component/soc/realtek/8195a/cmsis/device/system_8195a.h new file mode 100644 index 0000000..a730aff --- /dev/null +++ b/component/soc/realtek/8195a/cmsis/device/system_8195a.h @@ -0,0 +1,77 @@ +/**************************************************************************//** + * @file system_ARMCM3.h + * @brief CMSIS Device System Header File for + * ARMCM3 Device Series + * @version V1.08 + * @date 23. November 2012 + * + * @note + * + ******************************************************************************/ +/* Copyright (c) 2011 - 2012 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - 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. + - Neither the name of ARM 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 HOLDERS 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 COPYRIGHT HOLDERS AND 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 _SYSTEM_8195A_H +#define _SYSTEM_8195A_H + +#ifdef __cplusplus +extern "C" { +#endif + +extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */ + + +/** + * Initialize the system + * + * @param none + * @return none + * + * @brief Setup the microcontroller system. + * Initialize the System and update the SystemCoreClock variable. + */ +extern void SystemInit (void); + +/** + * Update SystemCoreClock variable + * + * @param none + * @return none + * + * @brief Updates the SystemCoreClock with current core Clock + * retrieved from cpu registers. + */ +extern void SystemCoreClockUpdate (void); +extern u32 SystemGetCpuClk(void); +extern u32 Rand2(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _SYSTEM_8195A_H */ diff --git a/component/soc/realtek/8195a/cmsis/device/va_list.h b/component/soc/realtek/8195a/cmsis/device/va_list.h new file mode 100644 index 0000000..d3a1dd1 --- /dev/null +++ b/component/soc/realtek/8195a/cmsis/device/va_list.h @@ -0,0 +1,37 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#ifndef _VA_LIST_H_ +#define _VA_LIST_H_ + +#include "platform_autoconf.h" +#include "basic_types.h" + +#ifndef va_arg //this part is adapted from linux (Linux/include/acpi/platform/acenv.h) + +typedef s32 acpi_native_int;//this definition is in (Linux/include/acpi/actypes.h) + +#ifndef _VALIST +#define _VALIST + typedef char *va_list; +#endif /* _VALIST */ + +/* Storage alignment properties */ +#define _AUPBND (sizeof (acpi_native_int) - 1) +#define _ADNBND (sizeof (acpi_native_int) - 1) + +/* Variable argument list macro definitions */ +#define _bnd(X, bnd) (((sizeof (X)) + (bnd)) & (~(bnd))) +#define va_arg(ap, T) (*(T *)(((ap) += (_bnd (T, _AUPBND))) - (_bnd (T,_ADNBND)))) +#define va_end(ap) (ap = (va_list) NULL) +#define va_start(ap, A) (void) ((ap) = (((char *) &(A)) + (_bnd (A,_AUPBND)))) + +#endif /* va_arg */ + +#endif //_VA_LIST_H_ diff --git a/component/soc/realtek/8195a/fwlib/hal_adc.h b/component/soc/realtek/8195a/fwlib/hal_adc.h new file mode 100644 index 0000000..e5c72f5 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/hal_adc.h @@ -0,0 +1,317 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#ifndef _HAL_ADC_H_ +#define _HAL_ADC_H_ + +#include "rtl8195a.h" +#include "rtl8195a_adc.h" +#include "hal_gdma.h" + +//================ ADC Configuration ========================= +#define ADC_INTR_OP_TYPE 1 +#define ADC_DMA_OP_TYPE 1 + +// ADC SAL management macros +#define SAL_ADC_USER_CB_NUM (sizeof(SAL_ADC_USER_CB) / sizeof(PSAL_ADC_USERCB_ADPT)) + +// ADC used module. +// Please set the ADC module flag to 1 to enable the related +#define ADC0_USED 1 +#define ADC1_USED 1 +#define ADC2_USED 1 +#define ADC3_USED 1 + + +//================ Debug MSG Definition ======================= +#define ADC_PREFIX "RTL8195A[adc]: " +#define ADC_PREFIX_LVL " [ADC_DBG]: " + +typedef enum _ADC_DBG_LVL_ { + HAL_ADC_LVL = 0x01, + SAL_ADC_LVL = 0x02, + VERI_ADC_LVL = 0x04, +}ADC_DBG_LVL,*PADC_DBG_LVL; + +#ifdef CONFIG_DEBUG_LOG +#ifdef CONFIG_DEBUG_LOG_ADC_HAL + + #define DBG_8195A_ADC(...) do{ \ + _DbgDump("\r"ADC_PREFIX __VA_ARGS__);\ + }while(0) + + + #define ADCDBGLVL 0xFF + #define DBG_8195A_ADC_LVL(LVL,...) do{\ + if (LVL&ADCDBGLVL){\ + _DbgDump("\r"ADC_PREFIX_LVL __VA_ARGS__);\ + }\ + }while(0) +#else + #define DBG_ADC_LOG_PERD 100 + #define DBG_8195A_ADC(...) + #define DBG_8195A_ADC_LVL(...) +#endif +#endif + + +//================ ADC HAL Related Enumeration ================== +// ADC Module Selection +typedef enum _ADC_MODULE_SEL_ { + ADC0_SEL = 0x0, + ADC1_SEL = 0x1, + ADC2_SEL = 0x2, + ADC3_SEL = 0x3, +}ADC_MODULE_SEL,*PADC_MODULE_SEL; + +// ADC module status +typedef enum _ADC_MODULE_STATUS_ { + ADC_DISABLE = 0x0, + ADC_ENABLE = 0x1, +}ADC_MODULE_STATUS, *PADC_MODULE_STATUS; + +// ADC Data Endian +typedef enum _ADC_DATA_ENDIAN_ { + ADC_DATA_ENDIAN_LITTLE = 0x0, + ADC_DATA_ENDIAN_BIG = 0x1, +}ADC_DATA_ENDIAN,*PADC_DATA_ENDIAN; + +// ADC Debug Select +typedef enum _ADC_DEBUG_SEL_ { + ADC_DBG_SEL_DISABLE = 0x0, + ADC_DBG_SEL_ENABLE = 0x1, +}ADC_DEBUG_SEL,*PADC_DEBUG_SEL; + +typedef enum _ADC_COMPARE_SET_ { + ADC_COMP_SMALLER_THAN = 0x0, + ADC_COMP_GREATER_THAN = 0x1, +}ADC_COMPARE_SET, *PADC_COMPARE_SET; + +// ADC feature status +typedef enum _ADC_FEATURE_STATUS_{ + ADC_FEATURE_DISABLED = 0, + ADC_FEATURE_ENABLED = 1, +}ADC_FEATURE_STATUS,*PADC_FEATURE_STATUS; + +// ADC operation type +typedef enum _ADC_OP_TYPE_ { + ADC_RDREG_TYPE = 0x0, + ADC_DMA_TYPE = 0x1, + ADC_INTR_TYPE = 0x2, +}ADC_OP_TYPE, *PADC_OP_TYPE; + +// ADC device status +typedef enum _ADC_DEVICE_STATUS_ { + ADC_STS_UNINITIAL = 0x00, + ADC_STS_INITIALIZED = 0x01, + ADC_STS_IDLE = 0x02, + + ADC_STS_TX_READY = 0x03, + ADC_STS_TX_ING = 0x04, + + ADC_STS_RX_READY = 0x05, + ADC_STS_RX_ING = 0x06, + + ADC_STS_ERROR = 0x07, + ADC_STS_FULL = 0x08, +}ADC_DEVICE_STATUS, *PADC_DEVICE_STATUS; + +// ADC error type +typedef enum _ADC_ERR_TYPE_ { + ADC_ERR_FIFO_RD_ERROR = 0x40, //ADC FIFO read error +}ADC_ERR_TYPE, *PADC_ERR_TYPE; + +// ADC initial status +typedef enum _ADC_INITAIL_STATUS_ { + ADC0_INITED = 0x1, + ADC1_INITED = 0x2, + ADC2_INITED = 0x4, + ADC3_INITED = 0x8, +}ADC_INITAIL_STATUS, *PADC_INITAIL_STATUS; + + +//================ ADC HAL Data Structure ====================== +// ADC HAL initial data structure +typedef struct _HAL_ADC_INIT_DAT_ { + u8 ADCIdx; //ADC index used + u8 ADCEn; //ADC module enable + u8 ADCEndian; //ADC endian selection, + //but actually it's for 32-bit ADC data swap control + //1'b0: no swap, + //1'b1: swap the upper 16-bit and the lower 16-bit + u8 ADCBurstSz; //ADC DMA operation threshold + + u8 ADCCompOnly; //ADC compare mode only enable (without FIFO enable) + u8 ADCOneShotEn; //ADC one-shot mode enable + u8 ADCOverWREn; //ADC overwrite mode enable + u8 ADCOneShotTD; //ADC one shot mode threshold + + u16 ADCCompCtrl; //ADC compare mode control, + //1'b0:less than the compare threshold + //1'b1:greater than the compare threshod + u16 ADCCompTD; //ADC compare mode threshold + + u8 ADCDataRate; //ADC down sample data rate, + u8 ADCAudioEn; //ADC audio mode enable + u8 ADCEnManul; //ADC enable manually + u8 ADCDbgSel; + + u32 RSVD0; + + u32 *ADCData; //ADC data pointer + u32 ADCPWCtrl; //ADC0 power control + u32 ADCIntrMSK; //ADC Interrupt Mask + u32 ADCAnaParAd3; //ADC analog parameter 3 + u32 ADCInInput; //ADC Input is internal? +}HAL_ADC_INIT_DAT,*PHAL_ADC_INIT_DAT; + +// ADC HAL Operations +typedef struct _HAL_ADC_OP_ { + RTK_STATUS (*HalADCInit) (VOID *Data); //HAL ADC initialization + RTK_STATUS (*HalADCDeInit) (VOID *Data); //HAL ADC de-initialization + RTK_STATUS (*HalADCEnable) (VOID *Data); //HAL ADC de-initialization + u32 (*HalADCReceive) (VOID *Data); //HAL ADC receive + RTK_STATUS (*HalADCIntrCtrl) (VOID *Data); //HAL ADC interrupt control + u32 (*HalADCReadReg) (VOID *Data, u8 ADCReg);//HAL ADC read register +}HAL_ADC_OP, *PHAL_ADC_OP; + +// ADC user callback adapter +typedef struct _SAL_ADC_USERCB_ADPT_ { + VOID (*USERCB) (VOID *Data); + u32 USERData; +}SAL_ADC_USERCB_ADPT, *PSAL_ADC_USERCB_ADPT; + +// ADC user callback structure +typedef struct _SAL_ADC_USER_CB_ { + PSAL_ADC_USERCB_ADPT pTXCB; //ADC Transmit Callback + PSAL_ADC_USERCB_ADPT pTXCCB; //ADC Transmit Complete Callback + PSAL_ADC_USERCB_ADPT pRXCB; //ADC Receive Callback + PSAL_ADC_USERCB_ADPT pRXCCB; //ADC Receive Complete Callback + PSAL_ADC_USERCB_ADPT pRDREQCB; //ADC Read Request Callback + PSAL_ADC_USERCB_ADPT pERRCB; //ADC Error Callback + PSAL_ADC_USERCB_ADPT pDMATXCB; //ADC DMA Transmit Callback + PSAL_ADC_USERCB_ADPT pDMATXCCB; //ADC DMA Transmit Complete Callback + PSAL_ADC_USERCB_ADPT pDMARXCB; //ADC DMA Receive Callback + PSAL_ADC_USERCB_ADPT pDMARXCCB; //ADC DMA Receive Complete Callback +}SAL_ADC_USER_CB, *PSAL_ADC_USER_CB; + +// ADC Transmit Buffer +typedef struct _SAL_ADC_TRANSFER_BUF_ { + u32 DataLen; //ADC Transmfer Length + u32 *pDataBuf; //ADC Transfer Buffer Pointer + u32 RSVD; // +}SAL_ADC_TRANSFER_BUF,*PSAL_ADC_TRANSFER_BUF; + +typedef struct _SAL_ADC_DMA_USER_DEF_ { + + u8 TxDatSrcWdth; + u8 TxDatDstWdth; + u8 TxDatSrcBstSz; + u8 TxDatDstBstSz; + + u8 TxChNo; + u8 LlpCtrl; + u16 RSVD0; + + u32 MaxMultiBlk; + u32 pLlix; + u32 pBlockSizeList; +}SAL_ADC_DMA_USER_DEF, *PSAL_ADC_DMA_USER_DEF; + +// Software API Level ADC Handler +typedef struct _SAL_ADC_HND_ { + u8 DevNum; //ADC device number + u8 PinMux; //ADC pin mux seletion + u8 OpType; //ADC operation type selection + volatile u8 DevSts; //ADC device status + + u32 ADCExd; //ADC extended options: + //bit 0: example + //bit 31~bit 1: Reserved + u32 ErrType; // + u32 TimeOut; //ADC IO Timeout count + + PHAL_ADC_INIT_DAT pInitDat; //Pointer to ADC initial data struct + PSAL_ADC_TRANSFER_BUF pRXBuf; //Pointer to ADC TX buffer + PSAL_ADC_USER_CB pUserCB; //Pointer to ADC User Callback +}SAL_ADC_HND, *PSAL_ADC_HND; + +// ADC SAL handle private +typedef struct _SAL_ADC_HND_PRIV_ { + VOID **ppSalADCHnd; //Pointer to SAL_ADC_HND pointer + SAL_ADC_HND SalADCHndPriv; //Private SAL_ADC_HND +}SAL_ADC_HND_PRIV, *PSAL_ADC_HND_PRIV; + +//ADC SAL management adapter +typedef struct _SAL_ADC_MNGT_ADPT_ { + PSAL_ADC_HND_PRIV pSalHndPriv; //Pointer to SAL_ADC_HND + PHAL_ADC_INIT_DAT pHalInitDat; //Pointer to HAL ADC initial data( HAL_ADC_INIT_DAT ) + PHAL_ADC_OP pHalOp; //Pointer to HAL ADC operation( HAL_ADC_OP ) + VOID (*pHalOpInit)(VOID*);//Pointer to HAL ADC initialize function + + PIRQ_HANDLE pIrqHnd; //Pointer to IRQ handler in SAL layer( IRQ_HANDLE ) + VOID (*pSalIrqFunc)(VOID*); //Used for SAL ADC interrupt function + + PSAL_ADC_DMA_USER_DEF pDMAConf; //Pointer to DAC User Define DMA config + PHAL_GDMA_ADAPTER pHalGdmaAdp; + PHAL_GDMA_OP pHalGdmaOp; + PIRQ_HANDLE pIrqGdmaHnd; + VOID (*pHalGdmaOpInit)(VOID*); //Pointer to HAL DAC initialize function + PSAL_ADC_USER_CB pUserCB; //Pointer to SAL user callbacks (SAL_ADC_USER_CB ) + VOID (*pSalDMAIrqFunc)(VOID*); //Used for SAL DAC interrupt function +}SAL_ADC_MNGT_ADPT, *PSAL_ADC_MNGT_ADPT; + + +//================ ADC HAL Function Prototype =================== +// ADC HAL inline function +// For checking I2C input index valid or not +static inline RTK_STATUS +RtkADCIdxChk( + IN u8 ADCIdx +) +{ +#if !ADC0_USED + if (ADCIdx == ADC0_SEL) + return _EXIT_FAILURE; +#endif + +#if !ADC1_USED + if (ADCIdx == ADC1_SEL) + return _EXIT_FAILURE; +#endif + +#if !ADC2_USED + if (ADCIdx == ADC2_SEL) + return _EXIT_FAILURE; +#endif + +#if !ADC3_USED + if (ADCIdx == ADC3_SEL) + return _EXIT_FAILURE; +#endif + + return _EXIT_SUCCESS; +} + +VOID HalADCOpInit(IN VOID *Data); +PSAL_ADC_HND RtkADCGetSalHnd(IN u8 DACIdx); +RTK_STATUS RtkADCFreeSalHnd(IN PSAL_ADC_HND pSalADCHND); +RTK_STATUS RtkADCLoadDefault(IN VOID *Data); +RTK_STATUS RtkADCInit(IN VOID *Data); +RTK_STATUS RtkADCDeInit(IN VOID *Data); +//RTK_STATUS RtkADCReceive(IN VOID *Data); +u32 RtkADCReceive(IN VOID *Data); +u32 RtkADCReceiveBuf(IN VOID *Data,IN u32 *pBuf); + +PSAL_ADC_MNGT_ADPT RtkADCGetMngtAdpt(IN u8 ADCIdx); +RTK_STATUS RtkADCFreeMngtAdpt(IN PSAL_ADC_MNGT_ADPT pSalADCMngtAdpt); +VOID ADCISRHandle(IN VOID *Data); +VOID ADCGDMAISRHandle(IN VOID *Data); + +#endif diff --git a/component/soc/realtek/8195a/fwlib/hal_api.h b/component/soc/realtek/8195a/fwlib/hal_api.h new file mode 100644 index 0000000..033a6b9 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/hal_api.h @@ -0,0 +1,123 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ +#ifndef _HAL_API_H_ +#define _HAL_API_H_ + +#include "basic_types.h" +#include "hal_irqn.h" + +#define HAL_READ32(base, addr) \ + rtk_le32_to_cpu(*((volatile u32*)(base + addr))) + +#define HAL_WRITE32(base, addr, value32) \ + ((*((volatile u32*)(base + addr))) = rtk_cpu_to_le32(value32)) + + +#define HAL_READ16(base, addr) \ + rtk_le16_to_cpu(*((volatile u16*)(base + addr))) + +#define HAL_WRITE16(base, addr, value) \ + ((*((volatile u16*)(base + addr))) = rtk_cpu_to_le16(value)) + + +#define HAL_READ8(base, addr) \ + (*((volatile u8*)(base + addr))) + +#define HAL_WRITE8(base, addr, value) \ + ((*((volatile u8*)(base + addr))) = value) + +#if 0 +// These "extern _LONG_CALL_" function declaration are for RAM code building only +// For ROM code building, thses code should be marked off +extern _LONG_CALL_ u8 +HalPinCtrlRtl8195A( + IN u32 Function, + IN u32 PinLocation, + IN BOOL Operation + ); + +extern _LONG_CALL_ VOID +HalSerialPutcRtl8195a( + IN u8 c + ); + +extern _LONG_CALL_ u8 +HalSerialGetcRtl8195a( + IN BOOL PullMode + ); + +extern _LONG_CALL_ u32 +HalSerialGetIsrEnRegRtl8195a(VOID); + +extern _LONG_CALL_ VOID +HalSerialSetIrqEnRegRtl8195a ( + IN u32 SetValue + ); + +extern _LONG_CALL_ VOID +VectorTableInitForOSRtl8195A( + IN VOID *PortSVC, + IN VOID *PortPendSVH, + IN VOID *PortSysTick + ); + +extern _LONG_CALL_ BOOL +VectorIrqRegisterRtl8195A( + IN PIRQ_HANDLE pIrqHandle + ); + +extern _LONG_CALL_ BOOL +VectorIrqUnRegisterRtl8195A( + IN PIRQ_HANDLE pIrqHandle + ); + +extern _LONG_CALL_ VOID +VectorIrqEnRtl8195A( + IN PIRQ_HANDLE pIrqHandle + ); + +extern _LONG_CALL_ VOID +VectorIrqDisRtl8195A( + IN PIRQ_HANDLE pIrqHandle + ); +#endif + +#define PinCtrl HalPinCtrlRtl8195A + +#define DiagPutChar HalSerialPutcRtl8195a +#define DiagGetChar HalSerialGetcRtl8195a +#define DiagGetIsrEnReg HalSerialGetIsrEnRegRtl8195a +#define DiagSetIsrEnReg HalSerialSetIrqEnRegRtl8195a + +#define InterruptForOSInit VectorTableInitForOSRtl8195A +#define InterruptRegister VectorIrqRegisterRtl8195A +#define InterruptUnRegister VectorIrqUnRegisterRtl8195A + +#define InterruptEn VectorIrqEnRtl8195A +#define InterruptDis VectorIrqDisRtl8195A + +#define SpicFlashInit SpicFlashInitRtl8195A +#define Calibration32k En32KCalibration +#define WDGInit InitWDGIRQ + +typedef enum _HAL_Status +{ + HAL_OK = 0x00, + HAL_BUSY = 0x01, + HAL_TIMEOUT = 0x02, + HAL_ERR_PARA = 0x03, // error with invaild parameters + HAL_ERR_MEM = 0x04, // error with memory allocation failed + HAL_ERR_HW = 0x05, // error with hardware error + + HAL_ERR_UNKNOWN = 0xee // unknown error + +} HAL_Status; + + +#endif //_HAL_API_H_ diff --git a/component/soc/realtek/8195a/fwlib/hal_common.h b/component/soc/realtek/8195a/fwlib/hal_common.h new file mode 100644 index 0000000..113c1a1 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/hal_common.h @@ -0,0 +1,17 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#ifndef _HAL_COMMON_H_ +#define _HAL_COMMON_H_ + +//================= Function Prototype START =================== +HAL_Status HalCommonInit(void); +//================= Function Prototype END =================== + +#endif diff --git a/component/soc/realtek/8195a/fwlib/hal_crypto.h b/component/soc/realtek/8195a/fwlib/hal_crypto.h new file mode 100644 index 0000000..0224448 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/hal_crypto.h @@ -0,0 +1,213 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + + +#ifndef __HAL_CRYPTO_H__ +#define __HAL_CRYPTO_H__ + + +#include "hal_api.h" +#include "basic_types.h" + + +#define CRYPTO_MAX_MSG_LENGTH 16000 +#define CRYPTO_MD5_DIGEST_LENGTH 16 +#define CRYPTO_SHA1_DIGEST_LENGTH 20 +#define CRYPTO_SHA2_DIGEST_LENGTH 32 + + +typedef enum _SHA2_TYPE_ { + SHA2_NONE = 0, + SHA2_224 = 224/8, + SHA2_256 = 256/8, + SHA2_384 = 384/8, + SHA2_512 = 512/8 +} SHA2_TYPE; + + +#define _ERRNO_CRYPTO_DESC_NUM_SET_OutRange -2 +#define _ERRNO_CRYPTO_BURST_NUM_SET_OutRange -3 +#define _ERRNO_CRYPTO_NULL_POINTER -4 +#define _ERRNO_CRYPTO_ENGINE_NOT_INIT -5 +#define _ERRNO_CRYPTO_ADDR_NOT_4Byte_Aligned -6 +#define _ERRNO_CRYPTO_KEY_OutRange -7 +#define _ERRNO_CRYPTO_MSG_OutRange -8 +#define _ERRNO_CRYPTO_IV_OutRange -9 +#define _ERRNO_CRYPTO_AUTH_TYPE_NOT_MATCH -10 +#define _ERRNO_CRYPTO_CIPHER_TYPE_NOT_MATCH -11 +#define _ERRNO_CRYPTO_KEY_IV_LEN_DIFF -12 + + + +// +// External API Functions +// + + +// Crypto Engine +extern int rtl_cryptoEngine_init(void); +extern void rtl_cryptoEngine_info(void); + + + +// +// Authentication +// + +// md5 + +extern int rtl_crypto_md5(IN const u8* message, IN const u32 msglen, OUT u8* pDigest); + +extern int rtl_crypto_md5_init(void); +extern int rtl_crypto_md5_process(IN const u8* message, const IN u32 msglen, OUT u8* pDigest); + + +// sha1 +extern int rtl_crypto_sha1(IN const u8* message, IN const u32 msglen, OUT u8* pDigest); + +extern int rtl_crypto_sha1_init(void); +extern int rtl_crypto_sha1_process(IN const u8* message, IN const u32 msglen, OUT u8* pDigest); + +// sha2 + +extern int rtl_crypto_sha2(IN const SHA2_TYPE sha2type, + IN const u8* message, IN const u32 msglen, OUT u8* pDigest); + +extern int rtl_crypto_sha2_init(IN const SHA2_TYPE sha2type); +extern int rtl_crypto_sha2_process(IN const u8* message, IN const u32 msglen, OUT u8* pDigest); + + +// HMAC-md5 +extern int rtl_crypto_hmac_md5(IN const u8* message, IN const u32 msglen, + IN const u8* key, IN const u32 keylen, OUT u8* pDigest); + +extern int rtl_crypto_hmac_md5_init(IN const u8* key, IN const u32 keylen); +extern int rtl_crypto_hmac_md5_process(IN const u8* message, IN const u32 msglen, OUT u8* pDigest); + + +// HMAC-sha1 +extern int rtl_crypto_hmac_sha1(IN const u8* message, IN const u32 msglen, + IN const u8* key, IN const u32 keylen, OUT u8* pDigest); + +extern int rtl_crypto_hmac_sha1_init(IN const u8* key, IN const u32 keylen); +extern int rtl_crypto_hmac_sha1_process(IN const u8* message, IN const u32 msglen, OUT u8* pDigest); + + +// HMAC-sha2 +extern int rtl_crypto_hmac_sha2(IN const SHA2_TYPE sha2type, IN const u8* message, IN const u32 msglen, + IN const u8* key, IN const u32 keylen, OUT u8* pDigest); + +extern int rtl_crypto_hmac_sha2_init(IN const SHA2_TYPE sha2type, IN const u8* key, IN const u32 keylen); +extern int rtl_crypto_hmac_sha2_process(IN const u8* message, IN const u32 msglen, OUT u8* pDigest); + + +// +// Cipher Functions +// + +// AES - CBC + +extern int rtl_crypto_aes_cbc_init(IN const u8* key, IN const u32 keylen); + +extern int rtl_crypto_aes_cbc_encrypt( + IN const u8* message, IN const u32 msglen, + IN const u8* iv, IN const u32 ivlen, OUT u8* pResult); + +extern int rtl_crypto_aes_cbc_decrypt( + IN const u8* message, IN const u32 msglen, + IN const u8* iv, IN const u32 ivlen, OUT u8* pResult); + + +// AES - ECB + +extern int rtl_crypto_aes_ecb_init(IN const u8* key, IN const u32 keylen); + +extern int rtl_crypto_aes_ecb_encrypt( + IN const u8* message, IN const u32 msglen, + IN const u8* iv, IN const u32 ivlen, OUT u8* pResult); + +extern int rtl_crypto_aes_ecb_decrypt( + IN const u8* message, IN const u32 msglen, + IN const u8* iv, IN const u32 ivlen, OUT u8* pResult); + + +// AES - CTR + +extern int rtl_crypto_aes_ctr_init(IN const u8* key, IN const u32 keylen); + +extern int rtl_crypto_aes_ctr_encrypt( + IN const u8* message, IN const u32 msglen, + IN const u8* iv, IN const u32 ivlen, OUT u8* pResult); + +extern int rtl_crypto_aes_ctr_decrypt( + IN const u8* message, IN const u32 msglen, + IN const u8* iv, IN const u32 ivlen, OUT u8* pResult); + + +// 3DES - CBC + +extern int rtl_crypto_3des_cbc_init(IN const u8* key, IN const u32 keylen); + +extern int rtl_crypto_3des_cbc_encrypt( + IN const u8* message, IN const u32 msglen, + IN const u8* iv, IN const u32 ivlen, OUT u8* pResult); + +extern int rtl_crypto_3des_cbc_decrypt( + IN const u8* message, IN const u32 msglen, + IN const u8* iv, IN const u32 ivlen, OUT u8* pResult); + + +// 3DES - ECB + +extern int rtl_crypto_3des_ecb_init(IN const u8* key, IN const u32 keylen); + +extern int rtl_crypto_3des_ecb_encrypt( + IN const u8* message, IN const u32 msglen, + IN const u8* iv, IN const u32 ivlen, OUT u8* pResult); + +extern int rtl_crypto_3des_ecb_decrypt( + IN const u8* message, IN const u32 msglen, + IN const u8* iv, IN const u32 ivlen, OUT u8* pResult); + + +// DES - CBC + +extern int rtl_crypto_des_cbc_init(IN const u8* key, IN const u32 keylen); + +extern int rtl_crypto_des_cbc_encrypt( + IN const u8* message, IN const u32 msglen, + IN const u8* iv, IN const u32 ivlen, OUT u8* pResult); + +extern int rtl_crypto_des_cbc_decrypt( + IN const u8* message, IN const u32 msglen, + IN const u8* iv, IN const u32 ivlen, OUT u8* pResult); + + +// DES - ECB + +extern int rtl_crypto_des_ecb_init(IN const u8* key, IN const u32 keylen); + +extern int rtl_crypto_des_ecb_encrypt( + IN const u8* message, IN const u32 msglen, + IN const u8* iv, IN const u32 ivlen, OUT u8* pResult); + +extern int rtl_crypto_des_ecb_decrypt( + IN const u8* message, IN const u32 msglen, + IN const u8* iv, IN const u32 ivlen, OUT u8* pResult); + + +// +// C functions in ROM +// + +extern int rtl_memcmpb(const u8 *dst, const u8 *src, int bytes); +extern int rtl_memcpyb(u8 *dst, const u8 *src, int bytes); + +#endif /* __HAL_CRYPTO_H__ */ + diff --git a/component/soc/realtek/8195a/fwlib/hal_dac.h b/component/soc/realtek/8195a/fwlib/hal_dac.h new file mode 100644 index 0000000..f8b3c8f --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/hal_dac.h @@ -0,0 +1,313 @@ +//====================================================== +// Routines to access hardware +// +// Copyright (c) 2013 Realtek Semiconductor Corp. +// +// This module is a confidential and proprietary property of RealTek and +// possession or use of this module requires written permission of RealTek. +//====================================================== +#ifndef _HAL_DAC_H_ +#define _HAL_DAC_H_ + +#include "rtl8195a.h" +#include "rtl8195a_dac.h" +#include "hal_api.h" +#include "hal_gdma.h" + +//================ DAC Configuration ========================= +#define DAC_INTR_OP_TYPE 1 +#define DAC_DMA_OP_TYPE 1 + +// DAC SAL management macros +#define SAL_DAC_USER_CB_NUM (sizeof(SAL_DAC_USER_CB) / sizeof(PSAL_DAC_USERCB_ADPT)) + +// DAC SAL used module. +// Please set the DAC module flag to 1 to enable the related DAC module functions. +#define DAC0_USED 1 +#define DAC1_USED 1 + + +//================ Debug MSG Definition ======================= +#define DAC_PREFIX "RTL8195A[dac]: " +#define DAC_PREFIX_LVL " [DAC_DBG]: " + +typedef enum _DAC_DBG_LVL_ { + HAL_DAC_LVL = 0x00, + SAL_DAC_LVL = 0x02, + VERI_DAC_LVL = 0x04, +}DAC_DBG_LVL,*PDAC_DBG_LVL; + +#ifdef CONFIG_DEBUG_LOG +#ifdef CONFIG_DEBUG_LOG_DAC_HAL + + #define DBG_8195A_DAC(...) do{ \ + _DbgDump("\r"DAC_PREFIX __VA_ARGS__);\ + }while(0) + + + #define DACDBGLVL 0xFF + #define DBG_8195A_DAC_LVL(LVL,...) do{\ + if (LVL&DACDBGLVL){\ + _DbgDump("\r"DAC_PREFIX_LVL __VA_ARGS__);\ + }\ + }while(0) +#else + #define DBG_DAC_LOG_PERD 100 + #define DBG_8195A_DAC(...) + #define DBG_8195A_DAC_LVL(...) +#endif +#endif + + +//================ DAC HAL Related Enumeration ================== +// DAC Module Selection +typedef enum _DAC_MODULE_SEL_ { + DAC0_SEL = 0x0, + DAC1_SEL = 0x1, +}DAC_MODULE_SEL,*PDAC_MODULE_SEL; + +// DAC module status +typedef enum _DAC_MODULE_STATUS_ { + DAC_DISABLE = 0x0, + DAC_ENABLE = 0x1, +}DAC_MODULE_STATUS, *PDAC_MODULE_STATUS; + +// DAC Data Rate +typedef enum _DAC_DATA_RATE_ { + DAC_DATA_RATE_10K = 0x0, + DAC_DATA_RATE_250K = 0x1, +}DAC_DATA_RATE,*PDAC_DATA_RATE; + +// DAC Data Endian +typedef enum _DAC_DATA_ENDIAN_ { + DAC_DATA_ENDIAN_LITTLE = 0x0, + DAC_DATA_ENDIAN_BIG = 0x1, +}DAC_DATA_ENDIAN,*PDAC_DATA_ENDIAN; + +// DAC Debug Select +typedef enum _DAC_DEBUG_SEL_ { + DAC_DBG_SEL_DISABLE = 0x0, + DAC_DBG_SEL_ENABLE = 0x1, +}DAC_DEBUG_SEL,*PDAC_DEBUG_SEL; + +// DAC Dsc Debug Select +typedef enum _DAC_DSC_DEBUG_SEL_ { + DAC_DSC_DBG_SEL_DISABLE = 0x0, + DAC_DSC_DBG_SEL_ENABLE = 0x1, +}DAC_DSC_DEBUG_SEL,*PDAC_DSC_DEBUG_SEL; + + +// DAC Bypass Dsc Debug Select +typedef enum _DAC_BYPASS_DSC_SEL_ { + DAC_BYPASS_DSC_SEL_DISABLE = 0x0, + DAC_BYPASS_DSC_SEL_ENABLE = 0x1, +}DAC_BYPASS_DSC_SEL,*PDAC_BYPASS_DSC_SEL; + +// DAC feature status +typedef enum _DAC_FEATURE_STATUS_{ + DAC_FEATURE_DISABLED = 0, + DAC_FEATURE_ENABLED = 1, +}DAC_FEATURE_STATUS,*PDAC_FEATURE_STATUS; + +// DAC operation type +typedef enum _DAC_OP_TYPE_ { + DAC_POLL_TYPE = 0x0, + DAC_DMA_TYPE = 0x1, + DAC_INTR_TYPE = 0x2, +}DAC_OP_TYPE, *PDAC_OP_TYPE; + +// DAC device status +typedef enum _DAC_Device_STATUS_ { + DAC_STS_UNINITIAL = 0x00, + DAC_STS_INITIALIZED = 0x01, + DAC_STS_IDLE = 0x02, + + DAC_STS_TX_READY = 0x03, + DAC_STS_TX_ING = 0x04, + + DAC_STS_RX_READY = 0x05, + DAC_STS_RX_ING = 0x06, + + DAC_STS_ERROR = 0x07, +}DAC_Device_STATUS, *PDAC_Device_STATUS; + +//DAC device error type +typedef enum _DAC_ERR_TYPE_ { + DAC_ERR_FIFO_OVER = 0x04, //DAC FIFO overflow. + DAC_ERR_FIFO_STOP = 0x08, //DAC FIFO is completely empty, and it will be stopped automatically. + DAC_ERR_FIFO_WRFAIL = 0x10, //When DAC is NOT enabled, a write operation attempts to access DAC register. + DAC_ERR_FIFO_DSC_OVER0 = 0x20, + DAC_ERR_FIFO_DSC_OVER1 = 0x40, +}DAC_ERR_TYPE, *PDAC_ERR_TYPE; + +// DAC data input method +typedef enum _DAC_INPUT_TYPE_{ + DAC_INPUT_SINGLE_WR = 0x1, //DAC input by using single register write + DAC_INPUT_DMA_ONEBLK = 0x2, //DAC input by using single DMA block + DAC_INPUT_DMA_LLP = 0x3, //DAC input by using DMA linked list mode +}DAC_INPUT_TYPE,*PDAC_INPUT_TYPE; + + + + +//====================================================== +// DAC HAL initial data structure +typedef struct _HAL_DAC_INIT_DAT_ { + u8 DACIdx; //DAC index used + u8 DACEn; //DAC module enable + u8 DACDataRate; //DAC data rate, 1'b0:10KHz, 1'b1:250KHz + u8 DACEndian; //DAC endian selection, + //but actually it's for 32-bit DAC data swap control + //1'b0: no swap, + //1'b1: swap the upper 16-bit and the lower 16-bit + u8 DACFilterSet; //DAC filter settle + u8 DACBurstSz; //DAC burst size + u8 DACDbgSel; //DAC debug sel + u8 DACDscDbgSel; //DAC debug dsc sel + + u8 DACBPDsc; //DAC bypass delta sigma for loopback + u8 DACDeltaSig; //DAC bypass value of delta sigma + u16 RSVD1; + + + + u32 *DACData; //DAC data pointer + u32 DACPWCtrl; //DAC0 and DAC1 power control + u32 DACAnaCtrl0; //DAC anapar_da control 0 + u32 DACAnaCtrl1; //DAC anapar_da control 1 + u32 DACIntrMSK; //DAC Interrupt Mask +}HAL_DAC_INIT_DAT,*PHAL_DAC_INIT_DAT; + +// DAC HAL Operations +typedef struct _HAL_DAC_OP_ { + RTK_STATUS (*HalDACInit) (VOID *Data); //HAL DAC initialization + RTK_STATUS (*HalDACDeInit) (VOID *Data); //HAL DAC de-initialization + RTK_STATUS (*HalDACEnable) (VOID *Data); //HAL DAC de-initialization + u8 (*HalDACSend) (VOID *Data); //HAL DAC receive + RTK_STATUS (*HalDACIntrCtrl) (VOID *Data); //HAL DAC interrupt control + u32 (*HalDACReadReg) (VOID *Data, u8 DACReg);//HAL DAC read register +}HAL_DAC_OP, *PHAL_DAC_OP; + +// DAC user callback adapter +typedef struct _SAL_DAC_USERCB_ADPT_ { + VOID (*USERCB) (VOID *Data); + u32 USERData; +}SAL_DAC_USERCB_ADPT, *PSAL_DAC_USERCB_ADPT; + +// DAC user callback structure +typedef struct _SAL_DAC_USER_CB_ { + PSAL_DAC_USERCB_ADPT pTXCB; //DAC Transmit Callback + PSAL_DAC_USERCB_ADPT pTXCCB; //DAC Transmit Complete Callback + PSAL_DAC_USERCB_ADPT pRXCB; //DAC Receive Callback + PSAL_DAC_USERCB_ADPT pRXCCB; //DAC Receive Complete Callback + PSAL_DAC_USERCB_ADPT pRDREQCB; //DAC Read Request Callback + PSAL_DAC_USERCB_ADPT pERRCB; //DAC Error Callback + PSAL_DAC_USERCB_ADPT pDMATXCB; //DAC DMA Transmit Callback + PSAL_DAC_USERCB_ADPT pDMATXCCB; //DAC DMA Transmit Complete Callback + PSAL_DAC_USERCB_ADPT pDMARXCB; //DAC DMA Receive Callback + PSAL_DAC_USERCB_ADPT pDMARXCCB; //DAC DMA Receive Complete Callback +}SAL_DAC_USER_CB, *PSAL_DAC_USER_CB; + +// DAC Transmit Buffer +typedef struct _SAL_DAC_TRANSFER_BUF_ { + u32 DataLen; //DAC Transmfer Length + u32 *pDataBuf; //DAC Transfer Buffer Pointer + u32 RSVD; // +}SAL_DAC_TRANSFER_BUF,*PSAL_DAC_TRANSFER_BUF; + +typedef struct _SAL_DAC_DMA_USER_DEF_ { + + u8 TxDatSrcWdth; + u8 TxDatDstWdth; + u8 TxDatSrcBstSz; + u8 TxDatDstBstSz; + + u8 TxChNo; + u8 LlpCtrl; + u16 RSVD0; + + u32 MaxMultiBlk; + u32 pLlix; + u32 pBlockSizeList; +}SAL_DAC_DMA_USER_DEF, *PSAL_DAC_DMA_USER_DEF; + +// Software API Level DAC Handler +typedef struct _SAL_DAC_HND_ { + u8 DevNum; //DAC device number + u8 PinMux; //DAC pin mux seletion + u8 OpType; //DAC operation type selection + volatile u8 DevSts; //DAC device status + + u8 DACInType; //DAC input type + u8 RSVD0; + u16 RSVD1; + + u32 DACExd; //DAC extended options: + //bit 0: example + //bit 31~bit 1: Reserved + u32 ErrType; // + u32 TimeOut; //DAC IO Timeout count + + PHAL_DAC_INIT_DAT pInitDat; //Pointer to DAC initial data struct + PSAL_DAC_TRANSFER_BUF pTXBuf; //Pointer to DAC TX buffer + PSAL_DAC_USER_CB pUserCB; //Pointer to DAC User Callback + PSAL_DAC_DMA_USER_DEF pDMAConf; //Pointer to DAC User Define DMA Config +}SAL_DAC_HND, *PSAL_DAC_HND; + +// DAC SAL handle private +typedef struct _SAL_DAC_HND_PRIV_ { + VOID **ppSalDACHnd; //Pointer to SAL_DAC_HND pointer + SAL_DAC_HND SalDACHndPriv; //Private SAL_DAC_HND +}SAL_DAC_HND_PRIV, *PSAL_DAC_HND_PRIV; + +//DAC SAL management adapter +typedef struct _SAL_DAC_MNGT_ADPT_ { + PSAL_DAC_HND_PRIV pSalHndPriv; //Pointer to SAL_DAC_HND + PHAL_DAC_INIT_DAT pHalInitDat; //Pointer to HAL DAC initial data( HAL_I2C_INIT_DAT ) + PHAL_DAC_OP pHalOp; //Pointer to HAL DAC operation( HAL_DAC_OP ) + VOID (*pHalOpInit)(VOID*); //Pointer to HAL DAC initialize function + PIRQ_HANDLE pIrqHnd; //Pointer to IRQ handler in SAL layer( IRQ_HANDLE ) + PSAL_DAC_USER_CB pUserCB; //Pointer to SAL user callbacks (SAL_DAC_USER_CB ) + VOID (*pSalIrqFunc)(VOID*); //Used for SAL DAC interrupt function + + PSAL_DAC_DMA_USER_DEF pDMAConf; //Pointer to DAC User Define DMA config + PHAL_GDMA_ADAPTER pHalGdmaAdp; + PHAL_GDMA_OP pHalGdmaOp; + VOID (*pHalGdmaOpInit)(VOID*); //Pointer to HAL DAC initialize function + PIRQ_HANDLE pIrqGdmaHnd; + VOID (*pSalDMAIrqFunc)(VOID*); //Used for SAL DAC interrupt function +}SAL_DAC_MNGT_ADPT, *PSAL_DAC_MNGT_ADPT; + + +//================ DAC HAL Function Prototype =================== +// DAC HAL inline function +// For checking DAC input index valid or not +static inline RTK_STATUS +RtkDACIdxChk( + IN u8 DACIdx +) +{ +#if !DAC0_USED + if (DACIdx == DAC0_SEL) + return _EXIT_FAILURE; +#endif + +#if !DAC1_USED + if (DACIdx == DAC1_SEL) + return _EXIT_FAILURE; +#endif + + return _EXIT_SUCCESS; +} + +VOID HalDACOpInit(IN VOID *Data); +RTK_STATUS RtkDACLoadDefault(IN VOID *Data); +RTK_STATUS RtkDACInit(IN VOID *Data); +RTK_STATUS RtkDACDeInit(IN VOID *Data); +RTK_STATUS RtkDACSend(IN VOID *Data); +PSAL_DAC_HND RtkDACGetSalHnd(IN u8 DACIdx); +RTK_STATUS RtkDACFreeSalHnd(IN PSAL_DAC_HND pSalDACHND); +PSAL_DAC_MNGT_ADPT RtkDACGetMngtAdpt(IN u8 DACIdx); +RTK_STATUS RtkDACFreeMngtAdpt(IN PSAL_DAC_MNGT_ADPT pSalDACMngtAdpt); + +#endif diff --git a/component/soc/realtek/8195a/fwlib/hal_diag.h b/component/soc/realtek/8195a/fwlib/hal_diag.h new file mode 100644 index 0000000..61ad49e --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/hal_diag.h @@ -0,0 +1,107 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#ifndef _HAL_DIAG_H_ +#define _HAL_DIAG_H_ + + +//Register offset +#define UART_REV_BUF_OFF 0x00 +#define UART_TRAN_HOLD_OFF 0x00 +#define UART_DLH_OFF 0x04 +#define UART_DLL_OFF 0x00 +#define UART_INTERRUPT_EN_REG_OFF 0x04 +#define UART_INTERRUPT_IDEN_REG_OFF 0x08 +#define UART_FIFO_CTL_REG_OFF 0x08 +#define UART_LINE_CTL_REG_OFF 0x0c +#define UART_MODEM_CTL_REG_OFF 0x10 +#define UART_LINE_STATUS_REG_OFF 0x14 +#define UART_MODEM_STATUS_REG_OFF 0x18 +#define UART_FIFO_ACCESS_REG_OFF 0x70 +#define UART_STATUS_REG_OFF 0x7c +#define UART_TFL_OFF 0x80 +#define UART_RFL_OFF 0x84 + + +//Buad rate +#define UART_BAUD_RATE_2400 2400 +#define UART_BAUD_RATE_4800 4800 +#define UART_BAUD_RATE_9600 9600 +#define UART_BAUD_RATE_19200 19200 +#define UART_BAUD_RATE_38400 38400 +#define UART_BAUD_RATE_57600 57600 +#define UART_BAUD_RATE_115200 115200 +#define UART_BAUD_RATE_921600 921600 +#define UART_BAUD_RATE_1152000 1152000 + +#define UART_PARITY_ENABLE 0x08 +#define UART_PARITY_DISABLE 0 + +#define UART_DATA_LEN_5BIT 0x0 +#define UART_DATA_LEN_6BIT 0x1 +#define UART_DATA_LEN_7BIT 0x2 +#define UART_DATA_LEN_8BIT 0x3 + +#define UART_STOP_1BIT 0x0 +#define UART_STOP_2BIT 0x4 + + +#define HAL_UART_READ32(addr) HAL_READ32(LOG_UART_REG_BASE, addr) +#define HAL_UART_WRITE32(addr, value) HAL_WRITE32(LOG_UART_REG_BASE, addr, value) +#define HAL_UART_READ16(addr) HAL_READ16(LOG_UART_REG_BASE, addr) +#define HAL_UART_WRITE16(addr, value) HAL_WRITE16(LOG_UART_REG_BASE, addr, value) +#define HAL_UART_READ8(addr) HAL_READ8(LOG_UART_REG_BASE, addr) +#define HAL_UART_WRITE8(addr, value) HAL_WRITE8(LOG_UART_REG_BASE, addr, value) + +typedef struct _LOG_UART_ADAPTER_ { + u32 BaudRate; + u32 FIFOControl; + u32 IntEnReg; + u8 Parity; + u8 Stop; + u8 DataLength; +}LOG_UART_ADAPTER, *PLOG_UART_ADAPTER; + +typedef struct _COMMAND_TABLE_ { + const u8* cmd; + u16 ArgvCnt; + u32 (*func)(u16 argc, u8* argv[]); + const u8* msg; +}COMMAND_TABLE, *PCOMMAND_TABLE; + +//VOID +//HalLogUartHandle(void); + + +extern _LONG_CALL_ u32 +HalLogUartInit( + IN LOG_UART_ADAPTER UartAdapter + ); + + +extern _LONG_CALL_ VOID +HalSerialPutcRtl8195a( + IN u8 c + ); + +extern _LONG_CALL_ u8 +HalSerialGetcRtl8195a( + IN BOOL PullMode + ); + +extern _LONG_CALL_ u32 +HalSerialGetIsrEnRegRtl8195a(VOID); + +extern _LONG_CALL_ VOID +HalSerialSetIrqEnRegRtl8195a ( + IN u32 SetValue +); + + +#endif//_HAL_DIAG_H_ diff --git a/component/soc/realtek/8195a/fwlib/hal_efuse.h b/component/soc/realtek/8195a/fwlib/hal_efuse.h new file mode 100644 index 0000000..047fada --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/hal_efuse.h @@ -0,0 +1,28 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#ifndef _HAL_EFUSE_H_ +#define _HAL_EFUSE_H_ + +_LONG_CALL_ extern VOID HalEFUSEPowerSwitch8195AROM(IN u8 bWrite, IN u8 PwrState, IN u8 L25OutVoltage); +_LONG_CALL_ extern u32 HALEFUSEOneByteReadROM(IN u32 CtrlSetting, IN u16 Addr, OUT u8 *Data, IN u8 L25OutVoltage); +_LONG_CALL_ extern u32 HALEFUSEOneByteWriteROM(IN u32 CtrlSetting, IN u16 Addr, IN u8 Data, IN u8 L25OutVoltage); + +#define EFUSERead8 HALEFUSEOneByteReadROM +#define EFUSEWrite8 HALEFUSEOneByteWriteROM + +#define L25EOUTVOLTAGE 7 + +VOID HalEFUSEOpInit( + IN VOID *Data +); + + +#endif + diff --git a/component/soc/realtek/8195a/fwlib/hal_gdma.h b/component/soc/realtek/8195a/fwlib/hal_gdma.h new file mode 100644 index 0000000..70d254a --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/hal_gdma.h @@ -0,0 +1,127 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#ifndef _HAL_GDMA_H_ +#define _HAL_GDMA_H_ + +#include "rtl8195a_gdma.h" + +typedef struct _GDMA_CH_LLI_ELE_ { + u32 Sarx; + u32 Darx; + u32 Llpx; + u32 CtlxLow; + u32 CtlxUp; + u32 Temp; +}GDMA_CH_LLI_ELE, *PGDMA_CH_LLI_ELE; +#if 1 +#if 0 +typedef struct _GDMA_CH_LLI_ { + PGDMA_CH_LLI_ELE pLliEle; + PGDMA_CH_LLI pNextLli; +}GDMA_CH_LLI, *PGDMA_CH_LLI; + +typedef struct _BLOCK_SIZE_LIST_ { + u32 BlockSize; + PBLOCK_SIZE_LIST pNextBlockSiz; +}BLOCK_SIZE_LIST, *PBLOCK_SIZE_LIST; +#else +struct GDMA_CH_LLI { + PGDMA_CH_LLI_ELE pLliEle; + struct GDMA_CH_LLI *pNextLli; +}; + +struct BLOCK_SIZE_LIST { + u32 BlockSize; + struct BLOCK_SIZE_LIST *pNextBlockSiz; +}; + +#endif + +#endif +typedef struct _HAL_GDMA_ADAPTER_ { + u32 ChSar; + u32 ChDar; + GDMA_CHANNEL_NUM ChEn; + GDMA_CTL_REG GdmaCtl; + GDMA_CFG_REG GdmaCfg; + u32 PacketLen; + u32 BlockLen; + u32 MuliBlockCunt; + u32 MaxMuliBlock; + struct GDMA_CH_LLI *pLlix; + struct BLOCK_SIZE_LIST *pBlockSizeList; + + PGDMA_CH_LLI_ELE pLli; + u32 NextPlli; + u8 TestItem; + u8 ChNum; + u8 GdmaIndex; + u8 IsrCtrl:1; + u8 GdmaOnOff:1; + u8 Llpctrl:1; + u8 Lli0:1; + u8 Rsvd4to7:4; + u8 GdmaIsrType; +}HAL_GDMA_ADAPTER, *PHAL_GDMA_ADAPTER; + +typedef struct _HAL_GDMA_CHNL_ { + u8 GdmaIndx; + u8 GdmaChnl; + u8 IrqNum; + u8 Reserved; +}HAL_GDMA_CHNL, *PHAL_GDMA_CHNL; + + +typedef struct _HAL_GDMA_OP_ { + VOID (*HalGdmaOnOff)(VOID *Data); + BOOL (*HalGdamChInit)(VOID *Data); + BOOL (*HalGdmaChSeting)(VOID *Data); + BOOL (*HalGdmaChBlockSeting)(VOID *Data); + VOID (*HalGdmaChDis)(VOID *Data); + VOID (*HalGdmaChEn)(VOID *Data); + VOID (*HalGdmaChIsrEnAndDis) (VOID *Data); + u8 (*HalGdmaChIsrClean)(VOID *Data); + VOID (*HalGdmaChCleanAutoSrc)(VOID *Data); + VOID (*HalGdmaChCleanAutoDst)(VOID *Data); +}HAL_GDMA_OP, *PHAL_GDMA_OP; + +typedef struct _HAL_GDMA_OBJ_ { + HAL_GDMA_ADAPTER HalGdmaAdapter; + IRQ_HANDLE GdmaIrqHandle; + u8 Busy; // is transfering +} HAL_GDMA_OBJ, *PHAL_GDMA_OBJ; + +VOID HalGdmaOpInit(IN VOID *Data); +VOID HalGdmaOn(PHAL_GDMA_ADAPTER pHalGdmaAdapter); +VOID HalGdmaOff(PHAL_GDMA_ADAPTER pHalGdmaAdapter); +BOOL HalGdmaChInit(PHAL_GDMA_ADAPTER pHalGdmaAdapter); +VOID HalGdmaChDis(PHAL_GDMA_ADAPTER pHalGdmaAdapter); +VOID HalGdmaChEn(PHAL_GDMA_ADAPTER pHalGdmaAdapter); +BOOL HalGdmaChSeting(PHAL_GDMA_ADAPTER pHalGdmaAdapter); +BOOL HalGdmaChBlockSeting(PHAL_GDMA_ADAPTER pHalGdmaAdapter); +VOID HalGdmaChIsrEn(PHAL_GDMA_ADAPTER pHalGdmaAdapter); +VOID HalGdmaChIsrDis(PHAL_GDMA_ADAPTER pHalGdmaAdapter); +u8 HalGdmaChIsrClean(PHAL_GDMA_ADAPTER pHalGdmaAdapter); +VOID HalGdmaChCleanAutoSrc(PHAL_GDMA_ADAPTER pHalGdmaAdapter); +VOID HalGdmaChCleanAutoDst(PHAL_GDMA_ADAPTER pHalGdmaAdapter); + +extern HAL_Status HalGdmaChnlRegister (u8 GdmaIdx, u8 ChnlNum); +extern VOID HalGdmaChnlUnRegister (u8 GdmaIdx, u8 ChnlNum); +extern PHAL_GDMA_CHNL HalGdmaChnlAlloc (HAL_GDMA_CHNL *pChnlOption); +extern VOID HalGdmaChnlFree (HAL_GDMA_CHNL *pChnl); +extern BOOL HalGdmaMemCpyInit(PHAL_GDMA_OBJ pHalGdmaObj); +extern VOID HalGdmaMemCpyDeInit(PHAL_GDMA_OBJ pHalGdmaObj); +extern VOID* HalGdmaMemCpy(PHAL_GDMA_OBJ pHalGdmaObj, void* pDest, void* pSrc, u32 len); + +extern const HAL_GDMA_OP _HalGdmaOp; +extern const HAL_GDMA_CHNL GDMA_Chnl_Option[]; +extern const u16 HalGdmaChnlEn[6]; + +#endif diff --git a/component/soc/realtek/8195a/fwlib/hal_gpio.h b/component/soc/realtek/8195a/fwlib/hal_gpio.h new file mode 100644 index 0000000..3046336 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/hal_gpio.h @@ -0,0 +1,236 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#ifndef _HAL_GPIO_H_ +#define _HAL_GPIO_H_ + +#define HAL_GPIO_PIN_INT_MODE 0x80 + +typedef enum { + _PORT_A = 0, + _PORT_B = 1, + _PORT_C = 2, + _PORT_D = 3, + _PORT_E = 4, + _PORT_F = 5, + _PORT_G = 6, + _PORT_H = 7, + _PORT_I = 8, + _PORT_J = 9, + _PORT_K = 10, + + _PORT_MAX +} HAL_GPIO_PORT_NAME; + +typedef enum { + _PA_0 = (_PORT_A<<4|0), + _PA_1 = (_PORT_A<<4|1), + _PA_2 = (_PORT_A<<4|2), + _PA_3 = (_PORT_A<<4|3), + _PA_4 = (_PORT_A<<4|4), + _PA_5 = (_PORT_A<<4|5), + _PA_6 = (_PORT_A<<4|6), + _PA_7 = (_PORT_A<<4|7), + + _PB_0 = (_PORT_B<<4|0), + _PB_1 = (_PORT_B<<4|1), + _PB_2 = (_PORT_B<<4|2), + _PB_3 = (_PORT_B<<4|3), + _PB_4 = (_PORT_B<<4|4), + _PB_5 = (_PORT_B<<4|5), + _PB_6 = (_PORT_B<<4|6), + _PB_7 = (_PORT_B<<4|7), + + _PC_0 = (_PORT_C<<4|0), + _PC_1 = (_PORT_C<<4|1), + _PC_2 = (_PORT_C<<4|2), + _PC_3 = (_PORT_C<<4|3), + _PC_4 = (_PORT_C<<4|4), + _PC_5 = (_PORT_C<<4|5), + _PC_6 = (_PORT_C<<4|6), + _PC_7 = (_PORT_C<<4|7), + _PC_8 = (_PORT_C<<4|8), + _PC_9 = (_PORT_C<<4|9), + + _PD_0 = (_PORT_D<<4|0), + _PD_1 = (_PORT_D<<4|1), + _PD_2 = (_PORT_D<<4|2), + _PD_3 = (_PORT_D<<4|3), + _PD_4 = (_PORT_D<<4|4), + _PD_5 = (_PORT_D<<4|5), + _PD_6 = (_PORT_D<<4|6), + _PD_7 = (_PORT_D<<4|7), + _PD_8 = (_PORT_D<<4|8), + _PD_9 = (_PORT_D<<4|9), + + _PE_0 = (_PORT_E<<4|0), + _PE_1 = (_PORT_E<<4|1), + _PE_2 = (_PORT_E<<4|2), + _PE_3 = (_PORT_E<<4|3), + _PE_4 = (_PORT_E<<4|4), + _PE_5 = (_PORT_E<<4|5), + _PE_6 = (_PORT_E<<4|6), + _PE_7 = (_PORT_E<<4|7), + _PE_8 = (_PORT_E<<4|8), + _PE_9 = (_PORT_E<<4|9), + _PE_A = (_PORT_E<<4|10), + + _PF_0 = (_PORT_F<<4|0), + _PF_1 = (_PORT_F<<4|1), + _PF_2 = (_PORT_F<<4|2), + _PF_3 = (_PORT_F<<4|3), + _PF_4 = (_PORT_F<<4|4), + _PF_5 = (_PORT_F<<4|5), +// _PF_6 = (_PORT_F<<4|6), +// _PF_7 = (_PORT_F<<4|7), + + _PG_0 = (_PORT_G<<4|0), + _PG_1 = (_PORT_G<<4|1), + _PG_2 = (_PORT_G<<4|2), + _PG_3 = (_PORT_G<<4|3), + _PG_4 = (_PORT_G<<4|4), + _PG_5 = (_PORT_G<<4|5), + _PG_6 = (_PORT_G<<4|6), + _PG_7 = (_PORT_G<<4|7), + + _PH_0 = (_PORT_H<<4|0), + _PH_1 = (_PORT_H<<4|1), + _PH_2 = (_PORT_H<<4|2), + _PH_3 = (_PORT_H<<4|3), + _PH_4 = (_PORT_H<<4|4), + _PH_5 = (_PORT_H<<4|5), + _PH_6 = (_PORT_H<<4|6), + _PH_7 = (_PORT_H<<4|7), + + _PI_0 = (_PORT_I<<4|0), + _PI_1 = (_PORT_I<<4|1), + _PI_2 = (_PORT_I<<4|2), + _PI_3 = (_PORT_I<<4|3), + _PI_4 = (_PORT_I<<4|4), + _PI_5 = (_PORT_I<<4|5), + _PI_6 = (_PORT_I<<4|6), + _PI_7 = (_PORT_I<<4|7), + + _PJ_0 = (_PORT_J<<4|0), + _PJ_1 = (_PORT_J<<4|1), + _PJ_2 = (_PORT_J<<4|2), + _PJ_3 = (_PORT_J<<4|3), + _PJ_4 = (_PORT_J<<4|4), + _PJ_5 = (_PORT_J<<4|5), + _PJ_6 = (_PORT_J<<4|6), +// _PJ_7 = (_PORT_J<<4|7), + + _PK_0 = (_PORT_K<<4|0), + _PK_1 = (_PORT_K<<4|1), + _PK_2 = (_PORT_K<<4|2), + _PK_3 = (_PORT_K<<4|3), + _PK_4 = (_PORT_K<<4|4), + _PK_5 = (_PORT_K<<4|5), + _PK_6 = (_PORT_K<<4|6), +// _PK_7 = (_PORT_K<<4|7), + + // Not connected + _PIN_NC = (int)0xFFFFFFFF +} HAL_PIN_NAME; + +typedef enum +{ + GPIO_PIN_LOW = 0, + GPIO_PIN_HIGH = 1, + GPIO_PIN_ERR = 2 // read Pin error +} HAL_GPIO_PIN_STATE; + +typedef enum { + DIN_PULL_NONE = 0, //floating or high impedance ? + DIN_PULL_LOW = 1, + DIN_PULL_HIGH = 2, + + DOUT_PUSH_PULL = 3, + DOUT_OPEN_DRAIN = 4, + + INT_LOW = (5|HAL_GPIO_PIN_INT_MODE), // Interrupt Low level trigger + INT_HIGH = (6|HAL_GPIO_PIN_INT_MODE), // Interrupt High level trigger + INT_FALLING = (7|HAL_GPIO_PIN_INT_MODE), // Interrupt Falling edge trigger + INT_RISING = (8|HAL_GPIO_PIN_INT_MODE) // Interrupt Rising edge trigger +} HAL_GPIO_PIN_MODE; + +enum { + GPIO_PORT_A = 0, + GPIO_PORT_B = 1, + GPIO_PORT_C = 2, + GPIO_PORT_D = 3 +}; + +typedef enum { + hal_PullNone = 0, + hal_PullUp = 1, + hal_PullDown = 2, + hal_OpenDrain = 3, + hal_PullDefault = hal_PullNone +} HAL_PinMode; + +typedef struct _HAL_GPIO_PORT_ { + u32 out_data; // to write the GPIO port + u32 in_data; // to read the GPIO port + u32 dir; // config each pin direction +}HAL_GPIO_PORT, *PHAL_GPIO_PORT; + +#define HAL_GPIO_PIN_NAME(port,pin) (((port)<<5)|(pin)) +#define HAL_GPIO_GET_PORT_BY_NAME(x) ((x>>5) & 0x03) +#define HAL_GPIO_GET_PIN_BY_NAME(x) (x & 0x1f) + +typedef struct _HAL_GPIO_PIN_ { + HAL_GPIO_PIN_MODE pin_mode; + u32 pin_name; // Pin: [7:5]: port number, [4:0]: pin number +}HAL_GPIO_PIN, *PHAL_GPIO_PIN; + +typedef struct _HAL_GPIO_OP_ { +#if defined(__ICCARM__) + void* dummy; +#endif +}HAL_GPIO_OP, *PHAL_GPIO_OP; + +typedef void (*GPIO_IRQ_FUN)(VOID *Data, u32 Id); +typedef void (*GPIO_USER_IRQ_FUN)(u32 Id); + +typedef struct _HAL_GPIO_ADAPTER_ { + IRQ_HANDLE IrqHandle; // GPIO HAL IRQ Handle + GPIO_USER_IRQ_FUN UserIrqHandler; // GPIO IRQ Handler + GPIO_IRQ_FUN PortA_IrqHandler[32]; // The interrupt handler triggered by Port A[x] + VOID *PortA_IrqData[32]; + VOID (*EnterCritical)(void); + VOID (*ExitCritical)(void); + u32 Local_Gpio_Dir[3]; // to record direction setting: 0- IN, 1- Out + u8 Gpio_Func_En; // Is GPIO HW function enabled ? + u8 Locked; +}HAL_GPIO_ADAPTER, *PHAL_GPIO_ADAPTER; + +u32 +HAL_GPIO_GetPinName( + u32 chip_pin +); + +VOID +HAL_GPIO_PullCtrl( + u32 pin, + u32 mode +); + +VOID +HAL_GPIO_Init( + HAL_GPIO_PIN *GPIO_Pin +); + +VOID +HAL_GPIO_Irq_Init( + HAL_GPIO_PIN *GPIO_Pin +); + +#endif // end of "#define _HAL_GPIO_H_" + diff --git a/component/soc/realtek/8195a/fwlib/hal_i2c.h b/component/soc/realtek/8195a/fwlib/hal_i2c.h new file mode 100644 index 0000000..13996c0 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/hal_i2c.h @@ -0,0 +1,565 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#ifndef _HAL_I2C_H_ //#ifndef _HAL_I2C_H_ +#define _HAL_I2C_H_ + +#include "rtl8195a_i2c.h" +#include "hal_gdma.h" + +//================= I2C CONFIGURATION START ================== +// I2C SAL User Configuration Flags + +// I2C SAL operation types +#define I2C_POLL_OP_TYPE 1 +#define I2C_INTR_OP_TYPE 1 +#define I2C_DMA_OP_TYPE 1 + +// I2C supports user register address +#define I2C_USER_REG_ADDR 1 //I2C User specific register address by using + //the first I2C data as the register + //address + +// I2C SAL used module. Please set the I2C module flag to 1 to enable the related +// I2C module functions. +#define I2C0_USED 1 +#define I2C1_USED 1 +#define I2C2_USED 1 +#define I2C3_USED 1 +//================= I2C CONFIGURATION END =================== + + +//================= I2C HAL START ========================== +// I2C debug output +#define I2C_PREFIX "RTL8195A[i2c]: " +#define I2C_PREFIX_LVL " [i2c_DBG]: " + +typedef enum _I2C_DBG_LVL_ { + HAL_I2C_LVL = 0x01, + SAL_I2C_LVL = 0x02, + VERI_I2C_LVL = 0x03, +}I2C_DBG_LVL,*PI2C_DBG_LVL; + +#ifdef CONFIG_DEBUG_LOG +#ifdef CONFIG_DEBUG_LOG_I2C_HAL +#define DBG_I2C_LOG_PERD 100 + + #define I2CDBGLVL 0xFF + #define DBG_8195A_I2C(...) do{ \ + _DbgDump("\r"I2C_PREFIX __VA_ARGS__);\ + }while(0) + + #define DBG_8195A_I2C_LVL(LVL,...) do{\ + if (LVL&I2CDBGLVL){\ + _DbgDump("\r"I2C_PREFIX_LVL __VA_ARGS__);\ + }\ + }while(0) +#else + #define DBG_I2C_LOG_PERD 100 + #define DBG_8195A_I2C(...) + #define DBG_8195A_I2C_LVL(...) +#endif +#else + #define DBG_I2C_LOG_PERD 100 + #define DBG_8195A_I2C(...) + #define DBG_8195A_I2C_LVL(...) +#endif + +//====================================================== +// I2C HAL related enumeration +// I2C Module Selection +typedef enum _I2C_MODULE_SEL_ { + I2C0_SEL = 0x0, + I2C1_SEL = 0x1, + I2C2_SEL = 0x2, + I2C3_SEL = 0x3, +}I2C_MODULE_SEL,*PI2C_MODULE_SEL; + +// I2C HAL initial data structure +typedef struct _HAL_I2C_INIT_DAT_ { + u8 I2CIdx; //I2C index used + u8 I2CEn; //I2C module enable + u8 I2CMaster; //Master or Slave mode + u8 I2CAddrMod; //I2C addressing mode(7-bit, 10-bit) + + u8 I2CSpdMod; //I2C speed mode(Standard, Fast, High) + u8 I2CSetup; //I2C SDA setup time + u8 I2CRXTL; //I2C RX FIFO Threshold + u8 I2CTXTL; //I2C TX FIFO Threshold + + u8 I2CBusLd; //I2C bus load (pf) for high speed mode + u8 I2CReSTR; //I2C restart support + u8 I2CGC; //I2C general support + u8 I2CStartB; //I2C start byte support + + u8 I2CSlvNoAck; //I2C slave no ack support + u8 I2CDMACtrl; //I2C DMA feature support + u8 I2CCmd; //I2C Command + u8 I2CDataLen; //I2C Data Length + + u8 I2CSlvAckGC; //I2C slave acks to General Call + u8 I2CStop; //I2C issues STOP bit or not + u16 RSVD0; + + u8 *I2CRWData; //I2C Read/Write data pointer + + u16 I2CIntrMSK; //I2C Interrupt Mask + u16 I2CIntrClr; //I2C Interrupt register to clear + + u16 I2CAckAddr; //I2C target address in I2C Master mode, + //ack address in I2C Slave mode + u16 I2CSdaHd; //I2C SDA hold time + + u32 I2CClk; //I2C bus clock (in kHz) + + u8 I2CTxDMARqLv; //I2C TX DMA Empty Level + u8 I2CRxDMARqLv; //I2C RX DMA Full Level + u16 RSVD1; //Reserved +}HAL_I2C_INIT_DAT,*PHAL_I2C_INIT_DAT; + +// I2C HAL Operations +typedef struct _HAL_I2C_OP_ { + HAL_Status (*HalI2CInit) (VOID *Data); //HAL I2C initialization + HAL_Status (*HalI2CDeInit) (VOID *Data); //HAL I2C de-initialization + HAL_Status (*HalI2CSend) (VOID *Data); //HAL I2C send + u8 (*HalI2CReceive) (VOID *Data); //HAL I2C receive + HAL_Status (*HalI2CEnable) (VOID *Data); //HAL I2C enable module + HAL_Status (*HalI2CIntrCtrl) (VOID *Data); //HAL I2C interrupt control + u32 (*HalI2CReadReg) (VOID *Data, u8 I2CReg);//HAL I2C read register + HAL_Status (*HalI2CWriteReg) (VOID *Data, u8 I2CReg, u32 RegVal);//HAL I2C write register + HAL_Status (*HalI2CSetCLK) (VOID *Data); //HAL I2C set bus clock + HAL_Status (*HalI2CMassSend) (VOID *Data); //HAL I2C mass send + HAL_Status (*HalI2CClrIntr) (VOID *Data); //HAL I2C clear interrupts + HAL_Status (*HalI2CClrAllIntr) (VOID *Data); //HAL I2C clear all interrupts + HAL_Status (*HalI2CDMACtrl) (VOID *Data); //HAL I2C DMA control +}HAL_I2C_OP, *PHAL_I2C_OP; +//================= I2C HAL END =========================== + + +//================= I2C SAL START ========================== +//I2C SAL Macros + +//====================================================== +// I2C SAL related enumerations +// I2C Extend Features +typedef enum _I2C_EXD_SUPPORT_{ + I2C_EXD_RESTART = 0x1, //BIT_0, RESTART bit + I2C_EXD_GENCALL = 0x2, //BIT_1, Master generates General Call. All "send" operations generate General Call addresss + I2C_EXD_STARTB = 0x4, //BIT_2, Using START BYTE, instead of START Bit + I2C_EXD_SLVNOACK = 0x8, //BIT_3, Slave no ack to master + I2C_EXD_BUS400PF = 0x10, //BIT_4, I2C bus loading is 400pf + I2C_EXD_SLVACKGC = 0x20, //BIT_5, Slave acks to a General Call + I2C_EXD_USER_REG = 0x40, //BIT_6, Using User Register Address + I2C_EXD_USER_TWOB = 0x80, //BIT_7, User Register Address is 2-byte + I2C_EXD_MTR_ADDR_RTY= 0x100, //BIT_8, Master retries to send start condition and Slave address when the slave doesn't ack + // the address. + I2C_EXD_MTR_ADDR_UPD= 0x200, //BIT_9, Master dynamically updates slave address + I2C_EXD_MTR_HOLD_BUS= 0x400, //BIT_10, Master doesn't generate STOP when the FIFO is empty. This would make Master hold + // the bus. +}I2C_EXD_SUPPORT,*PI2C_EXD_SUPPORT; + +// I2C operation type +typedef enum _I2C_OP_TYPE_ { + I2C_POLL_TYPE = 0x0, + I2C_DMA_TYPE = 0x1, + I2C_INTR_TYPE = 0x2, +}I2C_OP_TYPE, *PI2C_OP_TYPE; + +// I2C pinmux selection +typedef enum _I2C_PINMUX_ { + I2C_PIN_S0 = 0x0, + I2C_PIN_S1 = 0x1, + I2C_PIN_S2 = 0x2, + I2C_PIN_S3 = 0x3, //Only valid for I2C0 and I2C3 +}I2C_PINMUX, *PI2C_PINMUX; + +// I2C module status +typedef enum _I2C_MODULE_STATUS_ { + I2C_DISABLE = 0x0, + I2C_ENABLE = 0x1, +}I2C_MODULE_STATUS, *PI2C_MODULE_STATUS; + +// I2C device status +typedef enum _I2C_Device_STATUS_ { + I2C_STS_UNINITIAL = 0x00, + I2C_STS_INITIALIZED = 0x01, + I2C_STS_IDLE = 0x02, + + I2C_STS_TX_READY = 0x03, + I2C_STS_TX_ING = 0x04, + + I2C_STS_RX_READY = 0x05, + I2C_STS_RX_ING = 0x06, + + I2C_STS_ERROR = 0x10, + I2C_STS_TIMEOUT = 0x11, +}I2C_Device_STATUS, *PI2C_Device_STATUS; + +// I2C feature status +typedef enum _I2C_FEATURE_STATUS_{ + I2C_FEATURE_DISABLED = 0, + I2C_FEATURE_ENABLED = 1, +}I2C_FEATURE_STATUS,*PI2C_FEATURE_STATUS; + +// I2C device mode +typedef enum _I2C_DEV_MODE_ { + I2C_SLAVE_MODE = 0x0, + I2C_MASTER_MODE = 0x1, +}I2C_DEV_MODE, *PI2C_DEV_MODE; + +// I2C Bus Transmit/Receive +typedef enum _I2C_DIRECTION_ { + I2C_ONLY_TX = 0x1, + I2C_ONLY_RX = 0x2, + I2C_TXRX = 0x3, +}I2C_DIRECTION, *PI2C_DIRECTION; + +//I2C DMA module number +typedef enum _I2C_DMA_MODULE_SEL_ { + I2C_DMA_MODULE_0 = 0x0, + I2C_DMA_MODULE_1 = 0x1 +}I2C_DMA_MODULE_SEL, *PI2C_DMA_MODULE_SEL; + +// I2C0 DMA peripheral number +typedef enum _I2C0_DMA_PERI_NUM_ { + I2C0_DMA_TX_NUM = 0x8, + I2C0_DMA_RX_NUM = 0x9, +}I2C0_DMA_PERI_NUM,*PI2C0_DMA_PERI_NUM; + +// I2C1 DMA peripheral number +typedef enum _I2C1_DMA_PERI_NUM_ { + I2C1_DMA_TX_NUM = 0xA, + I2C1_DMA_RX_NUM = 0xB, +}I2C1_DMA_PERI_NUM,*PI2C1_DMA_PERI_NUM; + +// I2C0 DMA module used +typedef enum _I2C0_DMA_MODULE_ { + I2C0_DMA0 = 0x0, + I2C0_DMA1 = 0x1, +}I2C0_DMA_MODULE,*PI2C0_DMA_MODULE; + +// I2C0 DMA module used +typedef enum _I2C1_DMA_MODULE_ { + I2C1_DMA0 = 0x0, + I2C1_DMA1 = 0x1, +}I2C1_DMA_MODULE,*PI2C1_DMA_MODULE; + +// I2C command type +typedef enum _I2C_COMMAND_TYPE_ { + I2C_WRITE_CMD = 0x0, + I2C_READ_CMD = 0x1, +}I2C_COMMAND_TYPE,*PI2C_COMMAND_TYPE; + +// I2C STOP BIT +typedef enum _I2C_STOP_TYPE_ { + I2C_STOP_DIS = 0x0, + I2C_STOP_EN = 0x1, +}I2C_STOP_TYPE, *PI2C_STOP_TYPE; + +// I2C error type +typedef enum _I2C_ERR_TYPE_ { + I2C_ERR_RX_UNDER = 0x01, //I2C RX FIFO Underflow + I2C_ERR_RX_OVER = 0x02, //I2C RX FIFO Overflow + I2C_ERR_TX_OVER = 0x04, //I2C TX FIFO Overflow + I2C_ERR_TX_ABRT = 0x08, //I2C TX terminated + I2C_ERR_SLV_TX_NACK = 0x10, //I2C slave transmission terminated by master NACK, + //but there are data in slave TX FIFO + I2C_ERR_USER_REG_TO = 0x20, + + I2C_ERR_RX_CMD_TO = 0x21, + I2C_ERR_RX_FF_TO = 0x22, + I2C_ERR_TX_CMD_TO = 0x23, + I2C_ERR_TX_FF_TO = 0x24, + + I2C_ERR_TX_ADD_TO = 0x25, + I2C_ERR_RX_ADD_TO = 0x26, +}I2C_ERR_TYPE, *PI2C_ERR_TYPE; + +// I2C Time Out type +typedef enum _I2C_TIMEOUT_TYPE_ { + I2C_TIMEOOUT_DISABLE = 0x00, + I2C_TIMEOOUT_ENDLESS = 0xFFFFFFFF, +}I2C_TIMEOUT_TYPE, *PI2C_TIMEOUT_TYPE; + +//====================================================== +// SAL I2C related data structures +// I2C user callback adapter +typedef struct _SAL_I2C_USERCB_ADPT_ { + VOID (*USERCB) (VOID *Data); + u32 USERData; +}SAL_I2C_USERCB_ADPT, *PSAL_I2C_USERCB_ADPT; + +// I2C user callback structure +typedef struct _SAL_I2C_USER_CB_ { + PSAL_I2C_USERCB_ADPT pTXCB; //I2C Transmit Callback + PSAL_I2C_USERCB_ADPT pTXCCB; //I2C Transmit Complete Callback + PSAL_I2C_USERCB_ADPT pRXCB; //I2C Receive Callback + PSAL_I2C_USERCB_ADPT pRXCCB; //I2C Receive Complete Callback + PSAL_I2C_USERCB_ADPT pRDREQCB; //I2C Read Request Callback + PSAL_I2C_USERCB_ADPT pERRCB; //I2C Error Callback + PSAL_I2C_USERCB_ADPT pDMATXCB; //I2C DMA Transmit Callback + PSAL_I2C_USERCB_ADPT pDMATXCCB; //I2C DMA Transmit Complete Callback + PSAL_I2C_USERCB_ADPT pDMARXCB; //I2C DMA Receive Callback + PSAL_I2C_USERCB_ADPT pDMARXCCB; //I2C DMA Receive Complete Callback + PSAL_I2C_USERCB_ADPT pGENCALLCB; //I2C General Call Callback +}SAL_I2C_USER_CB, *PSAL_I2C_USER_CB; + +// I2C Transmit Buffer +typedef struct _SAL_I2C_TRANSFER_BUF_ { + u16 DataLen; //I2C Transmfer Length + u16 TargetAddr; //I2C Target Address. It's only valid in Master Mode. + u32 RegAddr; //I2C Register Address. It's only valid in Master Mode. + u32 RSVD; // + u8 *pDataBuf; //I2C Transfer Buffer Pointer +}SAL_I2C_TRANSFER_BUF,*PSAL_I2C_TRANSFER_BUF; + +typedef struct _SAL_I2C_DMA_USER_DEF_ { + u8 TxDatSrcWdth; + u8 TxDatDstWdth; + u8 TxDatSrcBstSz; + u8 TxDatDstBstSz; + u8 TxChNo; + u8 RSVD0; + u16 RSVD1; + u8 RxDatSrcWdth; + u8 RxDatDstWdth; + u8 RxDatSrcBstSz; + u8 RxDatDstBstSz; + u8 RxChNo; + u8 RSVD2; + u16 RSVD3; +}SAL_I2C_DMA_USER_DEF, *PSAL_I2C_DMA_USER_DEF; + +// RTK I2C OP +typedef struct _RTK_I2C_OP_ { + HAL_Status (*Init) (VOID *Data); + HAL_Status (*DeInit) (VOID *Data); + HAL_Status (*Send) (VOID *Data); + HAL_Status (*Receive) (VOID *Data); + HAL_Status (*IoCtrl) (VOID *Data); + HAL_Status (*PowerCtrl) (VOID *Data); +}RTK_I2C_OP, *PRTK_I2C_OP; + +// Software API Level I2C Handler +typedef struct _SAL_I2C_HND_ { + u8 DevNum; //I2C device number + u8 PinMux; //I2C pin mux seletion + u8 OpType; //I2C operation type selection + volatile u8 DevSts; //I2C device status + + u8 I2CMaster; //I2C Master or Slave mode + u8 I2CAddrMod; //I2C 7-bit or 10-bit mode + u8 I2CSpdMod; //I2C SS/ FS/ HS speed mode + u8 I2CAckAddr; //I2C target address in Master + //mode or ack address in Slave + //mode + + u16 I2CClk; //I2C bus clock + u8 MasterRead; //I2C Master Read Supported, + //An Address will be sent before + //read data back. + + u8 I2CDmaSel; //I2C DMA module select + // 0 for DMA0, + // 1 for DMA1 + u8 I2CTxDMARqLv; //I2C TX DMA Empty Level + u8 I2CRxDMARqLv; //I2C RX DMA Full Level + u16 RSVD0; //Reserved + + u32 RSVD1; //Reserved + + u32 I2CExd; //I2C extended options: + //bit 0: I2C RESTART supported, + // 0 for NOT supported, + // 1 for supported + //bit 1: I2C General Call supported + // 0 for NOT supported, + // 1 for supported + //bit 2: I2C START Byte supported + // 0 for NOT supported, + // 1 for supported + //bit 3: I2C Slave-No-Ack + // supported + // 0 for NOT supported, + // 1 for supported + //bit 4: I2C bus loading, + // 0 for 100pf, + // 1 for 400pf + //bit 5: I2C slave ack to General + // Call + //bit 6: I2C User register address + //bit 7: I2C 2-Byte User register + // address + //bit 8: I2C slave address no ack retry, + // It's only for Master mode, + // when slave doesn't ack the + // address + //bit 31~bit 8: Reserved + u32 ErrType; // + u32 TimeOut; //I2C IO Timeout count, in ms + + PHAL_I2C_INIT_DAT pInitDat; //Pointer to I2C initial data struct + PSAL_I2C_TRANSFER_BUF pTXBuf; //Pointer to I2C TX buffer + PSAL_I2C_TRANSFER_BUF pRXBuf; //Pointer to I2C RX buffer + PSAL_I2C_USER_CB pUserCB; //Pointer to I2C User Callback + PSAL_I2C_DMA_USER_DEF pDMAConf; //Pointer to I2C User Define DMA config +}SAL_I2C_HND, *PSAL_I2C_HND; + + + +//====================================================== +// I2C SAL Function Prototypes + +// For checking I2C input index valid or not +static inline HAL_Status +RtkI2CIdxChk( + IN u8 I2CIdx +) +{ + if (I2CIdx > I2C3_SEL) + return HAL_ERR_UNKNOWN; + + return HAL_OK; +} +#if 0 +//For checking I2C operation type valid or not +static inline HAL_Status +RtkI2COpTypeChk( + IN VOID *Data +) +{ + PSAL_I2C_HND pSalI2CHND = (PSAL_I2C_HND) Data; + + if (pSalI2CHND->OpType == I2C_POLL_TYPE) + return HAL_ERR_UNKNOWN; + + if (pSalI2CHND->OpType == I2C_DMA_TYPE) + return HAL_ERR_UNKNOWN; + + if (pSalI2CHND->OpType == I2C_INTR_TYPE) + return HAL_ERR_UNKNOWN; + + pSalI2CHND = pSalI2CHND; + + return HAL_OK; +} +#endif +//For checking I2C DMA available or not +static inline HAL_Status +RtkI2CDMAChk( + IN VOID *Data +) +{ + PSAL_I2C_HND pSalI2CHND = (PSAL_I2C_HND) Data; + + if (pSalI2CHND->OpType == I2C_DMA_TYPE) { + if (pSalI2CHND->DevNum >= I2C2_SEL) + return HAL_ERR_UNKNOWN; + } + else { + return HAL_ERR_UNKNOWN; + } + + return HAL_OK; +} + +//For checking I2C DMA available or not +static inline HAL_Status +RtkI2CDMAInitChk( + IN VOID *Data +) +{ + PSAL_I2C_HND pSalI2CHND = (PSAL_I2C_HND) Data; + + if (pSalI2CHND->OpType != I2C_DMA_TYPE) { + return HAL_ERR_UNKNOWN; + } + else { + return HAL_OK; + } + +} + +//====================================================== +//SAL I2C management function prototype +_LONG_CALL_ HAL_Status RtkI2CLoadDefault(IN VOID *Data); +_LONG_CALL_ HAL_Status RtkI2CInit(IN VOID *Data); +_LONG_CALL_ HAL_Status RtkI2CDeInit(IN VOID *Data); +_LONG_CALL_ HAL_Status RtkI2CSend(IN VOID *Data); +_LONG_CALL_ HAL_Status RtkI2CReceive(IN VOID *Data); +_LONG_CALL_ VOID RtkSalI2COpInit(IN VOID *Data); +_LONG_CALL_ HAL_Status RtkI2CSendUserAddr(IN VOID *Data,IN u8 MtrWr); +_LONG_CALL_ HAL_Status RtkI2CIoCtrl(IN VOID *Data); +_LONG_CALL_ HAL_Status RtkI2CPowerCtrl(IN VOID *Data); +//================= I2C SAL END =========================== + + +//================= I2C SAL MANAGEMENT START ================= +// I2C SAL management macros +#define SAL_USER_CB_NUM (sizeof(SAL_I2C_USER_CB) / sizeof(PSAL_I2C_USERCB_ADPT)) + +//====================================================== +// I2C SAL management data structures +// I2C SAL handle private +typedef struct _SAL_I2C_HND_PRIV_ { + VOID **ppSalI2CHnd; //Pointer to SAL_I2C_HND pointer + SAL_I2C_HND SalI2CHndPriv; //Private SAL_I2C_HND +}SAL_I2C_HND_PRIV, *PSAL_I2C_HND_PRIV; + +//I2C SAL management adapter +typedef struct _SAL_I2C_MNGT_ADPT_ { + PSAL_I2C_HND_PRIV pSalHndPriv; //Pointer to SAL_I2C_HND + PHAL_I2C_INIT_DAT pHalInitDat; //Pointer to HAL I2C initial data( HAL_I2C_INIT_DAT ) + PHAL_I2C_OP pHalOp; //Pointer to HAL I2C operation( HAL_I2C_OP ) + VOID (*pHalOpInit)(VOID*); //Pointer to HAL I2C initialize function + PIRQ_HANDLE pIrqHnd; //Pointer to IRQ handler in SAL layer( IRQ_HANDLE ) + PSAL_I2C_USER_CB pUserCB; //Pointer to SAL user callbacks (SAL_I2C_USER_CB ) + volatile u32 MstRDCmdCnt; //Used for Master Read command count + volatile u32 InnerTimeOut; //Used for SAL internal timeout count + VOID (*pSalIrqFunc)(VOID*); //Used for SAL I2C interrupt function + + PSAL_I2C_DMA_USER_DEF pDMAConf; //Pointer to I2C User Define DMA config + PHAL_GDMA_ADAPTER pHalTxGdmaAdp; //Pointer to HAL_GDMA_ADAPTER + PHAL_GDMA_ADAPTER pHalRxGdmaAdp; //Pointer to HAL_GDMA_ADAPTER + PHAL_GDMA_OP pHalGdmaOp; //Pointer to HAL_GDMA_OP + VOID (*pHalGdmaOpInit)(VOID*); //Pointer to HAL I2C initialize function + PIRQ_HANDLE pIrqTxGdmaHnd; //Pointer to IRQ handler for Tx GDMA + PIRQ_HANDLE pIrqRxGdmaHnd; //Pointer to IRQ handler for Rx GDMA + VOID (*pSalDMATxIrqFunc)(VOID*); //Used for SAL I2C interrupt function + VOID (*pSalDMARxIrqFunc)(VOID*); //Used for SAL I2C interrupt function + u32 RSVD; //Reserved +}SAL_I2C_MNGT_ADPT, *PSAL_I2C_MNGT_ADPT; + +//====================================================== +//SAL I2C management function prototype +PSAL_I2C_MNGT_ADPT RtkI2CGetMngtAdpt(IN u8 I2CIdx); +HAL_Status RtkI2CFreeMngtAdpt(IN PSAL_I2C_MNGT_ADPT pSalI2CMngtAdpt); +PSAL_I2C_HND RtkI2CGetSalHnd(IN u8 I2CIdx); +HAL_Status RtkI2CFreeSalHnd(IN PSAL_I2C_HND pSalI2CHND); +u32 RtkSalI2CSts(IN VOID *Data); + +extern _LONG_CALL_ VOID I2CISRHandle(IN VOID *Data); +extern _LONG_CALL_ VOID I2CTXGDMAISRHandle(IN VOID *Data); +extern _LONG_CALL_ VOID I2CRXGDMAISRHandle(IN VOID *Data); +extern HAL_Status I2CIsTimeout (IN u32 StartCount, IN u32 TimeoutCnt); +extern HAL_TIMER_OP HalTimerOp; +//====================================================== +// Function Prototypes +_LONG_CALL_ VOID HalI2COpInit(IN VOID *Data); +//================= I2C SAL MANAGEMENT END ================== + +//================= Rtl8195a I2C V02 function prototype ============ +_LONG_CALL_ VOID HalI2COpInitV02(IN VOID *Data); +_LONG_CALL_ VOID I2CISRHandleV02(IN VOID *Data); +_LONG_CALL_ HAL_Status RtkI2CSendV02(IN VOID *Data); +_LONG_CALL_ HAL_Status RtkI2CReceiveV02(IN VOID *Data); +_LONG_CALL_ VOID RtkSalI2COpInitV02(IN VOID *Data); +//================= Rtl8195a I2C V02 function prototype END========== + +#endif //#ifndef _HAL_I2C_H_ diff --git a/component/soc/realtek/8195a/fwlib/hal_i2s.h b/component/soc/realtek/8195a/fwlib/hal_i2s.h new file mode 100644 index 0000000..2e49d09 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/hal_i2s.h @@ -0,0 +1,333 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#ifndef _HAL_I2S_H_ +#define _HAL_I2S_H_ + +#include "rtl8195a_i2s.h" + +/* User Define Flags */ + +#define I2S_MAX_ID 1 // valid I2S index 0 ~ I2S_MAX_ID + +/**********************************************************************/ +/* I2S HAL initial data structure */ +typedef struct _HAL_I2S_INIT_DAT_ { + u8 I2SIdx; /*I2S index used*/ + u8 I2SEn; /*I2S module enable tx/rx/tx+rx*/ + u8 I2SMaster; /*I2S Master or Slave mode*/ + u8 I2SWordLen; /*I2S Word length 16 or 24bits*/ + + u8 I2SChNum; /*I2S Channel number mono or stereo*/ + u8 I2SPageNum; /*I2S Page Number 2~4*/ + u16 I2SPageSize; /*I2S page Size 1~4096 word*/ + + u8 *I2STxData; /*I2S Tx data pointer*/ + + u8 *I2SRxData; /*I2S Rx data pointer*/ + + u32 I2STxIntrMSK; /*I2S Tx Interrupt Mask*/ + u32 I2STxIntrClr; /*I2S Tx Interrupt register to clear */ + + u32 I2SRxIntrMSK; /*I2S Rx Interrupt Mask*/ + u32 I2SRxIntrClr; /*I2S Rx Interrupt register to clear*/ + + u16 I2STxIdx; /*I2S TX page index */ + u16 I2SRxIdx; /*I2S RX page index */ + + u16 I2SHWTxIdx; /*I2S HW TX page index */ + u16 I2SHWRxIdx; /*I2S HW RX page index */ + + + u16 I2SRate; /*I2S sample rate*/ + u8 I2STRxAct; /*I2S tx rx act*/ +}HAL_I2S_INIT_DAT, *PHAL_I2S_INIT_DAT; + +/**********************************************************************/ +/* I2S Data Structures */ +/* I2S Module Selection */ +typedef enum _I2S_MODULE_SEL_ { + I2S0_SEL = 0x0, + I2S1_SEL = 0x1, +}I2S_MODULE_SEL,*PI2S_MODULE_SEL; +/* +typedef struct _HAL_I2S_ADAPTER_ { + u32 Enable:1; + I2S_CTL_REG I2sCtl; + I2S_SETTING_REG I2sSetting; + u32 abc; + u8 I2sIndex; +}HAL_I2S_ADAPTER, *PHAL_I2S_ADAPTER; +*/ +/* I2S HAL Operations */ +typedef struct _HAL_I2S_OP_ { + RTK_STATUS (*HalI2SInit) (VOID *Data); + RTK_STATUS (*HalI2SDeInit) (VOID *Data); + RTK_STATUS (*HalI2STx) (VOID *Data, u8 *pBuff); + RTK_STATUS (*HalI2SRx) (VOID *Data, u8 *pBuff); + RTK_STATUS (*HalI2SEnable) (VOID *Data); + RTK_STATUS (*HalI2SIntrCtrl) (VOID *Data); + u32 (*HalI2SReadReg) (VOID *Data, u8 I2SReg); + RTK_STATUS (*HalI2SSetRate) (VOID *Data); + RTK_STATUS (*HalI2SSetWordLen) (VOID *Data); + RTK_STATUS (*HalI2SSetChNum) (VOID *Data); + RTK_STATUS (*HalI2SSetPageNum) (VOID *Data); + RTK_STATUS (*HalI2SSetPageSize) (VOID *Data); + + RTK_STATUS (*HalI2SClrIntr) (VOID *Data); + RTK_STATUS (*HalI2SClrAllIntr) (VOID *Data); + RTK_STATUS (*HalI2SDMACtrl) (VOID *Data); +/* + VOID (*HalI2sOnOff)(VOID *Data); + BOOL (*HalI2sInit)(VOID *Data); + BOOL (*HalI2sSetting)(VOID *Data); + BOOL (*HalI2sEn)(VOID *Data); + BOOL (*HalI2sIsrEnAndDis) (VOID *Data); + BOOL (*HalI2sDumpReg)(VOID *Data); + BOOL (*HalI2s)(VOID *Data); +*/ +}HAL_I2S_OP, *PHAL_I2S_OP; + + +/**********************************************************************/ + +/* I2S Pinmux Selection */ +#if 0 +typedef enum _I2S0_PINMUX_ { + I2S0_TO_S0 = 0x0, + I2S0_TO_S1 = 0x1, + I2S0_TO_S2 = 0x2, +}I2S0_PINMUX, *PI2S0_PINMUX; + +typedef enum _I2S1_PINMUX_ { + I2S1_TO_S0 = 0x0, + I2S1_TO_S1 = 0x1, +}I2S1_PINMUX, *PI2S1_PINMUX; +#endif + +typedef enum _I2S_PINMUX_ { + I2S_S0 = 0, + I2S_S1 = 1, + I2S_S2 = 2, + I2S_S3 = 3 +}I2S_PINMUX, *PI2S_PINMUX; + + +/* I2S Module Status */ +typedef enum _I2S_MODULE_STATUS_ { + I2S_DISABLE = 0x0, + I2S_ENABLE = 0x1, +}I2S_MODULE_STATUS, *PI2S_MODULE_STATUS; + + +/* I2S Device Status */ +typedef enum _I2S_Device_STATUS_ { + I2S_STS_UNINITIAL = 0x00, + I2S_STS_INITIALIZED = 0x01, + I2S_STS_IDLE = 0x02, + + I2S_STS_TX_READY = 0x03, + I2S_STS_TX_ING = 0x04, + + I2S_STS_RX_READY = 0x05, + I2S_STS_RX_ING = 0x06, + + I2S_STS_TRX_READY = 0x07, + I2S_STS_TRX_ING = 0x08, + + I2S_STS_ERROR = 0x09, +}I2S_Device_STATUS, *PI2S_Device_STATUS; + + +/* I2S Feature Status */ +typedef enum _I2S_FEATURE_STATUS_{ + I2S_FEATURE_DISABLED = 0, + I2S_FEATURE_ENABLED = 1, +}I2S_FEATURE_STATUS,*PI2S_FEATURE_STATUS; + +/* I2S Device Mode */ +typedef enum _I2S_DEV_MODE_ { + I2S_MASTER_MODE = 0x0, + I2S_SLAVE_MODE = 0x1 +}I2S_DEV_MODE, *PI2S_DEV_MODE; + +/* I2S Word Length */ +typedef enum _I2S_WORD_LEN_ { + I2S_WL_16 = 0x0, + I2S_WL_24 = 0x1, +}I2S_WORD_LEN, *PI2S_WORD_LEN; + +/* I2S Bus Transmit/Receive */ +typedef enum _I2S_DIRECTION_ { + I2S_ONLY_RX = 0x0, + I2S_ONLY_TX = 0x1, + I2S_TXRX = 0x2 +}I2S_DIRECTION, *PI2S_DIRECTION; + +/* I2S Channel number */ +typedef enum _I2S_CH_NUM_ { + I2S_CH_STEREO = 0x0, + I2S_CH_RSVD = 0x1, + I2S_CH_MONO = 0x2 +}I2S_CH_NUM, *PI2S_CH_NUM; + +/* I2S Page number */ +typedef enum _I2S_PAGE_NUM_ { + I2S_1PAGE = 0x0, + I2S_2PAGE = 0x1, + I2S_3PAGE = 0x2, + I2S_4PAGE = 0x3 +}I2S_PAGE_NUM, *PI2S_PAGE_NUM; + +/* I2S Sample rate*/ +typedef enum _I2S_SAMPLE_RATE_ { + I2S_SR_8KHZ = 0x00, // /12 + I2S_SR_16KHZ = 0x01, // /6 + I2S_SR_24KHZ = 0x02, // /4 + I2S_SR_32KHZ = 0x03, // /3 + I2S_SR_48KHZ = 0x05, // /2 + I2S_SR_96KHZ = 0x06, // x1, base 96kHz + I2S_SR_7p35KHZ = 0x10, + I2S_SR_11p02KHZ = 0x11, + I2S_SR_22p05KHZ = 0x12, + I2S_SR_29p4KHZ = 0x13, + I2S_SR_44p1KHZ = 0x15, + I2S_SR_88p2KHZ = 0x16 // x1, base 88200Hz +}I2S_SAMPLE_RATE, *PI2S_SAMPLE_RATE; + +/* I2S TX interrupt mask/status */ +typedef enum _I2S_TX_IMR_ { + I2S_TX_INT_PAGE0_OK = (1<<0), + I2S_TX_INT_PAGE1_OK = (1<<1), + I2S_TX_INT_PAGE2_OK = (1<<2), + I2S_TX_INT_PAGE3_OK = (1<<3), + I2S_TX_INT_FULL = (1<<4), + I2S_TX_INT_EMPTY = (1<<5) +} I2S_TX_IMR, *PI2S_TX_IMR; + +/* I2S RX interrupt mask/status */ +typedef enum _I2S_RX_IMR_ { + I2S_RX_INT_PAGE0_OK = (1<<0), + I2S_RX_INT_PAGE1_OK = (1<<1), + I2S_RX_INT_PAGE2_OK = (1<<2), + I2S_RX_INT_PAGE3_OK = (1<<3), + I2S_RX_INT_EMPTY = (1<<4), + I2S_RX_INT_FULL = (1<<5) +} I2S_RX_IMR, *PI2S_RX_IMR; + +/* I2S User Callbacks */ +typedef struct _SAL_I2S_USER_CB_{ + VOID (*TXCB) (VOID *Data); + VOID (*TXCCB) (VOID *Data); + VOID (*RXCB) (VOID *Data); + VOID (*RXCCB) (VOID *Data); + VOID (*RDREQCB) (VOID *Data); + VOID (*ERRCB) (VOID *Data); + VOID (*GENCALLCB) (VOID *Data); +}SAL_I2S_USER_CB,*PSAL_I2S_USER_CB; + +typedef struct _I2S_USER_CB_{ + VOID (*TxCCB)(uint32_t id, char *pbuf); + u32 TxCBId; + VOID (*RxCCB)(uint32_t id, char *pbuf); + u32 RxCBId; +}I2S_USER_CB,*PI2S_USER_CB; + +/* Software API Level I2S Handler */ +typedef struct _HAL_I2S_ADAPTER_{ + u8 DevNum; //I2S device number + u8 PinMux; //I2S pin mux seletion + u8 RSVD0; //Reserved + volatile u8 DevSts; //I2S device status + + u32 RSVD2; //Reserved + u32 I2SExd; //I2S extended options: + //bit 0: I2C RESTART supported, + // 0 for NOT supported, + // 1 for supported + //bit 1: I2C General Call supported + // 0 for NOT supported, + // 1 for supported + //bit 2: I2C START Byte supported + // 0 for NOT supported, + // 1 for supported + //bit 3: I2C Slave-No-Ack + // supported + // 0 for NOT supported, + // 1 for supported + //bit 4: I2C bus loading, + // 0 for 100pf, + // 1 for 400pf + //bit 5: I2C slave ack to General + // Call + //bit 6: I2C User register address + //bit 7: I2C 2-Byte User register + // address + //bit 31~bit 8: Reserved + u32 ErrType; // + u32 TimeOut; //I2S IO Timeout count + + PHAL_I2S_INIT_DAT pInitDat; //Pointer to I2S initial data struct + I2S_USER_CB UserCB; //Pointer to I2S User Callback + IRQ_HANDLE IrqHandle; // Irq Handler + + u32* TxPageList[4]; // The Tx DAM buffer: pointer of each page + u32* RxPageList[4]; // The Tx DAM buffer: pointer of each page +}HAL_I2S_ADAPTER, *PHAL_I2S_ADAPTER; + +typedef struct _HAL_I2S_DEF_SETTING_{ + u8 I2SMaster; // Master or Slave mode + u8 DevSts; //I2S device status + u8 I2SChNum; //I2S Channel number mono or stereo + u8 I2SPageNum; //I2S Page number 2~4 + u8 I2STRxAct; //I2S tx rx act, tx only or rx only or tx+rx + u8 I2SWordLen; //I2S Word length 16bit or 24bit + u16 I2SPageSize; //I2S Page size 1~4096 word + + u16 I2SRate; //I2S sample rate 8k ~ 96khz + + u32 I2STxIntrMSK; /*I2S Tx Interrupt Mask*/ + u32 I2SRxIntrMSK; /*I2S Rx Interrupt Mask*/ +}HAL_I2S_DEF_SETTING, *PHAL_I2S_DEF_SETTING; + + + +/**********************************************************************/ +HAL_Status +RtkI2SLoadDefault(IN VOID *Adapter, IN VOID *Setting); + +HAL_Status +RtkI2SInit(IN VOID *Data); + +HAL_Status +RtkI2SDeInit(IN VOID *Data); + +HAL_Status +RtkI2SEnable(IN VOID *Data); + +HAL_Status +RtkI2SDisable(IN VOID *Data); + + +/**********************************************************************/ + + +VOID I2S0ISRHandle(VOID *Data); +VOID I2S1ISRHandle(VOID *Data); + + +/**********************************************************************/ + +VOID HalI2SOpInit( + IN VOID *Data +); + + +#endif + diff --git a/component/soc/realtek/8195a/fwlib/hal_irqn.h b/component/soc/realtek/8195a/fwlib/hal_irqn.h new file mode 100644 index 0000000..952a78b --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/hal_irqn.h @@ -0,0 +1,111 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#ifndef _HAL_IRQN_H_ +#define _HAL_IRQN_H_ + +#define PERIPHERAL_IRQ_BASE_NUM 64 + +typedef enum _IRQn_Type_ { +#if 0 +/****** Cortex-M3 Processor Exceptions Numbers ********/ + NON_MASKABLE_INT_IRQ = -14, + HARD_FAULT_IRQ = -13, + MEM_MANAGE_FAULT_IRQ = -12, + BUS_FAULT_IRQ = -11, + USAGE_FAULT_IRQ = -10, + SVCALL_IRQ = -5, + DEBUG_MONITOR_IRQ = -4, + PENDSVC_IRQ = -2, + SYSTICK_IRQ = -1, +#else +/****** Cortex-M3 Processor Exceptions Numbers ********/ + NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */ + HardFault_IRQn = -13, /*!< 3 Hard Fault, all classes of Fault */ + MemoryManagement_IRQn = -12, /*!< 4 Cortex-M3 Memory Management Interrupt */ + BusFault_IRQn = -11, /*!< 5 Cortex-M3 Bus Fault Interrupt */ + UsageFault_IRQn = -10, /*!< 6 Cortex-M3 Usage Fault Interrupt */ + SVCall_IRQn = -5, /*!< 11 Cortex-M3 SV Call Interrupt */ + DebugMonitor_IRQn = -4, /*!< 12 Cortex-M3 Debug Monitor Interrupt */ + PendSV_IRQn = -2, /*!< 14 Cortex-M3 Pend SV Interrupt */ + SysTick_IRQn = -1, /*!< 15 Cortex-M3 System Tick Interrupt */ +#endif +/****** RTL8195A Specific Interrupt Numbers ************/ + SYSTEM_ON_IRQ = 0, + WDG_IRQ = 1, + TIMER0_IRQ = 2, + TIMER1_IRQ = 3, + I2C3_IRQ = 4, + TIMER2_7_IRQ = 5, + SPI0_IRQ = 6, + GPIO_IRQ = 7, + UART0_IRQ = 8, + SPI_FLASH_IRQ = 9, + USB_OTG_IRQ = 10, + SDIO_HOST_IRQ = 11, + SDIO_DEVICE_IRQ = 12, + I2S0_PCM0_IRQ = 13, + I2S1_PCM1_IRQ = 14, + WL_DMA_IRQ = 15, + WL_PROTOCOL_IRQ = 16, + CRYPTO_IRQ = 17, + GMAC_IRQ = 18, + PERIPHERAL_IRQ = 19, + GDMA0_CHANNEL0_IRQ = 20, + GDMA0_CHANNEL1_IRQ = 21, + GDMA0_CHANNEL2_IRQ = 22, + GDMA0_CHANNEL3_IRQ = 23, + GDMA0_CHANNEL4_IRQ = 24, + GDMA0_CHANNEL5_IRQ = 25, + GDMA1_CHANNEL0_IRQ = 26, + GDMA1_CHANNEL1_IRQ = 27, + GDMA1_CHANNEL2_IRQ = 28, + GDMA1_CHANNEL3_IRQ = 29, + GDMA1_CHANNEL4_IRQ = 30, + GDMA1_CHANNEL5_IRQ = 31, + +/****** RTL8195A Peripheral Interrupt Numbers ************/ + I2C0_IRQ = 64,// 0 + 64, + I2C1_IRQ = 65,// 1 + 64, + I2C2_IRQ = 66,// 2 + 64, + SPI1_IRQ = 72,// 8 + 64, + SPI2_IRQ = 73,// 9 + 64, + UART1_IRQ = 80,// 16 + 64, + UART2_IRQ = 81,// 17 + 64, + UART_LOG_IRQ = 88,// 24 + 64, + ADC_IRQ = 89,// 25 + 64, + DAC0_IRQ = 91,// 27 + 64, + DAC1_IRQ = 92,// 28 + 64, + //RXI300_IRQ = 93// 29 + 64 + LP_EXTENSION_IRQ = 93,// 29+64 + + RXI300_IRQ = 96,// 0+32 + 64 + NFC_IRQ = 97// 1+32+64 +} IRQn_Type, *PIRQn_Type; + + +typedef VOID (*HAL_VECTOR_FUN) (VOID); + +typedef enum _VECTOR_TABLE_TYPE_{ + DEDECATED_VECTRO_TABLE, + PERIPHERAL_VECTOR_TABLE +}VECTOR_TABLE_TYPE, *PVECTOR_TABLE_TYPE; + + +typedef u32 (*IRQ_FUN)(VOID *Data); + +typedef struct _IRQ_HANDLE_ { + IRQ_FUN IrqFun; + IRQn_Type IrqNum; + u32 Data; + u32 Priority; +}IRQ_HANDLE, *PIRQ_HANDLE; + + +#endif //_HAL_IRQN_H_ diff --git a/component/soc/realtek/8195a/fwlib/hal_mii.h b/component/soc/realtek/8195a/fwlib/hal_mii.h new file mode 100644 index 0000000..7a9b970 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/hal_mii.h @@ -0,0 +1,118 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#ifndef _HAL_MII_H_ +#define _HAL_MII_H_ + +#include "rtl8195a_mii.h" + + +/** + * LOG Configurations + */ + +// #define NOLOG + +#define LOG_TAG "NoTag" +#define LOG_INFO_HEADER "I" +#define LOG_DEBUG_HEADER "D" +#define LOG_ERROR_HEADER "E" +#define LOG_TEST_HEADER "T" + +#define IDENT_TWO_SPACE " " +#define IDENT_FOUR_SPACE " " + +#define LOG_INFO(...) do {\ + DiagPrintf("\r"LOG_INFO_HEADER"/"LOG_TAG": " __VA_ARGS__);\ +}while(0) + +#define LOG_DEBUG(...) do {\ + DiagPrintf("\r"LOG_DEBUG_HEADER"/"LOG_TAG": " __VA_ARGS__);\ +}while(0) + +#define LOG_ERROR(...) do {\ + DiagPrintf("\r"LOG_ERROR_HEADER"/"LOG_TAG": " __VA_ARGS__);\ +}while(0) + +#ifdef NOLOG + #define LOGI + #define LOGD + #define LOGE + #define LOGI2 + #define LOGD2 + #define LOGE2 + #define LOGI4 + #define LOGD4 + #define LOGE4 +#else + #define LOGI LOG_INFO + #define LOGD LOG_DEBUG + #define LOGE LOG_ERROR + #define LOGI2(...) LOG_INFO(IDENT_TWO_SPACE __VA_ARGS__) + #define LOGD2(...) LOG_DEBUG(IDENT_TWO_SPACE __VA_ARGS__) + #define LOGE2(...) LOG_ERROR(IDENT_TWO_SPACE __VA_ARGS__) + #define LOGI4(...) LOG_INFO(IDENT_FOUR_SPACE __VA_ARGS__) + #define LOGD4(...) LOG_DEBUG(IDENT_FOUR_SPACE __VA_ARGS__) + #define LOGE4(...) LOG_ERROR(IDENT_FOUR_SPACE __VA_ARGS__) +#endif + +#define ANSI_COLOR_GREEN "\x1b[32m" +#define ANSI_COLOR_CYAN "\x1b[36m" +#define ANSI_COLOR_YELLOW "\x1b[33m" +#define ANSI_COLOR_MAGENTA "\x1b[35m" +#define ANSI_COLOR_RED "\x1b[31m" +#define ANSI_COLOR_BLUE "\x1b[34m" +#define ANSI_COLOR_RESET "\x1b[0m" + +#define DBG_ENTRANCE LOGI(ANSI_COLOR_GREEN "=> %s() <%s>\n" ANSI_COLOR_RESET, \ + __func__, __FILE__) + + +// GMAC MII Configurations +#ifdef LOG_TAG +#undef LOG_TAG +#define LOG_TAG "MII" +#endif + + +typedef struct _HAL_MII_ADAPTER_ { + u32 InterruptMask; + PPHY_MODE_INFO pPhyModeInfo; +}HAL_MII_ADAPTER, *PHAL_MII_ADAPTER; + +typedef struct _HAL_MII_OP_ { + BOOL (*HalMiiGmacInit)(VOID *Data); + BOOL (*HalMiiInit)(VOID *Data); + BOOL (*HalMiiGmacReset)(VOID *Data); + BOOL (*HalMiiGmacEnablePhyMode)(VOID *Data); + u32 (*HalMiiGmacXmit)(VOID *Data); + VOID (*HalMiiGmacCleanTxRing)(VOID *Data); + VOID (*HalMiiGmacFillTxInfo)(VOID *Data); + VOID (*HalMiiGmacFillRxInfo)(VOID *Data); + VOID (*HalMiiGmacTx)(VOID *Data); + VOID (*HalMiiGmacRx)(VOID *Data); + VOID (*HalMiiGmacSetDefaultEthIoCmd)(VOID *Data); + VOID (*HalMiiGmacInitIrq)(VOID *Data); + u32 (*HalMiiGmacGetInterruptStatus)(VOID); + VOID (*HalMiiGmacClearInterruptStatus)(u32 IsrStatus); +}HAL_MII_OP, *PHAL_MII_OP; + +VOID HalMiiOpInit(IN VOID *Data); + +typedef struct _MII_ADAPTER_ { + PHAL_MII_OP pHalMiiOp; + PHAL_MII_ADAPTER pHalMiiAdapter; + PTX_INFO pTx_Info; + PRX_INFO pRx_Info; + VOID* TxBuffer; + VOID* RxBuffer; +}MII_ADAPTER, *PMII_ADAPTER; + +#endif + diff --git a/component/soc/realtek/8195a/fwlib/hal_misc.h b/component/soc/realtek/8195a/fwlib/hal_misc.h new file mode 100644 index 0000000..1d72114 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/hal_misc.h @@ -0,0 +1,30 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#ifndef _MISC_H_ +#define _MISC_H_ + +#include + +#ifdef CONFIG_TIMER_MODULE +extern _LONG_CALL_ u32 HalDelayUs(u32 us); +#endif + +extern _LONG_CALL_ u32 HalGetCpuClk(VOID); +extern _LONG_CALL_ u8 HalGetRomInfo(VOID); + +extern _LONG_CALL_ void *_memset( void *s, int c, SIZE_T n ); +extern _LONG_CALL_ void *_memcpy( void *s1, const void *s2, SIZE_T n ); +extern _LONG_CALL_ int _memcmp( const void *av, const void *bv, SIZE_T len ); + +extern _LONG_CALL_ SIZE_T _strlen(const char *s); +extern _LONG_CALL_ int _strcmp(const char *cs, const char *ct); + + +#endif //_MISC_H_ diff --git a/component/soc/realtek/8195a/fwlib/hal_nfc.h b/component/soc/realtek/8195a/fwlib/hal_nfc.h new file mode 100644 index 0000000..b73dada --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/hal_nfc.h @@ -0,0 +1,22 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#ifndef _HAL_NFC_H_ +#define _HAL_NFC_H_ + +#include "rtl8195a_nfc.h" + + +VOID HalNFCOpInit( + IN VOID *Data +); + + +#endif + diff --git a/component/soc/realtek/8195a/fwlib/hal_pcm.h b/component/soc/realtek/8195a/fwlib/hal_pcm.h new file mode 100644 index 0000000..fa34432 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/hal_pcm.h @@ -0,0 +1,104 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#ifndef _HAL_PCM_H_ +#define _HAL_PCM_H_ + +#include "rtl8195a_pcm.h" +/* +typedef struct _GDMA_CH_LLI_ELE_ { + u32 Sarx; + u32 Darx; + u32 Llpx; + u32 CtlxLow; + u32 CtlxUp; + u32 Temp; +}GDMA_CH_LLI_ELE, *PGDMA_CH_LLI_ELE; +#if 1 +#if 0 +typedef struct _GDMA_CH_LLI_ { + PGDMA_CH_LLI_ELE pLliEle; + PGDMA_CH_LLI pNextLli; +}GDMA_CH_LLI, *PGDMA_CH_LLI; + +typedef struct _BLOCK_SIZE_LIST_ { + u32 BlockSize; + PBLOCK_SIZE_LIST pNextBlockSiz; +}BLOCK_SIZE_LIST, *PBLOCK_SIZE_LIST; +#else +struct GDMA_CH_LLI { + PGDMA_CH_LLI_ELE pLliEle; + struct GDMA_CH_LLI *pNextLli; +}; + +struct BLOCK_SIZE_LIST { + u32 BlockSize; + struct BLOCK_SIZE_LIST *pNextBlockSiz; +}; + +#endif + +#endif +typedef struct _HAL_GDMA_ADAPTER_ { + u32 ChSar; + u32 ChDar; + GDMA_CHANNEL_NUM ChEn; + GDMA_CTL_REG GdmaCtl; + GDMA_CFG_REG GdmaCfg; + u32 PacketLen; + u32 BlockLen; + u32 MuliBlockCunt; + u32 MaxMuliBlock; + struct GDMA_CH_LLI *pLlix; + struct BLOCK_SIZE_LIST *pBlockSizeList; + + PGDMA_CH_LLI_ELE pLli; + u32 NextPlli; + u8 TestItem; + u8 ChNum; + u8 GdmaIndex; + u8 IsrCtrl:1; + u8 GdmaOnOff:1; + u8 Llpctrl:1; + u8 Lli0:1; + u8 Rsvd4to7:4; + u8 GdmaIsrType; +}HAL_GDMA_ADAPTER, *PHAL_GDMA_ADAPTER; + +*/ + +typedef struct _HAL_PCM_ADAPTER_ { + u32 Enable:1; + PCM_CTL_REG PcmCtl; + PCM_CHCNR03_REG PcmChCNR03; + PCM_TSR03_REG PcmTSR03; + PCM_BSIZE03_REG PcmBSize03; + u32 abc; + u8 PcmIndex; + u8 PcmCh; +}HAL_PCM_ADAPTER, *PHAL_PCM_ADAPTER; + + +typedef struct _HAL_PCM_OP_ { + VOID (*HalPcmOnOff)(VOID *Data); + BOOL (*HalPcmInit)(VOID *Data); + BOOL (*HalPcmSetting)(VOID *Data); + BOOL (*HalPcmEn)(VOID *Data); + BOOL (*HalPcmIsrEnAndDis) (VOID *Data); + BOOL (*HalPcmDumpReg)(VOID *Data); + BOOL (*HalPcm)(VOID *Data); +}HAL_PCM_OP, *PHAL_PCM_OP; + + +VOID HalPcmOpInit( + IN VOID *Data +); + + +#endif diff --git a/component/soc/realtek/8195a/fwlib/hal_peri_on.h b/component/soc/realtek/8195a/fwlib/hal_peri_on.h new file mode 100644 index 0000000..abcbdd0 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/hal_peri_on.h @@ -0,0 +1,451 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#ifndef _HAL_PERI_ON_H_ +#define _HAL_PERI_ON_H_ + +#define MASK_ALLON 0xFFFFFFFF + +#define HAL_PERI_ON_READ32(addr) HAL_READ32(PERI_ON_BASE, addr) +#define HAL_PERI_ON_WRITE32(addr, value) HAL_WRITE32(PERI_ON_BASE, addr, value) +#define HAL_PERI_ON_READ16(addr) HAL_READ16(PERI_ON_BASE, addr) +#define HAL_PERI_ON_WRITE16(addr, value) HAL_WRITE16(PERI_ON_BASE, addr, value) +#define HAL_PERI_ON_READ8(addr) HAL_READ8(PERI_ON_BASE, addr) +#define HAL_PERI_ON_WRITE8(addr, value) HAL_WRITE8(PERI_ON_BASE, addr, value) +#define HAL_PERL_ON_FUNC_CTRL(addr,value,ctrl) \ + HAL_PERI_ON_WRITE32(addr, ((HAL_PERI_ON_READ32(addr) & (~value))|((MASK_ALLON - ctrl + 1) & value))) +#define HAL_PERL_ON_PIN_SEL(addr,mask,value) \ + HAL_PERI_ON_WRITE32(addr, ((HAL_PERI_ON_READ32(addr) & (~mask)) | value)) + +//40 REG_SYS_REGU_CTRL0 +#define LDO25M_CTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_SYS_REGU_CTRL0, BIT_SYS_REGU_LDO25M_EN, ctrl) + +//A0 SYS_DEBUG_CTRL +#define DEBUG_PIN_CTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_SYS_DEBUG_CTRL, BIT_SYS_DBG_PIN_EN, ctrl) + +//A4 SYS_PINMUX_CTRL +#define SIC_PIN_CTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_SYS_PINMUX_CTRL, BIT_SIC_PIN_EN, ctrl) +#define EEPROM_PIN_CTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_SYS_PINMUX_CTRL, BIT_EEPROM_PIN_EN, ctrl) + + +//210 SOV_FUNC_EN +#define LXBUS_FCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_SOC_FUNC_EN, BIT_SOC_LXBUS_EN, ctrl) +#define FLASH_FCTRL(ctrl) { \ + if (!ctrl) { \ + HAL_READ32(SPI_FLASH_BASE,0);\ + }\ + HAL_PERL_ON_FUNC_CTRL(REG_SOC_FUNC_EN, BIT_SOC_FLASH_EN, ctrl);} + +#define MEM_CTRL_FCTRL(ctrl) { \ + if (!ctrl) { \ + HAL_READ32(SDR_SDRAM_BASE,0);\ + }\ + HAL_PERL_ON_FUNC_CTRL(REG_SOC_FUNC_EN, BIT_SOC_MEM_CTRL_EN, ctrl);} + +#define LOC_UART_FCTRL(ctrl) { \ + if (!ctrl) { \ + HAL_READ32(LOG_UART_REG_BASE,0);\ + }\ + HAL_PERL_ON_FUNC_CTRL(REG_SOC_FUNC_EN, BIT_SOC_LOG_UART_EN, ctrl);} + +#define GDMA0_FCTRL(ctrl) { \ + if (!ctrl) { \ + HAL_READ32(GDMA0_REG_BASE,0);\ + }\ + HAL_PERL_ON_FUNC_CTRL(REG_SOC_FUNC_EN, BIT_SOC_GDMA0_EN, ctrl);} + +#define GDMA1_FCTRL(ctrl) { \ + if (!ctrl) { \ + HAL_READ32(GDMA1_REG_BASE,0);\ + }\ + HAL_PERL_ON_FUNC_CTRL(REG_SOC_FUNC_EN, BIT_SOC_GDMA1_EN, ctrl);} + +#define GTIMER_FCTRL(ctrl) { \ + if (!ctrl) { \ + HAL_READ32(TIMER_REG_BASE,0);\ + }\ + HAL_PERL_ON_FUNC_CTRL(REG_SOC_FUNC_EN, BIT_SOC_GTIMER_EN, ctrl);} + +#define SECURITY_FCTRL(ctrl) { \ + if (!ctrl) { \ + HAL_READ32(CRYPTO_REG_BASE,0);\ + }\ + HAL_PERL_ON_FUNC_CTRL(REG_SOC_FUNC_EN, BIT_SOC_SECURITY_ENGINE_EN, ctrl);} + +//214 SOC_HCI_COM_FUNC_EN +#define SDIOD_ON_FCTRL(ctrl) { \ + if (!ctrl) { \ + HAL_READ32(SDIO_DEVICE_REG_BASE,0);\ + }\ + HAL_PERL_ON_FUNC_CTRL(REG_SOC_HCI_COM_FUNC_EN, BIT_SOC_HCI_SDIOD_ON_EN, ctrl);} + +#define SDIOD_OFF_FCTRL(ctrl) { \ + if (!ctrl) { \ + HAL_READ32(SDIO_DEVICE_REG_BASE,0);\ + }\ + HAL_PERL_ON_FUNC_CTRL(REG_SOC_HCI_COM_FUNC_EN, BIT_SOC_HCI_SDIOD_OFF_EN, ctrl);} + +#define SDIOH_FCTRL(ctrl) { \ + if (!ctrl) { \ + HAL_READ32(SDIO_HOST_REG_BASE,0);\ + }\ + HAL_PERL_ON_FUNC_CTRL(REG_SOC_HCI_COM_FUNC_EN, BIT_SOC_HCI_SDIOH_EN, ctrl);} + +#define SDIO_ON_RST_MASK(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_SOC_HCI_COM_FUNC_EN, BIT_SOC_HCI_SDIOD_ON_RST_MUX, ctrl) +#define OTG_FCTRL(ctrl) { \ + if (!ctrl) { \ + HAL_READ32(USB_OTG_REG_BASE,0);\ + }\ + HAL_PERL_ON_FUNC_CTRL(REG_SOC_HCI_COM_FUNC_EN, BIT_SOC_HCI_OTG_EN, ctrl);} + +#define OTG_RST_MASK(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_SOC_HCI_COM_FUNC_EN, BIT_SOC_HCI_OTG_RST_MUX, ctrl) +#define MII_FCTRL(ctrl) { \ + if (!ctrl) { \ + HAL_READ32(MII_REG_BASE,0);\ + }\ + HAL_PERL_ON_FUNC_CTRL(REG_SOC_HCI_COM_FUNC_EN, BIT_SOC_HCI_MII_EN, ctrl);} + +#define MII_MUX_SEL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_SOC_HCI_COM_FUNC_EN, BIT_SOC_HCI_SM_SEL, ctrl) +#define WL_MACON_FCTRL(ctrl) { \ + if (!ctrl) { \ + HAL_READ32(WIFI_REG_BASE,0);\ + }\ + HAL_PERL_ON_FUNC_CTRL(REG_SOC_HCI_COM_FUNC_EN, BIT_SOC_HCI_WL_MACON_EN, ctrl);} + +//218 SOC_PERI_FUNC0_EN +#define UART0_FCTRL(ctrl) { \ + if (!ctrl) { \ + HAL_READ32(UART0_REG_BASE,0);\ + }\ + HAL_PERL_ON_FUNC_CTRL(REG_SOC_PERI_FUNC0_EN, BIT_PERI_UART0_EN, ctrl);} + +#define UART1_FCTRL(ctrl) { \ + if (!ctrl) { \ + HAL_READ32(UART1_REG_BASE,0);\ + }\ + HAL_PERL_ON_FUNC_CTRL(REG_SOC_PERI_FUNC0_EN, BIT_PERI_UART1_EN, ctrl);} + +#define UART2_FCTRL(ctrl) { \ + if (!ctrl) { \ + HAL_READ32(UART2_REG_BASE,0);\ + }\ + HAL_PERL_ON_FUNC_CTRL(REG_SOC_PERI_FUNC0_EN, BIT_PERI_UART2_EN, ctrl);} + +#define SPI0_FCTRL(ctrl) { \ + if (!ctrl) { \ + HAL_READ32(SPI0_REG_BASE,0);\ + }\ + HAL_PERL_ON_FUNC_CTRL(REG_SOC_PERI_FUNC0_EN, BIT_PERI_SPI0_EN, ctrl);} + +#define SPI1_FCTRL(ctrl) { \ + if (!ctrl) { \ + HAL_READ32(SPI1_REG_BASE,0);\ + }\ + HAL_PERL_ON_FUNC_CTRL(REG_SOC_PERI_FUNC0_EN, BIT_PERI_SPI1_EN, ctrl);} + +#define SPI2_FCTRL(ctrl) { \ + if (!ctrl) { \ + HAL_READ32(SPI2_REG_BASE,0);\ + }\ + HAL_PERL_ON_FUNC_CTRL(REG_SOC_PERI_FUNC0_EN, BIT_PERI_SPI2_EN, ctrl);} + +#define I2C0_FCTRL(ctrl) { \ + if (!ctrl) { \ + HAL_READ32(I2C0_REG_BASE,0);\ + }\ + HAL_PERL_ON_FUNC_CTRL(REG_SOC_PERI_FUNC0_EN, BIT_PERI_I2C0_EN, ctrl);} + +#define I2C1_FCTRL(ctrl) { \ + if (!ctrl) { \ + HAL_READ32(I2C1_REG_BASE,0);\ + }\ + HAL_PERL_ON_FUNC_CTRL(REG_SOC_PERI_FUNC0_EN, BIT_PERI_I2C1_EN, ctrl);} + +#define I2C2_FCTRL(ctrl) { \ + if (!ctrl) { \ + HAL_READ32(I2C2_REG_BASE,0);\ + }\ + HAL_PERL_ON_FUNC_CTRL(REG_SOC_PERI_FUNC0_EN, BIT_PERI_I2C2_EN, ctrl);} + +#define I2C3_FCTRL(ctrl) { \ + if (!ctrl) { \ + HAL_READ32(I2C3_REG_BASE,0);\ + }\ + HAL_PERL_ON_FUNC_CTRL(REG_SOC_PERI_FUNC0_EN, BIT_PERI_I2C3_EN, ctrl);} + +#define I2S0_FCTRL(ctrl) { \ + if (!ctrl) { \ + HAL_READ32(I2S0_REG_BASE,0);\ + }\ + HAL_PERL_ON_FUNC_CTRL(REG_SOC_PERI_FUNC0_EN, BIT_PERI_I2S0_EN, ctrl);} + +#define I2S1_FCTRL(ctrl) { \ + if (!ctrl) { \ + HAL_READ32(I2S1_REG_BASE,0);\ + }\ + HAL_PERL_ON_FUNC_CTRL(REG_SOC_PERI_FUNC0_EN, BIT_PERI_I2S1_EN, ctrl);} + +#define PCM0_FCTRL(ctrl) { \ + if (!ctrl) { \ + HAL_READ32(PCM0_REG_BASE,0);\ + }\ + HAL_PERL_ON_FUNC_CTRL(REG_SOC_PERI_FUNC0_EN, BIT_PERI_PCM0_EN, ctrl);} + +#define PCM1_FCTRL(ctrl) { \ + if (!ctrl) { \ + HAL_READ32(PCM1_REG_BASE,0);\ + }\ + HAL_PERL_ON_FUNC_CTRL(REG_SOC_PERI_FUNC0_EN, BIT_PERI_PCM1_EN, ctrl);} + +//21C SOC_PERI_FUNC1_EN +#define ADC0_FCTRL(ctrl) { \ + if (!ctrl) { \ + HAL_READ32(ADC_REG_BASE,0);\ + }\ + HAL_PERL_ON_FUNC_CTRL(REG_SOC_PERI_FUNC1_EN, BIT_PERI_ADC0_EN, ctrl);} + +#define DAC0_FCTRL(ctrl) { \ + if (!ctrl) { \ + HAL_READ32(DAC_REG_BASE,0);\ + }\ + HAL_PERL_ON_FUNC_CTRL(REG_SOC_PERI_FUNC1_EN, BIT_PERI_DAC0_EN, ctrl);} + +#define DAC1_FCTRL(ctrl) { \ + if (!ctrl) { \ + HAL_READ32(DAC_REG_BASE,0);\ + }\ + HAL_PERL_ON_FUNC_CTRL(REG_SOC_PERI_FUNC1_EN, BIT_PERI_DAC1_EN, ctrl);} + +#define GPIO_FCTRL(ctrl) { \ + if (!ctrl) { \ + HAL_READ32(GPIO_REG_BASE,0);\ + }\ + HAL_PERL_ON_FUNC_CTRL(REG_SOC_PERI_FUNC1_EN, BIT_PERI_GPIO_EN, ctrl);} + +//220 SOC_PERI_BD_FUNC0_EN +#define UART0_BD_FCTRL(ctrl) { \ + if (!ctrl) { \ + HAL_READ32(UART0_REG_BASE,0);\ + }\ + HAL_PERL_ON_FUNC_CTRL(REG_SOC_PERI_BD_FUNC0_EN, BIT_PERI_UART0_BD_EN, ctrl);} + +#define UART1_BD_FCTRL(ctrl) { \ + if (!ctrl) { \ + HAL_READ32(UART1_REG_BASE,0);\ + }\ + HAL_PERL_ON_FUNC_CTRL(REG_SOC_PERI_BD_FUNC0_EN, BIT_PERI_UART1_BD_EN, ctrl);} + +#define UART2_BD_FCTRL(ctrl) { \ + if (!ctrl) { \ + HAL_READ32(UART2_REG_BASE,0);\ + }\ + HAL_PERL_ON_FUNC_CTRL(REG_SOC_PERI_BD_FUNC0_EN, BIT_PERI_UART2_BD_EN, ctrl);} + +//230 PESOC_CLK_CTRL +#define ACTCK_CPU_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_CLK_CTRL, BIT_SOC_CKE_PLFM, ctrl) +#define ACTCK_TRACE_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_CLK_CTRL, BIT_SOC_ACTCK_TRACE_EN, ctrl) +#define SLPCK_TRACE_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_CLK_CTRL, BIT_SOC_SLPCK_TRACE_EN, ctrl) +#define ACTCK_VENDOR_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_CLK_CTRL, BIT_SOC_ACTCK_VENDOR_REG_EN, ctrl) +#define SLPCK_VENDOR_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_CLK_CTRL, BIT_SOC_SLPCK_VENDOR_REG_EN, ctrl) +#define ACTCK_FLASH_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_CLK_CTRL, BIT_SOC_ACTCK_FLASH_EN, ctrl) +#define SLPCK_FLASH_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_CLK_CTRL, BIT_SOC_SLPCK_FLASH_EN, ctrl) +#define ACTCK_SDR_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_CLK_CTRL, BIT_SOC_ACTCK_SDR_EN, ctrl) +#define SLPCK_SDR_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_CLK_CTRL, BIT_SOC_SLPCK_SDR_EN, ctrl) +#define ACTCK_LOG_UART_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_CLK_CTRL, BIT_SOC_ACTCK_LOG_UART_EN, ctrl) +#define SLPCK_LOG_UART_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_CLK_CTRL, BIT_SOC_SLPCK_LOG_UART_EN, ctrl) +#define ACTCK_TIMER_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_CLK_CTRL, BIT_SOC_ACTCK_TIMER_EN, ctrl) +#define SLPCK_TIMER_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_CLK_CTRL, BIT_SOC_SLPCK_TIMER_EN, ctrl) +#define ACTCK_GDMA0_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_CLK_CTRL, BIT_SOC_ACTCK_GDMA0_EN, ctrl) +#define SLPCK_GDMA0_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_CLK_CTRL, BIT_SOC_SLPCK_GDMA0_EN, ctrl) +#define ACTCK_GDMA1_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_CLK_CTRL, BIT_SOC_ACTCK_GDMA1_EN, ctrl) +#define SLPCK_GDMA1_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_CLK_CTRL, BIT_SOC_SLPCK_GDMA1_EN, ctrl) +#define ACTCK_GPIO_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_CLK_CTRL, BIT_SOC_ACTCK_GPIO_EN, ctrl) +#define SLPCK_GPIO_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_CLK_CTRL, BIT_SOC_SLPCK_GPIO_EN, ctrl) +#define ACTCK_BTCMD_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_CLK_CTRL, BIT_SOC_ACTCK_BTCMD_EN, ctrl) +#define SLPCK_BTCMD_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_CLK_CTRL, BIT_SOC_SLPCK_BTCMD_EN, ctrl) + +//234 PESOC_PERI_CLK_CTRL0 +#define ACTCK_UART0_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_PERI_CLK_CTRL0, BIT_SOC_ACTCK_UART0_EN, ctrl) +#define SLPCK_UART0_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_PERI_CLK_CTRL0, BIT_SOC_SLPCK_UART0_EN, ctrl) +#define ACTCK_UART1_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_PERI_CLK_CTRL0, BIT_SOC_ACTCK_UART1_EN, ctrl) +#define SLPCK_UART1_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_PERI_CLK_CTRL0, BIT_SOC_SLPCK_UART1_EN, ctrl) +#define ACTCK_UART2_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_PERI_CLK_CTRL0, BIT_SOC_ACTCK_UART2_EN, ctrl) +#define SLPCK_UART2_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_PERI_CLK_CTRL0, BIT_SOC_SLPCK_UART2_EN, ctrl) +#define ACTCK_SPI0_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_PERI_CLK_CTRL0, BIT_SOC_ACTCK_SPI0_EN, ctrl) +#define SLPCK_SPI0_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_PERI_CLK_CTRL0, BIT_SOC_SLPCK_SPI0_EN, ctrl) +#define ACTCK_SPI1_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_PERI_CLK_CTRL0, BIT_SOC_ACTCK_SPI1_EN, ctrl) +#define SLPCK_SPI1_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_PERI_CLK_CTRL0, BIT_SOC_SLPCK_SPI1_EN, ctrl) +#define ACTCK_SPI2_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_PERI_CLK_CTRL0, BIT_SOC_ACTCK_SPI2_EN, ctrl) +#define SLPCK_SPI2_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_PERI_CLK_CTRL0, BIT_SOC_SLPCK_SPI2_EN, ctrl) + +//238 PESOC_PERI_CLK_CTRL1 +#define ACTCK_I2C0_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_PERI_CLK_CTRL1, BIT_SOC_ACTCK_I2C0_EN, ctrl) +#define SLPCK_I2C0_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_PERI_CLK_CTRL1, BIT_SOC_SLPCK_I2C0_EN, ctrl) +#define ACTCK_I2C1_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_PERI_CLK_CTRL1, BIT_SOC_ACTCK_I2C1_EN, ctrl) +#define SLPCK_I2C1_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_PERI_CLK_CTRL1, BIT_SOC_SLPCK_I2C1_EN, ctrl) +#define ACTCK_I2C2_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_PERI_CLK_CTRL1, BIT_SOC_ACTCK_I2C2_EN, ctrl) +#define SLPCK_I2C2_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_PERI_CLK_CTRL1, BIT_SOC_SLPCK_I2C2_EN, ctrl) +#define ACTCK_I2C3_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_PERI_CLK_CTRL1, BIT_SOC_ACTCK_I2C3_EN, ctrl) +#define SLPCK_I2C3_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_PERI_CLK_CTRL1, BIT_SOC_SLPCK_I2C3_EN, ctrl) +#define ACTCK_I2S_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_PERI_CLK_CTRL1, BIT_SOC_ACTCK_I2S_EN, ctrl) +#define SLPCK_I2S_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_PERI_CLK_CTRL1, BIT_SOC_SLPCK_I2S_EN, ctrl) +#define ACTCK_PCM_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_PERI_CLK_CTRL1, BIT_SOC_ACTCK_PCM_EN, ctrl) +#define SLPCK_PCM_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_PERI_CLK_CTRL1, BIT_SOC_SLPCK_PCM_EN, ctrl) +#define ACTCK_ADC_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_PERI_CLK_CTRL1, BIT_SOC_ACTCK_ADC_EN, ctrl) +#define SLPCK_ADC_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_PERI_CLK_CTRL1, BIT_SOC_SLPCK_ADC_EN, ctrl) +#define ACTCK_DAC_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_PERI_CLK_CTRL1, BIT_SOC_ACTCK_DAC_EN, ctrl) +#define SLPCK_DAC_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_PERI_CLK_CTRL1, BIT_SOC_SLPCK_DAC_EN, ctrl) + +//240 PESOC_HCI_CLK_CTRL0 +#define ACTCK_SDIOD_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_HCI_CLK_CTRL0, BIT_SOC_ACTCK_SDIO_DEV_EN, ctrl) +#define SLPCK_SDIOD_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_HCI_CLK_CTRL0, BIT_SOC_SLPCK_SDIO_DEV_EN, ctrl) +#define ACTCK_SDIOH_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_HCI_CLK_CTRL0, BIT_SOC_ACTCK_SDIO_HST_EN, ctrl) +#define SLPCK_SDIOH_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_HCI_CLK_CTRL0, BIT_SOC_SLPCK_SDIO_HST_EN, ctrl) +#define ACTCK_OTG_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_HCI_CLK_CTRL0, BIT_SOC_ACTCK_OTG_EN, ctrl) +#define SLPCK_OTG_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_HCI_CLK_CTRL0, BIT_SOC_SLPCK_OTG_EN, ctrl) +#define ACTCK_MII_MPHY_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_HCI_CLK_CTRL0, BIT_SOC_ACTCK_MII_MPHY_EN, ctrl) +#define SLPCK_MII_MPHY_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_HCI_CLK_CTRL0, BIT_SOC_SLPCK_MII_MPHY_EN, ctrl) + +//244 PESOC_COM_CLK_CTRL1 +#define ACTCK_WL_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_COM_CLK_CTRL1, BIT_SOC_ACTCK_WL_EN, ctrl) +#define SLPCK_WL_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_COM_CLK_CTRL1, BIT_SOC_SLPCK_WL_EN, ctrl) +#define ACTCK_SEC_ENG_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_COM_CLK_CTRL1, BIT_SOC_ACTCK_SECURITY_ENG_EN, ctrl) +#define SLPCK_SEC_ENG_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_COM_CLK_CTRL1, BIT_SOC_SLPCK_SECURITY_ENG_EN, ctrl) +#define ACTCK_NFC_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_COM_CLK_CTRL1, BIT_SOC_ACTCK_NFC_EN, ctrl) +#define SLPCK_NFC_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_COM_CLK_CTRL1, BIT_SOC_SLPCK_NFC_EN, ctrl) +#define NFC_CAL_CCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_COM_CLK_CTRL1, BIT_SOC_NFC_CAL_EN, ctrl) + +//250 REG_PERI_CLK_SEL +#define TRACE_CLK_SEL(num) HAL_PERL_ON_PIN_SEL(REG_PESOC_CLK_SEL, (BIT_MASK_PESOC_TRACE_CK_SEL << BIT_SHIFT_PESOC_TRACE_CK_SEL), BIT_PESOC_TRACE_CK_SEL(num)) +#define FLASH_CLK_SEL(num) HAL_PERL_ON_PIN_SEL(REG_PESOC_CLK_SEL, (BIT_MASK_PESOC_FLASH_CK_SEL << BIT_SHIFT_PESOC_FLASH_CK_SEL), BIT_PESOC_FLASH_CK_SEL(num)) +#define SDR_CLK_SEL(num) HAL_PERL_ON_PIN_SEL(REG_PESOC_CLK_SEL, (BIT_MASK_PESOC_SDR_CK_SEL << BIT_SHIFT_PESOC_SDR_CK_SEL), BIT_PESOC_SDR_CK_SEL(num)) +#define I2C_SCLK_SEL(num) HAL_PERL_ON_PIN_SEL(REG_PESOC_CLK_SEL, (BIT_MASK_PESOC_PERI_SCLK_SEL << BIT_SHIFT_PESOC_PERI_SCLK_SEL), BIT_PESOC_PERI_SCLK_SEL(num)) + +//270 REG_OSC32K_CTRL +#define OSC32K_CKGEN_CTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_OSC32K_CTRL, BIT_32K_POW_CKGEN_EN, ctrl) + +//280 REG_UART_MUX_CTRL +#define UART0_PIN_CTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_UART_MUX_CTRL, BIT_UART0_PIN_EN, ctrl) +#define UART0_PIN_SEL(num) HAL_PERL_ON_PIN_SEL(REG_UART_MUX_CTRL, (BIT_MASK_UART0_PIN_SEL << BIT_SHIFT_UART0_PIN_SEL), BIT_UART0_PIN_SEL(num)) +#define UART1_PIN_CTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_UART_MUX_CTRL, BIT_UART1_PIN_EN, ctrl) +#define UART1_PIN_SEL(num) HAL_PERL_ON_PIN_SEL(REG_UART_MUX_CTRL, (BIT_MASK_UART1_PIN_SEL << BIT_SHIFT_UART1_PIN_SEL), BIT_UART1_PIN_SEL(num)) +#define UART2_PIN_CTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_UART_MUX_CTRL, BIT_UART2_PIN_EN, ctrl) +#define UART2_PIN_SEL(num) HAL_PERL_ON_PIN_SEL(REG_UART_MUX_CTRL, (BIT_MASK_UART2_PIN_SEL << BIT_SHIFT_UART2_PIN_SEL), BIT_UART2_PIN_SEL(num)) + +//284 REG_SPI_MUX_CTRL +#define SPI0_PIN_CTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_SPI_MUX_CTRL, BIT_SPI0_PIN_EN, ctrl) +#define SPI0_PIN_SEL(num) HAL_PERL_ON_PIN_SEL(REG_SPI_MUX_CTRL, (BIT_MASK_SPI0_PIN_SEL << BIT_SHIFT_SPI0_PIN_SEL), BIT_SPI0_PIN_SEL(num)) +#define SPI1_PIN_CTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_SPI_MUX_CTRL, BIT_SPI1_PIN_EN, ctrl) +#define SPI1_PIN_SEL(num) HAL_PERL_ON_PIN_SEL(REG_SPI_MUX_CTRL, (BIT_MASK_SPI1_PIN_SEL << BIT_SHIFT_SPI1_PIN_SEL), BIT_SPI1_PIN_SEL(num)) +#define SPI2_PIN_CTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_SPI_MUX_CTRL, BIT_SPI2_PIN_EN, ctrl) +#define SPI2_PIN_SEL(num) HAL_PERL_ON_PIN_SEL(REG_SPI_MUX_CTRL, (BIT_MASK_SPI2_PIN_SEL << BIT_SHIFT_SPI2_PIN_SEL), BIT_SPI2_PIN_SEL(num)) +#define SPI0_MULTI_CS_CTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_SPI_MUX_CTRL, BIT_SPI0_MULTI_CS_EN, ctrl) + +//288 REG_I2C_MUX_CTRL +#define I2C0_PIN_CTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_I2C_MUX_CTRL, BIT_I2C0_PIN_EN, ctrl) +#define I2C0_PIN_SEL(num) HAL_PERL_ON_PIN_SEL(REG_I2C_MUX_CTRL, (BIT_MASK_I2C0_PIN_SEL << BIT_SHIFT_I2C0_PIN_SEL), BIT_I2C0_PIN_SEL(num)) +#define I2C1_PIN_CTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_I2C_MUX_CTRL, BIT_I2C1_PIN_EN, ctrl) +#define I2C1_PIN_SEL(num) HAL_PERL_ON_PIN_SEL(REG_I2C_MUX_CTRL, (BIT_MASK_I2C1_PIN_SEL << BIT_SHIFT_I2C1_PIN_SEL), BIT_I2C1_PIN_SEL(num)) +#define I2C2_PIN_CTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_I2C_MUX_CTRL, BIT_I2C2_PIN_EN, ctrl) +#define I2C2_PIN_SEL(num) HAL_PERL_ON_PIN_SEL(REG_I2C_MUX_CTRL, (BIT_MASK_I2C2_PIN_SEL << BIT_SHIFT_I2C2_PIN_SEL), BIT_I2C2_PIN_SEL(num)) +#define I2C3_PIN_CTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_I2C_MUX_CTRL, BIT_I2C3_PIN_EN, ctrl) +#define I2C3_PIN_SEL(num) HAL_PERL_ON_PIN_SEL(REG_I2C_MUX_CTRL, (BIT_MASK_I2C3_PIN_SEL << BIT_SHIFT_I2C3_PIN_SEL), BIT_I2C3_PIN_SEL(num)) + +//28C REG_I2S_MUX_CTRL +#define I2S0_PIN_CTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_I2S_MUX_CTRL, BIT_I2S0_PIN_EN, ctrl) +#define I2S0_MCK_CTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_I2S_MUX_CTRL, BIT_I2S0_MCK_EN, ctrl) +#define I2S0_PIN_SEL(num) HAL_PERL_ON_PIN_SEL(REG_I2S_MUX_CTRL, (BIT_MASK_I2S0_PIN_SEL << BIT_SHIFT_I2S0_PIN_SEL), BIT_I2S0_PIN_SEL(num)) +#define I2S1_PIN_CTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_I2S_MUX_CTRL, BIT_I2S1_PIN_EN, ctrl) +#define I2S1_MCK_CTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_I2S_MUX_CTRL, BIT_I2S1_MCK_EN, ctrl) +#define I2S1_PIN_SEL(num) HAL_PERL_ON_PIN_SEL(REG_I2S_MUX_CTRL, (BIT_MASK_I2S1_PIN_SEL << BIT_SHIFT_I2S1_PIN_SEL), BIT_I2S1_PIN_SEL(num)) +#define PCM0_PIN_CTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_I2S_MUX_CTRL, BIT_PCM0_PIN_EN, ctrl) +#define PCM0_PIN_SEL(num) HAL_PERL_ON_PIN_SEL(REG_I2S_MUX_CTRL, (BIT_MASK_PCM0_PIN_SEL << BIT_SHIFT_PCM0_PIN_SEL), BIT_PCM0_PIN_SEL(num)) +#define PCM1_PIN_CTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_I2S_MUX_CTRL, BIT_PCM1_PIN_EN, ctrl) +#define PCM1_PIN_SEL(num) HAL_PERL_ON_PIN_SEL(REG_I2S_MUX_CTRL, (BIT_MASK_PCM1_PIN_SEL << BIT_SHIFT_PCM1_PIN_SEL), BIT_PCM1_PIN_SEL(num)) + +//2A0 HCI_PINMUX_CTRL +#define SDIOD_PIN_FCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_HCI_PINMUX_CTRL, BIT_HCI_SDIOD_PIN_EN, ctrl) +#define SDIOH_PIN_FCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_HCI_PINMUX_CTRL, BIT_HCI_SDIOH_PIN_EN, ctrl) +#define MII_PIN_FCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_HCI_PINMUX_CTRL, BIT_HCI_MII_PIN_EN, ctrl) + +//2A4 WL_PINMUX_CTRL +#define LED_PIN_FCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_WL_PINMUX_CTRL, BIT_WL_LED_PIN_EN, ctrl) +#define LED_PIN_SEL(num) HAL_PERL_ON_PIN_SEL(REG_WL_PINMUX_CTRL, (BIT_MASK_WL_LED_PIN_SEL << BIT_SHIFT_WL_LED_PIN_SEL), BIT_WL_LED_PIN_SEL(num)) +#define ANT0_PIN_FCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_WL_PINMUX_CTRL, BIT_WL_ANT0_PIN_EN, ctrl) +#define ANT1_PIN_FCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_WL_PINMUX_CTRL, BIT_WL_ANT1_PIN_EN, ctrl) +#define BTCOEX_PIN_FCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_WL_PINMUX_CTRL, BIT_WL_BTCOEX_PIN_EN, ctrl) +#define BTCMD_PIN_FCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_WL_PINMUX_CTRL, BIT_WL_BTCMD_PIN_EN, ctrl) +#define NFC_PIN_FCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_WL_PINMUX_CTRL, BIT_NFC_PIN_EN, ctrl) + +//2AC PWM_PINMUX_CTRL +#define PWM0_PIN_FCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PWM_PINMUX_CTRL, BIT_PWM0_PIN_EN, ctrl) +#define PWM0_PIN_SEL(num) HAL_PERL_ON_PIN_SEL(REG_PWM_PINMUX_CTRL, (BIT_MASK_PWM0_PIN_SEL << BIT_SHIFT_PWM0_PIN_SEL), BIT_PWM0_PIN_SEL(num)) +#define PWM1_PIN_FCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PWM_PINMUX_CTRL, BIT_PWM1_PIN_EN, ctrl) +#define PWM1_PIN_SEL(num) HAL_PERL_ON_PIN_SEL(REG_PWM_PINMUX_CTRL, (BIT_MASK_PWM1_PIN_SEL << BIT_SHIFT_PWM1_PIN_SEL), BIT_PWM1_PIN_SEL(num)) +#define PWM2_PIN_FCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PWM_PINMUX_CTRL, BIT_PWM2_PIN_EN, ctrl) +#define PWM2_PIN_SEL(num) HAL_PERL_ON_PIN_SEL(REG_PWM_PINMUX_CTRL, (BIT_MASK_PWM2_PIN_SEL << BIT_SHIFT_PWM2_PIN_SEL), BIT_PWM2_PIN_SEL(num)) +#define PWM3_PIN_FCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PWM_PINMUX_CTRL, BIT_PWM3_PIN_EN, ctrl) +#define PWM3_PIN_SEL(num) HAL_PERL_ON_PIN_SEL(REG_PWM_PINMUX_CTRL, (BIT_MASK_PWM3_PIN_SEL << BIT_SHIFT_PWM3_PIN_SEL), BIT_PWM3_PIN_SEL(num)) +#define ETE0_PIN_FCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PWM_PINMUX_CTRL, BIT_ETE0_PIN_EN, ctrl) +#define ETE0_PIN_SEL(num) HAL_PERL_ON_PIN_SEL(REG_PWM_PINMUX_CTRL, (BIT_MASK_ETE0_PIN_SEL << BIT_SHIFT_ETE0_PIN_SEL), BIT_ETE0_PIN_SEL(num)) +#define ETE1_PIN_FCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PWM_PINMUX_CTRL, BIT_ETE1_PIN_EN, ctrl) +#define ETE1_PIN_SEL(num) HAL_PERL_ON_PIN_SEL(REG_PWM_PINMUX_CTRL, (BIT_MASK_ETE1_PIN_SEL << BIT_SHIFT_ETE1_PIN_SEL), BIT_ETE1_PIN_SEL(num)) +#define ETE2_PIN_FCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PWM_PINMUX_CTRL, BIT_ETE2_PIN_EN, ctrl) +#define ETE2_PIN_SEL(num) HAL_PERL_ON_PIN_SEL(REG_PWM_PINMUX_CTRL, (BIT_MASK_ETE2_PIN_SEL << BIT_SHIFT_ETE2_PIN_SEL), BIT_ETE2_PIN_SEL(num)) +#define ETE3_PIN_FCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PWM_PINMUX_CTRL, BIT_ETE3_PIN_EN, ctrl) +#define ETE3_PIN_SEL(num) HAL_PERL_ON_PIN_SEL(REG_PWM_PINMUX_CTRL, (BIT_MASK_ETE3_PIN_SEL << BIT_SHIFT_ETE3_PIN_SEL), BIT_ETE3_PIN_SEL(num)) + +//2C0 CPU_PERIPHERAL_CTRL +#define SPI_FLASH_PIN_FCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_CPU_PERIPHERAL_CTRL, BIT_SPI_FLSH_PIN_EN, ctrl) +#define SPI_FLASH_PIN_SEL(num) HAL_PERL_ON_PIN_SEL(REG_CPU_PERIPHERAL_CTRL, (BIT_MASK_SPI_FLSH_PIN_SEL << BIT_SHIFT_SPI_FLSH_PIN_SEL), BIT_SPI_FLSH_PIN_SEL(num)) +#define SDR_PIN_FCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_CPU_PERIPHERAL_CTRL, BIT_SDR_PIN_EN, ctrl) +#define TRACE_PIN_FCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_CPU_PERIPHERAL_CTRL, BIT_TRACE_PIN_EN, ctrl) +#define LOG_UART_PIN_FCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_CPU_PERIPHERAL_CTRL, BIT_LOG_UART_PIN_EN, ctrl) +#define LOG_UART_IR_FCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_CPU_PERIPHERAL_CTRL, BIT_LOG_UART_IR_EN, ctrl) + +//300 REG_PESOC_MEM_CTRL +#define SDR_DDL_FCTRL(ctrl) HAL_PERL_ON_PIN_SEL(REG_PESOC_MEM_CTRL, (BIT_MASK_PESOC_SDR_DDL_CTRL << BIT_SHIFT_PESOC_SDR_DDL_CTRL), BIT_PESOC_SDR_DDL_CTRL(ctrl)) +#define FLASH_DDL_FCTRL(ctrl) HAL_PERL_ON_PIN_SEL(REG_PESOC_MEM_CTRL, (BIT_MASK_PESOC_FLASH_DDL_CTRL << BIT_SHIFT_PESOC_FLASH_DDL_CTRL), BIT_PESOC_FLASH_DDL_CTRL(ctrl)) + +//304 REG_PESOC_SOC_CTRL +#define SRAM_MUX_CFG(num) HAL_PERL_ON_PIN_SEL(REG_PESOC_SOC_CTRL, (BIT_MASK_PESOC_SRAM_MUX_CFG << BIT_SHIFT_PESOC_SRAM_MUX_CFG), BIT_PESOC_SRAM_MUX_CFG(num)) +#define LX_WL_SWAP_CTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_SOC_CTRL, BIT_PESOC_LX_WL_SWAP_SEL, ctrl) +#define LX_MST_SWAP_CTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_SOC_CTRL, BIT_PESOC_LX_MST_SWAP_SEL, ctrl) +#define LX_SLV_SWAP_CTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_SOC_CTRL, BIT_PESOC_LX_SLV_SWAP_SEL, ctrl) +#define MII_LX_WRAPPER_FCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_SOC_CTRL, BIT_PESOC_MII_LX_WRAPPER_EN, ctrl) +#define MII_LX_MST_SWAP_CTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_SOC_CTRL, BIT_PESOC_MII_LX_MST_SWAP_SEL, ctrl) +#define MII_LX_SLV_SWAP_CTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_SOC_CTRL, BIT_PESOC_MII_LX_SLV_SWAP_SEL, ctrl) +#define GDMA_CFG(num) HAL_PERL_ON_PIN_SEL(REG_PESOC_SOC_CTRL, (BIT_MASK_PESOC_GDMA_CFG << BIT_SHIFT_PESOC_GDMA_CFG), BIT_PESOC_GDMA_CFG(num)) + +//308 PESOC_PERI_CTRL +#define SPI_RN_FCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PESOC_PERI_CTRL, BIT_SOC_FUNC_SPI_RN, ctrl) + +//320 GPIO_SHTDN_CTRL +#define GPIO_GPA_SHTDN_N_FCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_GPIO_SHTDN_CTRL, BIT_GPIO_GPA_SHTDN_N, ctrl) +#define GPIO_GPB_SHTDN_N_FCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_GPIO_SHTDN_CTRL, BIT_GPIO_GPB_SHTDN_N, ctrl) +#define GPIO_GPC_SHTDN_N_FCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_GPIO_SHTDN_CTRL, BIT_GPIO_GPC_SHTDN_N, ctrl) +#define GPIO_GPD_SHTDN_N_FCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_GPIO_SHTDN_CTRL, BIT_GPIO_GPD_SHTDN_N, ctrl) +#define GPIO_GPE_SHTDN_N_FCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_GPIO_SHTDN_CTRL, BIT_GPIO_GPE_SHTDN_N, ctrl) +#define GPIO_GPF_SHTDN_N_FCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_GPIO_SHTDN_CTRL, BIT_GPIO_GPF_SHTDN_N, ctrl) +#define GPIO_GPG_SHTDN_N_FCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_GPIO_SHTDN_CTRL, BIT_GPIO_GPG_SHTDN_N, ctrl) +#define GPIO_GPH_SHTDN_N_FCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_GPIO_SHTDN_CTRL, BIT_GPIO_GPH_SHTDN_N, ctrl) +#define GPIO_GPI_SHTDN_N_FCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_GPIO_SHTDN_CTRL, BIT_GPIO_GPI_SHTDN_N, ctrl) +#define GPIO_GPJ_SHTDN_N_FCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_GPIO_SHTDN_CTRL, BIT_GPIO_GPJ_SHTDN_N, ctrl) +#define GPIO_GPK_SHTDN_N_FCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_GPIO_SHTDN_CTRL, BIT_GPIO_GPK_SHTDN_N, ctrl) + +//374 +#define EGTIM_FCTRL(ctrl) HAL_PERL_ON_FUNC_CTRL(REG_PERI_EGTIM_CTRL, BIT_PERI_EGTIM_EN, ctrl) +#define EGTIM_RSIG_SEL(num) HAL_PERL_ON_PIN_SEL(REG_PERI_EGTIM_CTRL, (BIT_MASK_PERI_EGTIM_REF_SIG_SEL << BIT_SHIFT_PERI_EGTIM_REF_SIG_SEL), BIT_PERI_EGTIM_REF_SIG_SEL(num)) +#define EGTIME_PIN_G0_OPT_SEL(num) HAL_PERL_ON_PIN_SEL(REG_PERI_EGTIM_CTRL, (BIT_MASK_PERI_EGTIM_PIN_GROUP0_OPT_SEL << BIT_SHIFT_PERI_EGTIM_PIN_GROUP0_OPT_SEL), BIT_PERI_EGTIM_PIN_GROUP0_OPT_SEL(num)) +#define EGTIME_PIN_G1_OPT_SEL(num) HAL_PERL_ON_PIN_SEL(REG_PERI_EGTIM_CTRL, (BIT_MASK_PERI_EGTIM_PIN_GROUP1_OPT_SEL << BIT_SHIFT_PERI_EGTIM_PIN_GROUP1_OPT_SEL), BIT_PERI_EGTIM_PIN_GROUP1_OPT_SEL(num)) +#define EGTIME_PIN_G2_OPT_SEL(num) HAL_PERL_ON_PIN_SEL(REG_PERI_EGTIM_CTRL, (BIT_MASK_PERI_EGTIM_PIN_GROUP2_OPT_SEL << BIT_SHIFT_PERI_EGTIM_PIN_GROUP2_OPT_SEL), BIT_PERI_EGTIM_PIN_GROUP2_OPT_SEL(num)) + + +#endif //_HAL_PERI_ON_H_ + diff --git a/component/soc/realtek/8195a/fwlib/hal_pinmux.h b/component/soc/realtek/8195a/fwlib/hal_pinmux.h new file mode 100644 index 0000000..9a6596e --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/hal_pinmux.h @@ -0,0 +1,60 @@ +#ifndef _HAL_PINMUX_ +#define _HAL_PINMUX_ + + +//Function Index +#define UART0 0 +#define UART1 1 +#define UART2 2 +#define SPI0 8 +#define SPI1 9 +#define SPI2 10 +#define SPI0_MCS 15 +#define I2C0 16 +#define I2C1 17 +#define I2C2 18 +#define I2C3 19 +#define I2S0 24 +#define I2S1 25 +#define PCM0 28 +#define PCM1 29 +#define SDIOD 64 +#define SDIOH 65 +#define MII 88 +#define WL_LED 96 +#define WL_ANT0 104 +#define WL_ANT1 105 +#define WL_BTCOEX 108 +#define WL_BTCMD 109 +#define NFC 112 +#define PWM0 160 +#define PWM1 161 +#define PWM2 162 +#define PWM3 163 +#define ETE0 164 +#define ETE1 165 +#define ETE2 166 +#define ETE3 167 +#define EGTIM 168 +#define SPI_FLASH 196 +#define SDR 200 +#define JTAG 216 +#define TRACE 217 +#define LOG_UART 220 +#define LOG_UART_IR 221 +#define SIC 224 +#define EEPROM 225 +#define DEBUG 226 + +//Location Index(Pin Mux Selection) +#define S0 0 +#define S1 1 +#define S2 2 +#define S3 3 + +_LONG_CALL_ u8 +HalPinCtrlRtl8195A( + IN u32 Function, + IN u32 PinLocation, + IN BOOL Operation); +#endif //_HAL_PINMUX_ \ No newline at end of file diff --git a/component/soc/realtek/8195a/fwlib/hal_platform.h b/component/soc/realtek/8195a/fwlib/hal_platform.h new file mode 100644 index 0000000..d0979d7 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/hal_platform.h @@ -0,0 +1,102 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + + +#ifndef _HAL_PLATFORM_ +#define _HAL_PLATFORM_ + +#define ROMVERSION 0x03 +#define ROMINFORMATION (ROMVERSION) + +#define SYSTEM_CLK PLATFORM_CLOCK + +#define SDR_SDRAM_BASE 0x30000000 +#define SYSTEM_CTRL_BASE 0x40000000 +#define PERI_ON_BASE 0x40000000 +#define VENDOR_REG_BASE 0x40002800 +#define SPI_FLASH_BASE 0x98000000 +#define SDR_CTRL_BASE 0x40005000 + +#define PERIPHERAL_IRQ_STATUS 0x04 +#define PERIPHERAL_IRQ_MODE 0x08 +#define PERIPHERAL_IRQ_EN 0x0C +#define LP_PERI_EXT_IRQ_STATUS 0x24 +#define LP_PERI_EXT_IRQ_MODE 0x28 +#define LP_PERI_EXT_IRQ_EN 0x2C + +#define PERIPHERAL_IRQ_ALL_LEVEL 0 + +#define TIMER_CLK 32*1000 + +//3 Peripheral IP Base Address +#define GPIO_REG_BASE 0x40001000 +#define TIMER_REG_BASE 0x40002000 +#define NFC_INTERFACE_BASE 0x40002400 +#define LOG_UART_REG_BASE 0x40003000 +#define I2C2_REG_BASE 0x40003400 +#define I2C3_REG_BASE 0x40003800 +#define SPI_FLASH_CTRL_BASE 0x40006000 +#define ADC_REG_BASE 0x40010000 +#define DAC_REG_BASE 0x40011000 +#define UART0_REG_BASE 0x40040000 +#define UART1_REG_BASE 0x40040400 +#define UART2_REG_BASE 0x40040800 +#define SPI0_REG_BASE 0x40042000 +#define SPI1_REG_BASE 0x40042400 +#define SPI2_REG_BASE 0x40042800 +#define I2C0_REG_BASE 0x40044000 +#define I2C1_REG_BASE 0x40044400 +#define SDIO_DEVICE_REG_BASE 0x40050000 +#define MII_REG_BASE 0x40050000 +#define SDIO_HOST_REG_BASE 0x40058000 +#define GDMA0_REG_BASE 0x40060000 +#define GDMA1_REG_BASE 0x40061000 +#define I2S0_REG_BASE 0x40062000 +#define I2S1_REG_BASE 0x40063000 +#define PCM0_REG_BASE 0x40064000 +#define PCM1_REG_BASE 0x40065000 +#define CRYPTO_REG_BASE 0x40070000 +#define WIFI_REG_BASE 0x40080000 +#define USB_OTG_REG_BASE 0x400C0000 + +#define GDMA1_REG_OFF 0x1000 +#define I2S1_REG_OFF 0x1000 +#define PCM1_REG_OFF 0x1000 +#define SSI_REG_OFF 0x400 +#define RUART_REG_OFF 0x400 + +#define CPU_CLK_TYPE_NO 6 + +enum _BOOT_TYPE_ { + BOOT_FROM_FLASH = 0, + BOOT_FROM_SDIO = 1, + BOOT_FROM_USB = 2, + BOOT_FROM_RSVD = 3, +}; + +enum _EFUSE_CPU_CLK_ { + #if 1 + CLK_200M = 0, + CLK_100M = 1, + CLK_50M = 2, + CLK_25M = 3, + CLK_12_5M = 4, + CLK_4M = 5, + #else + CLK_25M = 0, + CLK_200M = 1, + CLK_100M = 2, + CLK_50M = 3, + CLK_12_5M = 4, + CLK_4M = 5, + #endif +}; + + +#endif //_HAL_PLATFORM_ diff --git a/component/soc/realtek/8195a/fwlib/hal_pwm.h b/component/soc/realtek/8195a/fwlib/hal_pwm.h new file mode 100644 index 0000000..9863782 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/hal_pwm.h @@ -0,0 +1,57 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#ifndef _HAL_PWM_H_ +#define _HAL_PWM_H_ + +#define MAX_PWM_CTRL_PIN 4 +// the minimum tick time for G-timer is 61 us (clock source = 32768Hz, reload value=1 and reload takes extra 1T) +#define GTIMER_TICK_US 31 // micro-second, 1000000/32768 ~= 30.5 +#define MIN_GTIMER_TIMEOUT 61 // in micro-sec, use this value to set the g-timer to generate tick for PWM. 61=(1000000/32768)*2 +#define PWM_GTIMER_TICK_TIME 61 // in micro-sec, use this value to set the g-timer to generate tick for PWM. 61=(1000000/32768)*2 + +typedef struct _HAL_PWM_ADAPTER_ { + u8 pwm_id; // the PWM ID, 0~3 + u8 sel; // PWM Pin selection, 0~3 + u8 gtimer_id; // using G-Timer ID, there are 7 G-timer, but we prefer to use timer 3~6 + u8 enable; // is enabled +// u32 timer_value; // the G-Timer auto-reload value, source clock is 32768Hz, reload will takes extra 1 tick. To set the time of a tick of PWM + u32 tick_time; // the tick time for the G-timer + u32 period; // the period of a PWM control cycle, in PWM tick + u32 pulsewidth; // the pulse width in a period of a PWM control cycle, in PWM tick. To control the ratio +// float duty_ratio; // the dyty ratio = pulswidth/period +}HAL_PWM_ADAPTER, *PHAL_PWM_ADAPTER; + + +extern HAL_Status +HAL_Pwm_Init( + u32 pwm_id, + u32 sel +); + +extern void +HAL_Pwm_Enable( + u32 pwm_id +); + +extern void +HAL_Pwm_Disable( + u32 pwm_id +); + +extern void +HAL_Pwm_SetDuty( + u32 pwm_id, + u32 period, + u32 pulse_width +); + + +#endif + diff --git a/component/soc/realtek/8195a/fwlib/hal_sdio.h b/component/soc/realtek/8195a/fwlib/hal_sdio.h new file mode 100644 index 0000000..197e142 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/hal_sdio.h @@ -0,0 +1,241 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#ifndef _HAL_SDIO_H_ +#define _HAL_SDIO_H_ + +#include "rtl8195a_sdio.h" + +#if !SDIO_BOOT_DRIVER +#include "mailbox.h" +#endif + +#if SDIO_BOOT_DRIVER +typedef struct _HAL_SDIO_ADAPTER_ { + u8 *pTXBDAddr; /* The TX_BD start address */ + PSDIO_TX_BD pTXBDAddrAligned; /* The TX_BD start address, it must be 4-bytes aligned */ + PSDIO_TX_BD_HANDLE pTXBDHdl; /* point to the allocated memory for TX_BD Handle array */ + u16 TXBDWPtr; /* The SDIO TX(Host->Device) BD local write index, different with HW maintained write Index. */ + u16 TXBDRPtr; /* The SDIO TX(Host->Device) BD read index */ + u16 TXBDRPtrReg; /* The SDIO TX(Host->Device) BD read index has been write to HW register */ + u16 reserve1; + + u8 *pRXBDAddr; /* The RX_BD start address */ + PSDIO_RX_BD pRXBDAddrAligned; /* The RX_BD start address, it must be 8-bytes aligned */ + PSDIO_RX_BD_HANDLE pRXBDHdl; /* point to the allocated memory for RX_BD Handle array */ + u16 RXBDWPtr; /* The SDIO RX(Device->Host) BD write index */ + u16 RXBDRPtr; /* The SDIO RX(Device->Host) BD local read index, different with HW maintained Read Index. */ + u16 IntMask; /* The Interrupt Mask */ + u16 IntStatus; /* The Interrupt Status */ + u32 Events; /* The Event to the SDIO Task */ + + u32 EventSema; /* Semaphore for SDIO events, use to wakeup the SDIO task */ + u8 CCPWM; /* the value write to register CCPWM, which will sync to Host HCPWM */ + u8 reserve2; + u16 CCPWM2; /* the value write to register CCPWM2, which will sync to Host HCPWM2 */ + + s8 (*Tx_Callback)(VOID *pAdapter, u8 *pPkt, u16 Offset, u16 PktSize); /* to hook the WLan driver TX callback function to handle a Packet TX */ + VOID *pTxCb_Adapter; /* a pointer will be used to call the TX Callback function, + which is from the TX CallBack function register */ + s8 (*pTxCallback_Backup)(VOID *pAdapter, u8 *pPkt, u16 Offset, u16 PktSize); // Use to back up the registered TX Callback function, for MP/Normal mode switch + VOID *pTxCb_Adapter_Backup; // Backup the pTxCb_Adapter, for MP/Normal mode switch + _LIST FreeTxPktList; /* The list to queue free Tx packets handler */ + _LIST RxPktList; /* The list to queue RX packets */ + _LIST FreeRxPktList; /* The list to queue free Rx packets handler */ + SDIO_TX_PACKET *pTxPktHandler; /* to store allocated TX Packet handler memory address */ + SDIO_RX_PACKET *pRxPktHandler; /* to store allocated RX Packet handler memory address */ + u32 RxInQCnt; /* The packet count for Rx In Queue */ + u32 MemAllocCnt; // Memory allocated count, for debug only + u32 MAllocFailedCnt; // MemAlloc Failed count, for debugging + +// VOID *pHalOp; /* point to HAL operation function table */ +} HAL_SDIO_ADAPTER, *PHAL_SDIO_ADAPTER; + +extern BOOL SDIO_Device_Init_Rom( + IN PHAL_SDIO_ADAPTER pSDIODev +); +extern VOID SDIO_Device_DeInit_Rom( + IN PHAL_SDIO_ADAPTER pSDIODev +); +extern VOID SDIO_Send_C2H_IOMsg_Rom( + IN PHAL_SDIO_ADAPTER pSDIODev, + IN u32 *C2HMsg +); +extern u8 SDIO_Send_C2H_PktMsg_Rom( + IN PHAL_SDIO_ADAPTER pSDIODev, + IN u8 *C2HMsg, + IN u16 MsgLen +); +extern VOID SDIO_Register_Tx_Callback_Rom( + IN PHAL_SDIO_ADAPTER pSDIODev, + IN s8 (*Tx_Callback)(VOID *pAdapter, u8 *pPkt, u16 Offset, u16 PktSize), + IN VOID *pAdapter +); +extern s8 SDIO_Rx_Callback_Rom( + IN PHAL_SDIO_ADAPTER pSDIODev, + IN VOID *pData, + IN u16 Offset, + IN u16 Length, + IN u8 CmdType +); + +#else // else of "#if SDIO_BOOT_DRIVER" +typedef struct _HAL_SDIO_ADAPTER_ { +// u8 *pTxBuff; /* point to the SDIO TX Buffer */ +// u8 *pTxBuffAligned; /* point to the SDIO TX Buffer with 4-bytes aligned */ +// u32 TXFifoRPtr; /* The SDIO TX(Host->Device) FIFO buffer read pointer */ + + u8 *pTXBDAddr; /* The TX_BD start address */ + PSDIO_TX_BD pTXBDAddrAligned; /* The TX_BD start address, it must be 4-bytes aligned */ + PSDIO_TX_BD_HANDLE pTXBDHdl; /* point to the allocated memory for TX_BD Handle array */ + u16 TXBDWPtr; /* The SDIO TX(Host->Device) BD local write index, different with HW maintained write Index. */ + u16 TXBDRPtr; /* The SDIO TX(Host->Device) BD read index */ + u16 TXBDRPtrReg; /* The SDIO TX(Host->Device) BD read index has been write to HW register */ + + u8 *pRXBDAddr; /* The RX_BD start address */ + PSDIO_RX_BD pRXBDAddrAligned; /* The RX_BD start address, it must be 8-bytes aligned */ + PSDIO_RX_BD_HANDLE pRXBDHdl; /* point to the allocated memory for RX_BD Handle array */ + u16 RXBDWPtr; /* The SDIO RX(Device->Host) BD write index */ + u16 RXBDRPtr; /* The SDIO RX(Device->Host) BD local read index, different with HW maintained Read Index. */ + u16 IntMask; /* The Interrupt Mask */ + u16 IntStatus; /* The Interrupt Status */ + u32 Events; /* The Event to the SDIO Task */ + +#if !TASK_SCHEDULER_DISABLED + _Sema TxSema; /* Semaphore for SDIO TX, use to wakeup the SDIO TX task */ + _Sema RxSema; /* Semaphore for SDIO RX, use to wakeup the SDIO RX task */ +#else + u32 EventSema; /* Semaphore for SDIO events, use to wakeup the SDIO task */ +#endif + s8 (*Tx_Callback)(VOID *pAdapter, u8 *pPkt, u16 Offset, u16 PktSize); /* to hook the WLan driver TX callback function to handle a Packet TX */ + VOID *pTxCb_Adapter; /* a pointer will be used to call the TX Callback function, + which is from the TX CallBack function register */ + s8 (*pTxCallback_Backup)(VOID *pAdapter, u8 *pPkt, u16 Offset, u16 PktSize); // Use to back up the registered TX Callback function, for MP/Normal mode switch + VOID *pTxCb_Adapter_Backup; // Backup the pTxCb_Adapter, for MP/Normal mode switch + _LIST FreeTxPktList; /* The list to queue free Tx packets handler */ + _LIST RxPktList; /* The list to queue RX packets */ + _LIST FreeRxPktList; /* The list to queue free Rx packets handler */ +// _LIST RecyclePktList; /* The list to queue packets handler to be recycled */ + SDIO_TX_PACKET *pTxPktHandler; /* to store allocated TX Packet handler memory address */ + SDIO_RX_PACKET *pRxPktHandler; /* to store allocated RX Packet handler memory address */ + _Mutex RxMutex; /* The Mutex to protect RxPktList */ + u32 RxInQCnt; /* The packet count for Rx In Queue */ +#if SDIO_DEBUG + _Mutex StatisticMutex; /* The Mutex to protect Statistic data */ + u32 MemAllocCnt; // Memory allocated count, for debug only + u32 MAllocFailedCnt; // MemAlloc Failed count, for debugging +#endif + VOID *pHalOp; /* point to HAL operation function table */ + RTL_MAILBOX *pMBox; /* the Mail box for other driver module can send message to SDIO driver */ + +#ifdef PLATFORM_FREERTOS + xTaskHandle xSDIOTxTaskHandle; /* The handle of the SDIO Task for TX, can be used to delte the task */ + xTaskHandle xSDIORxTaskHandle; /* The handle of the SDIO Task speical for RX, can be used to delte the task */ +#endif + +#if SDIO_MP_MODE +#if !TASK_SCHEDULER_DISABLED + u32 MP_Events; /* The Event to the SDIO Task */ + _Sema MP_EventSema; /* Semaphore for SDIO events, use to wakeup the SDIO task */ + RTL_MAILBOX *pMP_MBox; /* the Mail box for communication with other driver module */ +#ifdef PLATFORM_FREERTOS + xTaskHandle MP_TaskHandle; /* The handle of the MP loopback Task, can be used to delte the task */ +#endif // end of "#ifdef PLATFORM_FREERTOS" +#endif // end of "#if !TASK_SCHEDULER_DISABLED" + // for MP mode + RTL_TIMER *pPeriodTimer; /* a timer to calculate throughput periodically */ + u8 MP_ModeEn; /* is in MP mode */ + u8 MP_LoopBackEn; /* is loop-back enabled */ + u8 MP_ContinueTx; /* is continue TX test enabled */ + u8 MP_ContinueRx; /* is continue RX test enabled */ + u8 MP_ContinueRxMode; /* continue RX test mode: static RX Buf, Dyna-Allocate RX Buf, Pre-Allocate RX Buf */ + u8 MP_CRxInfinite; /* is non-stop SDIO RX, no packet count limit */ + u16 MP_CRxSize; /* SDIO RX test packet size */ + u8 *pMP_CRxBuf; // the buffer for continye RX test + u32 MP_CRxPktCnt; /* SDIO RX test packet count */ + u32 MP_CRxPktPendingCnt; /* SDIO RX test packet pening count */ + u32 MP_TxPktCnt; /* SDIO TX packet count */ + u32 MP_RxPktCnt; /* SDIO RX packet count */ + u32 MP_TxByteCnt; /* SDIO TX Byte count */ + u32 MP_RxByteCnt; /* SDIO RX Byte count */ + u32 MP_TxDropCnt; /* SDIO TX Drop packet count */ + u32 MP_RxDropCnt; /* SDIO RX Drop packet count */ + + u32 MP_TxPktCntInPeriod; /* SDIO TX packet count in a period */ + u32 MP_RxPktCntInPeriod; /* SDIO RX packet count in a period */ + u32 MP_TxByteCntInPeriod; /* SDIO TX Byte count in a period */ + u32 MP_RxByteCntInPeriod; /* SDIO RX Byte count in a period */ + + u32 MP_TxAvgTPWin[SDIO_AVG_TP_WIN_SIZE]; /* a window of SDIO TX byte count history, for average throughput calculation */ + u32 MP_RxAvgTPWin[SDIO_AVG_TP_WIN_SIZE]; /* a window of SDIO RX byte count history, for average throughput calculation */ + u32 MP_TxAvgTPWinSum; /* The sum of all byte-count in the window */ + u32 MP_RxAvgTPWinSum; /* The sum of all byte-count in the window */ + u8 OldestTxAvgWinIdx; /* the index of the oldest TX byte count log */ + u8 TxAvgWinCnt; /* the number of log in the Window */ + u8 OldestRxAvgWinIdx; /* the index of the oldest RX byte count log */ + u8 RxAvgWinCnt; /* the number of log in the Window */ + + _LIST MP_RxPktList; /* The list to queue RX packets, for MP loopback test */ +#endif // end of '#if SDIO_MP_MODE' +} HAL_SDIO_ADAPTER, *PHAL_SDIO_ADAPTER; +#endif // end of "#else of "#if SDIO_BOOT_DRIVER"" + + +typedef struct _HAL_SDIO_OP_ { + BOOL (*HalSdioDevInit)(PHAL_SDIO_ADAPTER pSDIODev); + VOID (*HalSdioDevDeInit)(PHAL_SDIO_ADAPTER pSDIODev); + VOID (*HalSdioSendC2HIOMsg)(PHAL_SDIO_ADAPTER pSDIODev, u32 *C2HMsg); + u8 (*HalSdioSendC2HPktMsg)(PHAL_SDIO_ADAPTER pSDIODev, u8 *C2HMsg, u16 MsgLen); + VOID (*HalSdioRegTxCallback)(PHAL_SDIO_ADAPTER pSDIODev,s8 (*CallbackFun)(VOID *pAdapter, u8 *pPkt, u16 Offset, u16 PktSize), VOID *pAdapter); + s8 (*HalSdioRxCallback)(PHAL_SDIO_ADAPTER pSDIODev, VOID *pData, u16 Offset, u16 PktSize, u8 CmdType); +#if SDIO_MP_MODE + VOID (*HalSdioDevMPApp)(PHAL_SDIO_ADAPTER pSDIODev, u16 argc, u8 *argv[]); +#endif +}HAL_SDIO_OP, *PHAL_SDIO_OP; + + +extern BOOL SDIO_Device_Init( + IN PHAL_SDIO_ADAPTER pSDIODev +); +extern VOID SDIO_Device_DeInit( + IN PHAL_SDIO_ADAPTER pSDIODev +); +extern VOID SDIO_Send_C2H_IOMsg( + IN PHAL_SDIO_ADAPTER pSDIODev, + IN u32 *C2HMsg +); +extern u8 SDIO_Send_C2H_PktMsg( + IN PHAL_SDIO_ADAPTER pSDIODev, + IN u8 *C2HMsg, + IN u16 MsgLen +); +extern VOID SDIO_Register_Tx_Callback( + IN PHAL_SDIO_ADAPTER pSDIODev, + IN s8 (*Tx_Callback)(VOID *pAdapter, u8 *pPkt, u16 Offset, u16 PktSize), + IN VOID *pAdapter +); +extern s8 SDIO_Rx_Callback( + IN PHAL_SDIO_ADAPTER pSDIODev, + IN VOID *pData, + IN u16 Offset, + IN u16 Length, + IN u8 CmdType +); +#if SDIO_MP_MODE +extern VOID SDIO_DeviceMPApp( + IN PHAL_SDIO_ADAPTER pSDIODev, + IN u16 argc, + IN u8 *argv[] +); +#endif + +extern PHAL_SDIO_ADAPTER pgSDIODev; +extern VOID HalSdioInit(VOID); +extern VOID HalSdioDeInit(VOID); +#endif // #ifndef _HAL_SDIO_H_ diff --git a/component/soc/realtek/8195a/fwlib/hal_sdr_controller.h b/component/soc/realtek/8195a/fwlib/hal_sdr_controller.h new file mode 100644 index 0000000..79487a2 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/hal_sdr_controller.h @@ -0,0 +1,188 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#ifndef _HAL_SDR_CONTROLLER_H_ +#define _HAL_SDR_CONTROLLER_H_ + +typedef enum _DRAM_TYPE_ { + DRAM_DDR_1 = 1, + DRAM_DDR_2 = 2, + DRAM_DDR_3 = 3, + DRAM_DDR_4 = 4, + DRAM_SDR = 8 +}DRAM_TYPE; + +typedef enum _DRAM_COLADDR_WTH_ { + DRAM_COLADDR_8B = 0, + DRAM_COLADDR_9B = 1, + DRAM_COLADDR_10B = 2, + DRAM_COLADDR_11B = 3, + DRAM_COLADDR_12B = 4, + DRAM_COLADDR_13B = 5, + DRAM_COLADDR_14B = 6, + DRAM_COLADDR_15B = 7, + DRAM_COLADDR_16B = 8 +}DRAM_COLADDR_WTH; + +typedef enum _DRAM_BANK_SIZE_ { + DRAM_BANK_2 = 0, + DRAM_BANK_4 = 1, + DRAM_BANK_8 = 2 +}DRAM_BANK_SIZE; + +typedef enum _DRAM_DQ_WIDTH_ { + DRAM_DQ_16 = 0, + DRAM_DQ_32 = 1, + DRAM_HALF_DQ32 = 2 +}DRAM_DQ_WIDTH; + +typedef enum _MODE0_BST_LEN_ { + BST_LEN_4 = 0, + BST_LEN_FLY = 1, + BST_LEN_8 = 2 +}MODE0_BST_LEN; + +typedef enum _MODE0_BST_TYPE_ { + SENQUENTIAL = 0, + INTERLEAVE = 1 +}MODE0_BST_TYPE; + +typedef enum _DFI_RATIO_TYPE_ { + DFI_RATIO_1 = 0, // DFI= 1:1, or SDR + DFI_RATIO_2 = 1, + DFI_RATIO_4 = 2 +}DFI_RATIO_TYPE; + +typedef struct _DRAM_INFO_ { + DRAM_TYPE DeviceType; + DRAM_COLADDR_WTH ColAddrWth; + DRAM_BANK_SIZE Bank; + DRAM_DQ_WIDTH DqWidth; +}DRAM_INFO; + +typedef struct _DRAM_MODE_REG_INFO_ { + MODE0_BST_LEN BstLen; + MODE0_BST_TYPE BstType; + //enum mode0_cas rd_cas; + u32 Mode0Cas; + u32 Mode0Wr; + u32 Mode1DllEnN; + u32 Mode1AllLat; + u32 Mode2Cwl; +}DRAM_MODE_REG_INFO; + +typedef struct _DRAM_TIMING_INFO_ { + u32 TrfcPs; + u32 TrefiPs; + u32 WrMaxTck; + u32 TrcdPs; + u32 TrpPs; + u32 TrasPs; + u32 TrrdTck; + u32 TwrPs; + u32 TwtrTck; + //u32 TrtpPs; + u32 TmrdTck; + u32 TrtpTck; + u32 TccdTck; + u32 TrcPs; +}DRAM_TIMING_INFO; + + +typedef struct _DRAM_DEVICE_INFO_ { + DRAM_INFO *Dev; + DRAM_MODE_REG_INFO *ModeReg; + DRAM_TIMING_INFO *Timing; + u32 DdrPeriodPs; + DFI_RATIO_TYPE *DfiRate; +}DRAM_DEVICE_INFO; + + +//====================================================== +//DRAM Info +#ifdef CONFIG_FPGA + #define DRAM_INFO_TYPE DRAM_SDR + #define DRAM_INFO_COL_ADDR_WTH DRAM_COLADDR_9B + #define DRAM_INFO_BANK_SZ DRAM_BANK_4 + #define DRAM_INFO_DQ_WTH DRAM_DQ_16 +#else + #define DRAM_INFO_TYPE DRAM_SDR + #define DRAM_INFO_COL_ADDR_WTH DRAM_COLADDR_8B + #define DRAM_INFO_BANK_SZ DRAM_BANK_2 + #define DRAM_INFO_DQ_WTH DRAM_DQ_16 +#endif + +//====================================================== +//DRAM Timing +#ifdef CONFIG_SDR_100MHZ +#define DRAM_TIMING_TCK 10000 //ps +#endif +#ifdef CONFIG_SDR_50MHZ +#define DRAM_TIMING_TCK 20000 //ps +#endif +#ifdef CONFIG_SDR_25MHZ +#define DRAM_TIMING_TCK 40000 //ps +#endif +#ifdef CONFIG_SDR_12_5MHZ +#define DRAM_TIMING_TCK 80000 //ps +#endif + +#if 1 +#define DRAM_TIMING_TREF 64000 //us +#define DRAM_ROW_NUM 8192 //depends on row bit number + +#define DRAM_TIMING_TRFC 60000 //ps +#define DRAM_TIMING_TREFI ((u32)((DRAM_TIMING_TREF*1000)/DRAM_ROW_NUM)*1000) //ps +#define DRAM_TIMING_TWRMAXTCK 2 //tck +#define DRAM_TIMING_TRCD 15000 //ps +#define DRAM_TIMING_TRP 15000 //ps +#define DRAM_TIMING_TRAS 42000 //ps +#define DRAM_TIMING_TRRD 2 //tck +#define DRAM_TIMING_TWR ((u32)(DRAM_TIMING_TCK*2)) +#define DRAM_TIMING_TWTR 0 //tck +#define DRAM_TIMING_TMRD 2 //tck +#define DRAM_TIMING_TRTP 0 //tck +#define DRAM_TIMING_TCCD 1 //tck +#define DRAM_TIMING_TRC 60000 //ps +#else + +#define DRAM_TIMING_TREF 66000 //us +#define DRAM_ROW_NUM 8192 //depends on row bit number + +#define DRAM_TIMING_TRFC 66000 //ps +#define DRAM_TIMING_TREFI 63999800 +#define DRAM_TIMING_TWRMAXTCK 2 //tck +#define DRAM_TIMING_TRCD 15000 //ps +#define DRAM_TIMING_TRP 15000 //ps +#define DRAM_TIMING_TRAS 37000 //ps +#define DRAM_TIMING_TRRD 2 //tck +#define DRAM_TIMING_TWR 7000 +#define DRAM_TIMING_TWTR 0 //tck +#define DRAM_TIMING_TMRD 2 //tck +#define DRAM_TIMING_TRTP 0 //tck +#define DRAM_TIMING_TCCD 1 //tck +#define DRAM_TIMING_TRC 60000 //ps +#endif + +#define HAL_SDR_WRITE32(addr, value32) HAL_WRITE32(SDR_CTRL_BASE, addr, value32) +#define HAL_SDR_WRITE16(addr, value16) HAL_WRITE16(SDR_CTRL_BASE, addr, value16) +#define HAL_SDR_WRITE8(addr, value8) HAL_WRITE8(SDR_CTRL_BASE, addr, value8) +#define HAL_SDR_READ32(addr) HAL_READ32(SDR_CTRL_BASE, addr) +#define HAL_SDR_READ16(addr) HAL_READ16(SDR_CTRL_BASE, addr) +#define HAL_SDR_READ8(addr) HAL_READ8(SDR_CTRL_BASE, addr) + +#define HAL_SDRAM_WRITE32(addr, value32) HAL_WRITE32(SDR_SDRAM_BASE, addr, value32) +#define HAL_SDRAM_WRITE16(addr, value16) HAL_WRITE16(SDR_SDRAM_BASE, addr, value16) +#define HAL_SDRAM_WRITE8(addr, value8) HAL_WRITE8(SDR_SDRAM_BASE, addr, value8) +#define HAL_SDRAM_READ32(addr) HAL_READ32(SDR_SDRAM_BASE, addr) +#define HAL_SDRAM_READ16(addr) HAL_READ16(SDR_SDRAM_BASE, addr) +#define HAL_SDRAM_READ8(addr) HAL_READ8(SDR_SDRAM_BASE, addr) + + +#endif // end of "#ifndef _HAL_SDR_CONTROLLER_H_" diff --git a/component/soc/realtek/8195a/fwlib/hal_soc_ps_monitor.h b/component/soc/realtek/8195a/fwlib/hal_soc_ps_monitor.h new file mode 100644 index 0000000..8e33bdc --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/hal_soc_ps_monitor.h @@ -0,0 +1,254 @@ +#ifndef _HAL_SOCPWR_ +#define _HAL_SOCPWR_ + + + +#define MAX_BACKUP_SIZE 129 +#define MAXFUNC 10 +#define FSTREG 0xFF + +#define REG_VDR_ANACK_CAL_CTRL 0xA0 + +//SLP +#define SLP_STIMER BIT0 +#define SLP_GTIMER BIT1 +#define SLP_GPIO BIT2 +#define SLP_WL BIT3 +#define SLP_NFC BIT4 +#define SLP_SDIO BIT5 +#define SLP_USB BIT6 +#define SLP_TIMER33 BIT7 + +//DSTBY +#define DSTBY_STIMER BIT0 +#define DSTBY_NFC BIT1 +#define DSTBY_TIMER33 BIT2 +#define DSTBY_GPIO BIT3 + +//DS wake event +#define DS_TIMER33 BIT0 +#define DS_GPIO BIT1 + +enum power_state_idx{ + ACT = 0, + WFE = 1, + WFI = 2, + SNOOZE = 3, + SLPCG = 4, + SLPPG = 5, + DSTBY = 6, + DSLP = 7, + INACT = 8, + MAXSTATE = 9 +}; + +enum clk_idx{ + ANACK = 0, + A33CK = 1, +}; + + +typedef struct _power_state_{ + u8 FuncIdx; + u8 PowerState; + u32 ReqDuration; + u32 RegCount; + u32 RemainDuration; +}POWER_STATE, *pPOWER_STATE; + +typedef struct _reg_power_state_{ + u8 FuncIdx; + u8 PwrState; + u32 ReqDuration; + //u8 StateIdx; +}REG_POWER_STATE, *pPREG_POWER_STATE; + +typedef struct _power_mgn_{ + u8 ActFuncCount; + POWER_STATE PwrState[MAXFUNC]; + u8 CurrentState; + u32 MSPbackup[MAX_BACKUP_SIZE]; + u32 CPURegbackup[25]; + u32 CPUPSP; + u32 WakeEventFlag; + BOOL SleepFlag; + //u32 CPUReg[13]; + //u32 MSBackUp[128]; +}Power_Mgn, *pPower_Mgn; + +typedef struct _SYS_ADAPTER_ { + u8 function; +}SYS_ADAPTER, *PSYS_ADAPTER; + +extern Power_Mgn PwrAdapter; + +u8 ChangeSoCPwrState( + IN u8 RequestState, + IN u32 ReqCount +); + +VOID PrintCPU(VOID); +void WakeFromSLPPG(void); +VOID SOCPSTestApp(VOID *Data); + + +__inline static VOID +CPURegBackUp( + VOID +) +{ +#if defined (__ICCARM__) + // TODO: IAR has different way using assembly +#elif defined (__GNUC__) + //backup cpu reg + #if 0 + asm volatile + ( + "PUSH {PSR, PC, LR, R12,R3,R2,R1,R0}\n" + ); + #endif + #if 0 + asm volatile + ( + "PUSH {r0,r1,r2,r3,r4}\n" + ); + #endif + + asm volatile + ( + + "MOV %0, r0\n" + :"=r"(PwrAdapter.CPURegbackup[0]) + ::"memory" + ); + + asm volatile + ( + "MOV %0, r1\n" + :"=r"(PwrAdapter.CPURegbackup[1]) + ::"memory" + ); + + asm volatile + ( + "MOV %0, r2\n" + :"=r"(PwrAdapter.CPURegbackup[2]) + ::"memory" + ); + + asm volatile + ( + "MOV %0, r3\n" + :"=r"(PwrAdapter.CPURegbackup[3]) + ::"memory" + ); + + asm volatile + ( + "MOV %0, r4\n" + :"=r"(PwrAdapter.CPURegbackup[4]) + ::"memory" + ); + + asm volatile + ( + "MOV %0, r5\n" + :"=r"(PwrAdapter.CPURegbackup[5]) + ::"memory" + ); + + asm volatile + ( + "MOV %0, r6\n" + :"=r"(PwrAdapter.CPURegbackup[6]) + ::"memory" + ); + + asm volatile + ( + "MOV %0, r7\n" + :"=r"(PwrAdapter.CPURegbackup[7]) + ::"memory" + ); + + asm volatile + ( + "MOV %0, r8\n" + :"=r"(PwrAdapter.CPURegbackup[8]) + ::"memory" + ); + + asm volatile + ( + "MOV %0, r9\n" + :"=r"(PwrAdapter.CPURegbackup[9]) + ::"memory" + ); + + asm volatile + ( + "MOV %0, r10\n" + :"=r"(PwrAdapter.CPURegbackup[10]) + ::"memory" + ); + + asm volatile + ( + "MOV %0, r11\n" + :"=r"(PwrAdapter.CPURegbackup[11]) + ::"memory" + ); + asm volatile + ( + "MOV %0, r12\n" + :"=r"(PwrAdapter.CPURegbackup[12]) + ::"memory" + ); + + asm volatile + ( + "MOV %0, r13\n" + :"=r"(PwrAdapter.CPURegbackup[13]) + ::"memory" + ); + asm volatile + ( + //"MOV %0, r14\n" + "LDR %0, =SLPPG_WAKEUP_POINT\n" + "ADD %0, #1\n" + :"=r"(PwrAdapter.CPURegbackup[14]) + ::"memory" + ); + asm volatile + ( + "LDR %0, =SLPPG_WAKEUP_POINT\n" + "ADD %0, #1\n" + :"=r"(PwrAdapter.CPURegbackup[15]) + ::"memory" + ); + asm volatile + ( + "MRS %0, PSR\n" + :"=r"(PwrAdapter.CPURegbackup[16]) + ::"memory" + ); + +#if 1 + asm volatile + ( + "mov %0, r13\n" + "MOV %1, PC\n" + "MRS %2, CONTROL\n" + "MRS %3, PSP\n" + "MRS %4, MSP\n" + :"=r"(PwrAdapter.CPURegbackup[24]),"=r"(PwrAdapter.CPURegbackup[23]),"=r"(PwrAdapter.CPURegbackup[22]),"=r"(PwrAdapter.CPURegbackup[21]),"=r"(PwrAdapter.CPURegbackup[20]) + ::"memory" + ); +#endif + #ifdef CONFIG_SOC_PS_VERIFY + PrintCPU(); + #endif //#ifdef CONFIG_SOC_PS_VERIFY +#endif //#elif defined (__GNUC__) +} + +#endif //_HAL_SOCPWR_ diff --git a/component/soc/realtek/8195a/fwlib/hal_spi_flash.h b/component/soc/realtek/8195a/fwlib/hal_spi_flash.h new file mode 100644 index 0000000..04e1306 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/hal_spi_flash.h @@ -0,0 +1,235 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + + +#ifndef _HAL_SPIFLASH__ +#define _HAL_SPIFLASH__ +//====================================================== +// Header files +#include "rtl8195a_spi_flash.h" + +#define SPIC_CALIBRATION_IN_NVM 1 // if store the SPIC calibration data in the NVM +#ifndef CONFIG_IMAGE_SEPARATE // Store SPIC Calibration only for seprated image +#undef SPIC_CALIBRATION_IN_NVM +#define SPIC_CALIBRATION_IN_NVM 0 +#endif + +//====================================================== +// Definition +#define HAL_SPI_WRITE32(addr, value32) HAL_WRITE32(SPI_FLASH_CTRL_BASE, addr, value32) +#define HAL_SPI_WRITE16(addr, value16) HAL_WRITE16(SPI_FLASH_CTRL_BASE, addr, value16) +#define HAL_SPI_WRITE8(addr, value8) HAL_WRITE8(SPI_FLASH_CTRL_BASE, addr, value8) +#define HAL_SPI_READ32(addr) HAL_READ32(SPI_FLASH_CTRL_BASE, addr) +#define HAL_SPI_READ16(addr) HAL_READ16(SPI_FLASH_CTRL_BASE, addr) +#define HAL_SPI_READ8(addr) HAL_READ8(SPI_FLASH_CTRL_BASE, addr) + +typedef struct _SPIC_INIT_PARA_ { + u8 BaudRate; + u8 RdDummyCyle; + u8 DelayLine; + union { + u8 Rsvd; + u8 Valid; + }; +}SPIC_INIT_PARA, *PSPIC_INIT_PARA; + + +enum _SPIC_BIT_MODE_ { + SpicOneBitMode = 0, + SpicDualBitMode = 1, + SpicQuadBitMode = 2, +}; + +//====================================================== +// Flash type used +#define FLASH_MXIC_MX25L4006E 1 +#define FLASH_MXIC_MX25L8073E 0 + +// The below parts are based on the flash characteristics +//====== Flash Command Definition ====== +#if FLASH_MXIC_MX25L4006E + #define FLASH_CMD_WREN 0x06 //write enable + #define FLASH_CMD_WRDI 0x04 //write disable + #define FLASH_CMD_WRSR 0x01 //write status register + #define FLASH_CMD_RDID 0x9F //read idenfication + #define FLASH_CMD_RDSR 0x05 //read status register + #define FLASH_CMD_READ 0x03 //read data + #define FLASH_CMD_FREAD 0x0B //fast read data + #define FLASH_CMD_RDSFDP 0x5A //Read SFDP + #define FLASH_CMD_RES 0xAB //Read Electronic ID + #define FLASH_CMD_REMS 0x90 //Read Electronic Manufacturer & Device ID + #define FLASH_CMD_DREAD 0x3B //Double Output Mode command + #define FLASH_CMD_SE 0x20 //Sector Erase + #define FLASH_CMD_BE 0xD8 //Block Erase(or 0x52) + #define FLASH_CMD_CE 0x60 //Chip Erase(or 0xC7) + #define FLASH_CMD_PP 0x02 //Page Program + #define FLASH_CMD_DP 0xB9 //Deep Power Down + #define FLASH_CMD_RDP 0xAB //Release from Deep Power-Down +#elif FLASH_MXIC_MX25L8073E + #define FLASH_CMD_WREN 0x06 //write enable + #define FLASH_CMD_WRDI 0x04 //write disable + #define FLASH_CMD_WRSR 0x01 //write status register + #define FLASH_CMD_RDID 0x9F //read idenfication + #define FLASH_CMD_RDSR 0x05 //read status register + #define FLASH_CMD_READ 0x03 //read data + #define FLASH_CMD_FREAD 0x0B //fast read data + #define FLASH_CMD_RDSFDP 0x5A //Read SFDP + #define FLASH_CMD_RES 0xAB //Read Electronic ID + #define FLASH_CMD_REMS 0x90 //Read Electronic Manufacturer & Device ID + #define FLASH_CMD_DREAD 0x3B //Double Output Mode command + #define FLASH_CMD_SE 0x20 //Sector Erase + #define FLASH_CMD_BE 0x52 //Block Erase + #define FLASH_CMD_CE 0x60 //Chip Erase(or 0xC7) + #define FLASH_CMD_PP 0x02 //Page Program + #define FLASH_CMD_DP 0xB9 //Deep Power Down + #define FLASH_CMD_RDP 0xAB //Release from Deep Power-Down + #define FLASH_CMD_2READ 0xBB // 2 x I/O read command + #define FLASH_CMD_4READ 0xEB // 4 x I/O read command + #define FLASH_CMD_QREAD 0x6B // 1I / 4O read command + #define FLASH_CMD_4PP 0x38 //quad page program + #define FLASH_CMD_FF 0xFF //Release Read Enhanced + #define FLASH_CMD_REMS2 0xEF // read ID for 2x I/O mode + #define FLASH_CMD_REMS4 0xDF // read ID for 4x I/O mode + #define FLASH_CMD_ENSO 0xB1 // enter secured OTP + #define FLASH_CMD_EXSO 0xC1 // exit secured OTP + #define FLASH_CMD_RDSCUR 0x2B // read security register + #define FLASH_CMD_WRSCUR 0x2F // write security register +#else + #define FLASH_CMD_WREN 0x06 //write enable + #define FLASH_CMD_WRDI 0x04 //write disable + #define FLASH_CMD_WRSR 0x01 //write status register + #define FLASH_CMD_RDID 0x9F //read idenfication + #define FLASH_CMD_RDSR 0x05 //read status register + #define FLASH_CMD_READ 0x03 //read data + #define FLASH_CMD_FREAD 0x0B //fast read data + #define FLASH_CMD_RDSFDP 0x5A //Read SFDP + #define FLASH_CMD_RES 0xAB //Read Electronic ID + #define FLASH_CMD_REMS 0x90 //Read Electronic Manufacturer & Device ID + #define FLASH_CMD_DREAD 0x3B //Double Output Mode command + #define FLASH_CMD_SE 0x20 //Sector Erase + #define FLASH_CMD_BE 0x52 //Block Erase + #define FLASH_CMD_CE 0x60 //Chip Erase(or 0xC7) + #define FLASH_CMD_PP 0x02 //Page Program + #define FLASH_CMD_DP 0xB9 //Deep Power Down + #define FLASH_CMD_RDP 0xAB //Release from Deep Power-Down + #define FLASH_CMD_2READ 0xBB // 2 x I/O read command + #define FLASH_CMD_4READ 0xEB // 4 x I/O read command + #define FLASH_CMD_QREAD 0x6B // 1I / 4O read command + #define FLASH_CMD_4PP 0x38 //quad page program + #define FLASH_CMD_FF 0xFF //Release Read Enhanced + #define FLASH_CMD_REMS2 0xEF // read ID for 2x I/O mode + #define FLASH_CMD_REMS4 0xDF // read ID for 4x I/O mode + #define FLASH_CMD_ENSO 0xB1 // enter secured OTP + #define FLASH_CMD_EXSO 0xC1 // exit secured OTP + #define FLASH_CMD_RDSCUR 0x2B // read security register + #define FLASH_CMD_WRSCUR 0x2F // write security register +#endif //#if FLASH_MXIC_MX25L4006E +// ============================ + +// ===== Flash Parameter Definition ===== +#if FLASH_MXIC_MX25L4006E + #define FLASH_RD_2IO_EN 0 + #define FLASH_RD_2O_EN 1 + #define FLASH_RD_4IO_EN 0 + #define FLASH_RD_4O_EN 0 + #define FLASH_WR_2IO_EN 0 + #define FLASH_WR_2O_EN 0 + #define FLASH_WR_4IO_EN 0 + #define FLASH_WR_4O_EN 0 + + #define FLASH_DM_CYCLE_2O 0x08 + #define FLASH_VLD_DUAL_CMDS (BIT_WR_BLOCKING | BIT_RD_DUAL_I) + #define FLASH_VLD_QUAD_CMDS (0) + +#elif FLASH_MXIC_MX25L8073E //This flash model is just for prototype, if you want to use it, + //the code MUST be rechecked according to the flash spec. + #define FLASH_RD_2IO_EN 1 + #define FLASH_RD_2O_EN 0 + #define FLASH_RD_4IO_EN 1 + #define FLASH_RD_4O_EN 0 + #define FLASH_WR_2IO_EN 1 + #define FLASH_WR_2O_EN 0 + #define FLASH_WR_4IO_EN 1 + #define FLASH_WR_4O_EN 0 + + #define FLASH_DM_CYCLE_2O 0x08 + #define FLASH_DM_CYCLE_2IO 0x04 + #define FLASH_DM_CYCLE_4O 0x08 + #define FLASH_DM_CYCLE_4IO 0x04 + + #define FLASH_VLD_DUAL_CMDS (BIT_WR_BLOCKING | BIT_RD_DUAL_IO) + #define FLASH_VLD_QUAD_CMDS (BIT_WR_BLOCKING | BIT_WR_QUAD_II | BIT_RD_QUAD_IO) +#else + #define FLASH_RD_2IO_EN 1 + #define FLASH_RD_2O_EN 0 + #define FLASH_RD_4IO_EN 1 + #define FLASH_RD_4O_EN 0 + #define FLASH_WR_2IO_EN 1 + #define FLASH_WR_2O_EN 0 + #define FLASH_WR_4IO_EN 1 + #define FLASH_WR_4O_EN 0 + + #define FLASH_DM_CYCLE_2O 0x08 + #define FLASH_DM_CYCLE_2IO 0x04 + #define FLASH_DM_CYCLE_4O 0x08 + #define FLASH_DM_CYCLE_4IO 0x04 + + #define FLASH_VLD_DUAL_CMDS (BIT_WR_BLOCKING | BIT_RD_DUAL_IO) + #define FLASH_VLD_QUAD_CMDS (BIT_WR_BLOCKING | BIT_WR_QUAD_II | BIT_RD_QUAD_IO) +#endif +#if 0 +//====================================================== +// Function prototype +BOOLEAN SpicFlashInitRtl8195A(u8 SpicBitMode); + +_LONG_CALL_ +extern VOID SpicLoadInitParaFromClockRtl8195A(u8 CpuClkMode, u8 BaudRate, PSPIC_INIT_PARA pSpicInitPara); + +// spi-flash controller initialization +_LONG_CALL_ +extern VOID SpicInitRtl8195A(u8 InitBaudRate, u8 SpicBitMode); + +// wait sr[0] = 0, wait transmission done +_LONG_CALL_ +extern VOID SpicWaitBusyDoneRtl8195A(VOID); + +// wait spi-flash status register[0] = 0 +//_LONG_CALL_ +//extern VOID SpicWaitWipDoneRtl8195A(SPIC_INIT_PARA SpicInitPara); +#endif + +//====================================================== +// ROM Function prototype +_LONG_CALL_ VOID SpiFlashAppV02(IN VOID *Data); +_LONG_CALL_ VOID SpicInitRtl8195AV02(IN u8 InitBaudRate,IN u8 SpicBitMode); + +_LONG_CALL_ VOID SpicEraseFlashRtl8195AV02(); + +_LONG_CALL_ VOID SpicLoadInitParaFromClockRtl8195AV02(IN u8 CpuClkMode,IN u8 BaudRate,IN PSPIC_INIT_PARA pSpicInitPara); + + +VOID SpicBlockEraseFlashRtl8195A(IN u32 Address); +VOID SpicSectorEraseFlashRtl8195A(IN u32 Address); +VOID SpicWriteProtectFlashRtl8195A(IN u32 Protect); +VOID SpicWaitWipDoneRefinedRtl8195A(IN SPIC_INIT_PARA SpicInitPara); +VOID SpicRxCmdRefinedRtl8195A(IN u8 cmd,IN SPIC_INIT_PARA SpicInitPara); +u8 SpicGetFlashStatusRefinedRtl8195A(IN SPIC_INIT_PARA SpicInitPara); +VOID SpicInitRefinedRtl8195A(IN u8 InitBaudRate,IN u8 SpicBitMode); +u32 SpicWaitWipRtl8195A(VOID); +u32 SpicOneBitCalibrationRtl8195A(IN u8 SysCpuClk); +VOID SpicDisableRtl8195A(VOID); +VOID SpicDeepPowerDownFlashRtl8195A(VOID); + +#if SPIC_CALIBRATION_IN_NVM +VOID SpicNVMCalLoad(u8 BitMode, u8 CpuClk); +VOID SpicNVMCalLoadAll(void); +VOID SpicNVMCalStore(u8 BitMode, u8 CpuClk); +#endif // #if SPIC_CALIBRATION_IN_NVM + +#endif //_HAL_SPIFLASH__ diff --git a/component/soc/realtek/8195a/fwlib/hal_ssi.h b/component/soc/realtek/8195a/fwlib/hal_ssi.h new file mode 100644 index 0000000..792bec4 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/hal_ssi.h @@ -0,0 +1,303 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#ifndef _HAL_SSI_H_ +#define _HAL_SSI_H_ + +#include "rtl8195a_ssi.h" + +/** + * LOG Configurations + */ + +extern u32 SSI_DBG_CONFIG; +extern uint8_t SPI0_IS_AS_SLAVE; + + +#define SSI_DBG_ENTRANCE(...) do {\ + if (unlikely(SSI_DBG_CONFIG & DBG_TYPE_ENTRANCE)) \ + DBG_SSI_INFO(IDENT_FOUR_SPACE ANSI_COLOR_GREEN __VA_ARGS__ ANSI_COLOR_RESET); \ +}while(0) + +#define SSI_DBG_INIT(...) do {\ + if (unlikely(SSI_DBG_CONFIG & DBG_TYPE_INIT)) \ + DBG_SSI_INFO(IDENT_FOUR_SPACE __VA_ARGS__); \ +}while(0) + +#define SSI_DBG_INIT_V(...) do {\ + if (unlikely(SSI_DBG_CONFIG & DBG_TYPE_INIT_V)) \ + DBG_SSI_INFO(IDENT_FOUR_SPACE __VA_ARGS__); \ +}while(0) + +#define SSI_DBG_INIT_VV(...) do {\ + if (unlikely(SSI_DBG_CONFIG & DBG_TYPE_INIT_VV)) \ + DBG_SSI_INFO(IDENT_FOUR_SPACE __VA_ARGS__); \ +}while(0) + +#define SSI_DBG_PINMUX(...) do {\ + if (unlikely(SSI_DBG_CONFIG & DBG_TYPE_PINMUX)) \ + DBG_SSI_INFO(IDENT_FOUR_SPACE __VA_ARGS__); \ +}while(0) + +#define SSI_DBG_ENDIS(...) do {\ + if (unlikely(SSI_DBG_CONFIG & DBG_TYPE_ENDIS)) \ + DBG_SSI_INFO(IDENT_FOUR_SPACE __VA_ARGS__); \ +}while(0) + +#define SSI_DBG_INT(...) do {\ + if (unlikely(SSI_DBG_CONFIG & DBG_TYPE_INT)) \ + DBG_SSI_INFO(IDENT_FOUR_SPACE __VA_ARGS__); \ +}while(0) + +#define SSI_DBG_INT_V(...) do {\ + if (unlikely(SSI_DBG_CONFIG & DBG_TYPE_INT_V)) \ + DBG_SSI_INFO(IDENT_FOUR_SPACE __VA_ARGS__); \ +}while(0) + +#define SSI_DBG_INT_HNDLR(...) do {\ + if (unlikely(SSI_DBG_CONFIG & DBG_TYPE_INT_HNDLR)) \ + DBG_SSI_INFO(IDENT_FOUR_SPACE __VA_ARGS__); \ +}while(0) + +#define SSI_DBG_INT_READ(...) do {\ + if (unlikely(SSI_DBG_CONFIG & DBG_TYPE_INT_READ)) \ + DBG_SSI_INFO(IDENT_FOUR_SPACE __VA_ARGS__); \ +}while(0) + +#define SSI_DBG_INT_WRITE(...) do {\ + if (unlikely(SSI_DBG_CONFIG & DBG_TYPE_INT_WRITE)) \ + DBG_SSI_INFO(IDENT_FOUR_SPACE __VA_ARGS__); \ +}while(0) + +#define SSI_DBG_STATUS(...) do {\ + if (unlikely(SSI_DBG_CONFIG & DBG_TYPE_STATUS)) \ + DBG_SSI_INFO(IDENT_FOUR_SPACE __VA_ARGS__); \ +}while(0) + +#define SSI_DBG_FIFO(...) do {\ + if (unlikely(SSI_DBG_CONFIG & DBG_TYPE_FIFO)) \ + DBG_SSI_INFO(IDENT_FOUR_SPACE __VA_ARGS__); \ +}while(0) + +#define SSI_DBG_READ(...) do {\ + if (unlikely(SSI_DBG_CONFIG & DBG_TYPE_READ)) \ + DBG_SSI_INFO(IDENT_FOUR_SPACE __VA_ARGS__); \ +}while(0) + +#define SSI_DBG_WRITE(...) do {\ + if (unlikely(SSI_DBG_CONFIG & DBG_TYPE_WRITE)) \ + DBG_SSI_INFO(IDENT_FOUR_SPACE __VA_ARGS__); \ +}while(0) + +#define SSI_DBG_SLV_CTRL(...) do {\ + if (unlikely(SSI_DBG_CONFIG & DBG_TYPE_SLV_CTRL)) \ + DBG_SSI_INFO(IDENT_FOUR_SPACE __VA_ARGS__); \ +}while(0) + +typedef enum _SSI_DBG_TYPE_LIST_ { + DBG_TYPE_ENTRANCE = 1 << 0, + DBG_TYPE_INIT = 1 << 1, + DBG_TYPE_INIT_V = 1 << 2, + DBG_TYPE_INIT_VV = 1 << 3, + DBG_TYPE_PINMUX = 1 << 4, + DBG_TYPE_ENDIS = 1 << 5, + DBG_TYPE_INT = 1 << 6, + DBG_TYPE_INT_V = 1 << 7, + DBG_TYPE_INT_HNDLR = 1 << 8, + DBG_TYPE_INT_READ = 1 << 9, + DBG_TYPE_INT_WRITE = 1 << 10, + DBG_TYPE_STATUS = 1 << 11, + DBG_TYPE_FIFO = 1 << 12, + DBG_TYPE_READ = 1 << 13, + DBG_TYPE_WRITE = 1 << 14, + DBG_TYPE_SLV_CTRL = 1 << 15 +} SSI_DBG_TYPE_LIST, *PSSI_DBG_TYPE_LIST; + + typedef struct _SSI_DMA_CONFIG_ { + VOID *pHalGdmaOp; + VOID *pTxHalGdmaAdapter; + VOID *pRxHalGdmaAdapter; + u8 RxDmaBurstSize; + u8 TxDmaBurstSize; + u8 RxDmaEnable; + u8 TxDmaEnable; + IRQ_HANDLE RxGdmaIrqHandle; + IRQ_HANDLE TxGdmaIrqHandle; +}SSI_DMA_CONFIG, *PSSI_DMA_CONFIG; + +/** + * DesignWare SSI Configurations + */ +typedef struct _HAL_SSI_ADAPTOR_ { + SSI_DMA_CONFIG DmaConfig; + IRQ_HANDLE IrqHandle; + // + VOID (*RxCompCallback)(VOID *Para); + VOID *RxCompCbPara; + VOID *RxData; + VOID (*TxCompCallback)(VOID *Para); + VOID *TxCompCbPara; + VOID *TxData; + u32 DmaRxDataLevel; + u32 DmaTxDataLevel; + u32 InterruptPriority; + u32 RxLength; + u32 RxLengthRemainder; + u32 RxThresholdLevel; + u32 TxLength; + u32 TxThresholdLevel; + u32 SlaveSelectEnable; + // + u16 ClockDivider; + u16 DataFrameNumber; + // + u8 ControlFrameSize; + u8 DataFrameFormat; + u8 DataFrameSize; + u8 DmaControl; + u8 Index; + u8 InterruptMask; + u8 MicrowireDirection; + u8 MicrowireHandshaking; + u8 MicrowireTransferMode; + u8 PinmuxSelect; + u8 Role; + u8 SclkPhase; + u8 SclkPolarity; + u8 SlaveOutputEnable; + u8 TransferMode; + u8 TransferMechanism; + + // Extend + u32 Reserved1; + u8 DefaultRxThresholdLevel; +}HAL_SSI_ADAPTOR, *PHAL_SSI_ADAPTOR; + +typedef struct _HAL_SSI_OP_{ + HAL_Status (*HalSsiPinmuxEnable)(VOID *Adaptor); + HAL_Status (*HalSsiPinmuxDisable)(VOID *Adaptor); + HAL_Status (*HalSsiEnable)(VOID *Adaptor); + HAL_Status (*HalSsiDisable)(VOID *Adaptor); + HAL_Status (*HalSsiInit)(VOID *Adaptor); + HAL_Status (*HalSsiSetSclkPolarity)(VOID *Adaptor); + HAL_Status (*HalSsiSetSclkPhase)(VOID *Adaptor); + HAL_Status (*HalSsiWrite)(VOID *Adaptor, u32 value); + HAL_Status (*HalSsiLoadSetting)(VOID *Adaptor, VOID *Setting); + HAL_Status (*HalSsiSetInterruptMask)(VOID *Adaptor); + HAL_Status (*HalSsiSetDeviceRole)(VOID *Adaptor, u32 Role); + HAL_Status (*HalSsiInterruptEnable)(VOID *Adaptor); + HAL_Status (*HalSsiInterruptDisable)(VOID *Adaptor); + HAL_Status (*HalSsiReadInterrupt)(VOID *Adaptor, VOID *RxData, u32 Length); + HAL_Status (*HalSsiSetRxFifoThresholdLevel)(VOID *Adaptor); + HAL_Status (*HalSsiSetTxFifoThresholdLevel)(VOID *Adaptor); + HAL_Status (*HalSsiWriteInterrupt)(VOID *Adaptor, u8 *TxData, u32 Length); + HAL_Status (*HalSsiSetSlaveEnableRegister)(VOID *Adaptor, u32 SlaveIndex); + u32 (*HalSsiBusy)(VOID *Adaptor); + u32 (*HalSsiReadable)(VOID *Adaptor); + u32 (*HalSsiWriteable)(VOID *Adaptor); + u32 (*HalSsiGetInterruptMask)(VOID *Adaptor); + u32 (*HalSsiGetRxFifoLevel)(VOID *Adaptor); + u32 (*HalSsiGetTxFifoLevel)(VOID *Adaptor); + u32 (*HalSsiGetStatus)(VOID *Adaptor); + u32 (*HalSsiGetInterruptStatus)(VOID *Adaptor); + u32 (*HalSsiRead)(VOID *Adaptor); + u32 (*HalSsiGetRawInterruptStatus)(VOID *Adaptor); + u32 (*HalSsiGetSlaveEnableRegister)(VOID *Adaptor); +}HAL_SSI_OP, *PHAL_SSI_OP; + +typedef struct _DW_SSI_DEFAULT_SETTING_ { + VOID (*RxCompCallback)(VOID *Para); + VOID *RxCompCbPara; + VOID *RxData; + VOID (*TxCompCallback)(VOID *Para); + VOID *TxCompCbPara; + VOID *TxData; + u32 DmaRxDataLevel; + u32 DmaTxDataLevel; + u32 InterruptPriority; + u32 RxLength; + u32 RxLengthRemainder; + u32 RxThresholdLevel; + u32 TxLength; + u32 TxThresholdLevel; + u32 SlaveSelectEnable; + // + u16 ClockDivider; + u16 DataFrameNumber; + // + u8 ControlFrameSize; + u8 DataFrameFormat; + u8 DataFrameSize; + u8 DmaControl; + //u8 Index; + u8 InterruptMask; + u8 MicrowireDirection; + u8 MicrowireHandshaking; + u8 MicrowireTransferMode; + //u8 PinmuxSelect; + //u8 Role; + u8 SclkPhase; + u8 SclkPolarity; + u8 SlaveOutputEnable; + u8 TransferMode; + u8 TransferMechanism; +} DW_SSI_DEFAULT_SETTING, *PDW_SSI_DEFAULT_SETTING; + + +struct spi_s { + HAL_SSI_ADAPTOR spi_adp; + HAL_SSI_OP spi_op; + u32 irq_handler; + u32 irq_id; + u32 dma_en; + u32 state; + u8 sclk; +#ifdef CONFIG_GDMA_EN + HAL_GDMA_ADAPTER spi_gdma_adp_tx; + HAL_GDMA_ADAPTER spi_gdma_adp_rx; +#endif +}; + +VOID HalSsiOpInit(VOID *Adaptor); +static __inline__ VOID HalSsiSetSclk( + IN PHAL_SSI_ADAPTOR pHalSsiAdapter, + IN u32 ClkRate) +{ + HalSsiSetSclkRtl8195a((VOID*)pHalSsiAdapter, ClkRate); +} + +#ifdef CONFIG_GDMA_EN +HAL_Status HalSsiTxGdmaInit(PHAL_SSI_OP pHalSsiOp, PHAL_SSI_ADAPTOR pHalSsiAdapter); +VOID HalSsiTxGdmaDeInit(PHAL_SSI_ADAPTOR pHalSsiAdapter); +HAL_Status HalSsiRxGdmaInit(PHAL_SSI_OP pHalSsiOp, PHAL_SSI_ADAPTOR pHalSsiAdapter); +VOID HalSsiRxGdmaDeInit(PHAL_SSI_ADAPTOR pHalSsiAdapter); + +static __inline__ VOID +HalSsiDmaInit( + IN PHAL_SSI_ADAPTOR pHalSsiAdapter +) +{ + HalSsiDmaInitRtl8195a((void *)pHalSsiAdapter); +} + +static __inline__ HAL_Status HalSsiDmaSend(VOID *Adapter, u8 *pTxData, u32 Length) +{ + return (HalSsiDmaSendRtl8195a(Adapter, pTxData, Length)); +} + +static __inline__ HAL_Status HalSsiDmaRecv(VOID *Adapter, u8 *pRxData, u32 Length) +{ + return (HalSsiDmaRecvRtl8195a(Adapter, pRxData, Length)); +} + + +#endif // end of "#ifdef CONFIG_GDMA_EN" + +#endif + diff --git a/component/soc/realtek/8195a/fwlib/hal_timer.h b/component/soc/realtek/8195a/fwlib/hal_timer.h new file mode 100644 index 0000000..d0f8bc9 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/hal_timer.h @@ -0,0 +1,57 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#ifndef _HAL_TIMER_H_ +#define _HAL_TIMER_H_ +#include "basic_types.h" +#include "hal_platform.h" +#include "rtl8195a_timer.h" + +#define TIMER_TICK_US_X4 (4*1000000/32000) + +typedef enum _TIMER_MODE_ { + FREE_RUN_MODE = 0, + USER_DEFINED = 1 +}TIMER_MODE, *PTIMER_MODE; + + +typedef struct _TIMER_ADAPTER_ { + + u32 TimerLoadValueUs; + u32 TimerIrqPriority; + TIMER_MODE TimerMode; + IRQ_HANDLE IrqHandle; + u8 TimerId; + u8 IrqDis; + +}TIMER_ADAPTER, *PTIMER_ADAPTER; + + +typedef struct _HAL_TIMER_OP_ { + u32 (*HalGetTimerId)(u32 *TimerId); + BOOL (*HalTimerInit)(VOID *Data); + u32 (*HalTimerReadCount)(u32 TimerId); + VOID (*HalTimerIrqClear)(u32 TimerId); + VOID (*HalTimerDis)(u32 TimerId); + VOID (*HalTimerEn)(u32 TimerId); + VOID (*HalTimerDumpReg)(u32 TimerId); +}HAL_TIMER_OP, *PHAL_TIMER_OP; + +VOID HalTimerOpInit_Patch( + IN VOID *Data +); + + +//====================================================== +// ROM Function prototype +_LONG_CALL_ VOID HalTimerOpInitV02(IN VOID *Data); + +#define HalTimerOpInit HalTimerOpInit_Patch + +#endif diff --git a/component/soc/realtek/8195a/fwlib/hal_uart.h b/component/soc/realtek/8195a/fwlib/hal_uart.h new file mode 100644 index 0000000..c228b90 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/hal_uart.h @@ -0,0 +1,145 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#ifndef _HAL_UART_H_ +#define _HAL_UART_H_ + +#include "rtl8195a_uart.h" + +/** + * RUART Configurations + */ +#define UART_WAIT_FOREVER 0xffffffff + +typedef struct _UART_DMA_CONFIG_ { + u8 TxDmaEnable; + u8 RxDmaEnable; + u8 TxDmaBurstSize; + u8 RxDmaBurstSize; + VOID *pHalGdmaOp; + VOID *pTxHalGdmaAdapter; + VOID *pRxHalGdmaAdapter; + IRQ_HANDLE TxGdmaIrqHandle; + IRQ_HANDLE RxGdmaIrqHandle; +}UART_DMA_CONFIG, *PUART_DMA_CONFIG; + +typedef struct _HAL_RUART_ADAPTER_ { + u32 BaudRate; + u32 FlowControl; + u32 FifoControl; + u32 Interrupts; + u32 TxCount; // how many byte to TX + u32 RxCount; // how many bytes to RX + u8 *pTxBuf; + u8 *pRxBuf; + HAL_UART_State State; // UART state + u8 Status; // Transfer Status + u8 Locked; // is UART locked for operation + u8 UartIndex; + u8 WordLen; // word length select: 0 -> 7 bits, 1 -> 8 bits + u8 StopBit; // word length select: 0 -> no stop bit, 1 -> 1 stop bit + u8 Parity; // parity check enable + u8 ParityType; // parity check type + u8 StickParity; + u8 ModemStatus; // the modem status + u8 DmaEnable; + u8 TestCaseNumber; + u8 PinmuxSelect; + BOOL PullMode; + IRQ_HANDLE IrqHandle; + PUART_DMA_CONFIG DmaConfig; + VOID (*ModemStatusInd)(VOID *pAdapter); // modem status indication interrupt handler + VOID (*TxTDCallback)(VOID *pAdapter); // User Tx Done callback function + VOID (*RxDRCallback)(VOID *pAdapter); // User Rx Data ready callback function + VOID (*TxCompCallback)(VOID *para); // User Tx complete callback function + VOID (*RxCompCallback)(VOID *para); // User Rx complete callback function + VOID *TxTDCbPara; // the pointer agrument for TxTDCallback + VOID *RxDRCbPara; // the pointer agrument for RxDRCallback + VOID *TxCompCbPara; // the pointer argument for TxCompCbPara + VOID *RxCompCbPara; // the pointer argument for RxCompCallback + VOID (*EnterCritical)(void); + VOID (*ExitCritical)(void); +}HAL_RUART_ADAPTER, *PHAL_RUART_ADAPTER; + +typedef struct _HAL_RUART_OP_ { + VOID (*HalRuartAdapterLoadDef)(VOID *pAdp, u8 UartIdx); // Load UART adapter default setting + VOID (*HalRuartTxGdmaLoadDef)(VOID *pAdp, VOID *pCfg); // Load TX GDMA default setting + VOID (*HalRuartRxGdmaLoadDef)(VOID *pAdp, VOID *pCfg); // Load RX GDMA default setting + HAL_Status (*HalRuartResetRxFifo)(VOID *Data); + HAL_Status (*HalRuartInit)(VOID *Data); + VOID (*HalRuartDeInit)(VOID *Data); + HAL_Status (*HalRuartPutC)(VOID *Data, u8 TxData); + u32 (*HalRuartSend)(VOID *Data, u8 *pTxData, u32 Length, u32 Timeout); + HAL_Status (*HalRuartIntSend)(VOID *Data, u8 *pTxData, u32 Length); + HAL_Status (*HalRuartDmaSend)(VOID *Data, u8 *pTxData, u32 Length); + HAL_Status (*HalRuartStopSend)(VOID *Data); + HAL_Status (*HalRuartGetC)(VOID *Data, u8 *pRxByte); + u32 (*HalRuartRecv)(VOID *Data, u8 *pRxData, u32 Length, u32 Timeout); + HAL_Status (*HalRuartIntRecv)(VOID *Data, u8 *pRxData, u32 Length); + HAL_Status (*HalRuartDmaRecv)(VOID *Data, u8 *pRxData, u32 Length); + HAL_Status (*HalRuartStopRecv)(VOID *Data); + u8 (*HalRuartGetIMR)(VOID *Data); + VOID (*HalRuartSetIMR)(VOID *Data); + u32 (*HalRuartGetDebugValue)(VOID *Data, u32 DbgSel); + VOID (*HalRuartDmaInit)(VOID *Data); + VOID (*HalRuartRTSCtrl)(VOID *Data, BOOLEAN RtsCtrl); + VOID (*HalRuartRegIrq)(VOID *Data); + VOID (*HalRuartIntEnable)(VOID *Data); + VOID (*HalRuartIntDisable)(VOID *Data); +}HAL_RUART_OP, *PHAL_RUART_OP; + +typedef struct _RUART_DATA_ { + PHAL_RUART_ADAPTER pHalRuartAdapter; + BOOL PullMode; + u8 BinaryData; + u8 SendBuffer; + u8 RecvBuffer; +}RUART_DATA, *PRUART_DATA; + +typedef struct _RUART_ADAPTER_ { + PHAL_RUART_OP pHalRuartOp; + PHAL_RUART_ADAPTER pHalRuartAdapter; + PUART_DMA_CONFIG pHalRuartDmaCfg; +}RUART_ADAPTER, *PRUART_ADAPTER; + +extern VOID +HalRuartOpInit( + IN VOID *Data +); + +extern HAL_Status +HalRuartTxGdmaInit( + PHAL_RUART_OP pHalRuartOp, + PHAL_RUART_ADAPTER pHalRuartAdapter, + PUART_DMA_CONFIG pUartGdmaConfig +); + +extern VOID +HalRuartTxGdmaDeInit( + PUART_DMA_CONFIG pUartGdmaConfig +); + +extern HAL_Status +HalRuartRxGdmaInit( + PHAL_RUART_OP pHalRuartOp, + PHAL_RUART_ADAPTER pHalRuartAdapter, + PUART_DMA_CONFIG pUartGdmaConfig +); + +extern VOID +HalRuartRxGdmaDeInit( + PUART_DMA_CONFIG pUartGdmaConfig +); + +extern const HAL_RUART_OP _HalRuartOp; +extern HAL_Status RuartLock (PHAL_RUART_ADAPTER pHalRuartAdapter); +extern VOID RuartUnLock (PHAL_RUART_ADAPTER pHalRuartAdapter); + +#endif + diff --git a/component/soc/realtek/8195a/fwlib/hal_util.h b/component/soc/realtek/8195a/fwlib/hal_util.h new file mode 100644 index 0000000..d600ed6 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/hal_util.h @@ -0,0 +1,252 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ +#ifndef _HAL_UTIL_H_ +#define _HAL_UTIL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Simple doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ +struct LIST_HEADER { + struct LIST_HEADER *Next, *Prev; +}; + +typedef struct LIST_HEADER _LIST; + +//#define RTL_LIST_HEAD_INIT(name) { &(name), &(name) } + +#define RTL_INIT_LIST_HEAD(ptr) do { \ + (ptr)->Next = (ptr); (ptr)->Prev = (ptr); \ +} while (0) + + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ + static __inline__ VOID + __List_Add( + IN struct LIST_HEADER * New, + IN struct LIST_HEADER * Prev, + IN struct LIST_HEADER * Next +) +{ + Next->Prev = New; + New->Next = Next; + New->Prev = Prev; + Prev->Next = New; +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ + static __inline__ VOID + __List_Del( + IN struct LIST_HEADER * Prev, + IN struct LIST_HEADER * Next + ) +{ + Next->Prev = Prev; + Prev->Next = Next; +} + +/** + * ListDel - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty on entry does not return true after this, the entry is in an undefined state. + */ +static __inline__ VOID +ListDel( + IN struct LIST_HEADER *Entry +) +{ + __List_Del(Entry->Prev, Entry->Next); +} + +/** + * ListDelInit - deletes entry from list and reinitialize it. + * @entry: the element to delete from the list. + */ +static __inline__ VOID +ListDelInit( + IN struct LIST_HEADER *Entry +) +{ + __List_Del(Entry->Prev, Entry->Next); + RTL_INIT_LIST_HEAD(Entry); + +} + +/** + * ListEmpty - tests whether a list is empty + * @head: the list to test. + */ +static __inline__ u32 +ListEmpty( + IN struct LIST_HEADER *Head +) +{ + return Head->Next == Head; +} + +/** + * ListSplice - join two lists + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static __inline__ VOID +ListSplice( + IN struct LIST_HEADER *List, + IN struct LIST_HEADER *Head +) +{ + struct LIST_HEADER *First = List->Next; + + if (First != List) { + struct LIST_HEADER *Last = List->Prev; + struct LIST_HEADER *At = Head->Next; + + First->Prev = Head; + Head->Next = First; + + Last->Next = At; + At->Prev = Last; + } +} + +static __inline__ VOID +ListAdd( + IN struct LIST_HEADER *New, + IN struct LIST_HEADER *head +) +{ + __List_Add(New, head, head->Next); +} + + +static __inline__ VOID +ListAddTail( + IN struct LIST_HEADER *New, + IN struct LIST_HEADER *head +) +{ + __List_Add(New, head->Prev, head); +} + +static __inline VOID +RtlInitListhead( + IN _LIST *list +) +{ + RTL_INIT_LIST_HEAD(list); +} + + +/* +For the following list_xxx operations, +caller must guarantee the atomic context. +Otherwise, there will be racing condition. +*/ +static __inline u32 +RtlIsListEmpty( + IN _LIST *phead +) +{ + + if (ListEmpty(phead)) + return _TRUE; + else + return _FALSE; + +} + +static __inline VOID +RtlListInsertHead( + IN _LIST *plist, + IN _LIST *phead +) +{ + ListAdd(plist, phead); +} + +static __inline VOID +RtlListInsertTail( + IN _LIST *plist, + IN _LIST *phead +) +{ + ListAddTail(plist, phead); +} + + +static __inline _LIST +*RtlListGetNext( + IN _LIST *plist +) +{ + return plist->Next; +} + +static __inline VOID +RtlListDelete( + IN _LIST *plist +) +{ + ListDelInit(plist); +} + +#define RTL_LIST_CONTAINOR(ptr, type, member) \ + ((type *)((char *)(ptr)-(SIZE_T)(&((type *)0)->member))) + +#ifndef CONTAINER_OF +#define CONTAINER_OF(ptr, type, member) \ + ((type *)((char *)(ptr)-(SIZE_T)(&((type *)0)->member))) +#endif + +#define list_entry(ptr, type, member) \ + CONTAINER_OF(ptr, type, member) + +#define list_first_entry(ptr, type, member) \ + list_entry((ptr)->Next, type, member) + +#define list_next_entry(pos, member, type) \ + list_entry((pos)->member.Next, type, member) + +#define list_for_each_entry(pos, head, member, type) \ + for (pos = list_first_entry(head, type, member); \ + &pos->member != (head); \ + pos = list_next_entry(pos, member, type)) +#define list_for_each(pos, head) \ + for (pos = (head)->Next; pos != (head); pos = pos->Next) + + +#ifndef BIT + #define BIT(x) ( 1 << (x)) +#endif + +#ifdef __cplusplus +} +#endif + +#endif //_HAL_UTIL_H_ diff --git a/component/soc/realtek/8195a/fwlib/hal_vector_table.h b/component/soc/realtek/8195a/fwlib/hal_vector_table.h new file mode 100644 index 0000000..3a6d701 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/hal_vector_table.h @@ -0,0 +1,53 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + + +#ifndef _HAL_VECTOR_TABLE_H_ +#define _HAL_VECTOR_TABLE_H_ + + + + +extern _LONG_CALL_ VOID +VectorTableInitRtl8195A( + IN u32 StackP +); + +extern _LONG_CALL_ VOID +VectorTableInitForOSRtl8195A( + IN VOID *PortSVC, + IN VOID *PortPendSVH, + IN VOID *PortSysTick +); + +extern _LONG_CALL_ BOOL +VectorIrqRegisterRtl8195A( + IN PIRQ_HANDLE pIrqHandle +); + +extern _LONG_CALL_ BOOL +VectorIrqUnRegisterRtl8195A( + IN PIRQ_HANDLE pIrqHandle +); + + +extern _LONG_CALL_ VOID +VectorIrqEnRtl8195A( + IN PIRQ_HANDLE pIrqHandle +); + +extern _LONG_CALL_ VOID +VectorIrqDisRtl8195A( + IN PIRQ_HANDLE pIrqHandle +); + + +extern _LONG_CALL_ VOID +HalPeripheralIntrHandle(VOID); +#endif //_HAL_VECTOR_TABLE_H_ diff --git a/component/soc/realtek/8195a/fwlib/ram_lib/wlan/realtek/wlan_ram_map/rom/rom_wlan_ram_map.h b/component/soc/realtek/8195a/fwlib/ram_lib/wlan/realtek/wlan_ram_map/rom/rom_wlan_ram_map.h new file mode 100644 index 0000000..2944d18 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/ram_lib/wlan/realtek/wlan_ram_map/rom/rom_wlan_ram_map.h @@ -0,0 +1,9 @@ +#ifndef ROM_WLAN_RAM_MAP_H +#define ROM_WLAN_RAM_MAP_H + +struct _rom_wlan_ram_map { + unsigned char * (*rtw_malloc)(unsigned int sz); + void (*rtw_mfree)(unsigned char *pbuf, unsigned int sz); +}; + +#endif /* ROM_WLAN_RAM_MAP_H */ diff --git a/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a.h b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a.h new file mode 100644 index 0000000..ea0f430 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a.h @@ -0,0 +1,155 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ +#ifndef _HAL_8195A_H_ +#define _HAL_8195A_H_ + +#include "platform_autoconf.h" +#include "basic_types.h" +#include "section_config.h" +#include "rtl8195a_sys_on.h" +#include "rtl8195a_peri_on.h" +#include "hal_platform.h" +#include "hal_pinmux.h" +#include "hal_api.h" +#include "hal_peri_on.h" +#include "hal_misc.h" +#include "hal_irqn.h" +#include "hal_vector_table.h" +#include "hal_diag.h" +#include "hal_spi_flash.h" +#include "hal_timer.h" +#include "hal_util.h" +#include "hal_efuse.h" +#include "hal_soc_ps_monitor.h" +#include "diag.h" +#include "hal_common.h" +/* ---------------------------------------------------------------------------- + -- Cortex M3 Core Configuration + ---------------------------------------------------------------------------- */ + +/*! + * @addtogroup Cortex_Core_Configuration Cortex M0 Core Configuration + * @{ + */ + +#define __CM3_REV 0x0200 /**< Core revision r0p0 */ +#define __MPU_PRESENT 1 /**< Defines if an MPU is present or not */ +#define __NVIC_PRIO_BITS 4 /**< Number of priority bits implemented in the NVIC */ +#define __Vendor_SysTickConfig 1 /**< Vendor specific implementation of SysTickConfig is defined */ + +#include "core_cm3.h" + +#ifdef CONFIG_TIMER_EN +#include "hal_timer.h" +#endif + +#ifdef CONFIG_GDMA_EN +#include "hal_gdma.h" +#include "rtl8195a_gdma.h" +#endif + +#ifdef CONFIG_GPIO_EN +#include "hal_gpio.h" +#include "rtl8195a_gpio.h" +#endif + +#ifdef CONFIG_SPI_COM_EN +#include "hal_ssi.h" +#include "rtl8195a_ssi.h" +#endif + +#ifdef CONFIG_UART_EN +#include "hal_uart.h" +#include "rtl8195a_uart.h" +#endif + +#ifdef CONFIG_I2C_EN +#include "hal_i2c.h" +#include "rtl8195a_i2c.h" +#endif + +#ifdef CONFIG_PCM_EN +#include "hal_pcm.h" +#include "rtl8195a_pcm.h" +#endif + +#ifdef CONFIG_PWM_EN +#include "hal_pwm.h" +#include "rtl8195a_pwm.h" +#endif + +#ifdef CONFIG_I2S_EN +#include "hal_i2s.h" +#include "rtl8195a_i2s.h" +#endif + +#ifdef CONFIG_DAC_EN +#include "hal_dac.h" +#include "rtl8195a_dac.h" +#endif + +#ifdef CONFIG_ADC_EN +#include "hal_adc.h" +#include "rtl8195a_adc.h" +#endif + +#ifdef CONFIG_SDR_EN +#endif + +#ifdef CONFIG_SPIC_EN +#endif + +#ifdef CONFIG_SDIO_DEVICE_EN +#include "hal_sdio.h" +#endif + +#ifdef CONFIG_NFC_EN +#include "hal_nfc.h" +#include "rtl8195a_nfc.h" +#endif + +#if CONFIG_WDG +#include "rtl8195a_wdt.h" +#endif + +#ifdef CONFIG_USB_EN +#include "hal_usb.h" +#include "rtl8195a_usb.h" +#endif + + +// firmware information, located at the header of Image2 +#define FW_VERSION (0x0100) +#define FW_SUBVERSION (0x0001) +#define FW_CHIP_ID (0x8195) +#define FW_CHIP_VER (0x01) +#define FW_BUS_TYPE (0x01) // the iNIC firmware type: USB/SDIO +#define FW_INFO_RSV1 (0x00) // the firmware information reserved +#define FW_INFO_RSV2 (0x00) // the firmware information reserved +#define FW_INFO_RSV3 (0x00) // the firmware information reserved +#define FW_INFO_RSV4 (0x00) // the firmware information reserved + +#define FLASH_RESERVED_DATA_BASE 0x8000 // reserve 32K for Image1 +#define FLASH_SYSTEM_DATA_ADDR 0x9000 // reserve 32K+4K for Image1 + Reserved data +// Flash Map for Calibration data +#define FLASH_CAL_DATA_BASE 0xA000 +#define FLASH_CAL_DATA_ADDR(_offset) (FLASH_CAL_DATA_BASE + _offset) +#define FLASH_CAL_DATA_SIZE 0x1000 +#define FLASH_SECTOR_SIZE 0x1000 +// SPIC Calibration Data +#define FLASH_SPIC_PARA_OFFSET 0x80 +#define FLASH_SPIC_PARA_BASE (FLASH_SYSTEM_DATA_ADDR+FLASH_SPIC_PARA_OFFSET) +// SDRC Calibration Data +#define FLASH_SDRC_PARA_OFFSET 0x180 +#define FLASH_SDRC_PARA_BASE (FLASH_SYSTEM_DATA_ADDR+FLASH_SDRC_PARA_OFFSET) +// ADC Calibration Data +#define FLASH_ADC_PARA_OFFSET 0x200 +#define FLASH_ADC_PARA_BASE (FLASH_SYSTEM_DATA_ADDR+FLASH_ADC_PARA_OFFSET) + +#endif //_HAL_8195A_H_ diff --git a/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_adc.h b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_adc.h new file mode 100644 index 0000000..48240b0 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_adc.h @@ -0,0 +1,350 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#ifndef _RTL8195A_ADC_H_ +#define _RTL8195A_ADC_H_ + + +//================ Register Bit Field ========================== +//2 REG_ADC_FIFO_READ + +#define BIT_SHIFT_ADC_FIFO_RO 0 +#define BIT_MASK_ADC_FIFO_RO 0xffffffffL +#define BIT_ADC_FIFO_RO(x) (((x) & BIT_MASK_ADC_FIFO_RO) << BIT_SHIFT_ADC_FIFO_RO) +#define BIT_CTRL_ADC_FIFO_RO(x) (((x) & BIT_MASK_ADC_FIFO_RO) << BIT_SHIFT_ADC_FIFO_RO) +#define BIT_GET_ADC_FIFO_RO(x) (((x) >> BIT_SHIFT_ADC_FIFO_RO) & BIT_MASK_ADC_FIFO_RO) + + +//2 REG_ADC_CONTROL + +#define BIT_SHIFT_ADC_DBG_SEL 24 +#define BIT_MASK_ADC_DBG_SEL 0x7 +#define BIT_ADC_DBG_SEL(x) (((x) & BIT_MASK_ADC_DBG_SEL) << BIT_SHIFT_ADC_DBG_SEL) +#define BIT_CTRL_ADC_DBG_SEL(x) (((x) & BIT_MASK_ADC_DBG_SEL) << BIT_SHIFT_ADC_DBG_SEL) +#define BIT_GET_ADC_DBG_SEL(x) (((x) >> BIT_SHIFT_ADC_DBG_SEL) & BIT_MASK_ADC_DBG_SEL) + + +#define BIT_SHIFT_ADC_THRESHOLD 16 +#define BIT_MASK_ADC_THRESHOLD 0x3f +#define BIT_ADC_THRESHOLD(x) (((x) & BIT_MASK_ADC_THRESHOLD) << BIT_SHIFT_ADC_THRESHOLD) +#define BIT_CTRL_ADC_THRESHOLD(x) (((x) & BIT_MASK_ADC_THRESHOLD) << BIT_SHIFT_ADC_THRESHOLD) +#define BIT_GET_ADC_THRESHOLD(x) (((x) >> BIT_SHIFT_ADC_THRESHOLD) & BIT_MASK_ADC_THRESHOLD) + + +#define BIT_SHIFT_ADC_BURST_SIZE 8 +#define BIT_MASK_ADC_BURST_SIZE 0x1f +#define BIT_ADC_BURST_SIZE(x) (((x) & BIT_MASK_ADC_BURST_SIZE) << BIT_SHIFT_ADC_BURST_SIZE) +#define BIT_CTRL_ADC_BURST_SIZE(x) (((x) & BIT_MASK_ADC_BURST_SIZE) << BIT_SHIFT_ADC_BURST_SIZE) +#define BIT_GET_ADC_BURST_SIZE(x) (((x) >> BIT_SHIFT_ADC_BURST_SIZE) & BIT_MASK_ADC_BURST_SIZE) + +#define BIT_ADC_ENDIAN BIT(3) +#define BIT_SHIFT_ADC_ENDIAN 3 +#define BIT_MASK_ADC_ENDIAN 0x1 +#define BIT_CTRL_ADC_ENDIAN(x) (((x) & BIT_MASK_ADC_ENDIAN) << BIT_SHIFT_ADC_ENDIAN) + +#define BIT_ADC_OVERWRITE BIT(2) +#define BIT_SHIFT_ADC_OVERWRITE 2 +#define BIT_MASK_ADC_OVERWRITE 0x1 +#define BIT_CTRL_ADC_OVERWRITE(x) (((x) & BIT_MASK_ADC_OVERWRITE) << BIT_SHIFT_ADC_OVERWRITE) + +#define BIT_ADC_ONESHOT BIT(1) +#define BIT_SHIFT_ADC_ONESHOT 1 +#define BIT_MASK_ADC_ONESHOT 0x1 +#define BIT_CTRL_ADC_ONESHOT(x) (((x) & BIT_MASK_ADC_ONESHOT) << BIT_SHIFT_ADC_ONESHOT) + +#define BIT_ADC_COMP_ONLY BIT(0) +#define BIT_SHIFT_ADC_COMP_ONLY 0 +#define BIT_MASK_ADC_COMP_ONLY 0x1 +#define BIT_CTRL_ADC_COMP_ONLY(x) (((x) & BIT_MASK_ADC_COMP_ONLY) << BIT_SHIFT_ADC_COMP_ONLY) + + +//2 REG_ADC_INTR_EN +#define BIT_ADC_AWAKE_CPU_EN BIT(7) +#define BIT_SHIFT_ADC_AWAKE_CPU_EN 7 +#define BIT_MASK_ADC_AWAKE_CPU_EN 0x1 +#define BIT_CTRL_ADC_AWAKE_CPU_EN(x) (((x) & BIT_MASK_ADC_AWAKE_CPU_EN) << BIT_SHIFT_ADC_AWAKE_CPU_EN) + +#define BIT_ADC_FIFO_RD_ERROR_EN BIT(6) +#define BIT_SHIFT_ADC_FIFO_RD_ERROR_EN 6 +#define BIT_MASK_ADC_FIFO_RD_ERROR_EN 0x1 +#define BIT_CTRL_ADC_FIFO_RD_ERROR_EN(x) (((x) & BIT_MASK_ADC_FIFO_RD_ERROR_EN) << BIT_SHIFT_ADC_FIFO_RD_ERROR_EN) + +#define BIT_ADC_FIFO_RD_REQ_EN BIT(5) +#define BIT_SHIFT_ADC_FIFO_RD_REQ_EN 5 +#define BIT_MASK_ADC_FIFO_RD_REQ_EN 0x1 +#define BIT_CTRL_ADC_FIFO_RD_REQ_EN(x) (((x) & BIT_MASK_ADC_FIFO_RD_REQ_EN) << BIT_SHIFT_ADC_FIFO_RD_REQ_EN) + +#define BIT_ADC_FIFO_FULL_EN BIT(4) +#define BIT_SHIFT_ADC_FIFO_FULL_EN 4 +#define BIT_MASK_ADC_FIFO_FULL_EN 0x1 +#define BIT_CTRL_ADC_FIFO_FULL_EN(x) (((x) & BIT_MASK_ADC_FIFO_FULL_EN) << BIT_SHIFT_ADC_FIFO_FULL_EN) + +#define BIT_ADC_COMP_3_EN BIT(3) +#define BIT_SHIFT_ADC_COMP_3_EN 3 +#define BIT_MASK_ADC_COMP_3_EN 0x1 +#define BIT_CTRL_ADC_COMP_3_EN(x) (((x) & BIT_MASK_ADC_COMP_3_EN) << BIT_SHIFT_ADC_COMP_3_EN) + +#define BIT_ADC_COMP_2_EN BIT(2) +#define BIT_SHIFT_ADC_COMP_2_EN 2 +#define BIT_MASK_ADC_COMP_2_EN 0x1 +#define BIT_CTRL_ADC_COMP_2_EN(x) (((x) & BIT_MASK_ADC_COMP_2_EN) << BIT_SHIFT_ADC_COMP_2_EN) + +#define BIT_ADC_COMP_1_EN BIT(1) +#define BIT_SHIFT_ADC_COMP_1_EN 1 +#define BIT_MASK_ADC_COMP_1_EN 0x1 +#define BIT_CTRL_ADC_COMP_1_EN(x) (((x) & BIT_MASK_ADC_COMP_1_EN) << BIT_SHIFT_ADC_COMP_1_EN) + +#define BIT_ADC_COMP_0_EN BIT(0) +#define BIT_SHIFT_ADC_COMP_0_EN 0 +#define BIT_MASK_ADC_COMP_0_EN 0x1 +#define BIT_CTRL_ADC_COMP_0_EN(x) (((x) & BIT_MASK_ADC_COMP_0_EN) << BIT_SHIFT_ADC_COMP_0_EN) + + +//2 REG_ADC_INTR_STS +#define BIT_ADC_FIFO_THRESHOLD BIT(7) +#define BIT_SHIFT_ADC_FIFO_THRESHOLD 7 +#define BIT_MASK_ADC_FIFO_THRESHOLD 0x1 +#define BIT_CTRL_ADC_FIFO_THRESHOLD(x) (((x) & BIT_MASK_ADC_FIFO_THRESHOLD) << BIT_SHIFT_ADC_FIFO_THRESHOLD) + +#define BIT_ADC_FIFO_RD_ERROR_ST BIT(6) +#define BIT_SHIFT_ADC_FIFO_RD_ERROR_ST 6 +#define BIT_MASK_ADC_FIFO_RD_ERROR_ST 0x1 +#define BIT_CTRL_ADC_FIFO_RD_ERROR_ST(x) (((x) & BIT_MASK_ADC_FIFO_RD_ERROR_ST) << BIT_SHIFT_ADC_FIFO_RD_ERROR_ST) + +#define BIT_ADC_FIFO_RD_REQ_ST BIT(5) +#define BIT_SHIFT_ADC_FIFO_RD_REQ_ST 5 +#define BIT_MASK_ADC_FIFO_RD_REQ_ST 0x1 +#define BIT_CTRL_ADC_FIFO_RD_REQ_ST(x) (((x) & BIT_MASK_ADC_FIFO_RD_REQ_ST) << BIT_SHIFT_ADC_FIFO_RD_REQ_ST) + +#define BIT_ADC_FIFO_FULL_ST BIT(4) +#define BIT_SHIFT_ADC_FIFO_FULL_ST 4 +#define BIT_MASK_ADC_FIFO_FULL_ST 0x1 +#define BIT_CTRL_ADC_FIFO_FULL_ST(x) (((x) & BIT_MASK_ADC_FIFO_FULL_ST) << BIT_SHIFT_ADC_FIFO_FULL_ST) + +#define BIT_ADC_COMP_3_ST BIT(3) +#define BIT_SHIFT_ADC_COMP_3_ST 3 +#define BIT_MASK_ADC_COMP_3_ST 0x1 +#define BIT_CTRL_ADC_COMP_3_ST(x) (((x) & BIT_MASK_ADC_COMP_3_ST) << BIT_SHIFT_ADC_COMP_3_ST) + +#define BIT_ADC_COMP_2_ST BIT(2) +#define BIT_SHIFT_ADC_COMP_2_ST 2 +#define BIT_MASK_ADC_COMP_2_ST 0x1 +#define BIT_CTRL_ADC_COMP_2_ST(x) (((x) & BIT_MASK_ADC_COMP_2_ST) << BIT_SHIFT_ADC_COMP_2_ST) + +#define BIT_ADC_COMP_1_ST BIT(1) +#define BIT_SHIFT_ADC_COMP_1_ST 1 +#define BIT_MASK_ADC_COMP_1_ST 0x1 +#define BIT_CTRL_ADC_COMP_1_ST(x) (((x) & BIT_MASK_ADC_COMP_1_ST) << BIT_SHIFT_ADC_COMP_1_ST) + +#define BIT_ADC_COMP_0_ST BIT(0) +#define BIT_SHIFT_ADC_COMP_0_ST 0 +#define BIT_MASK_ADC_COMP_0_ST 0x1 +#define BIT_CTRL_ADC_COMP_0_ST(x) (((x) & BIT_MASK_ADC_COMP_0_ST) << BIT_SHIFT_ADC_COMP_0_ST) + + +//2 REG_ADC_COMP_VALUE_L + +#define BIT_SHIFT_ADC_COMP_TH_1 16 +#define BIT_MASK_ADC_COMP_TH_1 0xffff +#define BIT_ADC_COMP_TH_1(x) (((x) & BIT_MASK_ADC_COMP_TH_1) << BIT_SHIFT_ADC_COMP_TH_1) +#define BIT_CTRL_ADC_COMP_TH_1(x) (((x) & BIT_MASK_ADC_COMP_TH_1) << BIT_SHIFT_ADC_COMP_TH_1) +#define BIT_GET_ADC_COMP_TH_1(x) (((x) >> BIT_SHIFT_ADC_COMP_TH_1) & BIT_MASK_ADC_COMP_TH_1) + + +#define BIT_SHIFT_ADC_COMP_TH_0 0 +#define BIT_MASK_ADC_COMP_TH_0 0xffff +#define BIT_ADC_COMP_TH_0(x) (((x) & BIT_MASK_ADC_COMP_TH_0) << BIT_SHIFT_ADC_COMP_TH_0) +#define BIT_CTRL_ADC_COMP_TH_0(x) (((x) & BIT_MASK_ADC_COMP_TH_0) << BIT_SHIFT_ADC_COMP_TH_0) +#define BIT_GET_ADC_COMP_TH_0(x) (((x) >> BIT_SHIFT_ADC_COMP_TH_0) & BIT_MASK_ADC_COMP_TH_0) + + +//2 REG_ADC_COMP_VALUE_H + +#define BIT_SHIFT_ADC_COMP_TH_3 16 +#define BIT_MASK_ADC_COMP_TH_3 0xffff +#define BIT_ADC_COMP_TH_3(x) (((x) & BIT_MASK_ADC_COMP_TH_3) << BIT_SHIFT_ADC_COMP_TH_3) +#define BIT_CTRL_ADC_COMP_TH_3(x) (((x) & BIT_MASK_ADC_COMP_TH_3) << BIT_SHIFT_ADC_COMP_TH_3) +#define BIT_GET_ADC_COMP_TH_3(x) (((x) >> BIT_SHIFT_ADC_COMP_TH_3) & BIT_MASK_ADC_COMP_TH_3) + + +#define BIT_SHIFT_ADC_COMP_TH_2 0 +#define BIT_MASK_ADC_COMP_TH_2 0xffff +#define BIT_ADC_COMP_TH_2(x) (((x) & BIT_MASK_ADC_COMP_TH_2) << BIT_SHIFT_ADC_COMP_TH_2) +#define BIT_CTRL_ADC_COMP_TH_2(x) (((x) & BIT_MASK_ADC_COMP_TH_2) << BIT_SHIFT_ADC_COMP_TH_2) +#define BIT_GET_ADC_COMP_TH_2(x) (((x) >> BIT_SHIFT_ADC_COMP_TH_2) & BIT_MASK_ADC_COMP_TH_2) + + +//2 REG_ADC_COMP_SET + +#define BIT_SHIFT_ADC_GREATER_THAN 0 +#define BIT_MASK_ADC_GREATER_THAN 0xf +#define BIT_ADC_GREATER_THAN(x) (((x) & BIT_MASK_ADC_GREATER_THAN) << BIT_SHIFT_ADC_GREATER_THAN) +#define BIT_CTRL_ADC_GREATER_THAN(x) (((x) & BIT_MASK_ADC_GREATER_THAN) << BIT_SHIFT_ADC_GREATER_THAN) +#define BIT_GET_ADC_GREATER_THAN(x) (((x) >> BIT_SHIFT_ADC_GREATER_THAN) & BIT_MASK_ADC_GREATER_THAN) + + +//2 REG_ADC_POWER + +#define BIT_SHIFT_ADC_PWR_CUT_CNTR 16 +#define BIT_MASK_ADC_PWR_CUT_CNTR 0xff +#define BIT_ADC_PWR_CUT_CNTR(x) (((x) & BIT_MASK_ADC_PWR_CUT_CNTR) << BIT_SHIFT_ADC_PWR_CUT_CNTR) +#define BIT_CTRL_ADC_PWR_CUT_CNTR(x) (((x) & BIT_MASK_ADC_PWR_CUT_CNTR) << BIT_SHIFT_ADC_PWR_CUT_CNTR) +#define BIT_GET_ADC_PWR_CUT_CNTR(x) (((x) >> BIT_SHIFT_ADC_PWR_CUT_CNTR) & BIT_MASK_ADC_PWR_CUT_CNTR) + +#define BIT_ADC_FIFO_ON_ST BIT(11) +#define BIT_SHIFT_ADC_FIFO_ON_ST 11 +#define BIT_MASK_ADC_FIFO_ON_ST 0x1 +#define BIT_CTRL_ADC_FIFO_ON_ST(x) (((x) & BIT_MASK_ADC_FIFO_ON_ST) << BIT_SHIFT_ADC_FIFO_ON_ST) + +#define BIT_ADC_ISO_ON_ST BIT(10) +#define BIT_SHIFT_ADC_ISO_ON_ST 10 +#define BIT_MASK_ADC_ISO_ON_ST 0x1 +#define BIT_CTRL_ADC_ISO_ON_ST(x) (((x) & BIT_MASK_ADC_ISO_ON_ST) << BIT_SHIFT_ADC_ISO_ON_ST) + +#define BIT_ADC_PWR33_ON_ST BIT(9) +#define BIT_SHIFT_ADC_PWR33_ON_ST 9 +#define BIT_MASK_ADC_PWR33_ON_ST 0x1 +#define BIT_CTRL_ADC_PWR33_ON_ST(x) (((x) & BIT_MASK_ADC_PWR33_ON_ST) << BIT_SHIFT_ADC_PWR33_ON_ST) + +#define BIT_ADC_PWR12_ON_ST BIT(8) +#define BIT_SHIFT_ADC_PWR12_ON_ST 8 +#define BIT_MASK_ADC_PWR12_ON_ST 0x1 +#define BIT_CTRL_ADC_PWR12_ON_ST(x) (((x) & BIT_MASK_ADC_PWR12_ON_ST) << BIT_SHIFT_ADC_PWR12_ON_ST) + +#define BIT_ADC_ISO_MANUAL BIT(3) +#define BIT_SHIFT_ADC_ISO_MANUAL 3 +#define BIT_MASK_ADC_ISO_MANUAL 0x1 +#define BIT_CTRL_ADC_ISO_MANUAL(x) (((x) & BIT_MASK_ADC_ISO_MANUAL) << BIT_SHIFT_ADC_ISO_MANUAL) + +#define BIT_ADC_PWR33_MANUAL BIT(2) +#define BIT_SHIFT_ADC_PWR33_MANUAL 2 +#define BIT_MASK_ADC_PWR33_MANUAL 0x1 +#define BIT_CTRL_ADC_PWR33_MANUAL(x) (((x) & BIT_MASK_ADC_PWR33_MANUAL) << BIT_SHIFT_ADC_PWR33_MANUAL) + +#define BIT_ADC_PWR12_MANUAL BIT(1) +#define BIT_SHIFT_ADC_PWR12_MANUAL 1 +#define BIT_MASK_ADC_PWR12_MANUAL 0x1 +#define BIT_CTRL_ADC_PWR12_MANUAL(x) (((x) & BIT_MASK_ADC_PWR12_MANUAL) << BIT_SHIFT_ADC_PWR12_MANUAL) + +#define BIT_ADC_PWR_AUTO BIT(0) +#define BIT_SHIFT_ADC_PWR_AUTO 0 +#define BIT_MASK_ADC_PWR_AUTO 0x1 +#define BIT_CTRL_ADC_PWR_AUTO(x) (((x) & BIT_MASK_ADC_PWR_AUTO) << BIT_SHIFT_ADC_PWR_AUTO) + + +//2 REG_ADC_ANAPAR_AD0 + +#define BIT_SHIFT_ADC_ANAPAR_AD0 2 +#define BIT_MASK_ADC_ANAPAR_AD0 0x3fffffff +#define BIT_ADC_ANAPAR_AD0(x) (((x) & BIT_MASK_ADC_ANAPAR_AD0) << BIT_SHIFT_ADC_ANAPAR_AD0) +#define BIT_CTRL_ADC_ANAPAR_AD0(x) (((x) & BIT_MASK_ADC_ANAPAR_AD0) << BIT_SHIFT_ADC_ANAPAR_AD0) +#define BIT_GET_ADC_ANAPAR_AD0(x) (((x) >> BIT_SHIFT_ADC_ANAPAR_AD0) & BIT_MASK_ADC_ANAPAR_AD0) + +#define BIT_ADC_AUDIO_EN BIT(1) +#define BIT_SHIFT_ADC_AUDIO_EN 1 +#define BIT_MASK_ADC_AUDIO_EN 0x1 +#define BIT_CTRL_ADC_AUDIO_EN(x) (((x) & BIT_MASK_ADC_AUDIO_EN) << BIT_SHIFT_ADC_AUDIO_EN) + +#define BIT_ADC_EN_MANUAL BIT(0) +#define BIT_SHIFT_ADC_EN_MANUAL 0 +#define BIT_MASK_ADC_EN_MANUAL 0x1 +#define BIT_CTRL_ADC_EN_MANUAL(x) (((x) & BIT_MASK_ADC_EN_MANUAL) << BIT_SHIFT_ADC_EN_MANUAL) + + +//2 REG_ADC_ANAPAR_AD1 + +#define BIT_SHIFT_ADC_ANAPAR_AD1 0 +#define BIT_MASK_ADC_ANAPAR_AD1 0xffffffffL +#define BIT_ADC_ANAPAR_AD1(x) (((x) & BIT_MASK_ADC_ANAPAR_AD1) << BIT_SHIFT_ADC_ANAPAR_AD1) +#define BIT_CTRL_ADC_ANAPAR_AD1(x) (((x) & BIT_MASK_ADC_ANAPAR_AD1) << BIT_SHIFT_ADC_ANAPAR_AD1) +#define BIT_GET_ADC_ANAPAR_AD1(x) (((x) >> BIT_SHIFT_ADC_ANAPAR_AD1) & BIT_MASK_ADC_ANAPAR_AD1) + + +//2 REG_ADC_ANAPAR_AD2 + +#define BIT_SHIFT_ADC_ANAPAR_AD2 0 +#define BIT_MASK_ADC_ANAPAR_AD2 0xffffffffL +#define BIT_ADC_ANAPAR_AD2(x) (((x) & BIT_MASK_ADC_ANAPAR_AD2) << BIT_SHIFT_ADC_ANAPAR_AD2) +#define BIT_CTRL_ADC_ANAPAR_AD2(x) (((x) & BIT_MASK_ADC_ANAPAR_AD2) << BIT_SHIFT_ADC_ANAPAR_AD2) +#define BIT_GET_ADC_ANAPAR_AD2(x) (((x) >> BIT_SHIFT_ADC_ANAPAR_AD2) & BIT_MASK_ADC_ANAPAR_AD2) + + +//2 REG_ADC_ANAPAR_AD3 + +#define BIT_SHIFT_ADC_ANAPAR_AD3 0 +#define BIT_MASK_ADC_ANAPAR_AD3 0xffffffffL +#define BIT_ADC_ANAPAR_AD3(x) (((x) & BIT_MASK_ADC_ANAPAR_AD3) << BIT_SHIFT_ADC_ANAPAR_AD3) +#define BIT_CTRL_ADC_ANAPAR_AD3(x) (((x) & BIT_MASK_ADC_ANAPAR_AD3) << BIT_SHIFT_ADC_ANAPAR_AD3) +#define BIT_GET_ADC_ANAPAR_AD3(x) (((x) >> BIT_SHIFT_ADC_ANAPAR_AD3) & BIT_MASK_ADC_ANAPAR_AD3) + + +//2 REG_ADC_ANAPAR_AD4 + +#define BIT_SHIFT_ADC_ANAPAR_AD4 0 +#define BIT_MASK_ADC_ANAPAR_AD4 0xffffffffL +#define BIT_ADC_ANAPAR_AD4(x) (((x) & BIT_MASK_ADC_ANAPAR_AD4) << BIT_SHIFT_ADC_ANAPAR_AD4) +#define BIT_CTRL_ADC_ANAPAR_AD4(x) (((x) & BIT_MASK_ADC_ANAPAR_AD4) << BIT_SHIFT_ADC_ANAPAR_AD4) +#define BIT_GET_ADC_ANAPAR_AD4(x) (((x) >> BIT_SHIFT_ADC_ANAPAR_AD4) & BIT_MASK_ADC_ANAPAR_AD4) + + +//2 REG_ADC_ANAPAR_AD5 + +#define BIT_SHIFT_ADC_ANAPAR_AD5 0 +#define BIT_MASK_ADC_ANAPAR_AD5 0xffffffffL +#define BIT_ADC_ANAPAR_AD5(x) (((x) & BIT_MASK_ADC_ANAPAR_AD5) << BIT_SHIFT_ADC_ANAPAR_AD5) +#define BIT_CTRL_ADC_ANAPAR_AD5(x) (((x) & BIT_MASK_ADC_ANAPAR_AD5) << BIT_SHIFT_ADC_ANAPAR_AD5) +#define BIT_GET_ADC_ANAPAR_AD5(x) (((x) >> BIT_SHIFT_ADC_ANAPAR_AD5) & BIT_MASK_ADC_ANAPAR_AD5) + + +//2 REG_ADC_CALI_DATA + +#define BIT_SHIFT_ADC_CALI_DATA_6 16 +#define BIT_MASK_ADC_CALI_DATA_6 0xffff +#define BIT_ADC_CALI_DATA_6(x) (((x) & BIT_MASK_ADC_CALI_DATA_6) << BIT_SHIFT_ADC_CALI_DATA_6) +#define BIT_CTRL_ADC_CALI_DATA_6(x) (((x) & BIT_MASK_ADC_CALI_DATA_6) << BIT_SHIFT_ADC_CALI_DATA_6) +#define BIT_GET_ADC_CALI_DATA_6(x) (((x) >> BIT_SHIFT_ADC_CALI_DATA_6) & BIT_MASK_ADC_CALI_DATA_6) + + +#define BIT_SHIFT_ADC_CALI_DATA_0 0 +#define BIT_MASK_ADC_CALI_DATA_0 0xffff +#define BIT_ADC_CALI_DATA_0(x) (((x) & BIT_MASK_ADC_CALI_DATA_0) << BIT_SHIFT_ADC_CALI_DATA_0) +#define BIT_CTRL_ADC_CALI_DATA_0(x) (((x) & BIT_MASK_ADC_CALI_DATA_0) << BIT_SHIFT_ADC_CALI_DATA_0) +#define BIT_GET_ADC_CALI_DATA_0(x) (((x) >> BIT_SHIFT_ADC_CALI_DATA_0) & BIT_MASK_ADC_CALI_DATA_0) + +//================ Register Reg Field ========================= +#define REG_ADC_FIFO_READ 0x0000 +#define REG_ADC_CONTROL 0x0004 +#define REG_ADC_INTR_EN 0x0008 +#define REG_ADC_INTR_STS 0x000C +#define REG_ADC_COMP_VALUE_L 0x0010 +#define REG_ADC_COMP_VALUE_H 0x0014 +#define REG_ADC_COMP_SET 0x0018 +#define REG_ADC_POWER 0x001C +#define REG_ADC_ANAPAR_AD0 0x0020 +#define REG_ADC_ANAPAR_AD1 0x0024 +#define REG_ADC_ANAPAR_AD2 0x0028 +#define REG_ADC_ANAPAR_AD3 0x002C +#define REG_ADC_ANAPAR_AD4 0x0030 +#define REG_ADC_ANAPAR_AD5 0x0034 +#define REG_ADC_CALI_DATA 0x0038 + +//================ ADC HAL related enumeration ================== + +//================ ADC Function Prototypes ===================== +#define HAL_ADC_WRITE32(addr, value) HAL_WRITE32(ADC_REG_BASE,addr,value) +#define HAL_ADC_READ32(addr) HAL_READ32(ADC_REG_BASE,addr) + +RTK_STATUS HalADCInit8195a(IN VOID *Data); +RTK_STATUS HalADCDeInit8195a(IN VOID *Data); +RTK_STATUS HalADCEnableRtl8195a(IN VOID *Data); +RTK_STATUS HalADCIntrCtrl8195a(IN VOID *Data); +u32 HalADCReceiveRtl8195a(IN VOID *Data); +u32 HalADCReadRegRtl8195a(IN VOID *Data,IN u8 I2CReg); + +#endif diff --git a/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_dac.h b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_dac.h new file mode 100644 index 0000000..c3a9861 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_dac.h @@ -0,0 +1,294 @@ +#ifndef _RTL8195A_DAC_H_ +#define _RTL8195A_DAC_H_ + +//================ Register Bit Field ========================== +//2 REG_DAC0_FIFO_WR + +#define BIT_SHIFT_DAC0_FIFO_WO 0 +#define BIT_MASK_DAC0_FIFO_WO 0xffffffffL +#define BIT_DAC0_FIFO_WO(x) (((x) & BIT_MASK_DAC0_FIFO_WO) << BIT_SHIFT_DAC0_FIFO_WO) +#define BIT_CTRL_DAC0_FIFO_WO(x) (((x) & BIT_MASK_DAC0_FIFO_WO) << BIT_SHIFT_DAC0_FIFO_WO) +#define BIT_GET_DAC0_FIFO_WO(x) (((x) >> BIT_SHIFT_DAC0_FIFO_WO) & BIT_MASK_DAC0_FIFO_WO) + + +//2 REG_DAC_CTRL + +#define BIT_SHIFT_DAC_DELTA_SIGMA 25 +#define BIT_MASK_DAC_DELTA_SIGMA 0x7 +#define BIT_DAC_DELTA_SIGMA(x) (((x) & BIT_MASK_DAC_DELTA_SIGMA) << BIT_SHIFT_DAC_DELTA_SIGMA) +#define BIT_CTRL_DAC_DELTA_SIGMA(x) (((x) & BIT_MASK_DAC_DELTA_SIGMA) << BIT_SHIFT_DAC_DELTA_SIGMA) +#define BIT_GET_DAC_DELTA_SIGMA(x) (((x) >> BIT_SHIFT_DAC_DELTA_SIGMA) & BIT_MASK_DAC_DELTA_SIGMA) + +#define BIT_DAC_BYPASS_DSC BIT(24) +#define BIT_SHIFT_DAC_BYPASS_DSC 24 +#define BIT_MASK_DAC_BYPASS_DSC 0x1 +#define BIT_CTRL_DAC_BYPASS_DSC(x) (((x) & BIT_MASK_DAC_BYPASS_DSC) << BIT_SHIFT_DAC_BYPASS_DSC) + + +#define BIT_SHIFT_DAC_DSC_DBG_SEL 19 +#define BIT_MASK_DAC_DSC_DBG_SEL 0x3 +#define BIT_DAC_DSC_DBG_SEL(x) (((x) & BIT_MASK_DAC_DSC_DBG_SEL) << BIT_SHIFT_DAC_DSC_DBG_SEL) +#define BIT_CTRL_DAC_DSC_DBG_SEL(x) (((x) & BIT_MASK_DAC_DSC_DBG_SEL) << BIT_SHIFT_DAC_DSC_DBG_SEL) +#define BIT_GET_DAC_DSC_DBG_SEL(x) (((x) >> BIT_SHIFT_DAC_DSC_DBG_SEL) & BIT_MASK_DAC_DSC_DBG_SEL) + + +#define BIT_SHIFT_DAC_DBG_SEL 16 +#define BIT_MASK_DAC_DBG_SEL 0x7 +#define BIT_DAC_DBG_SEL(x) (((x) & BIT_MASK_DAC_DBG_SEL) << BIT_SHIFT_DAC_DBG_SEL) +#define BIT_CTRL_DAC_DBG_SEL(x) (((x) & BIT_MASK_DAC_DBG_SEL) << BIT_SHIFT_DAC_DBG_SEL) +#define BIT_GET_DAC_DBG_SEL(x) (((x) >> BIT_SHIFT_DAC_DBG_SEL) & BIT_MASK_DAC_DBG_SEL) + + +#define BIT_SHIFT_DAC_BURST_SIZE 8 +#define BIT_MASK_DAC_BURST_SIZE 0xf +#define BIT_DAC_BURST_SIZE(x) (((x) & BIT_MASK_DAC_BURST_SIZE) << BIT_SHIFT_DAC_BURST_SIZE) +#define BIT_CTRL_DAC_BURST_SIZE(x) (((x) & BIT_MASK_DAC_BURST_SIZE) << BIT_SHIFT_DAC_BURST_SIZE) +#define BIT_GET_DAC_BURST_SIZE(x) (((x) >> BIT_SHIFT_DAC_BURST_SIZE) & BIT_MASK_DAC_BURST_SIZE) + +#define BIT_DAC_FILTER_SETTLE BIT(4) +#define BIT_SHIFT_DAC_FILTER_SETTLE 4 +#define BIT_MASK_DAC_FILTER_SETTLE 0x1 +#define BIT_CTRL_DAC_FILTER_SETTLE(x) (((x) & BIT_MASK_DAC_FILTER_SETTLE) << BIT_SHIFT_DAC_FILTER_SETTLE) + +#define BIT_DAC_OV_OPTION BIT(3) +#define BIT_SHIFT_DAC_OV_OPTION 3 +#define BIT_MASK_DAC_OV_OPTION 0x1 +#define BIT_CTRL_DAC_OV_OPTION(x) (((x) & BIT_MASK_DAC_OV_OPTION) << BIT_SHIFT_DAC_OV_OPTION) + +#define BIT_DAC_ENDIAN BIT(2) +#define BIT_SHIFT_DAC_ENDIAN 2 +#define BIT_MASK_DAC_ENDIAN 0x1 +#define BIT_CTRL_DAC_ENDIAN(x) (((x) & BIT_MASK_DAC_ENDIAN) << BIT_SHIFT_DAC_ENDIAN) + +#define BIT_DAC_SPEED BIT(1) +#define BIT_SHIFT_DAC_SPEED 1 +#define BIT_MASK_DAC_SPEED 0x1 +#define BIT_CTRL_DAC_SPEED(x) (((x) & BIT_MASK_DAC_SPEED) << BIT_SHIFT_DAC_SPEED) + +#define BIT_DAC_FIFO_EN BIT(0) +#define BIT_SHIFT_DAC_FIFO_EN 0 +#define BIT_MASK_DAC_FIFO_EN 0x1 +#define BIT_CTRL_DAC_FIFO_EN(x) (((x) & BIT_MASK_DAC_FIFO_EN) << BIT_SHIFT_DAC_FIFO_EN) + + +//2 REG_DAC_INTR_CTRL +#define BIT_DAC_DSC_OVERFLOW1_EN BIT(6) +#define BIT_SHIFT_DAC_DSC_OVERFLOW1_EN 6 +#define BIT_MASK_DAC_DSC_OVERFLOW1_EN 0x1 +#define BIT_CTRL_DAC_DSC_OVERFLOW1_EN(x) (((x) & BIT_MASK_DAC_DSC_OVERFLOW1_EN) << BIT_SHIFT_DAC_DSC_OVERFLOW1_EN) + +#define BIT_DAC_DSC_OVERFLOW0_EN BIT(5) +#define BIT_SHIFT_DAC_DSC_OVERFLOW0_EN 5 +#define BIT_MASK_DAC_DSC_OVERFLOW0_EN 0x1 +#define BIT_CTRL_DAC_DSC_OVERFLOW0_EN(x) (((x) & BIT_MASK_DAC_DSC_OVERFLOW0_EN) << BIT_SHIFT_DAC_DSC_OVERFLOW0_EN) + +#define BIT_DAC__WRITE_ERROR_EN BIT(4) +#define BIT_SHIFT_DAC__WRITE_ERROR_EN 4 +#define BIT_MASK_DAC__WRITE_ERROR_EN 0x1 +#define BIT_CTRL_DAC__WRITE_ERROR_EN(x) (((x) & BIT_MASK_DAC__WRITE_ERROR_EN) << BIT_SHIFT_DAC__WRITE_ERROR_EN) + +#define BIT_DAC_FIFO_STOP_EN BIT(3) +#define BIT_SHIFT_DAC_FIFO_STOP_EN 3 +#define BIT_MASK_DAC_FIFO_STOP_EN 0x1 +#define BIT_CTRL_DAC_FIFO_STOP_EN(x) (((x) & BIT_MASK_DAC_FIFO_STOP_EN) << BIT_SHIFT_DAC_FIFO_STOP_EN) + +#define BIT_DAC_FIFO_OVERFLOW_EN BIT(2) +#define BIT_SHIFT_DAC_FIFO_OVERFLOW_EN 2 +#define BIT_MASK_DAC_FIFO_OVERFLOW_EN 0x1 +#define BIT_CTRL_DAC_FIFO_OVERFLOW_EN(x) (((x) & BIT_MASK_DAC_FIFO_OVERFLOW_EN) << BIT_SHIFT_DAC_FIFO_OVERFLOW_EN) + +#define BIT_DAC_FIFO_WR_REQ_EN BIT(1) +#define BIT_SHIFT_DAC_FIFO_WR_REQ_EN 1 +#define BIT_MASK_DAC_FIFO_WR_REQ_EN 0x1 +#define BIT_CTRL_DAC_FIFO_WR_REQ_EN(x) (((x) & BIT_MASK_DAC_FIFO_WR_REQ_EN) << BIT_SHIFT_DAC_FIFO_WR_REQ_EN) + +#define BIT_DAC_FIFO_FULL_EN BIT(0) +#define BIT_SHIFT_DAC_FIFO_FULL_EN 0 +#define BIT_MASK_DAC_FIFO_FULL_EN 0x1 +#define BIT_CTRL_DAC_FIFO_FULL_EN(x) (((x) & BIT_MASK_DAC_FIFO_FULL_EN) << BIT_SHIFT_DAC_FIFO_FULL_EN) + + +//2 REG_DAC_INTR_STS +#define BIT_DAC_DSC_OVERFLOW1_ST BIT(6) +#define BIT_SHIFT_DAC_DSC_OVERFLOW1_ST 6 +#define BIT_MASK_DAC_DSC_OVERFLOW1_ST 0x1 +#define BIT_CTRL_DAC_DSC_OVERFLOW1_ST(x) (((x) & BIT_MASK_DAC_DSC_OVERFLOW1_ST) << BIT_SHIFT_DAC_DSC_OVERFLOW1_ST) + +#define BIT_DAC_DSC_OVERFLOW0_ST BIT(5) +#define BIT_SHIFT_DAC_DSC_OVERFLOW0_ST 5 +#define BIT_MASK_DAC_DSC_OVERFLOW0_ST 0x1 +#define BIT_CTRL_DAC_DSC_OVERFLOW0_ST(x) (((x) & BIT_MASK_DAC_DSC_OVERFLOW0_ST) << BIT_SHIFT_DAC_DSC_OVERFLOW0_ST) + +#define BIT_DAC__WRITE_ERROR_ST BIT(4) +#define BIT_SHIFT_DAC__WRITE_ERROR_ST 4 +#define BIT_MASK_DAC__WRITE_ERROR_ST 0x1 +#define BIT_CTRL_DAC__WRITE_ERROR_ST(x) (((x) & BIT_MASK_DAC__WRITE_ERROR_ST) << BIT_SHIFT_DAC__WRITE_ERROR_ST) + +#define BIT_DAC_FIFO_STOP_ST BIT(3) +#define BIT_SHIFT_DAC_FIFO_STOP_ST 3 +#define BIT_MASK_DAC_FIFO_STOP_ST 0x1 +#define BIT_CTRL_DAC_FIFO_STOP_ST(x) (((x) & BIT_MASK_DAC_FIFO_STOP_ST) << BIT_SHIFT_DAC_FIFO_STOP_ST) + +#define BIT_DAC_FIFO_OVERFLOW_ST BIT(2) +#define BIT_SHIFT_DAC_FIFO_OVERFLOW_ST 2 +#define BIT_MASK_DAC_FIFO_OVERFLOW_ST 0x1 +#define BIT_CTRL_DAC_FIFO_OVERFLOW_ST(x) (((x) & BIT_MASK_DAC_FIFO_OVERFLOW_ST) << BIT_SHIFT_DAC_FIFO_OVERFLOW_ST) + +#define BIT_DAC_FIFO_WR_REQ_ST BIT(1) +#define BIT_SHIFT_DAC_FIFO_WR_REQ_ST 1 +#define BIT_MASK_DAC_FIFO_WR_REQ_ST 0x1 +#define BIT_CTRL_DAC_FIFO_WR_REQ_ST(x) (((x) & BIT_MASK_DAC_FIFO_WR_REQ_ST) << BIT_SHIFT_DAC_FIFO_WR_REQ_ST) + +#define BIT_DAC_FIFO_FULL_ST BIT(0) +#define BIT_SHIFT_DAC_FIFO_FULL_ST 0 +#define BIT_MASK_DAC_FIFO_FULL_ST 0x1 +#define BIT_CTRL_DAC_FIFO_FULL_ST(x) (((x) & BIT_MASK_DAC_FIFO_FULL_ST) << BIT_SHIFT_DAC_FIFO_FULL_ST) + + +//2 REG_DAC_PWR_CTRL + +#define BIT_SHIFT_DAC_PWR_CUT_CNTR 16 +#define BIT_MASK_DAC_PWR_CUT_CNTR 0xff +#define BIT_DAC_PWR_CUT_CNTR(x) (((x) & BIT_MASK_DAC_PWR_CUT_CNTR) << BIT_SHIFT_DAC_PWR_CUT_CNTR) +#define BIT_CTRL_DAC_PWR_CUT_CNTR(x) (((x) & BIT_MASK_DAC_PWR_CUT_CNTR) << BIT_SHIFT_DAC_PWR_CUT_CNTR) +#define BIT_GET_DAC_PWR_CUT_CNTR(x) (((x) >> BIT_SHIFT_DAC_PWR_CUT_CNTR) & BIT_MASK_DAC_PWR_CUT_CNTR) + +#define BIT_ST_DAC_FIFO_ON BIT(11) +#define BIT_SHIFT_ST_DAC_FIFO_ON 11 +#define BIT_MASK_ST_DAC_FIFO_ON 0x1 +#define BIT_CTRL_ST_DAC_FIFO_ON(x) (((x) & BIT_MASK_ST_DAC_FIFO_ON) << BIT_SHIFT_ST_DAC_FIFO_ON) + +#define BIT_ST_DAC_ISO_ON BIT(10) +#define BIT_SHIFT_ST_DAC_ISO_ON 10 +#define BIT_MASK_ST_DAC_ISO_ON 0x1 +#define BIT_CTRL_ST_DAC_ISO_ON(x) (((x) & BIT_MASK_ST_DAC_ISO_ON) << BIT_SHIFT_ST_DAC_ISO_ON) + +#define BIT_ST_DAC_PWR33_ON BIT(9) +#define BIT_SHIFT_ST_DAC_PWR33_ON 9 +#define BIT_MASK_ST_DAC_PWR33_ON 0x1 +#define BIT_CTRL_ST_DAC_PWR33_ON(x) (((x) & BIT_MASK_ST_DAC_PWR33_ON) << BIT_SHIFT_ST_DAC_PWR33_ON) + +#define BIT_ST_DAC_PWR12_ON BIT(8) +#define BIT_SHIFT_ST_DAC_PWR12_ON 8 +#define BIT_MASK_ST_DAC_PWR12_ON 0x1 +#define BIT_CTRL_ST_DAC_PWR12_ON(x) (((x) & BIT_MASK_ST_DAC_PWR12_ON) << BIT_SHIFT_ST_DAC_PWR12_ON) + +#define BIT_DAC_ISO_MANU BIT(3) +#define BIT_SHIFT_DAC_ISO_MANU 3 +#define BIT_MASK_DAC_ISO_MANU 0x1 +#define BIT_CTRL_DAC_ISO_MANU(x) (((x) & BIT_MASK_DAC_ISO_MANU) << BIT_SHIFT_DAC_ISO_MANU) + +#define BIT_DAC_PWR33_MANU BIT(2) +#define BIT_SHIFT_DAC_PWR33_MANU 2 +#define BIT_MASK_DAC_PWR33_MANU 0x1 +#define BIT_CTRL_DAC_PWR33_MANU(x) (((x) & BIT_MASK_DAC_PWR33_MANU) << BIT_SHIFT_DAC_PWR33_MANU) + +#define BIT_DAC_PWR12_MANU BIT(1) +#define BIT_SHIFT_DAC_PWR12_MANU 1 +#define BIT_MASK_DAC_PWR12_MANU 0x1 +#define BIT_CTRL_DAC_PWR12_MANU(x) (((x) & BIT_MASK_DAC_PWR12_MANU) << BIT_SHIFT_DAC_PWR12_MANU) + +#define BIT_DAC_PWR_AUTO BIT(0) +#define BIT_SHIFT_DAC_PWR_AUTO 0 +#define BIT_MASK_DAC_PWR_AUTO 0x1 +#define BIT_CTRL_DAC_PWR_AUTO(x) (((x) & BIT_MASK_DAC_PWR_AUTO) << BIT_SHIFT_DAC_PWR_AUTO) + + +//2 REG_DAC_ANAPAR_DA0 + +#define BIT_SHIFT_PWR_ALL_CNTR 12 +#define BIT_MASK_PWR_ALL_CNTR 0xfffff +#define BIT_PWR_ALL_CNTR(x) (((x) & BIT_MASK_PWR_ALL_CNTR) << BIT_SHIFT_PWR_ALL_CNTR) +#define BIT_CTRL_PWR_ALL_CNTR(x) (((x) & BIT_MASK_PWR_ALL_CNTR) << BIT_SHIFT_PWR_ALL_CNTR) +#define BIT_GET_PWR_ALL_CNTR(x) (((x) >> BIT_SHIFT_PWR_ALL_CNTR) & BIT_MASK_PWR_ALL_CNTR) + + +#define BIT_SHIFT_PWR_FUP_CNTR 0 +#define BIT_MASK_PWR_FUP_CNTR 0xfff +#define BIT_PWR_FUP_CNTR(x) (((x) & BIT_MASK_PWR_FUP_CNTR) << BIT_SHIFT_PWR_FUP_CNTR) +#define BIT_CTRL_PWR_FUP_CNTR(x) (((x) & BIT_MASK_PWR_FUP_CNTR) << BIT_SHIFT_PWR_FUP_CNTR) +#define BIT_GET_PWR_FUP_CNTR(x) (((x) >> BIT_SHIFT_PWR_FUP_CNTR) & BIT_MASK_PWR_FUP_CNTR) + + +//2 REG_DAC_ANAPAR_DA1 +#define BIT_FUP_EN BIT(31) +#define BIT_SHIFT_FUP_EN 31 +#define BIT_MASK_FUP_EN 0x1 +#define BIT_CTRL_FUP_EN(x) (((x) & BIT_MASK_FUP_EN) << BIT_SHIFT_FUP_EN) + + +#define BIT_SHIFT_ANAPAR_DA 8 +#define BIT_MASK_ANAPAR_DA 0x7fffff +#define BIT_ANAPAR_DA(x) (((x) & BIT_MASK_ANAPAR_DA) << BIT_SHIFT_ANAPAR_DA) +#define BIT_CTRL_ANAPAR_DA(x) (((x) & BIT_MASK_ANAPAR_DA) << BIT_SHIFT_ANAPAR_DA) +#define BIT_GET_ANAPAR_DA(x) (((x) >> BIT_SHIFT_ANAPAR_DA) & BIT_MASK_ANAPAR_DA) + +#define BIT_D_POW_DACVREF BIT(7) +#define BIT_SHIFT_D_POW_DACVREF 7 +#define BIT_MASK_D_POW_DACVREF 0x1 +#define BIT_CTRL_D_POW_DACVREF(x) (((x) & BIT_MASK_D_POW_DACVREF) << BIT_SHIFT_D_POW_DACVREF) + +#define BIT_D_POW_VREF2 BIT(6) +#define BIT_SHIFT_D_POW_VREF2 6 +#define BIT_MASK_D_POW_VREF2 0x1 +#define BIT_CTRL_D_POW_VREF2(x) (((x) & BIT_MASK_D_POW_VREF2) << BIT_SHIFT_D_POW_VREF2) + +#define BIT_D_POW_MBIAS BIT(5) +#define BIT_SHIFT_D_POW_MBIAS 5 +#define BIT_MASK_D_POW_MBIAS 0x1 +#define BIT_CTRL_D_POW_MBIAS(x) (((x) & BIT_MASK_D_POW_MBIAS) << BIT_SHIFT_D_POW_MBIAS) + +#define BIT_D_POW_DIV4 BIT(4) +#define BIT_SHIFT_D_POW_DIV4 4 +#define BIT_MASK_D_POW_DIV4 0x1 +#define BIT_CTRL_D_POW_DIV4(x) (((x) & BIT_MASK_D_POW_DIV4) << BIT_SHIFT_D_POW_DIV4) + +#define BIT_D_POW_DF1SE_R BIT(3) +#define BIT_SHIFT_D_POW_DF1SE_R 3 +#define BIT_MASK_D_POW_DF1SE_R 0x1 +#define BIT_CTRL_D_POW_DF1SE_R(x) (((x) & BIT_MASK_D_POW_DF1SE_R) << BIT_SHIFT_D_POW_DF1SE_R) + +#define BIT_D_POW_DF2SE_L BIT(2) +#define BIT_SHIFT_D_POW_DF2SE_L 2 +#define BIT_MASK_D_POW_DF2SE_L 0x1 +#define BIT_CTRL_D_POW_DF2SE_L(x) (((x) & BIT_MASK_D_POW_DF2SE_L) << BIT_SHIFT_D_POW_DF2SE_L) + +#define BIT_D_POW_DAC_R BIT(1) +#define BIT_SHIFT_D_POW_DAC_R 1 +#define BIT_MASK_D_POW_DAC_R 0x1 +#define BIT_CTRL_D_POW_DAC_R(x) (((x) & BIT_MASK_D_POW_DAC_R) << BIT_SHIFT_D_POW_DAC_R) + +#define BIT_D_POW_DAC_L BIT(0) +#define BIT_SHIFT_D_POW_DAC_L 0 +#define BIT_MASK_D_POW_DAC_L 0x1 +#define BIT_CTRL_D_POW_DAC_L(x) (((x) & BIT_MASK_D_POW_DAC_L) << BIT_SHIFT_D_POW_DAC_L) + + +//================ Register Reg Field ========================= +#define REG_DAC0_FIFO_WR 0x0000 +#define REG_DAC_CTRL 0x0004 +#define REG_DAC_INTR_CTRL 0x0008 +#define REG_DAC_INTR_STS 0x000C +#define REG_DAC_PWR_CTRL 0x0010 +#define REG_DAC_ANAPAR_DA0 0x0014 +#define REG_DAC_ANAPAR_DA1 0x0018 + + +//================ DAC HAL related enumeration ================== + + +//================ DAC HAL Macro =========================== +#define HAL_DAC_WRITE32(dacidx, addr, value) HAL_WRITE32(DAC_REG_BASE+dacidx*0x800 \ + ,addr,value) +#define HAL_DAC_READ32(dacidx, addr) HAL_READ32(DAC_REG_BASE+dacidx*0x800,addr) + + +//================ DAC Function Prototypes ===================== +RTK_STATUS HalDACInit8195a(IN VOID *Data); +RTK_STATUS HalDACDeInit8195a(IN VOID *Data); +RTK_STATUS HalDACEnableRtl8195a(IN VOID *Data); +RTK_STATUS HalDACIntrCtrl8195a(IN VOID *Data); +u8 HalDACSendRtl8195a(IN VOID *Data); +u32 HalDACReadRegRtl8195a(IN VOID *Data,IN u8 I2CReg); + +#endif diff --git a/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_gdma.h b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_gdma.h new file mode 100644 index 0000000..3a20e9b --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_gdma.h @@ -0,0 +1,486 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + + +#ifndef _RTL8195A_GDMA_H_ +#define _RTL8195A_GDMA_H_ + +// Define GDMA Handshake interface with peripheral, 0 -> GDMA0, 1-> GDMA1 +// Set this Hnadshake interface map to register REG_PESOC_SOC_CTRL +#define GDMA_HANDSHAKE_UART0_TX 0 +#define GDMA_HANDSHAKE_UART0_RX 1 +#define GDMA_HANDSHAKE_UART1_TX 2 +#define GDMA_HANDSHAKE_UART1_RX 3 +#define GDMA_HANDSHAKE_UART2_TX 14 // Only on GDMA 0, hardware fixed +#define GDMA_HANDSHAKE_UART2_RX 14 // Only on GDMA 1, hardware fixed + +#define GDMA_HANDSHAKE_SSI0_TX 4 +#define GDMA_HANDSHAKE_SSI0_RX 5 +#define GDMA_HANDSHAKE_SSI1_TX 6 +#define GDMA_HANDSHAKE_SSI1_RX 7 +#define GDMA_HANDSHAKE_SSI2_TX 15 // Only on GDMA 0, hardware fixed +#define GDMA_HANDSHAKE_SSI2_RX 15 // Only on GDMA 1, hardware fixed + +#define GDMA_HANDSHAKE_I2C0_TX 8 +#define GDMA_HANDSHAKE_I2C0_RX 9 +#define GDMA_HANDSHAKE_I2C1_TX 10 +#define GDMA_HANDSHAKE_I2C1_RX 11 + +#define GDMA_HANDSHAKE_ADC 12 +#define GDMA_HANDSHAKE_DAC0 13 // Only on GDMA 0, hardware fixed +#define GDMA_HANDSHAKE_DAC1 13 // Only on GDMA 1, hardware fixed + +#define HAL_GDMAX_READ32(GdmaIndex, addr) \ + HAL_READ32(GDMA0_REG_BASE+ (GdmaIndex*GDMA1_REG_OFF), addr) +#define HAL_GDMAX_WRITE32(GdmaIndex, addr, value) \ + HAL_WRITE32((GDMA0_REG_BASE+ (GdmaIndex*GDMA1_REG_OFF)), addr, value) +#define HAL_GDMAX_READ16(GdmaIndex, addr) \ + HAL_READ16(GDMA0_REG_BASE+ (GdmaIndex*GDMA1_REG_OFF), addr) +#define HAL_GDMAX_WRITE16(GdmaIndex, addr, value) \ + HAL_WRITE16(GDMA0_REG_BASE+ (GdmaIndex*GDMA1_REG_OFF), addr, value) +#define HAL_GDMAX_READ8(GdmaIndex, addr) \ + HAL_READ8(GDMA0_REG_BASE+ (GdmaIndex*GDMA1_REG_OFF), addr) +#define HAL_GDMAX_WRITE8(GdmaIndex, addr, value) \ + HAL_WRITE8(GDMA0_REG_BASE+ (GdmaIndex*GDMA1_REG_OFF), addr, value) + + +#define GDMA_CH_MAX 0x06 + +#define REG_GDMA_CH_OFF 0x058 +#define REG_GDMA_CH_SAR 0x000 +#define REG_GDMA_CH_DAR 0x008 +#define REG_GDMA_CH_LLP 0x010 +#define REG_GDMA_CH_CTL 0x018 +#define REG_GDMA_CH_SSTAT 0x020 +#define REG_GDMA_CH_DSTAT 0x028 +#define REG_GDMA_CH_SSTATAR 0x030 +#define REG_GDMA_CH_DSTATAR 0x038 +#define REG_GDMA_CH_CFG 0x040 +#define REG_GDMA_CH_SGR 0x048 +#define REG_GDMA_CH_DSR 0x050 + +//3 Interrupt Registers +#define REG_GDMA_RAW_INT_BASE 0x2C0 +#define REG_GDMA_RAW_INT_TFR 0x2C0 +#define REG_GDMA_RAW_INT_BLOCK 0x2c8 +#define REG_GDMA_RAW_INT_SRC_TRAN 0x2D0 +#define REG_GDMA_RAW_INT_DST_TRAN 0x2D8 +#define REG_GDMA_RAW_INT_ERR 0x2E0 + +#define REG_GDMA_STATUS_INT_BASE 0x2E8 +#define REG_GDMA_STATUS_INT_TFR 0x2E8 +#define REG_GDMA_STATUS_INT_BLOCK 0x2F0 +#define REG_GDMA_STATUS_INT_SRC_TRAN 0x2F8 +#define REG_GDMA_STATUS_INT_DST_TRAN 0x300 +#define REG_GDMA_STATUS_INT_ERR 0x308 + +#define REG_GDMA_MASK_INT_BASE 0x310 +#define REG_GDMA_MASK_INT_TFR 0x310 +#define REG_GDMA_MASK_INT_BLOCK 0x318 +#define REG_GDMA_MASK_INT_SRC_TRAN 0x320 +#define REG_GDMA_MASK_INT_DST_TRAN 0x328 +#define REG_GDMA_MASK_INT_INT_ERR 0x330 + +#define REG_GDMA_CLEAR_INT_BASE 0x338 +#define REG_GDMA_CLEAR_INT_TFR 0x338 +#define REG_GDMA_CLEAR_INT_BLOCK 0x340 +#define REG_GDMA_CLEAR_INT_SRC_TRAN 0x348 +#define REG_GDMA_CLEAR_INT_DST_TRAN 0x350 +#define REG_GDMA_CLEAR_INT_ERR 0x358 +#define REG_GDMA_STATUS_INT 0x360 + +//3 Software handshaking Registers +#define REG_GDMA_REQ_SRC 0x368 +#define REG_GDMA_REQ_DST 0x370 +#define REG_GDMA_REQ_SGL_REQ 0x378 +#define REG_GDMA_REQ_DST_REQ 0x380 +#define REG_GDMA_REQ_LST_SRC 0x388 +#define REG_GDMA_REQ_LST_DST 0x390 + +//3 Miscellaneous Registers +#define REG_GDMA_DMAC_CFG 0x398 +#define REG_GDMA_CH_EN 0x3A0 +#define REG_GDMA_DMA_ID 0x3A8 +#define REG_GDMA_DMA_TEST 0x3B0 +#define REG_GDMA_DMA_COM_PARAMS6 0x3C8 +#define REG_GDMA_DMA_COM_PARAMS5 0x3D0 +#define REG_GDMA_DMA_COM_PARAMS4 0x3D8 +#define REG_GDMA_DMA_COM_PARAMS3 0x3E0 +#define REG_GDMA_DMA_COM_PARAMS2 0x3E8 +#define REG_GDMA_DMA_COM_PARAMS1 0x3F0 +#define REG_GDMA_DMA_COM_PARAMS0 0x3F8 + +//3 CTL Register Bit Control +#define BIT_SHIFT_CTLX_LO_INT_EN 0 +#define BIT_MASK_CTLX_LO_INT_EN 0x1 +#define BIT_CTLX_LO_INT_EN(x)(((x) & BIT_MASK_CTLX_LO_INT_EN) << BIT_SHIFT_CTLX_LO_INT_EN) +#define BIT_INVC_CTLX_LO_INT_EN (~(BIT_MASK_CTLX_LO_INT_EN << BIT_SHIFT_CTLX_LO_INT_EN)) + +#define BIT_SHIFT_CTLX_LO_DST_TR_WIDTH 1 +#define BIT_MASK_CTLX_LO_DST_TR_WIDTH 0x7 +#define BIT_CTLX_LO_DST_TR_WIDTH(x) (((x) & BIT_MASK_CTLX_LO_DST_TR_WIDTH) << BIT_SHIFT_CTLX_LO_DST_TR_WIDTH) +#define BIT_INVC_CTLX_LO_DST_TR_WIDTH (~(BIT_MASK_CTLX_LO_DST_TR_WIDTH << BIT_SHIFT_CTLX_LO_DST_TR_WIDTH)) + +#define BIT_SHIFT_CTLX_LO_SRC_TR_WIDTH 4 +#define BIT_MASK_CTLX_LO_SRC_TR_WIDTH 0x7 +#define BIT_CTLX_LO_SRC_TR_WIDTH(x) (((x) & BIT_MASK_CTLX_LO_SRC_TR_WIDTH) << BIT_SHIFT_CTLX_LO_SRC_TR_WIDTH) +#define BIT_INVC_CTLX_LO_SRC_TR_WIDTH (~(BIT_MASK_CTLX_LO_SRC_TR_WIDTH << BIT_SHIFT_CTLX_LO_SRC_TR_WIDTH)) + +#define BIT_SHIFT_CTLX_LO_DINC 7 +#define BIT_MASK_CTLX_LO_DINC 0x3 +#define BIT_CTLX_LO_DINC(x)(((x) & BIT_MASK_CTLX_LO_DINC) << BIT_SHIFT_CTLX_LO_DINC) +#define BIT_INVC_CTLX_LO_DINC (~(BIT_MASK_CTLX_LO_DINC << BIT_SHIFT_CTLX_LO_DINC)) + +#define BIT_SHIFT_CTLX_LO_SINC 9 +#define BIT_MASK_CTLX_LO_SINC 0x3 +#define BIT_CTLX_LO_SINC(x)(((x) & BIT_MASK_CTLX_LO_SINC) << BIT_SHIFT_CTLX_LO_SINC) +#define BIT_INVC_CTLX_LO_SINC (~(BIT_MASK_CTLX_LO_SINC << BIT_SHIFT_CTLX_LO_SINC)) + +#define BIT_SHIFT_CTLX_LO_DEST_MSIZE 11 +#define BIT_MASK_CTLX_LO_DEST_MSIZE 0x7 +#define BIT_CTLX_LO_DEST_MSIZE(x)(((x) & BIT_MASK_CTLX_LO_DEST_MSIZE) << BIT_SHIFT_CTLX_LO_DEST_MSIZE) +#define BIT_INVC_CTLX_LO_DEST_MSIZE (~(BIT_MASK_CTLX_LO_DEST_MSIZE << BIT_SHIFT_CTLX_LO_DEST_MSIZE)) + +#define BIT_SHIFT_CTLX_LO_SRC_MSIZE 14 +#define BIT_MASK_CTLX_LO_SRC_MSIZE 0x7 +#define BIT_CTLX_LO_SRC_MSIZE(x)(((x) & BIT_MASK_CTLX_LO_SRC_MSIZE) << BIT_SHIFT_CTLX_LO_SRC_MSIZE) +#define BIT_INVC_CTLX_LO_SRC_MSIZE (~(BIT_MASK_CTLX_LO_SRC_MSIZE << BIT_SHIFT_CTLX_LO_SRC_MSIZE)) + + +#define BIT_SHIFT_CTLX_LO_SRC_GATHER_EN 17 +#define BIT_MASK_CTLX_LO_SRC_GATHER_EN 0x1 +#define BIT_CTLX_LO_SRC_GATHER_EN(x)(((x) & BIT_MASK_CTLX_LO_SRC_GATHER_EN) << BIT_SHIFT_CTLX_LO_SRC_GATHER_EN) +#define BIT_INVC_CTLX_LO_SRC_GATHER_EN (~(BIT_MASK_CTLX_LO_SRC_GATHER_EN << BIT_SHIFT_CTLX_LO_SRC_GATHER_EN)) + + +#define BIT_SHIFT_CTLX_LO_DST_SCATTER_EN 18 +#define BIT_MASK_CTLX_LO_DST_SCATTER_EN 0x1 +#define BIT_CTLX_LO_DST_SCATTER_EN(x)(((x) & BIT_MASK_CTLX_LO_DST_SCATTER_EN) << BIT_SHIFT_CTLX_LO_DST_SCATTER_EN) +#define BIT_INVC_CTLX_LO_DST_SCATTER_EN (~(BIT_MASK_CTLX_LO_DST_SCATTER_EN << BIT_SHIFT_CTLX_LO_DST_SCATTER_EN)) + + +#define BIT_SHIFT_CTLX_LO_TT_FC 20 +#define BIT_MASK_CTLX_LO_TT_FC 0x7 +#define BIT_CTLX_LO_TT_FC(x)(((x) & BIT_MASK_CTLX_LO_TT_FC) << BIT_SHIFT_CTLX_LO_TT_FC) +#define BIT_INVC_CTLX_LO_TT_FC (~(BIT_MASK_CTLX_LO_TT_FC << BIT_SHIFT_CTLX_LO_TT_FC)) + + +#define BIT_SHIFT_CTLX_LO_DMS 23 +#define BIT_MASK_CTLX_LO_DMS 0x3 +#define BIT_CTLX_LO_DMS(x)(((x) & BIT_MASK_CTLX_LO_DMS) << BIT_MASK_CTLX_LO_DMS) +#define BIT_INVC_CTLX_LO_DMS (~(BIT_MASK_CTLX_LO_DMS << BIT_SHIFT_CTLX_LO_DMS)) + + +#define BIT_SHIFT_CTLX_LO_SMS 25 +#define BIT_MASK_CTLX_LO_SMS 0x3 +#define BIT_CTLX_LO_SMS(x)(((x) & BIT_MASK_CTLX_LO_SMS) << BIT_SHIFT_CTLX_LO_SMS) +#define BIT_INVC_CTLX_LO_SMS (~(BIT_MASK_CTLX_LO_SMS << BIT_SHIFT_CTLX_LO_SMS)) + + +#define BIT_SHIFT_CTLX_LO_LLP_DST_EN 27 +#define BIT_MASK_CTLX_LO_LLP_DST_EN 0x1 +#define BIT_CTLX_LO_LLP_DST_EN(x)(((x) & BIT_MASK_CTLX_LO_LLP_DST_EN) << BIT_SHIFT_CTLX_LO_LLP_DST_EN) +#define BIT_INVC_CTLX_LO_LLP_DST_EN (~(BIT_MASK_CTLX_LO_LLP_DST_EN << BIT_SHIFT_CTLX_LO_LLP_DST_EN)) + +#define BIT_SHIFT_CTLX_LO_LLP_SRC_EN 28 +#define BIT_MASK_CTLX_LO_LLP_SRC_EN 0x1 +#define BIT_CTLX_LO_LLP_SRC_EN(x)(((x) & BIT_MASK_CTLX_LO_LLP_SRC_EN) << BIT_SHIFT_CTLX_LO_LLP_SRC_EN) +#define BIT_INVC_CTLX_LO_LLP_SRC_EN (~(BIT_MASK_CTLX_LO_LLP_SRC_EN << BIT_SHIFT_CTLX_LO_LLP_SRC_EN)) + + +#define BIT_SHIFT_CTLX_UP_BLOCK_BS 0 +#define BIT_MASK_CTLX_UP_BLOCK_BS 0xFFF +#define BIT_CTLX_UP_BLOCK_BS(x)(((x) & BIT_MASK_CTLX_UP_BLOCK_BS) << BIT_SHIFT_CTLX_UP_BLOCK_BS) +#define BIT_INVC_CTLX_UP_BLOCK_BS (~(BIT_MASK_CTLX_UP_BLOCK_BS << BIT_SHIFT_CTLX_UP_BLOCK_BS)) + + +#define BIT_SHIFT_CTLX_UP_DONE 12 +#define BIT_MASK_CTLX_UP_DONE 0x1 +#define BIT_CTLX_UP_DONE(x)(((x) & BIT_MASK_CTLX_UP_DONE) << BIT_SHIFT_CTLX_UP_DONE) +#define BIT_INVC_CTLX_UP_DONE (~(BIT_MASK_CTLX_UP_DONE << BIT_SHIFT_CTLX_UP_DONE)) + + +//3 CFG Register Bit Control +#define BIT_SHIFT_CFGX_LO_CH_PRIOR 5 +#define BIT_MASK_CFGX_LO_CH_PRIOR 0x7 +#define BIT_CFGX_LO_CH_PRIOR(x)(((x) & BIT_MASK_CFGX_LO_CH_PRIOR) << BIT_SHIFT_CFGX_LO_CH_PRIOR) +#define BIT_INVC_CFGX_LO_CH_PRIOR (~(BIT_MASK_CFGX_LO_CH_PRIOR << BIT_SHIFT_CFGX_LO_CH_PRIOR)) + + +#define BIT_SHIFT_CFGX_LO_CH_SUSP 8 +#define BIT_MASK_CFGX_LO_CH_SUSP 0x1 +#define BIT_CFGX_LO_CH_SUSP(x)(((x) & BIT_MASK_CFGX_LO_CH_SUSP) << BIT_SHIFT_CFGX_LO_CH_SUSP) +#define BIT_INVC_CFGX_LO_CH_SUSP (~(BIT_MASK_CFGX_LO_CH_SUSP << BIT_SHIFT_CFGX_LO_CH_SUSP)) + + +#define BIT_SHIFT_CFGX_LO_FIFO_EMPTY 9 +#define BIT_MASK_CFGX_LO_FIFO_EMPTY 0x1 +#define BIT_CFGX_LO_FIFO_EMPTY(x)(((x) & BIT_MASK_CFGX_LO_FIFO_EMPTY) << BIT_SHIFT_CFGX_LO_FIFO_EMPTY) +#define BIT_INVC_CFGX_LO_FIFO_EMPTY (~(BIT_MASK_CFGX_LO_FIFO_EMPTY << BIT_SHIFT_CFGX_LO_FIFO_EMPTY)) + + +#define BIT_SHIFT_CFGX_LO_HS_SEL_DST 10 +#define BIT_MASK_CFGX_LO_HS_SEL_DST 0x1 +#define BIT_CFGX_LO_HS_SEL_DST(x)(((x) & BIT_MASK_CFGX_LO_HS_SEL_DST) << BIT_SHIFT_CFGX_LO_HS_SEL_DST) +#define BIT_INVC_CFGX_LO_HS_SEL_DST (~(BIT_MASK_CFGX_LO_HS_SEL_DST << BIT_SHIFT_CFGX_LO_HS_SEL_DST)) + +#define BIT_SHIFT_CFGX_LO_HS_SEL_SRC 11 +#define BIT_MASK_CFGX_LO_HS_SEL_SRC 0x1 +#define BIT_CFGX_LO_HS_SEL_SRC(x)(((x) & BIT_MASK_CFGX_LO_HS_SEL_SRC) << BIT_SHIFT_CFGX_LO_HS_SEL_SRC) +#define BIT_INVC_CFGX_LO_HS_SEL_SRC (~(BIT_MASK_CFGX_LO_HS_SEL_SRC << BIT_SHIFT_CFGX_LO_HS_SEL_SRC)) + +#define BIT_SHIFT_CFGX_LO_LOCK_CH_L 12 +#define BIT_MASK_CFGX_LO_LOCK_CH_L 0x3 +#define BIT_CFGX_LO_LOCK_CH_L(x)(((x) & BIT_MASK_CFGX_LO_LOCK_CH_L) << BIT_SHIFT_CFGX_LO_LOCK_CH_L) +#define BIT_INVC_CFGX_LO_LOCK_CH_L (~(BIT_MASK_CFGX_LO_LOCK_CH_L << BIT_SHIFT_CFGX_LO_LOCK_CH_L)) + +#define BIT_SHIFT_CFGX_LO_LOCK_B_L 14 +#define BIT_MASK_CFGX_LO_LOCK_B_L 0x3 +#define BIT_CFGX_LO_LOCK_B_L(x)(((x) & BIT_MASK_CFGX_LO_LOCK_B_L) << BIT_SHIFT_CFGX_LO_LOCK_B_L) +#define BIT_INVC_CFGX_LO_LOCK_B_L (~(BIT_MASK_CFGX_LO_LOCK_B_L << BIT_SHIFT_CFGX_LO_LOCK_B_L)) + +#define BIT_SHIFT_CFGX_LO_LOCK_CH 16 +#define BIT_MASK_CFGX_LO_LOCK_CH 0x1 +#define BIT_CFGX_LO_LOCK_CH(x)(((x) & BIT_MASK_CFGX_LO_LOCK_CH) << BIT_SHIFT_CFGX_LO_LOCK_CH) +#define BIT_INVC_CFGX_LO_LOCK_CH (~(BIT_MASK_CFGX_LO_LOCK_CH << BIT_SHIFT_CFGX_LO_LOCK_CH)) + +#define BIT_SHIFT_CFGX_LO_LOCK_B 17 +#define BIT_MASK_CFGX_LO_LOCK_B 0x1 +#define BIT_CFGX_LO_LOCK_B(x)(((x) & BIT_MASK_CFGX_LO_LOCK_B) << BIT_SHIFT_CFGX_LO_LOCK_B) +#define BIT_INVC_CFGX_LO_LOCK_B (~(BIT_MASK_CFGX_LO_LOCK_B << BIT_SHIFT_CFGX_LO_LOCK_B)) + +#define BIT_SHIFT_CFGX_LO_DST_HS_POL 18 +#define BIT_MASK_CFGX_LO_DST_HS_POL 0x1 +#define BIT_CFGX_LO_DST_HS_POL(x)(((x) & BIT_MASK_CFGX_LO_DST_HS_POL) << BIT_SHIFT_CFGX_LO_DST_HS_POL) +#define BIT_INVC_CFGX_LO_DST_HS_POL (~(BIT_MASK_CFGX_LO_DST_HS_POL << BIT_SHIFT_CFGX_LO_DST_HS_POL)) + +#define BIT_SHIFT_CFGX_LO_SRC_HS_POL 19 +#define BIT_MASK_CFGX_LO_SRC_HS_POL 0x1 +#define BIT_CFGX_LO_SRC_HS_POL(x)(((x) & BIT_MASK_CFGX_LO_SRC_HS_POL) << BIT_SHIFT_CFGX_LO_SRC_HS_POL) +#define BIT_INVC_CFGX_LO_SRC_HS_POL (~(BIT_MASK_CFGX_LO_SRC_HS_POL << BIT_SHIFT_CFGX_LO_SRC_HS_POL)) + +#define BIT_SHIFT_CFGX_LO_MAX_ABRST 20 +#define BIT_MASK_CFGX_LO_MAX_ABRST 0x3FF +#define BIT_CFGX_LO_MAX_ABRST(x)(((x) & BIT_MASK_CFGX_LO_MAX_ABRST) << BIT_SHIFT_CFGX_LO_MAX_ABRST) +#define BIT_INVC_CFGX_LO_MAX_ABRST (~(BIT_MASK_CFGX_LO_MAX_ABRST << BIT_SHIFT_CFGX_LO_MAX_ABRST)) + +#define BIT_SHIFT_CFGX_LO_RELOAD_SRC 30 +#define BIT_MASK_CFGX_LO_RELOAD_SRC 0x1 +#define BIT_CFGX_LO_RELOAD_SRC(x)(((x) & BIT_MASK_CFGX_LO_RELOAD_SRC) << BIT_SHIFT_CFGX_LO_RELOAD_SRC) +#define BIT_INVC_CFGX_LO_RELOAD_SRC (~(BIT_MASK_CFGX_LO_RELOAD_SRC << BIT_SHIFT_CFGX_LO_RELOAD_SRC)) + +#define BIT_SHIFT_CFGX_LO_RELOAD_DST 31 +#define BIT_MASK_CFGX_LO_RELOAD_DST 0x1 +#define BIT_CFGX_LO_RELOAD_DST(x)(((x) & BIT_MASK_CFGX_LO_RELOAD_DST) << BIT_SHIFT_CFGX_LO_RELOAD_DST) +#define BIT_INVC_CFGX_LO_RELOAD_DST (~(BIT_MASK_CFGX_LO_RELOAD_DST << BIT_SHIFT_CFGX_LO_RELOAD_DST)) + +#define BIT_SHIFT_CFGX_UP_FCMODE 0 +#define BIT_MASK_CFGX_UP_FCMODE 0x1 +#define BIT_CFGX_UP_FCMODE(x)(((x) & BIT_MASK_CFGX_UP_FCMODE) << BIT_SHIFT_CFGX_UP_FCMODE) +#define BIT_INVC_CFGX_UP_FCMODE (~(BIT_MASK_CFGX_UP_FCMODE << BIT_SHIFT_CFGX_UP_FCMODE)) + +#define BIT_SHIFT_CFGX_UP_FIFO_MODE 1 +#define BIT_MASK_CFGX_UP_FIFO_MODE 0x1 +#define BIT_CFGX_UP_FIFO_MODE(x)(((x) & BIT_MASK_CFGX_UP_FIFO_MODE) << BIT_SHIFT_CFGX_UP_FIFO_MODE) +#define BIT_INVC_CFGX_UP_FIFO_MODE (~(BIT_MASK_CFGX_UP_FIFO_MODE << BIT_SHIFT_CFGX_UP_FIFO_MODE)) + +#define BIT_SHIFT_CFGX_UP_PROTCTL 2 +#define BIT_MASK_CFGX_UP_PROTCTL 0x7 +#define BIT_CFGX_UP_PROTCTL(x)(((x) & BIT_MASK_CFGX_UP_PROTCTL) << BIT_SHIFT_CFGX_UP_PROTCTL) +#define BIT_INVC_CFGX_UP_PROTCTL (~(BIT_MASK_CFGX_UP_PROTCTL << BIT_SHIFT_CFGX_UP_PROTCTL)) + +#define BIT_SHIFT_CFGX_UP_DS_UPD_EN 5 +#define BIT_MASK_CFGX_UP_DS_UPD_EN 0x1 +#define BIT_CFGX_UP_DS_UPD_EN(x)(((x) & BIT_MASK_CFGX_UP_DS_UPD_EN) << BIT_SHIFT_CFGX_UP_DS_UPD_EN) +#define BIT_INVC_CFGX_UP_DS_UPD_EN (~(BIT_MASK_CFGX_UP_DS_UPD_EN << BIT_SHIFT_CFGX_UP_DS_UPD_EN)) + +#define BIT_SHIFT_CFGX_UP_SS_UPD_EN 6 +#define BIT_MASK_CFGX_UP_SS_UPD_EN 0x1 +#define BIT_CFGX_UP_SS_UPD_EN(x)(((x) & BIT_MASK_CFGX_UP_SS_UPD_EN) << BIT_SHIFT_CFGX_UP_SS_UPD_EN) +#define BIT_INVC_CFGX_UP_SS_UPD_EN (~(BIT_MASK_CFGX_UP_SS_UPD_EN << BIT_SHIFT_CFGX_UP_SS_UPD_EN)) + +#define BIT_SHIFT_CFGX_UP_SRC_PER 7 +#define BIT_MASK_CFGX_UP_SRC_PER 0xF +#define BIT_CFGX_UP_SRC_PER(x)(((x) & BIT_MASK_CFGX_UP_SRC_PER) << BIT_SHIFT_CFGX_UP_SRC_PER) +#define BIT_INVC_CFGX_UP_SRC_PER (~(BIT_MASK_CFGX_UP_SRC_PER << BIT_SHIFT_CFGX_UP_SRC_PER)) + +#define BIT_SHIFT_CFGX_UP_DEST_PER 11 +#define BIT_MASK_CFGX_UP_DEST_PER 0xF +#define BIT_CFGX_UP_DEST_PER(x)(((x) & BIT_MASK_CFGX_UP_DEST_PER) << BIT_SHIFT_CFGX_UP_DEST_PER) +#define BIT_INVC_CFGX_UP_DEST_PER (~(BIT_MASK_CFGX_UP_DEST_PER << BIT_SHIFT_CFGX_UP_DEST_PER)) + +typedef enum _GDMA_CHANNEL_NUM_ { + GdmaNoCh = 0x0000, + GdmaCh0 = 0x0101, + GdmaCh1 = 0x0202, + GdmaCh2 = 0x0404, + GdmaCh3 = 0x0808, + GdmaCh4 = 0x1010, + GdmaCh5 = 0x2020, + GdmaCh6 = 0x4040, + GdmaCh7 = 0x8080, + GdmaAllCh = 0xffff +}GDMA_CHANNEL_NUM, *PGDMA_CHANNEL_NUM; + + +//3 CTL register struct + +typedef enum _GDMA_CTL_TT_FC_TYPE_ { + TTFCMemToMem = 0x00, + TTFCMemToPeri = 0x01, + TTFCPeriToMem = 0x02 +}GDMA_CTL_TT_FC_TYPE, *PGDMA_CTL_TT_FC_TYPE; + +//Max type = Bus Width +typedef enum _GDMA_CTL_TR_WIDTH_ { + TrWidthOneByte = 0x00, + TrWidthTwoBytes = 0x01, + TrWidthFourBytes = 0x02 +}GDMA_CTL_TR_WIDTH, *PGDMA_CTL_TR_WIDTH; + +typedef enum _GDMA_CTL_MSIZE_ { + MsizeOne = 0x00, + MsizeFour = 0x01, + MsizeEight = 0x02 +}GDMA_CTL_MSIZE, *PGDMA_CTL_MSIZE; + +typedef enum _GDMA_INC_TYPE_ { + IncType = 0x00, + DecType = 0x01, + NoChange = 0x02 +}GDMA_INC_TYPE, *PGDMA_INC_TYPE; + + +typedef struct _GDMA_CTL_REG_ { + GDMA_CTL_TT_FC_TYPE TtFc; + GDMA_CTL_TR_WIDTH DstTrWidth; + GDMA_CTL_TR_WIDTH SrcTrWidth; + GDMA_INC_TYPE Dinc; + GDMA_INC_TYPE Sinc; + GDMA_CTL_MSIZE DestMsize; + GDMA_CTL_MSIZE SrcMsize; + + u8 IntEn :1; // Bit 0 + u8 SrcGatherEn :1; // Bit 1 + u8 DstScatterEn :1; // Bit 2 + u8 LlpDstEn :1; // Bit 3 + u8 LlpSrcEn :1; // Bit 4 + u8 Done :1; // Bit 5 + u8 Rsvd6To7 :2; //Bit 6 -7 + u16 BlockSize; + +}GDMA_CTL_REG, *PGDMA_CTL_REG; + + +//3 CFG Register Structure + +typedef enum _GDMA_CH_PRIORITY_ { + Prior0 = 0, + Prior1 = 1, + Prior2 = 2, + Prior3 = 3, + Prior4 = 4, + Prior5 = 5, + Prior6 = 6, + Prior7 = 7 +}GDMA_CH_PRIORITY, *PGDMA_CH_PRIORITY; + +typedef enum _GDMA_LOCK_LEVEL_ { + OverComplDmaTransfer = 0x00, + OverComplDmaBlockTransfer = 0x01, + OverComplDmaTransation = 0x02 +}GDMA_LOCK_LEVEL, *PGDMA_LOCK_LEVEL; + + +typedef struct _GDMA_CFG_REG_ { + GDMA_CH_PRIORITY ChPrior; + GDMA_LOCK_LEVEL LockBL; + GDMA_LOCK_LEVEL LockChL; + u16 MaxAbrst; + u8 SrcPer; + u8 DestPer; + u16 ChSusp :1; //Bit 0 + u16 FifoEmpty :1; //Bit 1 + u16 HsSelDst :1; //Bit 2 + u16 HsSelSrc :1; //Bit 3 + u16 LockCh :1; //Bit 4 + u16 LockB :1; //Bit 5 + u16 DstHsPol :1; //Bit 6 + u16 SrcHsPol :1; //Bit 7 + u16 ReloadSrc :1; //Bit 8 + u16 ReloadDst :1; //Bit 9 + u16 FifoMode :1; //Bit 10 + u16 DsUpdEn :1; //Bit 11 + u16 SsUpdEn :1; //Bit 12 + u16 Rsvd13To15 :3; +}GDMA_CFG_REG, *PGDMA_CFG_REG; + +typedef enum _GDMA_ISR_TYPE_ { + TransferType = 0x1, + BlockType = 0x2, + SrcTransferType = 0x4, + DstTransferType = 0x8, + ErrType = 0x10 +}GDMA_ISR_TYPE, *PGDMA_ISR_TYPE; + + +VOID +HalGdmaOnOffRtl8195a ( + IN VOID *Data +); + +BOOL +HalGdamChInitRtl8195a( + IN VOID *Data +); + +BOOL +HalGdmaChSetingRtl8195a( + IN VOID *Data +); + +BOOL +HalGdmaChBlockSetingRtl8195a( + IN VOID *Data +); + + +VOID +HalGdmaChDisRtl8195a ( + IN VOID *Data +); + +VOID +HalGdmaChEnRtl8195a ( + IN VOID *Data +); + +VOID +HalGdmaChIsrEnAndDisRtl8195a ( + IN VOID *Data +); + +u8 +HalGdmaChIsrCleanRtl8195a ( + IN VOID *Data +); + +VOID +HalGdmaChCleanAutoSrcRtl8195a ( + IN VOID *Data +); + +VOID +HalGdmaChCleanAutoDstRtl8195a ( + IN VOID *Data +); + + + +#endif diff --git a/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_gpio.h b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_gpio.h new file mode 100644 index 0000000..a5ba6cc --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_gpio.h @@ -0,0 +1,352 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + + +#ifndef _RTL8195A_GPIO_H_ +#define _RTL8195A_GPIO_H_ + +#include "hal_api.h" +#include "hal_gpio.h" + +#define GPIO_PORTA_DR 0x00 // data register +#define GPIO_PORTA_DDR 0x04 // data direction +#define GPIO_PORTA_CTRL 0x08 // data source control, we should keep it as default: data source from software + +#define GPIO_PORTB_DR 0x0c // data register +#define GPIO_PORTB_DDR 0x10 // data direction +#define GPIO_PORTB_CTRL 0x14 // data source control, we should keep it as default: data source from software + +#define GPIO_PORTC_DR 0x18 // data register +#define GPIO_PORTC_DDR 0x1c // data direction +#define GPIO_PORTC_CTRL 0x20 // data source control, we should keep it as default: data source from software + +//1 Only the PORTA can be configured to generate interrupts +#define GPIO_INT_EN 0x30 // Interrupt enable register +#define GPIO_INT_MASK 0x34 // Interrupt mask +#define GPIO_INT_TYPE 0x38 // Interrupt type(level/edge) register +#define GPIO_INT_POLARITY 0x3C // Interrupt polarity(Active low/high) register +#define GPIO_INT_STATUS 0x40 // Interrupt status +#define GPIO_INT_RAWSTATUS 0x44 // Interrupt status without mask +#define GPIO_DEBOUNCE 0x48 // Interrupt signal debounce +#define GPIO_PORTA_EOI 0x4c // Clear interrupt + +#define GPIO_EXT_PORTA 0x50 // GPIO IN read or OUT read back +#define GPIO_EXT_PORTB 0x54 // GPIO IN read or OUT read back +#define GPIO_EXT_PORTC 0x58 // GPIO IN read or OUT read back + +#define GPIO_INT_SYNC 0x60 // Is level-sensitive interrupt being sync sith PCLK + +enum { + HAL_GPIO_HIGHZ = 0, + HAL_GPIO_PULL_LOW = 1, + HAL_GPIO_PULL_HIGH = 2 +}; + +//====================================================== +// ROM Function prototype +extern PHAL_GPIO_ADAPTER _pHAL_Gpio_Adapter; + +static __inline HAL_Status +GPIO_Lock ( + VOID +) +{ + HAL_Status Status; + + if (_pHAL_Gpio_Adapter->EnterCritical) { + _pHAL_Gpio_Adapter->EnterCritical(); + } + + if(_pHAL_Gpio_Adapter->Locked) { + Status = HAL_BUSY; + } + else { + _pHAL_Gpio_Adapter->Locked = 1; + Status = HAL_OK; + } + + if (_pHAL_Gpio_Adapter->ExitCritical) { + _pHAL_Gpio_Adapter->ExitCritical(); + } + + return Status; +} + + +static __inline VOID +GPIO_UnLock ( + VOID +) +{ + if (_pHAL_Gpio_Adapter->EnterCritical) { + _pHAL_Gpio_Adapter->EnterCritical(); + } + + _pHAL_Gpio_Adapter->Locked = 0; + + if (_pHAL_Gpio_Adapter->ExitCritical) { + _pHAL_Gpio_Adapter->ExitCritical(); + } +} + + +_LONG_CALL_ extern u32 +HAL_GPIO_IrqHandler_8195a( + IN VOID *pData +); + +_LONG_CALL_ extern u32 +HAL_GPIO_MbedIrqHandler_8195a( + IN VOID *pData +); + +_LONG_CALL_ HAL_Status +HAL_GPIO_IntCtrl_8195a( + HAL_GPIO_PIN *GPIO_Pin, + u32 En +); + +_LONG_CALL_ HAL_Status +HAL_GPIO_Init_8195a( + HAL_GPIO_PIN *GPIO_Pin +); + +_LONG_CALL_ HAL_Status +HAL_GPIO_DeInit_8195a( + HAL_GPIO_PIN *GPIO_Pin +); + +_LONG_CALL_ HAL_GPIO_PIN_STATE +HAL_GPIO_ReadPin_8195a( + HAL_GPIO_PIN *GPIO_Pin +); + +_LONG_CALL_ HAL_Status +HAL_GPIO_WritePin_8195a( + HAL_GPIO_PIN *GPIO_Pin, + HAL_GPIO_PIN_STATE Pin_State +); + +_LONG_CALL_ HAL_Status +HAL_GPIO_RegIrq_8195a( + IN PIRQ_HANDLE pIrqHandle +); + +_LONG_CALL_ HAL_Status +HAL_GPIO_UnRegIrq_8195a( + IN PIRQ_HANDLE pIrqHandle +); + +_LONG_CALL_ HAL_Status +HAL_GPIO_UserRegIrq_8195a( + HAL_GPIO_PIN *GPIO_Pin, + VOID *IrqHandler, + VOID *IrqData +); + +_LONG_CALL_ HAL_Status +HAL_GPIO_UserUnRegIrq_8195a( + HAL_GPIO_PIN *GPIO_Pin +); + +_LONG_CALL_ HAL_Status +HAL_GPIO_MaskIrq_8195a( + HAL_GPIO_PIN *GPIO_Pin +); + +_LONG_CALL_ HAL_Status +HAL_GPIO_UnMaskIrq_8195a( + HAL_GPIO_PIN *GPIO_Pin +); + +_LONG_CALL_ HAL_Status +HAL_GPIO_IntDebounce_8195a( + HAL_GPIO_PIN *GPIO_Pin, + u8 Enable +); + +_LONG_CALL_ u32 +HAL_GPIO_GetIPPinName_8195a( + u32 chip_pin +); + +_LONG_CALL_ HAL_Status +HAL_GPIO_PullCtrl_8195a( + u32 chip_pin, + u8 pull_type +); + +_LONG_CALL_ u32 +GPIO_GetChipPinName_8195a( + u32 port, + u32 pin +); + +_LONG_CALL_ VOID +GPIO_PullCtrl_8195a( + u32 chip_pin, + u8 pull_type +); + +_LONG_CALL_ VOID +GPIO_Int_SetType_8195a( + u8 pin_num, + u8 int_mode +); + + +_LONG_CALL_ HAL_Status HAL_GPIO_IntCtrl_8195aV02(HAL_GPIO_PIN *GPIO_Pin, u32 En); +_LONG_CALL_ u32 GPIO_Int_Clear_8195aV02(u32 irq_clr); + +HAL_Status +HAL_GPIO_ClearISR_8195a( + HAL_GPIO_PIN *GPIO_Pin +); + + +/********** HAL In-Line Functions **********/ + +/** + * @brief De-Initializes a GPIO Pin, reset it as default setting. + * + * @param GPIO_Pin: The data structer which contains the parameters for the GPIO Pin. + * + * @retval HAL_Status + */ +static __inline VOID +HAL_GPIO_DeInit( + HAL_GPIO_PIN *GPIO_Pin +) +{ + HAL_GPIO_DeInit_8195a(GPIO_Pin); +} + +/** + * @brief Reads the specified input port pin. + * + * @param GPIO_Pin: The data structer which contains the parameters for the GPIO Pin. + * + * @retval The input port pin current status(High or Low). + */ +static __inline s32 +HAL_GPIO_ReadPin( + HAL_GPIO_PIN *GPIO_Pin +) +{ + return (s32)HAL_GPIO_ReadPin_8195a(GPIO_Pin); +} + +/** + * @brief Write the specified output port pin. + * + * @param GPIO_Pin: The data structer which contains the parameters for the GPIO Pin. + * + * @param Pin_State: The state going to be set to the assigned GPIO pin. + * + * @retval None + */ +static __inline VOID +HAL_GPIO_WritePin( + HAL_GPIO_PIN *GPIO_Pin, + u32 Value +) +{ + HAL_GPIO_WritePin_8195a(GPIO_Pin, (HAL_GPIO_PIN_STATE)Value); +} + +/** + * @brief To register a user interrupt handler for a specified pin + * + * @param GPIO_Pin: The data structer which contains the parameters for the GPIO Pin. + * + * @param IrqHandler: The IRQ handler to be assigned to the specified pin + * + * @param IrqData: The pointer will be pass the the IRQ handler + * + * @retval None + */ +static __inline VOID +HAL_GPIO_UserRegIrq( + HAL_GPIO_PIN *GPIO_Pin, + VOID *IrqHandler, + VOID *IrqData +) +{ + HAL_GPIO_UserRegIrq_8195a(GPIO_Pin, IrqHandler, IrqData); +} + +/** + * @brief To un-register a user interrupt handler for a specified pin + * + * @param GPIO_Pin: The data structer which contains the parameters for the GPIO Pin. + * + * @retval None + */ +static __inline VOID +HAL_GPIO_UserUnRegIrq( + HAL_GPIO_PIN *GPIO_Pin +) +{ + HAL_GPIO_UserUnRegIrq_8195a(GPIO_Pin); +} + + +/** + * @brief Enable/Disable GPIO interrupt + * + * @param GPIO_Pin: The data structer which contains the parameters for the GPIO Pin initialization. + * + * @param En: Enable (1) or Disable (0) + * + * @retval HAL_Status + */ +static __inline VOID +HAL_GPIO_IntCtrl( + HAL_GPIO_PIN *GPIO_Pin, + u32 En +) +{ + HAL_GPIO_IntCtrl_8195a(GPIO_Pin, En); +} + +/** + * @brief Mask the interrupt of a specified pin + * + * @param GPIO_Pin: The data structer which contains the parameters for the GPIO Pin. + * + * @retval None + */ +static __inline VOID +HAL_GPIO_MaskIrq( + HAL_GPIO_PIN *GPIO_Pin +) +{ + HAL_GPIO_MaskIrq_8195a(GPIO_Pin); +} + + +/** + * @brief UnMask the interrupt of a specified pin + * + * @param GPIO_Pin: The data structer which contains the parameters for the GPIO Pin. + * + * @retval None + */ +static __inline VOID +HAL_GPIO_UnMaskIrq( + HAL_GPIO_PIN *GPIO_Pin +) +{ + HAL_GPIO_ClearISR_8195a(GPIO_Pin); + HAL_GPIO_UnMaskIrq_8195a(GPIO_Pin); +} + + +#endif // end of "#define _RTL8195A_GPIO_H_" + diff --git a/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_i2c.h b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_i2c.h new file mode 100644 index 0000000..ed7f1a7 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_i2c.h @@ -0,0 +1,844 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#ifndef _RTL8195A_I2C_H_ +#define _RTL8195A_I2C_H_ + +#include "hal_api.h" + +//================ Register Bit Field ================== +//2 REG_DW_I2C_IC_CON +#define BIT_IC_CON_IC_SLAVE_DISABLE BIT(6) +#define BIT_SHIFT_IC_CON_IC_SLAVE_DISABLE 6 +#define BIT_MASK_IC_CON_IC_SLAVE_DISABLE 0x1 +#define BIT_CTRL_IC_CON_IC_SLAVE_DISABLE(x) (((x) & BIT_MASK_IC_CON_IC_SLAVE_DISABLE) << BIT_SHIFT_IC_CON_IC_SLAVE_DISABLE) + +#define BIT_IC_CON_IC_RESTART_EN BIT(5) +#define BIT_SHIFT_IC_CON_IC_RESTART_EN 5 +#define BIT_MASK_IC_CON_IC_RESTART_EN 0x1 +#define BIT_CTRL_IC_CON_IC_RESTART_EN(x) (((x) & BIT_MASK_IC_CON_IC_RESTART_EN) << BIT_SHIFT_IC_CON_IC_RESTART_EN) + +#define BIT_IC_CON_IC_10BITADDR_MASTER BIT(4) +#define BIT_SHIFT_IC_CON_IC_10BITADDR_MASTER 4 +#define BIT_MASK_IC_CON_IC_10BITADDR_MASTER 0x1 +#define BIT_CTRL_IC_CON_IC_10BITADDR_MASTER(x) (((x) & BIT_MASK_IC_CON_IC_10BITADDR_MASTER) << BIT_SHIFT_IC_CON_IC_10BITADDR_MASTER) + +#define BIT_IC_CON_IC_10BITADDR_SLAVE BIT(3) +#define BIT_SHIFT_IC_CON_IC_10BITADDR_SLAVE 3 +#define BIT_MASK_IC_CON_IC_10BITADDR_SLAVE 0x1 +#define BIT_CTRL_IC_CON_IC_10BITADDR_SLAVE(x) (((x) & BIT_MASK_IC_CON_IC_10BITADDR_SLAVE) << BIT_SHIFT_IC_CON_IC_10BITADDR_SLAVE) + + +#define BIT_SHIFT_IC_CON_SPEED 1 +#define BIT_MASK_IC_CON_SPEED 0x3 +#define BIT_IC_CON_SPEED(x) (((x) & BIT_MASK_IC_CON_SPEED) << BIT_SHIFT_IC_CON_SPEED) +#define BIT_CTRL_IC_CON_SPEED(x) (((x) & BIT_MASK_IC_CON_SPEED) << BIT_SHIFT_IC_CON_SPEED) +#define BIT_GET_IC_CON_SPEED(x) (((x) >> BIT_SHIFT_IC_CON_SPEED) & BIT_MASK_IC_CON_SPEED) + +#define BIT_IC_CON_MASTER_MODE BIT(0) +#define BIT_SHIFT_IC_CON_MASTER_MODE 0 +#define BIT_MASK_IC_CON_MASTER_MODE 0x1 +#define BIT_CTRL_IC_CON_MASTER_MODE(x) (((x) & BIT_MASK_IC_CON_MASTER_MODE) << BIT_SHIFT_IC_CON_MASTER_MODE) + + +//2 REG_DW_I2C_IC_TAR +#define BIT_IC_TAR_IC_10BITADDR_MASTER BIT(12) +#define BIT_SHIFT_IC_TAR_IC_10BITADDR_MASTER 12 +#define BIT_MASK_IC_TAR_IC_10BITADDR_MASTER 0x1 +#define BIT_CTRL_IC_TAR_IC_10BITADDR_MASTER(x) (((x) & BIT_MASK_IC_TAR_IC_10BITADDR_MASTER) << BIT_SHIFT_IC_TAR_IC_10BITADDR_MASTER) + +#define BIT_IC_TAR_SPECIAL BIT(11) +#define BIT_SHIFT_IC_TAR_SPECIAL 11 +#define BIT_MASK_IC_TAR_SPECIAL 0x1 +#define BIT_CTRL_IC_TAR_SPECIAL(x) (((x) & BIT_MASK_IC_TAR_SPECIAL) << BIT_SHIFT_IC_TAR_SPECIAL) + +#define BIT_IC_TAR_GC_OR_START BIT(10) +#define BIT_SHIFT_IC_TAR_GC_OR_START 10 +#define BIT_MASK_IC_TAR_GC_OR_START 0x1 +#define BIT_CTRL_IC_TAR_GC_OR_START(x) (((x) & BIT_MASK_IC_TAR_GC_OR_START) << BIT_SHIFT_IC_TAR_GC_OR_START) + + +#define BIT_SHIFT_IC_TAR 0 +#define BIT_MASK_IC_TAR 0x3ff +#define BIT_IC_TAR(x) (((x) & BIT_MASK_IC_TAR) << BIT_SHIFT_IC_TAR) +#define BIT_CTRL_IC_TAR(x) (((x) & BIT_MASK_IC_TAR) << BIT_SHIFT_IC_TAR) +#define BIT_GET_IC_TAR(x) (((x) >> BIT_SHIFT_IC_TAR) & BIT_MASK_IC_TAR) + + +//2 REG_DW_I2C_IC_SAR + +#define BIT_SHIFT_IC_SAR 0 +#define BIT_MASK_IC_SAR 0x3ff +#define BIT_IC_SAR(x) (((x) & BIT_MASK_IC_SAR) << BIT_SHIFT_IC_SAR) +#define BIT_CTRL_IC_SAR(x) (((x) & BIT_MASK_IC_SAR) << BIT_SHIFT_IC_SAR) +#define BIT_GET_IC_SAR(x) (((x) >> BIT_SHIFT_IC_SAR) & BIT_MASK_IC_SAR) + + +//2 REG_DW_I2C_IC_HS_MADDR + +#define BIT_SHIFT_IC_HS_MADDR 0 +#define BIT_MASK_IC_HS_MADDR 0x7 +#define BIT_IC_HS_MADDR(x) (((x) & BIT_MASK_IC_HS_MADDR) << BIT_SHIFT_IC_HS_MADDR) +#define BIT_CTRL_IC_HS_MADDR(x) (((x) & BIT_MASK_IC_HS_MADDR) << BIT_SHIFT_IC_HS_MADDR) +#define BIT_GET_IC_HS_MADDR(x) (((x) >> BIT_SHIFT_IC_HS_MADDR) & BIT_MASK_IC_HS_MADDR) + + +//2 REG_DW_I2C_IC_DATA_CMD +#define BIT_IC_DATA_CMD_RESTART BIT(10) +#define BIT_SHIFT_IC_DATA_CMD_RESTART 10 +#define BIT_MASK_IC_DATA_CMD_RESTART 0x1 +#define BIT_CTRL_IC_DATA_CMD_RESTART(x) (((x) & BIT_MASK_IC_DATA_CMD_RESTART) << BIT_SHIFT_IC_DATA_CMD_RESTART) + +#define BIT_IC_DATA_CMD_STOP BIT(9) +#define BIT_SHIFT_IC_DATA_CMD_STOP 9 +#define BIT_MASK_IC_DATA_CMD_STOP 0x1 +#define BIT_CTRL_IC_DATA_CMD_STOP(x) (((x) & BIT_MASK_IC_DATA_CMD_STOP) << BIT_SHIFT_IC_DATA_CMD_STOP) + +#define BIT_IC_DATA_CMD_CMD BIT(8) +#define BIT_SHIFT_IC_DATA_CMD_CMD 8 +#define BIT_MASK_IC_DATA_CMD_CMD 0x1 +#define BIT_CTRL_IC_DATA_CMD_CMD(x) (((x) & BIT_MASK_IC_DATA_CMD_CMD) << BIT_SHIFT_IC_DATA_CMD_CMD) + + +#define BIT_SHIFT_IC_DATA_CMD_DAT 0 +#define BIT_MASK_IC_DATA_CMD_DAT 0xff +#define BIT_IC_DATA_CMD_DAT(x) (((x) & BIT_MASK_IC_DATA_CMD_DAT) << BIT_SHIFT_IC_DATA_CMD_DAT) +#define BIT_CTRL_IC_DATA_CMD_DAT(x) (((x) & BIT_MASK_IC_DATA_CMD_DAT) << BIT_SHIFT_IC_DATA_CMD_DAT) +#define BIT_GET_IC_DATA_CMD_DAT(x) (((x) >> BIT_SHIFT_IC_DATA_CMD_DAT) & BIT_MASK_IC_DATA_CMD_DAT) + + +//2 REG_DW_I2C_IC_SS_SCL_HCNT + +#define BIT_SHIFT_IC_SS_SCL_HCNT 0 +#define BIT_MASK_IC_SS_SCL_HCNT 0xffff +#define BIT_IC_SS_SCL_HCNT(x) (((x) & BIT_MASK_IC_SS_SCL_HCNT) << BIT_SHIFT_IC_SS_SCL_HCNT) +#define BIT_CTRL_IC_SS_SCL_HCNT(x) (((x) & BIT_MASK_IC_SS_SCL_HCNT) << BIT_SHIFT_IC_SS_SCL_HCNT) +#define BIT_GET_IC_SS_SCL_HCNT(x) (((x) >> BIT_SHIFT_IC_SS_SCL_HCNT) & BIT_MASK_IC_SS_SCL_HCNT) + + +//2 REG_DW_I2C_IC_SS_SCL_LCNT + +#define BIT_SHIFT_IC_SS_SCL_LCNT 0 +#define BIT_MASK_IC_SS_SCL_LCNT 0xffff +#define BIT_IC_SS_SCL_LCNT(x) (((x) & BIT_MASK_IC_SS_SCL_LCNT) << BIT_SHIFT_IC_SS_SCL_LCNT) +#define BIT_CTRL_IC_SS_SCL_LCNT(x) (((x) & BIT_MASK_IC_SS_SCL_LCNT) << BIT_SHIFT_IC_SS_SCL_LCNT) +#define BIT_GET_IC_SS_SCL_LCNT(x) (((x) >> BIT_SHIFT_IC_SS_SCL_LCNT) & BIT_MASK_IC_SS_SCL_LCNT) + + +//2 REG_DW_I2C_IC_FS_SCL_HCNT + +#define BIT_SHIFT_IC_FS_SCL_HCNT 0 +#define BIT_MASK_IC_FS_SCL_HCNT 0xffff +#define BIT_IC_FS_SCL_HCNT(x) (((x) & BIT_MASK_IC_FS_SCL_HCNT) << BIT_SHIFT_IC_FS_SCL_HCNT) +#define BIT_CTRL_IC_FS_SCL_HCNT(x) (((x) & BIT_MASK_IC_FS_SCL_HCNT) << BIT_SHIFT_IC_FS_SCL_HCNT) +#define BIT_GET_IC_FS_SCL_HCNT(x) (((x) >> BIT_SHIFT_IC_FS_SCL_HCNT) & BIT_MASK_IC_FS_SCL_HCNT) + + +//2 REG_DW_I2C_IC_FS_SCL_LCNT + +#define BIT_SHIFT_IC_FS_SCL_LCNT 0 +#define BIT_MASK_IC_FS_SCL_LCNT 0xffff +#define BIT_IC_FS_SCL_LCNT(x) (((x) & BIT_MASK_IC_FS_SCL_LCNT) << BIT_SHIFT_IC_FS_SCL_LCNT) +#define BIT_CTRL_IC_FS_SCL_LCNT(x) (((x) & BIT_MASK_IC_FS_SCL_LCNT) << BIT_SHIFT_IC_FS_SCL_LCNT) +#define BIT_GET_IC_FS_SCL_LCNT(x) (((x) >> BIT_SHIFT_IC_FS_SCL_LCNT) & BIT_MASK_IC_FS_SCL_LCNT) + + +//2 REG_DW_I2C_IC_HS_SCL_HCNT + +#define BIT_SHIFT_IC_HS_SCL_HCNT 0 +#define BIT_MASK_IC_HS_SCL_HCNT 0xffff +#define BIT_IC_HS_SCL_HCNT(x) (((x) & BIT_MASK_IC_HS_SCL_HCNT) << BIT_SHIFT_IC_HS_SCL_HCNT) +#define BIT_CTRL_IC_HS_SCL_HCNT(x) (((x) & BIT_MASK_IC_HS_SCL_HCNT) << BIT_SHIFT_IC_HS_SCL_HCNT) +#define BIT_GET_IC_HS_SCL_HCNT(x) (((x) >> BIT_SHIFT_IC_HS_SCL_HCNT) & BIT_MASK_IC_HS_SCL_HCNT) + + +//2 REG_DW_I2C_IC_HS_SCL_LCNT + +#define BIT_SHIFT_IC_HS_SCL_LCNT 0 +#define BIT_MASK_IC_HS_SCL_LCNT 0xffff +#define BIT_IC_HS_SCL_LCNT(x) (((x) & BIT_MASK_IC_HS_SCL_LCNT) << BIT_SHIFT_IC_HS_SCL_LCNT) +#define BIT_CTRL_IC_HS_SCL_LCNT(x) (((x) & BIT_MASK_IC_HS_SCL_LCNT) << BIT_SHIFT_IC_HS_SCL_LCNT) +#define BIT_GET_IC_HS_SCL_LCNT(x) (((x) >> BIT_SHIFT_IC_HS_SCL_LCNT) & BIT_MASK_IC_HS_SCL_LCNT) + + +//2 REG_DW_I2C_IC_INTR_STAT +#define BIT_IC_INTR_STAT_R_GEN_CALL BIT(11) +#define BIT_SHIFT_IC_INTR_STAT_R_GEN_CALL 11 +#define BIT_MASK_IC_INTR_STAT_R_GEN_CALL 0x1 +#define BIT_CTRL_IC_INTR_STAT_R_GEN_CALL(x) (((x) & BIT_MASK_IC_INTR_STAT_R_GEN_CALL) << BIT_SHIFT_IC_INTR_STAT_R_GEN_CALL) + +#define BIT_IC_INTR_STAT_R_START_DET BIT(10) +#define BIT_SHIFT_IC_INTR_STAT_R_START_DET 10 +#define BIT_MASK_IC_INTR_STAT_R_START_DET 0x1 +#define BIT_CTRL_IC_INTR_STAT_R_START_DET(x) (((x) & BIT_MASK_IC_INTR_STAT_R_START_DET) << BIT_SHIFT_IC_INTR_STAT_R_START_DET) + +#define BIT_IC_INTR_STAT_R_STOP_DET BIT(9) +#define BIT_SHIFT_IC_INTR_STAT_R_STOP_DET 9 +#define BIT_MASK_IC_INTR_STAT_R_STOP_DET 0x1 +#define BIT_CTRL_IC_INTR_STAT_R_STOP_DET(x) (((x) & BIT_MASK_IC_INTR_STAT_R_STOP_DET) << BIT_SHIFT_IC_INTR_STAT_R_STOP_DET) + +#define BIT_IC_INTR_STAT_R_ACTIVITY BIT(8) +#define BIT_SHIFT_IC_INTR_STAT_R_ACTIVITY 8 +#define BIT_MASK_IC_INTR_STAT_R_ACTIVITY 0x1 +#define BIT_CTRL_IC_INTR_STAT_R_ACTIVITY(x) (((x) & BIT_MASK_IC_INTR_STAT_R_ACTIVITY) << BIT_SHIFT_IC_INTR_STAT_R_ACTIVITY) + +#define BIT_IC_INTR_STAT_R_RX_DONE BIT(7) +#define BIT_SHIFT_IC_INTR_STAT_R_RX_DONE 7 +#define BIT_MASK_IC_INTR_STAT_R_RX_DONE 0x1 +#define BIT_CTRL_IC_INTR_STAT_R_RX_DONE(x) (((x) & BIT_MASK_IC_INTR_STAT_R_RX_DONE) << BIT_SHIFT_IC_INTR_STAT_R_RX_DONE) + +#define BIT_IC_INTR_STAT_R_TX_ABRT BIT(6) +#define BIT_SHIFT_IC_INTR_STAT_R_TX_ABRT 6 +#define BIT_MASK_IC_INTR_STAT_R_TX_ABRT 0x1 +#define BIT_CTRL_IC_INTR_STAT_R_TX_ABRT(x) (((x) & BIT_MASK_IC_INTR_STAT_R_TX_ABRT) << BIT_SHIFT_IC_INTR_STAT_R_TX_ABRT) + +#define BIT_IC_INTR_STAT_R_RD_REQ BIT(5) +#define BIT_SHIFT_IC_INTR_STAT_R_RD_REQ 5 +#define BIT_MASK_IC_INTR_STAT_R_RD_REQ 0x1 +#define BIT_CTRL_IC_INTR_STAT_R_RD_REQ(x) (((x) & BIT_MASK_IC_INTR_STAT_R_RD_REQ) << BIT_SHIFT_IC_INTR_STAT_R_RD_REQ) + +#define BIT_IC_INTR_STAT_R_TX_EMPTY BIT(4) +#define BIT_SHIFT_IC_INTR_STAT_R_TX_EMPTY 4 +#define BIT_MASK_IC_INTR_STAT_R_TX_EMPTY 0x1 +#define BIT_CTRL_IC_INTR_STAT_R_TX_EMPTY(x) (((x) & BIT_MASK_IC_INTR_STAT_R_TX_EMPTY) << BIT_SHIFT_IC_INTR_STAT_R_TX_EMPTY) + +#define BIT_IC_INTR_STAT_R_TX_OVER BIT(3) +#define BIT_SHIFT_IC_INTR_STAT_R_TX_OVER 3 +#define BIT_MASK_IC_INTR_STAT_R_TX_OVER 0x1 +#define BIT_CTRL_IC_INTR_STAT_R_TX_OVER(x) (((x) & BIT_MASK_IC_INTR_STAT_R_TX_OVER) << BIT_SHIFT_IC_INTR_STAT_R_TX_OVER) + +#define BIT_IC_INTR_STAT_R_RX_FULL BIT(2) +#define BIT_SHIFT_IC_INTR_STAT_R_RX_FULL 2 +#define BIT_MASK_IC_INTR_STAT_R_RX_FULL 0x1 +#define BIT_CTRL_IC_INTR_STAT_R_RX_FULL(x) (((x) & BIT_MASK_IC_INTR_STAT_R_RX_FULL) << BIT_SHIFT_IC_INTR_STAT_R_RX_FULL) + +#define BIT_IC_INTR_STAT_R_RX_OVER BIT(1) +#define BIT_SHIFT_IC_INTR_STAT_R_RX_OVER 1 +#define BIT_MASK_IC_INTR_STAT_R_RX_OVER 0x1 +#define BIT_CTRL_IC_INTR_STAT_R_RX_OVER(x) (((x) & BIT_MASK_IC_INTR_STAT_R_RX_OVER) << BIT_SHIFT_IC_INTR_STAT_R_RX_OVER) + +#define BIT_IC_INTR_STAT_R_RX_UNDER BIT(0) +#define BIT_SHIFT_IC_INTR_STAT_R_RX_UNDER 0 +#define BIT_MASK_IC_INTR_STAT_R_RX_UNDER 0x1 +#define BIT_CTRL_IC_INTR_STAT_R_RX_UNDER(x) (((x) & BIT_MASK_IC_INTR_STAT_R_RX_UNDER) << BIT_SHIFT_IC_INTR_STAT_R_RX_UNDER) + + +//2 REG_DW_I2C_IC_INTR_MASK +#define BIT_IC_INTR_MASK_M_GEN_CALL BIT(11) +#define BIT_SHIFT_IC_INTR_MASK_M_GEN_CALL 11 +#define BIT_MASK_IC_INTR_MASK_M_GEN_CALL 0x1 +#define BIT_CTRL_IC_INTR_MASK_M_GEN_CALL(x) (((x) & BIT_MASK_IC_INTR_MASK_M_GEN_CALL) << BIT_SHIFT_IC_INTR_MASK_M_GEN_CALL) + +#define BIT_IC_INTR_MASK_M_START_DET BIT(10) +#define BIT_SHIFT_IC_INTR_MASK_M_START_DET 10 +#define BIT_MASK_IC_INTR_MASK_M_START_DET 0x1 +#define BIT_CTRL_IC_INTR_MASK_M_START_DET(x) (((x) & BIT_MASK_IC_INTR_MASK_M_START_DET) << BIT_SHIFT_IC_INTR_MASK_M_START_DET) + +#define BIT_IC_INTR_MASK_M_STOP_DET BIT(9) +#define BIT_SHIFT_IC_INTR_MASK_M_STOP_DET 9 +#define BIT_MASK_IC_INTR_MASK_M_STOP_DET 0x1 +#define BIT_CTRL_IC_INTR_MASK_M_STOP_DET(x) (((x) & BIT_MASK_IC_INTR_MASK_M_STOP_DET) << BIT_SHIFT_IC_INTR_MASK_M_STOP_DET) + +#define BIT_IC_INTR_MASK_M_ACTIVITY BIT(8) +#define BIT_SHIFT_IC_INTR_MASK_M_ACTIVITY 8 +#define BIT_MASK_IC_INTR_MASK_M_ACTIVITY 0x1 +#define BIT_CTRL_IC_INTR_MASK_M_ACTIVITY(x) (((x) & BIT_MASK_IC_INTR_MASK_M_ACTIVITY) << BIT_SHIFT_IC_INTR_MASK_M_ACTIVITY) + +#define BIT_IC_INTR_MASK_M_RX_DONE BIT(7) +#define BIT_SHIFT_IC_INTR_MASK_M_RX_DONE 7 +#define BIT_MASK_IC_INTR_MASK_M_RX_DONE 0x1 +#define BIT_CTRL_IC_INTR_MASK_M_RX_DONE(x) (((x) & BIT_MASK_IC_INTR_MASK_M_RX_DONE) << BIT_SHIFT_IC_INTR_MASK_M_RX_DONE) + +#define BIT_IC_INTR_MASK_M_TX_ABRT BIT(6) +#define BIT_SHIFT_IC_INTR_MASK_M_TX_ABRT 6 +#define BIT_MASK_IC_INTR_MASK_M_TX_ABRT 0x1 +#define BIT_CTRL_IC_INTR_MASK_M_TX_ABRT(x) (((x) & BIT_MASK_IC_INTR_MASK_M_TX_ABRT) << BIT_SHIFT_IC_INTR_MASK_M_TX_ABRT) + +#define BIT_IC_INTR_MASK_M_RD_REQ BIT(5) +#define BIT_SHIFT_IC_INTR_MASK_M_RD_REQ 5 +#define BIT_MASK_IC_INTR_MASK_M_RD_REQ 0x1 +#define BIT_CTRL_IC_INTR_MASK_M_RD_REQ(x) (((x) & BIT_MASK_IC_INTR_MASK_M_RD_REQ) << BIT_SHIFT_IC_INTR_MASK_M_RD_REQ) + +#define BIT_IC_INTR_MASK_M_TX_EMPTY BIT(4) +#define BIT_SHIFT_IC_INTR_MASK_M_TX_EMPTY 4 +#define BIT_MASK_IC_INTR_MASK_M_TX_EMPTY 0x1 +#define BIT_CTRL_IC_INTR_MASK_M_TX_EMPTY(x) (((x) & BIT_MASK_IC_INTR_MASK_M_TX_EMPTY) << BIT_SHIFT_IC_INTR_MASK_M_TX_EMPTY) + +#define BIT_IC_INTR_MASK_M_TX_OVER BIT(3) +#define BIT_SHIFT_IC_INTR_MASK_M_TX_OVER 3 +#define BIT_MASK_IC_INTR_MASK_M_TX_OVER 0x1 +#define BIT_CTRL_IC_INTR_MASK_M_TX_OVER(x) (((x) & BIT_MASK_IC_INTR_MASK_M_TX_OVER) << BIT_SHIFT_IC_INTR_MASK_M_TX_OVER) + +#define BIT_IC_INTR_MASK_M_RX_FULL BIT(2) +#define BIT_SHIFT_IC_INTR_MASK_M_RX_FULL 2 +#define BIT_MASK_IC_INTR_MASK_M_RX_FULL 0x1 +#define BIT_CTRL_IC_INTR_MASK_M_RX_FULL(x) (((x) & BIT_MASK_IC_INTR_MASK_M_RX_FULL) << BIT_SHIFT_IC_INTR_MASK_M_RX_FULL) + +#define BIT_IC_INTR_MASK_M_RX_OVER BIT(1) +#define BIT_SHIFT_IC_INTR_MASK_M_RX_OVER 1 +#define BIT_MASK_IC_INTR_MASK_M_RX_OVER 0x1 +#define BIT_CTRL_IC_INTR_MASK_M_RX_OVER(x) (((x) & BIT_MASK_IC_INTR_MASK_M_RX_OVER) << BIT_SHIFT_IC_INTR_MASK_M_RX_OVER) + +#define BIT_IC_INTR_MASK_M_RX_UNDER BIT(0) +#define BIT_SHIFT_IC_INTR_MASK_M_RX_UNDER 0 +#define BIT_MASK_IC_INTR_MASK_M_RX_UNDER 0x1 +#define BIT_CTRL_IC_INTR_MASK_M_RX_UNDER(x) (((x) & BIT_MASK_IC_INTR_MASK_M_RX_UNDER) << BIT_SHIFT_IC_INTR_MASK_M_RX_UNDER) + + +//2 REG_DW_I2C_IC_RAW_INTR_STAT +#define BIT_IC_RAW_INTR_STAT_GEN_CALL BIT(11) +#define BIT_SHIFT_IC_RAW_INTR_STAT_GEN_CALL 11 +#define BIT_MASK_IC_RAW_INTR_STAT_GEN_CALL 0x1 +#define BIT_CTRL_IC_RAW_INTR_STAT_GEN_CALL(x) (((x) & BIT_MASK_IC_RAW_INTR_STAT_GEN_CALL) << BIT_SHIFT_IC_RAW_INTR_STAT_GEN_CALL) + +#define BIT_IC_RAW_INTR_STAT_START_DET BIT(10) +#define BIT_SHIFT_IC_RAW_INTR_STAT_START_DET 10 +#define BIT_MASK_IC_RAW_INTR_STAT_START_DET 0x1 +#define BIT_CTRL_IC_RAW_INTR_STAT_START_DET(x) (((x) & BIT_MASK_IC_RAW_INTR_STAT_START_DET) << BIT_SHIFT_IC_RAW_INTR_STAT_START_DET) + +#define BIT_IC_RAW_INTR_STAT_STOP_DET BIT(9) +#define BIT_SHIFT_IC_RAW_INTR_STAT_STOP_DET 9 +#define BIT_MASK_IC_RAW_INTR_STAT_STOP_DET 0x1 +#define BIT_CTRL_IC_RAW_INTR_STAT_STOP_DET(x) (((x) & BIT_MASK_IC_RAW_INTR_STAT_STOP_DET) << BIT_SHIFT_IC_RAW_INTR_STAT_STOP_DET) + +#define BIT_IC_RAW_INTR_STAT_ACTIVITY BIT(8) +#define BIT_SHIFT_IC_RAW_INTR_STAT_ACTIVITY 8 +#define BIT_MASK_IC_RAW_INTR_STAT_ACTIVITY 0x1 +#define BIT_CTRL_IC_RAW_INTR_STAT_ACTIVITY(x) (((x) & BIT_MASK_IC_RAW_INTR_STAT_ACTIVITY) << BIT_SHIFT_IC_RAW_INTR_STAT_ACTIVITY) + +#define BIT_IC_RAW_INTR_STAT_RX_DONE BIT(7) +#define BIT_SHIFT_IC_RAW_INTR_STAT_RX_DONE 7 +#define BIT_MASK_IC_RAW_INTR_STAT_RX_DONE 0x1 +#define BIT_CTRL_IC_RAW_INTR_STAT_RX_DONE(x) (((x) & BIT_MASK_IC_RAW_INTR_STAT_RX_DONE) << BIT_SHIFT_IC_RAW_INTR_STAT_RX_DONE) + +#define BIT_IC_RAW_INTR_STAT_TX_ABRT BIT(6) +#define BIT_SHIFT_IC_RAW_INTR_STAT_TX_ABRT 6 +#define BIT_MASK_IC_RAW_INTR_STAT_TX_ABRT 0x1 +#define BIT_CTRL_IC_RAW_INTR_STAT_TX_ABRT(x) (((x) & BIT_MASK_IC_RAW_INTR_STAT_TX_ABRT) << BIT_SHIFT_IC_RAW_INTR_STAT_TX_ABRT) + +#define BIT_IC_RAW_INTR_STAT_RD_REQ BIT(5) +#define BIT_SHIFT_IC_RAW_INTR_STAT_RD_REQ 5 +#define BIT_MASK_IC_RAW_INTR_STAT_RD_REQ 0x1 +#define BIT_CTRL_IC_RAW_INTR_STAT_RD_REQ(x) (((x) & BIT_MASK_IC_RAW_INTR_STAT_RD_REQ) << BIT_SHIFT_IC_RAW_INTR_STAT_RD_REQ) + +#define BIT_IC_RAW_INTR_STAT_TX_EMPTY BIT(4) +#define BIT_SHIFT_IC_RAW_INTR_STAT_TX_EMPTY 4 +#define BIT_MASK_IC_RAW_INTR_STAT_TX_EMPTY 0x1 +#define BIT_CTRL_IC_RAW_INTR_STAT_TX_EMPTY(x) (((x) & BIT_MASK_IC_RAW_INTR_STAT_TX_EMPTY) << BIT_SHIFT_IC_RAW_INTR_STAT_TX_EMPTY) + +#define BIT_IC_RAW_INTR_STAT_TX_OVER BIT(3) +#define BIT_SHIFT_IC_RAW_INTR_STAT_TX_OVER 3 +#define BIT_MASK_IC_RAW_INTR_STAT_TX_OVER 0x1 +#define BIT_CTRL_IC_RAW_INTR_STAT_TX_OVER(x) (((x) & BIT_MASK_IC_RAW_INTR_STAT_TX_OVER) << BIT_SHIFT_IC_RAW_INTR_STAT_TX_OVER) + +#define BIT_IC_RAW_INTR_STAT_RX_FULL BIT(2) +#define BIT_SHIFT_IC_RAW_INTR_STAT_RX_FULL 2 +#define BIT_MASK_IC_RAW_INTR_STAT_RX_FULL 0x1 +#define BIT_CTRL_IC_RAW_INTR_STAT_RX_FULL(x) (((x) & BIT_MASK_IC_RAW_INTR_STAT_RX_FULL) << BIT_SHIFT_IC_RAW_INTR_STAT_RX_FULL) + +#define BIT_IC_RAW_INTR_STAT_RX_OVER BIT(1) +#define BIT_SHIFT_IC_RAW_INTR_STAT_RX_OVER 1 +#define BIT_MASK_IC_RAW_INTR_STAT_RX_OVER 0x1 +#define BIT_CTRL_IC_RAW_INTR_STAT_RX_OVER(x) (((x) & BIT_MASK_IC_RAW_INTR_STAT_RX_OVER) << BIT_SHIFT_IC_RAW_INTR_STAT_RX_OVER) + +#define BIT_IC_RAW_INTR_STAT_RX_UNDER BIT(0) +#define BIT_SHIFT_IC_RAW_INTR_STAT_RX_UNDER 0 +#define BIT_MASK_IC_RAW_INTR_STAT_RX_UNDER 0x1 +#define BIT_CTRL_IC_RAW_INTR_STAT_RX_UNDER(x) (((x) & BIT_MASK_IC_RAW_INTR_STAT_RX_UNDER) << BIT_SHIFT_IC_RAW_INTR_STAT_RX_UNDER) + + +//2 REG_DW_I2C_IC_RX_TL + +#define BIT_SHIFT_IC_RX_TL 0 +#define BIT_MASK_IC_RX_TL 0xff +#define BIT_IC_RX_TL(x) (((x) & BIT_MASK_IC_RX_TL) << BIT_SHIFT_IC_RX_TL) +#define BIT_CTRL_IC_RX_TL(x) (((x) & BIT_MASK_IC_RX_TL) << BIT_SHIFT_IC_RX_TL) +#define BIT_GET_IC_RX_TL(x) (((x) >> BIT_SHIFT_IC_RX_TL) & BIT_MASK_IC_RX_TL) + + +//2 REG_DW_I2C_IC_TX_TL + +#define BIT_SHIFT_IC_TX_TL 0 +#define BIT_MASK_IC_TX_TL 0xff +#define BIT_IC_TX_TL(x) (((x) & BIT_MASK_IC_TX_TL) << BIT_SHIFT_IC_TX_TL) +#define BIT_CTRL_IC_TX_TL(x) (((x) & BIT_MASK_IC_TX_TL) << BIT_SHIFT_IC_TX_TL) +#define BIT_GET_IC_TX_TL(x) (((x) >> BIT_SHIFT_IC_TX_TL) & BIT_MASK_IC_TX_TL) + + +//2 REG_DW_I2C_IC_CLR_INTR +#define BIT_IC_CLR_INTR BIT(0) +#define BIT_SHIFT_IC_CLR_INTR 0 +#define BIT_MASK_IC_CLR_INTR 0x1 +#define BIT_CTRL_IC_CLR_INTR(x) (((x) & BIT_MASK_IC_CLR_INTR) << BIT_SHIFT_IC_CLR_INTR) + + +//2 REG_DW_I2C_IC_CLR_RX_UNDER +#define BIT_IC_CLR_RX_UNDER BIT(0) +#define BIT_SHIFT_IC_CLR_RX_UNDER 0 +#define BIT_MASK_IC_CLR_RX_UNDER 0x1 +#define BIT_CTRL_IC_CLR_RX_UNDER(x) (((x) & BIT_MASK_IC_CLR_RX_UNDER) << BIT_SHIFT_IC_CLR_RX_UNDER) + + +//2 REG_DW_I2C_IC_CLR_RX_OVER +#define BIT_IC_CLR_RX_OVER BIT(0) +#define BIT_SHIFT_IC_CLR_RX_OVER 0 +#define BIT_MASK_IC_CLR_RX_OVER 0x1 +#define BIT_CTRL_IC_CLR_RX_OVER(x) (((x) & BIT_MASK_IC_CLR_RX_OVER) << BIT_SHIFT_IC_CLR_RX_OVER) + + +//2 REG_DW_I2C_IC_CLR_TX_OVER +#define BIT_IC_CLR_TX_OVER BIT(0) +#define BIT_SHIFT_IC_CLR_TX_OVER 0 +#define BIT_MASK_IC_CLR_TX_OVER 0x1 +#define BIT_CTRL_IC_CLR_TX_OVER(x) (((x) & BIT_MASK_IC_CLR_TX_OVER) << BIT_SHIFT_IC_CLR_TX_OVER) + + +//2 REG_DW_I2C_IC_CLR_RD_REQ +#define BIT_IC_CLR_RD_REQ BIT(0) +#define BIT_SHIFT_IC_CLR_RD_REQ 0 +#define BIT_MASK_IC_CLR_RD_REQ 0x1 +#define BIT_CTRL_IC_CLR_RD_REQ(x) (((x) & BIT_MASK_IC_CLR_RD_REQ) << BIT_SHIFT_IC_CLR_RD_REQ) + + +//2 REG_DW_I2C_IC_CLR_TX_ABRT +#define BIT_CLR_RD_REQ BIT(0) +#define BIT_SHIFT_CLR_RD_REQ 0 +#define BIT_MASK_CLR_RD_REQ 0x1 +#define BIT_CTRL_CLR_RD_REQ(x) (((x) & BIT_MASK_CLR_RD_REQ) << BIT_SHIFT_CLR_RD_REQ) + + +//2 REG_DW_I2C_IC_CLR_RX_DONE +#define BIT_IC_CLR_RX_DONE BIT(0) +#define BIT_SHIFT_IC_CLR_RX_DONE 0 +#define BIT_MASK_IC_CLR_RX_DONE 0x1 +#define BIT_CTRL_IC_CLR_RX_DONE(x) (((x) & BIT_MASK_IC_CLR_RX_DONE) << BIT_SHIFT_IC_CLR_RX_DONE) + + +//2 REG_DW_I2C_IC_CLR_ACTIVITY +#define BIT_IC_CLR_ACTIVITY BIT(0) +#define BIT_SHIFT_IC_CLR_ACTIVITY 0 +#define BIT_MASK_IC_CLR_ACTIVITY 0x1 +#define BIT_CTRL_IC_CLR_ACTIVITY(x) (((x) & BIT_MASK_IC_CLR_ACTIVITY) << BIT_SHIFT_IC_CLR_ACTIVITY) + + +//2 REG_DW_I2C_IC_CLR_STOP_DET +#define BIT_IC_CLR_STOP_DET BIT(0) +#define BIT_SHIFT_IC_CLR_STOP_DET 0 +#define BIT_MASK_IC_CLR_STOP_DET 0x1 +#define BIT_CTRL_IC_CLR_STOP_DET(x) (((x) & BIT_MASK_IC_CLR_STOP_DET) << BIT_SHIFT_IC_CLR_STOP_DET) + + +//2 REG_DW_I2C_IC_CLR_START_DET +#define BIT_IC_CLR_START_DET BIT(0) +#define BIT_SHIFT_IC_CLR_START_DET 0 +#define BIT_MASK_IC_CLR_START_DET 0x1 +#define BIT_CTRL_IC_CLR_START_DET(x) (((x) & BIT_MASK_IC_CLR_START_DET) << BIT_SHIFT_IC_CLR_START_DET) + + +//2 REG_DW_I2C_IC_CLR_GEN_CALL +#define BIT_IC_CLR_GEN_CALL BIT(0) +#define BIT_SHIFT_IC_CLR_GEN_CALL 0 +#define BIT_MASK_IC_CLR_GEN_CALL 0x1 +#define BIT_CTRL_IC_CLR_GEN_CALL(x) (((x) & BIT_MASK_IC_CLR_GEN_CALL) << BIT_SHIFT_IC_CLR_GEN_CALL) + + +//2 REG_DW_I2C_IC_ENABLE +#define BIT_IC_ENABLE BIT(0) +#define BIT_SHIFT_IC_ENABLE 0 +#define BIT_MASK_IC_ENABLE 0x1 +#define BIT_CTRL_IC_ENABLE(x) (((x) & BIT_MASK_IC_ENABLE) << BIT_SHIFT_IC_ENABLE) + + +//2 REG_DW_I2C_IC_STATUS +#define BIT_IC_STATUS_SLV_ACTIVITY BIT(6) +#define BIT_SHIFT_IC_STATUS_SLV_ACTIVITY 6 +#define BIT_MASK_IC_STATUS_SLV_ACTIVITY 0x1 +#define BIT_CTRL_IC_STATUS_SLV_ACTIVITY(x) (((x) & BIT_MASK_IC_STATUS_SLV_ACTIVITY) << BIT_SHIFT_IC_STATUS_SLV_ACTIVITY) + +#define BIT_IC_STATUS_MST_ACTIVITY BIT(5) +#define BIT_SHIFT_IC_STATUS_MST_ACTIVITY 5 +#define BIT_MASK_IC_STATUS_MST_ACTIVITY 0x1 +#define BIT_CTRL_IC_STATUS_MST_ACTIVITY(x) (((x) & BIT_MASK_IC_STATUS_MST_ACTIVITY) << BIT_SHIFT_IC_STATUS_MST_ACTIVITY) + +#define BIT_IC_STATUS_RFF BIT(4) +#define BIT_SHIFT_IC_STATUS_RFF 4 +#define BIT_MASK_IC_STATUS_RFF 0x1 +#define BIT_CTRL_IC_STATUS_RFF(x) (((x) & BIT_MASK_IC_STATUS_RFF) << BIT_SHIFT_IC_STATUS_RFF) + +#define BIT_IC_STATUS_RFNE BIT(3) +#define BIT_SHIFT_IC_STATUS_RFNE 3 +#define BIT_MASK_IC_STATUS_RFNE 0x1 +#define BIT_CTRL_IC_STATUS_RFNE(x) (((x) & BIT_MASK_IC_STATUS_RFNE) << BIT_SHIFT_IC_STATUS_RFNE) + +#define BIT_IC_STATUS_TFE BIT(2) +#define BIT_SHIFT_IC_STATUS_TFE 2 +#define BIT_MASK_IC_STATUS_TFE 0x1 +#define BIT_CTRL_IC_STATUS_TFE(x) (((x) & BIT_MASK_IC_STATUS_TFE) << BIT_SHIFT_IC_STATUS_TFE) + +#define BIT_IC_STATUS_TFNF BIT(1) +#define BIT_SHIFT_IC_STATUS_TFNF 1 +#define BIT_MASK_IC_STATUS_TFNF 0x1 +#define BIT_CTRL_IC_STATUS_TFNF(x) (((x) & BIT_MASK_IC_STATUS_TFNF) << BIT_SHIFT_IC_STATUS_TFNF) + +#define BIT_IC_STATUS_ACTIVITY BIT(0) +#define BIT_SHIFT_IC_STATUS_ACTIVITY 0 +#define BIT_MASK_IC_STATUS_ACTIVITY 0x1 +#define BIT_CTRL_IC_STATUS_ACTIVITY(x) (((x) & BIT_MASK_IC_STATUS_ACTIVITY) << BIT_SHIFT_IC_STATUS_ACTIVITY) + + +//2 REG_DW_I2C_IC_TXFLR + +#define BIT_SHIFT_IC_TXFLR 0 +#define BIT_MASK_IC_TXFLR 0x3f +#define BIT_IC_TXFLR(x) (((x) & BIT_MASK_IC_TXFLR) << BIT_SHIFT_IC_TXFLR) +#define BIT_CTRL_IC_TXFLR(x) (((x) & BIT_MASK_IC_TXFLR) << BIT_SHIFT_IC_TXFLR) +#define BIT_GET_IC_TXFLR(x) (((x) >> BIT_SHIFT_IC_TXFLR) & BIT_MASK_IC_TXFLR) + + +//2 REG_DW_I2C_IC_RXFLR + +#define BIT_SHIFT_IC_RXFLR 0 +#define BIT_MASK_IC_RXFLR 0x1f +#define BIT_IC_RXFLR(x) (((x) & BIT_MASK_IC_RXFLR) << BIT_SHIFT_IC_RXFLR) +#define BIT_CTRL_IC_RXFLR(x) (((x) & BIT_MASK_IC_RXFLR) << BIT_SHIFT_IC_RXFLR) +#define BIT_GET_IC_RXFLR(x) (((x) >> BIT_SHIFT_IC_RXFLR) & BIT_MASK_IC_RXFLR) + + +//2 REG_DW_I2C_IC_SDA_HOLD + +#define BIT_SHIFT_IC_SDA_HOLD 0 +#define BIT_MASK_IC_SDA_HOLD 0xffff +#define BIT_IC_SDA_HOLD(x) (((x) & BIT_MASK_IC_SDA_HOLD) << BIT_SHIFT_IC_SDA_HOLD) +#define BIT_CTRL_IC_SDA_HOLD(x) (((x) & BIT_MASK_IC_SDA_HOLD) << BIT_SHIFT_IC_SDA_HOLD) +#define BIT_GET_IC_SDA_HOLD(x) (((x) >> BIT_SHIFT_IC_SDA_HOLD) & BIT_MASK_IC_SDA_HOLD) + + +//2 REG_DW_I2C_IC_TX_ABRT_SOURCE +#define BIT_IC_TX_ABRT_SOURCE_ABRT_SLVRD_INTX BIT(15) +#define BIT_SHIFT_IC_TX_ABRT_SOURCE_ABRT_SLVRD_INTX 15 +#define BIT_MASK_IC_TX_ABRT_SOURCE_ABRT_SLVRD_INTX 0x1 +#define BIT_CTRL_IC_TX_ABRT_SOURCE_ABRT_SLVRD_INTX(x) (((x) & BIT_MASK_IC_TX_ABRT_SOURCE_ABRT_SLVRD_INTX) << BIT_SHIFT_IC_TX_ABRT_SOURCE_ABRT_SLVRD_INTX) + +#define BIT_IC_TX_ABRT_SOURCE_ABRT_SLV_ARBLOST BIT(14) +#define BIT_SHIFT_IC_TX_ABRT_SOURCE_ABRT_SLV_ARBLOST 14 +#define BIT_MASK_IC_TX_ABRT_SOURCE_ABRT_SLV_ARBLOST 0x1 +#define BIT_CTRL_IC_TX_ABRT_SOURCE_ABRT_SLV_ARBLOST(x) (((x) & BIT_MASK_IC_TX_ABRT_SOURCE_ABRT_SLV_ARBLOST) << BIT_SHIFT_IC_TX_ABRT_SOURCE_ABRT_SLV_ARBLOST) + +#define BIT_IC_TX_ABRT_SOURCE_ABRT_SLVFLUSH_TXFIFO BIT(13) +#define BIT_SHIFT_IC_TX_ABRT_SOURCE_ABRT_SLVFLUSH_TXFIFO 13 +#define BIT_MASK_IC_TX_ABRT_SOURCE_ABRT_SLVFLUSH_TXFIFO 0x1 +#define BIT_CTRL_IC_TX_ABRT_SOURCE_ABRT_SLVFLUSH_TXFIFO(x) (((x) & BIT_MASK_IC_TX_ABRT_SOURCE_ABRT_SLVFLUSH_TXFIFO) << BIT_SHIFT_IC_TX_ABRT_SOURCE_ABRT_SLVFLUSH_TXFIFO) + +#define BIT_IC_TX_ABRT_SOURCE_ARB_LOST BIT(12) +#define BIT_SHIFT_IC_TX_ABRT_SOURCE_ARB_LOST 12 +#define BIT_MASK_IC_TX_ABRT_SOURCE_ARB_LOST 0x1 +#define BIT_CTRL_IC_TX_ABRT_SOURCE_ARB_LOST(x) (((x) & BIT_MASK_IC_TX_ABRT_SOURCE_ARB_LOST) << BIT_SHIFT_IC_TX_ABRT_SOURCE_ARB_LOST) + +#define BIT_IC_TX_ABRT_SOURCE_ABRT_MASTER_DIS BIT(11) +#define BIT_SHIFT_IC_TX_ABRT_SOURCE_ABRT_MASTER_DIS 11 +#define BIT_MASK_IC_TX_ABRT_SOURCE_ABRT_MASTER_DIS 0x1 +#define BIT_CTRL_IC_TX_ABRT_SOURCE_ABRT_MASTER_DIS(x) (((x) & BIT_MASK_IC_TX_ABRT_SOURCE_ABRT_MASTER_DIS) << BIT_SHIFT_IC_TX_ABRT_SOURCE_ABRT_MASTER_DIS) + +#define BIT_IC_TX_ABRT_SOURCE_ABRT_10B_RD_NORSTRT BIT(10) +#define BIT_SHIFT_IC_TX_ABRT_SOURCE_ABRT_10B_RD_NORSTRT 10 +#define BIT_MASK_IC_TX_ABRT_SOURCE_ABRT_10B_RD_NORSTRT 0x1 +#define BIT_CTRL_IC_TX_ABRT_SOURCE_ABRT_10B_RD_NORSTRT(x) (((x) & BIT_MASK_IC_TX_ABRT_SOURCE_ABRT_10B_RD_NORSTRT) << BIT_SHIFT_IC_TX_ABRT_SOURCE_ABRT_10B_RD_NORSTRT) + +#define BIT_IC_TX_ABRT_SOURCE_ABRT_SBYTE_NORSTRT BIT(9) +#define BIT_SHIFT_IC_TX_ABRT_SOURCE_ABRT_SBYTE_NORSTRT 9 +#define BIT_MASK_IC_TX_ABRT_SOURCE_ABRT_SBYTE_NORSTRT 0x1 +#define BIT_CTRL_IC_TX_ABRT_SOURCE_ABRT_SBYTE_NORSTRT(x) (((x) & BIT_MASK_IC_TX_ABRT_SOURCE_ABRT_SBYTE_NORSTRT) << BIT_SHIFT_IC_TX_ABRT_SOURCE_ABRT_SBYTE_NORSTRT) + +#define BIT_IC_TX_ABRT_SOURCE_ABRT_HS_NORSTRT BIT(8) +#define BIT_SHIFT_IC_TX_ABRT_SOURCE_ABRT_HS_NORSTRT 8 +#define BIT_MASK_IC_TX_ABRT_SOURCE_ABRT_HS_NORSTRT 0x1 +#define BIT_CTRL_IC_TX_ABRT_SOURCE_ABRT_HS_NORSTRT(x) (((x) & BIT_MASK_IC_TX_ABRT_SOURCE_ABRT_HS_NORSTRT) << BIT_SHIFT_IC_TX_ABRT_SOURCE_ABRT_HS_NORSTRT) + +#define BIT_IC_TX_ABRT_SOURCE_ABRT_SBYTE_ACKDET BIT(7) +#define BIT_SHIFT_IC_TX_ABRT_SOURCE_ABRT_SBYTE_ACKDET 7 +#define BIT_MASK_IC_TX_ABRT_SOURCE_ABRT_SBYTE_ACKDET 0x1 +#define BIT_CTRL_IC_TX_ABRT_SOURCE_ABRT_SBYTE_ACKDET(x) (((x) & BIT_MASK_IC_TX_ABRT_SOURCE_ABRT_SBYTE_ACKDET) << BIT_SHIFT_IC_TX_ABRT_SOURCE_ABRT_SBYTE_ACKDET) + +#define BIT_IC_TX_ABRT_SOURCE_ABRT_HS_ACKDET BIT(6) +#define BIT_SHIFT_IC_TX_ABRT_SOURCE_ABRT_HS_ACKDET 6 +#define BIT_MASK_IC_TX_ABRT_SOURCE_ABRT_HS_ACKDET 0x1 +#define BIT_CTRL_IC_TX_ABRT_SOURCE_ABRT_HS_ACKDET(x) (((x) & BIT_MASK_IC_TX_ABRT_SOURCE_ABRT_HS_ACKDET) << BIT_SHIFT_IC_TX_ABRT_SOURCE_ABRT_HS_ACKDET) + +#define BIT_IC_TX_ABRT_SOURCE_ABRT_GCALL_READ BIT(5) +#define BIT_SHIFT_IC_TX_ABRT_SOURCE_ABRT_GCALL_READ 5 +#define BIT_MASK_IC_TX_ABRT_SOURCE_ABRT_GCALL_READ 0x1 +#define BIT_CTRL_IC_TX_ABRT_SOURCE_ABRT_GCALL_READ(x) (((x) & BIT_MASK_IC_TX_ABRT_SOURCE_ABRT_GCALL_READ) << BIT_SHIFT_IC_TX_ABRT_SOURCE_ABRT_GCALL_READ) + +#define BIT_IC_TX_ABRT_SOURCE_ABRT_GCALL_NOACK BIT(4) +#define BIT_SHIFT_IC_TX_ABRT_SOURCE_ABRT_GCALL_NOACK 4 +#define BIT_MASK_IC_TX_ABRT_SOURCE_ABRT_GCALL_NOACK 0x1 +#define BIT_CTRL_IC_TX_ABRT_SOURCE_ABRT_GCALL_NOACK(x) (((x) & BIT_MASK_IC_TX_ABRT_SOURCE_ABRT_GCALL_NOACK) << BIT_SHIFT_IC_TX_ABRT_SOURCE_ABRT_GCALL_NOACK) + +#define BIT_IC_TX_ABRT_SOURCE_ABRT_TXDATA_NOACK BIT(3) +#define BIT_SHIFT_IC_TX_ABRT_SOURCE_ABRT_TXDATA_NOACK 3 +#define BIT_MASK_IC_TX_ABRT_SOURCE_ABRT_TXDATA_NOACK 0x1 +#define BIT_CTRL_IC_TX_ABRT_SOURCE_ABRT_TXDATA_NOACK(x) (((x) & BIT_MASK_IC_TX_ABRT_SOURCE_ABRT_TXDATA_NOACK) << BIT_SHIFT_IC_TX_ABRT_SOURCE_ABRT_TXDATA_NOACK) + +#define BIT_IC_TX_ABRT_SOURCE_ABRT_10ADDR2_NOACK BIT(2) +#define BIT_SHIFT_IC_TX_ABRT_SOURCE_ABRT_10ADDR2_NOACK 2 +#define BIT_MASK_IC_TX_ABRT_SOURCE_ABRT_10ADDR2_NOACK 0x1 +#define BIT_CTRL_IC_TX_ABRT_SOURCE_ABRT_10ADDR2_NOACK(x) (((x) & BIT_MASK_IC_TX_ABRT_SOURCE_ABRT_10ADDR2_NOACK) << BIT_SHIFT_IC_TX_ABRT_SOURCE_ABRT_10ADDR2_NOACK) + +#define BIT_IC_TX_ABRT_SOURCE_ABRT_10ADDR1_NOACK BIT(1) +#define BIT_SHIFT_IC_TX_ABRT_SOURCE_ABRT_10ADDR1_NOACK 1 +#define BIT_MASK_IC_TX_ABRT_SOURCE_ABRT_10ADDR1_NOACK 0x1 +#define BIT_CTRL_IC_TX_ABRT_SOURCE_ABRT_10ADDR1_NOACK(x) (((x) & BIT_MASK_IC_TX_ABRT_SOURCE_ABRT_10ADDR1_NOACK) << BIT_SHIFT_IC_TX_ABRT_SOURCE_ABRT_10ADDR1_NOACK) + +#define BIT_IC_TX_ABRT_SOURCE_ABRT_7B_ADDR_NOACK BIT(0) +#define BIT_SHIFT_IC_TX_ABRT_SOURCE_ABRT_7B_ADDR_NOACK 0 +#define BIT_MASK_IC_TX_ABRT_SOURCE_ABRT_7B_ADDR_NOACK 0x1 +#define BIT_CTRL_IC_TX_ABRT_SOURCE_ABRT_7B_ADDR_NOACK(x) (((x) & BIT_MASK_IC_TX_ABRT_SOURCE_ABRT_7B_ADDR_NOACK) << BIT_SHIFT_IC_TX_ABRT_SOURCE_ABRT_7B_ADDR_NOACK) + + +//2 REG_DW_I2C_IC_SLV_DATA_NACK_ONLY +#define BIT_IC_SLV_DATA_NACK_ONLY BIT(0) +#define BIT_SHIFT_IC_SLV_DATA_NACK_ONLY 0 +#define BIT_MASK_IC_SLV_DATA_NACK_ONLY 0x1 +#define BIT_CTRL_IC_SLV_DATA_NACK_ONLY(x) (((x) & BIT_MASK_IC_SLV_DATA_NACK_ONLY) << BIT_SHIFT_IC_SLV_DATA_NACK_ONLY) + + +//2 REG_DW_I2C_IC_DMA_CR +#define BIT_IC_DMA_CR_TDMAE BIT(1) +#define BIT_SHIFT_IC_DMA_CR_TDMAE 1 +#define BIT_MASK_IC_DMA_CR_TDMAE 0x1 +#define BIT_CTRL_IC_DMA_CR_TDMAE(x) (((x) & BIT_MASK_IC_DMA_CR_TDMAE) << BIT_SHIFT_IC_DMA_CR_TDMAE) + +#define BIT_IC_DMA_CR_RDMAE BIT(0) +#define BIT_SHIFT_IC_DMA_CR_RDMAE 0 +#define BIT_MASK_IC_DMA_CR_RDMAE 0x1 +#define BIT_CTRL_IC_DMA_CR_RDMAE(x) (((x) & BIT_MASK_IC_DMA_CR_RDMAE) << BIT_SHIFT_IC_DMA_CR_RDMAE) + + +//2 REG_DW_I2C_IC_DMA_TDLR + +#define BIT_SHIFT_IC_DMA_TDLR_DMATDL 0 +#define BIT_MASK_IC_DMA_TDLR_DMATDL 0x1f +#define BIT_IC_DMA_TDLR_DMATDL(x) (((x) & BIT_MASK_IC_DMA_TDLR_DMATDL) << BIT_SHIFT_IC_DMA_TDLR_DMATDL) +#define BIT_CTRL_IC_DMA_TDLR_DMATDL(x) (((x) & BIT_MASK_IC_DMA_TDLR_DMATDL) << BIT_SHIFT_IC_DMA_TDLR_DMATDL) +#define BIT_GET_IC_DMA_TDLR_DMATDL(x) (((x) >> BIT_SHIFT_IC_DMA_TDLR_DMATDL) & BIT_MASK_IC_DMA_TDLR_DMATDL) + + +//2 REG_DW_I2C_IC_DMA_RDLR + +#define BIT_SHIFT_IC_DMA_RDLR_DMARDL 0 +#define BIT_MASK_IC_DMA_RDLR_DMARDL 0xf +#define BIT_IC_DMA_RDLR_DMARDL(x) (((x) & BIT_MASK_IC_DMA_RDLR_DMARDL) << BIT_SHIFT_IC_DMA_RDLR_DMARDL) +#define BIT_CTRL_IC_DMA_RDLR_DMARDL(x) (((x) & BIT_MASK_IC_DMA_RDLR_DMARDL) << BIT_SHIFT_IC_DMA_RDLR_DMARDL) +#define BIT_GET_IC_DMA_RDLR_DMARDL(x) (((x) >> BIT_SHIFT_IC_DMA_RDLR_DMARDL) & BIT_MASK_IC_DMA_RDLR_DMARDL) + + +//2 REG_DW_I2C_IC_SDA_SETUP + +#define BIT_SHIFT_IC_SDA_SETUP 0 +#define BIT_MASK_IC_SDA_SETUP 0xff +#define BIT_IC_SDA_SETUP(x) (((x) & BIT_MASK_IC_SDA_SETUP) << BIT_SHIFT_IC_SDA_SETUP) +#define BIT_CTRL_IC_SDA_SETUP(x) (((x) & BIT_MASK_IC_SDA_SETUP) << BIT_SHIFT_IC_SDA_SETUP) +#define BIT_GET_IC_SDA_SETUP(x) (((x) >> BIT_SHIFT_IC_SDA_SETUP) & BIT_MASK_IC_SDA_SETUP) + + +//2 REG_DW_I2C_IC_ACK_GENERAL_CALL +#define BIT_IC_ACK_GENERAL_CALL BIT(0) +#define BIT_SHIFT_IC_ACK_GENERAL_CALL 0 +#define BIT_MASK_IC_ACK_GENERAL_CALL 0x1 +#define BIT_CTRL_IC_ACK_GENERAL_CALL(x) (((x) & BIT_MASK_IC_ACK_GENERAL_CALL) << BIT_SHIFT_IC_ACK_GENERAL_CALL) + + +//2 REG_DW_I2C_IC_ENABLE_STATUS +#define BIT_IC_ENABLE_STATUS_SLV_RX_DATA_LOST BIT(2) +#define BIT_SHIFT_IC_ENABLE_STATUS_SLV_RX_DATA_LOST 2 +#define BIT_MASK_IC_ENABLE_STATUS_SLV_RX_DATA_LOST 0x1 +#define BIT_CTRL_IC_ENABLE_STATUS_SLV_RX_DATA_LOST(x) (((x) & BIT_MASK_IC_ENABLE_STATUS_SLV_RX_DATA_LOST) << BIT_SHIFT_IC_ENABLE_STATUS_SLV_RX_DATA_LOST) + +#define BIT_IC_ENABLE_STATUS_SLV_DISABLED_WHILE_BUSY BIT(1) +#define BIT_SHIFT_IC_ENABLE_STATUS_SLV_DISABLED_WHILE_BUSY 1 +#define BIT_MASK_IC_ENABLE_STATUS_SLV_DISABLED_WHILE_BUSY 0x1 +#define BIT_CTRL_IC_ENABLE_STATUS_SLV_DISABLED_WHILE_BUSY(x) (((x) & BIT_MASK_IC_ENABLE_STATUS_SLV_DISABLED_WHILE_BUSY) << BIT_SHIFT_IC_ENABLE_STATUS_SLV_DISABLED_WHILE_BUSY) + +#define BIT_IC_ENABLE_STATUS_IC_EN BIT(0) +#define BIT_SHIFT_IC_ENABLE_STATUS_IC_EN 0 +#define BIT_MASK_IC_ENABLE_STATUS_IC_EN 0x1 +#define BIT_CTRL_IC_ENABLE_STATUS_IC_EN(x) (((x) & BIT_MASK_IC_ENABLE_STATUS_IC_EN) << BIT_SHIFT_IC_ENABLE_STATUS_IC_EN) + + +//2 REG_DW_I2C_IC_COMP_PARAM_1 + +#define BIT_SHIFT_IC_COMP_PARAM_1_TX_BUFFER_DEPTH 16 +#define BIT_MASK_IC_COMP_PARAM_1_TX_BUFFER_DEPTH 0xff +#define BIT_IC_COMP_PARAM_1_TX_BUFFER_DEPTH(x) (((x) & BIT_MASK_IC_COMP_PARAM_1_TX_BUFFER_DEPTH) << BIT_SHIFT_IC_COMP_PARAM_1_TX_BUFFER_DEPTH) +#define BIT_CTRL_IC_COMP_PARAM_1_TX_BUFFER_DEPTH(x) (((x) & BIT_MASK_IC_COMP_PARAM_1_TX_BUFFER_DEPTH) << BIT_SHIFT_IC_COMP_PARAM_1_TX_BUFFER_DEPTH) +#define BIT_GET_IC_COMP_PARAM_1_TX_BUFFER_DEPTH(x) (((x) >> BIT_SHIFT_IC_COMP_PARAM_1_TX_BUFFER_DEPTH) & BIT_MASK_IC_COMP_PARAM_1_TX_BUFFER_DEPTH) + + +#define BIT_SHIFT_IC_COMP_PARAM_1_RX_BUFFER_DEPTH 8 +#define BIT_MASK_IC_COMP_PARAM_1_RX_BUFFER_DEPTH 0xff +#define BIT_IC_COMP_PARAM_1_RX_BUFFER_DEPTH(x) (((x) & BIT_MASK_IC_COMP_PARAM_1_RX_BUFFER_DEPTH) << BIT_SHIFT_IC_COMP_PARAM_1_RX_BUFFER_DEPTH) +#define BIT_CTRL_IC_COMP_PARAM_1_RX_BUFFER_DEPTH(x) (((x) & BIT_MASK_IC_COMP_PARAM_1_RX_BUFFER_DEPTH) << BIT_SHIFT_IC_COMP_PARAM_1_RX_BUFFER_DEPTH) +#define BIT_GET_IC_COMP_PARAM_1_RX_BUFFER_DEPTH(x) (((x) >> BIT_SHIFT_IC_COMP_PARAM_1_RX_BUFFER_DEPTH) & BIT_MASK_IC_COMP_PARAM_1_RX_BUFFER_DEPTH) + +#define BIT_IC_COMP_PARAM_1_ADD_ENCODED_PARAMS BIT(7) +#define BIT_SHIFT_IC_COMP_PARAM_1_ADD_ENCODED_PARAMS 7 +#define BIT_MASK_IC_COMP_PARAM_1_ADD_ENCODED_PARAMS 0x1 +#define BIT_CTRL_IC_COMP_PARAM_1_ADD_ENCODED_PARAMS(x) (((x) & BIT_MASK_IC_COMP_PARAM_1_ADD_ENCODED_PARAMS) << BIT_SHIFT_IC_COMP_PARAM_1_ADD_ENCODED_PARAMS) + +#define BIT_IC_COMP_PARAM_1_HAS_DMA BIT(6) +#define BIT_SHIFT_IC_COMP_PARAM_1_HAS_DMA 6 +#define BIT_MASK_IC_COMP_PARAM_1_HAS_DMA 0x1 +#define BIT_CTRL_IC_COMP_PARAM_1_HAS_DMA(x) (((x) & BIT_MASK_IC_COMP_PARAM_1_HAS_DMA) << BIT_SHIFT_IC_COMP_PARAM_1_HAS_DMA) + +#define BIT_IC_COMP_PARAM_1_INTR_IO BIT(5) +#define BIT_SHIFT_IC_COMP_PARAM_1_INTR_IO 5 +#define BIT_MASK_IC_COMP_PARAM_1_INTR_IO 0x1 +#define BIT_CTRL_IC_COMP_PARAM_1_INTR_IO(x) (((x) & BIT_MASK_IC_COMP_PARAM_1_INTR_IO) << BIT_SHIFT_IC_COMP_PARAM_1_INTR_IO) + +#define BIT_IC_COMP_PARAM_1_HC_COUNT_VALUES BIT(4) +#define BIT_SHIFT_IC_COMP_PARAM_1_HC_COUNT_VALUES 4 +#define BIT_MASK_IC_COMP_PARAM_1_HC_COUNT_VALUES 0x1 +#define BIT_CTRL_IC_COMP_PARAM_1_HC_COUNT_VALUES(x) (((x) & BIT_MASK_IC_COMP_PARAM_1_HC_COUNT_VALUES) << BIT_SHIFT_IC_COMP_PARAM_1_HC_COUNT_VALUES) + + +#define BIT_SHIFT_IC_COMP_PARAM_1_MAX_SPEED_MODE 2 +#define BIT_MASK_IC_COMP_PARAM_1_MAX_SPEED_MODE 0x3 +#define BIT_IC_COMP_PARAM_1_MAX_SPEED_MODE(x) (((x) & BIT_MASK_IC_COMP_PARAM_1_MAX_SPEED_MODE) << BIT_SHIFT_IC_COMP_PARAM_1_MAX_SPEED_MODE) +#define BIT_CTRL_IC_COMP_PARAM_1_MAX_SPEED_MODE(x) (((x) & BIT_MASK_IC_COMP_PARAM_1_MAX_SPEED_MODE) << BIT_SHIFT_IC_COMP_PARAM_1_MAX_SPEED_MODE) +#define BIT_GET_IC_COMP_PARAM_1_MAX_SPEED_MODE(x) (((x) >> BIT_SHIFT_IC_COMP_PARAM_1_MAX_SPEED_MODE) & BIT_MASK_IC_COMP_PARAM_1_MAX_SPEED_MODE) + + +#define BIT_SHIFT_IC_COMP_PARAM_1_APB_DATA_WIDTH 0 +#define BIT_MASK_IC_COMP_PARAM_1_APB_DATA_WIDTH 0x3 +#define BIT_IC_COMP_PARAM_1_APB_DATA_WIDTH(x) (((x) & BIT_MASK_IC_COMP_PARAM_1_APB_DATA_WIDTH) << BIT_SHIFT_IC_COMP_PARAM_1_APB_DATA_WIDTH) +#define BIT_CTRL_IC_COMP_PARAM_1_APB_DATA_WIDTH(x) (((x) & BIT_MASK_IC_COMP_PARAM_1_APB_DATA_WIDTH) << BIT_SHIFT_IC_COMP_PARAM_1_APB_DATA_WIDTH) +#define BIT_GET_IC_COMP_PARAM_1_APB_DATA_WIDTH(x) (((x) >> BIT_SHIFT_IC_COMP_PARAM_1_APB_DATA_WIDTH) & BIT_MASK_IC_COMP_PARAM_1_APB_DATA_WIDTH) + + +//2 REG_DW_I2C_IC_COMP_VERSION + +#define BIT_SHIFT_IC_COMP_VERSION 0 +#define BIT_MASK_IC_COMP_VERSION 0xffffffffL +#define BIT_IC_COMP_VERSION(x) (((x) & BIT_MASK_IC_COMP_VERSION) << BIT_SHIFT_IC_COMP_VERSION) +#define BIT_CTRL_IC_COMP_VERSION(x) (((x) & BIT_MASK_IC_COMP_VERSION) << BIT_SHIFT_IC_COMP_VERSION) +#define BIT_GET_IC_COMP_VERSION(x) (((x) >> BIT_SHIFT_IC_COMP_VERSION) & BIT_MASK_IC_COMP_VERSION) + + +//2 REG_DW_I2C_IC_COMP_TYPE + +#define BIT_SHIFT_IC_COMP_TYPE 0 +#define BIT_MASK_IC_COMP_TYPE 0xffffffffL +#define BIT_IC_COMP_TYPE(x) (((x) & BIT_MASK_IC_COMP_TYPE) << BIT_SHIFT_IC_COMP_TYPE) +#define BIT_CTRL_IC_COMP_TYPE(x) (((x) & BIT_MASK_IC_COMP_TYPE) << BIT_SHIFT_IC_COMP_TYPE) +#define BIT_GET_IC_COMP_TYPE(x) (((x) >> BIT_SHIFT_IC_COMP_TYPE) & BIT_MASK_IC_COMP_TYPE) + +//======================== Register Address Definition ======================== +#define REG_DW_I2C_IC_CON 0x0000 +#define REG_DW_I2C_IC_TAR 0x0004 +#define REG_DW_I2C_IC_SAR 0x0008 +#define REG_DW_I2C_IC_HS_MADDR 0x000C +#define REG_DW_I2C_IC_DATA_CMD 0x0010 +#define REG_DW_I2C_IC_SS_SCL_HCNT 0x0014 +#define REG_DW_I2C_IC_SS_SCL_LCNT 0x0018 +#define REG_DW_I2C_IC_FS_SCL_HCNT 0x001C +#define REG_DW_I2C_IC_FS_SCL_LCNT 0x0020 +#define REG_DW_I2C_IC_HS_SCL_HCNT 0x0024 +#define REG_DW_I2C_IC_HS_SCL_LCNT 0x0028 +#define REG_DW_I2C_IC_INTR_STAT 0x002C +#define REG_DW_I2C_IC_INTR_MASK 0x0030 +#define REG_DW_I2C_IC_RAW_INTR_STAT 0x0034 +#define REG_DW_I2C_IC_RX_TL 0x0038 +#define REG_DW_I2C_IC_TX_TL 0x003C +#define REG_DW_I2C_IC_CLR_INTR 0x0040 +#define REG_DW_I2C_IC_CLR_RX_UNDER 0x0044 +#define REG_DW_I2C_IC_CLR_RX_OVER 0x0048 +#define REG_DW_I2C_IC_CLR_TX_OVER 0x004C +#define REG_DW_I2C_IC_CLR_RD_REQ 0x0050 +#define REG_DW_I2C_IC_CLR_TX_ABRT 0x0054 +#define REG_DW_I2C_IC_CLR_RX_DONE 0x0058 +#define REG_DW_I2C_IC_CLR_ACTIVITY 0x005C +#define REG_DW_I2C_IC_CLR_STOP_DET 0x0060 +#define REG_DW_I2C_IC_CLR_START_DET 0x0064 +#define REG_DW_I2C_IC_CLR_GEN_CALL 0x0068 +#define REG_DW_I2C_IC_ENABLE 0x006C +#define REG_DW_I2C_IC_STATUS 0x0070 +#define REG_DW_I2C_IC_TXFLR 0x0074 +#define REG_DW_I2C_IC_RXFLR 0x0078 +#define REG_DW_I2C_IC_SDA_HOLD 0x007C +#define REG_DW_I2C_IC_TX_ABRT_SOURCE 0x0080 +#define REG_DW_I2C_IC_SLV_DATA_NACK_ONLY 0x0084 +#define REG_DW_I2C_IC_DMA_CR 0x0088 +#define REG_DW_I2C_IC_DMA_TDLR 0x008C +#define REG_DW_I2C_IC_DMA_RDLR 0x0090 +#define REG_DW_I2C_IC_SDA_SETUP 0x0094 +#define REG_DW_I2C_IC_ACK_GENERAL_CALL 0x0098 +#define REG_DW_I2C_IC_ENABLE_STATUS 0x009C +#define REG_DW_I2C_IC_COMP_PARAM_1 0x00F4 +#define REG_DW_I2C_IC_COMP_VERSION 0x00F8 +#define REG_DW_I2C_IC_COMP_TYPE 0x00FC + +//====================================================== +// I2C related enumeration +// I2C Address Mode +typedef enum _I2C_ADDR_MODE_ { + I2C_ADDR_7BIT = 0, + I2C_ADDR_10BIT = 1, +}I2C_ADDR_MODE,*PI2C_ADDR_MODE; + +// I2C Speed Mode +typedef enum _I2C_SPD_MODE_ { + I2C_SS_MODE = 1, + I2C_FS_MODE = 2, + I2C_HS_MODE = 3, +}I2C_SPD_MODE,*PI2C_SPD_MODE; + +//I2C Timing Parameters +#define I2C_SS_MIN_SCL_HTIME 4000 //the unit is ns. +#define I2C_SS_MIN_SCL_LTIME 4700 //the unit is ns. + +#define I2C_FS_MIN_SCL_HTIME 600 //the unit is ns. +#define I2C_FS_MIN_SCL_LTIME 1300 //the unit is ns. + +#define I2C_HS_MIN_SCL_HTIME_100 60 //the unit is ns, with bus loading = 100pf +#define I2C_HS_MIN_SCL_LTIME_100 120 //the unit is ns., with bus loading = 100pf + +#define I2C_HS_MIN_SCL_HTIME_400 160 //the unit is ns, with bus loading = 400pf +#define I2C_HS_MIN_SCL_LTIME_400 320 //the unit is ns., with bus loading = 400pf + + +//====================================================== +//I2C Essential functions and macros +_LONG_CALL_ VOID HalI2CWrite32(IN u8 I2CIdx, IN u8 I2CReg, IN u32 I2CVal); +_LONG_CALL_ u32 HalI2CRead32(IN u8 I2CIdx, IN u8 I2CReg); + +#define HAL_I2C_WRITE32(I2CIdx, addr, value) HalI2CWrite32(I2CIdx,addr,value) +#define HAL_I2C_READ32(I2CIdx, addr) HalI2CRead32(I2CIdx,addr) + +// Rtl8195a I2C function prototypes +_LONG_CALL_ HAL_Status HalI2CEnableRtl8195a(IN VOID *Data); +_LONG_CALL_ HAL_Status HalI2CInit8195a(IN VOID *Data); +_LONG_CALL_ HAL_Status HalI2CDeInit8195a(IN VOID *Data); +_LONG_CALL_ HAL_Status HalI2CSetCLKRtl8195a(IN VOID *Data); +_LONG_CALL_ HAL_Status HalI2CMassSendRtl8195a(IN VOID *Data); +_LONG_CALL_ HAL_Status HalI2CSendRtl8195a(IN VOID *Data); +_LONG_CALL_ u8 HalI2CReceiveRtl8195a(IN VOID *Data); +_LONG_CALL_ HAL_Status HalI2CIntrCtrl8195a(IN VOID *Data); +_LONG_CALL_ HAL_Status HalI2CClrIntrRtl8195a(IN VOID *Data); +_LONG_CALL_ HAL_Status HalI2CClrAllIntrRtl8195a(IN VOID *Data); +_LONG_CALL_ HAL_Status HalI2CDMACtrl8195a(IN VOID *Data); +_LONG_CALL_ u32 HalI2CReadRegRtl8195a(IN VOID *Data, IN u8 I2CReg); +_LONG_CALL_ HAL_Status HalI2CWriteRegRtl8195a(IN VOID *Data, IN u8 I2CReg, IN u32 RegVal); +_LONG_CALL_ HAL_Status HalI2CDMACtrl8195a(IN VOID *Data); + +//Rtl8195a I2C V02 function prototype +_LONG_CALL_ HAL_Status HalI2CSendRtl8195aV02(IN VOID *Data); +_LONG_CALL_ HAL_Status HalI2CSetCLKRtl8195aV02(IN VOID *Data); +//Rtl8195a I2C V02 function prototype END + +#endif diff --git a/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_i2s.h b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_i2s.h new file mode 100644 index 0000000..33a0bf8 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_i2s.h @@ -0,0 +1,617 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + + +#ifndef _RTL8195A_I2S_H_ +#define _RTL8195A_I2S_H_ + + +//=============== Register Bit Field Definition ==================== +// REG_I2S_CONTROL +#define BIT_CTLX_I2S_EN BIT(0) +#define BIT_SHIFT_CTLX_I2S_EN 0 +#define BIT_MASK_CTLX_I2S_EN 0x1 +#define BIT_CTRL_CTLX_I2S_EN(x) (((x) & BIT_MASK_CTLX_I2S_EN) << BIT_SHIFT_CTLX_I2S_EN) + +#define BIT_SHIFT_CTLX_I2S_TRX_ACT 1 +#define BIT_MASK_CTLX_I2S_TRX_ACT 0x3 +#define BIT_CTRL_CTLX_I2S_TRX_ACT(x) (((x) & BIT_MASK_CTLX_I2S_TRX_ACT) << BIT_SHIFT_CTLX_I2S_TRX_ACT) +#define BIT_GET_CTLX_I2S_TRX_ACT(x) (((x) >> BIT_SHIFT_CTLX_I2S_TRX_ACT) & BIT_MASK_CTLX_I2S_TRX_ACT) + +#define BIT_SHIFT_CTLX_I2S_CH_NUM 3 +#define BIT_MASK_CTLX_I2S_CH_NUM 0x3 +#define BIT_CTRL_CTLX_I2S_CH_NUM(x) (((x) & BIT_MASK_CTLX_I2S_CH_NUM) << BIT_SHIFT_CTLX_I2S_CH_NUM) +#define BIT_GET_CTLX_I2S_CH_NUM(x) (((x) >> BIT_SHIFT_CTLX_I2S_CH_NUM) & BIT_MASK_CTLX_I2S_CH_NUM) + +#define BIT_CTLX_I2S_WL BIT(6) +#define BIT_SHIFT_CTLX_I2S_WL 6 +#define BIT_MASK_CTLX_I2S_WL 0x1 +#define BIT_CTRL_CTLX_I2S_WL(x) (((x) & BIT_MASK_CTLX_I2S_WL) << BIT_SHIFT_CTLX_I2S_WL) + +#define BIT_CTLX_I2S_LRSWAP BIT(10) +#define BIT_SHIFT_CTLX_I2S_LRSWAP 10 +#define BIT_MASK_CTLX_I2S_LRSWAP 0x1 +#define BIT_CTRL_CTLX_I2S_LRSWAP(x) (((x) & BIT_MASK_CTLX_I2S_LRSWAP) << BIT_SHIFT_CTLX_I2S_LRSWAP) + +#define BIT_CTLX_I2S_SCK_INV BIT(11) +#define BIT_SHIFT_CTLX_I2S_SCK_INV 11 +#define BIT_MASK_CTLX_I2S_SCK_INV 0x1 +#define BIT_CTRL_CTLX_I2S_SCK_INV(x) (((x) & BIT_MASK_CTLX_I2S_SCK_INV) << BIT_SHIFT_CTLX_I2S_SCK_INV) + +#define BIT_CTLX_I2S_ENDIAN_SWAP BIT(12) +#define BIT_SHIFT_CTLX_I2S_ENDIAN_SWAP 12 +#define BIT_MASK_CTLX_I2S_ENDIAN_SWAP 0x1 +#define BIT_CTRL_CTLX_I2S_ENDIAN_SWAP(x) (((x) & BIT_MASK_CTLX_I2S_ENDIAN_SWAP) << BIT_SHIFT_CTLX_I2S_ENDIAN_SWAP) + +#define BIT_CTLX_I2S_SLAVE_MODE BIT(29) +#define BIT_SHIFT_CTLX_I2S_SLAVE_MODE 29 +#define BIT_MASK_CTLX_I2S_SLAVE_MODE 0x1 +#define BIT_CTRL_CTLX_I2S_SLAVE_MODE(x) (((x) & BIT_MASK_CTLX_I2S_SLAVE_MODE) << BIT_SHIFT_CTLX_I2S_SLAVE_MODE) + +#define BIT_CTLX_I2S_CLK_SRC BIT(30) +#define BIT_SHIFT_CTLX_I2S_CLK_SRC 30 +#define BIT_MASK_CTLX_I2S_CLK_SRC 0x1 +#define BIT_CTRL_CTLX_I2S_CLK_SRC(x) (((x) & BIT_MASK_CTLX_I2S_CLK_SRC) << BIT_SHIFT_CTLX_I2S_CLK_SRC) + +#define BIT_CTLX_I2S_SW_RSTN BIT(31) +#define BIT_SHIFT_CTLX_I2S_SW_RSTN 31 +#define BIT_MASK_CTLX_I2S_SW_RSTN 0x1 +#define BIT_CTRL_CTLX_I2S_SW_RSTN(x) (((x) & BIT_MASK_CTLX_I2S_SW_RSTN) << BIT_SHIFT_CTLX_I2S_SW_RSTN) + +// REG_I2S_SETTING +#define BIT_SHIFT_SETTING_I2S_PAGE_SZ 0 +#define BIT_MASK_SETTING_I2S_PAGE_SZ 0xFFF +#define BIT_CTRL_SETTING_I2S_PAGE_SZ(x) (((x) & BIT_MASK_SETTING_I2S_PAGE_SZ) << BIT_SHIFT_SETTING_I2S_PAGE_SZ) +#define BIT_GET_SETTING_I2S_PAGE_SZ(x) (((x) >> BIT_SHIFT_SETTING_I2S_PAGE_SZ) & BIT_MASK_SETTING_I2S_PAGE_SZ) + +#define BIT_SHIFT_SETTING_I2S_PAGE_NUM 12 +#define BIT_MASK_SETTING_I2S_PAGE_NUM 0x3 +#define BIT_CTRL_SETTING_I2S_PAGE_NUM(x) (((x) & BIT_MASK_SETTING_I2S_PAGE_NUM) << BIT_SHIFT_SETTING_I2S_PAGE_NUM) +#define BIT_GET_SETTING_I2S_PAGE_NUM(x) (((x) >> BIT_SHIFT_SETTING_I2S_PAGE_NUM) & BIT_MASK_SETTING_I2S_PAGE_NUM) + +#define BIT_SHIFT_SETTING_I2S_SAMPLE_RATE 14 +#define BIT_MASK_SETTING_I2S_SAMPLE_RATE 0x7 +#define BIT_CTRL_SETTING_I2S_SAMPLE_RATE(x) (((x) & BIT_MASK_SETTING_I2S_SAMPLE_RATE) << BIT_SHIFT_SETTING_I2S_SAMPLE_RATE) +#define BIT_GET_SETTING_I2S_SAMPLE_RATE(x) (((x) >> BIT_SHIFT_SETTING_I2S_SAMPLE_RATE) & BIT_MASK_SETTING_I2S_SAMPLE_RATE) + +// i2s trx page own bit +#define BIT_PAGE_I2S_OWN_BIT BIT(31) +#define BIT_SHIFT_PAGE_I2S_OWN_BIT 31 +#define BIT_MASK_PAGE_I2S_OWN_BIT 0x1 +#define BIT_CTRL_PAGE_I2S_OWN_BIT(x) (((x) & BIT_MASK_PAGE_I2S_OWN_BIT) << BIT_SHIFT_PAGE_I2S_OWN_BIT) + +//=============== Register Address Definition ==================== +#define REG_I2S_PAGE_OWN_OFF 0x004 + +#define REG_I2S_CTL 0x000 +#define REG_I2S_TX_PAGE_PTR 0x004 +#define REG_I2S_RX_PAGE_PTR 0x008 +#define REG_I2S_SETTING 0x00C + +#define REG_I2S_TX_MASK_INT 0x010 +#define REG_I2S_TX_STATUS_INT 0x014 +#define REG_I2S_RX_MASK_INT 0x018 +#define REG_I2S_RX_STATUS_INT 0x01c + + +#define REG_I2S_TX_PAGE0_OWN 0x020 +#define REG_I2S_TX_PAGE1_OWN 0x024 +#define REG_I2S_TX_PAGE2_OWN 0x028 +#define REG_I2S_TX_PAGE3_OWN 0x02C +#define REG_I2S_RX_PAGE0_OWN 0x030 +#define REG_I2S_RX_PAGE1_OWN 0x034 +#define REG_I2S_RX_PAGE2_OWN 0x038 +#define REG_I2S_RX_PAGE3_OWN 0x03C + +/*I2S Essential Functions and Macros*/ +VOID +HalI2SWrite32( + IN u8 I2SIdx, + IN u8 I2SReg, + IN u32 I2SVal +); + +u32 +HalI2SRead32( + IN u8 I2SIdx, + IN u8 I2SReg +); + +/* +#define HAL_I2SX_READ32(I2sIndex, addr) \ + HAL_READ32(I2S0_REG_BASE+ (I2sIndex*I2S1_REG_OFF), addr) +#define HAL_I2SX_WRITE32(I2sIndex, addr, value) \ + HAL_WRITE32((I2S0_REG_BASE+ (I2sIndex*I2S1_REG_OFF)), addr, value) +*/ + +#define HAL_I2S_WRITE32(I2SIdx, addr, value) HalI2SWrite32(I2SIdx,addr,value) +#define HAL_I2S_READ32(I2SIdx, addr) HalI2SRead32(I2SIdx,addr) + +/* I2S debug output*/ +#define I2S_PREFIX "RTL8195A[i2s]: " +#define I2S_PREFIX_LVL " [i2s_DBG]: " + +typedef enum _I2S_DBG_LVL_ { + HAL_I2S_LVL = 0x01, + SAL_I2S_LVL = 0x02, + VERI_I2S_LVL = 0x03, +}I2S_DBG_LVL,*PI2S_DBG_LVL; + +#ifdef CONFIG_DEBUG_LOG +#ifdef CONFIG_DEBUG_LOG_I2S_HAL + + #define DBG_8195A_I2S(...) do{ \ + _DbgDump("\r"I2S_PREFIX __VA_ARGS__);\ + }while(0) + + + #define I2SDBGLVL 0xFF + #define DBG_8195A_I2S_LVL(LVL,...) do{\ + if (LVL&I2SDBGLVL){\ + _DbgDump("\r"I2S_PREFIX_LVL __VA_ARGS__);\ + }\ + }while(0) +#else + #define DBG_I2S_LOG_PERD 100 + #define DBG_8195A_I2S(...) + #define DBG_8195A_I2S_LVL(...) +#endif +#else + #define DBG_I2S_LOG_PERD 100 + #define DBG_8195A_I2S(...) + #define DBG_8195A_I2S_LVL(...) +#endif + +/* +#define REG_I2S_PAGE_OWN_OFF 0x004 +#define REG_I2S_CTL 0x000 +#define REG_I2S_TX_PAGE_PTR 0x004 +#define REG_I2S_RX_PAGE_PTR 0x008 +#define REG_I2S_SETTING 0x00C + +#define REG_I2S_TX_MASK_INT 0x010 +#define REG_I2S_TX_STATUS_INT 0x014 +#define REG_I2S_RX_MASK_INT 0x018 +#define REG_I2S_RX_STATUS_INT 0x01c + + + +#define REG_I2S_TX_PAGE0_OWN 0x020 +#define REG_I2S_TX_PAGE1_OWN 0x024 +#define REG_I2S_TX_PAGE2_OWN 0x028 +#define REG_I2S_TX_PAGE3_OWN 0x02C +#define REG_I2S_RX_PAGE0_OWN 0x030 +#define REG_I2S_RX_PAGE1_OWN 0x034 +#define REG_I2S_RX_PAGE2_OWN 0x038 +#define REG_I2S_RX_PAGE3_OWN 0x03C +*/ +/* template +#define BIT_SHIFT_CTLX_ 7 +#define BIT_MASK_CTLX_ 0x1 +#define BIT_CTLX_(x) (((x) & BIT_MASK_CTLX_) << BIT_SHIFT_CTLX_) +#define BIT_INV_CTLX_ (~(BIT_MASK_CTLX_ << BIT_SHIFT_CTLX_)) +*//* +#define BIT_SHIFT_CTLX_IIS_EN 0 +#define BIT_MASK_CTLX_IIS_EN 0x1 +#define BIT_CTLX_IIS_EN(x) (((x) & BIT_MASK_CTLX_IIS_EN) << BIT_SHIFT_CTLX_IIS_EN) +#define BIT_INV_CTLX_IIS_EN (~(BIT_MASK_CTLX_IIS_EN << BIT_SHIFT_CTLX_IIS_EN)) + +#define BIT_SHIFT_CTLX_TRX 1 +#define BIT_MASK_CTLX_TRX 0x3 +#define BIT_CTLX_TRX(x) (((x) & BIT_MASK_CTLX_TRX) << BIT_SHIFT_CTLX_TRX) +#define BIT_INV_CTLX_TRX (~(BIT_MASK_CTLX_TRX << BIT_SHIFT_CTLX_TRX)) + +#define BIT_SHIFT_CTLX_CH_NUM 3 +#define BIT_MASK_CTLX_CH_NUM 0x3 +#define BIT_CTLX_CH_NUM(x) (((x) & BIT_MASK_CTLX_CH_NUM) << BIT_SHIFT_CTLX_CH_NUM) +#define BIT_INV_CTLX_CH_NUM (~(BIT_MASK_CTLX_CH_NUM << BIT_SHIFT_CTLX_CH_NUM)) + +#define BIT_SHIFT_CTLX_EDGE_SW 5 +#define BIT_MASK_CTLX_EDGE_SW 0x1 +#define BIT_CTLX_EDGE_SW(x) (((x) & BIT_MASK_CTLX_EDGE_SW) << BIT_SHIFT_CTLX_EDGE_SW) +#define BIT_INV_CTLX_EDGE_SW (~(BIT_MASK_CTLX_EDGE_SW << BIT_SHIFT_CTLX_EDGE_SW)) + +#define BIT_SHIFT_CTLX_WL 6 +#define BIT_MASK_CTLX_WL 0x1 +#define BIT_CTLX_WL(x) (((x) & BIT_MASK_CTLX_WL) << BIT_SHIFT_CTLX_WL) +#define BIT_INV_CTLX_WL (~(BIT_MASK_CTLX_WL << BIT_SHIFT_CTLX_WL)) + +#define BIT_SHIFT_CTLX_LOOP_BACK 7 +#define BIT_MASK_CTLX_LOOP_BACK 0x1 +#define BIT_CTLX_LOOP_BACK(x) (((x) & BIT_MASK_CTLX_LOOP_BACK) << BIT_SHIFT_CTLX_LOOP_BACK) +#define BIT_INV_CTLX_LOOP_BACK (~(BIT_MASK_CTLX_LOOP_BACK << BIT_SHIFT_CTLX_LOOP_BACK)) + + +#define BIT_SHIFT_CTLX_FORMAT 8 +#define BIT_MASK_CTLX_FORMAT 0x3 +#define BIT_CTLX_FORMAT(x) (((x) & BIT_MASK_CTLX_FORMAT) << BIT_SHIFT_CTLX_FORMAT) +#define BIT_INV_CTLX_FORMAT (~(BIT_MASK_CTLX_FORMAT << BIT_SHIFT_CTLX_FORMAT)) + +#define BIT_SHIFT_CTLX_LRSWAP 10 +#define BIT_MASK_CTLX_LRSWAP 0x1 +#define BIT_CTLX_LRSWAP(x) (((x) & BIT_MASK_CTLX_LRSWAP) << BIT_SHIFT_CTLX_LRSWAP) +#define BIT_INV_CTLX_LRSWAP (~(BIT_MASK_CTLX_LRSWAP << BIT_SHIFT_CTLX_LRSWAP)) + +#define BIT_SHIFT_CTLX_SCK_INV 11 +#define BIT_MASK_CTLX_SCK_INV 0x1 +#define BIT_CTLX_SCK_INV(x) (((x) & BIT_MASK_CTLX_SCK_INV) << BIT_SHIFT_CTLX_SCK_INV) +#define BIT_INV_CTLX_SCK_INV (~(BIT_MASK_CTLX_SCK_INV << BIT_SHIFT_CTLX_SCK_INV)) + +#define BIT_SHIFT_CTLX_ENDIAN_SWAP 12 +#define BIT_MASK_CTLX_ENDIAN_SWAP 0x1 +#define BIT_CTLX_ENDIAN_SWAP(x) (((x) & BIT_MASK_CTLX_ENDIAN_SWAP) << BIT_SHIFT_CTLX_ENDIAN_SWAP) +#define BIT_INV_CTLX_ENDIAN_SWAP (~(BIT_MASK_CTLX_ENDIAN_SWAP << BIT_SHIFT_CTLX_ENDIAN_SWAP)) + + +#define BIT_SHIFT_CTLX_DEBUG_SWITCH 15 +#define BIT_MASK_CTLX_DEBUG_SWITCH 0x3 +#define BIT_CTLX_DEBUG_SWITCH(x) (((x) & BIT_MASK_CTLX_DEBUG_SWITCH) << BIT_SHIFT_CTLX_DEBUG_SWITCH) +#define BIT_INV_CTLX_DEBUG_SWITCH (~(BIT_MASK_CTLX_DEBUG_SWITCH << BIT_SHIFT_CTLX_DEBUG_SWITCH)) + +#define BIT_SHIFT_CTLX_SLAVE_SEL 29 +#define BIT_MASK_CTLX_SLAVE_SEL 0x1 +#define BIT_CTLX_SLAVE_SEL(x) (((x) & BIT_MASK_CTLX_SLAVE_SEL) << BIT_SHIFT_CTLX_SLAVE_SEL) +#define BIT_INV_CTLX_SLAVE_SEL (~(BIT_MASK_CTLX_SLAVE_SEL << BIT_SHIFT_CTLX_SLAVE_SEL)) + + +#define BIT_SHIFT_CTLX_CLK_SRC 30 +#define BIT_MASK_CTLX_CLK_SRC 0x1 +#define BIT_CTLX_CLK_SRC(x) (((x) & BIT_MASK_CTLX_CLK_SRC) << BIT_SHIFT_CTLX_CLK_SRC) +#define BIT_INV_CTLX_CLK_SRC (~(BIT_MASK_CTLX_CLK_SRC << BIT_SHIFT_CTLX_CLK_SRC)) + + + +#define BIT_SHIFT_CTLX_SW_RSTN 31 +#define BIT_MASK_CTLX_SW_RSTN 0x1 +#define BIT_CTLX_SW_RSTN(x) (((x) & BIT_MASK_CTLX_SW_RSTN) << BIT_SHIFT_CTLX_SW_RSTN) +#define BIT_INV_CTLX_SW_RSTN (~(BIT_MASK_CTLX_SW_RSTN << BIT_SHIFT_CTLX_SW_RSTN)) + + +#define BIT_SHIFT_SETTING_PAGE_SZ 0 +#define BIT_MASK_SETTING_PAGE_SZ 0xFFF +#define BIT_SETTING_PAGE_SZ(x) (((x) & BIT_MASK_SETTING_PAGE_SZ) << BIT_SHIFT_SETTING_PAGE_SZ) +#define BIT_INV_SETTING_PAGE_SZ (~(BIT_MASK_SETTING_PAGE_SZ << BIT_SHIFT_SETTING_PAGE_SZ)) + +#define BIT_SHIFT_SETTING_PAGE_NUM 12 +#define BIT_MASK_SETTING_PAGE_NUM 0x3 +#define BIT_SETTING_PAGE_NUM(x) (((x) & BIT_MASK_SETTING_PAGE_NUM) << BIT_SHIFT_SETTING_PAGE_NUM) +#define BIT_INV_SETTING_PAGE_NUM (~(BIT_MASK_SETTING_PAGE_NUM << BIT_SHIFT_SETTING_PAGE_NUM)) + +#define BIT_SHIFT_SETTING_SAMPLE_RATE 14 +#define BIT_MASK_SETTING_SAMPLE_RATE 0x7 +#define BIT_SETTING_SAMPLE_RATE(x) (((x) & BIT_MASK_SETTING_SAMPLE_RATE) << BIT_SHIFT_SETTING_SAMPLE_RATE) +#define BIT_INV_SETTING_SAMPLE_RATE (~(BIT_MASK_SETTING_SAMPLE_RATE << BIT_SHIFT_SETTING_SAMPLE_RATE)) +*/ + +typedef enum _I2S_CTL_FORMAT { + FormatI2s = 0x00, + FormatLeftJustified = 0x01, + FormatRightJustified = 0x02 +}I2S_CTL_FORMAT, *PI2S_CTL_FORMAT; + +typedef enum _I2S_CTL_CHNUM { + ChannelStereo = 0x00, + Channel5p1 = 0x01, + ChannelMono = 0x02 +}I2S_CTL_CHNUM, *PI2S_CTL_CHNUM; + +typedef enum _I2S_CTL_TRX_ACT { + RxOnly = 0x00, + TxOnly = 0x01, + TXRX = 0x02 +}I2S_CTL_TRX_ACT, *PI2S_CTL_TRX_ACT; +/* +typedef struct _I2S_CTL_REG_ { + I2S_CTL_FORMAT Format; + I2S_CTL_CHNUM ChNum; + I2S_CTL_TRX_ACT TrxAct; + + u32 I2s_En :1; // Bit 0 + u32 Rsvd1to4 :4; // Bit 1-4 is TrxAct, ChNum + u32 EdgeSw :1; // Bit 5 Edge switch + u32 WordLength :1; // Bit 6 + u32 LoopBack :1; // Bit 7 + u32 Rsvd8to9 :2; // Bit 8-9 is Format + u32 DacLrSwap :1; // Bit 10 + u32 SckInv :1; // Bit 11 + u32 EndianSwap :1; // Bit 12 + u32 Rsvd13to14 :2; // Bit 11-14 + u32 DebugSwitch :2; // Bit 15-16 + u32 Rsvd17to28 :12; // Bit 17-28 + u32 SlaveMode :1; // Bit 29 + u32 SR44p1KHz :1; // Bit 30 + u32 SwRstn :1; // Bit 31 +} I2S_CTL_REG, *PI2S_CTL_REG; +*/ +typedef enum _I2S_SETTING_PAGE_NUM { + I2s1Page = 0x00, + I2s2Page = 0x01, + I2s3Page = 0x02, + I2s4Page = 0x03 +}I2S_SETTING_PAGE_NUM, *PI2S_SETTING_PAGE_NUM; + +//sampling rate +typedef enum _I2S_SETTING_SR { + I2sSR8K = 0x00, + I2sSR16K = 0x01, + I2sSR24K = 0x02, + I2sSR32K = 0x03, + I2sSR48K = 0x05, + I2sSR44p1K = 0x15, + I2sSR96K = 0x06, + I2sSR88p2K = 0x16 +}I2S_SETTING_SR, *PI2S_SETTING_SR; +/* +typedef struct _I2S_SETTING_REG_ { + I2S_SETTING_PAGE_NUM PageNum; + I2S_SETTING_SR SampleRate; + + u32 PageSize:12; // Bit 0-11 +}I2S_SETTING_REG, *PI2S_SETTING_REG; + +typedef enum _I2S_TX_ISR { + I2sTxP0OK = 0x01, + I2sTxP1OK = 0x02, + I2sTxP2OK = 0x04, + I2sTxP3OK = 0x08, + I2sTxPageUn = 0x10, + I2sTxFifoEmpty = 0x20 +}I2S_TX_ISR, *PI2S_TX_ISR; + +typedef enum _I2S_RX_ISR { + I2sRxP0OK = 0x01, + I2sRxP1OK = 0x02, + I2sRxP2OK = 0x04, + I2sRxP3OK = 0x08, + I2sRxPageUn = 0x10, + I2sRxFifoFull = 0x20 +}I2S_RX_ISR, *PI2S_RX_ISR; +*/ + +/* Hal I2S function prototype*/ +RTK_STATUS +HalI2SInitRtl8195a( + IN VOID *Data +); + +RTK_STATUS +HalI2SInitRtl8195a_Patch( + IN VOID *Data +); + +RTK_STATUS +HalI2SDeInitRtl8195a( + IN VOID *Data +); + +RTK_STATUS +HalI2STxRtl8195a( + IN VOID *Data, + IN u8 *pBuff +); + +RTK_STATUS +HalI2SRxRtl8195a( + IN VOID *Data, + OUT u8 *pBuff +); + +RTK_STATUS +HalI2SEnableRtl8195a( + IN VOID *Data +); + +RTK_STATUS +HalI2SIntrCtrlRtl8195a( + IN VOID *Data +); + +u32 +HalI2SReadRegRtl8195a( + IN VOID *Data, + IN u8 I2SReg +); + +RTK_STATUS +HalI2SSetRateRtl8195a( + IN VOID *Data +); + +RTK_STATUS +HalI2SSetWordLenRtl8195a( + IN VOID *Data +); + +RTK_STATUS +HalI2SSetChNumRtl8195a( + IN VOID *Data +); + +RTK_STATUS +HalI2SSetPageNumRtl8195a( + IN VOID *Data +); + +RTK_STATUS +HalI2SSetPageSizeRtl8195a( + IN VOID *Data +); + +RTK_STATUS +HalI2SSetDirectionRtl8195a( + IN VOID *Data +); + +RTK_STATUS +HalI2SSetDMABufRtl8195a( + IN VOID *Data +); + +RTK_STATUS +HalI2SClrIntrRtl8195a( + IN VOID *Data +); + +RTK_STATUS +HalI2SClrAllIntrRtl8195a( + IN VOID *Data +); + +RTK_STATUS +HalI2SDMACtrlRtl8195a( + IN VOID *Data +); + +u8 +HalI2SGetTxPageRtl8195a( + IN VOID *Data +); + +u8 +HalI2SGetRxPageRtl8195a( + IN VOID *Data +); + +RTK_STATUS +HalI2SPageSendRtl8195a( + IN VOID *Data, + IN u8 PageIdx +); + +#if 0 +RTK_STATUS +HalI2SPageRecvRtl8195a( + IN VOID *Data, + IN u8 PageIdx +); +#else +RTK_STATUS +HalI2SPageRecvRtl8195a( + IN VOID *Data +); +#endif + +RTK_STATUS +HalI2SClearAllOwnBitRtl8195a( + IN VOID *Data +); + + +// HAL functions Wrapper +static __inline VOID +HalI2SSetRate( + IN VOID *Data +) +{ + HalI2SSetRateRtl8195a(Data); +} + +static __inline VOID +HalI2SSetWordLen( + IN VOID *Data +) +{ + HalI2SSetWordLenRtl8195a(Data); +} + +static __inline VOID +HalI2SSetChNum( + IN VOID *Data +) +{ + HalI2SSetChNumRtl8195a(Data); +} + +static __inline VOID +HalI2SSetPageNum( + IN VOID *Data +) +{ + HalI2SSetPageNumRtl8195a(Data); +} + +static __inline VOID +HalI2SSetPageSize( + IN VOID *Data +) +{ + HalI2SSetPageSizeRtl8195a(Data); +} + +static __inline VOID +HalI2SSetDirection( + IN VOID *Data +) +{ + HalI2SSetDirectionRtl8195a(Data); +} + +static __inline VOID +HalI2SSetDMABuf( + IN VOID *Data +) +{ + HalI2SSetDMABufRtl8195a(Data); +} + +static __inline u8 +HalI2SGetTxPage( + IN VOID *Data +) +{ + return HalI2SGetTxPageRtl8195a(Data); +} + +static __inline u8 +HalI2SGetRxPage( + IN VOID *Data +) +{ + return HalI2SGetRxPageRtl8195a(Data); +} + +static __inline VOID +HalI2SPageSend( + IN VOID *Data, + IN u8 PageIdx +) +{ + HalI2SPageSendRtl8195a(Data, PageIdx); +} + +#if 0 +static __inline VOID +HalI2SPageRecv( + IN VOID *Data, + IN u8 PageIdx +) +{ + HalI2SPageRecvRtl8195a(Data, PageIdx); +} +#else +static __inline VOID +HalI2SPageRecv( + IN VOID *Data +) +{ + HalI2SPageRecvRtl8195a(Data); +} +#endif + +static __inline VOID +HalI2SClearAllOwnBit( + IN VOID *Data +) +{ + HalI2SClearAllOwnBitRtl8195a(Data); +} + +#endif /* _RTL8195A_I2S_H_ */ + + diff --git a/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_mii.h b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_mii.h new file mode 100644 index 0000000..56ebbdc --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_mii.h @@ -0,0 +1,674 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + + +#ifndef _RTL8195A_MII_H_ +#define _RTL8195A_MII_H_ + +#include "basic_types.h" +#include "hal_api.h" + + +#define ETHERNET_REG_BASE 0x40050000 +#define ETHERNET_MODULE_BASE ETHERNET_REG_BASE + 0x0000 +#define CPU_INTERFACE_BASE ETHERNET_REG_BASE + 0x1300 + +/* Ethernet Module registers */ +#define REG_RTL_MII_IDR0 0x0000 // Table 2 IDR0 (Offset 0000h-0003h, R/W) +#define REG_RTL_MII_IDR4 0x0004 // Table 3 IDR4 (Offset 0004h-0007h, R/W) +#define REG_RTL_MII_MAR0 0x0008 // Table 4 MAR0 (Offset 0008h-000bh, R/W) +#define REG_RTL_MII_MAR4 0x000C // Table 5 MAR4 (Offset 000ch-000fh, R/W) +#define REG_RTL_MII_CR 0x0038 // Table 21 Command Register (COM_REG, Offset 0038-003Bh, R/W) +#define REG_RTL_MII_IMRISR 0x003C // Table 22 + Table 23 +#define REG_RTL_MII_TCR 0x0040 // Table 24 Transmit Configuration Register (TC_REG, Offset 0040h-0043h, R/W) +#define REG_RTL_MII_RCR 0x0044 // Table 25 Receive Configuration Register (RC_REG, Offset 0044h-0047h, R/W) +#define REG_RTL_MII_CTCR 0x0048 // Table 26 CPU Tag Control Register (CPUTAG_REG, Offset 0048h-004bh, R/W) +#define REG_RTL_MII_CONFIG 0x004C // Table 27 Configuration Register (CONFIG_REG, Offset 004ch-004fh, R/W) +#define REG_RTL_MII_CTCR1 0x0050 // Table 28 CPUTAG1 Register (CPUTAG1_REG, Offset 0050h-0053h, R/W) +#define REG_RTL_MII_MSR 0x0058 // Table 29 Media Status Register (MS_reg: Offset 0058h – 005bh, R/W) +#define REG_RTL_MII_MIIAR 0x005C // Table 30 MII Access Register (MIIA_REG, Offset 005c-005fh, R/W) +#define REG_RTL_MII_VR 0x0064 // Table 32 VLAN Register (VLAN_REG, Offset 0064-0067h, R/W) +#define REG_RTL_MII_IMR0 0x00D0 // Table 50 IMR0_REG (IMR0_REG, Offset D0h-D3h) +#define REG_RTL_MII_IMR1 0x00D4 // Table 51 IMR1_REG (IMR1_REG, Offset d4h-d7h) +#define REG_RTL_MII_ISR1 0x00D8 // Table 52 ISR1 Register (ISR1_REG, Offset D8h-DBh) +#define REG_RTL_MII_INTR 0x00DC // Table 53 Interrupt routing register (INTR_REG, Offset DCh-DFh) +#define REG_RTL_MII_CCR 0x00E4 // Table xx Clock Control Register (CLKCTL_REG, Offset E4h-E7h) + +/* CPU Interface registers */ +#define REG_RTL_MII_TXFDP1 0x1300 // Table 55 TxFDP1 register (TXFDP1_REG, offset 1300h-1303h) +#define REG_RTL_MII_TXCDO1 0x1304 // Table 56 TxCDO1 register (TXCDO1_REG, offset 1304h-1305h) +#define REG_RTL_MII_TXFDP2 0x1310 // Table 57 TxFDP2 register (TXFDP2_REG, offset 1310h-1313h) +#define REG_RTL_MII_TXCDO2 0x1314 // Table 58 TxCDO2 register (TXCDO2_REG, offset 1314h-1315h) +#define REG_RTL_MII_TXFDP3 0x1320 // Table 59 TxFDP3 register (TXFDP3_REG, offset 1320h-1323h) +#define REG_RTL_MII_TXCDO3 0x1324 // Table 60 TxCDO3 register (TXCDO3_REG, offset 1324h-1325h) +#define REG_RTL_MII_TXFDP4 0x1330 // Table 61 TxFDP4 register (TXFDP4_REG, offset 1330h-1333h) +#define REG_RTL_MII_TXCDO4 0x1334 // Table 62 TxCDO4 register (TXCDO4_REG, offset 1334h-1335h) +#define REG_RTL_MII_TXFDP5 0x1340 // Table 63 TxFDP5 register (TXFDP5_REG, offset 1340h-1343h) +#define REG_RTL_MII_TXCDO5 0x1344 // Table 64 TxCDO5 register (TXCDO5_REG, offset 1344h-1345h) +#define REG_RTL_MII_RXFDP2 0x1390 // Table 66 RxFDP2 register (RXFDP#_REG, offset 1390h-1393h) +#define REG_RTL_MII_RXFDP1 0x13F0 // Table 71 RxFDP1 register (RXFDP1_REG, offset 13F0h-13F3h) +#define REG_RTL_MII_RXRS1 0x13F6 // Table 73 Rx Ring Size1 register (RX_RS1_REG, offset 13F6h-13F7h) + +#define REG_RTL_MII_RX_PSE1 0x142C // Table 77 Rx_Pse_Des_Thres_1_h (RX_PSE1_REG, Offset 142ch) +#define REG_RTL_MII_ETNRXCPU1 0x1430 // Table 79 EhtrntRxCPU_Des_Num1 (ETNRXCPU1_REG, Offset 1430h-1433h) +#define REG_RTL_MII_IOCMD 0x1434 // Table 80 Ethernet_IO_CMD (ETN_IO_CMD_REG, Offset 1434h-1437h) +#define REG_RTL_MII_IOCMD1 0x1438 // Table 81 Ethernet_IO_CMD1 (IO_CMD1_REG: Offset 1438h-143bh) + + +#define HAL_MII_READ32(addr) \ + HAL_READ32(ETHERNET_REG_BASE, addr) +#define HAL_MII_WRITE32(addr, value) \ + HAL_WRITE32(ETHERNET_REG_BASE, addr, value) +#define HAL_MII_READ16(addr) \ + HAL_READ16(ETHERNET_REG_BASE, addr) +#define HAL_MII_WRITE16(addr, value) \ + HAL_WRITE16(ETHERNET_REG_BASE, addr, value) +#define HAL_MII_READ8(addr) \ + HAL_READ8(ETHERNET_REG_BASE, addr) +#define HAL_MII_WRITE8(addr, value) \ + HAL_WRITE8(ETHERNET_REG_BASE, addr, value) + +#define CMD_CONFIG 0x00081000 + +//2014-04-29 yclin (disable [27] r_en_precise_dma) +// #define CMD1_CONFIG 0x39000000 +#define CMD1_CONFIG 0x31000000 + +// #define MAX_RX_DESC_SIZE 6 +#define MAX_RX_DESC_SIZE 1 +#define MAX_TX_DESC_SIZE 5 + +// 0058h +#define BIT_SHIFT_MSR_FORCE_SPEED_SELECT 16 +#define BIT_MASK_MSR_FORCE_SPEED_SELECT 0x3 +#define BIT_MSR_FORCE_SPEED_SELECT(x)(((x) & BIT_MASK_MSR_FORCE_SPEED_SELECT) << BIT_SHIFT_MSR_FORCE_SPEED_SELECT) +#define BIT_INVC_MSR_FORCE_SPEED_SELECT (~(BIT_MASK_MSR_FORCE_SPEED_SELECT << BIT_SHIFT_MSR_FORCE_SPEED_SELECT)) + +#define BIT_SHIFT_MSR_FORCE_SPEED_MODE_ENABLE 10 +#define BIT_MASK_MSR_FORCE_SPEED_MODE_ENABLE 0x1 +#define BIT_MSR_FORCE_SPEED_MODE_ENABLE(x)(((x) & BIT_MASK_MSR_FORCE_SPEED_MODE_ENABLE) << BIT_SHIFT_MSR_FORCE_SPEED_MODE_ENABLE) +#define BIT_INVC_MSR_FORCE_SPEED_MODE_ENABLE (~(BIT_MASK_MSR_FORCE_SPEED_MODE_ENABLE << BIT_SHIFT_MSR_FORCE_SPEED_MODE_ENABLE)) + +// 1434h +#define BIT_SHIFT_IOCMD_RXENABLE 5 +#define BIT_MASK_IOCMD_RXENABLE 0x1 +#define BIT_IOCMD_RXENABLE(x)(((x) & BIT_MASK_IOCMD_RXENABLE) << BIT_SHIFT_IOCMD_RXENABLE) +#define BIT_INVC_IOCMD_RXENABLE (~(BIT_MASK_IOCMD_RXENABLE << BIT_SHIFT_IOCMD_RXENABLE)) + +#define BIT_SHIFT_IOCMD_TXENABLE 4 +#define BIT_MASK_IOCMD_TXENABLE 0x1 +#define BIT_IOCMD_TXENABLE(x)(((x) & BIT_MASK_IOCMD_TXENABLE) << BIT_SHIFT_IOCMD_TXENABLE) +#define BIT_INVC_IOCMD_TXENABLE (~(BIT_MASK_IOCMD_TXENABLE << BIT_SHIFT_IOCMD_TXENABLE)) + +#define BIT_SHIFT_IOCMD_FIRST_DMATX_ENABLE 0 +#define BIT_MASK_IOCMD_FIRST_DMATX_ENABLE 0x1 +#define BIT_IOCMD_FIRST_DMATX_ENABLE(x)(((x) & BIT_MASK_IOCMD_FIRST_DMATX_ENABLE) << BIT_SHIFT_IOCMD_FIRST_DMATX_ENABLE) +#define BIT_INVC_IOCMD_FIRST_DMATX_ENABLE (~(BIT_MASK_IOCMD_FIRST_DMATX_ENABLE << BIT_SHIFT_IOCMD_FIRST_DMATX_ENABLE)) + +// 1438h +#define BIT_SHIFT_IOCMD1_FIRST_DMARX_ENABLE 16 +#define BIT_MASK_IOCMD1_FIRST_DMARX_ENABLE 0x1 +#define BIT_IOCMD1_FIRST_DMARX_ENABLE(x)(((x) & BIT_MASK_IOCMD1_FIRST_DMARX_ENABLE) << BIT_SHIFT_IOCMD1_FIRST_DMARX_ENABLE) +#define BIT_INVC_IOCMD1_FIRST_DMARX_ENABLE (~(BIT_MASK_IOCMD1_FIRST_DMARX_ENABLE << BIT_SHIFT_IOCMD1_FIRST_DMARX_ENABLE)) + + +/** + * 1.4.1.7 Tx command descriptor used in RL6266 + * 5 dobule words + */ +typedef struct _TX_INFO_ { + union { + struct { + u32 own:1; //31 + u32 eor:1; //30 + u32 fs:1; //29 + u32 ls:1; //28 + u32 ipcs:1; //27 + u32 l4cs:1; //26 + u32 keep:1; //25 + u32 blu:1; //24 + u32 crc:1; //23 + u32 vsel:1; //22 + u32 dislrn:1; //21 + u32 cputag_ipcs:1; //20 + u32 cputag_l4cs:1; //19 + u32 cputag_psel:1; //18 + u32 rsvd:1; //17 + u32 data_length:17; //0~16 + } bit; + u32 dw; //double word + } opts1; + + u32 addr; + + union { + struct { + u32 cputag:1; //31 + u32 aspri:1; //30 + u32 cputag_pri:3; //27~29 + u32 tx_vlan_action:2; //25~26 + u32 tx_pppoe_action:2; //23~24 + u32 tx_pppoe_idx:3; //20~22 + u32 efid:1; //19 + u32 enhance_fid:3; //16~18 + u32 vidl:8; // 8~15 + u32 prio:3; // 5~7 + u32 cfi:1; // 4 + u32 vidh:4; // 0~3 + } bit; + u32 dw; //double word + } opts2; + + union { + struct { + u32 extspa:3; //29~31 + u32 tx_portmask:6; //23~28 + u32 tx_dst_stream_id:7; //16~22 + u32 rsvd:14; // 2~15 + u32 l34keep:1; // 1 + u32 ptp:1; // 0 + } bit; + u32 dw; //double word + } opts3; + + union { + struct { + u32 lgsen:1; //31 + u32 lgmss:11; //20~30 + u32 rsvd:20; // 0~19 + } bit; + u32 dw; //double word + } opts4; + +} TX_INFO, *PTX_INFO; + +typedef struct _RX_INFO_ { + union{ + struct{ + u32 own:1; //31 + u32 eor:1; //30 + u32 fs:1; //29 + u32 ls:1; //28 + u32 crcerr:1; //27 + u32 ipv4csf:1; //26 + u32 l4csf:1; //25 + u32 rcdf:1; //24 + u32 ipfrag:1; //23 + u32 pppoetag:1; //22 + u32 rwt:1; //21 + u32 pkttype:4; //20-17 + u32 l3routing:1; //16 + u32 origformat:1; //15 + u32 pctrl:1; //14 +#ifdef CONFIG_RG_JUMBO_FRAME + u32 data_length:14; //13~0 +#else + u32 rsvd:2; //13~12 + u32 data_length:12; //11~0 +#endif + }bit; + u32 dw; //double word + }opts1; + + u32 addr; + + union{ + struct{ + u32 cputag:1; //31 + u32 ptp_in_cpu_tag_exist:1; //30 + u32 svlan_tag_exist:1; //29 + u32 rsvd_2:2; //27~28 + u32 pon_stream_id:7; //20~26 + u32 rsvd_1:3; //17~19 + u32 ctagva:1; //16 + u32 cvlan_tag:16; //15~0 + }bit; + u32 dw; //double word + }opts2; + + union{ + struct{ + u32 src_port_num:5; //27~31 + u32 dst_port_mask:6; //21~26 + u32 reason:8; //13~20 + u32 internal_priority:3; //10~12 + u32 ext_port_ttl_1:5; //5~9 + u32 rsvd:5; //4~0 + }bit; + u32 dw; //double word + }opts3; +} RX_INFO, *PRX_INFO; + +/** + * GMAC_STATUS_REGS + */ +// TX/RX Descriptor Common +#define BIT_SHIFT_GMAC_DESCOWN 31 +#define BIT_MASK_GMAC_DESCOWN 0x1 +#define BIT_GMAC_DESCOWN(x)(((x) & BIT_MASK_GMAC_DESCOWN) << BIT_SHIFT_GMAC_DESCOWN) +#define BIT_INVC_GMAC_DESCOWN (~(BIT_MASK_GMAC_DESCOWN << BIT_SHIFT_GMAC_DESCOWN)) + +#define BIT_SHIFT_GMAC_RINGEND 30 +#define BIT_MASK_GMAC_RINGEND 0x1 +#define BIT_GMAC_RINGEND(x)(((x) & BIT_MASK_GMAC_RINGEND) << BIT_SHIFT_GMAC_RINGEND) +#define BIT_INVC_GMAC_RINGEND (~(BIT_MASK_GMAC_RINGEND << BIT_SHIFT_GMAC_RINGEND)) + +#define BIT_SHIFT_GMAC_FIRSTFRAG 29 +#define BIT_MASK_GMAC_FIRSTFRAG 0x1 +#define BIT_GMAC_FIRSTFRAG(x)(((x) & BIT_MASK_GMAC_FIRSTFRAG) << BIT_SHIFT_GMAC_FIRSTFRAG) +#define BIT_INVC_GMAC_FIRSTFRAG (~(BIT_MASK_GMAC_FIRSTFRAG << BIT_SHIFT_GMAC_FIRSTFRAG)) + +#define BIT_SHIFT_GMAC_LASTFRAG 28 +#define BIT_MASK_GMAC_LASTFRAG 0x1 +#define BIT_GMAC_LASTFRAG(x)(((x) & BIT_MASK_GMAC_LASTFRAG) << BIT_SHIFT_GMAC_LASTFRAG) +#define BIT_INVC_GMAC_LASTFRAG (~(BIT_MASK_GMAC_LASTFRAG << BIT_SHIFT_GMAC_LASTFRAG)) + +// TX Descriptor opts1 +#define BIT_SHIFT_GMAC_IPCS 27 +#define BIT_MASK_GMAC_IPCS 0x1 +#define BIT_GMAC_IPCS(x)(((x) & BIT_MASK_GMAC_IPCS) << BIT_SHIFT_GMAC_IPCS) +#define BIT_INVC_GMAC_IPCS (~(BIT_MASK_GMAC_IPCS << BIT_SHIFT_GMAC_IPCS)) + +#define BIT_SHIFT_GMAC_L4CS 26 +#define BIT_MASK_GMAC_L4CS 0x1 +#define BIT_GMAC_L4CS(x)(((x) & BIT_MASK_GMAC_L4CS) << BIT_SHIFT_GMAC_L4CS) +#define BIT_INVC_GMAC_L4CS (~(BIT_MASK_GMAC_L4CS << BIT_SHIFT_GMAC_L4CS)) + +#define BIT_SHIFT_GMAC_KEEP 25 +#define BIT_MASK_GMAC_KEEP 0x1 +#define BIT_GMAC_KEEP(x)(((x) & BIT_MASK_GMAC_KEEP) << BIT_SHIFT_GMAC_KEEP) +#define BIT_INVC_GMAC_KEEP (~(BIT_MASK_GMAC_KEEP << BIT_SHIFT_GMAC_KEEP)) + +#define BIT_SHIFT_GMAC_BLU 24 +#define BIT_MASK_GMAC_BLU 0x1 +#define BIT_GMAC_BLU(x)(((x) & BIT_MASK_GMAC_BLU) << BIT_SHIFT_GMAC_BLU) +#define BIT_INVC_GMAC_BLU (~(BIT_MASK_GMAC_BLU << BIT_SHIFT_GMAC_BLU)) + +#define BIT_SHIFT_GMAC_TXCRC 23 +#define BIT_MASK_GMAC_TXCRC 0x1 +#define BIT_GMAC_TXCRC(x)(((x) & BIT_MASK_GMAC_TXCRC) << BIT_SHIFT_GMAC_TXCRC) +#define BIT_INVC_GMAC_TXCRC (~(BIT_MASK_GMAC_TXCRC << BIT_SHIFT_GMAC_TXCRC)) + +#define BIT_SHIFT_GMAC_VSEL 22 +#define BIT_MASK_GMAC_VSEL 0x1 +#define BIT_GMAC_VSEL(x)(((x) & BIT_MASK_GMAC_VSEL) << BIT_SHIFT_GMAC_VSEL) +#define BIT_INVC_GMAC_VSEL (~(BIT_MASK_GMAC_VSEL << BIT_SHIFT_GMAC_VSEL)) + +#define BIT_SHIFT_GMAC_DISLRN 21 +#define BIT_MASK_GMAC_DISLRN 0x1 +#define BIT_GMAC_DISLRN(x)(((x) & BIT_MASK_GMAC_DISLRN) << BIT_SHIFT_GMAC_DISLRN) +#define BIT_INVC_GMAC_DISLRN (~(BIT_MASK_GMAC_DISLRN << BIT_SHIFT_GMAC_DISLRN)) + +#define BIT_SHIFT_GMAC_CPUTAG_IPCS 20 +#define BIT_MASK_GMAC_CPUTAG_IPCS 0x1 +#define BIT_GMAC_CPUTAG_IPCS(x)(((x) & BIT_MASK_GMAC_CPUTAG_IPCS) << BIT_SHIFT_GMAC_CPUTAG_IPCS) +#define BIT_INVC_GMAC_CPUTAG_IPCS (~(BIT_MASK_GMAC_CPUTAG_IPCS << BIT_SHIFT_GMAC_CPUTAG_IPCS)) + +#define BIT_SHIFT_GMAC_CPUTAG_L4CS 19 +#define BIT_MASK_GMAC_CPUTAG_L4CS 0x1 +#define BIT_GMAC_CPUTAG_L4CS(x)(((x) & BIT_MASK_GMAC_CPUTAG_L4CS) << BIT_SHIFT_GMAC_CPUTAG_L4CS) +#define BIT_INVC_GMAC_CPUTAG_L4CS (~(BIT_MASK_GMAC_CPUTAG_L4CS << BIT_SHIFT_GMAC_CPUTAG_L4CS)) + +#define BIT_SHIFT_GMAC_CPUTAG_PSEL 18 +#define BIT_MASK_GMAC_CPUTAG_PSEL 0x1 +#define BIT_GMAC_CPUTAG_PSEL(x)(((x) & BIT_MASK_GMAC_CPUTAG_PSEL) << BIT_SHIFT_GMAC_CPUTAG_PSEL) +#define BIT_INVC_GMAC_CPUTAG_PSEL (~(BIT_MASK_GMAC_CPUTAG_PSEL << BIT_SHIFT_GMAC_CPUTAG_PSEL)) + + +#if 0 +enum RE8670_STATUS_REGS +{ + /*TX/RX share */ + DescOwn = (1 << 31), /* Descriptor is owned by NIC */ + RingEnd = (1 << 30), /* End of descriptor ring */ + FirstFrag = (1 << 29), /* First segment of a packet */ + LastFrag = (1 << 28), /* Final segment of a packet */ + + /*Tx descriptor opt1*/ + IPCS = (1 << 27), + L4CS = (1 << 26), + KEEP = (1 << 25), + BLU = (1 << 24), + TxCRC = (1 << 23), + VSEL = (1 << 22), + DisLrn = (1 << 21), + CPUTag_ipcs = (1 << 20), + CPUTag_l4cs = (1 << 19), + + /*Tx descriptor opt2*/ + CPUTag = (1 << 31), + aspri = (1 << 30), + CPRI = (1 << 27), + TxVLAN_int = (0 << 25), //intact + TxVLAN_ins = (1 << 25), //insert + TxVLAN_rm = (2 << 25), //remove + TxVLAN_re = (3 << 25), //remark + //TxPPPoEAct = (1 << 23), + TxPPPoEAct = 23, + //TxPPPoEIdx = (1 << 20), + TxPPPoEIdx = 20, + Efid = (1 << 19), + //Enhan_Fid = (1 << 16), + Enhan_Fid = 16, + /*Tx descriptor opt3*/ + SrcExtPort = 29, + TxDesPortM = 23, + TxDesStrID = 16, + TxDesVCM = 0, + /*Tx descriptor opt4*/ + /*Rx descriptor opt1*/ + CRCErr = (1 << 27), + IPV4CSF = (1 << 26), + L4CSF = (1 << 25), + RCDF = (1 << 24), + IP_FRAG = (1 << 23), + PPPoE_tag = (1 << 22), + RWT = (1 << 21), + PktType = (1 << 17), + RxProtoIP = 1, + RxProtoPPTP = 2, + RxProtoICMP = 3, + RxProtoIGMP = 4, + RxProtoTCP = 5, + RxProtoUDP = 6, + RxProtoIPv6 = 7, + RxProtoICMPv6 = 8, + RxProtoTCPv6 = 9, + RxProtoUDPv6 = 10, + L3route = (1 << 16), + OrigFormat = (1 << 15), + PCTRL = (1 << 14), + /*Rx descriptor opt2*/ + PTPinCPU = (1 << 30), + SVlanTag = (1 << 29), + /*Rx descriptor opt3*/ + SrcPort = (1 << 27), + DesPortM = (1 << 21), + Reason = (1 << 13), + IntPriority = (1 << 10), + ExtPortTTL = (1 << 5), +}; + +enum _DescStatusBit { + DescOwn = (1 << 31), /* Descriptor is owned by NIC */ + RingEnd = (1 << 30), /* End of descriptor ring */ + FirstFrag = (1 << 29), /* First segment of a packet */ + LastFrag = (1 << 28), /* Final segment of a packet */ + + /* Tx private */ + LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */ + MSSShift = 16, /* MSS value position */ + MSSMask = 0xfff, /* MSS value + LargeSend bit: 12 bits */ + IPCS = (1 << 18), /* Calculate IP checksum */ + UDPCS = (1 << 17), /* Calculate UDP/IP checksum */ + TCPCS = (1 << 16), /* Calculate TCP/IP checksum */ + TxVlanTag = (1 << 17), /* Add VLAN tag */ + + /* Rx private */ + PID1 = (1 << 18), /* Protocol ID bit 1/2 */ + PID0 = (1 << 17), /* Protocol ID bit 2/2 */ + +#define RxProtoUDP (PID1) +#define RxProtoTCP (PID0) +#define RxProtoIP (PID1 | PID0) +#define RxProtoMask RxProtoIP + + IPFail = (1 << 16), /* IP checksum failed */ + UDPFail = (1 << 15), /* UDP/IP checksum failed */ + TCPFail = (1 << 14), /* TCP/IP checksum failed */ + RxVlanTag = (1 << 16), /* VLAN tag available */ +}; +#endif + +typedef struct _PHY_MODE_INFO_ { + u8 PhyAddress; + u8 PhyMode; + u8 PhyInterface; +} PHY_MODE_INFO, *PPHY_MODE_INFO; + +typedef enum _PHY_MODE_SWITCH_ { + PHY_MODE_DISABLE = 0, + PHY_MODE_ENABLE = 1 +} PHY_MODE_SWITCH, *PPHY_MODE_SWITCH; + +typedef enum _PHY_INTERFACE_SELECT_ { + PHY_INTERFACE_ONE_WORKS = 0, + PHY_INTERFACE_ZERO_WORKS = 1 +} PHY_INTERFACE_SELECT, *PPHY_INTERFACE_SELECT; + +typedef enum _GMAC_MSR_FORCE_SPEED_ { + FORCE_SPD_100M = 0, + FORCE_SPD_10M = 1, + FORCE_SPD_GIGA = 2, + NO_FORCE_SPD = 3 +}GMAC_MSR_FORCE_SPEED, *PGMAC_MSR_FORCE_SPEED; + +// typedef enum _GMAC_INTERRUPT_MASK_ { +// GMAC_IMR_ROK = BIT0, +// GMAC_IMR_CNT_WRAP = BIT1, +// GMAC_IMR_RER_RUNT = BIT2, +// // BIT3 Reserved +// GMAC_IMR_RER_OVF = BIT4, +// GMAC_IMR_RDU = BIT5, +// GMAC_IMR_TOK_TI = BIT6, +// GMAC_IMR_TER = BIT7, +// GMAC_IMR_LINKCHG = BIT8, +// GMAC_IMR_TDU = BIT9, +// GMAC_IMR_SWINT = BIT10, +// GMAC_IMR_RDU2 = BIT11, +// GMAC_IMR_RDU3 = BIT12, +// GMAC_IMR_RDU4 = BIT13, +// GMAC_IMR_RDU5 = BIT14, +// GMAC_IMR_RDU6 = BIT15, +// } GMAC_INTERRUPT_MASK, *PGMAC_INTERRUPT_MASK; + +typedef enum _GMAC_INTERRUPT_MASK_ { + GMAC_IMR_ROK = BIT16, + GMAC_IMR_CNT_WRAP = BIT17, + GMAC_IMR_RER_RUNT = BIT18, + // BIT19 Reserved + GMAC_IMR_RER_OVF = BIT20, + GMAC_IMR_RDU = BIT21, + GMAC_IMR_TOK_TI = BIT22, + GMAC_IMR_TER = BIT23, + GMAC_IMR_LINKCHG = BIT24, + GMAC_IMR_TDU = BIT25, + GMAC_IMR_SWINT = BIT26, + GMAC_IMR_RDU2 = BIT27, + GMAC_IMR_RDU3 = BIT28, + GMAC_IMR_RDU4 = BIT29, + GMAC_IMR_RDU5 = BIT30, + GMAC_IMR_RDU6 = BIT31, +} GMAC_INTERRUPT_MASK, *PGMAC_INTERRUPT_MASK; + +typedef enum _GMAC_INTERRUPT_STATUS_ { + GMAC_ISR_ROK = BIT0, + GMAC_ISR_CNT_WRAP = BIT1, + GMAC_ISR_RER_RUNT = BIT2, + // BIT3 Reserved + GMAC_ISR_RER_OVF = BIT4, + GMAC_ISR_RDU = BIT5, + GMAC_ISR_TOK_TI = BIT6, + GMAC_ISR_TER = BIT7, + GMAC_ISR_LINKCHG = BIT8, + GMAC_ISR_TDU = BIT9, + GMAC_ISR_SWINT = BIT10, + GMAC_ISR_RDU2 = BIT11, + GMAC_ISR_RDU3 = BIT12, + GMAC_ISR_RDU4 = BIT13, + GMAC_ISR_RDU5 = BIT14, + GMAC_ISR_RDU6 = BIT15, +} GMAC_INTERRUPT_STATUS, *PGMAC_INTERRUPT_STATUS; + +typedef enum _GMAC_TX_VLAN_ACTION_ { + INTACT = 0, + INSERT_VLAN_HDR = 1, + REMOVE_VLAN_HDR = 2, + REMARKING_VID = 3 +}GMAC_TX_VLAN_ACTION, *PGMAC_TX_VLAN_ACTION; + +typedef enum _GMAC_RX_PACKET_TYPE_ { + TYPE_ETHERNET = 0, + TYPE_IPV4 = 1, + TYPE_IPV4_PPTP = 2, + TYPE_IPV4_ICMP = 3, + TYPE_IPV4_IGMP = 4, + TYPE_IPV4_TCP = 5, + TYPE_IPV4_UDP = 6, + TYPE_IPV6 = 7, + TYPE_ICMPV6 = 8, + TYPE_IPV6_TCP = 9, + TYPE_IPV6_UDP = 10 +}GMAC_RX_PACKET_TYPE, *PGMAC_RX_PACKET_TYPE; + + +/* + +// Memory Map of DW_apb_ssi +#define REG_DW_SSI_CTRLR0 0x00 // 16 bits +#define REG_DW_SSI_CTRLR1 0x04 // 16 bits +#define REG_DW_SSI_SSIENR 0x08 // 1 bit +#define REG_DW_SSI_RX_SAMPLE_DLY 0xF0 // 8 bits +#define REG_DW_SSI_RSVD_0 0xF4 // 32 bits +#define REG_DW_SSI_RSVD_1 0xF8 // 32 bits +#define REG_DW_SSI_RSVD_2 0xFC // 32 bits + +// CTRLR0 0x00 // 16 bits, 6.2.1 +// DFS Reset Value: 0x7 +#define BIT_SHIFT_CTRLR0_DFS 0 +#define BIT_MASK_CTRLR0_DFS 0xF +#define BIT_CTRLR0_DFS(x)(((x) & BIT_MASK_CTRLR0_DFS) << BIT_SHIFT_CTRLR0_DFS) +#define BIT_INVC_CTRLR0_DFS (~(BIT_MASK_CTRLR0_DFS << BIT_SHIFT_CTRLR0_DFS)) + +#define BIT_SHIFT_CTRLR0_FRF 4 +#define BIT_MASK_CTRLR0_FRF 0x3 +#define BIT_CTRLR0_FRF(x)(((x) & BIT_MASK_CTRLR0_FRF) << BIT_SHIFT_CTRLR0_FRF) +#define BIT_INVC_CTRLR0_FRF (~(BIT_MASK_CTRLR0_FRF << BIT_SHIFT_CTRLR0_FRF)) + +#define BIT_SHIFT_CTRLR0_SCPH 6 +#define BIT_MASK_CTRLR0_SCPH 0x1 +#define BIT_CTRLR0_SCPH(x)(((x) & BIT_MASK_CTRLR0_SCPH) << BIT_SHIFT_CTRLR0_SCPH) +#define BIT_INVC_CTRLR0_SCPH (~(BIT_MASK_CTRLR0_SCPH << BIT_SHIFT_CTRLR0_SCPH)) + +// CTRLR1 0x04 // 16 bits +#define BIT_SHIFT_CTRLR1_NDF 0 +#define BIT_MASK_CTRLR1_NDF 0xFFFF +#define BIT_CTRLR1_NDF(x)(((x) & BIT_MASK_CTRLR1_NDF) << BIT_SHIFT_CTRLR1_NDF) +#define BIT_INVC_CTRLR1_NDF (~(BIT_MASK_CTRLR1_NDF << BIT_SHIFT_CTRLR1_NDF)) + +// TXFLTR 0x18 // Variable Length +#define BIT_SHIFT_TXFTLR_TFT 0 +#define BIT_MASK_TXFTLR_TFT 0x3F // (TX_ABW-1):0 +#define BIT_TXFTLR_TFT(x)(((x) & BIT_MASK_TXFTLR_TFT) << BIT_SHIFT_TXFTLR_TFT) +#define BIT_INVC_TXFTLR_TFT (~(BIT_MASK_TXFTLR_TFT << BIT_SHIFT_TXFTLR_TFT)) + +// TXFLR 0x20 // see [READ ONLY] +#define BIT_MASK_TXFLR_TXTFL 0x7F // (TX_ABW):0 + +// RXFLR 0x24 // see [READ ONLY] +#define BIT_MASK_RXFLR_RXTFL 0x7F // (RX_ABW):0 + +// SR 0x28 // 7 bits [READ ONLY] +#define BIT_SR_BUSY BIT0 +#define BIT_SR_TFNF BIT1 +#define BIT_SR_TFE BIT2 +#define BIT_SR_RFNE BIT3 +#define BIT_SR_RFF BIT4 +#define BIT_SR_TXE BIT5 +#define BIT_SR_DCOL BIT6 + +#define BIT_IMR_TXEIM BIT0 +#define BIT_IMR_TXOIM BIT1 +#define BIT_IMR_RXUIM BIT2 +#define BIT_IMR_RXOIM BIT3 +#define BIT_IMR_RXFIM BIT4 +#define BIT_IMR_MSTIM BIT5 + +// ISR 0x30 // 6 bits [READ ONLY] +#define BIT_ISR_TXEIS BIT0 +#define BIT_ISR_TXOIS BIT1 +#define BIT_ISR_RXUIS BIT2 +#define BIT_ISR_RXOIS BIT3 +#define BIT_ISR_RXFIS BIT4 +#define BIT_ISR_MSTIS BIT5 + +*/ + +BOOL +HalMiiGmacInitRtl8195a( + IN VOID *Data + ); + +BOOL +HalMiiInitRtl8195a( + IN VOID *Data + ); + +BOOL +HalMiiGmacResetRtl8195a( + IN VOID *Data + ); + +BOOL +HalMiiGmacEnablePhyModeRtl8195a( + IN VOID *Data + ); + +u32 +HalMiiGmacXmitRtl8195a( + IN VOID *Data + ); + +VOID +HalMiiGmacCleanTxRingRtl8195a( + IN VOID *Data + ); + +VOID +HalMiiGmacFillTxInfoRtl8195a( + IN VOID *Data + ); + +VOID +HalMiiGmacFillRxInfoRtl8195a( + IN VOID *Data + ); + +VOID +HalMiiGmacTxRtl8195a( + IN VOID *Data + ); + +VOID +HalMiiGmacRxRtl8195a( + IN VOID *Data + ); + +VOID +HalMiiGmacSetDefaultEthIoCmdRtl8195a( + IN VOID *Data + ); + +VOID +HalMiiGmacInitIrqRtl8195a( + IN VOID *Data + ); + +u32 +HalMiiGmacGetInterruptStatusRtl8195a( + VOID + ); + +VOID +HalMiiGmacClearInterruptStatusRtl8195a( + u32 IsrStatus + ); + +#endif + diff --git a/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_nfc.h b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_nfc.h new file mode 100644 index 0000000..257454e --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_nfc.h @@ -0,0 +1,153 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + + +#ifndef _RTL8195A_NFC_H_ +#define _RTL8195A_NFC_H_ + +#include "hal_api.h" +#include "osdep_api.h" +#ifdef CONFIG_NFC_VERIFY +#include "../test/nfc/rtl8195a_nfc_test.h" +#endif + +#if CONFIG_NFC_NORMAL +//===================== Register Bit Field Definition ===================== +// TODO: +//===================== Register Address Definition ===================== +//TODO: +#include "osdep_api.h" +#define N2A_Q_LENGTH 10 +#define N2ARLENGTH 4 +//#define NFCTAGLENGTH 36 // maximum 36*4=144 bytes +#define NFCTAG_BASE 0x7F000 +#define NFCTAG_PAGESIZE 256 +#define NFCTAG_MAXPAGEIDX 16//(4*(1024/NFCTAG_PAGESIZE)) +#define A2NWCLENGTH 4 + +#define FLASHAPPLENGTH 31 +#define FLASHAPP_BASE 0x7E000 +#define FLASH_PAGESIZE 128 +#define FLASH_MAXPAGEIDX 32//(4*(1024/FLASH_PAGESIZE)) + +typedef struct _A2N_CATCH_W_ { + //u8 Vaild; + u8 A2NCatchRPage; + u32 A2NCatchWData[A2NWCLENGTH]; +}A2N_CATCH_W_QUEUE, *PA2N_CATCH_W_QUEUE; + +typedef struct _A2N_MAILBOX_Q_ { + u8 Length; + u8 Response; + u32 Content[A2NWCLENGTH+1]; +}A2N_MAILBOX_Q,*PA2N_MAILBOX_Q; + +typedef struct _N2A_CATCH_R_ { + u8 Vaild; + u8 N2ACatchRPage; + u32 N2ACatchRData[N2ARLENGTH]; +}N2A_CATCH_R_QUEUE, *PN2A_CATCH_R_QUEUE; + + +typedef struct _N2A_R_ { + u8 Vaild; + u8 N2ARPage; +}N2A_R_QUEUE, *PN2A_R_QUEUE; + +typedef struct _N2A_W_ { + u8 Vaild; + u8 N2AWPage; + u32 N2AWData; +}N2A_W_QUEUE, *PN2A_W_QUEUE; + +typedef struct _NFC_ADAPTER_ { + u8 Function; + u32 NFCIsr; + u8 N2ABoxOpen; + u8 A2NSeq; + //u8 NFCTagFlashWIdx; + //u8 NFCTagFlashRIdx; +// u32 NFCTag[NFCTAGLENGTH]; +#if !TASK_SCHEDULER_DISABLED + _Sema VeriSema; +#else + u32 VeriSema; +#endif +#ifdef PLATFORM_FREERTOS + xTaskHandle NFCTask; +#else + u32 NFCTask; +#endif +#ifdef CONFIG_NFC_VERIFY + //N2A Write Tag + u8 N2AWQRIdx; + u8 N2AWQWIdx; + N2A_W_QUEUE N2AWQ[N2A_Q_LENGTH]; + //N2A Read Tag + u8 N2ARQRIdx; + u8 N2ARQWIdx; + N2A_R_QUEUE N2ARQ[N2A_Q_LENGTH]; + //N2A Read Catch + u8 N2ARCRIdx; + u8 N2ARCWIdx; + N2A_CATCH_R_QUEUE N2ACatchR[N2A_Q_LENGTH]; +#endif + //A2N Write Catch + //u8 A2NWCRIdx; + //u8 A2NWCWIdx; + //A2N_CATCH_W_QUEUE A2NCatchW[N2A_Q_LENGTH]; + + //A2N Write mailbox queue + u8 A2NWMailBox; + u8 A2NWQRIdx; + u8 A2NWQWIdx; + A2N_MAILBOX_Q A2NMAILQ[N2A_Q_LENGTH]; + + u8 TaskStop; + void *nfc_obj; +}NFC_ADAPTER, *PNFC_ADAPTER; + +typedef enum _N2A_CMD_ { + TAG_READ = 0, + TAG_WRITE = 1, + CATCH_READ_DATA = 2, + NFC_R_PRESENT = 4, + N2A_MAILBOX_STATE = 5, + EXT_CLK_REQ = 6, + MAX_N2ACMD +}; + +typedef enum _A2N_CMD_ { + TAG_READ_DATA = 0, + CATCH_READ = 2, + CATCH_WRITE = 3, + A2N_MAILBOX_STATE = 4, + CONFIRM_N2A_BOX_STATE = 5, + EXT_CLK_RSP = 6, + MAX_A2NCMD +}; + +// Callback event defination +typedef enum _NFC_HAL_EVENT_ { + NFC_HAL_READER_PRESENT = (1<<0), + NFC_HAL_READ = (1<<1), + NFC_HAL_WRITE = (1<<2), + NFC_HAL_ERR = (1<<3), + NFC_HAL_CACHE_RD = (1<<4) +}NFC_CB_EVENT, *PNFC_CB_EVENT; + +VOID A2NWriteCatch(IN VOID *pNFCAdapte, IN u8 N2AWPage, + IN u8 Length, IN u32 *WData); +VOID A2NReadCatch(IN VOID *pNFCAdapte, IN u8 A2NRPage); +VOID HalNFCDmemInit(IN u32 *pTagData, IN u32 TagLen); +VOID HalNFCInit(PNFC_ADAPTER pNFCAdp); +VOID HalNFCDeinit(PNFC_ADAPTER pNFCAdp); +VOID HalNFCFwDownload(VOID); +#endif //CONFIG_NFC_NORMAL +#endif diff --git a/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_pcm.h b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_pcm.h new file mode 100644 index 0000000..c2bd793 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_pcm.h @@ -0,0 +1,449 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + + +#ifndef _RTL8195A_PCM_H_ +#define _RTL8195A_PCM_H_ + +#include "basic_types.h" +#include "hal_api.h" + +#define HAL_PCMX_READ32(PcmIndex, addr) \ + HAL_READ32(PCM0_REG_BASE+ (PcmIndex*PCM1_REG_OFF), addr) +#define HAL_PCMX_WRITE32(PcmIndex, addr, value) \ + HAL_WRITE32((PCM0_REG_BASE+ (PcmIndex*PCM1_REG_OFF)), addr, value) + +#define REG_PCM_TRXBSA_OFF 0x004 +#define REG_PCM_CTL 0x000 +#define REG_PCM_CHCNR03 0x004 +#define REG_PCM_TSR03 0x008 +#define REG_PCM_BSIZE03 0x00C + +#define REG_PCM_CH0TXBSA 0x010 +#define REG_PCM_CH1TXBSA 0x014 +#define REG_PCM_CH2TXBSA 0x018 +#define REG_PCM_CH3TXBSA 0x01c +#define REG_PCM_CH0RXBSA 0x020 +#define REG_PCM_CH1RXBSA 0x024 +#define REG_PCM_CH2RXBSA 0x028 +#define REG_PCM_CH3RXBSA 0x02c + +#define REG_PCM_IMR03 0x030 +#define REG_PCM_ISR03 0x034 + +#define REG_PCM_CHCNR47 0x038 +#define REG_PCM_TSR47 0x03c +#define REG_PCM_BSIZE47 0x040 +#define REG_PCM_CH4TXBSA 0x044 +#define REG_PCM_CH5TXBSA 0x048 +#define REG_PCM_CH6TXBSA 0x04c +#define REG_PCM_CH7TXBSA 0x050 +#define REG_PCM_CH4RXBSA 0x054 +#define REG_PCM_CH5RXBSA 0x058 +#define REG_PCM_CH6RXBSA 0x05c +#define REG_PCM_CH7RXBSA 0x060 + +#define REG_PCM_IMR47 0x064 +#define REG_PCM_ISR47 0x068 + +#define REG_PCM_CHCNR811 0x06c +#define REG_PCM_TSR811 0x070 +#define REG_PCM_BSIZE811 0x074 +#define REG_PCM_CH8TXBSA 0x078 +#define REG_PCM_CH9TXBSA 0x07c +#define REG_PCM_CH10TXBSA 0x080 +#define REG_PCM_CH11TXBSA 0x084 +#define REG_PCM_CH8RXBSA 0x088 +#define REG_PCM_CH9RXBSA 0x08c +#define REG_PCM_CH10RXBSA 0x090 +#define REG_PCM_CH11RXBSA 0x094 + +#define REG_PCM_IMR811 0x098 +#define REG_PCM_ISR811 0x09c + +#define REG_PCM_CHCNR1215 0x0a0 +#define REG_PCM_TSR1215 0x0a4 +#define REG_PCM_BSIZE1215 0x0a8 +#define REG_PCM_CH12TXBSA 0x0ac +#define REG_PCM_CH13TXBSA 0x0b0 +#define REG_PCM_CH14TXBSA 0x0b4 +#define REG_PCM_CH15TXBSA 0x0b8 +#define REG_PCM_CH12RXBSA 0x0bc +#define REG_PCM_CH13RXBSA 0x0c0 +#define REG_PCM_CH14RXBSA 0x0c4 +#define REG_PCM_CH15RXBSA 0x0c8 + +#define REG_PCM_IMR1215 0x0cc +#define REG_PCM_ISR1215 0x0d0 + +#define REG_PCM_INTMAP 0x0d4 +#define REG_PCM_WTSR03 0x0d8 +#define REG_PCM_WTSR47 0x0dc + +#define REG_PCM_RX_BUFOW 0x0e0 + +/* template +#define BIT_SHIFT_CTLX_ 7 +#define BIT_MASK_CTLX_ 0x1 +#define BIT_CTLX_(x) (((x) & BIT_MASK_CTLX_) << BIT_SHIFT_CTLX_) +#define BIT_INV_CTLX_ (~(BIT_MASK_CTLX_ << BIT_SHIFT_CTLX_)) +*/ +#define BIT_SHIFT_CTLX_SLAVE_SEL 8 +#define BIT_MASK_CTLX_SLAVE_SEL 0x1 +#define BIT_CTLX_SLAVE_SEL(x) (((x) & BIT_MASK_CTLX_SLAVE_SEL) << BIT_SHIFT_CTLX_SLAVE_SEL) +#define BIT_INV_CTLX_SLAVE_SEL (~(BIT_MASK_CTLX_SLAVE_SEL << BIT_SHIFT_CTLX_SLAVE_SEL)) + +#define BIT_SHIFT_CTLX_FSINV 9 +#define BIT_MASK_CTLX_FSINV 0x1 +#define BIT_CTLX_FSINV(x) (((x) & BIT_MASK_CTLX_FSINV) << BIT_SHIFT_CTLX_FSINV) +#define BIT_INV_CTLX_FSINV (~(BIT_MASK_CTLX_FSINV << BIT_SHIFT_CTLX_FSINV)) + +#define BIT_SHIFT_CTLX_PCM_EN 12 +#define BIT_MASK_CTLX_PCM_EN 0x1 +#define BIT_CTLX_PCM_EN(x) (((x) & BIT_MASK_CTLX_PCM_EN) << BIT_SHIFT_CTLX_PCM_EN) +#define BIT_INV_CTLX_PCM_EN (~(BIT_MASK_CTLX_PCM_EN << BIT_SHIFT_CTLX_PCM_EN)) + +#define BIT_SHIFT_CTLX_LINEARMODE 13 +#define BIT_MASK_CTLX_LINEARMODE 0x1 +#define BIT_CTLX_LINEARMODE(x) (((x) & BIT_MASK_CTLX_LINEARMODE) << BIT_SHIFT_CTLX_LINEARMODE) +#define BIT_INV_CTLX_LINEARMODE (~(BIT_MASK_CTLX_LINEARMODE << BIT_SHIFT_CTLX_LINEARMODE)) + +#define BIT_SHIFT_CTLX_LOOP_BACK 14 +#define BIT_MASK_CTLX_LOOP_BACK 0x1 +#define BIT_CTLX_LOOP_BACK(x) (((x) & BIT_MASK_CTLX_LOOP_BACK) << BIT_SHIFT_CTLX_LOOP_BACK) +#define BIT_INV_CTLX_LOOP_BACK (~(BIT_MASK_CTLX_LOOP_BACK << BIT_SHIFT_CTLX_LOOP_BACK)) + +#define BIT_SHIFT_CTLX_ENDIAN_SWAP 17 +#define BIT_MASK_CTLX_ENDIAN_SWAP 0x1 +#define BIT_CTLX_ENDIAN_SWAP(x) (((x) & BIT_MASK_CTLX_ENDIAN_SWAP) << BIT_SHIFT_CTLX_ENDIAN_SWAP) +#define BIT_INV_CTLX_ENDIAN_SWAP (~(BIT_MASK_CTLX_ENDIAN_SWAP << BIT_SHIFT_CTLX_ENDIAN_SWAP)) + +#define BIT_SHIFT_CHCNR03_CH0RE 24 +#define BIT_MASK_CHCNR03_CH0RE 0x1 +#define BIT_CHCNR03_CH0RE(x) (((x) & BIT_MASK_CHCNR03_CH0RE) << BIT_SHIFT_CHCNR03_CH0RE) +#define BIT_INV_CHCNR03_CH0RE (~(BIT_MASK_CHCNR03_CH0RE << BIT_SHIFT_CHCNR03_CH0RE)) + +#define BIT_SHIFT_CHCNR03_CH0TE 25 +#define BIT_MASK_CHCNR03_CH0TE 0x1 +#define BIT_CHCNR03_CH0TE(x) (((x) & BIT_MASK_CHCNR03_CH0TE) << BIT_SHIFT_CHCNR03_CH0TE) +#define BIT_INV_CHCNR03_CH0TE (~(BIT_MASK_CHCNR03_CH0TE << BIT_SHIFT_CHCNR03_CH0TE)) + +#define BIT_SHIFT_CHCNR03_CH1RE 16 +#define BIT_MASK_CHCNR03_CH1RE 0x1 +#define BIT_CHCNR03_CH1RE(x) (((x) & BIT_MASK_CHCNR03_CH1RE) << BIT_SHIFT_CHCNR03_CH1RE) +#define BIT_INV_CHCNR03_CH1RE (~(BIT_MASK_CHCNR03_CH1RE << BIT_SHIFT_CHCNR03_CH1RE)) + +#define BIT_SHIFT_CHCNR03_CH1TE 17 +#define BIT_MASK_CHCNR03_CH1TE 0x1 +#define BIT_CHCNR03_CH1TE(x) (((x) & BIT_MASK_CHCNR03_CH1TE) << BIT_SHIFT_CHCNR03_CH1TE) +#define BIT_INV_CHCNR03_CH1TE (~(BIT_MASK_CHCNR03_CH1TE << BIT_SHIFT_CHCNR03_CH1TE)) + +#define BIT_SHIFT_CHCNR03_CH2RE 8 +#define BIT_MASK_CHCNR03_CH2RE 0x1 +#define BIT_CHCNR03_CH2RE(x) (((x) & BIT_MASK_CHCNR03_CH2RE) << BIT_SHIFT_CHCNR03_CH2RE) +#define BIT_INV_CHCNR03_CH2RE (~(BIT_MASK_CHCNR03_CH2RE << BIT_SHIFT_CHCNR03_CH2RE)) + +#define BIT_SHIFT_CHCNR03_CH2TE 9 +#define BIT_MASK_CHCNR03_CH2TE 0x1 +#define BIT_CHCNR03_CH2TE(x) (((x) & BIT_MASK_CHCNR03_CH2TE) << BIT_SHIFT_CHCNR03_CH2TE) +#define BIT_INV_CHCNR03_CH2TE (~(BIT_MASK_CHCNR03_CH2TE << BIT_SHIFT_CHCNR03_CH2TE)) + +#define BIT_SHIFT_CHCNR03_CH3RE 0 +#define BIT_MASK_CHCNR03_CH3RE 0x1 +#define BIT_CHCNR03_CH3RE(x) (((x) & BIT_MASK_CHCNR03_CH3RE) << BIT_SHIFT_CHCNR03_CH3RE) +#define BIT_INV_CHCNR03_CH3RE (~(BIT_MASK_CHCNR03_CH3RE << BIT_SHIFT_CHCNR03_CH3RE)) + +#define BIT_SHIFT_CHCNR03_CH3TE 1 +#define BIT_MASK_CHCNR03_CH3TE 0x1 +#define BIT_CHCNR03_CH3TE(x) (((x) & BIT_MASK_CHCNR03_CH3TE) << BIT_SHIFT_CHCNR03_CH3TE) +#define BIT_INV_CHCNR03_CH3TE (~(BIT_MASK_CHCNR03_CH3TE << BIT_SHIFT_CHCNR03_CH3TE)) + +#define BIT_SHIFT_CHCNR03_CH0MUA 26 +#define BIT_MASK_CHCNR03_CH0MUA 0x1 +#define BIT_CHCNR03_CH0MUA(x) (((x) & BIT_MASK_CHCNR03_CH0MUA) << BIT_SHIFT_CHCNR03_CH0MUA) +#define BIT_INV_CHCNR03_CH0MUA (~(BIT_MASK_CHCNR03_CH0MUA << BIT_SHIFT_CHCNR03_CH0MUA)) + +#define BIT_SHIFT_CHCNR03_CH0BAND 27 +#define BIT_MASK_CHCNR03_CH0BAND 0x1 +#define BIT_CHCNR03_CH0BAND(x) (((x) & BIT_MASK_CHCNR03_CH0BAND) << BIT_SHIFT_CHCNR03_CH0BAND) +#define BIT_INV_CHCNR03_CH0BAND (~(BIT_MASK_CHCNR03_CH0BAND << BIT_SHIFT_CHCNR03_CH0BAND)) + +#define BIT_SHIFT_TSR03_CH0TSA 24 +#define BIT_MASK_TSR03_CH0TSA 0x1F +#define BIT_TSR03_CH0TSA(x) (((x) & BIT_MASK_TSR03_CH0TSA) << BIT_SHIFT_TSR03_CH0TSA) +#define BIT_INV_TSR03_CH0TSA (~(BIT_MASK_TSR03_CH0TSA << BIT_SHIFT_TSR03_CH0TSA)) + +#define BIT_SHIFT_BSIZE03_CH0BSIZE 24 +#define BIT_MASK_BSIZE03_CH0BSIZE 0xFF +#define BIT_BSIZE03_CH0BSIZE(x) (((x) & BIT_MASK_BSIZE03_CH0BSIZE) << BIT_SHIFT_BSIZE03_CH0BSIZE) +#define BIT_INV_BSIZE03_CH0BSIZE (~(BIT_MASK_BSIZE03_CH0BSIZE << BIT_SHIFT_BSIZE03_CH0BSIZE)) + +typedef struct _PCM_CTL_REG_ { + u32 FCNT :8; // Bit 0-7 + u32 SlaveMode :1; // Bit 8 + u32 FsInv :1; // Bit 9 + u32 Rsvd10to11 :1; // Bit 10-11 + u32 Pcm_En :1; // Bit 12 + u32 LinearMode :1; // Bit 13 + u32 LoopBack :1; // Bit 14 + u32 Rsvd15to16 :2; // Bit 15-16 + u32 EndianSwap :1; // Bit 17 + u32 Rsvd18to31 :14; // Bit 18-31 +} PCM_CTL_REG, *PPCM_CTL_REG; + + + +typedef struct _PCM_CHCNR03_REG_ { + u32 CH3RE :1; // Bit 0 + u32 CH3TE :1; // Bit 1 + u32 CH3MuA :1; // Bit 2 + u32 CH3Band :1; // Bit 3 + u32 CH3SlicSel:4; // Bit 4-7 + u32 CH2RE :1; // Bit 8 + u32 CH2TE :1; // Bit 9 + u32 CH2MuA :1; // Bit 10 + u32 CH2Band :1; // Bit 11 + u32 CH2SlicSel:4; // Bit 12-15 + u32 CH1RE :1; // Bit 16 + u32 CH1TE :1; // Bit 17 + u32 CH1MuA :1; // Bit 18 + u32 CH1Band :1; // Bit 19 + u32 CH1SlicSel:4; // Bit 20-23 + u32 CH0RE :1; // Bit 24 + u32 CH0TE :1; // Bit 25 + u32 CH0MuA :1; // Bit 26 + u32 CH0Band :1; // Bit 27 + u32 CH0SlicSel:4; // Bit 28-31 +}PCM_CHCNR03_REG, *PPCM_CHCNR03_REG; + +typedef struct _PCM_TSR03_REG_ { + u32 CH3TSA :5; // Bit 0-4 + u32 Rsvd5to7 :3; // Bit 5-7 + u32 CH2TSA :5; // Bit 8-12 + u32 Rsvd13to15:3; // Bit 13-15 + u32 CH1TSA :5; // Bit 16-20 + u32 Rsvd21to23:3; // Bit 21-23 + u32 CH0TSA :5; // Bit 24-28 + u32 Rsvd29to31:3; // Bit 29-31 +}PCM_TSR03_REG, *PPCM_TSR03_REG; + +typedef struct _PCM_BSIZE03_REG_ { + u32 CH3BSize :8; // Bit 0-7 + u32 CH2BSize :8; // Bit 8-15 + u32 CH1BSize :8; // Bit 16-23 + u32 CH0BSize :8; // Bit 24-31 +}PCM_BSIZE03_REG, *PPCM_BSIZE03_REG; + +typedef struct _PCM_ISR03_REG_ { + u32 CH3RXP1UA :1; // Bit 0 + u32 CH3RXP0UA :1; // Bit 1 + u32 CH3TXP1UA :1; // Bit 2 + u32 CH3TXP0UA :1; // Bit 3 + u32 CH3RXP1IP :1; // Bit 4 + u32 CH3RXP0IP :1; // Bit 5 + u32 CH3TXP1IP :1; // Bit 6 + u32 CH3TXP0IP :1; // Bit 7 + u32 CH2RXP1UA :1; // Bit 8 + u32 CH2RXP0UA :1; // Bit 9 + u32 CH2TXP1UA :1; // Bit 10 + u32 CH2TXP0UA :1; // Bit 11 + u32 CH2RXP1IP :1; // Bit 12 + u32 CH2RXP0IP :1; // Bit 13 + u32 CH2TXP1IP :1; // Bit 14 + u32 CH2TXP0IP :1; // Bit 15 + u32 CH1RXP1UA :1; // Bit 16 + u32 CH1RXP0UA :1; // Bit 17 + u32 CH1TXP1UA :1; // Bit 18 + u32 CH1TXP0UA :1; // Bit 19 + u32 CH1RXP1IP :1; // Bit 20 + u32 CH1RXP0IP :1; // Bit 21 + u32 CH1TXP1IP :1; // Bit 22 + u32 CH1TXP0IP :1; // Bit 23 + u32 CH0RXP1UA :1; // Bit 24 + u32 CH0RXP0UA :1; // Bit 25 + u32 CH0TXP1UA :1; // Bit 26 + u32 CH0TXP0UA :1; // Bit 27 + u32 CH0RXP1IP :1; // Bit 28 + u32 CH0RXP0IP :1; // Bit 29 + u32 CH0TXP1IP :1; // Bit 30 + u32 CH0TXP0IP :1; // Bit 31 +}PCM_ISR03_REG, *PPCM_ISR03_REG; + +typedef enum _PCM_ISR015 { + PcmCh3P1RBU = 0x00000001, //ch0-3 + PcmCh3P0RBU = 0x00000002, + PcmCh3P1TBU = 0x00000004, + PcmCh3P0TBU = 0x00000008, + PcmCh3P1ROK = 0x00000010, + PcmCh3P0ROK = 0x00000020, + PcmCh3P1TOK = 0x00000040, + PcmCh3P0TOK = 0x00000080, + PcmCh2P1RBU = 0x00000100, + PcmCh2P0RBU = 0x00000200, + PcmCh2P1TBU = 0x00000400, + PcmCh2P0TBU = 0x00000800, + PcmCh2P1ROK = 0x00001000, + PcmCh2P0ROK = 0x00002000, + PcmCh2P1TOK = 0x00004000, + PcmCh2P0TOK = 0x00008000, + PcmCh1P1RBU = 0x00010000, + PcmCh1P0RBU = 0x00020000, + PcmCh1P1TBU = 0x00040000, + PcmCh1P0TBU = 0x00080000, + PcmCh1P1ROK = 0x00100000, + PcmCh1P0ROK = 0x00200000, + PcmCh1P1TOK = 0x00400000, + PcmCh1P0TOK = 0x00800000, + PcmCh0P1RBU = 0x01000000, + PcmCh0P0RBU = 0x02000000, + PcmCh0P1TBU = 0x04000000, + PcmCh0P0TBU = 0x08000000, + PcmCh0P1ROK = 0x10000000, + PcmCh0P0ROK = 0x20000000, + PcmCh0P1TOK = 0x40000000, + PcmCh0P0TOK = 0x80000000, + + PcmCh7P1RBU = 0x00000001, //ch4-7 + PcmCh7P0RBU = 0x00000002, + PcmCh7P1TBU = 0x00000004, + PcmCh7P0TBU = 0x00000008, + PcmCh7P1ROK = 0x00000010, + PcmCh7P0ROK = 0x00000020, + PcmCh7P1TOK = 0x00000040, + PcmCh7P0TOK = 0x00000080, + PcmCh6P1RBU = 0x00000100, + PcmCh6P0RBU = 0x00000200, + PcmCh6P1TBU = 0x00000400, + PcmCh6P0TBU = 0x00000800, + PcmCh6P1ROK = 0x00001000, + PcmCh6P0ROK = 0x00002000, + PcmCh6P1TOK = 0x00004000, + PcmCh6P0TOK = 0x00008000, + PcmCh5P1RBU = 0x00010000, + PcmCh5P0RBU = 0x00020000, + PcmCh5P1TBU = 0x00040000, + PcmCh5P0TBU = 0x00080000, + PcmCh5P1ROK = 0x00100000, + PcmCh5P0ROK = 0x00200000, + PcmCh5P1TOK = 0x00400000, + PcmCh5P0TOK = 0x00800000, + PcmCh4P1RBU = 0x01000000, + PcmCh4P0RBU = 0x02000000, + PcmCh4P1TBU = 0x04000000, + PcmCh4P0TBU = 0x08000000, + PcmCh4P1ROK = 0x10000000, + PcmCh4P0ROK = 0x20000000, + PcmCh4P1TOK = 0x40000000, + PcmCh4P0TOK = 0x80000000, + + PcmCh11P1RBU = 0x00000001, //ch8-11 + PcmCh11P0RBU = 0x00000002, + PcmCh11P1TBU = 0x00000004, + PcmCh11P0TBU = 0x00000008, + PcmCh11P1ROK = 0x00000010, + PcmCh11P0ROK = 0x00000020, + PcmCh11P1TOK = 0x00000040, + PcmCh11P0TOK = 0x00000080, + PcmCh10P1RBU = 0x00000100, + PcmCh10P0RBU = 0x00000200, + PcmCh10P1TBU = 0x00000400, + PcmCh10P0TBU = 0x00000800, + PcmCh10P1ROK = 0x00001000, + PcmCh10P0ROK = 0x00002000, + PcmCh10P1TOK = 0x00004000, + PcmCh10P0TOK = 0x00008000, + PcmCh9P1RBU = 0x00010000, + PcmCh9P0RBU = 0x00020000, + PcmCh9P1TBU = 0x00040000, + PcmCh9P0TBU = 0x00080000, + PcmCh9P1ROK = 0x00100000, + PcmCh9P0ROK = 0x00200000, + PcmCh9P1TOK = 0x00400000, + PcmCh9P0TOK = 0x00800000, + PcmCh8P1RBU = 0x01000000, + PcmCh8P0RBU = 0x02000000, + PcmCh8P1TBU = 0x04000000, + PcmCh8P0TBU = 0x08000000, + PcmCh8P1ROK = 0x10000000, + PcmCh8P0ROK = 0x20000000, + PcmCh8P1TOK = 0x40000000, + PcmCh8P0TOK = 0x80000000, + + PcmCh15P1RBU = 0x00000001, //ch12-15 + PcmCh15P0RBU = 0x00000002, + PcmCh15P1TBU = 0x00000004, + PcmCh15P0TBU = 0x00000008, + PcmCh15P1ROK = 0x00000010, + PcmCh15P0ROK = 0x00000020, + PcmCh15P1TOK = 0x00000040, + PcmCh15P0TOK = 0x00000080, + PcmCh14P1RBU = 0x00000100, + PcmCh14P0RBU = 0x00000200, + PcmCh14P1TBU = 0x00000400, + PcmCh14P0TBU = 0x00000800, + PcmCh14P1ROK = 0x00001000, + PcmCh14P0ROK = 0x00002000, + PcmCh14P1TOK = 0x00004000, + PcmCh14P0TOK = 0x00008000, + PcmCh13P1RBU = 0x00010000, + PcmCh13P0RBU = 0x00020000, + PcmCh13P1TBU = 0x00040000, + PcmCh13P0TBU = 0x00080000, + PcmCh13P1ROK = 0x00100000, + PcmCh13P0ROK = 0x00200000, + PcmCh13P1TOK = 0x00400000, + PcmCh13P0TOK = 0x00800000, + PcmCh12P1RBU = 0x01000000, + PcmCh12P0RBU = 0x02000000, + PcmCh12P1TBU = 0x04000000, + PcmCh12P0TBU = 0x08000000, + PcmCh12P1ROK = 0x10000000, + PcmCh12P0ROK = 0x20000000, + PcmCh12P1TOK = 0x40000000, + PcmCh12P0TOK = 0x80000000 +}PCM_ISR015, *PPCM_ISR015; + +VOID +HalPcmOnOffRtl8195a( + IN VOID *Data +); + +BOOL +HalPcmInitRtl8195a( + IN VOID *Data +); + +BOOL +HalPcmSettingRtl8195a( + IN VOID *Data +); + +BOOL +HalPcmEnRtl8195a( + IN VOID *Data +); + +BOOL +HalPcmIsrEnAndDisRtl8195a( + IN VOID *Data +); + +BOOL +HalPcmDumpRegRtl8195a( + IN VOID *Data +); + +BOOL +HalPcmRtl8195a( + IN VOID *Data +); + +#endif /* _RTL8195A_PCM_H_ */ + + diff --git a/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_peri_on.h b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_peri_on.h new file mode 100644 index 0000000..da99b98 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_peri_on.h @@ -0,0 +1,1251 @@ +#ifndef __INC_RTL8195A_PERI_ON_H +#define __INC_RTL8195A_PERI_ON_H + +#define CPU_OPT_WIDTH 0x1F + +//2 REG_NOT_VALID + +//2 REG_PEON_PWR_CTRL +#define BIT_SOC_UAHV_EN BIT(2) +#define BIT_SOC_UALV_EN BIT(1) +#define BIT_SOC_USBD_EN BIT(0) + +//2 REG_PON_ISO_CTRL + +//2 REG_NOT_VALID +#define BIT_ISO_OSC32K_EN BIT(4) +//#define BIT_ISO_USBA_EN BIT(1) +//#define BIT_ISO_USBD_EN BIT(0) + +//2 REG_RSVD + +//2 REG_RSVD + +//2 REG_NOT_VALID + +//2 REG_SOC_FUNC_EN +#define BIT_SOC_SECURITY_ENGINE_EN BIT(20) +#define BIT_SOC_GTIMER_EN BIT(16) +#define BIT_SOC_GDMA1_EN BIT(14) +#define BIT_SOC_GDMA0_EN BIT(13) +#define BIT_SOC_LOG_UART_EN BIT(12) +#define BIT_SOC_CPU_EN BIT(8) +#define BIT_SOC_MEM_CTRL_EN BIT(6) +#define BIT_SOC_FLASH_EN BIT(4) +#define BIT_SOC_LXBUS_EN BIT(2) +#define BIT_SOC_OCP_EN BIT(1) +#define BiT_SOC_FUN_EN BIT(0) + +//2 REG_SOC_HCI_COM_FUNC_EN +#define BIT_SOC_HCI_WL_MACON_EN BIT(16) +#define BIT_SOC_HCI_SM_SEL BIT(13) +#define BIT_SOC_HCI_MII_EN BIT(12) +#define BIT_SOC_HCI_OTG_RST_MUX BIT(5) +#define BIT_SOC_HCI_OTG_EN BIT(4) +#define BIT_SOC_HCI_SDIOD_ON_RST_MUX BIT(3) +#define BIT_SOC_HCI_SDIOH_EN BIT(2) +#define BIT_SOC_HCI_SDIOD_OFF_EN BIT(1) +#define BIT_SOC_HCI_SDIOD_ON_EN BIT(0) + +//2 REG_SOC_PERI_FUNC0_EN +#define BIT_PERI_PCM1_EN BIT(29) +#define BIT_PERI_PCM0_EN BIT(28) +#define BIT_PERI_I2S1_EN BIT(25) +#define BIT_PERI_I2S0_EN BIT(24) +#define BIT_PERI_I2C3_EN BIT(19) +#define BIT_PERI_I2C2_EN BIT(18) +#define BIT_PERI_I2C1_EN BIT(17) +#define BIT_PERI_I2C0_EN BIT(16) +#define BIT_PERI_SPI2_EN BIT(10) +#define BIT_PERI_SPI1_EN BIT(9) +#define BIT_PERI_SPI0_EN BIT(8) +#define BIT_PERI_UART2_EN BIT(2) +#define BIT_PERI_UART1_EN BIT(1) +#define BIT_PERI_UART0_EN BIT(0) + +//2 REG_SOC_PERI_FUNC1_EN +#define BIT_PERI_GPIO_EN BIT(8) +#define BIT_PERI_DAC1_EN BIT(5) +#define BIT_PERI_DAC0_EN BIT(4) +#define BIT_PERI_ADC0_EN BIT(0) + +//2 REG_SOC_PERI_BD_FUNC0_EN +#define BIT_PERI_UART2_BD_EN BIT(2) +#define BIT_PERI_UART1_BD_EN BIT(1) +#define BIT_PERI_UART0_BD_EN BIT(0) + +//2 REG_RSVD + +//2 REG_RSVD + +//2 REG_NOT_VALID + +//2 REG_RSVD + +//2 REG_PESOC_CLK_CTRL +#define BIT_SOC_SLPCK_BTCMD_EN BIT(29) +#define BIT_SOC_ACTCK_BTCMD_EN BIT(28) +#define BIT_SOC_SLPCK_GPIO_EN BIT(25) +#define BIT_SOC_ACTCK_GPIO_EN BIT(24) +#define BIT_SOC_SLPCK_GDMA1_EN BIT(19) +#define BIT_SOC_ACTCK_GDMA1_EN BIT(18) +#define BIT_SOC_SLPCK_GDMA0_EN BIT(17) +#define BIT_SOC_ACTCK_GDMA0_EN BIT(16) +#define BIT_SOC_SLPCK_TIMER_EN BIT(15) +#define BIT_SOC_ACTCK_TIMER_EN BIT(14) +#define BIT_SOC_SLPCK_LOG_UART_EN BIT(13) +#define BIT_SOC_ACTCK_LOG_UART_EN BIT(12) +#define BIT_SOC_SLPCK_SDR_EN BIT(11) +#define BIT_SOC_ACTCK_SDR_EN BIT(10) +#define BIT_SOC_SLPCK_FLASH_EN BIT(9) +#define BIT_SOC_ACTCK_FLASH_EN BIT(8) +#define BIT_SOC_SLPCK_VENDOR_REG_EN BIT(7) +#define BIT_SOC_ACTCK_VENDOR_REG_EN BIT(6) +#define BIT_SOC_SLPCK_TRACE_EN BIT(5) +#define BIT_SOC_ACTCK_TRACE_EN BIT(4) +#define BIT_SOC_CKE_PLFM BIT(2) +#define BIT_SOC_CKE_OCP BIT(0) + +//2 REG_PESOC_PERI_CLK_CTRL0 +#define BIT_SOC_SLPCK_SPI2_EN BIT(21) +#define BIT_SOC_ACTCK_SPI2_EN BIT(20) +#define BIT_SOC_SLPCK_SPI1_EN BIT(19) +#define BIT_SOC_ACTCK_SPI1_EN BIT(18) +#define BIT_SOC_SLPCK_SPI0_EN BIT(17) +#define BIT_SOC_ACTCK_SPI0_EN BIT(16) +#define BIT_SOC_SLPCK_UART2_EN BIT(5) +#define BIT_SOC_ACTCK_UART2_EN BIT(4) +#define BIT_SOC_SLPCK_UART1_EN BIT(3) +#define BIT_SOC_ACTCK_UART1_EN BIT(2) +#define BIT_SOC_SLPCK_UART0_EN BIT(1) +#define BIT_SOC_ACTCK_UART0_EN BIT(0) + +//2 REG_PESOC_PERI_CLK_CTRL1 +#define BIT_SOC_SLPCK_DAC_EN BIT(29) +#define BIT_SOC_ACTCK_DAC_EN BIT(28) +#define BIT_SOC_SLPCK_ADC_EN BIT(25) +#define BIT_SOC_ACTCK_ADC_EN BIT(24) +#define BIT_SOC_SLPCK_PCM_EN BIT(21) +#define BIT_SOC_ACTCK_PCM_EN BIT(20) +#define BIT_SOC_SLPCK_I2S_EN BIT(17) +#define BIT_SOC_ACTCK_I2S_EN BIT(16) +#define BIT_SOC_SLPCK_I2C3_EN BIT(7) +#define BIT_SOC_ACTCK_I2C3_EN BIT(6) +#define BIT_SOC_SLPCK_I2C2_EN BIT(5) +#define BIT_SOC_ACTCK_I2C2_EN BIT(4) +#define BIT_SOC_SLPCK_I2C1_EN BIT(3) +#define BIT_SOC_ACTCK_I2C1_EN BIT(2) +#define BIT_SOC_SLPCK_I2C0_EN BIT(1) +#define BIT_SOC_ACTCK_I2C0_EN BIT(0) + +//2 REG_PESOC_CLK_CTRL3 + +//2 REG_PESOC_HCI_CLK_CTRL0 +#define BIT_SOC_SLPCK_MII_MPHY_EN BIT(25) +#define BIT_SOC_ACTCK_MII_MPHY_EN BIT(24) +#define BIT_SOC_SLPCK_OTG_EN BIT(5) +#define BIT_SOC_ACTCK_OTG_EN BIT(4) +#define BIT_SOC_SLPCK_SDIO_HST_EN BIT(3) +#define BIT_SOC_ACTCK_SDIO_HST_EN BIT(2) +#define BIT_SOC_SLPCK_SDIO_DEV_EN BIT(1) +#define BIT_SOC_ACTCK_SDIO_DEV_EN BIT(0) + +//2 REG_PESOC_COM_CLK_CTRL1 +#define BIT_SOC_NFC_CAL_EN BIT(18) +#define BIT_SOC_SLPCK_NFC_EN BIT(17) +#define BIT_SOC_ACTCK_NFC_EN BIT(16) +#define BIT_SOC_SLPCK_SECURITY_ENG_EN BIT(5) +#define BIT_SOC_ACTCK_SECURITY_ENG_EN BIT(4) +#define BIT_SOC_SLPCK_WL_EN BIT(1) +#define BIT_SOC_ACTCK_WL_EN BIT(0) + +//2 REG_PESOC_HW_ENG_CLK_CTRL + +//2 REG_RSVD + +//2 REG_PESOC_CLK_SEL +#define BIT_PESOC_SPI1_SCLK_SEL BIT(18) + +#define BIT_SHIFT_PESOC_PERI_SCLK_SEL 16 +#define BIT_MASK_PESOC_PERI_SCLK_SEL 0x3 +#define BIT_PESOC_PERI_SCLK_SEL(x) (((x) & BIT_MASK_PESOC_PERI_SCLK_SEL) << BIT_SHIFT_PESOC_PERI_SCLK_SEL) + + +#define BIT_SHIFT_PESOC_SDR_CK_SEL 10 +#define BIT_MASK_PESOC_SDR_CK_SEL 0x3 +#define BIT_PESOC_SDR_CK_SEL(x) (((x) & BIT_MASK_PESOC_SDR_CK_SEL) << BIT_SHIFT_PESOC_SDR_CK_SEL) + + +#define BIT_SHIFT_PESOC_FLASH_CK_SEL 8 +#define BIT_MASK_PESOC_FLASH_CK_SEL 0x3 +#define BIT_PESOC_FLASH_CK_SEL(x) (((x) & BIT_MASK_PESOC_FLASH_CK_SEL) << BIT_SHIFT_PESOC_FLASH_CK_SEL) + + +#define BIT_SHIFT_PESOC_TRACE_CK_SEL 4 +#define BIT_MASK_PESOC_TRACE_CK_SEL 0x3 +#define BIT_PESOC_TRACE_CK_SEL(x) (((x) & BIT_MASK_PESOC_TRACE_CK_SEL) << BIT_SHIFT_PESOC_TRACE_CK_SEL) + + +//2 REG_RSVD + +//2 REG_RSVD + +//2 REG_RSVD + +//2 REG_RSVD + +//2 REG_RSVD + +//2 REG_RSVD + +//2 REG_SYS_ANACK_CAL_CTRL +#define BIT_SYS_ANACK_CAL_CMD BIT(15) +#define BIT_SYS_ANACK_CAL_SEL BIT(14) + +#define BIT_SHIFT_SYS_ANACK_CAL_RPT 0 +#define BIT_MASK_SYS_ANACK_CAL_RPT 0x3fff +#define BIT_SYS_ANACK_CAL_RPT(x) (((x) & BIT_MASK_SYS_ANACK_CAL_RPT) << BIT_SHIFT_SYS_ANACK_CAL_RPT) + + +//2 REG_OSC32K_CTRL + +#define BIT_SHIFT_32K_BIAS_CURRENT 16 +#define BIT_MASK_32K_BIAS_CURRENT 0xffff +#define BIT_32K_BIAS_CURRENT(x) (((x) & BIT_MASK_32K_BIAS_CURRENT) << BIT_SHIFT_32K_BIAS_CURRENT) + + +#define BIT_SHIFT_32K_RESISTOR_COM 2 +#define BIT_MASK_32K_RESISTOR_COM 0x3 +#define BIT_32K_RESISTOR_COM(x) (((x) & BIT_MASK_32K_RESISTOR_COM) << BIT_SHIFT_32K_RESISTOR_COM) + +#define BIT_32K_DBG_SEL BIT(1) +#define BIT_32K_POW_CKGEN_EN BIT(0) + +//2 REG_OSC32K_REG_CTRL0 +#define BIT_32K_REG_INDIRT_CMD BIT(23) + +#define BIT_SHIFT_32K_REG_INDIRT_ADDR 16 +#define BIT_MASK_32K_REG_INDIRT_ADDR 0x3f +#define BIT_32K_REG_INDIRT_ADDR(x) (((x) & BIT_MASK_32K_REG_INDIRT_ADDR) << BIT_SHIFT_32K_REG_INDIRT_ADDR) + + +#define BIT_SHIFT_32K_REG_INDIRT_WDATA 0 +#define BIT_MASK_32K_REG_INDIRT_WDATA 0xffff +#define BIT_32K_REG_INDIRT_WDATA(x) (((x) & BIT_MASK_32K_REG_INDIRT_WDATA) << BIT_SHIFT_32K_REG_INDIRT_WDATA) + + +//2 REG_OSC32K_REG_CTRL1 + +#define BIT_SHIFT_32K_REG_INDIRT_RDATA 0 +#define BIT_MASK_32K_REG_INDIRT_RDATA 0xffff +#define BIT_32K_REG_INDIRT_RDATA(x) (((x) & BIT_MASK_32K_REG_INDIRT_RDATA) << BIT_SHIFT_32K_REG_INDIRT_RDATA) + + +//2 REG_THERMAL_METER_CTRL + +#define BIT_SHIFT_TEMP_VALUE 24 +#define BIT_MASK_TEMP_VALUE 0x3f +#define BIT_TEMP_VALUE(x) (((x) & BIT_MASK_TEMP_VALUE) << BIT_SHIFT_TEMP_VALUE) + + +#define BIT_SHIFT_TEMP_DELTA 16 +#define BIT_MASK_TEMP_DELTA 0x3f +#define BIT_TEMP_DELTA(x) (((x) & BIT_MASK_TEMP_DELTA) << BIT_SHIFT_TEMP_DELTA) + +#define BIT_THERMAL_METER_EN BIT(15) +#define BIT_THERMAL_METER_VALID BIT(14) + +#define BIT_SHIFT_THERMAL_METER_TIMER 0 +#define BIT_MASK_THERMAL_METER_TIMER 0xfff +#define BIT_THERMAL_METER_TIMER(x) (((x) & BIT_MASK_THERMAL_METER_TIMER) << BIT_SHIFT_THERMAL_METER_TIMER) + + +//2 REG_UART_MUX_CTRL + +#define BIT_SHIFT_UART2_PIN_SEL 9 +#define BIT_MASK_UART2_PIN_SEL 0x7 +#define BIT_UART2_PIN_SEL(x) (((x) & BIT_MASK_UART2_PIN_SEL) << BIT_SHIFT_UART2_PIN_SEL) + +#define BIT_UART2_PIN_EN BIT(8) + +#define BIT_SHIFT_UART1_PIN_SEL 5 +#define BIT_MASK_UART1_PIN_SEL 0x7 +#define BIT_UART1_PIN_SEL(x) (((x) & BIT_MASK_UART1_PIN_SEL) << BIT_SHIFT_UART1_PIN_SEL) + +#define BIT_UART1_PIN_EN BIT(4) + +#define BIT_SHIFT_UART0_PIN_SEL 1 +#define BIT_MASK_UART0_PIN_SEL 0x7 +#define BIT_UART0_PIN_SEL(x) (((x) & BIT_MASK_UART0_PIN_SEL) << BIT_SHIFT_UART0_PIN_SEL) + +#define BIT_UART0_PIN_EN BIT(0) + +//2 REG_SPI_MUX_CTRL +#define BIT_SPI0_MULTI_CS_EN BIT(28) + +#define BIT_SHIFT_SPI2_PIN_SEL 9 +#define BIT_MASK_SPI2_PIN_SEL 0x7 +#define BIT_SPI2_PIN_SEL(x) (((x) & BIT_MASK_SPI2_PIN_SEL) << BIT_SHIFT_SPI2_PIN_SEL) + +#define BIT_SPI2_PIN_EN BIT(8) + +#define BIT_SHIFT_SPI1_PIN_SEL 5 +#define BIT_MASK_SPI1_PIN_SEL 0x7 +#define BIT_SPI1_PIN_SEL(x) (((x) & BIT_MASK_SPI1_PIN_SEL) << BIT_SHIFT_SPI1_PIN_SEL) + +#define BIT_SPI1_PIN_EN BIT(4) + +#define BIT_SHIFT_SPI0_PIN_SEL 1 +#define BIT_MASK_SPI0_PIN_SEL 0x7 +#define BIT_SPI0_PIN_SEL(x) (((x) & BIT_MASK_SPI0_PIN_SEL) << BIT_SHIFT_SPI0_PIN_SEL) + +#define BIT_SPI0_PIN_EN BIT(0) + +//2 REG_I2C_MUX_CTRL + +#define BIT_SHIFT_I2C3_PIN_SEL 13 +#define BIT_MASK_I2C3_PIN_SEL 0x7 +#define BIT_I2C3_PIN_SEL(x) (((x) & BIT_MASK_I2C3_PIN_SEL) << BIT_SHIFT_I2C3_PIN_SEL) + +#define BIT_I2C3_PIN_EN BIT(12) + +#define BIT_SHIFT_I2C2_PIN_SEL 9 +#define BIT_MASK_I2C2_PIN_SEL 0x7 +#define BIT_I2C2_PIN_SEL(x) (((x) & BIT_MASK_I2C2_PIN_SEL) << BIT_SHIFT_I2C2_PIN_SEL) + +#define BIT_I2C2_PIN_EN BIT(8) + +#define BIT_SHIFT_I2C1_PIN_SEL 5 +#define BIT_MASK_I2C1_PIN_SEL 0x7 +#define BIT_I2C1_PIN_SEL(x) (((x) & BIT_MASK_I2C1_PIN_SEL) << BIT_SHIFT_I2C1_PIN_SEL) + +#define BIT_I2C1_PIN_EN BIT(4) + +#define BIT_SHIFT_I2C0_PIN_SEL 1 +#define BIT_MASK_I2C0_PIN_SEL 0x7 +#define BIT_I2C0_PIN_SEL(x) (((x) & BIT_MASK_I2C0_PIN_SEL) << BIT_SHIFT_I2C0_PIN_SEL) + +#define BIT_I2C0_PIN_EN BIT(0) + +//2 REG_I2S_MUX_CTRL/ REG_PCM_MUX_CTRL + +//2 REG_NOT_VALID + +#define BIT_SHIFT_PCM1_PIN_SEL 21 +#define BIT_MASK_PCM1_PIN_SEL 0x7 +#define BIT_PCM1_PIN_SEL(x) (((x) & BIT_MASK_PCM1_PIN_SEL) << BIT_SHIFT_PCM1_PIN_SEL) + +#define BIT_PCM1_PIN_EN BIT(20) + +#define BIT_SHIFT_PCM0_PIN_SEL 17 +#define BIT_MASK_PCM0_PIN_SEL 0x7 +#define BIT_PCM0_PIN_SEL(x) (((x) & BIT_MASK_PCM0_PIN_SEL) << BIT_SHIFT_PCM0_PIN_SEL) + +#define BIT_PCM0_PIN_EN BIT(16) + +//2 REG_NOT_VALID + +#define BIT_SHIFT_I2S1_PIN_SEL 6 +#define BIT_MASK_I2S1_PIN_SEL 0x3 +#define BIT_I2S1_PIN_SEL(x) (((x) & BIT_MASK_I2S1_PIN_SEL) << BIT_SHIFT_I2S1_PIN_SEL) + +#define BIT_I2S1_MCK_EN BIT(5) +#define BIT_I2S1_PIN_EN BIT(4) + +#define BIT_SHIFT_I2S0_PIN_SEL 2 +#define BIT_MASK_I2S0_PIN_SEL 0x3 +#define BIT_I2S0_PIN_SEL(x) (((x) & BIT_MASK_I2S0_PIN_SEL) << BIT_SHIFT_I2S0_PIN_SEL) + +#define BIT_I2S0_MCK_EN BIT(1) +#define BIT_I2S0_PIN_EN BIT(0) + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_HCI_PINMUX_CTRL +#define BIT_HCI_MII_PIN_EN BIT(24) +#define BIT_HCI_SDIOH_PIN_EN BIT(1) +#define BIT_HCI_SDIOD_PIN_EN BIT(0) + +//2 REG_WL_PINMUX_CTRL +#define BIT_NFC_PIN_EN BIT(16) +#define BIT_WL_BTCMD_PIN_EN BIT(13) +#define BIT_WL_BTCOEX_PIN_EN BIT(12) +#define BIT_WL_ANT1_PIN_EN BIT(9) +#define BIT_WL_ANT0_PIN_EN BIT(8) + +#define BIT_SHIFT_WL_LED_PIN_SEL 1 +#define BIT_MASK_WL_LED_PIN_SEL 0x3 +#define BIT_WL_LED_PIN_SEL(x) (((x) & BIT_MASK_WL_LED_PIN_SEL) << BIT_SHIFT_WL_LED_PIN_SEL) + +#define BIT_WL_LED_PIN_EN BIT(0) + +//2 REG_BT_PINMUX_CTRL + +//2 REG_PWM_PINMUX_CTRL + +#define BIT_SHIFT_ETE3_PIN_SEL 29 +#define BIT_MASK_ETE3_PIN_SEL 0x3 +#define BIT_ETE3_PIN_SEL(x) (((x) & BIT_MASK_ETE3_PIN_SEL) << BIT_SHIFT_ETE3_PIN_SEL) + +#define BIT_ETE3_PIN_EN BIT(28) + +#define BIT_SHIFT_ETE2_PIN_SEL 25 +#define BIT_MASK_ETE2_PIN_SEL 0x3 +#define BIT_ETE2_PIN_SEL(x) (((x) & BIT_MASK_ETE2_PIN_SEL) << BIT_SHIFT_ETE2_PIN_SEL) + +#define BIT_ETE2_PIN_EN BIT(24) + +#define BIT_SHIFT_ETE1_PIN_SEL 21 +#define BIT_MASK_ETE1_PIN_SEL 0x3 +#define BIT_ETE1_PIN_SEL(x) (((x) & BIT_MASK_ETE1_PIN_SEL) << BIT_SHIFT_ETE1_PIN_SEL) + +#define BIT_ETE1_PIN_EN BIT(20) + +#define BIT_SHIFT_ETE0_PIN_SEL 17 +#define BIT_MASK_ETE0_PIN_SEL 0x3 +#define BIT_ETE0_PIN_SEL(x) (((x) & BIT_MASK_ETE0_PIN_SEL) << BIT_SHIFT_ETE0_PIN_SEL) + +#define BIT_ETE0_PIN_EN BIT(16) + +#define BIT_SHIFT_PWM3_PIN_SEL 13 +#define BIT_MASK_PWM3_PIN_SEL 0x3 +#define BIT_PWM3_PIN_SEL(x) (((x) & BIT_MASK_PWM3_PIN_SEL) << BIT_SHIFT_PWM3_PIN_SEL) + +#define BIT_PWM3_PIN_EN BIT(12) + +#define BIT_SHIFT_PWM2_PIN_SEL 9 +#define BIT_MASK_PWM2_PIN_SEL 0x3 +#define BIT_PWM2_PIN_SEL(x) (((x) & BIT_MASK_PWM2_PIN_SEL) << BIT_SHIFT_PWM2_PIN_SEL) + +#define BIT_PWM2_PIN_EN BIT(8) + +#define BIT_SHIFT_PWM1_PIN_SEL 5 +#define BIT_MASK_PWM1_PIN_SEL 0x3 +#define BIT_PWM1_PIN_SEL(x) (((x) & BIT_MASK_PWM1_PIN_SEL) << BIT_SHIFT_PWM1_PIN_SEL) + +#define BIT_PWM1_PIN_EN BIT(4) + +#define BIT_SHIFT_PWM0_PIN_SEL 1 +#define BIT_MASK_PWM0_PIN_SEL 0x3 +#define BIT_PWM0_PIN_SEL(x) (((x) & BIT_MASK_PWM0_PIN_SEL) << BIT_SHIFT_PWM0_PIN_SEL) + +#define BIT_PWM0_PIN_EN BIT(0) + +//2 REG_RSVD + +//2 REG_RSVD + +//2 REG_RSVD + +//2 REG_RSVD + +//2 REG_CPU_PERIPHERAL_CTRL + +#define BIT_SHIFT_LOG_UART_PIN_SEL 22 +#define BIT_MASK_LOG_UART_PIN_SEL 0x3 +#define BIT_LOG_UART_PIN_SEL(x) (((x) & BIT_MASK_LOG_UART_PIN_SEL) << BIT_SHIFT_LOG_UART_PIN_SEL) + +#define BIT_LOG_UART_IR_EN BIT(21) +#define BIT_LOG_UART_PIN_EN BIT(20) +#define BIT_TRACE_PIN_EN BIT(17) +#define BIT_SDR_PIN_EN BIT(4) + +#define BIT_SHIFT_SPI_FLSH_PIN_SEL 1 +#define BIT_MASK_SPI_FLSH_PIN_SEL 0x3 +#define BIT_SPI_FLSH_PIN_SEL(x) (((x) & BIT_MASK_SPI_FLSH_PIN_SEL) << BIT_SHIFT_SPI_FLSH_PIN_SEL) + +#define BIT_SPI_FLSH_PIN_EN BIT(0) + +//2 REG_RSVD + +//2 REG_RSVD + +//2 REG_RSVD + +//2 REG_RSVD + +//2 REG_RSVD + +//2 REG_RSVD + +//2 REG_RSVD + +//2 REG_HCI_CTRL_STATUS_0 + +//2 REG_HCI_CTRL_STATUS_1 + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_PESOC_MEM_CTRL + +#define BIT_SHIFT_PESOC_SDR_DDL_CTRL 16 +#define BIT_MASK_PESOC_SDR_DDL_CTRL 0xff +#define BIT_PESOC_SDR_DDL_CTRL(x) (((x) & BIT_MASK_PESOC_SDR_DDL_CTRL) << BIT_SHIFT_PESOC_SDR_DDL_CTRL) + + +#define BIT_SHIFT_PESOC_FLASH_DDL_CTRL 0 +#define BIT_MASK_PESOC_FLASH_DDL_CTRL 0xff +#define BIT_PESOC_FLASH_DDL_CTRL(x) (((x) & BIT_MASK_PESOC_FLASH_DDL_CTRL) << BIT_SHIFT_PESOC_FLASH_DDL_CTRL) + + +//2 REG_PESOC_SOC_CTRL + +#define BIT_SHIFT_PESOC_GDMA_CFG 16 +#define BIT_MASK_PESOC_GDMA_CFG 0x1fff +#define BIT_PESOC_GDMA_CFG(x) (((x) & BIT_MASK_PESOC_GDMA_CFG) << BIT_SHIFT_PESOC_GDMA_CFG) + +#define BIT_PESOC_MII_LX_SLV_SWAP_SEL BIT(13) +#define BIT_PESOC_MII_LX_MST_SWAP_SEL BIT(12) +#define BIT_PESOC_MII_LX_WRAPPER_EN BIT(11) +#define BIT_PESOC_LX_SLV_SWAP_SEL BIT(10) +#define BIT_PESOC_LX_MST_SWAP_SEL BIT(9) +#define BIT_PESOC_LX_WL_SWAP_SEL BIT(8) + +#define BIT_SHIFT_PESOC_SRAM_MUX_CFG 0 +#define BIT_MASK_PESOC_SRAM_MUX_CFG 0x7 +#define BIT_PESOC_SRAM_MUX_CFG(x) (((x) & BIT_MASK_PESOC_SRAM_MUX_CFG) << BIT_SHIFT_PESOC_SRAM_MUX_CFG) + + +//2 REG_PESOC_PERI_CTRL +#define BIT_SOC_FUNC_SPI_RN BIT(8) + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID +#define BIT_FW_CTRL_INT0 BIT(24) + +//2 REG_NOT_VALID + +//2 REG_GPIO_SHTDN_CTRL +#define BIT_GPIO_GPK_SHTDN_N BIT(10) +#define BIT_GPIO_GPJ_SHTDN_N BIT(9) +#define BIT_GPIO_GPI_SHTDN_N BIT(8) +#define BIT_GPIO_GPH_SHTDN_N BIT(7) +#define BIT_GPIO_GPG_SHTDN_N BIT(6) +#define BIT_GPIO_GPF_SHTDN_N BIT(5) +#define BIT_GPIO_GPE_SHTDN_N BIT(4) +#define BIT_GPIO_GPD_SHTDN_N BIT(3) +#define BIT_GPIO_GPC_SHTDN_N BIT(2) +#define BIT_GPIO_GPB_SHTDN_N BIT(1) +#define BIT_GPIO_GPA_SHTDN_N BIT(0) + +//2 REG_GPIO_DRIVING_CTRL +#define BIT_GPIO_GPK_DRV_SEL BIT(20) +#define BIT_GPIO_GPJ_DRV_SEL BIT(18) +#define BIT_GPIO_GPI_DRV_SEL BIT(16) +#define BIT_GPIO_GPH_DRV_SEL BIT(14) +#define BIT_GPIO_GPG_DRV_SEL BIT(12) +#define BIT_GPIO_GPF_DRV_SEL BIT(10) +#define BIT_GPIO_GPE_DRV_SEL BIT(8) +#define BIT_GPIO_GPD_DRV_SEL BIT(6) +#define BIT_GPIO_GPC_DRV_SEL BIT(4) +#define BIT_GPIO_GPB_DRV_SEL BIT(2) +#define BIT_GPIO_GPA_DRV_SEL BIT(0) + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_GPIO_PULL_CTRL0 + +#define BIT_SHIFT_GPIO_GPB7_PULL_CTRL 30 +#define BIT_MASK_GPIO_GPB7_PULL_CTRL 0x3 +#define BIT_GPIO_GPB7_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPB7_PULL_CTRL) << BIT_SHIFT_GPIO_GPB7_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPB6_PULL_CTRL 28 +#define BIT_MASK_GPIO_GPB6_PULL_CTRL 0x3 +#define BIT_GPIO_GPB6_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPB6_PULL_CTRL) << BIT_SHIFT_GPIO_GPB6_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPB5_PULL_CTRL 26 +#define BIT_MASK_GPIO_GPB5_PULL_CTRL 0x3 +#define BIT_GPIO_GPB5_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPB5_PULL_CTRL) << BIT_SHIFT_GPIO_GPB5_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPB4_PULL_CTRL 24 +#define BIT_MASK_GPIO_GPB4_PULL_CTRL 0x3 +#define BIT_GPIO_GPB4_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPB4_PULL_CTRL) << BIT_SHIFT_GPIO_GPB4_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPB3_PULL_CTRL 22 +#define BIT_MASK_GPIO_GPB3_PULL_CTRL 0x3 +#define BIT_GPIO_GPB3_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPB3_PULL_CTRL) << BIT_SHIFT_GPIO_GPB3_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPB2_PULL_CTRL 20 +#define BIT_MASK_GPIO_GPB2_PULL_CTRL 0x3 +#define BIT_GPIO_GPB2_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPB2_PULL_CTRL) << BIT_SHIFT_GPIO_GPB2_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPB1_PULL_CTRL 18 +#define BIT_MASK_GPIO_GPB1_PULL_CTRL 0x3 +#define BIT_GPIO_GPB1_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPB1_PULL_CTRL) << BIT_SHIFT_GPIO_GPB1_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPB0_PULL_CTRL 16 +#define BIT_MASK_GPIO_GPB0_PULL_CTRL 0x3 +#define BIT_GPIO_GPB0_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPB0_PULL_CTRL) << BIT_SHIFT_GPIO_GPB0_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPA7_PULL_CTRL 14 +#define BIT_MASK_GPIO_GPA7_PULL_CTRL 0x3 +#define BIT_GPIO_GPA7_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPA7_PULL_CTRL) << BIT_SHIFT_GPIO_GPA7_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPA6_PULL_CTRL 12 +#define BIT_MASK_GPIO_GPA6_PULL_CTRL 0x3 +#define BIT_GPIO_GPA6_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPA6_PULL_CTRL) << BIT_SHIFT_GPIO_GPA6_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPA5_PULL_CTRL 10 +#define BIT_MASK_GPIO_GPA5_PULL_CTRL 0x3 +#define BIT_GPIO_GPA5_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPA5_PULL_CTRL) << BIT_SHIFT_GPIO_GPA5_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPA4_PULL_CTRL 8 +#define BIT_MASK_GPIO_GPA4_PULL_CTRL 0x3 +#define BIT_GPIO_GPA4_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPA4_PULL_CTRL) << BIT_SHIFT_GPIO_GPA4_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPA3_PULL_CTRL 6 +#define BIT_MASK_GPIO_GPA3_PULL_CTRL 0x3 +#define BIT_GPIO_GPA3_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPA3_PULL_CTRL) << BIT_SHIFT_GPIO_GPA3_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPA2_PULL_CTRL 4 +#define BIT_MASK_GPIO_GPA2_PULL_CTRL 0x3 +#define BIT_GPIO_GPA2_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPA2_PULL_CTRL) << BIT_SHIFT_GPIO_GPA2_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPA1_PULL_CTRL 2 +#define BIT_MASK_GPIO_GPA1_PULL_CTRL 0x3 +#define BIT_GPIO_GPA1_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPA1_PULL_CTRL) << BIT_SHIFT_GPIO_GPA1_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPA0_PULL_CTRL 0 +#define BIT_MASK_GPIO_GPA0_PULL_CTRL 0x3 +#define BIT_GPIO_GPA0_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPA0_PULL_CTRL) << BIT_SHIFT_GPIO_GPA0_PULL_CTRL) + + +//2 REG_GPIO_PULL_CTRL1 + +#define BIT_SHIFT_GPIO_GPD7_PULL_CTRL 29 +#define BIT_MASK_GPIO_GPD7_PULL_CTRL 0x7 +#define BIT_GPIO_GPD7_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPD7_PULL_CTRL) << BIT_SHIFT_GPIO_GPD7_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPD6_PULL_CTRL 28 +#define BIT_MASK_GPIO_GPD6_PULL_CTRL 0x3 +#define BIT_GPIO_GPD6_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPD6_PULL_CTRL) << BIT_SHIFT_GPIO_GPD6_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPD5_PULL_CTRL 26 +#define BIT_MASK_GPIO_GPD5_PULL_CTRL 0x3 +#define BIT_GPIO_GPD5_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPD5_PULL_CTRL) << BIT_SHIFT_GPIO_GPD5_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPD4_PULL_CTRL 24 +#define BIT_MASK_GPIO_GPD4_PULL_CTRL 0x3 +#define BIT_GPIO_GPD4_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPD4_PULL_CTRL) << BIT_SHIFT_GPIO_GPD4_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPD3_PULL_CTRL 22 +#define BIT_MASK_GPIO_GPD3_PULL_CTRL 0x3 +#define BIT_GPIO_GPD3_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPD3_PULL_CTRL) << BIT_SHIFT_GPIO_GPD3_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPD2_PULL_CTRL 20 +#define BIT_MASK_GPIO_GPD2_PULL_CTRL 0x3 +#define BIT_GPIO_GPD2_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPD2_PULL_CTRL) << BIT_SHIFT_GPIO_GPD2_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPD1_PULL_CTRL 18 +#define BIT_MASK_GPIO_GPD1_PULL_CTRL 0x3 +#define BIT_GPIO_GPD1_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPD1_PULL_CTRL) << BIT_SHIFT_GPIO_GPD1_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPD0_PULL_CTRL 16 +#define BIT_MASK_GPIO_GPD0_PULL_CTRL 0x3 +#define BIT_GPIO_GPD0_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPD0_PULL_CTRL) << BIT_SHIFT_GPIO_GPD0_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPC7_PULL_CTRL 14 +#define BIT_MASK_GPIO_GPC7_PULL_CTRL 0x3 +#define BIT_GPIO_GPC7_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPC7_PULL_CTRL) << BIT_SHIFT_GPIO_GPC7_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPC6_PULL_CTRL 12 +#define BIT_MASK_GPIO_GPC6_PULL_CTRL 0x3 +#define BIT_GPIO_GPC6_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPC6_PULL_CTRL) << BIT_SHIFT_GPIO_GPC6_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPC5_PULL_CTRL 10 +#define BIT_MASK_GPIO_GPC5_PULL_CTRL 0x3 +#define BIT_GPIO_GPC5_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPC5_PULL_CTRL) << BIT_SHIFT_GPIO_GPC5_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPC4_PULL_CTRL 8 +#define BIT_MASK_GPIO_GPC4_PULL_CTRL 0x3 +#define BIT_GPIO_GPC4_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPC4_PULL_CTRL) << BIT_SHIFT_GPIO_GPC4_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPC3_PULL_CTRL 6 +#define BIT_MASK_GPIO_GPC3_PULL_CTRL 0x3 +#define BIT_GPIO_GPC3_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPC3_PULL_CTRL) << BIT_SHIFT_GPIO_GPC3_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPC2_PULL_CTRL 4 +#define BIT_MASK_GPIO_GPC2_PULL_CTRL 0x3 +#define BIT_GPIO_GPC2_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPC2_PULL_CTRL) << BIT_SHIFT_GPIO_GPC2_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPC1_PULL_CTRL 2 +#define BIT_MASK_GPIO_GPC1_PULL_CTRL 0x3 +#define BIT_GPIO_GPC1_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPC1_PULL_CTRL) << BIT_SHIFT_GPIO_GPC1_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPC0_PULL_CTRL 0 +#define BIT_MASK_GPIO_GPC0_PULL_CTRL 0x3 +#define BIT_GPIO_GPC0_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPC0_PULL_CTRL) << BIT_SHIFT_GPIO_GPC0_PULL_CTRL) + + +//2 REG_GPIO_PULL_CTRL2 + +#define BIT_SHIFT_GPIO_GPF5_PULL_CTRL 26 +#define BIT_MASK_GPIO_GPF5_PULL_CTRL 0x3 +#define BIT_GPIO_GPF5_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPF5_PULL_CTRL) << BIT_SHIFT_GPIO_GPF5_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPF4_PULL_CTRL 24 +#define BIT_MASK_GPIO_GPF4_PULL_CTRL 0x3 +#define BIT_GPIO_GPF4_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPF4_PULL_CTRL) << BIT_SHIFT_GPIO_GPF4_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPF3_PULL_CTRL 22 +#define BIT_MASK_GPIO_GPF3_PULL_CTRL 0x3 +#define BIT_GPIO_GPF3_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPF3_PULL_CTRL) << BIT_SHIFT_GPIO_GPF3_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPF2_PULL_CTRL 20 +#define BIT_MASK_GPIO_GPF2_PULL_CTRL 0x3 +#define BIT_GPIO_GPF2_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPF2_PULL_CTRL) << BIT_SHIFT_GPIO_GPF2_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPF1_PULL_CTRL 18 +#define BIT_MASK_GPIO_GPF1_PULL_CTRL 0x3 +#define BIT_GPIO_GPF1_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPF1_PULL_CTRL) << BIT_SHIFT_GPIO_GPF1_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPF0_PULL_CTRL 16 +#define BIT_MASK_GPIO_GPF0_PULL_CTRL 0x3 +#define BIT_GPIO_GPF0_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPF0_PULL_CTRL) << BIT_SHIFT_GPIO_GPF0_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPE7_PULL_CTRL 14 +#define BIT_MASK_GPIO_GPE7_PULL_CTRL 0x3 +#define BIT_GPIO_GPE7_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPE7_PULL_CTRL) << BIT_SHIFT_GPIO_GPE7_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPE6_PULL_CTRL 12 +#define BIT_MASK_GPIO_GPE6_PULL_CTRL 0x3 +#define BIT_GPIO_GPE6_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPE6_PULL_CTRL) << BIT_SHIFT_GPIO_GPE6_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPE5_PULL_CTRL 10 +#define BIT_MASK_GPIO_GPE5_PULL_CTRL 0x3 +#define BIT_GPIO_GPE5_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPE5_PULL_CTRL) << BIT_SHIFT_GPIO_GPE5_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPE4_PULL_CTRL 8 +#define BIT_MASK_GPIO_GPE4_PULL_CTRL 0x3 +#define BIT_GPIO_GPE4_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPE4_PULL_CTRL) << BIT_SHIFT_GPIO_GPE4_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPE3_PULL_CTRL 6 +#define BIT_MASK_GPIO_GPE3_PULL_CTRL 0x3 +#define BIT_GPIO_GPE3_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPE3_PULL_CTRL) << BIT_SHIFT_GPIO_GPE3_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPE2_PULL_CTRL 4 +#define BIT_MASK_GPIO_GPE2_PULL_CTRL 0x3 +#define BIT_GPIO_GPE2_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPE2_PULL_CTRL) << BIT_SHIFT_GPIO_GPE2_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPE1_PULL_CTRL 2 +#define BIT_MASK_GPIO_GPE1_PULL_CTRL 0x3 +#define BIT_GPIO_GPE1_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPE1_PULL_CTRL) << BIT_SHIFT_GPIO_GPE1_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPE0_PULL_CTRL 0 +#define BIT_MASK_GPIO_GPE0_PULL_CTRL 0x3 +#define BIT_GPIO_GPE0_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPE0_PULL_CTRL) << BIT_SHIFT_GPIO_GPE0_PULL_CTRL) + + +//2 REG_NOT_VALID + +#define BIT_SHIFT_GPIO_GPH7_PULL_CTRL 30 +#define BIT_MASK_GPIO_GPH7_PULL_CTRL 0x3 +#define BIT_GPIO_GPH7_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPH7_PULL_CTRL) << BIT_SHIFT_GPIO_GPH7_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPH6_PULL_CTRL 28 +#define BIT_MASK_GPIO_GPH6_PULL_CTRL 0x3 +#define BIT_GPIO_GPH6_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPH6_PULL_CTRL) << BIT_SHIFT_GPIO_GPH6_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPH5_PULL_CTRL 26 +#define BIT_MASK_GPIO_GPH5_PULL_CTRL 0x3 +#define BIT_GPIO_GPH5_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPH5_PULL_CTRL) << BIT_SHIFT_GPIO_GPH5_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPH4_PULL_CTRL 24 +#define BIT_MASK_GPIO_GPH4_PULL_CTRL 0x3 +#define BIT_GPIO_GPH4_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPH4_PULL_CTRL) << BIT_SHIFT_GPIO_GPH4_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPH3_PULL_CTRL 22 +#define BIT_MASK_GPIO_GPH3_PULL_CTRL 0x3 +#define BIT_GPIO_GPH3_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPH3_PULL_CTRL) << BIT_SHIFT_GPIO_GPH3_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPH2_PULL_CTRL 20 +#define BIT_MASK_GPIO_GPH2_PULL_CTRL 0x3 +#define BIT_GPIO_GPH2_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPH2_PULL_CTRL) << BIT_SHIFT_GPIO_GPH2_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPH1_PULL_CTRL 18 +#define BIT_MASK_GPIO_GPH1_PULL_CTRL 0x3 +#define BIT_GPIO_GPH1_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPH1_PULL_CTRL) << BIT_SHIFT_GPIO_GPH1_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPH0_PULL_CTRL 16 +#define BIT_MASK_GPIO_GPH0_PULL_CTRL 0x3 +#define BIT_GPIO_GPH0_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPH0_PULL_CTRL) << BIT_SHIFT_GPIO_GPH0_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPG7_PULL_CTRL 14 +#define BIT_MASK_GPIO_GPG7_PULL_CTRL 0x3 +#define BIT_GPIO_GPG7_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPG7_PULL_CTRL) << BIT_SHIFT_GPIO_GPG7_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPG6_PULL_CTRL 12 +#define BIT_MASK_GPIO_GPG6_PULL_CTRL 0x3 +#define BIT_GPIO_GPG6_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPG6_PULL_CTRL) << BIT_SHIFT_GPIO_GPG6_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPG5_PULL_CTRL 10 +#define BIT_MASK_GPIO_GPG5_PULL_CTRL 0x3 +#define BIT_GPIO_GPG5_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPG5_PULL_CTRL) << BIT_SHIFT_GPIO_GPG5_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPG4_PULL_CTRL 8 +#define BIT_MASK_GPIO_GPG4_PULL_CTRL 0x3 +#define BIT_GPIO_GPG4_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPG4_PULL_CTRL) << BIT_SHIFT_GPIO_GPG4_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPG3_PULL_CTRL 6 +#define BIT_MASK_GPIO_GPG3_PULL_CTRL 0x3 +#define BIT_GPIO_GPG3_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPG3_PULL_CTRL) << BIT_SHIFT_GPIO_GPG3_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPG2_PULL_CTRL 4 +#define BIT_MASK_GPIO_GPG2_PULL_CTRL 0x3 +#define BIT_GPIO_GPG2_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPG2_PULL_CTRL) << BIT_SHIFT_GPIO_GPG2_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPG1_PULL_CTRL 2 +#define BIT_MASK_GPIO_GPG1_PULL_CTRL 0x3 +#define BIT_GPIO_GPG1_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPG1_PULL_CTRL) << BIT_SHIFT_GPIO_GPG1_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPG0_PULL_CTRL 0 +#define BIT_MASK_GPIO_GPG0_PULL_CTRL 0x3 +#define BIT_GPIO_GPG0_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPG0_PULL_CTRL) << BIT_SHIFT_GPIO_GPG0_PULL_CTRL) + + +//2 REG_GPIO_PULL_CTRL4 + +#define BIT_SHIFT_GPIO_GPJ6_PULL_CTRL 28 +#define BIT_MASK_GPIO_GPJ6_PULL_CTRL 0x3 +#define BIT_GPIO_GPJ6_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPJ6_PULL_CTRL) << BIT_SHIFT_GPIO_GPJ6_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPJ5_PULL_CTRL 26 +#define BIT_MASK_GPIO_GPJ5_PULL_CTRL 0x3 +#define BIT_GPIO_GPJ5_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPJ5_PULL_CTRL) << BIT_SHIFT_GPIO_GPJ5_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPJ4_PULL_CTRL 24 +#define BIT_MASK_GPIO_GPJ4_PULL_CTRL 0x3 +#define BIT_GPIO_GPJ4_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPJ4_PULL_CTRL) << BIT_SHIFT_GPIO_GPJ4_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPJ3_PULL_CTRL 22 +#define BIT_MASK_GPIO_GPJ3_PULL_CTRL 0x3 +#define BIT_GPIO_GPJ3_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPJ3_PULL_CTRL) << BIT_SHIFT_GPIO_GPJ3_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPJ2_PULL_CTRL 20 +#define BIT_MASK_GPIO_GPJ2_PULL_CTRL 0x3 +#define BIT_GPIO_GPJ2_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPJ2_PULL_CTRL) << BIT_SHIFT_GPIO_GPJ2_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPJ1_PULL_CTRL 18 +#define BIT_MASK_GPIO_GPJ1_PULL_CTRL 0x3 +#define BIT_GPIO_GPJ1_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPJ1_PULL_CTRL) << BIT_SHIFT_GPIO_GPJ1_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPJ0_PULL_CTRL 16 +#define BIT_MASK_GPIO_GPJ0_PULL_CTRL 0x3 +#define BIT_GPIO_GPJ0_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPJ0_PULL_CTRL) << BIT_SHIFT_GPIO_GPJ0_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPI7_PULL_CTRL 14 +#define BIT_MASK_GPIO_GPI7_PULL_CTRL 0x3 +#define BIT_GPIO_GPI7_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPI7_PULL_CTRL) << BIT_SHIFT_GPIO_GPI7_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPI6_PULL_CTRL 12 +#define BIT_MASK_GPIO_GPI6_PULL_CTRL 0x3 +#define BIT_GPIO_GPI6_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPI6_PULL_CTRL) << BIT_SHIFT_GPIO_GPI6_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPI5_PULL_CTRL 10 +#define BIT_MASK_GPIO_GPI5_PULL_CTRL 0x3 +#define BIT_GPIO_GPI5_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPI5_PULL_CTRL) << BIT_SHIFT_GPIO_GPI5_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPI4_PULL_CTRL 8 +#define BIT_MASK_GPIO_GPI4_PULL_CTRL 0x3 +#define BIT_GPIO_GPI4_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPI4_PULL_CTRL) << BIT_SHIFT_GPIO_GPI4_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPI3_PULL_CTRL 6 +#define BIT_MASK_GPIO_GPI3_PULL_CTRL 0x3 +#define BIT_GPIO_GPI3_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPI3_PULL_CTRL) << BIT_SHIFT_GPIO_GPI3_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPI2_PULL_CTRL 4 +#define BIT_MASK_GPIO_GPI2_PULL_CTRL 0x3 +#define BIT_GPIO_GPI2_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPI2_PULL_CTRL) << BIT_SHIFT_GPIO_GPI2_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPI1_PULL_CTRL 2 +#define BIT_MASK_GPIO_GPI1_PULL_CTRL 0x3 +#define BIT_GPIO_GPI1_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPI1_PULL_CTRL) << BIT_SHIFT_GPIO_GPI1_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPI0_PULL_CTRL 0 +#define BIT_MASK_GPIO_GPI0_PULL_CTRL 0x3 +#define BIT_GPIO_GPI0_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPI0_PULL_CTRL) << BIT_SHIFT_GPIO_GPI0_PULL_CTRL) + + +//2 REG_GPIO_PULL_CTRL5 + +#define BIT_SHIFT_GPIO_GPEA_PULL_CTRL 20 +#define BIT_MASK_GPIO_GPEA_PULL_CTRL 0x3 +#define BIT_GPIO_GPEA_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPEA_PULL_CTRL) << BIT_SHIFT_GPIO_GPEA_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPE9_PULL_CTRL 18 +#define BIT_MASK_GPIO_GPE9_PULL_CTRL 0x3 +#define BIT_GPIO_GPE9_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPE9_PULL_CTRL) << BIT_SHIFT_GPIO_GPE9_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPE8_PULL_CTRL 16 +#define BIT_MASK_GPIO_GPE8_PULL_CTRL 0x3 +#define BIT_GPIO_GPE8_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPE8_PULL_CTRL) << BIT_SHIFT_GPIO_GPE8_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPK7_PULL_CTRL 12 +#define BIT_MASK_GPIO_GPK7_PULL_CTRL 0x3 +#define BIT_GPIO_GPK7_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPK7_PULL_CTRL) << BIT_SHIFT_GPIO_GPK7_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPK5_PULL_CTRL 10 +#define BIT_MASK_GPIO_GPK5_PULL_CTRL 0x3 +#define BIT_GPIO_GPK5_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPK5_PULL_CTRL) << BIT_SHIFT_GPIO_GPK5_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPK4_PULL_CTRL 8 +#define BIT_MASK_GPIO_GPK4_PULL_CTRL 0x3 +#define BIT_GPIO_GPK4_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPK4_PULL_CTRL) << BIT_SHIFT_GPIO_GPK4_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPK3_PULL_CTRL 6 +#define BIT_MASK_GPIO_GPK3_PULL_CTRL 0x3 +#define BIT_GPIO_GPK3_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPK3_PULL_CTRL) << BIT_SHIFT_GPIO_GPK3_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPK2_PULL_CTRL 4 +#define BIT_MASK_GPIO_GPK2_PULL_CTRL 0x3 +#define BIT_GPIO_GPK2_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPK2_PULL_CTRL) << BIT_SHIFT_GPIO_GPK2_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPK1_PULL_CTRL 2 +#define BIT_MASK_GPIO_GPK1_PULL_CTRL 0x3 +#define BIT_GPIO_GPK1_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPK1_PULL_CTRL) << BIT_SHIFT_GPIO_GPK1_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPK0_PULL_CTRL 0 +#define BIT_MASK_GPIO_GPK0_PULL_CTRL 0x3 +#define BIT_GPIO_GPK0_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPK0_PULL_CTRL) << BIT_SHIFT_GPIO_GPK0_PULL_CTRL) + + +//2 REG_GPIO_PULL_CTRL6 + +#define BIT_SHIFT_GPIO_GPD9_PULL_CTRL 18 +#define BIT_MASK_GPIO_GPD9_PULL_CTRL 0x3 +#define BIT_GPIO_GPD9_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPD9_PULL_CTRL) << BIT_SHIFT_GPIO_GPD9_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPD8_PULL_CTRL 16 +#define BIT_MASK_GPIO_GPD8_PULL_CTRL 0x3 +#define BIT_GPIO_GPD8_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPD8_PULL_CTRL) << BIT_SHIFT_GPIO_GPD8_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPC9_PULL_CTRL 2 +#define BIT_MASK_GPIO_GPC9_PULL_CTRL 0x3 +#define BIT_GPIO_GPC9_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPC9_PULL_CTRL) << BIT_SHIFT_GPIO_GPC9_PULL_CTRL) + + +#define BIT_SHIFT_GPIO_GPC8_PULL_CTRL 0 +#define BIT_MASK_GPIO_GPC8_PULL_CTRL 0x3 +#define BIT_GPIO_GPC8_PULL_CTRL(x) (((x) & BIT_MASK_GPIO_GPC8_PULL_CTRL) << BIT_SHIFT_GPIO_GPC8_PULL_CTRL) + + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_PERI_PWM0_CTRL +#define BIT_PERI_PWM0_EN BIT(31) + +#define BIT_SHIFT_PERI_PWM0_GT_SEL 24 +#define BIT_MASK_PERI_PWM0_GT_SEL 0xf +#define BIT_PERI_PWM0_GT_SEL(x) (((x) & BIT_MASK_PERI_PWM0_GT_SEL) << BIT_SHIFT_PERI_PWM0_GT_SEL) + + +#define BIT_SHIFT_PERI_PWM0_DUTY 12 +#define BIT_MASK_PERI_PWM0_DUTY 0x3ff +#define BIT_PERI_PWM0_DUTY(x) (((x) & BIT_MASK_PERI_PWM0_DUTY) << BIT_SHIFT_PERI_PWM0_DUTY) + + +#define BIT_SHIFT_PERI_PWM0_PERIOD 0 +#define BIT_MASK_PERI_PWM0_PERIOD 0x3ff +#define BIT_PERI_PWM0_PERIOD(x) (((x) & BIT_MASK_PERI_PWM0_PERIOD) << BIT_SHIFT_PERI_PWM0_PERIOD) + + +//2 REG_PERI_PWM1_CTRL +#define BIT_PERI_PWM1_EN BIT(31) + +#define BIT_SHIFT_PERI_PWM1_GT_SEL 24 +#define BIT_MASK_PERI_PWM1_GT_SEL 0xf +#define BIT_PERI_PWM1_GT_SEL(x) (((x) & BIT_MASK_PERI_PWM1_GT_SEL) << BIT_SHIFT_PERI_PWM1_GT_SEL) + + +#define BIT_SHIFT_PERI_PWM1_DUTY 12 +#define BIT_MASK_PERI_PWM1_DUTY 0x3ff +#define BIT_PERI_PWM1_DUTY(x) (((x) & BIT_MASK_PERI_PWM1_DUTY) << BIT_SHIFT_PERI_PWM1_DUTY) + + +#define BIT_SHIFT_PERI_PWM1_PERIOD 0 +#define BIT_MASK_PERI_PWM1_PERIOD 0x3ff +#define BIT_PERI_PWM1_PERIOD(x) (((x) & BIT_MASK_PERI_PWM1_PERIOD) << BIT_SHIFT_PERI_PWM1_PERIOD) + + +//2 REG_PERI_PWM2_CTRL +#define BIT_PERI_PWM2_EN BIT(31) + +#define BIT_SHIFT_PERI_PWM2_GT_SEL 24 +#define BIT_MASK_PERI_PWM2_GT_SEL 0xf +#define BIT_PERI_PWM2_GT_SEL(x) (((x) & BIT_MASK_PERI_PWM2_GT_SEL) << BIT_SHIFT_PERI_PWM2_GT_SEL) + + +#define BIT_SHIFT_PERI_PWM2_DUTY 12 +#define BIT_MASK_PERI_PWM2_DUTY 0x3ff +#define BIT_PERI_PWM2_DUTY(x) (((x) & BIT_MASK_PERI_PWM2_DUTY) << BIT_SHIFT_PERI_PWM2_DUTY) + + +#define BIT_SHIFT_PERI_PWM2_PERIOD 0 +#define BIT_MASK_PERI_PWM2_PERIOD 0x3ff +#define BIT_PERI_PWM2_PERIOD(x) (((x) & BIT_MASK_PERI_PWM2_PERIOD) << BIT_SHIFT_PERI_PWM2_PERIOD) + + +//2 REG_PERI_PWM3_CTRL +#define BIT_PERI_PWM3_EN BIT(31) + +#define BIT_SHIFT_PERI_PWM3_GT_SEL 24 +#define BIT_MASK_PERI_PWM3_GT_SEL 0xf +#define BIT_PERI_PWM3_GT_SEL(x) (((x) & BIT_MASK_PERI_PWM3_GT_SEL) << BIT_SHIFT_PERI_PWM3_GT_SEL) + + +#define BIT_SHIFT_PERI_PWM3_DUTY 12 +#define BIT_MASK_PERI_PWM3_DUTY 0x3ff +#define BIT_PERI_PWM3_DUTY(x) (((x) & BIT_MASK_PERI_PWM3_DUTY) << BIT_SHIFT_PERI_PWM3_DUTY) + + +#define BIT_SHIFT_PERI_PWM3_PERIOD 0 +#define BIT_MASK_PERI_PWM3_PERIOD 0x3ff +#define BIT_PERI_PWM3_PERIOD(x) (((x) & BIT_MASK_PERI_PWM3_PERIOD) << BIT_SHIFT_PERI_PWM3_PERIOD) + + +//2 REG_PERI_TIM_EVT_CTRL +#define BIT_PERI_GT_EVT3_EN BIT(31) + +#define BIT_SHIFT_PERI_GT_EVT3_SRC_SEL 28 +#define BIT_MASK_PERI_GT_EVT3_SRC_SEL 0x7 +#define BIT_PERI_GT_EVT3_SRC_SEL(x) (((x) & BIT_MASK_PERI_GT_EVT3_SRC_SEL) << BIT_SHIFT_PERI_GT_EVT3_SRC_SEL) + + +#define BIT_SHIFT_PERI_GT_EVT3_PULSE_DUR 24 +#define BIT_MASK_PERI_GT_EVT3_PULSE_DUR 0xf +#define BIT_PERI_GT_EVT3_PULSE_DUR(x) (((x) & BIT_MASK_PERI_GT_EVT3_PULSE_DUR) << BIT_SHIFT_PERI_GT_EVT3_PULSE_DUR) + +#define BIT_PERI_GT_EVT2_EN BIT(23) + +#define BIT_SHIFT_PERI_GT_EVT2_SRC_SEL 20 +#define BIT_MASK_PERI_GT_EVT2_SRC_SEL 0x7 +#define BIT_PERI_GT_EVT2_SRC_SEL(x) (((x) & BIT_MASK_PERI_GT_EVT2_SRC_SEL) << BIT_SHIFT_PERI_GT_EVT2_SRC_SEL) + + +#define BIT_SHIFT_PERI_GT_EVT2_PULSE_DUR 16 +#define BIT_MASK_PERI_GT_EVT2_PULSE_DUR 0xf +#define BIT_PERI_GT_EVT2_PULSE_DUR(x) (((x) & BIT_MASK_PERI_GT_EVT2_PULSE_DUR) << BIT_SHIFT_PERI_GT_EVT2_PULSE_DUR) + +#define BIT_PERI_GT_EVT1_EN BIT(15) + +#define BIT_SHIFT_PERI_GT_EVT1_SRC_SEL 12 +#define BIT_MASK_PERI_GT_EVT1_SRC_SEL 0x7 +#define BIT_PERI_GT_EVT1_SRC_SEL(x) (((x) & BIT_MASK_PERI_GT_EVT1_SRC_SEL) << BIT_SHIFT_PERI_GT_EVT1_SRC_SEL) + + +#define BIT_SHIFT_PERI_GT_EVT1_PULSE_DUR 8 +#define BIT_MASK_PERI_GT_EVT1_PULSE_DUR 0xf +#define BIT_PERI_GT_EVT1_PULSE_DUR(x) (((x) & BIT_MASK_PERI_GT_EVT1_PULSE_DUR) << BIT_SHIFT_PERI_GT_EVT1_PULSE_DUR) + +#define BIT_PERI_GT_EVT0_EN BIT(7) + +#define BIT_SHIFT_PERI_GT_EVT0_SRC_SEL 4 +#define BIT_MASK_PERI_GT_EVT0_SRC_SEL 0x7 +#define BIT_PERI_GT_EVT0_SRC_SEL(x) (((x) & BIT_MASK_PERI_GT_EVT0_SRC_SEL) << BIT_SHIFT_PERI_GT_EVT0_SRC_SEL) + + +#define BIT_SHIFT_PERI_GT_EVT0_PULSE_DUR 0 +#define BIT_MASK_PERI_GT_EVT0_PULSE_DUR 0xf +#define BIT_PERI_GT_EVT0_PULSE_DUR(x) (((x) & BIT_MASK_PERI_GT_EVT0_PULSE_DUR) << BIT_SHIFT_PERI_GT_EVT0_PULSE_DUR) + + +//2 REG_PERI_EGTIM_CTRL + +#define BIT_SHIFT_PERI_EGTIM_PIN_GROUP2_OPT_SEL 12 +#define BIT_MASK_PERI_EGTIM_PIN_GROUP2_OPT_SEL 0x3 +#define BIT_PERI_EGTIM_PIN_GROUP2_OPT_SEL(x) (((x) & BIT_MASK_PERI_EGTIM_PIN_GROUP2_OPT_SEL) << BIT_SHIFT_PERI_EGTIM_PIN_GROUP2_OPT_SEL) + + +#define BIT_SHIFT_PERI_EGTIM_PIN_GROUP1_OPT_SEL 10 +#define BIT_MASK_PERI_EGTIM_PIN_GROUP1_OPT_SEL 0x3 +#define BIT_PERI_EGTIM_PIN_GROUP1_OPT_SEL(x) (((x) & BIT_MASK_PERI_EGTIM_PIN_GROUP1_OPT_SEL) << BIT_SHIFT_PERI_EGTIM_PIN_GROUP1_OPT_SEL) + + +#define BIT_SHIFT_PERI_EGTIM_PIN_GROUP0_OPT_SEL 8 +#define BIT_MASK_PERI_EGTIM_PIN_GROUP0_OPT_SEL 0x3 +#define BIT_PERI_EGTIM_PIN_GROUP0_OPT_SEL(x) (((x) & BIT_MASK_PERI_EGTIM_PIN_GROUP0_OPT_SEL) << BIT_SHIFT_PERI_EGTIM_PIN_GROUP0_OPT_SEL) + + +//2 REG_NOT_VALID + +#define BIT_SHIFT_PERI_EGTIM_REF_SIG_SEL 4 +#define BIT_MASK_PERI_EGTIM_REF_SIG_SEL 0x3 +#define BIT_PERI_EGTIM_REF_SIG_SEL(x) (((x) & BIT_MASK_PERI_EGTIM_REF_SIG_SEL) << BIT_SHIFT_PERI_EGTIM_REF_SIG_SEL) + +#define BIT_PERI_EGTIM_EN BIT(0) + +//2 REG_NOT_VALID + +//2 REG_PEON_CFG + +//2 REG_PEON_STATUS +#define BIT_PEON_SDIO_ALDN BIT(0) + + +//========== Register Address Definition ==================// +#define REG_PEON_PWR_CTRL 0x0200 +#define REG_PON_ISO_CTRL 0x0204 +#define REG_SOC_FUNC_EN 0x0210 +#define REG_SOC_HCI_COM_FUNC_EN 0x0214 +#define REG_SOC_PERI_FUNC0_EN 0x0218 +#define REG_SOC_PERI_FUNC1_EN 0x021C +#define REG_SOC_PERI_BD_FUNC0_EN 0x0220 +#define REG_PESOC_CLK_CTRL 0x0230 +#define REG_PESOC_PERI_CLK_CTRL0 0x0234 +#define REG_PESOC_PERI_CLK_CTRL1 0x0238 +#define REG_PESOC_CLK_CTRL3 0x023C +#define REG_PESOC_HCI_CLK_CTRL0 0x0240 +#define REG_PESOC_COM_CLK_CTRL1 0x0244 +#define REG_PESOC_HW_ENG_CLK_CTRL 0x0248 +#define REG_PESOC_CLK_SEL 0x0250 +#define REG_SYS_ANACK_CAL_CTRL 0x026C +#define REG_OSC32K_CTRL 0x0270 +#define REG_OSC32K_REG_CTRL0 0x0274 +#define REG_OSC32K_REG_CTRL1 0x0278 +#define REG_THERMAL_METER_CTRL 0x027C +#define REG_UART_MUX_CTRL 0x0280 +#define REG_SPI_MUX_CTRL 0x0284 +#define REG_I2C_MUX_CTRL 0x0288 +#define REG_I2S_MUX_CTRL 0x028C +#define REG_HCI_PINMUX_CTRL 0x02A0 +#define REG_WL_PINMUX_CTRL 0x02A4 +#define REG_BT_PINMUX_CTRL 0x02A8 +#define REG_PWM_PINMUX_CTRL 0x02AC +#define REG_CPU_PERIPHERAL_CTRL 0x02C0 +#define REG_HCI_CTRL_STATUS_0 0x02E0 +#define REG_HCI_CTRL_STATUS_1 0x02E4 +#define REG_PESOC_MEM_CTRL 0x0300 +#define REG_PESOC_SOC_CTRL 0x0304 +#define REG_PESOC_PERI_CTRL 0x0308 +#define REG_GPIO_SHTDN_CTRL 0x0320 +#define REG_GPIO_DRIVING_CTRL 0x0324 +#define REG_GPIO_PULL_CTRL0 0x0330 +#define REG_GPIO_PULL_CTRL1 0x0334 +#define REG_GPIO_PULL_CTRL2 0x0338 +#define REG_GPIO_PULL_CTRL3 0x033C +#define REG_GPIO_PULL_CTRL4 0x0340 +#define REG_GPIO_PULL_CTRL5 0x0344 +#define REG_GPIO_PULL_CTRL6 0x0348 +#define REG_PERI_PWM0_CTRL 0x0360 +#define REG_PERI_PWM1_CTRL 0x0364 +#define REG_PERI_PWM2_CTRL 0x0368 +#define REG_PERI_PWM3_CTRL 0x036C +#define REG_PERI_TIM_EVT_CTRL 0x0370 +#define REG_PERI_EGTIM_CTRL 0x0374 +#define REG_PEON_CFG 0x03F0 +#define REG_PEON_STATUS 0x03F4 + + +#endif // end of "#ifndef __INC_RTL8195A_PERI_ON_H" diff --git a/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_pwm.h b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_pwm.h new file mode 100644 index 0000000..ddf166b --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_pwm.h @@ -0,0 +1,37 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + + +#ifndef _RTL8195A_PWM_H_ +#define _RTL8195A_PWM_H_ + +extern void +HAL_Pwm_SetDuty_8195a( + HAL_PWM_ADAPTER *pPwmAdapt, + u32 period, + u32 pulse_width +); + +extern HAL_Status +HAL_Pwm_Init_8195a( + HAL_PWM_ADAPTER *pPwmAdapt +); + +extern void +HAL_Pwm_Enable_8195a( + HAL_PWM_ADAPTER *pPwmAdapt +); + +extern void +HAL_Pwm_Disable_8195a( + HAL_PWM_ADAPTER *pPwmAdapt +); + + +#endif diff --git a/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_sdio.h b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_sdio.h new file mode 100644 index 0000000..f60ae95 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_sdio.h @@ -0,0 +1,946 @@ + /* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + + +#ifndef _RTL8195A_SDIO_H_ +#define _RTL8195A_SDIO_H_ + +#include "hal_api.h" +#include "hal_util.h" +#if defined(CONFIG_SDIO_BOOT_SIM) || defined(CONFIG_SDIO_BOOT_ROM) +#define SDIO_BOOT_DRIVER 1 // is this SDIO driver works for booting +#else +#include "osdep_api.h" +#define SDIO_BOOT_DRIVER 0 // is this SDIO driver works for booting +#endif +#define SDIO_DEBUG 1 +#define SDIO_MP_MODE 1 // if includes MP mode function +#define SDIO_MAX_WAIT_RX_DMA 100 // Wait RX DMA done +#define SDIO_RX_PKT_SIZE_OVER_16K 0 /* is support SDIO RX packet size > 16K. if true, + a big packet will be transmited via multiple RX_BD */ +#define SDIO_MAILBOX_SIZE 10 // the maximum number of message block can be stored in this mailbox +#define SDIO_PERIODICAL_TIMER_INTERVAL 2000 // in ms, the interval of SDIO periodical timer +#define SDIO_AVG_TP_WIN_SIZE 20 // the number of entry to log the byte count for every periodical timer statistic, to calculate throughput + +#define HAL_SDIO_READ32(addr) HAL_READ32(SDIO_DEVICE_REG_BASE, addr) +#define HAL_SDIO_WRITE32(addr, value) HAL_WRITE32(SDIO_DEVICE_REG_BASE, addr, value) +#define HAL_SDIO_READ16(addr) HAL_READ16(SDIO_DEVICE_REG_BASE, addr) +#define HAL_SDIO_WRITE16(addr, value) HAL_WRITE16(SDIO_DEVICE_REG_BASE, addr, value) +#define HAL_SDIO_READ8(addr) HAL_READ8(SDIO_DEVICE_REG_BASE, addr) +#define HAL_SDIO_WRITE8(addr, value) HAL_WRITE8(SDIO_DEVICE_REG_BASE, addr, value) + +/***** Register Address *****/ +#define REG_SPDIO_TXBD_ADDR 0xA0 // 4 Bytes +#define REG_SPDIO_TXBD_SIZE 0xA4 // 4 Bytes +#define REG_SPDIO_TXBD_WPTR 0xA8 // 2 Bytes +#define REG_SPDIO_TXBD_RPTR 0xAC // 2 Bytes +#define REG_SPDIO_RXBD_ADDR 0xB0 // 4 Bytes +#define REG_SPDIO_RXBD_SIZE 0xB4 // 2 Bytes +#define REG_SPDIO_RXBD_C2H_WPTR 0xB6 // 2 Bytes +#define REG_SPDIO_RXBD_C2H_RPTR 0xB8 // 2 Bytes +#define REG_SPDIO_HCI_RX_REQ 0xBA // 1 Byte +#define REG_SPDIO_CPU_RST_DMA 0xBB // 1 Byte +#define REG_SPDIO_RX_REQ_ADDR 0xBC // 2 Bytes +#define REG_SPDIO_CPU_INT_MASK 0xC0 // 2 Bytes +#define REG_SPDIO_CPU_INT_STAS 0xC2 // 2 Bytes +#define REG_SPDIO_CCPWM 0xC4 // 1 Byts +#define REG_SPDIO_CPU_IND 0xC5 // 1 Byte +#define REG_SPDIO_CCPWM2 0xC6 // 2 Bytes +#define REG_SPDIO_CPU_H2C_MSG 0xC8 // 4 Bytes +#define REG_SPDIO_CPU_C2H_MSG 0xCC // 4 Bytes +#define REG_SPDIO_CRPWM 0xD0 // 1 Bytes +#define REG_SPDIO_CRPWM2 0xD2 // 2 Bytes +#define REG_SPDIO_AHB_DMA_CTRL 0xD4 // 4 Bytes +#define REG_SPDIO_RXBD_CNT 0xD8 // 4 Bytes +#define REG_SPDIO_TX_BUF_UNIT_SZ 0xD9 // 1 Bytes +#define REG_SPDIO_RX_BD_FREE_CNT 0xDA // 2 Bytes +#define REG_SPDIO_CPU_H2C_MSG_EXT 0xDC // 4 Bytes +#define REG_SPDIO_CPU_C2H_MSG_EXT 0xE0 // 4 Bytes + +// Register REG_SPDIO_CPU_RST_DMA +#define BIT_CPU_RST_SDIO_DMA BIT(7) + +// Register REG_SPDIO_CPU_INT_MASK, REG_SPDIO_CPU_INT_STAS +#define BIT_TXFIFO_H2C_OVF BIT(0) +#define BIT_H2C_BUS_RES_FAIL BIT(1) +#define BIT_H2C_DMA_OK BIT(2) +#define BIT_C2H_DMA_OK BIT(3) +#define BIT_H2C_MSG_INT BIT(4) +#define BIT_RPWM1_INT BIT(5) +#define BIT_RPWM2_INT BIT(6) +#define BIT_SDIO_RST_CMD_INT BIT(7) +#define BIT_RXBD_FLAG_ERR_INT BIT(8) +#define BIT_RX_BD_AVAI_INT BIT(9) +#define BIT_HOST_WAKE_CPU_INT BIT(10) + +// Register REG_SPDIO_CPU_IND +#define BIT_SYSTEM_TRX_RDY_IND BIT(0) + +// Register REG_SPDIO_HCI_RX_REQ +#define BIT_HCI_RX_REQ BIT(0) + +/* Register for SOC_HCI_COM_FUN_EN */ +#define BIT_SOC_HCI_SDIOD_OFF_EN BIT(1) // SDIO Function Block on Power_Off domain +#define BIT_SOC_HCI_SDIOD_ON_EN BIT(0) // SDIO Function Block on Power_On domain + +/* Register REG_PESOC_HCI_CLK_CTRL0 */ +#define BIT_SOC_SLPCK_SDIO_HST_EN BIT(3) // SDIO_HST clock enable when CPU sleep command +#define BIT_SOC_ACTCK_SDIO_HST_EN BIT(2) // SDIO_HST clock enable in CPU run mode +#define BIT_SOC_SLPCK_SDIO_DEV_EN BIT(1) // SDIO_DEV clock enable when CPU sleep command +#define BIT_SOC_ACTCK_SDIO_DEV_EN BIT(0) // SDIO_DEV clock enable in CPU run mode + +/***** Structer for each Register *****/ +#if (SYSTEM_ENDIAN==PLATFORM_LITTLE_ENDIAN) +// Little Endian +// Register REG_SPDIO_HCI_RX_REQ @ 0xBA +typedef struct _SPDIO_HCI_RX_REQ { + u8 HCI_RX_REQ:1; /* bit[0], CPU trigger this bit to enable SDIO IP RX transfer by fetch BD info */ + u8 Reserved:7; /* bit[7:1], Reserved */ +} SPDIO_HCI_RX_REQ, *PSPDIO_HCI_RX_REQ; + +// Register REG_SPDIO_CPU_RST_DMA @ 0xBB +typedef struct _SPDIO_CPU_RST_DMA { + u8 Reserved:7; /* bit[6:0], Reserved */ + u8 CPU_RST_SDIO:1; /* bit[7], CPU set this bit to reset SDIO DMA */ +} SPDIO_CPU_RST_DMA, *PSPDIO_CPU_RST_DMA; + +// Register REG_SPDIO_CPU_INT_MASK @ 0xC0 +typedef struct _SPDIO_CPU_INT_MASK { + u16 TXFIFO_H2C_OVF:1; /* bit[0], set 0 to mask TXFIFO_H2C_OVF_INT */ + u16 H2C_BUS_RES_FAIL:1; /* bit[1], set 0 to mask H2C_BUS_RES_FAIL_INT */ + u16 H2C_DMA_OK:1; /* bit[2], set 0 to mask H2C_DMA_OK_INT */ + u16 C2H_DMA_OK:1; /* bit[3], set 0 to mask C2H_DMA_OK_INT */ + u16 H2C_MSG_INT:1; /* bit[4], set 0 to mask H2C_MSG_INT_INT */ + u16 RPWM_INT:1; /* bit[5], set 0 to mask RPWM_INT */ + u16 RPWM2_INT:1; /* bit[6], set 0 to mask RPWM2_INT */ + u16 SDIO_RST_CMD_INT:1; /* bit[7], set 0 to mask SDIO_RST_CMD_INT */ + u16 BD_FLAG_ERR_INT:1; /* bit[8], set 0 to mask BD_FLAG_ERR_INT */ + u16 Reserved:7; /* bit[15:9], Reserved */ +} SPDIO_CPU_INT_MASK, *PSPDIO_CPU_INT_MASK; + +// Register REG_SPDIO_CPU_INT_STATUS @ 0xC2 +typedef struct _SPDIO_CPU_INT_STAS { + u16 TXFIFO_H2C_OVF:1; /* bit[0], set 0 to mask TXFIFO_H2C_OVF_INT */ + u16 H2C_BUS_RES_FAIL:1; /* bit[1], set 0 to mask H2C_BUS_RES_FAIL_INT */ + u16 H2C_DMA_OK:1; /* bit[2], set 0 to mask H2C_DMA_OK_INT */ + u16 C2H_DMA_OK:1; /* bit[3], set 0 to mask C2H_DMA_OK_INT */ + u16 H2C_MSG_INT:1; /* bit[4], set 0 to mask H2C_MSG_INT_INT */ + u16 RPWM_INT:1; /* bit[5], set 0 to mask RPWM_INT */ + u16 RPWM2_INT:1; /* bit[6], set 0 to mask RPWM2_INT */ + u16 SDIO_RST_CMD_INT:1; /* bit[7], set 0 to mask SDIO_RST_CMD_INT */ + u16 BD_FLAG_ERR_INT:1; /* bit[8], set 0 to mask BD_FLAG_ERR_INT */ + u16 Reserved:7; /* bit[15:9], Reserved */ +} SPDIO_CPU_INT_STAS, *PSPDIO_CPU_INT_STAS; + +// Register REG_SPDIO_CCPWM @ 0xC4 +typedef struct _SPDIO_CCPWM { + u8 :1; /* bit[0] */ + u8 WLAN_TRX:1; /* bit[1], 0: WLAN Off; 1: WLAN On */ + u8 RPS_ST:1; /* bit[2], 0/1: AP Register Sleep/Active state */ + u8 WWLAN:1; /* bit[3], 0/1: "Wake on WLAN"/"Normal" state */ + u8 Reserved:3; /* bit[6:4], Reserved */ + u8 TOGGLING:1; /* bit[7], issue interrupt when 0->1 or 1->0 */ +} SPDIO_CCPWM, *PSPDIO_CCPWM; + +// Register REG_SPDIO_CPU_IND @ 0xC5 +typedef struct _SPDIO_CPU_IND { + u8 SYS_TRX_RDY:1; /* bit[0], To indicate the Host system that CPU is ready for TRX + , to be sync to 0x87[0] */ + u8 Reserved:7; /* bit[7:1], Reserved */ +} SPDIO_CPU_IND, *PSPDIO_CPU_IND; + +// Register REG_SPDIO_CPU_H2C_MSG @ 0xC8 +typedef struct _SPDIO_CPU_H2C_MSG { + u32 CPU_H2C_MSG:30; /* bit[30:0], Host CPU to FW message, sync from REG_SDIO_H2C_MSG */ + u32 Reserved:1; /* bit[31], Reserved */ +} SPDIO_CPU_H2C_MSG, *PSPDIO_CPU_H2C_MSG; + +// Register REG_SPDIO_CPU_C2H_MSG @ 0xCC +typedef struct _SPDIO_CPU_C2H_MSG { + u32 CPU_C2H_MSG:30; /* bit[30:0], FW to Host CPU message, sync to REG_SDIO_C2H_MSG */ + u32 Reserved:1; /* bit[31], Reserved */ +} SPDIO_CPU_C2H_MSG, *PSPDIO_CPU_C2H_MSG; + +// Register REG_SPDIO_CRPWM @ 0xD0 +typedef struct _SPDIO_CRPWM { + u8 :1; /* bit[0] */ + u8 WLAN_TRX:1; /* bit[1], 0: WLAN Off; 1: WLAN On */ + u8 RPS_ST:1; /* bit[2], 0/1: AP Register Sleep/Active state */ + u8 WWLAN:1; /* bit[3], 0/1: "Wake on WLAN"/"Normal" state */ + u8 Reserved:3; /* bit[6:4], Reserved */ + u8 TOGGLING:1; /* bit[7], issue interrupt when 0->1 or 1->0 */ +} SPDIO_CRPWM, *PSPDIO_CRPWM; + +// Register REG_SPDIO_AHB_DMA_CTRL @ 0xD4 +typedef struct _SPDIO_AHB_DMA_CTRL { + u32 TXFF_WLEVEL:7; /* bit[6:0], SPDIO TX FIFO water level */ + u32 :1; /* bit[7] */ + u32 RXFF_WLEVEL:7; /* bit[14:8], SPDIO RX FIFO water level */ + u32 :1; /* bit[15] */ + u32 AHB_DMA_CS:4; /* bit[19:16], AHB DMA state */ + u32 :1; /* bit[20] */ + u32 AHB_MASTER_RDY:1; /* bit[21], AHB Master Hready signal */ + u32 AHB_DMA_TRANS:2; /* bit[23:22], AHB DMA Trans value, for debugging */ + u32 AHB_BUSY_WAIT_CNT:4; /* bit[27:24], timeout for AHB controller to wait busy */ + u32 AHB_BURST_TYPE:3; /* bit[30:28], AHB burst type */ + u32 DISPATCH_TXAGG:1; /* bit[31], Enable to dispatch aggregated TX packet */ +} SPDIO_AHB_DMA_CTRL, *PSPDIO_AHB_DMA_CTRL; + +#else /* else of '#if LITTLE_ENDIAN' */ +// Big Endian +typedef struct _SPDIO_HCI_RX_REQ { + u8 Reserved:7; /* bit[7:1], Reserved */ + u8 HCI_RX_REQ:1; /* bit[0], CPU trigger this bit to enable SDIO IP RX transfer by fetch BD info */ +} SPDIO_HCI_RX_REQ, *PSPDIO_HCI_RX_REQ; + +// Register REG_SPDIO_CPU_RST_DMA @ 0xBB +typedef struct _SPDIO_CPU_RST_DMA { + u8 CPU_RST_SDIO:1; /* bit[7], CPU set this bit to reset SDIO DMA */ + u8 Reserved:7; /* bit[6:0], Reserved */ +} SPDIO_CPU_RST_DMA, *PSPDIO_CPU_RST_DMA; + +// Register REG_SPDIO_CPU_INT_MASK @ 0xC0 +typedef struct _SPDIO_CPU_INT_MASK { + u16 Reserved:7; /* bit[15:9], Reserved */ + u16 BD_FLAG_ERR_INT:1; /* bit[8], set 0 to mask BD_FLAG_ERR_INT */ + u16 SDIO_RST_CMD_INT:1; /* bit[7], set 0 to mask SDIO_RST_CMD_INT */ + u16 RPWM2_INT:1; /* bit[6], set 0 to mask RPWM2_INT */ + u16 RPWM_INT:1; /* bit[5], set 0 to mask RPWM_INT */ + u16 H2C_MSG_INT:1; /* bit[4], set 0 to mask H2C_MSG_INT_INT */ + u16 C2H_DMA_OK:1; /* bit[3], set 0 to mask C2H_DMA_OK_INT */ + u16 H2C_DMA_OK:1; /* bit[2], set 0 to mask H2C_DMA_OK_INT */ + u16 H2C_BUS_RES_FAIL:1; /* bit[1], set 0 to mask H2C_BUS_RES_FAIL_INT */ + u16 TXFIFO_H2C_OVF:1; /* bit[0], set 0 to mask TXFIFO_H2C_OVF_INT */ +} SPDIO_CPU_INT_MASK, *PSPDIO_CPU_INT_MASK; + +// Register REG_SPDIO_CPU_INT_STAS @ 0xC2 +typedef struct _SPDIO_CPU_INT_STAS { + u16 Reserved:7; /* bit[15:9], Reserved */ + u16 BD_FLAG_ERR_INT:1; /* bit[8], set 0 to mask BD_FLAG_ERR_INT */ + u16 SDIO_RST_CMD_INT:1; /* bit[7], set 0 to mask SDIO_RST_CMD_INT */ + u16 RPWM2_INT:1; /* bit[6], set 0 to mask RPWM2_INT */ + u16 RPWM_INT:1; /* bit[5], set 0 to mask RPWM_INT */ + u16 H2C_MSG_INT:1; /* bit[4], set 0 to mask H2C_MSG_INT_INT */ + u16 C2H_DMA_OK:1; /* bit[3], set 0 to mask C2H_DMA_OK_INT */ + u16 H2C_DMA_OK:1; /* bit[2], set 0 to mask H2C_DMA_OK_INT */ + u16 H2C_BUS_RES_FAIL:1; /* bit[1], set 0 to mask H2C_BUS_RES_FAIL_INT */ + u16 TXFIFO_H2C_OVF:1; /* bit[0], set 0 to mask TXFIFO_H2C_OVF_INT */ +} SPDIO_CPU_INT_STAS, *PSPDIO_CPU_INT_STAS; + +// Register REG_SPDIO_CCPWM @ 0xC4 +typedef struct _SPDIO_CCPWM { + u8 TOGGLING:1; /* bit[7], issue interrupt when 0->1 or 1->0 */ + u8 Reserved:3; /* bit[6:4], Reserved */ + u8 WWLAN:1; /* bit[3], 0/1: "Wake on WLAN"/"Normal" state */ + u8 RPS_ST:1; /* bit[2], 0/1: AP Register Sleep/Active state */ + u8 WLAN_TRX:1; /* bit[1], 0: WLAN Off; 1: WLAN On */ + u8 :1; /* bit[0] */ +} SPDIO_CCPWM, *PSPDIO_CCPWM; + +// Register REG_SPDIO_CPU_IND @ 0xC5 +typedef struct _SPDIO_CPU_IND { + u8 Reserved:7; /* bit[7:1], Reserved */ + u8 SYS_TRX_RDY:1; /* bit[0], To indicate the Host system that CPU is ready for TRX + , to be sync to 0x87[0] */ +} SPDIO_CPU_IND, *PSPDIO_CPU_IND; + +// Register REG_SPDIO_CPU_H2C_MSG @ 0xC8 +typedef struct _SPDIO_CPU_H2C_MSG { + u32 Reserved:1; /* bit[31], Reserved */ + u32 CPU_H2C_MSG:30; /* bit[30:0], Host CPU to FW message */ +} SPDIO_CPU_H2C_MSG, *PSPDIO_CPU_H2C_MSG; + +// Register REG_SPDIO_CPU_C2H_MSG @ 0xCC +typedef struct _SPDIO_CPU_C2H_MSG { + u32 Reserved:1; /* bit[31], Reserved */ + u32 CPU_C2H_MSG:30; /* bit[30:0], FW to Host CPU message, sync to REG_SDIO_C2H_MSG */ +} SPDIO_CPU_C2H_MSG, *PSPDIO_CPU_C2H_MSG; + +// Register REG_SPDIO_CRPWM @ 0xD0 +typedef struct _SPDIO_CRPWM { + u8 TOGGLING:1; /* bit[7], issue interrupt when 0->1 or 1->0 */ + u8 Reserved:3; /* bit[6:4], Reserved */ + u8 WWLAN:1; /* bit[3], 0/1: "Wake on WLAN"/"Normal" state */ + u8 RPS_ST:1; /* bit[2], 0/1: AP Register Sleep/Active state */ + u8 WLAN_TRX:1; /* bit[1], 0: WLAN Off; 1: WLAN On */ + u8 :1; /* bit[0] */ +} SPDIO_CRPWM, *PSPDIO_CRPWM; + +// Register REG_SPDIO_AHB_DMA_CTRL @ 0xD4 +typedef struct _SPDIO_AHB_DMA_CTRL { + u32 DISPATCH_TXAGG:1; /* bit[31], Enable to dispatch aggregated TX packet */ + u32 AHB_BURST_TYPE:3; /* bit[30:28], AHB burst type */ + u32 AHB_BUSY_WAIT_CNT:4; /* bit[27:24], timeout for AHB controller to wait busy */ + u32 AHB_DMA_TRANS:2; /* bit[23:22], AHB DMA Trans value, for debugging */ + u32 AHB_MASTER_RDY:1; /* bit[21], AHB Master Hready signal */ + u32 :1; /* bit[20] */ + u32 AHB_DMA_CS:4; /* bit[19:16], AHB DMA state */ + u32 :1; /* bit[15] */ + u32 RXFF_WLEVEL:7; /* bit[14:8], SPDIO RX FIFO water level */ + u32 :1; /* bit[7] */ + u32 TXFF_WLEVEL:7; /* bit[6:0], SPDIO TX FIFO water level */ +} SPDIO_AHB_DMA_CTRL, *PSPDIO_AHB_DMA_CTRL; + +#endif /* end of '#if LITTLE_ENDIAN' */ + + +//#define TX_FIFO_ADDR 0x0000 +//#define TX_FIFO_SIZE 0x8000 + +//TX BD setting +#if SDIO_BOOT_DRIVER +// for build ROM library +#define SDIO_TX_BD_NUM 2 // Number of TX BD +#define SDIO_TX_BD_BUF_SIZE (2048+32) // the size of a TX BD pointed buffer, WLan header = 26 bytes +#define SDIO_TX_PKT_NUM 10 // Number of TX packet handler + +//RX BD setting +#define RX_BD_FREE_TH 4 // trigger the interrupt when free RX BD over this threshold + +#define MAX_RX_BD_BUF_SIZE 16380 // the Maximum size for a RX_BD point to, make it 4-bytes aligned + +#define SDIO_RX_PKT_NUM 3 // Number of RX packet handler +//#define SDIO_RX_BD_NUM 10 // Number of RX BD, to make 32K of bus aggregation, it needs 22 RX_BD at least +#define SDIO_RX_BD_NUM (SDIO_RX_PKT_NUM*2) // Number of RX BD, to make 32K of bus aggregation, it needs 22 RX_BD at least +#define SDIO_RX_BD_BUF_SIZE (2048+24) // the size of a RX BD pointed buffer, sizeof(RX Desc) = 26 bytes +#define MIN_RX_BD_SEND_PKT 2 /* the minum needed RX_BD to send a Packet to Host, we need 2: + one for RX_Desc, the other for payload */ + +// CCPWM2 bit map definition for Firmware download +#define SDIO_INIT_DONE (BIT0) +#define SDIO_MEM_WR_DONE (BIT1) +#define SDIO_MEM_RD_DONE (BIT2) +#define SDIO_MEM_ST_DONE (BIT3) + +#define SDIO_CPWM2_TOGGLE (BIT15) + +#else +#define SDIO_TX_BD_NUM 24 // Number of TX BD +#define SDIO_TX_BD_BUF_SIZE (2048+32) // the size of a TX BD pointed buffer, WLan header = 26 bytes +#define SDIO_TX_PKT_NUM 128 // Number of TX packet handler + +//RX BD setting +#define RX_BD_FREE_TH 5 // trigger the interrupt when free RX BD over this threshold + +#define SDIO_RX_BD_BUF_SIZE 2048 +#define MAX_RX_BD_BUF_SIZE 16380 // the Maximum size for a RX_BD point to, make it 4-bytes aligned + +//#define SDIO_TX_FIFO_SIZE (1024*64) // 64K +#define SDIO_RX_BD_NUM 24 // Number of RX BD, to make 32K of bus aggregation, it needs 22 RX_BD at least +#define SDIO_RX_PKT_NUM 128 // Number of RX packet handler +#define MIN_RX_BD_SEND_PKT 2 /* the minum needed RX_BD to send a Packet to Host, we need 2: + one for RX_Desc, the other for payload */ +#endif + +#define SDIO_IRQ_PRIORITY 10 + +/* SDIO Events */ +#define SDIO_EVENT_IRQ BIT(0) // Interrupt triggered +#define SDIO_EVENT_RX_PKT_RDY BIT(1) // A new SDIO packet ready +#define SDIO_EVENT_C2H_DMA_DONE BIT(2) // Interrupt of C2H DMA done triggered +#define SDIO_EVENT_DUMP BIT(3) // SDIO status dump periodically Enable +#define SDIO_EVENT_TXBD_REFILL BIT(4) // To refill TX BD buffer +#define SDIO_EVENT_EXIT BIT(28) // Request to exit the SDIO task +#define SDIO_EVENT_MP_STOPPED BIT(29) // The SDIO task is stopped +#define SDIO_EVENT_TX_STOPPED BIT(30) // The SDIO task is stopped +#define SDIO_EVENT_RX_STOPPED BIT(31) // The SDIO task is stopped + +#define SDIO_TASK_PRIORITY 1 // it can be 0(lowest) ~ configMAX_PRIORITIES-1(highest) +#define SDIO_MP_TASK_PRIORITY 2 // it can be 0(lowest) ~ configMAX_PRIORITIES-1(highest) +//#if SDIO_TASK_PRIORITY > (configMAX_PRIORITIES - 1) +#if SDIO_TASK_PRIORITY > (4 - 1) +#error "SDIO Task Priority Should be 0~(configMAX_PRIORITIES-1)" +#endif + +//#define TX_RX_PACKET_SIZE 0x144 + +typedef struct _SDIO_TX_BD_ { + u32 Address; /* The TX buffer physical address, it must be 4-bytes aligned */ +}SDIO_TX_BD, *PSDIO_TX_BD; + +#define TX_BD_STRUCTURE_SIZE (sizeof(SDIO_TX_BD)) + + +/* The RX Buffer Descriptor format */ + +#if (SYSTEM_ENDIAN==PLATFORM_LITTLE_ENDIAN) +typedef struct _SDIO_RX_BD_ { + u32 BuffSize:14; /* bit[13:0], RX Buffer Size, Maximum 16384-1 */ + u32 LS:1; /* bit[14], is the Last Segment ? */ + u32 FS:1; /* bit[15], is the First Segment ? */ + u32 Seq:16; /* bit[31:16], The sequence number, it's no use for now */ + u32 PhyAddr; /* The RX buffer physical address, it must be 4-bytes aligned */ +} SDIO_RX_BD, *PSDIO_RX_BD; +#else +typedef struct _SDIO_RX_BD_ { + u32 Seq:16; /* bit[31:16], The sequence number, be used for ?? */ + u32 FS:1; /* bit[15], is the First Segment ? */ + u32 LS:1; /* bit[14], is the Last Segment ? */ + u32 BuffSize:14; /* bit[13:0], RX Buffer Size, Maximum 16384 */ + u32 PhyAddr; /* The RX buffer physical address, it must be 4-bytes aligned */ +} SDIO_RX_BD, *PSDIO_RX_BD; +#endif +#define RX_BD_STRUCTURE_SIZE (sizeof(SDIO_RX_BD)) + +// TODO: This data structer just for test, we should modify it for the normal driver +typedef struct _SDIO_TX_DESC{ + // u4Byte 0 +#if (SYSTEM_ENDIAN==PLATFORM_LITTLE_ENDIAN) + u32 txpktsize:16; // bit[15:0] + u32 offset:8; // bit[23:16], store the sizeof(SDIO_TX_DESC) + u32 bus_agg_num:8; // bit[31:24], the bus aggregation number +#else + u32 bus_agg_num:8; // bit[31:24], the bus aggregation number + u32 offset:8; // bit[23:16], store the sizeof(SDIO_TX_DESC) + u32 txpktsize:16; // bit[15:0] +#endif + + // u4Byte 1 +#if (SYSTEM_ENDIAN==PLATFORM_LITTLE_ENDIAN) + u32 type:8; // bit[7:0], the packet type + u32 rsvd0:24; +#else + u32 rsvd0:24; + u32 type:8; // bit[7:0], the packet type +#endif + + // u4Byte 2 + u32 rsvd1; + + // u4Byte 3 + u32 rsvd2; + + // u4Byte 4 + u32 rsvd3; + + // u4Byte 5 + u32 rsvd4; +} SDIO_TX_DESC, *PSDIO_TX_DESC; + +// TX Desc for Memory Write command +typedef struct _SDIO_TX_DESC_MW{ + // u4Byte 0 +#if (SYSTEM_ENDIAN==PLATFORM_LITTLE_ENDIAN) + u32 txpktsize:16; // bit[15:0] + u32 offset:8; // bit[23:16], store the sizeof(SDIO_TX_DESC) + u32 bus_agg_num:8; // bit[31:24], the bus aggregation number +#else + u32 bus_agg_num:8; // bit[31:24], the bus aggregation number + u32 offset:8; // bit[23:16], store the sizeof(SDIO_TX_DESC) + u32 txpktsize:16; // bit[15:0] +#endif + + // u4Byte 1 +#if (SYSTEM_ENDIAN==PLATFORM_LITTLE_ENDIAN) + u32 type:8; // bit[7:0], the packet type + u32 reply:1; // bit[8], request to send a reply message + u32 rsvd0:23; +#else + u32 rsvd0:23; + u32 reply:1; // bit[8], request to send a reply message + u32 type:8; // bit[7:0], the packet type +#endif + + // u4Byte 2 + u32 start_addr; // memory write start address + + // u4Byte 3 +#if (SYSTEM_ENDIAN==PLATFORM_LITTLE_ENDIAN) + u32 write_len:16; // bit[15:0], the length to write + u32 rsvd2:16; // bit[31:16] +#else + u32 rsvd2:16; // bit[31:16] + u32 write_len:16; // bit[15:0], the length to write +#endif + + // u4Byte 4 + u32 rsvd3; + + // u4Byte 5 + u32 rsvd4; +} SDIO_TX_DESC_MW, *PSDIO_TX_DESC_MW; + +// TX Desc for Memory Read command +typedef struct _SDIO_TX_DESC_MR{ + // u4Byte 0 +#if (SYSTEM_ENDIAN==PLATFORM_LITTLE_ENDIAN) + u32 txpktsize:16; // bit[15:0] + u32 offset:8; // bit[23:16], store the sizeof(SDIO_TX_DESC) + u32 bus_agg_num:8; // bit[31:24], the bus aggregation number +#else + u32 bus_agg_num:8; // bit[31:24], the bus aggregation number + u32 offset:8; // bit[23:16], store the sizeof(SDIO_TX_DESC) + u32 txpktsize:16; // bit[15:0] +#endif + + // u4Byte 1 +#if (SYSTEM_ENDIAN==PLATFORM_LITTLE_ENDIAN) + u32 type:8; // bit[7:0], the packet type + u32 rsvd0:24; +#else + u32 rsvd0:24; + u32 type:8; // bit[7:0], the packet type +#endif + + // u4Byte 2 + u32 start_addr; // memory write start address + + // u4Byte 3 +#if (SYSTEM_ENDIAN==PLATFORM_LITTLE_ENDIAN) + u32 read_len:16; // bit[15:0], the length to read + u32 rsvd2:16; // bit[31:16] +#else + u32 rsvd2:16; // bit[31:16] + u32 read_len:16; // bit[15:0], the length to read +#endif + + // u4Byte 4 + u32 rsvd3; + + // u4Byte 5 + u32 rsvd4; +} SDIO_TX_DESC_MR, *PSDIO_TX_DESC_MR; + +// TX Desc for Memory Set command +typedef struct _SDIO_TX_DESC_MS{ + // u4Byte 0 +#if (SYSTEM_ENDIAN==PLATFORM_LITTLE_ENDIAN) + u32 txpktsize:16; // bit[15:0] + u32 offset:8; // bit[23:16], store the sizeof(SDIO_TX_DESC) + u32 bus_agg_num:8; // bit[31:24], the bus aggregation number +#else + u32 bus_agg_num:8; // bit[31:24], the bus aggregation number + u32 offset:8; // bit[23:16], store the sizeof(SDIO_TX_DESC) + u32 txpktsize:16; // bit[15:0] +#endif + + // u4Byte 1 +#if (SYSTEM_ENDIAN==PLATFORM_LITTLE_ENDIAN) + u32 type:8; // bit[7:0], the packet type + u32 data:8; // bit[8:15], the value to be written to the memory + u32 reply:1; // bit[16], request to send a reply message + u32 rsvd0:15; +#else + u32 rsvd0:15; + u32 reply:1; // bit[16], request to send a reply message + u32 data:8; // bit[8:15], the value to be written to the memory + u32 type:8; // bit[7:0], the packet type +#endif + + // u4Byte 2 + u32 start_addr; // memory write start address + + // u4Byte 3 +#if (SYSTEM_ENDIAN==PLATFORM_LITTLE_ENDIAN) + u32 write_len:16; // bit[15:0], the length to write + u32 rsvd2:16; // bit[31:16] +#else + u32 rsvd2:16; // bit[31:16] + u32 write_len:16; // bit[15:0], the length to write +#endif + + // u4Byte 4 + u32 rsvd3; + + // u4Byte 5 + u32 rsvd4; +} SDIO_TX_DESC_MS, *PSDIO_TX_DESC_MS; + +// TX Desc for Jump to Start command +typedef struct _SDIO_TX_DESC_JS{ + // u4Byte 0 +#if (SYSTEM_ENDIAN==PLATFORM_LITTLE_ENDIAN) + u32 txpktsize:16; // bit[15:0] + u32 offset:8; // bit[23:16], store the sizeof(SDIO_TX_DESC) + u32 bus_agg_num:8; // bit[31:24], the bus aggregation number +#else + u32 bus_agg_num:8; // bit[31:24], the bus aggregation number + u32 offset:8; // bit[23:16], store the sizeof(SDIO_TX_DESC) + u32 txpktsize:16; // bit[15:0] +#endif + + // u4Byte 1 +#if (SYSTEM_ENDIAN==PLATFORM_LITTLE_ENDIAN) + u32 type:8; // bit[7:0], the packet type + u32 rsvd0:24; +#else + u32 rsvd0:24; + u32 type:8; // bit[7:0], the packet type +#endif + + // u4Byte 2 + u32 start_fun; // the pointer of the startup function + + // u4Byte 3 + u32 rsvd2; + + // u4Byte 4 + u32 rsvd3; + + // u4Byte 5 + u32 rsvd4; +} SDIO_TX_DESC_JS, *PSDIO_TX_DESC_JS; + + +#define SIZE_TX_DESC (sizeof(SDIO_TX_DESC)) +// define the TX BD buffer size with unite of 64 byets +/* Be carefull!! the setting of hardware's TX BD buffer size may exceed the real size of + the TX BD buffer size, and then it may cause the hardware DMA write the buffer overflow */ +#define SDIO_TX_BUF_SZ_UNIT 64 +#define SDIO_TX_BD_BUF_USIZE ((((SDIO_TX_BD_BUF_SIZE+sizeof(SDIO_TX_DESC)-1)/SDIO_TX_BUF_SZ_UNIT)+1)&0xff) + +typedef struct _SDIO_TX_BD_BUFFER_ { + SDIO_TX_DESC TX_Desc; + u8 TX_Buffer[SDIO_TX_BD_BUF_SIZE]; +}SDIO_TX_BD_BUFFER, *PSDIO_TX_BD_BUFFER; + + +// TODO: This data structer just for test, we should modify it for the normal driver +typedef struct _SDIO_RX_DESC{ + // u4Byte 0 +#if (SYSTEM_ENDIAN==PLATFORM_LITTLE_ENDIAN) + u32 pkt_len:16; // bit[15:0], the packet size + u32 offset:8; // bit[23:16], the offset from the packet start to the buf start, also means the size of RX Desc + u32 rsvd0:6; // bit[29:24] + u32 icv:1; // bit[30], ICV error + u32 crc:1; // bit[31], CRC error +#else + u32 crc:1; // bit[31], CRC error + u32 icv:1; // bit[30], ICV error + u32 rsvd0:6; // bit[29:24] + u32 offset:8; // bit[23:16], the offset from the packet start to the buf start, also means the size of RX Desc + u32 pkt_len:16; // bit[15:0], the packet size +#endif + + // u4Byte 1 +#if (SYSTEM_ENDIAN==PLATFORM_LITTLE_ENDIAN) + u32 type:8; // bit[7:0], the type of this packet + u32 rsvd1:24; // bit[31:8] +#else + u32 rsvd1:24; // bit[31:8] + u32 type:8; // bit[7:0], the type of this packet +#endif + + // u4Byte 2 + u32 rsvd2; + + // u4Byte 3 + u32 rsvd3; + + // u4Byte 4 + u32 rsvd4; + + // u4Byte 5 + u32 rsvd5; +} SDIO_RX_DESC, *PSDIO_RX_DESC; + +// For memory read command +typedef struct _SDIO_RX_DESC_MR{ + // u4Byte 0 +#if (SYSTEM_ENDIAN==PLATFORM_LITTLE_ENDIAN) + u32 pkt_len:16; // bit[15:0], the packet size + u32 offset:8; // bit[23:16], the offset from the packet start to the buf start, also means the size of RX Desc + u32 rsvd0:8; // bit[31:24] +#else + u32 rsvd0:8; // bit[31:24] + u32 offset:8; // bit[23:16], the offset from the packet start to the buf start, also means the size of RX Desc + u32 pkt_len:16; // bit[15:0], the packet size +#endif + + // u4Byte 1 +#if (SYSTEM_ENDIAN==PLATFORM_LITTLE_ENDIAN) + u32 type:8; // bit[7:0], the type of this packet + u32 rsvd1:24; // bit[31:8] +#else + u32 rsvd1:24; // bit[31:8] + u32 type:8; // bit[7:0], the type of this packet +#endif + + // u4Byte 2 + u32 start_addr; + + // u4Byte 3 + u32 rsvd2; + + // u4Byte 4 + u32 rsvd3; + + // u4Byte 5 + u32 rsvd4; +} SDIO_RX_DESC_MR, *PSDIO_RX_DESC_MR; + +// For memory write reply command +typedef struct _SDIO_RX_DESC_MW{ + // u4Byte 0 +#if (SYSTEM_ENDIAN==PLATFORM_LITTLE_ENDIAN) + u32 pkt_len:16; // bit[15:0], the packet size + u32 offset:8; // bit[23:16], the offset from the packet start to the buf start, also means the size of RX Desc + u32 rsvd0:8; // bit[31:24] +#else + u32 rsvd0:8; // bit[31:24] + u32 offset:8; // bit[23:16], the offset from the packet start to the buf start, also means the size of RX Desc + u32 pkt_len:16; // bit[15:0], the packet size +#endif + + // u4Byte 1 +#if (SYSTEM_ENDIAN==PLATFORM_LITTLE_ENDIAN) + u32 type:8; // bit[7:0], the type of this packet + u32 rsvd1:24; // bit[31:8] +#else + u32 rsvd1:24; // bit[31:8] + u32 type:8; // bit[7:0], the type of this packet +#endif + + // u4Byte 2 + u32 start_addr; + + // u4Byte 3 +#if (SYSTEM_ENDIAN==PLATFORM_LITTLE_ENDIAN) + u32 write_len:16; // bit[15:0], the type of this packet + u32 result:8; // bit[23:16], the result of memory write command + u32 rsvd2:8; // bit[31:24] +#else + u32 rsvd2:8; // bit[31:24] + u32 result:8; // bit[23:16], the result of memory write command + u32 write_len:16; // bit[15:0], the type of this packet +#endif + + // u4Byte 4 + u32 rsvd3; + + // u4Byte 5 + u32 rsvd4; +} SDIO_RX_DESC_MW, *PSDIO_RX_DESC_MW; + +// For memory set reply command +typedef struct _SDIO_RX_DESC_MS{ + // u4Byte 0 +#if (SYSTEM_ENDIAN==PLATFORM_LITTLE_ENDIAN) + u32 pkt_len:16; // bit[15:0], the packet size + u32 offset:8; // bit[23:16], the offset from the packet start to the buf start, also means the size of RX Desc + u32 rsvd0:8; // bit[31:24] +#else + u32 rsvd0:8; // bit[31:24] + u32 offset:8; // bit[23:16], the offset from the packet start to the buf start, also means the size of RX Desc + u32 pkt_len:16; // bit[15:0], the packet size +#endif + + // u4Byte 1 +#if (SYSTEM_ENDIAN==PLATFORM_LITTLE_ENDIAN) + u32 type:8; // bit[7:0], the type of this packet + u32 rsvd1:24; // bit[31:8] +#else + u32 rsvd1:24; // bit[31:8] + u32 type:8; // bit[7:0], the type of this packet +#endif + + // u4Byte 2 + u32 start_addr; + + // u4Byte 3 +#if (SYSTEM_ENDIAN==PLATFORM_LITTLE_ENDIAN) + u32 write_len:16; // bit[15:0], the type of this packet + u32 result:8; // bit[23:16], the result of memory write command + u32 rsvd2:8; // bit[31:24] +#else + u32 rsvd2:8; // bit[31:24] + u32 result:8; // bit[23:16], the result of memory write command + u32 write_len:16; // bit[15:0], the type of this packet +#endif + + // u4Byte 4 + u32 rsvd3; + + // u4Byte 5 + u32 rsvd4; +} SDIO_RX_DESC_MS, *PSDIO_RX_DESC_MS; + +#define SIZE_RX_DESC (sizeof(SDIO_RX_DESC)) + +typedef struct _SDIO_RX_BD_BUFFER_ { + SDIO_RX_DESC RX_Desc; + u8 RX_Buffer[SDIO_RX_BD_BUF_SIZE]; +}SDIO_RX_BD_BUFFER, *PSDIO_RX_BD_BUFFER; + + +/* The data structer for a packet fordwarding to the WLan driver to transmit it */ +// TODO: This data structer just for test, we may need modify it for the normal driver +typedef struct _SDIO_TX_PACKET_ { + u8 *pHeader; // Point to the 1st byte of the packets + u16 PktSize; // the size (bytes) of this packet + _LIST list; // the link list to chain packets + u8 isDyna; // is Dynamic allocated +} SDIO_TX_PACKET, *PSDIO_TX_PACKET; + +/* the data structer to bind a TX_BD with a TX Packet */ +typedef struct _SDIO_TX_BD_HANDLE_ { + SDIO_TX_BD *pTXBD; // Point to the TX_BD buffer + SDIO_TX_PACKET *pPkt; // point to the Tx Packet + u8 isPktEnd; // For a packet over 1 BD , this flag to indicate is this BD contains a packet end + u8 isFree; // is this TX BD free +} SDIO_TX_BD_HANDLE, *PSDIO_TX_BD_HANDLE; + +/* The data structer for a packet which from the WLan driver to send to the Host */ +// TODO: This data structer just for test, we may need modify it for the normal driver + +#if SDIO_BOOT_DRIVER +typedef struct _SDIO_RX_PACKET_ { +// SDIO_RX_DESC RxDesc; // The RX Descriptor for this packet, to be send to Host ahead this packet + u8 *pData; // point to the head of payload of this packet + u16 Offset; // the offset from the pData to the payload buffer + _LIST list; // the link list to chain packets + u8 PktBuf[SDIO_RX_BD_BUF_SIZE]; // the Rx_Desc + payload data buffer, the first 24 bytes is reserved for RX_DESC +} SDIO_RX_PACKET, *PSDIO_RX_PACKET; +#else +typedef struct _SDIO_RX_PACKET_ { + SDIO_RX_DESC RxDesc; // The RX Descriptor for this packet, to be send to Host ahead this packet + u8 *pData; // point to the head of payload of this packet + u16 Offset; // the offset from the pData to the payload buffer + _LIST list; // the link list to chain packets + u8 isDyna; // is Dynamic allocated +} SDIO_RX_PACKET, *PSDIO_RX_PACKET; +#endif + +/* the data structer to bind a RX_BD with a RX Packet */ +typedef struct _SDIO_RX_BD_HANDLE_ { + SDIO_RX_BD *pRXBD; // Point to the RX_BD buffer + SDIO_RX_PACKET *pPkt; // point to the Rx Packet + u8 isPktEnd; // For a packet over 1 BD , this flag to indicate is this BD contains a packet end + u8 isFree; // is this RX BD free (DMA done and its RX packet has been freed) +} SDIO_RX_BD_HANDLE, *PSDIO_RX_BD_HANDLE; + +#if SDIO_MP_MODE +typedef struct _SDIO_MP_CMD_ { + u8 cmd_name[16]; + u32 cmd_type; +} SDIO_MP_CMD, *PSDIO_MP_CMD; + +typedef enum _SDIO_MP_CMD_TYPE_{ + SDIO_MP_START=1, + SDIO_MP_STOP=2, + SDIO_MP_LOOPBACK=3, + SDIO_MP_STATUS=4, + SDIO_MP_READ_REG8=5, + SDIO_MP_READ_REG16=6, + SDIO_MP_READ_REG32=7, + SDIO_MP_WRITE_REG8=8, + SDIO_MP_WRITE_REG16=9, + SDIO_MP_WRITE_REG32=10, + SDIO_MP_WAKEUP=11, // wakeup the SDIO task manually, for debugging + SDIO_MP_DUMP=12, // start/stop to dump the SDIO status periodically + SDIO_MP_CTX=13, // setup continue TX test + SDIO_MP_CRX=14, // setup continue RX test + SDIO_MP_CRX_DA=15, // setup continue RX with dynamic allocate RX Buf test + SDIO_MP_CRX_STOP=16, // setup continue RX test + SDIO_MP_DBG_MSG=17, // Debug message On/Off + +}SDIO_MP_CMD_TYPE; + +typedef enum _SDIO_CRX_MODE_{ + SDIO_CRX_STATIC_BUF = 1, + SDIO_CRX_DYNA_BUF = 2, +} SDIO_CRX_MODE; + +typedef struct _SDIO_MP_RX_PACKET_ { + _LIST list; // this member MUST be the 1st one, the link list to chain packets + u8 *pData; // point to the head of payload of this packet + u16 Offset; // the offset from the pData to the payload + u16 DataLen; // the data length of this packet +} SDIO_MP_RX_PACKET, *PSDIO_MP_RX_PACKET; + +#endif // end of '#if SDIO_MP_MODE' + +#define SDIO_CMD_TX_ETH 0x83 // request to TX a 802.3 packet +#define SDIO_CMD_TX_WLN 0x81 // request to TX a 802.11 packet +#define SDIO_CMD_H2C 0x11 // H2C(host to device) command packet +#define SDIO_CMD_MEMRD 0x51 // request to read a block of memory data +#define SDIO_CMD_MEMWR 0x53 // request to write a block of memory +#define SDIO_CMD_MEMST 0x55 // request to set a block of memory with a value +#define SDIO_CMD_STARTUP 0x61 // request to jump to the start up function + +#define SDIO_CMD_RX_ETH 0x82 // indicate a RX 802.3 packet +#define SDIO_CMD_RX_WLN 0x80 // indicate a RX 802.11 packet +#define SDIO_CMD_C2H 0x10 // C2H(device to host) command packet +#define SDIO_CMD_MEMRD_RSP 0x50 // response to memory block read command +#define SDIO_CMD_MEMWR_RSP 0x52 // response to memory write command +#define SDIO_CMD_MEMST_RSP 0x54 // response to memory set command +#define SDIO_CMD_STARTED 0x60 // indicate the program has jumped to the given function + +#ifdef CONFIG_SDIO_DEVICE_VERIFY + +#define TX_BD_STRUCTURE_NUM 10 +#define RX_BD_STRUCTURE_NUM 10 +#define TX_BD_BUFFER_SIZE 0x1000//0x2000//0x800 +#define RX_BD_BUFFER_SIZE 0x400//0x800 + +#define SDIO_RAM_ADDR_BASE 0x20080000 +#define SDIO_BUFFER_HEAD(addr) SDIO_RAM_ADDR_BASE + addr +#define HAL_SDIO_BUFFER_READ8(addr) HAL_READ8(SDIO_RAM_ADDR_BASE, addr) +#define HAL_SDIO_BUFFER_READ32(addr) HAL_READ32(SDIO_RAM_ADDR_BASE, addr) +#define HAL_SDIO_BUFFER_WRITE32(addr, value) HAL_WRITE32(SDIO_RAM_ADDR_BASE, addr, value) + +//#define RX_BD_ADDR 0x8000 +//#define RX_BUFFER_ADDR 0x8050 + +typedef enum _SDIO_TEST_FUNC_ { + SDIO_TEST_INIT, // 0 + SDIO_TEST_INT_ON, // 1 + SDIO_TEST_INT_OFF, // 2 + SDIO_HCI_RX_REQ, // 3 + SDIO_RESET_TXFIFIO, // 4 + SDIO_CPU_RST_DMA, // 5 + SDIO_CPU_CLR_INT_REG, // 6 + SDIO_TIMER_TEST, // 7 + SDIO_TEST_DEBUG, // 8 + SDIO_TEST, // 9 + SDIO_HELP = 0xff +}SDIO_TEST_FUNC, *PSDIO_TEST_FUNC; + +typedef struct _SDIO_TEST_ADAPTER_ { + u32 TXWritePtr; + u32 TXReadPtr; + u16 RXWritePtr; + u16 RXReadPtr; + u16 IntMask; + u16 IntStatus; +} SDIO_TEST_ADAPTER, *PSDIO_TEST_ADAPTER; + + +VOID +MovePKTToRX( + IN u32 Source, IN u32 Destination, IN u32 PKTSize +); + +BOOL +PacketProcess( + IN SDIO_TEST_ADAPTER *pDevStatus +); + +VOID +SdioDeviceIrqHandleFunc( + IN VOID *DATA +); + +VOID +SdioDeviceTestApp( + IN u32 Data +); + +VOID +InitRXBD(VOID); + +VOID +InitTXFIFO(VOID); + +VOID +IrqRegister(VOID); + +#endif // end of "#ifdef CONFIG_SDIO_DEVICE_VERIFY" + +#endif /* #ifndef _RTL8195A_SDIO_H_ */ diff --git a/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_sdio_host.h b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_sdio_host.h new file mode 100644 index 0000000..ee1f892 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_sdio_host.h @@ -0,0 +1,295 @@ + /* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + + +#ifndef _RTL8195A_SDIO_HOST_H_ +#define _RTL8195A_SDIO_HOST_H_ + +#include "hal_api.h" +#include "osdep_api.h" + + + + +#ifdef CONFIG_SDIO_HOST_VERIFY + +#define HAL_MMC_HOST_READ32(addr) HAL_READ32(SDIO_HOST_REG_BASE, addr) +#define HAL_MMC_HOST_WRITE32(addr, value) HAL_WRITE32(SDIO_HOST_REG_BASE, addr, value) +#define HAL_MMC_HOST_READ16(addr) HAL_READ16(SDIO_HOST_REG_BASE, addr) +#define HAL_MMC_HOST_WRITE16(addr, value) HAL_WRITE16(SDIO_HOST_REG_BASE, addr, value) +#define HAL_MMC_HOST_READ8(addr) HAL_READ8(SDIO_HOST_REG_BASE, addr) +#define HAL_MMC_HOST_WRITE8(addr, value) HAL_WRITE8(SDIO_HOST_REG_BASE, addr, value) + +/* RTL8195A Register */ +// REG_SOC_HCI_COM_FUNC_EN (0x214) +#define SD_DEVICE_IP_ON_BLK BIT0 +#define SD_DEVICE_IP_OFF_BLK BIT1 +#define SD_HOST_IP_BLK BIT2 + +// REG_PESOC_HCI_CLK_CTRL0 (0x240) +#define SD_HOST_CLKEN_IN_CPU_RUN_MODE BIT2 + +// REG_HCI_PINMUX_CTRL (0x2A0) +#define SD_DEVICE_MODE_PINMUX_EN BIT0 +#define SD_HOST_MODE_PINMUX_EN BIT1 + +// 0x40059000 +#define SD_HOST_CARD_DETECT_CIRCUIT BIT10 + + + +/* SD Host Register */ +#define REG_SDMA_SYS_ADDR_ARG 0x00 // 4byte +#define REG_BLOCK_SIZE 0x04 // 2byte +#define REG_BLOCK_COUNT 0x06 // 2byte +#define REG_ARGUMENT1 0x08 // 4byte +#define REG_TRANSFER_MODE 0x0C // 2byte +#define REG_COMMAND 0x0E // 2byte +#define REG_RESPONSE0 0x10 // 4byte +#define REG_RESPONSE2 0x14 // 4byte +#define REG_RESPONSE4 0x18 // 4byte +#define REG_RESPONSE6 0x1C // 4byte +#define REG_BUFFER_DATA_PORT 0x20 // 4byte +#define REG_PRESENT_STATE 0x24 // 4byte +#define REG_HOST_CONTROL1 0x28 // 1byte +#define REG_POWER_CONTROL 0x29 // 1byte +#define REG_BLOCK_GAP_CONTROL 0x2A // 1byte +#define REG_WAKEUP_CONTROL 0x2B // 1byte +#define REG_CLOCK_CONTROL 0x2C // 2byte +#define REG_TIMEOUT_CONTROL 0x2E // 1byte +#define REG_SW_RESET 0x2F // 1byte +#define REG_NORMAL_INT_STATUS 0x30 // 2byte +#define REG_ERROR_INT_STATUS 0x32 // 2byte +#define REG_NORMAL_INT_STATUS_ENABLE 0x34 // 2byte +#define REG_ERROR_INT_STATUS_ENABLE 0x36 // 2byte +#define REG_NORMAL_INT_SIGNAL_ENABLE 0x38 // 2byte +#define REG_ERROR_INT_SIGNAL_ENABLE 0x3A // 2byte +#define REG_CAPABILITIES 0x40 // 8byte +#define REG_ADMA_ADDRESS 0x58 // 8byte + +// Transfer Mode (0x0C) +#define BIT_DMA_EN BIT0 +#define BIT_BLK_CNT_EN BIT1 +#define BIT_AUTO_CMD12_EN BIT2 +#define BIT_AUTO_CMD23_EN BIT3 +#define BIT_READ_TRANS BIT4 +#define BIT_MULTI_BLK BIT5 + +// Present State (0x24) +#define BIT_CMD_INHIBIT_CMD BIT0 +#define BIT_CMD_INHIBIT_DAT BIT1 +#define BIT_CARD_INSERTED BIT16 +#define BIT_WRITE_PROTECT_SWITCH_PIN BIT19 + +// Power Control (0x29) +#define BIT_POWER_33 0xE +#define BIT_POWER_30 0xC +#define BIT_POWER_18 0xA + +// Clock Control (0x2C) +#define BIT_INTERNAL_CLK_EN BIT0 +#define BIT_INTERNAL_CLK_STABLE BIT1 +#define BIT_SD_CLK_EN BIT2 + +// Software Reset (0x2F) +#define BIT_SW_RESET_ALL BIT0 +#define BIT_SW_RESET_CMD_LINE BIT1 +#define BIT_SW_RESET_DAT_LINE BIT2 + +// Norma Interrupt Status (0x30) +#define BIT_COMMAND_COMPLETE BIT0 +#define BIT_TRANSFER_COMPLETE BIT1 +#define BIT_BLOCK_GAP_EVENT BIT2 +#define BIT_DMA_INT BIT3 +#define BIT_BUFFER_WRITE_RDY BIT4 +#define BIT_BUFFER_READ_RDY BIT5 +#define BIT_CARD_INSERTION BIT6 +#define BIT_CARD_REMOVAL BIT7 +#define BIT_CARD_INT BIT8 +#define BIT_ERROR_INT BIT15 + +// Error Interrupt Status (0x32) +#define BIT_DATA_TIME_OUT_ERROR BIT4 +#define BIT_DATA_CRC_ERROR BIT5 +#define BIT_ADMA_ERROR BIT9 + +// Capabilities (0x40) +#define BIT_VDD_33 BIT24 +#define BIT_VDD_30 BIT25 +#define BIT_VDD_18 BIT26 + + +#define ENABLE 1 +#define DISABLE 0 + +#define ADMA_DESC_NUM 50 + +#define BUFFER_UNIT_SIZE 512 + +typedef enum _MMC_HOST_TEST_FUNC_ { + MMC_HOST_TEST_HW_INIT, // 0 + MMC_HOST_TEST_CARD_INIT, // 1 + MMC_HOST_TEST_SEND_CMD, // 2 + MMC_HOST_TEST_DEBUG, // 3 + MMC_HOST_TEST_SW_RESET, // 4 + MMC_HOST_TEST_READ_SINGLE, // 5 + MMC_HOST_TEST_WRITE_SINGLE, // 6 + MMC_HOST_TEST_READ_MULTI, // 7 + MMC_HOST_TEST_WRITE_MULTI, // 8 + MMC_HOST_TEST_SINGLE_LONGRUN, // 9 + MMC_HOST_TEST_MULTI_LONGRUN, // 10 + MMC_HOST_TEST_CARD_DETECTION, // 11 + MMC_HOST_TEST_WRITE_PROTECT, // 12 + MMC_HOST_TEST_REGISTER_RW // 13 +}MMC_HOST_TEST_FUNC; + +typedef enum _RESPONSE_TYPE_ { + No_Response, // 00b + Response_136, // 01b + Response_48, // 10b + Response_48_Busy // 11b +}RESPONSE_TYPE; + +typedef enum _COMMAND_TYPE_ { + Normal, // 00b + Suspend, // 01b + Resume, // 10b + Abort // 11b +}COMMAND_TYPE; + +typedef enum _DATA_PRESENT_ { + No_Data_Present, // 00b + Data_Present, // 01b +}DATA_PRESENT; + +typedef enum _SUPPLY_VOLTAGE_ { + MMC_VDD_27_28 = BIT15, + MMC_VDD_28_29 = BIT16, + MMC_VDD_29_30 = BIT17, + MMC_VDD_30_31 = BIT18, + MMC_VDD_31_32 = BIT19, + MMC_VDD_32_33 = BIT20, + MMC_VDD_33_34 = BIT21, + MMC_VDD_34_35 = BIT22, + MMC_VDD_35_36 = BIT23, +}SUPPLY_VOLTAGE; + +typedef enum _COMMAND_INDEX_ { + GO_IDLE_STATE = 0, + ALL_SEND_CID = 2, + SEND_RELATIVE_ADDR = 3, + SET_BUS_WIDTH = 6, + SELECT_CARD = 7, + SEND_IF_COND = 8, + SEND_CSD = 9, + STOP_TRANSMISSION = 12, + SEND_STATUS = 13, + READ_SINGLE_BLOCK = 17, + READ_MULTIPLE_BLOCK = 18, + WRITE_BLOCK = 24, + WRITE_MULTIPLE_BLOCK = 25, + SD_SEND_OP_COND = 41, + APP_CMD = 55, +}COMMAND_INDEX; + +typedef enum _TRANSFER_CONFIG_ { + Read_Data = 0, + Write_Data = 1, + Single_Block = 0, + Multiple_Block = 1, +}TRANSFER_CONFIG; + +typedef enum _ERROR_STATUS_ { + General_Error, // 0 + CRC_Error, // 1 + TIME_OUT_ERROR, // 2 + CRC_Error_NeedCMD12, // 3 + Transfer_OK // 4 +}ERROR_STATUS; + +typedef enum _CARD_CURRENT_STATE_ { + IDLE_STATE, + READY_STATE, + IDENT_STATE, + STBY_STATE, + TRAN_STATE, + DATA_STATE, + RCV_STATE, + PRG_STATE, + DIS_STATE, + UNKNOWN_STATE +}CARD_CURRENT_STATE; + +typedef struct _COMMAND_FORMAT_ +{ + u16 Resp_Type:2; + u16 Rsvd0:1; + u16 CMD_CRC_Chk:1; + u16 CMD_Idx_Chk:1; + u16 Data_Present:1; + u16 CMD_Type:2; + u16 CMD_Idx:6; + u16 Rsvd1:2; +}COMMAND_FORMAT, *PCOMMAND_FPRMAT; + +typedef struct _MMC_COMMAND +{ + COMMAND_FORMAT Cmd_Format; + u32 Arg; +}MMC_COMMAND; + +typedef struct _MMC_HOST_ +{ + u32 OCR_Avail; + u32 Resp[4]; + u32 CID[4]; + u32 RCA; +}MMC_HOST, *PMMC_HOST; + +typedef struct _ADMA_ATTR_ +{ + u16 Valid:1; + u16 End:1; + u16 Int:1; + u16 Rsvd1:1; + u16 Act1:1; + u16 Act2:1; + u16 Rsvd2:10; +}ADMA_ATTR, *PADMA_ATTR; +// 24 bytes +typedef struct _ADMA_DESC_TABLE_ +{ + // 1st buffer desc + ADMA_ATTR Attribute1; + u16 Length1; + u32 Address1; + // 2nd buffer desc + ADMA_ATTR Attribute2; + u16 Length2; + u32 Address2; + // 3rd buffer desc + ADMA_ATTR Attribute3; + u16 Length3; + u32 Address3; +}ADMA_DESC_TABLE, *PADMA_DESC_TABLE; +// 1024 bytes +typedef struct _ADMA_BUFFER_ +{ + u8 Data1[512]; /* 1st buffer */ + u8 Data2[512]; /* 2nd buffer */ +}ADMA_BUFFER, *PADMA_BUFFER; + + +VOID +SdHostTestApp( + IN u8 *argv[] +); +#endif // end of "#ifdef CONFIG_SDIO_HOST_VERIFY" + +#endif /* #ifndef _RTL8195A_SDIO_HOST_H_ */ diff --git a/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_sdr.h b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_sdr.h new file mode 100644 index 0000000..05a13fa --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_sdr.h @@ -0,0 +1,379 @@ +#ifndef _RTL8195A_SDR_H +#define _RTL8195A_SDR_H + +#define MS_0_CTRL_BASE BSP_MS_I_DRAMC_0_BASE +#define MS_0_CTRL_PHY_BASE (BSP_MS_I_DRAMC_0_BASE) +#define MS_0_WRAP_BASE (MS_0_CTRL_BASE + 0x200) + +#define MS_1_CTRL_BASE BSP_MS_I_DRAMC_1_BASE +#define MS_1_CTRL_PHY_BASE (BSP_MS_I_DRAMC_1_BASE) +#define MS_1_WRAP_BASE (MS_1_CTRL_BASE + 0x200) + +#define MS_PCTL_CCR_OFFSET 0x000 +#define MS_PCTL_DCR_OFFSET 0x004 +#define MS_PCTL_IOCR_OFFSET 0x008 +#define MS_PCTL_CSR_OFFSET 0x00c +#define MS_PCTL_DRR_OFFSET 0x010 +#define MS_PCTL_TPR0_OFFSET 0x014 +#define MS_PCTL_TPR1_OFFSET 0x018 +#define MS_PCTL_TPR2_OFFSET 0x01c +#define MS_PCTL_MR_OFFSET 0x020 +#define MS_PCTL_EMR1_OFFSET 0x024 +#define MS_PCTL_EMR2_OFFSET 0x028 +#define MS_PCTL_EMR3_OFFSET 0x02c +#define MS_PCTL_CSR2_OFFSET 0x030 +#define MS_PCTL_SRST_OFFSET 0x034 +#define MS_PCTL_DTR2_OFFSET 0x038 +#define MS_PCTL_DTR3_OFFSET 0x03c +#define MS_PCTL_GDLLCR_OFFSET 0x040 +#define MS_PCTL_DLLCR0_OFFSET 0x044 +#define MS_PCTL_DLLCR1_OFFSET 0x048 +#define MS_PCTL_DLLCR2_OFFSET 0x04c +#define MS_PCTL_DLLCR3_OFFSET 0x050 +#define MS_PCTL_DLLCR4_OFFSET 0x054 +#define MS_PCTL_DLLCR5_OFFSET 0x058 +#define MS_PCTL_DLLCR6_OFFSET 0x05c +#define MS_PCTL_DLLCR7_OFFSET 0x060 +#define MS_PCTL_DLLCR8_OFFSET 0x064 +#define MS_PCTL_DQTR0_OFFSET 0x068 +#define MS_PCTL_DQTR1_OFFSET 0x06c +#define MS_PCTL_DQTR2_OFFSET 0x070 +#define MS_PCTL_DQTR3_OFFSET 0x074 +#define MS_PCTL_DQTR4_OFFSET 0x078 +#define MS_PCTL_DQTR5_OFFSET 0x07c +#define MS_PCTL_DQTR6_OFFSET 0x080 +#define MS_PCTL_DQTR7_OFFSET 0x084 +#define MS_PCTL_DQSTR_OFFSET 0x088 +#define MS_PCTL_DQSBTR_OFFSET 0x08c +#define MS_PCTL_ODTCR_OFFSET 0x090 +#define MS_PCTL_DTR0_OFFSET 0x094 +#define MS_PCTL_DTR1_OFFSET 0x098 +#define MS_PCTL_DTAR_OFFSET 0x09c +#define MS_PCTL_ZQCR0_OFFSET 0x0a0 +#define MS_PCTL_ZQCR1_OFFSET 0x0a4 +#define MS_PCTL_ZQSR_OFFSET 0x0a8 +#define MS_PCTL_RSLR0_OFFSET 0x0ac +#define MS_PCTL_RSLR1_OFFSET 0x0b0 +#define MS_PCTL_RSLR2_OFFSET 0x0b4 +#define MS_PCTL_RSLR3_OFFSET 0x0b8 +#define MS_PCTL_RDGR0_OFFSET 0x0bc +#define MS_PCTL_RDGR1_OFFSET 0x0c0 +#define MS_PCTL_RDGR2_OFFSET 0x0c4 +#define MS_PCTL_RDGR3_OFFSET 0x0c8 +#define MS_PCTL_MXSL_OFFSET 0x0cc + +#define MS_PCTL_BCR_OFFSET 0x0d0 +#define MS_PCTL_BALR0_OFFSET 0x0d4 +#define MS_PCTL_BALR1_OFFSET 0x0d8 +#define MS_PCTL_BDR0_OFFSET 0x0dc +#define MS_PCTL_BDR1_OFFSET 0x0e0 +#define MS_PCTL_BBR_OFFSET 0x0e4 +#define MS_PCTL_BSR_OFFSET 0x0e8 +#define MS_PCTL_BYR_OFFSET 0x0ec +#define MS_PCTL_BFA_OFFSET 0x0f0 +#define MS_PCTL_IDR_OFFSET 0x0f8 +#define MS_PCTL_ERR_OFFSET 0x0fc + +#define MS_WRAP_SCR_OFFSET 0x224 +#define MS_WRAP_QCR_OFFSET 0x230 +#define MS_WRAP_PCR_OFFSET 0x234 +#define MS_WRAP_QTR0_OFFSET 0x240 +#define MS_WRAP_QTR1_OFFSET 0x244 +#define MS_WRAP_QTR2_OFFSET 0x248 +#define MS_WRAP_QTR3_OFFSET 0x24c +#define MS_WRAP_QTR4_OFFSET 0x250 +#define MS_WRAP_QTR5_OFFSET 0x254 +#define MS_WRAP_QTR6_OFFSET 0x258 +#define MS_WRAP_QTR7_OFFSET 0x25c +#define MS_WRAP_QTR8_OFFSET 0x260 +#define MS_WRAP_QTR9_OFFSET 0x264 +#define MS_WRAP_QTR10_OFFSET 0x268 +#define MS_WRAP_QTR11_OFFSET 0x26c +#define MS_WRAP_QTR12_OFFSET 0x270 +#define MS_WRAP_QTR13_OFFSET 0x274 +#define MS_WRAP_QTR14_OFFSET 0x278 +#define MS_WRAP_QTR15_OFFSET 0x27c + +#define MS_PHY_DLY0 0x100 +#define MS_PHY_DLY1_RST 0x104 +#define MS_PHY_DLY_CLK 0x108 +#define MS_PHY_DLY_ST 0x10c +#define MS_PHY_DLY_NUM 0x100 + +#define PCTL_CCR_INIT_BFO 0 +#define PCTL_CCR_INIT_BFW 1 +#define PCTL_CCR_DTT_BFO 1 +#define PCTL_CCR_DTT_BFW 1 +#define PCTL_CCR_BTT_BFO 2 +#define PCTL_CCR_BTT_BFW 1 +#define PCTL_CCR_DPIT_BFO 3 +#define PCTL_CCR_DPIT_BFW 1 +#define PCTL_CCR_FLUSH_FIFO_BFO 8 +#define PCTL_CCR_FLUSH_FIFO_BFW 1 + +#define PCTL_DCR_DDR3_BFO 0 +#define PCTL_DCR_DDR3_BFW 1 +#define PCTL_DCR_SDR_BFO 1 +#define PCTL_DCR_SDR_BFW 1 +#define PCTL_DCR_DQ32_BFO 4 +#define PCTL_DCR_DQ32_BFW 1 +#define PCTL_DCR_DFI_RATE_BFO 8 +#define PCTL_DCR_DFI_RATE_BFW 3 + +#define PCTL_IOCR_RD_PIPE_BFO 8 +#define PCTL_IOCR_RD_PIPE_BFW 4 +#define PCTL_IOCR_TPHY_WD_BFO 12 +#define PCTL_IOCR_TPHY_WD_BFW 5 +#define PCTL_IOCR_TPHY_WL_BFO 17 +#define PCTL_IOCR_TPHY_WL_BFW 3 +#define PCTL_IOCR_TPHY_RD_EN_BFO 20 +#define PCTL_IOCR_TPHY_RD_EN_BFW 5 + +#define PCTL_CSR_MEM_IDLE_BFO 8 +#define PCTL_CSR_MEM_IDLE_BFW 1 +#define PCTL_CSR_DT_IDLE_BFO 9 +#define PCTL_CSR_DT_IDLE_BFW 1 +#define PCTL_CSR_BIST_IDLE_BFO 10 +#define PCTL_CSR_BIST_IDLE_BFW 1 +#define PCTL_CSR_DT_FAIL_BFO 11 +#define PCTL_CSR_DT_FAIL_BFW 1 +#define PCTL_CSR_BT_FAIL_BFO 12 +#define PCTL_CSR_BT_FAIL_BFW 1 + +#define PCTL_DRR_TRFC_BFO 0 +#define PCTL_DRR_TRFC_BFW 7 +#define PCTL_DRR_TREF_BFO 8 +#define PCTL_DRR_TREF_BFW 24 +#define PCTL_DRR_REF_NUM_BFO 24 +#define PCTL_DRR_REF_NUM_BFW 4 +#define PCTL_DRR_REF_DIS_BFO 28 +#define PCTL_DRR_REF_DIS_BFW 1 + +#define PCTL_TPR0_TRP_BFO 0 +#define PCTL_TPR0_TRP_BFW 4 +#define PCTL_TPR0_TRAS_BFO 4 +#define PCTL_TPR0_TRAS_BFW 5 +#define PCTL_TPR0_TWR_BFO 9 +#define PCTL_TPR0_TWR_BFW 4 +#define PCTL_TPR0_TRTP_BFO 13 +#define PCTL_TPR0_TRTP_BFW 3 + +#define PCTL_TPR1_TRRD_BFO 0 +#define PCTL_TPR1_TRRD_BFW 4 +#define PCTL_TPR1_TRC_BFO 4 +#define PCTL_TPR1_TRC_BFW 6 +#define PCTL_TPR1_TRCD_BFO 10 +#define PCTL_TPR1_TRCD_BFW 4 +#define PCTL_TPR1_TCCD_BFO 14 +#define PCTL_TPR1_TCCD_BFW 3 +#define PCTL_TPR1_TWTR_BFO 17 +#define PCTL_TPR1_TWTR_BFW 3 +#define PCTL_TPR1_TRTW_BFO 20 +#define PCTL_TPR1_TRTW_BFW 4 + +#define PCTL_TPR2_INIT_REF_NUM_BFO 0 +#define PCTL_TPR2_INIT_REF_NUM_BFW 4 +#define PCTL_TPR2_INIT_NS_EN_BFO 4 +#define PCTL_TPR2_INIT_NS_EN_BFW 1 +#define PCTL_TPR2_TMRD_BFO 5 +#define PCTL_TPR2_TMRD_BFW 2 + +#define PCTL_MR_BL_BFO 0 +#define PCTL_MR_BL_BFW 3 +#define PCTL_MR_BT_BFO 3 +#define PCTL_MR_BT_BFW 1 +#define PCTL_MR_CAS_BFO 4 +#define PCTL_MR_CAS_BFW 3 +#define PCTL_MR_OP_BFO 8 +#define PCTL_MR_OP_BFW 12 + +#define PCTL_EMR1_ADDLAT_BFO 3 +#define PCTL_EMR1_ADDLAT_BFW 3 + +#define PCTL_CMD_DPIN_RSTN_BFO 0 +#define PCTL_CMD_DPIN_RSTN_BFW 1 +#define PCTL_CMD_DPIN_CKE_BFO 1 +#define PCTL_CMD_DPIN_CKE_BFW 1 +#define PCTL_CMD_DPIN_ODT_BFO 2 +#define PCTL_CMD_DPIN_ODT_BFW 1 + +#define PCTL_BCR_STOP_BFO 0 +#define PCTL_BCR_STOP_BFW 1 +#define PCTL_BCR_CMP_BFO 1 +#define PCTL_BCR_CMP_BFW 1 +#define PCTL_BCR_LOOP_BFO 2 +#define PCTL_BCR_LOOP_BFW 1 +#define PCTL_BCR_DIS_MASK_BFO 3 +#define PCTL_BCR_DIS_MASK_BFW 1 +#define PCTL_BCR_AT_STOP_BFO 4 +#define PCTL_BCR_AT_STOP_BFW 1 +#define PCTL_BCR_FLUSH_CMD_BFO 8 +#define PCTL_BCR_FLUSH_CMD_BFW 1 +#define PCTL_BCR_FLUSH_WD_BFO 9 +#define PCTL_BCR_FLUSH_WD_BFW 1 +#define PCTL_BCR_FLUSH_RGD_BFO 10 +#define PCTL_BCR_FLUSH_RGD_BFW 1 +#define PCTL_BCR_FLUSH_RD_BFO 11 +#define PCTL_BCR_FLUSH_RD_BFW 1 +#define PCTL_BCR_FLUSH_RD_EXPC_BFO 16 +#define PCTL_BCR_FLUSH_RD_EXPC_BFW 14 + +#define PCTL_BST_ERR_FST_TH_BFO 0 +#define PCTL_BST_ERR_FST_TH_BFW 12 +#define PCTL_BST_ERR_CNT_BFO 16 +#define PCTL_BST_ERR_CNT_BFW 14 + +#define PCTL_BSRAM0_CMD_LEVEL_BFO 0 +#define PCTL_BSRAM0_CMD_LEVEL_BFW 12 +#define PCTL_BSRAM0_WD_LEVEL_BFO 16 +#define PCTL_BSRAM0_WD_LEVEL_BFW 14 + +#define PCTL_BSRAM1_RG_LEVEL_BFO 0 +#define PCTL_BSRAM1_RG_LEVEL_BFW 14 +#define PCTL_BSRAM1_RD_LEVEL_BFO 16 +#define PCTL_BSRAM1_RD_LEVEL_BFW 14 + +#define WRAP_MISC_PAGE_SIZE_BFO 0 +#define WRAP_MISC_PAGE_SIZE_BFW 4 +#define WRAP_MISC_BANK_SIZE_BFO 4 +#define WRAP_MISC_BANK_SIZE_BFW 2 +#define WRAP_MISC_BST_SIZE_BFO 6 +#define WRAP_MISC_BST_SIZE_BFW 2 +#define WRAP_MISC_DDR_PARAL_BFO 8 +#define WRAP_MISC_DDR_PARAL_BFW 1 + +struct ms_rxi310_portmap { + volatile unsigned int ccr; /* 0x000 */ + volatile unsigned int dcr; /* 0x004 */ + volatile unsigned int iocr; /* 0x008 */ + volatile unsigned int csr; /* 0x00c */ + volatile unsigned int drr; /* 0x010 */ + volatile unsigned int tpr0; /* 0x014 */ + volatile unsigned int tpr1; /* 0x018 */ + volatile unsigned int tpr2; /* 0x01c */ + volatile unsigned int mr; /* 0x020 */ + volatile unsigned int emr1; /* 0x024 */ + volatile unsigned int emr2; /* 0x028 */ + volatile unsigned int emr3; /* 0x02c */ + volatile unsigned int cdpin; /* 0x030 */ + volatile unsigned int tdpin; /* 0x034 */ + volatile unsigned int dtr2; /* 0x038 */ + volatile unsigned int dtr3; /* 0x03c */ + volatile unsigned int gdllcr; /* 0x040 */ + volatile unsigned int dllcr0; /* 0x044 */ + volatile unsigned int dllcr1; /* 0x048 */ + volatile unsigned int dllcr2; /* 0x04c */ + volatile unsigned int dllcr3; /* 0x050 */ + volatile unsigned int dllcr4; /* 0x054 */ + volatile unsigned int dllcr5; /* 0x058 */ + volatile unsigned int dllcr6; /* 0x05c */ + volatile unsigned int dllcr7; /* 0x060 */ + volatile unsigned int dllcr8; /* 0x064 */ + volatile unsigned int dqtr0; /* 0x068 */ + volatile unsigned int dqtr1; /* 0x06c */ + volatile unsigned int dqtr2; /* 0x070 */ + volatile unsigned int dqtr3; /* 0x074 */ + volatile unsigned int dqtr4; /* 0x078 */ + volatile unsigned int dqtr5; /* 0x07c */ + volatile unsigned int dqtr6; /* 0x080 */ + volatile unsigned int dqtr7; /* 0x084 */ + volatile unsigned int dqstr; /* 0x088 */ + volatile unsigned int dqsbtr; /* 0x08c */ + volatile unsigned int odtcr; /* 0x090 */ + volatile unsigned int dtr0; /* 0x094 */ + volatile unsigned int dtr1; /* 0x098 */ + volatile unsigned int dtar; /* 0x09c */ + volatile unsigned int zqcr0; /* 0x0a0 */ + volatile unsigned int zqcr1; /* 0x0a4 */ + volatile unsigned int zqsr; /* 0x0a8 */ + volatile unsigned int rslr0; /* 0x0ac */ + volatile unsigned int rslr1; /* 0x0b0 */ + volatile unsigned int rslr2; /* 0x0b4 */ + volatile unsigned int rslr3; /* 0x0b8 */ + volatile unsigned int rdgr0; /* 0x0bc */ + volatile unsigned int rdgr1; /* 0x0c0 */ + volatile unsigned int rdgr2; /* 0x0c4 */ + volatile unsigned int rdgr3; /* 0x0c8 */ + volatile unsigned int mxsl; /* 0x0cc */ + volatile unsigned int bcr; /* 0x0d0 */ + volatile unsigned int bst; /* 0x0d4 */ + volatile unsigned int bsram0; /* 0x0d8 */ + volatile unsigned int bsram1; /* 0x0dc */ + volatile unsigned int bdr1; /* 0x0e0 */ + volatile unsigned int bbr; /* 0x0e4 */ + volatile unsigned int bsr; /* 0x0e8 */ + volatile unsigned int byr; /* 0x0ec */ + volatile unsigned int bfa; /* 0x0f0 */ + volatile unsigned int pctl_svn; /* 0x0f4 */ + volatile unsigned int pctl_idr; /* 0x0f8 */ + volatile unsigned int err; /* 0x0fc */ + + // SDR_PHY CONTROL REGISTER + volatile unsigned int phy_dly0; /* 0x100 */ + volatile unsigned int phy_dly1_rst; /* 0x104 */ + volatile unsigned int phy_dly_clk; /* 0x108 */ + volatile unsigned int phy_dly_st; /* 0x10c */ + volatile unsigned int phy_dly_num; /* 0x110 */ + volatile unsigned int reserved0[68]; + + // WRAP CONTROL REGISTER + volatile unsigned int misc; /* 0x224 */ + volatile unsigned int cq_ver; /* 0x228 */ + volatile unsigned int cq_mon; /* 0x22c */ + volatile unsigned int wq_ver; /* 0x230 */ + volatile unsigned int wq_mon; /* 0x234 */ + volatile unsigned int rq_ver; /* 0x240 */ + volatile unsigned int rq_mon; /* 0x244 */ + volatile unsigned int reserved1[22]; + volatile unsigned int wwrap_idr; /* 0x2a0 */ + volatile unsigned int wrap_svn; /* 0x2a4 */ + +}; //ms_rxi310_portmap + +#define QFIFO_CMD_BANK_BFO (35 - QFIFO_CMD_WRRD_BFO) // [38:35] +#define QFIFO_CMD_BANK_BFW 4 +#define QFIFO_CMD_PAGE_BFO (20 - QFIFO_CMD_WRRD_BFO) // [34:20] +#define QFIFO_CMD_PAGE_BFW 15 +#define QFIFO_CMD_COLU_BFO (7 - QFIFO_CMD_WRRD_BFO) // [19: 7] +#define QFIFO_CMD_COLU_BFW 13 // [19: 7] +#define QFIFO_BST_LEN_BFO (3 - QFIFO_CMD_WRRD_BFO) // [6:3] +#define QFIFO_BST_LEN_BFW 4 // [6:3] +#define QFIFO_CMD_WRRD_BFO 2 // [2], remove bit[1:0] +#define QFIFO_CMD_WRRD_BFW 1 // [2], remove bit[1:0] + +//====================================================// + +#define REG_SDR_CCR 0x00 +#define REG_SDR_DCR 0x04 +#define REG_SDR_IOCR 0x08 +#define REG_SDR_CSR 0x0C +#define REG_SDR_DRR 0x10 +#define REG_SDR_TPR0 0x14 +#define REG_SDR_TPR1 0x18 +#define REG_SDR_TPR2 0x1C +#define REG_SDR_MR 0x20 +#define REG_SDR_EMR1 0x24 +#define REG_SDR_EMR2 0x28 +#define REG_SDR_EMR3 0x2C +#define REG_SDR_CMD_DPIN 0x30 +#define REG_SDR_TIE_DPIN 0x34 +#define REG_SDR_BCR 0xD0 +#define REG_SDR_BST 0xD4 +#define REG_SDR_BSRAM0 0xD8 +#define REG_SDR_BSRAM1 0xDC +#define REG_SDR_PCTL_SVN_ID 0xF4 +#define REG_SDR_PCTL_IDR 0xF8 +#define REG_SDR_DLY0 0x100 + +#define REG_SDR_DLY1 0x104 +#define REG_SDR_DCM_RST 0x104 + +#define REG_SDR_DLY_CLK_PHA 0x108 +#define REG_SDR_DLY_ST 0x10C + +#define REG_SDR_MISC 0x224 +#define REG_SDR_OCP_WRAP_IDR 0x2A0 +#define REG_SDR_OCP_WRAP_VERSION 0x2A4 + + +#endif // end of "#ifndef _RTL8195A_SDR_H" diff --git a/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_spi_flash.h b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_spi_flash.h new file mode 100644 index 0000000..1ac2c16 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_spi_flash.h @@ -0,0 +1,990 @@ +#ifndef _RTL8195A_SPI_FLASH_H +#define _RTL8195A_SPI_FLASH_H + +#define CPU_OPT_WIDTH 0x1F + +//2 REG_NOT_VALID + +//2 REG_SPIC_CTRLR0 + +#define BIT_SHIFT_CK_MTIMES 23 +#define BIT_MASK_CK_MTIMES 0x1f +#define BIT_CK_MTIMES(x) (((x) & BIT_MASK_CK_MTIMES) << BIT_SHIFT_CK_MTIMES) +#define BIT_CTRL_CK_MTIMES(x) (((x) & BIT_MASK_CK_MTIMES) << BIT_SHIFT_CK_MTIMES) +#define BIT_GET_CK_MTIMES(x) (((x) >> BIT_SHIFT_CK_MTIMES) & BIT_MASK_CK_MTIMES) + +#define BIT_FAST_RD BIT(22) +#define BIT_SHIFT_FAST_RD 22 +#define BIT_MASK_FAST_RD 0x1 +#define BIT_CTRL_FAST_RD(x) (((x) & BIT_MASK_FAST_RD) << BIT_SHIFT_FAST_RD) + + +#define BIT_SHIFT_CMD_CH 20 +#define BIT_MASK_CMD_CH 0x3 +#define BIT_CMD_CH(x) (((x) & BIT_MASK_CMD_CH) << BIT_SHIFT_CMD_CH) +#define BIT_CTRL_CMD_CH(x) (((x) & BIT_MASK_CMD_CH) << BIT_SHIFT_CMD_CH) +#define BIT_GET_CMD_CH(x) (((x) >> BIT_SHIFT_CMD_CH) & BIT_MASK_CMD_CH) + + +#define BIT_SHIFT_DATA_CH 18 +#define BIT_MASK_DATA_CH 0x3 +#define BIT_DATA_CH(x) (((x) & BIT_MASK_DATA_CH) << BIT_SHIFT_DATA_CH) +#define BIT_CTRL_DATA_CH(x) (((x) & BIT_MASK_DATA_CH) << BIT_SHIFT_DATA_CH) +#define BIT_GET_DATA_CH(x) (((x) >> BIT_SHIFT_DATA_CH) & BIT_MASK_DATA_CH) + + +#define BIT_SHIFT_ADDR_CH 16 +#define BIT_MASK_ADDR_CH 0x3 +#define BIT_ADDR_CH(x) (((x) & BIT_MASK_ADDR_CH) << BIT_SHIFT_ADDR_CH) +#define BIT_CTRL_ADDR_CH(x) (((x) & BIT_MASK_ADDR_CH) << BIT_SHIFT_ADDR_CH) +#define BIT_GET_ADDR_CH(x) (((x) >> BIT_SHIFT_ADDR_CH) & BIT_MASK_ADDR_CH) + + +#define BIT_SHIFT_TMOD 8 +#define BIT_MASK_TMOD 0x3 +#define BIT_TMOD(x) (((x) & BIT_MASK_TMOD) << BIT_SHIFT_TMOD) +#define BIT_CTRL_TMOD(x) (((x) & BIT_MASK_TMOD) << BIT_SHIFT_TMOD) +#define BIT_GET_TMOD(x) (((x) >> BIT_SHIFT_TMOD) & BIT_MASK_TMOD) + +#define BIT_SCPOL BIT(7) +#define BIT_SHIFT_SCPOL 7 +#define BIT_MASK_SCPOL 0x1 +#define BIT_CTRL_SCPOL(x) (((x) & BIT_MASK_SCPOL) << BIT_SHIFT_SCPOL) + +#define BIT_SCPH BIT(6) +#define BIT_SHIFT_SCPH 6 +#define BIT_MASK_SCPH 0x1 +#define BIT_CTRL_SCPH(x) (((x) & BIT_MASK_SCPH) << BIT_SHIFT_SCPH) + +//2 REG_SPIC_CTRLR1 + +#define BIT_SHIFT_NDF 0 +#define BIT_MASK_NDF 0xfff +#define BIT_NDF(x) (((x) & BIT_MASK_NDF) << BIT_SHIFT_NDF) +#define BIT_CTRL_NDF(x) (((x) & BIT_MASK_NDF) << BIT_SHIFT_NDF) +#define BIT_GET_NDF(x) (((x) >> BIT_SHIFT_NDF) & BIT_MASK_NDF) + + +//2 REG_SPIC_SSIENR +#define BIT_ATCK_CMD BIT(1) +#define BIT_SHIFT_ATCK_CMD 1 +#define BIT_MASK_ATCK_CMD 0x1 +#define BIT_CTRL_ATCK_CMD(x) (((x) & BIT_MASK_ATCK_CMD) << BIT_SHIFT_ATCK_CMD) + +#define BIT_SPIC_EN BIT(0) +#define BIT_SHIFT_SPIC_EN 0 +#define BIT_MASK_SPIC_EN 0x1 +#define BIT_CTRL_SPIC_EN(x) (((x) & BIT_MASK_SPIC_EN) << BIT_SHIFT_SPIC_EN) + +//2 REG_SPIC_MWCR + +//2 REG_SPIC_SER +#define BIT_SER BIT(0) +#define BIT_SHIFT_SER 0 +#define BIT_MASK_SER 0x1 +#define BIT_CTRL_SER(x) (((x) & BIT_MASK_SER) << BIT_SHIFT_SER) + +//2 REG_SPIC_BAUDR + +#define BIT_SHIFT_SCKDV 0 +#define BIT_MASK_SCKDV 0xffff +#define BIT_SCKDV(x) (((x) & BIT_MASK_SCKDV) << BIT_SHIFT_SCKDV) +#define BIT_CTRL_SCKDV(x) (((x) & BIT_MASK_SCKDV) << BIT_SHIFT_SCKDV) +#define BIT_GET_SCKDV(x) (((x) >> BIT_SHIFT_SCKDV) & BIT_MASK_SCKDV) + + +//2 REG_SPIC_TXFTLR + +#define BIT_SHIFT_TFT 0 +#define BIT_MASK_TFT 0x1f +#define BIT_TFT(x) (((x) & BIT_MASK_TFT) << BIT_SHIFT_TFT) +#define BIT_CTRL_TFT(x) (((x) & BIT_MASK_TFT) << BIT_SHIFT_TFT) +#define BIT_GET_TFT(x) (((x) >> BIT_SHIFT_TFT) & BIT_MASK_TFT) + + +//2 REG_SPIC_RXFTLR + +#define BIT_SHIFT_RFT 0 +#define BIT_MASK_RFT 0x1f +#define BIT_RFT(x) (((x) & BIT_MASK_RFT) << BIT_SHIFT_RFT) +#define BIT_CTRL_RFT(x) (((x) & BIT_MASK_RFT) << BIT_SHIFT_RFT) +#define BIT_GET_RFT(x) (((x) >> BIT_SHIFT_RFT) & BIT_MASK_RFT) + + +//2 REG_SPIC_TXFLR + +#define BIT_SHIFT_TXFL 0 +#define BIT_MASK_TXFL 0x3f +#define BIT_TXFL(x) (((x) & BIT_MASK_TXFL) << BIT_SHIFT_TXFL) +#define BIT_CTRL_TXFL(x) (((x) & BIT_MASK_TXFL) << BIT_SHIFT_TXFL) +#define BIT_GET_TXFL(x) (((x) >> BIT_SHIFT_TXFL) & BIT_MASK_TXFL) + + +//2 REG_SPIC_RXFLR + +#define BIT_SHIFT_RXFL 0 +#define BIT_MASK_RXFL 0x3f +#define BIT_RXFL(x) (((x) & BIT_MASK_RXFL) << BIT_SHIFT_RXFL) +#define BIT_CTRL_RXFL(x) (((x) & BIT_MASK_RXFL) << BIT_SHIFT_RXFL) +#define BIT_GET_RXFL(x) (((x) >> BIT_SHIFT_RXFL) & BIT_MASK_RXFL) + + +//2 REG_SPIC_SR +#define BIT_TXE BIT(5) +#define BIT_SHIFT_TXE 5 +#define BIT_MASK_TXE 0x1 +#define BIT_CTRL_TXE(x) (((x) & BIT_MASK_TXE) << BIT_SHIFT_TXE) + +#define BIT_RFF BIT(4) +#define BIT_SHIFT_RFF 4 +#define BIT_MASK_RFF 0x1 +#define BIT_CTRL_RFF(x) (((x) & BIT_MASK_RFF) << BIT_SHIFT_RFF) + +#define BIT_RFNE BIT(3) +#define BIT_SHIFT_RFNE 3 +#define BIT_MASK_RFNE 0x1 +#define BIT_CTRL_RFNE(x) (((x) & BIT_MASK_RFNE) << BIT_SHIFT_RFNE) + +#define BIT_TFE BIT(2) +#define BIT_SHIFT_TFE 2 +#define BIT_MASK_TFE 0x1 +#define BIT_CTRL_TFE(x) (((x) & BIT_MASK_TFE) << BIT_SHIFT_TFE) + +#define BIT_TFNF BIT(1) +#define BIT_SHIFT_TFNF 1 +#define BIT_MASK_TFNF 0x1 +#define BIT_CTRL_TFNF(x) (((x) & BIT_MASK_TFNF) << BIT_SHIFT_TFNF) + +#define BIT_BUSY BIT(0) +#define BIT_SHIFT_BUSY 0 +#define BIT_MASK_BUSY 0x1 +#define BIT_CTRL_BUSY(x) (((x) & BIT_MASK_BUSY) << BIT_SHIFT_BUSY) + +//2 REG_SPIC_IMR +#define BIT_TXSIM BIT(9) +#define BIT_SHIFT_TXSIM 9 +#define BIT_MASK_TXSIM 0x1 +#define BIT_CTRL_TXSIM(x) (((x) & BIT_MASK_TXSIM) << BIT_SHIFT_TXSIM) + +#define BIT_ACEIM BIT(8) +#define BIT_SHIFT_ACEIM 8 +#define BIT_MASK_ACEIM 0x1 +#define BIT_CTRL_ACEIM(x) (((x) & BIT_MASK_ACEIM) << BIT_SHIFT_ACEIM) + +#define BIT_BYEIM BIT(7) +#define BIT_SHIFT_BYEIM 7 +#define BIT_MASK_BYEIM 0x1 +#define BIT_CTRL_BYEIM(x) (((x) & BIT_MASK_BYEIM) << BIT_SHIFT_BYEIM) + +#define BIT_WBEIM BIT(6) +#define BIT_SHIFT_WBEIM 6 +#define BIT_MASK_WBEIM 0x1 +#define BIT_CTRL_WBEIM(x) (((x) & BIT_MASK_WBEIM) << BIT_SHIFT_WBEIM) + +#define BIT_FSEIM BIT(5) +#define BIT_SHIFT_FSEIM 5 +#define BIT_MASK_FSEIM 0x1 +#define BIT_CTRL_FSEIM(x) (((x) & BIT_MASK_FSEIM) << BIT_SHIFT_FSEIM) + +#define BIT_RXFIM BIT(4) +#define BIT_SHIFT_RXFIM 4 +#define BIT_MASK_RXFIM 0x1 +#define BIT_CTRL_RXFIM(x) (((x) & BIT_MASK_RXFIM) << BIT_SHIFT_RXFIM) + +#define BIT_RXOIM BIT(3) +#define BIT_SHIFT_RXOIM 3 +#define BIT_MASK_RXOIM 0x1 +#define BIT_CTRL_RXOIM(x) (((x) & BIT_MASK_RXOIM) << BIT_SHIFT_RXOIM) + +#define BIT_RXUIM BIT(2) +#define BIT_SHIFT_RXUIM 2 +#define BIT_MASK_RXUIM 0x1 +#define BIT_CTRL_RXUIM(x) (((x) & BIT_MASK_RXUIM) << BIT_SHIFT_RXUIM) + +#define BIT_TXOIM BIT(1) +#define BIT_SHIFT_TXOIM 1 +#define BIT_MASK_TXOIM 0x1 +#define BIT_CTRL_TXOIM(x) (((x) & BIT_MASK_TXOIM) << BIT_SHIFT_TXOIM) + +#define BIT_TXEIM BIT(0) +#define BIT_SHIFT_TXEIM 0 +#define BIT_MASK_TXEIM 0x1 +#define BIT_CTRL_TXEIM(x) (((x) & BIT_MASK_TXEIM) << BIT_SHIFT_TXEIM) + +//2 REG_SPIC_ISR +#define BIT_TXSIS BIT(9) +#define BIT_SHIFT_TXSIS 9 +#define BIT_MASK_TXSIS 0x1 +#define BIT_CTRL_TXSIS(x) (((x) & BIT_MASK_TXSIS) << BIT_SHIFT_TXSIS) + +#define BIT_ACEIS BIT(8) +#define BIT_SHIFT_ACEIS 8 +#define BIT_MASK_ACEIS 0x1 +#define BIT_CTRL_ACEIS(x) (((x) & BIT_MASK_ACEIS) << BIT_SHIFT_ACEIS) + +#define BIT_BYEIS BIT(7) +#define BIT_SHIFT_BYEIS 7 +#define BIT_MASK_BYEIS 0x1 +#define BIT_CTRL_BYEIS(x) (((x) & BIT_MASK_BYEIS) << BIT_SHIFT_BYEIS) + +#define BIT_WBEIS BIT(6) +#define BIT_SHIFT_WBEIS 6 +#define BIT_MASK_WBEIS 0x1 +#define BIT_CTRL_WBEIS(x) (((x) & BIT_MASK_WBEIS) << BIT_SHIFT_WBEIS) + +#define BIT_FSEIS BIT(5) +#define BIT_SHIFT_FSEIS 5 +#define BIT_MASK_FSEIS 0x1 +#define BIT_CTRL_FSEIS(x) (((x) & BIT_MASK_FSEIS) << BIT_SHIFT_FSEIS) + +#define BIT_RXFIS BIT(4) +#define BIT_SHIFT_RXFIS 4 +#define BIT_MASK_RXFIS 0x1 +#define BIT_CTRL_RXFIS(x) (((x) & BIT_MASK_RXFIS) << BIT_SHIFT_RXFIS) + +#define BIT_RXOIS BIT(3) +#define BIT_SHIFT_RXOIS 3 +#define BIT_MASK_RXOIS 0x1 +#define BIT_CTRL_RXOIS(x) (((x) & BIT_MASK_RXOIS) << BIT_SHIFT_RXOIS) + +#define BIT_RXUIS BIT(2) +#define BIT_SHIFT_RXUIS 2 +#define BIT_MASK_RXUIS 0x1 +#define BIT_CTRL_RXUIS(x) (((x) & BIT_MASK_RXUIS) << BIT_SHIFT_RXUIS) + +#define BIT_TXOIS BIT(1) +#define BIT_SHIFT_TXOIS 1 +#define BIT_MASK_TXOIS 0x1 +#define BIT_CTRL_TXOIS(x) (((x) & BIT_MASK_TXOIS) << BIT_SHIFT_TXOIS) + +#define BIT_TXEIS BIT(0) +#define BIT_SHIFT_TXEIS 0 +#define BIT_MASK_TXEIS 0x1 +#define BIT_CTRL_TXEIS(x) (((x) & BIT_MASK_TXEIS) << BIT_SHIFT_TXEIS) + +//2 REG_SPIC_RISR +#define BIT_ACEIR BIT(8) +#define BIT_SHIFT_ACEIR 8 +#define BIT_MASK_ACEIR 0x1 +#define BIT_CTRL_ACEIR(x) (((x) & BIT_MASK_ACEIR) << BIT_SHIFT_ACEIR) + +#define BIT_BYEIR BIT(7) +#define BIT_SHIFT_BYEIR 7 +#define BIT_MASK_BYEIR 0x1 +#define BIT_CTRL_BYEIR(x) (((x) & BIT_MASK_BYEIR) << BIT_SHIFT_BYEIR) + +#define BIT_WBEIR BIT(6) +#define BIT_SHIFT_WBEIR 6 +#define BIT_MASK_WBEIR 0x1 +#define BIT_CTRL_WBEIR(x) (((x) & BIT_MASK_WBEIR) << BIT_SHIFT_WBEIR) + +#define BIT_FSEIR BIT(5) +#define BIT_SHIFT_FSEIR 5 +#define BIT_MASK_FSEIR 0x1 +#define BIT_CTRL_FSEIR(x) (((x) & BIT_MASK_FSEIR) << BIT_SHIFT_FSEIR) + +#define BIT_RXFIR BIT(4) +#define BIT_SHIFT_RXFIR 4 +#define BIT_MASK_RXFIR 0x1 +#define BIT_CTRL_RXFIR(x) (((x) & BIT_MASK_RXFIR) << BIT_SHIFT_RXFIR) + +#define BIT_RXOIR BIT(3) +#define BIT_SHIFT_RXOIR 3 +#define BIT_MASK_RXOIR 0x1 +#define BIT_CTRL_RXOIR(x) (((x) & BIT_MASK_RXOIR) << BIT_SHIFT_RXOIR) + +#define BIT_RXUIR BIT(2) +#define BIT_SHIFT_RXUIR 2 +#define BIT_MASK_RXUIR 0x1 +#define BIT_CTRL_RXUIR(x) (((x) & BIT_MASK_RXUIR) << BIT_SHIFT_RXUIR) + +#define BIT_TXOIR BIT(1) +#define BIT_SHIFT_TXOIR 1 +#define BIT_MASK_TXOIR 0x1 +#define BIT_CTRL_TXOIR(x) (((x) & BIT_MASK_TXOIR) << BIT_SHIFT_TXOIR) + +#define BIT_TXEIR BIT(0) +#define BIT_SHIFT_TXEIR 0 +#define BIT_MASK_TXEIR 0x1 +#define BIT_CTRL_TXEIR(x) (((x) & BIT_MASK_TXEIR) << BIT_SHIFT_TXEIR) + +//2 REG_SPIC_TXOICR +#define BIT_TXOICR BIT(0) +#define BIT_SHIFT_TXOICR 0 +#define BIT_MASK_TXOICR 0x1 +#define BIT_CTRL_TXOICR(x) (((x) & BIT_MASK_TXOICR) << BIT_SHIFT_TXOICR) + +//2 REG_SPIC_RXOICR +#define BIT_RXOCIR BIT(0) +#define BIT_SHIFT_RXOCIR 0 +#define BIT_MASK_RXOCIR 0x1 +#define BIT_CTRL_RXOCIR(x) (((x) & BIT_MASK_RXOCIR) << BIT_SHIFT_RXOCIR) + +//2 REG_SPC_RXUICR +#define BIT_RXUICR BIT(0) +#define BIT_SHIFT_RXUICR 0 +#define BIT_MASK_RXUICR 0x1 +#define BIT_CTRL_RXUICR(x) (((x) & BIT_MASK_RXUICR) << BIT_SHIFT_RXUICR) + +//2 REG_SPIC_MSTICR +#define BIT_MSTICR BIT(0) +#define BIT_SHIFT_MSTICR 0 +#define BIT_MASK_MSTICR 0x1 +#define BIT_CTRL_MSTICR(x) (((x) & BIT_MASK_MSTICR) << BIT_SHIFT_MSTICR) + +//2 REG_SPIC_ICR + +#define BIT_SHIFT_ICR 0 +#define BIT_MASK_ICR 0xff +#define BIT_ICR(x) (((x) & BIT_MASK_ICR) << BIT_SHIFT_ICR) +#define BIT_CTRL_ICR(x) (((x) & BIT_MASK_ICR) << BIT_SHIFT_ICR) +#define BIT_GET_ICR(x) (((x) >> BIT_SHIFT_ICR) & BIT_MASK_ICR) + + +//2 REG_SPIC_DMACR + +//2 REG_SPIC_DMATDLR0 + +//2 REG_SPIC_DMATDLR1 + +//2 REG_SPIC_IDR + +#define BIT_SHIFT_IDCODE 0 +#define BIT_MASK_IDCODE 0xffffffffL +#define BIT_IDCODE(x) (((x) & BIT_MASK_IDCODE) << BIT_SHIFT_IDCODE) +#define BIT_CTRL_IDCODE(x) (((x) & BIT_MASK_IDCODE) << BIT_SHIFT_IDCODE) +#define BIT_GET_IDCODE(x) (((x) >> BIT_SHIFT_IDCODE) & BIT_MASK_IDCODE) + + +//2 REG_SPIC_VERSION + +#define BIT_SHIFT_SPIC_VERSION 0 +#define BIT_MASK_SPIC_VERSION 0xffffffffL +#define BIT_SPIC_VERSION(x) (((x) & BIT_MASK_SPIC_VERSION) << BIT_SHIFT_SPIC_VERSION) +#define BIT_CTRL_SPIC_VERSION(x) (((x) & BIT_MASK_SPIC_VERSION) << BIT_SHIFT_SPIC_VERSION) +#define BIT_GET_SPIC_VERSION(x) (((x) >> BIT_SHIFT_SPIC_VERSION) & BIT_MASK_SPIC_VERSION) + + +//2 REG_SPIC_DR0 + +#define BIT_SHIFT_DR0 0 +#define BIT_MASK_DR0 0xffffffffL +#define BIT_DR0(x) (((x) & BIT_MASK_DR0) << BIT_SHIFT_DR0) +#define BIT_CTRL_DR0(x) (((x) & BIT_MASK_DR0) << BIT_SHIFT_DR0) +#define BIT_GET_DR0(x) (((x) >> BIT_SHIFT_DR0) & BIT_MASK_DR0) + + +//2 REG_SPIC_DR1 + +#define BIT_SHIFT_DR1 0 +#define BIT_MASK_DR1 0xffffffffL +#define BIT_DR1(x) (((x) & BIT_MASK_DR1) << BIT_SHIFT_DR1) +#define BIT_CTRL_DR1(x) (((x) & BIT_MASK_DR1) << BIT_SHIFT_DR1) +#define BIT_GET_DR1(x) (((x) >> BIT_SHIFT_DR1) & BIT_MASK_DR1) + + +//2 REG_SPIC_DR2 + +#define BIT_SHIFT_DR2 0 +#define BIT_MASK_DR2 0xffffffffL +#define BIT_DR2(x) (((x) & BIT_MASK_DR2) << BIT_SHIFT_DR2) +#define BIT_CTRL_DR2(x) (((x) & BIT_MASK_DR2) << BIT_SHIFT_DR2) +#define BIT_GET_DR2(x) (((x) >> BIT_SHIFT_DR2) & BIT_MASK_DR2) + + +//2 REG_SPIC_DR3 + +#define BIT_SHIFT_DR3 0 +#define BIT_MASK_DR3 0xffffffffL +#define BIT_DR3(x) (((x) & BIT_MASK_DR3) << BIT_SHIFT_DR3) +#define BIT_CTRL_DR3(x) (((x) & BIT_MASK_DR3) << BIT_SHIFT_DR3) +#define BIT_GET_DR3(x) (((x) >> BIT_SHIFT_DR3) & BIT_MASK_DR3) + + +//2 REG_SPIC_DR4 + +#define BIT_SHIFT_DR4 0 +#define BIT_MASK_DR4 0xffffffffL +#define BIT_DR4(x) (((x) & BIT_MASK_DR4) << BIT_SHIFT_DR4) +#define BIT_CTRL_DR4(x) (((x) & BIT_MASK_DR4) << BIT_SHIFT_DR4) +#define BIT_GET_DR4(x) (((x) >> BIT_SHIFT_DR4) & BIT_MASK_DR4) + + +//2 REG_SPIC_DR5 + +#define BIT_SHIFT_DR5 0 +#define BIT_MASK_DR5 0xffffffffL +#define BIT_DR5(x) (((x) & BIT_MASK_DR5) << BIT_SHIFT_DR5) +#define BIT_CTRL_DR5(x) (((x) & BIT_MASK_DR5) << BIT_SHIFT_DR5) +#define BIT_GET_DR5(x) (((x) >> BIT_SHIFT_DR5) & BIT_MASK_DR5) + + +//2 REG_SPIC_DR6 + +#define BIT_SHIFT_DR6 0 +#define BIT_MASK_DR6 0xffffffffL +#define BIT_DR6(x) (((x) & BIT_MASK_DR6) << BIT_SHIFT_DR6) +#define BIT_CTRL_DR6(x) (((x) & BIT_MASK_DR6) << BIT_SHIFT_DR6) +#define BIT_GET_DR6(x) (((x) >> BIT_SHIFT_DR6) & BIT_MASK_DR6) + + +//2 REG_SPIC_DR7 + +#define BIT_SHIFT_DR7 0 +#define BIT_MASK_DR7 0xffffffffL +#define BIT_DR7(x) (((x) & BIT_MASK_DR7) << BIT_SHIFT_DR7) +#define BIT_CTRL_DR7(x) (((x) & BIT_MASK_DR7) << BIT_SHIFT_DR7) +#define BIT_GET_DR7(x) (((x) >> BIT_SHIFT_DR7) & BIT_MASK_DR7) + + +//2 REG_SPIC_DR8 + +#define BIT_SHIFT_DR8 0 +#define BIT_MASK_DR8 0xffffffffL +#define BIT_DR8(x) (((x) & BIT_MASK_DR8) << BIT_SHIFT_DR8) +#define BIT_CTRL_DR8(x) (((x) & BIT_MASK_DR8) << BIT_SHIFT_DR8) +#define BIT_GET_DR8(x) (((x) >> BIT_SHIFT_DR8) & BIT_MASK_DR8) + + +//2 REG_SPIC_DR9 + +#define BIT_SHIFT_DR9 0 +#define BIT_MASK_DR9 0xffffffffL +#define BIT_DR9(x) (((x) & BIT_MASK_DR9) << BIT_SHIFT_DR9) +#define BIT_CTRL_DR9(x) (((x) & BIT_MASK_DR9) << BIT_SHIFT_DR9) +#define BIT_GET_DR9(x) (((x) >> BIT_SHIFT_DR9) & BIT_MASK_DR9) + + +//2 REG_SPIC_DR10 + +#define BIT_SHIFT_DR10 0 +#define BIT_MASK_DR10 0xffffffffL +#define BIT_DR10(x) (((x) & BIT_MASK_DR10) << BIT_SHIFT_DR10) +#define BIT_CTRL_DR10(x) (((x) & BIT_MASK_DR10) << BIT_SHIFT_DR10) +#define BIT_GET_DR10(x) (((x) >> BIT_SHIFT_DR10) & BIT_MASK_DR10) + + +//2 REG_SPIC_DR11 + +#define BIT_SHIFT_DR11 0 +#define BIT_MASK_DR11 0xffffffffL +#define BIT_DR11(x) (((x) & BIT_MASK_DR11) << BIT_SHIFT_DR11) +#define BIT_CTRL_DR11(x) (((x) & BIT_MASK_DR11) << BIT_SHIFT_DR11) +#define BIT_GET_DR11(x) (((x) >> BIT_SHIFT_DR11) & BIT_MASK_DR11) + + +//2 REG_SPIC_DR12 + +#define BIT_SHIFT_DR12 0 +#define BIT_MASK_DR12 0xffffffffL +#define BIT_DR12(x) (((x) & BIT_MASK_DR12) << BIT_SHIFT_DR12) +#define BIT_CTRL_DR12(x) (((x) & BIT_MASK_DR12) << BIT_SHIFT_DR12) +#define BIT_GET_DR12(x) (((x) >> BIT_SHIFT_DR12) & BIT_MASK_DR12) + + +//2 REG_SPIC_DR13 + +#define BIT_SHIFT_DR13 0 +#define BIT_MASK_DR13 0xffffffffL +#define BIT_DR13(x) (((x) & BIT_MASK_DR13) << BIT_SHIFT_DR13) +#define BIT_CTRL_DR13(x) (((x) & BIT_MASK_DR13) << BIT_SHIFT_DR13) +#define BIT_GET_DR13(x) (((x) >> BIT_SHIFT_DR13) & BIT_MASK_DR13) + + +//2 REG_SPIC_DR14 + +#define BIT_SHIFT_DR14 0 +#define BIT_MASK_DR14 0xffffffffL +#define BIT_DR14(x) (((x) & BIT_MASK_DR14) << BIT_SHIFT_DR14) +#define BIT_CTRL_DR14(x) (((x) & BIT_MASK_DR14) << BIT_SHIFT_DR14) +#define BIT_GET_DR14(x) (((x) >> BIT_SHIFT_DR14) & BIT_MASK_DR14) + + +//2 REG_SPIC_DR15 + +#define BIT_SHIFT_DR15 0 +#define BIT_MASK_DR15 0xffffffffL +#define BIT_DR15(x) (((x) & BIT_MASK_DR15) << BIT_SHIFT_DR15) +#define BIT_CTRL_DR15(x) (((x) & BIT_MASK_DR15) << BIT_SHIFT_DR15) +#define BIT_GET_DR15(x) (((x) >> BIT_SHIFT_DR15) & BIT_MASK_DR15) + + +//2 REG_SPIC_DR16 + +#define BIT_SHIFT_DR16 0 +#define BIT_MASK_DR16 0xffffffffL +#define BIT_DR16(x) (((x) & BIT_MASK_DR16) << BIT_SHIFT_DR16) +#define BIT_CTRL_DR16(x) (((x) & BIT_MASK_DR16) << BIT_SHIFT_DR16) +#define BIT_GET_DR16(x) (((x) >> BIT_SHIFT_DR16) & BIT_MASK_DR16) + + +//2 REG_SPIC_DR17 + +#define BIT_SHIFT_DR17 0 +#define BIT_MASK_DR17 0xffffffffL +#define BIT_DR17(x) (((x) & BIT_MASK_DR17) << BIT_SHIFT_DR17) +#define BIT_CTRL_DR17(x) (((x) & BIT_MASK_DR17) << BIT_SHIFT_DR17) +#define BIT_GET_DR17(x) (((x) >> BIT_SHIFT_DR17) & BIT_MASK_DR17) + + +//2 REG_SPIC_DR18 + +#define BIT_SHIFT_DR18 0 +#define BIT_MASK_DR18 0xffffffffL +#define BIT_DR18(x) (((x) & BIT_MASK_DR18) << BIT_SHIFT_DR18) +#define BIT_CTRL_DR18(x) (((x) & BIT_MASK_DR18) << BIT_SHIFT_DR18) +#define BIT_GET_DR18(x) (((x) >> BIT_SHIFT_DR18) & BIT_MASK_DR18) + + +//2 REG_SPIC_DR19 + +#define BIT_SHIFT_DR19 0 +#define BIT_MASK_DR19 0xffffffffL +#define BIT_DR19(x) (((x) & BIT_MASK_DR19) << BIT_SHIFT_DR19) +#define BIT_CTRL_DR19(x) (((x) & BIT_MASK_DR19) << BIT_SHIFT_DR19) +#define BIT_GET_DR19(x) (((x) >> BIT_SHIFT_DR19) & BIT_MASK_DR19) + + +//2 REG_SPIC_DR20 + +#define BIT_SHIFT_DR20 0 +#define BIT_MASK_DR20 0xffffffffL +#define BIT_DR20(x) (((x) & BIT_MASK_DR20) << BIT_SHIFT_DR20) +#define BIT_CTRL_DR20(x) (((x) & BIT_MASK_DR20) << BIT_SHIFT_DR20) +#define BIT_GET_DR20(x) (((x) >> BIT_SHIFT_DR20) & BIT_MASK_DR20) + + +//2 REG_SPIC_DR21 + +#define BIT_SHIFT_DR21 0 +#define BIT_MASK_DR21 0xffffffffL +#define BIT_DR21(x) (((x) & BIT_MASK_DR21) << BIT_SHIFT_DR21) +#define BIT_CTRL_DR21(x) (((x) & BIT_MASK_DR21) << BIT_SHIFT_DR21) +#define BIT_GET_DR21(x) (((x) >> BIT_SHIFT_DR21) & BIT_MASK_DR21) + + +//2 REG_SPIC_DR22 + +#define BIT_SHIFT_DR22 0 +#define BIT_MASK_DR22 0xffffffffL +#define BIT_DR22(x) (((x) & BIT_MASK_DR22) << BIT_SHIFT_DR22) +#define BIT_CTRL_DR22(x) (((x) & BIT_MASK_DR22) << BIT_SHIFT_DR22) +#define BIT_GET_DR22(x) (((x) >> BIT_SHIFT_DR22) & BIT_MASK_DR22) + + +//2 REG_SPIC_DR23 + +#define BIT_SHIFT_DR23 0 +#define BIT_MASK_DR23 0xffffffffL +#define BIT_DR23(x) (((x) & BIT_MASK_DR23) << BIT_SHIFT_DR23) +#define BIT_CTRL_DR23(x) (((x) & BIT_MASK_DR23) << BIT_SHIFT_DR23) +#define BIT_GET_DR23(x) (((x) >> BIT_SHIFT_DR23) & BIT_MASK_DR23) + + +//2 REG_SPIC_DR24 + +#define BIT_SHIFT_DR24 0 +#define BIT_MASK_DR24 0xffffffffL +#define BIT_DR24(x) (((x) & BIT_MASK_DR24) << BIT_SHIFT_DR24) +#define BIT_CTRL_DR24(x) (((x) & BIT_MASK_DR24) << BIT_SHIFT_DR24) +#define BIT_GET_DR24(x) (((x) >> BIT_SHIFT_DR24) & BIT_MASK_DR24) + + +//2 REG_SPIC_DR25 + +#define BIT_SHIFT_DR25 0 +#define BIT_MASK_DR25 0xffffffffL +#define BIT_DR25(x) (((x) & BIT_MASK_DR25) << BIT_SHIFT_DR25) +#define BIT_CTRL_DR25(x) (((x) & BIT_MASK_DR25) << BIT_SHIFT_DR25) +#define BIT_GET_DR25(x) (((x) >> BIT_SHIFT_DR25) & BIT_MASK_DR25) + + +//2 REG_SPIC_DR26 + +#define BIT_SHIFT_DR26 0 +#define BIT_MASK_DR26 0xffffffffL +#define BIT_DR26(x) (((x) & BIT_MASK_DR26) << BIT_SHIFT_DR26) +#define BIT_CTRL_DR26(x) (((x) & BIT_MASK_DR26) << BIT_SHIFT_DR26) +#define BIT_GET_DR26(x) (((x) >> BIT_SHIFT_DR26) & BIT_MASK_DR26) + + +//2 REG_SPIC_DR27 + +#define BIT_SHIFT_DR27 0 +#define BIT_MASK_DR27 0xffffffffL +#define BIT_DR27(x) (((x) & BIT_MASK_DR27) << BIT_SHIFT_DR27) +#define BIT_CTRL_DR27(x) (((x) & BIT_MASK_DR27) << BIT_SHIFT_DR27) +#define BIT_GET_DR27(x) (((x) >> BIT_SHIFT_DR27) & BIT_MASK_DR27) + + +//2 REG_SPIC_DR28 + +#define BIT_SHIFT_DR28 0 +#define BIT_MASK_DR28 0xffffffffL +#define BIT_DR28(x) (((x) & BIT_MASK_DR28) << BIT_SHIFT_DR28) +#define BIT_CTRL_DR28(x) (((x) & BIT_MASK_DR28) << BIT_SHIFT_DR28) +#define BIT_GET_DR28(x) (((x) >> BIT_SHIFT_DR28) & BIT_MASK_DR28) + + +//2 REG_SPIC_DR29 + +#define BIT_SHIFT_DR29 0 +#define BIT_MASK_DR29 0xffffffffL +#define BIT_DR29(x) (((x) & BIT_MASK_DR29) << BIT_SHIFT_DR29) +#define BIT_CTRL_DR29(x) (((x) & BIT_MASK_DR29) << BIT_SHIFT_DR29) +#define BIT_GET_DR29(x) (((x) >> BIT_SHIFT_DR29) & BIT_MASK_DR29) + + +//2 REG_SPIC_DR30 + +#define BIT_SHIFT_DR30 0 +#define BIT_MASK_DR30 0xffffffffL +#define BIT_DR30(x) (((x) & BIT_MASK_DR30) << BIT_SHIFT_DR30) +#define BIT_CTRL_DR30(x) (((x) & BIT_MASK_DR30) << BIT_SHIFT_DR30) +#define BIT_GET_DR30(x) (((x) >> BIT_SHIFT_DR30) & BIT_MASK_DR30) + + +//2 REG_SPIC_DR31 + +#define BIT_SHIFT_DR31 0 +#define BIT_MASK_DR31 0xffffffffL +#define BIT_DR31(x) (((x) & BIT_MASK_DR31) << BIT_SHIFT_DR31) +#define BIT_CTRL_DR31(x) (((x) & BIT_MASK_DR31) << BIT_SHIFT_DR31) +#define BIT_GET_DR31(x) (((x) >> BIT_SHIFT_DR31) & BIT_MASK_DR31) + + +//2 REG_SPIC_READ_FAST_SINGLE + +#define BIT_SHIFT_FRD_CMD 0 +#define BIT_MASK_FRD_CMD 0xff +#define BIT_FRD_CMD(x) (((x) & BIT_MASK_FRD_CMD) << BIT_SHIFT_FRD_CMD) +#define BIT_CTRL_FRD_CMD(x) (((x) & BIT_MASK_FRD_CMD) << BIT_SHIFT_FRD_CMD) +#define BIT_GET_FRD_CMD(x) (((x) >> BIT_SHIFT_FRD_CMD) & BIT_MASK_FRD_CMD) + + +//2 REG_SPIC_READ_DUAL_DATA + +#define BIT_SHIFT_RD_DUAL_O_CMD 0 +#define BIT_MASK_RD_DUAL_O_CMD 0xff +#define BIT_RD_DUAL_O_CMD(x) (((x) & BIT_MASK_RD_DUAL_O_CMD) << BIT_SHIFT_RD_DUAL_O_CMD) +#define BIT_CTRL_RD_DUAL_O_CMD(x) (((x) & BIT_MASK_RD_DUAL_O_CMD) << BIT_SHIFT_RD_DUAL_O_CMD) +#define BIT_GET_RD_DUAL_O_CMD(x) (((x) >> BIT_SHIFT_RD_DUAL_O_CMD) & BIT_MASK_RD_DUAL_O_CMD) + + +//2 REG_SPIC_READ_DUAL_ADDR_DATA + +#define BIT_SHIFT_RD_DUAL_IO_CMD 0 +#define BIT_MASK_RD_DUAL_IO_CMD 0xff +#define BIT_RD_DUAL_IO_CMD(x) (((x) & BIT_MASK_RD_DUAL_IO_CMD) << BIT_SHIFT_RD_DUAL_IO_CMD) +#define BIT_CTRL_RD_DUAL_IO_CMD(x) (((x) & BIT_MASK_RD_DUAL_IO_CMD) << BIT_SHIFT_RD_DUAL_IO_CMD) +#define BIT_GET_RD_DUAL_IO_CMD(x) (((x) >> BIT_SHIFT_RD_DUAL_IO_CMD) & BIT_MASK_RD_DUAL_IO_CMD) + + +//2 REG_SPIC_READ_QUAD_DATA + +#define BIT_SHIFT_RD_QUAD_O_CMD 0 +#define BIT_MASK_RD_QUAD_O_CMD 0xff +#define BIT_RD_QUAD_O_CMD(x) (((x) & BIT_MASK_RD_QUAD_O_CMD) << BIT_SHIFT_RD_QUAD_O_CMD) +#define BIT_CTRL_RD_QUAD_O_CMD(x) (((x) & BIT_MASK_RD_QUAD_O_CMD) << BIT_SHIFT_RD_QUAD_O_CMD) +#define BIT_GET_RD_QUAD_O_CMD(x) (((x) >> BIT_SHIFT_RD_QUAD_O_CMD) & BIT_MASK_RD_QUAD_O_CMD) + + +//2 REG_SPIC_READ_QUAD_ADDR_DATA + +#define BIT_SHIFT_RD_QUAD_IO_CMD 0 +#define BIT_MASK_RD_QUAD_IO_CMD 0xff +#define BIT_RD_QUAD_IO_CMD(x) (((x) & BIT_MASK_RD_QUAD_IO_CMD) << BIT_SHIFT_RD_QUAD_IO_CMD) +#define BIT_CTRL_RD_QUAD_IO_CMD(x) (((x) & BIT_MASK_RD_QUAD_IO_CMD) << BIT_SHIFT_RD_QUAD_IO_CMD) +#define BIT_GET_RD_QUAD_IO_CMD(x) (((x) >> BIT_SHIFT_RD_QUAD_IO_CMD) & BIT_MASK_RD_QUAD_IO_CMD) + + +//2 REG_SPIC_WRITE_SIGNLE + +#define BIT_SHIFT_WR_CMD 0 +#define BIT_MASK_WR_CMD 0xff +#define BIT_WR_CMD(x) (((x) & BIT_MASK_WR_CMD) << BIT_SHIFT_WR_CMD) +#define BIT_CTRL_WR_CMD(x) (((x) & BIT_MASK_WR_CMD) << BIT_SHIFT_WR_CMD) +#define BIT_GET_WR_CMD(x) (((x) >> BIT_SHIFT_WR_CMD) & BIT_MASK_WR_CMD) + + +//2 REG_SPIC_WRITE_DUAL_DATA + +#define BIT_SHIFT_WR_DUAL_I_CMD 0 +#define BIT_MASK_WR_DUAL_I_CMD 0xff +#define BIT_WR_DUAL_I_CMD(x) (((x) & BIT_MASK_WR_DUAL_I_CMD) << BIT_SHIFT_WR_DUAL_I_CMD) +#define BIT_CTRL_WR_DUAL_I_CMD(x) (((x) & BIT_MASK_WR_DUAL_I_CMD) << BIT_SHIFT_WR_DUAL_I_CMD) +#define BIT_GET_WR_DUAL_I_CMD(x) (((x) >> BIT_SHIFT_WR_DUAL_I_CMD) & BIT_MASK_WR_DUAL_I_CMD) + + +//2 REG_SPIC_WRITE_DUAL_ADDR_DATA + +#define BIT_SHIFT_WR_DUAL_II_CMD 0 +#define BIT_MASK_WR_DUAL_II_CMD 0xff +#define BIT_WR_DUAL_II_CMD(x) (((x) & BIT_MASK_WR_DUAL_II_CMD) << BIT_SHIFT_WR_DUAL_II_CMD) +#define BIT_CTRL_WR_DUAL_II_CMD(x) (((x) & BIT_MASK_WR_DUAL_II_CMD) << BIT_SHIFT_WR_DUAL_II_CMD) +#define BIT_GET_WR_DUAL_II_CMD(x) (((x) >> BIT_SHIFT_WR_DUAL_II_CMD) & BIT_MASK_WR_DUAL_II_CMD) + + +//2 REG_SPIC_WRITE_QUAD_DATA + +#define BIT_SHIFT_WR_QUAD_I_CMD 0 +#define BIT_MASK_WR_QUAD_I_CMD 0xff +#define BIT_WR_QUAD_I_CMD(x) (((x) & BIT_MASK_WR_QUAD_I_CMD) << BIT_SHIFT_WR_QUAD_I_CMD) +#define BIT_CTRL_WR_QUAD_I_CMD(x) (((x) & BIT_MASK_WR_QUAD_I_CMD) << BIT_SHIFT_WR_QUAD_I_CMD) +#define BIT_GET_WR_QUAD_I_CMD(x) (((x) >> BIT_SHIFT_WR_QUAD_I_CMD) & BIT_MASK_WR_QUAD_I_CMD) + + +//2 REG_SPIC_WRITE_QUAD_ADDR_DATA + +#define BIT_SHIFT_WR_QUAD_II_CMD 0 +#define BIT_MASK_WR_QUAD_II_CMD 0xff +#define BIT_WR_QUAD_II_CMD(x) (((x) & BIT_MASK_WR_QUAD_II_CMD) << BIT_SHIFT_WR_QUAD_II_CMD) +#define BIT_CTRL_WR_QUAD_II_CMD(x) (((x) & BIT_MASK_WR_QUAD_II_CMD) << BIT_SHIFT_WR_QUAD_II_CMD) +#define BIT_GET_WR_QUAD_II_CMD(x) (((x) >> BIT_SHIFT_WR_QUAD_II_CMD) & BIT_MASK_WR_QUAD_II_CMD) + + +//2 REG_SPIC_WRITE_ENABLE + +#define BIT_SHIFT_WR_EN_CMD 0 +#define BIT_MASK_WR_EN_CMD 0xff +#define BIT_WR_EN_CMD(x) (((x) & BIT_MASK_WR_EN_CMD) << BIT_SHIFT_WR_EN_CMD) +#define BIT_CTRL_WR_EN_CMD(x) (((x) & BIT_MASK_WR_EN_CMD) << BIT_SHIFT_WR_EN_CMD) +#define BIT_GET_WR_EN_CMD(x) (((x) >> BIT_SHIFT_WR_EN_CMD) & BIT_MASK_WR_EN_CMD) + + +//2 REG_SPIC_READ_STATUS + +#define BIT_SHIFT_RD_ST_CMD 0 +#define BIT_MASK_RD_ST_CMD 0xff +#define BIT_RD_ST_CMD(x) (((x) & BIT_MASK_RD_ST_CMD) << BIT_SHIFT_RD_ST_CMD) +#define BIT_CTRL_RD_ST_CMD(x) (((x) & BIT_MASK_RD_ST_CMD) << BIT_SHIFT_RD_ST_CMD) +#define BIT_GET_RD_ST_CMD(x) (((x) >> BIT_SHIFT_RD_ST_CMD) & BIT_MASK_RD_ST_CMD) + + +//2 REG_SPIC_CTRLR2 + +#define BIT_SHIFT_FIFO_ENTRY 4 +#define BIT_MASK_FIFO_ENTRY 0xf +#define BIT_FIFO_ENTRY(x) (((x) & BIT_MASK_FIFO_ENTRY) << BIT_SHIFT_FIFO_ENTRY) +#define BIT_CTRL_FIFO_ENTRY(x) (((x) & BIT_MASK_FIFO_ENTRY) << BIT_SHIFT_FIFO_ENTRY) +#define BIT_GET_FIFO_ENTRY(x) (((x) >> BIT_SHIFT_FIFO_ENTRY) & BIT_MASK_FIFO_ENTRY) + +#define BIT_WR_SEQ BIT(3) +#define BIT_SHIFT_WR_SEQ 3 +#define BIT_MASK_WR_SEQ 0x1 +#define BIT_CTRL_WR_SEQ(x) (((x) & BIT_MASK_WR_SEQ) << BIT_SHIFT_WR_SEQ) + +#define BIT_WPN_DNUM BIT(2) +#define BIT_SHIFT_WPN_DNUM 2 +#define BIT_MASK_WPN_DNUM 0x1 +#define BIT_CTRL_WPN_DNUM(x) (((x) & BIT_MASK_WPN_DNUM) << BIT_SHIFT_WPN_DNUM) + +#define BIT_WPN_SET BIT(1) +#define BIT_SHIFT_WPN_SET 1 +#define BIT_MASK_WPN_SET 0x1 +#define BIT_CTRL_WPN_SET(x) (((x) & BIT_MASK_WPN_SET) << BIT_SHIFT_WPN_SET) + +#define BIT_SO_DUM BIT(0) +#define BIT_SHIFT_SO_DUM 0 +#define BIT_MASK_SO_DUM 0x1 +#define BIT_CTRL_SO_DUM(x) (((x) & BIT_MASK_SO_DUM) << BIT_SHIFT_SO_DUM) + +//2 REG_SPIC_FBAUDR + +#define BIT_SHIFT_FSCKDV 0 +#define BIT_MASK_FSCKDV 0xfff +#define BIT_FSCKDV(x) (((x) & BIT_MASK_FSCKDV) << BIT_SHIFT_FSCKDV) +#define BIT_CTRL_FSCKDV(x) (((x) & BIT_MASK_FSCKDV) << BIT_SHIFT_FSCKDV) +#define BIT_GET_FSCKDV(x) (((x) >> BIT_SHIFT_FSCKDV) & BIT_MASK_FSCKDV) + + +//2 REG_SPIC_ADDR_LENGTH + +#define BIT_SHIFT_ADDR_PHASE_LENGTH 0 +#define BIT_MASK_ADDR_PHASE_LENGTH 0x3 +#define BIT_ADDR_PHASE_LENGTH(x) (((x) & BIT_MASK_ADDR_PHASE_LENGTH) << BIT_SHIFT_ADDR_PHASE_LENGTH) +#define BIT_CTRL_ADDR_PHASE_LENGTH(x) (((x) & BIT_MASK_ADDR_PHASE_LENGTH) << BIT_SHIFT_ADDR_PHASE_LENGTH) +#define BIT_GET_ADDR_PHASE_LENGTH(x) (((x) >> BIT_SHIFT_ADDR_PHASE_LENGTH) & BIT_MASK_ADDR_PHASE_LENGTH) + + +//2 REG_SPIC_AUTO_LENGTH + +#define BIT_SHIFT_CS_H_WR_DUM_LEN 28 +#define BIT_MASK_CS_H_WR_DUM_LEN 0xf +#define BIT_CS_H_WR_DUM_LEN(x) (((x) & BIT_MASK_CS_H_WR_DUM_LEN) << BIT_SHIFT_CS_H_WR_DUM_LEN) +#define BIT_CTRL_CS_H_WR_DUM_LEN(x) (((x) & BIT_MASK_CS_H_WR_DUM_LEN) << BIT_SHIFT_CS_H_WR_DUM_LEN) +#define BIT_GET_CS_H_WR_DUM_LEN(x) (((x) >> BIT_SHIFT_CS_H_WR_DUM_LEN) & BIT_MASK_CS_H_WR_DUM_LEN) + + +#define BIT_SHIFT_CS_H_RD_DUM_LEN 26 +#define BIT_MASK_CS_H_RD_DUM_LEN 0x3 +#define BIT_CS_H_RD_DUM_LEN(x) (((x) & BIT_MASK_CS_H_RD_DUM_LEN) << BIT_SHIFT_CS_H_RD_DUM_LEN) +#define BIT_CTRL_CS_H_RD_DUM_LEN(x) (((x) & BIT_MASK_CS_H_RD_DUM_LEN) << BIT_SHIFT_CS_H_RD_DUM_LEN) +#define BIT_GET_CS_H_RD_DUM_LEN(x) (((x) >> BIT_SHIFT_CS_H_RD_DUM_LEN) & BIT_MASK_CS_H_RD_DUM_LEN) + + +#define BIT_SHIFT_AUTO_DUM_LEN 18 +#define BIT_MASK_AUTO_DUM_LEN 0xff +#define BIT_AUTO_DUM_LEN(x) (((x) & BIT_MASK_AUTO_DUM_LEN) << BIT_SHIFT_AUTO_DUM_LEN) +#define BIT_CTRL_AUTO_DUM_LEN(x) (((x) & BIT_MASK_AUTO_DUM_LEN) << BIT_SHIFT_AUTO_DUM_LEN) +#define BIT_GET_AUTO_DUM_LEN(x) (((x) >> BIT_SHIFT_AUTO_DUM_LEN) & BIT_MASK_AUTO_DUM_LEN) + + +#define BIT_SHIFT_AUTO_ADDR__LENGTH 16 +#define BIT_MASK_AUTO_ADDR__LENGTH 0x3 +#define BIT_AUTO_ADDR__LENGTH(x) (((x) & BIT_MASK_AUTO_ADDR__LENGTH) << BIT_SHIFT_AUTO_ADDR__LENGTH) +#define BIT_CTRL_AUTO_ADDR__LENGTH(x) (((x) & BIT_MASK_AUTO_ADDR__LENGTH) << BIT_SHIFT_AUTO_ADDR__LENGTH) +#define BIT_GET_AUTO_ADDR__LENGTH(x) (((x) >> BIT_SHIFT_AUTO_ADDR__LENGTH) & BIT_MASK_AUTO_ADDR__LENGTH) + + +#define BIT_SHIFT_RD_DUMMY_LENGTH 0 +#define BIT_MASK_RD_DUMMY_LENGTH 0xffff +#define BIT_RD_DUMMY_LENGTH(x) (((x) & BIT_MASK_RD_DUMMY_LENGTH) << BIT_SHIFT_RD_DUMMY_LENGTH) +#define BIT_CTRL_RD_DUMMY_LENGTH(x) (((x) & BIT_MASK_RD_DUMMY_LENGTH) << BIT_SHIFT_RD_DUMMY_LENGTH) +#define BIT_GET_RD_DUMMY_LENGTH(x) (((x) >> BIT_SHIFT_RD_DUMMY_LENGTH) & BIT_MASK_RD_DUMMY_LENGTH) + + +//2 REG_SPIC_VALID_CMD +#define BIT_WR_BLOCKING BIT(9) +#define BIT_SHIFT_WR_BLOCKING 9 +#define BIT_MASK_WR_BLOCKING 0x1 +#define BIT_CTRL_WR_BLOCKING(x) (((x) & BIT_MASK_WR_BLOCKING) << BIT_SHIFT_WR_BLOCKING) + +#define BIT_WR_QUAD_II BIT(8) +#define BIT_SHIFT_WR_QUAD_II 8 +#define BIT_MASK_WR_QUAD_II 0x1 +#define BIT_CTRL_WR_QUAD_II(x) (((x) & BIT_MASK_WR_QUAD_II) << BIT_SHIFT_WR_QUAD_II) + +#define BIT_WR_QUAD_I BIT(7) +#define BIT_SHIFT_WR_QUAD_I 7 +#define BIT_MASK_WR_QUAD_I 0x1 +#define BIT_CTRL_WR_QUAD_I(x) (((x) & BIT_MASK_WR_QUAD_I) << BIT_SHIFT_WR_QUAD_I) + +#define BIT_WR_DUAL_II BIT(6) +#define BIT_SHIFT_WR_DUAL_II 6 +#define BIT_MASK_WR_DUAL_II 0x1 +#define BIT_CTRL_WR_DUAL_II(x) (((x) & BIT_MASK_WR_DUAL_II) << BIT_SHIFT_WR_DUAL_II) + +#define BIT_WR_DUAL_I BIT(5) +#define BIT_SHIFT_WR_DUAL_I 5 +#define BIT_MASK_WR_DUAL_I 0x1 +#define BIT_CTRL_WR_DUAL_I(x) (((x) & BIT_MASK_WR_DUAL_I) << BIT_SHIFT_WR_DUAL_I) + +#define BIT_RD_QUAD_IO BIT(4) +#define BIT_SHIFT_RD_QUAD_IO 4 +#define BIT_MASK_RD_QUAD_IO 0x1 +#define BIT_CTRL_RD_QUAD_IO(x) (((x) & BIT_MASK_RD_QUAD_IO) << BIT_SHIFT_RD_QUAD_IO) + +#define BIT_RD_QUAD_O BIT(3) +#define BIT_SHIFT_RD_QUAD_O 3 +#define BIT_MASK_RD_QUAD_O 0x1 +#define BIT_CTRL_RD_QUAD_O(x) (((x) & BIT_MASK_RD_QUAD_O) << BIT_SHIFT_RD_QUAD_O) + +#define BIT_RD_DUAL_IO BIT(2) +#define BIT_SHIFT_RD_DUAL_IO 2 +#define BIT_MASK_RD_DUAL_IO 0x1 +#define BIT_CTRL_RD_DUAL_IO(x) (((x) & BIT_MASK_RD_DUAL_IO) << BIT_SHIFT_RD_DUAL_IO) + +#define BIT_RD_DUAL_I BIT(1) +#define BIT_SHIFT_RD_DUAL_I 1 +#define BIT_MASK_RD_DUAL_I 0x1 +#define BIT_CTRL_RD_DUAL_I(x) (((x) & BIT_MASK_RD_DUAL_I) << BIT_SHIFT_RD_DUAL_I) + +#define BIT_FRD_SINGEL BIT(0) +#define BIT_SHIFT_FRD_SINGEL 0 +#define BIT_MASK_FRD_SINGEL 0x1 +#define BIT_CTRL_FRD_SINGEL(x) (((x) & BIT_MASK_FRD_SINGEL) << BIT_SHIFT_FRD_SINGEL) + +//2 REG_SPIC_FLASE_SIZE + +#define BIT_SHIFT_FLASE_SIZE 0 +#define BIT_MASK_FLASE_SIZE 0xf +#define BIT_FLASE_SIZE(x) (((x) & BIT_MASK_FLASE_SIZE) << BIT_SHIFT_FLASE_SIZE) +#define BIT_CTRL_FLASE_SIZE(x) (((x) & BIT_MASK_FLASE_SIZE) << BIT_SHIFT_FLASE_SIZE) +#define BIT_GET_FLASE_SIZE(x) (((x) >> BIT_SHIFT_FLASE_SIZE) & BIT_MASK_FLASE_SIZE) + + +//2 REG_SPIC_FLUSH_FIFO +#define BIT_FLUSH_FIFO BIT(0) +#define BIT_SHIFT_FLUSH_FIFO 0 +#define BIT_MASK_FLUSH_FIFO 0x1 +#define BIT_CTRL_FLUSH_FIFO(x) (((x) & BIT_MASK_FLUSH_FIFO) << BIT_SHIFT_FLUSH_FIFO) + +//=================== Register Address Definition ============================// +#define REG_SPIC_CTRLR0 0x0000//O +#define REG_SPIC_CTRLR1 0x0004//O +#define REG_SPIC_SSIENR 0x0008//O +#define REG_SPIC_MWCR 0x000C +#define REG_SPIC_SER 0x0010//O +#define REG_SPIC_BAUDR 0x0014//O +#define REG_SPIC_TXFTLR 0x0018 +#define REG_SPIC_RXFTLR 0x001C//O +#define REG_SPIC_TXFLR 0x0020//O +#define REG_SPIC_RXFLR 0x0024 +#define REG_SPIC_SR 0x0028 +#define REG_SPIC_IMR 0x002C//O +#define REG_SPIC_ISR 0x0030 +#define REG_SPIC_RISR 0x0034 +#define REG_SPIC_TXOICR 0x0038 +#define REG_SPIC_RXOICR 0x003C +#define REG_SPC_RXUICR 0x0040 +#define REG_SPIC_MSTICR 0x0044 +#define REG_SPIC_ICR 0x0048 +#define REG_SPIC_DMACR 0x004C +#define REG_SPIC_DMATDLR0 0x0050 +#define REG_SPIC_DMATDLR1 0x0054 +#define REG_SPIC_IDR 0x0058 +#define REG_SPIC_VERSION 0x005C +#define REG_SPIC_DR0 0x0060 +#define REG_SPIC_DR1 0x0064 +#define REG_SPIC_DR2 0x0068 +#define REG_SPIC_DR3 0x006C +#define REG_SPIC_DR4 0x0070 +#define REG_SPIC_DR5 0x0074 +#define REG_SPIC_DR6 0x0078 +#define REG_SPIC_DR7 0x007C +#define REG_SPIC_DR8 0x0080 +#define REG_SPIC_DR9 0x0084 +#define REG_SPIC_DR10 0x0088 +#define REG_SPIC_DR11 0x008C +#define REG_SPIC_DR12 0x0090 +#define REG_SPIC_DR13 0x0094 +#define REG_SPIC_DR14 0x0098 +#define REG_SPIC_DR15 0x009C +#define REG_SPIC_DR16 0x00A0 +#define REG_SPIC_DR17 0x00A4 +#define REG_SPIC_DR18 0x00A8 +#define REG_SPIC_DR19 0x00AC +#define REG_SPIC_DR20 0x00B0 +#define REG_SPIC_DR21 0x00B4 +#define REG_SPIC_DR22 0x00B8 +#define REG_SPIC_DR23 0x00BC +#define REG_SPIC_DR24 0x00C0 +#define REG_SPIC_DR25 0x00C4 +#define REG_SPIC_DR26 0x00C8 +#define REG_SPIC_DR27 0x00CC +#define REG_SPIC_DR28 0x00D0 +#define REG_SPIC_DR29 0x00D4 +#define REG_SPIC_DR30 0x00D8 +#define REG_SPIC_DR31 0x00DC +#define REG_SPIC_READ_FAST_SINGLE 0x00E0//O +#define REG_SPIC_READ_DUAL_DATA 0x00E4//O +#define REG_SPIC_READ_DUAL_ADDR_DATA 0x00E8//O +#define REG_SPIC_READ_QUAD_DATA 0x00EC//O +#define REG_SPIC_READ_QUAD_ADDR_DATA 0x00F0//O +#define REG_SPIC_WRITE_SIGNLE 0x00F4//O +#define REG_SPIC_WRITE_DUAL_DATA 0x00F8//O +#define REG_SPIC_WRITE_DUAL_ADDR_DATA 0x00FC//O +#define REG_SPIC_WRITE_QUAD_DATA 0x0100//O +#define REG_SPIC_WRITE_QUAD_ADDR_DATA 0x0104//O +#define REG_SPIC_WRITE_ENABLE 0x0108//O +#define REG_SPIC_READ_STATUS 0x010C//O +#define REG_SPIC_CTRLR2 0x0110//O +#define REG_SPIC_FBAUDR 0x0114//O +#define REG_SPIC_ADDR_LENGTH 0x0118//O +#define REG_SPIC_AUTO_LENGTH 0x011C//O +#define REG_SPIC_VALID_CMD 0x0120//O +#define REG_SPIC_FLASE_SIZE 0x0124//O +#define REG_SPIC_FLUSH_FIFO 0x0128//O + +#endif // end of "#ifndef _RTL8195A_SPI_FLASH_H" diff --git a/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_ssi.h b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_ssi.h new file mode 100644 index 0000000..1611401 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_ssi.h @@ -0,0 +1,495 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#ifndef _RTL8195A_SSI_H_ +#define _RTL8195A_SSI_H_ + +#define SSI_DUMMY_DATA 0x00 // for master mode, we need to push a Dummy data to TX FIFO for read + +#define SSI_CLK_SPI1 (PLATFORM_CLOCK/2) +#define SSI_CLK_SPI0_2 (PLATFORM_CLOCK/4) + +/* Parameters of DW_apb_ssi for RTL8195A */ +#define SSI_TX_FIFO_DEPTH 64 +#define TX_ABW 6 // 1-8, log2(SSI_TX_FIFO_DEPTH) +#define SSI_RX_FIFO_DEPTH 64 +#define RX_ABW 6 // 1-8, log2(SSI_RX_FIFO_DEPTH) + +#define SSI0_REG_BASE 0x40042000 +#define SSI1_REG_BASE 0x40042400 +#define SSI2_REG_BASE 0x40042800 + +/* Memory Map of DW_apb_ssi */ +#define REG_DW_SSI_CTRLR0 0x00 // 16 bits +#define REG_DW_SSI_CTRLR1 0x04 // 16 bits +#define REG_DW_SSI_SSIENR 0x08 // 1 bit +#define REG_DW_SSI_MWCR 0x0C // 3 bits +#define REG_DW_SSI_SER 0x10 // +#define REG_DW_SSI_BAUDR 0x14 // 16 bits +#define REG_DW_SSI_TXFTLR 0x18 // TX_ABW +#define REG_DW_SSI_RXFTLR 0x1C // RX_ABW +#define REG_DW_SSI_TXFLR 0x20 // +#define REG_DW_SSI_RXFLR 0x24 // +#define REG_DW_SSI_SR 0x28 // 7 bits +#define REG_DW_SSI_IMR 0x2C // +#define REG_DW_SSI_ISR 0x30 // 6 bits +#define REG_DW_SSI_RISR 0x34 // 6 bits +#define REG_DW_SSI_TXOICR 0x38 // 1 bits +#define REG_DW_SSI_RXOICR 0x3C // 1 bits +#define REG_DW_SSI_RXUICR 0x40 // 1 bits +#define REG_DW_SSI_MSTICR 0x44 // 1 bits +#define REG_DW_SSI_ICR 0x48 // 1 bits +#define REG_DW_SSI_DMACR 0x4C // 2 bits +#define REG_DW_SSI_DMATDLR 0x50 // TX_ABW +#define REG_DW_SSI_DMARDLR 0x54 // RX_ABW +#define REG_DW_SSI_IDR 0x58 // 32 bits +#define REG_DW_SSI_COMP_VERSION 0x5C // 32 bits +#define REG_DW_SSI_DR 0x60 // 16 bits 0x60-0xEC +#define REG_DW_SSI_RX_SAMPLE_DLY 0xF0 // 8 bits +#define REG_DW_SSI_RSVD_0 0xF4 // 32 bits +#define REG_DW_SSI_RSVD_1 0xF8 // 32 bits +#define REG_DW_SSI_RSVD_2 0xFC // 32 bits + +// CTRLR0 0x00 // 16 bits, 6.2.1 +// DFS Reset Value: 0x7 +#define BIT_SHIFT_CTRLR0_DFS 0 +#define BIT_MASK_CTRLR0_DFS 0xF +#define BIT_CTRLR0_DFS(x)(((x) & BIT_MASK_CTRLR0_DFS) << BIT_SHIFT_CTRLR0_DFS) +#define BIT_INVC_CTRLR0_DFS (~(BIT_MASK_CTRLR0_DFS << BIT_SHIFT_CTRLR0_DFS)) + +#define BIT_SHIFT_CTRLR0_FRF 4 +#define BIT_MASK_CTRLR0_FRF 0x3 +#define BIT_CTRLR0_FRF(x)(((x) & BIT_MASK_CTRLR0_FRF) << BIT_SHIFT_CTRLR0_FRF) +#define BIT_INVC_CTRLR0_FRF (~(BIT_MASK_CTRLR0_FRF << BIT_SHIFT_CTRLR0_FRF)) + +#define BIT_SHIFT_CTRLR0_SCPH 6 +#define BIT_MASK_CTRLR0_SCPH 0x1 +#define BIT_CTRLR0_SCPH(x)(((x) & BIT_MASK_CTRLR0_SCPH) << BIT_SHIFT_CTRLR0_SCPH) +#define BIT_INVC_CTRLR0_SCPH (~(BIT_MASK_CTRLR0_SCPH << BIT_SHIFT_CTRLR0_SCPH)) + +#define BIT_SHIFT_CTRLR0_SCPOL 7 +#define BIT_MASK_CTRLR0_SCPOL 0x1 +#define BIT_CTRLR0_SCPOL(x)(((x) & BIT_MASK_CTRLR0_SCPOL) << BIT_SHIFT_CTRLR0_SCPOL) +#define BIT_INVC_CTRLR0_SCPOL (~(BIT_MASK_CTRLR0_SCPOL << BIT_SHIFT_CTRLR0_SCPOL)) + +#define BIT_SHIFT_CTRLR0_TMOD 8 +#define BIT_MASK_CTRLR0_TMOD 0x3 +#define BIT_CTRLR0_TMOD(x)(((x) & BIT_MASK_CTRLR0_TMOD) << BIT_SHIFT_CTRLR0_TMOD) +#define BIT_INVC_CTRLR0_TMOD (~(BIT_MASK_CTRLR0_TMOD << BIT_SHIFT_CTRLR0_TMOD)) + +#define BIT_SHIFT_CTRLR0_SLV_OE 10 +#define BIT_MASK_CTRLR0_SLV_OE 0x1 +#define BIT_CTRLR0_SLV_OE(x)(((x) & BIT_MASK_CTRLR0_SLV_OE) << BIT_SHIFT_CTRLR0_SLV_OE) +#define BIT_INVC_CTRLR0_SLV_OE (~(BIT_MASK_CTRLR0_SLV_OE << BIT_SHIFT_CTRLR0_SLV_OE)) + +#define BIT_SHIFT_CTRLR0_SRL 11 +#define BIT_MASK_CTRLR0_SRL 0x1 +#define BIT_CTRLR0_SRL(x)(((x) & BIT_MASK_CTRLR0_SRL) << BIT_SHIFT_CTRLR0_SRL) +#define BIT_INVC_CTRLR0_SRL (~(BIT_MASK_CTRLR0_SRL << BIT_SHIFT_CTRLR0_SRL)) + +#define BIT_SHIFT_CTRLR0_CFS 12 +#define BIT_MASK_CTRLR0_CFS 0xF +#define BIT_CTRLR0_CFS(x)(((x) & BIT_MASK_CTRLR0_CFS) << BIT_SHIFT_CTRLR0_CFS) +#define BIT_INVC_CTRLR0_CFS (~(BIT_MASK_CTRLR0_CFS << BIT_SHIFT_CTRLR0_CFS)) + +// CTRLR1 0x04 // 16 bits +#define BIT_SHIFT_CTRLR1_NDF 0 +#define BIT_MASK_CTRLR1_NDF 0xFFFF +#define BIT_CTRLR1_NDF(x)(((x) & BIT_MASK_CTRLR1_NDF) << BIT_SHIFT_CTRLR1_NDF) +#define BIT_INVC_CTRLR1_NDF (~(BIT_MASK_CTRLR1_NDF << BIT_SHIFT_CTRLR1_NDF)) + +// SSIENR 0x08 // 1 bit +#define BIT_SHIFT_SSIENR_SSI_EN 0 +#define BIT_MASK_SSIENR_SSI_EN 0x1 +#define BIT_SSIENR_SSI_EN(x)(((x) & BIT_MASK_SSIENR_SSI_EN) << BIT_SHIFT_SSIENR_SSI_EN) +#define BIT_INVC_SSIENR_SSI_EN (~(BIT_MASK_SSIENR_SSI_EN << BIT_SHIFT_SSIENR_SSI_EN)) + +// MWCR 0x0c // 3 bits +#define BIT_SHIFT_MWCR_MWMOD 0 +#define BIT_MASK_MWCR_MWMOD 0x1 +#define BIT_MWCR_MWMOD(x)(((x) & BIT_MASK_MWCR_MWMOD) << BIT_SHIFT_MWCR_MWMOD) +#define BIT_INVC_MWCR_MWMOD (~(BIT_MASK_MWCR_MWMOD << BIT_SHIFT_MWCR_MWMOD)) + +#define BIT_SHIFT_MWCR_MDD 1 +#define BIT_MASK_MWCR_MDD 0x1 +#define BIT_MWCR_MDD(x)(((x) & BIT_MASK_MWCR_MDD) << BIT_SHIFT_MWCR_MDD) +#define BIT_INVC_MWCR_MDD (~(BIT_MASK_MWCR_MDD << BIT_SHIFT_MWCR_MDD)) + +#define BIT_SHIFT_MWCR_MHS 2 +#define BIT_MASK_MWCR_MHS 0x1 +#define BIT_MWCR_MHS(x)(((x) & BIT_MASK_MWCR_MHS) << BIT_SHIFT_MWCR_MHS) +#define BIT_INVC_MWCR_MHS (~(BIT_MASK_MWCR_MHS << BIT_SHIFT_MWCR_MHS)) + +// SER 0x10 // Variable Length +#define BIT_SHIFT_SER_SER 0 +#define BIT_MASK_SER_SER 0xFF +#define BIT_SER_SER(x)(((x) & BIT_MASK_SER_SER) << BIT_SHIFT_SER_SER) +#define BIT_INVC_SER_SER (~(BIT_MASK_SER_SER << BIT_SHIFT_SER_SER)) + +// BAUDR 0x14 // 16 bits +#define BIT_SHIFT_BAUDR_SCKDV 0 +#define BIT_MASK_BAUDR_SCKDV 0xFFFF +#define BIT_BAUDR_SCKDV(x)(((x) & BIT_MASK_BAUDR_SCKDV) << BIT_SHIFT_BAUDR_SCKDV) +#define BIT_INVC_BAUDR_SCKDV (~(BIT_MASK_BAUDR_SCKDV << BIT_SHIFT_BAUDR_SCKDV)) + +// TXFLTR 0x18 // Variable Length +#define BIT_SHIFT_TXFTLR_TFT 0 +#define BIT_MASK_TXFTLR_TFT 0x3F // (TX_ABW-1):0 +#define BIT_TXFTLR_TFT(x)(((x) & BIT_MASK_TXFTLR_TFT) << BIT_SHIFT_TXFTLR_TFT) +#define BIT_INVC_TXFTLR_TFT (~(BIT_MASK_TXFTLR_TFT << BIT_SHIFT_TXFTLR_TFT)) + +// RXFLTR 0x1c // Variable Length +#define BIT_SHIFT_RXFTLR_RFT 0 +#define BIT_MASK_RXFTLR_RFT 0x3F // (RX_ABW-1):0 +#define BIT_RXFTLR_RFT(x)(((x) & BIT_MASK_RXFTLR_RFT) << BIT_SHIFT_RXFTLR_RFT) +#define BIT_INVC_RXFTLR_RFT (~(BIT_MASK_RXFTLR_RFT << BIT_SHIFT_RXFTLR_RFT)) + +// TXFLR 0x20 // see [READ ONLY] +#define BIT_MASK_TXFLR_TXTFL 0x7F // (TX_ABW):0 + +// RXFLR 0x24 // see [READ ONLY] +#define BIT_MASK_RXFLR_RXTFL 0x7F // (RX_ABW):0 + +// SR 0x28 // 7 bits [READ ONLY] +#define BIT_SR_BUSY BIT0 +#define BIT_SR_TFNF BIT1 +#define BIT_SR_TFE BIT2 +#define BIT_SR_RFNE BIT3 +#define BIT_SR_RFF BIT4 +#define BIT_SR_TXE BIT5 +#define BIT_SR_DCOL BIT6 + +// IMR 0x2c // see +#define BIT_SHIFT_IMR_TXEIM 0 +#define BIT_MASK_IMR_TXEIM 0x1 +// #define BIT_IMR_TXEIM(x)(((x) & BIT_MASK_IMR_TXEIM) << BIT_SHIFT_IMR_TXEIM) +#define BIT_INVC_IMR_TXEIM (~(BIT_MASK_IMR_TXEIM << BIT_SHIFT_IMR_TXEIM)) + +#define BIT_SHIFT_IMR_TXOIM 1 +#define BIT_MASK_IMR_TXOIM 0x1 +// #define BIT_IMR_TXOIM(x)(((x) & BIT_MASK_IMR_TXOIM) << BIT_SHIFT_IMR_TXOIM) +#define BIT_INVC_IMR_TXOIM (~(BIT_MASK_IMR_TXOIM << BIT_SHIFT_IMR_TXOIM)) + +#define BIT_SHIFT_IMR_RXUIM 2 +#define BIT_MASK_IMR_RXUIM 0x1 +// #define BIT_IMR_RXUIM(x)(((x) & BIT_MASK_IMR_RXUIM) << BIT_SHIFT_IMR_RXUIM) +#define BIT_INVC_IMR_RXUIM (~(BIT_MASK_IMR_RXUIM << BIT_SHIFT_IMR_RXUIM)) + +#define BIT_SHIFT_IMR_RXOIM 3 +#define BIT_MASK_IMR_RXOIM 0x1 +// #define BIT_IMR_RXOIM(x)(((x) & BIT_MASK_IMR_RXOIM) << BIT_SHIFT_IMR_RXOIM) +#define BIT_INVC_IMR_RXOIM (~(BIT_MASK_IMR_RXOIM << BIT_SHIFT_IMR_RXOIM)) + +#define BIT_SHIFT_IMR_RXFIM 4 +#define BIT_MASK_IMR_RXFIM 0x1 +// #define BIT_IMR_RXFIM(x)(((x) & BIT_MASK_IMR_RXFIM) << BIT_SHIFT_IMR_RXFIM) +#define BIT_INVC_IMR_RXFIM (~(BIT_MASK_IMR_RXFIM << BIT_SHIFT_IMR_RXFIM)) + +#define BIT_SHIFT_IMR_MSTIM 5 +#define BIT_MASK_IMR_MSTIM 0x1 +// #define BIT_IMR_MSTIM(x)(((x) & BIT_MASK_IMR_MSTIM) << BIT_SHIFT_IMR_MSTIM) +#define BIT_INVC_IMR_MSTIM (~(BIT_MASK_IMR_MSTIM << BIT_SHIFT_IMR_MSTIM)) + +#define BIT_IMR_TXEIM BIT0 +#define BIT_IMR_TXOIM BIT1 +#define BIT_IMR_RXUIM BIT2 +#define BIT_IMR_RXOIM BIT3 +#define BIT_IMR_RXFIM BIT4 +#define BIT_IMR_MSTIM BIT5 + +// ISR 0x30 // 6 bits [READ ONLY] +#define BIT_ISR_TXEIS BIT0 +#define BIT_ISR_TXOIS BIT1 +#define BIT_ISR_RXUIS BIT2 +#define BIT_ISR_RXOIS BIT3 +#define BIT_ISR_RXFIS BIT4 +#define BIT_ISR_MSTIS BIT5 + +// RISR 0x34 // 6 bits [READ ONLY] +#define BIT_RISR_TXEIR BIT0 +#define BIT_RISR_TXOIR BIT1 +#define BIT_RISR_RXUIR BIT2 +#define BIT_RISR_RXOIR BIT3 +#define BIT_RISR_RXFIR BIT4 +#define BIT_RISR_MSTIR BIT5 + +// TXOICR 0x38 // 1 bits [READ ONLY] +// RXOICR 0x3c // 1 bits [READ ONLY] +// RXUICR 0x40 // 1 bits [READ ONLY] +// MSTICR 0x44 // 1 bits [READ ONLY] +// ICR 0x48 // 1 bits [READ ONLY] + +// DMACR 0x4c // 2 bits +#define BIT_SHIFT_DMACR_RDMAE 0 +#define BIT_MASK_DMACR_RDMAE 0x1 +#define BIT_DMACR_RDMAE(x)(((x) & BIT_MASK_DMACR_RDMAE) << BIT_SHIFT_DMACR_RDMAE) +#define BIT_INVC_DMACR_RDMAE (~(BIT_MASK_DMACR_RDMAE << BIT_SHIFT_DMACR_RDMAE)) + +#define BIT_SHIFT_DMACR_TDMAE 1 +#define BIT_MASK_DMACR_TDMAE 0x1 +#define BIT_DMACR_TDMAE(x)(((x) & BIT_MASK_DMACR_TDMAE) << BIT_SHIFT_DMACR_TDMAE) +#define BIT_INVC_DMACR_TDMAE (~(BIT_MASK_DMACR_TDMAE << BIT_SHIFT_DMACR_TDMAE)) + +// DMATDLR 0x50 +#define BIT_SHIFT_DMATDLR_DMATDL 0 +#define BIT_MASK_DMATDLR_DMATDL 0x3F // (TX_ABW-1):0 +#define BIT_DMATDLR_DMATDL(x)(((x) & BIT_MASK_DMATDLR_DMATDL) << BIT_SHIFT_DMATDLR_DMATDL) +#define BIT_INVC_DMATDLR_DMATDL (~(BIT_MASK_DMATDLR_DMATDL << BIT_SHIFT_DMATDLR_DMATDL)) + +// DMARDLR 0x54 +#define BIT_SHIFT_DMARDLR_DMARDL 0 +#define BIT_MASK_DMARDLR_DMARDL 0x3F // (RX_ABW-1):0 +#define BIT_DMARDLR_DMARDL(x)(((x) & BIT_MASK_DMARDLR_DMARDL) << BIT_SHIFT_DMARDLR_DMARDL) +#define BIT_INVC_DMARDLR_DMARDL (~(BIT_MASK_DMARDLR_DMARDL << BIT_SHIFT_DMARDLR_DMARDL)) + +// IDR 0x58 // 32 bits [READ ONLY] +// COMP_VERSION 0x5c // 32 bits [READ ONLY] + +// DR 0x60 // 16 bits 0x60-0xEC +#define BIT_SHIFT_DR_DR 0 +#define BIT_MASK_DR_DR 0xFFFF +#define BIT_DR_DR(x)(((x) & BIT_MASK_DR_DR) << BIT_SHIFT_DR_DR) +#define BIT_INVC_DR_DR (~(BIT_MASK_DR_DR << BIT_SHIFT_DR_DR)) + +// RX_SAMPLE_DLY 0xF0 // 8 bits +#define BIT_SHIFT_RX_SAMPLE_DLY_RSD 0 +#define BIT_MASK_RX_SAMPLE_DLY_RSD 0xFFFF +#define BIT_RX_SAMPLE_DLY_RSD(x)(((x) & BIT_MASK_RX_SAMPLE_DLY_RSD) << BIT_SHIFT_RX_SAMPLE_DLY_RSD) +#define BIT_INVC_RX_SAMPLE_DLY_RSD (~(BIT_MASK_RX_SAMPLE_DLY_RSD << BIT_SHIFT_RX_SAMPLE_DLY_RSD)) + +// RSVD_0 0xF4 // 32 bits +// RSVD_1 0xF8 // 32 bits +// RSVD_2 0xFC // 32 bits + +// SSI0 Pinmux +#define BIT_SHIFT_SSI0_PIN_EN 0 +#define BIT_MASK_SSI0_PIN_EN 0x1 +#define BIT_SSI0_PIN_EN(x)(((x) & BIT_MASK_SSI0_PIN_EN) << BIT_SHIFT_SSI0_PIN_EN) +#define BIT_INVC_SSI0_PIN_EN (~(BIT_MASK_SSI0_PIN_EN << BIT_SHIFT_SSI0_PIN_EN)) + +#define BIT_SHIFT_SSI0_PIN_SEL 1 +#define BIT_MASK_SSI0_PIN_SEL 0x7 +#define BIT_SSI0_PIN_SEL(x)(((x) & BIT_MASK_SSI0_PIN_SEL) << BIT_SHIFT_SSI0_PIN_SEL) +#define BIT_INVC_SSI0_PIN_SEL (~(BIT_MASK_SSI0_PIN_SEL << BIT_SHIFT_SSI0_PIN_SEL)) + +// SSI1 Pinmux +#define BIT_SHIFT_SSI1_PIN_EN 4 +#define BIT_MASK_SSI1_PIN_EN 0x1 +#define BIT_SSI1_PIN_EN(x)(((x) & BIT_MASK_SSI1_PIN_EN) << BIT_SHIFT_SSI1_PIN_EN) +#define BIT_INVC_SSI1_PIN_EN (~(BIT_MASK_SSI1_PIN_EN << BIT_SHIFT_SSI1_PIN_EN)) + +#define BIT_SHIFT_SSI1_PIN_SEL 5 +#define BIT_MASK_SSI1_PIN_SEL 0x7 +#define BIT_SSI1_PIN_SEL(x)(((x) & BIT_MASK_SSI1_PIN_SEL) << BIT_SHIFT_SSI1_PIN_SEL) +#define BIT_INVC_SSI1_PIN_SEL (~(BIT_MASK_SSI1_PIN_SEL << BIT_SHIFT_SSI1_PIN_SEL)) + +// SSI2 Pinmux +#define BIT_SHIFT_SSI2_PIN_EN 8 +#define BIT_MASK_SSI2_PIN_EN 0x1 +#define BIT_SSI2_PIN_EN(x)(((x) & BIT_MASK_SSI2_PIN_EN) << BIT_SHIFT_SSI2_PIN_EN) +#define BIT_INVC_SSI2_PIN_EN (~(BIT_MASK_SSI2_PIN_EN << BIT_SHIFT_SSI2_PIN_EN)) + +#define BIT_SHIFT_SSI2_PIN_SEL 9 +#define BIT_MASK_SSI2_PIN_SEL 0x7 +#define BIT_SSI2_PIN_SEL(x)(((x) & BIT_MASK_SSI2_PIN_SEL) << BIT_SHIFT_SSI2_PIN_SEL) +#define BIT_INVC_SSI2_PIN_SEL (~(BIT_MASK_SSI2_PIN_SEL << BIT_SHIFT_SSI2_PIN_SEL)) + +// SSI0 Multiple Chip Selection (Pinmux Select is controlled by BIT_SSI0_PIN_SEL) +#define BIT_SHIFT_SSI0_MULTI_CS_EN 28 +#define BIT_MASK_SSI0_MULTI_CS_EN 0x1 +#define BIT_SSI0_MULTI_CS_EN(x)(((x) & BIT_MASK_SSI0_MULTI_CS_EN) << BIT_SHIFT_SSI0_MULTI_CS_EN) +#define BIT_INVC_SSI0_MULTI_CS_EN (~(BIT_MASK_SSI0_MULTI_CS_EN << BIT_SHIFT_SSI0_MULTI_CS_EN)) + + +#define HAL_SSI_READ32(SsiIndex, addr) \ + HAL_READ32(SPI0_REG_BASE+ (SsiIndex*SSI_REG_OFF), addr) +#define HAL_SSI_WRITE32(SsiIndex, addr, value) \ + HAL_WRITE32(SPI0_REG_BASE+ (SsiIndex*SSI_REG_OFF), addr, value) +#define HAL_SSI_READ16(SsiIndex, addr) \ + HAL_READ16(SPI0_REG_BASE+ (SsiIndex*SSI_REG_OFF), addr) +#define HAL_SSI_WRITE16(SsiIndex, addr, value) \ + HAL_WRITE16(SPI0_REG_BASE+ (SsiIndex*SSI_REG_OFF), addr, value) +#define HAL_SSI_READ8(SsiIndex, addr) \ + HAL_READ8(SPI0_REG_BASE+ (SsiIndex*SSI_REG_OFF), addr) +#define HAL_SSI_WRITE8(SsiIndex, addr, value) \ + HAL_WRITE8(SPI0_REG_BASE+ (SsiIndex*SSI_REG_OFF), addr, value) + + +// SSI Pinmux Select +typedef enum _SSI0_PINMUX_SELECT_ { + SSI0_MUX_TO_GPIOE = S0, + SSI0_MUX_TO_GPIOC = S1 +}SSI0_PINMUX_SELECT, *PSSI0_PINMUX_SELECT; + +typedef enum _SSI1_PINMUX_SELECT_ { + SSI1_MUX_TO_GPIOA = S0, + SSI1_MUX_TO_GPIOB = S1, + SSI1_MUX_TO_GPIOD = S2 +}SSI1_PINMUX_SELECT, *PSSI1_PINMUX_SELECT; + +typedef enum _SSI2_PINMUX_SELECT_ { + SSI2_MUX_TO_GPIOG = S0, + SSI2_MUX_TO_GPIOE = S1, + SSI2_MUX_TO_GPIOD = S2 +}SSI2_PINMUX_SELECT, *PSSI2_PINMUX_SELECT; + +typedef enum _SSI0_MULTI_CS_PINMUX_SELECT_ { + SSI0_CS_MUX_TO_GPIOE = S0, + SSI0_CS_MUX_TO_GPIOC = S1 +}SSI0_MULTI_CS_PINMUX_SELECT, *PSSI0_MULTI_CS_PINMUX_SELECT; + +typedef enum _SSI_CTRLR0_TMOD_ { + TMOD_TR = 0, + TMOD_TO = 1, + TMOD_RO = 2, + TMOD_EEPROM_R = 3 +}SSI_CTRLR0_TMOD, *PSSI_CTRLR0_TMOD; + +typedef enum _SSI_CTRLR0_SCPOL_ { + SCPOL_INACTIVE_IS_LOW = 0, + SCPOL_INACTIVE_IS_HIGH = 1 +}SSI_CTRLR0_SCPOL, *PSSI_CTRLR0_SCPOL; + +typedef enum _SSI_CTRLR0_SCPH_ { + SCPH_TOGGLES_IN_MIDDLE = 0, + SCPH_TOGGLES_AT_START = 1 +}SSI_CTRLR0_SCPH, *PSSI_CTRLR0_SCPH; + +typedef enum _SSI_CTRLR0_DFS_ { + DFS_4_BITS = 3, + DFS_5_BITS = 4, + DFS_6_BITS = 5, + DFS_7_BITS = 6, + DFS_8_BITS = 7, + DFS_9_BITS = 8, + DFS_10_BITS = 9, + DFS_11_BITS = 10, + DFS_12_BITS = 11, + DFS_13_BITS = 12, + DFS_14_BITS = 13, + DFS_15_BITS = 14, + DFS_16_BITS = 15, +}SSI_CTRLR0_DFS, *PSSI_CTRLR0_DFS; + +typedef enum _SSI_CTRLR0_CFS_ { + CFS_1_BIT = 0, + CFS_2_BITS = 1, + CFS_3_BITS = 2, + CFS_4_BITS = 3, + CFS_5_BITS = 4, + CFS_6_BITS = 5, + CFS_7_BITS = 6, + CFS_8_BITS = 7, + CFS_9_BITS = 8, + CFS_10_BITS = 9, + CFS_11_BITS = 10, + CFS_12_BITS = 11, + CFS_13_BITS = 12, + CFS_14_BITS = 13, + CFS_15_BITS = 14, + CFS_16_BITS = 15 +}SSI_CTRLR0_CFS, *PSSI_CTRLR0_CFS; + +typedef enum _SSI_CTRLR0_SLV_OE_ { + SLV_TXD_ENABLE = 0, + SLV_TXD_DISABLE = 1 +}SSI_CTRLR0_SLV_OE, *PSSI_CTRLR0_SLV_OE; + +typedef enum _SSI_ROLE_SELECT_ { + SSI_SLAVE = 0, + SSI_MASTER = 1 +}SSI_ROLE_SELECT, *PSSI_ROLE_SELECT; + +typedef enum _SSI_FRAME_FORMAT_ { + FRF_MOTOROLA_SPI = 0, + FRF_TI_SSP = 1, + FRF_NS_MICROWIRE = 2, + FRF_RSVD = 3 +}SSI_FRAME_FORMAT, *PSSI_FRAME_FORMAT; + +typedef enum _SSI_DMACR_ENABLE_ { + SSI_NODMA = 0, + SSI_RXDMA_ENABLE = 1, + SSI_TXDMA_ENABLE = 2, + SSI_TRDMA_ENABLE = 3 +}SSI_DMACR_ENABLE, *PSSI_DMACR_ENABLE; + +typedef enum _SSI_MWCR_HANDSHAKE_ { + MW_HANDSHAKE_DISABLE = 0, + MW_HANDSHAKE_ENABLE = 1 +}SSI_MWCR_HANDSHAKE, *PSSI_MWCR_HANDSHAKE; + +typedef enum _SSI_MWCR_DIRECTION_ { + MW_DIRECTION_SLAVE_TO_MASTER = 0, + MW_DIRECTION_MASTER_TO_SLAVE = 1 +}SSI_MWCR_DIRECTION, *PSSI_MWCR_DIRECTION; + +typedef enum _SSI_MWCR_TMOD_ { + MW_TMOD_NONSEQUENTIAL = 0, + MW_TMOD_SEQUENTIAL = 1 +}SSI_MWCR_TMOD, *PSSI_MWCR_TMOD; + +typedef enum _SSI_DATA_TRANSFER_MECHANISM_ { + SSI_DTM_BASIC, + SSI_DTM_INTERRUPT, + SSI_DTM_DMA +}SSI_DATA_TRANSFER_MECHANISM, *PSSI_DATA_TRANSFER_MECHANISM; + + +_LONG_CALL_ HAL_Status HalSsiPinmuxEnableRtl8195a(VOID *Adaptor); +_LONG_CALL_ HAL_Status HalSsiEnableRtl8195a(VOID *Adaptor); +_LONG_CALL_ HAL_Status HalSsiDisableRtl8195a(VOID *Adaptor); +_LONG_CALL_ HAL_Status HalSsiInitRtl8195a(VOID *Adaptor); +_LONG_CALL_ HAL_Status HalSsiSetSclkPolarityRtl8195a(VOID *Adaptor); +_LONG_CALL_ HAL_Status HalSsiSetSclkPhaseRtl8195a(VOID *Adaptor); +_LONG_CALL_ HAL_Status HalSsiWriteRtl8195a(VOID *Adaptor, u32 value); +_LONG_CALL_ HAL_Status HalSsiLoadSettingRtl8195a(VOID *Adaptor, VOID *Setting); +_LONG_CALL_ HAL_Status HalSsiSetInterruptMaskRtl8195a(VOID *Adaptor); +_LONG_CALL_ HAL_Status HalSsiSetDeviceRoleRtl8195a(VOID *Adaptor, u32 Role); +_LONG_CALL_ HAL_Status HalSsiInterruptEnableRtl8195a(VOID *Adaptor); +_LONG_CALL_ HAL_Status HalSsiInterruptDisableRtl8195a(VOID *Adaptor); +_LONG_CALL_ HAL_Status HalSsiReadInterruptRtl8195a(VOID *Adaptor, VOID *RxData, u32 Length); +_LONG_CALL_ HAL_Status HalSsiSetRxFifoThresholdLevelRtl8195a(VOID *Adaptor); +_LONG_CALL_ HAL_Status HalSsiSetTxFifoThresholdLevelRtl8195a(VOID *Adaptor); +_LONG_CALL_ HAL_Status HalSsiWriteInterruptRtl8195a(VOID *Adaptor, VOID *TxData, u32 Length); +_LONG_CALL_ HAL_Status HalSsiSetSlaveEnableRegisterRtl8195a(VOID *Adaptor, u32 SlaveIndex); +_LONG_CALL_ u32 HalSsiBusyRtl8195a(VOID *Adaptor); +_LONG_CALL_ u32 HalSsiWriteableRtl8195a(VOID *Adaptor); +_LONG_CALL_ u32 HalSsiReadableRtl8195a(VOID *Adaptor); +_LONG_CALL_ u32 HalSsiGetInterruptMaskRtl8195a(VOID *Adaptor); +_LONG_CALL_ u32 HalSsiGetRxFifoLevelRtl8195a(VOID *Adaptor); +_LONG_CALL_ u32 HalSsiGetTxFifoLevelRtl8195a(VOID *Adaptor); +_LONG_CALL_ u32 HalSsiGetStatusRtl8195a(VOID *Adaptor); +_LONG_CALL_ u32 HalSsiGetInterruptStatusRtl8195a(VOID *Adaptor); +_LONG_CALL_ u32 HalSsiReadRtl8195a(VOID *Adaptor); +_LONG_CALL_ u32 HalSsiGetRawInterruptStatusRtl8195a(VOID *Adaptor); +_LONG_CALL_ u32 HalSsiGetSlaveEnableRegisterRtl8195a(VOID *Adaptor); + +_LONG_CALL_ VOID _SsiReadInterrupt(VOID *Adaptor); +_LONG_CALL_ VOID _SsiWriteInterrupt(VOID *Adaptor); +_LONG_CALL_ u32 _SsiIrqHandle(VOID *Adaptor); + +// ROM code patch +VOID _SsiReadInterruptRtl8195a(VOID *Adapter); +VOID _SsiWriteInterruptRtl8195a(VOID *Adapter); +HAL_Status HalSsiInitRtl8195a_Patch(VOID *Adaptor); +HAL_Status HalSsiPinmuxEnableRtl8195a_Patch(VOID *Adaptor); +HAL_Status HalSsiPinmuxDisableRtl8195a(VOID *Adaptor); +VOID HalSsiSetSclkRtl8195a(VOID *Adapter, u32 ClkRate); +HAL_Status HalSsiIntReadRtl8195a(VOID *Adapter, VOID *RxData, u32 Length); +HAL_Status HalSsiIntWriteRtl8195a(VOID *Adapter, u8 *pTxData, u32 Length); +#ifdef CONFIG_GDMA_EN +VOID HalSsiTxGdmaLoadDefRtl8195a(VOID *Adapter); +VOID HalSsiRxGdmaLoadDefRtl8195a(VOID *Adapter); +VOID HalSsiDmaInitRtl8195a(VOID *Adapter); +HAL_Status HalSsiDmaSendRtl8195a(VOID *Adapter, u8 *pTxData, u32 Length); +HAL_Status HalSsiDmaRecvRtl8195a(VOID *Adapter, u8 *pRxData, u32 Length); +#endif // end of "#ifdef CONFIG_GDMA_EN" + +#endif diff --git a/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_sys_on.h b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_sys_on.h new file mode 100644 index 0000000..2c5ef62 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_sys_on.h @@ -0,0 +1,1093 @@ +#ifndef __INC_RTL8195A_SYS_ON_BIT_H +#define __INC_RTL8195A_SYS_ON_BIT_H + +#define CPU_OPT_WIDTH 0x1F + +//2 REG_NOT_VALID + +//2 REG_SYS_PWR_CTRL + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID +#define BIT_SYS_PWR_SOC_EN BIT(2) +#define BIT_SYS_PWR_RET_MEM_EN BIT(1) +#define BIT_SYS_PWR_PEON_EN BIT(0) + +//2 REG_SYS_ISO_CTRL + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID +#define BIT_SYS_ISO_SYSPLL BIT(7) + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID +#define BIT_SYS_ISO_SOC BIT(2) +#define BIT_SYS_ISO_RET_MEM BIT(1) +#define BIT_SYS_ISO_PEON BIT(0) + +//2 REG_RSVD + +//2 REG_NOT_VALID + +//2 REG_SYS_FUNC_EN +#define BIT_SYS_AMACRO_EN BIT(31) +#define BIT_SYS_PWRON_TRAP_SHTDN_N BIT(30) +#define BIT_SYS_FEN_SIC_MST BIT(25) +#define BIT_SYS_FEN_SIC BIT(24) + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID +#define BIT_SOC_SYSPEON_EN BIT(4) + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID +#define BIT_SYS_FEN_EELDR BIT(0) + +//2 REG_RSVD + +//2 REG_NOT_VALID + +//2 REG_SYS_CLK_CTRL0 + +//2 REG_NOT_VALID +#define BIT_SOC_OCP_IOBUS_CK_EN BIT(2) +#define BIT_SYSON_CK_EELDR_EN BIT(1) +#define BIT_SYSON_CK_SYSREG_EN BIT(0) + +//2 REG_SYS_CLK_CTRL1 + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +#define BIT_SHIFT_PESOC_OCP_CPU_CK_SEL 4 +#define BIT_MASK_PESOC_OCP_CPU_CK_SEL 0x7 +#define BIT_PESOC_OCP_CPU_CK_SEL(x) (((x) & BIT_MASK_PESOC_OCP_CPU_CK_SEL) << BIT_SHIFT_PESOC_OCP_CPU_CK_SEL) + + +//2 REG_NOT_VALID +#define BIT_PESOC_EELDR_CK_SEL BIT(0) + +//2 REG_SYS_SWR_CTRL3 + +//2 REG_RSV_CTRL + +//2 REG_RF_CTRL + +//2 REG_SYS_EFUSE_SYSCFG0 + +#define BIT_SHIFT_SYS_EEROM_SWR_PAR_05_00 24 +#define BIT_MASK_SYS_EEROM_SWR_PAR_05_00 0x3f +#define BIT_SYS_EEROM_SWR_PAR_05_00(x) (((x) & BIT_MASK_SYS_EEROM_SWR_PAR_05_00) << BIT_SHIFT_SYS_EEROM_SWR_PAR_05_00) + + +#define BIT_SHIFT_SYS_EEROM_LDO_PAR_07_04 20 +#define BIT_MASK_SYS_EEROM_LDO_PAR_07_04 0xf +#define BIT_SYS_EEROM_LDO_PAR_07_04(x) (((x) & BIT_MASK_SYS_EEROM_LDO_PAR_07_04) << BIT_SHIFT_SYS_EEROM_LDO_PAR_07_04) + +#define BIT_SYS_CHIPPDN_EN BIT(17) +#define BIT_SYS_EEROM_B12V_EN BIT(16) + +#define BIT_SHIFT_SYS_EEROM_VID1 8 +#define BIT_MASK_SYS_EEROM_VID1 0xff +#define BIT_SYS_EEROM_VID1(x) (((x) & BIT_MASK_SYS_EEROM_VID1) << BIT_SHIFT_SYS_EEROM_VID1) + + +#define BIT_SHIFT_SYS_EEROM_VID0 0 +#define BIT_MASK_SYS_EEROM_VID0 0xff +#define BIT_SYS_EEROM_VID0(x) (((x) & BIT_MASK_SYS_EEROM_VID0) << BIT_SHIFT_SYS_EEROM_VID0) + + +//2 REG_SYS_EFUSE_SYSCFG1 + +#define BIT_SHIFT_SYS_PDSPL_STL 24 +#define BIT_MASK_SYS_PDSPL_STL 0x3 +#define BIT_SYS_PDSPL_STL(x) (((x) & BIT_MASK_SYS_PDSPL_STL) << BIT_SHIFT_SYS_PDSPL_STL) + + +#define BIT_SHIFT_SYS_PDSOC_STL 22 +#define BIT_MASK_SYS_PDSOC_STL 0x3 +#define BIT_SYS_PDSOC_STL(x) (((x) & BIT_MASK_SYS_PDSOC_STL) << BIT_SHIFT_SYS_PDSOC_STL) + + +#define BIT_SHIFT_SYS_PDPON_STL 20 +#define BIT_MASK_SYS_PDPON_STL 0x3 +#define BIT_SYS_PDPON_STL(x) (((x) & BIT_MASK_SYS_PDPON_STL) << BIT_SHIFT_SYS_PDPON_STL) + + +#define BIT_SHIFT_SYS_SWREG_XRT 18 +#define BIT_MASK_SYS_SWREG_XRT 0x3 +#define BIT_SYS_SWREG_XRT(x) (((x) & BIT_MASK_SYS_SWREG_XRT) << BIT_SHIFT_SYS_SWREG_XRT) + + +#define BIT_SHIFT_SYS_SWSLC_STL 16 +#define BIT_MASK_SYS_SWSLC_STL 0x3 +#define BIT_SYS_SWSLC_STL(x) (((x) & BIT_MASK_SYS_SWSLC_STL) << BIT_SHIFT_SYS_SWSLC_STL) + + +#define BIT_SHIFT_SYS_EEROM_SWR_PAR_46_45 14 +#define BIT_MASK_SYS_EEROM_SWR_PAR_46_45 0x3 +#define BIT_SYS_EEROM_SWR_PAR_46_45(x) (((x) & BIT_MASK_SYS_EEROM_SWR_PAR_46_45) << BIT_SHIFT_SYS_EEROM_SWR_PAR_46_45) + + +#define BIT_SHIFT_SYS_EEROM_SWR_PAR_40_39 12 +#define BIT_MASK_SYS_EEROM_SWR_PAR_40_39 0x3 +#define BIT_SYS_EEROM_SWR_PAR_40_39(x) (((x) & BIT_MASK_SYS_EEROM_SWR_PAR_40_39) << BIT_SHIFT_SYS_EEROM_SWR_PAR_40_39) + + +#define BIT_SHIFT_SYS_EEROM_SWR_PAR_33_26 4 +#define BIT_MASK_SYS_EEROM_SWR_PAR_33_26 0xff +#define BIT_SYS_EEROM_SWR_PAR_33_26(x) (((x) & BIT_MASK_SYS_EEROM_SWR_PAR_33_26) << BIT_SHIFT_SYS_EEROM_SWR_PAR_33_26) + + +#define BIT_SHIFT_SYS_EEROM_SWSLD_VOL 0 +#define BIT_MASK_SYS_EEROM_SWSLD_VOL 0x7 +#define BIT_SYS_EEROM_SWSLD_VOL(x) (((x) & BIT_MASK_SYS_EEROM_SWSLD_VOL) << BIT_SHIFT_SYS_EEROM_SWSLD_VOL) + + +//2 REG_SYS_EFUSE_SYSCFG2 + +#define BIT_SHIFT_SYS_EERROM_ANAPAR_SPLL_24_15 21 +#define BIT_MASK_SYS_EERROM_ANAPAR_SPLL_24_15 0x3ff +#define BIT_SYS_EERROM_ANAPAR_SPLL_24_15(x) (((x) & BIT_MASK_SYS_EERROM_ANAPAR_SPLL_24_15) << BIT_SHIFT_SYS_EERROM_ANAPAR_SPLL_24_15) + + +#define BIT_SHIFT_SYS_EEROM_ANAPAR_SPLL_05_02 16 +#define BIT_MASK_SYS_EEROM_ANAPAR_SPLL_05_02 0xf +#define BIT_SYS_EEROM_ANAPAR_SPLL_05_02(x) (((x) & BIT_MASK_SYS_EEROM_ANAPAR_SPLL_05_02) << BIT_SHIFT_SYS_EEROM_ANAPAR_SPLL_05_02) + + +#define BIT_SHIFT_SYS_EEROM_XTAL_STEL_SEL 12 +#define BIT_MASK_SYS_EEROM_XTAL_STEL_SEL 0x3 +#define BIT_SYS_EEROM_XTAL_STEL_SEL(x) (((x) & BIT_MASK_SYS_EEROM_XTAL_STEL_SEL) << BIT_SHIFT_SYS_EEROM_XTAL_STEL_SEL) + + +#define BIT_SHIFT_SYS_EEROM_XTAL_FREQ_SEL 8 +#define BIT_MASK_SYS_EEROM_XTAL_FREQ_SEL 0xf +#define BIT_SYS_EEROM_XTAL_FREQ_SEL(x) (((x) & BIT_MASK_SYS_EEROM_XTAL_FREQ_SEL) << BIT_SHIFT_SYS_EEROM_XTAL_FREQ_SEL) + + +//2 REG_SYS_EFUSE_SYSCFG3 + +#define BIT_SHIFT_SYS_DBG_PINGP_EN 28 +#define BIT_MASK_SYS_DBG_PINGP_EN 0xf +#define BIT_SYS_DBG_PINGP_EN(x) (((x) & BIT_MASK_SYS_DBG_PINGP_EN) << BIT_SHIFT_SYS_DBG_PINGP_EN) + + +#define BIT_SHIFT_SYS_DBG_SEL 16 +#define BIT_MASK_SYS_DBG_SEL 0xfff +#define BIT_SYS_DBG_SEL(x) (((x) & BIT_MASK_SYS_DBG_SEL) << BIT_SHIFT_SYS_DBG_SEL) + + +#define BIT_SHIFT_SYS_DBGBY3_LOC_SEL 14 +#define BIT_MASK_SYS_DBGBY3_LOC_SEL 0x3 +#define BIT_SYS_DBGBY3_LOC_SEL(x) (((x) & BIT_MASK_SYS_DBGBY3_LOC_SEL) << BIT_SHIFT_SYS_DBGBY3_LOC_SEL) + + +#define BIT_SHIFT_SYS_DBGBY2_LOC_SEL 12 +#define BIT_MASK_SYS_DBGBY2_LOC_SEL 0x3 +#define BIT_SYS_DBGBY2_LOC_SEL(x) (((x) & BIT_MASK_SYS_DBGBY2_LOC_SEL) << BIT_SHIFT_SYS_DBGBY2_LOC_SEL) + + +#define BIT_SHIFT_SYS_DBGBY1_LOC_SEL 10 +#define BIT_MASK_SYS_DBGBY1_LOC_SEL 0x3 +#define BIT_SYS_DBGBY1_LOC_SEL(x) (((x) & BIT_MASK_SYS_DBGBY1_LOC_SEL) << BIT_SHIFT_SYS_DBGBY1_LOC_SEL) + + +#define BIT_SHIFT_SYS_DBGBY0_LOC_SEL 8 +#define BIT_MASK_SYS_DBGBY0_LOC_SEL 0x3 +#define BIT_SYS_DBGBY0_LOC_SEL(x) (((x) & BIT_MASK_SYS_DBGBY0_LOC_SEL) << BIT_SHIFT_SYS_DBGBY0_LOC_SEL) + +#define BIT_SYS_EEROM_ANAPAR_SPLL_49 BIT(3) + +#define BIT_SHIFT_SYS_EEROM_ANAPAR_SPLL_27_25 0 +#define BIT_MASK_SYS_EEROM_ANAPAR_SPLL_27_25 0x7 +#define BIT_SYS_EEROM_ANAPAR_SPLL_27_25(x) (((x) & BIT_MASK_SYS_EEROM_ANAPAR_SPLL_27_25) << BIT_SHIFT_SYS_EEROM_ANAPAR_SPLL_27_25) + + +//2 REG_SYS_EFUSE_SYSCFG4 + +#define BIT_SHIFT_SYS_GPIOA_E2 1 +#define BIT_MASK_SYS_GPIOA_E2 0x7 +#define BIT_SYS_GPIOA_E2(x) (((x) & BIT_MASK_SYS_GPIOA_E2) << BIT_SHIFT_SYS_GPIOA_E2) + +#define BIT_SYS_GPIOA_H3L1 BIT(0) + +//2 REG_SYS_EFUSE_SYSCFG5 + +//2 REG_NOT_VALID + +//2 REG_SYS_EFUSE_SYSCFG6 + +#define BIT_SHIFT_SYS_SPIC_INIT_BAUD_RATE_SEL 26 +#define BIT_MASK_SYS_SPIC_INIT_BAUD_RATE_SEL 0x3 +#define BIT_SYS_SPIC_INIT_BAUD_RATE_SEL(x) (((x) & BIT_MASK_SYS_SPIC_INIT_BAUD_RATE_SEL) << BIT_SHIFT_SYS_SPIC_INIT_BAUD_RATE_SEL) + + +#define BIT_SHIFT_SYS_CPU_CLK_SEL 24 +#define BIT_MASK_SYS_CPU_CLK_SEL 0x3 +#define BIT_SYS_CPU_CLK_SEL(x) (((x) & BIT_MASK_SYS_CPU_CLK_SEL) << BIT_SHIFT_SYS_CPU_CLK_SEL) + + +//2 REG_SYS_EFUSE_SYSCFG7 +#define BIT_SYS_MEM_RMV_SIGN BIT(31) +#define BIT_SYS_MEM_RMV_1PRF1 BIT(29) +#define BIT_SYS_MEM_RMV_1PRF0 BIT(28) +#define BIT_SYS_MEM_RMV_1PSR BIT(27) +#define BIT_SYS_MEM_RMV_1PHSR BIT(26) +#define BIT_SYS_MEM_RMV_ROM BIT(25) + +#define BIT_SHIFT_SYS_MEM_RME_CPU 22 +#define BIT_MASK_SYS_MEM_RME_CPU 0x7 +#define BIT_SYS_MEM_RME_CPU(x) (((x) & BIT_MASK_SYS_MEM_RME_CPU) << BIT_SHIFT_SYS_MEM_RME_CPU) + + +#define BIT_SHIFT_SYS_MEM_RME_WLAN 19 +#define BIT_MASK_SYS_MEM_RME_WLAN 0x7 +#define BIT_SYS_MEM_RME_WLAN(x) (((x) & BIT_MASK_SYS_MEM_RME_WLAN) << BIT_SHIFT_SYS_MEM_RME_WLAN) + +#define BIT_SYS_MEM_RME_USB BIT(18) +#define BIT_SYS_MEM_RME_SDIO BIT(17) + +//2 REG_SYS_REGU_CTRL0 + +#define BIT_SHIFT_SYS_REGU_LDO25M_ADJ 20 +#define BIT_MASK_SYS_REGU_LDO25M_ADJ 0xf +#define BIT_SYS_REGU_LDO25M_ADJ(x) (((x) & BIT_MASK_SYS_REGU_LDO25M_ADJ) << BIT_SHIFT_SYS_REGU_LDO25M_ADJ) + +#define BIT_SYS_REGU_ANACK_4M_EN BIT(19) +#define BIT_SYS_REGU_ANACK_4M_SEL BIT(18) +#define BIT_SYS_REGU_PC_EF_EN BIT(17) +#define BIT_SYS_REGU_LDOH12_SLP_EN BIT(16) + +#define BIT_SHIFT_SYS_REGU_LDOH12_ADJ 12 +#define BIT_MASK_SYS_REGU_LDOH12_ADJ 0xf +#define BIT_SYS_REGU_LDOH12_ADJ(x) (((x) & BIT_MASK_SYS_REGU_LDOH12_ADJ) << BIT_SHIFT_SYS_REGU_LDOH12_ADJ) + + +#define BIT_SHIFT_SYS_REGU_LDO25E_ADJ 8 +#define BIT_MASK_SYS_REGU_LDO25E_ADJ 0xf +#define BIT_SYS_REGU_LDO25E_ADJ(x) (((x) & BIT_MASK_SYS_REGU_LDO25E_ADJ) << BIT_SHIFT_SYS_REGU_LDO25E_ADJ) + +#define BIT_SYS_REGU_DSLEPM_EN BIT(7) +#define BIT_SYS_REGU_PC_33V_EN BIT(3) +#define BIT_SYS_REGU_PC_EF25_EN BIT(2) +#define BIT_SYS_REGU_LDO25M_EN BIT(1) +#define BIT_SYS_REGU_LDO25E_EN BIT(0) + +//2 REG_RSVD + +//2 REG_NOT_VALID + +//2 REG_SYS_SWR_CTRL0 + +#define BIT_SHIFT_SYS_SWR12_COMP_R2 30 +#define BIT_MASK_SYS_SWR12_COMP_R2 0x3 +#define BIT_SYS_SWR12_COMP_R2(x) (((x) & BIT_MASK_SYS_SWR12_COMP_R2) << BIT_SHIFT_SYS_SWR12_COMP_R2) + + +#define BIT_SHIFT_SYS_SWR12_COMP_R1 28 +#define BIT_MASK_SYS_SWR12_COMP_R1 0x3 +#define BIT_SYS_SWR12_COMP_R1(x) (((x) & BIT_MASK_SYS_SWR12_COMP_R1) << BIT_SHIFT_SYS_SWR12_COMP_R1) + + +#define BIT_SHIFT_SYS_SWR12_COMP_C3 26 +#define BIT_MASK_SYS_SWR12_COMP_C3 0x3 +#define BIT_SYS_SWR12_COMP_C3(x) (((x) & BIT_MASK_SYS_SWR12_COMP_C3) << BIT_SHIFT_SYS_SWR12_COMP_C3) + + +#define BIT_SHIFT_SYS_SWR12_COMP_C2 24 +#define BIT_MASK_SYS_SWR12_COMP_C2 0x3 +#define BIT_SYS_SWR12_COMP_C2(x) (((x) & BIT_MASK_SYS_SWR12_COMP_C2) << BIT_SHIFT_SYS_SWR12_COMP_C2) + + +#define BIT_SHIFT_SYS_SWR12_COMP_C1 22 +#define BIT_MASK_SYS_SWR12_COMP_C1 0x3 +#define BIT_SYS_SWR12_COMP_C1(x) (((x) & BIT_MASK_SYS_SWR12_COMP_C1) << BIT_SHIFT_SYS_SWR12_COMP_C1) + +#define BIT_SYS_SWR12_COMP_TYPE_L BIT(21) +#define BIT_SYS_SWR12_FPWM_MD BIT(20) + +#define BIT_SHIFT_SYS_SPSLDO_VOL 17 +#define BIT_MASK_SYS_SPSLDO_VOL 0x7 +#define BIT_SYS_SPSLDO_VOL(x) (((x) & BIT_MASK_SYS_SPSLDO_VOL) << BIT_SHIFT_SYS_SPSLDO_VOL) + + +#define BIT_SHIFT_SYS_SWR12_IN 14 +#define BIT_MASK_SYS_SWR12_IN 0x7 +#define BIT_SYS_SWR12_IN(x) (((x) & BIT_MASK_SYS_SWR12_IN) << BIT_SHIFT_SYS_SWR12_IN) + + +#define BIT_SHIFT_SYS_SWR12_STD 12 +#define BIT_MASK_SYS_SWR12_STD 0x3 +#define BIT_SYS_SWR12_STD(x) (((x) & BIT_MASK_SYS_SWR12_STD) << BIT_SHIFT_SYS_SWR12_STD) + + +#define BIT_SHIFT_SYS_SWR12_VOL 8 +#define BIT_MASK_SYS_SWR12_VOL 0xf +#define BIT_SYS_SWR12_VOL(x) (((x) & BIT_MASK_SYS_SWR12_VOL) << BIT_SHIFT_SYS_SWR12_VOL) + + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID +#define BIT_SYS_SWR_EN BIT(1) +#define BIT_SYS_SWR_LDO_EN BIT(0) + +//2 REG_SYS_SWR_CTRL1 +#define BIT_SYS_SW12_PFM_SEL BIT(25) +#define BIT_SYS_SW12_AUTO_ZCD_L BIT(24) +#define BIT_SYS_SW12_AUTO_MODE BIT(23) +#define BIT_SYS_SW12_LDOF_L BIT(22) +#define BIT_SYS_SW12_OCPS_L BIT(21) + +#define BIT_SHIFT_SYS_SW12_TBOX 17 +#define BIT_MASK_SYS_SW12_TBOX 0x3 +#define BIT_SYS_SW12_TBOX(x) (((x) & BIT_MASK_SYS_SW12_TBOX) << BIT_SHIFT_SYS_SW12_TBOX) + + +#define BIT_SHIFT_SYS_SW12_NONOVRLAP_DLY 15 +#define BIT_MASK_SYS_SW12_NONOVRLAP_DLY 0x3 +#define BIT_SYS_SW12_NONOVRLAP_DLY(x) (((x) & BIT_MASK_SYS_SW12_NONOVRLAP_DLY) << BIT_SHIFT_SYS_SW12_NONOVRLAP_DLY) + +#define BIT_SYS_SW12_CLAMP_DUTY BIT(14) +#define BIT_SYS_SWR12_BYPASS_SSR BIT(13) +#define BIT_SYS_SWR12_ZCDOUT_EN BIT(12) +#define BIT_SYS_SWR12_POW_ZCD BIT(11) +#define BIT_SYS_SW12_AREN BIT(10) + +#define BIT_SHIFT_SYS_SWR12_OCP_CUR 7 +#define BIT_MASK_SYS_SWR12_OCP_CUR 0x7 +#define BIT_SYS_SWR12_OCP_CUR(x) (((x) & BIT_MASK_SYS_SWR12_OCP_CUR) << BIT_SHIFT_SYS_SWR12_OCP_CUR) + +#define BIT_SYS_SWR12_OCP_EN BIT(6) + +#define BIT_SHIFT_SYS_SWR12_SAWTOOTH_CF_L 4 +#define BIT_MASK_SYS_SWR12_SAWTOOTH_CF_L 0x3 +#define BIT_SYS_SWR12_SAWTOOTH_CF_L(x) (((x) & BIT_MASK_SYS_SWR12_SAWTOOTH_CF_L) << BIT_SHIFT_SYS_SWR12_SAWTOOTH_CF_L) + + +#define BIT_SHIFT_SYS_SWR12_SAWTOOTH_CFC_L 2 +#define BIT_MASK_SYS_SWR12_SAWTOOTH_CFC_L 0x3 +#define BIT_SYS_SWR12_SAWTOOTH_CFC_L(x) (((x) & BIT_MASK_SYS_SWR12_SAWTOOTH_CFC_L) << BIT_SHIFT_SYS_SWR12_SAWTOOTH_CFC_L) + + +#define BIT_SHIFT_SYS_SWR12_COMP_R3 0 +#define BIT_MASK_SYS_SWR12_COMP_R3 0x3 +#define BIT_SYS_SWR12_COMP_R3(x) (((x) & BIT_MASK_SYS_SWR12_COMP_R3) << BIT_SHIFT_SYS_SWR12_COMP_R3) + + +//2 REG_RSVD + +//2 REG_RSVD + +//2 REG_RSVD + +//2 REG_RSVD + +//2 REG_SYS_XTAL_CTRL0 +#define BIT_SYS_XTAL_XQSEL BIT(31) +#define BIT_SYS_XTAL_XQSEL_RF BIT(30) + +#define BIT_SHIFT_SYS_XTAL_SC_XO 24 +#define BIT_MASK_SYS_XTAL_SC_XO 0x3f +#define BIT_SYS_XTAL_SC_XO(x) (((x) & BIT_MASK_SYS_XTAL_SC_XO) << BIT_SHIFT_SYS_XTAL_SC_XO) + + +#define BIT_SHIFT_SYS_XTAL_SC_XI 18 +#define BIT_MASK_SYS_XTAL_SC_XI 0x3f +#define BIT_SYS_XTAL_SC_XI(x) (((x) & BIT_MASK_SYS_XTAL_SC_XI) << BIT_SHIFT_SYS_XTAL_SC_XI) + + +#define BIT_SHIFT_SYS_XTAL_GMN 13 +#define BIT_MASK_SYS_XTAL_GMN 0x1f +#define BIT_SYS_XTAL_GMN(x) (((x) & BIT_MASK_SYS_XTAL_GMN) << BIT_SHIFT_SYS_XTAL_GMN) + + +#define BIT_SHIFT_SYS_XTAL_GMP 8 +#define BIT_MASK_SYS_XTAL_GMP 0x1f +#define BIT_SYS_XTAL_GMP(x) (((x) & BIT_MASK_SYS_XTAL_GMP) << BIT_SHIFT_SYS_XTAL_GMP) + +#define BIT_SYS_XTAL_EN BIT(1) +#define BIT_SYS_XTAL_BGMB_EN BIT(0) + +//2 REG_SYS_XTAL_CTRL1 + +#define BIT_SHIFT_SYS_XTAL_COUNTER_MUX 25 +#define BIT_MASK_SYS_XTAL_COUNTER_MUX 0x3 +#define BIT_SYS_XTAL_COUNTER_MUX(x) (((x) & BIT_MASK_SYS_XTAL_COUNTER_MUX) << BIT_SHIFT_SYS_XTAL_COUNTER_MUX) + +#define BIT_SYS_XTAL_DELAY_SYSPLL BIT(24) +#define BIT_SYS_XTAL_DELAY_USB BIT(23) +#define BIT_SYS_XTAL_DELAY_WLAFE BIT(22) +#define BIT_SYS_XTAL_AGPIO_SEL BIT(21) + +#define BIT_SHIFT_SYS_XTAL_DRV_AGPIO 19 +#define BIT_MASK_SYS_XTAL_DRV_AGPIO 0x3 +#define BIT_SYS_XTAL_DRV_AGPIO(x) (((x) & BIT_MASK_SYS_XTAL_DRV_AGPIO) << BIT_SHIFT_SYS_XTAL_DRV_AGPIO) + + +#define BIT_SHIFT_SYS_XTAL_AGPIO 16 +#define BIT_MASK_SYS_XTAL_AGPIO 0x7 +#define BIT_SYS_XTAL_AGPIO(x) (((x) & BIT_MASK_SYS_XTAL_AGPIO) << BIT_SHIFT_SYS_XTAL_AGPIO) + + +#define BIT_SHIFT_SYS_XTAL_DRV_SYSPLL 14 +#define BIT_MASK_SYS_XTAL_DRV_SYSPLL 0x3 +#define BIT_SYS_XTAL_DRV_SYSPLL(x) (((x) & BIT_MASK_SYS_XTAL_DRV_SYSPLL) << BIT_SHIFT_SYS_XTAL_DRV_SYSPLL) + +#define BIT_SYS_XTAL_GATE_SYSPLL BIT(13) + +#define BIT_SHIFT_SYS_XTAL_DRV_USB 11 +#define BIT_MASK_SYS_XTAL_DRV_USB 0x3 +#define BIT_SYS_XTAL_DRV_USB(x) (((x) & BIT_MASK_SYS_XTAL_DRV_USB) << BIT_SHIFT_SYS_XTAL_DRV_USB) + +#define BIT_SYS_XTAL_GATE_USB BIT(10) + +#define BIT_SHIFT_SYS_XTAL_DRV_WLAFE 8 +#define BIT_MASK_SYS_XTAL_DRV_WLAFE 0x3 +#define BIT_SYS_XTAL_DRV_WLAFE(x) (((x) & BIT_MASK_SYS_XTAL_DRV_WLAFE) << BIT_SHIFT_SYS_XTAL_DRV_WLAFE) + +#define BIT_SYS_XTAL_GATE_WLAFE BIT(7) + +#define BIT_SHIFT_SYS_XTAL_DRV_RF2 5 +#define BIT_MASK_SYS_XTAL_DRV_RF2 0x3 +#define BIT_SYS_XTAL_DRV_RF2(x) (((x) & BIT_MASK_SYS_XTAL_DRV_RF2) << BIT_SHIFT_SYS_XTAL_DRV_RF2) + +#define BIT_SYS_XTAL_GATE_RF2 BIT(4) + +#define BIT_SHIFT_SYS_XTAL_DRV_RF1 3 +#define BIT_MASK_SYS_XTAL_DRV_RF1 0x3 +#define BIT_SYS_XTAL_DRV_RF1(x) (((x) & BIT_MASK_SYS_XTAL_DRV_RF1) << BIT_SHIFT_SYS_XTAL_DRV_RF1) + +#define BIT_SYS_XTAL_GATE_RF1 BIT(1) + +#define BIT_SHIFT_SYS_XTAL_LDO 0 +#define BIT_MASK_SYS_XTAL_LDO 0x3 +#define BIT_SYS_XTAL_LDO(x) (((x) & BIT_MASK_SYS_XTAL_LDO) << BIT_SHIFT_SYS_XTAL_LDO) + + +//2 REG_RSVD + +//2 REG_RSVD + +//2 REG_SYS_SYSPLL_CTRL0 + +#define BIT_SHIFT_SYS_SYSPLL_LPF_R3 29 +#define BIT_MASK_SYS_SYSPLL_LPF_R3 0x7 +#define BIT_SYS_SYSPLL_LPF_R3(x) (((x) & BIT_MASK_SYS_SYSPLL_LPF_R3) << BIT_SHIFT_SYS_SYSPLL_LPF_R3) + + +#define BIT_SHIFT_SYS_SYSPLL_LPF_CS 27 +#define BIT_MASK_SYS_SYSPLL_LPF_CS 0x3 +#define BIT_SYS_SYSPLL_LPF_CS(x) (((x) & BIT_MASK_SYS_SYSPLL_LPF_CS) << BIT_SHIFT_SYS_SYSPLL_LPF_CS) + + +#define BIT_SHIFT_SYS_SYSPLL_LPF_CP 25 +#define BIT_MASK_SYS_SYSPLL_LPF_CP 0x3 +#define BIT_SYS_SYSPLL_LPF_CP(x) (((x) & BIT_MASK_SYS_SYSPLL_LPF_CP) << BIT_SHIFT_SYS_SYSPLL_LPF_CP) + + +#define BIT_SHIFT_SYS_SYSPLL_LPF_C3 23 +#define BIT_MASK_SYS_SYSPLL_LPF_C3 0x3 +#define BIT_SYS_SYSPLL_LPF_C3(x) (((x) & BIT_MASK_SYS_SYSPLL_LPF_C3) << BIT_SHIFT_SYS_SYSPLL_LPF_C3) + +#define BIT_SYS_SYSPLL_WDOG_ENB BIT(22) +#define BIT_SYS_SYSPLL_CKTST_EN BIT(21) + +#define BIT_SHIFT_SYS_SYSPLL_MONCK_SEL 18 +#define BIT_MASK_SYS_SYSPLL_MONCK_SEL 0x7 +#define BIT_SYS_SYSPLL_MONCK_SEL(x) (((x) & BIT_MASK_SYS_SYSPLL_MONCK_SEL) << BIT_SHIFT_SYS_SYSPLL_MONCK_SEL) + + +#define BIT_SHIFT_SYS_SYSPLL_CP_IOFFSET 13 +#define BIT_MASK_SYS_SYSPLL_CP_IOFFSET 0x1f +#define BIT_SYS_SYSPLL_CP_IOFFSET(x) (((x) & BIT_MASK_SYS_SYSPLL_CP_IOFFSET) << BIT_SHIFT_SYS_SYSPLL_CP_IOFFSET) + +#define BIT_SYS_SYSPLL_CP_IDOUBLE BIT(12) + +#define BIT_SHIFT_SYS_SYSPLL_CP_BIAS 9 +#define BIT_MASK_SYS_SYSPLL_CP_BIAS 0x7 +#define BIT_SYS_SYSPLL_CP_BIAS(x) (((x) & BIT_MASK_SYS_SYSPLL_CP_BIAS) << BIT_SHIFT_SYS_SYSPLL_CP_BIAS) + +#define BIT_SYS_SYSPLL_FREF_EDGE BIT(8) +#define BIT_SYS_SYSPLL_EN BIT(1) +#define BIT_SYS_SYSPLL_LVPC_EN BIT(0) + +//2 REG_SYS_SYSPLL_CTRL1 +#define BIT_SYS_SYSPLL_CK500K_SEL BIT(15) +#define BIT_SYS_SYSPLL_CK200M_EN BIT(14) +#define BIT_SYS_SYSPLL_CKSDR_EN BIT(13) + +#define BIT_SHIFT_SYS_SYSPLL_CKSDR_DIV 11 +#define BIT_MASK_SYS_SYSPLL_CKSDR_DIV 0x3 +#define BIT_SYS_SYSPLL_CKSDR_DIV(x) (((x) & BIT_MASK_SYS_SYSPLL_CKSDR_DIV) << BIT_SHIFT_SYS_SYSPLL_CKSDR_DIV) + +#define BIT_SYS_SYSPLL_CK24P576_EN BIT(9) +#define BIT_SYS_SYSPLL_CK22P5792_EN BIT(8) +#define BIT_SYS_SYSPLL_CK_PS_EN BIT(6) + +#define BIT_SHIFT_SYS_SYSPLL_CK_PS_SEL 3 +#define BIT_MASK_SYS_SYSPLL_CK_PS_SEL 0x7 +#define BIT_SYS_SYSPLL_CK_PS_SEL(x) (((x) & BIT_MASK_SYS_SYSPLL_CK_PS_SEL) << BIT_SHIFT_SYS_SYSPLL_CK_PS_SEL) + + +#define BIT_SHIFT_SYS_SYSPLL_LPF_RS 0 +#define BIT_MASK_SYS_SYSPLL_LPF_RS 0x7 +#define BIT_SYS_SYSPLL_LPF_RS(x) (((x) & BIT_MASK_SYS_SYSPLL_LPF_RS) << BIT_SHIFT_SYS_SYSPLL_LPF_RS) + + +//2 REG_SYS_SYSPLL_CTRL2 + +#define BIT_SHIFT_XTAL_DRV_RF_LATCH 0 +#define BIT_MASK_XTAL_DRV_RF_LATCH 0xffffffffL +#define BIT_XTAL_DRV_RF_LATCH(x) (((x) & BIT_MASK_XTAL_DRV_RF_LATCH) << BIT_SHIFT_XTAL_DRV_RF_LATCH) + + +//2 REG_RSVD + +//2 REG_RSVD + +#define BIT_SHIFT_PESOC_CPU_OCP_CK_SEL 0 +#define BIT_MASK_PESOC_CPU_OCP_CK_SEL 0x7 +#define BIT_PESOC_CPU_OCP_CK_SEL(x) (((x) & BIT_MASK_PESOC_CPU_OCP_CK_SEL) << BIT_SHIFT_PESOC_CPU_OCP_CK_SEL) + + +//2 REG_RSVD + +//2 REG_RSVD + +//2 REG_ + +//2 REG_SYS_ANA_TIM_CTRL + +#define BIT_SHIFT_SYS_ANACK_TU_TIME 16 +#define BIT_MASK_SYS_ANACK_TU_TIME 0x3f +#define BIT_SYS_ANACK_TU_TIME(x) (((x) & BIT_MASK_SYS_ANACK_TU_TIME) << BIT_SHIFT_SYS_ANACK_TU_TIME) + +#define BIT_SYS_DSBYCNT_EN BIT(15) + +#define BIT_SHIFT_SYS_DSTDY_TIM_SCAL 8 +#define BIT_MASK_SYS_DSTDY_TIM_SCAL 0xf +#define BIT_SYS_DSTDY_TIM_SCAL(x) (((x) & BIT_MASK_SYS_DSTDY_TIM_SCAL) << BIT_SHIFT_SYS_DSTDY_TIM_SCAL) + + +#define BIT_SHIFT_SYS_DSTBY_TIM_PERIOD 0 +#define BIT_MASK_SYS_DSTBY_TIM_PERIOD 0xff +#define BIT_SYS_DSTBY_TIM_PERIOD(x) (((x) & BIT_MASK_SYS_DSTBY_TIM_PERIOD) << BIT_SHIFT_SYS_DSTBY_TIM_PERIOD) + + +//2 REG_SYS_DSLP_TIM_CTRL + +#define BIT_SHIFT_SYS_REGU_ASIF_EN 24 +#define BIT_MASK_SYS_REGU_ASIF_EN 0xff +#define BIT_SYS_REGU_ASIF_EN(x) (((x) & BIT_MASK_SYS_REGU_ASIF_EN) << BIT_SHIFT_SYS_REGU_ASIF_EN) + + +#define BIT_SHIFT_SYS_REGU_ASIF_THP_DA 20 +#define BIT_MASK_SYS_REGU_ASIF_THP_DA 0x3 +#define BIT_SYS_REGU_ASIF_THP_DA(x) (((x) & BIT_MASK_SYS_REGU_ASIF_THP_DA) << BIT_SHIFT_SYS_REGU_ASIF_THP_DA) + + +#define BIT_SHIFT_SYS_REGU_ASIF_TPD_CK 18 +#define BIT_MASK_SYS_REGU_ASIF_TPD_CK 0x3 +#define BIT_SYS_REGU_ASIF_TPD_CK(x) (((x) & BIT_MASK_SYS_REGU_ASIF_TPD_CK) << BIT_SHIFT_SYS_REGU_ASIF_TPD_CK) + + +#define BIT_SHIFT_SYS_REGU_ASIF_TSP_DA 16 +#define BIT_MASK_SYS_REGU_ASIF_TSP_DA 0x3 +#define BIT_SYS_REGU_ASIF_TSP_DA(x) (((x) & BIT_MASK_SYS_REGU_ASIF_TSP_DA) << BIT_SHIFT_SYS_REGU_ASIF_TSP_DA) + +#define BIT_SYS_REGU_ASIF_POLL BIT(15) +#define BIT_SYS_REGU_ASIF_MODE BIT(14) +#define BIT_SYS_REGU_ASIF_WE BIT(12) + +#define BIT_SHIFT_SYS_REGU_ASIF_AD 8 +#define BIT_MASK_SYS_REGU_ASIF_AD 0xf +#define BIT_SYS_REGU_ASIF_AD(x) (((x) & BIT_MASK_SYS_REGU_ASIF_AD) << BIT_SHIFT_SYS_REGU_ASIF_AD) + + +#define BIT_SHIFT_SYS_REGU_ASIF_WD 0 +#define BIT_MASK_SYS_REGU_ASIF_WD 0xff +#define BIT_SYS_REGU_ASIF_WD(x) (((x) & BIT_MASK_SYS_REGU_ASIF_WD) << BIT_SHIFT_SYS_REGU_ASIF_WD) + + +//2 REG_SYS_DSLP_TIM_CAL_CTRL +#define BIT_SYS_DSLP_TIM_EN BIT(24) + +#define BIT_SHIFT_SYS_DSLP_TIM_PERIOD 0 +#define BIT_MASK_SYS_DSLP_TIM_PERIOD 0x7fffff +#define BIT_SYS_DSLP_TIM_PERIOD(x) (((x) & BIT_MASK_SYS_DSLP_TIM_PERIOD) << BIT_SHIFT_SYS_DSLP_TIM_PERIOD) + + +//2 REG_RSVD + +//2 REG_SYS_DEBUG_CTRL +#define BIT_SYS_DBG_PIN_EN BIT(0) + +//2 REG_SYS_PINMUX_CTRL +#define BIT_EEPROM_PIN_EN BIT(4) +#define BIT_SIC_PIN_EN BIT(0) + +//2 REG_SYS_GPIO_DSTBY_WAKE_CTRL0 +#define BIT_SYS_GPIOE3_WEVENT_STS BIT(27) +#define BIT_SYS_GPIOD5_WEVENT_STS BIT(26) +#define BIT_SYS_GPIOC7_WEVENT_STS BIT(25) +#define BIT_SYS_GPIOA5_WEVENT_STS BIT(24) +#define BIT_SYS_GPIO_GPE3_PULL_CTRL_EN BIT(19) +#define BIT_SYS_GPIO_GPD5_PULL_CTRL_EN BIT(18) +#define BIT_SYS_GPIO_GPC7_PULL_CTRL_EN BIT(17) +#define BIT_SYS_GPIO_GPA5_PULL_CTRL_EN BIT(16) +#define BIT_SYS_GPIOE3_WINT_MODE BIT(11) +#define BIT_SYS_GPIOD5_WINT_MODE BIT(10) +#define BIT_SYS_GPIOC7_WINT_MODE BIT(9) +#define BIT_SYS_GPIOA5_WINT_MODE BIT(8) +#define BIT_SYS_GPIOE3_PIN_EN BIT(3) +#define BIT_SYS_GPIOD5_PIN_EN BIT(2) +#define BIT_SYS_GPIOC7_PIN_EN BIT(1) +#define BIT_SYS_GPIOA5_PIN_EN BIT(0) + +//2 REG_SYS_GPIO_DSTBY_WAKE_CTRL1 +#define BIT_SYS_GPIOE3_SHTDN_N BIT(19) +#define BIT_SYS_GPIOD5_SHTDN_N BIT(18) +#define BIT_SYS_GPIOC7_SHTDN_N BIT(17) +#define BIT_SYS_GPIOA5_SHTDN_N BIT(16) + +#define BIT_SHIFT_SYS_WINT_DEBOUNCE_TIM_SCAL 8 +#define BIT_MASK_SYS_WINT_DEBOUNCE_TIM_SCAL 0x3 +#define BIT_SYS_WINT_DEBOUNCE_TIM_SCAL(x) (((x) & BIT_MASK_SYS_WINT_DEBOUNCE_TIM_SCAL) << BIT_SHIFT_SYS_WINT_DEBOUNCE_TIM_SCAL) + +#define BIT_SYS_GPIOE3_WINT_DEBOUNCE_EN BIT(3) +#define BIT_SYS_GPIOD5_WINT_DEBOUNCE_EN BIT(2) +#define BIT_SYS_GPIOC7_WINT_DEBOUNCE_EN BIT(1) +#define BIT_SYS_GPIOA5_WINT_DEBOUNCE_EN BIT(0) + +//2 REG_RSVD + +//2 REG_NOT_VALID + +//2 REG_RSVD + +//2 REG_RSVD + +//2 REG_NOT_VALID + +//2 REG_SYS_DEBUG_REG + +#define BIT_SHIFT_SYS_DBG_VALUE 0 +#define BIT_MASK_SYS_DBG_VALUE 0xffffffffL +#define BIT_SYS_DBG_VALUE(x) (((x) & BIT_MASK_SYS_DBG_VALUE) << BIT_SHIFT_SYS_DBG_VALUE) + + +//2 REG_RSVD + +//2 REG_NOT_VALID + +//2 REG_RSVD + +//2 REG_NOT_VALID + +//2 REG_RSVD + +//2 REG_NOT_VALID + +//2 REG_RSVD + +//2 REG_NOT_VALID + +//2 REG_RSVD + +//2 REG_NOT_VALID + +//2 REG_RSVD + +//2 REG_NOT_VALID + +//2 REG_RSVD + +//2 REG_NOT_VALID + +//2 REG_RSVD + +//2 REG_NOT_VALID + +//2 REG_SYS_EEPROM_CTRL0 + +#define BIT_SHIFT_EFUSE_UNLOCK 24 +#define BIT_MASK_EFUSE_UNLOCK 0xff +#define BIT_EFUSE_UNLOCK(x) (((x) & BIT_MASK_EFUSE_UNLOCK) << BIT_SHIFT_EFUSE_UNLOCK) + + +//2 REG_NOT_VALID +#define BIT_SYS_EFUSE_LDALL BIT(16) + +#define BIT_SHIFT_SYS_EEPROM_VPDIDX 8 +#define BIT_MASK_SYS_EEPROM_VPDIDX 0xff +#define BIT_SYS_EEPROM_VPDIDX(x) (((x) & BIT_MASK_SYS_EEPROM_VPDIDX) << BIT_SHIFT_SYS_EEPROM_VPDIDX) + + +#define BIT_SHIFT_SYS_EEPROM_MD 6 +#define BIT_MASK_SYS_EEPROM_MD 0x3 +#define BIT_SYS_EEPROM_MD(x) (((x) & BIT_MASK_SYS_EEPROM_MD) << BIT_SHIFT_SYS_EEPROM_MD) + +#define BIT_SYS_AUTOLOAD_SUS BIT(5) +#define BIT_SYS_EEPROM_SEL BIT(4) +#define BIT_SYS_EEPROM_EECS BIT(3) +#define BIT_SYS_EEPROM_EESK BIT(2) +#define BIT_SYS_EEPROM_EEDI BIT(1) +#define BIT_SYS_EEPROM_EEDO BIT(0) + +//2 REG_SYS_EEPROM_CTRL1 + +#define BIT_SHIFT_SYS_EEPROM_VPD 0 +#define BIT_MASK_SYS_EEPROM_VPD 0xffffffffL +#define BIT_SYS_EEPROM_VPD(x) (((x) & BIT_MASK_SYS_EEPROM_VPD) << BIT_SHIFT_SYS_EEPROM_VPD) + + +//2 REG_SYS_EFUSE_CTRL +#define BIT_SYS_EF_RWFLAG BIT(31) + +#define BIT_SHIFT_SYS_EF_PGPD 28 +#define BIT_MASK_SYS_EF_PGPD 0x7 +#define BIT_SYS_EF_PGPD(x) (((x) & BIT_MASK_SYS_EF_PGPD) << BIT_SHIFT_SYS_EF_PGPD) + + +#define BIT_SHIFT_SYS_EF_RDT 24 +#define BIT_MASK_SYS_EF_RDT 0xf +#define BIT_SYS_EF_RDT(x) (((x) & BIT_MASK_SYS_EF_RDT) << BIT_SHIFT_SYS_EF_RDT) + + +#define BIT_SHIFT_SYS_EF_PGTS 20 +#define BIT_MASK_SYS_EF_PGTS 0xf +#define BIT_SYS_EF_PGTS(x) (((x) & BIT_MASK_SYS_EF_PGTS) << BIT_SHIFT_SYS_EF_PGTS) + +#define BIT_SYS_EF_PDWN BIT(19) +#define BIT_SYS_EF_ALDEN BIT(18) + +#define BIT_SHIFT_SYS_EF_ADDR 8 +#define BIT_MASK_SYS_EF_ADDR 0x3ff +#define BIT_SYS_EF_ADDR(x) (((x) & BIT_MASK_SYS_EF_ADDR) << BIT_SHIFT_SYS_EF_ADDR) + + +#define BIT_SHIFT_SYS_EF_DATA 0 +#define BIT_MASK_SYS_EF_DATA 0xff +#define BIT_SYS_EF_DATA(x) (((x) & BIT_MASK_SYS_EF_DATA) << BIT_SHIFT_SYS_EF_DATA) + + +//2 REG_SYS_EFUSE_TEST +#define BIT_SYS_EF_CRES_SEL BIT(26) + +#define BIT_SHIFT_SYS_EF_SCAN_START 16 +#define BIT_MASK_SYS_EF_SCAN_START 0x1ff +#define BIT_SYS_EF_SCAN_START(x) (((x) & BIT_MASK_SYS_EF_SCAN_START) << BIT_SHIFT_SYS_EF_SCAN_START) + + +#define BIT_SHIFT_SYS_EF_SCAN_END 12 +#define BIT_MASK_SYS_EF_SCAN_END 0xf +#define BIT_SYS_EF_SCAN_END(x) (((x) & BIT_MASK_SYS_EF_SCAN_END) << BIT_SHIFT_SYS_EF_SCAN_END) + +#define BIT_SYS_EF_FORCE_PGMEN BIT(11) + +#define BIT_SHIFT_SYS_EF_CELL_SEL 8 +#define BIT_MASK_SYS_EF_CELL_SEL 0x3 +#define BIT_SYS_EF_CELL_SEL(x) (((x) & BIT_MASK_SYS_EF_CELL_SEL) << BIT_SHIFT_SYS_EF_CELL_SEL) + +#define BIT_SYS_EF_TRPT BIT(7) + +#define BIT_SHIFT_SYS_EF_SCAN_TTHD 0 +#define BIT_MASK_SYS_EF_SCAN_TTHD 0x7f +#define BIT_SYS_EF_SCAN_TTHD(x) (((x) & BIT_MASK_SYS_EF_SCAN_TTHD) << BIT_SHIFT_SYS_EF_SCAN_TTHD) + + +//2 REG_SYS_DSTBY_INFO0 + +//2 REG_NOT_VALID + +//2 REG_SYS_DSTBY_INFO1 + +//2 REG_SYS_DSTBY_INFO2 + +//2 REG_NOT_VALID + +//2 REG_SYS_DSTBY_INFO3 + +//2 REG_SYS_SLP_WAKE_EVENT_MSK0 +#define BIT_SYSON_WEVT_GPIO_DSTBY_MSK BIT(29) +#define BIT_SYSON_WEVT_A33_MSK BIT(28) +#define BIT_SYSON_WEVT_ADC_MSK BIT(26) +#define BIT_SYSON_WEVT_I2C_MSK BIT(24) +#define BIT_SYSON_WEVT_SPI_MSK BIT(22) +#define BIT_SYSON_WEVT_UART_MSK BIT(20) +#define BIT_SYSON_WEVT_USB_MSK BIT(16) +#define BIT_SYSON_WEVT_SDIO_MSK BIT(14) +#define BIT_SYSON_WEVT_NFC_MSK BIT(9) +#define BIT_SYSON_WEVT_WLAN_MSK BIT(8) +#define BIT_SYSON_WEVT_GPIO_MSK BIT(4) +#define BIT_SYSON_WEVT_CHIP_EN_MSK BIT(3) +#define BIT_SYSON_WEVT_OVER_CURRENT_MSK BIT(2) +#define BIT_SYSON_WEVT_GTIM_MSK BIT(1) +#define BIT_SYSON_WEVT_SYSTIM_MSK BIT(0) + +//2 REG_SYS_SLP_WAKE_EVENT_MSK1 + +//2 REG_SYS_SLP_WAKE_EVENT_STATUS0 +#define BIT_SYSON_WEVT_GPIO_DSTBY_STS BIT(29) +#define BIT_SYSON_WEVT_A33_STS BIT(28) +#define BIT_SYSON_WEVT_ADC_STS BIT(26) +#define BIT_SYSON_WEVT_I2C_STS BIT(24) +#define BIT_SYSON_WEVT_SPI_STS BIT(22) +#define BIT_SYSON_WEVT_UART_STS BIT(20) +#define BIT_SYSON_WEVT_USB_STS BIT(16) +#define BIT_SYSON_WEVT_SDIO_STS BIT(14) +#define BIT_SYSON_WEVT_NFC_STS BIT(9) +#define BIT_SYSON_WEVT_WLAN_STS BIT(8) +#define BIT_SYSON_WEVT_GPIO_STS BIT(4) +#define BIT_SYSON_WEVT_CHIP_EN_STS BIT(3) +#define BIT_SYSON_WEVT_OVER_CURRENT_STS BIT(2) +#define BIT_SYSON_WEVT_GTIM_STS BIT(1) +#define BIT_SYSON_WEVT_SYSTIM_STS BIT(0) + +//2 REG_SYS_SLP_WAKE_EVENT_STATUS1 + +//2 REG_SYS_SNF_WAKE_EVENT_MSK0 + +#define BIT_SHIFT_SYS_WKPERI_IMR0 1 +#define BIT_MASK_SYS_WKPERI_IMR0 0x7fffffffL +#define BIT_SYS_WKPERI_IMR0(x) (((x) & BIT_MASK_SYS_WKPERI_IMR0) << BIT_SHIFT_SYS_WKPERI_IMR0) + +#define BIT_SYSON_SNFEVT_ADC_MSK BIT(0) + +//2 REG_SYS_SNF_WAKE_EVENT_STATUS + +#define BIT_SHIFT_SYS_WKPERI_ISR0 1 +#define BIT_MASK_SYS_WKPERI_ISR0 0x7fffffffL +#define BIT_SYS_WKPERI_ISR0(x) (((x) & BIT_MASK_SYS_WKPERI_ISR0) << BIT_SHIFT_SYS_WKPERI_ISR0) + +#define BIT_SYSON_SNFEVT_ADC_STS BIT(0) + +//2 REG_SYS_PWRMGT_CTRL +#define BIT_SYSON_REGU_DSLP BIT(7) + +//2 REG_NOT_VALID +#define BIT_SYSON_PM_CMD_SLP BIT(2) +#define BIT_SYSON_PM_CMD_DSTBY BIT(1) +#define BIT_SYSON_PM_CMD_DSLP BIT(0) + +//2 REG_RSVD + +//2 REG_SYS_PWRMGT_OPTION +#define BIT_SYSON_PMOPT_NORM_SYSCLK_SEL BIT(30) +#define BIT_SYSON_PMOPT_NORM_SYSPLL_EN BIT(29) +#define BIT_SYSON_PMOPT_NORM_XTAL_EN BIT(28) +#define BIT_SYSON_PMOPT_NORM_EN_SOC BIT(27) +#define BIT_SYSON_PMOPT_NORM_EN_PWM BIT(26) +#define BIT_SYSON_PMOPT_NORM_EN_SWR BIT(25) +#define BIT_SYSON_PMOPT_NORM_LPLDO_SEL BIT(24) +#define BIT_SYSON_PMOPT_SNZ_SYSCLK_SEL BIT(22) +#define BIT_SYSON_PMOPT_SNZ_SYSPLL_EN BIT(21) +#define BIT_SYSON_PMOPT_SNZ_XTAL_EN BIT(20) +#define BIT_SYSON_PMOPT_SNZ_EN_SOC BIT(19) +#define BIT_SYSON_PMOPT_SNZ_EN_PWM BIT(18) +#define BIT_SYSON_PMOPT_SNZ_EN_SWR BIT(17) +#define BIT_SYSON_PMOPT_SNZ_LPLDO_SEL BIT(16) +#define BIT_SYSON_PMOPT_SLP_SYSCLK_SEL BIT(14) +#define BIT_SYSON_PMOPT_SLP_SYSPLL_EN BIT(13) +#define BIT_SYSON_PMOPT_SLP_XTAL_EN BIT(12) +#define BIT_SYSON_PMOPT_SLP_EN_SOC BIT(11) +#define BIT_SYSON_PMOPT_SLP_EN_PWM BIT(10) +#define BIT_SYSON_PMOPT_SLP_EN_SWR BIT(9) +#define BIT_SYSON_PMOPT_SLP_LPLDO_SEL BIT(8) +#define BIT_SYSON_PMOPT_DSTBY_SYSCLK_SEL BIT(6) +#define BIT_SYSON_PMOPT_DSTBY_SYSPLL_EN BIT(5) +#define BIT_SYSON_PMOPT_DSTBY_XTAL_EN BIT(4) +#define BIT_SYSON_PMOPT_DSTBY_EN_SOC BIT(3) +#define BIT_SYSON_PMOPT_DSTBY_EN_PWM BIT(2) +#define BIT_SYSON_PMOPT_DSTBY_EN_SWR BIT(1) +#define BIT_SYSON_PMOPT_DSTBY_LPLDO_SEL BIT(0) + +//2 REG_SYS_PWRMGT_OPTION_EXT +#define BIT_SYSON_PMOPT_SLP_ANACK_SEL BIT(2) +#define BIT_SYSON_PMOPT_SLP_ANACK_EN BIT(1) +#define BIT_SYSON_PMOPT_SLP_SWR_ADJ BIT(0) + +//2 REG_SYS_DSLP_WEVENT +#define BIT_SYSON_DSLP_GPIO BIT(2) +#define BIT_SYSON_DSLP_NFC BIT(1) +#define BIT_SYSON_DSLP_WTIMER33 BIT(0) + +//2 REG_SYS_PERI_MONITOR +#define BIT_SYSON_ISO33_NFC BIT(0) + +//2 REG_SYS_SYSTEM_CFG0 +#define BIT_SYSCFG_BD_PKG_SEL BIT(31) + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +#define BIT_SHIFT_VENDOR_ID 8 +#define BIT_MASK_VENDOR_ID 0xf +#define BIT_VENDOR_ID(x) (((x) & BIT_MASK_VENDOR_ID) << BIT_SHIFT_VENDOR_ID) + + +#define BIT_SHIFT_CHIP_VER 4 +#define BIT_MASK_CHIP_VER 0xf +#define BIT_CHIP_VER(x) (((x) & BIT_MASK_CHIP_VER) << BIT_SHIFT_CHIP_VER) + + +#define BIT_SHIFT_RF_RL_ID 0 +#define BIT_MASK_RF_RL_ID 0xf +#define BIT_RF_RL_ID(x) (((x) & BIT_MASK_RF_RL_ID) << BIT_SHIFT_RF_RL_ID) + + +//2 REG_SYS_SYSTEM_CFG1 + +#define BIT_SHIFT_SYSCFG_TRP_ICFG 28 +#define BIT_MASK_SYSCFG_TRP_ICFG 0xf +#define BIT_SYSCFG_TRP_ICFG(x) (((x) & BIT_MASK_SYSCFG_TRP_ICFG) << BIT_SHIFT_SYSCFG_TRP_ICFG) + +#define BIT_SYSCFG_TRP_BOOT_SEL_ BIT(27) +#define BIT_SysCFG_TRP_SPSLDO_SEL BIT(26) +#define BIT_V15_VLD BIT(16) +#define BIT_SYS_SYSPLL_CLK_RDY BIT(9) +#define BIT_SYS_XCLK_VLD BIT(8) +#define BIT_SYSCFG_ALDN_STS BIT(0) + +//2 REG_RSVD + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + +//2 REG_RSVD + +//2 REG_NOT_VALID + +//2 REG_NOT_VALID + + +//================= Register Address Definition =====================// +#define REG_SYS_PWR_CTRL 0x0000 +#define REG_SYS_ISO_CTRL 0x0002 +#define REG_SYS_FUNC_EN 0x0008 +#define REG_SYS_CLK_CTRL0 0x0010 +#define REG_SYS_CLK_CTRL1 0x0014 +#define REG_SYS_EFUSE_SYSCFG0 0x0020 +#define REG_SYS_EFUSE_SYSCFG1 0x0024 +#define REG_SYS_EFUSE_SYSCFG2 0x0028 +#define REG_SYS_EFUSE_SYSCFG3 0x002C +#define REG_SYS_EFUSE_SYSCFG4 0x0030 +#define REG_SYS_EFUSE_SYSCFG5 0x0034 +#define REG_SYS_EFUSE_SYSCFG6 0x0038 +#define REG_SYS_EFUSE_SYSCFG7 0x003C +#define REG_SYS_REGU_CTRL0 0x0040 +#define REG_SYS_SWR_CTRL0 0x0048 +#define REG_SYS_SWR_CTRL1 0x004C +#define REG_SYS_XTAL_CTRL0 0x0060 +#define REG_SYS_XTAL_CTRL1 0x0064 +#define REG_SYS_SYSPLL_CTRL0 0x0070 +#define REG_SYS_SYSPLL_CTRL1 0x0074 +#define REG_SYS_SYSPLL_CTRL2 0x0078 +#define REG_SYS_ANA_TIM_CTRL 0x0090 +#define REG_SYS_DSLP_TIM_CTRL 0x0094 +#define REG_SYS_DSLP_TIM_CAL_CTRL 0x0098 +#define REG_SYS_DEBUG_CTRL 0x00A0 +#define REG_SYS_PINMUX_CTRL 0x00A4 +#define REG_SYS_GPIO_DSTBY_WAKE_CTRL0 0x00A8 +#define REG_SYS_GPIO_DSTBY_WAKE_CTRL1 0x00AC +#define REG_SYS_DEBUG_REG 0x00BC +#define REG_SYS_EEPROM_CTRL0 0x00E0 +#define REG_SYS_EEPROM_CTRL1 0x00E4 +#define REG_SYS_EFUSE_CTRL 0x00E8 +#define REG_SYS_EFUSE_TEST 0x00EC +#define REG_SYS_DSTBY_INFO0 0x00F0 +#define REG_SYS_DSTBY_INFO1 0x00F4 +#define REG_SYS_DSTBY_INFO2 0x00F8 +#define REG_SYS_DSTBY_INFO3 0x00FC +#define REG_SYS_SLP_WAKE_EVENT_MSK0 0x0100 +#define REG_SYS_SLP_WAKE_EVENT_MSK1 0x0104 +#define REG_SYS_SLP_WAKE_EVENT_STATUS0 0x0108 +#define REG_SYS_SLP_WAKE_EVENT_STATUS1 0x010C +#define REG_SYS_SNF_WAKE_EVENT_MSK0 0x0110 +#define REG_SYS_SNF_WAKE_EVENT_STATUS 0x0114 +#define REG_SYS_PWRMGT_CTRL 0x0118 +#define REG_SYS_PWRMGT_OPTION 0x0120 +#define REG_SYS_PWRMGT_OPTION_EXT 0x0124 +#define REG_SYS_DSLP_WEVENT 0x0130 +#define REG_SYS_PERI_MONITOR 0x0134 +#define REG_SYS_SYSTEM_CFG0 0x01F0 +#define REG_SYS_SYSTEM_CFG1 0x01F4 +#define REG_SYS_SYSTEM_CFG2 0x01F8 + +#endif diff --git a/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_timer.h b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_timer.h new file mode 100644 index 0000000..da4a540 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_timer.h @@ -0,0 +1,222 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#ifndef _RTL8195A_TIMER_H_ +#define _RTL8195A_TIMER_H_ + + +#define TIMER_TICK_US 31 + +#define TIMER_LOAD_COUNT_OFF 0x00 +#define TIMER_CURRENT_VAL_OFF 0x04 +#define TIMER_CTL_REG_OFF 0x08 +#define TIMER_EOI_OFF 0x0c +#define TIMER_INT_STATUS_OFF 0x10 +#define TIMER_INTERVAL 0x14 +#define TIMERS_INT_STATUS_OFF 0xa0 +#define TIMERS_EOI_OFF 0xa4 +#define TIMERS_RAW_INT_STATUS_OFF 0xa8 +#define TIMERS_COMP_VER_OFF 0xac + +#define MAX_TIMER_VECTOR_TABLE_NUM 6 + +#define HAL_TIMER_READ32(addr) (*((volatile u32*)(TIMER_REG_BASE + addr)))//HAL_READ32(TIMER_REG_BASE, addr) +#define HAL_TIMER_WRITE32(addr, value) ((*((volatile u32*)(TIMER_REG_BASE + addr))) = value)//HAL_WRITE32(TIMER_REG_BASE, addr, value) +#define HAL_TIMER_READ16(addr) (*((volatile u16*)(TIMER_REG_BASE + addr)))//HAL_READ16(TIMER_REG_BASE, addr) +#define HAL_TIMER_WRITE16(addr, value) ((*((volatile u16*)(TIMER_REG_BASE + addr))) = value)//HAL_WRITE16(TIMER_REG_BASE, addr, value) +#define HAL_TIMER_READ8(addr) (*((volatile u8*)(TIMER_REG_BASE + addr)))//HAL_READ8(TIMER_REG_BASE, addr) +#define HAL_TIMER_WRITE8(addr, value) ((*((volatile u8*)(TIMER_REG_BASE + addr))) = value)//HAL_WRITE8(TIMER_REG_BASE, addr, value) + +_LONG_CALL_ u32 +HalGetTimerIdRtl8195a( + IN u32 *TimerID +); + +_LONG_CALL_ BOOL +HalTimerInitRtl8195a( + IN VOID *Data +); + +_LONG_CALL_ u32 +HalTimerReadCountRtl8195a( + IN u32 TimerId +); + +_LONG_CALL_ VOID +HalTimerIrqClearRtl8195a( + IN u32 TimerId +); + +_LONG_CALL_ VOID +HalTimerDisRtl8195a( + IN u32 TimerId +); + +_LONG_CALL_ VOID +HalTimerEnRtl8195a( + IN u32 TimerId +); + +_LONG_CALL_ VOID +HalTimerDumpRegRtl8195a( + IN u32 TimerId +); + +// ROM Code patch +HAL_Status +HalTimerInitRtl8195a_Patch( + IN VOID *Data +); + +u32 +HalTimerReadCountRtl8195a_Patch( + IN u32 TimerId +); + +VOID +HalTimerReLoadRtl8195a_Patch( + IN u32 TimerId, + IN u32 LoadUs +); + +u32 +HalTimerReadCountRtl8195a_Patch( + IN u32 TimerId +); + +VOID +HalTimerIrqEnRtl8195a( + IN u32 TimerId +); + +VOID +HalTimerIrqDisRtl8195a( + IN u32 TimerId +); + +VOID +HalTimerEnRtl8195a_Patch( + IN u32 TimerId +); + +VOID +HalTimerDisRtl8195a_Patch( + IN u32 TimerId +); + +VOID +HalTimerDeInitRtl8195a_Patch( + IN VOID *Data +); + +#ifdef CONFIG_CHIP_C_CUT + +__weak _LONG_CALL_ +VOID +HalTimerIrq2To7HandleV02( + IN VOID *Data +); + +__weak _LONG_CALL_ +HAL_Status +HalTimerIrqRegisterRtl8195aV02( + IN VOID *Data +); + +__weak _LONG_CALL_ +HAL_Status +HalTimerInitRtl8195aV02( + IN VOID *Data +); + +__weak _LONG_CALL_ +u32 +HalTimerReadCountRtl8195aV02( + IN u32 TimerId +); + +__weak _LONG_CALL_ +VOID +HalTimerReLoadRtl8195aV02( + IN u32 TimerId, + IN u32 LoadUs +); + +__weak _LONG_CALL_ +HAL_Status +HalTimerIrqUnRegisterRtl8195aV02( + IN VOID *Data +); + +__weak _LONG_CALL_ +VOID +HalTimerDeInitRtl8195aV02( + IN VOID *Data +); + +#endif // end of "#ifdef CONFIG_CHIP_C_CUT" + +// HAL functions wrapper +static __inline HAL_Status +HalTimerInit( + IN VOID *Data +) +{ + return (HalTimerInitRtl8195a_Patch(Data)); +} + +static __inline VOID +HalTimerEnable( + IN u32 TimerId +) +{ + HalTimerIrqEnRtl8195a(TimerId); + HalTimerEnRtl8195a_Patch(TimerId); +} + +static __inline VOID +HalTimerDisable( + IN u32 TimerId +) +{ + HalTimerDisRtl8195a_Patch(TimerId); +} + +static __inline VOID +HalTimerReLoad( + IN u32 TimerId, + IN u32 LoadUs +) +{ + HalTimerReLoadRtl8195a_Patch(TimerId, LoadUs); +} + +#ifndef CONFIG_CHIP_C_CUT + +static __inline VOID +HalTimerDeInit( + IN VOID *Data +) +{ + HalTimerDeInitRtl8195a_Patch(Data); +} + +#else + +static __inline VOID +HalTimerDeInit( + IN VOID *Data +) +{ + HalTimerDeInitRtl8195aV02(Data); +} + +#endif // end of "#ifndef CONFIG_CHIP_C_CUT" + +#endif //_RTL8195A_TIMER_H_ diff --git a/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_uart.h b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_uart.h new file mode 100644 index 0000000..a2051b4 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_uart.h @@ -0,0 +1,403 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + + +#ifndef _RTL8195A_UART_H_ +#define _RTL8195A_UART_H_ + +#define MAX_UART_INDEX 2 + +#define RUART_DLL_OFF 0x00 +#define RUART_DLM_OFF 0x04 //RW, DLAB = 1 +#define RUART_INTERRUPT_EN_REG_OFF 0x04 +#define RUART_IER_ERBI 0x01 //BIT0, Enable Received Data Available Interrupt (rx trigger) +#define RUART_IER_ETBEI (1<<1) //BIT1, Enable Transmitter FIFO Empty Interrupt (tx fifo empty) +#define RUART_IER_ELSI (1<<2) //BIT2, Enable Receiver Line Status Interrupt (receiver line status) +#define RUART_IER_EDSSI (1<<3) //BIT3, Enable Modem Status Interrupt (modem status transition) + +#define RUART_INT_ID_REG_OFF 0x08 //[R] +#define RUART_IIR_INT_PEND 0x01 +#define RUART_IIR_INT_ID (0x07<<1) //011(3), 010(2), 110(6), 001(1), 000(0) +#define RUART_FIFO_CTL_REG_OFF 0x08 //[W] +#define RUART_FIFO_CTL_REG_CLEAR_RXFIFO (1<<1) //BIT1, 0x02, Write 1 clear +#define RUART_FIFO_CTL_REG_CLEAR_TXFIFO (1<<2) //BIT2, 0x04, Write 1 clear +#define RUART_FIFO_CTL_REG_DMA_ENABLE 0x08 //BIT3 + +#define FIFO_CTL_DEFAULT_WITH_FIFO_DMA 0xC9 +#define FIFO_CTL_DEFAULT_WITH_FIFO 0xC1 + +#define RUART_MODEM_CTL_REG_OFF 0x10 +#define RUART_MCR_RTS BIT1 +#define RUART_MCL_AUTOFLOW_ENABLE (1<<5) //BIT5, 0x20 + +#define RUART_LINE_CTL_REG_OFF 0x0C +#define RUART_LINE_CTL_REG_DLAB_ENABLE (1<<7) //BIT7, 0x80 + +#define RUART_LINE_STATUS_REG_OFF 0x14 +#define RUART_LINE_STATUS_REG_DR 0x01 //BIT0, Data Ready indicator +#define RUART_LINE_STATUS_ERR_OVERRUN (1<<1) //BIT1, Over Run +#define RUART_LINE_STATUS_ERR_PARITY (1<<2) //BIT2, Parity error +#define RUART_LINE_STATUS_ERR_FRAMING (1<<3) //BIT3, Framing error +#define RUART_LINE_STATUS_ERR_BREAK (1<<4) //BIT4, Break interrupt error +#define RUART_LINE_STATUS_REG_THRE (1<<5) //BIT5, 0x20, Transmit Holding Register Empty Interrupt enable +#define RUART_LINE_STATUS_REG_TEMT (1<<6) //BIT6, 0x40, Transmitter Empty indicator(bit) +#define RUART_LINE_STATUS_ERR_RXFIFO (1<<7) //BIT7, RX FIFO error +#define RUART_LINE_STATUS_ERR (RUART_LINE_STATUS_ERR_OVERRUN|RUART_LINE_STATUS_ERR_PARITY| \ + RUART_LINE_STATUS_ERR_FRAMING|RUART_LINE_STATUS_ERR_BREAK| \ + RUART_LINE_STATUS_ERR_RXFIFO) //Line status error + +#define RUART_MODEM_STATUS_REG_OFF 0x18 //Modem Status Register +#define RUART_SCRATCH_PAD_REG_OFF 0x1C //Scratch Pad Register +#define RUART_SP_REG_RXBREAK_INT_STATUS (1<<7) //BIT7, 0x80, Write 1 clear +#define RUART_SP_REG_DBG_SEL 0x0F<<8 //[11:8], Debug port selection +#define RUART_SP_REG_XFACTOR_ADJ 0x7FF<<16 //[26:16] + +#define RUART_STS_REG_OFF 0x20 +#define RUART_STS_REG_RESET_RCV (1<<3) //BIT3, 0x08, Reset Uart Receiver +#define RUART_STS_REG_XFACTOR 0xF<<4 + +#define RUART_REV_BUF_REG_OFF 0x24 //Receiver Buffer Register +#define RUART_TRAN_HOLD_REG_OFF 0x24 //Transmitter Holding Register + +#define RUART_MISC_CTL_REG_OFF 0x28 +#define RUART_TXDMA_BURSTSIZE_MASK 0xF8 //7:3 +#define RUART_RXDMA_BURSTSIZE_MASK 0x1F00 //12:8 + +#define RUART_DEBUG_REG_OFF 0x3C + +// RUART_LINE_CTL_REG_OFF (0x0C) +#define BIT_SHIFT_LCR_WLS 0 // word length select: 0: 7 bits, 1: 8bits +#define BIT_MASK_LCR_WLS_8BITS 0x1 +#define BIT_LCR_WLS(x)(((x) & BIT_MASK_LCR_WLS_8BITS) << BIT_SHIFT_LCR_WLS) +#define BIT_CLR_LCR_WLS (~(BIT_MASK_LCR_WLS_8BITS << BIT_SHIFT_LCR_WLS)) + +#define BIT_SHIFT_LCR_STB 2 // Stop bit select: 0: no stop bit, 1: 1 stop bit +#define BIT_MASK_LCR_STB_EN 0x1 +#define BIT_LCR_STB_EN(x)(((x) & BIT_MASK_LCR_STB_EN) << BIT_SHIFT_LCR_STB) +#define BIT_INVC_LCR_STB_EN (~(BIT_MASK_LCR_STB_EN << BIT_SHIFT_LCR_STB)) + +#define BIT_SHIFT_LCR_PARITY_EN 3 +#define BIT_MASK_LCR_PARITY_EN 0x1 +#define BIT_LCR_PARITY_EN(x)(((x) & BIT_MASK_LCR_PARITY_EN) << BIT_SHIFT_LCR_PARITY_EN) +#define BIT_INVC_LCR_PARITY_EN (~(BIT_MASK_LCR_PARITY_EN << BIT_SHIFT_LCR_PARITY_EN)) + +#define BIT_SHIFT_LCR_PARITY_TYPE 4 +#define BIT_MASK_LCR_PARITY_TYPE 0x1 +#define BIT_LCR_PARITY_TYPE(x)(((x) & BIT_MASK_LCR_PARITY_TYPE) << BIT_SHIFT_LCR_PARITY_TYPE) +#define BIT_INVC_LCR_PARITY_TYPE (~(BIT_MASK_LCR_PARITY_TYPE << BIT_SHIFT_LCR_PARITY_TYPE)) + +#define BIT_SHIFT_LCR_STICK_PARITY_EN 5 +#define BIT_MASK_LCR_STICK_PARITY_EN 0x1 +#define BIT_LCR_STICK_PARITY_EN(x)(((x) & BIT_MASK_LCR_STICK_PARITY_EN) << BIT_SHIFT_LCR_STICK_PARITY_EN) +#define BIT_INVC_LCR_STICK_PARITY_EN (~(BIT_MASK_LCR_STICK_PARITY_EN << BIT_SHIFT_LCR_STICK_PARITY_EN)) + +#define BIT_SHIFT_LCR_BREAK_CTRL 6 +#define BIT_MASK_LCR_BREAK_CTRL 0x1 +#define BIT_UART_LCR_BREAK_CTRL ((BIT_MASK_LCR_BREAK_CTRL) << BIT_SHIFT_LCR_BREAK_CTRL) + +#define RUART_BAUD_RATE_2400 2400 +#define RUART_BAUD_RATE_4800 4800 +#define RUART_BAUD_RATE_9600 9600 +#define RUART_BAUD_RATE_19200 19200 +#define RUART_BAUD_RATE_38400 38400 +#define RUART_BAUD_RATE_57600 57600 +#define RUART_BAUD_RATE_115200 115200 +#define RUART_BAUD_RATE_921600 921600 +#define RUART_BAUD_RATE_1152000 1152000 + +#define HAL_RUART_READ32(UartIndex, addr) \ + HAL_READ32(UART0_REG_BASE+ (UartIndex*RUART_REG_OFF), addr) +#define HAL_RUART_WRITE32(UartIndex, addr, value) \ + HAL_WRITE32(UART0_REG_BASE+ (UartIndex*RUART_REG_OFF), addr, value) +#define HAL_RUART_READ16(UartIndex, addr) \ + HAL_READ16(UART0_REG_BASE+ (UartIndex*RUART_REG_OFF), addr) +#define HAL_RUART_WRITE16(UartIndex, addr, value) \ + HAL_WRITE16(UART0_REG_BASE+ (UartIndex*RUART_REG_OFF), addr, value) +#define HAL_RUART_READ8(UartIndex, addr) \ + HAL_READ8(UART0_REG_BASE+ (UartIndex*RUART_REG_OFF), addr) +#define HAL_RUART_WRITE8(UartIndex, addr, value) \ + HAL_WRITE8(UART0_REG_BASE+ (UartIndex*RUART_REG_OFF), addr, value) + +typedef struct _RUART_SPEED_SETTING_ { + u32 BaudRate; + u32 Ovsr; + u32 Div; + u32 Ovsr_adj; +}RUART_SPEED_SETTING, *PRUART_SPEED_SETTING; + +typedef enum _UART_RXFIFO_TRIGGER_LEVEL_ { + OneByte = 0x00, + FourBytes = 0x01, + EightBytes = 0x10, + FourteenBytes = 0x11 +}UART_RXFIFO_TRIGGER_LEVEL, *PUART_RXFIFO_TRIGGER_LEVEL; + +typedef enum _RUART0_PINMUX_SELECT_ { + RUART0_MUX_TO_GPIOC = S0, + RUART0_MUX_TO_GPIOE = S1, + RUART0_MUX_TO_GPIOA = S2 +}RUART0_PINMUX_SELECT, *PRUART0_PINMUX_SELECT; + +typedef enum _RUART1_PINMUX_SELECT_ { + RUART1_MUX_TO_GPIOD = S0, + RUART1_MUX_TO_GPIOE = S1, + RUART1_MUX_TO_GPIOB = S2 +}RUART1_PINMUX_SELECT, *PRUART1_PINMUX_SELECT; + +typedef enum _RUART2_PINMUX_SELECT_ { + RUART2_MUX_TO_GPIOA = S0, + RUART2_MUX_TO_GPIOC = S1, + RUART2_MUX_TO_GPIOD = S2 +}RUART2_PINMUX_SELECT, *PRUART2_PINMUX_SELECT; + +typedef enum _RUART_FLOW_CONTROL_ { + AUTOFLOW_DISABLE = 0, + AUTOFLOW_ENABLE = 1 +}RUART_FLOW_CONTROL, *PRUART_FLOW_CONTROL; + +typedef enum _RUART_WORD_LEN_SEL_ { + RUART_WLS_7BITS = 0, + RUART_WLS_8BITS = 1 +}RUART_WORD_LEN_SEL, *PRUART_WORD_LEN_SEL; + +typedef enum _RUART_STOP_BITS_ { + RUART_NO_STOP_BIT = 0, + RUART_1_STOP_BIT = 1 +}RUART_STOP_BITS, *PRUART_STOP_BITS; + +typedef enum _RUART_PARITY_CONTROL_ { + RUART_PARITY_DISABLE = 0, + RUART_PARITY_ENABLE = 1 +}RUART_PARITY_CONTROL, *PRUART_PARITY_CONTROL; + +typedef enum _RUART_PARITY_TYPE_ { + RUART_ODD_PARITY = 0, + RUART_EVEN_PARITY = 1 +}RUART_PARITY_TYPE, *PRUART_PARITY_TYPE; + +typedef enum _RUART_STICK_PARITY_CONTROL_ { + RUART_STICK_PARITY_DISABLE = 0, + RUART_STICK_PARITY_ENABLE = 1 +}RUART_STICK_PARITY_CONTROL, *PRUART_STICK_PARITY_CONTROL; + +typedef enum _UART_INT_ID_ { + ModemStatus = 0, + TxFifoEmpty = 1, + ReceiverDataAvailable = 2, + ReceivLineStatus = 3, + TimeoutIndication = 6 +}UART_INT_ID, *PUART_INT_ID; + +typedef enum _HAL_UART_State_ +{ + HAL_UART_STATE_NULL = 0x00, // UART hardware not been initial yet + HAL_UART_STATE_READY = 0x10, // UART is initialed, ready to use + HAL_UART_STATE_BUSY = 0x20, // UART hardware is busy on configuration + HAL_UART_STATE_BUSY_TX = 0x21, // UART is buzy on TX + HAL_UART_STATE_BUSY_RX = 0x22, // UART is busy on RX + HAL_UART_STATE_BUSY_TX_RX = 0x23, // UART is busy on TX an RX + HAL_UART_STATE_TIMEOUT = 0x30, // Transfer timeout + HAL_UART_STATE_ERROR = 0x40 // UART Error +}HAL_UART_State, *PHAL_UART_State; + +typedef enum _HAL_UART_Status_ +{ + HAL_UART_STATUS_OK = 0x00, // Transfer OK + HAL_UART_STATUS_TIMEOUT = 0x01, // Transfer Timeout + HAL_UART_STATUS_ERR_OVERRUN = 0x02, // RX Over run + HAL_UART_STATUS_ERR_PARITY = 0x04, // Parity error + HAL_UART_STATUS_ERR_FRAM = 0x08, // Framing Error + HAL_UART_STATUS_ERR_BREAK = 0x10, // Break Interrupt + HAL_UART_STATUS_ERR_PARA = 0x20, // Parameter error + HAL_UART_STATUS_ERR_RXFIFO = 0x80, // RX FIFO error +}HAL_UART_Status, *PHAL_UART_Status; + +u32 +HalRuartGetDebugValueRtl8195a( + IN VOID* Data, + IN u32 DbgSel + ); + +#if 0 +u32 +FindElementIndex( + u32 Element, + u32* Array + ); +#endif + +VOID +RuartResetRxFifoRtl8195a( + IN u8 UartIndex + ); +#if 0 +VOID +RuartBusDomainEnableRtl8195a( + IN u8 UartIndex + ); +#endif + +HAL_Status +HalRuartResetRxFifoRtl8195a( + IN VOID *Data + ); + +HAL_Status +HalRuartInitRtl8195a( + IN VOID *Data + ); + +VOID +HalRuartDeInitRtl8195a( + IN VOID *Data ///< RUART Adapter + ); + +HAL_Status +HalRuartPutCRtl8195a( + IN VOID *Data, + IN u8 TxData + ); + +u32 +HalRuartSendRtl8195a( + IN VOID *Data, + IN u8 *pTxData, + IN u32 Length, + IN u32 Timeout + ); + +HAL_Status +HalRuartIntSendRtl8195a( + IN VOID *Data, // PHAL_RUART_ADAPTER + IN u8 *pTxData, // the Buffer to be send + IN u32 Length // the length of data to be send + ); + +HAL_Status +HalRuartDmaSendRtl8195a( + IN VOID *Data, // PHAL_RUART_ADAPTER + IN u8 *pTxData, // the Buffer to be send + IN u32 Length // the length of data to be send +); + +HAL_Status +HalRuartStopSendRtl8195a( + IN VOID *Data // PHAL_RUART_ADAPTER +); + +HAL_Status +HalRuartGetCRtl8195a( + IN VOID *Data, + OUT u8 *pRxByte + ); + +u32 +HalRuartRecvRtl8195a( + IN VOID *Data, + IN u8 *pRxData, + IN u32 Length, + IN u32 Timeout + ); + +HAL_Status +HalRuartIntRecvRtl8195a( + IN VOID *Data, ///< RUART Adapter + IN u8 *pRxData, ///< Rx buffer + IN u32 Length // buffer length + ); + +HAL_Status +HalRuartDmaRecvRtl8195a( + IN VOID *Data, ///< RUART Adapter + IN u8 *pRxData, ///< Rx buffer + IN u32 Length // buffer length + ); + +HAL_Status +HalRuartStopRecvRtl8195a( + IN VOID *Data // PHAL_RUART_ADAPTER +); + +u8 +HalRuartGetIMRRtl8195a( + IN VOID *Data + ); + +_LONG_CALL_ VOID +HalRuartSetIMRRtl8195a( + IN VOID *Data + ); + +VOID +HalRuartDmaInitRtl8195a( + IN VOID *Data + ); + +VOID +HalRuartRTSCtrlRtl8195a( + IN VOID *Data, + IN BOOLEAN RtsCtrl + ); + +VOID +HalRuartRegIrqRtl8195a( + IN VOID *Data + ); + +VOID +HalRuartIntEnableRtl8195a( + IN VOID *Data + ); + +VOID +HalRuartIntDisableRtl8195a( + IN VOID *Data + ); + +VOID +HalRuartAdapterLoadDefRtl8195a( + IN VOID *pAdp, + IN u8 UartIdx +); + +VOID +HalRuartTxGdmaLoadDefRtl8195a( + IN VOID *pAdp, + IN VOID *pCfg +); + +VOID +HalRuartRxGdmaLoadDefRtl8195a( + IN VOID *pAdp, + IN VOID *pCfg +); + +_LONG_CALL_ HAL_Status HalRuartIntSendRtl8195aV02( + IN VOID *Data, // PHAL_RUART_ADAPTER + IN u8 *pTxData, // the Buffer to be send + IN u32 Length // the length of data to be send +); + +_LONG_CALL_ HAL_Status +HalRuartIntRecvRtl8195aV02( + IN VOID *Data, ///< RUART Adapter + IN u8 *pRxData, ///< Rx buffer + IN u32 Length // buffer length +); + +_LONG_CALL_ s32 +FindElementIndex_v02( + u32 Element, ///< RUART Baudrate + u32* Array, ///< Pre-defined Baudrate Array + u32 ElementNo +); + +_LONG_CALL_ HAL_Status HalRuartInitRtl8195a_v02(IN VOID *Data); + +#endif diff --git a/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_wdt.h b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_wdt.h new file mode 100644 index 0000000..edbedd2 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/rtl8195a/rtl8195a_wdt.h @@ -0,0 +1,86 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2014 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#ifndef _RTL8195A_WDT_H_ +#define _RTL8195A_WDT_H_ + +#define WDGTIMERELY (10*1024) //us + +typedef struct _WDG_REG_ { + u16 WdgScalar; + u8 WdgEnByte; + u8 WdgClear:1; + u8 WdgCunLimit:4; + u8 Rsvd:1; + u8 WdgMode:1; + u8 WdgToISR:1; +}WDG_REG, *PWDG_REG; + +typedef struct _WDG_ADAPTER_ { + + WDG_REG Ctrl; + IRQ_HANDLE IrqHandle; + TIMER_ADAPTER WdgGTimer; + VOID (*UserCallback)(u32 callback_id); // User callback function + u32 callback_id; +}WDG_ADAPTER, *PWDG_ADAPTER; + +typedef enum _WDG_CNTLMT_ { + CNT1H = 0, + CNT3H = 1, + CNT7H = 2, + CNTFH = 3, + CNT1FH = 4, + CNT3FH = 5, + CNT7FH = 6, + CNTFFH = 7, + CNT1FFH = 8, + CNT3FFH = 9, + CNT7FFH = 10, + CNTFFFH = 11 +}WDG_CNTLMT, *PWDG_CNTLMT; + + +typedef enum _WDG_MODE_ { + INT_MODE = 0, + RESET_MODE = 1 +}WDG_MODE, *PWDG_MODE; + +extern VOID +WDGInitial( + IN u32 Period +); + +extern VOID +WDGIrqInitial( + VOID +); + +extern VOID +WDGIrqInitial( + VOID +); + +extern VOID +WDGStop( + VOID +); + +extern VOID +WDGRefresh( + VOID +); + +extern VOID +WDGIrqCallBackReg( + IN VOID *CallBack, + IN u32 Id +); + +#endif //_RTL8195A_WDT_H_ diff --git a/component/soc/realtek/8195a/fwlib/rtl8195a/src/rtl8195a_adc.c b/component/soc/realtek/8195a/fwlib/rtl8195a/src/rtl8195a_adc.c new file mode 100644 index 0000000..133b1fa --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/rtl8195a/src/rtl8195a_adc.c @@ -0,0 +1,380 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + + +#include "platform_autoconf.h" +#include "diag.h" +#include "rtl8195a_adc.h" +#include "hal_adc.h" + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// HalI2CInit8195a +// +// Description: +// To initialize I2C module by using the given data. +// +// Arguments: +// [in] VOID *Data - +// The I2C parameter data struct. +// +// Return: +// The status of the DeInit process. +// _EXIT_SUCCESS if the initialization succeeded. +// _EXIT_FAILURE if the initialization failed. +// +// Note: +// None +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-04-02. +// +//--------------------------------------------------------------------------------------------------- +RTK_STATUS +HalADCInit8195a( + IN VOID *Data +) +{ + PHAL_ADC_INIT_DAT pHalAdcInitData = (PHAL_ADC_INIT_DAT)Data; + u32 AdcTempDat; + u8 AdcTempIdx = pHalAdcInitData->ADCIdx; + + /* Enable ADC power cut */ +/* + AdcTempDat = HAL_ADC_READ32(REG_ADC_POWER); + AdcTempDat |= BIT_ADC_PWR_AUTO; + HAL_ADC_WRITE32(REG_ADC_POWER, AdcTempDat); +*/ + + /* ADC Control register set-up*/ + AdcTempDat = 0; + AdcTempDat |= (BIT_CTRL_ADC_COMP_ONLY(pHalAdcInitData->ADCCompOnly) | + BIT_CTRL_ADC_ONESHOT(pHalAdcInitData->ADCOneShotEn) | + BIT_CTRL_ADC_OVERWRITE(pHalAdcInitData->ADCOverWREn) | + BIT_CTRL_ADC_ENDIAN(pHalAdcInitData->ADCEndian) | + BIT_CTRL_ADC_BURST_SIZE(pHalAdcInitData->ADCBurstSz) | + BIT_CTRL_ADC_THRESHOLD(pHalAdcInitData->ADCOneShotTD) | + BIT_CTRL_ADC_DBG_SEL(pHalAdcInitData->ADCDbgSel)); + HAL_ADC_WRITE32(REG_ADC_CONTROL,AdcTempDat); + + DBG_8195A_ADC_LVL(HAL_ADC_LVL,"REG_ADC_CONTROL:%x\n", HAL_ADC_READ32(REG_ADC_CONTROL)); + + /* ADC compare value and compare method setting*/ + switch (AdcTempIdx) { + case ADC0_SEL: + AdcTempDat = HAL_ADC_READ32(REG_ADC_COMP_VALUE_L); + AdcTempDat &= ~(BIT_ADC_COMP_TH_0(0xFFFF)); + AdcTempDat |= BIT_CTRL_ADC_COMP_TH_0(pHalAdcInitData->ADCCompTD); + HAL_ADC_WRITE32(REG_ADC_COMP_VALUE_L, AdcTempDat); + break; + + case ADC1_SEL: + AdcTempDat = HAL_ADC_READ32(REG_ADC_COMP_VALUE_L); + AdcTempDat &= ~(BIT_ADC_COMP_TH_1(0xFFFF)); + AdcTempDat |= BIT_CTRL_ADC_COMP_TH_1(pHalAdcInitData->ADCCompTD); + HAL_ADC_WRITE32(REG_ADC_COMP_VALUE_L, AdcTempDat); + break; + + case ADC2_SEL: + AdcTempDat = HAL_ADC_READ32(REG_ADC_COMP_VALUE_H); + AdcTempDat &= ~(BIT_ADC_COMP_TH_2(0xFFFF)); + AdcTempDat |= BIT_CTRL_ADC_COMP_TH_2(pHalAdcInitData->ADCCompTD); + HAL_ADC_WRITE32(REG_ADC_COMP_VALUE_H, AdcTempDat); + break; + + case ADC3_SEL: + AdcTempDat = HAL_ADC_READ32(REG_ADC_COMP_VALUE_H); + AdcTempDat &= ~(BIT_ADC_COMP_TH_3(0xFFFF)); + AdcTempDat |= BIT_CTRL_ADC_COMP_TH_3(pHalAdcInitData->ADCCompTD); + HAL_ADC_WRITE32(REG_ADC_COMP_VALUE_H, AdcTempDat); + break; + default: + return _EXIT_FAILURE; + } + + /* ADC compare mode setting */ + AdcTempDat = HAL_ADC_READ32(REG_ADC_COMP_SET); + AdcTempDat &= (~(0x01 << pHalAdcInitData->ADCIdx)); + AdcTempDat |= (BIT_CTRL_ADC_COMP_0_EN(pHalAdcInitData->ADCCompCtrl) << + pHalAdcInitData->ADCIdx); + HAL_ADC_WRITE32(REG_ADC_COMP_SET, AdcTempDat); + + /* ADC audio mode set-up */ + AdcTempDat = HAL_ADC_READ32(REG_ADC_ANAPAR_AD0); + AdcTempDat &= ~(BIT_ADC_AUDIO_EN); + AdcTempDat |= BIT_CTRL_ADC_AUDIO_EN(pHalAdcInitData->ADCAudioEn); + HAL_ADC_WRITE32(REG_ADC_ANAPAR_AD0, AdcTempDat); + + /* ADC enable manually setting */ + AdcTempDat = HAL_ADC_READ32(REG_ADC_ANAPAR_AD0); + AdcTempDat &= ~(BIT_ADC_EN_MANUAL); + AdcTempDat |= BIT_CTRL_ADC_EN_MANUAL(pHalAdcInitData->ADCEnManul); + HAL_ADC_WRITE32(REG_ADC_ANAPAR_AD0, AdcTempDat); + + + /* ADC analog parameter 0 */ + AdcTempDat = HAL_ADC_READ32(REG_ADC_ANAPAR_AD0); + DBG_ADC_INFO("AD0:%x\n", AdcTempDat); + AdcTempDat |= (BIT0); + if (pHalAdcInitData->ADCInInput == 1){ + AdcTempDat &= (~BIT14); + } + else { + AdcTempDat |= (BIT14); + } + AdcTempDat &= (~(BIT3|BIT2)); + + /* Adjust VCM for C-Cut*/ +#ifdef CONFIG_CHIP_C_CUT + AdcTempDat |= (BIT22); +#endif + + HAL_ADC_WRITE32(REG_ADC_ANAPAR_AD0, AdcTempDat); + AdcTempDat = HAL_ADC_READ32(REG_ADC_ANAPAR_AD0); + DBG_ADC_INFO("AD0:%x\n", AdcTempDat); + + /* ADC analog parameter 1 */ + AdcTempDat = HAL_ADC_READ32(REG_ADC_ANAPAR_AD1); + AdcTempDat &= (~BIT1); + AdcTempDat |= (BIT2|BIT0); + HAL_ADC_WRITE32(REG_ADC_ANAPAR_AD1, AdcTempDat); + AdcTempDat = HAL_ADC_READ32(REG_ADC_ANAPAR_AD1); + DBG_ADC_INFO("AD1:%x\n", AdcTempDat); + + /* ADC analog parameter 2 */ + AdcTempDat = HAL_ADC_READ32(REG_ADC_ANAPAR_AD2); + DBG_ADC_INFO("AD2:%x\n", AdcTempDat); + AdcTempDat = 0x67884400; + HAL_ADC_WRITE32(REG_ADC_ANAPAR_AD2, AdcTempDat); + AdcTempDat = HAL_ADC_READ32(REG_ADC_ANAPAR_AD2); + DBG_ADC_INFO("AD2:%x\n", AdcTempDat); + + /* ADC analog parameter 3 */ + AdcTempDat = HAL_ADC_READ32(REG_ADC_ANAPAR_AD3); + DBG_ADC_INFO("AD3:%x\n", AdcTempDat); + AdcTempDat = 0x77780039; + HAL_ADC_WRITE32(REG_ADC_ANAPAR_AD3, AdcTempDat); + AdcTempDat = HAL_ADC_READ32(REG_ADC_ANAPAR_AD3); + DBG_ADC_INFO("AD3:%x\n", AdcTempDat); + + /* ADC analog parameter 4 */ + AdcTempDat = HAL_ADC_READ32(REG_ADC_ANAPAR_AD4); + DBG_ADC_INFO("AD4:%x\n", AdcTempDat); + AdcTempDat = 0x0004d501; + HAL_ADC_WRITE32(REG_ADC_ANAPAR_AD4, AdcTempDat); + AdcTempDat = HAL_ADC_READ32(REG_ADC_ANAPAR_AD4); + DBG_ADC_INFO("AD4:%x\n", AdcTempDat); + + /* ADC analog parameter 5 */ + AdcTempDat = HAL_ADC_READ32(REG_ADC_ANAPAR_AD5); + DBG_ADC_INFO("AD5:%x\n", AdcTempDat); + AdcTempDat = 0x1E010800; + HAL_ADC_WRITE32(REG_ADC_ANAPAR_AD5, AdcTempDat); + AdcTempDat = HAL_ADC_READ32(REG_ADC_ANAPAR_AD5); + DBG_ADC_INFO("AD5:%x\n", AdcTempDat); + + return _EXIT_SUCCESS; +} + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// HalI2CInit8195a +// +// Description: +// To initialize I2C module by using the given data. +// +// Arguments: +// [in] VOID *Data - +// The I2C parameter data struct. +// +// Return: +// The status of the DeInit process. +// _EXIT_SUCCESS if the initialization succeeded. +// _EXIT_FAILURE if the initialization failed. +// +// Note: +// None +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-04-02. +// +//--------------------------------------------------------------------------------------------------- +RTK_STATUS +HalADCDeInit8195a( + IN VOID *Data +) +{ + u32 AdcTempDat; + + AdcTempDat = HAL_ADC_READ32(REG_ADC_POWER); + AdcTempDat &= ~(BIT_ADC_PWR_AUTO); + HAL_ADC_WRITE32(REG_ADC_POWER, AdcTempDat); + + return _EXIT_SUCCESS; +} + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// HalI2CIntrCtrl8195a +// +// Description: +// Modify the I2C interrupt mask according to the given value +// +// Arguments: +// [in] VOID *Data - +// The I2C parameter data struct. +// +// Return: +// The status of the enable process. +// _EXIT_SUCCESS if the de-initialization succeeded. +// _EXIT_FAILURE if the de-initialization failed. +// +// Note: +// None +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-02-18. +// +//--------------------------------------------------------------------------------------------------- +RTK_STATUS +HalADCEnableRtl8195a( + IN VOID *Data +){ + PHAL_ADC_INIT_DAT pHalAdcInitData = (PHAL_ADC_INIT_DAT)Data; + u32 AdcTempDat; + + + AdcTempDat = HAL_ADC_READ32(REG_ADC_POWER); + AdcTempDat &= (~BIT_ADC_PWR_AUTO); + AdcTempDat |= BIT_CTRL_ADC_PWR_AUTO(pHalAdcInitData->ADCEn); + HAL_ADC_WRITE32(REG_ADC_POWER, AdcTempDat); + + return _EXIT_SUCCESS; +} + + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// HalI2CIntrCtrl8195a +// +// Description: +// Modify the I2C interrupt mask according to the given value +// +// Arguments: +// [in] VOID *Data - +// The I2C parameter data struct. +// +// Return: +// The status of the enable process. +// _EXIT_SUCCESS if the de-initialization succeeded. +// _EXIT_FAILURE if the de-initialization failed. +// +// Note: +// None +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-02-18. +// +//--------------------------------------------------------------------------------------------------- +RTK_STATUS +HalADCIntrCtrl8195a( + IN VOID *Data +){ + PHAL_ADC_INIT_DAT pHalAdcInitData = (PHAL_ADC_INIT_DAT)Data; + + HAL_ADC_WRITE32(REG_ADC_INTR_EN, pHalAdcInitData->ADCIntrMSK); + + return _EXIT_SUCCESS; +} + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// HalI2CReceiveRtl8195a +// +// Description: +// Directly read one data byte a I2C data fifo. +// +// Arguments: +// [in] VOID *Data - +// The I2C parameter data struct. +// +// Return: +// The first data fifo content. +// +// Note: +// None +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-02-18. +// +//--------------------------------------------------------------------------------------------------- +u32 +HalADCReceiveRtl8195a( + IN VOID *Data +){ + u32 AdcTempDat; + + AdcTempDat = HAL_ADC_READ32(REG_ADC_FIFO_READ); + + return (AdcTempDat); +} + + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// HalI2CReadRegRtl8195a +// +// Description: +// Directly read a I2C register according to the register offset. +// +// Arguments: +// [in] VOID *Data - +// The I2C parameter data struct. +// [in] I2CReg - +// The I2C register offset. +// +// Return: +// The register content in u32 format. +// +// Note: +// None +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-02-18. +// +//--------------------------------------------------------------------------------------------------- +u32 +HalADCReadRegRtl8195a( + IN VOID *Data, + IN u8 I2CReg +){ + u32 AdcTempDat; + + AdcTempDat = HAL_ADC_READ32(I2CReg); + return (AdcTempDat); +} + diff --git a/component/soc/realtek/8195a/fwlib/rtl8195a/src/rtl8195a_dac.c b/component/soc/realtek/8195a/fwlib/rtl8195a/src/rtl8195a_dac.c new file mode 100644 index 0000000..a9bc7a7 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/rtl8195a/src/rtl8195a_dac.c @@ -0,0 +1,269 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + + +#include "rtl8195a.h" +#include "rtl8195a_dac.h" +#include "hal_dac.h" + + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// HalDACInit8195a +// +// Description: +// To initialize DAC module by using the given data. +// +// Arguments: +// [in] VOID *Data - +// The DAC parameter data struct. +// +// Return: +// The status of the DeInit process. +// _EXIT_SUCCESS if the initialization succeeded. +// _EXIT_FAILURE if the initialization failed. +// +// Note: +// None +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-04-15. +// +//--------------------------------------------------------------------------------------------------- +RTK_STATUS +HalDACInit8195a( + IN VOID *Data +){ + PHAL_DAC_INIT_DAT pHalDacInitData = (PHAL_DAC_INIT_DAT)Data; + u32 DacTempDat; + u8 DacTempIdx = pHalDacInitData->DACIdx; + + /* Enable DAC power cut */ + DacTempDat = HAL_DAC_READ32(0, REG_DAC_PWR_CTRL); + DacTempDat |= BIT_DAC_PWR_AUTO; + + HAL_DAC_WRITE32(0, REG_DAC_PWR_CTRL, DacTempDat); + + /* Disable DAC module first */ + HAL_DAC_WRITE32(DacTempIdx, REG_DAC_CTRL, 0); + + /* Setup DAC module */ + DacTempDat = 0; + DacTempDat |= (BIT_CTRL_DAC_SPEED(pHalDacInitData->DACDataRate) | + BIT_CTRL_DAC_ENDIAN(pHalDacInitData->DACEndian) | + BIT_CTRL_DAC_FILTER_SETTLE(pHalDacInitData->DACFilterSet) | + BIT_CTRL_DAC_BURST_SIZE(pHalDacInitData->DACBurstSz) | + BIT_CTRL_DAC_DBG_SEL(pHalDacInitData->DACDbgSel) | + BIT_CTRL_DAC_DSC_DBG_SEL(pHalDacInitData->DACDscDbgSel) | + BIT_CTRL_DAC_BYPASS_DSC(pHalDacInitData->DACBPDsc) | + BIT_CTRL_DAC_DELTA_SIGMA(pHalDacInitData->DACDeltaSig)); + + HAL_DAC_WRITE32(DacTempIdx, REG_DAC_CTRL, DacTempDat); + + return _EXIT_SUCCESS; +} + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// HalI2CInit8195a +// +// Description: +// To initialize I2C module by using the given data. +// +// Arguments: +// [in] VOID *Data - +// The I2C parameter data struct. +// +// Return: +// The status of the DeInit process. +// _EXIT_SUCCESS if the initialization succeeded. +// _EXIT_FAILURE if the initialization failed. +// +// Note: +// None +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-04-02. +// +//--------------------------------------------------------------------------------------------------- +RTK_STATUS +HalDACDeInit8195a( + IN VOID *Data +){ + PHAL_DAC_INIT_DAT pHalDacInitData = (PHAL_DAC_INIT_DAT)Data; + u32 DacTempDat; + + DacTempDat = HAL_DAC_READ32(pHalDacInitData->DACIdx, REG_DAC_CTRL); + DacTempDat &= (~BIT_DAC_FIFO_EN); + HAL_DAC_WRITE32(pHalDacInitData->DACIdx, REG_DAC_CTRL ,DacTempDat); + + return _EXIT_SUCCESS; +} + + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// HalI2CIntrCtrl8195a +// +// Description: +// Modify the I2C interrupt mask according to the given value +// +// Arguments: +// [in] VOID *Data - +// The I2C parameter data struct. +// +// Return: +// The status of the enable process. +// _EXIT_SUCCESS if the de-initialization succeeded. +// _EXIT_FAILURE if the de-initialization failed. +// +// Note: +// None +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-02-18. +// +//--------------------------------------------------------------------------------------------------- +RTK_STATUS +HalDACEnableRtl8195a( + IN VOID *Data +){ + PHAL_DAC_INIT_DAT pHalDacInitData = (PHAL_DAC_INIT_DAT)Data; + u32 DacTempDat; + u8 DacTempIdx = pHalDacInitData->DACIdx; + + DacTempDat = HAL_DAC_READ32(DacTempIdx, REG_DAC_CTRL); + DacTempDat &= (~BIT_DAC_FIFO_EN); + + DacTempDat |= BIT_CTRL_DAC_FIFO_EN(pHalDacInitData->DACEn); + HAL_DAC_WRITE32(DacTempIdx, REG_DAC_CTRL, DacTempDat); + + return _EXIT_SUCCESS; +} + + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// HalI2CIntrCtrl8195a +// +// Description: +// Modify the I2C interrupt mask according to the given value +// +// Arguments: +// [in] VOID *Data - +// The I2C parameter data struct. +// +// Return: +// The status of the enable process. +// _EXIT_SUCCESS if the de-initialization succeeded. +// _EXIT_FAILURE if the de-initialization failed. +// +// Note: +// None +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-02-18. +// +//--------------------------------------------------------------------------------------------------- +RTK_STATUS +HalDACIntrCtrl8195a( + IN VOID *Data +){ + PHAL_DAC_INIT_DAT pHalDacInitData = (PHAL_DAC_INIT_DAT)Data; + + HAL_DAC_WRITE32(pHalDacInitData->DACIdx, REG_DAC_INTR_CTRL, pHalDacInitData->DACIntrMSK); + + return _EXIT_SUCCESS; +} + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// HalI2CReceiveRtl8195a +// +// Description: +// Directly read one data byte a I2C data fifo. +// +// Arguments: +// [in] VOID *Data - +// The I2C parameter data struct. +// +// Return: +// The first data fifo content. +// +// Note: +// None +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-02-18. +// +//--------------------------------------------------------------------------------------------------- +u8 +HalDACSendRtl8195a( + IN VOID *Data +){ + + + return (0); +} + + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// HalDACReadRegRtl8195a +// +// Description: +// +// +// Arguments: +// [in] VOID *Data - +// The DAC parameter data struct. +// [in] I2CReg - +// The DAC register offset. +// +// Return: +// The DAC register content in u32 format. +// +// Note: +// None +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-04-15. +// +//--------------------------------------------------------------------------------------------------- +u32 +HalDACReadRegRtl8195a( + IN VOID *Data, + IN u8 I2CReg +){ + PHAL_DAC_INIT_DAT pHalDacInitData = (PHAL_DAC_INIT_DAT)Data; + + //DBG_8195A_DAC("dac read reg idx:%x\n",pHalDacInitData->DACIdx); + //DBG_8195A_DAC("dac read reg offset:%x\n",I2CReg); + + return (u32)HAL_DAC_READ32(pHalDacInitData->DACIdx, I2CReg); +} + diff --git a/component/soc/realtek/8195a/fwlib/rtl8195a/src/rtl8195a_gdma.c b/component/soc/realtek/8195a/fwlib/rtl8195a/src/rtl8195a_gdma.c new file mode 100644 index 0000000..640f787 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/rtl8195a/src/rtl8195a_gdma.c @@ -0,0 +1,243 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + + +#include "rtl8195a.h" +#include "rtl8195a_gdma.h" +#include "hal_gdma.h" + +#ifndef CONFIG_CHIP_D_CUT +BOOL +HalGdmaChBlockSetingRtl8195a( + IN VOID *Data +) +{ + PHAL_GDMA_ADAPTER pHalGdmaAdapter = (PHAL_GDMA_ADAPTER) Data; + PGDMA_CH_LLI_ELE pLliEle; + struct GDMA_CH_LLI *pGdmaChLli; + struct BLOCK_SIZE_LIST *pGdmaChBkLi; + u32 MultiBlockCount = pHalGdmaAdapter->MaxMuliBlock; + u32 CtlxLow, CtlxUp, CfgxLow, CfgxUp; + u8 GdmaIndex = pHalGdmaAdapter->GdmaIndex; + u8 ChNum = pHalGdmaAdapter->ChNum; + u32 ChEn = pHalGdmaAdapter->ChEn; + u8 GdmaChIsrBitmap = (ChEn & 0xFF); + u8 PendingIsrIndex; + + + pLliEle = pHalGdmaAdapter->pLlix->pLliEle; + pGdmaChLli = pHalGdmaAdapter->pLlix->pNextLli; + pGdmaChBkLi = pHalGdmaAdapter->pBlockSizeList; + + + //4 1) Check chanel is avaliable + if (HAL_GDMAX_READ32(GdmaIndex, REG_GDMA_CH_EN) & ChEn) { + //4 Disable Channel + DBG_GDMA_WARN("Channel had used; Disable Channel!!!!\n"); + + HalGdmaChDisRtl8195a(Data); + + } + + //4 2) Check if there are the pending isr; TFR, Block, Src Tran, Dst Tran, Error + for (PendingIsrIndex=0; PendingIsrIndex<5;PendingIsrIndex++) { + + u32 PendRaw, PendStstus; + PendRaw = HAL_GDMAX_READ32(GdmaIndex, + (REG_GDMA_RAW_INT_BASE + PendingIsrIndex*8)); + PendStstus = HAL_GDMAX_READ32(GdmaIndex, + (REG_GDMA_STATUS_INT_BASE + PendingIsrIndex*8)); + + if ((PendRaw & GdmaChIsrBitmap) || (PendStstus & GdmaChIsrBitmap)) { + //4 Clear Pending Isr + HAL_GDMAX_WRITE32(GdmaIndex, + (REG_GDMA_CLEAR_INT_BASE + PendingIsrIndex*8), + (PendStstus & (GdmaChIsrBitmap)) + ); + + } + } + + //4 Fill in SARx register + HAL_GDMAX_WRITE32(GdmaIndex, + (REG_GDMA_CH_SAR + ChNum*REG_GDMA_CH_OFF), + (pHalGdmaAdapter->ChSar) + ); + + + //4 Fill in DARx register + HAL_GDMAX_WRITE32(GdmaIndex, + (REG_GDMA_CH_DAR + ChNum*REG_GDMA_CH_OFF), + (pHalGdmaAdapter->ChDar) + ); + + + + //4 3) Process CTLx + CtlxLow = HAL_GDMAX_READ32(GdmaIndex, + (REG_GDMA_CH_CTL + ChNum*REG_GDMA_CH_OFF)); + + //4 Clear Config low register bits + CtlxLow &= (BIT_INVC_CTLX_LO_INT_EN & + BIT_INVC_CTLX_LO_DST_TR_WIDTH & + BIT_INVC_CTLX_LO_SRC_TR_WIDTH & + BIT_INVC_CTLX_LO_DINC & + BIT_INVC_CTLX_LO_SINC & + BIT_INVC_CTLX_LO_DEST_MSIZE & + BIT_INVC_CTLX_LO_SRC_MSIZE & + BIT_INVC_CTLX_LO_TT_FC & + BIT_INVC_CTLX_LO_LLP_DST_EN & + BIT_INVC_CTLX_LO_LLP_SRC_EN); + + CtlxUp = HAL_GDMAX_READ32(GdmaIndex, + (REG_GDMA_CH_CTL + ChNum*REG_GDMA_CH_OFF + 4)); + + //4 Clear Config upper register bits + CtlxUp &= (BIT_INVC_CTLX_UP_BLOCK_BS & + BIT_INVC_CTLX_UP_DONE); + + + CtlxLow = BIT_CTLX_LO_INT_EN(pHalGdmaAdapter->GdmaCtl.IntEn) | + BIT_CTLX_LO_DST_TR_WIDTH(pHalGdmaAdapter->GdmaCtl.DstTrWidth) | + BIT_CTLX_LO_SRC_TR_WIDTH(pHalGdmaAdapter->GdmaCtl.SrcTrWidth) | + BIT_CTLX_LO_DINC(pHalGdmaAdapter->GdmaCtl.Dinc) | + BIT_CTLX_LO_SINC(pHalGdmaAdapter->GdmaCtl.Sinc) | + BIT_CTLX_LO_DEST_MSIZE(pHalGdmaAdapter->GdmaCtl.DestMsize) | + BIT_CTLX_LO_SRC_MSIZE(pHalGdmaAdapter->GdmaCtl.SrcMsize) | + BIT_CTLX_LO_TT_FC(pHalGdmaAdapter->GdmaCtl.TtFc) | + BIT_CTLX_LO_LLP_DST_EN(pHalGdmaAdapter->GdmaCtl.LlpDstEn) | + BIT_CTLX_LO_LLP_SRC_EN(pHalGdmaAdapter->GdmaCtl.LlpSrcEn) | + CtlxLow; + + CtlxUp = BIT_CTLX_UP_BLOCK_BS(pGdmaChBkLi->BlockSize) | + BIT_CTLX_UP_DONE(pHalGdmaAdapter->GdmaCtl.Done) | + CtlxUp; + + //4 Fill in CTLx register + HAL_GDMAX_WRITE32(GdmaIndex, + (REG_GDMA_CH_CTL + ChNum*REG_GDMA_CH_OFF), + CtlxLow + ); + + HAL_GDMAX_WRITE32(GdmaIndex, + (REG_GDMA_CH_CTL + ChNum*REG_GDMA_CH_OFF +4), + CtlxUp + ); + + //4 4) Program CFGx + + CfgxLow = HAL_GDMAX_READ32(GdmaIndex, + (REG_GDMA_CH_CFG + ChNum*REG_GDMA_CH_OFF)); + + CfgxLow &= (BIT_INVC_CFGX_LO_CH_PRIOR & + BIT_INVC_CFGX_LO_CH_SUSP & + BIT_INVC_CFGX_LO_HS_SEL_DST & + BIT_INVC_CFGX_LO_HS_SEL_SRC & + BIT_INVC_CFGX_LO_LOCK_CH_L & + BIT_INVC_CFGX_LO_LOCK_B_L & + BIT_INVC_CFGX_LO_LOCK_CH & + BIT_INVC_CFGX_LO_LOCK_B & + BIT_INVC_CFGX_LO_RELOAD_SRC & + BIT_INVC_CFGX_LO_RELOAD_DST); + + CfgxUp = HAL_GDMAX_READ32(GdmaIndex, + (REG_GDMA_CH_CFG + ChNum*REG_GDMA_CH_OFF + 4)); + + CfgxUp &= (BIT_INVC_CFGX_UP_FIFO_MODE & + BIT_INVC_CFGX_UP_DS_UPD_EN & + BIT_INVC_CFGX_UP_SS_UPD_EN & + BIT_INVC_CFGX_UP_SRC_PER & + BIT_INVC_CFGX_UP_DEST_PER); + + CfgxLow = BIT_CFGX_LO_CH_PRIOR(pHalGdmaAdapter->GdmaCfg.ChPrior) | + BIT_CFGX_LO_CH_SUSP(pHalGdmaAdapter->GdmaCfg.ChSusp) | + BIT_CFGX_LO_HS_SEL_DST(pHalGdmaAdapter->GdmaCfg.HsSelDst) | + BIT_CFGX_LO_HS_SEL_SRC(pHalGdmaAdapter->GdmaCfg.HsSelSrc) | + BIT_CFGX_LO_LOCK_CH_L(pHalGdmaAdapter->GdmaCfg.LockChL) | + BIT_CFGX_LO_LOCK_B_L(pHalGdmaAdapter->GdmaCfg.LockBL) | + BIT_CFGX_LO_LOCK_CH(pHalGdmaAdapter->GdmaCfg.LockCh) | + BIT_CFGX_LO_LOCK_B(pHalGdmaAdapter->GdmaCfg.LockB) | + BIT_CFGX_LO_RELOAD_SRC(pHalGdmaAdapter->GdmaCfg.ReloadSrc) | + BIT_CFGX_LO_RELOAD_DST(pHalGdmaAdapter->GdmaCfg.ReloadDst) | + CfgxLow; + + CfgxUp = BIT_CFGX_UP_FIFO_MODE(pHalGdmaAdapter->GdmaCfg.FifoMode) | + BIT_CFGX_UP_DS_UPD_EN(pHalGdmaAdapter->GdmaCfg.DsUpdEn) | + BIT_CFGX_UP_SS_UPD_EN(pHalGdmaAdapter->GdmaCfg.SsUpdEn) | + BIT_CFGX_UP_SRC_PER(pHalGdmaAdapter->GdmaCfg.SrcPer) | + BIT_CFGX_UP_DEST_PER(pHalGdmaAdapter->GdmaCfg.DestPer) | + CfgxUp; + + HAL_GDMAX_WRITE32(GdmaIndex, + (REG_GDMA_CH_CFG + ChNum*REG_GDMA_CH_OFF), + CfgxLow + ); + + HAL_GDMAX_WRITE32(GdmaIndex, + (REG_GDMA_CH_CFG + ChNum*REG_GDMA_CH_OFF +4), + CfgxUp + ); + + + + //4 Check 4 Bytes Alignment + if ((u32)(pLliEle) & 0x3) { + DBG_GDMA_WARN("LLi Addr: 0x%x not 4 bytes alignment!!!!\n", + pHalGdmaAdapter->pLli); + return _FALSE; + } + + HAL_GDMAX_WRITE32(GdmaIndex, + (REG_GDMA_CH_LLP + ChNum*REG_GDMA_CH_OFF), + pLliEle + ); + + //4 Update the first llp0 + pLliEle->CtlxLow = CtlxLow; + pLliEle->CtlxUp = CtlxUp; + pLliEle->Llpx = (u32)pGdmaChLli->pLliEle; + DBG_GDMA_INFO("Block Count %d\n", MultiBlockCount); + + pGdmaChBkLi = pGdmaChBkLi->pNextBlockSiz; + + while (MultiBlockCount > 1) { + MultiBlockCount--; + DBG_GDMA_INFO("Block Count %d\n", MultiBlockCount); + pLliEle = pGdmaChLli->pLliEle; + + if (NULL == pLliEle) { + DBG_8195A("pLliEle Null Point!!!!!\n"); + return _FALSE; + } + + //4 Clear the last element llp enable bit + if (1 == MultiBlockCount) { + if (((pHalGdmaAdapter->Rsvd4to7) & 0x01) == 0){ + CtlxLow &= (BIT_INVC_CTLX_LO_LLP_DST_EN & + BIT_INVC_CTLX_LO_LLP_SRC_EN); + } + } + //4 Update block size for transfer + CtlxUp &= (BIT_INVC_CTLX_UP_BLOCK_BS); + CtlxUp |= BIT_CTLX_UP_BLOCK_BS(pGdmaChBkLi->BlockSize); + + //4 Update tje Lli and Block size list point to next llp + pGdmaChLli = pGdmaChLli->pNextLli; + pGdmaChBkLi = pGdmaChBkLi->pNextBlockSiz; + + //4 Updatethe Llpx context + pLliEle->CtlxLow = CtlxLow; + pLliEle->CtlxUp = CtlxUp; + pLliEle->Llpx = pGdmaChLli->pLliEle; + + } + + return _TRUE; +} +#endif diff --git a/component/soc/realtek/8195a/fwlib/rtl8195a/src/rtl8195a_gpio.c b/component/soc/realtek/8195a/fwlib/rtl8195a/src/rtl8195a_gpio.c new file mode 100644 index 0000000..6f67d90 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/rtl8195a/src/rtl8195a_gpio.c @@ -0,0 +1,53 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#include "rtl8195a.h" +#include "hal_gpio.h" +#include "rtl8195a_gpio.h" +#include "gpio_irq_api.h" + +extern PHAL_GPIO_ADAPTER _pHAL_Gpio_Adapter; + +/** + * @brief Clear the pending interrupt of a specified pin + * + * @param GPIO_Pin: The data structer which contains the parameters for the GPIO Pin. + * + * @retval None + */ +HAL_Status +HAL_GPIO_ClearISR_8195a( + HAL_GPIO_PIN *GPIO_Pin +) +{ + u8 port_num; + u8 pin_num; + HAL_GPIO_PIN_MODE pin_mode; + + port_num = HAL_GPIO_GET_PORT_BY_NAME(GPIO_Pin->pin_name); + pin_num = HAL_GPIO_GET_PIN_BY_NAME(GPIO_Pin->pin_name); + pin_mode = GPIO_Pin->pin_mode; + + if ((pin_mode & HAL_GPIO_PIN_INT_MODE)==0 || (port_num != GPIO_PORT_A)) { + DBG_GPIO_ERR("HAL_GPIO_ClearISR_8195a: This pin(%x:%x) is'nt an interrupt pin\n", GPIO_Pin->pin_name, GPIO_Pin->pin_mode); + return HAL_ERR_PARA; + } + + if (GPIO_Lock() != HAL_OK) { + return HAL_BUSY; + } + + // Clear pending interrupt before unmask it + HAL_WRITE32(GPIO_REG_BASE, GPIO_PORTA_EOI, (1<I2SIdx; + I2SEn = pHalI2SInitData->I2SEn; + I2SMaster = pHalI2SInitData->I2SMaster; + I2SWordLen = pHalI2SInitData->I2SWordLen; + I2SChNum = pHalI2SInitData->I2SChNum; + I2SPageNum = pHalI2SInitData->I2SPageNum; + I2SPageSize = pHalI2SInitData->I2SPageSize; + I2SRate = pHalI2SInitData->I2SRate; + I2STRxAct = pHalI2SInitData->I2STRxAct; + I2STxData = pHalI2SInitData->I2STxData; + I2SRxData = pHalI2SInitData->I2SRxData; + + + /* Disable the I2S first, and reset to default */ + HAL_I2S_WRITE32(I2SIdx, REG_I2S_CTL, BIT_CTRL_CTLX_I2S_EN(0) | + BIT_CTRL_CTLX_I2S_SW_RSTN(1)); + HAL_I2S_WRITE32(I2SIdx, REG_I2S_CTL, BIT_CTRL_CTLX_I2S_EN(0) | + BIT_CTRL_CTLX_I2S_SW_RSTN(0)); + HAL_I2S_WRITE32(I2SIdx, REG_I2S_CTL, BIT_CTRL_CTLX_I2S_EN(0) | + BIT_CTRL_CTLX_I2S_SW_RSTN(1)); + + Tmp = HAL_I2S_READ32(I2SIdx, REG_I2S_CTL); + Tmp |= BIT_CTRL_CTLX_I2S_ENDIAN_SWAP(1); + + if (I2SRate&0x10) + { + Tmp |= BIT_CTRL_CTLX_I2S_CLK_SRC(1); + } + + Tmp |= (BIT_CTRL_CTLX_I2S_WL(I2SWordLen) | BIT_CTRL_CTLX_I2S_CH_NUM(I2SChNum) | + BIT_CTRL_CTLX_I2S_SLAVE_MODE(I2SMaster) | BIT_CTRL_CTLX_I2S_TRX_ACT(I2STRxAct)); + /* set 44.1khz clock source, word length, channel number, master or slave, trx act */ + HAL_I2S_WRITE32(I2SIdx, REG_I2S_CTL, Tmp); + + Tmp = BIT_CTRL_SETTING_I2S_PAGE_SZ(I2SPageSize) | BIT_CTRL_SETTING_I2S_PAGE_NUM(I2SPageNum) | + BIT_CTRL_SETTING_I2S_SAMPLE_RATE(I2SRate); + /* set page size, page number, sample rate */ + HAL_I2S_WRITE32(I2SIdx, REG_I2S_SETTING, Tmp); + + /* need tx rx buffer? need rx page own bit */ + if (I2STxData != NULL) { + HAL_I2S_WRITE32(I2SIdx, REG_I2S_TX_PAGE_PTR, (u32)I2STxData); + } + + if (I2SRxData != NULL) { + HAL_I2S_WRITE32(I2SIdx, REG_I2S_RX_PAGE_PTR, (u32)I2SRxData); + } + + pHalI2SInitData->I2STxIdx = 0; + pHalI2SInitData->I2SRxIdx = 0; + pHalI2SInitData->I2SHWTxIdx = 0; + pHalI2SInitData->I2SHWRxIdx = 0; + /* I2S Clear all interrupts first */ + HalI2SClrAllIntrRtl8195a(pHalI2SInitData); + + /* I2S Disable all interrupts first */ + I2STxIntrMSK = pHalI2SInitData->I2STxIntrMSK; + I2SRxIntrMSK = pHalI2SInitData->I2SRxIntrMSK; + pHalI2SInitData->I2STxIntrMSK = 0; + pHalI2SInitData->I2SRxIntrMSK = 0; + HalI2SIntrCtrlRtl8195a(pHalI2SInitData); + pHalI2SInitData->I2STxIntrMSK = I2STxIntrMSK; + pHalI2SInitData->I2SRxIntrMSK = I2SRxIntrMSK; + + return _EXIT_SUCCESS; +} + +RTK_STATUS +HalI2SSetRateRtl8195a( + IN VOID *Data +) +{ + PHAL_I2S_INIT_DAT pHalI2SInitData = (PHAL_I2S_INIT_DAT)Data; + u8 I2SIdx; + u32 reg_value; + + I2SIdx = pHalI2SInitData->I2SIdx; + + reg_value = HAL_I2S_READ32(I2SIdx, REG_I2S_CTL); + reg_value &= ~(BIT_MASK_CTLX_I2S_CLK_SRC << BIT_SHIFT_CTLX_I2S_CLK_SRC); + if (pHalI2SInitData->I2SRate&0x10) + { + reg_value |= BIT_CTRL_CTLX_I2S_CLK_SRC(1); + } + HAL_I2S_WRITE32(I2SIdx, REG_I2S_CTL, reg_value); + + reg_value = HAL_I2S_READ32(I2SIdx, REG_I2S_SETTING); + reg_value &= ~(BIT_MASK_SETTING_I2S_SAMPLE_RATE << BIT_SHIFT_SETTING_I2S_SAMPLE_RATE); + reg_value |= BIT_CTRL_SETTING_I2S_SAMPLE_RATE(pHalI2SInitData->I2SRate); + HAL_I2S_WRITE32(I2SIdx, REG_I2S_SETTING, reg_value); + + return _EXIT_SUCCESS; +} + +RTK_STATUS +HalI2SSetWordLenRtl8195a( + IN VOID *Data +) +{ + PHAL_I2S_INIT_DAT pHalI2SInitData = (PHAL_I2S_INIT_DAT)Data; + u8 I2SIdx; + u32 reg_value; + + I2SIdx = pHalI2SInitData->I2SIdx; + reg_value = HAL_I2S_READ32(I2SIdx, REG_I2S_CTL); + reg_value &= ~(BIT_MASK_CTLX_I2S_WL << BIT_SHIFT_CTLX_I2S_WL); + reg_value |= BIT_CTRL_CTLX_I2S_WL(pHalI2SInitData->I2SWordLen); + HAL_I2S_WRITE32(I2SIdx, REG_I2S_CTL, reg_value); + + return _EXIT_SUCCESS; +} + +RTK_STATUS +HalI2SSetChNumRtl8195a( + IN VOID *Data +) +{ + PHAL_I2S_INIT_DAT pHalI2SInitData = (PHAL_I2S_INIT_DAT)Data; + u8 I2SIdx; + u32 reg_value; + + I2SIdx = pHalI2SInitData->I2SIdx; + reg_value = HAL_I2S_READ32(I2SIdx, REG_I2S_CTL); + reg_value &= ~(BIT_MASK_CTLX_I2S_CH_NUM << BIT_SHIFT_CTLX_I2S_CH_NUM); + reg_value |= BIT_CTRL_CTLX_I2S_CH_NUM(pHalI2SInitData->I2SChNum); + HAL_I2S_WRITE32(I2SIdx, REG_I2S_CTL, reg_value); + + return _EXIT_SUCCESS; +} + +RTK_STATUS +HalI2SSetPageNumRtl8195a( + IN VOID *Data +) +{ + PHAL_I2S_INIT_DAT pHalI2SInitData = (PHAL_I2S_INIT_DAT)Data; + u8 I2SIdx; + u32 reg_value; + + I2SIdx = pHalI2SInitData->I2SIdx; + + reg_value = HAL_I2S_READ32(I2SIdx, REG_I2S_SETTING); + reg_value &= ~(BIT_MASK_SETTING_I2S_PAGE_NUM << BIT_SHIFT_SETTING_I2S_PAGE_NUM); + reg_value |= BIT_CTRL_SETTING_I2S_PAGE_NUM(pHalI2SInitData->I2SPageNum); + HAL_I2S_WRITE32(I2SIdx, REG_I2S_SETTING, reg_value); + + return _EXIT_SUCCESS; +} + +RTK_STATUS +HalI2SSetPageSizeRtl8195a( + IN VOID *Data +) +{ + PHAL_I2S_INIT_DAT pHalI2SInitData = (PHAL_I2S_INIT_DAT)Data; + u8 I2SIdx; + u32 reg_value; + + I2SIdx = pHalI2SInitData->I2SIdx; + + reg_value = HAL_I2S_READ32(I2SIdx, REG_I2S_SETTING); + reg_value &= ~(BIT_MASK_SETTING_I2S_PAGE_SZ << BIT_SHIFT_SETTING_I2S_PAGE_SZ); + reg_value |= BIT_CTRL_SETTING_I2S_PAGE_SZ(pHalI2SInitData->I2SPageSize); + HAL_I2S_WRITE32(I2SIdx, REG_I2S_SETTING, reg_value); + + return _EXIT_SUCCESS; +} + +RTK_STATUS +HalI2SSetDirectionRtl8195a( + IN VOID *Data +) +{ + PHAL_I2S_INIT_DAT pHalI2SInitData = (PHAL_I2S_INIT_DAT)Data; + u8 I2SIdx; + u32 reg_value; + + I2SIdx = pHalI2SInitData->I2SIdx; + + reg_value = HAL_I2S_READ32(I2SIdx, REG_I2S_CTL); + reg_value &= ~(BIT_MASK_CTLX_I2S_TRX_ACT << BIT_SHIFT_CTLX_I2S_TRX_ACT); + reg_value |= BIT_CTRL_CTLX_I2S_TRX_ACT(pHalI2SInitData->I2STRxAct); + HAL_I2S_WRITE32(I2SIdx, REG_I2S_CTL, reg_value); + + return _EXIT_SUCCESS; +} + +RTK_STATUS +HalI2SSetDMABufRtl8195a( + IN VOID *Data +) +{ + PHAL_I2S_INIT_DAT pHalI2SInitData = (PHAL_I2S_INIT_DAT)Data; + u8 I2SIdx; + u32 reg_value; + u32 page_num; + + I2SIdx = pHalI2SInitData->I2SIdx; + + reg_value = HAL_I2S_READ32(I2SIdx, REG_I2S_SETTING); + reg_value &= ~(BIT_MASK_SETTING_I2S_PAGE_SZ << BIT_SHIFT_SETTING_I2S_PAGE_SZ); + reg_value &= ~(BIT_MASK_SETTING_I2S_PAGE_NUM << BIT_SHIFT_SETTING_I2S_PAGE_NUM); + reg_value |= BIT_CTRL_SETTING_I2S_PAGE_SZ(pHalI2SInitData->I2SPageSize); + reg_value |= BIT_CTRL_SETTING_I2S_PAGE_NUM(pHalI2SInitData->I2SPageNum); + HAL_I2S_WRITE32(I2SIdx, REG_I2S_SETTING, reg_value); + + page_num = pHalI2SInitData->I2SPageNum + 1; + if (pHalI2SInitData->I2STxData) { + HAL_I2S_WRITE32(I2SIdx, REG_I2S_TX_PAGE_PTR, (uint32_t)pHalI2SInitData->I2STxData); + pHalI2SInitData->I2STxIntrMSK = (1<I2STxIntrMSK = 0; + } + + if (pHalI2SInitData->I2SRxData) { + HAL_I2S_WRITE32(I2SIdx, REG_I2S_RX_PAGE_PTR, (uint32_t)pHalI2SInitData->I2SRxData); + pHalI2SInitData->I2SRxIntrMSK = (1<I2SRxIntrMSK = 0; + + } + + // According to the page number to modify the ISR mask + HalI2SIntrCtrlRtl8195a(pHalI2SInitData); + + return _EXIT_SUCCESS; +} + +u8 +HalI2SGetTxPageRtl8195a( + IN VOID *Data +) +{ + PHAL_I2S_INIT_DAT pHalI2SInitData = (PHAL_I2S_INIT_DAT)Data; + + u8 I2SIdx; + u16 I2STxIdx = pHalI2SInitData->I2STxIdx; + u32 reg; + + I2SIdx = pHalI2SInitData->I2SIdx; + + reg = HAL_I2S_READ32(I2SIdx, REG_I2S_TX_PAGE0_OWN+(I2STxIdx<<2)); + if ((reg & (1<<31)) == 0) { + return I2STxIdx; + } else { + return 0xFF; + } +} + +u8 +HalI2SGetRxPageRtl8195a( + IN VOID *Data +) +{ + PHAL_I2S_INIT_DAT pHalI2SInitData = (PHAL_I2S_INIT_DAT)Data; + + u8 I2SIdx; + u16 I2SRxIdx = pHalI2SInitData->I2SRxIdx; + u32 reg; + + I2SIdx = pHalI2SInitData->I2SIdx; + + reg = HAL_I2S_READ32(I2SIdx, REG_I2S_RX_PAGE0_OWN+(I2SRxIdx << 2)); + if ((reg & (1<<31)) == 0) { + return I2SRxIdx; + } else { + return 0xFF; + } +} + +RTK_STATUS +HalI2SPageSendRtl8195a( + IN VOID *Data, + IN u8 PageIdx +) +{ + PHAL_I2S_INIT_DAT pHalI2SInitData = (PHAL_I2S_INIT_DAT)Data; + u16 I2STxIdx = pHalI2SInitData->I2STxIdx; + u8 I2SPageNum = pHalI2SInitData->I2SPageNum; + u8 I2SIdx; + + if (I2STxIdx != PageIdx) { + DBG_I2S_ERR("HalI2SPageSendRtl8195a: UnExpected Page Index. TxPage=%d, Expected:%d\r\n", + PageIdx, I2STxIdx); + } + + I2SIdx = pHalI2SInitData->I2SIdx; + + HAL_I2S_WRITE32(I2SIdx, REG_I2S_TX_PAGE0_OWN+4*PageIdx, 1<<31); + I2STxIdx = PageIdx+1; + if (I2STxIdx > I2SPageNum) { + I2STxIdx = 0; + } + pHalI2SInitData->I2STxIdx = I2STxIdx; + + return _EXIT_SUCCESS; +} + +RTK_STATUS +HalI2SPageRecvRtl8195a( + IN VOID *Data +) +{ + PHAL_I2S_INIT_DAT pHalI2SInitData = (PHAL_I2S_INIT_DAT)Data; + u16 I2SRxIdx = pHalI2SInitData->I2SRxIdx; + u8 I2SPageNum = pHalI2SInitData->I2SPageNum; + u32 reg; + u8 I2SIdx; + + I2SIdx = pHalI2SInitData->I2SIdx; + reg = HAL_I2S_READ32(I2SIdx, REG_I2S_RX_PAGE0_OWN+(I2SRxIdx << 2)); + if ((reg & (1<<31)) != 0) { + DBG_I2S_ERR("HalI2SPageRecvRtl8195a: No Idle Rx Page\r\n"); + return _EXIT_FAILURE; + } + + HAL_I2S_WRITE32(I2SIdx, REG_I2S_RX_PAGE0_OWN+(I2SRxIdx<<2), 1<<31); + I2SRxIdx += 1; + if (I2SRxIdx > I2SPageNum) { + I2SRxIdx = 0; + } + pHalI2SInitData->I2SRxIdx = I2SRxIdx; + + return _EXIT_SUCCESS; +} + +RTK_STATUS +HalI2SClearAllOwnBitRtl8195a( + IN VOID *Data +) +{ + PHAL_I2S_INIT_DAT pHalI2SInitData = (PHAL_I2S_INIT_DAT)Data; + u8 I2SIdx; + u32 i; + + I2SIdx = pHalI2SInitData->I2SIdx; + + for (i=0;i<4;i++) { + HAL_I2S_WRITE32(I2SIdx, REG_I2S_TX_PAGE0_OWN+(i<<2), 0); + HAL_I2S_WRITE32(I2SIdx, REG_I2S_RX_PAGE0_OWN+(i<<2), 0); + } + return _EXIT_SUCCESS; +} + +RTK_STATUS +HalI2SDMACtrlRtl8195a( + IN VOID *Data +) +{ + + return _EXIT_SUCCESS; +} + + diff --git a/component/soc/realtek/8195a/fwlib/rtl8195a/src/rtl8195a_mii.c b/component/soc/realtek/8195a/fwlib/rtl8195a/src/rtl8195a_mii.c new file mode 100644 index 0000000..b4e7139 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/rtl8195a/src/rtl8195a_mii.c @@ -0,0 +1,411 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + + +#include "rtl8195a.h" +#include "rtl8195a_mii.h" +#include "hal_mii.h" + + + +VOID MiiIrqHandle (IN VOID *Data); + +VOID MiiIrqHandle (IN VOID *Data) { + PMII_ADAPTER pMiiAdapter = (PMII_ADAPTER) Data; + PHAL_MII_ADAPTER pHalMiiAdapter = pMiiAdapter->pHalMiiAdapter; + u32 RegValue = HalMiiGmacGetInterruptStatusRtl8195a(); +#ifdef CONFIG_MII_VERIFY + extern u8 isRxOK; + extern u8 isTxOK; + extern u8 RxIntCnt; + + +// DBG_8195A("ISR = 0x%08X\n", RegValue); + if(RegValue & GMAC_ISR_ROK) { + HalMiiGmacClearInterruptStatusRtl8195a(0x00410001); + isRxOK = 1; + RxIntCnt++; + } + + if(RegValue & GMAC_ISR_TOK_TI) { + HalMiiGmacClearInterruptStatusRtl8195a(0x00410040); + isTxOK = 1; + } +#else + +#endif +} + + +VOID +ConfigDebugPort_E4(u32 DebugSelect) { + u32 RegValue; + BOOL DebugMsg = _FALSE; + + if (DebugMsg) { + LOGI(ANSI_COLOR_YELLOW"Debug Port Select (0xE4)\n"ANSI_COLOR_RESET); + LOGD2("[P] PERI_ON_010: %X\n", HAL_READ32(PERI_ON_BASE, REG_SOC_FUNC_EN)); + LOGD2("[P] PERI_ON_014: %X\n", HAL_READ32(PERI_ON_BASE, REG_SOC_HCI_COM_FUNC_EN)); + } + + RegValue = HAL_MII_READ32(REG_RTL_MII_CCR); + if (DebugMsg) { + LOGD2("[B] 0x00E4: %X\n", RegValue); + } + + RegValue |= DebugSelect << 2; + if (DebugMsg) { + LOGD2("[B] RegValue: %X\n", RegValue); + } + + HAL_MII_WRITE32(REG_RTL_MII_CCR, RegValue); + if (DebugMsg) { + LOGD2("[A] 0x00E4: %X\n", HAL_MII_READ32(REG_RTL_MII_CCR)); + } +} + + +/** + * MII Initialize. + * + * MII Initialize. + * + * Initialization Steps: + * I. Rtl8195A Board Configurations: + * 1. MII Function Enable & AHB mux + * + * @return runtime status value. + */ +BOOL +HalMiiGmacInitRtl8195a( + IN VOID *Data + ) +{ + PMII_ADAPTER pMiiAdapter = (PMII_ADAPTER) Data; + PHAL_MII_ADAPTER pHalMiiAdapter = pMiiAdapter->pHalMiiAdapter; + u32 RegValue; + + + /* 1. enable MII Pinmux & disable SDIO Host/Device mode Pinmux */ + RegValue = HAL_READ32(PERI_ON_BASE, REG_HCI_PINMUX_CTRL); + RegValue |= BIT24; + RegValue &= ~(BIT0 | BIT1); // Important! + HAL_WRITE32(PERI_ON_BASE, REG_HCI_PINMUX_CTRL, RegValue); + + /* 2. enable MII IP block (214, 12) */ + RegValue = HAL_READ32(PERI_ON_BASE, REG_SOC_HCI_COM_FUNC_EN); + RegValue |= BIT12; + HAL_WRITE32(PERI_ON_BASE, REG_SOC_HCI_COM_FUNC_EN, RegValue); + + /* 3. Lexra2AHB Function Enable (304, 11) */ + RegValue = HAL_READ32(PERI_ON_BASE, REG_PESOC_SOC_CTRL); + RegValue |= BIT11; + HAL_WRITE32(PERI_ON_BASE, REG_PESOC_SOC_CTRL, RegValue); + + /* 4. enable MII bus clock (240, 24|25) */ + RegValue = HAL_READ32(PERI_ON_BASE, REG_PESOC_HCI_CLK_CTRL0); + RegValue |= (BIT24 | BIT25); + HAL_WRITE32(PERI_ON_BASE, REG_PESOC_HCI_CLK_CTRL0, RegValue); + + /* 5. */ + RegValue = HAL_READ32(SYSTEM_CTRL_BASE, 0x74) & 0xFFFFC7FF; + HAL_WRITE32(SYSTEM_CTRL_BASE, 0x74, (RegValue | 0x00003000)); + + /* 6. AHB mux: select MII (214, 13) */ + RegValue = HAL_READ32(PERI_ON_BASE, REG_SOC_HCI_COM_FUNC_EN); + RegValue |= BIT13; + HAL_WRITE32(PERI_ON_BASE, REG_SOC_HCI_COM_FUNC_EN, RegValue); + + /* 7. Vendor Register Clock Enable (230, 6|7) */ + RegValue = HAL_READ32(PERI_ON_BASE, REG_PESOC_CLK_CTRL); + RegValue |= (BIT6 | BIT7); + HAL_WRITE32(PERI_ON_BASE, REG_PESOC_CLK_CTRL, RegValue); + + /* 8. Enable GMAC Lexra Timeout (090, 16|17|18) */ + RegValue = HAL_READ32(VENDOR_REG_BASE, 0x0090); + RegValue |= (BIT16 | BIT17 | BIT18); + HAL_WRITE32(VENDOR_REG_BASE, 0x0090, RegValue); + + /* 9. Endian Swap Control (304, 12|13) */ + RegValue = HAL_READ32(PERI_ON_BASE, REG_PESOC_SOC_CTRL); + RegValue |= (BIT12 | BIT13); + HAL_WRITE32(PERI_ON_BASE, REG_PESOC_SOC_CTRL, RegValue); + + return _TRUE; +} + + +BOOL +HalMiiInitRtl8195a( + IN VOID *Data + ) +{ + DBG_ENTRANCE; + PMII_ADAPTER pMiiAdapter = (PMII_ADAPTER) Data; + PHAL_MII_ADAPTER pHalMiiAdapter = pMiiAdapter->pHalMiiAdapter; + u32 RegValue; + + return _TRUE; +} + + +BOOL +HalMiiGmacResetRtl8195a( + IN VOID *Data + ) +{ + HAL_MII_WRITE32(REG_RTL_MII_CR, (HAL_MII_READ32(REG_RTL_MII_CR) | BIT0)); + + return _TRUE; +} + + +BOOL +HalMiiGmacEnablePhyModeRtl8195a( + IN VOID *Data + ) +{ + return _TRUE; +} + + +u32 +HalMiiGmacXmitRtl8195a( + IN VOID *Data + ) +{ + return 0; +} + + +VOID +HalMiiGmacCleanTxRingRtl8195a( + IN VOID *Data + ) +{ +} + + +VOID +HalMiiGmacFillTxInfoRtl8195a( + IN VOID *Data + ) +{ + DBG_ENTRANCE; + PMII_ADAPTER pMiiAdapter = (PMII_ADAPTER) Data; + PHAL_MII_ADAPTER pHalMiiAdapter = pMiiAdapter->pHalMiiAdapter; + PTX_INFO pTx_Info = pMiiAdapter->pTx_Info; + VOID* TxBuffer = pMiiAdapter->TxBuffer; + u32 RegValue; + + LOGI(ANSI_COLOR_GREEN"==[ Tx Descriptor Configuration ]======\n"ANSI_COLOR_RESET); + + pTx_Info->opts1.dw = 0xBC8001FE; + /* pTx_Info->opts1.dw = 0xBC800080; // size: 128 */ + + pTx_Info->addr = (u32)TxBuffer; + pTx_Info->opts2.dw = 0x0400279F; + pTx_Info->opts3.dw = 0x00000000; + /* pTx_Info->opts4.dw = 0x57800000; */ + pTx_Info->opts4.dw = 0x1FE00000; + LOGI("pTx_Info->addr: %X\n", pTx_Info->addr); + + LOGI(ANSI_COLOR_YELLOW"TxFDP1 Register(0x%04X) (W: 0x%X)\n"ANSI_COLOR_RESET, REG_RTL_MII_TXFDP1, pTx_Info); + RegValue = HAL_MII_READ32(REG_RTL_MII_TXFDP1); + LOGD2("[B] REG_RTL_MII_TXFDP1: %X\n", RegValue); + HAL_MII_WRITE32(REG_RTL_MII_TXFDP1, pTx_Info); + LOGD2("[A] REG_RTL_MII_TXFDP1: %X\n", HAL_MII_READ32(REG_RTL_MII_TXFDP1)); +} + + +VOID +HalMiiGmacFillRxInfoRtl8195a( + IN VOID *Data + ) +{ + DBG_ENTRANCE; + PMII_ADAPTER pMiiAdapter = (PMII_ADAPTER) Data; + PHAL_MII_ADAPTER pHalMiiAdapter = pMiiAdapter->pHalMiiAdapter; + PRX_INFO pRx_Info = pMiiAdapter->pRx_Info; + VOID* RxBuffer = pMiiAdapter->RxBuffer; + u32 RegValue; + + LOGI(ANSI_COLOR_GREEN"==[ Rx Descriptor Configuration ]======\n"ANSI_COLOR_RESET); + + /* pRx_Info->opts1.dw = 0x80000200; //Data Length: 4095(FFF), 512(200) */ + pRx_Info->opts1.dw = 0x800001FC; //Data Length: 4095(FFF), 512(200) + /* pRx_Info->opts1.dw = 0x8000007F; */ + + pRx_Info->addr = (u32)RxBuffer; + pRx_Info->opts2.dw = 0x00000000; + pRx_Info->opts3.dw = 0x00000000; + + LOGI(ANSI_COLOR_YELLOW"RxFDP1 Register(0x%04X) (W: 0x%X)\n"ANSI_COLOR_RESET, REG_RTL_MII_RXFDP1, pRx_Info); + RegValue = HAL_MII_READ32(REG_RTL_MII_RXFDP1); + LOGD2("[B] REG_RTL_MII_RXFDP1: %X\n", RegValue); + HAL_MII_WRITE32(REG_RTL_MII_RXFDP1, pRx_Info); + LOGD2("[A] REG_RTL_MII_RXFDP1: %X\n", HAL_MII_READ32(REG_RTL_MII_RXFDP1)); +} + + +VOID +HalMiiGmacTxRtl8195a( + IN VOID *Data + ) +{ + DBG_ENTRANCE; + PMII_ADAPTER pMiiAdapter = (PMII_ADAPTER) Data; + PHAL_MII_ADAPTER pHalMiiAdapter = pMiiAdapter->pHalMiiAdapter; + PTX_INFO pTx_Info = pMiiAdapter->pTx_Info; + u32 RegValue; + + LOGI(ANSI_COLOR_GREEN"==[ Tx ]===============================\n"ANSI_COLOR_RESET); + + LOGI(ANSI_COLOR_YELLOW"REG_RTL_MII_IOCMD Register(0x%04X): Enable Tx (W: 0x10, BIT4)\n"ANSI_COLOR_RESET, REG_RTL_MII_IOCMD); + RegValue = HAL_MII_READ32(REG_RTL_MII_IOCMD); + LOGD2("[B] REG_RTL_MII_IOCMD: %X\n", RegValue); + RegValue |= BIT_IOCMD_TXENABLE(1); + HAL_MII_WRITE32(REG_RTL_MII_IOCMD, RegValue); + LOGD2("[A] REG_RTL_MII_IOCMD: %X\n", HAL_MII_READ32(REG_RTL_MII_IOCMD)); + LOGD4("--> Tx Descriptor opts1: %X\n", HAL_READ32(pTx_Info, 0)); + + LOGI(ANSI_COLOR_YELLOW"REG_RTL_MII_IOCMD Register(0x%04X): Enable 1st Tx (W: 0x1, BIT0)\n"ANSI_COLOR_RESET, REG_RTL_MII_IOCMD); + RegValue = HAL_MII_READ32(REG_RTL_MII_IOCMD); + LOGD2("[B] REG_RTL_MII_IOCMD: %X\n", RegValue); + RegValue |= BIT_IOCMD_FIRST_DMATX_ENABLE(1); + HAL_MII_WRITE32(REG_RTL_MII_IOCMD, RegValue); + LOGD2("[A] REG_RTL_MII_IOCMD: %X\n", HAL_MII_READ32(REG_RTL_MII_IOCMD)); + LOGD4("--> Tx Descriptor opts1: %X\n", HAL_READ32(pTx_Info, 0)); +} + + +VOID +HalMiiGmacRxRtl8195a( + IN VOID *Data + ) +{ + DBG_ENTRANCE; + PMII_ADAPTER pMiiAdapter = (PMII_ADAPTER) Data; + PHAL_MII_ADAPTER pHalMiiAdapter = pMiiAdapter->pHalMiiAdapter; + u32 RegValue; + + LOGI(ANSI_COLOR_GREEN"==[ Rx ]===============================\n"ANSI_COLOR_RESET); + LOGI(ANSI_COLOR_YELLOW"Transmit (Tx) Configuration Register (0x%04X) (W: 0x00000C00)\n"ANSI_COLOR_RESET, REG_RTL_MII_TCR); + RegValue = HAL_MII_READ32(REG_RTL_MII_TCR); + LOGD2("[B] REG_RTL_MII_TCR: %X\n", RegValue); + + HAL_MII_WRITE32(REG_RTL_MII_TCR, 0x00000D00); // loopback R2T mode + LOGD2("[A] REG_RTL_MII_TCR: %X\n", HAL_MII_READ32(REG_RTL_MII_TCR)); + + LOGI(ANSI_COLOR_YELLOW"Receive (Rx) Configuration Register (0x%04X) (W: 0x0000007F)\n"ANSI_COLOR_RESET, REG_RTL_MII_RCR); + RegValue = HAL_MII_READ32(REG_RTL_MII_RCR); + LOGD2("[B] REG_RTL_MII_RCR: %X\n", RegValue); + HAL_MII_WRITE32(REG_RTL_MII_RCR, 0x0000007F); + LOGD2("[A] REG_RTL_MII_RCR: %X\n", HAL_MII_READ32(REG_RTL_MII_RCR)); + + LOGI(ANSI_COLOR_YELLOW"EhtrntRxCPU_Des_Num1 (0x%04X) (W: 0x1F0A0F00)\n"ANSI_COLOR_RESET, REG_RTL_MII_ETNRXCPU1); + RegValue = HAL_MII_READ32(REG_RTL_MII_ETNRXCPU1); + LOGD2("[B] REG_RTL_MII_ETNRXCPU1: %X\n", RegValue); + HAL_MII_WRITE32(REG_RTL_MII_ETNRXCPU1, 0x1F0A0F00); + LOGD2("[A] REG_RTL_MII_ETNRXCPU1: %X\n", HAL_MII_READ32(REG_RTL_MII_ETNRXCPU1)); + + LOGI(ANSI_COLOR_YELLOW"Rx_Pse_Des_Thres_1_h (0x%04X) (W: 0x00000022)\n"ANSI_COLOR_RESET, REG_RTL_MII_RX_PSE1); + RegValue = HAL_MII_READ32(REG_RTL_MII_RX_PSE1); + LOGD2("[B] REG_RTL_MII_RX_PSE1: %X\n", RegValue); + HAL_MII_WRITE32(REG_RTL_MII_RX_PSE1, 0x00000022); + LOGD2("[A] REG_RTL_MII_RX_PSE1: %X\n", HAL_MII_READ32(REG_RTL_MII_RX_PSE1)); + + LOGI(ANSI_COLOR_YELLOW"Ethernet_IO_CMD1 Register(0x%04X): Enable Rx Ring1 (W: 0x10000, BIT16)\n"ANSI_COLOR_RESET, REG_RTL_MII_IOCMD1); + RegValue = HAL_MII_READ32(REG_RTL_MII_IOCMD1); + LOGD2("[B] REG_RTL_MII_IOCMD1: %X\n", RegValue); + RegValue |= BIT_IOCMD1_FIRST_DMARX_ENABLE(1); + HAL_MII_WRITE32(REG_RTL_MII_IOCMD1, RegValue); + LOGD2("[A] REG_RTL_MII_IOCMD1: %X\n", HAL_MII_READ32(REG_RTL_MII_IOCMD1)); + + LOGI(ANSI_COLOR_YELLOW"REG_RTL_MII_IOCMD Register(0x%04X): Enable Rx (W: 0x20, BIT5)\n"ANSI_COLOR_RESET, REG_RTL_MII_IOCMD); + RegValue = HAL_MII_READ32(REG_RTL_MII_IOCMD); + LOGD2("[B] REG_RTL_MII_IOCMD: %X\n", RegValue); + RegValue |= BIT_IOCMD_RXENABLE(1); + HAL_MII_WRITE32(REG_RTL_MII_IOCMD, RegValue); + LOGD2("[A] REG_RTL_MII_IOCMD: %X\n", HAL_MII_READ32(REG_RTL_MII_IOCMD)); +} + + +VOID +HalMiiGmacSetDefaultEthIoCmdRtl8195a( + IN VOID *Data + ) +{ + DBG_ENTRANCE; + PMII_ADAPTER pMiiAdapter = (PMII_ADAPTER) Data; + PHAL_MII_ADAPTER pHalMiiAdapter = pMiiAdapter->pHalMiiAdapter; + u32 RegValue; + + LOGI(ANSI_COLOR_YELLOW"REG_RTL_MII_IOCMD Register(0x%04X) (W: CMD_CONFIG)\n"ANSI_COLOR_RESET, REG_RTL_MII_IOCMD); + RegValue = HAL_MII_READ32(REG_RTL_MII_IOCMD); + LOGD2("[B] REG_RTL_MII_IOCMD: %X\n", RegValue); + HAL_MII_WRITE32(REG_RTL_MII_IOCMD, CMD_CONFIG); + LOGD2("[A] REG_RTL_MII_IOCMD: %X\n", HAL_MII_READ32(REG_RTL_MII_IOCMD)); + + LOGI(ANSI_COLOR_YELLOW"Ethernet_IO_CMD1 Register(0x%04X) (W: CMD1_CONFIG)\n"ANSI_COLOR_RESET, REG_RTL_MII_IOCMD1); + RegValue = HAL_MII_READ32(REG_RTL_MII_IOCMD1); + LOGD2("[B] REG_RTL_MII_IOCMD1: %X\n", RegValue); + HAL_MII_WRITE32(REG_RTL_MII_IOCMD1, CMD1_CONFIG); + LOGD2("[A] REG_RTL_MII_IOCMD1: %X\n", HAL_MII_READ32(REG_RTL_MII_IOCMD1)); + + //2014-04-29 yclin (disable 0x40051438[27] r_en_precise_dma) { + RegValue = HAL_MII_READ32(REG_RTL_MII_IOCMD1); + RegValue = RegValue & 0xF7FFFFFF; + HAL_MII_WRITE32(REG_RTL_MII_IOCMD1, RegValue); + // } +} + + +VOID +HalMiiGmacInitIrqRtl8195a( + IN VOID *Data + ) +{ + IRQ_HANDLE MiiIrqHandle_Master; + PMII_ADAPTER pMiiAdapter = (PMII_ADAPTER) Data; + + + MiiIrqHandle_Master.Data = (u32) (pMiiAdapter); + MiiIrqHandle_Master.IrqNum = GMAC_IRQ; + MiiIrqHandle_Master.IrqFun = (IRQ_FUN) MiiIrqHandle; + MiiIrqHandle_Master.Priority = 0; + InterruptRegister(&MiiIrqHandle_Master); + InterruptEn(&MiiIrqHandle_Master); +} + + +u32 +HalMiiGmacGetInterruptStatusRtl8195a( + VOID + ) +{ + DBG_ENTRANCE; + u32 RegValue; + + RegValue = HAL_MII_READ32(REG_RTL_MII_IMRISR); + LOGD("REG_RTL_MII_IMRISR: %X\n", RegValue); + return RegValue; +} + + +VOID +HalMiiGmacClearInterruptStatusRtl8195a( + u32 IsrStatus + ) +{ + DBG_ENTRANCE; + HAL_MII_WRITE32(REG_RTL_MII_IMRISR, IsrStatus); +} + + diff --git a/component/soc/realtek/8195a/fwlib/rtl8195a/src/rtl8195a_nfc.c b/component/soc/realtek/8195a/fwlib/rtl8195a/src/rtl8195a_nfc.c new file mode 100644 index 0000000..25cf1ec --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/rtl8195a/src/rtl8195a_nfc.c @@ -0,0 +1,1919 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#include "rtl8195a.h" + +//#include "autoconf.h" +//#include "diag.h" +//#include "hal_peri_on.h" +#include "rtl8195a_nfc.h" +//#include "hal_nfc.h" +//#include "rtl8195a_peri_on.h" +//#include "rtl8195a_sys_on.h" +//#include "hal_platform.h" + +#ifdef CONFIG_NFC_NORMAL + +extern void nfc_tagwrite_callback(PNFC_ADAPTER pNFCAdp, uint32_t page, uint32_t wr_data); +extern void nfc_event_callback(PNFC_ADAPTER pNFCAdp, uint32_t event); +extern void nfc_tagread_callback(PNFC_ADAPTER pNFCAdp, uint32_t page); +extern void nfc_cache_read_callback(PNFC_ADAPTER pNFCAdp, uint32_t start_pg, uint32_t *pbuf); + +extern VOID SpicLoadInitParaFromClockRtl8195A(u8 CpuClkMode, u8 BaudRate, PSPIC_INIT_PARA pSpicInitPara); +extern VOID SpicSectorEraseFlashRtl8195A(u32 Address); +extern VOID SpicWaitBusyDoneRtl8195A(VOID); +extern VOID SpicWaitWipDoneRtl8195A(SPIC_INIT_PARA SpicInitPara); + + +VOID WriteA2NMailbox(IN VOID *pNFCAdapte); +VOID A2NWriteInQueue(IN VOID *pNFCAdapte, IN VOID *pBuff); +VOID A2NWriteDeQueue(IN VOID *pNFCAdapte); +VOID N2AReadTag(IN VOID *pNFCAdapte, IN u8 N2ARPage); +u32 HalNFCRead32(IN u32 Addr); +VOID HalNFCWrite32(IN u32 Addr, IN u32 Data); +VOID N2AWriteTag(IN VOID *pNFCAdapte, IN u8 N2AWPage); +VOID N2AReadCatch(IN VOID *pNFCAdapte, IN u8 N2ACatchRPage); +VOID NFCReaderPresent(IN VOID *pNFCAdapte, IN u8 State); +VOID N2AMailboxState(IN VOID *pNFCAdapte, IN u8 State, IN u8 Seq); +VOID NFC25MClkReq(IN VOID *pNFCAdapte, IN u8 OP, IN u8 Seq); + +//demo +u8 NFCFWIMEM[]={ +0x01, 0x10, 0x00, 0x65, 0x00, 0x68, 0xA8, 0xB9, 0x00, 0x65, 0x40, 0xF0, 0x20, 0x69, 0x89, 0xB9, +0x00, 0x65, 0x13, 0xF7, 0x20, 0x6A, 0x80, 0xF0, 0x08, 0x4A, 0x7E, 0xF0, 0x2D, 0x68, 0x7E, 0xF0, +0x0C, 0x48, 0x00, 0xDA, 0x00, 0x65, 0x00, 0x65, 0x00, 0x65, 0x00, 0x65, 0x13, 0xF7, 0x20, 0x6A, +0x08, 0x4A, 0x00, 0x9A, 0x00, 0x65, 0x00, 0xF0, 0x20, 0x69, 0xFF, 0xF4, 0x1F, 0x49, 0x2C, 0xE8, +0x00, 0xDA, 0x00, 0x65, 0x13, 0xF7, 0x20, 0x6A, 0x80, 0xF0, 0x04, 0x4A, 0x00, 0x68, 0x00, 0xDA, +0x00, 0x65, 0x13, 0xF7, 0x20, 0x6A, 0x80, 0xF0, 0x00, 0x4A, 0x02, 0xF0, 0x20, 0x68, 0xFF, 0x48, +0x00, 0xDA, 0x00, 0x65, 0x10, 0xF0, 0x20, 0x68, 0x00, 0xF4, 0x01, 0x48, 0x00, 0xE8, 0x00, 0x65, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xDF, 0xF7, 0x04, 0x63, 0x0E, 0xD2, 0x0D, 0xD3, 0x0C, 0xD0, 0x0B, 0xD1, 0x0A, 0xD4, 0x09, 0xD5, +0x08, 0xD6, 0x07, 0xD7, 0x58, 0x67, 0x06, 0xD2, 0x05, 0x62, 0x8D, 0xB8, 0xAE, 0xB8, 0xC8, 0xB8, +0xEC, 0xB8, 0x00, 0x18, 0x28, 0x01, 0x00, 0x65, 0x00, 0x6A, 0xAA, 0xB9, 0x06, 0x92, 0x1A, 0x65, +0x05, 0x92, 0xFA, 0x65, 0x0E, 0x92, 0x0D, 0x93, 0x0C, 0x90, 0x0B, 0x91, 0x0A, 0x94, 0x09, 0x95, +0x08, 0x96, 0x07, 0x97, 0x20, 0xF0, 0x1C, 0x63, 0x00, 0xBA, 0x00, 0x65, 0x00, 0xF0, 0x20, 0x6A, +0xFF, 0x4A, 0x60, 0x9A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x13, 0xF7, 0x20, 0x6A, 0x50, 0x4A, 0x00, 0x9A, 0x00, 0x65, 0x10, 0xF0, 0x20, 0x69, 0xFF, 0x49, +0x2C, 0xE8, 0x00, 0xDA, 0x00, 0x65, 0x34, 0xB8, 0x00, 0xF4, 0x00, 0x68, 0x2D, 0xE8, 0x90, 0xB9, +0x00, 0x65, 0x00, 0x65, 0x00, 0x65, 0x14, 0xB8, 0x00, 0xF4, 0x00, 0x69, 0x2C, 0xE8, 0xFB, 0x20, +0x00, 0x65, 0x10, 0xF0, 0x20, 0x68, 0x20, 0xF4, 0x1F, 0x48, 0x00, 0xE8, 0x00, 0x65, 0x10, 0xF0, +0x30, 0x6A, 0xC0, 0xF2, 0x00, 0x4A, 0x10, 0xF0, 0x30, 0x6B, 0xA0, 0xF6, 0x08, 0x4B, 0x00, 0x68, +0x00, 0xDA, 0x01, 0xDA, 0x02, 0xDA, 0x03, 0xDA, 0x10, 0x4A, 0x63, 0xEA, 0xF9, 0x61, 0x00, 0x65, +0x10, 0xF0, 0x30, 0x68, 0xE0, 0xF2, 0x00, 0x48, 0xB8, 0x65, 0x00, 0x65, 0x10, 0xF0, 0x30, 0x68, +0xE0, 0xF5, 0x08, 0x48, 0xB8, 0x65, 0x00, 0x68, 0xA8, 0xB9, 0x0C, 0xB8, 0x00, 0x65, 0x1F, 0xF7, +0x01, 0x69, 0x2D, 0xE8, 0xDF, 0xF7, 0x20, 0x69, 0xFF, 0x49, 0x2C, 0xE8, 0x88, 0xB9, 0x00, 0x65, +0x10, 0xF0, 0x20, 0x68, 0x40, 0xF5, 0x05, 0x48, 0x00, 0xE8, 0x00, 0x65, 0x20, 0xBA, 0x00, 0x65, +0xF9, 0x63, 0x0D, 0x62, 0x0C, 0xD1, 0x04, 0x01, 0x8A, 0xD9, 0xAB, 0xD9, 0xCC, 0xD9, 0xED, 0xD9, +0x6A, 0x99, 0x1F, 0xF7, 0x00, 0x6A, 0x6C, 0xEA, 0x43, 0x32, 0x45, 0xD9, 0x6D, 0x99, 0x1F, 0xF7, +0x00, 0x6A, 0x6C, 0xEA, 0x43, 0x32, 0x44, 0xD9, 0x6A, 0x99, 0x7C, 0x6A, 0x6C, 0xEA, 0x4B, 0x32, +0x43, 0xD9, 0x64, 0x99, 0x45, 0x99, 0x83, 0x67, 0xA2, 0x67, 0x00, 0x18, 0x3A, 0x01, 0xB9, 0x65, +0x09, 0x97, 0x08, 0x91, 0x05, 0x63, 0x00, 0xEF, 0xFB, 0x63, 0x09, 0x62, 0x08, 0xD1, 0x04, 0x01, +0x86, 0xD9, 0xA7, 0xD9, 0x66, 0x99, 0x47, 0x99, 0x6C, 0xEA, 0x43, 0xD9, 0x63, 0x99, 0x80, 0x6A, +0x6C, 0xEA, 0x02, 0x22, 0x00, 0x18, 0xCD, 0x02, 0x63, 0x99, 0x40, 0x6A, 0x6C, 0xEA, 0x02, 0x22, +0x00, 0x18, 0x99, 0x03, 0x63, 0x99, 0x20, 0x6A, 0x6C, 0xEA, 0x02, 0x22, 0x00, 0x18, 0xA0, 0x03, +0x63, 0x99, 0x10, 0x6A, 0x6C, 0xEA, 0x02, 0x22, 0x00, 0x18, 0x06, 0x03, 0x63, 0x99, 0x08, 0x6A, +0x6C, 0xEA, 0x02, 0x22, 0x00, 0x18, 0x21, 0x04, 0xB9, 0x65, 0x05, 0x97, 0x04, 0x91, 0x03, 0x63, +0x00, 0xEF, 0x00, 0x65, 0xFB, 0x63, 0x09, 0x62, 0x08, 0xD1, 0x04, 0x01, 0x20, 0x6A, 0x49, 0xC1, +0x00, 0x6A, 0x48, 0xC1, 0x60, 0x6C, 0x00, 0x18, 0x73, 0x02, 0x00, 0x18, 0x7E, 0x01, 0x00, 0x18, +0x6E, 0x01, 0x00, 0x18, 0x92, 0x01, 0x00, 0x18, 0x5E, 0x01, 0x00, 0x18, 0x66, 0x01, 0x0A, 0x6C, +0x00, 0x18, 0xFD, 0x06, 0xFF, 0x17, 0x00, 0x65, 0xFF, 0x63, 0x01, 0xD1, 0x3D, 0x67, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xA0, 0xF0, 0x48, 0x9A, 0x00, 0x6B, 0x60, 0xCA, 0xB9, 0x65, +0x01, 0x91, 0x01, 0x63, 0x20, 0xE8, 0x00, 0x65, 0xFF, 0x63, 0x01, 0xD1, 0x3D, 0x67, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xA0, 0xF0, 0x4C, 0x9A, 0x00, 0xF4, 0x00, 0x6B, 0x60, 0xDA, +0xB9, 0x65, 0x01, 0x91, 0x01, 0x63, 0x20, 0xE8, 0xFF, 0x63, 0x01, 0xD1, 0x3D, 0x67, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x12, 0xF0, 0x01, 0x6B, 0x00, 0xF6, 0x64, 0xDA, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xA0, 0xF0, 0x50, 0x9A, 0x04, 0x6B, 0x60, 0xDA, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xA0, 0xF0, 0x54, 0x9A, 0x04, 0x6B, 0x60, 0xDA, 0xB9, 0x65, +0x01, 0x91, 0x01, 0x63, 0x20, 0xE8, 0x00, 0x65, 0xFF, 0x63, 0x01, 0xD1, 0x3D, 0x67, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xA0, 0xF0, 0x58, 0x9A, 0x01, 0x6B, 0x60, 0xDA, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xA0, 0xF0, 0x5C, 0x9A, 0x07, 0x6B, 0x60, 0xDA, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF0, 0x40, 0x9A, 0xFF, 0x6B, 0x60, 0xDA, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF0, 0x44, 0x9A, 0x00, 0x6B, 0x60, 0xDA, 0xB9, 0x65, +0x01, 0x91, 0x01, 0x63, 0x20, 0xE8, 0x00, 0x65, 0xFD, 0x63, 0x05, 0xD1, 0x3D, 0x67, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF0, 0x48, 0x9A, 0x10, 0xF0, 0x10, 0x6B, 0x60, 0x33, +0x60, 0x33, 0xC0, 0xF0, 0x6C, 0x9B, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0xC0, 0xF0, 0x50, 0x9A, 0x40, 0x9A, 0x42, 0xD9, 0x62, 0x99, 0x7E, 0x6A, 0x6D, 0xEA, 0x42, 0xD9, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF0, 0x50, 0x9A, 0x62, 0x99, 0x60, 0xDA, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF0, 0x54, 0x9A, 0x40, 0x9A, 0x42, 0xD9, +0x62, 0x99, 0x00, 0xF2, 0x01, 0x6A, 0x6D, 0xEA, 0x42, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0xC0, 0xF0, 0x54, 0x9A, 0x62, 0x99, 0x60, 0xDA, 0x62, 0x99, 0x00, 0xF4, 0x03, 0x6A, +0x4B, 0xEA, 0x6C, 0xEA, 0x42, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF0, +0x54, 0x9A, 0x62, 0x99, 0x60, 0xDA, 0x62, 0x99, 0x00, 0xF4, 0x02, 0x6A, 0x6D, 0xEA, 0x42, 0xD9, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF0, 0x54, 0x9A, 0x62, 0x99, 0x60, 0xDA, +0x00, 0x6A, 0x41, 0xD9, 0x1D, 0x10, 0x00, 0x6A, 0x40, 0xD9, 0x03, 0x10, 0x40, 0x99, 0x01, 0x4A, +0x40, 0xD9, 0x40, 0x99, 0x64, 0x5A, 0x58, 0x67, 0xF9, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0xC0, 0xF0, 0x58, 0x9A, 0x40, 0x9A, 0x42, 0xD9, 0x62, 0x99, 0xA0, 0x6A, 0x6C, 0xEA, +0x42, 0xD9, 0x42, 0x99, 0xA0, 0x6B, 0x6E, 0xEA, 0x08, 0x22, 0x41, 0x99, 0x01, 0x4A, 0x41, 0xD9, +0x41, 0x99, 0x0A, 0x5A, 0x58, 0x67, 0xDF, 0x2A, 0x01, 0x10, 0x00, 0x65, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0xC0, 0xF0, 0x48, 0x9A, 0x01, 0x6B, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0xC0, 0xF0, 0x5C, 0x9A, 0x10, 0xF0, 0x10, 0x6B, 0x60, 0x33, 0x60, 0x33, +0xE0, 0xF0, 0x60, 0x9B, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xE0, 0xF0, +0x44, 0x9A, 0x24, 0x6B, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xE0, 0xF0, +0x48, 0x9A, 0x40, 0x9A, 0x42, 0xD9, 0x62, 0x99, 0x01, 0x6A, 0x6D, 0xEA, 0x42, 0xD9, 0x62, 0x99, +0x0A, 0x6A, 0x6D, 0xEA, 0x42, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xE0, 0xF0, +0x48, 0x9A, 0x62, 0x99, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xE0, 0xF0, +0x4C, 0x9A, 0x40, 0x9A, 0x42, 0xD9, 0x62, 0x99, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0xE0, 0xF0, 0x50, 0x9A, 0x6C, 0xEA, 0x42, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0xE0, 0xF0, 0x4C, 0x9A, 0x62, 0x99, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0xE0, 0xF0, 0x54, 0x9A, 0x40, 0x9A, 0x42, 0xD9, 0x62, 0x99, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0xE0, 0xF0, 0x58, 0x9A, 0x6C, 0xEA, 0x42, 0xD9, 0x62, 0x99, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0xE0, 0xF0, 0x5C, 0x9A, 0x6D, 0xEA, 0x42, 0xD9, 0x62, 0x99, 0x04, 0xF0, +0x01, 0x6A, 0x4B, 0xEA, 0x6C, 0xEA, 0x42, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0xE0, 0xF0, 0x54, 0x9A, 0x62, 0x99, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0xE0, 0xF0, 0x54, 0x9A, 0x40, 0x9A, 0x42, 0xD9, 0x62, 0x99, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x00, 0xF1, 0x40, 0x9A, 0x6D, 0xEA, 0x42, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0xE0, 0xF0, 0x54, 0x9A, 0x62, 0x99, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0xC0, 0xF0, 0x50, 0x9A, 0x40, 0x9A, 0x42, 0xD9, 0x62, 0x99, 0x80, 0xF7, 0x00, 0x6A, +0x6D, 0xEA, 0x42, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF0, 0x50, 0x9A, +0x62, 0x99, 0x60, 0xDA, 0x62, 0x99, 0x01, 0xF0, 0x00, 0x6A, 0x6D, 0xEA, 0x42, 0xD9, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF0, 0x50, 0x9A, 0x62, 0x99, 0x60, 0xDA, 0x62, 0x99, +0x01, 0xF0, 0x01, 0x6A, 0x4B, 0xEA, 0x6C, 0xEA, 0x42, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0xC0, 0xF0, 0x50, 0x9A, 0x62, 0x99, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x00, 0xF1, 0x44, 0x9A, 0x40, 0x9A, 0x42, 0xD9, 0x62, 0x99, 0x09, 0x6A, 0x6D, 0xEA, +0x42, 0xD9, 0x62, 0x99, 0x03, 0x6A, 0x4B, 0xEA, 0x6C, 0xEA, 0x42, 0xD9, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x00, 0xF1, 0x44, 0x9A, 0x62, 0x99, 0x60, 0xDA, 0x62, 0x99, 0x10, 0x6A, +0x6D, 0xEA, 0x42, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF1, 0x44, 0x9A, +0x62, 0x99, 0x60, 0xDA, 0x62, 0x99, 0x11, 0x6A, 0x4B, 0xEA, 0x6C, 0xEA, 0x42, 0xD9, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF1, 0x44, 0x9A, 0x62, 0x99, 0x60, 0xDA, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF1, 0x48, 0x9A, 0x40, 0x9A, 0x42, 0xD9, 0x62, 0x99, +0xFF, 0x6A, 0x01, 0x4A, 0x6D, 0xEA, 0x42, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x00, 0xF1, 0x48, 0x9A, 0x62, 0x99, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0xC0, 0xF0, 0x50, 0x9A, 0x40, 0x9A, 0x42, 0xD9, 0x62, 0x99, 0x7F, 0x6A, 0x4B, 0xEA, 0x6C, 0xEA, +0x42, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF0, 0x50, 0x9A, 0x62, 0x99, +0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF0, 0x50, 0x9A, 0x40, 0x9A, +0x42, 0xD9, 0x62, 0x99, 0x10, 0x6A, 0x6D, 0xEA, 0x42, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0xC0, 0xF0, 0x50, 0x9A, 0x62, 0x99, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x00, 0xF1, 0x4C, 0x9A, 0x40, 0x9A, 0x42, 0xD9, 0x62, 0x99, 0x07, 0x6A, 0x6D, 0xEA, +0x42, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF1, 0x4C, 0x9A, 0x62, 0x99, +0x60, 0xDA, 0xB9, 0x65, 0x05, 0x91, 0x03, 0x63, 0x20, 0xE8, 0x00, 0x65, 0xFC, 0x63, 0x07, 0xD1, +0x3D, 0x67, 0x44, 0x67, 0x20, 0xF0, 0x40, 0xC1, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x00, 0xF1, 0x50, 0x9A, 0x00, 0x6B, 0x60, 0xDA, 0x82, 0x6A, 0x44, 0xD9, 0x64, 0x99, 0xFF, 0x6A, +0x6C, 0xEA, 0x42, 0xD9, 0x64, 0x99, 0x1F, 0xF7, 0x00, 0x6A, 0x6C, 0xEA, 0x42, 0x32, 0x43, 0xD9, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF1, 0x54, 0x9A, 0x80, 0x6B, 0x60, 0xDA, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF1, 0x58, 0x9A, 0x62, 0x99, 0x60, 0xDA, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF1, 0x50, 0x9A, 0x63, 0x99, 0x60, 0xDA, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF1, 0x54, 0x9A, 0x03, 0x6B, 0x60, 0xDA, +0xB9, 0x65, 0x07, 0x91, 0x04, 0x63, 0x20, 0xE8, 0xFE, 0x63, 0x03, 0xD1, 0x3D, 0x67, 0x00, 0x6A, +0x41, 0xC1, 0x26, 0x10, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF1, 0x5C, 0x9A, +0x40, 0x9A, 0x62, 0x67, 0x01, 0x6A, 0x4C, 0xEB, 0xFF, 0x6A, 0x6C, 0xEA, 0x0C, 0x22, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF1, 0x58, 0x9A, 0x40, 0x9A, 0x00, 0xF6, 0x40, 0x32, +0x00, 0xF6, 0x43, 0x32, 0x13, 0x10, 0x00, 0x6A, 0x40, 0xC1, 0x03, 0x10, 0x40, 0xA1, 0x01, 0x4A, +0x40, 0xC1, 0x40, 0xA1, 0x0A, 0x5A, 0x58, 0x67, 0xF9, 0x2A, 0x41, 0xA1, 0x01, 0x4A, 0x41, 0xC1, +0x41, 0xA1, 0x64, 0x5A, 0x58, 0x67, 0xD6, 0x2A, 0x01, 0x6A, 0x4B, 0xEA, 0xB9, 0x65, 0x03, 0x91, +0x02, 0x63, 0x20, 0xE8, 0xFE, 0x63, 0x03, 0xD1, 0x3D, 0x67, 0x44, 0x67, 0x50, 0xC1, 0x00, 0x6A, +0x41, 0xC9, 0x2C, 0x10, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF1, 0x5C, 0x9A, +0x60, 0x9A, 0x20, 0x6A, 0x6C, 0xEA, 0x14, 0x22, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x00, 0xF1, 0x58, 0x9A, 0x70, 0xA1, 0x60, 0xDA, 0x00, 0x6A, 0x40, 0xC9, 0x03, 0x10, 0x40, 0xA9, +0x01, 0x4A, 0x40, 0xC9, 0x40, 0x89, 0x00, 0x52, 0x58, 0x67, 0xF9, 0x22, 0x00, 0x6A, 0x15, 0x10, +0x00, 0x6A, 0x40, 0xC9, 0x03, 0x10, 0x40, 0xA9, 0x01, 0x4A, 0x40, 0xC9, 0x40, 0xA9, 0xE0, 0xF3, +0x08, 0x5A, 0x58, 0x67, 0xF8, 0x2A, 0x41, 0xA9, 0x01, 0x4A, 0x41, 0xC9, 0x41, 0xA9, 0x02, 0xF0, +0x00, 0x5A, 0x58, 0x67, 0xCF, 0x2A, 0x01, 0x6A, 0x4B, 0xEA, 0xB9, 0x65, 0x03, 0x91, 0x02, 0x63, +0x20, 0xE8, 0x00, 0x65, 0xFD, 0x63, 0x05, 0xD1, 0x3D, 0x67, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x20, 0xF1, 0x40, 0x9A, 0x40, 0x9A, 0x42, 0xD9, 0x42, 0x99, 0x01, 0x6B, 0x6E, 0xEA, +0x20, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xA0, 0xF0, 0x50, 0x9A, 0x04, 0x6B, +0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x20, 0xF1, 0x44, 0x9A, 0x40, 0x9A, +0x42, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x12, 0xF0, 0x01, 0x6B, 0x00, 0xF6, +0x64, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xA0, 0xF0, 0x50, 0x9A, 0x03, 0x6B, +0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x20, 0xF1, 0x48, 0x9A, 0x40, 0x9A, +0x42, 0xD9, 0x42, 0x99, 0x01, 0x6B, 0x6E, 0xEA, 0x33, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x20, 0xF1, 0x4C, 0x9A, 0x40, 0x9A, 0x42, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x20, 0xF1, 0x50, 0x9A, 0x40, 0x9A, 0x40, 0xD9, 0x60, 0x99, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x20, 0xF1, 0x54, 0x9A, 0x6D, 0xEA, 0x40, 0xD9, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x20, 0xF1, 0x50, 0x9A, 0x60, 0x99, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x60, 0xF6, 0x5C, 0x9A, 0x2E, 0xF5, 0x10, 0x5A, 0x58, 0x67, 0x08, 0x22, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xA0, 0xF0, 0x54, 0x9A, 0x03, 0x6B, 0x60, 0xDA, +0xB9, 0x65, 0x05, 0x91, 0x03, 0x63, 0x20, 0xE8, 0xF8, 0x63, 0x0F, 0x62, 0x0E, 0xD1, 0x04, 0x01, +0x00, 0xF3, 0x00, 0x6A, 0x49, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF0, +0x00, 0x4A, 0x40, 0xD9, 0x47, 0x41, 0x1D, 0x4A, 0x42, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0xA0, 0xF0, 0x4C, 0x9A, 0x40, 0x9A, 0x47, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0xA0, 0xF0, 0x4C, 0x9A, 0x00, 0x6B, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x20, 0xF1, 0x58, 0x9A, 0x40, 0x9A, 0x48, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x20, 0xF1, 0x5C, 0x9A, 0x40, 0x9A, 0x46, 0xD9, 0x66, 0x99, 0x80, 0x6A, 0x6D, 0xEA, +0x46, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x20, 0xF1, 0x5C, 0x9A, 0x66, 0x99, +0x60, 0xDA, 0x68, 0x99, 0x01, 0xF0, 0x00, 0x6A, 0x6C, 0xEA, 0x1B, 0x22, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x40, 0xF1, 0x40, 0x9A, 0x88, 0x99, 0x10, 0xF0, 0x10, 0x6B, 0x60, 0x33, +0x60, 0x33, 0x00, 0xF1, 0x60, 0x9B, 0x6D, 0xE4, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x40, 0xF1, 0x44, 0x9A, 0x40, 0x9A, 0x46, 0xD9, 0x66, 0x99, 0x0F, 0x6A, 0x6C, 0xEA, +0x44, 0xD9, 0x68, 0x99, 0x00, 0xF4, 0x00, 0x6A, 0x6C, 0xEA, 0x80, 0xF0, 0x1F, 0x22, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF1, 0x44, 0x9A, 0x40, 0x9A, 0x46, 0xD9, 0x66, 0x99, +0x40, 0x6A, 0x6C, 0xEA, 0x80, 0xF0, 0x0D, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x40, 0xF1, 0x48, 0x9A, 0x40, 0x9A, 0x49, 0xD9, 0x42, 0x99, 0x60, 0xA2, 0x20, 0x6A, 0x4B, 0xEA, +0x6C, 0xEA, 0x46, 0xC1, 0x46, 0xA1, 0x56, 0x32, 0x46, 0xC1, 0x42, 0x99, 0x02, 0x4A, 0x40, 0xA2, +0x45, 0xC1, 0x46, 0xA1, 0x7B, 0x22, 0x42, 0x99, 0x02, 0x4A, 0x40, 0xA2, 0x45, 0xC1, 0x42, 0x99, +0x40, 0xA2, 0x62, 0x67, 0x1F, 0x6A, 0x6C, 0xEA, 0x02, 0x6B, 0x4E, 0xEB, 0x2F, 0x23, 0x03, 0x52, +0x78, 0x67, 0x02, 0x23, 0x20, 0x22, 0x6A, 0x10, 0x03, 0x6B, 0x4E, 0xEB, 0x31, 0x23, 0x04, 0x6B, +0x6E, 0xEA, 0x64, 0x2A, 0x42, 0x99, 0x02, 0x4A, 0x40, 0xA2, 0x07, 0x2A, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x00, 0x6B, 0x80, 0xF6, 0x64, 0xC2, 0x42, 0x99, 0x02, 0x4A, 0x40, 0xA2, +0x01, 0x6B, 0x6E, 0xEA, 0x50, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x01, 0x6B, +0x80, 0xF6, 0x64, 0xC2, 0x4B, 0x10, 0x42, 0x99, 0x01, 0x4A, 0x40, 0xA2, 0x62, 0x67, 0x45, 0xA1, +0x00, 0x6C, 0xA3, 0x67, 0xC2, 0x67, 0x00, 0x18, 0x5B, 0x0E, 0x40, 0x10, 0x42, 0x99, 0x01, 0x4A, +0x40, 0xA2, 0x62, 0x67, 0x45, 0xA1, 0x02, 0x6C, 0xA3, 0x67, 0xC2, 0x67, 0x00, 0x18, 0x5B, 0x0E, +0x46, 0xA1, 0x05, 0x6B, 0x6E, 0xEA, 0x1C, 0x2A, 0x45, 0xA1, 0x26, 0x5A, 0x58, 0x67, 0x2D, 0x22, +0x00, 0x6A, 0x45, 0xD9, 0x11, 0x10, 0x65, 0xA1, 0x45, 0x99, 0x49, 0xE3, 0x48, 0x32, 0x60, 0x99, +0x49, 0xE3, 0x10, 0xF0, 0x10, 0x6B, 0x60, 0x33, 0x60, 0x33, 0x40, 0xF1, 0x68, 0x9B, 0x60, 0x9B, +0x60, 0xDA, 0x45, 0x99, 0x01, 0x4A, 0x45, 0xD9, 0x45, 0x99, 0x04, 0x5A, 0x58, 0x67, 0xEB, 0x2A, +0x46, 0xA1, 0x02, 0x6B, 0x6E, 0xEA, 0x12, 0x2A, 0x45, 0xA1, 0x48, 0x32, 0x60, 0x99, 0x49, 0xE3, +0x10, 0xF0, 0x10, 0x6B, 0x60, 0x33, 0x60, 0x33, 0x40, 0xF1, 0x68, 0x9B, 0x60, 0x9B, 0x60, 0xDA, +0x05, 0x10, 0x00, 0x65, 0x03, 0x10, 0x00, 0x65, 0x01, 0x10, 0x00, 0x65, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x20, 0xF1, 0x58, 0x9A, 0x68, 0x99, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x40, 0xF1, 0x40, 0x9A, 0x10, 0xF0, 0x10, 0x6B, 0x60, 0x33, 0x60, 0x33, +0x20, 0xF1, 0x78, 0x9B, 0x60, 0x9B, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0xA0, 0xF0, 0x4C, 0x9A, 0x67, 0x99, 0x60, 0xDA, 0xB9, 0x65, 0x0B, 0x97, 0x0A, 0x91, 0x06, 0x63, +0x00, 0xEF, 0x00, 0x65, 0xFF, 0x63, 0x01, 0xD1, 0x3D, 0x67, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x40, 0xF1, 0x4C, 0x9A, 0x40, 0x9A, 0xB9, 0x65, 0x01, 0x91, 0x01, 0x63, 0x20, 0xE8, +0xFD, 0x63, 0x05, 0xD1, 0x3D, 0x67, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF1, +0x50, 0x9A, 0x40, 0x9A, 0x42, 0xD9, 0x62, 0x99, 0x02, 0x6A, 0x4B, 0xEA, 0x6C, 0xEA, 0x42, 0xD9, +0x00, 0x6A, 0x41, 0xD9, 0x03, 0x10, 0x41, 0x99, 0x01, 0x4A, 0x41, 0xD9, 0x41, 0x99, 0x05, 0x5A, +0x58, 0x67, 0xF9, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF1, 0x50, 0x9A, +0x62, 0x99, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF1, 0x54, 0x9A, +0x40, 0x9A, 0x40, 0xD9, 0x00, 0x6A, 0x41, 0xD9, 0x03, 0x10, 0x41, 0x99, 0x01, 0x4A, 0x41, 0xD9, +0x41, 0x99, 0x05, 0x5A, 0x58, 0x67, 0xF9, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x40, 0xF1, 0x54, 0x9A, 0x80, 0x99, 0x10, 0xF0, 0x10, 0x6B, 0x60, 0x33, 0x60, 0x33, 0x40, 0xF1, +0x78, 0x9B, 0x8C, 0xEB, 0x60, 0xDA, 0x00, 0x6A, 0x41, 0xD9, 0x03, 0x10, 0x41, 0x99, 0x01, 0x4A, +0x41, 0xD9, 0x41, 0x99, 0x05, 0x5A, 0x58, 0x67, 0xF9, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x40, 0xF1, 0x5C, 0x9A, 0x40, 0x9A, 0x42, 0xD9, 0x00, 0x6A, 0x41, 0xD9, 0x03, 0x10, +0x41, 0x99, 0x01, 0x4A, 0x41, 0xD9, 0x41, 0x99, 0x05, 0x5A, 0x58, 0x67, 0xF9, 0x2A, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x60, 0xF1, 0x40, 0x9A, 0x40, 0x9A, 0x42, 0xD9, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF6, 0x0C, 0x4A, 0x02, 0x6B, 0x64, 0xCA, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x04, 0xF0, 0x00, 0x6B, 0x80, 0xF6, 0x6C, 0xDA, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xA0, 0xF0, 0x48, 0x9A, 0x00, 0x6B, 0x60, 0xCA, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x20, 0xF6, 0x04, 0x4A, 0x54, 0xA2, 0x61, 0x42, 0xFF, 0x6A, +0x4C, 0xEB, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x20, 0xF6, 0x04, 0x4A, 0x74, 0xC2, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF1, 0x5C, 0x9A, 0x40, 0x9A, 0x42, 0xD9, +0x00, 0x6A, 0x41, 0xD9, 0x03, 0x10, 0x41, 0x99, 0x01, 0x4A, 0x41, 0xD9, 0x41, 0x99, 0x32, 0x5A, +0x58, 0x67, 0xF9, 0x2A, 0x62, 0x99, 0x01, 0x6A, 0x6D, 0xEA, 0x42, 0xD9, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x40, 0xF1, 0x5C, 0x9A, 0x62, 0x99, 0x60, 0xDA, 0x00, 0x6A, 0x41, 0xD9, +0x03, 0x10, 0x41, 0x99, 0x01, 0x4A, 0x41, 0xD9, 0x41, 0x99, 0x32, 0x5A, 0x58, 0x67, 0xF9, 0x2A, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xE0, 0xF0, 0x48, 0x9A, 0x40, 0x9A, 0x42, 0xD9, +0x00, 0x6A, 0x41, 0xD9, 0x03, 0x10, 0x41, 0x99, 0x01, 0x4A, 0x41, 0xD9, 0x41, 0x99, 0x05, 0x5A, +0x58, 0x67, 0xF9, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xE0, 0xF0, 0x48, 0x9A, +0x82, 0x99, 0x02, 0x6B, 0x6B, 0xEB, 0x8C, 0xEB, 0x60, 0xDA, 0x00, 0x6A, 0x41, 0xD9, 0x03, 0x10, +0x41, 0x99, 0x01, 0x4A, 0x41, 0xD9, 0x41, 0x99, 0x05, 0x5A, 0x58, 0x67, 0xF9, 0x2A, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF1, 0x50, 0x9A, 0x40, 0x9A, 0x42, 0xD9, 0x00, 0x6A, +0x41, 0xD9, 0x03, 0x10, 0x41, 0x99, 0x01, 0x4A, 0x41, 0xD9, 0x41, 0x99, 0x05, 0x5A, 0x58, 0x67, +0xF9, 0x2A, 0x62, 0x99, 0x01, 0x6A, 0x6D, 0xEA, 0x42, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x40, 0xF1, 0x50, 0x9A, 0x62, 0x99, 0x60, 0xDA, 0xB9, 0x65, 0x05, 0x91, 0x03, 0x63, +0x20, 0xE8, 0x00, 0x65, 0xFD, 0x63, 0x05, 0xD1, 0x3D, 0x67, 0x00, 0x6A, 0x4E, 0xC1, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF6, 0x00, 0x4A, 0x41, 0xD9, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x60, 0xF1, 0x44, 0x9A, 0x40, 0xAA, 0x46, 0xC9, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x60, 0xF1, 0x44, 0x9A, 0x00, 0x6B, 0x60, 0xCA, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x60, 0xF1, 0x48, 0x9A, 0x40, 0xAA, 0x45, 0xC9, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x60, 0xF1, 0x48, 0x9A, 0x65, 0xA9, 0x60, 0xCA, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x20, 0xF6, 0x04, 0x4A, 0x50, 0xA2, 0x61, 0x42, 0xFF, 0x6A, 0x4C, 0xEB, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x20, 0xF6, 0x04, 0x4A, 0x70, 0xC2, 0x65, 0xA9, +0x08, 0x6A, 0x6C, 0xEA, 0x43, 0x22, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x12, 0xF0, +0x04, 0x6B, 0x20, 0xF6, 0x64, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x60, 0xF1, +0x4C, 0x9A, 0x01, 0x6B, 0x60, 0xC2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x20, 0xF6, +0x04, 0x4A, 0x52, 0xA2, 0x61, 0x42, 0xFF, 0x6A, 0x4C, 0xEB, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x20, 0xF6, 0x04, 0x4A, 0x72, 0xC2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0xC0, 0xF2, 0x48, 0x9A, 0x01, 0x6B, 0x6E, 0xEA, 0x08, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0xE0, 0xF0, 0x48, 0x9A, 0x0B, 0x6B, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0xC0, 0xF2, 0x48, 0x9A, 0x02, 0x6B, 0x6E, 0xEA, 0x08, 0x2A, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x60, 0xF1, 0x50, 0x9A, 0x00, 0x6B, 0x60, 0xDA, 0x65, 0xA9, 0x01, 0x6A, +0x4C, 0xEB, 0xFF, 0x6A, 0x6C, 0xEA, 0xE0, 0xF0, 0x0B, 0x22, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x20, 0xF6, 0x04, 0x4A, 0x51, 0xA2, 0x61, 0x42, 0xFF, 0x6A, 0x4C, 0xEB, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x20, 0xF6, 0x04, 0x4A, 0x71, 0xC2, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x60, 0xF1, 0x54, 0x9A, 0x60, 0xAA, 0xFF, 0xF7, 0x1F, 0x6A, 0x4C, 0xEB, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x20, 0xF6, 0x04, 0x4A, 0x63, 0xCA, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x20, 0xF6, 0x04, 0x4A, 0x43, 0xAA, 0x62, 0x67, 0x1F, 0xF7, +0x00, 0x6A, 0x6C, 0xEA, 0x27, 0x22, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x20, 0xF6, +0x04, 0x4A, 0x43, 0xAA, 0x42, 0x33, 0xFF, 0xF7, 0x1F, 0x6A, 0x4C, 0xEB, 0xFF, 0x6A, 0x4C, 0xEB, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x20, 0xF6, 0x04, 0x4A, 0x69, 0xC2, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x20, 0xF6, 0x04, 0x4A, 0x43, 0xAA, 0xFF, 0x6B, 0x6C, 0xEA, +0x10, 0xF0, 0x10, 0x6B, 0x60, 0x33, 0x60, 0x33, 0x20, 0xF6, 0x04, 0x4B, 0x43, 0xCB, 0x01, 0x6A, +0x4E, 0xC1, 0x0A, 0x10, 0x00, 0x6A, 0x4E, 0xC1, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x20, 0xF6, 0x04, 0x4A, 0x00, 0x6B, 0x69, 0xC2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x20, 0xF6, 0x04, 0x4A, 0x43, 0xAA, 0x0B, 0x5A, 0x58, 0x67, 0x3F, 0x2A, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x60, 0xF1, 0x4C, 0x9A, 0x01, 0x6B, 0x60, 0xC2, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x40, 0xF1, 0x40, 0x9A, 0x10, 0xF0, 0x10, 0x6B, 0x60, 0x33, 0x60, 0x33, +0x20, 0xF6, 0x04, 0x4B, 0x63, 0xAB, 0x83, 0x67, 0x10, 0xF0, 0x10, 0x6B, 0x60, 0x33, 0x60, 0x33, +0x60, 0xF1, 0x78, 0x9B, 0x6D, 0xE4, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x20, 0xF6, 0x04, 0x4A, 0x00, 0x6B, 0x63, 0xCA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x01, 0x6B, 0x6B, 0xEB, 0x40, 0xF6, 0x60, 0xC2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x04, 0xF0, 0x00, 0x6B, 0x80, 0xF6, 0x6C, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0xA0, 0xF0, 0x48, 0x9A, 0x01, 0x6B, 0x60, 0xCA, 0x43, 0x10, 0x00, 0x6A, 0x4F, 0xC1, 0x0F, 0x10, +0x4F, 0xA1, 0x48, 0x32, 0x61, 0x99, 0x49, 0xE3, 0x10, 0xF0, 0x10, 0x6B, 0x60, 0x33, 0x60, 0x33, +0x60, 0xF1, 0x7C, 0x9B, 0x60, 0x9B, 0x60, 0xDA, 0x4F, 0xA1, 0x01, 0x4A, 0x4F, 0xC1, 0x8F, 0xA1, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x20, 0xF6, 0x04, 0x4A, 0x43, 0xAA, 0x62, 0x67, +0x4E, 0xA1, 0x49, 0xE3, 0x03, 0x4A, 0x00, 0x52, 0x78, 0x67, 0x01, 0x23, 0x03, 0x4A, 0x4B, 0x32, +0x42, 0xEC, 0x58, 0x67, 0xDD, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF6, +0x60, 0xA2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x20, 0xF6, 0x04, 0x4A, 0x73, 0xC2, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x60, 0xF1, 0x4C, 0x9A, 0x01, 0x6B, 0x60, 0xC2, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x12, 0xF0, 0x03, 0x6B, 0x20, 0xF6, 0x64, 0xDA, +0x65, 0xA9, 0x02, 0x6A, 0x6C, 0xEA, 0x11, 0x22, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x20, 0xF6, 0x04, 0x4A, 0x4C, 0xA2, 0x61, 0x42, 0xFF, 0x6A, 0x4C, 0xEB, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x20, 0xF6, 0x04, 0x4A, 0x6C, 0xC2, 0x65, 0xA9, 0x04, 0x6A, 0x6C, 0xEA, +0x11, 0x22, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x20, 0xF6, 0x04, 0x4A, 0x4D, 0xA2, +0x61, 0x42, 0xFF, 0x6A, 0x4C, 0xEB, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x20, 0xF6, +0x04, 0x4A, 0x6D, 0xC2, 0x65, 0xA9, 0x00, 0xF2, 0x00, 0x6A, 0x6C, 0xEA, 0x11, 0x22, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x20, 0xF6, 0x04, 0x4A, 0x4F, 0xA2, 0x61, 0x42, 0xFF, 0x6A, +0x4C, 0xEB, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x20, 0xF6, 0x04, 0x4A, 0x6F, 0xC2, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x60, 0xF1, 0x44, 0x9A, 0x66, 0xA9, 0x60, 0xCA, +0xB9, 0x65, 0x05, 0x91, 0x03, 0x63, 0x20, 0xE8, 0xFF, 0x63, 0x01, 0xD1, 0x3D, 0x67, 0x82, 0xD9, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF1, 0x40, 0x9A, 0x62, 0x99, 0x60, 0xDA, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xA0, 0xF0, 0x50, 0x9A, 0x03, 0x6B, 0x60, 0xDA, +0xB9, 0x65, 0x01, 0x91, 0x01, 0x63, 0x20, 0xE8, 0xFF, 0x63, 0x01, 0xD1, 0x3D, 0x67, 0x82, 0xD9, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF1, 0x44, 0x9A, 0x62, 0x99, 0x60, 0xDA, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xA0, 0xF0, 0x54, 0x9A, 0x03, 0x6B, 0x60, 0xDA, +0xB9, 0x65, 0x01, 0x91, 0x01, 0x63, 0x20, 0xE8, 0xFF, 0x63, 0x01, 0xD1, 0x3D, 0x67, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xA0, 0xF0, 0x50, 0x9A, 0x04, 0x6B, 0x60, 0xDA, 0xB9, 0x65, +0x01, 0x91, 0x01, 0x63, 0x20, 0xE8, 0x00, 0x65, 0xFF, 0x63, 0x01, 0xD1, 0x3D, 0x67, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xA0, 0xF0, 0x54, 0x9A, 0x04, 0x6B, 0x60, 0xDA, 0xB9, 0x65, +0x01, 0x91, 0x01, 0x63, 0x20, 0xE8, 0x00, 0x65, 0xFE, 0x63, 0x03, 0xD1, 0x3D, 0x67, 0x84, 0xD9, +0xA5, 0xD9, 0xC6, 0xD9, 0x64, 0x99, 0x46, 0x99, 0x49, 0xE3, 0x40, 0xD9, 0x0A, 0x10, 0x44, 0x99, +0x65, 0x99, 0x60, 0xA3, 0x60, 0xC2, 0x44, 0x99, 0x01, 0x4A, 0x44, 0xD9, 0x45, 0x99, 0x01, 0x4A, +0x45, 0xD9, 0x65, 0x99, 0x40, 0x99, 0x43, 0xEB, 0x58, 0x67, 0xF1, 0x2A, 0x44, 0x99, 0xB9, 0x65, +0x03, 0x91, 0x02, 0x63, 0x20, 0xE8, 0x00, 0x65, 0xFE, 0x63, 0x03, 0xD1, 0x3D, 0x67, 0x84, 0xD9, +0xA5, 0xD9, 0x64, 0x99, 0x45, 0x99, 0x49, 0xE3, 0x40, 0xD9, 0x06, 0x10, 0x44, 0x99, 0x00, 0x6B, +0x60, 0xC2, 0x44, 0x99, 0x01, 0x4A, 0x44, 0xD9, 0x64, 0x99, 0x40, 0x99, 0x43, 0xEB, 0x58, 0x67, +0xF5, 0x2A, 0x44, 0x99, 0xB9, 0x65, 0x03, 0x91, 0x02, 0x63, 0x20, 0xE8, 0xFE, 0x63, 0x03, 0xD1, +0x3D, 0x67, 0x84, 0xD9, 0xA5, 0xD9, 0xC6, 0xD9, 0x00, 0x6A, 0x40, 0xD9, 0x0F, 0x10, 0x64, 0x99, +0x40, 0x99, 0x49, 0xE3, 0x60, 0xA2, 0x85, 0x99, 0x40, 0x99, 0x49, 0xE4, 0x40, 0xA2, 0x6E, 0xEA, +0x02, 0x22, 0x00, 0x6A, 0x09, 0x10, 0x40, 0x99, 0x01, 0x4A, 0x40, 0xD9, 0x60, 0x99, 0x46, 0x99, +0x43, 0xEB, 0x58, 0x67, 0xEC, 0x2A, 0x01, 0x6A, 0xB9, 0x65, 0x03, 0x91, 0x02, 0x63, 0x20, 0xE8, +0xFF, 0x63, 0x01, 0xD1, 0x3D, 0x67, 0x44, 0x67, 0xA3, 0xD9, 0x48, 0xC1, 0x43, 0x99, 0x60, 0xAA, +0xFF, 0x6A, 0x4C, 0xEB, 0x48, 0xA1, 0x6E, 0xEA, 0x48, 0xC1, 0x48, 0xA1, 0x50, 0x32, 0x00, 0xF6, +0x40, 0x33, 0x00, 0xF6, 0x63, 0x33, 0x48, 0x81, 0x6E, 0xEA, 0x00, 0xF6, 0x40, 0x32, 0x00, 0xF6, +0x43, 0x32, 0x48, 0xC1, 0x43, 0x99, 0x40, 0xAA, 0x42, 0x33, 0xFF, 0xF7, 0x1F, 0x6A, 0x6C, 0xEA, +0x40, 0x33, 0x60, 0x33, 0x63, 0x33, 0x63, 0x33, 0x48, 0xA1, 0x40, 0x32, 0x40, 0x32, 0x40, 0x32, +0x43, 0x32, 0x43, 0x32, 0x6E, 0xEA, 0x40, 0x33, 0x60, 0x33, 0x63, 0x33, 0x63, 0x33, 0x48, 0xA1, +0x4C, 0x32, 0x40, 0x32, 0x40, 0x32, 0x43, 0x32, 0x43, 0x32, 0x6E, 0xEA, 0x40, 0x33, 0x60, 0x33, +0x63, 0x33, 0x63, 0x33, 0x48, 0xA1, 0x52, 0x34, 0xFF, 0x6A, 0x8C, 0xEA, 0x6E, 0xEA, 0x40, 0x33, +0x60, 0x33, 0x63, 0x33, 0x63, 0x33, 0xFF, 0xF7, 0x1F, 0x6A, 0x4C, 0xEB, 0x43, 0x99, 0x60, 0xCA, +0x43, 0x99, 0x40, 0xAA, 0xB9, 0x65, 0x01, 0x91, 0x01, 0x63, 0x20, 0xE8, 0xFC, 0x63, 0x07, 0x62, +0x06, 0xD1, 0x04, 0x01, 0x84, 0xD9, 0xA5, 0xD9, 0xC6, 0xD9, 0xE7, 0xD9, 0x44, 0x99, 0x01, 0x6B, +0x4E, 0xEB, 0x04, 0x23, 0x02, 0x6B, 0x6E, 0xEA, 0x05, 0x22, 0x32, 0x10, 0x6C, 0xF3, 0x03, 0x6A, +0x41, 0xC9, 0x04, 0x10, 0x01, 0x6A, 0x4B, 0xEA, 0x41, 0xC9, 0x00, 0x65, 0x45, 0x99, 0x40, 0x82, +0x40, 0xC1, 0x45, 0x99, 0x01, 0x4A, 0x45, 0xD9, 0x60, 0xA1, 0x42, 0x41, 0x83, 0x67, 0xA2, 0x67, +0x00, 0x18, 0x58, 0x05, 0x46, 0x99, 0xFF, 0x4A, 0x46, 0xD9, 0x46, 0x99, 0xEF, 0x2A, 0x44, 0x99, +0x02, 0x6B, 0x6E, 0xEA, 0x06, 0x2A, 0x41, 0xA9, 0x4F, 0xEB, 0xFF, 0xF7, 0x1F, 0x6A, 0x6C, 0xEA, +0x41, 0xC9, 0x61, 0xA9, 0xFF, 0x6A, 0x4C, 0xEB, 0x47, 0x99, 0x60, 0xC2, 0x41, 0xA9, 0x42, 0x33, +0xFF, 0xF7, 0x1F, 0x6A, 0x4C, 0xEB, 0xFF, 0x6A, 0x4C, 0xEB, 0x48, 0x99, 0x60, 0xC2, 0x00, 0x65, +0xB9, 0x65, 0x03, 0x97, 0x02, 0x91, 0x02, 0x63, 0x00, 0xEF, 0x00, 0x65, 0xFB, 0x63, 0x09, 0x62, +0x08, 0xD1, 0x06, 0x01, 0x84, 0xD9, 0x65, 0x67, 0x46, 0x67, 0x74, 0xC1, 0x58, 0xC1, 0x58, 0xA1, +0x01, 0x6B, 0x6E, 0xEA, 0x0B, 0x2A, 0xA4, 0x99, 0x74, 0xA1, 0x43, 0x41, 0x84, 0x41, 0x04, 0xD4, +0x01, 0x6C, 0xC3, 0x67, 0xE2, 0x67, 0x00, 0x18, 0x7F, 0x05, 0x0A, 0x10, 0xA4, 0x99, 0x74, 0xA1, +0x43, 0x41, 0x84, 0x41, 0x04, 0xD4, 0x02, 0x6C, 0xC3, 0x67, 0xE2, 0x67, 0x00, 0x18, 0x7F, 0x05, +0x43, 0xA1, 0x40, 0xC9, 0x40, 0xA9, 0x40, 0x32, 0x40, 0xC9, 0x44, 0xA1, 0x62, 0x67, 0x40, 0xA9, +0x6D, 0xEA, 0x40, 0xC9, 0x40, 0xA9, 0xB9, 0x65, 0x03, 0x97, 0x02, 0x91, 0x02, 0x63, 0x00, 0xEF, +0xFD, 0x63, 0x05, 0xD1, 0x3D, 0x67, 0xB9, 0x65, 0x05, 0x91, 0x03, 0x63, 0x20, 0xE8, 0x00, 0x65, +0xFF, 0x63, 0x01, 0xD1, 0x3D, 0x67, 0xB9, 0x65, 0x01, 0x91, 0x01, 0x63, 0x20, 0xE8, 0x00, 0x65, +0xFF, 0x63, 0x01, 0xD1, 0x3D, 0x67, 0xB9, 0x65, 0x01, 0x91, 0x01, 0x63, 0x20, 0xE8, 0x00, 0x65, +0xFD, 0x63, 0x05, 0xD1, 0x3D, 0x67, 0x86, 0xD9, 0x46, 0x99, 0x40, 0xD9, 0x40, 0x99, 0x77, 0xF0, +0x24, 0x6B, 0x4D, 0xE3, 0x40, 0x9B, 0x62, 0xD9, 0x41, 0xD9, 0x41, 0x99, 0xB9, 0x65, 0x05, 0x91, +0x03, 0x63, 0x20, 0xE8, 0xFD, 0x63, 0x05, 0xD1, 0x3D, 0x67, 0x86, 0xD9, 0xA7, 0xD9, 0x46, 0x99, +0x40, 0xD9, 0x47, 0x99, 0x41, 0xD9, 0x41, 0x99, 0x60, 0x99, 0x77, 0xF0, 0x24, 0x6A, 0x69, 0xE2, +0x40, 0xDA, 0x42, 0xD9, 0xB9, 0x65, 0x05, 0x91, 0x03, 0x63, 0x20, 0xE8, 0xFF, 0x63, 0x01, 0xD1, +0x3D, 0x67, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF2, 0x44, 0x9A, 0x61, 0x42, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF2, 0x64, 0xDA, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x80, 0xF1, 0x48, 0x9A, 0x10, 0xF0, 0x10, 0x6B, 0x60, 0x33, 0x60, 0x33, +0xC0, 0xF2, 0x64, 0x9B, 0x60, 0xDA, 0xB9, 0x65, 0x01, 0x91, 0x01, 0x63, 0x20, 0xE8, 0x00, 0x65, +0xFE, 0x63, 0x03, 0xD1, 0x3D, 0x67, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF6, +0x0C, 0x4A, 0x02, 0x6B, 0x64, 0xCA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF6, +0x0C, 0x4A, 0x00, 0x6B, 0x61, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF1, +0x4C, 0x9A, 0x00, 0x6B, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF1, +0x50, 0x9A, 0x08, 0x6B, 0x60, 0xC2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF1, +0x54, 0x9A, 0xA7, 0xF7, 0x07, 0x6B, 0x6B, 0xEB, 0x60, 0xCA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0xC0, 0xF1, 0x58, 0x9A, 0x00, 0xF4, 0x05, 0x6B, 0x60, 0xCA, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x04, 0xF0, 0x00, 0x6B, 0x80, 0xF6, 0x6C, 0xDA, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x00, 0xF0, 0x60, 0xA2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x80, 0xF6, 0x0C, 0x4A, 0x6C, 0xC2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF0, +0x00, 0x4A, 0x61, 0xA2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF6, 0x0C, 0x4A, +0x6D, 0xC2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF0, 0x00, 0x4A, 0x62, 0xA2, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF6, 0x0C, 0x4A, 0x6E, 0xC2, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF0, 0x00, 0x4A, 0x63, 0xA2, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x80, 0xF6, 0x0C, 0x4A, 0x6F, 0xC2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x00, 0xF0, 0x00, 0x4A, 0x64, 0xA2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x80, 0xF6, 0x0C, 0x4A, 0x70, 0xC2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF0, +0x00, 0x4A, 0x65, 0xA2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF6, 0x0C, 0x4A, +0x71, 0xC2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF0, 0x00, 0x4A, 0x66, 0xA2, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF6, 0x0C, 0x4A, 0x72, 0xC2, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF0, 0x00, 0x4A, 0x67, 0xA2, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x80, 0xF6, 0x0C, 0x4A, 0x73, 0xC2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x00, 0xF0, 0x00, 0x4A, 0x68, 0xA2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x80, 0xF6, 0x0C, 0x4A, 0x74, 0xC2, 0xB9, 0x65, 0x03, 0x91, 0x02, 0x63, 0x20, 0xE8, 0x00, 0x65, +0xFE, 0x63, 0x03, 0xD1, 0x3D, 0x67, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x12, 0xF0, +0x06, 0x6B, 0x20, 0xF6, 0x64, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF1, +0x5C, 0x9A, 0x01, 0x6B, 0x60, 0xC2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF1, +0x58, 0x9A, 0x00, 0xF4, 0x05, 0x6B, 0x60, 0xCA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0xC0, 0xF1, 0x54, 0x9A, 0x87, 0xF7, 0x07, 0x6B, 0x6B, 0xEB, 0x60, 0xCA, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0xC0, 0xF1, 0x58, 0x9A, 0x00, 0xF4, 0x05, 0x6B, 0x60, 0xCA, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xE0, 0xF1, 0x40, 0x9A, 0x08, 0x6B, 0x60, 0xC2, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF2, 0x48, 0x9A, 0x01, 0x6B, 0x6E, 0xEA, 0x08, 0x2A, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xE0, 0xF1, 0x44, 0x9A, 0x1B, 0x6B, 0x60, 0xDA, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF2, 0x48, 0x9A, 0x02, 0x6B, 0x6E, 0xEA, +0x10, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xE0, 0xF1, 0x48, 0x9A, 0x02, 0x6B, +0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xE0, 0xF1, 0x44, 0x9A, 0x0B, 0x6B, +0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xE0, 0xF1, 0x4C, 0x9A, 0x02, 0x6B, +0x60, 0xCA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xE0, 0xF1, 0x50, 0x9A, 0x44, 0x6B, +0x60, 0xDA, 0xB9, 0x65, 0x03, 0x91, 0x02, 0x63, 0x20, 0xE8, 0x00, 0x65, 0xFE, 0x63, 0x03, 0xD1, +0x3D, 0x67, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x12, 0xF0, 0x06, 0x6B, 0x20, 0xF6, +0x64, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF1, 0x5C, 0x9A, 0x01, 0x6B, +0x60, 0xC2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF1, 0x58, 0x9A, 0x00, 0xF4, +0x05, 0x6B, 0x60, 0xCA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF1, 0x54, 0x9A, +0x87, 0xF7, 0x07, 0x6B, 0x6B, 0xEB, 0x60, 0xCA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0xC0, 0xF1, 0x58, 0x9A, 0x00, 0xF4, 0x05, 0x6B, 0x60, 0xCA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0xE0, 0xF1, 0x40, 0x9A, 0x08, 0x6B, 0x60, 0xC2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0xC0, 0xF2, 0x48, 0x9A, 0x01, 0x6B, 0x6E, 0xEA, 0x08, 0x2A, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0xE0, 0xF1, 0x44, 0x9A, 0x1B, 0x6B, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0xC0, 0xF2, 0x48, 0x9A, 0x02, 0x6B, 0x6E, 0xEA, 0x10, 0x2A, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xE0, 0xF1, 0x48, 0x9A, 0x02, 0x6B, 0x60, 0xDA, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xE0, 0xF1, 0x44, 0x9A, 0x0B, 0x6B, 0x60, 0xDA, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xE0, 0xF1, 0x4C, 0x9A, 0x01, 0x6B, 0x60, 0xCA, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xE0, 0xF1, 0x50, 0x9A, 0x00, 0x6B, 0x60, 0xDA, 0xB9, 0x65, +0x03, 0x91, 0x02, 0x63, 0x20, 0xE8, 0x00, 0x65, 0xFE, 0x63, 0x03, 0xD1, 0x3D, 0x67, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x12, 0xF0, 0x06, 0x6B, 0x20, 0xF6, 0x64, 0xDA, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF1, 0x5C, 0x9A, 0x01, 0x6B, 0x60, 0xC2, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF1, 0x58, 0x9A, 0x00, 0xF4, 0x05, 0x6B, 0x60, 0xCA, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF1, 0x54, 0x9A, 0x87, 0xF7, 0x07, 0x6B, +0x6B, 0xEB, 0x60, 0xCA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF1, 0x58, 0x9A, +0x00, 0xF4, 0x05, 0x6B, 0x60, 0xCA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xE0, 0xF1, +0x40, 0x9A, 0x08, 0x6B, 0x60, 0xC2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF2, +0x48, 0x9A, 0x01, 0x6B, 0x6E, 0xEA, 0x08, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0xE0, 0xF1, 0x44, 0x9A, 0x1B, 0x6B, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0xC0, 0xF2, 0x48, 0x9A, 0x02, 0x6B, 0x6E, 0xEA, 0x10, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0xE0, 0xF1, 0x48, 0x9A, 0x02, 0x6B, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0xE0, 0xF1, 0x44, 0x9A, 0x0B, 0x6B, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0xE0, 0xF1, 0x4C, 0x9A, 0x01, 0x6B, 0x60, 0xCA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0xE0, 0xF1, 0x50, 0x9A, 0x00, 0x6B, 0x60, 0xDA, 0xB9, 0x65, 0x03, 0x91, 0x02, 0x63, +0x20, 0xE8, 0x00, 0x65, 0xF8, 0x63, 0x0F, 0x62, 0x0E, 0xD1, 0x04, 0x01, 0x44, 0x67, 0x20, 0xF0, +0x50, 0xC1, 0x00, 0x6A, 0x5C, 0xC1, 0x00, 0x6A, 0x43, 0xD9, 0x00, 0x6A, 0x42, 0xD9, 0x00, 0x6A, +0x44, 0xC1, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF0, 0x00, 0x4A, 0x40, 0xD9, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xE0, 0xF1, 0x54, 0x9A, 0x40, 0x9A, 0x46, 0xD9, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xE0, 0xF1, 0x54, 0x9A, 0x10, 0xF0, 0x10, 0x6B, +0x60, 0x33, 0x60, 0x33, 0xE0, 0xF1, 0x78, 0x9B, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0xE0, 0xF1, 0x54, 0x9A, 0x10, 0xF0, 0x10, 0x6B, 0x60, 0x33, 0x60, 0x33, 0xE0, 0xF1, +0x7C, 0x9B, 0x60, 0xDA, 0x00, 0x6A, 0x51, 0xC9, 0x03, 0x10, 0x51, 0xA9, 0x01, 0x4A, 0x51, 0xC9, +0x51, 0xA9, 0x0A, 0x5A, 0x58, 0x67, 0xF9, 0x2A, 0x00, 0x18, 0xEC, 0x05, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x00, 0xF2, 0x40, 0x9A, 0xFF, 0x6B, 0x60, 0xCA, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x12, 0xF0, 0x06, 0x6B, 0x20, 0xF6, 0x64, 0xDA, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x00, 0xF2, 0x44, 0x9A, 0x01, 0x6B, 0x60, 0xCA, 0x01, 0x10, 0x00, 0x65, +0x00, 0x18, 0x78, 0x08, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF2, 0x48, 0x9A, +0x40, 0x9A, 0x45, 0xD9, 0x45, 0x99, 0x22, 0xF2, 0x14, 0x6B, 0x6E, 0xEA, 0x01, 0x5A, 0x58, 0x67, +0x62, 0x67, 0xFF, 0x6A, 0x4C, 0xEB, 0x45, 0x99, 0x22, 0xF2, 0x15, 0x6C, 0x8E, 0xEA, 0x01, 0x5A, +0x58, 0x67, 0x82, 0x67, 0xFF, 0x6A, 0x8C, 0xEA, 0x4D, 0xEB, 0xFF, 0x6A, 0x6C, 0xEA, 0x62, 0x67, +0x45, 0x99, 0x22, 0xF2, 0x16, 0x6C, 0x8E, 0xEA, 0x01, 0x5A, 0x58, 0x67, 0x6D, 0xEA, 0x2D, 0x22, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF2, 0x4C, 0x9A, 0x40, 0x9A, 0x44, 0xD9, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF2, 0x4C, 0x9A, 0x64, 0x99, 0x60, 0xDA, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF2, 0x50, 0x9A, 0x80, 0xF4, 0x00, 0x6B, +0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF2, 0x54, 0x9A, 0x40, 0x9A, +0x44, 0xD9, 0x64, 0x99, 0x80, 0x6A, 0x6D, 0xEA, 0x44, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x00, 0xF2, 0x54, 0x9A, 0x64, 0x99, 0x60, 0xDA, 0x45, 0x99, 0x02, 0xF1, 0x11, 0x6B, +0x6E, 0xEA, 0x12, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF1, 0x0C, 0x4A, +0x82, 0x67, 0x00, 0x18, 0x71, 0x10, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF2, +0x48, 0x9A, 0x24, 0xF2, 0x02, 0x6B, 0x60, 0xDA, 0x45, 0x99, 0x26, 0xF3, 0x12, 0x6C, 0x8E, 0xEA, +0x39, 0x2A, 0x00, 0x6A, 0x45, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x20, 0xF6, +0x04, 0x4A, 0x4D, 0xA2, 0x45, 0xD9, 0x45, 0x99, 0x40, 0x32, 0x45, 0xD9, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x20, 0xF6, 0x04, 0x4A, 0x53, 0xA2, 0x65, 0x99, 0x6D, 0xEA, 0x45, 0xD9, +0x45, 0x99, 0x40, 0x32, 0x45, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x20, 0xF6, +0x04, 0x4A, 0x43, 0xAA, 0x65, 0x99, 0x6D, 0xEA, 0x45, 0xD9, 0x45, 0x99, 0x40, 0x32, 0x45, 0xD9, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x20, 0xF6, 0x04, 0x4A, 0x54, 0xA2, 0x65, 0x99, +0x6D, 0xEA, 0x45, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF2, 0x48, 0x9A, +0x65, 0x99, 0x60, 0xDA, 0x45, 0x99, 0x26, 0xF3, 0x13, 0x6B, 0x6E, 0xEA, 0x0C, 0x2A, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF2, 0x48, 0x9A, 0x60, 0x99, 0x60, 0x9B, 0x60, 0xDA, +0x40, 0x99, 0x04, 0x4A, 0x40, 0xD9, 0x45, 0x99, 0x26, 0xF3, 0x14, 0x6C, 0x8E, 0xEA, 0x39, 0x2A, +0x00, 0x6A, 0x45, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x20, 0xF6, 0x04, 0x4A, +0x51, 0xA2, 0x45, 0xD9, 0x45, 0x99, 0x40, 0x32, 0x45, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x20, 0xF6, 0x04, 0x4A, 0x52, 0xA2, 0x65, 0x99, 0x6D, 0xEA, 0x45, 0xD9, 0x45, 0x99, +0x40, 0x32, 0x45, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x20, 0xF6, 0x04, 0x4A, +0x50, 0xA2, 0x65, 0x99, 0x6D, 0xEA, 0x45, 0xD9, 0x45, 0x99, 0x40, 0x32, 0x45, 0xD9, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x20, 0xF6, 0x04, 0x4A, 0x4C, 0xA2, 0x65, 0x99, 0x6D, 0xEA, +0x45, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF2, 0x48, 0x9A, 0x65, 0x99, +0x60, 0xDA, 0x45, 0x99, 0x26, 0xF3, 0x15, 0x6B, 0x6E, 0xEA, 0x0D, 0x2A, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x00, 0xF2, 0x48, 0x9A, 0x10, 0xF0, 0x10, 0x6B, 0x60, 0x33, 0x60, 0x33, +0x80, 0xF6, 0x6C, 0x9B, 0x60, 0xDA, 0x45, 0x99, 0x26, 0xF3, 0x16, 0x6C, 0x8E, 0xEA, 0x0D, 0x2A, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF2, 0x48, 0x9A, 0x10, 0xF0, 0x10, 0x6B, +0x60, 0x33, 0x60, 0x33, 0xA0, 0xF6, 0x64, 0x9B, 0x60, 0xDA, 0x45, 0x99, 0x26, 0xF3, 0x17, 0x6B, +0x6E, 0xEA, 0x0D, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF2, 0x48, 0x9A, +0x10, 0xF0, 0x10, 0x6B, 0x60, 0x33, 0x60, 0x33, 0x80, 0xF6, 0x68, 0x9B, 0x60, 0xDA, 0x45, 0x99, +0x26, 0xF3, 0x18, 0x6C, 0x8E, 0xEA, 0x07, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x01, 0x6B, 0xC0, 0xF2, 0x68, 0xDA, 0x45, 0x99, 0x26, 0xF3, 0x19, 0x6B, 0x6E, 0xEA, 0x07, 0x2A, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x02, 0x6B, 0xC0, 0xF2, 0x68, 0xDA, 0x45, 0x99, +0x46, 0xF3, 0x00, 0x6C, 0x8E, 0xEA, 0x07, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x00, 0x6B, 0xC0, 0xF2, 0x68, 0xDA, 0x45, 0x99, 0x46, 0xF3, 0x01, 0x6B, 0x6E, 0xEA, 0x0D, 0x2A, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF2, 0x48, 0x9A, 0x10, 0xF0, 0x10, 0x6B, +0x60, 0x33, 0x60, 0x33, 0xC0, 0xF2, 0x68, 0x9B, 0x60, 0xDA, 0x45, 0x99, 0x22, 0xF2, 0x14, 0x6C, +0x8E, 0xEA, 0x2E, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF2, 0x48, 0x9A, +0xAA, 0xF5, 0x0A, 0x6B, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF2, +0x54, 0x9A, 0x10, 0xF0, 0x10, 0x6B, 0x60, 0x33, 0x60, 0x33, 0x00, 0xF2, 0x78, 0x9B, 0x60, 0xDA, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF2, 0x5C, 0x9A, 0x10, 0xF0, 0x10, 0x6B, +0x60, 0x33, 0x60, 0x33, 0x20, 0xF2, 0x60, 0x9B, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x20, 0xF2, 0x44, 0x9A, 0x00, 0xF3, 0x00, 0x6B, 0x60, 0xDA, 0x00, 0x18, 0x27, 0x01, +0x45, 0x99, 0x22, 0xF2, 0x15, 0x6B, 0x6E, 0xEA, 0x37, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x00, 0xF2, 0x48, 0x9A, 0x93, 0xF1, 0x19, 0x6B, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x20, 0xF2, 0x48, 0x9A, 0xAF, 0xF3, 0x1C, 0x6B, 0x6B, 0xEB, 0x60, 0xDA, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF1, 0x4C, 0x9A, 0x00, 0x6B, 0x60, 0xDA, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF2, 0x5C, 0x9A, 0x10, 0xF0, 0x10, 0x6B, +0x60, 0x33, 0x60, 0x33, 0x20, 0xF2, 0x60, 0x9B, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x00, 0xF2, 0x54, 0x9A, 0x10, 0xF0, 0x10, 0x6B, 0x60, 0x33, 0x60, 0x33, 0x20, 0xF2, +0x6C, 0x9B, 0x60, 0xDA, 0x00, 0x18, 0x27, 0x01, 0x45, 0x99, 0x22, 0xF2, 0x16, 0x6C, 0x8E, 0xEA, +0x3C, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF2, 0x48, 0x9A, 0x93, 0xF1, +0x19, 0x6B, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF2, 0x5C, 0x9A, +0x10, 0xF0, 0x10, 0x6B, 0x60, 0x33, 0x60, 0x33, 0x20, 0xF2, 0x60, 0x9B, 0x60, 0xDA, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF2, 0x54, 0x9A, 0x10, 0xF0, 0x10, 0x6B, 0x60, 0x33, +0x60, 0x33, 0x20, 0xF2, 0x70, 0x9B, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x20, 0xF2, 0x48, 0x9A, 0xAF, 0xF3, 0x1C, 0x6B, 0x6B, 0xEB, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x20, 0xF2, 0x54, 0x9A, 0x10, 0xF0, 0x10, 0x6B, 0x60, 0x33, 0x60, 0x33, +0x20, 0xF2, 0x78, 0x9B, 0x60, 0xDA, 0x00, 0x18, 0x27, 0x01, 0x45, 0x99, 0x24, 0xF2, 0x16, 0x6B, +0x6E, 0xEA, 0x07, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x01, 0x6B, 0x80, 0xF6, +0x68, 0xDA, 0x45, 0x99, 0x24, 0xF2, 0x15, 0x6C, 0x8E, 0xEA, 0x07, 0x2A, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x02, 0x6B, 0x80, 0xF6, 0x68, 0xDA, 0x45, 0x99, 0x24, 0xF2, 0x14, 0x6B, +0x6E, 0xEA, 0x07, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x03, 0x6B, 0x80, 0xF6, +0x68, 0xDA, 0x45, 0x99, 0x44, 0xF2, 0x00, 0x6C, 0x8E, 0xEA, 0x07, 0x2A, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x01, 0x6B, 0xC0, 0xF2, 0x6C, 0xDA, 0x45, 0x99, 0x44, 0xF2, 0x01, 0x6B, +0x6E, 0xEA, 0x0D, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF2, 0x48, 0x9A, +0x10, 0xF0, 0x10, 0x6B, 0x60, 0x33, 0x60, 0x33, 0xC0, 0xF2, 0x6C, 0x9B, 0x60, 0xDA, 0x45, 0x99, +0x44, 0xF2, 0x02, 0x6C, 0x8E, 0xEA, 0x0E, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x00, 0xF2, 0x48, 0x9A, 0x10, 0xF0, 0x10, 0x6B, 0x60, 0x33, 0x60, 0x33, 0x80, 0xF6, 0x0C, 0x4B, +0x64, 0xAB, 0x60, 0xDA, 0x45, 0x99, 0x44, 0xF2, 0x03, 0x6B, 0x6E, 0xEA, 0x07, 0x2A, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x01, 0x6B, 0xA0, 0xF0, 0x64, 0xDA, 0x45, 0x99, 0x44, 0xF2, +0x04, 0x6C, 0x8E, 0xEA, 0x07, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0x6B, +0xA0, 0xF0, 0x64, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x20, 0xF6, 0x44, 0x9A, +0x12, 0xF0, 0x03, 0x6B, 0x6E, 0xEA, 0x7F, 0xF5, 0x12, 0x2A, 0x00, 0x18, 0x86, 0x09, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x12, 0xF0, 0x06, 0x6B, 0x20, 0xF6, 0x64, 0xDA, 0x68, 0x15, +0xFB, 0x63, 0x09, 0x62, 0x08, 0xD1, 0x04, 0x01, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x20, 0xF2, 0x5C, 0x9A, 0x40, 0x9A, 0x42, 0xD9, 0x62, 0x99, 0x10, 0x6A, 0x6C, 0xEA, 0x71, 0x22, +0x00, 0x6A, 0x40, 0xC1, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xA0, 0xF6, 0x44, 0x9A, +0x61, 0x42, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xA0, 0xF6, 0x64, 0xDA, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xA0, 0xF6, 0x64, 0x9A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x40, 0xF2, 0x40, 0x9A, 0x63, 0xEA, 0x58, 0x67, 0x5C, 0x22, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x00, 0x6B, 0xA0, 0xF6, 0x64, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0xA0, 0xF0, 0x44, 0x9A, 0x01, 0x6B, 0x6E, 0xEA, 0x04, 0x2A, 0x04, 0x6C, 0x00, 0x6D, +0x00, 0x18, 0x5B, 0x0E, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF6, 0x0C, 0x4A, +0x02, 0x6B, 0x64, 0xCA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF6, 0x48, 0x9A, +0x01, 0x6B, 0x6E, 0xEA, 0x09, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF2, +0x48, 0x9A, 0x22, 0xF2, 0x16, 0x6B, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x80, 0xF6, 0x48, 0x9A, 0x02, 0x6B, 0x6E, 0xEA, 0x09, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x00, 0xF2, 0x48, 0x9A, 0x22, 0xF2, 0x15, 0x6B, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x80, 0xF6, 0x48, 0x9A, 0x03, 0x6B, 0x6E, 0xEA, 0x13, 0x2A, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF2, 0x48, 0x9A, 0x22, 0xF2, 0x14, 0x6B, 0x60, 0xDA, +0x09, 0x10, 0x01, 0x6A, 0x40, 0xC1, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0x6B, +0xA0, 0xF6, 0x64, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF6, 0x0C, 0x4A, +0x44, 0xAA, 0x02, 0x6B, 0x6E, 0xEA, 0xE0, 0xF0, 0x0B, 0x2A, 0x40, 0xA1, 0x01, 0x6B, 0x6E, 0xEA, +0x10, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF6, 0x0C, 0x4A, 0x41, 0x9A, +0x61, 0x42, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF6, 0x0C, 0x4A, 0x61, 0xDA, +0x08, 0x10, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF6, 0x0C, 0x4A, 0x00, 0x6B, +0x61, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF6, 0x0C, 0x4A, 0x41, 0x9A, +0x11, 0x5A, 0x58, 0x67, 0xE0, 0xF0, 0x12, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x80, 0xF6, 0x0C, 0x4A, 0x00, 0x6B, 0x61, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x40, 0xF2, 0x44, 0x9A, 0x40, 0x9A, 0x42, 0xD9, 0x62, 0x99, 0x02, 0x6A, 0x4B, 0xEA, 0x6C, 0xEA, +0x42, 0xD9, 0x00, 0x6A, 0x41, 0xD9, 0x03, 0x10, 0x41, 0x99, 0x01, 0x4A, 0x41, 0xD9, 0x41, 0x99, +0x0A, 0x5A, 0x58, 0x67, 0xF9, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF2, +0x44, 0x9A, 0x62, 0x99, 0x60, 0xDA, 0x00, 0x6A, 0x41, 0xD9, 0x03, 0x10, 0x41, 0x99, 0x01, 0x4A, +0x41, 0xD9, 0x41, 0x99, 0x0A, 0x5A, 0x58, 0x67, 0xF9, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0xE0, 0xF1, 0x44, 0x9A, 0x40, 0x9A, 0x42, 0xD9, 0x00, 0x6A, 0x41, 0xD9, 0x03, 0x10, +0x41, 0x99, 0x01, 0x4A, 0x41, 0xD9, 0x41, 0x99, 0x32, 0x5A, 0x58, 0x67, 0xF9, 0x2A, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xE0, 0xF1, 0x44, 0x9A, 0x82, 0x99, 0x01, 0x6B, 0x8D, 0xEB, +0x60, 0xDA, 0x00, 0x6A, 0x41, 0xD9, 0x03, 0x10, 0x41, 0x99, 0x01, 0x4A, 0x41, 0xD9, 0x41, 0x99, +0x32, 0x5A, 0x58, 0x67, 0xF9, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF2, +0x48, 0x9A, 0x00, 0x6B, 0x60, 0xDA, 0x00, 0x6A, 0x41, 0xD9, 0x03, 0x10, 0x41, 0x99, 0x01, 0x4A, +0x41, 0xD9, 0x41, 0x99, 0x32, 0x5A, 0x58, 0x67, 0xF9, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x40, 0xF2, 0x48, 0x9A, 0x07, 0x6B, 0x60, 0xDA, 0x00, 0x6A, 0x41, 0xD9, 0x11, 0x10, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF2, 0x4C, 0x9A, 0x40, 0x9A, 0x42, 0xD9, +0x62, 0x99, 0x01, 0x6A, 0x4C, 0xEB, 0xFF, 0x6A, 0x6C, 0xEA, 0x0E, 0x2A, 0x41, 0x99, 0x01, 0x4A, +0x41, 0xD9, 0x61, 0x99, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF2, 0x50, 0x9A, +0x43, 0xEB, 0x58, 0x67, 0xE5, 0x2A, 0x01, 0x10, 0x00, 0x65, 0x00, 0x18, 0x52, 0x09, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF2, 0x44, 0x9A, 0x01, 0x6B, 0x60, 0xCA, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF2, 0x44, 0x9A, 0x40, 0x9A, 0x42, 0xD9, 0x62, 0x99, +0x01, 0x6A, 0x6D, 0xEA, 0x42, 0xD9, 0x00, 0x6A, 0x41, 0xD9, 0x03, 0x10, 0x41, 0x99, 0x01, 0x4A, +0x41, 0xD9, 0x41, 0x99, 0x0A, 0x5A, 0x58, 0x67, 0xF9, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x40, 0xF2, 0x44, 0x9A, 0x62, 0x99, 0x60, 0xDA, 0x00, 0x6A, 0x41, 0xD9, 0x03, 0x10, +0x41, 0x99, 0x01, 0x4A, 0x41, 0xD9, 0x41, 0x99, 0x0A, 0x5A, 0x58, 0x67, 0xF9, 0x2A, 0x2E, 0x10, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF2, 0x4C, 0x9A, 0x27, 0x22, 0x01, 0x10, +0x00, 0x65, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x20, 0xF2, 0x5C, 0x9A, 0x40, 0x9A, +0x42, 0xD9, 0x62, 0x99, 0x10, 0x6A, 0x6C, 0xEA, 0x18, 0x22, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0xC0, 0xF2, 0x4C, 0x9A, 0x61, 0x42, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0xC0, 0xF2, 0x6C, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF2, 0x4C, 0x9A, +0x02, 0xF0, 0x01, 0x5A, 0x58, 0x67, 0xDC, 0x2A, 0x01, 0x10, 0x00, 0x65, 0xB9, 0x65, 0x05, 0x97, +0x04, 0x91, 0x03, 0x63, 0x00, 0xEF, 0x00, 0x65, 0xFC, 0x63, 0x07, 0x62, 0x06, 0xD1, 0x04, 0x01, +0x00, 0x6A, 0x40, 0xD9, 0x03, 0x10, 0x40, 0x99, 0x01, 0x4A, 0x40, 0xD9, 0x40, 0x99, 0x32, 0x5A, +0x58, 0x67, 0xF9, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF1, 0x4C, 0x9A, +0x10, 0xF0, 0x10, 0x6B, 0x60, 0x33, 0x60, 0x33, 0x40, 0xF2, 0x74, 0x9B, 0x60, 0xDA, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xA0, 0xF0, 0x44, 0x9A, 0x01, 0x6B, 0x6E, 0xEA, 0x16, 0x2A, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF6, 0x0C, 0x4A, 0x44, 0xAA, 0x02, 0x6B, +0x6E, 0xEA, 0x0C, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF6, 0x0C, 0x4A, +0x01, 0x6B, 0x64, 0xCA, 0x04, 0x6C, 0x00, 0x6D, 0x00, 0x18, 0x5B, 0x0E, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x80, 0xF6, 0x0C, 0x4A, 0x01, 0x6B, 0x64, 0xCA, 0xB9, 0x65, 0x03, 0x97, +0x02, 0x91, 0x02, 0x63, 0x00, 0xEF, 0x00, 0x65, 0xFF, 0x63, 0x01, 0xD1, 0x3D, 0x67, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF6, 0x0C, 0x4A, 0x02, 0x6B, 0x64, 0xCA, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF1, 0x4C, 0x9A, 0x00, 0x6B, 0x60, 0xDA, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x04, 0xF0, 0x00, 0x6B, 0x80, 0xF6, 0x6C, 0xDA, 0xB9, 0x65, +0x01, 0x91, 0x01, 0x63, 0x20, 0xE8, 0x00, 0x65, 0xFC, 0x63, 0x07, 0x62, 0x06, 0xD1, 0x04, 0x01, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF6, 0x4C, 0x9A, 0x1C, 0xF0, 0x00, 0x4A, +0x0E, 0x5A, 0x78, 0x67, 0x20, 0xF1, 0x00, 0x23, 0x48, 0x33, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x80, 0xF1, 0x14, 0x4A, 0x49, 0xE3, 0x40, 0x9A, 0x00, 0xEA, 0x00, 0x18, 0xDF, 0x0C, +0x44, 0xC1, 0x44, 0xA1, 0x01, 0x6B, 0x6E, 0xEA, 0x00, 0xF1, 0x10, 0x2A, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x04, 0xF0, 0x01, 0x6B, 0x80, 0xF6, 0x6C, 0xDA, 0x08, 0x11, 0x00, 0x18, +0x23, 0x0A, 0x44, 0xC1, 0x44, 0xA1, 0x02, 0x2A, 0x00, 0x6A, 0x02, 0x11, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x00, 0xF2, 0x44, 0x9A, 0x05, 0x6B, 0x60, 0xCA, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x04, 0xF0, 0x01, 0x6B, 0x80, 0xF6, 0x6C, 0xDA, 0xF0, 0x10, 0x01, 0x6C, +0x00, 0x18, 0x33, 0x0A, 0x44, 0xC1, 0x44, 0xA1, 0x0A, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x04, 0xF0, 0x00, 0x6B, 0x80, 0xF6, 0x6C, 0xDA, 0x00, 0x6A, 0xE1, 0x10, 0x44, 0xA1, +0x01, 0x6B, 0x6E, 0xEA, 0x0A, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x04, 0xF0, +0x01, 0x6B, 0x80, 0xF6, 0x6C, 0xDA, 0x00, 0x6A, 0xD3, 0x10, 0x44, 0xA1, 0x02, 0x6B, 0x6E, 0xEA, +0x0A, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x04, 0xF0, 0x0C, 0x6B, 0x80, 0xF6, +0x6C, 0xDA, 0x00, 0x6A, 0xC5, 0x10, 0x44, 0xA1, 0x07, 0x6B, 0x6E, 0xEA, 0x0A, 0x2A, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x04, 0xF0, 0x03, 0x6B, 0x80, 0xF6, 0x6C, 0xDA, 0x00, 0x6A, +0xB7, 0x10, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x04, 0xF0, 0x00, 0x6B, 0x80, 0xF6, +0x6C, 0xDA, 0x00, 0x6A, 0xAD, 0x10, 0x02, 0x6C, 0x00, 0x18, 0x20, 0x0B, 0x44, 0xC1, 0x44, 0xA1, +0x0A, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x04, 0xF0, 0x00, 0x6B, 0x80, 0xF6, +0x6C, 0xDA, 0x00, 0x6A, 0x9D, 0x10, 0x44, 0xA1, 0x01, 0x6B, 0x6E, 0xEA, 0x0A, 0x2A, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x04, 0xF0, 0x03, 0x6B, 0x80, 0xF6, 0x6C, 0xDA, 0x00, 0x6A, +0x8F, 0x10, 0x44, 0xA1, 0x02, 0x6B, 0x6E, 0xEA, 0x12, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x04, 0xF0, 0x0C, 0x6B, 0x80, 0xF6, 0x6C, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x00, 0xF2, 0x44, 0x9A, 0x07, 0x6B, 0x60, 0xCA, 0x00, 0x6A, 0x79, 0x10, 0x44, 0xA1, +0x07, 0x6B, 0x6E, 0xEA, 0x12, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x04, 0xF0, +0x0C, 0x6B, 0x80, 0xF6, 0x6C, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF2, +0x44, 0x9A, 0x07, 0x6B, 0x60, 0xCA, 0x00, 0x6A, 0x63, 0x10, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x04, 0xF0, 0x00, 0x6B, 0x80, 0xF6, 0x6C, 0xDA, 0x00, 0x6A, 0x59, 0x10, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x20, 0xF6, 0x04, 0x4A, 0x4B, 0xA2, 0x12, 0x22, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x04, 0xF0, 0x00, 0x6B, 0x80, 0xF6, 0x6C, 0xDA, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF2, 0x44, 0x9A, 0x05, 0x6B, 0x60, 0xCA, 0x00, 0x6A, +0x3F, 0x10, 0x00, 0x18, 0xBF, 0x0C, 0x44, 0xC1, 0x44, 0xA1, 0x03, 0x6B, 0x6E, 0xEA, 0x12, 0x2A, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF2, 0x44, 0x9A, 0x05, 0x6B, 0x60, 0xCA, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x04, 0xF0, 0x0D, 0x6B, 0x80, 0xF6, 0x6C, 0xDA, +0x00, 0x6A, 0x26, 0x10, 0x44, 0xA1, 0x12, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x04, 0xF0, 0x00, 0x6B, 0x80, 0xF6, 0x6C, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x00, 0xF2, 0x44, 0x9A, 0x05, 0x6B, 0x60, 0xCA, 0x00, 0x6A, 0x12, 0x10, 0x44, 0xA1, 0x02, 0x6B, +0x6E, 0xEA, 0x08, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x04, 0xF0, 0x0C, 0x6B, +0x80, 0xF6, 0x6C, 0xDA, 0x00, 0x6A, 0x04, 0x10, 0x00, 0x6A, 0x02, 0x10, 0x00, 0x65, 0x00, 0x10, +0xB9, 0x65, 0x03, 0x97, 0x02, 0x91, 0x02, 0x63, 0x00, 0xEF, 0x00, 0x65, 0xFD, 0x63, 0x05, 0x62, +0x04, 0xD1, 0x04, 0x01, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF6, 0x40, 0xA2, +0x26, 0x6B, 0x6E, 0xEA, 0x02, 0x2A, 0x00, 0x18, 0x4C, 0x06, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x40, 0xF6, 0x40, 0xA2, 0x52, 0x6B, 0x6E, 0xEA, 0x02, 0x2A, 0x00, 0x18, 0x4C, 0x06, +0x01, 0x6A, 0xB9, 0x65, 0x01, 0x97, 0x00, 0x91, 0x01, 0x63, 0x00, 0xEF, 0xFA, 0x63, 0x0B, 0x62, +0x0A, 0xD1, 0x04, 0x01, 0x44, 0x67, 0x20, 0xF0, 0x40, 0xC1, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x40, 0xF6, 0x00, 0x4A, 0x41, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x40, 0xF6, 0x00, 0x4A, 0x41, 0xA2, 0x40, 0xC1, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x40, 0xF6, 0x40, 0xA2, 0x93, 0x6B, 0x6E, 0xEA, 0xA0, 0xF1, 0x14, 0x2A, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x40, 0xF6, 0x00, 0x4A, 0x41, 0xA2, 0x70, 0x6C, 0x8E, 0xEA, 0x05, 0x2A, +0x00, 0x6C, 0x00, 0x18, 0x41, 0x0C, 0x07, 0x6A, 0xA6, 0x11, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x40, 0xF6, 0x00, 0x4A, 0x41, 0xA2, 0x20, 0x5A, 0x58, 0x67, 0x02, 0x22, 0x00, 0x6A, +0x9A, 0x11, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF6, 0x00, 0x4A, 0x41, 0xA2, +0x68, 0x5A, 0x58, 0x67, 0x02, 0x2A, 0x00, 0x6A, 0x8E, 0x11, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x40, 0xF6, 0x00, 0x4A, 0x41, 0xA2, 0x20, 0x6B, 0x6E, 0xEA, 0x4D, 0x2A, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x78, 0x6B, 0x6B, 0xEB, 0x40, 0xF6, 0x60, 0xC2, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF6, 0x0C, 0x4A, 0x6C, 0xA2, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x40, 0xF6, 0x00, 0x4A, 0x61, 0xC2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x80, 0xF6, 0x0C, 0x4A, 0x6D, 0xA2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x40, 0xF6, 0x00, 0x4A, 0x62, 0xC2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF6, +0x0C, 0x4A, 0x6E, 0xA2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF6, 0x00, 0x4A, +0x63, 0xC2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF6, 0x0C, 0x4A, 0x6F, 0xA2, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF6, 0x00, 0x4A, 0x64, 0xC2, 0x40, 0xA1, +0x10, 0xF0, 0x10, 0x6B, 0x60, 0x33, 0x60, 0x33, 0x40, 0xF6, 0x00, 0x4B, 0x83, 0x67, 0xA2, 0x67, +0x00, 0x18, 0xCE, 0x0B, 0x01, 0x6A, 0x37, 0x11, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x40, 0xF6, 0x40, 0xA2, 0x30, 0x6C, 0x8E, 0xEA, 0x0E, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x40, 0xF6, 0x00, 0x4A, 0x41, 0xA2, 0x04, 0x2A, 0x00, 0x18, 0x29, 0x0D, 0x02, 0x6A, +0x22, 0x11, 0x00, 0x6A, 0x20, 0x11, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF6, +0x00, 0x4A, 0x41, 0xA2, 0x62, 0x67, 0x0F, 0x6A, 0x6C, 0xEA, 0x16, 0x22, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x40, 0xF6, 0x00, 0x4A, 0x41, 0xA2, 0x52, 0x33, 0xFF, 0x6A, 0x6C, 0xEA, +0x62, 0x67, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x20, 0xF6, 0x04, 0x4A, 0x43, 0xAA, +0x6E, 0xEA, 0x02, 0x22, 0x00, 0x6A, 0xFF, 0x10, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x40, 0xF6, 0x00, 0x4A, 0x41, 0xA2, 0x62, 0x67, 0x0F, 0x6A, 0x4C, 0xEB, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x20, 0xF6, 0x04, 0x4A, 0x49, 0xA2, 0x6E, 0xEA, 0x02, 0x22, 0x00, 0x6A, +0xEA, 0x10, 0x40, 0xA1, 0xE0, 0x4A, 0x53, 0x32, 0x43, 0xC1, 0x00, 0x6A, 0x42, 0xC1, 0x2C, 0x10, +0x42, 0xA1, 0x0F, 0x2A, 0x42, 0xA1, 0x62, 0x42, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x40, 0xF6, 0x00, 0x4A, 0x49, 0xE3, 0x40, 0xA2, 0x88, 0x6B, 0x6E, 0xEA, 0x1A, 0x22, 0x00, 0x6A, +0xD2, 0x10, 0x42, 0xA1, 0x62, 0x42, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF6, +0x00, 0x4A, 0x49, 0xE3, 0x60, 0xA2, 0x42, 0xA1, 0x8F, 0x42, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x80, 0xF6, 0x0C, 0x4A, 0x49, 0xE4, 0x4C, 0xA2, 0x6E, 0xEA, 0x02, 0x22, 0x00, 0x6A, +0xBA, 0x10, 0x42, 0xA1, 0x01, 0x4A, 0x42, 0xC1, 0x62, 0xA1, 0x43, 0xA1, 0x43, 0xEB, 0x58, 0x67, +0xCF, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF6, 0x00, 0x4A, 0x61, 0xA2, +0x0F, 0x6A, 0x6C, 0xEA, 0x48, 0xC1, 0x48, 0xA1, 0x40, 0x22, 0x48, 0xA1, 0x08, 0x6B, 0x4B, 0xE3, +0x48, 0xC1, 0x43, 0xA1, 0x14, 0x2A, 0x48, 0xA1, 0x88, 0x6B, 0x83, 0x67, 0x84, 0xEA, 0x44, 0x67, +0x4A, 0xC1, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF6, 0x00, 0x4A, 0x42, 0xA2, +0x62, 0x67, 0x48, 0xA1, 0x83, 0x67, 0x84, 0xEA, 0x44, 0x67, 0x49, 0xC1, 0x20, 0x10, 0x43, 0xA1, +0x6F, 0x42, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF6, 0x0C, 0x4A, 0x49, 0xE3, +0x4C, 0xA2, 0x62, 0x67, 0x48, 0xA1, 0x83, 0x67, 0x84, 0xEA, 0x44, 0x67, 0x4A, 0xC1, 0x43, 0xA1, +0x62, 0x42, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF6, 0x00, 0x4A, 0x49, 0xE3, +0x40, 0xA2, 0x62, 0x67, 0x48, 0xA1, 0x83, 0x67, 0x84, 0xEA, 0x44, 0x67, 0x49, 0xC1, 0x6A, 0xA1, +0x49, 0xA1, 0x6E, 0xEA, 0x02, 0x22, 0x00, 0x6A, 0x66, 0x10, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x80, 0xF6, 0x0C, 0x4A, 0x6F, 0xA2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x40, 0xF6, 0x00, 0x4A, 0x64, 0xC2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF6, +0x0C, 0x4A, 0x6E, 0xA2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF6, 0x00, 0x4A, +0x63, 0xC2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF6, 0x0C, 0x4A, 0x6D, 0xA2, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF6, 0x00, 0x4A, 0x62, 0xC2, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF6, 0x0C, 0x4A, 0x6C, 0xA2, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x40, 0xF6, 0x00, 0x4A, 0x61, 0xC2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x78, 0x6B, 0x6B, 0xEB, 0x40, 0xF6, 0x60, 0xC2, 0x00, 0x6A, 0x42, 0xC1, 0x12, 0x10, +0x42, 0xA1, 0x83, 0xA1, 0x62, 0xA1, 0x71, 0xE4, 0x10, 0xF0, 0x10, 0x6B, 0x60, 0x33, 0x60, 0x33, +0x40, 0xF6, 0x00, 0x4B, 0x6D, 0xE4, 0x60, 0xA3, 0x91, 0x67, 0x49, 0xE4, 0x70, 0xC2, 0x42, 0xA1, +0x01, 0x4A, 0x42, 0xC1, 0x62, 0xA1, 0x43, 0xA1, 0x05, 0x6C, 0x4B, 0xE4, 0x42, 0xEB, 0x58, 0x67, +0xE7, 0x2A, 0x40, 0xA1, 0x67, 0x41, 0x09, 0x4B, 0x83, 0x67, 0xA2, 0x67, 0x00, 0x18, 0xCE, 0x0B, +0x01, 0x6A, 0x01, 0x10, 0x00, 0x6A, 0xB9, 0x65, 0x07, 0x97, 0x06, 0x91, 0x04, 0x63, 0x00, 0xEF, +0xFA, 0x63, 0x0B, 0x62, 0x0A, 0xD1, 0x04, 0x01, 0x44, 0x67, 0x20, 0xF0, 0x40, 0xC1, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF6, 0x00, 0x4A, 0x41, 0xA2, 0x40, 0xC1, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF6, 0x40, 0xA2, 0x95, 0x6B, 0x6E, 0xEA, 0x20, 0xF1, +0x1D, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF6, 0x00, 0x4A, 0x41, 0xA2, +0x70, 0x6C, 0x8E, 0xEA, 0x05, 0x2A, 0x01, 0x6C, 0x00, 0x18, 0x41, 0x0C, 0x07, 0x6A, 0x2F, 0x11, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF6, 0x00, 0x4A, 0x41, 0xA2, 0x20, 0x6B, +0x6E, 0xEA, 0x52, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF6, 0x0C, 0x4A, +0x70, 0xA2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF6, 0x60, 0xC2, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF6, 0x0C, 0x4A, 0x71, 0xA2, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x40, 0xF6, 0x00, 0x4A, 0x61, 0xC2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x80, 0xF6, 0x0C, 0x4A, 0x72, 0xA2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x40, 0xF6, 0x00, 0x4A, 0x62, 0xC2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF6, +0x0C, 0x4A, 0x73, 0xA2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF6, 0x00, 0x4A, +0x63, 0xC2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF6, 0x0C, 0x4A, 0x74, 0xA2, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF6, 0x00, 0x4A, 0x64, 0xC2, 0x40, 0xA1, +0x10, 0xF0, 0x10, 0x6B, 0x60, 0x33, 0x60, 0x33, 0x40, 0xF6, 0x00, 0x4B, 0x83, 0x67, 0xA2, 0x67, +0x00, 0x18, 0xCE, 0x0B, 0x01, 0x6A, 0xD3, 0x10, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x40, 0xF6, 0x40, 0xA2, 0x30, 0x6C, 0x8E, 0xEA, 0x0E, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x40, 0xF6, 0x00, 0x4A, 0x41, 0xA2, 0x04, 0x2A, 0x00, 0x18, 0x29, 0x0D, 0x02, 0x6A, +0xBE, 0x10, 0x00, 0x6A, 0xBC, 0x10, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF6, +0x00, 0x4A, 0x41, 0xA2, 0x62, 0x67, 0x01, 0x6A, 0x4C, 0xEB, 0xFF, 0x6A, 0x6C, 0xEA, 0x16, 0x22, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF6, 0x00, 0x4A, 0x41, 0xA2, 0x52, 0x33, +0xFF, 0x6A, 0x6C, 0xEA, 0x62, 0x67, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x20, 0xF6, +0x04, 0x4A, 0x43, 0xAA, 0x6E, 0xEA, 0x02, 0x22, 0x00, 0x6A, 0x99, 0x10, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x40, 0xF6, 0x00, 0x4A, 0x41, 0xA2, 0x62, 0x67, 0x0F, 0x6A, 0x4C, 0xEB, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x20, 0xF6, 0x04, 0x4A, 0x49, 0xA2, 0x6E, 0xEA, +0x02, 0x22, 0x00, 0x6A, 0x84, 0x10, 0x40, 0xA1, 0xE0, 0x4A, 0x53, 0x32, 0x42, 0xC1, 0x00, 0x6A, +0x41, 0xC1, 0x1B, 0x10, 0x41, 0xA1, 0x62, 0x42, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x40, 0xF6, 0x00, 0x4A, 0x49, 0xE3, 0x60, 0xA2, 0x41, 0xA1, 0x84, 0x42, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x80, 0xF6, 0x0C, 0x4A, 0x49, 0xE4, 0x4C, 0xA2, 0x6E, 0xEA, 0x02, 0x22, +0x00, 0x6A, 0x65, 0x10, 0x41, 0xA1, 0x01, 0x4A, 0x41, 0xC1, 0x61, 0xA1, 0x42, 0xA1, 0x43, 0xEB, +0x58, 0x67, 0xE0, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF6, 0x00, 0x4A, +0x61, 0xA2, 0x0F, 0x6A, 0x6C, 0xEA, 0x45, 0xC1, 0x45, 0xA1, 0x2A, 0x22, 0x45, 0xA1, 0x08, 0x6B, +0x4B, 0xE3, 0x45, 0xC1, 0x42, 0xA1, 0x64, 0x42, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x80, 0xF6, 0x0C, 0x4A, 0x49, 0xE3, 0x4C, 0xA2, 0x62, 0x67, 0x45, 0xA1, 0x83, 0x67, 0x84, 0xEA, +0x44, 0x67, 0x44, 0xC1, 0x42, 0xA1, 0x62, 0x42, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x40, 0xF6, 0x00, 0x4A, 0x49, 0xE3, 0x40, 0xA2, 0x62, 0x67, 0x45, 0xA1, 0x83, 0x67, 0x84, 0xEA, +0x44, 0x67, 0x43, 0xC1, 0x64, 0xA1, 0x43, 0xA1, 0x6E, 0xEA, 0x02, 0x22, 0x00, 0x6A, 0x27, 0x10, +0x00, 0x6A, 0x41, 0xC1, 0x13, 0x10, 0x41, 0xA1, 0x62, 0xA1, 0x84, 0x43, 0x61, 0xA1, 0x71, 0xE4, +0x10, 0xF0, 0x10, 0x6B, 0x60, 0x33, 0x60, 0x33, 0x80, 0xF6, 0x0C, 0x4B, 0x6D, 0xE4, 0x6C, 0xA3, +0x91, 0x67, 0x49, 0xE4, 0x68, 0xC2, 0x41, 0xA1, 0x01, 0x4A, 0x41, 0xC1, 0x61, 0xA1, 0x42, 0xA1, +0x05, 0x6C, 0x4B, 0xE4, 0x42, 0xEB, 0x58, 0x67, 0xE6, 0x2A, 0x40, 0xA1, 0x67, 0x41, 0x01, 0x4B, +0x83, 0x67, 0xA2, 0x67, 0x00, 0x18, 0xCE, 0x0B, 0x01, 0x6A, 0x01, 0x10, 0x00, 0x6A, 0xB9, 0x65, +0x07, 0x97, 0x06, 0x91, 0x04, 0x63, 0x00, 0xEF, 0xFA, 0x63, 0x0B, 0xD1, 0x3D, 0x67, 0x8C, 0xD9, +0x45, 0x67, 0x20, 0xF0, 0x54, 0xC1, 0x00, 0x6A, 0x46, 0xC9, 0x00, 0x6A, 0x41, 0xD9, 0x4C, 0x99, +0x40, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x12, 0xF0, 0x06, 0x6B, 0x20, 0xF6, +0x64, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF1, 0x58, 0x9A, 0x00, 0xF4, +0x05, 0x6B, 0x60, 0xCA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xE0, 0xF1, 0x40, 0x9A, +0x08, 0x6B, 0x60, 0xC2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF1, 0x5C, 0x9A, +0x01, 0x6B, 0x60, 0xC2, 0x20, 0xF0, 0x74, 0xA1, 0x0F, 0x6A, 0x6C, 0xEA, 0x20, 0x22, 0x20, 0xF0, +0x54, 0xA1, 0x0F, 0x6B, 0x6C, 0xEA, 0x08, 0x6B, 0x4B, 0xE3, 0x46, 0xC9, 0x46, 0xA9, 0x40, 0x32, +0x46, 0xC9, 0x20, 0xF0, 0x54, 0xA1, 0xE0, 0x4A, 0x53, 0x33, 0xFF, 0xF7, 0x1F, 0x6A, 0x6C, 0xEA, +0x66, 0xA9, 0x4F, 0xE3, 0xFF, 0xF7, 0x1F, 0x6A, 0x6C, 0xEA, 0x04, 0x4A, 0x46, 0xC9, 0x66, 0xA9, +0xFF, 0x6A, 0x6C, 0xEA, 0x45, 0xC9, 0x45, 0xA9, 0x01, 0x4A, 0x45, 0xC9, 0x10, 0x10, 0x20, 0xF0, +0x54, 0xA1, 0xE0, 0x4A, 0x53, 0x33, 0xFF, 0xF7, 0x1F, 0x6A, 0x6C, 0xEA, 0x66, 0xA9, 0x4F, 0xE3, +0xFF, 0xF7, 0x1F, 0x6A, 0x6C, 0xEA, 0x05, 0x4A, 0x46, 0xC9, 0x46, 0xA9, 0x45, 0xC9, 0x46, 0xA9, +0x05, 0x6B, 0x6E, 0xEA, 0x09, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xE0, 0xF1, +0x40, 0x9A, 0x08, 0x6B, 0x60, 0xC2, 0x08, 0x10, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0xE0, 0xF1, 0x40, 0x9A, 0x48, 0x6B, 0x60, 0xC2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0xE0, 0xF1, 0x4C, 0x9A, 0x66, 0xA9, 0x60, 0xCA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0xC0, 0xF2, 0x48, 0x9A, 0x01, 0x6B, 0x6E, 0xEA, 0x08, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0xE0, 0xF1, 0x44, 0x9A, 0x1B, 0x6B, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0xC0, 0xF2, 0x48, 0x9A, 0x02, 0x6B, 0x6E, 0xEA, 0x10, 0x2A, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0xE0, 0xF1, 0x48, 0x9A, 0x02, 0x6B, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0xE0, 0xF1, 0x44, 0x9A, 0x0B, 0x6B, 0x60, 0xDA, 0x45, 0xA9, 0x05, 0x5A, +0x58, 0x67, 0x0A, 0x22, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xE0, 0xF1, 0x50, 0x9A, +0x60, 0x99, 0x60, 0x9B, 0x60, 0xDA, 0x13, 0x10, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0xE0, 0xF1, 0x50, 0x9A, 0x60, 0x99, 0x60, 0x9B, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0xE0, 0xF1, 0x50, 0x9A, 0x60, 0x99, 0x04, 0x4B, 0x60, 0x9B, 0x60, 0xDA, 0x00, 0x6A, +0x44, 0xD9, 0x0D, 0x10, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x20, 0xF6, 0x44, 0x9A, +0x12, 0xF0, 0x04, 0x6B, 0x6E, 0xEA, 0x09, 0x22, 0x44, 0x99, 0x01, 0x4A, 0x44, 0xD9, 0x44, 0x99, +0xE5, 0xF7, 0x1F, 0x5A, 0x58, 0x67, 0xEE, 0x2A, 0x01, 0x10, 0x00, 0x65, 0xB9, 0x65, 0x0B, 0x91, +0x06, 0x63, 0x20, 0xE8, 0xFC, 0x63, 0x07, 0x62, 0x06, 0xD1, 0x04, 0x01, 0x44, 0x67, 0x50, 0xC1, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF6, 0x00, 0x4A, 0x41, 0xD9, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF6, 0x4C, 0x9A, 0x04, 0xF0, 0x01, 0x6B, 0x6E, 0xEA, +0x26, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF6, 0x00, 0x4A, 0x42, 0xA2, +0x88, 0x6B, 0x6E, 0xEA, 0x02, 0x22, 0x00, 0x6A, 0x3F, 0x10, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x62, 0x67, 0x40, 0xF6, 0x03, 0x4B, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x80, 0xF6, 0x18, 0x4A, 0x83, 0x67, 0xA2, 0x67, 0x03, 0x6E, 0x00, 0x18, 0x47, 0x05, 0x01, 0x6B, +0x6E, 0xEA, 0x02, 0x22, 0x00, 0x6A, 0x28, 0x10, 0x00, 0x6C, 0x00, 0x18, 0x75, 0x0C, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF6, 0x4C, 0x9A, 0x04, 0xF0, 0x03, 0x6B, 0x6E, 0xEA, +0x1A, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x62, 0x67, 0x40, 0xF6, 0x02, 0x4B, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF6, 0x1C, 0x4A, 0x83, 0x67, 0xA2, 0x67, +0x04, 0x6E, 0x00, 0x18, 0x47, 0x05, 0x01, 0x6B, 0x6E, 0xEA, 0x02, 0x22, 0x00, 0x6A, 0x04, 0x10, +0x01, 0x6C, 0x00, 0x18, 0x75, 0x0C, 0x00, 0x10, 0xB9, 0x65, 0x03, 0x97, 0x02, 0x91, 0x02, 0x63, +0x00, 0xEF, 0x00, 0x65, 0xFE, 0x63, 0x03, 0xD1, 0x3D, 0x67, 0x44, 0x67, 0x50, 0xC1, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x12, 0xF0, 0x06, 0x6B, 0x20, 0xF6, 0x64, 0xDA, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF1, 0x5C, 0x9A, 0x01, 0x6B, 0x60, 0xC2, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF1, 0x58, 0x9A, 0x00, 0xF4, 0x07, 0x6B, 0x60, 0xCA, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xE0, 0xF1, 0x40, 0x9A, 0x08, 0x6B, 0x60, 0xC2, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF2, 0x48, 0x9A, 0x01, 0x6B, 0x6E, 0xEA, +0x08, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xE0, 0xF1, 0x44, 0x9A, 0x1B, 0x6B, +0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF2, 0x48, 0x9A, 0x02, 0x6B, +0x6E, 0xEA, 0x10, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xE0, 0xF1, 0x48, 0x9A, +0x02, 0x6B, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xE0, 0xF1, 0x44, 0x9A, +0x0B, 0x6B, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xE0, 0xF1, 0x4C, 0x9A, +0x01, 0x6B, 0x60, 0xCA, 0x50, 0xA1, 0x09, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0xE0, 0xF1, 0x50, 0x9A, 0x04, 0x6B, 0x60, 0xDA, 0x08, 0x10, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0xE0, 0xF1, 0x50, 0x9A, 0x00, 0x6B, 0x60, 0xDA, 0x00, 0x6A, 0x40, 0xD9, 0x0D, 0x10, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x20, 0xF6, 0x44, 0x9A, 0x12, 0xF0, 0x04, 0x6B, +0x6E, 0xEA, 0x0E, 0x22, 0x40, 0x99, 0x01, 0x4A, 0x40, 0xD9, 0x60, 0x99, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x40, 0xF2, 0x58, 0x9A, 0x63, 0xEA, 0x58, 0x67, 0xE9, 0x22, 0x01, 0x10, +0x00, 0x65, 0xB9, 0x65, 0x03, 0x91, 0x02, 0x63, 0x20, 0xE8, 0x00, 0x65, 0xFF, 0x63, 0x01, 0xD1, +0x3D, 0x67, 0xB9, 0x65, 0x01, 0x91, 0x01, 0x63, 0x20, 0xE8, 0x00, 0x65, 0xFD, 0x63, 0x05, 0x62, +0x04, 0xD1, 0x04, 0x01, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF6, 0x40, 0xA2, +0x50, 0x6B, 0x4E, 0xEB, 0x11, 0x23, 0x51, 0x52, 0x78, 0x67, 0x07, 0x23, 0x1A, 0x6B, 0x4E, 0xEB, +0x23, 0x23, 0x30, 0x6B, 0x6E, 0xEA, 0x18, 0x22, 0x23, 0x10, 0x60, 0x6B, 0x4E, 0xEB, 0x18, 0x23, +0xA2, 0x6B, 0x6E, 0xEA, 0x0D, 0x22, 0x1C, 0x10, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x40, 0xF6, 0x00, 0x4A, 0x41, 0xA2, 0x02, 0x22, 0x00, 0x6A, 0x13, 0x10, 0x03, 0x6A, 0x11, 0x10, +0x00, 0x18, 0xEB, 0x0C, 0x01, 0x6A, 0x0D, 0x10, 0x00, 0x18, 0x29, 0x0D, 0x02, 0x6A, 0x09, 0x10, +0x00, 0x18, 0x87, 0x06, 0x04, 0x6A, 0x05, 0x10, 0x00, 0x18, 0xC2, 0x06, 0x04, 0x6A, 0x01, 0x10, +0x00, 0x6A, 0xB9, 0x65, 0x01, 0x97, 0x00, 0x91, 0x01, 0x63, 0x00, 0xEF, 0xFD, 0x63, 0x05, 0x62, +0x04, 0xD1, 0x04, 0x01, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF6, 0x40, 0xA2, +0x52, 0x6B, 0x6E, 0xEA, 0x04, 0x2A, 0x00, 0x18, 0x4C, 0x06, 0x01, 0x6A, 0x01, 0x10, 0x00, 0x6A, +0xB9, 0x65, 0x01, 0x97, 0x00, 0x91, 0x01, 0x63, 0x00, 0xEF, 0x00, 0x65, 0xFB, 0x63, 0x09, 0x62, +0x08, 0xD1, 0x04, 0x01, 0x01, 0x6A, 0x42, 0xC1, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x40, 0xF6, 0x00, 0x4A, 0x42, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF6, +0x00, 0x4A, 0x41, 0xA2, 0x41, 0xC1, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF0, +0x00, 0x4A, 0x4A, 0xA2, 0x40, 0xC1, 0x41, 0xA1, 0x2A, 0x5A, 0x58, 0x67, 0x01, 0x6B, 0x6E, 0xEA, +0x62, 0x67, 0xFF, 0x6A, 0x4C, 0xEB, 0x41, 0xA1, 0x02, 0x5A, 0x58, 0x67, 0x82, 0x67, 0xFF, 0x6A, +0x8C, 0xEA, 0x4D, 0xEB, 0xFF, 0x6A, 0x6C, 0xEA, 0x05, 0x22, 0x00, 0x6C, 0x00, 0x18, 0x82, 0x0D, +0x00, 0x6A, 0x42, 0x10, 0x42, 0xA1, 0x28, 0x22, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x40, 0xF6, 0x00, 0x4A, 0x41, 0xA2, 0x48, 0x32, 0x44, 0xC1, 0x00, 0x6A, 0x43, 0xC1, 0x18, 0x10, +0x64, 0xA1, 0x43, 0xA1, 0x51, 0xE3, 0x43, 0xA1, 0x62, 0x42, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x40, 0xF6, 0x00, 0x4A, 0x49, 0xE3, 0x60, 0xA2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x00, 0xF0, 0x00, 0x4A, 0x49, 0xE4, 0x60, 0xC2, 0x43, 0xA1, 0x01, 0x4A, 0x43, 0xC1, +0x43, 0xA1, 0x04, 0x5A, 0x58, 0x67, 0xE4, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0xA0, 0xF0, 0x44, 0x9A, 0x01, 0x6B, 0x6E, 0xEA, 0x0B, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x40, 0xF6, 0x00, 0x4A, 0x41, 0xA2, 0x01, 0x6C, 0xA2, 0x67, 0x00, 0x18, 0x5B, 0x0E, +0x0A, 0x6C, 0x00, 0x18, 0x82, 0x0D, 0x01, 0x6A, 0xB9, 0x65, 0x05, 0x97, 0x04, 0x91, 0x03, 0x63, +0x00, 0xEF, 0x00, 0x65, 0xFB, 0x63, 0x09, 0x62, 0x08, 0xD1, 0x04, 0x01, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x00, 0xF0, 0x00, 0x4A, 0x41, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0xC0, 0xF1, 0x5C, 0x9A, 0x01, 0x6B, 0x60, 0xC2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0xC0, 0xF1, 0x58, 0x9A, 0x00, 0xF4, 0x07, 0x6B, 0x60, 0xCA, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0xE0, 0xF1, 0x40, 0x9A, 0x08, 0x6B, 0x60, 0xC2, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x12, 0xF0, 0x06, 0x6B, 0x20, 0xF6, 0x64, 0xDA, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x40, 0xF6, 0x00, 0x4A, 0x41, 0xA2, 0x2A, 0x5A, 0x58, 0x67, 0x07, 0x2A, +0x00, 0x6C, 0x00, 0x18, 0x82, 0x0D, 0x00, 0x6A, 0x62, 0x67, 0x43, 0x67, 0x6F, 0x10, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF6, 0x00, 0x4A, 0x41, 0xA2, 0x48, 0x32, 0x61, 0x99, +0x49, 0xE3, 0x41, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF2, 0x48, 0x9A, +0x01, 0x6B, 0x6E, 0xEA, 0x08, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xE0, 0xF1, +0x44, 0x9A, 0x1B, 0x6B, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF2, +0x48, 0x9A, 0x02, 0x6B, 0x6E, 0xEA, 0x10, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0xE0, 0xF1, 0x48, 0x9A, 0x02, 0x6B, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0xE0, 0xF1, 0x44, 0x9A, 0x0B, 0x6B, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0xE0, 0xF1, 0x4C, 0x9A, 0x10, 0x6B, 0x60, 0xCA, 0x00, 0x6A, 0x48, 0xC1, 0x0F, 0x10, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xE0, 0xF1, 0x50, 0x9A, 0x68, 0xA1, 0x68, 0x33, 0x81, 0x99, +0x6D, 0xE4, 0x60, 0x9B, 0x60, 0xDA, 0x48, 0xA1, 0x01, 0x4A, 0x48, 0xC1, 0x48, 0xA1, 0x04, 0x5A, +0x58, 0x67, 0xED, 0x2A, 0x00, 0x6A, 0x40, 0xD9, 0x0D, 0x10, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x20, 0xF6, 0x44, 0x9A, 0x12, 0xF0, 0x04, 0x6B, 0x6E, 0xEA, 0x0E, 0x22, 0x40, 0x99, +0x01, 0x4A, 0x40, 0xD9, 0x60, 0x99, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF2, +0x58, 0x9A, 0x63, 0xEA, 0x58, 0x67, 0xE9, 0x22, 0x01, 0x10, 0x00, 0x65, 0xB9, 0x65, 0x05, 0x97, +0x04, 0x91, 0x03, 0x63, 0x00, 0xEF, 0x00, 0x65, 0xFE, 0x63, 0x03, 0xD1, 0x3D, 0x67, 0x44, 0x67, +0x50, 0xC1, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF1, 0x5C, 0x9A, 0x01, 0x6B, +0x60, 0xC2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF1, 0x58, 0x9A, 0x00, 0xF4, +0x05, 0x6B, 0x60, 0xCA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xE0, 0xF1, 0x40, 0x9A, +0x00, 0x6B, 0x60, 0xC2, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x12, 0xF0, 0x06, 0x6B, +0x20, 0xF6, 0x64, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF2, 0x48, 0x9A, +0x01, 0x6B, 0x6E, 0xEA, 0x08, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xE0, 0xF1, +0x44, 0x9A, 0x1B, 0x6B, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF2, +0x48, 0x9A, 0x02, 0x6B, 0x6E, 0xEA, 0x10, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0xE0, 0xF1, 0x48, 0x9A, 0x02, 0x6B, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0xE0, 0xF1, 0x44, 0x9A, 0x0B, 0x6B, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0xE0, 0xF1, 0x4C, 0x9A, 0x00, 0xF4, 0x00, 0x6B, 0x60, 0xCA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0xE0, 0xF1, 0x50, 0x9A, 0x70, 0xA1, 0x60, 0xDA, 0x00, 0x6A, 0x40, 0xD9, 0x0D, 0x10, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x20, 0xF6, 0x44, 0x9A, 0x12, 0xF0, 0x04, 0x6B, +0x6E, 0xEA, 0x09, 0x22, 0x40, 0x99, 0x01, 0x4A, 0x40, 0xD9, 0x40, 0x99, 0xE5, 0xF7, 0x1F, 0x5A, +0x58, 0x67, 0xEE, 0x2A, 0x01, 0x10, 0x00, 0x65, 0xB9, 0x65, 0x03, 0x91, 0x02, 0x63, 0x20, 0xE8, +0xFE, 0x63, 0x03, 0xD1, 0x3D, 0x67, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF2, +0x44, 0x9A, 0x40, 0x9A, 0x41, 0xD9, 0x61, 0x99, 0x02, 0x6A, 0x4B, 0xEA, 0x6C, 0xEA, 0x41, 0xD9, +0x00, 0x6A, 0x40, 0xD9, 0x03, 0x10, 0x40, 0x99, 0x01, 0x4A, 0x40, 0xD9, 0x40, 0x99, 0x0A, 0x5A, +0x58, 0x67, 0xF9, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF2, 0x44, 0x9A, +0x61, 0x99, 0x60, 0xDA, 0x00, 0x6A, 0x40, 0xD9, 0x03, 0x10, 0x40, 0x99, 0x01, 0x4A, 0x40, 0xD9, +0x40, 0x99, 0x32, 0x5A, 0x58, 0x67, 0xF9, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x40, 0xF2, 0x5C, 0x9A, 0x40, 0x9A, 0x41, 0xD9, 0x00, 0x6A, 0x40, 0xD9, 0x03, 0x10, 0x40, 0x99, +0x01, 0x4A, 0x40, 0xD9, 0x40, 0x99, 0x32, 0x5A, 0x58, 0x67, 0xF9, 0x2A, 0x61, 0x99, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x60, 0xF2, 0x40, 0x9A, 0x6D, 0xEA, 0x41, 0xD9, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF2, 0x5C, 0x9A, 0x61, 0x99, 0x60, 0xDA, 0x00, 0x6A, +0x40, 0xD9, 0x03, 0x10, 0x40, 0x99, 0x01, 0x4A, 0x40, 0xD9, 0x40, 0x99, 0x32, 0x5A, 0x58, 0x67, +0xF9, 0x2A, 0x61, 0x99, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x60, 0xF2, 0x44, 0x9A, +0x6C, 0xEA, 0x41, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF2, 0x5C, 0x9A, +0x61, 0x99, 0x60, 0xDA, 0x00, 0x6A, 0x40, 0xD9, 0x03, 0x10, 0x40, 0x99, 0x01, 0x4A, 0x40, 0xD9, +0x40, 0x99, 0x32, 0x5A, 0x58, 0x67, 0xF9, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x60, 0xF2, 0x48, 0x9A, 0x40, 0x9A, 0x41, 0xD9, 0x61, 0x99, 0x01, 0x6A, 0x6D, 0xEA, 0x41, 0xD9, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x60, 0xF2, 0x48, 0x9A, 0x61, 0x99, 0x60, 0xDA, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF2, 0x44, 0x9A, 0x40, 0x9A, 0x41, 0xD9, +0x61, 0x99, 0x01, 0x6A, 0x6D, 0xEA, 0x41, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x40, 0xF2, 0x44, 0x9A, 0x61, 0x99, 0x60, 0xDA, 0xB9, 0x65, 0x03, 0x91, 0x02, 0x63, 0x20, 0xE8, +0xFE, 0x63, 0x03, 0xD1, 0x3D, 0x67, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF2, +0x44, 0x9A, 0x40, 0x9A, 0x40, 0xD9, 0x60, 0x99, 0x02, 0x6A, 0x4B, 0xEA, 0x6C, 0xEA, 0x40, 0xD9, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF2, 0x44, 0x9A, 0x60, 0x99, 0x60, 0xDA, +0xB9, 0x65, 0x03, 0x91, 0x02, 0x63, 0x20, 0xE8, 0xFE, 0x63, 0x03, 0xD1, 0x3D, 0x67, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF2, 0x44, 0x9A, 0x40, 0x9A, 0x40, 0xD9, 0x60, 0x99, +0x03, 0x6A, 0x4B, 0xEA, 0x6C, 0xEA, 0x40, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x40, 0xF2, 0x44, 0x9A, 0x60, 0x99, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x60, 0xF2, 0x4C, 0x9A, 0x10, 0xF0, 0x10, 0x6B, 0x60, 0x33, 0x60, 0x33, 0x60, 0xF2, 0x70, 0x9B, +0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x60, 0xF2, 0x48, 0x9A, 0x40, 0x9A, +0x40, 0xD9, 0x60, 0x99, 0x02, 0x6A, 0x6D, 0xEA, 0x40, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x60, 0xF2, 0x48, 0x9A, 0x60, 0x99, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x60, 0xF2, 0x4C, 0x9A, 0x10, 0xF0, 0x10, 0x6B, 0x60, 0x33, 0x60, 0x33, 0x60, 0xF2, +0x74, 0x9B, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF2, 0x44, 0x9A, +0x40, 0x9A, 0x40, 0xD9, 0x60, 0x99, 0x02, 0x6A, 0x6D, 0xEA, 0x40, 0xD9, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x40, 0xF2, 0x44, 0x9A, 0x60, 0x99, 0x60, 0xDA, 0xB9, 0x65, 0x03, 0x91, +0x02, 0x63, 0x20, 0xE8, 0xFE, 0x63, 0x03, 0xD1, 0x3D, 0x67, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x40, 0xF2, 0x44, 0x9A, 0x40, 0x9A, 0x40, 0xD9, 0x60, 0x99, 0x03, 0x6A, 0x4B, 0xEA, +0x6C, 0xEA, 0x40, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF2, 0x44, 0x9A, +0x60, 0x99, 0x60, 0xDA, 0xB9, 0x65, 0x03, 0x91, 0x02, 0x63, 0x20, 0xE8, 0xFC, 0x63, 0x07, 0xD1, +0x3D, 0x67, 0x64, 0x67, 0x45, 0x67, 0x20, 0xF0, 0x60, 0xC1, 0x20, 0xF0, 0x44, 0xC1, 0x00, 0x6A, +0x43, 0xD9, 0x00, 0x6A, 0x48, 0xC1, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF2, +0x50, 0x9A, 0x40, 0x9A, 0x40, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF2, +0x50, 0x9A, 0x00, 0x6B, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF0, +0x00, 0x4A, 0x41, 0xD9, 0x48, 0xA1, 0x45, 0xD9, 0x20, 0xF0, 0x40, 0xA1, 0x04, 0x6B, 0x6E, 0xEA, +0x20, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF2, 0x50, 0xA2, 0x62, 0x67, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF6, 0x0C, 0x4A, 0x44, 0xAA, 0x6E, 0xEA, +0xA0, 0xF1, 0x1D, 0x22, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF6, 0x0C, 0x4A, +0x64, 0xAA, 0xFF, 0x6A, 0x4C, 0xEB, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF2, +0x70, 0xC2, 0x00, 0x6A, 0x43, 0xD9, 0x0E, 0x10, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x60, 0xF2, 0x58, 0x9A, 0x40, 0x9A, 0x45, 0xD9, 0x65, 0x99, 0xFF, 0x6A, 0x6C, 0xEA, 0x40, 0x6B, +0x6E, 0xEA, 0x13, 0x22, 0x63, 0x99, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x60, 0xF2, +0x5C, 0x9A, 0x63, 0xEA, 0x58, 0x67, 0x01, 0x6B, 0x6E, 0xEA, 0x62, 0x67, 0xFF, 0x6A, 0x6C, 0xEA, +0x63, 0x99, 0x01, 0x4B, 0x63, 0xD9, 0xE0, 0x2A, 0x01, 0x10, 0x00, 0x65, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x00, 0xF2, 0x48, 0x9A, 0x10, 0xF0, 0x10, 0x6B, 0x60, 0x33, 0x60, 0x33, +0x60, 0xF2, 0x78, 0x9B, 0x60, 0x9B, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0xC0, 0xF2, 0x40, 0x9A, 0x61, 0x42, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF2, +0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF2, 0x40, 0x9A, 0x80, 0x6B, +0x6E, 0xEA, 0x07, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0x6B, 0xC0, 0xF2, +0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF2, 0x40, 0x9A, 0x10, 0xF0, +0x10, 0x6B, 0x60, 0x33, 0x60, 0x33, 0xC0, 0xF2, 0x60, 0x9B, 0x60, 0x34, 0x10, 0xF0, 0x10, 0x6B, +0x60, 0x33, 0x60, 0x33, 0x80, 0xF2, 0x64, 0x9B, 0x6D, 0xE4, 0x60, 0xDA, 0x01, 0x6A, 0x48, 0xC1, +0x20, 0xF0, 0x40, 0xA1, 0x01, 0x6B, 0x4E, 0xEB, 0x39, 0x23, 0x02, 0x52, 0x78, 0x67, 0x02, 0x23, +0x0A, 0x22, 0xFE, 0x10, 0x02, 0x6B, 0x4E, 0xEB, 0x80, 0xF0, 0x0E, 0x23, 0x04, 0x6B, 0x6E, 0xEA, +0xA0, 0xF0, 0x0A, 0x22, 0xF5, 0x10, 0x20, 0xF0, 0x44, 0xA1, 0x45, 0xD9, 0x45, 0x99, 0x40, 0x32, +0x40, 0x32, 0x00, 0xF5, 0x00, 0x4A, 0x45, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x80, 0xF2, 0x40, 0x9A, 0x65, 0x99, 0x60, 0xDA, 0x00, 0x6A, 0x44, 0xD9, 0x12, 0x10, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF2, 0x40, 0x9A, 0x20, 0xF0, 0x84, 0xA1, 0x64, 0x99, +0x6D, 0xE4, 0x68, 0x33, 0x81, 0x99, 0x6D, 0xE4, 0x60, 0x9B, 0x60, 0xDA, 0x44, 0x99, 0x01, 0x4A, +0x44, 0xD9, 0x44, 0x99, 0x04, 0x5A, 0x58, 0x67, 0xEA, 0x2A, 0xCA, 0x10, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x40, 0xF6, 0x00, 0x4A, 0x41, 0xA2, 0x45, 0xD9, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0xC0, 0xF2, 0x40, 0x9A, 0x61, 0x42, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0xC0, 0xF2, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF2, +0x40, 0x9A, 0x80, 0x6B, 0x6E, 0xEA, 0x07, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x00, 0x6B, 0xC0, 0xF2, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF2, +0x40, 0x9A, 0x10, 0xF0, 0x10, 0x6B, 0x60, 0x33, 0x60, 0x33, 0xC0, 0xF2, 0x60, 0x9B, 0x60, 0x34, +0x65, 0x99, 0x60, 0x33, 0x60, 0x33, 0x6D, 0xE4, 0x41, 0x4B, 0x60, 0xDA, 0x00, 0x6A, 0x45, 0xD9, +0x00, 0x6A, 0x44, 0xD9, 0x14, 0x10, 0x45, 0x99, 0x40, 0x32, 0x45, 0xD9, 0x05, 0x6B, 0x44, 0x99, +0x4F, 0xE3, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF6, 0x00, 0x4A, 0x49, 0xE3, +0x40, 0xA2, 0x65, 0x99, 0x49, 0xE3, 0x45, 0xD9, 0x44, 0x99, 0x01, 0x4A, 0x44, 0xD9, 0x44, 0x99, +0x04, 0x5A, 0x58, 0x67, 0xE8, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF2, +0x40, 0x9A, 0x65, 0x99, 0x60, 0xDA, 0x6C, 0x10, 0x20, 0xF0, 0x44, 0xA1, 0x45, 0xD9, 0x45, 0x99, +0x40, 0x32, 0x40, 0x32, 0x45, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF2, +0x40, 0x9A, 0x85, 0x99, 0x00, 0xF2, 0x02, 0x6B, 0x8D, 0xEB, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x80, 0xF2, 0x40, 0x9A, 0x20, 0xF0, 0x64, 0xA1, 0x68, 0x33, 0x81, 0x99, +0x6D, 0xE4, 0x60, 0x9B, 0x60, 0xDA, 0x4C, 0x10, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0xC0, 0xF2, 0x40, 0x9A, 0x61, 0x42, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF2, +0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF2, 0x40, 0x9A, 0x80, 0x6B, +0x6E, 0xEA, 0x07, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0x6B, 0xC0, 0xF2, +0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF6, 0x0C, 0x4A, 0x44, 0xAA, +0x01, 0x6B, 0x6E, 0xEA, 0x16, 0x2A, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF2, +0x40, 0x9A, 0x10, 0xF0, 0x10, 0x6B, 0x60, 0x33, 0x60, 0x33, 0xC0, 0xF2, 0x60, 0x9B, 0x60, 0x34, +0x10, 0xF0, 0x10, 0x6B, 0x60, 0x33, 0x60, 0x33, 0x80, 0xF2, 0x68, 0x9B, 0x6D, 0xE4, 0x60, 0xDA, +0x0F, 0x10, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF2, 0x40, 0x9A, 0x10, 0xF0, +0x10, 0x6B, 0x60, 0x33, 0x60, 0x33, 0xC0, 0xF2, 0x60, 0x9B, 0x60, 0x33, 0x24, 0x4B, 0x60, 0xDA, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF2, 0x40, 0x9A, 0x61, 0x42, 0x10, 0xF0, +0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xC0, 0xF2, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0xC0, 0xF2, 0x40, 0x9A, 0x80, 0x6B, 0x6E, 0xEA, 0x07, 0x2A, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x00, 0x6B, 0xC0, 0xF2, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, +0x40, 0x32, 0x80, 0xF2, 0x40, 0x9A, 0x10, 0xF0, 0x10, 0x6B, 0x60, 0x33, 0x60, 0x33, 0xC0, 0xF2, +0x60, 0x9B, 0x60, 0x33, 0x25, 0x4B, 0x60, 0xDA, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x80, 0xF2, 0x4C, 0x9A, 0x40, 0x9A, 0x45, 0xD9, 0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, +0x80, 0xF2, 0x4C, 0x9A, 0x85, 0x99, 0x01, 0x6B, 0x8D, 0xEB, 0x60, 0xDA, 0x01, 0x10, 0x00, 0x65, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x00, 0xF2, 0x50, 0x9A, 0x60, 0x99, 0x60, 0xDA, +0xB9, 0x65, 0x07, 0x91, 0x04, 0x63, 0x20, 0xE8, 0xFD, 0x63, 0x05, 0xD1, 0x3D, 0x67, 0x86, 0xD9, +0xA7, 0xD9, 0x00, 0x6A, 0x41, 0xD9, 0x41, 0x99, 0x42, 0xD9, 0x46, 0x99, 0x43, 0xD9, 0x34, 0x10, +0x41, 0xA1, 0x30, 0x5A, 0x58, 0x67, 0x08, 0x2A, 0x41, 0xA1, 0x3A, 0x5A, 0x58, 0x67, 0x04, 0x22, +0x41, 0xA1, 0xD0, 0x4A, 0x40, 0xC1, 0x1A, 0x10, 0x41, 0xA1, 0x61, 0x5A, 0x58, 0x67, 0x08, 0x2A, +0x41, 0xA1, 0x67, 0x5A, 0x58, 0x67, 0x04, 0x22, 0x41, 0xA1, 0xA9, 0x4A, 0x40, 0xC1, 0x0E, 0x10, +0x41, 0xA1, 0x41, 0x5A, 0x58, 0x67, 0x08, 0x2A, 0x41, 0xA1, 0x47, 0x5A, 0x58, 0x67, 0x04, 0x22, +0x41, 0xA1, 0xC9, 0x4A, 0x40, 0xC1, 0x02, 0x10, 0x00, 0x6A, 0x1F, 0x10, 0x41, 0x99, 0x50, 0x33, +0x40, 0xA1, 0x49, 0xE3, 0x42, 0xD9, 0x62, 0x99, 0x41, 0x99, 0x43, 0xEB, 0x58, 0x67, 0x02, 0x22, +0x00, 0x6A, 0x13, 0x10, 0x42, 0x99, 0x41, 0xD9, 0x43, 0x99, 0x40, 0xA2, 0x41, 0xC1, 0x00, 0x6A, +0x61, 0xA1, 0x01, 0x23, 0x01, 0x6A, 0xFF, 0x6B, 0x6C, 0xEA, 0x63, 0x99, 0x01, 0x4B, 0x63, 0xD9, +0xBF, 0x2A, 0x47, 0x99, 0x61, 0x99, 0x60, 0xDA, 0x01, 0x6A, 0xB9, 0x65, 0x05, 0x91, 0x03, 0x63, +0x20, 0xE8, 0x00, 0x65, 0xF3, 0x63, 0x19, 0x62, 0x18, 0xD1, 0x04, 0x01, 0x96, 0xD9, 0xB7, 0xD9, +0xD8, 0xD9, 0x56, 0x99, 0x4B, 0xD9, 0xB5, 0x11, 0x57, 0x99, 0x40, 0x82, 0x25, 0x6B, 0x6E, 0xEA, +0x10, 0x22, 0x56, 0x99, 0x08, 0x22, 0x57, 0x99, 0x60, 0x82, 0x4B, 0x99, 0x60, 0xC2, 0x4B, 0x99, +0x01, 0x4A, 0x4B, 0xD9, 0xA3, 0x11, 0x57, 0x99, 0x40, 0x82, 0x82, 0x67, 0x00, 0x18, 0xAD, 0x02, +0x9D, 0x11, 0x57, 0x99, 0x01, 0x4A, 0x57, 0xD9, 0x57, 0x99, 0x40, 0x82, 0x73, 0x6B, 0x6E, 0xEA, +0x1D, 0x2A, 0x58, 0x99, 0x40, 0x9A, 0x4C, 0xD9, 0x58, 0x99, 0x04, 0x4A, 0x58, 0xD9, 0x12, 0x10, +0x56, 0x99, 0x08, 0x22, 0x4C, 0x99, 0x60, 0x82, 0x4B, 0x99, 0x60, 0xC2, 0x4B, 0x99, 0x01, 0x4A, +0x4B, 0xD9, 0x05, 0x10, 0x4C, 0x99, 0x40, 0x82, 0x82, 0x67, 0x00, 0x18, 0xAD, 0x02, 0x4C, 0x99, +0x01, 0x4A, 0x4C, 0xD9, 0x4C, 0x99, 0x40, 0x82, 0xEB, 0x2A, 0x78, 0x11, 0x47, 0x41, 0x2D, 0x4A, +0x4A, 0xD9, 0x00, 0x6A, 0x49, 0xD9, 0x04, 0x6A, 0x48, 0xD9, 0x57, 0x99, 0x40, 0x82, 0x23, 0x6B, +0x6E, 0xEA, 0x05, 0x2A, 0x01, 0x6A, 0x49, 0xD9, 0x57, 0x99, 0x01, 0x4A, 0x57, 0xD9, 0x57, 0x99, +0x40, 0x82, 0x68, 0x6B, 0x6E, 0xEA, 0x05, 0x2A, 0x0C, 0x6A, 0x48, 0xD9, 0x57, 0x99, 0x01, 0x4A, +0x57, 0xD9, 0x57, 0x99, 0x40, 0x82, 0x68, 0x6B, 0x6E, 0xEA, 0x05, 0x2A, 0x04, 0x6A, 0x48, 0xD9, +0x57, 0x99, 0x01, 0x4A, 0x57, 0xD9, 0x57, 0x99, 0x60, 0x82, 0x20, 0x6A, 0x6D, 0xEA, 0x00, 0xF6, +0x40, 0x32, 0x00, 0xF6, 0x43, 0x32, 0x78, 0x6B, 0x6E, 0xEA, 0x4F, 0x2A, 0x58, 0x99, 0x47, 0xD9, +0x47, 0x99, 0x40, 0x9A, 0x46, 0xD9, 0x47, 0x99, 0x04, 0x4A, 0x47, 0xD9, 0x57, 0x99, 0x60, 0x82, +0xFF, 0x6A, 0x6C, 0xEA, 0x62, 0x67, 0x20, 0x6A, 0x6C, 0xEA, 0x45, 0xD9, 0x47, 0x99, 0x58, 0xD9, +0x49, 0x99, 0x36, 0x22, 0x4A, 0x99, 0x30, 0x6B, 0x60, 0xC2, 0x4A, 0x99, 0x01, 0x4A, 0x4A, 0xD9, +0x45, 0x99, 0x00, 0xF6, 0x40, 0x33, 0x00, 0xF6, 0x63, 0x33, 0x58, 0x6A, 0x6D, 0xEA, 0x00, 0xF6, +0x40, 0x33, 0x00, 0xF6, 0x63, 0x33, 0x4A, 0x99, 0x60, 0xC2, 0x4A, 0x99, 0x01, 0x4A, 0x4A, 0xD9, +0x1F, 0x10, 0x66, 0x99, 0x48, 0x99, 0x67, 0xEA, 0x0F, 0x6A, 0x4C, 0xEB, 0x10, 0xF0, 0x10, 0x6A, +0x40, 0x32, 0x40, 0x32, 0x80, 0xF2, 0x1C, 0x4A, 0x49, 0xE3, 0x60, 0x82, 0x45, 0x99, 0x00, 0xF6, +0x40, 0x32, 0x00, 0xF6, 0x43, 0x32, 0x6D, 0xEA, 0x00, 0xF6, 0x40, 0x33, 0x00, 0xF6, 0x63, 0x33, +0x4A, 0x99, 0x60, 0xC2, 0x4A, 0x99, 0x01, 0x4A, 0x4A, 0xD9, 0x48, 0x99, 0xFC, 0x4A, 0x48, 0xD9, +0x48, 0x99, 0x00, 0x52, 0x58, 0x67, 0xDD, 0x22, 0xDE, 0x10, 0x57, 0x99, 0x40, 0x82, 0x64, 0x6B, +0x6E, 0xEA, 0x62, 0x2A, 0x58, 0x99, 0x40, 0x9A, 0x44, 0xD9, 0x58, 0x99, 0x04, 0x4A, 0x58, 0xD9, +0x44, 0x99, 0x00, 0x52, 0x58, 0x67, 0x09, 0x22, 0x4A, 0x99, 0x2D, 0x6B, 0x60, 0xC2, 0x4A, 0x99, +0x01, 0x4A, 0x4A, 0xD9, 0x44, 0x99, 0x4B, 0xEA, 0x44, 0xD9, 0x4A, 0x99, 0x4C, 0xD9, 0x64, 0x99, +0x10, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xA0, 0xF2, 0x50, 0x9A, 0x58, 0xEB, 0x10, 0xEA, +0x4B, 0x34, 0xC0, 0xF7, 0x63, 0x32, 0x4B, 0xE4, 0x44, 0x32, 0x48, 0x34, 0x89, 0xE2, 0x4B, 0xE3, +0xFF, 0x6B, 0x6C, 0xEA, 0x67, 0x42, 0x29, 0x4B, 0xFF, 0x6A, 0x6C, 0xEA, 0x00, 0xF6, 0x40, 0x33, +0x00, 0xF6, 0x63, 0x33, 0x4A, 0x99, 0x60, 0xC2, 0x4A, 0x99, 0x01, 0x4A, 0x4A, 0xD9, 0x44, 0x99, +0x10, 0xF0, 0x10, 0x6B, 0x60, 0x33, 0x60, 0x33, 0xA0, 0xF2, 0x70, 0x9B, 0x78, 0xEA, 0x10, 0xEB, +0x6B, 0x33, 0xC0, 0xF7, 0x43, 0x32, 0x4B, 0xE3, 0x44, 0xD9, 0x44, 0x99, 0xD0, 0x2A, 0x4A, 0x99, +0x43, 0xD9, 0x11, 0x10, 0x43, 0x99, 0x40, 0x82, 0x44, 0xD9, 0x4C, 0x99, 0x60, 0x82, 0x43, 0x99, +0x60, 0xC2, 0x44, 0x99, 0x00, 0xF6, 0x40, 0x33, 0x00, 0xF6, 0x63, 0x33, 0x4C, 0x99, 0x60, 0xC2, +0x4C, 0x99, 0x01, 0x4A, 0x4C, 0xD9, 0x43, 0x99, 0xFF, 0x4A, 0x43, 0xD9, 0x63, 0x99, 0x4C, 0x99, +0x63, 0xEA, 0x58, 0x67, 0xE7, 0x2A, 0x77, 0x10, 0x57, 0x99, 0x40, 0x82, 0x40, 0x6B, 0x6E, 0xEA, +0x2C, 0x2A, 0x58, 0x99, 0x41, 0xD9, 0x41, 0x99, 0x40, 0x9A, 0x52, 0xD9, 0x41, 0x99, 0x04, 0x4A, +0x41, 0xD9, 0x41, 0x99, 0x58, 0xD9, 0x47, 0x41, 0x41, 0x4A, 0x42, 0xD9, 0x13, 0x10, 0x42, 0x99, +0x40, 0xA2, 0x8A, 0x99, 0x10, 0xF0, 0x10, 0x6B, 0x60, 0x33, 0x60, 0x33, 0x80, 0xF2, 0x10, 0x4B, +0xA3, 0x67, 0xC2, 0x67, 0x00, 0x18, 0x7C, 0x10, 0x6A, 0x99, 0x49, 0xE3, 0x4A, 0xD9, 0x42, 0x99, +0x01, 0x4A, 0x42, 0xD9, 0x47, 0x41, 0x41, 0x4A, 0x64, 0x42, 0x42, 0x99, 0x63, 0xEA, 0x58, 0x67, +0xE6, 0x2A, 0x4A, 0x99, 0xFF, 0x4A, 0x4A, 0xD9, 0x46, 0x10, 0x57, 0x99, 0x40, 0x82, 0x21, 0x6B, +0x6E, 0xEA, 0x26, 0x2A, 0x58, 0x99, 0x40, 0x9A, 0x4C, 0xD9, 0x58, 0x99, 0x04, 0x4A, 0x58, 0xD9, +0x4C, 0x99, 0x06, 0x4A, 0x40, 0xD9, 0x13, 0x10, 0x4C, 0x99, 0x40, 0x82, 0x8A, 0x99, 0x10, 0xF0, +0x10, 0x6B, 0x60, 0x33, 0x60, 0x33, 0x80, 0xF2, 0x14, 0x4B, 0xA3, 0x67, 0xC2, 0x67, 0x00, 0x18, +0x7C, 0x10, 0x6A, 0x99, 0x49, 0xE3, 0x4A, 0xD9, 0x4C, 0x99, 0x01, 0x4A, 0x4C, 0xD9, 0x6C, 0x99, +0x40, 0x99, 0x43, 0xEB, 0x58, 0x67, 0xE8, 0x2A, 0x4A, 0x99, 0xFF, 0x4A, 0x4A, 0xD9, 0x1B, 0x10, +0x57, 0x99, 0x40, 0x82, 0x63, 0x6B, 0x6E, 0xEA, 0x0F, 0x2A, 0x58, 0x99, 0x40, 0x9A, 0x00, 0xF6, +0x40, 0x33, 0x00, 0xF6, 0x63, 0x33, 0x4A, 0x99, 0x60, 0xC2, 0x4A, 0x99, 0x01, 0x4A, 0x4A, 0xD9, +0x58, 0x99, 0x04, 0x4A, 0x58, 0xD9, 0x07, 0x10, 0x57, 0x99, 0x60, 0x82, 0x4A, 0x99, 0x60, 0xC2, +0x4A, 0x99, 0x01, 0x4A, 0x4A, 0xD9, 0x47, 0x41, 0x2D, 0x4A, 0x4C, 0xD9, 0x12, 0x10, 0x56, 0x99, +0x08, 0x22, 0x4C, 0x99, 0x60, 0x82, 0x4B, 0x99, 0x60, 0xC2, 0x4B, 0x99, 0x01, 0x4A, 0x4B, 0xD9, +0x05, 0x10, 0x4C, 0x99, 0x40, 0x82, 0x82, 0x67, 0x00, 0x18, 0xAD, 0x02, 0x4C, 0x99, 0x01, 0x4A, +0x4C, 0xD9, 0x6C, 0x99, 0x4A, 0x99, 0x43, 0xEB, 0x58, 0x67, 0xE9, 0x2A, 0x57, 0x99, 0x01, 0x4A, +0x57, 0xD9, 0x57, 0x99, 0x40, 0x82, 0x5F, 0xF6, 0x07, 0x2A, 0x56, 0x99, 0x03, 0x22, 0x4B, 0x99, +0x00, 0x6B, 0x60, 0xC2, 0x6B, 0x99, 0x56, 0x99, 0x4B, 0xE3, 0xB9, 0x65, 0x15, 0x97, 0x14, 0x91, +0x0B, 0x63, 0x00, 0xEF, 0xFD, 0x63, 0x05, 0x62, 0x04, 0xD1, 0x04, 0x01, 0xA3, 0xD9, 0xC4, 0xD9, +0xE5, 0xD9, 0x82, 0xD9, 0x62, 0x99, 0x47, 0x41, 0x01, 0x4A, 0x04, 0x4A, 0x00, 0x6C, 0xA3, 0x67, +0xC2, 0x67, 0x00, 0x18, 0x89, 0x0F, 0xB9, 0x65, 0x01, 0x97, 0x00, 0x91, 0x01, 0x63, 0x00, 0xEF, +0xFD, 0x63, 0x05, 0x62, 0x04, 0xD1, 0x04, 0x01, 0x82, 0xD9, 0xC4, 0xD9, 0xE5, 0xD9, 0xA3, 0xD9, +0x63, 0x99, 0x47, 0x41, 0x05, 0x4A, 0x04, 0x4A, 0x82, 0x99, 0xA3, 0x67, 0xC2, 0x67, 0x00, 0x18, +0x89, 0x0F, 0xB9, 0x65, 0x01, 0x97, 0x00, 0x91, 0x01, 0x63, 0x00, 0xEF, +}; + + +u8 NFCFWDMEM[]={ +0x58, 0x53, 0x9B, 0x18, 0x22, 0xB6, 0x28, 0x80, 0x3C, 0x48, 0x00, 0x00, 0xE1, 0x11, 0x12, 0x00, +0x01, 0x03, 0xA0, 0x10, 0x44, 0x03, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x93, 0x84, 0x00, 0x00, 0x9F, +0x08, 0x10, 0x00, 0x90, 0x1C, 0x10, 0x00, 0x90, 0x60, 0x20, 0x00, 0x90, 0x48, 0x20, 0x00, 0x90, +0x04, 0x20, 0x00, 0x90, 0x00, 0x20, 0x00, 0x90, 0x54, 0x00, 0x00, 0x94, 0xFF, 0xFF, 0x0F, 0x00, +0x50, 0x00, 0x00, 0x94, 0x74, 0x00, 0x00, 0x94, 0x70, 0x01, 0x00, 0x94, 0x58, 0x00, 0x00, 0x94, +0xFF, 0xAF, 0x0E, 0x00, 0x1C, 0x04, 0x00, 0x94, 0x5C, 0x00, 0x00, 0x94, 0x08, 0x08, 0x00, 0x94, +0xFF, 0xFF, 0xFE, 0xFF, 0x6C, 0x00, 0x00, 0x94, 0xFF, 0xFF, 0x03, 0xFC, 0x00, 0x00, 0x34, 0x00, +0x00, 0x00, 0x00, 0x20, 0x04, 0x04, 0x00, 0x94, 0x70, 0x00, 0x00, 0x94, 0x28, 0x00, 0x00, 0x94, +0x04, 0x00, 0x00, 0x90, 0x0C, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x90, 0x14, 0x00, 0x00, 0x90, +0x10, 0x10, 0x00, 0x90, 0x0C, 0x10, 0x00, 0x90, 0x24, 0x10, 0x00, 0x90, 0x20, 0x10, 0x00, 0x90, +0x54, 0x00, 0x00, 0x9F, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x9F, 0x0C, 0x00, 0x00, 0x9F, +0xFC, 0x00, 0x00, 0x9F, 0x64, 0x00, 0x00, 0x9F, 0x60, 0x00, 0x00, 0x9F, 0x7C, 0x00, 0x00, 0x90, +0x2C, 0x00, 0x00, 0x94, 0x14, 0x00, 0x00, 0x9F, 0xFF, 0xFF, 0xFF, 0xFE, 0x20, 0x01, 0x00, 0x94, +0x24, 0x01, 0x00, 0x94, 0x22, 0x00, 0x00, 0x93, 0x20, 0x00, 0x00, 0x93, 0x10, 0x00, 0x00, 0x93, +0x0C, 0x00, 0x00, 0x94, 0x0A, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x30, 0x0C, 0x00, 0x00, 0x93, +0x00, 0x10, 0x00, 0x90, 0x14, 0x10, 0x00, 0x90, 0xC4, 0x01, 0x64, 0xB8, 0x68, 0x65, 0x6C, 0x6C, +0x6F, 0x0A, 0x00, 0x00, 0x6F, 0x26, 0x00, 0x80, 0x9F, 0x26, 0x00, 0x80, 0x79, 0x28, 0x00, 0x80, +0x27, 0x27, 0x00, 0x80, 0x79, 0x28, 0x00, 0x80, 0x79, 0x28, 0x00, 0x80, 0x79, 0x28, 0x00, 0x80, +0x79, 0x28, 0x00, 0x80, 0x79, 0x28, 0x00, 0x80, 0x79, 0x28, 0x00, 0x80, 0x79, 0x28, 0x00, 0x80, +0x79, 0x28, 0x00, 0x80, 0xCF, 0x27, 0x00, 0x80, 0x4D, 0x26, 0x00, 0x80, 0x14, 0x00, 0x00, 0x9F, +0x12, 0x00, 0x00, 0x93, 0x14, 0x00, 0x00, 0x93, 0x16, 0x00, 0x00, 0x93, 0x10, 0x00, 0x00, 0x93, +0x26, 0x00, 0x00, 0x93, 0x5C, 0x00, 0x00, 0x94, 0x0C, 0x00, 0x00, 0x94, 0x08, 0x00, 0x00, 0x93, +0x0C, 0x00, 0x00, 0x93, 0x20, 0x00, 0x00, 0x9F, 0x00, 0x00, 0x34, 0x12, 0x01, 0x00, 0x34, 0x12, +0x22, 0x00, 0x00, 0x93, 0x18, 0x00, 0x00, 0x93, 0xFC, 0x00, 0x00, 0x9F, 0x80, 0x00, 0x00, 0x9F, +0x84, 0x00, 0x00, 0x9F, 0x0C, 0x00, 0x00, 0x9F, 0x03, 0x01, 0xD0, 0x00, 0x50, 0x00, 0x00, 0x9F, +0xF2, 0x00, 0x00, 0xA0, 0x08, 0x00, 0x00, 0x9F, 0x10, 0x00, 0x00, 0x9F, 0x02, 0x01, 0x70, 0x00, +0x01, 0x01, 0x70, 0x00, 0x88, 0x00, 0x00, 0x9F, 0x6C, 0xB0, 0x6C, 0xB0, 0x24, 0x01, 0x00, 0x94, +0x00, 0x00, 0x20, 0x00, 0x2C, 0x00, 0x00, 0x94, 0x28, 0x00, 0x00, 0x94, 0x68, 0x01, 0x00, 0x94, +0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFE, 0xFF, 0x02, 0x00, 0x6C, 0x00, 0x00, 0x94, +0x00, 0x00, 0x02, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x20, 0x01, 0x00, 0x94, 0x70, 0x00, 0x00, 0x94, +0x00, 0xD0, 0x80, 0x3D, 0x00, 0x90, 0x80, 0x3D, 0x5C, 0x00, 0x00, 0x9F, 0xFF, 0xFF, 0xFF, 0x00, +0x58, 0x00, 0x00, 0x9F, 0x25, 0x00, 0x01, 0x00, 0x24, 0x00, 0x01, 0x00, 0x68, 0x00, 0x00, 0x9F, +0x25, 0x64, 0x2E, 0x00, 0x25, 0x68, 0x68, 0x58, 0x3A, 0x00, 0x00, 0x00, 0x30, 0x31, 0x32, 0x33, +0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x00, 0x00, 0x00, 0x00, +0x67, 0x66, 0x66, 0x66, +}; + + +//NFC_ADAPTER NFCAdapter; +IRQ_FUN LpPeriIrqFunTable[32]; +u32 LpPeriIrqDataTable[32]; + +VOID +WriteA2NMailbox( + IN VOID *pNFCAdapte +) +{ + PNFC_ADAPTER pNFCAdp = (PNFC_ADAPTER) pNFCAdapte; + u8 i = 0; + u32 RegTemp; + u32 TimeIdx = 0; + + if (!(pNFCAdp->A2NMAILQ[pNFCAdp->A2NWQRIdx].Response)) { + pNFCAdp->A2NMAILQ[pNFCAdp->A2NWQRIdx].Content[0] = + (pNFCAdp->A2NMAILQ[pNFCAdp->A2NWQRIdx].Content[0]|(pNFCAdp->A2NSeq << 8)); + pNFCAdp->A2NSeq++; + } + + for(i = 0; i < pNFCAdp->A2NMAILQ[pNFCAdp->A2NWQRIdx].Length; i++) { + HalDelayUs(30); + HAL_WRITE32(NFC_INTERFACE_BASE, 0x10, pNFCAdp->A2NMAILQ[pNFCAdp->A2NWQRIdx].Content[i]); + } + + HalDelayUs(30); + RegTemp = HAL_READ32(NFC_INTERFACE_BASE,0x24)|BIT1; + HAL_WRITE32(NFC_INTERFACE_BASE, 0x24, RegTemp); + + RegTemp = (HAL_READ32(NFC_INTERFACE_BASE,0x24)&(~BIT1)); + HAL_WRITE32(NFC_INTERFACE_BASE, 0x24, RegTemp); +} + +VOID +A2NWriteInQueue( + IN VOID *pNFCAdapte, + IN VOID *pBuff +) +{ + PNFC_ADAPTER pNFCAdp = (PNFC_ADAPTER) pNFCAdapte; + PA2N_MAILBOX_Q pA2NWData = (PA2N_MAILBOX_Q) pBuff; + u8 Idx; + + //Q full handle + if ((pNFCAdp->A2NWQWIdx == (pNFCAdp->A2NWQRIdx - 1))|| + ((pNFCAdp->A2NWQRIdx == 0)&&(pNFCAdp->A2NWQWIdx == N2A_Q_LENGTH - 1))){ + + DBG_8195A("A2N write Mailbox Queue full !!\n"); + } + + for (Idx = 0; Idx < pA2NWData->Length; Idx++) { + pNFCAdp->A2NMAILQ[pNFCAdp->A2NWQWIdx].Content[Idx] = pA2NWData->Content[Idx]; + } + + pNFCAdp->A2NMAILQ[pNFCAdp->A2NWQWIdx].Length = pA2NWData->Length; + pNFCAdp->A2NMAILQ[pNFCAdp->A2NWQWIdx].Response = pA2NWData->Response; + pNFCAdp->A2NWQWIdx++; + + if (pNFCAdp->A2NWQWIdx == N2A_Q_LENGTH){ + pNFCAdp->A2NWQWIdx = 0; + } + + //check qu and enable task + if (pNFCAdp->A2NWQWIdx != pNFCAdp->A2NWQRIdx){ + pNFCAdp->A2NWMailBox = TRUE; + RtlUpSema(&(pNFCAdp->VeriSema)); + } + + + #if 0 + { + u8 i = 0; + u8 j = 0; + DBG_8195A("A2N idx = 0x%x \n", pNFCAdp->A2NWMailBox); + DBG_8195A("A2N write R idx = 0x%x \n", pNFCAdp->A2NWQRIdx); + DBG_8195A("A2N write W idx = 0x%x \n", pNFCAdp->A2NWQWIdx); + + for(i = 0;iA2NWQWIdx;i++) { + + DBG_8195A("A2N write queue %d, length = 0x%x \n", i, pNFCAdp->A2NMAILQ[i].Length); + DBG_8195A("A2N write queue %d, response = 0x%x \n", i, pNFCAdp->A2NMAILQ[i].Response); + for(j = 0;j < 5; j++) { + DBG_8195A("A2N write queue %d, data = 0x%x \n", i, pNFCAdp->A2NMAILQ[i].Content[j]); + } + } + } + #endif +} + +VOID +A2NWriteDeQueue( + IN VOID *pNFCAdapte +) +{ + PNFC_ADAPTER pNFCAdp = (PNFC_ADAPTER) pNFCAdapte; + u32 TimeIdx = 0; + + while(((HAL_READ32(NFC_INTERFACE_BASE, 0x14)>>1) & 0xf)!= 0){ + DBG_8195A("A2N Mailbox W MISC 0x%08x\n", ((HAL_READ32(NFC_INTERFACE_BASE, 0x14)>>1) & 0xf)); + HalDelayUs(30); + TimeIdx++; + if (TimeIdx > 10000){ + + DBG_8195A("A2N Mailbox write timeout\n"); + + //check qu and enable task + if (pNFCAdp->A2NWQWIdx != pNFCAdp->A2NWQRIdx){ + pNFCAdp->A2NWMailBox = TRUE; + RtlUpSema(&(pNFCAdp->VeriSema)); + } + return; + } + }; + + WriteA2NMailbox(pNFCAdapte); + + pNFCAdp->A2NWQRIdx++; + if (pNFCAdp->A2NWQRIdx == N2A_Q_LENGTH) { + pNFCAdp->A2NWQRIdx = 0; + } + + //check qu and enable task + if (pNFCAdp->A2NWQWIdx != pNFCAdp->A2NWQRIdx){ + pNFCAdp->A2NWMailBox = TRUE; + RtlUpSema(&(pNFCAdp->VeriSema)); + } + else { + pNFCAdp->A2NWMailBox = FALSE; + } +} + + +//cmd 0 +VOID +N2AReadTag( + IN VOID *pNFCAdapte, + IN u8 N2ARPage +) +{ + PNFC_ADAPTER pNFCAdp = (PNFC_ADAPTER)pNFCAdapte; + + nfc_tagread_callback (pNFCAdp, N2ARPage); +} + +VOID +A2NWriteCatch( + IN VOID *pNFCAdapte, + IN u8 N2AWPage, + IN u8 Length, + IN u32 *WData +) +{ + PNFC_ADAPTER pNFCAdp = (PNFC_ADAPTER)pNFCAdapte; + u8 Idx; + A2N_MAILBOX_Q DataTemp; + + DataTemp.Length = Length+1; + DataTemp.Response = 0; + DataTemp.Content[0] = (CATCH_WRITE|(DataTemp.Length<<5)|(N2AWPage<<16)); + for (Idx = 0; Idx < Length; Idx++) { + DataTemp.Content[Idx+1] = WData[Idx]; + } + A2NWriteInQueue(pNFCAdp, &DataTemp); +} + + +VOID +A2NReadCatch( + IN VOID *pNFCAdapte, + IN u8 A2NRPage +) +{ + u8 Idx; + A2N_MAILBOX_Q DataTemp; + + DataTemp.Length = 1; + DataTemp.Response = 0; + DataTemp.Content[0] = (CATCH_READ|(DataTemp.Length<<5)|(A2NRPage<<16)); + + A2NWriteInQueue((PNFC_ADAPTER)pNFCAdapte, &DataTemp); +} + +//cmd 1 +VOID +N2AWriteTag( + IN VOID *pNFCAdapte, + IN u8 N2AWPage +) +{ + PNFC_ADAPTER pNFCAdp = (PNFC_ADAPTER)pNFCAdapte; + u32 wr_data; + + wr_data = HAL_READ32(NFC_INTERFACE_BASE, 0x18); + nfc_tagwrite_callback(pNFCAdp, N2AWPage, wr_data); +} + + +//cmd 3 +VOID +N2AReadCatch( + IN VOID *pNFCAdapte, + IN u8 N2ACatchRPage +) +{ + PNFC_ADAPTER pNFCAdp = (PNFC_ADAPTER)pNFCAdapte; + u32 TagBuf[4]; + + TagBuf[0] = HAL_READ32(NFC_INTERFACE_BASE, 0x18); + TagBuf[1] = HAL_READ32(NFC_INTERFACE_BASE, 0x18); + TagBuf[2] = HAL_READ32(NFC_INTERFACE_BASE, 0x18); + TagBuf[3] = HAL_READ32(NFC_INTERFACE_BASE, 0x18); + + nfc_cache_read_callback(pNFCAdp, N2ACatchRPage, TagBuf); +} + +//cmd 4 +VOID +NFCReaderPresent( + IN VOID *pNFCAdapte, + IN u8 State +) +{ + PNFC_ADAPTER pNFCAdp = (PNFC_ADAPTER)pNFCAdapte; + + if (State) { + DBG_8195A("NFC Reader Present\n"); + + //call app + nfc_event_callback(pNFCAdp, NFC_HAL_READER_PRESENT); + } +} + + +//cmd 5 +VOID +N2AMailboxState( + IN VOID *pNFCAdapte, + IN u8 State, + IN u8 Seq +) +{ + A2N_MAILBOX_Q MailData; + PNFC_ADAPTER pNFCAdp = (PNFC_ADAPTER)pNFCAdapte; + + pNFCAdp->N2ABoxOpen = State; + DBG_8195A("N2A Mailbox State = %d\n", pNFCAdp->N2ABoxOpen); + + if (State) { + MailData.Length = 1; + MailData.Response = 1; + MailData.Content[0] = (CONFIRM_N2A_BOX_STATE)|(0x1<<5)|((Seq|BIT7)<<8)|(ON<<16); + //WriteA2NMailbox(1, &MailData, 1); + A2NWriteInQueue(pNFCAdp, &MailData); + } +} + + +//cmd 6 +VOID +NFC25MClkReq( + IN VOID *pNFCAdapte, + IN u8 OP, + IN u8 Seq +) +{ + PNFC_ADAPTER pNFCAdp = (PNFC_ADAPTER)pNFCAdapte; + A2N_MAILBOX_Q MailData; + u32 RegTemp = HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_SYSPLL_CTRL1); + if (OP) { + RegTemp = ((RegTemp & 0xFFFFC7FF)|(BIT_SYS_SYSPLL_CKSDR_EN|BIT_SYS_SYSPLL_CKSDR_DIV(2))); + } + else { + RegTemp = RegTemp & 0xFFFFC7FF; + } + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_SYSPLL_CTRL1, RegTemp); + + //write mailbox + MailData.Length = 1; + MailData.Response = 1; + MailData.Content[0] = (EXT_CLK_RSP)|(0x1<<5)|((Seq|BIT7)<<8)|(ON<<16); + //WriteA2NMailbox(pNFCAdp, &MailData); + A2NWriteInQueue(pNFCAdp, &MailData); +} + + +VOID +NFCRoutine( + IN VOID *pNFCAdapte +) +{ + u32 N2ARData, N2AMISC; + u8 N2ARB2; + u8 Seq; + PNFC_ADAPTER pNFCAdp = (PNFC_ADAPTER)pNFCAdapte; + + //N2A MEM DATA + if (pNFCAdp->NFCIsr & (BIT0|BIT6)) { + pNFCAdp->NFCIsr &= ~(BIT6|BIT0); + + N2AMISC = ((HAL_READ32(NFC_INTERFACE_BASE, 0x1c)>>1)&0xf); + //DBG_8195A("NFC 0x1C = 0x%x \n", N2AMISC); + while (N2AMISC != 0){ + + N2ARData = HAL_READ32(NFC_INTERFACE_BASE, 0x18); + N2ARB2 = ((u8)(N2ARData>>16)); + Seq = (u8)(N2ARData>>8); + //DBG_8195A("NFC 0x18 = 0x%x \n", N2ARData); + + switch(N2ARData & 0x1F) { + case TAG_READ: + //get data + N2AReadTag(pNFCAdapte, N2ARB2); + //call app + + break; + case TAG_WRITE: + //get data + N2AWriteTag(pNFCAdapte, N2ARB2); + //call app + + break; + case CATCH_READ_DATA: + //get data + N2AReadCatch(pNFCAdapte, N2ARB2); + //call app + + break; + case NFC_R_PRESENT: + NFCReaderPresent(pNFCAdapte, N2ARB2); + break; + case N2A_MAILBOX_STATE: + N2AMailboxState(pNFCAdapte, N2ARB2, Seq); + break; + case EXT_CLK_REQ: + NFC25MClkReq(pNFCAdapte, N2ARB2, Seq); + break; + default: + break; + } + + N2AMISC = ((HAL_READ32(NFC_INTERFACE_BASE, 0x1c)>>1)&0xf); + } + } + + if(pNFCAdp->A2NWMailBox){ + A2NWriteDeQueue(pNFCAdp); + } + //enable int + //A2NWRITE32(0x68, 0xff00); +} + + +VOID +NFCTaskHandle( + IN VOID *pNFCAdapte +) +{ + PNFC_ADAPTER pNFCAdp = (PNFC_ADAPTER)pNFCAdapte; + + #if !TASK_SCHEDULER_DISABLED//#if !TASK_SCHEDULER_DISABLED(>>) + for (;;)//start of for(;;) + { + //4 waiting for start command + RtlDownSema(&(pNFCAdp->VeriSema)); + + if (pNFCAdp->TaskStop) { + break; // task stopping, break the for loop + } + NFCRoutine(pNFCAdapte); + + }//end of for(;;) + + pNFCAdp->TaskStop = 0; +#if ( INCLUDE_vTaskDelete == 1 ) + vTaskDelete(NULL); +#endif + #endif +} + +VOID +LPIrqHandle( + IN VOID *pNFCAdapte +) +{ + u32 LpIrqStatus, CheckIndex, ExactIrqStatus, TableIndex; + + //DBG_8195A("Enter ISR\n"); + + LpIrqStatus = HAL_READ32(VENDOR_REG_BASE, LP_PERI_EXT_IRQ_STATUS); + + //Save exact IRQ status + ExactIrqStatus = LpIrqStatus & + HAL_READ32(VENDOR_REG_BASE, LP_PERI_EXT_IRQ_EN); + + //Check exact IRQ function + for(CheckIndex = 0;CheckIndex<32;CheckIndex++) { + if (ExactIrqStatus & BIT_(CheckIndex)) { + TableIndex = CheckIndex; + LpPeriIrqFunTable[TableIndex]((VOID *)(LpPeriIrqDataTable[TableIndex])); + } + } + + //Clear sub-rout IRQ + HAL_WRITE32(VENDOR_REG_BASE, LP_PERI_EXT_IRQ_STATUS, LpIrqStatus); + +} + +VOID +NFCIrqHandle( + IN VOID *pNFCAdapte +) +{ + PNFC_ADAPTER pNFCAdp = (PNFC_ADAPTER)pNFCAdapte; + u32 ISR = HalNFCRead32(0x68); + pNFCAdp->NFCIsr = (((u8)((ISR&0xbf00)>>8))&((u8)ISR)); + //DBG_8195A("A2N 0x68 = 0x%x\n", ISR); + + //stop int + //ISR = ISR&0xff; + + HalNFCWrite32(0x68, ISR); + + //DBG_8195A("After clean ISR A2N 0x68 = 0x%x\n", A2NREAD32(0x68)); + RtlUpSema(&(pNFCAdp->VeriSema)); +} + +VOID HalNFCDmemInit( + IN u32 *pTagData, + IN u32 TagLen +) +{ + if (pTagData == NULL) { + return; + } + + u32 pgidx, dmemidx; + for (pgidx = 0, dmemidx = 0; pgidx> 0); + NFCFWDMEM[dmemidx++] = (u8)((pTagData[pgidx] & 0x0000FF00) >> 8); + NFCFWDMEM[dmemidx++] = (u8)((pTagData[pgidx] & 0x00FF0000) >> 16); + NFCFWDMEM[dmemidx++] = (u8)((pTagData[pgidx] & 0xFF000000) >> 24); + } +} + +VOID +HalNFCInit( + PNFC_ADAPTER pNFCAdp +) +{ + u32 Rtemp = 0; + + _memset(pNFCAdp, 0, sizeof(NFC_ADAPTER)); + + //Enable NFC clk 0x244[17:16] = 3 + Rtemp = HAL_READ32(SYSTEM_CTRL_BASE, REG_PESOC_COM_CLK_CTRL1)|0x00030000; + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_PESOC_COM_CLK_CTRL1, Rtemp); + + //Enable A33 interface + Rtemp = (HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL) | 0x80000000); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL, Rtemp); + + //Enabel NFC and release IOS33_Ameba + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL) & 0xffff0000) | 0x00009401); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL, Rtemp); + + //polling ISO33_NFC 0x134 [0] = 0 + while ( (HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_PERI_MONITOR)&BIT0) != 0 ){}; + + //DBG_8195A("NFC Initialization Finish\n"); + + //CLK 25M + { + u32 RegTemp = HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_SYSPLL_CTRL1); + + RegTemp = ((RegTemp & 0xFFFFC7FF)|(BIT_SYS_SYSPLL_CKSDR_EN|BIT_SYS_SYSPLL_CKSDR_DIV(2))); + //RegTemp = ((RegTemp & 0xFFFFC7FF)|BIT13|BIT12); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_SYSPLL_CTRL1, RegTemp); + HAL_WRITE32(SYSTEM_CTRL_BASE, 0x244, HAL_READ32(SYSTEM_CTRL_BASE, 0x244)|BIT18); + } + + + //Init INT + { + IRQ_HANDLE NfcHandle; + NfcHandle.Data = (u32) (pNFCAdp); + NfcHandle.IrqNum = LP_EXTENSION_IRQ;//NFC_IRQ; + NfcHandle.IrqFun = (IRQ_FUN) LPIrqHandle; + NfcHandle.Priority = 3; + + InterruptRegister(&NfcHandle); + InterruptEn(&NfcHandle); + + LpPeriIrqFunTable[1] = (IRQ_FUN)((u32)NFCIrqHandle | 0x1); + + LpPeriIrqDataTable[1] = (u32)(pNFCAdp); + //level trigger + HAL_WRITE32(VENDOR_REG_BASE, LP_PERI_EXT_IRQ_MODE,0); + //enable imr + HAL_WRITE32(VENDOR_REG_BASE, LP_PERI_EXT_IRQ_EN, + (HAL_READ32(VENDOR_REG_BASE, LP_PERI_EXT_IRQ_EN) | BIT1)); + HalNFCWrite32(0x68, 0xBF00); + + } + + #if !TASK_SCHEDULER_DISABLED + { + u32 NFCTmpSts; + //create task + RtlInitSema(&(pNFCAdp->VeriSema),0); + NFCTmpSts = xTaskCreate( NFCTaskHandle, (const signed char *)"NFC_TASK", + ((1024*4)/sizeof(portBASE_TYPE)), (void *)pNFCAdp, 1, &(pNFCAdp->NFCTask)); + } + #endif + +} + +VOID +HalNFCDeinit( + PNFC_ADAPTER pNFCAdp +) +{ + u32 i; + u32 Rtemp = 0; + + pNFCAdp->TaskStop = 1; + RtlUpSema(&(pNFCAdp->VeriSema)); + // wait sometime for the task be stooped + for(i=0;i<1000;i++) { + if (pNFCAdp->TaskStop == 0) { + break; + } + else { + RtlMsleepOS(100); + } + } + //4 free the task semaphore + RtlFreeSema(&(pNFCAdp->VeriSema)); + _memset(pNFCAdp, 0, sizeof(NFC_ADAPTER)); + + //4 Disable NFC clk + Rtemp = HAL_READ32(SYSTEM_CTRL_BASE, REG_PESOC_COM_CLK_CTRL1)&0xFFFCFFFF; + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_PESOC_COM_CLK_CTRL1, Rtemp); + + //4 Enable A33 interface + Rtemp = (HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL) | 0x80000000); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL, Rtemp); + + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL) & 0xffff0000) | 0x00009404); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL, Rtemp); +} + + +u32 +HalNFCRead32( + IN u32 Addr +) +{ + //byte0: test type, byte1: Base address, byte2: offset + + u32 Rtemp = 0; + u32 Idxtemp = 0; + + //full addr + HAL_WRITE32(NFC_INTERFACE_BASE, 0x0, (0x1f000000+Addr)); + //R_cmd + HAL_WRITE32(NFC_INTERFACE_BASE, 0x4, 0x2f); + #if 1 + //polling 0x4[7]=1 + while(1) { + if( (HAL_READ32(NFC_INTERFACE_BASE, 0x4)&BIT7) == 0 ){ + Idxtemp++; + if((Idxtemp)%10000 == 0) { + DBG_8195A("Idxtemp: 0x%x\n", Idxtemp); + } + if (Idxtemp > 0x0fffff) { + DBG_8195A("A2N_OCP_MISC_R_IN_WHILE: 0x%x\r\n", HAL_READ32(NFC_INTERFACE_BASE, 0x4)); + DBG_8195A("Read FAIL!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1\r\n"); + return 0; + } + } + else { + //DBG_8195A("A2N_OCP_MISC_R_IN_WHILE: 0x%x\n", HAL_READ32(NFC_INTERFACE_BASE, 0x4)); + HAL_WRITE32(NFC_INTERFACE_BASE, 0x4, BIT7); + Rtemp = HAL_READ32(NFC_INTERFACE_BASE, 0xc); + break; + } + } + #endif + //DBG_8195A("A2N_MEM_MISC: 0x%x\n", Rtemp); + return Rtemp; +} + +VOID +HalNFCWrite32( + IN u32 Addr, + IN u32 Data +) +{ + //byte0: test type, byte1: Base address, byte2: offset, byte3:value + u32 Idxtemp = 0; + + //full addr + HAL_WRITE32(NFC_INTERFACE_BASE, 0x0, 0x1f000000+Addr); + //full data + HAL_WRITE32(NFC_INTERFACE_BASE, 0x8, Data); + //W_cmd + HAL_WRITE32(NFC_INTERFACE_BASE, 0x4, 0x1f); + + //polling 0x4[7]=1 + while(1) { + if( (HAL_READ32(NFC_INTERFACE_BASE, 0x4)&BIT7) == 0 ){ + Idxtemp++; + if((Idxtemp)%10000 == 0) { + DBG_8195A("Idxtemp: 0x%x\n", Idxtemp); + } + if (Idxtemp > 0x0fffff) { + DBG_8195A("A2N_OCP_MISC_R_IN_WHILE: 0x%x\r\n", HAL_READ32(NFC_INTERFACE_BASE, 0x4)); + DBG_8195A("write FAIL!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1\r\n"); + return; + } + } + else { + //DBG_8195A("A2N_OCP_MISC_W_IN_WHILE: 0x%x\n", HAL_READ32(NFC_INTERFACE_BASE, 0x4)); + HAL_WRITE32(NFC_INTERFACE_BASE, 0x4, BIT7); + break; + } + } +} + +VOID +HalNFCFwFullMEM( + IN VOID *Data, + IN u32 NFCFwLength +) +{ + u32 *NFCFW; + NFCFW = (u32*) Data; + u32 Idx, NFCFwTemp, RTemp; + u8 Temp = (NFCFwLength%4); + u32 IdxTemp = ((NFCFwLength-Temp)/4); + u8 MEMTemp = 0; + u8 MEMCnt = 0; + + u32 FWChkSum = 0; + + HalNFCWrite32(0x4C, 0x0); + + //write fw to MEM + for (Idx = 0; Idx < IdxTemp; Idx++ ) { + + NFCFwTemp = *(NFCFW+Idx); + HAL_WRITE32(NFC_INTERFACE_BASE, 0x10, NFCFwTemp); + + //cal chksum + FWChkSum ^= NFCFwTemp; + MEMTemp++; + HalDelayUs(1); + + if (MEMTemp == 8) { + + MEMTemp = 0; + + //check mem empty + while(1){ + + RTemp = HAL_READ32(NFC_INTERFACE_BASE, 0x14); + MEMCnt = (((u8)(RTemp & 0x1e)) >> 1); + + if ( RTemp & BIT6) { + break; + } + else { + } + } + } + } + + HalDelayUs(200); + + while(1){ + RTemp = HAL_READ32(NFC_INTERFACE_BASE, 0x14); + if ( RTemp & BIT6) { + break; + } + else { + } + } + + //write chksum + HAL_WRITE32(NFC_INTERFACE_BASE, 0x10, FWChkSum); + + while(1){ + RTemp = HAL_READ32(NFC_INTERFACE_BASE, 0x14); + if ( RTemp & BIT6) { + break; + } + else { + } + } +} + + +VOID +HalNFCFwDownload( + VOID +) +{ + u32 Rtemp = 0; + + //switch free run clock from 500K to 80M + HalNFCWrite32(0x88, 0xf06cf06c); + + //2 Download NFC FW + //3 Download IMEM + //setting fw download + HalNFCWrite32(0x48, 0x1); + + //reset NFC CPU + HalNFCWrite32(0x20, 0x1234FFFF); + + //switch IMEM + HAL_WRITE32(NFC_INTERFACE_BASE, 0x14, 0); + + //write fw to MEM + HalNFCFwFullMEM(NFCFWIMEM,sizeof(NFCFWIMEM)); + HalDelayUs(100); + + Rtemp = HalNFCRead32(0x48); + if(Rtemp & BIT1) { + //DBG_8195A("NFC FW Download IMEM SUCCESS \n"); + } + else { + DBG_8195A("NFC FW Download IMEM FAIL !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! \n"); + return; + } + + //3 Download DMEM + //setting fw download + HalNFCWrite32(0x48, 0x1); + + //switch DMEM + HAL_WRITE32(NFC_INTERFACE_BASE, 0x14, 1); + + //write fw to MEM + HalNFCFwFullMEM(NFCFWDMEM,sizeof(NFCFWDMEM)); + + HalDelayUs(100); + Rtemp = HalNFCRead32(0x48); + if(Rtemp & BIT1) { + //DBG_8195A("NFC FW Download DMEM SUCCESS \n"); + } + else { + DBG_8195A("NFC FW Download DMEM FAIL !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! \n"); + return; + } + + //Reset CPU + HalNFCWrite32(0x48, 0x80); + + DBG_8195A("NFC REBOOT SUCCESS \n"); +} + +#endif //CONFIG_NFC_EN diff --git a/component/soc/realtek/8195a/fwlib/rtl8195a/src/rtl8195a_pcm.c b/component/soc/realtek/8195a/fwlib/rtl8195a/src/rtl8195a_pcm.c new file mode 100644 index 0000000..abf6b18 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/rtl8195a/src/rtl8195a_pcm.c @@ -0,0 +1,360 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + + +#include "platform_autoconf.h" +#include "diag.h" +#include "rtl8195a_pcm.h" +#include "hal_pcm.h" + +extern void * +_memset( void *s, int c, SIZE_T n ); + +VOID +HalPcmOnOffRtl8195a ( + IN VOID *Data +) +{ + PHAL_PCM_ADAPTER pHalPcmAdapter = (PHAL_PCM_ADAPTER) Data; + //todo on off pcm + +} + +//default sampling rate 8khz, linear, 10ms frame size, time slot 0 , tx+rx +// master mode, enable endian swap +// Question: need local tx/rx page? +BOOL +HalPcmInitRtl8195a( + IN VOID *Data +) +{ + + PHAL_PCM_ADAPTER pHalPcmAdapter = (PHAL_PCM_ADAPTER) Data; + _memset((void *)pHalPcmAdapter, 0, sizeof(HAL_PCM_ADAPTER)); + + //4 1) Initial PcmChCNR03 Register + pHalPcmAdapter->PcmChCNR03.CH0MuA = 0; + pHalPcmAdapter->PcmChCNR03.CH0Band = 0; + + + //4 1) Initial PcmTSR03 Register + pHalPcmAdapter->PcmTSR03.CH0TSA = 0; + + //4 1) Initial PcmBSize03 Register + pHalPcmAdapter->PcmBSize03.CH0BSize = 39; // 40word= 8khz*0.01s*1ch*2byte/4byte + + + //4 2) Initial Ctl Register + + pHalPcmAdapter->PcmCtl.Pcm_En = 1; + pHalPcmAdapter->PcmCtl.SlaveMode = 0; + pHalPcmAdapter->PcmCtl.FsInv = 0; + pHalPcmAdapter->PcmCtl.LinearMode = 0; + pHalPcmAdapter->PcmCtl.LoopBack = 0; + pHalPcmAdapter->PcmCtl.EndianSwap = 1; + + return _TRUE; +} + + +BOOL +HalPcmSettingRtl8195a( + IN VOID *Data +) +{ + + PHAL_PCM_ADAPTER pHalPcmAdapter = (PHAL_PCM_ADAPTER) Data; + u8 PcmIndex = pHalPcmAdapter->PcmIndex; + u8 PcmCh = pHalPcmAdapter->PcmCh; + u32 RegCtl, RegChCNR03, RegTSR03, RegBSize03; + u32 Isr03; + + PcmCh=0; + //4 1) Check Pcm index is avaliable + if (HAL_PCMX_READ32(PcmIndex, REG_PCM_CHCNR03) & (BIT24|BIT25)) { + //4 Pcm index is running, stop first + DBG_8195A_DMA("Error, PCM %d ch%d is running; stop first!\n", PcmIndex, PcmCh); + + return _FALSE; + } + + //4 2) Check if there are the pending isr + + + Isr03 = HAL_PCMX_READ32(PcmIndex, REG_PCM_ISR03); + Isr03 &= 0xff000000; + //4 Clear Pending Isr + HAL_PCMX_WRITE32(PcmIndex, REG_PCM_ISR03, Isr03); + //} + + + //4 3) Process RegCtl + RegCtl = HAL_PCMX_READ32(PcmIndex, REG_PCM_CTL); + + //4 Clear Ctl register bits + RegCtl &= ( BIT_INV_CTLX_SLAVE_SEL & + BIT_INV_CTLX_FSINV & + BIT_INV_CTLX_PCM_EN & + BIT_INV_CTLX_LINEARMODE & + BIT_INV_CTLX_LOOP_BACK & + BIT_INV_CTLX_ENDIAN_SWAP); + + RegCtl = BIT_CTLX_SLAVE_SEL(pHalPcmAdapter->PcmCtl.SlaveMode) | + BIT_CTLX_FSINV(pHalPcmAdapter->PcmCtl.FsInv) | + BIT_CTLX_PCM_EN(pHalPcmAdapter->PcmCtl.Pcm_En) | + BIT_CTLX_LINEARMODE(pHalPcmAdapter->PcmCtl.LinearMode) | + BIT_CTLX_LOOP_BACK(pHalPcmAdapter->PcmCtl.LoopBack) | + BIT_CTLX_ENDIAN_SWAP(pHalPcmAdapter->PcmCtl.EndianSwap) | + RegCtl; + + HAL_PCMX_WRITE32(PcmIndex, REG_PCM_CTL, RegCtl); + //4 4) Program ChCNR03 Register + + RegChCNR03 = HAL_PCMX_READ32(PcmIndex, REG_PCM_CHCNR03); + + RegChCNR03 &= (BIT_INV_CHCNR03_CH0RE & + BIT_INV_CHCNR03_CH0TE & + BIT_INV_CHCNR03_CH0MUA & + BIT_INV_CHCNR03_CH0BAND); + + RegChCNR03 = BIT_CHCNR03_CH0RE(pHalPcmAdapter->PcmChCNR03.CH0RE) | + BIT_CHCNR03_CH0TE(pHalPcmAdapter->PcmChCNR03.CH0TE) | + BIT_CHCNR03_CH0MUA(pHalPcmAdapter->PcmChCNR03.CH0MuA) | + BIT_CHCNR03_CH0BAND(pHalPcmAdapter->PcmChCNR03.CH0Band) | + RegChCNR03; + + DBG_8195A_DMA("RegChCNR03 data:0x%x\n", RegChCNR03); + + HAL_PCMX_WRITE32(PcmIndex, REG_PCM_CHCNR03, RegChCNR03); + // time slot + RegTSR03 = HAL_PCMX_READ32(PcmIndex, REG_PCM_TSR03); + + RegTSR03 &= (BIT_INV_TSR03_CH0TSA); + RegTSR03 = BIT_TSR03_CH0TSA(pHalPcmAdapter->PcmTSR03.CH0TSA) | + RegTSR03; + + DBG_8195A_DMA("RegTSR03 data:0x%x\n", RegTSR03); + + HAL_PCMX_WRITE32(PcmIndex, REG_PCM_TSR03, RegTSR03); + + // buffer size + RegBSize03 = HAL_PCMX_READ32(PcmIndex, REG_PCM_BSIZE03); + + RegBSize03 &= (BIT_INV_BSIZE03_CH0BSIZE); + RegBSize03 = BIT_BSIZE03_CH0BSIZE(pHalPcmAdapter->PcmBSize03.CH0BSize) | + RegBSize03; + + DBG_8195A_DMA("RegBSize03 data:0x%x\n", RegBSize03); + + HAL_PCMX_WRITE32(PcmIndex, REG_PCM_BSIZE03, RegBSize03); + + + + + return _TRUE; +} + +BOOL +HalPcmEnRtl8195a( + IN VOID *Data +) +{ + + PHAL_PCM_ADAPTER pHalPcmAdapter = (PHAL_PCM_ADAPTER) Data; + u8 PcmIndex = pHalPcmAdapter->PcmIndex; + u8 PcmCh = pHalPcmAdapter->PcmCh; + u32 RegChCNR03; + + PcmCh=0; + pHalPcmAdapter->Enable = 1; + + + //4 1) Check Pcm index is avaliable + RegChCNR03 = HAL_PCMX_READ32(PcmIndex, REG_PCM_CHCNR03); + if (RegChCNR03 & (BIT24|BIT25)) { + //4 Pcm index is running, stop first + DBG_8195A_DMA("Error, PCM %d ch%d is running; stop first!\n", PcmIndex, PcmCh); + + return _FALSE; + } + + HAL_PCMX_WRITE32(PcmIndex, REG_PCM_CHCNR03, RegChCNR03|BIT24|BIT25); + pHalPcmAdapter->PcmChCNR03.CH0RE = 1; + pHalPcmAdapter->PcmChCNR03.CH0TE = 1; + + return _TRUE; +} + +BOOL +HalPcmDisRtl8195a( + IN VOID *Data +) +{ + + PHAL_PCM_ADAPTER pHalPcmAdapter = (PHAL_PCM_ADAPTER) Data; + u8 PcmIndex = pHalPcmAdapter->PcmIndex; + u8 PcmCh = pHalPcmAdapter->PcmCh; + u32 RegChCNR03; + + PcmCh=0; + pHalPcmAdapter->Enable = 0; + + + RegChCNR03 = HAL_PCMX_READ32(PcmIndex, REG_PCM_CHCNR03); + + HAL_PCMX_WRITE32(PcmIndex, REG_PCM_CHCNR03, RegChCNR03&(~(BIT24|BIT25))); + pHalPcmAdapter->PcmChCNR03.CH0RE = 0; + pHalPcmAdapter->PcmChCNR03.CH0TE = 0; + + return _TRUE; +} + + + +BOOL +HalPcmIsrEnAndDisRtl8195a ( + IN VOID *Data +) +{ +/* + PHAL_GDMA_ADAPTER pHalGdmaAdapter = (PHAL_GDMA_ADAPTER) Data; + u32 IsrMask, Addr, IsrCtrl; + u8 IsrTypeIndex = 0; + + for (IsrTypeIndex=0; IsrTypeIndex<5; IsrTypeIndex++) { + + if (BIT_(IsrTypeIndex) & pHalGdmaAdapter->GdmaIsrType) { + Addr = (REG_GDMA_MASK_INT_BASE + IsrTypeIndex*8); + + IsrMask = HAL_GDMAX_READ32(pHalGdmaAdapter->GdmaIndex, Addr); + + IsrCtrl = ((pHalGdmaAdapter->IsrCtrl)?(pHalGdmaAdapter->ChEn | IsrMask): + ((~pHalGdmaAdapter->ChEn) & IsrMask)); + + HAL_GDMAX_WRITE32(pHalGdmaAdapter->GdmaIndex, + Addr, + IsrCtrl + ); + + } + } +*/ + return _TRUE; +} + + + +BOOL +HalPcmDumpRegRtl8195a ( + IN VOID *Data +) +{ +/* + PHAL_GDMA_ADAPTER pHalGdmaAdapter = Data; + HAL_GDMAX_WRITE32(pHalGdmaAdapter->GdmaIndex, + REG_GDMA_CH_EN, + (HAL_GDMAX_READ32(pHalGdmaAdapter->GdmaIndex, REG_GDMA_CH_EN)| + (pHalGdmaAdapter->ChEn)) + ); +*/ + return _TRUE; +} + +BOOL +HalPcmRtl8195a ( + IN VOID *Data +) +{ +/* PHAL_GDMA_ADAPTER pHalGdmaAdapter = (PHAL_GDMA_ADAPTER) Data; + HAL_GDMAX_WRITE32(pHalGdmaAdapter->GdmaIndex, + REG_GDMA_CH_EN, + (HAL_GDMAX_READ32(pHalGdmaAdapter->GdmaIndex, REG_GDMA_CH_EN)& + ~(pHalGdmaAdapter->ChEn)) + ); +*/ + return _TRUE; +} +/* +u8 +HalGdmaChIsrCleanRtl8195a ( + IN VOID *Data +) +{ + PHAL_GDMA_ADAPTER pHalGdmaAdapter = (PHAL_GDMA_ADAPTER) Data; + u32 IsrStatus; + u8 IsrTypeIndex = 0, IsrActBitMap = 0; + + for (IsrTypeIndex=0; IsrTypeIndex<5; IsrTypeIndex++) { + + IsrStatus = HAL_GDMAX_READ32(pHalGdmaAdapter->GdmaIndex, + (REG_GDMA_RAW_INT_BASE + IsrTypeIndex*8)); + +// DBG_8195A_DMA("Isr Type %d: Isr Status 0x%x\n", IsrTypeIndex, IsrStatus); + + IsrStatus = (IsrStatus & (pHalGdmaAdapter->ChEn & 0xFF)); + + if (BIT_(IsrTypeIndex) & pHalGdmaAdapter->GdmaIsrType) { + HAL_GDMAX_WRITE32(pHalGdmaAdapter->GdmaIndex, + (REG_GDMA_CLEAR_INT_BASE+ (IsrTypeIndex*8)), + (IsrStatus)// & (pHalGdmaAdapter->ChEn & 0xFF)) + ); + IsrActBitMap |= BIT_(IsrTypeIndex); + + } + + } + return IsrActBitMap; + +} + + +VOID +HalGdmaChCleanAutoSrcRtl8195a ( + IN VOID *Data +) +{ + u32 CfgxLow; + PHAL_GDMA_ADAPTER pHalGdmaAdapter = (PHAL_GDMA_ADAPTER) Data; + CfgxLow = HAL_GDMAX_READ32(pHalGdmaAdapter->GdmaIndex, + (REG_GDMA_CH_CFG + pHalGdmaAdapter->ChNum*REG_GDMA_CH_OFF)); + + CfgxLow &= BIT_INVC_CFGX_LO_RELOAD_SRC; + + HAL_GDMAX_WRITE32(pHalGdmaAdapter->GdmaIndex, + (REG_GDMA_CH_CFG + pHalGdmaAdapter->ChNum*REG_GDMA_CH_OFF), + CfgxLow + ); + + DBG_8195A_DMA("CFG Low data:0x%x\n", + HAL_GDMAX_READ32(pHalGdmaAdapter->GdmaIndex, (REG_GDMA_CH_CFG + pHalGdmaAdapter->ChNum*REG_GDMA_CH_OFF))); +} + +VOID +HalGdmaChCleanAutoDstRtl8195a ( + IN VOID *Data +) +{ + u32 CfgxLow; + PHAL_GDMA_ADAPTER pHalGdmaAdapter = (PHAL_GDMA_ADAPTER) Data; + CfgxLow = HAL_GDMAX_READ32(pHalGdmaAdapter->GdmaIndex, + (REG_GDMA_CH_CFG + pHalGdmaAdapter->ChNum*REG_GDMA_CH_OFF)); + + CfgxLow &= BIT_INVC_CFGX_LO_RELOAD_DST; + + HAL_GDMAX_WRITE32(pHalGdmaAdapter->GdmaIndex, + (REG_GDMA_CH_CFG + pHalGdmaAdapter->ChNum*REG_GDMA_CH_OFF), + CfgxLow + ); + DBG_8195A_DMA("CFG Low data:0x%x\n", + HAL_GDMAX_READ32(pHalGdmaAdapter->GdmaIndex, (REG_GDMA_CH_CFG + pHalGdmaAdapter->ChNum*REG_GDMA_CH_OFF))); + +} +*/ + + diff --git a/component/soc/realtek/8195a/fwlib/rtl8195a/src/rtl8195a_pwm.c b/component/soc/realtek/8195a/fwlib/rtl8195a/src/rtl8195a_pwm.c new file mode 100644 index 0000000..dd5163e --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/rtl8195a/src/rtl8195a_pwm.c @@ -0,0 +1,219 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + + +#include "rtl8195a.h" +#include "hal_peri_on.h" + +#ifdef CONFIG_PWM_EN +#include "rtl8195a_pwm.h" +#include "hal_pwm.h" + +extern HAL_PWM_ADAPTER PWMPin[]; + +extern HAL_TIMER_OP HalTimerOp; + +/** + * @brief Configure a G-Timer to generate a tick with certain time. + * + * @param pwm_id: the PWM pin index + * @param tick_time: the time (micro-second) of a tick + * + * @retval None + */ +void +Pwm_SetTimerTick_8195a( + HAL_PWM_ADAPTER *pPwmAdapt, + u32 tick_time +) +{ + TIMER_ADAPTER TimerAdapter; + + + if (tick_time <= MIN_GTIMER_TIMEOUT) { + tick_time = MIN_GTIMER_TIMEOUT; + } + else { + tick_time = (((tick_time-1)/TIMER_TICK_US)+1) * TIMER_TICK_US; + } + + // Initial a G-Timer for the PWM pin + if (pPwmAdapt->tick_time != tick_time) { + TimerAdapter.IrqDis = 1; // Disable Irq + TimerAdapter.IrqHandle.IrqFun = (IRQ_FUN) NULL; + TimerAdapter.IrqHandle.IrqNum = TIMER2_7_IRQ; + TimerAdapter.IrqHandle.Priority = 0; + TimerAdapter.IrqHandle.Data = (u32)NULL; + TimerAdapter.TimerId = pPwmAdapt->gtimer_id; + TimerAdapter.TimerIrqPriority = 0; + TimerAdapter.TimerLoadValueUs = tick_time-1; + TimerAdapter.TimerMode = 1; // auto-reload with user defined value + + HalTimerOp.HalTimerInit((VOID*) &TimerAdapter); + pPwmAdapt->tick_time = tick_time; + DBG_PWM_INFO("%s: Timer_Id=%d Count=%d\n", __FUNCTION__, pPwmAdapt->gtimer_id, tick_time); + } + +} + + +/** + * @brief Set the duty ratio of the PWM pin. + * + * @param pwm_id: the PWM pin index + * @param period: the period time, in micro-second. + * @param pulse_width: the pulse width time, in micro-second. + * + * @retval None + */ +void +HAL_Pwm_SetDuty_8195a( + HAL_PWM_ADAPTER *pPwmAdapt, + u32 period, + u32 pulse_width +) +{ + u32 RegAddr; + u32 RegValue; + u32 period_tick; + u32 pulsewidth_tick; + u32 tick_time; + u8 timer_id; + u8 pwm_id; + + pwm_id = pPwmAdapt->pwm_id; + // Adjust the tick time to a proper value + if (period < (MIN_GTIMER_TIMEOUT*2)) { + DBG_PWM_ERR ("HAL_Pwm_SetDuty_8195a: Invalid PWM period(%d), too short!!\n", period); + tick_time = MIN_GTIMER_TIMEOUT; + period = MIN_GTIMER_TIMEOUT*2; + } + else { + tick_time = period / 0x3fc; + if (tick_time < MIN_GTIMER_TIMEOUT) { + tick_time = MIN_GTIMER_TIMEOUT; + } + } + + Pwm_SetTimerTick_8195a(pPwmAdapt, tick_time); + tick_time = pPwmAdapt->tick_time; +#if 0 + // Check if current tick time needs adjustment + if ((pPwmAdapt->tick_time << 12) <= period) { + // need a longger tick time + } + else if ((pPwmAdapt->tick_time >> 2) >= period) { + // need a shorter tick time + } +#endif + period_tick = period/tick_time; + if (period_tick == 0) { + period_tick = 1; + } + + if (pulse_width >= period) { +// pulse_width = period-1; + pulse_width = period; + } + pulsewidth_tick = pulse_width/tick_time; + if (pulsewidth_tick == 0) { +// pulsewidth_tick = 1; + } + + timer_id = pPwmAdapt->gtimer_id; + + pPwmAdapt->period = period_tick & 0x3ff; + pPwmAdapt->pulsewidth = pulsewidth_tick & 0x3ff; + + RegAddr = REG_PERI_PWM0_CTRL + (pwm_id*4); + RegValue = BIT31 | (timer_id<<24) | (pulsewidth_tick<<12) | period_tick; + + HAL_WRITE32(PERI_ON_BASE, RegAddr, RegValue); +} + +/** + * @brief Initializes and enable a PWM control pin. + * + * @param pwm_id: the PWM pin index + * @param sel: pin mux selection + * @param timer_id: the G-timer index assigned to this PWM + * + * @retval HAL_Status + */ +HAL_Status +HAL_Pwm_Init_8195a( + HAL_PWM_ADAPTER *pPwmAdapt +) +{ + u32 pwm_id; + u32 pin_sel; + + pwm_id = pPwmAdapt->pwm_id; + pin_sel = pPwmAdapt->sel; + // Initial a G-Timer for the PWM pin + Pwm_SetTimerTick_8195a(pPwmAdapt, MIN_GTIMER_TIMEOUT); + + // Set default duty ration + HAL_Pwm_SetDuty_8195a(pPwmAdapt, 20000, 10000); + + // Configure the Pin Mux + PinCtrl((PWM0+pwm_id), pin_sel, 1); + + return HAL_OK; +} + + +/** + * @brief Enable a PWM control pin. + * + * @param pwm_id: the PWM pin index + * + * @retval None + */ +void +HAL_Pwm_Enable_8195a( + HAL_PWM_ADAPTER *pPwmAdapt +) +{ + u32 pwm_id; + + pwm_id = pPwmAdapt->pwm_id; + // Configure the Pin Mux + if (!pPwmAdapt->enable) { + PinCtrl((PWM0+pwm_id), pPwmAdapt->sel, 1); + HalTimerOp.HalTimerEn(pPwmAdapt->gtimer_id); + pPwmAdapt->enable = 1; + } +} + + +/** + * @brief Disable a PWM control pin. + * + * @param pwm_id: the PWM pin index + * + * @retval None + */ +void +HAL_Pwm_Disable_8195a( + HAL_PWM_ADAPTER *pPwmAdapt +) +{ + u32 pwm_id; + + pwm_id = pPwmAdapt->pwm_id; + // Configure the Pin Mux + if (pPwmAdapt->enable) { + PinCtrl((PWM0+pwm_id), pPwmAdapt->sel, 0); + HalTimerOp.HalTimerDis(pPwmAdapt->gtimer_id); + pPwmAdapt->enable = 0; + } +} + +#endif //CONFIG_PWM_EN diff --git a/component/soc/realtek/8195a/fwlib/rtl8195a/src/rtl8195a_sdio_device.c b/component/soc/realtek/8195a/fwlib/rtl8195a/src/rtl8195a_sdio_device.c new file mode 100644 index 0000000..03260b2 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/rtl8195a/src/rtl8195a_sdio_device.c @@ -0,0 +1,2766 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#include "rtl8195a.h" +#include "hal_sdio.h" +#include "mailbox.h" + +#ifndef CONFIG_INIC_EN +#define CONFIG_INIC_EN 0//for iNIC, disable by default +#endif +/****************************************************************************** + * Function Prototype Declaration + ******************************************************************************/ +BOOL SDIO_Device_Init( + IN PHAL_SDIO_ADAPTER pSDIODev +); + +VOID SDIO_Device_DeInit( + IN PHAL_SDIO_ADAPTER pSDIODev +); + +VOID SDIO_IRQ_Handler( + IN VOID *pData +); + +VOID SDIO_Interrupt_Init( + IN PHAL_SDIO_ADAPTER pSDIODev +); + +VOID SDIO_Enable_Interrupt( + IN PHAL_SDIO_ADAPTER pSDIODev, + IN u32 IntMask +); + +VOID SDIO_Disable_Interrupt( + IN PHAL_SDIO_ADAPTER pSDIODev, + IN u32 IntMask +); + +VOID SDIO_Clear_ISR( + IN PHAL_SDIO_ADAPTER pSDIODev, + IN u32 IntMask +); + +VOID SDIO_TxTask( + IN VOID *pData +); + +VOID SDIO_RxTask( + IN VOID *pData +); + +static __inline VOID SDIO_Wakeup_Task( + IN PHAL_SDIO_ADAPTER pSDIODev +); + +static VOID SDIO_SetEvent( + IN PHAL_SDIO_ADAPTER pSDIODev, + IN u32 Event +); + +static VOID SDIO_ClearEvent( + IN PHAL_SDIO_ADAPTER pSDIODev, + IN u32 Event +); + +static BOOL SDIO_IsEventPending( + IN PHAL_SDIO_ADAPTER pSDIODev, + IN u32 Event +); + +VOID SDIO_IRQ_Handler_BH( + IN PHAL_SDIO_ADAPTER pSDIODev +); + +VOID SDIO_RX_IRQ_Handler_BH( + IN PHAL_SDIO_ADAPTER pSDIODev +); + +VOID SDIO_TX_BD_Buf_Refill( + IN PHAL_SDIO_ADAPTER pSDIODev +); + +VOID SDIO_TX_FIFO_DataReady( + IN PHAL_SDIO_ADAPTER pSDIODev +); + +PSDIO_RX_PACKET SDIO_Alloc_Rx_Pkt( + IN PHAL_SDIO_ADAPTER pSDIODev +); + +VOID SDIO_Free_Rx_Pkt( + IN PHAL_SDIO_ADAPTER pSDIODev, + IN PSDIO_RX_PACKET pPkt +); + +VOID SDIO_Recycle_Rx_BD ( + IN PHAL_SDIO_ADAPTER pSDIODev +); + +VOID SDIO_Process_H2C_IOMsg( + IN PHAL_SDIO_ADAPTER pSDIODev +); + +VOID SDIO_Send_C2H_IOMsg( + IN PHAL_SDIO_ADAPTER pSDIODev, + IN u32 *C2HMsg +); + +VOID SDIO_Process_H2C_PktMsg( + IN PHAL_SDIO_ADAPTER pSDIODev, + IN u8 *H2CMsg +); + +u8 SDIO_Send_C2H_PktMsg( + IN PHAL_SDIO_ADAPTER pSDIODev, + IN u8 *C2HMsg, + IN u16 MsgLen +); + +u8 SDIO_Process_RPWM( + IN PHAL_SDIO_ADAPTER pSDIODev +); + +VOID SDIO_Reset_Cmd( + IN PHAL_SDIO_ADAPTER pSDIODev +); + +VOID SDIO_Return_Rx_Data( + IN PHAL_SDIO_ADAPTER pSDIODev +); + +VOID SDIO_Register_Tx_Callback( + IN PHAL_SDIO_ADAPTER pSDIODev, + IN s8 (*CallbackFun)(VOID *pAdapter, u8 *pPkt, u16 Offset, u16 PktSize), + IN VOID *pAdapter +); + +s8 SDIO_Rx_Callback( + IN PHAL_SDIO_ADAPTER pSDIODev, + IN VOID *pData, + IN u16 Offset, + IN u16 Length, + IN u8 CmdType +); + +s8 SDIO_Handle_MsgBlk( + IN PHAL_SDIO_ADAPTER pSDIODev, + IN MSG_BLK *pMblk +); + +#if SDIO_MP_MODE +VOID SDIO_PeriodicalTimerCallback( + void *pContex +); + +u8 SDIO_MapMPCmd( + IN char *CmdStr, + IN u16 *Offset +); + +VOID SDIO_DumpMPStatus( + IN PHAL_SDIO_ADAPTER pSDIODev + ); + +VOID SDIO_StatisticDump( + IN PHAL_SDIO_ADAPTER pSDIODev +); + +s8 SDIO_MP_Loopback( + IN VOID *pAdapter, + IN u8 *pData, + IN u16 Offset, + IN u16 PktSize +); + +s8 SDIO_MP_ContinueTx( + IN VOID *pAdapter, + IN u8 *pData, + IN u16 Offset, + IN u16 PktSize +); + +VOID SDIO_MP_ContinueRx( + IN PHAL_SDIO_ADAPTER pSDIODev +); + +VOID SDIO_DeviceMPApp( + IN PHAL_SDIO_ADAPTER pSDIODev, + IN u16 argc, + IN u8 *argv[] +); +#endif /* endof '#if SDIO_MP_MODE' */ + +/****************************************************************************** + * Global Variable Declaration + ******************************************************************************/ + +#if SDIO_MP_MODE +const SDIO_MP_CMD SDIO_MPCmdTable[] = { + {"mp_start", SDIO_MP_START}, + {"mp_stop", SDIO_MP_STOP}, + {"mp_loopback", SDIO_MP_LOOPBACK}, + {"status", SDIO_MP_STATUS}, + {"read_reg8", SDIO_MP_READ_REG8}, + {"read_reg16", SDIO_MP_READ_REG16}, + {"read_reg32", SDIO_MP_READ_REG32}, + {"write_reg8", SDIO_MP_WRITE_REG8}, + {"write_reg16", SDIO_MP_WRITE_REG16}, + {"write_reg32", SDIO_MP_WRITE_REG32}, + {"wakeup", SDIO_MP_WAKEUP}, + {"dump", SDIO_MP_DUMP}, + {"ctx", SDIO_MP_CTX}, + {"crx", SDIO_MP_CRX}, + {"crx_da", SDIO_MP_CRX_DA}, + {"crx_stop", SDIO_MP_CRX_STOP}, + {"dbg_msg", SDIO_MP_DBG_MSG} +}; + +const u8 MP_WlanHdr[]={ + 0x88,0x01,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff, + 0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00, + 0x00,0x01,0x10,0x00,0x06,0x00}; +#endif + +/****************************************************************************** + * External Function & Variable Declaration + ******************************************************************************/ +extern PHAL_SDIO_ADAPTER pgSDIODev; + +extern u32 Strtoul( + IN const u8 *nptr, + IN u8 **endptr, + IN u32 base +); + +/****************************************************************************** + * Function: SDIO_Device_Init + * Desc: SDIO device driver initialization. + * 1. Allocate SDIO TX FIFO buffer and initial TX related register. + * 2. Allocate SDIO RX Buffer Descriptor and RX Buffer. Initial RX related + * register. + * 3. Register the Interrupt function. + * 4. Create the SDIO Task and allocate resource(Semaphore). + * + ******************************************************************************/ +BOOL SDIO_Device_Init( + IN PHAL_SDIO_ADAPTER pSDIODev +) +{ + int i; + SDIO_TX_PACKET *pTxPkt; + SDIO_RX_PACKET *pPkt; + SDIO_TX_BD_HANDLE *pTxBdHdl; + SDIO_RX_BD_HANDLE *pRxBdHdl; + int ret; + u32 reg; + + DBG_SDIO_INFO("SDIO_Device_Init==>\n"); + + /* SDIO Function Enable */ +#if 0 + reg = HAL_READ32(PERI_ON_BASE, 0x214); + reg |= (BIT_SOC_HCI_SDIOD_OFF_EN | BIT_SOC_HCI_SDIOD_ON_EN); + HAL_WRITE32(PERI_ON_BASE, 0x214, reg); // write REG_SOC_HCI_COM_FUNC_EN +#endif + SDIOD_ON_FCTRL(ON); + SDIOD_OFF_FCTRL(ON); + + /* Enable Clock for SDIO function */ +#if 0 + reg = HAL_READ32(PERI_ON_BASE, 0x240); +// reg |= (BIT_SOC_SLPCK_SDIO_DEV_EN | BIT_SOC_ACTCK_SDIO_DEV_EN); + reg |= BIT_SOC_ACTCK_SDIO_DEV_EN; + HAL_WRITE32(PERI_ON_BASE, 0x240, reg); // write REG_PESOC_HCI_CLK_CTRL0 +#endif + ACTCK_SDIOD_CCTRL(ON); + + // Reset SDIO DMA + HAL_SDIO_WRITE8(REG_SPDIO_CPU_RST_DMA, BIT_CPU_RST_SDIO_DMA); + + /* Initial SDIO TX BD */ + DBG_SDIO_INFO("Tx BD Init==>\n"); + +// TODO: initial TX BD + pSDIODev->pTXBDAddr = RtlZmalloc((SDIO_TX_BD_NUM * sizeof(SDIO_TX_BD))+3); + if (NULL == pSDIODev->pTXBDAddr) { + DBG_SDIO_ERR("SDIO_Device_Init: Malloc for TX_BD Err!!\n"); + goto SDIO_INIT_ERR; + } + pSDIODev->pTXBDAddrAligned = (PSDIO_TX_BD)(((((u32)pSDIODev->pTXBDAddr - 1) >> 2) + 1) << 2); // Make it 4-bytes aligned + HAL_SDIO_WRITE32(REG_SPDIO_TXBD_ADDR, pSDIODev->pTXBDAddrAligned); + HAL_SDIO_WRITE16(REG_SPDIO_TXBD_SIZE, SDIO_TX_BD_NUM); + /* Set TX_BUFF_UNIT_SIZE */ +#if 0 + reg = HAL_SDIO_READ32(REG_SPDIO_RXBD_CNT); + reg &= ~((0xff)<<8); + reg |= (SDIO_TX_BD_BUF_USIZE<<8); + HAL_SDIO_WRITE32(REG_SPDIO_RXBD_CNT, reg); +#endif + HAL_SDIO_WRITE8(REG_SPDIO_TX_BUF_UNIT_SZ, SDIO_TX_BD_BUF_USIZE); + + DBG_SDIO_INFO("Tx BD Buf Unit Size(%d), Reg=0x%x\n", SDIO_TX_BD_BUF_USIZE, HAL_SDIO_READ8(REG_SPDIO_TX_BUF_UNIT_SZ)); + + /* Set DISPATCH_TXAGG_PKT */ + HAL_SDIO_WRITE32(REG_SPDIO_AHB_DMA_CTRL, HAL_SDIO_READ32(REG_SPDIO_AHB_DMA_CTRL)|BIT31); + // Reset HW TX BD pointer + pSDIODev->TXBDWPtr = HAL_SDIO_READ32(REG_SPDIO_TXBD_WPTR); + pSDIODev->TXBDRPtr = pSDIODev->TXBDWPtr; + pSDIODev->TXBDRPtrReg = pSDIODev->TXBDWPtr; + HAL_SDIO_WRITE32(REG_SPDIO_TXBD_RPTR, pSDIODev->TXBDRPtrReg); + + pSDIODev->pTXBDHdl = (PSDIO_TX_BD_HANDLE)RtlZmalloc(SDIO_TX_BD_NUM * sizeof(SDIO_TX_BD_HANDLE)); + if (NULL == pSDIODev->pTXBDHdl) { + DBG_SDIO_ERR("SDIO_Device_Init: Malloc for TX_BD Handle Err!!\n"); + goto SDIO_INIT_ERR; + } + + for (i=0;ipTXBDHdl + i; + pTxBdHdl->pTXBD = pSDIODev->pTXBDAddrAligned + i; + // Allocate buffer for each TX BD + pTxBdHdl->pTXBD->Address = (u32)RtlMalloc(SDIO_TX_BD_BUF_USIZE*SDIO_TX_BUF_SZ_UNIT); +#if SDIO_DEBUG + pSDIODev->MemAllocCnt++; +#endif + if (NULL == pTxBdHdl->pTXBD->Address) { + // Memory Allocate Failed + int j; + + for (j=0;jpTXBDHdl + j; + pTxBdHdl->pTXBD = pSDIODev->pTXBDAddrAligned + j; + if (pTxBdHdl->pTXBD->Address) { + RtlMfree((u8 *)pTxBdHdl->pTXBD->Address, (SDIO_TX_BD_BUF_USIZE*SDIO_TX_BUF_SZ_UNIT)); + } + } + goto SDIO_INIT_ERR; + } + pTxBdHdl->isFree = 1; + DBG_SDIO_INFO("TX_BD%d @ 0x%x 0x%x\n", i, pTxBdHdl, pTxBdHdl->pTXBD); + } + + + RtlInitListhead(&pSDIODev->FreeTxPktList); // Init the list for free packet handler + /* Allocate memory for TX Packets handler */ + pSDIODev->pTxPktHandler = (SDIO_TX_PACKET *)(RtlZmalloc(sizeof(SDIO_TX_PACKET)*SDIO_TX_PKT_NUM)); + if (NULL == pSDIODev->pTxPktHandler) { + DBG_SDIO_ERR("SDIO_Device_Init: Malloc for TX PKT Handler Err!!\n"); + goto SDIO_INIT_ERR; + } + /* Add all TX packet handler into the Free Queue(list) */ + for (i=0;ipTxPktHandler + i; + RtlListInsertTail(&pTxPkt->list, &pSDIODev->FreeTxPktList); + } + + /* Init RX BD and RX Buffer */ + pSDIODev->pRXBDAddr = RtlZmalloc((SDIO_RX_BD_NUM * sizeof(SDIO_RX_BD))+7); + if (NULL == pSDIODev->pRXBDAddr) { + DBG_SDIO_ERR("SDIO_Device_Init: Malloc for RX_BD Err!!\n"); + goto SDIO_INIT_ERR; + } + pSDIODev->pRXBDAddrAligned = (PSDIO_RX_BD)(((((u32)pSDIODev->pRXBDAddr - 1) >> 3) + 1) << 3); // Make it 8-bytes aligned + HAL_SDIO_WRITE32(REG_SPDIO_RXBD_ADDR, pSDIODev->pRXBDAddrAligned); + HAL_SDIO_WRITE16(REG_SPDIO_RXBD_SIZE, SDIO_RX_BD_NUM); + + // Set the threshold of free RX BD count to trigger interrupt + HAL_SDIO_WRITE16(REG_SPDIO_RX_BD_FREE_CNT, RX_BD_FREE_TH); + DBG_SDIO_INFO("Rx BD Free Cnt(%d), Reg=0x%x\n", RX_BD_FREE_TH, HAL_SDIO_READ16(REG_SPDIO_RX_BD_FREE_CNT)); + + pSDIODev->pRXBDHdl = (PSDIO_RX_BD_HANDLE)RtlZmalloc(SDIO_RX_BD_NUM * sizeof(SDIO_RX_BD_HANDLE)); + if (NULL == pSDIODev->pRXBDHdl) { + DBG_SDIO_ERR("SDIO_Device_Init: Malloc for RX_BD Handle Err!!\n"); + goto SDIO_INIT_ERR; + } + + for (i=0;ipRXBDHdl + i; + pRxBdHdl->pRXBD = pSDIODev->pRXBDAddrAligned + i; + pRxBdHdl->isFree = 1; + DBG_SDIO_INFO("RX_BD%d @ 0x%x 0x%x\n", i, pRxBdHdl, pRxBdHdl->pRXBD); + } + + + RtlInitListhead(&pSDIODev->FreeRxPktList); // Init the list for free packet handler + /* Allocate memory for RX Packets handler */ + pSDIODev->pRxPktHandler = (SDIO_RX_PACKET *)(RtlZmalloc(sizeof(SDIO_RX_PACKET)*SDIO_RX_PKT_NUM)); + if (NULL == pSDIODev->pRxPktHandler) { + DBG_SDIO_ERR("SDIO_Device_Init: Malloc for RX PKT Handler Err!!\n"); + goto SDIO_INIT_ERR; + } + /* Add all RX packet handler into the Free Queue(list) */ + for (i=0;ipRxPktHandler + i; + RtlListInsertTail(&pPkt->list, &pSDIODev->FreeRxPktList); + } + RtlInitListhead(&pSDIODev->RxPktList); // Init the list for RX packet to be send to the SDIO bus +// RtlInitListhead(&pSDIODev->RecyclePktList); // Init the list for packet to be recycled after the SDIO RX DMA is done + + RtlMutexInit(&pSDIODev->RxMutex); +#if SDIO_DEBUG + RtlMutexInit(&pSDIODev->StatisticMutex); +#endif + /* Create a Semaphone for SDIO Sync control */ +#if !TASK_SCHEDULER_DISABLED + RtlInitSema(&(pSDIODev->TxSema), 0); + if (NULL == pSDIODev->TxSema){ + DBG_SDIO_ERR("SDIO_Device_Init Create Semaphore Err!!\n"); + goto SDIO_INIT_ERR; + } + + RtlInitSema(&(pSDIODev->RxSema), 0); + if (NULL == pSDIODev->RxSema){ + DBG_SDIO_ERR("SDIO_Device_Init Create RX Semaphore Err!!\n"); + goto SDIO_INIT_ERR; + } + + /* create a Mailbox for other driver module to send message to SDIO driver */ + pSDIODev->pMBox = RtlMailboxCreate(MBOX_ID_SDIO, SDIO_MAILBOX_SIZE, &(pSDIODev->RxSema)); + if (NULL == pSDIODev->pMBox) { + DBG_SDIO_ERR("SDIO_Device_Init Create Mailbox Err!!\n"); + goto SDIO_INIT_ERR; + } +#if SDIO_MP_MODE + pSDIODev->pPeriodTimer = RtlTimerCreate("SDIO_Periodical", SDIO_PERIODICAL_TIMER_INTERVAL, SDIO_PeriodicalTimerCallback, pSDIODev, 1); +#endif + /* Create the SDIO task */ +#ifdef PLATFORM_FREERTOS + ret = xTaskCreate( SDIO_TxTask, "SDIO_TX_TASK", ((1024*2)/sizeof(portBASE_TYPE)), (void *)pSDIODev, SDIO_TASK_PRIORITY, &pSDIODev->xSDIOTxTaskHandle); + if (pdTRUE != ret ) + { + DBG_SDIO_ERR("SDIO_Device_Init: Create Task Err(%d)!!\n", ret); + goto SDIO_INIT_ERR; + } + + ret = xTaskCreate( SDIO_RxTask, "SDIO_RX_TASK", ((1024*1)/sizeof(portBASE_TYPE)), (void *)pSDIODev, SDIO_TASK_PRIORITY, &pSDIODev->xSDIORxTaskHandle); + if (pdTRUE != ret ) + { + DBG_SDIO_ERR("SDIO_Device_Init: Create RX Task Err(%d)!!\n", ret); + goto SDIO_INIT_ERR; + } + +#endif +#endif // end of "#if !TASK_SCHEDULER_DISABLED" +#if SDIO_MP_MODE +//1 for MP mode test only + pSDIODev->MP_ModeEn = 1; +// SDIO_Register_Tx_Callback(pSDIODev, (VOID *)SDIO_MP_Loopback, (VOID *) pSDIODev); +// pSDIODev->MP_LoopBackEn = 1; +//End +#endif +#if TASK_SCHEDULER_DISABLED + /* enable the interrupt */ + SDIO_Interrupt_Init(pSDIODev); + + /* Indicate the Host system that the TX/RX is ready */ + HAL_SDIO_WRITE8(REG_SPDIO_CPU_IND, \ + HAL_SDIO_READ8(REG_SPDIO_CPU_IND)|BIT_SYSTEM_TRX_RDY_IND); +#endif + DBG_SDIO_INFO("<==SDIO_Device_Init\n"); + + return SUCCESS; + + SDIO_INIT_ERR: +#if !TASK_SCHEDULER_DISABLED + if (pSDIODev->TxSema) { + RtlFreeSema(&pSDIODev->TxSema); + pSDIODev->TxSema = NULL; + } + + if (pSDIODev->RxSema) { + RtlFreeSema(&pSDIODev->RxSema); + pSDIODev->RxSema = NULL; + } +#endif + + if (pSDIODev->RxMutex) { + RtlMutexFree(&pSDIODev->RxMutex); + } +#if SDIO_DEBUG + if (pSDIODev->StatisticMutex) { + RtlMutexFree(&pSDIODev->StatisticMutex); + } +#endif + if (pSDIODev->pRxPktHandler) { + RtlMfree((u8*)pSDIODev->pRxPktHandler, sizeof(SDIO_RX_PACKET)*SDIO_RX_PKT_NUM); + pSDIODev->pRxPktHandler = NULL; + } + + if (pSDIODev->pRXBDHdl) { + RtlMfree((u8 *)pSDIODev->pRXBDHdl, SDIO_RX_BD_NUM * sizeof(SDIO_RX_BD_HANDLE)); + pSDIODev->pRXBDHdl = NULL; + } + + if (pSDIODev->pRXBDAddr) { + RtlMfree((u8 *)pSDIODev->pRXBDAddr, (SDIO_RX_BD_NUM * sizeof(SDIO_RX_BD))+7); + pSDIODev->pRXBDAddr = NULL; + } + + if (pSDIODev->pTxPktHandler) { + RtlMfree((u8 *)pSDIODev->pTxPktHandler, (sizeof(SDIO_TX_PACKET)*SDIO_TX_PKT_NUM)); + pSDIODev->pTxPktHandler = NULL; + } + + if ((pSDIODev->pTXBDHdl) && (pSDIODev->pTXBDAddr)) { + for (i=0;ipTXBDHdl + i; + if (pTxBdHdl->pTXBD->Address) { + RtlMfree((u8 *)pTxBdHdl->pTXBD->Address, (SDIO_TX_BD_BUF_USIZE*SDIO_TX_BUF_SZ_UNIT)); + pTxBdHdl->pTXBD->Address = NULL; + } + } + } + + if (pSDIODev->pTXBDHdl) { + RtlMfree((u8 *)pSDIODev->pTXBDHdl, (SDIO_TX_BD_NUM * sizeof(SDIO_TX_BD_HANDLE))); + pSDIODev->pTXBDHdl = NULL; + } + + if (pSDIODev->pTXBDAddr) { + RtlMfree(pSDIODev->pTXBDAddr, ((SDIO_TX_BD_NUM * sizeof(SDIO_TX_BD))+3)); + pSDIODev->pTXBDAddr = NULL; + pSDIODev->pTXBDAddrAligned = NULL; + } + +#if !TASK_SCHEDULER_DISABLED + if (pSDIODev->pMBox) { + RtlMailboxDel(pSDIODev->pMBox); + pSDIODev->pMBox = NULL; + } +#if SDIO_MP_MODE + if (pSDIODev->pPeriodTimer) { + RtlTimerDelete(pSDIODev->pPeriodTimer); + pSDIODev->pPeriodTimer = NULL; + } +#endif +#endif + return FAIL; +} + + +/****************************************************************************** + * Function: SDIO_Device_DeInit + * Desc: SDIO device driver free resource. This function should be called in + * a task. + * 1. Free TX FIFO buffer + * + * Para: + * pSDIODev: The SDIO device data structor. + ******************************************************************************/ +//TODO: Call this function in a task + +VOID SDIO_Device_DeInit( + IN PHAL_SDIO_ADAPTER pSDIODev +) +{ + int i=0; + SDIO_TX_BD_HANDLE *pTxBdHdl; + + if (NULL == pSDIODev) + return; + +#if !TASK_SCHEDULER_DISABLED + /* Exit the SDIO task */ + SDIO_SetEvent(pSDIODev, SDIO_EVENT_EXIT); + SDIO_Wakeup_Task(pSDIODev); + + while (1) { + if (SDIO_IsEventPending(pSDIODev, SDIO_EVENT_TX_STOPPED) && + SDIO_IsEventPending(pSDIODev, (u32)SDIO_EVENT_RX_STOPPED)) { + SDIO_ClearEvent(pSDIODev, SDIO_EVENT_EXIT); + break; // break the while loop + } + RtlMsleepOS(10); + i++; + if (i> 100) { + DBG_SDIO_ERR("SDIO_Device_DeInit: Delete SDIO Task Failed with Timeout\n"); + break; + } + } +#if SDIO_MP_MODE + if (pSDIODev->pPeriodTimer) { + RtlTimerDelete(pSDIODev->pPeriodTimer); + pSDIODev->pPeriodTimer = NULL; + } +#endif + /* Delete the Mailbox */ + if (pSDIODev->pMBox) { + RtlMailboxDel(pSDIODev->pMBox); + pSDIODev->pMBox = NULL; + } + + /* Delete the Semaphore */ + if (pSDIODev->TxSema) { + RtlFreeSema(&pSDIODev->TxSema); + pSDIODev->TxSema = NULL; + } + + if (pSDIODev->RxSema) { + RtlFreeSema(&pSDIODev->RxSema); + pSDIODev->RxSema = NULL; + } +#endif + + if (pSDIODev->RxMutex) { + RtlMutexFree(&pSDIODev->RxMutex); + } +#if SDIO_DEBUG + if (pSDIODev->StatisticMutex) { + RtlMutexFree(&pSDIODev->StatisticMutex); + } +#endif + if (pSDIODev->pRxPktHandler) { + RtlMfree((u8*)pSDIODev->pRxPktHandler, sizeof(SDIO_RX_PACKET)*SDIO_RX_PKT_NUM); + pSDIODev->pRxPktHandler = NULL; + } + + if (pSDIODev->pRXBDHdl) { + RtlMfree((u8 *)pSDIODev->pRXBDHdl, SDIO_RX_BD_NUM * sizeof(SDIO_RX_BD_HANDLE)); + pSDIODev->pRXBDHdl = NULL; + } + + /* Free RX BD */ + if (pSDIODev->pRXBDAddr) { + RtlMfree((u8 *)pSDIODev->pRXBDAddr, (SDIO_RX_BD_NUM * sizeof(SDIO_RX_BD))+7); + pSDIODev->pRXBDAddr = NULL; + } + + /* Free TX FIFO Buffer */ + for (i=0;ipTXBDHdl + i; + if (pTxBdHdl->pTXBD->Address) { + RtlMfree((u8 *)pTxBdHdl->pTXBD->Address, (SDIO_TX_BD_BUF_USIZE*SDIO_TX_BUF_SZ_UNIT)); + pTxBdHdl->pTXBD->Address = NULL; + } + } + + if (pSDIODev->pTxPktHandler) { + RtlMfree((u8 *)pSDIODev->pTxPktHandler, (sizeof(SDIO_TX_PACKET)*SDIO_TX_PKT_NUM)); + pSDIODev->pTxPktHandler = NULL; + } + + if (pSDIODev->pTXBDHdl) { + RtlMfree((u8 *)pSDIODev->pTXBDHdl, (SDIO_TX_BD_NUM * sizeof(SDIO_TX_BD_HANDLE))); + pSDIODev->pTXBDHdl = NULL; + } + + if (pSDIODev->pTXBDAddr) { + RtlMfree(pSDIODev->pTXBDAddr, ((SDIO_TX_BD_NUM * sizeof(SDIO_TX_BD))+3)); + pSDIODev->pTXBDAddr = NULL; + pSDIODev->pTXBDAddrAligned = NULL; + } + +} + +#if TASK_SCHEDULER_DISABLED +/****************************************************************************** + * Function: SDIO_TaskUp + * Desc: For the Task scheduler no running case, use this function to run the + * SDIO task main loop. + * + * Para: + * pSDIODev: The SDIO device data structor. + ******************************************************************************/ +VOID SDIO_TaskUp( + IN PHAL_SDIO_ADAPTER pSDIODev +) +{ + u16 ISRStatus; + +// DiagPrintf("SDIO_TaskUp==>\n"); + pSDIODev->EventSema++; + if (pSDIODev->EventSema > 1000) { + pSDIODev->EventSema = 1000; + } + if (pSDIODev->EventSema == 1) { + while (pSDIODev->EventSema > 0) { + ISRStatus = HAL_SDIO_READ16(REG_SPDIO_CPU_INT_STAS); + pSDIODev->IntStatus |= ISRStatus; + HAL_SDIO_WRITE16(REG_SPDIO_CPU_INT_STAS, ISRStatus); // clean the ISR + SDIO_SetEvent(pSDIODev, SDIO_EVENT_IRQ|SDIO_EVENT_C2H_DMA_DONE); + + SDIO_TxTask(pSDIODev); + SDIO_RxTask(pSDIODev); + + pSDIODev->EventSema--; + } + } +// DiagPrintf("<==SDIO_TaskUp\n"); +} +#endif + +/****************************************************************************** + * Function: SDIO_IRQ_Handler + * Desc: SDIO device interrupt service routine + * 1. Read & clean the interrupt status + * 2. Wake up the SDIO task to handle the IRQ event + * + * Para: + * pSDIODev: The SDIO device data structor. + ******************************************************************************/ +VOID SDIO_IRQ_Handler( + IN VOID *pData +) +{ + PHAL_SDIO_ADAPTER pSDIODev = pData; + u16 ISRStatus; + + ISRStatus = HAL_SDIO_READ16(REG_SPDIO_CPU_INT_STAS); + DBG_SDIO_INFO("%s:ISRStatus=0x%x\n", __FUNCTION__, ISRStatus); + + pSDIODev->IntStatus |= ISRStatus; + HAL_SDIO_WRITE16(REG_SPDIO_CPU_INT_STAS, ISRStatus); // clean the ISR +#if !TASK_SCHEDULER_DISABLED + if (ISRStatus & BIT_C2H_DMA_OK) { + SDIO_SetEvent(pSDIODev, SDIO_EVENT_C2H_DMA_DONE); + RtlUpSemaFromISR(&pSDIODev->RxSema); + } + + if (ISRStatus & ~BIT_C2H_DMA_OK) { + SDIO_SetEvent(pSDIODev, SDIO_EVENT_IRQ); + RtlUpSemaFromISR(&pSDIODev->TxSema); + } +#else + SDIO_SetEvent(pSDIODev, SDIO_EVENT_IRQ|SDIO_EVENT_C2H_DMA_DONE); + SDIO_TaskUp(pSDIODev); +#endif +} + +/****************************************************************************** + * Function: SDIO_Interrupt_Init + * Desc: SDIO device interrupt initialization. + * 1. Register the ISR + * 2. Initial the IMR register + * + * Para: + * pSDIODev: The SDIO device data structor. + ******************************************************************************/ +VOID SDIO_Interrupt_Init( + IN PHAL_SDIO_ADAPTER pSDIODev +) +{ + IRQ_HANDLE SdioIrqHandle; + + pSDIODev->IntMask = BIT_H2C_DMA_OK | BIT_C2H_DMA_OK | BIT_H2C_MSG_INT | BIT_RPWM1_INT | \ + BIT_H2C_BUS_RES_FAIL | BIT_RXBD_FLAG_ERR_INT; + HAL_SDIO_WRITE16(REG_SPDIO_CPU_INT_STAS, pSDIODev->IntMask); // Clean pending interrupt first + + SdioIrqHandle.Data = (u32) pSDIODev; + SdioIrqHandle.IrqNum = SDIO_DEVICE_IRQ; + SdioIrqHandle.IrqFun = (IRQ_FUN) SDIO_IRQ_Handler; + SdioIrqHandle.Priority = SDIO_IRQ_PRIORITY; + + InterruptRegister(&SdioIrqHandle); + InterruptEn(&SdioIrqHandle); + + HAL_SDIO_WRITE16(REG_SPDIO_CPU_INT_MASK, pSDIODev->IntMask); +} + +/****************************************************************************** + * Function: SDIO_Enable_Interrupt + * Desc: SDIO enable interrupt by modify the interrupt mask + * + * Para: + * pSDIODev: The SDIO device data structor. + * IntMask: The bit map to enable the interrupt. + ******************************************************************************/ +__inline VOID SDIO_Enable_Interrupt( + IN PHAL_SDIO_ADAPTER pSDIODev, + IN u32 IntMask +) +{ + RtlEnterCritical(); + pSDIODev->IntMask |= IntMask; + HAL_SDIO_WRITE16(REG_SPDIO_CPU_INT_MASK, pSDIODev->IntMask); + RtlExitCritical(); +} + +/****************************************************************************** + * Function: SDIO_Disable_Interrupt + * Desc: SDIO disable interrupt by modify the interrupt mask + * + * Para: + * pSDIODev: The SDIO device data structor. + * IntMask: The bit map to disable the interrupt. + ******************************************************************************/ +__inline VOID SDIO_Disable_Interrupt( + IN PHAL_SDIO_ADAPTER pSDIODev, + IN u32 IntMask +) +{ + RtlEnterCritical(); + pSDIODev->IntMask &= ~IntMask; + HAL_SDIO_WRITE16(REG_SPDIO_CPU_INT_MASK, pSDIODev->IntMask); + RtlExitCritical(); +} + +/****************************************************************************** + * Function: SDIO_Clear_ISR + * Desc: SDIO clear ISR bit map. + * + * Para: + * pSDIODev: The SDIO device data structor. + * IntMask: The bit map to be clean. + ******************************************************************************/ +__inline VOID SDIO_Clear_ISR( + IN PHAL_SDIO_ADAPTER pSDIODev, + IN u32 IntMask +) +{ + RtlEnterCritical(); + pSDIODev->IntStatus &= ~IntMask; + RtlExitCritical(); +} + +/****************************************************************************** + * Function: SDIO_TxTask + * Desc: The SDIO task handler. This is the main function of the SDIO device + * driver. + * 1. Handle interrupt events. + * * SDIO TX data ready + * * Error handling + * 2. + * + * Para: + * pSDIODev: The SDIO device data structor. + ******************************************************************************/ +VOID SDIO_TxTask( + IN VOID *pData +) +{ + PHAL_SDIO_ADAPTER pSDIODev = pData; + MSG_BLK Mblk; + + /* Initial resource */ +#if !TASK_SCHEDULER_DISABLED + /* enable the interrupt */ + SDIO_Interrupt_Init(pSDIODev); + + /* Indicate the Host system that the TX/RX is ready */ + HAL_SDIO_WRITE8(REG_SPDIO_CPU_IND, \ + HAL_SDIO_READ8(REG_SPDIO_CPU_IND)|BIT_SYSTEM_TRX_RDY_IND); +#if SDIO_MP_MODE + if (pSDIODev->pPeriodTimer) { + RtlTimerStart(pSDIODev->pPeriodTimer, 0); + } +#endif +#endif + +#if !TASK_SCHEDULER_DISABLED + for (;;) +#endif + { + /* Task blocked and wait the semaphore(events) here */ +#if !TASK_SCHEDULER_DISABLED + RtlDownSema(&pSDIODev->TxSema); +#endif + if (SDIO_IsEventPending(pSDIODev, SDIO_EVENT_IRQ)) { + SDIO_ClearEvent(pSDIODev, SDIO_EVENT_IRQ); + SDIO_IRQ_Handler_BH(pSDIODev); + } + + if (SDIO_IsEventPending(pSDIODev, SDIO_EVENT_TXBD_REFILL)) { + SDIO_ClearEvent(pSDIODev, SDIO_EVENT_TXBD_REFILL); + SDIO_TX_BD_Buf_Refill(pSDIODev); + } + +#if !TASK_SCHEDULER_DISABLED + if (SDIO_IsEventPending(pSDIODev, SDIO_EVENT_EXIT)) { + break; // break the loop to exit the task + } +#endif + } + +#if !TASK_SCHEDULER_DISABLED +#if SDIO_MP_MODE + if (pSDIODev->pPeriodTimer) { + RtlTimerStop(pSDIODev->pPeriodTimer, 0); + } +#endif + SDIO_SetEvent(pSDIODev, SDIO_EVENT_TX_STOPPED); + DBG_SDIO_INFO("SDIO TX Task Stopped!\n"); +#if ( INCLUDE_vTaskDelete == 1 ) + vTaskDelete(NULL); +#endif +#endif +} + +/****************************************************************************** + * Function: SDIO_RxTask + * Desc: The SDIO RX task handler. This is the main function of the SDIO device + * driver to handle SDIO RX. + * 1. Handle interrupt events. + * * SDIO RX done + * 2. Send RX data back to the host by fill RX_BD to hardware. + * 3. Handle messages from mailbox + * + * Para: + * pSDIODev: The SDIO device data structor. + ******************************************************************************/ +VOID SDIO_RxTask( + IN VOID *pData +) +{ + PHAL_SDIO_ADAPTER pSDIODev = pData; + MSG_BLK Mblk; + +#if !TASK_SCHEDULER_DISABLED + for (;;) +#endif + { + /* Task blocked and wait the semaphore(events) here */ +#if !TASK_SCHEDULER_DISABLED + RtlDownSema(&pSDIODev->RxSema); +#endif + if (SDIO_IsEventPending(pSDIODev, SDIO_EVENT_C2H_DMA_DONE)) { + SDIO_ClearEvent(pSDIODev, SDIO_EVENT_C2H_DMA_DONE); + SDIO_RX_IRQ_Handler_BH(pSDIODev); + } + +#if SDIO_MP_MODE + if (pSDIODev->MP_ContinueRx) { + SDIO_MP_ContinueRx(pSDIODev); + } +#endif // end of "#if SDIO_MP_MODE" + + if (SDIO_IsEventPending(pSDIODev, SDIO_EVENT_RX_PKT_RDY)) { + SDIO_ClearEvent(pSDIODev, SDIO_EVENT_RX_PKT_RDY); + SDIO_Return_Rx_Data(pSDIODev); + } + +#if !TASK_SCHEDULER_DISABLED + /* handle message block in the mailbox */ + do { + if (_SUCCESS == RtlMailboxReceive(MBOX_ID_SDIO, &Mblk, MBOX_WAIT_NONE, 0)) { + SDIO_Handle_MsgBlk(pSDIODev, &Mblk); + } + else { + break; // no more message pending, break the while loop + } + } while (1); + + if (SDIO_IsEventPending(pSDIODev, SDIO_EVENT_EXIT)) { + break; // break the loop to exit the task + } +#endif + } + +#if !TASK_SCHEDULER_DISABLED + SDIO_SetEvent(pSDIODev, (u32)SDIO_EVENT_RX_STOPPED); + DBG_SDIO_INFO("SDIO RX Task Stopped!\n"); +#if ( INCLUDE_vTaskDelete == 1 ) + vTaskDelete(NULL); +#endif +#endif +} + + +/****************************************************************************** + * Function: SDIO_Wakeup_Task + * Desc: Send a semaphore to wake up the task. + * + * Para: + * pSDIODev: The SDIO device data structor. + ******************************************************************************/ +static __inline VOID SDIO_Wakeup_Task( + IN PHAL_SDIO_ADAPTER pSDIODev +) +{ +#if !TASK_SCHEDULER_DISABLED + RtlUpSema(&pSDIODev->TxSema); + RtlUpSema(&pSDIODev->RxSema); +#else + SDIO_TaskUp(pSDIODev); +#endif +} + +/****************************************************************************** + * Function: SDIO_SetEvent + * Desc: Set an event and wake up SDIO task to handle it. + * + * Para: + * pSDIODev: The SDIO device data structor. + * Event: The event to be set. + ******************************************************************************/ +static VOID SDIO_SetEvent( + IN PHAL_SDIO_ADAPTER pSDIODev, + IN u32 Event +) +{ + RtlEnterCritical(); + pSDIODev->Events |= Event; + RtlExitCritical(); +} + +/****************************************************************************** + * Function: SDIO_ClearEvent + * Desc: Clean a SDIO event. + * + * Para: + * pSDIODev: The SDIO device data structor. + * Event: The event to be cleaned. + ******************************************************************************/ +static VOID SDIO_ClearEvent( + IN PHAL_SDIO_ADAPTER pSDIODev, + IN u32 Event +) +{ + RtlEnterCritical(); + pSDIODev->Events &= ~Event; + RtlExitCritical(); +} + +/****************************************************************************** + * Function: SDIO_IsEventPending + * Desc: To check is a event pending. + * + * Para: + * pSDIODev: The SDIO device data structor. + * Event: The event to check. + ******************************************************************************/ +static BOOL SDIO_IsEventPending( + IN PHAL_SDIO_ADAPTER pSDIODev, + IN u32 Event +) +{ + BOOL ret; + + RtlEnterCritical(); + ret = (pSDIODev->Events & Event) ? 1:0; + RtlExitCritical(); + + return ret; +} + +/****************************************************************************** + * Function: SDIO_IRQ_Handler_BH + * Desc: Process the SDIO IRQ, the button helf. + * 1. SDIO TX data ready. + * 2. H2C command ready. + * 3. Host driver RPWM status updated. + * 4. SDIO RX data transfer done. + * 5. SDIO HW/BUS errors. + * + * Para: + * pSDIODev: The SDIO device data structor. + ******************************************************************************/ +VOID SDIO_IRQ_Handler_BH( + IN PHAL_SDIO_ADAPTER pSDIODev +) +{ + u32 IntStatus; + + DBG_SDIO_INFO("%s @1 IntStatus=0x%x\n", __FUNCTION__, pSDIODev->IntStatus); + + RtlEnterCritical(); + IntStatus = pSDIODev->IntStatus; + RtlExitCritical(); + + if (IntStatus & BIT_H2C_DMA_OK) { + SDIO_Clear_ISR(pSDIODev, BIT_H2C_DMA_OK); + SDIO_Disable_Interrupt(pSDIODev, BIT_H2C_DMA_OK); + SDIO_TX_FIFO_DataReady(pSDIODev); + SDIO_Enable_Interrupt(pSDIODev, BIT_H2C_DMA_OK); + } + + if (IntStatus & BIT_H2C_MSG_INT) { + SDIO_Clear_ISR(pSDIODev, BIT_H2C_MSG_INT); + SDIO_Process_H2C_IOMsg(pSDIODev); + } + + if (IntStatus & BIT_RPWM1_INT) { + SDIO_Clear_ISR(pSDIODev, BIT_RPWM1_INT); + SDIO_Process_RPWM(pSDIODev); + } + + if (IntStatus & BIT_SDIO_RST_CMD_INT) { + SDIO_Clear_ISR(pSDIODev, BIT_SDIO_RST_CMD_INT); + SDIO_Reset_Cmd(pSDIODev); + } + + DBG_SDIO_INFO("%s @2 IntStatus=0x%x\n", __FUNCTION__, pSDIODev->IntStatus); +} + +/****************************************************************************** + * Function: SDIO_RX_IRQ_Handler_BH + * Desc: Process the SDIO RX IRQ, the button helf. + * 1. SDIO RX data transfer done. + * + * Para: + * pSDIODev: The SDIO device data structor. + ******************************************************************************/ +VOID SDIO_RX_IRQ_Handler_BH( + IN PHAL_SDIO_ADAPTER pSDIODev +) +{ + u32 IntStatus; + + RtlEnterCritical(); + IntStatus = pSDIODev->IntStatus; + RtlExitCritical(); + + if (IntStatus & BIT_C2H_DMA_OK) { + SDIO_Clear_ISR(pSDIODev, BIT_C2H_DMA_OK); + SDIO_Recycle_Rx_BD(pSDIODev); +// SDIO_Return_Rx_Data(pSDIODev); + } +} + + +/****************************************************************************** + * Function: SDIO_TX_BD_Buf_Refill + * Desc: To refill all TX BD buffer. + * 1. Check all TX BD buffer + * 2. Allocate a new buffer for TX BD buffer is invalid + * + * Para: + * pSDIODev: The SDIO device data structor. + ******************************************************************************/ +VOID SDIO_TX_BD_Buf_Refill( + IN PHAL_SDIO_ADAPTER pSDIODev +) +{ + u32 i,j; + u32 wait_loop; + PSDIO_TX_BD_HANDLE pTxBdHdl; + #define WAIT_TIMEOUT 100 + + for (i=0;ipTXBDHdl + pSDIODev->TXBDRPtrReg; + if (NULL == pTxBdHdl->pTXBD->Address) { + for (j=0;jpTXBD->Address = (u32)RtlMalloc(SDIO_TX_BD_BUF_USIZE*SDIO_TX_BUF_SZ_UNIT); + if (NULL == pTxBdHdl->pTXBD->Address) { + DBG_SDIO_WARN("%s Alloc Mem(size=%d) Failed\n", __FUNCTION__, SDIO_TX_BD_BUF_USIZE*SDIO_TX_BUF_SZ_UNIT); + RtlMsleepOS(20); + } + else { +#if SDIO_DEBUG + pSDIODev->MemAllocCnt++; +#endif + pSDIODev->TXBDRPtrReg++; + if (pSDIODev->TXBDRPtrReg >= SDIO_TX_BD_NUM) { + pSDIODev->TXBDRPtrReg = 0; + } + HAL_SDIO_WRITE16(REG_SPDIO_TXBD_RPTR, pSDIODev->TXBDRPtrReg); + break; // break the for loop + } + } + if (j == WAIT_TIMEOUT) { + break; // break the for loop + } + } + else { + break; // break the for loop + } + } + + if (pSDIODev->TXBDRPtrReg != pSDIODev->TXBDRPtr) { + DBG_SDIO_ERR("SDIO_TX_BD_Buf_Refill Err: TXBDRPtrReg=%d TXBDRPtr=%d\n", pSDIODev->TXBDRPtrReg, pSDIODev->TXBDRPtr); + } +} + + +/****************************************************************************** + * Function: SDIO_TX_FIFO_DataReady + * Desc: Handle the SDIO FIFO data ready interrupt. + * 1. Send those data to the target driver via callback fun., like WLan. + * 2. Allocate a buffer for the TX BD + * + * Para: + * pSDIODev: The SDIO device data structor. + ******************************************************************************/ +VOID SDIO_TX_FIFO_DataReady( + IN PHAL_SDIO_ADAPTER pSDIODev +) +{ + PSDIO_TX_BD_HANDLE pTxBdHdl; + PSDIO_TX_DESC pTxDesc; + volatile u16 TxBDWPtr=0; + u32 processed_pkt_cnt=0; + u8 isForceBreak=0; + s8 ret=FAIL; + u32 mem_alloc_failed=0; + + +// DBG_SDIO_INFO("SDIO_TX_FIFO_DataReady==>\n"); + + TxBDWPtr = HAL_SDIO_READ16(REG_SPDIO_TXBD_WPTR); + if (TxBDWPtr == pSDIODev->TXBDRPtr) { + if ((pSDIODev->IntStatus & BIT_TXFIFO_H2C_OVF) == 0) { + DBG_SDIO_WARN("SDIO TX Data Read False Triggered!!, TXBDWPtr=0x%x\n", TxBDWPtr); + return; + } + } + + do { + DBG_SDIO_INFO("SDIO_TX_DataReady: TxBDWPtr=%d TxBDRPtr=%d\n", TxBDWPtr, pSDIODev->TXBDRPtr); + pTxBdHdl = pSDIODev->pTXBDHdl + pSDIODev->TXBDRPtr; + pTxDesc = (PSDIO_TX_DESC)(pTxBdHdl->pTXBD->Address); + + DBG_SDIO_INFO("SDIO_TX_DataReady: PktSz=%d Offset=%d\n", pTxDesc->txpktsize, pTxDesc->offset); + if ((pTxDesc->txpktsize + pTxDesc->offset) > (SDIO_TX_BD_BUF_USIZE*SDIO_TX_BUF_SZ_UNIT)) { + DBG_SDIO_WARN("SDIO_TX_DataReady Err: Incorrect TxDesc, PktSz=%d Offset=%d BufSize=%d\n", pTxDesc->txpktsize, pTxDesc->offset, \ + (SDIO_TX_BD_BUF_USIZE*SDIO_TX_BUF_SZ_UNIT)); + } + // use the callback function to fordward this packet to target(WLan) driver + if (pSDIODev->Tx_Callback) { +#if 1 + ret = pSDIODev->Tx_Callback(pSDIODev->pTxCb_Adapter, (u8*)pTxBdHdl->pTXBD->Address, pTxDesc->offset, pTxDesc->txpktsize); // includes TX Desc +#else + ret = pSDIODev->Tx_Callback(pSDIODev->pTxCb_Adapter, // doesn't include TX Desc + (u8*)(pTxBdHdl->pTXBD->Address+pTxDesc->offset), + pTxDesc->txpktsize); +#endif + } + else { + ret = FAIL; + DBG_SDIO_ERR("SDIO TX_Callback is Null!\n"); + } + processed_pkt_cnt++; + if (SUCCESS != ret) { + // may be is caused by TX queue is full, so we skip it and try again later + isForceBreak = 1; + break; // break the while loop + } + else { +#if SDIO_MP_MODE + pSDIODev->MP_TxPktCnt++; + pSDIODev->MP_TxByteCnt += pTxDesc->txpktsize; + + pSDIODev->MP_TxPktCntInPeriod++; + pSDIODev->MP_TxByteCntInPeriod += pTxDesc->txpktsize; +#endif + pSDIODev->TXBDRPtr++; + if (pSDIODev->TXBDRPtr >= SDIO_TX_BD_NUM) { + pSDIODev->TXBDRPtr = 0; + } + + // allocate a new buffer for this TX BD + // buf once if the memory allocation failed, we will try it later + if (mem_alloc_failed == 0) { + pTxBdHdl->pTXBD->Address = (u32)RtlMalloc(SDIO_TX_BD_BUF_USIZE*SDIO_TX_BUF_SZ_UNIT); + if (NULL == pTxBdHdl->pTXBD->Address) { + // memory allocate error + // once memory allocate failed, stop to allocate new buffer for TX BD buffer + //, we refill TX BD buffer later + DBG_SDIO_WARN("%s: Alloc new TX BD Buf Failed\n", __FUNCTION__); + mem_alloc_failed++; + SDIO_SetEvent(pSDIODev, SDIO_EVENT_TXBD_REFILL); + } + else { +#if SDIO_DEBUG + pSDIODev->MemAllocCnt++; +#endif + pSDIODev->TXBDRPtrReg = pSDIODev->TXBDRPtr; + HAL_SDIO_WRITE16(REG_SPDIO_TXBD_RPTR, pSDIODev->TXBDRPtrReg); + } + } + else { + pTxBdHdl->pTXBD->Address = NULL; + } + } + + TxBDWPtr = HAL_SDIO_READ16(REG_SPDIO_TXBD_WPTR); + if (isForceBreak) { + break; // break the TX FIFO DMA Done processing + } + } while (pSDIODev->TXBDRPtr != TxBDWPtr); + + // if not all TX data were processed, set an event to trigger SDIO_Task to process them later + if (isForceBreak) { + DBG_SDIO_WARN("SDIO_TX Force Break: TXBDWP=0x%x TXBDRP=0x%x\n", TxBDWPtr, pSDIODev->TXBDRPtr); + RtlEnterCritical(); + if ((pSDIODev->IntStatus & BIT_TXFIFO_H2C_OVF) != 0) { + if (pSDIODev->TXBDRPtr != TxBDWPtr) { + pSDIODev->IntStatus &= ~BIT_TXFIFO_H2C_OVF; + } + } + pSDIODev->IntStatus |= BIT_H2C_DMA_OK; + RtlExitCritical(); + SDIO_SetEvent(pSDIODev, SDIO_EVENT_IRQ); +#if !TASK_SCHEDULER_DISABLED + RtlUpSema(&pSDIODev->TxSema); +#else + SDIO_TaskUp(pSDIODev); +#endif + } + else { + if ((pSDIODev->IntStatus & BIT_TXFIFO_H2C_OVF) != 0) { + SDIO_Clear_ISR(pSDIODev, BIT_TXFIFO_H2C_OVF); + } + } +} + +/****************************************************************************** + * Function: SDIO_Alloc_Rx_Pkt + * Desc: Allocate a RX Packet Handle from the queue. + * + * Para: + * pSDIODev: The SDIO device data structor. + * + * Return: + * The allocated RX packet handler. + ******************************************************************************/ +PSDIO_RX_PACKET SDIO_Alloc_Rx_Pkt( + IN PHAL_SDIO_ADAPTER pSDIODev +) +{ + _LIST *plist; + SDIO_RX_PACKET *pPkt; + u32 loop_cnt; + + RtlDownMutex(&pSDIODev->RxMutex); + if (RtlIsListEmpty(&pSDIODev->FreeRxPktList)) { + RtlUpMutex(&pSDIODev->RxMutex); + loop_cnt = 0; + do { + pPkt =(SDIO_RX_PACKET *)RtlZmalloc(sizeof(SDIO_RX_PACKET)); + if (NULL != pPkt) { + pPkt->isDyna = 1; // this packet handler is dynamic allocated + DBG_SDIO_WARN("Warn! No Free RX PKT, Use Dyna Alloc\n"); + } + else { + RtlMsleepOS(10); + loop_cnt++; + if (loop_cnt > 100) { + DBG_SDIO_ERR("SDIO_Alloc_Rx_Pkt: Err!! Allocate RX PKT Failed!!\n"); + break; + } + } + }while (NULL == pPkt); + return pPkt; + } + + plist = RtlListGetNext(&pSDIODev->FreeRxPktList); + pPkt = CONTAINER_OF(plist, SDIO_RX_PACKET, list); + + RtlListDelete(&pPkt->list); + RtlUpMutex(&pSDIODev->RxMutex); + return pPkt; +} + +/****************************************************************************** + * Function: SDIO_Free_Rx_Pkt + * Desc: Put a RX Packet Handle back to the queue. + * + * Para: + * pSDIODev: The SDIO device data structor. + * pPkt: The packet handler to be free. + * + ******************************************************************************/ +VOID SDIO_Free_Rx_Pkt( + IN PHAL_SDIO_ADAPTER pSDIODev, + IN PSDIO_RX_PACKET pPkt +) +{ + if (pPkt->isDyna) { + RtlMfree((u8 *)pPkt, sizeof(SDIO_RX_PACKET)); + } + else { + RtlDownMutex(&pSDIODev->RxMutex); + RtlListInsertTail(&pPkt->list, &pSDIODev->FreeRxPktList); + RtlUpMutex(&pSDIODev->RxMutex); + } +} + +/****************************************************************************** + * Function: SDIO_Recycle_Rx_BD + * Desc: To recycle some RX BD when C2H RX DMA done. + * 1. Free the RX packet. + * + * Para: + * pSDIODev: The SDIO device data structor. + ******************************************************************************/ +VOID SDIO_Recycle_Rx_BD ( + IN PHAL_SDIO_ADAPTER pSDIODev +) +{ + SDIO_RX_BD_HANDLE *pRxBdHdl; + SDIO_RX_BD *pRXBD; + u32 PktSize; + u32 FreeCnt=0; // for debugging + + DBG_SDIO_INFO("SDIO_Recycle_Rx_BD==> %d %d\n", HAL_SDIO_READ16(REG_SPDIO_RXBD_C2H_RPTR), pSDIODev->RXBDRPtr); + SDIO_Disable_Interrupt(pSDIODev, BIT_C2H_DMA_OK); + while (HAL_SDIO_READ16(REG_SPDIO_RXBD_C2H_RPTR) != pSDIODev->RXBDRPtr) + { + pRxBdHdl = pSDIODev->pRXBDHdl + pSDIODev->RXBDRPtr; + pRXBD = pSDIODev->pRXBDAddrAligned + pSDIODev->RXBDRPtr; + if (!pRxBdHdl->isFree) { + if (pRxBdHdl->isPktEnd && (NULL != pRxBdHdl->pPkt)) { + /* Free this packet */ + // TODO: The RX_DESC format may needs to be refined + PktSize = pRxBdHdl->pPkt->RxDesc.pkt_len; +#if SDIO_MP_MODE + if ((pSDIODev->MP_CRxPktPendingCnt > 0)) { + pSDIODev->MP_CRxPktPendingCnt--; + } + + if (((pSDIODev->MP_CRxPktCnt == 0) && (pSDIODev->MP_CRxPktPendingCnt == 0)) || + (SDIO_CRX_DYNA_BUF == pSDIODev->MP_ContinueRxMode)) +#endif + { +#if CONFIG_INIC_EN + RtlMfree((u8 *) (pRxBdHdl->pPkt->pData), (pRxBdHdl->pPkt->Offset+PktSize)); // free packet buffer +#else + RtlMfree((u8 *) (pRxBdHdl->pPkt->pData), (pRxBdHdl->pPkt->Offset+PktSize)); // free packet buffer +#if SDIO_DEBUG + RtlDownMutex(&pSDIODev->StatisticMutex); + pSDIODev->MemAllocCnt--; + RtlUpMutex(&pSDIODev->StatisticMutex); +#endif +#endif +#if SDIO_MP_MODE + pSDIODev->pMP_CRxBuf = NULL; +#endif + } + + _memset((void *)&(pRxBdHdl->pPkt->RxDesc), 0, sizeof(SDIO_RX_DESC)); + RtlListInsertTail(&pRxBdHdl->pPkt->list, &pSDIODev->FreeRxPktList); // Put packet handle to free queue + FreeCnt++; + pRxBdHdl->isPktEnd = 0; + pRxBdHdl->pPkt = NULL; + DBG_SDIO_INFO("SDIO_Recycle_Rx_BD: Recycle Pkt, RXBDRPtr=%d\n", pSDIODev->RXBDRPtr); +#if SDIO_MP_MODE + pSDIODev->MP_RxPktCnt++; + pSDIODev->MP_RxByteCnt += PktSize; + + pSDIODev->MP_RxPktCntInPeriod++; + pSDIODev->MP_RxByteCntInPeriod += PktSize; +#endif + } + _memset((void *)pRXBD , 0, sizeof(SDIO_RX_BD)); // clean this RX_BD + pRxBdHdl->isFree = 1; + } + else { + DBG_SDIO_WARN("SDIO_Recycle_Rx_BD: Warring, Recycle a Free RX_BD,RXBDRPtr=%d\n",pSDIODev->RXBDRPtr); + } + pSDIODev->RXBDRPtr++; + if (pSDIODev->RXBDRPtr >= SDIO_RX_BD_NUM) { + pSDIODev->RXBDRPtr -= SDIO_RX_BD_NUM; + } + } + SDIO_Enable_Interrupt(pSDIODev, BIT_C2H_DMA_OK); + DBG_SDIO_INFO("<==SDIO_Recycle_Rx_BD(%d)\n", FreeCnt); + +} + +/****************************************************************************** + * Function: SDIO_Process_H2C_IOMsg + * Desc: Handle the interrupt for HC2 message ready. Read the H2C_MSG register + * and process the H2C message. + * + * Para: + * pSDIODev: The SDIO device data structor. + ******************************************************************************/ +VOID SDIO_Process_H2C_IOMsg( + IN PHAL_SDIO_ADAPTER pSDIODev +) +{ + u32 H2CMsg; + + // TODO: define H2C message type & format, currently we have 30 bits message only, may needs to extend the HW register + H2CMsg = HAL_SDIO_READ32(REG_SPDIO_CPU_H2C_MSG); + DBG_SDIO_INFO("H2C_MSG: 0x%x\n", H2CMsg); + // TODO: May needs to handle endian free + switch (H2CMsg) + { + default: + break; + } + // TODO: Some H2C message needs to be fordward to WLan driver +} + +/****************************************************************************** + * Function: SDIO_Send_C2H_IOMsg + * Desc: Send C2H message to the Host. + * + * Para: + * pSDIODev: The SDIO device data structor. + ******************************************************************************/ +VOID SDIO_Send_C2H_IOMsg( + IN PHAL_SDIO_ADAPTER pSDIODev, + IN u32 *C2HMsg +) +{ + u32 TmpC2HMsg; + + // TODO: define C2H message type & format, currently we have 30 bits message only, may needs to extend the HW register + + // TODO: May needs to handle endian free + TmpC2HMsg = HAL_SDIO_READ32(REG_SPDIO_CPU_C2H_MSG); + TmpC2HMsg = ((TmpC2HMsg ^ (u32)BIT(31)) & (u32)BIT(31)) | *C2HMsg; + HAL_SDIO_WRITE32(REG_SPDIO_CPU_C2H_MSG, TmpC2HMsg); +} + +/****************************************************************************** + * Function: SDIO_Process_H2C_PktMsg + * Desc: Handle the packet H2C message which from block write(CMD53). + * + * Para: + * pSDIODev: The SDIO device data structor. + * H2CMsg: point to the buffer of the H2C message received. + ******************************************************************************/ +VOID SDIO_Process_H2C_PktMsg( + IN PHAL_SDIO_ADAPTER pSDIODev, + IN u8 *H2CMsg +) +{ + + // TODO: define H2C message type & format + DBG_SDIO_INFO("H2C_MSG: 0x%x\n", *H2CMsg); + // TODO: May needs to handle endian free + // TODO: Some H2C message needs to be fordward to WLan driver +} + +/****************************************************************************** + * Function: SDIO_Send_C2H_PktMsg + * Desc: To send a C2H message to the Host through the block read command. + * + * Para: + * pSDIODev: The SDIO device data structor. + * H2CMsg: point to the buffer of the H2C message received. + * MsgLen: The length of this message. + ******************************************************************************/ +u8 SDIO_Send_C2H_PktMsg( + IN PHAL_SDIO_ADAPTER pSDIODev, + IN u8 *C2HMsg, + IN u16 MsgLen +) +{ + u8 *MsgBuf; + PSDIO_RX_DESC pRxDesc; + SDIO_RX_PACKET *pPkt; + + // TODO: define H2C message type & format + DBG_SDIO_INFO("C2H_MSG: 0x%x\n", *C2HMsg); + // TODO: May needs to handle endian free + + MsgBuf = RtlZmalloc(MsgLen); + if (NULL == MsgBuf) { + DBG_SDIO_ERR("SDIO_Send_C2H_PktMsg: Malloc Err!!\n"); + return FAIL; + } + _memcpy((void *)(MsgBuf), (void *)C2HMsg, MsgLen); + + pPkt = SDIO_Alloc_Rx_Pkt(pSDIODev); + if (pPkt == NULL) { + DBG_SDIO_ERR("RX Callback Err!! No Free RX PKT!\n"); + return FAIL; + } + pRxDesc = &pPkt->RxDesc; + pRxDesc->type = SDIO_CMD_C2H; + pRxDesc->pkt_len = MsgLen; + pRxDesc->offset = sizeof(SDIO_RX_DESC); + pPkt->pData = MsgBuf; + pPkt->Offset = 0; + RtlDownMutex(&pSDIODev->RxMutex); + RtlListInsertTail(&pPkt->list, &pSDIODev->RxPktList); + pSDIODev->RxInQCnt++; + RtlUpMutex(&pSDIODev->RxMutex); + SDIO_SetEvent(pSDIODev, SDIO_EVENT_RX_PKT_RDY); +#if !TASK_SCHEDULER_DISABLED + if (pSDIODev->RxInQCnt == 1) { + RtlUpSema(&pSDIODev->RxSema); + } +#else + SDIO_TaskUp(pSDIODev); +#endif + + return SUCCESS; + +} + +/****************************************************************************** + * Function: SDIO_Process_RPWM + * Desc: To handle RPWM interrupt. + * + * Para: + * pSDIODev: The SDIO device data structor. + ******************************************************************************/ +u8 SDIO_Process_RPWM( + IN PHAL_SDIO_ADAPTER pSDIODev +) +{ + u8 rpwm; + + rpwm = HAL_SDIO_READ8(REG_SPDIO_CRPWM); + + DBG_SDIO_INFO ("RPWM1: 0x%x\n", rpwm); + // TODO: forward this RPWM message to WLan + + return 0; +} + +/****************************************************************************** + * Function: SDIO_Reset_Cmd + * Desc: Handle the SDIO Reset Command interrupt. We did nothing currently. + * + * Para: + * pSDIODev: The SDIO device data structor. + ******************************************************************************/ +VOID SDIO_Reset_Cmd( + IN PHAL_SDIO_ADAPTER pSDIODev +) +{ + // TODO: + return; +} + +/****************************************************************************** + * Function: SDIO_Return_Rx_Data + * Desc: To send all packets in the RX packet list to the Host system via the + * SDIO bus. + * + * Para: + * pSDIODev: The SDIO device data structor. + ******************************************************************************/ +VOID SDIO_Return_Rx_Data( + IN PHAL_SDIO_ADAPTER pSDIODev +) +{ + SDIO_RX_PACKET *pPkt=NULL; + SDIO_RX_DESC *pRxDesc; + SDIO_RX_BD_HANDLE *pRxBdHdl; + _LIST *plist; + SDIO_RX_BD *pRXBD; + u32 Offset=0; + u16 i; + u16 RxBdWrite=0; // to count how much RX_BD used in a Transaction + u16 RxBdRdPtr=0; // RX_BD read pointer + u16 AvailRxBdNum=0; + u32 pkt_size; + u8 isForceBreak=0; + u8 isListEmpty; +#if SDIO_RX_PKT_SIZE_OVER_16K + u8 needed_rxbd_num; +#endif + + DBG_SDIO_INFO("SDIO_Return_Rx_Data==> RXBDWPtr=%d\n", pSDIODev->RXBDWPtr); + RtlDownMutex(&pSDIODev->RxMutex); + + if (RtlIsListEmpty(&pSDIODev->RxPktList)) { + DBG_SDIO_INFO("SDIO_Return_Rx_Data: Queue is empty\n"); + RtlUpMutex(&pSDIODev->RxMutex); + return; + } + RtlUpMutex(&pSDIODev->RxMutex); + + RxBdRdPtr = pSDIODev->RXBDRPtr; + do { + /* Check if we shoule handle the RX_BD recycle ? */ + if (RxBdRdPtr != HAL_SDIO_READ16(REG_SPDIO_RXBD_C2H_RPTR)) { + SDIO_Recycle_Rx_BD(pSDIODev); + RxBdRdPtr = pSDIODev->RXBDRPtr; + } + + /* check if RX_BD available */ + RtlDownMutex(&pSDIODev->RxMutex); + plist = RtlListGetNext(&pSDIODev->RxPktList); + RtlUpMutex(&pSDIODev->RxMutex); + pPkt = CONTAINER_OF(plist, SDIO_RX_PACKET, list); + pRxDesc = &(pPkt->RxDesc); +#if SDIO_RX_PKT_SIZE_OVER_16K + needed_rxbd_num = ((pRxDesc->pkt_len - 1)/MAX_RX_BD_BUF_SIZE) + MIN_RX_BD_SEND_PKT; +#endif + if (RxBdRdPtr != pSDIODev->RXBDWPtr) { + if (pSDIODev->RXBDWPtr > RxBdRdPtr) { +#if SDIO_RX_PKT_SIZE_OVER_16K + if ((pSDIODev->RXBDWPtr - RxBdRdPtr) == (SDIO_RX_BD_NUM - needed_rxbd_num)) +#else + if ((pSDIODev->RXBDWPtr - RxBdRdPtr) == (SDIO_RX_BD_NUM - MIN_RX_BD_SEND_PKT)) +#endif + { + DBG_SDIO_WARN("SDIO_Return_Rx_Data: No Available RX_BD, ReadPtr=%d WritePtr=%d\n", \ + RxBdRdPtr, pSDIODev->RXBDWPtr); + isForceBreak = 1; + break; // break the while loop + } + } + else { +#if SDIO_RX_PKT_SIZE_OVER_16K + if ((RxBdRdPtr - pSDIODev->RXBDWPtr) == needed_rxbd_num) +#else + if ((RxBdRdPtr - pSDIODev->RXBDWPtr) == MIN_RX_BD_SEND_PKT) +#endif + { + DBG_SDIO_WARN("SDIO_Return_Rx_Data: No Available RX_BD, ReadPtr=%d WritePtr=%d\n", RxBdRdPtr, pSDIODev->RXBDWPtr); + isForceBreak = 1; + break; // break the while loop + } + } + } + + RtlDownMutex(&pSDIODev->RxMutex); + RtlListDelete(&pPkt->list); // remove it from the SDIO RX packet Queue + pSDIODev->RxInQCnt--; + RtlUpMutex(&pSDIODev->RxMutex); + + // TODO: Add RX_DESC before the packet + + /* a SDIO RX packet will use at least 2 RX_BD, the 1st one is for RX_Desc, + other RX_BDs are for packet payload */ + /* Use a RX_BD to transmit RX_Desc */ + pRXBD = pSDIODev->pRXBDAddrAligned + pSDIODev->RXBDWPtr; // get the RX_BD head + pRxBdHdl = pSDIODev->pRXBDHdl + pSDIODev->RXBDWPtr; + if (!pRxBdHdl->isFree) { + DBG_SDIO_ERR("SDIO_Return_Rx_Data: Allocated a non-free RX_BD\n"); + } + pRxBdHdl->isFree = 0; + pRxBdHdl->pPkt = pPkt; + pRXBD->FS = 1; + pRXBD->PhyAddr = (u32)((u8 *)pRxDesc); + pRXBD->BuffSize = sizeof(SDIO_RX_DESC); + pRxBdHdl->isPktEnd = 0; + pSDIODev->RXBDWPtr += 1; + if (pSDIODev->RXBDWPtr >= SDIO_RX_BD_NUM) { + pSDIODev->RXBDWPtr -= SDIO_RX_BD_NUM; + } + + /* Take RX_BD to transmit packet payload */ + pkt_size = pRxDesc->pkt_len; + Offset = 0; + do { + pRXBD = pSDIODev->pRXBDAddrAligned + pSDIODev->RXBDWPtr; // get the RX_BD head + pRxBdHdl = pSDIODev->pRXBDHdl + pSDIODev->RXBDWPtr; + pRxBdHdl->isFree = 0; + pRxBdHdl->pPkt = pPkt; + pRXBD->FS = 0; + pRXBD->PhyAddr = (u32)(((u8 *)pPkt->pData)+pPkt->Offset); +#if SDIO_RX_PKT_SIZE_OVER_16K + if ((pkt_size - Offset) <= MAX_RX_BD_BUF_SIZE) { + pRXBD->BuffSize = pkt_size - Offset; + pRxBdHdl->isPktEnd = 1; + } + else { + pRXBD->BuffSize = MAX_RX_BD_BUF_SIZE; + pRxBdHdl->isPktEnd = 0; + DBG_SDIO_INFO("SDIO_Return_Rx_Data: Split RX_BD, Offset=%d PktSize=%d\n", \ + Offset, pkt_size); + } +#else + if (pkt_size > MAX_RX_BD_BUF_SIZE) { + // if come to here, please enable "SDIO_RX_PKT_SIZE_OVER_16K" + DBG_SDIO_ERR("SDIO_Return_Rx_Data: The Packet Size bigger than 16K\n"); + pkt_size = MAX_RX_BD_BUF_SIZE; + } + pRXBD->BuffSize = pkt_size; + pRxBdHdl->isPktEnd = 1; +#endif + Offset += pRXBD->BuffSize; + // Move the RX_BD Write pointer forward + RxBdWrite++; + pSDIODev->RXBDWPtr += 1; + if (pSDIODev->RXBDWPtr >= SDIO_RX_BD_NUM) { + pSDIODev->RXBDWPtr -= SDIO_RX_BD_NUM; + } + + if (Offset >= pkt_size) { + pRXBD->LS = 1; + HAL_SDIO_WRITE16(REG_SPDIO_RXBD_C2H_WPTR, pSDIODev->RXBDWPtr); + DBG_SDIO_INFO("SDIO_Return_Rx_Data:RXBDWPtr=%d\n", pSDIODev->RXBDWPtr); + } + } while (Offset < pkt_size); + RtlDownMutex(&pSDIODev->RxMutex); + isListEmpty = RtlIsListEmpty(&pSDIODev->RxPktList); + RtlUpMutex(&pSDIODev->RxMutex); + } while(!isListEmpty); + + if (RxBdWrite > 0) { + HAL_SDIO_WRITE8(REG_SPDIO_HCI_RX_REQ, BIT_HCI_RX_REQ); + } + + if (isForceBreak) { +// SDIO_Recycle_Rx_BD(pSDIODev); + // function end with insufficient resource, set event to try again later + SDIO_SetEvent(pSDIODev, SDIO_EVENT_RX_PKT_RDY); +#if !TASK_SCHEDULER_DISABLED + RtlMsleepOS(10); // no resource, sleep a while + RtlUpSema(&pSDIODev->RxSema); +#else + SDIO_TaskUp(pSDIODev); +#endif + } + DBG_SDIO_INFO("SDIO_Return_Rx_Data(%d)<==\n", RxBdWrite); + +} + +/****************************************************************************** + * Function: SDIO_Register_Tx_Callback + * Desc: For a TX data target driver to register its TX callback function, so + * the SDIO driver can use it to fordward a TX packet to the target driver. + * + * Para: + * pSDIODev: point to the SDIO device handler + * CallbackFun: The function pointer of the callback + * pAdapter: a pointer will be use to call the registered CallBack function. + * It can be used to point to a handler of the caller, like WLan + * Adapter. + ******************************************************************************/ +VOID SDIO_Register_Tx_Callback( + IN PHAL_SDIO_ADAPTER pSDIODev, + IN s8 (*CallbackFun)(VOID *pAdapter, u8 *pPkt, u16 Offset, u16 PktSize), + IN VOID *pAdapter +) +{ + pSDIODev->Tx_Callback = CallbackFun; + pSDIODev->pTxCb_Adapter = pAdapter; +} + +/****************************************************************************** + * Function: SDIO_Rx_Callback + * Desc: The callback function for an packet receiving, which be called from + * the Target (WLan) driver to send a packet to the SDIO host. + * + * Para: + * pSDIODev: Point to the SDIO device data structer. + * pData: Point to the head of the data to be return to the Host system. + * Length: The length of the data to be send, in byte. + * + * Return: + * The result, SUCCESS or FAIL. + ******************************************************************************/ +s8 SDIO_Rx_Callback( + IN PHAL_SDIO_ADAPTER pSDIODev, + IN VOID *pData, + IN u16 Offset, + IN u16 PktSize, + IN u8 CmdType +) +{ + PSDIO_RX_DESC pRxDesc; + SDIO_RX_PACKET *pPkt; + + pPkt = SDIO_Alloc_Rx_Pkt(pSDIODev); + if (pPkt == NULL) { + DBG_SDIO_ERR("RX Callback Err!! No Free RX PKT!\n"); + return FAIL; + } + pRxDesc = &pPkt->RxDesc; + pRxDesc->type = CmdType; + pRxDesc->pkt_len = PktSize; + pRxDesc->offset = sizeof(SDIO_RX_DESC); + pPkt->pData = pData; + pPkt->Offset = Offset; + RtlDownMutex(&pSDIODev->RxMutex); + RtlListInsertTail(&pPkt->list, &pSDIODev->RxPktList); + pSDIODev->RxInQCnt++; + RtlUpMutex(&pSDIODev->RxMutex); + SDIO_SetEvent(pSDIODev, SDIO_EVENT_RX_PKT_RDY); +#if !TASK_SCHEDULER_DISABLED + if (pSDIODev->RxInQCnt == 1) { + RtlUpSema(&pSDIODev->RxSema); + } +#else + SDIO_TaskUp(pSDIODev); +#endif + + return SUCCESS; +} + +/****************************************************************************** + * Function: SDIO_Handle_MsgBlk + * Desc: Process a message block. + * + * Para: + * pSDIODev: Point to the SDIO device data structer. + * MSG_BLK: The message block to be processed. + * Length: The length of the data to be send, in byte. + * + * Return: + * The result, SUCCESS or FAIL. + ******************************************************************************/ +s8 SDIO_Handle_MsgBlk( + IN PHAL_SDIO_ADAPTER pSDIODev, + IN MSG_BLK *pMblk +) +{ + s8 ret; + + DBG_SDIO_INFO("SDIO_Handle_MsgBlk==> MsgType=%d\n", pMblk->MsgType); + switch (pMblk->MsgType) { + case MSG_SDIO_RX_PKT: + ret = SDIO_Rx_Callback(pSDIODev, pMblk->pBuf, pMblk->Reserved, pMblk->DateLen, SDIO_CMD_RX_ETH); //pMblk->Reserved = Offset + if (SUCCESS != ret) { + // failed to send this packet to the host, drop it + RtlMfree((u8 *) pMblk->pBuf, (pMblk->Reserved + pMblk->DateLen)); // pMblk->Reserved = Offset +#if SDIO_DEBUG + RtlDownMutex(&pSDIODev->StatisticMutex); + pSDIODev->MemAllocCnt--; + RtlUpMutex(&pSDIODev->StatisticMutex); +#endif +#if SDIO_MP_MODE + pSDIODev->MP_RxDropCnt++; +#endif + } + break; + + case MSG_SDIO_C2H: + break; + + case MSG_SDIO_RPWM: + break; + + default: + DBG_SDIO_WARN("SDIO_Handle_MsgBlk: UnKnown MsgType %d\n", pMblk->MsgType); + break; + } + + return ret; +} + +#if SDIO_MP_MODE + +/****************************************************************************** + * Function: SDIO_PeriodicalTimerCallback + * Desc: The callback function of the 1 Sec timer. It be used to statistic the + * throughput and update the status or something need to do periodically. + * + * Para: + * pContex: this pointer actually is the pointer of the SDIO device. + * + * Return: None + ******************************************************************************/ +VOID SDIO_PeriodicalTimerCallback( + void *pContex +) +{ + PHAL_SDIO_ADAPTER pSDIODev = pContex; + + if (SDIO_IsEventPending(pSDIODev, SDIO_EVENT_DUMP)) { + SDIO_StatisticDump(pSDIODev); +} +} + +#if !TASK_SCHEDULER_DISABLED +/****************************************************************************** + * Function: SDIO_MP_Task + * Desc: The SDIO MP test task handler. This is the main function of the SDIO + * device MP test mode. + * + * Para: + * pSDIODev: The SDIO device data structor. + ******************************************************************************/ +VOID SDIO_MP_Task( + IN VOID *pData +) +{ + PHAL_SDIO_ADAPTER pSDIODev = pData; + MSG_BLK Mblk_r; + MSG_BLK Mblk_w; + SDIO_MP_RX_PACKET *pRxPkt; + _LIST *plist; + int malloc_err_cnt=0; + + DiagPrintf("SDIO_MP_Task Started...\n"); + RtlInitListhead(&pSDIODev->MP_RxPktList); + + /* Initial resource */ + for (;;) + { + /* Task blocked and wait the semaphore(events) here */ + RtlDownSema(&pSDIODev->MP_EventSema); + /* handle message block in the mailbox */ + do { + if (_SUCCESS == RtlMailboxReceive(MBOX_ID_SDIO_MP, &Mblk_r, MBOX_WAIT_NONE, 0)) { + switch (Mblk_r.MsgType) { + case MSG_SDIO_MP_LOOP_TXPKT: + pRxPkt = NULL; + malloc_err_cnt = 0; + do { + pRxPkt = (SDIO_MP_RX_PACKET *)RtlZmalloc(sizeof(SDIO_MP_RX_PACKET)); + if (NULL != pRxPkt) { + pRxPkt->pData = Mblk_r.pBuf; + pRxPkt->Offset = Mblk_r.Reserved; + pRxPkt->DataLen = Mblk_r.DateLen; + RtlListInsertTail(&pRxPkt->list, &pSDIODev->MP_RxPktList); + } + else { + RtlMsleepOS(10); + malloc_err_cnt++; + if (malloc_err_cnt > 100) { + DBG_SDIO_ERR("SDIO_MP_Task: Malloc for Rx Pkt Failed\n"); + // no memory to handle this packet, drop it + RtlMfree(Mblk_r.pBuf, (Mblk_r.Reserved+Mblk_r.DateLen)); + pSDIODev->MP_RxDropCnt++; +#if SDIO_DEBUG + RtlDownMutex(&pSDIODev->StatisticMutex); + pSDIODev->MemAllocCnt--; + RtlUpMutex(&pSDIODev->StatisticMutex); +#endif + break; // break the while loop + } + } + }while (NULL == pRxPkt); + break; + + default: + DBG_SDIO_WARN("SDIO_MP_TASK: UnKnown MsgType %d\n", Mblk_r.MsgType); + break; + } + } + else { + break; // no more message pending, break the while loop + } + } while (1); + + while (!RtlIsListEmpty(&pSDIODev->MP_RxPktList)) { + plist = RtlListGetNext(&pSDIODev->MP_RxPktList); + pRxPkt = CONTAINER_OF(plist, SDIO_MP_RX_PACKET, list); + RtlListDelete(&pRxPkt->list); + + Mblk_w.MsgType = MSG_SDIO_RX_PKT; + Mblk_w.pBuf = pRxPkt->pData; + Mblk_w.Reserved = pRxPkt->Offset; + Mblk_w.DateLen = pRxPkt->DataLen; + if (_SUCCESS != RtlMailboxSendToBack(MBOX_ID_SDIO, &Mblk_w, 2000, 0)) { + DBG_SDIO_ERR("SDIO_MP_Task: Send MSG_SDIO_RX_PKT FAILED\n"); + RtlListInsertHead(&pRxPkt->list, &pSDIODev->MP_RxPktList); + break; + } + else { + RtlMfree((u8 *)pRxPkt, sizeof(SDIO_MP_RX_PACKET)); + } + } + + RtlEnterCritical(); + if (pSDIODev->MP_Events & SDIO_EVENT_EXIT) { + pSDIODev->MP_Events &= ~SDIO_EVENT_EXIT; + RtlExitCritical(); + DBG_SDIO_INFO("SDIO_MP_Task Exiting...\n"); + break; // break the loop to exit the task + } + RtlExitCritical(); + } + + RtlEnterCritical(); + pSDIODev->MP_Events |= SDIO_EVENT_MP_STOPPED; + RtlExitCritical(); + DBG_SDIO_INFO("SDIO_MP_Task Stoped!\n"); +#if ( INCLUDE_vTaskDelete == 1 ) + vTaskDelete(NULL); +#endif +} +#endif // end of "#if !TASK_SCHEDULER_DISABLED" + +/****************************************************************************** + * Function: SDIO_MapMPCmd + * Desc: Map a MP command string to a MP command type. + * + * Para: + * CmdStr: point to the command string buffer + * + * return: + * The MP command type + * + ******************************************************************************/ +u8 SDIO_MapMPCmd( + IN char *CmdStr, + IN u16 *Offset +) +{ + char cmd_str[16]; + u16 i; + u16 str_len=0; + u16 entry_num; + u8 mp_cmd=0xff; + + for (i=0;i<16;i++) { + if ((' ' != *(CmdStr+i)) && ('=' != *(CmdStr+i)) && (*(CmdStr+i))) { + cmd_str[i] = *(CmdStr+i); + str_len++; + } + else { + break; + } + } + + *Offset = str_len+1; + + entry_num = sizeof(SDIO_MPCmdTable)/sizeof(SDIO_MP_CMD); + + for (i=0;iMP_ModeEn); + DiagPrintf("MP_Loopback=%d\n", pSDIODev->MP_LoopBackEn); + DiagPrintf("TX: Packet Count=%d, Byte Count=%d\n", pSDIODev->MP_TxPktCnt, pSDIODev->MP_TxByteCnt); + DiagPrintf("TX: TX_BD_WPTR=%d, TX_BD_RPTR=%d\n", HAL_SDIO_READ16(REG_SPDIO_TXBD_WPTR), HAL_SDIO_READ16(REG_SPDIO_TXBD_RPTR)); + DiagPrintf("RX: Packet Count=%d, Byte Count=%d\n", pSDIODev->MP_RxPktCnt, pSDIODev->MP_RxByteCnt); + DiagPrintf("RX: RXBDWPtr=%d, RXBDRPtr=%d\n", pSDIODev->RXBDWPtr, pSDIODev->RXBDRPtr); +#if SDIO_DEBUG + DiagPrintf("RX: InQueueCount=%d MemAllocatedCnt=%d\n", pSDIODev->RxInQCnt, pSDIODev->MemAllocCnt); +#endif + DiagPrintf("TxDropPkt=%d RxDropPkt=%d\n", pSDIODev->MP_TxDropCnt, pSDIODev->MP_RxDropCnt); +} + +/****************************************************************************** + * Function: SDIO_StatisticDump + * Desc: Periodical dump SDIO throughput and other status. + * + * Para: + * pSDIODev: The SDIO device data structor. + * + * return: None + * + ******************************************************************************/ +VOID SDIO_StatisticDump( + IN PHAL_SDIO_ADAPTER pSDIODev +) +{ + unsigned long tp; // throughput + u32 oldest_byte_cnt; + u32 tx_avg_tp=0; // in Kbps + u32 rx_avg_tp=0; // in Kbps + + // calculate the TX throughput + if (pSDIODev->TxAvgWinCnt >= SDIO_AVG_TP_WIN_SIZE) { + // flush the oldest one and add the newest one + oldest_byte_cnt = pSDIODev->MP_TxAvgTPWin[pSDIODev->OldestTxAvgWinIdx]; + + if (pSDIODev->MP_TxAvgTPWinSum >= oldest_byte_cnt) { + pSDIODev->MP_TxAvgTPWinSum -= oldest_byte_cnt; + pSDIODev->MP_TxAvgTPWin[pSDIODev->OldestTxAvgWinIdx] = pSDIODev->MP_TxByteCntInPeriod; + pSDIODev->OldestTxAvgWinIdx++; + if (SDIO_AVG_TP_WIN_SIZE <= pSDIODev->OldestTxAvgWinIdx) { + pSDIODev->OldestTxAvgWinIdx = 0; + } + + if (0 == pSDIODev->MP_TxAvgTPWinSum) { + // reset the statistic + pSDIODev->TxAvgWinCnt = 0; + pSDIODev->OldestTxAvgWinIdx = 0; + } + } + else { + pSDIODev->MP_TxAvgTPWinSum = 0; + // reset the statistic + if (pSDIODev->MP_TxByteCntInPeriod > 0) + pSDIODev->TxAvgWinCnt = 1; + else + pSDIODev->TxAvgWinCnt = 0; + pSDIODev->OldestTxAvgWinIdx = 0; + } + pSDIODev->MP_TxAvgTPWinSum += pSDIODev->MP_TxByteCntInPeriod; + tx_avg_tp = (pSDIODev->MP_TxAvgTPWinSum << 3) / (SDIO_PERIODICAL_TIMER_INTERVAL * SDIO_AVG_TP_WIN_SIZE); + } + else { + if ((pSDIODev->MP_TxAvgTPWinSum > 0) || (pSDIODev->MP_TxByteCntInPeriod > 0)) { + pSDIODev->MP_TxAvgTPWinSum += pSDIODev->MP_TxByteCntInPeriod; + pSDIODev->MP_TxAvgTPWin[pSDIODev->TxAvgWinCnt] = pSDIODev->MP_TxByteCntInPeriod; + pSDIODev->TxAvgWinCnt++; + tx_avg_tp = (pSDIODev->MP_TxAvgTPWinSum << 3) / (SDIO_PERIODICAL_TIMER_INTERVAL * pSDIODev->TxAvgWinCnt); + } + } + + // calculate the RX throughput + if (pSDIODev->RxAvgWinCnt >= SDIO_AVG_TP_WIN_SIZE) { + // flush the oldest one and add the newest one + oldest_byte_cnt = pSDIODev->MP_RxAvgTPWin[pSDIODev->OldestRxAvgWinIdx]; + if (pSDIODev->MP_RxAvgTPWinSum >= oldest_byte_cnt) { + pSDIODev->MP_RxAvgTPWinSum -= oldest_byte_cnt; + pSDIODev->MP_RxAvgTPWin[pSDIODev->OldestRxAvgWinIdx] = pSDIODev->MP_RxByteCntInPeriod; + pSDIODev->OldestRxAvgWinIdx++; + if (SDIO_AVG_TP_WIN_SIZE <= pSDIODev->OldestRxAvgWinIdx) { + pSDIODev->OldestRxAvgWinIdx = 0; + } + + if (0 == pSDIODev->MP_RxAvgTPWinSum) { + // reset the statistic + pSDIODev->RxAvgWinCnt = 0; + pSDIODev->OldestRxAvgWinIdx = 0; + } + } + else { + pSDIODev->MP_RxAvgTPWinSum = 0; + // reset the statistic + if (pSDIODev->MP_RxByteCntInPeriod > 0) + pSDIODev->RxAvgWinCnt = 1; + else + pSDIODev->RxAvgWinCnt = 0; + + pSDIODev->OldestRxAvgWinIdx = 0; + } + pSDIODev->MP_RxAvgTPWinSum += pSDIODev->MP_RxByteCntInPeriod; + + rx_avg_tp = (pSDIODev->MP_RxAvgTPWinSum << 3) / (SDIO_PERIODICAL_TIMER_INTERVAL * SDIO_AVG_TP_WIN_SIZE); + } + else { + if ((pSDIODev->MP_RxAvgTPWinSum > 0) || (pSDIODev->MP_RxByteCntInPeriod > 0)) { + pSDIODev->MP_RxAvgTPWinSum += pSDIODev->MP_RxByteCntInPeriod; + pSDIODev->MP_RxAvgTPWin[pSDIODev->RxAvgWinCnt] = pSDIODev->MP_RxByteCntInPeriod; + pSDIODev->RxAvgWinCnt++; + rx_avg_tp = (pSDIODev->MP_RxAvgTPWinSum << 3) / (SDIO_PERIODICAL_TIMER_INTERVAL * pSDIODev->RxAvgWinCnt); + } + } + + if ((pSDIODev->MP_TxByteCntInPeriod > 0) || (pSDIODev->MP_RxByteCntInPeriod > 0)) { + DiagPrintf("SDIO Dump:\n"); + tp = (pSDIODev->MP_TxByteCntInPeriod << 3)/(SDIO_PERIODICAL_TIMER_INTERVAL/1000); + if (tp > 1000) { + DiagPrintf("TX: Packet Count=%d, Byte Count=%d, TP=%d Kbps\n", pSDIODev->MP_TxPktCntInPeriod, pSDIODev->MP_TxByteCntInPeriod, tp/1000); + } + else { + DiagPrintf("TX: Packet Count=%d, Byte Count=%d, TP=%d bps\n", pSDIODev->MP_TxPktCntInPeriod, pSDIODev->MP_TxByteCntInPeriod, tp); + } + tp = (pSDIODev->MP_RxByteCntInPeriod << 3)/(SDIO_PERIODICAL_TIMER_INTERVAL/1000); + if (tp > 1000) { + DiagPrintf("RX: Packet Count=%d, Byte Count=%d, TP=%d Kbps\n", pSDIODev->MP_RxPktCntInPeriod, pSDIODev->MP_RxByteCntInPeriod, tp/1000); + } + else { + DiagPrintf("RX: Packet Count=%d, Byte Count=%d, TP=%d bps\n", pSDIODev->MP_RxPktCntInPeriod, pSDIODev->MP_RxByteCntInPeriod, tp); + } + + pSDIODev->MP_TxPktCntInPeriod = 0; + pSDIODev->MP_TxByteCntInPeriod = 0; + pSDIODev->MP_RxPktCntInPeriod = 0; + pSDIODev->MP_RxByteCntInPeriod = 0; + } + + if ((tx_avg_tp > 0) || (rx_avg_tp > 0)) { + DiagPrintf("TX Avg TP=%d Kbps, RX Avg TP=%d Kbps\n", tx_avg_tp, rx_avg_tp); + } +} + +/****************************************************************************** + * Function: SDIO_MP_Loopback + * Desc: The loopback test function for MP mode. + * + * Para: + * pAdapter: a pointer which got from the callback function register, + * here it point to the SDIO device itself. + * pData: The pointer of the SDIO TX data buffer. + * PktSize: The size (in byte) of this SDIO TX data. + * + * return: + * The result of this function, SUCCESS or FAILED. + * + ******************************************************************************/ +s8 SDIO_MP_Loopback( + IN VOID *pAdapter, + IN u8 *pData, + IN u16 Offset, + IN u16 PktSize +) +{ + PHAL_SDIO_ADAPTER pSDIODev=(PHAL_SDIO_ADAPTER)pAdapter; + s8 ret; + + MSG_BLK MBlk; + +// DBG_SDIO_INFO("SDIO_MP_Loopback==>\n"); + + +#if TASK_SCHEDULER_DISABLED + ret = SDIO_Rx_Callback(pSDIODev, pData, Offset, PktSize, SDIO_CMD_RX_ETH); +#else + // Mailbox test, use message to replace call SDIO_Rx_Callback directly + MBlk.MsgType = MSG_SDIO_MP_LOOP_TXPKT; + MBlk.pBuf = pData; + MBlk.Reserved = (u8)Offset; + MBlk.DateLen = PktSize; + if (_SUCCESS == RtlMailboxSendToBack(MBOX_ID_SDIO_MP, &MBlk, 2000, 0)) { + ret = SUCCESS; + } + else { + DBG_SDIO_ERR("SDIO_MP_Loopback FAILED\n"); + ret = FAIL; + } +#endif + return ret; +} + +/****************************************************************************** + * Function: SDIO_MP_ContinueTx + * Desc: The continue TX test function for MP mode. We just drop the TX packet. + * + * Para: + * pAdapter: a pointer which got from the callback function register, + * here it point to the SDIO device itself. + * pData: The pointer of the SDIO TX data buffer. + * PktSize: The size (in byte) of this SDIO TX data. + * + * return: + * The result of this function, SUCCESS or FAILED. + * + ******************************************************************************/ +s8 SDIO_MP_ContinueTx( + IN VOID *pAdapter, + IN u8 *pData, + IN u16 Offset, + IN u16 PktSize +) +{ + PHAL_SDIO_ADAPTER pSDIODev=(PHAL_SDIO_ADAPTER)pAdapter; + + RtlMfree(pData, (Offset+PktSize)); +#if SDIO_DEBUG + RtlDownMutex(&pSDIODev->StatisticMutex); + pSDIODev->MemAllocCnt--; + RtlUpMutex(&pSDIODev->StatisticMutex); +#endif + return SUCCESS; +} + +/****************************************************************************** + * Function: SDIO_MP_ContinueRx + * Desc: Process Continue RX test. + * + * Para: + * pSDIODev: The SDIO device adapter. + * + * return: None + * + ******************************************************************************/ +VOID SDIO_MP_ContinueRx( + IN PHAL_SDIO_ADAPTER pSDIODev +) +{ + u8 *pRxBuf; + s8 ret; + + while (1) { + if (pSDIODev->MP_CRxPktPendingCnt > 10) { + break; + } + + if (pSDIODev->MP_ContinueRxMode == SDIO_CRX_STATIC_BUF) { + pRxBuf = pSDIODev->pMP_CRxBuf; + } + else if (pSDIODev->MP_ContinueRxMode == SDIO_CRX_DYNA_BUF) { + pRxBuf = RtlMalloc(pSDIODev->MP_CRxSize+26); // 26: Wlan header +#if SDIO_DEBUG + pSDIODev->MemAllocCnt++; +#endif + if (NULL != pRxBuf) { + _memcpy(pRxBuf, MP_WlanHdr, 26); + _memset((pRxBuf+26), 0x3E, pSDIODev->MP_CRxSize); + } + } + + if (NULL != pRxBuf) { + ret = SDIO_Rx_Callback(pSDIODev, pRxBuf, 0, pSDIODev->MP_CRxSize+26, SDIO_CMD_RX_ETH); + if (SUCCESS == ret) { + if (pSDIODev->MP_CRxPktCnt > 0) { + pSDIODev->MP_CRxPktCnt--; + pSDIODev->MP_CRxPktPendingCnt++; + if (0 == pSDIODev->MP_CRxPktCnt) { + pSDIODev->MP_ContinueRx = 0; + break; // break the while loop + } + } + if (pSDIODev->MP_CRxPktPendingCnt > 10) { + break; + } + } + else { + if (pSDIODev->MP_ContinueRxMode == SDIO_CRX_DYNA_BUF) { + RtlMfree(pRxBuf, pSDIODev->MP_CRxSize+26); +#if SDIO_DEBUG + pSDIODev->MemAllocCnt--; +#endif + } +#if !TASK_SCHEDULER_DISABLED + RtlMsleepOS(10); // no resource, sleep a while + RtlUpSema(&pSDIODev->RxSema); +#else + SDIO_TaskUp(pSDIODev); +#endif + break; + } + } + else { +#if !TASK_SCHEDULER_DISABLED + RtlMsleepOS(10); // no resource, sleep a while + RtlUpSema(&pSDIODev->RxSema); +#else + SDIO_TaskUp(pSDIODev); +#endif + break; + } + } +} + +/****************************************************************************** + * Function: SDIO_DeviceMPApp + * Desc: To handle SDIO MP command + * + * Para: + * pData: point to the command buffer + * + ******************************************************************************/ +VOID SDIO_DeviceMPApp( + IN PHAL_SDIO_ADAPTER pSDIODev, + IN u16 argc, + IN u8 *argv[] +) +{ + u8 cmd_type; + u16 offset=0; + u32 arg1, arg2; + int ret; + int i; + + DBG_SDIO_INFO("==>MP_App: arg_num=%d cmd_str=%s\n", argc, (char *)argv[0]); + + cmd_type = SDIO_MapMPCmd((char *)argv[0], &offset); + DBG_SDIO_INFO("MP_App: MP_Cmdtype=%d\n", cmd_type); + + switch (cmd_type) + { + case SDIO_MP_START: + if (!pSDIODev->MP_ModeEn) { + pSDIODev->MP_ModeEn = 1; + pSDIODev->MP_TxPktCnt = 0; /* SDIO TX packet count */ + pSDIODev->MP_RxPktCnt = 0; /* SDIO RX packet count */ + pSDIODev->MP_TxByteCnt = 0; /* SDIO TX Byte count */ + pSDIODev->MP_RxByteCnt = 0; /* SDIO RX Byte count */ + DiagPrintf("SDIO MP Started!\n"); + } + else { + DiagPrintf("In SDIO MP Mode already!\n"); + } + break; + + case SDIO_MP_STOP: + pSDIODev->MP_ModeEn = 0; + DiagPrintf("SDIO MP Stoped!\n"); + break; + + case SDIO_MP_LOOPBACK: + DBG_SDIO_INFO("MP_App: argv[1]=%s\n", argv[1]); + if (pSDIODev->MP_ModeEn == 0) { + DiagPrintf("Not in MP mode!! Please start MP mode first.\n"); + break; + } + arg1 = Strtoul((const u8*)(argv[1]), (u8 **)NULL, 10); + if (arg1) { + if (pSDIODev->MP_LoopBackEn == 0) { + // Create a Task for MP loopback test +#if !TASK_SCHEDULER_DISABLED + RtlInitSema(&(pSDIODev->MP_EventSema), 0); + if (NULL == pSDIODev->MP_EventSema){ + DBG_SDIO_ERR("SDIO MP_Loopback Create Semaphore Err!!\n"); + break; // break the switch case + } + + /* create a Mailbox for other driver module to send message to SDIO driver */ + pSDIODev->pMP_MBox = RtlMailboxCreate(MBOX_ID_SDIO_MP, SDIO_MAILBOX_SIZE, &(pSDIODev->MP_EventSema)); + if (NULL == pSDIODev->pMBox) { + DBG_SDIO_ERR("SDIO MP_Loopback Create Mailbox Err!!\n"); + break; // break the switch case + } + + /* Create the SDIO task */ +#ifdef PLATFORM_FREERTOS + ret = xTaskCreate( SDIO_MP_Task, "SDIO_MP_TASK", ((256*4)/sizeof(portBASE_TYPE)), (void *)pSDIODev, SDIO_MP_TASK_PRIORITY, &pSDIODev->MP_TaskHandle); + if (pdTRUE != ret ) + { + DBG_SDIO_ERR("SDIO MP Create Task Err(%d)!!\n", ret); + break; + } +#endif + DiagPrintf("SDIO MP Task Created\n"); +#endif // end of "#if !TASK_SCHEDULER_DISABLED" + + // Backup origional TX Callback function + pSDIODev->pTxCallback_Backup = pSDIODev->Tx_Callback; + pSDIODev->pTxCb_Adapter_Backup = (VOID *)pSDIODev->pTxCb_Adapter; + DiagPrintf("Register SDIO TX Callback with Loopback function\n"); + SDIO_Register_Tx_Callback(pSDIODev, &SDIO_MP_Loopback, (VOID *) pSDIODev); + pSDIODev->MP_LoopBackEn = 1; + } + else { + DiagPrintf("SDIO MP LoopBack is On already!\n"); + } + } + else { + if (pSDIODev->MP_LoopBackEn) { + // Restore origional TX Callback function + DiagPrintf("Restore SDIO TX Callback...\n"); + SDIO_Register_Tx_Callback(pSDIODev, pSDIODev->pTxCallback_Backup, pSDIODev->pTxCb_Adapter_Backup); + pSDIODev->MP_LoopBackEn = 0; +#if !TASK_SCHEDULER_DISABLED + /* Exit the SDIO task */ + if (pSDIODev->MP_TaskHandle) { + RtlEnterCritical(); + pSDIODev->MP_Events |= SDIO_EVENT_EXIT; + RtlExitCritical(); + RtlUpSema(&pSDIODev->MP_EventSema); + i=0; + while (1) { + RtlEnterCritical(); + if (pSDIODev->MP_Events & SDIO_EVENT_MP_STOPPED) { + RtlExitCritical(); + break; + } + RtlExitCritical(); + RtlMsleepOS(10); + i++; + if (i> 100) { + DBG_SDIO_ERR("Delete SDIO MP Task Failed with Timeout\n"); + break; + } + } + } + + /* Delete the Mailbox */ + if (pSDIODev->pMP_MBox) { + RtlMailboxDel(pSDIODev->pMP_MBox); + pSDIODev->pMP_MBox = NULL; + } + + /* Delete the Semaphore */ + if (pSDIODev->MP_EventSema) { + RtlFreeSema(&pSDIODev->MP_EventSema); + pSDIODev->MP_EventSema = NULL; + } + DiagPrintf("SDIO MP Task Deleted\n"); +#endif + + } + } + DiagPrintf("SDIO MP LoopBack=%d\n", pSDIODev->MP_LoopBackEn); + break; + + case SDIO_MP_STATUS: + SDIO_DumpMPStatus(pSDIODev); + break; + + case SDIO_MP_READ_REG8: + arg1 = Strtoul((const u8*)(argv[1]), (u8 **)NULL, 16); + DiagPrintf("SDIO_Reg[%x]=%x\n", arg1, HAL_SDIO_READ8(arg1)); + break; + + case SDIO_MP_READ_REG16: + arg1 = Strtoul((const u8*)(argv[1]), (u8 **)NULL, 16); + DiagPrintf("SDIO_Reg[%x]=%x\n", arg1, HAL_SDIO_READ16(arg1)); + break; + + case SDIO_MP_READ_REG32: + arg1 = Strtoul((const u8*)(argv[1]), (u8 **)NULL, 16); + DiagPrintf("SDIO_Reg[%x]=%x\n", arg1, HAL_SDIO_READ32(arg1)); + break; + + case SDIO_MP_WRITE_REG8: + arg1 = Strtoul((const u8*)(argv[1]), (u8 **)NULL, 16); + arg2 = Strtoul((const u8*)(argv[2]), (u8 **)NULL, 16); + HAL_SDIO_WRITE8(arg1, arg2); + DiagPrintf("Write Reg[%x]=%x, Readback:%x\n", arg1, arg2, HAL_SDIO_READ8(arg1)); + break; + + case SDIO_MP_WRITE_REG16: + arg1 = Strtoul((const u8*)(argv[1]), (u8 **)NULL, 16); + arg2 = Strtoul((const u8*)(argv[2]), (u8 **)NULL, 16); + HAL_SDIO_WRITE16(arg1, arg2); + DiagPrintf("Write Reg[%x]=%x, Readback:%x\n", arg1, arg2, HAL_SDIO_READ16(arg1)); + break; + + case SDIO_MP_WRITE_REG32: + arg1 = Strtoul((const u8*)(argv[1]), (u8 **)NULL, 16); + arg2 = Strtoul((const u8*)(argv[2]), (u8 **)NULL, 16); + HAL_SDIO_WRITE32(arg1, arg2); + DiagPrintf("Write Reg[%x]=%x, Readback:%x\n", arg1, arg2, HAL_SDIO_READ32(arg1)); + break; + + case SDIO_MP_WAKEUP: + SDIO_Wakeup_Task(pSDIODev); + break; + + case SDIO_MP_DUMP: + arg1 = Strtoul((const u8*)(argv[1]), (u8 **)NULL, 10); + if (arg1) { + if (!SDIO_IsEventPending(pSDIODev, SDIO_EVENT_DUMP)) { + // reset statistic + for (i=0;iMP_TxAvgTPWin[i] = 0; + pSDIODev->MP_RxAvgTPWin[i] = 0; + } + pSDIODev->MP_TxAvgTPWinSum = 0; + pSDIODev->MP_RxAvgTPWinSum = 0; + pSDIODev->OldestTxAvgWinIdx = 0; + pSDIODev->OldestRxAvgWinIdx = 0; + pSDIODev->TxAvgWinCnt = 0; + pSDIODev->RxAvgWinCnt = 0; + } + SDIO_SetEvent(pSDIODev, SDIO_EVENT_DUMP); + } + else { + SDIO_ClearEvent(pSDIODev, SDIO_EVENT_DUMP); + } + DiagPrintf("SDIO Dump %d\n", arg1); + break; + + case SDIO_MP_CTX: + arg1 = Strtoul((const u8*)(argv[1]), (u8 **)NULL, 10); + if (arg1) { + if (!pSDIODev->MP_ContinueTx) { + // Backup origional TX Callback function + pSDIODev->pTxCallback_Backup = pSDIODev->Tx_Callback; + pSDIODev->pTxCb_Adapter_Backup = (VOID *)pSDIODev->pTxCb_Adapter; + DiagPrintf("Register SDIO TX Callback with Continue TX Test function\n"); + SDIO_Register_Tx_Callback(pSDIODev, &SDIO_MP_ContinueTx, (VOID *) pSDIODev); + pSDIODev->MP_ContinueTx = 1; + } + DiagPrintf("SDIO Continue TX Test Enabled\n"); + } + else { + if (pSDIODev->MP_ContinueTx) { + // Restore origional TX Callback function + DiagPrintf("Restore SDIO TX Callback...\n"); + SDIO_Register_Tx_Callback(pSDIODev, pSDIODev->pTxCallback_Backup, pSDIODev->pTxCb_Adapter_Backup); + pSDIODev->MP_ContinueTx = 0; + DiagPrintf("SDIO Continue TX Test Disabled\n"); + } + else { + DiagPrintf("SDIO Continue TX Test Didn't Enabled\n"); + } + } + break; + + case SDIO_MP_CRX: + case SDIO_MP_CRX_DA: + if(SDIO_MP_CRX == cmd_type) { + pSDIODev->MP_ContinueRxMode = SDIO_CRX_STATIC_BUF; + } + else if (SDIO_MP_CRX_DA == cmd_type) { + pSDIODev->MP_ContinueRxMode = SDIO_CRX_DYNA_BUF; + } + + if (pSDIODev->MP_ContinueRx) { + DiagPrintf("SDIO Continue RX Test Running\n"); + break; + } + pSDIODev->MP_ContinueRx = 1; + arg1 = Strtoul((const u8*)(argv[1]), (u8 **)NULL, 10); + if (arg1 < 16) { + DiagPrintf("SDIO RX Test Min Pkt Size is 16\n"); + arg1 = 16; + } + + if (arg1 > 4096) { + DiagPrintf("SDIO RX Test Max Pkt Size is 4096\n"); + arg1 = 4096; + } + pSDIODev->MP_CRxSize = arg1; + arg2 = Strtoul((const u8*)(argv[2]), (u8 **)NULL, 10); + pSDIODev->MP_CRxPktCnt = arg2; + if (arg2 == 0) { + pSDIODev->MP_CRxInfinite = 1; + } + + if (SDIO_CRX_STATIC_BUF == pSDIODev->MP_ContinueRxMode) { + if (NULL == pSDIODev->pMP_CRxBuf) { + pSDIODev->pMP_CRxBuf = RtlMalloc(pSDIODev->MP_CRxSize+26); // 26: Wlan header + DiagPrintf("SDIO RX Test: pBuf @ 0x%x\n", (u32)pSDIODev->pMP_CRxBuf); + if (((u32)(pSDIODev->pMP_CRxBuf) & 0x03) != 0) { + DiagPrintf("SDIO RX Test: pBuf Not 4-bytes Aligned!!\n"); + } +#if SDIO_DEBUG + pSDIODev->MemAllocCnt++; +#endif + if (NULL != pSDIODev->pMP_CRxBuf) { + _memcpy(pSDIODev->pMP_CRxBuf, MP_WlanHdr, 26); + _memset((pSDIODev->pMP_CRxBuf+26), 0x3E, pSDIODev->MP_CRxSize); + } + } + + if (pSDIODev->pMP_CRxBuf) { + DiagPrintf("SDIO RX Test(Static RX Buf): PktSize=%d, PktCount=%d\n", pSDIODev->MP_CRxSize, pSDIODev->MP_CRxPktCnt); + SDIO_Wakeup_Task(pSDIODev); + } + else { + pSDIODev->MP_ContinueRx = 0; + pSDIODev->MP_CRxInfinite= 0; + pSDIODev->MP_CRxPktCnt = 0; + DiagPrintf("SDIO RX Test: Mem Allocate Failed\n"); + } + } + + if (SDIO_CRX_DYNA_BUF == pSDIODev->MP_ContinueRxMode) { + DiagPrintf("SDIO RX Test(Dyna-Allocate RX Buf): PktSize=%d, PktCount=%d\n", pSDIODev->MP_CRxSize, pSDIODev->MP_CRxPktCnt); + SDIO_Wakeup_Task(pSDIODev); + } + + break; + + case SDIO_MP_CRX_STOP: + pSDIODev->MP_ContinueRx = 0; + pSDIODev->MP_CRxPktCnt = 0; + pSDIODev->MP_CRxInfinite= 0; + DiagPrintf("SDIO RX Test Stopping...\n"); + break; + + case SDIO_MP_DBG_MSG: + arg1 = Strtoul((const u8*)(argv[1]), (u8 **)NULL, 10); + if (arg1) { + ConfigDebugInfo |= _DBG_SDIO_; + ConfigDebugWarn |= _DBG_SDIO_; + DiagPrintf("SDIO Debug Message On.\n"); + } + else { + ConfigDebugInfo &= ~_DBG_SDIO_; + ConfigDebugWarn &= ~_DBG_SDIO_; + DiagPrintf("SDIO Debug Message Off.\n"); + } + break; + + default: + DiagPrintf("SDIO_DeviceMPApp: Unknown Cmd=%s\n", argv[0]); + DiagPrintf("==== SDIO Command Help ====\n"); + DiagPrintf("SDIO mp_start : Enter MP mode\n"); + DiagPrintf("SDIO mp_stop : Exit MP mode(Switch back to Normal mode)\n"); + DiagPrintf("SDIO mp_loopback <1/0> : enable/disable data path loopback test\n"); + DiagPrintf("SDIO ctx <1/0> : Start/Stop SDIO continue TX test\n"); + DiagPrintf("SDIO crx : Start SDIO continue RX test with static RX Buffer\n"); + DiagPrintf("SDIO crx_da : Start SDIO continue RX test with Dynamic Allocate RX Buffer\n"); + DiagPrintf("SDIO crx_stop : Stop SDIO continue RX test\n"); + DiagPrintf("SDIO status : Dump current SDIO driver status\n"); + DiagPrintf("SDIO read_reg8 : Read SDIO register via 1-byte access\n"); + DiagPrintf("SDIO read_reg16 : Read SDIO register via 2-bytes access\n"); + DiagPrintf("SDIO read_reg32 : Read SDIO register via 4-bytes access\n"); + DiagPrintf("SDIO write_reg8 : Write SDIO register via 1-byte access\n"); + DiagPrintf("SDIO write_reg16 : Write SDIO register via 2-bytes access\n"); + DiagPrintf("SDIO write_reg32 : Write SDIO register via 4-bytes access\n"); + DiagPrintf("SDIO dump <1/0> : Start/Stop to dump SDIO throughput statistic periodically.\n"); + break; + } +} +#endif /* endof '#if SDIO_MP_MODE' */ + diff --git a/component/soc/realtek/8195a/fwlib/rtl8195a/src/rtl8195a_ssi.c b/component/soc/realtek/8195a/fwlib/rtl8195a/src/rtl8195a_ssi.c new file mode 100644 index 0000000..b040c6e --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/rtl8195a/src/rtl8195a_ssi.c @@ -0,0 +1,1188 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#include "rtl8195a.h" +#include "rtl8195a_ssi.h" +#include "hal_ssi.h" + +extern _LONG_CALL_ +HAL_Status HalSsiInitRtl8195a(VOID *Adaptor); + +extern _LONG_CALL_ +u32 HalGetCpuClk(VOID); + + +VOID _SsiReadInterruptRtl8195a(VOID *Adapter) +{ + SSI_DBG_ENTRANCE("_SsiReadInterrupt()\n"); + PHAL_SSI_ADAPTOR pHalSsiAdapter = (PHAL_SSI_ADAPTOR) Adapter; + u32 ReceiveLevel; + volatile u32 Readable = HalSsiReadableRtl8195a(Adapter); + u8 Index = pHalSsiAdapter->Index; + u32 dummy_read_data; + + while (Readable) { + ReceiveLevel = HalSsiGetRxFifoLevelRtl8195a(Adapter); + + while (ReceiveLevel--) { + if (pHalSsiAdapter->RxData != NULL) { + if ((pHalSsiAdapter->DataFrameSize+1) > 8) { + // 16~9 bits mode + *((u16*)(pHalSsiAdapter->RxData)) = (u16)(HAL_SSI_READ32(Index, REG_DW_SSI_DR)); + pHalSsiAdapter->RxData = (VOID*)(((u16*)pHalSsiAdapter->RxData) + 1); + } + else { + // 8~4 bits mode + *((u8*)(pHalSsiAdapter->RxData)) = (u8)(HAL_SSI_READ32(Index, REG_DW_SSI_DR)); + pHalSsiAdapter->RxData = (VOID*)(((u8*)pHalSsiAdapter->RxData) + 1); + } + } + else { + // for Master mode, doing TX also will got RX data, so drop the dummy data + dummy_read_data = (u16)(HAL_SSI_READ32(Index, REG_DW_SSI_DR)); + } + + if (pHalSsiAdapter->RxLength > 0) { + pHalSsiAdapter->RxLength--; + } +#if 0 + else if (pHalSsiAdapter->RxLengthRemainder > 0) { + pHalSsiAdapter->RxLengthRemainder--; + } + + // Fixed length receive Complete. (RxLength & RxLengthRemainder == 0) + if ((pHalSsiAdapter->RxLength == 0) && (pHalSsiAdapter->RxLengthRemainder == 0)) { + break; + } +#endif + if (pHalSsiAdapter->RxLength == 0) { + break; + } + } + + if (pHalSsiAdapter->RxLength == 0) { + break; + } + + Readable = HalSsiReadableRtl8195a(Adapter); + } + + if ((pHalSsiAdapter->RxLength > 0) && + (pHalSsiAdapter->RxLength < (pHalSsiAdapter->RxThresholdLevel+1))) { + SSI_DBG_INT_READ("Setting Rx FIFO Threshold Level to 1\n"); + pHalSsiAdapter->RxThresholdLevel = 0; + HalSsiSetRxFifoThresholdLevelRtl8195a((VOID*)pHalSsiAdapter); + } + + if (pHalSsiAdapter->RxLength == 0) { + DBG_SSI_INFO("_SsiReadInterruptRtl8195a: RX_Done\r\n"); + pHalSsiAdapter->InterruptMask &= ~(BIT_IMR_RXFIM | BIT_IMR_RXOIM | BIT_IMR_RXUIM); + HalSsiSetInterruptMaskRtl8195a((VOID*)pHalSsiAdapter); +// if (pHalSsiAdapter->RxData != NULL) { + if (pHalSsiAdapter->RxCompCallback != NULL) { + pHalSsiAdapter->RxCompCallback(pHalSsiAdapter->RxCompCbPara); + } +// } + } + +} + + +VOID _SsiWriteInterruptRtl8195a(VOID *Adapter) +{ + SSI_DBG_ENTRANCE("_SsiWriteInterrupt()\n"); + PHAL_SSI_ADAPTOR pHalSsiAdapter = (PHAL_SSI_ADAPTOR) Adapter; + u32 Writeable = HalSsiWriteableRtl8195a(Adapter); + u32 TxWriteMax = SSI_TX_FIFO_DEPTH - pHalSsiAdapter->TxThresholdLevel; + u32 ReadData; + u8 Index = pHalSsiAdapter->Index; + + if (Writeable) { + /* Disable Tx FIFO Empty IRQ */ + pHalSsiAdapter->InterruptMask &= ~ BIT_IMR_TXEIM; + HalSsiSetInterruptMaskRtl8195a((VOID*)pHalSsiAdapter); + + while (TxWriteMax--) { + if ((pHalSsiAdapter->DataFrameSize+1) > 8) { + // 16~9 bits mode + if (pHalSsiAdapter->TxData != NULL) { + HAL_SSI_WRITE16(Index, REG_DW_SSI_DR, *((u16*)(pHalSsiAdapter->TxData))); + pHalSsiAdapter->TxData = (VOID*)(((u16*)pHalSsiAdapter->TxData) + 1); + } + else { + // For master mode: Push a dummy to TX FIFO for Read + if (pHalSsiAdapter->Role == SSI_MASTER) { + HAL_SSI_WRITE16(Index, REG_DW_SSI_DR, (u16)SSI_DUMMY_DATA); // Dummy byte + } + } + } + else { + // 8~4 bits mode + if (pHalSsiAdapter->TxData != NULL) { + HAL_SSI_WRITE8(Index, REG_DW_SSI_DR, *((u8*)(pHalSsiAdapter->TxData))); + pHalSsiAdapter->TxData = (VOID*)(((u8*)pHalSsiAdapter->TxData) + 1); + } + else { + // For master mode: Push a dummy to TX FIFO for Read + if (pHalSsiAdapter->Role == SSI_MASTER) { + HAL_SSI_WRITE8(Index, REG_DW_SSI_DR, (u8)SSI_DUMMY_DATA); // Dummy byte + } + } + } + + pHalSsiAdapter->TxLength--; + + if (pHalSsiAdapter->TxLength == 0) + break; + } + + /* Enable Tx FIFO Empty IRQ */ + pHalSsiAdapter->InterruptMask |= BIT_IMR_TXEIM; + HalSsiSetInterruptMaskRtl8195a((VOID*)pHalSsiAdapter); + } + + if (pHalSsiAdapter->TxLength == 0) { + DBG_SSI_INFO("_SsiWriteInterruptRtl8195a: TX_Done\r\n"); + pHalSsiAdapter->InterruptMask &= ~(BIT_IMR_TXOIM | BIT_IMR_TXEIM); + HalSsiSetInterruptMaskRtl8195a((VOID*)pHalSsiAdapter); + // If it's not a dummy TX for master read SPI, then call the TX_done callback + if (pHalSsiAdapter->TxData != NULL) { + if (pHalSsiAdapter->TxCompCallback != NULL) { + pHalSsiAdapter->TxCompCallback(pHalSsiAdapter->TxCompCbPara); + } + } + } +} + + +u32 _SsiIrqHandleRtl8195a(VOID *Adaptor) +{ + SSI_DBG_ENTRANCE("_SsiIrqHandle()\n"); + PHAL_SSI_ADAPTOR pHalSsiAdaptor = (PHAL_SSI_ADAPTOR) Adaptor; + u32 InterruptStatus = HalSsiGetInterruptStatusRtl8195a(Adaptor); + u8 Index = pHalSsiAdaptor->Index; + + if (InterruptStatus & BIT_ISR_TXOIS) { + SSI_DBG_INT_HNDLR("[INT][SSI%d] Transmit FIFO Overflow Interrupt\n", Index); + HAL_SSI_READ32(Index, REG_DW_SSI_TXOICR); + } + + if (InterruptStatus & BIT_ISR_RXUIS) { + SSI_DBG_INT_HNDLR("[INT][SSI%d] Receive FIFO Underflow Interrupt\n", Index); + HAL_SSI_READ32(Index, REG_DW_SSI_RXUICR); + } + + if (InterruptStatus & BIT_ISR_RXOIS) { + SSI_DBG_INT_HNDLR("[INT][SSI%d] Receive FIFO Overflow Interrupt\n", Index); + HAL_SSI_READ32(Index, REG_DW_SSI_RXOICR); + } + + if (InterruptStatus & BIT_ISR_MSTIS) { + SSI_DBG_INT_HNDLR("[INT][SSI%d] Multi-Master Contention Interrupt\n", Index); + /* Another master is actively transferring data */ + /* TODO: Do reading data... */ + HAL_SSI_READ32(Index, REG_DW_SSI_MSTICR); + } + + if ((InterruptStatus & BIT_ISR_RXFIS) ) { + SSI_DBG_INT_HNDLR("[INT][SSI%d] Receive FIFO Full Interrupt\n", Index); + _SsiReadInterruptRtl8195a(Adaptor); + } + + if (InterruptStatus & BIT_ISR_TXEIS) { + /* Tx FIFO is empty, need to transfer data */ + SSI_DBG_INT_HNDLR("[INT][SSI%d] Transmit FIFO Empty Interrupt\n", Index); + _SsiWriteInterruptRtl8195a(Adaptor); + } + + return 0; +} + +HAL_Status HalSsiInitRtl8195a_Patch(VOID *Adaptor) +{ + SSI_DBG_ENTRANCE("HalSsiInitRtl8195a()\n"); + PHAL_SSI_ADAPTOR pHalSsiAdaptor = (PHAL_SSI_ADAPTOR) Adaptor; + volatile IRQn_Type IrqNum; + u32 IRQ_UNKNOWN = -999; + u32 Ctrlr0Value = 0; + u32 Ctrlr1Value = 0; + u32 SerValue = 0; + u32 BaudrValue = 0; + u32 TxftlrValue = 0; + u32 RxftlrValue = 0; + u32 DmacrValue = 0; + u32 MwcrValue = 0; + u32 DmatdlrValue = 0; + u32 DmardlrValue = 0; + u8 MicrowireTransferMode = pHalSsiAdaptor->MicrowireTransferMode; + u8 DataFrameFormat = pHalSsiAdaptor->DataFrameFormat; + u8 TransferMode = pHalSsiAdaptor->TransferMode; + u8 Index = pHalSsiAdaptor->Index; + u8 Role = pHalSsiAdaptor->Role; + + if (Index > 2) { + DBG_SSI_ERR("HalSsiInitRtl8195a: Invalid SSI Idx %d\r\n", Index); + return HAL_ERR_PARA; + } + + HalSsiDisableRtl8195a(Adaptor); + + /* REG_DW_SSI_CTRLR0 */ + Ctrlr0Value |= BIT_CTRLR0_DFS(pHalSsiAdaptor->DataFrameSize); + Ctrlr0Value |= BIT_CTRLR0_FRF(pHalSsiAdaptor->DataFrameFormat); + Ctrlr0Value |= BIT_CTRLR0_SCPH(pHalSsiAdaptor->SclkPhase); + Ctrlr0Value |= BIT_CTRLR0_SCPOL(pHalSsiAdaptor->SclkPolarity); + Ctrlr0Value |= BIT_CTRLR0_TMOD(pHalSsiAdaptor->TransferMode); + Ctrlr0Value |= BIT_CTRLR0_CFS(pHalSsiAdaptor->ControlFrameSize); + + if (Role == SSI_SLAVE) + Ctrlr0Value |= BIT_CTRLR0_SLV_OE(pHalSsiAdaptor->SlaveOutputEnable); + + SSI_DBG_INIT("[1] Set SSI%d REG_DW_SSI_CTRLR0 Value: %X\n", Index, Ctrlr0Value); + + HAL_SSI_WRITE32(Index, REG_DW_SSI_CTRLR0, Ctrlr0Value); + + SSI_DBG_INIT("[2] SSI%d REG_DW_SSI_CTRLR0(%X) = %X\n", Index, + SSI0_REG_BASE + (SSI_REG_OFF * Index) + REG_DW_SSI_CTRLR0, + HAL_SSI_READ32(Index, REG_DW_SSI_CTRLR0)); + + /* REG_DW_SSI_TXFTLR */ + TxftlrValue = BIT_TXFTLR_TFT(pHalSsiAdaptor->TxThresholdLevel); + SSI_DBG_INIT("[1] Set SSI%d REG_DW_SSI_TXFTLR Value: %X\n", Index, TxftlrValue); + + HAL_SSI_WRITE32(Index, REG_DW_SSI_TXFTLR, TxftlrValue); + + SSI_DBG_INIT("[2] SSI%d REG_DW_SSI_TXFTLR(%X) = %X\n", Index, + SSI0_REG_BASE + (SSI_REG_OFF * Index) + REG_DW_SSI_TXFTLR, + HAL_SSI_READ32(Index, REG_DW_SSI_TXFTLR)); + + /* REG_DW_SSI_RXFTLR */ + RxftlrValue = BIT_RXFTLR_RFT(pHalSsiAdaptor->RxThresholdLevel); + SSI_DBG_INIT("[1] Set SSI%d REG_DW_SSI_RXFTLR Value: %X\n", Index, RxftlrValue); + + HAL_SSI_WRITE32(Index, REG_DW_SSI_RXFTLR, RxftlrValue); + + SSI_DBG_INIT("[2] SSI%d REG_DW_SSI_RXFTLR(%X) = %X\n", Index, + SSI0_REG_BASE + (SSI_REG_OFF * Index) + REG_DW_SSI_RXFTLR, + HAL_SSI_READ32(Index, REG_DW_SSI_RXFTLR)); + /** + * Master Only + * REG_DW_SSI_CTRLR1, REG_DW_SSI_SER, REG_DW_SSI_BAUDR + */ + if (Role & SSI_MASTER) { + if ((TransferMode == TMOD_RO) || (TransferMode == TMOD_EEPROM_R) || + ((DataFrameFormat == FRF_NS_MICROWIRE) && (MicrowireTransferMode == MW_TMOD_SEQUENTIAL))) { + Ctrlr1Value = BIT_CTRLR1_NDF(pHalSsiAdaptor->DataFrameNumber); + SSI_DBG_INIT("[1] Set SSI%d REG_DW_SSI_CTRLR1 Value: %X\n", Index, Ctrlr1Value); + + HAL_SSI_WRITE32(Index, REG_DW_SSI_CTRLR1, Ctrlr1Value); + + SSI_DBG_INIT("[2] SSI%d REG_DW_SSI_CTRLR1(%X) = %X\n", Index, + SSI0_REG_BASE + (SSI_REG_OFF * Index) + REG_DW_SSI_CTRLR1, + HAL_SSI_READ32(Index, REG_DW_SSI_CTRLR1)); + } + + SerValue = BIT_SER_SER(1 << (pHalSsiAdaptor->SlaveSelectEnable)); + SSI_DBG_INIT("[1] Set SSI%d REG_DW_SSI_SER Value: %X\n", Index, SerValue); + + //HAL_SSI_WRITE32(Index, REG_DW_SSI_SER, SerValue); + HalSsiSetSlaveEnableRegisterRtl8195a(Adaptor, pHalSsiAdaptor->SlaveSelectEnable); + + SSI_DBG_INIT("[2] SSI%d REG_DW_SSI_SER(%X) = %X\n", Index, + SSI0_REG_BASE + (SSI_REG_OFF * Index) + REG_DW_SSI_SER, + HalSsiGetSlaveEnableRegisterRtl8195a(Adaptor)); + + BaudrValue = BIT_BAUDR_SCKDV(pHalSsiAdaptor->ClockDivider); + SSI_DBG_INIT("[1] Set SSI%d REG_DW_SSI_BAUDR Value: %X\n", Index, BaudrValue); + + HAL_SSI_WRITE32(Index, REG_DW_SSI_BAUDR, BaudrValue); + + SSI_DBG_INIT("[2] SSI%d REG_DW_SSI_BAUDR(%X) = %X\n", Index, + SSI0_REG_BASE + (SSI_REG_OFF * Index) + REG_DW_SSI_BAUDR, + HAL_SSI_READ32(Index, REG_DW_SSI_BAUDR)); + } +#if 0 + /** + * DMA Configurations + */ + DmacrValue = pHalSsiAdaptor->DmaControl; + SSI_DBG_INIT("[1] Set SSI%d REG_DW_SSI_DMACR Value: %X\n", Index, DmacrValue); + + HAL_SSI_WRITE32(Index, REG_DW_SSI_DMACR, DmacrValue); + + SSI_DBG_INIT("[2] SSI%d REG_DW_SSI_DMACR(%X) = %X\n", Index, + SSI0_REG_BASE + (SSI_REG_OFF * Index) + REG_DW_SSI_DMACR, + HAL_SSI_READ32(Index, REG_DW_SSI_DMACR)); + + DmatdlrValue = BIT_DMATDLR_DMATDL(pHalSsiAdaptor->DmaTxDataLevel); + SSI_DBG_INIT("[1] Set SSI%d REG_DW_SSI_DMATDLR Value: %X\n", Index, DmatdlrValue); + + HAL_SSI_WRITE32(Index, REG_DW_SSI_DMATDLR, DmatdlrValue); + + SSI_DBG_INIT("[2] SSI%d REG_DW_SSI_DMATDLR(%X) = %X\n", Index, + SSI0_REG_BASE + (SSI_REG_OFF * Index) + REG_DW_SSI_DMATDLR, + HAL_SSI_READ32(Index, REG_DW_SSI_DMATDLR)); + + DmardlrValue = BIT_DMARDLR_DMARDL(pHalSsiAdaptor->DmaRxDataLevel); + SSI_DBG_INIT("[1] Set SSI%d REG_DW_SSI_DMARDLR Value: %X\n", Index, DmardlrValue); + + HAL_SSI_WRITE32(Index, REG_DW_SSI_DMARDLR, DmardlrValue); + + SSI_DBG_INIT("[2] SSI%d REG_DW_SSI_DMARDLR(%X) = %X\n", Index, + SSI0_REG_BASE + (SSI_REG_OFF * Index) + REG_DW_SSI_DMARDLR, + HAL_SSI_READ32(Index, REG_DW_SSI_DMARDLR)); +#endif + // Microwire + MwcrValue |= BIT_MWCR_MWMOD(pHalSsiAdaptor->MicrowireTransferMode); + MwcrValue |= BIT_MWCR_MDD(pHalSsiAdaptor->MicrowireDirection); + MwcrValue |= BIT_MWCR_MHS(pHalSsiAdaptor->MicrowireHandshaking); + SSI_DBG_INIT("[1] Set SSI%d REG_DW_SSI_MWCR Value: %X\n", Index, MwcrValue); + + HAL_SSI_WRITE32(Index, REG_DW_SSI_MWCR, MwcrValue); + + SSI_DBG_INIT("[2] SSI%d REG_DW_SSI_MWCR(%X) = %X\n", Index, + SSI0_REG_BASE + (SSI_REG_OFF * Index) + REG_DW_SSI_MWCR, + HAL_SSI_READ32(Index, REG_DW_SSI_MWCR)); + + SSI_DBG_INIT("SSI%d TransferMechanism: %d\n", Index, pHalSsiAdaptor->TransferMechanism); + if (pHalSsiAdaptor->TransferMechanism == SSI_DTM_INTERRUPT) + { + SSI_DBG_INIT("SSI%d Interrupt initialize, Interrupt: %X\n", Index, pHalSsiAdaptor->InterruptMask); + switch (Index) { + case 0: + IrqNum = SPI0_IRQ; + break; + case 1: + IrqNum = SPI1_IRQ; + break; + case 2: + IrqNum = SPI2_IRQ; + break; + default: + IrqNum = IRQ_UNKNOWN; + break; + } + + if (likely(IrqNum != IRQ_UNKNOWN)) { + /* REG_DW_SSI_IMR */ + HalSsiSetInterruptMaskRtl8195a(Adaptor); + + pHalSsiAdaptor->IrqHandle.Data = (u32)pHalSsiAdaptor; + pHalSsiAdaptor->IrqHandle.IrqFun = (IRQ_FUN)_SsiIrqHandleRtl8195a; + pHalSsiAdaptor->IrqHandle.IrqNum = (IRQn_Type)IrqNum; + pHalSsiAdaptor->IrqHandle.Priority = pHalSsiAdaptor->InterruptPriority; + + InterruptRegister(&pHalSsiAdaptor->IrqHandle); + InterruptEn(&pHalSsiAdaptor->IrqHandle); + } + else { + SSI_DBG_INIT("Unknown SSI Index.\n"); + pHalSsiAdaptor->TransferMechanism = SSI_DTM_BASIC; + } + } + + HalSsiEnableRtl8195a(Adaptor); + + return HAL_OK; +} + +HAL_Status HalSsiPinmuxEnableRtl8195a_Patch(VOID *Adaptor) +{ + SSI_DBG_ENTRANCE("HalSsiPinmuxEnableRtl8195a()\n"); + PHAL_SSI_ADAPTOR pHalSsiAdaptor = (PHAL_SSI_ADAPTOR) Adaptor; + volatile HAL_Status Result; + u32 PinmuxSelect = pHalSsiAdaptor->PinmuxSelect; + u8 Index = pHalSsiAdaptor->Index; + + SSI_DBG_PINMUX("[1] SSI%d REG_SSI_MUX_CTRL(%X) = %X\n", Index, + PERI_ON_BASE + REG_SPI_MUX_CTRL, + HAL_READ32(PERI_ON_BASE, REG_SPI_MUX_CTRL)); + + switch (Index) + { + case 0: + { + ACTCK_SPI0_CCTRL(ON); + PinCtrl(SPI0, PinmuxSelect, ON); + SPI0_FCTRL(ON); + Result = HAL_OK; + break; + } + case 1: + { + ACTCK_SPI1_CCTRL(ON); + PinCtrl(SPI1, PinmuxSelect, ON); + SPI1_FCTRL(ON); + Result = HAL_OK; + break; + } + case 2: + { + ACTCK_SPI2_CCTRL(ON); + PinCtrl(SPI2, PinmuxSelect, ON); + SPI2_FCTRL(ON); + Result = HAL_OK; + break; + } + default: + { + DBG_SSI_ERR("Invalid SSI Index %d!\n", Index); + Result = HAL_ERR_PARA; + break; + } + } + + SSI_DBG_PINMUX("[2] SSI%d REG_SSI_MUX_CTRL(%X) = %X\n", Index, + PERI_ON_BASE + REG_SPI_MUX_CTRL, + HAL_READ32(PERI_ON_BASE, REG_SPI_MUX_CTRL)); + + return Result; +} + +HAL_Status HalSsiPinmuxDisableRtl8195a(VOID *Adaptor) +{ + SSI_DBG_ENTRANCE("HalSsiPinmuxEnableRtl8195a()\n"); + PHAL_SSI_ADAPTOR pHalSsiAdaptor = (PHAL_SSI_ADAPTOR) Adaptor; + volatile HAL_Status Result; + u32 PinmuxSelect = pHalSsiAdaptor->PinmuxSelect; + u8 Index = pHalSsiAdaptor->Index; + + SSI_DBG_PINMUX("[1] SSI%d REG_SSI_MUX_CTRL(%X) = %X\n", Index, + PERI_ON_BASE + REG_SPI_MUX_CTRL, + HAL_READ32(PERI_ON_BASE, REG_SPI_MUX_CTRL)); + + switch (Index) + { + case 0: + { + ACTCK_SPI0_CCTRL(OFF); + PinCtrl(SPI0, PinmuxSelect, OFF); + SPI0_FCTRL(OFF); + Result = HAL_OK; + break; + } + case 1: + { + ACTCK_SPI1_CCTRL(OFF); + PinCtrl(SPI1, PinmuxSelect, OFF); + SPI1_FCTRL(OFF); + Result = HAL_OK; + break; + } + case 2: + { + ACTCK_SPI2_CCTRL(OFF); + PinCtrl(SPI2, PinmuxSelect, OFF); + SPI2_FCTRL(OFF); + Result = HAL_OK; + break; + } + default: + { + DBG_SSI_ERR("Invalid SSI Index %d!\n", Index); + Result = HAL_ERR_PARA; + break; + } + } + + SSI_DBG_PINMUX("[2] SSI%d REG_SSI_MUX_CTRL(%X) = %X\n", Index, + PERI_ON_BASE + REG_SPI_MUX_CTRL, + HAL_READ32(PERI_ON_BASE, REG_SPI_MUX_CTRL)); + + return Result; +} + + +VOID HalSsiSetSclkRtl8195a(VOID *Adapter, u32 ClkRate) +{ + PHAL_SSI_ADAPTOR pHalSsiAdapter = (PHAL_SSI_ADAPTOR) Adapter; + u32 ssi_clk; + u32 ClockDivider; + u32 SsiEn; + u32 RegValue; + u32 SystemClock; + u8 spi_idx = pHalSsiAdapter->Index; + + // Set SCLK Freq only available for Master mode + // For Slave mode, the baud rate is depends on the Master side, max rate = ssi_clk/2 + // Fsclk_out = Fssi_clk/SCKDV + SystemClock = HalGetCpuClk(); + + if (spi_idx == 1) { + ssi_clk = SystemClock >> 1; + RegValue = HAL_READ32(SYSTEM_CTRL_BASE, 0x250); + if (ClkRate > (ssi_clk/2)) { + // Use High speed clock: Fixed Freq. + RegValue |= BIT18; + ssi_clk = (200000000*5/6) >> 1; + } + else { + // Use Normal speed clock: CPU_Clk/2 + RegValue &= ~BIT18; + } + HAL_WRITE32(SYSTEM_CTRL_BASE, 0x250, RegValue); + } + else { + ssi_clk = SystemClock >> 2; + } + + if (pHalSsiAdapter->Role == SSI_MASTER) { + if (ClkRate > (ssi_clk/2)) { + DBG_SSI_ERR("spi_frequency: Freq %d is too high, available highest Freq=%d\r\n", ClkRate, (ssi_clk/2)); + ClockDivider = 2; + } + else { + ClockDivider = ssi_clk/ClkRate + 1; + if ((ssi_clk%ClkRate) > (ClkRate/2)) { + ClockDivider++; + } + if (ClockDivider >= 0xFFFF) { + // devider is 16 bits + ClockDivider = 0xFFFE; + } + ClockDivider &= 0xFFFE; // bit 0 always is 0 + } + DBG_SSI_INFO("spi_frequency: Set SCLK Freq=%d\r\n", (ssi_clk/ClockDivider)); + pHalSsiAdapter->ClockDivider = ClockDivider; + + SsiEn = HAL_SSI_READ32(spi_idx, REG_DW_SSI_SSIENR); // Backup SSI_EN register + + // Disable SSI first, so we can modify the Clock Divider + RegValue = SsiEn & BIT_INVC_SSIENR_SSI_EN; + HAL_SSI_WRITE32(spi_idx, REG_DW_SSI_SSIENR, RegValue); + HAL_SSI_WRITE32(spi_idx, REG_DW_SSI_BAUDR, (pHalSsiAdapter->ClockDivider & 0xFFFF)); + // recover the SSI_EN setting + HAL_SSI_WRITE32(spi_idx, REG_DW_SSI_SSIENR, SsiEn); + } + else { + if (ClkRate > (ssi_clk/10)) { + DBG_SSI_ERR("spi_frequency: Freq %d is too high, available highest Freq=%d\r\n", ClkRate, (ssi_clk/10)); + } + } +} + +HAL_Status HalSsiIntReadRtl8195a(VOID *Adapter, VOID *RxData, u32 Length) +{ + PHAL_SSI_ADAPTOR pHalSsiAdapter = (PHAL_SSI_ADAPTOR) Adapter; + u32 RxLengthRemainder; + u32 RxFifoThresholdLevel; + u8 Index = pHalSsiAdapter->Index; + + DBG_SSI_INFO("HalSsiIntReadRtl8195a: Idx=%d, RxData=0x%x, Len=0x%x\r\n", Index, RxData, Length); + if (HalSsiBusyRtl8195a(Adapter)) { + // As a Slave mode, if the peer(Master) side is power off, the BUSY flag is always on + DBG_SSI_WARN("HalSsiIntReadRtl8195a: SSI%d is busy\n", Index); + return HAL_BUSY; + } + + if (Length == 0) { + SSI_DBG_INT_READ("SSI%d RxData addr: 0x%X, Length: %d\n", Index, RxData, Length); + return HAL_ERR_PARA; + } + + if (Length > (pHalSsiAdapter->DefaultRxThresholdLevel)) { + RxFifoThresholdLevel = pHalSsiAdapter->DefaultRxThresholdLevel; + } + else { + RxFifoThresholdLevel = 0; + } + + if (pHalSsiAdapter->RxThresholdLevel != RxFifoThresholdLevel) { + DBG_SSI_INFO("Setting Rx FIFO Threshold Level to %d\n", RxFifoThresholdLevel); + pHalSsiAdapter->RxThresholdLevel = RxFifoThresholdLevel; + HalSsiSetRxFifoThresholdLevelRtl8195a((VOID*)pHalSsiAdapter); + } + + if ((pHalSsiAdapter->DataFrameSize+1) > 8) { + // 16~9 bits mode + pHalSsiAdapter->RxLength = Length >> 1; // 2 bytes(16 bit) every transfer + } + else { + // 8~4 bits mode + pHalSsiAdapter->RxLength = Length; // 1 byte(8 bit) every transfer + } + + pHalSsiAdapter->RxData = RxData; + DBG_SSI_INFO("SSI%d RxData addr: 0x%X, Length: %d\n", Index, + pHalSsiAdapter->RxData, pHalSsiAdapter->RxLength); + + pHalSsiAdapter->InterruptMask |= BIT_IMR_RXFIM | BIT_IMR_RXOIM | BIT_IMR_RXUIM; + HalSsiSetInterruptMaskRtl8195a((VOID*)pHalSsiAdapter); + + return HAL_OK; +} + + +HAL_Status +HalSsiIntWriteRtl8195a( + IN VOID *Adapter, // PHAL_SSI_ADAPTOR + IN u8 *pTxData, // the Buffer to be send + IN u32 Length // the length of data to be send +) +{ + PHAL_SSI_ADAPTOR pHalSsiAdapter = (PHAL_SSI_ADAPTOR) Adapter; + + DBG_SSI_INFO("HalSsiIntWriteRtl8195a: Idx=%d, RxData=0x%x, Len=0x%x\r\n", pHalSsiAdapter->Index, pTxData, Length); + if ((Length == 0)) { + DBG_SSI_ERR("HalSsiIntSendRtl8195a: Err: pTxData=0x%x, Length=%d\n", pTxData, Length); + return HAL_ERR_PARA; + } + + if ((pHalSsiAdapter->DataFrameSize+1) > 8) { + // 16~9 bits mode + pHalSsiAdapter->TxLength = Length >> 1; // 2 bytes(16 bit) every transfer + } + else { + // 8~4 bits mode + pHalSsiAdapter->TxLength = Length; // 1 byte(8 bit) every transfer + } + + pHalSsiAdapter->TxData = (void*)pTxData; + pHalSsiAdapter->InterruptMask |= BIT_IMR_TXOIM | BIT_IMR_TXEIM; + HalSsiSetInterruptMaskRtl8195a((VOID*)pHalSsiAdapter); + + return HAL_OK; +} + +#ifdef CONFIG_GDMA_EN +/** + * GDMA IRQ Handler + */ +VOID SsiTxGdmaIrqHandle (VOID *Data) +{ + PHAL_SSI_ADAPTOR pHalSsiAdapter = (PHAL_SSI_ADAPTOR) Data; + PSSI_DMA_CONFIG pDmaConfig = &pHalSsiAdapter->DmaConfig;; + PHAL_GDMA_ADAPTER pHalGdmaAdapter; + PHAL_GDMA_OP pHalGdmaOp; + u8 IsrTypeMap = 0; + + pHalGdmaAdapter = (PHAL_GDMA_ADAPTER)pDmaConfig->pTxHalGdmaAdapter; + pHalGdmaOp = (PHAL_GDMA_OP)pDmaConfig->pHalGdmaOp; + + /* Clear Pending ISR */ + IsrTypeMap = pHalGdmaOp->HalGdmaChIsrClean((VOID*)pHalGdmaAdapter); + /* Maintain Block Count */ +#if 0 + if (IsrTypeMap & BlockType) { + DBG_SSI_WARN("DMA Block %d\n",pHalGdmaAdapter->MuliBlockCunt); + pHalGdmaAdapter->MuliBlockCunt++; + } +#endif + +#if 0 + /* Set SSI DMA Disable */ + HAL_SSI_WRITE32(pHalSsiAdapter->Index, REG_DW_SSI_DMACR, \ + (HAL_SSI_READ32(pHalSsiAdapter->Index, REG_DW_SSI_DMACR) & ~SSI_TXDMA_ENABLE)); +#endif + pHalGdmaOp->HalGdmaChDis((VOID*)(pHalGdmaAdapter)); + // Call user TX complete callback + if (NULL != pHalSsiAdapter->TxCompCallback) { + pHalSsiAdapter->TxCompCallback(pHalSsiAdapter->TxCompCbPara); + } +} + +VOID SsiRxGdmaIrqHandle (VOID *Data) +{ + PHAL_SSI_ADAPTOR pHalSsiAdapter = (PHAL_SSI_ADAPTOR) Data; + PSSI_DMA_CONFIG pDmaConfig = &pHalSsiAdapter->DmaConfig;; + PHAL_GDMA_ADAPTER pHalGdmaAdapter; + PHAL_GDMA_OP pHalGdmaOp; + u8 IsrTypeMap = 0; + + pHalGdmaAdapter = (PHAL_GDMA_ADAPTER)pDmaConfig->pRxHalGdmaAdapter; + pHalGdmaOp = (PHAL_GDMA_OP)pDmaConfig->pHalGdmaOp; + /* Clear Pending ISR */ + IsrTypeMap = pHalGdmaOp->HalGdmaChIsrClean((VOID*)pHalGdmaAdapter); + + /* Maintain Block Count */ +#if 0 + if (IsrTypeMap & BlockType) { + DBG_SSI_WARN("DMA Block %d\n",pHalGdmaAdapter->MuliBlockCunt); + pHalGdmaAdapter->MuliBlockCunt++; + } +#endif + + /* Set SSI DMA Disable */ + HAL_SSI_WRITE32(pHalSsiAdapter->Index, REG_DW_SSI_DMACR, \ + (HAL_SSI_READ32(pHalSsiAdapter->Index, REG_DW_SSI_DMACR) & ~SSI_RXDMA_ENABLE)); + pHalGdmaOp->HalGdmaChDis((VOID*)(pHalGdmaAdapter)); + // Call user RX complete callback + if (NULL != pHalSsiAdapter->RxCompCallback) { + pHalSsiAdapter->RxCompCallback(pHalSsiAdapter->RxCompCbPara); + } + +} + +VOID +HalSsiTxGdmaLoadDefRtl8195a( + IN VOID *Adapter +) +{ + PHAL_SSI_ADAPTOR pHalSsiAdapter = (PHAL_SSI_ADAPTOR) Adapter; + PSSI_DMA_CONFIG pDmaConfig; + PHAL_GDMA_ADAPTER pHalGdmaAdapter; + u8 *pDst; + u8 DmaIdx; + u8 DmaCh; + u8 DstPer; + u8 ssi_idx; + u32 DmaChEn; + IRQn_Type IrqNum; + + if ((NULL == pHalSsiAdapter)) { + return; + } + pDmaConfig = &pHalSsiAdapter->DmaConfig; + + ssi_idx = pHalSsiAdapter->Index; + pHalGdmaAdapter = (PHAL_GDMA_ADAPTER)pDmaConfig->pTxHalGdmaAdapter; + if (NULL == pHalGdmaAdapter) { + DBG_SSI_ERR("HalSsiTxGdmaLoadDefRtl8195a: HalGdmaAdapter is NULL\r\n"); + return; + } + _memset((void *)pHalGdmaAdapter, 0, sizeof(HAL_GDMA_ADAPTER)); + + pHalSsiAdapter->DmaControl |= SSI_TXDMA_ENABLE; + if ((pHalSsiAdapter->DataFrameSize+1) > 8) { + // 16~9 bits mode + pHalSsiAdapter->DmaTxDataLevel = 48; // When TX FIFO entity number <=48 then DMA Request asserted + } + else { + // 8~4 bits mode + pHalSsiAdapter->DmaTxDataLevel = 56; // When TX FIFO entity number <=56 then DMA Request asserted + } + + switch (ssi_idx) { + case 0: + pDst = (u8*) (SSI0_REG_BASE + REG_DW_SSI_DR); + DmaIdx = 0; + DmaCh = 1; + DmaChEn = GdmaCh1; + IrqNum = GDMA0_CHANNEL1_IRQ; + DstPer = GDMA_HANDSHAKE_SSI0_TX; + break; + + case 1: + pDst = (u8*) (SSI1_REG_BASE + REG_DW_SSI_DR); + DmaIdx = 1; + DmaCh = 1; + DmaChEn = GdmaCh1; + IrqNum = GDMA1_CHANNEL1_IRQ; + DstPer = GDMA_HANDSHAKE_SSI1_TX; + break; + + case 2: + pDst = (u8*) (SSI2_REG_BASE + REG_DW_SSI_DR); + DmaIdx = 0; // SPI2 TX only can use GDMA0 + DmaCh = 3; + DmaChEn = GdmaCh3; + IrqNum = GDMA0_CHANNEL3_IRQ; + DstPer = GDMA_HANDSHAKE_SSI2_TX; + break; + + default: + return; + } + + pHalGdmaAdapter->GdmaCtl.TtFc = TTFCMemToPeri; + pHalGdmaAdapter->GdmaCtl.Done = 1; + pHalGdmaAdapter->MuliBlockCunt = 0; + pHalGdmaAdapter->MaxMuliBlock = 1; + pHalGdmaAdapter->GdmaCfg.DestPer = DstPer; + pHalGdmaAdapter->ChDar = (u32)pDst; + pHalGdmaAdapter->GdmaIndex = DmaIdx; + pHalGdmaAdapter->ChNum = DmaCh; + pHalGdmaAdapter->ChEn = DmaChEn; + pHalGdmaAdapter->GdmaIsrType = (BlockType|TransferType|ErrType); + pHalGdmaAdapter->IsrCtrl = ENABLE; + pHalGdmaAdapter->GdmaOnOff = ON; + + pHalGdmaAdapter->GdmaCtl.IntEn = 1; + pHalGdmaAdapter->GdmaCtl.SrcMsize = MsizeOne; + pHalGdmaAdapter->GdmaCtl.DestMsize = MsizeFour; + pHalGdmaAdapter->GdmaCtl.SrcTrWidth = TrWidthFourBytes; + pHalGdmaAdapter->GdmaCtl.DstTrWidth = TrWidthOneByte; + pHalGdmaAdapter->GdmaCtl.Dinc = NoChange; + pHalGdmaAdapter->GdmaCtl.Sinc = IncType; + + pDmaConfig->TxGdmaIrqHandle.Data = (u32)pHalSsiAdapter; + pDmaConfig->TxGdmaIrqHandle.IrqNum = IrqNum; + pDmaConfig->TxGdmaIrqHandle.IrqFun = (IRQ_FUN)SsiTxGdmaIrqHandle; + pDmaConfig->TxGdmaIrqHandle.Priority = 0x10; +} + + +VOID +HalSsiRxGdmaLoadDefRtl8195a( + IN VOID *Adapter +) +{ + PHAL_SSI_ADAPTOR pHalSsiAdapter = (PHAL_SSI_ADAPTOR) Adapter; + PSSI_DMA_CONFIG pDmaConfig; + PHAL_GDMA_ADAPTER pHalGdmaAdapter; + u8 *pSrc; + u8 DmaIdx; + u8 DmaCh; + u8 SrcPer; + u8 ssi_idx; + u32 DmaChEn; + IRQn_Type IrqNum; + + if ((NULL == pHalSsiAdapter)) { + return; + } + + pDmaConfig = &pHalSsiAdapter->DmaConfig; + + ssi_idx = pHalSsiAdapter->Index; + + pHalGdmaAdapter = (PHAL_GDMA_ADAPTER)pDmaConfig->pRxHalGdmaAdapter; + if (NULL == pHalGdmaAdapter) { + return; + } + + _memset((void *)pHalGdmaAdapter, 0, sizeof(HAL_GDMA_ADAPTER)); + + pHalSsiAdapter->DmaControl |= SSI_RXDMA_ENABLE; + if ((pHalSsiAdapter->DataFrameSize+1) > 8) { + // 16~9 bits mode + pHalSsiAdapter->DmaRxDataLevel = 7; // RX FIFO stored bytes > (DMARDLR(7) + 1) then request DMA transfer + } + else { + // 8~4 bits mode + pHalSsiAdapter->DmaRxDataLevel = 3; // RX FIFO stored bytes > (DMARDLR(3) + 1) then request DMA transfer + } + switch (ssi_idx) { + case 0: + pSrc = (u8*) (SSI0_REG_BASE + REG_DW_SSI_DR); + DmaIdx = 0; + DmaCh = 2; + DmaChEn = GdmaCh2; + SrcPer = GDMA_HANDSHAKE_SSI0_RX; + IrqNum = GDMA0_CHANNEL2_IRQ; + break; + + case 1: + pSrc = (u8*) (SSI1_REG_BASE + REG_DW_SSI_DR); + DmaIdx = 1; + DmaCh = 2; + DmaChEn = GdmaCh2; + SrcPer = GDMA_HANDSHAKE_SSI1_RX; + IrqNum = GDMA1_CHANNEL2_IRQ; + break; + + case 2: + pSrc = (u8*) (SSI2_REG_BASE + REG_DW_SSI_DR); + DmaIdx = 1; // SSI2 RX only can use GDMA1 + DmaCh = 3; + DmaChEn = GdmaCh3; + SrcPer = GDMA_HANDSHAKE_SSI2_RX; + IrqNum = GDMA1_CHANNEL3_IRQ; + break; + + default: + return; + } + + pHalGdmaAdapter->GdmaCtl.TtFc = TTFCPeriToMem; + pHalGdmaAdapter->GdmaCtl.Done = 1; + pHalGdmaAdapter->GdmaCfg.ReloadSrc = 1; + pHalGdmaAdapter->GdmaCfg.SrcPer = SrcPer; + pHalGdmaAdapter->MuliBlockCunt = 0; + pHalGdmaAdapter->MaxMuliBlock = 1; + pHalGdmaAdapter->ChSar = (u32)pSrc; + pHalGdmaAdapter->GdmaIndex = DmaIdx; + pHalGdmaAdapter->ChNum = DmaCh; + pHalGdmaAdapter->ChEn = DmaChEn; + pHalGdmaAdapter->GdmaIsrType = (BlockType|TransferType|ErrType); + pHalGdmaAdapter->IsrCtrl = ENABLE; + pHalGdmaAdapter->GdmaOnOff = ON; + + pHalGdmaAdapter->GdmaCtl.IntEn = 1; + pHalGdmaAdapter->GdmaCtl.SrcMsize = MsizeEight; + pHalGdmaAdapter->GdmaCtl.DestMsize = MsizeFour; + pHalGdmaAdapter->GdmaCtl.SrcTrWidth = TrWidthTwoBytes; + pHalGdmaAdapter->GdmaCtl.DstTrWidth = TrWidthFourBytes; + pHalGdmaAdapter->GdmaCtl.Dinc = IncType; + pHalGdmaAdapter->GdmaCtl.Sinc = NoChange; + + pDmaConfig->RxGdmaIrqHandle.Data = (u32)pHalSsiAdapter; + pDmaConfig->RxGdmaIrqHandle.IrqNum = IrqNum; + pDmaConfig->RxGdmaIrqHandle.IrqFun = (IRQ_FUN)SsiRxGdmaIrqHandle; + pDmaConfig->RxGdmaIrqHandle.Priority = 0x10; +} + +VOID +HalSsiDmaInitRtl8195a( + IN VOID *Adapter +) +{ + u32 RegValue; + PHAL_SSI_ADAPTOR pHalSsiAdapter = (PHAL_SSI_ADAPTOR) Adapter; + PSSI_DMA_CONFIG pDmaConfig; + PHAL_GDMA_ADAPTER pTxHalGdmaAdapter; + PHAL_GDMA_ADAPTER pRxHalGdmaAdapter; + u8 ssi_idx; + u32 hdk_tx_bit; + u32 hdk_rx_bit; + u32 DmatdlrValue = 0; + u32 DmardlrValue = 0; + + pDmaConfig = &pHalSsiAdapter->DmaConfig; + pTxHalGdmaAdapter = (PHAL_GDMA_ADAPTER)pDmaConfig->pTxHalGdmaAdapter; + pRxHalGdmaAdapter = (PHAL_GDMA_ADAPTER)pDmaConfig->pRxHalGdmaAdapter; + ssi_idx = pHalSsiAdapter->Index; + + // Set REG_PESOC_SOC_CTRL[28:16] to configure the GDMA handshake connection + // SSI2 handshake connection is hardware fixed + if (ssi_idx != 2) { + hdk_tx_bit = 16+pTxHalGdmaAdapter->GdmaCfg.DestPer; + hdk_rx_bit = 16+pRxHalGdmaAdapter->GdmaCfg.SrcPer; + } + else { + hdk_tx_bit = 0; + hdk_rx_bit = 0; + } + + HalSsiDisableRtl8195a(pHalSsiAdapter); + + RegValue = HAL_READ32(PERI_ON_BASE, REG_PESOC_SOC_CTRL); + if (pHalSsiAdapter->DmaControl & SSI_TXDMA_ENABLE) { + // TX DMA is enabled + if (pTxHalGdmaAdapter->GdmaIndex ==0) { + ACTCK_GDMA0_CCTRL(ON); + GDMA0_FCTRL(ON); + if (hdk_tx_bit != 0) { + RegValue &= ~(1<DmaTxDataLevel); + HAL_SSI_WRITE32(ssi_idx, REG_DW_SSI_DMATDLR, DmatdlrValue); + + /* Set SSI DMA Enable */ + HAL_SSI_WRITE32(pHalSsiAdapter->Index, REG_DW_SSI_DMACR, \ + (HAL_SSI_READ32(pHalSsiAdapter->Index, REG_DW_SSI_DMACR) | SSI_TXDMA_ENABLE)); + } + + if (pHalSsiAdapter->DmaControl & SSI_RXDMA_ENABLE) { + // RX DMA is enabled + if (pRxHalGdmaAdapter->GdmaIndex ==0) { + ACTCK_GDMA0_CCTRL(ON); + GDMA0_FCTRL(ON); + if (hdk_rx_bit != 0) { + RegValue &= ~(1<DmaRxDataLevel); + HAL_SSI_WRITE32(ssi_idx, REG_DW_SSI_DMARDLR, DmardlrValue); + // the RX DMA will be enabled at read start. + } + + HAL_WRITE32(PERI_ON_BASE, REG_PESOC_SOC_CTRL, RegValue); + + HalSsiEnableRtl8195a(pHalSsiAdapter); +} + +HAL_Status +HalSsiDmaSendRtl8195a( + IN VOID *Adapter, // PHAL_SSI_ADAPTOR + IN u8 *pTxData, // the Buffer to be send + IN u32 Length // the length of data to be send +) +{ + PHAL_SSI_ADAPTOR pHalSsiAdapter = (PHAL_SSI_ADAPTOR) Adapter; + PSSI_DMA_CONFIG pDmaConfig; + PHAL_GDMA_ADAPTER pHalGdmaAdapter; + PHAL_GDMA_OP pHalGdmaOp; + + + if ((pTxData == NULL) || (Length == 0)) { + DBG_SSI_ERR("HalSsiDmaSendRtl8195a: Err: pTxData=0x%x, Length=%d\n", pTxData, Length); + return HAL_ERR_PARA; + } + pDmaConfig = &pHalSsiAdapter->DmaConfig; + pHalGdmaAdapter = (PHAL_GDMA_ADAPTER)pDmaConfig->pTxHalGdmaAdapter; + + pHalSsiAdapter->TxLength = Length; + pHalSsiAdapter->TxData = (void*)pTxData; + + // Cofigure GDMA transfer + if ((pHalSsiAdapter->DataFrameSize+1) > 8) { + // 16~9 bits mode + if (((Length & 0x03)==0) && + (((u32)(pTxData) & 0x03)==0)) { + // 4-bytes aligned, move 4 bytes each transfer + pHalGdmaAdapter->GdmaCtl.SrcMsize = MsizeFour; + pHalGdmaAdapter->GdmaCtl.SrcTrWidth = TrWidthFourBytes; + pHalGdmaAdapter->GdmaCtl.DestMsize = MsizeEight; + pHalGdmaAdapter->GdmaCtl.DstTrWidth = TrWidthTwoBytes; + pHalGdmaAdapter->GdmaCtl.BlockSize = Length >> 2; + } + else if (((Length & 0x01)==0) && + (((u32)(pTxData) & 0x01)==0)) { + // 2-bytes aligned, move 2 bytes each transfer + pHalGdmaAdapter->GdmaCtl.SrcMsize = MsizeEight; + pHalGdmaAdapter->GdmaCtl.SrcTrWidth = TrWidthTwoBytes; + pHalGdmaAdapter->GdmaCtl.DestMsize = MsizeEight; + pHalGdmaAdapter->GdmaCtl.DstTrWidth = TrWidthTwoBytes; + pHalGdmaAdapter->GdmaCtl.BlockSize = Length >> 1; + } + else { + DBG_SSI_ERR("HalSsiDmaSendRtl8195a: Aligment Err: pTxData=0x%x, Length=%d\n", pTxData, Length); + return HAL_ERR_PARA; + } + } + else { + // 8~4 bits mode + if (((Length & 0x03)==0) && + (((u32)(pTxData) & 0x03)==0)) { + // 4-bytes aligned, move 4 bytes each transfer + pHalGdmaAdapter->GdmaCtl.SrcMsize = MsizeOne; + pHalGdmaAdapter->GdmaCtl.SrcTrWidth = TrWidthFourBytes; + pHalGdmaAdapter->GdmaCtl.BlockSize = Length >> 2; + } + else { + pHalGdmaAdapter->GdmaCtl.SrcMsize = MsizeFour; + pHalGdmaAdapter->GdmaCtl.SrcTrWidth = TrWidthOneByte; + pHalGdmaAdapter->GdmaCtl.BlockSize = Length; + } + pHalGdmaAdapter->GdmaCtl.DestMsize = MsizeFour; + pHalGdmaAdapter->GdmaCtl.DstTrWidth = TrWidthOneByte; + } + + DBG_SSI_INFO("SrcMsize=%d SrcTrWidth=%d DestMsize=%d DstTrWidth=%d BlockSize=%d\n", \ + pHalGdmaAdapter->GdmaCtl.SrcMsize, pHalGdmaAdapter->GdmaCtl.SrcTrWidth, \ + pHalGdmaAdapter->GdmaCtl.DestMsize, pHalGdmaAdapter->GdmaCtl.DstTrWidth, \ + pHalGdmaAdapter->GdmaCtl.BlockSize); + + if (pHalGdmaAdapter->GdmaCtl.BlockSize > 4096) { + // over Maximum block size 4096 + DBG_SSI_ERR("HalSsiDmaSendRtl8195a: GDMA Block Size(%d) too big\n", pHalGdmaAdapter->GdmaCtl.BlockSize); + return HAL_ERR_PARA; + } + + pHalGdmaAdapter->ChSar = (u32)pTxData; + + // Enable GDMA for TX + pHalGdmaOp = (PHAL_GDMA_OP)pDmaConfig->pHalGdmaOp; + pHalGdmaOp->HalGdmaChSeting((VOID*)(pHalGdmaAdapter)); + pHalGdmaOp->HalGdmaChEn((VOID*)(pHalGdmaAdapter)); + +#if 0 + /* Set SSI DMA Enable */ + // TODO: protect the enable DMA register, it may collision with the DMA disable in the GDMA done ISR + HAL_SSI_WRITE32(pHalSsiAdapter->Index, REG_DW_SSI_DMACR, \ + (HAL_SSI_READ32(pHalSsiAdapter->Index, REG_DW_SSI_DMACR) | SSI_TXDMA_ENABLE)); +#endif + + return HAL_OK; +} + +HAL_Status +HalSsiDmaRecvRtl8195a( + IN VOID *Adapter, // PHAL_SSI_ADAPTOR + IN u8 *pRxData, ///< Rx buffer + IN u32 Length // buffer length +) +{ + PHAL_SSI_ADAPTOR pHalSsiAdapter = (PHAL_SSI_ADAPTOR) Adapter; + PSSI_DMA_CONFIG pDmaConfig; + PHAL_GDMA_ADAPTER pHalGdmaAdapter; + PHAL_GDMA_OP pHalGdmaOp; + + if ((pRxData == NULL) || (Length == 0)) { + DBG_SSI_ERR("HalRuartDmaRecvRtl8195a: Null Err: pRxData=0x%x, Length=%d\n", pRxData, Length); + return HAL_ERR_PARA; + } + + pDmaConfig = &pHalSsiAdapter->DmaConfig; + pHalGdmaAdapter = (PHAL_GDMA_ADAPTER)pDmaConfig->pRxHalGdmaAdapter; + + pHalSsiAdapter->RxLength = Length; + pHalSsiAdapter->RxData = (void*)pRxData; + + // Cofigure GDMA transfer + if ((pHalSsiAdapter->DataFrameSize+1) > 8) { + // 16~9 bits mode + pHalGdmaAdapter->GdmaCtl.SrcMsize = MsizeEight; + pHalGdmaAdapter->GdmaCtl.SrcTrWidth = TrWidthTwoBytes; + pHalGdmaAdapter->GdmaCtl.BlockSize = Length >> 1; + if (((Length & 0x03)==0) && + (((u32)(pRxData) & 0x03)==0)) { + // 4-bytes aligned, move 4 bytes each transfer + pHalGdmaAdapter->GdmaCtl.DestMsize = MsizeFour; + pHalGdmaAdapter->GdmaCtl.DstTrWidth = TrWidthFourBytes; + } + else if (((Length & 0x01)==0) && + (((u32)(pRxData) & 0x01)==0)) { + // 2-bytes aligned, move 2 bytes each transfer + pHalGdmaAdapter->GdmaCtl.DestMsize = MsizeEight; + pHalGdmaAdapter->GdmaCtl.DstTrWidth = TrWidthTwoBytes; + } + else { + DBG_SSI_ERR("HalSsiDmaSendRtl8195a: Aligment Err: pTxData=0x%x, Length=%d\n", pRxData, Length); + return HAL_ERR_PARA; + } + } + else { + // 8~4 bits mode + pHalGdmaAdapter->GdmaCtl.SrcMsize = MsizeFour; + pHalGdmaAdapter->GdmaCtl.SrcTrWidth = TrWidthOneByte; + pHalGdmaAdapter->GdmaCtl.BlockSize = Length; + if (((Length & 0x03)==0) && + (((u32)(pRxData) & 0x03)==0)) { + // 4-bytes aligned, move 4 bytes each transfer + pHalGdmaAdapter->GdmaCtl.DestMsize = MsizeOne; + pHalGdmaAdapter->GdmaCtl.DstTrWidth = TrWidthFourBytes; + } + else { + pHalGdmaAdapter->GdmaCtl.DestMsize = MsizeFour; + pHalGdmaAdapter->GdmaCtl.DstTrWidth = TrWidthOneByte; + } + } + + if (pHalGdmaAdapter->GdmaCtl.BlockSize > 4096) { + // over Maximum block size 4096 + DBG_SSI_ERR("HalRuartDmaRecvRtl8195a: GDMA Block Size(%d) too big\n", pHalGdmaAdapter->GdmaCtl.BlockSize); + return HAL_ERR_PARA; + } + + pHalGdmaAdapter->ChDar = (u32)pRxData; + + // Enable GDMA for RX + pHalGdmaOp = (PHAL_GDMA_OP)pDmaConfig->pHalGdmaOp; + pHalGdmaOp->HalGdmaChSeting((VOID*)(pHalGdmaAdapter)); + pHalGdmaOp->HalGdmaChEn((VOID*)(pHalGdmaAdapter)); + + /* Set SSI DMA Enable */ + // TODO: protect the enable DMA register, it may collision with the DMA disable in the GDMA TX done ISR + HAL_SSI_WRITE32(pHalSsiAdapter->Index, REG_DW_SSI_DMACR, \ + (HAL_SSI_READ32(pHalSsiAdapter->Index, REG_DW_SSI_DMACR) | SSI_RXDMA_ENABLE)); + + return HAL_OK; +} + +#endif // end of "#ifdef CONFIG_GDMA_EN" + diff --git a/component/soc/realtek/8195a/fwlib/rtl8195a/src/rtl8195a_timer.c b/component/soc/realtek/8195a/fwlib/rtl8195a/src/rtl8195a_timer.c new file mode 100644 index 0000000..911c5b8 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/rtl8195a/src/rtl8195a_timer.c @@ -0,0 +1,317 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ +#include "rtl8195a.h" +#include "rtl8195a_timer.h" + +extern u32 gTimerRecord; +extern IRQ_FUN Timer2To7VectorTable[MAX_TIMER_VECTOR_TABLE_NUM]; + +#ifdef CONFIG_CHIP_C_CUT +extern u32 Timer2To7HandlerData[MAX_TIMER_VECTOR_TABLE_NUM]; +#else +u32 Timer2To7HandlerData[MAX_TIMER_VECTOR_TABLE_NUM]; +#endif + +VOID +HalTimerIrq2To7Handle_Patch( + IN VOID *Data +) +{ + u32 TimerIrqStatus = 0, CheckIndex; + IRQ_FUN pHandler; + + TimerIrqStatus = HAL_TIMER_READ32(TIMERS_INT_STATUS_OFF); + + DBG_TIMER_INFO("%s:TimerIrqStatus: 0x%x\n",__FUNCTION__, TimerIrqStatus); + + for (CheckIndex = 2; CheckIndex<8; CheckIndex++) { + + //3 Check IRQ status bit and Timer X IRQ enable bit + if ((TimerIrqStatus & BIT_(CheckIndex)) && + (HAL_TIMER_READ32(TIMER_INTERVAL*CheckIndex + TIMER_CTL_REG_OFF) & BIT0)) { + //3 Execute Timer callback function + pHandler = Timer2To7VectorTable[CheckIndex-2]; + if (pHandler != NULL) { + pHandler((void*)Timer2To7HandlerData[CheckIndex-2]); + } + //3 Clear Timer ISR + HAL_TIMER_READ32(TIMER_INTERVAL*CheckIndex + TIMER_EOI_OFF); + } + } +} + +HAL_Status +HalTimerIrqRegisterRtl8195a_Patch( + IN VOID *Data +) +{ + PTIMER_ADAPTER pHalTimerAdap = (PTIMER_ADAPTER) Data; + IRQ_HANDLE TimerIrqHandle; + IRQ_FUN BackUpIrqFun = NULL; + + if (pHalTimerAdap->TimerId > 7) { + DBG_TIMER_ERR("%s: No Support Timer ID %d!\r\n", __FUNCTION__, pHalTimerAdap->TimerId); + return HAL_ERR_PARA; + } + else { + if (pHalTimerAdap->TimerId > 1) { + + TimerIrqHandle.IrqNum = TIMER2_7_IRQ; + TimerIrqHandle.IrqFun = (IRQ_FUN) HalTimerIrq2To7Handle_Patch; + + Timer2To7VectorTable[pHalTimerAdap->TimerId-2] = + (IRQ_FUN) pHalTimerAdap->IrqHandle.IrqFun; + Timer2To7HandlerData[pHalTimerAdap->TimerId-2] = + (uint32_t) pHalTimerAdap->IrqHandle.Data; + } + else { + TimerIrqHandle.IrqNum = (pHalTimerAdap->TimerId ? TIMER1_IRQ : TIMER0_IRQ); + TimerIrqHandle.IrqFun = (IRQ_FUN) pHalTimerAdap->IrqHandle.IrqFun; + } + TimerIrqHandle.Data = (u32)pHalTimerAdap; + InterruptRegister(&TimerIrqHandle); + } + + return HAL_OK; +} + +HAL_Status +HalTimerInitRtl8195a_Patch( + IN VOID *Data +) +{ + PTIMER_ADAPTER pHalTimerAdap = (PTIMER_ADAPTER) Data; + HAL_Status ret=HAL_OK; + u32 ControlReg = 0, LoadCount = 0; + u32 LoadUsX4; + + if ((gTimerRecord & (1<TimerId)) != 0) { + DBG_TIMER_ERR ("%s:Error! Timer %d is occupied!\r\n", __FUNCTION__, pHalTimerAdap->TimerId); + return HAL_BUSY; + } + + ControlReg = ((u32)pHalTimerAdap->TimerMode<<1)|((u32)pHalTimerAdap->IrqDis<<2); + + if (pHalTimerAdap->TimerMode) { + //User-defined Mode + LoadUsX4 = pHalTimerAdap->TimerLoadValueUs << 2; + if (LoadUsX4 < TIMER_TICK_US_X4) { + DBG_TIMER_WARN("%s : Timer Load Count = 1!\r\n", __FUNCTION__); + LoadCount = 1; + } + else { + LoadCount = (LoadUsX4-(TIMER_TICK_US_X4>>1))/TIMER_TICK_US_X4; // to get the most closed integer + if (LoadCount == 0) { + LoadCount = 1; + } + } + } + else { + LoadCount = 0xFFFFFFFF; + } + + + //4 1) Config Timer Setting + /* + set TimerControlReg + 0: Timer enable (0,disable; 1,enable) + 1: Timer Mode (0, free-running mode; 1, user-defined count mode) + 2: Timer Interrupt Mask (0, not masked; 1,masked) + */ + HAL_TIMER_WRITE32((TIMER_INTERVAL*pHalTimerAdap->TimerId + TIMER_CTL_REG_OFF), + ControlReg); + + // set TimerLoadCount Register + HAL_TIMER_WRITE32((TIMER_INTERVAL*pHalTimerAdap->TimerId + TIMER_LOAD_COUNT_OFF), + LoadCount); + + //4 2) Setting Timer IRQ + if (!pHalTimerAdap->IrqDis) { + if (pHalTimerAdap->IrqHandle.IrqFun != NULL) { + //4 2.1) Initial TimerIRQHandle + ret = HalTimerIrqRegisterRtl8195a_Patch(pHalTimerAdap); + if (HAL_OK != ret) { + DBG_TIMER_ERR ("%s: Timer %d Register IRQ Err!\r\n", __FUNCTION__, pHalTimerAdap->TimerId); + return ret; + } + //4 2.2) Enable TimerIRQ for Platform + InterruptEn((PIRQ_HANDLE)&pHalTimerAdap->IrqHandle); + + } + else { + DBG_TIMER_ERR ("%s: Timer %d ISR Handler is NULL!\r\n", __FUNCTION__, pHalTimerAdap->TimerId); + return HAL_ERR_PARA; + } + + } + + //4 4) Enable Timer +// HAL_TIMER_WRITE32((TIMER_INTERVAL*pHalTimerAdap->TimerId + TIMER_CTL_REG_OFF), +// (ControlReg|0x1)); + + gTimerRecord |= (1<TimerId); + + return ret; +} + + +HAL_Status +HalTimerIrqUnRegisterRtl8195a_Patch( + IN VOID *Data +) +{ + PTIMER_ADAPTER pHalTimerAdap = (PTIMER_ADAPTER) Data; + PIRQ_HANDLE pTimerIrqHandle; + u32 i; + + pTimerIrqHandle = &pHalTimerAdap->IrqHandle; + + if (pHalTimerAdap->TimerId > 7) { + DBG_TIMER_ERR("%s:Error: No Support Timer ID!\n", __FUNCTION__); + return HAL_ERR_PARA; + } + else { + if (pHalTimerAdap->TimerId > 1) { + pTimerIrqHandle->IrqNum = TIMER2_7_IRQ; + Timer2To7VectorTable[pHalTimerAdap->TimerId-2] = NULL; + for (i=0;iIrqHandle); + InterruptUnRegister(pTimerIrqHandle); + } + } + else { + pTimerIrqHandle->IrqNum = (pHalTimerAdap->TimerId ? TIMER1_IRQ : TIMER0_IRQ); + InterruptUnRegister(pTimerIrqHandle); + } + + } + + return HAL_OK; +} + + +VOID +HalTimerDeInitRtl8195a_Patch( + IN VOID *Data +) +{ + PTIMER_ADAPTER pHalTimerAdap = (PTIMER_ADAPTER) Data; + u32 timer_id; + + timer_id = pHalTimerAdap->TimerId; + HalTimerDisRtl8195a (timer_id); + if (!pHalTimerAdap->IrqDis) { + if (pHalTimerAdap->IrqHandle.IrqFun != NULL) { + HalTimerIrqUnRegisterRtl8195a_Patch(pHalTimerAdap); + } + } + + gTimerRecord &= ~(1<TimerId); +} + +VOID +HalTimerReLoadRtl8195a_Patch( + IN u32 TimerId, + IN u32 LoadUs +) +{ + u32 LoadCount = 0; + u32 LoadUsX4; + + //User-defined Mode + LoadUsX4 = LoadUs << 2; // time 4 + if (LoadUsX4 < TIMER_TICK_US_X4) { + DBG_TIMER_WARN("HalTimerReLoadRtl8195a Warning : Timer Load Count = 1!!!!!!!\n"); + LoadCount = 1; + } + else { + LoadCount = (LoadUsX4-(TIMER_TICK_US_X4>>1))/TIMER_TICK_US_X4; // to get the most closed integer + if (LoadCount == 0) { + LoadCount = 1; + } + } + + DBG_TIMER_INFO("%s: Load Count=0x%x\r\n", __FUNCTION__, LoadCount); + // set TimerLoadCount Register + HAL_TIMER_WRITE32((TIMER_INTERVAL*TimerId + TIMER_LOAD_COUNT_OFF), + LoadCount); +} + +u32 +HalTimerReadCountRtl8195a_Patch( + IN u32 TimerId +) +{ + u32 TimerCountOld; + u32 TimerCountNew; + u32 TimerRDCnt; + + TimerRDCnt = 0; + TimerCountOld = HAL_TIMER_READ32(TimerId*TIMER_INTERVAL + TIMER_CURRENT_VAL_OFF); + while(1) { + TimerCountNew = HAL_TIMER_READ32(TimerId*TIMER_INTERVAL + TIMER_CURRENT_VAL_OFF); + + if (TimerCountOld == TimerCountNew) { + return (u32)TimerCountOld; + } + else { + TimerRDCnt++; + TimerCountOld = TimerCountNew; + + if (TimerRDCnt >= 2){ + return (u32)TimerCountOld; + } + } + } +} + +VOID +HalTimerIrqEnRtl8195a( + IN u32 TimerId +) +{ + HAL_TIMER_WRITE32((TIMER_INTERVAL*TimerId + TIMER_CTL_REG_OFF), + HAL_TIMER_READ32(TIMER_INTERVAL*TimerId + TIMER_CTL_REG_OFF) & (~(BIT2))); +} + +VOID +HalTimerIrqDisRtl8195a( + IN u32 TimerId +) +{ + HAL_TIMER_WRITE32((TIMER_INTERVAL*TimerId + TIMER_CTL_REG_OFF), + HAL_TIMER_READ32(TIMER_INTERVAL*TimerId + TIMER_CTL_REG_OFF) | (BIT2)); +} + +VOID +HalTimerEnRtl8195a_Patch( + IN u32 TimerId +) +{ + HAL_TIMER_WRITE32((TIMER_INTERVAL*TimerId + TIMER_CTL_REG_OFF), + HAL_TIMER_READ32(TIMER_INTERVAL*TimerId + TIMER_CTL_REG_OFF) | (BIT0)); +} + +VOID +HalTimerDisRtl8195a_Patch( + IN u32 TimerId +) +{ + // Disable Timer will alos disable the IRQ, so need to re-enable the IRQ when re-enable the timer + HAL_TIMER_WRITE32((TIMER_INTERVAL*TimerId + TIMER_CTL_REG_OFF), + HAL_TIMER_READ32(TIMER_INTERVAL*TimerId + TIMER_CTL_REG_OFF) & (~BIT0)); +} + diff --git a/component/soc/realtek/8195a/fwlib/rtl8195a/src/rtl8195a_uart.c b/component/soc/realtek/8195a/fwlib/rtl8195a/src/rtl8195a_uart.c new file mode 100644 index 0000000..e1bc13a --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/rtl8195a/src/rtl8195a_uart.c @@ -0,0 +1,399 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + + +#include "rtl8195a.h" +#include "rtl8195a_uart.h" +#include "hal_uart.h" +#include "hal_gdma.h" + +#if (CONFIG_CHIP_A_CUT | CONFIG_CHIP_B_CUT) + +const u32 BAUDRATE_PATCH[] = { + 1200, 2400, 4800, 9600, + 14400, 19200, 28800, 38400, + 57600, 76800, 115200, 128000, + 153600, 230400, 460800, 500000, + 921600, 1000000, 1382400, 1444400, + 1500000, 1843200, 2000000, 2100000, + 2764800, 3000000, 3250000, 3692300, + 3750000, 4000000, 6000000, + + // For UART to IR Carrier + 66000, 72000, 73400, 76000, + 80000, 112000 +}; + +#if 0 +const u32 OVSR_PATCH[] = { + 11, 13, 19, 10, + 20, 10, 20, 17, + 11, 10, 17, 10, + 10, 13, 18, 13, + 20, 19, 13, 15, + 13, 13, 15, 13, + 12, 11, 11, 20, + 13 +}; + +const u32 DIV_PATCH[] = { + 6105, 643, 293, 434, + 142, 217, 71, 62, + 65, 62, 31, 34, + 17, 12, 5, 6, + 3, 3, 4, 3, + 3, 3, 2, 2, + 2, 2, 2, 1, + 1 +}; + +const u32 OVSR_ADJ_PATCH[] = { + 0x24A, 0x555, 0x3BB, 0x000, + 0x24A, 0x000, 0x24A, 0x555, + 0x008, 0x555, 0x555, 0x5AD, + 0x5AD, 0x7EF, 0x020, 0x7EF, + 0x020, 0x444, 0x7EF, 0x080, + 0x7EF, 0x444, 0x080, 0x7EF, + 0x6FB, 0x122, 0x010, 0x5F7, + 0x7EF +}; +#else +const u8 OVSR_PATCH[] = { + 10, 10, 10, 15, + 10, 13, 15, 11, + 12, 11, 12, 11, + 11, 18, 11, 18, + 11, 10, 11, 11, + 18, 11, 10, 13, + 14, 13, 12, 11, + 10, 10, 13, + + // For UART to IR Carrier + 11, 18, 14, 10, + 10, 11 +}; + +const u16 DIV_PATCH[] = { + 6516, 3258, 1629, 543, + 543, 311, 181, 188, + 114, 94, 57, 57, + 47, 19, 15, 9, + 8, 8, 5, 5, + 3, 4, 4, 3, + 2, 2, 2, 2, + 2, 2, 1, + + // For UART to IR Carrier + 111, 63, 79, 102, + 98, 64 +}; + +const u16 OVSR_ADJ_PATCH[] = { + 0x555, 0x555, 0x555, 0x3BB, + 0x555, 0x5DD, 0x3BB, 0x252, + 0x555, 0x252, 0x555, 0x222, + 0x252, 0x3BB, 0x7EF, 0x444, + 0x008, 0x222, 0x7EF, 0x252, + 0x444, 0x008, 0x222, 0x000, + 0x5F7, 0x76D, 0x5AD, 0x010, + 0x5FF, 0x222, 0x76D, + + // For UART to IR Carrier + 0x24A, 0x252, 0x252, 0x5DD, + 0x5AD, 0x5AD +}; +#endif +#if 0 +static s32 +FindElementIndex( + u32 Element, ///< RUART Baudrate + u32* Array ///< Pre-defined Baudrate Array + ) +{ + /* DBG_ENTRANCE; */ + u32 BaudRateNumber = 29; + s32 Result = -1; + u32 Index = 0; + + for (Index = 0; Index < BaudRateNumber && Result == -1; Index++) { + if (Element == Array[Index]) + Result = Index; + } + return Result; //TODO: Error handling +} +#endif +s32 +FindElementIndex_Patch( + u32 Element, ///< RUART Baudrate + u32* Array, ///< Pre-defined Baudrate Array + u32 ElementNo + ) +{ + /* DBG_ENTRANCE; */ + s32 Result = -1; + u32 Index = 0; + + for (Index = 0; Index < ElementNo && Result == -1; Index++) { + if (Element == Array[Index]) + Result = Index; + } + return Result; //TODO: Error handling +} + +HAL_Status +HalRuartInitRtl8195a_Patch( + IN VOID *Data ///< RUART Adapter + ) +{ + /* DBG_ENTRANCE; */ + u32 RegValue; + u32 Divisor; + u32 Dll; + u32 Dlm; + u8 UartIndex; + s32 ElementIndex; + RUART_SPEED_SETTING RuartSpeedSetting; + u8 PinmuxSelect; + + PHAL_RUART_ADAPTER pHalRuartAdapter = (PHAL_RUART_ADAPTER) Data; + + UartIndex = pHalRuartAdapter->UartIndex; + PinmuxSelect = pHalRuartAdapter->PinmuxSelect; + + if (UartIndex > 2) { + DBG_UART_ERR(ANSI_COLOR_MAGENTA"HalRuartInitRtl8195a: Invalid UART Index\n"ANSI_COLOR_RESET); + return HAL_ERR_PARA; + } + + DBG_UART_INFO("%s==>\n", __FUNCTION__); + DBG_UART_INFO("HalRuartInitRtl8195a: [UART %d] PinSel=%d\n", UartIndex, PinmuxSelect); + if(( PinmuxSelect == RUART0_MUX_TO_GPIOE ) && ((UartIndex == 0) || (UartIndex == 1))) { + DBG_UART_WARN(ANSI_COLOR_MAGENTA"UART Pin may conflict with JTAG\r\n"ANSI_COLOR_RESET); + } + + // switch Pin from EEPROM to UART0 + if(( PinmuxSelect == RUART0_MUX_TO_GPIOC ) && (UartIndex == 0)) { + RegValue = HAL_READ32(SYSTEM_CTRL_BASE, 0xa4); + if (RegValue & 0x10) { + DBG_UART_WARN("Disable EEPROM Pin for UART 0\n"); + HAL_WRITE32(SYSTEM_CTRL_BASE, 0xa4, (RegValue & (~0x10))); + } + } + + switch (UartIndex) { + case 0: + /* UART 0 */ + ACTCK_UART0_CCTRL(ON); + SLPCK_UART0_CCTRL(ON); + PinCtrl(UART0, PinmuxSelect, ON); + UART0_FCTRL(ON); + UART0_BD_FCTRL(ON); + break; + + case 1: + /* UART 1 */ + ACTCK_UART1_CCTRL(ON); + SLPCK_UART1_CCTRL(ON); + PinCtrl(UART1, PinmuxSelect, ON); + UART1_FCTRL(ON); + UART1_BD_FCTRL(ON); + break; + + case 2: + /* UART 1 */ + ACTCK_UART2_CCTRL(ON); + SLPCK_UART2_CCTRL(ON); + PinCtrl(UART2, PinmuxSelect, ON); + UART2_FCTRL(ON); + UART2_BD_FCTRL(ON); + break; + + default: + DBG_UART_ERR("Invalid UART Index(%d)\n", UartIndex); + return HAL_ERR_PARA; + } + + /* Reset RX FIFO */ + HalRuartResetRxFifoRtl8195a(Data); + DBG_UART_INFO(ANSI_COLOR_CYAN"HAL UART Init[UART %d]\n"ANSI_COLOR_RESET, UartIndex); + + /* Disable all interrupts */ + HAL_RUART_WRITE32(UartIndex, RUART_INTERRUPT_EN_REG_OFF, 0x00); + + /* Set DLAB bit to 1 to access DLL/DLM */ + RegValue = HAL_RUART_READ32(UartIndex, RUART_LINE_CTL_REG_OFF); + RegValue |= RUART_LINE_CTL_REG_DLAB_ENABLE; + HAL_RUART_WRITE32(UartIndex, RUART_LINE_CTL_REG_OFF, RegValue); + DBG_UART_INFO("[R] RUART_LINE_CTL_REG_OFF(0x0C) = %x\n", HAL_RUART_READ32(UartIndex, RUART_LINE_CTL_REG_OFF)); + + /* Set Baudrate Division */ +#if 1 + ElementIndex = FindElementIndex_Patch(pHalRuartAdapter->BaudRate, (uint32_t*)BAUDRATE_PATCH, sizeof(BAUDRATE_PATCH)/sizeof(u32)); + if (ElementIndex < 0) { + ElementIndex = 5; + DBG_UART_ERR("Invalid BaudRate(%d), Force it as default(%d)\n", pHalRuartAdapter->BaudRate, BAUDRATE_PATCH[ElementIndex]); + } + + RuartSpeedSetting.BaudRate = BAUDRATE_PATCH[ElementIndex]; + RuartSpeedSetting.Ovsr = OVSR_PATCH[ElementIndex]; + RuartSpeedSetting.Div = DIV_PATCH[ElementIndex]; + RuartSpeedSetting.Ovsr_adj = OVSR_ADJ_PATCH[ElementIndex]; +#else + RuartSpeedSetting.BaudRate = 38400; + RuartSpeedSetting.Ovsr = 10; + RuartSpeedSetting.Div = 217; + RuartSpeedSetting.Ovsr_adj = 0x0; +#endif + + DBG_UART_INFO("Baud %d, Ovsr %d, Div %d, OvsrAdj 0x%X\n", + RuartSpeedSetting.BaudRate, + RuartSpeedSetting.Ovsr, + RuartSpeedSetting.Div, + RuartSpeedSetting.Ovsr_adj + ); + /* Divisor = (SYSTEM_CLK / ((ovsr + 5 + ovsr_adj/11) * (UartAdapter.BaudRate))); */ + + /* Set Divisor */ + Divisor = RuartSpeedSetting.Div; + + Dll = Divisor & 0xFF; + Dlm = (Divisor & 0xFF00) >> 8; + +// DBG_UART_INFO("Calculated Dll, Dlm = %02x, %02x\n", Dll, Dlm); +// DBG_UART_INFO("---- Before setting baud rate ----\n"); +// DBG_UART_INFO(" [R] RUART_DLL_OFF(0x00) = %x\n", HAL_RUART_READ32(UartIndex, RUART_DLL_OFF)); +// DBG_UART_INFO(" [R] RUART_DLM_OFF(0x04) = %x\n", HAL_RUART_READ32(UartIndex, RUART_DLM_OFF)); + + HAL_RUART_WRITE32(UartIndex, RUART_DLL_OFF, Dll); + HAL_RUART_WRITE32(UartIndex, RUART_DLM_OFF, Dlm); + +// DBG_UART_INFO("---- After setting baud rate ----\n"); +// DBG_UART_INFO(" [R] RUART_DLL_OFF(0x00) = %x\n", HAL_RUART_READ32(UartIndex, RUART_DLL_OFF)); +// DBG_UART_INFO(" [R] RUART_DLM_OFF(0x04) = %x\n", HAL_RUART_READ32(UartIndex, RUART_DLM_OFF)); + +// DBG_UART_INFO(ANSI_COLOR_CYAN"---- Befor OVSR & OVSR_ADJ ----\n"ANSI_COLOR_RESET); +// RegValue = HAL_RUART_READ32(UartIndex, RUART_SCRATCH_PAD_REG_OFF); +// DBG_UART_INFO("UART%d SPR(0x1C) = %X\n", UartIndex, RegValue); +// RegValue = HAL_RUART_READ32(UartIndex, RUART_STS_REG_OFF); +// DBG_UART_INFO("UART%d SIS(0x20) = %X\n", UartIndex, RegValue); + + /** + * Clean Rx break signal interrupt status at initial stage. + */ + RegValue = HAL_RUART_READ32(UartIndex, RUART_SCRATCH_PAD_REG_OFF); + RegValue |= RUART_SP_REG_RXBREAK_INT_STATUS; + HAL_RUART_WRITE32(UartIndex, RUART_SCRATCH_PAD_REG_OFF, RegValue); + + /* Set OVSR(xfactor) */ + RegValue = HAL_RUART_READ32(UartIndex, RUART_STS_REG_OFF); + RegValue &= ~(RUART_STS_REG_XFACTOR); + RegValue |= (((RuartSpeedSetting.Ovsr - 5) << 4) & RUART_STS_REG_XFACTOR); + HAL_RUART_WRITE32(UartIndex, RUART_STS_REG_OFF, RegValue); + + /* Set OVSR_ADJ[10:0] (xfactor_adj[26:16]) */ + RegValue = HAL_RUART_READ32(UartIndex, RUART_SCRATCH_PAD_REG_OFF); + RegValue &= ~(RUART_SP_REG_XFACTOR_ADJ); + RegValue |= ((RuartSpeedSetting.Ovsr_adj << 16) & RUART_SP_REG_XFACTOR_ADJ); + HAL_RUART_WRITE32(UartIndex, RUART_SCRATCH_PAD_REG_OFF, RegValue); + +// DBG_UART_INFO(ANSI_COLOR_CYAN"---- After OVSR & OVSR_ADJ ----\n"ANSI_COLOR_RESET); +// RegValue = HAL_RUART_READ32(UartIndex, RUART_SCRATCH_PAD_REG_OFF); +// DBG_UART_INFO("UART%d SPR(0x1C) = %X\n", UartIndex, RegValue); +// RegValue = HAL_RUART_READ32(UartIndex, RUART_STS_REG_OFF); +// DBG_UART_INFO("UART%d SIS(0x20) = %X\n", UartIndex, RegValue); + + /* clear DLAB bit */ + RegValue = HAL_RUART_READ32(UartIndex, RUART_LINE_CTL_REG_OFF); + RegValue &= ~(RUART_LINE_CTL_REG_DLAB_ENABLE); + HAL_RUART_WRITE32(UartIndex, RUART_LINE_CTL_REG_OFF, RegValue); +// DBG_UART_INFO("[R] RUART_LINE_CTL_REG_OFF(0x0C) = %x\n", HAL_RUART_READ32(UartIndex, RUART_LINE_CTL_REG_OFF)); +// DBG_UART_INFO("[R] UART%d INT_EN(0x04) = %x\n", UartIndex, pHalRuartAdapter->Interrupts); + RegValue = ((pHalRuartAdapter->Interrupts) & 0xFF); + HAL_RUART_WRITE32(UartIndex, RUART_INTERRUPT_EN_REG_OFF, RegValue); +// DBG_UART_INFO("[W] UART%d INT_EN(0x04) = %x\n", UartIndex, RegValue); + + /* Configure FlowControl */ + if (pHalRuartAdapter->FlowControl == AUTOFLOW_ENABLE) { + RegValue = HAL_RUART_READ32(UartIndex, RUART_MODEM_CTL_REG_OFF); + RegValue |= RUART_MCL_AUTOFLOW_ENABLE; + HAL_RUART_WRITE32(UartIndex, RUART_MODEM_CTL_REG_OFF, RegValue); + } + + /* RUART DMA Initialization */ + HalRuartDmaInitRtl8195a(pHalRuartAdapter); + + DBG_UART_INFO("[R] UART%d LCR(0x%02X): %X\n", UartIndex, RUART_LINE_CTL_REG_OFF, HAL_RUART_READ32(UartIndex, RUART_LINE_CTL_REG_OFF)); + RegValue = HAL_RUART_READ32(UartIndex, RUART_LINE_CTL_REG_OFF); + + /* PARITY CONTROL */ + RegValue &= BIT_CLR_LCR_WLS; + RegValue |= BIT_LCR_WLS(pHalRuartAdapter->WordLen); + + RegValue &= BIT_INVC_LCR_STB_EN; + RegValue |= BIT_LCR_STB_EN(pHalRuartAdapter->StopBit); + + RegValue &= BIT_INVC_LCR_PARITY_EN; + RegValue |= BIT_LCR_PARITY_EN(pHalRuartAdapter->Parity); + + /* PARITY TYPE SELECT */ + RegValue &= BIT_INVC_LCR_PARITY_TYPE; + RegValue |= BIT_LCR_PARITY_TYPE(pHalRuartAdapter->ParityType); + + /* STICK PARITY CONTROL */ + RegValue &= BIT_INVC_LCR_STICK_PARITY_EN; + RegValue |= BIT_LCR_STICK_PARITY_EN(pHalRuartAdapter->StickParity); + + HAL_RUART_WRITE32(UartIndex, RUART_LINE_CTL_REG_OFF, RegValue); + DBG_UART_INFO("[W] UART%d LCR(0x%02X): %X\n", UartIndex, RUART_LINE_CTL_REG_OFF, HAL_RUART_READ32(UartIndex, RUART_LINE_CTL_REG_OFF)); + + /* Need to assert RTS during initial stage. */ + if (pHalRuartAdapter->FlowControl == AUTOFLOW_ENABLE) { + HalRuartRTSCtrlRtl8195a(Data, 1); + } + pHalRuartAdapter->State = HAL_UART_STATE_READY; + + return HAL_OK; +} + +#endif + +/** + * Reset RUART Tx FIFO. + * + * Reset RUART Receiver and Rx FIFO wrapper function. + * It will check LINE_STATUS_REG until reset action completion. + * + * @return BOOL + */ +HAL_Status +HalRuartResetTxFifoRtl8195a( + IN VOID *Data ///< RUART Adapter + ) +{ + PHAL_RUART_ADAPTER pHalRuartAdapter = (PHAL_RUART_ADAPTER) Data; + u8 UartIndex = pHalRuartAdapter->UartIndex; + u32 rx_trigger_lv; + u32 RegValue; + + // Backup the RX FIFO trigger Level setting + rx_trigger_lv = HAL_RUART_READ32(UartIndex, RUART_FIFO_CTL_REG_OFF); + rx_trigger_lv &= 0xC0; // only keep the bit[7:6] + + /* Step 2: Enable clear_txfifo */ + RegValue = (FIFO_CTL_DEFAULT_WITH_FIFO_DMA | RUART_FIFO_CTL_REG_CLEAR_TXFIFO) & (~0xC0); + RegValue |= rx_trigger_lv; + HAL_RUART_WRITE32(UartIndex, RUART_FIFO_CTL_REG_OFF, RegValue); + + //TODO: Check Defautl Value + RegValue = (FIFO_CTL_DEFAULT_WITH_FIFO_DMA & (~0xC0)) | rx_trigger_lv; + HAL_RUART_WRITE32(UartIndex, RUART_FIFO_CTL_REG_OFF, RegValue); + + return HAL_OK; +} + diff --git a/component/soc/realtek/8195a/fwlib/src/hal_32k.c b/component/soc/realtek/8195a/fwlib/src/hal_32k.c new file mode 100644 index 0000000..70d7a59 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/src/hal_32k.c @@ -0,0 +1,293 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + + +#include "rtl8195a.h" + +#ifdef CONFIG_TIMER_MODULE + +VOID +En32KCalibration( + VOID +) +{ + u32 Rtemp; + u32 Ttemp = 0; + + //DiagPrintf("32K clock source calibration\n"); + + //set parameter + HAL_WRITE32(SYSTEM_CTRL_BASE,REG_OSC32K_REG_CTRL0, 0); + //offset 1 = 0x1500 + Rtemp = 0x811500; + HAL_WRITE32(SYSTEM_CTRL_BASE,REG_OSC32K_REG_CTRL0, Rtemp); + HalDelayUs(40); + HAL_WRITE32(SYSTEM_CTRL_BASE,REG_OSC32K_REG_CTRL0, 0); + + //offset 2 = 0x01c0 + Rtemp = 0x8201c0; + HAL_WRITE32(SYSTEM_CTRL_BASE,REG_OSC32K_REG_CTRL0, Rtemp); + HalDelayUs(40); + HAL_WRITE32(SYSTEM_CTRL_BASE,REG_OSC32K_REG_CTRL0, 0); + + //offset 4 = 0x0100 + Rtemp = 0x840100; + HAL_WRITE32(SYSTEM_CTRL_BASE,REG_OSC32K_REG_CTRL0, Rtemp); + HalDelayUs(40); + HAL_WRITE32(SYSTEM_CTRL_BASE,REG_OSC32K_REG_CTRL0, 0); + + //offset 0 = 0xf980 + Rtemp = 0x80f980; + HAL_WRITE32(SYSTEM_CTRL_BASE,REG_OSC32K_REG_CTRL0, Rtemp); + HalDelayUs(40); + HAL_WRITE32(SYSTEM_CTRL_BASE,REG_OSC32K_REG_CTRL0, 0); + + while(1) { + //Polling LOCK + Rtemp = 0x110000; + HAL_WRITE32(SYSTEM_CTRL_BASE,REG_OSC32K_REG_CTRL0, Rtemp); + //DiagPrintf("Polling lock\n"); + HalDelayUs(40); + + Rtemp = HAL_READ32(SYSTEM_CTRL_BASE,REG_OSC32K_REG_CTRL1); + if ((Rtemp & 0x3000) != 0x0){ + //DiagPrintf("32.768 Calibration Success\n", Ttemp); + break; + } + else { + Ttemp++; + HalDelayUs(30); + //DiagPrintf("Check lock: %d\n", Ttemp); + //DiagPrintf("0x278: %x\n", Rtemp); + if (Ttemp > 100000) { /*Delay 100ms*/ + DiagPrintf("32K Calibration Fail!!\n", Ttemp); + break; + } + } + } +} + +#if CONFIG_WDG +WDG_ADAPTER WDGAdapter; +extern HAL_TIMER_OP HalTimerOp; + +#ifdef CONFIG_WDG_NORMAL +VOID +WDGInitial( + IN u32 Period +) +{ + u8 CountId; + u16 DivFactor; + u32 CountTemp; + u32 CountProcess = 0; + u32 DivFacProcess = 0; + u32 PeriodProcess = 100*Period; + u32 MinPeriodTemp = 0xFFFFFFFF; + u32 PeriodTemp = 0; + u32 *Reg = (u32*)&(WDGAdapter.Ctrl); + + DBG_8195A(" Period = 0x%08x\n", Period); + + for (CountId = 0; CountId < 12; CountId++) { + CountTemp = ((0x00000001 << (CountId+1))-1); + DivFactor = (u16)((PeriodProcess)/(CountTemp*3)); + + if (DivFactor > 0) { + PeriodTemp = 3*(DivFactor+1)*CountTemp; + if (PeriodProcess < PeriodTemp) { + if (MinPeriodTemp > PeriodTemp) { + MinPeriodTemp = PeriodTemp; + CountProcess = CountId; + DivFacProcess = DivFactor; + } + } + } + } + + DBG_8195A("WdgScalar = 0x%08x\n", DivFacProcess); + DBG_8195A("WdgCunLimit = 0x%08x\n", CountProcess); + + WDGAdapter.Ctrl.WdgScalar = DivFacProcess; + WDGAdapter.Ctrl.WdgEnByte = 0; + WDGAdapter.Ctrl.WdgClear = 1; + WDGAdapter.Ctrl.WdgCunLimit = CountProcess; + WDGAdapter.Ctrl.WdgMode = RESET_MODE; + WDGAdapter.Ctrl.WdgToISR = 0; + + HAL_WRITE32(VENDOR_REG_BASE, 0, (*Reg)); + +} + +VOID +WDGIrqHandle +( + IN VOID *Data +) +{ + u32 temp; + WDG_REG *CtrlReg; + + if (NULL != WDGAdapter.UserCallback) { + WDGAdapter.UserCallback(WDGAdapter.callback_id); + } + + // Clear ISR + temp = HAL_READ32(VENDOR_REG_BASE, 0); + CtrlReg = (WDG_REG*)&temp; + CtrlReg->WdgToISR = 1; // write 1 clear + HAL_WRITE32(VENDOR_REG_BASE, 0, (temp)); +} + +VOID +WDGIrqInitial( + VOID +) +{ + u32 *Temp = (u32*)&(WDGAdapter.Ctrl); + + WDGAdapter.IrqHandle.Data = (u32)&WDGAdapter; + WDGAdapter.IrqHandle.IrqFun = (IRQ_FUN)WDGIrqHandle; + WDGAdapter.IrqHandle.IrqNum = WDG_IRQ; + WDGAdapter.IrqHandle.Priority = 0; + + InterruptRegister(&(WDGAdapter.IrqHandle)); + InterruptEn(&(WDGAdapter.IrqHandle)); + + WDGAdapter.Ctrl.WdgToISR = 1; // clear ISR first + WDGAdapter.Ctrl.WdgMode = INT_MODE; + HAL_WRITE32(VENDOR_REG_BASE, 0, ((*Temp))); + WDGAdapter.Ctrl.WdgToISR = 0; +} + +VOID +WDGStart( + VOID +) +{ + u32 *Temp = (u32*)&(WDGAdapter.Ctrl); + WDGAdapter.Ctrl.WdgEnByte = 0xA5; + HAL_WRITE32(VENDOR_REG_BASE, 0, ((*Temp))); +} + +VOID +WDGStop( + VOID +) +{ + u32 *Temp = (u32*)&(WDGAdapter.Ctrl); + WDGAdapter.Ctrl.WdgEnByte = 0; + HAL_WRITE32(VENDOR_REG_BASE, 0, ((*Temp))); +} + +VOID +WDGRefresh( + VOID +) +{ + u32 *Temp = (u32*)&(WDGAdapter.Ctrl); + WDGAdapter.Ctrl.WdgClear = 1; + HAL_WRITE32(VENDOR_REG_BASE, 0, ((*Temp))); +} + +VOID +WDGIrqCallBackReg( + IN VOID *CallBack, + IN u32 Id +) +{ + WDGAdapter.UserCallback = (VOID (*)(u32))CallBack; + WDGAdapter.callback_id = Id; +} + +#endif + +#ifdef CONFIG_GDMA_TEST +VOID +WDGIrqHandle +( + IN VOID *Data +) +{ +} + + +VOID +WDGGtimerHandle +( + IN VOID *Data +) +{ + u32 *Temp = (u32*)&(WDGAdapter.Ctrl); + WDGAdapter.Ctrl.WdgClear = 1; + DBG_8195A("reset WDG\n"); + if (HAL_READ32(SYSTEM_CTRL_BASE,REG_SYS_DSTBY_INFO2) == 0) { + HAL_WRITE32(VENDOR_REG_BASE, 0, ((*Temp))); + } +} + + +VOID +InitWDGIRQ(VOID) +{ + u32 *Temp = (u32*)&(WDGAdapter.Ctrl); + + WDGAdapter.Ctrl.WdgScalar = 0x96; + WDGAdapter.Ctrl.WdgEnByte = 0xA5; + WDGAdapter.Ctrl.WdgClear = 1; + WDGAdapter.Ctrl.WdgCunLimit = CNTFFFH; + WDGAdapter.Ctrl.WdgMode = RESET_MODE; + WDGAdapter.Ctrl.WdgToISR = 0; + + if (WDGAdapter.Ctrl.WdgMode == INT_MODE) { + + WDGAdapter.IrqHandle.Data = NULL; + WDGAdapter.IrqHandle.IrqFun = (IRQ_FUN)WDGIrqHandle; + WDGAdapter.IrqHandle.IrqNum = WDG_IRQ; + WDGAdapter.IrqHandle.Priority = 0; + + InterruptRegister(&(WDGAdapter.IrqHandle)); + InterruptEn(&(WDGAdapter.IrqHandle)); + } + else { + + WDGAdapter.WdgGTimer.TimerIrqPriority = 0; + WDGAdapter.WdgGTimer.TimerMode = USER_DEFINED; + WDGAdapter.WdgGTimer.IrqDis = OFF; + WDGAdapter.WdgGTimer.TimerId = 2;// + WDGAdapter.WdgGTimer.IrqHandle.IrqFun = (IRQ_FUN)WDGGtimerHandle; + WDGAdapter.WdgGTimer.IrqHandle.IrqNum = TIMER2_7_IRQ; + WDGAdapter.WdgGTimer.IrqHandle.Priority = 0; + WDGAdapter.WdgGTimer.IrqHandle.Data = NULL; + + if ((WDGAdapter.Ctrl.WdgCunLimit == CNTFFFH)&&(WDGAdapter.Ctrl.WdgScalar >= 0x8429)){ + WDGAdapter.WdgGTimer.TimerLoadValueUs = 0xFFFFFFFF - WDGTIMERELY; + } + else { + WDGAdapter.WdgGTimer.TimerLoadValueUs = (BIT0 << (WDGAdapter.Ctrl.WdgCunLimit+1)) + *WDGAdapter.Ctrl.WdgScalar*TIMER_TICK_US - WDGTIMERELY; + } + + HalTimerOp.HalTimerInit((VOID*) &(WDGAdapter.WdgGTimer)); + } + //fill reg + HAL_WRITE32(VENDOR_REG_BASE, 0, ((*Temp))); +} + + +//WDG +VOID HalWdgInit( + VOID +) +{ + +} +#endif //WDG_Verify_Mode +#endif //CONFIG_WDG +#endif //#ifdef CONFIG_TIMER_MODULE diff --git a/component/soc/realtek/8195a/fwlib/src/hal_adc.c b/component/soc/realtek/8195a/fwlib/src/hal_adc.c new file mode 100644 index 0000000..1cae2f0 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/src/hal_adc.c @@ -0,0 +1,1428 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#include "basic_types.h" +#include "diag.h" +#include "rand.h" +#include "section_config.h" +#include "rtl_utility.h" +#include "osdep_api.h" +#include "hal_adc.h" +#include "hal_gdma.h" +#include "hal_timer.h" + +#define ADC_STATIC_ALLOC 0 + +static volatile u32 ADCDatBuf[2]; +static volatile u8 ADCFullStsFlag; +static RTK_STATUS +RtkADCPinMuxDeInit( + IN PSAL_ADC_HND pSalADCHND +); + +static RTK_STATUS +RtkADCIrqDeInit( + IN PSAL_ADC_HND pSalADCHND +); + +static RTK_STATUS +RtkADCDMADeInit( + IN PSAL_ADC_HND pSalADCHND +); +/* DAC SAL global variables declaration when kernel disabled */ +#ifndef CONFIG_KERNEL + SRAM_BF_DATA_SECTION + HAL_ADC_OP HalADCOpSAL; +#endif + +#if ADC0_USED /*#if ADC0_USED*/ +#if ADC_STATIC_ALLOC + SRAM_BF_DATA_SECTION + SAL_ADC_MNGT_ADPT SalADC0MngtAdpt; + + SRAM_BF_DATA_SECTION + SAL_ADC_HND_PRIV SalADC0HndPriv; + + SRAM_BF_DATA_SECTION + HAL_ADC_INIT_DAT HalADC0InitData; + + SRAM_BF_DATA_SECTION + IRQ_HANDLE ADC0IrqHandleDat; + + SRAM_BF_DATA_SECTION + HAL_GDMA_ADAPTER HalADC0GdmaAdpt; + + SRAM_BF_DATA_SECTION + HAL_GDMA_OP HalADC0GdmaOp; + + SRAM_BF_DATA_SECTION + IRQ_HANDLE ADC0GDMAIrqHandleDat; + + SRAM_BF_DATA_SECTION + SAL_ADC_USER_CB SalADC0UserCB; + + SRAM_BF_DATA_SECTION + SAL_ADC_USERCB_ADPT SalADC0UserCBAdpt[SAL_ADC_USER_CB_NUM]; +#endif +#endif /*#if ADC0_USED*/ + +#if ADC1_USED /*#if ADC1_USED*/ +#if ADC_STATIC_ALLOC + SRAM_BF_DATA_SECTION + SAL_ADC_MNGT_ADPT SalADC1MngtAdpt; + + SRAM_BF_DATA_SECTION + SAL_ADC_HND_PRIV SalADC1HndPriv; + + SRAM_BF_DATA_SECTION + HAL_ADC_INIT_DAT HalADC1InitData; + + SRAM_BF_DATA_SECTION + IRQ_HANDLE ADC1IrqHandleDat; + + SRAM_BF_DATA_SECTION + HAL_GDMA_ADAPTER HalADC1GdmaAdpt; + + SRAM_BF_DATA_SECTION + HAL_GDMA_OP HalADC1GdmaOp; + + SRAM_BF_DATA_SECTION + IRQ_HANDLE ADC1GDMAIrqHandleDat; + + SRAM_BF_DATA_SECTION + SAL_ADC_USER_CB SalADC1UserCB; + + SRAM_BF_DATA_SECTION + SAL_ADC_USERCB_ADPT SalADC1UserCBAdpt[SAL_ADC_USER_CB_NUM]; +#endif +#endif /*#if ADC1_USED*/ + +#if ADC2_USED /*#if ADC2_USED*/ +#if ADC_STATIC_ALLOC + SRAM_BF_DATA_SECTION + SAL_ADC_MNGT_ADPT SalADC2MngtAdpt; + + SRAM_BF_DATA_SECTION + SAL_ADC_HND_PRIV SalADC2HndPriv; + + SRAM_BF_DATA_SECTION + HAL_ADC_INIT_DAT HalADC2InitData; + + SRAM_BF_DATA_SECTION + IRQ_HANDLE ADC2IrqHandleDat; + + SRAM_BF_DATA_SECTION + HAL_GDMA_ADAPTER HalADC2GdmaAdpt; + + SRAM_BF_DATA_SECTION + HAL_GDMA_OP HalADC2GdmaOp; + + SRAM_BF_DATA_SECTION + IRQ_HANDLE ADC2GDMAIrqHandleDat; + + SRAM_BF_DATA_SECTION + SAL_ADC_USER_CB SalADC2UserCB; + + SRAM_BF_DATA_SECTION + SAL_ADC_USERCB_ADPT SalADC2UserCBAdpt[SAL_ADC_USER_CB_NUM]; +#endif +#endif /*#if ADC2_USED*/ + +#if ADC3_USED /*#if ADC3_USED*/ +#if ADC_STATIC_ALLOC + SRAM_BF_DATA_SECTION + SAL_ADC_MNGT_ADPT SalADC3MngtAdpt; + + SRAM_BF_DATA_SECTION + SAL_ADC_HND_PRIV SalADC3HndPriv; + + SRAM_BF_DATA_SECTION + HAL_ADC_INIT_DAT HalADC3InitData; + + SRAM_BF_DATA_SECTION + IRQ_HANDLE ADC3IrqHandleDat; + + SRAM_BF_DATA_SECTION + HAL_GDMA_ADAPTER HalADC3GdmaAdpt; + + SRAM_BF_DATA_SECTION + HAL_GDMA_OP HalADC3GdmaOp; + + SRAM_BF_DATA_SECTION + IRQ_HANDLE ADC3GDMAIrqHandleDat; + + SRAM_BF_DATA_SECTION + SAL_ADC_USER_CB SalADC3UserCB; + + SRAM_BF_DATA_SECTION + SAL_ADC_USERCB_ADPT SalADC3UserCBAdpt[SAL_ADC_USER_CB_NUM]; +#endif +#endif /*#if ADC3_USED*/ + +/* Global variables */ +u8 SalAdcInitialFlag = 0; +HAL_ADC_INIT_DAT SalAdcInitialDatKeep = {.ADCIdx = 0, + .ADCEn = 0, + .ADCEndian = 0, + .ADCBurstSz = 0, + .ADCCompOnly = 0, + .ADCOneShotEn = 0, + .ADCOverWREn = 0, + .ADCOneShotTD = 0, + .ADCCompCtrl = 0, + .ADCCompTD = 0, + .ADCDataRate = 0, + .ADCAudioEn = 0, + .ADCEnManul = 0, + .ADCDbgSel = 0, + .RSVD0 = 0, + .ADCData = (u32 *)NULL, + .ADCPWCtrl = 0, + .ADCIntrMSK = 0}; + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// RtkI2CGetMngtAdpt +// +// Description: +// According to the input index, all the memory space are allocated and all the +// related pointers are assigned. The management adapter pointer will be +// returned. +// +// Arguments: +// [in] u8 I2CIdx - +// I2C module index +// +// Return: +// PSAL_I2C_MNGT_ADPT +// +// Note: +// NA +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-04-02. +// +//--------------------------------------------------------------------------------------------------- +VOID HalADCOpInit( + IN VOID *Data +) +{ + PHAL_ADC_OP pHalAdcOp = (PHAL_ADC_OP) Data; + + pHalAdcOp->HalADCInit = HalADCInit8195a; + pHalAdcOp->HalADCDeInit = HalADCDeInit8195a; + pHalAdcOp->HalADCEnable = HalADCEnableRtl8195a; + pHalAdcOp->HalADCReceive = HalADCReceiveRtl8195a; + pHalAdcOp->HalADCIntrCtrl = HalADCIntrCtrl8195a; + pHalAdcOp->HalADCReadReg = HalADCReadRegRtl8195a; +} + +#ifndef CONFIG_MBED_ENABLED +//--------------------------------------------------------------------------------------------------- +//Function Name: +// RtkI2CGetMngtAdpt +// +// Description: +// According to the input index, all the memory space are allocated and all the +// related pointers are assigned. The management adapter pointer will be +// returned. +// +// Arguments: +// [in] u8 I2CIdx - +// I2C module index +// +// Return: +// PSAL_I2C_MNGT_ADPT +// +// Note: +// NA +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-04-02. +// +//--------------------------------------------------------------------------------------------------- +PSAL_ADC_MNGT_ADPT +RtkADCGetMngtAdpt( + IN u8 ADCIdx +){ + PSAL_ADC_MNGT_ADPT pSalADCMngtAdpt = NULL; + PSAL_ADC_USERCB_ADPT pSalADCUserCBAdpt = NULL; + + /* If the kernel is available, Memory-allocation is used. */ +#if (!ADC_STATIC_ALLOC) + pSalADCMngtAdpt = (PSAL_ADC_MNGT_ADPT)RtlZmalloc(sizeof(SAL_ADC_MNGT_ADPT)); + pSalADCMngtAdpt->pSalHndPriv = (PSAL_ADC_HND_PRIV)RtlZmalloc(sizeof(SAL_ADC_HND_PRIV)); + pSalADCMngtAdpt->pHalInitDat = (PHAL_ADC_INIT_DAT)RtlZmalloc(sizeof(HAL_ADC_INIT_DAT)); + pSalADCMngtAdpt->pHalOp = (PHAL_ADC_OP)RtlZmalloc(sizeof(HAL_ADC_OP)); + pSalADCMngtAdpt->pIrqHnd = (PIRQ_HANDLE)RtlZmalloc(sizeof(IRQ_HANDLE)); + pSalADCMngtAdpt->pUserCB = (PSAL_ADC_USER_CB)RtlZmalloc(sizeof(SAL_ADC_USER_CB)); + pSalADCMngtAdpt->pHalGdmaAdp = (PHAL_GDMA_ADAPTER)RtlZmalloc(sizeof(HAL_GDMA_ADAPTER)); + pSalADCMngtAdpt->pHalGdmaOp = (PHAL_GDMA_OP)RtlZmalloc(sizeof(HAL_GDMA_OP)); + pSalADCMngtAdpt->pIrqGdmaHnd = (PIRQ_HANDLE)RtlZmalloc(sizeof(IRQ_HANDLE)); + pSalADCUserCBAdpt = (PSAL_ADC_USERCB_ADPT)RtlZmalloc((sizeof(SAL_ADC_USERCB_ADPT)*SAL_ADC_USER_CB_NUM)); +#else + switch (ADCIdx){ + case ADC0_SEL: + { + pSalADCMngtAdpt = &SalADC0MngtAdpt; + pSalADCMngtAdpt->pSalHndPriv = &SalADC0HndPriv; + pSalADCMngtAdpt->pHalInitDat = &HalADC0InitData; + pSalADCMngtAdpt->pHalOp = &HalADCOpSAL; + pSalADCMngtAdpt->pIrqHnd = &ADC0IrqHandleDat; + pSalADCMngtAdpt->pHalGdmaAdp = &HalADC0GdmaAdpt; + pSalADCMngtAdpt->pHalGdmaOp = &HalADC0GdmaOp; + pSalADCMngtAdpt->pIrqGdmaHnd = &ADC0GDMAIrqHandleDat; + pSalADCMngtAdpt->pUserCB = &SalADC0UserCB; + pSalADCUserCBAdpt = &SalADC0UserCBAdpt; + break; + } + + case ADC1_SEL: + { + pSalADCMngtAdpt = &SalADC1MngtAdpt; + pSalADCMngtAdpt->pSalHndPriv = &SalADC1HndPriv; + pSalADCMngtAdpt->pHalInitDat = &HalADC1InitData; + pSalADCMngtAdpt->pHalOp = &HalADCOpSAL; + pSalADCMngtAdpt->pIrqHnd = &ADC1IrqHandleDat; + pSalADCMngtAdpt->pHalGdmaAdp = &HalADC1GdmaAdpt; + pSalADCMngtAdpt->pHalGdmaOp = &HalADC1GdmaOp; + pSalADCMngtAdpt->pIrqGdmaHnd = &ADC1GDMAIrqHandleDat; + pSalADCMngtAdpt->pUserCB = &SalADC1UserCB; + pSalADCUserCBAdpt = &SalADC1UserCBAdpt; + break; + } + + case ADC2_SEL: + { + pSalADCMngtAdpt = &SalADC2MngtAdpt; + pSalADCMngtAdpt->pSalHndPriv = &SalADC2HndPriv; + pSalADCMngtAdpt->pHalInitDat = &HalADC2InitData; + pSalADCMngtAdpt->pHalOp = &HalADCOpSAL; + pSalADCMngtAdpt->pIrqHnd = &ADC2IrqHandleDat; + pSalADCMngtAdpt->pHalGdmaAdp = &HalADC2GdmaAdpt; + pSalADCMngtAdpt->pHalGdmaOp = &HalADC2GdmaOp; + pSalADCMngtAdpt->pIrqGdmaHnd = &ADC2GDMAIrqHandleDat; + pSalADCMngtAdpt->pUserCB = &SalADC2UserCB; + pSalADCUserCBAdpt = &SalADC2UserCBAdpt; + break; + } + + case ADC3_SEL: + { + pSalADCMngtAdpt = &SalADC3MngtAdpt; + pSalADCMngtAdpt->pSalHndPriv = &SalADC3HndPriv; + pSalADCMngtAdpt->pHalInitDat = &HalADC3InitData; + pSalADCMngtAdpt->pHalOp = &HalADCOpSAL; + pSalADCMngtAdpt->pIrqHnd = &ADC3IrqHandleDat; + pSalADCMngtAdpt->pHalGdmaAdp = &HalADC3GdmaAdpt; + pSalADCMngtAdpt->pHalGdmaOp = &HalADC3GdmaOp; + pSalADCMngtAdpt->pIrqGdmaHnd = &ADC3GDMAIrqHandleDat; + pSalADCMngtAdpt->pUserCB = &SalADC3UserCB; + pSalADCUserCBAdpt = &SalADC3UserCBAdpt; + break; + } + default + break; + } +#endif + + /*To assign user callback pointers*/ + pSalADCMngtAdpt->pUserCB->pTXCB = pSalADCUserCBAdpt; + pSalADCMngtAdpt->pUserCB->pTXCCB = (pSalADCUserCBAdpt+1); + pSalADCMngtAdpt->pUserCB->pRXCB = (pSalADCUserCBAdpt+2); + pSalADCMngtAdpt->pUserCB->pRXCCB = (pSalADCUserCBAdpt+3); + pSalADCMngtAdpt->pUserCB->pRDREQCB = (pSalADCUserCBAdpt+4); + pSalADCMngtAdpt->pUserCB->pERRCB = (pSalADCUserCBAdpt+5); + pSalADCMngtAdpt->pUserCB->pDMATXCB = (pSalADCUserCBAdpt+6); + pSalADCMngtAdpt->pUserCB->pDMATXCCB = (pSalADCUserCBAdpt+7); + pSalADCMngtAdpt->pUserCB->pDMARXCB = (pSalADCUserCBAdpt+8); + pSalADCMngtAdpt->pUserCB->pDMARXCCB = (pSalADCUserCBAdpt+9); + + /*To assign the rest pointers*/ + pSalADCMngtAdpt->pSalHndPriv->ppSalADCHnd = (void**)&(pSalADCMngtAdpt->pSalHndPriv); + + /* To assign the default (ROM) HAL OP initialization function */ + pSalADCMngtAdpt->pHalOpInit = &HalADCOpInit; + + /* To assign the default (ROM) HAL GDMA OP initialization function */ + pSalADCMngtAdpt->pHalGdmaOpInit = &HalGdmaOpInit; + + /* To assign the default (ROM) SAL interrupt function */ + pSalADCMngtAdpt->pSalIrqFunc = &ADCISRHandle; + + /* To assign the default (ROM) SAL DMA TX interrupt function */ + pSalADCMngtAdpt->pSalDMAIrqFunc = &ADCGDMAISRHandle; + + return pSalADCMngtAdpt; +} + + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// RtkI2CFreeMngtAdpt +// +// Description: +// Free all the previous allocated memory space. +// +// Arguments: +// [in] PSAL_I2C_MNGT_ADPT pSalI2CMngtAdpt - +// I2C SAL management adapter pointer +// +// +// Return: +// The status of the enable process. +// _EXIT_SUCCESS if the RtkI2CFreeMngtAdpt succeeded. +// _EXIT_FAILURE if the RtkI2CFreeMngtAdpt failed. +// +// Note: +// NA +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-04-02. +// +//--------------------------------------------------------------------------------------------------- +RTK_STATUS +RtkADCFreeMngtAdpt( + IN PSAL_ADC_MNGT_ADPT pSalADCMngtAdpt +){ +#ifdef CONFIG_KERNEL + RtlMfree((u8 *)pSalADCMngtAdpt->pUserCB->pTXCB, (sizeof(SAL_ADC_USERCB_ADPT)*SAL_ADC_USER_CB_NUM)); + RtlMfree((u8 *)pSalADCMngtAdpt->pIrqGdmaHnd, sizeof(IRQ_HANDLE)); + RtlMfree((u8 *)pSalADCMngtAdpt->pHalGdmaOp, sizeof(HAL_GDMA_OP)); + RtlMfree((u8 *)pSalADCMngtAdpt->pHalGdmaAdp, sizeof(HAL_GDMA_ADAPTER)); + RtlMfree((u8 *)pSalADCMngtAdpt->pUserCB, sizeof(SAL_ADC_USER_CB)); + RtlMfree((u8 *)pSalADCMngtAdpt->pIrqHnd, sizeof(IRQ_HANDLE)); + RtlMfree((u8 *)pSalADCMngtAdpt->pHalOp, sizeof(HAL_ADC_OP)); + RtlMfree((u8 *)pSalADCMngtAdpt->pHalInitDat, sizeof(HAL_ADC_INIT_DAT)); + RtlMfree((u8 *)pSalADCMngtAdpt->pSalHndPriv, sizeof(SAL_ADC_HND_PRIV)); + RtlMfree((u8 *)pSalADCMngtAdpt, sizeof(SAL_ADC_MNGT_ADPT)); +#else + ; +#endif + + return _EXIT_SUCCESS; +} +#endif + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// I2CISRHandle +// +// Description: +// I2C Interrupt Service Routine. +// According to the input pointer to SAL_I2C_HND, all the rest pointers will be +// found and be used to the rest part of this servie routine. +// The following types of interrupt will be taken care: +// - General Call (providing General Call Callback). Slave receives a general call. +// - STOP Bit (NOT providing General Call Callback) +// - START Bit (NOTproviding General Call Callback) +// - I2C Activity (NOTproviding General Call Callback) +// - RX Done (providing Error Callback). The slave transmitter does NOT +// receive a proper NACK for the end of whole transfer. +// - TX Abort (providing Error Call Callback). The Master/Slave +// transmitting is terminated. +// - RD Req (providing TX and TXC Callback). Slave gets a Read Request +// and starts a slave-transmitter operation. The slave transmit +// data will be written into slave TX FIFO from user data buffer. +// - TX Empty (providing TX and TXC Callback). Master TX FIFO is empty. +// The user transmit data will be written into master TX FIFO +// from user data buffer. +// - TX Over (providing Error Callback). Master TX FIFO is Overflow. +// - RX Full (providing RX and RXC Callback). Master/Slave RX FIFO contains +// data. And the received data will be put into Master/Slave user +// receive data buffer. +// - RX Over (providing Error Callback). Master/Slave RX FIFO is Overflow. +// - RX Under (providing Error Callback). Master/Slave RX FIFO is Underflow. +// +// Arguments: +// [in] VOID *Data - +// I2C SAL handle +// +// Return: +// NA +// +// Note: +// NA +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-04-02. +// +//---------------------------------------------------------------------------------------------------- +VOID +ADCISRHandle( + IN VOID *Data +){ +#ifdef CONFIG_DEBUG_LOG_ADC_HAL + PSAL_ADC_HND pSalADCHND = (PSAL_ADC_HND) Data; + PSAL_ADC_HND_PRIV pSalADCHNDPriv = NULL; + PSAL_ADC_MNGT_ADPT pSalADCMngtAdpt = NULL; + PHAL_ADC_INIT_DAT pHalADCInitDat = NULL; + PHAL_ADC_OP pHalADCOP = NULL; + PSAL_ADC_USER_CB pSalADCUserCB = NULL; + u8 ADCIrqIdx; + + /* To get the SAL_I2C_MNGT_ADPT pointer, and parse the rest pointers */ + pSalADCHNDPriv = CONTAINER_OF(pSalADCHND, SAL_ADC_HND_PRIV, SalADCHndPriv); + pSalADCMngtAdpt = CONTAINER_OF(pSalADCHNDPriv->ppSalADCHnd, SAL_ADC_MNGT_ADPT, pSalHndPriv); + pHalADCInitDat = pSalADCMngtAdpt->pHalInitDat; + pHalADCOP = pSalADCMngtAdpt->pHalOp; + ADCIrqIdx = pHalADCInitDat->ADCIdx; + pSalADCUserCB = pSalADCHND->pUserCB; + + DBG_8195A_ADC_LVL(HAL_ADC_LVL,"ADC INTR STS:%x\n",pHalADCOP->HalADCReadReg(pHalADCInitDat, REG_ADC_INTR_STS)); +#else + PSAL_ADC_HND pSalADCHND = (PSAL_ADC_HND) Data; + PSAL_ADC_HND_PRIV pSalADCHNDPriv = NULL; + PSAL_ADC_MNGT_ADPT pSalADCMngtAdpt = NULL; + PHAL_ADC_INIT_DAT pHalADCInitDat = NULL; + PHAL_ADC_OP pHalADCOP = NULL; + PSAL_ADC_USER_CB pSalADCUserCB = NULL; + u8 ADCIrqIdx; + u32 ADCTemp; + + /* To get the SAL_I2C_MNGT_ADPT pointer, and parse the rest pointers */ + pSalADCHNDPriv = CONTAINER_OF(pSalADCHND, SAL_ADC_HND_PRIV, SalADCHndPriv); + pSalADCMngtAdpt = CONTAINER_OF(pSalADCHNDPriv->ppSalADCHnd, SAL_ADC_MNGT_ADPT, pSalHndPriv); + pHalADCInitDat = pSalADCMngtAdpt->pHalInitDat; + pHalADCOP = pSalADCMngtAdpt->pHalOp; + ADCIrqIdx = pHalADCInitDat->ADCIdx; + pSalADCUserCB = pSalADCHND->pUserCB; + + if (pSalADCHND->OpType == ADC_RDREG_TYPE){ + ADCFullStsFlag = 1; + ADCDatBuf[0] = (u32)HAL_ADC_READ32(REG_ADC_FIFO_READ); + ADCDatBuf[1] = (u32)HAL_ADC_READ32(REG_ADC_FIFO_READ); + pSalADCHND->pInitDat->ADCIntrMSK = 0; + pHalADCOP->HalADCIntrCtrl(pSalADCHND->pInitDat); + } + else + pHalADCOP->HalADCReadReg(pHalADCInitDat, REG_ADC_INTR_STS); + +#endif +} + +VOID +ADCGDMAISRHandle( + IN VOID *Data +){ + + /* DBG_ENTRANCE; */ + PSAL_ADC_HND pSalADCHND = (PSAL_ADC_HND) Data; + PSAL_ADC_HND_PRIV pSalADCHNDPriv = NULL; + PSAL_ADC_MNGT_ADPT pSalADCMngtAdpt = NULL; + PHAL_ADC_INIT_DAT pHalADCInitDat = NULL; + PHAL_ADC_OP pHalADCOP = NULL; + PSAL_ADC_USER_CB pSalADCUserCB = NULL; + + PHAL_GDMA_ADAPTER pHalADCGdmaAdapter; + PHAL_GDMA_OP pHalADCGdmaOp; + + u8 ADCIrqIdx; + u8 IsrTypeMap = 0; + + /* To get the SAL_I2C_MNGT_ADPT pointer, and parse the rest pointers */ + pSalADCHNDPriv = CONTAINER_OF(pSalADCHND, SAL_ADC_HND_PRIV, SalADCHndPriv); + pSalADCMngtAdpt = CONTAINER_OF(pSalADCHNDPriv->ppSalADCHnd, SAL_ADC_MNGT_ADPT, pSalHndPriv); + pHalADCInitDat = pSalADCMngtAdpt->pHalInitDat; + pHalADCOP = pSalADCMngtAdpt->pHalOp; + ADCIrqIdx = pHalADCInitDat->ADCIdx; + pSalADCUserCB = pSalADCHND->pUserCB; + + pHalADCGdmaAdapter = pSalADCMngtAdpt->pHalGdmaAdp; + pHalADCGdmaOp = pSalADCMngtAdpt->pHalGdmaOp; + + DBG_8195A_ADC_LVL(HAL_ADC_LVL,"%s\n",__func__); + + if ((pHalADCGdmaAdapter->MaxMuliBlock) == pHalADCGdmaAdapter->MuliBlockCunt+1) { + pSalADCHND->pInitDat->ADCIntrMSK = 0; + pHalADCOP->HalADCIntrCtrl(pSalADCHND->pInitDat); + + /* Clear ADC Status */ + HAL_ADC_READ32(REG_ADC_INTR_STS); + + pSalADCHND->pInitDat->ADCEn = ADC_DISABLE; + pHalADCOP->HalADCEnable(pSalADCHND->pInitDat); + pHalADCGdmaOp->HalGdmaChCleanAutoSrc(pHalADCGdmaAdapter); + pHalADCGdmaOp->HalGdmaChDis(pHalADCGdmaAdapter); + pSalADCHND->DevSts = ADC_STS_IDLE; + + if (pSalADCUserCB->pDMARXCCB->USERCB != NULL) { + pSalADCUserCB->pDMARXCCB->USERCB((VOID*)pSalADCUserCB->pDMARXCCB->USERData); + } + } + + //3 Clear Pending ISR + IsrTypeMap = pHalADCGdmaOp->HalGdmaChIsrClean((VOID*)pHalADCGdmaAdapter); + + //3 Maintain Block Count + if (IsrTypeMap & BlockType) { + pHalADCGdmaAdapter->MuliBlockCunt++; + } +} + +static RTK_STATUS +RtkADCPinMuxInit( + IN PSAL_ADC_HND pSalADCHND +){ + + u32 ADCLocalTemp; + + /* Check the I2C index first */ + if (RtkADCIdxChk(pSalADCHND->DevNum)) + return _EXIT_FAILURE; + + ADCLocalTemp = HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_SYSPLL_CTRL2); + ADCLocalTemp |= BIT25; + + /* To release DAC delta sigma clock gating */ + HAL_WRITE32(SYSTEM_CTRL_BASE,REG_SYS_SYSPLL_CTRL2,ADCLocalTemp); + + /* Turn on DAC active clock */ + ACTCK_ADC_CCTRL(ON); + + /* Enable DAC0 module */ + ADC0_FCTRL(ON); + + return _EXIT_SUCCESS; + +} + +static RTK_STATUS +RtkADCPinMuxDeInit( + IN PSAL_ADC_HND pSalADCHND +){ + + u32 ADCLocalTemp; + + /* Check the I2C index first */ + if (RtkADCIdxChk(pSalADCHND->DevNum)) + return _EXIT_FAILURE; + + /* Turn on DAC active clock */ + ACTCK_ADC_CCTRL(OFF); + + /* Enable DAC1 module */ + ADC0_FCTRL(OFF); + + ADCLocalTemp = HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_SYSPLL_CTRL2); + ADCLocalTemp &= (~BIT25); + + /* To release DAC delta sigma clock gating */ + HAL_WRITE32(SYSTEM_CTRL_BASE,REG_SYS_SYSPLL_CTRL2,ADCLocalTemp); + return _EXIT_SUCCESS; +} + + +#if ADC_INTR_OP_TYPE +//--------------------------------------------------------------------------------------------------- +//Function Name: +// RtkI2CIrqInit +// +// Description: +// I2C interrupt initialization function. +// For I2C interrupt operation mode, I2C module MUST register itself to the platform +// by providing the interrupt handler which contains interrupt input data (arguments), +// interrupt service routine, interrupt number, interrupt priority. And then the interrupt +// should be enabled. +// +// Arguments: +// [in] VOID *Data - +// I2C SAL handle +// +// Return: +// The status of the I2C interrupt initialization process. +// _EXIT_SUCCESS if the RtkI2CIrqInit succeeded. +// _EXIT_FAILURE if the RtkI2CIrqInit failed. +// +// Note: +// NA +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-04-03. +// +//---------------------------------------------------------------------------------------------------- +static RTK_STATUS +RtkADCIrqInit( + IN PSAL_ADC_HND pSalADCHND +){ + + PSAL_ADC_HND_PRIV pSalADCHNDPriv = NULL; + PSAL_ADC_MNGT_ADPT pSalADCMngtAdpt = NULL; + PIRQ_HANDLE pIrqHandle = NULL; + + /* To Get the SAL_I2C_MNGT_ADPT Pointer */ + pSalADCHNDPriv = CONTAINER_OF(pSalADCHND, SAL_ADC_HND_PRIV, SalADCHndPriv); + pSalADCMngtAdpt = CONTAINER_OF(pSalADCHNDPriv->ppSalADCHnd, SAL_ADC_MNGT_ADPT, pSalHndPriv); + pIrqHandle = pSalADCMngtAdpt->pIrqHnd; +/* + if (RtkADCIdxChk(pSalADCHND->DevNum)) + return _EXIT_FAILURE; +*/ + + pIrqHandle->Data = (u32)(pSalADCHND); + pIrqHandle->IrqNum = ADC_IRQ; + pIrqHandle->IrqFun = (IRQ_FUN)pSalADCMngtAdpt->pSalIrqFunc; + pIrqHandle->Priority = 5; + InterruptRegister(pIrqHandle); + InterruptEn(pIrqHandle); + + return _EXIT_SUCCESS; +} + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// RtkI2CIrqDeInit +// +// Description: +// I2C interrupt de-initialization function. +// According to the given I2C device number, the I2C interrupt will be unreigster +// from the platform and the relative interrupt handler will be cleared. +// +// Arguments: +// [in] VOID *Data - +// I2C SAL handle +// +// Return: +// The status of the I2C interrupt de-initialization process. +// _EXIT_SUCCESS if the RtkI2CIrqDeInit succeeded. +// _EXIT_FAILURE if the RtkI2CIrqDeInit failed. +// +// Note: +// NA +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-04-03. +// +//---------------------------------------------------------------------------------------------------- +static RTK_STATUS +RtkADCIrqDeInit( + IN PSAL_ADC_HND pSalADCHND +){ + + PSAL_ADC_HND_PRIV pSalADCHNDPriv = NULL; + PSAL_ADC_MNGT_ADPT pSalADCMngtAdpt = NULL; + PIRQ_HANDLE pIrqHandle = NULL; + + /* To Get the SAL_I2C_MNGT_ADPT Pointer */ + pSalADCHNDPriv = CONTAINER_OF(pSalADCHND, SAL_ADC_HND_PRIV, SalADCHndPriv); + pSalADCMngtAdpt = CONTAINER_OF(pSalADCHNDPriv->ppSalADCHnd, SAL_ADC_MNGT_ADPT, pSalHndPriv); + pIrqHandle = pSalADCMngtAdpt->pIrqHnd; +/* + if (RtkADCIdxChk(pSalADCHND->DevNum)) + return _EXIT_FAILURE; +*/ + InterruptUnRegister(pIrqHandle); + return _EXIT_SUCCESS; + +} + +#endif + + +#if ADC_DMA_OP_TYPE +//--------------------------------------------------------------------------------------------------- +//Function Name: +// RtkI2CIrqInit +// +// Description: +// I2C interrupt initialization function. +// For I2C interrupt operation mode, I2C module MUST register itself to the platform +// by providing the interrupt handler which contains interrupt input data (arguments), +// interrupt service routine, interrupt number, interrupt priority. And then the interrupt +// should be enabled. +// +// Arguments: +// [in] VOID *Data - +// I2C SAL handle +// +// Return: +// The status of the I2C interrupt initialization process. +// _EXIT_SUCCESS if the RtkI2CIrqInit succeeded. +// _EXIT_FAILURE if the RtkI2CIrqInit failed. +// +// Note: +// NA +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-04-03. +// +//---------------------------------------------------------------------------------------------------- +static RTK_STATUS +RtkADCDMAInit( + IN PSAL_ADC_HND pSalADCHND +){ + PSAL_ADC_HND_PRIV pSalADCHNDPriv = NULL; + PSAL_ADC_MNGT_ADPT pSalADCMngtAdpt = NULL; + PHAL_GDMA_ADAPTER pHALADCGdmaAdpt = NULL; + PHAL_GDMA_OP pHALADCGdmaOp = NULL; + PIRQ_HANDLE pIrqHandleADCGdma = NULL; + + /* To Get the SAL_I2C_MNGT_ADPT Pointer */ + pSalADCHNDPriv = CONTAINER_OF(pSalADCHND, SAL_ADC_HND_PRIV, SalADCHndPriv); + pSalADCMngtAdpt = CONTAINER_OF(pSalADCHNDPriv->ppSalADCHnd, SAL_ADC_MNGT_ADPT, pSalHndPriv); + + pHALADCGdmaAdpt = pSalADCMngtAdpt->pHalGdmaAdp; + pHALADCGdmaOp = pSalADCMngtAdpt->pHalGdmaOp; + pIrqHandleADCGdma = pSalADCMngtAdpt->pIrqGdmaHnd; +/* + if (RtkADCIdxChk(pSalADCHND->DevNum)) + return _EXIT_FAILURE; +*/ + //HalGdmaOpInit(pHALADCGdmaOp); + pSalADCMngtAdpt->pHalGdmaOpInit(pHALADCGdmaOp); + _memset((void *)pHALADCGdmaAdpt, 0, sizeof(HAL_GDMA_ADAPTER)); + + pHALADCGdmaAdpt->GdmaCtl.IntEn = 1; + + //ADC RX DMA + pHALADCGdmaAdpt->GdmaCtl.SrcTrWidth = TrWidthFourBytes; + pHALADCGdmaAdpt->GdmaCtl.DstTrWidth = TrWidthFourBytes; + pHALADCGdmaAdpt->GdmaCtl.SrcMsize = MsizeEight; + pHALADCGdmaAdpt->GdmaCtl.DestMsize = MsizeEight; + + pHALADCGdmaAdpt->GdmaCtl.Sinc = NoChange; + pHALADCGdmaAdpt->GdmaCtl.Dinc = IncType; + + pHALADCGdmaAdpt->GdmaCtl.Done = 1; + pHALADCGdmaAdpt->GdmaCtl.TtFc = (GDMA_CTL_TT_FC_TYPE)0x2; + + pHALADCGdmaAdpt->GdmaCfg.SrcPer = 12; + pHALADCGdmaAdpt->GdmaCfg.ReloadSrc = 1; + + pHALADCGdmaAdpt->MuliBlockCunt = 0; + pHALADCGdmaAdpt->MaxMuliBlock = 1;//MaxLlp; + + pHALADCGdmaAdpt->GdmaIsrType = (BlockType|TransferType|ErrType); + pHALADCGdmaAdpt->IsrCtrl = ENABLE; + pHALADCGdmaAdpt->GdmaOnOff = ON; + + pHALADCGdmaAdpt->ChNum = 4; + pHALADCGdmaAdpt->ChEn = GdmaCh4; + + pHALADCGdmaAdpt->TestItem = 3; + DBG_ADC_INFO("pSalADCHND->DevNum:%x\n",pSalADCHND->DevNum); + + pHALADCGdmaAdpt->GdmaIndex = 1; + pIrqHandleADCGdma->IrqNum = GDMA1_CHANNEL4_IRQ; + + /* GDMA interrupt register */ + pIrqHandleADCGdma->Data = (u32) (pSalADCHND); + pIrqHandleADCGdma->IrqFun = (IRQ_FUN) pSalADCMngtAdpt->pSalDMAIrqFunc; + pIrqHandleADCGdma->Priority = 2; + InterruptRegister(pIrqHandleADCGdma); + InterruptEn(pIrqHandleADCGdma); + + /* GDMA initialization */ + /* Enable the whole GDMA module first */ + if (pHALADCGdmaAdpt->GdmaIndex == 0) { + ACTCK_GDMA0_CCTRL(ON); + SLPCK_GDMA0_CCTRL(ON); + GDMA0_FCTRL(ON); + } + else { + ACTCK_GDMA1_CCTRL(ON); + SLPCK_GDMA1_CCTRL(ON); + GDMA1_FCTRL(ON); + } + + pHALADCGdmaOp->HalGdmaOnOff((VOID*)pHALADCGdmaAdpt); + pHALADCGdmaOp->HalGdmaChIsrEnAndDis((VOID*)pHALADCGdmaAdpt); + //pHALADCGdmaOp->HalGdmaChSeting((VOID*)pHALADCGdmaAdpt); + + return _EXIT_SUCCESS; +} + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// RtkI2CIrqDeInit +// +// Description: +// I2C interrupt de-initialization function. +// According to the given I2C device number, the I2C interrupt will be unreigster +// from the platform and the relative interrupt handler will be cleared. +// +// Arguments: +// [in] VOID *Data - +// I2C SAL handle +// +// Return: +// The status of the I2C interrupt de-initialization process. +// _EXIT_SUCCESS if the RtkI2CIrqDeInit succeeded. +// _EXIT_FAILURE if the RtkI2CIrqDeInit failed. +// +// Note: +// NA +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-04-03. +// +//---------------------------------------------------------------------------------------------------- +static RTK_STATUS +RtkADCDMADeInit( + IN PSAL_ADC_HND pSalADCHND +){ + PSAL_ADC_HND_PRIV pSalADCHNDPriv = NULL; + PSAL_ADC_MNGT_ADPT pSalADCMngtAdpt = NULL; + + PHAL_GDMA_ADAPTER pHALADCGdmaAdpt = NULL; + PHAL_GDMA_OP pHALADCGdmaOp = NULL; + PIRQ_HANDLE pIrqHandleADCGdma = NULL; + + /*To Get the SAL_I2C_MNGT_ADPT Pointer*/ + pSalADCHNDPriv = CONTAINER_OF(pSalADCHND, SAL_ADC_HND_PRIV, SalADCHndPriv); + pSalADCMngtAdpt = CONTAINER_OF(pSalADCHNDPriv->ppSalADCHnd, SAL_ADC_MNGT_ADPT, pSalHndPriv); + + pHALADCGdmaAdpt = pSalADCMngtAdpt->pHalGdmaAdp; + pHALADCGdmaOp = pSalADCMngtAdpt->pHalGdmaOp; + pIrqHandleADCGdma = pSalADCMngtAdpt->pIrqGdmaHnd; + + if (RtkADCIdxChk(pSalADCHND->DevNum)) + return _EXIT_FAILURE; + + //HalGdmaOpInit(pHALADCGdmaOp); + pSalADCMngtAdpt->pHalGdmaOpInit(pHALADCGdmaOp); + + pHALADCGdmaAdpt->IsrCtrl = DISABLE; + pHALADCGdmaOp->HalGdmaChIsrEnAndDis((VOID*)pHALADCGdmaAdpt); + pHALADCGdmaOp->HalGdmaChIsrClean((VOID*)pHALADCGdmaAdpt); + pHALADCGdmaOp->HalGdmaChDis((VOID*)pHALADCGdmaAdpt); + + InterruptUnRegister(pIrqHandleADCGdma); +#if 0 + _memset((void *)pIrqHandleDACGdma , 0, sizeof(IRQ_HANDLE)); + _memset((void *)pHALDACGdmaOp , 0, sizeof(HAL_GDMA_OP)); + _memset((void *)pHALDACGdmaAdpt , 0, sizeof(HAL_GDMA_ADAPTER)); +#endif + return _EXIT_SUCCESS; + +} +#endif + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// RtkI2CInit +// +// Description: +// According to the given I2C index, the related SAL_I2C_MNGT_ADPT pointer used +// for retrieving each I2C data sturcture pointer will be reversely parsed first. +// Then, initializing I2C HAL operation, initializing I2C interrupt (if needed), +// initializing I2C DMA (if needed) and initializing I2C pinmux will be done. +// User specified I2C configuration will be assigned to I2C initial data structure +// (PHAL_I2C_INIT_DAT pHalI2CInitDat). I2C HAL initialization is executed after +// all the configuration data taken. +// In the end, I2C module is enabled as a final step of the whole initialization. +// For a slave ack General Call support, an additional step may be followed after +// the above steps. +// +// Arguments: +// [in] VOID *Data - +// I2C SAL handle +// +// Return: +// The status of the I2C initialization process. +// _EXIT_SUCCESS if the RtkI2CInit succeeded. +// _EXIT_FAILURE if the RtkI2CInit failed. +// +// Note: +// NA +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-04-03. +// +//---------------------------------------------------------------------------------------------------- +RTK_STATUS +RtkADCInit( + IN VOID *Data +){ + PSAL_ADC_HND pSalADCHND = (PSAL_ADC_HND) Data; + PSAL_ADC_HND_PRIV pSalADCHNDPriv = NULL; + PSAL_ADC_MNGT_ADPT pSalADCMngtAdpt = NULL; + PHAL_ADC_INIT_DAT pHalADCInitDat = NULL; + PHAL_ADC_OP pHalADCOP = NULL; + + DBG_ADC_INFO("%s\n",__func__); + /* To Get the SAL_ADC_MNGT_ADPT Pointer */ + pSalADCHNDPriv = CONTAINER_OF(pSalADCHND, SAL_ADC_HND_PRIV, SalADCHndPriv); + pSalADCMngtAdpt = CONTAINER_OF(pSalADCHNDPriv->ppSalADCHnd, SAL_ADC_MNGT_ADPT, pSalHndPriv); + + pHalADCInitDat = pSalADCMngtAdpt->pHalInitDat; + pHalADCOP = pSalADCMngtAdpt->pHalOp; + + /* Check the input I2C index first */ + if (RtkADCIdxChk(pSalADCHND->DevNum)) + return _EXIT_FAILURE; + +#if 0 + /* Check the input I2C operation type */ + if (RtkI2COpTypeChk(pSalI2CHND)) + return _EXIT_FAILURE; +#endif + + /* ADC Initial data check, if the setting is different from the previous initial data, + an warning is shown on Log-Uart and directly return from this function */ + if (SalAdcInitialFlag != 0) { + if (_memcmp(pHalADCInitDat, &SalAdcInitialDatKeep, sizeof(HAL_ADC_INIT_DAT))) { + pSalADCMngtAdpt->pHalOpInit(pHalADCOP); + /* DAC Device Status Update */ + pSalADCHND->DevSts = ADC_STS_IDLE; + DBG_8195A("The DAC initial value is different from the previous value.\n"); + } + } + else { + /* ADC Initialize HAL Operations */ + //HalADCOpInit(pHalADCOP); + pSalADCMngtAdpt->pHalOpInit(pHalADCOP); + + /* ADC Interrupt Initialization */ +#if ADC_INTR_OP_TYPE + RtkADCIrqInit(pSalADCHND); +#endif + + /* ADC DMA Initialization */ +#if ADC_DMA_OP_TYPE + RtkADCDMAInit(pSalADCHND); +#endif + + /* ADC Function and Clock Enable*/ + RtkADCPinMuxInit(pSalADCHND); + pHalADCOP->HalADCInit(pSalADCHND->pInitDat); + + if (pSalADCHND->OpType == ADC_DMA_TYPE){ + pSalADCHND->pInitDat->ADCIntrMSK = (BIT_ADC_FIFO_RD_REQ_EN | + BIT_ADC_FIFO_RD_ERROR_EN); + } + else if (pSalADCHND->OpType == ADC_INTR_TYPE){ + pSalADCHND->pInitDat->ADCIntrMSK = (BIT_ADC_FIFO_FULL_EN | + BIT_ADC_FIFO_RD_REQ_EN | + BIT_ADC_FIFO_RD_ERROR_EN); + } + else{ + pSalADCHND->pInitDat->ADCIntrMSK = 0; + } + + + if (pHalADCInitDat->ADCOneShotEn == ADC_FEATURE_ENABLED) { + pSalADCHND->pInitDat->ADCIntrMSK |= BIT_ADC_AWAKE_CPU_EN; + } + pHalADCOP->HalADCIntrCtrl(pSalADCHND->pInitDat); + + //pSalADCHND->pInitDat->ADCEn = ADC_ENABLE; + //pHalADCOP->HalADCEnable(pSalADCHND->pInitDat); + + if (pHalADCInitDat->ADCOneShotEn == ADC_FEATURE_ENABLED) { + HAL_TIMER_WRITE32(TIMER_INTERVAL, 30); + HAL_TIMER_WRITE32(0x1C, 3); + } + + SalAdcInitialFlag |= (0x01 << pSalADCHND->DevNum); + _memcpy(&SalAdcInitialDatKeep, pSalADCHND->pInitDat, sizeof(HAL_ADC_INIT_DAT)); + } + + /* DAC Device Status Update */ + pSalADCHND->DevSts = ADC_STS_IDLE; + return _EXIT_SUCCESS; +} + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// RtkI2CInit +// +// Description: +// According to the given I2C index, the related SAL_I2C_MNGT_ADPT pointer used +// for retrieving each I2C data sturcture pointer will be reversely parsed first. +// Then, initializing I2C HAL operation, initializing I2C interrupt (if needed), +// initializing I2C DMA (if needed) and initializing I2C pinmux will be done. +// User specified I2C configuration will be assigned to I2C initial data structure +// (PHAL_I2C_INIT_DAT pHalI2CInitDat). I2C HAL initialization is executed after +// all the configuration data taken. +// In the end, I2C module is enabled as a final step of the whole initialization. +// For a slave ack General Call support, an additional step may be followed after +// the above steps. +// +// Arguments: +// [in] VOID *Data - +// I2C SAL handle +// +// Return: +// The status of the I2C initialization process. +// _EXIT_SUCCESS if the RtkI2CInit succeeded. +// _EXIT_FAILURE if the RtkI2CInit failed. +// +// Note: +// NA +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-04-03. +// +//---------------------------------------------------------------------------------------------------- +RTK_STATUS +RtkADCDeInit( + IN VOID *Data +){ + PSAL_ADC_HND pSalADCHND = (PSAL_ADC_HND) Data; + PSAL_ADC_HND_PRIV pSalADCHNDPriv = NULL; + PSAL_ADC_MNGT_ADPT pSalADCMngtAdpt = NULL; + PHAL_ADC_INIT_DAT pHalADCInitDat = NULL; + PHAL_ADC_OP pHalADCOP = NULL; + + /* To Get the SAL_ADC_MNGT_ADPT Pointer */ + pSalADCHNDPriv = CONTAINER_OF(pSalADCHND, SAL_ADC_HND_PRIV, SalADCHndPriv); + pSalADCMngtAdpt = CONTAINER_OF(pSalADCHNDPriv->ppSalADCHnd, SAL_ADC_MNGT_ADPT, pSalHndPriv); + + pHalADCInitDat = pSalADCMngtAdpt->pHalInitDat; + pHalADCOP = pSalADCMngtAdpt->pHalOp; + + /* Check the input ADC index first */ + if (RtkADCIdxChk(pSalADCHND->DevNum)) + return _EXIT_FAILURE; + + SalAdcInitialFlag &= (~(0x01 << pSalADCHND->DevNum)); + + if (SalAdcInitialFlag == 0) { + + /* ADC Initialize HAL Operations */ + HalADCOpInit(pHalADCOP); + + RtkADCPinMuxDeInit(pSalADCHND); + + /* ADC Interrupt Initialization */ +#if ADC_INTR_OP_TYPE + RtkADCIrqDeInit(pSalADCHND); +#endif + + /* ADC DMA Initialization */ +#if ADC_DMA_OP_TYPE + RtkADCDMADeInit(pSalADCHND); +#endif + + pHalADCInitDat->ADCEn = ADC_DISABLE; + pHalADCOP->HalADCEnable(pHalADCInitDat); + pHalADCOP->HalADCDeInit(pHalADCInitDat); + + /* ADC Function and Clock Enable*/ + RtkADCPinMuxDeInit(pSalADCHND); + } + + return _EXIT_SUCCESS; +} + +u32 +RtkADCReceive( + IN VOID *Data +){ + PSAL_ADC_HND pSalADCHND = (PSAL_ADC_HND) Data; + PSAL_ADC_HND_PRIV pSalADCHNDPriv = NULL; + PSAL_ADC_MNGT_ADPT pSalADCMngtAdpt = NULL; + PHAL_GDMA_ADAPTER pHALADCGdmaAdpt = NULL; + PHAL_GDMA_OP pHALADCGdmaOp = NULL; + PHAL_ADC_INIT_DAT pHalADCInitDat = NULL; + PHAL_ADC_OP pHalADCOP = NULL; + + //PIRQ_HANDLE pIrqHandleADCGdma = NULL; + u32 AdcTempDat; + + /* To Get the SAL_I2C_MNGT_ADPT Pointer */ + pSalADCHNDPriv = CONTAINER_OF(pSalADCHND, SAL_ADC_HND_PRIV, SalADCHndPriv); + pSalADCMngtAdpt = CONTAINER_OF(pSalADCHNDPriv->ppSalADCHnd, SAL_ADC_MNGT_ADPT, pSalHndPriv); + + pHALADCGdmaAdpt = pSalADCMngtAdpt->pHalGdmaAdp; + pHALADCGdmaOp = pSalADCMngtAdpt->pHalGdmaOp; + pHalADCInitDat = pSalADCMngtAdpt->pHalInitDat; + pHalADCOP = pSalADCMngtAdpt->pHalOp; + + if (pSalADCHND->OpType == ADC_DMA_TYPE) { + /* Clear ADC Status */ + HAL_ADC_READ32(REG_ADC_INTR_STS); + + HalGdmaOpInit(pHALADCGdmaOp); + pHALADCGdmaAdpt->GdmaCtl.BlockSize = pSalADCHND->pRXBuf->DataLen; + pHALADCGdmaAdpt->ChSar = (u32)(ADC_REG_BASE); + pHALADCGdmaAdpt->ChDar = (u32)pSalADCHND->pRXBuf->pDataBuf; + pHALADCGdmaAdpt->MuliBlockCunt = 0; + + pHALADCGdmaOp->HalGdmaChSeting(pHALADCGdmaAdpt); + pHALADCGdmaOp->HalGdmaChEn(pHALADCGdmaAdpt); + + pSalADCHND->DevSts = ADC_STS_RX_ING; + AdcTempDat = HAL_ADC_READ32(REG_ADC_POWER); + AdcTempDat |= BIT_ADC_PWR_AUTO; + HAL_ADC_WRITE32(REG_ADC_POWER, AdcTempDat); + return _EXIT_SUCCESS; + } + return _EXIT_FAILURE; +} + +extern u32 +HalDelayUs( + IN u32 us +); + +u32 +RtkADCReceiveBuf( + IN VOID *Data, + IN u32 *pBuf +){ + PSAL_ADC_HND pSalADCHND = (PSAL_ADC_HND) Data; + PSAL_ADC_HND_PRIV pSalADCHNDPriv = NULL; + PSAL_ADC_MNGT_ADPT pSalADCMngtAdpt = NULL; + PHAL_GDMA_ADAPTER pHALADCGdmaAdpt = NULL; + PHAL_GDMA_OP pHALADCGdmaOp = NULL; + PHAL_ADC_INIT_DAT pHalADCInitDat = NULL; + PHAL_ADC_OP pHalADCOP = NULL; + + //PIRQ_HANDLE pIrqHandleADCGdma = NULL; + u32 AdcTempDat; + + /* To Get the SAL_I2C_MNGT_ADPT Pointer */ + pSalADCHNDPriv = CONTAINER_OF(pSalADCHND, SAL_ADC_HND_PRIV, SalADCHndPriv); + pSalADCMngtAdpt = CONTAINER_OF(pSalADCHNDPriv->ppSalADCHnd, SAL_ADC_MNGT_ADPT, pSalHndPriv); + + pHALADCGdmaAdpt = pSalADCMngtAdpt->pHalGdmaAdp; + pHALADCGdmaOp = pSalADCMngtAdpt->pHalGdmaOp; + pHalADCInitDat = pSalADCMngtAdpt->pHalInitDat; + pHalADCOP = pSalADCMngtAdpt->pHalOp; + + + + /* Clear ADC Status */ + HAL_ADC_READ32(REG_ADC_INTR_STS); + ADCFullStsFlag = 0; + HalDelayUs(2000); + + pSalADCHND->pInitDat->ADCIntrMSK = (BIT_ADC_FIFO_FULL_EN); + pHalADCOP->HalADCIntrCtrl(pSalADCHND->pInitDat); + pSalADCHND->DevSts = ADC_STS_IDLE; + + pSalADCHND->pInitDat->ADCEn = ADC_ENABLE; + pHalADCOP->HalADCEnable(pSalADCHND->pInitDat); + AdcTempDat = (u32)HAL_ADC_READ32(REG_ADC_POWER); + while((AdcTempDat & BIT_ADC_FIFO_ON_ST) == 0){ + AdcTempDat = (u32)HAL_ADC_READ32(REG_ADC_POWER); + } + while (ADCFullStsFlag == 0){ + } + + pSalADCHND->pInitDat->ADCEn = ADC_DISABLE; + pHalADCOP->HalADCEnable(pSalADCHND->pInitDat); + + AdcTempDat = (u32)HAL_ADC_READ32(REG_ADC_POWER); + while((AdcTempDat & BIT_ADC_FIFO_ON_ST) != 0){ + AdcTempDat = (u32)HAL_ADC_READ32(REG_ADC_POWER); + } + + /* Clear ADC Status */ + HAL_ADC_READ32(REG_ADC_INTR_STS); + ADCFullStsFlag = 0; + + *pBuf = (u32)ADCDatBuf[0]; + *(pBuf+1) = (u32)ADCDatBuf[1]; + ADCDatBuf[0] = 0; + ADCDatBuf[1] = 0; + + return _EXIT_SUCCESS; +} + + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// RtkI2CGetSalHnd +// +// Description: +// Allocation of lower layer memory spaces will be done by invoking RtkI2CGetMngtAdpt +// in this function and return a SAL_I2C_HND pointer to upper layer. +// According to the given I2C index, RtkI2CGetMngtAdpt will allocate all the memory +// space such as SAL_I2C_HND, HAL_I2C_INIT_DAT, SAL_I2C_USER_CB etc. +// +// +// Arguments: +// [in] u8 I2CIdx - +// I2C Index +// +// Return: +// PSAL_I2C_HND +// A pointer to SAL_I2C_HND which is allocated in the lower layer. +// Note: +// NA +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-04-03. +// +//---------------------------------------------------------------------------------------------------- +PSAL_ADC_HND +RtkADCGetSalHnd( + IN u8 ADCIdx +){ + PSAL_ADC_MNGT_ADPT pSalADCMngtAdpt = NULL; + PSAL_ADC_HND pSalADCHND = NULL; + + /* Check the user define setting and the given index */ + if (RtkADCIdxChk(ADCIdx)) { + return (PSAL_ADC_HND)NULL; + } + + /* Invoke RtkI2CGetMngtAdpt to get the I2C SAL management adapter pointer */ + pSalADCMngtAdpt = RtkADCGetMngtAdpt(ADCIdx); + + /* Assign the private SAL handle to public SAL handle */ + pSalADCHND = &(pSalADCMngtAdpt->pSalHndPriv->SalADCHndPriv); + + /* Assign the internal HAL initial data pointer to the SAL handle */ + pSalADCHND->pInitDat = pSalADCMngtAdpt->pHalInitDat; + + /* Assign the internal user callback pointer to the SAL handle */ + pSalADCHND->pUserCB = pSalADCMngtAdpt->pUserCB; + + return &(pSalADCMngtAdpt->pSalHndPriv->SalADCHndPriv); + +} + + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// RtkI2CGetSalHnd +// +// Description: +// Allocation of lower layer memory spaces will be done by invoking RtkI2CGetMngtAdpt +// in this function and return a SAL_I2C_HND pointer to upper layer. +// According to the given I2C index, RtkI2CGetMngtAdpt will allocate all the memory +// space such as SAL_I2C_HND, HAL_I2C_INIT_DAT, SAL_I2C_USER_CB etc. +// +// +// Arguments: +// [in] u8 I2CIdx - +// I2C Index +// +// Return: +// PSAL_I2C_HND +// A pointer to SAL_I2C_HND which is allocated in the lower layer. +// Note: +// NA +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-04-03. +// +//---------------------------------------------------------------------------------------------------- +RTK_STATUS +RtkADCFreeSalHnd( + IN PSAL_ADC_HND pSalADCHND +){ + PSAL_ADC_MNGT_ADPT pSalADCMngtAdpt = NULL; + PSAL_ADC_HND_PRIV pSalADCHNDPriv = NULL; + + /* To get the SAL_DAC_MNGT_ADPT pointer */ + pSalADCHNDPriv = CONTAINER_OF(pSalADCHND, SAL_ADC_HND_PRIV, SalADCHndPriv); + pSalADCMngtAdpt = CONTAINER_OF(pSalADCHNDPriv->ppSalADCHnd, SAL_ADC_MNGT_ADPT, pSalHndPriv); + + /* Invoke RtkDACFreeMngtAdpt to free all the lower layer memory space */ + return (RtkADCFreeMngtAdpt(pSalADCMngtAdpt)); +} + + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// RtkI2CLoadDefault +// +// Description: +// Accrording the given I2C index, the default I2C configuration is done. +// +// +// Arguments: +// [in] PSAL_I2C_HND pSalI2CHND - +// SAL I2C handle +// +// Return: +// The status of the loading I2C default configuration. +// _EXIT_SUCCESS if the RtkI2CLoadDefault succeeded. +// _EXIT_FAILURE if the RtkI2CLoadDefault failed. +// +// Note: +// NA +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-04-03. +// +//---------------------------------------------------------------------------------------------------- +RTK_STATUS +RtkADCLoadDefault( + IN VOID *Data +){ + PSAL_ADC_HND pSalADCHND = (PSAL_ADC_HND) Data; + + /* Check the input ADC index first */ + if (RtkADCIdxChk(pSalADCHND->DevNum)) + return _EXIT_FAILURE; + + /* Load SAL handle default value */ + pSalADCHND->PinMux = 0; + pSalADCHND->OpType = ADC_RDREG_TYPE; + pSalADCHND->DevSts = ADC_STS_UNINITIAL; + pSalADCHND->ADCExd = 0; + pSalADCHND->ErrType = (u32)NULL; + + /* Load HAL initial data structure default value */ + pSalADCHND->pInitDat->ADCIdx = pSalADCHND->DevNum; + pSalADCHND->pInitDat->ADCEn = ADC_DISABLE; + pSalADCHND->pInitDat->ADCEndian = ADC_DATA_ENDIAN_LITTLE; + pSalADCHND->pInitDat->ADCBurstSz = 8; + pSalADCHND->pInitDat->ADCCompOnly = ADC_FEATURE_DISABLED; + pSalADCHND->pInitDat->ADCOneShotEn = ADC_FEATURE_DISABLED; + pSalADCHND->pInitDat->ADCOverWREn = ADC_FEATURE_DISABLED; + pSalADCHND->pInitDat->ADCOneShotTD = 8; + pSalADCHND->pInitDat->ADCCompCtrl = ADC_COMP_SMALLER_THAN; + pSalADCHND->pInitDat->ADCCompTD = 8; + pSalADCHND->pInitDat->ADCDataRate = 0; + pSalADCHND->pInitDat->ADCAudioEn = ADC_FEATURE_DISABLED; + pSalADCHND->pInitDat->ADCEnManul = ADC_FEATURE_DISABLED; + pSalADCHND->pInitDat->ADCDbgSel = ADC_DBG_SEL_DISABLE; + pSalADCHND->pInitDat->ADCPWCtrl = 0; + pSalADCHND->pInitDat->ADCIntrMSK = ADC_FEATURE_DISABLED; + pSalADCHND->pInitDat->ADCAnaParAd3 = 0; + return _EXIT_SUCCESS; +} + + diff --git a/component/soc/realtek/8195a/fwlib/src/hal_common.c b/component/soc/realtek/8195a/fwlib/src/hal_common.c new file mode 100644 index 0000000..6594168 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/src/hal_common.c @@ -0,0 +1,23 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#include "rtl8195a.h" +#include "hal_common.h" + +extern HAL_TIMER_OP HalTimerOp; + +HAL_Status +HalCommonInit(void){ + +#ifdef CONFIG_TIMER_MODULE + HalTimerOpInit_Patch((VOID*)(&HalTimerOp)); +#endif + + return HAL_OK; +} diff --git a/component/soc/realtek/8195a/fwlib/src/hal_dac.c b/component/soc/realtek/8195a/fwlib/src/hal_dac.c new file mode 100644 index 0000000..e149c2a --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/src/hal_dac.c @@ -0,0 +1,1452 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#include "rtl8195a.h" +#include "rtl_utility.h" +#include "osdep_api.h" +#include "hal_dac.h" +#include "hal_gdma.h" + +#define DAC_STATIC_ALLOC 0 + +/* DAC SAL global variables declaration when kernel disabled */ + +#if DAC_STATIC_ALLOC + SRAM_BF_DATA_SECTION + HAL_DAC_OP HalDACOpSAL; +#endif + + +#if DAC0_USED /*#if DAC0_USED*/ +#if DAC_STATIC_ALLOC + SRAM_BF_DATA_SECTION + SAL_DAC_MNGT_ADPT SalDAC0MngtAdpt; + + SRAM_BF_DATA_SECTION + SAL_DAC_HND_PRIV SalDAC0HndPriv; + + SRAM_BF_DATA_SECTION + HAL_DAC_INIT_DAT HalDAC0InitData; + + SRAM_BF_DATA_SECTION + IRQ_HANDLE DAC0IrqHandleDat; + + SRAM_BF_DATA_SECTION + HAL_GDMA_ADAPTER HalDAC0GdmaAdpt; + + SRAM_BF_DATA_SECTION + HAL_GDMA_OP HalDAC0GdmaOp; + + SRAM_BF_DATA_SECTION + IRQ_HANDLE DAC0GDMAIrqHandleDat; + + SRAM_BF_DATA_SECTION + SAL_DAC_USER_CB SalDAC0UserCB; + + SRAM_BF_DATA_SECTION + SAL_DAC_DMA_USER_DEF SalDAC0DmaUserDef; + + SRAM_BF_DATA_SECTION + SAL_DAC_USERCB_ADPT SalDAC0UserCBAdpt[SAL_DAC_USER_CB_NUM]; +#endif +#endif /*#if DAC0_USED*/ + +#if DAC1_USED /*#if DAC1_USED*/ +#if DAC_STATIC_ALLOC + + SRAM_BF_DATA_SECTION + SAL_DAC_MNGT_ADPT SalDAC1MngtAdpt; + + SRAM_BF_DATA_SECTION + SAL_DAC_HND_PRIV SalDAC1HndPriv; + + SRAM_BF_DATA_SECTION + HAL_DAC_INIT_DAT HalDAC1InitData; + + SRAM_BF_DATA_SECTION + IRQ_HANDLE DAC1IrqHandleDat; + + SRAM_BF_DATA_SECTION + HAL_GDMA_ADAPTER HalDAC1GdmaAdpt; + + SRAM_BF_DATA_SECTION + HAL_GDMA_OP HalDAC1GdmaOp; + + SRAM_BF_DATA_SECTION + IRQ_HANDLE DAC1GDMAIrqHandleDat; + + SRAM_BF_DATA_SECTION + SAL_DAC_USER_CB SalDAC1UserCB; + + SRAM_BF_DATA_SECTION + SAL_DAC_DMA_USER_DEF SalDAC1DmaUserDef; + + SRAM_BF_DATA_SECTION + SAL_DAC_USERCB_ADPT SalDAC1UserCBAdpt[SAL_DAC_USER_CB_NUM]; +#endif +#endif /*#if DAC1_USED*/ + +/* Function prototype */ +VOID DACISRHandle(IN VOID *Data); +VOID DACGDMAISRHandle(IN VOID * Data); +VOID DACGDMALLPISRHandle(IN VOID *Data); + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// RtkI2CGetMngtAdpt +// +// Description: +// According to the input index, all the memory space are allocated and all the +// related pointers are assigned. The management adapter pointer will be +// returned. +// +// Arguments: +// [in] u8 I2CIdx - +// I2C module index +// +// Return: +// PSAL_I2C_MNGT_ADPT +// +// Note: +// NA +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-04-02. +// +//--------------------------------------------------------------------------------------------------- +VOID HalDACOpInit( + IN VOID *Data +) +{ + PHAL_DAC_OP pHalDacOp = (PHAL_DAC_OP) Data; + + pHalDacOp->HalDACInit = HalDACInit8195a; + pHalDacOp->HalDACDeInit = HalDACDeInit8195a; + pHalDacOp->HalDACEnable = HalDACEnableRtl8195a; + pHalDacOp->HalDACSend = HalDACSendRtl8195a; + pHalDacOp->HalDACIntrCtrl = HalDACIntrCtrl8195a; + pHalDacOp->HalDACReadReg = HalDACReadRegRtl8195a; +} + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// RtkI2CGetMngtAdpt +// +// Description: +// According to the input index, all the memory space are allocated and all the +// related pointers are assigned. The management adapter pointer will be +// returned. +// +// Arguments: +// [in] u8 I2CIdx - +// I2C module index +// +// Return: +// PSAL_I2C_MNGT_ADPT +// +// Note: +// NA +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-04-02. +// +//--------------------------------------------------------------------------------------------------- +PSAL_DAC_MNGT_ADPT +RtkDACGetMngtAdpt( + IN u8 DACIdx +){ + PSAL_DAC_MNGT_ADPT pSalDACMngtAdpt = NULL; + PSAL_DAC_USERCB_ADPT pSalDACUserCBAdpt = NULL; + + /* If the kernel is available, Memory-allocation is used. */ +#if !DAC_STATIC_ALLOC + + pSalDACMngtAdpt = (PSAL_DAC_MNGT_ADPT)RtlZmalloc(sizeof(SAL_DAC_MNGT_ADPT)); + pSalDACMngtAdpt->pSalHndPriv = (PSAL_DAC_HND_PRIV)RtlZmalloc(sizeof(SAL_DAC_HND_PRIV)); + pSalDACMngtAdpt->pHalInitDat = (PHAL_DAC_INIT_DAT)RtlZmalloc(sizeof(HAL_DAC_INIT_DAT)); + pSalDACMngtAdpt->pHalOp = (PHAL_DAC_OP)RtlZmalloc(sizeof(HAL_DAC_OP)); + pSalDACMngtAdpt->pIrqHnd = (PIRQ_HANDLE)RtlZmalloc(sizeof(IRQ_HANDLE)); + pSalDACMngtAdpt->pUserCB = (PSAL_DAC_USER_CB)RtlZmalloc(sizeof(SAL_DAC_USER_CB)); + pSalDACMngtAdpt->pDMAConf = (PSAL_DAC_DMA_USER_DEF)RtlZmalloc(sizeof(SAL_DAC_DMA_USER_DEF)); + pSalDACMngtAdpt->pHalGdmaAdp = (PHAL_GDMA_ADAPTER)RtlZmalloc(sizeof(HAL_GDMA_ADAPTER)); + pSalDACMngtAdpt->pHalGdmaOp = (PHAL_GDMA_OP)RtlZmalloc(sizeof(HAL_GDMA_OP)); + pSalDACMngtAdpt->pIrqGdmaHnd = (PIRQ_HANDLE)RtlZmalloc(sizeof(IRQ_HANDLE)); + pSalDACUserCBAdpt = (PSAL_DAC_USERCB_ADPT)RtlZmalloc((sizeof(SAL_DAC_USERCB_ADPT)*SAL_DAC_USER_CB_NUM)); +#else + switch (DACIdx){ + case DAC0_SEL: + { + pSalDACMngtAdpt = &SalDAC0MngtAdpt; + pSalDACMngtAdpt->pSalHndPriv = &SalDAC0HndPriv; + pSalDACMngtAdpt->pHalInitDat = &HalDAC0InitData; + pSalDACMngtAdpt->pHalOp = &HalDACOpSAL; + pSalDACMngtAdpt->pIrqHnd = &DAC0IrqHandleDat; + pSalDACMngtAdpt->pUserCB = &SalDAC0UserCB; + pSalDACMngtAdpt->pDMAConf = &SalDAC0DmaUserDef; + pSalDACMngtAdpt->pHalGdmaAdp = &HalDAC0GdmaAdpt; + pSalDACMngtAdpt->pHalGdmaOp = &HalDAC0GdmaOp; + pSalDACMngtAdpt->pIrqGdmaHnd = &DAC0IrqHandleDat; + pSalDACUserCBAdpt = &SalDAC0UserCBAdpt; + break; + } + + case DAC1_SEL: + { + pSalDACMngtAdpt = &SalDAC1MngtAdpt; + pSalDACMngtAdpt->pSalHndPriv = &SalDAC1HndPriv; + pSalDACMngtAdpt->pHalInitDat = &HalDAC1InitData; + pSalDACMngtAdpt->pHalOp = &HalDACOpSAL; + pSalDACMngtAdpt->pIrqHnd = &DAC1IrqHandleDat; + pSalDACMngtAdpt->pUserCB = &SalDAC1UserCB; + pSalDACMngtAdpt->pDMAConf = &SalDAC1DmaUserDef; + pSalDACMngtAdpt->pHalGdmaAdp = &HalDAC1GdmaAdpt; + pSalDACMngtAdpt->pHalGdmaOp = &HalDAC1GdmaOp; + pSalDACMngtAdpt->pIrqGdmaHnd = &DAC1IrqHandleDat; + pSalDACUserCBAdpt = &SalDAC1UserCBAdpt; + break; + } + + default: + break; + } +#endif + + /*To assign user callback pointers*/ + pSalDACMngtAdpt->pUserCB->pTXCB = pSalDACUserCBAdpt; + pSalDACMngtAdpt->pUserCB->pTXCCB = (pSalDACUserCBAdpt+1); + pSalDACMngtAdpt->pUserCB->pRXCB = (pSalDACUserCBAdpt+2); + pSalDACMngtAdpt->pUserCB->pRXCCB = (pSalDACUserCBAdpt+3); + pSalDACMngtAdpt->pUserCB->pRDREQCB = (pSalDACUserCBAdpt+4); + pSalDACMngtAdpt->pUserCB->pERRCB = (pSalDACUserCBAdpt+5); + pSalDACMngtAdpt->pUserCB->pDMATXCB = (pSalDACUserCBAdpt+6); + pSalDACMngtAdpt->pUserCB->pDMATXCCB = (pSalDACUserCBAdpt+7); + pSalDACMngtAdpt->pUserCB->pDMARXCB = (pSalDACUserCBAdpt+8); + pSalDACMngtAdpt->pUserCB->pDMARXCCB = (pSalDACUserCBAdpt+9); + + /*To assign the rest pointers*/ + pSalDACMngtAdpt->pSalHndPriv->ppSalDACHnd = (void**)&(pSalDACMngtAdpt->pSalHndPriv); + + /* To assign the default HAL OP initialization function */ + pSalDACMngtAdpt->pHalOpInit = &HalDACOpInit; + + /* To assign the default HAL GDMA OP initialization function */ + pSalDACMngtAdpt->pHalGdmaOpInit = &HalGdmaOpInit; + + /* To assign the default SAL interrupt function */ + pSalDACMngtAdpt->pSalIrqFunc = &DACISRHandle; + + /* To assign the default SAL DMA interrupt function */ + pSalDACMngtAdpt->pSalDMAIrqFunc = &DACGDMAISRHandle; + + return pSalDACMngtAdpt; +} + + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// RtkI2CFreeMngtAdpt +// +// Description: +// Free all the previous allocated memory space. +// +// Arguments: +// [in] PSAL_I2C_MNGT_ADPT pSalI2CMngtAdpt - +// I2C SAL management adapter pointer +// +// +// Return: +// The status of the enable process. +// _EXIT_SUCCESS if the RtkI2CFreeMngtAdpt succeeded. +// _EXIT_FAILURE if the RtkI2CFreeMngtAdpt failed. +// +// Note: +// NA +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-04-02. +// +//--------------------------------------------------------------------------------------------------- +RTK_STATUS +RtkDACFreeMngtAdpt( + IN PSAL_DAC_MNGT_ADPT pSalDACMngtAdpt +){ +#if !DAC_STATIC_ALLOC + RtlMfree((u8 *)pSalDACMngtAdpt->pUserCB->pTXCB, (sizeof(SAL_DAC_USERCB_ADPT)*SAL_DAC_USER_CB_NUM)); + RtlMfree((u8 *)pSalDACMngtAdpt->pIrqGdmaHnd, sizeof(IRQ_HANDLE)); + RtlMfree((u8 *)pSalDACMngtAdpt->pHalGdmaOp, sizeof(HAL_GDMA_OP)); + RtlMfree((u8 *)pSalDACMngtAdpt->pHalGdmaAdp, sizeof(HAL_GDMA_ADAPTER)); + RtlMfree((u8 *)pSalDACMngtAdpt->pDMAConf, sizeof(SAL_DAC_DMA_USER_DEF)); + RtlMfree((u8 *)pSalDACMngtAdpt->pUserCB, sizeof(SAL_DAC_USER_CB)); + RtlMfree((u8 *)pSalDACMngtAdpt->pIrqHnd, sizeof(IRQ_HANDLE)); + RtlMfree((u8 *)pSalDACMngtAdpt->pHalOp, sizeof(HAL_DAC_OP)); + RtlMfree((u8 *)pSalDACMngtAdpt->pHalInitDat, sizeof(HAL_DAC_INIT_DAT)); + RtlMfree((u8 *)pSalDACMngtAdpt->pSalHndPriv, sizeof(SAL_DAC_HND_PRIV)); + RtlMfree((u8 *)pSalDACMngtAdpt, sizeof(SAL_DAC_MNGT_ADPT)); +#else + ; +#endif + + return _EXIT_SUCCESS; +} + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// I2CISRHandle +// +// Description: +// I2C Interrupt Service Routine. +// According to the input pointer to SAL_I2C_HND, all the rest pointers will be +// found and be used to the rest part of this servie routine. +// The following types of interrupt will be taken care: +// - General Call (providing General Call Callback). Slave receives a general call. +// - STOP Bit (NOT providing General Call Callback) +// - START Bit (NOTproviding General Call Callback) +// - I2C Activity (NOTproviding General Call Callback) +// - RX Done (providing Error Callback). The slave transmitter does NOT +// receive a proper NACK for the end of whole transfer. +// - TX Abort (providing Error Call Callback). The Master/Slave +// transmitting is terminated. +// - RD Req (providing TX and TXC Callback). Slave gets a Read Request +// and starts a slave-transmitter operation. The slave transmit +// data will be written into slave TX FIFO from user data buffer. +// - TX Empty (providing TX and TXC Callback). Master TX FIFO is empty. +// The user transmit data will be written into master TX FIFO +// from user data buffer. +// - TX Over (providing Error Callback). Master TX FIFO is Overflow. +// - RX Full (providing RX and RXC Callback). Master/Slave RX FIFO contains +// data. And the received data will be put into Master/Slave user +// receive data buffer. +// - RX Over (providing Error Callback). Master/Slave RX FIFO is Overflow. +// - RX Under (providing Error Callback). Master/Slave RX FIFO is Underflow. +// +// Arguments: +// [in] VOID *Data - +// I2C SAL handle +// +// Return: +// NA +// +// Note: +// NA +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-04-02. +// +//---------------------------------------------------------------------------------------------------- +VOID +DACISRHandle( + IN VOID *Data +){ +#ifdef CONFIG_DEBUG_LOG_DAC_HAL + PSAL_DAC_HND pSalDACHND = (PSAL_DAC_HND) Data; + PSAL_DAC_HND_PRIV pSalDACHNDPriv = NULL; + PSAL_DAC_MNGT_ADPT pSalDACMngtAdpt = NULL; + PHAL_DAC_INIT_DAT pHalDACInitDat = NULL; + PHAL_DAC_OP pHalDACOP = NULL; + PSAL_DAC_USER_CB pSalDACUserCB = NULL; + u8 DACIrqIdx; + + /* To get the SAL_I2C_MNGT_ADPT pointer, and parse the rest pointers */ + pSalDACHNDPriv = CONTAINER_OF(pSalDACHND, SAL_DAC_HND_PRIV, SalDACHndPriv); + pSalDACMngtAdpt = CONTAINER_OF(pSalDACHNDPriv->ppSalDACHnd, SAL_DAC_MNGT_ADPT, pSalHndPriv); + pHalDACInitDat = pSalDACMngtAdpt->pHalInitDat; + pHalDACOP = pSalDACMngtAdpt->pHalOp; + DACIrqIdx = pHalDACInitDat->DACIdx; + pSalDACUserCB = pSalDACHND->pUserCB; + + DBG_DAC_INFO("DAC INTR STS:%x\n",pHalDACOP->HalDACReadReg(pHalDACInitDat, REG_DAC_INTR_STS)); + if ((pHalDACOP->HalDACReadReg(pHalDACInitDat, REG_DAC_INTR_STS)) & BIT_DAC_FIFO_STOP_ST){ + pHalDACInitDat->DACEn = DAC_DISABLE; + pHalDACOP->HalDACEnable((void *)pHalDACInitDat); + } +#else + /* To reduce warning */ + PSAL_DAC_HND pSalDACHND = (PSAL_DAC_HND) Data; + PSAL_DAC_HND_PRIV pSalDACHNDPriv = NULL; + PSAL_DAC_MNGT_ADPT pSalDACMngtAdpt = NULL; + PHAL_DAC_INIT_DAT pHalDACInitDat = NULL; + PHAL_DAC_OP pHalDACOP = NULL; + PSAL_DAC_USER_CB pSalDACUserCB = NULL; + u8 DACIrqIdx; + + /* To get the SAL_I2C_MNGT_ADPT pointer, and parse the rest pointers */ + pSalDACHNDPriv = CONTAINER_OF(pSalDACHND, SAL_DAC_HND_PRIV, SalDACHndPriv); + pSalDACMngtAdpt = CONTAINER_OF(pSalDACHNDPriv->ppSalDACHnd, SAL_DAC_MNGT_ADPT, pSalHndPriv); + pHalDACInitDat = pSalDACMngtAdpt->pHalInitDat; + pHalDACOP = pSalDACMngtAdpt->pHalOp; + DACIrqIdx = pHalDACInitDat->DACIdx; + pSalDACUserCB = pSalDACHND->pUserCB; + + pHalDACOP->HalDACReadReg(pHalDACInitDat, REG_DAC_INTR_STS); +#endif +} + +VOID +DACGDMAISRHandle( + IN VOID *Data +){ + + PSAL_DAC_HND pSalDACHND = (PSAL_DAC_HND) Data; + PSAL_DAC_HND_PRIV pSalDACHNDPriv = NULL; + PSAL_DAC_MNGT_ADPT pSalDACMngtAdpt = NULL; + + PHAL_GDMA_ADAPTER pHalDACGdmaAdapter = NULL; + PHAL_GDMA_OP pHalDACGdmaOp = NULL; + PSAL_DAC_USER_CB pSalDACUserCB = NULL; + + u8 IsrTypeMap = 0; + DBG_8195A_DAC_LVL(HAL_DAC_LVL,"%s\n",__func__); + + + pSalDACHNDPriv = CONTAINER_OF(pSalDACHND, SAL_DAC_HND_PRIV, SalDACHndPriv); + pSalDACMngtAdpt = CONTAINER_OF(pSalDACHNDPriv->ppSalDACHnd, SAL_DAC_MNGT_ADPT, pSalHndPriv); + + pHalDACGdmaAdapter = pSalDACMngtAdpt->pHalGdmaAdp; + pHalDACGdmaOp = pSalDACMngtAdpt->pHalGdmaOp; + pSalDACUserCB = pSalDACMngtAdpt->pUserCB; + + pSalDACMngtAdpt->pHalGdmaOpInit(pHalDACGdmaOp); + + if ((pHalDACGdmaAdapter->MaxMuliBlock) == pHalDACGdmaAdapter->MuliBlockCunt+1) { + pHalDACGdmaOp->HalGdmaChCleanAutoSrc(pHalDACGdmaAdapter); + pHalDACGdmaOp->HalGdmaChDis(pHalDACGdmaAdapter); + pSalDACHND->DevSts = DAC_STS_IDLE; + if (pSalDACUserCB->pDMATXCCB->USERCB != NULL) + { + pSalDACUserCB->pDMATXCCB->USERCB((void*)pSalDACUserCB->pDMATXCCB->USERData); + } + } + else { + //pHalDACGdmaOp->HalGdmaChCleanAutoSrc(pHalDACGdmaAdapter); + pSalDACHND->DevSts = DAC_STS_TX_ING; + + if (pSalDACUserCB->pDMATXCB->USERCB != NULL){ + pSalDACUserCB->pDMATXCB->USERCB((void*)pSalDACUserCB->pDMATXCB->USERData);} + } + + //3 Clear Pending ISR + IsrTypeMap = pHalDACGdmaOp->HalGdmaChIsrClean((VOID*)pHalDACGdmaAdapter); + + //3 Maintain Block Count + if (IsrTypeMap & BlockType) { + pHalDACGdmaAdapter->MuliBlockCunt++; + } + +} + +VOID +DACGDMALLPISRHandle( + IN VOID *Data +){ + PSAL_DAC_HND pSalDACHND = (PSAL_DAC_HND) Data; + PSAL_DAC_HND_PRIV pSalDACHNDPriv = NULL; + PSAL_DAC_MNGT_ADPT pSalDACMngtAdpt = NULL; + + PHAL_GDMA_ADAPTER pHalDACGdmaAdapter = NULL; + PHAL_GDMA_OP pHalDACGdmaOp = NULL; + PSAL_DAC_USER_CB pSalDACUserCB = NULL; + u8 IsrTypeMap; + + pSalDACHNDPriv = CONTAINER_OF(pSalDACHND, SAL_DAC_HND_PRIV, SalDACHndPriv); + pSalDACMngtAdpt = CONTAINER_OF(pSalDACHNDPriv->ppSalDACHnd, SAL_DAC_MNGT_ADPT, pSalHndPriv); + + pHalDACGdmaAdapter = pSalDACMngtAdpt->pHalGdmaAdp; + pHalDACGdmaOp = pSalDACMngtAdpt->pHalGdmaOp; + pSalDACUserCB = pSalDACMngtAdpt->pUserCB; + + pSalDACMngtAdpt->pHalGdmaOpInit(pHalDACGdmaOp); +#if 0 + PGDMA_ADAPTER pGdmaAdapte = (PGDMA_ADAPTER) Data; + PHAL_GDMA_ADAPTER pHalGdmaAdapter = pGdmaAdapte->pHalGdmaAdapter; + PGDMA_CH_LLI_ELE pGdmaChLliEle; + struct GDMA_CH_LLI *pGdmaChLli = pHalGdmaAdapter->pLlix; + struct BLOCK_SIZE_LIST *pBlockSizeList = pHalGdmaAdapter->pBlockSizeList; + u32 TotalBlockSize = 0; + u8 IsrTypeMap, BlockIndex; + u8 *pSrc = NULL, *pDst = NULL; + DBG_8195A_DMA("Enter Gdma0 Channel 5 ISr =====>\n"); +#endif + + + + if ((pHalDACGdmaAdapter->MaxMuliBlock) == pHalDACGdmaAdapter->MuliBlockCunt) { + //HalGdmaOp.HalGdmaChCleanAutoSrc(pHalGdmaAdapter); + //DAC0_FCTRL(OFF); + + //HalGdmaOp.HalGdmaChCleanAutoDst(pHalGdmaAdapter); + pHalDACGdmaOp->HalGdmaChDis(pHalDACGdmaAdapter); + + DBG_8195A("dma done\n"); + } + + + IsrTypeMap = pHalDACGdmaOp->HalGdmaChIsrClean((VOID*)pHalDACGdmaAdapter); + + if (IsrTypeMap & BlockType) { + pHalDACGdmaAdapter->MuliBlockCunt++; + } +} + +static RTK_STATUS +RtkDACPinMuxInit( + IN PSAL_DAC_HND pSalDACHND +){ + u32 DACLocalTemp; + + /* Check the I2C index first */ + if (RtkDACIdxChk(pSalDACHND->DevNum)) + return _EXIT_FAILURE; + + DACLocalTemp = HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_SYSPLL_CTRL2); + DACLocalTemp |= BIT26; + + /* To release DAC delta sigma clock gating */ + HAL_WRITE32(SYSTEM_CTRL_BASE,REG_SYS_SYSPLL_CTRL2,DACLocalTemp); + + switch (pSalDACHND->DevNum){ +#if DAC0_USED + case DAC0_SEL: + { + /* Turn on DAC active clock */ + ACTCK_DAC_CCTRL(ON); + + /* Enable DAC0 module */ + DAC0_FCTRL(ON); + break; + } +#endif +#if DAC1_USED + case DAC1_SEL: + { + /* Turn on DAC active clock */ + ACTCK_DAC_CCTRL(ON); + + /* Enable DAC1 module */ + DAC1_FCTRL(ON); + break; + } +#endif + default: + return _EXIT_FAILURE; + } + + return _EXIT_SUCCESS; +} + +static RTK_STATUS +RtkDACPinMuxDeInit( + IN PSAL_DAC_HND pSalDACHND +){ + + u32 DACLocalTemp; + + /* Check the I2C index first */ + if (RtkDACIdxChk(pSalDACHND->DevNum)) + return _EXIT_FAILURE; + + switch (pSalDACHND->DevNum){ +#if DAC0_USED + case DAC0_SEL: + { + /* Turn on DAC active clock */ + ACTCK_DAC_CCTRL(OFF); + + /* Enable DAC0 module */ + DAC0_FCTRL(OFF); + break; + } +#endif +#if DAC1_USED + case DAC1_SEL: + { + /* Turn on DAC active clock */ + ACTCK_DAC_CCTRL(OFF); + + /* Enable DAC1 module */ + DAC1_FCTRL(OFF); + break; + } +#endif + default: + return _EXIT_FAILURE; + } + + + DACLocalTemp = HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_SYSPLL_CTRL2); + DACLocalTemp &= (~BIT26); + + /* To release DAC delta sigma clock gating */ + HAL_WRITE32(SYSTEM_CTRL_BASE,REG_SYS_SYSPLL_CTRL2,DACLocalTemp); + + return _EXIT_SUCCESS; +} + + +#if DAC_INTR_OP_TYPE +//--------------------------------------------------------------------------------------------------- +//Function Name: +// RtkI2CIrqInit +// +// Description: +// I2C interrupt initialization function. +// For I2C interrupt operation mode, I2C module MUST register itself to the platform +// by providing the interrupt handler which contains interrupt input data (arguments), +// interrupt service routine, interrupt number, interrupt priority. And then the interrupt +// should be enabled. +// +// Arguments: +// [in] VOID *Data - +// I2C SAL handle +// +// Return: +// The status of the I2C interrupt initialization process. +// _EXIT_SUCCESS if the RtkI2CIrqInit succeeded. +// _EXIT_FAILURE if the RtkI2CIrqInit failed. +// +// Note: +// NA +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-04-03. +// +//---------------------------------------------------------------------------------------------------- +static RTK_STATUS +RtkDACIrqInit( + IN PSAL_DAC_HND pSalDACHND +){ + PSAL_DAC_HND_PRIV pSalDACHNDPriv = NULL; + PSAL_DAC_MNGT_ADPT pSalDACMngtAdpt = NULL; + PIRQ_HANDLE pIrqHandle = NULL; + + /* To Get the SAL_I2C_MNGT_ADPT Pointer */ + pSalDACHNDPriv = CONTAINER_OF(pSalDACHND, SAL_DAC_HND_PRIV, SalDACHndPriv); + pSalDACMngtAdpt = CONTAINER_OF(pSalDACHNDPriv->ppSalDACHnd, SAL_DAC_MNGT_ADPT, pSalHndPriv); + pIrqHandle = pSalDACMngtAdpt->pIrqHnd; + + if (RtkDACIdxChk(pSalDACHND->DevNum)) + return _EXIT_FAILURE; + + switch (pSalDACHND->DevNum){ +#if DAC0_USED + case DAC0_SEL: + { + pIrqHandle->Data = (u32) (pSalDACHND); + pIrqHandle->IrqNum = DAC0_IRQ; + pIrqHandle->IrqFun = (IRQ_FUN) pSalDACMngtAdpt->pSalIrqFunc; + pIrqHandle->Priority = 5; + InterruptRegister(pIrqHandle); + InterruptEn(pIrqHandle); + break; + } +#endif +#if DAC1_USED + case DAC1_SEL: + { + pIrqHandle->Data = (u32) (pSalDACHND); + pIrqHandle->IrqNum = DAC1_IRQ; + pIrqHandle->IrqFun = (IRQ_FUN) pSalDACMngtAdpt->pSalIrqFunc;; + pIrqHandle->Priority = 5; + InterruptRegister(pIrqHandle); + InterruptEn(pIrqHandle); + break; + } +#endif + default: + return _EXIT_FAILURE; + } + + + + return _EXIT_SUCCESS; +} + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// RtkI2CIrqDeInit +// +// Description: +// I2C interrupt de-initialization function. +// According to the given I2C device number, the I2C interrupt will be unreigster +// from the platform and the relative interrupt handler will be cleared. +// +// Arguments: +// [in] VOID *Data - +// I2C SAL handle +// +// Return: +// The status of the I2C interrupt de-initialization process. +// _EXIT_SUCCESS if the RtkI2CIrqDeInit succeeded. +// _EXIT_FAILURE if the RtkI2CIrqDeInit failed. +// +// Note: +// NA +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-04-03. +// +//---------------------------------------------------------------------------------------------------- +static RTK_STATUS +RtkDACIrqDeInit( + IN PSAL_DAC_HND pSalDACHND +){ + PSAL_DAC_HND_PRIV pSalDACHNDPriv = NULL; + PSAL_DAC_MNGT_ADPT pSalDACMngtAdpt = NULL; + PIRQ_HANDLE pIrqHandle = NULL; + + /*To Get the SAL_I2C_MNGT_ADPT Pointer*/ + pSalDACHNDPriv = CONTAINER_OF(pSalDACHND, SAL_DAC_HND_PRIV, SalDACHndPriv); + pSalDACMngtAdpt = CONTAINER_OF(pSalDACHNDPriv->ppSalDACHnd, SAL_DAC_MNGT_ADPT, pSalHndPriv); + pIrqHandle = pSalDACMngtAdpt->pIrqHnd; + + if (RtkDACIdxChk(pSalDACHND->DevNum)) + return _EXIT_FAILURE; + + InterruptUnRegister(pIrqHandle); + return _EXIT_SUCCESS; +} + +#endif + + +#if DAC_DMA_OP_TYPE +const u16 DACDmaChNo[10] = {GdmaNoCh ,GdmaCh0, + GdmaCh1 ,GdmaCh2, + GdmaCh3 ,GdmaCh4, + GdmaCh5 ,GdmaCh6, + GdmaCh7 ,GdmaAllCh}; + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// RtkI2CIrqInit +// +// Description: +// I2C interrupt initialization function. +// For I2C interrupt operation mode, I2C module MUST register itself to the platform +// by providing the interrupt handler which contains interrupt input data (arguments), +// interrupt service routine, interrupt number, interrupt priority. And then the interrupt +// should be enabled. +// +// Arguments: +// [in] VOID *Data - +// I2C SAL handle +// +// Return: +// The status of the I2C interrupt initialization process. +// _EXIT_SUCCESS if the RtkI2CIrqInit succeeded. +// _EXIT_FAILURE if the RtkI2CIrqInit failed. +// +// Note: +// NA +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-04-03. +// +//---------------------------------------------------------------------------------------------------- +static RTK_STATUS +RtkDACDMAInit( + IN PSAL_DAC_HND pSalDACHND +){ + PSAL_DAC_HND_PRIV pSalDACHNDPriv = NULL; + PSAL_DAC_MNGT_ADPT pSalDACMngtAdpt = NULL; + PHAL_GDMA_ADAPTER pHALDACGdmaAdpt = NULL; + PHAL_GDMA_OP pHALDACGdmaOp = NULL; + PIRQ_HANDLE pIrqHandleDACGdma = NULL; + PSAL_DAC_DMA_USER_DEF pSalDACDmaUserDef = NULL; + + u32 I2CLocalTemp; + u32 I2CLocalMask; + + /* To Get the SAL_I2C_MNGT_ADPT Pointer */ + pSalDACHNDPriv = CONTAINER_OF(pSalDACHND, SAL_DAC_HND_PRIV, SalDACHndPriv); + pSalDACMngtAdpt = CONTAINER_OF(pSalDACHNDPriv->ppSalDACHnd, SAL_DAC_MNGT_ADPT, pSalHndPriv); + + pHALDACGdmaAdpt = pSalDACMngtAdpt->pHalGdmaAdp; + pHALDACGdmaOp = pSalDACMngtAdpt->pHalGdmaOp; + pIrqHandleDACGdma = pSalDACMngtAdpt->pIrqGdmaHnd; + pSalDACDmaUserDef = pSalDACHND->pDMAConf; + + if (RtkDACIdxChk(pSalDACHND->DevNum)) + return _EXIT_FAILURE; + + if (pSalDACHND->DACInType == DAC_INPUT_SINGLE_WR) + return _EXIT_SUCCESS; + + /* GDMA operation initialization */ + //HalGdmaOpInit(pHalI2CGdmaOp); + _memset((void *)pHALDACGdmaAdpt, 0, sizeof(HAL_GDMA_ADAPTER)); + pSalDACMngtAdpt->pHalGdmaOpInit(pHALDACGdmaOp); + pHALDACGdmaOp->HalGdamChInit((VOID*)(pHALDACGdmaAdpt)); + + + + pHALDACGdmaAdpt->GdmaIndex = pSalDACHND->DevNum; + pHALDACGdmaAdpt->GdmaCtl.IntEn = 1; + pHALDACGdmaAdpt->ChNum = pSalDACDmaUserDef->TxChNo; + + pHALDACGdmaAdpt->ChEn = DACDmaChNo[pHALDACGdmaAdpt->ChNum+1]; + pHALDACGdmaAdpt->IsrCtrl = ENABLE; + pHALDACGdmaAdpt->GdmaOnOff = ON; + + + /* GDMA initialization */ + /* Enable the whole GDMA module first */ + if (pHALDACGdmaAdpt->GdmaIndex == 0) { + ACTCK_GDMA0_CCTRL(ON); + SLPCK_GDMA0_CCTRL(ON); + GDMA0_FCTRL(ON); + } + else { + ACTCK_GDMA1_CCTRL(ON); + SLPCK_GDMA1_CCTRL(ON); + GDMA1_FCTRL(ON); + } + + if (pSalDACHND->DACInType == DAC_INPUT_DMA_ONEBLK) { + //DAC TX DMA + pHALDACGdmaAdpt->GdmaCtl.SrcTrWidth = pSalDACDmaUserDef->TxDatSrcWdth; + pHALDACGdmaAdpt->GdmaCtl.DstTrWidth = pSalDACDmaUserDef->TxDatDstWdth; + pHALDACGdmaAdpt->GdmaCtl.SrcMsize = pSalDACDmaUserDef->TxDatSrcBstSz; + pHALDACGdmaAdpt->GdmaCtl.DestMsize = pSalDACDmaUserDef->TxDatDstBstSz; + + pHALDACGdmaAdpt->GdmaCtl.Sinc = IncType; + pHALDACGdmaAdpt->GdmaCtl.Dinc = NoChange; + + pHALDACGdmaAdpt->GdmaCtl.Done = 1; + pHALDACGdmaAdpt->GdmaCtl.TtFc = 0x01; + + pHALDACGdmaAdpt->GdmaCfg.DestPer = 13; + pHALDACGdmaAdpt->GdmaCfg.ReloadSrc = 1; + + pHALDACGdmaAdpt->MuliBlockCunt = 1; + pHALDACGdmaAdpt->MaxMuliBlock = pSalDACHND->pDMAConf->MaxMultiBlk; + + pHALDACGdmaAdpt->GdmaIsrType = (BlockType|TransferType|ErrType); + + + pHALDACGdmaAdpt->TestItem = 3; + + + //pSalDACMngtAdpt->pSalDMAIrqFunc = &DACGDMAISRHandle; + } + else if (pSalDACHND->DACInType == DAC_INPUT_DMA_LLP) { + //DAC TX DMA + pHALDACGdmaAdpt->GdmaCtl.SrcTrWidth = pSalDACDmaUserDef->TxDatSrcWdth; + pHALDACGdmaAdpt->GdmaCtl.DstTrWidth = pSalDACDmaUserDef->TxDatDstWdth; + pHALDACGdmaAdpt->GdmaCtl.SrcMsize = pSalDACDmaUserDef->TxDatSrcBstSz; + pHALDACGdmaAdpt->GdmaCtl.DestMsize = pSalDACDmaUserDef->TxDatDstBstSz; + + pHALDACGdmaAdpt->GdmaCtl.Dinc = NoChange; + + pHALDACGdmaAdpt->GdmaCtl.Done = 1; + pHALDACGdmaAdpt->GdmaCtl.TtFc = 0x01; + pHALDACGdmaAdpt->GdmaCtl.LlpSrcEn = 1; + + pHALDACGdmaAdpt->GdmaCfg.DestPer = 13; + + pHALDACGdmaAdpt->GdmaIsrType = (BlockType|ErrType); + + /* Enable LLP control */ + pHALDACGdmaAdpt->Llpctrl = pSalDACDmaUserDef->LlpCtrl; + + pHALDACGdmaAdpt->MuliBlockCunt = 1; + pHALDACGdmaAdpt->MaxMuliBlock = pSalDACDmaUserDef->MaxMultiBlk; + + pHALDACGdmaAdpt->TestItem = 9; + + //pSalDACMngtAdpt->pSalDMAIrqFunc = &DACGDMALLPISRHandle; + } + + + /* GDMA interrupt register */ + pIrqHandleDACGdma->Data = (u32) (pSalDACHND); + pIrqHandleDACGdma->IrqNum = GDMA0_CHANNEL0_IRQ + pHALDACGdmaAdpt->ChNum + + ((pHALDACGdmaAdpt->GdmaIndex)*6); + pIrqHandleDACGdma->IrqFun = (IRQ_FUN) pSalDACMngtAdpt->pSalDMAIrqFunc; + pIrqHandleDACGdma->Priority = 2; + InterruptRegister(pIrqHandleDACGdma); + InterruptEn(pIrqHandleDACGdma); + + + pHALDACGdmaOp->HalGdmaOnOff((VOID*)pHALDACGdmaAdpt); + pHALDACGdmaOp->HalGdmaChIsrEnAndDis((VOID*)pHALDACGdmaAdpt); + +#if 0 + /* Enable GDMA according to the DMA type */ + if (pSalDACHND->DACInType == DAC_INPUT_DMA_ONEBLK) { + pHALDACGdmaOp->HalGdmaChSeting((VOID*)pHALDACGdmaAdpt); + } + else if (pSalDACHND->DACInType == DAC_INPUT_DMA_LLP){ + //pHALDACGdmaOp->HalGdmaChBlockSeting((VOID*)(pHALDACGdmaAdpt)); + } +#endif + return _EXIT_SUCCESS; +} + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// RtkI2CIrqDeInit +// +// Description: +// I2C interrupt de-initialization function. +// According to the given I2C device number, the I2C interrupt will be unreigster +// from the platform and the relative interrupt handler will be cleared. +// +// Arguments: +// [in] VOID *Data - +// I2C SAL handle +// +// Return: +// The status of the I2C interrupt de-initialization process. +// _EXIT_SUCCESS if the RtkI2CIrqDeInit succeeded. +// _EXIT_FAILURE if the RtkI2CIrqDeInit failed. +// +// Note: +// NA +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-04-03. +// +//---------------------------------------------------------------------------------------------------- +static RTK_STATUS +RtkDACDMADeInit( + IN PSAL_DAC_HND pSalDACHND +){ + PSAL_DAC_HND_PRIV pSalDACHNDPriv = NULL; + PSAL_DAC_MNGT_ADPT pSalDACMngtAdpt = NULL; + + PHAL_GDMA_ADAPTER pHALDACGdmaAdpt = NULL; + PHAL_GDMA_OP pHALDACGdmaOp = NULL; + PIRQ_HANDLE pIrqHandleDACGdma = NULL; + + /*To Get the SAL_I2C_MNGT_ADPT Pointer*/ + pSalDACHNDPriv = CONTAINER_OF(pSalDACHND, SAL_DAC_HND_PRIV, SalDACHndPriv); + pSalDACMngtAdpt = CONTAINER_OF(pSalDACHNDPriv->ppSalDACHnd, SAL_DAC_MNGT_ADPT, pSalHndPriv); + + pHALDACGdmaAdpt = pSalDACMngtAdpt->pHalGdmaAdp; + pHALDACGdmaOp = pSalDACMngtAdpt->pHalGdmaOp; + pIrqHandleDACGdma = pSalDACMngtAdpt->pIrqGdmaHnd; + + if (RtkDACIdxChk(pSalDACHND->DevNum)) + return _EXIT_FAILURE; + + HalGdmaOpInit(pHALDACGdmaOp); + + pHALDACGdmaAdpt->IsrCtrl = DISABLE; + pHALDACGdmaOp->HalGdmaChIsrEnAndDis((VOID*)pHALDACGdmaAdpt); + pHALDACGdmaOp->HalGdmaChIsrClean((VOID*)pHALDACGdmaAdpt); + pHALDACGdmaOp->HalGdmaChDis((VOID*)pHALDACGdmaAdpt); + + InterruptUnRegister(pIrqHandleDACGdma); +#if 0 + _memset((void *)pIrqHandleDACGdma , 0, sizeof(IRQ_HANDLE)); + _memset((void *)pHALDACGdmaOp , 0, sizeof(HAL_GDMA_OP)); + _memset((void *)pHALDACGdmaAdpt , 0, sizeof(HAL_GDMA_ADAPTER)); +#endif + return _EXIT_SUCCESS; +} + +#endif + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// RtkI2CInit +// +// Description: +// According to the given I2C index, the related SAL_I2C_MNGT_ADPT pointer used +// for retrieving each I2C data sturcture pointer will be reversely parsed first. +// Then, initializing I2C HAL operation, initializing I2C interrupt (if needed), +// initializing I2C DMA (if needed) and initializing I2C pinmux will be done. +// User specified I2C configuration will be assigned to I2C initial data structure +// (PHAL_I2C_INIT_DAT pHalI2CInitDat). I2C HAL initialization is executed after +// all the configuration data taken. +// In the end, I2C module is enabled as a final step of the whole initialization. +// For a slave ack General Call support, an additional step may be followed after +// the above steps. +// +// Arguments: +// [in] VOID *Data - +// I2C SAL handle +// +// Return: +// The status of the I2C initialization process. +// _EXIT_SUCCESS if the RtkI2CInit succeeded. +// _EXIT_FAILURE if the RtkI2CInit failed. +// +// Note: +// NA +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-04-03. +// +//---------------------------------------------------------------------------------------------------- +RTK_STATUS +RtkDACInit( + IN VOID *Data +){ + PSAL_DAC_HND pSalDACHND = (PSAL_DAC_HND) Data; + PSAL_DAC_HND_PRIV pSalDACHNDPriv = NULL; + PSAL_DAC_MNGT_ADPT pSalDACMngtAdpt = NULL; + //PHAL_DAC_INIT_DAT pHalDACInitDat = NULL; + PHAL_DAC_OP pHalDACOP = NULL; + + u32 DacTemp; + + /* To Get the SAL_I2C_MNGT_ADPT Pointer */ + pSalDACHNDPriv = CONTAINER_OF(pSalDACHND, SAL_DAC_HND_PRIV, SalDACHndPriv); + pSalDACMngtAdpt = CONTAINER_OF(pSalDACHNDPriv->ppSalDACHnd, SAL_DAC_MNGT_ADPT, pSalHndPriv); + + //pHalDACInitDat = pSalDACMngtAdpt->pHalInitDat; + pHalDACOP = pSalDACMngtAdpt->pHalOp; + + /* Check the input I2C index first */ + if (RtkDACIdxChk(pSalDACHND->DevNum)) + return _EXIT_FAILURE; + +#if 0 + /* Check the input I2C operation type */ + if (RtkI2COpTypeChk(pSalI2CHND)) + return _EXIT_FAILURE; +#endif + + /* DAC Initialize HAL Operations */ + HalDACOpInit(pHalDACOP); + + /* DAC Interrupt Initialization */ +#if DAC_INTR_OP_TYPE + RtkDACIrqInit(pSalDACHND); +#endif + + /* DAC DMA Initialization */ +#if DAC_DMA_OP_TYPE + RtkDACDMAInit(pSalDACHND); +#endif + + + /* DAC Function and Clock Enable*/ + RtkDACPinMuxInit(pSalDACHND); + + pHalDACOP->HalDACInit(pSalDACHND->pInitDat); + + #if 1 + HAL_DAC_WRITE32(pSalDACHND->DevNum, REG_DAC_INTR_CTRL, + (BIT_DAC_FIFO_FULL_EN | + BIT_DAC_FIFO_OVERFLOW_EN | + BIT_DAC_FIFO_STOP_EN | + BIT_DAC__WRITE_ERROR_EN | + BIT_DAC_DSC_OVERFLOW0_EN | + BIT_DAC_DSC_OVERFLOW1_EN)); + #else + HAL_DAC_WRITE32(pSalDACHND->DevNum, REG_DAC_INTR_CTRL, + (BIT_DAC_FIFO_FULL_EN| + BIT_DAC_FIFO_OVERFLOW_EN| + BIT_DAC_FIFO_STOP_EN| + BIT_DAC__WRITE_ERROR_EN| + BIT_DAC_DSC_OVERFLOW0_EN| + BIT_DAC_DSC_OVERFLOW1_EN)); + #endif + DBG_DAC_INFO("INTR MSK:%x\n", HAL_DAC_READ32(pSalDACHND->DevNum,REG_DAC_INTR_CTRL)); + + + + DacTemp = HAL_DAC_READ32(pSalDACHND->DevNum, REG_DAC_ANAPAR_DA1); + DacTemp |= (BIT31); + HAL_DAC_WRITE32(pSalDACHND->DevNum, REG_DAC_ANAPAR_DA1, DacTemp); + //DBG_DAC_INFO("REG_DAC_ANAPAR_DA1:%08x\n",DacTemp); + DBG_DAC_INFO("REG_DAC_ANAPAR_DA1:%08x\n",HAL_DAC_READ32(pSalDACHND->DevNum, REG_DAC_ANAPAR_DA1)); + DacTemp = HAL_DAC_READ32(pSalDACHND->DevNum, REG_DAC_CTRL); + DacTemp |= BIT3; + HAL_DAC_WRITE32(pSalDACHND->DevNum, REG_DAC_CTRL, DacTemp); + DBG_DAC_INFO("REG_DAC_CTRL:%08x\n",DacTemp); + + pSalDACHND->pInitDat->DACEn = DAC_ENABLE; + pHalDACOP->HalDACEnable(pSalDACHND->pInitDat); + + /* DAC Device Status Update */ + pSalDACHND->DevSts = DAC_STS_IDLE; + + return _EXIT_SUCCESS; +} + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// RtkI2CInit +// +// Description: +// According to the given I2C index, the related SAL_I2C_MNGT_ADPT pointer used +// for retrieving each I2C data sturcture pointer will be reversely parsed first. +// Then, initializing I2C HAL operation, initializing I2C interrupt (if needed), +// initializing I2C DMA (if needed) and initializing I2C pinmux will be done. +// User specified I2C configuration will be assigned to I2C initial data structure +// (PHAL_I2C_INIT_DAT pHalI2CInitDat). I2C HAL initialization is executed after +// all the configuration data taken. +// In the end, I2C module is enabled as a final step of the whole initialization. +// For a slave ack General Call support, an additional step may be followed after +// the above steps. +// +// Arguments: +// [in] VOID *Data - +// I2C SAL handle +// +// Return: +// The status of the I2C initialization process. +// _EXIT_SUCCESS if the RtkI2CInit succeeded. +// _EXIT_FAILURE if the RtkI2CInit failed. +// +// Note: +// NA +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-04-03. +// +//---------------------------------------------------------------------------------------------------- +RTK_STATUS +RtkDACDeInit( + IN VOID *Data +){ + PSAL_DAC_HND pSalDACHND = (PSAL_DAC_HND) Data; + PSAL_DAC_HND_PRIV pSalDACHNDPriv = NULL; + PSAL_DAC_MNGT_ADPT pSalDACMngtAdpt = NULL; + PHAL_DAC_INIT_DAT pHalDACInitDat = NULL; + PHAL_DAC_OP pHalDACOP = NULL; + + /* To Get the SAL_DAC_MNGT_ADPT Pointer */ + pSalDACHNDPriv = CONTAINER_OF(pSalDACHND, SAL_DAC_HND_PRIV, SalDACHndPriv); + pSalDACMngtAdpt = CONTAINER_OF(pSalDACHNDPriv->ppSalDACHnd, SAL_DAC_MNGT_ADPT, pSalHndPriv); + + pHalDACInitDat = pSalDACMngtAdpt->pHalInitDat; + pHalDACOP = pSalDACMngtAdpt->pHalOp; + + /* Check the input DAC index first */ + if (RtkDACIdxChk(pSalDACHND->DevNum)) + return _EXIT_FAILURE; + + { + /* DAC Initialize HAL Operations */ + HalDACOpInit(pHalDACOP); + + /* DAC Interrupt Initialization */ +#if DAC_INTR_OP_TYPE + RtkDACIrqDeInit(pSalDACHND); +#endif + + /* DAC DMA Initialization */ +#if DAC_DMA_OP_TYPE + RtkDACDMADeInit(pSalDACHND); +#endif + + pHalDACInitDat->DACEn = DAC_DISABLE; + pHalDACOP->HalDACEnable(pHalDACInitDat); + pHalDACOP->HalDACDeInit(pHalDACInitDat); + + /* DAC Function and Clock Enable*/ + RtkDACPinMuxDeInit(pSalDACHND); + } + + return _EXIT_SUCCESS; +} + + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// RtkI2CInit +// +// Description: +// According to the given I2C index, the related SAL_I2C_MNGT_ADPT pointer used +// for retrieving each I2C data sturcture pointer will be reversely parsed first. +// Then, initializing I2C HAL operation, initializing I2C interrupt (if needed), +// initializing I2C DMA (if needed) and initializing I2C pinmux will be done. +// User specified I2C configuration will be assigned to I2C initial data structure +// (PHAL_I2C_INIT_DAT pHalI2CInitDat). I2C HAL initialization is executed after +// all the configuration data taken. +// In the end, I2C module is enabled as a final step of the whole initialization. +// For a slave ack General Call support, an additional step may be followed after +// the above steps. +// +// Arguments: +// [in] VOID *Data - +// I2C SAL handle +// +// Return: +// The status of the I2C initialization process. +// _EXIT_SUCCESS if the RtkI2CInit succeeded. +// _EXIT_FAILURE if the RtkI2CInit failed. +// +// Note: +// NA +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-04-03. +// +//---------------------------------------------------------------------------------------------------- +RTK_STATUS +RtkDACSend( + IN VOID *Data +){ + PSAL_DAC_HND pSalDACHND = (PSAL_DAC_HND) Data; + PSAL_DAC_HND_PRIV pSalDACHNDPriv = NULL; + PSAL_DAC_MNGT_ADPT pSalDACMngtAdpt = NULL; + PHAL_GDMA_ADAPTER pHALDACGdmaAdpt = NULL; + PHAL_GDMA_OP pHALDACGdmaOp = NULL; + PSAL_DAC_DMA_USER_DEF pSalDACDmaUserDef = NULL; + //PIRQ_HANDLE pIrqHandleDACGdma = NULL; + + /* To Get the SAL_I2C_MNGT_ADPT Pointer */ + pSalDACHNDPriv = CONTAINER_OF(pSalDACHND, SAL_DAC_HND_PRIV, SalDACHndPriv); + pSalDACMngtAdpt = CONTAINER_OF(pSalDACHNDPriv->ppSalDACHnd, SAL_DAC_MNGT_ADPT, pSalHndPriv); + + pHALDACGdmaAdpt = pSalDACMngtAdpt->pHalGdmaAdp; + pHALDACGdmaOp = pSalDACMngtAdpt->pHalGdmaOp; + pSalDACDmaUserDef = pSalDACMngtAdpt->pDMAConf; + + switch (pSalDACHND->DACInType) { + case DAC_INPUT_SINGLE_WR: + { + break; + } + case DAC_INPUT_DMA_ONEBLK: + { + HalGdmaOpInit(pHALDACGdmaOp); + + pHALDACGdmaAdpt->GdmaCtl.BlockSize = pSalDACHND->pTXBuf->DataLen; + pHALDACGdmaAdpt->ChSar = (u32)pSalDACHND->pTXBuf->pDataBuf; + pHALDACGdmaAdpt->ChDar = (u32)(DAC_REG_BASE+(pSalDACHND->DevNum*0x800)); + + DBG_DAC_INFO("src addr:%x\n", pHALDACGdmaAdpt->ChSar); + DBG_DAC_INFO("dst addr:%x\n", pHALDACGdmaAdpt->ChDar); + pHALDACGdmaOp->HalGdmaChSeting(pHALDACGdmaAdpt); + + pHALDACGdmaOp->HalGdmaChEn(pHALDACGdmaAdpt); + break; + } + case DAC_INPUT_DMA_LLP: + { + pHALDACGdmaAdpt->Rsvd4to7 = 1; + pHALDACGdmaAdpt->pLlix = (struct GDMA_CH_LLI *)pSalDACDmaUserDef->pLlix; + pHALDACGdmaAdpt->pBlockSizeList = (struct BLOCK_SIZE_LIST *)pSalDACDmaUserDef->pBlockSizeList; + pHALDACGdmaAdpt->ChDar = (u32)(DAC_REG_BASE+(pSalDACHND->DevNum*0x800)); + pHALDACGdmaOp->HalGdmaChBlockSeting(pHALDACGdmaAdpt); + + pHALDACGdmaOp->HalGdmaChEn(pHALDACGdmaAdpt); + break; + } + + default: + return _EXIT_FAILURE; + } + + + return _EXIT_SUCCESS; +} + + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// RtkI2CGetSalHnd +// +// Description: +// Allocation of lower layer memory spaces will be done by invoking RtkI2CGetMngtAdpt +// in this function and return a SAL_I2C_HND pointer to upper layer. +// According to the given I2C index, RtkI2CGetMngtAdpt will allocate all the memory +// space such as SAL_I2C_HND, HAL_I2C_INIT_DAT, SAL_I2C_USER_CB etc. +// +// +// Arguments: +// [in] u8 I2CIdx - +// I2C Index +// +// Return: +// PSAL_I2C_HND +// A pointer to SAL_I2C_HND which is allocated in the lower layer. +// Note: +// NA +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-04-03. +// +//---------------------------------------------------------------------------------------------------- +PSAL_DAC_HND +RtkDACGetSalHnd( + IN u8 DACIdx +){ + PSAL_DAC_MNGT_ADPT pSalDACMngtAdpt = NULL; + PSAL_DAC_HND pSalDACHND = NULL; + + /* Check the user define setting and the given index */ + if (RtkDACIdxChk(DACIdx)) { + return (PSAL_DAC_HND)NULL; + } + + /* Invoke RtkI2CGetMngtAdpt to get the I2C SAL management adapter pointer */ + pSalDACMngtAdpt = RtkDACGetMngtAdpt(DACIdx); + + /* Assign the private SAL handle to public SAL handle */ + pSalDACHND = &(pSalDACMngtAdpt->pSalHndPriv->SalDACHndPriv); + + /* Assign the internal HAL initial data pointer to the SAL handle */ + pSalDACHND->pInitDat = pSalDACMngtAdpt->pHalInitDat; + + /* Assign the internal user callback pointer to the SAL handle */ + pSalDACHND->pUserCB = pSalDACMngtAdpt->pUserCB; + + /* Assign the internal user DMA config to the SAL handle */ + pSalDACHND->pDMAConf = pSalDACMngtAdpt->pDMAConf; + + return &(pSalDACMngtAdpt->pSalHndPriv->SalDACHndPriv); +} + + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// RtkI2CGetSalHnd +// +// Description: +// Allocation of lower layer memory spaces will be done by invoking RtkI2CGetMngtAdpt +// in this function and return a SAL_I2C_HND pointer to upper layer. +// According to the given I2C index, RtkI2CGetMngtAdpt will allocate all the memory +// space such as SAL_I2C_HND, HAL_I2C_INIT_DAT, SAL_I2C_USER_CB etc. +// +// +// Arguments: +// [in] u8 I2CIdx - +// I2C Index +// +// Return: +// PSAL_I2C_HND +// A pointer to SAL_I2C_HND which is allocated in the lower layer. +// Note: +// NA +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-04-03. +// +//---------------------------------------------------------------------------------------------------- +RTK_STATUS +RtkDACFreeSalHnd( + IN PSAL_DAC_HND pSalDACHND +){ + PSAL_DAC_MNGT_ADPT pSalDACMngtAdpt = NULL; + PSAL_DAC_HND_PRIV pSalDACHNDPriv = NULL; + + /* To get the SAL_DAC_MNGT_ADPT pointer */ + pSalDACHNDPriv = CONTAINER_OF(pSalDACHND, SAL_DAC_HND_PRIV, SalDACHndPriv); + pSalDACMngtAdpt = CONTAINER_OF(pSalDACHNDPriv->ppSalDACHnd, SAL_DAC_MNGT_ADPT, pSalHndPriv); + + /* Invoke RtkDACFreeMngtAdpt to free all the lower layer memory space */ + return (RtkDACFreeMngtAdpt(pSalDACMngtAdpt)); + +} + + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// RtkI2CLoadDefault +// +// Description: +// Accrording the given I2C index, the default I2C configuration is done. +// +// +// Arguments: +// [in] PSAL_I2C_HND pSalI2CHND - +// SAL I2C handle +// +// Return: +// The status of the loading I2C default configuration. +// _EXIT_SUCCESS if the RtkI2CLoadDefault succeeded. +// _EXIT_FAILURE if the RtkI2CLoadDefault failed. +// +// Note: +// NA +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-04-03. +// +//---------------------------------------------------------------------------------------------------- +RTK_STATUS +RtkDACLoadDefault( + IN VOID *Data +){ + PSAL_DAC_HND pSalDACHND = (PSAL_DAC_HND) Data; + + /* Check the input DAC index first */ + if (RtkDACIdxChk(pSalDACHND->DevNum)) + return _EXIT_FAILURE; + + /* Load SAL handle default value */ + pSalDACHND->PinMux = 0; + pSalDACHND->OpType = DAC_POLL_TYPE; + pSalDACHND->DevSts = DAC_STS_UNINITIAL; + pSalDACHND->DACExd = 0; + pSalDACHND->ErrType = (u32)NULL; + + /* Load HAL initial data structure default value */ + pSalDACHND->pInitDat->DACIdx = pSalDACHND->DevNum; + pSalDACHND->pInitDat->DACEn = DAC_DISABLE; + pSalDACHND->pInitDat->DACDataRate = DAC_DATA_RATE_250K; + pSalDACHND->pInitDat->DACEndian = DAC_DATA_ENDIAN_LITTLE; + pSalDACHND->pInitDat->DACBurstSz = 7; + pSalDACHND->pInitDat->DACDbgSel = DAC_DBG_SEL_DISABLE; + pSalDACHND->pInitDat->DACDscDbgSel = DAC_DSC_DBG_SEL_DISABLE; + pSalDACHND->pInitDat->DACBPDsc = DAC_BYPASS_DSC_SEL_DISABLE; + pSalDACHND->pInitDat->DACDeltaSig = 0; + pSalDACHND->pInitDat->DACAnaCtrl0 = 0; + pSalDACHND->pInitDat->DACAnaCtrl1 = 0; + pSalDACHND->pInitDat->DACIntrMSK = DAC_FEATURE_DISABLED; + + /* Load DAC DMA user configuration default value */ + pSalDACHND->pDMAConf->MaxMultiBlk = 5000; + pSalDACHND->pDMAConf->TxDatSrcWdth = TrWidthFourBytes; + pSalDACHND->pDMAConf->TxDatSrcBstSz = MsizeFour; + pSalDACHND->pDMAConf->TxDatDstWdth = TrWidthFourBytes; + pSalDACHND->pDMAConf->TxDatDstBstSz = MsizeFour; + pSalDACHND->pDMAConf->TxChNo = 4; + + return _EXIT_SUCCESS; +} diff --git a/component/soc/realtek/8195a/fwlib/src/hal_gdma.c b/component/soc/realtek/8195a/fwlib/src/hal_gdma.c new file mode 100644 index 0000000..2014cc9 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/src/hal_gdma.c @@ -0,0 +1,358 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + + +#include "rtl8195a.h" +#include "hal_gdma.h" + +#define MAX_GDMA_INDX 1 +#define MAX_GDMA_CHNL 6 + +static u8 HalGdmaReg[MAX_GDMA_INDX+1]; + +const HAL_GDMA_CHNL GDMA_Chnl_Option[] = { + {0,0,GDMA0_CHANNEL0_IRQ,0}, + {1,0,GDMA1_CHANNEL0_IRQ,0}, + {0,1,GDMA0_CHANNEL1_IRQ,0}, + {1,1,GDMA1_CHANNEL1_IRQ,0}, + {0,2,GDMA0_CHANNEL2_IRQ,0}, + {1,2,GDMA1_CHANNEL2_IRQ,0}, + {0,3,GDMA0_CHANNEL3_IRQ,0}, + {1,3,GDMA1_CHANNEL3_IRQ,0}, + {0,4,GDMA0_CHANNEL4_IRQ,0}, + {1,4,GDMA1_CHANNEL4_IRQ,0}, + {0,5,GDMA0_CHANNEL5_IRQ,0}, + {1,5,GDMA1_CHANNEL5_IRQ,0}, + + {0xff,0,0,0} // end +}; + +const u16 HalGdmaChnlEn[6] = { + GdmaCh0, GdmaCh1, GdmaCh2, GdmaCh3, + GdmaCh4, GdmaCh5 +}; + +VOID HalGdmaOpInit( + IN VOID *Data +) +{ + PHAL_GDMA_OP pHalGdmaOp = (PHAL_GDMA_OP) Data; + + pHalGdmaOp->HalGdmaOnOff = HalGdmaOnOffRtl8195a; + pHalGdmaOp->HalGdamChInit = HalGdamChInitRtl8195a; + pHalGdmaOp->HalGdmaChDis = HalGdmaChDisRtl8195a; + pHalGdmaOp->HalGdmaChEn = HalGdmaChEnRtl8195a; + pHalGdmaOp->HalGdmaChSeting = HalGdmaChSetingRtl8195a; + pHalGdmaOp->HalGdmaChBlockSeting = HalGdmaChBlockSetingRtl8195a; + pHalGdmaOp->HalGdmaChIsrEnAndDis = HalGdmaChIsrEnAndDisRtl8195a; + pHalGdmaOp->HalGdmaChIsrClean = HalGdmaChIsrCleanRtl8195a; + pHalGdmaOp->HalGdmaChCleanAutoSrc = HalGdmaChCleanAutoSrcRtl8195a; + pHalGdmaOp->HalGdmaChCleanAutoDst = HalGdmaChCleanAutoDstRtl8195a; +} + +VOID HalGdmaOn(PHAL_GDMA_ADAPTER pHalGdmaAdapter) +{ + pHalGdmaAdapter->GdmaOnOff = ON; + HalGdmaOnOffRtl8195a((VOID*)pHalGdmaAdapter); +} + +VOID HalGdmaOff(PHAL_GDMA_ADAPTER pHalGdmaAdapter) +{ + pHalGdmaAdapter->GdmaOnOff = OFF; + HalGdmaOnOffRtl8195a((VOID*)pHalGdmaAdapter); +} + +BOOL HalGdmaChInit(PHAL_GDMA_ADAPTER pHalGdmaAdapter) +{ + return (HalGdamChInitRtl8195a((VOID*)pHalGdmaAdapter)); +} + +VOID HalGdmaChDis(PHAL_GDMA_ADAPTER pHalGdmaAdapter) +{ + HalGdmaChDisRtl8195a((VOID*)pHalGdmaAdapter); +} + +VOID HalGdmaChEn(PHAL_GDMA_ADAPTER pHalGdmaAdapter) +{ + HalGdmaChEnRtl8195a((VOID*)pHalGdmaAdapter); +} + +BOOL HalGdmaChSeting(PHAL_GDMA_ADAPTER pHalGdmaAdapter) +{ + return (HalGdmaChSetingRtl8195a((VOID*)pHalGdmaAdapter)); +} + +BOOL HalGdmaChBlockSeting(PHAL_GDMA_ADAPTER pHalGdmaAdapter) +{ + return (HalGdmaChBlockSetingRtl8195a((VOID*)pHalGdmaAdapter)); +} + +VOID HalGdmaChIsrEn(PHAL_GDMA_ADAPTER pHalGdmaAdapter) +{ + pHalGdmaAdapter->IsrCtrl = ENABLE; + HalGdmaChIsrEnAndDisRtl8195a((VOID*)pHalGdmaAdapter); +} + +VOID HalGdmaChIsrDis(PHAL_GDMA_ADAPTER pHalGdmaAdapter) +{ + pHalGdmaAdapter->IsrCtrl = DISABLE; + HalGdmaChIsrEnAndDisRtl8195a((VOID*)pHalGdmaAdapter); +} + +u8 HalGdmaChIsrClean(PHAL_GDMA_ADAPTER pHalGdmaAdapter) +{ + return (HalGdmaChIsrCleanRtl8195a((VOID*)pHalGdmaAdapter)); +} + +VOID HalGdmaChCleanAutoSrc(PHAL_GDMA_ADAPTER pHalGdmaAdapter) +{ + HalGdmaChCleanAutoSrcRtl8195a((VOID*)pHalGdmaAdapter); +} + +VOID HalGdmaChCleanAutoDst(PHAL_GDMA_ADAPTER pHalGdmaAdapter) +{ + HalGdmaChCleanAutoDstRtl8195a((VOID*)pHalGdmaAdapter); +} + +HAL_Status HalGdmaChnlRegister (u8 GdmaIdx, u8 ChnlNum) +{ + u32 mask; + + if ((GdmaIdx > MAX_GDMA_INDX) || (ChnlNum > MAX_GDMA_CHNL)) { + // Invalid GDMA Index or Channel Number + return HAL_ERR_PARA; + } + + mask = 1 << ChnlNum; + + if ((HalGdmaReg[GdmaIdx] & mask) != 0) { + return HAL_BUSY; + } + else { +#if 1 + if (HalGdmaReg[GdmaIdx] == 0) { + if (GdmaIdx == 0) { + ACTCK_GDMA0_CCTRL(ON); + GDMA0_FCTRL(ON); + } + else { + ACTCK_GDMA1_CCTRL(ON); + GDMA1_FCTRL(ON); + } + } +#endif + HalGdmaReg[GdmaIdx] |= mask; + return HAL_OK; + } +} + +VOID HalGdmaChnlUnRegister (u8 GdmaIdx, u8 ChnlNum) +{ + u32 mask; + + if ((GdmaIdx > MAX_GDMA_INDX) || (ChnlNum > MAX_GDMA_CHNL)) { + // Invalid GDMA Index or Channel Number + return; + } + + mask = 1 << ChnlNum; + + HalGdmaReg[GdmaIdx] &= ~mask; +#if 1 + if (HalGdmaReg[GdmaIdx] == 0) { + if (GdmaIdx == 0) { + ACTCK_GDMA0_CCTRL(OFF); + GDMA0_FCTRL(OFF); + } + else { + ACTCK_GDMA1_CCTRL(OFF); + GDMA1_FCTRL(OFF); + } + } +#endif +} + +PHAL_GDMA_CHNL HalGdmaChnlAlloc (HAL_GDMA_CHNL *pChnlOption) +{ + HAL_GDMA_CHNL *pgdma_chnl; + + pgdma_chnl = pChnlOption; + if (pChnlOption == NULL) { + // Use default GDMA Channel Option table + pgdma_chnl = (HAL_GDMA_CHNL*)&GDMA_Chnl_Option[0]; + } + + while (pgdma_chnl->GdmaIndx <= MAX_GDMA_INDX) { + if (HalGdmaChnlRegister(pgdma_chnl->GdmaIndx, pgdma_chnl->GdmaChnl) == HAL_OK) { + // This GDMA Channel is available + break; + } + pgdma_chnl += 1; + } + + if (pgdma_chnl->GdmaIndx > MAX_GDMA_INDX) { + pgdma_chnl = NULL; + } + + return pgdma_chnl; +} + +VOID HalGdmaChnlFree (HAL_GDMA_CHNL *pChnl) +{ + IRQ_HANDLE IrqHandle; + + IrqHandle.IrqNum = pChnl->IrqNum; + InterruptDis(&IrqHandle); + InterruptUnRegister(&IrqHandle); + HalGdmaChnlUnRegister(pChnl->GdmaIndx, pChnl->GdmaChnl); +} + +VOID HalGdmaMemIrqHandler(VOID *pData) +{ + PHAL_GDMA_OBJ pHalGdmaObj=(PHAL_GDMA_OBJ)pData; + PHAL_GDMA_ADAPTER pHalGdmaAdapter; + PIRQ_HANDLE pGdmaIrqHandle; + u8 IsrTypeMap; + + pHalGdmaAdapter = &(pHalGdmaObj->HalGdmaAdapter); + pGdmaIrqHandle = &(pHalGdmaObj->GdmaIrqHandle); + // Clean Auto Reload Bit + HalGdmaChCleanAutoDst((VOID*)pHalGdmaAdapter); + + // Clear Pending ISR + IsrTypeMap = HalGdmaChIsrClean((VOID*)pHalGdmaAdapter); + + HalGdmaChDis((VOID*)(pHalGdmaAdapter)); + pHalGdmaObj->Busy = 0; + + if (pGdmaIrqHandle->IrqFun != NULL) { + pGdmaIrqHandle->IrqFun((VOID*)pGdmaIrqHandle->Data); + } +} + +BOOL HalGdmaMemCpyInit(PHAL_GDMA_OBJ pHalGdmaObj) +{ + HAL_GDMA_CHNL *pgdma_chnl; + PHAL_GDMA_ADAPTER pHalGdmaAdapter; + PIRQ_HANDLE pGdmaIrqHandle; + IRQ_HANDLE IrqHandle; + + pgdma_chnl = HalGdmaChnlAlloc(NULL); // get a whatever GDMA channel + if (NULL == pgdma_chnl) { + DBG_GDMA_ERR("%s: Cannot allocate a GDMA Channel\n", __FUNCTION__); + return _FALSE; + } + + pHalGdmaAdapter = &(pHalGdmaObj->HalGdmaAdapter); + pGdmaIrqHandle = &(pHalGdmaObj->GdmaIrqHandle); + + DBG_GDMA_INFO("%s: Use GDMA%d CH%d\n", __FUNCTION__, pgdma_chnl->GdmaIndx, pgdma_chnl->GdmaChnl); +#if 0 + if (pgdma_chnl->GdmaIndx == 0) { + ACTCK_GDMA0_CCTRL(ON); + GDMA0_FCTRL(ON); + } + else if (pgdma_chnl->GdmaIndx == 1) { + ACTCK_GDMA1_CCTRL(ON); + GDMA1_FCTRL(ON); + } +#endif + _memset((void *)pHalGdmaAdapter, 0, sizeof(HAL_GDMA_ADAPTER)); + +// pHalGdmaAdapter->GdmaCtl.TtFc = TTFCMemToMem; + pHalGdmaAdapter->GdmaCtl.Done = 1; +// pHalGdmaAdapter->MuliBlockCunt = 0; +// pHalGdmaAdapter->MaxMuliBlock = 1; + pHalGdmaAdapter->ChNum = pgdma_chnl->GdmaChnl; + pHalGdmaAdapter->GdmaIndex = pgdma_chnl->GdmaIndx; + pHalGdmaAdapter->ChEn = 0x0101 << pgdma_chnl->GdmaChnl; + pHalGdmaAdapter->GdmaIsrType = (TransferType|ErrType); + pHalGdmaAdapter->IsrCtrl = ENABLE; + pHalGdmaAdapter->GdmaOnOff = ON; + + pHalGdmaAdapter->GdmaCtl.IntEn = 1; +// pHalGdmaAdapter->GdmaCtl.SrcMsize = MsizeEight; +// pHalGdmaAdapter->GdmaCtl.DestMsize = MsizeEight; +// pHalGdmaAdapter->GdmaCtl.SrcTrWidth = TrWidthFourBytes; +// pHalGdmaAdapter->GdmaCtl.DstTrWidth = TrWidthFourBytes; +// pHalGdmaAdapter->GdmaCtl.Dinc = IncType; +// pHalGdmaAdapter->GdmaCtl.Sinc = IncType; + + pGdmaIrqHandle->IrqNum = pgdma_chnl->IrqNum; + pGdmaIrqHandle->Priority = 10; + + IrqHandle.IrqFun = (IRQ_FUN) HalGdmaMemIrqHandler; + IrqHandle.Data = (u32) pHalGdmaObj; + IrqHandle.IrqNum = pGdmaIrqHandle->IrqNum; + IrqHandle.Priority = pGdmaIrqHandle->Priority; + + InterruptRegister(&IrqHandle); + InterruptEn(&IrqHandle); + pHalGdmaObj->Busy = 0; + + return _TRUE; +} + +VOID HalGdmaMemCpyDeInit(PHAL_GDMA_OBJ pHalGdmaObj) +{ + HAL_GDMA_CHNL GdmaChnl; + PHAL_GDMA_ADAPTER pHalGdmaAdapter; + PIRQ_HANDLE pGdmaIrqHandle; + + pHalGdmaAdapter = &(pHalGdmaObj->HalGdmaAdapter); + pGdmaIrqHandle = &(pHalGdmaObj->GdmaIrqHandle); + + GdmaChnl.GdmaIndx = pHalGdmaAdapter->GdmaIndex; + GdmaChnl.GdmaChnl = pHalGdmaAdapter->ChNum; + GdmaChnl.IrqNum = pGdmaIrqHandle->IrqNum; + HalGdmaChnlFree(&GdmaChnl); +} + +// If multi-task using the same GDMA Object, then it needs a mutex to protect this procedure +VOID* HalGdmaMemCpy(PHAL_GDMA_OBJ pHalGdmaObj, void* pDest, void* pSrc, u32 len) +{ + PHAL_GDMA_ADAPTER pHalGdmaAdapter; + + if (pHalGdmaObj->Busy) { + DBG_GDMA_ERR("%s: ==> GDMA is Busy\r\n", __FUNCTION__); + return 0; + } + pHalGdmaObj->Busy = 1; + pHalGdmaAdapter = &(pHalGdmaObj->HalGdmaAdapter); + + DBG_GDMA_INFO("%s: ==> Src=0x%x Dst=0x%x Len=%d\r\n", __FUNCTION__, pSrc, pDest, len); + if ((((u32)pSrc & 0x03)==0) && + (((u32)pDest & 0x03)==0) && + ((len & 0x03)== 0)) { + // 4-bytes aligned, move 4 bytes each transfer + pHalGdmaAdapter->GdmaCtl.SrcMsize = MsizeEight; + pHalGdmaAdapter->GdmaCtl.SrcTrWidth = TrWidthFourBytes; + pHalGdmaAdapter->GdmaCtl.DestMsize = MsizeEight; + pHalGdmaAdapter->GdmaCtl.DstTrWidth = TrWidthFourBytes; + pHalGdmaAdapter->GdmaCtl.BlockSize = len >> 2; + } + else { + pHalGdmaAdapter->GdmaCtl.SrcMsize = MsizeEight; + pHalGdmaAdapter->GdmaCtl.SrcTrWidth = TrWidthOneByte; + pHalGdmaAdapter->GdmaCtl.DestMsize = MsizeEight; + pHalGdmaAdapter->GdmaCtl.DstTrWidth = TrWidthOneByte; + pHalGdmaAdapter->GdmaCtl.BlockSize = len; + } + + pHalGdmaAdapter->ChSar = (u32)pSrc; + pHalGdmaAdapter->ChDar = (u32)pDest; + pHalGdmaAdapter->PacketLen = len; + + HalGdmaOn((pHalGdmaAdapter)); + HalGdmaChIsrEn((pHalGdmaAdapter)); + HalGdmaChSeting((pHalGdmaAdapter)); + HalGdmaChEn((pHalGdmaAdapter)); + + return (pDest); +} diff --git a/component/soc/realtek/8195a/fwlib/src/hal_gpio.c b/component/soc/realtek/8195a/fwlib/src/hal_gpio.c new file mode 100644 index 0000000..7c647d7 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/src/hal_gpio.c @@ -0,0 +1,144 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#include "rtl8195a.h" + +#ifdef CONFIG_GPIO_EN + +HAL_GPIO_DATA_SECTION HAL_GPIO_ADAPTER gHAL_Gpio_Adapter; +extern PHAL_GPIO_ADAPTER _pHAL_Gpio_Adapter; + +extern VOID GPIO_PullCtrl_8195a(u32 chip_pin, u8 pull_type); + +/** + * @brief To get the GPIO IP Pin name for the given chip pin name + * + * @param chip_pin: The chip pin name. + * + * @retval The gotten GPIO IP pin name + */ +HAL_GPIO_TEXT_SECTION u32 +HAL_GPIO_GetPinName( + u32 chip_pin +) +{ + return HAL_GPIO_GetIPPinName_8195a((u32)chip_pin); +} + +/** + * @brief Set the GPIO pad Pull type + * + * @param pin: The pin for pull type control. + * @param mode: the pull type for the pin. + * @return None + */ +VOID +HAL_GPIO_PullCtrl( + u32 pin, + u32 mode +) +{ + u8 pull_type; + + DBG_GPIO_INFO("%s: pin=0x%x mode=%d\n ", __FUNCTION__, (u32)pin, (u32)mode); + + switch (mode) { + case hal_PullNone: + pull_type = DIN_PULL_NONE; + break; + + case hal_PullDown: + pull_type = DIN_PULL_LOW; + break; + + case hal_PullUp: + pull_type = DIN_PULL_HIGH; + break; + + case hal_OpenDrain: + default: + pull_type = DIN_PULL_NONE; + break; + } + +// HAL_GPIO_PullCtrl_8195a (pin, pull_type); + GPIO_PullCtrl_8195a (pin, pull_type); +} + + +/** + * @brief Initializes a GPIO Pin by the GPIO_Pin parameters. + * + * @param GPIO_Pin: The data structer which contains the parameters for the GPIO Pin initialization. + * + * @retval HAL_Status + */ +HAL_GPIO_TEXT_SECTION VOID +HAL_GPIO_Init( + HAL_GPIO_PIN *GPIO_Pin +) +{ + if (_pHAL_Gpio_Adapter == NULL) { + _pHAL_Gpio_Adapter = &gHAL_Gpio_Adapter; + DBG_GPIO_INFO("%s: Initial GPIO Adapter\n ", __FUNCTION__); + } + + HAL_GPIO_Init_8195a(GPIO_Pin); +} + +/** + * @brief Initializes a GPIO Pin as a interrupt signal + * + * @param GPIO_Pin: The data structer which contains the parameters for the GPIO Pin initialization. + * + * @retval HAL_Status + */ +VOID +HAL_GPIO_Irq_Init( + HAL_GPIO_PIN *GPIO_Pin +) +{ + if (_pHAL_Gpio_Adapter == NULL) { + _pHAL_Gpio_Adapter = &gHAL_Gpio_Adapter; + DBG_GPIO_INFO("%s: Initial GPIO Adapter\n ", __FUNCTION__); + } + + if (_pHAL_Gpio_Adapter->IrqHandle.IrqFun == NULL) { + _pHAL_Gpio_Adapter->IrqHandle.IrqFun = HAL_GPIO_MbedIrqHandler_8195a; + _pHAL_Gpio_Adapter->IrqHandle.Priority = 0x10; + HAL_GPIO_RegIrq_8195a(&_pHAL_Gpio_Adapter->IrqHandle); + InterruptEn(&_pHAL_Gpio_Adapter->IrqHandle); + DBG_GPIO_INFO("%s: Initial GPIO IRQ Adapter\n ", __FUNCTION__); + } + + DBG_GPIO_INFO("%s: GPIO(name=0x%x)(mode=%d)\n ", __FUNCTION__, GPIO_Pin->pin_name, + GPIO_Pin->pin_mode); + HAL_GPIO_Init_8195a(GPIO_Pin); +} + +/** + * @brief UnInitial GPIO Adapter + * + * + * @retval HAL_Status + */ +VOID +HAL_GPIO_IP_DeInit( + VOID +) +{ + if (_pHAL_Gpio_Adapter != NULL) { + InterruptDis(&_pHAL_Gpio_Adapter->IrqHandle); + HAL_GPIO_UnRegIrq_8195a(&_pHAL_Gpio_Adapter->IrqHandle); + _pHAL_Gpio_Adapter = NULL; + } + +} + +#endif // CONFIG_GPIO_EN diff --git a/component/soc/realtek/8195a/fwlib/src/hal_i2c.c b/component/soc/realtek/8195a/fwlib/src/hal_i2c.c new file mode 100644 index 0000000..0b4e628 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/src/hal_i2c.c @@ -0,0 +1,2805 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#include "rtl8195a.h" +#include +#include "hal_i2c.h" + +//--------------------------------------------------------------------------------------------------- +//External functions +//--------------------------------------------------------------------------------------------------- +extern HAL_TIMER_OP HalTimerOp; + +#define I2C_STATIC_ALLOC 1 +/* I2C SAL global variables declaration when kernel disabled */ +#ifdef I2C_STATIC_ALLOC + HAL_I2C_OP HalI2COpSAL; +#endif + +#if I2C0_USED /*#if I2C0_USED*/ +#ifdef I2C_STATIC_ALLOC + SAL_I2C_MNGT_ADPT SalI2C0MngtAdpt; + + SAL_I2C_HND_PRIV SalI2C0HndPriv; + + HAL_I2C_INIT_DAT HalI2C0InitData; + + IRQ_HANDLE I2C0IrqHandleDat; + + HAL_GDMA_ADAPTER HalI2C0TxGdmaAdpt; + + HAL_GDMA_ADAPTER HalI2C0RxGdmaAdpt; + + HAL_GDMA_OP HalI2C0GdmaOp; + + IRQ_HANDLE I2C0TxGdmaIrqHandleDat; + + IRQ_HANDLE I2C0RxGdmaIrqHandleDat; + + SAL_I2C_USER_CB SalI2C0UserCB; + + SAL_I2C_USERCB_ADPT SalI2C0UserCBAdpt[SAL_USER_CB_NUM]; + + SAL_I2C_DMA_USER_DEF SalI2C0DmaUserDef; +#endif +#endif /*#if I2C0_USED*/ + +#if I2C1_USED /*#if I2C1_USED*/ +#ifdef I2C_STATIC_ALLOC + SAL_I2C_MNGT_ADPT SalI2C1MngtAdpt; + + SAL_I2C_HND_PRIV SalI2C1HndPriv; + + HAL_I2C_INIT_DAT HalI2C1InitData; + + IRQ_HANDLE I2C1IrqHandleDat; + + HAL_GDMA_ADAPTER HalI2C1TxGdmaAdpt; + + HAL_GDMA_ADAPTER HalI2C1RxGdmaAdpt; + + HAL_GDMA_OP HalI2C1GdmaOp; + + IRQ_HANDLE I2C1TxGdmaIrqHandleDat; + + IRQ_HANDLE I2C1RxGdmaIrqHandleDat; + + SAL_I2C_USER_CB SalI2C1UserCB; + + SAL_I2C_USERCB_ADPT SalI2C1UserCBAdpt[SAL_USER_CB_NUM]; + + SAL_I2C_DMA_USER_DEF SalI2C1DmaUserDef; +#endif +#endif /*#if I2C1_USED*/ + +#if I2C2_USED /*#if I2C2_USED*/ +#ifdef I2C_STATIC_ALLOC + + SAL_I2C_MNGT_ADPT SalI2C2MngtAdpt; + + SAL_I2C_HND_PRIV SalI2C2HndPriv; + + HAL_I2C_INIT_DAT HalI2C2InitData; + + IRQ_HANDLE I2C2IrqHandleDat; + + HAL_GDMA_ADAPTER HalI2C2TxGdmaAdpt; + + HAL_GDMA_ADAPTER HalI2C2RxGdmaAdpt; + + HAL_GDMA_OP HalI2C2GdmaOp; + + IRQ_HANDLE I2C2TxGdmaIrqHandleDat; + + IRQ_HANDLE I2C2RxGdmaIrqHandleDat; + + SAL_I2C_USER_CB SalI2C2UserCB; + + SAL_I2C_USERCB_ADPT SalI2C2UserCBAdpt[SAL_USER_CB_NUM]; + + SAL_I2C_DMA_USER_DEF SalI2C2DmaUserDef; +#endif +#endif /*#if I2C2_USED*/ + +#if I2C3_USED /*#if I2C3_USED*/ +#ifdef I2C_STATIC_ALLOC + + SAL_I2C_MNGT_ADPT SalI2C3MngtAdpt; + + SAL_I2C_HND_PRIV SalI2C3HndPriv; + + HAL_I2C_INIT_DAT HalI2C3InitData; + + IRQ_HANDLE I2C3IrqHandleDat; + + HAL_GDMA_ADAPTER HalI2C3TxGdmaAdpt; + + HAL_GDMA_ADAPTER HalI2C3RxGdmaAdpt; + + HAL_GDMA_OP HalI2C3GdmaOp; + + IRQ_HANDLE I2C3TxGdmaIrqHandleDat; + + IRQ_HANDLE I2C3RxGdmaIrqHandleDat; + + SAL_I2C_USER_CB SalI2C3UserCB; + + SAL_I2C_USERCB_ADPT SalI2C3UserCBAdpt[SAL_USER_CB_NUM]; + + SAL_I2C_DMA_USER_DEF SalI2C3DmaUserDef; +#endif +#endif /*#if I2C3_USED*/ + +/* Used only for A~C Version */ +#ifndef CONFIG_CHIP_D_CUT +//--------------------------------------------------------------------------------------------------- +//Function Name: +// HalI2CSendRtl8195a +// +// Description: +// Send one byte to the I2C internal fifo, it will generate START and STOP bit +// automatically. +// +// Arguments: +// [in] VOID *Data - +// The I2C parameter data struct. +// +// Return: +// _EXIT_SUCCESS if the sending succeeded. +// _EXIT_FAILURE if the sending failed. +// +// Note: +// None +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-02-18. +// +//--------------------------------------------------------------------------------------------------- +HAL_Status +HalI2CSendRtl8195a( + IN VOID *Data +){ + PHAL_I2C_INIT_DAT pHalI2CInitData = (PHAL_I2C_INIT_DAT)Data; + u8 I2CIdx = pHalI2CInitData->I2CIdx; + u8 *pDat = pHalI2CInitData->I2CRWData; + u8 I2CCmd = pHalI2CInitData->I2CCmd; + u8 I2CStop = pHalI2CInitData->I2CStop; + u8 I2CReSTR= pHalI2CInitData->I2CReSTR; + + DBG_I2C_INFO("HalI2CSendRtl8195a\n"); + DBG_I2C_INFO("I2C Index: %x\n",I2CIdx); + + HAL_I2C_WRITE32(I2CIdx,REG_DW_I2C_IC_DATA_CMD, + *(pDat) | + BIT_CTRL_IC_DATA_CMD_RESTART(I2CReSTR)| + BIT_CTRL_IC_DATA_CMD_CMD(I2CCmd) | + BIT_CTRL_IC_DATA_CMD_STOP(I2CStop)); + + return (HAL_OK); +} + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// HalI2CInit8195a +// +// Description: +// To initialize I2C module by using the given data. +// +// Arguments: +// [in] VOID *Data - +// The I2C parameter data struct. +// +// Return: +// The status of the DeInit process. +// _EXIT_SUCCESS if the initialization succeeded. +// _EXIT_FAILURE if the initialization failed. +// +// Note: +// None +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-04-02. +// +//--------------------------------------------------------------------------------------------------- +HAL_Status +HalI2CInit8195a( + IN VOID *Data +) +{ + PHAL_I2C_INIT_DAT pHalI2CInitData = (PHAL_I2C_INIT_DAT)Data; + + u8 Master; + u8 I2CIdx; + u8 SpdMd; + u8 AddrMd; + u8 ReSTR; + u8 StartByte; + u8 Specical; + u8 GC; + u16 I2CAckAddr; + u16 SdaHd; + u8 SdaSetup; + u8 RXTL; + u8 TXTL; + u8 SlvNoAck; + u32 INTRMsk; + u8 TxDMARqLv; + u8 RxDMARqLv; + + /* Get the I2C parameters*/ + I2CIdx = pHalI2CInitData->I2CIdx; + SpdMd = pHalI2CInitData->I2CSpdMod; + AddrMd = pHalI2CInitData->I2CAddrMod; + I2CAckAddr = pHalI2CInitData->I2CAckAddr; + Master = pHalI2CInitData->I2CMaster; + SdaHd = pHalI2CInitData->I2CSdaHd; + SdaSetup = pHalI2CInitData->I2CSetup; + + ReSTR = pHalI2CInitData->I2CReSTR; + GC = pHalI2CInitData->I2CGC; + StartByte = pHalI2CInitData->I2CStartB; + SlvNoAck = pHalI2CInitData->I2CSlvNoAck; + + RXTL = pHalI2CInitData->I2CRXTL; + TXTL = pHalI2CInitData->I2CTXTL; + + TxDMARqLv = pHalI2CInitData->I2CTxDMARqLv; + RxDMARqLv = pHalI2CInitData->I2CRxDMARqLv; + + /* Disable the IC first */ + HAL_I2C_WRITE32(I2CIdx,REG_DW_I2C_IC_ENABLE,BIT_CTRL_IC_ENABLE(0)); + + /* Master case*/ + if (Master) { + /*RESTART MUST be set in these condition in Master mode. + But it might be NOT compatible in old slaves.*/ + if ((AddrMd == I2C_ADDR_10BIT) || (SpdMd == I2C_HS_MODE)) + ReSTR = 1; + + HAL_I2C_WRITE32(I2CIdx,REG_DW_I2C_IC_CON, + (BIT_CTRL_IC_CON_IC_SLAVE_DISABLE(1) | + BIT_CTRL_IC_CON_IC_RESTART_EN(ReSTR) | + BIT_CTRL_IC_CON_IC_10BITADDR_MASTER(AddrMd) | + BIT_CTRL_IC_CON_SPEED(SpdMd) | + BIT_CTRL_IC_CON_MASTER_MODE(Master))); + + DBG_I2C_INFO("Init master, IC_CON%d[%2x]: %x\n", I2CIdx, REG_DW_I2C_IC_CON, HAL_I2C_READ32(I2CIdx,REG_DW_I2C_IC_CON)); + + + /* To set target addr.*/ + Specical = 0; + if ((GC!=0) || (StartByte!=0)) + Specical = 1; + HAL_I2C_WRITE32(I2CIdx,REG_DW_I2C_IC_TAR, + (BIT_CTRL_IC_TAR_IC_10BITADDR_MASTER(AddrMd) | + BIT_CTRL_IC_TAR_SPECIAL(Specical) | + BIT_CTRL_IC_TAR_GC_OR_START(StartByte) | + BIT_CTRL_IC_TAR(I2CAckAddr))); + + /* To Set I2C clock*/ + HalI2CSetCLKRtl8195a(pHalI2CInitData); + + + DBG_I2C_INFO("Init master, IC_TAR%d[%2x]: %x\n", I2CIdx, REG_DW_I2C_IC_TAR, HAL_I2C_READ32(I2CIdx,REG_DW_I2C_IC_TAR)); + + } /*if (Master)*/ + else { + HAL_I2C_WRITE32(I2CIdx,REG_DW_I2C_IC_CON, + BIT_CTRL_IC_CON_IC_10BITADDR_SLAVE(AddrMd) | + BIT_CTRL_IC_CON_IC_SLAVE_DISABLE(Master) | + BIT_CTRL_IC_CON_SPEED(SpdMd)| + BIT_CTRL_IC_CON_MASTER_MODE(Master)); + + DBG_I2C_INFO("Init slave, IC_CON%d[%2x]: %x\n", I2CIdx, REG_DW_I2C_IC_CON, HAL_I2C_READ32(I2CIdx,REG_DW_I2C_IC_CON)); + + + /* To set slave addr. */ + HAL_I2C_WRITE32(I2CIdx,REG_DW_I2C_IC_SAR,BIT_CTRL_IC_SAR(I2CAckAddr)); + + DBG_I2C_INFO("Init slave, IC_SAR%d[%2x]: %x\n", I2CIdx, REG_DW_I2C_IC_SAR, HAL_I2C_READ32(I2CIdx,REG_DW_I2C_IC_SAR)); + + + /* To set slave no ack */ + HAL_I2C_WRITE32(I2CIdx,REG_DW_I2C_IC_SLV_DATA_NACK_ONLY,BIT_CTRL_IC_SLV_DATA_NACK_ONLY(SlvNoAck)); + + /* Set ack general call. */ + HAL_I2C_WRITE32(I2CIdx,REG_DW_I2C_IC_ACK_GENERAL_CALL,BIT_CTRL_IC_ACK_GENERAL_CALL(pHalI2CInitData->I2CSlvAckGC)); + + + + DBG_I2C_INFO("Init slave, I2C_IC_ACK_GC%d[%2x]: %x\n", I2CIdx, REG_DW_I2C_IC_ACK_GENERAL_CALL, HAL_I2C_READ32(I2CIdx,REG_DW_I2C_IC_ACK_GENERAL_CALL)); + + /* to set SDA hold time */ + HAL_I2C_WRITE32(I2CIdx,REG_DW_I2C_IC_SDA_HOLD,BIT_CTRL_IC_SDA_HOLD(SdaHd)); + //4 + /* to set SDA setup time */ + HAL_I2C_WRITE32(I2CIdx,REG_DW_I2C_IC_SDA_SETUP,BIT_CTRL_IC_SDA_SETUP(SdaSetup)); + } + + /* To set TX_Empty Level */ + HAL_I2C_WRITE32(I2CIdx,REG_DW_I2C_IC_TX_TL,TXTL); + + /* To set RX_Full Level */ + HAL_I2C_WRITE32(I2CIdx,REG_DW_I2C_IC_RX_TL,RXTL); + + /* To set TX/RX FIFO level */ + HAL_I2C_WRITE32(I2CIdx,REG_DW_I2C_IC_DMA_TDLR,TxDMARqLv); + HAL_I2C_WRITE32(I2CIdx,REG_DW_I2C_IC_DMA_RDLR,RxDMARqLv); + + + DBG_I2C_INFO("Init i2c dev, I2C_IC_DMA_TDLR%d[%2x]: %x\n", I2CIdx, REG_DW_I2C_IC_DMA_TDLR, HAL_I2C_READ32(I2CIdx,REG_DW_I2C_IC_DMA_TDLR)); + DBG_I2C_INFO("Init i2c dev, I2C_IC_DMA_RDLR%d[%2x]: %x\n", I2CIdx, REG_DW_I2C_IC_DMA_RDLR, HAL_I2C_READ32(I2CIdx,REG_DW_I2C_IC_DMA_RDLR)); + + + /*I2C Clear all interrupts first*/ + HalI2CClrAllIntrRtl8195a(pHalI2CInitData); + + /*I2C Disable all interrupts first*/ + INTRMsk = pHalI2CInitData->I2CIntrMSK; + pHalI2CInitData->I2CIntrMSK = 0; + HalI2CIntrCtrl8195a(pHalI2CInitData); + pHalI2CInitData->I2CIntrMSK = INTRMsk; + + return HAL_OK; +} + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// HalI2CSetCLKRtl8195a +// +// Description: +// To set I2C bus clock rate. +// +// Arguments: +// [in] VOID *Data - +// The I2C parameter data struct. +// +// Return: +// The status of the enable process. +// _EXIT_SUCCESS if the de-initialization succeeded. +// _EXIT_FAILURE if the de-initialization failed. +// +// Note: +// None +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-02-18. +// +//--------------------------------------------------------------------------------------------------- +HAL_Status +HalI2CSetCLKRtl8195a( + IN VOID *Data +) +{ + PHAL_I2C_INIT_DAT pHalI2CInitData = (PHAL_I2C_INIT_DAT)Data; + u8 SpdMd = pHalI2CInitData->I2CSpdMod; + u32 I2CClk = pHalI2CInitData->I2CClk; + u8 I2CIdx = pHalI2CInitData->I2CIdx; + u32 ICHLcnt; + u32 ICHtime; + u32 ICLtime; + + /* Get the IC-Clk setting first for the following process*/ +#ifdef CONFIG_FPGA + u32 IcClk = SYSTEM_CLK/1000000; +#else + u32 IcClk; + u32 ClkSELTmp = 0; + u32 CpuClkTmp = 0; + + #if CONFIG_CHIP_A_CUT + CpuClkTmp = StartupHalGetCpuClk(); + #elif CONFIG_CHIP_B_CUT + CpuClkTmp = HalGetCpuClk(); + #endif + + DBG_I2C_INFO("%s, CPU Clk:%x\n",__func__, CpuClkTmp); + + ClkSELTmp = HAL_READ32(PERI_ON_BASE, REG_PESOC_CLK_SEL); + ClkSELTmp &= (~(BIT_PESOC_PERI_SCLK_SEL(3))); + HAL_WRITE32(PERI_ON_BASE,REG_PESOC_CLK_SEL,ClkSELTmp); + IcClk = (CpuClkTmp/1000000)>>1; + +#if 0 + if ((I2CClk > 0) && (I2CClk <= 400)) { + ClkSELTmp &= (~(BIT_PESOC_PERI_SCLK_SEL(3))); + HAL_WRITE32(PERI_ON_BASE,REG_PESOC_CLK_SEL,ClkSELTmp); + IcClk = ClkSELTmp/1000000; /*actually it's 12.5MHz*/ + } + else { + ClkSELTmp &= (~(BIT_PESOC_PERI_SCLK_SEL(3))); + HAL_WRITE32(PERI_ON_BASE,REG_PESOC_CLK_SEL,ClkSELTmp); + IcClk = 100; + } +#endif +#endif + + switch (SpdMd) + { + case I2C_SS_MODE: + { + ICHtime = ((1000000/I2CClk)*I2C_SS_MIN_SCL_HTIME)/(I2C_SS_MIN_SCL_HTIME+I2C_SS_MIN_SCL_LTIME); + ICLtime = ((1000000/I2CClk)*I2C_SS_MIN_SCL_LTIME)/(I2C_SS_MIN_SCL_HTIME+I2C_SS_MIN_SCL_LTIME); + + ICHLcnt = (ICHtime * IcClk)/1000; + HAL_I2C_WRITE32(I2CIdx,REG_DW_I2C_IC_SS_SCL_HCNT,ICHLcnt); + + + DBG_I2C_INFO("IC_SS_SCL_HCNT%d[%2x]: %x\n", I2CIdx, + REG_DW_I2C_IC_SS_SCL_HCNT, HAL_I2C_READ32(I2CIdx,REG_DW_I2C_IC_SS_SCL_HCNT)); + + + ICHLcnt = (ICLtime * IcClk)/1000; + HAL_I2C_WRITE32(I2CIdx,REG_DW_I2C_IC_SS_SCL_LCNT,ICHLcnt); + + + DBG_I2C_INFO("IC_SS_SCL_LCNT%d[%2x]: %x\n", I2CIdx, + REG_DW_I2C_IC_SS_SCL_LCNT, HAL_I2C_READ32(I2CIdx,REG_DW_I2C_IC_SS_SCL_LCNT)); + + break; + } + + case I2C_FS_MODE: + { + ICHtime = ((1000000/I2CClk)*I2C_FS_MIN_SCL_HTIME)/(I2C_FS_MIN_SCL_HTIME+I2C_FS_MIN_SCL_LTIME); + ICLtime = ((1000000/I2CClk)*I2C_FS_MIN_SCL_LTIME)/(I2C_FS_MIN_SCL_HTIME+I2C_FS_MIN_SCL_LTIME); + + ICHLcnt = (ICHtime * IcClk)/1000; + if (ICHLcnt>4)/*this part is according to the fine-tune result*/ + ICHLcnt -= 4; + HAL_I2C_WRITE32(I2CIdx,REG_DW_I2C_IC_FS_SCL_HCNT,ICHLcnt); + + + DBG_I2C_INFO("IC_FS_SCL_HCNT%d[%2x]: %x\n", I2CIdx, + REG_DW_I2C_IC_FS_SCL_HCNT, HAL_I2C_READ32(I2CIdx,REG_DW_I2C_IC_FS_SCL_HCNT)); + + + ICHLcnt = (ICLtime * IcClk)/1000; + if (ICHLcnt>3)/*this part is according to the fine-tune result*/ + ICHLcnt -= 3; + HAL_I2C_WRITE32(I2CIdx,REG_DW_I2C_IC_FS_SCL_LCNT,ICHLcnt); + + + DBG_I2C_INFO("IC_FS_SCL_LCNT%d[%2x]: %x\n", I2CIdx, + REG_DW_I2C_IC_FS_SCL_LCNT, HAL_I2C_READ32(I2CIdx,REG_DW_I2C_IC_FS_SCL_LCNT)); + + break; + } + + case I2C_HS_MODE: + { + ICHLcnt = 400; + HAL_I2C_WRITE32(I2CIdx,REG_DW_I2C_IC_SS_SCL_HCNT,ICHLcnt); + + ICHLcnt = 470; + HAL_I2C_WRITE32(I2CIdx,REG_DW_I2C_IC_SS_SCL_LCNT,ICHLcnt); + + ICHLcnt = 60; + HAL_I2C_WRITE32(I2CIdx,REG_DW_I2C_IC_FS_SCL_HCNT,ICHLcnt); + + ICHLcnt = 130; + HAL_I2C_WRITE32(I2CIdx,REG_DW_I2C_IC_FS_SCL_LCNT,ICHLcnt); + + ICHtime = ((1000000/I2CClk)*I2C_HS_MIN_SCL_HTIME_100)/(I2C_HS_MIN_SCL_HTIME_100+I2C_HS_MIN_SCL_LTIME_100); + ICLtime = ((1000000/I2CClk)*I2C_HS_MIN_SCL_LTIME_100)/(I2C_HS_MIN_SCL_HTIME_100+I2C_HS_MIN_SCL_LTIME_100); + + + DBG_I2C_INFO("ICHtime:%x\n",ICHtime); + DBG_I2C_INFO("ICLtime:%x\n",ICLtime); + + + ICHLcnt = (ICHtime * IcClk)/1000; + if (ICHLcnt>8)/*this part is according to the fine-tune result*/ + ICHLcnt -= 3; + HAL_I2C_WRITE32(I2CIdx,REG_DW_I2C_IC_HS_SCL_HCNT,ICHLcnt); + + + DBG_I2C_INFO("IC_HS_SCL_HCNT%d[%2x]: %x\n", I2CIdx, + REG_DW_I2C_IC_HS_SCL_HCNT, HAL_I2C_READ32(I2CIdx,REG_DW_I2C_IC_HS_SCL_HCNT)); + + + ICHLcnt = (ICLtime * IcClk)/1000; + if (ICHLcnt>6)/*this part is according to the fine-tune result*/ + ICHLcnt -= 6; + HAL_I2C_WRITE32(I2CIdx,REG_DW_I2C_IC_HS_SCL_LCNT,ICHLcnt); + + + DBG_I2C_INFO("IC_HS_SCL_LCNT%d[%2x]: %x\n", I2CIdx, + REG_DW_I2C_IC_HS_SCL_LCNT, HAL_I2C_READ32(I2CIdx,REG_DW_I2C_IC_HS_SCL_LCNT)); + + + break; + } + + default: + break; + } + + return HAL_OK; +} + + +VOID +HalI2COpInit( + IN VOID *Data +) +{ + PHAL_I2C_OP pHalI2COp = (PHAL_I2C_OP) Data; + + pHalI2COp->HalI2CInit = HalI2CInit8195a; + DBG_I2C_INFO("HalOpInit->HalI2CInit:%x\n",pHalI2COp->HalI2CInit); + + pHalI2COp->HalI2CDeInit = HalI2CDeInit8195a; + DBG_I2C_INFO("HalOpInit->HalI2CDeInit:%x\n",pHalI2COp->HalI2CDeInit); + + pHalI2COp->HalI2CSend = HalI2CSendRtl8195a; + DBG_I2C_INFO("HalOpInit->HalI2CSend:%x\n",pHalI2COp->HalI2CSend); + + pHalI2COp->HalI2CReceive = HalI2CReceiveRtl8195a; + DBG_I2C_INFO("HalOpInit->HalI2CReceive:%x\n",pHalI2COp->HalI2CReceive); + + pHalI2COp->HalI2CEnable = HalI2CEnableRtl8195a; + DBG_I2C_INFO("HalOpInit->HalI2CEnable:%x\n",pHalI2COp->HalI2CEnable); + + pHalI2COp->HalI2CIntrCtrl = HalI2CIntrCtrl8195a; + DBG_I2C_INFO("HalOpInit->HalI2CIntrCtrl:%x\n",pHalI2COp->HalI2CIntrCtrl); + + pHalI2COp->HalI2CReadReg = HalI2CReadRegRtl8195a; + DBG_I2C_INFO("HalOpInit->HalI2CReadReg:%x\n",pHalI2COp->HalI2CReadReg); + + pHalI2COp->HalI2CWriteReg = HalI2CWriteRegRtl8195a; + DBG_I2C_INFO("pHalI2COp->HalI2CWriteReg:%x\n",pHalI2COp->HalI2CWriteReg); + + pHalI2COp->HalI2CSetCLK = HalI2CSetCLKRtl8195a; + DBG_I2C_INFO("HalOpInit->HalI2CSetCLK:%x\n",pHalI2COp->HalI2CSetCLK); + + pHalI2COp->HalI2CMassSend = HalI2CMassSendRtl8195a; + DBG_I2C_INFO("HalOpInit->HalI2CMassSend:%x\n",pHalI2COp->HalI2CMassSend); + + pHalI2COp->HalI2CClrIntr = HalI2CClrIntrRtl8195a; + DBG_I2C_INFO("HalOpInit->HalI2CClrIntr:%x\n",pHalI2COp->HalI2CClrIntr); + + pHalI2COp->HalI2CClrAllIntr = HalI2CClrAllIntrRtl8195a; + DBG_I2C_INFO("HalOpInit->HalI2CClrAllIntr:%x\n",pHalI2COp->HalI2CClrAllIntr); + + pHalI2COp->HalI2CDMACtrl = HalI2CDMACtrl8195a; + DBG_I2C_INFO("HalOpInit->HalI2CDMACtrl:%x\n",pHalI2COp->HalI2CDMACtrl); +} + + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// I2CISRHandle +// +// Description: +// I2C Interrupt Service Routine. +// According to the input pointer to SAL_I2C_HND, all the rest pointers will be +// found and be used to the rest part of this servie routine. +// The following types of interrupt will be taken care: +// - General Call (providing General Call Callback). Slave receives a general call. +// - STOP Bit (NOT providing General Call Callback) +// - START Bit (NOTproviding General Call Callback) +// - I2C Activity (NOTproviding General Call Callback) +// - RX Done (providing Error Callback). The slave transmitter does NOT +// receive a proper NACK for the end of whole transfer. +// - TX Abort (providing Error Call Callback). The Master/Slave +// transmitting is terminated. +// - RD Req (providing TX and TXC Callback). Slave gets a Read Request +// and starts a slave-transmitter operation. The slave transmit +// data will be written into slave TX FIFO from user data buffer. +// - TX Empty (providing TX and TXC Callback). Master TX FIFO is empty. +// The user transmit data will be written into master TX FIFO +// from user data buffer. +// - TX Over (providing Error Callback). Master TX FIFO is Overflow. +// - RX Full (providing RX and RXC Callback). Master/Slave RX FIFO contains +// data. And the received data will be put into Master/Slave user +// receive data buffer. +// - RX Over (providing Error Callback). Master/Slave RX FIFO is Overflow. +// - RX Under (providing Error Callback). Master/Slave RX FIFO is Underflow. +// +// Arguments: +// [in] VOID *Data - +// I2C SAL handle +// +// Return: +// NA +// +// Note: +// NA +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-04-02. +// +//---------------------------------------------------------------------------------------------------- +VOID +I2CISRHandle( + IN VOID *Data +){ + PSAL_I2C_HND pSalI2CHND = (PSAL_I2C_HND) Data; + PSAL_I2C_HND_PRIV pSalI2CHNDPriv = NULL; + PSAL_I2C_MNGT_ADPT pSalI2CMngtAdpt = NULL; + PHAL_I2C_INIT_DAT pHalI2CInitDat = NULL; + PHAL_I2C_OP pHalI2COP = NULL; + PSAL_I2C_USER_CB pSalI2CUserCB = NULL; + u32 I2CLocalTemp = 0; + u32 I2CInTOTcnt = 0; + u32 I2CIrqIdx = 0; + u32 InTimeoutCount = 0; + u32 InStartCount = 0; + volatile u32 I2CLocalRawSts = 0; + + + /* To get the SAL_I2C_MNGT_ADPT pointer, and parse the rest pointers */ + pSalI2CHNDPriv = CONTAINER_OF(pSalI2CHND, SAL_I2C_HND_PRIV, SalI2CHndPriv); + pSalI2CMngtAdpt = CONTAINER_OF(pSalI2CHNDPriv->ppSalI2CHnd, SAL_I2C_MNGT_ADPT, pSalHndPriv); + pHalI2CInitDat = pSalI2CMngtAdpt->pHalInitDat; + pHalI2COP = pSalI2CMngtAdpt->pHalOp; + I2CInTOTcnt = pSalI2CMngtAdpt->InnerTimeOut; + I2CIrqIdx = pHalI2CInitDat->I2CIdx; + pSalI2CUserCB = pSalI2CHND->pUserCB; + //DBG_8195A("NEW ISR\n"); + /* I2C General Call Intr*/ + if (pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_INTR_STAT) & + BIT_CTRL_IC_INTR_STAT_R_GEN_CALL(1)) { + + DBG_I2C_WARN("I2C%d INTR_GEN_CALL\n",I2CIrqIdx); + + /* Clear I2C interrupt */ + pHalI2CInitDat->I2CIntrClr = REG_DW_I2C_IC_CLR_GEN_CALL; + pHalI2COP->HalI2CClrIntr(pHalI2CInitDat); + + /* Invoke I2C General Call callback if available*/ + if (pSalI2CUserCB->pGENCALLCB->USERCB != NULL) { + pSalI2CUserCB->pGENCALLCB->USERCB((void *)pSalI2CUserCB->pGENCALLCB->USERData); + } + } + + /* I2C START DET Intr */ + if (pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_INTR_STAT) & + BIT_CTRL_IC_INTR_STAT_R_START_DET(1)) { + + DBG_I2C_WARN("I2C%d INTR_START_DET\n",I2CIrqIdx); + + /* Clear I2C interrupt */ + pHalI2CInitDat->I2CIntrClr = REG_DW_I2C_IC_CLR_START_DET; + pHalI2COP->HalI2CClrIntr(pHalI2CInitDat); + } + + /* I2C STOP DET Intr */ + if (pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_INTR_STAT) & + BIT_CTRL_IC_INTR_STAT_R_STOP_DET(1)) { + + DBG_I2C_WARN("I2C%d INTR_STOP_DET\n",I2CIrqIdx); + + /* Clear I2C interrupt */ + pHalI2CInitDat->I2CIntrClr = REG_DW_I2C_IC_CLR_STOP_DET; + pHalI2COP->HalI2CClrIntr(pHalI2CInitDat); + } + + /* I2C Activity Intr */ + if (pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_INTR_STAT) & + BIT_CTRL_IC_INTR_STAT_R_ACTIVITY(1)) { + + DBG_I2C_WARN("I2C%d INTR_ACTIVITY\n",I2CIrqIdx); + + /* Clear I2C interrupt */ + pHalI2CInitDat->I2CIntrClr = REG_DW_I2C_IC_CLR_ACTIVITY; + pHalI2COP->HalI2CClrIntr(pHalI2CInitDat); + } + + /* I2C RX Done Intr */ + if (pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_INTR_STAT) & + BIT_CTRL_IC_INTR_STAT_R_RX_DONE(1)) { + //DBG_8195A("rxdone\n"); + DBG_I2C_ERR("I2C%d INTR_RX_DONE\n",I2CIrqIdx); + DBG_I2C_ERR("I2C%d IC_TXFLR:%2x\n",I2CIrqIdx, + pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_TXFLR)); + + /* Clear I2C interrupt */ + pHalI2CInitDat->I2CIntrClr = REG_DW_I2C_IC_CLR_RX_DONE; + pHalI2COP->HalI2CClrIntr(pHalI2CInitDat); + + /* Update I2C device status */ + pSalI2CHND->DevSts = I2C_STS_ERROR; + + /* Update I2C error type */ + pSalI2CHND->ErrType |= I2C_ERR_SLV_TX_NACK; + + /* Invoke I2C error callback if available */ + if (pSalI2CUserCB->pERRCB->USERCB != NULL) + pSalI2CUserCB->pERRCB->USERCB((void *)pSalI2CUserCB->pERRCB->USERData); + } + + /* I2C TX Abort Intr */ + if (pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_INTR_STAT) & + BIT_CTRL_IC_INTR_STAT_R_TX_ABRT(1)) { + //DBG_8195A("abort\n"); + DBG_I2C_ERR("!!!I2C%d INTR_TX_ABRT!!!\n",I2CIrqIdx); + DBG_I2C_ERR("I2C%d IC_TX_ABRT_SOURCE[%2x]: %x\n", I2CIrqIdx, REG_DW_I2C_IC_TX_ABRT_SOURCE, + pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_TX_ABRT_SOURCE)); + DBG_I2C_ERR("Dev Sts:%x\n",pSalI2CHND->DevSts); + DBG_I2C_ERR("rx len:%x\n",pSalI2CHND->pRXBuf->DataLen); + DBG_I2C_ERR("tx len:%x\n",pSalI2CHND->pTXBuf->DataLen); + DBG_I2C_ERR("raw sts:%x\n",pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_RAW_INTR_STAT)); + DBG_I2C_ERR("ic sts:%x\n",pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_STATUS)); + /* Clear I2C Interrupt */ + pHalI2CInitDat->I2CIntrClr = REG_DW_I2C_IC_CLR_TX_ABRT; + pHalI2COP->HalI2CClrIntr(pHalI2CInitDat); + I2CLocalTemp = pSalI2CHND->DevSts; + + /* Update I2C device status */ + pSalI2CHND->DevSts = I2C_STS_ERROR; + + /* Update I2C error type */ + pSalI2CHND->ErrType |= I2C_ERR_TX_ABRT; + + /* Invoke I2C error callback */ + if (pSalI2CUserCB->pERRCB->USERCB != NULL) + pSalI2CUserCB->pERRCB->USERCB((void *)pSalI2CUserCB->pERRCB->USERData); + + if (pSalI2CHND->I2CExd & I2C_EXD_MTR_ADDR_RTY) { + if (pSalI2CHND->I2CMaster == I2C_MASTER_MODE) { + if ((I2CLocalTemp == I2C_STS_RX_READY) || (I2CLocalTemp == I2C_STS_RX_ING)) { + /* Clear Abort source */ + pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_CLR_TX_ABRT); + + /* Update I2C device status */ + pSalI2CHND->DevSts = I2C_STS_RX_ING; + + if (pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_STATUS) + & BIT_IC_STATUS_TFNF) { + if (pSalI2CMngtAdpt->MstRDCmdCnt > 0) { + pHalI2CInitDat->I2CCmd = I2C_READ_CMD; + pHalI2CInitDat->I2CDataLen= 1; + pHalI2CInitDat->I2CRWData = pSalI2CHND->pRXBuf->pDataBuf; + pHalI2CInitDat->I2CStop = I2C_STOP_DIS; + if ((pSalI2CMngtAdpt->MstRDCmdCnt == 1) && ((pSalI2CHND->I2CExd & I2C_EXD_MTR_HOLD_BUS) == 0)) + pHalI2CInitDat->I2CStop = I2C_STOP_EN; + //DBG_8195A("A0\n"); + pSalI2CMngtAdpt->MstRDCmdCnt--; + pHalI2COP->HalI2CMassSend(pHalI2CInitDat); + } + + } + } + else if ((I2CLocalTemp == I2C_STS_TX_READY) || (I2CLocalTemp == I2C_STS_TX_ING)){ + /* Clear Abort source */ + pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_CLR_TX_ABRT); + + /* Update I2C device status */ + pSalI2CHND->DevSts = I2C_STS_TX_ING; + + /* Return to the former transfer status */ + pSalI2CHND->pTXBuf->pDataBuf--; + pSalI2CHND->pTXBuf->DataLen++; + + if (pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_STATUS) + & BIT_IC_STATUS_TFNF) { + pHalI2CInitDat->I2CCmd = I2C_WRITE_CMD; + pHalI2CInitDat->I2CDataLen= 1; + pHalI2CInitDat->I2CRWData = pSalI2CHND->pTXBuf->pDataBuf; + pHalI2CInitDat->I2CStop = I2C_STOP_DIS; + if ((pSalI2CHND->pTXBuf->DataLen == 1) && ((pSalI2CHND->I2CExd & I2C_EXD_MTR_HOLD_BUS) == 0)) + pHalI2CInitDat->I2CStop = I2C_STOP_EN; + + pHalI2COP->HalI2CMassSend(pHalI2CInitDat); + + pSalI2CHND->pTXBuf->pDataBuf++; + pSalI2CHND->pTXBuf->DataLen--; + } + } + } + } + } + + /* I2C RD REQ Intr */ + if (pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_INTR_STAT) & + BIT_CTRL_IC_INTR_STAT_R_RD_REQ(1)) { + /* Confirm it's slave mode */ + if (pSalI2CHND->I2CMaster == I2C_SLAVE_MODE) { + //DBG_8195A("rq\n"); + if (pSalI2CHND->pTXBuf->DataLen>0) { + /* Update I2C device status */ + pSalI2CHND->DevSts = I2C_STS_TX_ING; + + /* Invoke I2C TX callback if available */ + if (pSalI2CUserCB->pTXCB->USERCB != NULL) + pSalI2CUserCB->pTXCB->USERCB((void *)pSalI2CUserCB->pTXCB->USERData); + + /* I2C Slave transmits data to Master. If the TX FIFO is NOT full, + write one byte from slave TX buffer to TX FIFO. */ + if ((pHalI2COP->HalI2CReadReg(pHalI2CInitDat, REG_DW_I2C_IC_STATUS) + & (BIT_IC_STATUS_TFNF)) == BIT_IC_STATUS_TFNF) { + pHalI2CInitDat->I2CCmd = I2C_WRITE_CMD; + pHalI2CInitDat->I2CDataLen= 1; + pHalI2CInitDat->I2CRWData = pSalI2CHND->pTXBuf->pDataBuf; + pHalI2CInitDat->I2CStop = I2C_STOP_DIS; + if ((pSalI2CHND->pTXBuf->DataLen == 1) && ((pSalI2CHND->I2CExd & I2C_EXD_MTR_HOLD_BUS) == 0)) + pHalI2CInitDat->I2CStop = I2C_STOP_EN; + + pHalI2COP->HalI2CMassSend(pHalI2CInitDat); + + pSalI2CHND->pTXBuf->pDataBuf++; + pSalI2CHND->pTXBuf->DataLen--; + } + } + + /* To clear Read Request Intr */ + pHalI2CInitDat->I2CIntrClr = REG_DW_I2C_IC_CLR_RD_REQ; + pHalI2COP->HalI2CClrIntr(pHalI2CInitDat); + + /* To check I2C slave TX data length. If all the data are transmitted, + mask all the interrupts and invoke the user callback */ + if (!pSalI2CHND->pTXBuf->DataLen) { + /* This is a software patch */ + pHalI2COP->HalI2CReadReg(pHalI2CInitDat, REG_DW_I2C_IC_RAW_INTR_STAT); + HalDelayUs(1000); + + /* Disable I2C TX Related Interrupts */ + I2CLocalTemp = pHalI2COP->HalI2CReadReg(pHalI2CInitDat, REG_DW_I2C_IC_INTR_MASK); + I2CLocalTemp &= ~(BIT_IC_INTR_MASK_M_TX_ABRT | + BIT_IC_INTR_MASK_M_TX_OVER | + BIT_IC_INTR_MASK_M_RX_DONE | + BIT_IC_INTR_MASK_M_RD_REQ); + pHalI2CInitDat->I2CIntrMSK = I2CLocalTemp; + pHalI2COP->HalI2CIntrCtrl(pHalI2CInitDat); + pHalI2COP->HalI2CClrAllIntr(pHalI2CInitDat); + + /* Update I2C device status */ + pSalI2CHND->DevSts = I2C_STS_IDLE; + + /* Invoke I2C TX complete callback if available */ + if (pSalI2CUserCB->pTXCCB->USERCB != NULL) + pSalI2CUserCB->pTXCCB->USERCB((void *)pSalI2CUserCB->pTXCCB->USERData); + } + } + } + + /* I2C TX Empty Intr */ + if (pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_INTR_STAT) & + BIT_CTRL_IC_INTR_STAT_R_TX_EMPTY(1)) { + /* Confirm it's master mode */ + if (pSalI2CHND->I2CMaster == I2C_MASTER_MODE) { + + /* To check I2C master TX data length. If all the data are transmitted, + mask all the interrupts and invoke the user callback */ + if (!pSalI2CHND->pTXBuf->DataLen) { + /* I2C Disable TX Related Interrupts */ + I2CLocalTemp = pHalI2COP->HalI2CReadReg(pHalI2CInitDat, REG_DW_I2C_IC_INTR_MASK); + I2CLocalTemp &= ~(BIT_IC_INTR_MASK_M_TX_ABRT | + BIT_IC_INTR_MASK_M_TX_EMPTY | + BIT_IC_INTR_MASK_M_TX_OVER); + pHalI2CInitDat->I2CIntrMSK = I2CLocalTemp; + pHalI2COP->HalI2CIntrCtrl(pHalI2CInitDat); + + /* Clear all I2C pending interrupts */ + pHalI2COP->HalI2CClrIntr(pHalI2CInitDat); + /* Update I2C device status */ + pSalI2CHND->DevSts = I2C_STS_IDLE; + + /* Invoke I2C TX Complete callback */ + if (pSalI2CUserCB->pTXCCB->USERCB != NULL) + pSalI2CUserCB->pTXCCB->USERCB((void *)pSalI2CUserCB->pTXCCB->USERData); + } + + if (pSalI2CHND->pTXBuf->DataLen > 0) { + /* Update I2C device status */ + pSalI2CHND->DevSts = I2C_STS_TX_ING; + + /* Invoke I2C TX callback if available */ + if (pSalI2CUserCB->pTXCB->USERCB != NULL) + pSalI2CUserCB->pTXCB->USERCB((void *)pSalI2CUserCB->pTXCB->USERData); + + /* Check I2C TX FIFO status. If it's not full, one byte data will be written into it. */ + if ((pHalI2COP->HalI2CReadReg(pHalI2CInitDat, REG_DW_I2C_IC_STATUS) + & (BIT_IC_STATUS_TFNF)) == BIT_IC_STATUS_TFNF) { + pHalI2CInitDat->I2CCmd = I2C_WRITE_CMD; + pHalI2CInitDat->I2CDataLen= 1; + pHalI2CInitDat->I2CRWData = pSalI2CHND->pTXBuf->pDataBuf; + pHalI2CInitDat->I2CStop = I2C_STOP_DIS; + pHalI2CInitDat->I2CReSTR = 1; + if ((pSalI2CHND->pTXBuf->DataLen == 1) && ((pSalI2CHND->I2CExd & I2C_EXD_MTR_HOLD_BUS) == 0)) + pHalI2CInitDat->I2CStop = I2C_STOP_EN; + + pHalI2COP->HalI2CMassSend(pHalI2CInitDat); + + pSalI2CHND->pTXBuf->pDataBuf++; + pSalI2CHND->pTXBuf->DataLen--; + + } + } + }/*if (pSalI2CHND->I2CMaster == I2C_MASTER_MODE)*/ + } + + /* I2C TX Over Run Intr */ + if (pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_INTR_STAT) & + BIT_CTRL_IC_INTR_STAT_R_TX_OVER(1)) { + + DBG_I2C_ERR("!!!I2C%d INTR_TX_OVER!!!\n",I2CIrqIdx); + + /* Clear I2C interrupt */ + pHalI2CInitDat->I2CIntrClr = REG_DW_I2C_IC_CLR_TX_OVER; + pHalI2COP->HalI2CClrIntr(pHalI2CInitDat); + + /* Update I2C device status */ + pSalI2CHND->DevSts = I2C_STS_ERROR; + + /* Update I2C error type */ + pSalI2CHND->ErrType |= I2C_ERR_TX_OVER; + + /* Invoke I2C error callback if available */ + if (pSalI2CUserCB->pERRCB->USERCB != NULL) + pSalI2CUserCB->pERRCB->USERCB((void *)pSalI2CUserCB->pERRCB->USERData); + } + + /* I2C RX Full Intr */ + if (pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_INTR_STAT) & + BIT_CTRL_IC_INTR_STAT_R_RX_FULL(1)) { + /* Check if it's Master */ + if (pSalI2CHND->I2CMaster == I2C_MASTER_MODE){ + + //DBG_8195A("full\n"); + /* Check if the receive transfer is NOT finished. If it is not, check if there + is data in the RX FIFO and move the data from RX FIFO to user data buffer*/ + if (pSalI2CHND->pRXBuf->DataLen > 0) { + + /* Update I2C device status */ + pSalI2CHND->DevSts = I2C_STS_RX_ING; + + /* Invoke I2C RX callback if available */ + if (pSalI2CUserCB->pRXCB->USERCB != NULL) + pSalI2CUserCB->pRXCB->USERCB((void *)pSalI2CUserCB->pRXCB->USERData); + + I2CInTOTcnt = (u32)pSalI2CMngtAdpt->InnerTimeOut; + InTimeoutCount = 0; + /* Calculate internal time out parameters */ + if ((I2CInTOTcnt != 0) && (I2CInTOTcnt != I2C_TIMEOOUT_ENDLESS)) { + InTimeoutCount = (I2CInTOTcnt*1000/TIMER_TICK_US); + InStartCount = HalTimerOp.HalTimerReadCount(1); + } + + while (1) { + I2CLocalRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_STATUS); + if ((I2CLocalRawSts & (BIT_IC_STATUS_RFNE | BIT_IC_STATUS_RFF)) != 0) { + *(pSalI2CHND->pRXBuf->pDataBuf) = + pHalI2COP->HalI2CReceive(pHalI2CInitDat); + //DBG_8195A("rx:%x\n",*(pSalI2CHND->pRXBuf->pDataBuf)); + pSalI2CHND->pRXBuf->pDataBuf++; + pSalI2CHND->pRXBuf->DataLen--; + + if ((pSalI2CHND->pRXBuf->DataLen) == 0) + break; + } + else if ((pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_RAW_INTR_STAT) + & (BIT_IC_RAW_INTR_STAT_RX_OVER | BIT_IC_RAW_INTR_STAT_RX_UNDER)) != 0) { + break; + } + else { + if ((pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_STATUS) & BIT_IC_STATUS_RFNE) + == 0){ + break; + } + } + + if (InTimeoutCount > 0) { + if (HAL_TIMEOUT == I2CIsTimeout(InStartCount, InTimeoutCount)) { + pSalI2CHND->DevSts = I2C_STS_TIMEOUT; + pSalI2CHND->ErrType = I2C_ERR_RX_FF_TO; + DBG_I2C_ERR("RX Full Timeout, I2C%2x,1\n",pSalI2CHND->DevNum); + DBG_I2C_ERR("DevSts:%x, ErrType:%x\n", pSalI2CHND->DevSts, pSalI2CHND->ErrType); + break; + } + } + else { + if (I2CInTOTcnt == 0) { + pSalI2CHND->DevSts = I2C_STS_TIMEOUT; + pSalI2CHND->ErrType = I2C_ERR_RX_FF_TO; + DBG_I2C_ERR("RX Full Timeout, I2C%2x,2\n",pSalI2CHND->DevNum); + DBG_I2C_ERR("DevSts:%x, ErrType:%x\n", pSalI2CHND->DevSts, pSalI2CHND->ErrType); + break; + } + } + } + } + + /* To check I2C master RX data length. If all the data are received, + mask all the interrupts and invoke the user callback. + Otherwise, the master should send another Read Command to slave for + the next data byte receiving. */ + if (!pSalI2CHND->pRXBuf->DataLen) { + /* I2C Disable RX Related Interrupts */ + I2CLocalTemp = pHalI2COP->HalI2CReadReg(pHalI2CInitDat, REG_DW_I2C_IC_INTR_MASK); + I2CLocalTemp &= ~(BIT_IC_INTR_MASK_M_RX_FULL | + BIT_IC_INTR_MASK_M_RX_OVER | + BIT_IC_INTR_MASK_M_RX_UNDER| + BIT_IC_INTR_MASK_M_TX_ABRT); + + pHalI2CInitDat->I2CIntrMSK = I2CLocalTemp; + pHalI2COP->HalI2CIntrCtrl(pHalI2CInitDat); + + /* Clear all I2C pending interrupts */ + pHalI2COP->HalI2CClrAllIntr(pHalI2CInitDat); + /* Update I2C device status */ + pSalI2CHND->DevSts = I2C_STS_IDLE; + + /* Invoke I2C RX complete callback if available */ + if (pSalI2CUserCB->pRXCCB->USERCB != NULL) + pSalI2CUserCB->pRXCCB->USERCB((void *)pSalI2CUserCB->pRXCCB->USERData); + } + else { + /* If TX FIFO is not full, another Read Command is written into it. */ + if (pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_STATUS) + & BIT_IC_STATUS_TFNF) { + if (pSalI2CMngtAdpt->MstRDCmdCnt > 0) { + pHalI2CInitDat->I2CCmd = I2C_READ_CMD; + pHalI2CInitDat->I2CDataLen= 1; + pHalI2CInitDat->I2CRWData = pSalI2CHND->pRXBuf->pDataBuf; + pHalI2CInitDat->I2CStop = I2C_STOP_DIS; + pHalI2CInitDat->I2CReSTR = 1; + if ((pSalI2CMngtAdpt->MstRDCmdCnt == 1) && ((pSalI2CHND->I2CExd & I2C_EXD_MTR_HOLD_BUS) == 0)){ + pHalI2CInitDat->I2CStop = I2C_STOP_EN; + } + pSalI2CMngtAdpt->MstRDCmdCnt--; + pHalI2COP->HalI2CMassSend(pHalI2CInitDat); + } + } + } + + }/*(pSalI2CHND->I2CMaster == I2C_MASTER_MODE)*/ + else{ + /* To check I2C master RX data length. If all the data are received, + mask all the interrupts and invoke the user callback. + Otherwise, if there is data in the RX FIFO and move the data from RX + FIFO to user data buffer*/ + if (pSalI2CHND->pRXBuf->DataLen > 0){ + + /* Update I2C device status */ + pSalI2CHND->DevSts = I2C_STS_RX_ING; + + /* Invoke I2C RX callback if available */ + if (pSalI2CUserCB->pRXCB->USERCB != NULL) + pSalI2CUserCB->pRXCB->USERCB((void *)pSalI2CUserCB->pRXCB->USERData); + + if ((pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_STATUS) + & (BIT_IC_STATUS_RFNE | BIT_IC_STATUS_RFF)) != 0) { + *(pSalI2CHND->pRXBuf->pDataBuf) = + pHalI2COP->HalI2CReceive(pHalI2CInitDat); + pSalI2CHND->pRXBuf->pDataBuf++; + pSalI2CHND->pRXBuf->DataLen--; + } + } + + /* All data are received. Mask all related interrupts. */ + if (!pSalI2CHND->pRXBuf->DataLen){ + /*I2C Disable RX Related Interrupts*/ + I2CLocalTemp = pHalI2COP->HalI2CReadReg(pHalI2CInitDat, REG_DW_I2C_IC_INTR_MASK); + I2CLocalTemp &= ~(BIT_IC_INTR_MASK_M_RX_FULL | + BIT_IC_INTR_MASK_M_RX_OVER | + BIT_IC_INTR_MASK_M_RX_UNDER); + + pHalI2CInitDat->I2CIntrMSK = I2CLocalTemp; + pHalI2COP->HalI2CIntrCtrl(pHalI2CInitDat); + + /* Update I2C device status */ + pSalI2CHND->DevSts = I2C_STS_IDLE; + + /* Invoke I2C RX complete callback if available */ + if (pSalI2CUserCB->pRXCCB->USERCB != NULL) + pSalI2CUserCB->pRXCCB->USERCB((void *)pSalI2CUserCB->pRXCCB->USERData); + } + } + } + + /*I2C RX Over Run Intr*/ + if (pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_INTR_STAT) & + BIT_CTRL_IC_INTR_STAT_R_RX_OVER(1)) { + + DBG_I2C_ERR("I2C%d INTR_RX_OVER\n",I2CIrqIdx); + + pHalI2CInitDat->I2CIntrClr = REG_DW_I2C_IC_CLR_RX_OVER; + pHalI2COP->HalI2CClrIntr(pHalI2CInitDat); + + /* Update I2C device status */ + pSalI2CHND->DevSts = I2C_STS_ERROR; + + /* Update I2C error type */ + pSalI2CHND->ErrType |= I2C_ERR_RX_OVER; + + /* Invoke I2C error callback if available */ + if (pSalI2CUserCB->pERRCB->USERCB != NULL) + pSalI2CUserCB->pERRCB->USERCB((void *)pSalI2CUserCB->pERRCB->USERData); + } + + /*I2C RX Under Run Intr*/ + if (pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_INTR_STAT) & + BIT_CTRL_IC_INTR_STAT_R_RX_UNDER(1)) { + + DBG_I2C_ERR("!!!I2C%d INTR_RX_UNDER!!!\n",I2CIrqIdx); + + pHalI2CInitDat->I2CIntrClr = REG_DW_I2C_IC_CLR_RX_UNDER; + pHalI2COP->HalI2CClrIntr(pHalI2CInitDat); + + /* Update I2C device status */ + pSalI2CHND->DevSts = I2C_STS_ERROR; + + /* Update I2C error type */ + pSalI2CHND->ErrType |= I2C_ERR_RX_UNDER; + + /* Invoke I2C error callback if available */ + if (pSalI2CUserCB->pERRCB->USERCB != NULL) + pSalI2CUserCB->pERRCB->USERCB((void *)pSalI2CUserCB->pERRCB->USERData); + } +} + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// RtkI2CSend +// +// Description: +// To execute Master-Transmitter and Slave-Transmitter operation. +// There are 3 operation mode in this function which are separated by compile-time +// flag. +// For Master-Transmitter, the User Register Address flag is checked first. +// User Register Address may be sent before any formal transfer, no matter in +// Poll-, Intr- or DMA- Mode. +// +// In Poll-Mode, no matter it's master or slave mode, the transfer will be done in +// this function by checking the transfer length. +// -Master in Poll-Mode: +// a. Send the User Register Address if needed. +// b. Check if all the data are transmitted. If it's NOT, checking the TX FIFO +// status is done for writing data from user TX buffer to I2C TX FIFO when +// TX FIFO is NOT full. +// TX data length decrements one after writing one byte into TX FIFO. +// c. b is executed circularly till the TX buffer data length is zero. +// +// -Slave in Poll-Mode: +// Slave could send data only when it received a Read Commmand matched +// with its own I2C address from other I2C master. Once a slave correctly +// received a Read Command matched with its own addr., a Read-Request +// flag is set at the same time. +// In this Poll-Mode, the slave checks the Read-Request flag to decide +// if it could send its TX buffer data. +// a. Check if the Read-Request flag is set or not. If the flag is set, it should +// check if TX buffer data length is zero. If it's NOT, +// the I2C TX FIFO status will be checked for the following operation. +// b. If the TX FIFO is NOT empty, slave will write one byte data from TX data +// buffer to TX FIFO. +// c. a and b are executed circularly till the TX buffer data length is zero. +//---------------------------------------------------------------------- +// In Intr-Mode, this function is used to unmask the realted I2C interrupt for +// the following interrupt operations. +// -Master in Intr-Mode: +// a. Send the User Register Address if needed. +// b. Unmask the TX-Empty and realted error interrupts. +// +// -Slave in Intr-Mode: +// a. Unmask the RD-Req and realted error interrupts. +// +// Arguments: +// [in] VOID *Data - +// I2C SAL handle +// +// Return: +// The status of the I2C send process. +// _EXIT_SUCCESS if the RtkI2CSend succeeded. +// _EXIT_FAILURE if the RtkI2CSend failed. +// +// Note: +// NA +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-04-03. +// +//---------------------------------------------------------------------------------------------------- +HAL_Status +RtkI2CSend( + IN VOID *Data +){ + PSAL_I2C_HND pSalI2CHND = (PSAL_I2C_HND) Data; + PSAL_I2C_HND_PRIV pSalI2CHNDPriv = NULL; + PSAL_I2C_MNGT_ADPT pSalI2CMngtAdpt = NULL; + PHAL_I2C_INIT_DAT pHalI2CInitDat = NULL; + PHAL_I2C_OP pHalI2COP = NULL; + + PHAL_GDMA_ADAPTER pHalI2CTxGdmaAdpt = NULL; + PHAL_GDMA_OP pHalI2CGdmaOp = NULL; + + u32 I2CLocalTemp = 0; + u32 I2CInTOTcnt = 0; + u32 InTimeoutCount = 0; + u32 InStartCount = 0; + u32 I2CChkRawSts = 0; + u32 I2CChkRawSts2 = 0; + u32 I2CDataLenBak = 0; + u32 I2CDataPtrBak = 0; + + + /* To Get the SAL_I2C_MNGT_ADPT Pointer */ + pSalI2CHNDPriv = CONTAINER_OF(pSalI2CHND, SAL_I2C_HND_PRIV, SalI2CHndPriv); + pSalI2CMngtAdpt = CONTAINER_OF(pSalI2CHNDPriv->ppSalI2CHnd, SAL_I2C_MNGT_ADPT, pSalHndPriv); + + + + pHalI2CInitDat = pSalI2CMngtAdpt->pHalInitDat; + + pHalI2COP = pSalI2CMngtAdpt->pHalOp; + + + pHalI2CTxGdmaAdpt = pSalI2CMngtAdpt->pHalTxGdmaAdp; + pHalI2CGdmaOp = pSalI2CMngtAdpt->pHalGdmaOp; + + /* Check if it's Master Mode */ + if (pSalI2CHND->I2CMaster == I2C_MASTER_MODE) { + //DBG_8195A("m\n"); + /* Master run-time update target address */ + if (pSalI2CHND->I2CExd & I2C_EXD_MTR_ADDR_UPD) { + + /* Calculate user time out parameters */ + I2CInTOTcnt = pSalI2CHND->TimeOut; + if ((I2CInTOTcnt != 0) && (I2CInTOTcnt != I2C_TIMEOOUT_ENDLESS)) { + InTimeoutCount = (I2CInTOTcnt*1000/TIMER_TICK_US); + InStartCount = HalTimerOp.HalTimerReadCount(1); + } + + /* Check Master activity status */ + while ((pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_STATUS)) & BIT_IC_STATUS_MST_ACTIVITY) { + /* Time-Out check */ + if (InTimeoutCount > 0) { + if (HAL_TIMEOUT == I2CIsTimeout(InStartCount, InTimeoutCount)) { + pSalI2CHND->DevSts = I2C_STS_TIMEOUT; + pSalI2CHND->ErrType = I2C_ERR_TX_ADD_TO; + DBG_I2C_ERR("RtkI2CSend Timeout, I2C%2x,1\n",pSalI2CHND->DevNum); + DBG_I2C_ERR("DevSts:%x, ErrType:%x\n", pSalI2CHND->DevSts, pSalI2CHND->ErrType); + return HAL_TIMEOUT; + } + } + else { + if (I2CInTOTcnt == 0) { + pSalI2CHND->DevSts = I2C_STS_TIMEOUT; + pSalI2CHND->ErrType = I2C_ERR_TX_ADD_TO; + DBG_I2C_ERR("RtkI2CSend Timeout, I2C%2x,2\n",pSalI2CHND->DevNum); + DBG_I2C_ERR("DevSts:%x, ErrType:%x\n", pSalI2CHND->DevSts, pSalI2CHND->ErrType); + return HAL_TIMEOUT; + } + } + } + /* Calculate user time out parameters */ + I2CInTOTcnt = pSalI2CHND->TimeOut; + if ((I2CInTOTcnt != 0) && (I2CInTOTcnt != I2C_TIMEOOUT_ENDLESS)) { + InTimeoutCount = (I2CInTOTcnt*1000/TIMER_TICK_US); + InStartCount = HalTimerOp.HalTimerReadCount(1); + } + + /* Check TX FIFO status */ + while (!((pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_STATUS)) & BIT_IC_STATUS_TFE)) { + /* Time-Out check */ + if (InTimeoutCount > 0) { + if (HAL_TIMEOUT == I2CIsTimeout(InStartCount, InTimeoutCount)) { + pSalI2CHND->DevSts = I2C_STS_TIMEOUT; + pSalI2CHND->ErrType = I2C_ERR_TX_ADD_TO; + DBG_I2C_ERR("RtkI2CSend Timeout, I2C%2x,3\n",pSalI2CHND->DevNum); + DBG_I2C_ERR("DevSts:%x, ErrType:%x\n", pSalI2CHND->DevSts, pSalI2CHND->ErrType); + return HAL_TIMEOUT; + } + } + else { + if (I2CInTOTcnt == 0) { + pSalI2CHND->DevSts = I2C_STS_TIMEOUT; + pSalI2CHND->ErrType = I2C_ERR_TX_ADD_TO; + DBG_I2C_ERR("RtkI2CSend Timeout, I2C%2x,4\n",pSalI2CHND->DevNum); + DBG_I2C_ERR("DevSts:%x, ErrType:%x\n", pSalI2CHND->DevSts, pSalI2CHND->ErrType); + return HAL_TIMEOUT; + } + } + } + + I2CLocalTemp = 0; + I2CLocalTemp = pHalI2COP->HalI2CReadReg(pHalI2CInitDat, REG_DW_I2C_IC_TAR); + I2CLocalTemp &= (~BIT_MASK_IC_TAR); + I2CLocalTemp |= BIT_CTRL_IC_TAR(pSalI2CHND->pTXBuf->TargetAddr); + /* Update Master Target address */ + pHalI2COP->HalI2CWriteReg(pHalI2CInitDat, REG_DW_I2C_IC_TAR, I2CLocalTemp); + } + + RtkI2CSendUserAddr(pSalI2CHND, 0); + + /* #if I2C_POLL_OP_TYPE */ + if (pSalI2CHND->OpType == I2C_POLL_TYPE) { /* if (pSalI2CHND->OpType == I2C_POLL_TYPE) */ + /* I2C Device Status Update */ + pSalI2CHND->DevSts = I2C_STS_TX_READY; + + /* Calculate user time out parameters */ + I2CInTOTcnt = pSalI2CHND->TimeOut; + if ((I2CInTOTcnt != 0) && (I2CInTOTcnt != I2C_TIMEOOUT_ENDLESS)) { + InTimeoutCount = (I2CInTOTcnt*1000/TIMER_TICK_US); + InStartCount = HalTimerOp.HalTimerReadCount(1); + } + + /* Send data till the TX buffer data length is zero */ + for (;pSalI2CHND->pTXBuf->DataLen>0;) { + /* I2C Device Status Update */ + pSalI2CHND->DevSts = I2C_STS_TX_ING; + + /* Check I2C TX FIFO status */ + if ((pHalI2COP->HalI2CReadReg(pHalI2CInitDat, REG_DW_I2C_IC_STATUS) + & (BIT_IC_STATUS_TFNF)) == BIT_IC_STATUS_TFNF) { + /* Wrtie data into I2C TX FIFO */ + pHalI2CInitDat->I2CCmd = I2C_WRITE_CMD; + pHalI2CInitDat->I2CDataLen= 1; + pHalI2CInitDat->I2CRWData = pSalI2CHND->pTXBuf->pDataBuf; + pHalI2CInitDat->I2CStop = I2C_STOP_DIS; + if ((pSalI2CHND->pTXBuf->DataLen == 1) && ((pSalI2CHND->I2CExd & I2C_EXD_MTR_HOLD_BUS) == 0)) + pHalI2CInitDat->I2CStop = I2C_STOP_EN; + pHalI2COP->HalI2CMassSend(pHalI2CInitDat); + + pSalI2CHND->pTXBuf->pDataBuf++; + pSalI2CHND->pTXBuf->DataLen--; + } + else { + /* Time-Out check */ + if (InTimeoutCount > 0) { + if (HAL_TIMEOUT == I2CIsTimeout(InStartCount, InTimeoutCount)) { + pSalI2CHND->DevSts = I2C_STS_TIMEOUT; + pSalI2CHND->ErrType = I2C_ERR_TX_CMD_TO; + DBG_I2C_ERR("RtkI2CSend Timeout, I2C%2x,5\n",pSalI2CHND->DevNum); + DBG_I2C_ERR("DevSts:%x, ErrType:%x\n", pSalI2CHND->DevSts, pSalI2CHND->ErrType); + return HAL_TIMEOUT; + } + } + else { + if (I2CInTOTcnt == 0) { + pSalI2CHND->DevSts = I2C_STS_TIMEOUT; + pSalI2CHND->ErrType = I2C_ERR_TX_CMD_TO; + DBG_I2C_ERR("RtkI2CSend Timeout, I2C%2x,6\n",pSalI2CHND->DevNum); + DBG_I2C_ERR("DevSts:%x, ErrType:%x\n", pSalI2CHND->DevSts, pSalI2CHND->ErrType); + return HAL_TIMEOUT; + } + } + } + + if (pSalI2CHND->I2CExd & I2C_EXD_MTR_ADDR_RTY) { + HalDelayUs(((1000*30)/pHalI2CInitDat->I2CClk)); //the 10 is for ten bit time + + if (pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_RAW_INTR_STAT) & + BIT_IC_RAW_INTR_STAT_TX_ABRT) { + pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_CLR_TX_ABRT); + pSalI2CHND->pTXBuf->pDataBuf--; + pSalI2CHND->pTXBuf->DataLen++; + } + } + } + + /* Calculate user time out parameters */ + I2CInTOTcnt = pSalI2CMngtAdpt->InnerTimeOut; + if ((I2CInTOTcnt != 0) && (I2CInTOTcnt != I2C_TIMEOOUT_ENDLESS)) { + InTimeoutCount = (I2CInTOTcnt*1000/TIMER_TICK_US); + InStartCount = HalTimerOp.HalTimerReadCount(1); + } + /* I2C Wait TX FIFO Empty */ + while (1) { + if ((pHalI2COP->HalI2CReadReg(pHalI2CInitDat, REG_DW_I2C_IC_STATUS) + & (BIT_IC_STATUS_TFE | BIT_IC_STATUS_TFNF)) == + (BIT_IC_STATUS_TFE | BIT_IC_STATUS_TFNF)){ + break; + } + else { + /* Time-Out check */ + if (InTimeoutCount > 0) { + if (HAL_TIMEOUT == I2CIsTimeout(InStartCount, InTimeoutCount)) { + pSalI2CHND->DevSts = I2C_STS_TIMEOUT; + pSalI2CHND->ErrType = I2C_ERR_TX_FF_TO; + DBG_I2C_ERR("RtkI2CSend Timeout, I2C%2x,7\n",pSalI2CHND->DevNum); + DBG_I2C_ERR("DevSts:%x, ErrType:%x\n", pSalI2CHND->DevSts, pSalI2CHND->ErrType); + return HAL_TIMEOUT; + } + } + else { + if (I2CInTOTcnt == 0) { + pSalI2CHND->DevSts = I2C_STS_TIMEOUT; + pSalI2CHND->ErrType = I2C_ERR_TX_FF_TO; + DBG_I2C_ERR("RtkI2CSend Timeout, I2C%2x,8\n",pSalI2CHND->DevNum); + DBG_I2C_ERR("DevSts:%x, ErrType:%x\n", pSalI2CHND->DevSts, pSalI2CHND->ErrType); + return HAL_TIMEOUT; + } + } + } + } + + /* I2C Device Status Update */ + pSalI2CHND->DevSts = I2C_STS_IDLE; + }/* if (pSalI2CHND->OpType == I2C_POLL_TYPE) */ + /* #if I2C_POLL_OP_TYPE */ + +#if I2C_INTR_OP_TYPE + if (pSalI2CHND->OpType == I2C_INTR_TYPE) { /* if (pSalI2CHND->OpType == I2C_INTR_TYPE) */ + /* Calculate user time out parameters */ + InTimeoutCount = 0; + InStartCount = 0; + I2CInTOTcnt = pSalI2CHND->TimeOut; + if ((I2CInTOTcnt != 0) && (I2CInTOTcnt != I2C_TIMEOOUT_ENDLESS)) { + InTimeoutCount = (I2CInTOTcnt*1000/TIMER_TICK_US); + InStartCount = HalTimerOp.HalTimerReadCount(1); + } + + I2CDataLenBak = (u32)(pSalI2CHND->pTXBuf->DataLen); + I2CDataPtrBak = (u32)(pSalI2CHND->pTXBuf->pDataBuf); + /* I2C Device Status Update */ + pSalI2CHND->DevSts = I2C_STS_IDLE; + pHalI2CInitDat->I2CIntrClr = REG_DW_I2C_IC_CLR_TX_ABRT; + pHalI2COP->HalI2CClrIntr(pHalI2CInitDat); + pHalI2COP->HalI2CClrAllIntr(pHalI2CInitDat); + + /* Send data till the TX buffer data length is zero */ + for (;;) { +SEND_I2C_WR_CMD_INTR: + + /* I2C Device Status Update */ + pSalI2CHND->DevSts = I2C_STS_TX_ING; + + /* Check I2C TX FIFO status */ + /* Fill TX FIFO only when it's completely empty */ + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_STATUS); + if ((I2CChkRawSts & BIT_IC_STATUS_TFE) == BIT_IC_STATUS_TFE) { + if (pSalI2CHND->pTXBuf->DataLen > 0) { + /* Wrtie data into I2C TX FIFO */ + pHalI2CInitDat->I2CCmd = I2C_WRITE_CMD; + pHalI2CInitDat->I2CDataLen= 1; + pHalI2CInitDat->I2CRWData = pSalI2CHND->pTXBuf->pDataBuf; + pHalI2CInitDat->I2CStop = I2C_STOP_DIS; + + if ((pSalI2CHND->pTXBuf->DataLen == 1) && ((pSalI2CHND->I2CExd & I2C_EXD_MTR_HOLD_BUS) == 0)) + pHalI2CInitDat->I2CStop = I2C_STOP_EN; + + pHalI2COP->HalI2CMassSend(pHalI2CInitDat); + + pSalI2CHND->pTXBuf->pDataBuf++; + pSalI2CHND->pTXBuf->DataLen--; + } + } + + if (pSalI2CHND->I2CExd & I2C_EXD_MTR_ADDR_RTY) { + u32 I2CInTOTcntRty = 0; + u32 InTimeoutCountRty = 0; + u32 InStartCountRty = 0; + /* Calculate user time out parameters */ + InTimeoutCountRty = 0; + InStartCountRty = 0; + I2CInTOTcntRty = pSalI2CHND->TimeOut; + + if ((I2CInTOTcntRty != 0) && (I2CInTOTcntRty!= I2C_TIMEOOUT_ENDLESS)) { + InTimeoutCountRty= (I2CInTOTcntRty*1000/TIMER_TICK_US); + InStartCountRty= HalTimerOp.HalTimerReadCount(1); + } + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_STATUS); + while ((I2CChkRawSts & BIT_IC_STATUS_TFE) == 0) { + I2CChkRawSts2 = pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_RAW_INTR_STAT); + if ((I2CChkRawSts2 & BIT_IC_RAW_INTR_STAT_TX_ABRT) != 0){ + break; + } + + /* Time-Out check */ + if (InTimeoutCountRty > 0) { + if (HAL_TIMEOUT == I2CIsTimeout(InStartCountRty, InTimeoutCountRty)) { + break; + } + } + else { + if (I2CInTOTcntRty == 0) { + break; + } + } + + /* Read I2C IC status again */ + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_STATUS); + } + + HalDelayUs((u32)((1000*30)/pHalI2CInitDat->I2CClk)); //the 10 is for ten bit time + + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_RAW_INTR_STAT); + if (I2CChkRawSts & BIT_IC_RAW_INTR_STAT_TX_ABRT) { +#if 1 + RtkI2CDeInit(pSalI2CHND); + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_ENABLE_STATUS); + while((I2CChkRawSts & BIT_IC_ENABLE_STATUS_IC_EN) == BIT_IC_ENABLE_STATUS_IC_EN){ + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_ENABLE_STATUS); + } + RtkI2CInit(pSalI2CHND); + + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_ENABLE_STATUS); + while((I2CChkRawSts & BIT_IC_ENABLE_STATUS_IC_EN) != BIT_IC_ENABLE_STATUS_IC_EN){ + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_ENABLE_STATUS); + } + + pSalI2CHND->DevSts = I2C_STS_TX_READY; + pSalI2CHND->ErrType = 0; + pSalI2CHND->pTXBuf->DataLen = (u16)I2CDataLenBak; + pSalI2CHND->pTXBuf->pDataBuf= (u8*)I2CDataPtrBak; + /* Calculate user time out parameters */ + InTimeoutCount = 0; + InStartCount = 0; + I2CInTOTcnt = pSalI2CHND->TimeOut; + if ((I2CInTOTcnt != 0) && (I2CInTOTcnt != I2C_TIMEOOUT_ENDLESS)) { + InTimeoutCount = (I2CInTOTcnt*1000/TIMER_TICK_US); + InStartCount = HalTimerOp.HalTimerReadCount(1); + } + goto SEND_I2C_WR_CMD_INTR; +#else + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_STATUS); + while ((I2CChkRawSts & BIT_IC_STATUS_ACTIVITY) != 0) { + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_STATUS); + } + + pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_CLR_TX_ABRT); + + /* Clear all I2C pending interrupts */ + pHalI2COP->HalI2CClrAllIntr(pHalI2CInitDat); + + pSalI2CHND->pTXBuf->pDataBuf--; + pSalI2CHND->pTXBuf->DataLen++; + + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_STATUS); + while ((I2CChkRawSts & BIT_IC_STATUS_ACTIVITY) != 0) { + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_STATUS); + } +#endif + } + else if (((u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_STATUS) & BIT_IC_STATUS_TFE) != BIT_IC_STATUS_TFE) { + { + RtkI2CDeInit(pSalI2CHND); + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_ENABLE_STATUS); + while((I2CChkRawSts & BIT_IC_ENABLE_STATUS_IC_EN) == BIT_IC_ENABLE_STATUS_IC_EN){ + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_ENABLE_STATUS); + } + RtkI2CInit(pSalI2CHND); + + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_ENABLE_STATUS); + while((I2CChkRawSts & BIT_IC_ENABLE_STATUS_IC_EN) != BIT_IC_ENABLE_STATUS_IC_EN){ + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_ENABLE_STATUS); + } + + pSalI2CHND->DevSts = I2C_STS_TX_READY; + pSalI2CHND->ErrType = 0; + pSalI2CHND->pTXBuf->DataLen = (u16)I2CDataLenBak; + pSalI2CHND->pTXBuf->pDataBuf= (u8 *)I2CDataPtrBak; + /* Calculate user time out parameters */ + InTimeoutCount = 0; + InStartCount = 0; + I2CInTOTcnt = pSalI2CHND->TimeOut; + if ((I2CInTOTcnt != 0) && (I2CInTOTcnt != I2C_TIMEOOUT_ENDLESS)) { + InTimeoutCount = (I2CInTOTcnt*1000/TIMER_TICK_US); + InStartCount = HalTimerOp.HalTimerReadCount(1); + } + goto SEND_I2C_WR_CMD_INTR; + } + } + else { + /* I2C Enable TX Related Interrupts */ + I2CLocalTemp = 0; + I2CLocalTemp = pHalI2COP->HalI2CReadReg(pHalI2CInitDat, REG_DW_I2C_IC_INTR_MASK); + I2CLocalTemp |= (BIT_IC_INTR_MASK_M_TX_ABRT | + BIT_IC_INTR_MASK_M_TX_EMPTY | + BIT_IC_INTR_MASK_M_TX_OVER); + pHalI2CInitDat->I2CIntrMSK = I2CLocalTemp; + pHalI2COP->HalI2CIntrCtrl(pHalI2CInitDat); + + break; + } + } + else { + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_STATUS); + while ((I2CChkRawSts & BIT_IC_STATUS_TFE) == 0) { + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_STATUS); + } + + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_STATUS); + if (I2CChkRawSts & BIT_IC_STATUS_TFE) { + /* I2C Enable TX Related Interrupts */ + I2CLocalTemp = 0; + I2CLocalTemp = pHalI2COP->HalI2CReadReg(pHalI2CInitDat, REG_DW_I2C_IC_INTR_MASK); + I2CLocalTemp |= (BIT_IC_INTR_MASK_M_TX_ABRT | + BIT_IC_INTR_MASK_M_TX_EMPTY | + BIT_IC_INTR_MASK_M_TX_OVER); + pHalI2CInitDat->I2CIntrMSK = I2CLocalTemp; + pHalI2COP->HalI2CIntrCtrl(pHalI2CInitDat); + break; + } + } +#if 1 + /* Time-Out check */ + if (InTimeoutCount > 0) { + if (HAL_TIMEOUT == I2CIsTimeout(InStartCount, InTimeoutCount)) { + pSalI2CHND->DevSts = I2C_STS_TIMEOUT; + pSalI2CHND->ErrType = I2C_ERR_TX_FF_TO; + //DBG_I2C_ERR("RtkI2CSend Timeout, I2C%2x,7\n",pSalI2CHND->DevNum); + //DBG_I2C_ERR("DevSts:%x, ErrType:%x\n", pSalI2CHND->DevSts, pSalI2CHND->ErrType); + RtkI2CDeInit(pSalI2CHND); + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_ENABLE_STATUS); + while((I2CChkRawSts & BIT_IC_ENABLE_STATUS_IC_EN) == BIT_IC_ENABLE_STATUS_IC_EN){ + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_ENABLE_STATUS); + } + RtkI2CInit(pSalI2CHND); + + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_ENABLE_STATUS); + while((I2CChkRawSts & BIT_IC_ENABLE_STATUS_IC_EN) != BIT_IC_ENABLE_STATUS_IC_EN){ + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_ENABLE_STATUS); + } +#if 0 + pSalI2CHND->DevSts = I2C_STS_TX_READY; + pSalI2CHND->ErrType = 0; + pSalI2CHND->pTXBuf->DataLen = I2CDataLenBak; + pSalI2CHND->pTXBuf->pDataBuf= I2CDataPtrBak; + /* Calculate user time out parameters */ + InTimeoutCount = 0; + InStartCount = 0; + I2CInTOTcnt = pSalI2CHND->TimeOut; + if ((I2CInTOTcnt != 0) && (I2CInTOTcnt != I2C_TIMEOOUT_ENDLESS)) { + InTimeoutCount = (I2CInTOTcnt*1000/TIMER_TICK_US); + InStartCount = HalTimerOp.HalTimerReadCount(1); + } +#endif + return HAL_TIMEOUT; + } + } + else { + if (I2CInTOTcnt == 0) { + pSalI2CHND->DevSts = I2C_STS_TIMEOUT; + pSalI2CHND->ErrType = I2C_ERR_TX_FF_TO; + + RtkI2CDeInit(pSalI2CHND); + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_ENABLE_STATUS); + while((I2CChkRawSts & BIT_IC_ENABLE_STATUS_IC_EN) == BIT_IC_ENABLE_STATUS_IC_EN){ + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_ENABLE_STATUS); + } + RtkI2CInit(pSalI2CHND); + + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_ENABLE_STATUS); + while((I2CChkRawSts & BIT_IC_ENABLE_STATUS_IC_EN) != BIT_IC_ENABLE_STATUS_IC_EN){ + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_ENABLE_STATUS); + } +#if 0 + pSalI2CHND->DevSts = I2C_STS_TX_READY; + pSalI2CHND->ErrType = 0; + pSalI2CHND->pTXBuf->DataLen = I2CDataLenBak; + pSalI2CHND->pTXBuf->pDataBuf= I2CDataPtrBak; + /* Calculate user time out parameters */ + InTimeoutCount = 0; + InStartCount = 0; + I2CInTOTcnt = pSalI2CHND->TimeOut; + if ((I2CInTOTcnt != 0) && (I2CInTOTcnt != I2C_TIMEOOUT_ENDLESS)) { + InTimeoutCount = (I2CInTOTcnt*1000/TIMER_TICK_US); + InStartCount = HalTimerOp.HalTimerReadCount(1); + } +#endif + return HAL_TIMEOUT; + } + } +#endif + } + } /* if (pSalI2CHND->OpType == I2C_INTR_TYPE) */ +#endif + + /* if (pSalI2CHND->OpType == I2C_DMA_TYPE) */ + if (pSalI2CHND->OpType == I2C_DMA_TYPE) { + /* I2C Device Status Update */ + pSalI2CHND->DevSts = I2C_STS_TX_READY; + + /* I2C Enable TX Related Interrupts */ + I2CLocalTemp = pHalI2COP->HalI2CReadReg(pHalI2CInitDat, REG_DW_I2C_IC_INTR_MASK); + I2CLocalTemp |= (BIT_IC_INTR_MASK_M_TX_ABRT | + BIT_IC_INTR_MASK_M_TX_OVER); + pHalI2CInitDat->I2CIntrMSK = I2CLocalTemp; + pHalI2COP->HalI2CIntrCtrl(pHalI2CInitDat); + + //HalGdmaOpInit(pHalI2CGdmaOp); + pSalI2CMngtAdpt->pHalGdmaOpInit(pHalI2CGdmaOp); + pHalI2CTxGdmaAdpt->GdmaCtl.BlockSize = pSalI2CHND->pTXBuf->DataLen; + pHalI2CTxGdmaAdpt->ChSar = (u32)pSalI2CHND->pTXBuf->pDataBuf; + pHalI2CTxGdmaAdpt->ChDar = (u32)(I2C0_REG_BASE+REG_DW_I2C_IC_DATA_CMD+ + pSalI2CHND->DevNum*0x400); + pHalI2CGdmaOp->HalGdmaChSeting(pHalI2CTxGdmaAdpt); + pHalI2CGdmaOp->HalGdmaChEn(pHalI2CTxGdmaAdpt); + pSalI2CHND->DevSts = I2C_STS_TX_ING; + pHalI2CInitDat->I2CDMACtrl = BIT_CTRL_IC_DMA_CR_TDMAE(1); + pHalI2COP->HalI2CDMACtrl(pHalI2CInitDat); + + } + /* if (pSalI2CHND->OpType == I2C_DMA_TYPE) */ + + }/* if (pSalI2CHND->I2CMaster == I2C_MASTER_MODE) */ + else{ + /* #if I2C_POLL_OP_TYPE */ + if (pSalI2CHND->OpType == I2C_POLL_TYPE) { + /* Calculate user time out parameters */ + I2CInTOTcnt = pSalI2CHND->TimeOut; + if ((I2CInTOTcnt != 0) && (I2CInTOTcnt != I2C_TIMEOOUT_ENDLESS)) { + InTimeoutCount = (I2CInTOTcnt*1000/TIMER_TICK_US); + InStartCount = HalTimerOp.HalTimerReadCount(1); + } + + /* I2C Device Status Update */ + pSalI2CHND->DevSts = I2C_STS_TX_READY; + + /* Send data till the TX buffer data length is zero */ + for (;pSalI2CHND->pTXBuf->DataLen>0;) { + /* I2C Device Status Update */ + pSalI2CHND->DevSts = I2C_STS_TX_ING; + + /* Check I2C RD Request flag */ + if ((pHalI2COP->HalI2CReadReg(pHalI2CInitDat, REG_DW_I2C_IC_RAW_INTR_STAT)) + & BIT_IC_RAW_INTR_STAT_RD_REQ) { + + /* Check I2C TX FIFO status */ + if ((pHalI2COP->HalI2CReadReg(pHalI2CInitDat, REG_DW_I2C_IC_STATUS) + & (BIT_IC_STATUS_TFNF)) == BIT_IC_STATUS_TFNF) { + pHalI2CInitDat->I2CDataLen= 1; + pHalI2CInitDat->I2CRWData = pSalI2CHND->pTXBuf->pDataBuf; + pHalI2COP->HalI2CMassSend(pHalI2CInitDat); + pHalI2CInitDat->I2CIntrClr = REG_DW_I2C_IC_CLR_RD_REQ; + pHalI2COP->HalI2CClrIntr(pHalI2CInitDat); + pSalI2CHND->pTXBuf->pDataBuf++; + pSalI2CHND->pTXBuf->DataLen--; + } + } + else { + /* Time-Out check */ + if (InTimeoutCount > 0) { + if (HAL_TIMEOUT == I2CIsTimeout(InStartCount, InTimeoutCount)) { + pSalI2CHND->DevSts = I2C_STS_TIMEOUT; + pSalI2CHND->ErrType = I2C_ERR_TX_FF_TO; + DBG_I2C_ERR("RtkI2CSend Timeout, I2C%2x,9\n",pSalI2CHND->DevNum); + DBG_I2C_ERR("DevSts:%x, ErrType:%x\n", pSalI2CHND->DevSts, pSalI2CHND->ErrType); + return HAL_TIMEOUT; + } + } + else { + if (I2CInTOTcnt == 0) { + pSalI2CHND->DevSts = I2C_STS_TIMEOUT; + pSalI2CHND->ErrType = I2C_ERR_TX_FF_TO; + DBG_I2C_ERR("RtkI2CSend Timeout, I2C%2x,10\n",pSalI2CHND->DevNum); + DBG_I2C_ERR("DevSts:%x, ErrType:%x\n", pSalI2CHND->DevSts, pSalI2CHND->ErrType); + return HAL_TIMEOUT; + } + } + } + } + + /* I2C Device Status Update */ + pSalI2CHND->DevSts = I2C_STS_IDLE; + } + /* #if I2C_POLL_OP_TYPE */ + + /* #if I2C_INTR_OP_TYPE */ + if (pSalI2CHND->OpType == I2C_INTR_TYPE) { + /* I2C Device Status Update */ + pSalI2CHND->DevSts = I2C_STS_IDLE; + pHalI2CInitDat->I2CIntrClr = REG_DW_I2C_IC_CLR_TX_ABRT; + pHalI2COP->HalI2CClrIntr(pHalI2CInitDat); + pHalI2CInitDat->I2CIntrClr = REG_DW_I2C_IC_CLR_TX_OVER; + pHalI2COP->HalI2CClrIntr(pHalI2CInitDat); + pHalI2CInitDat->I2CIntrClr = REG_DW_I2C_IC_CLR_RD_REQ; + pHalI2COP->HalI2CClrIntr(pHalI2CInitDat); + pHalI2CInitDat->I2CIntrClr = REG_DW_I2C_IC_CLR_ACTIVITY; + pHalI2COP->HalI2CClrIntr(pHalI2CInitDat); + pHalI2COP->HalI2CClrAllIntr(pHalI2CInitDat); + pSalI2CHND->DevSts = I2C_STS_TX_READY; + + /* I2C Enable TX Related Interrupts. In Slave-Transmitter, the below + interrupts should be enabled. */ + I2CLocalTemp = pHalI2COP->HalI2CReadReg(pHalI2CInitDat, REG_DW_I2C_IC_INTR_MASK); + I2CLocalTemp |= (BIT_IC_INTR_MASK_M_TX_ABRT | + BIT_IC_INTR_MASK_M_TX_OVER | + BIT_IC_INTR_MASK_M_RX_DONE | + BIT_IC_INTR_MASK_M_RD_REQ); + pHalI2CInitDat->I2CIntrMSK = I2CLocalTemp; + pHalI2COP->HalI2CIntrCtrl(pHalI2CInitDat); + } + /* #if I2C_INTR_OP_TYPE */ + + /* #if I2C_DMA_OP_TYPE */ + ; + /* #if I2C_DMA_OP_TYPE */ + } + + return HAL_OK; +} + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// RtkI2CReceive +// +// Description: +// To execute Master-Receiver and Slave-Receiver operation. +// There are 3 operation mode in this function which are separated by compile-time +// flag. +// For Master-Receiver, the User Register Address flag is checked first. +// User Register Address may be sent before any formal transfer, no matter in +// Poll-, Intr- or DMA- Mode. +// +// For Master-Receiver, the I2C master have to send a Read Command for receiving +// one byte from the other I2C slave. +// +// In Poll-Mode, no matter it's master or slave mode, the transfer will be done in +// this function by checking the transfer length. +// -Master in Poll-Mode: +// a. Send the User Register Address if needed. +// b. Check if all the data are received. If it's NOT, checking the TX FIFO +// status will be done. If the TX FIFO it's full, a Read Command will be +// wirtten into the TX FIFO. +// c. After b, the I2C master contineously polls the RX FIFO status to see +// if there is a received data. If it received one, it will move the data from +// I2C RX FIFO into user RX data buffer. +// d. b and c are executed circularly till the RX buffer data length is zero. +// +// -Slave in Poll-Mode: +// a. Check if all the data are received. +// b. The I2C slave contineously polls the RX FIFO status to see +// if there is a received data. If it received one, it will move the data from +// I2C RX FIFO into user RX data buffer. +// c. a and b are executed circularly till the RX buffer data length is zero. +// +//---------------------------------------------------------------------- +// In Intr-Mode, this function is used to unmask the realted I2C interrupt for +// the following interrupt operations. +// -Master in Intr-Mode: +// a. Send the User Register Address if needed. +// b. Unmask the RX-Full and realted error interrupts. +// c. Write one or two Read Command into master TX FIFO for requesting +// another slave providing data. +// +// -Slave in Intr-Mode: +// a. Unmask the RX-Full and realted error interrupts. +// +// Arguments: +// [in] VOID *Data - +// I2C SAL handle +// +// Return: +// The status of the I2C receive process. +// _EXIT_SUCCESS if the RtkI2CReceive succeeded. +// _EXIT_FAILURE if the RtkI2CReceive failed. +// +// Note: +// NA +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-04-03. +// +//---------------------------------------------------------------------------------------------------- +HAL_Status +RtkI2CReceive( + IN VOID *Data +){ + PSAL_I2C_HND pSalI2CHND = (PSAL_I2C_HND) Data; + PSAL_I2C_HND_PRIV pSalI2CHNDPriv = NULL; + PSAL_I2C_MNGT_ADPT pSalI2CMngtAdpt = NULL; + PHAL_I2C_INIT_DAT pHalI2CInitDat = NULL; + PHAL_I2C_OP pHalI2COP = NULL; +#if I2C_DMA_OP_TYPE + PHAL_GDMA_ADAPTER pHalI2CRxGdmaAdpt = NULL; + PHAL_GDMA_OP pHalI2CGdmaOp = NULL; +#endif + + u32 I2CLocalTemp = 0; + u32 I2CInTOTcnt = 0; + u32 InTimeoutCount = 0; + u32 InStartCount = 0; + u32 I2CLocalLen = 0; + u32 I2CChkRawSts = 0; + u32 I2CChkRawSts2 = 0; + u32 I2CDataLenBak = 0; + u32 I2CDataPtrBak = 0; + u32 I2CInTOTcntRty = 0; + u32 InTimeoutCountRty = 0; + u32 InStartCountRty = 0; + + + /*To Get the SAL_I2C_MNGT_ADPT Pointer*/ + pSalI2CHNDPriv = CONTAINER_OF(pSalI2CHND, SAL_I2C_HND_PRIV, SalI2CHndPriv); + pSalI2CMngtAdpt = CONTAINER_OF(pSalI2CHNDPriv->ppSalI2CHnd, SAL_I2C_MNGT_ADPT, pSalHndPriv); + pHalI2CInitDat = pSalI2CMngtAdpt->pHalInitDat; + pHalI2COP = pSalI2CMngtAdpt->pHalOp; +#if I2C_DMA_OP_TYPE + pHalI2CRxGdmaAdpt = pSalI2CMngtAdpt->pHalRxGdmaAdp; + pHalI2CGdmaOp = pSalI2CMngtAdpt->pHalGdmaOp; +#endif + + if (pSalI2CHND->I2CMaster == I2C_MASTER_MODE)/*if (pSalI2CHND->I2CMaster == I2C_MASTER_MODE)*/ + { + /* Master run-time update target address */ + if (pSalI2CHND->I2CExd & I2C_EXD_MTR_ADDR_UPD) { + /* Calculate user time out parameters */ + I2CInTOTcnt = pSalI2CHND->TimeOut; + if ((I2CInTOTcnt != 0) && (I2CInTOTcnt != I2C_TIMEOOUT_ENDLESS)) { + InTimeoutCount = (I2CInTOTcnt*1000/TIMER_TICK_US); + InStartCount = HalTimerOp.HalTimerReadCount(1); + } + + /* Check Master activity status */ + while ((pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_STATUS)) & BIT_IC_STATUS_MST_ACTIVITY) { + pHalI2COP->HalI2CClrAllIntr(pHalI2CInitDat); + //DBG_8195A("~\n"); + /* Time-Out check */ + if (InTimeoutCount > 0) { + if (HAL_TIMEOUT == I2CIsTimeout(InStartCount, InTimeoutCount)) { + pSalI2CHND->DevSts = I2C_STS_TIMEOUT; + pSalI2CHND->ErrType = I2C_ERR_RX_ADD_TO; + DBG_I2C_ERR("RtkI2CReceive Timeout, I2C%2x,1\n",pSalI2CHND->DevNum); + DBG_I2C_ERR("DevSts:%x, ErrType:%x\n", pSalI2CHND->DevSts, pSalI2CHND->ErrType); + return HAL_TIMEOUT; + } + } + else { + if (I2CInTOTcnt == 0) { + pSalI2CHND->DevSts = I2C_STS_TIMEOUT; + pSalI2CHND->ErrType = I2C_ERR_RX_ADD_TO; + DBG_I2C_ERR("RtkI2CReceive Timeout, I2C%2x,2\n",pSalI2CHND->DevNum); + DBG_I2C_ERR("DevSts:%x, ErrType:%x\n", pSalI2CHND->DevSts, pSalI2CHND->ErrType); + return HAL_TIMEOUT; + } + } + } + + /* Calculate user time out parameters */ + I2CInTOTcnt = pSalI2CHND->TimeOut; + if ((I2CInTOTcnt != 0) && (I2CInTOTcnt != I2C_TIMEOOUT_ENDLESS)) { + InTimeoutCount = (I2CInTOTcnt*1000/TIMER_TICK_US); + InStartCount = HalTimerOp.HalTimerReadCount(1); + } + + /* Check TX FIFO status */ + while (!((pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_STATUS)) & BIT_IC_STATUS_TFE)) { + /* Time-Out check */ + if (InTimeoutCount > 0) { + if (HAL_TIMEOUT == I2CIsTimeout(InStartCount, InTimeoutCount)) { + pSalI2CHND->DevSts = I2C_STS_TIMEOUT; + pSalI2CHND->ErrType = I2C_ERR_RX_ADD_TO; + DBG_I2C_ERR("RtkI2CReceive Timeout, I2C%2x,3\n",pSalI2CHND->DevNum); + DBG_I2C_ERR("DevSts:%x, ErrType:%x\n", pSalI2CHND->DevSts, pSalI2CHND->ErrType); + return HAL_TIMEOUT; + } + } + else { + if (I2CInTOTcnt == 0) { + pSalI2CHND->DevSts = I2C_STS_TIMEOUT; + pSalI2CHND->ErrType = I2C_ERR_RX_ADD_TO; + DBG_I2C_ERR("RtkI2CReceive Timeout, I2C%2x,4\n",pSalI2CHND->DevNum); + DBG_I2C_ERR("DevSts:%x, ErrType:%x\n", pSalI2CHND->DevSts, pSalI2CHND->ErrType); + return HAL_TIMEOUT; + } + } + } + + I2CLocalTemp = pHalI2COP->HalI2CReadReg(pHalI2CInitDat, REG_DW_I2C_IC_TAR); + I2CLocalTemp &= (~BIT_MASK_IC_TAR); + I2CLocalTemp |= BIT_CTRL_IC_TAR(pSalI2CHND->pRXBuf->TargetAddr); + /* Update Master Target address */ + pHalI2COP->HalI2CWriteReg(pHalI2CInitDat, REG_DW_I2C_IC_TAR, I2CLocalTemp); + } + + +#if I2C_USER_REG_ADDR /*I2C_USER_REG_ADDR*/ + RtkI2CSendUserAddr(pSalI2CHND, 1); +#endif /*I2C_USER_REG_ADDR*/ + +#if I2C_POLL_OP_TYPE/*I2C_POLL_OP_TYPE*/ + if (pSalI2CHND->OpType == I2C_POLL_TYPE) + { + //DBG_8195A("p\n"); + /* I2C Device Status Update */ + pSalI2CHND->DevSts = I2C_STS_RX_READY; + + pSalI2CMngtAdpt->MstRDCmdCnt = pSalI2CHND->pRXBuf->DataLen; + I2CLocalTemp = pSalI2CHND->pRXBuf->DataLen; + + /* Calculate user time out parameters */ + I2CInTOTcnt = pSalI2CHND->TimeOut; + if ((I2CInTOTcnt != 0) && (I2CInTOTcnt != I2C_TIMEOOUT_ENDLESS)) { + InTimeoutCount = (I2CInTOTcnt*1000/TIMER_TICK_US); + InStartCount = HalTimerOp.HalTimerReadCount(1); + } + + /* Receive data till the RX buffer data length is zero */ + for ( ;pSalI2CHND->pRXBuf->DataLen>0; ) { +SEND_I2C_RD_CMD: + /* I2C Device Status Update */ + pSalI2CHND->DevSts = I2C_STS_RX_ING; + /* Check I2C TX FIFO status. If it's NOT full, a Read command is written + into the TX FIFO.*/ + if (pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_STATUS) + & BIT_IC_STATUS_TFNF) { + if (pSalI2CMngtAdpt->MstRDCmdCnt > 0) { + pHalI2CInitDat->I2CCmd = I2C_READ_CMD; + pHalI2CInitDat->I2CDataLen= 1; + pHalI2CInitDat->I2CRWData = pSalI2CHND->pRXBuf->pDataBuf; + pHalI2CInitDat->I2CStop = I2C_STOP_DIS; + if ((pSalI2CMngtAdpt->MstRDCmdCnt == 1) && ((pSalI2CHND->I2CExd & I2C_EXD_MTR_HOLD_BUS) == 0)){ + pHalI2CInitDat->I2CStop = I2C_STOP_EN; + } + pHalI2COP->HalI2CMassSend(pHalI2CInitDat); + if (pSalI2CMngtAdpt->MstRDCmdCnt > 0) + pSalI2CMngtAdpt->MstRDCmdCnt--; + } + } + + if (I2CLocalTemp == pSalI2CHND->pRXBuf->DataLen){ + if (pSalI2CHND->I2CExd & I2C_EXD_MTR_ADDR_RTY) { + HalDelayUs(((1000*30)/pHalI2CInitDat->I2CClk)); //the 10 is for ten bit time + if (pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_RAW_INTR_STAT) & + BIT_IC_RAW_INTR_STAT_TX_ABRT) { + pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_CLR_TX_ABRT); + pSalI2CMngtAdpt->MstRDCmdCnt++; + goto SEND_I2C_RD_CMD; + } + } + } + + /* Contineously poll the I2C RX FIFO status */ + while (1) { + if ((pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_STATUS) + & (BIT_IC_STATUS_RFNE | BIT_IC_STATUS_RFF)) != 0) { + *(pSalI2CHND->pRXBuf->pDataBuf) = + pHalI2COP->HalI2CReceive(pHalI2CInitDat); + + pSalI2CHND->pRXBuf->pDataBuf++; + pSalI2CHND->pRXBuf->DataLen--; + + if (!pSalI2CHND->pRXBuf->DataLen) { + break; + } + } + else { + break; + } + } + + /* Time-Out check */ + if (InTimeoutCount > 0) { + if (HAL_TIMEOUT == I2CIsTimeout(InStartCount, InTimeoutCount)) { + pSalI2CHND->DevSts = I2C_STS_TIMEOUT; + pSalI2CHND->ErrType = I2C_ERR_RX_FF_TO; + DBG_I2C_ERR("RtkI2CReceive Timeout, I2C%2x,5\n",pSalI2CHND->DevNum); + DBG_I2C_ERR("DevSts:%x, ErrType:%x\n", pSalI2CHND->DevSts, pSalI2CHND->ErrType); + return HAL_TIMEOUT; + } + } + else { + if (I2CInTOTcnt == 0) { + pSalI2CHND->DevSts = I2C_STS_TIMEOUT; + pSalI2CHND->ErrType = I2C_ERR_RX_FF_TO; + DBG_I2C_ERR("RtkI2CReceive Timeout, I2C%2x,6\n",pSalI2CHND->DevNum); + DBG_I2C_ERR("DevSts:%x, ErrType:%x\n", pSalI2CHND->DevSts, pSalI2CHND->ErrType); + return HAL_TIMEOUT; + } + } + + } + + /* I2C Device Status Update */ + pSalI2CHND->DevSts = I2C_STS_IDLE; + } +#endif/*I2C_POLL_OP_TYPE*/ + +#if I2C_INTR_OP_TYPE/*I2C_INTR_OP_TYPE*/ + if (pSalI2CHND->OpType == I2C_INTR_TYPE) { + /* Calculate user time out parameters */ + InTimeoutCount= 0; + InStartCount = 0; + I2CInTOTcnt = pSalI2CMngtAdpt->InnerTimeOut; + if ((I2CInTOTcnt!= 0) && (I2CInTOTcnt!= I2C_TIMEOOUT_ENDLESS)) { + InTimeoutCount = (I2CInTOTcnt*1000/TIMER_TICK_US); + InStartCount= HalTimerOp.HalTimerReadCount(1); + } + I2CDataLenBak = (u32)(pSalI2CHND->pRXBuf->DataLen); + I2CDataPtrBak = (u32)(pSalI2CHND->pRXBuf->pDataBuf); + + /* I2C Device Status Update */ + pSalI2CHND->DevSts = I2C_STS_RX_READY; + pHalI2CInitDat->I2CIntrClr = REG_DW_I2C_IC_CLR_TX_ABRT; + pHalI2COP->HalI2CClrIntr(pHalI2CInitDat); + pHalI2CInitDat->I2CIntrClr = REG_DW_I2C_IC_CLR_ACTIVITY; + pHalI2COP->HalI2CClrIntr(pHalI2CInitDat); + pHalI2COP->HalI2CClrAllIntr(pHalI2CInitDat); + + /* Clear RX FIFO */ + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_RXFLR); + while (I2CChkRawSts > 0){ + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_RXFLR); + } + + /* To fill the Master Read Command into TX FIFO */ + pSalI2CMngtAdpt->MstRDCmdCnt = pSalI2CHND->pRXBuf->DataLen; + I2CLocalLen = 2;//pSalI2CHND->pRXBuf->DataLen; + pSalI2CHND->DevSts = I2C_STS_RX_READY; + + + while (1) { +SEND_I2C_RD_CMD_INTR: + + /* Calculate user time out parameters */ + InTimeoutCountRty = 0; + InStartCountRty = 0; + I2CInTOTcntRty = pSalI2CHND->TimeOut; + + if ((I2CInTOTcntRty != 0) && (I2CInTOTcntRty!= I2C_TIMEOOUT_ENDLESS)) { + InTimeoutCountRty= (I2CInTOTcntRty*1000/TIMER_TICK_US); + InStartCountRty= HalTimerOp.HalTimerReadCount(1); + } + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_STATUS); + + if ((pSalI2CMngtAdpt->MstRDCmdCnt > 0) && (I2CLocalLen > 0)){ + pHalI2CInitDat->I2CCmd = I2C_READ_CMD; + pHalI2CInitDat->I2CDataLen= 1; + pHalI2CInitDat->I2CRWData = pSalI2CHND->pRXBuf->pDataBuf; + pHalI2CInitDat->I2CStop = I2C_STOP_DIS; + + if ((pSalI2CMngtAdpt->MstRDCmdCnt == 1) && ((pSalI2CHND->I2CExd & I2C_EXD_MTR_HOLD_BUS) == 0)){ + pHalI2CInitDat->I2CStop = I2C_STOP_EN; + } + + pHalI2COP->HalI2CMassSend(pHalI2CInitDat); + } + + if (pSalI2CHND->I2CExd & I2C_EXD_MTR_ADDR_RTY) { + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_STATUS); + while ((I2CChkRawSts & BIT_IC_STATUS_TFE) == 0) { + I2CChkRawSts2 = pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_RAW_INTR_STAT); + if ((I2CChkRawSts2 & BIT_IC_RAW_INTR_STAT_TX_ABRT) != 0){ + break; + } + + /* Time-Out check */ + if (InTimeoutCountRty > 0) { + if (HAL_TIMEOUT == I2CIsTimeout(InStartCountRty, InTimeoutCountRty)) { + break; + } + } + else { + if (I2CInTOTcntRty == 0) { + break; + } + } + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_STATUS); + + } + + HalDelayUs(((1000*30)/pHalI2CInitDat->I2CClk)); //the 10 is for ten bit time + + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_RAW_INTR_STAT); + I2CChkRawSts2 = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_STATUS); + if (I2CChkRawSts & BIT_IC_RAW_INTR_STAT_TX_ABRT) { + + RtkI2CDeInit(pSalI2CHND); + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_ENABLE_STATUS); + while((I2CChkRawSts & BIT_IC_ENABLE_STATUS_IC_EN) == BIT_IC_ENABLE_STATUS_IC_EN){ + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_ENABLE_STATUS); + } + RtkI2CInit(pSalI2CHND); + + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_ENABLE_STATUS); + while((I2CChkRawSts & BIT_IC_ENABLE_STATUS_IC_EN) != BIT_IC_ENABLE_STATUS_IC_EN){ + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_ENABLE_STATUS); + } + pSalI2CHND->DevSts = I2C_STS_RX_READY; + pSalI2CHND->ErrType = 0; + pSalI2CHND->pRXBuf->DataLen = (u16)I2CDataLenBak; + pSalI2CHND->pRXBuf->pDataBuf= (u8 *)I2CDataPtrBak; + + /* Calculate user time out parameters */ + InTimeoutCount = 0; + InStartCount = 0; + I2CInTOTcnt = pSalI2CMngtAdpt->InnerTimeOut; + if ((I2CInTOTcnt != 0) && (I2CInTOTcnt != I2C_TIMEOOUT_ENDLESS)) { + InTimeoutCount = (I2CInTOTcnt*1000/TIMER_TICK_US); + InStartCount = HalTimerOp.HalTimerReadCount(1); + } + goto SEND_I2C_RD_CMD_INTR; + } + else if ((I2CChkRawSts2 & BIT_IC_STATUS_TFE) != BIT_IC_STATUS_TFE){ + RtkI2CDeInit(pSalI2CHND); + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_ENABLE_STATUS); + while((I2CChkRawSts & BIT_IC_ENABLE_STATUS_IC_EN) == BIT_IC_ENABLE_STATUS_IC_EN){ + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_ENABLE_STATUS); + } + RtkI2CInit(pSalI2CHND); + + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_ENABLE_STATUS); + while((I2CChkRawSts & BIT_IC_ENABLE_STATUS_IC_EN) != BIT_IC_ENABLE_STATUS_IC_EN){ + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_ENABLE_STATUS); + } + pSalI2CHND->DevSts = I2C_STS_RX_READY; + pSalI2CHND->ErrType = 0; + pSalI2CHND->pRXBuf->DataLen = (u16)I2CDataLenBak; + pSalI2CHND->pRXBuf->pDataBuf= (u8 *)I2CDataPtrBak; + + /* Calculate user time out parameters */ + InTimeoutCount = 0; + InStartCount = 0; + I2CInTOTcnt = pSalI2CMngtAdpt->InnerTimeOut; + if ((I2CInTOTcnt != 0) && (I2CInTOTcnt != I2C_TIMEOOUT_ENDLESS)) { + InTimeoutCount = (I2CInTOTcnt*1000/TIMER_TICK_US); + InStartCount = HalTimerOp.HalTimerReadCount(1); + } + goto SEND_I2C_RD_CMD_INTR; + } + else { + I2CChkRawSts2 = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_STATUS); + //if ((I2CChkRawSts2 & BIT_IC_STATUS_RFNE) == BIT_IC_STATUS_RFNE) + { + //DBG_8195A("h\n"); + if (I2CLocalLen>0){ + I2CLocalLen--; + pSalI2CMngtAdpt->MstRDCmdCnt --; + } + } + } + } + else { + if (I2CLocalLen>0) { + I2CLocalLen--; + pSalI2CMngtAdpt->MstRDCmdCnt --; + } + } + + if ((I2CLocalLen == 0) || (pSalI2CHND->pRXBuf->DataLen == 1)){ + pHalI2CInitDat->I2CIntrClr = REG_DW_I2C_IC_CLR_TX_ABRT; + pHalI2COP->HalI2CClrIntr(pHalI2CInitDat); + I2CLocalTemp = 0; + I2CLocalTemp = pHalI2COP->HalI2CReadReg(pHalI2CInitDat, REG_DW_I2C_IC_INTR_MASK); + I2CLocalTemp |= (BIT_IC_INTR_MASK_M_RX_FULL | + BIT_IC_INTR_MASK_M_RX_OVER | + BIT_IC_INTR_MASK_M_RX_UNDER|BIT_IC_INTR_MASK_M_TX_ABRT); + pHalI2CInitDat->I2CIntrMSK = I2CLocalTemp; + pHalI2COP->HalI2CIntrCtrl(pHalI2CInitDat); + break; + } + + /* Time-Out check */ + if (InTimeoutCount > 0) { + if (HAL_TIMEOUT == I2CIsTimeout(InStartCount, InTimeoutCount)) { + pSalI2CHND->DevSts = I2C_STS_TIMEOUT; + pSalI2CHND->ErrType = I2C_ERR_TX_FF_TO; + + RtkI2CDeInit(pSalI2CHND); + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_ENABLE_STATUS); + while((I2CChkRawSts & BIT_IC_ENABLE_STATUS_IC_EN) == BIT_IC_ENABLE_STATUS_IC_EN){ + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_ENABLE_STATUS); + } + RtkI2CInit(pSalI2CHND); + + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_ENABLE_STATUS); + while((I2CChkRawSts & BIT_IC_ENABLE_STATUS_IC_EN) != BIT_IC_ENABLE_STATUS_IC_EN){ + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_ENABLE_STATUS); + } + return HAL_TIMEOUT; + } + } + else { + if (I2CInTOTcnt == 0) { + pSalI2CHND->DevSts = I2C_STS_TIMEOUT; + pSalI2CHND->ErrType = I2C_ERR_TX_FF_TO; + + RtkI2CDeInit(pSalI2CHND); + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_ENABLE_STATUS); + while((I2CChkRawSts & BIT_IC_ENABLE_STATUS_IC_EN) == BIT_IC_ENABLE_STATUS_IC_EN){ + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_ENABLE_STATUS); + } + RtkI2CInit(pSalI2CHND); + + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_ENABLE_STATUS); + while((I2CChkRawSts & BIT_IC_ENABLE_STATUS_IC_EN) != BIT_IC_ENABLE_STATUS_IC_EN){ + I2CChkRawSts = (u32)pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_ENABLE_STATUS); + } + return HAL_TIMEOUT; + } + } + } + + } +#endif/*I2C_INTR_OP_TYPE*/ + }/*if (pSalI2CHND->I2CMaster == I2C_MASTER_MODE)*/ + else + { +#if I2C_POLL_OP_TYPE + if (pSalI2CHND->OpType == I2C_POLL_TYPE) { + /* Calculate user time out parameters */ + I2CInTOTcnt = pSalI2CHND->TimeOut; + if ((I2CInTOTcnt != 0) && (I2CInTOTcnt != I2C_TIMEOOUT_ENDLESS)) { + InTimeoutCount = (I2CInTOTcnt*1000/TIMER_TICK_US); + InStartCount = HalTimerOp.HalTimerReadCount(1); + } + + /* Receive data till the RX buffer data length is zero */ + for (;pSalI2CHND->pRXBuf->DataLen>0; ) { + if ((pHalI2COP->HalI2CReadReg(pHalI2CInitDat,REG_DW_I2C_IC_STATUS) + & (BIT_IC_STATUS_RFNE | BIT_IC_STATUS_RFF)) != 0) { + *(pSalI2CHND->pRXBuf->pDataBuf) = + pHalI2COP->HalI2CReceive(pHalI2CInitDat); + pSalI2CHND->pRXBuf->pDataBuf++; + pSalI2CHND->pRXBuf->DataLen--; + } + else { + /* Time-Out check */ + if (InTimeoutCount > 0) { + if (HAL_TIMEOUT == I2CIsTimeout(InStartCount, InTimeoutCount)) { + pSalI2CHND->DevSts = I2C_STS_TIMEOUT; + pSalI2CHND->ErrType = I2C_ERR_RX_FF_TO; + DBG_I2C_ERR("RtkI2CReceive Timeout, I2C%2x,9\n",pSalI2CHND->DevNum); + DBG_I2C_ERR("DevSts:%x, ErrType:%x\n", pSalI2CHND->DevSts, pSalI2CHND->ErrType); + return HAL_TIMEOUT; + } + } + else { + if (I2CInTOTcnt == 0) { + pSalI2CHND->DevSts = I2C_STS_TIMEOUT; + pSalI2CHND->ErrType = I2C_ERR_RX_FF_TO; + DBG_I2C_ERR("RtkI2CReceive Timeout, I2C%2x,10\n",pSalI2CHND->DevNum); + DBG_I2C_ERR("DevSts:%x, ErrType:%x\n", pSalI2CHND->DevSts, pSalI2CHND->ErrType); + return HAL_TIMEOUT; + } + } + } + } + + /* I2C Device Status Update */ + pSalI2CHND->DevSts = I2C_STS_IDLE; + } +#endif + +#if I2C_INTR_OP_TYPE/*I2C_INTR_OP_TYPE*/ + if (pSalI2CHND->OpType == I2C_INTR_TYPE) { + pSalI2CHND->DevSts = I2C_STS_RX_READY; + + /*I2C Enable RX Related Interrupts*/ + I2CLocalTemp = pHalI2COP->HalI2CReadReg(pHalI2CInitDat, REG_DW_I2C_IC_INTR_MASK); + I2CLocalTemp |= (BIT_IC_INTR_MASK_M_RX_FULL | + BIT_IC_INTR_MASK_M_RX_OVER | + BIT_IC_INTR_MASK_M_RX_UNDER); + pHalI2CInitDat->I2CIntrMSK = I2CLocalTemp; + pHalI2COP->HalI2CIntrCtrl(pHalI2CInitDat); + } +#endif/*I2C_INTR_OP_TYPE*/ + +#if I2C_DMA_OP_TYPE/*I2C_INTR_OP_TYPE*/ + if (pSalI2CHND->OpType == I2C_DMA_TYPE) { + pSalI2CHND->DevSts = I2C_STS_RX_READY; + + /*I2C Enable RX Related Interrupts*/ + I2CLocalTemp = pHalI2COP->HalI2CReadReg(pHalI2CInitDat, REG_DW_I2C_IC_INTR_MASK); + I2CLocalTemp |= (BIT_IC_INTR_MASK_M_RX_OVER | + BIT_IC_INTR_MASK_M_RX_UNDER); + pHalI2CInitDat->I2CIntrMSK = I2CLocalTemp; + pHalI2COP->HalI2CIntrCtrl(pHalI2CInitDat); + + //HalGdmaOpInit(pHalI2CGdmaOp); + pSalI2CMngtAdpt->pHalGdmaOpInit(pHalI2CGdmaOp); + + pHalI2CRxGdmaAdpt->GdmaCtl.BlockSize = pSalI2CHND->pRXBuf->DataLen; + pHalI2CRxGdmaAdpt->ChSar = (u32)(I2C0_REG_BASE+REG_DW_I2C_IC_DATA_CMD+ + pSalI2CHND->DevNum*0x400); + pHalI2CRxGdmaAdpt->ChDar = (u32)pSalI2CHND->pRXBuf->pDataBuf; + + pHalI2CGdmaOp->HalGdmaChSeting(pHalI2CRxGdmaAdpt); + pHalI2CGdmaOp->HalGdmaChEn(pHalI2CRxGdmaAdpt); + pSalI2CHND->DevSts = I2C_STS_RX_ING; + pHalI2CInitDat->I2CDMACtrl = BIT_CTRL_IC_DMA_CR_RDMAE(1); + pHalI2COP->HalI2CDMACtrl(pHalI2CInitDat); + } +#endif/*I2C_INTR_OP_TYPE*/ + + } + + return HAL_OK; +} +#endif + +#ifndef CONFIG_MBED_ENABLED +//--------------------------------------------------------------------------------------------------- +//Function Name: +// RtkI2CGetMngtAdpt +// +// Description: +// According to the input index, all the memory space are allocated and all the +// related pointers are assigned. The management adapter pointer will be +// returned. +// +// Arguments: +// [in] u8 I2CIdx - +// I2C module index +// +// Return: +// PSAL_I2C_MNGT_ADPT +// +// Note: +// NA +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-04-02. +// +//--------------------------------------------------------------------------------------------------- +PSAL_I2C_MNGT_ADPT +RtkI2CGetMngtAdpt( + IN u8 I2CIdx +){ + PSAL_I2C_MNGT_ADPT pSalI2CMngtAdpt = NULL; + PSAL_I2C_USERCB_ADPT pSalI2CUserCBAdpt = NULL; + + /* If the kernel is available, Memory-allocation is used. */ +#ifdef I2C_STATIC_ALLOC + + pSalI2CMngtAdpt = (PSAL_I2C_MNGT_ADPT)RtlZmalloc(sizeof(SAL_I2C_MNGT_ADPT)); + pSalI2CMngtAdpt->pSalHndPriv = (PSAL_I2C_HND_PRIV)RtlZmalloc(sizeof(SAL_I2C_HND_PRIV)); + pSalI2CMngtAdpt->pHalInitDat = (PHAL_I2C_INIT_DAT)RtlZmalloc(sizeof(HAL_I2C_INIT_DAT)); + pSalI2CMngtAdpt->pHalOp = (PHAL_I2C_OP)RtlZmalloc(sizeof(HAL_I2C_OP)); + pSalI2CMngtAdpt->pIrqHnd = (PIRQ_HANDLE)RtlZmalloc(sizeof(IRQ_HANDLE)); + pSalI2CMngtAdpt->pHalTxGdmaAdp = (PHAL_GDMA_ADAPTER)RtlZmalloc(sizeof(HAL_GDMA_ADAPTER)); + pSalI2CMngtAdpt->pHalRxGdmaAdp = (PHAL_GDMA_ADAPTER)RtlZmalloc(sizeof(HAL_GDMA_ADAPTER)); + pSalI2CMngtAdpt->pHalGdmaOp = (PHAL_GDMA_OP)RtlZmalloc(sizeof(HAL_GDMA_OP)); + pSalI2CMngtAdpt->pIrqTxGdmaHnd = (PIRQ_HANDLE)RtlZmalloc(sizeof(IRQ_HANDLE)); + pSalI2CMngtAdpt->pIrqRxGdmaHnd = (PIRQ_HANDLE)RtlZmalloc(sizeof(IRQ_HANDLE)); + pSalI2CMngtAdpt->pUserCB = (PSAL_I2C_USER_CB)RtlZmalloc(sizeof(SAL_I2C_USER_CB)); + pSalI2CMngtAdpt->pDMAConf = (PSAL_I2C_DMA_USER_DEF)RtlZmalloc(sizeof(SAL_I2C_DMA_USER_DEF)); + pSalI2CUserCBAdpt = (PSAL_I2C_USERCB_ADPT)RtlZmalloc((sizeof(SAL_I2C_USERCB_ADPT)*SAL_USER_CB_NUM)); +#else + switch (I2CIdx){ + case I2C0_SEL: + { + pSalI2CMngtAdpt = &SalI2C0MngtAdpt; + pSalI2CMngtAdpt->pSalHndPriv = &SalI2C0HndPriv; + pSalI2CMngtAdpt->pHalInitDat = &HalI2C0InitData; + pSalI2CMngtAdpt->pHalOp = &HalI2COpSAL; + pSalI2CMngtAdpt->pIrqHnd = &I2C0IrqHandleDat; + pSalI2CMngtAdpt->pHalTxGdmaAdp = &HalI2C0TxGdmaAdpt; + pSalI2CMngtAdpt->pHalRxGdmaAdp = &HalI2C0RxGdmaAdpt; + pSalI2CMngtAdpt->pHalGdmaOp = &HalI2C0GdmaOp; + pSalI2CMngtAdpt->pIrqTxGdmaHnd = &I2C0TxGdmaIrqHandleDat; + pSalI2CMngtAdpt->pIrqRxGdmaHnd = &I2C0RxGdmaIrqHandleDat; + pSalI2CMngtAdpt->pUserCB = &SalI2C0UserCB; + pSalI2CMngtAdpt->pDMAConf = &SalI2C0DmaUserDef; + pSalI2CUserCBAdpt = (PSAL_I2C_USERCB_ADPT)&SalI2C0UserCBAdpt; + break; + } + + case I2C1_SEL: + { + pSalI2CMngtAdpt = &SalI2C1MngtAdpt; + pSalI2CMngtAdpt->pSalHndPriv = &SalI2C1HndPriv; + pSalI2CMngtAdpt->pHalInitDat = &HalI2C1InitData; + pSalI2CMngtAdpt->pHalOp = &HalI2COpSAL; + pSalI2CMngtAdpt->pIrqHnd = &I2C1IrqHandleDat; + pSalI2CMngtAdpt->pHalTxGdmaAdp = &HalI2C1TxGdmaAdpt; + pSalI2CMngtAdpt->pHalRxGdmaAdp = &HalI2C1RxGdmaAdpt; + pSalI2CMngtAdpt->pHalGdmaOp = &HalI2C1GdmaOp; + pSalI2CMngtAdpt->pIrqTxGdmaHnd = &I2C1TxGdmaIrqHandleDat; + pSalI2CMngtAdpt->pIrqRxGdmaHnd = &I2C1RxGdmaIrqHandleDat; + pSalI2CMngtAdpt->pUserCB = &SalI2C1UserCB; + pSalI2CMngtAdpt->pDMAConf = &SalI2C1DmaUserDef; + pSalI2CUserCBAdpt = (PSAL_I2C_USERCB_ADPT)&SalI2C1UserCBAdpt; + break; + } + + case I2C2_SEL: + { + pSalI2CMngtAdpt = &SalI2C2MngtAdpt; + pSalI2CMngtAdpt->pSalHndPriv = &SalI2C2HndPriv; + pSalI2CMngtAdpt->pHalInitDat = &HalI2C2InitData; + pSalI2CMngtAdpt->pHalOp = &HalI2COpSAL; + pSalI2CMngtAdpt->pIrqHnd = &I2C2IrqHandleDat; + pSalI2CMngtAdpt->pHalTxGdmaAdp = &HalI2C2TxGdmaAdpt; + pSalI2CMngtAdpt->pHalRxGdmaAdp = &HalI2C2RxGdmaAdpt; + pSalI2CMngtAdpt->pHalGdmaOp = &HalI2C2GdmaOp; + pSalI2CMngtAdpt->pIrqTxGdmaHnd = &I2C2TxGdmaIrqHandleDat; + pSalI2CMngtAdpt->pIrqRxGdmaHnd = &I2C2RxGdmaIrqHandleDat; + pSalI2CMngtAdpt->pUserCB = &SalI2C2UserCB; + pSalI2CMngtAdpt->pDMAConf = &SalI2C2DmaUserDef; + pSalI2CUserCBAdpt = (PSAL_I2C_USERCB_ADPT)&SalI2C2UserCBAdpt; + break; + } + + case I2C3_SEL: + { + pSalI2CMngtAdpt = &SalI2C3MngtAdpt; + pSalI2CMngtAdpt->pSalHndPriv = &SalI2C3HndPriv; + pSalI2CMngtAdpt->pHalInitDat = &HalI2C3InitData; + pSalI2CMngtAdpt->pHalOp = &HalI2COpSAL; + pSalI2CMngtAdpt->pIrqHnd = &I2C3IrqHandleDat; + pSalI2CMngtAdpt->pHalTxGdmaAdp = &HalI2C3TxGdmaAdpt; + pSalI2CMngtAdpt->pHalRxGdmaAdp = &HalI2C3RxGdmaAdpt; + pSalI2CMngtAdpt->pHalGdmaOp = &HalI2C3GdmaOp; + pSalI2CMngtAdpt->pIrqTxGdmaHnd = &I2C3TxGdmaIrqHandleDat; + pSalI2CMngtAdpt->pIrqRxGdmaHnd = &I2C3RxGdmaIrqHandleDat; + pSalI2CMngtAdpt->pUserCB = &SalI2C3UserCB; + pSalI2CMngtAdpt->pDMAConf = &SalI2C3DmaUserDef; + pSalI2CUserCBAdpt = (PSAL_I2C_USERCB_ADPT)&SalI2C3UserCBAdpt; + break; + } + + default + break; + } +#endif + + /*To assign user callback pointers*/ + pSalI2CMngtAdpt->pUserCB->pTXCB = pSalI2CUserCBAdpt; + pSalI2CMngtAdpt->pUserCB->pTXCCB = (pSalI2CUserCBAdpt+1); + pSalI2CMngtAdpt->pUserCB->pRXCB = (pSalI2CUserCBAdpt+2); + pSalI2CMngtAdpt->pUserCB->pRXCCB = (pSalI2CUserCBAdpt+3); + pSalI2CMngtAdpt->pUserCB->pRDREQCB = (pSalI2CUserCBAdpt+4); + pSalI2CMngtAdpt->pUserCB->pERRCB = (pSalI2CUserCBAdpt+5); + pSalI2CMngtAdpt->pUserCB->pDMATXCB = (pSalI2CUserCBAdpt+6); + pSalI2CMngtAdpt->pUserCB->pDMATXCCB = (pSalI2CUserCBAdpt+7); + pSalI2CMngtAdpt->pUserCB->pDMARXCB = (pSalI2CUserCBAdpt+8); + pSalI2CMngtAdpt->pUserCB->pDMARXCCB = (pSalI2CUserCBAdpt+9); + pSalI2CMngtAdpt->pUserCB->pGENCALLCB= (pSalI2CUserCBAdpt+10); + + /*To assign the rest pointers*/ + pSalI2CMngtAdpt->MstRDCmdCnt = 0; + pSalI2CMngtAdpt->InnerTimeOut = 2000; // inner time-out count, 2000 ms + pSalI2CMngtAdpt->pSalHndPriv->ppSalI2CHnd = (void**)&(pSalI2CMngtAdpt->pSalHndPriv); + + /* To assign the default (ROM) HAL OP initialization function */ +#if defined(CONFIG_CHIP_A_CUT) || defined(CONFIG_CHIP_B_CUT) + pSalI2CMngtAdpt->pHalOpInit = &HalI2COpInit; +#elif defined(CONFIG_CHIP_C_CUT) + pSalI2CMngtAdpt->pHalOpInit = &HalI2COpInitV02; +#endif + + /* To assign the default (ROM) HAL GDMA OP initialization function */ + pSalI2CMngtAdpt->pHalGdmaOpInit = &HalGdmaOpInit; + + /* To assign the default (ROM) SAL interrupt function */ +#ifndef CONFIG_CHIP_D_CUT + pSalI2CMngtAdpt->pSalIrqFunc = &I2CISRHandle; +#endif + + /* To assign the default (ROM) SAL DMA TX interrupt function */ + pSalI2CMngtAdpt->pSalDMATxIrqFunc = &I2CTXGDMAISRHandle; + + /* To assign the default (ROM) SAL DMA RX interrupt function */ + pSalI2CMngtAdpt->pSalDMARxIrqFunc = &I2CRXGDMAISRHandle; + + return pSalI2CMngtAdpt; +} + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// RtkI2CFreeMngtAdpt +// +// Description: +// Free all the previous allocated memory space. +// +// Arguments: +// [in] PSAL_I2C_MNGT_ADPT pSalI2CMngtAdpt - +// I2C SAL management adapter pointer +// +// +// Return: +// The status of the enable process. +// _EXIT_SUCCESS if the RtkI2CFreeMngtAdpt succeeded. +// _EXIT_FAILURE if the RtkI2CFreeMngtAdpt failed. +// +// Note: +// NA +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-04-02. +// +//--------------------------------------------------------------------------------------------------- +HAL_Status +RtkI2CFreeMngtAdpt( + IN PSAL_I2C_MNGT_ADPT pSalI2CMngtAdpt +){ +#ifdef I2C_STATIC_ALLOC + RtlMfree((u8 *)pSalI2CMngtAdpt->pUserCB->pTXCB, (sizeof(SAL_I2C_USERCB_ADPT)*SAL_USER_CB_NUM)); + RtlMfree((u8 *)pSalI2CMngtAdpt->pDMAConf, (sizeof(SAL_I2C_DMA_USER_DEF))); + RtlMfree((u8 *)pSalI2CMngtAdpt->pIrqRxGdmaHnd, (sizeof(IRQ_HANDLE))); + RtlMfree((u8 *)pSalI2CMngtAdpt->pIrqTxGdmaHnd, (sizeof(IRQ_HANDLE))); + RtlMfree((u8 *)pSalI2CMngtAdpt->pHalGdmaOp, (sizeof(HAL_GDMA_OP))); + RtlMfree((u8 *)pSalI2CMngtAdpt->pHalRxGdmaAdp, (sizeof(HAL_GDMA_ADAPTER))); + RtlMfree((u8 *)pSalI2CMngtAdpt->pHalTxGdmaAdp, (sizeof(HAL_GDMA_ADAPTER))); + RtlMfree((u8 *)pSalI2CMngtAdpt->pUserCB, sizeof(SAL_I2C_USER_CB)); + RtlMfree((u8 *)pSalI2CMngtAdpt->pIrqHnd, sizeof(IRQ_HANDLE)); + RtlMfree((u8 *)pSalI2CMngtAdpt->pHalOp, sizeof(HAL_I2C_OP)); + RtlMfree((u8 *)pSalI2CMngtAdpt->pHalInitDat, sizeof(HAL_I2C_INIT_DAT)); + RtlMfree((u8 *)pSalI2CMngtAdpt->pSalHndPriv, sizeof(SAL_I2C_HND_PRIV)); + RtlMfree((u8 *)pSalI2CMngtAdpt, sizeof(SAL_I2C_MNGT_ADPT)); +#else + ; +#endif + + return HAL_OK; +} + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// RtkI2CGetSalHnd +// +// Description: +// Allocation of lower layer memory spaces will be done by invoking RtkI2CGetMngtAdpt +// in this function and return a SAL_I2C_HND pointer to upper layer. +// According to the given I2C index, RtkI2CGetMngtAdpt will allocate all the memory +// space such as SAL_I2C_HND, HAL_I2C_INIT_DAT, SAL_I2C_USER_CB etc. +// +// +// Arguments: +// [in] u8 I2CIdx - +// I2C Index +// +// Return: +// PSAL_I2C_HND +// A pointer to SAL_I2C_HND which is allocated in the lower layer. +// Note: +// NA +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-04-03. +// +//---------------------------------------------------------------------------------------------------- +PSAL_I2C_HND +RtkI2CGetSalHnd( + IN u8 I2CIdx +){ + PSAL_I2C_MNGT_ADPT pSalI2CMngtAdpt = NULL; + PSAL_I2C_HND pSalI2CHND = NULL; + + /* Check the user define setting and the given index */ + if (RtkI2CIdxChk(I2CIdx)) { + return (PSAL_I2C_HND)NULL; + } + + /* Invoke RtkI2CGetMngtAdpt to get the I2C SAL management adapter pointer */ + pSalI2CMngtAdpt = RtkI2CGetMngtAdpt(I2CIdx); + + /* Assign the private SAL handle to public SAL handle */ + pSalI2CHND = &(pSalI2CMngtAdpt->pSalHndPriv->SalI2CHndPriv); + + /* Assign the internal HAL initial data pointer to the SAL handle */ + pSalI2CHND->pInitDat = pSalI2CMngtAdpt->pHalInitDat; + + /* Assign the internal user callback pointer to the SAL handle */ + pSalI2CHND->pUserCB = pSalI2CMngtAdpt->pUserCB; + + /* Assign the internal user define DMA configuration to the SAL handle */ + pSalI2CHND->pDMAConf = pSalI2CMngtAdpt->pDMAConf; + + return &(pSalI2CMngtAdpt->pSalHndPriv->SalI2CHndPriv); +} + + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// RtkI2CFreeSalHnd +// +// Description: +// Based on the given pSalI2CHND, the top layer management adapter pointer could +// be reversely parsed. And free memory space is done by RtkI2CFreeMngtAdpt. +// +// +// Arguments: +// [in] PSAL_I2C_HND pSalI2CHND - +// SAL I2C handle +// +// Return: +// The status of the free SAL memory space process. +// _EXIT_SUCCESS if the RtkI2CFreeSalHnd succeeded. +// _EXIT_FAILURE if the RtkI2CFreeSalHnd failed. +// +// Note: +// NA +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-04-03. +// +//---------------------------------------------------------------------------------------------------- +HAL_Status +RtkI2CFreeSalHnd( + IN PSAL_I2C_HND pSalI2CHND +){ + PSAL_I2C_MNGT_ADPT pSalI2CMngtAdpt = NULL; + PSAL_I2C_HND_PRIV pSalI2CHNDPriv = NULL; + + /* To get the SAL_I2C_MNGT_ADPT pointer */ + pSalI2CHNDPriv = CONTAINER_OF(pSalI2CHND, SAL_I2C_HND_PRIV, SalI2CHndPriv); + pSalI2CMngtAdpt = CONTAINER_OF(pSalI2CHNDPriv->ppSalI2CHnd, SAL_I2C_MNGT_ADPT, pSalHndPriv); + + /* Invoke RtkI2CFreeMngtAdpt to free all the lower layer memory space */ + return (RtkI2CFreeMngtAdpt(pSalI2CMngtAdpt)); +} + +#endif // end of "#ifndef CONFIG_MBED_ENABLED" + +//--------------------------------------------------------------------------------------------------- +//Function Name: +// RtkSalI2CSts +// +// Description: +// Get i2c status +// +// Arguments: +// A SAL operation adapter pointer +// +// Return: +// NA +// +// Note: +// NA +// +// See Also: +// NA +// +// Author: +// By Jason Deng, 2014-04-03. +// +//--------------------------------------------------------------------------------------------------- +u32 +RtkSalI2CSts( + IN VOID *Data +){ + PSAL_I2C_HND pSalI2CHND = (PSAL_I2C_HND) Data; + PSAL_I2C_HND_PRIV pSalI2CHNDPriv = NULL; + PSAL_I2C_MNGT_ADPT pSalI2CMngtAdpt = NULL; + PHAL_I2C_INIT_DAT pHalI2CInitDat = NULL; + PHAL_I2C_OP pHalI2COP = NULL; + u32 I2CLocalTemp; + + + /* To Get the SAL_I2C_MNGT_ADPT Pointer */ + pSalI2CHNDPriv = CONTAINER_OF(pSalI2CHND, SAL_I2C_HND_PRIV, SalI2CHndPriv); + pSalI2CMngtAdpt = CONTAINER_OF(pSalI2CHNDPriv->ppSalI2CHnd, SAL_I2C_MNGT_ADPT, pSalHndPriv); + + pHalI2CInitDat = pSalI2CMngtAdpt->pHalInitDat; + pHalI2COP = pSalI2CMngtAdpt->pHalOp; + + I2CLocalTemp = pHalI2COP->HalI2CReadReg(pHalI2CInitDat, REG_DW_I2C_IC_RAW_INTR_STAT); + + if (I2CLocalTemp & BIT_IC_RAW_INTR_STAT_GEN_CALL) { + return 2; + } + else if (I2CLocalTemp & BIT_IC_RAW_INTR_STAT_RD_REQ) { + return 1; + } + + I2CLocalTemp = pHalI2COP->HalI2CReadReg(pHalI2CInitDat, REG_DW_I2C_IC_STATUS); + + if (I2CLocalTemp & BIT_IC_STATUS_RFNE) { + return 3; + } + + return 0; +} diff --git a/component/soc/realtek/8195a/fwlib/src/hal_i2s.c b/component/soc/realtek/8195a/fwlib/src/hal_i2s.c new file mode 100644 index 0000000..3361540 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/src/hal_i2s.c @@ -0,0 +1,415 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + + +#include "rtl8195a.h" +#include "hal_i2s.h" +#include "rand.h" +#include "rtl_utility.h" + + +//1 need to be modified + + +/*====================================================== + Local used variables +*/ +SRAM_BF_DATA_SECTION +HAL_I2S_OP HalI2SOpSAL={0}; + + +VOID +I2SISRHandle( + IN VOID *Data +) +{ + PHAL_I2S_ADAPTER pI2SAdp = (PHAL_I2S_ADAPTER) Data; + PHAL_I2S_OP pHalI2SOP = &HalI2SOpSAL; + PHAL_I2S_INIT_DAT pI2SCfg = pI2SAdp->pInitDat; + u8 I2SIrqIdx = pI2SCfg->I2SIdx; + u32 I2STxIsr, I2SRxIsr; + u8 I2SPageNum = pI2SCfg->I2SPageNum+1; +// u32 I2SPageSize = (pI2SAdp->I2SPageSize+1)<<2; + u32 i; + u32 pbuf; + + I2STxIsr = pHalI2SOP->HalI2SReadReg(pI2SCfg, REG_I2S_TX_STATUS_INT); + I2SRxIsr = pHalI2SOP->HalI2SReadReg(pI2SCfg, REG_I2S_RX_STATUS_INT); + + pI2SCfg->I2STxIntrClr = I2STxIsr; + pI2SCfg->I2SRxIntrClr = I2SRxIsr; + pHalI2SOP->HalI2SClrIntr(pI2SCfg); + + for (i=0 ; iI2SHWTxIdx)) { +// pbuf = ((u32)(pI2SCfg->I2STxData)) + (I2SPageSize*pI2SCfg->I2SHWTxIdx); + pbuf = (u32)pI2SAdp->TxPageList[pI2SCfg->I2SHWTxIdx]; + pI2SAdp->UserCB.TxCCB(pI2SAdp->UserCB.TxCBId, (char*)pbuf); + I2STxIsr &= ~(1<I2SHWTxIdx); + pI2SCfg->I2SHWTxIdx += 1; + if (pI2SCfg->I2SHWTxIdx == I2SPageNum) { + pI2SCfg->I2SHWTxIdx = 0; + } + } + + if (I2SRxIsr & (1<I2SHWRxIdx)) { +// pbuf = ((u32)(pI2SCfg->I2SRxData)) + (I2SPageSize*pI2SCfg->I2SHWRxIdx); + pbuf = (u32)pI2SAdp->RxPageList[pI2SCfg->I2SHWRxIdx]; + pI2SAdp->UserCB.RxCCB(pI2SAdp->UserCB.RxCBId, (char*)pbuf); + I2SRxIsr &= ~(1<I2SHWRxIdx); + pI2SCfg->I2SHWRxIdx += 1; + if (pI2SCfg->I2SHWRxIdx == I2SPageNum) { + pI2SCfg->I2SHWRxIdx = 0; + } + } + } +} + + +static HAL_Status +RtkI2SIrqInit( + IN PHAL_I2S_ADAPTER pI2SAdapter +) +{ + PIRQ_HANDLE pIrqHandle; + + if (pI2SAdapter->DevNum > I2S_MAX_ID) { + DBG_I2S_ERR("RtkI2SIrqInit: Invalid I2S Index(&d)\r\n", pI2SAdapter->DevNum); + return HAL_ERR_PARA; + } + + pIrqHandle = &pI2SAdapter->IrqHandle; + + switch (pI2SAdapter->DevNum){ + case I2S0_SEL: + pIrqHandle->IrqNum = I2S0_PCM0_IRQ; + break; + + case I2S1_SEL: + pIrqHandle->IrqNum = I2S1_PCM1_IRQ; + break; + + default: + return HAL_ERR_PARA; + } + + pIrqHandle->Data = (u32) (pI2SAdapter); + pIrqHandle->IrqFun = (IRQ_FUN) I2SISRHandle; + pIrqHandle->Priority = 3; + InterruptRegister(pIrqHandle); + InterruptEn(pIrqHandle); + + return HAL_OK; +} + +static HAL_Status +RtkI2SIrqDeInit( + IN PHAL_I2S_ADAPTER pI2SAdapter +) +{ + if (pI2SAdapter->DevNum > I2S_MAX_ID) { + DBG_I2S_ERR("RtkI2SIrqDeInit: Invalid I2S Index(&d)\r\n", pI2SAdapter->DevNum); + return HAL_ERR_PARA; + } + + InterruptDis(&pI2SAdapter->IrqHandle); + InterruptUnRegister(&pI2SAdapter->IrqHandle); + + return HAL_OK; +} + +static HAL_Status +RtkI2SPinMuxInit( + IN PHAL_I2S_ADAPTER pI2SAdapter +) +{ + u32 I2Stemp; + + if (pI2SAdapter->DevNum > I2S_MAX_ID) { + DBG_I2S_ERR("RtkI2SPinMuxInit: Invalid I2S Index(&d)\r\n", pI2SAdapter->DevNum); + return HAL_ERR_PARA; + } + + // enable system pll + I2Stemp = HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_SYSPLL_CTRL1) | (1<<9) | (1<<10); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_SYSPLL_CTRL1, I2Stemp); + + switch (pI2SAdapter->DevNum){ + case I2S0_SEL: + ACTCK_I2S_CCTRL(ON); + LXBUS_FCTRL(ON); // enable lx bus for i2s + + /*I2S0 Pin Mux Setting*/ + PinCtrl(I2S0, pI2SAdapter->PinMux, ON); + if (pI2SAdapter->PinMux == I2S_S0) { + DBG_I2S_WARN(ANSI_COLOR_MAGENTA"I2S0 Pin may conflict with JTAG\r\n"ANSI_COLOR_RESET); + } + I2S0_MCK_CTRL(ON); + I2S0_PIN_CTRL(ON); + I2S0_FCTRL(ON); + + break; + case I2S1_SEL: + ACTCK_I2S_CCTRL(ON); + LXBUS_FCTRL(ON); // enable lx bus for i2s + + /*I2S1 Pin Mux Setting*/ + PinCtrl(I2S1, pI2SAdapter->PinMux, ON); + if (pI2SAdapter->PinMux == I2S_S2) { + DBG_I2S_WARN(ANSI_COLOR_MAGENTA"I2S1 Pin may conflict with JTAG\r\n"ANSI_COLOR_RESET); + } + I2S1_MCK_CTRL(ON); + I2S1_PIN_CTRL(ON); + I2S0_FCTRL(ON); //i2s 1 is control by bit 24 BIT_PERI_I2S0_EN + I2S1_FCTRL(ON); + break; + default: + return HAL_ERR_PARA; + } + + return HAL_OK; +} + + +static HAL_Status +RtkI2SPinMuxDeInit( + IN PHAL_I2S_ADAPTER pI2SAdapter +) +{ + if (pI2SAdapter->DevNum > I2S_MAX_ID) { + DBG_I2S_ERR("RtkI2SPinMuxDeInit: Invalid I2S Index(&d)\r\n", pI2SAdapter->DevNum); + return HAL_ERR_PARA; + } + + switch (pI2SAdapter->DevNum){ + case I2S0_SEL: + /*I2S0 Pin Mux Setting*/ + //ACTCK_I2C0_CCTRL(OFF); + PinCtrl(I2S0, pI2SAdapter->PinMux, OFF); + I2S0_MCK_CTRL(OFF); + I2S0_PIN_CTRL(OFF); + //I2S0_FCTRL(OFF); + + break; + case I2S1_SEL: + /*I2S1 Pin Mux Setting*/ + //ACTCK_I2C1_CCTRL(OFF); + PinCtrl(I2S1, pI2SAdapter->PinMux, OFF); + I2S1_MCK_CTRL(OFF); + I2S1_PIN_CTRL(OFF); + //I2S1_FCTRL(OFF); + break; + default: + return HAL_ERR_PARA; + } + + return HAL_OK; +} + + +HAL_Status +RtkI2SInit( + IN VOID *Data +) +{ + PHAL_I2S_ADAPTER pI2SAdapter = (PHAL_I2S_ADAPTER) Data; + PHAL_I2S_OP pHalI2SOP = &HalI2SOpSAL; + PHAL_I2S_INIT_DAT pI2SCfg; + + if (pI2SAdapter == 0) { + DBG_I2S_ERR("RtkI2SInit: Null Pointer\r\n"); + return HAL_ERR_PARA; + } + + if (pI2SAdapter->DevNum > I2S_MAX_ID) { + DBG_I2S_ERR("RtkI2SInit: Invalid I2S Index(&d)\r\n", pI2SAdapter->DevNum); + return HAL_ERR_PARA; + } + + pI2SCfg = pI2SAdapter->pInitDat; + + /*I2S Initialize HAL Operations*/ + HalI2SOpInit(pHalI2SOP); + + /*I2S Interrupt Initialization*/ + RtkI2SIrqInit(pI2SAdapter); + + /*I2S Pin Mux Initialization*/ + RtkI2SPinMuxInit(pI2SAdapter); + + /*I2S Load User Setting*/ + pI2SCfg->I2SIdx = pI2SAdapter->DevNum; + + /*I2S HAL Initialization*/ + pHalI2SOP->HalI2SInit(pI2SCfg); + + /*I2S Device Status Update*/ + pI2SAdapter->DevSts = I2S_STS_INITIALIZED; + + /*I2S Enable Module*/ + pI2SCfg->I2SEn = I2S_ENABLE; + pHalI2SOP->HalI2SEnable(pI2SCfg); + + /*I2S Device Status Update*/ + pI2SAdapter->DevSts = I2S_STS_IDLE; + + return HAL_OK; +} + +HAL_Status +RtkI2SDeInit( + IN VOID *Data +) +{ + PHAL_I2S_ADAPTER pI2SAdapter = (PHAL_I2S_ADAPTER) Data; + PHAL_I2S_OP pHalI2SOP = &HalI2SOpSAL; + PHAL_I2S_INIT_DAT pI2SCfg; + + if (pI2SAdapter == 0) { + DBG_I2S_ERR("RtkI2SDeInit: Null Pointer\r\n"); + return HAL_ERR_PARA; + } + + pI2SCfg = pI2SAdapter->pInitDat; + + /*I2S Disable Module*/ + pI2SCfg->I2SEn = I2S_DISABLE; + pHalI2SOP->HalI2SEnable(pI2SCfg); + + /*I2C HAL DeInitialization*/ + //pHalI2SOP->HalI2SDeInit(pI2SCfg); + + /*I2S Interrupt DeInitialization*/ + RtkI2SIrqDeInit(pI2SAdapter); + + /*I2S Pin Mux DeInitialization*/ + RtkI2SPinMuxDeInit(pI2SAdapter); + + /*I2S HAL DeInitialization*/ + pHalI2SOP->HalI2SDeInit(pI2SCfg); + + /*I2S Device Status Update*/ + pI2SAdapter->DevSts = I2S_STS_UNINITIAL; + + return HAL_OK; +} + +HAL_Status +RtkI2SEnable( + IN VOID *Data +) +{ + PHAL_I2S_ADAPTER pI2SAdapter = (PHAL_I2S_ADAPTER) Data; + PHAL_I2S_OP pHalI2SOP = &HalI2SOpSAL; + PHAL_I2S_INIT_DAT pI2SCfg; + + pI2SCfg = pI2SAdapter->pInitDat; + pI2SCfg->I2SEn = I2S_ENABLE; + pHalI2SOP->HalI2SEnable(pI2SCfg); + + return HAL_OK; +} + +HAL_Status +RtkI2SDisable( + IN VOID *Data +) +{ + PHAL_I2S_ADAPTER pI2SAdapter = (PHAL_I2S_ADAPTER) Data; + PHAL_I2S_OP pHalI2SOP = &HalI2SOpSAL; + PHAL_I2S_INIT_DAT pI2SCfg; + + pI2SCfg = pI2SAdapter->pInitDat; + pI2SCfg->I2SEn = I2S_DISABLE; + pHalI2SOP->HalI2SEnable(pI2SCfg); + + HalI2SClearAllOwnBit((VOID*)pI2SCfg); + + return HAL_OK; +} + +RTK_STATUS +RtkI2SIoCtrl( + IN VOID *Data +) +{ + return _EXIT_SUCCESS; +} + +RTK_STATUS +RtkI2SPowerCtrl( + IN VOID *Data +) +{ + return _EXIT_SUCCESS; +} + +HAL_Status +RtkI2SLoadDefault( + IN VOID *Adapter, + IN VOID *Setting +) +{ + PHAL_I2S_ADAPTER pI2SAdapter = (PHAL_I2S_ADAPTER) Adapter; + PHAL_I2S_INIT_DAT pI2SCfg = pI2SAdapter->pInitDat; + PHAL_I2S_DEF_SETTING pLoadSetting = (PHAL_I2S_DEF_SETTING)Setting; + + if (pI2SAdapter == 0) { + DBG_I2S_ERR("RtkI2SLoadDefault: Null Pointer\r\n"); + return HAL_ERR_PARA; + } + + if (pI2SAdapter->pInitDat == NULL) { + DBG_I2S_ERR("RtkI2SLoadDefault: pInitDat is NULL!\r\n", pI2SAdapter->DevNum); + return HAL_ERR_PARA; + } + + pI2SAdapter->DevSts = pLoadSetting->DevSts; + pI2SAdapter->ErrType = 0; + pI2SAdapter->TimeOut = 0; + + pI2SCfg->I2SIdx = pI2SAdapter->DevNum; + pI2SCfg->I2SEn = I2S_DISABLE; + pI2SCfg->I2SMaster = pLoadSetting->I2SMaster; + pI2SCfg->I2SWordLen = pLoadSetting->I2SWordLen; + pI2SCfg->I2SChNum = pLoadSetting->I2SChNum; + pI2SCfg->I2SPageNum = pLoadSetting->I2SPageNum; + pI2SCfg->I2SPageSize = pLoadSetting->I2SPageSize; + pI2SCfg->I2SRate = pLoadSetting->I2SRate; + pI2SCfg->I2STRxAct = pLoadSetting->I2STRxAct; + pI2SCfg->I2STxIntrMSK = pLoadSetting->I2STxIntrMSK; + pI2SCfg->I2SRxIntrMSK = pLoadSetting->I2SRxIntrMSK; + + return HAL_OK; +} + +VOID HalI2SOpInit( + IN VOID *Data +) +{ + PHAL_I2S_OP pHalI2SOp = (PHAL_I2S_OP) Data; + + pHalI2SOp->HalI2SInit = HalI2SInitRtl8195a_Patch; + pHalI2SOp->HalI2SDeInit = HalI2SDeInitRtl8195a; + pHalI2SOp->HalI2STx = HalI2STxRtl8195a; + pHalI2SOp->HalI2SRx = HalI2SRxRtl8195a; + pHalI2SOp->HalI2SEnable = HalI2SEnableRtl8195a; + pHalI2SOp->HalI2SIntrCtrl = HalI2SIntrCtrlRtl8195a; + pHalI2SOp->HalI2SReadReg = HalI2SReadRegRtl8195a; + pHalI2SOp->HalI2SSetRate = HalI2SSetRateRtl8195a; + pHalI2SOp->HalI2SSetWordLen = HalI2SSetWordLenRtl8195a; + pHalI2SOp->HalI2SSetChNum = HalI2SSetChNumRtl8195a; + pHalI2SOp->HalI2SSetPageNum = HalI2SSetPageNumRtl8195a; + pHalI2SOp->HalI2SSetPageSize = HalI2SSetPageSizeRtl8195a; + pHalI2SOp->HalI2SClrIntr = HalI2SClrIntrRtl8195a; + pHalI2SOp->HalI2SClrAllIntr = HalI2SClrAllIntrRtl8195a; + pHalI2SOp->HalI2SDMACtrl = HalI2SDMACtrlRtl8195a; +} + + diff --git a/component/soc/realtek/8195a/fwlib/src/hal_mii.c b/component/soc/realtek/8195a/fwlib/src/hal_mii.c new file mode 100644 index 0000000..7af663e --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/src/hal_mii.c @@ -0,0 +1,43 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + + +#include "hal_mii.h" + +VOID +HalMiiOpInit( + IN VOID *Data + ) +{ + DBG_ENTRANCE; + PHAL_MII_OP pHalMiiOp = (PHAL_MII_OP) Data; + + pHalMiiOp->HalMiiGmacInit = HalMiiGmacInitRtl8195a; + pHalMiiOp->HalMiiInit = HalMiiInitRtl8195a; + pHalMiiOp->HalMiiGmacReset = HalMiiGmacResetRtl8195a; + pHalMiiOp->HalMiiGmacEnablePhyMode = HalMiiGmacEnablePhyModeRtl8195a; + pHalMiiOp->HalMiiGmacXmit = HalMiiGmacXmitRtl8195a; + pHalMiiOp->HalMiiGmacCleanTxRing = HalMiiGmacCleanTxRingRtl8195a; + pHalMiiOp->HalMiiGmacFillTxInfo = HalMiiGmacFillTxInfoRtl8195a; + pHalMiiOp->HalMiiGmacFillRxInfo = HalMiiGmacFillRxInfoRtl8195a; + pHalMiiOp->HalMiiGmacTx = HalMiiGmacTxRtl8195a; + pHalMiiOp->HalMiiGmacRx = HalMiiGmacRxRtl8195a; + pHalMiiOp->HalMiiGmacSetDefaultEthIoCmd = HalMiiGmacSetDefaultEthIoCmdRtl8195a; + pHalMiiOp->HalMiiGmacInitIrq = HalMiiGmacInitIrqRtl8195a; + pHalMiiOp->HalMiiGmacGetInterruptStatus = HalMiiGmacGetInterruptStatusRtl8195a; + pHalMiiOp->HalMiiGmacClearInterruptStatus = HalMiiGmacClearInterruptStatusRtl8195a; +#if 0 + pHalMiiOp-> = Rtl8195a; + pHalMiiOp-> = Rtl8195a; + pHalMiiOp-> = Rtl8195a; + pHalMiiOp-> = Rtl8195a; + pHalMiiOp-> = Rtl8195a; +#endif +} + diff --git a/component/soc/realtek/8195a/fwlib/src/hal_nfc.c b/component/soc/realtek/8195a/fwlib/src/hal_nfc.c new file mode 100644 index 0000000..bafa43e --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/src/hal_nfc.c @@ -0,0 +1,20 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + + +#include "rtl8195a.h" +#include "hal_nfc.h" + +VOID HalNFCOpInit( + IN VOID *Data +) +{ + +} + diff --git a/component/soc/realtek/8195a/fwlib/src/hal_pcm.c b/component/soc/realtek/8195a/fwlib/src/hal_pcm.c new file mode 100644 index 0000000..5ccf96a --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/src/hal_pcm.c @@ -0,0 +1,28 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + + +#include "hal_pcm.h" + +VOID HalPcmOpInit( + IN VOID *Data +) +{ + PHAL_PCM_OP pHalPcmOp = (PHAL_PCM_OP) Data; + + pHalPcmOp->HalPcmOnOff = HalPcmOnOffRtl8195a; + pHalPcmOp->HalPcmInit = HalPcmInitRtl8195a; + pHalPcmOp->HalPcmSetting = HalPcmSettingRtl8195a; + pHalPcmOp->HalPcmEn = HalPcmEnRtl8195a; + pHalPcmOp->HalPcmIsrEnAndDis= HalPcmIsrEnAndDisRtl8195a; + pHalPcmOp->HalPcmDumpReg= HalPcmDumpRegRtl8195a; + pHalPcmOp->HalPcm= HalPcmRtl8195a; +} + + diff --git a/component/soc/realtek/8195a/fwlib/src/hal_pwm.c b/component/soc/realtek/8195a/fwlib/src/hal_pwm.c new file mode 100644 index 0000000..0e8432d --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/src/hal_pwm.c @@ -0,0 +1,131 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + + +#include "rtl8195a.h" + +#ifdef CONFIG_PWM_EN +#include "hal_pwm.h" +#include "hal_timer.h" + +HAL_PWM_ADAPTER PWMPin[MAX_PWM_CTRL_PIN]; +const u8 PWMTimerIdx[MAX_PWM_CTRL_PIN]= {3,4,5,6}; // the G-timer ID used for PWM pin 0~3 + +/** + * @brief Initializes and enable a PWM control pin. + * + * @param pwm_id: the PWM pin index + * @param sel: pin mux selection + * + * @retval HAL_Status + */ +HAL_Status +HAL_Pwm_Init( + u32 pwm_id, + u32 sel +) +{ + HAL_PWM_ADAPTER *pPwmAdapt; + u32 timer_id; + + DBG_PWM_INFO("%s: Init PWM for PWM %d, Sel %d\n", __FUNCTION__, pwm_id, sel); + + if ((pwm_id >= MAX_PWM_CTRL_PIN) || (sel > 3)) { + DBG_PWM_ERR ("HAL_Pwm_Init: Invalid PWM index(%d), sel(%d)\n", pwm_id, sel); + return HAL_ERR_PARA; + } + + pPwmAdapt = &PWMPin[pwm_id]; + pPwmAdapt->pwm_id = pwm_id; + pPwmAdapt->sel = sel; + timer_id = PWMTimerIdx[pwm_id]; + pPwmAdapt->gtimer_id = timer_id; + + return HAL_Pwm_Init_8195a (pPwmAdapt); +} + + +/** + * @brief Disable a PWM control pin. + * + * @param pwm_id: the PWM pin index + * + * @retval None + */ +void +HAL_Pwm_Enable( + u32 pwm_id +) +{ + HAL_PWM_ADAPTER *pPwmAdapt; + + if (pwm_id >= MAX_PWM_CTRL_PIN) { + DBG_PWM_ERR ("HAL_Pwm_Enable: Invalid PWM index(%d)\n", pwm_id); + return; + } + pPwmAdapt = &PWMPin[pwm_id]; + + HAL_Pwm_Enable_8195a(pPwmAdapt); +} + + +/** + * @brief Disable a PWM control pin. + * + * @param pwm_id: the PWM pin index + * + * @retval None + */ +void +HAL_Pwm_Disable( + u32 pwm_id +) +{ + HAL_PWM_ADAPTER *pPwmAdapt; + + if (pwm_id >= MAX_PWM_CTRL_PIN) { + DBG_PWM_ERR ("HAL_Pwm_Disable: Invalid PWM index(%d)\n", pwm_id); + return; + } + pPwmAdapt = &PWMPin[pwm_id]; + + HAL_Pwm_Disable_8195a(pPwmAdapt); +} + +/** + * @brief Set the duty ratio of the PWM pin. + * + * @param pwm_id: the PWM pin index + * @param period: the period time, in micro-second. + * @param pulse_width: the pulse width time, in micro-second. + * + * @retval None + */ +void +HAL_Pwm_SetDuty( + u32 pwm_id, + u32 period, + u32 pulse_width +) +{ + HAL_PWM_ADAPTER *pPwmAdapt; + + if (pwm_id >= MAX_PWM_CTRL_PIN) { + DBG_PWM_ERR ("HAL_Pwm_SetDuty: Invalid PWM index(%d)\n", pwm_id); + return; + } + +// DBG_PWM_INFO("%s: Period%d Pulse%d\n", __FUNCTION__, period, pulse_width); + pPwmAdapt = &PWMPin[pwm_id]; + + HAL_Pwm_SetDuty_8195a(pPwmAdapt, period, pulse_width); +} + + +#endif // end of "#ifdef CONFIG_PWM_EN" diff --git a/component/soc/realtek/8195a/fwlib/src/hal_sdr_controller.c b/component/soc/realtek/8195a/fwlib/src/hal_sdr_controller.c new file mode 100644 index 0000000..ba52e49 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/src/hal_sdr_controller.c @@ -0,0 +1,962 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ +#include "rtl8195a.h" +#include "hal_sdr_controller.h" +#include "rtl8195a_sdr.h" +#if 0 +#define HAL_SDR_WRITE32(addr, value32) HAL_WRITE32(SDR_CTRL_BASE, addr, value32) +#define HAL_SDR_WRITE16(addr, value16) HAL_WRITE16(SDR_CTRL_BASE, addr, value16) +#define HAL_SDR_WRITE8(addr, value8) HAL_WRITE8(SDR_CTRL_BASE, addr, value8) +#define HAL_SDR_READ32(addr) HAL_READ32(SDR_CTRL_BASE, addr) +#define HAL_SDR_READ16(addr) HAL_READ16(SDR_CTRL_BASE, addr) +#define HAL_SDR_READ8(addr) HAL_READ8(SDR_CTRL_BASE, addr) + +#define HAL_SDRAM_WRITE32(addr, value32) HAL_WRITE32(SDR_SDRAM_BASE, addr, value32) +#define HAL_SDRAM_WRITE16(addr, value16) HAL_WRITE16(SDR_SDRAM_BASE, addr, value16) +#define HAL_SDRAM_WRITE8(addr, value8) HAL_WRITE8(SDR_SDRAM_BASE, addr, value8) +#define HAL_SDRAM_READ32(addr) HAL_READ32(SDR_SDRAM_BASE, addr) +#define HAL_SDRAM_READ16(addr) HAL_READ16(SDR_SDRAM_BASE, addr) +#define HAL_SDRAM_READ8(addr) HAL_READ8(SDR_SDRAM_BASE, addr) +#endif + + + +HAL_CUT_B_RAM_DATA_SECTION +DRAM_INFO SdrDramDev = { + DRAM_INFO_TYPE, + DRAM_INFO_COL_ADDR_WTH, + DRAM_INFO_BANK_SZ, + DRAM_INFO_DQ_WTH +}; + + +HAL_CUT_B_RAM_DATA_SECTION +DRAM_MODE_REG_INFO SdrDramModeReg = { + BST_LEN_4, + SENQUENTIAL, + 0x3, // Mode0Cas: 3 + 0x0, // Mode0Wr + 0, // Mode1DllEnN + 0, // Mode1AllLat + 0 // Mode2Cwl +}; + +HAL_CUT_B_RAM_DATA_SECTION +DRAM_TIMING_INFO SdrDramTiming = { + DRAM_TIMING_TRFC, // TrfcPs; + DRAM_TIMING_TREFI, // TrefiPs; + DRAM_TIMING_TWRMAXTCK, // WrMaxTck; + DRAM_TIMING_TRCD, // TrcdPs; + DRAM_TIMING_TRP, // TrpPs; + DRAM_TIMING_TRAS, // TrasPs; + DRAM_TIMING_TRRD, // TrrdTck; + DRAM_TIMING_TWR, // TwrPs; + DRAM_TIMING_TWTR, // TwtrTck; + //13090, // TrtpPs; + DRAM_TIMING_TMRD, // TmrdTck; + DRAM_TIMING_TRTP, // TrtpTck; + DRAM_TIMING_TCCD, // TccdTck; + DRAM_TIMING_TRC // TrcPs; +}; + +HAL_CUT_B_RAM_DATA_SECTION +DRAM_DEVICE_INFO SdrDramInfo = { + &SdrDramDev, + &SdrDramModeReg, + &SdrDramTiming, + DRAM_TIMING_TCK, + DFI_RATIO_1 +}; + + +#define FPGA +#define FPGA_TEMP +#define SDR_CLK_DLY_CTRL 0x40000300 +#define MIN_RD_PIPE 0x0 +#define MAX_RD_PIPE 0x7 + +#define SUPPORT_DRAM_KED + + +#ifdef FPGA +#ifdef FPGA_TEMP +#define MAX_TAP_DLY 0xC +#else +#define MAX_TAP_DLY 0x7F +#define SPEC_MAX_TAP 0xFF +#endif +#else +#define MAX_TAP_DLY 99 // 0~99 +#define SPEC_MAX_TAP 99 +#define WINDOW_COMBIN // combine window [0~a] and [b~99] (for asic mode) +#endif + +#define TAP_DLY 0x1 +#define REC_NUM 512 + + +u32 SdrControllerInit(VOID); +VOID DramInit(DRAM_DEVICE_INFO *); +s32 MemTest(u32 loop_cnt); +u32 SdrCalibration(VOID); +u32 Sdr_Rand2(VOID); + +//3 Note: stack overfloat if the arrary is declared in the task +HAL_CUT_B_RAM_DATA_SECTION +u32 AvaWds[2][REC_NUM]; + +HAL_CUT_B_RAM_DATA_SECTION +unsigned int rand_x = 123456789; + +#ifdef CONFIG_SDR_EN + +#ifdef CONFIG_SDR_VERIFY +enum{ + LLT, + TXRPT, + RXBUFF, + TXBUFF, +}; +#define REPORT_OFFSET 0x8000 +#define RAMASK_OFFSET 0x8800 +#define LLT_H_ADDR 0x650 +#define TXREPORT_H_ADDR 0x660 +#define RXBUFF_H_ADDR 0x670 +#define TXBUFF_H_ADDR 0x680 + +#define REG_PKTBUF_DBG_CTRL_8723B 0x0140 + +int +rt_rpt_h_addr(u8 rpt) +{ + u32 r_val, offset; + + if (rpt == LLT){ + offset = LLT_H_ADDR; + } + else if (rpt == TXRPT){ + offset = TXREPORT_H_ADDR; + } + else if (rpt == RXBUFF){ + offset = RXBUFF_H_ADDR; + } + else if (rpt == TXBUFF){ + offset = TXBUFF_H_ADDR; + } + else { + } + + r_val = ((HAL_READ32(WIFI_REG_BASE, REG_PKTBUF_DBG_CTRL_8723B)&0xFFFFF000)|offset); + HAL_WRITE32(WIFI_REG_BASE, REG_PKTBUF_DBG_CTRL_8723B, r_val); +} + + + +int +rt_txrpt_read32(u8 macid, u8 offset) +{ + u32 r_val; + + rt_rpt_h_addr(TXRPT); + r_val = HAL_READ32(WIFI_REG_BASE, (REPORT_OFFSET + macid*4 + offset)); + + return r_val; +} + +int +rt_txrpt_read16(u8 macid, u8 offset) +{ + u16 r_val; + + rt_rpt_h_addr(TXRPT); + r_val = HAL_READ16(WIFI_REG_BASE, (REPORT_OFFSET + macid*8 + offset)); + + return r_val; +} + +int +rt_txrpt_read8(u8 macid, u8 offset) +{ + u8 r_val; + + rt_rpt_h_addr(TXRPT); + r_val = HAL_READ8(WIFI_REG_BASE, (REPORT_OFFSET + macid*16 + offset)); + + return r_val; +} + +int +rt_txrpt_read_1b(u8 macid, u8 offset, u8 bit_offset) +{ + u8 r_val = ((rt_txrpt_read8(macid, offset) & BIT(bit_offset))?1:0); + + return r_val; +} + + +int +rt_txrpt_write32(u8 macid, u8 offset, u32 val) +{ + rt_rpt_h_addr(TXRPT); + HAL_WRITE32(WIFI_REG_BASE, (REPORT_OFFSET + macid*4 + offset), val); +} + +int +rt_txrpt_write16(u8 macid, u8 offset, u16 val) +{ + rt_rpt_h_addr(TXRPT); + HAL_WRITE16(WIFI_REG_BASE, (REPORT_OFFSET + macid*8 + offset), val); +} + +int +rt_txrpt_write8(u8 macid, u8 offset, u8 val) +{ + rt_rpt_h_addr(TXRPT); + DBG_8195A("Write addr %x %x\n", (REPORT_OFFSET + macid*16 + offset), val); + HAL_WRITE8(WIFI_REG_BASE, (REPORT_OFFSET + macid*16 + offset), val); +} + +int +rt_txrpt_write_1b(u8 macid, u8 offset, u8 bit_offset, u8 val) +{ + u8 r_val = rt_txrpt_read8(macid, offset); + + if (val){ + r_val |= BIT(bit_offset); + } + else { + r_val &= (~BIT(bit_offset)); + } + + HAL_WRITE8(WIFI_REG_BASE, (REPORT_OFFSET + macid*16 + offset), r_val); +} + + +u8 +ReadTxrptsdr8( + IN u8 Macid, + IN u8 Offset) +{ + u8 r_val; + + r_val = rt_txrpt_read8(Macid, Offset); + return r_val; +} + +VOID +WriteTxrptsdr8( + IN u8 Macid, + IN u8 Offset, + IN u8 Val) +{ + rt_txrpt_write8(Macid, Offset, Val); +} + +VOID +SdrTestApp( + IN VOID *Data +) +{ + u32 *Cmd =(u32*)Data; + u32 Loop, LoopIndex, Value32, Addr, Loop1, LoopIndex1; + + switch (Cmd[0]) { + case 1: + DBG_8195A("Initial SDR\n"); + + //1 "SdrControllerInit" is located in Image1, so we shouldn't call it in Image2 + if (!SdrControllerInit()) { + DBG_8195A("SDR Calibartion Fail!!!!\n"); + } + break; + case 2: + Loop = Cmd[1]; + Loop1 = Cmd[2]; + DBG_8195A("Verify SDR: Loop = 0x%08x Loop1 = 0x%08x\n",Loop, Loop1); + + for (LoopIndex1=0; LoopIndex1 < Loop1; LoopIndex1++) { + + for (LoopIndex=0; LoopIndex < Loop; LoopIndex++) { + Value32 = Rand2(); + Addr = Rand2(); + Addr &= 0x1FFFFF; + Addr &= (~0x3); + + if (!(LoopIndex & 0xFFFFF)) { + DBG_8195A("Alive: LOOP = 0x%08x, LOOP = 0x%08x\n",LoopIndex1, LoopIndex); + } + + // DBG_8195A("Value: 0x%x; Addr: 0x%x\n", Value32, Addr+SDR_SDRAM_BASE); + HAL_SDRAM_WRITE32(Addr, Value32); + + if (Value32 != HAL_SDRAM_READ32(Addr)) { + DBG_8195A("Loop:%d; Addr: 0x%08x => CheckData error: W: 0x%08x /R:0x%x\n" + ,LoopIndex + ,Addr + ,Value32 + ,HAL_SDRAM_READ32(Addr)); + + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSTBY_INFO2, HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSTBY_INFO2)+1); + break; + } + } + } + DBG_8195A("Verify SDR Success\n"); + break; + + case 3: + DBG_8195A("WL read RPT MACID %x\n", Cmd[1]); + { + u8 i =0; + for(i=0;i<16;i++) { + DBG_8195A("WL RPT offset %d = %x\n", i, ReadTxrptsdr8(Cmd[1],i)); + } + } + break; + case 4: + DBG_8195A("WL write RPT MACID %x\n", Cmd[1]); + { + u8 i =0; + for(i=0;i<16;i++) { + WriteTxrptsdr8(Cmd[1],i,Cmd[2]); + //DBG_8195A("WL RPT offset %d = %x\n", i, ReadTxrptsdr8(Cmd[1],i)); + } + } + break; + default: + break; + } + +} + +#endif + +HAL_SDRC_TEXT_SECTION +u32 +SdrControllerInit( +VOID +) +{ + DBG_8195A("SDR Controller Init\n"); + + SRAM_MUX_CFG(0x2); + + SDR_CLK_SEL(SDR_CLOCK_SEL_VALUE); + + HAL_PERI_ON_WRITE32(REG_GPIO_PULL_CTRL4,0); + + ACTCK_SDR_CCTRL(ON); + + SLPCK_SDR_CCTRL(ON); + + PinCtrl(SDR, 0, ON); + + HAL_PERI_ON_WRITE32(REG_GPIO_PULL_CTRL4,0); + + //MEM_CTRL_FCTRL(OFF); + + MEM_CTRL_FCTRL(ON); + + LDO25M_CTRL(ON); + + HalDelayUs(3000); + + // sdr initialization + DramInit(&SdrDramInfo); + + // sdr calibration + if(!SdrCalibration()) { + return 0; + } + else { + return 1; + } +} + + +HAL_SDRC_TEXT_SECTION +VOID +DramInit ( + IN DRAM_DEVICE_INFO *DramInfo +) +{ + u32 CsBstLen = 0; // 0:bst_4, 1:bst_8 + u32 CasWr = 0;//, CasWrT; // cas write latency + u32 CasRd = 0, CasRdT = 0, CrlSrt = 0; // cas read latency + u32 AddLat; + u32 DramEmr2 = 0, DramMr0 = 0; + u32 CrTwr, DramMaxWr, DramWr; + u32 CrTrtw = 0, CrTrtwT = 0; + u32 DrmaPeriod; + DRAM_TYPE DdrType; + DRAM_DQ_WIDTH DqWidth; + DRAM_COLADDR_WTH Page; + u32 DfiRate; + volatile struct ms_rxi310_portmap *ms_ctrl_0_map; + ms_ctrl_0_map = (struct ms_rxi310_portmap*) SDR_CTRL_BASE; + ms_ctrl_0_map = ms_ctrl_0_map; + + DfiRate = 1 << (u32) (DramInfo->DfiRate); + DrmaPeriod = (DramInfo->DdrPeriodPs)*(DfiRate); // according DFI_RATE to setting + + // In PHY, write latency == 3 + DramMaxWr= (DramInfo->Timing->WrMaxTck)/(DfiRate) +1; + DramWr = ((DramInfo->Timing->TwrPs) / DrmaPeriod)+1; + CrTwr = ((DramInfo->Timing->TwrPs) / DrmaPeriod) + 3; + + if (CrTwr < DramMaxWr) { + CrTwr = CrTwr; + } + else { + CrTwr = DramMaxWr; + } + + if ((DramInfo->Dev->DeviceType) == DRAM_DDR_2) { + DdrType = DRAM_DDR_2; + if (DramInfo->ModeReg->BstLen == BST_LEN_4) { + CsBstLen = 0; //bst_4 + CrTrtwT = 2+2; //4/2+2 + DramMr0 = 0x2; + } + else { // BST_LEN_8 + CsBstLen = 1; // bst_8 + CrTrtwT = 4+2; // 8/2+2 + DramMr0 = 0x3; + } + CasRd = DramInfo->ModeReg->Mode0Cas; + AddLat = DramInfo->ModeReg ->Mode1AllLat; + CasWr = CasRd + AddLat -1; + DramEmr2 = 0; + + DramMr0 =(((DramWr%6)-1) << (PCTL_MR_OP_BFO+1)) | // write_recovery + (0 << PCTL_MR_OP_BFO ) | // dll + (DramInfo->ModeReg->Mode0Cas << PCTL_MR_CAS_BFO ) | + (DramInfo->ModeReg->BstType << PCTL_MR_BT_BFO ) | + DramMr0; + } + else if ((DramInfo->Dev->DeviceType) == DRAM_DDR_3) { + DdrType = DRAM_DDR_3; + if (DramInfo->ModeReg->BstLen == BST_LEN_4) { + CsBstLen = 0; //bst_4 + DramMr0 = 0x2; + } + else { // BST_LEN_8 + CsBstLen = 1; // bst_8 + DramMr0 = 0x0; + } + + CrlSrt = (DramInfo->ModeReg->Mode0Cas >> 1); + if (((DramInfo->ModeReg->Mode0Cas) & 0x1) ) { + CasRdT = CrlSrt+ 12; + } + else { + CasRdT = CrlSrt+ 4; + } + + if (DramInfo->ModeReg->Mode1AllLat == 1) { // CL-1 + AddLat = CasRd -1; + } + else if (DramInfo->ModeReg->Mode1AllLat == 2){ // CL-2 + AddLat = CasRd -2; + } + else { + AddLat = 0; + } + + CasRd = CasRdT + AddLat; + + CasWr = DramInfo->ModeReg->Mode2Cwl + 5 + AddLat; + + DramEmr2 = DramInfo->ModeReg->Mode2Cwl << 3; + + if (DramWr == 16) { + DramWr = 0; + } + else if (DramWr <= 9) { // 5< wr <= 9 + DramWr = DramWr - 4; + } + else { + DramWr = (DramWr + 1) / 2; + } + + DramMr0 =(DramWr << (PCTL_MR_OP_BFO+1) ) | // write_recovery + (0 << PCTL_MR_OP_BFO ) | // dll + ((DramInfo->ModeReg->Mode0Cas >>1 ) << PCTL_MR_CAS_BFO ) | + (DramInfo->ModeReg->BstType << PCTL_MR_BT_BFO ) | + ((DramInfo->ModeReg->Mode0Cas & 0x1) << 2 ) | + DramMr0; + + CrTrtwT = (CasRdT + 6) - CasWr; + + } // ddr2/ddr3 + else if ((DramInfo->Dev->DeviceType) == DRAM_SDR) { + DdrType = DRAM_SDR; + if (DramInfo->ModeReg->BstLen == BST_LEN_4) { + DramMr0 = 2; // bst_4 + CsBstLen = 0; //bst_4 + CasRd = 0x2; + } + else { // BST_LEN_8 + DramMr0 = 3; // bst_8 + CsBstLen = 1; // bst_8 + CasRd = 0x3; + } + + CasWr = 0; + + DramMr0 =(CasRd << PCTL_MR_CAS_BFO) | + (DramInfo->ModeReg->BstType << PCTL_MR_BT_BFO ) | + DramMr0; + + CrTrtwT = 0; // tic: CasRd + rd_rtw + rd_pipe + } // SDR + + + // countting tRTW + if ((CrTrtwT & 0x1)) { + CrTrtw = (CrTrtwT+1) /(DfiRate); + } + else { + CrTrtw = CrTrtwT /(DfiRate); + } + + DqWidth = (DramInfo->Dev->DqWidth); + Page = DramInfo->Dev->ColAddrWth +1; // DQ16 -> memory:byte_unit *2 + if (DqWidth == DRAM_DQ_32) { // paralle dq_16 => Page + 1 + Page = Page +1; + } +#if 1 + + // WRAP_MISC setting + HAL_SDR_WRITE32(REG_SDR_MISC,( + (Page << WRAP_MISC_PAGE_SIZE_BFO) | + (DramInfo->Dev->Bank << WRAP_MISC_BANK_SIZE_BFO) | + (CsBstLen << WRAP_MISC_BST_SIZE_BFO ) | + (DqWidth << WRAP_MISC_DDR_PARAL_BFO) + )); + // PCTL setting + HAL_SDR_WRITE32(REG_SDR_DCR,( + (0x2 << PCTL_DCR_DFI_RATE_BFO) | + (DqWidth << PCTL_DCR_DQ32_BFO ) | + (DdrType << PCTL_DCR_DDR3_BFO ) + )); + + HAL_SDR_WRITE32(REG_SDR_IOCR,( + ((CasRd -4)/(DfiRate) << PCTL_IOCR_TPHY_RD_EN_BFO ) | + (0 << PCTL_IOCR_TPHY_WL_BFO ) | + (((CasWr -3)/(DfiRate)) << PCTL_IOCR_TPHY_WD_BFO ) | + (0 << PCTL_IOCR_RD_PIPE_BFO ) + )); + + if ((DramInfo->Dev->DeviceType) != SDR) { // DDR2/3 + HAL_SDR_WRITE32(REG_SDR_EMR2,DramEmr2); + HAL_SDR_WRITE32(REG_SDR_EMR1,( + (1 << 2 ) | //RTT + (1 << 1 ) | //D.I.C + (DramInfo->ModeReg->Mode1DllEnN ) + )); + } // DDR2/3 + + HAL_SDR_WRITE32(REG_SDR_MR,DramMr0); + + HAL_SDR_WRITE32(REG_SDR_DRR, ( + (0 << PCTL_DRR_REF_DIS_BFO) | + (9 << PCTL_DRR_REF_NUM_BFO) | + ((((DramInfo->Timing->TrefiPs)/DrmaPeriod)+1) << PCTL_DRR_TREF_BFO ) | + ((((DramInfo->Timing->TrfcPs)/DrmaPeriod)+1) << PCTL_DRR_TRFC_BFO ) + )); + + HAL_SDR_WRITE32(REG_SDR_TPR0,( + ((((DramInfo->Timing->TrtpTck)/DfiRate)+1) << PCTL_TPR0_TRTP_BFO) | + (CrTwr << PCTL_TPR0_TWR_BFO ) | + ((((DramInfo->Timing->TrasPs)/DrmaPeriod)+1) << PCTL_TPR0_TRAS_BFO) | + ((((DramInfo->Timing->TrpPs)/DrmaPeriod)+1) << PCTL_TPR0_TRP_BFO ) + )); + + HAL_SDR_WRITE32(REG_SDR_TPR1, ( + (CrTrtw << PCTL_TPR1_TRTW_BFO) | + ((((DramInfo->Timing->TwtrTck)/DfiRate)+3) << PCTL_TPR1_TWTR_BFO) | + ((((DramInfo->Timing->TccdTck)/DfiRate)+1) << PCTL_TPR1_TCCD_BFO) | + ((((DramInfo->Timing->TrcdPs)/DrmaPeriod)+1) << PCTL_TPR1_TRCD_BFO) | + ((((DramInfo->Timing->TrcPs)/DrmaPeriod)+1) << PCTL_TPR1_TRC_BFO ) | + (((DramInfo->Timing->TrrdTck/DfiRate)+1) << PCTL_TPR1_TRRD_BFO) + )); + + HAL_SDR_WRITE32(REG_SDR_TPR2, ( + (DramInfo->Timing->TmrdTck << PCTL_TPR2_TMRD_BFO ) | + (0 << PCTL_TPR2_INIT_NS_EN_BFO ) | + (2 << PCTL_TPR2_INIT_REF_NUM_BFO) + )); + + // set all_mode _idle + HAL_SDR_WRITE32(REG_SDR_CSR,0x700); + + // start to init + HAL_SDR_WRITE32(REG_SDR_CCR,0x01); + while ((HAL_SDR_READ32(REG_SDR_CCR)& 0x1) == 0x0); + + // enter mem_mode + HAL_SDR_WRITE32(REG_SDR_CSR,0x600); +#else + // WRAP_MISC setting + ms_ctrl_0_map->misc = //0x12; + ( + (Page << WRAP_MISC_PAGE_SIZE_BFO) | + (DramInfo->Dev->Bank << WRAP_MISC_BANK_SIZE_BFO) | + (CsBstLen << WRAP_MISC_BST_SIZE_BFO ) | + (DqWidth << WRAP_MISC_DDR_PARAL_BFO) + ); + // PCTL setting + ms_ctrl_0_map->dcr = //0x208; + ( + (0x2 << PCTL_DCR_DFI_RATE_BFO) | + (DqWidth << PCTL_DCR_DQ32_BFO ) | + (DdrType << PCTL_DCR_DDR3_BFO ) + ); + + ms_ctrl_0_map->iocr = ( + ((CasRd -4)/(DfiRate) << PCTL_IOCR_TPHY_RD_EN_BFO ) | + (0 << PCTL_IOCR_TPHY_WL_BFO ) | + (((CasWr -3)/(DfiRate)) << PCTL_IOCR_TPHY_WD_BFO ) | + (0 << PCTL_IOCR_RD_PIPE_BFO ) + ); + + if ((DramInfo->Dev->DeviceType) != SDR) { // DDR2/3 + ms_ctrl_0_map->emr2 = DramEmr2; + + ms_ctrl_0_map->emr1 = ( + (1 << 2 ) | //RTT + (1 << 1 ) | //D.I.C + (DramInfo->ModeReg->Mode1DllEnN ) + ); + } // DDR2/3 + + ms_ctrl_0_map->mr = DramMr0; + + ms_ctrl_0_map->drr = ( + (0 << PCTL_DRR_REF_DIS_BFO) | + (9 << PCTL_DRR_REF_NUM_BFO) | + ((((DramInfo->Timing->TrefiPs)/DrmaPeriod)+1)<< PCTL_DRR_TREF_BFO ) | + ((((DramInfo->Timing->TrfcPs)/DrmaPeriod)+1) << PCTL_DRR_TRFC_BFO ) + ); + + ms_ctrl_0_map->tpr0= ( + ((((DramInfo->Timing->TrtpTck)/DfiRate)+1) << PCTL_TPR0_TRTP_BFO) | + (CrTwr << PCTL_TPR0_TWR_BFO ) | + ((((DramInfo->Timing->TrasPs)/DrmaPeriod)+1) << PCTL_TPR0_TRAS_BFO) | + ((((DramInfo->Timing->TrpPs)/DrmaPeriod)+1) << PCTL_TPR0_TRP_BFO ) + ); + + ms_ctrl_0_map->tpr1= ( + (CrTrtw << PCTL_TPR1_TRTW_BFO) | + ((((DramInfo->Timing->TwtrTck)/DfiRate)+3) << PCTL_TPR1_TWTR_BFO) | + ((((DramInfo->Timing->TccdTck)/DfiRate)+1) << PCTL_TPR1_TCCD_BFO) | + ((((DramInfo->Timing->TrcdPs)/DrmaPeriod)+1) << PCTL_TPR1_TRCD_BFO) | + ((((DramInfo->Timing->TrcPs)/DrmaPeriod)+1) << PCTL_TPR1_TRC_BFO ) | + (((DramInfo->Timing->TrrdTck/DfiRate)+1) << PCTL_TPR1_TRRD_BFO) + ); + + ms_ctrl_0_map->tpr2= ( + (DramInfo->Timing->TmrdTck << PCTL_TPR2_TMRD_BFO ) | + (0 << PCTL_TPR2_INIT_NS_EN_BFO ) | + (2 << PCTL_TPR2_INIT_REF_NUM_BFO) + ); + // set all_mode _idle + ms_ctrl_0_map->csr = 0x700; + + // start to init + ms_ctrl_0_map->ccr = 0x1; + while (((ms_ctrl_0_map->ccr)& 0x1) == 0x0); + + // enter mem_mode + ms_ctrl_0_map->csr= 0x600; +#endif +} // DramInit + + //3 +extern void * +_memset( void *s, int c, SIZE_T n ); + +HAL_SDRC_TEXT_SECTION +u32 +SdrCalibration( + VOID +) +{ +#ifdef FPGA +#ifdef FPGA_TEMP +// u32 Value32; +#endif +#else +// u32 Value32; +#endif + u32 RdPipe = 0, TapCnt = 0, Pass = 0, AvaWdsCnt = 0; + u32 RdPipeCounter, RecNum[2], RecRdPipe[2];//, AvaWds[2][REC_NUM]; + BOOL RdPipeFlag, PassFlag = 0, Result; + + Result = _FALSE; + +#ifdef SUPPORT_DRAM_KED + // read calibration data from system data 0x5d~0x6c + SPIC_INIT_PARA SpicInitPara; + u32 valid; + union { u8 b[4]; u32 l;} value; + u32 CpuType = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_CLK_CTRL1) & (0x70)) >> 4); + + valid = RdPipe = TapCnt = 0xFFFFFFFF; + value.l = HAL_READ32(SPI_FLASH_BASE, FLASH_SDRC_PARA_BASE+8*CpuType); + if((value.b[0]^value.b[1])==0xFF) + valid = value.b[0]; + //DiagPrintf("dump1 %x, %x %x %x %x \n\r", value.l, value.b[0], value.b[1], value.b[2], value.b[3]); + value.l = HAL_READ32(SPI_FLASH_BASE, FLASH_SDRC_PARA_BASE+8*CpuType+4); + if((value.b[0]^value.b[1])==0xFF) + RdPipe = value.b[0]; + if((value.b[2]^value.b[3])==0xFF) + TapCnt = value.b[2]; + //DiagPrintf("dump2 %x, %x %x %x %x \n\r", value.l, value.b[0], value.b[1], value.b[2], value.b[3]); + + if((valid==1)&&(RdPipe!=0xFFFFFFFF)&&(TapCnt!=0xFFFFFFFF)){ + // wait DRAM settle down + HalDelayUs(10); + // load previous dram Ked data + HAL_SDR_WRITE32(REG_SDR_IOCR, ((HAL_SDR_READ32(REG_SDR_IOCR) & 0xff) | (RdPipe << PCTL_IOCR_RD_PIPE_BFO))); + SDR_DDL_FCTRL(TapCnt); + if(MemTest(3)) + return _TRUE; + } +#endif + + _memset((u8*)AvaWds, 0, sizeof(u32)*REC_NUM*2); + + volatile struct ms_rxi310_portmap *ms_ctrl_0_map; + ms_ctrl_0_map = (struct ms_rxi310_portmap*) SDR_CTRL_BASE; + ms_ctrl_0_map = ms_ctrl_0_map; + PassFlag = PassFlag; + RdPipeCounter =0; + +// DBG_8195A("%d\n",__LINE__); + + for(RdPipe=MIN_RD_PIPE; RdPipe<=MAX_RD_PIPE; RdPipe++) { +// ms_ctrl_0_map->iocr = (ms_ctrl_0_map->iocr & 0xff) | (RdPipe << PCTL_IOCR_RD_PIPE_BFO); + HAL_SDR_WRITE32(REG_SDR_IOCR, ((HAL_SDR_READ32(REG_SDR_IOCR) & 0xff) | (RdPipe << PCTL_IOCR_RD_PIPE_BFO))); + + DBG_SDR_INFO("IOCR: 0x%x; Write: 0x%x\n",HAL_SDR_READ32(REG_SDR_IOCR), (RdPipe << PCTL_IOCR_RD_PIPE_BFO)); +// DBG_8195A("IOCR: 0x%x; Write: 0x%x\n",ms_ctrl_0_map->iocr, (RdPipe << PCTL_IOCR_RD_PIPE_BFO)); + + RdPipeFlag = _FALSE; + PassFlag = _FALSE; + AvaWdsCnt = 0; + + for(TapCnt=0; TapCnt < (MAX_TAP_DLY+1); TapCnt++) { + // Modify clk delay +#ifdef FPGA +#ifdef FPGA_TEMP + SDR_DDL_FCTRL(TapCnt); +// Value32 = (RD_DATA(SDR_CLK_DLY_CTRL) & 0xFF00FFFF); +// Value32 = (Value32 | (TapCnt << 16)); +// WR_DATA(SDR_CLK_DLY_CTRL, Value32); +#else + HAL_SDR_WRITE32(REG_SDR_DLY0, TapCnt); +// ms_ctrl_0_map->phy_dly0 = TapCnt; +#endif + DBG_SDR_INFO("DLY: 0x%x; Write: 0x%x\n",HAL_PERI_ON_READ32(REG_PESOC_MEM_CTRL), TapCnt); +#else + SDR_DDL_FCTRL(TapCnt); +// Value32 = (RD_DATA(SDR_CLK_DLY_CTRL) & 0xFF00FFFF); +// Value32 = (Value32 | (TapCnt << 16)); +// WR_DATA(SDR_CLK_DLY_CTRL, Value32); +#endif + + Pass = MemTest(10000); + PassFlag = _FALSE; + + if(Pass==_TRUE) { // PASS + + if (!RdPipeFlag) { + DBG_SDR_INFO("%d Time Pass\n", RdPipeCounter); + RdPipeCounter++; + RdPipeFlag = _TRUE; + RecRdPipe[RdPipeCounter - 1] = RdPipe; + } + + AvaWds[RdPipeCounter-1][AvaWdsCnt] = TapCnt; + AvaWdsCnt++; + + RecNum[RdPipeCounter-1] = AvaWdsCnt; + + if((TapCnt+TAP_DLY)>=MAX_TAP_DLY) { + break; + } + + PassFlag = _TRUE; + + DBG_SDR_INFO("Verify Pass => RdPipe:%d; TapCnt: %d\n", RdPipe, TapCnt); + + } + else { // FAIL +// if(PassFlag==_TRUE) { +// break; +// } +// else { + if (RdPipeCounter > 0) { + RdPipeCounter++; + if (RdPipeCounter < 3) { + RecNum[RdPipeCounter-1] = 0; + RecRdPipe[RdPipeCounter - 1] = RdPipe; + } + break; + } +// } + } + } + + + if (RdPipeCounter > 2) { + u8 BestRangeIndex, BestIndex; + u32 i; + + #ifdef CONFIG_SDR_VERIFY //to reduce log + DBG_SDR_INFO("Avaliable RdPipe 0\n"); + + for (i=0;i<256;i++) { + DBG_SDR_INFO("%d\n", AvaWds[0][i]); + } + DBG_SDR_INFO("Avaliable RdPipe 1\n"); + for (i=0;i<256;i++) { + DBG_SDR_INFO("%d\n", AvaWds[1][i]); + } + #endif + + DBG_SDR_INFO("Rec 0 => total counter %d; RdPipe:%d;\n", RecNum[0], RecRdPipe[0]); + DBG_SDR_INFO("Rec 1 => total counter %d; RdPipe:%d;\n", RecNum[1], RecRdPipe[1]); + + BestRangeIndex = (RecNum[0] > RecNum[1]) ? 0 : 1; + + BestIndex = RecNum[BestRangeIndex]>>1; + + DBG_SDR_INFO("The Finial RdPipe: %d; TpCnt: 0x%x\n", RecRdPipe[BestRangeIndex], AvaWds[BestRangeIndex][BestIndex]); + + // set RdPipe and tap_dly +// ms_ctrl_0_map->iocr = (ms_ctrl_0_map->iocr & 0xff) | (RecRdPipe[BestRangeIndex] << PCTL_IOCR_RD_PIPE_BFO); + HAL_SDR_WRITE32(REG_SDR_IOCR, ((HAL_SDR_READ32(REG_SDR_IOCR) & 0xff) | (RecRdPipe[BestRangeIndex] << PCTL_IOCR_RD_PIPE_BFO))); + +#ifdef FPGA +#ifdef FPGA_TEMP + SDR_DDL_FCTRL(AvaWds[BestRangeIndex][BestIndex]); + +// Value32 = (RD_DATA(SDR_CLK_DLY_CTRL) & 0xFF00FFFF); +// Value32 = Value32 | (AvaWds[BestRangeIndex][BestIndex] << 16); +// WR_DATA(SDR_CLK_DLY_CTRL, Value32); +#else + HAL_SDR_WRITE32(REG_SDR_DLY0, AvaWds[BestRangeIndex][BestIndex]); +// ms_ctrl_0_map->phy_dly0 = AvaWds[BestRangeIndex][BestIndex]; +#endif +#else + SDR_DDL_FCTRL(AvaWds[BestRangeIndex][BestIndex]); +// Value32 = (RD_DATA(SDR_CLK_DLY_CTRL) & 0xFF00FFFF); +// Value32 = Value32 | (AvaWds[BestRangeIndex][BestIndex] << 16); +// WR_DATA(SDR_CLK_DLY_CTRL, Value32); +#endif + #ifdef SUPPORT_DRAM_KED + RdPipe = RecRdPipe[BestRangeIndex]; + TapCnt = AvaWds[BestRangeIndex][BestIndex]; + + value.b[0] = (u8)RdPipe; + value.b[1] = ~value.b[0]; + value.b[2] = (u8)TapCnt; + value.b[3] = ~value.b[2]; + //DiagPrintf("dump1w %x, %x %x %x %x \n\r", value.l, value.b[0], value.b[1], value.b[2], value.b[3]); + HAL_WRITE32(SPI_FLASH_BASE, FLASH_SDRC_PARA_BASE+8*CpuType+4, value.l); + SpicWaitWipDoneRefinedRtl8195A(SpicInitPara); + + valid = 1; + value.b[0] = (u8)valid; + value.b[1] = ~value.b[0]; + value.b[2] = 0xFF; + value.b[3] = 0xFF; + //DiagPrintf("dump1w %x, %x %x %x %x \n\r", value.l, value.b[0], value.b[1], value.b[2], value.b[3]); + HAL_WRITE32(SPI_FLASH_BASE, FLASH_SDRC_PARA_BASE+8*CpuType, value.l); + SpicWaitWipDoneRefinedRtl8195A(SpicInitPara); + #endif + Result = _TRUE; + break; + } + + if (RdPipeCounter == 0) { + + DBG_SDR_INFO("NOT Find RdPipe\n"); + } + } + + return Result; +} // SdrCalibration + + + + +HAL_SDRC_TEXT_SECTION +VOID +ChangeRandSeed( + IN u32 Seed +) +{ + rand_x = Seed; +} + +HAL_SDRC_TEXT_SECTION +u32 +Sdr_Rand2( + VOID +) +{ + HAL_RAM_DATA_SECTION static unsigned int y = 362436; + + HAL_RAM_DATA_SECTION static unsigned int z = 521288629; + + HAL_RAM_DATA_SECTION static unsigned int c = 7654321; + + unsigned long long t, a= 698769069; + + rand_x = 69069 * rand_x + 12345; + y ^= (y << 13); y ^= (y >> 17); y ^= (y << 5); + t = a * z + c; c = (t >> 32); z = t; + + return rand_x + y + z; +} + +HAL_SDRC_TEXT_SECTION +s32 +MemTest( + u32 LoopCnt +) +{ + u32 LoopIndex = 0; + u32 Value32, Addr; + for (LoopIndex = 0; LoopIndex 0x%x != 0x%x\n",LoopIndex, + Addr, Value32, HAL_SDRAM_READ32(Addr)); + return _FALSE; + } + else { + // HAL_SDRAM_WRITE32(Addr, 0); + } + } + return _TRUE; + +} // MemTest + +#endif // end of "#ifdef CONFIG_SDR_EN" diff --git a/component/soc/realtek/8195a/fwlib/src/hal_soc_ps_monitor.c b/component/soc/realtek/8195a/fwlib/src/hal_soc_ps_monitor.c new file mode 100644 index 0000000..fef35df --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/src/hal_soc_ps_monitor.c @@ -0,0 +1,2487 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ +#include "rtl8195a.h" +#include "hal_soc_ps_monitor.h" + +#ifdef CONFIG_SOC_PS_MODULE +START_RAM_FUN_B_SECTION +RAM_START_FUNCTION gRamWakeupFun = {WakeFromSLPPG}; + +extern VOID UartLogIrqHandleRam(VOID * Data); +#if defined (__ICCARM__) +extern void xPortPendSVHandler( void ); +#elif defined (__GNUC__) +extern void xPortPendSVHandler( void ) __attribute__ (( naked )); +#endif +extern void xPortSysTickHandler( void ); +extern void vPortSVCHandler( void ); +extern u32 HalGetCpuClk(VOID); +extern _LONG_CALL_ u32 HalDelayUs(u32 us); + +extern COMMAND_TABLE UartLogRomCmdTable[]; +extern HAL_TIMER_OP HalTimerOp; +extern u32 STACK_TOP; // which is defined in vectors.s + +SYS_ADAPTER SYSAdapte; + +Power_Mgn PwrAdapter; + +VOID ReFillCpuClk(VOID); + +u32 +PatchHalLogUartInit( + IN LOG_UART_ADAPTER UartAdapter +) +{ + u32 SetData; + u32 Divisor; + u32 Dlh; + u32 Dll; + u32 SysClock; + + /* + Interrupt enable Register + 7: THRE Interrupt Mode Enable + 2: Enable Receiver Line Status Interrupt + 1: Enable Transmit Holding Register Empty Interrupt + 0: Enable Received Data Available Interrupt + */ + // disable all interrupts + HAL_UART_WRITE32(UART_INTERRUPT_EN_REG_OFF, 0); + + /* + Line Control Register + 7: DLAB, enable reading and writing DLL and DLH register, and must be cleared after + initial baud rate setup + 3: PEN, parity enable/disable + 2: STOP, stop bit + 1:0 DLS, data length + */ + + // set DLAB bit to 1 + HAL_UART_WRITE32(UART_LINE_CTL_REG_OFF, 0x80); + + // set up buad rate division + +#if 0//def CONFIG_FPGA + SysClock = SYSTEM_CLK; + Divisor = (SysClock / (16 * (UartAdapter.BaudRate))); +#else + { + u32 SampleRate,Remaind; + + SysClock = (HalGetCpuClk()>>2); + + SampleRate = (16 * (UartAdapter.BaudRate)); + + Divisor= SysClock/SampleRate; + + Remaind = ((SysClock*10)/SampleRate) - (Divisor*10); + + if (Remaind>4) { + Divisor++; + } + } +#endif + + + Dll = Divisor & 0xff; + Dlh = (Divisor & 0xff00)>>8; + HAL_UART_WRITE32(UART_DLL_OFF, Dll); + HAL_UART_WRITE32(UART_DLH_OFF, Dlh); + + // clear DLAB bit + HAL_UART_WRITE32(UART_LINE_CTL_REG_OFF, 0); + + // set data format + SetData = UartAdapter.Parity | UartAdapter.Stop | UartAdapter.DataLength; + HAL_UART_WRITE32(UART_LINE_CTL_REG_OFF, SetData); + + /* FIFO Control Register + 7:6 level of receive data available interrupt + 5:4 level of TX empty trigger + 2 XMIT FIFO reset + 1 RCVR FIFO reset + 0 FIFO enable/disable + */ + // FIFO setting, enable FIFO and set trigger level (2 less than full when receive + // and empty when transfer + HAL_UART_WRITE32(UART_FIFO_CTL_REG_OFF, UartAdapter.FIFOControl); + + /* + Interrupt Enable Register + 7: THRE Interrupt Mode enable + 2: Enable Receiver Line status Interrupt + 1: Enable Transmit Holding register empty INT32 + 0: Enable received data available interrupt + */ + HAL_UART_WRITE32(UART_INTERRUPT_EN_REG_OFF, UartAdapter.IntEnReg); + + if (UartAdapter.IntEnReg) { + // Enable Peripheral_IRQ Setting for Log_Uart + HAL_WRITE32(VENDOR_REG_BASE, PERIPHERAL_IRQ_EN, 0x1000000); + + // Enable ARM Cortex-M3 IRQ + NVIC_SetPriorityGrouping(0x3); + NVIC_SetPriority(PERIPHERAL_IRQ, 14); + NVIC_EnableIRQ(PERIPHERAL_IRQ); + } + + + return 0; +} + + +VOID +PSHalInitPlatformLogUart( + VOID +) +{ + IRQ_HANDLE UartIrqHandle; + LOG_UART_ADAPTER UartAdapter; + + //4 Release log uart reset and clock + LOC_UART_FCTRL(OFF); + LOC_UART_FCTRL(ON); + ACTCK_LOG_UART_CCTRL(ON); + + PinCtrl(LOG_UART,S0,ON); + + //4 Register Log Uart Callback function + UartIrqHandle.Data = (u32)NULL;//(u32)&UartAdapter; + UartIrqHandle.IrqNum = UART_LOG_IRQ; + UartIrqHandle.IrqFun = (IRQ_FUN) UartLogIrqHandleRam; + UartIrqHandle.Priority = 0; + + //4 Inital Log uart + UartAdapter.BaudRate = UART_BAUD_RATE_38400; + UartAdapter.DataLength = UART_DATA_LEN_8BIT; + UartAdapter.FIFOControl = 0xC1; + UartAdapter.IntEnReg = 0x00; + UartAdapter.Parity = UART_PARITY_DISABLE; + UartAdapter.Stop = UART_STOP_1BIT; + + //4 Initial Log Uart + PatchHalLogUartInit(UartAdapter); + + //4 Register Isr handle + InterruptRegister(&UartIrqHandle); + + UartAdapter.IntEnReg = 0x05; + + //4 Initial Log Uart for Interrupt + PatchHalLogUartInit(UartAdapter); + + //4 initial uart log parameters before any uartlog operation + //RtlConsolInit(ROM_STAGE,GetRomCmdNum(),(VOID*)&UartLogRomCmdTable);// executing boot seq., + //pUartLogCtl->TaskRdy = 1; +} + + +VOID +SYSIrqHandle +( + IN VOID *Data +) +{ + u32 Rtemp; + + //change cpu clk + ReFillCpuClk(); + HalDelayUs(100); + + Rtemp = (HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_FUNC_EN) | 0x40000000); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_FUNC_EN, Rtemp); + + //disable DSTBY timer + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_ANA_TIM_CTRL, 0); + + //clear wake event IMR + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_SLP_WAKE_EVENT_MSK0, 0); + + //clear wake event ISR + Rtemp = HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_SLP_WAKE_EVENT_STATUS0); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_SLP_WAKE_EVENT_STATUS0, Rtemp); + + //set event flag + PwrAdapter.WakeEventFlag = _TRUE; +} + +VOID +InitSYSIRQ(VOID) +{ + IRQ_HANDLE SysHandle; + PSYS_ADAPTER pSYSAdapte; + pSYSAdapte = &SYSAdapte; + SysHandle.Data = (u32) (pSYSAdapte); + SysHandle.IrqNum = SYSTEM_ON_IRQ; + SysHandle.IrqFun = (IRQ_FUN) SYSIrqHandle; + SysHandle.Priority = 0; + + InterruptRegister(&SysHandle); + InterruptEn(&SysHandle); + PwrAdapter.WakeEventFlag = _FALSE; +} + +void vWFSSVCHandler( void ) +{ +#if defined (__ICCARM__) + // TODO: IAR has different way using assembly +#elif defined (__GNUC__) + asm volatile + ( + "svcing:\n" + " mov r0, %0 \n" + " ldmia r0!, {r4-r7} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ + " ldmia r0!, {r8-r11} \n" + " msr psp, r0 \n" /* Restore the task stack pointer. */ + " orr r14, #0xd \n" + " bx r14 \n" + ::"r"(PwrAdapter.CPUPSP):"r0" + ); +#endif +} + + +VOID +WakeFromSLPPG( + VOID +) +{ + //release shutdone + HAL_WRITE32(PERI_ON_BASE, REG_GPIO_SHTDN_CTRL, 0x7FF); + //HAL_WRITE32(PERI_ON_BASE, REG_CPU_PERIPHERAL_CTRL, 0x110001); + //JTAG rst pull high + HAL_WRITE32(PERI_ON_BASE, REG_GPIO_PULL_CTRL2, 0x05555556); + + ReFillCpuClk(); + + //3 Need Modify + VectorTableInitRtl8195A(0x1FFFFFFC); + + //3 Make PendSV, CallSV and SysTick the same priroity as the kernel. + HAL_WRITE32(0xE000ED00, 0x20, 0xF0F00000); + + //3 Initial Log Uart + PSHalInitPlatformLogUart(); + +#ifdef CONFIG_KERNEL + InterruptForOSInit((VOID*)vWFSSVCHandler, + (VOID*)xPortPendSVHandler, + (VOID*)xPortSysTickHandler); +#endif + //CPURegbackup[13] = CPURegbackup[13]-4; + PwrAdapter.CPURegbackup[16] |= 0x1000000 ; + + ( * ( ( volatile unsigned long * ) (PwrAdapter.CPURegbackup[13]-4) ) )= PwrAdapter.CPURegbackup[16]; //PSR + ( * ( ( volatile unsigned long * ) (PwrAdapter.CPURegbackup[13]-8) ) )= PwrAdapter.CPURegbackup[15]; //PC + ( * ( ( volatile unsigned long * ) (PwrAdapter.CPURegbackup[13]-12) ) )= PwrAdapter.CPURegbackup[14]; //LR + ( * ( ( volatile unsigned long * ) (PwrAdapter.CPURegbackup[13]-16) ) )= PwrAdapter.CPURegbackup[12]; //R12 + ( * ( ( volatile unsigned long * ) (PwrAdapter.CPURegbackup[13]-20) ) )= PwrAdapter.CPURegbackup[3]; //R3 + ( * ( ( volatile unsigned long * ) (PwrAdapter.CPURegbackup[13]-24) ) )= PwrAdapter.CPURegbackup[2]; //R2 + ( * ( ( volatile unsigned long * ) (PwrAdapter.CPURegbackup[13]-28) ) )= PwrAdapter.CPURegbackup[1]; //R1 + ( * ( ( volatile unsigned long * ) (PwrAdapter.CPURegbackup[13]-32) ) )= PwrAdapter.CPURegbackup[0]; //R0 + ( * ( ( volatile unsigned long * ) (PwrAdapter.CPURegbackup[13]-36) ) )= PwrAdapter.CPURegbackup[11]; //R11 + ( * ( ( volatile unsigned long * ) (PwrAdapter.CPURegbackup[13]-40) ) )= PwrAdapter.CPURegbackup[10]; //R10 + ( * ( ( volatile unsigned long * ) (PwrAdapter.CPURegbackup[13]-44) ) )= PwrAdapter.CPURegbackup[9]; //R9 + ( * ( ( volatile unsigned long * ) (PwrAdapter.CPURegbackup[13]-48) ) )= PwrAdapter.CPURegbackup[8]; //R8 + ( * ( ( volatile unsigned long * ) (PwrAdapter.CPURegbackup[13]-52) ) )= PwrAdapter.CPURegbackup[7]; //R7 + ( * ( ( volatile unsigned long * ) (PwrAdapter.CPURegbackup[13]-56) ) )= PwrAdapter.CPURegbackup[6]; //R6 + ( * ( ( volatile unsigned long * ) (PwrAdapter.CPURegbackup[13]-60) ) )= PwrAdapter.CPURegbackup[5]; //R5 + ( * ( ( volatile unsigned long * ) (PwrAdapter.CPURegbackup[13]-64) ) )= PwrAdapter.CPURegbackup[4]; //R4 + PwrAdapter.CPURegbackup[13] = PwrAdapter.CPURegbackup[13]-64; //PSP + PwrAdapter.CPUPSP = PwrAdapter.CPURegbackup[13]; + CPURegBackUp(); + + asm volatile( + " cpsie i \n" /* Globally enable interrupts. */ + " svc 0 \n" /* System call to start first task. */ + " nop \n" + ); +} + +VOID +DurationScaleAndPeriodOP( + IN u32 SDuration, + OUT u32 *ScaleTemp, + OUT u32 *PeriodTemp +) +{ + u8 Idx = 0; + if (SDuration > 8355){ + SDuration = 0x20A3; + } + + //in unit 128us + SDuration = ((SDuration*125)/16); + + for (Idx = 8; Idx < 32; Idx++) { + + if ( (SDuration & 0xFFFFFF00) > 0 ) { + (*ScaleTemp) = (*ScaleTemp) + 1; + SDuration = (SDuration >> 1); + } + else { + break; + } + } + + *ScaleTemp = ((*ScaleTemp) << 8); + *PeriodTemp = SDuration; +} + + +u32 +CLKCal( + IN u8 ClkSel +) +{ + u32 Rtemp = 0; + u32 RRTemp = 0; + + if( ClkSel ){ + //a33_ck + Rtemp |= 0x10000; + } + + //Enable cal + Rtemp |= 0x800000; + HAL_WRITE32(VENDOR_REG_BASE, REG_VDR_ANACK_CAL_CTRL, Rtemp); + + while( (HAL_READ32(VENDOR_REG_BASE, REG_VDR_ANACK_CAL_CTRL) & BIT23) != 0 ); + Rtemp = ((HAL_READ32(VENDOR_REG_BASE, REG_VDR_ANACK_CAL_CTRL) & 0x3FFF))+1; + + if( ClkSel ){ + //a33_ck + RRTemp = (Rtemp); + } + else { + //anack + RRTemp = ((2133/Rtemp) - 1); + } + + //DiagPrintf("CAL : 0x%x\n", RRTemp); + + return RRTemp; +} + +VOID +BackupCPUClk( + VOID +) +{ + u32 Cpubp; + Cpubp = ((HAL_READ32(SYSTEM_CTRL_BASE,REG_SYS_DSTBY_INFO0)&0xFFFFFFF0)|((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_CLK_CTRL1) & (0x70)) >> 4)); + HAL_WRITE32(SYSTEM_CTRL_BASE,REG_SYS_DSTBY_INFO0,Cpubp); +} + +VOID +ReFillCpuClk( + VOID +) +{ + u8 CpuClk = ((u8)(HAL_READ32(SYSTEM_CTRL_BASE,REG_SYS_DSTBY_INFO0)& (0xF))); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_CLK_CTRL1, + ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_CLK_CTRL1) & (~0x70)) + |(CpuClk << 4))); +} + +VOID +SleepClkGatted( + IN u32 SDuration +) +{ + u32 Rtemp = 0; + u32 ScaleTemp = 0; + u32 PeriodTemp = 0; + u32 CalTemp = 0; + + //Backup CPU CLK + BackupCPUClk(); + + //truncate duration + SDuration &= 0x0003FFFC; + //2 CSleep + //3 1.1 Set TU timer timescale + //0x4000_0090[21:16] = 6'h1F + //0x4000_0090[15] = 1'b0 => Disable timer + CalTemp = (CLKCal(ANACK) << 16); + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_ANA_TIM_CTRL)& 0xffff7fff & 0xffc0ffff) | CalTemp); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_ANA_TIM_CTRL, Rtemp); + + //0x4000_0090[11:8] => Time scale + //0x4000_0090[7:0] => Time period + //max duration 0x7FFFFF us, min 0x80 + DurationScaleAndPeriodOP(SDuration, &ScaleTemp, &PeriodTemp); + + Rtemp = (((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_ANA_TIM_CTRL) & 0xfffff000) | ScaleTemp) | PeriodTemp); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_ANA_TIM_CTRL, Rtemp); + + //0x4000_0090[15] = 1'b1 => Enable timer + Rtemp = HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_ANA_TIM_CTRL) | 0x00008000; + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_ANA_TIM_CTRL, Rtemp); + + //3 1.2 Configure platform wake event + //0x4000_0100[0] = 1'b1 => Enable timer and GT as wakeup event to wakeup CPU + Rtemp = 0x00000001; + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_SLP_WAKE_EVENT_MSK0, Rtemp); + + //3 1.3 Configure power state option: + // 1.4.3 0x120[15:8]: sleep power mode option0 [11] = 1 + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_PWRMGT_OPTION) & 0xffff00ff) | 0x74000A00);//A + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_PWRMGT_OPTION, Rtemp); + + // 1.4.4 0x124[7:0]: sleep power mode option1 [0] =1 + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_PWRMGT_OPTION_EXT) & 0xffffff00) | 0x00000001); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_PWRMGT_OPTION_EXT, Rtemp); + + //3 1.5 Enable low power mode + // 1.5.1 0x4000_0118[2] = 1 => for sleep mode + Rtemp = 0x00000004;//HAL_READ32(SYSTEM_CTRL_BASE, REG_SYSON_PWRMGT_CTRL) | 0x00000004; + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_PWRMGT_CTRL, Rtemp); + + //3 1.6 Wait CHIP enter low power mode + // 1.7 Wait deep standby timer timeout + // 1.8 Wait CHIP resume to norm power mode + HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_PWRMGT_CTRL); + __WFI(); + +} + + +VOID SleepPwrGatted( + IN u32 SDuration +) +{ + u32 Rtemp = 0; + u32 ScaleTemp = 0; + u32 PeriodTemp = 0; + u32 CalTemp = 0; + + //Backup CPU CLK + BackupCPUClk(); + + //truncate duration + SDuration &= 0x0003FFFC; + + //2 PSleep + //3 1.1 Set TU timer timescale + //0x4000_0090[21:16] = 6'h1F + //0x4000_0090[15] = 1'b0 => Disable timer + CalTemp = (CLKCal(ANACK) << 16); + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_ANA_TIM_CTRL)& 0xffff7fff & 0xffc0ffff) | CalTemp); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_ANA_TIM_CTRL, Rtemp); + + //0x4000_0090[11:8] => Time scale + //0x4000_0090[7:0] => Time period + //max duration 0x7FFFFF us, min 0x80 + DurationScaleAndPeriodOP(SDuration, &ScaleTemp, &PeriodTemp); + + Rtemp = (((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_ANA_TIM_CTRL) & 0xfffff000) | ScaleTemp) | PeriodTemp); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_ANA_TIM_CTRL, Rtemp); + + //0x4000_0090[15] = 1'b1 => Enable timer + Rtemp = HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_ANA_TIM_CTRL) | 0x00008000; + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_ANA_TIM_CTRL, Rtemp); + + //3 1.2 Configure platform wake event + //0x4000_0100[0] = 1'b1 => Enable timer and GT as wakeup event to wakeup CPU + Rtemp = 0x00000003; + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_SLP_WAKE_EVENT_MSK0, Rtemp); + + //3 1.4 Configure power state option: + // 1.4.3 0x120[15:8]: sleep power mode option0: + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_PWRMGT_OPTION) & 0x00ff00ff) | 0x74000000); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_PWRMGT_OPTION, Rtemp); + + // 1.4.4 0x124[7:0]: sleep power mode option1: + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_PWRMGT_OPTION_EXT) & 0xffffff00) | 0x00000003); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_PWRMGT_OPTION_EXT, Rtemp); + + //3 1.5 Enable low power mode + // 1.5.1 0x4000_0118[2] = 1 => for sleep mode + Rtemp = 0x00000004;//HAL_READ32(SYSTEM_CTRL_BASE, REG_SYSON_PWRMGT_CTRL) | 0x00000004; + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_PWRMGT_CTRL, Rtemp); + + //3 1.6 Wait CHIP enter low power mode + // 1.7 Wait deep standby timer timeout + // 1.8 Wait CHIP resume to norm power mode + HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_PWRMGT_CTRL); + __WFI(); + DiagPrintf("YOU CAN'T SEE ME ~~~~!!!!!!!!!!!!!!!!!!!~~~~~slppg~~~~!!!!!!!!!!"); +} + + +VOID +DStandby( + IN u32 SDuration +) +{ + u32 Rtemp = 0; + u32 ScaleTemp = 0; + u32 PeriodTemp = 0; + u32 CalTemp = 0; + + //Backup CPU CLK + BackupCPUClk(); + + //Clear A33 timer event + //Rtemp = HAL_READ32(SYSTEM_CTRL_BASE, REG_SOC_SYSON_SLP_WAKE_EVENT_STATUS0); + //HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SOC_SYSON_SLP_WAKE_EVENT_STATUS0, Rtemp); + + //2 Deep Standby mode + //3 1.1 Set TU timer timescale + //0x4000_0090[21:16] = 6'h1F + //0x4000_0090[15] = 1'b0 => Disable timer + CalTemp = (CLKCal(ANACK) << 16); + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_ANA_TIM_CTRL)& 0xffff7fff & 0xffc0ffff) | CalTemp); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_ANA_TIM_CTRL, Rtemp); + + //0x4000_0090[11:8] => Time scale + //0x4000_0090[7:0] => Time period + //max duration 0x7FFFFF us, min 0x80 + DurationScaleAndPeriodOP(SDuration, &ScaleTemp, &PeriodTemp); + + Rtemp = (((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_ANA_TIM_CTRL) & 0xfffff000) | ScaleTemp) | PeriodTemp); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_ANA_TIM_CTRL, Rtemp); + + //0x4000_0090[15] = 1'b1 => Enable timer + Rtemp = HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_ANA_TIM_CTRL) | 0x00008000; + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_ANA_TIM_CTRL, Rtemp); + + //3 1.3 Configure platform wake event + // 1.3.1 0x4000_0100[0] = 1'b1 => Enable deep standby timer wakeup event to wakeup CPU + Rtemp = 0x00000001; + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_SLP_WAKE_EVENT_MSK0, Rtemp); + + //3 1.4 Configure power state option: + // 1.4.4 0x120[7:0]: deep standby power mode option: + Rtemp = 0x74000000; + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_PWRMGT_OPTION, Rtemp); + + // 1.4.5 0x124[7:0]: sleep power mode option1 [0] =1 + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_PWRMGT_OPTION_EXT) & 0xffffff00) | 0x00000001); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_PWRMGT_OPTION_EXT, Rtemp); + + //3 1.5 Enable low power mode + // [0x4000_0118[1] = 1 => for deep standby mode] + Rtemp = 0x00000002; + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_PWRMGT_CTRL, Rtemp); + + //3 1.6 Wait CHIP enter low power mode + // 1.7 Wait deep standby timer timeout + // 1.8 Wait CHIP resume to norm power mode + HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_PWRMGT_CTRL); + __WFI(); + + DiagPrintf("YOU CAN'T SEE ME ~~~~!!!!!!!!!!!!!!!!!!!~~~~~~~~~~~~~~~!!!!!!!!!!"); +} + + +VOID +DSleep( + IN u32 SDuration +) +{ + u32 Rtemp = 0; + //u32 ScaleTemp = 0; + //u32 PeriodTemp = 0; + u32 UTemp = 0; + u32 MaxTemp = 0; + + u32 Reada335 = 0; + + //2 Deep Sleep mode: + //3 2.1 Set TU timer timescale + + //3 2.2 Configure deep sleep timer: + //2.2.1 Enable REGU access interface 0x4000_0094[31] = 1 + Rtemp = (HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL) | 0x80000000); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL, Rtemp); + + //2.2.2 Calibration A33 CLK + UTemp = CLKCal(A33CK); + + //Calculate the max value base on the a33 duration + MaxTemp = 0x7FFFFF*0x100/100000*UTemp/100*0x80; + //DiagPrintf("MaxTemp : 0x%x\n", MaxTemp); + + if ( SDuration >= MaxTemp ) { + SDuration = 0x7FFFFF; + } + else { + //In unit of A33 CLK : max num is bounded by anaclk = 1.5k + SDuration = ((((SDuration)/UTemp)*25/16*25/16*125)); + //DiagPrintf("SDuration : 0x%x\n", SDuration); + } + + DiagPrintf("SDuration : 0x%x\n", SDuration); + + //3 2.2.2 Initialize deep sleep counter + //2.2.2.0 0x4000_0094[15:0] = 16'hD300 => Disable deep sleep counter + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL) & 0xffff0000) | 0x0000D300); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL, Rtemp); + //2.2.2.0.1 Clear event + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_WEVENT, HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_WEVENT)); + //2.2.2.1 0x4000_0094[15:0] = 16'h9008 => set counter[7:0] + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL) & 0xffff0000) | 0x00009000 | ((u8)SDuration)); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL, Rtemp); + + //2.2.2.2 0x4000_0094[15:0] = 16'h9100 => set counter[15:8] + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL) & 0xffff0000) | 0x00009100 | ((u8)(SDuration >> 8))); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL, Rtemp); + + //2.2.2.3 0x4000_0094[15:0] = 16'h9200 => set counter[22:16] + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL) & 0xffff0000) | 0x00009200 | ((u8)(SDuration >> 16))); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL, Rtemp); + + //2.2.2.4 0x4000_0094[15:0] = 16'hD380 => Enable deep sleep counter + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL) & 0xffff0000) | 0x0000D380); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL, Rtemp); + + HalDelayUs(1000); + Reada335 = HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CAL_CTRL); + DiagPrintf("a33 timer : 0x%x\n", Reada335); + + HalDelayUs(8000); + + //3 2.2.3 + //2.3 Enable low power mode: 0x4000_0118[0] = 1'b1; + Rtemp = 0x00000001;//HAL_READ32(SYSTEM_CTRL_BASE, REG_SYSON_PWRMGT_CTRL) | 0x00000001; + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_PWRMGT_CTRL, Rtemp); + + //2.4 Wait CHIP enter deep sleep mode + //2.5 Wait deep sleep counter timeout + HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_PWRMGT_CTRL); + __WFI(); + + DiagPrintf("YOU CAN'T SEE ME ~~~~!!!!!!!!!!!!!!!!!!!~~~~~~~~~~~~~~~!!!!!!!!!!"); +} + +VOID +MSBackupProcess( + void +) +{ + + u8 i = 0; + + //backup main stack + for (i = 0; i < (MAX_BACKUP_SIZE-1); i++) { + PwrAdapter.MSPbackup[i] = HAL_READ32(0x1FFFFE00, (0x1FC - (i*4))); + } + + asm volatile + ( + "MRS r0, MSP\n" + "MOV %0, r0\n" + :"=r"(PwrAdapter.MSPbackup[MAX_BACKUP_SIZE-1]) + ::"memory" + ); +} + + +VOID +MSReFillProcess( + VOID +) +{ + u8 i = 0; + + for (i = 0; i < (MAX_BACKUP_SIZE-1); i++) { + + HAL_WRITE32(0x1FFFFE00, (0x1FC - (i*4)), PwrAdapter.MSPbackup[i]); + } + + asm volatile + ( + "MSR MSP, %0\n" + ::"r"(PwrAdapter.MSPbackup[MAX_BACKUP_SIZE-1]):"memory" + ); +} + + +VOID +SoCPSGPIOCtrl( + VOID +) +{ + HAL_WRITE32(PERI_ON_BASE,0x330,0x55555555); + HAL_WRITE32(PERI_ON_BASE,0x334,0x55555555); + HAL_WRITE32(PERI_ON_BASE,0x338,0x05555555); + HAL_WRITE32(PERI_ON_BASE,0x33c,0x55555555); + HAL_WRITE32(PERI_ON_BASE,0x340,0x55555555); + HAL_WRITE32(PERI_ON_BASE,0x344,0x55555555); + HAL_WRITE32(PERI_ON_BASE,0x348,0x55555555); + HAL_WRITE32(PERI_ON_BASE,0x320,0x0); +} + + +VOID +InitSoCPW( + VOID +) +{ + u8 Idx = 0; + + PwrAdapter.ActFuncCount = 0; + PwrAdapter.CurrentState = ACT; + for (Idx = 0; Idx < MAXSTATE; Idx++) { + PwrAdapter.PwrState[Idx].FuncIdx = 0xFF; + PwrAdapter.PwrState[Idx].PowerState = 0xFF; + } +} + +u8 +ChangeSoCPwrState( + IN u8 RequestState, + IN u32 ReqCount +) +{ + + //DiagPrintf("Go to sleep"); + + while(1) { + + HalDelayUs(100); + + if (HAL_READ8(LOG_UART_REG_BASE,0x14)&BIT6){ + + break; + } + } + + switch (RequestState) { + + case ACT: + break; + + case WFE: + __WFE(); + break; + + case WFI: + __WFI(); + break; + + //case SNOOZE: + //break; + + case SLPCG: + SleepClkGatted(ReqCount); + break; + + case SLPPG: + //Resume jump to wakeup function + //HAL_WRITE32(PERI_ON_BASE, 0x218, (HAL_READ32(PERI_ON_BASE,0x218)|BIT31)); + + SoCPSGPIOCtrl(); + SleepPwrGatted(ReqCount); + break; + + case DSTBY: + SoCPSGPIOCtrl(); + DStandby(ReqCount); + break; + + case DSLP: + case INACT: + SoCPSGPIOCtrl(); + DSleep(ReqCount); + break; + } + return 0; +} + + +VOID +SoCPwrDecision( + void +) +{ + u8 Idx = 0; + u8 StateIdx = 0; + u8 State = _TRUE; + u8 NextState = 0; + u32 CurrentCount, RemainCount, PTTemp; + + if ( PwrAdapter.ActFuncCount ) { + + //update remaining count + CurrentCount = HalTimerOp.HalTimerReadCount(1); + + for (Idx = 0; Idx < PwrAdapter.ActFuncCount; Idx++) { + + if (PwrAdapter.PwrState[Idx].RegCount < CurrentCount) { + PTTemp = (0xFFFFFFFF - CurrentCount + PwrAdapter.PwrState[Idx].RegCount); + } + else { + PTTemp = (PwrAdapter.PwrState[Idx].RegCount - CurrentCount); + } + + if ( PTTemp < PwrAdapter.PwrState[Idx].ReqDuration ) { + PwrAdapter.PwrState[Idx].RemainDuration = PwrAdapter.PwrState[Idx].ReqDuration - PTTemp; + } + else { + //active this function + if ( PwrAdapter.PwrState[Idx].PowerState > SLPPG ) { + //Todo: re-initial function as GPIO wake + } + PwrAdapter.PwrState[Idx].PowerState = ACT; + PwrAdapter.PwrState[Idx].RemainDuration = 0; + PwrAdapter.PwrState[Idx].ReqDuration = 0; + } + } + + //Select next power mode + for (StateIdx = DSLP; StateIdx >= ACT; StateIdx--) { + + for (Idx = 0; Idx < PwrAdapter.ActFuncCount; Idx++) { + + State = _TRUE; + if (PwrAdapter.PwrState[Idx].PowerState < StateIdx) { + State = _FALSE; + break; + } + } + + if ( State ) { + NextState = StateIdx; + break; + } + } + + //fine min sleep time + RemainCount = PwrAdapter.PwrState[0].RemainDuration; + for (Idx = 0; Idx < PwrAdapter.ActFuncCount; Idx++) { + + if ( RemainCount > PwrAdapter.PwrState[Idx].RemainDuration ) { + + RemainCount = PwrAdapter.PwrState[Idx].RemainDuration; + } + } + + //for debug + #if 1 + DiagPrintf("RemainCount : 0x%x \n", RemainCount); + DiagPrintf("NextState : 0x%x \n", NextState); + #endif + #if 0 + //Change state + if ( NextState > SLPCG ) { + if ( RemainCount > 640 ) { + ChangeSoCPwrState(NextState, RemainCount); + } + else { + ChangeSoCPwrState(SLPCG, RemainCount); + } + } + else { + if (NextState != ACT ) { + ChangeSoCPwrState(NextState, RemainCount); + } + } + #endif + } + else { + //todo: go to DSLP + } +} + + +VOID +RegPowerState( + REG_POWER_STATE RegPwrState +) +{ + u8 Idx = 0; + u8 StateIdx; + u8 FState = 0; + + for (Idx = 0; Idx < PwrAdapter.ActFuncCount; Idx++) { + if (PwrAdapter.PwrState[Idx].FuncIdx == RegPwrState.FuncIdx) { + StateIdx = Idx; + FState = _TRUE; + } + } + + switch (RegPwrState.PwrState) { + + case INACT : + if (FState) { + for (Idx = StateIdx; Idx < PwrAdapter.ActFuncCount; Idx++) { + PwrAdapter.PwrState[Idx].FuncIdx = PwrAdapter.PwrState[Idx+1].FuncIdx; + PwrAdapter.PwrState[Idx].PowerState = PwrAdapter.PwrState[Idx+1].PowerState; + PwrAdapter.PwrState[Idx].ReqDuration = PwrAdapter.PwrState[Idx+1].ReqDuration; + PwrAdapter.PwrState[Idx].RegCount = PwrAdapter.PwrState[Idx+1].RegCount; + } + PwrAdapter.ActFuncCount--; + } + else { + } + break; + + default: + + if (FState) { + PwrAdapter.PwrState[StateIdx].PowerState = RegPwrState.PwrState; + PwrAdapter.PwrState[StateIdx].ReqDuration = RegPwrState.ReqDuration; + PwrAdapter.PwrState[StateIdx].RegCount = HalTimerOp.HalTimerReadCount(1); + } + else { + PwrAdapter.PwrState[PwrAdapter.ActFuncCount].FuncIdx = RegPwrState.FuncIdx; + PwrAdapter.PwrState[PwrAdapter.ActFuncCount].PowerState = RegPwrState.PwrState; + PwrAdapter.PwrState[PwrAdapter.ActFuncCount].ReqDuration = RegPwrState.ReqDuration; + PwrAdapter.PwrState[PwrAdapter.ActFuncCount].RegCount = HalTimerOp.HalTimerReadCount(1); + PwrAdapter.ActFuncCount++; + } + + break; + } + + //for debug + #if 1 + for (Idx = 0; Idx < PwrAdapter.ActFuncCount; Idx++) { + DiagPrintf("RegPwrIdx : %d \n", Idx); + DiagPrintf("FuncIdx : %d \n", PwrAdapter.PwrState[Idx].FuncIdx); + DiagPrintf("PowerState : 0x%x \n", PwrAdapter.PwrState[Idx].PowerState); + DiagPrintf("ReqDuration : 0x%x \n", PwrAdapter.PwrState[Idx].ReqDuration); + DiagPrintf("RegCount : 0x%x \n", PwrAdapter.PwrState[Idx].RegCount); + } + #endif +} + + +VOID +SetSYSTimer( + IN u32 SDuration +) +{ + u32 Rtemp = 0; + u32 ScaleTemp = 0; + u32 PeriodTemp = 0; + u32 CalTemp = 0; + + //0x4000_0090[15] = 1'b0 => Disable timer + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_ANA_TIM_CTRL, 0); + + //calculate scale and period + CalTemp = (CLKCal(ANACK) << 16); + DurationScaleAndPeriodOP(SDuration, &ScaleTemp, &PeriodTemp); + + Rtemp = ((CalTemp | ScaleTemp) | PeriodTemp); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_ANA_TIM_CTRL, Rtemp); +} + +VOID +SleepCG( + IN u8 Option, + IN u32 SDuration +) +{ + u32 Rtemp = 0; + u32 WakeEvent = HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_SLP_WAKE_EVENT_MSK0); + + //Backup CPU CLK + BackupCPUClk(); + + //Clear event + PwrAdapter.WakeEventFlag = _FALSE; + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_SLP_WAKE_EVENT_STATUS0, HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_SLP_WAKE_EVENT_STATUS0)); + + //3 2 Configure power state option: + // 2.1 power mode option: + Rtemp = 0x74000900; + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_PWRMGT_OPTION, Rtemp); + + // 2.2 sleep power mode option1 + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_PWRMGT_OPTION_EXT) & 0xffffff00)|0x2); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_PWRMGT_OPTION_EXT, Rtemp); + + if (Option & SLP_STIMER) { + + //Set TU timer timescale + SetSYSTimer(SDuration); + + //0x4000_0090[15] = 1'b1 => Enable timer + Rtemp = HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_ANA_TIM_CTRL) | 0x00008000; + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_ANA_TIM_CTRL, Rtemp); + + //Enable wake event + WakeEvent |= BIT0; + } + + if (Option & SLP_GTIMER) { + + //Enable wake event + WakeEvent |= BIT1; + } + + if (Option & SLP_GPIO) { + + //Enable wake event + WakeEvent |= BIT4; + } + + if (Option & SLP_WL) { + + //Enable wake event + WakeEvent |= BIT8; + } + + if (Option & SLP_NFC) { + + //Enable wake event + WakeEvent |= BIT28; + } + + if (Option & SLP_SDIO) { + + //Enable wake event + //WakeEvent |= BIT14; + } + + if (Option & SLP_USB) { + + //Enable wake event + //WakeEvent |= BIT16; + } + + if (Option & SLP_TIMER33) { + + //Enable wake event + WakeEvent |= BIT28; + } + + while(1) { + + HalDelayUs(100); + + if (HAL_READ8(LOG_UART_REG_BASE,0x14)&BIT6){ + + break; + } + } + + //Set Event + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_SLP_WAKE_EVENT_MSK0, WakeEvent); + + //3 Enable low power mode + //Enable low power mode: + if (PwrAdapter.WakeEventFlag != _TRUE){ + + Rtemp = 0x00000004; + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_PWRMGT_CTRL, Rtemp); + + //3 Wait CHIP enter low power mode + // Wait deep standby timer timeout + // Wait CHIP resume to norm power mode + HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_PWRMGT_CTRL); + __WFI(); + } +} + + +VOID +DSTBYGpioCtrl( + IN u8 PinEn, + IN u8 WMode +) +{ + u32 Rtemp = (HAL_READ32(SYSTEM_CTRL_BASE,REG_SYS_GPIO_DSTBY_WAKE_CTRL0)|PinEn|(PinEn<<16)|(PinEn<<24)); + u32 Stemp = (PinEn<<8); + + if (WMode) { + Rtemp = (Rtemp|Stemp); + } + else { + Rtemp = (Rtemp & (~Stemp)); + } + + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_GPIO_DSTBY_WAKE_CTRL0, Rtemp); + + Rtemp = (HAL_READ32(SYSTEM_CTRL_BASE,REG_SYS_GPIO_DSTBY_WAKE_CTRL1)|PinEn|(PinEn<<16)|BIT9); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_GPIO_DSTBY_WAKE_CTRL1, Rtemp); +} + + +VOID +DeepStandby( + IN u8 Option, + IN u32 SDuration, + IN u8 GpioOption +) +{ + u32 Rtemp = 0; + + //Clear event + PwrAdapter.WakeEventFlag = _FALSE; + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_SLP_WAKE_EVENT_STATUS0, HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_SLP_WAKE_EVENT_STATUS0)); + + //3 2 Configure power state option: + // 2.1 deep standby power mode option: + Rtemp = 0x74000100; + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_PWRMGT_OPTION, Rtemp); + + // 2.2 sleep power mode option1 + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_PWRMGT_OPTION_EXT) & 0xffffff00)); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_PWRMGT_OPTION_EXT, Rtemp); + + if (Option & DSTBY_STIMER) { + + //3 3.1 Set TU timer timescale + SetSYSTimer(SDuration); + + //3 3.2 Configure platform wake event + // 1.3.1 0x4000_0100[0] = 1'b1 => Enable deep standby timer wakeup event to wakeup CPU + Rtemp = (HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_SLP_WAKE_EVENT_MSK0)|BIT0); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_SLP_WAKE_EVENT_MSK0, Rtemp); + + //0x4000_0090[15] = 1'b1 => Enable timer + Rtemp = HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_ANA_TIM_CTRL) | 0x00008000; + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_ANA_TIM_CTRL, Rtemp); + } + + if (Option & DSTBY_NFC){ + //Enable wake event + Rtemp = (HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_SLP_WAKE_EVENT_MSK0)|BIT28); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_SLP_WAKE_EVENT_MSK0, Rtemp); + } + + if (Option & DSTBY_TIMER33){ + //Enable wake event + Rtemp = (HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_SLP_WAKE_EVENT_MSK0)|BIT28); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_SLP_WAKE_EVENT_MSK0, Rtemp); + } + + if (Option & DSTBY_GPIO){ + + if (GpioOption & BIT0) { + DSTBYGpioCtrl(BIT0, (GpioOption & BIT4)); + } + + if (GpioOption & BIT1) { + DSTBYGpioCtrl(BIT1, (GpioOption & BIT5)); + } + + if (GpioOption & BIT2) { + DSTBYGpioCtrl(BIT2, (GpioOption & BIT6)); + } + + if (GpioOption & BIT3) { + DSTBYGpioCtrl(BIT3, (GpioOption & BIT7)); + } + + //Enable wake event + if (GpioOption & 0xF){ + Rtemp = (HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_SLP_WAKE_EVENT_MSK0)|BIT29); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_SLP_WAKE_EVENT_MSK0, Rtemp); + } + } + + + //3 Enable low power mode + //Enable low power mode: + if (PwrAdapter.WakeEventFlag != _TRUE){ + + SpicDeepPowerDownFlashRtl8195A(); + + LDO25M_CTRL(OFF); + + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_GPIO_SHTDN_CTRL, 0x0); + + Rtemp = (HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_FUNC_EN) & 0xBFFFFFFF); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_FUNC_EN, Rtemp); + + Rtemp = 0x00000002; + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_PWRMGT_CTRL, Rtemp); + + //3 Wait CHIP enter low power mode + // Wait deep standby timer timeout + // Wait CHIP resume to norm power mode + HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_PWRMGT_CTRL); + __WFI(); + } +} + + + +VOID +DeepSleep( + IN u8 Option, + IN u32 SDuration +) +{ + u32 Rtemp = 0; + u32 UTemp = 0; + u32 MaxTemp = 0; + + //1.1.1 Enable REGU access interface 0x4000_0094[31] = 1 + Rtemp = (HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL) | 0x80000000); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL, Rtemp); + + //1.1.2 0x4000_0094[15:0] = 16'hD300 => Disable deep sleep counter + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL) & 0xffff0000) | 0x0000D300); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL, Rtemp); + + while(HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL)&BIT15){}; + + //1.1.3 Clear event + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_WEVENT, HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_WEVENT)); + + if (Option & DS_TIMER33){ + //2.1.1 Calibration A33 CLK + UTemp = CLKCal(A33CK); + + //Calculate the max value base on the a33 duration + MaxTemp = ((((0x7FFFFF/3)*500)/UTemp)*25); + + if ( SDuration >= MaxTemp ) { + SDuration = 0x7FFFFF; + } + else { + //In unit of A33 CLK : max num is bounded by anaclk = 1.5k + SDuration = ((((SDuration/3)*500)/UTemp)*25); + } + + //2.1.2 Initialize deep sleep counter + //2.1.3.1 0x4000_0094[15:0] = 16'h9008 => set counter[7:0] + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL) & 0xffff0000) | 0x00009000 | ((u8)SDuration)); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL, Rtemp); + + while(HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL)&BIT15){}; + + //2.1.3.2 0x4000_0094[15:0] = 16'h9100 => set counter[15:8] + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL) & 0xffff0000) | 0x00009100 | ((u8)(SDuration >> 8))); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL, Rtemp); + + while(HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL)&BIT15){}; + + //2.1.3.3 0x4000_0094[15:0] = 16'h9200 => set counter[22:16] + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL) & 0xffff0000) | 0x00009200 | ((u8)(SDuration >> 16))); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL, Rtemp); + + while(HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL)&BIT15){}; + + //2.1.3.4 0x4000_0094[15:0] = 16'hD380 => Enable deep sleep counter + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL) & 0xffff0000) | 0x0000D380); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL, Rtemp); + + while(HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL)&BIT15){}; + } + + if (Option & DS_GPIO) { + //2.2 en GPIO + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL) & 0xffff0000) | 0x00009410); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL, Rtemp); + while(HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL)&BIT15){}; + } + + + //0x4000_0100[28] = 1'b1 => Enable A33 wakeup event to wakeup CPU + PwrAdapter.WakeEventFlag = _FALSE; + Rtemp = (HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_SLP_WAKE_EVENT_MSK0)|BIT28); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_SLP_WAKE_EVENT_MSK0, Rtemp); + + //3 2.3 + //2.3 Enable low power mode: 0x4000_0118[0] = 1'b1; + if (PwrAdapter.WakeEventFlag != _TRUE){ + + SpicDeepPowerDownFlashRtl8195A(); + + LDO25M_CTRL(OFF); + + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_GPIO_SHTDN_CTRL, 0x0); + + Rtemp = (HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_FUNC_EN) & 0xBFFFFFFF); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_FUNC_EN, Rtemp); + + Rtemp = 0x00000001;//HAL_READ32(SYSTEM_CTRL_BASE, REG_SYSON_PWRMGT_CTRL) | 0x00000001; + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_PWRMGT_CTRL, Rtemp); + + //2.4 Wait CHIP enter deep sleep mode + //2.5 Wait deep sleep counter timeout + HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_PWRMGT_CTRL); + __WFI(); + } +} + + +VOID +DSleep_GPIO( + VOID +) +{ + u32 Rtemp = 0; + + //1.1 Clear event + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_WEVENT, HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_WEVENT)); + + //2 Deep Sleep mode: + //3 2.2 Configure GPIO: + //2.2.1 Enable REGU access interface 0x4000_0094[31] = 1 + Rtemp = (HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL) | 0x80000000); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL, Rtemp); + + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL) & 0xffff0000) | 0x00009410); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL, Rtemp); + + //2.2.2 + //2.3 Enable low power mode: 0x4000_0118[0] = 1'b1; + Rtemp = 0x00000001;//HAL_READ32(SYSTEM_CTRL_BASE, REG_SYSON_PWRMGT_CTRL) | 0x00000001; + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_PWRMGT_CTRL, Rtemp); + + //2.4 Wait CHIP enter deep sleep mode + //2.5 Wait deep sleep counter timeout + HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_PWRMGT_CTRL); + __WFI(); +} + +VOID +DSleep_Timer( + IN u32 SDuration +) +{ + u32 Rtemp = 0; + u32 UTemp = 0; + u32 MaxTemp = 0; + + //2 Deep Sleep mode: + //3 2.1 Set TU timer timescale + + //3 2.2 Configure deep sleep timer: + //2.2.1 Enable REGU access interface 0x4000_0094[31] = 1 + Rtemp = (HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL) | 0x80000000); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL, Rtemp); + + //2.2.2 0x4000_0094[15:0] = 16'hD300 => Disable deep sleep counter + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL) & 0xffff0000) | 0x0000D300); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL, Rtemp); + + //2.2.3 Clear event + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_WEVENT, HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_WEVENT)); + + //2.2.4 Calibration A33 CLK + UTemp = CLKCal(A33CK); + + //Calculate the max value base on the a33 duration + MaxTemp = 0x7FFFFF*0x100/100000*UTemp/100*0x80; + + if ( SDuration >= MaxTemp ) { + SDuration = 0x7FFFFF; + } + else { + //In unit of A33 CLK : max num is bounded by anaclk = 1.5k + SDuration = ((((SDuration)/UTemp)*25/16*25/16*125)); + } + + //DiagPrintf("SDuration : 0x%x\n", SDuration); + + //2.2.5 Initialize deep sleep counter + //2.2.5.1 0x4000_0094[15:0] = 16'h9008 => set counter[7:0] + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL) & 0xffff0000) | 0x00009000 | ((u8)SDuration)); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL, Rtemp); + + //2.2.5.2 0x4000_0094[15:0] = 16'h9100 => set counter[15:8] + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL) & 0xffff0000) | 0x00009100 | ((u8)(SDuration >> 8))); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL, Rtemp); + + //2.2.5.3 0x4000_0094[15:0] = 16'h9200 => set counter[22:16] + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL) & 0xffff0000) | 0x00009200 | ((u8)(SDuration >> 16))); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL, Rtemp); + + //2.2.5.4 0x4000_0094[15:0] = 16'hD380 => Enable deep sleep counter + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL) & 0xffff0000) | 0x0000D380); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL, Rtemp); + + //HalDelayUs(1000); + //Rtemp = HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CAL_CTRL); + //DiagPrintf("a33 timer : 0x%x\n", Rtemp); + HalDelayUs(8000); + + //3 2.3 + //2.3 Enable low power mode: 0x4000_0118[0] = 1'b1; + Rtemp = 0x00000001;//HAL_READ32(SYSTEM_CTRL_BASE, REG_SYSON_PWRMGT_CTRL) | 0x00000001; + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_PWRMGT_CTRL, Rtemp); + + //2.4 Wait CHIP enter deep sleep mode + //2.5 Wait deep sleep counter timeout + HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_PWRMGT_CTRL); + __WFI(); +} + + +#if 0 +VOID +En32KCalibration( + VOID +) +{ + u32 Rtemp; + u32 Ttemp = 0; + + while(1) { + + //set parameter + HAL_WRITE32(SYSTEM_CTRL_BASE,REG_OSC32K_REG_CTRL0, 0); + Rtemp = 0x80f880; + HAL_WRITE32(SYSTEM_CTRL_BASE,REG_OSC32K_REG_CTRL0, Rtemp); + + DiagPrintf("cal en\n"); + + //Polling LOCK + Rtemp = 0x110000; + HAL_WRITE32(SYSTEM_CTRL_BASE,REG_OSC32K_REG_CTRL0, Rtemp); + DiagPrintf("polling lock\n"); + + Rtemp = HAL_READ32(SYSTEM_CTRL_BASE,REG_OSC32K_REG_CTRL1); + if ((Rtemp & 0x3000) != 0x0){ + break; + } + else { + Ttemp++; + DiagPrintf("check lock: %d\n", Ttemp); + } + } + + Rtemp = 0x884000; + HAL_WRITE32(SYSTEM_CTRL_BASE,REG_OSC32K_REG_CTRL0, Rtemp); +} +#endif + + +VOID +SoCPwrReinitProcess( + VOID +) +{ + //clear resume jumping condition + HAL_WRITE32(PERI_ON_BASE, 0x218, (HAL_READ32(PERI_ON_BASE,0x218)&(~BIT31))); + + #ifdef CONFIG_KERNEL + InterruptForOSInit((VOID*)vPortSVCHandler, + (VOID*)xPortPendSVHandler, + (VOID*)xPortSysTickHandler); + #endif + + //msp stack + MSReFillProcess(); + + //init sys timer + ( * ( ( volatile unsigned long * ) 0xe000e014 ) ) = 0xc34f;//portNVIC_SYSTICK_LOAD_REG + ( * ( ( volatile unsigned long * ) 0xe000e010 ) ) = 0x10007;//portNVIC_SYSTICK_CTRL_REG + + //3 Reinit SYS int + { + IRQ_HANDLE SysHandle; + PSYS_ADAPTER pSYSAdapte; + pSYSAdapte = &SYSAdapte; + SysHandle.Data = (u32) (pSYSAdapte); + SysHandle.IrqNum = SYSTEM_ON_IRQ; + SysHandle.IrqFun = (IRQ_FUN) SYSIrqHandle; + SysHandle.Priority = 0; + + InterruptRegister(&SysHandle); + InterruptEn(&SysHandle); + } + //DiagPrintf("REINIT IRQ0!!!!!!!!!!\n"); + //HAL_WRITE32(0xE000ED00, 0x14, 0x200); + +} + + +VOID +SoCEnterPS( + VOID +) +{ +} + + +VOID +SoCPWRIdleTaskHandle( + VOID +) +{ + //static u32 IdleLoopCount = 0; + static u32 IdleCount = 0; + //u8 Chktemp = 0; + //u32 CMDTemp[6]; + //u32 Rtemp,Rtemp1,Rtemp2; + + //IdleCount++; + //HalDelayUs(1000); + //if ((IdleCount > 5000)||(HAL_READ8(SYSTEM_CTRL_BASE,REG_SOC_SYSON_DSTBY_INFO0+1) == 0x12)) + if (HAL_READ8(SYSTEM_CTRL_BASE, 0xf2) == 0xda) {// { + + HAL_WRITE32(SYSTEM_CTRL_BASE,REG_SOC_FUNC_EN, (HAL_READ32(SYSTEM_CTRL_BASE,REG_SOC_FUNC_EN)|BIT29)); + + HAL_WRITE32(SYSTEM_CTRL_BASE,0xf0,0); + + #if 0 //slp pg + //backup cpu reg + CPURegBackUp(); + + //backup main stack + MSBackupProcess(); + + //Wait for LogUart print out + while(1) { + HalDelayUs(100); + if (HAL_READ8(LOG_UART_REG_BASE,0x14)&BIT6){ + break; + } + } + + SoCPSGPIOCtrl(); + + ChangeSoCPwrState(SLPPG, 0xFFFFF); + + asm volatile + ( + "SLPPG_WAKEUP_POINT:\n" + ); + + SoCPwrReinitProcess(); + + //DiagPrintf("idle~~~~~~~~~~~~~~~~~\n"); + DiagPrintf("SLP_PG = %d\n", HAL_READ32(SYSTEM_CTRL_BASE,0xf8)); + #endif + asm volatile + ( + "SLPPG_WAKEUP_POINT:\n" + ); + + #if 1 //dslp + //Wait for LogUart print out + while(1) { + HalDelayUs(100); + if (HAL_READ8(LOG_UART_REG_BASE,0x14)&BIT6){ + break; + } + } + + ChangeSoCPwrState(DSTBY, 0xFFFFF); + #endif + + } + + if (IdleCount>500){ + IdleCount = 0; + if (HAL_READ32(SYSTEM_CTRL_BASE,0xf4) ==0) { + HAL_WRITE32(SYSTEM_CTRL_BASE,0xf0,HAL_READ32(SYSTEM_CTRL_BASE,0xf0)|0xda0000); + HAL_WRITE32(SYSTEM_CTRL_BASE,0xf8,HAL_READ32(SYSTEM_CTRL_BASE,0xf8)+1); + DiagPrintf("DSTBY = %d\n", HAL_READ32(SYSTEM_CTRL_BASE,0xf8)); + } + //DiagPrintf("idle~~~~~~~~~~~~~~~~~\n"); + } + else { + HalDelayUs(100000); + IdleCount++; + } +} + +#ifdef CONFIG_SOC_PS_VERIFY +VOID +SYSTestIrqHandle +( + IN VOID *Data +) +{ + u32 Rtemp; + static u32 Ttemp = 0; + + //change cpu clk + ReFillCpuClk(); + HalDelayUs(100); + + //JTAG rst pull high + HAL_WRITE32(PERI_ON_BASE, REG_GPIO_PULL_CTRL2, 0x0202aaaa); + + //release shutdone + //HAL_WRITE32(PERI_ON_BASE, REG_GPIO_SHTDN_CTRL, 0x7ff); + + //disable DSTBY timer + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_ANA_TIM_CTRL, 0); + + //clear wake event IMR + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_SLP_WAKE_EVENT_MSK0, 0); + + //clear wake event ISR + Rtemp = HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_SLP_WAKE_EVENT_STATUS0); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_SLP_WAKE_EVENT_STATUS0, Rtemp); + + //HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SOC_SYSON_DSTBY_INFO0, Ttemp); + + //DiagPrintf("Ttemp : %d\n", Ttemp); + + Ttemp++; + //Rtemp = HalTimerOp.HalTimerReadCount(1); + //DiagPrintf("32k counter : %x\n", Rtemp);//32k counter : + //DiagPrintf("\n"); + + //PwrAdapter.SleepFlag = 1; + //DiagPrintf("\n"); + //DiagPrintf("0x234 after slp : %x\n", HAL_READ32(SYSTEM_CTRL_BASE,0x234)+1); + //HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SOC_SYSON_DSTBY_INFO0, HAL_READ32(SYSTEM_CTRL_BASE,REG_SOC_SYSON_DSTBY_INFO0)+1); + //HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SOC_SYSON_DSTBY_INFO1, HAL_READ32(SYSTEM_CTRL_BASE,REG_SOC_SYSON_DSTBY_INFO1)+1); + //HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SOC_SYSON_DSTBY_INFO2, HAL_READ32(SYSTEM_CTRL_BASE,REG_SOC_SYSON_DSTBY_INFO2)+1); + //HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SOC_SYSON_DSTBY_INFO3, HAL_READ32(SYSTEM_CTRL_BASE,REG_SOC_SYSON_DSTBY_INFO3)+1); + //DiagPrintf("f0 counter : %x\n", HAL_READ32(SYSTEM_CTRL_BASE,REG_SOC_SYSON_DSTBY_INFO0)); + //DiagPrintf("f1 counter : %x\n", HAL_READ32(SYSTEM_CTRL_BASE,REG_SOC_SYSON_DSTBY_INFO1)); + //DiagPrintf("f2 counter : %x\n", HAL_READ32(SYSTEM_CTRL_BASE,REG_SOC_SYSON_DSTBY_INFO2)); + //DiagPrintf("f3 counter : %x\n", HAL_READ32(SYSTEM_CTRL_BASE,REG_SOC_SYSON_DSTBY_INFO3)); + //DiagPrintf("\n"); + //DiagPrintf("ya ~~~~\n"); + + PwrAdapter.WakeEventFlag = _TRUE; +} + +VOID +InitSYSTestIRQ(VOID) +{ + IRQ_HANDLE SysHandle; + PSYS_ADAPTER pSYSAdapte; + pSYSAdapte = &SYSAdapte; + SysHandle.Data = (u32) (pSYSAdapte); + SysHandle.IrqNum = SYSTEM_ON_IRQ; + SysHandle.IrqFun = (IRQ_FUN) SYSIrqHandle; + SysHandle.Priority = 0; + + InterruptRegister(&SysHandle); + InterruptEn(&SysHandle); + PwrAdapter.WakeEventFlag = _FALSE; +} + +VOID +SetA33Timer( + IN u32 SDuration +) +{ + u32 Rtemp = 0; + //u32 ScaleTemp = 0; + //u32 PeriodTemp = 0; + u32 UTemp = 0; + u32 MaxTemp = 0; + + //2 Deep Sleep mode: + //3 2.1 Set TU timer timescale + + //3 2.2 Configure deep sleep timer: + //2.2.1 Enable REGU access interface 0x4000_0094[31] = 1 + Rtemp = (HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL) | 0x80000000); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL, Rtemp); + + //2.2.2 Calibration A33 CLK + UTemp = CLKCal(A33CK); + DiagPrintf("CAL : 0x%x\n", UTemp); + + //Calculate the max value base on the a33 duration + MaxTemp = 0x7FFFFF*0x100/100000*UTemp/100*0x80; + DiagPrintf("MaxTemp : 0x%x\n", MaxTemp); + + if ( SDuration >= MaxTemp ) { + SDuration = 0x7FFFFF; + } + else { + //In unit of A33 CLK : max num is bounded by anaclk = 1.5k + SDuration = ((((SDuration)/UTemp)*25/16*25/16*125)); + DiagPrintf("SDuration : 0x%x\n", SDuration); + + } + + //3 2.2.2 Initialize deep sleep counter + //2.2.2.1 0x4000_0094[15:0] = 16'h9008 => set counter[7:0] + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL) & 0xffff0000) | 0x00009000 | ((u8)SDuration)); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL, Rtemp); + + //2.2.2.2 0x4000_0094[15:0] = 16'h9100 => set counter[15:8] + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL) & 0xffff0000) | 0x00009100 | ((u8)(SDuration >> 8))); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL, Rtemp); + + //2.2.2.3 0x4000_0094[15:0] = 16'h9200 => set counter[22:16] + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL) & 0xffff0000) | 0x00009200 | ((u8)(SDuration >> 16))); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL, Rtemp); + + //2.2.2.4 0x4000_0094[15:0] = 16'hD380 => Enable deep sleep counter + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL) & 0xffff0000) | 0x0000D380); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL, Rtemp); + + DiagPrintf("a33 timer : 0x%x\n", HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CAL_CTRL)); +} + + +VOID +PrintCPU( + VOID +) +{ + + #if 0 + DiagPrintf("r13 : 0x%x\n", PwrAdapter.CPURegbackup[24]); + DiagPrintf("pc : 0x%x\n", PwrAdapter.CPURegbackup[23]); + DiagPrintf("control : 0x%x\n", PwrAdapter.CPURegbackup[22]); + DiagPrintf("psp : 0x%x\n", PwrAdapter.CPURegbackup[21]); + DiagPrintf("msp : 0x%x\n", PwrAdapter.CPURegbackup[20]); + #endif + + #if 0 + u8 i; + for (i = 0; i < 21; i++){ + PwrAdapter.CPURegbackup[i] = ( * ( ( volatile unsigned long * ) (PwrAdapter.CPURegbackup[24]+(i*4)) ) ); + } + #endif + + u8 i; + for (i = 0; i < 25; i++){ + DiagPrintf("CPURegbackup_idx : %d , 0x%x\n", i, PwrAdapter.CPURegbackup[i]); + } + + + #if 1 + for (i = 0; i < 21; i++) { + DiagPrintf("backup_idx : 0x%x , 0x%x\n", PwrAdapter.CPUPSP+(i*4),( * ( ( volatile unsigned long * ) (PwrAdapter.CPUPSP+(i*4)) ) ));//CPURegbackup[1] + } + #endif + + #if 0 + { + u32 cpupspc; + asm volatile + ( + "MRS %0, PSP\n" + :"=r"(cpupspc) + ::"memory" + ); + for (i = 0; i < 21; i++) { + DiagPrintf("stack addr : 0x%x , 0x%x\n", (cpupspc+(i*4)),( * ( ( volatile unsigned long * ) (cpupspc+(i*4)) ) ));//CPURegbackup[1] + } + } + #endif +} + + +VOID +SoCPSMEMTestInit( + IN u32 StartAddr, + IN u32 Length, + IN u32 Pattern +) +{ + u32 Idx; + for( Idx = 0; Idx < Length; Idx += 4 ){ + + HAL_WRITE32(StartAddr,Idx,Pattern); + } +} + +u8 +SoCPSMEMTestChk( + IN u32 StartAddr, + IN u32 Length, + IN u32 Pattern +) +{ + u32 Idx; + + for( Idx = 0; Idx < Length; Idx += 4 ){ + if (HAL_READ32(StartAddr,Idx) != Pattern) { + DiagPrintf("addr 0x%x fail\n", (StartAddr+Idx)); + return 0; + } + } + DiagPrintf("addr 0x%x pass\n", StartAddr); + return 1; +} + + +VOID +SoCPWRIdleTaskHandleTest( + VOID +) +{ + static u32 IdleTemp = 0; + u32 Rtemp,Rtemp1,Rtemp2; + u8 RRtemp,CMDTemp[8],Chktemp; + + if (0){//(HAL_READ8(SYSTEM_CTRL_BASE,REG_SOC_SYSON_DSTBY_INFO0) == 0x0) { + + IdleTemp++; + HalDelayUs(1000); + + if (IdleTemp >= 15000) { + DiagPrintf("\n"); + DiagPrintf("Go to sleep ~~~~ \n"); + HAL_WRITE32(SYSTEM_CTRL_BASE,REG_SYS_DSTBY_INFO0,0x12345678); + DiagPrintf("0xf0 : 0x%x\n",HAL_READ32(SYSTEM_CTRL_BASE,REG_SYS_DSTBY_INFO0)); + //a33 reg chk + Rtemp = (HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL) | 0x80000000); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL, Rtemp); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL, 0x80008400); + HalDelayUs(1000); + if ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL)&BIT15)==0){ + RRtemp = ((u8)HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL))+1; + } + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL) & 0xffff0000) | 0x00009400|RRtemp); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL, Rtemp); + DiagPrintf("a33 0x4 : 0x%x\n",RRtemp); + + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL, 0x80008500); + HalDelayUs(1000); + if ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL)&BIT15)==0){ + DiagPrintf("a33 0x5 before : 0x%x\n", HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL)); + RRtemp = ((u8)HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL))+1; + } + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL) & 0xffff0000) | 0x00009500|RRtemp); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL, Rtemp); + DiagPrintf("a33 0x5 : 0x%x\n",RRtemp); + + ChangeSoCPwrState(7,0xE8800); + } + } + + ////debug + if (PwrAdapter.SleepFlag) { + PwrAdapter.SleepFlag = 0; + HAL_WRITE32(SYSTEM_CTRL_BASE,0x234, 0xdddddddd); + DiagPrintf("0x234 before slp : %x\n", HAL_READ32(SYSTEM_CTRL_BASE,0x234)); + //cal 32k + //En32KCalibration(); + HalDelayUs(1000); + + ChangeSoCPwrState(5,0xb000); + //HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SOC_SYSON_DSTBY_INFO1, PwrAdapter.SleepFlag); + } + + if (0){//(HAL_READ8(SYSTEM_CTRL_BASE,REG_SOC_SYSON_DSTBY_INFO0) == 0x0) { + + IdleTemp++; + HalDelayUs(1000); + if (IdleTemp > 0xfffff){ + IdleTemp = 0; + __WFI(); + } + } + + if (0){ //((HAL_READ8(SYSTEM_CTRL_BASE,REG_SOC_SYSON_DSTBY_INFO0) == 0x0)) { + IdleTemp++; + HalDelayUs(1000); + if ((IdleTemp > 5000)||(HAL_READ8(SYSTEM_CTRL_BASE,REG_SYS_DSTBY_INFO0+1) == 0x12)){ + + DiagPrintf("\n"); + DiagPrintf("0x20080000 : 0x%x\n", HAL_READ32(0x20080000,0)); + DiagPrintf("0x20080004 : 0x%x\n", HAL_READ32(0x20080000,4)); + DiagPrintf("0x2009F404 : 0x%x\n", HAL_READ32(0x2009F400,4)); + DiagPrintf("0x2009F408 : 0x%x\n", HAL_READ32(0x2009F400,8)); + DiagPrintf("\n"); + + HAL_WRITE32(0x40000000,0x330,0x55559555);//0x55552a2a + //slp pg GPIOD GPIOE + HAL_WRITE32(0x40000000,0x334,0x55555555); + HAL_WRITE32(0x40000000,0x338,0x05555555); + HAL_WRITE32(0x40000000,0x33c,0x55555555); + HAL_WRITE32(0x40000000,0x340,0x55555555); + HAL_WRITE32(0x40000000,0x344,0x55555555); + HAL_WRITE32(0x40000000,0x320,0x0); + + HAL_WRITE32(0x20080000, 0, (HAL_READ32(0x20080000,0)+1)); + HAL_WRITE32(0x20080000, 4, (HAL_READ32(0x20080000,4)+1)); + HAL_WRITE32(0x2009F404, 0, (HAL_READ32(0x2009F400,4)+1)); + HAL_WRITE32(0x2009F408, 0, (HAL_READ32(0x2009F400,8)+1)); + HalDelayUs(10000); + ChangeSoCPwrState(SLPPG, 0xFFFFF); + } + } + //mem test + if (HAL_READ8(0x40000000,0xf1) == 0xaa) { + + CMDTemp[0] = 8; + SOCPSTestApp((VOID*)CMDTemp); + Rtemp = HAL_READ32(0x40080000,0x824); + Rtemp2 = Rtemp; + Rtemp2 = ((Rtemp2 & 0x807fffff) | 0x80000000); + HAL_WRITE32(0x40080000,0x824,Rtemp&0x7fffffff); + HAL_WRITE32(0x40080000,0x824,Rtemp2); + HAL_WRITE32(0x40080000,0x824,(Rtemp|0x80000000)); + Rtemp1 = HAL_READ32(0x40080000,0x820)&BIT8; + if (Rtemp1) { + Rtemp = HAL_READ32(0x40080000,0x8b8)&0xfffff; + } + else { + Rtemp = HAL_READ32(0x40080000,0x8a0)&0xfffff; + } + if(Rtemp== 0x00045678){ + Chktemp = 1; + } + + Chktemp &= SoCPSMEMTestChk(0x20010000,0x20000,0x12345678)&SoCPSMEMTestChk(0x200a0000,0x0FFE0,0x12345678) + &SoCPSMEMTestChk(0x1FFF4000,0x5000,0x12345678); + + if (Chktemp) { + HAL_WRITE32(0x40080000,0x4,(HAL_READ32(0x40080000,0x4)&0xFFFFFFF0)); + HAL_WRITE32(0x40000000,0xfc,(HAL_READ32(0x40000000,0xfc)+1)); + DiagPrintf("run %d times\n", HAL_READ32(0x40000000,0xfc)); + CMDTemp[0] = 1; + CMDTemp[1] = 5; + CMDTemp[2] = 0xff; + SOCPSTestApp((VOID*)CMDTemp); + } + else { + HAL_WRITE32(0x40000000,0xf0,0); + } + + } +} + +//30 +VOID +TimerHandleTset( + IN VOID *Data +) +{ + #if 0 + //static u32 temp = 0; + TIMER_ADAPTER TimerAdapter; + + TimerAdapter.IrqDis = OFF; + //TimerAdapter.IrqHandle = (IRQ_FUN) TimerHandleTset; + TimerAdapter.IrqHandle.IrqFun = (IRQ_FUN) TimerHandleTset; + //DBG_8195A("IrqFun : 0x%x\n", TimerAdapter.IrqHandle.IrqFun); + TimerAdapter.IrqHandle.IrqNum = TIMER2_7_IRQ; + TimerAdapter.IrqHandle.Priority = 0; + TimerAdapter.IrqHandle.Data = NULL; + TimerAdapter.TimerId = 2; + TimerAdapter.TimerIrqPriority = 0; + TimerAdapter.TimerLoadValueUs = 4000; + TimerAdapter.TimerMode = USER_DEFINED; + //temp++; + //DBG_8195A("time : 0x%x\n", temp); + + HalTimerOp.HalTimerInit((VOID*) &TimerAdapter); + #endif + DBG_8195A("<<< time out >>>\n"); +} + +extern IRQ_FUN Timer2To7VectorTable[6]; + +//30 +VOID +InitTimerTest( + //IN VOID *Data + VOID +) +{ + //[0]:type, [1]: timerID, [2]: timerMode, [3]: IrqDIS, [4]:period + TIMER_ADAPTER TimerAdapter; + //u32 *TestParameter; + + //TestParameter = (u32*) Data; + + TimerAdapter.IrqDis = 0; // off :0 + //TimerAdapter.IrqHandle = (IRQ_FUN) TimerHandleTset; + TimerAdapter.IrqHandle.IrqFun = (IRQ_FUN) TimerHandleTset; + //DBG_8195A("IrqFun : 0x%x\n", TimerAdapter.IrqHandle.IrqFun); + TimerAdapter.IrqHandle.IrqNum = TIMER2_7_IRQ; + TimerAdapter.IrqHandle.Priority = 0; + TimerAdapter.IrqHandle.Data = NULL; + TimerAdapter.TimerId = 5; + TimerAdapter.TimerIrqPriority = 0; + TimerAdapter.TimerLoadValueUs = 0x4EC14; + TimerAdapter.TimerMode = 1; // user_define :1 + + + //mer2To7VectorTable[0] = (IRQ_FUN) TimerHandleTset; + + HalTimerOp.HalTimerInit((VOID*) &TimerAdapter); + //mer2To7VectorTable[0] = (IRQ_FUN) TimerHandleTset; + + +} + +VOID +SOCPSTestApp( + VOID *Data +) +{ + u32 *TestParameter; + TestParameter = (u32*) Data; + unsigned int Rtemp, Rtemp1, Rtemp2;//, CalTemp32k, CalTempa33; + static u32 Read32k5 = 0; + static u32 Reada335 = 0; + DiagPrintf("TestParameter[0]: 0x%x\n",TestParameter[0]); + + switch (TestParameter[0]) { + + case 0: + DiagPrintf("SoC PWR Init wlan\n"); + Rtemp = HAL_READ32(SYSTEM_CTRL_BASE,0x214)|BIT16; + HAL_WRITE32(SYSTEM_CTRL_BASE,0x214,Rtemp); + + Rtemp = HAL_READ32(SYSTEM_CTRL_BASE,0x244)|BIT0; + HAL_WRITE32(SYSTEM_CTRL_BASE,0x244,Rtemp); + + Rtemp = HAL_READ32(SYSTEM_CTRL_BASE,0x210)|BIT2; + HAL_WRITE32(SYSTEM_CTRL_BASE,0x210,Rtemp); + + HalDelayUs(100); + + Rtemp = HAL_READ32(WIFI_REG_BASE,0x0)|BIT0; + HAL_WRITE32(WIFI_REG_BASE,0x0,Rtemp); + #if 0 + DiagPrintf("SoC PWR debug setting\n"); + Rtemp = 0; + HAL_WRITE32(SYSTEM_CTRL_BASE,0x33c,Rtemp); + + Rtemp = 0; + HAL_WRITE32(SYSTEM_CTRL_BASE,0x334,Rtemp); + + #if 0 + //en debug + Rtemp = 1;//HAL_READ32(SYSTEM_CTRL_BASE,REG_SOC_SYS_DEBUG_CTRL); + HAL_WRITE32(SYSTEM_CTRL_BASE,REG_SOC_SYS_DEBUG_CTRL,Rtemp); + + //debug port sel + Rtemp = 0xf0f10004;//HAL_READ32(SYSTEM_CTRL_BASE,REG_SOC_EFUSE_SYSCFG3)|0xf0000000; + HAL_WRITE32(SYSTEM_CTRL_BASE,REG_SOC_EFUSE_SYSCFG3, Rtemp); + #endif + + //cal 32k + //En32KCalibration(); + + //en gpio + GPIO_FCTRL(ON); + SLPCK_GPIO_CCTRL(ON); + ACTCK_GPIO_CCTRL(ON); + + //DiagPrintf("debug sel 0x2C : 0x%x\n", HAL_READ32(SYSTEM_CTRL_BASE,REG_SOC_EFUSE_SYSCFG3)); + //DiagPrintf("debug EN 0xA0 : 0x%x\n", HAL_READ32(SYSTEM_CTRL_BASE,REG_SOC_SYS_DEBUG_CTRL)); + //DiagPrintf("PULL CTRL 0x33c: 0x%x\n", HAL_READ32(SYSTEM_CTRL_BASE,0x33C)); + //DiagPrintf("debug port : 0x%x\n", HAL_READ32(SYSTEM_CTRL_BASE,REG_SOC_SYS_DEBUG_REG)); + DiagPrintf("0x90 : 0x%x\n", HAL_READ32(SYSTEM_CTRL_BASE,0x90)); + #endif + break; + + case 1: + DiagPrintf("SoC PWR TEST : Enter = %d, Period = %d\n",TestParameter[1], TestParameter[2]); + Rtemp = HalTimerOp.HalTimerReadCount(1); + //GPIO + //HAL_WRITE32(0x40001000,0x4,0x4000000); + + //SIC EN + //HAL_WRITE32(0x40000000,0x8,0x81000010); + //HAL_WRITE32(0x40000000,0xA4,0x00000001); + + //Wait for LogUart print out + while(1) { + HalDelayUs(100); + if (HAL_READ8(LOG_UART_REG_BASE,0x14)&BIT6){ + break; + } + } + + #if 0 + + HAL_WRITE32(0x40000000,0x330,0x55559555);//0x55552a2a + //slp pg GPIOD GPIOE + HAL_WRITE32(0x40000000,0x334,0x55555555); + HAL_WRITE32(0x40000000,0x338,0x05555555); + HAL_WRITE32(0x40000000,0x33c,0x55555555); + HAL_WRITE32(0x40000000,0x340,0x55555555); + HAL_WRITE32(0x40000000,0x344,0x55555555); + HAL_WRITE32(0x40000000,0x320,0x0); + #endif + + ChangeSoCPwrState(TestParameter[1], TestParameter[2]); + + Rtemp2 = HalTimerOp.HalTimerReadCount(1); + DiagPrintf("before : %x\n", Rtemp); + DiagPrintf("after : %x\n", Rtemp2); + DiagPrintf("period : %d\n", Rtemp-Rtemp2); + DiagPrintf("0x90 : 0x%x\n", HAL_READ32(SYSTEM_CTRL_BASE,0x90)); + break; + + case 2: + #if 1 + if (HAL_READ32(0x40000000,0xf8) == 0x11) { + HAL_WRITE32(0x40000000,0x320,0x7ff); + } + HAL_WRITE32(0x40000000,0x320,0x7ff); + HAL_WRITE32(0x40000000,0x330,0x5565A555); + //slp pg GPIOD GPIOE + HAL_WRITE32(0x40000000,0x334,0x55555555); + HAL_WRITE32(0x40000000,0x338,0x05555555); + HAL_WRITE32(0x40000000,0x33c,0x55555555); + HAL_WRITE32(0x40000000,0x340,0x55555555); + HAL_WRITE32(0x40000000,0x344,0x55555555); + HAL_WRITE32(0x40000000,0x348,0x55555555); + HAL_WRITE32(0x40000000,0x320,0x0); + + if (HAL_READ32(0x40000000,0xf4) == 0x11) { + HAL_WRITE32(0x40000000,0x8,0x80000011); + } + HAL_WRITE32(0x40000000,0x8,0x80000011); + #endif + HAL_WRITE32(SYSTEM_CTRL_BASE, 0X120, TestParameter[1]); + HAL_WRITE32(SYSTEM_CTRL_BASE, 0X124, TestParameter[2]); + + if (TestParameter[4] == 0xff) { + //SIC EN + HAL_WRITE32(0x40000000,0x8,0x81000010); + HAL_WRITE32(0x40000000,0xA4,0x00000001); + } + + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_PWRMGT_CTRL, TestParameter[3]); + #if 0 + //clear isr + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SOC_SYS_ANA_TIM_CTRL)& 0xffff7fff)); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SOC_SYS_ANA_TIM_CTRL, Rtemp); + + Rtemp = HAL_READ32(SYSTEM_CTRL_BASE, REG_SOC_SYSON_SLP_WAKE_EVENT_STATUS0); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SOC_SYSON_SLP_WAKE_EVENT_STATUS0, Rtemp); + #endif + break; + + case 3: + HAL_WRITE32(SYSTEM_CTRL_BASE, 0X120, 0x74000e00); + HAL_WRITE32(SYSTEM_CTRL_BASE, 0X124, 2); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_PWRMGT_CTRL, TestParameter[1]); + #if 0 + { + u32 targetunit = 0; + + //cal a33 + Rtemp = CLKCal(A33CK); + + targetunit = (TestParameter[1]/3*250)/Rtemp*50; + if (targetunit > 0x7fffff) { + targetunit = 0x7fffff; + } + + DBG_8195A("targeunit = 0x%08x\n",targetunit); + + targetunit = (50*TestParameter[1]/Rtemp)*250/3; + if (targetunit > 0x7fffff) { + targetunit = 0x7fffff; + } + + DBG_8195A("targeunit = 0x%08x\n",targetunit); + + + } + #endif + #if 0 + //cal a33 + Rtemp = CLKCal(A33CK); + Rtemp1 = (((((TestParameter[1] & 0x0FFFFFFF)<<4)/Rtemp)*20)-1); + DiagPrintf("Rtemp : 0x%x\n", Rtemp); + DiagPrintf("Vendor 0xA0 : 0x%x\n", HAL_READ32(VENDOR_REG_BASE,0xA0)); + DiagPrintf("way1 : 0x%x\n", Rtemp1); + Rtemp2 = (((((TestParameter[1] & 0x0FFFFFFF))/Rtemp)*320)-1); + DiagPrintf("way2 : 0x%x\n", Rtemp2); + + Rtemp = Rtemp1/6; + DiagPrintf("Rtemp1 : %d\n", Rtemp); + Rtemp = 0x7fffffff; + DiagPrintf("Rtemp1 : %d\n", Rtemp); + #endif + break; + + case 4: + DiagPrintf("set timer\n"); + SetA33Timer(TestParameter[1]); + Rtemp = HalTimerOp.HalTimerReadCount(1); + DiagPrintf("32k timer : 0x%x\n", Rtemp); + break; + + case 5: + DiagPrintf("read timer\n"); + Reada335 = HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CAL_CTRL); + DiagPrintf("a33 timer : 0x%x\n", Reada335); + Read32k5 = HalTimerOp.HalTimerReadCount(1); + DiagPrintf("32k timer : 0x%x\n", Read32k5); + break; + + case 6: + #if 0 + DiagPrintf("interval cal\n"); + Rtemp1 = HAL_READ32(SYSTEM_CTRL_BASE, REG_SOC_SYS_DSLP_TIM_CAL_CTRL); + Rtemp2 = HalTimerOp.HalTimerReadCount(1); + DiagPrintf("Reada335 : 0x%x\n", Reada335); + DiagPrintf("Read32k5 : 0x%x\n", Read32k5); + DiagPrintf("a33 timer : 0x%x\n", Rtemp1); + DiagPrintf("32k timer : 0x%x\n", Rtemp2); + CalTemp32k = (Read32k5 - Rtemp2); + CalTempa33 = (((Reada335 - Rtemp1)*((HAL_READ32(VENDOR_REG_BASE, REG_VDR_ANACK_CAL_CTRL) & 0x3FFF)+1))/5); + DiagPrintf("a33 timer interval : 0x%x\n", CalTempa33); + DiagPrintf("32k timer interval : 0x%x\n", CalTemp32k); + Read32k5 = Rtemp2; + Reada335 = Rtemp1; + #endif + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_ANA_TIM_CTRL) & 0xffff7000) | 0x7ff); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_ANA_TIM_CTRL, Rtemp); + + //0x4000_0090[15] = 1'b1 => Enable timer + Rtemp = HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_ANA_TIM_CTRL) | 0x00008000; + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_ANA_TIM_CTRL, Rtemp); + + Rtemp = 0x00000001; + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_SLP_WAKE_EVENT_MSK0, Rtemp); +#if 0 + HAL_WRITE32(0x40000000,0x330,0x55559555);//0x55552a2a + HAL_WRITE32(0x40000000,0x2C0,0x100001); + //slp pg GPIOD GPIOE + HAL_WRITE32(0x40000000,0x334,0x55555555); + HAL_WRITE32(0x40000000,0x338,0x05555555); + HAL_WRITE32(0x40000000,0x33c,0x55555555); + HAL_WRITE32(0x40000000,0x340,0x55555555); + HAL_WRITE32(0x40000000,0x344,0x55555555); + HAL_WRITE32(0x40000000,0x320,0x0); +#endif + HAL_WRITE32(SYSTEM_CTRL_BASE, 0X120, TestParameter[1]); + HAL_WRITE32(SYSTEM_CTRL_BASE, 0X124, TestParameter[2]); + + if (TestParameter[4] == 0xff) { + //SIC EN + HAL_WRITE32(0x40000000,0x8,0x81000010); + HAL_WRITE32(0x40000000,0xA4,0x00000001); + } + + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_PWRMGT_CTRL, TestParameter[3]); + break; + + case 7: + { + u32 Rtemp = 0; + u32 UTemp = 0; + u32 MaxTemp = 0; + u32 Reada335 = 0; + + //2 Deep Sleep mode: + //3 2.1 Set TU timer timescale + + //3 2.2 Configure deep sleep timer: + //2.2.1 Enable REGU access interface 0x4000_0094[31] = 1 + Rtemp = (HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL) | 0x80000000); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL, Rtemp); + + DiagPrintf("SDuration : 0x%x\n", TestParameter[1]); + + //3 2.2.2 Initialize deep sleep counter + //2.2.2.0 0x4000_0094[15:0] = 16'hD300 => Disable deep sleep counter + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL) & 0xffff0000) | 0x0000D300); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL, Rtemp); + //2.2.2.1 0x4000_0094[15:0] = 16'h9008 => set counter[7:0] + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL) & 0xffff0000) | 0x00009000 | ((u8)TestParameter[1])); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL, Rtemp); + + //2.2.2.2 0x4000_0094[15:0] = 16'h9100 => set counter[15:8] + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL) & 0xffff0000) | 0x00009100 | ((u8)(TestParameter[1] >> 8))); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL, Rtemp); + + //2.2.2.3 0x4000_0094[15:0] = 16'h9200 => set counter[22:16] + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL) & 0xffff0000) | 0x00009200 | ((u8)(TestParameter[1] >> 16))); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL, Rtemp); + + //2.2.2.4 0x4000_0094[15:0] = 16'hD380 => Enable deep sleep counter + Rtemp = ((HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL) & 0xffff0000) | 0x0000D380); + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CTRL, Rtemp); + + HalDelayUs(1000); + Reada335 = HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSLP_TIM_CAL_CTRL); + DiagPrintf("a33 timer : 0x%x\n", Reada335); + + HalDelayUs(8000); + + //3 2.2.3 + //2.3 Enable low power mode: 0x4000_0118[0] = 1'b1; + Rtemp = 0x00000001;//HAL_READ32(SYSTEM_CTRL_BASE, REG_SYSON_PWRMGT_CTRL) | 0x00000001; + HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_PWRMGT_CTRL, Rtemp); + + //2.4 Wait CHIP enter deep sleep mode + //2.5 Wait deep sleep counter timeout + //__WFI(); + + DiagPrintf("YOU CAN'T SEE ME ~~~~!!!!!!!!!!!!!!!!!!!~~~~~~~~~~~~~~~!!!!!!!!!!"); + } + break; + + case 8: + DiagPrintf("enable wifi\n"); + + Rtemp = HAL_READ32(0x40000000,0x214)|0x10000; + HAL_WRITE32(0x40000000,0x214,Rtemp); + Rtemp = HAL_READ32(0x40000000,0x244)|0x1; + HAL_WRITE32(0x40000000,0x244,Rtemp); + Rtemp = HAL_READ32(0x40000000,0x210)|0x4; + HAL_WRITE32(0x40000000,0x210,Rtemp); + + Rtemp = HAL_READ32(0x40080000,0x0)&0xFFFFFFDF; + HAL_WRITE32(0x40080000,0x0,Rtemp); + Rtemp = HAL_READ32(0x40080000,0x4)|0x1; + HAL_WRITE32(0x40080000,0x4,Rtemp); + Rtemp = HAL_READ32(0x40080000,0x20)|0x1; + HAL_WRITE32(0x40080000,0x20,Rtemp); + while( (HAL_READ32(0x40080000,0x20)&BIT0)!=0); + + Rtemp = HAL_READ32(0x40080000,0x4)|0x30000; + HAL_WRITE32(0x40080000,0x4,Rtemp); + Rtemp = HAL_READ32(0x40080000,0x4)|0x7000000; + HAL_WRITE32(0x40080000,0x4,Rtemp); + Rtemp = HAL_READ32(0x40080000,0x50)&0xFFFFFF00; + HAL_WRITE32(0x40080000,0x50,Rtemp); + break; + + case 9: + #if 0 + PwrAdapter.CPURegbackup[13] = 0x12340; + PwrAdapter.CPUPSP = PwrAdapter.CPURegbackup[13]; + + asm volatile + ( + + " ldr r3, pxCPUPSPConst23 \n" /* Restore the context. */ + "MOV %0, r3\n" + " ldr r1, [r3] \n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ + "MOV %1, r1\n" + " ldr r0, [r1] \n" + "MOV %2, r0\n" + " .align 2 \n" + "pxCPUPSPConst23: .word PwrAdapter.CPUPSP \n" + :"=r"(PwrAdapter.CPURegbackup[0]),"=r"(PwrAdapter.CPURegbackup[1]),"=r"(PwrAdapter.CPURegbackup[2]),"=r"(PwrAdapter.CPURegbackup[3]) + :"r"(PwrAdapter.CPUPSP) + :"memory" + ); + PrintCPU(); + #endif + break; + + case 10: + Rtemp = HAL_READ32(0x40080000,0x824); + Rtemp2 = Rtemp; + Rtemp2 = Rtemp2 & 0x807fffff | (TestParameter[1]<<23) | 0x80000000; + HAL_WRITE32(0x40080000,0x824,Rtemp&0x7fffffff); + HAL_WRITE32(0x40080000,0x824,Rtemp2); + HAL_WRITE32(0x40080000,0x824,Rtemp|0x80000000); + Rtemp1 = HAL_READ32(0x40080000,0x820)&BIT8; + if (Rtemp1) { + Rtemp = HAL_READ32(0x40080000,0x8b8)&0xfffff; + } + else { + Rtemp = HAL_READ32(0x40080000,0x8a0)&0xfffff; + } + DiagPrintf("rf offset: 0x%x, 0x%x\n", TestParameter[1], Rtemp); + break; + + case 11://addr [1]; date [2] + TestParameter[1] &= 0x3f; + Rtemp = (TestParameter[1]<<20)|(TestParameter[2]&0x000fffff)&0x0fffffff; + HAL_WRITE32(0x40080000,0x840,Rtemp); + + //SoCPWRIdleTaskHandle(); + break; + + case 12: + SoCPSMEMTestInit(TestParameter[1],TestParameter[2],TestParameter[3]); + break; + + case 13: + Rtemp = SoCPSMEMTestChk(TestParameter[1],TestParameter[2],TestParameter[3]); + break; + + case 14: + HAL_WRITE32(0x40000000,TestParameter[1],0x12345678); + DiagPrintf("w32: 0x%x\n", HAL_READ32(0x40000000,TestParameter[1])); + HAL_WRITE32(0x40000000,TestParameter[1],0); + HAL_WRITE16(0x40000000,TestParameter[1],0x1234); + DiagPrintf("w16: 0x%x\n", HAL_READ32(0x40000000,TestParameter[1])); + HAL_WRITE32(0x40000000,TestParameter[1],0); + HAL_WRITE8(0x40000000,TestParameter[1],0x12); + DiagPrintf("w8: 0x%x\n", HAL_READ32(0x40000000,TestParameter[1])); + HAL_WRITE32(0x40000000,TestParameter[1],0x12345678); + DiagPrintf("R32: 0x%x\n", HAL_READ32(0x40000000,TestParameter[1])); + DiagPrintf("R16: 0x%x\n", HAL_READ16(0x40000000,TestParameter[1])); + DiagPrintf("R8: 0x%x\n", HAL_READ8(0x40000000,TestParameter[1])); + Rtemp = ((HAL_READ32(0x40000000,0xf4))?1:0); + DiagPrintf("R: 0x%x\n", Rtemp); + break; + + case 15: + asm volatile + ( + "MRS R0, BASEPRI\n" + "MOV %0, R0\n" + :"=r"(Rtemp) + ::"memory" + ); + DiagPrintf("basepri: 0x%x\n", Rtemp); + break; + case 16: + HalDelayUs(10000000); + DSleep_GPIO(); + break; + case 17: + DSleep_Timer(TestParameter[1]); + break; + case 18: + DiagPrintf("WDG CAL\n"); + { + u8 CountId; + u16 DivFactor; + u32 CountTemp; + u32 CountProcess = 0; + u32 DivFacProcess = 0; + u32 MinPeriodTemp = 0xFFFFFFFF; + u32 PeriodTemp = 0; + + DBG_8195A(" Period = %d\n", TestParameter[1]); + + for (CountId = 0; CountId < 12; CountId++) { + CountTemp = ((0x00000001 << (CountId+1))-1); + DivFactor = (u16)((100*TestParameter[1])/(CountTemp*3)); + + if (DivFactor > 0) { + PeriodTemp = 3*(DivFactor+1)*CountTemp; + DBG_8195A("PeriodTemp = %d\n", PeriodTemp); + if ((100*TestParameter[1]) PeriodTemp) { + MinPeriodTemp = PeriodTemp; + CountProcess = CountTemp; + DivFacProcess = DivFactor; + } + } + } + } + DBG_8195A("MinPeriodTemp = %d\n", MinPeriodTemp); + DBG_8195A("WdgScalar = 0x%08x\n", DivFacProcess); + DBG_8195A("WdgCunLimit = 0x%08x\n", CountProcess); + } + break; + + case 19: + DBG_8195A("DeepStandby~~~\n"); + DeepStandby(TestParameter[1],TestParameter[2],TestParameter[3]); + break; + + case 20: + DBG_8195A("SleepCG~~~\n"); + if (TestParameter[1]&BIT1){ + InitTimerTest(); + } + SleepCG(TestParameter[1],TestParameter[2]); + break; + + default: + break; + } + + +} +#endif //CONFIG_SOC_PS_VERIFY +#endif //CONFIG_SOC_PS_MODULE + diff --git a/component/soc/realtek/8195a/fwlib/src/hal_ssi.c b/component/soc/realtek/8195a/fwlib/src/hal_ssi.c new file mode 100644 index 0000000..6bfe332 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/src/hal_ssi.c @@ -0,0 +1,281 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#include "rtl8195a.h" +#include "hal_ssi.h" + +const HAL_GDMA_CHNL Ssi2_TX_GDMA_Chnl_Option[] = { + {0,4,GDMA0_CHANNEL4_IRQ,0}, + {0,5,GDMA0_CHANNEL5_IRQ,0}, + {0,3,GDMA0_CHANNEL3_IRQ,0}, + {0,0,GDMA0_CHANNEL0_IRQ,0}, + {0,1,GDMA0_CHANNEL1_IRQ,0}, + {0,2,GDMA0_CHANNEL2_IRQ,0}, + + {0xff,0,0,0} // end +}; + +const HAL_GDMA_CHNL Ssi2_RX_GDMA_Chnl_Option[] = { + {1,4,GDMA1_CHANNEL4_IRQ,0}, + {1,5,GDMA1_CHANNEL5_IRQ,0}, + {1,3,GDMA1_CHANNEL3_IRQ,0}, + {1,0,GDMA1_CHANNEL0_IRQ,0}, + {1,1,GDMA1_CHANNEL1_IRQ,0}, + {1,2,GDMA1_CHANNEL2_IRQ,0}, + + {0xff,0,0,0} // end +}; + +//TODO: Load default Setting: It should be loaded from external setting file. +const DW_SSI_DEFAULT_SETTING SpiDefaultSetting = +{ + .RxCompCallback = NULL, + .RxCompCbPara = NULL, + .RxData = NULL, + .TxCompCallback = NULL, + .TxCompCbPara = NULL, + .TxData = NULL, + .DmaRxDataLevel = 7, // RX FIFO stored bytes > (DMARDLR(7) + 1) then trigger DMA transfer + .DmaTxDataLevel = 48, // TX FIFO free space > (FIFO_SPACE(64)-DMATDLR(48)) then trigger DMA transfer + .InterruptPriority = 0x20, + .RxLength = 0, + .RxLengthRemainder = 0, + .RxThresholdLevel = 7, // if number of entries in th RX FIFO >= (RxThresholdLevel+1), RX interrupt asserted + .TxLength = 0, + .TxThresholdLevel = 8, // if number of entries in th TX FIFO <= TxThresholdLevel, TX interrupt asserted + .SlaveSelectEnable = 0, + .ClockDivider = SSI_CLK_SPI0_2/1000000, // SCLK=1M + .DataFrameNumber = 0, + .ControlFrameSize = CFS_1_BIT, + .DataFrameFormat = FRF_MOTOROLA_SPI, + .DataFrameSize = DFS_8_BITS, + .DmaControl = 0, // default DMA is disable + .InterruptMask = 0x0, + .MicrowireDirection = MW_DIRECTION_MASTER_TO_SLAVE, + .MicrowireHandshaking = MW_HANDSHAKE_DISABLE, + .MicrowireTransferMode = MW_TMOD_NONSEQUENTIAL, + .SclkPhase = SCPH_TOGGLES_AT_START, + .SclkPolarity = SCPOL_INACTIVE_IS_HIGH, + .SlaveOutputEnable = SLV_TXD_ENABLE, // Slave + .TransferMode = TMOD_TR, + .TransferMechanism = SSI_DTM_INTERRUPT +}; + +extern HAL_Status HalSsiInitRtl8195a_Patch(VOID *Adaptor); +extern HAL_Status HalSsiPinmuxEnableRtl8195a_Patch(VOID *Adaptor); +extern HAL_Status HalSsiPinmuxDisableRtl8195a(VOID *Adaptor); +extern HAL_Status HalSsiIntReadRtl8195a(VOID *Adapter, VOID *RxData, u32 Length); +extern HAL_Status HalSsiIntWriteRtl8195a(VOID *Adapter, u8 *pTxData, u32 Length); +extern VOID HalSsiSetSclkRtl8195a(VOID *Adapter, u32 ClkRate); +#ifdef CONFIG_GDMA_EN +extern VOID HalSsiDmaInitRtl8195a(VOID *Adapter); +#endif + +VOID HalSsiOpInit(VOID *Adaptor) +{ + PHAL_SSI_OP pHalSsiOp = (PHAL_SSI_OP) Adaptor; + +// pHalSsiOp->HalSsiPinmuxEnable = HalSsiPinmuxEnableRtl8195a; + pHalSsiOp->HalSsiPinmuxEnable = HalSsiPinmuxEnableRtl8195a_Patch; + pHalSsiOp->HalSsiPinmuxDisable = HalSsiPinmuxDisableRtl8195a; + pHalSsiOp->HalSsiEnable = HalSsiEnableRtl8195a; + pHalSsiOp->HalSsiDisable = HalSsiDisableRtl8195a; +// pHalSsiOp->HalSsiInit = HalSsiInitRtl8195a; + pHalSsiOp->HalSsiInit = HalSsiInitRtl8195a_Patch; + pHalSsiOp->HalSsiSetSclkPolarity = HalSsiSetSclkPolarityRtl8195a; + pHalSsiOp->HalSsiSetSclkPhase = HalSsiSetSclkPhaseRtl8195a; + pHalSsiOp->HalSsiWrite = HalSsiWriteRtl8195a; + pHalSsiOp->HalSsiRead = HalSsiReadRtl8195a; + pHalSsiOp->HalSsiGetRxFifoLevel = HalSsiGetRxFifoLevelRtl8195a; + pHalSsiOp->HalSsiGetTxFifoLevel = HalSsiGetTxFifoLevelRtl8195a; + pHalSsiOp->HalSsiGetStatus = HalSsiGetStatusRtl8195a; + pHalSsiOp->HalSsiGetInterruptStatus = HalSsiGetInterruptStatusRtl8195a; + pHalSsiOp->HalSsiLoadSetting = HalSsiLoadSettingRtl8195a; + pHalSsiOp->HalSsiSetInterruptMask = HalSsiSetInterruptMaskRtl8195a; + pHalSsiOp->HalSsiGetInterruptMask = HalSsiGetInterruptMaskRtl8195a; + pHalSsiOp->HalSsiSetDeviceRole = HalSsiSetDeviceRoleRtl8195a; + pHalSsiOp->HalSsiWriteable = HalSsiWriteableRtl8195a; + pHalSsiOp->HalSsiReadable = HalSsiReadableRtl8195a; + pHalSsiOp->HalSsiBusy = HalSsiBusyRtl8195a; + pHalSsiOp->HalSsiInterruptEnable = HalSsiInterruptEnableRtl8195a; + pHalSsiOp->HalSsiInterruptDisable = HalSsiInterruptDisableRtl8195a; +// pHalSsiOp->HalSsiReadInterrupt = HalSsiReadInterruptRtl8195a; + pHalSsiOp->HalSsiReadInterrupt = HalSsiIntReadRtl8195a; + pHalSsiOp->HalSsiSetRxFifoThresholdLevel = HalSsiSetRxFifoThresholdLevelRtl8195a; + pHalSsiOp->HalSsiSetTxFifoThresholdLevel = HalSsiSetTxFifoThresholdLevelRtl8195a; +// pHalSsiOp->HalSsiWriteInterrupt = HalSsiWriteInterruptRtl8195a; + pHalSsiOp->HalSsiWriteInterrupt = HalSsiIntWriteRtl8195a; + pHalSsiOp->HalSsiGetRawInterruptStatus = HalSsiGetRawInterruptStatusRtl8195a; + pHalSsiOp->HalSsiGetSlaveEnableRegister = HalSsiGetSlaveEnableRegisterRtl8195a; + pHalSsiOp->HalSsiSetSlaveEnableRegister = HalSsiSetSlaveEnableRegisterRtl8195a; +} + + +#ifdef CONFIG_GDMA_EN + +HAL_Status +HalSsiTxGdmaInit( + IN PHAL_SSI_OP pHalSsiOp, + IN PHAL_SSI_ADAPTOR pHalSsiAdapter +) +{ + PHAL_GDMA_ADAPTER pHalGdmaAdapter; + PSSI_DMA_CONFIG pDmaConfig; + u8 gdma_idx; + u8 gdma_chnum; + HAL_GDMA_CHNL *pgdma_chnl; + PHAL_GDMA_OP pHalGdmaOp; + + if ((NULL == pHalSsiOp) || (NULL == pHalSsiAdapter)) { + return HAL_ERR_PARA; + } + + pDmaConfig = &pHalSsiAdapter->DmaConfig; + + // Load default setting + HalSsiTxGdmaLoadDefRtl8195a((void*)pHalSsiAdapter); + + // Start to patch the default setting + pHalGdmaAdapter = (PHAL_GDMA_ADAPTER)pDmaConfig->pTxHalGdmaAdapter; + if (HalGdmaChnlRegister(pHalGdmaAdapter->GdmaIndex, pHalGdmaAdapter->ChNum) != HAL_OK) { + // The default GDMA Channel is not available, try others + if (pHalSsiAdapter->Index == 2) { + // SSI2 TX Only can use GDMA 0 + pgdma_chnl = HalGdmaChnlAlloc((HAL_GDMA_CHNL*)Ssi2_TX_GDMA_Chnl_Option); + } + else { + pgdma_chnl = HalGdmaChnlAlloc(NULL); + } + + if (pgdma_chnl == NULL) { + // No Available DMA channel + return HAL_BUSY; + } + else { + pHalGdmaAdapter->GdmaIndex = pgdma_chnl->GdmaIndx; + pHalGdmaAdapter->ChNum = pgdma_chnl->GdmaChnl; + pHalGdmaAdapter->ChEn = 0x0101 << pgdma_chnl->GdmaChnl; + pDmaConfig->TxGdmaIrqHandle.IrqNum = pgdma_chnl->IrqNum; + } + } + + DBG_SSI_INFO("HalSsiTxGdmaInit: GdmaIndex=%d ChNum=%d \r\n", pHalGdmaAdapter->GdmaIndex, pHalGdmaAdapter->ChNum); + pHalGdmaOp = (PHAL_GDMA_OP)pDmaConfig->pHalGdmaOp; + pHalGdmaOp->HalGdmaOnOff((VOID*)(pHalGdmaAdapter)); + pHalGdmaOp->HalGdmaChIsrEnAndDis((VOID*)(pHalGdmaAdapter)); + + HalSsiDmaInit(pHalSsiAdapter); + InterruptRegister(&pDmaConfig->TxGdmaIrqHandle); + InterruptEn(&pDmaConfig->TxGdmaIrqHandle); + + return HAL_OK; +} + +VOID +HalSsiTxGdmaDeInit( + IN PHAL_SSI_ADAPTOR pHalSsiAdapter +) +{ + PSSI_DMA_CONFIG pDmaConfig; + PHAL_GDMA_ADAPTER pHalGdmaAdapter; + HAL_GDMA_CHNL GdmaChnl; + + if (NULL == pHalSsiAdapter) { + return; + } + + pDmaConfig = &pHalSsiAdapter->DmaConfig; + + pHalGdmaAdapter = (PHAL_GDMA_ADAPTER)pDmaConfig->pTxHalGdmaAdapter; + GdmaChnl.GdmaIndx = pHalGdmaAdapter->GdmaIndex; + GdmaChnl.GdmaChnl = pHalGdmaAdapter->ChNum; + GdmaChnl.IrqNum = pDmaConfig->TxGdmaIrqHandle.IrqNum; + HalGdmaChnlFree(&GdmaChnl); +} + + +HAL_Status +HalSsiRxGdmaInit( + IN PHAL_SSI_OP pHalSsiOp, + IN PHAL_SSI_ADAPTOR pHalSsiAdapter +) +{ + PHAL_GDMA_ADAPTER pHalGdmaAdapter; + PSSI_DMA_CONFIG pDmaConfig; + HAL_GDMA_CHNL *pgdma_chnl; + PHAL_GDMA_OP pHalGdmaOp; + + if ((NULL == pHalSsiOp) || (NULL == pHalSsiAdapter)) { + return HAL_ERR_PARA; + } + + pDmaConfig = &pHalSsiAdapter->DmaConfig; + // Load default setting + HalSsiRxGdmaLoadDefRtl8195a((void*)pHalSsiAdapter); + + // Start to patch the default setting + pHalGdmaAdapter = (PHAL_GDMA_ADAPTER)pDmaConfig->pRxHalGdmaAdapter; + if (HalGdmaChnlRegister(pHalGdmaAdapter->GdmaIndex, pHalGdmaAdapter->ChNum) != HAL_OK) { + // The default GDMA Channel is not available, try others + if (pHalSsiAdapter->Index == 2) { + // SSI2 RX Only can use GDMA 1 + pgdma_chnl = HalGdmaChnlAlloc((HAL_GDMA_CHNL*)Ssi2_RX_GDMA_Chnl_Option); + } + else { + pgdma_chnl = HalGdmaChnlAlloc(NULL); + } + + if (pgdma_chnl == NULL) { + // No Available DMA channel + return HAL_BUSY; + } + else { + pHalGdmaAdapter->GdmaIndex = pgdma_chnl->GdmaIndx; + pHalGdmaAdapter->ChNum = pgdma_chnl->GdmaChnl; + pHalGdmaAdapter->ChEn = 0x0101 << pgdma_chnl->GdmaChnl; + pDmaConfig->RxGdmaIrqHandle.IrqNum = pgdma_chnl->IrqNum; + } + } + + DBG_SSI_INFO("HalSsiRxGdmaInit: GdmaIndex=%d ChNum=%d \r\n", pHalGdmaAdapter->GdmaIndex, pHalGdmaAdapter->ChNum); + pHalGdmaOp = (PHAL_GDMA_OP)pDmaConfig->pHalGdmaOp; + pHalGdmaOp->HalGdmaOnOff((VOID*)(pHalGdmaAdapter)); + pHalGdmaOp->HalGdmaChIsrEnAndDis((VOID*)(pHalGdmaAdapter)); + + HalSsiDmaInit(pHalSsiAdapter); + InterruptRegister(&pDmaConfig->RxGdmaIrqHandle); + InterruptEn(&pDmaConfig->RxGdmaIrqHandle); + + return HAL_OK; +} + +VOID +HalSsiRxGdmaDeInit( + IN PHAL_SSI_ADAPTOR pHalSsiAdapter +) +{ + PSSI_DMA_CONFIG pDmaConfig; + PHAL_GDMA_ADAPTER pHalGdmaAdapter; + HAL_GDMA_CHNL GdmaChnl; + + if (NULL == pHalSsiAdapter) { + return; + } + + pDmaConfig = &pHalSsiAdapter->DmaConfig; + + pHalGdmaAdapter = (PHAL_GDMA_ADAPTER)pDmaConfig->pRxHalGdmaAdapter; + GdmaChnl.GdmaIndx = pHalGdmaAdapter->GdmaIndex; + GdmaChnl.GdmaChnl = pHalGdmaAdapter->ChNum; + GdmaChnl.IrqNum = pDmaConfig->RxGdmaIrqHandle.IrqNum; + HalGdmaChnlFree(&GdmaChnl); +} + +#endif // end of "#ifdef CONFIG_GDMA_EN" + diff --git a/component/soc/realtek/8195a/fwlib/src/hal_timer.c b/component/soc/realtek/8195a/fwlib/src/hal_timer.c new file mode 100644 index 0000000..617b593 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/src/hal_timer.c @@ -0,0 +1,32 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + + +#include "rtl8195a.h" + +VOID +HalTimerOpInit_Patch( + IN VOID *Data +) +{ + PHAL_TIMER_OP pHalTimerOp = (PHAL_TIMER_OP) Data; + + pHalTimerOp->HalGetTimerId = HalGetTimerIdRtl8195a; + pHalTimerOp->HalTimerInit = (BOOL (*)(void*))HalTimerInitRtl8195a_Patch; +#ifdef CONFIG_CHIP_C_CUT + pHalTimerOp->HalTimerReadCount = HalTimerReadCountRtl8195aV02; +#else + pHalTimerOp->HalTimerReadCount = HalTimerReadCountRtl8195a_Patch; +#endif + pHalTimerOp->HalTimerIrqClear = HalTimerIrqClearRtl8195a; + pHalTimerOp->HalTimerDis = HalTimerDisRtl8195a_Patch; + pHalTimerOp->HalTimerEn = HalTimerEnRtl8195a_Patch; + pHalTimerOp->HalTimerDumpReg = HalTimerDumpRegRtl8195a; +} + diff --git a/component/soc/realtek/8195a/fwlib/src/hal_uart.c b/component/soc/realtek/8195a/fwlib/src/hal_uart.c new file mode 100644 index 0000000..aac0619 --- /dev/null +++ b/component/soc/realtek/8195a/fwlib/src/hal_uart.c @@ -0,0 +1,332 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + + +#include "rtl8195a.h" +#include "rtl8195a_uart.h" +#include "hal_uart.h" +#include "hal_gdma.h" + +extern u32 _UartIrqHandle(VOID *Data); + +#if (CONFIG_CHIP_A_CUT | CONFIG_CHIP_B_CUT) +HAL_Status +HalRuartInitRtl8195a_Patch( + IN VOID *Data ///< RUART Adapter + ); +#else +extern _LONG_CALL_ HAL_Status +HalRuartInitRtl8195aV02( + IN VOID *Data ///< RUART Adapter + ); +#endif + +const HAL_GDMA_CHNL Uart2_TX_GDMA_Chnl_Option[] = { + {0,0,GDMA0_CHANNEL0_IRQ,0}, + {0,1,GDMA0_CHANNEL1_IRQ,0}, + {0,2,GDMA0_CHANNEL2_IRQ,0}, + {0,3,GDMA0_CHANNEL3_IRQ,0}, + {0,4,GDMA0_CHANNEL4_IRQ,0}, + {0,5,GDMA0_CHANNEL5_IRQ,0}, + + {0xff,0,0,0} // end +}; + +const HAL_GDMA_CHNL Uart2_RX_GDMA_Chnl_Option[] = { + {1,0,GDMA1_CHANNEL0_IRQ,0}, + {1,1,GDMA1_CHANNEL1_IRQ,0}, + {1,2,GDMA1_CHANNEL2_IRQ,0}, + {1,3,GDMA1_CHANNEL3_IRQ,0}, + {1,4,GDMA1_CHANNEL4_IRQ,0}, + {1,5,GDMA1_CHANNEL5_IRQ,0}, + + {0xff,0,0,0} // end +}; + +VOID +HalRuartOpInit( + IN VOID *Data +) +{ + PHAL_RUART_OP pHalRuartOp = (PHAL_RUART_OP) Data; + + pHalRuartOp->HalRuartAdapterLoadDef = HalRuartAdapterLoadDefRtl8195a; + pHalRuartOp->HalRuartTxGdmaLoadDef = HalRuartTxGdmaLoadDefRtl8195a; + pHalRuartOp->HalRuartRxGdmaLoadDef = HalRuartRxGdmaLoadDefRtl8195a; + pHalRuartOp->HalRuartResetRxFifo = HalRuartResetRxFifoRtl8195a; +#if (CONFIG_CHIP_A_CUT | CONFIG_CHIP_B_CUT) + pHalRuartOp->HalRuartInit = HalRuartInitRtl8195a_Patch; // Hardware Init ROM code patch +#else + pHalRuartOp->HalRuartInit = HalRuartInitRtl8195aV02; // Hardware Init +#endif + pHalRuartOp->HalRuartDeInit = HalRuartDeInitRtl8195a; // Hardware Init + pHalRuartOp->HalRuartPutC = HalRuartPutCRtl8195a; // Send a byte + pHalRuartOp->HalRuartSend = HalRuartSendRtl8195a; // Polling mode Tx + pHalRuartOp->HalRuartIntSend = HalRuartIntSendRtl8195a; // Interrupt mode Tx + pHalRuartOp->HalRuartDmaSend = HalRuartDmaSendRtl8195a; // DMA mode Tx + pHalRuartOp->HalRuartStopSend = HalRuartStopSendRtl8195a; // Stop non-blocking TX + pHalRuartOp->HalRuartGetC = HalRuartGetCRtl8195a; // get a byte + pHalRuartOp->HalRuartRecv = HalRuartRecvRtl8195a; // Polling mode Rx + pHalRuartOp->HalRuartIntRecv = HalRuartIntRecvRtl8195a; // Interrupt mode Rx + pHalRuartOp->HalRuartDmaRecv = HalRuartDmaRecvRtl8195a; // DMA mode Rx + pHalRuartOp->HalRuartStopRecv = HalRuartStopRecvRtl8195a; // Stop non-blocking Rx + pHalRuartOp->HalRuartGetIMR = HalRuartGetIMRRtl8195a; + pHalRuartOp->HalRuartSetIMR = HalRuartSetIMRRtl8195a; + pHalRuartOp->HalRuartGetDebugValue = HalRuartGetDebugValueRtl8195a; + pHalRuartOp->HalRuartDmaInit = HalRuartDmaInitRtl8195a; + pHalRuartOp->HalRuartRTSCtrl = HalRuartRTSCtrlRtl8195a; + pHalRuartOp->HalRuartRegIrq = HalRuartRegIrqRtl8195a; + pHalRuartOp->HalRuartIntEnable = HalRuartIntEnableRtl8195a; + pHalRuartOp->HalRuartIntDisable = HalRuartIntDisableRtl8195a; +} + + + +/** + * Load UART HAL default setting + * + * Call this function to load the default setting for UART HAL adapter + * + * + */ +VOID +HalRuartAdapterInit( + PRUART_ADAPTER pRuartAdapter, + u8 UartIdx +) +{ + PHAL_RUART_OP pHalRuartOp; + PHAL_RUART_ADAPTER pHalRuartAdapter; + + if (NULL == pRuartAdapter) { + return; + } + + pHalRuartOp = pRuartAdapter->pHalRuartOp; + pHalRuartAdapter = pRuartAdapter->pHalRuartAdapter; + + if ((NULL == pHalRuartOp) || (NULL == pHalRuartAdapter)) { + return; + } + + // Load default setting + if (pHalRuartOp->HalRuartAdapterLoadDef != NULL) { + pHalRuartOp->HalRuartAdapterLoadDef (pHalRuartAdapter, UartIdx); + } + else { + // Initial your UART HAL adapter here + } + + // Start to modify the defualt setting + pHalRuartAdapter->PinmuxSelect = RUART0_MUX_TO_GPIOC; + pHalRuartAdapter->BaudRate = 38400; + +// pHalRuartAdapter->IrqHandle.IrqFun = (IRQ_FUN)_UartIrqHandle; +// pHalRuartAdapter->IrqHandle.Data = (void *)pHalRuartAdapter; +// pHalRuartAdapter->IrqHandle.Priority = 0x20; + + // Register IRQ + InterruptRegister(&pHalRuartAdapter->IrqHandle); + +} + +/** + * Load UART HAL GDMA default setting + * + * Call this function to load the default setting for UART GDMA + * + * + */ +HAL_Status +HalRuartTxGdmaInit( + PHAL_RUART_OP pHalRuartOp, + PHAL_RUART_ADAPTER pHalRuartAdapter, + PUART_DMA_CONFIG pUartGdmaConfig +) +{ + PHAL_GDMA_ADAPTER pHalGdmaAdapter; + u8 gdma_idx; + u8 gdma_chnum; + HAL_GDMA_CHNL *pgdma_chnl; + + if ((NULL == pHalRuartOp) || (NULL == pHalRuartAdapter) || (NULL == pUartGdmaConfig)) { + return HAL_ERR_PARA; + } + + // Load default setting + if (pHalRuartOp->HalRuartTxGdmaLoadDef != NULL) { + pHalRuartOp->HalRuartTxGdmaLoadDef (pHalRuartAdapter, pUartGdmaConfig); + } + else { + // Initial your GDMA setting here + } + + // Start to patch the default setting + pHalGdmaAdapter = (PHAL_GDMA_ADAPTER)pUartGdmaConfig->pTxHalGdmaAdapter; + if (HalGdmaChnlRegister(pHalGdmaAdapter->GdmaIndex, pHalGdmaAdapter->ChNum) != HAL_OK) { + // The default GDMA Channel is not available, try others + if (pHalRuartAdapter->UartIndex == 2) { + // UART2 TX Only can use GDMA 0 + pgdma_chnl = HalGdmaChnlAlloc((HAL_GDMA_CHNL*)Uart2_TX_GDMA_Chnl_Option); + } + else { + pgdma_chnl = HalGdmaChnlAlloc(NULL); + } + + if (pgdma_chnl == NULL) { + // No Available DMA channel + return HAL_BUSY; + } + else { + pHalGdmaAdapter->GdmaIndex = pgdma_chnl->GdmaIndx; + pHalGdmaAdapter->ChNum = pgdma_chnl->GdmaChnl; + pHalGdmaAdapter->ChEn = 0x0101 << pgdma_chnl->GdmaChnl; + pUartGdmaConfig->TxGdmaIrqHandle.IrqNum = pgdma_chnl->IrqNum; + } + } + + // User can assign a Interrupt Handler here +// pUartGdmaConfig->TxGdmaIrqHandle.Data = pHalRuartAdapter; +// pUartGdmaConfig->TxGdmaIrqHandle.IrqFun = (IRQ_FUN)_UartTxDmaIrqHandle +// pUartGdmaConfig->TxGdmaIrqHandle.Priority = 0x20; + + pHalRuartOp->HalRuartDmaInit (pHalRuartAdapter); + InterruptRegister(&pUartGdmaConfig->TxGdmaIrqHandle); + InterruptEn(&pUartGdmaConfig->TxGdmaIrqHandle); + + return HAL_OK; +} + +VOID +HalRuartTxGdmaDeInit( + PUART_DMA_CONFIG pUartGdmaConfig +) +{ + PHAL_GDMA_ADAPTER pHalGdmaAdapter; + HAL_GDMA_CHNL GdmaChnl; + + pHalGdmaAdapter = (PHAL_GDMA_ADAPTER)pUartGdmaConfig->pTxHalGdmaAdapter; + GdmaChnl.GdmaIndx = pHalGdmaAdapter->GdmaIndex; + GdmaChnl.GdmaChnl = pHalGdmaAdapter->ChNum; + GdmaChnl.IrqNum = pUartGdmaConfig->TxGdmaIrqHandle.IrqNum; + HalGdmaChnlFree(&GdmaChnl); +} + +/** + * Load UART HAL GDMA default setting + * + * Call this function to load the default setting for UART GDMA + * + * + */ +HAL_Status +HalRuartRxGdmaInit( + PHAL_RUART_OP pHalRuartOp, + PHAL_RUART_ADAPTER pHalRuartAdapter, + PUART_DMA_CONFIG pUartGdmaConfig +) +{ + PHAL_GDMA_ADAPTER pHalGdmaAdapter; + HAL_GDMA_CHNL *pgdma_chnl; + + if ((NULL == pHalRuartOp) || (NULL == pHalRuartAdapter) || (NULL == pUartGdmaConfig)) { + return HAL_ERR_PARA; + } + + // Load default setting + if (pHalRuartOp->HalRuartRxGdmaLoadDef != NULL) { + pHalRuartOp->HalRuartRxGdmaLoadDef (pHalRuartAdapter, pUartGdmaConfig); + } + else { + // Initial your GDMA setting here + } + + // Start to patch the default setting + pHalGdmaAdapter = (PHAL_GDMA_ADAPTER)pUartGdmaConfig->pRxHalGdmaAdapter; + if (HalGdmaChnlRegister(pHalGdmaAdapter->GdmaIndex, pHalGdmaAdapter->ChNum) != HAL_OK) { + // The default GDMA Channel is not available, try others + if (pHalRuartAdapter->UartIndex == 2) { + // UART2 RX Only can use GDMA 1 + pgdma_chnl = HalGdmaChnlAlloc((HAL_GDMA_CHNL*)Uart2_RX_GDMA_Chnl_Option); + } + else { + pgdma_chnl = HalGdmaChnlAlloc(NULL); + } + + if (pgdma_chnl == NULL) { + // No Available DMA channel + return HAL_BUSY; + } + else { + pHalGdmaAdapter->GdmaIndex = pgdma_chnl->GdmaIndx; + pHalGdmaAdapter->ChNum = pgdma_chnl->GdmaChnl; + pHalGdmaAdapter->ChEn = 0x0101 << pgdma_chnl->GdmaChnl; + pUartGdmaConfig->RxGdmaIrqHandle.IrqNum = pgdma_chnl->IrqNum; + } + } + +// pUartGdmaConfig->RxGdmaIrqHandle.Data = pHalRuartAdapter; +// pUartGdmaConfig->RxGdmaIrqHandle.IrqFun = (IRQ_FUN)_UartTxDmaIrqHandle; +// pUartGdmaConfig->RxGdmaIrqHandle.Priority = 0x20; + + pHalRuartOp->HalRuartDmaInit (pHalRuartAdapter); + InterruptRegister(&pUartGdmaConfig->RxGdmaIrqHandle); + InterruptEn(&pUartGdmaConfig->RxGdmaIrqHandle); + + return HAL_OK; +} + +VOID +HalRuartRxGdmaDeInit( + PUART_DMA_CONFIG pUartGdmaConfig +) +{ + PHAL_GDMA_ADAPTER pHalGdmaAdapter; + HAL_GDMA_CHNL GdmaChnl; + + pHalGdmaAdapter = (PHAL_GDMA_ADAPTER)pUartGdmaConfig->pRxHalGdmaAdapter; + GdmaChnl.GdmaIndx = pHalGdmaAdapter->GdmaIndex; + GdmaChnl.GdmaChnl = pHalGdmaAdapter->ChNum; + GdmaChnl.IrqNum = pUartGdmaConfig->RxGdmaIrqHandle.IrqNum; + HalGdmaChnlFree(&GdmaChnl); +} + +/** + * Hook a RX indication callback + * + * To hook a callback function which will be called when a got a RX byte + * + * + */ +VOID +HalRuartRxIndHook( + PRUART_ADAPTER pRuartAdapter, + VOID *pCallback, + VOID *pPara +) +{ + PHAL_RUART_ADAPTER pHalRuartAdapter = pRuartAdapter->pHalRuartAdapter; + + pHalRuartAdapter->RxDRCallback = (void (*)(void*))pCallback; + pHalRuartAdapter->RxDRCbPara = pPara; + + // enable RX data ready interrupt + pHalRuartAdapter->Interrupts |= RUART_IER_ERBI | RUART_IER_ELSI; + pRuartAdapter->pHalRuartOp->HalRuartSetIMR(pHalRuartAdapter); +} + + +HAL_Status +HalRuartResetTxFifo( + IN VOID *Data +) +{ + return (HalRuartResetTxFifoRtl8195a(Data)); +} + diff --git a/component/soc/realtek/8195a/misc/bsp/image/ram_1.p.bin b/component/soc/realtek/8195a/misc/bsp/image/ram_1.p.bin new file mode 100644 index 0000000..4c52ae2 Binary files /dev/null and b/component/soc/realtek/8195a/misc/bsp/image/ram_1.p.bin differ diff --git a/component/soc/realtek/8195a/misc/bsp/image/ram_1.r.bin b/component/soc/realtek/8195a/misc/bsp/image/ram_1.r.bin new file mode 100644 index 0000000..e6f1a64 Binary files /dev/null and b/component/soc/realtek/8195a/misc/bsp/image/ram_1.r.bin differ diff --git a/component/soc/realtek/8195a/misc/bsp/lib/va0/lib_mdns.a b/component/soc/realtek/8195a/misc/bsp/lib/va0/lib_mdns.a new file mode 100644 index 0000000..e6e94ef Binary files /dev/null and b/component/soc/realtek/8195a/misc/bsp/lib/va0/lib_mdns.a differ diff --git a/component/soc/realtek/8195a/misc/bsp/lib/va0/lib_platform.a b/component/soc/realtek/8195a/misc/bsp/lib/va0/lib_platform.a new file mode 100644 index 0000000..236a172 Binary files /dev/null and b/component/soc/realtek/8195a/misc/bsp/lib/va0/lib_platform.a differ diff --git a/component/soc/realtek/8195a/misc/bsp/lib/va0/lib_rtlstd.a b/component/soc/realtek/8195a/misc/bsp/lib/va0/lib_rtlstd.a new file mode 100644 index 0000000..7871070 Binary files /dev/null and b/component/soc/realtek/8195a/misc/bsp/lib/va0/lib_rtlstd.a differ diff --git a/component/soc/realtek/8195a/misc/bsp/lib/va0/lib_wlan.a b/component/soc/realtek/8195a/misc/bsp/lib/va0/lib_wlan.a new file mode 100644 index 0000000..0f21559 Binary files /dev/null and b/component/soc/realtek/8195a/misc/bsp/lib/va0/lib_wlan.a differ diff --git a/component/soc/realtek/8195a/misc/bsp/lib/va0/lib_wlan_mp.a b/component/soc/realtek/8195a/misc/bsp/lib/va0/lib_wlan_mp.a new file mode 100644 index 0000000..d038541 Binary files /dev/null and b/component/soc/realtek/8195a/misc/bsp/lib/va0/lib_wlan_mp.a differ diff --git a/component/soc/realtek/8195a/misc/bsp/lib/va0/lib_wps.a b/component/soc/realtek/8195a/misc/bsp/lib/va0/lib_wps.a new file mode 100644 index 0000000..69f1de3 Binary files /dev/null and b/component/soc/realtek/8195a/misc/bsp/lib/va0/lib_wps.a differ diff --git a/component/soc/realtek/8195a/misc/bsp/lib/va0/rom.a b/component/soc/realtek/8195a/misc/bsp/lib/va0/rom.a new file mode 100644 index 0000000..4b7947a Binary files /dev/null and b/component/soc/realtek/8195a/misc/bsp/lib/va0/rom.a differ diff --git a/component/soc/realtek/8195a/misc/driver/low_level_io.c b/component/soc/realtek/8195a/misc/driver/low_level_io.c new file mode 100644 index 0000000..80be01c --- /dev/null +++ b/component/soc/realtek/8195a/misc/driver/low_level_io.c @@ -0,0 +1,39 @@ +#include +#include "hal_api.h" + +size_t __write(int Handle, const unsigned char * Buf, size_t Bufsize) +{ + int nChars = 0; + /* Check for stdout and stderr + (only necessary if file descriptors are enabled.) */ + if (Handle != 1 && Handle != 2) + { + return -1; + } + for (/*Empty */; Bufsize > 0; --Bufsize) + { + DiagPutChar(*Buf++); + ++nChars; + } + return nChars; +} + +size_t __read(int Handle, unsigned char * Buf, size_t Bufsize) +{ + int nChars = 0; + /* Check for stdin + (only necessary if FILE descriptors are enabled) */ + if (Handle != 0) + { + return -1; + } + for (/*Empty*/; Bufsize > 0; --Bufsize) + { + int c = DiagGetChar(_FALSE); + if (c < 0) + break; + *(Buf++) = c; + ++nChars; + } + return nChars; +} \ No newline at end of file diff --git a/component/soc/realtek/8195a/misc/driver/rtl_consol.c b/component/soc/realtek/8195a/misc/driver/rtl_consol.c new file mode 100644 index 0000000..2840005 --- /dev/null +++ b/component/soc/realtek/8195a/misc/driver/rtl_consol.c @@ -0,0 +1,333 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#include "rtl8195a.h" +//#include +#include "rtl_consol.h" +#include "osdep_api.h" +#if defined(configUSE_WAKELOCK_PMU) && (configUSE_WAKELOCK_PMU == 1) +#include "freertos_pmu.h" +#endif + +MON_RAM_BSS_SECTION + volatile UART_LOG_CTL UartLogCtl; +MON_RAM_BSS_SECTION + volatile UART_LOG_CTL *pUartLogCtl; +MON_RAM_BSS_SECTION + u8 *ArgvArray[MAX_ARGV]; +MON_RAM_BSS_SECTION + UART_LOG_BUF UartLogBuf; + + +#ifdef CONFIG_UART_LOG_HISTORY +MON_RAM_BSS_SECTION + u8 UartLogHistoryBuf[UART_LOG_HISTORY_LEN][UART_LOG_CMD_BUFLEN]; +#endif + +_LONG_CALL_ +extern u8 +UartLogCmdChk( + IN u8 RevData, + IN UART_LOG_CTL *prvUartLogCtl, + IN u8 EchoFlag +); + +_LONG_CALL_ +extern VOID +ArrayInitialize( + IN u8 *pArrayToInit, + IN u8 ArrayLen, + IN u8 InitValue +); + +_LONG_CALL_ +extern VOID +UartLogHistoryCmd( + IN u8 RevData, + IN UART_LOG_CTL *prvUartLogCtl, + IN u8 EchoFlag +); + +_LONG_CALL_ +extern VOID +UartLogCmdExecute( + IN PUART_LOG_CTL pUartLogCtlExe +); + + + +//================================================= + + +/* Minimum and maximum values a `signed long int' can hold. + (Same as `int'). */ +#ifndef __LONG_MAX__ +#if defined (__alpha__) || (defined (__sparc__) && defined(__arch64__)) || defined (__sparcv9) || defined (__s390x__) +#define __LONG_MAX__ 9223372036854775807L +#else +#define __LONG_MAX__ 2147483647L +#endif /* __alpha__ || sparc64 */ +#endif +#undef LONG_MIN +#define LONG_MIN (-LONG_MAX-1) +#undef LONG_MAX +#define LONG_MAX __LONG_MAX__ + +/* Maximum value an `unsigned long int' can hold. (Minimum is 0). */ +#undef ULONG_MAX +#define ULONG_MAX (LONG_MAX * 2UL + 1) + +#ifndef __LONG_LONG_MAX__ +#define __LONG_LONG_MAX__ 9223372036854775807LL +#endif + + + + +//====================================================== +//: UartLogIrqHandleRam +//: To deal with Uart-Log RX IRQ +//: VOID +//: VOID +//: NA +//====================================================== +MON_RAM_TEXT_SECTION +VOID +UartLogIrqHandleRam +( + VOID * Data +) +{ + u8 UartReceiveData = 0; + //For Test + BOOL PullMode = _FALSE; + + u32 IrqEn = DiagGetIsrEnReg(); + + DiagSetIsrEnReg(0); + + UartReceiveData = DiagGetChar(PullMode); + + //KB_ESC chk is for cmd history, it's a special case here. + if (UartReceiveData == KB_ASCII_ESC) { + //4 Esc detection is only valid in the first stage of boot sequence (few seconds) + if (pUartLogCtl->ExecuteEsc != _TRUE) + { + pUartLogCtl->ExecuteEsc = _TRUE; + (*pUartLogCtl).EscSTS = 0; + } + else + { + //4 the input commands are valid only when the task is ready to execute commands + if ((pUartLogCtl->BootRdy == 1) +#ifdef CONFIG_KERNEL + ||(pUartLogCtl->TaskRdy == 1) +#endif + ) + { + if ((*pUartLogCtl).EscSTS==0) + { + (*pUartLogCtl).EscSTS = 1; + } + } + else + { + (*pUartLogCtl).EscSTS = 0; + } + } + } + else if ((*pUartLogCtl).EscSTS==1){ + if (UartReceiveData != KB_ASCII_LBRKT){ + (*pUartLogCtl).EscSTS = 0; + } + else{ + (*pUartLogCtl).EscSTS = 2; + } + } + + else{ + if ((*pUartLogCtl).EscSTS==2){ + (*pUartLogCtl).EscSTS = 0; +#ifdef CONFIG_UART_LOG_HISTORY + if ((UartReceiveData=='A')|| UartReceiveData=='B'){ + UartLogHistoryCmd(UartReceiveData,(UART_LOG_CTL *)pUartLogCtl,1); + } +#endif + } + else{ + if (UartLogCmdChk(UartReceiveData,(UART_LOG_CTL *)pUartLogCtl,1)==2) + { + //4 check UartLog buffer to prevent from incorrect access + if (pUartLogCtl->pTmpLogBuf != NULL) + { + pUartLogCtl->ExecuteCmd = _TRUE; +#if defined(CONFIG_KERNEL) && !TASK_SCHEDULER_DISABLED + if (pUartLogCtl->TaskRdy) + RtlUpSemaFromISR((_Sema *)&pUartLogCtl->Sema); +#endif + } + else + { + ArrayInitialize((u8 *)pUartLogCtl->pTmpLogBuf->UARTLogBuf, UART_LOG_CMD_BUFLEN, '\0'); + } + } + } + } + DiagSetIsrEnReg(IrqEn); + +} + + + +MON_RAM_TEXT_SECTION +VOID +RtlConsolInitRam( + IN u32 Boot, + IN u32 TBLSz, + IN VOID *pTBL +) +{ + UartLogBuf.BufCount = 0; + ArrayInitialize(&UartLogBuf.UARTLogBuf[0],UART_LOG_CMD_BUFLEN,'\0'); + pUartLogCtl = &UartLogCtl; + + pUartLogCtl->NewIdx = 0; + pUartLogCtl->SeeIdx = 0; + pUartLogCtl->RevdNo = 0; + pUartLogCtl->EscSTS = 0; + pUartLogCtl->BootRdy = 0; + pUartLogCtl->pTmpLogBuf = &UartLogBuf; +#ifdef CONFIG_UART_LOG_HISTORY + pUartLogCtl->CRSTS = 0; + pUartLogCtl->pHistoryBuf = &UartLogHistoryBuf[0]; +#endif + pUartLogCtl->pfINPUT = (VOID*)&DiagPrintf; + pUartLogCtl->pCmdTbl = (PCOMMAND_TABLE) pTBL; + pUartLogCtl->CmdTblSz = TBLSz; +#ifdef CONFIG_KERNEL + pUartLogCtl->TaskRdy = 0; +#endif + //executing boot sequence + if (Boot == ROM_STAGE) + { + pUartLogCtl->ExecuteCmd = _FALSE; + pUartLogCtl->ExecuteEsc = _FALSE; + } + else + { + pUartLogCtl->ExecuteCmd = _FALSE; + pUartLogCtl->ExecuteEsc= _TRUE;//don't check Esc anymore +#if defined(CONFIG_KERNEL) + /* Create a Semaphone */ + RtlInitSema((_Sema*)&(pUartLogCtl->Sema), 0); + pUartLogCtl->TaskRdy = 0; +#ifdef PLATFORM_FREERTOS + if (pdTRUE != xTaskCreate( RtlConsolTaskRam, (const signed char * const)"LOGUART_TASK", 512, NULL, tskIDLE_PRIORITY + 5 + PRIORITIE_OFFSET, NULL)) + { + DiagPrintf("Create Log UART Task Err!!\n"); + } +#endif +#endif + } + + CONSOLE_8195A(); +} + +extern u8** GetArgv(const u8 *string); +#if SUPPORT_LOG_SERVICE +extern char log_buf[LOG_SERVICE_BUFLEN]; +extern xSemaphoreHandle log_rx_interrupt_sema; +#endif +//====================================================== +void console_cmd_exec(PUART_LOG_CTL pUartLogCtlExe) +{ + u8 CmdCnt = 0; + u8 argc = 0; + u8 **argv; + //u32 CmdNum; + PUART_LOG_BUF pUartLogBuf = pUartLogCtlExe->pTmpLogBuf; +#if SUPPORT_LOG_SERVICE + strncpy(log_buf, (const u8*)&(*pUartLogBuf).UARTLogBuf[0], LOG_SERVICE_BUFLEN-1); +#endif + argc = GetArgc((const u8*)&((*pUartLogBuf).UARTLogBuf[0])); + argv = GetArgv((const u8*)&((*pUartLogBuf).UARTLogBuf[0])); + + if(argc > 0){ +#if SUPPORT_LOG_SERVICE +// if(log_handler(argv[0]) == NULL) +// legency_interactive_handler(argc, argv); + RtlUpSema((_Sema *)&log_rx_interrupt_sema); +#endif + ArrayInitialize(argv[0], sizeof(argv[0]) ,0); + }else{ +#if defined(configUSE_WAKELOCK_PMU) && (configUSE_WAKELOCK_PMU == 1) + acquire_wakelock(WAKELOCK_LOGUART); +#endif + CONSOLE_8195A(); // for null command + } + + (*pUartLogBuf).BufCount = 0; + ArrayInitialize(&(*pUartLogBuf).UARTLogBuf[0], UART_LOG_CMD_BUFLEN, '\0'); +} +//====================================================== +// overload original RtlConsolTaskRam +MON_RAM_TEXT_SECTION +VOID +RtlConsolTaskRam( + VOID *Data +) +{ +#if SUPPORT_LOG_SERVICE + log_service_init(); +#endif + //4 Set this for UartLog check cmd history +#ifdef CONFIG_KERNEL + pUartLogCtl->TaskRdy = 1; +#endif +#ifndef CONFIG_KERNEL + pUartLogCtl->BootRdy = 1; +#endif + do{ +#if defined(CONFIG_KERNEL) && !TASK_SCHEDULER_DISABLED + RtlDownSema((_Sema *)&pUartLogCtl->Sema); +#endif + if (pUartLogCtl->ExecuteCmd) { + // Add command handler here + console_cmd_exec((PUART_LOG_CTL)pUartLogCtl); + //UartLogCmdExecute((PUART_LOG_CTL)pUartLogCtl); + pUartLogCtl->ExecuteCmd = _FALSE; + } + }while(1); +} + +//====================================================== +void console_init(void) +{ + IRQ_HANDLE UartIrqHandle; + + //4 Register Log Uart Callback function + UartIrqHandle.Data = NULL;//(u32)&UartAdapter; + UartIrqHandle.IrqNum = UART_LOG_IRQ; + UartIrqHandle.IrqFun = (IRQ_FUN) UartLogIrqHandleRam; + UartIrqHandle.Priority = 0; + + + //4 Register Isr handle + InterruptUnRegister(&UartIrqHandle); + InterruptRegister(&UartIrqHandle); +#if !TASK_SCHEDULER_DISABLED + RtlConsolInitRam((u32)RAM_STAGE,(u32)0,(VOID*)NULL); +#else + RtlConsolInitRam((u32)ROM_STAGE,(u32)0,(VOID*)NULL); +#endif +} + + + + diff --git a/component/soc/realtek/8195a/misc/driver/rtl_consol.h b/component/soc/realtek/8195a/misc/driver/rtl_consol.h new file mode 100644 index 0000000..c27eed8 --- /dev/null +++ b/component/soc/realtek/8195a/misc/driver/rtl_consol.h @@ -0,0 +1,133 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#ifndef _RTK_CONSOL_H_ +#define _RTK_CONSOL_H_ +/* + * Include user defined options first. Anything not defined in these files + * will be set to standard values. Override anything you dont like! + */ + #if defined(CONFIG_PLATFORM_8195A) || defined(CONFIG_PLATFORM_8711B) +#include "platform_opts.h" +#endif + +#include "osdep_api.h" +#include "hal_diag.h" + +#define CONSOLE_PREFIX "#" + + +//Log UART +//UART_LOG_CMD_BUFLEN: only 126 bytes could be used for keeping input +// cmd, the last byte is for string end ('\0'). +#define UART_LOG_CMD_BUFLEN 127 +#define MAX_ARGV 10 + + + +typedef u32 (*ECHOFUNC)(IN u8*,...); //UART LOG echo-function type. + +typedef struct _UART_LOG_BUF_ { + u8 BufCount; //record the input cmd char number. + u8 UARTLogBuf[UART_LOG_CMD_BUFLEN]; //record the input command. +} UART_LOG_BUF, *PUART_LOG_BUF; + + + +typedef struct _UART_LOG_CTL_ { + u8 NewIdx; + u8 SeeIdx; + u8 RevdNo; + u8 EscSTS; + u8 ExecuteCmd; + u8 ExecuteEsc; + u8 BootRdy; + u8 Resvd; + PUART_LOG_BUF pTmpLogBuf; + VOID *pfINPUT; + PCOMMAND_TABLE pCmdTbl; + u32 CmdTblSz; +#ifdef CONFIG_UART_LOG_HISTORY + u32 CRSTS; +#endif +#ifdef CONFIG_UART_LOG_HISTORY + u8 (*pHistoryBuf)[UART_LOG_CMD_BUFLEN]; +#endif +#ifdef CONFIG_KERNEL + u32 TaskRdy; + _Sema Sema; +#else + // Since ROM code will reference this typedef, so keep the typedef same size + u32 TaskRdy; + void *Sema; +#endif +} UART_LOG_CTL, *PUART_LOG_CTL; + + +#define KB_ASCII_NUL 0x00 +#define KB_ASCII_BS 0x08 +#define KB_ASCII_TAB 0x09 +#define KB_ASCII_LF 0x0A +#define KB_ASCII_CR 0x0D +#define KB_ASCII_ESC 0x1B +#define KB_ASCII_SP 0x20 +#define KB_ASCII_BS_7F 0x7F +#define KB_ASCII_LBRKT 0x5B //[ + +#define KB_SPACENO_TAB 1 + +#ifdef CONFIG_UART_LOG_HISTORY +#define UART_LOG_HISTORY_LEN 5 +#endif + +#ifdef CONFIG_DEBUG_LOG +#define _ConsolePrint DiagPrintf +#else +#define _ConsolePrint +#endif + +#ifndef CONSOLE_PREFIX +#define CONSOLE_PREFIX "" +#endif + +#define CONSOLE_8195A(...) do {\ + _ConsolePrint("\r"CONSOLE_PREFIX __VA_ARGS__);\ +}while(0) + + +_LONG_CALL_ VOID +RtlConsolInit( + IN u32 Boot, + IN u32 TBLSz, + IN VOID *pTBL +); + +#if defined(CONFIG_KERNEL) +_LONG_CALL_ VOID +RtlConsolTaskRam( + VOID *Data +); +#endif + +_LONG_CALL_ VOID +RtlConsolTaskRom( + VOID *Data +); + + +_LONG_CALL_ u32 +Strtoul( + IN const u8 *nptr, + IN u8 **endptr, + IN u32 base +); + +void console_init(void); + +#endif //_RTK_CONSOL_H_ diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/8195a.ddf b/component/soc/realtek/8195a/misc/iar_utility/common/8195a.ddf new file mode 100644 index 0000000..c00b2b0 --- /dev/null +++ b/component/soc/realtek/8195a/misc/iar_utility/common/8195a.ddf @@ -0,0 +1,23 @@ +;; Memory information ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Used to define address zones within the ARM address space (Memory). +;; +;; Name may be almost anything +;; AdrSpace must be Memory +;; StartAdr start of memory block +;; EndAdr end of memory block +;; AccType type of access, read-only (R), read-write (RW) or SFR (W) + +[Memory] +;; Name AdrSpace StartAdr EndAdr AccType Width +Memory = ROM Memory 0x00000000 0x003FFFFF RW +Memory = SRAM Memory 0x10000000 0x1FFFFFFF RW +Memory = DRAM Memory 0x30000000 0x30FFFFFF RW +Memory = SFR Memory 0x40000000 0x41FFFFFF RW +Memory = SFR_Bitband Memory 0x42000000 0x43FFFFFF RW +Memory = PPB Memory 0xE0000000 0xFFFFFFFF RW + +TrustedRanges = true +UseSfrFilter = true + +[SfrInclude] diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/dram/EM6A6165TS_7G.mac b/component/soc/realtek/8195a/misc/iar_utility/common/dram/EM6A6165TS_7G.mac new file mode 100644 index 0000000..64aea1e --- /dev/null +++ b/component/soc/realtek/8195a/misc/iar_utility/common/dram/EM6A6165TS_7G.mac @@ -0,0 +1,41 @@ +__load_dram_param(){ + //DRAM_INFO + DeviceType = 8; //DRAM_SDR + Page = 0; //DRAM_COLADDR_8B + Bank=0; //DRAM_BANK_2 + DqWidth=0; //DRAM_DQ_1 + + //DRAM_MODE_REG_INFO + BstLen=0; //BST_LEN_4 + BstType=0; //SENQUENTIAL + Mode0Cas=3; + Mode0Wr=0; + Mode1DllEnN=0; + Mode1AllLat=0; + Mode2Cwl=0; + + //DRAM_TIMING_INFO + DramTimingTref = 64000; + DramRowNum = 8192; + //SDR 100MHZ==>10000, 50MHZ==>20000, 25MHZ==>40000, 12.5MHZ==>80000 + Tck = 80000; //SDR 12.5MHZ + + TrfcPs=60000; + TrefiPs=((DramTimingTref*1000)/DramRowNum)*1000; + WrMaxTck=2; + TrcdPs=15000; + TrpPs=15000; + TrasPs=42000; + TrrdTck=2; + TwrPs=Tck*2; + TwtrTck=0; + TmrdTck=2; + TrtpTck=0; + TccdTck=1; + TrcPs=60000; + + //DRAM_DEVICE_INFO + DdrPeriodPs=Tck; + DfiRate=0; //DFI_RATIO_1 + +} \ No newline at end of file diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/dram/common.mac b/component/soc/realtek/8195a/misc/iar_utility/common/dram/common.mac new file mode 100644 index 0000000..d79771c --- /dev/null +++ b/component/soc/realtek/8195a/misc/iar_utility/common/dram/common.mac @@ -0,0 +1,4 @@ + +__load_dram_common(){ + __registerMacroFile("$PROJ_DIR$\\..\\..\\..\\component\\soc\\realtek\\8195a\\misc\\iar_utility\\common\\dram\\EM6A6165TS_7G.mac"); +} \ No newline at end of file diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/dram/readme.txt b/component/soc/realtek/8195a/misc/iar_utility/common/dram/readme.txt new file mode 100644 index 0000000..2fa0238 --- /dev/null +++ b/component/soc/realtek/8195a/misc/iar_utility/common/dram/readme.txt @@ -0,0 +1,4 @@ +To Change DRAM setting + +1. Create and Fill content like EM6A6165TS_7G.mac +2. Change load file in common.mac \ No newline at end of file diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/flashloader/FlashRTL8195aMP.board b/component/soc/realtek/8195a/misc/iar_utility/common/flashloader/FlashRTL8195aMP.board new file mode 100644 index 0000000..a2c0b37 --- /dev/null +++ b/component/soc/realtek/8195a/misc/iar_utility/common/flashloader/FlashRTL8195aMP.board @@ -0,0 +1,24 @@ + + + + + CODE 0x10000bc0 0x10003FFF + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\misc\iar_utility\common\flashloader\FlashRTL8195aMP.flash + 0x00000000 + --head + + + CODE 0x10004000 0x1006FFFF + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\misc\iar_utility\common\flashloader\FlashRTL8195aMP.flash + 0x00000000 + --cascade + + + CODE 0x30000000 0x301FFFFF + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\misc\iar_utility\common\flashloader\FlashRTL8195aMP.flash + 0x00000000 + --cascade + + CODE 0x00000000 0x000FFFFF + CODE 0x10000000 0x10000bbf + diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/flashloader/FlashRTL8195aMP.flash b/component/soc/realtek/8195a/misc/iar_utility/common/flashloader/FlashRTL8195aMP.flash new file mode 100644 index 0000000..9660e0d --- /dev/null +++ b/component/soc/realtek/8195a/misc/iar_utility/common/flashloader/FlashRTL8195aMP.flash @@ -0,0 +1,10 @@ + + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\misc\iar_utility\common\flashloader\FlashRTL8195aMP.out + 0x00000000 + 8 + 256 0x1000 + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\misc\iar_utility\common\flashloader\FlashRTL8195aMP.mac + 1 + diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/flashloader/FlashRTL8195aMP.mac b/component/soc/realtek/8195a/misc/iar_utility/common/flashloader/FlashRTL8195aMP.mac new file mode 100644 index 0000000..1d4dfc9 --- /dev/null +++ b/component/soc/realtek/8195a/misc/iar_utility/common/flashloader/FlashRTL8195aMP.mac @@ -0,0 +1,69 @@ +setup() +{ + __var tmp; + + __hwResetWithStrategy(0, 2); + __hwReset(1); + + tmp = __readMemory32(0x40000014,"Memory"); __delay(10); + __message "0x40000014=",tmp:%x; + + __writeMemory32(0x21, 0x40000014, "Memory"); __delay(10); + + __writeMemory32(0x1FC00002, 0x40000304, "Memory"); __delay(10); + __writeMemory32(0x400, 0x40000250, "Memory"); __delay(10); + __writeMemory32(0x0, 0x40000340, "Memory"); __delay(10); + __writeMemory32(0xc04, 0x40000230, "Memory"); __delay(10); + __writeMemory32(0x1157, 0x40000210, "Memory"); __delay(10); + __writeMemory32(0x110011, 0x400002c0, "Memory"); __delay(10); + __writeMemory32(0xffffffff, 0x40000320, "Memory"); __delay(10); +/* + __writeMemory32(0x1, 0x40005224, "Memory"); __delay(10); + __writeMemory32(0x2c8, 0x40005004, "Memory"); __delay(10); + __writeMemory32(0xffffd000, 0x40005008, "Memory"); __delay(10); + __delay(3); + __writeMemory32(0x22, 0x40005020, "Memory"); __delay(10); + __delay(3); + __writeMemory32(0x09032001, 0x40005010, "Memory"); __delay(10); + __delay(3); + __writeMemory32(0x2611, 0x40005014, "Memory"); __delay(10); + __delay(3); + __writeMemory32(0x68413, 0x40005018, "Memory"); __delay(10); + __delay(3); + __writeMemory32(0x42, 0x4000501c, "Memory"); __delay(10); + __delay(3); + + // Enable + __writeMemory32(0x700, 0x4000500c, "Memory"); __delay(10); + __delay(20); + __writeMemory32(0x1, 0x40005000, "Memory"); __delay(10); + __delay(100); + tmp = __readMemory32(0x40005000,"Memory"); __delay(10); + __writeMemory32(0x600, 0x4000500c, "Memory"); __delay(10); + __delay(30); +*/ +} + +execUserPreload() +{ + __var tmp; + setup(); + tmp = __readMemory32(0x40000210, "Memory")|(1<<27); + __writeMemory32(tmp, 0x40000210, "Memory"); +} + +execUserSetup() +{ + //execUserPreload(); + //__loadImage("$TARGET_PATH$ ", 0, 0); + //__writeMemory32(0x80000000, 0x40000218, "Memory"); +} + +execUserFlashInit() // Called by debugger before loading flash loader in RAM. +{ + __var tmp; + __message "----- Prepare hardware for Flashloader -----\n"; + setup(); + tmp = __readMemory32(0x40000210, "Memory")|(1<<27); + __writeMemory32(tmp, 0x40000210, "Memory"); +} \ No newline at end of file diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/flashloader/FlashRTL8195aMP.out b/component/soc/realtek/8195a/misc/iar_utility/common/flashloader/FlashRTL8195aMP.out new file mode 100644 index 0000000..ff36436 Binary files /dev/null and b/component/soc/realtek/8195a/misc/iar_utility/common/flashloader/FlashRTL8195aMP.out differ diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/flashloader/FlashRTL8195aMP_img1.board b/component/soc/realtek/8195a/misc/iar_utility/common/flashloader/FlashRTL8195aMP_img1.board new file mode 100644 index 0000000..7e5c606 --- /dev/null +++ b/component/soc/realtek/8195a/misc/iar_utility/common/flashloader/FlashRTL8195aMP_img1.board @@ -0,0 +1,17 @@ + + + + + CODE 0x10000bc0 0x10003FFF + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\misc\iar_utility\common\flashloader\FlashRTL8195aMP.flash + 0x00000000 + --head + --img2_addr + 0xB000 + + + CODE 0x00000000 0x000FFFFF + CODE 0x10000000 0x10000bbf + CODE 0x10004000 0x1006FFFF + CODE 0x30000000 0x301FFFFF + diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/flashloader/FlashRTL8195aMP_img2.board b/component/soc/realtek/8195a/misc/iar_utility/common/flashloader/FlashRTL8195aMP_img2.board new file mode 100644 index 0000000..80cff48 --- /dev/null +++ b/component/soc/realtek/8195a/misc/iar_utility/common/flashloader/FlashRTL8195aMP_img2.board @@ -0,0 +1,26 @@ + + + + + CODE 0x10000bc8 0x10003FFF + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\misc\iar_utility\common\flashloader\FlashRTL8195aMP.flash + 0x00000000 + --head + --img2_addr + 0xB000 + + + CODE 0x10004000 0x1006FFFF + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\misc\iar_utility\common\flashloader\FlashRTL8195aMP.flash + 0xB000 + + + CODE 0x30000000 0x301FFFFF + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\misc\iar_utility\common\flashloader\FlashRTL8195aMP.flash + 0x0000 + --cascade + + CODE 0x00000000 0x000FFFFF + CODE 0x10000000 0x10000bc7 + CODE 0x1FFF0000 0x1FFFFFFF + diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/flashloader/FlashRTL8195aQA.board b/component/soc/realtek/8195a/misc/iar_utility/common/flashloader/FlashRTL8195aQA.board new file mode 100644 index 0000000..2562be5 --- /dev/null +++ b/component/soc/realtek/8195a/misc/iar_utility/common/flashloader/FlashRTL8195aQA.board @@ -0,0 +1,30 @@ + + + + + CODE 0x200006b4 0x2002FFFF + $PROJ_DIR$\flashloader\FlashRTL8195aQA.flash + 0x00000000 + + + CODE 0x30000000 0x301FFFFF + $PROJ_DIR$\flashloader\FlashRTL8195aQA.flash + 0x00010000 + DATA_Z 0x30000000 0x301FFFFF + + + CODE 0x20080000 0x200BFFFF + $PROJ_DIR$\flashloader\FlashRTL8195aQA.flash + 0x00020000 + DATA_Z 0x20080000 0x200BFFFF + + + CODE 0x00000000 0x00000000 + $PROJ_DIR$\flashloader\FlashRTL8195aQA.flash + 0x00030000 + + CODE 0x00000001 0x000BFFFF + CODE 0x20000000 0x200006b3 + + + diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/flashloader/FlashRTL8195aQA.flash b/component/soc/realtek/8195a/misc/iar_utility/common/flashloader/FlashRTL8195aQA.flash new file mode 100644 index 0000000..8613f80 --- /dev/null +++ b/component/soc/realtek/8195a/misc/iar_utility/common/flashloader/FlashRTL8195aQA.flash @@ -0,0 +1,10 @@ + + + + $PROJ_DIR$\flashloader\FlashRTL8195aQA.out + 0x00000000 + 8 + 256 0x1000 + $PROJ_DIR$\flashloader\FlashRTL8195aQA.mac + 1 + diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/flashloader/FlashRTL8195aQA.mac b/component/soc/realtek/8195a/misc/iar_utility/common/flashloader/FlashRTL8195aQA.mac new file mode 100644 index 0000000..4d670e0 --- /dev/null +++ b/component/soc/realtek/8195a/misc/iar_utility/common/flashloader/FlashRTL8195aQA.mac @@ -0,0 +1,60 @@ +setup() +{ + __var tmp; + + __hwReset(1); + + __writeMemory32(0x21, 0x40000014, "Memory"); __delay(10); + __writeMemory32(0x1FC00002, 0x40000304, "Memory"); __delay(10); + __writeMemory32(0x400, 0x40000250, "Memory"); __delay(10); + __writeMemory32(0x0, 0x40000340, "Memory"); __delay(10); + __writeMemory32(0xc04, 0x40000230, "Memory"); __delay(10); + __writeMemory32(0x1157, 0x40000210, "Memory"); __delay(10); + __writeMemory32(0x110011, 0x400002c0, "Memory"); __delay(10); + __writeMemory32(0xffffffff, 0x40000320, "Memory"); __delay(10); + + __writeMemory32(0x1, 0x40005224, "Memory"); __delay(10); + __writeMemory32(0x2c8, 0x40005004, "Memory"); __delay(10); + __writeMemory32(0xffffd000, 0x40005008, "Memory"); __delay(10); + __delay(3); + __writeMemory32(0x22, 0x40005020, "Memory"); __delay(10); + __delay(3); + __writeMemory32(0x09032001, 0x40005010, "Memory"); __delay(10); + __delay(3); + __writeMemory32(0x2611, 0x40005014, "Memory"); __delay(10); + __delay(3); + __writeMemory32(0x68413, 0x40005018, "Memory"); __delay(10); + __delay(3); + __writeMemory32(0x42, 0x4000501c, "Memory"); __delay(10); + __delay(3); + + // Enable + __writeMemory32(0x700, 0x4000500c, "Memory"); __delay(10); + __delay(20); + __writeMemory32(0x1, 0x40005000, "Memory"); __delay(10); + __delay(100); + tmp = __readMemory32(0x40005000,"Memory"); __delay(10); + __writeMemory32(0x600, 0x4000500c, "Memory"); __delay(10); + __delay(30); +} + +execUserPreload() +{ + __message "----- Prepare hardware for Flashloader -----\n"; + setup(); + __writeMemory32(0x80000000, 0x40000218, "Memory"); +} + +execUserSetup() +{ + //execUserPreload(); + //__loadImage("$TARGET_PATH$ ", 0, 0); + //__writeMemory32(0x80000000, 0x40000218, "Memory"); +} + +execUserFlashInit() // Called by debugger before loading flash loader in RAM. +{ + __message "----- Prepare hardware for Flashloader -----\n"; + setup(); + __writeMemory32(0x80000000, 0x40000218, "Memory"); +} \ No newline at end of file diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/flashloader/FlashRTL8195aQA.out b/component/soc/realtek/8195a/misc/iar_utility/common/flashloader/FlashRTL8195aQA.out new file mode 100644 index 0000000..c89a959 Binary files /dev/null and b/component/soc/realtek/8195a/misc/iar_utility/common/flashloader/FlashRTL8195aQA.out differ diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/gen_board.bat b/component/soc/realtek/8195a/misc/iar_utility/common/gen_board.bat new file mode 100644 index 0000000..c96cffe --- /dev/null +++ b/component/soc/realtek/8195a/misc/iar_utility/common/gen_board.bat @@ -0,0 +1,53 @@ +@set /a tmp = %1-1 +@call :toHex %tmp% end1 +@set /a tmp2 = %2-1 +@call :toHex %tmp2% end2 +@set /a tmp3 = %3-1 +@call :toHex %tmp3% end0 + +@echo echo image 2 start %1 +@echo echo image 1 end 0x%end1% +@echo off +@echo ^ > tmp.board +@echo. >> tmp.board +@echo ^ >> tmp.board +@echo ^ >> tmp.board +@echo ^CODE %3 0x%end1%^ >> tmp.board +@echo ^$PROJ_DIR$\..\..\..\component\soc\realtek\8195a\misc\iar_utility\common\flashloader\FlashRTL8195aMP.flash^ >> tmp.board +@echo ^0x00000000^ >> tmp.board +@echo ^--head^ >> tmp.board +@echo ^ >> tmp.board +@echo ^ >> tmp.board +@echo ^CODE %1 0x%end2%^ >> tmp.board +@echo ^$PROJ_DIR$\..\..\..\component\soc\realtek\8195a\misc\iar_utility\common\flashloader\FlashRTL8195aMP.flash^ >> tmp.board +@echo ^0x00000000^ >> tmp.board +@echo ^--cascade^ >> tmp.board +@echo ^ >> tmp.board +@echo ^ >> tmp.board +@echo ^CODE 0x30000000 0x301FFFFF^ >> tmp.board +@echo ^$PROJ_DIR$\..\..\..\component\soc\realtek\8195a\misc\iar_utility\common\flashloader\FlashRTL8195aMP.flash^ >> tmp.board +@echo ^0x00000000^ >> tmp.board +@echo ^--cascade^ >> tmp.board +@echo ^ >> tmp.board +@echo ^CODE 0x00000000 0x000FFFFF^ >> tmp.board +@echo ^CODE 0x10000000 0x%end0%^ >> tmp.board +@echo ^CODE %2 0x1006FFFF^ >> tmp.board +@echo ^ >> tmp.board >> tmp.board + +exit + +:toHex dec hex -- convert a decimal number to hexadecimal, i.e. -20 to FFFFFFEC or 26 to 0000001A +@echo off +SETLOCAL ENABLEDELAYEDEXPANSION +set /a dec=%~1 +set "hex=" +set "map=0123456789ABCDEF" +for /L %%N in (1,1,8) do ( + set /a "d=dec&15,dec>>=4" + for %%D in (!d!) do set "hex=!map:~%%D,1!!hex!" +) + +( ENDLOCAL & REM RETURN VALUES + IF "%~2" NEQ "" (SET %~2=%hex%) ELSE ECHO.%hex% +) +EXIT /b \ No newline at end of file diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/gen_board_img2.bat b/component/soc/realtek/8195a/misc/iar_utility/common/gen_board_img2.bat new file mode 100644 index 0000000..d02407c --- /dev/null +++ b/component/soc/realtek/8195a/misc/iar_utility/common/gen_board_img2.bat @@ -0,0 +1,57 @@ +@set /a tmp = %1-1 +@call :toHex %tmp% end1 +@set /a tmp2 = %2-1 +@call :toHex %tmp2% end2 +@set /a tmp3 = %3-1 +@call :toHex %tmp3% end3 + +@echo echo image 2 start %1 +@echo echo image 1 end 0x%end1% +@echo off +@echo ^ > tmp.board +@echo. >> tmp.board +@echo ^ >> tmp.board +@echo ^ >> tmp.board +@echo ^CODE 0x10000bc8 0x10003FFF^ >> tmp.board +@echo ^$PROJ_DIR$\..\..\..\component\soc\realtek\8195a\misc\iar_utility\common\flashloader\FlashRTL8195aMP.flash^ >> tmp.board +@echo ^0x00000000^ >> tmp.board +@echo ^--head >> tmp.board +@echo --img2_addr >> tmp.board +@echo 0xB000^ >> tmp.board +@echo ^ >> tmp.board +@echo ^ >> tmp.board +@echo ^CODE 0x10004000 0x%end2%^ >> tmp.board +@echo ^$PROJ_DIR$\..\..\..\component\soc\realtek\8195a\misc\iar_utility\common\flashloader\FlashRTL8195aMP.flash^ >> tmp.board +@echo ^0xB000^ >> tmp.board +@echo ^ >> tmp.board +if NOT "%3"=="" ( +@echo ^ >> tmp.board +@echo ^CODE 0x30000000 0x%end3%^ >> tmp.board +@echo ^$PROJ_DIR$\..\..\..\component\soc\realtek\8195a\misc\iar_utility\common\flashloader\FlashRTL8195aMP.flash^ >> tmp.board +@echo ^0x0000^ >> tmp.board +@echo ^--cascade^ >> tmp.board +@echo ^ >> tmp.board +) +@echo ^CODE 0x00000000 0x000FFFFF^ >> tmp.board +@echo ^CODE 0x10000000 0x10000bc7^ >> tmp.board +@echo ^CODE %2 0x1006FFFF^ >> tmp.board +@echo ^CODE 0x1FFF0000 0x1FFFFFFF^ >> tmp.board +@echo ^ >> tmp.board >> tmp.board + +exit + +:toHex dec hex -- convert a decimal number to hexadecimal, i.e. -20 to FFFFFFEC or 26 to 0000001A +@echo off +SETLOCAL ENABLEDELAYEDEXPANSION +set /a dec=%~1 +set "hex=" +set "map=0123456789ABCDEF" +for /L %%N in (1,1,8) do ( + set /a "d=dec&15,dec>>=4" + for %%D in (!d!) do set "hex=!map:~%%D,1!!hex!" +) + +( ENDLOCAL & REM RETURN VALUES + IF "%~2" NEQ "" (SET %~2=%hex%) ELSE ECHO.%hex% +) +EXIT /b \ No newline at end of file diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/postbuild.bat b/component/soc/realtek/8195a/misc/iar_utility/common/postbuild.bat new file mode 100644 index 0000000..985ccd8 --- /dev/null +++ b/component/soc/realtek/8195a/misc/iar_utility/common/postbuild.bat @@ -0,0 +1,47 @@ +cd /D %2 +set tooldir=%2\..\..\..\component\soc\realtek\8195a\misc\iar_utility\common\tools + +del Debug/Exe/target.map Debug/Exe/target.asm *.bin +cmd /c "%tooldir%\nm Debug/Exe/target.axf | %tooldir%\sort > Debug/Exe/target.map" +cmd /c "%tooldir%\objdump -d Debug/Exe/target.axf > Debug/Exe/target.asm" + +for /f "delims=" %%i in ('cmd /c "%tooldir%\grep IMAGE1 Debug/Exe/target.map | %tooldir%\grep Base | %tooldir%\gawk '{print $1}'"') do set ram1_start=0x%%i +for /f "delims=" %%i in ('cmd /c "%tooldir%\grep IMAGE2 Debug/Exe/target.map | %tooldir%\grep Base | %tooldir%\gawk '{print $1}'"') do set ram2_start=0x%%i +for /f "delims=" %%i in ('cmd /c "%tooldir%\grep SDRAM Debug/Exe/target.map | %tooldir%\grep Base | %tooldir%\gawk '{print $1}'"') do set ram3_start=0x%%i +::for /f "delims=" %%i in ('cmd /c "%tooldir%\grep .ram_image4 Debug/Exe/target.map | %tooldir%\grep Base | %tooldir%\gawk '{print $1}'"') do set ram4_start=0x%%i + +for /f "delims=" %%i in ('cmd /c "%tooldir%\grep IMAGE1 Debug/Exe/target.map | %tooldir%\grep Limit | %tooldir%\gawk '{print $1}'"') do set ram1_end=0x%%i +for /f "delims=" %%i in ('cmd /c "%tooldir%\grep IMAGE2 Debug/Exe/target.map | %tooldir%\grep Limit | %tooldir%\gawk '{print $1}'"') do set ram2_end=0x%%i +for /f "delims=" %%i in ('cmd /c "%tooldir%\grep SDRAM Debug/Exe/target.map | %tooldir%\grep Limit | %tooldir%\gawk '{print $1}'"') do set ram3_end=0x%%i +::for /f "delims=" %%i in ('cmd /c "%tooldir%\grep .ram_image4 Debug/Exe/target.map | %tooldir%\grep Limit | %tooldir%\gawk '{print $1}'"') do set ram4_end=0x%%i + +::echo %ram1_start% > tmp.txt +::echo %ram2_start% >> tmp.txt +::echo %ram3_start% >> tmp.txt +::echo %ram1_end% >> tmp.txt +::echo %ram2_end% >> tmp.txt +::echo %ram3_end% >> tmp.txt + +%tooldir%\objcopy -j "A2 rw" -Obinary Debug/Exe/target.axf Debug/Exe/ram_1.bin +%tooldir%\objcopy -j "A3 rw" -Obinary Debug/Exe/target.axf Debug/Exe/sdram.bin + +%tooldir%\pick %ram1_start% %ram1_end% Debug\Exe\ram_1.bin Debug\Exe\ram_1.p.bin head +%tooldir%\pick %ram2_start% %ram2_end% Debug\Exe\ram_1.bin Debug\Exe\ram_2.p.bin body +if defined %ram3_start ( +%tooldir%\pick %ram3_start% %ram3_end% Debug\Exe\sdram.bin Debug\Exe\ram_3.p.bin body +) + +:: SDRAM case +if defined %ram3_start ( +copy /b Debug\Exe\ram_1.p.bin+Debug\Exe\ram_2.p.bin+Debug\Exe\ram_3.p.bin Debug\Exe\ram_all.bin +) + +:: NO SDRAM case +if not defined %ram3_start ( +copy /b Debug\Exe\ram_1.p.bin+Debug\Exe\ram_2.p.bin Debug\Exe\ram_all.bin +) + +:: board generator +%tooldir%\..\gen_board.bat %ram2_start% %ram2_end% %ram1_start% + +exit \ No newline at end of file diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/postbuild.vbs b/component/soc/realtek/8195a/misc/iar_utility/common/postbuild.vbs new file mode 100644 index 0000000..af44493 --- /dev/null +++ b/component/soc/realtek/8195a/misc/iar_utility/common/postbuild.vbs @@ -0,0 +1,5 @@ +Dim WshShell + +Set WshShell = WScript.CreateObject("WScript.Shell") + +WshShell.Run "cmd /c "+WScript.Arguments.Item(1)+"\..\..\..\component\soc\realtek\8195a\misc\iar_utility\common\postbuild.bat "+WScript.Arguments.Item(0)+" "+WScript.Arguments.Item(1), 0 \ No newline at end of file diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/postbuild_img1.bat b/component/soc/realtek/8195a/misc/iar_utility/common/postbuild_img1.bat new file mode 100644 index 0000000..87573d4 --- /dev/null +++ b/component/soc/realtek/8195a/misc/iar_utility/common/postbuild_img1.bat @@ -0,0 +1,30 @@ +cd /D %2 +set tooldir=%2\..\..\..\component\soc\realtek\8195a\misc\iar_utility\common\tools +set libdir=%2\..\..\..\component\soc\realtek\8195a\misc\bsp + +del Debug/Exe/bootloader.map Debug/Exe/bootloader.asm *.bin +cmd /c "%tooldir%\nm Debug/Exe/bootloader.axf | %tooldir%\sort > Debug/Exe/bootloader.map" +cmd /c "%tooldir%\objdump -d Debug/Exe/bootloader.axf > Debug/Exe/bootloader.asm" + +for /f "delims=" %%i in ('cmd /c "%tooldir%\grep IMAGE1 Debug/Exe/bootloader.map | %tooldir%\grep Base | %tooldir%\gawk '{print $1}'"') do set ram1_start=0x%%i +for /f "delims=" %%i in ('cmd /c "%tooldir%\grep IMAGE1 Debug/Exe/bootloader.map | %tooldir%\grep Limit | %tooldir%\gawk '{print $1}'"') do set ram1_end=0x%%i + + +::echo %ram1_start% > tmp.txt +::echo %ram2_start% >> tmp.txt +::echo %ram3_start% >> tmp.txt +::echo %ram1_end% >> tmp.txt +::echo %ram2_end% >> tmp.txt +::echo %ram3_end% >> tmp.txt + +%tooldir%\objcopy -j "A2 rw" -Obinary Debug/Exe/bootloader.axf Debug/Exe/ram_1.bin +::%tooldir%\objcopy -j "A3 rw" -Obinary Debug/Exe/bootloader.axf Debug/Exe/sdram.bin + +%tooldir%\pick %ram1_start% %ram1_end% Debug\Exe\ram_1.bin Debug\Exe\ram_1.p.bin head 0xb000 +%tooldir%\pick %ram1_start% %ram1_end% Debug\Exe\ram_1.bin Debug\Exe\ram_1.r.bin raw + +:: update ram_1.p.bin, raw file for application +copy Debug\Exe\ram_1.p.bin %libdir%\image\ram_1.p.bin +copy Debug\Exe\ram_1.r.bin %libdir%\image\ram_1.r.bin + +exit \ No newline at end of file diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/postbuild_img1.vbs b/component/soc/realtek/8195a/misc/iar_utility/common/postbuild_img1.vbs new file mode 100644 index 0000000..cecbede --- /dev/null +++ b/component/soc/realtek/8195a/misc/iar_utility/common/postbuild_img1.vbs @@ -0,0 +1,5 @@ +Dim WshShell + +Set WshShell = WScript.CreateObject("WScript.Shell") + +WshShell.Run "cmd /c "+WScript.Arguments.Item(1)+"\..\..\..\component\soc\realtek\8195a\misc\iar_utility\common\postbuild_img1.bat "+WScript.Arguments.Item(0)+" "+WScript.Arguments.Item(1), 0 \ No newline at end of file diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/postbuild_img2.bat b/component/soc/realtek/8195a/misc/iar_utility/common/postbuild_img2.bat new file mode 100644 index 0000000..da1523c --- /dev/null +++ b/component/soc/realtek/8195a/misc/iar_utility/common/postbuild_img2.bat @@ -0,0 +1,59 @@ +cd /D %2 +set tooldir=%2\..\..\..\component\soc\realtek\8195a\misc\iar_utility\common\tools +set libdir=%2\..\..\..\component\soc\realtek\8195a\misc\bsp + +del Debug/Exe/target.map Debug/Exe/application.asm *.bin +cmd /c "%tooldir%\nm Debug/Exe/application.axf | %tooldir%\sort > Debug/Exe/application.map" +cmd /c "%tooldir%\objdump -d Debug/Exe/application.axf > Debug/Exe/application.asm" + +for /f "delims=" %%i in ('cmd /c "%tooldir%\grep IMAGE2 Debug/Exe/application.map | %tooldir%\grep Base | %tooldir%\gawk '{print $1}'"') do set ram2_start=0x%%i +for /f "delims=" %%i in ('cmd /c "%tooldir%\grep SDRAM Debug/Exe/application.map | %tooldir%\grep Base | %tooldir%\gawk '{print $1}'"') do set ram3_start=0x%%i + +for /f "delims=" %%i in ('cmd /c "%tooldir%\grep IMAGE2 Debug/Exe/application.map | %tooldir%\grep Limit | %tooldir%\gawk '{print $1}'"') do set ram2_end=0x%%i +for /f "delims=" %%i in ('cmd /c "%tooldir%\grep SDRAM Debug/Exe/application.map | %tooldir%\grep Limit | %tooldir%\gawk '{print $1}'"') do set ram3_end=0x%%i + +::echo %ram1_start% > tmp.txt +::echo %ram2_start% >> tmp.txt +::echo %ram3_start% >> tmp.txt +::echo %ram1_end% >> tmp.txt +::echo %ram2_end% >> tmp.txt +::echo %ram3_end% >> tmp.txt + +%tooldir%\objcopy -j "A3 rw" -Obinary Debug/Exe/application.axf Debug/Exe/ram_2.bin +if defined %ram3_start ( + %tooldir%\objcopy -j "A5 rw" -Obinary Debug/Exe/application.axf Debug/Exe/sdram.bin +) + +%tooldir%\pick %ram2_start% %ram2_end% Debug\Exe\ram_2.bin Debug\Exe\ram_2.p.bin body+reset_offset+sig +if defined %ram3_start ( +%tooldir%\pick %ram3_start% %ram3_end% Debug\Exe\sdram.bin Debug\Exe\ram_3.p.bin body+reset_offset +) + +:: check ram_1.p.bin exist, copy default +if not exist Debug\Exe\ram_1.p.bin ( + copy %libdir%\image\ram_1.p.bin Debug\Exe\ram_1.p.bin +) + +::if not exist Debug\Exe\data.p.bin ( +:: copy %tooldir%\..\image\data.p.bin Debug\Exe\data.p.bin +::) + +::padding ram_1.p.bin to 32K+4K+4K+4K, LOADER/RSVD/SYSTEM/CALIBRATION +%tooldir%\padding 44k 0xFF Debug\Exe\ram_1.p.bin + +:: SDRAM case +if defined %ram3_start ( +copy /b Debug\Exe\ram_1.p.bin+Debug\Exe\ram_2.p.bin+Debug\Exe\ram_3.p.bin Debug\Exe\ram_all.bin +copy /b Debug\Exe\ram_2.p.bin+Debug\Exe\ram_3.p.bin Debug\Exe\ota.bin +) + +:: NO SDRAM case +if not defined %ram3_start ( +copy /b Debug\Exe\ram_1.p.bin+Debug\Exe\ram_2.p.bin Debug\Exe\ram_all.bin +copy /b Debug\Exe\ram_2.p.bin Debug\Exe\ota.bin +) + +:: board generator +%tooldir%\..\gen_board_img2.bat %ram2_start% %ram2_end% %ram3_end% + +exit \ No newline at end of file diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/postbuild_img2.vbs b/component/soc/realtek/8195a/misc/iar_utility/common/postbuild_img2.vbs new file mode 100644 index 0000000..4144da9 --- /dev/null +++ b/component/soc/realtek/8195a/misc/iar_utility/common/postbuild_img2.vbs @@ -0,0 +1,5 @@ +Dim WshShell + +Set WshShell = WScript.CreateObject("WScript.Shell") + +WshShell.Run "cmd /c "+WScript.Arguments.Item(1)+"\..\..\..\component\soc\realtek\8195a\misc\iar_utility\common\postbuild_img2.bat "+WScript.Arguments.Item(0)+" "+WScript.Arguments.Item(1), 0 \ No newline at end of file diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/prebuild.bat b/component/soc/realtek/8195a/misc/iar_utility/common/prebuild.bat new file mode 100644 index 0000000..fc09b0a --- /dev/null +++ b/component/soc/realtek/8195a/misc/iar_utility/common/prebuild.bat @@ -0,0 +1,17 @@ +cd /D %1 +:: Generate build_info.h +echo off +::echo %date:~0,10%-%time:~0,8% +::echo %USERNAME% +for /f "usebackq" %%i in (`hostname`) do set hostname=%%i +::echo %hostname% + +echo #define UTS_VERSION "%date:~0,10%-%time:~0,8%" > ..\inc\build_info.h +echo #define RTL8195AFW_COMPILE_TIME "%date:~0,10%-%time:~0,8%" >> ..\inc\build_info.h +echo #define RTL8195AFW_COMPILE_BY "%USERNAME%" >> ..\inc\build_info.h +echo #define RTL8195AFW_COMPILE_HOST "%hostname%" >> ..\inc\build_info.h +echo #define RTL8195AFW_COMPILE_DOMAIN >> ..\inc\build_info.h +echo #define RTL195AFW_COMPILER "IAR compiler" >> ..\inc\build_info.h + +exit + diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/prebuild.vbs b/component/soc/realtek/8195a/misc/iar_utility/common/prebuild.vbs new file mode 100644 index 0000000..3873489 --- /dev/null +++ b/component/soc/realtek/8195a/misc/iar_utility/common/prebuild.vbs @@ -0,0 +1,5 @@ +Dim WshShell + +Set WshShell = WScript.CreateObject("WScript.Shell") + +WshShell.Run "cmd /c "+WScript.Arguments.Item(0)+"\..\..\..\component\soc\realtek\8195a\misc\iar_utility\common\prebuild.bat "+WScript.Arguments.Item(0), 0 \ No newline at end of file diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/preload.dap.mac b/component/soc/realtek/8195a/misc/iar_utility/common/preload.dap.mac new file mode 100644 index 0000000..613b841 --- /dev/null +++ b/component/soc/realtek/8195a/misc/iar_utility/common/preload.dap.mac @@ -0,0 +1,372 @@ +//DRAM_INFO +__var DeviceType; +__var Page; +__var Bank; +__var DqWidth; + +//DRAM_MODE_REG_INFO +__var BstLen; +__var BstType; +__var Mode0Cas; +__var Mode0Wr; +__var Mode1DllEnN; +__var Mode1AllLat; +__var Mode2Cwl; + +//DRAM_TIMING_INFO, additional parameter, to config DRAM_TIMING INFO +__var DramTimingTref; +__var DramRowNum; +__var Tck; + +//DRAM_TIMING_INFO +__var TrfcPs; +__var TrefiPs; +__var WrMaxTck; +__var TrcdPs; +__var TrpPs; +__var TrasPs; +__var TrrdTck; +__var TwrPs; +__var TwtrTck; +__var TmrdTck; +__var TrtpTck; +__var TccdTck; +__var TrcPs; + +//DRAM_DEVICE_INFO +__var DdrPeriodPs; +__var DfiRate; + +__config_dram_param(){ + __var CsBstLen; + __var CasWr; + __var CasRd; + __var CasRdT; + __var ClrSrt; + __var AddLat; + __var DramEmr2; + __var DramMr0; + __var CrTwr; + __var DramMaxWr; + __var DramWr; + __var CrTrtw; + __var CrTrtwT; + __var DramPeriod; + __var DdrType; + //__var paDqWidth; + //__var paPage; + //__var paDfiRate + + __var tmp; + + // Register dram common.mac + //__registerMacroFile("$PROJ_DIR$\\..\\..\\..\\component\\soc\\realtek\\8195a\\misc\\iar_utility\\common\\dram\\common.mac"); + __load_dram_common(); + + // Load parameter + __load_dram_param(); + + DfiRate = 1<> 1); + if (((Mode0Cas) & 0x1) ) { + CasRdT = CrlSrt+ 12; + }else{ + CasRdT = CrlSrt+ 4; + } + + AddLat = 0; + if (Mode1AllLat == 1) { // CL-1 + AddLat = CasRd -1; + } + if (Mode1AllLat == 2){ // CL-2 + AddLat = CasRd -2; + } + CasRd = CasRdT + AddLat; + CasWr = Mode2Cwl + 5 + AddLat; + DramEmr2 = Mode2Cwl << 3; + + DramWr = (DramWr + 1) / 2; + if (DramWr == 16) { + DramWr = 0; + } + if (DramWr <= 9) { // 5< wr <= 9 + DramWr = DramWr - 4; + } + DramMr0 =(DramWr<<(8+1))|(0<<8)|((Mode0Cas>>1)<<4)|(BstType<<3)|((Mode0Cas&0x1)<<2)|DramMr0; + CrTrtwT = (CasRdT + 6) - CasWr; + } + if (DeviceType == 8){ + DdrType = 8; + if (BstLen == 0) { + DramMr0 = 2; // bst_4 + CsBstLen = 0; //bst_4 + CasRd = 0x2; + } else { + DramMr0 = 3; // bst_8 + CsBstLen = 1; // bst_8 + CasRd = 0x3; + } + CasWr = 0; + DramMr0 =(CasRd<<4)|(BstType<<3)|DramMr0; + CrTrtwT = 0; // tic: CasRd + rd_rtw + rd_pipe + } + + // countting tRTW + if ((CrTrtwT & 0x1)) { + CrTrtw = (CrTrtwT+1) /(DfiRate); + } else { + CrTrtw = CrTrtwT /(DfiRate); + } + + DqWidth = DqWidth; + Page = Page +1; // DQ16 -> memory:byte_unit *2 + if (DqWidth == 1) { // paralle dq_16 => Page + 1 + Page = Page +1; + } + + // REG_SDR_MISC + tmp =(Page<<0)|(Bank<<4)|(CsBstLen<<6)|(DqWidth<<8); + __writeMemory32(tmp, 0x40005224, "Memory"); __delay(10); + // REG_SDR_DCR + tmp =(0x2<<8)|(DqWidth<<4)|(DdrType<<0); + __writeMemory32(tmp, 0x40005004, "Memory"); __delay(10); + // REG_SDR_IOCR + tmp =((CasRd-4)/(DfiRate)<<20)|(0<<17)|(((CasWr-3)/(DfiRate))<<12)|(0<<8); + __writeMemory32(tmp, 0x40005008, "Memory"); __delay(10); + if(DeviceType != 8){ + tmp =DramEmr2; + __writeMemory32(tmp, 0x40005028, "Memory"); __delay(10); + tmp =(1<<2)|(1<<1)|(Mode1DllEnN); + __writeMemory32(tmp, 0x40005024, "Memory"); __delay(10); + } + tmp =DramMr0; + __writeMemory32(tmp, 0x40005020, "Memory"); __delay(10); + tmp =(0<<28)|(9<<24)|((((TrefiPs)/DramPeriod)+1)<<8)|((((TrfcPs)/DramPeriod)+1)<<0); + __writeMemory32(tmp, 0x40005010, "Memory"); __delay(10); + tmp =((((TrtpTck)/DfiRate)+1)<<13)|(CrTwr<<9)|((((TrasPs)/DramPeriod)+1)<<4)|((((TrpPs)/DramPeriod)+1)<<0); + __writeMemory32(tmp, 0x40005014, "Memory"); __delay(10); + tmp =(CrTrtw << 20) | + ((((TwtrTck)/DfiRate)+3) << 17) | + ((((TccdTck)/DfiRate)+1) << 14) | + ((((TrcdPs)/DramPeriod)+1) << 10) | + ((((TrcPs)/DramPeriod)+1) << 4 ) | + (((TrrdTck/DfiRate)+1) << 0); + __writeMemory32(tmp, 0x40005018, "Memory"); __delay(10); + tmp =(TmrdTck<<5)|(0<<4)|(2<<0); + __writeMemory32(tmp, 0x4000501c, "Memory"); __delay(10); + // Set Idle + __writeMemory32(0x700, 0x4000500c, "Memory"); __delay(10); + // start init + __writeMemory32(0x1, 0x40005000, "Memory"); __delay(100); + tmp = __readMemory32(0x40005000,"Memory"); __delay(10); + // enter memory mode + __writeMemory32(0x600, 0x4000500c, "Memory"); __delay(10); +} + +__config_dram_param_fixed(){ + __var tmp; + // Dram Attribute + __writeMemory32(0x1, 0x40005224, "Memory"); __delay(10); + __writeMemory32(0x2c8, 0x40005004, "Memory"); __delay(10); + __writeMemory32(0xffffd000, 0x40005008, "Memory"); __delay(10); + __delay(3); + __writeMemory32(0x22, 0x40005020, "Memory"); __delay(10); + __delay(3); + __writeMemory32(0x09032001, 0x40005010, "Memory"); __delay(10); + __delay(3); + __writeMemory32(0x2611, 0x40005014, "Memory"); __delay(10); + __delay(3); + __writeMemory32(0x68413, 0x40005018, "Memory"); __delay(10); + __delay(3); + __writeMemory32(0x42, 0x4000501c, "Memory"); __delay(10); + __delay(3); + + // Enable + __writeMemory32(0x700, 0x4000500c, "Memory"); __delay(10); + __delay(20); + __writeMemory32(0x1, 0x40005000, "Memory"); __delay(10); + __delay(100); + tmp = __readMemory32(0x40005000,"Memory"); __delay(10); + __writeMemory32(0x600, 0x4000500c, "Memory"); __delay(10); + __delay(30); +} + +__mem_test(){ + __var i; + __var vaddr; + __var tmp; + + i=0; + while(i<10){ + vaddr = 0x30000000+((i*23)&0x1FFFFC); + __writeMemory32(0x55AA55AA, vaddr, "Memory"); + tmp = __readMemory32(vaddr,"Memory"); + if(tmp!=0x55AA55AA) + return 1; + i=i+1; + } + return 0; +} + +__var ok_pipe_id0; +__var ok_pipe_id1; +__var ok_tpc_min0; +__var ok_tpc_max0; +__var ok_tpc_min1; +__var ok_tpc_max1; +__var tpc0_cnt; +__var tpc1_cnt; + +// calibration result +__var isCalibrationDone; + +__dram_calibration(){ + __var rdp; + __var tpc; + __var rdp_reg; + __var tpc_reg; + __var err_cnt; + __var ok_cnt; + + + ok_cnt=0; + ok_pipe_id0 = 15; + ok_tpc_min0 = 12; + ok_tpc_max0 = 0; + + rdp_reg = __readMemory32(0x40005008,"Memory")&0xFFFF00FF; + tpc_reg = __readMemory32(0x40000300,"Memory")&0xFF00FFFF; + for(rdp=0;(rdp<=7)&&(err_cnt==0||ok_cnt==0);rdp++){ + err_cnt=0; + // try pipe + __writeMemory32(rdp_reg|rdp<<8,0x40005008, "Memory");__delay(10); + for(tpc=0;(tpc<=12)&&(err_cnt<2);tpc++){ + // try tpc + __writeMemory32(tpc_reg|tpc<<16,0x40000300, "Memory");__delay(10); + if(__mem_test()==0){ + if(ok_pipe_id0==15) {ok_pipe_id0 = rdp; ok_cnt++;} + if(ok_tpc_min0>tpc) ok_tpc_min0 = tpc; + if(ok_tpc_max0tpc0_cnt){ + __writeMemory32(rdp_reg|ok_pipe_id1<<8,0x40005008, "Memory");__delay(10); + __writeMemory32(tpc_reg|(tpc1_cnt/2)<<16,0x40000300, "Memory");__delay(10); + }else{ + __writeMemory32(rdp_reg|ok_pipe_id0<<8,0x40005008, "Memory");__delay(10); + __writeMemory32(tpc_reg|(tpc0_cnt/2)<<16,0x40000300, "Memory");__delay(10); + } +} + +__setup_system() +{ + __var tmp; + + __hwReset(1); + + __writeMemory32(0x21, 0x40000014, "Memory"); __delay(10); + __writeMemory32(0x1FC00002, 0x40000304, "Memory"); __delay(10); + __writeMemory32(0x400, 0x40000250, "Memory"); __delay(10); + __writeMemory32(0x0, 0x40000340, "Memory"); __delay(10); + __writeMemory32(0xdcc4, 0x40000230, "Memory"); __delay(10); + __writeMemory32(0x11117, 0x40000210, "Memory"); __delay(10); + __writeMemory32(0x11157, 0x40000210, "Memory"); __delay(10); + __writeMemory32(0x110011, 0x400002c0, "Memory"); __delay(10); + __writeMemory32(0xffffffff, 0x40000320, "Memory"); __delay(10); + + __config_dram_param(); + + if(isCalibrationDone){ + __var rdp_reg; + __var tpc_reg; + rdp_reg = __readMemory32(0x40005008,"Memory")&0xFFFF00FF; + tpc_reg = __readMemory32(0x40000300,"Memory")&0xFF00FFFF; + if(tpc1_cnt>tpc0_cnt){ + __writeMemory32(rdp_reg|ok_pipe_id1<<8,0x40005008, "Memory");__delay(10); + __writeMemory32(tpc_reg|(tpc1_cnt/2)<<16,0x40000300, "Memory");__delay(10); + }else{ + __writeMemory32(rdp_reg|ok_pipe_id0<<8,0x40005008, "Memory");__delay(10); + __writeMemory32(tpc_reg|(tpc0_cnt/2)<<16,0x40000300, "Memory");__delay(10); + } + }else{ + // Calibration + __dram_calibration(); + isCalibrationDone = 1; + } +} + +execUserPreload() +{ + // Register dram common.mac + __registerMacroFile("$PROJ_DIR$\\..\\..\\..\\component\\soc\\realtek\\8195a\\misc\\iar_utility\\common\\dram\\common.mac"); + + __message "User Preload...."; + //isCalibrationDone = 0; + __setup_system(); +} + +execUserSetup() +{ + __var tmp; + __message "User Setup...."; + // if use normal reset, please unmark those 2 lines + //execUserPreload(); + __setup_system(); + //__loadImage("$TARGET_PATH$", 0, 0); + // DISABLE DRAM init + tmp = __readMemory32(0x40000210, "Memory")|(1<<21); + __writeMemory32(tmp, 0x40000210, "Memory"); +} \ No newline at end of file diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/preload.mac b/component/soc/realtek/8195a/misc/iar_utility/common/preload.mac new file mode 100644 index 0000000..96f4b85 --- /dev/null +++ b/component/soc/realtek/8195a/misc/iar_utility/common/preload.mac @@ -0,0 +1,382 @@ +//DRAM_INFO +__var DeviceType; +__var Page; +__var Bank; +__var DqWidth; + +//DRAM_MODE_REG_INFO +__var BstLen; +__var BstType; +__var Mode0Cas; +__var Mode0Wr; +__var Mode1DllEnN; +__var Mode1AllLat; +__var Mode2Cwl; + +//DRAM_TIMING_INFO, additional parameter, to config DRAM_TIMING INFO +__var DramTimingTref; +__var DramRowNum; +__var Tck; + +//DRAM_TIMING_INFO +__var TrfcPs; +__var TrefiPs; +__var WrMaxTck; +__var TrcdPs; +__var TrpPs; +__var TrasPs; +__var TrrdTck; +__var TwrPs; +__var TwtrTck; +__var TmrdTck; +__var TrtpTck; +__var TccdTck; +__var TrcPs; + +//DRAM_DEVICE_INFO +__var DdrPeriodPs; +__var DfiRate; + +__config_dram_param(){ + __var CsBstLen; + __var CasWr; + __var CasRd; + __var CasRdT; + __var ClrSrt; + __var AddLat; + __var DramEmr2; + __var DramMr0; + __var CrTwr; + __var DramMaxWr; + __var DramWr; + __var CrTrtw; + __var CrTrtwT; + __var DramPeriod; + __var DdrType; + //__var paDqWidth; + //__var paPage; + //__var paDfiRate + + __var tmp; + + // Register dram common.mac + //__registerMacroFile("$PROJ_DIR$\\..\\..\\..\\component\\soc\\realtek\\8195a\\misc\\iar_utility\\common\\dram\\common.mac"); + __load_dram_common(); + + // Load parameter + __load_dram_param(); + + DfiRate = 1<> 1); + if (((Mode0Cas) & 0x1) ) { + CasRdT = CrlSrt+ 12; + }else{ + CasRdT = CrlSrt+ 4; + } + + AddLat = 0; + if (Mode1AllLat == 1) { // CL-1 + AddLat = CasRd -1; + } + if (Mode1AllLat == 2){ // CL-2 + AddLat = CasRd -2; + } + CasRd = CasRdT + AddLat; + CasWr = Mode2Cwl + 5 + AddLat; + DramEmr2 = Mode2Cwl << 3; + + DramWr = (DramWr + 1) / 2; + if (DramWr == 16) { + DramWr = 0; + } + if (DramWr <= 9) { // 5< wr <= 9 + DramWr = DramWr - 4; + } + DramMr0 =(DramWr<<(8+1))|(0<<8)|((Mode0Cas>>1)<<4)|(BstType<<3)|((Mode0Cas&0x1)<<2)|DramMr0; + CrTrtwT = (CasRdT + 6) - CasWr; + } + if (DeviceType == 8){ + DdrType = 8; + if (BstLen == 0) { + DramMr0 = 2; // bst_4 + CsBstLen = 0; //bst_4 + CasRd = 0x2; + } else { + DramMr0 = 3; // bst_8 + CsBstLen = 1; // bst_8 + CasRd = 0x3; + } + CasWr = 0; + DramMr0 =(CasRd<<4)|(BstType<<3)|DramMr0; + CrTrtwT = 0; // tic: CasRd + rd_rtw + rd_pipe + } + + // countting tRTW + if ((CrTrtwT & 0x1)) { + CrTrtw = (CrTrtwT+1) /(DfiRate); + } else { + CrTrtw = CrTrtwT /(DfiRate); + } + + DqWidth = DqWidth; + Page = Page +1; // DQ16 -> memory:byte_unit *2 + if (DqWidth == 1) { // paralle dq_16 => Page + 1 + Page = Page +1; + } + + // REG_SDR_MISC + tmp =(Page<<0)|(Bank<<4)|(CsBstLen<<6)|(DqWidth<<8); + __writeMemory32(tmp, 0x40005224, "Memory"); __delay(10); + // REG_SDR_DCR + tmp =(0x2<<8)|(DqWidth<<4)|(DdrType<<0); + __writeMemory32(tmp, 0x40005004, "Memory"); __delay(10); + // REG_SDR_IOCR + tmp =((CasRd-4)/(DfiRate)<<20)|(0<<17)|(((CasWr-3)/(DfiRate))<<12)|(0<<8); + __writeMemory32(tmp, 0x40005008, "Memory"); __delay(10); + if(DeviceType != 8){ + tmp =DramEmr2; + __writeMemory32(tmp, 0x40005028, "Memory"); __delay(10); + tmp =(1<<2)|(1<<1)|(Mode1DllEnN); + __writeMemory32(tmp, 0x40005024, "Memory"); __delay(10); + } + tmp =DramMr0; + __writeMemory32(tmp, 0x40005020, "Memory"); __delay(10); + tmp =(0<<28)|(9<<24)|((((TrefiPs)/DramPeriod)+1)<<8)|((((TrfcPs)/DramPeriod)+1)<<0); + __writeMemory32(tmp, 0x40005010, "Memory"); __delay(10); + tmp =((((TrtpTck)/DfiRate)+1)<<13)|(CrTwr<<9)|((((TrasPs)/DramPeriod)+1)<<4)|((((TrpPs)/DramPeriod)+1)<<0); + __writeMemory32(tmp, 0x40005014, "Memory"); __delay(10); + tmp =(CrTrtw << 20) | + ((((TwtrTck)/DfiRate)+3) << 17) | + ((((TccdTck)/DfiRate)+1) << 14) | + ((((TrcdPs)/DramPeriod)+1) << 10) | + ((((TrcPs)/DramPeriod)+1) << 4 ) | + (((TrrdTck/DfiRate)+1) << 0); + __writeMemory32(tmp, 0x40005018, "Memory"); __delay(10); + tmp =(TmrdTck<<5)|(0<<4)|(2<<0); + __writeMemory32(tmp, 0x4000501c, "Memory"); __delay(10); + // Set Idle + __writeMemory32(0x700, 0x4000500c, "Memory"); __delay(10); + // start init + __writeMemory32(0x1, 0x40005000, "Memory"); __delay(100); + tmp = __readMemory32(0x40005000,"Memory"); __delay(10); + // enter memory mode + __writeMemory32(0x600, 0x4000500c, "Memory"); __delay(10); +} + +__config_dram_param_fixed(){ + __var tmp; + // Dram Attribute + __writeMemory32(0x1, 0x40005224, "Memory"); __delay(10); + __writeMemory32(0x2c8, 0x40005004, "Memory"); __delay(10); + __writeMemory32(0xffffd000, 0x40005008, "Memory"); __delay(10); + __delay(3); + __writeMemory32(0x22, 0x40005020, "Memory"); __delay(10); + __delay(3); + __writeMemory32(0x09032001, 0x40005010, "Memory"); __delay(10); + __delay(3); + __writeMemory32(0x2611, 0x40005014, "Memory"); __delay(10); + __delay(3); + __writeMemory32(0x68413, 0x40005018, "Memory"); __delay(10); + __delay(3); + __writeMemory32(0x42, 0x4000501c, "Memory"); __delay(10); + __delay(3); + + // Enable + __writeMemory32(0x700, 0x4000500c, "Memory"); __delay(10); + __delay(20); + __writeMemory32(0x1, 0x40005000, "Memory"); __delay(10); + __delay(100); + tmp = __readMemory32(0x40005000,"Memory"); __delay(10); + __writeMemory32(0x600, 0x4000500c, "Memory"); __delay(10); + __delay(30); +} + +__mem_test(){ + __var i; + __var vaddr; + __var tmp; + + i=0; + while(i<10){ + vaddr = 0x30000000+((i*23)&0x1FFFFC); + __writeMemory32(0x55AA55AA, vaddr, "Memory"); + tmp = __readMemory32(vaddr,"Memory"); + if(tmp!=0x55AA55AA) + return 1; + i=i+1; + } + return 0; +} + +__var ok_pipe_id0; +__var ok_pipe_id1; +__var ok_tpc_min0; +__var ok_tpc_max0; +__var ok_tpc_min1; +__var ok_tpc_max1; +__var tpc0_cnt; +__var tpc1_cnt; + +// calibration result +__var isCalibrationDone; + +__dram_calibration(){ + __var rdp; + __var tpc; + __var rdp_reg; + __var tpc_reg; + __var err_cnt; + __var ok_cnt; + + + ok_cnt=0; + ok_pipe_id0 = 15; + ok_tpc_min0 = 12; + ok_tpc_max0 = 0; + + rdp_reg = __readMemory32(0x40005008,"Memory")&0xFFFF00FF; + tpc_reg = __readMemory32(0x40000300,"Memory")&0xFF00FFFF; + for(rdp=0;(rdp<=7)&&(err_cnt==0||ok_cnt==0);rdp++){ + err_cnt=0; + // try pipe + __writeMemory32(rdp_reg|rdp<<8,0x40005008, "Memory");__delay(10); + for(tpc=0;(tpc<=12)&&(err_cnt<2);tpc++){ + // try tpc + __writeMemory32(tpc_reg|tpc<<16,0x40000300, "Memory");__delay(10); + if(__mem_test()==0){ + if(ok_pipe_id0==15) {ok_pipe_id0 = rdp; ok_cnt++;} + if(ok_tpc_min0>tpc) ok_tpc_min0 = tpc; + if(ok_tpc_max0tpc0_cnt){ + __writeMemory32(rdp_reg|ok_pipe_id1<<8,0x40005008, "Memory");__delay(10); + __writeMemory32(tpc_reg|(tpc1_cnt/2)<<16,0x40000300, "Memory");__delay(10); + }else{ + __writeMemory32(rdp_reg|ok_pipe_id0<<8,0x40005008, "Memory");__delay(10); + __writeMemory32(tpc_reg|(tpc0_cnt/2)<<16,0x40000300, "Memory");__delay(10); + } +} + +__setup_system() +{ + __var tmp; + + __hwReset(1); + + __writeMemory32(0x21, 0x40000014, "Memory"); __delay(10); + __writeMemory32(0x1FC00002, 0x40000304, "Memory"); __delay(10); + __writeMemory32(0x400, 0x40000250, "Memory"); __delay(10); + __writeMemory32(0x0, 0x40000340, "Memory"); __delay(10); + __writeMemory32(0xdcc4, 0x40000230, "Memory"); __delay(10); + __writeMemory32(0x11117, 0x40000210, "Memory"); __delay(10); + __writeMemory32(0x11157, 0x40000210, "Memory"); __delay(10); + __writeMemory32(0x110011, 0x400002c0, "Memory"); __delay(10); + __writeMemory32(0xffffffff, 0x40000320, "Memory"); __delay(10); + + __config_dram_param(); + + if(isCalibrationDone){ + __var rdp_reg; + __var tpc_reg; + rdp_reg = __readMemory32(0x40005008,"Memory")&0xFFFF00FF; + tpc_reg = __readMemory32(0x40000300,"Memory")&0xFF00FFFF; + if(tpc1_cnt>tpc0_cnt){ + __writeMemory32(rdp_reg|ok_pipe_id1<<8,0x40005008, "Memory");__delay(10); + __writeMemory32(tpc_reg|(tpc1_cnt/2)<<16,0x40000300, "Memory");__delay(10); + }else{ + __writeMemory32(rdp_reg|ok_pipe_id0<<8,0x40005008, "Memory");__delay(10); + __writeMemory32(tpc_reg|(tpc0_cnt/2)<<16,0x40000300, "Memory");__delay(10); + } + }else{ + // Calibration + __dram_calibration(); + isCalibrationDone = 1; + } +} + +execUserPreload() +{ + // Register dram common.mac + __registerMacroFile("$PROJ_DIR$\\..\\..\\..\\component\\soc\\realtek\\8195a\\misc\\iar_utility\\common\\dram\\common.mac"); + + __message "User Preload...."; + if(__driverType("jlink")){ + __message "driver type J-LINK"; + isCalibrationDone = 0; + }else if(__driverType("cmsisdap")){ + __message "driver type CMSIS-DAP"; + } + __setup_system(); +} + +execUserSetup() +{ + __var tmp; + __message "User Setup...."; + // if use normal reset, please unmark those 2 lines + //execUserPreload(); + __setup_system(); + if(__driverType("jlink")){ + __loadImage("$TARGET_PATH$ ", 0, 0); + tmp = __readMemory32(0x40000210, "Memory")|(1<<27); + }else if(__driverType("cmsisdap")){ + tmp = __readMemory32(0x40000210, "Memory")|(1<<21); + }else{ + __message "Not support drive type"; + } + __writeMemory32(tmp, 0x40000210, "Memory"); +} \ No newline at end of file diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/tools/cyggcc_s-1.dll b/component/soc/realtek/8195a/misc/iar_utility/common/tools/cyggcc_s-1.dll new file mode 100644 index 0000000..1c5e62c Binary files /dev/null and b/component/soc/realtek/8195a/misc/iar_utility/common/tools/cyggcc_s-1.dll differ diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/tools/cyggmp-10.dll b/component/soc/realtek/8195a/misc/iar_utility/common/tools/cyggmp-10.dll new file mode 100644 index 0000000..ef02f64 Binary files /dev/null and b/component/soc/realtek/8195a/misc/iar_utility/common/tools/cyggmp-10.dll differ diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/tools/cygiconv-2.dll b/component/soc/realtek/8195a/misc/iar_utility/common/tools/cygiconv-2.dll new file mode 100644 index 0000000..e824d2d Binary files /dev/null and b/component/soc/realtek/8195a/misc/iar_utility/common/tools/cygiconv-2.dll differ diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/tools/cygintl-8.dll b/component/soc/realtek/8195a/misc/iar_utility/common/tools/cygintl-8.dll new file mode 100644 index 0000000..fa08150 Binary files /dev/null and b/component/soc/realtek/8195a/misc/iar_utility/common/tools/cygintl-8.dll differ diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/tools/cygmpfr-4.dll b/component/soc/realtek/8195a/misc/iar_utility/common/tools/cygmpfr-4.dll new file mode 100644 index 0000000..253c6c6 Binary files /dev/null and b/component/soc/realtek/8195a/misc/iar_utility/common/tools/cygmpfr-4.dll differ diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/tools/cygncursesw-10.dll b/component/soc/realtek/8195a/misc/iar_utility/common/tools/cygncursesw-10.dll new file mode 100644 index 0000000..2f30a91 Binary files /dev/null and b/component/soc/realtek/8195a/misc/iar_utility/common/tools/cygncursesw-10.dll differ diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/tools/cygpcre-1.dll b/component/soc/realtek/8195a/misc/iar_utility/common/tools/cygpcre-1.dll new file mode 100644 index 0000000..de39d78 Binary files /dev/null and b/component/soc/realtek/8195a/misc/iar_utility/common/tools/cygpcre-1.dll differ diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/tools/cygreadline7.dll b/component/soc/realtek/8195a/misc/iar_utility/common/tools/cygreadline7.dll new file mode 100644 index 0000000..0c9603f Binary files /dev/null and b/component/soc/realtek/8195a/misc/iar_utility/common/tools/cygreadline7.dll differ diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/tools/cygwin1.dll b/component/soc/realtek/8195a/misc/iar_utility/common/tools/cygwin1.dll new file mode 100644 index 0000000..0492dcc Binary files /dev/null and b/component/soc/realtek/8195a/misc/iar_utility/common/tools/cygwin1.dll differ diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/tools/cygz.dll b/component/soc/realtek/8195a/misc/iar_utility/common/tools/cygz.dll new file mode 100644 index 0000000..29d3bff Binary files /dev/null and b/component/soc/realtek/8195a/misc/iar_utility/common/tools/cygz.dll differ diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/tools/gawk.exe b/component/soc/realtek/8195a/misc/iar_utility/common/tools/gawk.exe new file mode 100644 index 0000000..6890ed1 Binary files /dev/null and b/component/soc/realtek/8195a/misc/iar_utility/common/tools/gawk.exe differ diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/tools/grep.exe b/component/soc/realtek/8195a/misc/iar_utility/common/tools/grep.exe new file mode 100644 index 0000000..1e8308b Binary files /dev/null and b/component/soc/realtek/8195a/misc/iar_utility/common/tools/grep.exe differ diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/tools/nm.exe b/component/soc/realtek/8195a/misc/iar_utility/common/tools/nm.exe new file mode 100644 index 0000000..7091e7a Binary files /dev/null and b/component/soc/realtek/8195a/misc/iar_utility/common/tools/nm.exe differ diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/tools/objcopy.exe b/component/soc/realtek/8195a/misc/iar_utility/common/tools/objcopy.exe new file mode 100644 index 0000000..e27f101 Binary files /dev/null and b/component/soc/realtek/8195a/misc/iar_utility/common/tools/objcopy.exe differ diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/tools/objdump.exe b/component/soc/realtek/8195a/misc/iar_utility/common/tools/objdump.exe new file mode 100644 index 0000000..3496453 Binary files /dev/null and b/component/soc/realtek/8195a/misc/iar_utility/common/tools/objdump.exe differ diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/tools/padding.exe b/component/soc/realtek/8195a/misc/iar_utility/common/tools/padding.exe new file mode 100644 index 0000000..c737002 Binary files /dev/null and b/component/soc/realtek/8195a/misc/iar_utility/common/tools/padding.exe differ diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/tools/pick.exe b/component/soc/realtek/8195a/misc/iar_utility/common/tools/pick.exe new file mode 100644 index 0000000..460132d Binary files /dev/null and b/component/soc/realtek/8195a/misc/iar_utility/common/tools/pick.exe differ diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/tools/sort.exe b/component/soc/realtek/8195a/misc/iar_utility/common/tools/sort.exe new file mode 100644 index 0000000..8f7413d Binary files /dev/null and b/component/soc/realtek/8195a/misc/iar_utility/common/tools/sort.exe differ diff --git a/component/soc/realtek/8195a/misc/iar_utility/common/tools/strip.exe b/component/soc/realtek/8195a/misc/iar_utility/common/tools/strip.exe new file mode 100644 index 0000000..fa020ca Binary files /dev/null and b/component/soc/realtek/8195a/misc/iar_utility/common/tools/strip.exe differ diff --git a/component/soc/realtek/common/bsp/basic_types.h b/component/soc/realtek/common/bsp/basic_types.h new file mode 100644 index 0000000..0a38a92 --- /dev/null +++ b/component/soc/realtek/common/bsp/basic_types.h @@ -0,0 +1,497 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * + ******************************************************************************/ +#ifndef __BASIC_TYPES_H__ +#define __BASIC_TYPES_H__ + +//#define PLATFORM_FREERTOS +#include + +#define PLATFORM_LITTLE_ENDIAN 0 +#define PLATFORM_BIG_ENDIAN 1 + +#define SYSTEM_ENDIAN PLATFORM_LITTLE_ENDIAN + +#define SUCCESS 0 +#define FAIL (-1) + +#undef _SUCCESS +#define _SUCCESS 1 + +#undef _FAIL +#define _FAIL 0 + +#ifndef FALSE + #define FALSE 0 +#endif + +#ifndef TRUE + #define TRUE (!FALSE) +#endif + +#define _TRUE TRUE +#define _FALSE FALSE + +#ifndef NULL +#define NULL 0 +#endif + +#ifdef __GNUC__ +#define __weak __attribute__((weak)) +#define likely(x) __builtin_expect ((x), 1) +#define unlikely(x) __builtin_expect ((x), 0) +#endif + +typedef unsigned int uint; +typedef signed int sint; + +#ifdef __ICCARM__ +typedef signed long long __int64_t; +typedef unsigned long long __uint64_t; +#endif + +#define s8 int8_t +#define u8 uint8_t +#define s16 int16_t +#define u16 uint16_t +#define s32 int32_t +#define u32 uint32_t +#define s64 int64_t +#define u64 uint64_t + +#ifdef CONFIG_MBED_ENABLED +typedef unsigned int BOOL; +#else +#ifndef BOOL +typedef unsigned char BOOL; +#endif +#ifndef bool +typedef unsigned char bool; +#endif +#endif + +#define UCHAR uint8_t +#define USHORT uint16_t +#define UINT uint32_t +#define ULONG uint32_t + +typedef struct { volatile int counter; } atomic_t; + +typedef enum _RTK_STATUS_ { + _EXIT_SUCCESS = 0, + _EXIT_FAILURE = 1 +}RTK_STATUS, *PRTK_STATUS; + +#define IN +#define OUT +#define VOID void +#define INOUT +#define NDIS_OID uint +#define NDIS_STATUS uint + +#ifndef PVOID +typedef void * PVOID; +#endif + +typedef u32 dma_addr_t; + +typedef void (*proc_t)(void*); + +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; + +typedef __kernel_size_t SIZE_T; +typedef __kernel_ssize_t SSIZE_T; +#define FIELD_OFFSET(s,field) ((SSIZE_T)&((s*)(0))->field) + +#define MEM_ALIGNMENT_OFFSET (sizeof (SIZE_T)) +#define MEM_ALIGNMENT_PADDING (sizeof(SIZE_T) - 1) + +#define SIZE_PTR SIZE_T +#define SSIZE_PTR SSIZE_T + +#ifndef ON +#define ON 1 +#endif + +#ifndef OFF +#define OFF 0 +#endif + +#ifndef ENABLE +#define ENABLE 1 +#endif + +#ifndef DISABLE +#define DISABLE 0 +#endif + + +#define BIT0 0x0001 +#define BIT1 0x0002 +#define BIT2 0x0004 +#define BIT3 0x0008 +#define BIT4 0x0010 +#define BIT5 0x0020 +#define BIT6 0x0040 +#define BIT7 0x0080 +#define BIT8 0x0100 +#define BIT9 0x0200 +#define BIT10 0x0400 +#define BIT11 0x0800 +#define BIT12 0x1000 +#define BIT13 0x2000 +#define BIT14 0x4000 +#define BIT15 0x8000 +#define BIT16 0x00010000 +#define BIT17 0x00020000 +#define BIT18 0x00040000 +#define BIT19 0x00080000 +#define BIT20 0x00100000 +#define BIT21 0x00200000 +#define BIT22 0x00400000 +#define BIT23 0x00800000 +#define BIT24 0x01000000 +#define BIT25 0x02000000 +#define BIT26 0x04000000 +#define BIT27 0x08000000 +#define BIT28 0x10000000 +#define BIT29 0x20000000 +#define BIT30 0x40000000 +#define BIT31 0x80000000 + +#define BIT_(__n) (1<<(__n)) + +#ifndef BIT +#define BIT(__n) (1<<(__n)) +#endif + +#if defined (__ICCARM__) +#define STRINGIFY(s) #s +#define SECTION(_name) _Pragma( STRINGIFY(location=##_name##)) +#define ALIGNMTO(_bound) _Pragma( STRINGIFY(data_alignment=##_bound##)) +#define _PACKED_ _Pragma( STRINGIFY(pack)) +#define _LONG_CALL_ +#define _WEAK __weak +#else +#define SECTION(_name) __attribute__ ((__section__(_name))) +#define ALIGNMTO(_bound) __attribute__ ((aligned (_bound))) +#define _PACKED_ __attribute__ ((packed)) +#define _LONG_CALL_ __attribute__ ((long_call)) +#define _WEAK __attribute__ ((weak)) +#endif + + + +//port from fw by thomas +// TODO: Belows are Sync from SD7-Driver. It is necessary to check correctness + +#define SWAP32(x) ((u32)( \ + (((u32)(x) & (u32)0x000000ff) << 24) | \ + (((u32)(x) & (u32)0x0000ff00) << 8) | \ + (((u32)(x) & (u32)0x00ff0000) >> 8) | \ + (((u32)(x) & (u32)0xff000000) >> 24))) + +#define WAP16(x) ((u16)( \ + (((u16)(x) & (u16)0x00ff) << 8) | \ + (((u16)(x) & (u16)0xff00) >> 8))) + +#if SYSTEM_ENDIAN == PLATFORM_LITTLE_ENDIAN +#ifndef rtk_le16_to_cpu +#define rtk_cpu_to_le32(x) ((u32)(x)) +#define rtk_le32_to_cpu(x) ((u32)(x)) +#define rtk_cpu_to_le16(x) ((u16)(x)) +#define rtk_le16_to_cpu(x) ((u16)(x)) +#define rtk_cpu_to_be32(x) SWAP32((x)) +#define rtk_be32_to_cpu(x) SWAP32((x)) +#define rtk_cpu_to_be16(x) WAP16((x)) +#define rtk_be16_to_cpu(x) WAP16((x)) +#endif + +#elif SYSTEM_ENDIAN == PLATFORM_BIG_ENDIAN +#ifndef rtk_le16_to_cpu +#define rtk_cpu_to_le32(x) SWAP32((x)) +#define rtk_le32_to_cpu(x) SWAP32((x)) +#define rtk_cpu_to_le16(x) WAP16((x)) +#define rtk_le16_to_cpu(x) WAP16((x)) +#define rtk_cpu_to_be32(x) ((__u32)(x)) +#define rtk_be32_to_cpu(x) ((__u32)(x)) +#define rtk_cpu_to_be16(x) ((__u16)(x)) +#define rtk_be16_to_cpu(x) ((__u16)(x)) +#endif +#endif + + +/* + * Call endian free function when + * 1. Read/write packet content. + * 2. Before write integer to IO. + * 3. After read integer from IO. +*/ + +// +// Byte Swapping routine. +// +#define EF1Byte (u8) +#define EF2Byte le16_to_cpu +#define EF4Byte le32_to_cpu + +// +// Read LE format data from memory +// +#define ReadEF1Byte(_ptr) EF1Byte(*((u8 *)(_ptr))) +#define ReadEF2Byte(_ptr) EF2Byte(*((u16 *)(_ptr))) +#define ReadEF4Byte(_ptr) EF4Byte(*((u32 *)(_ptr))) + +// +// Write LE data to memory +// +#define WriteEF1Byte(_ptr, _val) (*((u8 *)(_ptr)))=EF1Byte(_val) +#define WriteEF2Byte(_ptr, _val) (*((u16 *)(_ptr)))=EF2Byte(_val) +#define WriteEF4Byte(_ptr, _val) (*((u32 *)(_ptr)))=EF4Byte(_val) + +// +// Example: +// BIT_LEN_MASK_32(0) => 0x00000000 +// BIT_LEN_MASK_32(1) => 0x00000001 +// BIT_LEN_MASK_32(2) => 0x00000003 +// BIT_LEN_MASK_32(32) => 0xFFFFFFFF +// +#define BIT_LEN_MASK_32(__BitLen) \ + (0xFFFFFFFF >> (32 - (__BitLen))) +// +// Example: +// BIT_OFFSET_LEN_MASK_32(0, 2) => 0x00000003 +// BIT_OFFSET_LEN_MASK_32(16, 2) => 0x00030000 +// +#define BIT_OFFSET_LEN_MASK_32(__BitOffset, __BitLen) \ + (BIT_LEN_MASK_32(__BitLen) << (__BitOffset)) + +// +// Description: +// Return 4-byte value in host byte ordering from +// 4-byte pointer in litten-endian system. +// +#define LE_P4BYTE_TO_HOST_4BYTE(__pStart) \ + (EF4Byte(*((u32 *)(__pStart)))) + +// +// Description: +// Translate subfield (continuous bits in little-endian) of 4-byte value in litten byte to +// 4-byte value in host byte ordering. +// +#define LE_BITS_TO_4BYTE(__pStart, __BitOffset, __BitLen) \ + ( \ + ( LE_P4BYTE_TO_HOST_4BYTE(__pStart) >> (__BitOffset) ) \ + & \ + BIT_LEN_MASK_32(__BitLen) \ + ) + +// +// Description: +// Mask subfield (continuous bits in little-endian) of 4-byte value in litten byte oredering +// and return the result in 4-byte value in host byte ordering. +// +#define LE_BITS_CLEARED_TO_4BYTE(__pStart, __BitOffset, __BitLen) \ + ( \ + LE_P4BYTE_TO_HOST_4BYTE(__pStart) \ + & \ + ( ~ BIT_OFFSET_LEN_MASK_32(__BitOffset, __BitLen) ) \ + ) + +// +// Description: +// Set subfield of little-endian 4-byte value to specified value. +// +#define SET_BITS_TO_LE_4BYTE(__pStart, __BitOffset, __BitLen, __Value) \ + *((u32 *)(__pStart)) = \ + EF4Byte( \ + LE_BITS_CLEARED_TO_4BYTE(__pStart, __BitOffset, __BitLen) \ + | \ + ( (((u32)__Value) & BIT_LEN_MASK_32(__BitLen)) << (__BitOffset) ) \ + ); + + +#define BIT_LEN_MASK_16(__BitLen) \ + (0xFFFF >> (16 - (__BitLen))) + +#define BIT_OFFSET_LEN_MASK_16(__BitOffset, __BitLen) \ + (BIT_LEN_MASK_16(__BitLen) << (__BitOffset)) + +#define LE_P2BYTE_TO_HOST_2BYTE(__pStart) \ + (EF2Byte(*((u16 *)(__pStart)))) + +#define LE_BITS_TO_2BYTE(__pStart, __BitOffset, __BitLen) \ + ( \ + ( LE_P2BYTE_TO_HOST_2BYTE(__pStart) >> (__BitOffset) ) \ + & \ + BIT_LEN_MASK_16(__BitLen) \ + ) + +#define LE_BITS_CLEARED_TO_2BYTE(__pStart, __BitOffset, __BitLen) \ + ( \ + LE_P2BYTE_TO_HOST_2BYTE(__pStart) \ + & \ + ( ~ BIT_OFFSET_LEN_MASK_16(__BitOffset, __BitLen) ) \ + ) + +#define SET_BITS_TO_LE_2BYTE(__pStart, __BitOffset, __BitLen, __Value) \ + *((u16 *)(__pStart)) = \ + EF2Byte( \ + LE_BITS_CLEARED_TO_2BYTE(__pStart, __BitOffset, __BitLen) \ + | \ + ( (((u16)__Value) & BIT_LEN_MASK_16(__BitLen)) << (__BitOffset) ) \ + ); + +#define BIT_LEN_MASK_8(__BitLen) \ + (0xFF >> (8 - (__BitLen))) + +#define BIT_OFFSET_LEN_MASK_8(__BitOffset, __BitLen) \ + (BIT_LEN_MASK_8(__BitLen) << (__BitOffset)) + +#define LE_P1BYTE_TO_HOST_1BYTE(__pStart) \ + (EF1Byte(*((u8 *)(__pStart)))) + +#define LE_BITS_TO_1BYTE(__pStart, __BitOffset, __BitLen) \ + ( \ + ( LE_P1BYTE_TO_HOST_1BYTE(__pStart) >> (__BitOffset) ) \ + & \ + BIT_LEN_MASK_8(__BitLen) \ + ) + +#define LE_BITS_CLEARED_TO_1BYTE(__pStart, __BitOffset, __BitLen) \ + ( \ + LE_P1BYTE_TO_HOST_1BYTE(__pStart) \ + & \ + ( ~BIT_OFFSET_LEN_MASK_8(__BitOffset, __BitLen) ) \ + ) + +#define SET_BITS_TO_LE_1BYTE(__pStart, __BitOffset, __BitLen, __Value) \ + *((u8 *)(__pStart)) = \ + EF1Byte( \ + LE_BITS_CLEARED_TO_1BYTE(__pStart, __BitOffset, __BitLen) \ + | \ + ( (((u8)__Value) & BIT_LEN_MASK_8(__BitLen)) << (__BitOffset) ) \ + ); + +//pclint +#define LE_BITS_CLEARED_TO_1BYTE_8BIT(__pStart, __BitOffset, __BitLen) \ + ( \ + LE_P1BYTE_TO_HOST_1BYTE(__pStart) \ + ) + +//pclint +#define SET_BITS_TO_LE_1BYTE_8BIT(__pStart, __BitOffset, __BitLen, __Value) \ +{ \ + *((pu1Byte)(__pStart)) = \ + EF1Byte( \ + LE_BITS_CLEARED_TO_1BYTE_8BIT(__pStart, __BitOffset, __BitLen) \ + | \ + ((u1Byte)__Value) \ + ); \ +} + +// Get the N-bytes aligment offset from the current length +#define N_BYTE_ALIGMENT(__Value, __Aligment) ((__Aligment == 1) ? (__Value) : (((__Value + __Aligment - 1) / __Aligment) * __Aligment)) + +typedef unsigned char BOOLEAN,*PBOOLEAN; + +#define TEST_FLAG(__Flag,__testFlag) (((__Flag) & (__testFlag)) != 0) +#define SET_FLAG(__Flag, __setFlag) ((__Flag) |= __setFlag) +#define CLEAR_FLAG(__Flag, __clearFlag) ((__Flag) &= ~(__clearFlag)) +#define CLEAR_FLAGS(__Flag) ((__Flag) = 0) +#define TEST_FLAGS(__Flag, __testFlags) (((__Flag) & (__testFlags)) == (__testFlags)) + +/* Define compilor specific symbol */ +// +// inline function +// + +#if defined ( __ICCARM__ ) +#define __inline__ inline +#define __inline inline +#define __inline_definition //In dialect C99, inline means that a function's definition is provided + //only for inlining, and that there is another definition + //(without inline) somewhere else in the program. + //That means that this program is incomplete, because if + //add isn't inlined (for example, when compiling without optimization), + //then main will have an unresolved reference to that other definition. + + // Do not inline function is the function body is defined .c file and this + // function will be called somewhere else, otherwise there is compile error +#elif defined ( __CC_ARM ) +#define __inline__ __inline //__linine__ is not supported in keil compilor, use __inline instead +#define inline __inline +#define __inline_definition // for dialect C99 +#elif defined ( __GNUC__ ) +#define __inline__ inline +#define __inline inline +#define __inline_definition inline +#endif + +// +// pack +// + +#if defined (__ICCARM__) + +#define RTW_PACK_STRUCT_BEGIN +#define RTW_PACK_STRUCT_STRUCT +#define RTW_PACK_STRUCT_END +#define RTW_PACK_STRUCT_USE_INCLUDES + +#elif defined (__CC_ARM) + +#define RTW_PACK_STRUCT_BEGIN __packed +#define RTW_PACK_STRUCT_STRUCT +#define RTW_PACK_STRUCT_END + +#elif defined (__GNUC__) + +#define RTW_PACK_STRUCT_BEGIN +#define RTW_PACK_STRUCT_STRUCT __attribute__ ((__packed__)) +#define RTW_PACK_STRUCT_END + +#elif defined(PLATFORM_WINDOWS) + +#define RTW_PACK_STRUCT_BEGIN +#define RTW_PACK_STRUCT_STRUCT +#define RTW_PACK_STRUCT_END +#define RTW_PACK_STRUCT_USE_INCLUDES +#endif + +// for standard library +#ifdef __ICCARM__ +#define __extension__ /* Ignore */ +#define __restrict /* Ignore */ +#endif + +typedef struct _RAM_START_FUNCTION_ { + VOID (*RamStartFun) (VOID); +}RAM_START_FUNCTION, *PRAM_START_FUNCTION; + +typedef struct _RAM_FUNCTION_START_TABLE_ { + VOID (*RamStartFun) (VOID); + VOID (*RamWakeupFun) (VOID); + VOID (*RamPatchFun0) (VOID); + VOID (*RamPatchFun1) (VOID); + VOID (*RamPatchFun2) (VOID); +}RAM_FUNCTION_START_TABLE, *PRAM_FUNCTION_START_TABLE; + +#endif// __BASIC_TYPES_H__ diff --git a/component/soc/realtek/common/bsp/section_config.h b/component/soc/realtek/common/bsp/section_config.h new file mode 100644 index 0000000..4164d6a --- /dev/null +++ b/component/soc/realtek/common/bsp/section_config.h @@ -0,0 +1,239 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#ifndef _SECTION_CONFIG_H_ +#define _SECTION_CONFIG_H_ + +#include "basic_types.h" + +#define RAM_DEDECATED_VECTOR_TABLE_SECTION \ + SECTION(".ram_dedecated_vector_table") + +#define RAM_USER_IRQ_FUN_TABLE_SECTION \ + SECTION(".ram_user_define_irq_table") + +#define RAM_USER_IRQ_DATA_TABLE_SECTION \ + SECTION(".ram_user_define_data_table") + +//3 Timer Section +#define SECTION_RAM_TIMER2TO7_VECTOR_TABLE \ + SECTION(".timer2_7_vector_table.data") + +#define SECTION_RAM_BSS_TIMER_RECORDER_TABLE \ + SECTION(".timer.ram.data") + +#define TIMER_ROM_TEXT_SECTION \ + SECTION(".timer.rom.text") + +#define TIMER_ROM_DATA_SECTION \ + SECTION(".timer.rom.rodata") + +#define TIMER_RAM_TEXT_SECTION \ + SECTION(".timer.ram.text") + +#define TIMER_RAM_DATA_SECTION \ + SECTION(".timer.ram.data") + + +//3 Wifi Section +#define WIFI_ROM_TEXT_SECTION \ + SECTION(".wifi.rom.text") + +#define WIFI_ROM_DATA_SECTION \ + SECTION(".wifi.rom.rodata") + +#define WIFI_RAM_TEXT_SECTION \ + SECTION(".wifi.ram.text") + +#define WIFI_RAM_DATA_SECTION \ + SECTION(".wifi.ram.data") + +//3 Hal Section +#define HAL_ROM_TEXT_SECTION \ + SECTION(".hal.rom.text") + +#define HAL_ROM_DATA_SECTION \ + SECTION(".hal.rom.rodata") + +#define HAL_RAM_TEXT_SECTION \ + SECTION(".hal.ram.text") + +#define HAL_FLASH_TEXT_SECTION \ + SECTION(".hal.flash.text") + +#define HAL_FLASH_DATA_SECTION \ + SECTION(".hal.flash.data") + +#define HAL_SDRC_TEXT_SECTION \ + SECTION(".hal.sdrc.text") + +#define HAL_SDRC_DATA_SECTION \ + SECTION(".hal.sdrc.data") + +#define HAL_CUT_B_RAM_DATA_SECTION \ + SECTION(".cutb.ram.data") + +#define HAL_CUT_C_RAM_DATA_SECTION \ + SECTION(".cutc.ram.data") + +#define HAL_RAM_DATA_SECTION \ + SECTION(".hal.ram.data") + +#define HAL_RAM_BSS_SECTION \ + SECTION(".hal.ram.bss") + +#define HAL_ROM_OP_SECTION \ + SECTION(".halop.rom.rodata") + +#define HAL_GPIO_TEXT_SECTION \ + SECTION(".hal.gpio.text") + +#define HAL_GPIO_DATA_SECTION \ + SECTION(".hal.gpio.data") + +//3 C-Cut ROM Patch/New functions location +#define C_CUT_ROM_TEXT_SECTION \ + SECTION(".cutc.rom.text") + +#define C_CUT_ROM_RODATA_SECTION \ + SECTION(".cutc.rom.rodata") + +#define C_CUT_ROM_DATA_SECTION \ + SECTION(".cutc.ram.data") + + +//3 Store the Image 1 validate code +#define IMAGE1_VALID_PATTEN_SECTION \ + SECTION(".image1.validate.rodata") + +#define IMAGE2_VALID_PATTEN_SECTION \ + SECTION(".image2.validate.rodata") + +//3 Infra Section +#define INFRA_ROM_TEXT_SECTION \ + SECTION(".infra.rom.text") + +#define INFRA_ROM_DATA_SECTION \ + SECTION(".infra.rom.rodata") + +#define INFRA_RAM_TEXT_SECTION \ + SECTION(".infra.ram.text") + +#define INFRA_RAM_DATA_SECTION \ + SECTION(".infra.ram.data") + +#define INFRA_RAM_BSS_SECTION \ + SECTION(".infra.ram.bss") + +#define INFRA_START_SECTION \ + SECTION(".infra.ram.start") + + +//3 Pin Mutex Section +#define PINMUX_ROM_TEXT_SECTION \ + SECTION(".hal.rom.text") + +#define PINMUX_ROM_DATA_SECTION \ + SECTION(".hal.rom.rodata") + +#define PINMUX_RAM_TEXT_SECTION \ + SECTION(".hal.ram.text") + +#define PINMUX_RAM_DATA_SECTION \ + SECTION(".hal.ram.data") + +#define PINMUX_RAM_BSS_SECTION \ + SECTION(".hal.ram.bss") + + +//3 Monitor App Section +#define MON_ROM_TEXT_SECTION \ + SECTION(".mon.rom.text") + +#define MON_ROM_DATA_SECTION \ + SECTION(".mon.rom.rodata") + +#define MON_RAM_TEXT_SECTION \ + SECTION(".mon.ram.text") + +#define MON_RAM_DATA_SECTION \ + SECTION(".mon.ram.data") + +#define MON_RAM_BSS_SECTION \ + SECTION(".mon.ram.bss") + + +//3 SDIO Section +#define SECTION_SDIO_RAM +#define SECTION_SDIO_ROM +#define SDIO_ROM_BSS_SECTION \ + SECTION(".sdio.rom.bss") +#define SDIO_ROM_TEXT_SECTION \ + SECTION(".sdio.rom.text") + +//3 SRAM Config Section +#define SRAM_BD_DATA_SECTION \ + SECTION(".bdsram.data") + +#define SRAM_BF_DATA_SECTION \ + SECTION(".bfsram.data") + + +#define START_RAM_FUN_SECTION \ + SECTION(".start.ram.data") + +#define START_RAM_FUN_A_SECTION \ + SECTION(".start.ram.data.a") + +#define START_RAM_FUN_B_SECTION \ + SECTION(".start.ram.data.b") + +#define START_RAM_FUN_C_SECTION \ + SECTION(".start.ram.data.c") + +#define START_RAM_FUN_D_SECTION \ + SECTION(".start.ram.data.d") + +#define START_RAM_FUN_E_SECTION \ + SECTION(".start.ram.data.e") + +#define IMAGE2_START_RAM_FUN_SECTION \ + SECTION(".image2.ram.data") + +#define SDRAM_DATA_SECTION \ + SECTION(".sdram.data") + +//3 Wlan Section +#define WLAN_ROM_TEXT_SECTION \ + SECTION(".wlan.rom.text") + +#define WLAN_ROM_DATA_SECTION \ + SECTION(".wlan.rom.rodata") + +#define WLAN_RAM_MAP_SECTION \ + SECTION(".wlan_ram_map") + +//3 Apple Section +#define APPLE_ROM_TEXT_SECTION \ + SECTION(".apple.rom.text") + +#define APPLE_ROM_DATA_SECTION \ + SECTION(".apple.rom.rodata") + +//3 Libc Section +#define LIBC_ROM_TEXT_SECTION \ + SECTION(".libc.rom.text") + +#define LIBC_ROM_DATA_SECTION \ + SECTION(".libc.rom.rodata") + +#define LIBC_RAM_BSS_SECTION \ + SECTION(".libc.ram.bss") + +#endif //_SECTION_CONFIG_H_ diff --git a/component/soc/realtek/common/rtl_std_lib/include/rtl_lib.h b/component/soc/realtek/common/rtl_std_lib/include/rtl_lib.h new file mode 100644 index 0000000..8584e92 --- /dev/null +++ b/component/soc/realtek/common/rtl_std_lib/include/rtl_lib.h @@ -0,0 +1,141 @@ +/* + * rtl_lib.h + * + * Definitions for RTL library functions + */ + +#ifndef _RTL_LIB_H_ +#define _RTL_LIB_H_ + + +#include +#include + + +extern int __rtl_errno; + + +void init_rom_libgloss_ram_map(void); + + +// +// RTL library functions for Libc::stdio +// + +extern int rtl_printf(IN const char* fmt, ...); +extern int rtl_sprintf(char* str, const char* fmt, ...); +extern int rtl_snprintf(char* str, size_t size, const char* fmt, ...); + +// +// RTL library functions for string +// + +extern void * rtl_memchr(const void * src_void , int c , size_t length); +extern int rtl_memcmp(const void * m1 , const void * m2 , size_t n); +extern void * rtl_memcpy(void * dst0 , const void * src0 , size_t len0); +extern void * rtl_memmove( void * dst_void , const void * src_void , size_t length); +extern void * rtl_memset(void * m , int c , size_t n); +extern char * rtl_strcat(char * s1 , const char * s2); +extern char * rtl_strchr(const char *s1 , int i); +extern int rtl_strcmp(const char *s1 , const char *s2); +extern char* rtl_strcpy(char *dst0 , const char *src0); +extern size_t rtl_strlen(const char *str); +extern char * rtl_strncat(char * s1 , const char * s2 , size_t n); +extern int rtl_strncmp(const char *s1 , const char *s2 , size_t n); +extern char * rtl_strncpy(char * dst0 , const char * src0 , size_t count); +extern char * rtl_strstr(const char *searchee , const char *lookfor); +extern char * rtl_strsep(char **source_ptr , const char *delim); +extern char * rtl_strtok(char * s , const char * delim); + +// +// RTL library functions for math +// + + +extern double rtl_fabs(double); +extern float rtl_fabsf(float a); +extern float rtl_cos_f32(float a); +extern float rtl_sin_f32(float a); + +extern float rtl_fadd(float a, float b); +extern float rtl_fsub(float a, float b); +extern float rtl_fmul(float a, float b); +extern float rtl_fdiv(float a, float b); + +extern int rtl_fcmplt(float a, float b); +extern int rtl_fcmpgt(float a, float b); + + + + + +// +// RTL eabi functions + +extern double rtl_ftod(float f); + +extern double rtl_ddiv(double a, double b); + + +// +// Macro Library Functions +// + +typedef union +{ + float value; + u32 word; +} ieee_float_shape_type; + +/* Get a 32 bit int from a float. */ + +#define GET_FLOAT_WORD(i,d) \ +do { \ + ieee_float_shape_type gf_u; \ + gf_u.value = (d); \ + (i) = gf_u.word; \ +} while (0) + +/* Set a float from a 32 bit int. */ + +#define SET_FLOAT_WORD(d,i) \ +do { \ + ieee_float_shape_type sf_u; \ + sf_u.word = (i); \ + (d) = sf_u.value; \ +} while (0) + +static inline +float rtl_nanf(void) +{ + float x; + + SET_FLOAT_WORD(x,0x7fc00000); + return x; +} + + +// +// Library Test functions +// + +extern int rtl_lib_test(IN u16 argc, IN u8 *argv[]); +extern int rtl_math_test(IN u16 argc, IN u8 *argv[]); +extern int rtl_string_test(IN u16 argc, IN u8 *argv[]); + + +// +// Macro functions +// + +#undef dbg_printf +#define dbg_printf(fmt, args...) \ + rtl_printf("%s():%d : " fmt "\n", __FUNCTION__, __LINE__, ##args); + + +#undef err_printf +#define err_printf(fmt, args...) \ + rtl_printf("%s():%d : " fmt "\n", __FUNCTION__, __LINE__, ##args); + + +#endif /* _RTL_LIB_H_ */ diff --git a/project/realtek_ameba1_va0_example/EWARM-RELEASE/Debug/Exe/application.asm b/project/realtek_ameba1_va0_example/EWARM-RELEASE/Debug/Exe/application.asm new file mode 100644 index 0000000..df280dc --- /dev/null +++ b/project/realtek_ameba1_va0_example/EWARM-RELEASE/Debug/Exe/application.asm @@ -0,0 +1,190694 @@ + +Debug/Exe/application.axf: file format elf32-littlearm + + +Disassembly of section A1 rw: + +00000000 <__vectors_table>: + 0: 1ffffffc .word 0x1ffffffc + 4: 00000101 .word 0x00000101 + 8: 00000109 .word 0x00000109 + c: 0000010d .word 0x0000010d + 10: 00000121 .word 0x00000121 + 14: 00000125 .word 0x00000125 + 18: 00000129 .word 0x00000129 + ... + +00000100 : + 100: f8df d028 ldr.w sp, [pc, #40] ; 12c + 104: f000 b95e b.w 3c4 + +00000108 : + 108: f000 bbea b.w 8e0 + +0000010c : + 10c: f01e 0f04 tst.w lr, #4 + 110: bf0c ite eq + 112: f3ef 8008 mrseq r0, MSP + 116: f3ef 8009 mrsne r0, PSP + 11a: f000 bbf9 b.w 910 + ... + +00000120 : + 120: f000 bd72 b.w c08 + +00000124 : + 124: f000 bd88 b.w c38 + +00000128 : + 128: f000 bd9e b.w c68 + 12c: 1ffffffc .word 0x1ffffffc + ... + +00000200 : + 200: b5f0 push {r4, r5, r6, r7, lr} + 202: f243 0504 movw r5, #12292 ; 0x3004 + 206: f243 040c movw r4, #12300 ; 0x300c + 20a: f2c4 0500 movt r5, #16384 ; 0x4000 + 20e: f2c4 0400 movt r4, #16384 ; 0x4000 + 212: b085 sub sp, #20 + 214: ae04 add r6, sp, #16 + 216: e906 000f stmdb r6, {r0, r1, r2, r3} + 21a: 2200 movs r2, #0 + 21c: 2380 movs r3, #128 ; 0x80 + 21e: 9e02 ldr r6, [sp, #8] + 220: 602a str r2, [r5, #0] + 222: 6023 str r3, [r4, #0] + 224: f000 f896 bl 354 + 228: 9b00 ldr r3, [sp, #0] + 22a: 0880 lsrs r0, r0, #2 + 22c: eb00 0280 add.w r2, r0, r0, lsl #2 + 230: 011b lsls r3, r3, #4 + 232: fbb0 f0f3 udiv r0, r0, r3 + 236: 0052 lsls r2, r2, #1 + 238: fbb2 f3f3 udiv r3, r2, r3 + 23c: eb00 0280 add.w r2, r0, r0, lsl #2 + 240: eba3 0342 sub.w r3, r3, r2, lsl #1 + 244: 2b04 cmp r3, #4 + 246: f243 020c movw r2, #12300 ; 0x300c + 24a: f243 0304 movw r3, #12292 ; 0x3004 + 24e: f243 0108 movw r1, #12296 ; 0x3008 + 252: f44f 5440 mov.w r4, #12288 ; 0x3000 + 256: f2c4 0200 movt r2, #16384 ; 0x4000 + 25a: f2c4 0400 movt r4, #16384 ; 0x4000 + 25e: f2c4 0300 movt r3, #16384 ; 0x4000 + 262: f2c4 0100 movt r1, #16384 ; 0x4000 + 266: bf88 it hi + 268: 3001 addhi r0, #1 + 26a: b2c7 uxtb r7, r0 + 26c: 2500 movs r5, #0 + 26e: f3c0 2007 ubfx r0, r0, #8, #8 + 272: 6027 str r7, [r4, #0] + 274: 6018 str r0, [r3, #0] + 276: 6015 str r5, [r2, #0] + 278: f89d 500d ldrb.w r5, [sp, #13] + 27c: f89d 000c ldrb.w r0, [sp, #12] + 280: f89d 400e ldrb.w r4, [sp, #14] + 284: 4328 orrs r0, r5 + 286: 4320 orrs r0, r4 + 288: 6010 str r0, [r2, #0] + 28a: 9a01 ldr r2, [sp, #4] + 28c: 600a str r2, [r1, #0] + 28e: 601e str r6, [r3, #0] + 290: b1f6 cbz r6, 2d0 + 292: f642 040c movw r4, #10252 ; 0x280c + 296: f44f 416d mov.w r1, #60672 ; 0xed00 + 29a: f2c4 0400 movt r4, #16384 ; 0x4000 + 29e: f2ce 0100 movt r1, #57344 ; 0xe000 + 2a2: f64f 00ff movw r0, #63743 ; 0xf8ff + 2a6: f44f 7340 mov.w r3, #768 ; 0x300 + 2aa: f2c0 53fa movt r3, #1530 ; 0x5fa + 2ae: f44f 4261 mov.w r2, #57600 ; 0xe100 + 2b2: f2ce 0200 movt r2, #57344 ; 0xe000 + 2b6: f04f 7580 mov.w r5, #16777216 ; 0x1000000 + 2ba: 6025 str r5, [r4, #0] + 2bc: 68cd ldr r5, [r1, #12] + 2be: 24e0 movs r4, #224 ; 0xe0 + 2c0: 4028 ands r0, r5 + 2c2: 4303 orrs r3, r0 + 2c4: f44f 2000 mov.w r0, #524288 ; 0x80000 + 2c8: 60cb str r3, [r1, #12] + 2ca: f882 4313 strb.w r4, [r2, #787] ; 0x313 + 2ce: 6010 str r0, [r2, #0] + 2d0: 2000 movs r0, #0 + 2d2: b005 add sp, #20 + 2d4: bdf0 pop {r4, r5, r6, r7, pc} + 2d6: bf00 nop + +000002d8 : + 2d8: f243 0114 movw r1, #12308 ; 0x3014 + 2dc: f641 138b movw r3, #6539 ; 0x198b + 2e0: f2c4 0100 movt r1, #16384 ; 0x4000 + 2e4: e001 b.n 2ea + 2e6: 3b01 subs r3, #1 + 2e8: d003 beq.n 2f2 + 2ea: 780a ldrb r2, [r1, #0] + 2ec: f012 0f60 tst.w r2, #96 ; 0x60 + 2f0: d0f9 beq.n 2e6 + 2f2: f44f 5340 mov.w r3, #12288 ; 0x3000 + 2f6: f2c4 0300 movt r3, #16384 ; 0x4000 + 2fa: 280a cmp r0, #10 + 2fc: bf08 it eq + 2fe: 220d moveq r2, #13 + 300: 7018 strb r0, [r3, #0] + 302: bf08 it eq + 304: 701a strbeq r2, [r3, #0] + 306: 4770 bx lr + +00000308 : + 308: b130 cbz r0, 318 + 30a: f243 0214 movw r2, #12308 ; 0x3014 + 30e: f2c4 0200 movt r2, #16384 ; 0x4000 + 312: 7813 ldrb r3, [r2, #0] + 314: 07db lsls r3, r3, #31 + 316: d5fc bpl.n 312 + 318: f44f 5340 mov.w r3, #12288 ; 0x3000 + 31c: f2c4 0300 movt r3, #16384 ; 0x4000 + 320: 7818 ldrb r0, [r3, #0] + 322: b2c0 uxtb r0, r0 + 324: 4770 bx lr + 326: bf00 nop + +00000328 : + 328: f243 0304 movw r3, #12292 ; 0x3004 + 32c: f2c4 0300 movt r3, #16384 ; 0x4000 + 330: 6818 ldr r0, [r3, #0] + 332: 4770 bx lr + +00000334 : + 334: f243 0304 movw r3, #12292 ; 0x3004 + 338: f2c4 0300 movt r3, #16384 ; 0x4000 + 33c: 6018 str r0, [r3, #0] + 33e: 4770 bx lr + +00000340 : + 340: 2314 movs r3, #20 + 342: f2c4 0300 movt r3, #16384 ; 0x4000 + 346: 681a ldr r2, [r3, #0] + 348: f022 0270 bic.w r2, r2, #112 ; 0x70 + 34c: ea42 1000 orr.w r0, r2, r0, lsl #4 + 350: 6018 str r0, [r3, #0] + 352: 4770 bx lr + +00000354 : + 354: f640 4368 movw r3, #3176 ; 0xc68 + 358: 2114 movs r1, #20 + 35a: f2c4 0100 movt r1, #16384 ; 0x4000 + 35e: 2274 movs r2, #116 ; 0x74 + 360: f2c4 0200 movt r2, #16384 ; 0x4000 + 364: f2c0 0303 movt r3, #3 + 368: 6809 ldr r1, [r1, #0] + 36a: 6812 ldr r2, [r2, #0] + 36c: f3c1 1102 ubfx r1, r1, #4, #3 + 370: f853 0021 ldr.w r0, [r3, r1, lsl #2] + 374: 0393 lsls r3, r2, #14 + 376: d40f bmi.n 398 + 378: f44f 6310 mov.w r3, #2304 ; 0x900 + 37c: f2c0 033d movt r3, #61 ; 0x3d + 380: 4298 cmp r0, r3 + 382: bf81 itttt hi + 384: f64a 23ab movwhi r3, #43691 ; 0xaaab + 388: f6ca 23aa movthi r3, #43690 ; 0xaaaa + 38c: eb00 0080 addhi.w r0, r0, r0, lsl #2 + 390: fba3 2000 umullhi r2, r0, r3, r0 + 394: bf88 it hi + 396: 0880 lsrhi r0, r0, #2 + 398: 4770 bx lr + 39a: bf00 nop + +0000039c : + 39c: f44f 73fc mov.w r3, #504 ; 0x1f8 + 3a0: f2c4 0300 movt r3, #16384 ; 0x4000 + 3a4: 681a ldr r2, [r3, #0] + 3a6: f022 02ff bic.w r2, r2, #255 ; 0xff + 3aa: f042 0202 orr.w r2, r2, #2 + 3ae: 601a str r2, [r3, #0] + 3b0: 4770 bx lr + 3b2: bf00 nop + +000003b4 : + 3b4: f44f 73fc mov.w r3, #504 ; 0x1f8 + 3b8: f2c4 0300 movt r3, #16384 ; 0x4000 + 3bc: 6818 ldr r0, [r3, #0] + 3be: b2c0 uxtb r0, r0 + 3c0: 4770 bx lr + 3c2: bf00 nop + +000003c4 : + 3c4: f240 3000 movw r0, #768 ; 0x300 + 3c8: f640 32c8 movw r2, #3016 ; 0xbc8 + 3cc: f2c1 0000 movt r0, #4096 ; 0x1000 + 3d0: f2c1 0200 movt r2, #4096 ; 0x1000 + 3d4: f24f 5311 movw r3, #62737 ; 0xf511 + 3d8: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 3dc: 1a12 subs r2, r2, r0 + 3de: b08d sub sp, #52 ; 0x34 + 3e0: f2c0 0300 movt r3, #0 + 3e4: 2100 movs r1, #0 + 3e6: 4798 blx r3 + 3e8: f7ff ffd8 bl 39c + 3ec: f44f 730c mov.w r3, #560 ; 0x230 + 3f0: f2c4 0300 movt r3, #16384 ; 0x4000 + 3f4: 681a ldr r2, [r3, #0] + 3f6: 2100 movs r1, #0 + 3f8: f042 0240 orr.w r2, r2, #64 ; 0x40 + 3fc: 601a str r2, [r3, #0] + 3fe: 681a ldr r2, [r3, #0] + 400: 20d8 movs r0, #216 ; 0xd8 + 402: f042 0280 orr.w r2, r2, #128 ; 0x80 + 406: 601a str r2, [r3, #0] + 408: 2201 movs r2, #1 + 40a: f002 fb95 bl 2b38 + 40e: f44f 734e mov.w r3, #824 ; 0x338 + 412: f2c4 0300 movt r3, #16384 ; 0x4000 + 416: f44f 7204 mov.w r2, #528 ; 0x210 + 41a: f2c4 0200 movt r2, #16384 ; 0x4000 + 41e: f640 37c8 movw r7, #3016 ; 0xbc8 + 422: 6819 ldr r1, [r3, #0] + 424: f2c1 0700 movt r7, #4096 ; 0x1000 + 428: f021 0103 bic.w r1, r1, #3 + 42c: f041 0102 orr.w r1, r1, #2 + 430: 6019 str r1, [r3, #0] + 432: 6813 ldr r3, [r2, #0] + 434: 009a lsls r2, r3, #2 + 436: f100 8224 bmi.w 882 + 43a: f44f 7304 mov.w r3, #528 ; 0x210 + 43e: f2c4 0300 movt r3, #16384 ; 0x4000 + 442: 681b ldr r3, [r3, #0] + 444: 011b lsls r3, r3, #4 + 446: f100 8219 bmi.w 87c + 44a: f44f 73fa mov.w r3, #500 ; 0x1f4 + 44e: f2c4 0300 movt r3, #16384 ; 0x4000 + 452: 681b ldr r3, [r3, #0] + 454: 011e lsls r6, r3, #4 + 456: d51d bpl.n 494 + 458: 2320 movs r3, #32 + 45a: f2c4 0300 movt r3, #16384 ; 0x4000 + 45e: f44f 7204 mov.w r2, #528 ; 0x210 + 462: f2c4 0200 movt r2, #16384 ; 0x4000 + 466: 6819 ldr r1, [r3, #0] + 468: f441 3100 orr.w r1, r1, #131072 ; 0x20000 + 46c: 6019 str r1, [r3, #0] + 46e: 6813 ldr r3, [r2, #0] + 470: 2b00 cmp r3, #0 + 472: f2c0 820c blt.w 88e + 476: f44f 7304 mov.w r3, #528 ; 0x210 + 47a: f2c4 0300 movt r3, #16384 ; 0x4000 + 47e: 681b ldr r3, [r3, #0] + 480: 00d8 lsls r0, r3, #3 + 482: f100 8201 bmi.w 888 + 486: f44f 7304 mov.w r3, #528 ; 0x210 + 48a: f2c4 0300 movt r3, #16384 ; 0x4000 + 48e: 681a ldr r2, [r3, #0] + 490: 0051 lsls r1, r2, #1 + 492: d5fc bpl.n 48e + 494: f240 3414 movw r4, #788 ; 0x314 + 498: 2002 movs r0, #2 + 49a: f7ff ff51 bl 340 + 49e: f44f 7a04 mov.w sl, #528 ; 0x210 + 4a2: f64f 70fc movw r0, #65532 ; 0xfffc + 4a6: f643 53e5 movw r3, #15845 ; 0x3de5 + 4aa: f2c4 0a00 movt sl, #16384 ; 0x4000 + 4ae: f2c1 0400 movt r4, #4096 ; 0x1000 + 4b2: f44f 780c mov.w r8, #560 ; 0x230 + 4b6: f2c4 0800 movt r8, #16384 ; 0x4000 + 4ba: f04f 32ff mov.w r2, #4294967295 + 4be: f6c1 70ff movt r0, #8191 ; 0x1fff + 4c2: f2c0 0300 movt r3, #0 + 4c6: 6022 str r2, [r4, #0] + 4c8: 4798 blx r3 + 4ca: f8da 3000 ldr.w r3, [sl] + 4ce: 2100 movs r1, #0 + 4d0: f443 5380 orr.w r3, r3, #4096 ; 0x1000 + 4d4: f8ca 3000 str.w r3, [sl] + 4d8: f8d8 3000 ldr.w r3, [r8] + 4dc: 2201 movs r2, #1 + 4de: f443 5380 orr.w r3, r3, #4096 ; 0x1000 + 4e2: f8c8 3000 str.w r3, [r8] + 4e6: 20dc movs r0, #220 ; 0xdc + 4e8: f002 fb26 bl 2b38 + 4ec: f64e 3ef5 movw lr, #60405 ; 0xebf5 + 4f0: f240 2901 movw r9, #513 ; 0x201 + 4f4: f2c0 0e00 movt lr, #0 + 4f8: 2500 movs r5, #0 + 4fa: f44f 4116 mov.w r1, #38400 ; 0x9600 + 4fe: 2203 movs r2, #3 + 500: 23c1 movs r3, #193 ; 0xc1 + 502: 9506 str r5, [sp, #24] + 504: f88d 501c strb.w r5, [sp, #28] + 508: f88d 501d strb.w r5, [sp, #29] + 50c: ae04 add r6, sp, #16 + 50e: 9104 str r1, [sp, #16] + 510: f88d 201e strb.w r2, [sp, #30] + 514: 9305 str r3, [sp, #20] + 516: f04f 0c58 mov.w ip, #88 ; 0x58 + 51a: e896 000f ldmia.w r6, {r0, r1, r2, r3} + 51e: f2c0 0900 movt r9, #0 + 522: f8cd e000 str.w lr, [sp] + 526: f8cd c004 str.w ip, [sp, #4] + 52a: 9502 str r5, [sp, #8] + 52c: 9503 str r5, [sp, #12] + 52e: 47c8 blx r9 + 530: f244 0329 movw r3, #16425 ; 0x4029 + 534: 4668 mov r0, sp + 536: f2c0 0300 movt r3, #0 + 53a: 4798 blx r3 + 53c: 2305 movs r3, #5 + 53e: 9306 str r3, [sp, #24] + 540: e896 000f ldmia.w r6, {r0, r1, r2, r3} + 544: 47c8 blx r9 + 546: f00e f92f bl e7a8 + 54a: f241 62a0 movw r2, #5792 ; 0x16a0 + 54e: f240 3b18 movw fp, #792 ; 0x318 + 552: 4601 mov r1, r0 + 554: f2c0 0203 movt r2, #3 + 558: 4628 mov r0, r5 + 55a: f00e fbb3 bl ecc4 + 55e: f44f 721c mov.w r2, #624 ; 0x270 + 562: f2c4 0200 movt r2, #16384 ; 0x4000 + 566: f44f 7301 mov.w r3, #516 ; 0x204 + 56a: f2c4 0300 movt r3, #16384 ; 0x4000 + 56e: f2c1 0b00 movt fp, #4096 ; 0x1000 + 572: 6811 ldr r1, [r2, #0] + 574: 4658 mov r0, fp + 576: f041 0101 orr.w r1, r1, #1 + 57a: 6011 str r1, [r2, #0] + 57c: f8da 1000 ldr.w r1, [sl] + 580: 2201 movs r2, #1 + 582: f441 3180 orr.w r1, r1, #65536 ; 0x10000 + 586: f8ca 1000 str.w r1, [sl] + 58a: f8d8 1000 ldr.w r1, [r8] + 58e: f441 4180 orr.w r1, r1, #16384 ; 0x4000 + 592: f8c8 1000 str.w r1, [r8] + 596: f8d8 1000 ldr.w r1, [r8] + 59a: f441 4100 orr.w r1, r1, #32768 ; 0x8000 + 59e: f8c8 1000 str.w r1, [r8] + 5a2: 6819 ldr r1, [r3, #0] + 5a4: f021 0110 bic.w r1, r1, #16 + 5a8: 6019 str r1, [r3, #0] + 5aa: f88d 202d strb.w r2, [sp, #45] ; 0x2d + 5ae: f88d 202c strb.w r2, [sp, #44] ; 0x2c + 5b2: 9505 str r5, [sp, #20] + 5b4: 9504 str r5, [sp, #16] + 5b6: 9506 str r5, [sp, #24] + 5b8: f00e fc28 bl ee0c + 5bc: f8db 3004 ldr.w r3, [fp, #4] + 5c0: 4630 mov r0, r6 + 5c2: 4798 blx r3 + 5c4: f7ff fef6 bl 3b4 + 5c8: 6823 ldr r3, [r4, #0] + 5ca: 4680 mov r8, r0 + 5cc: 005d lsls r5, r3, #1 + 5ce: f100 812c bmi.w 82a + 5d2: f24f 359d movw r5, #62365 ; 0xf39d + 5d6: f2c0 0500 movt r5, #0 + 5da: f44f 7304 mov.w r3, #528 ; 0x210 + 5de: f2c4 0300 movt r3, #16384 ; 0x4000 + 5e2: 681b ldr r3, [r3, #0] + 5e4: 0159 lsls r1, r3, #5 + 5e6: f100 811d bmi.w 824 + 5ea: f44f 73fa mov.w r3, #500 ; 0x1f4 + 5ee: f2c4 0300 movt r3, #16384 ; 0x4000 + 5f2: 681b ldr r3, [r3, #0] + 5f4: f003 4370 and.w r3, r3, #4026531840 ; 0xf0000000 + 5f8: f1b3 5f00 cmp.w r3, #536870912 ; 0x20000000 + 5fc: f000 80f4 beq.w 7e8 + 600: 2338 movs r3, #56 ; 0x38 + 602: f2c4 0300 movt r3, #16384 ; 0x4000 + 606: 681b ldr r3, [r3, #0] + 608: ea4f 6813 mov.w r8, r3, lsr #24 + 60c: f3c8 0381 ubfx r3, r8, #2, #2 + 610: f3c8 1801 ubfx r8, r8, #4, #2 + 614: b1d3 cbz r3, 64c + 616: 2b01 cmp r3, #1 + 618: f000 80e2 beq.w 7e0 + 61c: 2b02 cmp r3, #2 + 61e: d102 bne.n 626 + 620: 2001 movs r0, #1 + 622: f7ff fe8d bl 340 + 626: 2300 movs r3, #0 + 628: 2003 movs r0, #3 + 62a: 21c1 movs r1, #193 ; 0xc1 + 62c: 2205 movs r2, #5 + 62e: f44f 4e16 mov.w lr, #38400 ; 0x9600 + 632: f8cd e010 str.w lr, [sp, #16] + 636: f88d 001e strb.w r0, [sp, #30] + 63a: 9105 str r1, [sp, #20] + 63c: 9206 str r2, [sp, #24] + 63e: f88d 301c strb.w r3, [sp, #28] + 642: f88d 301d strb.w r3, [sp, #29] + 646: e896 000f ldmia.w r6, {r0, r1, r2, r3} + 64a: 47c8 blx r9 + 64c: f240 3614 movw r6, #788 ; 0x314 + 650: 6823 ldr r3, [r4, #0] + 652: f2c1 0600 movt r6, #4096 ; 0x1000 + 656: f013 4380 ands.w r3, r3, #1073741824 ; 0x40000000 + 65a: f040 80b8 bne.w 7ce + 65e: f1b8 0f01 cmp.w r8, #1 + 662: f000 80ab beq.w 7bc + 666: f1b8 0f02 cmp.w r8, #2 + 66a: f000 8082 beq.w 772 + 66e: f1b8 0f00 cmp.w r8, #0 + 672: d00c beq.n 68e + 674: b123 cbz r3, 680 + 676: f64e 603c movw r0, #60988 ; 0xee3c + 67a: f2c0 0003 movt r0, #3 + 67e: 47a8 blx r5 + 680: f248 60a0 movw r0, #34464 ; 0x86a0 + 684: f2c0 0001 movt r0, #1 + 688: f00e fba0 bl edcc + 68c: e7fe b.n 68c + 68e: b123 cbz r3, 69a + 690: f64e 5038 movw r0, #60728 ; 0xed38 + 694: f2c0 0003 movt r0, #3 + 698: 47a8 blx r5 + 69a: f44f 71fa mov.w r1, #500 ; 0x1f4 + 69e: f2c4 0100 movt r1, #16384 ; 0x4000 + 6a2: f44f 7204 mov.w r2, #528 ; 0x210 + 6a6: f2c4 0200 movt r2, #16384 ; 0x4000 + 6aa: f44f 730c mov.w r3, #560 ; 0x230 + 6ae: f2c4 0300 movt r3, #16384 ; 0x4000 + 6b2: 6809 ldr r1, [r1, #0] + 6b4: 6810 ldr r0, [r2, #0] + 6b6: f001 4170 and.w r1, r1, #4026531840 ; 0xf0000000 + 6ba: f1a1 5140 sub.w r1, r1, #805306368 ; 0x30000000 + 6be: fab1 f181 clz r1, r1 + 6c2: f040 0010 orr.w r0, r0, #16 + 6c6: 6010 str r0, [r2, #0] + 6c8: 681a ldr r2, [r3, #0] + 6ca: 0949 lsrs r1, r1, #5 + 6cc: f442 7280 orr.w r2, r2, #256 ; 0x100 + 6d0: 601a str r2, [r3, #0] + 6d2: 681a ldr r2, [r3, #0] + 6d4: 20c4 movs r0, #196 ; 0xc4 + 6d6: f442 7200 orr.w r2, r2, #512 ; 0x200 + 6da: 601a str r2, [r3, #0] + 6dc: 2201 movs r2, #1 + 6de: f002 fa2b bl 2b38 + 6e2: 2001 movs r0, #1 + 6e4: 2100 movs r1, #0 + 6e6: f002 fcfd bl 30e4 + 6ea: 2210 movs r2, #16 + 6ec: 2314 movs r3, #20 + 6ee: f6c9 0200 movt r2, #38912 ; 0x9800 + 6f2: f6c9 0300 movt r3, #38912 ; 0x9800 + 6f6: 6821 ldr r1, [r4, #0] + 6f8: f8d2 8000 ldr.w r8, [r2] + 6fc: 0048 lsls r0, r1, #1 + 6fe: 681e ldr r6, [r3, #0] + 700: d506 bpl.n 710 + 702: f64e 5048 movw r0, #60744 ; 0xed48 + 706: 4641 mov r1, r8 + 708: f2c0 0003 movt r0, #3 + 70c: 4632 mov r2, r6 + 70e: 47a8 blx r5 + 710: f108 0820 add.w r8, r8, #32 + 714: f1b8 0f20 cmp.w r8, #32 + 718: bf84 itt hi + 71a: 3e20 subhi r6, #32 + 71c: 2320 movhi r3, #32 + 71e: d906 bls.n 72e + 720: f103 4218 add.w r2, r3, #2550136832 ; 0x98000000 + 724: 6812 ldr r2, [r2, #0] + 726: 50f2 str r2, [r6, r3] + 728: 3304 adds r3, #4 + 72a: 4543 cmp r3, r8 + 72c: d3f8 bcc.n 720 + 72e: f640 32dc movw r2, #3036 ; 0xbdc + 732: f2c1 0200 movt r2, #4096 ; 0x1000 + 736: 7813 ldrb r3, [r2, #0] + 738: 2b23 cmp r3, #35 ; 0x23 + 73a: bf04 itt eq + 73c: 4855 ldreq r0, [pc, #340] ; (894 ) + 73e: 2300 moveq r3, #0 + 740: d003 beq.n 74a + 742: e01e b.n 782 + 744: 5cd6 ldrb r6, [r2, r3] + 746: 428e cmp r6, r1 + 748: d11b bne.n 782 + 74a: 3301 adds r3, #1 + 74c: 5cc1 ldrb r1, [r0, r3] + 74e: 29ff cmp r1, #255 ; 0xff + 750: d1f8 bne.n 744 + 752: 6823 ldr r3, [r4, #0] + 754: 005b lsls r3, r3, #1 + 756: d504 bpl.n 762 + 758: f64e 50d0 movw r0, #60880 ; 0xedd0 + 75c: f2c0 0003 movt r0, #3 + 760: 47a8 blx r5 + 762: 2100 movs r1, #0 + 764: 460a mov r2, r1 + 766: 20d8 movs r0, #216 ; 0xd8 + 768: f002 f9e6 bl 2b38 + 76c: 683b ldr r3, [r7, #0] + 76e: 4798 blx r3 + 770: e78c b.n 68c + 772: 2b00 cmp r3, #0 + 774: d084 beq.n 680 + 776: f64e 601c movw r0, #60956 ; 0xee1c + 77a: f2c0 0003 movt r0, #3 + 77e: 47a8 blx r5 + 780: e77e b.n 680 + 782: f240 3614 movw r6, #788 ; 0x314 + 786: 6823 ldr r3, [r4, #0] + 788: f2c1 0600 movt r6, #4096 ; 0x1000 + 78c: 0059 lsls r1, r3, #1 + 78e: d50d bpl.n 7ac + 790: f64e 5070 movw r0, #60784 ; 0xed70 + 794: f2c0 0003 movt r0, #3 + 798: 47a8 blx r5 + 79a: 6833 ldr r3, [r6, #0] + 79c: e006 b.n 7ac + 79e: f248 60a0 movw r0, #34464 ; 0x86a0 + 7a2: f2c0 0001 movt r0, #1 + 7a6: f00e fb11 bl edcc + 7aa: 6823 ldr r3, [r4, #0] + 7ac: 005a lsls r2, r3, #1 + 7ae: d5f6 bpl.n 79e + 7b0: f64e 5094 movw r0, #60820 ; 0xed94 + 7b4: f2c0 0003 movt r0, #3 + 7b8: 47a8 blx r5 + 7ba: e7f0 b.n 79e + 7bc: 2b00 cmp r3, #0 + 7be: f43f af5f beq.w 680 + 7c2: f64e 50fc movw r0, #60924 ; 0xedfc + 7c6: f2c0 0003 movt r0, #3 + 7ca: 47a8 blx r5 + 7cc: e758 b.n 680 + 7ce: f64e 5018 movw r0, #60696 ; 0xed18 + 7d2: f2c0 0003 movt r0, #3 + 7d6: 47a8 blx r5 + 7d8: 6833 ldr r3, [r6, #0] + 7da: f003 4380 and.w r3, r3, #1073741824 ; 0x40000000 + 7de: e73e b.n 65e + 7e0: 2003 movs r0, #3 + 7e2: f7ff fdad bl 340 + 7e6: e71e b.n 626 + 7e8: 6823 ldr r3, [r4, #0] + 7ea: 005a lsls r2, r3, #1 + 7ec: d504 bpl.n 7f8 + 7ee: f64e 500c movw r0, #60684 ; 0xed0c + 7f2: f2c0 0003 movt r0, #3 + 7f6: 47a8 blx r5 + 7f8: f44f 73fa mov.w r3, #500 ; 0x1f4 + 7fc: f2c4 0300 movt r3, #16384 ; 0x4000 + 800: 681b ldr r3, [r3, #0] + 802: 01db lsls r3, r3, #7 + 804: f57f aefc bpl.w 600 + 808: 2338 movs r3, #56 ; 0x38 + 80a: f2c4 0300 movt r3, #16384 ; 0x4000 + 80e: 681b ldr r3, [r3, #0] + 810: 2b00 cmp r3, #0 + 812: f6bf aef5 bge.w 600 + 816: f248 60a0 movw r0, #34464 ; 0x86a0 + 81a: f2c0 0001 movt r0, #1 + 81e: f00e fad5 bl edcc + 822: e6ed b.n 600 + 824: 693b ldr r3, [r7, #16] + 826: 4798 blx r3 + 828: e6df b.n 5ea + 82a: f64e 4024 movw r0, #60452 ; 0xec24 + 82e: f24f 359d movw r5, #62365 ; 0xf39d + 832: f2c0 0003 movt r0, #3 + 836: f2c0 0500 movt r5, #0 + 83a: 47a8 blx r5 + 83c: 6823 ldr r3, [r4, #0] + 83e: 005a lsls r2, r3, #1 + 840: f57f aecb bpl.w 5da + 844: f64e 4064 movw r0, #60516 ; 0xec64 + 848: ea4f 1118 mov.w r1, r8, lsr #4 + 84c: f2c0 0003 movt r0, #3 + 850: f008 020f and.w r2, r8, #15 + 854: 47a8 blx r5 + 856: 6823 ldr r3, [r4, #0] + 858: 005b lsls r3, r3, #1 + 85a: f57f aebe bpl.w 5da + 85e: f64e 407c movw r0, #60540 ; 0xec7c + 862: f2c0 0003 movt r0, #3 + 866: 47a8 blx r5 + 868: 6823 ldr r3, [r4, #0] + 86a: 0058 lsls r0, r3, #1 + 86c: f57f aeb5 bpl.w 5da + 870: f64e 40d0 movw r0, #60624 ; 0xecd0 + 874: f2c0 0003 movt r0, #3 + 878: 47a8 blx r5 + 87a: e6ae b.n 5da + 87c: 68fb ldr r3, [r7, #12] + 87e: 4798 blx r3 + 880: e5e3 b.n 44a + 882: 687b ldr r3, [r7, #4] + 884: 4798 blx r3 + 886: e5d8 b.n 43a + 888: 68bb ldr r3, [r7, #8] + 88a: 4798 blx r3 + 88c: e5fb b.n 486 + 88e: 683b ldr r3, [r7, #0] + 890: 4798 blx r3 + 892: e5f0 b.n 476 + 894: 00030c80 .word 0x00030c80 + +00000898 : + 898: f241 0385 movw r3, #4229 ; 0x1085 + 89c: b570 push {r4, r5, r6, lr} + 89e: f240 3518 movw r5, #792 ; 0x318 + 8a2: f6c0 0342 movt r3, #2114 ; 0x842 + 8a6: f2c1 0500 movt r5, #4096 ; 0x1000 + 8aa: fba3 2300 umull r2, r3, r3, r0 + 8ae: 1ac6 subs r6, r0, r3 + 8b0: eb03 0656 add.w r6, r3, r6, lsr #1 + 8b4: 0936 lsrs r6, r6, #4 + 8b6: f04f 0001 mov.w r0, #1 + 8ba: 68ab ldr r3, [r5, #8] + 8bc: bf08 it eq + 8be: 4606 moveq r6, r0 + 8c0: 4798 blx r3 + 8c2: 4604 mov r4, r0 + 8c4: 68ab ldr r3, [r5, #8] + 8c6: 2001 movs r0, #1 + 8c8: 4798 blx r3 + 8ca: 4284 cmp r4, r0 + 8cc: eba4 0300 sub.w r3, r4, r0 + 8d0: bf34 ite cc + 8d2: f103 30ff addcc.w r0, r3, #4294967295 + 8d6: 1a20 subcs r0, r4, r0 + 8d8: 42b0 cmp r0, r6 + 8da: d9f3 bls.n 8c4 + 8dc: 2000 movs r0, #0 + 8de: bd70 pop {r4, r5, r6, pc} + +000008e0 : + 8e0: f240 3214 movw r2, #788 ; 0x314 + 8e4: f2c1 0200 movt r2, #4096 ; 0x1000 + 8e8: b508 push {r3, lr} + 8ea: f44f 5300 mov.w r3, #8192 ; 0x2000 + 8ee: f2c4 0300 movt r3, #16384 ; 0x4000 + 8f2: 6812 ldr r2, [r2, #0] + 8f4: 4013 ands r3, r2 + 8f6: b903 cbnz r3, 8fa + 8f8: e7fe b.n 8f8 + 8fa: f64e 605c movw r0, #61020 ; 0xee5c + 8fe: f24f 339d movw r3, #62365 ; 0xf39d + 902: f2c0 0003 movt r0, #3 + 906: f2c0 0300 movt r3, #0 + 90a: 4798 blx r3 + 90c: e7f4 b.n 8f8 + 90e: bf00 nop + +00000910 : + 910: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 914: f240 3614 movw r6, #788 ; 0x314 + 918: f2c1 0600 movt r6, #4096 ; 0x1000 + 91c: f44f 5300 mov.w r3, #8192 ; 0x2000 + 920: f2c4 0300 movt r3, #16384 ; 0x4000 + 924: 6832 ldr r2, [r6, #0] + 926: b08b sub sp, #44 ; 0x2c + 928: 4013 ands r3, r2 + 92a: 4605 mov r5, r0 + 92c: 2b00 cmp r3, #0 + 92e: f040 815a bne.w be6 + 932: f24f 349d movw r4, #62365 ; 0xf39d + 936: f2c0 0400 movt r4, #0 + 93a: f64e 5b38 movw fp, #60728 ; 0xed38 + 93e: f64e 5c28 movw ip, #60712 ; 0xed28 + 942: f64e 5e2c movw lr, #60716 ; 0xed2c + 946: f64e 5030 movw r0, #60720 ; 0xed30 + 94a: f64e 523c movw r2, #60732 ; 0xed3c + 94e: f2ce 0b00 movt fp, #57344 ; 0xe000 + 952: f2ce 0c00 movt ip, #57344 ; 0xe000 + 956: f2ce 0e00 movt lr, #57344 ; 0xe000 + 95a: f2ce 0000 movt r0, #57344 ; 0xe000 + 95e: f2ce 0200 movt r2, #57344 ; 0xe000 + 962: 6829 ldr r1, [r5, #0] + 964: f8d5 a004 ldr.w sl, [r5, #4] + 968: f8d5 9008 ldr.w r9, [r5, #8] + 96c: 68ef ldr r7, [r5, #12] + 96e: 9702 str r7, [sp, #8] + 970: 692f ldr r7, [r5, #16] + 972: 9701 str r7, [sp, #4] + 974: 696f ldr r7, [r5, #20] + 976: 9703 str r7, [sp, #12] + 978: 69af ldr r7, [r5, #24] + 97a: 9704 str r7, [sp, #16] + 97c: 69ef ldr r7, [r5, #28] + 97e: f8db b000 ldr.w fp, [fp] + 982: f8dc 5000 ldr.w r5, [ip] + 986: 9506 str r5, [sp, #24] + 988: f8de 5000 ldr.w r5, [lr] + 98c: 6800 ldr r0, [r0, #0] + 98e: 6812 ldr r2, [r2, #0] + 990: 9507 str r5, [sp, #28] + 992: 9008 str r0, [sp, #32] + 994: 9209 str r2, [sp, #36] ; 0x24 + 996: b903 cbnz r3, 99a + 998: e7fe b.n 998 + 99a: f64e 60a4 movw r0, #61092 ; 0xeea4 + 99e: f2c0 0003 movt r0, #3 + 9a2: 47a0 blx r4 + 9a4: f44f 5200 mov.w r2, #8192 ; 0x2000 + 9a8: f2c4 0200 movt r2, #16384 ; 0x4000 + 9ac: f24f 359d movw r5, #62365 ; 0xf39d + 9b0: f240 3814 movw r8, #788 ; 0x314 + 9b4: 6831 ldr r1, [r6, #0] + 9b6: f2c0 0500 movt r5, #0 + 9ba: 400a ands r2, r1 + 9bc: f2c1 0800 movt r8, #4096 ; 0x1000 + 9c0: 2a00 cmp r2, #0 + 9c2: d0e9 beq.n 998 + 9c4: f64e 60c0 movw r0, #61120 ; 0xeec0 + 9c8: 4651 mov r1, sl + 9ca: f2c0 0003 movt r0, #3 + 9ce: 47a8 blx r5 + 9d0: f44f 5200 mov.w r2, #8192 ; 0x2000 + 9d4: f2c4 0200 movt r2, #16384 ; 0x4000 + 9d8: f8d8 1000 ldr.w r1, [r8] + 9dc: 400a ands r2, r1 + 9de: 2a00 cmp r2, #0 + 9e0: d0da beq.n 998 + 9e2: f64e 60dc movw r0, #61148 ; 0xeedc + 9e6: 4649 mov r1, r9 + 9e8: f2c0 0003 movt r0, #3 + 9ec: 47a8 blx r5 + 9ee: f44f 5200 mov.w r2, #8192 ; 0x2000 + 9f2: f2c4 0200 movt r2, #16384 ; 0x4000 + 9f6: f8d8 1000 ldr.w r1, [r8] + 9fa: 400a ands r2, r1 + 9fc: 2a00 cmp r2, #0 + 9fe: d0cb beq.n 998 + a00: f64e 60f8 movw r0, #61176 ; 0xeef8 + a04: 9902 ldr r1, [sp, #8] + a06: f2c0 0003 movt r0, #3 + a0a: 47a8 blx r5 + a0c: f44f 5200 mov.w r2, #8192 ; 0x2000 + a10: f2c4 0200 movt r2, #16384 ; 0x4000 + a14: f8d8 1000 ldr.w r1, [r8] + a18: 400a ands r2, r1 + a1a: 2a00 cmp r2, #0 + a1c: d0bc beq.n 998 + a1e: f64e 7014 movw r0, #61204 ; 0xef14 + a22: 9901 ldr r1, [sp, #4] + a24: f2c0 0003 movt r0, #3 + a28: 47a8 blx r5 + a2a: f44f 5200 mov.w r2, #8192 ; 0x2000 + a2e: f2c4 0200 movt r2, #16384 ; 0x4000 + a32: f8d8 1000 ldr.w r1, [r8] + a36: 400a ands r2, r1 + a38: 2a00 cmp r2, #0 + a3a: d0ad beq.n 998 + a3c: f64e 7030 movw r0, #61232 ; 0xef30 + a40: 9903 ldr r1, [sp, #12] + a42: f2c0 0003 movt r0, #3 + a46: 47a8 blx r5 + a48: f44f 5200 mov.w r2, #8192 ; 0x2000 + a4c: f2c4 0200 movt r2, #16384 ; 0x4000 + a50: f8d8 1000 ldr.w r1, [r8] + a54: 400a ands r2, r1 + a56: 2a00 cmp r2, #0 + a58: d09e beq.n 998 + a5a: f64e 704c movw r0, #61260 ; 0xef4c + a5e: 9904 ldr r1, [sp, #16] + a60: f2c0 0003 movt r0, #3 + a64: 47a8 blx r5 + a66: f44f 5200 mov.w r2, #8192 ; 0x2000 + a6a: f2c4 0200 movt r2, #16384 ; 0x4000 + a6e: f8d8 1000 ldr.w r1, [r8] + a72: 400a ands r2, r1 + a74: 2a00 cmp r2, #0 + a76: d08f beq.n 998 + a78: f64e 7068 movw r0, #61288 ; 0xef68 + a7c: 4639 mov r1, r7 + a7e: f2c0 0003 movt r0, #3 + a82: 47a8 blx r5 + a84: f44f 5200 mov.w r2, #8192 ; 0x2000 + a88: f2c4 0200 movt r2, #16384 ; 0x4000 + a8c: f8d8 1000 ldr.w r1, [r8] + a90: 400a ands r2, r1 + a92: 2a00 cmp r2, #0 + a94: d080 beq.n 998 + a96: f64e 7084 movw r0, #61316 ; 0xef84 + a9a: 4659 mov r1, fp + a9c: f2c0 0003 movt r0, #3 + aa0: 47a8 blx r5 + aa2: f44f 5200 mov.w r2, #8192 ; 0x2000 + aa6: f2c4 0200 movt r2, #16384 ; 0x4000 + aaa: f8d8 3000 ldr.w r3, [r8] + aae: 401a ands r2, r3 + ab0: 2a00 cmp r2, #0 + ab2: f43f af71 beq.w 998 + ab6: f64e 70a4 movw r0, #61348 ; 0xefa4 + aba: 9906 ldr r1, [sp, #24] + abc: f2c0 0003 movt r0, #3 + ac0: 47a0 blx r4 + ac2: f44f 5300 mov.w r3, #8192 ; 0x2000 + ac6: f2c4 0300 movt r3, #16384 ; 0x4000 + aca: f24f 349d movw r4, #62365 ; 0xf39d + ace: 6832 ldr r2, [r6, #0] + ad0: f2c0 0400 movt r4, #0 + ad4: 4013 ands r3, r2 + ad6: 2b00 cmp r3, #0 + ad8: f43f af5e beq.w 998 + adc: f64e 70c4 movw r0, #61380 ; 0xefc4 + ae0: 9907 ldr r1, [sp, #28] + ae2: f2c0 0003 movt r0, #3 + ae6: 47a0 blx r4 + ae8: f44f 5300 mov.w r3, #8192 ; 0x2000 + aec: f2c4 0300 movt r3, #16384 ; 0x4000 + af0: f8d8 2000 ldr.w r2, [r8] + af4: 4013 ands r3, r2 + af6: 2b00 cmp r3, #0 + af8: f43f af4e beq.w 998 + afc: f64e 70e4 movw r0, #61412 ; 0xefe4 + b00: 9908 ldr r1, [sp, #32] + b02: f2c0 0003 movt r0, #3 + b06: 47a0 blx r4 + b08: f44f 5300 mov.w r3, #8192 ; 0x2000 + b0c: f2c4 0300 movt r3, #16384 ; 0x4000 + b10: f8d8 2000 ldr.w r2, [r8] + b14: 4013 ands r3, r2 + b16: 2b00 cmp r3, #0 + b18: f43f af3e beq.w 998 + b1c: f24f 0004 movw r0, #61444 ; 0xf004 + b20: 9909 ldr r1, [sp, #36] ; 0x24 + b22: f2c0 0003 movt r0, #3 + b26: 47a0 blx r4 + b28: f44f 5300 mov.w r3, #8192 ; 0x2000 + b2c: f2c4 0300 movt r3, #16384 ; 0x4000 + b30: f8d8 2000 ldr.w r2, [r8] + b34: 4013 ands r3, r2 + b36: 2b00 cmp r3, #0 + b38: f43f af2e beq.w 998 + b3c: f3ef 8110 mrs r1, PRIMASK + b40: f24f 0024 movw r0, #61476 ; 0xf024 + b44: f2c0 0003 movt r0, #3 + b48: 47a0 blx r4 + b4a: f44f 5300 mov.w r3, #8192 ; 0x2000 + b4e: f2c4 0300 movt r3, #16384 ; 0x4000 + b52: f8d8 2000 ldr.w r2, [r8] + b56: 4013 ands r3, r2 + b58: 2b00 cmp r3, #0 + b5a: f43f af1d beq.w 998 + b5e: f3ef 8112 mrs r1, BASEPRI_MAX + b62: f24f 0044 movw r0, #61508 ; 0xf044 + b66: f2c0 0003 movt r0, #3 + b6a: 47a0 blx r4 + b6c: f44f 5300 mov.w r3, #8192 ; 0x2000 + b70: f2c4 0300 movt r3, #16384 ; 0x4000 + b74: f8d8 2000 ldr.w r2, [r8] + b78: 4013 ands r3, r2 + b7a: 2b00 cmp r3, #0 + b7c: f43f af0c beq.w 998 + b80: f64e 531f movw r3, #60703 ; 0xed1f + b84: f24f 0064 movw r0, #61540 ; 0xf064 + b88: f2ce 0300 movt r3, #57344 ; 0xe000 + b8c: f2c0 0003 movt r0, #3 + b90: 7819 ldrb r1, [r3, #0] + b92: 47a0 blx r4 + b94: f44f 5300 mov.w r3, #8192 ; 0x2000 + b98: f2c4 0300 movt r3, #16384 ; 0x4000 + b9c: f8d8 2000 ldr.w r2, [r8] + ba0: 4013 ands r3, r2 + ba2: 2b00 cmp r3, #0 + ba4: f43f aef8 beq.w 998 + ba8: f64e 5322 movw r3, #60706 ; 0xed22 + bac: f24f 008c movw r0, #61580 ; 0xf08c + bb0: f2ce 0300 movt r3, #57344 ; 0xe000 + bb4: f2c0 0003 movt r0, #3 + bb8: 7819 ldrb r1, [r3, #0] + bba: 47a0 blx r4 + bbc: f44f 5300 mov.w r3, #8192 ; 0x2000 + bc0: f2c4 0300 movt r3, #16384 ; 0x4000 + bc4: f8d8 2000 ldr.w r2, [r8] + bc8: 4013 ands r3, r2 + bca: 2b00 cmp r3, #0 + bcc: f43f aee4 beq.w 998 + bd0: f64e 5323 movw r3, #60707 ; 0xed23 + bd4: f24f 00b8 movw r0, #61624 ; 0xf0b8 + bd8: f2ce 0300 movt r3, #57344 ; 0xe000 + bdc: f2c0 0003 movt r0, #3 + be0: 7819 ldrb r1, [r3, #0] + be2: 47a0 blx r4 + be4: e6d8 b.n 998 + be6: f64e 607c movw r0, #61052 ; 0xee7c + bea: f24f 349d movw r4, #62365 ; 0xf39d + bee: f2c0 0003 movt r0, #3 + bf2: f2c0 0400 movt r4, #0 + bf6: 47a0 blx r4 + bf8: f44f 5300 mov.w r3, #8192 ; 0x2000 + bfc: f2c4 0300 movt r3, #16384 ; 0x4000 + c00: 6832 ldr r2, [r6, #0] + c02: 4013 ands r3, r2 + c04: e699 b.n 93a + c06: bf00 nop + +00000c08 : + c08: f240 3214 movw r2, #788 ; 0x314 + c0c: f2c1 0200 movt r2, #4096 ; 0x1000 + c10: b508 push {r3, lr} + c12: f44f 5300 mov.w r3, #8192 ; 0x2000 + c16: f2c4 0300 movt r3, #16384 ; 0x4000 + c1a: 6812 ldr r2, [r2, #0] + c1c: 4013 ands r3, r2 + c1e: b903 cbnz r3, c22 + c20: e7fe b.n c20 + c22: f24f 00e4 movw r0, #61668 ; 0xf0e4 + c26: f24f 339d movw r3, #62365 ; 0xf39d + c2a: f2c0 0003 movt r0, #3 + c2e: f2c0 0300 movt r3, #0 + c32: 4798 blx r3 + c34: e7f4 b.n c20 + c36: bf00 nop + +00000c38 : + c38: f240 3214 movw r2, #788 ; 0x314 + c3c: f2c1 0200 movt r2, #4096 ; 0x1000 + c40: b508 push {r3, lr} + c42: f44f 5300 mov.w r3, #8192 ; 0x2000 + c46: f2c4 0300 movt r3, #16384 ; 0x4000 + c4a: 6812 ldr r2, [r2, #0] + c4c: 4013 ands r3, r2 + c4e: b903 cbnz r3, c52 + c50: e7fe b.n c50 + c52: f24f 1010 movw r0, #61712 ; 0xf110 + c56: f24f 339d movw r3, #62365 ; 0xf39d + c5a: f2c0 0003 movt r0, #3 + c5e: f2c0 0300 movt r3, #0 + c62: 4798 blx r3 + c64: e7f4 b.n c50 + c66: bf00 nop + +00000c68 : + c68: f240 3214 movw r2, #788 ; 0x314 + c6c: f2c1 0200 movt r2, #4096 ; 0x1000 + c70: b508 push {r3, lr} + c72: f44f 5300 mov.w r3, #8192 ; 0x2000 + c76: f2c4 0300 movt r3, #16384 ; 0x4000 + c7a: 6812 ldr r2, [r2, #0] + c7c: 4013 ands r3, r2 + c7e: b903 cbnz r3, c82 + c80: e7fe b.n c80 + c82: f24f 1038 movw r0, #61752 ; 0xf138 + c86: f24f 339d movw r3, #62365 ; 0xf39d + c8a: f2c0 0003 movt r0, #3 + c8e: f2c0 0300 movt r3, #0 + c92: 4798 blx r3 + c94: e7f4 b.n c80 + c96: bf00 nop + +00000c98 : + c98: f240 3334 movw r3, #820 ; 0x334 + c9c: f44f 7248 mov.w r2, #800 ; 0x320 + ca0: f2c1 0300 movt r3, #4096 ; 0x1000 + ca4: f2c4 0200 movt r2, #16384 ; 0x4000 + ca8: b470 push {r4, r5, r6} + caa: f833 6010 ldrh.w r6, [r3, r0, lsl #1] + cae: 6814 ldr r4, [r2, #0] + cb0: 2501 movs r5, #1 + cb2: 4085 lsls r5, r0 + cb4: 4331 orrs r1, r6 + cb6: 432c orrs r4, r5 + cb8: f823 1010 strh.w r1, [r3, r0, lsl #1] + cbc: 6014 str r4, [r2, #0] + cbe: bc70 pop {r4, r5, r6} + cc0: 4770 bx lr + cc2: bf00 nop + +00000cc4 : + cc4: b9ca cbnz r2, cfa + cc6: f240 3334 movw r3, #820 ; 0x334 + cca: f2c1 0300 movt r3, #4096 ; 0x1000 + cce: b430 push {r4, r5} + cd0: 460d mov r5, r1 + cd2: f833 1010 ldrh.w r1, [r3, r0, lsl #1] + cd6: ea21 0105 bic.w r1, r1, r5 + cda: f823 1010 strh.w r1, [r3, r0, lsl #1] + cde: b951 cbnz r1, cf6 + ce0: f44f 7348 mov.w r3, #800 ; 0x320 + ce4: f2c4 0300 movt r3, #16384 ; 0x4000 + ce8: 2101 movs r1, #1 + cea: 681a ldr r2, [r3, #0] + cec: fa01 f400 lsl.w r4, r1, r0 + cf0: ea22 0404 bic.w r4, r2, r4 + cf4: 601c str r4, [r3, #0] + cf6: bc30 pop {r4, r5} + cf8: 4770 bx lr + cfa: e7cd b.n c98 + +00000cfc : + cfc: 2801 cmp r0, #1 + cfe: b510 push {r4, lr} + d00: 4604 mov r4, r0 + d02: d03b beq.n d7c + d04: d31c bcc.n d40 + d06: 2802 cmp r0, #2 + d08: d00e beq.n d28 + d0a: b9b9 cbnz r1, d3c + d0c: f44f 7320 mov.w r3, #640 ; 0x280 + d10: f2c4 0300 movt r3, #16384 ; 0x4000 + d14: 681a ldr r2, [r3, #0] + d16: 2001 movs r0, #1 + d18: f022 020e bic.w r2, r2, #14 + d1c: 601a str r2, [r3, #0] + d1e: 681a ldr r2, [r3, #0] + d20: f022 0201 bic.w r2, r2, #1 + d24: 601a str r2, [r3, #0] + d26: bd10 pop {r4, pc} + d28: 2900 cmp r1, #0 + d2a: d03b beq.n da4 + d2c: f240 3334 movw r3, #820 ; 0x334 + d30: f2c1 0300 movt r3, #4096 ; 0x1000 + d34: 8818 ldrh r0, [r3, #0] + d36: f010 00e8 ands.w r0, r0, #232 ; 0xe8 + d3a: d03f beq.n dbc + d3c: 2000 movs r0, #0 + d3e: bd10 pop {r4, pc} + d40: b351 cbz r1, d98 + d42: f240 3334 movw r3, #820 ; 0x334 + d46: f2c1 0300 movt r3, #4096 ; 0x1000 + d4a: 889b ldrh r3, [r3, #4] + d4c: 071a lsls r2, r3, #28 + d4e: d1f5 bne.n d3c + d50: 460a mov r2, r1 + d52: 2002 movs r0, #2 + d54: 210f movs r1, #15 + d56: f7ff ffb5 bl cc4 + d5a: f44f 7320 mov.w r3, #640 ; 0x280 + d5e: f2c4 0300 movt r3, #16384 ; 0x4000 + d62: 681a ldr r2, [r3, #0] + d64: f004 0407 and.w r4, r4, #7 + d68: f022 020e bic.w r2, r2, #14 + d6c: ea42 0444 orr.w r4, r2, r4, lsl #1 + d70: 601c str r4, [r3, #0] + d72: 681a ldr r2, [r3, #0] + d74: 2001 movs r0, #1 + d76: 4302 orrs r2, r0 + d78: 601a str r2, [r3, #0] + d7a: bd10 pop {r4, pc} + d7c: b1c1 cbz r1, db0 + d7e: f240 3334 movw r3, #820 ; 0x334 + d82: f2c1 0300 movt r3, #4096 ; 0x1000 + d86: 891b ldrh r3, [r3, #8] + d88: 071b lsls r3, r3, #28 + d8a: d1d7 bne.n d3c + d8c: 460a mov r2, r1 + d8e: 2004 movs r0, #4 + d90: 210f movs r1, #15 + d92: f7ff ff97 bl cc4 + d96: e7e0 b.n d5a + d98: 460a mov r2, r1 + d9a: 2002 movs r0, #2 + d9c: 210f movs r1, #15 + d9e: f7ff ff91 bl cc4 + da2: e7b3 b.n d0c + da4: 4608 mov r0, r1 + da6: 21e8 movs r1, #232 ; 0xe8 + da8: 4602 mov r2, r0 + daa: f7ff ff8b bl cc4 + dae: e7ad b.n d0c + db0: 460a mov r2, r1 + db2: 2004 movs r0, #4 + db4: 210f movs r1, #15 + db6: f7ff ff85 bl cc4 + dba: e7a7 b.n d0c + dbc: 460a mov r2, r1 + dbe: 21e8 movs r1, #232 ; 0xe8 + dc0: f7ff ff80 bl cc4 + dc4: e7c9 b.n d5a + dc6: bf00 nop + +00000dc8 : + dc8: 2801 cmp r0, #1 + dca: b510 push {r4, lr} + dcc: 4604 mov r4, r0 + dce: d03c beq.n e4a + dd0: d31d bcc.n e0e + dd2: 2802 cmp r0, #2 + dd4: d00e beq.n df4 + dd6: b9c1 cbnz r1, e0a + dd8: f44f 7320 mov.w r3, #640 ; 0x280 + ddc: f2c4 0300 movt r3, #16384 ; 0x4000 + de0: 681a ldr r2, [r3, #0] + de2: 2001 movs r0, #1 + de4: f022 02e0 bic.w r2, r2, #224 ; 0xe0 + de8: 601a str r2, [r3, #0] + dea: 681a ldr r2, [r3, #0] + dec: f022 0210 bic.w r2, r2, #16 + df0: 601a str r2, [r3, #0] + df2: bd10 pop {r4, pc} + df4: 2900 cmp r1, #0 + df6: d03e beq.n e76 + df8: f240 3334 movw r3, #820 ; 0x334 + dfc: f2c1 0300 movt r3, #4096 ; 0x1000 + e00: 885b ldrh r3, [r3, #2] + e02: f003 03f0 and.w r3, r3, #240 ; 0xf0 + e06: 2b00 cmp r3, #0 + e08: d041 beq.n e8e + e0a: 2000 movs r0, #0 + e0c: bd10 pop {r4, pc} + e0e: b361 cbz r1, e6a + e10: f240 3334 movw r3, #820 ; 0x334 + e14: f2c1 0300 movt r3, #4096 ; 0x1000 + e18: 88db ldrh r3, [r3, #6] + e1a: 071b lsls r3, r3, #28 + e1c: d1f5 bne.n e0a + e1e: 460a mov r2, r1 + e20: 2003 movs r0, #3 + e22: 210f movs r1, #15 + e24: f7ff ff4e bl cc4 + e28: f44f 7320 mov.w r3, #640 ; 0x280 + e2c: f2c4 0300 movt r3, #16384 ; 0x4000 + e30: 681a ldr r2, [r3, #0] + e32: 0164 lsls r4, r4, #5 + e34: f022 02e0 bic.w r2, r2, #224 ; 0xe0 + e38: b2e4 uxtb r4, r4 + e3a: 4314 orrs r4, r2 + e3c: 601c str r4, [r3, #0] + e3e: 681a ldr r2, [r3, #0] + e40: 2001 movs r0, #1 + e42: f042 0210 orr.w r2, r2, #16 + e46: 601a str r2, [r3, #0] + e48: bd10 pop {r4, pc} + e4a: b1d1 cbz r1, e82 + e4c: f240 3334 movw r3, #820 ; 0x334 + e50: f2c1 0300 movt r3, #4096 ; 0x1000 + e54: 891b ldrh r3, [r3, #8] + e56: f003 03f0 and.w r3, r3, #240 ; 0xf0 + e5a: 2b00 cmp r3, #0 + e5c: d1d5 bne.n e0a + e5e: 460a mov r2, r1 + e60: 2004 movs r0, #4 + e62: 21f0 movs r1, #240 ; 0xf0 + e64: f7ff ff2e bl cc4 + e68: e7de b.n e28 + e6a: 460a mov r2, r1 + e6c: 2003 movs r0, #3 + e6e: 210f movs r1, #15 + e70: f7ff ff28 bl cc4 + e74: e7b0 b.n dd8 + e76: 460a mov r2, r1 + e78: 2001 movs r0, #1 + e7a: 21f0 movs r1, #240 ; 0xf0 + e7c: f7ff ff22 bl cc4 + e80: e7aa b.n dd8 + e82: 460a mov r2, r1 + e84: 2004 movs r0, #4 + e86: 21f0 movs r1, #240 ; 0xf0 + e88: f7ff ff1c bl cc4 + e8c: e7a4 b.n dd8 + e8e: 460a mov r2, r1 + e90: 2001 movs r0, #1 + e92: 21f0 movs r1, #240 ; 0xf0 + e94: f7ff ff16 bl cc4 + e98: e7c6 b.n e28 + e9a: bf00 nop + +00000e9c : + e9c: 2801 cmp r0, #1 + e9e: b510 push {r4, lr} + ea0: 4604 mov r4, r0 + ea2: d03d beq.n f20 + ea4: d31d bcc.n ee2 + ea6: 2802 cmp r0, #2 + ea8: d00e beq.n ec8 + eaa: b9c1 cbnz r1, ede + eac: f44f 7320 mov.w r3, #640 ; 0x280 + eb0: f2c4 0300 movt r3, #16384 ; 0x4000 + eb4: 681a ldr r2, [r3, #0] + eb6: 2001 movs r0, #1 + eb8: f422 6260 bic.w r2, r2, #3584 ; 0xe00 + ebc: 601a str r2, [r3, #0] + ebe: 681a ldr r2, [r3, #0] + ec0: f422 7280 bic.w r2, r2, #256 ; 0x100 + ec4: 601a str r2, [r3, #0] + ec6: bd10 pop {r4, pc} + ec8: 2900 cmp r1, #0 + eca: d040 beq.n f4e + ecc: f240 3334 movw r3, #820 ; 0x334 + ed0: f2c1 0300 movt r3, #4096 ; 0x1000 + ed4: 88db ldrh r3, [r3, #6] + ed6: f003 03f0 and.w r3, r3, #240 ; 0xf0 + eda: 2b00 cmp r3, #0 + edc: d044 beq.n f68 + ede: 2000 movs r0, #0 + ee0: bd10 pop {r4, pc} + ee2: b371 cbz r1, f42 + ee4: f240 3334 movw r3, #820 ; 0x334 + ee8: f2c1 0300 movt r3, #4096 ; 0x1000 + eec: 8818 ldrh r0, [r3, #0] + eee: f010 0017 ands.w r0, r0, #23 + ef2: d1f4 bne.n ede + ef4: 460a mov r2, r1 + ef6: 2117 movs r1, #23 + ef8: f7ff fee4 bl cc4 + efc: f44f 7320 mov.w r3, #640 ; 0x280 + f00: f2c4 0300 movt r3, #16384 ; 0x4000 + f04: 681a ldr r2, [r3, #0] + f06: f004 0407 and.w r4, r4, #7 + f0a: f422 6260 bic.w r2, r2, #3584 ; 0xe00 + f0e: ea42 2444 orr.w r4, r2, r4, lsl #9 + f12: 601c str r4, [r3, #0] + f14: 681a ldr r2, [r3, #0] + f16: 2001 movs r0, #1 + f18: f442 7280 orr.w r2, r2, #256 ; 0x100 + f1c: 601a str r2, [r3, #0] + f1e: bd10 pop {r4, pc} + f20: b1d9 cbz r1, f5a + f22: f240 3334 movw r3, #820 ; 0x334 + f26: f2c1 0300 movt r3, #4096 ; 0x1000 + f2a: 889b ldrh r3, [r3, #4] + f2c: f403 7370 and.w r3, r3, #960 ; 0x3c0 + f30: 2b00 cmp r3, #0 + f32: d1d4 bne.n ede + f34: 460a mov r2, r1 + f36: 2002 movs r0, #2 + f38: f44f 7170 mov.w r1, #960 ; 0x3c0 + f3c: f7ff fec2 bl cc4 + f40: e7dc b.n efc + f42: 4608 mov r0, r1 + f44: 2117 movs r1, #23 + f46: 4602 mov r2, r0 + f48: f7ff febc bl cc4 + f4c: e7ae b.n eac + f4e: 460a mov r2, r1 + f50: 2003 movs r0, #3 + f52: 21f0 movs r1, #240 ; 0xf0 + f54: f7ff feb6 bl cc4 + f58: e7a8 b.n eac + f5a: 460a mov r2, r1 + f5c: 2002 movs r0, #2 + f5e: f44f 7170 mov.w r1, #960 ; 0x3c0 + f62: f7ff feaf bl cc4 + f66: e7a1 b.n eac + f68: 460a mov r2, r1 + f6a: 2003 movs r0, #3 + f6c: 21f0 movs r1, #240 ; 0xf0 + f6e: f7ff fea9 bl cc4 + f72: e7c3 b.n efc + +00000f74 : + f74: b510 push {r4, lr} + f76: 4604 mov r4, r0 + f78: b1e0 cbz r0, fb4 + f7a: 2801 cmp r0, #1 + f7c: d10a bne.n f94 + f7e: 2900 cmp r1, #0 + f80: d042 beq.n 1008 + f82: f240 3334 movw r3, #820 ; 0x334 + f86: f2c1 0300 movt r3, #4096 ; 0x1000 + f8a: 889b ldrh r3, [r3, #4] + f8c: 071b lsls r3, r3, #28 + f8e: d02f beq.n ff0 + f90: 2000 movs r0, #0 + f92: bd10 pop {r4, pc} + f94: 2900 cmp r1, #0 + f96: d1fb bne.n f90 + f98: f44f 7321 mov.w r3, #644 ; 0x284 + f9c: f2c4 0300 movt r3, #16384 ; 0x4000 + fa0: 681a ldr r2, [r3, #0] + fa2: 2001 movs r0, #1 + fa4: f022 020e bic.w r2, r2, #14 + fa8: 601a str r2, [r3, #0] + faa: 681a ldr r2, [r3, #0] + fac: f022 0201 bic.w r2, r2, #1 + fb0: 601a str r2, [r3, #0] + fb2: bd10 pop {r4, pc} + fb4: b311 cbz r1, ffc + fb6: f240 3334 movw r3, #820 ; 0x334 + fba: f2c1 0300 movt r3, #4096 ; 0x1000 + fbe: 891b ldrh r3, [r3, #8] + fc0: 071a lsls r2, r3, #28 + fc2: d1e5 bne.n f90 + fc4: 460a mov r2, r1 + fc6: 2004 movs r0, #4 + fc8: 210f movs r1, #15 + fca: f7ff fe7b bl cc4 + fce: f44f 7321 mov.w r3, #644 ; 0x284 + fd2: f2c4 0300 movt r3, #16384 ; 0x4000 + fd6: 681a ldr r2, [r3, #0] + fd8: f004 0407 and.w r4, r4, #7 + fdc: f022 020e bic.w r2, r2, #14 + fe0: ea42 0444 orr.w r4, r2, r4, lsl #1 + fe4: 601c str r4, [r3, #0] + fe6: 681a ldr r2, [r3, #0] + fe8: 2001 movs r0, #1 + fea: 4302 orrs r2, r0 + fec: 601a str r2, [r3, #0] + fee: bd10 pop {r4, pc} + ff0: 460a mov r2, r1 + ff2: 2002 movs r0, #2 + ff4: 210f movs r1, #15 + ff6: f7ff fe65 bl cc4 + ffa: e7e8 b.n fce + ffc: 460a mov r2, r1 + ffe: 2004 movs r0, #4 + 1000: 210f movs r1, #15 + 1002: f7ff fe5f bl cc4 + 1006: e7c7 b.n f98 + 1008: 460a mov r2, r1 + 100a: 2002 movs r0, #2 + 100c: 210f movs r1, #15 + 100e: f7ff fe59 bl cc4 + 1012: e7c1 b.n f98 + +00001014 : + 1014: 2801 cmp r0, #1 + 1016: b510 push {r4, lr} + 1018: 4604 mov r4, r0 + 101a: d03c beq.n 1096 + 101c: d31d bcc.n 105a + 101e: 2802 cmp r0, #2 + 1020: d00e beq.n 1040 + 1022: b9c1 cbnz r1, 1056 + 1024: f44f 7321 mov.w r3, #644 ; 0x284 + 1028: f2c4 0300 movt r3, #16384 ; 0x4000 + 102c: 681a ldr r2, [r3, #0] + 102e: 2001 movs r0, #1 + 1030: f022 02e0 bic.w r2, r2, #224 ; 0xe0 + 1034: 601a str r2, [r3, #0] + 1036: 681a ldr r2, [r3, #0] + 1038: f022 0210 bic.w r2, r2, #16 + 103c: 601a str r2, [r3, #0] + 103e: bd10 pop {r4, pc} + 1040: 2900 cmp r1, #0 + 1042: d03d beq.n 10c0 + 1044: f240 3334 movw r3, #820 ; 0x334 + 1048: f2c1 0300 movt r3, #4096 ; 0x1000 + 104c: 88db ldrh r3, [r3, #6] + 104e: f003 03f0 and.w r3, r3, #240 ; 0xf0 + 1052: 2b00 cmp r3, #0 + 1054: d03f beq.n 10d6 + 1056: 2000 movs r0, #0 + 1058: bd10 pop {r4, pc} + 105a: b359 cbz r1, 10b4 + 105c: f240 3334 movw r3, #820 ; 0x334 + 1060: f2c1 0300 movt r3, #4096 ; 0x1000 + 1064: 8818 ldrh r0, [r3, #0] + 1066: f010 0017 ands.w r0, r0, #23 + 106a: d1f4 bne.n 1056 + 106c: 460a mov r2, r1 + 106e: 2117 movs r1, #23 + 1070: f7ff fe28 bl cc4 + 1074: f44f 7321 mov.w r3, #644 ; 0x284 + 1078: f2c4 0300 movt r3, #16384 ; 0x4000 + 107c: 681a ldr r2, [r3, #0] + 107e: 0164 lsls r4, r4, #5 + 1080: f022 02e0 bic.w r2, r2, #224 ; 0xe0 + 1084: b2e4 uxtb r4, r4 + 1086: 4314 orrs r4, r2 + 1088: 601c str r4, [r3, #0] + 108a: 681a ldr r2, [r3, #0] + 108c: 2001 movs r0, #1 + 108e: f042 0210 orr.w r2, r2, #16 + 1092: 601a str r2, [r3, #0] + 1094: bd10 pop {r4, pc} + 1096: b1c9 cbz r1, 10cc + 1098: f240 3334 movw r3, #820 ; 0x334 + 109c: f2c1 0300 movt r3, #4096 ; 0x1000 + 10a0: 885b ldrh r3, [r3, #2] + 10a2: f003 03f0 and.w r3, r3, #240 ; 0xf0 + 10a6: 2b00 cmp r3, #0 + 10a8: d1d5 bne.n 1056 + 10aa: 460a mov r2, r1 + 10ac: 21f0 movs r1, #240 ; 0xf0 + 10ae: f7ff fe09 bl cc4 + 10b2: e7df b.n 1074 + 10b4: 4608 mov r0, r1 + 10b6: 2117 movs r1, #23 + 10b8: 4602 mov r2, r0 + 10ba: f7ff fe03 bl cc4 + 10be: e7b1 b.n 1024 + 10c0: 460a mov r2, r1 + 10c2: 2003 movs r0, #3 + 10c4: 21f0 movs r1, #240 ; 0xf0 + 10c6: f7ff fdfd bl cc4 + 10ca: e7ab b.n 1024 + 10cc: 460a mov r2, r1 + 10ce: 21f0 movs r1, #240 ; 0xf0 + 10d0: f7ff fdf8 bl cc4 + 10d4: e7a6 b.n 1024 + 10d6: 460a mov r2, r1 + 10d8: 2003 movs r0, #3 + 10da: 21f0 movs r1, #240 ; 0xf0 + 10dc: f7ff fdf2 bl cc4 + 10e0: e7c8 b.n 1074 + 10e2: bf00 nop + +000010e4 : + 10e4: 2801 cmp r0, #1 + 10e6: b510 push {r4, lr} + 10e8: 4604 mov r4, r0 + 10ea: d03b beq.n 1164 + 10ec: d31b bcc.n 1126 + 10ee: 2802 cmp r0, #2 + 10f0: d00e beq.n 1110 + 10f2: b9b1 cbnz r1, 1122 + 10f4: f44f 7321 mov.w r3, #644 ; 0x284 + 10f8: f2c4 0300 movt r3, #16384 ; 0x4000 + 10fc: 681a ldr r2, [r3, #0] + 10fe: 2001 movs r0, #1 + 1100: f422 6260 bic.w r2, r2, #3584 ; 0xe00 + 1104: 601a str r2, [r3, #0] + 1106: 681a ldr r2, [r3, #0] + 1108: f422 7280 bic.w r2, r2, #256 ; 0x100 + 110c: 601a str r2, [r3, #0] + 110e: bd10 pop {r4, pc} + 1110: 2900 cmp r1, #0 + 1112: d03d beq.n 1190 + 1114: f240 3334 movw r3, #820 ; 0x334 + 1118: f2c1 0300 movt r3, #4096 ; 0x1000 + 111c: 88db ldrh r3, [r3, #6] + 111e: 071b lsls r3, r3, #28 + 1120: d042 beq.n 11a8 + 1122: 2000 movs r0, #0 + 1124: bd10 pop {r4, pc} + 1126: b369 cbz r1, 1184 + 1128: f240 3334 movw r3, #820 ; 0x334 + 112c: f2c1 0300 movt r3, #4096 ; 0x1000 + 1130: 899b ldrh r3, [r3, #12] + 1132: 071a lsls r2, r3, #28 + 1134: d1f5 bne.n 1122 + 1136: 460a mov r2, r1 + 1138: 2006 movs r0, #6 + 113a: 210f movs r1, #15 + 113c: f7ff fdc2 bl cc4 + 1140: f44f 7321 mov.w r3, #644 ; 0x284 + 1144: f2c4 0300 movt r3, #16384 ; 0x4000 + 1148: 681a ldr r2, [r3, #0] + 114a: f004 0407 and.w r4, r4, #7 + 114e: f422 6260 bic.w r2, r2, #3584 ; 0xe00 + 1152: ea42 2444 orr.w r4, r2, r4, lsl #9 + 1156: 601c str r4, [r3, #0] + 1158: 681a ldr r2, [r3, #0] + 115a: 2001 movs r0, #1 + 115c: f442 7280 orr.w r2, r2, #256 ; 0x100 + 1160: 601a str r2, [r3, #0] + 1162: bd10 pop {r4, pc} + 1164: b1d1 cbz r1, 119c + 1166: f240 3334 movw r3, #820 ; 0x334 + 116a: f2c1 0300 movt r3, #4096 ; 0x1000 + 116e: 891b ldrh r3, [r3, #8] + 1170: f003 03f0 and.w r3, r3, #240 ; 0xf0 + 1174: 2b00 cmp r3, #0 + 1176: d1d4 bne.n 1122 + 1178: 460a mov r2, r1 + 117a: 2004 movs r0, #4 + 117c: 21f0 movs r1, #240 ; 0xf0 + 117e: f7ff fda1 bl cc4 + 1182: e7dd b.n 1140 + 1184: 460a mov r2, r1 + 1186: 2006 movs r0, #6 + 1188: 210f movs r1, #15 + 118a: f7ff fd9b bl cc4 + 118e: e7b1 b.n 10f4 + 1190: 460a mov r2, r1 + 1192: 2003 movs r0, #3 + 1194: 210f movs r1, #15 + 1196: f7ff fd95 bl cc4 + 119a: e7ab b.n 10f4 + 119c: 460a mov r2, r1 + 119e: 2004 movs r0, #4 + 11a0: 21f0 movs r1, #240 ; 0xf0 + 11a2: f7ff fd8f bl cc4 + 11a6: e7a5 b.n 10f4 + 11a8: 460a mov r2, r1 + 11aa: 2003 movs r0, #3 + 11ac: 210f movs r1, #15 + 11ae: f7ff fd89 bl cc4 + 11b2: e7c5 b.n 1140 + +000011b4 : + 11b4: b510 push {r4, lr} + 11b6: 4604 mov r4, r0 + 11b8: b310 cbz r0, 1200 + 11ba: 2801 cmp r0, #1 + 11bc: d10c bne.n 11d8 + 11be: 2900 cmp r1, #0 + 11c0: d051 beq.n 1266 + 11c2: f240 3334 movw r3, #820 ; 0x334 + 11c6: f2c1 0300 movt r3, #4096 ; 0x1000 + 11ca: 889b ldrh r3, [r3, #4] + 11cc: f3c3 0309 ubfx r3, r3, #0, #10 + 11d0: 2b00 cmp r3, #0 + 11d2: d03a beq.n 124a + 11d4: 2000 movs r0, #0 + 11d6: bd10 pop {r4, pc} + 11d8: 2900 cmp r1, #0 + 11da: d1fb bne.n 11d4 + 11dc: f44f 7321 mov.w r3, #644 ; 0x284 + 11e0: f2c4 0300 movt r3, #16384 ; 0x4000 + 11e4: 681a ldr r2, [r3, #0] + 11e6: 2001 movs r0, #1 + 11e8: f022 020e bic.w r2, r2, #14 + 11ec: 601a str r2, [r3, #0] + 11ee: 681a ldr r2, [r3, #0] + 11f0: f022 0201 bic.w r2, r2, #1 + 11f4: 601a str r2, [r3, #0] + 11f6: 681a ldr r2, [r3, #0] + 11f8: f022 5280 bic.w r2, r2, #268435456 ; 0x10000000 + 11fc: 601a str r2, [r3, #0] + 11fe: bd10 pop {r4, pc} + 1200: b351 cbz r1, 1258 + 1202: f240 3334 movw r3, #820 ; 0x334 + 1206: f2c1 0300 movt r3, #4096 ; 0x1000 + 120a: 891b ldrh r3, [r3, #8] + 120c: f3c3 030a ubfx r3, r3, #0, #11 + 1210: 2b00 cmp r3, #0 + 1212: d1df bne.n 11d4 + 1214: 460a mov r2, r1 + 1216: 2004 movs r0, #4 + 1218: f240 71ff movw r1, #2047 ; 0x7ff + 121c: f7ff fd52 bl cc4 + 1220: f44f 7321 mov.w r3, #644 ; 0x284 + 1224: f2c4 0300 movt r3, #16384 ; 0x4000 + 1228: 681a ldr r2, [r3, #0] + 122a: f004 0407 and.w r4, r4, #7 + 122e: f022 020e bic.w r2, r2, #14 + 1232: ea42 0444 orr.w r4, r2, r4, lsl #1 + 1236: 601c str r4, [r3, #0] + 1238: 681a ldr r2, [r3, #0] + 123a: 2001 movs r0, #1 + 123c: 4302 orrs r2, r0 + 123e: 601a str r2, [r3, #0] + 1240: 681a ldr r2, [r3, #0] + 1242: f042 5280 orr.w r2, r2, #268435456 ; 0x10000000 + 1246: 601a str r2, [r3, #0] + 1248: bd10 pop {r4, pc} + 124a: 460a mov r2, r1 + 124c: 2002 movs r0, #2 + 124e: f240 31ff movw r1, #1023 ; 0x3ff + 1252: f7ff fd37 bl cc4 + 1256: e7e3 b.n 1220 + 1258: 460a mov r2, r1 + 125a: 2004 movs r0, #4 + 125c: f240 71ff movw r1, #2047 ; 0x7ff + 1260: f7ff fd30 bl cc4 + 1264: e7ba b.n 11dc + 1266: 460a mov r2, r1 + 1268: 2002 movs r0, #2 + 126a: f240 31ff movw r1, #1023 ; 0x3ff + 126e: f7ff fd29 bl cc4 + 1272: e7b3 b.n 11dc + +00001274 : + 1274: b510 push {r4, lr} + 1276: 4604 mov r4, r0 + 1278: 2803 cmp r0, #3 + 127a: d851 bhi.n 1320 + 127c: e8df f000 tbb [pc, r0] + 1280: 020f2140 .word 0x020f2140 + 1284: 2900 cmp r1, #0 + 1286: d068 beq.n 135a + 1288: f240 3334 movw r3, #820 ; 0x334 + 128c: f2c1 0300 movt r3, #4096 ; 0x1000 + 1290: 891b ldrh r3, [r3, #8] + 1292: f003 03c0 and.w r3, r3, #192 ; 0xc0 + 1296: 2b00 cmp r3, #0 + 1298: d06b beq.n 1372 + 129a: 2000 movs r0, #0 + 129c: bd10 pop {r4, pc} + 129e: 2900 cmp r1, #0 + 12a0: d054 beq.n 134c + 12a2: f240 3334 movw r3, #820 ; 0x334 + 12a6: f2c1 0300 movt r3, #4096 ; 0x1000 + 12aa: 889b ldrh r3, [r3, #4] + 12ac: f403 7340 and.w r3, r3, #768 ; 0x300 + 12b0: 2b00 cmp r3, #0 + 12b2: d1f2 bne.n 129a + 12b4: 460a mov r2, r1 + 12b6: 2002 movs r0, #2 + 12b8: f44f 7140 mov.w r1, #768 ; 0x300 + 12bc: f7ff fd02 bl cc4 + 12c0: e00d b.n 12de + 12c2: 2900 cmp r1, #0 + 12c4: d03c beq.n 1340 + 12c6: f240 3334 movw r3, #820 ; 0x334 + 12ca: f2c1 0300 movt r3, #4096 ; 0x1000 + 12ce: 89db ldrh r3, [r3, #14] + 12d0: 079b lsls r3, r3, #30 + 12d2: d1e2 bne.n 129a + 12d4: 460a mov r2, r1 + 12d6: 2007 movs r0, #7 + 12d8: 2103 movs r1, #3 + 12da: f7ff fcf3 bl cc4 + 12de: f44f 7322 mov.w r3, #648 ; 0x288 + 12e2: f2c4 0300 movt r3, #16384 ; 0x4000 + 12e6: 681a ldr r2, [r3, #0] + 12e8: f004 0407 and.w r4, r4, #7 + 12ec: f022 020e bic.w r2, r2, #14 + 12f0: ea42 0444 orr.w r4, r2, r4, lsl #1 + 12f4: 601c str r4, [r3, #0] + 12f6: 681a ldr r2, [r3, #0] + 12f8: 2001 movs r0, #1 + 12fa: 4302 orrs r2, r0 + 12fc: 601a str r2, [r3, #0] + 12fe: bd10 pop {r4, pc} + 1300: b389 cbz r1, 1366 + 1302: f240 3334 movw r3, #820 ; 0x334 + 1306: f2c1 0300 movt r3, #4096 ; 0x1000 + 130a: 88db ldrh r3, [r3, #6] + 130c: f003 0330 and.w r3, r3, #48 ; 0x30 + 1310: 2b00 cmp r3, #0 + 1312: d1c2 bne.n 129a + 1314: 460a mov r2, r1 + 1316: 2003 movs r0, #3 + 1318: 2130 movs r1, #48 ; 0x30 + 131a: f7ff fcd3 bl cc4 + 131e: e7de b.n 12de + 1320: 2900 cmp r1, #0 + 1322: d1ba bne.n 129a + 1324: f44f 7322 mov.w r3, #648 ; 0x288 + 1328: f2c4 0300 movt r3, #16384 ; 0x4000 + 132c: 681a ldr r2, [r3, #0] + 132e: 2001 movs r0, #1 + 1330: f022 020e bic.w r2, r2, #14 + 1334: 601a str r2, [r3, #0] + 1336: 681a ldr r2, [r3, #0] + 1338: f022 0201 bic.w r2, r2, #1 + 133c: 601a str r2, [r3, #0] + 133e: bd10 pop {r4, pc} + 1340: 460a mov r2, r1 + 1342: 2007 movs r0, #7 + 1344: 2103 movs r1, #3 + 1346: f7ff fcbd bl cc4 + 134a: e7eb b.n 1324 + 134c: 460a mov r2, r1 + 134e: 2002 movs r0, #2 + 1350: f44f 7140 mov.w r1, #768 ; 0x300 + 1354: f7ff fcb6 bl cc4 + 1358: e7e4 b.n 1324 + 135a: 460a mov r2, r1 + 135c: 2004 movs r0, #4 + 135e: 21c0 movs r1, #192 ; 0xc0 + 1360: f7ff fcb0 bl cc4 + 1364: e7de b.n 1324 + 1366: 460a mov r2, r1 + 1368: 2003 movs r0, #3 + 136a: 2130 movs r1, #48 ; 0x30 + 136c: f7ff fcaa bl cc4 + 1370: e7d8 b.n 1324 + 1372: 460a mov r2, r1 + 1374: 2004 movs r0, #4 + 1376: 21c0 movs r1, #192 ; 0xc0 + 1378: f7ff fca4 bl cc4 + 137c: e7af b.n 12de + 137e: bf00 nop + +00001380 : + 1380: 2801 cmp r0, #1 + 1382: b510 push {r4, lr} + 1384: 4604 mov r4, r0 + 1386: d03e beq.n 1406 + 1388: d31d bcc.n 13c6 + 138a: 2802 cmp r0, #2 + 138c: d00e beq.n 13ac + 138e: b9c1 cbnz r1, 13c2 + 1390: f44f 7322 mov.w r3, #648 ; 0x288 + 1394: f2c4 0300 movt r3, #16384 ; 0x4000 + 1398: 681a ldr r2, [r3, #0] + 139a: 2001 movs r0, #1 + 139c: f022 02e0 bic.w r2, r2, #224 ; 0xe0 + 13a0: 601a str r2, [r3, #0] + 13a2: 681a ldr r2, [r3, #0] + 13a4: f022 0210 bic.w r2, r2, #16 + 13a8: 601a str r2, [r3, #0] + 13aa: bd10 pop {r4, pc} + 13ac: 2900 cmp r1, #0 + 13ae: d040 beq.n 1432 + 13b0: f240 3334 movw r3, #820 ; 0x334 + 13b4: f2c1 0300 movt r3, #4096 ; 0x1000 + 13b8: 88db ldrh r3, [r3, #6] + 13ba: f003 03c0 and.w r3, r3, #192 ; 0xc0 + 13be: 2b00 cmp r3, #0 + 13c0: d043 beq.n 144a + 13c2: 2000 movs r0, #0 + 13c4: bd10 pop {r4, pc} + 13c6: b371 cbz r1, 1426 + 13c8: f240 3334 movw r3, #820 ; 0x334 + 13cc: f2c1 0300 movt r3, #4096 ; 0x1000 + 13d0: 889b ldrh r3, [r3, #4] + 13d2: f003 0330 and.w r3, r3, #48 ; 0x30 + 13d6: 2b00 cmp r3, #0 + 13d8: d1f3 bne.n 13c2 + 13da: 460a mov r2, r1 + 13dc: 2002 movs r0, #2 + 13de: 2130 movs r1, #48 ; 0x30 + 13e0: f7ff fc70 bl cc4 + 13e4: f44f 7322 mov.w r3, #648 ; 0x288 + 13e8: f2c4 0300 movt r3, #16384 ; 0x4000 + 13ec: 681a ldr r2, [r3, #0] + 13ee: 0164 lsls r4, r4, #5 + 13f0: f022 02e0 bic.w r2, r2, #224 ; 0xe0 + 13f4: b2e4 uxtb r4, r4 + 13f6: 4314 orrs r4, r2 + 13f8: 601c str r4, [r3, #0] + 13fa: 681a ldr r2, [r3, #0] + 13fc: 2001 movs r0, #1 + 13fe: f042 0210 orr.w r2, r2, #16 + 1402: 601a str r2, [r3, #0] + 1404: bd10 pop {r4, pc} + 1406: b1d1 cbz r1, 143e + 1408: f240 3334 movw r3, #820 ; 0x334 + 140c: f2c1 0300 movt r3, #4096 ; 0x1000 + 1410: 89db ldrh r3, [r3, #14] + 1412: f003 030c and.w r3, r3, #12 + 1416: 2b00 cmp r3, #0 + 1418: d1d3 bne.n 13c2 + 141a: 460a mov r2, r1 + 141c: 2007 movs r0, #7 + 141e: 210c movs r1, #12 + 1420: f7ff fc50 bl cc4 + 1424: e7de b.n 13e4 + 1426: 460a mov r2, r1 + 1428: 2002 movs r0, #2 + 142a: 2130 movs r1, #48 ; 0x30 + 142c: f7ff fc4a bl cc4 + 1430: e7ae b.n 1390 + 1432: 460a mov r2, r1 + 1434: 2003 movs r0, #3 + 1436: 21c0 movs r1, #192 ; 0xc0 + 1438: f7ff fc44 bl cc4 + 143c: e7a8 b.n 1390 + 143e: 460a mov r2, r1 + 1440: 2007 movs r0, #7 + 1442: 210c movs r1, #12 + 1444: f7ff fc3e bl cc4 + 1448: e7a2 b.n 1390 + 144a: 460a mov r2, r1 + 144c: 2003 movs r0, #3 + 144e: 21c0 movs r1, #192 ; 0xc0 + 1450: f7ff fc38 bl cc4 + 1454: e7c6 b.n 13e4 + 1456: bf00 nop + +00001458 : + 1458: 2801 cmp r0, #1 + 145a: b510 push {r4, lr} + 145c: 4604 mov r4, r0 + 145e: d03f beq.n 14e0 + 1460: d31d bcc.n 149e + 1462: 2802 cmp r0, #2 + 1464: d00e beq.n 1484 + 1466: b9c1 cbnz r1, 149a + 1468: f44f 7322 mov.w r3, #648 ; 0x288 + 146c: f2c4 0300 movt r3, #16384 ; 0x4000 + 1470: 681a ldr r2, [r3, #0] + 1472: 2001 movs r0, #1 + 1474: f422 6260 bic.w r2, r2, #3584 ; 0xe00 + 1478: 601a str r2, [r3, #0] + 147a: 681a ldr r2, [r3, #0] + 147c: f422 7280 bic.w r2, r2, #256 ; 0x100 + 1480: 601a str r2, [r3, #0] + 1482: bd10 pop {r4, pc} + 1484: 2900 cmp r1, #0 + 1486: d03f beq.n 1508 + 1488: f240 3334 movw r3, #820 ; 0x334 + 148c: f2c1 0300 movt r3, #4096 ; 0x1000 + 1490: 889b ldrh r3, [r3, #4] + 1492: f003 03c0 and.w r3, r3, #192 ; 0xc0 + 1496: 2b00 cmp r3, #0 + 1498: d041 beq.n 151e + 149a: 2000 movs r0, #0 + 149c: bd10 pop {r4, pc} + 149e: b369 cbz r1, 14fc + 14a0: f240 3334 movw r3, #820 ; 0x334 + 14a4: f2c1 0300 movt r3, #4096 ; 0x1000 + 14a8: 885b ldrh r3, [r3, #2] + 14aa: f003 03c0 and.w r3, r3, #192 ; 0xc0 + 14ae: 2b00 cmp r3, #0 + 14b0: d1f3 bne.n 149a + 14b2: 460a mov r2, r1 + 14b4: 2001 movs r0, #1 + 14b6: 21c0 movs r1, #192 ; 0xc0 + 14b8: f7ff fc04 bl cc4 + 14bc: f44f 7322 mov.w r3, #648 ; 0x288 + 14c0: f2c4 0300 movt r3, #16384 ; 0x4000 + 14c4: 681a ldr r2, [r3, #0] + 14c6: f004 0407 and.w r4, r4, #7 + 14ca: f422 6260 bic.w r2, r2, #3584 ; 0xe00 + 14ce: ea42 2444 orr.w r4, r2, r4, lsl #9 + 14d2: 601c str r4, [r3, #0] + 14d4: 681a ldr r2, [r3, #0] + 14d6: 2001 movs r0, #1 + 14d8: f442 7280 orr.w r2, r2, #256 ; 0x100 + 14dc: 601a str r2, [r3, #0] + 14de: bd10 pop {r4, pc} + 14e0: b1b9 cbz r1, 1512 + 14e2: f240 3334 movw r3, #820 ; 0x334 + 14e6: f2c1 0300 movt r3, #4096 ; 0x1000 + 14ea: 891b ldrh r3, [r3, #8] + 14ec: 079b lsls r3, r3, #30 + 14ee: d1d4 bne.n 149a + 14f0: 460a mov r2, r1 + 14f2: 2004 movs r0, #4 + 14f4: 2103 movs r1, #3 + 14f6: f7ff fbe5 bl cc4 + 14fa: e7df b.n 14bc + 14fc: 460a mov r2, r1 + 14fe: 2001 movs r0, #1 + 1500: 21c0 movs r1, #192 ; 0xc0 + 1502: f7ff fbdf bl cc4 + 1506: e7af b.n 1468 + 1508: 460a mov r2, r1 + 150a: 21c0 movs r1, #192 ; 0xc0 + 150c: f7ff fbda bl cc4 + 1510: e7aa b.n 1468 + 1512: 460a mov r2, r1 + 1514: 2004 movs r0, #4 + 1516: 2103 movs r1, #3 + 1518: f7ff fbd4 bl cc4 + 151c: e7a4 b.n 1468 + 151e: 460a mov r2, r1 + 1520: 21c0 movs r1, #192 ; 0xc0 + 1522: f7ff fbcf bl cc4 + 1526: e7c9 b.n 14bc + +00001528 : + 1528: b510 push {r4, lr} + 152a: 4604 mov r4, r0 + 152c: 2803 cmp r0, #3 + 152e: d852 bhi.n 15d6 + 1530: e8df f000 tbb [pc, r0] + 1534: 020f2041 .word 0x020f2041 + 1538: 2900 cmp r1, #0 + 153a: d068 beq.n 160e + 153c: f240 3334 movw r3, #820 ; 0x334 + 1540: f2c1 0300 movt r3, #4096 ; 0x1000 + 1544: 88db ldrh r3, [r3, #6] + 1546: f403 7340 and.w r3, r3, #768 ; 0x300 + 154a: 2b00 cmp r3, #0 + 154c: d06c beq.n 1628 + 154e: 2000 movs r0, #0 + 1550: bd10 pop {r4, pc} + 1552: 2900 cmp r1, #0 + 1554: d055 beq.n 1602 + 1556: f240 3334 movw r3, #820 ; 0x334 + 155a: f2c1 0300 movt r3, #4096 ; 0x1000 + 155e: 891b ldrh r3, [r3, #8] + 1560: f003 0330 and.w r3, r3, #48 ; 0x30 + 1564: 2b00 cmp r3, #0 + 1566: d1f2 bne.n 154e + 1568: 460a mov r2, r1 + 156a: 2004 movs r0, #4 + 156c: 2130 movs r1, #48 ; 0x30 + 156e: f7ff fba9 bl cc4 + 1572: e00f b.n 1594 + 1574: 2900 cmp r1, #0 + 1576: d03e beq.n 15f6 + 1578: f240 3334 movw r3, #820 ; 0x334 + 157c: f2c1 0300 movt r3, #4096 ; 0x1000 + 1580: 891b ldrh r3, [r3, #8] + 1582: f003 030c and.w r3, r3, #12 + 1586: 2b00 cmp r3, #0 + 1588: d1e1 bne.n 154e + 158a: 460a mov r2, r1 + 158c: 2004 movs r0, #4 + 158e: 210c movs r1, #12 + 1590: f7ff fb98 bl cc4 + 1594: f44f 7322 mov.w r3, #648 ; 0x288 + 1598: f2c4 0300 movt r3, #16384 ; 0x4000 + 159c: 681a ldr r2, [r3, #0] + 159e: 0364 lsls r4, r4, #13 + 15a0: f422 4260 bic.w r2, r2, #57344 ; 0xe000 + 15a4: b2a4 uxth r4, r4 + 15a6: 4314 orrs r4, r2 + 15a8: 601c str r4, [r3, #0] + 15aa: 681a ldr r2, [r3, #0] + 15ac: 2001 movs r0, #1 + 15ae: f442 5280 orr.w r2, r2, #4096 ; 0x1000 + 15b2: 601a str r2, [r3, #0] + 15b4: bd10 pop {r4, pc} + 15b6: b389 cbz r1, 161c + 15b8: f240 3334 movw r3, #820 ; 0x334 + 15bc: f2c1 0300 movt r3, #4096 ; 0x1000 + 15c0: 885b ldrh r3, [r3, #2] + 15c2: f003 030c and.w r3, r3, #12 + 15c6: 2b00 cmp r3, #0 + 15c8: d1c1 bne.n 154e + 15ca: 460a mov r2, r1 + 15cc: 2001 movs r0, #1 + 15ce: 210c movs r1, #12 + 15d0: f7ff fb78 bl cc4 + 15d4: e7de b.n 1594 + 15d6: 2900 cmp r1, #0 + 15d8: d1b9 bne.n 154e + 15da: f44f 7322 mov.w r3, #648 ; 0x288 + 15de: f2c4 0300 movt r3, #16384 ; 0x4000 + 15e2: 681a ldr r2, [r3, #0] + 15e4: 2001 movs r0, #1 + 15e6: f422 4260 bic.w r2, r2, #57344 ; 0xe000 + 15ea: 601a str r2, [r3, #0] + 15ec: 681a ldr r2, [r3, #0] + 15ee: f422 5280 bic.w r2, r2, #4096 ; 0x1000 + 15f2: 601a str r2, [r3, #0] + 15f4: bd10 pop {r4, pc} + 15f6: 460a mov r2, r1 + 15f8: 2004 movs r0, #4 + 15fa: 210c movs r1, #12 + 15fc: f7ff fb62 bl cc4 + 1600: e7eb b.n 15da + 1602: 460a mov r2, r1 + 1604: 2004 movs r0, #4 + 1606: 2130 movs r1, #48 ; 0x30 + 1608: f7ff fb5c bl cc4 + 160c: e7e5 b.n 15da + 160e: 460a mov r2, r1 + 1610: 2003 movs r0, #3 + 1612: f44f 7140 mov.w r1, #768 ; 0x300 + 1616: f7ff fb55 bl cc4 + 161a: e7de b.n 15da + 161c: 460a mov r2, r1 + 161e: 2001 movs r0, #1 + 1620: 210c movs r1, #12 + 1622: f7ff fb4f bl cc4 + 1626: e7d8 b.n 15da + 1628: 460a mov r2, r1 + 162a: 2003 movs r0, #3 + 162c: f44f 7140 mov.w r1, #768 ; 0x300 + 1630: f7ff fb48 bl cc4 + 1634: e7ae b.n 1594 + 1636: bf00 nop + +00001638 : + 1638: b538 push {r3, r4, r5, lr} + 163a: 4604 mov r4, r0 + 163c: 460d mov r5, r1 + 163e: 2803 cmp r0, #3 + 1640: d85e bhi.n 1700 + 1642: e8df f000 tbb [pc, r0] + 1646: 2041 .short 0x2041 + 1648: 020f .short 0x020f + 164a: 2900 cmp r1, #0 + 164c: d074 beq.n 1738 + 164e: f240 3334 movw r3, #820 ; 0x334 + 1652: f2c1 0300 movt r3, #4096 ; 0x1000 + 1656: 889b ldrh r3, [r3, #4] + 1658: f403 7378 and.w r3, r3, #992 ; 0x3e0 + 165c: 2b00 cmp r3, #0 + 165e: d07d beq.n 175c + 1660: 2000 movs r0, #0 + 1662: bd38 pop {r3, r4, r5, pc} + 1664: 2900 cmp r1, #0 + 1666: d061 beq.n 172c + 1668: f240 3334 movw r3, #820 ; 0x334 + 166c: f2c1 0300 movt r3, #4096 ; 0x1000 + 1670: 88db ldrh r3, [r3, #6] + 1672: f003 034f and.w r3, r3, #79 ; 0x4f + 1676: 2b00 cmp r3, #0 + 1678: d1f2 bne.n 1660 + 167a: 460a mov r2, r1 + 167c: 2003 movs r0, #3 + 167e: 214f movs r1, #79 ; 0x4f + 1680: f7ff fb20 bl cc4 + 1684: e00f b.n 16a6 + 1686: 2900 cmp r1, #0 + 1688: d04a beq.n 1720 + 168a: f240 3334 movw r3, #820 ; 0x334 + 168e: f2c1 0300 movt r3, #4096 ; 0x1000 + 1692: 89db ldrh r3, [r3, #14] + 1694: f003 032f and.w r3, r3, #47 ; 0x2f + 1698: 2b00 cmp r3, #0 + 169a: d1e1 bne.n 1660 + 169c: 460a mov r2, r1 + 169e: 2007 movs r0, #7 + 16a0: 212f movs r1, #47 ; 0x2f + 16a2: f7ff fb0f bl cc4 + 16a6: f44f 7323 mov.w r3, #652 ; 0x28c + 16aa: f2c4 0300 movt r3, #16384 ; 0x4000 + 16ae: 681a ldr r2, [r3, #0] + 16b0: f004 0403 and.w r4, r4, #3 + 16b4: f022 020c bic.w r2, r2, #12 + 16b8: ea42 0484 orr.w r4, r2, r4, lsl #2 + 16bc: 601c str r4, [r3, #0] + 16be: 681a ldr r2, [r3, #0] + 16c0: 2001 movs r0, #1 + 16c2: 4302 orrs r2, r0 + 16c4: 601a str r2, [r3, #0] + 16c6: bd38 pop {r3, r4, r5, pc} + 16c8: 2900 cmp r1, #0 + 16ca: d03c beq.n 1746 + 16cc: f240 3334 movw r3, #820 ; 0x334 + 16d0: f2c1 0300 movt r3, #4096 ; 0x1000 + 16d4: 88d8 ldrh r0, [r3, #6] + 16d6: 891b ldrh r3, [r3, #8] + 16d8: f000 0040 and.w r0, r0, #64 ; 0x40 + 16dc: b280 uxth r0, r0 + 16de: f003 030f and.w r3, r3, #15 + 16e2: 2800 cmp r0, #0 + 16e4: d1bc bne.n 1660 + 16e6: 2b00 cmp r3, #0 + 16e8: d1bb bne.n 1662 + 16ea: 462a mov r2, r5 + 16ec: 2004 movs r0, #4 + 16ee: 210f movs r1, #15 + 16f0: f7ff fae8 bl cc4 + 16f4: 462a mov r2, r5 + 16f6: 2003 movs r0, #3 + 16f8: 2140 movs r1, #64 ; 0x40 + 16fa: f7ff fae3 bl cc4 + 16fe: e7d2 b.n 16a6 + 1700: 2900 cmp r1, #0 + 1702: d1ad bne.n 1660 + 1704: f44f 7323 mov.w r3, #652 ; 0x28c + 1708: f2c4 0300 movt r3, #16384 ; 0x4000 + 170c: 681a ldr r2, [r3, #0] + 170e: 2001 movs r0, #1 + 1710: f022 020c bic.w r2, r2, #12 + 1714: 601a str r2, [r3, #0] + 1716: 681a ldr r2, [r3, #0] + 1718: f022 0201 bic.w r2, r2, #1 + 171c: 601a str r2, [r3, #0] + 171e: bd38 pop {r3, r4, r5, pc} + 1720: 460a mov r2, r1 + 1722: 2007 movs r0, #7 + 1724: 212f movs r1, #47 ; 0x2f + 1726: f7ff facd bl cc4 + 172a: e7eb b.n 1704 + 172c: 460a mov r2, r1 + 172e: 2003 movs r0, #3 + 1730: 214f movs r1, #79 ; 0x4f + 1732: f7ff fac7 bl cc4 + 1736: e7e5 b.n 1704 + 1738: 460a mov r2, r1 + 173a: 2002 movs r0, #2 + 173c: f44f 7178 mov.w r1, #992 ; 0x3e0 + 1740: f7ff fac0 bl cc4 + 1744: e7de b.n 1704 + 1746: 462a mov r2, r5 + 1748: 2004 movs r0, #4 + 174a: 210f movs r1, #15 + 174c: f7ff faba bl cc4 + 1750: 462a mov r2, r5 + 1752: 2003 movs r0, #3 + 1754: 2140 movs r1, #64 ; 0x40 + 1756: f7ff fab5 bl cc4 + 175a: e7d3 b.n 1704 + 175c: 460a mov r2, r1 + 175e: 2002 movs r0, #2 + 1760: f44f 7178 mov.w r1, #992 ; 0x3e0 + 1764: f7ff faae bl cc4 + 1768: e79d b.n 16a6 + 176a: bf00 nop + +0000176c : + 176c: 2801 cmp r0, #1 + 176e: b510 push {r4, lr} + 1770: 4604 mov r4, r0 + 1772: d03c beq.n 17ee + 1774: d31d bcc.n 17b2 + 1776: 2802 cmp r0, #2 + 1778: d00e beq.n 1798 + 177a: b9c1 cbnz r1, 17ae + 177c: f44f 7323 mov.w r3, #652 ; 0x28c + 1780: f2c4 0300 movt r3, #16384 ; 0x4000 + 1784: 681a ldr r2, [r3, #0] + 1786: 2001 movs r0, #1 + 1788: f022 02c0 bic.w r2, r2, #192 ; 0xc0 + 178c: 601a str r2, [r3, #0] + 178e: 681a ldr r2, [r3, #0] + 1790: f022 0210 bic.w r2, r2, #16 + 1794: 601a str r2, [r3, #0] + 1796: bd10 pop {r4, pc} + 1798: 2900 cmp r1, #0 + 179a: d03e beq.n 181a + 179c: f240 3334 movw r3, #820 ; 0x334 + 17a0: f2c1 0300 movt r3, #4096 ; 0x1000 + 17a4: 891b ldrh r3, [r3, #8] + 17a6: f403 73f8 and.w r3, r3, #496 ; 0x1f0 + 17aa: 2b00 cmp r3, #0 + 17ac: d042 beq.n 1834 + 17ae: 2000 movs r0, #0 + 17b0: bd10 pop {r4, pc} + 17b2: b361 cbz r1, 180e + 17b4: f240 3334 movw r3, #820 ; 0x334 + 17b8: f2c1 0300 movt r3, #4096 ; 0x1000 + 17bc: 889b ldrh r3, [r3, #4] + 17be: 06db lsls r3, r3, #27 + 17c0: d1f5 bne.n 17ae + 17c2: 460a mov r2, r1 + 17c4: 2002 movs r0, #2 + 17c6: 211f movs r1, #31 + 17c8: f7ff fa7c bl cc4 + 17cc: f44f 7323 mov.w r3, #652 ; 0x28c + 17d0: f2c4 0300 movt r3, #16384 ; 0x4000 + 17d4: 681a ldr r2, [r3, #0] + 17d6: 01a4 lsls r4, r4, #6 + 17d8: f022 02c0 bic.w r2, r2, #192 ; 0xc0 + 17dc: b2e4 uxtb r4, r4 + 17de: 4314 orrs r4, r2 + 17e0: 601c str r4, [r3, #0] + 17e2: 681a ldr r2, [r3, #0] + 17e4: 2001 movs r0, #1 + 17e6: f042 0210 orr.w r2, r2, #16 + 17ea: 601a str r2, [r3, #0] + 17ec: bd10 pop {r4, pc} + 17ee: b1d9 cbz r1, 1828 + 17f0: f240 3334 movw r3, #820 ; 0x334 + 17f4: f2c1 0300 movt r3, #4096 ; 0x1000 + 17f8: 88db ldrh r3, [r3, #6] + 17fa: f003 03f8 and.w r3, r3, #248 ; 0xf8 + 17fe: 2b00 cmp r3, #0 + 1800: d1d5 bne.n 17ae + 1802: 460a mov r2, r1 + 1804: 2003 movs r0, #3 + 1806: 21f8 movs r1, #248 ; 0xf8 + 1808: f7ff fa5c bl cc4 + 180c: e7de b.n 17cc + 180e: 460a mov r2, r1 + 1810: 2002 movs r0, #2 + 1812: 211f movs r1, #31 + 1814: f7ff fa56 bl cc4 + 1818: e7b0 b.n 177c + 181a: 460a mov r2, r1 + 181c: 2004 movs r0, #4 + 181e: f44f 71f8 mov.w r1, #496 ; 0x1f0 + 1822: f7ff fa4f bl cc4 + 1826: e7a9 b.n 177c + 1828: 460a mov r2, r1 + 182a: 2003 movs r0, #3 + 182c: 21f8 movs r1, #248 ; 0xf8 + 182e: f7ff fa49 bl cc4 + 1832: e7a3 b.n 177c + 1834: 460a mov r2, r1 + 1836: 2004 movs r0, #4 + 1838: f44f 71f8 mov.w r1, #496 ; 0x1f0 + 183c: f7ff fa42 bl cc4 + 1840: e7c4 b.n 17cc + 1842: bf00 nop + +00001844 : + 1844: b510 push {r4, lr} + 1846: 4604 mov r4, r0 + 1848: 2803 cmp r0, #3 + 184a: d84e bhi.n 18ea + 184c: e8df f000 tbb [pc, r0] + 1850: 020d1c3f .word 0x020d1c3f + 1854: 2900 cmp r1, #0 + 1856: d065 beq.n 1924 + 1858: f240 3334 movw r3, #820 ; 0x334 + 185c: f2c1 0300 movt r3, #4096 ; 0x1000 + 1860: 891b ldrh r3, [r3, #8] + 1862: 071b lsls r3, r3, #28 + 1864: d06a beq.n 193c + 1866: 2000 movs r0, #0 + 1868: bd10 pop {r4, pc} + 186a: 2900 cmp r1, #0 + 186c: d054 beq.n 1918 + 186e: f240 3334 movw r3, #820 ; 0x334 + 1872: f2c1 0300 movt r3, #4096 ; 0x1000 + 1876: 88db ldrh r3, [r3, #6] + 1878: 071a lsls r2, r3, #28 + 187a: d1f4 bne.n 1866 + 187c: 460a mov r2, r1 + 187e: 2003 movs r0, #3 + 1880: 210f movs r1, #15 + 1882: f7ff fa1f bl cc4 + 1886: e010 b.n 18aa + 1888: 2900 cmp r1, #0 + 188a: d03e beq.n 190a + 188c: f240 3334 movw r3, #820 ; 0x334 + 1890: f2c1 0300 movt r3, #4096 ; 0x1000 + 1894: 889b ldrh r3, [r3, #4] + 1896: f403 7370 and.w r3, r3, #960 ; 0x3c0 + 189a: 2b00 cmp r3, #0 + 189c: d1e3 bne.n 1866 + 189e: 460a mov r2, r1 + 18a0: 2002 movs r0, #2 + 18a2: f44f 7170 mov.w r1, #960 ; 0x3c0 + 18a6: f7ff fa0d bl cc4 + 18aa: f44f 7323 mov.w r3, #652 ; 0x28c + 18ae: f2c4 0300 movt r3, #16384 ; 0x4000 + 18b2: 681a ldr r2, [r3, #0] + 18b4: f004 0407 and.w r4, r4, #7 + 18b8: f422 2260 bic.w r2, r2, #917504 ; 0xe0000 + 18bc: ea42 4444 orr.w r4, r2, r4, lsl #17 + 18c0: 601c str r4, [r3, #0] + 18c2: 681a ldr r2, [r3, #0] + 18c4: 2001 movs r0, #1 + 18c6: f442 3280 orr.w r2, r2, #65536 ; 0x10000 + 18ca: 601a str r2, [r3, #0] + 18cc: bd10 pop {r4, pc} + 18ce: b379 cbz r1, 1930 + 18d0: f240 3334 movw r3, #820 ; 0x334 + 18d4: f2c1 0300 movt r3, #4096 ; 0x1000 + 18d8: 89db ldrh r3, [r3, #14] + 18da: 0718 lsls r0, r3, #28 + 18dc: d1c3 bne.n 1866 + 18de: 460a mov r2, r1 + 18e0: 2007 movs r0, #7 + 18e2: 210f movs r1, #15 + 18e4: f7ff f9ee bl cc4 + 18e8: e7df b.n 18aa + 18ea: 2900 cmp r1, #0 + 18ec: d1bb bne.n 1866 + 18ee: f44f 7323 mov.w r3, #652 ; 0x28c + 18f2: f2c4 0300 movt r3, #16384 ; 0x4000 + 18f6: 681a ldr r2, [r3, #0] + 18f8: 2001 movs r0, #1 + 18fa: f422 2260 bic.w r2, r2, #917504 ; 0xe0000 + 18fe: 601a str r2, [r3, #0] + 1900: 681a ldr r2, [r3, #0] + 1902: f422 3280 bic.w r2, r2, #65536 ; 0x10000 + 1906: 601a str r2, [r3, #0] + 1908: bd10 pop {r4, pc} + 190a: 460a mov r2, r1 + 190c: 2002 movs r0, #2 + 190e: f44f 7170 mov.w r1, #960 ; 0x3c0 + 1912: f7ff f9d7 bl cc4 + 1916: e7ea b.n 18ee + 1918: 460a mov r2, r1 + 191a: 2003 movs r0, #3 + 191c: 210f movs r1, #15 + 191e: f7ff f9d1 bl cc4 + 1922: e7e4 b.n 18ee + 1924: 460a mov r2, r1 + 1926: 2004 movs r0, #4 + 1928: 210f movs r1, #15 + 192a: f7ff f9cb bl cc4 + 192e: e7de b.n 18ee + 1930: 460a mov r2, r1 + 1932: 2007 movs r0, #7 + 1934: 210f movs r1, #15 + 1936: f7ff f9c5 bl cc4 + 193a: e7d8 b.n 18ee + 193c: 460a mov r2, r1 + 193e: 2004 movs r0, #4 + 1940: 210f movs r1, #15 + 1942: f7ff f9bf bl cc4 + 1946: e7b0 b.n 18aa + +00001948 : + 1948: 2801 cmp r0, #1 + 194a: b510 push {r4, lr} + 194c: 4604 mov r4, r0 + 194e: d03d beq.n 19cc + 1950: d31d bcc.n 198e + 1952: 2802 cmp r0, #2 + 1954: d00e beq.n 1974 + 1956: b9c1 cbnz r1, 198a + 1958: f44f 7323 mov.w r3, #652 ; 0x28c + 195c: f2c4 0300 movt r3, #16384 ; 0x4000 + 1960: 681a ldr r2, [r3, #0] + 1962: 2001 movs r0, #1 + 1964: f422 0260 bic.w r2, r2, #14680064 ; 0xe00000 + 1968: 601a str r2, [r3, #0] + 196a: 681a ldr r2, [r3, #0] + 196c: f422 1280 bic.w r2, r2, #1048576 ; 0x100000 + 1970: 601a str r2, [r3, #0] + 1972: bd10 pop {r4, pc} + 1974: 2900 cmp r1, #0 + 1976: d03f beq.n 19f8 + 1978: f240 3334 movw r3, #820 ; 0x334 + 197c: f2c1 0300 movt r3, #4096 ; 0x1000 + 1980: 891b ldrh r3, [r3, #8] + 1982: f003 03f0 and.w r3, r3, #240 ; 0xf0 + 1986: 2b00 cmp r3, #0 + 1988: d042 beq.n 1a10 + 198a: 2000 movs r0, #0 + 198c: bd10 pop {r4, pc} + 198e: b369 cbz r1, 19ec + 1990: f240 3334 movw r3, #820 ; 0x334 + 1994: f2c1 0300 movt r3, #4096 ; 0x1000 + 1998: 889b ldrh r3, [r3, #4] + 199a: 071b lsls r3, r3, #28 + 199c: d1f5 bne.n 198a + 199e: 460a mov r2, r1 + 19a0: 2002 movs r0, #2 + 19a2: 210f movs r1, #15 + 19a4: f7ff f98e bl cc4 + 19a8: f44f 7323 mov.w r3, #652 ; 0x28c + 19ac: f2c4 0300 movt r3, #16384 ; 0x4000 + 19b0: 681a ldr r2, [r3, #0] + 19b2: f004 0407 and.w r4, r4, #7 + 19b6: f422 0260 bic.w r2, r2, #14680064 ; 0xe00000 + 19ba: ea42 5444 orr.w r4, r2, r4, lsl #21 + 19be: 601c str r4, [r3, #0] + 19c0: 681a ldr r2, [r3, #0] + 19c2: 2001 movs r0, #1 + 19c4: f442 1280 orr.w r2, r2, #1048576 ; 0x100000 + 19c8: 601a str r2, [r3, #0] + 19ca: bd10 pop {r4, pc} + 19cc: b1d1 cbz r1, 1a04 + 19ce: f240 3334 movw r3, #820 ; 0x334 + 19d2: f2c1 0300 movt r3, #4096 ; 0x1000 + 19d6: 88db ldrh r3, [r3, #6] + 19d8: f003 03f0 and.w r3, r3, #240 ; 0xf0 + 19dc: 2b00 cmp r3, #0 + 19de: d1d4 bne.n 198a + 19e0: 460a mov r2, r1 + 19e2: 2003 movs r0, #3 + 19e4: 21f0 movs r1, #240 ; 0xf0 + 19e6: f7ff f96d bl cc4 + 19ea: e7dd b.n 19a8 + 19ec: 460a mov r2, r1 + 19ee: 2002 movs r0, #2 + 19f0: 210f movs r1, #15 + 19f2: f7ff f967 bl cc4 + 19f6: e7af b.n 1958 + 19f8: 460a mov r2, r1 + 19fa: 2004 movs r0, #4 + 19fc: 21f0 movs r1, #240 ; 0xf0 + 19fe: f7ff f961 bl cc4 + 1a02: e7a9 b.n 1958 + 1a04: 460a mov r2, r1 + 1a06: 2003 movs r0, #3 + 1a08: 21f0 movs r1, #240 ; 0xf0 + 1a0a: f7ff f95b bl cc4 + 1a0e: e7a3 b.n 1958 + 1a10: 460a mov r2, r1 + 1a12: 2004 movs r0, #4 + 1a14: 21f0 movs r1, #240 ; 0xf0 + 1a16: f7ff f955 bl cc4 + 1a1a: e7c5 b.n 19a8 + +00001a1c : + 1a1c: b508 push {r3, lr} + 1a1e: b1b1 cbz r1, 1a4e + 1a20: f240 3334 movw r3, #820 ; 0x334 + 1a24: f2c1 0300 movt r3, #4096 ; 0x1000 + 1a28: 8818 ldrh r0, [r3, #0] + 1a2a: f010 007f ands.w r0, r0, #127 ; 0x7f + 1a2e: d001 beq.n 1a34 + 1a30: 2000 movs r0, #0 + 1a32: bd08 pop {r3, pc} + 1a34: 217f movs r1, #127 ; 0x7f + 1a36: f7ff f92f bl c98 + 1a3a: f44f 7328 mov.w r3, #672 ; 0x2a0 + 1a3e: f2c4 0300 movt r3, #16384 ; 0x4000 + 1a42: 681a ldr r2, [r3, #0] + 1a44: 2001 movs r0, #1 + 1a46: f042 0202 orr.w r2, r2, #2 + 1a4a: 601a str r2, [r3, #0] + 1a4c: bd08 pop {r3, pc} + 1a4e: 4608 mov r0, r1 + 1a50: 217f movs r1, #127 ; 0x7f + 1a52: 4602 mov r2, r0 + 1a54: f7ff f936 bl cc4 + 1a58: f44f 7328 mov.w r3, #672 ; 0x2a0 + 1a5c: f2c4 0300 movt r3, #16384 ; 0x4000 + 1a60: 681a ldr r2, [r3, #0] + 1a62: 2001 movs r0, #1 + 1a64: f022 0202 bic.w r2, r2, #2 + 1a68: 601a str r2, [r3, #0] + 1a6a: bd08 pop {r3, pc} + +00001a6c : + 1a6c: b508 push {r3, lr} + 1a6e: b1a1 cbz r1, 1a9a + 1a70: f240 3334 movw r3, #820 ; 0x334 + 1a74: f2c1 0300 movt r3, #4096 ; 0x1000 + 1a78: 7818 ldrb r0, [r3, #0] + 1a7a: b108 cbz r0, 1a80 + 1a7c: 2000 movs r0, #0 + 1a7e: bd08 pop {r3, pc} + 1a80: 21ff movs r1, #255 ; 0xff + 1a82: f7ff f909 bl c98 + 1a86: f44f 7328 mov.w r3, #672 ; 0x2a0 + 1a8a: f2c4 0300 movt r3, #16384 ; 0x4000 + 1a8e: 681a ldr r2, [r3, #0] + 1a90: 2001 movs r0, #1 + 1a92: f042 0202 orr.w r2, r2, #2 + 1a96: 601a str r2, [r3, #0] + 1a98: bd08 pop {r3, pc} + 1a9a: 4608 mov r0, r1 + 1a9c: 21ff movs r1, #255 ; 0xff + 1a9e: 4602 mov r2, r0 + 1aa0: f7ff f910 bl cc4 + 1aa4: f44f 7328 mov.w r3, #672 ; 0x2a0 + 1aa8: f2c4 0300 movt r3, #16384 ; 0x4000 + 1aac: 681a ldr r2, [r3, #0] + 1aae: 2001 movs r0, #1 + 1ab0: f022 0202 bic.w r2, r2, #2 + 1ab4: 601a str r2, [r3, #0] + 1ab6: bd08 pop {r3, pc} + +00001ab8 : + 1ab8: b510 push {r4, lr} + 1aba: 460c mov r4, r1 + 1abc: b379 cbz r1, 1b1e + 1abe: f240 3334 movw r3, #820 ; 0x334 + 1ac2: f2c1 0300 movt r3, #4096 ; 0x1000 + 1ac6: 889a ldrh r2, [r3, #4] + 1ac8: 88d8 ldrh r0, [r3, #6] + 1aca: f012 0f7f tst.w r2, #127 ; 0x7f + 1ace: bf0c ite eq + 1ad0: 2201 moveq r2, #1 + 1ad2: 2200 movne r2, #0 + 1ad4: f000 0030 and.w r0, r0, #48 ; 0x30 + 1ad8: 2800 cmp r0, #0 + 1ada: bf14 ite ne + 1adc: 2000 movne r0, #0 + 1ade: f002 0001 andeq.w r0, r2, #1 + 1ae2: 781b ldrb r3, [r3, #0] + 1ae4: 2b00 cmp r3, #0 + 1ae6: bf14 ite ne + 1ae8: 2000 movne r0, #0 + 1aea: f000 0001 andeq.w r0, r0, #1 + 1aee: b900 cbnz r0, 1af2 + 1af0: bd10 pop {r4, pc} + 1af2: 2000 movs r0, #0 + 1af4: 21ff movs r1, #255 ; 0xff + 1af6: f7ff f8cf bl c98 + 1afa: 2002 movs r0, #2 + 1afc: 217f movs r1, #127 ; 0x7f + 1afe: f7ff f8cb bl c98 + 1b02: 2003 movs r0, #3 + 1b04: 2130 movs r1, #48 ; 0x30 + 1b06: f7ff f8c7 bl c98 + 1b0a: f44f 7328 mov.w r3, #672 ; 0x2a0 + 1b0e: f2c4 0300 movt r3, #16384 ; 0x4000 + 1b12: 681a ldr r2, [r3, #0] + 1b14: 2001 movs r0, #1 + 1b16: f042 7280 orr.w r2, r2, #16777216 ; 0x1000000 + 1b1a: 601a str r2, [r3, #0] + 1b1c: bd10 pop {r4, pc} + 1b1e: 4608 mov r0, r1 + 1b20: 4622 mov r2, r4 + 1b22: 21ff movs r1, #255 ; 0xff + 1b24: f7ff f8ce bl cc4 + 1b28: 4622 mov r2, r4 + 1b2a: 2002 movs r0, #2 + 1b2c: 217f movs r1, #127 ; 0x7f + 1b2e: f7ff f8c9 bl cc4 + 1b32: 4622 mov r2, r4 + 1b34: 2003 movs r0, #3 + 1b36: 2130 movs r1, #48 ; 0x30 + 1b38: f7ff f8c4 bl cc4 + 1b3c: f44f 7328 mov.w r3, #672 ; 0x2a0 + 1b40: f2c4 0300 movt r3, #16384 ; 0x4000 + 1b44: 681a ldr r2, [r3, #0] + 1b46: 2001 movs r0, #1 + 1b48: f022 7280 bic.w r2, r2, #16777216 ; 0x1000000 + 1b4c: 601a str r2, [r3, #0] + 1b4e: bd10 pop {r4, pc} + +00001b50 : + 1b50: 2801 cmp r0, #1 + 1b52: b510 push {r4, lr} + 1b54: 460a mov r2, r1 + 1b56: 4604 mov r4, r0 + 1b58: d039 beq.n 1bce + 1b5a: d31b bcc.n 1b94 + 1b5c: 2802 cmp r0, #2 + 1b5e: d00e beq.n 1b7e + 1b60: b9b1 cbnz r1, 1b90 + 1b62: f44f 7329 mov.w r3, #676 ; 0x2a4 + 1b66: f2c4 0300 movt r3, #16384 ; 0x4000 + 1b6a: 681a ldr r2, [r3, #0] + 1b6c: 2001 movs r0, #1 + 1b6e: f022 0206 bic.w r2, r2, #6 + 1b72: 601a str r2, [r3, #0] + 1b74: 681a ldr r2, [r3, #0] + 1b76: f022 0201 bic.w r2, r2, #1 + 1b7a: 601a str r2, [r3, #0] + 1b7c: bd10 pop {r4, pc} + 1b7e: 2900 cmp r1, #0 + 1b80: d036 beq.n 1bf0 + 1b82: f240 3334 movw r3, #820 ; 0x334 + 1b86: f2c1 0300 movt r3, #4096 ; 0x1000 + 1b8a: 885b ldrh r3, [r3, #2] + 1b8c: 079b lsls r3, r3, #30 + 1b8e: d538 bpl.n 1c02 + 1b90: 2000 movs r0, #0 + 1b92: bd10 pop {r4, pc} + 1b94: b339 cbz r1, 1be6 + 1b96: f240 3334 movw r3, #820 ; 0x334 + 1b9a: f2c1 0300 movt r3, #4096 ; 0x1000 + 1b9e: 885b ldrh r3, [r3, #2] + 1ba0: 0698 lsls r0, r3, #26 + 1ba2: d4f5 bmi.n 1b90 + 1ba4: 2001 movs r0, #1 + 1ba6: 2120 movs r1, #32 + 1ba8: f7ff f88c bl cc4 + 1bac: f44f 7329 mov.w r3, #676 ; 0x2a4 + 1bb0: f2c4 0300 movt r3, #16384 ; 0x4000 + 1bb4: 681a ldr r2, [r3, #0] + 1bb6: f004 0403 and.w r4, r4, #3 + 1bba: f022 0206 bic.w r2, r2, #6 + 1bbe: ea42 0444 orr.w r4, r2, r4, lsl #1 + 1bc2: 601c str r4, [r3, #0] + 1bc4: 681a ldr r2, [r3, #0] + 1bc6: 2001 movs r0, #1 + 1bc8: 4302 orrs r2, r0 + 1bca: 601a str r2, [r3, #0] + 1bcc: bd10 pop {r4, pc} + 1bce: b1a1 cbz r1, 1bfa + 1bd0: f240 3334 movw r3, #820 ; 0x334 + 1bd4: f2c1 0300 movt r3, #4096 ; 0x1000 + 1bd8: 885b ldrh r3, [r3, #2] + 1bda: 06d9 lsls r1, r3, #27 + 1bdc: d4d8 bmi.n 1b90 + 1bde: 2110 movs r1, #16 + 1be0: f7ff f870 bl cc4 + 1be4: e7e2 b.n 1bac + 1be6: 2001 movs r0, #1 + 1be8: 2120 movs r1, #32 + 1bea: f7ff f86b bl cc4 + 1bee: e7b8 b.n 1b62 + 1bf0: 4601 mov r1, r0 + 1bf2: 2001 movs r0, #1 + 1bf4: f7ff f866 bl cc4 + 1bf8: e7b3 b.n 1b62 + 1bfa: 2110 movs r1, #16 + 1bfc: f7ff f862 bl cc4 + 1c00: e7af b.n 1b62 + 1c02: 2001 movs r0, #1 + 1c04: 4621 mov r1, r4 + 1c06: f7ff f85d bl cc4 + 1c0a: e7cf b.n 1bac + +00001c0c : + 1c0c: b508 push {r3, lr} + 1c0e: b1b9 cbz r1, 1c40 + 1c10: f240 3334 movw r3, #820 ; 0x334 + 1c14: f2c1 0300 movt r3, #4096 ; 0x1000 + 1c18: 885b ldrh r3, [r3, #2] + 1c1a: f003 030c and.w r3, r3, #12 + 1c1e: b10b cbz r3, 1c24 + 1c20: 2000 movs r0, #0 + 1c22: bd08 pop {r3, pc} + 1c24: 2001 movs r0, #1 + 1c26: 210c movs r1, #12 + 1c28: f7ff f836 bl c98 + 1c2c: f44f 7329 mov.w r3, #676 ; 0x2a4 + 1c30: f2c4 0300 movt r3, #16384 ; 0x4000 + 1c34: 681a ldr r2, [r3, #0] + 1c36: 2001 movs r0, #1 + 1c38: f442 7280 orr.w r2, r2, #256 ; 0x100 + 1c3c: 601a str r2, [r3, #0] + 1c3e: bd08 pop {r3, pc} + 1c40: 460a mov r2, r1 + 1c42: 2001 movs r0, #1 + 1c44: 210c movs r1, #12 + 1c46: f7ff f83d bl cc4 + 1c4a: f44f 7329 mov.w r3, #676 ; 0x2a4 + 1c4e: f2c4 0300 movt r3, #16384 ; 0x4000 + 1c52: 681a ldr r2, [r3, #0] + 1c54: 2001 movs r0, #1 + 1c56: f422 7280 bic.w r2, r2, #256 ; 0x100 + 1c5a: 601a str r2, [r3, #0] + 1c5c: bd08 pop {r3, pc} + 1c5e: bf00 nop + +00001c60 : + 1c60: b508 push {r3, lr} + 1c62: b1b9 cbz r1, 1c94 + 1c64: f240 3334 movw r3, #820 ; 0x334 + 1c68: f2c1 0300 movt r3, #4096 ; 0x1000 + 1c6c: 885b ldrh r3, [r3, #2] + 1c6e: f003 03c0 and.w r3, r3, #192 ; 0xc0 + 1c72: b10b cbz r3, 1c78 + 1c74: 2000 movs r0, #0 + 1c76: bd08 pop {r3, pc} + 1c78: 2001 movs r0, #1 + 1c7a: 21c0 movs r1, #192 ; 0xc0 + 1c7c: f7ff f80c bl c98 + 1c80: f44f 7329 mov.w r3, #676 ; 0x2a4 + 1c84: f2c4 0300 movt r3, #16384 ; 0x4000 + 1c88: 681a ldr r2, [r3, #0] + 1c8a: 2001 movs r0, #1 + 1c8c: f442 7200 orr.w r2, r2, #512 ; 0x200 + 1c90: 601a str r2, [r3, #0] + 1c92: bd08 pop {r3, pc} + 1c94: 460a mov r2, r1 + 1c96: 2001 movs r0, #1 + 1c98: 21c0 movs r1, #192 ; 0xc0 + 1c9a: f7ff f813 bl cc4 + 1c9e: f44f 7329 mov.w r3, #676 ; 0x2a4 + 1ca2: f2c4 0300 movt r3, #16384 ; 0x4000 + 1ca6: 681a ldr r2, [r3, #0] + 1ca8: 2001 movs r0, #1 + 1caa: f422 7200 bic.w r2, r2, #512 ; 0x200 + 1cae: 601a str r2, [r3, #0] + 1cb0: bd08 pop {r3, pc} + 1cb2: bf00 nop + +00001cb4 : + 1cb4: b508 push {r3, lr} + 1cb6: b1b1 cbz r1, 1ce6 + 1cb8: f240 3334 movw r3, #820 ; 0x334 + 1cbc: f2c1 0300 movt r3, #4096 ; 0x1000 + 1cc0: 889b ldrh r3, [r3, #4] + 1cc2: 071b lsls r3, r3, #28 + 1cc4: d001 beq.n 1cca + 1cc6: 2000 movs r0, #0 + 1cc8: bd08 pop {r3, pc} + 1cca: 2002 movs r0, #2 + 1ccc: 210f movs r1, #15 + 1cce: f7fe ffe3 bl c98 + 1cd2: f44f 7329 mov.w r3, #676 ; 0x2a4 + 1cd6: f2c4 0300 movt r3, #16384 ; 0x4000 + 1cda: 681a ldr r2, [r3, #0] + 1cdc: 2001 movs r0, #1 + 1cde: f442 5280 orr.w r2, r2, #4096 ; 0x1000 + 1ce2: 601a str r2, [r3, #0] + 1ce4: bd08 pop {r3, pc} + 1ce6: 460a mov r2, r1 + 1ce8: 2002 movs r0, #2 + 1cea: 210f movs r1, #15 + 1cec: f7fe ffea bl cc4 + 1cf0: f44f 7329 mov.w r3, #676 ; 0x2a4 + 1cf4: f2c4 0300 movt r3, #16384 ; 0x4000 + 1cf8: 681a ldr r2, [r3, #0] + 1cfa: 2001 movs r0, #1 + 1cfc: f422 5280 bic.w r2, r2, #4096 ; 0x1000 + 1d00: 601a str r2, [r3, #0] + 1d02: bd08 pop {r3, pc} + +00001d04 : + 1d04: b508 push {r3, lr} + 1d06: b1b9 cbz r1, 1d38 + 1d08: f240 3334 movw r3, #820 ; 0x334 + 1d0c: f2c1 0300 movt r3, #4096 ; 0x1000 + 1d10: 889b ldrh r3, [r3, #4] + 1d12: f003 0370 and.w r3, r3, #112 ; 0x70 + 1d16: b10b cbz r3, 1d1c + 1d18: 2000 movs r0, #0 + 1d1a: bd08 pop {r3, pc} + 1d1c: 2002 movs r0, #2 + 1d1e: 2170 movs r1, #112 ; 0x70 + 1d20: f7fe ffba bl c98 + 1d24: f44f 7329 mov.w r3, #676 ; 0x2a4 + 1d28: f2c4 0300 movt r3, #16384 ; 0x4000 + 1d2c: 681a ldr r2, [r3, #0] + 1d2e: 2001 movs r0, #1 + 1d30: f442 5200 orr.w r2, r2, #8192 ; 0x2000 + 1d34: 601a str r2, [r3, #0] + 1d36: bd08 pop {r3, pc} + 1d38: 460a mov r2, r1 + 1d3a: 2002 movs r0, #2 + 1d3c: 2170 movs r1, #112 ; 0x70 + 1d3e: f7fe ffc1 bl cc4 + 1d42: f44f 7329 mov.w r3, #676 ; 0x2a4 + 1d46: f2c4 0300 movt r3, #16384 ; 0x4000 + 1d4a: 681a ldr r2, [r3, #0] + 1d4c: 2001 movs r0, #1 + 1d4e: f422 5200 bic.w r2, r2, #8192 ; 0x2000 + 1d52: 601a str r2, [r3, #0] + 1d54: bd08 pop {r3, pc} + 1d56: bf00 nop + +00001d58 : + 1d58: b508 push {r3, lr} + 1d5a: b1b1 cbz r1, 1d8a + 1d5c: f240 3334 movw r3, #820 ; 0x334 + 1d60: f2c1 0300 movt r3, #4096 ; 0x1000 + 1d64: 885b ldrh r3, [r3, #2] + 1d66: 069b lsls r3, r3, #26 + 1d68: d001 beq.n 1d6e + 1d6a: 2000 movs r0, #0 + 1d6c: bd08 pop {r3, pc} + 1d6e: 2001 movs r0, #1 + 1d70: 213f movs r1, #63 ; 0x3f + 1d72: f7fe ff91 bl c98 + 1d76: f44f 7329 mov.w r3, #676 ; 0x2a4 + 1d7a: f2c4 0300 movt r3, #16384 ; 0x4000 + 1d7e: 681a ldr r2, [r3, #0] + 1d80: 2001 movs r0, #1 + 1d82: f442 3280 orr.w r2, r2, #65536 ; 0x10000 + 1d86: 601a str r2, [r3, #0] + 1d88: bd08 pop {r3, pc} + 1d8a: 460a mov r2, r1 + 1d8c: 2001 movs r0, #1 + 1d8e: 213f movs r1, #63 ; 0x3f + 1d90: f7fe ff98 bl cc4 + 1d94: f44f 7329 mov.w r3, #676 ; 0x2a4 + 1d98: f2c4 0300 movt r3, #16384 ; 0x4000 + 1d9c: 681a ldr r2, [r3, #0] + 1d9e: 2001 movs r0, #1 + 1da0: f422 3280 bic.w r2, r2, #65536 ; 0x10000 + 1da4: 601a str r2, [r3, #0] + 1da6: bd08 pop {r3, pc} + +00001da8 : + 1da8: b538 push {r3, r4, r5, lr} + 1daa: 4604 mov r4, r0 + 1dac: 460d mov r5, r1 + 1dae: 2803 cmp r0, #3 + 1db0: d84e bhi.n 1e50 + 1db2: e8df f000 tbb [pc, r0] + 1db6: 1c3f .short 0x1c3f + 1db8: 020d .short 0x020d + 1dba: 2900 cmp r1, #0 + 1dbc: d064 beq.n 1e88 + 1dbe: f240 3334 movw r3, #820 ; 0x334 + 1dc2: f2c1 0300 movt r3, #4096 ; 0x1000 + 1dc6: 891b ldrh r3, [r3, #8] + 1dc8: 07db lsls r3, r3, #31 + 1dca: d569 bpl.n 1ea0 + 1dcc: 2000 movs r0, #0 + 1dce: bd38 pop {r3, r4, r5, pc} + 1dd0: 2900 cmp r1, #0 + 1dd2: d053 beq.n 1e7c + 1dd4: f240 3334 movw r3, #820 ; 0x334 + 1dd8: f2c1 0300 movt r3, #4096 ; 0x1000 + 1ddc: 88db ldrh r3, [r3, #6] + 1dde: 06da lsls r2, r3, #27 + 1de0: d4f4 bmi.n 1dcc + 1de2: 2003 movs r0, #3 + 1de4: 2110 movs r1, #16 + 1de6: 462a mov r2, r5 + 1de8: f7fe ff6c bl cc4 + 1dec: e00d b.n 1e0a + 1dee: 2900 cmp r1, #0 + 1df0: d03e beq.n 1e70 + 1df2: f240 3334 movw r3, #820 ; 0x334 + 1df6: f2c1 0300 movt r3, #4096 ; 0x1000 + 1dfa: 889b ldrh r3, [r3, #4] + 1dfc: 07d9 lsls r1, r3, #31 + 1dfe: d4e5 bmi.n 1dcc + 1e00: 2002 movs r0, #2 + 1e02: 2101 movs r1, #1 + 1e04: 462a mov r2, r5 + 1e06: f7fe ff5d bl cc4 + 1e0a: f44f 732b mov.w r3, #684 ; 0x2ac + 1e0e: f2c4 0300 movt r3, #16384 ; 0x4000 + 1e12: 681a ldr r2, [r3, #0] + 1e14: f004 0403 and.w r4, r4, #3 + 1e18: f022 0206 bic.w r2, r2, #6 + 1e1c: ea42 0444 orr.w r4, r2, r4, lsl #1 + 1e20: 601c str r4, [r3, #0] + 1e22: 681a ldr r2, [r3, #0] + 1e24: f005 0501 and.w r5, r5, #1 + 1e28: f022 0201 bic.w r2, r2, #1 + 1e2c: 4315 orrs r5, r2 + 1e2e: 601d str r5, [r3, #0] + 1e30: 2001 movs r0, #1 + 1e32: bd38 pop {r3, r4, r5, pc} + 1e34: b371 cbz r1, 1e94 + 1e36: f240 3334 movw r3, #820 ; 0x334 + 1e3a: f2c1 0300 movt r3, #4096 ; 0x1000 + 1e3e: 885b ldrh r3, [r3, #2] + 1e40: 06d8 lsls r0, r3, #27 + 1e42: d4c3 bmi.n 1dcc + 1e44: 2001 movs r0, #1 + 1e46: 2110 movs r1, #16 + 1e48: 462a mov r2, r5 + 1e4a: f7fe ff3b bl cc4 + 1e4e: e7dc b.n 1e0a + 1e50: 2900 cmp r1, #0 + 1e52: d1bb bne.n 1dcc + 1e54: f44f 732b mov.w r3, #684 ; 0x2ac + 1e58: f2c4 0300 movt r3, #16384 ; 0x4000 + 1e5c: 681a ldr r2, [r3, #0] + 1e5e: 2001 movs r0, #1 + 1e60: f022 0206 bic.w r2, r2, #6 + 1e64: 601a str r2, [r3, #0] + 1e66: 681a ldr r2, [r3, #0] + 1e68: f022 0201 bic.w r2, r2, #1 + 1e6c: 601a str r2, [r3, #0] + 1e6e: bd38 pop {r3, r4, r5, pc} + 1e70: 460a mov r2, r1 + 1e72: 2002 movs r0, #2 + 1e74: 2101 movs r1, #1 + 1e76: f7fe ff25 bl cc4 + 1e7a: e7eb b.n 1e54 + 1e7c: 460a mov r2, r1 + 1e7e: 2003 movs r0, #3 + 1e80: 2110 movs r1, #16 + 1e82: f7fe ff1f bl cc4 + 1e86: e7e5 b.n 1e54 + 1e88: 460a mov r2, r1 + 1e8a: 2004 movs r0, #4 + 1e8c: 2101 movs r1, #1 + 1e8e: f7fe ff19 bl cc4 + 1e92: e7df b.n 1e54 + 1e94: 460a mov r2, r1 + 1e96: 2001 movs r0, #1 + 1e98: 2110 movs r1, #16 + 1e9a: f7fe ff13 bl cc4 + 1e9e: e7d9 b.n 1e54 + 1ea0: 2004 movs r0, #4 + 1ea2: 2101 movs r1, #1 + 1ea4: 462a mov r2, r5 + 1ea6: f7fe ff0d bl cc4 + 1eaa: e7ae b.n 1e0a + +00001eac : + 1eac: b538 push {r3, r4, r5, lr} + 1eae: 4604 mov r4, r0 + 1eb0: 460d mov r5, r1 + 1eb2: 2803 cmp r0, #3 + 1eb4: d84f bhi.n 1f56 + 1eb6: e8df f000 tbb [pc, r0] + 1eba: 1c40 .short 0x1c40 + 1ebc: 020d .short 0x020d + 1ebe: 2900 cmp r1, #0 + 1ec0: d065 beq.n 1f8e + 1ec2: f240 3334 movw r3, #820 ; 0x334 + 1ec6: f2c1 0300 movt r3, #4096 ; 0x1000 + 1eca: 891b ldrh r3, [r3, #8] + 1ecc: 079b lsls r3, r3, #30 + 1ece: d56a bpl.n 1fa6 + 1ed0: 2000 movs r0, #0 + 1ed2: bd38 pop {r3, r4, r5, pc} + 1ed4: 2900 cmp r1, #0 + 1ed6: d054 beq.n 1f82 + 1ed8: f240 3334 movw r3, #820 ; 0x334 + 1edc: f2c1 0300 movt r3, #4096 ; 0x1000 + 1ee0: 88db ldrh r3, [r3, #6] + 1ee2: 069a lsls r2, r3, #26 + 1ee4: d4f4 bmi.n 1ed0 + 1ee6: 2003 movs r0, #3 + 1ee8: 2120 movs r1, #32 + 1eea: 462a mov r2, r5 + 1eec: f7fe feea bl cc4 + 1ef0: e00d b.n 1f0e + 1ef2: 2900 cmp r1, #0 + 1ef4: d03f beq.n 1f76 + 1ef6: f240 3334 movw r3, #820 ; 0x334 + 1efa: f2c1 0300 movt r3, #4096 ; 0x1000 + 1efe: 889b ldrh r3, [r3, #4] + 1f00: 0799 lsls r1, r3, #30 + 1f02: d4e5 bmi.n 1ed0 + 1f04: 2002 movs r0, #2 + 1f06: 4601 mov r1, r0 + 1f08: 462a mov r2, r5 + 1f0a: f7fe fedb bl cc4 + 1f0e: f44f 732b mov.w r3, #684 ; 0x2ac + 1f12: f2c4 0300 movt r3, #16384 ; 0x4000 + 1f16: 681a ldr r2, [r3, #0] + 1f18: f004 0403 and.w r4, r4, #3 + 1f1c: f022 0260 bic.w r2, r2, #96 ; 0x60 + 1f20: ea42 1444 orr.w r4, r2, r4, lsl #5 + 1f24: 601c str r4, [r3, #0] + 1f26: 681a ldr r2, [r3, #0] + 1f28: 426d negs r5, r5 + 1f2a: f022 0210 bic.w r2, r2, #16 + 1f2e: f005 0510 and.w r5, r5, #16 + 1f32: 4315 orrs r5, r2 + 1f34: 601d str r5, [r3, #0] + 1f36: 2001 movs r0, #1 + 1f38: bd38 pop {r3, r4, r5, pc} + 1f3a: b371 cbz r1, 1f9a + 1f3c: f240 3334 movw r3, #820 ; 0x334 + 1f40: f2c1 0300 movt r3, #4096 ; 0x1000 + 1f44: 885b ldrh r3, [r3, #2] + 1f46: 0698 lsls r0, r3, #26 + 1f48: d4c2 bmi.n 1ed0 + 1f4a: 2001 movs r0, #1 + 1f4c: 2120 movs r1, #32 + 1f4e: 462a mov r2, r5 + 1f50: f7fe feb8 bl cc4 + 1f54: e7db b.n 1f0e + 1f56: 2900 cmp r1, #0 + 1f58: d1ba bne.n 1ed0 + 1f5a: f44f 732b mov.w r3, #684 ; 0x2ac + 1f5e: f2c4 0300 movt r3, #16384 ; 0x4000 + 1f62: 681a ldr r2, [r3, #0] + 1f64: 2001 movs r0, #1 + 1f66: f022 0260 bic.w r2, r2, #96 ; 0x60 + 1f6a: 601a str r2, [r3, #0] + 1f6c: 681a ldr r2, [r3, #0] + 1f6e: f022 0210 bic.w r2, r2, #16 + 1f72: 601a str r2, [r3, #0] + 1f74: bd38 pop {r3, r4, r5, pc} + 1f76: 2002 movs r0, #2 + 1f78: 460a mov r2, r1 + 1f7a: 4601 mov r1, r0 + 1f7c: f7fe fea2 bl cc4 + 1f80: e7eb b.n 1f5a + 1f82: 460a mov r2, r1 + 1f84: 2003 movs r0, #3 + 1f86: 2120 movs r1, #32 + 1f88: f7fe fe9c bl cc4 + 1f8c: e7e5 b.n 1f5a + 1f8e: 460a mov r2, r1 + 1f90: 2004 movs r0, #4 + 1f92: 2102 movs r1, #2 + 1f94: f7fe fe96 bl cc4 + 1f98: e7df b.n 1f5a + 1f9a: 460a mov r2, r1 + 1f9c: 2001 movs r0, #1 + 1f9e: 2120 movs r1, #32 + 1fa0: f7fe fe90 bl cc4 + 1fa4: e7d9 b.n 1f5a + 1fa6: 2004 movs r0, #4 + 1fa8: 2102 movs r1, #2 + 1faa: 462a mov r2, r5 + 1fac: f7fe fe8a bl cc4 + 1fb0: e7ad b.n 1f0e + 1fb2: bf00 nop + +00001fb4 : + 1fb4: b510 push {r4, lr} + 1fb6: 4604 mov r4, r0 + 1fb8: 2803 cmp r0, #3 + 1fba: d84b bhi.n 2054 + 1fbc: e8df f000 tbb [pc, r0] + 1fc0: 020d1c3c .word 0x020d1c3c + 1fc4: 2900 cmp r1, #0 + 1fc6: d061 beq.n 208c + 1fc8: f240 3334 movw r3, #820 ; 0x334 + 1fcc: f2c1 0300 movt r3, #4096 ; 0x1000 + 1fd0: 891b ldrh r3, [r3, #8] + 1fd2: 075b lsls r3, r3, #29 + 1fd4: d566 bpl.n 20a4 + 1fd6: 2000 movs r0, #0 + 1fd8: bd10 pop {r4, pc} + 1fda: 2900 cmp r1, #0 + 1fdc: d050 beq.n 2080 + 1fde: f240 3334 movw r3, #820 ; 0x334 + 1fe2: f2c1 0300 movt r3, #4096 ; 0x1000 + 1fe6: 88db ldrh r3, [r3, #6] + 1fe8: 065a lsls r2, r3, #25 + 1fea: d4f4 bmi.n 1fd6 + 1fec: 460a mov r2, r1 + 1fee: 2003 movs r0, #3 + 1ff0: 2140 movs r1, #64 ; 0x40 + 1ff2: f7fe fe67 bl cc4 + 1ff6: e00d b.n 2014 + 1ff8: 2900 cmp r1, #0 + 1ffa: d03b beq.n 2074 + 1ffc: f240 3334 movw r3, #820 ; 0x334 + 2000: f2c1 0300 movt r3, #4096 ; 0x1000 + 2004: 889b ldrh r3, [r3, #4] + 2006: 0758 lsls r0, r3, #29 + 2008: d4e5 bmi.n 1fd6 + 200a: 460a mov r2, r1 + 200c: 2002 movs r0, #2 + 200e: 2104 movs r1, #4 + 2010: f7fe fe58 bl cc4 + 2014: f44f 732b mov.w r3, #684 ; 0x2ac + 2018: f2c4 0300 movt r3, #16384 ; 0x4000 + 201c: 681a ldr r2, [r3, #0] + 201e: f004 0403 and.w r4, r4, #3 + 2022: f422 62c0 bic.w r2, r2, #1536 ; 0x600 + 2026: ea42 2444 orr.w r4, r2, r4, lsl #9 + 202a: 601c str r4, [r3, #0] + 202c: 681a ldr r2, [r3, #0] + 202e: 2001 movs r0, #1 + 2030: f442 7280 orr.w r2, r2, #256 ; 0x100 + 2034: 601a str r2, [r3, #0] + 2036: bd10 pop {r4, pc} + 2038: b371 cbz r1, 2098 + 203a: f240 3334 movw r3, #820 ; 0x334 + 203e: f2c1 0300 movt r3, #4096 ; 0x1000 + 2042: 885b ldrh r3, [r3, #2] + 2044: 065b lsls r3, r3, #25 + 2046: d4c6 bmi.n 1fd6 + 2048: 460a mov r2, r1 + 204a: 2001 movs r0, #1 + 204c: 2140 movs r1, #64 ; 0x40 + 204e: f7fe fe39 bl cc4 + 2052: e7df b.n 2014 + 2054: 2900 cmp r1, #0 + 2056: d1be bne.n 1fd6 + 2058: f44f 732b mov.w r3, #684 ; 0x2ac + 205c: f2c4 0300 movt r3, #16384 ; 0x4000 + 2060: 681a ldr r2, [r3, #0] + 2062: 2001 movs r0, #1 + 2064: f422 62c0 bic.w r2, r2, #1536 ; 0x600 + 2068: 601a str r2, [r3, #0] + 206a: 681a ldr r2, [r3, #0] + 206c: f422 7280 bic.w r2, r2, #256 ; 0x100 + 2070: 601a str r2, [r3, #0] + 2072: bd10 pop {r4, pc} + 2074: 460a mov r2, r1 + 2076: 2002 movs r0, #2 + 2078: 2104 movs r1, #4 + 207a: f7fe fe23 bl cc4 + 207e: e7eb b.n 2058 + 2080: 460a mov r2, r1 + 2082: 2003 movs r0, #3 + 2084: 2140 movs r1, #64 ; 0x40 + 2086: f7fe fe1d bl cc4 + 208a: e7e5 b.n 2058 + 208c: 2004 movs r0, #4 + 208e: 460a mov r2, r1 + 2090: 4601 mov r1, r0 + 2092: f7fe fe17 bl cc4 + 2096: e7df b.n 2058 + 2098: 460a mov r2, r1 + 209a: 2001 movs r0, #1 + 209c: 2140 movs r1, #64 ; 0x40 + 209e: f7fe fe11 bl cc4 + 20a2: e7d9 b.n 2058 + 20a4: 2004 movs r0, #4 + 20a6: 460a mov r2, r1 + 20a8: 4601 mov r1, r0 + 20aa: f7fe fe0b bl cc4 + 20ae: e7b1 b.n 2014 + +000020b0 : + 20b0: b538 push {r3, r4, r5, lr} + 20b2: 4604 mov r4, r0 + 20b4: 460d mov r5, r1 + 20b6: 2803 cmp r0, #3 + 20b8: d84f bhi.n 215a + 20ba: e8df f000 tbb [pc, r0] + 20be: 1c40 .short 0x1c40 + 20c0: 020d .short 0x020d + 20c2: 2900 cmp r1, #0 + 20c4: d065 beq.n 2192 + 20c6: f240 3334 movw r3, #820 ; 0x334 + 20ca: f2c1 0300 movt r3, #4096 ; 0x1000 + 20ce: 891b ldrh r3, [r3, #8] + 20d0: 071b lsls r3, r3, #28 + 20d2: d56a bpl.n 21aa + 20d4: 2000 movs r0, #0 + 20d6: bd38 pop {r3, r4, r5, pc} + 20d8: 2900 cmp r1, #0 + 20da: d054 beq.n 2186 + 20dc: f240 3334 movw r3, #820 ; 0x334 + 20e0: f2c1 0300 movt r3, #4096 ; 0x1000 + 20e4: 88db ldrh r3, [r3, #6] + 20e6: 061a lsls r2, r3, #24 + 20e8: d4f4 bmi.n 20d4 + 20ea: 2003 movs r0, #3 + 20ec: 2180 movs r1, #128 ; 0x80 + 20ee: 462a mov r2, r5 + 20f0: f7fe fde8 bl cc4 + 20f4: e00d b.n 2112 + 20f6: 2900 cmp r1, #0 + 20f8: d03f beq.n 217a + 20fa: f240 3334 movw r3, #820 ; 0x334 + 20fe: f2c1 0300 movt r3, #4096 ; 0x1000 + 2102: 889b ldrh r3, [r3, #4] + 2104: 0719 lsls r1, r3, #28 + 2106: d4e5 bmi.n 20d4 + 2108: 2002 movs r0, #2 + 210a: 2108 movs r1, #8 + 210c: 462a mov r2, r5 + 210e: f7fe fdd9 bl cc4 + 2112: f44f 732b mov.w r3, #684 ; 0x2ac + 2116: f2c4 0300 movt r3, #16384 ; 0x4000 + 211a: 681a ldr r2, [r3, #0] + 211c: f004 0403 and.w r4, r4, #3 + 2120: f422 42c0 bic.w r2, r2, #24576 ; 0x6000 + 2124: ea42 3444 orr.w r4, r2, r4, lsl #13 + 2128: 601c str r4, [r3, #0] + 212a: 681a ldr r2, [r3, #0] + 212c: 426d negs r5, r5 + 212e: f422 5280 bic.w r2, r2, #4096 ; 0x1000 + 2132: f405 5580 and.w r5, r5, #4096 ; 0x1000 + 2136: 4315 orrs r5, r2 + 2138: 601d str r5, [r3, #0] + 213a: 2001 movs r0, #1 + 213c: bd38 pop {r3, r4, r5, pc} + 213e: b371 cbz r1, 219e + 2140: f240 3334 movw r3, #820 ; 0x334 + 2144: f2c1 0300 movt r3, #4096 ; 0x1000 + 2148: 885b ldrh r3, [r3, #2] + 214a: 0618 lsls r0, r3, #24 + 214c: d4c2 bmi.n 20d4 + 214e: 2001 movs r0, #1 + 2150: 2180 movs r1, #128 ; 0x80 + 2152: 462a mov r2, r5 + 2154: f7fe fdb6 bl cc4 + 2158: e7db b.n 2112 + 215a: 2900 cmp r1, #0 + 215c: d1ba bne.n 20d4 + 215e: f44f 732b mov.w r3, #684 ; 0x2ac + 2162: f2c4 0300 movt r3, #16384 ; 0x4000 + 2166: 681a ldr r2, [r3, #0] + 2168: 2001 movs r0, #1 + 216a: f422 42c0 bic.w r2, r2, #24576 ; 0x6000 + 216e: 601a str r2, [r3, #0] + 2170: 681a ldr r2, [r3, #0] + 2172: f422 5280 bic.w r2, r2, #4096 ; 0x1000 + 2176: 601a str r2, [r3, #0] + 2178: bd38 pop {r3, r4, r5, pc} + 217a: 460a mov r2, r1 + 217c: 2002 movs r0, #2 + 217e: 2108 movs r1, #8 + 2180: f7fe fda0 bl cc4 + 2184: e7eb b.n 215e + 2186: 460a mov r2, r1 + 2188: 2003 movs r0, #3 + 218a: 2180 movs r1, #128 ; 0x80 + 218c: f7fe fd9a bl cc4 + 2190: e7e5 b.n 215e + 2192: 460a mov r2, r1 + 2194: 2004 movs r0, #4 + 2196: 2108 movs r1, #8 + 2198: f7fe fd94 bl cc4 + 219c: e7df b.n 215e + 219e: 460a mov r2, r1 + 21a0: 2001 movs r0, #1 + 21a2: 2180 movs r1, #128 ; 0x80 + 21a4: f7fe fd8e bl cc4 + 21a8: e7d9 b.n 215e + 21aa: 2004 movs r0, #4 + 21ac: 2108 movs r1, #8 + 21ae: 462a mov r2, r5 + 21b0: f7fe fd88 bl cc4 + 21b4: e7ad b.n 2112 + 21b6: bf00 nop + +000021b8 : + 21b8: b538 push {r3, r4, r5, lr} + 21ba: 4604 mov r4, r0 + 21bc: 460d mov r5, r1 + 21be: 2803 cmp r0, #3 + 21c0: d84f bhi.n 2262 + 21c2: e8df f000 tbb [pc, r0] + 21c6: 1c40 .short 0x1c40 + 21c8: 020d .short 0x020d + 21ca: 2900 cmp r1, #0 + 21cc: d065 beq.n 229a + 21ce: f240 3334 movw r3, #820 ; 0x334 + 21d2: f2c1 0300 movt r3, #4096 ; 0x1000 + 21d6: 89db ldrh r3, [r3, #14] + 21d8: 07db lsls r3, r3, #31 + 21da: d56a bpl.n 22b2 + 21dc: 2000 movs r0, #0 + 21de: bd38 pop {r3, r4, r5, pc} + 21e0: 2900 cmp r1, #0 + 21e2: d054 beq.n 228e + 21e4: f240 3334 movw r3, #820 ; 0x334 + 21e8: f2c1 0300 movt r3, #4096 ; 0x1000 + 21ec: 88db ldrh r3, [r3, #6] + 21ee: 06da lsls r2, r3, #27 + 21f0: d4f4 bmi.n 21dc + 21f2: 2003 movs r0, #3 + 21f4: 2110 movs r1, #16 + 21f6: 462a mov r2, r5 + 21f8: f7fe fd64 bl cc4 + 21fc: e00d b.n 221a + 21fe: 2900 cmp r1, #0 + 2200: d03f beq.n 2282 + 2202: f240 3334 movw r3, #820 ; 0x334 + 2206: f2c1 0300 movt r3, #4096 ; 0x1000 + 220a: 889b ldrh r3, [r3, #4] + 220c: 07d9 lsls r1, r3, #31 + 220e: d4e5 bmi.n 21dc + 2210: 2002 movs r0, #2 + 2212: 2101 movs r1, #1 + 2214: 462a mov r2, r5 + 2216: f7fe fd55 bl cc4 + 221a: f44f 732b mov.w r3, #684 ; 0x2ac + 221e: f2c4 0300 movt r3, #16384 ; 0x4000 + 2222: 681a ldr r2, [r3, #0] + 2224: f004 0403 and.w r4, r4, #3 + 2228: f422 22c0 bic.w r2, r2, #393216 ; 0x60000 + 222c: ea42 4444 orr.w r4, r2, r4, lsl #17 + 2230: 601c str r4, [r3, #0] + 2232: 681a ldr r2, [r3, #0] + 2234: 426d negs r5, r5 + 2236: f422 3280 bic.w r2, r2, #65536 ; 0x10000 + 223a: f405 3580 and.w r5, r5, #65536 ; 0x10000 + 223e: 4315 orrs r5, r2 + 2240: 601d str r5, [r3, #0] + 2242: 2001 movs r0, #1 + 2244: bd38 pop {r3, r4, r5, pc} + 2246: b371 cbz r1, 22a6 + 2248: f240 3334 movw r3, #820 ; 0x334 + 224c: f2c1 0300 movt r3, #4096 ; 0x1000 + 2250: 885b ldrh r3, [r3, #2] + 2252: 07d8 lsls r0, r3, #31 + 2254: d4c2 bmi.n 21dc + 2256: 2001 movs r0, #1 + 2258: 4601 mov r1, r0 + 225a: 462a mov r2, r5 + 225c: f7fe fd32 bl cc4 + 2260: e7db b.n 221a + 2262: 2900 cmp r1, #0 + 2264: d1ba bne.n 21dc + 2266: f44f 732b mov.w r3, #684 ; 0x2ac + 226a: f2c4 0300 movt r3, #16384 ; 0x4000 + 226e: 681a ldr r2, [r3, #0] + 2270: 2001 movs r0, #1 + 2272: f422 22c0 bic.w r2, r2, #393216 ; 0x60000 + 2276: 601a str r2, [r3, #0] + 2278: 681a ldr r2, [r3, #0] + 227a: f422 3280 bic.w r2, r2, #65536 ; 0x10000 + 227e: 601a str r2, [r3, #0] + 2280: bd38 pop {r3, r4, r5, pc} + 2282: 460a mov r2, r1 + 2284: 2002 movs r0, #2 + 2286: 2101 movs r1, #1 + 2288: f7fe fd1c bl cc4 + 228c: e7eb b.n 2266 + 228e: 460a mov r2, r1 + 2290: 2003 movs r0, #3 + 2292: 2110 movs r1, #16 + 2294: f7fe fd16 bl cc4 + 2298: e7e5 b.n 2266 + 229a: 460a mov r2, r1 + 229c: 2007 movs r0, #7 + 229e: 2101 movs r1, #1 + 22a0: f7fe fd10 bl cc4 + 22a4: e7df b.n 2266 + 22a6: 2001 movs r0, #1 + 22a8: 460a mov r2, r1 + 22aa: 4601 mov r1, r0 + 22ac: f7fe fd0a bl cc4 + 22b0: e7d9 b.n 2266 + 22b2: 2007 movs r0, #7 + 22b4: 2101 movs r1, #1 + 22b6: 462a mov r2, r5 + 22b8: f7fe fd04 bl cc4 + 22bc: e7ad b.n 221a + 22be: bf00 nop + +000022c0 : + 22c0: b538 push {r3, r4, r5, lr} + 22c2: 4604 mov r4, r0 + 22c4: 460d mov r5, r1 + 22c6: 2803 cmp r0, #3 + 22c8: d84f bhi.n 236a + 22ca: e8df f000 tbb [pc, r0] + 22ce: 1c40 .short 0x1c40 + 22d0: 020d .short 0x020d + 22d2: 2900 cmp r1, #0 + 22d4: d065 beq.n 23a2 + 22d6: f240 3334 movw r3, #820 ; 0x334 + 22da: f2c1 0300 movt r3, #4096 ; 0x1000 + 22de: 89db ldrh r3, [r3, #14] + 22e0: 079b lsls r3, r3, #30 + 22e2: d56a bpl.n 23ba + 22e4: 2000 movs r0, #0 + 22e6: bd38 pop {r3, r4, r5, pc} + 22e8: 2900 cmp r1, #0 + 22ea: d054 beq.n 2396 + 22ec: f240 3334 movw r3, #820 ; 0x334 + 22f0: f2c1 0300 movt r3, #4096 ; 0x1000 + 22f4: 88db ldrh r3, [r3, #6] + 22f6: 069a lsls r2, r3, #26 + 22f8: d4f4 bmi.n 22e4 + 22fa: 2003 movs r0, #3 + 22fc: 2120 movs r1, #32 + 22fe: 462a mov r2, r5 + 2300: f7fe fce0 bl cc4 + 2304: e00d b.n 2322 + 2306: 2900 cmp r1, #0 + 2308: d03f beq.n 238a + 230a: f240 3334 movw r3, #820 ; 0x334 + 230e: f2c1 0300 movt r3, #4096 ; 0x1000 + 2312: 889b ldrh r3, [r3, #4] + 2314: 0799 lsls r1, r3, #30 + 2316: d4e5 bmi.n 22e4 + 2318: 2002 movs r0, #2 + 231a: 4601 mov r1, r0 + 231c: 462a mov r2, r5 + 231e: f7fe fcd1 bl cc4 + 2322: f44f 732b mov.w r3, #684 ; 0x2ac + 2326: f2c4 0300 movt r3, #16384 ; 0x4000 + 232a: 681a ldr r2, [r3, #0] + 232c: f004 0403 and.w r4, r4, #3 + 2330: f422 02c0 bic.w r2, r2, #6291456 ; 0x600000 + 2334: ea42 5444 orr.w r4, r2, r4, lsl #21 + 2338: 601c str r4, [r3, #0] + 233a: 681a ldr r2, [r3, #0] + 233c: 426d negs r5, r5 + 233e: f422 1280 bic.w r2, r2, #1048576 ; 0x100000 + 2342: f405 1580 and.w r5, r5, #1048576 ; 0x100000 + 2346: 4315 orrs r5, r2 + 2348: 601d str r5, [r3, #0] + 234a: 2001 movs r0, #1 + 234c: bd38 pop {r3, r4, r5, pc} + 234e: b371 cbz r1, 23ae + 2350: f240 3334 movw r3, #820 ; 0x334 + 2354: f2c1 0300 movt r3, #4096 ; 0x1000 + 2358: 885b ldrh r3, [r3, #2] + 235a: 0798 lsls r0, r3, #30 + 235c: d4c2 bmi.n 22e4 + 235e: 2001 movs r0, #1 + 2360: 2102 movs r1, #2 + 2362: 462a mov r2, r5 + 2364: f7fe fcae bl cc4 + 2368: e7db b.n 2322 + 236a: 2900 cmp r1, #0 + 236c: d1ba bne.n 22e4 + 236e: f44f 732b mov.w r3, #684 ; 0x2ac + 2372: f2c4 0300 movt r3, #16384 ; 0x4000 + 2376: 681a ldr r2, [r3, #0] + 2378: 2001 movs r0, #1 + 237a: f422 02c0 bic.w r2, r2, #6291456 ; 0x600000 + 237e: 601a str r2, [r3, #0] + 2380: 681a ldr r2, [r3, #0] + 2382: f422 1280 bic.w r2, r2, #1048576 ; 0x100000 + 2386: 601a str r2, [r3, #0] + 2388: bd38 pop {r3, r4, r5, pc} + 238a: 2002 movs r0, #2 + 238c: 460a mov r2, r1 + 238e: 4601 mov r1, r0 + 2390: f7fe fc98 bl cc4 + 2394: e7eb b.n 236e + 2396: 460a mov r2, r1 + 2398: 2003 movs r0, #3 + 239a: 2120 movs r1, #32 + 239c: f7fe fc92 bl cc4 + 23a0: e7e5 b.n 236e + 23a2: 460a mov r2, r1 + 23a4: 2007 movs r0, #7 + 23a6: 2102 movs r1, #2 + 23a8: f7fe fc8c bl cc4 + 23ac: e7df b.n 236e + 23ae: 460a mov r2, r1 + 23b0: 2001 movs r0, #1 + 23b2: 2102 movs r1, #2 + 23b4: f7fe fc86 bl cc4 + 23b8: e7d9 b.n 236e + 23ba: 2007 movs r0, #7 + 23bc: 2102 movs r1, #2 + 23be: 462a mov r2, r5 + 23c0: f7fe fc80 bl cc4 + 23c4: e7ad b.n 2322 + 23c6: bf00 nop + +000023c8 : + 23c8: b538 push {r3, r4, r5, lr} + 23ca: 4604 mov r4, r0 + 23cc: 460d mov r5, r1 + 23ce: 2803 cmp r0, #3 + 23d0: d84f bhi.n 2472 + 23d2: e8df f000 tbb [pc, r0] + 23d6: 1c40 .short 0x1c40 + 23d8: 020d .short 0x020d + 23da: 2900 cmp r1, #0 + 23dc: d065 beq.n 24aa + 23de: f240 3334 movw r3, #820 ; 0x334 + 23e2: f2c1 0300 movt r3, #4096 ; 0x1000 + 23e6: 89db ldrh r3, [r3, #14] + 23e8: 075b lsls r3, r3, #29 + 23ea: d56a bpl.n 24c2 + 23ec: 2000 movs r0, #0 + 23ee: bd38 pop {r3, r4, r5, pc} + 23f0: 2900 cmp r1, #0 + 23f2: d054 beq.n 249e + 23f4: f240 3334 movw r3, #820 ; 0x334 + 23f8: f2c1 0300 movt r3, #4096 ; 0x1000 + 23fc: 88db ldrh r3, [r3, #6] + 23fe: 065a lsls r2, r3, #25 + 2400: d4f4 bmi.n 23ec + 2402: 2003 movs r0, #3 + 2404: 2140 movs r1, #64 ; 0x40 + 2406: 462a mov r2, r5 + 2408: f7fe fc5c bl cc4 + 240c: e00d b.n 242a + 240e: 2900 cmp r1, #0 + 2410: d03f beq.n 2492 + 2412: f240 3334 movw r3, #820 ; 0x334 + 2416: f2c1 0300 movt r3, #4096 ; 0x1000 + 241a: 889b ldrh r3, [r3, #4] + 241c: 0759 lsls r1, r3, #29 + 241e: d4e5 bmi.n 23ec + 2420: 2002 movs r0, #2 + 2422: 2104 movs r1, #4 + 2424: 462a mov r2, r5 + 2426: f7fe fc4d bl cc4 + 242a: f44f 732b mov.w r3, #684 ; 0x2ac + 242e: f2c4 0300 movt r3, #16384 ; 0x4000 + 2432: 681a ldr r2, [r3, #0] + 2434: f004 0403 and.w r4, r4, #3 + 2438: f022 62c0 bic.w r2, r2, #100663296 ; 0x6000000 + 243c: ea42 6444 orr.w r4, r2, r4, lsl #25 + 2440: 601c str r4, [r3, #0] + 2442: 681a ldr r2, [r3, #0] + 2444: 426d negs r5, r5 + 2446: f022 7280 bic.w r2, r2, #16777216 ; 0x1000000 + 244a: f005 7580 and.w r5, r5, #16777216 ; 0x1000000 + 244e: 4315 orrs r5, r2 + 2450: 601d str r5, [r3, #0] + 2452: 2001 movs r0, #1 + 2454: bd38 pop {r3, r4, r5, pc} + 2456: b371 cbz r1, 24b6 + 2458: f240 3334 movw r3, #820 ; 0x334 + 245c: f2c1 0300 movt r3, #4096 ; 0x1000 + 2460: 885b ldrh r3, [r3, #2] + 2462: 0758 lsls r0, r3, #29 + 2464: d4c2 bmi.n 23ec + 2466: 2001 movs r0, #1 + 2468: 2104 movs r1, #4 + 246a: 462a mov r2, r5 + 246c: f7fe fc2a bl cc4 + 2470: e7db b.n 242a + 2472: 2900 cmp r1, #0 + 2474: d1ba bne.n 23ec + 2476: f44f 732b mov.w r3, #684 ; 0x2ac + 247a: f2c4 0300 movt r3, #16384 ; 0x4000 + 247e: 681a ldr r2, [r3, #0] + 2480: 2001 movs r0, #1 + 2482: f022 62c0 bic.w r2, r2, #100663296 ; 0x6000000 + 2486: 601a str r2, [r3, #0] + 2488: 681a ldr r2, [r3, #0] + 248a: f022 7280 bic.w r2, r2, #16777216 ; 0x1000000 + 248e: 601a str r2, [r3, #0] + 2490: bd38 pop {r3, r4, r5, pc} + 2492: 460a mov r2, r1 + 2494: 2002 movs r0, #2 + 2496: 2104 movs r1, #4 + 2498: f7fe fc14 bl cc4 + 249c: e7eb b.n 2476 + 249e: 460a mov r2, r1 + 24a0: 2003 movs r0, #3 + 24a2: 2140 movs r1, #64 ; 0x40 + 24a4: f7fe fc0e bl cc4 + 24a8: e7e5 b.n 2476 + 24aa: 460a mov r2, r1 + 24ac: 2007 movs r0, #7 + 24ae: 2104 movs r1, #4 + 24b0: f7fe fc08 bl cc4 + 24b4: e7df b.n 2476 + 24b6: 460a mov r2, r1 + 24b8: 2001 movs r0, #1 + 24ba: 2104 movs r1, #4 + 24bc: f7fe fc02 bl cc4 + 24c0: e7d9 b.n 2476 + 24c2: 2007 movs r0, #7 + 24c4: 2104 movs r1, #4 + 24c6: 462a mov r2, r5 + 24c8: f7fe fbfc bl cc4 + 24cc: e7ad b.n 242a + 24ce: bf00 nop + +000024d0 : + 24d0: b538 push {r3, r4, r5, lr} + 24d2: 4604 mov r4, r0 + 24d4: 460d mov r5, r1 + 24d6: 2803 cmp r0, #3 + 24d8: d84f bhi.n 257a + 24da: e8df f000 tbb [pc, r0] + 24de: 1c40 .short 0x1c40 + 24e0: 020d .short 0x020d + 24e2: 2900 cmp r1, #0 + 24e4: d065 beq.n 25b2 + 24e6: f240 3334 movw r3, #820 ; 0x334 + 24ea: f2c1 0300 movt r3, #4096 ; 0x1000 + 24ee: 89db ldrh r3, [r3, #14] + 24f0: 071b lsls r3, r3, #28 + 24f2: d56a bpl.n 25ca + 24f4: 2000 movs r0, #0 + 24f6: bd38 pop {r3, r4, r5, pc} + 24f8: 2900 cmp r1, #0 + 24fa: d054 beq.n 25a6 + 24fc: f240 3334 movw r3, #820 ; 0x334 + 2500: f2c1 0300 movt r3, #4096 ; 0x1000 + 2504: 88db ldrh r3, [r3, #6] + 2506: 061a lsls r2, r3, #24 + 2508: d4f4 bmi.n 24f4 + 250a: 2003 movs r0, #3 + 250c: 2180 movs r1, #128 ; 0x80 + 250e: 462a mov r2, r5 + 2510: f7fe fbd8 bl cc4 + 2514: e00d b.n 2532 + 2516: 2900 cmp r1, #0 + 2518: d03f beq.n 259a + 251a: f240 3334 movw r3, #820 ; 0x334 + 251e: f2c1 0300 movt r3, #4096 ; 0x1000 + 2522: 889b ldrh r3, [r3, #4] + 2524: 0719 lsls r1, r3, #28 + 2526: d4e5 bmi.n 24f4 + 2528: 2002 movs r0, #2 + 252a: 2108 movs r1, #8 + 252c: 462a mov r2, r5 + 252e: f7fe fbc9 bl cc4 + 2532: f44f 732b mov.w r3, #684 ; 0x2ac + 2536: f2c4 0300 movt r3, #16384 ; 0x4000 + 253a: 681a ldr r2, [r3, #0] + 253c: f004 0403 and.w r4, r4, #3 + 2540: f022 42c0 bic.w r2, r2, #1610612736 ; 0x60000000 + 2544: ea42 7444 orr.w r4, r2, r4, lsl #29 + 2548: 601c str r4, [r3, #0] + 254a: 681a ldr r2, [r3, #0] + 254c: 426d negs r5, r5 + 254e: f022 5280 bic.w r2, r2, #268435456 ; 0x10000000 + 2552: f005 5580 and.w r5, r5, #268435456 ; 0x10000000 + 2556: 4315 orrs r5, r2 + 2558: 601d str r5, [r3, #0] + 255a: 2001 movs r0, #1 + 255c: bd38 pop {r3, r4, r5, pc} + 255e: b371 cbz r1, 25be + 2560: f240 3334 movw r3, #820 ; 0x334 + 2564: f2c1 0300 movt r3, #4096 ; 0x1000 + 2568: 885b ldrh r3, [r3, #2] + 256a: 0718 lsls r0, r3, #28 + 256c: d4c2 bmi.n 24f4 + 256e: 2001 movs r0, #1 + 2570: 2108 movs r1, #8 + 2572: 462a mov r2, r5 + 2574: f7fe fba6 bl cc4 + 2578: e7db b.n 2532 + 257a: 2900 cmp r1, #0 + 257c: d1ba bne.n 24f4 + 257e: f44f 732b mov.w r3, #684 ; 0x2ac + 2582: f2c4 0300 movt r3, #16384 ; 0x4000 + 2586: 681a ldr r2, [r3, #0] + 2588: 2001 movs r0, #1 + 258a: f022 42c0 bic.w r2, r2, #1610612736 ; 0x60000000 + 258e: 601a str r2, [r3, #0] + 2590: 681a ldr r2, [r3, #0] + 2592: f022 5280 bic.w r2, r2, #268435456 ; 0x10000000 + 2596: 601a str r2, [r3, #0] + 2598: bd38 pop {r3, r4, r5, pc} + 259a: 460a mov r2, r1 + 259c: 2002 movs r0, #2 + 259e: 2108 movs r1, #8 + 25a0: f7fe fb90 bl cc4 + 25a4: e7eb b.n 257e + 25a6: 460a mov r2, r1 + 25a8: 2003 movs r0, #3 + 25aa: 2180 movs r1, #128 ; 0x80 + 25ac: f7fe fb8a bl cc4 + 25b0: e7e5 b.n 257e + 25b2: 460a mov r2, r1 + 25b4: 2007 movs r0, #7 + 25b6: 2108 movs r1, #8 + 25b8: f7fe fb84 bl cc4 + 25bc: e7df b.n 257e + 25be: 460a mov r2, r1 + 25c0: 2001 movs r0, #1 + 25c2: 2108 movs r1, #8 + 25c4: f7fe fb7e bl cc4 + 25c8: e7d9 b.n 257e + 25ca: 2007 movs r0, #7 + 25cc: 2108 movs r1, #8 + 25ce: 462a mov r2, r5 + 25d0: f7fe fb78 bl cc4 + 25d4: e7ad b.n 2532 + 25d6: bf00 nop + +000025d8 : + 25d8: b510 push {r4, lr} + 25da: 460c mov r4, r1 + 25dc: b389 cbz r1, 2642 + 25de: f240 3334 movw r3, #820 ; 0x334 + 25e2: f2c1 0300 movt r3, #4096 ; 0x1000 + 25e6: 891a ldrh r2, [r3, #8] + 25e8: 7918 ldrb r0, [r3, #4] + 25ea: f3c2 0209 ubfx r2, r2, #0, #10 + 25ee: 2800 cmp r0, #0 + 25f0: bf08 it eq + 25f2: 2a00 cmpeq r2, #0 + 25f4: 8858 ldrh r0, [r3, #2] + 25f6: bf0c ite eq + 25f8: 2201 moveq r2, #1 + 25fa: 2200 movne r2, #0 + 25fc: f080 0020 eor.w r0, r0, #32 + 2600: ea12 1050 ands.w r0, r2, r0, lsr #5 + 2604: d100 bne.n 2608 + 2606: bd10 pop {r4, pc} + 2608: 4622 mov r2, r4 + 260a: 2001 movs r0, #1 + 260c: 2120 movs r1, #32 + 260e: f7fe fb59 bl cc4 + 2612: 4622 mov r2, r4 + 2614: 2002 movs r0, #2 + 2616: 21ff movs r1, #255 ; 0xff + 2618: f7fe fb54 bl cc4 + 261c: 4622 mov r2, r4 + 261e: 2004 movs r0, #4 + 2620: f240 31ff movw r1, #1023 ; 0x3ff + 2624: f7fe fb4e bl cc4 + 2628: f44f 735d mov.w r3, #884 ; 0x374 + 262c: f2c4 0300 movt r3, #16384 ; 0x4000 + 2630: 681a ldr r2, [r3, #0] + 2632: f004 0401 and.w r4, r4, #1 + 2636: f022 0201 bic.w r2, r2, #1 + 263a: 4314 orrs r4, r2 + 263c: 601c str r4, [r3, #0] + 263e: 2001 movs r0, #1 + 2640: bd10 pop {r4, pc} + 2642: 4622 mov r2, r4 + 2644: 2001 movs r0, #1 + 2646: 2120 movs r1, #32 + 2648: f7fe fb3c bl cc4 + 264c: 4622 mov r2, r4 + 264e: 2002 movs r0, #2 + 2650: 21ff movs r1, #255 ; 0xff + 2652: f7fe fb37 bl cc4 + 2656: 4622 mov r2, r4 + 2658: 2004 movs r0, #4 + 265a: f240 31ff movw r1, #1023 ; 0x3ff + 265e: f7fe fb31 bl cc4 + 2662: f44f 735d mov.w r3, #884 ; 0x374 + 2666: f2c4 0300 movt r3, #16384 ; 0x4000 + 266a: 681a ldr r2, [r3, #0] + 266c: 2001 movs r0, #1 + 266e: f022 0201 bic.w r2, r2, #1 + 2672: 601a str r2, [r3, #0] + 2674: bd10 pop {r4, pc} + 2676: bf00 nop + +00002678 : + 2678: b538 push {r3, r4, r5, lr} + 267a: 4605 mov r5, r0 + 267c: 460c mov r4, r1 + 267e: b1e0 cbz r0, 26ba + 2680: 2801 cmp r0, #1 + 2682: d10a bne.n 269a + 2684: 2900 cmp r1, #0 + 2686: d046 beq.n 2716 + 2688: f240 3334 movw r3, #820 ; 0x334 + 268c: f2c1 0300 movt r3, #4096 ; 0x1000 + 2690: 889b ldrh r3, [r3, #4] + 2692: 071b lsls r3, r3, #28 + 2694: d033 beq.n 26fe + 2696: 2000 movs r0, #0 + 2698: bd38 pop {r3, r4, r5, pc} + 269a: 2900 cmp r1, #0 + 269c: d1fb bne.n 2696 + 269e: f44f 7330 mov.w r3, #704 ; 0x2c0 + 26a2: f2c4 0300 movt r3, #16384 ; 0x4000 + 26a6: 681a ldr r2, [r3, #0] + 26a8: 2001 movs r0, #1 + 26aa: f022 0206 bic.w r2, r2, #6 + 26ae: 601a str r2, [r3, #0] + 26b0: 681a ldr r2, [r3, #0] + 26b2: f022 0201 bic.w r2, r2, #1 + 26b6: 601a str r2, [r3, #0] + 26b8: bd38 pop {r3, r4, r5, pc} + 26ba: b331 cbz r1, 270a + 26bc: f240 3334 movw r3, #820 ; 0x334 + 26c0: f2c1 0300 movt r3, #4096 ; 0x1000 + 26c4: 895b ldrh r3, [r3, #10] + 26c6: 069a lsls r2, r3, #26 + 26c8: d1e5 bne.n 2696 + 26ca: 2005 movs r0, #5 + 26cc: 213f movs r1, #63 ; 0x3f + 26ce: 4622 mov r2, r4 + 26d0: f7fe faf8 bl cc4 + 26d4: f44f 7330 mov.w r3, #704 ; 0x2c0 + 26d8: f2c4 0300 movt r3, #16384 ; 0x4000 + 26dc: 681a ldr r2, [r3, #0] + 26de: f005 0503 and.w r5, r5, #3 + 26e2: f022 0206 bic.w r2, r2, #6 + 26e6: ea42 0545 orr.w r5, r2, r5, lsl #1 + 26ea: 601d str r5, [r3, #0] + 26ec: 681a ldr r2, [r3, #0] + 26ee: f004 0401 and.w r4, r4, #1 + 26f2: f022 0201 bic.w r2, r2, #1 + 26f6: 4314 orrs r4, r2 + 26f8: 601c str r4, [r3, #0] + 26fa: 2001 movs r0, #1 + 26fc: bd38 pop {r3, r4, r5, pc} + 26fe: 2002 movs r0, #2 + 2700: 210f movs r1, #15 + 2702: 4622 mov r2, r4 + 2704: f7fe fade bl cc4 + 2708: e7e4 b.n 26d4 + 270a: 460a mov r2, r1 + 270c: 2005 movs r0, #5 + 270e: 213f movs r1, #63 ; 0x3f + 2710: f7fe fad8 bl cc4 + 2714: e7c3 b.n 269e + 2716: 460a mov r2, r1 + 2718: 2002 movs r0, #2 + 271a: 210f movs r1, #15 + 271c: f7fe fad2 bl cc4 + 2720: e7bd b.n 269e + 2722: bf00 nop + +00002724 : + 2724: b510 push {r4, lr} + 2726: 460c mov r4, r1 + 2728: 2900 cmp r1, #0 + 272a: d04b beq.n 27c4 + 272c: f240 3334 movw r3, #820 ; 0x334 + 2730: f2c1 0300 movt r3, #4096 ; 0x1000 + 2734: 8a59 ldrh r1, [r3, #18] + 2736: 8a9a ldrh r2, [r3, #20] + 2738: f011 0f7f tst.w r1, #127 ; 0x7f + 273c: bf0c ite eq + 273e: 2001 moveq r0, #1 + 2740: 2000 movne r0, #0 + 2742: 7c19 ldrb r1, [r3, #16] + 2744: f012 0f7f tst.w r2, #127 ; 0x7f + 2748: f000 0001 and.w r0, r0, #1 + 274c: bf18 it ne + 274e: 2000 movne r0, #0 + 2750: 2900 cmp r1, #0 + 2752: bf14 ite ne + 2754: 2000 movne r0, #0 + 2756: f000 0001 andeq.w r0, r0, #1 + 275a: 7b9a ldrb r2, [r3, #14] + 275c: 7b1b ldrb r3, [r3, #12] + 275e: 2a00 cmp r2, #0 + 2760: bf14 ite ne + 2762: 2000 movne r0, #0 + 2764: f000 0001 andeq.w r0, r0, #1 + 2768: 2b00 cmp r3, #0 + 276a: bf14 ite ne + 276c: 2000 movne r0, #0 + 276e: f000 0001 andeq.w r0, r0, #1 + 2772: b900 cbnz r0, 2776 + 2774: bd10 pop {r4, pc} + 2776: 4622 mov r2, r4 + 2778: 2006 movs r0, #6 + 277a: 21ff movs r1, #255 ; 0xff + 277c: f7fe faa2 bl cc4 + 2780: 4622 mov r2, r4 + 2782: 2007 movs r0, #7 + 2784: 21ff movs r1, #255 ; 0xff + 2786: f7fe fa9d bl cc4 + 278a: 4622 mov r2, r4 + 278c: 2008 movs r0, #8 + 278e: 21ff movs r1, #255 ; 0xff + 2790: f7fe fa98 bl cc4 + 2794: 4622 mov r2, r4 + 2796: 2009 movs r0, #9 + 2798: 217f movs r1, #127 ; 0x7f + 279a: f7fe fa93 bl cc4 + 279e: 4622 mov r2, r4 + 27a0: 200a movs r0, #10 + 27a2: 217f movs r1, #127 ; 0x7f + 27a4: f7fe fa8e bl cc4 + 27a8: f44f 7330 mov.w r3, #704 ; 0x2c0 + 27ac: f2c4 0300 movt r3, #16384 ; 0x4000 + 27b0: 681a ldr r2, [r3, #0] + 27b2: 4264 negs r4, r4 + 27b4: f022 0210 bic.w r2, r2, #16 + 27b8: f004 0410 and.w r4, r4, #16 + 27bc: 4314 orrs r4, r2 + 27be: 601c str r4, [r3, #0] + 27c0: 2001 movs r0, #1 + 27c2: bd10 pop {r4, pc} + 27c4: 4622 mov r2, r4 + 27c6: 2006 movs r0, #6 + 27c8: 21ff movs r1, #255 ; 0xff + 27ca: f7fe fa7b bl cc4 + 27ce: 4622 mov r2, r4 + 27d0: 2007 movs r0, #7 + 27d2: 21ff movs r1, #255 ; 0xff + 27d4: f7fe fa76 bl cc4 + 27d8: 4622 mov r2, r4 + 27da: 2008 movs r0, #8 + 27dc: 21ff movs r1, #255 ; 0xff + 27de: f7fe fa71 bl cc4 + 27e2: 4622 mov r2, r4 + 27e4: 2009 movs r0, #9 + 27e6: 217f movs r1, #127 ; 0x7f + 27e8: f7fe fa6c bl cc4 + 27ec: 4622 mov r2, r4 + 27ee: 200a movs r0, #10 + 27f0: 217f movs r1, #127 ; 0x7f + 27f2: f7fe fa67 bl cc4 + 27f6: f44f 7330 mov.w r3, #704 ; 0x2c0 + 27fa: f2c4 0300 movt r3, #16384 ; 0x4000 + 27fe: 681a ldr r2, [r3, #0] + 2800: 2001 movs r0, #1 + 2802: f022 0210 bic.w r2, r2, #16 + 2806: 601a str r2, [r3, #0] + 2808: bd10 pop {r4, pc} + 280a: bf00 nop + +0000280c : + 280c: b508 push {r3, lr} + 280e: b1b9 cbz r1, 2840 + 2810: f240 3334 movw r3, #820 ; 0x334 + 2814: f2c1 0300 movt r3, #4096 ; 0x1000 + 2818: 891b ldrh r3, [r3, #8] + 281a: 06db lsls r3, r3, #27 + 281c: d001 beq.n 2822 + 281e: 2000 movs r0, #0 + 2820: bd08 pop {r3, pc} + 2822: 460a mov r2, r1 + 2824: 2004 movs r0, #4 + 2826: 211f movs r1, #31 + 2828: f7fe fa4c bl cc4 + 282c: f44f 7330 mov.w r3, #704 ; 0x2c0 + 2830: f2c4 0300 movt r3, #16384 ; 0x4000 + 2834: 681a ldr r2, [r3, #0] + 2836: 2001 movs r0, #1 + 2838: f442 3280 orr.w r2, r2, #65536 ; 0x10000 + 283c: 601a str r2, [r3, #0] + 283e: bd08 pop {r3, pc} + 2840: 460a mov r2, r1 + 2842: 2004 movs r0, #4 + 2844: 211f movs r1, #31 + 2846: f7fe fa3d bl cc4 + 284a: f44f 7330 mov.w r3, #704 ; 0x2c0 + 284e: f2c4 0300 movt r3, #16384 ; 0x4000 + 2852: 681a ldr r2, [r3, #0] + 2854: 2001 movs r0, #1 + 2856: f422 3280 bic.w r2, r2, #65536 ; 0x10000 + 285a: 601a str r2, [r3, #0] + 285c: bd08 pop {r3, pc} + 285e: bf00 nop + +00002860 : + 2860: b508 push {r3, lr} + 2862: b1c9 cbz r1, 2898 + 2864: f240 3334 movw r3, #820 ; 0x334 + 2868: f2c1 0300 movt r3, #4096 ; 0x1000 + 286c: 891b ldrh r3, [r3, #8] + 286e: f403 7378 and.w r3, r3, #992 ; 0x3e0 + 2872: b10b cbz r3, 2878 + 2874: 2000 movs r0, #0 + 2876: bd08 pop {r3, pc} + 2878: 460a mov r2, r1 + 287a: 2004 movs r0, #4 + 287c: f44f 7178 mov.w r1, #992 ; 0x3e0 + 2880: f7fe fa20 bl cc4 + 2884: f44f 7330 mov.w r3, #704 ; 0x2c0 + 2888: f2c4 0300 movt r3, #16384 ; 0x4000 + 288c: 681a ldr r2, [r3, #0] + 288e: 2001 movs r0, #1 + 2890: f442 3200 orr.w r2, r2, #131072 ; 0x20000 + 2894: 601a str r2, [r3, #0] + 2896: bd08 pop {r3, pc} + 2898: 460a mov r2, r1 + 289a: 2004 movs r0, #4 + 289c: f44f 7178 mov.w r1, #992 ; 0x3e0 + 28a0: f7fe fa10 bl cc4 + 28a4: f44f 7330 mov.w r3, #704 ; 0x2c0 + 28a8: f2c4 0300 movt r3, #16384 ; 0x4000 + 28ac: 681a ldr r2, [r3, #0] + 28ae: 2001 movs r0, #1 + 28b0: f422 3200 bic.w r2, r2, #131072 ; 0x20000 + 28b4: 601a str r2, [r3, #0] + 28b6: bd08 pop {r3, pc} + +000028b8 : + 28b8: b508 push {r3, lr} + 28ba: b1d9 cbz r1, 28f4 + 28bc: f240 3334 movw r3, #820 ; 0x334 + 28c0: f2c1 0300 movt r3, #4096 ; 0x1000 + 28c4: 885b ldrh r3, [r3, #2] + 28c6: 079b lsls r3, r3, #30 + 28c8: d001 beq.n 28ce + 28ca: 2000 movs r0, #0 + 28cc: bd08 pop {r3, pc} + 28ce: 460a mov r2, r1 + 28d0: 2001 movs r0, #1 + 28d2: 2103 movs r1, #3 + 28d4: f7fe f9f6 bl cc4 + 28d8: f44f 7330 mov.w r3, #704 ; 0x2c0 + 28dc: f2c4 0300 movt r3, #16384 ; 0x4000 + 28e0: 681a ldr r2, [r3, #0] + 28e2: 2001 movs r0, #1 + 28e4: f422 1200 bic.w r2, r2, #2097152 ; 0x200000 + 28e8: 601a str r2, [r3, #0] + 28ea: 681a ldr r2, [r3, #0] + 28ec: f442 1280 orr.w r2, r2, #1048576 ; 0x100000 + 28f0: 601a str r2, [r3, #0] + 28f2: bd08 pop {r3, pc} + 28f4: 460a mov r2, r1 + 28f6: 2001 movs r0, #1 + 28f8: 2103 movs r1, #3 + 28fa: f7fe f9e3 bl cc4 + 28fe: f44f 7330 mov.w r3, #704 ; 0x2c0 + 2902: f2c4 0300 movt r3, #16384 ; 0x4000 + 2906: 681a ldr r2, [r3, #0] + 2908: 2001 movs r0, #1 + 290a: f422 1200 bic.w r2, r2, #2097152 ; 0x200000 + 290e: 601a str r2, [r3, #0] + 2910: 681a ldr r2, [r3, #0] + 2912: f422 1280 bic.w r2, r2, #1048576 ; 0x100000 + 2916: 601a str r2, [r3, #0] + 2918: bd08 pop {r3, pc} + 291a: bf00 nop + +0000291c : + 291c: b508 push {r3, lr} + 291e: b1d9 cbz r1, 2958 + 2920: f240 3334 movw r3, #820 ; 0x334 + 2924: f2c1 0300 movt r3, #4096 ; 0x1000 + 2928: 885b ldrh r3, [r3, #2] + 292a: 079b lsls r3, r3, #30 + 292c: d001 beq.n 2932 + 292e: 2000 movs r0, #0 + 2930: bd08 pop {r3, pc} + 2932: 460a mov r2, r1 + 2934: 2001 movs r0, #1 + 2936: 2103 movs r1, #3 + 2938: f7fe f9c4 bl cc4 + 293c: f44f 7330 mov.w r3, #704 ; 0x2c0 + 2940: f2c4 0300 movt r3, #16384 ; 0x4000 + 2944: 681a ldr r2, [r3, #0] + 2946: 2001 movs r0, #1 + 2948: f442 1280 orr.w r2, r2, #1048576 ; 0x100000 + 294c: 601a str r2, [r3, #0] + 294e: 681a ldr r2, [r3, #0] + 2950: f442 1200 orr.w r2, r2, #2097152 ; 0x200000 + 2954: 601a str r2, [r3, #0] + 2956: bd08 pop {r3, pc} + 2958: 460a mov r2, r1 + 295a: 2001 movs r0, #1 + 295c: 2103 movs r1, #3 + 295e: f7fe f9b1 bl cc4 + 2962: f44f 7330 mov.w r3, #704 ; 0x2c0 + 2966: f2c4 0300 movt r3, #16384 ; 0x4000 + 296a: 681a ldr r2, [r3, #0] + 296c: 2001 movs r0, #1 + 296e: f422 1280 bic.w r2, r2, #1048576 ; 0x100000 + 2972: 601a str r2, [r3, #0] + 2974: 681a ldr r2, [r3, #0] + 2976: f422 1200 bic.w r2, r2, #2097152 ; 0x200000 + 297a: 601a str r2, [r3, #0] + 297c: bd08 pop {r3, pc} + 297e: bf00 nop + +00002980 : + 2980: b510 push {r4, lr} + 2982: 460c mov r4, r1 + 2984: b1d1 cbz r1, 29bc + 2986: f240 3334 movw r3, #820 ; 0x334 + 298a: f2c1 0300 movt r3, #4096 ; 0x1000 + 298e: 889b ldrh r3, [r3, #4] + 2990: f003 0330 and.w r3, r3, #48 ; 0x30 + 2994: b10b cbz r3, 299a + 2996: 2000 movs r0, #0 + 2998: bd10 pop {r4, pc} + 299a: 4622 mov r2, r4 + 299c: 2002 movs r0, #2 + 299e: 2130 movs r1, #48 ; 0x30 + 29a0: f7fe f990 bl cc4 + 29a4: 23a4 movs r3, #164 ; 0xa4 + 29a6: f2c4 0300 movt r3, #16384 ; 0x4000 + 29aa: 681a ldr r2, [r3, #0] + 29ac: f004 0401 and.w r4, r4, #1 + 29b0: f022 0201 bic.w r2, r2, #1 + 29b4: 4314 orrs r4, r2 + 29b6: 601c str r4, [r3, #0] + 29b8: 2001 movs r0, #1 + 29ba: bd10 pop {r4, pc} + 29bc: 460a mov r2, r1 + 29be: 2002 movs r0, #2 + 29c0: 2130 movs r1, #48 ; 0x30 + 29c2: f7fe f97f bl cc4 + 29c6: 23a4 movs r3, #164 ; 0xa4 + 29c8: f2c4 0300 movt r3, #16384 ; 0x4000 + 29cc: 681a ldr r2, [r3, #0] + 29ce: 2001 movs r0, #1 + 29d0: f022 0201 bic.w r2, r2, #1 + 29d4: 601a str r2, [r3, #0] + 29d6: bd10 pop {r4, pc} + +000029d8 : + 29d8: b510 push {r4, lr} + 29da: 460c mov r4, r1 + 29dc: b1d1 cbz r1, 2a14 + 29de: f240 3334 movw r3, #820 ; 0x334 + 29e2: f2c1 0300 movt r3, #4096 ; 0x1000 + 29e6: 889b ldrh r3, [r3, #4] + 29e8: 071b lsls r3, r3, #28 + 29ea: d001 beq.n 29f0 + 29ec: 2000 movs r0, #0 + 29ee: bd10 pop {r4, pc} + 29f0: 4622 mov r2, r4 + 29f2: 2002 movs r0, #2 + 29f4: 210f movs r1, #15 + 29f6: f7fe f965 bl cc4 + 29fa: 23a4 movs r3, #164 ; 0xa4 + 29fc: f2c4 0300 movt r3, #16384 ; 0x4000 + 2a00: 681a ldr r2, [r3, #0] + 2a02: 4264 negs r4, r4 + 2a04: f022 0210 bic.w r2, r2, #16 + 2a08: f004 0410 and.w r4, r4, #16 + 2a0c: 4314 orrs r4, r2 + 2a0e: 601c str r4, [r3, #0] + 2a10: 2001 movs r0, #1 + 2a12: bd10 pop {r4, pc} + 2a14: 460a mov r2, r1 + 2a16: 2002 movs r0, #2 + 2a18: 210f movs r1, #15 + 2a1a: f7fe f953 bl cc4 + 2a1e: 23a4 movs r3, #164 ; 0xa4 + 2a20: f2c4 0300 movt r3, #16384 ; 0x4000 + 2a24: 681a ldr r2, [r3, #0] + 2a26: 2001 movs r0, #1 + 2a28: f022 0210 bic.w r2, r2, #16 + 2a2c: 601a str r2, [r3, #0] + 2a2e: bd10 pop {r4, pc} + +00002a30 : + 2a30: b510 push {r4, lr} + 2a32: 460c mov r4, r1 + 2a34: 2900 cmp r1, #0 + 2a36: d058 beq.n 2aea + 2a38: f240 3334 movw r3, #820 ; 0x334 + 2a3c: f2c1 0300 movt r3, #4096 ; 0x1000 + 2a40: 891a ldrh r2, [r3, #8] + 2a42: 8959 ldrh r1, [r3, #10] + 2a44: f012 0f3f tst.w r2, #63 ; 0x3f + 2a48: bf0c ite eq + 2a4a: 2201 moveq r2, #1 + 2a4c: 2200 movne r2, #0 + 2a4e: f001 0130 and.w r1, r1, #48 ; 0x30 + 2a52: 2900 cmp r1, #0 + 2a54: bf14 ite ne + 2a56: 2100 movne r1, #0 + 2a58: f002 0101 andeq.w r1, r2, #1 + 2a5c: 88d8 ldrh r0, [r3, #6] + 2a5e: 791a ldrb r2, [r3, #4] + 2a60: f000 0030 and.w r0, r0, #48 ; 0x30 + 2a64: 2800 cmp r0, #0 + 2a66: bf14 ite ne + 2a68: 2000 movne r0, #0 + 2a6a: f001 0001 andeq.w r0, r1, #1 + 2a6e: 2a00 cmp r2, #0 + 2a70: bf14 ite ne + 2a72: 2000 movne r0, #0 + 2a74: f000 0001 andeq.w r0, r0, #1 + 2a78: 885a ldrh r2, [r3, #2] + 2a7a: 781b ldrb r3, [r3, #0] + 2a7c: f012 0f3f tst.w r2, #63 ; 0x3f + 2a80: f000 0001 and.w r0, r0, #1 + 2a84: bf18 it ne + 2a86: 2000 movne r0, #0 + 2a88: 2b00 cmp r3, #0 + 2a8a: bf14 ite ne + 2a8c: 2000 movne r0, #0 + 2a8e: f000 0001 andeq.w r0, r0, #1 + 2a92: b900 cbnz r0, 2a96 + 2a94: bd10 pop {r4, pc} + 2a96: 4622 mov r2, r4 + 2a98: 2000 movs r0, #0 + 2a9a: 21ff movs r1, #255 ; 0xff + 2a9c: f7fe f912 bl cc4 + 2aa0: 4622 mov r2, r4 + 2aa2: 2001 movs r0, #1 + 2aa4: 213f movs r1, #63 ; 0x3f + 2aa6: f7fe f90d bl cc4 + 2aaa: 4622 mov r2, r4 + 2aac: 2002 movs r0, #2 + 2aae: 21ff movs r1, #255 ; 0xff + 2ab0: f7fe f908 bl cc4 + 2ab4: 4622 mov r2, r4 + 2ab6: 2003 movs r0, #3 + 2ab8: 2130 movs r1, #48 ; 0x30 + 2aba: f7fe f903 bl cc4 + 2abe: 4622 mov r2, r4 + 2ac0: 2004 movs r0, #4 + 2ac2: 213f movs r1, #63 ; 0x3f + 2ac4: f7fe f8fe bl cc4 + 2ac8: 4622 mov r2, r4 + 2aca: 2005 movs r0, #5 + 2acc: 2130 movs r1, #48 ; 0x30 + 2ace: f7fe f8f9 bl cc4 + 2ad2: 23a0 movs r3, #160 ; 0xa0 + 2ad4: f2c4 0300 movt r3, #16384 ; 0x4000 + 2ad8: 681a ldr r2, [r3, #0] + 2ada: f004 0401 and.w r4, r4, #1 + 2ade: f022 0201 bic.w r2, r2, #1 + 2ae2: 4314 orrs r4, r2 + 2ae4: 601c str r4, [r3, #0] + 2ae6: 2001 movs r0, #1 + 2ae8: bd10 pop {r4, pc} + 2aea: 4608 mov r0, r1 + 2aec: 4622 mov r2, r4 + 2aee: 21ff movs r1, #255 ; 0xff + 2af0: f7fe f8e8 bl cc4 + 2af4: 4622 mov r2, r4 + 2af6: 2001 movs r0, #1 + 2af8: 213f movs r1, #63 ; 0x3f + 2afa: f7fe f8e3 bl cc4 + 2afe: 4622 mov r2, r4 + 2b00: 2002 movs r0, #2 + 2b02: 21ff movs r1, #255 ; 0xff + 2b04: f7fe f8de bl cc4 + 2b08: 4622 mov r2, r4 + 2b0a: 2003 movs r0, #3 + 2b0c: 2130 movs r1, #48 ; 0x30 + 2b0e: f7fe f8d9 bl cc4 + 2b12: 4622 mov r2, r4 + 2b14: 2004 movs r0, #4 + 2b16: 213f movs r1, #63 ; 0x3f + 2b18: f7fe f8d4 bl cc4 + 2b1c: 4622 mov r2, r4 + 2b1e: 2005 movs r0, #5 + 2b20: 2130 movs r1, #48 ; 0x30 + 2b22: f7fe f8cf bl cc4 + 2b26: 23a0 movs r3, #160 ; 0xa0 + 2b28: f2c4 0300 movt r3, #16384 ; 0x4000 + 2b2c: 681a ldr r2, [r3, #0] + 2b2e: 2001 movs r0, #1 + 2b30: f022 0201 bic.w r2, r2, #1 + 2b34: 601a str r2, [r3, #0] + 2b36: bd10 pop {r4, pc} + +00002b38 : + 2b38: 28e2 cmp r0, #226 ; 0xe2 + 2b3a: f200 818d bhi.w 2e58 + 2b3e: e8df f010 tbh [pc, r0, lsl #1] + 2b42: 0187 .short 0x0187 + 2b44: 017f0183 .word 0x017f0183 + 2b48: 018b018b .word 0x018b018b + 2b4c: 018b018b .word 0x018b018b + 2b50: 017b018b .word 0x017b018b + 2b54: 01730177 .word 0x01730177 + 2b58: 018b018b .word 0x018b018b + 2b5c: 018b018b .word 0x018b018b + 2b60: 016b016f .word 0x016b016f + 2b64: 01630167 .word 0x01630167 + 2b68: 018b015f .word 0x018b015f + 2b6c: 018b018b .word 0x018b018b + 2b70: 015b018b .word 0x015b018b + 2b74: 018b0157 .word 0x018b0157 + 2b78: 0153018b .word 0x0153018b + 2b7c: 018b014f .word 0x018b014f + 2b80: 018b018b .word 0x018b018b + 2b84: 018b018b .word 0x018b018b + 2b88: 018b018b .word 0x018b018b + 2b8c: 018b018b .word 0x018b018b + 2b90: 018b018b .word 0x018b018b + 2b94: 018b018b .word 0x018b018b + 2b98: 018b018b .word 0x018b018b + 2b9c: 018b018b .word 0x018b018b + 2ba0: 018b018b .word 0x018b018b + 2ba4: 018b018b .word 0x018b018b + 2ba8: 018b018b .word 0x018b018b + 2bac: 018b018b .word 0x018b018b + 2bb0: 018b018b .word 0x018b018b + 2bb4: 018b018b .word 0x018b018b + 2bb8: 018b018b .word 0x018b018b + 2bbc: 018b018b .word 0x018b018b + 2bc0: 014b018b .word 0x014b018b + 2bc4: 018b0147 .word 0x018b0147 + 2bc8: 018b018b .word 0x018b018b + 2bcc: 018b018b .word 0x018b018b + 2bd0: 018b018b .word 0x018b018b + 2bd4: 018b018b .word 0x018b018b + 2bd8: 018b018b .word 0x018b018b + 2bdc: 018b018b .word 0x018b018b + 2be0: 018b018b .word 0x018b018b + 2be4: 018b018b .word 0x018b018b + 2be8: 018b018b .word 0x018b018b + 2bec: 018b018b .word 0x018b018b + 2bf0: 0143018b .word 0x0143018b + 2bf4: 018b018b .word 0x018b018b + 2bf8: 018b018b .word 0x018b018b + 2bfc: 018b018b .word 0x018b018b + 2c00: 013f018b .word 0x013f018b + 2c04: 018b018b .word 0x018b018b + 2c08: 018b018b .word 0x018b018b + 2c0c: 018b018b .word 0x018b018b + 2c10: 013b018b .word 0x013b018b + 2c14: 018b0137 .word 0x018b0137 + 2c18: 0133018b .word 0x0133018b + 2c1c: 018b012f .word 0x018b012f + 2c20: 012b018b .word 0x012b018b + 2c24: 018b018b .word 0x018b018b + 2c28: 018b018b .word 0x018b018b + 2c2c: 018b018b .word 0x018b018b + 2c30: 018b018b .word 0x018b018b + 2c34: 018b018b .word 0x018b018b + 2c38: 018b018b .word 0x018b018b + 2c3c: 018b018b .word 0x018b018b + 2c40: 018b018b .word 0x018b018b + 2c44: 018b018b .word 0x018b018b + 2c48: 018b018b .word 0x018b018b + 2c4c: 018b018b .word 0x018b018b + 2c50: 018b018b .word 0x018b018b + 2c54: 018b018b .word 0x018b018b + 2c58: 018b018b .word 0x018b018b + 2c5c: 018b018b .word 0x018b018b + 2c60: 018b018b .word 0x018b018b + 2c64: 018b018b .word 0x018b018b + 2c68: 018b018b .word 0x018b018b + 2c6c: 018b018b .word 0x018b018b + 2c70: 018b018b .word 0x018b018b + 2c74: 018b018b .word 0x018b018b + 2c78: 018b018b .word 0x018b018b + 2c7c: 018b018b .word 0x018b018b + 2c80: 0127018b .word 0x0127018b + 2c84: 011f0123 .word 0x011f0123 + 2c88: 0117011b .word 0x0117011b + 2c8c: 010f0113 .word 0x010f0113 + 2c90: 0107010b .word 0x0107010b + 2c94: 018b018b .word 0x018b018b + 2c98: 018b018b .word 0x018b018b + 2c9c: 018b018b .word 0x018b018b + 2ca0: 018b018b .word 0x018b018b + 2ca4: 018b018b .word 0x018b018b + 2ca8: 018b018b .word 0x018b018b + 2cac: 018b018b .word 0x018b018b + 2cb0: 018b018b .word 0x018b018b + 2cb4: 018b018b .word 0x018b018b + 2cb8: 018b018b .word 0x018b018b + 2cbc: 018b018b .word 0x018b018b + 2cc0: 018b018b .word 0x018b018b + 2cc4: 018b018b .word 0x018b018b + 2cc8: 0103018b .word 0x0103018b + 2ccc: 018b018b .word 0x018b018b + 2cd0: 00ff018b .word 0x00ff018b + 2cd4: 018b018b .word 0x018b018b + 2cd8: 018b018b .word 0x018b018b + 2cdc: 018b018b .word 0x018b018b + 2ce0: 018b018b .word 0x018b018b + 2ce4: 018b018b .word 0x018b018b + 2ce8: 018b018b .word 0x018b018b + 2cec: 018b018b .word 0x018b018b + 2cf0: 00fb018b .word 0x00fb018b + 2cf4: 018b00f7 .word 0x018b00f7 + 2cf8: 00f3018b .word 0x00f3018b + 2cfc: 018b00ef .word 0x018b00ef + 2d00: 00eb018b .word 0x00eb018b + 2d04: 00e300e7 .word 0x00e300e7 + 2d08: 4608 mov r0, r1 + 2d0a: 4611 mov r1, r2 + 2d0c: f7ff be90 b.w 2a30 + 2d10: 4608 mov r0, r1 + 2d12: 4611 mov r1, r2 + 2d14: f7ff be60 b.w 29d8 + 2d18: 4608 mov r0, r1 + 2d1a: 4611 mov r1, r2 + 2d1c: f7ff be30 b.w 2980 + 2d20: 4608 mov r0, r1 + 2d22: 4611 mov r1, r2 + 2d24: f7ff bdfa b.w 291c + 2d28: 4608 mov r0, r1 + 2d2a: 4611 mov r1, r2 + 2d2c: f7ff bdc4 b.w 28b8 + 2d30: 4608 mov r0, r1 + 2d32: 4611 mov r1, r2 + 2d34: f7ff bd94 b.w 2860 + 2d38: 4608 mov r0, r1 + 2d3a: 4611 mov r1, r2 + 2d3c: f7ff bd66 b.w 280c + 2d40: 4608 mov r0, r1 + 2d42: 4611 mov r1, r2 + 2d44: f7ff bcee b.w 2724 + 2d48: 4608 mov r0, r1 + 2d4a: 4611 mov r1, r2 + 2d4c: f7ff bc94 b.w 2678 + 2d50: 4608 mov r0, r1 + 2d52: 4611 mov r1, r2 + 2d54: f7ff bc40 b.w 25d8 + 2d58: 4608 mov r0, r1 + 2d5a: 4611 mov r1, r2 + 2d5c: f7ff bbb8 b.w 24d0 + 2d60: 4608 mov r0, r1 + 2d62: 4611 mov r1, r2 + 2d64: f7ff bb30 b.w 23c8 + 2d68: 4608 mov r0, r1 + 2d6a: 4611 mov r1, r2 + 2d6c: f7ff baa8 b.w 22c0 + 2d70: 4608 mov r0, r1 + 2d72: 4611 mov r1, r2 + 2d74: f7ff ba20 b.w 21b8 + 2d78: 4608 mov r0, r1 + 2d7a: 4611 mov r1, r2 + 2d7c: f7ff b998 b.w 20b0 + 2d80: 4608 mov r0, r1 + 2d82: 4611 mov r1, r2 + 2d84: f7ff b916 b.w 1fb4 + 2d88: 4608 mov r0, r1 + 2d8a: 4611 mov r1, r2 + 2d8c: f7ff b88e b.w 1eac + 2d90: 4608 mov r0, r1 + 2d92: 4611 mov r1, r2 + 2d94: f7ff b808 b.w 1da8 + 2d98: 4608 mov r0, r1 + 2d9a: 4611 mov r1, r2 + 2d9c: f7fe bfdc b.w 1d58 + 2da0: 4608 mov r0, r1 + 2da2: 4611 mov r1, r2 + 2da4: f7fe bfae b.w 1d04 + 2da8: 4608 mov r0, r1 + 2daa: 4611 mov r1, r2 + 2dac: f7fe bf82 b.w 1cb4 + 2db0: 4608 mov r0, r1 + 2db2: 4611 mov r1, r2 + 2db4: f7fe bf54 b.w 1c60 + 2db8: 4608 mov r0, r1 + 2dba: 4611 mov r1, r2 + 2dbc: f7fe bf26 b.w 1c0c + 2dc0: 4608 mov r0, r1 + 2dc2: 4611 mov r1, r2 + 2dc4: f7fe bec4 b.w 1b50 + 2dc8: 4608 mov r0, r1 + 2dca: 4611 mov r1, r2 + 2dcc: f7fe be74 b.w 1ab8 + 2dd0: 4608 mov r0, r1 + 2dd2: 4611 mov r1, r2 + 2dd4: f7fe be4a b.w 1a6c + 2dd8: 4608 mov r0, r1 + 2dda: 4611 mov r1, r2 + 2ddc: f7fe be1e b.w 1a1c + 2de0: 4608 mov r0, r1 + 2de2: 4611 mov r1, r2 + 2de4: f7fe bdb0 b.w 1948 + 2de8: 4608 mov r0, r1 + 2dea: 4611 mov r1, r2 + 2dec: f7fe bd2a b.w 1844 + 2df0: 4608 mov r0, r1 + 2df2: 4611 mov r1, r2 + 2df4: f7fe bcba b.w 176c + 2df8: 4608 mov r0, r1 + 2dfa: 4611 mov r1, r2 + 2dfc: f7fe bc1c b.w 1638 + 2e00: 4608 mov r0, r1 + 2e02: 4611 mov r1, r2 + 2e04: f7fe bb90 b.w 1528 + 2e08: 4608 mov r0, r1 + 2e0a: 4611 mov r1, r2 + 2e0c: f7fe bb24 b.w 1458 + 2e10: 4608 mov r0, r1 + 2e12: 4611 mov r1, r2 + 2e14: f7fe bab4 b.w 1380 + 2e18: 4608 mov r0, r1 + 2e1a: 4611 mov r1, r2 + 2e1c: f7fe ba2a b.w 1274 + 2e20: 4608 mov r0, r1 + 2e22: 4611 mov r1, r2 + 2e24: f7fe b9c6 b.w 11b4 + 2e28: 4608 mov r0, r1 + 2e2a: 4611 mov r1, r2 + 2e2c: f7fe b95a b.w 10e4 + 2e30: 4608 mov r0, r1 + 2e32: 4611 mov r1, r2 + 2e34: f7fe b8ee b.w 1014 + 2e38: 4608 mov r0, r1 + 2e3a: 4611 mov r1, r2 + 2e3c: f7fe b89a b.w f74 + 2e40: 4608 mov r0, r1 + 2e42: 4611 mov r1, r2 + 2e44: f7fe b82a b.w e9c + 2e48: 4608 mov r0, r1 + 2e4a: 4611 mov r1, r2 + 2e4c: f7fd bfbc b.w dc8 + 2e50: 4608 mov r0, r1 + 2e52: 4611 mov r1, r2 + 2e54: f7fd bf52 b.w cfc + 2e58: 2000 movs r0, #0 + 2e5a: 4770 bx lr + +00002e5c : + 2e5c: f246 0308 movw r3, #24584 ; 0x6008 + 2e60: b470 push {r4, r5, r6} + 2e62: f246 0460 movw r4, #24672 ; 0x6060 + 2e66: f246 0228 movw r2, #24616 ; 0x6028 + 2e6a: f2c4 0300 movt r3, #16384 ; 0x4000 + 2e6e: f44f 41c0 mov.w r1, #24576 ; 0x6000 + 2e72: f2c4 0100 movt r1, #16384 ; 0x4000 + 2e76: f2c4 0400 movt r4, #16384 ; 0x4000 + 2e7a: f2c4 0200 movt r2, #16384 ; 0x4000 + 2e7e: 2500 movs r5, #0 + 2e80: 601d str r5, [r3, #0] + 2e82: 680e ldr r6, [r1, #0] + 2e84: 2501 movs r5, #1 + 2e86: f426 2670 bic.w r6, r6, #983040 ; 0xf0000 + 2e8a: f426 7640 bic.w r6, r6, #768 ; 0x300 + 2e8e: f446 7640 orr.w r6, r6, #768 ; 0x300 + 2e92: 600e str r6, [r1, #0] + 2e94: 7020 strb r0, [r4, #0] + 2e96: 601d str r5, [r3, #0] + 2e98: 6813 ldr r3, [r2, #0] + 2e9a: 07db lsls r3, r3, #31 + 2e9c: d4fc bmi.n 2e98 + 2e9e: bc70 pop {r4, r5, r6} + 2ea0: 4770 bx lr + 2ea2: bf00 nop + +00002ea4 : + 2ea4: f246 0228 movw r2, #24616 ; 0x6028 + 2ea8: f2c4 0200 movt r2, #16384 ; 0x4000 + 2eac: 6813 ldr r3, [r2, #0] + 2eae: 07db lsls r3, r3, #31 + 2eb0: d4fc bmi.n 2eac + 2eb2: 4770 bx lr + +00002eb4 : + 2eb4: b5f0 push {r4, r5, r6, r7, lr} + 2eb6: f246 0308 movw r3, #24584 ; 0x6008 + 2eba: f246 0e04 movw lr, #24580 ; 0x6004 + 2ebe: f246 141c movw r4, #24860 ; 0x611c + 2ec2: f246 0660 movw r6, #24672 ; 0x6060 + 2ec6: f246 0228 movw r2, #24616 ; 0x6028 + 2eca: f2c4 0300 movt r3, #16384 ; 0x4000 + 2ece: f2c4 0e00 movt lr, #16384 ; 0x4000 + 2ed2: f2c4 0400 movt r4, #16384 ; 0x4000 + 2ed6: f44f 41c0 mov.w r1, #24576 ; 0x6000 + 2eda: f2c4 0100 movt r1, #16384 ; 0x4000 + 2ede: f2c4 0600 movt r6, #16384 ; 0x4000 + 2ee2: f2c4 0200 movt r2, #16384 ; 0x4000 + 2ee6: 2700 movs r7, #0 + 2ee8: b083 sub sp, #12 + 2eea: 2501 movs r5, #1 + 2eec: 9001 str r0, [sp, #4] + 2eee: 601f str r7, [r3, #0] + 2ef0: f8ce 5000 str.w r5, [lr] + 2ef4: 6820 ldr r0, [r4, #0] + 2ef6: f89d e005 ldrb.w lr, [sp, #5] + 2efa: ea4f 4c10 mov.w ip, r0, lsr #16 + 2efe: ea4e 4e0c orr.w lr, lr, ip, lsl #16 + 2f02: f8c4 e000 str.w lr, [r4] + 2f06: 601f str r7, [r3, #0] + 2f08: 680c ldr r4, [r1, #0] + 2f0a: 2705 movs r7, #5 + 2f0c: f424 2e70 bic.w lr, r4, #983040 ; 0xf0000 + 2f10: f42e 7e40 bic.w lr, lr, #768 ; 0x300 + 2f14: f44e 7e40 orr.w lr, lr, #768 ; 0x300 + 2f18: f8c1 e000 str.w lr, [r1] + 2f1c: b284 uxth r4, r0 + 2f1e: 7037 strb r7, [r6, #0] + 2f20: 601d str r5, [r3, #0] + 2f22: 6813 ldr r3, [r2, #0] + 2f24: 07db lsls r3, r3, #31 + 2f26: d4fc bmi.n 2f22 + 2f28: f246 0160 movw r1, #24672 ; 0x6060 + 2f2c: f246 0208 movw r2, #24584 ; 0x6008 + 2f30: f246 131c movw r3, #24860 ; 0x611c + 2f34: f2c4 0100 movt r1, #16384 ; 0x4000 + 2f38: f2c4 0200 movt r2, #16384 ; 0x4000 + 2f3c: f2c4 0300 movt r3, #16384 ; 0x4000 + 2f40: 2500 movs r5, #0 + 2f42: 7808 ldrb r0, [r1, #0] + 2f44: 6015 str r5, [r2, #0] + 2f46: 681a ldr r2, [r3, #0] + 2f48: 0c12 lsrs r2, r2, #16 + 2f4a: ea44 4202 orr.w r2, r4, r2, lsl #16 + 2f4e: 601a str r2, [r3, #0] + 2f50: b003 add sp, #12 + 2f52: bdf0 pop {r4, r5, r6, r7, pc} + +00002f54 : + 2f54: b500 push {lr} + 2f56: b083 sub sp, #12 + 2f58: 9001 str r0, [sp, #4] + 2f5a: 9801 ldr r0, [sp, #4] + 2f5c: f7ff ffaa bl 2eb4 + 2f60: 07c3 lsls r3, r0, #31 + 2f62: d4fa bmi.n 2f5a + 2f64: b003 add sp, #12 + 2f66: f85d fb04 ldr.w pc, [sp], #4 + 2f6a: bf00 nop + +00002f6c : + 2f6c: f246 0308 movw r3, #24584 ; 0x6008 + 2f70: b570 push {r4, r5, r6, lr} + 2f72: f246 0560 movw r5, #24672 ; 0x6060 + 2f76: f246 0228 movw r2, #24616 ; 0x6028 + 2f7a: f2c4 0300 movt r3, #16384 ; 0x4000 + 2f7e: f44f 44c0 mov.w r4, #24576 ; 0x6000 + 2f82: f2c4 0400 movt r4, #16384 ; 0x4000 + 2f86: f2c4 0500 movt r5, #16384 ; 0x4000 + 2f8a: f2c4 0200 movt r2, #16384 ; 0x4000 + 2f8e: 2600 movs r6, #0 + 2f90: b084 sub sp, #16 + 2f92: 9101 str r1, [sp, #4] + 2f94: 601e str r6, [r3, #0] + 2f96: 6826 ldr r6, [r4, #0] + 2f98: 2101 movs r1, #1 + 2f9a: f426 2670 bic.w r6, r6, #983040 ; 0xf0000 + 2f9e: f426 7640 bic.w r6, r6, #768 ; 0x300 + 2fa2: 6026 str r6, [r4, #0] + 2fa4: 7028 strb r0, [r5, #0] + 2fa6: 6019 str r1, [r3, #0] + 2fa8: 6813 ldr r3, [r2, #0] + 2faa: 07d9 lsls r1, r3, #31 + 2fac: d4fc bmi.n 2fa8 + 2fae: 9b01 ldr r3, [sp, #4] + 2fb0: 9303 str r3, [sp, #12] + 2fb2: 9803 ldr r0, [sp, #12] + 2fb4: f7ff ff7e bl 2eb4 + 2fb8: 07c3 lsls r3, r0, #31 + 2fba: d4fa bmi.n 2fb2 + 2fbc: b004 add sp, #16 + 2fbe: bd70 pop {r4, r5, r6, pc} + +00002fc0 : + 2fc0: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + 2fc4: f246 1418 movw r4, #24856 ; 0x6118 + 2fc8: f2c4 0400 movt r4, #16384 ; 0x4000 + 2fcc: b084 sub sp, #16 + 2fce: 9101 str r1, [sp, #4] + 2fd0: 4680 mov r8, r0 + 2fd2: 2006 movs r0, #6 + 2fd4: 6827 ldr r7, [r4, #0] + 2fd6: f7ff ffc9 bl 2f6c + 2fda: f246 0308 movw r3, #24584 ; 0x6008 + 2fde: f246 0560 movw r5, #24672 ; 0x6060 + 2fe2: f246 0228 movw r2, #24616 ; 0x6028 + 2fe6: f2c4 0300 movt r3, #16384 ; 0x4000 + 2fea: f44f 46c0 mov.w r6, #24576 ; 0x6000 + 2fee: f2c4 0600 movt r6, #16384 ; 0x4000 + 2ff2: f2c4 0500 movt r5, #16384 ; 0x4000 + 2ff6: f2c4 0200 movt r2, #16384 ; 0x4000 + 2ffa: 2100 movs r1, #0 + 2ffc: 6019 str r1, [r3, #0] + 2ffe: 6830 ldr r0, [r6, #0] + 3000: 2101 movs r1, #1 + 3002: fa5f f888 uxtb.w r8, r8 + 3006: f420 7040 bic.w r0, r0, #768 ; 0x300 + 300a: 6030 str r0, [r6, #0] + 300c: 6021 str r1, [r4, #0] + 300e: 7029 strb r1, [r5, #0] + 3010: f885 8000 strb.w r8, [r5] + 3014: 6019 str r1, [r3, #0] + 3016: 6813 ldr r3, [r2, #0] + 3018: 07d9 lsls r1, r3, #31 + 301a: d4fc bmi.n 3016 + 301c: f246 0208 movw r2, #24584 ; 0x6008 + 3020: f246 1318 movw r3, #24856 ; 0x6118 + 3024: f2c4 0200 movt r2, #16384 ; 0x4000 + 3028: f2c4 0300 movt r3, #16384 ; 0x4000 + 302c: 2100 movs r1, #0 + 302e: 6011 str r1, [r2, #0] + 3030: 601f str r7, [r3, #0] + 3032: 9b01 ldr r3, [sp, #4] + 3034: 9303 str r3, [sp, #12] + 3036: 9803 ldr r0, [sp, #12] + 3038: f7ff ff3c bl 2eb4 + 303c: 07c3 lsls r3, r0, #31 + 303e: d4fa bmi.n 3036 + 3040: b004 add sp, #16 + 3042: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 3046: bf00 nop + +00003048 : + 3048: f640 4088 movw r0, #3208 ; 0xc88 + 304c: b410 push {r4} + 304e: 2410 movs r4, #16 + 3050: f2c0 0003 movt r0, #3 + 3054: f6c9 0400 movt r4, #38912 ; 0x9800 + 3058: f04f 4318 mov.w r3, #2550136832 ; 0x98000000 + 305c: 18c2 adds r2, r0, r3 + 305e: f102 42d0 add.w r2, r2, #1744830464 ; 0x68000000 + 3062: 6811 ldr r1, [r2, #0] + 3064: 681a ldr r2, [r3, #0] + 3066: 3304 adds r3, #4 + 3068: 4291 cmp r1, r2 + 306a: d105 bne.n 3078 + 306c: 42a3 cmp r3, r4 + 306e: d1f5 bne.n 305c + 3070: 2001 movs r0, #1 + 3072: f85d 4b04 ldr.w r4, [sp], #4 + 3076: 4770 bx lr + 3078: 2000 movs r0, #0 + 307a: f85d 4b04 ldr.w r4, [sp], #4 + 307e: 4770 bx lr + +00003080 : + 3080: 2338 movs r3, #56 ; 0x38 + 3082: b470 push {r4, r5, r6} + 3084: f2c4 0300 movt r3, #16384 ; 0x4000 + 3088: f44f 74fa mov.w r4, #500 ; 0x1f4 + 308c: f2c4 0400 movt r4, #16384 ; 0x4000 + 3090: 6818 ldr r0, [r3, #0] + 3092: 4913 ldr r1, [pc, #76] ; (30e0 ) + 3094: 6825 ldr r5, [r4, #0] + 3096: f3c0 6081 ubfx r0, r0, #26, #2 + 309a: eb01 0480 add.w r4, r1, r0, lsl #2 + 309e: f015 0501 ands.w r5, r5, #1 + 30a2: 78a6 ldrb r6, [r4, #2] + 30a4: d013 beq.n 30ce + 30a6: 25e0 movs r5, #224 ; 0xe0 + 30a8: f2c4 0500 movt r5, #16384 ; 0x4000 + 30ac: 682d ldr r5, [r5, #0] + 30ae: f015 0520 ands.w r5, r5, #32 + 30b2: d00c beq.n 30ce + 30b4: 681d ldr r5, [r3, #0] + 30b6: f015 7580 ands.w r5, r5, #16777216 ; 0x1000000 + 30ba: bf1f itttt ne + 30bc: 681d ldrne r5, [r3, #0] + 30be: f3c5 4507 ubfxne r5, r5, #16, #8 + 30c2: f005 061f andne.w r6, r5, #31 + 30c6: eb06 0646 addne.w r6, r6, r6, lsl #1 + 30ca: bf18 it ne + 30cc: 096d lsrne r5, r5, #5 + 30ce: 7864 ldrb r4, [r4, #1] + 30d0: f811 3020 ldrb.w r3, [r1, r0, lsl #2] + 30d4: 4425 add r5, r4 + 30d6: 7055 strb r5, [r2, #1] + 30d8: 7096 strb r6, [r2, #2] + 30da: 7013 strb r3, [r2, #0] + 30dc: bc70 pop {r4, r5, r6} + 30de: 4770 bx lr + 30e0: 00030c98 .word 0x00030c98 + +000030e4 : + 30e4: 2314 movs r3, #20 + 30e6: f2c4 0300 movt r3, #16384 ; 0x4000 + 30ea: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + 30ee: 4604 mov r4, r0 + 30f0: 6818 ldr r0, [r3, #0] + 30f2: b082 sub sp, #8 + 30f4: 4688 mov r8, r1 + 30f6: f3c0 1002 ubfx r0, r0, #4, #3 + 30fa: 4621 mov r1, r4 + 30fc: aa01 add r2, sp, #4 + 30fe: f246 0708 movw r7, #24584 ; 0x6008 + 3102: f246 0614 movw r6, #24596 ; 0x6014 + 3106: f246 0510 movw r5, #24592 ; 0x6010 + 310a: f7ff ffb9 bl 3080 + 310e: f246 121c movw r2, #24860 ; 0x611c + 3112: f246 0004 movw r0, #24580 ; 0x6004 + 3116: f2c4 0700 movt r7, #16384 ; 0x4000 + 311a: f2c4 0600 movt r6, #16384 ; 0x4000 + 311e: f2c4 0500 movt r5, #16384 ; 0x4000 + 3122: f2c4 0200 movt r2, #16384 ; 0x4000 + 3126: f44f 7340 mov.w r3, #768 ; 0x300 + 312a: f2c4 0300 movt r3, #16384 ; 0x4000 + 312e: f2c4 0000 movt r0, #16384 ; 0x4000 + 3132: 2101 movs r1, #1 + 3134: f04f 0e00 mov.w lr, #0 + 3138: f8c7 e000 str.w lr, [r7] + 313c: 6034 str r4, [r6, #0] + 313e: 6029 str r1, [r5, #0] + 3140: 6811 ldr r1, [r2, #0] + 3142: f89d 4005 ldrb.w r4, [sp, #5] + 3146: 0c09 lsrs r1, r1, #16 + 3148: ea44 4101 orr.w r1, r4, r1, lsl #16 + 314c: 6011 str r1, [r2, #0] + 314e: 6819 ldr r1, [r3, #0] + 3150: f89d 2006 ldrb.w r2, [sp, #6] + 3154: f021 01ff bic.w r1, r1, #255 ; 0xff + 3158: 4311 orrs r1, r2 + 315a: f1b8 0f01 cmp.w r8, #1 + 315e: f04f 0204 mov.w r2, #4 + 3162: 6019 str r1, [r3, #0] + 3164: 6002 str r2, [r0, #0] + 3166: d01b beq.n 31a0 + 3168: d30f bcc.n 318a + 316a: f1b8 0f02 cmp.w r8, #2 + 316e: d109 bne.n 3184 + 3170: f44f 43c0 mov.w r3, #24576 ; 0x6000 + 3174: f2c4 0300 movt r3, #16384 ; 0x4000 + 3178: 681a ldr r2, [r3, #0] + 317a: f422 127c bic.w r2, r2, #4128768 ; 0x3f0000 + 317e: f442 2220 orr.w r2, r2, #655360 ; 0xa0000 + 3182: 601a str r2, [r3, #0] + 3184: b002 add sp, #8 + 3186: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 318a: f44f 43c0 mov.w r3, #24576 ; 0x6000 + 318e: f2c4 0300 movt r3, #16384 ; 0x4000 + 3192: 681a ldr r2, [r3, #0] + 3194: f422 127c bic.w r2, r2, #4128768 ; 0x3f0000 + 3198: 601a str r2, [r3, #0] + 319a: b002 add sp, #8 + 319c: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 31a0: f44f 43c0 mov.w r3, #24576 ; 0x6000 + 31a4: f2c4 0300 movt r3, #16384 ; 0x4000 + 31a8: 681a ldr r2, [r3, #0] + 31aa: f422 127c bic.w r2, r2, #4128768 ; 0x3f0000 + 31ae: f442 22a0 orr.w r2, r2, #327680 ; 0x50000 + 31b2: 601a str r2, [r3, #0] + 31b4: b002 add sp, #8 + 31b6: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 31ba: bf00 nop + +000031bc : + 31bc: b530 push {r4, r5, lr} + 31be: f240 3414 movw r4, #788 ; 0x314 + 31c2: 2314 movs r3, #20 + 31c4: f2c4 0300 movt r3, #16384 ; 0x4000 + 31c8: f2c1 0400 movt r4, #4096 ; 0x1000 + 31cc: 6818 ldr r0, [r3, #0] + 31ce: b083 sub sp, #12 + 31d0: 466a mov r2, sp + 31d2: 2101 movs r1, #1 + 31d4: f3c0 1002 ubfx r0, r0, #4, #3 + 31d8: f7ff ff52 bl 3080 + 31dc: 6823 ldr r3, [r4, #0] + 31de: 005a lsls r2, r3, #1 + 31e0: d420 bmi.n 3224 + 31e2: 9b00 ldr r3, [sp, #0] + 31e4: 9301 str r3, [sp, #4] + 31e6: 9801 ldr r0, [sp, #4] + 31e8: f7ff fe64 bl 2eb4 + 31ec: 07c1 lsls r1, r0, #31 + 31ee: d4fa bmi.n 31e6 + 31f0: e002 b.n 31f8 + 31f2: 9900 ldr r1, [sp, #0] + 31f4: f7ff feba bl 2f6c + 31f8: 9800 ldr r0, [sp, #0] + 31fa: f7ff fe5b bl 2eb4 + 31fe: f010 0f02 tst.w r0, #2 + 3202: f04f 0006 mov.w r0, #6 + 3206: d0f4 beq.n 31f2 + 3208: 6823 ldr r3, [r4, #0] + 320a: 005a lsls r2, r3, #1 + 320c: d42a bmi.n 3264 + 320e: 20c7 movs r0, #199 ; 0xc7 + 3210: 9900 ldr r1, [sp, #0] + 3212: f7ff feab bl 2f6c + 3216: 9800 ldr r0, [sp, #0] + 3218: f7ff fe4c bl 2eb4 + 321c: 0783 lsls r3, r0, #30 + 321e: d4fa bmi.n 3216 + 3220: b003 add sp, #12 + 3222: bd30 pop {r4, r5, pc} + 3224: f24f 1060 movw r0, #61792 ; 0xf160 + 3228: f24f 359d movw r5, #62365 ; 0xf39d + 322c: f2c0 0003 movt r0, #3 + 3230: f2c0 0500 movt r5, #0 + 3234: f89d 1000 ldrb.w r1, [sp] + 3238: 47a8 blx r5 + 323a: 6823 ldr r3, [r4, #0] + 323c: 005b lsls r3, r3, #1 + 323e: d5d0 bpl.n 31e2 + 3240: f24f 1078 movw r0, #61816 ; 0xf178 + 3244: f89d 1001 ldrb.w r1, [sp, #1] + 3248: f2c0 0003 movt r0, #3 + 324c: 47a8 blx r5 + 324e: 6823 ldr r3, [r4, #0] + 3250: 0058 lsls r0, r3, #1 + 3252: d5c6 bpl.n 31e2 + 3254: f24f 1090 movw r0, #61840 ; 0xf190 + 3258: f89d 1002 ldrb.w r1, [sp, #2] + 325c: f2c0 0003 movt r0, #3 + 3260: 47a8 blx r5 + 3262: e7be b.n 31e2 + 3264: f24f 10a8 movw r0, #61864 ; 0xf1a8 + 3268: f24f 339d movw r3, #62365 ; 0xf39d + 326c: f2c0 0003 movt r0, #3 + 3270: f2c0 0300 movt r3, #0 + 3274: 4798 blx r3 + 3276: e7ca b.n 320e + +00003278 : + 3278: 2314 movs r3, #20 + 327a: f2c4 0300 movt r3, #16384 ; 0x4000 + 327e: b570 push {r4, r5, r6, lr} + 3280: 4605 mov r5, r0 + 3282: 6818 ldr r0, [r3, #0] + 3284: b082 sub sp, #8 + 3286: 2101 movs r1, #1 + 3288: f3c0 1002 ubfx r0, r0, #4, #3 + 328c: aa01 add r2, sp, #4 + 328e: f7ff fef7 bl 3080 + 3292: 682b ldr r3, [r5, #0] + 3294: 2b01 cmp r3, #1 + 3296: d00f beq.n 32b8 + 3298: 2b02 cmp r3, #2 + 329a: d10b bne.n 32b4 + 329c: f240 3414 movw r4, #788 ; 0x314 + 32a0: f2c1 0400 movt r4, #4096 ; 0x1000 + 32a4: 6823 ldr r3, [r4, #0] + 32a6: 005a lsls r2, r3, #1 + 32a8: d45b bmi.n 3362 + 32aa: f7ff ff87 bl 31bc + 32ae: 6823 ldr r3, [r4, #0] + 32b0: 005b lsls r3, r3, #1 + 32b2: d442 bmi.n 333a + 32b4: b002 add sp, #8 + 32b6: bd70 pop {r4, r5, r6, pc} + 32b8: f240 3414 movw r4, #788 ; 0x314 + 32bc: f2c1 0400 movt r4, #4096 ; 0x1000 + 32c0: 6823 ldr r3, [r4, #0] + 32c2: 686d ldr r5, [r5, #4] + 32c4: 005e lsls r6, r3, #1 + 32c6: d442 bmi.n 334e + 32c8: f44f 7204 mov.w r2, #528 ; 0x210 + 32cc: f2c4 0200 movt r2, #16384 ; 0x4000 + 32d0: f44f 730c mov.w r3, #560 ; 0x230 + 32d4: f2c4 0300 movt r3, #16384 ; 0x4000 + 32d8: 6811 ldr r1, [r2, #0] + 32da: 20c4 movs r0, #196 ; 0xc4 + 32dc: f041 0110 orr.w r1, r1, #16 + 32e0: 6011 str r1, [r2, #0] + 32e2: 681a ldr r2, [r3, #0] + 32e4: 2100 movs r1, #0 + 32e6: f442 7280 orr.w r2, r2, #256 ; 0x100 + 32ea: 601a str r2, [r3, #0] + 32ec: 681e ldr r6, [r3, #0] + 32ee: 2201 movs r2, #1 + 32f0: f446 7600 orr.w r6, r6, #512 ; 0x200 + 32f4: 601e str r6, [r3, #0] + 32f6: f7ff fc1f bl 2b38 + 32fa: 2d01 cmp r5, #1 + 32fc: d014 beq.n 3328 + 32fe: d30a bcc.n 3316 + 3300: 2d02 cmp r5, #2 + 3302: d1d7 bne.n 32b4 + 3304: 6823 ldr r3, [r4, #0] + 3306: 0059 lsls r1, r3, #1 + 3308: d449 bmi.n 339e + 330a: f89d 0004 ldrb.w r0, [sp, #4] + 330e: 2102 movs r1, #2 + 3310: f7ff fee8 bl 30e4 + 3314: e7ce b.n 32b4 + 3316: 6823 ldr r3, [r4, #0] + 3318: 005c lsls r4, r3, #1 + 331a: d436 bmi.n 338a + 331c: f89d 0004 ldrb.w r0, [sp, #4] + 3320: 2100 movs r1, #0 + 3322: f7ff fedf bl 30e4 + 3326: e7c5 b.n 32b4 + 3328: 6823 ldr r3, [r4, #0] + 332a: 0058 lsls r0, r3, #1 + 332c: d423 bmi.n 3376 + 332e: f89d 0004 ldrb.w r0, [sp, #4] + 3332: 2101 movs r1, #1 + 3334: f7ff fed6 bl 30e4 + 3338: e7bc b.n 32b4 + 333a: f24f 2044 movw r0, #62020 ; 0xf244 + 333e: f24f 339d movw r3, #62365 ; 0xf39d + 3342: f2c0 0003 movt r0, #3 + 3346: f2c0 0300 movt r3, #0 + 334a: 4798 blx r3 + 334c: e7b2 b.n 32b4 + 334e: f24f 10b8 movw r0, #61880 ; 0xf1b8 + 3352: f24f 339d movw r3, #62365 ; 0xf39d + 3356: f2c0 0003 movt r0, #3 + 335a: f2c0 0300 movt r3, #0 + 335e: 4798 blx r3 + 3360: e7b2 b.n 32c8 + 3362: f24f 2030 movw r0, #62000 ; 0xf230 + 3366: f24f 339d movw r3, #62365 ; 0xf39d + 336a: f2c0 0003 movt r0, #3 + 336e: f2c0 0300 movt r3, #0 + 3372: 4798 blx r3 + 3374: e799 b.n 32aa + 3376: f24f 10f4 movw r0, #61940 ; 0xf1f4 + 337a: f24f 339d movw r3, #62365 ; 0xf39d + 337e: f2c0 0003 movt r0, #3 + 3382: f2c0 0300 movt r3, #0 + 3386: 4798 blx r3 + 3388: e7d1 b.n 332e + 338a: f24f 10d8 movw r0, #61912 ; 0xf1d8 + 338e: f24f 339d movw r3, #62365 ; 0xf39d + 3392: f2c0 0003 movt r0, #3 + 3396: f2c0 0300 movt r3, #0 + 339a: 4798 blx r3 + 339c: e7be b.n 331c + 339e: f24f 2010 movw r0, #61968 ; 0xf210 + 33a2: f24f 339d movw r3, #62365 ; 0xf39d + 33a6: f2c0 0003 movt r0, #3 + 33aa: f2c0 0300 movt r3, #0 + 33ae: 4798 blx r3 + 33b0: e7ab b.n 330a + 33b2: bf00 nop + +000033b4 : + 33b4: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} + 33b8: f642 0204 movw r2, #10244 ; 0x2804 + 33bc: f642 030c movw r3, #10252 ; 0x280c + 33c0: f2c4 0200 movt r2, #16384 ; 0x4000 + 33c4: f2c4 0300 movt r3, #16384 ; 0x4000 + 33c8: f240 1600 movw r6, #256 ; 0x100 + 33cc: f240 2500 movw r5, #512 ; 0x200 + 33d0: f8d2 9000 ldr.w r9, [r2] + 33d4: 681b ldr r3, [r3, #0] + 33d6: f2c1 0600 movt r6, #4096 ; 0x1000 + 33da: f2c1 0500 movt r5, #4096 ; 0x1000 + 33de: 2400 movs r4, #0 + 33e0: ea03 0809 and.w r8, r3, r9 + 33e4: 2701 movs r7, #1 + 33e6: e005 b.n 33f4 + 33e8: 2c20 cmp r4, #32 + 33ea: f106 0604 add.w r6, r6, #4 + 33ee: f105 0504 add.w r5, r5, #4 + 33f2: d011 beq.n 3418 + 33f4: fa07 f304 lsl.w r3, r7, r4 + 33f8: ea13 0f08 tst.w r3, r8 + 33fc: f104 0401 add.w r4, r4, #1 + 3400: d0f2 beq.n 33e8 + 3402: f8d6 3080 ldr.w r3, [r6, #128] ; 0x80 + 3406: f8d5 0080 ldr.w r0, [r5, #128] ; 0x80 + 340a: 4798 blx r3 + 340c: 2c20 cmp r4, #32 + 340e: f106 0604 add.w r6, r6, #4 + 3412: f105 0504 add.w r5, r5, #4 + 3416: d1ed bne.n 33f4 + 3418: f642 0204 movw r2, #10244 ; 0x2804 + 341c: f44f 4361 mov.w r3, #57600 ; 0xe100 + 3420: f2c4 0200 movt r2, #16384 ; 0x4000 + 3424: f2ce 0300 movt r3, #57344 ; 0xe000 + 3428: f44f 2100 mov.w r1, #524288 ; 0x80000 + 342c: f8c2 9000 str.w r9, [r2] + 3430: f8c3 1180 str.w r1, [r3, #384] ; 0x180 + 3434: e8bd 83f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} + +00003438 : + 3438: b508 push {r3, lr} + 343a: f240 1300 movw r3, #256 ; 0x100 + 343e: f2c1 0300 movt r3, #4096 ; 0x1000 + 3442: 6819 ldr r1, [r3, #0] + 3444: b169 cbz r1, 3462 + 3446: f240 2300 movw r3, #512 ; 0x200 + 344a: f2c1 0300 movt r3, #4096 ; 0x1000 + 344e: 6818 ldr r0, [r3, #0] + 3450: 4788 blx r1 + 3452: f44f 4361 mov.w r3, #57600 ; 0xe100 + 3456: f2ce 0300 movt r3, #57344 ; 0xe000 + 345a: 2201 movs r2, #1 + 345c: f8c3 2180 str.w r2, [r3, #384] ; 0x180 + 3460: bd08 pop {r3, pc} + 3462: f240 3314 movw r3, #788 ; 0x314 + 3466: f2c1 0300 movt r3, #4096 ; 0x1000 + 346a: 681b ldr r3, [r3, #0] + 346c: 005b lsls r3, r3, #1 + 346e: d5f0 bpl.n 3452 + 3470: f24f 2058 movw r0, #62040 ; 0xf258 + 3474: f24f 339d movw r3, #62365 ; 0xf39d + 3478: f2c0 0003 movt r0, #3 + 347c: f2c0 0300 movt r3, #0 + 3480: 4798 blx r3 + 3482: e7e6 b.n 3452 + +00003484 : + 3484: b508 push {r3, lr} + 3486: f240 1300 movw r3, #256 ; 0x100 + 348a: f2c1 0300 movt r3, #4096 ; 0x1000 + 348e: 685b ldr r3, [r3, #4] + 3490: b16b cbz r3, 34ae + 3492: f240 2200 movw r2, #512 ; 0x200 + 3496: f2c1 0200 movt r2, #4096 ; 0x1000 + 349a: 6850 ldr r0, [r2, #4] + 349c: 4798 blx r3 + 349e: f44f 4361 mov.w r3, #57600 ; 0xe100 + 34a2: f2ce 0300 movt r3, #57344 ; 0xe000 + 34a6: 2202 movs r2, #2 + 34a8: f8c3 2180 str.w r2, [r3, #384] ; 0x180 + 34ac: bd08 pop {r3, pc} + 34ae: f240 3314 movw r3, #788 ; 0x314 + 34b2: f2c1 0300 movt r3, #4096 ; 0x1000 + 34b6: 681b ldr r3, [r3, #0] + 34b8: 005b lsls r3, r3, #1 + 34ba: d5f0 bpl.n 349e + 34bc: f24f 2058 movw r0, #62040 ; 0xf258 + 34c0: f24f 339d movw r3, #62365 ; 0xf39d + 34c4: 2101 movs r1, #1 + 34c6: f2c0 0300 movt r3, #0 + 34ca: f2c0 0003 movt r0, #3 + 34ce: 4798 blx r3 + 34d0: e7e5 b.n 349e + 34d2: bf00 nop + +000034d4 : + 34d4: b508 push {r3, lr} + 34d6: f240 1300 movw r3, #256 ; 0x100 + 34da: f2c1 0300 movt r3, #4096 ; 0x1000 + 34de: 689b ldr r3, [r3, #8] + 34e0: b16b cbz r3, 34fe + 34e2: f240 2200 movw r2, #512 ; 0x200 + 34e6: f2c1 0200 movt r2, #4096 ; 0x1000 + 34ea: 6890 ldr r0, [r2, #8] + 34ec: 4798 blx r3 + 34ee: f44f 4361 mov.w r3, #57600 ; 0xe100 + 34f2: f2ce 0300 movt r3, #57344 ; 0xe000 + 34f6: 2204 movs r2, #4 + 34f8: f8c3 2180 str.w r2, [r3, #384] ; 0x180 + 34fc: bd08 pop {r3, pc} + 34fe: f240 3314 movw r3, #788 ; 0x314 + 3502: f2c1 0300 movt r3, #4096 ; 0x1000 + 3506: 681b ldr r3, [r3, #0] + 3508: 005b lsls r3, r3, #1 + 350a: d5f0 bpl.n 34ee + 350c: f24f 2058 movw r0, #62040 ; 0xf258 + 3510: f24f 339d movw r3, #62365 ; 0xf39d + 3514: 2102 movs r1, #2 + 3516: f2c0 0300 movt r3, #0 + 351a: f2c0 0003 movt r0, #3 + 351e: 4798 blx r3 + 3520: e7e5 b.n 34ee + 3522: bf00 nop + +00003524 : + 3524: b508 push {r3, lr} + 3526: f240 1300 movw r3, #256 ; 0x100 + 352a: f2c1 0300 movt r3, #4096 ; 0x1000 + 352e: 68db ldr r3, [r3, #12] + 3530: b16b cbz r3, 354e + 3532: f240 2200 movw r2, #512 ; 0x200 + 3536: f2c1 0200 movt r2, #4096 ; 0x1000 + 353a: 68d0 ldr r0, [r2, #12] + 353c: 4798 blx r3 + 353e: f44f 4361 mov.w r3, #57600 ; 0xe100 + 3542: f2ce 0300 movt r3, #57344 ; 0xe000 + 3546: 2208 movs r2, #8 + 3548: f8c3 2180 str.w r2, [r3, #384] ; 0x180 + 354c: bd08 pop {r3, pc} + 354e: f240 3314 movw r3, #788 ; 0x314 + 3552: f2c1 0300 movt r3, #4096 ; 0x1000 + 3556: 681b ldr r3, [r3, #0] + 3558: 005b lsls r3, r3, #1 + 355a: d5f0 bpl.n 353e + 355c: f24f 2058 movw r0, #62040 ; 0xf258 + 3560: f24f 339d movw r3, #62365 ; 0xf39d + 3564: 2103 movs r1, #3 + 3566: f2c0 0300 movt r3, #0 + 356a: f2c0 0003 movt r0, #3 + 356e: 4798 blx r3 + 3570: e7e5 b.n 353e + 3572: bf00 nop + +00003574 : + 3574: b508 push {r3, lr} + 3576: f240 1300 movw r3, #256 ; 0x100 + 357a: f2c1 0300 movt r3, #4096 ; 0x1000 + 357e: 691b ldr r3, [r3, #16] + 3580: b16b cbz r3, 359e + 3582: f240 2200 movw r2, #512 ; 0x200 + 3586: f2c1 0200 movt r2, #4096 ; 0x1000 + 358a: 6910 ldr r0, [r2, #16] + 358c: 4798 blx r3 + 358e: f44f 4361 mov.w r3, #57600 ; 0xe100 + 3592: f2ce 0300 movt r3, #57344 ; 0xe000 + 3596: 2210 movs r2, #16 + 3598: f8c3 2180 str.w r2, [r3, #384] ; 0x180 + 359c: bd08 pop {r3, pc} + 359e: f240 3314 movw r3, #788 ; 0x314 + 35a2: f2c1 0300 movt r3, #4096 ; 0x1000 + 35a6: 681b ldr r3, [r3, #0] + 35a8: 005b lsls r3, r3, #1 + 35aa: d5f0 bpl.n 358e + 35ac: f24f 2058 movw r0, #62040 ; 0xf258 + 35b0: f24f 339d movw r3, #62365 ; 0xf39d + 35b4: 2104 movs r1, #4 + 35b6: f2c0 0300 movt r3, #0 + 35ba: f2c0 0003 movt r0, #3 + 35be: 4798 blx r3 + 35c0: e7e5 b.n 358e + 35c2: bf00 nop + +000035c4 : + 35c4: b508 push {r3, lr} + 35c6: f240 1300 movw r3, #256 ; 0x100 + 35ca: f2c1 0300 movt r3, #4096 ; 0x1000 + 35ce: 695b ldr r3, [r3, #20] + 35d0: b16b cbz r3, 35ee + 35d2: f240 2200 movw r2, #512 ; 0x200 + 35d6: f2c1 0200 movt r2, #4096 ; 0x1000 + 35da: 6950 ldr r0, [r2, #20] + 35dc: 4798 blx r3 + 35de: f44f 4361 mov.w r3, #57600 ; 0xe100 + 35e2: f2ce 0300 movt r3, #57344 ; 0xe000 + 35e6: 2220 movs r2, #32 + 35e8: f8c3 2180 str.w r2, [r3, #384] ; 0x180 + 35ec: bd08 pop {r3, pc} + 35ee: f240 3314 movw r3, #788 ; 0x314 + 35f2: f2c1 0300 movt r3, #4096 ; 0x1000 + 35f6: 681b ldr r3, [r3, #0] + 35f8: 005b lsls r3, r3, #1 + 35fa: d5f0 bpl.n 35de + 35fc: f24f 2058 movw r0, #62040 ; 0xf258 + 3600: f24f 339d movw r3, #62365 ; 0xf39d + 3604: 2105 movs r1, #5 + 3606: f2c0 0300 movt r3, #0 + 360a: f2c0 0003 movt r0, #3 + 360e: 4798 blx r3 + 3610: e7e5 b.n 35de + 3612: bf00 nop + +00003614 : + 3614: b508 push {r3, lr} + 3616: f240 1300 movw r3, #256 ; 0x100 + 361a: f2c1 0300 movt r3, #4096 ; 0x1000 + 361e: 699b ldr r3, [r3, #24] + 3620: b16b cbz r3, 363e + 3622: f240 2200 movw r2, #512 ; 0x200 + 3626: f2c1 0200 movt r2, #4096 ; 0x1000 + 362a: 6990 ldr r0, [r2, #24] + 362c: 4798 blx r3 + 362e: f44f 4361 mov.w r3, #57600 ; 0xe100 + 3632: f2ce 0300 movt r3, #57344 ; 0xe000 + 3636: 2240 movs r2, #64 ; 0x40 + 3638: f8c3 2180 str.w r2, [r3, #384] ; 0x180 + 363c: bd08 pop {r3, pc} + 363e: f240 3314 movw r3, #788 ; 0x314 + 3642: f2c1 0300 movt r3, #4096 ; 0x1000 + 3646: 681b ldr r3, [r3, #0] + 3648: 005b lsls r3, r3, #1 + 364a: d5f0 bpl.n 362e + 364c: f24f 2058 movw r0, #62040 ; 0xf258 + 3650: f24f 339d movw r3, #62365 ; 0xf39d + 3654: 2106 movs r1, #6 + 3656: f2c0 0300 movt r3, #0 + 365a: f2c0 0003 movt r0, #3 + 365e: 4798 blx r3 + 3660: e7e5 b.n 362e + 3662: bf00 nop + +00003664 : + 3664: b508 push {r3, lr} + 3666: f240 1300 movw r3, #256 ; 0x100 + 366a: f2c1 0300 movt r3, #4096 ; 0x1000 + 366e: 69db ldr r3, [r3, #28] + 3670: b16b cbz r3, 368e + 3672: f240 2200 movw r2, #512 ; 0x200 + 3676: f2c1 0200 movt r2, #4096 ; 0x1000 + 367a: 69d0 ldr r0, [r2, #28] + 367c: 4798 blx r3 + 367e: f44f 4361 mov.w r3, #57600 ; 0xe100 + 3682: f2ce 0300 movt r3, #57344 ; 0xe000 + 3686: 2280 movs r2, #128 ; 0x80 + 3688: f8c3 2180 str.w r2, [r3, #384] ; 0x180 + 368c: bd08 pop {r3, pc} + 368e: f240 3314 movw r3, #788 ; 0x314 + 3692: f2c1 0300 movt r3, #4096 ; 0x1000 + 3696: 681b ldr r3, [r3, #0] + 3698: 005b lsls r3, r3, #1 + 369a: d5f0 bpl.n 367e + 369c: f24f 2058 movw r0, #62040 ; 0xf258 + 36a0: f24f 339d movw r3, #62365 ; 0xf39d + 36a4: 2107 movs r1, #7 + 36a6: f2c0 0300 movt r3, #0 + 36aa: f2c0 0003 movt r0, #3 + 36ae: 4798 blx r3 + 36b0: e7e5 b.n 367e + 36b2: bf00 nop + +000036b4 : + 36b4: b508 push {r3, lr} + 36b6: f240 1300 movw r3, #256 ; 0x100 + 36ba: f2c1 0300 movt r3, #4096 ; 0x1000 + 36be: 6a1b ldr r3, [r3, #32] + 36c0: b173 cbz r3, 36e0 + 36c2: f240 2200 movw r2, #512 ; 0x200 + 36c6: f2c1 0200 movt r2, #4096 ; 0x1000 + 36ca: 6a10 ldr r0, [r2, #32] + 36cc: 4798 blx r3 + 36ce: f44f 4361 mov.w r3, #57600 ; 0xe100 + 36d2: f2ce 0300 movt r3, #57344 ; 0xe000 + 36d6: f44f 7280 mov.w r2, #256 ; 0x100 + 36da: f8c3 2180 str.w r2, [r3, #384] ; 0x180 + 36de: bd08 pop {r3, pc} + 36e0: f240 3314 movw r3, #788 ; 0x314 + 36e4: f2c1 0300 movt r3, #4096 ; 0x1000 + 36e8: 681b ldr r3, [r3, #0] + 36ea: 005b lsls r3, r3, #1 + 36ec: d5ef bpl.n 36ce + 36ee: f24f 2058 movw r0, #62040 ; 0xf258 + 36f2: f24f 339d movw r3, #62365 ; 0xf39d + 36f6: 2108 movs r1, #8 + 36f8: f2c0 0300 movt r3, #0 + 36fc: f2c0 0003 movt r0, #3 + 3700: 4798 blx r3 + 3702: e7e4 b.n 36ce + +00003704 : + 3704: b508 push {r3, lr} + 3706: f240 1300 movw r3, #256 ; 0x100 + 370a: f2c1 0300 movt r3, #4096 ; 0x1000 + 370e: 6a5b ldr r3, [r3, #36] ; 0x24 + 3710: b173 cbz r3, 3730 + 3712: f240 2200 movw r2, #512 ; 0x200 + 3716: f2c1 0200 movt r2, #4096 ; 0x1000 + 371a: 6a50 ldr r0, [r2, #36] ; 0x24 + 371c: 4798 blx r3 + 371e: f44f 4361 mov.w r3, #57600 ; 0xe100 + 3722: f2ce 0300 movt r3, #57344 ; 0xe000 + 3726: f44f 7200 mov.w r2, #512 ; 0x200 + 372a: f8c3 2180 str.w r2, [r3, #384] ; 0x180 + 372e: bd08 pop {r3, pc} + 3730: f240 3314 movw r3, #788 ; 0x314 + 3734: f2c1 0300 movt r3, #4096 ; 0x1000 + 3738: 681b ldr r3, [r3, #0] + 373a: 005b lsls r3, r3, #1 + 373c: d5ef bpl.n 371e + 373e: f24f 2058 movw r0, #62040 ; 0xf258 + 3742: f24f 339d movw r3, #62365 ; 0xf39d + 3746: 2109 movs r1, #9 + 3748: f2c0 0300 movt r3, #0 + 374c: f2c0 0003 movt r0, #3 + 3750: 4798 blx r3 + 3752: e7e4 b.n 371e + +00003754 : + 3754: b508 push {r3, lr} + 3756: f240 1300 movw r3, #256 ; 0x100 + 375a: f2c1 0300 movt r3, #4096 ; 0x1000 + 375e: 6a9b ldr r3, [r3, #40] ; 0x28 + 3760: b173 cbz r3, 3780 + 3762: f240 2200 movw r2, #512 ; 0x200 + 3766: f2c1 0200 movt r2, #4096 ; 0x1000 + 376a: 6a90 ldr r0, [r2, #40] ; 0x28 + 376c: 4798 blx r3 + 376e: f44f 4361 mov.w r3, #57600 ; 0xe100 + 3772: f2ce 0300 movt r3, #57344 ; 0xe000 + 3776: f44f 6280 mov.w r2, #1024 ; 0x400 + 377a: f8c3 2180 str.w r2, [r3, #384] ; 0x180 + 377e: bd08 pop {r3, pc} + 3780: f240 3314 movw r3, #788 ; 0x314 + 3784: f2c1 0300 movt r3, #4096 ; 0x1000 + 3788: 681b ldr r3, [r3, #0] + 378a: 005b lsls r3, r3, #1 + 378c: d5ef bpl.n 376e + 378e: f24f 2058 movw r0, #62040 ; 0xf258 + 3792: f24f 339d movw r3, #62365 ; 0xf39d + 3796: 210a movs r1, #10 + 3798: f2c0 0300 movt r3, #0 + 379c: f2c0 0003 movt r0, #3 + 37a0: 4798 blx r3 + 37a2: e7e4 b.n 376e + +000037a4 : + 37a4: b508 push {r3, lr} + 37a6: f240 1300 movw r3, #256 ; 0x100 + 37aa: f2c1 0300 movt r3, #4096 ; 0x1000 + 37ae: 6adb ldr r3, [r3, #44] ; 0x2c + 37b0: b173 cbz r3, 37d0 + 37b2: f240 2200 movw r2, #512 ; 0x200 + 37b6: f2c1 0200 movt r2, #4096 ; 0x1000 + 37ba: 6ad0 ldr r0, [r2, #44] ; 0x2c + 37bc: 4798 blx r3 + 37be: f44f 4361 mov.w r3, #57600 ; 0xe100 + 37c2: f2ce 0300 movt r3, #57344 ; 0xe000 + 37c6: f44f 6200 mov.w r2, #2048 ; 0x800 + 37ca: f8c3 2180 str.w r2, [r3, #384] ; 0x180 + 37ce: bd08 pop {r3, pc} + 37d0: f240 3314 movw r3, #788 ; 0x314 + 37d4: f2c1 0300 movt r3, #4096 ; 0x1000 + 37d8: 681b ldr r3, [r3, #0] + 37da: 005b lsls r3, r3, #1 + 37dc: d5ef bpl.n 37be + 37de: f24f 2058 movw r0, #62040 ; 0xf258 + 37e2: f24f 339d movw r3, #62365 ; 0xf39d + 37e6: 210b movs r1, #11 + 37e8: f2c0 0300 movt r3, #0 + 37ec: f2c0 0003 movt r0, #3 + 37f0: 4798 blx r3 + 37f2: e7e4 b.n 37be + +000037f4 : + 37f4: b508 push {r3, lr} + 37f6: f240 1300 movw r3, #256 ; 0x100 + 37fa: f2c1 0300 movt r3, #4096 ; 0x1000 + 37fe: 6b5b ldr r3, [r3, #52] ; 0x34 + 3800: b173 cbz r3, 3820 + 3802: f240 2200 movw r2, #512 ; 0x200 + 3806: f2c1 0200 movt r2, #4096 ; 0x1000 + 380a: 6b50 ldr r0, [r2, #52] ; 0x34 + 380c: 4798 blx r3 + 380e: f44f 4361 mov.w r3, #57600 ; 0xe100 + 3812: f2ce 0300 movt r3, #57344 ; 0xe000 + 3816: f44f 5200 mov.w r2, #8192 ; 0x2000 + 381a: f8c3 2180 str.w r2, [r3, #384] ; 0x180 + 381e: bd08 pop {r3, pc} + 3820: f240 3314 movw r3, #788 ; 0x314 + 3824: f2c1 0300 movt r3, #4096 ; 0x1000 + 3828: 681b ldr r3, [r3, #0] + 382a: 005b lsls r3, r3, #1 + 382c: d5ef bpl.n 380e + 382e: f24f 2058 movw r0, #62040 ; 0xf258 + 3832: f24f 339d movw r3, #62365 ; 0xf39d + 3836: 210d movs r1, #13 + 3838: f2c0 0300 movt r3, #0 + 383c: f2c0 0003 movt r0, #3 + 3840: 4798 blx r3 + 3842: e7e4 b.n 380e + +00003844 : + 3844: b508 push {r3, lr} + 3846: f240 1300 movw r3, #256 ; 0x100 + 384a: f2c1 0300 movt r3, #4096 ; 0x1000 + 384e: 6b9b ldr r3, [r3, #56] ; 0x38 + 3850: b173 cbz r3, 3870 + 3852: f240 2200 movw r2, #512 ; 0x200 + 3856: f2c1 0200 movt r2, #4096 ; 0x1000 + 385a: 6b90 ldr r0, [r2, #56] ; 0x38 + 385c: 4798 blx r3 + 385e: f44f 4361 mov.w r3, #57600 ; 0xe100 + 3862: f2ce 0300 movt r3, #57344 ; 0xe000 + 3866: f44f 4280 mov.w r2, #16384 ; 0x4000 + 386a: f8c3 2180 str.w r2, [r3, #384] ; 0x180 + 386e: bd08 pop {r3, pc} + 3870: f240 3314 movw r3, #788 ; 0x314 + 3874: f2c1 0300 movt r3, #4096 ; 0x1000 + 3878: 681b ldr r3, [r3, #0] + 387a: 005b lsls r3, r3, #1 + 387c: d5ef bpl.n 385e + 387e: f24f 2058 movw r0, #62040 ; 0xf258 + 3882: f24f 339d movw r3, #62365 ; 0xf39d + 3886: 210e movs r1, #14 + 3888: f2c0 0300 movt r3, #0 + 388c: f2c0 0003 movt r0, #3 + 3890: 4798 blx r3 + 3892: e7e4 b.n 385e + +00003894 : + 3894: b508 push {r3, lr} + 3896: f240 1300 movw r3, #256 ; 0x100 + 389a: f2c1 0300 movt r3, #4096 ; 0x1000 + 389e: 6bdb ldr r3, [r3, #60] ; 0x3c + 38a0: b173 cbz r3, 38c0 + 38a2: f240 2200 movw r2, #512 ; 0x200 + 38a6: f2c1 0200 movt r2, #4096 ; 0x1000 + 38aa: 6bd0 ldr r0, [r2, #60] ; 0x3c + 38ac: 4798 blx r3 + 38ae: f44f 4361 mov.w r3, #57600 ; 0xe100 + 38b2: f2ce 0300 movt r3, #57344 ; 0xe000 + 38b6: f44f 4200 mov.w r2, #32768 ; 0x8000 + 38ba: f8c3 2180 str.w r2, [r3, #384] ; 0x180 + 38be: bd08 pop {r3, pc} + 38c0: f240 3314 movw r3, #788 ; 0x314 + 38c4: f2c1 0300 movt r3, #4096 ; 0x1000 + 38c8: 681b ldr r3, [r3, #0] + 38ca: 005b lsls r3, r3, #1 + 38cc: d5ef bpl.n 38ae + 38ce: f24f 2058 movw r0, #62040 ; 0xf258 + 38d2: f24f 339d movw r3, #62365 ; 0xf39d + 38d6: 210f movs r1, #15 + 38d8: f2c0 0300 movt r3, #0 + 38dc: f2c0 0003 movt r0, #3 + 38e0: 4798 blx r3 + 38e2: e7e4 b.n 38ae + +000038e4 : + 38e4: b508 push {r3, lr} + 38e6: f240 1300 movw r3, #256 ; 0x100 + 38ea: f2c1 0300 movt r3, #4096 ; 0x1000 + 38ee: 6c1b ldr r3, [r3, #64] ; 0x40 + 38f0: b173 cbz r3, 3910 + 38f2: f240 2200 movw r2, #512 ; 0x200 + 38f6: f2c1 0200 movt r2, #4096 ; 0x1000 + 38fa: 6c10 ldr r0, [r2, #64] ; 0x40 + 38fc: 4798 blx r3 + 38fe: f44f 4361 mov.w r3, #57600 ; 0xe100 + 3902: f2ce 0300 movt r3, #57344 ; 0xe000 + 3906: f44f 3280 mov.w r2, #65536 ; 0x10000 + 390a: f8c3 2180 str.w r2, [r3, #384] ; 0x180 + 390e: bd08 pop {r3, pc} + 3910: f240 3314 movw r3, #788 ; 0x314 + 3914: f2c1 0300 movt r3, #4096 ; 0x1000 + 3918: 681b ldr r3, [r3, #0] + 391a: 005b lsls r3, r3, #1 + 391c: d5ef bpl.n 38fe + 391e: f24f 2058 movw r0, #62040 ; 0xf258 + 3922: f24f 339d movw r3, #62365 ; 0xf39d + 3926: 2110 movs r1, #16 + 3928: f2c0 0300 movt r3, #0 + 392c: f2c0 0003 movt r0, #3 + 3930: 4798 blx r3 + 3932: e7e4 b.n 38fe + +00003934 : + 3934: b508 push {r3, lr} + 3936: f240 1300 movw r3, #256 ; 0x100 + 393a: f2c1 0300 movt r3, #4096 ; 0x1000 + 393e: 6c5b ldr r3, [r3, #68] ; 0x44 + 3940: b173 cbz r3, 3960 + 3942: f240 2200 movw r2, #512 ; 0x200 + 3946: f2c1 0200 movt r2, #4096 ; 0x1000 + 394a: 6c50 ldr r0, [r2, #68] ; 0x44 + 394c: 4798 blx r3 + 394e: f44f 4361 mov.w r3, #57600 ; 0xe100 + 3952: f2ce 0300 movt r3, #57344 ; 0xe000 + 3956: f44f 3200 mov.w r2, #131072 ; 0x20000 + 395a: f8c3 2180 str.w r2, [r3, #384] ; 0x180 + 395e: bd08 pop {r3, pc} + 3960: f240 3314 movw r3, #788 ; 0x314 + 3964: f2c1 0300 movt r3, #4096 ; 0x1000 + 3968: 681b ldr r3, [r3, #0] + 396a: 005b lsls r3, r3, #1 + 396c: d5ef bpl.n 394e + 396e: f24f 2058 movw r0, #62040 ; 0xf258 + 3972: f24f 339d movw r3, #62365 ; 0xf39d + 3976: 2111 movs r1, #17 + 3978: f2c0 0300 movt r3, #0 + 397c: f2c0 0003 movt r0, #3 + 3980: 4798 blx r3 + 3982: e7e4 b.n 394e + +00003984 : + 3984: b508 push {r3, lr} + 3986: f240 1300 movw r3, #256 ; 0x100 + 398a: f2c1 0300 movt r3, #4096 ; 0x1000 + 398e: 6c9b ldr r3, [r3, #72] ; 0x48 + 3990: b173 cbz r3, 39b0 + 3992: f240 2200 movw r2, #512 ; 0x200 + 3996: f2c1 0200 movt r2, #4096 ; 0x1000 + 399a: 6c90 ldr r0, [r2, #72] ; 0x48 + 399c: 4798 blx r3 + 399e: f44f 4361 mov.w r3, #57600 ; 0xe100 + 39a2: f2ce 0300 movt r3, #57344 ; 0xe000 + 39a6: f44f 2280 mov.w r2, #262144 ; 0x40000 + 39aa: f8c3 2180 str.w r2, [r3, #384] ; 0x180 + 39ae: bd08 pop {r3, pc} + 39b0: f240 3314 movw r3, #788 ; 0x314 + 39b4: f2c1 0300 movt r3, #4096 ; 0x1000 + 39b8: 681b ldr r3, [r3, #0] + 39ba: 005b lsls r3, r3, #1 + 39bc: d5ef bpl.n 399e + 39be: f24f 2058 movw r0, #62040 ; 0xf258 + 39c2: f24f 339d movw r3, #62365 ; 0xf39d + 39c6: 2112 movs r1, #18 + 39c8: f2c0 0300 movt r3, #0 + 39cc: f2c0 0003 movt r0, #3 + 39d0: 4798 blx r3 + 39d2: e7e4 b.n 399e + +000039d4 : + 39d4: b508 push {r3, lr} + 39d6: f240 1300 movw r3, #256 ; 0x100 + 39da: f2c1 0300 movt r3, #4096 ; 0x1000 + 39de: 6d1b ldr r3, [r3, #80] ; 0x50 + 39e0: b173 cbz r3, 3a00 + 39e2: f240 2200 movw r2, #512 ; 0x200 + 39e6: f2c1 0200 movt r2, #4096 ; 0x1000 + 39ea: 6d10 ldr r0, [r2, #80] ; 0x50 + 39ec: 4798 blx r3 + 39ee: f44f 4361 mov.w r3, #57600 ; 0xe100 + 39f2: f2ce 0300 movt r3, #57344 ; 0xe000 + 39f6: f44f 1280 mov.w r2, #1048576 ; 0x100000 + 39fa: f8c3 2180 str.w r2, [r3, #384] ; 0x180 + 39fe: bd08 pop {r3, pc} + 3a00: f240 3314 movw r3, #788 ; 0x314 + 3a04: f2c1 0300 movt r3, #4096 ; 0x1000 + 3a08: 681b ldr r3, [r3, #0] + 3a0a: 005b lsls r3, r3, #1 + 3a0c: d5ef bpl.n 39ee + 3a0e: f24f 2058 movw r0, #62040 ; 0xf258 + 3a12: f24f 339d movw r3, #62365 ; 0xf39d + 3a16: 2114 movs r1, #20 + 3a18: f2c0 0300 movt r3, #0 + 3a1c: f2c0 0003 movt r0, #3 + 3a20: 4798 blx r3 + 3a22: e7e4 b.n 39ee + +00003a24 : + 3a24: b508 push {r3, lr} + 3a26: f240 1300 movw r3, #256 ; 0x100 + 3a2a: f2c1 0300 movt r3, #4096 ; 0x1000 + 3a2e: 6d5b ldr r3, [r3, #84] ; 0x54 + 3a30: b173 cbz r3, 3a50 + 3a32: f240 2200 movw r2, #512 ; 0x200 + 3a36: f2c1 0200 movt r2, #4096 ; 0x1000 + 3a3a: 6d50 ldr r0, [r2, #84] ; 0x54 + 3a3c: 4798 blx r3 + 3a3e: f44f 4361 mov.w r3, #57600 ; 0xe100 + 3a42: f2ce 0300 movt r3, #57344 ; 0xe000 + 3a46: f44f 1200 mov.w r2, #2097152 ; 0x200000 + 3a4a: f8c3 2180 str.w r2, [r3, #384] ; 0x180 + 3a4e: bd08 pop {r3, pc} + 3a50: f240 3314 movw r3, #788 ; 0x314 + 3a54: f2c1 0300 movt r3, #4096 ; 0x1000 + 3a58: 681b ldr r3, [r3, #0] + 3a5a: 005b lsls r3, r3, #1 + 3a5c: d5ef bpl.n 3a3e + 3a5e: f24f 2058 movw r0, #62040 ; 0xf258 + 3a62: f24f 339d movw r3, #62365 ; 0xf39d + 3a66: 2115 movs r1, #21 + 3a68: f2c0 0300 movt r3, #0 + 3a6c: f2c0 0003 movt r0, #3 + 3a70: 4798 blx r3 + 3a72: e7e4 b.n 3a3e + +00003a74 : + 3a74: b508 push {r3, lr} + 3a76: f240 1300 movw r3, #256 ; 0x100 + 3a7a: f2c1 0300 movt r3, #4096 ; 0x1000 + 3a7e: 6d9b ldr r3, [r3, #88] ; 0x58 + 3a80: b173 cbz r3, 3aa0 + 3a82: f240 2200 movw r2, #512 ; 0x200 + 3a86: f2c1 0200 movt r2, #4096 ; 0x1000 + 3a8a: 6d90 ldr r0, [r2, #88] ; 0x58 + 3a8c: 4798 blx r3 + 3a8e: f44f 4361 mov.w r3, #57600 ; 0xe100 + 3a92: f2ce 0300 movt r3, #57344 ; 0xe000 + 3a96: f44f 0280 mov.w r2, #4194304 ; 0x400000 + 3a9a: f8c3 2180 str.w r2, [r3, #384] ; 0x180 + 3a9e: bd08 pop {r3, pc} + 3aa0: f240 3314 movw r3, #788 ; 0x314 + 3aa4: f2c1 0300 movt r3, #4096 ; 0x1000 + 3aa8: 681b ldr r3, [r3, #0] + 3aaa: 005b lsls r3, r3, #1 + 3aac: d5ef bpl.n 3a8e + 3aae: f24f 2058 movw r0, #62040 ; 0xf258 + 3ab2: f24f 339d movw r3, #62365 ; 0xf39d + 3ab6: 2116 movs r1, #22 + 3ab8: f2c0 0300 movt r3, #0 + 3abc: f2c0 0003 movt r0, #3 + 3ac0: 4798 blx r3 + 3ac2: e7e4 b.n 3a8e + +00003ac4 : + 3ac4: b508 push {r3, lr} + 3ac6: f240 1300 movw r3, #256 ; 0x100 + 3aca: f2c1 0300 movt r3, #4096 ; 0x1000 + 3ace: 6ddb ldr r3, [r3, #92] ; 0x5c + 3ad0: b173 cbz r3, 3af0 + 3ad2: f240 2200 movw r2, #512 ; 0x200 + 3ad6: f2c1 0200 movt r2, #4096 ; 0x1000 + 3ada: 6dd0 ldr r0, [r2, #92] ; 0x5c + 3adc: 4798 blx r3 + 3ade: f44f 4361 mov.w r3, #57600 ; 0xe100 + 3ae2: f2ce 0300 movt r3, #57344 ; 0xe000 + 3ae6: f44f 0200 mov.w r2, #8388608 ; 0x800000 + 3aea: f8c3 2180 str.w r2, [r3, #384] ; 0x180 + 3aee: bd08 pop {r3, pc} + 3af0: f240 3314 movw r3, #788 ; 0x314 + 3af4: f2c1 0300 movt r3, #4096 ; 0x1000 + 3af8: 681b ldr r3, [r3, #0] + 3afa: 005b lsls r3, r3, #1 + 3afc: d5ef bpl.n 3ade + 3afe: f24f 2058 movw r0, #62040 ; 0xf258 + 3b02: f24f 339d movw r3, #62365 ; 0xf39d + 3b06: 2117 movs r1, #23 + 3b08: f2c0 0300 movt r3, #0 + 3b0c: f2c0 0003 movt r0, #3 + 3b10: 4798 blx r3 + 3b12: e7e4 b.n 3ade + +00003b14 : + 3b14: b508 push {r3, lr} + 3b16: f240 1300 movw r3, #256 ; 0x100 + 3b1a: f2c1 0300 movt r3, #4096 ; 0x1000 + 3b1e: 6e1b ldr r3, [r3, #96] ; 0x60 + 3b20: b173 cbz r3, 3b40 + 3b22: f240 2200 movw r2, #512 ; 0x200 + 3b26: f2c1 0200 movt r2, #4096 ; 0x1000 + 3b2a: 6e10 ldr r0, [r2, #96] ; 0x60 + 3b2c: 4798 blx r3 + 3b2e: f44f 4361 mov.w r3, #57600 ; 0xe100 + 3b32: f2ce 0300 movt r3, #57344 ; 0xe000 + 3b36: f04f 7280 mov.w r2, #16777216 ; 0x1000000 + 3b3a: f8c3 2180 str.w r2, [r3, #384] ; 0x180 + 3b3e: bd08 pop {r3, pc} + 3b40: f240 3314 movw r3, #788 ; 0x314 + 3b44: f2c1 0300 movt r3, #4096 ; 0x1000 + 3b48: 681b ldr r3, [r3, #0] + 3b4a: 005b lsls r3, r3, #1 + 3b4c: d5ef bpl.n 3b2e + 3b4e: f24f 2058 movw r0, #62040 ; 0xf258 + 3b52: f24f 339d movw r3, #62365 ; 0xf39d + 3b56: 2118 movs r1, #24 + 3b58: f2c0 0300 movt r3, #0 + 3b5c: f2c0 0003 movt r0, #3 + 3b60: 4798 blx r3 + 3b62: e7e4 b.n 3b2e + +00003b64 : + 3b64: b508 push {r3, lr} + 3b66: f240 1300 movw r3, #256 ; 0x100 + 3b6a: f2c1 0300 movt r3, #4096 ; 0x1000 + 3b6e: 6e5b ldr r3, [r3, #100] ; 0x64 + 3b70: b173 cbz r3, 3b90 + 3b72: f240 2200 movw r2, #512 ; 0x200 + 3b76: f2c1 0200 movt r2, #4096 ; 0x1000 + 3b7a: 6e50 ldr r0, [r2, #100] ; 0x64 + 3b7c: 4798 blx r3 + 3b7e: f44f 4361 mov.w r3, #57600 ; 0xe100 + 3b82: f2ce 0300 movt r3, #57344 ; 0xe000 + 3b86: f04f 7200 mov.w r2, #33554432 ; 0x2000000 + 3b8a: f8c3 2180 str.w r2, [r3, #384] ; 0x180 + 3b8e: bd08 pop {r3, pc} + 3b90: f240 3314 movw r3, #788 ; 0x314 + 3b94: f2c1 0300 movt r3, #4096 ; 0x1000 + 3b98: 681b ldr r3, [r3, #0] + 3b9a: 005b lsls r3, r3, #1 + 3b9c: d5ef bpl.n 3b7e + 3b9e: f24f 2058 movw r0, #62040 ; 0xf258 + 3ba2: f24f 339d movw r3, #62365 ; 0xf39d + 3ba6: 2119 movs r1, #25 + 3ba8: f2c0 0300 movt r3, #0 + 3bac: f2c0 0003 movt r0, #3 + 3bb0: 4798 blx r3 + 3bb2: e7e4 b.n 3b7e + +00003bb4 : + 3bb4: b508 push {r3, lr} + 3bb6: f240 1300 movw r3, #256 ; 0x100 + 3bba: f2c1 0300 movt r3, #4096 ; 0x1000 + 3bbe: 6e9b ldr r3, [r3, #104] ; 0x68 + 3bc0: b173 cbz r3, 3be0 + 3bc2: f240 2200 movw r2, #512 ; 0x200 + 3bc6: f2c1 0200 movt r2, #4096 ; 0x1000 + 3bca: 6e90 ldr r0, [r2, #104] ; 0x68 + 3bcc: 4798 blx r3 + 3bce: f44f 4361 mov.w r3, #57600 ; 0xe100 + 3bd2: f2ce 0300 movt r3, #57344 ; 0xe000 + 3bd6: f04f 6280 mov.w r2, #67108864 ; 0x4000000 + 3bda: f8c3 2180 str.w r2, [r3, #384] ; 0x180 + 3bde: bd08 pop {r3, pc} + 3be0: f240 3314 movw r3, #788 ; 0x314 + 3be4: f2c1 0300 movt r3, #4096 ; 0x1000 + 3be8: 681b ldr r3, [r3, #0] + 3bea: 005b lsls r3, r3, #1 + 3bec: d5ef bpl.n 3bce + 3bee: f24f 2058 movw r0, #62040 ; 0xf258 + 3bf2: f24f 339d movw r3, #62365 ; 0xf39d + 3bf6: 211a movs r1, #26 + 3bf8: f2c0 0300 movt r3, #0 + 3bfc: f2c0 0003 movt r0, #3 + 3c00: 4798 blx r3 + 3c02: e7e4 b.n 3bce + +00003c04 : + 3c04: b508 push {r3, lr} + 3c06: f240 1300 movw r3, #256 ; 0x100 + 3c0a: f2c1 0300 movt r3, #4096 ; 0x1000 + 3c0e: 6edb ldr r3, [r3, #108] ; 0x6c + 3c10: b173 cbz r3, 3c30 + 3c12: f240 2200 movw r2, #512 ; 0x200 + 3c16: f2c1 0200 movt r2, #4096 ; 0x1000 + 3c1a: 6ed0 ldr r0, [r2, #108] ; 0x6c + 3c1c: 4798 blx r3 + 3c1e: f44f 4361 mov.w r3, #57600 ; 0xe100 + 3c22: f2ce 0300 movt r3, #57344 ; 0xe000 + 3c26: f04f 6200 mov.w r2, #134217728 ; 0x8000000 + 3c2a: f8c3 2180 str.w r2, [r3, #384] ; 0x180 + 3c2e: bd08 pop {r3, pc} + 3c30: f240 3314 movw r3, #788 ; 0x314 + 3c34: f2c1 0300 movt r3, #4096 ; 0x1000 + 3c38: 681b ldr r3, [r3, #0] + 3c3a: 005b lsls r3, r3, #1 + 3c3c: d5ef bpl.n 3c1e + 3c3e: f24f 2058 movw r0, #62040 ; 0xf258 + 3c42: f24f 339d movw r3, #62365 ; 0xf39d + 3c46: 211b movs r1, #27 + 3c48: f2c0 0300 movt r3, #0 + 3c4c: f2c0 0003 movt r0, #3 + 3c50: 4798 blx r3 + 3c52: e7e4 b.n 3c1e + +00003c54 : + 3c54: b508 push {r3, lr} + 3c56: f240 1300 movw r3, #256 ; 0x100 + 3c5a: f2c1 0300 movt r3, #4096 ; 0x1000 + 3c5e: 6f1b ldr r3, [r3, #112] ; 0x70 + 3c60: b173 cbz r3, 3c80 + 3c62: f240 2200 movw r2, #512 ; 0x200 + 3c66: f2c1 0200 movt r2, #4096 ; 0x1000 + 3c6a: 6f10 ldr r0, [r2, #112] ; 0x70 + 3c6c: 4798 blx r3 + 3c6e: f44f 4361 mov.w r3, #57600 ; 0xe100 + 3c72: f2ce 0300 movt r3, #57344 ; 0xe000 + 3c76: f04f 5280 mov.w r2, #268435456 ; 0x10000000 + 3c7a: f8c3 2180 str.w r2, [r3, #384] ; 0x180 + 3c7e: bd08 pop {r3, pc} + 3c80: f240 3314 movw r3, #788 ; 0x314 + 3c84: f2c1 0300 movt r3, #4096 ; 0x1000 + 3c88: 681b ldr r3, [r3, #0] + 3c8a: 005b lsls r3, r3, #1 + 3c8c: d5ef bpl.n 3c6e + 3c8e: f24f 2058 movw r0, #62040 ; 0xf258 + 3c92: f24f 339d movw r3, #62365 ; 0xf39d + 3c96: 211c movs r1, #28 + 3c98: f2c0 0300 movt r3, #0 + 3c9c: f2c0 0003 movt r0, #3 + 3ca0: 4798 blx r3 + 3ca2: e7e4 b.n 3c6e + +00003ca4 : + 3ca4: b508 push {r3, lr} + 3ca6: f240 1300 movw r3, #256 ; 0x100 + 3caa: f2c1 0300 movt r3, #4096 ; 0x1000 + 3cae: 6f5b ldr r3, [r3, #116] ; 0x74 + 3cb0: b173 cbz r3, 3cd0 + 3cb2: f240 2200 movw r2, #512 ; 0x200 + 3cb6: f2c1 0200 movt r2, #4096 ; 0x1000 + 3cba: 6f50 ldr r0, [r2, #116] ; 0x74 + 3cbc: 4798 blx r3 + 3cbe: f44f 4361 mov.w r3, #57600 ; 0xe100 + 3cc2: f2ce 0300 movt r3, #57344 ; 0xe000 + 3cc6: f04f 5200 mov.w r2, #536870912 ; 0x20000000 + 3cca: f8c3 2180 str.w r2, [r3, #384] ; 0x180 + 3cce: bd08 pop {r3, pc} + 3cd0: f240 3314 movw r3, #788 ; 0x314 + 3cd4: f2c1 0300 movt r3, #4096 ; 0x1000 + 3cd8: 681b ldr r3, [r3, #0] + 3cda: 005b lsls r3, r3, #1 + 3cdc: d5ef bpl.n 3cbe + 3cde: f24f 2058 movw r0, #62040 ; 0xf258 + 3ce2: f24f 339d movw r3, #62365 ; 0xf39d + 3ce6: 211d movs r1, #29 + 3ce8: f2c0 0300 movt r3, #0 + 3cec: f2c0 0003 movt r0, #3 + 3cf0: 4798 blx r3 + 3cf2: e7e4 b.n 3cbe + +00003cf4 : + 3cf4: b508 push {r3, lr} + 3cf6: f240 1300 movw r3, #256 ; 0x100 + 3cfa: f2c1 0300 movt r3, #4096 ; 0x1000 + 3cfe: 6f9b ldr r3, [r3, #120] ; 0x78 + 3d00: b173 cbz r3, 3d20 + 3d02: f240 2200 movw r2, #512 ; 0x200 + 3d06: f2c1 0200 movt r2, #4096 ; 0x1000 + 3d0a: 6f90 ldr r0, [r2, #120] ; 0x78 + 3d0c: 4798 blx r3 + 3d0e: f44f 4361 mov.w r3, #57600 ; 0xe100 + 3d12: f2ce 0300 movt r3, #57344 ; 0xe000 + 3d16: f04f 4280 mov.w r2, #1073741824 ; 0x40000000 + 3d1a: f8c3 2180 str.w r2, [r3, #384] ; 0x180 + 3d1e: bd08 pop {r3, pc} + 3d20: f240 3314 movw r3, #788 ; 0x314 + 3d24: f2c1 0300 movt r3, #4096 ; 0x1000 + 3d28: 681b ldr r3, [r3, #0] + 3d2a: 005b lsls r3, r3, #1 + 3d2c: d5ef bpl.n 3d0e + 3d2e: f24f 2058 movw r0, #62040 ; 0xf258 + 3d32: f24f 339d movw r3, #62365 ; 0xf39d + 3d36: 211e movs r1, #30 + 3d38: f2c0 0300 movt r3, #0 + 3d3c: f2c0 0003 movt r0, #3 + 3d40: 4798 blx r3 + 3d42: e7e4 b.n 3d0e + +00003d44 : + 3d44: b508 push {r3, lr} + 3d46: f240 1300 movw r3, #256 ; 0x100 + 3d4a: f2c1 0300 movt r3, #4096 ; 0x1000 + 3d4e: 6fdb ldr r3, [r3, #124] ; 0x7c + 3d50: b173 cbz r3, 3d70 + 3d52: f240 2200 movw r2, #512 ; 0x200 + 3d56: f2c1 0200 movt r2, #4096 ; 0x1000 + 3d5a: 6fd0 ldr r0, [r2, #124] ; 0x7c + 3d5c: 4798 blx r3 + 3d5e: f44f 4361 mov.w r3, #57600 ; 0xe100 + 3d62: f2ce 0300 movt r3, #57344 ; 0xe000 + 3d66: f04f 4200 mov.w r2, #2147483648 ; 0x80000000 + 3d6a: f8c3 2180 str.w r2, [r3, #384] ; 0x180 + 3d6e: bd08 pop {r3, pc} + 3d70: f240 3314 movw r3, #788 ; 0x314 + 3d74: f2c1 0300 movt r3, #4096 ; 0x1000 + 3d78: 681b ldr r3, [r3, #0] + 3d7a: 005b lsls r3, r3, #1 + 3d7c: d5ef bpl.n 3d5e + 3d7e: f24f 2058 movw r0, #62040 ; 0xf258 + 3d82: f24f 339d movw r3, #62365 ; 0xf39d + 3d86: 211f movs r1, #31 + 3d88: f2c0 0300 movt r3, #0 + 3d8c: f2c0 0003 movt r0, #3 + 3d90: 4798 blx r3 + 3d92: e7e4 b.n 3d5e + +00003d94 : + 3d94: f240 1300 movw r3, #256 ; 0x100 + 3d98: f2c1 0300 movt r3, #4096 ; 0x1000 + 3d9c: f44f 4261 mov.w r2, #57600 ; 0xe100 + 3da0: f2ce 0200 movt r2, #57344 ; 0xe000 + 3da4: 6b1b ldr r3, [r3, #48] ; 0x30 + 3da6: f44f 5180 mov.w r1, #4096 ; 0x1000 + 3daa: f8c2 1180 str.w r1, [r2, #384] ; 0x180 + 3dae: b12b cbz r3, 3dbc + 3db0: f240 2200 movw r2, #512 ; 0x200 + 3db4: f2c1 0200 movt r2, #4096 ; 0x1000 + 3db8: 6b10 ldr r0, [r2, #48] ; 0x30 + 3dba: 4718 bx r3 + 3dbc: f240 3314 movw r3, #788 ; 0x314 + 3dc0: f2c1 0300 movt r3, #4096 ; 0x1000 + 3dc4: 681b ldr r3, [r3, #0] + 3dc6: 005b lsls r3, r3, #1 + 3dc8: d400 bmi.n 3dcc + 3dca: 4770 bx lr + 3dcc: f24f 2058 movw r0, #62040 ; 0xf258 + 3dd0: f24f 339d movw r3, #62365 ; 0xf39d + 3dd4: b510 push {r4, lr} + 3dd6: f2c0 0300 movt r3, #0 + 3dda: 210c movs r1, #12 + 3ddc: f2c0 0003 movt r0, #3 + 3de0: 4798 blx r3 + 3de2: bd10 pop {r4, pc} + +00003de4 : + 3de4: f243 6365 movw r3, #13925 ; 0x3665 + 3de8: f2c0 0300 movt r3, #0 + 3dec: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 3df0: b09b sub sp, #108 ; 0x6c + 3df2: 9302 str r3, [sp, #8] + 3df4: f243 63b5 movw r3, #14005 ; 0x36b5 + 3df8: f2c0 0300 movt r3, #0 + 3dfc: 9303 str r3, [sp, #12] + 3dfe: f243 7305 movw r3, #14085 ; 0x3705 + 3e02: f2c0 0300 movt r3, #0 + 3e06: 9304 str r3, [sp, #16] + 3e08: f243 7355 movw r3, #14165 ; 0x3755 + 3e0c: f2c0 0300 movt r3, #0 + 3e10: 9305 str r3, [sp, #20] + 3e12: f243 73a5 movw r3, #14245 ; 0x37a5 + 3e16: f2c0 0300 movt r3, #0 + 3e1a: 9306 str r3, [sp, #24] + 3e1c: f643 5395 movw r3, #15765 ; 0x3d95 + 3e20: f2c0 0300 movt r3, #0 + 3e24: 9307 str r3, [sp, #28] + 3e26: f243 73f5 movw r3, #14325 ; 0x37f5 + 3e2a: f2c0 0300 movt r3, #0 + 3e2e: 9308 str r3, [sp, #32] + 3e30: f643 0345 movw r3, #14405 ; 0x3845 + 3e34: f2c0 0300 movt r3, #0 + 3e38: 9309 str r3, [sp, #36] ; 0x24 + 3e3a: f643 0395 movw r3, #14485 ; 0x3895 + 3e3e: f2c0 0300 movt r3, #0 + 3e42: 930a str r3, [sp, #40] ; 0x28 + 3e44: f643 03e5 movw r3, #14565 ; 0x38e5 + 3e48: f2c0 0300 movt r3, #0 + 3e4c: 930b str r3, [sp, #44] ; 0x2c + 3e4e: f643 1335 movw r3, #14645 ; 0x3935 + 3e52: f2c0 0300 movt r3, #0 + 3e56: 930c str r3, [sp, #48] ; 0x30 + 3e58: f643 1385 movw r3, #14725 ; 0x3985 + 3e5c: f2c0 0300 movt r3, #0 + 3e60: 930d str r3, [sp, #52] ; 0x34 + 3e62: f243 33b5 movw r3, #13237 ; 0x33b5 + 3e66: f2c0 0300 movt r3, #0 + 3e6a: 930e str r3, [sp, #56] ; 0x38 + 3e6c: f643 13d5 movw r3, #14805 ; 0x39d5 + 3e70: f2c0 0300 movt r3, #0 + 3e74: 930f str r3, [sp, #60] ; 0x3c + 3e76: f643 2325 movw r3, #14885 ; 0x3a25 + 3e7a: f2c0 0300 movt r3, #0 + 3e7e: 9310 str r3, [sp, #64] ; 0x40 + 3e80: f643 2375 movw r3, #14965 ; 0x3a75 + 3e84: f2c0 0300 movt r3, #0 + 3e88: 9311 str r3, [sp, #68] ; 0x44 + 3e8a: f643 23c5 movw r3, #15045 ; 0x3ac5 + 3e8e: f2c0 0300 movt r3, #0 + 3e92: 9312 str r3, [sp, #72] ; 0x48 + 3e94: f643 3315 movw r3, #15125 ; 0x3b15 + 3e98: f2c0 0300 movt r3, #0 + 3e9c: 9313 str r3, [sp, #76] ; 0x4c + 3e9e: f643 3365 movw r3, #15205 ; 0x3b65 + 3ea2: f2c0 0300 movt r3, #0 + 3ea6: 9314 str r3, [sp, #80] ; 0x50 + 3ea8: f643 33b5 movw r3, #15285 ; 0x3bb5 + 3eac: f2c0 0300 movt r3, #0 + 3eb0: 9315 str r3, [sp, #84] ; 0x54 + 3eb2: f643 4305 movw r3, #15365 ; 0x3c05 + 3eb6: f2c0 0300 movt r3, #0 + 3eba: 9316 str r3, [sp, #88] ; 0x58 + 3ebc: f643 4355 movw r3, #15445 ; 0x3c55 + 3ec0: f2c0 0300 movt r3, #0 + 3ec4: 9317 str r3, [sp, #92] ; 0x5c + 3ec6: f643 43a5 movw r3, #15525 ; 0x3ca5 + 3eca: f2c0 0300 movt r3, #0 + 3ece: 9318 str r3, [sp, #96] ; 0x60 + 3ed0: f643 43f5 movw r3, #15605 ; 0x3cf5 + 3ed4: f240 0500 movw r5, #0 + 3ed8: f243 4a39 movw sl, #13369 ; 0x3439 + 3edc: f2c0 0300 movt r3, #0 + 3ee0: f2c1 0500 movt r5, #4096 ; 0x1000 + 3ee4: f243 4985 movw r9, #13445 ; 0x3485 + 3ee8: f243 48d5 movw r8, #13525 ; 0x34d5 + 3eec: f243 5c25 movw ip, #13605 ; 0x3525 + 3ef0: f243 5e75 movw lr, #13685 ; 0x3575 + 3ef4: f243 57c5 movw r7, #13765 ; 0x35c5 + 3ef8: f243 6615 movw r6, #13845 ; 0x3615 + 3efc: f2c0 0a00 movt sl, #0 + 3f00: 9319 str r3, [sp, #100] ; 0x64 + 3f02: 2300 movs r3, #0 + 3f04: 9301 str r3, [sp, #4] + 3f06: 461a mov r2, r3 + 3f08: 2304 movs r3, #4 + 3f0a: 681b ldr r3, [r3, #0] + 3f0c: f2c0 0900 movt r9, #0 + 3f10: e885 0009 stmia.w r5, {r0, r3} + 3f14: 2008 movs r0, #8 + 3f16: 6800 ldr r0, [r0, #0] + 3f18: f2c0 0800 movt r8, #0 + 3f1c: f2c0 0c00 movt ip, #0 + 3f20: f2c0 0e00 movt lr, #0 + 3f24: f2c0 0700 movt r7, #0 + 3f28: f2c0 0600 movt r6, #0 + 3f2c: 60a8 str r0, [r5, #8] + 3f2e: 200c movs r0, #12 + 3f30: 6800 ldr r0, [r0, #0] + 3f32: f8c5 a040 str.w sl, [r5, #64] ; 0x40 + 3f36: 60e8 str r0, [r5, #12] + 3f38: 9b02 ldr r3, [sp, #8] + 3f3a: f643 5b45 movw fp, #15685 ; 0x3d45 + 3f3e: 65eb str r3, [r5, #92] ; 0x5c + 3f40: 9b03 ldr r3, [sp, #12] + 3f42: f240 1400 movw r4, #256 ; 0x100 + 3f46: 662b str r3, [r5, #96] ; 0x60 + 3f48: 9b04 ldr r3, [sp, #16] + 3f4a: f240 2100 movw r1, #512 ; 0x200 + 3f4e: 666b str r3, [r5, #100] ; 0x64 + 3f50: 9b05 ldr r3, [sp, #20] + 3f52: f8c5 9044 str.w r9, [r5, #68] ; 0x44 + 3f56: 66ab str r3, [r5, #104] ; 0x68 + 3f58: 9b06 ldr r3, [sp, #24] + 3f5a: f8c5 8048 str.w r8, [r5, #72] ; 0x48 + 3f5e: 66eb str r3, [r5, #108] ; 0x6c + 3f60: 9b07 ldr r3, [sp, #28] + 3f62: f8c5 c04c str.w ip, [r5, #76] ; 0x4c + 3f66: 672b str r3, [r5, #112] ; 0x70 + 3f68: 9b08 ldr r3, [sp, #32] + 3f6a: f8c5 e050 str.w lr, [r5, #80] ; 0x50 + 3f6e: 676b str r3, [r5, #116] ; 0x74 + 3f70: 9b09 ldr r3, [sp, #36] ; 0x24 + 3f72: 656f str r7, [r5, #84] ; 0x54 + 3f74: 67ab str r3, [r5, #120] ; 0x78 + 3f76: 9b0a ldr r3, [sp, #40] ; 0x28 + 3f78: 65ae str r6, [r5, #88] ; 0x58 + 3f7a: 67eb str r3, [r5, #124] ; 0x7c + 3f7c: 9b0b ldr r3, [sp, #44] ; 0x2c + 3f7e: f2c0 0b00 movt fp, #0 + 3f82: f8c5 3080 str.w r3, [r5, #128] ; 0x80 + 3f86: 9b0c ldr r3, [sp, #48] ; 0x30 + 3f88: f2c1 0400 movt r4, #4096 ; 0x1000 + 3f8c: f8c5 3084 str.w r3, [r5, #132] ; 0x84 + 3f90: 9b0d ldr r3, [sp, #52] ; 0x34 + 3f92: f2c1 0100 movt r1, #4096 ; 0x1000 + 3f96: f8c5 3088 str.w r3, [r5, #136] ; 0x88 + 3f9a: 9b0e ldr r3, [sp, #56] ; 0x38 + 3f9c: f8c5 308c str.w r3, [r5, #140] ; 0x8c + 3fa0: 9b0f ldr r3, [sp, #60] ; 0x3c + 3fa2: f8c5 3090 str.w r3, [r5, #144] ; 0x90 + 3fa6: 9b10 ldr r3, [sp, #64] ; 0x40 + 3fa8: f8c5 b0bc str.w fp, [r5, #188] ; 0xbc + 3fac: f8c5 3094 str.w r3, [r5, #148] ; 0x94 + 3fb0: 9b11 ldr r3, [sp, #68] ; 0x44 + 3fb2: f8c5 3098 str.w r3, [r5, #152] ; 0x98 + 3fb6: 9b12 ldr r3, [sp, #72] ; 0x48 + 3fb8: f8c5 309c str.w r3, [r5, #156] ; 0x9c + 3fbc: 9b13 ldr r3, [sp, #76] ; 0x4c + 3fbe: f8c5 30a0 str.w r3, [r5, #160] ; 0xa0 + 3fc2: 9b14 ldr r3, [sp, #80] ; 0x50 + 3fc4: f8c5 30a4 str.w r3, [r5, #164] ; 0xa4 + 3fc8: 9b15 ldr r3, [sp, #84] ; 0x54 + 3fca: f8c5 30a8 str.w r3, [r5, #168] ; 0xa8 + 3fce: 9b16 ldr r3, [sp, #88] ; 0x58 + 3fd0: f8c5 30ac str.w r3, [r5, #172] ; 0xac + 3fd4: 9b17 ldr r3, [sp, #92] ; 0x5c + 3fd6: f8c5 30b0 str.w r3, [r5, #176] ; 0xb0 + 3fda: 9b18 ldr r3, [sp, #96] ; 0x60 + 3fdc: f8c5 30b4 str.w r3, [r5, #180] ; 0xb4 + 3fe0: 9b19 ldr r3, [sp, #100] ; 0x64 + 3fe2: f8c5 30b8 str.w r3, [r5, #184] ; 0xb8 + 3fe6: 4613 mov r3, r2 + 3fe8: 50e2 str r2, [r4, r3] + 3fea: 50ca str r2, [r1, r3] + 3fec: 3304 adds r3, #4 + 3fee: f5b3 7f80 cmp.w r3, #256 ; 0x100 + 3ff2: f04f 0000 mov.w r0, #0 + 3ff6: d1f7 bne.n 3fe8 + 3ff8: f642 0308 movw r3, #10248 ; 0x2808 + 3ffc: f44f 426d mov.w r2, #60672 ; 0xed00 + 4000: f2ce 0200 movt r2, #57344 ; 0xe000 + 4004: f2c4 0300 movt r3, #16384 ; 0x4000 + 4008: f04f 5180 mov.w r1, #268435456 ; 0x10000000 + 400c: 6091 str r1, [r2, #8] + 400e: 6018 str r0, [r3, #0] + 4010: b01b add sp, #108 ; 0x6c + 4012: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 4016: bf00 nop + +00004018 : + 4018: f240 0300 movw r3, #0 + 401c: f2c1 0300 movt r3, #4096 ; 0x1000 + 4020: 62d8 str r0, [r3, #44] ; 0x2c + 4022: 6399 str r1, [r3, #56] ; 0x38 + 4024: 63da str r2, [r3, #60] ; 0x3c + 4026: 4770 bx lr + +00004028 : + 4028: f240 1300 movw r3, #256 ; 0x100 + 402c: 6841 ldr r1, [r0, #4] + 402e: f2c1 0300 movt r3, #4096 ; 0x1000 + 4032: 293f cmp r1, #63 ; 0x3f + 4034: bfd4 ite le + 4036: 460a movle r2, r1 + 4038: f1a1 0220 subgt.w r2, r1, #32 + 403c: b510 push {r4, lr} + 403e: f853 4022 ldr.w r4, [r3, r2, lsl #2] + 4042: b15c cbz r4, 405c + 4044: f240 3314 movw r3, #788 ; 0x314 + 4048: f2c1 0300 movt r3, #4096 ; 0x1000 + 404c: f44f 5000 mov.w r0, #8192 ; 0x2000 + 4050: f2c4 0000 movt r0, #16384 ; 0x4000 + 4054: 681b ldr r3, [r3, #0] + 4056: 4018 ands r0, r3 + 4058: b970 cbnz r0, 4078 + 405a: bd10 pop {r4, pc} + 405c: f240 2100 movw r1, #512 ; 0x200 + 4060: f2c1 0100 movt r1, #4096 ; 0x1000 + 4064: 6804 ldr r4, [r0, #0] + 4066: 6880 ldr r0, [r0, #8] + 4068: f044 0401 orr.w r4, r4, #1 + 406c: f841 0022 str.w r0, [r1, r2, lsl #2] + 4070: f843 4022 str.w r4, [r3, r2, lsl #2] + 4074: 2001 movs r0, #1 + 4076: bd10 pop {r4, pc} + 4078: f24f 207c movw r0, #62076 ; 0xf27c + 407c: f24f 339d movw r3, #62365 ; 0xf39d + 4080: f2c0 0003 movt r0, #3 + 4084: f2c0 0300 movt r3, #0 + 4088: 4798 blx r3 + 408a: 2000 movs r0, #0 + 408c: bd10 pop {r4, pc} + 408e: bf00 nop + +00004090 : + 4090: f240 1300 movw r3, #256 ; 0x100 + 4094: 6841 ldr r1, [r0, #4] + 4096: f2c1 0300 movt r3, #4096 ; 0x1000 + 409a: 293f cmp r1, #63 ; 0x3f + 409c: bfd4 ite le + 409e: 460a movle r2, r1 + 40a0: f1a1 0220 subgt.w r2, r1, #32 + 40a4: b510 push {r4, lr} + 40a6: f853 4022 ldr.w r4, [r3, r2, lsl #2] + 40aa: b154 cbz r4, 40c2 + 40ac: f240 2100 movw r1, #512 ; 0x200 + 40b0: f2c1 0100 movt r1, #4096 ; 0x1000 + 40b4: 2000 movs r0, #0 + 40b6: f841 0022 str.w r0, [r1, r2, lsl #2] + 40ba: f843 0022 str.w r0, [r3, r2, lsl #2] + 40be: 2001 movs r0, #1 + 40c0: bd10 pop {r4, pc} + 40c2: f240 3314 movw r3, #788 ; 0x314 + 40c6: f2c1 0300 movt r3, #4096 ; 0x1000 + 40ca: f44f 5000 mov.w r0, #8192 ; 0x2000 + 40ce: f2c4 0000 movt r0, #16384 ; 0x4000 + 40d2: 681b ldr r3, [r3, #0] + 40d4: 4018 ands r0, r3 + 40d6: b900 cbnz r0, 40da + 40d8: bd10 pop {r4, pc} + 40da: f24f 20ac movw r0, #62124 ; 0xf2ac + 40de: f24f 339d movw r3, #62365 ; 0xf39d + 40e2: f2c0 0003 movt r0, #3 + 40e6: f2c0 0300 movt r3, #0 + 40ea: 4798 blx r3 + 40ec: 4620 mov r0, r4 + 40ee: e7f3 b.n 40d8 + +000040f0 : + 40f0: 6843 ldr r3, [r0, #4] + 40f2: b470 push {r4, r5, r6} + 40f4: 2b3f cmp r3, #63 ; 0x3f + 40f6: dd2b ble.n 4150 + 40f8: f642 0104 movw r1, #10244 ; 0x2804 + 40fc: f642 020c movw r2, #10252 ; 0x280c + 4100: f2c4 0100 movt r1, #16384 ; 0x4000 + 4104: f2c4 0200 movt r2, #16384 ; 0x4000 + 4108: f44f 4461 mov.w r4, #57600 ; 0xe100 + 410c: f2ce 0400 movt r4, #57344 ; 0xe000 + 4110: 680d ldr r5, [r1, #0] + 4112: 3b40 subs r3, #64 ; 0x40 + 4114: 600d str r5, [r1, #0] + 4116: 6811 ldr r1, [r2, #0] + 4118: 2501 movs r5, #1 + 411a: fa05 f303 lsl.w r3, r5, r3 + 411e: 430b orrs r3, r1 + 4120: f44f 2100 mov.w r1, #524288 ; 0x80000 + 4124: 6013 str r3, [r2, #0] + 4126: f8c4 1180 str.w r1, [r4, #384] ; 0x180 + 412a: 68c0 ldr r0, [r0, #12] + 412c: 2200 movs r2, #0 + 412e: 2413 movs r4, #19 + 4130: 0100 lsls r0, r0, #4 + 4132: f104 4360 add.w r3, r4, #3758096384 ; 0xe0000000 + 4136: b2c0 uxtb r0, r0 + 4138: f503 4361 add.w r3, r3, #57600 ; 0xe100 + 413c: f883 0300 strb.w r0, [r3, #768] ; 0x300 + 4140: f44f 4361 mov.w r3, #57600 ; 0xe100 + 4144: f2ce 0300 movt r3, #57344 ; 0xe000 + 4148: bc70 pop {r4, r5, r6} + 414a: f843 1022 str.w r1, [r3, r2, lsl #2] + 414e: 4770 bx lr + 4150: f44f 4461 mov.w r4, #57600 ; 0xe100 + 4154: f2ce 0400 movt r4, #57344 ; 0xe000 + 4158: 095a lsrs r2, r3, #5 + 415a: f003 011f and.w r1, r3, #31 + 415e: 2601 movs r6, #1 + 4160: f102 0560 add.w r5, r2, #96 ; 0x60 + 4164: fa06 f101 lsl.w r1, r6, r1 + 4168: f844 1025 str.w r1, [r4, r5, lsl #2] + 416c: 2b00 cmp r3, #0 + 416e: 68c0 ldr r0, [r0, #12] + 4170: 461c mov r4, r3 + 4172: dadd bge.n 4130 + 4174: f64e 44fc movw r4, #60668 ; 0xecfc + 4178: f2ce 0400 movt r4, #57344 ; 0xe000 + 417c: f003 030f and.w r3, r3, #15 + 4180: 0100 lsls r0, r0, #4 + 4182: b2c0 uxtb r0, r0 + 4184: 441c add r4, r3 + 4186: 7620 strb r0, [r4, #24] + 4188: e7da b.n 4140 + 418a: bf00 nop + +0000418c : + 418c: 6842 ldr r2, [r0, #4] + 418e: 2a3f cmp r2, #63 ; 0x3f + 4190: dd16 ble.n 41c0 + 4192: f642 010c movw r1, #10252 ; 0x280c + 4196: f2c4 0100 movt r1, #16384 ; 0x4000 + 419a: 2301 movs r3, #1 + 419c: 6808 ldr r0, [r1, #0] + 419e: 3a40 subs r2, #64 ; 0x40 + 41a0: fa03 f202 lsl.w r2, r3, r2 + 41a4: 4b20 ldr r3, [pc, #128] ; (4228 ) + 41a6: ea20 0202 bic.w r2, r0, r2 + 41aa: 600a str r2, [r1, #0] + 41ac: f503 7180 add.w r1, r3, #256 ; 0x100 + 41b0: e001 b.n 41b6 + 41b2: 428b cmp r3, r1 + 41b4: d034 beq.n 4220 + 41b6: f853 2f04 ldr.w r2, [r3, #4]! + 41ba: 2a00 cmp r2, #0 + 41bc: d0f9 beq.n 41b2 + 41be: 4770 bx lr + 41c0: 1e13 subs r3, r2, #0 + 41c2: db13 blt.n 41ec + 41c4: f003 021f and.w r2, r3, #31 + 41c8: 2101 movs r1, #1 + 41ca: 4091 lsls r1, r2 + 41cc: 095a lsrs r2, r3, #5 + 41ce: f103 4360 add.w r3, r3, #3758096384 ; 0xe0000000 + 41d2: f503 4361 add.w r3, r3, #57600 ; 0xe100 + 41d6: 2000 movs r0, #0 + 41d8: f883 0300 strb.w r0, [r3, #768] ; 0x300 + 41dc: f44f 4361 mov.w r3, #57600 ; 0xe100 + 41e0: f2ce 0300 movt r3, #57344 ; 0xe000 + 41e4: 3220 adds r2, #32 + 41e6: f843 1022 str.w r1, [r3, r2, lsl #2] + 41ea: 4770 bx lr + 41ec: f64e 43fc movw r3, #60668 ; 0xecfc + 41f0: f2ce 0300 movt r3, #57344 ; 0xe000 + 41f4: f002 010f and.w r1, r2, #15 + 41f8: b410 push {r4} + 41fa: 440b add r3, r1 + 41fc: 2400 movs r4, #0 + 41fe: 761c strb r4, [r3, #24] + 4200: f44f 4361 mov.w r3, #57600 ; 0xe100 + 4204: f2ce 0300 movt r3, #57344 ; 0xe000 + 4208: f002 011f and.w r1, r2, #31 + 420c: 2001 movs r0, #1 + 420e: 0952 lsrs r2, r2, #5 + 4210: fa00 f101 lsl.w r1, r0, r1 + 4214: 3220 adds r2, #32 + 4216: f843 1022 str.w r1, [r3, r2, lsl #2] + 421a: f85d 4b04 ldr.w r4, [sp], #4 + 421e: 4770 bx lr + 4220: f44f 2100 mov.w r1, #524288 ; 0x80000 + 4224: 2313 movs r3, #19 + 4226: e7d2 b.n 41ce + 4228: 100000fc .word 0x100000fc + +0000422c <_UartRxDmaIrqHandle>: + 422c: b570 push {r4, r5, r6, lr} + 422e: 4604 mov r4, r0 + 4230: 6c43 ldr r3, [r0, #68] ; 0x44 + 4232: 68dd ldr r5, [r3, #12] + 4234: 685e ldr r6, [r3, #4] + 4236: 4628 mov r0, r5 + 4238: 6a33 ldr r3, [r6, #32] + 423a: 4798 blx r3 + 423c: 69f3 ldr r3, [r6, #28] + 423e: 4628 mov r0, r5 + 4240: 4798 blx r3 + 4242: 6933 ldr r3, [r6, #16] + 4244: 4628 mov r0, r5 + 4246: 4798 blx r3 + 4248: f894 3026 ldrb.w r3, [r4, #38] ; 0x26 + 424c: f894 1024 ldrb.w r1, [r4, #36] ; 0x24 + 4250: f503 1380 add.w r3, r3, #1048576 ; 0x100000 + 4254: f503 7380 add.w r3, r3, #256 ; 0x100 + 4258: 029b lsls r3, r3, #10 + 425a: 695a ldr r2, [r3, #20] + 425c: 6a23 ldr r3, [r4, #32] + 425e: f022 0261 bic.w r2, r2, #97 ; 0x61 + 4262: 2b22 cmp r3, #34 ; 0x22 + 4264: bf0c ite eq + 4266: 2310 moveq r3, #16 + 4268: 2321 movne r3, #33 ; 0x21 + 426a: 6223 str r3, [r4, #32] + 426c: 6da3 ldr r3, [r4, #88] ; 0x58 + 426e: 430a orrs r2, r1 + 4270: f884 2024 strb.w r2, [r4, #36] ; 0x24 + 4274: b10b cbz r3, 427a <_UartRxDmaIrqHandle+0x4e> + 4276: 6ea0 ldr r0, [r4, #104] ; 0x68 + 4278: 4798 blx r3 + 427a: 2000 movs r0, #0 + 427c: bd70 pop {r4, r5, r6, pc} + 427e: bf00 nop + +00004280 : + 4280: f890 3026 ldrb.w r3, [r0, #38] ; 0x26 + 4284: f503 1380 add.w r3, r3, #1048576 ; 0x100000 + 4288: f503 7380 add.w r3, r3, #256 ; 0x100 + 428c: 029b lsls r3, r3, #10 + 428e: 695a ldr r2, [r3, #20] + 4290: 0652 lsls r2, r2, #25 + 4292: bf46 itte mi + 4294: 2000 movmi r0, #0 + 4296: 6259 strmi r1, [r3, #36] ; 0x24 + 4298: 2001 movpl r0, #1 + 429a: 4770 bx lr + +0000429c : + 429c: f890 3026 ldrb.w r3, [r0, #38] ; 0x26 + 42a0: f503 1380 add.w r3, r3, #1048576 ; 0x100000 + 42a4: f503 7380 add.w r3, r3, #256 ; 0x100 + 42a8: 029b lsls r3, r3, #10 + 42aa: 695a ldr r2, [r3, #20] + 42ac: 07d2 lsls r2, r2, #31 + 42ae: bf43 ittte mi + 42b0: 6a5b ldrmi r3, [r3, #36] ; 0x24 + 42b2: 2000 movmi r0, #0 + 42b4: 700b strbmi r3, [r1, #0] + 42b6: 2002 movpl r0, #2 + 42b8: 4770 bx lr + 42ba: bf00 nop + +000042bc : + 42bc: f890 3026 ldrb.w r3, [r0, #38] ; 0x26 + 42c0: f503 1380 add.w r3, r3, #1048576 ; 0x100000 + 42c4: f503 7380 add.w r3, r3, #256 ; 0x100 + 42c8: 029b lsls r3, r3, #10 + 42ca: 691a ldr r2, [r3, #16] + 42cc: b919 cbnz r1, 42d6 + 42ce: f022 0202 bic.w r2, r2, #2 + 42d2: 611a str r2, [r3, #16] + 42d4: 4770 bx lr + 42d6: f042 0202 orr.w r2, r2, #2 + 42da: 611a str r2, [r3, #16] + 42dc: 4770 bx lr + 42de: bf00 nop + +000042e0 : + 42e0: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} + 42e4: f240 3410 movw r4, #784 ; 0x310 + 42e8: f2c1 0400 movt r4, #4096 ; 0x1000 + 42ec: 6822 ldr r2, [r4, #0] + 42ee: f890 8026 ldrb.w r8, [r0, #38] ; 0x26 + 42f2: 0450 lsls r0, r2, #17 + 42f4: b082 sub sp, #8 + 42f6: 468a mov sl, r1 + 42f8: d41b bmi.n 4332 + 42fa: f508 1580 add.w r5, r8, #1048576 ; 0x100000 + 42fe: f505 7580 add.w r5, r5, #256 ; 0x100 + 4302: 02ad lsls r5, r5, #10 + 4304: 69ef ldr r7, [r5, #28] + 4306: f105 061c add.w r6, r5, #28 + 430a: f427 6770 bic.w r7, r7, #3840 ; 0xf00 + 430e: ea47 230a orr.w r3, r7, sl, lsl #8 + 4312: f240 3710 movw r7, #784 ; 0x310 + 4316: 6033 str r3, [r6, #0] + 4318: 6823 ldr r3, [r4, #0] + 431a: 6832 ldr r2, [r6, #0] + 431c: 0459 lsls r1, r3, #17 + 431e: f2c1 0700 movt r7, #4096 ; 0x1000 + 4322: bf58 it pl + 4324: 6833 ldrpl r3, [r6, #0] + 4326: d438 bmi.n 439a + 4328: 6bec ldr r4, [r5, #60] ; 0x3c + 432a: 4620 mov r0, r4 + 432c: b002 add sp, #8 + 432e: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + 4332: f24f 20dc movw r0, #62172 ; 0xf2dc + 4336: f24f 399d movw r9, #62365 ; 0xf39d + 433a: f2c0 0003 movt r0, #3 + 433e: f2c0 0900 movt r9, #0 + 4342: 47c8 blx r9 + 4344: f508 1580 add.w r5, r8, #1048576 ; 0x100000 + 4348: 6822 ldr r2, [r4, #0] + 434a: f505 7580 add.w r5, r5, #256 ; 0x100 + 434e: 02ad lsls r5, r5, #10 + 4350: 0452 lsls r2, r2, #17 + 4352: f105 061c add.w r6, r5, #28 + 4356: 69ef ldr r7, [r5, #28] + 4358: d5d7 bpl.n 430a + 435a: f24f 3000 movw r0, #62208 ; 0xf300 + 435e: 463a mov r2, r7 + 4360: 4641 mov r1, r8 + 4362: f2c0 0003 movt r0, #3 + 4366: 47c8 blx r9 + 4368: 6822 ldr r2, [r4, #0] + 436a: f427 6770 bic.w r7, r7, #3840 ; 0xf00 + 436e: 0453 lsls r3, r2, #17 + 4370: d5cd bpl.n 430e + 4372: f24f 3028 movw r0, #62248 ; 0xf328 + 4376: 4639 mov r1, r7 + 4378: f2c0 0003 movt r0, #3 + 437c: 47c8 blx r9 + 437e: 6822 ldr r2, [r4, #0] + 4380: ea47 230a orr.w r3, r7, sl, lsl #8 + 4384: 0450 lsls r0, r2, #17 + 4386: d5c4 bpl.n 4312 + 4388: f24f 3028 movw r0, #62248 ; 0xf328 + 438c: 4619 mov r1, r3 + 438e: f2c0 0003 movt r0, #3 + 4392: 9301 str r3, [sp, #4] + 4394: 47c8 blx r9 + 4396: 9b01 ldr r3, [sp, #4] + 4398: e7bb b.n 4312 + 439a: f24f 304c movw r0, #62284 ; 0xf34c + 439e: f24f 399d movw r9, #62365 ; 0xf39d + 43a2: f2c0 0003 movt r0, #3 + 43a6: f2c0 0900 movt r9, #0 + 43aa: 4641 mov r1, r8 + 43ac: 47c8 blx r9 + 43ae: 683b ldr r3, [r7, #0] + 43b0: 6836 ldr r6, [r6, #0] + 43b2: 045a lsls r2, r3, #17 + 43b4: f3c6 2603 ubfx r6, r6, #8, #4 + 43b8: d5b6 bpl.n 4328 + 43ba: f24f 20dc movw r0, #62172 ; 0xf2dc + 43be: 4631 mov r1, r6 + 43c0: f2c0 0003 movt r0, #3 + 43c4: 47c8 blx r9 + 43c6: 683b ldr r3, [r7, #0] + 43c8: 6bec ldr r4, [r5, #60] ; 0x3c + 43ca: 045b lsls r3, r3, #17 + 43cc: d5ad bpl.n 432a + 43ce: f24f 307c movw r0, #62332 ; 0xf37c + 43d2: 4641 mov r1, r8 + 43d4: 4632 mov r2, r6 + 43d6: 4623 mov r3, r4 + 43d8: f2c0 0003 movt r0, #3 + 43dc: 47c8 blx r9 + 43de: e7a4 b.n 432a + +000043e0 : + 43e0: f240 3310 movw r3, #784 ; 0x310 + 43e4: f2c1 0300 movt r3, #4096 ; 0x1000 + 43e8: b500 push {lr} + 43ea: f890 1026 ldrb.w r1, [r0, #38] ; 0x26 + 43ee: 681b ldr r3, [r3, #0] + 43f0: f501 1280 add.w r2, r1, #1048576 ; 0x100000 + 43f4: f502 7280 add.w r2, r2, #256 ; 0x100 + 43f8: 0292 lsls r2, r2, #10 + 43fa: 6852 ldr r2, [r2, #4] + 43fc: b083 sub sp, #12 + 43fe: b2d2 uxtb r2, r2 + 4400: 045b lsls r3, r3, #17 + 4402: f88d 2007 strb.w r2, [sp, #7] + 4406: d404 bmi.n 4412 + 4408: f89d 0007 ldrb.w r0, [sp, #7] + 440c: b003 add sp, #12 + 440e: f85d fb04 ldr.w pc, [sp], #4 + 4412: f24f 30b0 movw r0, #62384 ; 0xf3b0 + 4416: f24f 339d movw r3, #62365 ; 0xf39d + 441a: f89d 2007 ldrb.w r2, [sp, #7] + 441e: f2c0 0300 movt r3, #0 + 4422: f2c0 0003 movt r0, #3 + 4426: 4798 blx r3 + 4428: e7ee b.n 4408 + 442a: bf00 nop + +0000442c : + 442c: b508 push {r3, lr} + 442e: f240 3310 movw r3, #784 ; 0x310 + 4432: f2c1 0300 movt r3, #4096 ; 0x1000 + 4436: f890 1026 ldrb.w r1, [r0, #38] ; 0x26 + 443a: 7b02 ldrb r2, [r0, #12] + 443c: f501 1080 add.w r0, r1, #1048576 ; 0x100000 + 4440: f500 7080 add.w r0, r0, #256 ; 0x100 + 4444: 0280 lsls r0, r0, #10 + 4446: 6042 str r2, [r0, #4] + 4448: 681b ldr r3, [r3, #0] + 444a: 045b lsls r3, r3, #17 + 444c: d400 bmi.n 4450 + 444e: bd08 pop {r3, pc} + 4450: f24f 30d4 movw r0, #62420 ; 0xf3d4 + 4454: f24f 339d movw r3, #62365 ; 0xf39d + 4458: f2c0 0003 movt r0, #3 + 445c: f2c0 0300 movt r3, #0 + 4460: 4798 blx r3 + 4462: e7f4 b.n 444e + +00004464 <_UartIrqHandle>: + 4464: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 4468: f240 3914 movw r9, #788 ; 0x314 + 446c: f24f 389d movw r8, #62365 ; 0xf39d + 4470: f244 4a2d movw sl, #17453 ; 0x442d + 4474: 4683 mov fp, r0 + 4476: f2c1 0900 movt r9, #4096 ; 0x1000 + 447a: f2c0 0800 movt r8, #0 + 447e: f2c0 0a00 movt sl, #0 + 4482: f890 7026 ldrb.w r7, [r0, #38] ; 0x26 + 4486: b083 sub sp, #12 + 4488: f507 1780 add.w r7, r7, #1048576 ; 0x100000 + 448c: f507 7780 add.w r7, r7, #256 ; 0x100 + 4490: 02bf lsls r7, r7, #10 + 4492: 2405 movs r4, #5 + 4494: f107 0608 add.w r6, r7, #8 + 4498: 6832 ldr r2, [r6, #0] + 449a: b2d2 uxtb r2, r2 + 449c: f88d 2002 strb.w r2, [sp, #2] + 44a0: f89d 2002 ldrb.w r2, [sp, #2] + 44a4: 07d2 lsls r2, r2, #31 + 44a6: d415 bmi.n 44d4 <_UartIrqHandle+0x70> + 44a8: f89d 2002 ldrb.w r2, [sp, #2] + 44ac: f3c2 0242 ubfx r2, r2, #1, #3 + 44b0: 2a06 cmp r2, #6 + 44b2: d843 bhi.n 453c <_UartIrqHandle+0xd8> + 44b4: e8df f002 tbb [pc, r2] + 44b8: 04122a38 .word 0x04122a38 + 44bc: 4242 .short 0x4242 + 44be: 12 .byte 0x12 + 44bf: 00 .byte 0x00 + 44c0: 697a ldr r2, [r7, #20] + 44c2: f89b 1024 ldrb.w r1, [fp, #36] ; 0x24 + 44c6: f022 0261 bic.w r2, r2, #97 ; 0x61 + 44ca: 430a orrs r2, r1 + 44cc: f88b 2024 strb.w r2, [fp, #36] ; 0x24 + 44d0: 3c01 subs r4, #1 + 44d2: d1e1 bne.n 4498 <_UartIrqHandle+0x34> + 44d4: 2000 movs r0, #0 + 44d6: b003 add sp, #12 + 44d8: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 44dc: f8db 2020 ldr.w r2, [fp, #32] + 44e0: 3a22 subs r2, #34 ; 0x22 + 44e2: 2a01 cmp r2, #1 + 44e4: d96e bls.n 45c4 <_UartIrqHandle+0x160> + 44e6: f8db 2050 ldr.w r2, [fp, #80] ; 0x50 + 44ea: 2a00 cmp r2, #0 + 44ec: d0f0 beq.n 44d0 <_UartIrqHandle+0x6c> + 44ee: 6979 ldr r1, [r7, #20] + 44f0: f107 0514 add.w r5, r7, #20 + 44f4: 07c9 lsls r1, r1, #31 + 44f6: d5eb bpl.n 44d0 <_UartIrqHandle+0x6c> + 44f8: e001 b.n 44fe <_UartIrqHandle+0x9a> + 44fa: f8db 2050 ldr.w r2, [fp, #80] ; 0x50 + 44fe: f8db 0060 ldr.w r0, [fp, #96] ; 0x60 + 4502: 4790 blx r2 + 4504: 682a ldr r2, [r5, #0] + 4506: 07d2 lsls r2, r2, #31 + 4508: d5e2 bpl.n 44d0 <_UartIrqHandle+0x6c> + 450a: e7f6 b.n 44fa <_UartIrqHandle+0x96> + 450c: f8db 2020 ldr.w r2, [fp, #32] + 4510: f022 0202 bic.w r2, r2, #2 + 4514: 2a21 cmp r2, #33 ; 0x21 + 4516: d01b beq.n 4550 <_UartIrqHandle+0xec> + 4518: f8db 204c ldr.w r2, [fp, #76] ; 0x4c + 451c: 2a00 cmp r2, #0 + 451e: d0d7 beq.n 44d0 <_UartIrqHandle+0x6c> + 4520: f8db 005c ldr.w r0, [fp, #92] ; 0x5c + 4524: 4790 blx r2 + 4526: e7d3 b.n 44d0 <_UartIrqHandle+0x6c> + 4528: 69b9 ldr r1, [r7, #24] + 452a: f8db 2048 ldr.w r2, [fp, #72] ; 0x48 + 452e: f88b 102c strb.w r1, [fp, #44] ; 0x2c + 4532: 2a00 cmp r2, #0 + 4534: d0cc beq.n 44d0 <_UartIrqHandle+0x6c> + 4536: 4658 mov r0, fp + 4538: 4790 blx r2 + 453a: e7c9 b.n 44d0 <_UartIrqHandle+0x6c> + 453c: f8d9 2000 ldr.w r2, [r9] + 4540: 0453 lsls r3, r2, #17 + 4542: d5c5 bpl.n 44d0 <_UartIrqHandle+0x6c> + 4544: f24f 4000 movw r0, #62464 ; 0xf400 + 4548: f2c0 0003 movt r0, #3 + 454c: 47c0 blx r8 + 454e: e7bf b.n 44d0 <_UartIrqHandle+0x6c> + 4550: f8db 2010 ldr.w r2, [fp, #16] + 4554: f89b 1026 ldrb.w r1, [fp, #38] ; 0x26 + 4558: b1e2 cbz r2, 4594 <_UartIrqHandle+0x130> + 455a: f501 1080 add.w r0, r1, #1048576 ; 0x100000 + 455e: f500 7080 add.w r0, r0, #256 ; 0x100 + 4562: 0280 lsls r0, r0, #10 + 4564: 6942 ldr r2, [r0, #20] + 4566: f100 0514 add.w r5, r0, #20 + 456a: 0693 lsls r3, r2, #26 + 456c: d5b0 bpl.n 44d0 <_UartIrqHandle+0x6c> + 456e: 3024 adds r0, #36 ; 0x24 + 4570: f8db 2018 ldr.w r2, [fp, #24] + 4574: e002 b.n 457c <_UartIrqHandle+0x118> + 4576: 6829 ldr r1, [r5, #0] + 4578: 0689 lsls r1, r1, #26 + 457a: d5a9 bpl.n 44d0 <_UartIrqHandle+0x6c> + 457c: f812 1b01 ldrb.w r1, [r2], #1 + 4580: 6001 str r1, [r0, #0] + 4582: f8db 1010 ldr.w r1, [fp, #16] + 4586: f8cb 2018 str.w r2, [fp, #24] + 458a: 3901 subs r1, #1 + 458c: f8cb 1010 str.w r1, [fp, #16] + 4590: 2900 cmp r1, #0 + 4592: d1f0 bne.n 4576 <_UartIrqHandle+0x112> + 4594: f8db 200c ldr.w r2, [fp, #12] + 4598: 4658 mov r0, fp + 459a: f022 0202 bic.w r2, r2, #2 + 459e: f8cb 200c str.w r2, [fp, #12] + 45a2: 47d0 blx sl + 45a4: f8db 2020 ldr.w r2, [fp, #32] + 45a8: 2a21 cmp r2, #33 ; 0x21 + 45aa: bf1c itt ne + 45ac: 2222 movne r2, #34 ; 0x22 + 45ae: f8cb 2020 strne.w r2, [fp, #32] + 45b2: d05c beq.n 466e <_UartIrqHandle+0x20a> + 45b4: f8db 2054 ldr.w r2, [fp, #84] ; 0x54 + 45b8: 2a00 cmp r2, #0 + 45ba: d089 beq.n 44d0 <_UartIrqHandle+0x6c> + 45bc: f8db 0064 ldr.w r0, [fp, #100] ; 0x64 + 45c0: 4790 blx r2 + 45c2: e785 b.n 44d0 <_UartIrqHandle+0x6c> + 45c4: f89b 1026 ldrb.w r1, [fp, #38] ; 0x26 + 45c8: f8db 2014 ldr.w r2, [fp, #20] + 45cc: f501 1180 add.w r1, r1, #1048576 ; 0x100000 + 45d0: 2a00 cmp r2, #0 + 45d2: d050 beq.n 4676 <_UartIrqHandle+0x212> + 45d4: f501 7080 add.w r0, r1, #256 ; 0x100 + 45d8: 0280 lsls r0, r0, #10 + 45da: 6942 ldr r2, [r0, #20] + 45dc: f100 0514 add.w r5, r0, #20 + 45e0: 9201 str r2, [sp, #4] + 45e2: 9a01 ldr r2, [sp, #4] + 45e4: 07d2 lsls r2, r2, #31 + 45e6: f57f af73 bpl.w 44d0 <_UartIrqHandle+0x6c> + 45ea: 3024 adds r0, #36 ; 0x24 + 45ec: f8db 201c ldr.w r2, [fp, #28] + 45f0: e005 b.n 45fe <_UartIrqHandle+0x19a> + 45f2: 6829 ldr r1, [r5, #0] + 45f4: 9101 str r1, [sp, #4] + 45f6: 9901 ldr r1, [sp, #4] + 45f8: 07cb lsls r3, r1, #31 + 45fa: f57f af69 bpl.w 44d0 <_UartIrqHandle+0x6c> + 45fe: 6801 ldr r1, [r0, #0] + 4600: 7011 strb r1, [r2, #0] + 4602: f8db 1014 ldr.w r1, [fp, #20] + 4606: f8db 201c ldr.w r2, [fp, #28] + 460a: 3901 subs r1, #1 + 460c: 3201 adds r2, #1 + 460e: f8cb 1014 str.w r1, [fp, #20] + 4612: f8cb 201c str.w r2, [fp, #28] + 4616: 2900 cmp r1, #0 + 4618: d1eb bne.n 45f2 <_UartIrqHandle+0x18e> + 461a: f8db 2050 ldr.w r2, [fp, #80] ; 0x50 + 461e: b1ea cbz r2, 465c <_UartIrqHandle+0x1f8> + 4620: 6828 ldr r0, [r5, #0] + 4622: f8db 2020 ldr.w r2, [fp, #32] + 4626: 2a22 cmp r2, #34 ; 0x22 + 4628: b2c2 uxtb r2, r0 + 462a: f88d 2003 strb.w r2, [sp, #3] + 462e: f89d 5003 ldrb.w r5, [sp, #3] + 4632: f89b 0024 ldrb.w r0, [fp, #36] ; 0x24 + 4636: f005 059e and.w r5, r5, #158 ; 0x9e + 463a: f8db 2058 ldr.w r2, [fp, #88] ; 0x58 + 463e: bf14 ite ne + 4640: 2121 movne r1, #33 ; 0x21 + 4642: 2110 moveq r1, #16 + 4644: 4328 orrs r0, r5 + 4646: f88b 0024 strb.w r0, [fp, #36] ; 0x24 + 464a: f8cb 1020 str.w r1, [fp, #32] + 464e: 2a00 cmp r2, #0 + 4650: f43f af3e beq.w 44d0 <_UartIrqHandle+0x6c> + 4654: f8db 0068 ldr.w r0, [fp, #104] ; 0x68 + 4658: 4790 blx r2 + 465a: e739 b.n 44d0 <_UartIrqHandle+0x6c> + 465c: f8db 200c ldr.w r2, [fp, #12] + 4660: 4658 mov r0, fp + 4662: f022 0205 bic.w r2, r2, #5 + 4666: f8cb 200c str.w r2, [fp, #12] + 466a: 47d0 blx sl + 466c: e7d8 b.n 4620 <_UartIrqHandle+0x1bc> + 466e: 2310 movs r3, #16 + 4670: f8cb 3020 str.w r3, [fp, #32] + 4674: e79e b.n 45b4 <_UartIrqHandle+0x150> + 4676: f501 7580 add.w r5, r1, #256 ; 0x100 + 467a: 02ad lsls r5, r5, #10 + 467c: 3514 adds r5, #20 + 467e: e7cc b.n 461a <_UartIrqHandle+0x1b6> + +00004680 : + 4680: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} + 4684: f240 3510 movw r5, #784 ; 0x310 + 4688: 4604 mov r4, r0 + 468a: f2c1 0500 movt r5, #4096 ; 0x1000 + 468e: f890 6026 ldrb.w r6, [r0, #38] ; 0x26 + 4692: 6c43 ldr r3, [r0, #68] ; 0x44 + 4694: f506 1780 add.w r7, r6, #1048576 ; 0x100000 + 4698: f507 7780 add.w r7, r7, #256 ; 0x100 + 469c: 02ba lsls r2, r7, #10 + 469e: 7898 ldrb r0, [r3, #2] + 46a0: 6a91 ldr r1, [r2, #40] ; 0x28 + 46a2: 00c0 lsls r0, r0, #3 + 46a4: f021 0ef8 bic.w lr, r1, #248 ; 0xf8 + 46a8: b2c0 uxtb r0, r0 + 46aa: 78d9 ldrb r1, [r3, #3] + 46ac: ea4e 0000 orr.w r0, lr, r0 + 46b0: f420 50f8 bic.w r0, r0, #7936 ; 0x1f00 + 46b4: f001 011f and.w r1, r1, #31 + 46b8: ea40 2101 orr.w r1, r0, r1, lsl #8 + 46bc: f894 802d ldrb.w r8, [r4, #45] ; 0x2d + 46c0: 6291 str r1, [r2, #40] ; 0x28 + 46c2: 6829 ldr r1, [r5, #0] + 46c4: 6a92 ldr r2, [r2, #40] ; 0x28 + 46c6: 0449 lsls r1, r1, #17 + 46c8: bf58 it pl + 46ca: f048 05c1 orrpl.w r5, r8, #193 ; 0xc1 + 46ce: f100 80a2 bmi.w 4816 + 46d2: f44f 7241 mov.w r2, #772 ; 0x304 + 46d6: f2c4 0200 movt r2, #16384 ; 0x4000 + 46da: 02bf lsls r7, r7, #10 + 46dc: 60bd str r5, [r7, #8] + 46de: 2e01 cmp r6, #1 + 46e0: 6812 ldr r2, [r2, #0] + 46e2: 689c ldr r4, [r3, #8] + 46e4: 68d8 ldr r0, [r3, #12] + 46e6: d019 beq.n 471c + 46e8: f0c0 8084 bcc.w 47f4 + 46ec: 2e02 cmp r6, #2 + 46ee: bf04 itt eq + 46f0: 2300 moveq r3, #0 + 46f2: 4619 moveq r1, r3 + 46f4: d014 beq.n 4720 + 46f6: f240 3314 movw r3, #788 ; 0x314 + 46fa: f2c1 0300 movt r3, #4096 ; 0x1000 + 46fe: 681b ldr r3, [r3, #0] + 4700: 045b lsls r3, r3, #17 + 4702: d575 bpl.n 47f0 + 4704: f24f 4084 movw r0, #62596 ; 0xf484 + 4708: f24f 339d movw r3, #62365 ; 0xf39d + 470c: 4631 mov r1, r6 + 470e: f2c0 0300 movt r3, #0 + 4712: f2c0 0003 movt r0, #3 + 4716: 4798 blx r3 + 4718: e8bd 83f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} + 471c: 2313 movs r3, #19 + 471e: 2112 movs r1, #18 + 4720: f894 4062 ldrb.w r4, [r4, #98] ; 0x62 + 4724: f44f 750c mov.w r5, #560 ; 0x230 + 4728: f2c4 0500 movt r5, #16384 ; 0x4000 + 472c: bb6c cbnz r4, 478a + 472e: f44f 7404 mov.w r4, #528 ; 0x210 + 4732: f2c4 0400 movt r4, #16384 ; 0x4000 + 4736: 682e ldr r6, [r5, #0] + 4738: f446 3680 orr.w r6, r6, #65536 ; 0x10000 + 473c: 602e str r6, [r5, #0] + 473e: 6825 ldr r5, [r4, #0] + 4740: f445 5500 orr.w r5, r5, #8192 ; 0x2000 + 4744: 6025 str r5, [r4, #0] + 4746: 2900 cmp r1, #0 + 4748: d15f bne.n 480a + 474a: f890 1062 ldrb.w r1, [r0, #98] ; 0x62 + 474e: f44f 700c mov.w r0, #560 ; 0x230 + 4752: f2c4 0000 movt r0, #16384 ; 0x4000 + 4756: bb91 cbnz r1, 47be + 4758: f44f 7104 mov.w r1, #528 ; 0x210 + 475c: f2c4 0100 movt r1, #16384 ; 0x4000 + 4760: 6804 ldr r4, [r0, #0] + 4762: f444 3480 orr.w r4, r4, #65536 ; 0x10000 + 4766: 6004 str r4, [r0, #0] + 4768: 6808 ldr r0, [r1, #0] + 476a: f440 5000 orr.w r0, r0, #8192 ; 0x2000 + 476e: 6008 str r0, [r1, #0] + 4770: b123 cbz r3, 477c + 4772: 2101 movs r1, #1 + 4774: fa01 f303 lsl.w r3, r1, r3 + 4778: ea22 0203 bic.w r2, r2, r3 + 477c: f44f 7341 mov.w r3, #772 ; 0x304 + 4780: f2c4 0300 movt r3, #16384 ; 0x4000 + 4784: 601a str r2, [r3, #0] + 4786: e8bd 83f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} + 478a: f44f 7404 mov.w r4, #528 ; 0x210 + 478e: f2c4 0400 movt r4, #16384 ; 0x4000 + 4792: 682e ldr r6, [r5, #0] + 4794: f446 2680 orr.w r6, r6, #262144 ; 0x40000 + 4798: 602e str r6, [r5, #0] + 479a: 6825 ldr r5, [r4, #0] + 479c: f445 4580 orr.w r5, r5, #16384 ; 0x4000 + 47a0: 6025 str r5, [r4, #0] + 47a2: 2900 cmp r1, #0 + 47a4: d0d1 beq.n 474a + 47a6: 2401 movs r4, #1 + 47a8: fa04 f101 lsl.w r1, r4, r1 + 47ac: 430a orrs r2, r1 + 47ae: f890 1062 ldrb.w r1, [r0, #98] ; 0x62 + 47b2: f44f 700c mov.w r0, #560 ; 0x230 + 47b6: f2c4 0000 movt r0, #16384 ; 0x4000 + 47ba: 2900 cmp r1, #0 + 47bc: d0cc beq.n 4758 + 47be: f44f 7104 mov.w r1, #528 ; 0x210 + 47c2: f2c4 0100 movt r1, #16384 ; 0x4000 + 47c6: 6804 ldr r4, [r0, #0] + 47c8: f444 2480 orr.w r4, r4, #262144 ; 0x40000 + 47cc: 6004 str r4, [r0, #0] + 47ce: 6808 ldr r0, [r1, #0] + 47d0: f440 4080 orr.w r0, r0, #16384 ; 0x4000 + 47d4: 6008 str r0, [r1, #0] + 47d6: 2b00 cmp r3, #0 + 47d8: d0d0 beq.n 477c + 47da: 2101 movs r1, #1 + 47dc: fa01 f303 lsl.w r3, r1, r3 + 47e0: 431a orrs r2, r3 + 47e2: f44f 7341 mov.w r3, #772 ; 0x304 + 47e6: f2c4 0300 movt r3, #16384 ; 0x4000 + 47ea: 601a str r2, [r3, #0] + 47ec: e8bd 83f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} + 47f0: e8bd 83f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} + 47f4: f894 4062 ldrb.w r4, [r4, #98] ; 0x62 + 47f8: f44f 750c mov.w r5, #560 ; 0x230 + 47fc: 2311 movs r3, #17 + 47fe: 2110 movs r1, #16 + 4800: f2c4 0500 movt r5, #16384 ; 0x4000 + 4804: 2c00 cmp r4, #0 + 4806: d1c0 bne.n 478a + 4808: e791 b.n 472e + 480a: 2401 movs r4, #1 + 480c: fa04 f101 lsl.w r1, r4, r1 + 4810: ea22 0201 bic.w r2, r2, r1 + 4814: e799 b.n 474a + 4816: f24f 402c movw r0, #62508 ; 0xf42c + 481a: f24f 399d movw r9, #62365 ; 0xf39d + 481e: f2c0 0003 movt r0, #3 + 4822: f2c0 0900 movt r9, #0 + 4826: 4631 mov r1, r6 + 4828: 47c8 blx r9 + 482a: 682b ldr r3, [r5, #0] + 482c: f048 05c1 orr.w r5, r8, #193 ; 0xc1 + 4830: 045a lsls r2, r3, #17 + 4832: d505 bpl.n 4840 + 4834: f24f 405c movw r0, #62556 ; 0xf45c + 4838: 4629 mov r1, r5 + 483a: f2c0 0003 movt r0, #3 + 483e: 47c8 blx r9 + 4840: 6c63 ldr r3, [r4, #68] ; 0x44 + 4842: e746 b.n 46d2 + +00004844 : + 4844: b508 push {r3, lr} + 4846: f244 138d movw r3, #16781 ; 0x418d + 484a: 3034 adds r0, #52 ; 0x34 + 484c: f2c0 0300 movt r3, #0 + 4850: 4798 blx r3 + 4852: bd08 pop {r3, pc} + +00004854 : + 4854: b5f8 push {r3, r4, r5, r6, r7, lr} + 4856: f890 5026 ldrb.w r5, [r0, #38] ; 0x26 + 485a: 4604 mov r4, r0 + 485c: 2d02 cmp r5, #2 + 485e: f890 602f ldrb.w r6, [r0, #47] ; 0x2f + 4862: d844 bhi.n 48ee + 4864: 6b43 ldr r3, [r0, #52] ; 0x34 + 4866: b1ab cbz r3, 4894 + 4868: f244 138d movw r3, #16781 ; 0x418d + 486c: f505 1180 add.w r1, r5, #1048576 ; 0x100000 + 4870: f501 7180 add.w r1, r1, #256 ; 0x100 + 4874: 2200 movs r2, #0 + 4876: 0289 lsls r1, r1, #10 + 4878: f100 0734 add.w r7, r0, #52 ; 0x34 + 487c: 60c2 str r2, [r0, #12] + 487e: f2c0 0300 movt r3, #0 + 4882: 4638 mov r0, r7 + 4884: 604a str r2, [r1, #4] + 4886: 4798 blx r3 + 4888: f244 0391 movw r3, #16529 ; 0x4091 + 488c: 4638 mov r0, r7 + 488e: f2c0 0300 movt r3, #0 + 4892: 4798 blx r3 + 4894: f44f 730d mov.w r3, #564 ; 0x234 + 4898: f2c4 0300 movt r3, #16384 ; 0x4000 + 489c: 2d01 cmp r5, #1 + 489e: 681a ldr r2, [r3, #0] + 48a0: d04a beq.n 4938 + 48a2: 2d02 cmp r5, #2 + 48a4: d124 bne.n 48f0 + 48a6: f022 0210 bic.w r2, r2, #16 + 48aa: 601a str r2, [r3, #0] + 48ac: 681a ldr r2, [r3, #0] + 48ae: 4631 mov r1, r6 + 48b0: f022 0220 bic.w r2, r2, #32 + 48b4: 601a str r2, [r3, #0] + 48b6: 4628 mov r0, r5 + 48b8: 2201 movs r2, #1 + 48ba: f7fe f93d bl 2b38 + 48be: f44f 6200 mov.w r2, #2048 ; 0x800 + 48c2: f44f 7106 mov.w r1, #536 ; 0x218 + 48c6: f2c4 0204 movt r2, #16388 ; 0x4004 + 48ca: f2c4 0100 movt r1, #16384 ; 0x4000 + 48ce: f44f 7308 mov.w r3, #544 ; 0x220 + 48d2: f2c4 0300 movt r3, #16384 ; 0x4000 + 48d6: 6810 ldr r0, [r2, #0] + 48d8: 6808 ldr r0, [r1, #0] + 48da: f020 0004 bic.w r0, r0, #4 + 48de: 6008 str r0, [r1, #0] + 48e0: 6812 ldr r2, [r2, #0] + 48e2: 681a ldr r2, [r3, #0] + 48e4: f022 0204 bic.w r2, r2, #4 + 48e8: 601a str r2, [r3, #0] + 48ea: 2300 movs r3, #0 + 48ec: 6223 str r3, [r4, #32] + 48ee: bdf8 pop {r3, r4, r5, r6, r7, pc} + 48f0: f022 0201 bic.w r2, r2, #1 + 48f4: 601a str r2, [r3, #0] + 48f6: 681a ldr r2, [r3, #0] + 48f8: 2000 movs r0, #0 + 48fa: f022 0202 bic.w r2, r2, #2 + 48fe: 601a str r2, [r3, #0] + 4900: 4631 mov r1, r6 + 4902: 4602 mov r2, r0 + 4904: f7fe f918 bl 2b38 + 4908: 2200 movs r2, #0 + 490a: f44f 7106 mov.w r1, #536 ; 0x218 + 490e: f2c4 0204 movt r2, #16388 ; 0x4004 + 4912: f2c4 0100 movt r1, #16384 ; 0x4000 + 4916: f44f 7308 mov.w r3, #544 ; 0x220 + 491a: f2c4 0300 movt r3, #16384 ; 0x4000 + 491e: 6810 ldr r0, [r2, #0] + 4920: 6808 ldr r0, [r1, #0] + 4922: f020 0001 bic.w r0, r0, #1 + 4926: 6008 str r0, [r1, #0] + 4928: 6812 ldr r2, [r2, #0] + 492a: 681a ldr r2, [r3, #0] + 492c: f022 0201 bic.w r2, r2, #1 + 4930: 601a str r2, [r3, #0] + 4932: 2300 movs r3, #0 + 4934: 6223 str r3, [r4, #32] + 4936: e7da b.n 48ee + 4938: f022 0204 bic.w r2, r2, #4 + 493c: 601a str r2, [r3, #0] + 493e: 681a ldr r2, [r3, #0] + 4940: 4631 mov r1, r6 + 4942: f022 0208 bic.w r2, r2, #8 + 4946: 601a str r2, [r3, #0] + 4948: 4628 mov r0, r5 + 494a: 2200 movs r2, #0 + 494c: f7fe f8f4 bl 2b38 + 4950: f44f 6280 mov.w r2, #1024 ; 0x400 + 4954: f44f 7106 mov.w r1, #536 ; 0x218 + 4958: f2c4 0204 movt r2, #16388 ; 0x4004 + 495c: f2c4 0100 movt r1, #16384 ; 0x4000 + 4960: f44f 7308 mov.w r3, #544 ; 0x220 + 4964: f2c4 0300 movt r3, #16384 ; 0x4000 + 4968: 6810 ldr r0, [r2, #0] + 496a: 6808 ldr r0, [r1, #0] + 496c: f020 0002 bic.w r0, r0, #2 + 4970: 6008 str r0, [r1, #0] + 4972: 6812 ldr r2, [r2, #0] + 4974: 681a ldr r2, [r3, #0] + 4976: f022 0202 bic.w r2, r2, #2 + 497a: 601a str r2, [r3, #0] + 497c: 2300 movs r3, #0 + 497e: 6223 str r3, [r4, #32] + 4980: e7b5 b.n 48ee + 4982: bf00 nop + +00004984 : + 4984: b508 push {r3, lr} + 4986: f244 03f1 movw r3, #16625 ; 0x40f1 + 498a: 3034 adds r0, #52 ; 0x34 + 498c: f2c0 0300 movt r3, #0 + 4990: 4798 blx r3 + 4992: bd08 pop {r3, pc} + +00004994 <_UartTxDmaIrqHandle>: + 4994: b570 push {r4, r5, r6, lr} + 4996: 4604 mov r4, r0 + 4998: 6c43 ldr r3, [r0, #68] ; 0x44 + 499a: 689d ldr r5, [r3, #8] + 499c: 685e ldr r6, [r3, #4] + 499e: 4628 mov r0, r5 + 49a0: 6a73 ldr r3, [r6, #36] ; 0x24 + 49a2: 4798 blx r3 + 49a4: 69f3 ldr r3, [r6, #28] + 49a6: 4628 mov r0, r5 + 49a8: 4798 blx r3 + 49aa: 6933 ldr r3, [r6, #16] + 49ac: 4628 mov r0, r5 + 49ae: 4798 blx r3 + 49b0: 6a23 ldr r3, [r4, #32] + 49b2: f023 0202 bic.w r2, r3, #2 + 49b6: 2a21 cmp r2, #33 ; 0x21 + 49b8: d108 bne.n 49cc <_UartTxDmaIrqHandle+0x38> + 49ba: 2b21 cmp r3, #33 ; 0x21 + 49bc: bf0c ite eq + 49be: 2310 moveq r3, #16 + 49c0: 2322 movne r3, #34 ; 0x22 + 49c2: 6223 str r3, [r4, #32] + 49c4: 6d63 ldr r3, [r4, #84] ; 0x54 + 49c6: b10b cbz r3, 49cc <_UartTxDmaIrqHandle+0x38> + 49c8: 6e60 ldr r0, [r4, #100] ; 0x64 + 49ca: 4798 blx r3 + 49cc: 2000 movs r0, #0 + 49ce: bd70 pop {r4, r5, r6, pc} + +000049d0 : + 49d0: b508 push {r3, lr} + 49d2: f890 1026 ldrb.w r1, [r0, #38] ; 0x26 + 49d6: 2901 cmp r1, #1 + 49d8: d034 beq.n 4a44 + 49da: d31d bcc.n 4a18 + 49dc: 2902 cmp r1, #2 + 49de: d10a bne.n 49f6 + 49e0: 2351 movs r3, #81 ; 0x51 + 49e2: 6383 str r3, [r0, #56] ; 0x38 + 49e4: 6b43 ldr r3, [r0, #52] ; 0x34 + 49e6: b1e3 cbz r3, 4a22 + 49e8: f244 0329 movw r3, #16425 ; 0x4029 + 49ec: 3034 adds r0, #52 ; 0x34 + 49ee: f2c0 0300 movt r3, #0 + 49f2: 4798 blx r3 + 49f4: bd08 pop {r3, pc} + 49f6: f240 3314 movw r3, #788 ; 0x314 + 49fa: f2c1 0300 movt r3, #4096 ; 0x1000 + 49fe: 681b ldr r3, [r3, #0] + 4a00: 045a lsls r2, r3, #17 + 4a02: d5f7 bpl.n 49f4 + 4a04: f24f 40ac movw r0, #62636 ; 0xf4ac + 4a08: f24f 339d movw r3, #62365 ; 0xf39d + 4a0c: f2c0 0003 movt r0, #3 + 4a10: f2c0 0300 movt r3, #0 + 4a14: 4798 blx r3 + 4a16: bd08 pop {r3, pc} + 4a18: 2308 movs r3, #8 + 4a1a: 6383 str r3, [r0, #56] ; 0x38 + 4a1c: 6b43 ldr r3, [r0, #52] ; 0x34 + 4a1e: 2b00 cmp r3, #0 + 4a20: d1e2 bne.n 49e8 + 4a22: f240 3314 movw r3, #788 ; 0x314 + 4a26: f2c1 0300 movt r3, #4096 ; 0x1000 + 4a2a: 681b ldr r3, [r3, #0] + 4a2c: 045b lsls r3, r3, #17 + 4a2e: d5e1 bpl.n 49f4 + 4a30: f24f 40d0 movw r0, #62672 ; 0xf4d0 + 4a34: f24f 339d movw r3, #62365 ; 0xf39d + 4a38: f2c0 0003 movt r0, #3 + 4a3c: f2c0 0300 movt r3, #0 + 4a40: 4798 blx r3 + 4a42: bd08 pop {r3, pc} + 4a44: 2350 movs r3, #80 ; 0x50 + 4a46: 6383 str r3, [r0, #56] ; 0x38 + 4a48: e7cc b.n 49e4 + 4a4a: bf00 nop + +00004a4c : + 4a4c: b3a0 cbz r0, 4ab8 + 4a4e: b5f8 push {r3, r4, r5, r6, r7, lr} + 4a50: f24f 5311 movw r3, #62737 ; 0xf511 + 4a54: 460d mov r5, r1 + 4a56: f2c0 0300 movt r3, #0 + 4a5a: 2100 movs r1, #0 + 4a5c: 2274 movs r2, #116 ; 0x74 + 4a5e: 4604 mov r4, r0 + 4a60: 4798 blx r3 + 4a62: 2d01 cmp r5, #1 + 4a64: d032 beq.n 4acc + 4a66: d329 bcc.n 4abc + 4a68: 2d02 cmp r5, #2 + 4a6a: d126 bne.n 4aba + 4a6c: 2201 movs r2, #1 + 4a6e: 2351 movs r3, #81 ; 0x51 + 4a70: f884 5026 strb.w r5, [r4, #38] ; 0x26 + 4a74: f884 202f strb.w r2, [r4, #47] ; 0x2f + 4a78: 63a3 str r3, [r4, #56] ; 0x38 + 4a7a: f244 4165 movw r1, #17509 ; 0x4465 + 4a7e: f2c0 0100 movt r1, #0 + 4a82: 2300 movs r3, #0 + 4a84: 2201 movs r2, #1 + 4a86: 2508 movs r5, #8 + 4a88: f44f 4716 mov.w r7, #38400 ; 0x9600 + 4a8c: 26c9 movs r6, #201 ; 0xc9 + 4a8e: 2020 movs r0, #32 + 4a90: f884 302a strb.w r3, [r4, #42] ; 0x2a + 4a94: f884 302b strb.w r3, [r4, #43] ; 0x2b + 4a98: f884 502d strb.w r5, [r4, #45] ; 0x2d + 4a9c: f884 2029 strb.w r2, [r4, #41] ; 0x29 + 4aa0: f884 2028 strb.w r2, [r4, #40] ; 0x28 + 4aa4: f884 2027 strb.w r2, [r4, #39] ; 0x27 + 4aa8: 63e4 str r4, [r4, #60] ; 0x3c + 4aaa: 6361 str r1, [r4, #52] ; 0x34 + 4aac: 6027 str r7, [r4, #0] + 4aae: 6063 str r3, [r4, #4] + 4ab0: 60e3 str r3, [r4, #12] + 4ab2: 60a6 str r6, [r4, #8] + 4ab4: 6420 str r0, [r4, #64] ; 0x40 + 4ab6: bdf8 pop {r3, r4, r5, r6, r7, pc} + 4ab8: 4770 bx lr + 4aba: bdf8 pop {r3, r4, r5, r6, r7, pc} + 4abc: 2300 movs r3, #0 + 4abe: 2208 movs r2, #8 + 4ac0: f884 3026 strb.w r3, [r4, #38] ; 0x26 + 4ac4: f884 302f strb.w r3, [r4, #47] ; 0x2f + 4ac8: 63a2 str r2, [r4, #56] ; 0x38 + 4aca: e7d6 b.n 4a7a + 4acc: 2202 movs r2, #2 + 4ace: 2350 movs r3, #80 ; 0x50 + 4ad0: f884 5026 strb.w r5, [r4, #38] ; 0x26 + 4ad4: f884 202f strb.w r2, [r4, #47] ; 0x2f + 4ad8: 63a3 str r3, [r4, #56] ; 0x38 + 4ada: e7ce b.n 4a7a + +00004adc : + 4adc: 2900 cmp r1, #0 + 4ade: bf18 it ne + 4ae0: 2800 cmpne r0, #0 + 4ae2: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} + 4ae6: 4606 mov r6, r0 + 4ae8: 460d mov r5, r1 + 4aea: bf0c ite eq + 4aec: 2701 moveq r7, #1 + 4aee: 2700 movne r7, #0 + 4af0: d051 beq.n 4b96 + 4af2: 688c ldr r4, [r1, #8] + 4af4: f890 8026 ldrb.w r8, [r0, #38] ; 0x26 + 4af8: 6471 str r1, [r6, #68] ; 0x44 + 4afa: 2c00 cmp r4, #0 + 4afc: d04b beq.n 4b96 + 4afe: f24f 5311 movw r3, #62737 ; 0xf511 + 4b02: 2268 movs r2, #104 ; 0x68 + 4b04: f2c0 0300 movt r3, #0 + 4b08: 4620 mov r0, r4 + 4b0a: 4639 mov r1, r7 + 4b0c: 4798 blx r3 + 4b0e: 2201 movs r2, #1 + 4b10: 230e movs r3, #14 + 4b12: 4590 cmp r8, r2 + 4b14: 702a strb r2, [r5, #0] + 4b16: 70ab strb r3, [r5, #2] + 4b18: d04b beq.n 4bb2 + 4b1a: d340 bcc.n 4b9e + 4b1c: f1b8 0f02 cmp.w r8, #2 + 4b20: d13b bne.n 4b9a + 4b22: f640 0024 movw r0, #2084 ; 0x824 + 4b26: 469e mov lr, r3 + 4b28: f2c4 0004 movt r0, #16388 ; 0x4004 + 4b2c: f240 4b04 movw fp, #1028 ; 0x404 + 4b30: 46c2 mov sl, r8 + 4b32: 46b8 mov r8, r7 + 4b34: 2716 movs r7, #22 + 4b36: f644 1295 movw r2, #18837 ; 0x4995 + 4b3a: f2c0 0200 movt r2, #0 + 4b3e: f894 9028 ldrb.w r9, [r4, #40] ; 0x28 + 4b42: f894 c063 ldrb.w ip, [r4, #99] ; 0x63 + 4b46: f884 e03b strb.w lr, [r4, #59] ; 0x3b + 4b4a: 6060 str r0, [r4, #4] + 4b4c: f884 8062 strb.w r8, [r4, #98] ; 0x62 + 4b50: 2300 movs r3, #0 + 4b52: 2101 movs r1, #1 + 4b54: 2002 movs r0, #2 + 4b56: f049 0921 orr.w r9, r9, #33 ; 0x21 + 4b5a: f04c 0c03 orr.w ip, ip, #3 + 4b5e: f04f 0e13 mov.w lr, #19 + 4b62: f04f 0820 mov.w r8, #32 + 4b66: f884 a061 strb.w sl, [r4, #97] ; 0x61 + 4b6a: f8c4 b008 str.w fp, [r4, #8] + 4b6e: f884 9028 strb.w r9, [r4, #40] ; 0x28 + 4b72: f884 c063 strb.w ip, [r4, #99] ; 0x63 + 4b76: 60e1 str r1, [r4, #12] + 4b78: 64e1 str r1, [r4, #76] ; 0x4c + 4b7a: 6221 str r1, [r4, #32] + 4b7c: 64a3 str r3, [r4, #72] ; 0x48 + 4b7e: 6263 str r3, [r4, #36] ; 0x24 + 4b80: 6123 str r3, [r4, #16] + 4b82: 61e3 str r3, [r4, #28] + 4b84: f884 e064 strb.w lr, [r4, #100] ; 0x64 + 4b88: 6160 str r0, [r4, #20] + 4b8a: 61a0 str r0, [r4, #24] + 4b8c: 612a str r2, [r5, #16] + 4b8e: 61ae str r6, [r5, #24] + 4b90: 616f str r7, [r5, #20] + 4b92: f8c5 801c str.w r8, [r5, #28] + 4b96: e8bd 8ff8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, pc} + 4b9a: e8bd 8ff8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, pc} + 4b9e: 2024 movs r0, #36 ; 0x24 + 4ba0: 46be mov lr, r7 + 4ba2: 46ba mov sl, r7 + 4ba4: 46b8 mov r8, r7 + 4ba6: f2c4 0004 movt r0, #16388 ; 0x4004 + 4baa: 2714 movs r7, #20 + 4bac: f240 1b01 movw fp, #257 ; 0x101 + 4bb0: e7c1 b.n 4b36 + 4bb2: f240 4024 movw r0, #1060 ; 0x424 + 4bb6: 46ba mov sl, r7 + 4bb8: f2c4 0004 movt r0, #16388 ; 0x4004 + 4bbc: f240 1b01 movw fp, #257 ; 0x101 + 4bc0: 271a movs r7, #26 + 4bc2: f04f 0e02 mov.w lr, #2 + 4bc6: e7b6 b.n 4b36 + +00004bc8 : + 4bc8: 2900 cmp r1, #0 + 4bca: bf18 it ne + 4bcc: 2800 cmpne r0, #0 + 4bce: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} + 4bd2: 4606 mov r6, r0 + 4bd4: 460d mov r5, r1 + 4bd6: bf0c ite eq + 4bd8: f04f 0801 moveq.w r8, #1 + 4bdc: f04f 0800 movne.w r8, #0 + 4be0: d058 beq.n 4c94 + 4be2: 68cc ldr r4, [r1, #12] + 4be4: f890 9026 ldrb.w r9, [r0, #38] ; 0x26 + 4be8: 6471 str r1, [r6, #68] ; 0x44 + 4bea: 2c00 cmp r4, #0 + 4bec: d052 beq.n 4c94 + 4bee: f24f 5311 movw r3, #62737 ; 0xf511 + 4bf2: f04f 0b01 mov.w fp, #1 + 4bf6: f2c0 0300 movt r3, #0 + 4bfa: 4620 mov r0, r4 + 4bfc: 4641 mov r1, r8 + 4bfe: 2268 movs r2, #104 ; 0x68 + 4c00: 4798 blx r3 + 4c02: 2304 movs r3, #4 + 4c04: 45d9 cmp r9, fp + 4c06: f885 b001 strb.w fp, [r5, #1] + 4c0a: 70eb strb r3, [r5, #3] + 4c0c: d050 beq.n 4cb0 + 4c0e: d345 bcc.n 4c9c + 4c10: f1b9 0f02 cmp.w r9, #2 + 4c14: d140 bne.n 4c98 + 4c16: f640 0724 movw r7, #2084 ; 0x824 + 4c1a: 46ce mov lr, r9 + 4c1c: f2c4 0704 movt r7, #16388 ; 0x4004 + 4c20: f240 4a04 movw sl, #1028 ; 0x404 + 4c24: 211c movs r1, #28 + 4c26: 230e movs r3, #14 + 4c28: f244 222d movw r2, #16941 ; 0x422d + 4c2c: f2c0 0200 movt r2, #0 + 4c30: f894 9028 ldrb.w r9, [r4, #40] ; 0x28 + 4c34: f894 803d ldrb.w r8, [r4, #61] ; 0x3d + 4c38: f894 c063 ldrb.w ip, [r4, #99] ; 0x63 + 4c3c: f884 303a strb.w r3, [r4, #58] ; 0x3a + 4c40: 6027 str r7, [r4, #0] + 4c42: f884 b062 strb.w fp, [r4, #98] ; 0x62 + 4c46: f884 e061 strb.w lr, [r4, #97] ; 0x61 + 4c4a: 2300 movs r3, #0 + 4c4c: 2002 movs r0, #2 + 4c4e: 2701 movs r7, #1 + 4c50: f049 0921 orr.w r9, r9, #33 ; 0x21 + 4c54: f048 0801 orr.w r8, r8, #1 + 4c58: f04c 0c03 orr.w ip, ip, #3 + 4c5c: f04f 0b13 mov.w fp, #19 + 4c60: f04f 0e20 mov.w lr, #32 + 4c64: f8c4 a008 str.w sl, [r4, #8] + 4c68: f884 9028 strb.w r9, [r4, #40] ; 0x28 + 4c6c: f884 803d strb.w r8, [r4, #61] ; 0x3d + 4c70: f884 c063 strb.w ip, [r4, #99] ; 0x63 + 4c74: 60e0 str r0, [r4, #12] + 4c76: 6120 str r0, [r4, #16] + 4c78: 61e0 str r0, [r4, #28] + 4c7a: 64a3 str r3, [r4, #72] ; 0x48 + 4c7c: 6223 str r3, [r4, #32] + 4c7e: 6163 str r3, [r4, #20] + 4c80: 61a3 str r3, [r4, #24] + 4c82: 64e7 str r7, [r4, #76] ; 0x4c + 4c84: 6267 str r7, [r4, #36] ; 0x24 + 4c86: f884 b064 strb.w fp, [r4, #100] ; 0x64 + 4c8a: 622a str r2, [r5, #32] + 4c8c: 62ae str r6, [r5, #40] ; 0x28 + 4c8e: 6269 str r1, [r5, #36] ; 0x24 + 4c90: f8c5 e02c str.w lr, [r5, #44] ; 0x2c + 4c94: e8bd 8ff8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, pc} + 4c98: e8bd 8ff8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, pc} + 4c9c: 465b mov r3, fp + 4c9e: 2724 movs r7, #36 ; 0x24 + 4ca0: 46c3 mov fp, r8 + 4ca2: 469e mov lr, r3 + 4ca4: f2c4 0704 movt r7, #16388 ; 0x4004 + 4ca8: 2115 movs r1, #21 + 4caa: f240 2a02 movw sl, #514 ; 0x202 + 4cae: e7bb b.n 4c28 + 4cb0: f240 4724 movw r7, #1060 ; 0x424 + 4cb4: 46ce mov lr, r9 + 4cb6: 46cb mov fp, r9 + 4cb8: f2c4 0704 movt r7, #16388 ; 0x4004 + 4cbc: f240 2a02 movw sl, #514 ; 0x202 + 4cc0: 211b movs r1, #27 + 4cc2: 2303 movs r3, #3 + 4cc4: e7b0 b.n 4c28 + 4cc6: bf00 nop + +00004cc8 : + 4cc8: b538 push {r3, r4, r5, lr} + 4cca: 6ec3 ldr r3, [r0, #108] ; 0x6c + 4ccc: 4604 mov r4, r0 + 4cce: b103 cbz r3, 4cd2 + 4cd0: 4798 blx r3 + 4cd2: f894 0025 ldrb.w r0, [r4, #37] ; 0x25 + 4cd6: 2501 movs r5, #1 + 4cd8: b918 cbnz r0, 4ce2 + 4cda: 4605 mov r5, r0 + 4cdc: 2301 movs r3, #1 + 4cde: f884 3025 strb.w r3, [r4, #37] ; 0x25 + 4ce2: 6f23 ldr r3, [r4, #112] ; 0x70 + 4ce4: b103 cbz r3, 4ce8 + 4ce6: 4798 blx r3 + 4ce8: 4628 mov r0, r5 + 4cea: bd38 pop {r3, r4, r5, pc} + +00004cec : + 4cec: 6ec3 ldr r3, [r0, #108] ; 0x6c + 4cee: b510 push {r4, lr} + 4cf0: 4604 mov r4, r0 + 4cf2: b103 cbz r3, 4cf6 + 4cf4: 4798 blx r3 + 4cf6: 6f23 ldr r3, [r4, #112] ; 0x70 + 4cf8: 2200 movs r2, #0 + 4cfa: f884 2025 strb.w r2, [r4, #37] ; 0x25 + 4cfe: b113 cbz r3, 4d06 + 4d00: e8bd 4010 ldmia.w sp!, {r4, lr} + 4d04: 4718 bx r3 + 4d06: bd10 pop {r4, pc} + +00004d08 : + 4d08: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} + 4d0c: 6a06 ldr r6, [r0, #32] + 4d0e: 4604 mov r4, r0 + 4d10: 2e22 cmp r6, #34 ; 0x22 + 4d12: bf18 it ne + 4d14: 2e10 cmpne r6, #16 + 4d16: f890 9026 ldrb.w r9, [r0, #38] ; 0x26 + 4d1a: d00a beq.n 4d32 + 4d1c: f240 330c movw r3, #780 ; 0x30c + 4d20: f2c1 0300 movt r3, #4096 ; 0x1000 + 4d24: 681b ldr r3, [r3, #0] + 4d26: 045c lsls r4, r3, #17 + 4d28: d46b bmi.n 4e02 + 4d2a: 2501 movs r5, #1 + 4d2c: 4628 mov r0, r5 + 4d2e: e8bd 83f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} + 4d32: 2a00 cmp r2, #0 + 4d34: bf18 it ne + 4d36: 2900 cmpne r1, #0 + 4d38: 460f mov r7, r1 + 4d3a: 4690 mov r8, r2 + 4d3c: d116 bne.n 4d6c + 4d3e: f240 3314 movw r3, #788 ; 0x314 + 4d42: f2c1 0300 movt r3, #4096 ; 0x1000 + 4d46: 681b ldr r3, [r3, #0] + 4d48: 2020 movs r0, #32 + 4d4a: f884 0024 strb.w r0, [r4, #36] ; 0x24 + 4d4e: 0458 lsls r0, r3, #17 + 4d50: d56e bpl.n 4e30 + 4d52: f24f 5028 movw r0, #62760 ; 0xf528 + 4d56: f24f 339d movw r3, #62365 ; 0xf39d + 4d5a: 2503 movs r5, #3 + 4d5c: f2c0 0300 movt r3, #0 + 4d60: f2c0 0003 movt r0, #3 + 4d64: 4798 blx r3 + 4d66: 4628 mov r0, r5 + 4d68: e8bd 83f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} + 4d6c: f7ff ffac bl 4cc8 + 4d70: 4605 mov r5, r0 + 4d72: b188 cbz r0, 4d98 + 4d74: f240 330c movw r3, #780 ; 0x30c + 4d78: f2c1 0300 movt r3, #4096 ; 0x1000 + 4d7c: 681b ldr r3, [r3, #0] + 4d7e: 0459 lsls r1, r3, #17 + 4d80: d5d3 bpl.n 4d2a + 4d82: f24f 506c movw r0, #62828 ; 0xf56c + 4d86: f24f 339d movw r3, #62365 ; 0xf39d + 4d8a: 4631 mov r1, r6 + 4d8c: f2c0 0300 movt r3, #0 + 4d90: f2c0 0003 movt r0, #3 + 4d94: 4798 blx r3 + 4d96: e7c8 b.n 4d2a + 4d98: 2e10 cmp r6, #16 + 4d9a: bf0c ite eq + 4d9c: 2321 moveq r3, #33 ; 0x21 + 4d9e: 2323 movne r3, #35 ; 0x23 + 4da0: f509 1080 add.w r0, r9, #1048576 ; 0x100000 + 4da4: 6223 str r3, [r4, #32] + 4da6: f500 7080 add.w r0, r0, #256 ; 0x100 + 4daa: 2300 movs r3, #0 + 4dac: 0280 lsls r0, r0, #10 + 4dae: f8c4 8010 str.w r8, [r4, #16] + 4db2: f884 3024 strb.w r3, [r4, #36] ; 0x24 + 4db6: 6943 ldr r3, [r0, #20] + 4db8: f100 0e14 add.w lr, r0, #20 + 4dbc: 069a lsls r2, r3, #26 + 4dbe: 61a7 str r7, [r4, #24] + 4dc0: d52b bpl.n 4e1a + 4dc2: 4639 mov r1, r7 + 4dc4: 3024 adds r0, #36 ; 0x24 + 4dc6: 463a mov r2, r7 + 4dc8: e003 b.n 4dd2 + 4dca: f8de 3000 ldr.w r3, [lr] + 4dce: 069b lsls r3, r3, #26 + 4dd0: d523 bpl.n 4e1a + 4dd2: 780b ldrb r3, [r1, #0] + 4dd4: 1c51 adds r1, r2, #1 + 4dd6: 6003 str r3, [r0, #0] + 4dd8: 6923 ldr r3, [r4, #16] + 4dda: 61a1 str r1, [r4, #24] + 4ddc: 3b01 subs r3, #1 + 4dde: 6123 str r3, [r4, #16] + 4de0: 460a mov r2, r1 + 4de2: 2b00 cmp r3, #0 + 4de4: d1f1 bne.n 4dca + 4de6: 2e10 cmp r6, #16 + 4de8: bf1c itt ne + 4dea: 2322 movne r3, #34 ; 0x22 + 4dec: 6223 strne r3, [r4, #32] + 4dee: d100 bne.n 4df2 + 4df0: 6226 str r6, [r4, #32] + 4df2: 6d63 ldr r3, [r4, #84] ; 0x54 + 4df4: b10b cbz r3, 4dfa + 4df6: 6e60 ldr r0, [r4, #100] ; 0x64 + 4df8: 4798 blx r3 + 4dfa: 4620 mov r0, r4 + 4dfc: f7ff ff76 bl 4cec + 4e00: e794 b.n 4d2c + 4e02: f24f 40f0 movw r0, #62704 ; 0xf4f0 + 4e06: f24f 339d movw r3, #62365 ; 0xf39d + 4e0a: 4631 mov r1, r6 + 4e0c: f2c0 0003 movt r0, #3 + 4e10: f2c0 0300 movt r3, #0 + 4e14: 4798 blx r3 + 4e16: 2501 movs r5, #1 + 4e18: e788 b.n 4d2c + 4e1a: f244 432d movw r3, #17453 ; 0x442d + 4e1e: 68e2 ldr r2, [r4, #12] + 4e20: f2c0 0300 movt r3, #0 + 4e24: f042 0202 orr.w r2, r2, #2 + 4e28: 60e2 str r2, [r4, #12] + 4e2a: 4620 mov r0, r4 + 4e2c: 4798 blx r3 + 4e2e: e7e4 b.n 4dfa + 4e30: 2503 movs r5, #3 + 4e32: e77b b.n 4d2c + +00004e34 : + 4e34: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + 4e38: 6a04 ldr r4, [r0, #32] + 4e3a: 4605 mov r5, r0 + 4e3c: 2c22 cmp r4, #34 ; 0x22 + 4e3e: bf18 it ne + 4e40: 2c10 cmpne r4, #16 + 4e42: d00b beq.n 4e5c + 4e44: f240 330c movw r3, #780 ; 0x30c + 4e48: f2c1 0300 movt r3, #4096 ; 0x1000 + 4e4c: 681b ldr r3, [r3, #0] + 4e4e: 045d lsls r5, r3, #17 + 4e50: f100 808c bmi.w 4f6c + 4e54: 2601 movs r6, #1 + 4e56: 4630 mov r0, r6 + 4e58: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 4e5c: 2a00 cmp r2, #0 + 4e5e: bf18 it ne + 4e60: 2900 cmpne r1, #0 + 4e62: 4688 mov r8, r1 + 4e64: 4617 mov r7, r2 + 4e66: d117 bne.n 4e98 + 4e68: f240 3314 movw r3, #788 ; 0x314 + 4e6c: f2c1 0300 movt r3, #4096 ; 0x1000 + 4e70: 681b ldr r3, [r3, #0] + 4e72: 2020 movs r0, #32 + 4e74: f885 0024 strb.w r0, [r5, #36] ; 0x24 + 4e78: 0458 lsls r0, r3, #17 + 4e7a: f140 8082 bpl.w 4f82 + 4e7e: f24f 50e4 movw r0, #62948 ; 0xf5e4 + 4e82: f24f 339d movw r3, #62365 ; 0xf39d + 4e86: 2603 movs r6, #3 + 4e88: f2c0 0300 movt r3, #0 + 4e8c: f2c0 0003 movt r0, #3 + 4e90: 4798 blx r3 + 4e92: 4630 mov r0, r6 + 4e94: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 4e98: f7ff ff16 bl 4cc8 + 4e9c: 4606 mov r6, r0 + 4e9e: b190 cbz r0, 4ec6 + 4ea0: f240 330c movw r3, #780 ; 0x30c + 4ea4: f2c1 0300 movt r3, #4096 ; 0x1000 + 4ea8: 681b ldr r3, [r3, #0] + 4eaa: 045a lsls r2, r3, #17 + 4eac: d5d2 bpl.n 4e54 + 4eae: f24f 6028 movw r0, #63016 ; 0xf628 + 4eb2: f24f 339d movw r3, #62365 ; 0xf39d + 4eb6: 4621 mov r1, r4 + 4eb8: f2c0 0003 movt r0, #3 + 4ebc: f2c0 0300 movt r3, #0 + 4ec0: 4798 blx r3 + 4ec2: 2601 movs r6, #1 + 4ec4: e7c7 b.n 4e56 + 4ec6: 2c10 cmp r4, #16 + 4ec8: 6c6a ldr r2, [r5, #68] ; 0x44 + 4eca: f04f 0100 mov.w r1, #0 + 4ece: bf0c ite eq + 4ed0: 2321 moveq r3, #33 ; 0x21 + 4ed2: 2323 movne r3, #35 ; 0x23 + 4ed4: f885 1024 strb.w r1, [r5, #36] ; 0x24 + 4ed8: 622b str r3, [r5, #32] + 4eda: ea48 0307 orr.w r3, r8, r7 + 4ede: f013 0303 ands.w r3, r3, #3 + 4ee2: 6894 ldr r4, [r2, #8] + 4ee4: bf18 it ne + 4ee6: 2301 movne r3, #1 + 4ee8: f8c5 8018 str.w r8, [r5, #24] + 4eec: 612f str r7, [r5, #16] + 4eee: f8d2 8004 ldr.w r8, [r2, #4] + 4ef2: bf0c ite eq + 4ef4: 6263 streq r3, [r4, #36] ; 0x24 + 4ef6: 6263 strne r3, [r4, #36] ; 0x24 + 4ef8: f240 3314 movw r3, #788 ; 0x314 + 4efc: f2c1 0300 movt r3, #4096 ; 0x1000 + 4f00: 681b ldr r3, [r3, #0] + 4f02: bf05 ittet eq + 4f04: f3c7 028f ubfxeq r2, r7, #2, #16 + 4f08: 2102 moveq r1, #2 + 4f0a: b2ba uxthne r2, r7 + 4f0c: 8562 strheq r2, [r4, #42] ; 0x2a + 4f0e: bf0e itee eq + 4f10: 6161 streq r1, [r4, #20] + 4f12: 8562 strhne r2, [r4, #42] ; 0x2a + 4f14: 6161 strne r1, [r4, #20] + 4f16: 045b lsls r3, r3, #17 + 4f18: d509 bpl.n 4f2e + 4f1a: f24f 6068 movw r0, #63080 ; 0xf668 + 4f1e: f24f 339d movw r3, #62365 ; 0xf39d + 4f22: f2c0 0003 movt r0, #3 + 4f26: f2c0 0300 movt r3, #0 + 4f2a: 6961 ldr r1, [r4, #20] + 4f2c: 4798 blx r3 + 4f2e: 8d63 ldrh r3, [r4, #42] ; 0x2a + 4f30: f5b3 5f80 cmp.w r3, #4096 ; 0x1000 + 4f34: d904 bls.n 4f40 + 4f36: 4628 mov r0, r5 + 4f38: f7ff fed8 bl 4cec + 4f3c: 2603 movs r6, #3 + 4f3e: e78a b.n 4e56 + 4f40: 69ab ldr r3, [r5, #24] + 4f42: f8d8 2000 ldr.w r2, [r8] + 4f46: 4620 mov r0, r4 + 4f48: 6023 str r3, [r4, #0] + 4f4a: 4790 blx r2 + 4f4c: f8d8 3018 ldr.w r3, [r8, #24] + 4f50: 4620 mov r0, r4 + 4f52: 4798 blx r3 + 4f54: f8d8 3008 ldr.w r3, [r8, #8] + 4f58: 4620 mov r0, r4 + 4f5a: 4798 blx r3 + 4f5c: 4620 mov r0, r4 + 4f5e: f8d8 3014 ldr.w r3, [r8, #20] + 4f62: 4798 blx r3 + 4f64: 4628 mov r0, r5 + 4f66: f7ff fec1 bl 4cec + 4f6a: e774 b.n 4e56 + 4f6c: f24f 50ac movw r0, #62892 ; 0xf5ac + 4f70: f24f 339d movw r3, #62365 ; 0xf39d + 4f74: 4621 mov r1, r4 + 4f76: f2c0 0300 movt r3, #0 + 4f7a: f2c0 0003 movt r0, #3 + 4f7e: 4798 blx r3 + 4f80: e768 b.n 4e54 + 4f82: 2603 movs r6, #3 + 4f84: e767 b.n 4e56 + 4f86: bf00 nop + +00004f88 : + 4f88: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + 4f8c: 6a06 ldr r6, [r0, #32] + 4f8e: 4604 mov r4, r0 + 4f90: f026 0302 bic.w r3, r6, #2 + 4f94: 2b21 cmp r3, #33 ; 0x21 + 4f96: d00a beq.n 4fae + 4f98: f240 330c movw r3, #780 ; 0x30c + 4f9c: f2c1 0300 movt r3, #4096 ; 0x1000 + 4fa0: 681d ldr r5, [r3, #0] + 4fa2: f415 4580 ands.w r5, r5, #16384 ; 0x4000 + 4fa6: d145 bne.n 5034 + 4fa8: 4628 mov r0, r5 + 4faa: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 4fae: f7ff fe8b bl 4cc8 + 4fb2: 4605 mov r5, r0 + 4fb4: b1a0 cbz r0, 4fe0 + 4fb6: f240 330c movw r3, #780 ; 0x30c + 4fba: f2c1 0300 movt r3, #4096 ; 0x1000 + 4fbe: 681b ldr r3, [r3, #0] + 4fc0: 045b lsls r3, r3, #17 + 4fc2: bf58 it pl + 4fc4: 2501 movpl r5, #1 + 4fc6: d5ef bpl.n 4fa8 + 4fc8: f24f 6028 movw r0, #63016 ; 0xf628 + 4fcc: f24f 339d movw r3, #62365 ; 0xf39d + 4fd0: 4631 mov r1, r6 + 4fd2: f2c0 0003 movt r0, #3 + 4fd6: f2c0 0300 movt r3, #0 + 4fda: 4798 blx r3 + 4fdc: 2501 movs r5, #1 + 4fde: e7e3 b.n 4fa8 + 4fe0: f244 432d movw r3, #17453 ; 0x442d + 4fe4: 68e2 ldr r2, [r4, #12] + 4fe6: f2c0 0300 movt r3, #0 + 4fea: f022 0202 bic.w r2, r2, #2 + 4fee: 60e2 str r2, [r4, #12] + 4ff0: 4620 mov r0, r4 + 4ff2: 4798 blx r3 + 4ff4: 6c63 ldr r3, [r4, #68] ; 0x44 + 4ff6: b13b cbz r3, 5008 + 4ff8: 689f ldr r7, [r3, #8] + 4ffa: f8d3 8004 ldr.w r8, [r3, #4] + 4ffe: f1b8 0f00 cmp.w r8, #0 + 5002: bf18 it ne + 5004: 2f00 cmpne r7, #0 + 5006: d108 bne.n 501a + 5008: 2e21 cmp r6, #33 ; 0x21 + 500a: bf0c ite eq + 500c: 2310 moveq r3, #16 + 500e: 2322 movne r3, #34 ; 0x22 + 5010: 6223 str r3, [r4, #32] + 5012: 4620 mov r0, r4 + 5014: f7ff fe6a bl 4cec + 5018: e7c6 b.n 4fa8 + 501a: f8d8 3024 ldr.w r3, [r8, #36] ; 0x24 + 501e: 4638 mov r0, r7 + 5020: 4798 blx r3 + 5022: f8d8 301c ldr.w r3, [r8, #28] + 5026: 4638 mov r0, r7 + 5028: 4798 blx r3 + 502a: f8d8 3010 ldr.w r3, [r8, #16] + 502e: 4638 mov r0, r7 + 5030: 4798 blx r3 + 5032: e7e9 b.n 5008 + 5034: f24f 6090 movw r0, #63120 ; 0xf690 + 5038: f24f 339d movw r3, #62365 ; 0xf39d + 503c: 4631 mov r1, r6 + 503e: f2c0 0003 movt r0, #3 + 5042: f2c0 0300 movt r3, #0 + 5046: 4798 blx r3 + 5048: 2500 movs r5, #0 + 504a: e7ad b.n 4fa8 + +0000504c : + 504c: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} + 5050: 6a06 ldr r6, [r0, #32] + 5052: b083 sub sp, #12 + 5054: 2e21 cmp r6, #33 ; 0x21 + 5056: bf18 it ne + 5058: 2e10 cmpne r6, #16 + 505a: 4604 mov r4, r0 + 505c: f890 9026 ldrb.w r9, [r0, #38] ; 0x26 + 5060: d00c beq.n 507c + 5062: f240 330c movw r3, #780 ; 0x30c + 5066: f2c1 0300 movt r3, #4096 ; 0x1000 + 506a: 681b ldr r3, [r3, #0] + 506c: 045c lsls r4, r3, #17 + 506e: f100 8083 bmi.w 5178 + 5072: 2501 movs r5, #1 + 5074: 4628 mov r0, r5 + 5076: b003 add sp, #12 + 5078: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + 507c: 2a00 cmp r2, #0 + 507e: bf18 it ne + 5080: 2900 cmpne r1, #0 + 5082: 460f mov r7, r1 + 5084: 4690 mov r8, r2 + 5086: d118 bne.n 50ba + 5088: f240 3314 movw r3, #788 ; 0x314 + 508c: f2c1 0300 movt r3, #4096 ; 0x1000 + 5090: 681b ldr r3, [r3, #0] + 5092: 2020 movs r0, #32 + 5094: f884 0024 strb.w r0, [r4, #36] ; 0x24 + 5098: 0458 lsls r0, r3, #17 + 509a: f140 8084 bpl.w 51a6 + 509e: f24f 7008 movw r0, #63240 ; 0xf708 + 50a2: f24f 339d movw r3, #62365 ; 0xf39d + 50a6: 2503 movs r5, #3 + 50a8: f2c0 0300 movt r3, #0 + 50ac: f2c0 0003 movt r0, #3 + 50b0: 4798 blx r3 + 50b2: 4628 mov r0, r5 + 50b4: b003 add sp, #12 + 50b6: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + 50ba: f7ff fe05 bl 4cc8 + 50be: 4605 mov r5, r0 + 50c0: b188 cbz r0, 50e6 + 50c2: f240 330c movw r3, #780 ; 0x30c + 50c6: f2c1 0300 movt r3, #4096 ; 0x1000 + 50ca: 681b ldr r3, [r3, #0] + 50cc: 0459 lsls r1, r3, #17 + 50ce: d5d0 bpl.n 5072 + 50d0: f24f 704c movw r0, #63308 ; 0xf74c + 50d4: f24f 339d movw r3, #62365 ; 0xf39d + 50d8: 4631 mov r1, r6 + 50da: f2c0 0300 movt r3, #0 + 50de: f2c0 0003 movt r0, #3 + 50e2: 4798 blx r3 + 50e4: e7c5 b.n 5072 + 50e6: 2e10 cmp r6, #16 + 50e8: bf0c ite eq + 50ea: 2322 moveq r3, #34 ; 0x22 + 50ec: 2323 movne r3, #35 ; 0x23 + 50ee: f509 1980 add.w r9, r9, #1048576 ; 0x100000 + 50f2: 6223 str r3, [r4, #32] + 50f4: f509 7980 add.w r9, r9, #256 ; 0x100 + 50f8: 2300 movs r3, #0 + 50fa: ea4f 2989 mov.w r9, r9, lsl #10 + 50fe: f8c4 8014 str.w r8, [r4, #20] + 5102: f884 3024 strb.w r3, [r4, #36] ; 0x24 + 5106: f8d9 3014 ldr.w r3, [r9, #20] + 510a: f109 0014 add.w r0, r9, #20 + 510e: 9301 str r3, [sp, #4] + 5110: 9b01 ldr r3, [sp, #4] + 5112: 61e7 str r7, [r4, #28] + 5114: 07da lsls r2, r3, #31 + 5116: d53b bpl.n 5190 + 5118: 4639 mov r1, r7 + 511a: f109 0224 add.w r2, r9, #36 ; 0x24 + 511e: e004 b.n 512a + 5120: 6803 ldr r3, [r0, #0] + 5122: 9301 str r3, [sp, #4] + 5124: 9b01 ldr r3, [sp, #4] + 5126: 07db lsls r3, r3, #31 + 5128: d532 bpl.n 5190 + 512a: 6813 ldr r3, [r2, #0] + 512c: 700b strb r3, [r1, #0] + 512e: 6963 ldr r3, [r4, #20] + 5130: 69e1 ldr r1, [r4, #28] + 5132: 3b01 subs r3, #1 + 5134: 3101 adds r1, #1 + 5136: 6163 str r3, [r4, #20] + 5138: 61e1 str r1, [r4, #28] + 513a: 2b00 cmp r3, #0 + 513c: d1f0 bne.n 5120 + 513e: f8d9 3014 ldr.w r3, [r9, #20] + 5142: f894 2024 ldrb.w r2, [r4, #36] ; 0x24 + 5146: b2db uxtb r3, r3 + 5148: f88d 3003 strb.w r3, [sp, #3] + 514c: f89d 3003 ldrb.w r3, [sp, #3] + 5150: 2e10 cmp r6, #16 + 5152: f003 039e and.w r3, r3, #158 ; 0x9e + 5156: ea43 0302 orr.w r3, r3, r2 + 515a: f884 3024 strb.w r3, [r4, #36] ; 0x24 + 515e: bf1c itt ne + 5160: 2321 movne r3, #33 ; 0x21 + 5162: 6223 strne r3, [r4, #32] + 5164: 6da3 ldr r3, [r4, #88] ; 0x58 + 5166: bf08 it eq + 5168: 6226 streq r6, [r4, #32] + 516a: b10b cbz r3, 5170 + 516c: 6ea0 ldr r0, [r4, #104] ; 0x68 + 516e: 4798 blx r3 + 5170: 4620 mov r0, r4 + 5172: f7ff fdbb bl 4cec + 5176: e77d b.n 5074 + 5178: f24f 60d0 movw r0, #63184 ; 0xf6d0 + 517c: f24f 339d movw r3, #62365 ; 0xf39d + 5180: 4631 mov r1, r6 + 5182: f2c0 0003 movt r0, #3 + 5186: f2c0 0300 movt r3, #0 + 518a: 4798 blx r3 + 518c: 2501 movs r5, #1 + 518e: e771 b.n 5074 + 5190: f244 432d movw r3, #17453 ; 0x442d + 5194: 68e2 ldr r2, [r4, #12] + 5196: f2c0 0300 movt r3, #0 + 519a: f042 0205 orr.w r2, r2, #5 + 519e: 60e2 str r2, [r4, #12] + 51a0: 4620 mov r0, r4 + 51a2: 4798 blx r3 + 51a4: e7e4 b.n 5170 + 51a6: 2503 movs r5, #3 + 51a8: e764 b.n 5074 + 51aa: bf00 nop + +000051ac : + 51ac: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} + 51b0: 6a04 ldr r4, [r0, #32] + 51b2: 4605 mov r5, r0 + 51b4: 2c21 cmp r4, #33 ; 0x21 + 51b6: bf18 it ne + 51b8: 2c10 cmpne r4, #16 + 51ba: d00a beq.n 51d2 + 51bc: f240 330c movw r3, #780 ; 0x30c + 51c0: f2c1 0300 movt r3, #4096 ; 0x1000 + 51c4: 681b ldr r3, [r3, #0] + 51c6: 045d lsls r5, r3, #17 + 51c8: d472 bmi.n 52b0 + 51ca: 2601 movs r6, #1 + 51cc: 4630 mov r0, r6 + 51ce: e8bd 83f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} + 51d2: 2a00 cmp r2, #0 + 51d4: bf18 it ne + 51d6: 2900 cmpne r1, #0 + 51d8: 460f mov r7, r1 + 51da: 4690 mov r8, r2 + 51dc: d116 bne.n 520c + 51de: f240 3314 movw r3, #788 ; 0x314 + 51e2: f2c1 0300 movt r3, #4096 ; 0x1000 + 51e6: 681b ldr r3, [r3, #0] + 51e8: 2020 movs r0, #32 + 51ea: f885 0024 strb.w r0, [r5, #36] ; 0x24 + 51ee: 0458 lsls r0, r3, #17 + 51f0: d569 bpl.n 52c6 + 51f2: f24f 70b0 movw r0, #63408 ; 0xf7b0 + 51f6: f24f 339d movw r3, #62365 ; 0xf39d + 51fa: 2603 movs r6, #3 + 51fc: f2c0 0300 movt r3, #0 + 5200: f2c0 0003 movt r0, #3 + 5204: 4798 blx r3 + 5206: 4630 mov r0, r6 + 5208: e8bd 83f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} + 520c: f7ff fd5c bl 4cc8 + 5210: 4606 mov r6, r0 + 5212: b190 cbz r0, 523a + 5214: f240 330c movw r3, #780 ; 0x30c + 5218: f2c1 0300 movt r3, #4096 ; 0x1000 + 521c: 681b ldr r3, [r3, #0] + 521e: 045b lsls r3, r3, #17 + 5220: d5d3 bpl.n 51ca + 5222: f24f 70f4 movw r0, #63476 ; 0xf7f4 + 5226: f24f 339d movw r3, #62365 ; 0xf39d + 522a: 4621 mov r1, r4 + 522c: f2c0 0003 movt r0, #3 + 5230: f2c0 0300 movt r3, #0 + 5234: 4798 blx r3 + 5236: 2601 movs r6, #1 + 5238: e7c8 b.n 51cc + 523a: 2c10 cmp r4, #16 + 523c: bf0c ite eq + 523e: 2322 moveq r3, #34 ; 0x22 + 5240: 2323 movne r3, #35 ; 0x23 + 5242: 622b str r3, [r5, #32] + 5244: 2200 movs r2, #0 + 5246: 6c6b ldr r3, [r5, #68] ; 0x44 + 5248: f885 2024 strb.w r2, [r5, #36] ; 0x24 + 524c: 68dc ldr r4, [r3, #12] + 524e: 61ef str r7, [r5, #28] + 5250: f017 0703 ands.w r7, r7, #3 + 5254: f8d3 9004 ldr.w r9, [r3, #4] + 5258: f8c5 8014 str.w r8, [r5, #20] + 525c: bf0c ite eq + 525e: 2302 moveq r3, #2 + 5260: 2301 movne r3, #1 + 5262: fa1f f888 uxth.w r8, r8 + 5266: bf07 ittee eq + 5268: 6227 streq r7, [r4, #32] + 526a: 6123 streq r3, [r4, #16] + 526c: 6122 strne r2, [r4, #16] + 526e: 6223 strne r3, [r4, #32] + 5270: f5b8 5f80 cmp.w r8, #4096 ; 0x1000 + 5274: f8a4 802a strh.w r8, [r4, #42] ; 0x2a + 5278: d904 bls.n 5284 + 527a: 4628 mov r0, r5 + 527c: f7ff fd36 bl 4cec + 5280: 2603 movs r6, #3 + 5282: e7a3 b.n 51cc + 5284: 69eb ldr r3, [r5, #28] + 5286: f8d9 2000 ldr.w r2, [r9] + 528a: 4620 mov r0, r4 + 528c: 6063 str r3, [r4, #4] + 528e: 4790 blx r2 + 5290: f8d9 3018 ldr.w r3, [r9, #24] + 5294: 4620 mov r0, r4 + 5296: 4798 blx r3 + 5298: f8d9 3008 ldr.w r3, [r9, #8] + 529c: 4620 mov r0, r4 + 529e: 4798 blx r3 + 52a0: 4620 mov r0, r4 + 52a2: f8d9 3014 ldr.w r3, [r9, #20] + 52a6: 4798 blx r3 + 52a8: 4628 mov r0, r5 + 52aa: f7ff fd1f bl 4cec + 52ae: e78d b.n 51cc + 52b0: f24f 708c movw r0, #63372 ; 0xf78c + 52b4: f24f 339d movw r3, #62365 ; 0xf39d + 52b8: 4621 mov r1, r4 + 52ba: f2c0 0300 movt r3, #0 + 52be: f2c0 0003 movt r0, #3 + 52c2: 4798 blx r3 + 52c4: e781 b.n 51ca + 52c6: 2603 movs r6, #3 + 52c8: e780 b.n 51cc + 52ca: bf00 nop + +000052cc : + 52cc: b5f8 push {r3, r4, r5, r6, r7, lr} + 52ce: 6a06 ldr r6, [r0, #32] + 52d0: 4604 mov r4, r0 + 52d2: f1a6 0322 sub.w r3, r6, #34 ; 0x22 + 52d6: 2b01 cmp r3, #1 + 52d8: d909 bls.n 52ee + 52da: f240 330c movw r3, #780 ; 0x30c + 52de: f2c1 0300 movt r3, #4096 ; 0x1000 + 52e2: 6818 ldr r0, [r3, #0] + 52e4: f410 4580 ands.w r5, r0, #16384 ; 0x4000 + 52e8: d140 bne.n 536c + 52ea: 4628 mov r0, r5 + 52ec: bdf8 pop {r3, r4, r5, r6, r7, pc} + 52ee: f7ff fceb bl 4cc8 + 52f2: 4605 mov r5, r0 + 52f4: b1a0 cbz r0, 5320 + 52f6: f240 330c movw r3, #780 ; 0x30c + 52fa: f2c1 0300 movt r3, #4096 ; 0x1000 + 52fe: 681b ldr r3, [r3, #0] + 5300: 045b lsls r3, r3, #17 + 5302: bf58 it pl + 5304: 2501 movpl r5, #1 + 5306: d5f0 bpl.n 52ea + 5308: f64f 0074 movw r0, #63604 ; 0xf874 + 530c: f24f 339d movw r3, #62365 ; 0xf39d + 5310: 4631 mov r1, r6 + 5312: f2c0 0003 movt r0, #3 + 5316: f2c0 0300 movt r3, #0 + 531a: 4798 blx r3 + 531c: 2501 movs r5, #1 + 531e: e7e4 b.n 52ea + 5320: f244 432d movw r3, #17453 ; 0x442d + 5324: 68e2 ldr r2, [r4, #12] + 5326: f2c0 0300 movt r3, #0 + 532a: f022 0205 bic.w r2, r2, #5 + 532e: 60e2 str r2, [r4, #12] + 5330: 4620 mov r0, r4 + 5332: 4798 blx r3 + 5334: 6c63 ldr r3, [r4, #68] ; 0x44 + 5336: b12b cbz r3, 5344 + 5338: 68de ldr r6, [r3, #12] + 533a: 685f ldr r7, [r3, #4] + 533c: 2f00 cmp r7, #0 + 533e: bf18 it ne + 5340: 2e00 cmpne r6, #0 + 5342: d109 bne.n 5358 + 5344: 6a23 ldr r3, [r4, #32] + 5346: 4620 mov r0, r4 + 5348: 2b22 cmp r3, #34 ; 0x22 + 534a: bf0c ite eq + 534c: 2310 moveq r3, #16 + 534e: 2321 movne r3, #33 ; 0x21 + 5350: 6223 str r3, [r4, #32] + 5352: f7ff fccb bl 4cec + 5356: e7c8 b.n 52ea + 5358: 6a7b ldr r3, [r7, #36] ; 0x24 + 535a: 4630 mov r0, r6 + 535c: 4798 blx r3 + 535e: 69fb ldr r3, [r7, #28] + 5360: 4630 mov r0, r6 + 5362: 4798 blx r3 + 5364: 693b ldr r3, [r7, #16] + 5366: 4630 mov r0, r6 + 5368: 4798 blx r3 + 536a: e7eb b.n 5344 + 536c: f64f 0034 movw r0, #63540 ; 0xf834 + 5370: f24f 339d movw r3, #62365 ; 0xf39d + 5374: 4631 mov r1, r6 + 5376: f2c0 0003 movt r0, #3 + 537a: f2c0 0300 movt r3, #0 + 537e: 4798 blx r3 + 5380: 2500 movs r5, #0 + 5382: e7b2 b.n 52ea + +00005384 : + 5384: b538 push {r3, r4, r5, lr} + 5386: f240 3318 movw r3, #792 ; 0x318 + 538a: f2c1 0300 movt r3, #4096 ; 0x1000 + 538e: 4604 mov r4, r0 + 5390: 689b ldr r3, [r3, #8] + 5392: 2001 movs r0, #1 + 5394: 460d mov r5, r1 + 5396: 4798 blx r3 + 5398: 42a0 cmp r0, r4 + 539a: eba4 0000 sub.w r0, r4, r0 + 539e: bf88 it hi + 53a0: f100 30ff addhi.w r0, r0, #4294967295 + 53a4: 42a8 cmp r0, r5 + 53a6: bf8c ite hi + 53a8: 2002 movhi r0, #2 + 53aa: 2000 movls r0, #0 + 53ac: bd38 pop {r3, r4, r5, pc} + 53ae: bf00 nop + +000053b0 : + 53b0: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 53b4: 6a04 ldr r4, [r0, #32] + 53b6: b083 sub sp, #12 + 53b8: 2c22 cmp r4, #34 ; 0x22 + 53ba: bf18 it ne + 53bc: 2c10 cmpne r4, #16 + 53be: 4606 mov r6, r0 + 53c0: f890 9026 ldrb.w r9, [r0, #38] ; 0x26 + 53c4: bf14 ite ne + 53c6: 2501 movne r5, #1 + 53c8: 2500 moveq r5, #0 + 53ca: d00b beq.n 53e4 + 53cc: f240 330c movw r3, #780 ; 0x30c + 53d0: f2c1 0300 movt r3, #4096 ; 0x1000 + 53d4: 681b ldr r3, [r3, #0] + 53d6: 045f lsls r7, r3, #17 + 53d8: f100 80ae bmi.w 5538 + 53dc: 2000 movs r0, #0 + 53de: b003 add sp, #12 + 53e0: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 53e4: 2a00 cmp r2, #0 + 53e6: bf18 it ne + 53e8: 2900 cmpne r1, #0 + 53ea: 4688 mov r8, r1 + 53ec: 4617 mov r7, r2 + 53ee: bf0c ite eq + 53f0: f04f 0a01 moveq.w sl, #1 + 53f4: f04f 0a00 movne.w sl, #0 + 53f8: d116 bne.n 5428 + 53fa: f240 3314 movw r3, #788 ; 0x314 + 53fe: f2c1 0300 movt r3, #4096 ; 0x1000 + 5402: 681b ldr r3, [r3, #0] + 5404: 2020 movs r0, #32 + 5406: f886 0024 strb.w r0, [r6, #36] ; 0x24 + 540a: 045e lsls r6, r3, #17 + 540c: d5e6 bpl.n 53dc + 540e: f64f 00e8 movw r0, #63720 ; 0xf8e8 + 5412: f24f 339d movw r3, #62365 ; 0xf39d + 5416: f2c0 0003 movt r0, #3 + 541a: f2c0 0300 movt r3, #0 + 541e: 4798 blx r3 + 5420: 4628 mov r0, r5 + 5422: b003 add sp, #12 + 5424: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 5428: 469b mov fp, r3 + 542a: f7ff fc4d bl 4cc8 + 542e: b190 cbz r0, 5456 + 5430: f240 330c movw r3, #780 ; 0x30c + 5434: f2c1 0300 movt r3, #4096 ; 0x1000 + 5438: 681b ldr r3, [r3, #0] + 543a: 045d lsls r5, r3, #17 + 543c: d5ce bpl.n 53dc + 543e: f64f 1028 movw r0, #63784 ; 0xf928 + 5442: f24f 339d movw r3, #62365 ; 0xf39d + 5446: 4621 mov r1, r4 + 5448: f2c0 0003 movt r0, #3 + 544c: f2c0 0300 movt r3, #0 + 5450: 4798 blx r3 + 5452: 4650 mov r0, sl + 5454: e7c3 b.n 53de + 5456: f10b 33ff add.w r3, fp, #4294967295 + 545a: 3303 adds r3, #3 + 545c: bf88 it hi + 545e: 4682 movhi sl, r0 + 5460: d975 bls.n 554e + 5462: f240 3210 movw r2, #784 ; 0x310 + 5466: f2c1 0200 movt r2, #4096 ; 0x1000 + 546a: 6812 ldr r2, [r2, #0] + 546c: 0450 lsls r0, r2, #17 + 546e: f100 8086 bmi.w 557e + 5472: 2c10 cmp r4, #16 + 5474: f509 1c80 add.w ip, r9, #1048576 ; 0x100000 + 5478: bf0c ite eq + 547a: 2221 moveq r2, #33 ; 0x21 + 547c: 2223 movne r2, #35 ; 0x23 + 547e: f50c 7c80 add.w ip, ip, #256 ; 0x100 + 5482: 6232 str r2, [r6, #32] + 5484: ea4f 2c8c mov.w ip, ip, lsl #10 + 5488: 2200 movs r2, #0 + 548a: 4615 mov r5, r2 + 548c: f10c 0914 add.w r9, ip, #20 + 5490: f886 2024 strb.w r2, [r6, #36] ; 0x24 + 5494: e006 b.n 54a4 + 5496: f818 2005 ldrb.w r2, [r8, r5] + 549a: 3501 adds r5, #1 + 549c: f8cc 2024 str.w r2, [ip, #36] ; 0x24 + 54a0: 42bd cmp r5, r7 + 54a2: d20c bcs.n 54be + 54a4: f8d9 2000 ldr.w r2, [r9] + 54a8: 0691 lsls r1, r2, #26 + 54aa: d4f4 bmi.n 5496 + 54ac: f1ba 0f00 cmp.w sl, #0 + 54b0: d112 bne.n 54d8 + 54b2: f1bb 0f00 cmp.w fp, #0 + 54b6: d1f3 bne.n 54a0 + 54b8: 2201 movs r2, #1 + 54ba: f886 2024 strb.w r2, [r6, #36] ; 0x24 + 54be: 42bd cmp r5, r7 + 54c0: d029 beq.n 5516 + 54c2: 2c10 cmp r4, #16 + 54c4: bf18 it ne + 54c6: 2322 movne r3, #34 ; 0x22 + 54c8: 4630 mov r0, r6 + 54ca: bf0c ite eq + 54cc: 6234 streq r4, [r6, #32] + 54ce: 6233 strne r3, [r6, #32] + 54d0: f7ff fc0c bl 4cec + 54d4: 4628 mov r0, r5 + 54d6: e782 b.n 53de + 54d8: 9801 ldr r0, [sp, #4] + 54da: 4651 mov r1, sl + 54dc: f8cd c000 str.w ip, [sp] + 54e0: f7ff ff50 bl 5384 + 54e4: 2802 cmp r0, #2 + 54e6: f8dd c000 ldr.w ip, [sp] + 54ea: d1d9 bne.n 54a0 + 54ec: f240 320c movw r2, #780 ; 0x30c + 54f0: f2c1 0200 movt r2, #4096 ; 0x1000 + 54f4: 6812 ldr r2, [r2, #0] + 54f6: 2101 movs r1, #1 + 54f8: 0452 lsls r2, r2, #17 + 54fa: f886 1024 strb.w r1, [r6, #36] ; 0x24 + 54fe: d5de bpl.n 54be + 5500: f64f 109c movw r0, #63900 ; 0xf99c + 5504: f24f 329d movw r2, #62365 ; 0xf39d + 5508: 4629 mov r1, r5 + 550a: f2c0 0200 movt r2, #0 + 550e: f2c0 0003 movt r0, #3 + 5512: 4790 blx r2 + 5514: e7d3 b.n 54be + 5516: f8d9 2000 ldr.w r2, [r9] + 551a: 0653 lsls r3, r2, #25 + 551c: d4d1 bmi.n 54c2 + 551e: f1ba 0f00 cmp.w sl, #0 + 5522: d0f8 beq.n 5516 + 5524: 9801 ldr r0, [sp, #4] + 5526: 4651 mov r1, sl + 5528: f7ff ff2c bl 5384 + 552c: 2802 cmp r0, #2 + 552e: d1f2 bne.n 5516 + 5530: 2301 movs r3, #1 + 5532: f886 3024 strb.w r3, [r6, #36] ; 0x24 + 5536: e7c4 b.n 54c2 + 5538: f64f 00b4 movw r0, #63668 ; 0xf8b4 + 553c: f24f 339d movw r3, #62365 ; 0xf39d + 5540: 4621 mov r1, r4 + 5542: f2c0 0300 movt r3, #0 + 5546: f2c0 0003 movt r0, #3 + 554a: 4798 blx r3 + 554c: e746 b.n 53dc + 554e: f241 0385 movw r3, #4229 ; 0x1085 + 5552: f240 3218 movw r2, #792 ; 0x318 + 5556: f6c0 0342 movt r3, #2114 ; 0x842 + 555a: f2c1 0200 movt r2, #4096 ; 0x1000 + 555e: f44f 717a mov.w r1, #1000 ; 0x3e8 + 5562: fb01 f10b mul.w r1, r1, fp + 5566: fba3 0301 umull r0, r3, r3, r1 + 556a: 1ac9 subs r1, r1, r3 + 556c: eb03 0351 add.w r3, r3, r1, lsr #1 + 5570: 6892 ldr r2, [r2, #8] + 5572: 2001 movs r0, #1 + 5574: ea4f 1a13 mov.w sl, r3, lsr #4 + 5578: 4790 blx r2 + 557a: 9001 str r0, [sp, #4] + 557c: e771 b.n 5462 + 557e: f64f 1064 movw r0, #63844 ; 0xf964 + 5582: f24f 359d movw r5, #62365 ; 0xf39d + 5586: 4639 mov r1, r7 + 5588: f2c0 0500 movt r5, #0 + 558c: 465a mov r2, fp + 558e: f2c0 0003 movt r0, #3 + 5592: 47a8 blx r5 + 5594: e76d b.n 5472 + 5596: bf00 nop + +00005598 : + 5598: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 559c: 6a04 ldr r4, [r0, #32] + 559e: b085 sub sp, #20 + 55a0: 2c21 cmp r4, #33 ; 0x21 + 55a2: bf18 it ne + 55a4: 2c10 cmpne r4, #16 + 55a6: 4606 mov r6, r0 + 55a8: f890 b026 ldrb.w fp, [r0, #38] ; 0x26 + 55ac: bf14 ite ne + 55ae: 2501 movne r5, #1 + 55b0: 2500 moveq r5, #0 + 55b2: d00b beq.n 55cc + 55b4: f240 330c movw r3, #780 ; 0x30c + 55b8: f2c1 0300 movt r3, #4096 ; 0x1000 + 55bc: 681b ldr r3, [r3, #0] + 55be: 045d lsls r5, r3, #17 + 55c0: f100 8093 bmi.w 56ea + 55c4: 2000 movs r0, #0 + 55c6: b005 add sp, #20 + 55c8: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 55cc: 2a00 cmp r2, #0 + 55ce: bf18 it ne + 55d0: 2900 cmpne r1, #0 + 55d2: 4688 mov r8, r1 + 55d4: 4617 mov r7, r2 + 55d6: bf0c ite eq + 55d8: f04f 0a01 moveq.w sl, #1 + 55dc: f04f 0a00 movne.w sl, #0 + 55e0: d116 bne.n 5610 + 55e2: f240 3314 movw r3, #788 ; 0x314 + 55e6: f2c1 0300 movt r3, #4096 ; 0x1000 + 55ea: 681b ldr r3, [r3, #0] + 55ec: 2020 movs r0, #32 + 55ee: f886 0024 strb.w r0, [r6, #36] ; 0x24 + 55f2: 0458 lsls r0, r3, #17 + 55f4: d5e6 bpl.n 55c4 + 55f6: f64f 200c movw r0, #64012 ; 0xfa0c + 55fa: f24f 339d movw r3, #62365 ; 0xf39d + 55fe: f2c0 0003 movt r0, #3 + 5602: f2c0 0300 movt r3, #0 + 5606: 4798 blx r3 + 5608: 4628 mov r0, r5 + 560a: b005 add sp, #20 + 560c: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 5610: 4699 mov r9, r3 + 5612: f7ff fb59 bl 4cc8 + 5616: b190 cbz r0, 563e + 5618: f240 330c movw r3, #780 ; 0x30c + 561c: f2c1 0300 movt r3, #4096 ; 0x1000 + 5620: 681b ldr r3, [r3, #0] + 5622: 0459 lsls r1, r3, #17 + 5624: d5ce bpl.n 55c4 + 5626: f64f 204c movw r0, #64076 ; 0xfa4c + 562a: f24f 339d movw r3, #62365 ; 0xf39d + 562e: 4621 mov r1, r4 + 5630: f2c0 0003 movt r0, #3 + 5634: f2c0 0300 movt r3, #0 + 5638: 4798 blx r3 + 563a: 4650 mov r0, sl + 563c: e7c3 b.n 55c6 + 563e: f109 33ff add.w r3, r9, #4294967295 + 5642: 3303 adds r3, #3 + 5644: bf88 it hi + 5646: 4603 movhi r3, r0 + 5648: d95a bls.n 5700 + 564a: 2c10 cmp r4, #16 + 564c: f50b 1c80 add.w ip, fp, #1048576 ; 0x100000 + 5650: bf0c ite eq + 5652: 2222 moveq r2, #34 ; 0x22 + 5654: 2223 movne r2, #35 ; 0x23 + 5656: f50c 7c80 add.w ip, ip, #256 ; 0x100 + 565a: 6232 str r2, [r6, #32] + 565c: ea4f 2a8c mov.w sl, ip, lsl #10 + 5660: 2200 movs r2, #0 + 5662: 4615 mov r5, r2 + 5664: f10a 0b14 add.w fp, sl, #20 + 5668: f886 2024 strb.w r2, [r6, #36] ; 0x24 + 566c: e006 b.n 567c + 566e: f8da 2024 ldr.w r2, [sl, #36] ; 0x24 + 5672: f808 2005 strb.w r2, [r8, r5] + 5676: 3501 adds r5, #1 + 5678: 42bd cmp r5, r7 + 567a: d20c bcs.n 5696 + 567c: f8db 2000 ldr.w r2, [fp] + 5680: 9203 str r2, [sp, #12] + 5682: 9a03 ldr r2, [sp, #12] + 5684: 07d2 lsls r2, r2, #31 + 5686: d4f2 bmi.n 566e + 5688: b993 cbnz r3, 56b0 + 568a: f1b9 0f00 cmp.w r9, #0 + 568e: d1f3 bne.n 5678 + 5690: 2301 movs r3, #1 + 5692: f886 3024 strb.w r3, [r6, #36] ; 0x24 + 5696: 42bd cmp r5, r7 + 5698: d04b beq.n 5732 + 569a: 2c10 cmp r4, #16 + 569c: bf18 it ne + 569e: 2321 movne r3, #33 ; 0x21 + 56a0: 4630 mov r0, r6 + 56a2: bf0c ite eq + 56a4: 6234 streq r4, [r6, #32] + 56a6: 6233 strne r3, [r6, #32] + 56a8: f7ff fb20 bl 4cec + 56ac: 4628 mov r0, r5 + 56ae: e78a b.n 55c6 + 56b0: 4619 mov r1, r3 + 56b2: 9801 ldr r0, [sp, #4] + 56b4: 9300 str r3, [sp, #0] + 56b6: f7ff fe65 bl 5384 + 56ba: 2802 cmp r0, #2 + 56bc: 9b00 ldr r3, [sp, #0] + 56be: d1db bne.n 5678 + 56c0: f240 330c movw r3, #780 ; 0x30c + 56c4: f2c1 0300 movt r3, #4096 ; 0x1000 + 56c8: 681b ldr r3, [r3, #0] + 56ca: 2201 movs r2, #1 + 56cc: 045b lsls r3, r3, #17 + 56ce: f886 2024 strb.w r2, [r6, #36] ; 0x24 + 56d2: d5e0 bpl.n 5696 + 56d4: f64f 2088 movw r0, #64136 ; 0xfa88 + 56d8: f24f 339d movw r3, #62365 ; 0xf39d + 56dc: 4629 mov r1, r5 + 56de: f2c0 0300 movt r3, #0 + 56e2: f2c0 0003 movt r0, #3 + 56e6: 4798 blx r3 + 56e8: e7d5 b.n 5696 + 56ea: f64f 10d8 movw r0, #63960 ; 0xf9d8 + 56ee: f24f 339d movw r3, #62365 ; 0xf39d + 56f2: 4621 mov r1, r4 + 56f4: f2c0 0300 movt r3, #0 + 56f8: f2c0 0003 movt r0, #3 + 56fc: 4798 blx r3 + 56fe: e761 b.n 55c4 + 5700: f241 0385 movw r3, #4229 ; 0x1085 + 5704: f240 3218 movw r2, #792 ; 0x318 + 5708: f6c0 0342 movt r3, #2114 ; 0x842 + 570c: f2c1 0200 movt r2, #4096 ; 0x1000 + 5710: f44f 717a mov.w r1, #1000 ; 0x3e8 + 5714: fb01 f109 mul.w r1, r1, r9 + 5718: fba3 0301 umull r0, r3, r3, r1 + 571c: 1ac9 subs r1, r1, r3 + 571e: eb03 0351 add.w r3, r3, r1, lsr #1 + 5722: 091b lsrs r3, r3, #4 + 5724: 6892 ldr r2, [r2, #8] + 5726: 2001 movs r0, #1 + 5728: 9300 str r3, [sp, #0] + 572a: 4790 blx r2 + 572c: 9b00 ldr r3, [sp, #0] + 572e: 9001 str r0, [sp, #4] + 5730: e78b b.n 564a + 5732: f8da 2014 ldr.w r2, [sl, #20] + 5736: f896 3024 ldrb.w r3, [r6, #36] ; 0x24 + 573a: b2d2 uxtb r2, r2 + 573c: f88d 200b strb.w r2, [sp, #11] + 5740: f89d 200b ldrb.w r2, [sp, #11] + 5744: f002 029e and.w r2, r2, #158 ; 0x9e + 5748: 4313 orrs r3, r2 + 574a: f886 3024 strb.w r3, [r6, #36] ; 0x24 + 574e: e7a4 b.n 569a + +00005750 : + 5750: f500 1080 add.w r0, r0, #1048576 ; 0x100000 + 5754: f500 7380 add.w r3, r0, #256 ; 0x100 + 5758: 029b lsls r3, r3, #10 + 575a: 6a18 ldr r0, [r3, #32] + 575c: 22c9 movs r2, #201 ; 0xc9 + 575e: 2102 movs r1, #2 + 5760: f040 0008 orr.w r0, r0, #8 + 5764: 6218 str r0, [r3, #32] + 5766: 6099 str r1, [r3, #8] + 5768: 609a str r2, [r3, #8] + 576a: 6a1a ldr r2, [r3, #32] + 576c: f022 0208 bic.w r2, r2, #8 + 5770: 621a str r2, [r3, #32] + 5772: 4770 bx lr + +00005774 : + 5774: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + 5778: f240 360c movw r6, #780 ; 0x30c + 577c: f24f 379d movw r7, #62365 ; 0xf39d + 5780: f2c1 0600 movt r6, #4096 ; 0x1000 + 5784: f2c0 0700 movt r7, #0 + 5788: f890 5026 ldrb.w r5, [r0, #38] ; 0x26 + 578c: 2401 movs r4, #1 + 578e: f505 1880 add.w r8, r5, #1048576 ; 0x100000 + 5792: f508 7880 add.w r8, r8, #256 ; 0x100 + 5796: ea4f 2888 mov.w r8, r8, lsl #10 + 579a: f108 0814 add.w r8, r8, #20 + 579e: 4628 mov r0, r5 + 57a0: f7ff ffd6 bl 5750 + 57a4: f8d8 3000 ldr.w r3, [r8] + 57a8: b2db uxtb r3, r3 + 57aa: 2b60 cmp r3, #96 ; 0x60 + 57ac: d019 beq.n 57e2 + 57ae: 6832 ldr r2, [r6, #0] + 57b0: 0452 lsls r2, r2, #17 + 57b2: d420 bmi.n 57f6 + 57b4: 3401 adds r4, #1 + 57b6: 2c03 cmp r4, #3 + 57b8: d1f1 bne.n 579e + 57ba: f240 3314 movw r3, #788 ; 0x314 + 57be: f2c1 0300 movt r3, #4096 ; 0x1000 + 57c2: 681b ldr r3, [r3, #0] + 57c4: 045b lsls r3, r3, #17 + 57c6: d51e bpl.n 5806 + 57c8: f64f 304c movw r0, #64332 ; 0xfb4c + 57cc: f24f 339d movw r3, #62365 ; 0xf39d + 57d0: 4629 mov r1, r5 + 57d2: f2c0 0300 movt r3, #0 + 57d6: f2c0 0003 movt r0, #3 + 57da: 4798 blx r3 + 57dc: 2005 movs r0, #5 + 57de: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 57e2: f240 3210 movw r2, #784 ; 0x310 + 57e6: f2c1 0200 movt r2, #4096 ; 0x1000 + 57ea: 6810 ldr r0, [r2, #0] + 57ec: f410 4080 ands.w r0, r0, #16384 ; 0x4000 + 57f0: d10b bne.n 580a + 57f2: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 57f6: f64f 3008 movw r0, #64264 ; 0xfb08 + 57fa: 4621 mov r1, r4 + 57fc: 462a mov r2, r5 + 57fe: f2c0 0003 movt r0, #3 + 5802: 47b8 blx r7 + 5804: e7d6 b.n 57b4 + 5806: 2005 movs r0, #5 + 5808: e7f3 b.n 57f2 + 580a: f64f 20c4 movw r0, #64196 ; 0xfac4 + 580e: f24f 369d movw r6, #62365 ; 0xf39d + 5812: 4621 mov r1, r4 + 5814: 462a mov r2, r5 + 5816: f2c0 0600 movt r6, #0 + 581a: f2c0 0003 movt r0, #3 + 581e: 47b0 blx r6 + 5820: 2000 movs r0, #0 + 5822: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 5826: bf00 nop + +00005828 : + 5828: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 582c: f890 9026 ldrb.w r9, [r0, #38] ; 0x26 + 5830: b085 sub sp, #20 + 5832: f1b9 0f02 cmp.w r9, #2 + 5836: 4606 mov r6, r0 + 5838: f890 402f ldrb.w r4, [r0, #47] ; 0x2f + 583c: d914 bls.n 5868 + 583e: f240 3314 movw r3, #788 ; 0x314 + 5842: f2c1 0300 movt r3, #4096 ; 0x1000 + 5846: 681b ldr r3, [r3, #0] + 5848: 0458 lsls r0, r3, #17 + 584a: f140 81aa bpl.w 5ba2 + 584e: f64f 3080 movw r0, #64384 ; 0xfb80 + 5852: f24f 339d movw r3, #62365 ; 0xf39d + 5856: f2c0 0003 movt r0, #3 + 585a: f2c0 0300 movt r3, #0 + 585e: 4798 blx r3 + 5860: 2003 movs r0, #3 + 5862: b005 add sp, #20 + 5864: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 5868: f240 3810 movw r8, #784 ; 0x310 + 586c: f2c1 0800 movt r8, #4096 ; 0x1000 + 5870: f8d8 3000 ldr.w r3, [r8] + 5874: 0459 lsls r1, r3, #17 + 5876: f100 8188 bmi.w 5b8a + 587a: f1b9 0f01 cmp.w r9, #1 + 587e: bf98 it ls + 5880: 2c01 cmpls r4, #1 + 5882: d10f bne.n 58a4 + 5884: f240 330c movw r3, #780 ; 0x30c + 5888: f2c1 0300 movt r3, #4096 ; 0x1000 + 588c: 681b ldr r3, [r3, #0] + 588e: 045a lsls r2, r3, #17 + 5890: f100 8189 bmi.w 5ba6 + 5894: f44f 7330 mov.w r3, #704 ; 0x2c0 + 5898: f2c4 0300 movt r3, #16384 ; 0x4000 + 589c: 681a ldr r2, [r3, #0] + 589e: f422 3280 bic.w r2, r2, #65536 ; 0x10000 + 58a2: 601a str r2, [r3, #0] + 58a4: ea54 0309 orrs.w r3, r4, r9 + 58a8: d113 bne.n 58d2 + 58aa: 23a4 movs r3, #164 ; 0xa4 + 58ac: f2c4 0300 movt r3, #16384 ; 0x4000 + 58b0: 681d ldr r5, [r3, #0] + 58b2: 06eb lsls r3, r5, #27 + 58b4: d50d bpl.n 58d2 + 58b6: f240 330c movw r3, #780 ; 0x30c + 58ba: f2c1 0300 movt r3, #4096 ; 0x1000 + 58be: 681b ldr r3, [r3, #0] + 58c0: 045f lsls r7, r3, #17 + 58c2: f100 827f bmi.w 5dc4 + 58c6: 23a4 movs r3, #164 ; 0xa4 + 58c8: f2c4 0300 movt r3, #16384 ; 0x4000 + 58cc: f025 0510 bic.w r5, r5, #16 + 58d0: 601d str r5, [r3, #0] + 58d2: f44f 730d mov.w r3, #564 ; 0x234 + 58d6: f2c4 0300 movt r3, #16384 ; 0x4000 + 58da: f1b9 0f01 cmp.w r9, #1 + 58de: 681a ldr r2, [r3, #0] + 58e0: 4621 mov r1, r4 + 58e2: d073 beq.n 59cc + 58e4: f1b9 0f02 cmp.w r9, #2 + 58e8: d054 beq.n 5994 + 58ea: f042 0201 orr.w r2, r2, #1 + 58ee: 601a str r2, [r3, #0] + 58f0: 681a ldr r2, [r3, #0] + 58f2: 2000 movs r0, #0 + 58f4: f042 0202 orr.w r2, r2, #2 + 58f8: 601a str r2, [r3, #0] + 58fa: 2201 movs r2, #1 + 58fc: f7fd f91c bl 2b38 + 5900: f44f 7206 mov.w r2, #536 ; 0x218 + 5904: f2c4 0200 movt r2, #16384 ; 0x4000 + 5908: f44f 7308 mov.w r3, #544 ; 0x220 + 590c: f2c4 0300 movt r3, #16384 ; 0x4000 + 5910: 6811 ldr r1, [r2, #0] + 5912: f041 0101 orr.w r1, r1, #1 + 5916: 6011 str r1, [r2, #0] + 5918: 681a ldr r2, [r3, #0] + 591a: f042 0201 orr.w r2, r2, #1 + 591e: 601a str r2, [r3, #0] + 5920: 4630 mov r0, r6 + 5922: f7ff ff27 bl 5774 + 5926: f8d8 3000 ldr.w r3, [r8] + 592a: 045d lsls r5, r3, #17 + 592c: f100 8122 bmi.w 5b74 + 5930: f509 1780 add.w r7, r9, #1048576 ; 0x100000 + 5934: f507 7780 add.w r7, r7, #256 ; 0x100 + 5938: 02bf lsls r7, r7, #10 + 593a: 2300 movs r3, #0 + 593c: 607b str r3, [r7, #4] + 593e: 68fb ldr r3, [r7, #12] + 5940: f043 0380 orr.w r3, r3, #128 ; 0x80 + 5944: 60fb str r3, [r7, #12] + 5946: f8d8 3000 ldr.w r3, [r8] + 594a: 045c lsls r4, r3, #17 + 594c: f100 8244 bmi.w 5dd8 + 5950: 6831 ldr r1, [r6, #0] + 5952: 4cca ldr r4, [pc, #808] ; (5c7c ) + 5954: 2300 movs r3, #0 + 5956: f854 5f04 ldr.w r5, [r4, #4]! + 595a: 42a9 cmp r1, r5 + 595c: d052 beq.n 5a04 + 595e: 3301 adds r3, #1 + 5960: 2b1c cmp r3, #28 + 5962: d9f8 bls.n 5956 + 5964: f240 3314 movw r3, #788 ; 0x314 + 5968: f2c1 0300 movt r3, #4096 ; 0x1000 + 596c: 681b ldr r3, [r3, #0] + 596e: f640 44a8 movw r4, #3240 ; 0xca8 + 5972: 045a lsls r2, r3, #17 + 5974: f140 8121 bpl.w 5bba + 5978: f64f 40c4 movw r0, #64708 ; 0xfcc4 + 597c: f2c0 0403 movt r4, #3 + 5980: f24f 339d movw r3, #62365 ; 0xf39d + 5984: 6962 ldr r2, [r4, #20] + 5986: f2c0 0300 movt r3, #0 + 598a: f2c0 0003 movt r0, #3 + 598e: 4798 blx r3 + 5990: 2305 movs r3, #5 + 5992: e03d b.n 5a10 + 5994: f042 0210 orr.w r2, r2, #16 + 5998: 601a str r2, [r3, #0] + 599a: 681a ldr r2, [r3, #0] + 599c: 4648 mov r0, r9 + 599e: f042 0220 orr.w r2, r2, #32 + 59a2: 601a str r2, [r3, #0] + 59a4: 2201 movs r2, #1 + 59a6: f7fd f8c7 bl 2b38 + 59aa: f44f 7206 mov.w r2, #536 ; 0x218 + 59ae: f2c4 0200 movt r2, #16384 ; 0x4000 + 59b2: f44f 7308 mov.w r3, #544 ; 0x220 + 59b6: f2c4 0300 movt r3, #16384 ; 0x4000 + 59ba: 6811 ldr r1, [r2, #0] + 59bc: f041 0104 orr.w r1, r1, #4 + 59c0: 6011 str r1, [r2, #0] + 59c2: 681a ldr r2, [r3, #0] + 59c4: f042 0204 orr.w r2, r2, #4 + 59c8: 601a str r2, [r3, #0] + 59ca: e7a9 b.n 5920 + 59cc: f042 0204 orr.w r2, r2, #4 + 59d0: 601a str r2, [r3, #0] + 59d2: 681a ldr r2, [r3, #0] + 59d4: 4648 mov r0, r9 + 59d6: f042 0208 orr.w r2, r2, #8 + 59da: 601a str r2, [r3, #0] + 59dc: 464a mov r2, r9 + 59de: f7fd f8ab bl 2b38 + 59e2: f44f 7206 mov.w r2, #536 ; 0x218 + 59e6: f2c4 0200 movt r2, #16384 ; 0x4000 + 59ea: f44f 7308 mov.w r3, #544 ; 0x220 + 59ee: f2c4 0300 movt r3, #16384 ; 0x4000 + 59f2: 6811 ldr r1, [r2, #0] + 59f4: f041 0102 orr.w r1, r1, #2 + 59f8: 6011 str r1, [r2, #0] + 59fa: 681a ldr r2, [r3, #0] + 59fc: f042 0202 orr.w r2, r2, #2 + 5a00: 601a str r2, [r3, #0] + 5a02: e78d b.n 5920 + 5a04: 1c58 adds r0, r3, #1 + 5a06: d0ad beq.n 5964 + 5a08: f640 44a8 movw r4, #3240 ; 0xca8 + 5a0c: f2c0 0403 movt r4, #3 + 5a10: f240 3510 movw r5, #784 ; 0x310 + 5a14: eb04 0283 add.w r2, r4, r3, lsl #2 + 5a18: f8d8 0000 ldr.w r0, [r8] + 5a1c: f854 1023 ldr.w r1, [r4, r3, lsl #2] + 5a20: f8d2 40e8 ldr.w r4, [r2, #232] ; 0xe8 + 5a24: 0443 lsls r3, r0, #17 + 5a26: bf58 it pl + 5a28: b2e3 uxtbpl r3, r4 + 5a2a: f2c1 0500 movt r5, #4096 ; 0x1000 + 5a2e: f8d2 a074 ldr.w sl, [r2, #116] ; 0x74 + 5a32: f8d2 c15c ldr.w ip, [r2, #348] ; 0x15c + 5a36: bf58 it pl + 5a38: f3c4 2407 ubfxpl r4, r4, #8, #8 + 5a3c: f100 8174 bmi.w 5d28 + 5a40: f240 3510 movw r5, #784 ; 0x310 + 5a44: 603b str r3, [r7, #0] + 5a46: 607c str r4, [r7, #4] + 5a48: f8d8 3000 ldr.w r3, [r8] + 5a4c: f2c1 0500 movt r5, #4096 ; 0x1000 + 5a50: 045c lsls r4, r3, #17 + 5a52: f100 8115 bmi.w 5c80 + 5a56: 69fb ldr r3, [r7, #28] + 5a58: f107 0b1c add.w fp, r7, #28 + 5a5c: 6a3b ldr r3, [r7, #32] + 5a5e: f107 0520 add.w r5, r7, #32 + 5a62: 2300 movs r3, #0 + 5a64: f2c0 73ff movt r3, #2047 ; 0x7ff + 5a68: f240 3410 movw r4, #784 ; 0x310 + 5a6c: f8db 2000 ldr.w r2, [fp] + 5a70: f1aa 0a05 sub.w sl, sl, #5 + 5a74: f042 0280 orr.w r2, r2, #128 ; 0x80 + 5a78: f8cb 2000 str.w r2, [fp] + 5a7c: 682a ldr r2, [r5, #0] + 5a7e: ea4f 1a0a mov.w sl, sl, lsl #4 + 5a82: fa5f fa8a uxtb.w sl, sl + 5a86: f022 02f0 bic.w r2, r2, #240 ; 0xf0 + 5a8a: ea42 020a orr.w r2, r2, sl + 5a8e: 602a str r2, [r5, #0] + 5a90: f8db 2000 ldr.w r2, [fp] + 5a94: ea4f 4c0c mov.w ip, ip, lsl #16 + 5a98: f022 62ff bic.w r2, r2, #133693440 ; 0x7f80000 + 5a9c: ea0c 0303 and.w r3, ip, r3 + 5aa0: f422 22e0 bic.w r2, r2, #458752 ; 0x70000 + 5aa4: 4313 orrs r3, r2 + 5aa6: f8cb 3000 str.w r3, [fp] + 5aaa: f8d8 3000 ldr.w r3, [r8] + 5aae: f2c1 0400 movt r4, #4096 ; 0x1000 + 5ab2: 0458 lsls r0, r3, #17 + 5ab4: bf58 it pl + 5ab6: f8db 3000 ldrpl.w r3, [fp] + 5aba: f100 80bd bmi.w 5c38 + 5abe: 682b ldr r3, [r5, #0] + 5ac0: f240 3410 movw r4, #784 ; 0x310 + 5ac4: 68fb ldr r3, [r7, #12] + 5ac6: f2c1 0400 movt r4, #4096 ; 0x1000 + 5aca: f023 0380 bic.w r3, r3, #128 ; 0x80 + 5ace: 60fb str r3, [r7, #12] + 5ad0: f8d8 3000 ldr.w r3, [r8] + 5ad4: 045d lsls r5, r3, #17 + 5ad6: f100 8099 bmi.w 5c0c + 5ada: 7b32 ldrb r2, [r6, #12] + 5adc: 607a str r2, [r7, #4] + 5ade: f8d8 3000 ldr.w r3, [r8] + 5ae2: 0459 lsls r1, r3, #17 + 5ae4: f100 8087 bmi.w 5bf6 + 5ae8: 6873 ldr r3, [r6, #4] + 5aea: 4630 mov r0, r6 + 5aec: 2b01 cmp r3, #1 + 5aee: bf02 ittt eq + 5af0: 693b ldreq r3, [r7, #16] + 5af2: f043 0320 orreq.w r3, r3, #32 + 5af6: 613b streq r3, [r7, #16] + 5af8: f7fe fdc2 bl 4680 + 5afc: f8d8 3000 ldr.w r3, [r8] + 5b00: 045a lsls r2, r3, #17 + 5b02: d46b bmi.n 5bdc + 5b04: 68f9 ldr r1, [r7, #12] + 5b06: f896 2027 ldrb.w r2, [r6, #39] ; 0x27 + 5b0a: f896 3028 ldrb.w r3, [r6, #40] ; 0x28 + 5b0e: f021 0105 bic.w r1, r1, #5 + 5b12: f002 0201 and.w r2, r2, #1 + 5b16: 430a orrs r2, r1 + 5b18: f003 0301 and.w r3, r3, #1 + 5b1c: f896 1029 ldrb.w r1, [r6, #41] ; 0x29 + 5b20: ea42 0383 orr.w r3, r2, r3, lsl #2 + 5b24: f023 0308 bic.w r3, r3, #8 + 5b28: f896 202a ldrb.w r2, [r6, #42] ; 0x2a + 5b2c: f001 0101 and.w r1, r1, #1 + 5b30: ea43 01c1 orr.w r1, r3, r1, lsl #3 + 5b34: f021 0110 bic.w r1, r1, #16 + 5b38: f896 302b ldrb.w r3, [r6, #43] ; 0x2b + 5b3c: f002 0201 and.w r2, r2, #1 + 5b40: ea41 1202 orr.w r2, r1, r2, lsl #4 + 5b44: f022 0220 bic.w r2, r2, #32 + 5b48: f003 0301 and.w r3, r3, #1 + 5b4c: ea42 1343 orr.w r3, r2, r3, lsl #5 + 5b50: 60fb str r3, [r7, #12] + 5b52: f8d8 3000 ldr.w r3, [r8] + 5b56: 045b lsls r3, r3, #17 + 5b58: d433 bmi.n 5bc2 + 5b5a: 6871 ldr r1, [r6, #4] + 5b5c: 2901 cmp r1, #1 + 5b5e: d005 beq.n 5b6c + 5b60: 2310 movs r3, #16 + 5b62: 2000 movs r0, #0 + 5b64: 6233 str r3, [r6, #32] + 5b66: b005 add sp, #20 + 5b68: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 5b6c: 4630 mov r0, r6 + 5b6e: f7fe fba5 bl 42bc + 5b72: e7f5 b.n 5b60 + 5b74: f64f 4064 movw r0, #64612 ; 0xfc64 + 5b78: f24f 339d movw r3, #62365 ; 0xf39d + 5b7c: 4649 mov r1, r9 + 5b7e: f2c0 0300 movt r3, #0 + 5b82: f2c0 0003 movt r0, #3 + 5b86: 4798 blx r3 + 5b88: e6d2 b.n 5930 + 5b8a: f64f 30c0 movw r0, #64448 ; 0xfbc0 + 5b8e: f24f 339d movw r3, #62365 ; 0xf39d + 5b92: 4649 mov r1, r9 + 5b94: f2c0 0300 movt r3, #0 + 5b98: 4622 mov r2, r4 + 5b9a: f2c0 0003 movt r0, #3 + 5b9e: 4798 blx r3 + 5ba0: e66b b.n 587a + 5ba2: 2003 movs r0, #3 + 5ba4: e65d b.n 5862 + 5ba6: f64f 30f8 movw r0, #64504 ; 0xfbf8 + 5baa: f24f 339d movw r3, #62365 ; 0xf39d + 5bae: f2c0 0003 movt r0, #3 + 5bb2: f2c0 0300 movt r3, #0 + 5bb6: 4798 blx r3 + 5bb8: e66c b.n 5894 + 5bba: f2c0 0403 movt r4, #3 + 5bbe: 2305 movs r3, #5 + 5bc0: e726 b.n 5a10 + 5bc2: f64f 7028 movw r0, #65320 ; 0xff28 + 5bc6: f24f 349d movw r4, #62365 ; 0xf39d + 5bca: 68fb ldr r3, [r7, #12] + 5bcc: 4649 mov r1, r9 + 5bce: f2c0 0400 movt r4, #0 + 5bd2: 220c movs r2, #12 + 5bd4: f2c0 0003 movt r0, #3 + 5bd8: 47a0 blx r4 + 5bda: e7be b.n 5b5a + 5bdc: f64f 7000 movw r0, #65280 ; 0xff00 + 5be0: f24f 349d movw r4, #62365 ; 0xf39d + 5be4: 68fb ldr r3, [r7, #12] + 5be6: f2c0 0400 movt r4, #0 + 5bea: 4649 mov r1, r9 + 5bec: 220c movs r2, #12 + 5bee: f2c0 0003 movt r0, #3 + 5bf2: 47a0 blx r4 + 5bf4: e786 b.n 5b04 + 5bf6: f24f 30d4 movw r0, #62420 ; 0xf3d4 + 5bfa: f24f 339d movw r3, #62365 ; 0xf39d + 5bfe: 4649 mov r1, r9 + 5c00: f2c0 0300 movt r3, #0 + 5c04: f2c0 0003 movt r0, #3 + 5c08: 4798 blx r3 + 5c0a: e76d b.n 5ae8 + 5c0c: f64f 4090 movw r0, #64656 ; 0xfc90 + 5c10: f24f 359d movw r5, #62365 ; 0xf39d + 5c14: 68f9 ldr r1, [r7, #12] + 5c16: f2c0 0003 movt r0, #3 + 5c1a: f2c0 0500 movt r5, #0 + 5c1e: 47a8 blx r5 + 5c20: 6823 ldr r3, [r4, #0] + 5c22: 0458 lsls r0, r3, #17 + 5c24: f57f af59 bpl.w 5ada + 5c28: f64f 60d4 movw r0, #65236 ; 0xfed4 + 5c2c: 4649 mov r1, r9 + 5c2e: 68f2 ldr r2, [r6, #12] + 5c30: f2c0 0003 movt r0, #3 + 5c34: 47a8 blx r5 + 5c36: e750 b.n 5ada + 5c38: f64f 609c movw r0, #65180 ; 0xfe9c + 5c3c: f24f 3a9d movw sl, #62365 ; 0xf39d + 5c40: f2c0 0003 movt r0, #3 + 5c44: f2c0 0a00 movt sl, #0 + 5c48: 47d0 blx sl + 5c4a: 6823 ldr r3, [r4, #0] + 5c4c: f8db 2000 ldr.w r2, [fp] + 5c50: 0459 lsls r1, r3, #17 + 5c52: f57f af34 bpl.w 5abe + 5c56: f64f 6054 movw r0, #65108 ; 0xfe54 + 5c5a: 4649 mov r1, r9 + 5c5c: f2c0 0003 movt r0, #3 + 5c60: 47d0 blx sl + 5c62: 6823 ldr r3, [r4, #0] + 5c64: 682a ldr r2, [r5, #0] + 5c66: 045b lsls r3, r3, #17 + 5c68: f57f af2a bpl.w 5ac0 + 5c6c: f64f 6078 movw r0, #65144 ; 0xfe78 + 5c70: 4649 mov r1, r9 + 5c72: f2c0 0003 movt r0, #3 + 5c76: 47d0 blx sl + 5c78: e722 b.n 5ac0 + 5c7a: bf00 nop + 5c7c: 00030ca4 .word 0x00030ca4 + 5c80: f64f 50ec movw r0, #65004 ; 0xfdec + 5c84: f24f 349d movw r4, #62365 ; 0xf39d + 5c88: f8cd c008 str.w ip, [sp, #8] + 5c8c: f2c0 0003 movt r0, #3 + 5c90: f2c0 0400 movt r4, #0 + 5c94: 47a0 blx r4 + 5c96: 682b ldr r3, [r5, #0] + 5c98: f8dd c008 ldr.w ip, [sp, #8] + 5c9c: f413 4f80 tst.w r3, #16384 ; 0x4000 + 5ca0: f43f aed9 beq.w 5a56 + 5ca4: f64f 5094 movw r0, #64916 ; 0xfd94 + 5ca8: 6839 ldr r1, [r7, #0] + 5caa: f2c0 0003 movt r0, #3 + 5cae: 47a0 blx r4 + 5cb0: 682b ldr r3, [r5, #0] + 5cb2: f8dd c008 ldr.w ip, [sp, #8] + 5cb6: f413 4f80 tst.w r3, #16384 ; 0x4000 + 5cba: f43f aecc beq.w 5a56 + 5cbe: f64f 50c0 movw r0, #64960 ; 0xfdc0 + 5cc2: 6879 ldr r1, [r7, #4] + 5cc4: f2c0 0003 movt r0, #3 + 5cc8: 47a0 blx r4 + 5cca: 682b ldr r3, [r5, #0] + 5ccc: f8dd c008 ldr.w ip, [sp, #8] + 5cd0: f413 4f80 tst.w r3, #16384 ; 0x4000 + 5cd4: f43f aebf beq.w 5a56 + 5cd8: f64f 601c movw r0, #65052 ; 0xfe1c + 5cdc: f2c0 0003 movt r0, #3 + 5ce0: 47a0 blx r4 + 5ce2: 682b ldr r3, [r5, #0] + 5ce4: f107 0b1c add.w fp, r7, #28 + 5ce8: f413 4f80 tst.w r3, #16384 ; 0x4000 + 5cec: 69fa ldr r2, [r7, #28] + 5cee: f8dd c008 ldr.w ip, [sp, #8] + 5cf2: f43f aeb3 beq.w 5a5c + 5cf6: f64f 6054 movw r0, #65108 ; 0xfe54 + 5cfa: 4649 mov r1, r9 + 5cfc: f2c0 0003 movt r0, #3 + 5d00: 47a0 blx r4 + 5d02: 682b ldr r3, [r5, #0] + 5d04: 6a3a ldr r2, [r7, #32] + 5d06: f413 4f80 tst.w r3, #16384 ; 0x4000 + 5d0a: f107 0520 add.w r5, r7, #32 + 5d0e: f8dd c008 ldr.w ip, [sp, #8] + 5d12: f43f aea6 beq.w 5a62 + 5d16: f64f 6078 movw r0, #65144 ; 0xfe78 + 5d1a: 4649 mov r1, r9 + 5d1c: f2c0 0003 movt r0, #3 + 5d20: 47a0 blx r4 + 5d22: f8dd c008 ldr.w ip, [sp, #8] + 5d26: e69c b.n 5a62 + 5d28: f64f 5000 movw r0, #64768 ; 0xfd00 + 5d2c: f24f 3b9d movw fp, #62365 ; 0xf39d + 5d30: 4623 mov r3, r4 + 5d32: f8cd c000 str.w ip, [sp] + 5d36: 4652 mov r2, sl + 5d38: f8cd c008 str.w ip, [sp, #8] + 5d3c: f2c0 0003 movt r0, #3 + 5d40: f2c0 0b00 movt fp, #0 + 5d44: 47d8 blx fp + 5d46: 682a ldr r2, [r5, #0] + 5d48: b2e3 uxtb r3, r4 + 5d4a: f412 4f80 tst.w r2, #16384 ; 0x4000 + 5d4e: f3c4 2407 ubfx r4, r4, #8, #8 + 5d52: f8dd c008 ldr.w ip, [sp, #8] + 5d56: f43f ae73 beq.w 5a40 + 5d5a: f64f 5034 movw r0, #64820 ; 0xfd34 + 5d5e: 4619 mov r1, r3 + 5d60: 4622 mov r2, r4 + 5d62: 9303 str r3, [sp, #12] + 5d64: f2c0 0003 movt r0, #3 + 5d68: 47d8 blx fp + 5d6a: 682a ldr r2, [r5, #0] + 5d6c: 9b03 ldr r3, [sp, #12] + 5d6e: f412 4f80 tst.w r2, #16384 ; 0x4000 + 5d72: f8dd c008 ldr.w ip, [sp, #8] + 5d76: f43f ae63 beq.w 5a40 + 5d7a: f64f 5064 movw r0, #64868 ; 0xfd64 + 5d7e: f2c0 0003 movt r0, #3 + 5d82: 47d8 blx fp + 5d84: 682a ldr r2, [r5, #0] + 5d86: 9b03 ldr r3, [sp, #12] + 5d88: f412 4f80 tst.w r2, #16384 ; 0x4000 + 5d8c: f8dd c008 ldr.w ip, [sp, #8] + 5d90: f43f ae56 beq.w 5a40 + 5d94: f64f 5094 movw r0, #64916 ; 0xfd94 + 5d98: 6839 ldr r1, [r7, #0] + 5d9a: f2c0 0003 movt r0, #3 + 5d9e: 47d8 blx fp + 5da0: 682a ldr r2, [r5, #0] + 5da2: 9b03 ldr r3, [sp, #12] + 5da4: f412 4f80 tst.w r2, #16384 ; 0x4000 + 5da8: f8dd c008 ldr.w ip, [sp, #8] + 5dac: f43f ae48 beq.w 5a40 + 5db0: f64f 50c0 movw r0, #64960 ; 0xfdc0 + 5db4: 6879 ldr r1, [r7, #4] + 5db6: f2c0 0003 movt r0, #3 + 5dba: 47d8 blx fp + 5dbc: f8dd c008 ldr.w ip, [sp, #8] + 5dc0: 9b03 ldr r3, [sp, #12] + 5dc2: e63d b.n 5a40 + 5dc4: f64f 4038 movw r0, #64568 ; 0xfc38 + 5dc8: f24f 339d movw r3, #62365 ; 0xf39d + 5dcc: f2c0 0003 movt r0, #3 + 5dd0: f2c0 0300 movt r3, #0 + 5dd4: 4798 blx r3 + 5dd6: e576 b.n 58c6 + 5dd8: f64f 4090 movw r0, #64656 ; 0xfc90 + 5ddc: f24f 339d movw r3, #62365 ; 0xf39d + 5de0: 68f9 ldr r1, [r7, #12] + 5de2: f2c0 0300 movt r3, #0 + 5de6: f2c0 0003 movt r0, #3 + 5dea: 4798 blx r3 + 5dec: e5b0 b.n 5950 + 5dee: bf00 nop + +00005df0 : + 5df0: f890 3062 ldrb.w r3, [r0, #98] ; 0x62 + 5df4: f890 2063 ldrb.w r2, [r0, #99] ; 0x63 + 5df8: f503 2380 add.w r3, r3, #262144 ; 0x40000 + 5dfc: 3360 adds r3, #96 ; 0x60 + 5dfe: 031b lsls r3, r3, #12 + 5e00: f3c2 0240 ubfx r2, r2, #1, #1 + 5e04: f8c3 2398 str.w r2, [r3, #920] ; 0x398 + 5e08: 4770 bx lr + 5e0a: bf00 nop + +00005e0c : + 5e0c: b430 push {r4, r5} + 5e0e: f44f 7244 mov.w r2, #784 ; 0x310 + 5e12: 2300 movs r3, #0 + 5e14: f890 1064 ldrb.w r1, [r0, #100] ; 0x64 + 5e18: 4119 asrs r1, r3 + 5e1a: 07c9 lsls r1, r1, #31 + 5e1c: d511 bpl.n 5e42 + 5e1e: f890 1062 ldrb.w r1, [r0, #98] ; 0x62 + 5e22: f890 5063 ldrb.w r5, [r0, #99] ; 0x63 + 5e26: f501 2180 add.w r1, r1, #262144 ; 0x40000 + 5e2a: 3160 adds r1, #96 ; 0x60 + 5e2c: 0309 lsls r1, r1, #12 + 5e2e: f015 0f01 tst.w r5, #1 + 5e32: eb01 0402 add.w r4, r1, r2 + 5e36: 6885 ldr r5, [r0, #8] + 5e38: 5889 ldr r1, [r1, r2] + 5e3a: bf14 ite ne + 5e3c: 4329 orrne r1, r5 + 5e3e: 43a9 biceq r1, r5 + 5e40: 6021 str r1, [r4, #0] + 5e42: 3301 adds r3, #1 + 5e44: 2b05 cmp r3, #5 + 5e46: f102 0208 add.w r2, r2, #8 + 5e4a: d1e3 bne.n 5e14 + 5e4c: bc30 pop {r4, r5} + 5e4e: 4770 bx lr + +00005e50 : + 5e50: f890 3062 ldrb.w r3, [r0, #98] ; 0x62 + 5e54: 6882 ldr r2, [r0, #8] + 5e56: f503 2380 add.w r3, r3, #262144 ; 0x40000 + 5e5a: 3360 adds r3, #96 ; 0x60 + 5e5c: 031b lsls r3, r3, #12 + 5e5e: f8d3 13a0 ldr.w r1, [r3, #928] ; 0x3a0 + 5e62: 430a orrs r2, r1 + 5e64: f8c3 23a0 str.w r2, [r3, #928] ; 0x3a0 + 5e68: 4770 bx lr + 5e6a: bf00 nop + +00005e6c : + 5e6c: f890 3062 ldrb.w r3, [r0, #98] ; 0x62 + 5e70: 6882 ldr r2, [r0, #8] + 5e72: f503 2380 add.w r3, r3, #262144 ; 0x40000 + 5e76: 3360 adds r3, #96 ; 0x60 + 5e78: 031b lsls r3, r3, #12 + 5e7a: f8d3 13a0 ldr.w r1, [r3, #928] ; 0x3a0 + 5e7e: b2d0 uxtb r0, r2 + 5e80: ea21 0100 bic.w r1, r1, r0 + 5e84: f402 427f and.w r2, r2, #65280 ; 0xff00 + 5e88: 430a orrs r2, r1 + 5e8a: f8c3 23a0 str.w r2, [r3, #928] ; 0x3a0 + 5e8e: 4770 bx lr + +00005e90 : + 5e90: f24f 5311 movw r3, #62737 ; 0xf511 + 5e94: b510 push {r4, lr} + 5e96: 4604 mov r4, r0 + 5e98: f2c0 0300 movt r3, #0 + 5e9c: 2100 movs r1, #0 + 5e9e: 2268 movs r2, #104 ; 0x68 + 5ea0: 4798 blx r3 + 5ea2: f894 2028 ldrb.w r2, [r4, #40] ; 0x28 + 5ea6: 2302 movs r3, #2 + 5ea8: f042 0201 orr.w r2, r2, #1 + 5eac: f884 2028 strb.w r2, [r4, #40] ; 0x28 + 5eb0: 6163 str r3, [r4, #20] + 5eb2: 6123 str r3, [r4, #16] + 5eb4: 6263 str r3, [r4, #36] ; 0x24 + 5eb6: 6223 str r3, [r4, #32] + 5eb8: 2001 movs r0, #1 + 5eba: bd10 pop {r4, pc} + +00005ebc : + 5ebc: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 5ec0: f890 5062 ldrb.w r5, [r0, #98] ; 0x62 + 5ec4: 6886 ldr r6, [r0, #8] + 5ec6: f505 2580 add.w r5, r5, #262144 ; 0x40000 + 5eca: 3560 adds r5, #96 ; 0x60 + 5ecc: 032d lsls r5, r5, #12 + 5ece: f8d5 33a0 ldr.w r3, [r5, #928] ; 0x3a0 + 5ed2: b085 sub sp, #20 + 5ed4: 4233 tst r3, r6 + 5ed6: 4604 mov r4, r0 + 5ed8: f890 8061 ldrb.w r8, [r0, #97] ; 0x61 + 5edc: d00a beq.n 5ef4 + 5ede: f240 330c movw r3, #780 ; 0x30c + 5ee2: f2c1 0300 movt r3, #4096 ; 0x1000 + 5ee6: 681b ldr r3, [r3, #0] + 5ee8: 0798 lsls r0, r3, #30 + 5eea: f100 80ed bmi.w 60c8 + 5eee: 4620 mov r0, r4 + 5ef0: f7ff ffbc bl 5e6c + 5ef4: b2f0 uxtb r0, r6 + 5ef6: 2200 movs r2, #0 + 5ef8: f505 7730 add.w r7, r5, #704 ; 0x2c0 + 5efc: f505 763a add.w r6, r5, #744 ; 0x2e8 + 5f00: f505 7e4e add.w lr, r5, #824 ; 0x338 + 5f04: 58b9 ldr r1, [r7, r2] + 5f06: 58b3 ldr r3, [r6, r2] + 5f08: 4319 orrs r1, r3 + 5f0a: 4201 tst r1, r0 + 5f0c: ea03 0300 and.w r3, r3, r0 + 5f10: bf18 it ne + 5f12: f84e 3002 strne.w r3, [lr, r2] + 5f16: 3208 adds r2, #8 + 5f18: 2a28 cmp r2, #40 ; 0x28 + 5f1a: d1f3 bne.n 5f04 + 5f1c: f240 3e10 movw lr, #784 ; 0x310 + 5f20: f240 221f movw r2, #543 ; 0x21f + 5f24: 2100 movs r1, #0 + 5f26: f2ce 718e movt r1, #59278 ; 0xe78e + 5f2a: f2c1 0e00 movt lr, #4096 ; 0x1000 + 5f2e: f6c3 72fc movt r2, #16380 ; 0x3ffc + 5f32: 6960 ldr r0, [r4, #20] + 5f34: 6923 ldr r3, [r4, #16] + 5f36: f000 0907 and.w r9, r0, #7 + 5f3a: f894 0028 ldrb.w r0, [r4, #40] ; 0x28 + 5f3e: 69a6 ldr r6, [r4, #24] + 5f40: f003 0307 and.w r3, r3, #7 + 5f44: ea4f 1909 mov.w r9, r9, lsl #4 + 5f48: 69e7 ldr r7, [r4, #28] + 5f4a: f000 0c01 and.w ip, r0, #1 + 5f4e: ea49 0943 orr.w r9, r9, r3, lsl #1 + 5f52: ea49 090c orr.w r9, r9, ip + 5f56: f006 0c03 and.w ip, r6, #3 + 5f5a: 6a26 ldr r6, [r4, #32] + 5f5c: ea49 19cc orr.w r9, r9, ip, lsl #7 + 5f60: f007 0c03 and.w ip, r7, #3 + 5f64: 6a67 ldr r7, [r4, #36] ; 0x24 + 5f66: f04f 0a58 mov.w sl, #88 ; 0x58 + 5f6a: ea49 294c orr.w r9, r9, ip, lsl #9 + 5f6e: f006 0c07 and.w ip, r6, #7 + 5f72: 68e6 ldr r6, [r4, #12] + 5f74: fb0a f308 mul.w r3, sl, r8 + 5f78: ea49 29cc orr.w r9, r9, ip, lsl #11 + 5f7c: f007 0707 and.w r7, r7, #7 + 5f80: ea49 3987 orr.w r9, r9, r7, lsl #14 + 5f84: f006 0607 and.w r6, r6, #7 + 5f88: ea49 5606 orr.w r6, r9, r6, lsl #20 + 5f8c: f3c0 09c0 ubfx r9, r0, #3, #1 + 5f90: ea46 69c9 orr.w r9, r6, r9, lsl #27 + 5f94: 6826 ldr r6, [r4, #0] + 5f96: f103 0818 add.w r8, r3, #24 + 5f9a: f103 0c1c add.w ip, r3, #28 + 5f9e: f8cd 9004 str.w r9, [sp, #4] + 5fa2: f855 7008 ldr.w r7, [r5, r8] + 5fa6: f8b4 a02a ldrh.w sl, [r4, #42] ; 0x2a + 5faa: f855 b00c ldr.w fp, [r5, ip] + 5fae: 50ee str r6, [r5, r3] + 5fb0: 9e01 ldr r6, [sp, #4] + 5fb2: f3c0 1900 ubfx r9, r0, #4, #1 + 5fb6: ea46 7909 orr.w r9, r6, r9, lsl #28 + 5fba: 4039 ands r1, r7 + 5fbc: f3c0 1040 ubfx r0, r0, #5, #1 + 5fc0: f3ca 0a0b ubfx sl, sl, #0, #12 + 5fc4: ea4a 3a00 orr.w sl, sl, r0, lsl #12 + 5fc8: ea49 0001 orr.w r0, r9, r1 + 5fcc: 6b21 ldr r1, [r4, #48] ; 0x30 + 5fce: 6b67 ldr r7, [r4, #52] ; 0x34 + 5fd0: f42b 5bff bic.w fp, fp, #8160 ; 0x1fe0 + 5fd4: 6ae6 ldr r6, [r4, #44] ; 0x2c + 5fd6: f02b 0b1f bic.w fp, fp, #31 + 5fda: 9101 str r1, [sp, #4] + 5fdc: 6861 ldr r1, [r4, #4] + 5fde: ea4b 0a0a orr.w sl, fp, sl + 5fe2: f103 0908 add.w r9, r3, #8 + 5fe6: f007 0b03 and.w fp, r7, #3 + 5fea: 9f01 ldr r7, [sp, #4] + 5fec: f845 1009 str.w r1, [r5, r9] + 5ff0: 0176 lsls r6, r6, #5 + 5ff2: f845 0008 str.w r0, [r5, r8] + 5ff6: f845 a00c str.w sl, [r5, ip] + 5ffa: f894 003c ldrb.w r0, [r4, #60] ; 0x3c + 5ffe: b2f6 uxtb r6, r6 + 6000: 03b9 lsls r1, r7, #14 + 6002: ea46 3b0b orr.w fp, r6, fp, lsl #12 + 6006: b289 uxth r1, r1 + 6008: f000 0601 and.w r6, r0, #1 + 600c: ea4b 0b01 orr.w fp, fp, r1 + 6010: f894 103d ldrb.w r1, [r4, #61] ; 0x3d + 6014: ea4b 2b06 orr.w fp, fp, r6, lsl #8 + 6018: f3c0 0680 ubfx r6, r0, #2, #1 + 601c: ea4b 2b86 orr.w fp, fp, r6, lsl #10 + 6020: f3c1 0980 ubfx r9, r1, #2, #1 + 6024: f3c0 06c0 ubfx r6, r0, #3, #1 + 6028: f3c0 1c00 ubfx ip, r0, #4, #1 + 602c: f3c1 07c0 ubfx r7, r1, #3, #1 + 6030: ea4b 2bc6 orr.w fp, fp, r6, lsl #11 + 6034: ea4f 0949 mov.w r9, r9, lsl #1 + 6038: f103 0640 add.w r6, r3, #64 ; 0x40 + 603c: 3344 adds r3, #68 ; 0x44 + 603e: ea4b 4b0c orr.w fp, fp, ip, lsl #16 + 6042: f894 803a ldrb.w r8, [r4, #58] ; 0x3a + 6046: f855 c006 ldr.w ip, [r5, r6] + 604a: ea49 1947 orr.w r9, r9, r7, lsl #5 + 604e: f3c0 1040 ubfx r0, r0, #5, #1 + 6052: 58ef ldr r7, [r5, r3] + 6054: ea4b 4040 orr.w r0, fp, r0, lsl #17 + 6058: f3c1 1a00 ubfx sl, r1, #4, #1 + 605c: f001 0b01 and.w fp, r1, #1 + 6060: f894 403b ldrb.w r4, [r4, #59] ; 0x3b + 6064: ea40 7b8b orr.w fp, r0, fp, lsl #30 + 6068: ea49 198a orr.w r9, r9, sl, lsl #6 + 606c: f427 40ff bic.w r0, r7, #32640 ; 0x7f80 + 6070: f008 080f and.w r8, r8, #15 + 6074: f3c1 0140 ubfx r1, r1, #1, #1 + 6078: f8de 7000 ldr.w r7, [lr] + 607c: ea4b 71c1 orr.w r1, fp, r1, lsl #31 + 6080: ea49 19c8 orr.w r9, r9, r8, lsl #7 + 6084: f004 040f and.w r4, r4, #15 + 6088: ea0c 0202 and.w r2, ip, r2 + 608c: ea49 24c4 orr.w r4, r9, r4, lsl #11 + 6090: f020 0062 bic.w r0, r0, #98 ; 0x62 + 6094: 430a orrs r2, r1 + 6096: 07b9 lsls r1, r7, #30 + 6098: ea44 0400 orr.w r4, r4, r0 + 609c: d405 bmi.n 60aa + 609e: 2001 movs r0, #1 + 60a0: 51aa str r2, [r5, r6] + 60a2: 50ec str r4, [r5, r3] + 60a4: b005 add sp, #20 + 60a6: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 60aa: f64f 7084 movw r0, #65412 ; 0xff84 + 60ae: f24f 379d movw r7, #62365 ; 0xf39d + 60b2: 4611 mov r1, r2 + 60b4: 9203 str r2, [sp, #12] + 60b6: 9302 str r3, [sp, #8] + 60b8: f2c0 0003 movt r0, #3 + 60bc: f2c0 0700 movt r7, #0 + 60c0: 47b8 blx r7 + 60c2: 9b02 ldr r3, [sp, #8] + 60c4: 9a03 ldr r2, [sp, #12] + 60c6: e7ea b.n 609e + 60c8: f64f 7050 movw r0, #65360 ; 0xff50 + 60cc: f24f 339d movw r3, #62365 ; 0xf39d + 60d0: f2c0 0003 movt r0, #3 + 60d4: f2c0 0300 movt r3, #0 + 60d8: 4798 blx r3 + 60da: e708 b.n 5eee + +000060dc : + 60dc: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 60e0: f890 7062 ldrb.w r7, [r0, #98] ; 0x62 + 60e4: 6d03 ldr r3, [r0, #80] ; 0x50 + 60e6: f507 2780 add.w r7, r7, #262144 ; 0x40000 + 60ea: 3760 adds r7, #96 ; 0x60 + 60ec: 033f lsls r7, r7, #12 + 60ee: f8d7 23a0 ldr.w r2, [r7, #928] ; 0x3a0 + 60f2: f8d0 9008 ldr.w r9, [r0, #8] + 60f6: 6819 ldr r1, [r3, #0] + 60f8: 685d ldr r5, [r3, #4] + 60fa: 6d43 ldr r3, [r0, #84] ; 0x54 + 60fc: b089 sub sp, #36 ; 0x24 + 60fe: ea12 0f09 tst.w r2, r9 + 6102: 4604 mov r4, r0 + 6104: 9106 str r1, [sp, #24] + 6106: 6cc6 ldr r6, [r0, #76] ; 0x4c + 6108: f890 8061 ldrb.w r8, [r0, #97] ; 0x61 + 610c: 9307 str r3, [sp, #28] + 610e: d00a beq.n 6126 + 6110: f240 330c movw r3, #780 ; 0x30c + 6114: f2c1 0300 movt r3, #4096 ; 0x1000 + 6118: 681b ldr r3, [r3, #0] + 611a: 079a lsls r2, r3, #30 + 611c: f100 8159 bmi.w 63d2 + 6120: 4620 mov r0, r4 + 6122: f7ff fea3 bl 5e6c + 6126: fa5f f189 uxtb.w r1, r9 + 612a: 2300 movs r3, #0 + 612c: f507 7c30 add.w ip, r7, #704 ; 0x2c0 + 6130: f507 7e3a add.w lr, r7, #744 ; 0x2e8 + 6134: f507 794e add.w r9, r7, #824 ; 0x338 + 6138: f85c 0003 ldr.w r0, [ip, r3] + 613c: f85e 2003 ldr.w r2, [lr, r3] + 6140: 4310 orrs r0, r2 + 6142: 4208 tst r0, r1 + 6144: ea02 0201 and.w r2, r2, r1 + 6148: bf18 it ne + 614a: f849 2003 strne.w r2, [r9, r3] + 614e: 3308 adds r3, #8 + 6150: 2b28 cmp r3, #40 ; 0x28 + 6152: d1f1 bne.n 6138 + 6154: f240 231f movw r3, #543 ; 0x21f + 6158: 2200 movs r2, #0 + 615a: f2ce 728e movt r2, #59278 ; 0xe78e + 615e: 2158 movs r1, #88 ; 0x58 + 6160: fb01 f108 mul.w r1, r1, r8 + 6164: 9105 str r1, [sp, #20] + 6166: f8dd 8014 ldr.w r8, [sp, #20] + 616a: 6821 ldr r1, [r4, #0] + 616c: 9805 ldr r0, [sp, #20] + 616e: f847 1008 str.w r1, [r7, r8] + 6172: 6861 ldr r1, [r4, #4] + 6174: f8d4 9014 ldr.w r9, [r4, #20] + 6178: 3008 adds r0, #8 + 617a: 5039 str r1, [r7, r0] + 617c: 6920 ldr r0, [r4, #16] + 617e: f894 1028 ldrb.w r1, [r4, #40] ; 0x28 + 6182: f009 0907 and.w r9, r9, #7 + 6186: f000 0c07 and.w ip, r0, #7 + 618a: ea4f 1909 mov.w r9, r9, lsl #4 + 618e: 69a0 ldr r0, [r4, #24] + 6190: f001 0e01 and.w lr, r1, #1 + 6194: ea49 094c orr.w r9, r9, ip, lsl #1 + 6198: ea49 090e orr.w r9, r9, lr + 619c: f000 0e03 and.w lr, r0, #3 + 61a0: 69e0 ldr r0, [r4, #28] + 61a2: ea49 19ce orr.w r9, r9, lr, lsl #7 + 61a6: f000 0e03 and.w lr, r0, #3 + 61aa: 6a20 ldr r0, [r4, #32] + 61ac: f6c3 73fc movt r3, #16380 ; 0x3ffc + 61b0: ea49 294e orr.w r9, r9, lr, lsl #9 + 61b4: f000 0e07 and.w lr, r0, #7 + 61b8: 6a60 ldr r0, [r4, #36] ; 0x24 + 61ba: ea49 29ce orr.w r9, r9, lr, lsl #11 + 61be: f000 0807 and.w r8, r0, #7 + 61c2: 68e0 ldr r0, [r4, #12] + 61c4: f8dd e014 ldr.w lr, [sp, #20] + 61c8: f000 0a07 and.w sl, r0, #7 + 61cc: 9807 ldr r0, [sp, #28] + 61ce: ea49 3988 orr.w r9, r9, r8, lsl #14 + 61d2: 6800 ldr r0, [r0, #0] + 61d4: f10e 0c18 add.w ip, lr, #24 + 61d8: ea49 590a orr.w r9, r9, sl, lsl #20 + 61dc: f3c1 0ac0 ubfx sl, r1, #3, #1 + 61e0: f857 800c ldr.w r8, [r7, ip] + 61e4: f10e 0e1c add.w lr, lr, #28 + 61e8: 9003 str r0, [sp, #12] + 61ea: ea49 69ca orr.w r9, r9, sl, lsl #27 + 61ee: f3c1 1a00 ubfx sl, r1, #4, #1 + 61f2: f3c1 1140 ubfx r1, r1, #5, #1 + 61f6: f857 000e ldr.w r0, [r7, lr] + 61fa: 9104 str r1, [sp, #16] + 61fc: 9903 ldr r1, [sp, #12] + 61fe: ea08 0202 and.w r2, r8, r2 + 6202: f8dd 8010 ldr.w r8, [sp, #16] + 6206: f420 5bff bic.w fp, r0, #8160 ; 0x1fe0 + 620a: f3c1 000b ubfx r0, r1, #0, #12 + 620e: ea40 3108 orr.w r1, r0, r8, lsl #12 + 6212: ea49 790a orr.w r9, r9, sl, lsl #28 + 6216: 6ae0 ldr r0, [r4, #44] ; 0x2c + 6218: f02b 0b1f bic.w fp, fp, #31 + 621c: f8d4 8034 ldr.w r8, [r4, #52] ; 0x34 + 6220: ea49 0902 orr.w r9, r9, r2 + 6224: ea41 020b orr.w r2, r1, fp + 6228: 6b21 ldr r1, [r4, #48] ; 0x30 + 622a: 0140 lsls r0, r0, #5 + 622c: f847 900c str.w r9, [r7, ip] + 6230: f847 200e str.w r2, [r7, lr] + 6234: f894 e03c ldrb.w lr, [r4, #60] ; 0x3c + 6238: f008 0803 and.w r8, r8, #3 + 623c: 0389 lsls r1, r1, #14 + 623e: b2c0 uxtb r0, r0 + 6240: ea40 3008 orr.w r0, r0, r8, lsl #12 + 6244: fa1f fc81 uxth.w ip, r1 + 6248: f00e 0a01 and.w sl, lr, #1 + 624c: ea40 0c0c orr.w ip, r0, ip + 6250: ea4c 2c0a orr.w ip, ip, sl, lsl #8 + 6254: f3ce 0080 ubfx r0, lr, #2, #1 + 6258: ea4c 2c80 orr.w ip, ip, r0, lsl #10 + 625c: f3ce 00c0 ubfx r0, lr, #3, #1 + 6260: ea4c 2cc0 orr.w ip, ip, r0, lsl #11 + 6264: 9805 ldr r0, [sp, #20] + 6266: f894 103d ldrb.w r1, [r4, #61] ; 0x3d + 626a: f3ce 1800 ubfx r8, lr, #4, #1 + 626e: 3040 adds r0, #64 ; 0x40 + 6270: ea4c 4c08 orr.w ip, ip, r8, lsl #16 + 6274: f8dd 8014 ldr.w r8, [sp, #20] + 6278: 9004 str r0, [sp, #16] + 627a: f3c1 0a80 ubfx sl, r1, #2, #1 + 627e: f3ce 1e40 ubfx lr, lr, #5, #1 + 6282: f108 0b44 add.w fp, r8, #68 ; 0x44 + 6286: ea4c 4c4e orr.w ip, ip, lr, lsl #17 + 628a: f8dd 8010 ldr.w r8, [sp, #16] + 628e: f3c1 0ec0 ubfx lr, r1, #3, #1 + 6292: ea4f 0a4a mov.w sl, sl, lsl #1 + 6296: ea4a 1a4e orr.w sl, sl, lr, lsl #5 + 629a: f894 003a ldrb.w r0, [r4, #58] ; 0x3a + 629e: f001 0e01 and.w lr, r1, #1 + 62a2: ea4c 7c8e orr.w ip, ip, lr, lsl #30 + 62a6: f857 e008 ldr.w lr, [r7, r8] + 62aa: f3c1 0840 ubfx r8, r1, #1, #1 + 62ae: f3c1 1100 ubfx r1, r1, #4, #1 + 62b2: f000 000f and.w r0, r0, #15 + 62b6: ea4a 1181 orr.w r1, sl, r1, lsl #6 + 62ba: ea41 11c0 orr.w r1, r1, r0, lsl #7 + 62be: f857 a00b ldr.w sl, [r7, fp] + 62c2: f894 003b ldrb.w r0, [r4, #59] ; 0x3b + 62c6: f42a 4aff bic.w sl, sl, #32640 ; 0x7f80 + 62ca: f000 000f and.w r0, r0, #15 + 62ce: ea0e 0303 and.w r3, lr, r3 + 62d2: ea4c 7cc8 orr.w ip, ip, r8, lsl #31 + 62d6: f02a 0a62 bic.w sl, sl, #98 ; 0x62 + 62da: ea41 21c0 orr.w r1, r1, r0, lsl #11 + 62de: f8dd e010 ldr.w lr, [sp, #16] + 62e2: ea4c 0303 orr.w r3, ip, r3 + 62e6: ea41 010a orr.w r1, r1, sl + 62ea: f847 300e str.w r3, [r7, lr] + 62ee: f847 100b str.w r1, [r7, fp] + 62f2: 9906 ldr r1, [sp, #24] + 62f4: 078b lsls r3, r1, #30 + 62f6: d00a beq.n 630e + 62f8: f240 330c movw r3, #780 ; 0x30c + 62fc: f2c1 0300 movt r3, #4096 ; 0x1000 + 6300: 681b ldr r3, [r3, #0] + 6302: 079d lsls r5, r3, #30 + 6304: d47c bmi.n 6400 + 6306: 2000 movs r0, #0 + 6308: b009 add sp, #36 ; 0x24 + 630a: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 630e: f240 3410 movw r4, #784 ; 0x310 + 6312: f2c1 0400 movt r4, #4096 ; 0x1000 + 6316: 9b05 ldr r3, [sp, #20] + 6318: 9906 ldr r1, [sp, #24] + 631a: 3310 adds r3, #16 + 631c: 50f9 str r1, [r7, r3] + 631e: 6823 ldr r3, [r4, #0] + 6320: 6829 ldr r1, [r5, #0] + 6322: f8dd 8018 ldr.w r8, [sp, #24] + 6326: 0798 lsls r0, r3, #30 + 6328: f8c8 900c str.w r9, [r8, #12] + 632c: f8c8 2010 str.w r2, [r8, #16] + 6330: f8c8 1008 str.w r1, [r8, #8] + 6334: d457 bmi.n 63e6 + 6336: f8dd 801c ldr.w r8, [sp, #28] + 633a: 2e01 cmp r6, #1 + 633c: f8d8 3004 ldr.w r3, [r8, #4] + 6340: d929 bls.n 6396 + 6342: f24f 3a9d movw sl, #62365 ; 0xf39d + 6346: f2c0 0a00 movt sl, #0 + 634a: e00b b.n 6364 + 634c: 2e01 cmp r6, #1 + 634e: d02f beq.n 63b0 + 6350: 686d ldr r5, [r5, #4] + 6352: 6818 ldr r0, [r3, #0] + 6354: 6829 ldr r1, [r5, #0] + 6356: f360 020b bfi r2, r0, #0, #12 + 635a: 685b ldr r3, [r3, #4] + 635c: 60b9 str r1, [r7, #8] + 635e: 613a str r2, [r7, #16] + 6360: f8c7 900c str.w r9, [r7, #12] + 6364: 6821 ldr r1, [r4, #0] + 6366: 3e01 subs r6, #1 + 6368: 0789 lsls r1, r1, #30 + 636a: d416 bmi.n 639a + 636c: 682f ldr r7, [r5, #0] + 636e: 2f00 cmp r7, #0 + 6370: d1ec bne.n 634c + 6372: f240 3314 movw r3, #788 ; 0x314 + 6376: f2c1 0300 movt r3, #4096 ; 0x1000 + 637a: 681b ldr r3, [r3, #0] + 637c: 005b lsls r3, r3, #1 + 637e: d5c2 bpl.n 6306 + 6380: f64f 70f8 movw r0, #65528 ; 0xfff8 + 6384: f24f 339d movw r3, #62365 ; 0xf39d + 6388: f2c0 0003 movt r0, #3 + 638c: f2c0 0300 movt r3, #0 + 6390: 4798 blx r3 + 6392: 4638 mov r0, r7 + 6394: e7b8 b.n 6308 + 6396: 2001 movs r0, #1 + 6398: e7b6 b.n 6308 + 639a: f64f 70dc movw r0, #65500 ; 0xffdc + 639e: 9201 str r2, [sp, #4] + 63a0: 9302 str r3, [sp, #8] + 63a2: 4631 mov r1, r6 + 63a4: f2c0 0003 movt r0, #3 + 63a8: 47d0 blx sl + 63aa: 9b02 ldr r3, [sp, #8] + 63ac: 9a01 ldr r2, [sp, #4] + 63ae: e7dd b.n 636c + 63b0: 6819 ldr r1, [r3, #0] + 63b2: 686b ldr r3, [r5, #4] + 63b4: f422 627f bic.w r2, r2, #4080 ; 0xff0 + 63b8: 681b ldr r3, [r3, #0] + 63ba: f022 020f bic.w r2, r2, #15 + 63be: f3c1 010b ubfx r1, r1, #0, #12 + 63c2: 4311 orrs r1, r2 + 63c4: f029 52c0 bic.w r2, r9, #402653184 ; 0x18000000 + 63c8: 6139 str r1, [r7, #16] + 63ca: 60bb str r3, [r7, #8] + 63cc: 60fa str r2, [r7, #12] + 63ce: 4630 mov r0, r6 + 63d0: e79a b.n 6308 + 63d2: f64f 7050 movw r0, #65360 ; 0xff50 + 63d6: f24f 339d movw r3, #62365 ; 0xf39d + 63da: f2c0 0003 movt r0, #3 + 63de: f2c0 0300 movt r3, #0 + 63e2: 4798 blx r3 + 63e4: e69c b.n 6120 + 63e6: f64f 70dc movw r0, #65500 ; 0xffdc + 63ea: f24f 339d movw r3, #62365 ; 0xf39d + 63ee: 9201 str r2, [sp, #4] + 63f0: f2c0 0003 movt r0, #3 + 63f4: f2c0 0300 movt r3, #0 + 63f8: 4631 mov r1, r6 + 63fa: 4798 blx r3 + 63fc: 9a01 ldr r2, [sp, #4] + 63fe: e79a b.n 6336 + 6400: f64f 70a4 movw r0, #65444 ; 0xffa4 + 6404: f24f 339d movw r3, #62365 ; 0xf39d + 6408: 6da1 ldr r1, [r4, #88] ; 0x58 + 640a: f2c0 0300 movt r3, #0 + 640e: f2c0 0003 movt r0, #3 + 6412: 4798 blx r3 + 6414: e777 b.n 6306 + 6416: bf00 nop + +00006418 : + 6418: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} + 641c: f240 3610 movw r6, #784 ; 0x310 + 6420: f24f 399d movw r9, #62365 ; 0xf39d + 6424: 2400 movs r4, #0 + 6426: 4605 mov r5, r0 + 6428: f2c1 0600 movt r6, #4096 ; 0x1000 + 642c: f2c0 0900 movt r9, #0 + 6430: 4627 mov r7, r4 + 6432: f04f 0801 mov.w r8, #1 + 6436: f895 3062 ldrb.w r3, [r5, #98] ; 0x62 + 643a: 6831 ldr r1, [r6, #0] + 643c: f503 2380 add.w r3, r3, #262144 ; 0x40000 + 6440: eb04 2343 add.w r3, r4, r3, lsl #9 + 6444: f503 4340 add.w r3, r3, #49152 ; 0xc000 + 6448: 3358 adds r3, #88 ; 0x58 + 644a: 00db lsls r3, r3, #3 + 644c: 078a lsls r2, r1, #30 + 644e: f8d3 a000 ldr.w sl, [r3] + 6452: d41d bmi.n 6490 + 6454: f895 3064 ldrb.w r3, [r5, #100] ; 0x64 + 6458: 68aa ldr r2, [r5, #8] + 645a: 4123 asrs r3, r4 + 645c: 07db lsls r3, r3, #31 + 645e: d511 bpl.n 6484 + 6460: f895 3062 ldrb.w r3, [r5, #98] ; 0x62 + 6464: b2d2 uxtb r2, r2 + 6466: f503 2380 add.w r3, r3, #262144 ; 0x40000 + 646a: eb04 2343 add.w r3, r4, r3, lsl #9 + 646e: f503 4340 add.w r3, r3, #49152 ; 0xc000 + 6472: 3367 adds r3, #103 ; 0x67 + 6474: fa08 f104 lsl.w r1, r8, r4 + 6478: ea02 020a and.w r2, r2, sl + 647c: 00db lsls r3, r3, #3 + 647e: 430f orrs r7, r1 + 6480: 601a str r2, [r3, #0] + 6482: b2ff uxtb r7, r7 + 6484: 3401 adds r4, #1 + 6486: 2c05 cmp r4, #5 + 6488: d1d5 bne.n 6436 + 648a: 4638 mov r0, r7 + 648c: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + 6490: f240 0014 movw r0, #20 + 6494: 4621 mov r1, r4 + 6496: 4652 mov r2, sl + 6498: f2c0 0004 movt r0, #4 + 649c: 47c8 blx r9 + 649e: e7d9 b.n 6454 + +000064a0 : + 64a0: b538 push {r3, r4, r5, lr} + 64a2: f240 3310 movw r3, #784 ; 0x310 + 64a6: f2c1 0300 movt r3, #4096 ; 0x1000 + 64aa: f890 1061 ldrb.w r1, [r0, #97] ; 0x61 + 64ae: 2458 movs r4, #88 ; 0x58 + 64b0: 4602 mov r2, r0 + 64b2: fb04 f101 mul.w r1, r4, r1 + 64b6: f890 0062 ldrb.w r0, [r0, #98] ; 0x62 + 64ba: 3140 adds r1, #64 ; 0x40 + 64bc: f500 2080 add.w r0, r0, #262144 ; 0x40000 + 64c0: 3060 adds r0, #96 ; 0x60 + 64c2: 0300 lsls r0, r0, #12 + 64c4: 5845 ldr r5, [r0, r1] + 64c6: f025 4580 bic.w r5, r5, #1073741824 ; 0x40000000 + 64ca: 5045 str r5, [r0, r1] + 64cc: 681b ldr r3, [r3, #0] + 64ce: 079b lsls r3, r3, #30 + 64d0: d400 bmi.n 64d4 + 64d2: bd38 pop {r3, r4, r5, pc} + 64d4: f64f 7084 movw r0, #65412 ; 0xff84 + 64d8: f24f 339d movw r3, #62365 ; 0xf39d + 64dc: f892 5061 ldrb.w r5, [r2, #97] ; 0x61 + 64e0: f892 1062 ldrb.w r1, [r2, #98] ; 0x62 + 64e4: fb04 f205 mul.w r2, r4, r5 + 64e8: f501 2180 add.w r1, r1, #262144 ; 0x40000 + 64ec: 3160 adds r1, #96 ; 0x60 + 64ee: 3240 adds r2, #64 ; 0x40 + 64f0: 0309 lsls r1, r1, #12 + 64f2: 5889 ldr r1, [r1, r2] + 64f4: f2c0 0300 movt r3, #0 + 64f8: f2c0 0003 movt r0, #3 + 64fc: 4798 blx r3 + 64fe: e7e8 b.n 64d2 + +00006500 : + 6500: b538 push {r3, r4, r5, lr} + 6502: f240 3310 movw r3, #784 ; 0x310 + 6506: f2c1 0300 movt r3, #4096 ; 0x1000 + 650a: f890 1061 ldrb.w r1, [r0, #97] ; 0x61 + 650e: 2458 movs r4, #88 ; 0x58 + 6510: 4602 mov r2, r0 + 6512: fb04 f101 mul.w r1, r4, r1 + 6516: f890 0062 ldrb.w r0, [r0, #98] ; 0x62 + 651a: 3140 adds r1, #64 ; 0x40 + 651c: f500 2080 add.w r0, r0, #262144 ; 0x40000 + 6520: 3060 adds r0, #96 ; 0x60 + 6522: 0300 lsls r0, r0, #12 + 6524: 5845 ldr r5, [r0, r1] + 6526: f025 4500 bic.w r5, r5, #2147483648 ; 0x80000000 + 652a: 5045 str r5, [r0, r1] + 652c: 681b ldr r3, [r3, #0] + 652e: 079b lsls r3, r3, #30 + 6530: d400 bmi.n 6534 + 6532: bd38 pop {r3, r4, r5, pc} + 6534: f64f 7084 movw r0, #65412 ; 0xff84 + 6538: f24f 339d movw r3, #62365 ; 0xf39d + 653c: f892 5061 ldrb.w r5, [r2, #97] ; 0x61 + 6540: f892 1062 ldrb.w r1, [r2, #98] ; 0x62 + 6544: fb04 f205 mul.w r2, r4, r5 + 6548: f501 2180 add.w r1, r1, #262144 ; 0x40000 + 654c: 3160 adds r1, #96 ; 0x60 + 654e: 3240 adds r2, #64 ; 0x40 + 6550: 0309 lsls r1, r1, #12 + 6552: 5889 ldr r1, [r1, r2] + 6554: f2c0 0300 movt r3, #0 + 6558: f2c0 0003 movt r0, #3 + 655c: 4798 blx r3 + 655e: e7e8 b.n 6532 + +00006560 : + 6560: 2901 cmp r1, #1 + 6562: d011 beq.n 6588 + 6564: 23e0 movs r3, #224 ; 0xe0 + 6566: f2c4 0300 movt r3, #16384 ; 0x4000 + 656a: 681a ldr r2, [r3, #0] + 656c: 2801 cmp r0, #1 + 656e: f022 427f bic.w r2, r2, #4278190080 ; 0xff000000 + 6572: 601a str r2, [r3, #0] + 6574: d000 beq.n 6578 + 6576: 4770 bx lr + 6578: 2340 movs r3, #64 ; 0x40 + 657a: f2c4 0300 movt r3, #16384 ; 0x4000 + 657e: 681a ldr r2, [r3, #0] + 6580: f022 0201 bic.w r2, r2, #1 + 6584: 601a str r2, [r3, #0] + 6586: 4770 bx lr + 6588: 23e0 movs r3, #224 ; 0xe0 + 658a: f2c4 0300 movt r3, #16384 ; 0x4000 + 658e: 2108 movs r1, #8 + 6590: f2c4 0100 movt r1, #16384 ; 0x4000 + 6594: b410 push {r4} + 6596: 681c ldr r4, [r3, #0] + 6598: f024 447f bic.w r4, r4, #4278190080 ; 0xff000000 + 659c: f044 44d2 orr.w r4, r4, #1761607680 ; 0x69000000 + 65a0: 601c str r4, [r3, #0] + 65a2: 680b ldr r3, [r1, #0] + 65a4: 07dc lsls r4, r3, #31 + 65a6: bf5c itt pl + 65a8: f043 0301 orrpl.w r3, r3, #1 + 65ac: 600b strpl r3, [r1, #0] + 65ae: 2310 movs r3, #16 + 65b0: f2c4 0300 movt r3, #16384 ; 0x4000 + 65b4: 6819 ldr r1, [r3, #0] + 65b6: 078c lsls r4, r1, #30 + 65b8: bf5c itt pl + 65ba: f041 0102 orrpl.w r1, r1, #2 + 65be: 6019 strpl r1, [r3, #0] + 65c0: 2314 movs r3, #20 + 65c2: f2c4 0300 movt r3, #16384 ; 0x4000 + 65c6: 6819 ldr r1, [r3, #0] + 65c8: 07cc lsls r4, r1, #31 + 65ca: bf5c itt pl + 65cc: f041 0101 orrpl.w r1, r1, #1 + 65d0: 6019 strpl r1, [r3, #0] + 65d2: 2801 cmp r0, #1 + 65d4: d002 beq.n 65dc + 65d6: f85d 4b04 ldr.w r4, [sp], #4 + 65da: 4770 bx lr + 65dc: 2340 movs r3, #64 ; 0x40 + 65de: f2c4 0300 movt r3, #16384 ; 0x4000 + 65e2: 6819 ldr r1, [r3, #0] + 65e4: f002 020f and.w r2, r2, #15 + 65e8: f421 6170 bic.w r1, r1, #3840 ; 0xf00 + 65ec: f041 0101 orr.w r1, r1, #1 + 65f0: ea41 2202 orr.w r2, r1, r2, lsl #8 + 65f4: 601a str r2, [r3, #0] + 65f6: e7ee b.n 65d6 + +000065f8 : + 65f8: 29ff cmp r1, #255 ; 0xff + 65fa: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} + 65fe: 4688 mov r8, r1 + 6600: 4681 mov r9, r0 + 6602: 4617 mov r7, r2 + 6604: 461e mov r6, r3 + 6606: d909 bls.n 661c + 6608: f242 63ae movw r3, #9902 ; 0x26ae + 660c: b282 uxth r2, r0 + 660e: 429a cmp r2, r3 + 6610: d004 beq.n 661c + 6612: 23ff movs r3, #255 ; 0xff + 6614: 703b strb r3, [r7, #0] + 6616: 2000 movs r0, #0 + 6618: e8bd 83f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} + 661c: 2001 movs r0, #1 + 661e: 4632 mov r2, r6 + 6620: 4601 mov r1, r0 + 6622: f7ff ff9d bl 6560 + 6626: 23ec movs r3, #236 ; 0xec + 6628: f2c4 0300 movt r3, #16384 ; 0x4000 + 662c: 2400 movs r4, #0 + 662e: f6c7 74fc movt r4, #32764 ; 0x7ffc + 6632: 25e8 movs r5, #232 ; 0xe8 + 6634: f2c4 0500 movt r5, #16384 ; 0x4000 + 6638: 681a ldr r2, [r3, #0] + 663a: f3c8 0809 ubfx r8, r8, #0, #10 + 663e: ea09 0404 and.w r4, r9, r4 + 6642: ea44 2408 orr.w r4, r4, r8, lsl #8 + 6646: f422 6200 bic.w r2, r2, #2048 ; 0x800 + 664a: 601a str r2, [r3, #0] + 664c: 602c str r4, [r5, #0] + 664e: 682b ldr r3, [r5, #0] + 6650: 2b00 cmp r3, #0 + 6652: bfa8 it ge + 6654: 2400 movge r4, #0 + 6656: da02 bge.n 665e + 6658: e00c b.n 6674 + 665a: 2c64 cmp r4, #100 ; 0x64 + 665c: d018 beq.n 6690 + 665e: f44f 707a mov.w r0, #1000 ; 0x3e8 + 6662: f7fa f919 bl 898 + 6666: 6829 ldr r1, [r5, #0] + 6668: 3401 adds r4, #1 + 666a: 2900 cmp r1, #0 + 666c: b2e4 uxtb r4, r4 + 666e: daf4 bge.n 665a + 6670: 2c64 cmp r4, #100 ; 0x64 + 6672: d00d beq.n 6690 + 6674: 23e8 movs r3, #232 ; 0xe8 + 6676: f2c4 0300 movt r3, #16384 ; 0x4000 + 667a: 681b ldr r3, [r3, #0] + 667c: 2401 movs r4, #1 + 667e: 703b strb r3, [r7, #0] + 6680: 4632 mov r2, r6 + 6682: 2001 movs r0, #1 + 6684: 2100 movs r1, #0 + 6686: f7ff ff6b bl 6560 + 668a: 4620 mov r0, r4 + 668c: e8bd 83f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} + 6690: 23ff movs r3, #255 ; 0xff + 6692: 703b strb r3, [r7, #0] + 6694: 2400 movs r4, #0 + 6696: e7f3 b.n 6680 + +00006698 : + 6698: 29ff cmp r1, #255 ; 0xff + 669a: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} + 669e: 460e mov r6, r1 + 66a0: 4680 mov r8, r0 + 66a2: 4691 mov r9, r2 + 66a4: 461f mov r7, r3 + 66a6: d907 bls.n 66b8 + 66a8: f241 539d movw r3, #5533 ; 0x159d + 66ac: b282 uxth r2, r0 + 66ae: 429a cmp r2, r3 + 66b0: d002 beq.n 66b8 + 66b2: 2000 movs r0, #0 + 66b4: e8bd 83f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} + 66b8: 2001 movs r0, #1 + 66ba: 4601 mov r1, r0 + 66bc: 463a mov r2, r7 + 66be: f7ff ff4f bl 6560 + 66c2: 2400 movs r4, #0 + 66c4: 23ec movs r3, #236 ; 0xec + 66c6: f2c4 0300 movt r3, #16384 ; 0x4000 + 66ca: f6c7 74fc movt r4, #32764 ; 0x7ffc + 66ce: 25e8 movs r5, #232 ; 0xe8 + 66d0: f2c4 0500 movt r5, #16384 ; 0x4000 + 66d4: 681a ldr r2, [r3, #0] + 66d6: f049 4900 orr.w r9, r9, #2147483648 ; 0x80000000 + 66da: ea08 0404 and.w r4, r8, r4 + 66de: f3c6 0609 ubfx r6, r6, #0, #10 + 66e2: ea49 0404 orr.w r4, r9, r4 + 66e6: ea44 2406 orr.w r4, r4, r6, lsl #8 + 66ea: f442 6200 orr.w r2, r2, #2048 ; 0x800 + 66ee: 601a str r2, [r3, #0] + 66f0: f44f 707a mov.w r0, #1000 ; 0x3e8 + 66f4: 602c str r4, [r5, #0] + 66f6: f7fa f8cf bl 898 + 66fa: 682b ldr r3, [r5, #0] + 66fc: 2b00 cmp r3, #0 + 66fe: bfb8 it lt + 6700: 2400 movlt r4, #0 + 6702: db02 blt.n 670a + 6704: e00c b.n 6720 + 6706: 2c64 cmp r4, #100 ; 0x64 + 6708: d01a beq.n 6740 + 670a: f44f 707a mov.w r0, #1000 ; 0x3e8 + 670e: f7fa f8c3 bl 898 + 6712: 6829 ldr r1, [r5, #0] + 6714: 3401 adds r4, #1 + 6716: 2900 cmp r1, #0 + 6718: b2e4 uxtb r4, r4 + 671a: dbf4 blt.n 6706 + 671c: 2c64 cmp r4, #100 ; 0x64 + 671e: d00f beq.n 6740 + 6720: 2401 movs r4, #1 + 6722: 23ec movs r3, #236 ; 0xec + 6724: f2c4 0300 movt r3, #16384 ; 0x4000 + 6728: 6819 ldr r1, [r3, #0] + 672a: 463a mov r2, r7 + 672c: f421 6100 bic.w r1, r1, #2048 ; 0x800 + 6730: 6019 str r1, [r3, #0] + 6732: 2001 movs r0, #1 + 6734: 2100 movs r1, #0 + 6736: f7ff ff13 bl 6560 + 673a: 4620 mov r0, r4 + 673c: e8bd 83f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} + 6740: 2400 movs r4, #0 + 6742: e7ee b.n 6722 + +00006744 <__rtl_memDump_v1_00.part.7>: + 6744: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 6748: f24f 349d movw r4, #62365 ; 0xf39d + 674c: b083 sub sp, #12 + 674e: 4606 mov r6, r0 + 6750: 468b mov fp, r1 + 6752: f2c0 0400 movt r4, #0 + 6756: b14a cbz r2, 676c <__rtl_memDump_v1_00.part.7+0x28> + 6758: f240 0058 movw r0, #88 ; 0x58 + 675c: f24f 349d movw r4, #62365 ; 0xf39d + 6760: 4611 mov r1, r2 + 6762: f2c0 0004 movt r0, #4 + 6766: f2c0 0400 movt r4, #0 + 676a: 47a0 blx r4 + 676c: f24f 339d movw r3, #62365 ; 0xf39d + 6770: f2c0 0300 movt r3, #0 + 6774: ea4f 181b mov.w r8, fp, lsr #4 + 6778: 9300 str r3, [sp, #0] + 677a: f00b 030f and.w r3, fp, #15 + 677e: 9301 str r3, [sp, #4] + 6780: f108 0901 add.w r9, r8, #1 + 6784: 2700 movs r7, #0 + 6786: 45b8 cmp r8, r7 + 6788: bf18 it ne + 678a: 2510 movne r5, #16 + 678c: d041 beq.n 6812 <__rtl_memDump_v1_00.part.7+0xce> + 678e: f240 0060 movw r0, #96 ; 0x60 + 6792: 4631 mov r1, r6 + 6794: f2c0 0004 movt r0, #4 + 6798: 47a0 blx r4 + 679a: f04f 0a00 mov.w sl, #0 + 679e: e002 b.n 67a6 <__rtl_memDump_v1_00.part.7+0x62> + 67a0: f1ba 0f08 cmp.w sl, #8 + 67a4: d02e beq.n 6804 <__rtl_memDump_v1_00.part.7+0xc0> + 67a6: f240 0070 movw r0, #112 ; 0x70 + 67aa: f24f 3b9d movw fp, #62365 ; 0xf39d + 67ae: f816 100a ldrb.w r1, [r6, sl] + 67b2: f2c0 0004 movt r0, #4 + 67b6: f10a 0a01 add.w sl, sl, #1 + 67ba: 47a0 blx r4 + 67bc: 45aa cmp sl, r5 + 67be: f2c0 0b00 movt fp, #0 + 67c2: dbed blt.n 67a0 <__rtl_memDump_v1_00.part.7+0x5c> + 67c4: 2d10 cmp r5, #16 + 67c6: d00a beq.n 67de <__rtl_memDump_v1_00.part.7+0x9a> + 67c8: 2d07 cmp r5, #7 + 67ca: dd15 ble.n 67f8 <__rtl_memDump_v1_00.part.7+0xb4> + 67cc: f1c5 0510 rsb r5, r5, #16 + 67d0: f240 0078 movw r0, #120 ; 0x78 + 67d4: f2c0 0004 movt r0, #4 + 67d8: 47a0 blx r4 + 67da: 3d01 subs r5, #1 + 67dc: d1f8 bne.n 67d0 <__rtl_memDump_v1_00.part.7+0x8c> + 67de: 3701 adds r7, #1 + 67e0: 45b9 cmp r9, r7 + 67e2: f106 0610 add.w r6, r6, #16 + 67e6: dcce bgt.n 6786 <__rtl_memDump_v1_00.part.7+0x42> + 67e8: f240 005c movw r0, #92 ; 0x5c + 67ec: f2c0 0004 movt r0, #4 + 67f0: 47a0 blx r4 + 67f2: b003 add sp, #12 + 67f4: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 67f8: f240 006c movw r0, #108 ; 0x6c + 67fc: f2c0 0004 movt r0, #4 + 6800: 47d8 blx fp + 6802: e7e3 b.n 67cc <__rtl_memDump_v1_00.part.7+0x88> + 6804: f240 006c movw r0, #108 ; 0x6c + 6808: 9b00 ldr r3, [sp, #0] + 680a: f2c0 0004 movt r0, #4 + 680e: 4798 blx r3 + 6810: e7c9 b.n 67a6 <__rtl_memDump_v1_00.part.7+0x62> + 6812: 9b01 ldr r3, [sp, #4] + 6814: 2b00 cmp r3, #0 + 6816: d0e7 beq.n 67e8 <__rtl_memDump_v1_00.part.7+0xa4> + 6818: 9d01 ldr r5, [sp, #4] + 681a: e7b8 b.n 678e <__rtl_memDump_v1_00.part.7+0x4a> + +0000681c <__rtl_memcmpb_v1_00>: + 681c: 2a00 cmp r2, #0 + 681e: dd1d ble.n 685c <__rtl_memcmpb_v1_00+0x40> + 6820: b410 push {r4} + 6822: 780b ldrb r3, [r1, #0] + 6824: 7804 ldrb r4, [r0, #0] + 6826: 1ae3 subs r3, r4, r3 + 6828: f013 03ff ands.w r3, r3, #255 ; 0xff + 682c: bf04 itt eq + 682e: f102 34ff addeq.w r4, r2, #4294967295 + 6832: 1824 addeq r4, r4, r0 + 6834: d008 beq.n 6848 <__rtl_memcmpb_v1_00+0x2c> + 6836: e00d b.n 6854 <__rtl_memcmpb_v1_00+0x38> + 6838: f810 2f01 ldrb.w r2, [r0, #1]! + 683c: f811 3f01 ldrb.w r3, [r1, #1]! + 6840: 1ad3 subs r3, r2, r3 + 6842: f013 03ff ands.w r3, r3, #255 ; 0xff + 6846: d105 bne.n 6854 <__rtl_memcmpb_v1_00+0x38> + 6848: 42a0 cmp r0, r4 + 684a: d1f5 bne.n 6838 <__rtl_memcmpb_v1_00+0x1c> + 684c: 2000 movs r0, #0 + 684e: f85d 4b04 ldr.w r4, [sp], #4 + 6852: 4770 bx lr + 6854: 4618 mov r0, r3 + 6856: f85d 4b04 ldr.w r4, [sp], #4 + 685a: 4770 bx lr + 685c: 2000 movs r0, #0 + 685e: 4770 bx lr + +00006860 <__rtl_random_v1_00>: + 6860: b283 uxth r3, r0 + 6862: eb03 02c3 add.w r2, r3, r3, lsl #3 + 6866: 0c00 lsrs r0, r0, #16 + 6868: eb03 0342 add.w r3, r3, r2, lsl #1 + 686c: eb00 02c0 add.w r2, r0, r0, lsl #3 + 6870: eb00 0042 add.w r0, r0, r2, lsl #1 + 6874: 3325 adds r3, #37 ; 0x25 + 6876: ea83 4300 eor.w r3, r3, r0, lsl #16 + 687a: 4058 eors r0, r3 + 687c: 4770 bx lr + 687e: bf00 nop + +00006880 <__rtl_align_to_be32_v1_00>: + 6880: 2900 cmp r1, #0 + 6882: dd07 ble.n 6894 <__rtl_align_to_be32_v1_00+0x14> + 6884: 2200 movs r2, #0 + 6886: 6803 ldr r3, [r0, #0] + 6888: ba1b rev r3, r3 + 688a: 3201 adds r2, #1 + 688c: 428a cmp r2, r1 + 688e: f840 3b04 str.w r3, [r0], #4 + 6892: d1f8 bne.n 6886 <__rtl_align_to_be32_v1_00+0x6> + 6894: 4770 bx lr + 6896: bf00 nop + +00006898 <__rtl_memsetw_v1_00>: + 6898: 2a00 cmp r2, #0 + 689a: dd05 ble.n 68a8 <__rtl_memsetw_v1_00+0x10> + 689c: 2300 movs r3, #0 + 689e: 3301 adds r3, #1 + 68a0: 4293 cmp r3, r2 + 68a2: f840 1b04 str.w r1, [r0], #4 + 68a6: d1fa bne.n 689e <__rtl_memsetw_v1_00+0x6> + 68a8: 4770 bx lr + 68aa: bf00 nop + +000068ac <__rtl_memsetb_v1_00>: + 68ac: 2a00 cmp r2, #0 + 68ae: dd04 ble.n 68ba <__rtl_memsetb_v1_00+0xe> + 68b0: 1883 adds r3, r0, r2 + 68b2: f800 1b01 strb.w r1, [r0], #1 + 68b6: 4298 cmp r0, r3 + 68b8: d1fb bne.n 68b2 <__rtl_memsetb_v1_00+0x6> + 68ba: 4770 bx lr + +000068bc <__rtl_memcpyw_v1_00>: + 68bc: 2a00 cmp r2, #0 + 68be: dd0b ble.n 68d8 <__rtl_memcpyw_v1_00+0x1c> + 68c0: b410 push {r4} + 68c2: 3904 subs r1, #4 + 68c4: 2300 movs r3, #0 + 68c6: f851 4f04 ldr.w r4, [r1, #4]! + 68ca: 3301 adds r3, #1 + 68cc: 4293 cmp r3, r2 + 68ce: f840 4b04 str.w r4, [r0], #4 + 68d2: d1f8 bne.n 68c6 <__rtl_memcpyw_v1_00+0xa> + 68d4: f85d 4b04 ldr.w r4, [sp], #4 + 68d8: 4770 bx lr + 68da: bf00 nop + +000068dc <__rtl_memcpyb_v1_00>: + 68dc: 2a00 cmp r2, #0 + 68de: dd07 ble.n 68f0 <__rtl_memcpyb_v1_00+0x14> + 68e0: 3901 subs r1, #1 + 68e2: 4402 add r2, r0 + 68e4: f811 3f01 ldrb.w r3, [r1, #1]! + 68e8: f800 3b01 strb.w r3, [r0], #1 + 68ec: 4290 cmp r0, r2 + 68ee: d1f9 bne.n 68e4 <__rtl_memcpyb_v1_00+0x8> + 68f0: 4770 bx lr + 68f2: bf00 nop + +000068f4 <__rtl_memDump_v1_00>: + 68f4: 2900 cmp r1, #0 + 68f6: bf18 it ne + 68f8: 2800 cmpne r0, #0 + 68fa: d000 beq.n 68fe <__rtl_memDump_v1_00+0xa> + 68fc: e722 b.n 6744 <__rtl_memDump_v1_00.part.7> + 68fe: 4770 bx lr + +00006900 <__rtl_AES_set_encrypt_key>: + 6900: 2a00 cmp r2, #0 + 6902: bf18 it ne + 6904: 2800 cmpne r0, #0 + 6906: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 690a: b083 sub sp, #12 + 690c: f000 817b beq.w 6c06 <__rtl_AES_set_encrypt_key+0x306> + 6910: f021 0340 bic.w r3, r1, #64 ; 0x40 + 6914: 2b80 cmp r3, #128 ; 0x80 + 6916: d07c beq.n 6a12 <__rtl_AES_set_encrypt_key+0x112> + 6918: f5b1 7f80 cmp.w r1, #256 ; 0x100 + 691c: f040 8170 bne.w 6c00 <__rtl_AES_set_encrypt_key+0x300> + 6920: 230e movs r3, #14 + 6922: f8c2 30f0 str.w r3, [r2, #240] ; 0xf0 + 6926: 7844 ldrb r4, [r0, #1] + 6928: 7803 ldrb r3, [r0, #0] + 692a: 78c5 ldrb r5, [r0, #3] + 692c: 0424 lsls r4, r4, #16 + 692e: ea44 6403 orr.w r4, r4, r3, lsl #24 + 6932: 7883 ldrb r3, [r0, #2] + 6934: 406c eors r4, r5 + 6936: ea44 2403 orr.w r4, r4, r3, lsl #8 + 693a: 6014 str r4, [r2, #0] + 693c: 7945 ldrb r5, [r0, #5] + 693e: 7903 ldrb r3, [r0, #4] + 6940: 79c6 ldrb r6, [r0, #7] + 6942: 042d lsls r5, r5, #16 + 6944: ea45 6503 orr.w r5, r5, r3, lsl #24 + 6948: 7983 ldrb r3, [r0, #6] + 694a: 4075 eors r5, r6 + 694c: ea45 2503 orr.w r5, r5, r3, lsl #8 + 6950: 6055 str r5, [r2, #4] + 6952: 7a47 ldrb r7, [r0, #9] + 6954: 7a03 ldrb r3, [r0, #8] + 6956: 7ac6 ldrb r6, [r0, #11] + 6958: 043f lsls r7, r7, #16 + 695a: ea47 6703 orr.w r7, r7, r3, lsl #24 + 695e: 7a83 ldrb r3, [r0, #10] + 6960: 4077 eors r7, r6 + 6962: ea47 2703 orr.w r7, r7, r3, lsl #8 + 6966: 6097 str r7, [r2, #8] + 6968: 7b43 ldrb r3, [r0, #13] + 696a: 7b06 ldrb r6, [r0, #12] + 696c: f890 e00f ldrb.w lr, [r0, #15] + 6970: 041b lsls r3, r3, #16 + 6972: ea43 6306 orr.w r3, r3, r6, lsl #24 + 6976: 7b86 ldrb r6, [r0, #14] + 6978: ea83 030e eor.w r3, r3, lr + 697c: ea43 2306 orr.w r3, r3, r6, lsl #8 + 6980: 2980 cmp r1, #128 ; 0x80 + 6982: 60d3 str r3, [r2, #12] + 6984: d052 beq.n 6a2c <__rtl_AES_set_encrypt_key+0x12c> + 6986: 7c46 ldrb r6, [r0, #17] + 6988: f890 e010 ldrb.w lr, [r0, #16] + 698c: f890 c013 ldrb.w ip, [r0, #19] + 6990: 0436 lsls r6, r6, #16 + 6992: ea46 660e orr.w r6, r6, lr, lsl #24 + 6996: f890 e012 ldrb.w lr, [r0, #18] + 699a: ea86 060c eor.w r6, r6, ip + 699e: ea46 260e orr.w r6, r6, lr, lsl #8 + 69a2: 6116 str r6, [r2, #16] + 69a4: 7d46 ldrb r6, [r0, #21] + 69a6: f890 e014 ldrb.w lr, [r0, #20] + 69aa: f890 c017 ldrb.w ip, [r0, #23] + 69ae: 0436 lsls r6, r6, #16 + 69b0: ea46 660e orr.w r6, r6, lr, lsl #24 + 69b4: f890 e016 ldrb.w lr, [r0, #22] + 69b8: ea86 060c eor.w r6, r6, ip + 69bc: ea46 260e orr.w r6, r6, lr, lsl #8 + 69c0: 29c0 cmp r1, #192 ; 0xc0 + 69c2: 6156 str r6, [r2, #20] + 69c4: d069 beq.n 6a9a <__rtl_AES_set_encrypt_key+0x19a> + 69c6: 7e46 ldrb r6, [r0, #25] + 69c8: f890 e018 ldrb.w lr, [r0, #24] + 69cc: f890 c01b ldrb.w ip, [r0, #27] + 69d0: 0436 lsls r6, r6, #16 + 69d2: ea46 660e orr.w r6, r6, lr, lsl #24 + 69d6: f890 e01a ldrb.w lr, [r0, #26] + 69da: ea86 060c eor.w r6, r6, ip + 69de: ea46 260e orr.w r6, r6, lr, lsl #8 + 69e2: 6196 str r6, [r2, #24] + 69e4: f890 c01d ldrb.w ip, [r0, #29] + 69e8: 7f06 ldrb r6, [r0, #28] + 69ea: f890 e01f ldrb.w lr, [r0, #31] + 69ee: ea4f 4c0c mov.w ip, ip, lsl #16 + 69f2: ea4c 6c06 orr.w ip, ip, r6, lsl #24 + 69f6: 7f86 ldrb r6, [r0, #30] + 69f8: ea8c 000e eor.w r0, ip, lr + 69fc: ea40 2006 orr.w r0, r0, r6, lsl #8 + 6a00: f5b1 7f80 cmp.w r1, #256 ; 0x100 + 6a04: 61d0 str r0, [r2, #28] + 6a06: f000 8086 beq.w 6b16 <__rtl_AES_set_encrypt_key+0x216> + 6a0a: 2000 movs r0, #0 + 6a0c: b003 add sp, #12 + 6a0e: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 6a12: 2980 cmp r1, #128 ; 0x80 + 6a14: bf04 itt eq + 6a16: 230a moveq r3, #10 + 6a18: f8c2 30f0 streq.w r3, [r2, #240] ; 0xf0 + 6a1c: d083 beq.n 6926 <__rtl_AES_set_encrypt_key+0x26> + 6a1e: 29c0 cmp r1, #192 ; 0xc0 + 6a20: f47f af7e bne.w 6920 <__rtl_AES_set_encrypt_key+0x20> + 6a24: 230c movs r3, #12 + 6a26: f8c2 30f0 str.w r3, [r2, #240] ; 0xf0 + 6a2a: e77c b.n 6926 <__rtl_AES_set_encrypt_key+0x26> + 6a2c: 4877 ldr r0, [pc, #476] ; (6c0c <__rtl_AES_set_encrypt_key+0x30c>) + 6a2e: f102 0c90 add.w ip, r2, #144 ; 0x90 + 6a32: 1d01 adds r1, r0, #4 + 6a34: e000 b.n 6a38 <__rtl_AES_set_encrypt_key+0x138> + 6a36: 3210 adds r2, #16 + 6a38: b2de uxtb r6, r3 + 6a3a: ea4f 6e13 mov.w lr, r3, lsr #24 + 6a3e: eb01 0686 add.w r6, r1, r6, lsl #2 + 6a42: 6ab6 ldr r6, [r6, #40] ; 0x28 + 6a44: eb01 0e8e add.w lr, r1, lr, lsl #2 + 6a48: f3c3 4807 ubfx r8, r3, #16, #8 + 6a4c: f89e a028 ldrb.w sl, [lr, #40] ; 0x28 + 6a50: eb01 0888 add.w r8, r1, r8, lsl #2 + 6a54: f3c3 2e07 ubfx lr, r3, #8, #8 + 6a58: f406 497f and.w r9, r6, #65280 ; 0xff00 + 6a5c: f8d8 8028 ldr.w r8, [r8, #40] ; 0x28 + 6a60: f850 6f04 ldr.w r6, [r0, #4]! + 6a64: eb01 0e8e add.w lr, r1, lr, lsl #2 + 6a68: ea89 090a eor.w r9, r9, sl + 6a6c: f8de e028 ldr.w lr, [lr, #40] ; 0x28 + 6a70: ea89 0606 eor.w r6, r9, r6 + 6a74: f008 487f and.w r8, r8, #4278190080 ; 0xff000000 + 6a78: ea86 0608 eor.w r6, r6, r8 + 6a7c: f40e 0e7f and.w lr, lr, #16711680 ; 0xff0000 + 6a80: ea86 060e eor.w r6, r6, lr + 6a84: 4074 eors r4, r6 + 6a86: 4065 eors r5, r4 + 6a88: 406f eors r7, r5 + 6a8a: 407b eors r3, r7 + 6a8c: 4562 cmp r2, ip + 6a8e: 61d3 str r3, [r2, #28] + 6a90: 6197 str r7, [r2, #24] + 6a92: 6155 str r5, [r2, #20] + 6a94: 6114 str r4, [r2, #16] + 6a96: d1ce bne.n 6a36 <__rtl_AES_set_encrypt_key+0x136> + 6a98: e7b7 b.n 6a0a <__rtl_AES_set_encrypt_key+0x10a> + 6a9a: f8df e170 ldr.w lr, [pc, #368] ; 6c0c <__rtl_AES_set_encrypt_key+0x30c> + 6a9e: f102 0ca8 add.w ip, r2, #168 ; 0xa8 + 6aa2: f10e 0104 add.w r1, lr, #4 + 6aa6: e005 b.n 6ab4 <__rtl_AES_set_encrypt_key+0x1b4> + 6aa8: 6910 ldr r0, [r2, #16] + 6aaa: 3218 adds r2, #24 + 6aac: 4058 eors r0, r3 + 6aae: 4046 eors r6, r0 + 6ab0: 6156 str r6, [r2, #20] + 6ab2: 6110 str r0, [r2, #16] + 6ab4: b2f0 uxtb r0, r6 + 6ab6: eb01 0080 add.w r0, r1, r0, lsl #2 + 6aba: ea4f 6816 mov.w r8, r6, lsr #24 + 6abe: 6a80 ldr r0, [r0, #40] ; 0x28 + 6ac0: eb01 0888 add.w r8, r1, r8, lsl #2 + 6ac4: f3c6 4907 ubfx r9, r6, #16, #8 + 6ac8: f898 b028 ldrb.w fp, [r8, #40] ; 0x28 + 6acc: eb01 0989 add.w r9, r1, r9, lsl #2 + 6ad0: f3c6 2807 ubfx r8, r6, #8, #8 + 6ad4: f400 4a7f and.w sl, r0, #65280 ; 0xff00 + 6ad8: f8d9 9028 ldr.w r9, [r9, #40] ; 0x28 + 6adc: f85e 0f04 ldr.w r0, [lr, #4]! + 6ae0: eb01 0888 add.w r8, r1, r8, lsl #2 + 6ae4: ea8a 0a0b eor.w sl, sl, fp + 6ae8: f8d8 8028 ldr.w r8, [r8, #40] ; 0x28 + 6aec: ea8a 0000 eor.w r0, sl, r0 + 6af0: f009 497f and.w r9, r9, #4278190080 ; 0xff000000 + 6af4: ea80 0009 eor.w r0, r0, r9 + 6af8: f408 087f and.w r8, r8, #16711680 ; 0xff0000 + 6afc: ea80 0008 eor.w r0, r0, r8 + 6b00: 4044 eors r4, r0 + 6b02: 4065 eors r5, r4 + 6b04: 406f eors r7, r5 + 6b06: 407b eors r3, r7 + 6b08: 4562 cmp r2, ip + 6b0a: 6253 str r3, [r2, #36] ; 0x24 + 6b0c: 6217 str r7, [r2, #32] + 6b0e: 61d5 str r5, [r2, #28] + 6b10: 6194 str r4, [r2, #24] + 6b12: d1c9 bne.n 6aa8 <__rtl_AES_set_encrypt_key+0x1a8> + 6b14: e779 b.n 6a0a <__rtl_AES_set_encrypt_key+0x10a> + 6b16: f8df 90f4 ldr.w r9, [pc, #244] ; 6c0c <__rtl_AES_set_encrypt_key+0x30c> + 6b1a: f102 0bc0 add.w fp, r2, #192 ; 0xc0 + 6b1e: f109 0104 add.w r1, r9, #4 + 6b22: 460e mov r6, r1 + 6b24: e027 b.n 6b76 <__rtl_AES_set_encrypt_key+0x276> + 6b26: f8da a028 ldr.w sl, [sl, #40] ; 0x28 + 6b2a: f898 8028 ldrb.w r8, [r8, #40] ; 0x28 + 6b2e: 6914 ldr r4, [r2, #16] + 6b30: f00a 4a7f and.w sl, sl, #4278190080 ; 0xff000000 + 6b34: f8dc c028 ldr.w ip, [ip, #40] ; 0x28 + 6b38: ea8a 0a08 eor.w sl, sl, r8 + 6b3c: f8de e028 ldr.w lr, [lr, #40] ; 0x28 + 6b40: ea8a 0a04 eor.w sl, sl, r4 + 6b44: f40c 0c7f and.w ip, ip, #16711680 ; 0xff0000 + 6b48: 6954 ldr r4, [r2, #20] + 6b4a: f40e 4e7f and.w lr, lr, #65280 ; 0xff00 + 6b4e: ea8a 0c0c eor.w ip, sl, ip + 6b52: ea8c 080e eor.w r8, ip, lr + 6b56: ea88 0c04 eor.w ip, r8, r4 + 6b5a: 6994 ldr r4, [r2, #24] + 6b5c: f8c2 8030 str.w r8, [r2, #48] ; 0x30 + 6b60: ea8c 0e04 eor.w lr, ip, r4 + 6b64: ea80 000e eor.w r0, r0, lr + 6b68: 9c01 ldr r4, [sp, #4] + 6b6a: f8c2 c034 str.w ip, [r2, #52] ; 0x34 + 6b6e: 63d0 str r0, [r2, #60] ; 0x3c + 6b70: f8c2 e038 str.w lr, [r2, #56] ; 0x38 + 6b74: 3220 adds r2, #32 + 6b76: fa5f fe80 uxtb.w lr, r0 + 6b7a: eb01 0e8e add.w lr, r1, lr, lsl #2 + 6b7e: ea4f 6c10 mov.w ip, r0, lsr #24 + 6b82: eb01 0c8c add.w ip, r1, ip, lsl #2 + 6b86: f8de e028 ldr.w lr, [lr, #40] ; 0x28 + 6b8a: f89c a028 ldrb.w sl, [ip, #40] ; 0x28 + 6b8e: f3c0 4807 ubfx r8, r0, #16, #8 + 6b92: eb01 0888 add.w r8, r1, r8, lsl #2 + 6b96: f3c0 2c07 ubfx ip, r0, #8, #8 + 6b9a: f40e 4e7f and.w lr, lr, #65280 ; 0xff00 + 6b9e: ea8e 0e0a eor.w lr, lr, sl + 6ba2: f8d8 8028 ldr.w r8, [r8, #40] ; 0x28 + 6ba6: f859 af04 ldr.w sl, [r9, #4]! + 6baa: eb01 0c8c add.w ip, r1, ip, lsl #2 + 6bae: f8dc c028 ldr.w ip, [ip, #40] ; 0x28 + 6bb2: ea8e 0e0a eor.w lr, lr, sl + 6bb6: f008 487f and.w r8, r8, #4278190080 ; 0xff000000 + 6bba: ea8e 0e08 eor.w lr, lr, r8 + 6bbe: f40c 0c7f and.w ip, ip, #16711680 ; 0xff0000 + 6bc2: ea8e 0e0c eor.w lr, lr, ip + 6bc6: ea8e 0404 eor.w r4, lr, r4 + 6bca: 4065 eors r5, r4 + 6bcc: 406f eors r7, r5 + 6bce: 407b eors r3, r7 + 6bd0: ea4f 6a13 mov.w sl, r3, lsr #24 + 6bd4: fa5f f883 uxtb.w r8, r3 + 6bd8: f3c3 4c07 ubfx ip, r3, #16, #8 + 6bdc: f3c3 2e07 ubfx lr, r3, #8, #8 + 6be0: 455a cmp r2, fp + 6be2: 9401 str r4, [sp, #4] + 6be4: eb06 0a8a add.w sl, r6, sl, lsl #2 + 6be8: eb06 0888 add.w r8, r6, r8, lsl #2 + 6bec: eb06 0c8c add.w ip, r6, ip, lsl #2 + 6bf0: eb06 0e8e add.w lr, r6, lr, lsl #2 + 6bf4: 62d3 str r3, [r2, #44] ; 0x2c + 6bf6: 6297 str r7, [r2, #40] ; 0x28 + 6bf8: 6255 str r5, [r2, #36] ; 0x24 + 6bfa: 6214 str r4, [r2, #32] + 6bfc: d193 bne.n 6b26 <__rtl_AES_set_encrypt_key+0x226> + 6bfe: e704 b.n 6a0a <__rtl_AES_set_encrypt_key+0x10a> + 6c00: f06f 0001 mvn.w r0, #1 + 6c04: e702 b.n 6a0c <__rtl_AES_set_encrypt_key+0x10c> + 6c06: f04f 30ff mov.w r0, #4294967295 + 6c0a: e6ff b.n 6a0c <__rtl_AES_set_encrypt_key+0x10c> + 6c0c: 00030e74 .word 0x00030e74 + +00006c10 <__rtl_cryptoEngine_AES_set_decrypt_key>: + 6c10: b570 push {r4, r5, r6, lr} + 6c12: 4615 mov r5, r2 + 6c14: 4606 mov r6, r0 + 6c16: 4608 mov r0, r1 + 6c18: f106 0248 add.w r2, r6, #72 ; 0x48 + 6c1c: 4629 mov r1, r5 + 6c1e: 461c mov r4, r3 + 6c20: f7ff fe6e bl 6900 <__rtl_AES_set_encrypt_key> + 6c24: 2dc0 cmp r5, #192 ; 0xc0 + 6c26: d025 beq.n 6c74 <__rtl_cryptoEngine_AES_set_decrypt_key+0x64> + 6c28: f5b5 7f80 cmp.w r5, #256 ; 0x100 + 6c2c: d00d beq.n 6c4a <__rtl_cryptoEngine_AES_set_decrypt_key+0x3a> + 6c2e: 2d80 cmp r5, #128 ; 0x80 + 6c30: d002 beq.n 6c38 <__rtl_cryptoEngine_AES_set_decrypt_key+0x28> + 6c32: f04f 30ff mov.w r0, #4294967295 + 6c36: bd70 pop {r4, r5, r6, pc} + 6c38: 36e8 adds r6, #232 ; 0xe8 + 6c3a: 2200 movs r2, #0 + 6c3c: 58b3 ldr r3, [r6, r2] + 6c3e: 50a3 str r3, [r4, r2] + 6c40: 3204 adds r2, #4 + 6c42: 2a10 cmp r2, #16 + 6c44: d1fa bne.n 6c3c <__rtl_cryptoEngine_AES_set_decrypt_key+0x2c> + 6c46: 2000 movs r0, #0 + 6c48: bd70 pop {r4, r5, r6, pc} + 6c4a: f506 7194 add.w r1, r6, #296 ; 0x128 + 6c4e: 2200 movs r2, #0 + 6c50: 588b ldr r3, [r1, r2] + 6c52: 50a3 str r3, [r4, r2] + 6c54: 3204 adds r2, #4 + 6c56: 2a10 cmp r2, #16 + 6c58: d1fa bne.n 6c50 <__rtl_cryptoEngine_AES_set_decrypt_key+0x40> + 6c5a: f104 0310 add.w r3, r4, #16 + 6c5e: f506 768a add.w r6, r6, #276 ; 0x114 + 6c62: 3420 adds r4, #32 + 6c64: f856 2f04 ldr.w r2, [r6, #4]! + 6c68: f843 2b04 str.w r2, [r3], #4 + 6c6c: 42a3 cmp r3, r4 + 6c6e: d1f9 bne.n 6c64 <__rtl_cryptoEngine_AES_set_decrypt_key+0x54> + 6c70: 2000 movs r0, #0 + 6c72: bd70 pop {r4, r5, r6, pc} + 6c74: f506 7184 add.w r1, r6, #264 ; 0x108 + 6c78: 2200 movs r2, #0 + 6c7a: 588b ldr r3, [r1, r2] + 6c7c: 50a3 str r3, [r4, r2] + 6c7e: 3204 adds r2, #4 + 6c80: 2a10 cmp r2, #16 + 6c82: d1fa bne.n 6c7a <__rtl_cryptoEngine_AES_set_decrypt_key+0x6a> + 6c84: f8d6 3100 ldr.w r3, [r6, #256] ; 0x100 + 6c88: 2000 movs r0, #0 + 6c8a: 6123 str r3, [r4, #16] + 6c8c: f8d6 3104 ldr.w r3, [r6, #260] ; 0x104 + 6c90: 6163 str r3, [r4, #20] + 6c92: bd70 pop {r4, r5, r6, pc} + +00006c94 <__rtl_cryptoEngine_set_security_mode_v1_00>: + 6c94: b5f8 push {r3, r4, r5, r6, r7, lr} + 6c96: 9f08 ldr r7, [sp, #32] + 6c98: 4604 mov r4, r0 + 6c9a: 9d09 ldr r5, [sp, #36] ; 0x24 + 6c9c: 2800 cmp r0, #0 + 6c9e: f000 80ff beq.w 6ea0 <__rtl_cryptoEngine_set_security_mode_v1_00+0x20c> + 6ca2: 7800 ldrb r0, [r0, #0] + 6ca4: 2801 cmp r0, #1 + 6ca6: f040 80f5 bne.w 6e94 <__rtl_cryptoEngine_set_security_mode_v1_00+0x200> + 6caa: b12d cbz r5, 6cb8 <__rtl_cryptoEngine_set_security_mode_v1_00+0x24> + 6cac: 2f00 cmp r7, #0 + 6cae: f000 80f7 beq.w 6ea0 <__rtl_cryptoEngine_set_security_mode_v1_00+0x20c> + 6cb2: 2d40 cmp r5, #64 ; 0x40 + 6cb4: f200 80f1 bhi.w 6e9a <__rtl_cryptoEngine_set_security_mode_v1_00+0x206> + 6cb8: 2000 movs r0, #0 + 6cba: 7360 strb r0, [r4, #13] + 6cbc: 73a0 strb r0, [r4, #14] + 6cbe: 7320 strb r0, [r4, #12] + 6cc0: 73e0 strb r0, [r4, #15] + 6cc2: 1c50 adds r0, r2, #1 + 6cc4: 7121 strb r1, [r4, #4] + 6cc6: 60a2 str r2, [r4, #8] + 6cc8: d00f beq.n 6cea <__rtl_cryptoEngine_set_security_mode_v1_00+0x56> + 6cca: f002 0130 and.w r1, r2, #48 ; 0x30 + 6cce: 2910 cmp r1, #16 + 6cd0: f000 80cd beq.w 6e6e <__rtl_cryptoEngine_set_security_mode_v1_00+0x1da> + 6cd4: 2920 cmp r1, #32 + 6cd6: f000 80d2 beq.w 6e7e <__rtl_cryptoEngine_set_security_mode_v1_00+0x1ea> + 6cda: b909 cbnz r1, 6ce0 <__rtl_cryptoEngine_set_security_mode_v1_00+0x4c> + 6cdc: 2101 movs r1, #1 + 6cde: 7321 strb r1, [r4, #12] + 6ce0: f082 0280 eor.w r2, r2, #128 ; 0x80 + 6ce4: f3c2 12c0 ubfx r2, r2, #7, #1 + 6ce8: 73e2 strb r2, [r4, #15] + 6cea: 1c59 adds r1, r3, #1 + 6cec: 6123 str r3, [r4, #16] + 6cee: f000 80b0 beq.w 6e52 <__rtl_cryptoEngine_set_security_mode_v1_00+0x1be> + 6cf2: f003 0603 and.w r6, r3, #3 + 6cf6: f1a6 0e02 sub.w lr, r6, #2 + 6cfa: f1a6 0201 sub.w r2, r6, #1 + 6cfe: fab6 f186 clz r1, r6 + 6d02: fabe fe8e clz lr, lr + 6d06: fab2 f282 clz r2, r2 + 6d0a: ea4f 1e5e mov.w lr, lr, lsr #5 + 6d0e: 0952 lsrs r2, r2, #5 + 6d10: 0949 lsrs r1, r1, #5 + 6d12: f3c3 0080 ubfx r0, r3, #2, #1 + 6d16: 75a1 strb r1, [r4, #22] + 6d18: f884 e015 strb.w lr, [r4, #21] + 6d1c: 75e2 strb r2, [r4, #23] + 6d1e: 7520 strb r0, [r4, #20] + 6d20: b1e2 cbz r2, 6d5c <__rtl_cryptoEngine_set_security_mode_v1_00+0xc8> + 6d22: f003 0230 and.w r2, r3, #48 ; 0x30 + 6d26: 2a10 cmp r2, #16 + 6d28: f000 80b1 beq.w 6e8e <__rtl_cryptoEngine_set_security_mode_v1_00+0x1fa> + 6d2c: 2a20 cmp r2, #32 + 6d2e: d015 beq.n 6d5c <__rtl_cryptoEngine_set_security_mode_v1_00+0xc8> + 6d30: f240 3214 movw r2, #788 ; 0x314 + 6d34: f2c1 0200 movt r2, #4096 ; 0x1000 + 6d38: 6812 ldr r2, [r2, #0] + 6d3a: 0392 lsls r2, r2, #14 + 6d3c: d50d bpl.n 6d5a <__rtl_cryptoEngine_set_security_mode_v1_00+0xc6> + 6d3e: f240 007c movw r0, #124 ; 0x7c + 6d42: f240 01b0 movw r1, #176 ; 0xb0 + 6d46: f24f 3c9d movw ip, #62365 ; 0xf39d + 6d4a: 461a mov r2, r3 + 6d4c: f2c0 0004 movt r0, #4 + 6d50: f2c0 0104 movt r1, #4 + 6d54: f2c0 0c00 movt ip, #0 + 6d58: 47e0 blx ip + 6d5a: 2200 movs r2, #0 + 6d5c: 61a2 str r2, [r4, #24] + 6d5e: 2e01 cmp r6, #1 + 6d60: d005 beq.n 6d6e <__rtl_cryptoEngine_set_security_mode_v1_00+0xda> + 6d62: bf38 it cc + 6d64: 2214 movcc r2, #20 + 6d66: d302 bcc.n 6d6e <__rtl_cryptoEngine_set_security_mode_v1_00+0xda> + 6d68: 2e02 cmp r6, #2 + 6d6a: d178 bne.n 6e5e <__rtl_cryptoEngine_set_security_mode_v1_00+0x1ca> + 6d6c: 2210 movs r2, #16 + 6d6e: 9807 ldr r0, [sp, #28] + 6d70: 9b06 ldr r3, [sp, #24] + 6d72: 2d00 cmp r5, #0 + 6d74: 6462 str r2, [r4, #68] ; 0x44 + 6d76: f8c4 013c str.w r0, [r4, #316] ; 0x13c + 6d7a: f8c4 3140 str.w r3, [r4, #320] ; 0x140 + 6d7e: 6227 str r7, [r4, #32] + 6d80: 61e5 str r5, [r4, #28] + 6d82: dd6e ble.n 6e62 <__rtl_cryptoEngine_set_security_mode_v1_00+0x1ce> + 6d84: f504 7ec0 add.w lr, r4, #384 ; 0x180 + 6d88: 4672 mov r2, lr + 6d8a: f504 73e0 add.w r3, r4, #448 ; 0x1c0 + 6d8e: f8c4 e220 str.w lr, [r4, #544] ; 0x220 + 6d92: f8c4 3224 str.w r3, [r4, #548] ; 0x224 + 6d96: f04f 3036 mov.w r0, #909522486 ; 0x36363636 + 6d9a: f842 0b04 str.w r0, [r2], #4 + 6d9e: 429a cmp r2, r3 + 6da0: d1fb bne.n 6d9a <__rtl_cryptoEngine_set_security_mode_v1_00+0x106> + 6da2: f504 7600 add.w r6, r4, #512 ; 0x200 + 6da6: f04f 305c mov.w r0, #1549556828 ; 0x5c5c5c5c + 6daa: f843 0b04 str.w r0, [r3], #4 + 6dae: 42b3 cmp r3, r6 + 6db0: d1fb bne.n 6daa <__rtl_cryptoEngine_set_security_mode_v1_00+0x116> + 6db2: 4639 mov r1, r7 + 6db4: 4672 mov r2, lr + 6db6: 2300 movs r3, #0 + 6db8: e002 b.n 6dc0 <__rtl_cryptoEngine_set_security_mode_v1_00+0x12c> + 6dba: f8d4 2220 ldr.w r2, [r4, #544] ; 0x220 + 6dbe: 6a21 ldr r1, [r4, #32] + 6dc0: 5cc8 ldrb r0, [r1, r3] + 6dc2: 5cd1 ldrb r1, [r2, r3] + 6dc4: 4041 eors r1, r0 + 6dc6: 54d1 strb r1, [r2, r3] + 6dc8: f8d4 2224 ldr.w r2, [r4, #548] ; 0x224 + 6dcc: 6a21 ldr r1, [r4, #32] + 6dce: 5cd0 ldrb r0, [r2, r3] + 6dd0: 5cc9 ldrb r1, [r1, r3] + 6dd2: 4041 eors r1, r0 + 6dd4: 54d1 strb r1, [r2, r3] + 6dd6: 3301 adds r3, #1 + 6dd8: 429d cmp r5, r3 + 6dda: d1ee bne.n 6dba <__rtl_cryptoEngine_set_security_mode_v1_00+0x126> + 6ddc: 68a3 ldr r3, [r4, #8] + 6dde: f003 0330 and.w r3, r3, #48 ; 0x30 + 6de2: 2b10 cmp r3, #16 + 6de4: d01f beq.n 6e26 <__rtl_cryptoEngine_set_security_mode_v1_00+0x192> + 6de6: 2b20 cmp r3, #32 + 6de8: d11b bne.n 6e22 <__rtl_cryptoEngine_set_security_mode_v1_00+0x18e> + 6dea: 4620 mov r0, r4 + 6dec: f8d4 513c ldr.w r5, [r4, #316] ; 0x13c + 6df0: f504 74a8 add.w r4, r4, #336 ; 0x150 + 6df4: f8d0 1140 ldr.w r1, [r0, #320] ; 0x140 + 6df8: 00ea lsls r2, r5, #3 + 6dfa: 4623 mov r3, r4 + 6dfc: f7ff ff08 bl 6c10 <__rtl_cryptoEngine_AES_set_decrypt_key> + 6e00: 1ce8 adds r0, r5, #3 + 6e02: ea35 0525 bics.w r5, r5, r5, asr #32 + 6e06: bf28 it cs + 6e08: 4605 movcs r5, r0 + 6e0a: 10a8 asrs r0, r5, #2 + 6e0c: 2800 cmp r0, #0 + 6e0e: bfc8 it gt + 6e10: 2100 movgt r1, #0 + 6e12: dd06 ble.n 6e22 <__rtl_cryptoEngine_set_security_mode_v1_00+0x18e> + 6e14: 6822 ldr r2, [r4, #0] + 6e16: ba12 rev r2, r2 + 6e18: 3101 adds r1, #1 + 6e1a: 4281 cmp r1, r0 + 6e1c: f844 2b04 str.w r2, [r4], #4 + 6e20: d1f8 bne.n 6e14 <__rtl_cryptoEngine_set_security_mode_v1_00+0x180> + 6e22: 2000 movs r0, #0 + 6e24: bdf8 pop {r3, r4, r5, r6, r7, pc} + 6e26: f8d4 3140 ldr.w r3, [r4, #320] ; 0x140 + 6e2a: 2000 movs r0, #0 + 6e2c: 681a ldr r2, [r3, #0] + 6e2e: f8c4 2160 str.w r2, [r4, #352] ; 0x160 + 6e32: 685a ldr r2, [r3, #4] + 6e34: f8c4 2164 str.w r2, [r4, #356] ; 0x164 + 6e38: 689a ldr r2, [r3, #8] + 6e3a: f8c4 2158 str.w r2, [r4, #344] ; 0x158 + 6e3e: 68da ldr r2, [r3, #12] + 6e40: f8c4 215c str.w r2, [r4, #348] ; 0x15c + 6e44: 691a ldr r2, [r3, #16] + 6e46: f8c4 2150 str.w r2, [r4, #336] ; 0x150 + 6e4a: 695b ldr r3, [r3, #20] + 6e4c: f8c4 3154 str.w r3, [r4, #340] ; 0x154 + 6e50: bdf8 pop {r3, r4, r5, r6, r7, pc} + 6e52: 2300 movs r3, #0 + 6e54: 7563 strb r3, [r4, #21] + 6e56: 7523 strb r3, [r4, #20] + 6e58: 75a3 strb r3, [r4, #22] + 6e5a: 75e3 strb r3, [r4, #23] + 6e5c: 61a3 str r3, [r4, #24] + 6e5e: 2200 movs r2, #0 + 6e60: e785 b.n 6d6e <__rtl_cryptoEngine_set_security_mode_v1_00+0xda> + 6e62: 2300 movs r3, #0 + 6e64: f8c4 3220 str.w r3, [r4, #544] ; 0x220 + 6e68: f8c4 3224 str.w r3, [r4, #548] ; 0x224 + 6e6c: e7b6 b.n 6ddc <__rtl_cryptoEngine_set_security_mode_v1_00+0x148> + 6e6e: f082 0280 eor.w r2, r2, #128 ; 0x80 + 6e72: 2101 movs r1, #1 + 6e74: f3c2 12c0 ubfx r2, r2, #7, #1 + 6e78: 7361 strb r1, [r4, #13] + 6e7a: 73e2 strb r2, [r4, #15] + 6e7c: e735 b.n 6cea <__rtl_cryptoEngine_set_security_mode_v1_00+0x56> + 6e7e: f082 0280 eor.w r2, r2, #128 ; 0x80 + 6e82: 2101 movs r1, #1 + 6e84: f3c2 12c0 ubfx r2, r2, #7, #1 + 6e88: 73a1 strb r1, [r4, #14] + 6e8a: 73e2 strb r2, [r4, #15] + 6e8c: e72d b.n 6cea <__rtl_cryptoEngine_set_security_mode_v1_00+0x56> + 6e8e: 221c movs r2, #28 + 6e90: 61a2 str r2, [r4, #24] + 6e92: e764 b.n 6d5e <__rtl_cryptoEngine_set_security_mode_v1_00+0xca> + 6e94: f06f 0004 mvn.w r0, #4 + 6e98: bdf8 pop {r3, r4, r5, r6, r7, pc} + 6e9a: f06f 0006 mvn.w r0, #6 + 6e9e: bdf8 pop {r3, r4, r5, r6, r7, pc} + 6ea0: f06f 0003 mvn.w r0, #3 + 6ea4: bdf8 pop {r3, r4, r5, r6, r7, pc} + 6ea6: bf00 nop + +00006ea8 <__rtl_cryptoEngine_init_v1_00>: + 6ea8: 4603 mov r3, r0 + 6eaa: 78c0 ldrb r0, [r0, #3] + 6eac: 1e42 subs r2, r0, #1 + 6eae: 2a07 cmp r2, #7 + 6eb0: f200 80ca bhi.w 7048 <__rtl_cryptoEngine_init_v1_00+0x1a0> + 6eb4: f44f 7104 mov.w r1, #528 ; 0x210 + 6eb8: f2c4 0100 movt r1, #16384 ; 0x4000 + 6ebc: f44f 7211 mov.w r2, #580 ; 0x244 + 6ec0: f2c4 0200 movt r2, #16384 ; 0x4000 + 6ec4: b430 push {r4, r5} + 6ec6: 680d ldr r5, [r1, #0] + 6ec8: 785c ldrb r4, [r3, #1] + 6eca: f045 0504 orr.w r5, r5, #4 + 6ece: 600d str r5, [r1, #0] + 6ed0: 680d ldr r5, [r1, #0] + 6ed2: f445 1580 orr.w r5, r5, #1048576 ; 0x100000 + 6ed6: 600d str r5, [r1, #0] + 6ed8: 6811 ldr r1, [r2, #0] + 6eda: f041 0110 orr.w r1, r1, #16 + 6ede: 6011 str r1, [r2, #0] + 6ee0: 6811 ldr r1, [r2, #0] + 6ee2: f041 0120 orr.w r1, r1, #32 + 6ee6: 6011 str r1, [r2, #0] + 6ee8: 2c03 cmp r4, #3 + 6eea: f200 80b0 bhi.w 704e <__rtl_cryptoEngine_init_v1_00+0x1a6> + 6eee: e8df f004 tbb [pc, r4] + 6ef2: 029a .short 0x029a + 6ef4: 9e9c .short 0x9e9c + 6ef6: 2409 movs r4, #9 + 6ef8: 2208 movs r2, #8 + 6efa: f2c4 0207 movt r2, #16391 ; 0x4007 + 6efe: 6815 ldr r5, [r2, #0] + 6f00: f8d3 12e4 ldr.w r1, [r3, #740] ; 0x2e4 + 6f04: f045 0501 orr.w r5, r5, #1 + 6f08: 6015 str r5, [r2, #0] + 6f0a: b131 cbz r1, 6f1a <__rtl_cryptoEngine_init_v1_00+0x72> + 6f0c: 2100 movs r1, #0 + 6f0e: f2c4 0107 movt r1, #16391 ; 0x4007 + 6f12: 2200 movs r2, #0 + 6f14: 600a str r2, [r1, #0] + 6f16: f8c3 22e4 str.w r2, [r3, #740] ; 0x2e4 + 6f1a: f8d3 236c ldr.w r2, [r3, #876] ; 0x36c + 6f1e: b132 cbz r2, 6f2e <__rtl_cryptoEngine_init_v1_00+0x86> + 6f20: 2104 movs r1, #4 + 6f22: f2c4 0107 movt r1, #16391 ; 0x4007 + 6f26: 2200 movs r2, #0 + 6f28: 600a str r2, [r1, #0] + 6f2a: f8c3 236c str.w r2, [r3, #876] ; 0x36c + 6f2e: f503 723a add.w r2, r3, #744 ; 0x2e8 + 6f32: 70d8 strb r0, [r3, #3] + 6f34: f8c3 22e4 str.w r2, [r3, #740] ; 0x2e4 + 6f38: 0101 lsls r1, r0, #4 + 6f3a: b140 cbz r0, 6f4e <__rtl_cryptoEngine_init_v1_00+0xa6> + 6f3c: 1850 adds r0, r2, r1 + 6f3e: 2100 movs r1, #0 + 6f40: f802 1b01 strb.w r1, [r2], #1 + 6f44: 4282 cmp r2, r0 + 6f46: d1fb bne.n 6f40 <__rtl_cryptoEngine_init_v1_00+0x98> + 6f48: f8d3 22e4 ldr.w r2, [r3, #740] ; 0x2e4 + 6f4c: 78d8 ldrb r0, [r3, #3] + 6f4e: f100 5080 add.w r0, r0, #268435456 ; 0x10000000 + 6f52: 2100 movs r1, #0 + 6f54: 3801 subs r0, #1 + 6f56: eb02 1000 add.w r0, r2, r0, lsl #4 + 6f5a: f883 12e0 strb.w r1, [r3, #736] ; 0x2e0 + 6f5e: 78c1 ldrb r1, [r0, #3] + 6f60: f041 0140 orr.w r1, r1, #64 ; 0x40 + 6f64: 70c1 strb r1, [r0, #3] + 6f66: 78d9 ldrb r1, [r3, #3] + 6f68: f101 5180 add.w r1, r1, #268435456 ; 0x10000000 + 6f6c: 3901 subs r1, #1 + 6f6e: eb02 1101 add.w r1, r2, r1, lsl #4 + 6f72: f101 0510 add.w r5, r1, #16 + 6f76: 6808 ldr r0, [r1, #0] + 6f78: ba00 rev r0, r0 + 6f7a: f841 0b04 str.w r0, [r1], #4 + 6f7e: 42a9 cmp r1, r5 + 6f80: d1f9 bne.n 6f76 <__rtl_cryptoEngine_init_v1_00+0xce> + 6f82: 2100 movs r1, #0 + 6f84: f2c4 0107 movt r1, #16391 ; 0x4007 + 6f88: 600a str r2, [r1, #0] + 6f8a: 78d9 ldrb r1, [r3, #3] + 6f8c: 1e4a subs r2, r1, #1 + 6f8e: 2a07 cmp r2, #7 + 6f90: bf88 it hi + 6f92: f06f 0001 mvnhi.w r0, #1 + 6f96: d844 bhi.n 7022 <__rtl_cryptoEngine_init_v1_00+0x17a> + 6f98: f503 725c add.w r2, r3, #880 ; 0x370 + 6f9c: eb01 0541 add.w r5, r1, r1, lsl #1 + 6fa0: f8c3 236c str.w r2, [r3, #876] ; 0x36c + 6fa4: 0128 lsls r0, r5, #4 + 6fa6: 2d00 cmp r5, #0 + 6fa8: d043 beq.n 7032 <__rtl_cryptoEngine_init_v1_00+0x18a> + 6faa: 4410 add r0, r2 + 6fac: 2100 movs r1, #0 + 6fae: f802 1b01 strb.w r1, [r2], #1 + 6fb2: 4282 cmp r2, r0 + 6fb4: d1fb bne.n 6fae <__rtl_cryptoEngine_init_v1_00+0x106> + 6fb6: f8d3 536c ldr.w r5, [r3, #876] ; 0x36c + 6fba: 78d9 ldrb r1, [r3, #3] + 6fbc: eb01 0141 add.w r1, r1, r1, lsl #1 + 6fc0: 2000 movs r0, #0 + 6fc2: eb05 1201 add.w r2, r5, r1, lsl #4 + 6fc6: f883 0368 strb.w r0, [r3, #872] ; 0x368 + 6fca: f812 1c2d ldrb.w r1, [r2, #-45] + 6fce: f041 0140 orr.w r1, r1, #64 ; 0x40 + 6fd2: f802 1c2d strb.w r1, [r2, #-45] + 6fd6: 78da ldrb r2, [r3, #3] + 6fd8: eb02 0242 add.w r2, r2, r2, lsl #1 + 6fdc: eb05 1202 add.w r2, r5, r2, lsl #4 + 6fe0: 3a30 subs r2, #48 ; 0x30 + 6fe2: f102 0030 add.w r0, r2, #48 ; 0x30 + 6fe6: 6811 ldr r1, [r2, #0] + 6fe8: ba09 rev r1, r1 + 6fea: f842 1b04 str.w r1, [r2], #4 + 6fee: 4282 cmp r2, r0 + 6ff0: d1f9 bne.n 6fe6 <__rtl_cryptoEngine_init_v1_00+0x13e> + 6ff2: 2104 movs r1, #4 + 6ff4: f2c4 0107 movt r1, #16391 ; 0x4007 + 6ff8: 600d str r5, [r1, #0] + 6ffa: 789a ldrb r2, [r3, #2] + 6ffc: b1da cbz r2, 7036 <__rtl_cryptoEngine_init_v1_00+0x18e> + 6ffe: 220c movs r2, #12 + 7000: f2c4 0207 movt r2, #16391 ; 0x4007 + 7004: f044 7480 orr.w r4, r4, #16777216 ; 0x1000000 + 7008: f044 04c0 orr.w r4, r4, #192 ; 0xc0 + 700c: 6014 str r4, [r2, #0] + 700e: 2208 movs r2, #8 + 7010: f2c4 0207 movt r2, #16391 ; 0x4007 + 7014: 6810 ldr r0, [r2, #0] + 7016: 2101 movs r1, #1 + 7018: f440 4070 orr.w r0, r0, #61440 ; 0xf000 + 701c: 6010 str r0, [r2, #0] + 701e: 2000 movs r0, #0 + 7020: 7019 strb r1, [r3, #0] + 7022: bc30 pop {r4, r5} + 7024: 4770 bx lr + 7026: 2400 movs r4, #0 + 7028: e766 b.n 6ef8 <__rtl_cryptoEngine_init_v1_00+0x50> + 702a: 2412 movs r4, #18 + 702c: e764 b.n 6ef8 <__rtl_cryptoEngine_init_v1_00+0x50> + 702e: 241b movs r4, #27 + 7030: e762 b.n 6ef8 <__rtl_cryptoEngine_init_v1_00+0x50> + 7032: 4615 mov r5, r2 + 7034: e7c2 b.n 6fbc <__rtl_cryptoEngine_init_v1_00+0x114> + 7036: 220c movs r2, #12 + 7038: f2c4 0207 movt r2, #16391 ; 0x4007 + 703c: f044 7480 orr.w r4, r4, #16777216 ; 0x1000000 + 7040: f044 0440 orr.w r4, r4, #64 ; 0x40 + 7044: 6014 str r4, [r2, #0] + 7046: e7e2 b.n 700e <__rtl_cryptoEngine_init_v1_00+0x166> + 7048: f06f 0001 mvn.w r0, #1 + 704c: 4770 bx lr + 704e: f06f 0002 mvn.w r0, #2 + 7052: e7e6 b.n 7022 <__rtl_cryptoEngine_init_v1_00+0x17a> + +00007054 <__rtl_cryptoEngine_exit_v1_00>: + 7054: f44f 7311 mov.w r3, #580 ; 0x244 + 7058: f2c4 0300 movt r3, #16384 ; 0x4000 + 705c: 2100 movs r1, #0 + 705e: f44f 7204 mov.w r2, #528 ; 0x210 + 7062: f2c4 0200 movt r2, #16384 ; 0x4000 + 7066: f2c4 0107 movt r1, #16391 ; 0x4007 + 706a: b470 push {r4, r5, r6} + 706c: 2400 movs r4, #0 + 706e: 7004 strb r4, [r0, #0] + 7070: 681e ldr r6, [r3, #0] + 7072: f8d0 52e4 ldr.w r5, [r0, #740] ; 0x2e4 + 7076: f026 0610 bic.w r6, r6, #16 + 707a: 601e str r6, [r3, #0] + 707c: 681e ldr r6, [r3, #0] + 707e: f026 0620 bic.w r6, r6, #32 + 7082: 601e str r6, [r3, #0] + 7084: 680b ldr r3, [r1, #0] + 7086: 6813 ldr r3, [r2, #0] + 7088: f423 1380 bic.w r3, r3, #1048576 ; 0x100000 + 708c: 6013 str r3, [r2, #0] + 708e: b115 cbz r5, 7096 <__rtl_cryptoEngine_exit_v1_00+0x42> + 7090: 600c str r4, [r1, #0] + 7092: f8c0 42e4 str.w r4, [r0, #740] ; 0x2e4 + 7096: f8d0 336c ldr.w r3, [r0, #876] ; 0x36c + 709a: b133 cbz r3, 70aa <__rtl_cryptoEngine_exit_v1_00+0x56> + 709c: 2204 movs r2, #4 + 709e: f2c4 0207 movt r2, #16391 ; 0x4007 + 70a2: 2300 movs r3, #0 + 70a4: 6013 str r3, [r2, #0] + 70a6: f8c0 336c str.w r3, [r0, #876] ; 0x36c + 70aa: 2000 movs r0, #0 + 70ac: bc70 pop {r4, r5, r6} + 70ae: 4770 bx lr + +000070b0 <__rtl_cryptoEngine_reset_v1_00>: + 70b0: f44f 7311 mov.w r3, #580 ; 0x244 + 70b4: f2c4 0300 movt r3, #16384 ; 0x4000 + 70b8: 2100 movs r1, #0 + 70ba: f44f 7204 mov.w r2, #528 ; 0x210 + 70be: f2c4 0200 movt r2, #16384 ; 0x4000 + 70c2: f2c4 0107 movt r1, #16391 ; 0x4007 + 70c6: b430 push {r4, r5} + 70c8: 2500 movs r5, #0 + 70ca: 7005 strb r5, [r0, #0] + 70cc: 681c ldr r4, [r3, #0] + 70ce: f024 0410 bic.w r4, r4, #16 + 70d2: 601c str r4, [r3, #0] + 70d4: 681c ldr r4, [r3, #0] + 70d6: f024 0420 bic.w r4, r4, #32 + 70da: 601c str r4, [r3, #0] + 70dc: 680b ldr r3, [r1, #0] + 70de: 6813 ldr r3, [r2, #0] + 70e0: bc30 pop {r4, r5} + 70e2: f423 1380 bic.w r3, r3, #1048576 ; 0x100000 + 70e6: 6013 str r3, [r2, #0] + 70e8: f7ff bede b.w 6ea8 <__rtl_cryptoEngine_init_v1_00> + +000070ec <__rtl_cryptoEngine_v1_00>: + 70ec: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 70f0: 4691 mov r9, r2 + 70f2: b089 sub sp, #36 ; 0x24 + 70f4: 4604 mov r4, r0 + 70f6: 9a13 ldr r2, [sp, #76] ; 0x4c + 70f8: 6900 ldr r0, [r0, #16] + 70fa: 9103 str r1, [sp, #12] + 70fc: eb09 0702 add.w r7, r9, r2 + 7100: 1c41 adds r1, r0, #1 + 7102: 469b mov fp, r3 + 7104: 9702 str r7, [sp, #8] + 7106: 9e14 ldr r6, [sp, #80] ; 0x50 + 7108: bf08 it eq + 710a: 2300 moveq r3, #0 + 710c: d007 beq.n 711e <__rtl_cryptoEngine_v1_00+0x32> + 710e: 463b mov r3, r7 + 7110: 333f adds r3, #63 ; 0x3f + 7112: f023 033f bic.w r3, r3, #63 ; 0x3f + 7116: 1bdb subs r3, r3, r7 + 7118: 2b08 cmp r3, #8 + 711a: bf98 it ls + 711c: 3340 addls r3, #64 ; 0x40 + 711e: 68a5 ldr r5, [r4, #8] + 7120: 6c67 ldr r7, [r4, #68] ; 0x44 + 7122: f8c4 314c str.w r3, [r4, #332] ; 0x14c + 7126: 1c6b adds r3, r5, #1 + 7128: f8c4 2144 str.w r2, [r4, #324] ; 0x144 + 712c: f8c4 9148 str.w r9, [r4, #328] ; 0x148 + 7130: 9704 str r7, [sp, #16] + 7132: f000 84e6 beq.w 7b02 <__rtl_cryptoEngine_v1_00+0xa16> + 7136: 7be2 ldrb r2, [r4, #15] + 7138: f8d4 313c ldr.w r3, [r4, #316] ; 0x13c + 713c: 2a00 cmp r2, #0 + 713e: f040 80a8 bne.w 7292 <__rtl_cryptoEngine_v1_00+0x1a6> + 7142: f8d4 c140 ldr.w ip, [r4, #320] ; 0x140 + 7146: f894 e2e0 ldrb.w lr, [r4, #736] ; 0x2e0 + 714a: f8d4 a2e4 ldr.w sl, [r4, #740] ; 0x2e4 + 714e: ea4f 180e mov.w r8, lr, lsl #4 + 7152: eb0a 0008 add.w r0, sl, r8 + 7156: 4602 mov r2, r0 + 7158: 4617 mov r7, r2 + 715a: 9001 str r0, [sp, #4] + 715c: 2100 movs r1, #0 + 715e: 3010 adds r0, #16 + 7160: f802 1b01 strb.w r1, [r2], #1 + 7164: 4282 cmp r2, r0 + 7166: d1fb bne.n 7160 <__rtl_cryptoEngine_v1_00+0x74> + 7168: 78e2 ldrb r2, [r4, #3] + 716a: 9701 str r7, [sp, #4] + 716c: 3a01 subs r2, #1 + 716e: 4596 cmp lr, r2 + 7170: bf08 it eq + 7172: 78fa ldrbeq r2, [r7, #3] + 7174: f005 0507 and.w r5, r5, #7 + 7178: bf04 itt eq + 717a: f042 0240 orreq.w r2, r2, #64 ; 0x40 + 717e: 70fa strbeq r2, [r7, #3] + 7180: 9a01 ldr r2, [sp, #4] + 7182: 9f01 ldr r7, [sp, #4] + 7184: 78d1 ldrb r1, [r2, #3] + 7186: 2d02 cmp r5, #2 + 7188: f041 0120 orr.w r1, r1, #32 + 718c: 460a mov r2, r1 + 718e: 70f9 strb r1, [r7, #3] + 7190: 7921 ldrb r1, [r4, #4] + 7192: f361 0283 bfi r2, r1, #2, #2 + 7196: 70fa strb r2, [r7, #3] + 7198: f000 84a5 beq.w 7ae6 <__rtl_cryptoEngine_v1_00+0x9fa> + 719c: 2d03 cmp r5, #3 + 719e: f000 8083 beq.w 72a8 <__rtl_cryptoEngine_v1_00+0x1bc> + 71a2: 2d00 cmp r5, #0 + 71a4: f000 84a6 beq.w 7af4 <__rtl_cryptoEngine_v1_00+0xa08> + 71a8: f240 3510 movw r5, #784 ; 0x310 + 71ac: f2c1 0500 movt r5, #4096 ; 0x1000 + 71b0: 6920 ldr r0, [r4, #16] + 71b2: 3001 adds r0, #1 + 71b4: f000 810a beq.w 73cc <__rtl_cryptoEngine_v1_00+0x2e0> + 71b8: f8d4 32e4 ldr.w r3, [r4, #740] ; 0x2e4 + 71bc: f894 02e0 ldrb.w r0, [r4, #736] ; 0x2e0 + 71c0: 2100 movs r1, #0 + 71c2: eb03 1800 add.w r8, r3, r0, lsl #4 + 71c6: 4643 mov r3, r8 + 71c8: f108 0210 add.w r2, r8, #16 + 71cc: f803 1b01 strb.w r1, [r3], #1 + 71d0: 4293 cmp r3, r2 + 71d2: d1fb bne.n 71cc <__rtl_cryptoEngine_v1_00+0xe0> + 71d4: 78e3 ldrb r3, [r4, #3] + 71d6: f8d4 b2e4 ldr.w fp, [r4, #740] ; 0x2e4 + 71da: 3b01 subs r3, #1 + 71dc: 4298 cmp r0, r3 + 71de: bf02 ittt eq + 71e0: f898 3003 ldrbeq.w r3, [r8, #3] + 71e4: f043 0340 orreq.w r3, r3, #64 ; 0x40 + 71e8: f888 3003 strbeq.w r3, [r8, #3] + 71ec: 68a3 ldr r3, [r4, #8] + 71ee: 3301 adds r3, #1 + 71f0: bf02 ittt eq + 71f2: f898 3003 ldrbeq.w r3, [r8, #3] + 71f6: f043 0320 orreq.w r3, r3, #32 + 71fa: f888 3003 strbeq.w r3, [r8, #3] + 71fe: f894 a2e0 ldrb.w sl, [r4, #736] ; 0x2e0 + 7202: 7922 ldrb r2, [r4, #4] + 7204: ea4f 1a0a mov.w sl, sl, lsl #4 + 7208: eb0b 070a add.w r7, fp, sl + 720c: 78fb ldrb r3, [r7, #3] + 720e: 7879 ldrb r1, [r7, #1] + 7210: f362 0383 bfi r3, r2, #2, #2 + 7214: 70fb strb r3, [r7, #3] + 7216: 7de2 ldrb r2, [r4, #23] + 7218: 78bb ldrb r3, [r7, #2] + 721a: f002 0201 and.w r2, r2, #1 + 721e: f362 11c7 bfi r1, r2, #7, #1 + 7222: 7079 strb r1, [r7, #1] + 7224: 7d61 ldrb r1, [r4, #21] + 7226: f361 0300 bfi r3, r1, #0, #1 + 722a: 4619 mov r1, r3 + 722c: 70bb strb r3, [r7, #2] + 722e: 7d23 ldrb r3, [r4, #20] + 7230: f363 0141 bfi r1, r3, #1, #1 + 7234: 70b9 strb r1, [r7, #2] + 7236: 2a00 cmp r2, #0 + 7238: d072 beq.n 7320 <__rtl_cryptoEngine_v1_00+0x234> + 723a: 6c62 ldr r2, [r4, #68] ; 0x44 + 723c: f1a2 031c sub.w r3, r2, #28 + 7240: 2b24 cmp r3, #36 ; 0x24 + 7242: d859 bhi.n 72f8 <__rtl_cryptoEngine_v1_00+0x20c> + 7244: e8df f013 tbh [pc, r3, lsl #1] + 7248: 00580469 .word 0x00580469 + 724c: 00580058 .word 0x00580058 + 7250: 00580463 .word 0x00580463 + 7254: 00580058 .word 0x00580058 + 7258: 00580058 .word 0x00580058 + 725c: 00580058 .word 0x00580058 + 7260: 00580058 .word 0x00580058 + 7264: 00580058 .word 0x00580058 + 7268: 00580058 .word 0x00580058 + 726c: 00580058 .word 0x00580058 + 7270: 00580476 .word 0x00580476 + 7274: 00580058 .word 0x00580058 + 7278: 00580058 .word 0x00580058 + 727c: 00580058 .word 0x00580058 + 7280: 00580058 .word 0x00580058 + 7284: 00580058 .word 0x00580058 + 7288: 00580058 .word 0x00580058 + 728c: 00580058 .word 0x00580058 + 7290: 046f .short 0x046f + 7292: 68e2 ldr r2, [r4, #12] + 7294: f504 7ca8 add.w ip, r4, #336 ; 0x150 + 7298: f022 427f bic.w r2, r2, #4278190080 ; 0xff000000 + 729c: f022 02ff bic.w r2, r2, #255 ; 0xff + 72a0: 2a00 cmp r2, #0 + 72a2: f47f af50 bne.w 7146 <__rtl_cryptoEngine_v1_00+0x5a> + 72a6: e74c b.n 7142 <__rtl_cryptoEngine_v1_00+0x56> + 72a8: 9f01 ldr r7, [sp, #4] + 72aa: 78ba ldrb r2, [r7, #2] + 72ac: f042 0204 orr.w r2, r2, #4 + 72b0: 70ba strb r2, [r7, #2] + 72b2: 7b62 ldrb r2, [r4, #13] + 72b4: 7be1 ldrb r1, [r4, #15] + 72b6: 2a00 cmp r2, #0 + 72b8: f000 8368 beq.w 798c <__rtl_cryptoEngine_v1_00+0x8a0> + 72bc: 2900 cmp r1, #0 + 72be: bf0c ite eq + 72c0: 2105 moveq r1, #5 + 72c2: 2102 movne r1, #2 + 72c4: 9801 ldr r0, [sp, #4] + 72c6: 8842 ldrh r2, [r0, #2] + 72c8: f361 12c9 bfi r2, r1, #7, #3 + 72cc: 8042 strh r2, [r0, #2] + 72ce: 7ba2 ldrb r2, [r4, #14] + 72d0: 2a00 cmp r2, #0 + 72d2: f000 82a1 beq.w 7818 <__rtl_cryptoEngine_v1_00+0x72c> + 72d6: 2b18 cmp r3, #24 + 72d8: f000 84c2 beq.w 7c60 <__rtl_cryptoEngine_v1_00+0xb74> + 72dc: 2b20 cmp r3, #32 + 72de: f000 8430 beq.w 7b42 <__rtl_cryptoEngine_v1_00+0xa56> + 72e2: 2b10 cmp r3, #16 + 72e4: bf08 it eq + 72e6: 2101 moveq r1, #1 + 72e8: f47f af5e bne.w 71a8 <__rtl_cryptoEngine_v1_00+0xbc> + 72ec: 9801 ldr r0, [sp, #4] + 72ee: 7882 ldrb r2, [r0, #2] + 72f0: f361 1246 bfi r2, r1, #5, #2 + 72f4: 7082 strb r2, [r0, #2] + 72f6: e294 b.n 7822 <__rtl_cryptoEngine_v1_00+0x736> + 72f8: f240 3314 movw r3, #788 ; 0x314 + 72fc: f2c1 0300 movt r3, #4096 ; 0x1000 + 7300: 681b ldr r3, [r3, #0] + 7302: 039b lsls r3, r3, #14 + 7304: d50c bpl.n 7320 <__rtl_cryptoEngine_v1_00+0x234> + 7306: f240 1028 movw r0, #296 ; 0x128 + 730a: f240 01b0 movw r1, #176 ; 0xb0 + 730e: f24f 339d movw r3, #62365 ; 0xf39d + 7312: f2c0 0004 movt r0, #4 + 7316: f2c0 0104 movt r1, #4 + 731a: f2c0 0300 movt r3, #0 + 731e: 4798 blx r3 + 7320: 7d23 ldrb r3, [r4, #20] + 7322: 2b00 cmp r3, #0 + 7324: f000 81fc beq.w 7720 <__rtl_cryptoEngine_v1_00+0x634> + 7328: f83b 300a ldrh.w r3, [fp, sl] + 732c: 2280 movs r2, #128 ; 0x80 + 732e: f362 030d bfi r3, r2, #0, #14 + 7332: f82b 300a strh.w r3, [fp, sl] + 7336: 682b ldr r3, [r5, #0] + 7338: f8d4 2220 ldr.w r2, [r4, #544] ; 0x220 + 733c: 0398 lsls r0, r3, #14 + 733e: 60fa str r2, [r7, #12] + 7340: f100 8248 bmi.w 77d4 <__rtl_cryptoEngine_v1_00+0x6e8> + 7344: f8d4 2148 ldr.w r2, [r4, #328] ; 0x148 + 7348: f8b8 3004 ldrh.w r3, [r8, #4] + 734c: f8d4 0144 ldr.w r0, [r4, #324] ; 0x144 + 7350: f8d4 114c ldr.w r1, [r4, #332] ; 0x14c + 7354: f362 030d bfi r3, r2, #0, #14 + 7358: f8a8 3004 strh.w r3, [r8, #4] + 735c: f888 0006 strb.w r0, [r8, #6] + 7360: f888 100a strb.w r1, [r8, #10] + 7364: f894 72e0 ldrb.w r7, [r4, #736] ; 0x2e0 + 7368: f8d4 02e4 ldr.w r0, [r4, #740] ; 0x2e4 + 736c: eb00 1707 add.w r7, r0, r7, lsl #4 + 7370: 463b mov r3, r7 + 7372: 78fa ldrb r2, [r7, #3] + 7374: f107 0110 add.w r1, r7, #16 + 7378: f042 0280 orr.w r2, r2, #128 ; 0x80 + 737c: 70fa strb r2, [r7, #3] + 737e: 681a ldr r2, [r3, #0] + 7380: ba12 rev r2, r2 + 7382: f843 2b04 str.w r2, [r3], #4 + 7386: 428b cmp r3, r1 + 7388: d1f9 bne.n 737e <__rtl_cryptoEngine_v1_00+0x292> + 738a: 682b ldr r3, [r5, #0] + 738c: 0399 lsls r1, r3, #14 + 738e: f100 8376 bmi.w 7a7e <__rtl_cryptoEngine_v1_00+0x992> + 7392: f894 22e0 ldrb.w r2, [r4, #736] ; 0x2e0 + 7396: 78e3 ldrb r3, [r4, #3] + 7398: 3201 adds r2, #1 + 739a: fb92 f1f3 sdiv r1, r2, r3 + 739e: fb03 2211 mls r2, r3, r1, r2 + 73a2: b2d7 uxtb r7, r2 + 73a4: eb00 1007 add.w r0, r0, r7, lsl #4 + 73a8: 4603 mov r3, r0 + 73aa: f884 22e0 strb.w r2, [r4, #736] ; 0x2e0 + 73ae: f100 0110 add.w r1, r0, #16 + 73b2: 2200 movs r2, #0 + 73b4: f803 2b01 strb.w r2, [r3], #1 + 73b8: 428b cmp r3, r1 + 73ba: d1fb bne.n 73b4 <__rtl_cryptoEngine_v1_00+0x2c8> + 73bc: 78e3 ldrb r3, [r4, #3] + 73be: 3b01 subs r3, #1 + 73c0: 429f cmp r7, r3 + 73c2: bf02 ittt eq + 73c4: 78c3 ldrbeq r3, [r0, #3] + 73c6: f043 0340 orreq.w r3, r3, #64 ; 0x40 + 73ca: 70c3 strbeq r3, [r0, #3] + 73cc: f894 c2e0 ldrb.w ip, [r4, #736] ; 0x2e0 + 73d0: f8d4 e2e4 ldr.w lr, [r4, #740] ; 0x2e4 + 73d4: ea4f 170c mov.w r7, ip, lsl #4 + 73d8: eb0e 0007 add.w r0, lr, r7 + 73dc: 4603 mov r3, r0 + 73de: f100 0110 add.w r1, r0, #16 + 73e2: 2200 movs r2, #0 + 73e4: f803 2b01 strb.w r2, [r3], #1 + 73e8: 428b cmp r3, r1 + 73ea: d1fb bne.n 73e4 <__rtl_cryptoEngine_v1_00+0x2f8> + 73ec: 78e3 ldrb r3, [r4, #3] + 73ee: 6829 ldr r1, [r5, #0] + 73f0: 3b01 subs r3, #1 + 73f2: 459c cmp ip, r3 + 73f4: bf02 ittt eq + 73f6: 78c3 ldrbeq r3, [r0, #3] + 73f8: f043 0340 orreq.w r3, r3, #64 ; 0x40 + 73fc: 70c3 strbeq r3, [r0, #3] + 73fe: 78c2 ldrb r2, [r0, #3] + 7400: f83e 3007 ldrh.w r3, [lr, r7] + 7404: f36f 1245 bfc r2, #5, #1 + 7408: f369 030d bfi r3, r9, #0, #14 + 740c: 70c2 strb r2, [r0, #3] + 740e: f82e 3007 strh.w r3, [lr, r7] + 7412: 9f03 ldr r7, [sp, #12] + 7414: 038a lsls r2, r1, #14 + 7416: 60c7 str r7, [r0, #12] + 7418: f100 82dc bmi.w 79d4 <__rtl_cryptoEngine_v1_00+0x8e8> + 741c: f8d4 02e4 ldr.w r0, [r4, #740] ; 0x2e4 + 7420: f894 72e0 ldrb.w r7, [r4, #736] ; 0x2e0 + 7424: eb00 1707 add.w r7, r0, r7, lsl #4 + 7428: 463b mov r3, r7 + 742a: 78f9 ldrb r1, [r7, #3] + 742c: f107 0210 add.w r2, r7, #16 + 7430: f041 0180 orr.w r1, r1, #128 ; 0x80 + 7434: 70f9 strb r1, [r7, #3] + 7436: 6819 ldr r1, [r3, #0] + 7438: ba09 rev r1, r1 + 743a: f843 1b04 str.w r1, [r3], #4 + 743e: 4293 cmp r3, r2 + 7440: d1f9 bne.n 7436 <__rtl_cryptoEngine_v1_00+0x34a> + 7442: 682b ldr r3, [r5, #0] + 7444: 039b lsls r3, r3, #14 + 7446: f100 82ab bmi.w 79a0 <__rtl_cryptoEngine_v1_00+0x8b4> + 744a: f894 22e0 ldrb.w r2, [r4, #736] ; 0x2e0 + 744e: 78e3 ldrb r3, [r4, #3] + 7450: 3201 adds r2, #1 + 7452: fb92 f1f3 sdiv r1, r2, r3 + 7456: fb03 2211 mls r2, r3, r1, r2 + 745a: b2d7 uxtb r7, r2 + 745c: eb00 1007 add.w r0, r0, r7, lsl #4 + 7460: 4603 mov r3, r0 + 7462: f884 22e0 strb.w r2, [r4, #736] ; 0x2e0 + 7466: f100 0110 add.w r1, r0, #16 + 746a: 2200 movs r2, #0 + 746c: f803 2b01 strb.w r2, [r3], #1 + 7470: 428b cmp r3, r1 + 7472: d1fb bne.n 746c <__rtl_cryptoEngine_v1_00+0x380> + 7474: 78e3 ldrb r3, [r4, #3] + 7476: 3b01 subs r3, #1 + 7478: 429f cmp r7, r3 + 747a: bf02 ittt eq + 747c: 78c3 ldrbeq r3, [r0, #3] + 747e: f043 0340 orreq.w r3, r3, #64 ; 0x40 + 7482: 70c3 strbeq r3, [r0, #3] + 7484: 6923 ldr r3, [r4, #16] + 7486: 3301 adds r3, #1 + 7488: f000 80b0 beq.w 75ec <__rtl_cryptoEngine_v1_00+0x500> + 748c: f894 02e0 ldrb.w r0, [r4, #736] ; 0x2e0 + 7490: f8d4 92e4 ldr.w r9, [r4, #740] ; 0x2e4 + 7494: ea4f 1800 mov.w r8, r0, lsl #4 + 7498: eb09 0708 add.w r7, r9, r8 + 749c: 463b mov r3, r7 + 749e: f107 0110 add.w r1, r7, #16 + 74a2: 2200 movs r2, #0 + 74a4: f803 2b01 strb.w r2, [r3], #1 + 74a8: 428b cmp r3, r1 + 74aa: d1fb bne.n 74a4 <__rtl_cryptoEngine_v1_00+0x3b8> + 74ac: 78e3 ldrb r3, [r4, #3] + 74ae: f8d4 b14c ldr.w fp, [r4, #332] ; 0x14c + 74b2: 3b01 subs r3, #1 + 74b4: 4298 cmp r0, r3 + 74b6: bf08 it eq + 74b8: 78fb ldrbeq r3, [r7, #3] + 74ba: f1ab 0e08 sub.w lr, fp, #8 + 74be: bf04 itt eq + 74c0: f043 0340 orreq.w r3, r3, #64 ; 0x40 + 74c4: 70fb strbeq r3, [r7, #3] + 74c6: 2380 movs r3, #128 ; 0x80 + 74c8: f1be 0f01 cmp.w lr, #1 + 74cc: f884 3240 strb.w r3, [r4, #576] ; 0x240 + 74d0: bf88 it hi + 74d2: 2301 movhi r3, #1 + 74d4: f8d4 c148 ldr.w ip, [r4, #328] ; 0x148 + 74d8: f504 7210 add.w r2, r4, #576 ; 0x240 + 74dc: bf84 itt hi + 74de: 4619 movhi r1, r3 + 74e0: 2000 movhi r0, #0 + 74e2: d904 bls.n 74ee <__rtl_cryptoEngine_v1_00+0x402> + 74e4: 3301 adds r3, #1 + 74e6: 4573 cmp r3, lr + 74e8: 5450 strb r0, [r2, r1] + 74ea: 4619 mov r1, r3 + 74ec: d1fa bne.n 74e4 <__rtl_cryptoEngine_v1_00+0x3f8> + 74ee: 7d23 ldrb r3, [r4, #20] + 74f0: 2b00 cmp r3, #0 + 74f2: f000 8150 beq.w 7796 <__rtl_cryptoEngine_v1_00+0x6aa> + 74f6: f10c 0140 add.w r1, ip, #64 ; 0x40 + 74fa: 00c9 lsls r1, r1, #3 + 74fc: 2300 movs r3, #0 + 74fe: 9106 str r1, [sp, #24] + 7500: 9307 str r3, [sp, #28] + 7502: eb02 0a0b add.w sl, r2, fp + 7506: 4651 mov r1, sl + 7508: 2300 movs r3, #0 + 750a: 9203 str r2, [sp, #12] + 750c: e00a b.n 7524 <__rtl_cryptoEngine_v1_00+0x438> + 750e: f10d 0c18 add.w ip, sp, #24 + 7512: f81c 0003 ldrb.w r0, [ip, r3] + 7516: 3301 adds r3, #1 + 7518: 2b08 cmp r3, #8 + 751a: f801 0c01 strb.w r0, [r1, #-1] + 751e: f101 31ff add.w r1, r1, #4294967295 + 7522: d00d beq.n 7540 <__rtl_cryptoEngine_v1_00+0x454> + 7524: 7d60 ldrb r0, [r4, #21] + 7526: eb0a 0c03 add.w ip, sl, r3 + 752a: 2800 cmp r0, #0 + 752c: d1ef bne.n 750e <__rtl_cryptoEngine_v1_00+0x422> + 752e: aa06 add r2, sp, #24 + 7530: 5cd0 ldrb r0, [r2, r3] + 7532: 3301 adds r3, #1 + 7534: 2b08 cmp r3, #8 + 7536: f80c 0c08 strb.w r0, [ip, #-8] + 753a: f101 31ff add.w r1, r1, #4294967295 + 753e: d1f1 bne.n 7524 <__rtl_cryptoEngine_v1_00+0x438> + 7540: 9a03 ldr r2, [sp, #12] + 7542: f852 300e ldr.w r3, [r2, lr] + 7546: ba1b rev r3, r3 + 7548: f842 300e str.w r3, [r2, lr] + 754c: f1ab 0004 sub.w r0, fp, #4 + 7550: 5811 ldr r1, [r2, r0] + 7552: ba09 rev r1, r1 + 7554: f842 100e str.w r1, [r2, lr] + 7558: 5013 str r3, [r2, r0] + 755a: 78f8 ldrb r0, [r7, #3] + 755c: f839 1008 ldrh.w r1, [r9, r8] + 7560: f8d5 e000 ldr.w lr, [r5] + 7564: f3cb 030d ubfx r3, fp, #0, #14 + 7568: f060 007f orn r0, r0, #127 ; 0x7f + 756c: f36f 1045 bfc r0, #5, #1 + 7570: f363 010d bfi r1, r3, #0, #14 + 7574: f41e 3f00 tst.w lr, #131072 ; 0x20000 + 7578: 70f8 strb r0, [r7, #3] + 757a: f829 1008 strh.w r1, [r9, r8] + 757e: 60fa str r2, [r7, #12] + 7580: f040 825f bne.w 7a42 <__rtl_cryptoEngine_v1_00+0x956> + 7584: f8d4 02e4 ldr.w r0, [r4, #740] ; 0x2e4 + 7588: f894 72e0 ldrb.w r7, [r4, #736] ; 0x2e0 + 758c: eb00 1707 add.w r7, r0, r7, lsl #4 + 7590: 463b mov r3, r7 + 7592: 78f9 ldrb r1, [r7, #3] + 7594: f107 0210 add.w r2, r7, #16 + 7598: f041 0180 orr.w r1, r1, #128 ; 0x80 + 759c: 70f9 strb r1, [r7, #3] + 759e: 6819 ldr r1, [r3, #0] + 75a0: ba09 rev r1, r1 + 75a2: f843 1b04 str.w r1, [r3], #4 + 75a6: 4293 cmp r3, r2 + 75a8: d1f9 bne.n 759e <__rtl_cryptoEngine_v1_00+0x4b2> + 75aa: 682b ldr r3, [r5, #0] + 75ac: 0399 lsls r1, r3, #14 + 75ae: f100 8280 bmi.w 7ab2 <__rtl_cryptoEngine_v1_00+0x9c6> + 75b2: f894 22e0 ldrb.w r2, [r4, #736] ; 0x2e0 + 75b6: 78e3 ldrb r3, [r4, #3] + 75b8: 3201 adds r2, #1 + 75ba: fb92 f1f3 sdiv r1, r2, r3 + 75be: fb03 2211 mls r2, r3, r1, r2 + 75c2: b2d7 uxtb r7, r2 + 75c4: eb00 1007 add.w r0, r0, r7, lsl #4 + 75c8: 4603 mov r3, r0 + 75ca: f884 22e0 strb.w r2, [r4, #736] ; 0x2e0 + 75ce: f100 0110 add.w r1, r0, #16 + 75d2: 2200 movs r2, #0 + 75d4: f803 2b01 strb.w r2, [r3], #1 + 75d8: 428b cmp r3, r1 + 75da: d1fb bne.n 75d4 <__rtl_cryptoEngine_v1_00+0x4e8> + 75dc: 78e3 ldrb r3, [r4, #3] + 75de: 3b01 subs r3, #1 + 75e0: 429f cmp r7, r3 + 75e2: bf02 ittt eq + 75e4: 78c3 ldrbeq r3, [r0, #3] + 75e6: f043 0340 orreq.w r3, r3, #64 ; 0x40 + 75ea: 70c3 strbeq r3, [r0, #3] + 75ec: f894 7368 ldrb.w r7, [r4, #872] ; 0x368 + 75f0: f8d4 c36c ldr.w ip, [r4, #876] ; 0x36c + 75f4: eb07 0e47 add.w lr, r7, r7, lsl #1 + 75f8: ea4f 1e0e mov.w lr, lr, lsl #4 + 75fc: eb0c 000e add.w r0, ip, lr + 7600: 4603 mov r3, r0 + 7602: f100 0130 add.w r1, r0, #48 ; 0x30 + 7606: 2200 movs r2, #0 + 7608: f803 2b01 strb.w r2, [r3], #1 + 760c: 428b cmp r3, r1 + 760e: d1fb bne.n 7608 <__rtl_cryptoEngine_v1_00+0x51c> + 7610: 78e3 ldrb r3, [r4, #3] + 7612: 3b01 subs r3, #1 + 7614: 429f cmp r7, r3 + 7616: bf02 ittt eq + 7618: 78c3 ldrbeq r3, [r0, #3] + 761a: f043 0340 orreq.w r3, r3, #64 ; 0x40 + 761e: 70c3 strbeq r3, [r0, #3] + 7620: 68a3 ldr r3, [r4, #8] + 7622: 3301 adds r3, #1 + 7624: bf1c itt ne + 7626: 9a02 ldrne r2, [sp, #8] + 7628: 9f04 ldrne r7, [sp, #16] + 762a: f83c 300e ldrh.w r3, [ip, lr] + 762e: bf19 ittee ne + 7630: 19d2 addne r2, r2, r7 + 7632: f362 030d bfine r3, r2, #0, #14 + 7636: 2200 moveq r2, #0 + 7638: f36f 030d bfceq r3, #0, #14 + 763c: bf15 itete ne + 763e: f82c 300e strhne.w r3, [ip, lr] + 7642: f82c 300e strheq.w r3, [ip, lr] + 7646: 6046 strne r6, [r0, #4] + 7648: 6042 streq r2, [r0, #4] + 764a: f894 8368 ldrb.w r8, [r4, #872] ; 0x368 + 764e: f8d4 336c ldr.w r3, [r4, #876] ; 0x36c + 7652: eb08 0848 add.w r8, r8, r8, lsl #1 + 7656: eb03 1808 add.w r8, r3, r8, lsl #4 + 765a: 4643 mov r3, r8 + 765c: f898 1003 ldrb.w r1, [r8, #3] + 7660: f108 0230 add.w r2, r8, #48 ; 0x30 + 7664: f041 0180 orr.w r1, r1, #128 ; 0x80 + 7668: f888 1003 strb.w r1, [r8, #3] + 766c: 6819 ldr r1, [r3, #0] + 766e: ba09 rev r1, r1 + 7670: f843 1b04 str.w r1, [r3], #4 + 7674: 4293 cmp r3, r2 + 7676: d1f9 bne.n 766c <__rtl_cryptoEngine_v1_00+0x580> + 7678: 682b ldr r3, [r5, #0] + 767a: 039a lsls r2, r3, #14 + 767c: f100 81c9 bmi.w 7a12 <__rtl_cryptoEngine_v1_00+0x926> + 7680: 2208 movs r2, #8 + 7682: f2c4 0207 movt r2, #16391 ; 0x4007 + 7686: f244 2340 movw r3, #16960 ; 0x4240 + 768a: f44f 4178 mov.w r1, #63488 ; 0xf800 + 768e: 2002 movs r0, #2 + 7690: 6011 str r1, [r2, #0] + 7692: f2c0 030f movt r3, #15 + 7696: 4611 mov r1, r2 + 7698: 6010 str r0, [r2, #0] + 769a: e002 b.n 76a2 <__rtl_cryptoEngine_v1_00+0x5b6> + 769c: 3b01 subs r3, #1 + 769e: f000 8253 beq.w 7b48 <__rtl_cryptoEngine_v1_00+0xa5c> + 76a2: 680a ldr r2, [r1, #0] + 76a4: 2708 movs r7, #8 + 76a6: f412 4f78 tst.w r2, #63488 ; 0xf800 + 76aa: f2c4 0707 movt r7, #16391 ; 0x4007 + 76ae: d0f5 beq.n 769c <__rtl_cryptoEngine_v1_00+0x5b0> + 76b0: 683b ldr r3, [r7, #0] + 76b2: f413 4f68 tst.w r3, #59392 ; 0xe800 + 76b6: d073 beq.n 77a0 <__rtl_cryptoEngine_v1_00+0x6b4> + 76b8: f240 3814 movw r8, #788 ; 0x314 + 76bc: f2c1 0800 movt r8, #4096 ; 0x1000 + 76c0: f8d8 3000 ldr.w r3, [r8] + 76c4: 0398 lsls r0, r3, #14 + 76c6: d51a bpl.n 76fe <__rtl_cryptoEngine_v1_00+0x612> + 76c8: f240 10c8 movw r0, #456 ; 0x1c8 + 76cc: f240 01b0 movw r1, #176 ; 0xb0 + 76d0: f24f 399d movw r9, #62365 ; 0xf39d + 76d4: 683a ldr r2, [r7, #0] + 76d6: f2c0 0004 movt r0, #4 + 76da: f2c0 0104 movt r1, #4 + 76de: f2c0 0900 movt r9, #0 + 76e2: 47c8 blx r9 + 76e4: f8d8 3000 ldr.w r3, [r8] + 76e8: 039b lsls r3, r3, #14 + 76ea: d508 bpl.n 76fe <__rtl_cryptoEngine_v1_00+0x612> + 76ec: f240 2054 movw r0, #596 ; 0x254 + 76f0: f240 01b0 movw r1, #176 ; 0xb0 + 76f4: f2c0 0004 movt r0, #4 + 76f8: f2c0 0104 movt r1, #4 + 76fc: 47c8 blx r9 + 76fe: 7923 ldrb r3, [r4, #4] + 7700: 2b01 cmp r3, #1 + 7702: d014 beq.n 772e <__rtl_cryptoEngine_v1_00+0x642> + 7704: f894 2368 ldrb.w r2, [r4, #872] ; 0x368 + 7708: 78e3 ldrb r3, [r4, #3] + 770a: 3201 adds r2, #1 + 770c: fb92 f1f3 sdiv r1, r2, r3 + 7710: fb03 2311 mls r3, r3, r1, r2 + 7714: 2000 movs r0, #0 + 7716: f884 3368 strb.w r3, [r4, #872] ; 0x368 + 771a: b009 add sp, #36 ; 0x24 + 771c: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 7720: f83b 200a ldrh.w r2, [fp, sl] + 7724: f363 020d bfi r2, r3, #0, #14 + 7728: f82b 200a strh.w r2, [fp, sl] + 772c: e603 b.n 7336 <__rtl_cryptoEngine_v1_00+0x24a> + 772e: f894 3368 ldrb.w r3, [r4, #872] ; 0x368 + 7732: f8d4 236c ldr.w r2, [r4, #876] ; 0x36c + 7736: 6c61 ldr r1, [r4, #68] ; 0x44 + 7738: eb03 0343 add.w r3, r3, r3, lsl #1 + 773c: eb02 1203 add.w r2, r2, r3, lsl #4 + 7740: 2900 cmp r1, #0 + 7742: f102 000c add.w r0, r2, #12 + 7746: bfc8 it gt + 7748: 2300 movgt r3, #0 + 774a: dd04 ble.n 7756 <__rtl_cryptoEngine_v1_00+0x66a> + 774c: 5cc2 ldrb r2, [r0, r3] + 774e: 54f2 strb r2, [r6, r3] + 7750: 3301 adds r3, #1 + 7752: 4299 cmp r1, r3 + 7754: d1fa bne.n 774c <__rtl_cryptoEngine_v1_00+0x660> + 7756: 682b ldr r3, [r5, #0] + 7758: 039a lsls r2, r3, #14 + 775a: d5d3 bpl.n 7704 <__rtl_cryptoEngine_v1_00+0x618> + 775c: f240 00c8 movw r0, #200 ; 0xc8 + 7760: f240 01f4 movw r1, #244 ; 0xf4 + 7764: f24f 359d movw r5, #62365 ; 0xf39d + 7768: f2c0 0004 movt r0, #4 + 776c: f2c0 0104 movt r1, #4 + 7770: f2c0 0500 movt r5, #0 + 7774: 4632 mov r2, r6 + 7776: 9b04 ldr r3, [sp, #16] + 7778: 47a8 blx r5 + 777a: 9f04 ldr r7, [sp, #16] + 777c: 2f00 cmp r7, #0 + 777e: bf18 it ne + 7780: 2e00 cmpne r6, #0 + 7782: d0bf beq.n 7704 <__rtl_cryptoEngine_v1_00+0x618> + 7784: f240 2284 movw r2, #644 ; 0x284 + 7788: 4630 mov r0, r6 + 778a: 4639 mov r1, r7 + 778c: f2c0 0204 movt r2, #4 + 7790: f7fe ffd8 bl 6744 <__rtl_memDump_v1_00.part.7> + 7794: e7b6 b.n 7704 <__rtl_cryptoEngine_v1_00+0x618> + 7796: ea4f 01cc mov.w r1, ip, lsl #3 + 779a: 9106 str r1, [sp, #24] + 779c: 9307 str r3, [sp, #28] + 779e: e6b0 b.n 7502 <__rtl_cryptoEngine_v1_00+0x416> + 77a0: f898 3003 ldrb.w r3, [r8, #3] + 77a4: 09db lsrs r3, r3, #7 + 77a6: d0aa beq.n 76fe <__rtl_cryptoEngine_v1_00+0x612> + 77a8: f240 3314 movw r3, #788 ; 0x314 + 77ac: f2c1 0300 movt r3, #4096 ; 0x1000 + 77b0: 681b ldr r3, [r3, #0] + 77b2: 0399 lsls r1, r3, #14 + 77b4: d5a3 bpl.n 76fe <__rtl_cryptoEngine_v1_00+0x612> + 77b6: f240 2018 movw r0, #536 ; 0x218 + 77ba: f240 01b0 movw r1, #176 ; 0xb0 + 77be: f24f 339d movw r3, #62365 ; 0xf39d + 77c2: 683a ldr r2, [r7, #0] + 77c4: f2c0 0104 movt r1, #4 + 77c8: f2c0 0300 movt r3, #0 + 77cc: f2c0 0004 movt r0, #4 + 77d0: 4798 blx r3 + 77d2: e794 b.n 76fe <__rtl_cryptoEngine_v1_00+0x612> + 77d4: f240 00c8 movw r0, #200 ; 0xc8 + 77d8: f240 01f4 movw r1, #244 ; 0xf4 + 77dc: f24f 3c9d movw ip, #62365 ; 0xf39d + 77e0: f83b 300a ldrh.w r3, [fp, sl] + 77e4: f2c0 0104 movt r1, #4 + 77e8: f2c0 0004 movt r0, #4 + 77ec: f2c0 0c00 movt ip, #0 + 77f0: f3c3 030d ubfx r3, r3, #0, #14 + 77f4: 47e0 blx ip + 77f6: f83b 100a ldrh.w r1, [fp, sl] + 77fa: 68f8 ldr r0, [r7, #12] + 77fc: f3c1 010d ubfx r1, r1, #0, #14 + 7800: 2800 cmp r0, #0 + 7802: bf18 it ne + 7804: 2900 cmpne r1, #0 + 7806: f43f ad9d beq.w 7344 <__rtl_cryptoEngine_v1_00+0x258> + 780a: f240 1260 movw r2, #352 ; 0x160 + 780e: f2c0 0204 movt r2, #4 + 7812: f7fe ff97 bl 6744 <__rtl_memDump_v1_00.part.7> + 7816: e595 b.n 7344 <__rtl_cryptoEngine_v1_00+0x258> + 7818: 9f01 ldr r7, [sp, #4] + 781a: 78b9 ldrb r1, [r7, #2] + 781c: f362 1146 bfi r1, r2, #5, #2 + 7820: 70b9 strb r1, [r7, #2] + 7822: 9801 ldr r0, [sp, #4] + 7824: 7b62 ldrb r2, [r4, #13] + 7826: 7881 ldrb r1, [r0, #2] + 7828: f240 3510 movw r5, #784 ; 0x310 + 782c: f362 1104 bfi r1, r2, #4, #1 + 7830: 460a mov r2, r1 + 7832: 7081 strb r1, [r0, #2] + 7834: 7d21 ldrb r1, [r4, #20] + 7836: f2c1 0500 movt r5, #4096 ; 0x1000 + 783a: f361 0241 bfi r2, r1, #1, #1 + 783e: 4611 mov r1, r2 + 7840: 7082 strb r2, [r0, #2] + 7842: f894 e015 ldrb.w lr, [r4, #21] + 7846: 9f01 ldr r7, [sp, #4] + 7848: f83a 2008 ldrh.w r2, [sl, r8] + 784c: f8d4 0148 ldr.w r0, [r4, #328] ; 0x148 + 7850: f36e 0100 bfi r1, lr, #0, #1 + 7854: f3c3 030d ubfx r3, r3, #0, #14 + 7858: f8b7 e004 ldrh.w lr, [r7, #4] + 785c: f363 020d bfi r2, r3, #0, #14 + 7860: f360 0e0d bfi lr, r0, #0, #14 + 7864: 6828 ldr r0, [r5, #0] + 7866: 70b9 strb r1, [r7, #2] + 7868: f8d4 1144 ldr.w r1, [r4, #324] ; 0x144 + 786c: f82a 2008 strh.w r2, [sl, r8] + 7870: f8d4 214c ldr.w r2, [r4, #332] ; 0x14c + 7874: f8a7 e004 strh.w lr, [r7, #4] + 7878: 71b9 strb r1, [r7, #6] + 787a: 72ba strb r2, [r7, #10] + 787c: f8c7 c00c str.w ip, [r7, #12] + 7880: 0387 lsls r7, r0, #14 + 7882: f100 8179 bmi.w 7b78 <__rtl_cryptoEngine_v1_00+0xa8c> + 7886: f8d4 72e4 ldr.w r7, [r4, #740] ; 0x2e4 + 788a: f894 82e0 ldrb.w r8, [r4, #736] ; 0x2e0 + 788e: eb07 1808 add.w r8, r7, r8, lsl #4 + 7892: 4643 mov r3, r8 + 7894: f898 2003 ldrb.w r2, [r8, #3] + 7898: f108 0110 add.w r1, r8, #16 + 789c: f042 0280 orr.w r2, r2, #128 ; 0x80 + 78a0: f888 2003 strb.w r2, [r8, #3] + 78a4: 681a ldr r2, [r3, #0] + 78a6: ba12 rev r2, r2 + 78a8: f843 2b04 str.w r2, [r3], #4 + 78ac: 428b cmp r3, r1 + 78ae: d1f9 bne.n 78a4 <__rtl_cryptoEngine_v1_00+0x7b8> + 78b0: 682b ldr r3, [r5, #0] + 78b2: 0398 lsls r0, r3, #14 + 78b4: f100 81ba bmi.w 7c2c <__rtl_cryptoEngine_v1_00+0xb40> + 78b8: f894 22e0 ldrb.w r2, [r4, #736] ; 0x2e0 + 78bc: 78e3 ldrb r3, [r4, #3] + 78be: 3201 adds r2, #1 + 78c0: fb92 f1f3 sdiv r1, r2, r3 + 78c4: fb03 2211 mls r2, r3, r1, r2 + 78c8: b2d0 uxtb r0, r2 + 78ca: eb07 1700 add.w r7, r7, r0, lsl #4 + 78ce: 463b mov r3, r7 + 78d0: f884 22e0 strb.w r2, [r4, #736] ; 0x2e0 + 78d4: f107 0110 add.w r1, r7, #16 + 78d8: 2200 movs r2, #0 + 78da: f803 2b01 strb.w r2, [r3], #1 + 78de: 428b cmp r3, r1 + 78e0: d1fb bne.n 78da <__rtl_cryptoEngine_v1_00+0x7ee> + 78e2: 78e3 ldrb r3, [r4, #3] + 78e4: 883a ldrh r2, [r7, #0] + 78e6: 3b01 subs r3, #1 + 78e8: 4298 cmp r0, r3 + 78ea: bf08 it eq + 78ec: 78fb ldrbeq r3, [r7, #3] + 78ee: 9812 ldr r0, [sp, #72] ; 0x48 + 78f0: bf04 itt eq + 78f2: f043 0340 orreq.w r3, r3, #64 ; 0x40 + 78f6: 70fb strbeq r3, [r7, #3] + 78f8: 78f9 ldrb r1, [r7, #3] + 78fa: f3c0 030d ubfx r3, r0, #0, #14 + 78fe: f061 017f orn r1, r1, #127 ; 0x7f + 7902: 6828 ldr r0, [r5, #0] + 7904: f36f 1145 bfc r1, #5, #1 + 7908: f363 020d bfi r2, r3, #0, #14 + 790c: 70f9 strb r1, [r7, #3] + 790e: 0381 lsls r1, r0, #14 + 7910: f8c7 b00c str.w fp, [r7, #12] + 7914: 803a strh r2, [r7, #0] + 7916: f100 816b bmi.w 7bf0 <__rtl_cryptoEngine_v1_00+0xb04> + 791a: f8d4 02e4 ldr.w r0, [r4, #740] ; 0x2e4 + 791e: f894 72e0 ldrb.w r7, [r4, #736] ; 0x2e0 + 7922: eb00 1707 add.w r7, r0, r7, lsl #4 + 7926: 463b mov r3, r7 + 7928: 78fa ldrb r2, [r7, #3] + 792a: f107 0110 add.w r1, r7, #16 + 792e: f042 0280 orr.w r2, r2, #128 ; 0x80 + 7932: 70fa strb r2, [r7, #3] + 7934: 681a ldr r2, [r3, #0] + 7936: ba12 rev r2, r2 + 7938: f843 2b04 str.w r2, [r3], #4 + 793c: 428b cmp r3, r1 + 793e: d1f9 bne.n 7934 <__rtl_cryptoEngine_v1_00+0x848> + 7940: 682b ldr r3, [r5, #0] + 7942: 039a lsls r2, r3, #14 + 7944: f100 813a bmi.w 7bbc <__rtl_cryptoEngine_v1_00+0xad0> + 7948: f894 22e0 ldrb.w r2, [r4, #736] ; 0x2e0 + 794c: 78e3 ldrb r3, [r4, #3] + 794e: 3201 adds r2, #1 + 7950: fb92 f1f3 sdiv r1, r2, r3 + 7954: fb03 2211 mls r2, r3, r1, r2 + 7958: fa5f fe82 uxtb.w lr, r2 + 795c: eb00 170e add.w r7, r0, lr, lsl #4 + 7960: 463b mov r3, r7 + 7962: f884 22e0 strb.w r2, [r4, #736] ; 0x2e0 + 7966: f107 0110 add.w r1, r7, #16 + 796a: 2200 movs r2, #0 + 796c: f803 2b01 strb.w r2, [r3], #1 + 7970: 428b cmp r3, r1 + 7972: d1fb bne.n 796c <__rtl_cryptoEngine_v1_00+0x880> + 7974: 78e3 ldrb r3, [r4, #3] + 7976: 3b01 subs r3, #1 + 7978: 459e cmp lr, r3 + 797a: bf03 ittte eq + 797c: 78fb ldrbeq r3, [r7, #3] + 797e: 6920 ldreq r0, [r4, #16] + 7980: f043 0340 orreq.w r3, r3, #64 ; 0x40 + 7984: 6920 ldrne r0, [r4, #16] + 7986: bf08 it eq + 7988: 70fb strbeq r3, [r7, #3] + 798a: e412 b.n 71b2 <__rtl_cryptoEngine_v1_00+0xc6> + 798c: 2900 cmp r1, #0 + 798e: bf0c ite eq + 7990: 2107 moveq r1, #7 + 7992: 2100 movne r1, #0 + 7994: 9f01 ldr r7, [sp, #4] + 7996: 887a ldrh r2, [r7, #2] + 7998: f361 12c9 bfi r2, r1, #7, #3 + 799c: 807a strh r2, [r7, #2] + 799e: e496 b.n 72ce <__rtl_cryptoEngine_v1_00+0x1e2> + 79a0: f240 00c8 movw r0, #200 ; 0xc8 + 79a4: f240 01f4 movw r1, #244 ; 0xf4 + 79a8: f24f 3c9d movw ip, #62365 ; 0xf39d + 79ac: f2c0 0104 movt r1, #4 + 79b0: f2c0 0c00 movt ip, #0 + 79b4: 463a mov r2, r7 + 79b6: 2310 movs r3, #16 + 79b8: f2c0 0004 movt r0, #4 + 79bc: 47e0 blx ip + 79be: f240 1214 movw r2, #276 ; 0x114 + 79c2: 4638 mov r0, r7 + 79c4: 2110 movs r1, #16 + 79c6: f2c0 0204 movt r2, #4 + 79ca: f7fe febb bl 6744 <__rtl_memDump_v1_00.part.7> + 79ce: f8d4 02e4 ldr.w r0, [r4, #740] ; 0x2e4 + 79d2: e53a b.n 744a <__rtl_cryptoEngine_v1_00+0x35e> + 79d4: f240 00c8 movw r0, #200 ; 0xc8 + 79d8: f240 01f4 movw r1, #244 ; 0xf4 + 79dc: f24f 379d movw r7, #62365 ; 0xf39d + 79e0: f2c0 0004 movt r0, #4 + 79e4: f2c0 0700 movt r7, #0 + 79e8: f2c0 0104 movt r1, #4 + 79ec: 9a03 ldr r2, [sp, #12] + 79ee: 464b mov r3, r9 + 79f0: 47b8 blx r7 + 79f2: 9f03 ldr r7, [sp, #12] + 79f4: 2f00 cmp r7, #0 + 79f6: bf18 it ne + 79f8: f1b9 0f00 cmpne.w r9, #0 + 79fc: f43f ad0e beq.w 741c <__rtl_cryptoEngine_v1_00+0x330> + 7a00: f240 1268 movw r2, #360 ; 0x168 + 7a04: 4638 mov r0, r7 + 7a06: 4649 mov r1, r9 + 7a08: f2c0 0204 movt r2, #4 + 7a0c: f7fe fe9a bl 6744 <__rtl_memDump_v1_00.part.7> + 7a10: e504 b.n 741c <__rtl_cryptoEngine_v1_00+0x330> + 7a12: f240 00c8 movw r0, #200 ; 0xc8 + 7a16: f240 01f4 movw r1, #244 ; 0xf4 + 7a1a: f24f 379d movw r7, #62365 ; 0xf39d + 7a1e: 4642 mov r2, r8 + 7a20: f2c0 0104 movt r1, #4 + 7a24: f2c0 0700 movt r7, #0 + 7a28: 2330 movs r3, #48 ; 0x30 + 7a2a: f2c0 0004 movt r0, #4 + 7a2e: 47b8 blx r7 + 7a30: f240 127c movw r2, #380 ; 0x17c + 7a34: 4640 mov r0, r8 + 7a36: 2130 movs r1, #48 ; 0x30 + 7a38: f2c0 0204 movt r2, #4 + 7a3c: f7fe fe82 bl 6744 <__rtl_memDump_v1_00.part.7> + 7a40: e61e b.n 7680 <__rtl_cryptoEngine_v1_00+0x594> + 7a42: f240 00c8 movw r0, #200 ; 0xc8 + 7a46: f240 01f4 movw r1, #244 ; 0xf4 + 7a4a: f24f 3c9d movw ip, #62365 ; 0xf39d + 7a4e: f2c0 0104 movt r1, #4 + 7a52: f2c0 0004 movt r0, #4 + 7a56: f2c0 0c00 movt ip, #0 + 7a5a: 47e0 blx ip + 7a5c: f839 1008 ldrh.w r1, [r9, r8] + 7a60: 68f8 ldr r0, [r7, #12] + 7a62: f3c1 010d ubfx r1, r1, #0, #14 + 7a66: 2800 cmp r0, #0 + 7a68: bf18 it ne + 7a6a: 2900 cmpne r1, #0 + 7a6c: f43f ad8a beq.w 7584 <__rtl_cryptoEngine_v1_00+0x498> + 7a70: f240 1270 movw r2, #368 ; 0x170 + 7a74: f2c0 0204 movt r2, #4 + 7a78: f7fe fe64 bl 6744 <__rtl_memDump_v1_00.part.7> + 7a7c: e582 b.n 7584 <__rtl_cryptoEngine_v1_00+0x498> + 7a7e: f240 00c8 movw r0, #200 ; 0xc8 + 7a82: f240 01f4 movw r1, #244 ; 0xf4 + 7a86: f24f 3c9d movw ip, #62365 ; 0xf39d + 7a8a: f2c0 0104 movt r1, #4 + 7a8e: f2c0 0c00 movt ip, #0 + 7a92: 463a mov r2, r7 + 7a94: 2310 movs r3, #16 + 7a96: f2c0 0004 movt r0, #4 + 7a9a: 47e0 blx ip + 7a9c: f240 1214 movw r2, #276 ; 0x114 + 7aa0: 4638 mov r0, r7 + 7aa2: 2110 movs r1, #16 + 7aa4: f2c0 0204 movt r2, #4 + 7aa8: f7fe fe4c bl 6744 <__rtl_memDump_v1_00.part.7> + 7aac: f8d4 02e4 ldr.w r0, [r4, #740] ; 0x2e4 + 7ab0: e46f b.n 7392 <__rtl_cryptoEngine_v1_00+0x2a6> + 7ab2: f240 00c8 movw r0, #200 ; 0xc8 + 7ab6: f240 01f4 movw r1, #244 ; 0xf4 + 7aba: f24f 3c9d movw ip, #62365 ; 0xf39d + 7abe: f2c0 0104 movt r1, #4 + 7ac2: f2c0 0c00 movt ip, #0 + 7ac6: 463a mov r2, r7 + 7ac8: 2310 movs r3, #16 + 7aca: f2c0 0004 movt r0, #4 + 7ace: 47e0 blx ip + 7ad0: f240 1214 movw r2, #276 ; 0x114 + 7ad4: 4638 mov r0, r7 + 7ad6: 2110 movs r1, #16 + 7ad8: f2c0 0204 movt r2, #4 + 7adc: f7fe fe32 bl 6744 <__rtl_memDump_v1_00.part.7> + 7ae0: f8d4 02e4 ldr.w r0, [r4, #740] ; 0x2e4 + 7ae4: e565 b.n 75b2 <__rtl_cryptoEngine_v1_00+0x4c6> + 7ae6: 9901 ldr r1, [sp, #4] + 7ae8: 788a ldrb r2, [r1, #2] + 7aea: f36f 02c3 bfc r2, #3, #1 + 7aee: 708a strb r2, [r1, #2] + 7af0: f7ff bbdf b.w 72b2 <__rtl_cryptoEngine_v1_00+0x1c6> + 7af4: 9801 ldr r0, [sp, #4] + 7af6: 7882 ldrb r2, [r0, #2] + 7af8: f042 0208 orr.w r2, r2, #8 + 7afc: 7082 strb r2, [r0, #2] + 7afe: f7ff bbd8 b.w 72b2 <__rtl_cryptoEngine_v1_00+0x1c6> + 7b02: f240 3510 movw r5, #784 ; 0x310 + 7b06: f2c1 0500 movt r5, #4096 ; 0x1000 + 7b0a: f7ff bb52 b.w 71b2 <__rtl_cryptoEngine_v1_00+0xc6> + 7b0e: 79fb ldrb r3, [r7, #7] + 7b10: 2201 movs r2, #1 + 7b12: f362 1347 bfi r3, r2, #5, #3 + 7b16: 71fb strb r3, [r7, #7] + 7b18: e402 b.n 7320 <__rtl_cryptoEngine_v1_00+0x234> + 7b1a: 79fb ldrb r3, [r7, #7] + 7b1c: f36f 1347 bfc r3, #5, #3 + 7b20: 71fb strb r3, [r7, #7] + 7b22: f7ff bbfd b.w 7320 <__rtl_cryptoEngine_v1_00+0x234> + 7b26: 79fb ldrb r3, [r7, #7] + 7b28: 2203 movs r2, #3 + 7b2a: f362 1347 bfi r3, r2, #5, #3 + 7b2e: 71fb strb r3, [r7, #7] + 7b30: f7ff bbf6 b.w 7320 <__rtl_cryptoEngine_v1_00+0x234> + 7b34: 79fb ldrb r3, [r7, #7] + 7b36: 2202 movs r2, #2 + 7b38: f362 1347 bfi r3, r2, #5, #3 + 7b3c: 71fb strb r3, [r7, #7] + 7b3e: f7ff bbef b.w 7320 <__rtl_cryptoEngine_v1_00+0x234> + 7b42: 2103 movs r1, #3 + 7b44: f7ff bbd2 b.w 72ec <__rtl_cryptoEngine_v1_00+0x200> + 7b48: f240 3814 movw r8, #788 ; 0x314 + 7b4c: f2c1 0800 movt r8, #4096 ; 0x1000 + 7b50: f8d8 3000 ldr.w r3, [r8] + 7b54: 039b lsls r3, r3, #14 + 7b56: f57f add2 bpl.w 76fe <__rtl_cryptoEngine_v1_00+0x612> + 7b5a: f240 108c movw r0, #396 ; 0x18c + 7b5e: f240 01b0 movw r1, #176 ; 0xb0 + 7b62: f24f 399d movw r9, #62365 ; 0xf39d + 7b66: 683a ldr r2, [r7, #0] + 7b68: f2c0 0104 movt r1, #4 + 7b6c: f2c0 0900 movt r9, #0 + 7b70: f2c0 0004 movt r0, #4 + 7b74: 47c8 blx r9 + 7b76: e5b5 b.n 76e4 <__rtl_cryptoEngine_v1_00+0x5f8> + 7b78: f240 00c8 movw r0, #200 ; 0xc8 + 7b7c: f240 01f4 movw r1, #244 ; 0xf4 + 7b80: f24f 379d movw r7, #62365 ; 0xf39d + 7b84: 4662 mov r2, ip + 7b86: f2c0 0104 movt r1, #4 + 7b8a: f2c0 0004 movt r0, #4 + 7b8e: f2c0 0700 movt r7, #0 + 7b92: 47b8 blx r7 + 7b94: f8dd c004 ldr.w ip, [sp, #4] + 7b98: f83a 1008 ldrh.w r1, [sl, r8] + 7b9c: f8dc 000c ldr.w r0, [ip, #12] + 7ba0: f3c1 010d ubfx r1, r1, #0, #14 + 7ba4: 2800 cmp r0, #0 + 7ba6: bf18 it ne + 7ba8: 2900 cmpne r1, #0 + 7baa: f43f ae6c beq.w 7886 <__rtl_cryptoEngine_v1_00+0x79a> + 7bae: f240 120c movw r2, #268 ; 0x10c + 7bb2: f2c0 0204 movt r2, #4 + 7bb6: f7fe fdc5 bl 6744 <__rtl_memDump_v1_00.part.7> + 7bba: e664 b.n 7886 <__rtl_cryptoEngine_v1_00+0x79a> + 7bbc: f240 00c8 movw r0, #200 ; 0xc8 + 7bc0: f240 01f4 movw r1, #244 ; 0xf4 + 7bc4: f24f 3c9d movw ip, #62365 ; 0xf39d + 7bc8: f2c0 0104 movt r1, #4 + 7bcc: f2c0 0c00 movt ip, #0 + 7bd0: 463a mov r2, r7 + 7bd2: 2310 movs r3, #16 + 7bd4: f2c0 0004 movt r0, #4 + 7bd8: 47e0 blx ip + 7bda: f240 1214 movw r2, #276 ; 0x114 + 7bde: 4638 mov r0, r7 + 7be0: 2110 movs r1, #16 + 7be2: f2c0 0204 movt r2, #4 + 7be6: f7fe fdad bl 6744 <__rtl_memDump_v1_00.part.7> + 7bea: f8d4 02e4 ldr.w r0, [r4, #740] ; 0x2e4 + 7bee: e6ab b.n 7948 <__rtl_cryptoEngine_v1_00+0x85c> + 7bf0: f240 00c8 movw r0, #200 ; 0xc8 + 7bf4: f240 01f4 movw r1, #244 ; 0xf4 + 7bf8: f24f 3c9d movw ip, #62365 ; 0xf39d + 7bfc: f2c0 0104 movt r1, #4 + 7c00: 465a mov r2, fp + 7c02: f2c0 0004 movt r0, #4 + 7c06: f2c0 0c00 movt ip, #0 + 7c0a: 47e0 blx ip + 7c0c: 8839 ldrh r1, [r7, #0] + 7c0e: 68f8 ldr r0, [r7, #12] + 7c10: f3c1 010d ubfx r1, r1, #0, #14 + 7c14: 2800 cmp r0, #0 + 7c16: bf18 it ne + 7c18: 2900 cmpne r1, #0 + 7c1a: f43f ae7e beq.w 791a <__rtl_cryptoEngine_v1_00+0x82e> + 7c1e: f240 1220 movw r2, #288 ; 0x120 + 7c22: f2c0 0204 movt r2, #4 + 7c26: f7fe fd8d bl 6744 <__rtl_memDump_v1_00.part.7> + 7c2a: e676 b.n 791a <__rtl_cryptoEngine_v1_00+0x82e> + 7c2c: f240 00c8 movw r0, #200 ; 0xc8 + 7c30: f240 01f4 movw r1, #244 ; 0xf4 + 7c34: f24f 379d movw r7, #62365 ; 0xf39d + 7c38: f2c0 0104 movt r1, #4 + 7c3c: f2c0 0700 movt r7, #0 + 7c40: 4642 mov r2, r8 + 7c42: 2310 movs r3, #16 + 7c44: f2c0 0004 movt r0, #4 + 7c48: 47b8 blx r7 + 7c4a: f240 1214 movw r2, #276 ; 0x114 + 7c4e: 4640 mov r0, r8 + 7c50: 2110 movs r1, #16 + 7c52: f2c0 0204 movt r2, #4 + 7c56: f7fe fd75 bl 6744 <__rtl_memDump_v1_00.part.7> + 7c5a: f8d4 72e4 ldr.w r7, [r4, #740] ; 0x2e4 + 7c5e: e62b b.n 78b8 <__rtl_cryptoEngine_v1_00+0x7cc> + 7c60: 2102 movs r1, #2 + 7c62: f7ff bb43 b.w 72ec <__rtl_cryptoEngine_v1_00+0x200> + 7c66: bf00 nop + +00007c68 <__rtl_crypto_cipher_init_v1_00>: + 7c68: b510 push {r4, lr} + 7c6a: 460c mov r4, r1 + 7c6c: b084 sub sp, #16 + 7c6e: 2100 movs r1, #0 + 7c70: e88d 000c stmia.w sp, {r2, r3} + 7c74: 9102 str r1, [sp, #8] + 7c76: 4622 mov r2, r4 + 7c78: 9103 str r1, [sp, #12] + 7c7a: f04f 33ff mov.w r3, #4294967295 + 7c7e: f7ff f809 bl 6c94 <__rtl_cryptoEngine_set_security_mode_v1_00> + 7c82: b004 add sp, #16 + 7c84: bd10 pop {r4, pc} + 7c86: bf00 nop + +00007c88 <__rtl_crypto_cipher_encrypt_v1_00>: + 7c88: b4f0 push {r4, r5, r6, r7} + 7c8a: 6881 ldr r1, [r0, #8] + 7c8c: 9e05 ldr r6, [sp, #20] + 7c8e: 9f04 ldr r7, [sp, #16] + 7c90: 2500 movs r5, #0 + 7c92: 73c5 strb r5, [r0, #15] + 7c94: f041 0c80 orr.w ip, r1, #128 ; 0x80 + 7c98: f8c0 c008 str.w ip, [r0, #8] + 7c9c: 4611 mov r1, r2 + 7c9e: 9505 str r5, [sp, #20] + 7ca0: 461a mov r2, r3 + 7ca2: 9604 str r6, [sp, #16] + 7ca4: 463b mov r3, r7 + 7ca6: bcf0 pop {r4, r5, r6, r7} + 7ca8: f7ff ba20 b.w 70ec <__rtl_cryptoEngine_v1_00> + +00007cac <__rtl_crypto_cipher_decrypt_v1_00>: + 7cac: b4f0 push {r4, r5, r6, r7} + 7cae: 6881 ldr r1, [r0, #8] + 7cb0: 9f04 ldr r7, [sp, #16] + 7cb2: 9c05 ldr r4, [sp, #20] + 7cb4: f04f 0c01 mov.w ip, #1 + 7cb8: f081 0680 eor.w r6, r1, #128 ; 0x80 + 7cbc: f880 c00f strb.w ip, [r0, #15] + 7cc0: 2500 movs r5, #0 + 7cc2: 6086 str r6, [r0, #8] + 7cc4: 4611 mov r1, r2 + 7cc6: 9404 str r4, [sp, #16] + 7cc8: 461a mov r2, r3 + 7cca: 9505 str r5, [sp, #20] + 7ccc: 463b mov r3, r7 + 7cce: bcf0 pop {r4, r5, r6, r7} + 7cd0: f7ff ba0c b.w 70ec <__rtl_cryptoEngine_v1_00> + +00007cd4 : + 7cd4: b5f0 push {r4, r5, r6, r7, lr} + 7cd6: f240 3450 movw r4, #848 ; 0x350 + 7cda: f2c1 0400 movt r4, #4096 ; 0x1000 + 7cde: 6823 ldr r3, [r4, #0] + 7ce0: b083 sub sp, #12 + 7ce2: 07d9 lsls r1, r3, #31 + 7ce4: 4605 mov r5, r0 + 7ce6: f100 809a bmi.w 7e1e + 7cea: 06df lsls r7, r3, #27 + 7cec: f895 6089 ldrb.w r6, [r5, #137] ; 0x89 + 7cf0: f895 5084 ldrb.w r5, [r5, #132] ; 0x84 + 7cf4: d47b bmi.n 7dee + 7cf6: 2d01 cmp r5, #1 + 7cf8: d04a beq.n 7d90 + 7cfa: d331 bcc.n 7d60 + 7cfc: 2d02 cmp r5, #2 + 7cfe: d017 beq.n 7d30 + 7d00: f240 3314 movw r3, #788 ; 0x314 + 7d04: f2c1 0300 movt r3, #4096 ; 0x1000 + 7d08: 681b ldr r3, [r3, #0] + 7d0a: 0519 lsls r1, r3, #20 + 7d0c: d508 bpl.n 7d20 + 7d0e: f240 20fc movw r0, #764 ; 0x2fc + 7d12: f24f 339d movw r3, #62365 ; 0xf39d + 7d16: f2c0 0004 movt r0, #4 + 7d1a: f2c0 0300 movt r3, #0 + 7d1e: 4798 blx r3 + 7d20: 2303 movs r3, #3 + 7d22: 9301 str r3, [sp, #4] + 7d24: 6823 ldr r3, [r4, #0] + 7d26: 06da lsls r2, r3, #27 + 7d28: d44a bmi.n 7dc0 + 7d2a: 9801 ldr r0, [sp, #4] + 7d2c: b003 add sp, #12 + 7d2e: bdf0 pop {r4, r5, r6, r7, pc} + 7d30: f44f 730d mov.w r3, #564 ; 0x234 + 7d34: f2c4 0300 movt r3, #16384 ; 0x4000 + 7d38: 681a ldr r2, [r3, #0] + 7d3a: 4631 mov r1, r6 + 7d3c: f442 1280 orr.w r2, r2, #1048576 ; 0x100000 + 7d40: 601a str r2, [r3, #0] + 7d42: 200a movs r0, #10 + 7d44: 2201 movs r2, #1 + 7d46: f7fa fef7 bl 2b38 + 7d4a: f44f 7306 mov.w r3, #536 ; 0x218 + 7d4e: f2c4 0300 movt r3, #16384 ; 0x4000 + 7d52: 6819 ldr r1, [r3, #0] + 7d54: 2200 movs r2, #0 + 7d56: f441 6180 orr.w r1, r1, #1024 ; 0x400 + 7d5a: 6019 str r1, [r3, #0] + 7d5c: 9201 str r2, [sp, #4] + 7d5e: e7e1 b.n 7d24 + 7d60: f44f 730d mov.w r3, #564 ; 0x234 + 7d64: f2c4 0300 movt r3, #16384 ; 0x4000 + 7d68: 681a ldr r2, [r3, #0] + 7d6a: 4631 mov r1, r6 + 7d6c: f442 3280 orr.w r2, r2, #65536 ; 0x10000 + 7d70: 601a str r2, [r3, #0] + 7d72: 2008 movs r0, #8 + 7d74: 2201 movs r2, #1 + 7d76: f7fa fedf bl 2b38 + 7d7a: f44f 7306 mov.w r3, #536 ; 0x218 + 7d7e: f2c4 0300 movt r3, #16384 ; 0x4000 + 7d82: 6819 ldr r1, [r3, #0] + 7d84: 2200 movs r2, #0 + 7d86: f441 7180 orr.w r1, r1, #256 ; 0x100 + 7d8a: 6019 str r1, [r3, #0] + 7d8c: 9201 str r2, [sp, #4] + 7d8e: e7c9 b.n 7d24 + 7d90: f44f 730d mov.w r3, #564 ; 0x234 + 7d94: f2c4 0300 movt r3, #16384 ; 0x4000 + 7d98: 681a ldr r2, [r3, #0] + 7d9a: 4631 mov r1, r6 + 7d9c: f442 2280 orr.w r2, r2, #262144 ; 0x40000 + 7da0: 601a str r2, [r3, #0] + 7da2: 2009 movs r0, #9 + 7da4: 462a mov r2, r5 + 7da6: f7fa fec7 bl 2b38 + 7daa: f44f 7306 mov.w r3, #536 ; 0x218 + 7dae: f2c4 0300 movt r3, #16384 ; 0x4000 + 7db2: 6819 ldr r1, [r3, #0] + 7db4: 2200 movs r2, #0 + 7db6: f441 7100 orr.w r1, r1, #512 ; 0x200 + 7dba: 6019 str r1, [r3, #0] + 7dbc: 9201 str r2, [sp, #4] + 7dbe: e7b1 b.n 7d24 + 7dc0: f240 3310 movw r3, #784 ; 0x310 + 7dc4: f2c1 0300 movt r3, #4096 ; 0x1000 + 7dc8: 681b ldr r3, [r3, #0] + 7dca: 051b lsls r3, r3, #20 + 7dcc: d5ad bpl.n 7d2a + 7dce: f44f 7221 mov.w r2, #644 ; 0x284 + 7dd2: f2c4 0200 movt r2, #16384 ; 0x4000 + 7dd6: f240 301c movw r0, #796 ; 0x31c + 7dda: f24f 349d movw r4, #62365 ; 0xf39d + 7dde: 6813 ldr r3, [r2, #0] + 7de0: 4629 mov r1, r5 + 7de2: f2c0 0400 movt r4, #0 + 7de6: f2c0 0004 movt r0, #4 + 7dea: 47a0 blx r4 + 7dec: e79d b.n 7d2a + 7dee: f240 3310 movw r3, #784 ; 0x310 + 7df2: f2c1 0300 movt r3, #4096 ; 0x1000 + 7df6: 681b ldr r3, [r3, #0] + 7df8: 0518 lsls r0, r3, #20 + 7dfa: f57f af7c bpl.w 7cf6 + 7dfe: f44f 7221 mov.w r2, #644 ; 0x284 + 7e02: f2c4 0200 movt r2, #16384 ; 0x4000 + 7e06: f240 20c8 movw r0, #712 ; 0x2c8 + 7e0a: f24f 379d movw r7, #62365 ; 0xf39d + 7e0e: 6813 ldr r3, [r2, #0] + 7e10: f2c0 0700 movt r7, #0 + 7e14: 4629 mov r1, r5 + 7e16: f2c0 0004 movt r0, #4 + 7e1a: 47b8 blx r7 + 7e1c: e76b b.n 7cf6 + 7e1e: f240 3210 movw r2, #784 ; 0x310 + 7e22: f2c1 0200 movt r2, #4096 ; 0x1000 + 7e26: 6812 ldr r2, [r2, #0] + 7e28: 0512 lsls r2, r2, #20 + 7e2a: f57f af5e bpl.w 7cea + 7e2e: f240 2090 movw r0, #656 ; 0x290 + 7e32: f24f 339d movw r3, #62365 ; 0xf39d + 7e36: f2c0 0004 movt r0, #4 + 7e3a: f2c0 0300 movt r3, #0 + 7e3e: 4798 blx r3 + 7e40: 6823 ldr r3, [r4, #0] + 7e42: e752 b.n 7cea + +00007e44 : + 7e44: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + 7e48: f240 3450 movw r4, #848 ; 0x350 + 7e4c: f2c1 0400 movt r4, #4096 ; 0x1000 + 7e50: 6823 ldr r3, [r4, #0] + 7e52: 4605 mov r5, r0 + 7e54: 07df lsls r7, r3, #31 + 7e56: d415 bmi.n 7e84 + 7e58: f895 6084 ldrb.w r6, [r5, #132] ; 0x84 + 7e5c: 0698 lsls r0, r3, #26 + 7e5e: f506 1580 add.w r5, r6, #1048576 ; 0x100000 + 7e62: f505 7584 add.w r5, r5, #264 ; 0x108 + 7e66: ea4f 2585 mov.w r5, r5, lsl #10 + 7e6a: f105 0808 add.w r8, r5, #8 + 7e6e: 68af ldr r7, [r5, #8] + 7e70: d42e bmi.n 7ed0 + 7e72: f047 0701 orr.w r7, r7, #1 + 7e76: 60af str r7, [r5, #8] + 7e78: 6823 ldr r3, [r4, #0] + 7e7a: 069a lsls r2, r3, #26 + 7e7c: d414 bmi.n 7ea8 + 7e7e: 2000 movs r0, #0 + 7e80: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 7e84: f240 3210 movw r2, #784 ; 0x310 + 7e88: f2c1 0200 movt r2, #4096 ; 0x1000 + 7e8c: 6812 ldr r2, [r2, #0] + 7e8e: 0516 lsls r6, r2, #20 + 7e90: d5e2 bpl.n 7e58 + 7e92: f240 3050 movw r0, #848 ; 0x350 + 7e96: f24f 339d movw r3, #62365 ; 0xf39d + 7e9a: f2c0 0004 movt r0, #4 + 7e9e: f2c0 0300 movt r3, #0 + 7ea2: 4798 blx r3 + 7ea4: 6823 ldr r3, [r4, #0] + 7ea6: e7d7 b.n 7e58 + 7ea8: f240 3310 movw r3, #784 ; 0x310 + 7eac: f2c1 0300 movt r3, #4096 ; 0x1000 + 7eb0: 681b ldr r3, [r3, #0] + 7eb2: 051b lsls r3, r3, #20 + 7eb4: d5e3 bpl.n 7e7e + 7eb6: f240 30b8 movw r0, #952 ; 0x3b8 + 7eba: f24f 349d movw r4, #62365 ; 0xf39d + 7ebe: 68ab ldr r3, [r5, #8] + 7ec0: 4631 mov r1, r6 + 7ec2: 4642 mov r2, r8 + 7ec4: f2c0 0400 movt r4, #0 + 7ec8: f2c0 0004 movt r0, #4 + 7ecc: 47a0 blx r4 + 7ece: e7d6 b.n 7e7e + 7ed0: f240 3310 movw r3, #784 ; 0x310 + 7ed4: f2c1 0300 movt r3, #4096 ; 0x1000 + 7ed8: 681b ldr r3, [r3, #0] + 7eda: 0519 lsls r1, r3, #20 + 7edc: d5c9 bpl.n 7e72 + 7ede: f240 3080 movw r0, #896 ; 0x380 + 7ee2: f24f 3c9d movw ip, #62365 ; 0xf39d + 7ee6: 4631 mov r1, r6 + 7ee8: f2c0 0c00 movt ip, #0 + 7eec: 4642 mov r2, r8 + 7eee: 463b mov r3, r7 + 7ef0: f2c0 0004 movt r0, #4 + 7ef4: 47e0 blx ip + 7ef6: e7bc b.n 7e72 + +00007ef8 : + 7ef8: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + 7efc: f240 3450 movw r4, #848 ; 0x350 + 7f00: f2c1 0400 movt r4, #4096 ; 0x1000 + 7f04: 6823 ldr r3, [r4, #0] + 7f06: 4605 mov r5, r0 + 7f08: 07df lsls r7, r3, #31 + 7f0a: d415 bmi.n 7f38 + 7f0c: f895 6084 ldrb.w r6, [r5, #132] ; 0x84 + 7f10: 0698 lsls r0, r3, #26 + 7f12: f506 1580 add.w r5, r6, #1048576 ; 0x100000 + 7f16: f505 7584 add.w r5, r5, #264 ; 0x108 + 7f1a: ea4f 2585 mov.w r5, r5, lsl #10 + 7f1e: f105 0808 add.w r8, r5, #8 + 7f22: 68af ldr r7, [r5, #8] + 7f24: d42e bmi.n 7f84 + 7f26: f027 0701 bic.w r7, r7, #1 + 7f2a: 60af str r7, [r5, #8] + 7f2c: 6823 ldr r3, [r4, #0] + 7f2e: 069a lsls r2, r3, #26 + 7f30: d414 bmi.n 7f5c + 7f32: 2000 movs r0, #0 + 7f34: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 7f38: f240 3210 movw r2, #784 ; 0x310 + 7f3c: f2c1 0200 movt r2, #4096 ; 0x1000 + 7f40: 6812 ldr r2, [r2, #0] + 7f42: 0516 lsls r6, r2, #20 + 7f44: d5e2 bpl.n 7f0c + 7f46: f240 30f0 movw r0, #1008 ; 0x3f0 + 7f4a: f24f 339d movw r3, #62365 ; 0xf39d + 7f4e: f2c0 0004 movt r0, #4 + 7f52: f2c0 0300 movt r3, #0 + 7f56: 4798 blx r3 + 7f58: 6823 ldr r3, [r4, #0] + 7f5a: e7d7 b.n 7f0c + 7f5c: f240 3310 movw r3, #784 ; 0x310 + 7f60: f2c1 0300 movt r3, #4096 ; 0x1000 + 7f64: 681b ldr r3, [r3, #0] + 7f66: 051b lsls r3, r3, #20 + 7f68: d5e3 bpl.n 7f32 + 7f6a: f240 30b8 movw r0, #952 ; 0x3b8 + 7f6e: f24f 349d movw r4, #62365 ; 0xf39d + 7f72: 68ab ldr r3, [r5, #8] + 7f74: 4631 mov r1, r6 + 7f76: 4642 mov r2, r8 + 7f78: f2c0 0400 movt r4, #0 + 7f7c: f2c0 0004 movt r0, #4 + 7f80: 47a0 blx r4 + 7f82: e7d6 b.n 7f32 + 7f84: f240 3310 movw r3, #784 ; 0x310 + 7f88: f2c1 0300 movt r3, #4096 ; 0x1000 + 7f8c: 681b ldr r3, [r3, #0] + 7f8e: 0519 lsls r1, r3, #20 + 7f90: d5c9 bpl.n 7f26 + 7f92: f240 3080 movw r0, #896 ; 0x380 + 7f96: f24f 3c9d movw ip, #62365 ; 0xf39d + 7f9a: 4631 mov r1, r6 + 7f9c: f2c0 0c00 movt ip, #0 + 7fa0: 4642 mov r2, r8 + 7fa2: 463b mov r3, r7 + 7fa4: f2c0 0004 movt r0, #4 + 7fa8: 47e0 blx ip + 7faa: e7bc b.n 7f26 + +00007fac : + 7fac: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} + 7fb0: f240 3950 movw r9, #848 ; 0x350 + 7fb4: f2c1 0900 movt r9, #4096 ; 0x1000 + 7fb8: f8d9 3000 ldr.w r3, [r9] + 7fbc: b082 sub sp, #8 + 7fbe: 07dc lsls r4, r3, #31 + 7fc0: 4680 mov r8, r0 + 7fc2: d46d bmi.n 80a0 + 7fc4: 461a mov r2, r3 + 7fc6: 698b ldr r3, [r1, #24] + 7fc8: 6848 ldr r0, [r1, #4] + 7fca: 688f ldr r7, [r1, #8] + 7fcc: 68ce ldr r6, [r1, #12] + 7fce: 694c ldr r4, [r1, #20] + 7fd0: 690d ldr r5, [r1, #16] + 7fd2: f8c8 3058 str.w r3, [r8, #88] ; 0x58 + 7fd6: 6a0b ldr r3, [r1, #32] + 7fd8: f8c8 0044 str.w r0, [r8, #68] ; 0x44 + 7fdc: 69c8 ldr r0, [r1, #28] + 7fde: f8c8 3060 str.w r3, [r8, #96] ; 0x60 + 7fe2: 680b ldr r3, [r1, #0] + 7fe4: f8c8 005c str.w r0, [r8, #92] ; 0x5c + 7fe8: 6a48 ldr r0, [r1, #36] ; 0x24 + 7fea: f8c8 3040 str.w r3, [r8, #64] ; 0x40 + 7fee: 6a8b ldr r3, [r1, #40] ; 0x28 + 7ff0: f8c8 3068 str.w r3, [r8, #104] ; 0x68 + 7ff4: 6acb ldr r3, [r1, #44] ; 0x2c + 7ff6: f8c8 7048 str.w r7, [r8, #72] ; 0x48 + 7ffa: 6b0f ldr r7, [r1, #48] ; 0x30 + 7ffc: f8c8 604c str.w r6, [r8, #76] ; 0x4c + 8000: 6b4e ldr r6, [r1, #52] ; 0x34 + 8002: f8c8 306c str.w r3, [r8, #108] ; 0x6c + 8006: f8c8 4054 str.w r4, [r8, #84] ; 0x54 + 800a: f8c8 0064 str.w r0, [r8, #100] ; 0x64 + 800e: f8c8 5050 str.w r5, [r8, #80] ; 0x50 + 8012: f8c8 7070 str.w r7, [r8, #112] ; 0x70 + 8016: f8c8 6074 str.w r6, [r8, #116] ; 0x74 + 801a: f891 3040 ldrb.w r3, [r1, #64] ; 0x40 + 801e: f888 3080 strb.w r3, [r8, #128] ; 0x80 + 8022: f891 3041 ldrb.w r3, [r1, #65] ; 0x41 + 8026: f888 3081 strb.w r3, [r8, #129] ; 0x81 + 802a: f891 3042 ldrb.w r3, [r1, #66] ; 0x42 + 802e: f888 3082 strb.w r3, [r8, #130] ; 0x82 + 8032: f891 3043 ldrb.w r3, [r1, #67] ; 0x43 + 8036: f888 3083 strb.w r3, [r8, #131] ; 0x83 + 803a: f891 3044 ldrb.w r3, [r1, #68] ; 0x44 + 803e: f888 3085 strb.w r3, [r8, #133] ; 0x85 + 8042: f891 3048 ldrb.w r3, [r1, #72] ; 0x48 + 8046: f888 308b strb.w r3, [r8, #139] ; 0x8b + 804a: f891 3049 ldrb.w r3, [r1, #73] ; 0x49 + 804e: f888 308c strb.w r3, [r8, #140] ; 0x8c + 8052: f891 304b ldrb.w r3, [r1, #75] ; 0x4b + 8056: f888 308e strb.w r3, [r8, #142] ; 0x8e + 805a: f891 304c ldrb.w r3, [r1, #76] ; 0x4c + 805e: f888 308f strb.w r3, [r8, #143] ; 0x8f + 8062: 6b8b ldr r3, [r1, #56] ; 0x38 + 8064: 8f88 ldrh r0, [r1, #60] ; 0x3c + 8066: 8fcc ldrh r4, [r1, #62] ; 0x3e + 8068: f8a8 007c strh.w r0, [r8, #124] ; 0x7c + 806c: f8a8 407e strh.w r4, [r8, #126] ; 0x7e + 8070: f8c8 3078 str.w r3, [r8, #120] ; 0x78 + 8074: f891 304a ldrb.w r3, [r1, #74] ; 0x4a + 8078: f888 308d strb.w r3, [r8, #141] ; 0x8d + 807c: f891 3045 ldrb.w r3, [r1, #69] ; 0x45 + 8080: f888 3086 strb.w r3, [r8, #134] ; 0x86 + 8084: f891 3047 ldrb.w r3, [r1, #71] ; 0x47 + 8088: f888 3088 strb.w r3, [r8, #136] ; 0x88 + 808c: f891 3046 ldrb.w r3, [r1, #70] ; 0x46 + 8090: 0711 lsls r1, r2, #28 + 8092: f888 3087 strb.w r3, [r8, #135] ; 0x87 + 8096: d418 bmi.n 80ca + 8098: 2000 movs r0, #0 + 809a: b002 add sp, #8 + 809c: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + 80a0: f240 3210 movw r2, #784 ; 0x310 + 80a4: f2c1 0200 movt r2, #4096 ; 0x1000 + 80a8: 6812 ldr r2, [r2, #0] + 80aa: 0510 lsls r0, r2, #20 + 80ac: d58a bpl.n 7fc4 + 80ae: f240 4024 movw r0, #1060 ; 0x424 + 80b2: f24f 339d movw r3, #62365 ; 0xf39d + 80b6: 9101 str r1, [sp, #4] + 80b8: f2c0 0004 movt r0, #4 + 80bc: f2c0 0300 movt r3, #0 + 80c0: 4798 blx r3 + 80c2: f8d9 2000 ldr.w r2, [r9] + 80c6: 9901 ldr r1, [sp, #4] + 80c8: e77d b.n 7fc6 + 80ca: f240 3410 movw r4, #784 ; 0x310 + 80ce: f2c1 0400 movt r4, #4096 ; 0x1000 + 80d2: 6823 ldr r3, [r4, #0] + 80d4: 051a lsls r2, r3, #20 + 80d6: d5df bpl.n 8098 + 80d8: f240 405c movw r0, #1116 ; 0x45c + 80dc: f24f 359d movw r5, #62365 ; 0xf39d + 80e0: f240 3650 movw r6, #848 ; 0x350 + 80e4: f2c0 0004 movt r0, #4 + 80e8: f2c0 0500 movt r5, #0 + 80ec: f898 1084 ldrb.w r1, [r8, #132] ; 0x84 + 80f0: 47a8 blx r5 + 80f2: f8d9 3000 ldr.w r3, [r9] + 80f6: f2c1 0600 movt r6, #4096 ; 0x1000 + 80fa: 071f lsls r7, r3, #28 + 80fc: d5cc bpl.n 8098 + 80fe: 6823 ldr r3, [r4, #0] + 8100: 051b lsls r3, r3, #20 + 8102: d5c9 bpl.n 8098 + 8104: f240 408c movw r0, #1164 ; 0x48c + 8108: f8d8 1040 ldr.w r1, [r8, #64] ; 0x40 + 810c: f2c0 0004 movt r0, #4 + 8110: 47a8 blx r5 + 8112: 6833 ldr r3, [r6, #0] + 8114: 0719 lsls r1, r3, #28 + 8116: d5bf bpl.n 8098 + 8118: 6823 ldr r3, [r4, #0] + 811a: 0518 lsls r0, r3, #20 + 811c: d5bc bpl.n 8098 + 811e: f240 40b4 movw r0, #1204 ; 0x4b4 + 8122: f8d8 1044 ldr.w r1, [r8, #68] ; 0x44 + 8126: f2c0 0004 movt r0, #4 + 812a: 47a8 blx r5 + 812c: 6833 ldr r3, [r6, #0] + 812e: 071b lsls r3, r3, #28 + 8130: d5b2 bpl.n 8098 + 8132: 6823 ldr r3, [r4, #0] + 8134: 051a lsls r2, r3, #20 + 8136: d5af bpl.n 8098 + 8138: f240 40dc movw r0, #1244 ; 0x4dc + 813c: f8d8 1048 ldr.w r1, [r8, #72] ; 0x48 + 8140: f2c0 0004 movt r0, #4 + 8144: 47a8 blx r5 + 8146: 6833 ldr r3, [r6, #0] + 8148: 071e lsls r6, r3, #28 + 814a: d5a5 bpl.n 8098 + 814c: 6823 ldr r3, [r4, #0] + 814e: 051f lsls r7, r3, #20 + 8150: d5a2 bpl.n 8098 + 8152: f240 5004 movw r0, #1284 ; 0x504 + 8156: f24f 369d movw r6, #62365 ; 0xf39d + 815a: f240 3750 movw r7, #848 ; 0x350 + 815e: f8d8 104c ldr.w r1, [r8, #76] ; 0x4c + 8162: f2c0 0004 movt r0, #4 + 8166: 47a8 blx r5 + 8168: f8d9 3000 ldr.w r3, [r9] + 816c: f2c0 0600 movt r6, #0 + 8170: 0719 lsls r1, r3, #28 + 8172: f2c1 0700 movt r7, #4096 ; 0x1000 + 8176: d58f bpl.n 8098 + 8178: f240 3a10 movw sl, #784 ; 0x310 + 817c: 6823 ldr r3, [r4, #0] + 817e: f2c1 0a00 movt sl, #4096 ; 0x1000 + 8182: 0518 lsls r0, r3, #20 + 8184: d588 bpl.n 8098 + 8186: f240 502c movw r0, #1324 ; 0x52c + 818a: f8d8 1050 ldr.w r1, [r8, #80] ; 0x50 + 818e: f2c0 0004 movt r0, #4 + 8192: 47b0 blx r6 + 8194: 683b ldr r3, [r7, #0] + 8196: 071b lsls r3, r3, #28 + 8198: f57f af7e bpl.w 8098 + 819c: f8da 3000 ldr.w r3, [sl] + 81a0: 051a lsls r2, r3, #20 + 81a2: f57f af79 bpl.w 8098 + 81a6: f240 5054 movw r0, #1364 ; 0x554 + 81aa: f8d8 1054 ldr.w r1, [r8, #84] ; 0x54 + 81ae: f2c0 0004 movt r0, #4 + 81b2: 47b0 blx r6 + 81b4: 683b ldr r3, [r7, #0] + 81b6: 0719 lsls r1, r3, #28 + 81b8: f57f af6e bpl.w 8098 + 81bc: f8da 3000 ldr.w r3, [sl] + 81c0: 0518 lsls r0, r3, #20 + 81c2: f57f af69 bpl.w 8098 + 81c6: f240 507c movw r0, #1404 ; 0x57c + 81ca: f8d8 1058 ldr.w r1, [r8, #88] ; 0x58 + 81ce: f2c0 0004 movt r0, #4 + 81d2: 47b0 blx r6 + 81d4: 683b ldr r3, [r7, #0] + 81d6: 071b lsls r3, r3, #28 + 81d8: f57f af5e bpl.w 8098 + 81dc: f8da 3000 ldr.w r3, [sl] + 81e0: 051a lsls r2, r3, #20 + 81e2: f57f af59 bpl.w 8098 + 81e6: f240 50a4 movw r0, #1444 ; 0x5a4 + 81ea: f8d8 105c ldr.w r1, [r8, #92] ; 0x5c + 81ee: f2c0 0004 movt r0, #4 + 81f2: 47b0 blx r6 + 81f4: 683b ldr r3, [r7, #0] + 81f6: 071e lsls r6, r3, #28 + 81f8: f57f af4e bpl.w 8098 + 81fc: f8da 3000 ldr.w r3, [sl] + 8200: 051f lsls r7, r3, #20 + 8202: f57f af49 bpl.w 8098 + 8206: f240 50cc movw r0, #1484 ; 0x5cc + 820a: f24f 369d movw r6, #62365 ; 0xf39d + 820e: f240 3750 movw r7, #848 ; 0x350 + 8212: f8d8 1060 ldr.w r1, [r8, #96] ; 0x60 + 8216: f2c0 0004 movt r0, #4 + 821a: 47a8 blx r5 + 821c: f8d9 3000 ldr.w r3, [r9] + 8220: f2c0 0600 movt r6, #0 + 8224: 0719 lsls r1, r3, #28 + 8226: f2c1 0700 movt r7, #4096 ; 0x1000 + 822a: f57f af35 bpl.w 8098 + 822e: f240 3a10 movw sl, #784 ; 0x310 + 8232: 6823 ldr r3, [r4, #0] + 8234: f2c1 0a00 movt sl, #4096 ; 0x1000 + 8238: 0518 lsls r0, r3, #20 + 823a: f57f af2d bpl.w 8098 + 823e: f240 50f4 movw r0, #1524 ; 0x5f4 + 8242: f8d8 1064 ldr.w r1, [r8, #100] ; 0x64 + 8246: f2c0 0004 movt r0, #4 + 824a: 47b0 blx r6 + 824c: 683b ldr r3, [r7, #0] + 824e: 071b lsls r3, r3, #28 + 8250: f57f af22 bpl.w 8098 + 8254: f8da 3000 ldr.w r3, [sl] + 8258: 051a lsls r2, r3, #20 + 825a: f57f af1d bpl.w 8098 + 825e: f240 601c movw r0, #1564 ; 0x61c + 8262: f8d8 1068 ldr.w r1, [r8, #104] ; 0x68 + 8266: f2c0 0004 movt r0, #4 + 826a: 47b0 blx r6 + 826c: 683b ldr r3, [r7, #0] + 826e: 0719 lsls r1, r3, #28 + 8270: f57f af12 bpl.w 8098 + 8274: f8da 3000 ldr.w r3, [sl] + 8278: 0518 lsls r0, r3, #20 + 827a: f57f af0d bpl.w 8098 + 827e: f240 6044 movw r0, #1604 ; 0x644 + 8282: f8d8 106c ldr.w r1, [r8, #108] ; 0x6c + 8286: f2c0 0004 movt r0, #4 + 828a: 47b0 blx r6 + 828c: 683b ldr r3, [r7, #0] + 828e: 071b lsls r3, r3, #28 + 8290: f57f af02 bpl.w 8098 + 8294: f8da 3000 ldr.w r3, [sl] + 8298: 051a lsls r2, r3, #20 + 829a: f57f aefd bpl.w 8098 + 829e: f240 606c movw r0, #1644 ; 0x66c + 82a2: f8d8 1070 ldr.w r1, [r8, #112] ; 0x70 + 82a6: f2c0 0004 movt r0, #4 + 82aa: 47b0 blx r6 + 82ac: 683b ldr r3, [r7, #0] + 82ae: 071e lsls r6, r3, #28 + 82b0: f57f aef2 bpl.w 8098 + 82b4: f8da 3000 ldr.w r3, [sl] + 82b8: 051f lsls r7, r3, #20 + 82ba: f57f aeed bpl.w 8098 + 82be: f240 6094 movw r0, #1684 ; 0x694 + 82c2: f24f 369d movw r6, #62365 ; 0xf39d + 82c6: f240 3750 movw r7, #848 ; 0x350 + 82ca: f8d8 1074 ldr.w r1, [r8, #116] ; 0x74 + 82ce: f2c0 0004 movt r0, #4 + 82d2: 47a8 blx r5 + 82d4: f8d9 3000 ldr.w r3, [r9] + 82d8: f2c0 0600 movt r6, #0 + 82dc: 0719 lsls r1, r3, #28 + 82de: f2c1 0700 movt r7, #4096 ; 0x1000 + 82e2: f57f aed9 bpl.w 8098 + 82e6: f240 3a10 movw sl, #784 ; 0x310 + 82ea: 6823 ldr r3, [r4, #0] + 82ec: f2c1 0a00 movt sl, #4096 ; 0x1000 + 82f0: 0518 lsls r0, r3, #20 + 82f2: f57f aed1 bpl.w 8098 + 82f6: f240 60bc movw r0, #1724 ; 0x6bc + 82fa: f898 1080 ldrb.w r1, [r8, #128] ; 0x80 + 82fe: f2c0 0004 movt r0, #4 + 8302: 47b0 blx r6 + 8304: 683b ldr r3, [r7, #0] + 8306: 071b lsls r3, r3, #28 + 8308: f57f aec6 bpl.w 8098 + 830c: f8da 3000 ldr.w r3, [sl] + 8310: 051a lsls r2, r3, #20 + 8312: f57f aec1 bpl.w 8098 + 8316: f240 60e4 movw r0, #1764 ; 0x6e4 + 831a: f898 1081 ldrb.w r1, [r8, #129] ; 0x81 + 831e: f2c0 0004 movt r0, #4 + 8322: 47b0 blx r6 + 8324: 683b ldr r3, [r7, #0] + 8326: 0719 lsls r1, r3, #28 + 8328: f57f aeb6 bpl.w 8098 + 832c: f8da 3000 ldr.w r3, [sl] + 8330: 0518 lsls r0, r3, #20 + 8332: f57f aeb1 bpl.w 8098 + 8336: f240 700c movw r0, #1804 ; 0x70c + 833a: f898 1082 ldrb.w r1, [r8, #130] ; 0x82 + 833e: f2c0 0004 movt r0, #4 + 8342: 47b0 blx r6 + 8344: 683b ldr r3, [r7, #0] + 8346: 071b lsls r3, r3, #28 + 8348: f57f aea6 bpl.w 8098 + 834c: f8da 3000 ldr.w r3, [sl] + 8350: 051a lsls r2, r3, #20 + 8352: f57f aea1 bpl.w 8098 + 8356: f240 7034 movw r0, #1844 ; 0x734 + 835a: f898 1083 ldrb.w r1, [r8, #131] ; 0x83 + 835e: f2c0 0004 movt r0, #4 + 8362: 47b0 blx r6 + 8364: 683b ldr r3, [r7, #0] + 8366: 071e lsls r6, r3, #28 + 8368: f57f ae96 bpl.w 8098 + 836c: f8da 3000 ldr.w r3, [sl] + 8370: 051f lsls r7, r3, #20 + 8372: f57f ae91 bpl.w 8098 + 8376: f240 705c movw r0, #1884 ; 0x75c + 837a: f24f 369d movw r6, #62365 ; 0xf39d + 837e: f240 3750 movw r7, #848 ; 0x350 + 8382: f898 1085 ldrb.w r1, [r8, #133] ; 0x85 + 8386: f2c0 0004 movt r0, #4 + 838a: 47a8 blx r5 + 838c: f8d9 3000 ldr.w r3, [r9] + 8390: f2c0 0600 movt r6, #0 + 8394: 0719 lsls r1, r3, #28 + 8396: f2c1 0700 movt r7, #4096 ; 0x1000 + 839a: f57f ae7d bpl.w 8098 + 839e: f240 3a10 movw sl, #784 ; 0x310 + 83a2: 6823 ldr r3, [r4, #0] + 83a4: f2c1 0a00 movt sl, #4096 ; 0x1000 + 83a8: 0518 lsls r0, r3, #20 + 83aa: f57f ae75 bpl.w 8098 + 83ae: f240 7084 movw r0, #1924 ; 0x784 + 83b2: f898 108b ldrb.w r1, [r8, #139] ; 0x8b + 83b6: f2c0 0004 movt r0, #4 + 83ba: 47b0 blx r6 + 83bc: 683b ldr r3, [r7, #0] + 83be: 071b lsls r3, r3, #28 + 83c0: f57f ae6a bpl.w 8098 + 83c4: f8da 3000 ldr.w r3, [sl] + 83c8: 051a lsls r2, r3, #20 + 83ca: f57f ae65 bpl.w 8098 + 83ce: f240 70ac movw r0, #1964 ; 0x7ac + 83d2: f898 108c ldrb.w r1, [r8, #140] ; 0x8c + 83d6: f2c0 0004 movt r0, #4 + 83da: 47b0 blx r6 + 83dc: 683b ldr r3, [r7, #0] + 83de: 0719 lsls r1, r3, #28 + 83e0: f57f ae5a bpl.w 8098 + 83e4: f8da 3000 ldr.w r3, [sl] + 83e8: 0518 lsls r0, r3, #20 + 83ea: f57f ae55 bpl.w 8098 + 83ee: f240 70d4 movw r0, #2004 ; 0x7d4 + 83f2: f898 108e ldrb.w r1, [r8, #142] ; 0x8e + 83f6: f2c0 0004 movt r0, #4 + 83fa: 47b0 blx r6 + 83fc: 683b ldr r3, [r7, #0] + 83fe: 071b lsls r3, r3, #28 + 8400: f57f ae4a bpl.w 8098 + 8404: f8da 3000 ldr.w r3, [sl] + 8408: 051a lsls r2, r3, #20 + 840a: f57f ae45 bpl.w 8098 + 840e: f240 70fc movw r0, #2044 ; 0x7fc + 8412: f898 108f ldrb.w r1, [r8, #143] ; 0x8f + 8416: f2c0 0004 movt r0, #4 + 841a: 47b0 blx r6 + 841c: 683b ldr r3, [r7, #0] + 841e: 071e lsls r6, r3, #28 + 8420: f57f ae3a bpl.w 8098 + 8424: f8da 3000 ldr.w r3, [sl] + 8428: 051f lsls r7, r3, #20 + 842a: f57f ae35 bpl.w 8098 + 842e: f640 0024 movw r0, #2084 ; 0x824 + 8432: f24f 369d movw r6, #62365 ; 0xf39d + 8436: f240 3750 movw r7, #848 ; 0x350 + 843a: f8b8 107c ldrh.w r1, [r8, #124] ; 0x7c + 843e: f2c0 0004 movt r0, #4 + 8442: 47a8 blx r5 + 8444: f8d9 3000 ldr.w r3, [r9] + 8448: f2c0 0600 movt r6, #0 + 844c: 0719 lsls r1, r3, #28 + 844e: f2c1 0700 movt r7, #4096 ; 0x1000 + 8452: f57f ae21 bpl.w 8098 + 8456: f240 3a10 movw sl, #784 ; 0x310 + 845a: 6823 ldr r3, [r4, #0] + 845c: f2c1 0a00 movt sl, #4096 ; 0x1000 + 8460: 0518 lsls r0, r3, #20 + 8462: f57f ae19 bpl.w 8098 + 8466: f640 004c movw r0, #2124 ; 0x84c + 846a: f8b8 107e ldrh.w r1, [r8, #126] ; 0x7e + 846e: f2c0 0004 movt r0, #4 + 8472: 47b0 blx r6 + 8474: 683b ldr r3, [r7, #0] + 8476: 071b lsls r3, r3, #28 + 8478: f57f ae0e bpl.w 8098 + 847c: f8da 3000 ldr.w r3, [sl] + 8480: 051a lsls r2, r3, #20 + 8482: f57f ae09 bpl.w 8098 + 8486: f640 0074 movw r0, #2164 ; 0x874 + 848a: f8d8 1078 ldr.w r1, [r8, #120] ; 0x78 + 848e: f2c0 0004 movt r0, #4 + 8492: 47b0 blx r6 + 8494: 683b ldr r3, [r7, #0] + 8496: 0719 lsls r1, r3, #28 + 8498: f57f adfe bpl.w 8098 + 849c: f8da 3000 ldr.w r3, [sl] + 84a0: 0518 lsls r0, r3, #20 + 84a2: f57f adf9 bpl.w 8098 + 84a6: f640 009c movw r0, #2204 ; 0x89c + 84aa: f898 108d ldrb.w r1, [r8, #141] ; 0x8d + 84ae: f2c0 0004 movt r0, #4 + 84b2: 47b0 blx r6 + 84b4: 683b ldr r3, [r7, #0] + 84b6: 071b lsls r3, r3, #28 + 84b8: f57f adee bpl.w 8098 + 84bc: f8da 3000 ldr.w r3, [sl] + 84c0: 051a lsls r2, r3, #20 + 84c2: f57f ade9 bpl.w 8098 + 84c6: f640 00c4 movw r0, #2244 ; 0x8c4 + 84ca: f898 1086 ldrb.w r1, [r8, #134] ; 0x86 + 84ce: f2c0 0004 movt r0, #4 + 84d2: 47b0 blx r6 + 84d4: 683b ldr r3, [r7, #0] + 84d6: 0719 lsls r1, r3, #28 + 84d8: f57f adde bpl.w 8098 + 84dc: f8da 3000 ldr.w r3, [sl] + 84e0: 0518 lsls r0, r3, #20 + 84e2: f57f add9 bpl.w 8098 + 84e6: f640 00f0 movw r0, #2288 ; 0x8f0 + 84ea: f24f 369d movw r6, #62365 ; 0xf39d + 84ee: f2c0 0004 movt r0, #4 + 84f2: f898 1088 ldrb.w r1, [r8, #136] ; 0x88 + 84f6: 47a8 blx r5 + 84f8: f8d9 3000 ldr.w r3, [r9] + 84fc: f2c0 0600 movt r6, #0 + 8500: 071b lsls r3, r3, #28 + 8502: f57f adc9 bpl.w 8098 + 8506: 6823 ldr r3, [r4, #0] + 8508: 051a lsls r2, r3, #20 + 850a: f57f adc5 bpl.w 8098 + 850e: f640 101c movw r0, #2332 ; 0x91c + 8512: f898 1087 ldrb.w r1, [r8, #135] ; 0x87 + 8516: f2c0 0004 movt r0, #4 + 851a: 47b0 blx r6 + 851c: e5bc b.n 8098 + 851e: bf00 nop + +00008520 : + 8520: b570 push {r4, r5, r6, lr} + 8522: f240 3450 movw r4, #848 ; 0x350 + 8526: f2c1 0400 movt r4, #4096 ; 0x1000 + 852a: 6823 ldr r3, [r4, #0] + 852c: 4605 mov r5, r0 + 852e: 07d8 lsls r0, r3, #31 + 8530: d412 bmi.n 8558 + 8532: 065a lsls r2, r3, #25 + 8534: f895 6085 ldrb.w r6, [r5, #133] ; 0x85 + 8538: f895 5084 ldrb.w r5, [r5, #132] ; 0x84 + 853c: d431 bmi.n 85a2 + 853e: f505 1380 add.w r3, r5, #1048576 ; 0x100000 + 8542: f503 7384 add.w r3, r3, #264 ; 0x108 + 8546: 029b lsls r3, r3, #10 + 8548: 62de str r6, [r3, #44] ; 0x2c + 854a: 6821 ldr r1, [r4, #0] + 854c: f103 022c add.w r2, r3, #44 ; 0x2c + 8550: 0648 lsls r0, r1, #25 + 8552: d413 bmi.n 857c + 8554: 2000 movs r0, #0 + 8556: bd70 pop {r4, r5, r6, pc} + 8558: f240 3210 movw r2, #784 ; 0x310 + 855c: f2c1 0200 movt r2, #4096 ; 0x1000 + 8560: 6812 ldr r2, [r2, #0] + 8562: 0511 lsls r1, r2, #20 + 8564: d5e5 bpl.n 8532 + 8566: f640 1048 movw r0, #2376 ; 0x948 + 856a: f24f 339d movw r3, #62365 ; 0xf39d + 856e: f2c0 0004 movt r0, #4 + 8572: f2c0 0300 movt r3, #0 + 8576: 4798 blx r3 + 8578: 6823 ldr r3, [r4, #0] + 857a: e7da b.n 8532 + 857c: f240 3110 movw r1, #784 ; 0x310 + 8580: f2c1 0100 movt r1, #4096 ; 0x1000 + 8584: 6809 ldr r1, [r1, #0] + 8586: 0509 lsls r1, r1, #20 + 8588: d5e4 bpl.n 8554 + 858a: f640 10b0 movw r0, #2480 ; 0x9b0 + 858e: f24f 349d movw r4, #62365 ; 0xf39d + 8592: 6adb ldr r3, [r3, #44] ; 0x2c + 8594: 4629 mov r1, r5 + 8596: f2c0 0400 movt r4, #0 + 859a: f2c0 0004 movt r0, #4 + 859e: 47a0 blx r4 + 85a0: e7d8 b.n 8554 + 85a2: f240 3310 movw r3, #784 ; 0x310 + 85a6: f2c1 0300 movt r3, #4096 ; 0x1000 + 85aa: 681b ldr r3, [r3, #0] + 85ac: 051b lsls r3, r3, #20 + 85ae: d5c6 bpl.n 853e + 85b0: f640 1084 movw r0, #2436 ; 0x984 + 85b4: f24f 339d movw r3, #62365 ; 0xf39d + 85b8: 4629 mov r1, r5 + 85ba: f2c0 0300 movt r3, #0 + 85be: 4632 mov r2, r6 + 85c0: f2c0 0004 movt r0, #4 + 85c4: 4798 blx r3 + 85c6: e7ba b.n 853e + +000085c8 : + 85c8: b538 push {r3, r4, r5, lr} + 85ca: f240 3450 movw r4, #848 ; 0x350 + 85ce: f2c1 0400 movt r4, #4096 ; 0x1000 + 85d2: 6823 ldr r3, [r4, #0] + 85d4: 4605 mov r5, r0 + 85d6: 07d8 lsls r0, r3, #31 + 85d8: d40b bmi.n 85f2 + 85da: f895 1084 ldrb.w r1, [r5, #132] ; 0x84 + 85de: f501 1280 add.w r2, r1, #1048576 ; 0x100000 + 85e2: f502 7284 add.w r2, r2, #264 ; 0x108 + 85e6: 0292 lsls r2, r2, #10 + 85e8: 6ad4 ldr r4, [r2, #44] ; 0x2c + 85ea: 065a lsls r2, r3, #25 + 85ec: d413 bmi.n 8616 + 85ee: 4620 mov r0, r4 + 85f0: bd38 pop {r3, r4, r5, pc} + 85f2: f240 3210 movw r2, #784 ; 0x310 + 85f6: f2c1 0200 movt r2, #4096 ; 0x1000 + 85fa: 6812 ldr r2, [r2, #0] + 85fc: 0511 lsls r1, r2, #20 + 85fe: d5ec bpl.n 85da + 8600: f640 10e4 movw r0, #2532 ; 0x9e4 + 8604: f24f 339d movw r3, #62365 ; 0xf39d + 8608: f2c0 0004 movt r0, #4 + 860c: f2c0 0300 movt r3, #0 + 8610: 4798 blx r3 + 8612: 6823 ldr r3, [r4, #0] + 8614: e7e1 b.n 85da + 8616: f240 3310 movw r3, #784 ; 0x310 + 861a: f2c1 0300 movt r3, #4096 ; 0x1000 + 861e: 681b ldr r3, [r3, #0] + 8620: 051b lsls r3, r3, #20 + 8622: d5e4 bpl.n 85ee + 8624: f640 2020 movw r0, #2592 ; 0xa20 + 8628: f24f 339d movw r3, #62365 ; 0xf39d + 862c: 4622 mov r2, r4 + 862e: f2c0 0300 movt r3, #0 + 8632: f2c0 0004 movt r0, #4 + 8636: 4798 blx r3 + 8638: e7d9 b.n 85ee + 863a: bf00 nop + +0000863c : + 863c: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + 8640: f240 3450 movw r4, #848 ; 0x350 + 8644: f2c1 0400 movt r4, #4096 ; 0x1000 + 8648: 6823 ldr r3, [r4, #0] + 864a: 4605 mov r5, r0 + 864c: 07df lsls r7, r3, #31 + 864e: d427 bmi.n 86a0 + 8650: f895 7084 ldrb.w r7, [r5, #132] ; 0x84 + 8654: f895 808c ldrb.w r8, [r5, #140] ; 0x8c + 8658: f507 1680 add.w r6, r7, #1048576 ; 0x100000 + 865c: f506 7684 add.w r6, r6, #264 ; 0x108 + 8660: 02b6 lsls r6, r6, #10 + 8662: 6832 ldr r2, [r6, #0] + 8664: ea4f 18c8 mov.w r8, r8, lsl #7 + 8668: f022 0280 bic.w r2, r2, #128 ; 0x80 + 866c: fa5f f888 uxtb.w r8, r8 + 8670: 0758 lsls r0, r3, #29 + 8672: ea42 0808 orr.w r8, r2, r8 + 8676: d439 bmi.n 86ec + 8678: f647 63f9 movw r3, #32505 ; 0x7ef9 + 867c: 4628 mov r0, r5 + 867e: f2c0 0300 movt r3, #0 + 8682: 4798 blx r3 + 8684: f647 6345 movw r3, #32325 ; 0x7e45 + 8688: f8c6 8000 str.w r8, [r6] + 868c: f2c0 0300 movt r3, #0 + 8690: 4628 mov r0, r5 + 8692: 4798 blx r3 + 8694: 6823 ldr r3, [r4, #0] + 8696: 075a lsls r2, r3, #29 + 8698: d414 bmi.n 86c4 + 869a: 2000 movs r0, #0 + 869c: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 86a0: f240 3210 movw r2, #784 ; 0x310 + 86a4: f2c1 0200 movt r2, #4096 ; 0x1000 + 86a8: 6812 ldr r2, [r2, #0] + 86aa: 0516 lsls r6, r2, #20 + 86ac: d5d0 bpl.n 8650 + 86ae: f640 2044 movw r0, #2628 ; 0xa44 + 86b2: f24f 339d movw r3, #62365 ; 0xf39d + 86b6: f2c0 0004 movt r0, #4 + 86ba: f2c0 0300 movt r3, #0 + 86be: 4798 blx r3 + 86c0: 6823 ldr r3, [r4, #0] + 86c2: e7c5 b.n 8650 + 86c4: f240 3310 movw r3, #784 ; 0x310 + 86c8: f2c1 0300 movt r3, #4096 ; 0x1000 + 86cc: 681b ldr r3, [r3, #0] + 86ce: 051b lsls r3, r3, #20 + 86d0: d5e3 bpl.n 869a + 86d2: f640 20b8 movw r0, #2744 ; 0xab8 + 86d6: f24f 349d movw r4, #62365 ; 0xf39d + 86da: 6833 ldr r3, [r6, #0] + 86dc: 4639 mov r1, r7 + 86de: f2c0 0400 movt r4, #0 + 86e2: 4632 mov r2, r6 + 86e4: f2c0 0004 movt r0, #4 + 86e8: 47a0 blx r4 + 86ea: e7d6 b.n 869a + 86ec: f240 3310 movw r3, #784 ; 0x310 + 86f0: f2c1 0300 movt r3, #4096 ; 0x1000 + 86f4: 681b ldr r3, [r3, #0] + 86f6: 0519 lsls r1, r3, #20 + 86f8: d5be bpl.n 8678 + 86fa: f640 2080 movw r0, #2688 ; 0xa80 + 86fe: f24f 339d movw r3, #62365 ; 0xf39d + 8702: 4639 mov r1, r7 + 8704: f2c0 0300 movt r3, #0 + 8708: 4642 mov r2, r8 + 870a: f2c0 0004 movt r0, #4 + 870e: 4798 blx r3 + 8710: e7b2 b.n 8678 + 8712: bf00 nop + +00008714 : + 8714: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + 8718: f240 3450 movw r4, #848 ; 0x350 + 871c: f2c1 0400 movt r4, #4096 ; 0x1000 + 8720: 6823 ldr r3, [r4, #0] + 8722: 4605 mov r5, r0 + 8724: 07df lsls r7, r3, #31 + 8726: d425 bmi.n 8774 + 8728: f895 7084 ldrb.w r7, [r5, #132] ; 0x84 + 872c: f895 808b ldrb.w r8, [r5, #139] ; 0x8b + 8730: f507 1680 add.w r6, r7, #1048576 ; 0x100000 + 8734: f506 7684 add.w r6, r6, #264 ; 0x108 + 8738: 02b6 lsls r6, r6, #10 + 873a: 6832 ldr r2, [r6, #0] + 873c: f008 0801 and.w r8, r8, #1 + 8740: f022 0240 bic.w r2, r2, #64 ; 0x40 + 8744: 0758 lsls r0, r3, #29 + 8746: ea42 1888 orr.w r8, r2, r8, lsl #6 + 874a: d439 bmi.n 87c0 + 874c: f647 63f9 movw r3, #32505 ; 0x7ef9 + 8750: 4628 mov r0, r5 + 8752: f2c0 0300 movt r3, #0 + 8756: 4798 blx r3 + 8758: f647 6345 movw r3, #32325 ; 0x7e45 + 875c: f8c6 8000 str.w r8, [r6] + 8760: f2c0 0300 movt r3, #0 + 8764: 4628 mov r0, r5 + 8766: 4798 blx r3 + 8768: 6823 ldr r3, [r4, #0] + 876a: 075a lsls r2, r3, #29 + 876c: d414 bmi.n 8798 + 876e: 2000 movs r0, #0 + 8770: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 8774: f240 3210 movw r2, #784 ; 0x310 + 8778: f2c1 0200 movt r2, #4096 ; 0x1000 + 877c: 6812 ldr r2, [r2, #0] + 877e: 0516 lsls r6, r2, #20 + 8780: d5d2 bpl.n 8728 + 8782: f640 20f0 movw r0, #2800 ; 0xaf0 + 8786: f24f 339d movw r3, #62365 ; 0xf39d + 878a: f2c0 0004 movt r0, #4 + 878e: f2c0 0300 movt r3, #0 + 8792: 4798 blx r3 + 8794: 6823 ldr r3, [r4, #0] + 8796: e7c7 b.n 8728 + 8798: f240 3310 movw r3, #784 ; 0x310 + 879c: f2c1 0300 movt r3, #4096 ; 0x1000 + 87a0: 681b ldr r3, [r3, #0] + 87a2: 051b lsls r3, r3, #20 + 87a4: d5e3 bpl.n 876e + 87a6: f640 20b8 movw r0, #2744 ; 0xab8 + 87aa: f24f 349d movw r4, #62365 ; 0xf39d + 87ae: 6833 ldr r3, [r6, #0] + 87b0: 4639 mov r1, r7 + 87b2: f2c0 0400 movt r4, #0 + 87b6: 4632 mov r2, r6 + 87b8: f2c0 0004 movt r0, #4 + 87bc: 47a0 blx r4 + 87be: e7d6 b.n 876e + 87c0: f240 3310 movw r3, #784 ; 0x310 + 87c4: f2c1 0300 movt r3, #4096 ; 0x1000 + 87c8: 681b ldr r3, [r3, #0] + 87ca: 0519 lsls r1, r3, #20 + 87cc: d5be bpl.n 874c + 87ce: f640 3028 movw r0, #2856 ; 0xb28 + 87d2: f24f 339d movw r3, #62365 ; 0xf39d + 87d6: 4639 mov r1, r7 + 87d8: f2c0 0300 movt r3, #0 + 87dc: 4642 mov r2, r8 + 87de: f2c0 0004 movt r0, #4 + 87e2: 4798 blx r3 + 87e4: e7b2 b.n 874c + 87e6: bf00 nop + +000087e8 : + 87e8: b570 push {r4, r5, r6, lr} + 87ea: f240 3450 movw r4, #848 ; 0x350 + 87ee: f2c1 0400 movt r4, #4096 ; 0x1000 + 87f2: 6823 ldr r3, [r4, #0] + 87f4: 4606 mov r6, r0 + 87f6: 07d8 lsls r0, r3, #31 + 87f8: 460d mov r5, r1 + 87fa: d40c bmi.n 8816 + 87fc: 045a lsls r2, r3, #17 + 87fe: f896 4084 ldrb.w r4, [r6, #132] ; 0x84 + 8802: d41a bmi.n 883a + 8804: f504 1480 add.w r4, r4, #1048576 ; 0x100000 + 8808: f504 7484 add.w r4, r4, #264 ; 0x108 + 880c: 02a4 lsls r4, r4, #10 + 880e: b2ad uxth r5, r5 + 8810: 6625 str r5, [r4, #96] ; 0x60 + 8812: 2000 movs r0, #0 + 8814: bd70 pop {r4, r5, r6, pc} + 8816: f240 3210 movw r2, #784 ; 0x310 + 881a: f2c1 0200 movt r2, #4096 ; 0x1000 + 881e: 6812 ldr r2, [r2, #0] + 8820: 0511 lsls r1, r2, #20 + 8822: d5eb bpl.n 87fc + 8824: f640 305c movw r0, #2908 ; 0xb5c + 8828: f24f 339d movw r3, #62365 ; 0xf39d + 882c: f2c0 0004 movt r0, #4 + 8830: f2c0 0300 movt r3, #0 + 8834: 4798 blx r3 + 8836: 6823 ldr r3, [r4, #0] + 8838: e7e0 b.n 87fc + 883a: f240 3310 movw r3, #784 ; 0x310 + 883e: f2c1 0300 movt r3, #4096 ; 0x1000 + 8842: 681b ldr r3, [r3, #0] + 8844: 051b lsls r3, r3, #20 + 8846: d5dd bpl.n 8804 + 8848: f640 308c movw r0, #2956 ; 0xb8c + 884c: f24f 339d movw r3, #62365 ; 0xf39d + 8850: 4621 mov r1, r4 + 8852: f2c0 0300 movt r3, #0 + 8856: 462a mov r2, r5 + 8858: f2c0 0004 movt r0, #4 + 885c: 4798 blx r3 + 885e: e7d1 b.n 8804 + +00008860 : + 8860: f240 3350 movw r3, #848 ; 0x350 + 8864: f2c1 0300 movt r3, #4096 ; 0x1000 + 8868: b530 push {r4, r5, lr} + 886a: 681b ldr r3, [r3, #0] + 886c: b083 sub sp, #12 + 886e: 07da lsls r2, r3, #31 + 8870: 4604 mov r4, r0 + 8872: d415 bmi.n 88a0 + 8874: f894 0084 ldrb.w r0, [r4, #132] ; 0x84 + 8878: b110 cbz r0, 8880 + 887a: 2003 movs r0, #3 + 887c: b003 add sp, #12 + 887e: bd30 pop {r4, r5, pc} + 8880: f44f 7342 mov.w r3, #776 ; 0x308 + 8884: f2c4 0300 movt r3, #16384 ; 0x4000 + 8888: 681d ldr r5, [r3, #0] + 888a: 424a negs r2, r1 + 888c: f425 7580 bic.w r5, r5, #256 ; 0x100 + 8890: f402 7280 and.w r2, r2, #256 ; 0x100 + 8894: 432a orrs r2, r5 + 8896: 601a str r2, [r3, #0] + 8898: f884 108a strb.w r1, [r4, #138] ; 0x8a + 889c: b003 add sp, #12 + 889e: bd30 pop {r4, r5, pc} + 88a0: f240 3310 movw r3, #784 ; 0x310 + 88a4: f2c1 0300 movt r3, #4096 ; 0x1000 + 88a8: 681b ldr r3, [r3, #0] + 88aa: 051b lsls r3, r3, #20 + 88ac: d5e2 bpl.n 8874 + 88ae: f640 30b0 movw r0, #2992 ; 0xbb0 + 88b2: f24f 339d movw r3, #62365 ; 0xf39d + 88b6: 9101 str r1, [sp, #4] + 88b8: f2c0 0004 movt r0, #4 + 88bc: f2c0 0300 movt r3, #0 + 88c0: 4798 blx r3 + 88c2: 9901 ldr r1, [sp, #4] + 88c4: e7d6 b.n 8874 + 88c6: bf00 nop + +000088c8 : + 88c8: b538 push {r3, r4, r5, lr} + 88ca: f240 3450 movw r4, #848 ; 0x350 + 88ce: f2c1 0400 movt r4, #4096 ; 0x1000 + 88d2: 6823 ldr r3, [r4, #0] + 88d4: 4605 mov r5, r0 + 88d6: 07da lsls r2, r3, #31 + 88d8: d40f bmi.n 88fa + 88da: f895 1084 ldrb.w r1, [r5, #132] ; 0x84 + 88de: 6eea ldr r2, [r5, #108] ; 0x6c + 88e0: f501 1380 add.w r3, r1, #1048576 ; 0x100000 + 88e4: f503 7384 add.w r3, r3, #264 ; 0x108 + 88e8: 029b lsls r3, r3, #10 + 88ea: f002 003f and.w r0, r2, #63 ; 0x3f + 88ee: 61d8 str r0, [r3, #28] + 88f0: 6823 ldr r3, [r4, #0] + 88f2: 04d8 lsls r0, r3, #19 + 88f4: d412 bmi.n 891c + 88f6: 2000 movs r0, #0 + 88f8: bd38 pop {r3, r4, r5, pc} + 88fa: f240 3310 movw r3, #784 ; 0x310 + 88fe: f2c1 0300 movt r3, #4096 ; 0x1000 + 8902: 681b ldr r3, [r3, #0] + 8904: 051b lsls r3, r3, #20 + 8906: d5e8 bpl.n 88da + 8908: f640 30e8 movw r0, #3048 ; 0xbe8 + 890c: f24f 339d movw r3, #62365 ; 0xf39d + 8910: f2c0 0004 movt r0, #4 + 8914: f2c0 0300 movt r3, #0 + 8918: 4798 blx r3 + 891a: e7de b.n 88da + 891c: f240 3310 movw r3, #784 ; 0x310 + 8920: f2c1 0300 movt r3, #4096 ; 0x1000 + 8924: 681b ldr r3, [r3, #0] + 8926: 051b lsls r3, r3, #20 + 8928: d5e5 bpl.n 88f6 + 892a: f640 402c movw r0, #3116 ; 0xc2c + 892e: f24f 339d movw r3, #62365 ; 0xf39d + 8932: f2c0 0004 movt r0, #4 + 8936: f2c0 0300 movt r3, #0 + 893a: 4798 blx r3 + 893c: e7db b.n 88f6 + 893e: bf00 nop + +00008940 : + 8940: b538 push {r3, r4, r5, lr} + 8942: f240 3450 movw r4, #848 ; 0x350 + 8946: f2c1 0400 movt r4, #4096 ; 0x1000 + 894a: 6823 ldr r3, [r4, #0] + 894c: 4605 mov r5, r0 + 894e: 07da lsls r2, r3, #31 + 8950: d40f bmi.n 8972 + 8952: f895 1084 ldrb.w r1, [r5, #132] ; 0x84 + 8956: 6f6a ldr r2, [r5, #116] ; 0x74 + 8958: f501 1380 add.w r3, r1, #1048576 ; 0x100000 + 895c: f503 7384 add.w r3, r3, #264 ; 0x108 + 8960: 029b lsls r3, r3, #10 + 8962: f002 003f and.w r0, r2, #63 ; 0x3f + 8966: 6198 str r0, [r3, #24] + 8968: 6823 ldr r3, [r4, #0] + 896a: 04d8 lsls r0, r3, #19 + 896c: d412 bmi.n 8994 + 896e: 2000 movs r0, #0 + 8970: bd38 pop {r3, r4, r5, pc} + 8972: f240 3310 movw r3, #784 ; 0x310 + 8976: f2c1 0300 movt r3, #4096 ; 0x1000 + 897a: 681b ldr r3, [r3, #0] + 897c: 051b lsls r3, r3, #20 + 897e: d5e8 bpl.n 8952 + 8980: f640 4064 movw r0, #3172 ; 0xc64 + 8984: f24f 339d movw r3, #62365 ; 0xf39d + 8988: f2c0 0004 movt r0, #4 + 898c: f2c0 0300 movt r3, #0 + 8990: 4798 blx r3 + 8992: e7de b.n 8952 + 8994: f240 3310 movw r3, #784 ; 0x310 + 8998: f2c1 0300 movt r3, #4096 ; 0x1000 + 899c: 681b ldr r3, [r3, #0] + 899e: 051b lsls r3, r3, #20 + 89a0: d5e5 bpl.n 896e + 89a2: f640 40a8 movw r0, #3240 ; 0xca8 + 89a6: f24f 339d movw r3, #62365 ; 0xf39d + 89aa: f2c0 0004 movt r0, #4 + 89ae: f2c0 0300 movt r3, #0 + 89b2: 4798 blx r3 + 89b4: e7db b.n 896e + 89b6: bf00 nop + +000089b8 : + 89b8: b538 push {r3, r4, r5, lr} + 89ba: f240 3450 movw r4, #848 ; 0x350 + 89be: f2c1 0400 movt r4, #4096 ; 0x1000 + 89c2: 6823 ldr r3, [r4, #0] + 89c4: 4605 mov r5, r0 + 89c6: 07d8 lsls r0, r3, #31 + 89c8: d40b bmi.n 89e2 + 89ca: f895 1084 ldrb.w r1, [r5, #132] ; 0x84 + 89ce: f501 1280 add.w r2, r1, #1048576 ; 0x100000 + 89d2: f502 7284 add.w r2, r2, #264 ; 0x108 + 89d6: 0292 lsls r2, r2, #10 + 89d8: 6e14 ldr r4, [r2, #96] ; 0x60 + 89da: 049a lsls r2, r3, #18 + 89dc: d413 bmi.n 8a06 + 89de: 4620 mov r0, r4 + 89e0: bd38 pop {r3, r4, r5, pc} + 89e2: f240 3210 movw r2, #784 ; 0x310 + 89e6: f2c1 0200 movt r2, #4096 ; 0x1000 + 89ea: 6812 ldr r2, [r2, #0] + 89ec: 0511 lsls r1, r2, #20 + 89ee: d5ec bpl.n 89ca + 89f0: f640 40e0 movw r0, #3296 ; 0xce0 + 89f4: f24f 339d movw r3, #62365 ; 0xf39d + 89f8: f2c0 0004 movt r0, #4 + 89fc: f2c0 0300 movt r3, #0 + 8a00: 4798 blx r3 + 8a02: 6823 ldr r3, [r4, #0] + 8a04: e7e1 b.n 89ca + 8a06: f240 3310 movw r3, #784 ; 0x310 + 8a0a: f2c1 0300 movt r3, #4096 ; 0x1000 + 8a0e: 681b ldr r3, [r3, #0] + 8a10: 051b lsls r3, r3, #20 + 8a12: d5e4 bpl.n 89de + 8a14: f640 5010 movw r0, #3344 ; 0xd10 + 8a18: f24f 339d movw r3, #62365 ; 0xf39d + 8a1c: 4622 mov r2, r4 + 8a1e: f2c0 0300 movt r3, #0 + 8a22: f2c0 0004 movt r0, #4 + 8a26: 4798 blx r3 + 8a28: e7d9 b.n 89de + 8a2a: bf00 nop + +00008a2c : + 8a2c: b538 push {r3, r4, r5, lr} + 8a2e: f240 3450 movw r4, #848 ; 0x350 + 8a32: f2c1 0400 movt r4, #4096 ; 0x1000 + 8a36: 6823 ldr r3, [r4, #0] + 8a38: 4605 mov r5, r0 + 8a3a: 07d8 lsls r0, r3, #31 + 8a3c: d40d bmi.n 8a5a + 8a3e: f895 1084 ldrb.w r1, [r5, #132] ; 0x84 + 8a42: f501 1280 add.w r2, r1, #1048576 ; 0x100000 + 8a46: f502 7284 add.w r2, r2, #264 ; 0x108 + 8a4a: 0292 lsls r2, r2, #10 + 8a4c: 6a54 ldr r4, [r2, #36] ; 0x24 + 8a4e: 04da lsls r2, r3, #19 + 8a50: f004 047f and.w r4, r4, #127 ; 0x7f + 8a54: d413 bmi.n 8a7e + 8a56: 4620 mov r0, r4 + 8a58: bd38 pop {r3, r4, r5, pc} + 8a5a: f240 3210 movw r2, #784 ; 0x310 + 8a5e: f2c1 0200 movt r2, #4096 ; 0x1000 + 8a62: 6812 ldr r2, [r2, #0] + 8a64: 0511 lsls r1, r2, #20 + 8a66: d5ea bpl.n 8a3e + 8a68: f640 5030 movw r0, #3376 ; 0xd30 + 8a6c: f24f 339d movw r3, #62365 ; 0xf39d + 8a70: f2c0 0004 movt r0, #4 + 8a74: f2c0 0300 movt r3, #0 + 8a78: 4798 blx r3 + 8a7a: 6823 ldr r3, [r4, #0] + 8a7c: e7df b.n 8a3e + 8a7e: f240 3310 movw r3, #784 ; 0x310 + 8a82: f2c1 0300 movt r3, #4096 ; 0x1000 + 8a86: 681b ldr r3, [r3, #0] + 8a88: 051b lsls r3, r3, #20 + 8a8a: d5e4 bpl.n 8a56 + 8a8c: f640 5068 movw r0, #3432 ; 0xd68 + 8a90: f24f 339d movw r3, #62365 ; 0xf39d + 8a94: 4622 mov r2, r4 + 8a96: f2c0 0300 movt r3, #0 + 8a9a: f2c0 0004 movt r0, #4 + 8a9e: 4798 blx r3 + 8aa0: e7d9 b.n 8a56 + 8aa2: bf00 nop + +00008aa4 : + 8aa4: b538 push {r3, r4, r5, lr} + 8aa6: f240 3450 movw r4, #848 ; 0x350 + 8aaa: f2c1 0400 movt r4, #4096 ; 0x1000 + 8aae: 6823 ldr r3, [r4, #0] + 8ab0: 4605 mov r5, r0 + 8ab2: 07d8 lsls r0, r3, #31 + 8ab4: d40d bmi.n 8ad2 + 8ab6: f895 1084 ldrb.w r1, [r5, #132] ; 0x84 + 8aba: f501 1280 add.w r2, r1, #1048576 ; 0x100000 + 8abe: f502 7284 add.w r2, r2, #264 ; 0x108 + 8ac2: 0292 lsls r2, r2, #10 + 8ac4: 6a14 ldr r4, [r2, #32] + 8ac6: 04da lsls r2, r3, #19 + 8ac8: f004 047f and.w r4, r4, #127 ; 0x7f + 8acc: d413 bmi.n 8af6 + 8ace: 4620 mov r0, r4 + 8ad0: bd38 pop {r3, r4, r5, pc} + 8ad2: f240 3210 movw r2, #784 ; 0x310 + 8ad6: f2c1 0200 movt r2, #4096 ; 0x1000 + 8ada: 6812 ldr r2, [r2, #0] + 8adc: 0511 lsls r1, r2, #20 + 8ade: d5ea bpl.n 8ab6 + 8ae0: f640 5094 movw r0, #3476 ; 0xd94 + 8ae4: f24f 339d movw r3, #62365 ; 0xf39d + 8ae8: f2c0 0004 movt r0, #4 + 8aec: f2c0 0300 movt r3, #0 + 8af0: 4798 blx r3 + 8af2: 6823 ldr r3, [r4, #0] + 8af4: e7df b.n 8ab6 + 8af6: f240 3310 movw r3, #784 ; 0x310 + 8afa: f2c1 0300 movt r3, #4096 ; 0x1000 + 8afe: 681b ldr r3, [r3, #0] + 8b00: 051b lsls r3, r3, #20 + 8b02: d5e4 bpl.n 8ace + 8b04: f640 50cc movw r0, #3532 ; 0xdcc + 8b08: f24f 339d movw r3, #62365 ; 0xf39d + 8b0c: 4622 mov r2, r4 + 8b0e: f2c0 0300 movt r3, #0 + 8b12: f2c0 0004 movt r0, #4 + 8b16: 4798 blx r3 + 8b18: e7d9 b.n 8ace + 8b1a: bf00 nop + +00008b1c : + 8b1c: b538 push {r3, r4, r5, lr} + 8b1e: f240 3450 movw r4, #848 ; 0x350 + 8b22: f2c1 0400 movt r4, #4096 ; 0x1000 + 8b26: 6823 ldr r3, [r4, #0] + 8b28: 4605 mov r5, r0 + 8b2a: 07d8 lsls r0, r3, #31 + 8b2c: d40b bmi.n 8b46 + 8b2e: f895 1084 ldrb.w r1, [r5, #132] ; 0x84 + 8b32: f501 1280 add.w r2, r1, #1048576 ; 0x100000 + 8b36: f502 7284 add.w r2, r2, #264 ; 0x108 + 8b3a: 0292 lsls r2, r2, #10 + 8b3c: 6a94 ldr r4, [r2, #40] ; 0x28 + 8b3e: 051a lsls r2, r3, #20 + 8b40: d413 bmi.n 8b6a + 8b42: 4620 mov r0, r4 + 8b44: bd38 pop {r3, r4, r5, pc} + 8b46: f240 3210 movw r2, #784 ; 0x310 + 8b4a: f2c1 0200 movt r2, #4096 ; 0x1000 + 8b4e: 6812 ldr r2, [r2, #0] + 8b50: 0511 lsls r1, r2, #20 + 8b52: d5ec bpl.n 8b2e + 8b54: f640 50f8 movw r0, #3576 ; 0xdf8 + 8b58: f24f 339d movw r3, #62365 ; 0xf39d + 8b5c: f2c0 0004 movt r0, #4 + 8b60: f2c0 0300 movt r3, #0 + 8b64: 4798 blx r3 + 8b66: 6823 ldr r3, [r4, #0] + 8b68: e7e1 b.n 8b2e + 8b6a: f240 3310 movw r3, #784 ; 0x310 + 8b6e: f2c1 0300 movt r3, #4096 ; 0x1000 + 8b72: 681b ldr r3, [r3, #0] + 8b74: 051b lsls r3, r3, #20 + 8b76: d5e4 bpl.n 8b42 + 8b78: f640 602c movw r0, #3628 ; 0xe2c + 8b7c: f24f 339d movw r3, #62365 ; 0xf39d + 8b80: 4622 mov r2, r4 + 8b82: f2c0 0300 movt r3, #0 + 8b86: f2c0 0004 movt r0, #4 + 8b8a: 4798 blx r3 + 8b8c: e7d9 b.n 8b42 + 8b8e: bf00 nop + +00008b90 : + 8b90: b538 push {r3, r4, r5, lr} + 8b92: f240 3450 movw r4, #848 ; 0x350 + 8b96: f2c1 0400 movt r4, #4096 ; 0x1000 + 8b9a: 6823 ldr r3, [r4, #0] + 8b9c: 4605 mov r5, r0 + 8b9e: 07d8 lsls r0, r3, #31 + 8ba0: d40c bmi.n 8bbc + 8ba2: f648 331d movw r3, #35613 ; 0x8b1d + 8ba6: 4628 mov r0, r5 + 8ba8: f2c0 0300 movt r3, #0 + 8bac: 4798 blx r3 + 8bae: 6823 ldr r3, [r4, #0] + 8bb0: f3c0 0440 ubfx r4, r0, #1, #1 + 8bb4: 051a lsls r2, r3, #20 + 8bb6: d412 bmi.n 8bde + 8bb8: 4620 mov r0, r4 + 8bba: bd38 pop {r3, r4, r5, pc} + 8bbc: f240 3310 movw r3, #784 ; 0x310 + 8bc0: f2c1 0300 movt r3, #4096 ; 0x1000 + 8bc4: 681b ldr r3, [r3, #0] + 8bc6: 0519 lsls r1, r3, #20 + 8bc8: d5eb bpl.n 8ba2 + 8bca: f640 6050 movw r0, #3664 ; 0xe50 + 8bce: f24f 339d movw r3, #62365 ; 0xf39d + 8bd2: f2c0 0004 movt r0, #4 + 8bd6: f2c0 0300 movt r3, #0 + 8bda: 4798 blx r3 + 8bdc: e7e1 b.n 8ba2 + 8bde: f240 3310 movw r3, #784 ; 0x310 + 8be2: f2c1 0300 movt r3, #4096 ; 0x1000 + 8be6: 681b ldr r3, [r3, #0] + 8be8: 051b lsls r3, r3, #20 + 8bea: d5e5 bpl.n 8bb8 + 8bec: f640 6084 movw r0, #3716 ; 0xe84 + 8bf0: f24f 339d movw r3, #62365 ; 0xf39d + 8bf4: f895 1084 ldrb.w r1, [r5, #132] ; 0x84 + 8bf8: f2c0 0300 movt r3, #0 + 8bfc: 4622 mov r2, r4 + 8bfe: f2c0 0004 movt r0, #4 + 8c02: 4798 blx r3 + 8c04: e7d8 b.n 8bb8 + 8c06: bf00 nop + +00008c08 : + 8c08: b538 push {r3, r4, r5, lr} + 8c0a: f240 3450 movw r4, #848 ; 0x350 + 8c0e: f2c1 0400 movt r4, #4096 ; 0x1000 + 8c12: 6823 ldr r3, [r4, #0] + 8c14: 4605 mov r5, r0 + 8c16: 07d8 lsls r0, r3, #31 + 8c18: d40c bmi.n 8c34 + 8c1a: f648 331d movw r3, #35613 ; 0x8b1d + 8c1e: 4628 mov r0, r5 + 8c20: f2c0 0300 movt r3, #0 + 8c24: 4798 blx r3 + 8c26: 6823 ldr r3, [r4, #0] + 8c28: f3c0 04c0 ubfx r4, r0, #3, #1 + 8c2c: 051a lsls r2, r3, #20 + 8c2e: d412 bmi.n 8c56 + 8c30: 4620 mov r0, r4 + 8c32: bd38 pop {r3, r4, r5, pc} + 8c34: f240 3310 movw r3, #784 ; 0x310 + 8c38: f2c1 0300 movt r3, #4096 ; 0x1000 + 8c3c: 681b ldr r3, [r3, #0] + 8c3e: 0519 lsls r1, r3, #20 + 8c40: d5eb bpl.n 8c1a + 8c42: f640 60a8 movw r0, #3752 ; 0xea8 + 8c46: f24f 339d movw r3, #62365 ; 0xf39d + 8c4a: f2c0 0004 movt r0, #4 + 8c4e: f2c0 0300 movt r3, #0 + 8c52: 4798 blx r3 + 8c54: e7e1 b.n 8c1a + 8c56: f240 3310 movw r3, #784 ; 0x310 + 8c5a: f2c1 0300 movt r3, #4096 ; 0x1000 + 8c5e: 681b ldr r3, [r3, #0] + 8c60: 051b lsls r3, r3, #20 + 8c62: d5e5 bpl.n 8c30 + 8c64: f640 60dc movw r0, #3804 ; 0xedc + 8c68: f24f 339d movw r3, #62365 ; 0xf39d + 8c6c: f895 1084 ldrb.w r1, [r5, #132] ; 0x84 + 8c70: f2c0 0300 movt r3, #0 + 8c74: 4622 mov r2, r4 + 8c76: f2c0 0004 movt r0, #4 + 8c7a: 4798 blx r3 + 8c7c: e7d8 b.n 8c30 + 8c7e: bf00 nop + +00008c80 : + 8c80: b538 push {r3, r4, r5, lr} + 8c82: f240 3450 movw r4, #848 ; 0x350 + 8c86: f2c1 0400 movt r4, #4096 ; 0x1000 + 8c8a: 6823 ldr r3, [r4, #0] + 8c8c: 4605 mov r5, r0 + 8c8e: 07d8 lsls r0, r3, #31 + 8c90: d40c bmi.n 8cac + 8c92: f648 331d movw r3, #35613 ; 0x8b1d + 8c96: 4628 mov r0, r5 + 8c98: f2c0 0300 movt r3, #0 + 8c9c: 4798 blx r3 + 8c9e: 6823 ldr r3, [r4, #0] + 8ca0: f000 0401 and.w r4, r0, #1 + 8ca4: 051a lsls r2, r3, #20 + 8ca6: d412 bmi.n 8cce + 8ca8: 4620 mov r0, r4 + 8caa: bd38 pop {r3, r4, r5, pc} + 8cac: f240 3310 movw r3, #784 ; 0x310 + 8cb0: f2c1 0300 movt r3, #4096 ; 0x1000 + 8cb4: 681b ldr r3, [r3, #0] + 8cb6: 0519 lsls r1, r3, #20 + 8cb8: d5eb bpl.n 8c92 + 8cba: f640 7000 movw r0, #3840 ; 0xf00 + 8cbe: f24f 339d movw r3, #62365 ; 0xf39d + 8cc2: f2c0 0004 movt r0, #4 + 8cc6: f2c0 0300 movt r3, #0 + 8cca: 4798 blx r3 + 8ccc: e7e1 b.n 8c92 + 8cce: f240 3310 movw r3, #784 ; 0x310 + 8cd2: f2c1 0300 movt r3, #4096 ; 0x1000 + 8cd6: 681b ldr r3, [r3, #0] + 8cd8: 051b lsls r3, r3, #20 + 8cda: d5e5 bpl.n 8ca8 + 8cdc: f640 7030 movw r0, #3888 ; 0xf30 + 8ce0: f24f 339d movw r3, #62365 ; 0xf39d + 8ce4: f895 1084 ldrb.w r1, [r5, #132] ; 0x84 + 8ce8: f2c0 0300 movt r3, #0 + 8cec: 4622 mov r2, r4 + 8cee: f2c0 0004 movt r0, #4 + 8cf2: 4798 blx r3 + 8cf4: e7d8 b.n 8ca8 + 8cf6: bf00 nop + +00008cf8 : + 8cf8: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 8cfc: f240 3450 movw r4, #848 ; 0x350 + 8d00: f2c1 0400 movt r4, #4096 ; 0x1000 + 8d04: 6823 ldr r3, [r4, #0] + 8d06: 4617 mov r7, r2 + 8d08: 07da lsls r2, r3, #31 + 8d0a: b083 sub sp, #12 + 8d0c: 4605 mov r5, r0 + 8d0e: 4688 mov r8, r1 + 8d10: d47b bmi.n 8e0a + 8d12: f648 4681 movw r6, #35969 ; 0x8c81 + 8d16: 4628 mov r0, r5 + 8d18: f2c0 0600 movt r6, #0 + 8d1c: f895 9084 ldrb.w r9, [r5, #132] ; 0x84 + 8d20: 47b0 blx r6 + 8d22: b130 cbz r0, 8d32 + 8d24: 6823 ldr r3, [r4, #0] + 8d26: 059e lsls r6, r3, #22 + 8d28: d45c bmi.n 8de4 + 8d2a: 2001 movs r0, #1 + 8d2c: b003 add sp, #12 + 8d2e: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 8d32: 2f00 cmp r7, #0 + 8d34: bf18 it ne + 8d36: f1b8 0f00 cmpne.w r8, #0 + 8d3a: d106 bne.n 8d4a + 8d3c: 6823 ldr r3, [r4, #0] + 8d3e: 059c lsls r4, r3, #22 + 8d40: d475 bmi.n 8e2e + 8d42: 2003 movs r0, #3 + 8d44: b003 add sp, #12 + 8d46: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 8d4a: f509 1380 add.w r3, r9, #1048576 ; 0x100000 + 8d4e: f503 7384 add.w r3, r3, #264 ; 0x108 + 8d52: 029b lsls r3, r3, #10 + 8d54: 69de ldr r6, [r3, #28] + 8d56: 3601 adds r6, #1 + 8d58: 42b7 cmp r7, r6 + 8d5a: d232 bcs.n 8dc2 + 8d5c: f240 3650 movw r6, #848 ; 0x350 + 8d60: 6823 ldr r3, [r4, #0] + 8d62: f2c1 0600 movt r6, #4096 ; 0x1000 + 8d66: 059b lsls r3, r3, #22 + 8d68: f100 8098 bmi.w 8e9c + 8d6c: f647 63f9 movw r3, #32505 ; 0x7ef9 + 8d70: 4628 mov r0, r5 + 8d72: f2c0 0300 movt r3, #0 + 8d76: 4798 blx r3 + 8d78: f648 03c9 movw r3, #35017 ; 0x88c9 + 8d7c: 2600 movs r6, #0 + 8d7e: f2c0 0300 movt r3, #0 + 8d82: 66ee str r6, [r5, #108] ; 0x6c + 8d84: 4628 mov r0, r5 + 8d86: 4798 blx r3 + 8d88: f647 6345 movw r3, #32325 ; 0x7e45 + 8d8c: 4628 mov r0, r5 + 8d8e: f2c0 0300 movt r3, #0 + 8d92: 4798 blx r3 + 8d94: 6823 ldr r3, [r4, #0] + 8d96: f403 7300 and.w r3, r3, #512 ; 0x200 + 8d9a: 1bbf subs r7, r7, r6 + 8d9c: 666f str r7, [r5, #100] ; 0x64 + 8d9e: 66ae str r6, [r5, #104] ; 0x68 + 8da0: f8c5 8048 str.w r8, [r5, #72] ; 0x48 + 8da4: 2b00 cmp r3, #0 + 8da6: d157 bne.n 8e58 + 8da8: f248 5321 movw r3, #34081 ; 0x8521 + 8dac: 221c movs r2, #28 + 8dae: f2c0 0300 movt r3, #0 + 8db2: f885 2085 strb.w r2, [r5, #133] ; 0x85 + 8db6: 4628 mov r0, r5 + 8db8: 4798 blx r3 + 8dba: 2000 movs r0, #0 + 8dbc: b003 add sp, #12 + 8dbe: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 8dc2: fbb7 f2f6 udiv r2, r7, r6 + 8dc6: f240 3a50 movw sl, #848 ; 0x350 + 8dca: 6823 ldr r3, [r4, #0] + 8dcc: fb06 7612 mls r6, r6, r2, r7 + 8dd0: 0599 lsls r1, r3, #22 + 8dd2: f2c1 0a00 movt sl, #4096 ; 0x1000 + 8dd6: d454 bmi.n 8e82 + 8dd8: 1bbf subs r7, r7, r6 + 8dda: 666f str r7, [r5, #100] ; 0x64 + 8ddc: 66ae str r6, [r5, #104] ; 0x68 + 8dde: f8c5 8048 str.w r8, [r5, #72] ; 0x48 + 8de2: e7e1 b.n 8da8 + 8de4: f240 3310 movw r3, #784 ; 0x310 + 8de8: f2c1 0300 movt r3, #4096 ; 0x1000 + 8dec: 681b ldr r3, [r3, #0] + 8dee: 051d lsls r5, r3, #20 + 8df0: d59b bpl.n 8d2a + 8df2: f640 7088 movw r0, #3976 ; 0xf88 + 8df6: f24f 339d movw r3, #62365 ; 0xf39d + 8dfa: 4649 mov r1, r9 + 8dfc: f2c0 0004 movt r0, #4 + 8e00: f2c0 0300 movt r3, #0 + 8e04: 4798 blx r3 + 8e06: 2001 movs r0, #1 + 8e08: e790 b.n 8d2c + 8e0a: f240 3310 movw r3, #784 ; 0x310 + 8e0e: f2c1 0300 movt r3, #4096 ; 0x1000 + 8e12: 681b ldr r3, [r3, #0] + 8e14: 051b lsls r3, r3, #20 + 8e16: f57f af7c bpl.w 8d12 + 8e1a: f640 7050 movw r0, #3920 ; 0xf50 + 8e1e: f24f 339d movw r3, #62365 ; 0xf39d + 8e22: f2c0 0004 movt r0, #4 + 8e26: f2c0 0300 movt r3, #0 + 8e2a: 4798 blx r3 + 8e2c: e771 b.n 8d12 + 8e2e: f240 3310 movw r3, #784 ; 0x310 + 8e32: f2c1 0300 movt r3, #4096 ; 0x1000 + 8e36: 681b ldr r3, [r3, #0] + 8e38: 0518 lsls r0, r3, #20 + 8e3a: d582 bpl.n 8d42 + 8e3c: f640 70a8 movw r0, #4008 ; 0xfa8 + 8e40: f24f 349d movw r4, #62365 ; 0xf39d + 8e44: 4649 mov r1, r9 + 8e46: 4642 mov r2, r8 + 8e48: 463b mov r3, r7 + 8e4a: f2c0 0004 movt r0, #4 + 8e4e: f2c0 0400 movt r4, #0 + 8e52: 47a0 blx r4 + 8e54: 2003 movs r0, #3 + 8e56: e769 b.n 8d2c + 8e58: f240 3310 movw r3, #784 ; 0x310 + 8e5c: f2c1 0300 movt r3, #4096 ; 0x1000 + 8e60: 681b ldr r3, [r3, #0] + 8e62: 051b lsls r3, r3, #20 + 8e64: d5a0 bpl.n 8da8 + 8e66: f241 00a0 movw r0, #4256 ; 0x10a0 + 8e6a: f24f 349d movw r4, #62365 ; 0xf39d + 8e6e: 9600 str r6, [sp, #0] + 8e70: 4649 mov r1, r9 + 8e72: 4642 mov r2, r8 + 8e74: 463b mov r3, r7 + 8e76: f2c0 0400 movt r4, #0 + 8e7a: f2c0 0004 movt r0, #4 + 8e7e: 47a0 blx r4 + 8e80: e792 b.n 8da8 + 8e82: f240 3310 movw r3, #784 ; 0x310 + 8e86: f2c1 0300 movt r3, #4096 ; 0x1000 + 8e8a: 681a ldr r2, [r3, #0] + 8e8c: 0512 lsls r2, r2, #20 + 8e8e: d426 bmi.n 8ede + 8e90: 1bbf subs r7, r7, r6 + 8e92: 666f str r7, [r5, #100] ; 0x64 + 8e94: 66ae str r6, [r5, #104] ; 0x68 + 8e96: f8c5 8048 str.w r8, [r5, #72] ; 0x48 + 8e9a: e7e1 b.n 8e60 + 8e9c: f240 3b10 movw fp, #784 ; 0x310 + 8ea0: f2c1 0b00 movt fp, #4096 ; 0x1000 + 8ea4: f8db 3000 ldr.w r3, [fp] + 8ea8: 0518 lsls r0, r3, #20 + 8eaa: f57f af5f bpl.w 8d6c + 8eae: f241 0024 movw r0, #4132 ; 0x1024 + 8eb2: f24f 3a9d movw sl, #62365 ; 0xf39d + 8eb6: f2c0 0004 movt r0, #4 + 8eba: f2c0 0a00 movt sl, #0 + 8ebe: 47d0 blx sl + 8ec0: 6833 ldr r3, [r6, #0] + 8ec2: 059a lsls r2, r3, #22 + 8ec4: f57f af52 bpl.w 8d6c + 8ec8: f8db 3000 ldr.w r3, [fp] + 8ecc: 0519 lsls r1, r3, #20 + 8ece: f57f af4d bpl.w 8d6c + 8ed2: f241 0068 movw r0, #4200 ; 0x1068 + 8ed6: f2c0 0004 movt r0, #4 + 8eda: 47d0 blx sl + 8edc: e746 b.n 8d6c + 8ede: f640 70dc movw r0, #4060 ; 0xfdc + 8ee2: f24f 339d movw r3, #62365 ; 0xf39d + 8ee6: f2c0 0004 movt r0, #4 + 8eea: f2c0 0300 movt r3, #0 + 8eee: 4631 mov r1, r6 + 8ef0: 4798 blx r3 + 8ef2: f8da 3000 ldr.w r3, [sl] + 8ef6: f403 7300 and.w r3, r3, #512 ; 0x200 + 8efa: e74e b.n 8d9a + +00008efc : + 8efc: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} + 8f00: f240 3450 movw r4, #848 ; 0x350 + 8f04: f2c1 0400 movt r4, #4096 ; 0x1000 + 8f08: 6826 ldr r6, [r4, #0] + 8f0a: 4605 mov r5, r0 + 8f0c: 07f3 lsls r3, r6, #31 + 8f0e: 4688 mov r8, r1 + 8f10: 4617 mov r7, r2 + 8f12: d43d bmi.n 8f90 + 8f14: f648 4681 movw r6, #35969 ; 0x8c81 + 8f18: 4628 mov r0, r5 + 8f1a: f2c0 0600 movt r6, #0 + 8f1e: f895 9084 ldrb.w r9, [r5, #132] ; 0x84 + 8f22: 47b0 blx r6 + 8f24: 6823 ldr r3, [r4, #0] + 8f26: b120 cbz r0, 8f32 + 8f28: 055d lsls r5, r3, #21 + 8f2a: d41d bmi.n 8f68 + 8f2c: 2001 movs r0, #1 + 8f2e: e8bd 83f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} + 8f32: 2f00 cmp r7, #0 + 8f34: bf18 it ne + 8f36: f1b8 0f00 cmpne.w r8, #0 + 8f3a: d104 bne.n 8f46 + 8f3c: 0558 lsls r0, r3, #21 + 8f3e: d44c bmi.n 8fda + 8f40: 2003 movs r0, #3 + 8f42: e8bd 83f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} + 8f46: 055a lsls r2, r3, #21 + 8f48: 672f str r7, [r5, #112] ; 0x70 + 8f4a: f8c5 8054 str.w r8, [r5, #84] ; 0x54 + 8f4e: d430 bmi.n 8fb2 + 8f50: f248 5321 movw r3, #34081 ; 0x8521 + 8f54: 2203 movs r2, #3 + 8f56: f2c0 0300 movt r3, #0 + 8f5a: f885 2085 strb.w r2, [r5, #133] ; 0x85 + 8f5e: 4628 mov r0, r5 + 8f60: 4798 blx r3 + 8f62: 2000 movs r0, #0 + 8f64: e8bd 83f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} + 8f68: f240 3310 movw r3, #784 ; 0x310 + 8f6c: f2c1 0300 movt r3, #4096 ; 0x1000 + 8f70: 681b ldr r3, [r3, #0] + 8f72: 051c lsls r4, r3, #20 + 8f74: d5da bpl.n 8f2c + 8f76: f640 7088 movw r0, #3976 ; 0xf88 + 8f7a: f24f 339d movw r3, #62365 ; 0xf39d + 8f7e: 4649 mov r1, r9 + 8f80: f2c0 0300 movt r3, #0 + 8f84: f2c0 0004 movt r0, #4 + 8f88: 4798 blx r3 + 8f8a: 2001 movs r0, #1 + 8f8c: e8bd 83f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} + 8f90: f240 3310 movw r3, #784 ; 0x310 + 8f94: f2c1 0300 movt r3, #4096 ; 0x1000 + 8f98: 681b ldr r3, [r3, #0] + 8f9a: 051e lsls r6, r3, #20 + 8f9c: d5ba bpl.n 8f14 + 8f9e: f241 00e4 movw r0, #4324 ; 0x10e4 + 8fa2: f24f 339d movw r3, #62365 ; 0xf39d + 8fa6: f2c0 0004 movt r0, #4 + 8faa: f2c0 0300 movt r3, #0 + 8fae: 4798 blx r3 + 8fb0: e7b0 b.n 8f14 + 8fb2: f240 3310 movw r3, #784 ; 0x310 + 8fb6: f2c1 0300 movt r3, #4096 ; 0x1000 + 8fba: 681b ldr r3, [r3, #0] + 8fbc: 051b lsls r3, r3, #20 + 8fbe: d5c7 bpl.n 8f50 + 8fc0: f241 101c movw r0, #4380 ; 0x111c + 8fc4: f24f 349d movw r4, #62365 ; 0xf39d + 8fc8: 4649 mov r1, r9 + 8fca: 4642 mov r2, r8 + 8fcc: 463b mov r3, r7 + 8fce: f2c0 0400 movt r4, #0 + 8fd2: f2c0 0004 movt r0, #4 + 8fd6: 47a0 blx r4 + 8fd8: e7ba b.n 8f50 + 8fda: f240 3310 movw r3, #784 ; 0x310 + 8fde: f2c1 0300 movt r3, #4096 ; 0x1000 + 8fe2: 681b ldr r3, [r3, #0] + 8fe4: 0519 lsls r1, r3, #20 + 8fe6: d5ab bpl.n 8f40 + 8fe8: f241 101c movw r0, #4380 ; 0x111c + 8fec: f24f 349d movw r4, #62365 ; 0xf39d + 8ff0: 4649 mov r1, r9 + 8ff2: 4642 mov r2, r8 + 8ff4: 463b mov r3, r7 + 8ff6: f2c0 0400 movt r4, #0 + 8ffa: f2c0 0004 movt r0, #4 + 8ffe: 47a0 blx r4 + 9000: 2003 movs r0, #3 + 9002: e8bd 83f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} + 9006: bf00 nop + +00009008 : + 9008: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + 900c: f240 3450 movw r4, #848 ; 0x350 + 9010: f2c1 0400 movt r4, #4096 ; 0x1000 + 9014: 6823 ldr r3, [r4, #0] + 9016: 4605 mov r5, r0 + 9018: 07d8 lsls r0, r3, #31 + 901a: 460f mov r7, r1 + 901c: d44a bmi.n 90b4 + 901e: f648 4381 movw r3, #35969 ; 0x8c81 + 9022: 4628 mov r0, r5 + 9024: f2c0 0300 movt r3, #0 + 9028: f895 8084 ldrb.w r8, [r5, #132] ; 0x84 + 902c: 4798 blx r3 + 902e: 4606 mov r6, r0 + 9030: b128 cbz r0, 903e + 9032: 6823 ldr r3, [r4, #0] + 9034: 041a lsls r2, r3, #16 + 9036: d429 bmi.n 908c + 9038: 2001 movs r0, #1 + 903a: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 903e: f508 1380 add.w r3, r8, #1048576 ; 0x100000 + 9042: 2201 movs r2, #1 + 9044: f503 7384 add.w r3, r3, #264 ; 0x108 + 9048: 40ba lsls r2, r7 + 904a: 029b lsls r3, r3, #10 + 904c: b2d2 uxtb r2, r2 + 904e: 611a str r2, [r3, #16] + 9050: 6820 ldr r0, [r4, #0] + 9052: 67af str r7, [r5, #120] ; 0x78 + 9054: f410 4000 ands.w r0, r0, #32768 ; 0x8000 + 9058: d101 bne.n 905e + 905a: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 905e: f240 3310 movw r3, #784 ; 0x310 + 9062: f2c1 0300 movt r3, #4096 ; 0x1000 + 9066: 681b ldr r3, [r3, #0] + 9068: f413 6300 ands.w r3, r3, #2048 ; 0x800 + 906c: bf08 it eq + 906e: 4618 moveq r0, r3 + 9070: d0f3 beq.n 905a + 9072: f241 1090 movw r0, #4496 ; 0x1190 + 9076: f24f 339d movw r3, #62365 ; 0xf39d + 907a: 4641 mov r1, r8 + 907c: f2c0 0300 movt r3, #0 + 9080: f2c0 0004 movt r0, #4 + 9084: 4798 blx r3 + 9086: 4630 mov r0, r6 + 9088: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 908c: f240 3310 movw r3, #784 ; 0x310 + 9090: f2c1 0300 movt r3, #4096 ; 0x1000 + 9094: 681b ldr r3, [r3, #0] + 9096: 051b lsls r3, r3, #20 + 9098: d5ce bpl.n 9038 + 909a: f640 7088 movw r0, #3976 ; 0xf88 + 909e: f24f 339d movw r3, #62365 ; 0xf39d + 90a2: 4641 mov r1, r8 + 90a4: f2c0 0300 movt r3, #0 + 90a8: f2c0 0004 movt r0, #4 + 90ac: 4798 blx r3 + 90ae: 2001 movs r0, #1 + 90b0: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 90b4: f240 3310 movw r3, #784 ; 0x310 + 90b8: f2c1 0300 movt r3, #4096 ; 0x1000 + 90bc: 681b ldr r3, [r3, #0] + 90be: 0519 lsls r1, r3, #20 + 90c0: d5ad bpl.n 901e + 90c2: f241 1050 movw r0, #4432 ; 0x1150 + 90c6: f24f 339d movw r3, #62365 ; 0xf39d + 90ca: f2c0 0004 movt r0, #4 + 90ce: f2c0 0300 movt r3, #0 + 90d2: 4798 blx r3 + 90d4: e7a3 b.n 901e + 90d6: bf00 nop + +000090d8 : + 90d8: b538 push {r3, r4, r5, lr} + 90da: f240 3450 movw r4, #848 ; 0x350 + 90de: f2c1 0400 movt r4, #4096 ; 0x1000 + 90e2: 6823 ldr r3, [r4, #0] + 90e4: 4605 mov r5, r0 + 90e6: 07d8 lsls r0, r3, #31 + 90e8: d40b bmi.n 9102 + 90ea: f895 1084 ldrb.w r1, [r5, #132] ; 0x84 + 90ee: f501 1280 add.w r2, r1, #1048576 ; 0x100000 + 90f2: f502 7284 add.w r2, r2, #264 ; 0x108 + 90f6: 0292 lsls r2, r2, #10 + 90f8: 6b14 ldr r4, [r2, #48] ; 0x30 + 90fa: 065a lsls r2, r3, #25 + 90fc: d413 bmi.n 9126 + 90fe: 4620 mov r0, r4 + 9100: bd38 pop {r3, r4, r5, pc} + 9102: f240 3210 movw r2, #784 ; 0x310 + 9106: f2c1 0200 movt r2, #4096 ; 0x1000 + 910a: 6812 ldr r2, [r2, #0] + 910c: 0511 lsls r1, r2, #20 + 910e: d5ec bpl.n 90ea + 9110: f241 10b4 movw r0, #4532 ; 0x11b4 + 9114: f24f 339d movw r3, #62365 ; 0xf39d + 9118: f2c0 0004 movt r0, #4 + 911c: f2c0 0300 movt r3, #0 + 9120: 4798 blx r3 + 9122: 6823 ldr r3, [r4, #0] + 9124: e7e1 b.n 90ea + 9126: f240 3310 movw r3, #784 ; 0x310 + 912a: f2c1 0300 movt r3, #4096 ; 0x1000 + 912e: 681b ldr r3, [r3, #0] + 9130: 051b lsls r3, r3, #20 + 9132: d5e4 bpl.n 90fe + 9134: f241 10f0 movw r0, #4592 ; 0x11f0 + 9138: f24f 339d movw r3, #62365 ; 0xf39d + 913c: 4622 mov r2, r4 + 913e: f2c0 0300 movt r3, #0 + 9142: f2c0 0004 movt r0, #4 + 9146: 4798 blx r3 + 9148: e7d9 b.n 90fe + 914a: bf00 nop + +0000914c : + 914c: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} + 9150: f240 3450 movw r4, #848 ; 0x350 + 9154: f2c1 0400 movt r4, #4096 ; 0x1000 + 9158: 6823 ldr r3, [r4, #0] + 915a: 4606 mov r6, r0 + 915c: 07dd lsls r5, r3, #31 + 915e: d412 bmi.n 9186 + 9160: 0619 lsls r1, r3, #24 + 9162: d422 bmi.n 91aa + 9164: f106 0530 add.w r5, r6, #48 ; 0x30 + 9168: f244 0329 movw r3, #16425 ; 0x4029 + 916c: 4628 mov r0, r5 + 916e: f2c0 0300 movt r3, #0 + 9172: 4798 blx r3 + 9174: f244 03f1 movw r3, #16625 ; 0x40f1 + 9178: 4628 mov r0, r5 + 917a: f2c0 0300 movt r3, #0 + 917e: 4798 blx r3 + 9180: 2000 movs r0, #0 + 9182: e8bd 83f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} + 9186: f240 3210 movw r2, #784 ; 0x310 + 918a: f2c1 0200 movt r2, #4096 ; 0x1000 + 918e: 6812 ldr r2, [r2, #0] + 9190: 0510 lsls r0, r2, #20 + 9192: d5e5 bpl.n 9160 + 9194: f241 201c movw r0, #4636 ; 0x121c + 9198: f24f 339d movw r3, #62365 ; 0xf39d + 919c: f2c0 0004 movt r0, #4 + 91a0: f2c0 0300 movt r3, #0 + 91a4: 4798 blx r3 + 91a6: 6823 ldr r3, [r4, #0] + 91a8: e7da b.n 9160 + 91aa: f240 3710 movw r7, #784 ; 0x310 + 91ae: f2c1 0700 movt r7, #4096 ; 0x1000 + 91b2: 683b ldr r3, [r7, #0] + 91b4: 051a lsls r2, r3, #20 + 91b6: d5d5 bpl.n 9164 + 91b8: f248 53c9 movw r3, #34249 ; 0x85c9 + 91bc: 4630 mov r0, r6 + 91be: f2c0 0300 movt r3, #0 + 91c2: 4798 blx r3 + 91c4: f249 03d9 movw r3, #37081 ; 0x90d9 + 91c8: 4605 mov r5, r0 + 91ca: f2c0 0300 movt r3, #0 + 91ce: 4630 mov r0, r6 + 91d0: 4798 blx r3 + 91d2: f24f 389d movw r8, #62365 ; 0xf39d + 91d6: 4602 mov r2, r0 + 91d8: f241 2058 movw r0, #4696 ; 0x1258 + 91dc: f240 3950 movw r9, #848 ; 0x350 + 91e0: 4629 mov r1, r5 + 91e2: f2c0 0004 movt r0, #4 + 91e6: f2c0 0800 movt r8, #0 + 91ea: 47c0 blx r8 + 91ec: 6823 ldr r3, [r4, #0] + 91ee: f2c1 0900 movt r9, #4096 ; 0x1000 + 91f2: 061d lsls r5, r3, #24 + 91f4: d5b6 bpl.n 9164 + 91f6: 683b ldr r3, [r7, #0] + 91f8: 051b lsls r3, r3, #20 + 91fa: d5b3 bpl.n 9164 + 91fc: f241 2080 movw r0, #4736 ; 0x1280 + 9200: f106 0530 add.w r5, r6, #48 ; 0x30 + 9204: f896 1084 ldrb.w r1, [r6, #132] ; 0x84 + 9208: f2c0 0004 movt r0, #4 + 920c: 462a mov r2, r5 + 920e: 47c0 blx r8 + 9210: f8d9 3000 ldr.w r3, [r9] + 9214: 0619 lsls r1, r3, #24 + 9216: d5a7 bpl.n 9168 + 9218: 683b ldr r3, [r7, #0] + 921a: 0518 lsls r0, r3, #20 + 921c: d5a4 bpl.n 9168 + 921e: f241 20b4 movw r0, #4788 ; 0x12b4 + 9222: f896 1084 ldrb.w r1, [r6, #132] ; 0x84 + 9226: f2c0 0004 movt r0, #4 + 922a: 6b72 ldr r2, [r6, #52] ; 0x34 + 922c: 47c0 blx r8 + 922e: f8d9 3000 ldr.w r3, [r9] + 9232: 061b lsls r3, r3, #24 + 9234: d598 bpl.n 9168 + 9236: 683b ldr r3, [r7, #0] + 9238: 051a lsls r2, r3, #20 + 923a: d595 bpl.n 9168 + 923c: f241 20e4 movw r0, #4836 ; 0x12e4 + 9240: f896 1084 ldrb.w r1, [r6, #132] ; 0x84 + 9244: f2c0 0004 movt r0, #4 + 9248: 462a mov r2, r5 + 924a: 47c0 blx r8 + 924c: f8d9 3000 ldr.w r3, [r9] + 9250: 0619 lsls r1, r3, #24 + 9252: d589 bpl.n 9168 + 9254: 683b ldr r3, [r7, #0] + 9256: 0518 lsls r0, r3, #20 + 9258: d586 bpl.n 9168 + 925a: f241 3010 movw r0, #4880 ; 0x1310 + 925e: f24f 399d movw r9, #62365 ; 0xf39d + 9262: f2c0 0004 movt r0, #4 + 9266: f896 1084 ldrb.w r1, [r6, #132] ; 0x84 + 926a: f106 0238 add.w r2, r6, #56 ; 0x38 + 926e: 47c0 blx r8 + 9270: 6823 ldr r3, [r4, #0] + 9272: f2c0 0900 movt r9, #0 + 9276: 061b lsls r3, r3, #24 + 9278: f57f af76 bpl.w 9168 + 927c: 683b ldr r3, [r7, #0] + 927e: 051a lsls r2, r3, #20 + 9280: f57f af72 bpl.w 9168 + 9284: f241 303c movw r0, #4924 ; 0x133c + 9288: f896 1084 ldrb.w r1, [r6, #132] ; 0x84 + 928c: 6bf2 ldr r2, [r6, #60] ; 0x3c + 928e: f2c0 0004 movt r0, #4 + 9292: 47c8 blx r9 + 9294: e768 b.n 9168 + 9296: bf00 nop + +00009298 : + 9298: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} + 929c: f240 3450 movw r4, #848 ; 0x350 + 92a0: f2c1 0400 movt r4, #4096 ; 0x1000 + 92a4: 6823 ldr r3, [r4, #0] + 92a6: 4606 mov r6, r0 + 92a8: 07dd lsls r5, r3, #31 + 92aa: d412 bmi.n 92d2 + 92ac: 0619 lsls r1, r3, #24 + 92ae: d422 bmi.n 92f6 + 92b0: f106 0530 add.w r5, r6, #48 ; 0x30 + 92b4: f244 0391 movw r3, #16529 ; 0x4091 + 92b8: 4628 mov r0, r5 + 92ba: f2c0 0300 movt r3, #0 + 92be: 4798 blx r3 + 92c0: f244 138d movw r3, #16781 ; 0x418d + 92c4: 4628 mov r0, r5 + 92c6: f2c0 0300 movt r3, #0 + 92ca: 4798 blx r3 + 92cc: 2000 movs r0, #0 + 92ce: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + 92d2: f240 3210 movw r2, #784 ; 0x310 + 92d6: f2c1 0200 movt r2, #4096 ; 0x1000 + 92da: 6812 ldr r2, [r2, #0] + 92dc: 0510 lsls r0, r2, #20 + 92de: d5e5 bpl.n 92ac + 92e0: f241 306c movw r0, #4972 ; 0x136c + 92e4: f24f 339d movw r3, #62365 ; 0xf39d + 92e8: f2c0 0004 movt r0, #4 + 92ec: f2c0 0300 movt r3, #0 + 92f0: 4798 blx r3 + 92f2: 6823 ldr r3, [r4, #0] + 92f4: e7da b.n 92ac + 92f6: f240 3710 movw r7, #784 ; 0x310 + 92fa: f2c1 0700 movt r7, #4096 ; 0x1000 + 92fe: 683b ldr r3, [r7, #0] + 9300: 051a lsls r2, r3, #20 + 9302: d5d5 bpl.n 92b0 + 9304: f248 53c9 movw r3, #34249 ; 0x85c9 + 9308: 4630 mov r0, r6 + 930a: f2c0 0300 movt r3, #0 + 930e: f896 a084 ldrb.w sl, [r6, #132] ; 0x84 + 9312: 4798 blx r3 + 9314: f249 03d9 movw r3, #37081 ; 0x90d9 + 9318: 4605 mov r5, r0 + 931a: f2c0 0300 movt r3, #0 + 931e: 4630 mov r0, r6 + 9320: 4798 blx r3 + 9322: f24f 389d movw r8, #62365 ; 0xf39d + 9326: 4603 mov r3, r0 + 9328: f241 2058 movw r0, #4696 ; 0x1258 + 932c: f240 3950 movw r9, #848 ; 0x350 + 9330: 462a mov r2, r5 + 9332: 4651 mov r1, sl + 9334: f2c0 0004 movt r0, #4 + 9338: f2c0 0800 movt r8, #0 + 933c: 47c0 blx r8 + 933e: 6823 ldr r3, [r4, #0] + 9340: f2c1 0900 movt r9, #4096 ; 0x1000 + 9344: 061d lsls r5, r3, #24 + 9346: d5b3 bpl.n 92b0 + 9348: 683b ldr r3, [r7, #0] + 934a: 051b lsls r3, r3, #20 + 934c: d5b0 bpl.n 92b0 + 934e: f241 2080 movw r0, #4736 ; 0x1280 + 9352: f106 0530 add.w r5, r6, #48 ; 0x30 + 9356: f896 1084 ldrb.w r1, [r6, #132] ; 0x84 + 935a: f2c0 0004 movt r0, #4 + 935e: 462a mov r2, r5 + 9360: 47c0 blx r8 + 9362: f8d9 3000 ldr.w r3, [r9] + 9366: 0619 lsls r1, r3, #24 + 9368: d5a4 bpl.n 92b4 + 936a: 683b ldr r3, [r7, #0] + 936c: 0518 lsls r0, r3, #20 + 936e: d5a1 bpl.n 92b4 + 9370: f241 20b4 movw r0, #4788 ; 0x12b4 + 9374: f896 1084 ldrb.w r1, [r6, #132] ; 0x84 + 9378: f2c0 0004 movt r0, #4 + 937c: 6b72 ldr r2, [r6, #52] ; 0x34 + 937e: 47c0 blx r8 + 9380: f8d9 3000 ldr.w r3, [r9] + 9384: 061b lsls r3, r3, #24 + 9386: d595 bpl.n 92b4 + 9388: 683b ldr r3, [r7, #0] + 938a: 051a lsls r2, r3, #20 + 938c: d592 bpl.n 92b4 + 938e: f241 20e4 movw r0, #4836 ; 0x12e4 + 9392: f896 1084 ldrb.w r1, [r6, #132] ; 0x84 + 9396: f2c0 0004 movt r0, #4 + 939a: 462a mov r2, r5 + 939c: 47c0 blx r8 + 939e: f8d9 3000 ldr.w r3, [r9] + 93a2: 0619 lsls r1, r3, #24 + 93a4: d586 bpl.n 92b4 + 93a6: 683b ldr r3, [r7, #0] + 93a8: 0518 lsls r0, r3, #20 + 93aa: d583 bpl.n 92b4 + 93ac: f241 3010 movw r0, #4880 ; 0x1310 + 93b0: f24f 399d movw r9, #62365 ; 0xf39d + 93b4: f2c0 0004 movt r0, #4 + 93b8: f896 1084 ldrb.w r1, [r6, #132] ; 0x84 + 93bc: f106 0238 add.w r2, r6, #56 ; 0x38 + 93c0: 47c0 blx r8 + 93c2: 6823 ldr r3, [r4, #0] + 93c4: f2c0 0900 movt r9, #0 + 93c8: 061b lsls r3, r3, #24 + 93ca: f57f af73 bpl.w 92b4 + 93ce: 683b ldr r3, [r7, #0] + 93d0: 051a lsls r2, r3, #20 + 93d2: f57f af6f bpl.w 92b4 + 93d6: f241 303c movw r0, #4924 ; 0x133c + 93da: f896 1084 ldrb.w r1, [r6, #132] ; 0x84 + 93de: 6bf2 ldr r2, [r6, #60] ; 0x3c + 93e0: f2c0 0004 movt r0, #4 + 93e4: 47c8 blx r9 + 93e6: e765 b.n 92b4 + +000093e8 : + 93e8: b538 push {r3, r4, r5, lr} + 93ea: f240 3450 movw r4, #848 ; 0x350 + 93ee: f2c1 0400 movt r4, #4096 ; 0x1000 + 93f2: 6823 ldr r3, [r4, #0] + 93f4: 4605 mov r5, r0 + 93f6: 07d8 lsls r0, r3, #31 + 93f8: d40b bmi.n 9412 + 93fa: f895 1084 ldrb.w r1, [r5, #132] ; 0x84 + 93fe: f501 1280 add.w r2, r1, #1048576 ; 0x100000 + 9402: f502 7284 add.w r2, r2, #264 ; 0x108 + 9406: 0292 lsls r2, r2, #10 + 9408: 6b54 ldr r4, [r2, #52] ; 0x34 + 940a: 065a lsls r2, r3, #25 + 940c: d413 bmi.n 9436 + 940e: 4620 mov r0, r4 + 9410: bd38 pop {r3, r4, r5, pc} + 9412: f240 3210 movw r2, #784 ; 0x310 + 9416: f2c1 0200 movt r2, #4096 ; 0x1000 + 941a: 6812 ldr r2, [r2, #0] + 941c: 0511 lsls r1, r2, #20 + 941e: d5ec bpl.n 93fa + 9420: f241 30a8 movw r0, #5032 ; 0x13a8 + 9424: f24f 339d movw r3, #62365 ; 0xf39d + 9428: f2c0 0004 movt r0, #4 + 942c: f2c0 0300 movt r3, #0 + 9430: 4798 blx r3 + 9432: 6823 ldr r3, [r4, #0] + 9434: e7e1 b.n 93fa + 9436: f240 3310 movw r3, #784 ; 0x310 + 943a: f2c1 0300 movt r3, #4096 ; 0x1000 + 943e: 681b ldr r3, [r3, #0] + 9440: 051b lsls r3, r3, #20 + 9442: d5e4 bpl.n 940e + 9444: f241 30e8 movw r0, #5096 ; 0x13e8 + 9448: f24f 339d movw r3, #62365 ; 0xf39d + 944c: 4622 mov r2, r4 + 944e: f2c0 0300 movt r3, #0 + 9452: f2c0 0004 movt r0, #4 + 9456: 4798 blx r3 + 9458: e7d9 b.n 940e + 945a: bf00 nop + +0000945c : + 945c: b538 push {r3, r4, r5, lr} + 945e: f240 3450 movw r4, #848 ; 0x350 + 9462: f2c1 0400 movt r4, #4096 ; 0x1000 + 9466: 6823 ldr r3, [r4, #0] + 9468: 4605 mov r5, r0 + 946a: 07d8 lsls r0, r3, #31 + 946c: d40b bmi.n 9486 + 946e: f895 1084 ldrb.w r1, [r5, #132] ; 0x84 + 9472: f501 1280 add.w r2, r1, #1048576 ; 0x100000 + 9476: f502 7284 add.w r2, r2, #264 ; 0x108 + 947a: 0292 lsls r2, r2, #10 + 947c: 6914 ldr r4, [r2, #16] + 947e: 041a lsls r2, r3, #16 + 9480: d413 bmi.n 94aa + 9482: 4620 mov r0, r4 + 9484: bd38 pop {r3, r4, r5, pc} + 9486: f240 3210 movw r2, #784 ; 0x310 + 948a: f2c1 0200 movt r2, #4096 ; 0x1000 + 948e: 6812 ldr r2, [r2, #0] + 9490: 0511 lsls r1, r2, #20 + 9492: d5ec bpl.n 946e + 9494: f241 4018 movw r0, #5144 ; 0x1418 + 9498: f24f 339d movw r3, #62365 ; 0xf39d + 949c: f2c0 0004 movt r0, #4 + 94a0: f2c0 0300 movt r3, #0 + 94a4: 4798 blx r3 + 94a6: 6823 ldr r3, [r4, #0] + 94a8: e7e1 b.n 946e + 94aa: f240 3310 movw r3, #784 ; 0x310 + 94ae: f2c1 0300 movt r3, #4096 ; 0x1000 + 94b2: 681b ldr r3, [r3, #0] + 94b4: 051b lsls r3, r3, #20 + 94b6: d5e4 bpl.n 9482 + 94b8: f241 4058 movw r0, #5208 ; 0x1458 + 94bc: f24f 339d movw r3, #62365 ; 0xf39d + 94c0: 4622 mov r2, r4 + 94c2: f2c0 0300 movt r3, #0 + 94c6: f2c0 0004 movt r0, #4 + 94ca: 4798 blx r3 + 94cc: e7d9 b.n 9482 + 94ce: bf00 nop + +000094d0 : + 94d0: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 94d4: f240 3650 movw r6, #848 ; 0x350 + 94d8: f2c1 0600 movt r6, #4096 ; 0x1000 + 94dc: 6833 ldr r3, [r6, #0] + 94de: b087 sub sp, #28 + 94e0: 07da lsls r2, r3, #31 + 94e2: 4604 mov r4, r0 + 94e4: f100 81f5 bmi.w 98d2 + 94e8: f647 63f9 movw r3, #32505 ; 0x7ef9 + 94ec: f894 7088 ldrb.w r7, [r4, #136] ; 0x88 + 94f0: f2c0 0300 movt r3, #0 + 94f4: 4620 mov r0, r4 + 94f6: 9702 str r7, [sp, #8] + 94f8: f894 b081 ldrb.w fp, [r4, #129] ; 0x81 + 94fc: f894 a08e ldrb.w sl, [r4, #142] ; 0x8e + 9500: f894 9084 ldrb.w r9, [r4, #132] ; 0x84 + 9504: f894 808a ldrb.w r8, [r4, #138] ; 0x8a + 9508: 4798 blx r3 + 950a: f894 308b ldrb.w r3, [r4, #139] ; 0x8b + 950e: f894 1081 ldrb.w r1, [r4, #129] ; 0x81 + 9512: f003 0301 and.w r3, r3, #1 + 9516: f894 5082 ldrb.w r5, [r4, #130] ; 0x82 + 951a: f894 008c ldrb.w r0, [r4, #140] ; 0x8c + 951e: 019b lsls r3, r3, #6 + 9520: f001 0103 and.w r1, r1, #3 + 9524: ea43 1101 orr.w r1, r3, r1, lsl #4 + 9528: f005 050f and.w r5, r5, #15 + 952c: 01c0 lsls r0, r0, #7 + 952e: f894 308e ldrb.w r3, [r4, #142] ; 0x8e + 9532: f894 2080 ldrb.w r2, [r4, #128] ; 0x80 + 9536: 4329 orrs r1, r5 + 9538: b2c0 uxtb r0, r0 + 953a: 4301 orrs r1, r0 + 953c: f003 0303 and.w r3, r3, #3 + 9540: 0312 lsls r2, r2, #12 + 9542: ea41 2303 orr.w r3, r1, r3, lsl #8 + 9546: b292 uxth r2, r2 + 9548: 4313 orrs r3, r2 + 954a: f1b8 0f00 cmp.w r8, #0 + 954e: d105 bne.n 955c + 9550: f894 208d ldrb.w r2, [r4, #141] ; 0x8d + 9554: f002 0201 and.w r2, r2, #1 + 9558: ea43 2382 orr.w r3, r3, r2, lsl #10 + 955c: 6832 ldr r2, [r6, #0] + 955e: 0797 lsls r7, r2, #30 + 9560: f100 8281 bmi.w 9a66 + 9564: f240 3750 movw r7, #848 ; 0x350 + 9568: f2c1 0700 movt r7, #4096 ; 0x1000 + 956c: f509 1580 add.w r5, r9, #1048576 ; 0x100000 + 9570: f505 7584 add.w r5, r5, #264 ; 0x108 + 9574: 02ad lsls r5, r5, #10 + 9576: 602b str r3, [r5, #0] + 9578: 6833 ldr r3, [r6, #0] + 957a: 9700 str r7, [sp, #0] + 957c: 0798 lsls r0, r3, #30 + 957e: f100 823f bmi.w 9a00 + 9582: 6f63 ldr r3, [r4, #116] ; 0x74 + 9584: f003 033f and.w r3, r3, #63 ; 0x3f + 9588: f240 3750 movw r7, #848 ; 0x350 + 958c: f2c1 0700 movt r7, #4096 ; 0x1000 + 9590: 61ab str r3, [r5, #24] + 9592: 6833 ldr r3, [r6, #0] + 9594: 9700 str r7, [sp, #0] + 9596: 079b lsls r3, r3, #30 + 9598: f105 0218 add.w r2, r5, #24 + 959c: f100 81fe bmi.w 999c + 95a0: 6ee3 ldr r3, [r4, #108] ; 0x6c + 95a2: f003 033f and.w r3, r3, #63 ; 0x3f + 95a6: f240 3750 movw r7, #848 ; 0x350 + 95aa: 61eb str r3, [r5, #28] + 95ac: 6833 ldr r3, [r6, #0] + 95ae: f2c1 0700 movt r7, #4096 ; 0x1000 + 95b2: f013 0302 ands.w r3, r3, #2 + 95b6: f105 021c add.w r2, r5, #28 + 95ba: f040 81d8 bne.w 996e + 95be: f018 0f01 tst.w r8, #1 + 95c2: f000 80a4 beq.w 970e + 95c6: f1aa 0a02 sub.w sl, sl, #2 + 95ca: f1ba 0f01 cmp.w sl, #1 + 95ce: d906 bls.n 95de + 95d0: 9f02 ldr r7, [sp, #8] + 95d2: 2f01 cmp r7, #1 + 95d4: bf08 it eq + 95d6: f1bb 0f02 cmpeq.w fp, #2 + 95da: f040 80f7 bne.w 97cc + 95de: f8b4 807e ldrh.w r8, [r4, #126] ; 0x7e + 95e2: 2b00 cmp r3, #0 + 95e4: f040 82ad bne.w 9b42 + 95e8: f240 3750 movw r7, #848 ; 0x350 + 95ec: f8c5 8004 str.w r8, [r5, #4] + 95f0: 6833 ldr r3, [r6, #0] + 95f2: f2c1 0700 movt r7, #4096 ; 0x1000 + 95f6: 0799 lsls r1, r3, #30 + 95f8: f105 0204 add.w r2, r5, #4 + 95fc: f100 8296 bmi.w 9b2c + 9600: 6fa1 ldr r1, [r4, #120] ; 0x78 + 9602: f249 0309 movw r3, #36873 ; 0x9009 + 9606: f240 3750 movw r7, #848 ; 0x350 + 960a: f2c0 0300 movt r3, #0 + 960e: 4620 mov r0, r4 + 9610: 4798 blx r3 + 9612: 6833 ldr r3, [r6, #0] + 9614: f2c1 0700 movt r7, #4096 ; 0x1000 + 9618: 0798 lsls r0, r3, #30 + 961a: f100 8256 bmi.w 9aca + 961e: f8b4 307c ldrh.w r3, [r4, #124] ; 0x7c + 9622: f240 3750 movw r7, #848 ; 0x350 + 9626: 616b str r3, [r5, #20] + 9628: 6833 ldr r3, [r6, #0] + 962a: f2c1 0700 movt r7, #4096 ; 0x1000 + 962e: 0798 lsls r0, r3, #30 + 9630: f105 0214 add.w r2, r5, #20 + 9634: d456 bmi.n 96e4 + 9636: f894 8083 ldrb.w r8, [r4, #131] ; 0x83 + 963a: f240 3750 movw r7, #848 ; 0x350 + 963e: f8c5 804c str.w r8, [r5, #76] ; 0x4c + 9642: 6833 ldr r3, [r6, #0] + 9644: f2c1 0700 movt r7, #4096 ; 0x1000 + 9648: 079b lsls r3, r3, #30 + 964a: f105 024c add.w r2, r5, #76 ; 0x4c + 964e: f100 8116 bmi.w 987e + 9652: 6de3 ldr r3, [r4, #92] ; 0x5c + 9654: f003 033f and.w r3, r3, #63 ; 0x3f + 9658: f240 3750 movw r7, #848 ; 0x350 + 965c: 652b str r3, [r5, #80] ; 0x50 + 965e: 6833 ldr r3, [r6, #0] + 9660: f2c1 0700 movt r7, #4096 ; 0x1000 + 9664: 079b lsls r3, r3, #30 + 9666: f105 0250 add.w r2, r5, #80 ; 0x50 + 966a: f100 80de bmi.w 982a + 966e: 6da3 ldr r3, [r4, #88] ; 0x58 + 9670: f003 033f and.w r3, r3, #63 ; 0x3f + 9674: f240 3750 movw r7, #848 ; 0x350 + 9678: 656b str r3, [r5, #84] ; 0x54 + 967a: 6833 ldr r3, [r6, #0] + 967c: f2c1 0700 movt r7, #4096 ; 0x1000 + 9680: f013 0102 ands.w r1, r3, #2 + 9684: f105 0254 add.w r2, r5, #84 ; 0x54 + 9688: f040 80b8 bne.w 97fc + 968c: f894 0087 ldrb.w r0, [r4, #135] ; 0x87 + 9690: f894 3086 ldrb.w r3, [r4, #134] ; 0x86 + 9694: f000 0001 and.w r0, r0, #1 + 9698: f894 2088 ldrb.w r2, [r4, #136] ; 0x88 + 969c: 0080 lsls r0, r0, #2 + 969e: f003 0301 and.w r3, r3, #1 + 96a2: ea40 0343 orr.w r3, r0, r3, lsl #1 + 96a6: f002 0201 and.w r2, r2, #1 + 96aa: 4313 orrs r3, r2 + 96ac: 2900 cmp r1, #0 + 96ae: f040 8148 bne.w 9942 + 96b2: f240 3750 movw r7, #848 ; 0x350 + 96b6: 60eb str r3, [r5, #12] + 96b8: 6833 ldr r3, [r6, #0] + 96ba: f2c1 0700 movt r7, #4096 ; 0x1000 + 96be: 0799 lsls r1, r3, #30 + 96c0: f105 020c add.w r2, r5, #12 + 96c4: f100 8117 bmi.w 98f6 + 96c8: f894 308f ldrb.w r3, [r4, #143] ; 0x8f + 96cc: 2b01 cmp r3, #1 + 96ce: d035 beq.n 973c + 96d0: f647 6345 movw r3, #32325 ; 0x7e45 + 96d4: 4620 mov r0, r4 + 96d6: f2c0 0300 movt r3, #0 + 96da: 4798 blx r3 + 96dc: 2000 movs r0, #0 + 96de: b007 add sp, #28 + 96e0: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 96e4: f240 3310 movw r3, #784 ; 0x310 + 96e8: f2c1 0300 movt r3, #4096 ; 0x1000 + 96ec: 681b ldr r3, [r3, #0] + 96ee: 0519 lsls r1, r3, #20 + 96f0: d5a1 bpl.n 9636 + 96f2: f241 60ec movw r0, #5868 ; 0x16ec + 96f6: f24f 3c9d movw ip, #62365 ; 0xf39d + 96fa: 696b ldr r3, [r5, #20] + 96fc: f2c0 0004 movt r0, #4 + 9700: f2c0 0c00 movt ip, #0 + 9704: 4649 mov r1, r9 + 9706: 47e0 blx ip + 9708: 683b ldr r3, [r7, #0] + 970a: f003 0302 and.w r3, r3, #2 + 970e: f894 8083 ldrb.w r8, [r4, #131] ; 0x83 + 9712: 2b00 cmp r3, #0 + 9714: d091 beq.n 963a + 9716: f240 3310 movw r3, #784 ; 0x310 + 971a: f2c1 0300 movt r3, #4096 ; 0x1000 + 971e: 681b ldr r3, [r3, #0] + 9720: 051a lsls r2, r3, #20 + 9722: d58a bpl.n 963a + 9724: f241 7020 movw r0, #5920 ; 0x1720 + 9728: f24f 339d movw r3, #62365 ; 0xf39d + 972c: 4649 mov r1, r9 + 972e: f2c0 0300 movt r3, #0 + 9732: 4642 mov r2, r8 + 9734: f2c0 0004 movt r0, #4 + 9738: 4798 blx r3 + 973a: e77e b.n 963a + 973c: 6833 ldr r3, [r6, #0] + 973e: 0798 lsls r0, r3, #30 + 9740: f100 81a7 bmi.w 9a92 + 9744: f1b9 0f01 cmp.w r9, #1 + 9748: d055 beq.n 97f6 + 974a: d351 bcc.n 97f0 + 974c: f1b9 0f02 cmp.w r9, #2 + 9750: bf04 itt eq + 9752: 2349 moveq r3, #73 ; 0x49 + 9754: 9305 streq r3, [sp, #20] + 9756: d004 beq.n 9762 + 9758: f64f 4319 movw r3, #64537 ; 0xfc19 + 975c: f6cf 73ff movt r3, #65535 ; 0xffff + 9760: 9305 str r3, [sp, #20] + 9762: f64f 4319 movw r3, #64537 ; 0xfc19 + 9766: f6cf 73ff movt r3, #65535 ; 0xffff + 976a: 9a05 ldr r2, [sp, #20] + 976c: 429a cmp r2, r3 + 976e: f000 81a5 beq.w 9abc + 9772: f248 5321 movw r3, #34081 ; 0x8521 + 9776: 4620 mov r0, r4 + 9778: f2c0 0300 movt r3, #0 + 977c: 4798 blx r3 + 977e: f649 62b1 movw r2, #40625 ; 0x9eb1 + 9782: f244 0329 movw r3, #16425 ; 0x4029 + 9786: f2c0 0200 movt r2, #0 + 978a: 9805 ldr r0, [sp, #20] + 978c: 6e21 ldr r1, [r4, #96] ; 0x60 + 978e: f104 0530 add.w r5, r4, #48 ; 0x30 + 9792: 6360 str r0, [r4, #52] ; 0x34 + 9794: 63a4 str r4, [r4, #56] ; 0x38 + 9796: 6322 str r2, [r4, #48] ; 0x30 + 9798: f2c0 0300 movt r3, #0 + 979c: 63e1 str r1, [r4, #60] ; 0x3c + 979e: 4628 mov r0, r5 + 97a0: 4798 blx r3 + 97a2: f244 03f1 movw r3, #16625 ; 0x40f1 + 97a6: 4628 mov r0, r5 + 97a8: f2c0 0300 movt r3, #0 + 97ac: 4798 blx r3 + 97ae: e78f b.n 96d0 + 97b0: f241 600c movw r0, #5644 ; 0x160c + 97b4: f24f 3c9d movw ip, #62365 ; 0xf39d + 97b8: 686b ldr r3, [r5, #4] + 97ba: f2c0 0004 movt r0, #4 + 97be: f2c0 0c00 movt ip, #0 + 97c2: 4649 mov r1, r9 + 97c4: 47e0 blx ip + 97c6: 683b ldr r3, [r7, #0] + 97c8: f003 0302 and.w r3, r3, #2 + 97cc: 6fa1 ldr r1, [r4, #120] ; 0x78 + 97ce: 4608 mov r0, r1 + 97d0: 2b00 cmp r3, #0 + 97d2: f43f af16 beq.w 9602 + 97d6: f240 3310 movw r3, #784 ; 0x310 + 97da: f2c1 0300 movt r3, #4096 ; 0x1000 + 97de: 681b ldr r3, [r3, #0] + 97e0: 2201 movs r2, #1 + 97e2: 408a lsls r2, r1 + 97e4: 051f lsls r7, r3, #20 + 97e6: b2d2 uxtb r2, r2 + 97e8: f100 81bf bmi.w 9b6a + 97ec: 4601 mov r1, r0 + 97ee: e708 b.n 9602 + 97f0: 2306 movs r3, #6 + 97f2: 9305 str r3, [sp, #20] + 97f4: e7b5 b.n 9762 + 97f6: 2348 movs r3, #72 ; 0x48 + 97f8: 9305 str r3, [sp, #20] + 97fa: e7b2 b.n 9762 + 97fc: f240 3310 movw r3, #784 ; 0x310 + 9800: f2c1 0300 movt r3, #4096 ; 0x1000 + 9804: 681b ldr r3, [r3, #0] + 9806: 051b lsls r3, r3, #20 + 9808: f57f af40 bpl.w 968c + 980c: f641 0040 movw r0, #6208 ; 0x1840 + 9810: f24f 3c9d movw ip, #62365 ; 0xf39d + 9814: 4649 mov r1, r9 + 9816: 6d6b ldr r3, [r5, #84] ; 0x54 + 9818: f2c0 0004 movt r0, #4 + 981c: f2c0 0c00 movt ip, #0 + 9820: 47e0 blx ip + 9822: 6839 ldr r1, [r7, #0] + 9824: f001 0102 and.w r1, r1, #2 + 9828: e730 b.n 968c + 982a: f240 3a10 movw sl, #784 ; 0x310 + 982e: f2c1 0a00 movt sl, #4096 ; 0x1000 + 9832: f8da 3000 ldr.w r3, [sl] + 9836: 0518 lsls r0, r3, #20 + 9838: f57f af19 bpl.w 966e + 983c: f241 70cc movw r0, #6092 ; 0x17cc + 9840: f24f 389d movw r8, #62365 ; 0xf39d + 9844: 6d2b ldr r3, [r5, #80] ; 0x50 + 9846: 4649 mov r1, r9 + 9848: f2c0 0004 movt r0, #4 + 984c: f2c0 0800 movt r8, #0 + 9850: 47c0 blx r8 + 9852: 683a ldr r2, [r7, #0] + 9854: 6da3 ldr r3, [r4, #88] ; 0x58 + 9856: 0791 lsls r1, r2, #30 + 9858: f003 033f and.w r3, r3, #63 ; 0x3f + 985c: f57f af0a bpl.w 9674 + 9860: f8da 2000 ldr.w r2, [sl] + 9864: 0512 lsls r2, r2, #20 + 9866: f57f af05 bpl.w 9674 + 986a: f641 0004 movw r0, #6148 ; 0x1804 + 986e: 461a mov r2, r3 + 9870: 9301 str r3, [sp, #4] + 9872: 4649 mov r1, r9 + 9874: f2c0 0004 movt r0, #4 + 9878: 47c0 blx r8 + 987a: 9b01 ldr r3, [sp, #4] + 987c: e6fa b.n 9674 + 987e: f240 3a10 movw sl, #784 ; 0x310 + 9882: f2c1 0a00 movt sl, #4096 ; 0x1000 + 9886: f8da 3000 ldr.w r3, [sl] + 988a: 0518 lsls r0, r3, #20 + 988c: f57f aee1 bpl.w 9652 + 9890: f241 705c movw r0, #5980 ; 0x175c + 9894: f24f 389d movw r8, #62365 ; 0xf39d + 9898: 6ceb ldr r3, [r5, #76] ; 0x4c + 989a: 4649 mov r1, r9 + 989c: f2c0 0004 movt r0, #4 + 98a0: f2c0 0800 movt r8, #0 + 98a4: 47c0 blx r8 + 98a6: 683a ldr r2, [r7, #0] + 98a8: 6de3 ldr r3, [r4, #92] ; 0x5c + 98aa: 0791 lsls r1, r2, #30 + 98ac: f003 033f and.w r3, r3, #63 ; 0x3f + 98b0: f57f aed2 bpl.w 9658 + 98b4: f8da 2000 ldr.w r2, [sl] + 98b8: 0512 lsls r2, r2, #20 + 98ba: f57f aecd bpl.w 9658 + 98be: f241 7090 movw r0, #6032 ; 0x1790 + 98c2: 461a mov r2, r3 + 98c4: 9301 str r3, [sp, #4] + 98c6: 4649 mov r1, r9 + 98c8: f2c0 0004 movt r0, #4 + 98cc: 47c0 blx r8 + 98ce: 9b01 ldr r3, [sp, #4] + 98d0: e6c2 b.n 9658 + 98d2: f240 3310 movw r3, #784 ; 0x310 + 98d6: f2c1 0300 movt r3, #4096 ; 0x1000 + 98da: 681b ldr r3, [r3, #0] + 98dc: 051b lsls r3, r3, #20 + 98de: f57f ae03 bpl.w 94e8 + 98e2: f241 407c movw r0, #5244 ; 0x147c + 98e6: f24f 339d movw r3, #62365 ; 0xf39d + 98ea: f2c0 0004 movt r0, #4 + 98ee: f2c0 0300 movt r3, #0 + 98f2: 4798 blx r3 + 98f4: e5f8 b.n 94e8 + 98f6: f240 3a10 movw sl, #784 ; 0x310 + 98fa: f2c1 0a00 movt sl, #4096 ; 0x1000 + 98fe: f8da 3000 ldr.w r3, [sl] + 9902: 051b lsls r3, r3, #20 + 9904: f57f aee0 bpl.w 96c8 + 9908: f641 00b0 movw r0, #6320 ; 0x18b0 + 990c: f24f 389d movw r8, #62365 ; 0xf39d + 9910: 68eb ldr r3, [r5, #12] + 9912: f2c0 0004 movt r0, #4 + 9916: f2c0 0800 movt r8, #0 + 991a: 4649 mov r1, r9 + 991c: 47c0 blx r8 + 991e: 683b ldr r3, [r7, #0] + 9920: 079d lsls r5, r3, #30 + 9922: f57f aed1 bpl.w 96c8 + 9926: f8da 3000 ldr.w r3, [sl] + 992a: 051f lsls r7, r3, #20 + 992c: f57f aecc bpl.w 96c8 + 9930: f641 00e4 movw r0, #6372 ; 0x18e4 + 9934: 4649 mov r1, r9 + 9936: f894 208f ldrb.w r2, [r4, #143] ; 0x8f + 993a: f2c0 0004 movt r0, #4 + 993e: 47c0 blx r8 + 9940: e6c2 b.n 96c8 + 9942: f240 3210 movw r2, #784 ; 0x310 + 9946: f2c1 0200 movt r2, #4096 ; 0x1000 + 994a: 6812 ldr r2, [r2, #0] + 994c: 0510 lsls r0, r2, #20 + 994e: f57f aeb0 bpl.w 96b2 + 9952: f641 0078 movw r0, #6264 ; 0x1878 + 9956: f24f 379d movw r7, #62365 ; 0xf39d + 995a: 461a mov r2, r3 + 995c: 9301 str r3, [sp, #4] + 995e: f2c0 0004 movt r0, #4 + 9962: f2c0 0700 movt r7, #0 + 9966: 4649 mov r1, r9 + 9968: 47b8 blx r7 + 996a: 9b01 ldr r3, [sp, #4] + 996c: e6a1 b.n 96b2 + 996e: f240 3110 movw r1, #784 ; 0x310 + 9972: f2c1 0100 movt r1, #4096 ; 0x1000 + 9976: 6809 ldr r1, [r1, #0] + 9978: 0509 lsls r1, r1, #20 + 997a: f57f ae20 bpl.w 95be + 997e: f241 5098 movw r0, #5528 ; 0x1598 + 9982: f24f 3c9d movw ip, #62365 ; 0xf39d + 9986: 69eb ldr r3, [r5, #28] + 9988: f2c0 0004 movt r0, #4 + 998c: f2c0 0c00 movt ip, #0 + 9990: 4649 mov r1, r9 + 9992: 47e0 blx ip + 9994: 683b ldr r3, [r7, #0] + 9996: f003 0302 and.w r3, r3, #2 + 999a: e610 b.n 95be + 999c: f240 3c10 movw ip, #784 ; 0x310 + 99a0: f2c1 0c00 movt ip, #4096 ; 0x1000 + 99a4: f8dc 3000 ldr.w r3, [ip] + 99a8: 051f lsls r7, r3, #20 + 99aa: f57f adf9 bpl.w 95a0 + 99ae: f24f 379d movw r7, #62365 ; 0xf39d + 99b2: f241 5024 movw r0, #5412 ; 0x1524 + 99b6: f2c0 0700 movt r7, #0 + 99ba: 69ab ldr r3, [r5, #24] + 99bc: f2c0 0004 movt r0, #4 + 99c0: f8cd c004 str.w ip, [sp, #4] + 99c4: 4649 mov r1, r9 + 99c6: 9703 str r7, [sp, #12] + 99c8: 47b8 blx r7 + 99ca: 9f00 ldr r7, [sp, #0] + 99cc: 6ee3 ldr r3, [r4, #108] ; 0x6c + 99ce: 683a ldr r2, [r7, #0] + 99d0: f003 033f and.w r3, r3, #63 ; 0x3f + 99d4: f012 0f02 tst.w r2, #2 + 99d8: f8dd c004 ldr.w ip, [sp, #4] + 99dc: f43f ade3 beq.w 95a6 + 99e0: f8dc 2000 ldr.w r2, [ip] + 99e4: 0510 lsls r0, r2, #20 + 99e6: f57f adde bpl.w 95a6 + 99ea: f241 505c movw r0, #5468 ; 0x155c + 99ee: 461a mov r2, r3 + 99f0: 9301 str r3, [sp, #4] + 99f2: 4649 mov r1, r9 + 99f4: f2c0 0004 movt r0, #4 + 99f8: 9f03 ldr r7, [sp, #12] + 99fa: 47b8 blx r7 + 99fc: 9b01 ldr r3, [sp, #4] + 99fe: e5d2 b.n 95a6 + 9a00: f240 3c10 movw ip, #784 ; 0x310 + 9a04: f2c1 0c00 movt ip, #4096 ; 0x1000 + 9a08: f8dc 3000 ldr.w r3, [ip] + 9a0c: 0519 lsls r1, r3, #20 + 9a0e: f57f adb8 bpl.w 9582 + 9a12: f24f 379d movw r7, #62365 ; 0xf39d + 9a16: f640 20b8 movw r0, #2744 ; 0xab8 + 9a1a: f2c0 0700 movt r7, #0 + 9a1e: 682b ldr r3, [r5, #0] + 9a20: 462a mov r2, r5 + 9a22: f8cd c004 str.w ip, [sp, #4] + 9a26: f2c0 0004 movt r0, #4 + 9a2a: 4649 mov r1, r9 + 9a2c: 9703 str r7, [sp, #12] + 9a2e: 47b8 blx r7 + 9a30: 9f00 ldr r7, [sp, #0] + 9a32: 6f63 ldr r3, [r4, #116] ; 0x74 + 9a34: 683a ldr r2, [r7, #0] + 9a36: f003 033f and.w r3, r3, #63 ; 0x3f + 9a3a: f012 0f02 tst.w r2, #2 + 9a3e: f8dd c004 ldr.w ip, [sp, #4] + 9a42: f43f ada1 beq.w 9588 + 9a46: f8dc 2000 ldr.w r2, [ip] + 9a4a: 0512 lsls r2, r2, #20 + 9a4c: f57f ad9c bpl.w 9588 + 9a50: f241 40e8 movw r0, #5352 ; 0x14e8 + 9a54: 461a mov r2, r3 + 9a56: 9301 str r3, [sp, #4] + 9a58: 4649 mov r1, r9 + 9a5a: f2c0 0004 movt r0, #4 + 9a5e: 9f03 ldr r7, [sp, #12] + 9a60: 47b8 blx r7 + 9a62: 9b01 ldr r3, [sp, #4] + 9a64: e590 b.n 9588 + 9a66: f240 3210 movw r2, #784 ; 0x310 + 9a6a: f2c1 0200 movt r2, #4096 ; 0x1000 + 9a6e: 6812 ldr r2, [r2, #0] + 9a70: 0515 lsls r5, r2, #20 + 9a72: f57f ad77 bpl.w 9564 + 9a76: f241 40ac movw r0, #5292 ; 0x14ac + 9a7a: f24f 359d movw r5, #62365 ; 0xf39d + 9a7e: 461a mov r2, r3 + 9a80: 9301 str r3, [sp, #4] + 9a82: f2c0 0004 movt r0, #4 + 9a86: f2c0 0500 movt r5, #0 + 9a8a: 4649 mov r1, r9 + 9a8c: 47a8 blx r5 + 9a8e: 9b01 ldr r3, [sp, #4] + 9a90: e568 b.n 9564 + 9a92: f240 3310 movw r3, #784 ; 0x310 + 9a96: f2c1 0300 movt r3, #4096 ; 0x1000 + 9a9a: 681b ldr r3, [r3, #0] + 9a9c: 0519 lsls r1, r3, #20 + 9a9e: f57f ae51 bpl.w 9744 + 9aa2: f641 1010 movw r0, #6416 ; 0x1910 + 9aa6: f24f 339d movw r3, #62365 ; 0xf39d + 9aaa: 4649 mov r1, r9 + 9aac: f2c0 0300 movt r3, #0 + 9ab0: f894 2085 ldrb.w r2, [r4, #133] ; 0x85 + 9ab4: f2c0 0004 movt r0, #4 + 9ab8: 4798 blx r3 + 9aba: e643 b.n 9744 + 9abc: 6833 ldr r3, [r6, #0] + 9abe: 079a lsls r2, r3, #30 + 9ac0: d45e bmi.n 9b80 + 9ac2: 2300 movs r3, #0 + 9ac4: f884 308f strb.w r3, [r4, #143] ; 0x8f + 9ac8: e602 b.n 96d0 + 9aca: f240 3a10 movw sl, #784 ; 0x310 + 9ace: f2c1 0a00 movt sl, #4096 ; 0x1000 + 9ad2: f8da 3000 ldr.w r3, [sl] + 9ad6: 0519 lsls r1, r3, #20 + 9ad8: f57f ada1 bpl.w 961e + 9adc: f249 435d movw r3, #37981 ; 0x945d + 9ae0: 4620 mov r0, r4 + 9ae2: f2c0 0300 movt r3, #0 + 9ae6: 4798 blx r3 + 9ae8: f24f 389d movw r8, #62365 ; 0xf39d + 9aec: 4603 mov r3, r0 + 9aee: f241 607c movw r0, #5756 ; 0x167c + 9af2: f105 0210 add.w r2, r5, #16 + 9af6: f2c0 0004 movt r0, #4 + 9afa: f2c0 0800 movt r8, #0 + 9afe: 4649 mov r1, r9 + 9b00: 47c0 blx r8 + 9b02: 683a ldr r2, [r7, #0] + 9b04: f8b4 307c ldrh.w r3, [r4, #124] ; 0x7c + 9b08: 0792 lsls r2, r2, #30 + 9b0a: f57f ad8a bpl.w 9622 + 9b0e: f8da 2000 ldr.w r2, [sl] + 9b12: 0517 lsls r7, r2, #20 + 9b14: f57f ad85 bpl.w 9622 + 9b18: f241 60b0 movw r0, #5808 ; 0x16b0 + 9b1c: 461a mov r2, r3 + 9b1e: 9301 str r3, [sp, #4] + 9b20: 4649 mov r1, r9 + 9b22: f2c0 0004 movt r0, #4 + 9b26: 47c0 blx r8 + 9b28: 9b01 ldr r3, [sp, #4] + 9b2a: e57a b.n 9622 + 9b2c: f240 3310 movw r3, #784 ; 0x310 + 9b30: f2c1 0300 movt r3, #4096 ; 0x1000 + 9b34: 681b ldr r3, [r3, #0] + 9b36: 051b lsls r3, r3, #20 + 9b38: f53f ae3a bmi.w 97b0 + 9b3c: 6fa0 ldr r0, [r4, #120] ; 0x78 + 9b3e: 4601 mov r1, r0 + 9b40: e55f b.n 9602 + 9b42: f240 3310 movw r3, #784 ; 0x310 + 9b46: f2c1 0300 movt r3, #4096 ; 0x1000 + 9b4a: 681b ldr r3, [r3, #0] + 9b4c: 0518 lsls r0, r3, #20 + 9b4e: f57f ad4b bpl.w 95e8 + 9b52: f241 50d0 movw r0, #5584 ; 0x15d0 + 9b56: f24f 339d movw r3, #62365 ; 0xf39d + 9b5a: 4649 mov r1, r9 + 9b5c: f2c0 0300 movt r3, #0 + 9b60: 4642 mov r2, r8 + 9b62: f2c0 0004 movt r0, #4 + 9b66: 4798 blx r3 + 9b68: e53e b.n 95e8 + 9b6a: f241 6044 movw r0, #5700 ; 0x1644 + 9b6e: f24f 339d movw r3, #62365 ; 0xf39d + 9b72: 4649 mov r1, r9 + 9b74: f2c0 0300 movt r3, #0 + 9b78: f2c0 0004 movt r0, #4 + 9b7c: 4798 blx r3 + 9b7e: e53f b.n 9600 + 9b80: f240 3310 movw r3, #784 ; 0x310 + 9b84: f2c1 0300 movt r3, #4096 ; 0x1000 + 9b88: 681b ldr r3, [r3, #0] + 9b8a: 051b lsls r3, r3, #20 + 9b8c: d599 bpl.n 9ac2 + 9b8e: f641 104c movw r0, #6476 ; 0x194c + 9b92: f24f 339d movw r3, #62365 ; 0xf39d + 9b96: f2c0 0004 movt r0, #4 + 9b9a: f2c0 0300 movt r3, #0 + 9b9e: 4798 blx r3 + 9ba0: e78f b.n 9ac2 + 9ba2: bf00 nop + +00009ba4 <_SsiReadInterrupt>: + 9ba4: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 9ba8: f240 3b50 movw fp, #848 ; 0x350 + 9bac: f2c1 0b00 movt fp, #4096 ; 0x1000 + 9bb0: f8db 2000 ldr.w r2, [fp] + 9bb4: b083 sub sp, #12 + 9bb6: 07d1 lsls r1, r2, #31 + 9bb8: 4604 mov r4, r0 + 9bba: f100 80d5 bmi.w 9d68 <_SsiReadInterrupt+0x1c4> + 9bbe: f648 4609 movw r6, #35849 ; 0x8c09 + 9bc2: 4620 mov r0, r4 + 9bc4: f2c0 0600 movt r6, #0 + 9bc8: 47b0 blx r6 + 9bca: f894 3084 ldrb.w r3, [r4, #132] ; 0x84 + 9bce: 9301 str r3, [sp, #4] + 9bd0: 2800 cmp r0, #0 + 9bd2: d03e beq.n 9c52 <_SsiReadInterrupt+0xae> + 9bd4: f240 3350 movw r3, #848 ; 0x350 + 9bd8: f648 272d movw r7, #35373 ; 0x8a2d + 9bdc: f240 3910 movw r9, #784 ; 0x310 + 9be0: f24f 389d movw r8, #62365 ; 0xf39d + 9be4: f2c1 0300 movt r3, #4096 ; 0x1000 + 9be8: f2c0 0700 movt r7, #0 + 9bec: f2c1 0900 movt r9, #4096 ; 0x1000 + 9bf0: f2c0 0800 movt r8, #0 + 9bf4: 9300 str r3, [sp, #0] + 9bf6: 9b01 ldr r3, [sp, #4] + 9bf8: f503 1c80 add.w ip, r3, #1048576 ; 0x100000 + 9bfc: f50c 7c84 add.w ip, ip, #264 ; 0x108 + 9c00: ea4f 2c8c mov.w ip, ip, lsl #10 + 9c04: f10c 0a60 add.w sl, ip, #96 ; 0x60 + 9c08: 4620 mov r0, r4 + 9c0a: 47b8 blx r7 + 9c0c: 4605 mov r5, r0 + 9c0e: b1a5 cbz r5, 9c3a <_SsiReadInterrupt+0x96> + 9c10: 6ca1 ldr r1, [r4, #72] ; 0x48 + 9c12: f8da 2000 ldr.w r2, [sl] + 9c16: 600a str r2, [r1, #0] + 9c18: f8db 0000 ldr.w r0, [fp] + 9c1c: 0583 lsls r3, r0, #22 + 9c1e: bf5c itt pl + 9c20: 3104 addpl r1, #4 + 9c22: 64a1 strpl r1, [r4, #72] ; 0x48 + 9c24: d46e bmi.n 9d04 <_SsiReadInterrupt+0x160> + 9c26: 6e61 ldr r1, [r4, #100] ; 0x64 + 9c28: 2900 cmp r1, #0 + 9c2a: d03f beq.n 9cac <_SsiReadInterrupt+0x108> + 9c2c: 3901 subs r1, #1 + 9c2e: 6661 str r1, [r4, #100] ; 0x64 + 9c30: 2900 cmp r1, #0 + 9c32: d04f beq.n 9cd4 <_SsiReadInterrupt+0x130> + 9c34: 3d01 subs r5, #1 + 9c36: 2d00 cmp r5, #0 + 9c38: d1ea bne.n 9c10 <_SsiReadInterrupt+0x6c> + 9c3a: f8db 2000 ldr.w r2, [fp] + 9c3e: 6e61 ldr r1, [r4, #100] ; 0x64 + 9c40: 0592 lsls r2, r2, #22 + 9c42: d439 bmi.n 9cb8 <_SsiReadInterrupt+0x114> + 9c44: b909 cbnz r1, 9c4a <_SsiReadInterrupt+0xa6> + 9c46: 6ea1 ldr r1, [r4, #104] ; 0x68 + 9c48: b121 cbz r1, 9c54 <_SsiReadInterrupt+0xb0> + 9c4a: 4620 mov r0, r4 + 9c4c: 47b0 blx r6 + 9c4e: 2800 cmp r0, #0 + 9c50: d1da bne.n 9c08 <_SsiReadInterrupt+0x64> + 9c52: 6e61 ldr r1, [r4, #100] ; 0x64 + 9c54: f8db 2000 ldr.w r2, [fp] + 9c58: 0595 lsls r5, r2, #22 + 9c5a: d472 bmi.n 9d42 <_SsiReadInterrupt+0x19e> + 9c5c: bb19 cbnz r1, 9ca6 <_SsiReadInterrupt+0x102> + 9c5e: 9b01 ldr r3, [sp, #4] + 9c60: 6ee2 ldr r2, [r4, #108] ; 0x6c + 9c62: f503 1180 add.w r1, r3, #1048576 ; 0x100000 + 9c66: f501 7184 add.w r1, r1, #264 ; 0x108 + 9c6a: 0289 lsls r1, r1, #10 + 9c6c: 69c9 ldr r1, [r1, #28] + 9c6e: b1c2 cbz r2, 9ca2 <_SsiReadInterrupt+0xfe> + 9c70: f8db 3000 ldr.w r3, [fp] + 9c74: 059a lsls r2, r3, #22 + 9c76: f100 8089 bmi.w 9d8c <_SsiReadInterrupt+0x1e8> + 9c7a: f647 63f9 movw r3, #32505 ; 0x7ef9 + 9c7e: 4620 mov r0, r4 + 9c80: f2c0 0300 movt r3, #0 + 9c84: 4798 blx r3 + 9c86: f648 03c9 movw r3, #35017 ; 0x88c9 + 9c8a: 2200 movs r2, #0 + 9c8c: f2c0 0300 movt r3, #0 + 9c90: 66e2 str r2, [r4, #108] ; 0x6c + 9c92: 4620 mov r0, r4 + 9c94: 4798 blx r3 + 9c96: f647 6345 movw r3, #32325 ; 0x7e45 + 9c9a: 4620 mov r0, r4 + 9c9c: f2c0 0300 movt r3, #0 + 9ca0: 4798 blx r3 + 9ca2: 6ea3 ldr r3, [r4, #104] ; 0x68 + 9ca4: b1d3 cbz r3, 9cdc <_SsiReadInterrupt+0x138> + 9ca6: b003 add sp, #12 + 9ca8: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 9cac: 6ea2 ldr r2, [r4, #104] ; 0x68 + 9cae: b97a cbnz r2, 9cd0 <_SsiReadInterrupt+0x12c> + 9cb0: f8db 2000 ldr.w r2, [fp] + 9cb4: 0592 lsls r2, r2, #22 + 9cb6: d5c5 bpl.n 9c44 <_SsiReadInterrupt+0xa0> + 9cb8: f8d9 2000 ldr.w r2, [r9] + 9cbc: 0513 lsls r3, r2, #20 + 9cbe: d5c1 bpl.n 9c44 <_SsiReadInterrupt+0xa0> + 9cc0: f641 10e4 movw r0, #6628 ; 0x19e4 + 9cc4: 6ea2 ldr r2, [r4, #104] ; 0x68 + 9cc6: f2c0 0004 movt r0, #4 + 9cca: 47c0 blx r8 + 9ccc: 6e61 ldr r1, [r4, #100] ; 0x64 + 9cce: e7b9 b.n 9c44 <_SsiReadInterrupt+0xa0> + 9cd0: 3a01 subs r2, #1 + 9cd2: 66a2 str r2, [r4, #104] ; 0x68 + 9cd4: 6ea2 ldr r2, [r4, #104] ; 0x68 + 9cd6: 2a00 cmp r2, #0 + 9cd8: d1ac bne.n 9c34 <_SsiReadInterrupt+0x90> + 9cda: e7ae b.n 9c3a <_SsiReadInterrupt+0x96> + 9cdc: f248 5321 movw r3, #34081 ; 0x8521 + 9ce0: f894 2085 ldrb.w r2, [r4, #133] ; 0x85 + 9ce4: f2c0 0300 movt r3, #0 + 9ce8: f022 021c bic.w r2, r2, #28 + 9cec: f884 2085 strb.w r2, [r4, #133] ; 0x85 + 9cf0: 4620 mov r0, r4 + 9cf2: 4798 blx r3 + 9cf4: 6c23 ldr r3, [r4, #64] ; 0x40 + 9cf6: 2b00 cmp r3, #0 + 9cf8: d0d5 beq.n 9ca6 <_SsiReadInterrupt+0x102> + 9cfa: 6c60 ldr r0, [r4, #68] ; 0x44 + 9cfc: b003 add sp, #12 + 9cfe: e8bd 4ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 9d02: 4718 bx r3 + 9d04: f8d9 0000 ldr.w r0, [r9] + 9d08: 0500 lsls r0, r0, #20 + 9d0a: bf5c itt pl + 9d0c: 3104 addpl r1, #4 + 9d0e: 64a1 strpl r1, [r4, #72] ; 0x48 + 9d10: d409 bmi.n 9d26 <_SsiReadInterrupt+0x182> + 9d12: f8d9 2000 ldr.w r2, [r9] + 9d16: 0510 lsls r0, r2, #20 + 9d18: d585 bpl.n 9c26 <_SsiReadInterrupt+0x82> + 9d1a: f641 10c4 movw r0, #6596 ; 0x19c4 + 9d1e: f2c0 0004 movt r0, #4 + 9d22: 47c0 blx r8 + 9d24: e77f b.n 9c26 <_SsiReadInterrupt+0x82> + 9d26: f641 10a0 movw r0, #6560 ; 0x19a0 + 9d2a: f2c0 0004 movt r0, #4 + 9d2e: 47c0 blx r8 + 9d30: 9b00 ldr r3, [sp, #0] + 9d32: 6ca1 ldr r1, [r4, #72] ; 0x48 + 9d34: 681a ldr r2, [r3, #0] + 9d36: 3104 adds r1, #4 + 9d38: 0593 lsls r3, r2, #22 + 9d3a: 64a1 str r1, [r4, #72] ; 0x48 + 9d3c: f57f af73 bpl.w 9c26 <_SsiReadInterrupt+0x82> + 9d40: e7e7 b.n 9d12 <_SsiReadInterrupt+0x16e> + 9d42: f240 3210 movw r2, #784 ; 0x310 + 9d46: f2c1 0200 movt r2, #4096 ; 0x1000 + 9d4a: 6812 ldr r2, [r2, #0] + 9d4c: 0510 lsls r0, r2, #20 + 9d4e: d585 bpl.n 9c5c <_SsiReadInterrupt+0xb8> + 9d50: f641 10e4 movw r0, #6628 ; 0x19e4 + 9d54: f24f 359d movw r5, #62365 ; 0xf39d + 9d58: f2c0 0004 movt r0, #4 + 9d5c: f2c0 0500 movt r5, #0 + 9d60: 6ea2 ldr r2, [r4, #104] ; 0x68 + 9d62: 47a8 blx r5 + 9d64: 6e61 ldr r1, [r4, #100] ; 0x64 + 9d66: e779 b.n 9c5c <_SsiReadInterrupt+0xb8> + 9d68: f240 3210 movw r2, #784 ; 0x310 + 9d6c: f2c1 0200 movt r2, #4096 ; 0x1000 + 9d70: 6812 ldr r2, [r2, #0] + 9d72: 0512 lsls r2, r2, #20 + 9d74: f57f af23 bpl.w 9bbe <_SsiReadInterrupt+0x1a> + 9d78: f641 1070 movw r0, #6512 ; 0x1970 + 9d7c: f24f 329d movw r2, #62365 ; 0xf39d + 9d80: f2c0 0004 movt r0, #4 + 9d84: f2c0 0200 movt r2, #0 + 9d88: 4790 blx r2 + 9d8a: e718 b.n 9bbe <_SsiReadInterrupt+0x1a> + 9d8c: f240 3310 movw r3, #784 ; 0x310 + 9d90: f2c1 0300 movt r3, #4096 ; 0x1000 + 9d94: 681b ldr r3, [r3, #0] + 9d96: 051b lsls r3, r3, #20 + 9d98: f57f af6f bpl.w 9c7a <_SsiReadInterrupt+0xd6> + 9d9c: f241 0068 movw r0, #4200 ; 0x1068 + 9da0: f24f 339d movw r3, #62365 ; 0xf39d + 9da4: f2c0 0004 movt r0, #4 + 9da8: f2c0 0300 movt r3, #0 + 9dac: 4798 blx r3 + 9dae: e764 b.n 9c7a <_SsiReadInterrupt+0xd6> + +00009db0 <_SsiWriteInterrupt>: + 9db0: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} + 9db4: f240 3650 movw r6, #848 ; 0x350 + 9db8: f2c1 0600 movt r6, #4096 ; 0x1000 + 9dbc: 6833 ldr r3, [r6, #0] + 9dbe: 4604 mov r4, r0 + 9dc0: 07df lsls r7, r3, #31 + 9dc2: d463 bmi.n 9e8c <_SsiWriteInterrupt+0xdc> + 9dc4: f648 3391 movw r3, #35729 ; 0x8b91 + 9dc8: 4620 mov r0, r4 + 9dca: f2c0 0300 movt r3, #0 + 9dce: 4798 blx r3 + 9dd0: 6f65 ldr r5, [r4, #116] ; 0x74 + 9dd2: f894 7084 ldrb.w r7, [r4, #132] ; 0x84 + 9dd6: b9b0 cbnz r0, 9e06 <_SsiWriteInterrupt+0x56> + 9dd8: 6f23 ldr r3, [r4, #112] ; 0x70 + 9dda: b10b cbz r3, 9de0 <_SsiWriteInterrupt+0x30> + 9ddc: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + 9de0: f248 5321 movw r3, #34081 ; 0x8521 + 9de4: f894 2085 ldrb.w r2, [r4, #133] ; 0x85 + 9de8: f2c0 0300 movt r3, #0 + 9dec: f022 0203 bic.w r2, r2, #3 + 9df0: f884 2085 strb.w r2, [r4, #133] ; 0x85 + 9df4: 4620 mov r0, r4 + 9df6: 4798 blx r3 + 9df8: 6ce3 ldr r3, [r4, #76] ; 0x4c + 9dfa: 2b00 cmp r3, #0 + 9dfc: d0ee beq.n 9ddc <_SsiWriteInterrupt+0x2c> + 9dfe: 6d20 ldr r0, [r4, #80] ; 0x50 + 9e00: e8bd 47f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, lr} + 9e04: 4718 bx r3 + 9e06: f248 5821 movw r8, #34081 ; 0x8521 + 9e0a: f240 3a10 movw sl, #784 ; 0x310 + 9e0e: f24f 399d movw r9, #62365 ; 0xf39d + 9e12: f894 3085 ldrb.w r3, [r4, #133] ; 0x85 + 9e16: f2c0 0800 movt r8, #0 + 9e1a: f023 0301 bic.w r3, r3, #1 + 9e1e: f884 3085 strb.w r3, [r4, #133] ; 0x85 + 9e22: 4620 mov r0, r4 + 9e24: 47c0 blx r8 + 9e26: f2c1 0a00 movt sl, #4096 ; 0x1000 + 9e2a: f2c0 0900 movt r9, #0 + 9e2e: f507 1780 add.w r7, r7, #1048576 ; 0x100000 + 9e32: f507 7784 add.w r7, r7, #264 ; 0x108 + 9e36: 02bf lsls r7, r7, #10 + 9e38: f1c5 0540 rsb r5, r5, #64 ; 0x40 + 9e3c: 3760 adds r7, #96 ; 0x60 + 9e3e: b17d cbz r5, 9e60 <_SsiWriteInterrupt+0xb0> + 9e40: 6d61 ldr r1, [r4, #84] ; 0x54 + 9e42: 3d01 subs r5, #1 + 9e44: f851 3b04 ldr.w r3, [r1], #4 + 9e48: b29b uxth r3, r3 + 9e4a: 603b str r3, [r7, #0] + 9e4c: 6f22 ldr r2, [r4, #112] ; 0x70 + 9e4e: 6833 ldr r3, [r6, #0] + 9e50: 6838 ldr r0, [r7, #0] + 9e52: 3a01 subs r2, #1 + 9e54: 0558 lsls r0, r3, #21 + 9e56: 6561 str r1, [r4, #84] ; 0x54 + 9e58: 6722 str r2, [r4, #112] ; 0x70 + 9e5a: d40a bmi.n 9e72 <_SsiWriteInterrupt+0xc2> + 9e5c: 2a00 cmp r2, #0 + 9e5e: d1ee bne.n 9e3e <_SsiWriteInterrupt+0x8e> + 9e60: f894 3085 ldrb.w r3, [r4, #133] ; 0x85 + 9e64: 4620 mov r0, r4 + 9e66: f043 0301 orr.w r3, r3, #1 + 9e6a: f884 3085 strb.w r3, [r4, #133] ; 0x85 + 9e6e: 47c0 blx r8 + 9e70: e7b2 b.n 9dd8 <_SsiWriteInterrupt+0x28> + 9e72: f8da 3000 ldr.w r3, [sl] + 9e76: 051b lsls r3, r3, #20 + 9e78: d5f0 bpl.n 9e5c <_SsiWriteInterrupt+0xac> + 9e7a: f641 2048 movw r0, #6728 ; 0x1a48 + 9e7e: f2c0 0004 movt r0, #4 + 9e82: 47c8 blx r9 + 9e84: 6f22 ldr r2, [r4, #112] ; 0x70 + 9e86: 2a00 cmp r2, #0 + 9e88: d1d9 bne.n 9e3e <_SsiWriteInterrupt+0x8e> + 9e8a: e7e9 b.n 9e60 <_SsiWriteInterrupt+0xb0> + 9e8c: f240 3310 movw r3, #784 ; 0x310 + 9e90: f2c1 0300 movt r3, #4096 ; 0x1000 + 9e94: 681b ldr r3, [r3, #0] + 9e96: 051d lsls r5, r3, #20 + 9e98: d594 bpl.n 9dc4 <_SsiWriteInterrupt+0x14> + 9e9a: f641 2018 movw r0, #6680 ; 0x1a18 + 9e9e: f24f 339d movw r3, #62365 ; 0xf39d + 9ea2: f2c0 0004 movt r0, #4 + 9ea6: f2c0 0300 movt r3, #0 + 9eaa: 4798 blx r3 + 9eac: e78a b.n 9dc4 <_SsiWriteInterrupt+0x14> + 9eae: bf00 nop + +00009eb0 <_SsiIrqHandle>: + 9eb0: b5f8 push {r3, r4, r5, r6, r7, lr} + 9eb2: f240 3450 movw r4, #848 ; 0x350 + 9eb6: f2c1 0400 movt r4, #4096 ; 0x1000 + 9eba: 6823 ldr r3, [r4, #0] + 9ebc: 4606 mov r6, r0 + 9ebe: 07d8 lsls r0, r3, #31 + 9ec0: f100 80a9 bmi.w a016 <_SsiIrqHandle+0x166> + 9ec4: f249 03d9 movw r3, #37081 ; 0x90d9 + 9ec8: 4630 mov r0, r6 + 9eca: f2c0 0300 movt r3, #0 + 9ece: 4798 blx r3 + 9ed0: 0782 lsls r2, r0, #30 + 9ed2: 4605 mov r5, r0 + 9ed4: f896 7084 ldrb.w r7, [r6, #132] ; 0x84 + 9ed8: d509 bpl.n 9eee <_SsiIrqHandle+0x3e> + 9eda: 6823 ldr r3, [r4, #0] + 9edc: 05db lsls r3, r3, #23 + 9ede: f100 8087 bmi.w 9ff0 <_SsiIrqHandle+0x140> + 9ee2: f507 1380 add.w r3, r7, #1048576 ; 0x100000 + 9ee6: f503 7384 add.w r3, r3, #264 ; 0x108 + 9eea: 029b lsls r3, r3, #10 + 9eec: 6b9b ldr r3, [r3, #56] ; 0x38 + 9eee: 0769 lsls r1, r5, #29 + 9ef0: d508 bpl.n 9f04 <_SsiIrqHandle+0x54> + 9ef2: 6823 ldr r3, [r4, #0] + 9ef4: 05da lsls r2, r3, #23 + 9ef6: d469 bmi.n 9fcc <_SsiIrqHandle+0x11c> + 9ef8: f507 1380 add.w r3, r7, #1048576 ; 0x100000 + 9efc: f503 7384 add.w r3, r3, #264 ; 0x108 + 9f00: 029b lsls r3, r3, #10 + 9f02: 6c1b ldr r3, [r3, #64] ; 0x40 + 9f04: 0728 lsls r0, r5, #28 + 9f06: d508 bpl.n 9f1a <_SsiIrqHandle+0x6a> + 9f08: 6823 ldr r3, [r4, #0] + 9f0a: 05d9 lsls r1, r3, #23 + 9f0c: d44c bmi.n 9fa8 <_SsiIrqHandle+0xf8> + 9f0e: f507 1380 add.w r3, r7, #1048576 ; 0x100000 + 9f12: f503 7384 add.w r3, r3, #264 ; 0x108 + 9f16: 029b lsls r3, r3, #10 + 9f18: 6bdb ldr r3, [r3, #60] ; 0x3c + 9f1a: 06ab lsls r3, r5, #26 + 9f1c: d508 bpl.n 9f30 <_SsiIrqHandle+0x80> + 9f1e: 6823 ldr r3, [r4, #0] + 9f20: 05d8 lsls r0, r3, #23 + 9f22: d42f bmi.n 9f84 <_SsiIrqHandle+0xd4> + 9f24: f507 1380 add.w r3, r7, #1048576 ; 0x100000 + 9f28: f503 7384 add.w r3, r3, #264 ; 0x108 + 9f2c: 029b lsls r3, r3, #10 + 9f2e: 6c5b ldr r3, [r3, #68] ; 0x44 + 9f30: 06ea lsls r2, r5, #27 + 9f32: d508 bpl.n 9f46 <_SsiIrqHandle+0x96> + 9f34: 6823 ldr r3, [r4, #0] + 9f36: 05db lsls r3, r3, #23 + 9f38: d412 bmi.n 9f60 <_SsiIrqHandle+0xb0> + 9f3a: f649 33a5 movw r3, #39845 ; 0x9ba5 + 9f3e: 4630 mov r0, r6 + 9f40: f2c0 0300 movt r3, #0 + 9f44: 4798 blx r3 + 9f46: 07e9 lsls r1, r5, #31 + 9f48: d508 bpl.n 9f5c <_SsiIrqHandle+0xac> + 9f4a: 6823 ldr r3, [r4, #0] + 9f4c: 05da lsls r2, r3, #23 + 9f4e: d474 bmi.n a03a <_SsiIrqHandle+0x18a> + 9f50: f649 53b1 movw r3, #40369 ; 0x9db1 + 9f54: 4630 mov r0, r6 + 9f56: f2c0 0300 movt r3, #0 + 9f5a: 4798 blx r3 + 9f5c: 2000 movs r0, #0 + 9f5e: bdf8 pop {r3, r4, r5, r6, r7, pc} + 9f60: f240 3310 movw r3, #784 ; 0x310 + 9f64: f2c1 0300 movt r3, #4096 ; 0x1000 + 9f68: 681b ldr r3, [r3, #0] + 9f6a: 0518 lsls r0, r3, #20 + 9f6c: d5e5 bpl.n 9f3a <_SsiIrqHandle+0x8a> + 9f6e: f641 30a0 movw r0, #7072 ; 0x1ba0 + 9f72: f24f 339d movw r3, #62365 ; 0xf39d + 9f76: 4639 mov r1, r7 + 9f78: f2c0 0300 movt r3, #0 + 9f7c: f2c0 0004 movt r0, #4 + 9f80: 4798 blx r3 + 9f82: e7da b.n 9f3a <_SsiIrqHandle+0x8a> + 9f84: f240 3310 movw r3, #784 ; 0x310 + 9f88: f2c1 0300 movt r3, #4096 ; 0x1000 + 9f8c: 681b ldr r3, [r3, #0] + 9f8e: 0519 lsls r1, r3, #20 + 9f90: d5c8 bpl.n 9f24 <_SsiIrqHandle+0x74> + 9f92: f641 3060 movw r0, #7008 ; 0x1b60 + 9f96: f24f 339d movw r3, #62365 ; 0xf39d + 9f9a: 4639 mov r1, r7 + 9f9c: f2c0 0300 movt r3, #0 + 9fa0: f2c0 0004 movt r0, #4 + 9fa4: 4798 blx r3 + 9fa6: e7bd b.n 9f24 <_SsiIrqHandle+0x74> + 9fa8: f240 3310 movw r3, #784 ; 0x310 + 9fac: f2c1 0300 movt r3, #4096 ; 0x1000 + 9fb0: 681b ldr r3, [r3, #0] + 9fb2: 051a lsls r2, r3, #20 + 9fb4: d5ab bpl.n 9f0e <_SsiIrqHandle+0x5e> + 9fb6: f641 3020 movw r0, #6944 ; 0x1b20 + 9fba: f24f 339d movw r3, #62365 ; 0xf39d + 9fbe: 4639 mov r1, r7 + 9fc0: f2c0 0300 movt r3, #0 + 9fc4: f2c0 0004 movt r0, #4 + 9fc8: 4798 blx r3 + 9fca: e7a0 b.n 9f0e <_SsiIrqHandle+0x5e> + 9fcc: f240 3310 movw r3, #784 ; 0x310 + 9fd0: f2c1 0300 movt r3, #4096 ; 0x1000 + 9fd4: 681b ldr r3, [r3, #0] + 9fd6: 051b lsls r3, r3, #20 + 9fd8: d58e bpl.n 9ef8 <_SsiIrqHandle+0x48> + 9fda: f641 20e0 movw r0, #6880 ; 0x1ae0 + 9fde: f24f 339d movw r3, #62365 ; 0xf39d + 9fe2: 4639 mov r1, r7 + 9fe4: f2c0 0300 movt r3, #0 + 9fe8: f2c0 0004 movt r0, #4 + 9fec: 4798 blx r3 + 9fee: e783 b.n 9ef8 <_SsiIrqHandle+0x48> + 9ff0: f240 3310 movw r3, #784 ; 0x310 + 9ff4: f2c1 0300 movt r3, #4096 ; 0x1000 + 9ff8: 681b ldr r3, [r3, #0] + 9ffa: 0518 lsls r0, r3, #20 + 9ffc: f57f af71 bpl.w 9ee2 <_SsiIrqHandle+0x32> + a000: f641 20a0 movw r0, #6816 ; 0x1aa0 + a004: f24f 339d movw r3, #62365 ; 0xf39d + a008: 4639 mov r1, r7 + a00a: f2c0 0300 movt r3, #0 + a00e: f2c0 0004 movt r0, #4 + a012: 4798 blx r3 + a014: e765 b.n 9ee2 <_SsiIrqHandle+0x32> + a016: f240 3310 movw r3, #784 ; 0x310 + a01a: f2c1 0300 movt r3, #4096 ; 0x1000 + a01e: 681b ldr r3, [r3, #0] + a020: 0519 lsls r1, r3, #20 + a022: f57f af4f bpl.w 9ec4 <_SsiIrqHandle+0x14> + a026: f641 2074 movw r0, #6772 ; 0x1a74 + a02a: f24f 339d movw r3, #62365 ; 0xf39d + a02e: f2c0 0004 movt r0, #4 + a032: f2c0 0300 movt r3, #0 + a036: 4798 blx r3 + a038: e744 b.n 9ec4 <_SsiIrqHandle+0x14> + a03a: f240 3310 movw r3, #784 ; 0x310 + a03e: f2c1 0300 movt r3, #4096 ; 0x1000 + a042: 681b ldr r3, [r3, #0] + a044: 051b lsls r3, r3, #20 + a046: d583 bpl.n 9f50 <_SsiIrqHandle+0xa0> + a048: f641 30dc movw r0, #7132 ; 0x1bdc + a04c: f24f 339d movw r3, #62365 ; 0xf39d + a050: 4639 mov r1, r7 + a052: f2c0 0300 movt r3, #0 + a056: f2c0 0004 movt r0, #4 + a05a: 4798 blx r3 + a05c: e778 b.n 9f50 <_SsiIrqHandle+0xa0> + a05e: bf00 nop + +0000a060 : + a060: 2803 cmp r0, #3 + a062: d808 bhi.n a076 + a064: e8df f000 tbb [pc, r0] + a068: 02080e14 .word 0x02080e14 + a06c: f101 4180 add.w r1, r1, #1073741824 ; 0x40000000 + a070: f501 5160 add.w r1, r1, #14336 ; 0x3800 + a074: 600a str r2, [r1, #0] + a076: 4770 bx lr + a078: f101 4180 add.w r1, r1, #1073741824 ; 0x40000000 + a07c: f501 5150 add.w r1, r1, #13312 ; 0x3400 + a080: 600a str r2, [r1, #0] + a082: 4770 bx lr + a084: f44f 4388 mov.w r3, #17408 ; 0x4400 + a088: f2c4 0304 movt r3, #16388 ; 0x4004 + a08c: 50ca str r2, [r1, r3] + a08e: 4770 bx lr + a090: f101 2140 add.w r1, r1, #1073758208 ; 0x40004000 + a094: f501 2180 add.w r1, r1, #262144 ; 0x40000 + a098: 600a str r2, [r1, #0] + a09a: 4770 bx lr + +0000a09c : + a09c: 2803 cmp r0, #3 + a09e: d81b bhi.n a0d8 + a0a0: e8df f000 tbb [pc, r0] + a0a4: 02080e14 .word 0x02080e14 + a0a8: f101 4180 add.w r1, r1, #1073741824 ; 0x40000000 + a0ac: f501 5160 add.w r1, r1, #14336 ; 0x3800 + a0b0: 6808 ldr r0, [r1, #0] + a0b2: 4770 bx lr + a0b4: f101 4180 add.w r1, r1, #1073741824 ; 0x40000000 + a0b8: f501 5150 add.w r1, r1, #13312 ; 0x3400 + a0bc: 6808 ldr r0, [r1, #0] + a0be: 4770 bx lr + a0c0: f44f 4388 mov.w r3, #17408 ; 0x4400 + a0c4: f2c4 0304 movt r3, #16388 ; 0x4004 + a0c8: 58c8 ldr r0, [r1, r3] + a0ca: 4770 bx lr + a0cc: f101 2140 add.w r1, r1, #1073758208 ; 0x40004000 + a0d0: f501 2180 add.w r1, r1, #262144 ; 0x40000 + a0d4: 6808 ldr r0, [r1, #0] + a0d6: 4770 bx lr + a0d8: 2000 movs r0, #0 + a0da: 4770 bx lr + +0000a0dc : + a0dc: f24a 0361 movw r3, #41057 ; 0xa061 + a0e0: b510 push {r4, lr} + a0e2: 7804 ldrb r4, [r0, #0] + a0e4: f2c0 0300 movt r3, #0 + a0e8: 4620 mov r0, r4 + a0ea: 216c movs r1, #108 ; 0x6c + a0ec: 2200 movs r2, #0 + a0ee: 4798 blx r3 + a0f0: 2c03 cmp r4, #3 + a0f2: d820 bhi.n a136 + a0f4: e8df f004 tbb [pc, r4] + a0f8: 213f5d02 .word 0x213f5d02 + a0fc: f240 3310 movw r3, #784 ; 0x310 + a100: f2c1 0300 movt r3, #4096 ; 0x1000 + a104: 681b ldr r3, [r3, #0] + a106: 06d8 lsls r0, r3, #27 + a108: d515 bpl.n a136 + a10a: f24a 039d movw r3, #41117 ; 0xa09d + a10e: 216c movs r1, #108 ; 0x6c + a110: f2c0 0300 movt r3, #0 + a114: 2000 movs r0, #0 + a116: 4798 blx r3 + a118: f24f 349d movw r4, #62365 ; 0xf39d + a11c: 4603 mov r3, r0 + a11e: f244 026c movw r2, #16492 ; 0x406c + a122: f641 4018 movw r0, #7192 ; 0x1c18 + a126: f2c4 0204 movt r2, #16388 ; 0x4004 + a12a: f2c0 0004 movt r0, #4 + a12e: f2c0 0400 movt r4, #0 + a132: 2100 movs r1, #0 + a134: 47a0 blx r4 + a136: 2000 movs r0, #0 + a138: bd10 pop {r4, pc} + a13a: f240 3310 movw r3, #784 ; 0x310 + a13e: f2c1 0300 movt r3, #4096 ; 0x1000 + a142: 681b ldr r3, [r3, #0] + a144: 06db lsls r3, r3, #27 + a146: d5f6 bpl.n a136 + a148: f24a 039d movw r3, #41117 ; 0xa09d + a14c: 216c movs r1, #108 ; 0x6c + a14e: f2c0 0300 movt r3, #0 + a152: 2003 movs r0, #3 + a154: 4798 blx r3 + a156: f24f 349d movw r4, #62365 ; 0xf39d + a15a: 4603 mov r3, r0 + a15c: f643 026c movw r2, #14444 ; 0x386c + a160: f641 4018 movw r0, #7192 ; 0x1c18 + a164: f2c4 0200 movt r2, #16384 ; 0x4000 + a168: f2c0 0400 movt r4, #0 + a16c: 2103 movs r1, #3 + a16e: f2c0 0004 movt r0, #4 + a172: 47a0 blx r4 + a174: e7df b.n a136 + a176: f240 3310 movw r3, #784 ; 0x310 + a17a: f2c1 0300 movt r3, #4096 ; 0x1000 + a17e: 681b ldr r3, [r3, #0] + a180: 06da lsls r2, r3, #27 + a182: d5d8 bpl.n a136 + a184: f24a 039d movw r3, #41117 ; 0xa09d + a188: 216c movs r1, #108 ; 0x6c + a18a: f2c0 0300 movt r3, #0 + a18e: 2002 movs r0, #2 + a190: 4798 blx r3 + a192: f24f 349d movw r4, #62365 ; 0xf39d + a196: 4603 mov r3, r0 + a198: f243 426c movw r2, #13420 ; 0x346c + a19c: f641 4018 movw r0, #7192 ; 0x1c18 + a1a0: f2c4 0200 movt r2, #16384 ; 0x4000 + a1a4: f2c0 0400 movt r4, #0 + a1a8: 2102 movs r1, #2 + a1aa: f2c0 0004 movt r0, #4 + a1ae: 47a0 blx r4 + a1b0: e7c1 b.n a136 + a1b2: f240 3310 movw r3, #784 ; 0x310 + a1b6: f2c1 0300 movt r3, #4096 ; 0x1000 + a1ba: 681b ldr r3, [r3, #0] + a1bc: 06d9 lsls r1, r3, #27 + a1be: d5ba bpl.n a136 + a1c0: f24a 039d movw r3, #41117 ; 0xa09d + a1c4: 216c movs r1, #108 ; 0x6c + a1c6: f2c0 0300 movt r3, #0 + a1ca: 2001 movs r0, #1 + a1cc: 4798 blx r3 + a1ce: f24f 349d movw r4, #62365 ; 0xf39d + a1d2: 4603 mov r3, r0 + a1d4: f244 426c movw r2, #17516 ; 0x446c + a1d8: f641 4018 movw r0, #7192 ; 0x1c18 + a1dc: f2c4 0204 movt r2, #16388 ; 0x4004 + a1e0: f2c0 0400 movt r4, #0 + a1e4: 2101 movs r1, #1 + a1e6: f2c0 0004 movt r0, #4 + a1ea: 47a0 blx r4 + a1ec: e7a3 b.n a136 + a1ee: bf00 nop + a1f0: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} + a1f4: f240 3410 movw r4, #784 ; 0x310 + a1f8: f2c1 0400 movt r4, #4096 ; 0x1000 + a1fc: 6822 ldr r2, [r4, #0] + a1fe: 7805 ldrb r5, [r0, #0] + a200: 06d2 lsls r2, r2, #27 + a202: 6946 ldr r6, [r0, #20] + a204: 7b87 ldrb r7, [r0, #14] + a206: f890 8011 ldrb.w r8, [r0, #17] + a20a: d413 bmi.n a234 + a20c: f24a 0361 movw r3, #41057 ; 0xa061 + a210: f008 0801 and.w r8, r8, #1 + a214: 7831 ldrb r1, [r6, #0] + a216: ea4f 2848 mov.w r8, r8, lsl #9 + a21a: f007 0701 and.w r7, r7, #1 + a21e: ea48 2207 orr.w r2, r8, r7, lsl #8 + a222: 430a orrs r2, r1 + a224: 4628 mov r0, r5 + a226: f2c0 0300 movt r3, #0 + a22a: 2110 movs r1, #16 + a22c: 4798 blx r3 + a22e: 2000 movs r0, #0 + a230: e8bd 83f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} + a234: f641 4040 movw r0, #7232 ; 0x1c40 + a238: f24f 399d movw r9, #62365 ; 0xf39d + a23c: f2c0 0004 movt r0, #4 + a240: f2c0 0900 movt r9, #0 + a244: 47c8 blx r9 + a246: 6823 ldr r3, [r4, #0] + a248: 06db lsls r3, r3, #27 + a24a: d5df bpl.n a20c + a24c: f641 4060 movw r0, #7264 ; 0x1c60 + a250: 4629 mov r1, r5 + a252: f2c0 0004 movt r0, #4 + a256: 47c8 blx r9 + a258: e7d8 b.n a20c + a25a: bf00 nop + +0000a25c : + a25c: b508 push {r3, lr} + a25e: f24a 039d movw r3, #41117 ; 0xa09d + a262: 2110 movs r1, #16 + a264: f2c0 0300 movt r3, #0 + a268: 7800 ldrb r0, [r0, #0] + a26a: 4798 blx r3 + a26c: b2c0 uxtb r0, r0 + a26e: bd08 pop {r3, pc} + +0000a270 : + a270: f24a 0361 movw r3, #41057 ; 0xa061 + a274: b510 push {r4, lr} + a276: 7804 ldrb r4, [r0, #0] + a278: 7842 ldrb r2, [r0, #1] + a27a: f2c0 0300 movt r3, #0 + a27e: 4620 mov r0, r4 + a280: f002 0201 and.w r2, r2, #1 + a284: 216c movs r1, #108 ; 0x6c + a286: 4798 blx r3 + a288: 2c03 cmp r4, #3 + a28a: d820 bhi.n a2ce + a28c: e8df f004 tbb [pc, r4] + a290: 213f5d02 .word 0x213f5d02 + a294: f240 3310 movw r3, #784 ; 0x310 + a298: f2c1 0300 movt r3, #4096 ; 0x1000 + a29c: 681b ldr r3, [r3, #0] + a29e: 06d8 lsls r0, r3, #27 + a2a0: d515 bpl.n a2ce + a2a2: f24a 039d movw r3, #41117 ; 0xa09d + a2a6: 216c movs r1, #108 ; 0x6c + a2a8: f2c0 0300 movt r3, #0 + a2ac: 2000 movs r0, #0 + a2ae: 4798 blx r3 + a2b0: f24f 349d movw r4, #62365 ; 0xf39d + a2b4: 4603 mov r3, r0 + a2b6: f244 026c movw r2, #16492 ; 0x406c + a2ba: f641 4018 movw r0, #7192 ; 0x1c18 + a2be: f2c4 0204 movt r2, #16388 ; 0x4004 + a2c2: f2c0 0004 movt r0, #4 + a2c6: f2c0 0400 movt r4, #0 + a2ca: 2100 movs r1, #0 + a2cc: 47a0 blx r4 + a2ce: 2000 movs r0, #0 + a2d0: bd10 pop {r4, pc} + a2d2: f240 3310 movw r3, #784 ; 0x310 + a2d6: f2c1 0300 movt r3, #4096 ; 0x1000 + a2da: 681b ldr r3, [r3, #0] + a2dc: 06db lsls r3, r3, #27 + a2de: d5f6 bpl.n a2ce + a2e0: f24a 039d movw r3, #41117 ; 0xa09d + a2e4: 216c movs r1, #108 ; 0x6c + a2e6: f2c0 0300 movt r3, #0 + a2ea: 2003 movs r0, #3 + a2ec: 4798 blx r3 + a2ee: f24f 349d movw r4, #62365 ; 0xf39d + a2f2: 4603 mov r3, r0 + a2f4: f643 026c movw r2, #14444 ; 0x386c + a2f8: f641 4018 movw r0, #7192 ; 0x1c18 + a2fc: f2c4 0200 movt r2, #16384 ; 0x4000 + a300: f2c0 0400 movt r4, #0 + a304: 2103 movs r1, #3 + a306: f2c0 0004 movt r0, #4 + a30a: 47a0 blx r4 + a30c: e7df b.n a2ce + a30e: f240 3310 movw r3, #784 ; 0x310 + a312: f2c1 0300 movt r3, #4096 ; 0x1000 + a316: 681b ldr r3, [r3, #0] + a318: 06da lsls r2, r3, #27 + a31a: d5d8 bpl.n a2ce + a31c: f24a 039d movw r3, #41117 ; 0xa09d + a320: 216c movs r1, #108 ; 0x6c + a322: f2c0 0300 movt r3, #0 + a326: 2002 movs r0, #2 + a328: 4798 blx r3 + a32a: f24f 349d movw r4, #62365 ; 0xf39d + a32e: 4603 mov r3, r0 + a330: f243 426c movw r2, #13420 ; 0x346c + a334: f641 4018 movw r0, #7192 ; 0x1c18 + a338: f2c4 0200 movt r2, #16384 ; 0x4000 + a33c: f2c0 0400 movt r4, #0 + a340: 2102 movs r1, #2 + a342: f2c0 0004 movt r0, #4 + a346: 47a0 blx r4 + a348: e7c1 b.n a2ce + a34a: f240 3310 movw r3, #784 ; 0x310 + a34e: f2c1 0300 movt r3, #4096 ; 0x1000 + a352: 681b ldr r3, [r3, #0] + a354: 06d9 lsls r1, r3, #27 + a356: d5ba bpl.n a2ce + a358: f24a 039d movw r3, #41117 ; 0xa09d + a35c: 216c movs r1, #108 ; 0x6c + a35e: f2c0 0300 movt r3, #0 + a362: 2001 movs r0, #1 + a364: 4798 blx r3 + a366: f24f 349d movw r4, #62365 ; 0xf39d + a36a: 4603 mov r3, r0 + a36c: f244 426c movw r2, #17516 ; 0x446c + a370: f641 4018 movw r0, #7192 ; 0x1c18 + a374: f2c4 0204 movt r2, #16388 ; 0x4004 + a378: f2c0 0400 movt r4, #0 + a37c: 2101 movs r1, #1 + a37e: f2c0 0004 movt r0, #4 + a382: 47a0 blx r4 + a384: e7a3 b.n a2ce + a386: bf00 nop + +0000a388 : + a388: b508 push {r3, lr} + a38a: 4602 mov r2, r0 + a38c: f24a 0361 movw r3, #41057 ; 0xa061 + a390: 7800 ldrb r0, [r0, #0] + a392: 8b12 ldrh r2, [r2, #24] + a394: f2c0 0300 movt r3, #0 + a398: 2130 movs r1, #48 ; 0x30 + a39a: 4798 blx r3 + a39c: 2000 movs r0, #0 + a39e: bd08 pop {r3, pc} + +0000a3a0 : + a3a0: b508 push {r3, lr} + a3a2: f24a 039d movw r3, #41117 ; 0xa09d + a3a6: 7800 ldrb r0, [r0, #0] + a3a8: f2c0 0300 movt r3, #0 + a3ac: 4798 blx r3 + a3ae: bd08 pop {r3, pc} + +0000a3b0 : + a3b0: b508 push {r3, lr} + a3b2: f24a 0361 movw r3, #41057 ; 0xa061 + a3b6: 7800 ldrb r0, [r0, #0] + a3b8: f2c0 0300 movt r3, #0 + a3bc: 4798 blx r3 + a3be: 2000 movs r0, #0 + a3c0: bd08 pop {r3, pc} + a3c2: bf00 nop + a3c4: f44f 7314 mov.w r3, #592 ; 0x250 + a3c8: f2c4 0300 movt r3, #16384 ; 0x4000 + a3cc: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} + a3d0: 6a07 ldr r7, [r0, #32] + a3d2: 6819 ldr r1, [r3, #0] + a3d4: 1e7c subs r4, r7, #1 + a3d6: f5b4 7fc8 cmp.w r4, #400 ; 0x190 + a3da: 7902 ldrb r2, [r0, #4] + a3dc: bf34 ite cc + a3de: f441 3140 orrcc.w r1, r1, #196608 ; 0x30000 + a3e2: f421 3140 biccs.w r1, r1, #196608 ; 0x30000 + a3e6: 7806 ldrb r6, [r0, #0] + a3e8: bf39 ittee cc + a3ea: f04f 080c movcc.w r8, #12 + a3ee: 6019 strcc r1, [r3, #0] + a3f0: 6019 strcs r1, [r3, #0] + a3f2: f04f 0864 movcs.w r8, #100 ; 0x64 + a3f6: 2a02 cmp r2, #2 + a3f8: f000 80cc beq.w a594 + a3fc: 2a03 cmp r2, #3 + a3fe: d057 beq.n a4b0 + a400: 2a01 cmp r2, #1 + a402: d002 beq.n a40a + a404: 2000 movs r0, #0 + a406: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + a40a: f244 2140 movw r1, #16960 ; 0x4240 + a40e: f2c0 010f movt r1, #15 + a412: f245 3337 movw r3, #21303 ; 0x5337 + a416: f644 52d3 movw r2, #19923 ; 0x4dd3 + a41a: f240 3510 movw r5, #784 ; 0x310 + a41e: fbb1 f7f7 udiv r7, r1, r7 + a422: f6c3 4343 movt r3, #15427 ; 0x3c43 + a426: f241 205c movw r0, #4700 ; 0x125c + a42a: f2c1 0262 movt r2, #4194 ; 0x1062 + a42e: f24a 0461 movw r4, #41057 ; 0xa061 + a432: f2c1 0500 movt r5, #4096 ; 0x1000 + a436: f44f 617a mov.w r1, #4000 ; 0xfa0 + a43a: fb01 f107 mul.w r1, r1, r7 + a43e: fba3 e101 umull lr, r1, r3, r1 + a442: 0ac9 lsrs r1, r1, #11 + a444: fb01 f108 mul.w r1, r1, r8 + a448: fb00 f707 mul.w r7, r0, r7 + a44c: fba2 0201 umull r0, r2, r2, r1 + a450: f2c0 0400 movt r4, #0 + a454: fba3 1707 umull r1, r7, r3, r7 + a458: 0992 lsrs r2, r2, #6 + a45a: 2114 movs r1, #20 + a45c: 4630 mov r0, r6 + a45e: 47a0 blx r4 + a460: 682b ldr r3, [r5, #0] + a462: 0aff lsrs r7, r7, #11 + a464: 06d9 lsls r1, r3, #27 + a466: f100 8117 bmi.w a698 + a46a: f644 52d3 movw r2, #19923 ; 0x4dd3 + a46e: f2c1 0262 movt r2, #4194 ; 0x1062 + a472: fb07 f808 mul.w r8, r7, r8 + a476: fba2 3208 umull r3, r2, r2, r8 + a47a: 4630 mov r0, r6 + a47c: 0992 lsrs r2, r2, #6 + a47e: 2118 movs r1, #24 + a480: 47a0 blx r4 + a482: 682b ldr r3, [r5, #0] + a484: 06da lsls r2, r3, #27 + a486: d5bd bpl.n a404 + a488: f24a 039d movw r3, #41117 ; 0xa09d + a48c: 4630 mov r0, r6 + a48e: f2c0 0300 movt r3, #0 + a492: 2118 movs r1, #24 + a494: 4798 blx r3 + a496: f24f 349d movw r4, #62365 ; 0xf39d + a49a: 4603 mov r3, r0 + a49c: f641 40a4 movw r0, #7332 ; 0x1ca4 + a4a0: 4631 mov r1, r6 + a4a2: f2c0 0400 movt r4, #0 + a4a6: 2218 movs r2, #24 + a4a8: f2c0 0004 movt r0, #4 + a4ac: 47a0 blx r4 + a4ae: e7a9 b.n a404 + a4b0: f24a 0461 movw r4, #41057 ; 0xa061 + a4b4: 4630 mov r0, r6 + a4b6: f2c0 0400 movt r4, #0 + a4ba: 2114 movs r1, #20 + a4bc: f44f 72c8 mov.w r2, #400 ; 0x190 + a4c0: 47a0 blx r4 + a4c2: 4630 mov r0, r6 + a4c4: 2118 movs r1, #24 + a4c6: f44f 72eb mov.w r2, #470 ; 0x1d6 + a4ca: 47a0 blx r4 + a4cc: 4630 mov r0, r6 + a4ce: 211c movs r1, #28 + a4d0: 223c movs r2, #60 ; 0x3c + a4d2: 47a0 blx r4 + a4d4: 4630 mov r0, r6 + a4d6: 2282 movs r2, #130 ; 0x82 + a4d8: 2120 movs r1, #32 + a4da: 47a0 blx r4 + a4dc: f244 2240 movw r2, #16960 ; 0x4240 + a4e0: f2c0 020f movt r2, #15 + a4e4: f646 4317 movw r3, #27671 ; 0x6c17 + a4e8: f240 3510 movw r5, #784 ; 0x310 + a4ec: fbb2 f7f7 udiv r7, r2, r7 + a4f0: f2c1 63c1 movt r3, #5825 ; 0x16c1 + a4f4: f2c1 0500 movt r5, #4096 ; 0x1000 + a4f8: ebc7 1707 rsb r7, r7, r7, lsl #4 + a4fc: ea4f 09c7 mov.w r9, r7, lsl #3 + a500: ea4f 0999 mov.w r9, r9, lsr #2 + a504: f027 4740 bic.w r7, r7, #3221225472 ; 0xc0000000 + a508: fba3 e909 umull lr, r9, r3, r9 + a50c: fba3 0707 umull r0, r7, r3, r7 + a510: 682a ldr r2, [r5, #0] + a512: ea4f 0999 mov.w r9, r9, lsr #2 + a516: 06d0 lsls r0, r2, #27 + a518: ea4f 0797 mov.w r7, r7, lsr #2 + a51c: f100 8093 bmi.w a646 + a520: f644 50d3 movw r0, #19923 ; 0x4dd3 + a524: f2c1 0062 movt r0, #4194 ; 0x1062 + a528: fb07 f208 mul.w r2, r7, r8 + a52c: fba0 1202 umull r1, r2, r0, r2 + a530: 0992 lsrs r2, r2, #6 + a532: 2a08 cmp r2, #8 + a534: bf88 it hi + a536: 3a03 subhi r2, #3 + a538: 4630 mov r0, r6 + a53a: 2124 movs r1, #36 ; 0x24 + a53c: 47a0 blx r4 + a53e: 682b ldr r3, [r5, #0] + a540: 06da lsls r2, r3, #27 + a542: f100 8095 bmi.w a670 + a546: f644 53d3 movw r3, #19923 ; 0x4dd3 + a54a: f2c1 0362 movt r3, #4194 ; 0x1062 + a54e: fb09 f208 mul.w r2, r9, r8 + a552: fba3 e202 umull lr, r2, r3, r2 + a556: 0992 lsrs r2, r2, #6 + a558: 2a06 cmp r2, #6 + a55a: bf88 it hi + a55c: 3a06 subhi r2, #6 + a55e: 4630 mov r0, r6 + a560: 2128 movs r1, #40 ; 0x28 + a562: 47a0 blx r4 + a564: 682b ldr r3, [r5, #0] + a566: 06db lsls r3, r3, #27 + a568: f57f af4c bpl.w a404 + a56c: f24a 039d movw r3, #41117 ; 0xa09d + a570: 4630 mov r0, r6 + a572: f2c0 0300 movt r3, #0 + a576: 2128 movs r1, #40 ; 0x28 + a578: 4798 blx r3 + a57a: f24f 349d movw r4, #62365 ; 0xf39d + a57e: 4603 mov r3, r0 + a580: f641 5074 movw r0, #7540 ; 0x1d74 + a584: 4631 mov r1, r6 + a586: f2c0 0400 movt r4, #0 + a58a: 2228 movs r2, #40 ; 0x28 + a58c: f2c0 0004 movt r0, #4 + a590: 47a0 blx r4 + a592: e737 b.n a404 + a594: f244 2240 movw r2, #16960 ; 0x4240 + a598: f2c0 020f movt r2, #15 + a59c: f643 2335 movw r3, #14901 ; 0x3a35 + a5a0: f644 51d3 movw r1, #19923 ; 0x4dd3 + a5a4: fbb2 f7f7 udiv r7, r2, r7 + a5a8: f2c4 43fc movt r3, #17660 ; 0x44fc + a5ac: f240 3510 movw r5, #784 ; 0x310 + a5b0: f2c1 0162 movt r1, #4194 ; 0x1062 + a5b4: f44f 7216 mov.w r2, #600 ; 0x258 + a5b8: f240 5014 movw r0, #1300 ; 0x514 + a5bc: fb02 f207 mul.w r2, r2, r7 + a5c0: fba3 4202 umull r4, r2, r3, r2 + a5c4: f24a 0461 movw r4, #41057 ; 0xa061 + a5c8: f2c1 0500 movt r5, #4096 ; 0x1000 + a5cc: 0a52 lsrs r2, r2, #9 + a5ce: fb02 f208 mul.w r2, r2, r8 + a5d2: fba1 e202 umull lr, r2, r1, r2 + a5d6: fb00 f707 mul.w r7, r0, r7 + a5da: 0992 lsrs r2, r2, #6 + a5dc: 2a04 cmp r2, #4 + a5de: fba3 0707 umull r0, r7, r3, r7 + a5e2: bf88 it hi + a5e4: 3a04 subhi r2, #4 + a5e6: f2c0 0400 movt r4, #0 + a5ea: 4630 mov r0, r6 + a5ec: 211c movs r1, #28 + a5ee: 47a0 blx r4 + a5f0: 682b ldr r3, [r5, #0] + a5f2: 0a7f lsrs r7, r7, #9 + a5f4: 06db lsls r3, r3, #27 + a5f6: d463 bmi.n a6c0 + a5f8: f644 51d3 movw r1, #19923 ; 0x4dd3 + a5fc: f2c1 0162 movt r1, #4194 ; 0x1062 + a600: fb07 f208 mul.w r2, r7, r8 + a604: fba1 3202 umull r3, r2, r1, r2 + a608: 0992 lsrs r2, r2, #6 + a60a: 2a03 cmp r2, #3 + a60c: bf88 it hi + a60e: 3a03 subhi r2, #3 + a610: 4630 mov r0, r6 + a612: 2120 movs r1, #32 + a614: 47a0 blx r4 + a616: 682b ldr r3, [r5, #0] + a618: 06dc lsls r4, r3, #27 + a61a: f57f aef3 bpl.w a404 + a61e: f24a 039d movw r3, #41117 ; 0xa09d + a622: 4630 mov r0, r6 + a624: f2c0 0300 movt r3, #0 + a628: 2120 movs r1, #32 + a62a: 4798 blx r3 + a62c: f24f 349d movw r4, #62365 ; 0xf39d + a630: 4603 mov r3, r0 + a632: f641 40f4 movw r0, #7412 ; 0x1cf4 + a636: 4631 mov r1, r6 + a638: f2c0 0400 movt r4, #0 + a63c: 2220 movs r2, #32 + a63e: f2c0 0004 movt r0, #4 + a642: 47a0 blx r4 + a644: e6de b.n a404 + a646: f641 501c movw r0, #7452 ; 0x1d1c + a64a: f24f 3a9d movw sl, #62365 ; 0xf39d + a64e: 4639 mov r1, r7 + a650: f2c0 0004 movt r0, #4 + a654: f2c0 0a00 movt sl, #0 + a658: 47d0 blx sl + a65a: 682b ldr r3, [r5, #0] + a65c: 06d9 lsls r1, r3, #27 + a65e: f57f af5f bpl.w a520 + a662: f641 5034 movw r0, #7476 ; 0x1d34 + a666: 4649 mov r1, r9 + a668: f2c0 0004 movt r0, #4 + a66c: 47d0 blx sl + a66e: e757 b.n a520 + a670: f24a 039d movw r3, #41117 ; 0xa09d + a674: 4630 mov r0, r6 + a676: f2c0 0300 movt r3, #0 + a67a: 2124 movs r1, #36 ; 0x24 + a67c: 4798 blx r3 + a67e: f24f 379d movw r7, #62365 ; 0xf39d + a682: 4603 mov r3, r0 + a684: f641 504c movw r0, #7500 ; 0x1d4c + a688: f2c0 0700 movt r7, #0 + a68c: 4631 mov r1, r6 + a68e: 2224 movs r2, #36 ; 0x24 + a690: f2c0 0004 movt r0, #4 + a694: 47b8 blx r7 + a696: e756 b.n a546 + a698: f24a 039d movw r3, #41117 ; 0xa09d + a69c: 4630 mov r0, r6 + a69e: f2c0 0300 movt r3, #0 + a6a2: 2114 movs r1, #20 + a6a4: 4798 blx r3 + a6a6: f24f 3c9d movw ip, #62365 ; 0xf39d + a6aa: 4603 mov r3, r0 + a6ac: f641 407c movw r0, #7292 ; 0x1c7c + a6b0: f2c0 0c00 movt ip, #0 + a6b4: 4631 mov r1, r6 + a6b6: 2214 movs r2, #20 + a6b8: f2c0 0004 movt r0, #4 + a6bc: 47e0 blx ip + a6be: e6d4 b.n a46a + a6c0: f24a 039d movw r3, #41117 ; 0xa09d + a6c4: 4630 mov r0, r6 + a6c6: f2c0 0300 movt r3, #0 + a6ca: 211c movs r1, #28 + a6cc: 4798 blx r3 + a6ce: f24f 3c9d movw ip, #62365 ; 0xf39d + a6d2: 4603 mov r3, r0 + a6d4: f641 40cc movw r0, #7372 ; 0x1ccc + a6d8: f2c0 0c00 movt ip, #0 + a6dc: 4631 mov r1, r6 + a6de: 221c movs r2, #28 + a6e0: f2c0 0004 movt r0, #4 + a6e4: 47e0 blx ip + a6e6: e787 b.n a5f8 + +0000a6e8 : + a6e8: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} + a6ec: 7bc5 ldrb r5, [r0, #15] + a6ee: 7807 ldrb r7, [r0, #0] + a6f0: f890 a00e ldrb.w sl, [r0, #14] + a6f4: f8d0 8014 ldr.w r8, [r0, #20] + a6f8: f890 b011 ldrb.w fp, [r0, #17] + a6fc: b30d cbz r5, a742 + a6fe: f24a 0661 movw r6, #41057 ; 0xa061 + a702: f1bb 0f00 cmp.w fp, #0 + a706: bf14 ite ne + a708: f44f 7b00 movne.w fp, #512 ; 0x200 + a70c: f04f 0b00 moveq.w fp, #0 + a710: f2c0 0600 movt r6, #0 + a714: f00a 0a01 and.w sl, sl, #1 + a718: ea4f 2a0a mov.w sl, sl, lsl #8 + a71c: f105 39ff add.w r9, r5, #4294967295 + a720: 2400 movs r4, #0 + a722: 454c cmp r4, r9 + a724: bf0c ite eq + a726: 465b moveq r3, fp + a728: 2300 movne r3, #0 + a72a: f818 2004 ldrb.w r2, [r8, r4] + a72e: 4638 mov r0, r7 + a730: ea42 020a orr.w r2, r2, sl + a734: 431a orrs r2, r3 + a736: 3401 adds r4, #1 + a738: 2110 movs r1, #16 + a73a: 47b0 blx r6 + a73c: b2e3 uxtb r3, r4 + a73e: 429d cmp r5, r3 + a740: d8ef bhi.n a722 + a742: 2000 movs r0, #0 + a744: e8bd 8ff8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +0000a748 : + a748: b508 push {r3, lr} + a74a: 4602 mov r2, r0 + a74c: f24a 039d movw r3, #41117 ; 0xa09d + a750: 7e91 ldrb r1, [r2, #26] + a752: f2c0 0300 movt r3, #0 + a756: 7800 ldrb r0, [r0, #0] + a758: 4798 blx r3 + a75a: 2000 movs r0, #0 + a75c: bd08 pop {r3, pc} + a75e: bf00 nop + +0000a760 : + a760: b508 push {r3, lr} + a762: f24a 039d movw r3, #41117 ; 0xa09d + a766: 2140 movs r1, #64 ; 0x40 + a768: f2c0 0300 movt r3, #0 + a76c: 7800 ldrb r0, [r0, #0] + a76e: 4798 blx r3 + a770: 2000 movs r0, #0 + a772: bd08 pop {r3, pc} + a774: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + a778: 4604 mov r4, r0 + a77a: f24a 0561 movw r5, #41057 ; 0xa061 + a77e: f894 e00a ldrb.w lr, [r4, #10] + a782: b08b sub sp, #44 ; 0x2c + a784: f8cd e018 str.w lr, [sp, #24] + a788: f894 e00c ldrb.w lr, [r4, #12] + a78c: 8ba7 ldrh r7, [r4, #28] + a78e: f8cd e024 str.w lr, [sp, #36] ; 0x24 + a792: f894 e006 ldrb.w lr, [r4, #6] + a796: 9702 str r7, [sp, #8] + a798: 8be7 ldrh r7, [r4, #30] + a79a: f8cd e00c str.w lr, [sp, #12] + a79e: f894 e007 ldrb.w lr, [r4, #7] + a7a2: 7806 ldrb r6, [r0, #0] + a7a4: 78e3 ldrb r3, [r4, #3] + a7a6: 9707 str r7, [sp, #28] + a7a8: 7967 ldrb r7, [r4, #5] + a7aa: f890 8002 ldrb.w r8, [r0, #2] + a7ae: f8cd e010 str.w lr, [sp, #16] + a7b2: f894 e024 ldrb.w lr, [r4, #36] ; 0x24 + a7b6: f894 9004 ldrb.w r9, [r4, #4] + a7ba: 9708 str r7, [sp, #32] + a7bc: f894 a00b ldrb.w sl, [r4, #11] + a7c0: 7a67 ldrb r7, [r4, #9] + a7c2: f894 b025 ldrb.w fp, [r4, #37] ; 0x25 + a7c6: 4630 mov r0, r6 + a7c8: 9301 str r3, [sp, #4] + a7ca: f2c0 0500 movt r5, #0 + a7ce: 216c movs r1, #108 ; 0x6c + a7d0: 2200 movs r2, #0 + a7d2: f8cd e014 str.w lr, [sp, #20] + a7d6: 47a8 blx r5 + a7d8: 9b01 ldr r3, [sp, #4] + a7da: f1b8 0f00 cmp.w r8, #0 + a7de: d06d beq.n a8bc + a7e0: 2b01 cmp r3, #1 + a7e2: bf18 it ne + a7e4: f1b9 0f03 cmpne.w r9, #3 + a7e8: bf1c itt ne + a7ea: f007 0701 andne.w r7, r7, #1 + a7ee: 0179 lslne r1, r7, #5 + a7f0: f240 3710 movw r7, #784 ; 0x310 + a7f4: f2c1 0700 movt r7, #4096 ; 0x1000 + a7f8: f008 0201 and.w r2, r8, #1 + a7fc: f042 0240 orr.w r2, r2, #64 ; 0x40 + a800: f003 0801 and.w r8, r3, #1 + a804: ea42 1208 orr.w r2, r2, r8, lsl #4 + a808: f009 0903 and.w r9, r9, #3 + a80c: bf08 it eq + a80e: 2120 moveq r1, #32 + a810: ea42 0249 orr.w r2, r2, r9, lsl #1 + a814: 430a orrs r2, r1 + a816: 4630 mov r0, r6 + a818: 2100 movs r1, #0 + a81a: 47a8 blx r5 + a81c: 683b ldr r3, [r7, #0] + a81e: 06d9 lsls r1, r3, #27 + a820: f100 80b6 bmi.w a990 + a824: 9b06 ldr r3, [sp, #24] + a826: f8dd e008 ldr.w lr, [sp, #8] + a82a: ea5a 0303 orrs.w r3, sl, r3 + a82e: f00a 0a01 and.w sl, sl, #1 + a832: ea4f 2a8a mov.w sl, sl, lsl #10 + a836: f3ce 0009 ubfx r0, lr, #0, #10 + a83a: ea4a 3808 orr.w r8, sl, r8, lsl #12 + a83e: bf14 ite ne + a840: f44f 6100 movne.w r1, #2048 ; 0x800 + a844: 2100 moveq r1, #0 + a846: ea48 0200 orr.w r2, r8, r0 + a84a: 430a orrs r2, r1 + a84c: 4630 mov r0, r6 + a84e: 2104 movs r1, #4 + a850: 47a8 blx r5 + a852: f24e 439d movw r3, #58525 ; 0xe49d + a856: 4620 mov r0, r4 + a858: f2c1 0303 movt r3, #4099 ; 0x1003 + a85c: 4798 blx r3 + a85e: 683b ldr r3, [r7, #0] + a860: 06da lsls r2, r3, #27 + a862: f100 8081 bmi.w a968 + a866: f240 3810 movw r8, #784 ; 0x310 + a86a: 9a04 ldr r2, [sp, #16] + a86c: 4630 mov r0, r6 + a86e: 213c movs r1, #60 ; 0x3c + a870: 47a8 blx r5 + a872: 4630 mov r0, r6 + a874: 9a03 ldr r2, [sp, #12] + a876: 2138 movs r1, #56 ; 0x38 + a878: 47a8 blx r5 + a87a: 4630 mov r0, r6 + a87c: 9a05 ldr r2, [sp, #20] + a87e: 218c movs r1, #140 ; 0x8c + a880: 47a8 blx r5 + a882: 465a mov r2, fp + a884: 4630 mov r0, r6 + a886: 2190 movs r1, #144 ; 0x90 + a888: 47a8 blx r5 + a88a: 683b ldr r3, [r7, #0] + a88c: f2c1 0800 movt r8, #4096 ; 0x1000 + a890: 06da lsls r2, r3, #27 + a892: d446 bmi.n a922 + a894: f24a 7361 movw r3, #42849 ; 0xa761 + a898: 4620 mov r0, r4 + a89a: f2c0 0300 movt r3, #0 + a89e: 4798 blx r3 + a8a0: f24a 3389 movw r3, #41865 ; 0xa389 + a8a4: 2500 movs r5, #0 + a8a6: 8b26 ldrh r6, [r4, #24] + a8a8: f2c0 0300 movt r3, #0 + a8ac: 8325 strh r5, [r4, #24] + a8ae: 4620 mov r0, r4 + a8b0: 4798 blx r3 + a8b2: 4628 mov r0, r5 + a8b4: 8326 strh r6, [r4, #24] + a8b6: b00b add sp, #44 ; 0x2c + a8b8: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + a8bc: f240 3710 movw r7, #784 ; 0x310 + a8c0: f2c1 0700 movt r7, #4096 ; 0x1000 + a8c4: f003 0301 and.w r3, r3, #1 + a8c8: 00db lsls r3, r3, #3 + a8ca: f009 0203 and.w r2, r9, #3 + a8ce: ea43 0242 orr.w r2, r3, r2, lsl #1 + a8d2: 4630 mov r0, r6 + a8d4: 4641 mov r1, r8 + a8d6: 47a8 blx r5 + a8d8: 683b ldr r3, [r7, #0] + a8da: 06db lsls r3, r3, #27 + a8dc: d46c bmi.n a9b8 + a8de: 9b02 ldr r3, [sp, #8] + a8e0: 4630 mov r0, r6 + a8e2: f3c3 0209 ubfx r2, r3, #0, #10 + a8e6: 2108 movs r1, #8 + a8e8: 47a8 blx r5 + a8ea: 683b ldr r3, [r7, #0] + a8ec: 06d8 lsls r0, r3, #27 + a8ee: d477 bmi.n a9e0 + a8f0: f8dd e024 ldr.w lr, [sp, #36] ; 0x24 + a8f4: 4630 mov r0, r6 + a8f6: f00e 0201 and.w r2, lr, #1 + a8fa: 2184 movs r1, #132 ; 0x84 + a8fc: 47a8 blx r5 + a8fe: 7c22 ldrb r2, [r4, #16] + a900: 2198 movs r1, #152 ; 0x98 + a902: 4630 mov r0, r6 + a904: f002 0201 and.w r2, r2, #1 + a908: 47a8 blx r5 + a90a: 683b ldr r3, [r7, #0] + a90c: 06d9 lsls r1, r3, #27 + a90e: d47b bmi.n aa08 + a910: 9a07 ldr r2, [sp, #28] + a912: 4630 mov r0, r6 + a914: 217c movs r1, #124 ; 0x7c + a916: 47a8 blx r5 + a918: 4630 mov r0, r6 + a91a: 9a08 ldr r2, [sp, #32] + a91c: 2194 movs r1, #148 ; 0x94 + a91e: 47a8 blx r5 + a920: e7a1 b.n a866 + a922: f24a 079d movw r7, #41117 ; 0xa09d + a926: 218c movs r1, #140 ; 0x8c + a928: 4630 mov r0, r6 + a92a: f2c0 0700 movt r7, #0 + a92e: 47b8 blx r7 + a930: f24f 359d movw r5, #62365 ; 0xf39d + a934: 4603 mov r3, r0 + a936: f641 6080 movw r0, #7808 ; 0x1e80 + a93a: f2c0 0500 movt r5, #0 + a93e: f2c0 0004 movt r0, #4 + a942: 4631 mov r1, r6 + a944: 228c movs r2, #140 ; 0x8c + a946: 47a8 blx r5 + a948: f8d8 3000 ldr.w r3, [r8] + a94c: 06db lsls r3, r3, #27 + a94e: d5a1 bpl.n a894 + a950: 4630 mov r0, r6 + a952: 2190 movs r1, #144 ; 0x90 + a954: 47b8 blx r7 + a956: 4603 mov r3, r0 + a958: f641 60b8 movw r0, #7864 ; 0x1eb8 + a95c: 4631 mov r1, r6 + a95e: 2290 movs r2, #144 ; 0x90 + a960: f2c0 0004 movt r0, #4 + a964: 47a8 blx r5 + a966: e795 b.n a894 + a968: f24a 039d movw r3, #41117 ; 0xa09d + a96c: 4630 mov r0, r6 + a96e: f2c0 0300 movt r3, #0 + a972: 2104 movs r1, #4 + a974: 4798 blx r3 + a976: f24f 3c9d movw ip, #62365 ; 0xf39d + a97a: 4603 mov r3, r0 + a97c: f641 50c8 movw r0, #7624 ; 0x1dc8 + a980: f2c0 0c00 movt ip, #0 + a984: 4631 mov r1, r6 + a986: 2204 movs r2, #4 + a988: f2c0 0004 movt r0, #4 + a98c: 47e0 blx ip + a98e: e76a b.n a866 + a990: f24a 039d movw r3, #41117 ; 0xa09d + a994: 4630 mov r0, r6 + a996: f2c0 0300 movt r3, #0 + a99a: 2100 movs r1, #0 + a99c: 4798 blx r3 + a99e: f24f 3c9d movw ip, #62365 ; 0xf39d + a9a2: 4603 mov r3, r0 + a9a4: f641 509c movw r0, #7580 ; 0x1d9c + a9a8: f2c0 0c00 movt ip, #0 + a9ac: 4631 mov r1, r6 + a9ae: 2200 movs r2, #0 + a9b0: f2c0 0004 movt r0, #4 + a9b4: 47e0 blx ip + a9b6: e735 b.n a824 + a9b8: f24a 039d movw r3, #41117 ; 0xa09d + a9bc: 4641 mov r1, r8 + a9be: 4630 mov r0, r6 + a9c0: f2c0 0300 movt r3, #0 + a9c4: 4798 blx r3 + a9c6: f24f 3c9d movw ip, #62365 ; 0xf39d + a9ca: 4603 mov r3, r0 + a9cc: f641 50f4 movw r0, #7668 ; 0x1df4 + a9d0: 4642 mov r2, r8 + a9d2: f2c0 0c00 movt ip, #0 + a9d6: 4631 mov r1, r6 + a9d8: f2c0 0004 movt r0, #4 + a9dc: 47e0 blx ip + a9de: e77e b.n a8de + a9e0: f24a 039d movw r3, #41117 ; 0xa09d + a9e4: 4630 mov r0, r6 + a9e6: f2c0 0300 movt r3, #0 + a9ea: 2108 movs r1, #8 + a9ec: 4798 blx r3 + a9ee: f24f 3c9d movw ip, #62365 ; 0xf39d + a9f2: 4603 mov r3, r0 + a9f4: f641 6020 movw r0, #7712 ; 0x1e20 + a9f8: f2c0 0c00 movt ip, #0 + a9fc: 4631 mov r1, r6 + a9fe: 2208 movs r2, #8 + aa00: f2c0 0004 movt r0, #4 + aa04: 47e0 blx ip + aa06: e773 b.n a8f0 + aa08: f24a 039d movw r3, #41117 ; 0xa09d + aa0c: 4630 mov r0, r6 + aa0e: f2c0 0300 movt r3, #0 + aa12: 2198 movs r1, #152 ; 0x98 + aa14: 4798 blx r3 + aa16: f24f 3c9d movw ip, #62365 ; 0xf39d + aa1a: 4603 mov r3, r0 + aa1c: f641 604c movw r0, #7756 ; 0x1e4c + aa20: f2c0 0c00 movt ip, #0 + aa24: 4631 mov r1, r6 + aa26: 2298 movs r2, #152 ; 0x98 + aa28: f2c0 0004 movt r0, #4 + aa2c: 47e0 blx ip + aa2e: e76f b.n a910 + +0000aa30 : + aa30: b538 push {r3, r4, r5, lr} + aa32: f24a 039d movw r3, #41117 ; 0xa09d + aa36: 7804 ldrb r4, [r0, #0] + aa38: 4605 mov r5, r0 + aa3a: f2c0 0300 movt r3, #0 + aa3e: 4620 mov r0, r4 + aa40: 2188 movs r1, #136 ; 0x88 + aa42: 4798 blx r3 + aa44: f24a 0361 movw r3, #41057 ; 0xa061 + aa48: 7b6a ldrb r2, [r5, #13] + aa4a: f000 00fc and.w r0, r0, #252 ; 0xfc + aa4e: 4302 orrs r2, r0 + aa50: f2c0 0300 movt r3, #0 + aa54: 4620 mov r0, r4 + aa56: 2188 movs r1, #136 ; 0x88 + aa58: 4798 blx r3 + aa5a: 2000 movs r0, #0 + aa5c: bd38 pop {r3, r4, r5, pc} + aa5e: bf00 nop + +0000aa60 : + aa60: 2000 movs r0, #0 + aa62: 4770 bx lr + +0000aa64 : + aa64: 2000 movs r0, #0 + aa66: 4770 bx lr + aa68: b5f8 push {r3, r4, r5, r6, r7, lr} + aa6a: f240 3510 movw r5, #784 ; 0x310 + aa6e: f2c1 0500 movt r5, #4096 ; 0x1000 + aa72: 682b ldr r3, [r5, #0] + aa74: f24e 1139 movw r1, #57657 ; 0xe139 + aa78: 06db lsls r3, r3, #27 + aa7a: bf58 it pl + aa7c: f24a 03dd movwpl r3, #41181 ; 0xa0dd + aa80: f2c1 0103 movt r1, #4099 ; 0x1003 + aa84: bf58 it pl + aa86: f2c0 0300 movtpl r3, #0 + aa8a: 4604 mov r4, r0 + aa8c: 6001 str r1, [r0, #0] + aa8e: bf58 it pl + aa90: 6043 strpl r3, [r0, #4] + aa92: d437 bmi.n ab04 + aa94: f24e 03a1 movw r3, #57505 ; 0xe0a1 + aa98: f2c1 0303 movt r3, #4099 ; 0x1003 + aa9c: 60a3 str r3, [r4, #8] + aa9e: f24a 235d movw r3, #41565 ; 0xa25d + aaa2: f2c0 0300 movt r3, #0 + aaa6: 60e3 str r3, [r4, #12] + aaa8: f24a 2371 movw r3, #41585 ; 0xa271 + aaac: f2c0 0300 movt r3, #0 + aab0: 6123 str r3, [r4, #16] + aab2: f24a 3389 movw r3, #41865 ; 0xa389 + aab6: f2c0 0300 movt r3, #0 + aaba: 6163 str r3, [r4, #20] + aabc: f24a 33a1 movw r3, #41889 ; 0xa3a1 + aac0: f2c0 0300 movt r3, #0 + aac4: 61a3 str r3, [r4, #24] + aac6: f24a 33b1 movw r3, #41905 ; 0xa3b1 + aaca: f2c0 0300 movt r3, #0 + aace: 61e3 str r3, [r4, #28] + aad0: f24e 439d movw r3, #58525 ; 0xe49d + aad4: f2c1 0303 movt r3, #4099 ; 0x1003 + aad8: 6223 str r3, [r4, #32] + aada: f24a 63e9 movw r3, #42729 ; 0xa6e9 + aade: f2c0 0300 movt r3, #0 + aae2: 6263 str r3, [r4, #36] ; 0x24 + aae4: f24a 7349 movw r3, #42825 ; 0xa749 + aae8: f2c0 0300 movt r3, #0 + aaec: 62a3 str r3, [r4, #40] ; 0x28 + aaee: f24a 7361 movw r3, #42849 ; 0xa761 + aaf2: f2c0 0300 movt r3, #0 + aaf6: 62e3 str r3, [r4, #44] ; 0x2c + aaf8: f64a 2331 movw r3, #43569 ; 0xaa31 + aafc: f2c0 0300 movt r3, #0 + ab00: 6323 str r3, [r4, #48] ; 0x30 + ab02: bdf8 pop {r3, r4, r5, r6, r7, pc} + ab04: f641 60f0 movw r0, #7920 ; 0x1ef0 + ab08: f24f 369d movw r6, #62365 ; 0xf39d + ab0c: f2c0 0004 movt r0, #4 + ab10: f2c0 0600 movt r6, #0 + ab14: 47b0 blx r6 + ab16: f24a 01dd movw r1, #41181 ; 0xa0dd + ab1a: f2c0 0100 movt r1, #0 + ab1e: 682b ldr r3, [r5, #0] + ab20: 6061 str r1, [r4, #4] + ab22: 06df lsls r7, r3, #27 + ab24: d5b6 bpl.n aa94 + ab26: f641 7018 movw r0, #7960 ; 0x1f18 + ab2a: f2c0 0004 movt r0, #4 + ab2e: 47b0 blx r6 + ab30: f24e 01a1 movw r1, #57505 ; 0xe0a1 + ab34: f2c1 0103 movt r1, #4099 ; 0x1003 + ab38: 682b ldr r3, [r5, #0] + ab3a: 60a1 str r1, [r4, #8] + ab3c: 06d8 lsls r0, r3, #27 + ab3e: d5ae bpl.n aa9e + ab40: f641 7040 movw r0, #8000 ; 0x1f40 + ab44: f2c0 0004 movt r0, #4 + ab48: 47b0 blx r6 + ab4a: f24a 215d movw r1, #41565 ; 0xa25d + ab4e: f2c0 0100 movt r1, #0 + ab52: 682b ldr r3, [r5, #0] + ab54: 60e1 str r1, [r4, #12] + ab56: 06da lsls r2, r3, #27 + ab58: d5a6 bpl.n aaa8 + ab5a: f641 7068 movw r0, #8040 ; 0x1f68 + ab5e: f2c0 0004 movt r0, #4 + ab62: 47b0 blx r6 + ab64: f24a 2171 movw r1, #41585 ; 0xa271 + ab68: f2c0 0100 movt r1, #0 + ab6c: 682b ldr r3, [r5, #0] + ab6e: 6121 str r1, [r4, #16] + ab70: 06db lsls r3, r3, #27 + ab72: d59e bpl.n aab2 + ab74: f641 7090 movw r0, #8080 ; 0x1f90 + ab78: f2c0 0004 movt r0, #4 + ab7c: 47b0 blx r6 + ab7e: f24a 3189 movw r1, #41865 ; 0xa389 + ab82: f2c0 0100 movt r1, #0 + ab86: 682b ldr r3, [r5, #0] + ab88: 6161 str r1, [r4, #20] + ab8a: 06df lsls r7, r3, #27 + ab8c: d596 bpl.n aabc + ab8e: f641 70b8 movw r0, #8120 ; 0x1fb8 + ab92: f2c0 0004 movt r0, #4 + ab96: 47b0 blx r6 + ab98: f24a 31a1 movw r1, #41889 ; 0xa3a1 + ab9c: f2c0 0100 movt r1, #0 + aba0: 682b ldr r3, [r5, #0] + aba2: 61a1 str r1, [r4, #24] + aba4: 06d8 lsls r0, r3, #27 + aba6: d58e bpl.n aac6 + aba8: f641 70e4 movw r0, #8164 ; 0x1fe4 + abac: f2c0 0004 movt r0, #4 + abb0: 47b0 blx r6 + abb2: f24a 31b1 movw r1, #41905 ; 0xa3b1 + abb6: f2c0 0100 movt r1, #0 + abba: 682b ldr r3, [r5, #0] + abbc: 61e1 str r1, [r4, #28] + abbe: 06da lsls r2, r3, #27 + abc0: d586 bpl.n aad0 + abc2: f242 000c movw r0, #8204 ; 0x200c + abc6: f2c0 0004 movt r0, #4 + abca: 47b0 blx r6 + abcc: f24e 419d movw r1, #58525 ; 0xe49d + abd0: f2c1 0103 movt r1, #4099 ; 0x1003 + abd4: 682b ldr r3, [r5, #0] + abd6: 6221 str r1, [r4, #32] + abd8: 06db lsls r3, r3, #27 + abda: f57f af7e bpl.w aada + abde: f242 0038 movw r0, #8248 ; 0x2038 + abe2: f2c0 0004 movt r0, #4 + abe6: 47b0 blx r6 + abe8: f24a 63e9 movw r3, #42729 ; 0xa6e9 + abec: f2c0 0300 movt r3, #0 + abf0: 682a ldr r2, [r5, #0] + abf2: 6263 str r3, [r4, #36] ; 0x24 + abf4: 06d7 lsls r7, r2, #27 + abf6: f57f af75 bpl.w aae4 + abfa: f242 0060 movw r0, #8288 ; 0x2060 + abfe: 4619 mov r1, r3 + ac00: f2c0 0004 movt r0, #4 + ac04: 47b0 blx r6 + ac06: f24a 7149 movw r1, #42825 ; 0xa749 + ac0a: f24f 369d movw r6, #62365 ; 0xf39d + ac0e: f2c0 0100 movt r1, #0 + ac12: 682b ldr r3, [r5, #0] + ac14: 62a1 str r1, [r4, #40] ; 0x28 + ac16: 06d8 lsls r0, r3, #27 + ac18: f2c0 0600 movt r6, #0 + ac1c: f57f af67 bpl.w aaee + ac20: f242 008c movw r0, #8332 ; 0x208c + ac24: f2c0 0004 movt r0, #4 + ac28: 47b0 blx r6 + ac2a: f24a 7161 movw r1, #42849 ; 0xa761 + ac2e: f2c0 0100 movt r1, #0 + ac32: 682b ldr r3, [r5, #0] + ac34: 62e1 str r1, [r4, #44] ; 0x2c + ac36: 06da lsls r2, r3, #27 + ac38: f57f af5e bpl.w aaf8 + ac3c: f242 00b4 movw r0, #8372 ; 0x20b4 + ac40: f2c0 0004 movt r0, #4 + ac44: 47b0 blx r6 + ac46: f64a 2131 movw r1, #43569 ; 0xaa31 + ac4a: f2c0 0100 movt r1, #0 + ac4e: 682b ldr r3, [r5, #0] + ac50: 6321 str r1, [r4, #48] ; 0x30 + ac52: 06db lsls r3, r3, #27 + ac54: f57f af55 bpl.w ab02 + ac58: f242 00e0 movw r0, #8416 ; 0x20e0 + ac5c: f2c0 0004 movt r0, #4 + ac60: 47b0 blx r6 + ac62: bdf8 pop {r3, r4, r5, r6, r7, pc} + +0000ac64 : + ac64: b538 push {r3, r4, r5, lr} + ac66: f240 3318 movw r3, #792 ; 0x318 + ac6a: f2c1 0300 movt r3, #4096 ; 0x1000 + ac6e: 4604 mov r4, r0 + ac70: 689b ldr r3, [r3, #8] + ac72: 2001 movs r0, #1 + ac74: 460d mov r5, r1 + ac76: 4798 blx r3 + ac78: 42a0 cmp r0, r4 + ac7a: eba4 0000 sub.w r0, r4, r0 + ac7e: bf88 it hi + ac80: f100 30ff addhi.w r0, r0, #4294967295 + ac84: 42a8 cmp r0, r5 + ac86: bf8c ite hi + ac88: 2002 movhi r0, #2 + ac8a: 2000 movls r0, #0 + ac8c: bd38 pop {r3, r4, r5, pc} + ac8e: bf00 nop + ac90: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + ac94: 4606 mov r6, r0 + ac96: f850 7c04 ldr.w r7, [r0, #-4] + ac9a: b087 sub sp, #28 + ac9c: 687c ldr r4, [r7, #4] + ac9e: 68bd ldr r5, [r7, #8] + aca0: 69fa ldr r2, [r7, #28] + aca2: 212c movs r1, #44 ; 0x2c + aca4: 4620 mov r0, r4 + aca6: 69ab ldr r3, [r5, #24] + aca8: f894 9000 ldrb.w r9, [r4] + acac: 9202 str r2, [sp, #8] + acae: f8d6 802c ldr.w r8, [r6, #44] ; 0x2c + acb2: 4798 blx r3 + acb4: 0501 lsls r1, r0, #20 + acb6: d512 bpl.n acde + acb8: f240 330c movw r3, #780 ; 0x30c + acbc: f2c1 0300 movt r3, #4096 ; 0x1000 + acc0: 681b ldr r3, [r3, #0] + acc2: 06da lsls r2, r3, #27 + acc4: f100 82c7 bmi.w b256 + acc8: 2368 movs r3, #104 ; 0x68 + acca: 8363 strh r3, [r4, #26] + accc: 4620 mov r0, r4 + acce: 6aab ldr r3, [r5, #40] ; 0x28 + acd0: 4798 blx r3 + acd2: f8d8 2028 ldr.w r2, [r8, #40] ; 0x28 + acd6: 6813 ldr r3, [r2, #0] + acd8: b10b cbz r3, acde + acda: 6850 ldr r0, [r2, #4] + acdc: 4798 blx r3 + acde: 69ab ldr r3, [r5, #24] + ace0: 4620 mov r0, r4 + ace2: 212c movs r1, #44 ; 0x2c + ace4: 4798 blx r3 + ace6: 0543 lsls r3, r0, #21 + ace8: d50c bpl.n ad04 + acea: f240 330c movw r3, #780 ; 0x30c + acee: f2c1 0300 movt r3, #4096 ; 0x1000 + acf2: 681b ldr r3, [r3, #0] + acf4: 06d8 lsls r0, r3, #27 + acf6: f100 82b9 bmi.w b26c + acfa: 2364 movs r3, #100 ; 0x64 + acfc: 8363 strh r3, [r4, #26] + acfe: 4620 mov r0, r4 + ad00: 6aab ldr r3, [r5, #40] ; 0x28 + ad02: 4798 blx r3 + ad04: 212c movs r1, #44 ; 0x2c + ad06: 69ab ldr r3, [r5, #24] + ad08: 4620 mov r0, r4 + ad0a: 4798 blx r3 + ad0c: 0581 lsls r1, r0, #22 + ad0e: d50c bpl.n ad2a + ad10: f240 330c movw r3, #780 ; 0x30c + ad14: f2c1 0300 movt r3, #4096 ; 0x1000 + ad18: 681b ldr r3, [r3, #0] + ad1a: 06da lsls r2, r3, #27 + ad1c: f100 82b1 bmi.w b282 + ad20: 2360 movs r3, #96 ; 0x60 + ad22: 8363 strh r3, [r4, #26] + ad24: 4620 mov r0, r4 + ad26: 6aab ldr r3, [r5, #40] ; 0x28 + ad28: 4798 blx r3 + ad2a: 69ab ldr r3, [r5, #24] + ad2c: 4620 mov r0, r4 + ad2e: 212c movs r1, #44 ; 0x2c + ad30: 4798 blx r3 + ad32: 05c3 lsls r3, r0, #23 + ad34: d50c bpl.n ad50 + ad36: f240 330c movw r3, #780 ; 0x30c + ad3a: f2c1 0300 movt r3, #4096 ; 0x1000 + ad3e: 681b ldr r3, [r3, #0] + ad40: 06d8 lsls r0, r3, #27 + ad42: f100 827d bmi.w b240 + ad46: 235c movs r3, #92 ; 0x5c + ad48: 8363 strh r3, [r4, #26] + ad4a: 4620 mov r0, r4 + ad4c: 6aab ldr r3, [r5, #40] ; 0x28 + ad4e: 4798 blx r3 + ad50: 212c movs r1, #44 ; 0x2c + ad52: 69ab ldr r3, [r5, #24] + ad54: 4620 mov r0, r4 + ad56: 4798 blx r3 + ad58: 0601 lsls r1, r0, #24 + ad5a: d531 bpl.n adc0 + ad5c: f240 3a14 movw sl, #788 ; 0x314 + ad60: f2c1 0a00 movt sl, #4096 ; 0x1000 + ad64: f8da 3000 ldr.w r3, [sl] + ad68: 06da lsls r2, r3, #27 + ad6a: d518 bpl.n ad9e + ad6c: f242 108c movw r0, #8588 ; 0x218c + ad70: f24f 3b9d movw fp, #62365 ; 0xf39d + ad74: f2c0 0004 movt r0, #4 + ad78: f2c0 0b00 movt fp, #0 + ad7c: 4649 mov r1, r9 + ad7e: 47d8 blx fp + ad80: f8da 3000 ldr.w r3, [sl] + ad84: 06db lsls r3, r3, #27 + ad86: d50a bpl.n ad9e + ad88: 2174 movs r1, #116 ; 0x74 + ad8a: 69ab ldr r3, [r5, #24] + ad8c: 4620 mov r0, r4 + ad8e: 4798 blx r3 + ad90: 4602 mov r2, r0 + ad92: f242 10ac movw r0, #8620 ; 0x21ac + ad96: 4649 mov r1, r9 + ad98: f2c0 0004 movt r0, #4 + ad9c: 47d8 blx fp + ad9e: 2358 movs r3, #88 ; 0x58 + ada0: 8363 strh r3, [r4, #26] + ada2: 4620 mov r0, r4 + ada4: 6aab ldr r3, [r5, #40] ; 0x28 + ada6: 4798 blx r3 + ada8: 2310 movs r3, #16 + adaa: 70f3 strb r3, [r6, #3] + adac: f8d8 2014 ldr.w r2, [r8, #20] + adb0: 69b1 ldr r1, [r6, #24] + adb2: 6813 ldr r3, [r2, #0] + adb4: f041 0110 orr.w r1, r1, #16 + adb8: 61b1 str r1, [r6, #24] + adba: b10b cbz r3, adc0 + adbc: 6850 ldr r0, [r2, #4] + adbe: 4798 blx r3 + adc0: 69ab ldr r3, [r5, #24] + adc2: 4620 mov r0, r4 + adc4: 212c movs r1, #44 ; 0x2c + adc6: 4798 blx r3 + adc8: 0640 lsls r0, r0, #25 + adca: d53a bpl.n ae42 + adcc: f240 3a14 movw sl, #788 ; 0x314 + add0: f2c1 0a00 movt sl, #4096 ; 0x1000 + add4: f8da 3000 ldr.w r3, [sl] + add8: 06d9 lsls r1, r3, #27 + adda: d519 bpl.n ae10 + addc: f242 10cc movw r0, #8652 ; 0x21cc + ade0: f24f 3b9d movw fp, #62365 ; 0xf39d + ade4: f2c0 0004 movt r0, #4 + ade8: f2c0 0b00 movt fp, #0 + adec: 4649 mov r1, r9 + adee: 47d8 blx fp + adf0: f8da 3000 ldr.w r3, [sl] + adf4: 06da lsls r2, r3, #27 + adf6: d50b bpl.n ae10 + adf8: 69ab ldr r3, [r5, #24] + adfa: 2180 movs r1, #128 ; 0x80 + adfc: 4620 mov r0, r4 + adfe: 4798 blx r3 + ae00: 4603 mov r3, r0 + ae02: f242 10f4 movw r0, #8692 ; 0x21f4 + ae06: 4649 mov r1, r9 + ae08: f2c0 0004 movt r0, #4 + ae0c: 2280 movs r2, #128 ; 0x80 + ae0e: 47d8 blx fp + ae10: 2354 movs r3, #84 ; 0x54 + ae12: 8363 strh r3, [r4, #26] + ae14: 4620 mov r0, r4 + ae16: 6aab ldr r3, [r5, #40] ; 0x28 + ae18: 4798 blx r3 + ae1a: 2310 movs r3, #16 + ae1c: f896 b003 ldrb.w fp, [r6, #3] + ae20: 70f3 strb r3, [r6, #3] + ae22: f8d8 2014 ldr.w r2, [r8, #20] + ae26: 69b1 ldr r1, [r6, #24] + ae28: 6813 ldr r3, [r2, #0] + ae2a: f041 0108 orr.w r1, r1, #8 + ae2e: fa5f fb8b uxtb.w fp, fp + ae32: 61b1 str r1, [r6, #24] + ae34: b10b cbz r3, ae3a + ae36: 6850 ldr r0, [r2, #4] + ae38: 4798 blx r3 + ae3a: 6973 ldr r3, [r6, #20] + ae3c: 05db lsls r3, r3, #23 + ae3e: f100 80b6 bmi.w afae + ae42: 69ab ldr r3, [r5, #24] + ae44: 4620 mov r0, r4 + ae46: 212c movs r1, #44 ; 0x2c + ae48: 4798 blx r3 + ae4a: 0680 lsls r0, r0, #26 + ae4c: d503 bpl.n ae56 + ae4e: 7933 ldrb r3, [r6, #4] + ae50: 2b00 cmp r3, #0 + ae52: f000 80e9 beq.w b028 + ae56: 69ab ldr r3, [r5, #24] + ae58: 4620 mov r0, r4 + ae5a: 212c movs r1, #44 ; 0x2c + ae5c: 4798 blx r3 + ae5e: 06c3 lsls r3, r0, #27 + ae60: d503 bpl.n ae6a + ae62: 7933 ldrb r3, [r6, #4] + ae64: 2b01 cmp r3, #1 + ae66: f000 8149 beq.w b0fc + ae6a: 69ab ldr r3, [r5, #24] + ae6c: 4620 mov r0, r4 + ae6e: 212c movs r1, #44 ; 0x2c + ae70: 4798 blx r3 + ae72: 0702 lsls r2, r0, #28 + ae74: d521 bpl.n aeba + ae76: f240 3314 movw r3, #788 ; 0x314 + ae7a: f2c1 0300 movt r3, #4096 ; 0x1000 + ae7e: 681b ldr r3, [r3, #0] + ae80: 06db lsls r3, r3, #27 + ae82: d509 bpl.n ae98 + ae84: f242 20a0 movw r0, #8864 ; 0x22a0 + ae88: f24f 339d movw r3, #62365 ; 0xf39d + ae8c: f2c0 0004 movt r0, #4 + ae90: f2c0 0300 movt r3, #0 + ae94: 4649 mov r1, r9 + ae96: 4798 blx r3 + ae98: 234c movs r3, #76 ; 0x4c + ae9a: 8363 strh r3, [r4, #26] + ae9c: 4620 mov r0, r4 + ae9e: 6aab ldr r3, [r5, #40] ; 0x28 + aea0: 4798 blx r3 + aea2: 2310 movs r3, #16 + aea4: 70f3 strb r3, [r6, #3] + aea6: f8d8 2014 ldr.w r2, [r8, #20] + aeaa: 69b1 ldr r1, [r6, #24] + aeac: 6813 ldr r3, [r2, #0] + aeae: f041 0104 orr.w r1, r1, #4 + aeb2: 61b1 str r1, [r6, #24] + aeb4: b10b cbz r3, aeba + aeb6: 6850 ldr r0, [r2, #4] + aeb8: 4798 blx r3 + aeba: 69ab ldr r3, [r5, #24] + aebc: 4620 mov r0, r4 + aebe: 212c movs r1, #44 ; 0x2c + aec0: 4798 blx r3 + aec2: 0740 lsls r0, r0, #29 + aec4: d51d bpl.n af02 + aec6: 7933 ldrb r3, [r6, #4] + aec8: 2b01 cmp r3, #1 + aeca: 6ab3 ldr r3, [r6, #40] ; 0x28 + aecc: 881b ldrh r3, [r3, #0] + aece: f000 8141 beq.w b154 + aed2: 2b00 cmp r3, #0 + aed4: f000 80fd beq.w b0d2 + aed8: 2306 movs r3, #6 + aeda: 70f3 strb r3, [r6, #3] + aedc: f8d8 2008 ldr.w r2, [r8, #8] + aee0: 6813 ldr r3, [r2, #0] + aee2: b10b cbz r3, aee8 + aee4: 6850 ldr r0, [r2, #4] + aee6: 4798 blx r3 + aee8: 69ab ldr r3, [r5, #24] + aeea: 4620 mov r0, r4 + aeec: 2170 movs r1, #112 ; 0x70 + aeee: 4798 blx r3 + aef0: f010 0f18 tst.w r0, #24 + aef4: f040 8191 bne.w b21a + aef8: 6ab3 ldr r3, [r6, #40] ; 0x28 + aefa: 881b ldrh r3, [r3, #0] + aefc: 2b00 cmp r3, #0 + aefe: f000 80e8 beq.w b0d2 + af02: 69ab ldr r3, [r5, #24] + af04: 4620 mov r0, r4 + af06: 212c movs r1, #44 ; 0x2c + af08: 4798 blx r3 + af0a: 0780 lsls r0, r0, #30 + af0c: d521 bpl.n af52 + af0e: f240 3314 movw r3, #788 ; 0x314 + af12: f2c1 0300 movt r3, #4096 ; 0x1000 + af16: 681b ldr r3, [r3, #0] + af18: 06d9 lsls r1, r3, #27 + af1a: d509 bpl.n af30 + af1c: f242 20c8 movw r0, #8904 ; 0x22c8 + af20: f24f 339d movw r3, #62365 ; 0xf39d + af24: f2c0 0004 movt r0, #4 + af28: f2c0 0300 movt r3, #0 + af2c: 4649 mov r1, r9 + af2e: 4798 blx r3 + af30: 2348 movs r3, #72 ; 0x48 + af32: 8363 strh r3, [r4, #26] + af34: 4620 mov r0, r4 + af36: 6aab ldr r3, [r5, #40] ; 0x28 + af38: 4798 blx r3 + af3a: 2310 movs r3, #16 + af3c: 70f3 strb r3, [r6, #3] + af3e: f8d8 2014 ldr.w r2, [r8, #20] + af42: 69b1 ldr r1, [r6, #24] + af44: 6813 ldr r3, [r2, #0] + af46: f041 0102 orr.w r1, r1, #2 + af4a: 61b1 str r1, [r6, #24] + af4c: b10b cbz r3, af52 + af4e: 6850 ldr r0, [r2, #4] + af50: 4798 blx r3 + af52: 69ab ldr r3, [r5, #24] + af54: 4620 mov r0, r4 + af56: 212c movs r1, #44 ; 0x2c + af58: 4798 blx r3 + af5a: 07c2 lsls r2, r0, #31 + af5c: d524 bpl.n afa8 + af5e: f240 3314 movw r3, #788 ; 0x314 + af62: f2c1 0300 movt r3, #4096 ; 0x1000 + af66: 681b ldr r3, [r3, #0] + af68: 06db lsls r3, r3, #27 + af6a: d509 bpl.n af80 + af6c: f242 20e8 movw r0, #8936 ; 0x22e8 + af70: f24f 339d movw r3, #62365 ; 0xf39d + af74: 4649 mov r1, r9 + af76: f2c0 0004 movt r0, #4 + af7a: f2c0 0300 movt r3, #0 + af7e: 4798 blx r3 + af80: 2244 movs r2, #68 ; 0x44 + af82: 6aab ldr r3, [r5, #40] ; 0x28 + af84: 4620 mov r0, r4 + af86: 8362 strh r2, [r4, #26] + af88: 4798 blx r3 + af8a: 2310 movs r3, #16 + af8c: 70f3 strb r3, [r6, #3] + af8e: f8d8 2014 ldr.w r2, [r8, #20] + af92: 69b1 ldr r1, [r6, #24] + af94: 6813 ldr r3, [r2, #0] + af96: f041 0101 orr.w r1, r1, #1 + af9a: 61b1 str r1, [r6, #24] + af9c: b123 cbz r3, afa8 + af9e: 6850 ldr r0, [r2, #4] + afa0: b007 add sp, #28 + afa2: e8bd 4ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + afa6: 4718 bx r3 + afa8: b007 add sp, #28 + afaa: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + afae: 7933 ldrb r3, [r6, #4] + afb0: 2b01 cmp r3, #1 + afb2: f47f af46 bne.w ae42 + afb6: f1ab 0205 sub.w r2, fp, #5 + afba: 2a01 cmp r2, #1 + afbc: f240 818b bls.w b2d6 + afc0: f1ab 0b03 sub.w fp, fp, #3 + afc4: f1bb 0f01 cmp.w fp, #1 + afc8: f63f af3b bhi.w ae42 + afcc: 69aa ldr r2, [r5, #24] + afce: 2154 movs r1, #84 ; 0x54 + afd0: 9301 str r3, [sp, #4] + afd2: 4620 mov r0, r4 + afd4: 4790 blx r2 + afd6: 6a72 ldr r2, [r6, #36] ; 0x24 + afd8: 2104 movs r1, #4 + afda: 70f1 strb r1, [r6, #3] + afdc: 68d1 ldr r1, [r2, #12] + afde: 8810 ldrh r0, [r2, #0] + afe0: 3101 adds r1, #1 + afe2: 3801 subs r0, #1 + afe4: 60d1 str r1, [r2, #12] + afe6: 8010 strh r0, [r2, #0] + afe8: 2170 movs r1, #112 ; 0x70 + afea: 69aa ldr r2, [r5, #24] + afec: 4620 mov r0, r4 + afee: 4790 blx r2 + aff0: f010 0f02 tst.w r0, #2 + aff4: 9b01 ldr r3, [sp, #4] + aff6: f43f af24 beq.w ae42 + affa: 2200 movs r2, #0 + affc: 73e3 strb r3, [r4, #15] + affe: 73a2 strb r2, [r4, #14] + b000: 6a73 ldr r3, [r6, #36] ; 0x24 + b002: 68db ldr r3, [r3, #12] + b004: 7462 strb r2, [r4, #17] + b006: 6a72 ldr r2, [r6, #36] ; 0x24 + b008: 6163 str r3, [r4, #20] + b00a: 8813 ldrh r3, [r2, #0] + b00c: 2b01 cmp r3, #1 + b00e: f000 820c beq.w b42a + b012: 6a6b ldr r3, [r5, #36] ; 0x24 + b014: 4620 mov r0, r4 + b016: 4798 blx r3 + b018: 6a73 ldr r3, [r6, #36] ; 0x24 + b01a: 68da ldr r2, [r3, #12] + b01c: 8819 ldrh r1, [r3, #0] + b01e: 3201 adds r2, #1 + b020: 3901 subs r1, #1 + b022: 60da str r2, [r3, #12] + b024: 8019 strh r1, [r3, #0] + b026: e70c b.n ae42 + b028: 6a73 ldr r3, [r6, #36] ; 0x24 + b02a: 881b ldrh r3, [r3, #0] + b02c: b323 cbz r3, b078 + b02e: 2304 movs r3, #4 + b030: 70f3 strb r3, [r6, #3] + b032: f8d8 2000 ldr.w r2, [r8] + b036: 6813 ldr r3, [r2, #0] + b038: b10b cbz r3, b03e + b03a: 6850 ldr r0, [r2, #4] + b03c: 4798 blx r3 + b03e: 2170 movs r1, #112 ; 0x70 + b040: 69ab ldr r3, [r5, #24] + b042: 4620 mov r0, r4 + b044: 4798 blx r3 + b046: 0781 lsls r1, r0, #30 + b048: d516 bpl.n b078 + b04a: 2300 movs r3, #0 + b04c: 2201 movs r2, #1 + b04e: 73a3 strb r3, [r4, #14] + b050: 73e2 strb r2, [r4, #15] + b052: 6a72 ldr r2, [r6, #36] ; 0x24 + b054: 68d2 ldr r2, [r2, #12] + b056: 7463 strb r3, [r4, #17] + b058: 6a73 ldr r3, [r6, #36] ; 0x24 + b05a: 6162 str r2, [r4, #20] + b05c: 881b ldrh r3, [r3, #0] + b05e: 2b01 cmp r3, #1 + b060: f000 80e9 beq.w b236 + b064: 6a6b ldr r3, [r5, #36] ; 0x24 + b066: 4620 mov r0, r4 + b068: 4798 blx r3 + b06a: 6a73 ldr r3, [r6, #36] ; 0x24 + b06c: 68da ldr r2, [r3, #12] + b06e: 8819 ldrh r1, [r3, #0] + b070: 3201 adds r2, #1 + b072: 3901 subs r1, #1 + b074: 60da str r2, [r3, #12] + b076: 8019 strh r1, [r3, #0] + b078: 2350 movs r3, #80 ; 0x50 + b07a: 8363 strh r3, [r4, #26] + b07c: 4620 mov r0, r4 + b07e: 6aab ldr r3, [r5, #40] ; 0x28 + b080: 4798 blx r3 + b082: 6a73 ldr r3, [r6, #36] ; 0x24 + b084: 881b ldrh r3, [r3, #0] + b086: 2b00 cmp r3, #0 + b088: f47f aee5 bne.w ae56 + b08c: 2134 movs r1, #52 ; 0x34 + b08e: 69ab ldr r3, [r5, #24] + b090: 4620 mov r0, r4 + b092: 4798 blx r3 + b094: f640 0399 movw r3, #2201 ; 0x899 + b098: f44f 707a mov.w r0, #1000 ; 0x3e8 + b09c: f2c0 0300 movt r3, #0 + b0a0: 4798 blx r3 + b0a2: 2130 movs r1, #48 ; 0x30 + b0a4: 69ab ldr r3, [r5, #24] + b0a6: 4620 mov r0, r4 + b0a8: 4798 blx r3 + b0aa: f020 00e8 bic.w r0, r0, #232 ; 0xe8 + b0ae: 8320 strh r0, [r4, #24] + b0b0: 696b ldr r3, [r5, #20] + b0b2: 4620 mov r0, r4 + b0b4: 4798 blx r3 + b0b6: 6aeb ldr r3, [r5, #44] ; 0x2c + b0b8: 4620 mov r0, r4 + b0ba: 4798 blx r3 + b0bc: 2302 movs r3, #2 + b0be: 70f3 strb r3, [r6, #3] + b0c0: f8d8 2004 ldr.w r2, [r8, #4] + b0c4: 6813 ldr r3, [r2, #0] + b0c6: 2b00 cmp r3, #0 + b0c8: f43f aec5 beq.w ae56 + b0cc: 6850 ldr r0, [r2, #4] + b0ce: 4798 blx r3 + b0d0: e6c1 b.n ae56 + b0d2: 69ab ldr r3, [r5, #24] + b0d4: 4620 mov r0, r4 + b0d6: 2130 movs r1, #48 ; 0x30 + b0d8: 4798 blx r3 + b0da: 696b ldr r3, [r5, #20] + b0dc: f020 0007 bic.w r0, r0, #7 + b0e0: 8320 strh r0, [r4, #24] + b0e2: 4620 mov r0, r4 + b0e4: 4798 blx r3 + b0e6: 2302 movs r3, #2 + b0e8: 70f3 strb r3, [r6, #3] + b0ea: f8d8 200c ldr.w r2, [r8, #12] + b0ee: 6813 ldr r3, [r2, #0] + b0f0: 2b00 cmp r3, #0 + b0f2: f43f af06 beq.w af02 + b0f6: 6850 ldr r0, [r2, #4] + b0f8: 4798 blx r3 + b0fa: e702 b.n af02 + b0fc: 6a73 ldr r3, [r6, #36] ; 0x24 + b0fe: 881b ldrh r3, [r3, #0] + b100: 2b00 cmp r3, #0 + b102: f000 80c9 beq.w b298 + b106: 2304 movs r3, #4 + b108: 70f3 strb r3, [r6, #3] + b10a: f8d8 2000 ldr.w r2, [r8] + b10e: 6813 ldr r3, [r2, #0] + b110: b10b cbz r3, b116 + b112: 6850 ldr r0, [r2, #4] + b114: 4798 blx r3 + b116: 69ab ldr r3, [r5, #24] + b118: 4620 mov r0, r4 + b11a: 2170 movs r1, #112 ; 0x70 + b11c: 4798 blx r3 + b11e: 0780 lsls r0, r0, #30 + b120: f57f aea3 bpl.w ae6a + b124: 2300 movs r3, #0 + b126: 2201 movs r2, #1 + b128: 73a3 strb r3, [r4, #14] + b12a: 73e2 strb r2, [r4, #15] + b12c: 6a72 ldr r2, [r6, #36] ; 0x24 + b12e: 68d2 ldr r2, [r2, #12] + b130: 7463 strb r3, [r4, #17] + b132: 6a73 ldr r3, [r6, #36] ; 0x24 + b134: 6162 str r2, [r4, #20] + b136: 881b ldrh r3, [r3, #0] + b138: 2b01 cmp r3, #1 + b13a: f000 80c7 beq.w b2cc + b13e: 6a6b ldr r3, [r5, #36] ; 0x24 + b140: 4620 mov r0, r4 + b142: 4798 blx r3 + b144: 6a73 ldr r3, [r6, #36] ; 0x24 + b146: 68da ldr r2, [r3, #12] + b148: 8819 ldrh r1, [r3, #0] + b14a: 3201 adds r2, #1 + b14c: 3901 subs r1, #1 + b14e: 60da str r2, [r3, #12] + b150: 8019 strh r1, [r3, #0] + b152: e68a b.n ae6a + b154: b95b cbnz r3, b16e + b156: 69ab ldr r3, [r5, #24] + b158: 2130 movs r1, #48 ; 0x30 + b15a: 4620 mov r0, r4 + b15c: 4798 blx r3 + b15e: f020 0047 bic.w r0, r0, #71 ; 0x47 + b162: 8320 strh r0, [r4, #24] + b164: 696b ldr r3, [r5, #20] + b166: 4620 mov r0, r4 + b168: 4798 blx r3 + b16a: 6aeb ldr r3, [r5, #44] ; 0x2c + b16c: e7b9 b.n b0e2 + b16e: 2306 movs r3, #6 + b170: 70f3 strb r3, [r6, #3] + b172: f8d8 2008 ldr.w r2, [r8, #8] + b176: 6813 ldr r3, [r2, #0] + b178: b10b cbz r3, b17e + b17a: 6850 ldr r0, [r2, #4] + b17c: 4798 blx r3 + b17e: 9802 ldr r0, [sp, #8] + b180: 1e43 subs r3, r0, #1 + b182: 3303 adds r3, #3 + b184: bf88 it hi + b186: 46ba movhi sl, r7 + b188: d819 bhi.n b1be + b18a: f240 3318 movw r3, #792 ; 0x318 + b18e: f2c1 0300 movt r3, #4096 ; 0x1000 + b192: 2001 movs r0, #1 + b194: 689b ldr r3, [r3, #8] + b196: 4798 blx r3 + b198: 46ba mov sl, r7 + b19a: e010 b.n b1be + b19c: 6ab2 ldr r2, [r6, #40] ; 0x28 + b19e: 68eb ldr r3, [r5, #12] + b1a0: 4620 mov r0, r4 + b1a2: 68d7 ldr r7, [r2, #12] + b1a4: 4798 blx r3 + b1a6: 7038 strb r0, [r7, #0] + b1a8: 6ab3 ldr r3, [r6, #40] ; 0x28 + b1aa: 881a ldrh r2, [r3, #0] + b1ac: 68d9 ldr r1, [r3, #12] + b1ae: 3a01 subs r2, #1 + b1b0: 3101 adds r1, #1 + b1b2: b292 uxth r2, r2 + b1b4: 60d9 str r1, [r3, #12] + b1b6: 801a strh r2, [r3, #0] + b1b8: 2a00 cmp r2, #0 + b1ba: f000 8085 beq.w b2c8 + b1be: 69ab ldr r3, [r5, #24] + b1c0: 4620 mov r0, r4 + b1c2: 2170 movs r1, #112 ; 0x70 + b1c4: 4798 blx r3 + b1c6: f010 0f18 tst.w r0, #24 + b1ca: d1e7 bne.n b19c + b1cc: 4657 mov r7, sl + b1ce: 69ab ldr r3, [r5, #24] + b1d0: 4620 mov r0, r4 + b1d2: 2134 movs r1, #52 ; 0x34 + b1d4: 4798 blx r3 + b1d6: 6ab3 ldr r3, [r6, #40] ; 0x28 + b1d8: 881b ldrh r3, [r3, #0] + b1da: 2b00 cmp r3, #0 + b1dc: d0bb beq.n b156 + b1de: 2170 movs r1, #112 ; 0x70 + b1e0: 69ab ldr r3, [r5, #24] + b1e2: 4620 mov r0, r4 + b1e4: 4798 blx r3 + b1e6: 0781 lsls r1, r0, #30 + b1e8: f57f ae8b bpl.w af02 + b1ec: 69bb ldr r3, [r7, #24] + b1ee: 2b00 cmp r3, #0 + b1f0: f43f ae87 beq.w af02 + b1f4: 2301 movs r3, #1 + b1f6: 73a3 strb r3, [r4, #14] + b1f8: 73e3 strb r3, [r4, #15] + b1fa: 6ab2 ldr r2, [r6, #40] ; 0x28 + b1fc: 2300 movs r3, #0 + b1fe: 68d2 ldr r2, [r2, #12] + b200: 7463 strb r3, [r4, #17] + b202: 69bb ldr r3, [r7, #24] + b204: 6162 str r2, [r4, #20] + b206: 2b01 cmp r3, #1 + b208: f000 80f0 beq.w b3ec + b20c: 6a6b ldr r3, [r5, #36] ; 0x24 + b20e: 4620 mov r0, r4 + b210: 4798 blx r3 + b212: 69bb ldr r3, [r7, #24] + b214: 3b01 subs r3, #1 + b216: 61bb str r3, [r7, #24] + b218: e673 b.n af02 + b21a: 6ab2 ldr r2, [r6, #40] ; 0x28 + b21c: 68eb ldr r3, [r5, #12] + b21e: 4620 mov r0, r4 + b220: 68d7 ldr r7, [r2, #12] + b222: 4798 blx r3 + b224: 7038 strb r0, [r7, #0] + b226: 6ab3 ldr r3, [r6, #40] ; 0x28 + b228: 68da ldr r2, [r3, #12] + b22a: 8819 ldrh r1, [r3, #0] + b22c: 3201 adds r2, #1 + b22e: 3901 subs r1, #1 + b230: 60da str r2, [r3, #12] + b232: 8019 strh r1, [r3, #0] + b234: e661 b.n aefa + b236: 6972 ldr r2, [r6, #20] + b238: 0552 lsls r2, r2, #21 + b23a: bf58 it pl + b23c: 7463 strbpl r3, [r4, #17] + b23e: e711 b.n b064 + b240: f242 106c movw r0, #8556 ; 0x216c + b244: f24f 339d movw r3, #62365 ; 0xf39d + b248: 4649 mov r1, r9 + b24a: f2c0 0300 movt r3, #0 + b24e: f2c0 0004 movt r0, #4 + b252: 4798 blx r3 + b254: e577 b.n ad46 + b256: f242 1008 movw r0, #8456 ; 0x2108 + b25a: f24f 339d movw r3, #62365 ; 0xf39d + b25e: 4649 mov r1, r9 + b260: f2c0 0300 movt r3, #0 + b264: f2c0 0004 movt r0, #4 + b268: 4798 blx r3 + b26a: e52d b.n acc8 + b26c: f242 1028 movw r0, #8488 ; 0x2128 + b270: f24f 339d movw r3, #62365 ; 0xf39d + b274: 4649 mov r1, r9 + b276: f2c0 0300 movt r3, #0 + b27a: f2c0 0004 movt r0, #4 + b27e: 4798 blx r3 + b280: e53b b.n acfa + b282: f242 104c movw r0, #8524 ; 0x214c + b286: f24f 339d movw r3, #62365 ; 0xf39d + b28a: 4649 mov r1, r9 + b28c: f2c0 0300 movt r3, #0 + b290: f2c0 0004 movt r0, #4 + b294: 4798 blx r3 + b296: e543 b.n ad20 + b298: 69ab ldr r3, [r5, #24] + b29a: 2130 movs r1, #48 ; 0x30 + b29c: 4620 mov r0, r4 + b29e: 4798 blx r3 + b2a0: f020 0058 bic.w r0, r0, #88 ; 0x58 + b2a4: 8320 strh r0, [r4, #24] + b2a6: 696b ldr r3, [r5, #20] + b2a8: 4620 mov r0, r4 + b2aa: 4798 blx r3 + b2ac: 2302 movs r3, #2 + b2ae: 70f3 strb r3, [r6, #3] + b2b0: f8d8 2004 ldr.w r2, [r8, #4] + b2b4: 6813 ldr r3, [r2, #0] + b2b6: b10b cbz r3, b2bc + b2b8: 6850 ldr r0, [r2, #4] + b2ba: 4798 blx r3 + b2bc: 6a73 ldr r3, [r6, #36] ; 0x24 + b2be: 881b ldrh r3, [r3, #0] + b2c0: 2b00 cmp r3, #0 + b2c2: f43f add2 beq.w ae6a + b2c6: e71e b.n b106 + b2c8: 4657 mov r7, sl + b2ca: e785 b.n b1d8 + b2cc: 6972 ldr r2, [r6, #20] + b2ce: 0551 lsls r1, r2, #21 + b2d0: bf58 it pl + b2d2: 7463 strbpl r3, [r4, #17] + b2d4: e733 b.n b13e + b2d6: 69aa ldr r2, [r5, #24] + b2d8: 2154 movs r1, #84 ; 0x54 + b2da: 9301 str r3, [sp, #4] + b2dc: 4620 mov r0, r4 + b2de: 4790 blx r2 + b2e0: 6ab2 ldr r2, [r6, #40] ; 0x28 + b2e2: 2106 movs r1, #6 + b2e4: 8810 ldrh r0, [r2, #0] + b2e6: 9a02 ldr r2, [sp, #8] + b2e8: 61b8 str r0, [r7, #24] + b2ea: f102 3eff add.w lr, r2, #4294967295 + b2ee: f11e 0203 adds.w r2, lr, #3 + b2f2: bf88 it hi + b2f4: 2200 movhi r2, #0 + b2f6: 70f1 strb r1, [r6, #3] + b2f8: 9b01 ldr r3, [sp, #4] + b2fa: bf84 itt hi + b2fc: 9205 strhi r2, [sp, #20] + b2fe: 9203 strhi r2, [sp, #12] + b300: d979 bls.n b3f6 + b302: f64a 4365 movw r3, #44133 ; 0xac65 + b306: f2c0 0300 movt r3, #0 + b30a: f04f 0b01 mov.w fp, #1 + b30e: 9304 str r3, [sp, #16] + b310: 69ab ldr r3, [r5, #24] + b312: 4620 mov r0, r4 + b314: 2170 movs r1, #112 ; 0x70 + b316: 4798 blx r3 + b318: 0780 lsls r0, r0, #30 + b31a: d517 bpl.n b34c + b31c: 69bb ldr r3, [r7, #24] + b31e: 2b00 cmp r3, #0 + b320: f43f ad8f beq.w ae42 + b324: f04f 0200 mov.w r2, #0 + b328: f884 b00e strb.w fp, [r4, #14] + b32c: f884 b00f strb.w fp, [r4, #15] + b330: 6ab3 ldr r3, [r6, #40] ; 0x28 + b332: 4620 mov r0, r4 + b334: 68db ldr r3, [r3, #12] + b336: 7462 strb r2, [r4, #17] + b338: 69ba ldr r2, [r7, #24] + b33a: 6163 str r3, [r4, #20] + b33c: 2a01 cmp r2, #1 + b33e: d036 beq.n b3ae + b340: 6a6b ldr r3, [r5, #36] ; 0x24 + b342: 4798 blx r3 + b344: 69bb ldr r3, [r7, #24] + b346: 3b01 subs r3, #1 + b348: 61bb str r3, [r7, #24] + b34a: e7e1 b.n b310 + b34c: 69ab ldr r3, [r5, #24] + b34e: 4620 mov r0, r4 + b350: 2134 movs r1, #52 ; 0x34 + b352: 4798 blx r3 + b354: f010 0f48 tst.w r0, #72 ; 0x48 + b358: f47f ad73 bne.w ae42 + b35c: 9b03 ldr r3, [sp, #12] + b35e: bb5b cbnz r3, b3b8 + b360: 9b02 ldr r3, [sp, #8] + b362: 2b00 cmp r3, #0 + b364: d1d4 bne.n b310 + b366: f240 3b14 movw fp, #788 ; 0x314 + b36a: 2311 movs r3, #17 + b36c: 70f3 strb r3, [r6, #3] + b36e: f8da 3000 ldr.w r3, [sl] + b372: 2221 movs r2, #33 ; 0x21 + b374: 06d8 lsls r0, r3, #27 + b376: f2c1 0b00 movt fp, #4096 ; 0x1000 + b37a: 61b2 str r2, [r6, #24] + b37c: f57f ad61 bpl.w ae42 + b380: f242 2074 movw r0, #8820 ; 0x2274 + b384: f24f 3a9d movw sl, #62365 ; 0xf39d + b388: f2c0 0004 movt r0, #4 + b38c: 7831 ldrb r1, [r6, #0] + b38e: f2c0 0a00 movt sl, #0 + b392: 47d0 blx sl + b394: f8db 3000 ldr.w r3, [fp] + b398: 06d9 lsls r1, r3, #27 + b39a: f57f ad52 bpl.w ae42 + b39e: f242 2050 movw r0, #8784 ; 0x2250 + b3a2: 78f1 ldrb r1, [r6, #3] + b3a4: 69b2 ldr r2, [r6, #24] + b3a6: f2c0 0004 movt r0, #4 + b3aa: 47d0 blx sl + b3ac: e549 b.n ae42 + b3ae: 6973 ldr r3, [r6, #20] + b3b0: 0559 lsls r1, r3, #21 + b3b2: bf58 it pl + b3b4: 7462 strbpl r2, [r4, #17] + b3b6: e7c3 b.n b340 + b3b8: 9805 ldr r0, [sp, #20] + b3ba: 4619 mov r1, r3 + b3bc: 9a04 ldr r2, [sp, #16] + b3be: 4790 blx r2 + b3c0: 2802 cmp r0, #2 + b3c2: d1a5 bne.n b310 + b3c4: f240 3b14 movw fp, #788 ; 0x314 + b3c8: 2311 movs r3, #17 + b3ca: 70f3 strb r3, [r6, #3] + b3cc: f8da 3000 ldr.w r3, [sl] + b3d0: 2221 movs r2, #33 ; 0x21 + b3d2: 06db lsls r3, r3, #27 + b3d4: f2c1 0b00 movt fp, #4096 ; 0x1000 + b3d8: 61b2 str r2, [r6, #24] + b3da: f57f ad32 bpl.w ae42 + b3de: f242 2024 movw r0, #8740 ; 0x2224 + b3e2: f24f 3a9d movw sl, #62365 ; 0xf39d + b3e6: f2c0 0004 movt r0, #4 + b3ea: e7cf b.n b38c + b3ec: 6972 ldr r2, [r6, #20] + b3ee: 0552 lsls r2, r2, #21 + b3f0: bf58 it pl + b3f2: 7463 strbpl r3, [r4, #17] + b3f4: e70a b.n b20c + b3f6: f241 0185 movw r1, #4229 ; 0x1085 + b3fa: f240 3218 movw r2, #792 ; 0x318 + b3fe: f6c0 0142 movt r1, #2114 ; 0x842 + b402: f2c1 0200 movt r2, #4096 ; 0x1000 + b406: 9802 ldr r0, [sp, #8] + b408: f44f 7e7a mov.w lr, #1000 ; 0x3e8 + b40c: fb0e fe00 mul.w lr, lr, r0 + b410: fba1 010e umull r0, r1, r1, lr + b414: ebc1 0e0e rsb lr, r1, lr + b418: eb01 015e add.w r1, r1, lr, lsr #1 + b41c: 4618 mov r0, r3 + b41e: 0909 lsrs r1, r1, #4 + b420: 6893 ldr r3, [r2, #8] + b422: 9103 str r1, [sp, #12] + b424: 4798 blx r3 + b426: 9005 str r0, [sp, #20] + b428: e76b b.n b302 + b42a: 6972 ldr r2, [r6, #20] + b42c: 0552 lsls r2, r2, #21 + b42e: bf58 it pl + b430: 7463 strbpl r3, [r4, #17] + b432: e5ee b.n b012 + +0000b434 : + b434: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} + b438: f850 4c04 ldr.w r4, [r0, #-4] + b43c: f8d4 9008 ldr.w r9, [r4, #8] + b440: f8d4 8000 ldr.w r8, [r4] + b444: 6b26 ldr r6, [r4, #48] ; 0x30 + b446: 4648 mov r0, r9 + b448: 6aa5 ldr r5, [r4, #40] ; 0x28 + b44a: 68e3 ldr r3, [r4, #12] + b44c: f8d8 7024 ldr.w r7, [r8, #36] ; 0x24 + b450: f8d8 a030 ldr.w sl, [r8, #48] ; 0x30 + b454: 4798 blx r3 + b456: 6b63 ldr r3, [r4, #52] ; 0x34 + b458: 4630 mov r0, r6 + b45a: 4798 blx r3 + b45c: f895 3060 ldrb.w r3, [r5, #96] ; 0x60 + b460: 2b02 cmp r3, #2 + b462: d11f bne.n b4a4 + b464: 6caa ldr r2, [r5, #72] ; 0x48 + b466: 6ceb ldr r3, [r5, #76] ; 0x4c + b468: 3201 adds r2, #1 + b46a: 4293 cmp r3, r2 + b46c: d024 beq.n b4b8 + b46e: 2400 movs r4, #0 + b470: 737c strb r4, [r7, #13] + b472: f8d9 3030 ldr.w r3, [r9, #48] ; 0x30 + b476: 4638 mov r0, r7 + b478: 4798 blx r3 + b47a: f8d9 3014 ldr.w r3, [r9, #20] + b47e: 833c strh r4, [r7, #24] + b480: 4638 mov r0, r7 + b482: 4798 blx r3 + b484: f8d9 302c ldr.w r3, [r9, #44] ; 0x2c + b488: 4638 mov r0, r7 + b48a: 4798 blx r3 + b48c: 6933 ldr r3, [r6, #16] + b48e: 4628 mov r0, r5 + b490: 4798 blx r3 + b492: 2302 movs r3, #2 + b494: f888 3007 strb.w r3, [r8, #7] + b498: f8da 201c ldr.w r2, [sl, #28] + b49c: 6813 ldr r3, [r2, #0] + b49e: b10b cbz r3, b4a4 + b4a0: 6850 ldr r0, [r2, #4] + b4a2: 4798 blx r3 + b4a4: 69f3 ldr r3, [r6, #28] + b4a6: 4628 mov r0, r5 + b4a8: 4798 blx r3 + b4aa: 0783 lsls r3, r0, #30 + b4ac: bf42 ittt mi + b4ae: 6cab ldrmi r3, [r5, #72] ; 0x48 + b4b0: 3301 addmi r3, #1 + b4b2: 64ab strmi r3, [r5, #72] ; 0x48 + b4b4: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + b4b8: 6a73 ldr r3, [r6, #36] ; 0x24 + b4ba: 4628 mov r0, r5 + b4bc: 4798 blx r3 + b4be: e7d6 b.n b46e + +0000b4c0 : + b4c0: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} + b4c4: f850 4c04 ldr.w r4, [r0, #-4] + b4c8: f8d4 9008 ldr.w r9, [r4, #8] + b4cc: f8d4 8000 ldr.w r8, [r4] + b4d0: 6b26 ldr r6, [r4, #48] ; 0x30 + b4d2: 4648 mov r0, r9 + b4d4: 6ae5 ldr r5, [r4, #44] ; 0x2c + b4d6: 68e3 ldr r3, [r4, #12] + b4d8: f8d8 7024 ldr.w r7, [r8, #36] ; 0x24 + b4dc: f8d8 a030 ldr.w sl, [r8, #48] ; 0x30 + b4e0: 4798 blx r3 + b4e2: 6b63 ldr r3, [r4, #52] ; 0x34 + b4e4: 4630 mov r0, r6 + b4e6: 4798 blx r3 + b4e8: f895 3060 ldrb.w r3, [r5, #96] ; 0x60 + b4ec: 2b03 cmp r3, #3 + b4ee: d11f bne.n b530 + b4f0: 6caa ldr r2, [r5, #72] ; 0x48 + b4f2: 6ceb ldr r3, [r5, #76] ; 0x4c + b4f4: 3201 adds r2, #1 + b4f6: 4293 cmp r3, r2 + b4f8: d024 beq.n b544 + b4fa: 2400 movs r4, #0 + b4fc: 737c strb r4, [r7, #13] + b4fe: f8d9 3030 ldr.w r3, [r9, #48] ; 0x30 + b502: 4638 mov r0, r7 + b504: 4798 blx r3 + b506: f8d9 3014 ldr.w r3, [r9, #20] + b50a: 833c strh r4, [r7, #24] + b50c: 4638 mov r0, r7 + b50e: 4798 blx r3 + b510: f8d9 302c ldr.w r3, [r9, #44] ; 0x2c + b514: 4638 mov r0, r7 + b516: 4798 blx r3 + b518: 6933 ldr r3, [r6, #16] + b51a: 4628 mov r0, r5 + b51c: 4798 blx r3 + b51e: 2302 movs r3, #2 + b520: f888 3007 strb.w r3, [r8, #7] + b524: f8da 2024 ldr.w r2, [sl, #36] ; 0x24 + b528: 6813 ldr r3, [r2, #0] + b52a: b10b cbz r3, b530 + b52c: 6850 ldr r0, [r2, #4] + b52e: 4798 blx r3 + b530: 69f3 ldr r3, [r6, #28] + b532: 4628 mov r0, r5 + b534: 4798 blx r3 + b536: 0783 lsls r3, r0, #30 + b538: bf42 ittt mi + b53a: 6cab ldrmi r3, [r5, #72] ; 0x48 + b53c: 3301 addmi r3, #1 + b53e: 64ab strmi r3, [r5, #72] ; 0x48 + b540: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + b544: 6a33 ldr r3, [r6, #32] + b546: 4628 mov r0, r5 + b548: 4798 blx r3 + b54a: e7d6 b.n b4fa + +0000b54c : + b54c: b5f8 push {r3, r4, r5, r6, r7, lr} + b54e: f240 3410 movw r4, #784 ; 0x310 + b552: f2c1 0400 movt r4, #4096 ; 0x1000 + b556: 6823 ldr r3, [r4, #0] + b558: f850 7c04 ldr.w r7, [r0, #-4] + b55c: 06db lsls r3, r3, #27 + b55e: 4605 mov r5, r0 + b560: 693e ldr r6, [r7, #16] + b562: d43f bmi.n b5e4 + b564: 782b ldrb r3, [r5, #0] + b566: 2b03 cmp r3, #3 + b568: d901 bls.n b56e + b56a: 20ee movs r0, #238 ; 0xee + b56c: bdf8 pop {r3, r4, r5, r6, r7, pc} + b56e: 2b02 cmp r3, #2 + b570: d01b beq.n b5aa + b572: 2b03 cmp r3, #3 + b574: d023 beq.n b5be + b576: 2b01 cmp r3, #1 + b578: d01c beq.n b5b4 + b57a: f244 0329 movw r3, #16425 ; 0x4029 + b57e: 6a3a ldr r2, [r7, #32] + b580: 2040 movs r0, #64 ; 0x40 + b582: 2103 movs r1, #3 + b584: f2c0 0300 movt r3, #0 + b588: 6070 str r0, [r6, #4] + b58a: 6032 str r2, [r6, #0] + b58c: 60b5 str r5, [r6, #8] + b58e: 60f1 str r1, [r6, #12] + b590: 4630 mov r0, r6 + b592: 4798 blx r3 + b594: f244 03f1 movw r3, #16625 ; 0x40f1 + b598: 4630 mov r0, r6 + b59a: f2c0 0300 movt r3, #0 + b59e: 4798 blx r3 + b5a0: 6820 ldr r0, [r4, #0] + b5a2: f010 0010 ands.w r0, r0, #16 + b5a6: d127 bne.n b5f8 + b5a8: bdf8 pop {r3, r4, r5, r6, r7, pc} + b5aa: f244 0329 movw r3, #16425 ; 0x4029 + b5ae: 6a3a ldr r2, [r7, #32] + b5b0: 2042 movs r0, #66 ; 0x42 + b5b2: e7e6 b.n b582 + b5b4: f244 0329 movw r3, #16425 ; 0x4029 + b5b8: 6a3a ldr r2, [r7, #32] + b5ba: 2041 movs r0, #65 ; 0x41 + b5bc: e7e1 b.n b582 + b5be: f244 0229 movw r2, #16425 ; 0x4029 + b5c2: 6a39 ldr r1, [r7, #32] + b5c4: 2004 movs r0, #4 + b5c6: 60f3 str r3, [r6, #12] + b5c8: 6070 str r0, [r6, #4] + b5ca: 6031 str r1, [r6, #0] + b5cc: 60b5 str r5, [r6, #8] + b5ce: f2c0 0200 movt r2, #0 + b5d2: 4630 mov r0, r6 + b5d4: 4790 blx r2 + b5d6: f244 03f1 movw r3, #16625 ; 0x40f1 + b5da: 4630 mov r0, r6 + b5dc: f2c0 0300 movt r3, #0 + b5e0: 4798 blx r3 + b5e2: e7dd b.n b5a0 + b5e4: f242 3010 movw r0, #8976 ; 0x2310 + b5e8: f24f 339d movw r3, #62365 ; 0xf39d + b5ec: f2c0 0004 movt r0, #4 + b5f0: f2c0 0300 movt r3, #0 + b5f4: 4798 blx r3 + b5f6: e7b5 b.n b564 + b5f8: f242 3030 movw r0, #9008 ; 0x2330 + b5fc: f24f 339d movw r3, #62365 ; 0xf39d + b600: f2c0 0004 movt r0, #4 + b604: f2c0 0300 movt r3, #0 + b608: 4798 blx r3 + b60a: 2000 movs r0, #0 + b60c: bdf8 pop {r3, r4, r5, r6, r7, pc} + b60e: bf00 nop + +0000b610 : + b610: b570 push {r4, r5, r6, lr} + b612: f240 3410 movw r4, #784 ; 0x310 + b616: f2c1 0400 movt r4, #4096 ; 0x1000 + b61a: 6823 ldr r3, [r4, #0] + b61c: f850 2c04 ldr.w r2, [r0, #-4] + b620: 06db lsls r3, r3, #27 + b622: 4605 mov r5, r0 + b624: 6916 ldr r6, [r2, #16] + b626: d41a bmi.n b65e + b628: 782b ldrb r3, [r5, #0] + b62a: 2b03 cmp r3, #3 + b62c: d901 bls.n b632 + b62e: 20ee movs r0, #238 ; 0xee + b630: bd70 pop {r4, r5, r6, pc} + b632: f244 0391 movw r3, #16529 ; 0x4091 + b636: 4630 mov r0, r6 + b638: f2c0 0300 movt r3, #0 + b63c: 4798 blx r3 + b63e: 6820 ldr r0, [r4, #0] + b640: f010 0010 ands.w r0, r0, #16 + b644: d100 bne.n b648 + b646: bd70 pop {r4, r5, r6, pc} + b648: f242 3050 movw r0, #9040 ; 0x2350 + b64c: f24f 339d movw r3, #62365 ; 0xf39d + b650: f2c0 0004 movt r0, #4 + b654: f2c0 0300 movt r3, #0 + b658: 4798 blx r3 + b65a: 2000 movs r0, #0 + b65c: bd70 pop {r4, r5, r6, pc} + b65e: f242 3050 movw r0, #9040 ; 0x2350 + b662: f24f 339d movw r3, #62365 ; 0xf39d + b666: f2c0 0004 movt r0, #4 + b66a: f2c0 0300 movt r3, #0 + b66e: 4798 blx r3 + b670: e7da b.n b628 + b672: bf00 nop + +0000b674 : + b674: b570 push {r4, r5, r6, lr} + b676: f240 3410 movw r4, #784 ; 0x310 + b67a: f2c1 0400 movt r4, #4096 ; 0x1000 + b67e: 6823 ldr r3, [r4, #0] + b680: 4605 mov r5, r0 + b682: 06db lsls r3, r3, #27 + b684: f100 808a bmi.w b79c + b688: 782a ldrb r2, [r5, #0] + b68a: 2a03 cmp r2, #3 + b68c: d901 bls.n b692 + b68e: 20ee movs r0, #238 ; 0xee + b690: bd70 pop {r4, r5, r6, pc} + b692: 2a02 cmp r2, #2 + b694: d01d beq.n b6d2 + b696: 2a03 cmp r2, #3 + b698: d049 beq.n b72e + b69a: 2a01 cmp r2, #1 + b69c: d032 beq.n b704 + b69e: f44f 730e mov.w r3, #568 ; 0x238 + b6a2: f2c4 0300 movt r3, #16384 ; 0x4000 + b6a6: 681a ldr r2, [r3, #0] + b6a8: 2010 movs r0, #16 + b6aa: f042 0201 orr.w r2, r2, #1 + b6ae: 601a str r2, [r3, #0] + b6b0: 7869 ldrb r1, [r5, #1] + b6b2: 2201 movs r2, #1 + b6b4: f7f7 fa40 bl 2b38 + b6b8: f44f 7306 mov.w r3, #536 ; 0x218 + b6bc: f2c4 0300 movt r3, #16384 ; 0x4000 + b6c0: 681a ldr r2, [r3, #0] + b6c2: f442 3280 orr.w r2, r2, #65536 ; 0x10000 + b6c6: 601a str r2, [r3, #0] + b6c8: 6820 ldr r0, [r4, #0] + b6ca: f010 0010 ands.w r0, r0, #16 + b6ce: d16f bne.n b7b0 + b6d0: bd70 pop {r4, r5, r6, pc} + b6d2: f44f 730e mov.w r3, #568 ; 0x238 + b6d6: f2c4 0300 movt r3, #16384 ; 0x4000 + b6da: 681a ldr r2, [r3, #0] + b6dc: f042 0210 orr.w r2, r2, #16 + b6e0: 601a str r2, [r3, #0] + b6e2: 786e ldrb r6, [r5, #1] + b6e4: 2e01 cmp r6, #1 + b6e6: d03b beq.n b760 + b6e8: 4631 mov r1, r6 + b6ea: 2012 movs r0, #18 + b6ec: 2201 movs r2, #1 + b6ee: f7f7 fa23 bl 2b38 + b6f2: f44f 7306 mov.w r3, #536 ; 0x218 + b6f6: f2c4 0300 movt r3, #16384 ; 0x4000 + b6fa: 681a ldr r2, [r3, #0] + b6fc: f442 2280 orr.w r2, r2, #262144 ; 0x40000 + b700: 601a str r2, [r3, #0] + b702: e7e1 b.n b6c8 + b704: f44f 730e mov.w r3, #568 ; 0x238 + b708: f2c4 0300 movt r3, #16384 ; 0x4000 + b70c: 6819 ldr r1, [r3, #0] + b70e: 2011 movs r0, #17 + b710: f041 0104 orr.w r1, r1, #4 + b714: 6019 str r1, [r3, #0] + b716: 7869 ldrb r1, [r5, #1] + b718: f7f7 fa0e bl 2b38 + b71c: f44f 7306 mov.w r3, #536 ; 0x218 + b720: f2c4 0300 movt r3, #16384 ; 0x4000 + b724: 681a ldr r2, [r3, #0] + b726: f442 3200 orr.w r2, r2, #131072 ; 0x20000 + b72a: 601a str r2, [r3, #0] + b72c: e7cc b.n b6c8 + b72e: f44f 730e mov.w r3, #568 ; 0x238 + b732: f2c4 0300 movt r3, #16384 ; 0x4000 + b736: 681a ldr r2, [r3, #0] + b738: f042 0240 orr.w r2, r2, #64 ; 0x40 + b73c: 601a str r2, [r3, #0] + b73e: 7869 ldrb r1, [r5, #1] + b740: 1e4b subs r3, r1, #1 + b742: 2b01 cmp r3, #1 + b744: d91f bls.n b786 + b746: 2013 movs r0, #19 + b748: 2201 movs r2, #1 + b74a: f7f7 f9f5 bl 2b38 + b74e: f44f 7306 mov.w r3, #536 ; 0x218 + b752: f2c4 0300 movt r3, #16384 ; 0x4000 + b756: 681a ldr r2, [r3, #0] + b758: f442 2200 orr.w r2, r2, #524288 ; 0x80000 + b75c: 601a str r2, [r3, #0] + b75e: e7b3 b.n b6c8 + b760: f44f 7330 mov.w r3, #704 ; 0x2c0 + b764: f2c4 0300 movt r3, #16384 ; 0x4000 + b768: 681a ldr r2, [r3, #0] + b76a: 2100 movs r1, #0 + b76c: f422 3280 bic.w r2, r2, #65536 ; 0x10000 + b770: 601a str r2, [r3, #0] + b772: 20d8 movs r0, #216 ; 0xd8 + b774: 460a mov r2, r1 + b776: f7f7 f9df bl 2b38 + b77a: 7869 ldrb r1, [r5, #1] + b77c: 4632 mov r2, r6 + b77e: 2012 movs r0, #18 + b780: f7f7 f9da bl 2b38 + b784: e7b5 b.n b6f2 + b786: 2100 movs r1, #0 + b788: 460a mov r2, r1 + b78a: 20d8 movs r0, #216 ; 0xd8 + b78c: f7f7 f9d4 bl 2b38 + b790: 7869 ldrb r1, [r5, #1] + b792: 2201 movs r2, #1 + b794: 2013 movs r0, #19 + b796: f7f7 f9cf bl 2b38 + b79a: e7d8 b.n b74e + b79c: f242 3070 movw r0, #9072 ; 0x2370 + b7a0: f24f 339d movw r3, #62365 ; 0xf39d + b7a4: f2c0 0004 movt r0, #4 + b7a8: f2c0 0300 movt r3, #0 + b7ac: 4798 blx r3 + b7ae: e76b b.n b688 + b7b0: f242 3090 movw r0, #9104 ; 0x2390 + b7b4: f24f 339d movw r3, #62365 ; 0xf39d + b7b8: f2c0 0004 movt r0, #4 + b7bc: f2c0 0300 movt r3, #0 + b7c0: 4798 blx r3 + b7c2: 2000 movs r0, #0 + b7c4: bd70 pop {r4, r5, r6, pc} + b7c6: bf00 nop + +0000b7c8 : + b7c8: b538 push {r3, r4, r5, lr} + b7ca: f240 3410 movw r4, #784 ; 0x310 + b7ce: f2c1 0400 movt r4, #4096 ; 0x1000 + b7d2: 6823 ldr r3, [r4, #0] + b7d4: 4605 mov r5, r0 + b7d6: 06db lsls r3, r3, #27 + b7d8: f100 80a7 bmi.w b92a + b7dc: 782b ldrb r3, [r5, #0] + b7de: 2b03 cmp r3, #3 + b7e0: d901 bls.n b7e6 + b7e2: 20ee movs r0, #238 ; 0xee + b7e4: bd38 pop {r3, r4, r5, pc} + b7e6: 2b02 cmp r3, #2 + b7e8: d023 beq.n b832 + b7ea: 2b03 cmp r3, #3 + b7ec: d059 beq.n b8a2 + b7ee: 2b01 cmp r3, #1 + b7f0: d03c beq.n b86c + b7f2: f44f 730e mov.w r3, #568 ; 0x238 + b7f6: f2c4 0300 movt r3, #16384 ; 0x4000 + b7fa: 681a ldr r2, [r3, #0] + b7fc: 2010 movs r0, #16 + b7fe: f022 0201 bic.w r2, r2, #1 + b802: 601a str r2, [r3, #0] + b804: 7869 ldrb r1, [r5, #1] + b806: 2200 movs r2, #0 + b808: f7f7 f996 bl 2b38 + b80c: f44f 4280 mov.w r2, #16384 ; 0x4000 + b810: f44f 7306 mov.w r3, #536 ; 0x218 + b814: f2c4 0300 movt r3, #16384 ; 0x4000 + b818: f2c4 0204 movt r2, #16388 ; 0x4004 + b81c: 6812 ldr r2, [r2, #0] + b81e: 681a ldr r2, [r3, #0] + b820: f422 3280 bic.w r2, r2, #65536 ; 0x10000 + b824: 601a str r2, [r3, #0] + b826: 6820 ldr r0, [r4, #0] + b828: f010 0010 ands.w r0, r0, #16 + b82c: f040 8087 bne.w b93e + b830: bd38 pop {r3, r4, r5, pc} + b832: f44f 730e mov.w r3, #568 ; 0x238 + b836: f2c4 0300 movt r3, #16384 ; 0x4000 + b83a: 681a ldr r2, [r3, #0] + b83c: f022 0210 bic.w r2, r2, #16 + b840: 601a str r2, [r3, #0] + b842: 7869 ldrb r1, [r5, #1] + b844: 2901 cmp r1, #1 + b846: d04a beq.n b8de + b848: 2012 movs r0, #18 + b84a: 2200 movs r2, #0 + b84c: f7f7 f974 bl 2b38 + b850: f44f 5250 mov.w r2, #13312 ; 0x3400 + b854: f44f 7306 mov.w r3, #536 ; 0x218 + b858: f2c4 0300 movt r3, #16384 ; 0x4000 + b85c: f2c4 0200 movt r2, #16384 ; 0x4000 + b860: 6812 ldr r2, [r2, #0] + b862: 681a ldr r2, [r3, #0] + b864: f422 2280 bic.w r2, r2, #262144 ; 0x40000 + b868: 601a str r2, [r3, #0] + b86a: e7dc b.n b826 + b86c: f44f 730e mov.w r3, #568 ; 0x238 + b870: f2c4 0300 movt r3, #16384 ; 0x4000 + b874: 681a ldr r2, [r3, #0] + b876: 2011 movs r0, #17 + b878: f022 0204 bic.w r2, r2, #4 + b87c: 601a str r2, [r3, #0] + b87e: 7869 ldrb r1, [r5, #1] + b880: 2200 movs r2, #0 + b882: f7f7 f959 bl 2b38 + b886: f44f 4288 mov.w r2, #17408 ; 0x4400 + b88a: f44f 7306 mov.w r3, #536 ; 0x218 + b88e: f2c4 0300 movt r3, #16384 ; 0x4000 + b892: f2c4 0204 movt r2, #16388 ; 0x4004 + b896: 6812 ldr r2, [r2, #0] + b898: 681a ldr r2, [r3, #0] + b89a: f422 3200 bic.w r2, r2, #131072 ; 0x20000 + b89e: 601a str r2, [r3, #0] + b8a0: e7c1 b.n b826 + b8a2: f44f 730e mov.w r3, #568 ; 0x238 + b8a6: f2c4 0300 movt r3, #16384 ; 0x4000 + b8aa: 681a ldr r2, [r3, #0] + b8ac: f022 0240 bic.w r2, r2, #64 ; 0x40 + b8b0: 601a str r2, [r3, #0] + b8b2: 7869 ldrb r1, [r5, #1] + b8b4: 1e4b subs r3, r1, #1 + b8b6: 2b01 cmp r3, #1 + b8b8: d924 bls.n b904 + b8ba: 2013 movs r0, #19 + b8bc: 2200 movs r2, #0 + b8be: f7f7 f93b bl 2b38 + b8c2: f44f 5260 mov.w r2, #14336 ; 0x3800 + b8c6: f44f 7306 mov.w r3, #536 ; 0x218 + b8ca: f2c4 0300 movt r3, #16384 ; 0x4000 + b8ce: f2c4 0200 movt r2, #16384 ; 0x4000 + b8d2: 6812 ldr r2, [r2, #0] + b8d4: 681a ldr r2, [r3, #0] + b8d6: f422 2200 bic.w r2, r2, #524288 ; 0x80000 + b8da: 601a str r2, [r3, #0] + b8dc: e7a3 b.n b826 + b8de: f44f 7330 mov.w r3, #704 ; 0x2c0 + b8e2: f2c4 0300 movt r3, #16384 ; 0x4000 + b8e6: 6818 ldr r0, [r3, #0] + b8e8: 460a mov r2, r1 + b8ea: f440 3180 orr.w r1, r0, #65536 ; 0x10000 + b8ee: 6019 str r1, [r3, #0] + b8f0: 20d8 movs r0, #216 ; 0xd8 + b8f2: 2100 movs r1, #0 + b8f4: f7f7 f920 bl 2b38 + b8f8: 7869 ldrb r1, [r5, #1] + b8fa: 2200 movs r2, #0 + b8fc: 2012 movs r0, #18 + b8fe: f7f7 f91b bl 2b38 + b902: e7a5 b.n b850 + b904: f44f 7330 mov.w r3, #704 ; 0x2c0 + b908: f2c4 0300 movt r3, #16384 ; 0x4000 + b90c: 681a ldr r2, [r3, #0] + b90e: 2100 movs r1, #0 + b910: f442 3280 orr.w r2, r2, #65536 ; 0x10000 + b914: 601a str r2, [r3, #0] + b916: 20d8 movs r0, #216 ; 0xd8 + b918: 2201 movs r2, #1 + b91a: f7f7 f90d bl 2b38 + b91e: 7869 ldrb r1, [r5, #1] + b920: 2200 movs r2, #0 + b922: 2013 movs r0, #19 + b924: f7f7 f908 bl 2b38 + b928: e7cb b.n b8c2 + b92a: f242 30b0 movw r0, #9136 ; 0x23b0 + b92e: f24f 339d movw r3, #62365 ; 0xf39d + b932: f2c0 0004 movt r0, #4 + b936: f2c0 0300 movt r3, #0 + b93a: 4798 blx r3 + b93c: e74e b.n b7dc + b93e: f242 30d4 movw r0, #9172 ; 0x23d4 + b942: f24f 339d movw r3, #62365 ; 0xf39d + b946: f2c0 0004 movt r0, #4 + b94a: f2c0 0300 movt r3, #0 + b94e: 4798 blx r3 + b950: 2000 movs r0, #0 + b952: bd38 pop {r3, r4, r5, pc} + +0000b954 : + b954: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + b958: f240 3610 movw r6, #784 ; 0x310 + b95c: f2c1 0600 movt r6, #4096 ; 0x1000 + b960: 6832 ldr r2, [r6, #0] + b962: f850 4c04 ldr.w r4, [r0, #-4] + b966: 6b03 ldr r3, [r0, #48] ; 0x30 + b968: b087 sub sp, #28 + b96a: 06d1 lsls r1, r2, #27 + b96c: 4605 mov r5, r0 + b96e: f8d4 8028 ldr.w r8, [r4, #40] ; 0x28 + b972: 6ae7 ldr r7, [r4, #44] ; 0x2c + b974: f8d4 9030 ldr.w r9, [r4, #48] ; 0x30 + b978: f8d4 a038 ldr.w sl, [r4, #56] ; 0x38 + b97c: f8d4 b03c ldr.w fp, [r4, #60] ; 0x3c + b980: 9300 str r3, [sp, #0] + b982: f100 8162 bmi.w bc4a + b986: 782a ldrb r2, [r5, #0] + b988: 2a03 cmp r2, #3 + b98a: d802 bhi.n b992 + b98c: 78a9 ldrb r1, [r5, #2] + b98e: 2901 cmp r1, #1 + b990: d003 beq.n b99a + b992: 20ee movs r0, #238 ; 0xee + b994: b007 add sp, #28 + b996: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + b99a: 2a01 cmp r2, #1 + b99c: d8f9 bhi.n b992 + b99e: 6b62 ldr r2, [r4, #52] ; 0x34 + b9a0: 4648 mov r0, r9 + b9a2: 4790 blx r2 + b9a4: f44f 7141 mov.w r1, #772 ; 0x304 + b9a8: f2c4 0100 movt r1, #16384 ; 0x4000 + b9ac: 6832 ldr r2, [r6, #0] + b9ae: f8d1 c000 ldr.w ip, [r1] + b9b2: 06d3 lsls r3, r2, #27 + b9b4: f100 815e bmi.w bc74 + b9b8: 782a ldrb r2, [r5, #0] + b9ba: 2103 movs r1, #3 + b9bc: 320c adds r2, #12 + b9be: 0052 lsls r2, r2, #1 + b9c0: 4091 lsls r1, r2 + b9c2: 43c9 mvns r1, r1 + b9c4: 7ae8 ldrb r0, [r5, #11] + b9c6: ea01 020c and.w r2, r1, ip + b9ca: b108 cbz r0, b9d0 + b9cc: ea62 0201 orn r2, r2, r1 + b9d0: f44f 7141 mov.w r1, #772 ; 0x304 + b9d4: f2c4 0100 movt r1, #16384 ; 0x4000 + b9d8: 600a str r2, [r1, #0] + b9da: 6832 ldr r2, [r6, #0] + b9dc: 06d2 lsls r2, r2, #27 + b9de: f100 813e bmi.w bc5e + b9e2: 7aea ldrb r2, [r5, #11] + b9e4: 2a00 cmp r2, #0 + b9e6: f040 8113 bne.w bc10 + b9ea: f44f 720c mov.w r2, #560 ; 0x230 + b9ee: f2c4 0200 movt r2, #16384 ; 0x4000 + b9f2: f44f 7104 mov.w r1, #528 ; 0x210 + b9f6: f2c4 0100 movt r1, #16384 ; 0x4000 + b9fa: 6810 ldr r0, [r2, #0] + b9fc: f440 3080 orr.w r0, r0, #65536 ; 0x10000 + ba00: 6010 str r0, [r2, #0] + ba02: 6810 ldr r0, [r2, #0] + ba04: f440 3000 orr.w r0, r0, #131072 ; 0x20000 + ba08: 6010 str r0, [r2, #0] + ba0a: 680a ldr r2, [r1, #0] + ba0c: f442 5200 orr.w r2, r2, #8192 ; 0x2000 + ba10: 600a str r2, [r1, #0] + ba12: f24f 5311 movw r3, #62737 ; 0xf511 + ba16: f2c0 0300 movt r3, #0 + ba1a: 2100 movs r1, #0 + ba1c: 2268 movs r2, #104 ; 0x68 + ba1e: 4640 mov r0, r8 + ba20: 9305 str r3, [sp, #20] + ba22: 4798 blx r3 + ba24: f898 2028 ldrb.w r2, [r8, #40] ; 0x28 + ba28: 9b00 ldr r3, [sp, #0] + ba2a: f042 0201 orr.w r2, r2, #1 + ba2e: f888 2028 strb.w r2, [r8, #40] ; 0x28 + ba32: 7819 ldrb r1, [r3, #0] + ba34: b2d2 uxtb r2, r2 + ba36: f8c8 1014 str.w r1, [r8, #20] + ba3a: 7859 ldrb r1, [r3, #1] + ba3c: f042 0220 orr.w r2, r2, #32 + ba40: f8c8 1010 str.w r1, [r8, #16] + ba44: f893 e002 ldrb.w lr, [r3, #2] + ba48: 2000 movs r0, #0 + ba4a: f8c8 e024 str.w lr, [r8, #36] ; 0x24 + ba4e: f893 e003 ldrb.w lr, [r3, #3] + ba52: 2102 movs r1, #2 + ba54: f888 2028 strb.w r2, [r8, #40] ; 0x28 + ba58: 2201 movs r2, #1 + ba5a: f8c8 e020 str.w lr, [r8, #32] + ba5e: f8c8 001c str.w r0, [r8, #28] + ba62: f8c8 1018 str.w r1, [r8, #24] + ba66: f8c8 200c str.w r2, [r8, #12] + ba6a: 782a ldrb r2, [r5, #0] + ba6c: 2a00 cmp r2, #0 + ba6e: f040 80e8 bne.w bc42 + ba72: 2208 movs r2, #8 + ba74: f888 203b strb.w r2, [r8, #59] ; 0x3b + ba78: f244 03f1 movw r3, #16625 ; 0x40f1 + ba7c: f241 2ca0 movw ip, #4768 ; 0x12a0 + ba80: f898 e063 ldrb.w lr, [r8, #99] ; 0x63 + ba84: 7ae8 ldrb r0, [r5, #11] + ba86: 9304 str r3, [sp, #16] + ba88: 2300 movs r3, #0 + ba8a: f8c8 3048 str.w r3, [r8, #72] ; 0x48 + ba8e: f04e 0e03 orr.w lr, lr, #3 + ba92: 2201 movs r2, #1 + ba94: 9b00 ldr r3, [sp, #0] + ba96: 2113 movs r1, #19 + ba98: f888 e063 strb.w lr, [r8, #99] ; 0x63 + ba9c: f888 0062 strb.w r0, [r8, #98] ; 0x62 + baa0: f8c8 204c str.w r2, [r8, #76] ; 0x4c + baa4: f888 1064 strb.w r1, [r8, #100] ; 0x64 + baa8: 7919 ldrb r1, [r3, #4] + baaa: f244 0329 movw r3, #16425 ; 0x4029 + baae: f2c0 0c03 movt ip, #3 + bab2: f888 1061 strb.w r1, [r8, #97] ; 0x61 + bab6: 1888 adds r0, r1, r2 + bab8: f04f 0102 mov.w r1, #2 + babc: f2c0 0300 movt r3, #0 + bac0: f83c 0010 ldrh.w r0, [ip, r0, lsl #1] + bac4: f888 1060 strb.w r1, [r8, #96] ; 0x60 + bac8: f8c8 0008 str.w r0, [r8, #8] + bacc: f8ca 5008 str.w r5, [sl, #8] + bad0: 7ae9 ldrb r1, [r5, #11] + bad2: f898 0061 ldrb.w r0, [r8, #97] ; 0x61 + bad6: eb01 0141 add.w r1, r1, r1, lsl #1 + bada: 3014 adds r0, #20 + badc: eb00 0141 add.w r1, r0, r1, lsl #1 + bae0: f8ca 1004 str.w r1, [sl, #4] + bae4: 6c21 ldr r1, [r4, #64] ; 0x40 + bae6: 4650 mov r0, sl + bae8: f8ca 1000 str.w r1, [sl] + baec: f8ca 200c str.w r2, [sl, #12] + baf0: f8cd c008 str.w ip, [sp, #8] + baf4: 9303 str r3, [sp, #12] + baf6: 4798 blx r3 + baf8: 9b04 ldr r3, [sp, #16] + bafa: 4650 mov r0, sl + bafc: f2c0 0300 movt r3, #0 + bb00: 9304 str r3, [sp, #16] + bb02: 4798 blx r3 + bb04: f8d9 2000 ldr.w r2, [r9] + bb08: 4640 mov r0, r8 + bb0a: 4790 blx r2 + bb0c: f8d9 2018 ldr.w r2, [r9, #24] + bb10: 4640 mov r0, r8 + bb12: 4790 blx r2 + bb14: f8d9 2008 ldr.w r2, [r9, #8] + bb18: 4640 mov r0, r8 + bb1a: 4790 blx r2 + bb1c: 2100 movs r1, #0 + bb1e: 2268 movs r2, #104 ; 0x68 + bb20: 9b05 ldr r3, [sp, #20] + bb22: 4638 mov r0, r7 + bb24: 4798 blx r3 + bb26: f897 2028 ldrb.w r2, [r7, #40] ; 0x28 + bb2a: 9b00 ldr r3, [sp, #0] + bb2c: f042 0201 orr.w r2, r2, #1 + bb30: f887 2028 strb.w r2, [r7, #40] ; 0x28 + bb34: 7a19 ldrb r1, [r3, #8] + bb36: b2d2 uxtb r2, r2 + bb38: 6179 str r1, [r7, #20] + bb3a: 7a59 ldrb r1, [r3, #9] + bb3c: f042 0220 orr.w r2, r2, #32 + bb40: 6139 str r1, [r7, #16] + bb42: 7a99 ldrb r1, [r3, #10] + bb44: f8dd c008 ldr.w ip, [sp, #8] + bb48: 6279 str r1, [r7, #36] ; 0x24 + bb4a: 7ad9 ldrb r1, [r3, #11] + bb4c: 2300 movs r3, #0 + bb4e: 6239 str r1, [r7, #32] + bb50: 2102 movs r1, #2 + bb52: 61bb str r3, [r7, #24] + bb54: 61f9 str r1, [r7, #28] + bb56: 60f9 str r1, [r7, #12] + bb58: f887 2028 strb.w r2, [r7, #40] ; 0x28 + bb5c: 782a ldrb r2, [r5, #0] + bb5e: 2a00 cmp r2, #0 + bb60: d16b bne.n bc3a + bb62: 2209 movs r2, #9 + bb64: f887 203a strb.w r2, [r7, #58] ; 0x3a + bb68: f897 203d ldrb.w r2, [r7, #61] ; 0x3d + bb6c: f897 0063 ldrb.w r0, [r7, #99] ; 0x63 + bb70: f042 0201 orr.w r2, r2, #1 + bb74: f887 203d strb.w r2, [r7, #61] ; 0x3d + bb78: 7ae9 ldrb r1, [r5, #11] + bb7a: 2201 movs r2, #1 + bb7c: f887 1062 strb.w r1, [r7, #98] ; 0x62 + bb80: 2113 movs r1, #19 + bb82: f887 1064 strb.w r1, [r7, #100] ; 0x64 + bb86: f040 0003 orr.w r0, r0, #3 + bb8a: 9900 ldr r1, [sp, #0] + bb8c: f04f 0800 mov.w r8, #0 + bb90: 64fa str r2, [r7, #76] ; 0x4c + bb92: f887 0063 strb.w r0, [r7, #99] ; 0x63 + bb96: f8c7 8048 str.w r8, [r7, #72] ; 0x48 + bb9a: 7b0b ldrb r3, [r1, #12] + bb9c: 2103 movs r1, #3 + bb9e: 1898 adds r0, r3, r2 + bba0: f83c 0010 ldrh.w r0, [ip, r0, lsl #1] + bba4: f887 3061 strb.w r3, [r7, #97] ; 0x61 + bba8: 60b8 str r0, [r7, #8] + bbaa: f887 1060 strb.w r1, [r7, #96] ; 0x60 + bbae: f8cb 5008 str.w r5, [fp, #8] + bbb2: 7aeb ldrb r3, [r5, #11] + bbb4: f897 0061 ldrb.w r0, [r7, #97] ; 0x61 + bbb8: 6c61 ldr r1, [r4, #68] ; 0x44 + bbba: 3014 adds r0, #20 + bbbc: eb03 0343 add.w r3, r3, r3, lsl #1 + bbc0: eb00 0343 add.w r3, r0, r3, lsl #1 + bbc4: e88b 000a stmia.w fp, {r1, r3} + bbc8: f8cb 200c str.w r2, [fp, #12] + bbcc: 9b03 ldr r3, [sp, #12] + bbce: 4658 mov r0, fp + bbd0: 4798 blx r3 + bbd2: 4658 mov r0, fp + bbd4: 9b04 ldr r3, [sp, #16] + bbd6: 4798 blx r3 + bbd8: f8d9 3000 ldr.w r3, [r9] + bbdc: 4638 mov r0, r7 + bbde: 4798 blx r3 + bbe0: f8d9 3018 ldr.w r3, [r9, #24] + bbe4: 4638 mov r0, r7 + bbe6: 4798 blx r3 + bbe8: f8d9 3008 ldr.w r3, [r9, #8] + bbec: 4638 mov r0, r7 + bbee: 4798 blx r3 + bbf0: 6830 ldr r0, [r6, #0] + bbf2: f010 0010 ands.w r0, r0, #16 + bbf6: f43f aecd beq.w b994 + bbfa: f242 4080 movw r0, #9344 ; 0x2480 + bbfe: f24f 339d movw r3, #62365 ; 0xf39d + bc02: f2c0 0004 movt r0, #4 + bc06: f2c0 0300 movt r3, #0 + bc0a: 4798 blx r3 + bc0c: 4640 mov r0, r8 + bc0e: e6c1 b.n b994 + bc10: f44f 720c mov.w r2, #560 ; 0x230 + bc14: f2c4 0200 movt r2, #16384 ; 0x4000 + bc18: f44f 7104 mov.w r1, #528 ; 0x210 + bc1c: f2c4 0100 movt r1, #16384 ; 0x4000 + bc20: 6810 ldr r0, [r2, #0] + bc22: f440 2080 orr.w r0, r0, #262144 ; 0x40000 + bc26: 6010 str r0, [r2, #0] + bc28: 6810 ldr r0, [r2, #0] + bc2a: f440 2000 orr.w r0, r0, #524288 ; 0x80000 + bc2e: 6010 str r0, [r2, #0] + bc30: 680a ldr r2, [r1, #0] + bc32: f442 4280 orr.w r2, r2, #16384 ; 0x4000 + bc36: 600a str r2, [r1, #0] + bc38: e6eb b.n ba12 + bc3a: 220b movs r2, #11 + bc3c: f887 203a strb.w r2, [r7, #58] ; 0x3a + bc40: e792 b.n bb68 + bc42: 220a movs r2, #10 + bc44: f888 203b strb.w r2, [r8, #59] ; 0x3b + bc48: e716 b.n ba78 + bc4a: f242 30f8 movw r0, #9208 ; 0x23f8 + bc4e: f24f 329d movw r2, #62365 ; 0xf39d + bc52: f2c0 0004 movt r0, #4 + bc56: f2c0 0200 movt r2, #0 + bc5a: 4790 blx r2 + bc5c: e693 b.n b986 + bc5e: f242 4050 movw r0, #9296 ; 0x2450 + bc62: f24f 3c9d movw ip, #62365 ; 0xf39d + bc66: 680a ldr r2, [r1, #0] + bc68: f2c0 0c00 movt ip, #0 + bc6c: f2c0 0004 movt r0, #4 + bc70: 47e0 blx ip + bc72: e6b6 b.n b9e2 + bc74: f242 4018 movw r0, #9240 ; 0x2418 + bc78: f24f 339d movw r3, #62365 ; 0xf39d + bc7c: 4662 mov r2, ip + bc7e: f8cd c008 str.w ip, [sp, #8] + bc82: f2c0 0004 movt r0, #4 + bc86: f2c0 0300 movt r3, #0 + bc8a: 4798 blx r3 + bc8c: f8dd c008 ldr.w ip, [sp, #8] + bc90: e692 b.n b9b8 + bc92: bf00 nop + +0000bc94 : + bc94: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + bc98: f240 3610 movw r6, #784 ; 0x310 + bc9c: f2c1 0600 movt r6, #4096 ; 0x1000 + bca0: 6833 ldr r3, [r6, #0] + bca2: f850 7c04 ldr.w r7, [r0, #-4] + bca6: 06db lsls r3, r3, #27 + bca8: 4604 mov r4, r0 + bcaa: 687d ldr r5, [r7, #4] + bcac: f8d7 8008 ldr.w r8, [r7, #8] + bcb0: d466 bmi.n bd80 + bcb2: 7823 ldrb r3, [r4, #0] + bcb4: 2b03 cmp r3, #3 + bcb6: d902 bls.n bcbe + bcb8: 20ee movs r0, #238 ; 0xee + bcba: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + bcbe: 68fb ldr r3, [r7, #12] + bcc0: 4640 mov r0, r8 + bcc2: 4798 blx r3 + bcc4: f24b 534d movw r3, #46413 ; 0xb54d + bcc8: 4620 mov r0, r4 + bcca: f2c0 0300 movt r3, #0 + bcce: 4798 blx r3 + bcd0: f64b 1355 movw r3, #47445 ; 0xb955 + bcd4: 4620 mov r0, r4 + bcd6: f2c0 0300 movt r3, #0 + bcda: 4798 blx r3 + bcdc: f24b 6375 movw r3, #46709 ; 0xb675 + bce0: 4620 mov r0, r4 + bce2: f2c0 0300 movt r3, #0 + bce6: 4798 blx r3 + bce8: 7823 ldrb r3, [r4, #0] + bcea: 702b strb r3, [r5, #0] + bcec: 7923 ldrb r3, [r4, #4] + bcee: 70ab strb r3, [r5, #2] + bcf0: 7963 ldrb r3, [r4, #5] + bcf2: 70eb strb r3, [r5, #3] + bcf4: 79a3 ldrb r3, [r4, #6] + bcf6: 712b strb r3, [r5, #4] + bcf8: 8922 ldrh r2, [r4, #8] + bcfa: 6963 ldr r3, [r4, #20] + bcfc: 79e1 ldrb r1, [r4, #7] + bcfe: 622a str r2, [r5, #32] + bd00: 07da lsls r2, r3, #31 + bd02: 83a9 strh r1, [r5, #28] + bd04: d42f bmi.n bd66 + bd06: 0798 lsls r0, r3, #30 + bd08: bf42 ittt mi + bd0a: 2301 movmi r3, #1 + bd0c: 72ab strbmi r3, [r5, #10] + bd0e: 6963 ldrmi r3, [r4, #20] + bd10: 0759 lsls r1, r3, #29 + bd12: bf42 ittt mi + bd14: 2301 movmi r3, #1 + bd16: 72eb strbmi r3, [r5, #11] + bd18: 6963 ldrmi r3, [r4, #20] + bd1a: 071a lsls r2, r3, #28 + bd1c: bf42 ittt mi + bd1e: 2301 movmi r3, #1 + bd20: 732b strbmi r3, [r5, #12] + bd22: 6963 ldrmi r3, [r4, #20] + bd24: 06df lsls r7, r3, #27 + bd26: bf42 ittt mi + bd28: 2301 movmi r3, #1 + bd2a: 722b strbmi r3, [r5, #8] + bd2c: 6963 ldrmi r3, [r4, #20] + bd2e: 0698 lsls r0, r3, #26 + bd30: bf44 itt mi + bd32: 2301 movmi r3, #1 + bd34: 742b strbmi r3, [r5, #16] + bd36: f8d8 3000 ldr.w r3, [r8] + bd3a: 4628 mov r0, r5 + bd3c: 4798 blx r3 + bd3e: 2301 movs r3, #1 + bd40: 70e3 strb r3, [r4, #3] + bd42: 706b strb r3, [r5, #1] + bd44: f8d8 3010 ldr.w r3, [r8, #16] + bd48: 4628 mov r0, r5 + bd4a: 4798 blx r3 + bd4c: 7923 ldrb r3, [r4, #4] + bd4e: b913 cbnz r3, bd56 + bd50: 6963 ldr r3, [r4, #20] + bd52: 0699 lsls r1, r3, #26 + bd54: d40b bmi.n bd6e + bd56: 2302 movs r3, #2 + bd58: 70e3 strb r3, [r4, #3] + bd5a: 6830 ldr r0, [r6, #0] + bd5c: f010 0010 ands.w r0, r0, #16 + bd60: d118 bne.n bd94 + bd62: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + bd66: 2301 movs r3, #1 + bd68: 726b strb r3, [r5, #9] + bd6a: 6963 ldr r3, [r4, #20] + bd6c: e7cb b.n bd06 + bd6e: 8b2a ldrh r2, [r5, #24] + bd70: f8d8 3014 ldr.w r3, [r8, #20] + bd74: f442 6200 orr.w r2, r2, #2048 ; 0x800 + bd78: 832a strh r2, [r5, #24] + bd7a: 4628 mov r0, r5 + bd7c: 4798 blx r3 + bd7e: e7ea b.n bd56 + bd80: f242 40a0 movw r0, #9376 ; 0x24a0 + bd84: f24f 339d movw r3, #62365 ; 0xf39d + bd88: f2c0 0004 movt r0, #4 + bd8c: f2c0 0300 movt r3, #0 + bd90: 4798 blx r3 + bd92: e78e b.n bcb2 + bd94: f242 40bc movw r0, #9404 ; 0x24bc + bd98: f24f 339d movw r3, #62365 ; 0xf39d + bd9c: f2c0 0004 movt r0, #4 + bda0: f2c0 0300 movt r3, #0 + bda4: 4798 blx r3 + bda6: 2000 movs r0, #0 + bda8: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +0000bdac : + bdac: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} + bdb0: f240 3410 movw r4, #784 ; 0x310 + bdb4: f2c1 0400 movt r4, #4096 ; 0x1000 + bdb8: f850 3c04 ldr.w r3, [r0, #-4] + bdbc: 6822 ldr r2, [r4, #0] + bdbe: f8d3 8028 ldr.w r8, [r3, #40] ; 0x28 + bdc2: f8d3 902c ldr.w r9, [r3, #44] ; 0x2c + bdc6: 6b19 ldr r1, [r3, #48] ; 0x30 + bdc8: 6b9f ldr r7, [r3, #56] ; 0x38 + bdca: 6bde ldr r6, [r3, #60] ; 0x3c + bdcc: 06d3 lsls r3, r2, #27 + bdce: b082 sub sp, #8 + bdd0: 4605 mov r5, r0 + bdd2: d42f bmi.n be34 + bdd4: 782b ldrb r3, [r5, #0] + bdd6: 2b03 cmp r3, #3 + bdd8: d802 bhi.n bde0 + bdda: 78aa ldrb r2, [r5, #2] + bddc: 2a01 cmp r2, #1 + bdde: d003 beq.n bde8 + bde0: 20ee movs r0, #238 ; 0xee + bde2: b002 add sp, #8 + bde4: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + bde8: 2b01 cmp r3, #1 + bdea: d8f9 bhi.n bde0 + bdec: f244 0a91 movw sl, #16529 ; 0x4091 + bdf0: 4638 mov r0, r7 + bdf2: f2c0 0a00 movt sl, #0 + bdf6: 9101 str r1, [sp, #4] + bdf8: 47d0 blx sl + bdfa: 4630 mov r0, r6 + bdfc: 47d0 blx sl + bdfe: 78eb ldrb r3, [r5, #3] + be00: 9901 ldr r1, [sp, #4] + be02: b973 cbnz r3, be22 + be04: 6820 ldr r0, [r4, #0] + be06: f010 0010 ands.w r0, r0, #16 + be0a: d0ea beq.n bde2 + be0c: f242 40f8 movw r0, #9464 ; 0x24f8 + be10: f24f 339d movw r3, #62365 ; 0xf39d + be14: f2c0 0004 movt r0, #4 + be18: f2c0 0300 movt r3, #0 + be1c: 4798 blx r3 + be1e: 2000 movs r0, #0 + be20: e7df b.n bde2 + be22: 690b ldr r3, [r1, #16] + be24: 4640 mov r0, r8 + be26: 9101 str r1, [sp, #4] + be28: 4798 blx r3 + be2a: 9901 ldr r1, [sp, #4] + be2c: 4648 mov r0, r9 + be2e: 690b ldr r3, [r1, #16] + be30: 4798 blx r3 + be32: e7e7 b.n be04 + be34: f242 40d8 movw r0, #9432 ; 0x24d8 + be38: f24f 339d movw r3, #62365 ; 0xf39d + be3c: 9101 str r1, [sp, #4] + be3e: f2c0 0004 movt r0, #4 + be42: f2c0 0300 movt r3, #0 + be46: 4798 blx r3 + be48: 9901 ldr r1, [sp, #4] + be4a: e7c3 b.n bdd4 + +0000be4c : + be4c: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + be50: 4604 mov r4, r0 + be52: b370 cbz r0, beb2 + be54: f240 3510 movw r5, #784 ; 0x310 + be58: f2c1 0500 movt r5, #4096 ; 0x1000 + be5c: 682b ldr r3, [r5, #0] + be5e: f850 7c04 ldr.w r7, [r0, #-4] + be62: 06db lsls r3, r3, #27 + be64: f8d7 8004 ldr.w r8, [r7, #4] + be68: 68be ldr r6, [r7, #8] + be6a: d431 bmi.n bed0 + be6c: 68fb ldr r3, [r7, #12] + be6e: 4630 mov r0, r6 + be70: 4798 blx r3 + be72: 6873 ldr r3, [r6, #4] + be74: 4640 mov r0, r8 + be76: 4798 blx r3 + be78: f24b 6311 movw r3, #46609 ; 0xb611 + be7c: 4620 mov r0, r4 + be7e: f2c0 0300 movt r3, #0 + be82: 4798 blx r3 + be84: f64b 53ad movw r3, #48557 ; 0xbdad + be88: 4620 mov r0, r4 + be8a: f2c0 0300 movt r3, #0 + be8e: 4798 blx r3 + be90: f24b 73c9 movw r3, #47049 ; 0xb7c9 + be94: 4620 mov r0, r4 + be96: f2c0 0300 movt r3, #0 + be9a: 4798 blx r3 + be9c: 2700 movs r7, #0 + be9e: 6873 ldr r3, [r6, #4] + bea0: 4640 mov r0, r8 + bea2: 4798 blx r3 + bea4: 70e7 strb r7, [r4, #3] + bea6: 6828 ldr r0, [r5, #0] + bea8: f010 0010 ands.w r0, r0, #16 + beac: d104 bne.n beb8 + beae: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + beb2: 20ee movs r0, #238 ; 0xee + beb4: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + beb8: f242 5034 movw r0, #9524 ; 0x2534 + bebc: f24f 339d movw r3, #62365 ; 0xf39d + bec0: f2c0 0004 movt r0, #4 + bec4: f2c0 0300 movt r3, #0 + bec8: 4798 blx r3 + beca: 4638 mov r0, r7 + becc: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + bed0: f242 5018 movw r0, #9496 ; 0x2518 + bed4: f24f 339d movw r3, #62365 ; 0xf39d + bed8: f2c0 0004 movt r0, #4 + bedc: f2c0 0300 movt r3, #0 + bee0: 4798 blx r3 + bee2: e7c3 b.n be6c + +0000bee4 : + bee4: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + bee8: f850 2c04 ldr.w r2, [r0, #-4] + beec: 6943 ldr r3, [r0, #20] + beee: 6854 ldr r4, [r2, #4] + bef0: 6895 ldr r5, [r2, #8] + bef2: 69d7 ldr r7, [r2, #28] + bef4: 065a lsls r2, r3, #25 + bef6: b083 sub sp, #12 + bef8: 4606 mov r6, r0 + befa: f140 80a3 bpl.w c044 + befe: f640 0899 movw r8, #2201 ; 0x899 + bf02: 46b9 mov r9, r7 + bf04: f242 7a10 movw sl, #10000 ; 0x2710 + bf08: f2c0 0800 movt r8, #0 + bf0c: f04f 0b00 mov.w fp, #0 + bf10: 460f mov r7, r1 + bf12: e02a b.n bf6a + bf14: f04f 0002 mov.w r0, #2 + bf18: f884 b00e strb.w fp, [r4, #14] + bf1c: f884 b011 strb.w fp, [r4, #17] + bf20: 73e0 strb r0, [r4, #15] + bf22: 2f00 cmp r7, #0 + bf24: d12f bne.n bf86 + bf26: 6a73 ldr r3, [r6, #36] ; 0x24 + bf28: 685b ldr r3, [r3, #4] + bf2a: f3c3 2207 ubfx r2, r3, #8, #8 + bf2e: f88d 3005 strb.w r3, [sp, #5] + bf32: f88d 2004 strb.w r2, [sp, #4] + bf36: a801 add r0, sp, #4 + bf38: 6160 str r0, [r4, #20] + bf3a: 6a6b ldr r3, [r5, #36] ; 0x24 + bf3c: 4620 mov r0, r4 + bf3e: 4798 blx r3 + bf40: 6973 ldr r3, [r6, #20] + bf42: 05d8 lsls r0, r3, #23 + bf44: d52d bpl.n bfa2 + bf46: 6a20 ldr r0, [r4, #32] + bf48: fbba f0f0 udiv r0, sl, r0 + bf4c: 3002 adds r0, #2 + bf4e: 47c0 blx r8 + bf50: 2134 movs r1, #52 ; 0x34 + bf52: 69ab ldr r3, [r5, #24] + bf54: 4620 mov r0, r4 + bf56: 4798 blx r3 + bf58: f010 0f40 tst.w r0, #64 ; 0x40 + bf5c: f04f 0154 mov.w r1, #84 ; 0x54 + bf60: d01f beq.n bfa2 + bf62: 69ab ldr r3, [r5, #24] + bf64: 4620 mov r0, r4 + bf66: 4798 blx r3 + bf68: 6973 ldr r3, [r6, #20] + bf6a: f013 0380 ands.w r3, r3, #128 ; 0x80 + bf6e: d1d1 bne.n bf14 + bf70: 73a3 strb r3, [r4, #14] + bf72: 7463 strb r3, [r4, #17] + bf74: f04f 0301 mov.w r3, #1 + bf78: 73e3 strb r3, [r4, #15] + bf7a: b96f cbnz r7, bf98 + bf7c: 6a73 ldr r3, [r6, #36] ; 0x24 + bf7e: 685b ldr r3, [r3, #4] + bf80: f88d 3004 strb.w r3, [sp, #4] + bf84: e7d7 b.n bf36 + bf86: 6ab3 ldr r3, [r6, #40] ; 0x28 + bf88: 685b ldr r3, [r3, #4] + bf8a: f3c3 2207 ubfx r2, r3, #8, #8 + bf8e: f88d 3005 strb.w r3, [sp, #5] + bf92: f88d 2004 strb.w r2, [sp, #4] + bf96: e7ce b.n bf36 + bf98: 6ab3 ldr r3, [r6, #40] ; 0x28 + bf9a: 685b ldr r3, [r3, #4] + bf9c: f88d 3004 strb.w r3, [sp, #4] + bfa0: e7c9 b.n bf36 + bfa2: f109 33ff add.w r3, r9, #4294967295 + bfa6: 3303 adds r3, #3 + bfa8: bf88 it hi + bfaa: f04f 0a00 movhi.w sl, #0 + bfae: 464f mov r7, r9 + bfb0: bf88 it hi + bfb2: 46d0 movhi r8, sl + bfb4: d816 bhi.n bfe4 + bfb6: f241 0285 movw r2, #4229 ; 0x1085 + bfba: f240 3318 movw r3, #792 ; 0x318 + bfbe: f6c0 0242 movt r2, #2114 ; 0x842 + bfc2: f2c1 0300 movt r3, #4096 ; 0x1000 + bfc6: f44f 717a mov.w r1, #1000 ; 0x3e8 + bfca: fb01 f107 mul.w r1, r1, r7 + bfce: fba2 0201 umull r0, r2, r2, r1 + bfd2: 1a89 subs r1, r1, r2 + bfd4: eb02 0251 add.w r2, r2, r1, lsr #1 + bfd8: 689b ldr r3, [r3, #8] + bfda: 2001 movs r0, #1 + bfdc: ea4f 1812 mov.w r8, r2, lsr #4 + bfe0: 4798 blx r3 + bfe2: 4682 mov sl, r0 + bfe4: f64a 4965 movw r9, #44133 ; 0xac65 + bfe8: f2c0 0900 movt r9, #0 + bfec: 69ab ldr r3, [r5, #24] + bfee: 4620 mov r0, r4 + bff0: 2170 movs r1, #112 ; 0x70 + bff2: 4798 blx r3 + bff4: f000 0006 and.w r0, r0, #6 + bff8: 2806 cmp r0, #6 + bffa: d023 beq.n c044 + bffc: f1b8 0f00 cmp.w r8, #0 + c000: d124 bne.n c04c + c002: 2f00 cmp r7, #0 + c004: d1f2 bne.n bfec + c006: f240 3514 movw r5, #788 ; 0x314 + c00a: f2c1 0500 movt r5, #4096 ; 0x1000 + c00e: 2311 movs r3, #17 + c010: 70f3 strb r3, [r6, #3] + c012: 682b ldr r3, [r5, #0] + c014: 2220 movs r2, #32 + c016: 61b2 str r2, [r6, #24] + c018: 06da lsls r2, r3, #27 + c01a: d513 bpl.n c044 + c01c: f242 5080 movw r0, #9600 ; 0x2580 + c020: f24f 349d movw r4, #62365 ; 0xf39d + c024: f2c0 0004 movt r0, #4 + c028: f2c0 0400 movt r4, #0 + c02c: 7831 ldrb r1, [r6, #0] + c02e: 47a0 blx r4 + c030: 682b ldr r3, [r5, #0] + c032: 06db lsls r3, r3, #27 + c034: d506 bpl.n c044 + c036: f242 2050 movw r0, #8784 ; 0x2250 + c03a: 78f1 ldrb r1, [r6, #3] + c03c: f2c0 0004 movt r0, #4 + c040: 69b2 ldr r2, [r6, #24] + c042: 47a0 blx r4 + c044: 2000 movs r0, #0 + c046: b003 add sp, #12 + c048: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + c04c: 4650 mov r0, sl + c04e: 4641 mov r1, r8 + c050: 47c8 blx r9 + c052: 2802 cmp r0, #2 + c054: d1ca bne.n bfec + c056: f240 3514 movw r5, #788 ; 0x314 + c05a: f2c1 0500 movt r5, #4096 ; 0x1000 + c05e: 2311 movs r3, #17 + c060: 70f3 strb r3, [r6, #3] + c062: 682b ldr r3, [r5, #0] + c064: 2220 movs r2, #32 + c066: 06d9 lsls r1, r3, #27 + c068: 61b2 str r2, [r6, #24] + c06a: d5eb bpl.n c044 + c06c: f242 5050 movw r0, #9552 ; 0x2550 + c070: f24f 349d movw r4, #62365 ; 0xf39d + c074: f2c0 0004 movt r0, #4 + c078: e7d6 b.n c028 + c07a: bf00 nop + c07c: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + c080: f850 6c04 ldr.w r6, [r0, #-4] + c084: 4683 mov fp, r0 + c086: 7900 ldrb r0, [r0, #4] + c088: 6ab3 ldr r3, [r6, #40] ; 0x28 + c08a: 6b35 ldr r5, [r6, #48] ; 0x30 + c08c: b087 sub sp, #28 + c08e: 2801 cmp r0, #1 + c090: f8d6 a004 ldr.w sl, [r6, #4] + c094: 68b4 ldr r4, [r6, #8] + c096: 9301 str r3, [sp, #4] + c098: 9502 str r5, [sp, #8] + c09a: f000 8087 beq.w c1ac + c09e: f89b 3002 ldrb.w r3, [fp, #2] + c0a2: 2b00 cmp r3, #0 + c0a4: d14e bne.n c144 + c0a6: f8db 701c ldr.w r7, [fp, #28] + c0aa: 1e7a subs r2, r7, #1 + c0ac: 3203 adds r2, #3 + c0ae: bf84 itt hi + c0b0: 4699 movhi r9, r3 + c0b2: 464e movhi r6, r9 + c0b4: f240 8183 bls.w c3be + c0b8: f64a 4865 movw r8, #44133 ; 0xac65 + c0bc: 2303 movs r3, #3 + c0be: f88b 3003 strb.w r3, [fp, #3] + c0c2: f2c0 0800 movt r8, #0 + c0c6: f8db 3024 ldr.w r3, [fp, #36] ; 0x24 + c0ca: 2504 movs r5, #4 + c0cc: e006 b.n c0dc + c0ce: 2e00 cmp r6, #0 + c0d0: d13f bne.n c152 + c0d2: 2f00 cmp r7, #0 + c0d4: f000 818a beq.w c3ec + c0d8: f8db 3024 ldr.w r3, [fp, #36] ; 0x24 + c0dc: 881b ldrh r3, [r3, #0] + c0de: 2134 movs r1, #52 ; 0x34 + c0e0: b35b cbz r3, c13a + c0e2: f88b 5003 strb.w r5, [fp, #3] + c0e6: 69a3 ldr r3, [r4, #24] + c0e8: 4650 mov r0, sl + c0ea: 4798 blx r3 + c0ec: 0683 lsls r3, r0, #26 + c0ee: d5ee bpl.n c0ce + c0f0: 69a3 ldr r3, [r4, #24] + c0f2: 4650 mov r0, sl + c0f4: 2170 movs r1, #112 ; 0x70 + c0f6: 4798 blx r3 + c0f8: 0780 lsls r0, r0, #30 + c0fa: d5ed bpl.n c0d8 + c0fc: f04f 0101 mov.w r1, #1 + c100: f88a 100f strb.w r1, [sl, #15] + c104: f8db 3024 ldr.w r3, [fp, #36] ; 0x24 + c108: 6a62 ldr r2, [r4, #36] ; 0x24 + c10a: 68db ldr r3, [r3, #12] + c10c: 4650 mov r0, sl + c10e: f8ca 3014 str.w r3, [sl, #20] + c112: 4790 blx r2 + c114: f04f 0250 mov.w r2, #80 ; 0x50 + c118: 6aa3 ldr r3, [r4, #40] ; 0x28 + c11a: f8aa 201a strh.w r2, [sl, #26] + c11e: 4650 mov r0, sl + c120: 4798 blx r3 + c122: f8db 3024 ldr.w r3, [fp, #36] ; 0x24 + c126: 8819 ldrh r1, [r3, #0] + c128: 68da ldr r2, [r3, #12] + c12a: 3901 subs r1, #1 + c12c: 8019 strh r1, [r3, #0] + c12e: 3201 adds r2, #1 + c130: 60da str r2, [r3, #12] + c132: 881b ldrh r3, [r3, #0] + c134: 2134 movs r1, #52 ; 0x34 + c136: 2b00 cmp r3, #0 + c138: d1d3 bne.n c0e2 + c13a: 2202 movs r2, #2 + c13c: f89b 3002 ldrb.w r3, [fp, #2] + c140: f88b 2003 strb.w r2, [fp, #3] + c144: 2b02 cmp r3, #2 + c146: d079 beq.n c23c + c148: 2300 movs r3, #0 + c14a: 4618 mov r0, r3 + c14c: b007 add sp, #28 + c14e: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + c152: 4648 mov r0, r9 + c154: 4631 mov r1, r6 + c156: 47c0 blx r8 + c158: 2802 cmp r0, #2 + c15a: d1bd bne.n c0d8 + c15c: f240 3514 movw r5, #788 ; 0x314 + c160: f2c1 0500 movt r5, #4096 ; 0x1000 + c164: 2211 movs r2, #17 + c166: f88b 2003 strb.w r2, [fp, #3] + c16a: 682a ldr r2, [r5, #0] + c16c: 2124 movs r1, #36 ; 0x24 + c16e: f8cb 1018 str.w r1, [fp, #24] + c172: 06d1 lsls r1, r2, #27 + c174: 4603 mov r3, r0 + c176: d55c bpl.n c232 + c178: f242 7014 movw r0, #10004 ; 0x2714 + c17c: f24f 349d movw r4, #62365 ; 0xf39d + c180: f2c0 0004 movt r0, #4 + c184: f89b 1000 ldrb.w r1, [fp] + c188: f2c0 0400 movt r4, #0 + c18c: 9300 str r3, [sp, #0] + c18e: 47a0 blx r4 + c190: 682a ldr r2, [r5, #0] + c192: 06d2 lsls r2, r2, #27 + c194: d54d bpl.n c232 + c196: f242 2050 movw r0, #8784 ; 0x2250 + c19a: f89b 1003 ldrb.w r1, [fp, #3] + c19e: f2c0 0004 movt r0, #4 + c1a2: f8db 2018 ldr.w r2, [fp, #24] + c1a6: 47a0 blx r4 + c1a8: 9b00 ldr r3, [sp, #0] + c1aa: e7ce b.n c14a + c1ac: f8db 3014 ldr.w r3, [fp, #20] + c1b0: f413 7800 ands.w r8, r3, #512 ; 0x200 + c1b4: d051 beq.n c25a + c1b6: f8db 701c ldr.w r7, [fp, #28] + c1ba: 1e7b subs r3, r7, #1 + c1bc: 3303 adds r3, #3 + c1be: bf84 itt hi + c1c0: f04f 0800 movhi.w r8, #0 + c1c4: 4645 movhi r5, r8 + c1c6: f240 81a9 bls.w c51c + c1ca: f64a 4965 movw r9, #44133 ; 0xac65 + c1ce: f2c0 0900 movt r9, #0 + c1d2: 69a3 ldr r3, [r4, #24] + c1d4: 4650 mov r0, sl + c1d6: 2170 movs r1, #112 ; 0x70 + c1d8: 4798 blx r3 + c1da: 0683 lsls r3, r0, #26 + c1dc: f140 811b bpl.w c416 + c1e0: 2d00 cmp r5, #0 + c1e2: f040 80aa bne.w c33a + c1e6: 2f00 cmp r7, #0 + c1e8: d1f3 bne.n c1d2 + c1ea: f240 3514 movw r5, #788 ; 0x314 + c1ee: f2c1 0500 movt r5, #4096 ; 0x1000 + c1f2: 2311 movs r3, #17 + c1f4: f88b 3003 strb.w r3, [fp, #3] + c1f8: 682b ldr r3, [r5, #0] + c1fa: 2225 movs r2, #37 ; 0x25 + c1fc: 06d9 lsls r1, r3, #27 + c1fe: f8cb 2018 str.w r2, [fp, #24] + c202: d516 bpl.n c232 + c204: f242 50e0 movw r0, #9696 ; 0x25e0 + c208: f24f 349d movw r4, #62365 ; 0xf39d + c20c: f2c0 0004 movt r0, #4 + c210: f2c0 0400 movt r4, #0 + c214: f89b 1000 ldrb.w r1, [fp] + c218: 47a0 blx r4 + c21a: 682b ldr r3, [r5, #0] + c21c: 06da lsls r2, r3, #27 + c21e: d508 bpl.n c232 + c220: f242 2050 movw r0, #8784 ; 0x2250 + c224: f89b 1003 ldrb.w r1, [fp, #3] + c228: f2c0 0004 movt r0, #4 + c22c: f8db 2018 ldr.w r2, [fp, #24] + c230: 47a0 blx r4 + c232: 2302 movs r3, #2 + c234: 4618 mov r0, r3 + c236: b007 add sp, #28 + c238: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + c23c: 2303 movs r3, #3 + c23e: f88b 3003 strb.w r3, [fp, #3] + c242: 69a3 ldr r3, [r4, #24] + c244: 4650 mov r0, sl + c246: 2130 movs r1, #48 ; 0x30 + c248: 4798 blx r3 + c24a: f040 00e8 orr.w r0, r0, #232 ; 0xe8 + c24e: f8aa 0018 strh.w r0, [sl, #24] + c252: 6963 ldr r3, [r4, #20] + c254: 4650 mov r0, sl + c256: 4798 blx r3 + c258: e776 b.n c148 + c25a: 4645 mov r5, r8 + c25c: f64b 63e5 movw r3, #48869 ; 0xbee5 + c260: 4658 mov r0, fp + c262: f2c0 0300 movt r3, #0 + c266: 2100 movs r1, #0 + c268: 4798 blx r3 + c26a: f89b 3002 ldrb.w r3, [fp, #2] + c26e: 2b00 cmp r3, #0 + c270: f040 811a bne.w c4a8 + c274: f8db 201c ldr.w r2, [fp, #28] + c278: 9203 str r2, [sp, #12] + c27a: 9803 ldr r0, [sp, #12] + c27c: 2203 movs r2, #3 + c27e: 1e43 subs r3, r0, #1 + c280: 3303 adds r3, #3 + c282: f88b 2003 strb.w r2, [fp, #3] + c286: f240 8172 bls.w c56e + c28a: f64a 4265 movw r2, #44133 ; 0xac65 + c28e: f640 0399 movw r3, #2201 ; 0x899 + c292: f2c0 0200 movt r2, #0 + c296: f2c0 0300 movt r3, #0 + c29a: 9204 str r2, [sp, #16] + c29c: 9305 str r3, [sp, #20] + c29e: f04f 0904 mov.w r9, #4 + c2a2: f8db 3024 ldr.w r3, [fp, #36] ; 0x24 + c2a6: 2700 movs r7, #0 + c2a8: e023 b.n c2f2 + c2aa: f04f 0001 mov.w r0, #1 + c2ae: f88a 700e strb.w r7, [sl, #14] + c2b2: f88a 000f strb.w r0, [sl, #15] + c2b6: f8db 3024 ldr.w r3, [fp, #36] ; 0x24 + c2ba: 68db ldr r3, [r3, #12] + c2bc: f88a 7011 strb.w r7, [sl, #17] + c2c0: f8db 2024 ldr.w r2, [fp, #36] ; 0x24 + c2c4: f8ca 3014 str.w r3, [sl, #20] + c2c8: 8813 ldrh r3, [r2, #0] + c2ca: 2b01 cmp r3, #1 + c2cc: d070 beq.n c3b0 + c2ce: 6a63 ldr r3, [r4, #36] ; 0x24 + c2d0: 4650 mov r0, sl + c2d2: 4798 blx r3 + c2d4: f8db 3024 ldr.w r3, [fp, #36] ; 0x24 + c2d8: 68da ldr r2, [r3, #12] + c2da: 8819 ldrh r1, [r3, #0] + c2dc: 3201 adds r2, #1 + c2de: 3901 subs r1, #1 + c2e0: 60da str r2, [r3, #12] + c2e2: 8019 strh r1, [r3, #0] + c2e4: f8db 3014 ldr.w r3, [fp, #20] + c2e8: 05db lsls r3, r3, #23 + c2ea: f100 819b bmi.w c624 + c2ee: f8db 3024 ldr.w r3, [fp, #36] ; 0x24 + c2f2: 881b ldrh r3, [r3, #0] + c2f4: 2b00 cmp r3, #0 + c2f6: f000 8151 beq.w c59c + c2fa: f88b 9003 strb.w r9, [fp, #3] + c2fe: 69a3 ldr r3, [r4, #24] + c300: 4650 mov r0, sl + c302: 2170 movs r1, #112 ; 0x70 + c304: 4798 blx r3 + c306: 0783 lsls r3, r0, #30 + c308: d4cf bmi.n c2aa + c30a: bbad cbnz r5, c378 + c30c: 9b03 ldr r3, [sp, #12] + c30e: 2b00 cmp r3, #0 + c310: d1e8 bne.n c2e4 + c312: f240 3514 movw r5, #788 ; 0x314 + c316: f2c1 0500 movt r5, #4096 ; 0x1000 + c31a: 2311 movs r3, #17 + c31c: f88b 3003 strb.w r3, [fp, #3] + c320: 682b ldr r3, [r5, #0] + c322: 2223 movs r2, #35 ; 0x23 + c324: f8cb 2018 str.w r2, [fp, #24] + c328: 06da lsls r2, r3, #27 + c32a: d582 bpl.n c232 + c32c: f242 6090 movw r0, #9872 ; 0x2690 + c330: f24f 349d movw r4, #62365 ; 0xf39d + c334: f2c0 0004 movt r0, #4 + c338: e76a b.n c210 + c33a: 4640 mov r0, r8 + c33c: 4629 mov r1, r5 + c33e: 47c8 blx r9 + c340: 2802 cmp r0, #2 + c342: f47f af46 bne.w c1d2 + c346: f240 3514 movw r5, #788 ; 0x314 + c34a: f2c1 0500 movt r5, #4096 ; 0x1000 + c34e: 2211 movs r2, #17 + c350: f88b 2003 strb.w r2, [fp, #3] + c354: 682a ldr r2, [r5, #0] + c356: 4603 mov r3, r0 + c358: 06d0 lsls r0, r2, #27 + c35a: bf48 it mi + c35c: f242 50b4 movwmi r0, #9652 ; 0x25b4 + c360: f04f 0125 mov.w r1, #37 ; 0x25 + c364: f8cb 1018 str.w r1, [fp, #24] + c368: bf44 itt mi + c36a: f24f 349d movwmi r4, #62365 ; 0xf39d + c36e: f2c0 0004 movtmi r0, #4 + c372: f53f af07 bmi.w c184 + c376: e75c b.n c232 + c378: 4640 mov r0, r8 + c37a: 4629 mov r1, r5 + c37c: 9a04 ldr r2, [sp, #16] + c37e: 4790 blx r2 + c380: 2802 cmp r0, #2 + c382: d1af bne.n c2e4 + c384: f240 3514 movw r5, #788 ; 0x314 + c388: f2c1 0500 movt r5, #4096 ; 0x1000 + c38c: 2211 movs r2, #17 + c38e: f88b 2003 strb.w r2, [fp, #3] + c392: 682a ldr r2, [r5, #0] + c394: 2123 movs r1, #35 ; 0x23 + c396: f8cb 1018 str.w r1, [fp, #24] + c39a: 06d1 lsls r1, r2, #27 + c39c: 4603 mov r3, r0 + c39e: f57f af48 bpl.w c232 + c3a2: f242 6064 movw r0, #9828 ; 0x2664 + c3a6: f24f 349d movw r4, #62365 ; 0xf39d + c3aa: f2c0 0004 movt r0, #4 + c3ae: e6e9 b.n c184 + c3b0: f8db 2014 ldr.w r2, [fp, #20] + c3b4: 0550 lsls r0, r2, #21 + c3b6: bf58 it pl + c3b8: f88a 3011 strbpl.w r3, [sl, #17] + c3bc: e787 b.n c2ce + c3be: f241 0285 movw r2, #4229 ; 0x1085 + c3c2: f240 3318 movw r3, #792 ; 0x318 + c3c6: f6c0 0242 movt r2, #2114 ; 0x842 + c3ca: f2c1 0300 movt r3, #4096 ; 0x1000 + c3ce: f44f 717a mov.w r1, #1000 ; 0x3e8 + c3d2: fb01 f107 mul.w r1, r1, r7 + c3d6: fba2 0201 umull r0, r2, r2, r1 + c3da: 1a89 subs r1, r1, r2 + c3dc: eb02 0251 add.w r2, r2, r1, lsr #1 + c3e0: 689b ldr r3, [r3, #8] + c3e2: 2001 movs r0, #1 + c3e4: 0916 lsrs r6, r2, #4 + c3e6: 4798 blx r3 + c3e8: 4681 mov r9, r0 + c3ea: e665 b.n c0b8 + c3ec: f240 3514 movw r5, #788 ; 0x314 + c3f0: f2c1 0500 movt r5, #4096 ; 0x1000 + c3f4: 2311 movs r3, #17 + c3f6: f88b 3003 strb.w r3, [fp, #3] + c3fa: 682b ldr r3, [r5, #0] + c3fc: 2224 movs r2, #36 ; 0x24 + c3fe: 06db lsls r3, r3, #27 + c400: f8cb 2018 str.w r2, [fp, #24] + c404: f57f af15 bpl.w c232 + c408: f242 7040 movw r0, #10048 ; 0x2740 + c40c: f24f 349d movw r4, #62365 ; 0xf39d + c410: f2c0 0004 movt r0, #4 + c414: e6fc b.n c210 + c416: f8db 701c ldr.w r7, [fp, #28] + c41a: 1e7b subs r3, r7, #1 + c41c: 3303 adds r3, #3 + c41e: f240 811d bls.w c65c + c422: f64a 4965 movw r9, #44133 ; 0xac65 + c426: f2c0 0900 movt r9, #0 + c42a: 69a3 ldr r3, [r4, #24] + c42c: 4650 mov r0, sl + c42e: 2170 movs r1, #112 ; 0x70 + c430: 4798 blx r3 + c432: 0742 lsls r2, r0, #29 + c434: f100 8088 bmi.w c548 + c438: b9b5 cbnz r5, c468 + c43a: 2f00 cmp r7, #0 + c43c: d1f5 bne.n c42a + c43e: f240 3514 movw r5, #788 ; 0x314 + c442: f2c1 0500 movt r5, #4096 ; 0x1000 + c446: 2311 movs r3, #17 + c448: f88b 3003 strb.w r3, [fp, #3] + c44c: 682b ldr r3, [r5, #0] + c44e: 2225 movs r2, #37 ; 0x25 + c450: 06d9 lsls r1, r3, #27 + c452: f8cb 2018 str.w r2, [fp, #24] + c456: f57f aeec bpl.w c232 + c45a: f242 6038 movw r0, #9784 ; 0x2638 + c45e: f24f 349d movw r4, #62365 ; 0xf39d + c462: f2c0 0004 movt r0, #4 + c466: e6d3 b.n c210 + c468: 4640 mov r0, r8 + c46a: 4629 mov r1, r5 + c46c: 47c8 blx r9 + c46e: 2802 cmp r0, #2 + c470: d1db bne.n c42a + c472: f240 3514 movw r5, #788 ; 0x314 + c476: f2c1 0500 movt r5, #4096 ; 0x1000 + c47a: 2211 movs r2, #17 + c47c: f88b 2003 strb.w r2, [fp, #3] + c480: 682a ldr r2, [r5, #0] + c482: 4603 mov r3, r0 + c484: 2125 movs r1, #37 ; 0x25 + c486: 06d0 lsls r0, r2, #27 + c488: f8cb 1018 str.w r1, [fp, #24] + c48c: f57f aed1 bpl.w c232 + c490: f242 600c movw r0, #9740 ; 0x260c + c494: f24f 349d movw r4, #62365 ; 0xf39d + c498: f2c0 0004 movt r0, #4 + c49c: e672 b.n c184 + c49e: 2202 movs r2, #2 + c4a0: f89b 3002 ldrb.w r3, [fp, #2] + c4a4: f88b 2003 strb.w r2, [fp, #3] + c4a8: 2b02 cmp r3, #2 + c4aa: f000 8105 beq.w c6b8 + c4ae: 2b01 cmp r3, #1 + c4b0: f47f ae4a bne.w c148 + c4b4: 2303 movs r3, #3 + c4b6: f88b 3003 strb.w r3, [fp, #3] + c4ba: 2130 movs r1, #48 ; 0x30 + c4bc: 69a3 ldr r3, [r4, #24] + c4be: 4650 mov r0, sl + c4c0: 4798 blx r3 + c4c2: f040 0048 orr.w r0, r0, #72 ; 0x48 + c4c6: f8aa 0018 strh.w r0, [sl, #24] + c4ca: 6963 ldr r3, [r4, #20] + c4cc: 4650 mov r0, sl + c4ce: 4798 blx r3 + c4d0: 6b73 ldr r3, [r6, #52] ; 0x34 + c4d2: 9802 ldr r0, [sp, #8] + c4d4: 4798 blx r3 + c4d6: f244 0310 movw r3, #16400 ; 0x4010 + c4da: f2c4 0304 movt r3, #16388 ; 0x4004 + c4de: f8db 2024 ldr.w r2, [fp, #36] ; 0x24 + c4e2: 9d02 ldr r5, [sp, #8] + c4e4: 8810 ldrh r0, [r2, #0] + c4e6: 68a9 ldr r1, [r5, #8] + c4e8: 68d2 ldr r2, [r2, #12] + c4ea: 9d01 ldr r5, [sp, #4] + c4ec: 8568 strh r0, [r5, #42] ; 0x2a + c4ee: 602a str r2, [r5, #0] + c4f0: f89b 2000 ldrb.w r2, [fp] + c4f4: 4628 mov r0, r5 + c4f6: 0292 lsls r2, r2, #10 + c4f8: 4413 add r3, r2 + c4fa: 606b str r3, [r5, #4] + c4fc: 4788 blx r1 + c4fe: 9d02 ldr r5, [sp, #8] + c500: 9801 ldr r0, [sp, #4] + c502: 696b ldr r3, [r5, #20] + c504: 4798 blx r3 + c506: 2204 movs r2, #4 + c508: 2302 movs r3, #2 + c50a: f88b 2003 strb.w r2, [fp, #3] + c50e: f88a 300d strb.w r3, [sl, #13] + c512: 6b23 ldr r3, [r4, #48] ; 0x30 + c514: 4650 mov r0, sl + c516: 4798 blx r3 + c518: 2300 movs r3, #0 + c51a: e616 b.n c14a + c51c: f241 0285 movw r2, #4229 ; 0x1085 + c520: f240 3318 movw r3, #792 ; 0x318 + c524: f6c0 0242 movt r2, #2114 ; 0x842 + c528: f2c1 0300 movt r3, #4096 ; 0x1000 + c52c: f44f 717a mov.w r1, #1000 ; 0x3e8 + c530: fb01 f107 mul.w r1, r1, r7 + c534: fba2 5201 umull r5, r2, r2, r1 + c538: 1a89 subs r1, r1, r2 + c53a: eb02 0251 add.w r2, r2, r1, lsr #1 + c53e: 689b ldr r3, [r3, #8] + c540: 0915 lsrs r5, r2, #4 + c542: 4798 blx r3 + c544: 4680 mov r8, r0 + c546: e640 b.n c1ca + c548: 69a3 ldr r3, [r4, #24] + c54a: 4650 mov r0, sl + c54c: 2104 movs r1, #4 + c54e: 4798 blx r3 + c550: f8db 3024 ldr.w r3, [fp, #36] ; 0x24 + c554: f420 707f bic.w r0, r0, #1020 ; 0x3fc + c558: 885b ldrh r3, [r3, #2] + c55a: f020 0203 bic.w r2, r0, #3 + c55e: f3c3 0309 ubfx r3, r3, #0, #10 + c562: 431a orrs r2, r3 + c564: 4650 mov r0, sl + c566: 69e3 ldr r3, [r4, #28] + c568: 2104 movs r1, #4 + c56a: 4798 blx r3 + c56c: e676 b.n c25c + c56e: f241 0285 movw r2, #4229 ; 0x1085 + c572: f240 3318 movw r3, #792 ; 0x318 + c576: f6c0 0242 movt r2, #2114 ; 0x842 + c57a: f2c1 0300 movt r3, #4096 ; 0x1000 + c57e: f44f 717a mov.w r1, #1000 ; 0x3e8 + c582: fb01 f100 mul.w r1, r1, r0 + c586: fba2 5201 umull r5, r2, r2, r1 + c58a: 1a89 subs r1, r1, r2 + c58c: eb02 0251 add.w r2, r2, r1, lsr #1 + c590: 689b ldr r3, [r3, #8] + c592: 2001 movs r0, #1 + c594: 0915 lsrs r5, r2, #4 + c596: 4798 blx r3 + c598: 4680 mov r8, r0 + c59a: e676 b.n c28a + c59c: 69f7 ldr r7, [r6, #28] + c59e: 1e7b subs r3, r7, #1 + c5a0: 3303 adds r3, #3 + c5a2: d972 bls.n c68a + c5a4: f64a 4965 movw r9, #44133 ; 0xac65 + c5a8: f2c0 0900 movt r9, #0 + c5ac: 69a3 ldr r3, [r4, #24] + c5ae: 4650 mov r0, sl + c5b0: 2170 movs r1, #112 ; 0x70 + c5b2: 4798 blx r3 + c5b4: f000 0006 and.w r0, r0, #6 + c5b8: 2806 cmp r0, #6 + c5ba: f43f af70 beq.w c49e + c5be: b9b5 cbnz r5, c5ee + c5c0: 2f00 cmp r7, #0 + c5c2: d1f3 bne.n c5ac + c5c4: f240 3514 movw r5, #788 ; 0x314 + c5c8: f2c1 0500 movt r5, #4096 ; 0x1000 + c5cc: 2311 movs r3, #17 + c5ce: f88b 3003 strb.w r3, [fp, #3] + c5d2: 682b ldr r3, [r5, #0] + c5d4: 2224 movs r2, #36 ; 0x24 + c5d6: f8cb 2018 str.w r2, [fp, #24] + c5da: 06da lsls r2, r3, #27 + c5dc: f57f ae29 bpl.w c232 + c5e0: f242 60e8 movw r0, #9960 ; 0x26e8 + c5e4: f24f 349d movw r4, #62365 ; 0xf39d + c5e8: f2c0 0004 movt r0, #4 + c5ec: e610 b.n c210 + c5ee: 4640 mov r0, r8 + c5f0: 4629 mov r1, r5 + c5f2: 47c8 blx r9 + c5f4: 2802 cmp r0, #2 + c5f6: d1d9 bne.n c5ac + c5f8: f240 3514 movw r5, #788 ; 0x314 + c5fc: f2c1 0500 movt r5, #4096 ; 0x1000 + c600: 2211 movs r2, #17 + c602: f88b 2003 strb.w r2, [fp, #3] + c606: 682a ldr r2, [r5, #0] + c608: 2124 movs r1, #36 ; 0x24 + c60a: f8cb 1018 str.w r1, [fp, #24] + c60e: 06d1 lsls r1, r2, #27 + c610: 4603 mov r3, r0 + c612: f57f ae0e bpl.w c232 + c616: f242 60bc movw r0, #9916 ; 0x26bc + c61a: f24f 349d movw r4, #62365 ; 0xf39d + c61e: f2c0 0004 movt r0, #4 + c622: e5af b.n c184 + c624: f242 7010 movw r0, #10000 ; 0x2710 + c628: f8da 3020 ldr.w r3, [sl, #32] + c62c: 9a05 ldr r2, [sp, #20] + c62e: fbb0 f0f3 udiv r0, r0, r3 + c632: 4790 blx r2 + c634: 69a3 ldr r3, [r4, #24] + c636: 4650 mov r0, sl + c638: 2134 movs r1, #52 ; 0x34 + c63a: 4798 blx r3 + c63c: 0640 lsls r0, r0, #25 + c63e: f57f ae56 bpl.w c2ee + c642: 69a3 ldr r3, [r4, #24] + c644: 2154 movs r1, #84 ; 0x54 + c646: 4650 mov r0, sl + c648: 4798 blx r3 + c64a: f8db 3024 ldr.w r3, [fp, #36] ; 0x24 + c64e: 68da ldr r2, [r3, #12] + c650: 8819 ldrh r1, [r3, #0] + c652: 3a01 subs r2, #1 + c654: 3101 adds r1, #1 + c656: 60da str r2, [r3, #12] + c658: 8019 strh r1, [r3, #0] + c65a: e64a b.n c2f2 + c65c: f241 0285 movw r2, #4229 ; 0x1085 + c660: f240 3318 movw r3, #792 ; 0x318 + c664: f6c0 0242 movt r2, #2114 ; 0x842 + c668: f2c1 0300 movt r3, #4096 ; 0x1000 + c66c: f44f 717a mov.w r1, #1000 ; 0x3e8 + c670: fb01 f107 mul.w r1, r1, r7 + c674: fba2 0201 umull r0, r2, r2, r1 + c678: 1a89 subs r1, r1, r2 + c67a: eb02 0251 add.w r2, r2, r1, lsr #1 + c67e: 689b ldr r3, [r3, #8] + c680: 2001 movs r0, #1 + c682: 0915 lsrs r5, r2, #4 + c684: 4798 blx r3 + c686: 4680 mov r8, r0 + c688: e6cb b.n c422 + c68a: f241 0285 movw r2, #4229 ; 0x1085 + c68e: f240 3318 movw r3, #792 ; 0x318 + c692: f6c0 0242 movt r2, #2114 ; 0x842 + c696: f2c1 0300 movt r3, #4096 ; 0x1000 + c69a: f44f 717a mov.w r1, #1000 ; 0x3e8 + c69e: fb01 f107 mul.w r1, r1, r7 + c6a2: fba2 5201 umull r5, r2, r2, r1 + c6a6: 1a89 subs r1, r1, r2 + c6a8: eb02 0251 add.w r2, r2, r1, lsr #1 + c6ac: 689b ldr r3, [r3, #8] + c6ae: 2001 movs r0, #1 + c6b0: 0915 lsrs r5, r2, #4 + c6b2: 4798 blx r3 + c6b4: 4680 mov r8, r0 + c6b6: e775 b.n c5a4 + c6b8: 2303 movs r3, #3 + c6ba: f88b 3003 strb.w r3, [fp, #3] + c6be: 69a3 ldr r3, [r4, #24] + c6c0: 2130 movs r1, #48 ; 0x30 + c6c2: 4650 mov r0, sl + c6c4: 4798 blx r3 + c6c6: f040 0058 orr.w r0, r0, #88 ; 0x58 + c6ca: f8aa 0018 strh.w r0, [sl, #24] + c6ce: 6963 ldr r3, [r4, #20] + c6d0: 4650 mov r0, sl + c6d2: 4798 blx r3 + c6d4: f89b 3002 ldrb.w r3, [fp, #2] + c6d8: e6e9 b.n c4ae + c6da: bf00 nop + c6dc: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + c6e0: f850 bc04 ldr.w fp, [r0, #-4] + c6e4: 4682 mov sl, r0 + c6e6: 7900 ldrb r0, [r0, #4] + c6e8: f8db 202c ldr.w r2, [fp, #44] ; 0x2c + c6ec: f8db 3030 ldr.w r3, [fp, #48] ; 0x30 + c6f0: b087 sub sp, #28 + c6f2: 2801 cmp r0, #1 + c6f4: f8db 4004 ldr.w r4, [fp, #4] + c6f8: f8db 5008 ldr.w r5, [fp, #8] + c6fc: 9203 str r2, [sp, #12] + c6fe: 9304 str r3, [sp, #16] + c700: d075 beq.n c7ee + c702: f89a 6002 ldrb.w r6, [sl, #2] + c706: bb2e cbnz r6, c754 + c708: f8da 701c ldr.w r7, [sl, #28] + c70c: 1e7b subs r3, r7, #1 + c70e: 3303 adds r3, #3 + c710: bf88 it hi + c712: 9602 strhi r6, [sp, #8] + c714: f240 8140 bls.w c998 + c718: f64a 4865 movw r8, #44133 ; 0xac65 + c71c: f2c0 0800 movt r8, #0 + c720: f8da 3028 ldr.w r3, [sl, #40] ; 0x28 + c724: 881b ldrh r3, [r3, #0] + c726: 2170 movs r1, #112 ; 0x70 + c728: b17b cbz r3, c74a + c72a: 69ab ldr r3, [r5, #24] + c72c: 4620 mov r0, r4 + c72e: 4798 blx r3 + c730: f010 0f18 tst.w r0, #24 + c734: d119 bne.n c76a + c736: bb56 cbnz r6, c78e + c738: 2f00 cmp r7, #0 + c73a: f000 8118 beq.w c96e + c73e: f8da 3028 ldr.w r3, [sl, #40] ; 0x28 + c742: 2170 movs r1, #112 ; 0x70 + c744: 881b ldrh r3, [r3, #0] + c746: 2b00 cmp r3, #0 + c748: d1ef bne.n c72a + c74a: 2302 movs r3, #2 + c74c: f89a 6002 ldrb.w r6, [sl, #2] + c750: f88a 3003 strb.w r3, [sl, #3] + c754: 2e02 cmp r6, #2 + c756: f000 80e3 beq.w c920 + c75a: 2e01 cmp r6, #1 + c75c: f000 80af beq.w c8be + c760: 2300 movs r3, #0 + c762: 4618 mov r0, r3 + c764: b007 add sp, #28 + c766: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + c76a: f8da 2028 ldr.w r2, [sl, #40] ; 0x28 + c76e: 68eb ldr r3, [r5, #12] + c770: 4620 mov r0, r4 + c772: f8d2 900c ldr.w r9, [r2, #12] + c776: 4798 blx r3 + c778: f889 0000 strb.w r0, [r9] + c77c: f8da 3028 ldr.w r3, [sl, #40] ; 0x28 + c780: 68da ldr r2, [r3, #12] + c782: 8819 ldrh r1, [r3, #0] + c784: 3201 adds r2, #1 + c786: 3901 subs r1, #1 + c788: 60da str r2, [r3, #12] + c78a: 8019 strh r1, [r3, #0] + c78c: e7ca b.n c724 + c78e: 9802 ldr r0, [sp, #8] + c790: 4631 mov r1, r6 + c792: 47c0 blx r8 + c794: 2802 cmp r0, #2 + c796: d1d2 bne.n c73e + c798: f240 3514 movw r5, #788 ; 0x314 + c79c: f2c1 0500 movt r5, #4096 ; 0x1000 + c7a0: 2211 movs r2, #17 + c7a2: f88a 2003 strb.w r2, [sl, #3] + c7a6: 682a ldr r2, [r5, #0] + c7a8: 2122 movs r1, #34 ; 0x22 + c7aa: f8ca 1018 str.w r1, [sl, #24] + c7ae: 06d1 lsls r1, r2, #27 + c7b0: 4603 mov r3, r0 + c7b2: d562 bpl.n c87a + c7b4: f642 00cc movw r0, #10444 ; 0x28cc + c7b8: f24f 349d movw r4, #62365 ; 0xf39d + c7bc: f2c0 0004 movt r0, #4 + c7c0: f89a 1000 ldrb.w r1, [sl] + c7c4: f2c0 0400 movt r4, #0 + c7c8: 9301 str r3, [sp, #4] + c7ca: 47a0 blx r4 + c7cc: 682a ldr r2, [r5, #0] + c7ce: 06d2 lsls r2, r2, #27 + c7d0: d553 bpl.n c87a + c7d2: f242 2050 movw r0, #8784 ; 0x2250 + c7d6: f89a 1003 ldrb.w r1, [sl, #3] + c7da: f8da 2018 ldr.w r2, [sl, #24] + c7de: f2c0 0004 movt r0, #4 + c7e2: 47a0 blx r4 + c7e4: 9b01 ldr r3, [sp, #4] + c7e6: 4618 mov r0, r3 + c7e8: b007 add sp, #28 + c7ea: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + c7ee: f8da 3014 ldr.w r3, [sl, #20] + c7f2: f413 7300 ands.w r3, r3, #512 ; 0x200 + c7f6: f000 812e beq.w ca56 + c7fa: f8da 601c ldr.w r6, [sl, #28] + c7fe: 1e73 subs r3, r6, #1 + c800: 3303 adds r3, #3 + c802: bf82 ittt hi + c804: 2300 movhi r3, #0 + c806: 9303 strhi r3, [sp, #12] + c808: 9302 strhi r3, [sp, #8] + c80a: f240 8099 bls.w c940 + c80e: f64a 4765 movw r7, #44133 ; 0xac65 + c812: f2c0 0700 movt r7, #0 + c816: f8dd 8008 ldr.w r8, [sp, #8] + c81a: 69ab ldr r3, [r5, #24] + c81c: 4620 mov r0, r4 + c81e: 2170 movs r1, #112 ; 0x70 + c820: 4798 blx r3 + c822: 0680 lsls r0, r0, #26 + c824: f140 80cf bpl.w c9c6 + c828: f1b8 0f00 cmp.w r8, #0 + c82c: d12a bne.n c884 + c82e: 2e00 cmp r6, #0 + c830: d1f3 bne.n c81a + c832: f240 3514 movw r5, #788 ; 0x314 + c836: f2c1 0500 movt r5, #4096 ; 0x1000 + c83a: 2311 movs r3, #17 + c83c: f88a 3003 strb.w r3, [sl, #3] + c840: 682b ldr r3, [r5, #0] + c842: 2226 movs r2, #38 ; 0x26 + c844: 06de lsls r6, r3, #27 + c846: f8ca 2018 str.w r2, [sl, #24] + c84a: d516 bpl.n c87a + c84c: f242 7098 movw r0, #10136 ; 0x2798 + c850: f24f 349d movw r4, #62365 ; 0xf39d + c854: f2c0 0004 movt r0, #4 + c858: f2c0 0400 movt r4, #0 + c85c: f89a 1000 ldrb.w r1, [sl] + c860: 47a0 blx r4 + c862: 682b ldr r3, [r5, #0] + c864: 06dd lsls r5, r3, #27 + c866: d508 bpl.n c87a + c868: f242 2050 movw r0, #8784 ; 0x2250 + c86c: f89a 1003 ldrb.w r1, [sl, #3] + c870: f2c0 0004 movt r0, #4 + c874: f8da 2018 ldr.w r2, [sl, #24] + c878: 47a0 blx r4 + c87a: 2302 movs r3, #2 + c87c: 4618 mov r0, r3 + c87e: b007 add sp, #28 + c880: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + c884: 9803 ldr r0, [sp, #12] + c886: 4641 mov r1, r8 + c888: 47b8 blx r7 + c88a: 2802 cmp r0, #2 + c88c: d1c5 bne.n c81a + c88e: f240 3514 movw r5, #788 ; 0x314 + c892: f2c1 0500 movt r5, #4096 ; 0x1000 + c896: 2211 movs r2, #17 + c898: f88a 2003 strb.w r2, [sl, #3] + c89c: 682a ldr r2, [r5, #0] + c89e: 4603 mov r3, r0 + c8a0: 06d7 lsls r7, r2, #27 + c8a2: bf48 it mi + c8a4: f242 706c movwmi r0, #10092 ; 0x276c + c8a8: f04f 0126 mov.w r1, #38 ; 0x26 + c8ac: f8ca 1018 str.w r1, [sl, #24] + c8b0: bf44 itt mi + c8b2: f24f 349d movwmi r4, #62365 ; 0xf39d + c8b6: f2c0 0004 movtmi r0, #4 + c8ba: d481 bmi.n c7c0 + c8bc: e7dd b.n c87a + c8be: 2305 movs r3, #5 + c8c0: f88a 3003 strb.w r3, [sl, #3] + c8c4: 2130 movs r1, #48 ; 0x30 + c8c6: 69ab ldr r3, [r5, #24] + c8c8: 4620 mov r0, r4 + c8ca: 4798 blx r3 + c8cc: f040 0003 orr.w r0, r0, #3 + c8d0: 8320 strh r0, [r4, #24] + c8d2: 696b ldr r3, [r5, #20] + c8d4: 4620 mov r0, r4 + c8d6: 4798 blx r3 + c8d8: f8db 3034 ldr.w r3, [fp, #52] ; 0x34 + c8dc: 9804 ldr r0, [sp, #16] + c8de: 4798 blx r3 + c8e0: f244 0310 movw r3, #16400 ; 0x4010 + c8e4: f2c4 0304 movt r3, #16388 ; 0x4004 + c8e8: f8da 2028 ldr.w r2, [sl, #40] ; 0x28 + c8ec: 9f04 ldr r7, [sp, #16] + c8ee: 8810 ldrh r0, [r2, #0] + c8f0: 68b9 ldr r1, [r7, #8] + c8f2: 9f03 ldr r7, [sp, #12] + c8f4: 68d2 ldr r2, [r2, #12] + c8f6: 8578 strh r0, [r7, #42] ; 0x2a + c8f8: f89a 7000 ldrb.w r7, [sl] + c8fc: 9803 ldr r0, [sp, #12] + c8fe: 02bf lsls r7, r7, #10 + c900: 443b add r3, r7 + c902: 6042 str r2, [r0, #4] + c904: 6003 str r3, [r0, #0] + c906: 4788 blx r1 + c908: 9f04 ldr r7, [sp, #16] + c90a: 9803 ldr r0, [sp, #12] + c90c: 697b ldr r3, [r7, #20] + c90e: 4798 blx r3 + c910: 2306 movs r3, #6 + c912: f88a 3003 strb.w r3, [sl, #3] + c916: 7366 strb r6, [r4, #13] + c918: 6b2b ldr r3, [r5, #48] ; 0x30 + c91a: 4620 mov r0, r4 + c91c: 4798 blx r3 + c91e: e71f b.n c760 + c920: 2305 movs r3, #5 + c922: f88a 3003 strb.w r3, [sl, #3] + c926: 69ab ldr r3, [r5, #24] + c928: 2130 movs r1, #48 ; 0x30 + c92a: 4620 mov r0, r4 + c92c: 4798 blx r3 + c92e: f040 0007 orr.w r0, r0, #7 + c932: 8320 strh r0, [r4, #24] + c934: 696b ldr r3, [r5, #20] + c936: 4620 mov r0, r4 + c938: 4798 blx r3 + c93a: f89a 6002 ldrb.w r6, [sl, #2] + c93e: e70c b.n c75a + c940: f241 0285 movw r2, #4229 ; 0x1085 + c944: f240 3318 movw r3, #792 ; 0x318 + c948: f6c0 0242 movt r2, #2114 ; 0x842 + c94c: f2c1 0300 movt r3, #4096 ; 0x1000 + c950: f44f 717a mov.w r1, #1000 ; 0x3e8 + c954: fb01 f106 mul.w r1, r1, r6 + c958: fba2 7201 umull r7, r2, r2, r1 + c95c: 1a89 subs r1, r1, r2 + c95e: eb02 0251 add.w r2, r2, r1, lsr #1 + c962: 0912 lsrs r2, r2, #4 + c964: 689b ldr r3, [r3, #8] + c966: 9202 str r2, [sp, #8] + c968: 4798 blx r3 + c96a: 9003 str r0, [sp, #12] + c96c: e74f b.n c80e + c96e: f240 3514 movw r5, #788 ; 0x314 + c972: f2c1 0500 movt r5, #4096 ; 0x1000 + c976: 2311 movs r3, #17 + c978: f88a 3003 strb.w r3, [sl, #3] + c97c: 682b ldr r3, [r5, #0] + c97e: 2222 movs r2, #34 ; 0x22 + c980: 06db lsls r3, r3, #27 + c982: f8ca 2018 str.w r2, [sl, #24] + c986: f57f af78 bpl.w c87a + c98a: f642 00f8 movw r0, #10488 ; 0x28f8 + c98e: f24f 349d movw r4, #62365 ; 0xf39d + c992: f2c0 0004 movt r0, #4 + c996: e75f b.n c858 + c998: f241 0285 movw r2, #4229 ; 0x1085 + c99c: f240 3318 movw r3, #792 ; 0x318 + c9a0: f6c0 0242 movt r2, #2114 ; 0x842 + c9a4: f2c1 0300 movt r3, #4096 ; 0x1000 + c9a8: f44f 717a mov.w r1, #1000 ; 0x3e8 + c9ac: fb01 f107 mul.w r1, r1, r7 + c9b0: fba2 0201 umull r0, r2, r2, r1 + c9b4: 1a89 subs r1, r1, r2 + c9b6: eb02 0251 add.w r2, r2, r1, lsr #1 + c9ba: 689b ldr r3, [r3, #8] + c9bc: 2001 movs r0, #1 + c9be: 0916 lsrs r6, r2, #4 + c9c0: 4798 blx r3 + c9c2: 9002 str r0, [sp, #8] + c9c4: e6a8 b.n c718 + c9c6: f8da 601c ldr.w r6, [sl, #28] + c9ca: 1e73 subs r3, r6, #1 + c9cc: 3303 adds r3, #3 + c9ce: f240 81f9 bls.w cdc4 + c9d2: f64a 4765 movw r7, #44133 ; 0xac65 + c9d6: f2c0 0700 movt r7, #0 + c9da: f8dd 8008 ldr.w r8, [sp, #8] + c9de: 69ab ldr r3, [r5, #24] + c9e0: 4620 mov r0, r4 + c9e2: 2170 movs r1, #112 ; 0x70 + c9e4: 4798 blx r3 + c9e6: 0743 lsls r3, r0, #29 + c9e8: f100 8167 bmi.w ccba + c9ec: f1b8 0f00 cmp.w r8, #0 + c9f0: d116 bne.n ca20 + c9f2: 2e00 cmp r6, #0 + c9f4: d1f3 bne.n c9de + c9f6: f240 3514 movw r5, #788 ; 0x314 + c9fa: f2c1 0500 movt r5, #4096 ; 0x1000 + c9fe: 2311 movs r3, #17 + ca00: f88a 3003 strb.w r3, [sl, #3] + ca04: 682b ldr r3, [r5, #0] + ca06: 2226 movs r2, #38 ; 0x26 + ca08: f8ca 2018 str.w r2, [sl, #24] + ca0c: 06da lsls r2, r3, #27 + ca0e: f57f af34 bpl.w c87a + ca12: f242 70f0 movw r0, #10224 ; 0x27f0 + ca16: f24f 349d movw r4, #62365 ; 0xf39d + ca1a: f2c0 0004 movt r0, #4 + ca1e: e71b b.n c858 + ca20: 9803 ldr r0, [sp, #12] + ca22: 4641 mov r1, r8 + ca24: 47b8 blx r7 + ca26: 2802 cmp r0, #2 + ca28: d1d9 bne.n c9de + ca2a: f240 3514 movw r5, #788 ; 0x314 + ca2e: f2c1 0500 movt r5, #4096 ; 0x1000 + ca32: 2211 movs r2, #17 + ca34: f88a 2003 strb.w r2, [sl, #3] + ca38: 682a ldr r2, [r5, #0] + ca3a: 2126 movs r1, #38 ; 0x26 + ca3c: f8ca 1018 str.w r1, [sl, #24] + ca40: 06d1 lsls r1, r2, #27 + ca42: 4603 mov r3, r0 + ca44: f57f af19 bpl.w c87a + ca48: f242 70c4 movw r0, #10180 ; 0x27c4 + ca4c: f24f 349d movw r4, #62365 ; 0xf39d + ca50: f2c0 0004 movt r0, #4 + ca54: e6b4 b.n c7c0 + ca56: 9303 str r3, [sp, #12] + ca58: 9302 str r3, [sp, #8] + ca5a: f64b 63e5 movw r3, #48869 ; 0xbee5 + ca5e: 4650 mov r0, sl + ca60: f2c0 0300 movt r3, #0 + ca64: 2101 movs r1, #1 + ca66: 4798 blx r3 + ca68: f89a 3002 ldrb.w r3, [sl, #2] + ca6c: 2b00 cmp r3, #0 + ca6e: f040 80af bne.w cbd0 + ca72: 2205 movs r2, #5 + ca74: f88a 2003 strb.w r2, [sl, #3] + ca78: f8da 201c ldr.w r2, [sl, #28] + ca7c: f8da 3028 ldr.w r3, [sl, #40] ; 0x28 + ca80: 9204 str r2, [sp, #16] + ca82: 9804 ldr r0, [sp, #16] + ca84: 881f ldrh r7, [r3, #0] + ca86: 1e43 subs r3, r0, #1 + ca88: 1c7a adds r2, r7, #1 + ca8a: 3303 adds r3, #3 + ca8c: f8cb 2018 str.w r2, [fp, #24] + ca90: bf88 it hi + ca92: 463b movhi r3, r7 + ca94: f240 8124 bls.w cce0 + ca98: f64a 4265 movw r2, #44133 ; 0xac65 + ca9c: f640 0999 movw r9, #2201 ; 0x899 + caa0: f2c0 0200 movt r2, #0 + caa4: f2c0 0900 movt r9, #0 + caa8: 9205 str r2, [sp, #20] + caaa: f04f 0806 mov.w r8, #6 + caae: 2b00 cmp r3, #0 + cab0: f000 8089 beq.w cbc6 + cab4: f242 7610 movw r6, #10000 ; 0x2710 + cab8: e026 b.n cb08 + caba: 6a6b ldr r3, [r5, #36] ; 0x24 + cabc: 4620 mov r0, r4 + cabe: 4798 blx r3 + cac0: f8db 3018 ldr.w r3, [fp, #24] + cac4: b123 cbz r3, cad0 + cac6: f8db 3018 ldr.w r3, [fp, #24] + caca: 3b01 subs r3, #1 + cacc: f8cb 3018 str.w r3, [fp, #24] + cad0: f8da 3028 ldr.w r3, [sl, #40] ; 0x28 + cad4: 881b ldrh r3, [r3, #0] + cad6: 42bb cmp r3, r7 + cad8: d148 bne.n cb6c + cada: f8da 3014 ldr.w r3, [sl, #20] + cade: 05da lsls r2, r3, #23 + cae0: d544 bpl.n cb6c + cae2: 6a20 ldr r0, [r4, #32] + cae4: fbb6 f0f0 udiv r0, r6, r0 + cae8: 47c8 blx r9 + caea: 69ab ldr r3, [r5, #24] + caec: 4620 mov r0, r4 + caee: 2134 movs r1, #52 ; 0x34 + caf0: 4798 blx r3 + caf2: 0643 lsls r3, r0, #25 + caf4: d53a bpl.n cb6c + caf6: 69ab ldr r3, [r5, #24] + caf8: 4620 mov r0, r4 + cafa: 2154 movs r1, #84 ; 0x54 + cafc: 4798 blx r3 + cafe: f8db 3018 ldr.w r3, [fp, #24] + cb02: 3301 adds r3, #1 + cb04: f8cb 3018 str.w r3, [fp, #24] + cb08: f88a 8003 strb.w r8, [sl, #3] + cb0c: 69ab ldr r3, [r5, #24] + cb0e: 4620 mov r0, r4 + cb10: 2170 movs r1, #112 ; 0x70 + cb12: 4798 blx r3 + cb14: 0780 lsls r0, r0, #30 + cb16: d5db bpl.n cad0 + cb18: f8db 3018 ldr.w r3, [fp, #24] + cb1c: 2b00 cmp r3, #0 + cb1e: d0d7 beq.n cad0 + cb20: f04f 0301 mov.w r3, #1 + cb24: f04f 0000 mov.w r0, #0 + cb28: 73a3 strb r3, [r4, #14] + cb2a: 73e3 strb r3, [r4, #15] + cb2c: f8da 3028 ldr.w r3, [sl, #40] ; 0x28 + cb30: 68da ldr r2, [r3, #12] + cb32: 7460 strb r0, [r4, #17] + cb34: f8db 3018 ldr.w r3, [fp, #24] + cb38: 6162 str r2, [r4, #20] + cb3a: 2b01 cmp r3, #1 + cb3c: d1bd bne.n caba + cb3e: f8da 2014 ldr.w r2, [sl, #20] + cb42: 0551 lsls r1, r2, #21 + cb44: bf58 it pl + cb46: 7463 strbpl r3, [r4, #17] + cb48: e7b7 b.n caba + cb4a: f8da 2028 ldr.w r2, [sl, #40] ; 0x28 + cb4e: 68eb ldr r3, [r5, #12] + cb50: 4620 mov r0, r4 + cb52: 68d6 ldr r6, [r2, #12] + cb54: 4798 blx r3 + cb56: 7030 strb r0, [r6, #0] + cb58: f8da 3028 ldr.w r3, [sl, #40] ; 0x28 + cb5c: 881a ldrh r2, [r3, #0] + cb5e: 68d9 ldr r1, [r3, #12] + cb60: 3a01 subs r2, #1 + cb62: 3101 adds r1, #1 + cb64: b292 uxth r2, r2 + cb66: 60d9 str r1, [r3, #12] + cb68: 801a strh r2, [r3, #0] + cb6a: b132 cbz r2, cb7a + cb6c: 69ab ldr r3, [r5, #24] + cb6e: 4620 mov r0, r4 + cb70: 2170 movs r1, #112 ; 0x70 + cb72: 4798 blx r3 + cb74: f010 0f18 tst.w r0, #24 + cb78: d1e7 bne.n cb4a + cb7a: 9b02 ldr r3, [sp, #8] + cb7c: b93b cbnz r3, cb8e + cb7e: 9b04 ldr r3, [sp, #16] + cb80: 2b00 cmp r3, #0 + cb82: f000 8137 beq.w cdf4 + cb86: f8da 3028 ldr.w r3, [sl, #40] ; 0x28 + cb8a: 881b ldrh r3, [r3, #0] + cb8c: e78f b.n caae + cb8e: 9803 ldr r0, [sp, #12] + cb90: 9902 ldr r1, [sp, #8] + cb92: 9a05 ldr r2, [sp, #20] + cb94: 4790 blx r2 + cb96: 2802 cmp r0, #2 + cb98: d1f5 bne.n cb86 + cb9a: f240 3514 movw r5, #788 ; 0x314 + cb9e: f2c1 0500 movt r5, #4096 ; 0x1000 + cba2: 2211 movs r2, #17 + cba4: f88a 2003 strb.w r2, [sl, #3] + cba8: 682a ldr r2, [r5, #0] + cbaa: 2122 movs r1, #34 ; 0x22 + cbac: 06d4 lsls r4, r2, #27 + cbae: 4603 mov r3, r0 + cbb0: f8ca 1018 str.w r1, [sl, #24] + cbb4: f57f ae61 bpl.w c87a + cbb8: f642 001c movw r0, #10268 ; 0x281c + cbbc: f24f 349d movw r4, #62365 ; 0xf39d + cbc0: f2c0 0004 movt r0, #4 + cbc4: e5fc b.n c7c0 + cbc6: 2202 movs r2, #2 + cbc8: f89a 3002 ldrb.w r3, [sl, #2] + cbcc: f88a 2003 strb.w r2, [sl, #3] + cbd0: 2b02 cmp r3, #2 + cbd2: f47f adc5 bne.w c760 + cbd6: f8db 801c ldr.w r8, [fp, #28] + cbda: f108 33ff add.w r3, r8, #4294967295 + cbde: 3303 adds r3, #3 + cbe0: f240 811d bls.w ce1e + cbe4: f640 0399 movw r3, #2201 ; 0x899 + cbe8: f64a 4265 movw r2, #44133 ; 0xac65 + cbec: 9304 str r3, [sp, #16] + cbee: 2305 movs r3, #5 + cbf0: f88a 3003 strb.w r3, [sl, #3] + cbf4: 69ab ldr r3, [r5, #24] + cbf6: 2130 movs r1, #48 ; 0x30 + cbf8: 4620 mov r0, r4 + cbfa: 9205 str r2, [sp, #20] + cbfc: 4798 blx r3 + cbfe: 9f05 ldr r7, [sp, #20] + cc00: 9a04 ldr r2, [sp, #16] + cc02: f2c0 0700 movt r7, #0 + cc06: f2c0 0200 movt r2, #0 + cc0a: f040 0047 orr.w r0, r0, #71 ; 0x47 + cc0e: 8320 strh r0, [r4, #24] + cc10: 696b ldr r3, [r5, #20] + cc12: 4620 mov r0, r4 + cc14: 9705 str r7, [sp, #20] + cc16: 9204 str r2, [sp, #16] + cc18: 4798 blx r3 + cc1a: f8da 3028 ldr.w r3, [sl, #40] ; 0x28 + cc1e: 2601 movs r6, #1 + cc20: f8b3 9000 ldrh.w r9, [r3] + cc24: 2700 movs r7, #0 + cc26: f8cb 9018 str.w r9, [fp, #24] + cc2a: 2170 movs r1, #112 ; 0x70 + cc2c: 69ab ldr r3, [r5, #24] + cc2e: 4620 mov r0, r4 + cc30: 4798 blx r3 + cc32: 0781 lsls r1, r0, #30 + cc34: d56f bpl.n cd16 + cc36: 73a6 strb r6, [r4, #14] + cc38: 73e6 strb r6, [r4, #15] + cc3a: f8da 3028 ldr.w r3, [sl, #40] ; 0x28 + cc3e: 68da ldr r2, [r3, #12] + cc40: 7467 strb r7, [r4, #17] + cc42: f8db 3018 ldr.w r3, [fp, #24] + cc46: 6162 str r2, [r4, #20] + cc48: 2b01 cmp r3, #1 + cc4a: f000 80a8 beq.w cd9e + cc4e: 6a6b ldr r3, [r5, #36] ; 0x24 + cc50: 4620 mov r0, r4 + cc52: 4798 blx r3 + cc54: f8db 2018 ldr.w r2, [fp, #24] + cc58: f8da 3014 ldr.w r3, [sl, #20] + cc5c: 3a01 subs r2, #1 + cc5e: f8cb 2018 str.w r2, [fp, #24] + cc62: f413 7f80 tst.w r3, #256 ; 0x100 + cc66: f8db 3018 ldr.w r3, [fp, #24] + cc6a: d06e beq.n cd4a + cc6c: f1b9 0f01 cmp.w r9, #1 + cc70: f240 809b bls.w cdaa + cc74: 2b00 cmp r3, #0 + cc76: f43f ad73 beq.w c760 + cc7a: f8da 3028 ldr.w r3, [sl, #40] ; 0x28 + cc7e: f8db 2018 ldr.w r2, [fp, #24] + cc82: 881b ldrh r3, [r3, #0] + cc84: 3b02 subs r3, #2 + cc86: 429a cmp r2, r3 + cc88: f67f ad6a bls.w c760 + cc8c: f242 7310 movw r3, #10000 ; 0x2710 + cc90: 6a20 ldr r0, [r4, #32] + cc92: 9a04 ldr r2, [sp, #16] + cc94: fbb3 f0f0 udiv r0, r3, r0 + cc98: 4790 blx r2 + cc9a: 69ab ldr r3, [r5, #24] + cc9c: 4620 mov r0, r4 + cc9e: 2134 movs r1, #52 ; 0x34 + cca0: 4798 blx r3 + cca2: 0643 lsls r3, r0, #25 + cca4: d5c1 bpl.n cc2a + cca6: 69ab ldr r3, [r5, #24] + cca8: 4620 mov r0, r4 + ccaa: 2154 movs r1, #84 ; 0x54 + ccac: 4798 blx r3 + ccae: f8db 3018 ldr.w r3, [fp, #24] + ccb2: 3301 adds r3, #1 + ccb4: f8cb 3018 str.w r3, [fp, #24] + ccb8: e7b7 b.n cc2a + ccba: 69ab ldr r3, [r5, #24] + ccbc: 4620 mov r0, r4 + ccbe: 2104 movs r1, #4 + ccc0: 4798 blx r3 + ccc2: f8da 3028 ldr.w r3, [sl, #40] ; 0x28 + ccc6: f420 707f bic.w r0, r0, #1020 ; 0x3fc + ccca: 885b ldrh r3, [r3, #2] + cccc: f020 0203 bic.w r2, r0, #3 + ccd0: f3c3 0309 ubfx r3, r3, #0, #10 + ccd4: 431a orrs r2, r3 + ccd6: 4620 mov r0, r4 + ccd8: 69eb ldr r3, [r5, #28] + ccda: 2104 movs r1, #4 + ccdc: 4798 blx r3 + ccde: e6bc b.n ca5a + cce0: f241 0285 movw r2, #4229 ; 0x1085 + cce4: f240 3318 movw r3, #792 ; 0x318 + cce8: f6c0 0242 movt r2, #2114 ; 0x842 + ccec: f2c1 0300 movt r3, #4096 ; 0x1000 + ccf0: f44f 717a mov.w r1, #1000 ; 0x3e8 + ccf4: fb01 f100 mul.w r1, r1, r0 + ccf8: fba2 0201 umull r0, r2, r2, r1 + ccfc: 1a89 subs r1, r1, r2 + ccfe: eb02 0251 add.w r2, r2, r1, lsr #1 + cd02: 689b ldr r3, [r3, #8] + cd04: 0912 lsrs r2, r2, #4 + cd06: 2001 movs r0, #1 + cd08: 9202 str r2, [sp, #8] + cd0a: 4798 blx r3 + cd0c: f8da 3028 ldr.w r3, [sl, #40] ; 0x28 + cd10: 9003 str r0, [sp, #12] + cd12: 881b ldrh r3, [r3, #0] + cd14: e6c0 b.n ca98 + cd16: 9b02 ldr r3, [sp, #8] + cd18: bb23 cbnz r3, cd64 + cd1a: f1b8 0f00 cmp.w r8, #0 + cd1e: d184 bne.n cc2a + cd20: f240 3514 movw r5, #788 ; 0x314 + cd24: f2c1 0500 movt r5, #4096 ; 0x1000 + cd28: 2311 movs r3, #17 + cd2a: f88a 3003 strb.w r3, [sl, #3] + cd2e: 682b ldr r3, [r5, #0] + cd30: 2221 movs r2, #33 ; 0x21 + cd32: 06d8 lsls r0, r3, #27 + cd34: f8ca 2018 str.w r2, [sl, #24] + cd38: f57f ad9f bpl.w c87a + cd3c: f642 00a0 movw r0, #10400 ; 0x28a0 + cd40: f24f 349d movw r4, #62365 ; 0xf39d + cd44: f2c0 0004 movt r0, #4 + cd48: e586 b.n c858 + cd4a: 2b00 cmp r3, #0 + cd4c: f43f ad08 beq.w c760 + cd50: f8da 3028 ldr.w r3, [sl, #40] ; 0x28 + cd54: f8db 2018 ldr.w r2, [fp, #24] + cd58: 881b ldrh r3, [r3, #0] + cd5a: 3b02 subs r3, #2 + cd5c: 429a cmp r2, r3 + cd5e: f63f af64 bhi.w cc2a + cd62: e4fd b.n c760 + cd64: 9803 ldr r0, [sp, #12] + cd66: 4619 mov r1, r3 + cd68: 9a05 ldr r2, [sp, #20] + cd6a: 4790 blx r2 + cd6c: 2802 cmp r0, #2 + cd6e: f47f af5c bne.w cc2a + cd72: f240 3514 movw r5, #788 ; 0x314 + cd76: f2c1 0500 movt r5, #4096 ; 0x1000 + cd7a: 2211 movs r2, #17 + cd7c: f88a 2003 strb.w r2, [sl, #3] + cd80: 682a ldr r2, [r5, #0] + cd82: 2121 movs r1, #33 ; 0x21 + cd84: 06d4 lsls r4, r2, #27 + cd86: 4603 mov r3, r0 + cd88: f8ca 1018 str.w r1, [sl, #24] + cd8c: f57f ad75 bpl.w c87a + cd90: f642 0074 movw r0, #10356 ; 0x2874 + cd94: f24f 349d movw r4, #62365 ; 0xf39d + cd98: f2c0 0004 movt r0, #4 + cd9c: e510 b.n c7c0 + cd9e: f8da 2014 ldr.w r2, [sl, #20] + cda2: 0552 lsls r2, r2, #21 + cda4: bf58 it pl + cda6: 7463 strbpl r3, [r4, #17] + cda8: e751 b.n cc4e + cdaa: 2b00 cmp r3, #0 + cdac: f43f acd8 beq.w c760 + cdb0: f8da 3028 ldr.w r3, [sl, #40] ; 0x28 + cdb4: f8db 2018 ldr.w r2, [fp, #24] + cdb8: 881b ldrh r3, [r3, #0] + cdba: 3b01 subs r3, #1 + cdbc: 429a cmp r2, r3 + cdbe: f63f af65 bhi.w cc8c + cdc2: e4cd b.n c760 + cdc4: f241 0285 movw r2, #4229 ; 0x1085 + cdc8: f240 3318 movw r3, #792 ; 0x318 + cdcc: f6c0 0242 movt r2, #2114 ; 0x842 + cdd0: f2c1 0300 movt r3, #4096 ; 0x1000 + cdd4: f44f 717a mov.w r1, #1000 ; 0x3e8 + cdd8: fb01 f106 mul.w r1, r1, r6 + cddc: fba2 7201 umull r7, r2, r2, r1 + cde0: 1a89 subs r1, r1, r2 + cde2: eb02 0251 add.w r2, r2, r1, lsr #1 + cde6: 0912 lsrs r2, r2, #4 + cde8: 689b ldr r3, [r3, #8] + cdea: 2001 movs r0, #1 + cdec: 9202 str r2, [sp, #8] + cdee: 4798 blx r3 + cdf0: 9003 str r0, [sp, #12] + cdf2: e5ee b.n c9d2 + cdf4: f240 3514 movw r5, #788 ; 0x314 + cdf8: f2c1 0500 movt r5, #4096 ; 0x1000 + cdfc: 2311 movs r3, #17 + cdfe: f88a 3003 strb.w r3, [sl, #3] + ce02: 682b ldr r3, [r5, #0] + ce04: 2222 movs r2, #34 ; 0x22 + ce06: 06d8 lsls r0, r3, #27 + ce08: f8ca 2018 str.w r2, [sl, #24] + ce0c: f57f ad35 bpl.w c87a + ce10: f642 0048 movw r0, #10312 ; 0x2848 + ce14: f24f 349d movw r4, #62365 ; 0xf39d + ce18: f2c0 0004 movt r0, #4 + ce1c: e51c b.n c858 + ce1e: f241 0285 movw r2, #4229 ; 0x1085 + ce22: f240 3318 movw r3, #792 ; 0x318 + ce26: f6c0 0242 movt r2, #2114 ; 0x842 + ce2a: f2c1 0300 movt r3, #4096 ; 0x1000 + ce2e: f44f 717a mov.w r1, #1000 ; 0x3e8 + ce32: fb01 f108 mul.w r1, r1, r8 + ce36: fba2 7201 umull r7, r2, r2, r1 + ce3a: 1a89 subs r1, r1, r2 + ce3c: eb02 0251 add.w r2, r2, r1, lsr #1 + ce40: 0912 lsrs r2, r2, #4 + ce42: 689b ldr r3, [r3, #8] + ce44: 2001 movs r0, #1 + ce46: 9202 str r2, [sp, #8] + ce48: 4798 blx r3 + ce4a: 9003 str r0, [sp, #12] + ce4c: e6ca b.n cbe4 + ce4e: bf00 nop + +0000ce50 : + ce50: 4603 mov r3, r0 + ce52: 7800 ldrb r0, [r0, #0] + ce54: 2803 cmp r0, #3 + ce56: d85e bhi.n cf16 + ce58: b4f0 push {r4, r5, r6, r7} + ce5a: 6a1d ldr r5, [r3, #32] + ce5c: 2200 movs r2, #0 + ce5e: 2101 movs r1, #1 + ce60: 2464 movs r4, #100 ; 0x64 + ce62: 2709 movs r7, #9 + ce64: 2603 movs r6, #3 + ce66: 7119 strb r1, [r3, #4] + ce68: 7199 strb r1, [r3, #6] + ce6a: 71d9 strb r1, [r3, #7] + ce6c: 715a strb r2, [r3, #5] + ce6e: 615a str r2, [r3, #20] + ce70: 705a strb r2, [r3, #1] + ce72: 709a strb r2, [r3, #2] + ce74: 70da strb r2, [r3, #3] + ce76: 729a strb r2, [r3, #10] + ce78: 619a str r2, [r3, #24] + ce7a: 61da str r2, [r3, #28] + ce7c: 625a str r2, [r3, #36] ; 0x24 + ce7e: 629a str r2, [r3, #40] ; 0x28 + ce80: 731f strb r7, [r3, #12] + ce82: 735e strb r6, [r3, #13] + ce84: 811c strh r4, [r3, #8] + ce86: 7028 strb r0, [r5, #0] + ce88: 6a18 ldr r0, [r3, #32] + ce8a: 2712 movs r7, #18 + ce8c: 7042 strb r2, [r0, #1] + ce8e: 6a18 ldr r0, [r3, #32] + ce90: 2611 movs r6, #17 + ce92: 7081 strb r1, [r0, #2] + ce94: 6a18 ldr r0, [r3, #32] + ce96: 250a movs r5, #10 + ce98: 70c2 strb r2, [r0, #3] + ce9a: 6a18 ldr r0, [r3, #32] + ce9c: 7101 strb r1, [r0, #4] + ce9e: 6a19 ldr r1, [r3, #32] + cea0: 714f strb r7, [r1, #5] + cea2: 6a18 ldr r0, [r3, #32] + cea4: 620c str r4, [r1, #32] + cea6: 838e strh r6, [r1, #28] + cea8: 83cd strh r5, [r1, #30] + ceaa: 7182 strb r2, [r0, #6] + ceac: 6a19 ldr r1, [r3, #32] + ceae: 71ca strb r2, [r1, #7] + ceb0: 6a19 ldr r1, [r3, #32] + ceb2: 720c strb r4, [r1, #8] + ceb4: 6a19 ldr r1, [r3, #32] + ceb6: 724a strb r2, [r1, #9] + ceb8: 6a19 ldr r1, [r3, #32] + ceba: 728a strb r2, [r1, #10] + cebc: 6a19 ldr r1, [r3, #32] + cebe: 72ca strb r2, [r1, #11] + cec0: 6a19 ldr r1, [r3, #32] + cec2: 730a strb r2, [r1, #12] + cec4: 6a19 ldr r1, [r3, #32] + cec6: 734a strb r2, [r1, #13] + cec8: 6a19 ldr r1, [r3, #32] + ceca: 830a strh r2, [r1, #24] + cecc: 7b1a ldrb r2, [r3, #12] + cece: f881 2024 strb.w r2, [r1, #36] ; 0x24 + ced2: 6a1a ldr r2, [r3, #32] + ced4: 7b59 ldrb r1, [r3, #13] + ced6: f882 1025 strb.w r1, [r2, #37] ; 0x25 + ceda: 781a ldrb r2, [r3, #0] + cedc: b9ea cbnz r2, cf1a + cede: 72da strb r2, [r3, #11] + cee0: 6b19 ldr r1, [r3, #48] ; 0x30 + cee2: 2202 movs r2, #2 + cee4: 700a strb r2, [r1, #0] + cee6: 6b19 ldr r1, [r3, #48] ; 0x30 + cee8: 2401 movs r4, #1 + ceea: 704c strb r4, [r1, #1] + ceec: 6b18 ldr r0, [r3, #48] ; 0x30 + ceee: 2100 movs r1, #0 + cef0: 7084 strb r4, [r0, #2] + cef2: 6b18 ldr r0, [r3, #48] ; 0x30 + cef4: 2603 movs r6, #3 + cef6: 70c2 strb r2, [r0, #3] + cef8: 6b1d ldr r5, [r3, #48] ; 0x30 + cefa: 4608 mov r0, r1 + cefc: 712a strb r2, [r5, #4] + cefe: 6b1d ldr r5, [r3, #48] ; 0x30 + cf00: 7229 strb r1, [r5, #8] + cf02: 6b1d ldr r5, [r3, #48] ; 0x30 + cf04: 726a strb r2, [r5, #9] + cf06: 6b1a ldr r2, [r3, #48] ; 0x30 + cf08: 7294 strb r4, [r2, #10] + cf0a: 6b1a ldr r2, [r3, #48] ; 0x30 + cf0c: 72d1 strb r1, [r2, #11] + cf0e: 6b1b ldr r3, [r3, #48] ; 0x30 + cf10: 731e strb r6, [r3, #12] + cf12: bcf0 pop {r4, r5, r6, r7} + cf14: 4770 bx lr + cf16: 20ee movs r0, #238 ; 0xee + cf18: 4770 bx lr + cf1a: 2a01 cmp r2, #1 + cf1c: d1e0 bne.n cee0 + cf1e: e7de b.n cede + +0000cf20 : + cf20: b470 push {r4, r5, r6} + cf22: f64e 615d movw r1, #61021 ; 0xee5d + cf26: f64b 4695 movw r6, #48277 ; 0xbc95 + cf2a: f64b 654d movw r5, #48717 ; 0xbe4d + cf2e: f64e 0405 movw r4, #59397 ; 0xe805 + cf32: f64a 2261 movw r2, #43617 ; 0xaa61 + cf36: f64a 2365 movw r3, #43621 ; 0xaa65 + cf3a: f2c0 0600 movt r6, #0 + cf3e: f2c0 0500 movt r5, #0 + cf42: f2c1 0403 movt r4, #4099 ; 0x1003 + cf46: f2c1 0103 movt r1, #4099 ; 0x1003 + cf4a: f2c0 0200 movt r2, #0 + cf4e: f2c0 0300 movt r3, #0 + cf52: 6006 str r6, [r0, #0] + cf54: 6045 str r5, [r0, #4] + cf56: 6084 str r4, [r0, #8] + cf58: 60c1 str r1, [r0, #12] + cf5a: 6102 str r2, [r0, #16] + cf5c: 6143 str r3, [r0, #20] + cf5e: bc70 pop {r4, r5, r6} + cf60: 4770 bx lr + cf62: bf00 nop + +0000cf64 : + cf64: b140 cbz r0, cf78 + cf66: 2801 cmp r0, #1 + cf68: d105 bne.n cf76 + cf6a: f101 4180 add.w r1, r1, #1073741824 ; 0x40000000 + cf6e: f501 21c6 add.w r1, r1, #405504 ; 0x63000 + cf72: 600a str r2, [r1, #0] + cf74: 4770 bx lr + cf76: 4770 bx lr + cf78: f101 4180 add.w r1, r1, #1073741824 ; 0x40000000 + cf7c: f501 21c4 add.w r1, r1, #401408 ; 0x62000 + cf80: 600a str r2, [r1, #0] + cf82: 4770 bx lr + +0000cf84 : + cf84: b148 cbz r0, cf9a + cf86: 2801 cmp r0, #1 + cf88: d105 bne.n cf96 + cf8a: f101 4180 add.w r1, r1, #1073741824 ; 0x40000000 + cf8e: f501 21c6 add.w r1, r1, #405504 ; 0x63000 + cf92: 6808 ldr r0, [r1, #0] + cf94: 4770 bx lr + cf96: 2000 movs r0, #0 + cf98: 4770 bx lr + cf9a: f101 4180 add.w r1, r1, #1073741824 ; 0x40000000 + cf9e: f501 21c4 add.w r1, r1, #401408 ; 0x62000 + cfa2: 6808 ldr r0, [r1, #0] + cfa4: 4770 bx lr + cfa6: bf00 nop + +0000cfa8 : + cfa8: b510 push {r4, lr} + cfaa: 7804 ldrb r4, [r0, #0] + cfac: 2100 movs r1, #0 + cfae: 4620 mov r0, r4 + cfb0: f7ff ffe8 bl cf84 + cfb4: f020 4000 bic.w r0, r0, #2147483648 ; 0x80000000 + cfb8: f020 0201 bic.w r2, r0, #1 + cfbc: 2100 movs r1, #0 + cfbe: 4620 mov r0, r4 + cfc0: f7ff ffd0 bl cf64 + cfc4: 2000 movs r0, #0 + cfc6: bd10 pop {r4, pc} + +0000cfc8 : + cfc8: b5f8 push {r3, r4, r5, r6, r7, lr} + cfca: f24f 4365 movw r3, #62565 ; 0xf465 + cfce: 4604 mov r4, r0 + cfd0: 88c2 ldrh r2, [r0, #6] + cfd2: 8c05 ldrh r5, [r0, #32] + cfd4: 3201 adds r2, #1 + cfd6: 6880 ldr r0, [r0, #8] + cfd8: 0092 lsls r2, r2, #2 + cfda: fb02 0005 mla r0, r2, r5, r0 + cfde: f2c0 0300 movt r3, #0 + cfe2: 7966 ldrb r6, [r4, #5] + cfe4: 7827 ldrb r7, [r4, #0] + cfe6: 4798 blx r3 + cfe8: f105 0108 add.w r1, r5, #8 + cfec: 0089 lsls r1, r1, #2 + cfee: 4638 mov r0, r7 + cff0: f001 01fc and.w r1, r1, #252 ; 0xfc + cff4: f04f 4200 mov.w r2, #2147483648 ; 0x80000000 + cff8: 3501 adds r5, #1 + cffa: f7ff ffb3 bl cf64 + cffe: b2ad uxth r5, r5 + d000: 1c73 adds r3, r6, #1 + d002: fb95 f2f3 sdiv r2, r5, r3 + d006: fb03 5512 mls r5, r3, r2, r5 + d00a: 2000 movs r0, #0 + d00c: 8425 strh r5, [r4, #32] + d00e: bdf8 pop {r3, r4, r5, r6, r7, pc} + +0000d010 : + d010: b5f8 push {r3, r4, r5, r6, r7, lr} + d012: f24f 4365 movw r3, #62565 ; 0xf465 + d016: 4604 mov r4, r0 + d018: 88c6 ldrh r6, [r0, #6] + d01a: 8c45 ldrh r5, [r0, #34] ; 0x22 + d01c: 68c7 ldr r7, [r0, #12] + d01e: 3601 adds r6, #1 + d020: 00b6 lsls r6, r6, #2 + d022: 4632 mov r2, r6 + d024: f2c0 0300 movt r3, #0 + d028: 4608 mov r0, r1 + d02a: fb06 7105 mla r1, r6, r5, r7 + d02e: 7966 ldrb r6, [r4, #5] + d030: 7827 ldrb r7, [r4, #0] + d032: 4798 blx r3 + d034: f105 010c add.w r1, r5, #12 + d038: 0089 lsls r1, r1, #2 + d03a: 4638 mov r0, r7 + d03c: f001 01fc and.w r1, r1, #252 ; 0xfc + d040: f04f 4200 mov.w r2, #2147483648 ; 0x80000000 + d044: 3501 adds r5, #1 + d046: f7ff ff8d bl cf64 + d04a: b2ad uxth r5, r5 + d04c: 1c73 adds r3, r6, #1 + d04e: fb95 f2f3 sdiv r2, r5, r3 + d052: fb03 5512 mls r5, r3, r2, r5 + d056: 2000 movs r0, #0 + d058: 8465 strh r5, [r4, #34] ; 0x22 + d05a: bdf8 pop {r3, r4, r5, r6, r7, pc} + +0000d05c : + d05c: b570 push {r4, r5, r6, lr} + d05e: 7845 ldrb r5, [r0, #1] + d060: 7804 ldrb r4, [r0, #0] + d062: 2d01 cmp r5, #1 + d064: 6902 ldr r2, [r0, #16] + d066: 6986 ldr r6, [r0, #24] + d068: f04f 0110 mov.w r1, #16 + d06c: 4620 mov r0, r4 + d06e: d016 beq.n d09e + d070: 2200 movs r2, #0 + d072: f7ff ff77 bl cf64 + d076: 4620 mov r0, r4 + d078: 2118 movs r1, #24 + d07a: 2200 movs r2, #0 + d07c: f7ff ff72 bl cf64 + d080: 4620 mov r0, r4 + d082: 2100 movs r1, #0 + d084: f7ff ff7e bl cf84 + d088: f005 0501 and.w r5, r5, #1 + d08c: f020 0201 bic.w r2, r0, #1 + d090: 432a orrs r2, r5 + d092: 4620 mov r0, r4 + d094: 2100 movs r1, #0 + d096: f7ff ff65 bl cf64 + d09a: 2000 movs r0, #0 + d09c: bd70 pop {r4, r5, r6, pc} + d09e: f7ff ff61 bl cf64 + d0a2: 4620 mov r0, r4 + d0a4: 4632 mov r2, r6 + d0a6: 2118 movs r1, #24 + d0a8: f7ff ff5c bl cf64 + d0ac: e7e8 b.n d080 + d0ae: bf00 nop + +0000d0b0 : + d0b0: b538 push {r3, r4, r5, lr} + d0b2: 4603 mov r3, r0 + d0b4: 7804 ldrb r4, [r0, #0] + d0b6: 6985 ldr r5, [r0, #24] + d0b8: 691a ldr r2, [r3, #16] + d0ba: 4620 mov r0, r4 + d0bc: 2110 movs r1, #16 + d0be: f7ff ff51 bl cf64 + d0c2: 4620 mov r0, r4 + d0c4: 462a mov r2, r5 + d0c6: 2118 movs r1, #24 + d0c8: f7ff ff4c bl cf64 + d0cc: 2000 movs r0, #0 + d0ce: bd38 pop {r3, r4, r5, pc} + +0000d0d0 : + d0d0: b508 push {r3, lr} + d0d2: 7800 ldrb r0, [r0, #0] + d0d4: f7ff ff56 bl cf84 + d0d8: bd08 pop {r3, pc} + d0da: bf00 nop + +0000d0dc : + d0dc: b538 push {r3, r4, r5, lr} + d0de: 4603 mov r3, r0 + d0e0: 7804 ldrb r4, [r0, #0] + d0e2: 69c5 ldr r5, [r0, #28] + d0e4: 695a ldr r2, [r3, #20] + d0e6: 4620 mov r0, r4 + d0e8: 2114 movs r1, #20 + d0ea: f7ff ff3b bl cf64 + d0ee: 4620 mov r0, r4 + d0f0: 462a mov r2, r5 + d0f2: 211c movs r1, #28 + d0f4: f7ff ff36 bl cf64 + d0f8: 2000 movs r0, #0 + d0fa: bd38 pop {r3, r4, r5, pc} + +0000d0fc : + d0fc: b510 push {r4, lr} + d0fe: 7804 ldrb r4, [r0, #0] + d100: 2114 movs r1, #20 + d102: 4620 mov r0, r4 + d104: f240 12ff movw r2, #511 ; 0x1ff + d108: f7ff ff2c bl cf64 + d10c: 4620 mov r0, r4 + d10e: 211c movs r1, #28 + d110: f240 12ff movw r2, #511 ; 0x1ff + d114: f7ff ff26 bl cf64 + d118: 2000 movs r0, #0 + d11a: bd10 pop {r4, pc} + +0000d11c : + d11c: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + d120: 4604 mov r4, r0 + d122: 78a3 ldrb r3, [r4, #2] + d124: b085 sub sp, #20 + d126: 7805 ldrb r5, [r0, #0] + d128: f894 c003 ldrb.w ip, [r4, #3] + d12c: 9303 str r3, [sp, #12] + d12e: 7923 ldrb r3, [r4, #4] + d130: 2100 movs r1, #0 + d132: 4628 mov r0, r5 + d134: f04f 4200 mov.w r2, #2147483648 ; 0x80000000 + d138: 8d27 ldrh r7, [r4, #40] ; 0x28 + d13a: f894 602a ldrb.w r6, [r4, #42] ; 0x2a + d13e: f894 8005 ldrb.w r8, [r4, #5] + d142: f8b4 9006 ldrh.w r9, [r4, #6] + d146: f8d4 b008 ldr.w fp, [r4, #8] + d14a: f8d4 a00c ldr.w sl, [r4, #12] + d14e: 9301 str r3, [sp, #4] + d150: f8cd c008 str.w ip, [sp, #8] + d154: f7ff ff06 bl cf64 + d158: 2100 movs r1, #0 + d15a: 460a mov r2, r1 + d15c: 4628 mov r0, r5 + d15e: f7ff ff01 bl cf64 + d162: f04f 4200 mov.w r2, #2147483648 ; 0x80000000 + d166: 4628 mov r0, r5 + d168: 2100 movs r1, #0 + d16a: f7ff fefb bl cf64 + d16e: 2100 movs r1, #0 + d170: 4628 mov r0, r5 + d172: f7ff ff07 bl cf84 + d176: f8dd c008 ldr.w ip, [sp, #8] + d17a: f017 0f10 tst.w r7, #16 + d17e: 9b01 ldr r3, [sp, #4] + d180: bf14 ite ne + d182: f040 4280 orrne.w r2, r0, #1073741824 ; 0x40000000 + d186: f440 5280 orreq.w r2, r0, #4096 ; 0x1000 + d18a: f00c 0c01 and.w ip, ip, #1 + d18e: 9803 ldr r0, [sp, #12] + d190: ea4f 1c8c mov.w ip, ip, lsl #6 + d194: f003 0303 and.w r3, r3, #3 + d198: ea4c 03c3 orr.w r3, ip, r3, lsl #3 + d19c: f000 0101 and.w r1, r0, #1 + d1a0: ea43 7341 orr.w r3, r3, r1, lsl #29 + d1a4: f006 0103 and.w r1, r6, #3 + d1a8: bf18 it ne + d1aa: f442 5280 orrne.w r2, r2, #4096 ; 0x1000 + d1ae: ea43 0341 orr.w r3, r3, r1, lsl #1 + d1b2: 431a orrs r2, r3 + d1b4: 4628 mov r0, r5 + d1b6: 2100 movs r1, #0 + d1b8: f007 0707 and.w r7, r7, #7 + d1bc: f7ff fed2 bl cf64 + d1c0: 03bf lsls r7, r7, #14 + d1c2: f008 0203 and.w r2, r8, #3 + d1c6: f3c9 030b ubfx r3, r9, #0, #12 + d1ca: ea47 3202 orr.w r2, r7, r2, lsl #12 + d1ce: 431a orrs r2, r3 + d1d0: 4628 mov r0, r5 + d1d2: 210c movs r1, #12 + d1d4: f7ff fec6 bl cf64 + d1d8: 4628 mov r0, r5 + d1da: 2104 movs r1, #4 + d1dc: 465a mov r2, fp + d1de: f7ff fec1 bl cf64 + d1e2: 4628 mov r0, r5 + d1e4: 2108 movs r1, #8 + d1e6: 4652 mov r2, sl + d1e8: f7ff febc bl cf64 + d1ec: 1e73 subs r3, r6, #1 + d1ee: 2b01 cmp r3, #1 + d1f0: bf82 ittt hi + d1f2: 4628 movhi r0, r5 + d1f4: 2120 movhi r1, #32 + d1f6: 2200 movhi r2, #0 + d1f8: d962 bls.n d2c0 + d1fa: f7ff feb3 bl cf64 + d1fe: 4628 mov r0, r5 + d200: 2124 movs r1, #36 ; 0x24 + d202: 2200 movs r2, #0 + d204: f7ff feae bl cf64 + d208: 4628 mov r0, r5 + d20a: 2128 movs r1, #40 ; 0x28 + d20c: 2200 movs r2, #0 + d20e: f7ff fea9 bl cf64 + d212: 212c movs r1, #44 ; 0x2c + d214: 4628 mov r0, r5 + d216: 2200 movs r2, #0 + d218: f7ff fea4 bl cf64 + d21c: f016 01fd ands.w r1, r6, #253 ; 0xfd + d220: d029 beq.n d276 + d222: 4628 mov r0, r5 + d224: 2130 movs r1, #48 ; 0x30 + d226: 2200 movs r2, #0 + d228: f7ff fe9c bl cf64 + d22c: 4628 mov r0, r5 + d22e: 2134 movs r1, #52 ; 0x34 + d230: 2200 movs r2, #0 + d232: f7ff fe97 bl cf64 + d236: 4628 mov r0, r5 + d238: 2138 movs r1, #56 ; 0x38 + d23a: 2200 movs r2, #0 + d23c: f7ff fe92 bl cf64 + d240: 4628 mov r0, r5 + d242: 213c movs r1, #60 ; 0x3c + d244: 2200 movs r2, #0 + d246: f7ff fe8d bl cf64 + d24a: 2500 movs r5, #0 + d24c: 2301 movs r3, #1 + d24e: 8423 strh r3, [r4, #32] + d250: 8465 strh r5, [r4, #34] ; 0x22 + d252: 84a5 strh r5, [r4, #36] ; 0x24 + d254: 84e5 strh r5, [r4, #38] ; 0x26 + d256: 4620 mov r0, r4 + d258: f7ff ff50 bl d0fc + d25c: 6927 ldr r7, [r4, #16] + d25e: 69a6 ldr r6, [r4, #24] + d260: 6125 str r5, [r4, #16] + d262: 61a5 str r5, [r4, #24] + d264: 4620 mov r0, r4 + d266: f7ff ff23 bl d0b0 + d26a: 4628 mov r0, r5 + d26c: 6127 str r7, [r4, #16] + d26e: 61a6 str r6, [r4, #24] + d270: b005 add sp, #20 + d272: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + d276: f24f 5311 movw r3, #62737 ; 0xf511 + d27a: f109 0901 add.w r9, r9, #1 + d27e: ea4f 0289 mov.w r2, r9, lsl #2 + d282: f2c0 0300 movt r3, #0 + d286: fb08 2202 mla r2, r8, r2, r2 + d28a: 4650 mov r0, sl + d28c: 4798 blx r3 + d28e: 4628 mov r0, r5 + d290: 2130 movs r1, #48 ; 0x30 + d292: f04f 4200 mov.w r2, #2147483648 ; 0x80000000 + d296: f7ff fe65 bl cf64 + d29a: 4628 mov r0, r5 + d29c: 2134 movs r1, #52 ; 0x34 + d29e: f04f 4200 mov.w r2, #2147483648 ; 0x80000000 + d2a2: f7ff fe5f bl cf64 + d2a6: 4628 mov r0, r5 + d2a8: 2138 movs r1, #56 ; 0x38 + d2aa: f04f 4200 mov.w r2, #2147483648 ; 0x80000000 + d2ae: f7ff fe59 bl cf64 + d2b2: 4628 mov r0, r5 + d2b4: 213c movs r1, #60 ; 0x3c + d2b6: f04f 4200 mov.w r2, #2147483648 ; 0x80000000 + d2ba: f7ff fe53 bl cf64 + d2be: e7c4 b.n d24a + d2c0: f24f 5311 movw r3, #62737 ; 0xf511 + d2c4: f109 0201 add.w r2, r9, #1 + d2c8: 0092 lsls r2, r2, #2 + d2ca: fb08 2202 mla r2, r8, r2, r2 + d2ce: 2100 movs r1, #0 + d2d0: 4658 mov r0, fp + d2d2: f2c0 0300 movt r3, #0 + d2d6: 4798 blx r3 + d2d8: 4628 mov r0, r5 + d2da: 2120 movs r1, #32 + d2dc: f04f 4200 mov.w r2, #2147483648 ; 0x80000000 + d2e0: e78b b.n d1fa + d2e2: bf00 nop + +0000d2e4 : + d2e4: 4601 mov r1, r0 + d2e6: b1b8 cbz r0, d318 + d2e8: f241 23b4 movw r3, #4788 ; 0x12b4 + d2ec: b510 push {r4, lr} + d2ee: f2c0 0303 movt r3, #3 + d2f2: e002 b.n d2fa + d2f4: 7892 ldrb r2, [r2, #2] + d2f6: 428a cmp r2, r1 + d2f8: d00c beq.n d314 + d2fa: 78dc ldrb r4, [r3, #3] + d2fc: 461a mov r2, r3 + d2fe: 2cff cmp r4, #255 ; 0xff + d300: f103 0302 add.w r3, r3, #2 + d304: d1f6 bne.n d2f4 + d306: f240 330c movw r3, #780 ; 0x30c + d30a: f2c1 0300 movt r3, #4096 ; 0x1000 + d30e: 681b ldr r3, [r3, #0] + d310: 075b lsls r3, r3, #29 + d312: d402 bmi.n d31a + d314: 4620 mov r0, r4 + d316: bd10 pop {r4, pc} + d318: 4770 bx lr + d31a: f642 1028 movw r0, #10536 ; 0x2928 + d31e: f24f 339d movw r3, #62365 ; 0xf39d + d322: f2c0 0004 movt r0, #4 + d326: f2c0 0300 movt r3, #0 + d32a: 4798 blx r3 + d32c: 4620 mov r0, r4 + d32e: bd10 pop {r4, pc} + +0000d330 : + d330: b5f8 push {r3, r4, r5, r6, r7, lr} + d332: ea51 1640 orrs.w r6, r1, r0, lsl #5 + d336: bf1c itt ne + d338: f241 27b4 movwne r7, #4788 ; 0x12b4 + d33c: f2c0 0703 movtne r7, #3 + d340: 4686 mov lr, r0 + d342: 460a mov r2, r1 + d344: bf1c itt ne + d346: 463b movne r3, r7 + d348: 2500 movne r5, #0 + d34a: d102 bne.n d352 + d34c: e01c b.n d388 + d34e: 42b4 cmp r4, r6 + d350: d01f beq.n d392 + d352: 78dc ldrb r4, [r3, #3] + d354: 3501 adds r5, #1 + d356: 2cff cmp r4, #255 ; 0xff + d358: f103 0302 add.w r3, r3, #2 + d35c: d1f7 bne.n d34e + d35e: f240 330c movw r3, #780 ; 0x30c + d362: f2c1 0300 movt r3, #4096 ; 0x1000 + d366: 681b ldr r3, [r3, #0] + d368: 075b lsls r3, r3, #29 + d36a: bf58 it pl + d36c: 20ff movpl r0, #255 ; 0xff + d36e: d514 bpl.n d39a + d370: f642 106c movw r0, #10604 ; 0x296c + d374: f24f 339d movw r3, #62365 ; 0xf39d + d378: 4671 mov r1, lr + d37a: f2c0 0300 movt r3, #0 + d37e: f2c0 0004 movt r0, #4 + d382: 4798 blx r3 + d384: 20ff movs r0, #255 ; 0xff + d386: bdf8 pop {r3, r4, r5, r6, r7, pc} + d388: f241 27b4 movw r7, #4788 ; 0x12b4 + d38c: 4635 mov r5, r6 + d38e: f2c0 0703 movt r7, #3 + d392: f817 0015 ldrb.w r0, [r7, r5, lsl #1] + d396: 28ff cmp r0, #255 ; 0xff + d398: d0e1 beq.n d35e + d39a: bdf8 pop {r3, r4, r5, r6, r7, pc} + +0000d39c : + d39c: b538 push {r3, r4, r5, lr} + d39e: 4605 mov r5, r0 + d3a0: b1f0 cbz r0, d3e0 + d3a2: f64f 70ff movw r0, #65535 ; 0xffff + d3a6: 4b1d ldr r3, [pc, #116] ; (d41c ) + d3a8: 2400 movs r4, #0 + d3aa: e001 b.n d3b0 + d3ac: 42aa cmp r2, r5 + d3ae: d018 beq.n d3e2 + d3b0: 88da ldrh r2, [r3, #6] + d3b2: 3401 adds r4, #1 + d3b4: 4282 cmp r2, r0 + d3b6: f103 0306 add.w r3, r3, #6 + d3ba: d1f7 bne.n d3ac + d3bc: f240 330c movw r3, #780 ; 0x30c + d3c0: f2c1 0300 movt r3, #4096 ; 0x1000 + d3c4: 681b ldr r3, [r3, #0] + d3c6: 075b lsls r3, r3, #29 + d3c8: d526 bpl.n d418 + d3ca: f642 10b8 movw r0, #10680 ; 0x29b8 + d3ce: f24f 339d movw r3, #62365 ; 0xf39d + d3d2: 4629 mov r1, r5 + d3d4: f2c0 0300 movt r3, #0 + d3d8: f2c0 0004 movt r0, #4 + d3dc: 4798 blx r3 + d3de: bd38 pop {r3, r4, r5, pc} + d3e0: 4604 mov r4, r0 + d3e2: f241 23b4 movw r3, #4788 ; 0x12b4 + d3e6: f2c0 0303 movt r3, #3 + d3ea: f64f 70ff movw r0, #65535 ; 0xffff + d3ee: eb04 0444 add.w r4, r4, r4, lsl #1 + d3f2: eb03 0444 add.w r4, r3, r4, lsl #1 + d3f6: f8b4 30ba ldrh.w r3, [r4, #186] ; 0xba + d3fa: f8b4 20bc ldrh.w r2, [r4, #188] ; 0xbc + d3fe: 4283 cmp r3, r0 + d400: d0dc beq.n d3bc + d402: f103 4380 add.w r3, r3, #1073741824 ; 0x40000000 + d406: 681c ldr r4, [r3, #0] + d408: 2003 movs r0, #3 + d40a: 4090 lsls r0, r2 + d40c: ea24 0000 bic.w r0, r4, r0 + d410: fa01 f202 lsl.w r2, r1, r2 + d414: 4302 orrs r2, r0 + d416: 601a str r2, [r3, #0] + d418: bd38 pop {r3, r4, r5, pc} + d41a: bf00 nop + d41c: 0003136c .word 0x0003136c + +0000d420 : + d420: f240 3054 movw r0, #852 ; 0x354 + d424: f240 3210 movw r2, #784 ; 0x310 + d428: f44f 7107 mov.w r1, #540 ; 0x21c + d42c: f2c4 0100 movt r1, #16384 ; 0x4000 + d430: f44f 730c mov.w r3, #560 ; 0x230 + d434: f2c1 0000 movt r0, #4096 ; 0x1000 + d438: f2c4 0300 movt r3, #16384 ; 0x4000 + d43c: f2c1 0200 movt r2, #4096 ; 0x1000 + d440: b510 push {r4, lr} + d442: 680c ldr r4, [r1, #0] + d444: 6800 ldr r0, [r0, #0] + d446: f444 7480 orr.w r4, r4, #256 ; 0x100 + d44a: 600c str r4, [r1, #0] + d44c: 681c ldr r4, [r3, #0] + d44e: 2101 movs r1, #1 + d450: f044 7480 orr.w r4, r4, #16777216 ; 0x1000000 + d454: 601c str r4, [r3, #0] + d456: 681c ldr r4, [r3, #0] + d458: f044 7400 orr.w r4, r4, #33554432 ; 0x2000000 + d45c: 601c str r4, [r3, #0] + d45e: 6813 ldr r3, [r2, #0] + d460: f880 1128 strb.w r1, [r0, #296] ; 0x128 + d464: 075b lsls r3, r3, #29 + d466: d400 bmi.n d46a + d468: bd10 pop {r4, pc} + d46a: f642 10f0 movw r0, #10736 ; 0x29f0 + d46e: f24f 339d movw r3, #62365 ; 0xf39d + d472: f2c0 0004 movt r0, #4 + d476: f2c0 0300 movt r3, #0 + d47a: 4798 blx r3 + d47c: e7f4 b.n d468 + d47e: bf00 nop + +0000d480 : + d480: f240 3054 movw r0, #852 ; 0x354 + d484: f240 3210 movw r2, #784 ; 0x310 + d488: b510 push {r4, lr} + d48a: f44f 7107 mov.w r1, #540 ; 0x21c + d48e: f44f 5480 mov.w r4, #4096 ; 0x1000 + d492: f2c4 0100 movt r1, #16384 ; 0x4000 + d496: f2c4 0400 movt r4, #16384 ; 0x4000 + d49a: f44f 730c mov.w r3, #560 ; 0x230 + d49e: f2c1 0000 movt r0, #4096 ; 0x1000 + d4a2: f2c4 0300 movt r3, #16384 ; 0x4000 + d4a6: f2c1 0200 movt r2, #4096 ; 0x1000 + d4aa: 6824 ldr r4, [r4, #0] + d4ac: 680c ldr r4, [r1, #0] + d4ae: 6800 ldr r0, [r0, #0] + d4b0: f424 7480 bic.w r4, r4, #256 ; 0x100 + d4b4: 600c str r4, [r1, #0] + d4b6: 681c ldr r4, [r3, #0] + d4b8: 2100 movs r1, #0 + d4ba: f024 7480 bic.w r4, r4, #16777216 ; 0x1000000 + d4be: 601c str r4, [r3, #0] + d4c0: 681c ldr r4, [r3, #0] + d4c2: f024 7400 bic.w r4, r4, #33554432 ; 0x2000000 + d4c6: 601c str r4, [r3, #0] + d4c8: 6813 ldr r3, [r2, #0] + d4ca: f880 1128 strb.w r1, [r0, #296] ; 0x128 + d4ce: 075b lsls r3, r3, #29 + d4d0: d400 bmi.n d4d4 + d4d2: bd10 pop {r4, pc} + d4d4: f642 2010 movw r0, #10768 ; 0x2a10 + d4d8: f24f 339d movw r3, #62365 ; 0xf39d + d4dc: f2c0 0004 movt r0, #4 + d4e0: f2c0 0300 movt r3, #0 + d4e4: 4798 blx r3 + d4e6: e7f4 b.n d4d2 + +0000d4e8 : + d4e8: f241 0334 movw r3, #4148 ; 0x1034 + d4ec: f2c4 0300 movt r3, #16384 ; 0x4000 + d4f0: b410 push {r4} + d4f2: f000 001f and.w r0, r0, #31 + d4f6: 2401 movs r4, #1 + d4f8: 681a ldr r2, [r3, #0] + d4fa: 4021 ands r1, r4 + d4fc: 4084 lsls r4, r0 + d4fe: ea22 0204 bic.w r2, r2, r4 + d502: fa01 f000 lsl.w r0, r1, r0 + d506: 4302 orrs r2, r0 + d508: 601a str r2, [r3, #0] + d50a: f85d 4b04 ldr.w r4, [sp], #4 + d50e: 4770 bx lr + +0000d510 : + d510: b5f8 push {r3, r4, r5, r6, r7, lr} + d512: f1a1 0385 sub.w r3, r1, #133 ; 0x85 + d516: f000 061f and.w r6, r0, #31 + d51a: 2b03 cmp r3, #3 + d51c: d83c bhi.n d598 + d51e: e8df f003 tbb [pc, r3] + d522: 3036 .short 0x3036 + d524: 022a .short 0x022a + d526: 2701 movs r7, #1 + d528: 463a mov r2, r7 + d52a: 40b7 lsls r7, r6 + d52c: 463d mov r5, r7 + d52e: 4611 mov r1, r2 + d530: f240 3410 movw r4, #784 ; 0x310 + d534: f2c1 0400 movt r4, #4096 ; 0x1000 + d538: 6823 ldr r3, [r4, #0] + d53a: 0758 lsls r0, r3, #29 + d53c: d448 bmi.n d5d0 + d53e: f241 0338 movw r3, #4152 ; 0x1038 + d542: 2201 movs r2, #1 + d544: f2c4 0300 movt r3, #16384 ; 0x4000 + d548: fa02 f606 lsl.w r6, r2, r6 + d54c: 43f6 mvns r6, r6 + d54e: 681a ldr r2, [r3, #0] + d550: 4032 ands r2, r6 + d552: 433a orrs r2, r7 + d554: 601a str r2, [r3, #0] + d556: 6823 ldr r3, [r4, #0] + d558: 0759 lsls r1, r3, #29 + d55a: d443 bmi.n d5e4 + d55c: f241 033c movw r3, #4156 ; 0x103c + d560: f2c4 0300 movt r3, #16384 ; 0x4000 + d564: 681a ldr r2, [r3, #0] + d566: 4016 ands r6, r2 + d568: ea46 0205 orr.w r2, r6, r5 + d56c: 601a str r2, [r3, #0] + d56e: 6823 ldr r3, [r4, #0] + d570: 075b lsls r3, r3, #29 + d572: d422 bmi.n d5ba + d574: bdf8 pop {r3, r4, r5, r6, r7, pc} + d576: 2101 movs r1, #1 + d578: 2500 movs r5, #0 + d57a: fa01 f706 lsl.w r7, r1, r6 + d57e: 462a mov r2, r5 + d580: e7d6 b.n d530 + d582: 2201 movs r2, #1 + d584: 2700 movs r7, #0 + d586: fa02 f506 lsl.w r5, r2, r6 + d58a: 4639 mov r1, r7 + d58c: e7d0 b.n d530 + d58e: 2500 movs r5, #0 + d590: 462f mov r7, r5 + d592: 462a mov r2, r5 + d594: 4629 mov r1, r5 + d596: e7cb b.n d530 + d598: f240 3314 movw r3, #788 ; 0x314 + d59c: f2c1 0300 movt r3, #4096 ; 0x1000 + d5a0: 681b ldr r3, [r3, #0] + d5a2: 075c lsls r4, r3, #29 + d5a4: d5e6 bpl.n d574 + d5a6: f642 2034 movw r0, #10804 ; 0x2a34 + d5aa: f24f 339d movw r3, #62365 ; 0xf39d + d5ae: f2c0 0004 movt r0, #4 + d5b2: f2c0 0300 movt r3, #0 + d5b6: 4798 blx r3 + d5b8: bdf8 pop {r3, r4, r5, r6, r7, pc} + d5ba: f642 20a4 movw r0, #10916 ; 0x2aa4 + d5be: f24f 339d movw r3, #62365 ; 0xf39d + d5c2: 213c movs r1, #60 ; 0x3c + d5c4: f2c0 0300 movt r3, #0 + d5c8: f2c0 0004 movt r0, #4 + d5cc: 4798 blx r3 + d5ce: e7d1 b.n d574 + d5d0: f642 2064 movw r0, #10852 ; 0x2a64 + d5d4: f24f 339d movw r3, #62365 ; 0xf39d + d5d8: f2c0 0004 movt r0, #4 + d5dc: f2c0 0300 movt r3, #0 + d5e0: 4798 blx r3 + d5e2: e7ac b.n d53e + d5e4: f642 20a4 movw r0, #10916 ; 0x2aa4 + d5e8: f24f 339d movw r3, #62365 ; 0xf39d + d5ec: 2138 movs r1, #56 ; 0x38 + d5ee: f2c0 0300 movt r3, #0 + d5f2: f2c0 0004 movt r0, #4 + d5f6: 4798 blx r3 + d5f8: e7b0 b.n d55c + d5fa: bf00 nop + +0000d5fc : + d5fc: b5f8 push {r3, r4, r5, r6, r7, lr} + d5fe: f240 3754 movw r7, #852 ; 0x354 + d602: f44f 5382 mov.w r3, #4160 ; 0x1040 + d606: f2c4 0300 movt r3, #16384 ; 0x4000 + d60a: f2c1 0700 movt r7, #4096 ; 0x1000 + d60e: 681d ldr r5, [r3, #0] + d610: 2400 movs r4, #0 + d612: 2601 movs r6, #1 + d614: fa06 f304 lsl.w r3, r6, r4 + d618: 422b tst r3, r5 + d61a: d008 beq.n d62e + d61c: 683a ldr r2, [r7, #0] + d61e: eb02 0284 add.w r2, r2, r4, lsl #2 + d622: 6953 ldr r3, [r2, #20] + d624: b11b cbz r3, d62e + d626: f8d2 0094 ldr.w r0, [r2, #148] ; 0x94 + d62a: 4621 mov r1, r4 + d62c: 4798 blx r3 + d62e: 3401 adds r4, #1 + d630: 2c20 cmp r4, #32 + d632: d1ef bne.n d614 + d634: f241 034c movw r3, #4172 ; 0x104c + d638: f2c4 0300 movt r3, #16384 ; 0x4000 + d63c: 2000 movs r0, #0 + d63e: 601d str r5, [r3, #0] + d640: bdf8 pop {r3, r4, r5, r6, r7, pc} + d642: bf00 nop + +0000d644 : + d644: f241 0250 movw r2, #4176 ; 0x1050 + d648: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + d64c: f240 3854 movw r8, #852 ; 0x354 + d650: f44f 5382 mov.w r3, #4160 ; 0x1040 + d654: f2c4 0200 movt r2, #16384 ; 0x4000 + d658: f2c4 0300 movt r3, #16384 ; 0x4000 + d65c: f2c1 0800 movt r8, #4096 ; 0x1000 + d660: 6817 ldr r7, [r2, #0] + d662: 681d ldr r5, [r3, #0] + d664: 2400 movs r4, #0 + d666: 2601 movs r6, #1 + d668: fa06 f304 lsl.w r3, r6, r4 + d66c: 422b tst r3, r5 + d66e: d00c beq.n d68a + d670: f8d8 1000 ldr.w r1, [r8] + d674: eb01 0184 add.w r1, r1, r4, lsl #2 + d678: 694a ldr r2, [r1, #20] + d67a: b132 cbz r2, d68a + d67c: 423b tst r3, r7 + d67e: f8d1 0094 ldr.w r0, [r1, #148] ; 0x94 + d682: bf0c ite eq + d684: 2102 moveq r1, #2 + d686: 2101 movne r1, #1 + d688: 4790 blx r2 + d68a: 3401 adds r4, #1 + d68c: 2c20 cmp r4, #32 + d68e: d1eb bne.n d668 + d690: f241 034c movw r3, #4172 ; 0x104c + d694: f2c4 0300 movt r3, #16384 ; 0x4000 + d698: 2000 movs r0, #0 + d69a: 601d str r5, [r3, #0] + d69c: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +0000d6a0 : + d6a0: f240 3354 movw r3, #852 ; 0x354 + d6a4: f2c1 0300 movt r3, #4096 ; 0x1000 + d6a8: f44f 5282 mov.w r2, #4160 ; 0x1040 + d6ac: f2c4 0200 movt r2, #16384 ; 0x4000 + d6b0: 681b ldr r3, [r3, #0] + d6b2: b510 push {r4, lr} + d6b4: 691b ldr r3, [r3, #16] + d6b6: 6814 ldr r4, [r2, #0] + d6b8: b10b cbz r3, d6be + d6ba: 4620 mov r0, r4 + d6bc: 4798 blx r3 + d6be: f241 034c movw r3, #4172 ; 0x104c + d6c2: f2c4 0300 movt r3, #16384 ; 0x4000 + d6c6: 2000 movs r0, #0 + d6c8: 601c str r4, [r3, #0] + d6ca: bd10 pop {r4, pc} + +0000d6cc : + d6cc: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} + d6d0: 6844 ldr r4, [r0, #4] + d6d2: 6806 ldr r6, [r0, #0] + d6d4: f014 0f60 tst.w r4, #96 ; 0x60 + d6d8: d014 beq.n d704 + d6da: f240 3014 movw r0, #788 ; 0x314 + d6de: f2c1 0000 movt r0, #4096 ; 0x1000 + d6e2: 6803 ldr r3, [r0, #0] + d6e4: 0759 lsls r1, r3, #29 + d6e6: d572 bpl.n d7ce + d6e8: f642 20d0 movw r0, #10960 ; 0x2ad0 + d6ec: f24f 359d movw r5, #62365 ; 0xf39d + d6f0: 4621 mov r1, r4 + d6f2: 4632 mov r2, r6 + d6f4: f2c0 0500 movt r5, #0 + d6f8: f2c0 0004 movt r0, #4 + d6fc: 47a8 blx r5 + d6fe: 2003 movs r0, #3 + d700: e8bd 83f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} + d704: f240 3554 movw r5, #852 ; 0x354 + d708: f2c1 0500 movt r5, #4096 ; 0x1000 + d70c: 682b ldr r3, [r5, #0] + d70e: 460f mov r7, r1 + d710: f8d3 2114 ldr.w r2, [r3, #276] ; 0x114 + d714: b10a cbz r2, d71a + d716: 4790 blx r2 + d718: 682b ldr r3, [r5, #0] + d71a: f893 2129 ldrb.w r2, [r3, #297] ; 0x129 + d71e: f04f 0901 mov.w r9, #1 + d722: 2a00 cmp r2, #0 + d724: d03e beq.n d7a4 + d726: f8d3 3118 ldr.w r3, [r3, #280] ; 0x118 + d72a: b103 cbz r3, d72e + d72c: 4798 blx r3 + d72e: f1b9 0f00 cmp.w r9, #0 + d732: d13c bne.n d7ae + d734: f240 3810 movw r8, #784 ; 0x310 + d738: f2c1 0800 movt r8, #4096 ; 0x1000 + d73c: f8d8 3000 ldr.w r3, [r8] + d740: f004 041f and.w r4, r4, #31 + d744: 075a lsls r2, r3, #29 + d746: d450 bmi.n d7ea + d748: f241 0330 movw r3, #4144 ; 0x1030 + d74c: f2c4 0300 movt r3, #16384 ; 0x4000 + d750: f8d3 9000 ldr.w r9, [r3] + d754: bb77 cbnz r7, d7b4 + d756: f241 034c movw r3, #4172 ; 0x104c + d75a: f2c4 0300 movt r3, #16384 ; 0x4000 + d75e: 2201 movs r2, #1 + d760: fa02 f404 lsl.w r4, r2, r4 + d764: 601c str r4, [r3, #0] + d766: ea29 0204 bic.w r2, r9, r4 + d76a: f241 0330 movw r3, #4144 ; 0x1030 + d76e: f2c4 0300 movt r3, #16384 ; 0x4000 + d772: 601a str r2, [r3, #0] + d774: f8d8 3000 ldr.w r3, [r8] + d778: 075b lsls r3, r3, #29 + d77a: d42b bmi.n d7d4 + d77c: f240 3454 movw r4, #852 ; 0x354 + d780: 682a ldr r2, [r5, #0] + d782: f2c1 0400 movt r4, #4096 ; 0x1000 + d786: f8d2 3114 ldr.w r3, [r2, #276] ; 0x114 + d78a: b10b cbz r3, d790 + d78c: 4798 blx r3 + d78e: 6822 ldr r2, [r4, #0] + d790: f8d2 3118 ldr.w r3, [r2, #280] ; 0x118 + d794: 2400 movs r4, #0 + d796: f882 4129 strb.w r4, [r2, #297] ; 0x129 + d79a: b1ab cbz r3, d7c8 + d79c: 4798 blx r3 + d79e: 4620 mov r0, r4 + d7a0: e8bd 83f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} + d7a4: 2101 movs r1, #1 + d7a6: 4691 mov r9, r2 + d7a8: f883 1129 strb.w r1, [r3, #297] ; 0x129 + d7ac: e7bb b.n d726 + d7ae: 2001 movs r0, #1 + d7b0: e8bd 83f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} + d7b4: 4620 mov r0, r4 + d7b6: b2f1 uxtb r1, r6 + d7b8: f7ff feaa bl d510 + d7bc: 2301 movs r3, #1 + d7be: fa03 f404 lsl.w r4, r3, r4 + d7c2: ea44 0209 orr.w r2, r4, r9 + d7c6: e7d0 b.n d76a + d7c8: 4618 mov r0, r3 + d7ca: e8bd 83f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} + d7ce: 2003 movs r0, #3 + d7d0: e8bd 83f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} + d7d4: f642 20a4 movw r0, #10916 ; 0x2aa4 + d7d8: f24f 339d movw r3, #62365 ; 0xf39d + d7dc: 2130 movs r1, #48 ; 0x30 + d7de: f2c0 0300 movt r3, #0 + d7e2: f2c0 0004 movt r0, #4 + d7e6: 4798 blx r3 + d7e8: e7c8 b.n d77c + d7ea: f642 301c movw r0, #11036 ; 0x2b1c + d7ee: f24f 3c9d movw ip, #62365 ; 0xf39d + d7f2: 4649 mov r1, r9 + d7f4: f2c0 0c00 movt ip, #0 + d7f8: 4622 mov r2, r4 + d7fa: 4633 mov r3, r6 + d7fc: f2c0 0004 movt r0, #4 + d800: 47e0 blx ip + d802: e7a1 b.n d748 + +0000d804 : + d804: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + d808: f240 3454 movw r4, #852 ; 0x354 + d80c: f2c1 0400 movt r4, #4096 ; 0x1000 + d810: 6822 ldr r2, [r4, #0] + d812: 2a00 cmp r2, #0 + d814: f000 8095 beq.w d942 + d818: f240 3310 movw r3, #784 ; 0x310 + d81c: f2c1 0300 movt r3, #4096 ; 0x1000 + d820: 681b ldr r3, [r3, #0] + d822: 4605 mov r5, r0 + d824: 075e lsls r6, r3, #29 + d826: f100 8131 bmi.w da8c + d82a: f892 3128 ldrb.w r3, [r2, #296] ; 0x128 + d82e: 2b00 cmp r3, #0 + d830: d042 beq.n d8b8 + d832: cda0 ldmia r5, {r5, r7} + d834: 0628 lsls r0, r5, #24 + d836: f3c7 1841 ubfx r8, r7, #5, #2 + d83a: d516 bpl.n d86a + d83c: f1b8 0f00 cmp.w r8, #0 + d840: d013 beq.n d86a + d842: f240 3314 movw r3, #788 ; 0x314 + d846: f2c1 0300 movt r3, #4096 ; 0x1000 + d84a: 681b ldr r3, [r3, #0] + d84c: 0759 lsls r1, r3, #29 + d84e: f140 811a bpl.w da86 + d852: f642 30cc movw r0, #11212 ; 0x2bcc + d856: f24f 339d movw r3, #62365 ; 0xf39d + d85a: f2c0 0004 movt r0, #4 + d85e: f2c0 0300 movt r3, #0 + d862: 4798 blx r3 + d864: 2003 movs r0, #3 + d866: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + d86a: f240 3654 movw r6, #852 ; 0x354 + d86e: 6823 ldr r3, [r4, #0] + d870: f2c1 0600 movt r6, #4096 ; 0x1000 + d874: f8d3 2114 ldr.w r2, [r3, #276] ; 0x114 + d878: b10a cbz r2, d87e + d87a: 4790 blx r2 + d87c: 6833 ldr r3, [r6, #0] + d87e: f893 1129 ldrb.w r1, [r3, #297] ; 0x129 + d882: 2601 movs r6, #1 + d884: b179 cbz r1, d8a6 + d886: f8d3 3118 ldr.w r3, [r3, #280] ; 0x118 + d88a: b103 cbz r3, d88e + d88c: 4798 blx r3 + d88e: b1b6 cbz r6, d8be + d890: f240 330c movw r3, #780 ; 0x30c + d894: f2c1 0300 movt r3, #4096 ; 0x1000 + d898: 681b ldr r3, [r3, #0] + d89a: 075a lsls r2, r3, #29 + d89c: f100 8103 bmi.w daa6 + d8a0: 2001 movs r0, #1 + d8a2: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + d8a6: 2201 movs r2, #1 + d8a8: f883 2129 strb.w r2, [r3, #297] ; 0x129 + d8ac: f8d3 3118 ldr.w r3, [r3, #280] ; 0x118 + d8b0: 460e mov r6, r1 + d8b2: 2b00 cmp r3, #0 + d8b4: d1ea bne.n d88c + d8b6: e7ea b.n d88e + d8b8: f7ff fdb2 bl d420 + d8bc: e7b9 b.n d832 + d8be: f007 071f and.w r7, r7, #31 + d8c2: 4639 mov r1, r7 + d8c4: 4640 mov r0, r8 + d8c6: f7ff fd33 bl d330 + d8ca: f44f 7348 mov.w r3, #800 ; 0x320 + d8ce: f2c4 0300 movt r3, #16384 ; 0x4000 + d8d2: f3c0 1e03 ubfx lr, r0, #4, #4 + d8d6: f8d3 c000 ldr.w ip, [r3] + d8da: 2201 movs r2, #1 + d8dc: fa02 fe0e lsl.w lr, r2, lr + d8e0: ea4e 0e0c orr.w lr, lr, ip + d8e4: 2d04 cmp r5, #4 + d8e6: 4601 mov r1, r0 + d8e8: f8c3 e000 str.w lr, [r3] + d8ec: f000 8089 beq.w da02 + d8f0: d83b bhi.n d96a + d8f2: 2d02 cmp r5, #2 + d8f4: d961 bls.n d9ba + d8f6: f241 23b4 movw r3, #4788 ; 0x12b4 + d8fa: f2c0 0303 movt r3, #3 + d8fe: 4443 add r3, r8 + d900: f893 32e0 ldrb.w r3, [r3, #736] ; 0x2e0 + d904: fa02 f707 lsl.w r7, r2, r7 + d908: f103 4280 add.w r2, r3, #1073741824 ; 0x40000000 + d90c: f502 5280 add.w r2, r2, #4096 ; 0x1000 + d910: 6811 ldr r1, [r2, #0] + d912: 6823 ldr r3, [r4, #0] + d914: 4339 orrs r1, r7 + d916: 6011 str r1, [r2, #0] + d918: eb03 0888 add.w r8, r3, r8, lsl #2 + d91c: f8d8 211c ldr.w r2, [r8, #284] ; 0x11c + d920: 433a orrs r2, r7 + d922: f8c8 211c str.w r2, [r8, #284] ; 0x11c + d926: f8d3 2114 ldr.w r2, [r3, #276] ; 0x114 + d92a: b10a cbz r2, d930 + d92c: 4790 blx r2 + d92e: 6823 ldr r3, [r4, #0] + d930: f8d3 2118 ldr.w r2, [r3, #280] ; 0x118 + d934: 2100 movs r1, #0 + d936: f883 1129 strb.w r1, [r3, #297] ; 0x129 + d93a: b102 cbz r2, d93e + d93c: 4790 blx r2 + d93e: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + d942: f240 3314 movw r3, #788 ; 0x314 + d946: f2c1 0300 movt r3, #4096 ; 0x1000 + d94a: 681b ldr r3, [r3, #0] + d94c: 075f lsls r7, r3, #29 + d94e: f140 809a bpl.w da86 + d952: f642 3064 movw r0, #11108 ; 0x2b64 + d956: f24f 339d movw r3, #62365 ; 0xf39d + d95a: f2c0 0004 movt r0, #4 + d95e: f2c0 0300 movt r3, #0 + d962: 4798 blx r3 + d964: 2003 movs r0, #3 + d966: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + d96a: 2d86 cmp r5, #134 ; 0x86 + d96c: d004 beq.n d978 + d96e: d941 bls.n d9f4 + d970: 2d87 cmp r5, #135 ; 0x87 + d972: d041 beq.n d9f8 + d974: 2d88 cmp r5, #136 ; 0x88 + d976: d161 bne.n da3c + d978: 4608 mov r0, r1 + d97a: 2101 movs r1, #1 + d97c: f7ff fd0e bl d39c + d980: b2e9 uxtb r1, r5 + d982: 4638 mov r0, r7 + d984: f7ff fdc4 bl d510 + d988: f241 034c movw r3, #4172 ; 0x104c + d98c: f241 0230 movw r2, #4144 ; 0x1030 + d990: f2c4 0300 movt r3, #16384 ; 0x4000 + d994: f2c4 0200 movt r2, #16384 ; 0x4000 + d998: 2101 movs r1, #1 + d99a: fa01 f707 lsl.w r7, r1, r7 + d99e: 601f str r7, [r3, #0] + d9a0: 6811 ldr r1, [r2, #0] + d9a2: 6823 ldr r3, [r4, #0] + d9a4: 4339 orrs r1, r7 + d9a6: 6011 str r1, [r2, #0] + d9a8: eb03 0888 add.w r8, r3, r8, lsl #2 + d9ac: f8d8 211c ldr.w r2, [r8, #284] ; 0x11c + d9b0: ea22 0707 bic.w r7, r2, r7 + d9b4: f8c8 711c str.w r7, [r8, #284] ; 0x11c + d9b8: e7b5 b.n d926 + d9ba: f241 23b4 movw r3, #4788 ; 0x12b4 + d9be: f2c0 0303 movt r3, #3 + d9c2: fa02 f707 lsl.w r7, r2, r7 + d9c6: 43ff mvns r7, r7 + d9c8: 4443 add r3, r8 + d9ca: f893 32e0 ldrb.w r3, [r3, #736] ; 0x2e0 + d9ce: b2e9 uxtb r1, r5 + d9d0: f103 4380 add.w r3, r3, #1073741824 ; 0x40000000 + d9d4: f503 5380 add.w r3, r3, #4096 ; 0x1000 + d9d8: 681a ldr r2, [r3, #0] + d9da: 403a ands r2, r7 + d9dc: 601a str r2, [r3, #0] + d9de: f7ff fcdd bl d39c + d9e2: 6823 ldr r3, [r4, #0] + d9e4: eb03 0888 add.w r8, r3, r8, lsl #2 + d9e8: f8d8 211c ldr.w r2, [r8, #284] ; 0x11c + d9ec: 403a ands r2, r7 + d9ee: f8c8 211c str.w r2, [r8, #284] ; 0x11c + d9f2: e798 b.n d926 + d9f4: 2d85 cmp r5, #133 ; 0x85 + d9f6: d121 bne.n da3c + d9f8: 4608 mov r0, r1 + d9fa: 2102 movs r1, #2 + d9fc: f7ff fcce bl d39c + da00: e7be b.n d980 + da02: f241 23b4 movw r3, #4788 ; 0x12b4 + da06: f2c0 0303 movt r3, #3 + da0a: 4443 add r3, r8 + da0c: f893 32e0 ldrb.w r3, [r3, #736] ; 0x2e0 + da10: fa02 f707 lsl.w r7, r2, r7 + da14: f103 4380 add.w r3, r3, #1073741824 ; 0x40000000 + da18: f503 5380 add.w r3, r3, #4096 ; 0x1000 + da1c: 681a ldr r2, [r3, #0] + da1e: 4631 mov r1, r6 + da20: ea22 0207 bic.w r2, r2, r7 + da24: 601a str r2, [r3, #0] + da26: f7ff fcb9 bl d39c + da2a: 6823 ldr r3, [r4, #0] + da2c: eb03 0888 add.w r8, r3, r8, lsl #2 + da30: f8d8 211c ldr.w r2, [r8, #284] ; 0x11c + da34: 433a orrs r2, r7 + da36: f8c8 211c str.w r2, [r8, #284] ; 0x11c + da3a: e774 b.n d926 + da3c: f240 3314 movw r3, #788 ; 0x314 + da40: f2c1 0300 movt r3, #4096 ; 0x1000 + da44: 681b ldr r3, [r3, #0] + da46: 075b lsls r3, r3, #29 + da48: d509 bpl.n da5e + da4a: f642 4034 movw r0, #11316 ; 0x2c34 + da4e: f24f 339d movw r3, #62365 ; 0xf39d + da52: 4629 mov r1, r5 + da54: f2c0 0004 movt r0, #4 + da58: f2c0 0300 movt r3, #0 + da5c: 4798 blx r3 + da5e: f240 3554 movw r5, #852 ; 0x354 + da62: 6823 ldr r3, [r4, #0] + da64: f2c1 0500 movt r5, #4096 ; 0x1000 + da68: f8d3 2114 ldr.w r2, [r3, #276] ; 0x114 + da6c: b10a cbz r2, da72 + da6e: 4790 blx r2 + da70: 682b ldr r3, [r5, #0] + da72: f8d3 2118 ldr.w r2, [r3, #280] ; 0x118 + da76: 2100 movs r1, #0 + da78: f883 1129 strb.w r1, [r3, #297] ; 0x129 + da7c: b11a cbz r2, da86 + da7e: 4790 blx r2 + da80: 2003 movs r0, #3 + da82: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + da86: 2003 movs r0, #3 + da88: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + da8c: f642 3090 movw r0, #11152 ; 0x2b90 + da90: f24f 339d movw r3, #62365 ; 0xf39d + da94: 682a ldr r2, [r5, #0] + da96: f2c0 0004 movt r0, #4 + da9a: f2c0 0300 movt r3, #0 + da9e: 6869 ldr r1, [r5, #4] + daa0: 4798 blx r3 + daa2: 6822 ldr r2, [r4, #0] + daa4: e6c1 b.n d82a + daa6: f642 4004 movw r0, #11268 ; 0x2c04 + daaa: f24f 339d movw r3, #62365 ; 0xf39d + daae: f2c0 0004 movt r0, #4 + dab2: f2c0 0300 movt r3, #0 + dab6: 4798 blx r3 + dab8: 2001 movs r0, #1 + daba: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + dabe: bf00 nop + +0000dac0 : + dac0: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} + dac4: f240 3454 movw r4, #852 ; 0x354 + dac8: f2c1 0400 movt r4, #4096 ; 0x1000 + dacc: 6823 ldr r3, [r4, #0] + dace: 4605 mov r5, r0 + dad0: f8d3 2114 ldr.w r2, [r3, #276] ; 0x114 + dad4: 6846 ldr r6, [r0, #4] + dad6: 6807 ldr r7, [r0, #0] + dad8: b10a cbz r2, dade + dada: 4790 blx r2 + dadc: 6823 ldr r3, [r4, #0] + dade: f893 2129 ldrb.w r2, [r3, #297] ; 0x129 + dae2: f04f 0801 mov.w r8, #1 + dae6: b91a cbnz r2, daf0 + dae8: 4690 mov r8, r2 + daea: 2101 movs r1, #1 + daec: f883 1129 strb.w r1, [r3, #297] ; 0x129 + daf0: f8d3 3118 ldr.w r3, [r3, #280] ; 0x118 + daf4: b103 cbz r3, daf8 + daf6: 4798 blx r3 + daf8: f1b8 0f00 cmp.w r8, #0 + dafc: d156 bne.n dbac + dafe: f240 3310 movw r3, #784 ; 0x310 + db02: f2c1 0300 movt r3, #4096 ; 0x1000 + db06: 681b ldr r3, [r3, #0] + db08: 075a lsls r2, r3, #29 + db0a: d455 bmi.n dbb8 + db0c: f241 23b4 movw r3, #4788 ; 0x12b4 + db10: f2c0 0303 movt r3, #3 + db14: f006 081f and.w r8, r6, #31 + db18: f04f 0901 mov.w r9, #1 + db1c: fa09 f908 lsl.w r9, r9, r8 + db20: ea6f 0a09 mvn.w sl, r9 + db24: f3c6 1641 ubfx r6, r6, #5, #2 + db28: 4433 add r3, r6 + db2a: f893 32e0 ldrb.w r3, [r3, #736] ; 0x2e0 + db2e: 4641 mov r1, r8 + db30: f103 4380 add.w r3, r3, #1073741824 ; 0x40000000 + db34: f503 5380 add.w r3, r3, #4096 ; 0x1000 + db38: 681a ldr r2, [r3, #0] + db3a: 4630 mov r0, r6 + db3c: ea02 020a and.w r2, r2, sl + db40: 601a str r2, [r3, #0] + db42: f7ff fbf5 bl d330 + db46: 2100 movs r1, #0 + db48: f7ff fc28 bl d39c + db4c: 063b lsls r3, r7, #24 + db4e: d411 bmi.n db74 + db50: 6823 ldr r3, [r4, #0] + db52: f8d3 2114 ldr.w r2, [r3, #276] ; 0x114 + db56: 2100 movs r1, #0 + db58: 6029 str r1, [r5, #0] + db5a: b10a cbz r2, db60 + db5c: 4790 blx r2 + db5e: 6823 ldr r3, [r4, #0] + db60: f8d3 2118 ldr.w r2, [r3, #280] ; 0x118 + db64: 2400 movs r4, #0 + db66: f883 4129 strb.w r4, [r3, #297] ; 0x129 + db6a: b312 cbz r2, dbb2 + db6c: 4790 blx r2 + db6e: 4620 mov r0, r4 + db70: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + db74: 2e00 cmp r6, #0 + db76: d1eb bne.n db50 + db78: f241 0230 movw r2, #4144 ; 0x1030 + db7c: f241 014c movw r1, #4172 ; 0x104c + db80: f2c4 0200 movt r2, #16384 ; 0x4000 + db84: f2c4 0100 movt r1, #16384 ; 0x4000 + db88: 6810 ldr r0, [r2, #0] + db8a: 6823 ldr r3, [r4, #0] + db8c: ea0a 0000 and.w r0, sl, r0 + db90: 6010 str r0, [r2, #0] + db92: eb03 0888 add.w r8, r3, r8, lsl #2 + db96: f8c1 9000 str.w r9, [r1] + db9a: f8d8 2014 ldr.w r2, [r8, #20] + db9e: 2a00 cmp r2, #0 + dba0: d0d7 beq.n db52 + dba2: f8c8 6014 str.w r6, [r8, #20] + dba6: f8c8 6094 str.w r6, [r8, #148] ; 0x94 + dbaa: e7d2 b.n db52 + dbac: 2001 movs r0, #1 + dbae: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + dbb2: 4610 mov r0, r2 + dbb4: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + dbb8: f642 406c movw r0, #11372 ; 0x2c6c + dbbc: f24f 339d movw r3, #62365 ; 0xf39d + dbc0: 6869 ldr r1, [r5, #4] + dbc2: f2c0 0300 movt r3, #0 + dbc6: 682a ldr r2, [r5, #0] + dbc8: f2c0 0004 movt r0, #4 + dbcc: 4798 blx r3 + dbce: e79d b.n db0c + +0000dbd0 : + dbd0: b5f8 push {r3, r4, r5, r6, r7, lr} + dbd2: f240 3454 movw r4, #852 ; 0x354 + dbd6: f2c1 0400 movt r4, #4096 ; 0x1000 + dbda: 6823 ldr r3, [r4, #0] + dbdc: 6845 ldr r5, [r0, #4] + dbde: f8d3 2114 ldr.w r2, [r3, #276] ; 0x114 + dbe2: 6806 ldr r6, [r0, #0] + dbe4: b10a cbz r2, dbea + dbe6: 4790 blx r2 + dbe8: 6823 ldr r3, [r4, #0] + dbea: f893 2129 ldrb.w r2, [r3, #297] ; 0x129 + dbee: 2701 movs r7, #1 + dbf0: b91a cbnz r2, dbfa + dbf2: 4617 mov r7, r2 + dbf4: 2101 movs r1, #1 + dbf6: f883 1129 strb.w r1, [r3, #297] ; 0x129 + dbfa: f8d3 3118 ldr.w r3, [r3, #280] ; 0x118 + dbfe: b103 cbz r3, dc02 + dc00: 4798 blx r3 + dc02: b147 cbz r7, dc16 + dc04: f240 330c movw r3, #780 ; 0x30c + dc08: f2c1 0300 movt r3, #4096 ; 0x1000 + dc0c: 681b ldr r3, [r3, #0] + dc0e: 075b lsls r3, r3, #29 + dc10: d433 bmi.n dc7a + dc12: 2002 movs r0, #2 + dc14: bdf8 pop {r3, r4, r5, r6, r7, pc} + dc16: f241 23b4 movw r3, #4788 ; 0x12b4 + dc1a: f2c0 0303 movt r3, #3 + dc1e: f3c5 1241 ubfx r2, r5, #5, #2 + dc22: 4413 add r3, r2 + dc24: f893 32e4 ldrb.w r3, [r3, #740] ; 0x2e4 + dc28: 2201 movs r2, #1 + dc2a: f103 4380 add.w r3, r3, #1073741824 ; 0x40000000 + dc2e: f503 5380 add.w r3, r3, #4096 ; 0x1000 + dc32: 681b ldr r3, [r3, #0] + dc34: f005 051f and.w r5, r5, #31 + dc38: fa02 f505 lsl.w r5, r2, r5 + dc3c: 422b tst r3, r5 + dc3e: bf18 it ne + dc40: 4610 movne r0, r2 + dc42: f240 3554 movw r5, #852 ; 0x354 + dc46: 6823 ldr r3, [r4, #0] + dc48: bf08 it eq + dc4a: 2000 moveq r0, #0 + dc4c: f8d3 2114 ldr.w r2, [r3, #276] ; 0x114 + dc50: 2e04 cmp r6, #4 + dc52: bf14 ite ne + dc54: 4606 movne r6, r0 + dc56: f080 0601 eoreq.w r6, r0, #1 + dc5a: f2c1 0500 movt r5, #4096 ; 0x1000 + dc5e: b10a cbz r2, dc64 + dc60: 4790 blx r2 + dc62: 682b ldr r3, [r5, #0] + dc64: f8d3 2118 ldr.w r2, [r3, #280] ; 0x118 + dc68: 2100 movs r1, #0 + dc6a: f883 1129 strb.w r1, [r3, #297] ; 0x129 + dc6e: b112 cbz r2, dc76 + dc70: 4790 blx r2 + dc72: 4630 mov r0, r6 + dc74: bdf8 pop {r3, r4, r5, r6, r7, pc} + dc76: 4630 mov r0, r6 + dc78: bdf8 pop {r3, r4, r5, r6, r7, pc} + dc7a: f642 40ac movw r0, #11436 ; 0x2cac + dc7e: f24f 339d movw r3, #62365 ; 0xf39d + dc82: f2c0 0004 movt r0, #4 + dc86: f2c0 0300 movt r3, #0 + dc8a: 4798 blx r3 + dc8c: 2002 movs r0, #2 + dc8e: bdf8 pop {r3, r4, r5, r6, r7, pc} + +0000dc90 : + dc90: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + dc94: f240 3454 movw r4, #852 ; 0x354 + dc98: f2c1 0400 movt r4, #4096 ; 0x1000 + dc9c: 6823 ldr r3, [r4, #0] + dc9e: 460e mov r6, r1 + dca0: f8d3 2114 ldr.w r2, [r3, #276] ; 0x114 + dca4: 6845 ldr r5, [r0, #4] + dca6: 6807 ldr r7, [r0, #0] + dca8: b10a cbz r2, dcae + dcaa: 4790 blx r2 + dcac: 6823 ldr r3, [r4, #0] + dcae: f893 2129 ldrb.w r2, [r3, #297] ; 0x129 + dcb2: f04f 0801 mov.w r8, #1 + dcb6: b91a cbnz r2, dcc0 + dcb8: 4690 mov r8, r2 + dcba: 2101 movs r1, #1 + dcbc: f883 1129 strb.w r1, [r3, #297] ; 0x129 + dcc0: f8d3 3118 ldr.w r3, [r3, #280] ; 0x118 + dcc4: b103 cbz r3, dcc8 + dcc6: 4798 blx r3 + dcc8: f1b8 0f00 cmp.w r8, #0 + dccc: d009 beq.n dce2 + dcce: f240 330c movw r3, #780 ; 0x30c + dcd2: f2c1 0300 movt r3, #4096 ; 0x1000 + dcd6: 681b ldr r3, [r3, #0] + dcd8: 075b lsls r3, r3, #29 + dcda: d444 bmi.n dd66 + dcdc: 2001 movs r0, #1 + dcde: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + dce2: f241 23b4 movw r3, #4788 ; 0x12b4 + dce6: f2c0 0303 movt r3, #3 + dcea: f3c5 1241 ubfx r2, r5, #5, #2 + dcee: 2f04 cmp r7, #4 + dcf0: f005 051f and.w r5, r5, #31 + dcf4: 4413 add r3, r2 + dcf6: d023 beq.n dd40 + dcf8: f893 32e8 ldrb.w r3, [r3, #744] ; 0x2e8 + dcfc: 2101 movs r1, #1 + dcfe: f103 4380 add.w r3, r3, #1073741824 ; 0x40000000 + dd02: f503 5380 add.w r3, r3, #4096 ; 0x1000 + dd06: 681a ldr r2, [r3, #0] + dd08: 400e ands r6, r1 + dd0a: 40a9 lsls r1, r5 + dd0c: fa06 f505 lsl.w r5, r6, r5 + dd10: ea22 0601 bic.w r6, r2, r1 + dd14: 4335 orrs r5, r6 + dd16: 601d str r5, [r3, #0] + dd18: f240 3554 movw r5, #852 ; 0x354 + dd1c: 6822 ldr r2, [r4, #0] + dd1e: f2c1 0500 movt r5, #4096 ; 0x1000 + dd22: f8d2 3114 ldr.w r3, [r2, #276] ; 0x114 + dd26: b10b cbz r3, dd2c + dd28: 4798 blx r3 + dd2a: 682a ldr r2, [r5, #0] + dd2c: f8d2 3118 ldr.w r3, [r2, #280] ; 0x118 + dd30: 2400 movs r4, #0 + dd32: f882 4129 strb.w r4, [r2, #297] ; 0x129 + dd36: b19b cbz r3, dd60 + dd38: 4798 blx r3 + dd3a: 4620 mov r0, r4 + dd3c: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + dd40: 2e01 cmp r6, #1 + dd42: d01c beq.n dd7e + dd44: f893 32e0 ldrb.w r3, [r3, #736] ; 0x2e0 + dd48: 2101 movs r1, #1 + dd4a: f103 4380 add.w r3, r3, #1073741824 ; 0x40000000 + dd4e: f503 5380 add.w r3, r3, #4096 ; 0x1000 + dd52: 681a ldr r2, [r3, #0] + dd54: fa01 f505 lsl.w r5, r1, r5 + dd58: ea22 0505 bic.w r5, r2, r5 + dd5c: 601d str r5, [r3, #0] + dd5e: e7db b.n dd18 + dd60: 4618 mov r0, r3 + dd62: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + dd66: f642 40dc movw r0, #11484 ; 0x2cdc + dd6a: f24f 339d movw r3, #62365 ; 0xf39d + dd6e: f2c0 0004 movt r0, #4 + dd72: f2c0 0300 movt r3, #0 + dd76: 4798 blx r3 + dd78: 2001 movs r0, #1 + dd7a: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + dd7e: f893 22e0 ldrb.w r2, [r3, #736] ; 0x2e0 + dd82: f893 32e8 ldrb.w r3, [r3, #744] ; 0x2e8 + dd86: f102 4280 add.w r2, r2, #1073741824 ; 0x40000000 + dd8a: f502 5280 add.w r2, r2, #4096 ; 0x1000 + dd8e: 6811 ldr r1, [r2, #0] + dd90: fa06 f505 lsl.w r5, r6, r5 + dd94: 4329 orrs r1, r5 + dd96: f103 4380 add.w r3, r3, #1073741824 ; 0x40000000 + dd9a: f503 5380 add.w r3, r3, #4096 ; 0x1000 + dd9e: 6011 str r1, [r2, #0] + dda0: 681a ldr r2, [r3, #0] + dda2: ea22 0505 bic.w r5, r2, r5 + dda6: 601d str r5, [r3, #0] + dda8: e7b6 b.n dd18 + ddaa: bf00 nop + +0000ddac : + ddac: 6802 ldr r2, [r0, #0] + ddae: 2107 movs r1, #7 + ddb0: b508 push {r3, lr} + ddb2: 6041 str r1, [r0, #4] + ddb4: b14a cbz r2, ddca + ddb6: f244 0329 movw r3, #16425 ; 0x4029 + ddba: f2c0 0300 movt r3, #0 + ddbe: 4798 blx r3 + ddc0: 2801 cmp r0, #1 + ddc2: bf14 ite ne + ddc4: 20ee movne r0, #238 ; 0xee + ddc6: 2000 moveq r0, #0 + ddc8: bd08 pop {r3, pc} + ddca: f240 3314 movw r3, #788 ; 0x314 + ddce: f2c1 0300 movt r3, #4096 ; 0x1000 + ddd2: 681b ldr r3, [r3, #0] + ddd4: 075b lsls r3, r3, #29 + ddd6: d50a bpl.n ddee + ddd8: f642 5010 movw r0, #11536 ; 0x2d10 + dddc: f24f 339d movw r3, #62365 ; 0xf39d + dde0: f2c0 0004 movt r0, #4 + dde4: f2c0 0300 movt r3, #0 + dde8: 4798 blx r3 + ddea: 2003 movs r0, #3 + ddec: bd08 pop {r3, pc} + ddee: 2003 movs r0, #3 + ddf0: bd08 pop {r3, pc} + ddf2: bf00 nop + +0000ddf4 : + ddf4: f244 138d movw r3, #16781 ; 0x418d + ddf8: b510 push {r4, lr} + ddfa: f2c0 0300 movt r3, #0 + ddfe: 4604 mov r4, r0 + de00: 4798 blx r3 + de02: f244 0391 movw r3, #16529 ; 0x4091 + de06: 4620 mov r0, r4 + de08: f2c0 0300 movt r3, #0 + de0c: 4798 blx r3 + de0e: 2000 movs r0, #0 + de10: bd10 pop {r4, pc} + de12: bf00 nop + +0000de14 : + de14: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + de18: e890 0030 ldmia.w r0, {r4, r5} + de1c: 0620 lsls r0, r4, #24 + de1e: d502 bpl.n de26 + de20: f015 0f60 tst.w r5, #96 ; 0x60 + de24: d014 beq.n de50 + de26: f240 3314 movw r3, #788 ; 0x314 + de2a: f2c1 0300 movt r3, #4096 ; 0x1000 + de2e: 681b ldr r3, [r3, #0] + de30: 075a lsls r2, r3, #29 + de32: d552 bpl.n deda + de34: f642 5034 movw r0, #11572 ; 0x2d34 + de38: f24f 339d movw r3, #62365 ; 0xf39d + de3c: 4629 mov r1, r5 + de3e: 4622 mov r2, r4 + de40: f2c0 0300 movt r3, #0 + de44: f2c0 0004 movt r0, #4 + de48: 4798 blx r3 + de4a: 2003 movs r0, #3 + de4c: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + de50: f240 3454 movw r4, #852 ; 0x354 + de54: f2c1 0400 movt r4, #4096 ; 0x1000 + de58: 6823 ldr r3, [r4, #0] + de5a: 4617 mov r7, r2 + de5c: f8d3 2114 ldr.w r2, [r3, #276] ; 0x114 + de60: 460e mov r6, r1 + de62: b10a cbz r2, de68 + de64: 4790 blx r2 + de66: 6823 ldr r3, [r4, #0] + de68: f893 2129 ldrb.w r2, [r3, #297] ; 0x129 + de6c: f04f 0801 mov.w r8, #1 + de70: b91a cbnz r2, de7a + de72: 4690 mov r8, r2 + de74: 2101 movs r1, #1 + de76: f883 1129 strb.w r1, [r3, #297] ; 0x129 + de7a: f8d3 3118 ldr.w r3, [r3, #280] ; 0x118 + de7e: b103 cbz r3, de82 + de80: 4798 blx r3 + de82: f1b8 0f00 cmp.w r8, #0 + de86: d009 beq.n de9c + de88: f240 330c movw r3, #780 ; 0x30c + de8c: f2c1 0300 movt r3, #4096 ; 0x1000 + de90: 681b ldr r3, [r3, #0] + de92: 075b lsls r3, r3, #29 + de94: d424 bmi.n dee0 + de96: 2001 movs r0, #1 + de98: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + de9c: f240 3854 movw r8, #852 ; 0x354 + dea0: 6823 ldr r3, [r4, #0] + dea2: f005 051f and.w r5, r5, #31 + dea6: eb03 0585 add.w r5, r3, r5, lsl #2 + deaa: 616e str r6, [r5, #20] + deac: f8c5 7094 str.w r7, [r5, #148] ; 0x94 + deb0: f8d3 2114 ldr.w r2, [r3, #276] ; 0x114 + deb4: f2c1 0800 movt r8, #4096 ; 0x1000 + deb8: b112 cbz r2, dec0 + deba: 4790 blx r2 + debc: f8d8 3000 ldr.w r3, [r8] + dec0: f8d3 2118 ldr.w r2, [r3, #280] ; 0x118 + dec4: 2400 movs r4, #0 + dec6: f883 4129 strb.w r4, [r3, #297] ; 0x129 + deca: b11a cbz r2, ded4 + decc: 4790 blx r2 + dece: 4620 mov r0, r4 + ded0: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + ded4: 4610 mov r0, r2 + ded6: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + deda: 2003 movs r0, #3 + dedc: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + dee0: f642 5084 movw r0, #11652 ; 0x2d84 + dee4: f24f 339d movw r3, #62365 ; 0xf39d + dee8: f2c0 0004 movt r0, #4 + deec: f2c0 0300 movt r3, #0 + def0: 4798 blx r3 + def2: 2001 movs r0, #1 + def4: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +0000def8 : + def8: b5f8 push {r3, r4, r5, r6, r7, lr} + defa: e890 0014 ldmia.w r0, {r2, r4} + defe: 0610 lsls r0, r2, #24 + df00: d502 bpl.n df08 + df02: f014 0f60 tst.w r4, #96 ; 0x60 + df06: d012 beq.n df2e + df08: f240 3314 movw r3, #788 ; 0x314 + df0c: f2c1 0300 movt r3, #4096 ; 0x1000 + df10: 681b ldr r3, [r3, #0] + df12: 0759 lsls r1, r3, #29 + df14: d547 bpl.n dfa6 + df16: f642 50b8 movw r0, #11704 ; 0x2db8 + df1a: f24f 339d movw r3, #62365 ; 0xf39d + df1e: 4621 mov r1, r4 + df20: f2c0 0300 movt r3, #0 + df24: f2c0 0004 movt r0, #4 + df28: 4798 blx r3 + df2a: 2003 movs r0, #3 + df2c: bdf8 pop {r3, r4, r5, r6, r7, pc} + df2e: f240 3554 movw r5, #852 ; 0x354 + df32: f2c1 0500 movt r5, #4096 ; 0x1000 + df36: 682b ldr r3, [r5, #0] + df38: f8d3 2114 ldr.w r2, [r3, #276] ; 0x114 + df3c: b10a cbz r2, df42 + df3e: 4790 blx r2 + df40: 682b ldr r3, [r5, #0] + df42: f893 6129 ldrb.w r6, [r3, #297] ; 0x129 + df46: b986 cbnz r6, df6a + df48: 2201 movs r2, #1 + df4a: f883 2129 strb.w r2, [r3, #297] ; 0x129 + df4e: f8d3 3118 ldr.w r3, [r3, #280] ; 0x118 + df52: b103 cbz r3, df56 + df54: 4798 blx r3 + df56: b156 cbz r6, df6e + df58: f240 330c movw r3, #780 ; 0x30c + df5c: f2c1 0300 movt r3, #4096 ; 0x1000 + df60: 681b ldr r3, [r3, #0] + df62: 075b lsls r3, r3, #29 + df64: d421 bmi.n dfaa + df66: 2001 movs r0, #1 + df68: bdf8 pop {r3, r4, r5, r6, r7, pc} + df6a: 2601 movs r6, #1 + df6c: e7ef b.n df4e + df6e: f240 3754 movw r7, #852 ; 0x354 + df72: 682b ldr r3, [r5, #0] + df74: f004 041f and.w r4, r4, #31 + df78: eb03 0484 add.w r4, r3, r4, lsl #2 + df7c: 6166 str r6, [r4, #20] + df7e: f8c4 6094 str.w r6, [r4, #148] ; 0x94 + df82: f8d3 2114 ldr.w r2, [r3, #276] ; 0x114 + df86: f2c1 0700 movt r7, #4096 ; 0x1000 + df8a: b10a cbz r2, df90 + df8c: 4790 blx r2 + df8e: 683b ldr r3, [r7, #0] + df90: f8d3 2118 ldr.w r2, [r3, #280] ; 0x118 + df94: 2400 movs r4, #0 + df96: f883 4129 strb.w r4, [r3, #297] ; 0x129 + df9a: b112 cbz r2, dfa2 + df9c: 4790 blx r2 + df9e: 4620 mov r0, r4 + dfa0: bdf8 pop {r3, r4, r5, r6, r7, pc} + dfa2: 4610 mov r0, r2 + dfa4: bdf8 pop {r3, r4, r5, r6, r7, pc} + dfa6: 2003 movs r0, #3 + dfa8: bdf8 pop {r3, r4, r5, r6, r7, pc} + dfaa: f642 6008 movw r0, #11784 ; 0x2e08 + dfae: f24f 339d movw r3, #62365 ; 0xf39d + dfb2: f2c0 0004 movt r0, #4 + dfb6: f2c0 0300 movt r3, #0 + dfba: 4798 blx r3 + dfbc: 2001 movs r0, #1 + dfbe: bdf8 pop {r3, r4, r5, r6, r7, pc} + +0000dfc0 : + dfc0: b570 push {r4, r5, r6, lr} + dfc2: e890 0014 ldmia.w r0, {r2, r4} + dfc6: 0611 lsls r1, r2, #24 + dfc8: d502 bpl.n dfd0 + dfca: f014 0f60 tst.w r4, #96 ; 0x60 + dfce: d012 beq.n dff6 + dfd0: f240 3314 movw r3, #788 ; 0x314 + dfd4: f2c1 0300 movt r3, #4096 ; 0x1000 + dfd8: 681b ldr r3, [r3, #0] + dfda: 075b lsls r3, r3, #29 + dfdc: d53e bpl.n e05c + dfde: f642 6040 movw r0, #11840 ; 0x2e40 + dfe2: f24f 339d movw r3, #62365 ; 0xf39d + dfe6: 4621 mov r1, r4 + dfe8: f2c0 0300 movt r3, #0 + dfec: f2c0 0004 movt r0, #4 + dff0: 4798 blx r3 + dff2: 2003 movs r0, #3 + dff4: bd70 pop {r4, r5, r6, pc} + dff6: f240 3554 movw r5, #852 ; 0x354 + dffa: f2c1 0500 movt r5, #4096 ; 0x1000 + dffe: 682b ldr r3, [r5, #0] + e000: f8d3 2114 ldr.w r2, [r3, #276] ; 0x114 + e004: b10a cbz r2, e00a + e006: 4790 blx r2 + e008: 682b ldr r3, [r5, #0] + e00a: f893 2129 ldrb.w r2, [r3, #297] ; 0x129 + e00e: 2601 movs r6, #1 + e010: b91a cbnz r2, e01a + e012: 4616 mov r6, r2 + e014: 2101 movs r1, #1 + e016: f883 1129 strb.w r1, [r3, #297] ; 0x129 + e01a: f8d3 3118 ldr.w r3, [r3, #280] ; 0x118 + e01e: b103 cbz r3, e022 + e020: 4798 blx r3 + e022: b10e cbz r6, e028 + e024: 2001 movs r0, #1 + e026: bd70 pop {r4, r5, r6, pc} + e028: f240 3654 movw r6, #852 ; 0x354 + e02c: f004 001f and.w r0, r4, #31 + e030: 2101 movs r1, #1 + e032: f7ff fa59 bl d4e8 + e036: 682a ldr r2, [r5, #0] + e038: f2c1 0600 movt r6, #4096 ; 0x1000 + e03c: f8d2 3114 ldr.w r3, [r2, #276] ; 0x114 + e040: b10b cbz r3, e046 + e042: 4798 blx r3 + e044: 6832 ldr r2, [r6, #0] + e046: f8d2 3118 ldr.w r3, [r2, #280] ; 0x118 + e04a: 2400 movs r4, #0 + e04c: f882 4129 strb.w r4, [r2, #297] ; 0x129 + e050: b113 cbz r3, e058 + e052: 4798 blx r3 + e054: 4620 mov r0, r4 + e056: bd70 pop {r4, r5, r6, pc} + e058: 4618 mov r0, r3 + e05a: bd70 pop {r4, r5, r6, pc} + e05c: 2003 movs r0, #3 + e05e: bd70 pop {r4, r5, r6, pc} + +0000e060 : + e060: b5f8 push {r3, r4, r5, r6, r7, lr} + e062: e890 0014 ldmia.w r0, {r2, r4} + e066: 0611 lsls r1, r2, #24 + e068: d502 bpl.n e070 + e06a: f014 0f60 tst.w r4, #96 ; 0x60 + e06e: d012 beq.n e096 + e070: f240 3314 movw r3, #788 ; 0x314 + e074: f2c1 0300 movt r3, #4096 ; 0x1000 + e078: 681b ldr r3, [r3, #0] + e07a: 075b lsls r3, r3, #29 + e07c: d53e bpl.n e0fc + e07e: f642 608c movw r0, #11916 ; 0x2e8c + e082: f24f 339d movw r3, #62365 ; 0xf39d + e086: 4621 mov r1, r4 + e088: f2c0 0300 movt r3, #0 + e08c: f2c0 0004 movt r0, #4 + e090: 4798 blx r3 + e092: 2003 movs r0, #3 + e094: bdf8 pop {r3, r4, r5, r6, r7, pc} + e096: f240 3554 movw r5, #852 ; 0x354 + e09a: f2c1 0500 movt r5, #4096 ; 0x1000 + e09e: 682b ldr r3, [r5, #0] + e0a0: f8d3 2114 ldr.w r2, [r3, #276] ; 0x114 + e0a4: b10a cbz r2, e0aa + e0a6: 4790 blx r2 + e0a8: 682b ldr r3, [r5, #0] + e0aa: f893 1129 ldrb.w r1, [r3, #297] ; 0x129 + e0ae: 2601 movs r6, #1 + e0b0: b919 cbnz r1, e0ba + e0b2: 460e mov r6, r1 + e0b4: 2201 movs r2, #1 + e0b6: f883 2129 strb.w r2, [r3, #297] ; 0x129 + e0ba: f8d3 3118 ldr.w r3, [r3, #280] ; 0x118 + e0be: b103 cbz r3, e0c2 + e0c0: 4798 blx r3 + e0c2: b10e cbz r6, e0c8 + e0c4: 2001 movs r0, #1 + e0c6: bdf8 pop {r3, r4, r5, r6, r7, pc} + e0c8: f240 3754 movw r7, #852 ; 0x354 + e0cc: f004 001f and.w r0, r4, #31 + e0d0: 4631 mov r1, r6 + e0d2: f7ff fa09 bl d4e8 + e0d6: 682a ldr r2, [r5, #0] + e0d8: f2c1 0700 movt r7, #4096 ; 0x1000 + e0dc: f8d2 3114 ldr.w r3, [r2, #276] ; 0x114 + e0e0: b10b cbz r3, e0e6 + e0e2: 4798 blx r3 + e0e4: 683a ldr r2, [r7, #0] + e0e6: f8d2 3118 ldr.w r3, [r2, #280] ; 0x118 + e0ea: 2400 movs r4, #0 + e0ec: f882 4129 strb.w r4, [r2, #297] ; 0x129 + e0f0: b113 cbz r3, e0f8 + e0f2: 4798 blx r3 + e0f4: 4620 mov r0, r4 + e0f6: bdf8 pop {r3, r4, r5, r6, r7, pc} + e0f8: 4618 mov r0, r3 + e0fa: bdf8 pop {r3, r4, r5, r6, r7, pc} + e0fc: 2003 movs r0, #3 + e0fe: bdf8 pop {r3, r4, r5, r6, r7, pc} + +0000e100 : + e100: b5f8 push {r3, r4, r5, r6, r7, lr} + e102: e890 0014 ldmia.w r0, {r2, r4} + e106: 0610 lsls r0, r2, #24 + e108: d502 bpl.n e110 + e10a: f014 0f60 tst.w r4, #96 ; 0x60 + e10e: d012 beq.n e136 + e110: f240 3314 movw r3, #788 ; 0x314 + e114: f2c1 0300 movt r3, #4096 ; 0x1000 + e118: 681b ldr r3, [r3, #0] + e11a: 075b lsls r3, r3, #29 + e11c: d54e bpl.n e1bc + e11e: f642 60dc movw r0, #11996 ; 0x2edc + e122: f24f 339d movw r3, #62365 ; 0xf39d + e126: 4621 mov r1, r4 + e128: f2c0 0300 movt r3, #0 + e12c: f2c0 0004 movt r0, #4 + e130: 4798 blx r3 + e132: 2003 movs r0, #3 + e134: bdf8 pop {r3, r4, r5, r6, r7, pc} + e136: f240 3654 movw r6, #852 ; 0x354 + e13a: f2c1 0600 movt r6, #4096 ; 0x1000 + e13e: 6833 ldr r3, [r6, #0] + e140: 460d mov r5, r1 + e142: f8d3 2114 ldr.w r2, [r3, #276] ; 0x114 + e146: b10a cbz r2, e14c + e148: 4790 blx r2 + e14a: 6833 ldr r3, [r6, #0] + e14c: f893 2129 ldrb.w r2, [r3, #297] ; 0x129 + e150: 2701 movs r7, #1 + e152: b91a cbnz r2, e15c + e154: 4617 mov r7, r2 + e156: 2101 movs r1, #1 + e158: f883 1129 strb.w r1, [r3, #297] ; 0x129 + e15c: f8d3 3118 ldr.w r3, [r3, #280] ; 0x118 + e160: b103 cbz r3, e164 + e162: 4798 blx r3 + e164: b10f cbz r7, e16a + e166: 2001 movs r0, #1 + e168: bdf8 pop {r3, r4, r5, r6, r7, pc} + e16a: f241 0348 movw r3, #4168 ; 0x1048 + e16e: f2c4 0300 movt r3, #16384 ; 0x4000 + e172: f240 3754 movw r7, #852 ; 0x354 + e176: 6819 ldr r1, [r3, #0] + e178: 3500 adds r5, #0 + e17a: f004 041f and.w r4, r4, #31 + e17e: 6832 ldr r2, [r6, #0] + e180: f04f 0001 mov.w r0, #1 + e184: fa00 f004 lsl.w r0, r0, r4 + e188: bf18 it ne + e18a: 2501 movne r5, #1 + e18c: ea21 0000 bic.w r0, r1, r0 + e190: fa05 f404 lsl.w r4, r5, r4 + e194: f8d2 1114 ldr.w r1, [r2, #276] ; 0x114 + e198: 4304 orrs r4, r0 + e19a: 601c str r4, [r3, #0] + e19c: f2c1 0700 movt r7, #4096 ; 0x1000 + e1a0: b109 cbz r1, e1a6 + e1a2: 4788 blx r1 + e1a4: 683a ldr r2, [r7, #0] + e1a6: f8d2 3118 ldr.w r3, [r2, #280] ; 0x118 + e1aa: 2400 movs r4, #0 + e1ac: f882 4129 strb.w r4, [r2, #297] ; 0x129 + e1b0: b113 cbz r3, e1b8 + e1b2: 4798 blx r3 + e1b4: 4620 mov r0, r4 + e1b6: bdf8 pop {r3, r4, r5, r6, r7, pc} + e1b8: 4618 mov r0, r3 + e1ba: bdf8 pop {r3, r4, r5, r6, r7, pc} + e1bc: 2003 movs r0, #3 + e1be: bdf8 pop {r3, r4, r5, r6, r7, pc} + +0000e1c0 : + e1c0: b508 push {r3, lr} + e1c2: f7ff f88f bl d2e4 + e1c6: bd08 pop {r3, pc} + +0000e1c8 : + e1c8: b5f8 push {r3, r4, r5, r6, r7, lr} + e1ca: f240 3454 movw r4, #852 ; 0x354 + e1ce: f2c1 0400 movt r4, #4096 ; 0x1000 + e1d2: 6823 ldr r3, [r4, #0] + e1d4: 4606 mov r6, r0 + e1d6: f8d3 2114 ldr.w r2, [r3, #276] ; 0x114 + e1da: 460d mov r5, r1 + e1dc: b10a cbz r2, e1e2 + e1de: 4790 blx r2 + e1e0: 6823 ldr r3, [r4, #0] + e1e2: f893 2129 ldrb.w r2, [r3, #297] ; 0x129 + e1e6: 2701 movs r7, #1 + e1e8: b91a cbnz r2, e1f2 + e1ea: 4617 mov r7, r2 + e1ec: 2101 movs r1, #1 + e1ee: f883 1129 strb.w r1, [r3, #297] ; 0x129 + e1f2: f8d3 3118 ldr.w r3, [r3, #280] ; 0x118 + e1f6: b103 cbz r3, e1fa + e1f8: 4798 blx r3 + e1fa: b147 cbz r7, e20e + e1fc: f240 330c movw r3, #780 ; 0x30c + e200: f2c1 0300 movt r3, #4096 ; 0x1000 + e204: 681b ldr r3, [r3, #0] + e206: 075b lsls r3, r3, #29 + e208: d41a bmi.n e240 + e20a: 2001 movs r0, #1 + e20c: bdf8 pop {r3, r4, r5, r6, r7, pc} + e20e: f240 3754 movw r7, #852 ; 0x354 + e212: 4630 mov r0, r6 + e214: 4629 mov r1, r5 + e216: f7ff f8c1 bl d39c + e21a: 6822 ldr r2, [r4, #0] + e21c: f2c1 0700 movt r7, #4096 ; 0x1000 + e220: f8d2 3114 ldr.w r3, [r2, #276] ; 0x114 + e224: b10b cbz r3, e22a + e226: 4798 blx r3 + e228: 683a ldr r2, [r7, #0] + e22a: f8d2 3118 ldr.w r3, [r2, #280] ; 0x118 + e22e: 2400 movs r4, #0 + e230: f882 4129 strb.w r4, [r2, #297] ; 0x129 + e234: b113 cbz r3, e23c + e236: 4798 blx r3 + e238: 4620 mov r0, r4 + e23a: bdf8 pop {r3, r4, r5, r6, r7, pc} + e23c: 4618 mov r0, r3 + e23e: bdf8 pop {r3, r4, r5, r6, r7, pc} + e240: f642 702c movw r0, #12076 ; 0x2f2c + e244: f24f 339d movw r3, #62365 ; 0xf39d + e248: f2c0 0004 movt r0, #4 + e24c: f2c0 0300 movt r3, #0 + e250: 4798 blx r3 + e252: 2001 movs r0, #1 + e254: bdf8 pop {r3, r4, r5, r6, r7, pc} + e256: bf00 nop + +0000e258 : + e258: f240 3214 movw r2, #788 ; 0x314 + e25c: f2c1 0200 movt r2, #4096 ; 0x1000 + e260: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + e264: 6813 ldr r3, [r2, #0] + e266: b085 sub sp, #20 + e268: 005b lsls r3, r3, #1 + e26a: 4683 mov fp, r0 + e26c: fa5f fa81 uxtb.w sl, r1 + e270: f100 80b4 bmi.w e3dc + e274: fa4f fa8a sxtb.w sl, sl + e278: f1ba 0f00 cmp.w sl, #0 + e27c: dd65 ble.n e34a + e27e: f240 3314 movw r3, #788 ; 0x314 + e282: f2c1 0300 movt r3, #4096 ; 0x1000 + e286: 9303 str r3, [sp, #12] + e288: f24f 339d movw r3, #62365 ; 0xf39d + e28c: f04f 0800 mov.w r8, #0 + e290: f2c0 0300 movt r3, #0 + e294: 4689 mov r9, r1 + e296: 4647 mov r7, r8 + e298: 9302 str r3, [sp, #8] + e29a: 6811 ldr r1, [r2, #0] + e29c: f011 4080 ands.w r0, r1, #1073741824 ; 0x40000000 + e2a0: f040 80aa bne.w e3f8 + e2a4: f107 0310 add.w r3, r7, #16 + e2a8: 4553 cmp r3, sl + e2aa: da51 bge.n e350 + e2ac: 2600 movs r6, #0 + e2ae: 2510 movs r5, #16 + e2b0: 2400 movs r4, #0 + e2b2: f001 4380 and.w r3, r1, #1073741824 ; 0x40000000 + e2b6: eb0b 0c07 add.w ip, fp, r7 + e2ba: 4618 mov r0, r3 + e2bc: 2b00 cmp r3, #0 + e2be: d14e bne.n e35e + e2c0: 3401 adds r4, #1 + e2c2: fa4f fe84 sxtb.w lr, r4 + e2c6: 4575 cmp r5, lr + e2c8: dcf7 bgt.n e2ba + e2ca: 2e00 cmp r6, #0 + e2cc: dd0b ble.n e2e6 + e2ce: 2400 movs r4, #0 + e2d0: f001 4380 and.w r3, r1, #1073741824 ; 0x40000000 + e2d4: 4618 mov r0, r3 + e2d6: 2b00 cmp r3, #0 + e2d8: d153 bne.n e382 + e2da: 3401 adds r4, #1 + e2dc: b2e4 uxtb r4, r4 + e2de: fa4f fe84 sxtb.w lr, r4 + e2e2: 45b6 cmp lr, r6 + e2e4: dbf6 blt.n e2d4 + e2e6: 2800 cmp r0, #0 + e2e8: d163 bne.n e3b2 + e2ea: 2d00 cmp r5, #0 + e2ec: dd1f ble.n e32e + e2ee: f001 4380 and.w r3, r1, #1073741824 ; 0x40000000 + e2f2: 445f add r7, fp + e2f4: 2400 movs r4, #0 + e2f6: 4616 mov r6, r2 + e2f8: e005 b.n e306 + e2fa: 2b00 cmp r3, #0 + e2fc: d14e bne.n e39c + e2fe: 3401 adds r4, #1 + e300: b261 sxtb r1, r4 + e302: 428d cmp r5, r1 + e304: dd12 ble.n e32c + e306: 5d39 ldrb r1, [r7, r4] + e308: f1a1 0020 sub.w r0, r1, #32 + e30c: 285e cmp r0, #94 ; 0x5e + e30e: 4618 mov r0, r3 + e310: d9f3 bls.n e2fa + e312: 2b00 cmp r3, #0 + e314: d0f3 beq.n e2fe + e316: f642 70c0 movw r0, #12224 ; 0x2fc0 + e31a: 9b02 ldr r3, [sp, #8] + e31c: f2c0 0004 movt r0, #4 + e320: 4798 blx r3 + e322: 6833 ldr r3, [r6, #0] + e324: f003 4380 and.w r3, r3, #1073741824 ; 0x40000000 + e328: 4618 mov r0, r3 + e32a: e7e8 b.n e2fe + e32c: 4632 mov r2, r6 + e32e: 2800 cmp r0, #0 + e330: d14b bne.n e3ca + e332: f108 0810 add.w r8, r8, #16 + e336: fa5f f888 uxtb.w r8, r8 + e33a: fa4f f788 sxtb.w r7, r8 + e33e: f1a9 0910 sub.w r9, r9, #16 + e342: 45ba cmp sl, r7 + e344: fa5f f989 uxtb.w r9, r9 + e348: dca7 bgt.n e29a + e34a: b005 add sp, #20 + e34c: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + e350: fa4f f589 sxtb.w r5, r9 + e354: 2d00 cmp r5, #0 + e356: f1c5 0610 rsb r6, r5, #16 + e35a: dca9 bgt.n e2b0 + e35c: e7b5 b.n e2ca + e35e: f642 70a8 movw r0, #12200 ; 0x2fa8 + e362: f81c 1004 ldrb.w r1, [ip, r4] + e366: 9b02 ldr r3, [sp, #8] + e368: e88d 1004 stmia.w sp, {r2, ip} + e36c: f2c0 0004 movt r0, #4 + e370: 4798 blx r3 + e372: 9a00 ldr r2, [sp, #0] + e374: f8dd c004 ldr.w ip, [sp, #4] + e378: 6811 ldr r1, [r2, #0] + e37a: f001 4380 and.w r3, r1, #1073741824 ; 0x40000000 + e37e: 4618 mov r0, r3 + e380: e79e b.n e2c0 + e382: f642 70b0 movw r0, #12208 ; 0x2fb0 + e386: 9200 str r2, [sp, #0] + e388: 9b02 ldr r3, [sp, #8] + e38a: f2c0 0004 movt r0, #4 + e38e: 4798 blx r3 + e390: 9a00 ldr r2, [sp, #0] + e392: 6811 ldr r1, [r2, #0] + e394: f001 4380 and.w r3, r1, #1073741824 ; 0x40000000 + e398: 4618 mov r0, r3 + e39a: e79e b.n e2da + e39c: f642 70bc movw r0, #12220 ; 0x2fbc + e3a0: 9b02 ldr r3, [sp, #8] + e3a2: f2c0 0004 movt r0, #4 + e3a6: 4798 blx r3 + e3a8: 6833 ldr r3, [r6, #0] + e3aa: f003 4380 and.w r3, r3, #1073741824 ; 0x40000000 + e3ae: 4618 mov r0, r3 + e3b0: e7a5 b.n e2fe + e3b2: f642 70b4 movw r0, #12212 ; 0x2fb4 + e3b6: 9200 str r2, [sp, #0] + e3b8: f2c0 0004 movt r0, #4 + e3bc: 9b02 ldr r3, [sp, #8] + e3be: 4798 blx r3 + e3c0: 9a00 ldr r2, [sp, #0] + e3c2: 6811 ldr r1, [r2, #0] + e3c4: f001 4080 and.w r0, r1, #1073741824 ; 0x40000000 + e3c8: e78f b.n e2ea + e3ca: f642 70c4 movw r0, #12228 ; 0x2fc4 + e3ce: 9200 str r2, [sp, #0] + e3d0: f2c0 0004 movt r0, #4 + e3d4: 9b02 ldr r3, [sp, #8] + e3d6: 4798 blx r3 + e3d8: 9a00 ldr r2, [sp, #0] + e3da: e7aa b.n e332 + e3dc: f642 7060 movw r0, #12128 ; 0x2f60 + e3e0: f24f 339d movw r3, #62365 ; 0xf39d + e3e4: 9101 str r1, [sp, #4] + e3e6: 9200 str r2, [sp, #0] + e3e8: f2c0 0004 movt r0, #4 + e3ec: f2c0 0300 movt r3, #0 + e3f0: 4798 blx r3 + e3f2: 9a00 ldr r2, [sp, #0] + e3f4: 9901 ldr r1, [sp, #4] + e3f6: e73d b.n e274 + e3f8: f642 70a0 movw r0, #12192 ; 0x2fa0 + e3fc: eb0b 0107 add.w r1, fp, r7 + e400: 9200 str r2, [sp, #0] + e402: 9b02 ldr r3, [sp, #8] + e404: f2c0 0004 movt r0, #4 + e408: 4798 blx r3 + e40a: 9b03 ldr r3, [sp, #12] + e40c: 9a00 ldr r2, [sp, #0] + e40e: 6819 ldr r1, [r3, #0] + e410: f001 4080 and.w r0, r1, #1073741824 ; 0x40000000 + e414: e746 b.n e2a4 + e416: bf00 nop + +0000e418 : + e418: b5f8 push {r3, r4, r5, r6, r7, lr} + e41a: f240 3614 movw r6, #788 ; 0x314 + e41e: f2c1 0600 movt r6, #4096 ; 0x1000 + e422: 6833 ldr r3, [r6, #0] + e424: 005a lsls r2, r3, #1 + e426: d41d bmi.n e464 + e428: f241 64a0 movw r4, #5792 ; 0x16a0 + e42c: f24f 379d movw r7, #62365 ; 0xf39d + e430: f2c0 0403 movt r4, #3 + e434: f2c0 0700 movt r7, #0 + e438: f003 4380 and.w r3, r3, #1073741824 ; 0x40000000 + e43c: f104 0560 add.w r5, r4, #96 ; 0x60 + e440: 68e1 ldr r1, [r4, #12] + e442: 3410 adds r4, #16 + e444: b101 cbz r1, e448 + e446: b923 cbnz r3, e452 + e448: 42ac cmp r4, r5 + e44a: d1f9 bne.n e440 + e44c: b9ab cbnz r3, e47a + e44e: 2001 movs r0, #1 + e450: bdf8 pop {r3, r4, r5, r6, r7, pc} + e452: f243 101c movw r0, #12572 ; 0x311c + e456: f2c0 0004 movt r0, #4 + e45a: 47b8 blx r7 + e45c: 6833 ldr r3, [r6, #0] + e45e: f003 4380 and.w r3, r3, #1073741824 ; 0x40000000 + e462: e7f1 b.n e448 + e464: f243 00e0 movw r0, #12512 ; 0x30e0 + e468: f24f 339d movw r3, #62365 ; 0xf39d + e46c: f2c0 0004 movt r0, #4 + e470: f2c0 0300 movt r3, #0 + e474: 4798 blx r3 + e476: 6833 ldr r3, [r6, #0] + e478: e7d6 b.n e428 + e47a: f243 1024 movw r0, #12580 ; 0x3124 + e47e: f24f 339d movw r3, #62365 ; 0xf39d + e482: f2c0 0004 movt r0, #4 + e486: f2c0 0300 movt r3, #0 + e48a: 4798 blx r3 + e48c: e7df b.n e44e + e48e: bf00 nop + +0000e490 : + e490: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} + e494: f64e 0801 movw r8, #59393 ; 0xe801 + e498: 460e mov r6, r1 + e49a: 4681 mov r9, r0 + e49c: f2c0 0800 movt r8, #0 + e4a0: 6808 ldr r0, [r1, #0] + e4a2: 2210 movs r2, #16 + e4a4: 2100 movs r1, #0 + e4a6: 47c0 blx r8 + e4a8: 0781 lsls r1, r0, #30 + e4aa: 4604 mov r4, r0 + e4ac: d002 beq.n e4b4 + e4ae: 3401 adds r4, #1 + e4b0: 07a2 lsls r2, r4, #30 + e4b2: d1fc bne.n e4ae + e4b4: f1b9 0901 subs.w r9, r9, #1 + e4b8: d018 beq.n e4ec + e4ba: f240 3b14 movw fp, #788 ; 0x314 + e4be: f24f 3a9d movw sl, #62365 ; 0xf39d + e4c2: f2c1 0b00 movt fp, #4096 ; 0x1000 + e4c6: f2c0 0a00 movt sl, #0 + e4ca: 2500 movs r5, #0 + e4cc: f856 0f04 ldr.w r0, [r6, #4]! + e4d0: 2100 movs r1, #0 + e4d2: 2210 movs r2, #16 + e4d4: 47c0 blx r8 + e4d6: f8db 3000 ldr.w r3, [fp] + e4da: 4607 mov r7, r0 + e4dc: 005b lsls r3, r3, #1 + e4de: f105 0501 add.w r5, r5, #1 + e4e2: d406 bmi.n e4f2 + e4e4: 454d cmp r5, r9 + e4e6: f844 7b04 str.w r7, [r4], #4 + e4ea: d3ef bcc.n e4cc + e4ec: 2000 movs r0, #0 + e4ee: e8bd 8ff8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, pc} + e4f2: f243 1060 movw r0, #12640 ; 0x3160 + e4f6: 4621 mov r1, r4 + e4f8: 463a mov r2, r7 + e4fa: f2c0 0004 movt r0, #4 + e4fe: 47d0 blx sl + e500: e7f0 b.n e4e4 + e502: bf00 nop + +0000e504 : + e504: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + e508: 4604 mov r4, r0 + e50a: b086 sub sp, #24 + e50c: b950 cbnz r0, e524 + e50e: f240 3314 movw r3, #788 ; 0x314 + e512: f2c1 0300 movt r3, #4096 ; 0x1000 + e516: 6818 ldr r0, [r3, #0] + e518: f010 4080 ands.w r0, r0, #1073741824 ; 0x40000000 + e51c: d143 bne.n e5a6 + e51e: b006 add sp, #24 + e520: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + e524: 680f ldr r7, [r1, #0] + e526: 460d mov r5, r1 + e528: b347 cbz r7, e57c + e52a: f64e 0601 movw r6, #59393 ; 0xe801 + e52e: 4638 mov r0, r7 + e530: f2c0 0600 movt r6, #0 + e534: 2100 movs r1, #0 + e536: 2210 movs r2, #16 + e538: 47b0 blx r6 + e53a: 4604 mov r4, r0 + e53c: 6868 ldr r0, [r5, #4] + e53e: b380 cbz r0, e5a2 + e540: 2100 movs r1, #0 + e542: 220a movs r2, #10 + e544: 47b0 blx r6 + e546: 4607 mov r7, r0 + e548: e000 b.n e54c + e54a: 3401 adds r4, #1 + e54c: 07e2 lsls r2, r4, #31 + e54e: d4fc bmi.n e54a + e550: b187 cbz r7, e574 + e552: f240 3614 movw r6, #788 ; 0x314 + e556: f24f 389d movw r8, #62365 ; 0xf39d + e55a: f2c1 0600 movt r6, #4096 ; 0x1000 + e55e: f2c0 0800 movt r8, #0 + e562: 2500 movs r5, #0 + e564: 6833 ldr r3, [r6, #0] + e566: 3504 adds r5, #4 + e568: 005b lsls r3, r3, #1 + e56a: d427 bmi.n e5bc + e56c: 42bd cmp r5, r7 + e56e: f104 0410 add.w r4, r4, #16 + e572: d3f7 bcc.n e564 + e574: 2001 movs r0, #1 + e576: b006 add sp, #24 + e578: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + e57c: f240 3314 movw r3, #788 ; 0x314 + e580: f2c1 0300 movt r3, #4096 ; 0x1000 + e584: 6818 ldr r0, [r3, #0] + e586: f010 4080 ands.w r0, r0, #1073741824 ; 0x40000000 + e58a: d0c8 beq.n e51e + e58c: f243 107c movw r0, #12668 ; 0x317c + e590: f24f 339d movw r3, #62365 ; 0xf39d + e594: f2c0 0004 movt r0, #4 + e598: f2c0 0300 movt r3, #0 + e59c: 4798 blx r3 + e59e: 4638 mov r0, r7 + e5a0: e7bd b.n e51e + e5a2: 2701 movs r7, #1 + e5a4: e7d2 b.n e54c + e5a6: f243 107c movw r0, #12668 ; 0x317c + e5aa: f24f 339d movw r3, #62365 ; 0xf39d + e5ae: f2c0 0004 movt r0, #4 + e5b2: f2c0 0300 movt r3, #0 + e5b6: 4798 blx r3 + e5b8: 4620 mov r0, r4 + e5ba: e7b0 b.n e51e + e5bc: f243 1098 movw r0, #12696 ; 0x3198 + e5c0: 88a1 ldrh r1, [r4, #4] + e5c2: 8822 ldrh r2, [r4, #0] + e5c4: 8863 ldrh r3, [r4, #2] + e5c6: 9100 str r1, [sp, #0] + e5c8: 88e1 ldrh r1, [r4, #6] + e5ca: f2c0 0004 movt r0, #4 + e5ce: 9101 str r1, [sp, #4] + e5d0: 8921 ldrh r1, [r4, #8] + e5d2: 9102 str r1, [sp, #8] + e5d4: 8961 ldrh r1, [r4, #10] + e5d6: 9103 str r1, [sp, #12] + e5d8: f8b4 e00c ldrh.w lr, [r4, #12] + e5dc: 4621 mov r1, r4 + e5de: f8cd e010 str.w lr, [sp, #16] + e5e2: f8b4 e00e ldrh.w lr, [r4, #14] + e5e6: f8cd e014 str.w lr, [sp, #20] + e5ea: 47c0 blx r8 + e5ec: e7be b.n e56c + e5ee: bf00 nop + +0000e5f0 : + e5f0: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} + e5f4: 4604 mov r4, r0 + e5f6: b948 cbnz r0, e60c + e5f8: f240 3314 movw r3, #788 ; 0x314 + e5fc: f2c1 0300 movt r3, #4096 ; 0x1000 + e600: 6818 ldr r0, [r3, #0] + e602: f010 4080 ands.w r0, r0, #1073741824 ; 0x40000000 + e606: d143 bne.n e690 + e608: e8bd 83f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} + e60c: 680f ldr r7, [r1, #0] + e60e: 460d mov r5, r1 + e610: b347 cbz r7, e664 + e612: f64e 0601 movw r6, #59393 ; 0xe801 + e616: 4638 mov r0, r7 + e618: f2c0 0600 movt r6, #0 + e61c: 2100 movs r1, #0 + e61e: 2210 movs r2, #16 + e620: 47b0 blx r6 + e622: 4604 mov r4, r0 + e624: 6868 ldr r0, [r5, #4] + e626: b388 cbz r0, e68c + e628: 2100 movs r1, #0 + e62a: 220a movs r2, #10 + e62c: 47b0 blx r6 + e62e: 4607 mov r7, r0 + e630: e000 b.n e634 + e632: 3401 adds r4, #1 + e634: 07a5 lsls r5, r4, #30 + e636: d1fc bne.n e632 + e638: b18f cbz r7, e65e + e63a: f240 3614 movw r6, #788 ; 0x314 + e63e: f24f 389d movw r8, #62365 ; 0xf39d + e642: f2c1 0600 movt r6, #4096 ; 0x1000 + e646: f2c0 0800 movt r8, #0 + e64a: 46b1 mov r9, r6 + e64c: 2500 movs r5, #0 + e64e: 6833 ldr r3, [r6, #0] + e650: 3504 adds r5, #4 + e652: 0058 lsls r0, r3, #1 + e654: d428 bmi.n e6a8 + e656: 42bd cmp r5, r7 + e658: f104 0410 add.w r4, r4, #16 + e65c: d3f7 bcc.n e64e + e65e: 2001 movs r0, #1 + e660: e8bd 83f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} + e664: f240 3314 movw r3, #788 ; 0x314 + e668: f2c1 0300 movt r3, #4096 ; 0x1000 + e66c: 6818 ldr r0, [r3, #0] + e66e: f010 4080 ands.w r0, r0, #1073741824 ; 0x40000000 + e672: d0c9 beq.n e608 + e674: f243 107c movw r0, #12668 ; 0x317c + e678: f24f 339d movw r3, #62365 ; 0xf39d + e67c: f2c0 0004 movt r0, #4 + e680: f2c0 0300 movt r3, #0 + e684: 4798 blx r3 + e686: 4638 mov r0, r7 + e688: e8bd 83f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} + e68c: 2701 movs r7, #1 + e68e: e7d1 b.n e634 + e690: f243 107c movw r0, #12668 ; 0x317c + e694: f24f 339d movw r3, #62365 ; 0xf39d + e698: f2c0 0004 movt r0, #4 + e69c: f2c0 0300 movt r3, #0 + e6a0: 4798 blx r3 + e6a2: 4620 mov r0, r4 + e6a4: e8bd 83f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} + e6a8: f243 10d4 movw r0, #12756 ; 0x31d4 + e6ac: 4621 mov r1, r4 + e6ae: f2c0 0004 movt r0, #4 + e6b2: 6822 ldr r2, [r4, #0] + e6b4: 47c0 blx r8 + e6b6: f8d9 3000 ldr.w r3, [r9] + e6ba: 0059 lsls r1, r3, #1 + e6bc: d5cb bpl.n e656 + e6be: f243 10e4 movw r0, #12772 ; 0x31e4 + e6c2: 6861 ldr r1, [r4, #4] + e6c4: f2c0 0004 movt r0, #4 + e6c8: 47c0 blx r8 + e6ca: f8d9 3000 ldr.w r3, [r9] + e6ce: 005a lsls r2, r3, #1 + e6d0: d5c1 bpl.n e656 + e6d2: f243 10e4 movw r0, #12772 ; 0x31e4 + e6d6: 68a1 ldr r1, [r4, #8] + e6d8: f2c0 0004 movt r0, #4 + e6dc: 47c0 blx r8 + e6de: f8d9 3000 ldr.w r3, [r9] + e6e2: 005b lsls r3, r3, #1 + e6e4: d5b7 bpl.n e656 + e6e6: f243 10f0 movw r0, #12784 ; 0x31f0 + e6ea: 68e1 ldr r1, [r4, #12] + e6ec: f2c0 0004 movt r0, #4 + e6f0: 47c0 blx r8 + e6f2: e7b0 b.n e656 + +0000e6f4 : + e6f4: b570 push {r4, r5, r6, lr} + e6f6: 4604 mov r4, r0 + e6f8: b940 cbnz r0, e70c + e6fa: f240 3314 movw r3, #788 ; 0x314 + e6fe: f2c1 0300 movt r3, #4096 ; 0x1000 + e702: 681b ldr r3, [r3, #0] + e704: f013 4080 ands.w r0, r3, #1073741824 ; 0x40000000 + e708: d116 bne.n e738 + e70a: bd70 pop {r4, r5, r6, pc} + e70c: f64e 0401 movw r4, #59393 ; 0xe801 + e710: 460d mov r5, r1 + e712: 6808 ldr r0, [r1, #0] + e714: f2c0 0400 movt r4, #0 + e718: 2100 movs r1, #0 + e71a: 2210 movs r2, #16 + e71c: 47a0 blx r4 + e71e: 4606 mov r6, r0 + e720: 6868 ldr r0, [r5, #4] + e722: 2110 movs r1, #16 + e724: b118 cbz r0, e72e + e726: 2100 movs r1, #0 + e728: 220a movs r2, #10 + e72a: 47a0 blx r4 + e72c: b2c1 uxtb r1, r0 + e72e: 4630 mov r0, r6 + e730: f7ff fd92 bl e258 + e734: 2001 movs r0, #1 + e736: bd70 pop {r4, r5, r6, pc} + e738: f243 107c movw r0, #12668 ; 0x317c + e73c: f24f 339d movw r3, #62365 ; 0xf39d + e740: f2c0 0004 movt r0, #4 + e744: f2c0 0300 movt r3, #0 + e748: 4798 blx r3 + e74a: 4620 mov r0, r4 + e74c: bd70 pop {r4, r5, r6, pc} + e74e: bf00 nop + +0000e750 : + e750: b530 push {r4, r5, lr} + e752: 2801 cmp r0, #1 + e754: b083 sub sp, #12 + e756: d914 bls.n e782 + e758: f64e 0401 movw r4, #59393 ; 0xe801 + e75c: 460d mov r5, r1 + e75e: 6808 ldr r0, [r1, #0] + e760: f2c0 0400 movt r4, #0 + e764: 2100 movs r1, #0 + e766: 220a movs r2, #10 + e768: 47a0 blx r4 + e76a: 2100 movs r1, #0 + e76c: 9000 str r0, [sp, #0] + e76e: 220a movs r2, #10 + e770: 6868 ldr r0, [r5, #4] + e772: 47a0 blx r4 + e774: 9001 str r0, [sp, #4] + e776: 4668 mov r0, sp + e778: f7f4 fd7e bl 3278 + e77c: 2001 movs r0, #1 + e77e: b003 add sp, #12 + e780: bd30 pop {r4, r5, pc} + e782: f240 3314 movw r3, #788 ; 0x314 + e786: f2c1 0300 movt r3, #4096 ; 0x1000 + e78a: 6818 ldr r0, [r3, #0] + e78c: f010 4080 ands.w r0, r0, #1073741824 ; 0x40000000 + e790: d0f5 beq.n e77e + e792: f243 107c movw r0, #12668 ; 0x317c + e796: f24f 339d movw r3, #62365 ; 0xf39d + e79a: f2c0 0004 movt r0, #4 + e79e: f2c0 0300 movt r3, #0 + e7a2: 4798 blx r3 + e7a4: 2000 movs r0, #0 + e7a6: e7ea b.n e77e + +0000e7a8 : + e7a8: 2006 movs r0, #6 + e7aa: 4770 bx lr + +0000e7ac : + e7ac: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + e7b0: f64e 0601 movw r6, #59393 ; 0xe801 + e7b4: 1e47 subs r7, r0, #1 + e7b6: 4688 mov r8, r1 + e7b8: 6808 ldr r0, [r1, #0] + e7ba: f2c0 0600 movt r6, #0 + e7be: 2100 movs r1, #0 + e7c0: 2210 movs r2, #16 + e7c2: 47b0 blx r6 + e7c4: 2f00 cmp r7, #0 + e7c6: dd0d ble.n e7e4 + e7c8: 4605 mov r5, r0 + e7ca: 2300 movs r3, #0 + e7cc: 1c5c adds r4, r3, #1 + e7ce: f858 0024 ldr.w r0, [r8, r4, lsl #2] + e7d2: 2100 movs r1, #0 + e7d4: 2210 movs r2, #16 + e7d6: 47b0 blx r6 + e7d8: b2e3 uxtb r3, r4 + e7da: b2c0 uxtb r0, r0 + e7dc: 42bb cmp r3, r7 + e7de: f805 0b01 strb.w r0, [r5], #1 + e7e2: dbf3 blt.n e7cc + e7e4: 2000 movs r0, #0 + e7e6: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + e7ea: bf00 nop + +0000e7ec : + e7ec: f1a0 0309 sub.w r3, r0, #9 + e7f0: 2820 cmp r0, #32 + e7f2: bf18 it ne + e7f4: 2b04 cmpne r3, #4 + e7f6: bf94 ite ls + e7f8: 2001 movls r0, #1 + e7fa: 2000 movhi r0, #0 + e7fc: 4770 bx lr + e7fe: bf00 nop + +0000e800 : + e800: b430 push {r4, r5} + e802: 7803 ldrb r3, [r0, #0] + e804: f1a3 0409 sub.w r4, r3, #9 + e808: 2b20 cmp r3, #32 + e80a: bf18 it ne + e80c: 2c04 cmpne r4, #4 + e80e: d807 bhi.n e820 + e810: f810 3f01 ldrb.w r3, [r0, #1]! + e814: f1a3 0409 sub.w r4, r3, #9 + e818: 2b20 cmp r3, #32 + e81a: bf18 it ne + e81c: 2c04 cmpne r4, #4 + e81e: d9f7 bls.n e810 + e820: 2b2b cmp r3, #43 ; 0x2b + e822: bf08 it eq + e824: 3001 addeq r0, #1 + e826: 2a10 cmp r2, #16 + e828: 7803 ldrb r3, [r0, #0] + e82a: d02c beq.n e886 + e82c: b91a cbnz r2, e836 + e82e: 2b30 cmp r3, #48 ; 0x30 + e830: bf18 it ne + e832: 220a movne r2, #10 + e834: d034 beq.n e8a0 + e836: 2b00 cmp r3, #0 + e838: d037 beq.n e8aa + e83a: 2400 movs r4, #0 + e83c: e013 b.n e866 + e83e: 2b40 cmp r3, #64 ; 0x40 + e840: f1a3 0537 sub.w r5, r3, #55 ; 0x37 + e844: d813 bhi.n e86e + e846: 2b39 cmp r3, #57 ; 0x39 + e848: f1a3 0330 sub.w r3, r3, #48 ; 0x30 + e84c: bf94 ite ls + e84e: b2db uxtbls r3, r3 + e850: 23ff movhi r3, #255 ; 0xff + e852: 429a cmp r2, r3 + e854: d90e bls.n e874 + e856: fb02 f504 mul.w r5, r2, r4 + e85a: 42a5 cmp r5, r4 + e85c: d30f bcc.n e87e + e85e: 195c adds r4, r3, r5 + e860: f810 3f01 ldrb.w r3, [r0, #1]! + e864: b133 cbz r3, e874 + e866: 2b60 cmp r3, #96 ; 0x60 + e868: f1a3 0557 sub.w r5, r3, #87 ; 0x57 + e86c: d9e7 bls.n e83e + e86e: b2eb uxtb r3, r5 + e870: 429a cmp r2, r3 + e872: d8f0 bhi.n e856 + e874: b1b1 cbz r1, e8a4 + e876: 6008 str r0, [r1, #0] + e878: 4620 mov r0, r4 + e87a: bc30 pop {r4, r5} + e87c: 4770 bx lr + e87e: f04f 30ff mov.w r0, #4294967295 + e882: bc30 pop {r4, r5} + e884: 4770 bx lr + e886: 2b30 cmp r3, #48 ; 0x30 + e888: d1d5 bne.n e836 + e88a: 7843 ldrb r3, [r0, #1] + e88c: f003 03df and.w r3, r3, #223 ; 0xdf + e890: 2b58 cmp r3, #88 ; 0x58 + e892: bf18 it ne + e894: 2330 movne r3, #48 ; 0x30 + e896: d1d0 bne.n e83a + e898: 7883 ldrb r3, [r0, #2] + e89a: 2210 movs r2, #16 + e89c: 3002 adds r0, #2 + e89e: e7ca b.n e836 + e8a0: 2208 movs r2, #8 + e8a2: e7f2 b.n e88a + e8a4: 4620 mov r0, r4 + e8a6: bc30 pop {r4, r5} + e8a8: 4770 bx lr + e8aa: 461c mov r4, r3 + e8ac: e7e2 b.n e874 + e8ae: bf00 nop + +0000e8b0 : + e8b0: b141 cbz r1, e8c4 + e8b2: b410 push {r4} + e8b4: 2300 movs r3, #0 + e8b6: 54c2 strb r2, [r0, r3] + e8b8: 3301 adds r3, #1 + e8ba: b2dc uxtb r4, r3 + e8bc: 42a1 cmp r1, r4 + e8be: d8fa bhi.n e8b6 + e8c0: f85d 4b04 ldr.w r4, [sp], #4 + e8c4: 4770 bx lr + e8c6: bf00 nop + +0000e8c8 : + e8c8: 7803 ldrb r3, [r0, #0] + e8ca: 2200 movs r2, #0 + e8cc: b153 cbz r3, e8e4 + e8ce: 2b20 cmp r3, #32 + e8d0: d00e beq.n e8f0 + e8d2: 3201 adds r2, #1 + e8d4: b292 uxth r2, r2 + e8d6: f810 3f01 ldrb.w r3, [r0, #1]! + e8da: f013 0fdf tst.w r3, #223 ; 0xdf + e8de: d1fa bne.n e8d6 + e8e0: 2b00 cmp r3, #0 + e8e2: d1f4 bne.n e8ce + e8e4: 2009 movs r0, #9 + e8e6: 4290 cmp r0, r2 + e8e8: bf28 it cs + e8ea: 4610 movcs r0, r2 + e8ec: b2c0 uxtb r0, r0 + e8ee: 4770 bx lr + e8f0: 7843 ldrb r3, [r0, #1] + e8f2: 3001 adds r0, #1 + e8f4: e7ea b.n e8cc + e8f6: bf00 nop + +0000e8f8 : + e8f8: 4b16 ldr r3, [pc, #88] ; (e954 ) + e8fa: 2100 movs r1, #0 + e8fc: f103 0228 add.w r2, r3, #40 ; 0x28 + e900: f803 1f01 strb.w r1, [r3, #1]! + e904: 4293 cmp r3, r2 + e906: d1fb bne.n e900 + e908: 4a13 ldr r2, [pc, #76] ; (e958 ) + e90a: b410 push {r4} + e90c: f102 0128 add.w r1, r2, #40 ; 0x28 + e910: 2400 movs r4, #0 + e912: 7803 ldrb r3, [r0, #0] + e914: b1b3 cbz r3, e944 + e916: f842 0f04 str.w r0, [r2, #4]! + e91a: 7803 ldrb r3, [r0, #0] + e91c: f013 0fdf tst.w r3, #223 ; 0xdf + e920: d004 beq.n e92c + e922: f810 3f01 ldrb.w r3, [r0, #1]! + e926: f013 0fdf tst.w r3, #223 ; 0xdf + e92a: d1fa bne.n e922 + e92c: 7843 ldrb r3, [r0, #1] + e92e: 7004 strb r4, [r0, #0] + e930: 2b20 cmp r3, #32 + e932: f100 0001 add.w r0, r0, #1 + e936: d103 bne.n e940 + e938: f810 3f01 ldrb.w r3, [r0, #1]! + e93c: 2b20 cmp r3, #32 + e93e: d0fb beq.n e938 + e940: 428a cmp r2, r1 + e942: d1e6 bne.n e912 + e944: f240 60ac movw r0, #1708 ; 0x6ac + e948: f85d 4b04 ldr.w r4, [sp], #4 + e94c: f2c1 0000 movt r0, #4096 ; 0x1000 + e950: 4770 bx lr + e952: bf00 nop + e954: 100006ab .word 0x100006ab + e958: 100006a8 .word 0x100006a8 + +0000e95c : + e95c: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + e960: f8d0 a008 ldr.w sl, [r0, #8] + e964: b083 sub sp, #12 + e966: f10a 0401 add.w r4, sl, #1 + e96a: 4607 mov r7, r0 + e96c: 6905 ldr r5, [r0, #16] + e96e: 4620 mov r0, r4 + e970: f7ff ffaa bl e8c8 + e974: 9001 str r0, [sp, #4] + e976: 4620 mov r0, r4 + e978: f7ff ffbe bl e8f8 + e97c: 9b01 ldr r3, [sp, #4] + e97e: 697f ldr r7, [r7, #20] + e980: b953 cbnz r3, e998 + e982: 2200 movs r2, #0 + e984: 4613 mov r3, r2 + e986: f88a 2000 strb.w r2, [sl] + e98a: 54e2 strb r2, [r4, r3] + e98c: 3301 adds r3, #1 + e98e: 2b7f cmp r3, #127 ; 0x7f + e990: d1fb bne.n e98a + e992: b003 add sp, #12 + e994: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + e998: f24f 7349 movw r3, #63305 ; 0xf749 + e99c: 4606 mov r6, r0 + e99e: f2c0 0300 movt r3, #0 + e9a2: 6800 ldr r0, [r0, #0] + e9a4: 4798 blx r3 + e9a6: 2f00 cmp r7, #0 + e9a8: d0eb beq.n e982 + e9aa: f24f 7819 movw r8, #63257 ; 0xf719 + e9ae: f04f 0900 mov.w r9, #0 + e9b2: f2c0 0800 movt r8, #0 + e9b6: 46cb mov fp, r9 + e9b8: e002 b.n e9c0 + e9ba: 455f cmp r7, fp + e9bc: 46d9 mov r9, fp + e9be: d9e0 bls.n e982 + e9c0: ea4f 1909 mov.w r9, r9, lsl #4 + e9c4: f855 1009 ldr.w r1, [r5, r9] + e9c8: 6830 ldr r0, [r6, #0] + e9ca: 47c0 blx r8 + e9cc: f10b 0301 add.w r3, fp, #1 + e9d0: 44a9 add r9, r5 + e9d2: 4602 mov r2, r0 + e9d4: fa5f fb83 uxtb.w fp, r3 + e9d8: 2800 cmp r0, #0 + e9da: d1ee bne.n e9ba + e9dc: 9b01 ldr r3, [sp, #4] + e9de: 1d31 adds r1, r6, #4 + e9e0: 1e58 subs r0, r3, #1 + e9e2: b280 uxth r0, r0 + e9e4: f8d9 3008 ldr.w r3, [r9, #8] + e9e8: 9200 str r2, [sp, #0] + e9ea: 4798 blx r3 + e9ec: 6833 ldr r3, [r6, #0] + e9ee: 9a00 ldr r2, [sp, #0] + e9f0: 701a strb r2, [r3, #0] + e9f2: 705a strb r2, [r3, #1] + e9f4: 709a strb r2, [r3, #2] + e9f6: 70da strb r2, [r3, #3] + e9f8: e7c3 b.n e982 + e9fa: bf00 nop + +0000e9fc : + e9fc: b5f8 push {r3, r4, r5, r6, r7, lr} + e9fe: 4605 mov r5, r0 + ea00: b138 cbz r0, ea12 + ea02: 460e mov r6, r1 + ea04: 4617 mov r7, r2 + ea06: 2400 movs r4, #0 + ea08: b926 cbnz r6, ea14 + ea0a: 3401 adds r4, #1 + ea0c: b2e4 uxtb r4, r4 + ea0e: 42ac cmp r4, r5 + ea10: d1fa bne.n ea08 + ea12: bdf8 pop {r3, r4, r5, r6, r7, pc} + ea14: f243 4064 movw r0, #13412 ; 0x3464 + ea18: 2108 movs r1, #8 + ea1a: f2c0 0004 movt r0, #4 + ea1e: 47b8 blx r7 + ea20: f243 4068 movw r0, #13416 ; 0x3468 + ea24: f2c0 0004 movt r0, #4 + ea28: 47b8 blx r7 + ea2a: f243 4064 movw r0, #13412 ; 0x3464 + ea2e: 2108 movs r1, #8 + ea30: f2c0 0004 movt r0, #4 + ea34: 47b8 blx r7 + ea36: e7e8 b.n ea0a + +0000ea38 : + ea38: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + ea3c: f24f 6439 movw r4, #63033 ; 0xf639 + ea40: 1c45 adds r5, r0, #1 + ea42: 4606 mov r6, r0 + ea44: f2c0 0400 movt r4, #0 + ea48: 4628 mov r0, r5 + ea4a: 4617 mov r7, r2 + ea4c: 4698 mov r8, r3 + ea4e: 47a0 blx r4 + ea50: f24f 6199 movw r1, #63129 ; 0xf699 + ea54: 4628 mov r0, r5 + ea56: f2c0 0100 movt r1, #0 + ea5a: 4788 blx r1 + ea5c: 7030 strb r0, [r6, #0] + ea5e: b90f cbnz r7, ea64 + ea60: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + ea64: 4628 mov r0, r5 + ea66: 4643 mov r3, r8 + ea68: e8bd 41f0 ldmia.w sp!, {r4, r5, r6, r7, r8, lr} + ea6c: 4718 bx r3 + ea6e: bf00 nop + +0000ea70 : + ea70: 2841 cmp r0, #65 ; 0x41 + ea72: b538 push {r3, r4, r5, lr} + ea74: 460c mov r4, r1 + ea76: 68cd ldr r5, [r1, #12] + ea78: d019 beq.n eaae + ea7a: 2842 cmp r0, #66 ; 0x42 + ea7c: d000 beq.n ea80 + ea7e: bd38 pop {r3, r4, r5, pc} + ea80: 788b ldrb r3, [r1, #2] + ea82: b9fb cbnz r3, eac4 + ea84: 68a3 ldr r3, [r4, #8] + ea86: 2101 movs r1, #1 + ea88: 7818 ldrb r0, [r3, #0] + ea8a: 462a mov r2, r5 + ea8c: f7ff ffb6 bl e9fc + ea90: 78a3 ldrb r3, [r4, #2] + ea92: b14b cbz r3, eaa8 + ea94: 7863 ldrb r3, [r4, #1] + ea96: 69e2 ldr r2, [r4, #28] + ea98: ebc3 11c3 rsb r1, r3, r3, lsl #7 + ea9c: 4411 add r1, r2 + ea9e: 462b mov r3, r5 + eaa0: 68a0 ldr r0, [r4, #8] + eaa2: 2201 movs r2, #1 + eaa4: f7ff ffc8 bl ea38 + eaa8: 2300 movs r3, #0 + eaaa: 61a3 str r3, [r4, #24] + eaac: bd38 pop {r3, r4, r5, pc} + eaae: 698b ldr r3, [r1, #24] + eab0: b92b cbnz r3, eabe + eab2: 788b ldrb r3, [r1, #2] + eab4: b11b cbz r3, eabe + eab6: 7849 ldrb r1, [r1, #1] + eab8: b969 cbnz r1, ead6 + eaba: 3b01 subs r3, #1 + eabc: 7063 strb r3, [r4, #1] + eabe: 68a3 ldr r3, [r4, #8] + eac0: 4611 mov r1, r2 + eac2: e7e1 b.n ea88 + eac4: 784a ldrb r2, [r1, #1] + eac6: 3b01 subs r3, #1 + eac8: 429a cmp r2, r3 + eaca: bf0b itete eq + eacc: 2300 moveq r3, #0 + eace: 3201 addne r2, #1 + ead0: 704b strbeq r3, [r1, #1] + ead2: 704a strbne r2, [r1, #1] + ead4: e7d6 b.n ea84 + ead6: 3901 subs r1, #1 + ead8: 7061 strb r1, [r4, #1] + eada: e7f0 b.n eabe + +0000eadc : + eadc: b5f8 push {r3, r4, r5, r6, r7, lr} + eade: 460c mov r4, r1 + eae0: 6889 ldr r1, [r1, #8] + eae2: 4605 mov r5, r0 + eae4: 780b ldrb r3, [r1, #0] + eae6: 68e6 ldr r6, [r4, #12] + eae8: 2b7d cmp r3, #125 ; 0x7d + eaea: d903 bls.n eaf4 + eaec: 2b7e cmp r3, #126 ; 0x7e + eaee: d03b beq.n eb68 + eaf0: 2000 movs r0, #0 + eaf2: bdf8 pop {r3, r4, r5, r6, r7, pc} + eaf4: 2d0a cmp r5, #10 + eaf6: d01e beq.n eb36 + eaf8: 2d0d cmp r5, #13 + eafa: bf18 it ne + eafc: 2d00 cmpne r5, #0 + eafe: d11c bne.n eb3a + eb00: 2301 movs r3, #1 + eb02: 61a3 str r3, [r4, #24] + eb04: 7808 ldrb r0, [r1, #0] + eb06: 2300 movs r3, #0 + eb08: 4401 add r1, r0 + eb0a: 704b strb r3, [r1, #1] + eb0c: 2a00 cmp r2, #0 + eb0e: d151 bne.n ebb4 + eb10: 68a1 ldr r1, [r4, #8] + eb12: 780b ldrb r3, [r1, #0] + eb14: 2b00 cmp r3, #0 + eb16: d153 bne.n ebc0 + eb18: 2002 movs r0, #2 + eb1a: bdf8 pop {r3, r4, r5, r6, r7, pc} + eb1c: 440b add r3, r1 + eb1e: 2120 movs r1, #32 + eb20: 7059 strb r1, [r3, #1] + eb22: 68a3 ldr r3, [r4, #8] + eb24: 7819 ldrb r1, [r3, #0] + eb26: 3101 adds r1, #1 + eb28: 7019 strb r1, [r3, #0] + eb2a: b122 cbz r2, eb36 + eb2c: f243 4068 movw r0, #13416 ; 0x3468 + eb30: f2c0 0004 movt r0, #4 + eb34: 47b0 blx r6 + eb36: 2001 movs r0, #1 + eb38: bdf8 pop {r3, r4, r5, r6, r7, pc} + eb3a: 2d08 cmp r5, #8 + eb3c: bf18 it ne + eb3e: 2d7f cmpne r5, #127 ; 0x7f + eb40: d02d beq.n eb9e + eb42: 2d09 cmp r5, #9 + eb44: d0ea beq.n eb1c + eb46: b13a cbz r2, eb58 + eb48: f243 4064 movw r0, #13412 ; 0x3464 + eb4c: 4629 mov r1, r5 + eb4e: f2c0 0004 movt r0, #4 + eb52: 47b0 blx r6 + eb54: 68a1 ldr r1, [r4, #8] + eb56: 780b ldrb r3, [r1, #0] + eb58: 440b add r3, r1 + eb5a: 705d strb r5, [r3, #1] + eb5c: 68a3 ldr r3, [r4, #8] + eb5e: 2001 movs r0, #1 + eb60: 781a ldrb r2, [r3, #0] + eb62: 4402 add r2, r0 + eb64: 701a strb r2, [r3, #0] + eb66: bdf8 pop {r3, r4, r5, r6, r7, pc} + eb68: f010 0ff7 tst.w r0, #247 ; 0xf7 + eb6c: bf0c ite eq + eb6e: 2701 moveq r7, #1 + eb70: 2700 movne r7, #0 + eb72: 280d cmp r0, #13 + eb74: bf08 it eq + eb76: f047 0701 orreq.w r7, r7, #1 + eb7a: 2f00 cmp r7, #0 + eb7c: d1ba bne.n eaf4 + eb7e: 287f cmp r0, #127 ; 0x7f + eb80: d0ba beq.n eaf8 + eb82: f243 4070 movw r0, #13424 ; 0x3470 + eb86: f2c0 0004 movt r0, #4 + eb8a: 47b0 blx r6 + eb8c: 68a3 ldr r3, [r4, #8] + eb8e: 781a ldrb r2, [r3, #0] + eb90: 4413 add r3, r2 + eb92: 705f strb r7, [r3, #1] + eb94: 68a0 ldr r0, [r4, #8] + eb96: 3001 adds r0, #1 + eb98: 47b0 blx r6 + eb9a: 2001 movs r0, #1 + eb9c: bdf8 pop {r3, r4, r5, r6, r7, pc} + eb9e: 2b00 cmp r3, #0 + eba0: d0c9 beq.n eb36 + eba2: 3b01 subs r3, #1 + eba4: 2001 movs r0, #1 + eba6: 700b strb r3, [r1, #0] + eba8: 4632 mov r2, r6 + ebaa: 4601 mov r1, r0 + ebac: f7ff ff26 bl e9fc + ebb0: 2001 movs r0, #1 + ebb2: bdf8 pop {r3, r4, r5, r6, r7, pc} + ebb4: f243 406c movw r0, #13420 ; 0x346c + ebb8: f2c0 0004 movt r0, #4 + ebbc: 47b0 blx r6 + ebbe: e7a7 b.n eb10 + ebc0: f24f 6339 movw r3, #63033 ; 0xf639 + ebc4: 7822 ldrb r2, [r4, #0] + ebc6: 69e0 ldr r0, [r4, #28] + ebc8: ebc2 12c2 rsb r2, r2, r2, lsl #7 + ebcc: 4410 add r0, r2 + ebce: 3101 adds r1, #1 + ebd0: f2c0 0300 movt r3, #0 + ebd4: 4798 blx r3 + ebd6: 78a3 ldrb r3, [r4, #2] + ebd8: 2002 movs r0, #2 + ebda: 2b04 cmp r3, #4 + ebdc: bf94 ite ls + ebde: 3301 addls r3, #1 + ebe0: 2305 movhi r3, #5 + ebe2: 70a3 strb r3, [r4, #2] + ebe4: 7823 ldrb r3, [r4, #0] + ebe6: 2b03 cmp r3, #3 + ebe8: 7063 strb r3, [r4, #1] + ebea: bf94 ite ls + ebec: 3301 addls r3, #1 + ebee: 2300 movhi r3, #0 + ebf0: 7023 strb r3, [r4, #0] + ebf2: bdf8 pop {r3, r4, r5, r6, r7, pc} + +0000ebf4 : + ebf4: f240 3329 movw r3, #809 ; 0x329 + ebf8: b570 push {r4, r5, r6, lr} + ebfa: f2c0 0300 movt r3, #0 + ebfe: 4798 blx r3 + ec00: f240 3435 movw r4, #821 ; 0x335 + ec04: 4606 mov r6, r0 + ec06: f2c0 0400 movt r4, #0 + ec0a: 2000 movs r0, #0 + ec0c: 47a0 blx r4 + ec0e: f240 3309 movw r3, #777 ; 0x309 + ec12: 2000 movs r0, #0 + ec14: f2c0 0300 movt r3, #0 + ec18: 4798 blx r3 + ec1a: 281b cmp r0, #27 + ec1c: 4603 mov r3, r0 + ec1e: d020 beq.n ec62 + ec20: f240 65a8 movw r5, #1704 ; 0x6a8 + ec24: f2c1 0500 movt r5, #4096 ; 0x1000 + ec28: 6829 ldr r1, [r5, #0] + ec2a: 78ca ldrb r2, [r1, #3] + ec2c: 2a01 cmp r2, #1 + ec2e: d027 beq.n ec80 + ec30: 78ca ldrb r2, [r1, #3] + ec32: 2a02 cmp r2, #2 + ec34: d00b beq.n ec4e + ec36: 2201 movs r2, #1 + ec38: f7ff ff50 bl eadc + ec3c: 2802 cmp r0, #2 + ec3e: d10d bne.n ec5c + ec40: 682a ldr r2, [r5, #0] + ec42: 6893 ldr r3, [r2, #8] + ec44: 2b00 cmp r3, #0 + ec46: d034 beq.n ecb2 + ec48: 2301 movs r3, #1 + ec4a: 7113 strb r3, [r2, #4] + ec4c: e006 b.n ec5c + ec4e: f1a0 0341 sub.w r3, r0, #65 ; 0x41 + ec52: b2db uxtb r3, r3 + ec54: 2200 movs r2, #0 + ec56: 2b01 cmp r3, #1 + ec58: 70ca strb r2, [r1, #3] + ec5a: d926 bls.n ecaa + ec5c: 4630 mov r0, r6 + ec5e: 47a0 blx r4 + ec60: bd70 pop {r4, r5, r6, pc} + ec62: f240 63a8 movw r3, #1704 ; 0x6a8 + ec66: f2c1 0300 movt r3, #4096 ; 0x1000 + ec6a: 681b ldr r3, [r3, #0] + ec6c: 795a ldrb r2, [r3, #5] + ec6e: 2a01 cmp r2, #1 + ec70: d00e beq.n ec90 + ec72: 2101 movs r1, #1 + ec74: 2200 movs r2, #0 + ec76: 7159 strb r1, [r3, #5] + ec78: 4630 mov r0, r6 + ec7a: 70da strb r2, [r3, #3] + ec7c: 47a0 blx r4 + ec7e: bd70 pop {r4, r5, r6, pc} + ec80: 285b cmp r0, #91 ; 0x5b + ec82: bf14 ite ne + ec84: 2300 movne r3, #0 + ec86: 2302 moveq r3, #2 + ec88: 70cb strb r3, [r1, #3] + ec8a: 4630 mov r0, r6 + ec8c: 47a0 blx r4 + ec8e: bd70 pop {r4, r5, r6, pc} + ec90: 799a ldrb r2, [r3, #6] + ec92: b2d2 uxtb r2, r2 + ec94: 2a01 cmp r2, #1 + ec96: bf18 it ne + ec98: 2200 movne r2, #0 + ec9a: d001 beq.n eca0 + ec9c: 70da strb r2, [r3, #3] + ec9e: e7dd b.n ec5c + eca0: 78d9 ldrb r1, [r3, #3] + eca2: 2900 cmp r1, #0 + eca4: d1da bne.n ec5c + eca6: 70da strb r2, [r3, #3] + eca8: e7d8 b.n ec5c + ecaa: 2201 movs r2, #1 + ecac: f7ff fee0 bl ea70 + ecb0: e7d4 b.n ec5c + ecb2: 4619 mov r1, r3 + ecb4: 6892 ldr r2, [r2, #8] + ecb6: 3201 adds r2, #1 + ecb8: 54d1 strb r1, [r2, r3] + ecba: 3301 adds r3, #1 + ecbc: 2b7f cmp r3, #127 ; 0x7f + ecbe: d1fb bne.n ecb8 + ecc0: e7cc b.n ec5c + ecc2: bf00 nop + +0000ecc4 : + ecc4: b5f8 push {r3, r4, r5, r6, r7, lr} + ecc6: f240 34ac movw r4, #940 ; 0x3ac + ecca: f2c1 0400 movt r4, #4096 ; 0x1000 + ecce: 4627 mov r7, r4 + ecd0: 4623 mov r3, r4 + ecd2: 2500 movs r5, #0 + ecd4: 462e mov r6, r5 + ecd6: 7025 strb r5, [r4, #0] + ecd8: f104 057f add.w r5, r4, #127 ; 0x7f + ecdc: f803 6f01 strb.w r6, [r3, #1]! + ece0: 42ab cmp r3, r5 + ece2: f04f 0400 mov.w r4, #0 + ece6: d1f9 bne.n ecdc + ece8: f240 3384 movw r3, #900 ; 0x384 + ecec: f240 462c movw r6, #1068 ; 0x42c + ecf0: f24f 359d movw r5, #62365 ; 0xf39d + ecf4: f240 6ea8 movw lr, #1704 ; 0x6a8 + ecf8: f2c1 0300 movt r3, #4096 ; 0x1000 + ecfc: f2c1 0600 movt r6, #4096 ; 0x1000 + ed00: f2c0 0500 movt r5, #0 + ed04: f2c1 0e00 movt lr, #4096 ; 0x1000 + ed08: 701c strb r4, [r3, #0] + ed0a: f8ce 3000 str.w r3, [lr] + ed0e: 705c strb r4, [r3, #1] + ed10: 709c strb r4, [r3, #2] + ed12: 70dc strb r4, [r3, #3] + ed14: 719c strb r4, [r3, #6] + ed16: 609f str r7, [r3, #8] + ed18: 619c str r4, [r3, #24] + ed1a: 61de str r6, [r3, #28] + ed1c: 60dd str r5, [r3, #12] + ed1e: 611a str r2, [r3, #16] + ed20: 6159 str r1, [r3, #20] + ed22: 621c str r4, [r3, #32] + ed24: b140 cbz r0, ed38 + ed26: f243 4090 movw r0, #13456 ; 0x3490 + ed2a: 2201 movs r2, #1 + ed2c: f2c0 0004 movt r0, #4 + ed30: 711c strb r4, [r3, #4] + ed32: 715a strb r2, [r3, #5] + ed34: 47a8 blx r5 + ed36: bdf8 pop {r3, r4, r5, r6, r7, pc} + ed38: 7118 strb r0, [r3, #4] + ed3a: 7158 strb r0, [r3, #5] + ed3c: f243 4090 movw r0, #13456 ; 0x3490 + ed40: f2c0 0004 movt r0, #4 + ed44: 47a8 blx r5 + ed46: bdf8 pop {r3, r4, r5, r6, r7, pc} + +0000ed48 : + ed48: b570 push {r4, r5, r6, lr} + ed4a: f240 64a8 movw r4, #1704 ; 0x6a8 + ed4e: f24f 359d movw r5, #62365 ; 0xf39d + ed52: f2c1 0400 movt r4, #4096 ; 0x1000 + ed56: f2c0 0500 movt r5, #0 + ed5a: 6820 ldr r0, [r4, #0] + ed5c: 2600 movs r6, #0 + ed5e: 7903 ldrb r3, [r0, #4] + ed60: 2b01 cmp r3, #1 + ed62: d1fc bne.n ed5e + ed64: f7ff fdfa bl e95c + ed68: f243 4090 movw r0, #13456 ; 0x3490 + ed6c: f2c0 0004 movt r0, #4 + ed70: 47a8 blx r5 + ed72: 6820 ldr r0, [r4, #0] + ed74: 7106 strb r6, [r0, #4] + ed76: e7f2 b.n ed5e + +0000ed78 : + ed78: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + ed7c: f640 0699 movw r6, #2201 ; 0x899 + ed80: f240 67a8 movw r7, #1704 ; 0x6a8 + ed84: 4680 mov r8, r0 + ed86: f2c0 0600 movt r6, #0 + ed8a: f2c1 0700 movt r7, #4096 ; 0x1000 + ed8e: 2400 movs r4, #0 + ed90: f240 65a8 movw r5, #1704 ; 0x6a8 + ed94: 2064 movs r0, #100 ; 0x64 + ed96: 47b0 blx r6 + ed98: 683b ldr r3, [r7, #0] + ed9a: 3401 adds r4, #1 + ed9c: 795b ldrb r3, [r3, #5] + ed9e: f2c1 0500 movt r5, #4096 ; 0x1000 + eda2: 2b01 cmp r3, #1 + eda4: d004 beq.n edb0 + eda6: 45a0 cmp r8, r4 + eda8: d2f2 bcs.n ed90 + edaa: 2001 movs r0, #1 + edac: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + edb0: f243 4090 movw r0, #13456 ; 0x3490 + edb4: f24f 339d movw r3, #62365 ; 0xf39d + edb8: f2c0 0004 movt r0, #4 + edbc: f2c0 0300 movt r3, #0 + edc0: 4798 blx r3 + edc2: 682b ldr r3, [r5, #0] + edc4: 2000 movs r0, #0 + edc6: 70d8 strb r0, [r3, #3] + edc8: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +0000edcc : + edcc: b570 push {r4, r5, r6, lr} + edce: f7ff ffd3 bl ed78 + edd2: b9c8 cbnz r0, ee08 + edd4: f240 64a8 movw r4, #1704 ; 0x6a8 + edd8: f2c1 0400 movt r4, #4096 ; 0x1000 + eddc: f24f 359d movw r5, #62365 ; 0xf39d + ede0: 6823 ldr r3, [r4, #0] + ede2: 4606 mov r6, r0 + ede4: f2c0 0500 movt r5, #0 + ede8: 4618 mov r0, r3 + edea: 2201 movs r2, #1 + edec: 719a strb r2, [r3, #6] + edee: 7903 ldrb r3, [r0, #4] + edf0: 2b01 cmp r3, #1 + edf2: d1fc bne.n edee + edf4: f7ff fdb2 bl e95c + edf8: f243 4090 movw r0, #13456 ; 0x3490 + edfc: f2c0 0004 movt r0, #4 + ee00: 47a8 blx r5 + ee02: 6820 ldr r0, [r4, #0] + ee04: 7106 strb r6, [r0, #4] + ee06: e7f2 b.n edee + ee08: bd70 pop {r4, r5, r6, pc} + ee0a: bf00 nop + +0000ee0c : + ee0c: b4f0 push {r4, r5, r6, r7} + ee0e: f24f 0169 movw r1, #61545 ; 0xf069 + ee12: f64e 7709 movw r7, #61193 ; 0xef09 + ee16: f64e 763d movw r6, #61245 ; 0xef3d + ee1a: f24f 05a9 movw r5, #61609 ; 0xf0a9 + ee1e: f24f 04bd movw r4, #61629 ; 0xf0bd + ee22: f24f 0289 movw r2, #61577 ; 0xf089 + ee26: f24f 03d1 movw r3, #61649 ; 0xf0d1 + ee2a: f2c0 0700 movt r7, #0 + ee2e: f2c0 0600 movt r6, #0 + ee32: f2c0 0500 movt r5, #0 + ee36: f2c0 0400 movt r4, #0 + ee3a: f2c0 0100 movt r1, #0 + ee3e: f2c0 0200 movt r2, #0 + ee42: f2c0 0300 movt r3, #0 + ee46: 6007 str r7, [r0, #0] + ee48: 6046 str r6, [r0, #4] + ee4a: 6085 str r5, [r0, #8] + ee4c: 60c4 str r4, [r0, #12] + ee4e: 6101 str r1, [r0, #16] + ee50: 6142 str r2, [r0, #20] + ee52: 6183 str r3, [r0, #24] + ee54: bcf0 pop {r4, r5, r6, r7} + ee56: 4770 bx lr + +0000ee58 : + ee58: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} + ee5c: f240 3a14 movw sl, #788 ; 0x314 + ee60: f2c1 0a00 movt sl, #4096 ; 0x1000 + ee64: f8da 3000 ldr.w r3, [sl] + ee68: 0058 lsls r0, r3, #1 + ee6a: d42e bmi.n eeca + ee6c: f242 03a0 movw r3, #8352 ; 0x20a0 + ee70: f2c4 0300 movt r3, #16384 ; 0x4000 + ee74: 681f ldr r7, [r3, #0] + ee76: f242 0530 movw r5, #8240 ; 0x2030 + ee7a: f240 3b58 movw fp, #856 ; 0x358 + ee7e: f24f 399d movw r9, #62365 ; 0xf39d + ee82: f2c4 0500 movt r5, #16384 ; 0x4000 + ee86: f2c1 0b00 movt fp, #4096 ; 0x1000 + ee8a: f2c0 0900 movt r9, #0 + ee8e: 2600 movs r6, #0 + ee90: 2402 movs r4, #2 + ee92: f04f 0801 mov.w r8, #1 + ee96: fa08 f304 lsl.w r3, r8, r4 + ee9a: 423b tst r3, r7 + ee9c: f104 0401 add.w r4, r4, #1 + eea0: d00b beq.n eeba + eea2: 682b ldr r3, [r5, #0] + eea4: 07da lsls r2, r3, #31 + eea6: d508 bpl.n eeba + eea8: f8da 3000 ldr.w r3, [sl] + eeac: 005b lsls r3, r3, #1 + eeae: d425 bmi.n eefc + eeb0: f856 300b ldr.w r3, [r6, fp] + eeb4: 2000 movs r0, #0 + eeb6: 4798 blx r3 + eeb8: 686b ldr r3, [r5, #4] + eeba: 2c08 cmp r4, #8 + eebc: f105 0514 add.w r5, r5, #20 + eec0: f106 0604 add.w r6, r6, #4 + eec4: d1e7 bne.n ee96 + eec6: e8bd 8ff8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, pc} + eeca: f642 70c8 movw r0, #12232 ; 0x2fc8 + eece: f24f 349d movw r4, #62365 ; 0xf39d + eed2: f2c0 0004 movt r0, #4 + eed6: f2c0 0400 movt r4, #0 + eeda: 47a0 blx r4 + eedc: f242 03a0 movw r3, #8352 ; 0x20a0 + eee0: f2c4 0300 movt r3, #16384 ; 0x4000 + eee4: f8da 2000 ldr.w r2, [sl] + eee8: 681f ldr r7, [r3, #0] + eeea: 0051 lsls r1, r2, #1 + eeec: d5c3 bpl.n ee76 + eeee: f642 70d8 movw r0, #12248 ; 0x2fd8 + eef2: 4639 mov r1, r7 + eef4: f2c0 0004 movt r0, #4 + eef8: 47a0 blx r4 + eefa: e7bc b.n ee76 + eefc: f642 70f0 movw r0, #12272 ; 0x2ff0 + ef00: f2c0 0004 movt r0, #4 + ef04: 47c8 blx r9 + ef06: e7d3 b.n eeb0 + +0000ef08 : + ef08: b430 push {r4, r5} + ef0a: f240 354c movw r5, #844 ; 0x34c + ef0e: f2c1 0500 movt r5, #4096 ; 0x1000 + ef12: 6829 ldr r1, [r5, #0] + ef14: 2302 movs r3, #2 + ef16: 2401 movs r4, #1 + ef18: fa04 f203 lsl.w r2, r4, r3 + ef1c: 420a tst r2, r1 + ef1e: d006 beq.n ef2e + ef20: 3301 adds r3, #1 + ef22: 2b08 cmp r3, #8 + ef24: d1f8 bne.n ef18 + ef26: bc30 pop {r4, r5} + ef28: 2200 movs r2, #0 + ef2a: 4610 mov r0, r2 + ef2c: 4770 bx lr + ef2e: 430a orrs r2, r1 + ef30: 602a str r2, [r5, #0] + ef32: 2201 movs r2, #1 + ef34: 6003 str r3, [r0, #0] + ef36: bc30 pop {r4, r5} + ef38: 4610 mov r0, r2 + ef3a: 4770 bx lr + +0000ef3c : + ef3c: b5f8 push {r3, r4, r5, r6, r7, lr} + ef3e: 6883 ldr r3, [r0, #8] + ef40: 7f46 ldrb r6, [r0, #29] + ef42: 005a lsls r2, r3, #1 + ef44: 4604 mov r4, r0 + ef46: ea42 0686 orr.w r6, r2, r6, lsl #2 + ef4a: f04f 31ff mov.w r1, #4294967295 + ef4e: b163 cbz r3, ef6a + ef50: 6803 ldr r3, [r0, #0] + ef52: 2b1e cmp r3, #30 + ef54: d852 bhi.n effc + ef56: f240 3314 movw r3, #788 ; 0x314 + ef5a: f2c1 0300 movt r3, #4096 ; 0x1000 + ef5e: 681b ldr r3, [r3, #0] + ef60: f413 7f94 tst.w r3, #296 ; 0x128 + ef64: bf08 it eq + ef66: 2101 moveq r1, #1 + ef68: d172 bne.n f050 + ef6a: f242 0308 movw r3, #8200 ; 0x2008 + ef6e: f2c4 0300 movt r3, #16384 ; 0x4000 + ef72: 7f22 ldrb r2, [r4, #28] + ef74: eb02 0282 add.w r2, r2, r2, lsl #2 + ef78: 0092 lsls r2, r2, #2 + ef7a: 50d6 str r6, [r2, r3] + ef7c: 7f23 ldrb r3, [r4, #28] + ef7e: eb03 0383 add.w r3, r3, r3, lsl #2 + ef82: 009b lsls r3, r3, #2 + ef84: f103 4380 add.w r3, r3, #1073741824 ; 0x40000000 + ef88: f503 5300 add.w r3, r3, #8192 ; 0x2000 + ef8c: 6019 str r1, [r3, #0] + ef8e: 7f65 ldrb r5, [r4, #29] + ef90: bb35 cbnz r5, efe0 + ef92: 68e7 ldr r7, [r4, #12] + ef94: b387 cbz r7, eff8 + ef96: 7f23 ldrb r3, [r4, #28] + ef98: 2b07 cmp r3, #7 + ef9a: d83a bhi.n f012 + ef9c: 2b01 cmp r3, #1 + ef9e: f104 050c add.w r5, r4, #12 + efa2: d948 bls.n f036 + efa4: f240 3058 movw r0, #856 ; 0x358 + efa8: f64e 6159 movw r1, #61017 ; 0xee59 + efac: f2c1 0000 movt r0, #4096 ; 0x1000 + efb0: f2c0 0100 movt r1, #0 + efb4: f244 0229 movw r2, #16425 ; 0x4029 + efb8: 3b02 subs r3, #2 + efba: f04f 0e05 mov.w lr, #5 + efbe: f8c4 e010 str.w lr, [r4, #16] + efc2: f2c0 0200 movt r2, #0 + efc6: f840 7023 str.w r7, [r0, r3, lsl #2] + efca: 4628 mov r0, r5 + efcc: 6164 str r4, [r4, #20] + efce: 60e1 str r1, [r4, #12] + efd0: 4790 blx r2 + efd2: 60e7 str r7, [r4, #12] + efd4: f244 03f1 movw r3, #16625 ; 0x40f1 + efd8: 4628 mov r0, r5 + efda: f2c0 0300 movt r3, #0 + efde: 4798 blx r3 + efe0: f242 0308 movw r3, #8200 ; 0x2008 + efe4: f2c4 0300 movt r3, #16384 ; 0x4000 + efe8: 7f22 ldrb r2, [r4, #28] + efea: f046 0601 orr.w r6, r6, #1 + efee: eb02 0282 add.w r2, r2, r2, lsl #2 + eff2: 0092 lsls r2, r2, #2 + eff4: 50d6 str r6, [r2, r3] + eff6: 2501 movs r5, #1 + eff8: 4628 mov r0, r5 + effa: bdf8 pop {r3, r4, r5, r6, r7, pc} + effc: f241 0285 movw r2, #4229 ; 0x1085 + f000: f6c0 0242 movt r2, #2114 ; 0x842 + f004: fba2 1203 umull r1, r2, r2, r3 + f008: 1a99 subs r1, r3, r2 + f00a: eb02 0151 add.w r1, r2, r1, lsr #1 + f00e: 0909 lsrs r1, r1, #4 + f010: e7ab b.n ef6a + f012: f240 3314 movw r3, #788 ; 0x314 + f016: f2c1 0300 movt r3, #4096 ; 0x1000 + f01a: 681b ldr r3, [r3, #0] + f01c: f413 7f94 tst.w r3, #296 ; 0x128 + f020: d0ea beq.n eff8 + f022: f243 0040 movw r0, #12352 ; 0x3040 + f026: f24f 339d movw r3, #62365 ; 0xf39d + f02a: f2c0 0004 movt r0, #4 + f02e: f2c0 0300 movt r3, #0 + f032: 4798 blx r3 + f034: e7e0 b.n eff8 + f036: 2b00 cmp r3, #0 + f038: bf0c ite eq + f03a: 2302 moveq r3, #2 + f03c: 2303 movne r3, #3 + f03e: f244 0229 movw r2, #16425 ; 0x4029 + f042: 6123 str r3, [r4, #16] + f044: 6164 str r4, [r4, #20] + f046: f2c0 0200 movt r2, #0 + f04a: 4628 mov r0, r5 + f04c: 4790 blx r2 + f04e: e7c1 b.n efd4 + f050: f243 0004 movw r0, #12292 ; 0x3004 + f054: f24f 339d movw r3, #62365 ; 0xf39d + f058: f2c0 0004 movt r0, #4 + f05c: f2c0 0300 movt r3, #0 + f060: 4798 blx r3 + f062: 2101 movs r1, #1 + f064: e781 b.n ef6a + f066: bf00 nop + +0000f068 : + f068: f242 0308 movw r3, #8200 ; 0x2008 + f06c: f2c4 0300 movt r3, #16384 ; 0x4000 + f070: eb00 0080 add.w r0, r0, r0, lsl #2 + f074: 0080 lsls r0, r0, #2 + f076: f100 4280 add.w r2, r0, #1073741824 ; 0x40000000 + f07a: f502 5200 add.w r2, r2, #8192 ; 0x2000 + f07e: 6812 ldr r2, [r2, #0] + f080: f022 0201 bic.w r2, r2, #1 + f084: 50c2 str r2, [r0, r3] + f086: 4770 bx lr + +0000f088 : + f088: f242 0308 movw r3, #8200 ; 0x2008 + f08c: f2c4 0300 movt r3, #16384 ; 0x4000 + f090: eb00 0080 add.w r0, r0, r0, lsl #2 + f094: 0080 lsls r0, r0, #2 + f096: f100 4280 add.w r2, r0, #1073741824 ; 0x40000000 + f09a: f502 5200 add.w r2, r2, #8192 ; 0x2000 + f09e: 6812 ldr r2, [r2, #0] + f0a0: f042 0201 orr.w r2, r2, #1 + f0a4: 50c2 str r2, [r0, r3] + f0a6: 4770 bx lr + +0000f0a8 : + f0a8: f242 0304 movw r3, #8196 ; 0x2004 + f0ac: f2c4 0300 movt r3, #16384 ; 0x4000 + f0b0: eb00 0080 add.w r0, r0, r0, lsl #2 + f0b4: 0080 lsls r0, r0, #2 + f0b6: 58c0 ldr r0, [r0, r3] + f0b8: 4770 bx lr + f0ba: bf00 nop + +0000f0bc : + f0bc: f242 030c movw r3, #8204 ; 0x200c + f0c0: f2c4 0300 movt r3, #16384 ; 0x4000 + f0c4: eb00 0080 add.w r0, r0, r0, lsl #2 + f0c8: 0080 lsls r0, r0, #2 + f0ca: 58c3 ldr r3, [r0, r3] + f0cc: 4770 bx lr + f0ce: bf00 nop + +0000f0d0 : + f0d0: b570 push {r4, r5, r6, lr} + f0d2: f240 3414 movw r4, #788 ; 0x314 + f0d6: f2c1 0400 movt r4, #4096 ; 0x1000 + f0da: 6823 ldr r3, [r4, #0] + f0dc: f413 7f94 tst.w r3, #296 ; 0x128 + f0e0: d100 bne.n f0e4 + f0e2: bd70 pop {r4, r5, r6, pc} + f0e4: f242 0308 movw r3, #8200 ; 0x2008 + f0e8: 4602 mov r2, r0 + f0ea: f2c4 0300 movt r3, #16384 ; 0x4000 + f0ee: f243 0078 movw r0, #12408 ; 0x3078 + f0f2: f24f 359d movw r5, #62365 ; 0xf39d + f0f6: 2614 movs r6, #20 + f0f8: fb06 f602 mul.w r6, r6, r2 + f0fc: f2c0 0004 movt r0, #4 + f100: 58f1 ldr r1, [r6, r3] + f102: f2c0 0500 movt r5, #0 + f106: 47a8 blx r5 + f108: 6823 ldr r3, [r4, #0] + f10a: f413 7f94 tst.w r3, #296 ; 0x128 + f10e: d0e8 beq.n f0e2 + f110: f243 00a0 movw r0, #12448 ; 0x30a0 + f114: f106 4380 add.w r3, r6, #1073741824 ; 0x40000000 + f118: f503 5300 add.w r3, r3, #8192 ; 0x2000 + f11c: 6819 ldr r1, [r3, #0] + f11e: f2c0 0004 movt r0, #4 + f122: 47a8 blx r5 + f124: e7dd b.n f0e2 + f126: bf00 nop + +0000f128 : + f128: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + f12c: 780b ldrb r3, [r1, #0] + f12e: b08b sub sp, #44 ; 0x2c + f130: 460d mov r5, r1 + f132: 4606 mov r6, r0 + f134: 2b00 cmp r3, #0 + f136: f000 812d beq.w f394 + f13a: f64f 71ff movw r1, #65535 ; 0xffff + f13e: 4690 mov r8, r2 + f140: f243 0bcc movw fp, #12492 ; 0x30cc + f144: 460a mov r2, r1 + f146: f246 6967 movw r9, #26215 ; 0x6667 + f14a: f2c0 010e movt r1, #14 + f14e: f2c6 6966 movt r9, #26214 ; 0x6666 + f152: f2c0 0b04 movt fp, #4 + f156: f2c0 02ef movt r2, #239 ; 0xef + f15a: 9101 str r1, [sp, #4] + f15c: a905 add r1, sp, #20 + f15e: 4604 mov r4, r0 + f160: f8cd 900c str.w r9, [sp, #12] + f164: 9202 str r2, [sp, #8] + f166: 9100 str r1, [sp, #0] + f168: 4618 mov r0, r3 + f16a: 46d9 mov r9, fp + f16c: e009 b.n f182 + f16e: 2e00 cmp r6, #0 + f170: f000 80db beq.w f32a + f174: 7020 strb r0, [r4, #0] + f176: 3401 adds r4, #1 + f178: 7868 ldrb r0, [r5, #1] + f17a: 3501 adds r5, #1 + f17c: 2800 cmp r0, #0 + f17e: f000 8084 beq.w f28a + f182: 2825 cmp r0, #37 ; 0x25 + f184: d1f3 bne.n f16e + f186: 786f ldrb r7, [r5, #1] + f188: 3501 adds r5, #1 + f18a: 2f73 cmp r7, #115 ; 0x73 + f18c: f000 8084 beq.w f298 + f190: f8d8 2000 ldr.w r2, [r8] + f194: 2a0f cmp r2, #15 + f196: bfd8 it le + f198: f04f 0c00 movle.w ip, #0 + f19c: dd0f ble.n f1be + f19e: f1a2 0310 sub.w r3, r2, #16 + f1a2: 2bef cmp r3, #239 ; 0xef + f1a4: bf98 it ls + f1a6: f04f 0c04 movls.w ip, #4 + f1aa: d908 bls.n f1be + f1ac: f5a2 7380 sub.w r3, r2, #256 ; 0x100 + f1b0: f5b3 6f70 cmp.w r3, #3840 ; 0xf00 + f1b4: bf38 it cc + f1b6: f04f 0c08 movcc.w ip, #8 + f1ba: f080 8082 bcs.w f2c2 + f1be: f1a7 0330 sub.w r3, r7, #48 ; 0x30 + f1c2: 2b09 cmp r3, #9 + f1c4: d810 bhi.n f1e8 + f1c6: 2300 movs r3, #0 + f1c8: eb03 0383 add.w r3, r3, r3, lsl #2 + f1cc: eb07 0c43 add.w ip, r7, r3, lsl #1 + f1d0: f815 7f01 ldrb.w r7, [r5, #1]! + f1d4: f1ac 0330 sub.w r3, ip, #48 ; 0x30 + f1d8: f1a7 0130 sub.w r1, r7, #48 ; 0x30 + f1dc: 2909 cmp r1, #9 + f1de: d9f3 bls.n f1c8 + f1e0: f1ac 0c31 sub.w ip, ip, #49 ; 0x31 + f1e4: ea4f 0c8c mov.w ip, ip, lsl #2 + f1e8: f007 03df and.w r3, r7, #223 ; 0xdf + f1ec: 2b58 cmp r3, #88 ; 0x58 + f1ee: d026 beq.n f23e + f1f0: 2b50 cmp r3, #80 ; 0x50 + f1f2: f000 808b beq.w f30c + f1f6: 2f64 cmp r7, #100 ; 0x64 + f1f8: f000 809a beq.w f330 + f1fc: f10d 0a15 add.w sl, sp, #21 + f200: 46d3 mov fp, sl + f202: 2f63 cmp r7, #99 ; 0x63 + f204: bf03 ittte eq + f206: b2d7 uxtbeq r7, r2 + f208: f88d 7014 strbeq.w r7, [sp, #20] + f20c: f108 0804 addeq.w r8, r8, #4 + f210: f88d 7014 strbne.w r7, [sp, #20] + f214: b156 cbz r6, f22c + f216: 2f0a cmp r7, #10 + f218: 7027 strb r7, [r4, #0] + f21a: f104 0401 add.w r4, r4, #1 + f21e: d00a beq.n f236 + f220: 45d3 cmp fp, sl + f222: d9a9 bls.n f178 + f224: f81a 7b01 ldrb.w r7, [sl], #1 + f228: 2e00 cmp r6, #0 + f22a: d1f4 bne.n f216 + f22c: 4638 mov r0, r7 + f22e: f7f1 f853 bl 2d8 + f232: 2f0a cmp r7, #10 + f234: d1f4 bne.n f220 + f236: 200d movs r0, #13 + f238: f7f1 f84e bl 2d8 + f23c: e7f0 b.n f220 + f23e: f007 0720 and.w r7, r7, #32 + f242: f10d 0b14 add.w fp, sp, #20 + f246: b2ff uxtb r7, r7 + f248: f108 0804 add.w r8, r8, #4 + f24c: f1bc 0f00 cmp.w ip, #0 + f250: db12 blt.n f278 + f252: 4663 mov r3, ip + f254: 4659 mov r1, fp + f256: b2ff uxtb r7, r7 + f258: fa42 f003 asr.w r0, r2, r3 + f25c: f000 000f and.w r0, r0, #15 + f260: f819 0000 ldrb.w r0, [r9, r0] + f264: 3b04 subs r3, #4 + f266: ea40 0007 orr.w r0, r0, r7 + f26a: f801 0b01 strb.w r0, [r1], #1 + f26e: d5f3 bpl.n f258 + f270: eb0b 0b9c add.w fp, fp, ip, lsr #2 + f274: f10b 0b01 add.w fp, fp, #1 + f278: 9a00 ldr r2, [sp, #0] + f27a: 4593 cmp fp, r2 + f27c: f67f af7c bls.w f178 + f280: f89d 7014 ldrb.w r7, [sp, #20] + f284: f10d 0a15 add.w sl, sp, #21 + f288: e7c4 b.n f214 + f28a: 1ba0 subs r0, r4, r6 + f28c: b10e cbz r6, f292 + f28e: 2300 movs r3, #0 + f290: 7023 strb r3, [r4, #0] + f292: b00b add sp, #44 ; 0x2c + f294: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + f298: f8d8 7000 ldr.w r7, [r8] + f29c: f108 0804 add.w r8, r8, #4 + f2a0: 7838 ldrb r0, [r7, #0] + f2a2: 2800 cmp r0, #0 + f2a4: f43f af68 beq.w f178 + f2a8: b146 cbz r6, f2bc + f2aa: 7020 strb r0, [r4, #0] + f2ac: 3401 adds r4, #1 + f2ae: f817 0f01 ldrb.w r0, [r7, #1]! + f2b2: 2800 cmp r0, #0 + f2b4: f43f af60 beq.w f178 + f2b8: 2e00 cmp r6, #0 + f2ba: d1f6 bne.n f2aa + f2bc: f7f1 f80c bl 2d8 + f2c0: e7f5 b.n f2ae + f2c2: f5a2 5380 sub.w r3, r2, #4096 ; 0x1000 + f2c6: f5b3 4f70 cmp.w r3, #61440 ; 0xf000 + f2ca: bf38 it cc + f2cc: f04f 0c0c movcc.w ip, #12 + f2d0: f4ff af75 bcc.w f1be + f2d4: 9901 ldr r1, [sp, #4] + f2d6: f5a2 3380 sub.w r3, r2, #65536 ; 0x10000 + f2da: 428b cmp r3, r1 + f2dc: bf98 it ls + f2de: f04f 0c10 movls.w ip, #16 + f2e2: f67f af6c bls.w f1be + f2e6: 9902 ldr r1, [sp, #8] + f2e8: f5a2 1380 sub.w r3, r2, #1048576 ; 0x100000 + f2ec: 428b cmp r3, r1 + f2ee: bf98 it ls + f2f0: f04f 0c14 movls.w ip, #20 + f2f4: f67f af63 bls.w f1be + f2f8: f102 4c7f add.w ip, r2, #4278190080 ; 0xff000000 + f2fc: f1bc 6f70 cmp.w ip, #251658240 ; 0xf000000 + f300: bf2c ite cs + f302: f04f 0c1c movcs.w ip, #28 + f306: f04f 0c18 movcc.w ip, #24 + f30a: e758 b.n f1be + f30c: f007 0720 and.w r7, r7, #32 + f310: b2ff uxtb r7, r7 + f312: f047 0158 orr.w r1, r7, #88 ; 0x58 + f316: 2330 movs r3, #48 ; 0x30 + f318: f108 0804 add.w r8, r8, #4 + f31c: f88d 1015 strb.w r1, [sp, #21] + f320: f88d 3014 strb.w r3, [sp, #20] + f324: f10d 0b16 add.w fp, sp, #22 + f328: e790 b.n f24c + f32a: f7f0 ffd5 bl 2d8 + f32e: e723 b.n f178 + f330: 2a00 cmp r2, #0 + f332: bfbb ittet lt + f334: 232d movlt r3, #45 ; 0x2d + f336: f10d 0015 addlt.w r0, sp, #21 + f33a: a805 addge r0, sp, #20 + f33c: f88d 3014 strblt.w r3, [sp, #20] + f340: f108 0804 add.w r8, r8, #4 + f344: bfb8 it lt + f346: 4252 neglt r2, r2 + f348: 4603 mov r3, r0 + f34a: f8dd e00c ldr.w lr, [sp, #12] + f34e: e000 b.n f352 + f350: 465b mov r3, fp + f352: fb8e 1702 smull r1, r7, lr, r2 + f356: 17d1 asrs r1, r2, #31 + f358: ebc1 01a7 rsb r1, r1, r7, asr #2 + f35c: eb01 0781 add.w r7, r1, r1, lsl #2 + f360: eba2 0747 sub.w r7, r2, r7, lsl #1 + f364: 469b mov fp, r3 + f366: 460a mov r2, r1 + f368: f107 0130 add.w r1, r7, #48 ; 0x30 + f36c: b2c9 uxtb r1, r1 + f36e: f80b 1b01 strb.w r1, [fp], #1 + f372: 2a00 cmp r2, #0 + f374: d1ec bne.n f350 + f376: 4298 cmp r0, r3 + f378: f4bf af7e bcs.w f278 + f37c: 3b01 subs r3, #1 + f37e: e000 b.n f382 + f380: 7859 ldrb r1, [r3, #1] + f382: 7807 ldrb r7, [r0, #0] + f384: 705f strb r7, [r3, #1] + f386: f800 1b01 strb.w r1, [r0], #1 + f38a: 4298 cmp r0, r3 + f38c: f103 33ff add.w r3, r3, #4294967295 + f390: d3f6 bcc.n f380 + f392: e771 b.n f278 + f394: 4618 mov r0, r3 + f396: 4634 mov r4, r6 + f398: e778 b.n f28c + f39a: bf00 nop + +0000f39c : + f39c: b40f push {r0, r1, r2, r3} + f39e: b508 push {r3, lr} + f3a0: aa02 add r2, sp, #8 + f3a2: f852 1b04 ldr.w r1, [r2], #4 + f3a6: 2000 movs r0, #0 + f3a8: f7ff febe bl f128 + f3ac: e8bd 4008 ldmia.w sp!, {r3, lr} + f3b0: 2001 movs r0, #1 + f3b2: b004 add sp, #16 + f3b4: 4770 bx lr + f3b6: bf00 nop + +0000f3b8 : + f3b8: b40e push {r1, r2, r3} + f3ba: b500 push {lr} + f3bc: aa01 add r2, sp, #4 + f3be: f852 1b04 ldr.w r1, [r2], #4 + f3c2: f7ff feb1 bl f128 + f3c6: f85d eb04 ldr.w lr, [sp], #4 + f3ca: 2001 movs r0, #1 + f3cc: b003 add sp, #12 + f3ce: 4770 bx lr + +0000f3d0 : + f3d0: b40c push {r2, r3} + f3d2: b508 push {r3, lr} + f3d4: f24f 630d movw r3, #62989 ; 0xf60d + f3d8: 460a mov r2, r1 + f3da: f2c0 0300 movt r3, #0 + f3de: 9902 ldr r1, [sp, #8] + f3e0: 4798 blx r3 + f3e2: e8bd 4008 ldmia.w sp!, {r3, lr} + f3e6: b002 add sp, #8 + f3e8: 4770 bx lr + f3ea: bf00 nop + +0000f3ec : + f3ec: b40f push {r0, r1, r2, r3} + f3ee: b500 push {lr} + f3f0: b083 sub sp, #12 + f3f2: 9b04 ldr r3, [sp, #16] + f3f4: aa02 add r2, sp, #8 + f3f6: 4619 mov r1, r3 + f3f8: 2000 movs r0, #0 + f3fa: 9301 str r3, [sp, #4] + f3fc: f7ff fe94 bl f128 + f400: b003 add sp, #12 + f402: f85d eb04 ldr.w lr, [sp], #4 + f406: b004 add sp, #16 + f408: 4770 bx lr + f40a: bf00 nop + +0000f40c : + f40c: b40e push {r1, r2, r3} + f40e: b500 push {lr} + f410: b082 sub sp, #8 + f412: 9b03 ldr r3, [sp, #12] + f414: aa02 add r2, sp, #8 + f416: 4619 mov r1, r3 + f418: 9301 str r3, [sp, #4] + f41a: f7ff fe85 bl f128 + f41e: b002 add sp, #8 + f420: f85d eb04 ldr.w lr, [sp], #4 + f424: b003 add sp, #12 + f426: 4770 bx lr + +0000f428 <_memcmp>: + f428: b1ca cbz r2, f45e <_memcmp+0x36> + f42a: b410 push {r4} + f42c: 780b ldrb r3, [r1, #0] + f42e: 7804 ldrb r4, [r0, #0] + f430: 429c cmp r4, r3 + f432: bf04 itt eq + f434: f102 32ff addeq.w r2, r2, #4294967295 + f438: 1812 addeq r2, r2, r0 + f43a: d006 beq.n f44a <_memcmp+0x22> + f43c: e00b b.n f456 <_memcmp+0x2e> + f43e: f810 4f01 ldrb.w r4, [r0, #1]! + f442: f811 3f01 ldrb.w r3, [r1, #1]! + f446: 429c cmp r4, r3 + f448: d105 bne.n f456 <_memcmp+0x2e> + f44a: 4290 cmp r0, r2 + f44c: d1f7 bne.n f43e <_memcmp+0x16> + f44e: 2000 movs r0, #0 + f450: f85d 4b04 ldr.w r4, [sp], #4 + f454: 4770 bx lr + f456: 1ae0 subs r0, r4, r3 + f458: f85d 4b04 ldr.w r4, [sp], #4 + f45c: 4770 bx lr + f45e: 4610 mov r0, r2 + f460: 4770 bx lr + f462: bf00 nop + +0000f464 <_memcpy>: + f464: 2a03 cmp r2, #3 + f466: b4f0 push {r4, r5, r6, r7} + f468: d80a bhi.n f480 <_memcpy+0x1c> + f46a: b13a cbz r2, f47c <_memcpy+0x18> + f46c: 4603 mov r3, r0 + f46e: 4402 add r2, r0 + f470: f811 4b01 ldrb.w r4, [r1], #1 + f474: f803 4b01 strb.w r4, [r3], #1 + f478: 4293 cmp r3, r2 + f47a: d1f9 bne.n f470 <_memcpy+0xc> + f47c: bcf0 pop {r4, r5, r6, r7} + f47e: 4770 bx lr + f480: ea40 0301 orr.w r3, r0, r1 + f484: 079b lsls r3, r3, #30 + f486: d1f1 bne.n f46c <_memcpy+0x8> + f488: 2a0f cmp r2, #15 + f48a: d93e bls.n f50a <_memcpy+0xa6> + f48c: 460c mov r4, r1 + f48e: 4603 mov r3, r0 + f490: f1a2 0710 sub.w r7, r2, #16 + f494: 093f lsrs r7, r7, #4 + f496: eb00 1607 add.w r6, r0, r7, lsl #4 + f49a: 3610 adds r6, #16 + f49c: 6825 ldr r5, [r4, #0] + f49e: 3310 adds r3, #16 + f4a0: f843 5c10 str.w r5, [r3, #-16] + f4a4: 6865 ldr r5, [r4, #4] + f4a6: 3410 adds r4, #16 + f4a8: f843 5c0c str.w r5, [r3, #-12] + f4ac: f854 5c08 ldr.w r5, [r4, #-8] + f4b0: f843 5c08 str.w r5, [r3, #-8] + f4b4: f854 5c04 ldr.w r5, [r4, #-4] + f4b8: f843 5c04 str.w r5, [r3, #-4] + f4bc: 42b3 cmp r3, r6 + f4be: d1ed bne.n f49c <_memcpy+0x38> + f4c0: 1c7b adds r3, r7, #1 + f4c2: f002 020f and.w r2, r2, #15 + f4c6: 011b lsls r3, r3, #4 + f4c8: 2a03 cmp r2, #3 + f4ca: 4419 add r1, r3 + f4cc: 4403 add r3, r0 + f4ce: d911 bls.n f4f4 <_memcpy+0x90> + f4d0: 460e mov r6, r1 + f4d2: 461d mov r5, r3 + f4d4: 4614 mov r4, r2 + f4d6: f856 7b04 ldr.w r7, [r6], #4 + f4da: 3c04 subs r4, #4 + f4dc: 2c03 cmp r4, #3 + f4de: f845 7b04 str.w r7, [r5], #4 + f4e2: d8f8 bhi.n f4d6 <_memcpy+0x72> + f4e4: 1f14 subs r4, r2, #4 + f4e6: f024 0403 bic.w r4, r4, #3 + f4ea: 3404 adds r4, #4 + f4ec: 4423 add r3, r4 + f4ee: 4421 add r1, r4 + f4f0: f002 0203 and.w r2, r2, #3 + f4f4: 2a00 cmp r2, #0 + f4f6: d0c1 beq.n f47c <_memcpy+0x18> + f4f8: 441a add r2, r3 + f4fa: f811 4b01 ldrb.w r4, [r1], #1 + f4fe: f803 4b01 strb.w r4, [r3], #1 + f502: 4293 cmp r3, r2 + f504: d1f9 bne.n f4fa <_memcpy+0x96> + f506: bcf0 pop {r4, r5, r6, r7} + f508: 4770 bx lr + f50a: 4603 mov r3, r0 + f50c: e7e0 b.n f4d0 <_memcpy+0x6c> + f50e: bf00 nop + +0000f510 <_memset>: + f510: 2a0b cmp r2, #11 + f512: d808 bhi.n f526 <_memset+0x16> + f514: b312 cbz r2, f55c <_memset+0x4c> + f516: 4603 mov r3, r0 + f518: b2c9 uxtb r1, r1 + f51a: 4402 add r2, r0 + f51c: f803 1b01 strb.w r1, [r3], #1 + f520: 4293 cmp r3, r2 + f522: d1fb bne.n f51c <_memset+0xc> + f524: 4770 bx lr + f526: b4f0 push {r4, r5, r6, r7} + f528: 460d mov r5, r1 + f52a: b129 cbz r1, f538 <_memset+0x28> + f52c: 040d lsls r5, r1, #16 + f52e: ea45 6501 orr.w r5, r5, r1, lsl #24 + f532: 430d orrs r5, r1 + f534: ea45 2501 orr.w r5, r5, r1, lsl #8 + f538: f010 0603 ands.w r6, r0, #3 + f53c: bf08 it eq + f53e: 4606 moveq r6, r0 + f540: d115 bne.n f56e <_memset+0x5e> + f542: 0897 lsrs r7, r2, #2 + f544: 463b mov r3, r7 + f546: 4634 mov r4, r6 + f548: 3b01 subs r3, #1 + f54a: f844 5b04 str.w r5, [r4], #4 + f54e: d1fb bne.n f548 <_memset+0x38> + f550: f012 0203 ands.w r2, r2, #3 + f554: eb06 0387 add.w r3, r6, r7, lsl #2 + f558: d101 bne.n f55e <_memset+0x4e> + f55a: bcf0 pop {r4, r5, r6, r7} + f55c: 4770 bx lr + f55e: b2c9 uxtb r1, r1 + f560: 441a add r2, r3 + f562: f803 1b01 strb.w r1, [r3], #1 + f566: 4293 cmp r3, r2 + f568: d1fb bne.n f562 <_memset+0x52> + f56a: bcf0 pop {r4, r5, r6, r7} + f56c: e7f6 b.n f55c <_memset+0x4c> + f56e: 4604 mov r4, r0 + f570: f1c6 0604 rsb r6, r6, #4 + f574: 1b92 subs r2, r2, r6 + f576: b2cb uxtb r3, r1 + f578: 4406 add r6, r0 + f57a: f804 3b01 strb.w r3, [r4], #1 + f57e: 42b4 cmp r4, r6 + f580: d1fb bne.n f57a <_memset+0x6a> + f582: e7de b.n f542 <_memset+0x32> + +0000f584 : + f584: f240 3370 movw r3, #880 ; 0x370 + f588: f2c1 0300 movt r3, #4096 ; 0x1000 + f58c: 681a ldr r2, [r3, #0] + f58e: b5f0 push {r4, r5, r6, r7, lr} + f590: b9b2 cbnz r2, f5c0 + f592: f64d 00aa movw r0, #55466 ; 0xd8aa + f596: f641 0130 movw r1, #6192 ; 0x1830 + f59a: 221b movs r2, #27 + f59c: f24c 04e0 movw r4, #49376 ; 0xc0e0 + f5a0: f2cc 60f8 movt r0, #50936 ; 0xc6f8 + f5a4: f2c0 0118 movt r1, #24 + f5a8: f2c0 6200 movt r2, #1536 ; 0x600 + f5ac: 2561 movs r5, #97 ; 0x61 + f5ae: 2601 movs r6, #1 + f5b0: f364 451f bfi r5, r4, #16, #16 + f5b4: 601e str r6, [r3, #0] + f5b6: 605d str r5, [r3, #4] + f5b8: 609c str r4, [r3, #8] + f5ba: 60d9 str r1, [r3, #12] + f5bc: 611a str r2, [r3, #16] + f5be: bdf0 pop {r4, r5, r6, r7, pc} + f5c0: 1d18 adds r0, r3, #4 + f5c2: c807 ldmia r0, {r0, r1, r2} + f5c4: 691e ldr r6, [r3, #16] + f5c6: f020 0c01 bic.w ip, r0, #1 + f5ca: f021 0707 bic.w r7, r1, #7 + f5ce: ea80 1080 eor.w r0, r0, r0, lsl #6 + f5d2: 00bf lsls r7, r7, #2 + f5d4: ea81 0181 eor.w r1, r1, r1, lsl #2 + f5d8: f022 0e0f bic.w lr, r2, #15 + f5dc: ea4f 4c8c mov.w ip, ip, lsl #18 + f5e0: ea47 64d1 orr.w r4, r7, r1, lsr #27 + f5e4: ea82 3242 eor.w r2, r2, r2, lsl #13 + f5e8: f026 077f bic.w r7, r6, #127 ; 0x7f + f5ec: ea4c 3550 orr.w r5, ip, r0, lsr #13 + f5f0: ea4f 1ece mov.w lr, lr, lsl #7 + f5f4: ea4e 5152 orr.w r1, lr, r2, lsr #21 + f5f8: ea84 0005 eor.w r0, r4, r5 + f5fc: 037f lsls r7, r7, #13 + f5fe: ea86 06c6 eor.w r6, r6, r6, lsl #3 + f602: 4048 eors r0, r1 + f604: ea47 3216 orr.w r2, r7, r6, lsr #12 + f608: 4050 eors r0, r2 + f60a: e7d4 b.n f5b6 + +0000f60c <_strncpy>: + f60c: b15a cbz r2, f626 <_strncpy+0x1a> + f60e: 4603 mov r3, r0 + f610: b410 push {r4} + f612: 4402 add r2, r0 + f614: 780c ldrb r4, [r1, #0] + f616: f803 4b01 strb.w r4, [r3], #1 + f61a: b104 cbz r4, f61e <_strncpy+0x12> + f61c: 3101 adds r1, #1 + f61e: 4293 cmp r3, r2 + f620: d1f8 bne.n f614 <_strncpy+0x8> + f622: f85d 4b04 ldr.w r4, [sp], #4 + f626: 4770 bx lr + +0000f628 <_strcpy>: + f628: 4602 mov r2, r0 + f62a: f811 3b01 ldrb.w r3, [r1], #1 + f62e: f802 3b01 strb.w r3, [r2], #1 + f632: 2b00 cmp r3, #0 + f634: d1f9 bne.n f62a <_strcpy+0x2> + f636: 4770 bx lr + +0000f638 : + f638: 780b ldrb r3, [r1, #0] + f63a: b12b cbz r3, f648 + f63c: f800 3b01 strb.w r3, [r0], #1 + f640: f811 3f01 ldrb.w r3, [r1, #1]! + f644: 2b00 cmp r3, #0 + f646: d1f9 bne.n f63c + f648: 2300 movs r3, #0 + f64a: 7003 strb r3, [r0, #0] + f64c: 4770 bx lr + f64e: bf00 nop + +0000f650 <_strlen>: + f650: 7803 ldrb r3, [r0, #0] + f652: b133 cbz r3, f662 <_strlen+0x12> + f654: 4603 mov r3, r0 + f656: f813 2f01 ldrb.w r2, [r3, #1]! + f65a: 2a00 cmp r2, #0 + f65c: d1fb bne.n f656 <_strlen+0x6> + f65e: 1a18 subs r0, r3, r0 + f660: 4770 bx lr + f662: 4618 mov r0, r3 + f664: 4770 bx lr + f666: bf00 nop + +0000f668 <_strnlen>: + f668: b430 push {r4, r5} + f66a: 1e4d subs r5, r1, #1 + f66c: b189 cbz r1, f692 <_strnlen+0x2a> + f66e: 7801 ldrb r1, [r0, #0] + f670: b179 cbz r1, f692 <_strnlen+0x2a> + f672: 1c43 adds r3, r0, #1 + f674: 2200 movs r2, #0 + f676: e003 b.n f680 <_strnlen+0x18> + f678: 781c ldrb r4, [r3, #0] + f67a: 3201 adds r2, #1 + f67c: 3301 adds r3, #1 + f67e: b12c cbz r4, f68c <_strnlen+0x24> + f680: 4295 cmp r5, r2 + f682: 4619 mov r1, r3 + f684: d1f8 bne.n f678 <_strnlen+0x10> + f686: 1a18 subs r0, r3, r0 + f688: bc30 pop {r4, r5} + f68a: 4770 bx lr + f68c: 1a08 subs r0, r1, r0 + f68e: bc30 pop {r4, r5} + f690: 4770 bx lr + f692: 4608 mov r0, r1 + f694: e7f8 b.n f688 <_strnlen+0x20> + f696: bf00 nop + +0000f698 : + f698: f64f 71ff movw r1, #65535 ; 0xffff + f69c: 2300 movs r3, #0 + f69e: e002 b.n f6a6 + f6a0: 3301 adds r3, #1 + f6a2: 428b cmp r3, r1 + f6a4: d002 beq.n f6ac + f6a6: 5cc2 ldrb r2, [r0, r3] + f6a8: 2a00 cmp r2, #0 + f6aa: d1f9 bne.n f6a0 + f6ac: 4618 mov r0, r3 + f6ae: 4770 bx lr + +0000f6b0 <_strcmp>: + f6b0: f810 3b01 ldrb.w r3, [r0], #1 + f6b4: f811 2b01 ldrb.w r2, [r1], #1 + f6b8: 4293 cmp r3, r2 + f6ba: d103 bne.n f6c4 <_strcmp+0x14> + f6bc: 2b00 cmp r3, #0 + f6be: d1f7 bne.n f6b0 <_strcmp> + f6c0: 4618 mov r0, r3 + f6c2: 4770 bx lr + f6c4: 429a cmp r2, r3 + f6c6: bf94 ite ls + f6c8: 2001 movls r0, #1 + f6ca: f04f 30ff movhi.w r0, #4294967295 + f6ce: 4770 bx lr + +0000f6d0 <_strncmp>: + f6d0: b302 cbz r2, f714 <_strncmp+0x44> + f6d2: b430 push {r4, r5} + f6d4: 780d ldrb r5, [r1, #0] + f6d6: 7803 ldrb r3, [r0, #0] + f6d8: 3101 adds r1, #1 + f6da: 42ab cmp r3, r5 + f6dc: f100 0401 add.w r4, r0, #1 + f6e0: d10e bne.n f700 <_strncmp+0x30> + f6e2: b1a3 cbz r3, f70e <_strncmp+0x3e> + f6e4: 4402 add r2, r0 + f6e6: e006 b.n f6f6 <_strncmp+0x26> + f6e8: f814 3b01 ldrb.w r3, [r4], #1 + f6ec: f811 5b01 ldrb.w r5, [r1], #1 + f6f0: 42ab cmp r3, r5 + f6f2: d105 bne.n f700 <_strncmp+0x30> + f6f4: b15b cbz r3, f70e <_strncmp+0x3e> + f6f6: 4294 cmp r4, r2 + f6f8: d1f6 bne.n f6e8 <_strncmp+0x18> + f6fa: 2000 movs r0, #0 + f6fc: bc30 pop {r4, r5} + f6fe: 4770 bx lr + f700: 42ab cmp r3, r5 + f702: bf2c ite cs + f704: 2001 movcs r0, #1 + f706: f04f 30ff movcc.w r0, #4294967295 + f70a: bc30 pop {r4, r5} + f70c: 4770 bx lr + f70e: 4618 mov r0, r3 + f710: bc30 pop {r4, r5} + f712: 4770 bx lr + f714: 4610 mov r0, r2 + f716: 4770 bx lr + +0000f718 : + f718: 7803 ldrb r3, [r0, #0] + f71a: b16b cbz r3, f738 + f71c: 780a ldrb r2, [r1, #0] + f71e: 429a cmp r2, r3 + f720: d10f bne.n f742 + f722: 1c4b adds r3, r1, #1 + f724: e002 b.n f72c + f726: 7809 ldrb r1, [r1, #0] + f728: 4291 cmp r1, r2 + f72a: d10a bne.n f742 + f72c: f810 2f01 ldrb.w r2, [r0, #1]! + f730: 4619 mov r1, r3 + f732: 3301 adds r3, #1 + f734: 2a00 cmp r2, #0 + f736: d1f6 bne.n f726 + f738: 7808 ldrb r0, [r1, #0] + f73a: 3000 adds r0, #0 + f73c: bf18 it ne + f73e: 2001 movne r0, #1 + f740: 4770 bx lr + f742: 2001 movs r0, #1 + f744: 4770 bx lr + f746: bf00 nop + +0000f748 : + f748: 7803 ldrb r3, [r0, #0] + f74a: b15b cbz r3, f764 + f74c: 1c42 adds r2, r0, #1 + f74e: f1a3 0161 sub.w r1, r3, #97 ; 0x61 + f752: 2919 cmp r1, #25 + f754: bf9c itt ls + f756: 3b20 subls r3, #32 + f758: f802 3c01 strbls.w r3, [r2, #-1] + f75c: f812 3b01 ldrb.w r3, [r2], #1 + f760: 2b00 cmp r3, #0 + f762: d1f4 bne.n f74e + f764: 4770 bx lr + f766: bf00 nop + +0000f768 : + f768: b470 push {r4, r5, r6} + f76a: 7805 ldrb r5, [r0, #0] + f76c: 2100 movs r1, #0 + f76e: 4604 mov r4, r0 + f770: 460e mov r6, r1 + f772: 4608 mov r0, r1 + f774: b1a5 cbz r5, f7a0 + f776: 4623 mov r3, r4 + f778: f813 2f01 ldrb.w r2, [r3, #1]! + f77c: 2a00 cmp r2, #0 + f77e: d1fb bne.n f778 + f780: 1b1b subs r3, r3, r4 + f782: 4299 cmp r1, r3 + f784: d80f bhi.n f7a6 + f786: 5c63 ldrb r3, [r4, r1] + f788: f1a3 0230 sub.w r2, r3, #48 ; 0x30 + f78c: 2a09 cmp r2, #9 + f78e: d80e bhi.n f7ae + f790: eb00 0080 add.w r0, r0, r0, lsl #2 + f794: eb03 0040 add.w r0, r3, r0, lsl #1 + f798: 3830 subs r0, #48 ; 0x30 + f79a: 3101 adds r1, #1 + f79c: 2d00 cmp r5, #0 + f79e: d1ea bne.n f776 + f7a0: 462b mov r3, r5 + f7a2: 4299 cmp r1, r3 + f7a4: d9ef bls.n f786 + f7a6: b106 cbz r6, f7aa + f7a8: 4240 negs r0, r0 + f7aa: bc70 pop {r4, r5, r6} + f7ac: 4770 bx lr + f7ae: 2d2d cmp r5, #45 ; 0x2d + f7b0: d1f9 bne.n f7a6 + f7b2: 2900 cmp r1, #0 + f7b4: d1f7 bne.n f7a6 + f7b6: 2601 movs r6, #1 + f7b8: e7ef b.n f79a + f7ba: bf00 nop + +0000f7bc : + f7bc: b508 push {r3, lr} + f7be: f243 409c movw r0, #13468 ; 0x349c + f7c2: f24f 339d movw r3, #62365 ; 0xf39d + f7c6: f2c0 0004 movt r0, #4 + f7ca: f2c0 0300 movt r3, #0 + f7ce: 4798 blx r3 + f7d0: bd08 pop {r3, pc} + f7d2: bf00 nop + +0000f7d4 <_strsep>: + f7d4: b4f0 push {r4, r5, r6, r7} + f7d6: 4607 mov r7, r0 + f7d8: 6800 ldr r0, [r0, #0] + f7da: b1c0 cbz r0, f80e <_strsep+0x3a> + f7dc: 7804 ldrb r4, [r0, #0] + f7de: b184 cbz r4, f802 <_strsep+0x2e> + f7e0: 4605 mov r5, r0 + f7e2: 780e ldrb r6, [r1, #0] + f7e4: b14e cbz r6, f7fa <_strsep+0x26> + f7e6: 42b4 cmp r4, r6 + f7e8: d00d beq.n f806 <_strsep+0x32> + f7ea: 460a mov r2, r1 + f7ec: e001 b.n f7f2 <_strsep+0x1e> + f7ee: 429c cmp r4, r3 + f7f0: d009 beq.n f806 <_strsep+0x32> + f7f2: f812 3f01 ldrb.w r3, [r2, #1]! + f7f6: 2b00 cmp r3, #0 + f7f8: d1f9 bne.n f7ee <_strsep+0x1a> + f7fa: f815 4f01 ldrb.w r4, [r5, #1]! + f7fe: 2c00 cmp r4, #0 + f800: d1f0 bne.n f7e4 <_strsep+0x10> + f802: 4625 mov r5, r4 + f804: e002 b.n f80c <_strsep+0x38> + f806: 2300 movs r3, #0 + f808: 702b strb r3, [r5, #0] + f80a: 3501 adds r5, #1 + f80c: 603d str r5, [r7, #0] + f80e: bcf0 pop {r4, r5, r6, r7} + f810: 4770 bx lr + f812: bf00 nop + +0000f814 : + f814: 4602 mov r2, r0 + f816: 4610 mov r0, r2 + f818: f812 3b01 ldrb.w r3, [r2], #1 + f81c: 2b20 cmp r3, #32 + f81e: f1a3 0109 sub.w r1, r3, #9 + f822: d0f8 beq.n f816 + f824: 2904 cmp r1, #4 + f826: d9f6 bls.n f816 + f828: 2b2c cmp r3, #44 ; 0x2c + f82a: d0f4 beq.n f816 + f82c: 4770 bx lr + f82e: bf00 nop + +0000f830 : + f830: b430 push {r4, r5} + f832: 6803 ldr r3, [r0, #0] + f834: 4605 mov r5, r0 + f836: 781a ldrb r2, [r3, #0] + f838: 3a30 subs r2, #48 ; 0x30 + f83a: 2a09 cmp r2, #9 + f83c: d812 bhi.n f864 + f83e: 461a mov r2, r3 + f840: 2000 movs r0, #0 + f842: 3301 adds r3, #1 + f844: 602b str r3, [r5, #0] + f846: f812 1f01 ldrb.w r1, [r2, #1]! + f84a: f813 4c01 ldrb.w r4, [r3, #-1] + f84e: eb00 0080 add.w r0, r0, r0, lsl #2 + f852: 3930 subs r1, #48 ; 0x30 + f854: eb04 0440 add.w r4, r4, r0, lsl #1 + f858: 2909 cmp r1, #9 + f85a: f1a4 0030 sub.w r0, r4, #48 ; 0x30 + f85e: d9f0 bls.n f842 + f860: bc30 pop {r4, r5} + f862: 4770 bx lr + f864: 2000 movs r0, #0 + f866: e7fb b.n f860 + +0000f868 <_parse_integer_fixup_radix>: + f868: 680b ldr r3, [r1, #0] + f86a: b92b cbnz r3, f878 <_parse_integer_fixup_radix+0x10> + f86c: 7803 ldrb r3, [r0, #0] + f86e: 2b30 cmp r3, #48 ; 0x30 + f870: d00f beq.n f892 <_parse_integer_fixup_radix+0x2a> + f872: 230a movs r3, #10 + f874: 600b str r3, [r1, #0] + f876: 4770 bx lr + f878: 2b10 cmp r3, #16 + f87a: d102 bne.n f882 <_parse_integer_fixup_radix+0x1a> + f87c: 7803 ldrb r3, [r0, #0] + f87e: 2b30 cmp r3, #48 ; 0x30 + f880: d000 beq.n f884 <_parse_integer_fixup_radix+0x1c> + f882: 4770 bx lr + f884: 7843 ldrb r3, [r0, #1] + f886: f043 0320 orr.w r3, r3, #32 + f88a: 2b78 cmp r3, #120 ; 0x78 + f88c: bf08 it eq + f88e: 3002 addeq r0, #2 + f890: 4770 bx lr + f892: 7843 ldrb r3, [r0, #1] + f894: f043 0320 orr.w r3, r3, #32 + f898: 2b78 cmp r3, #120 ; 0x78 + f89a: d002 beq.n f8a2 <_parse_integer_fixup_radix+0x3a> + f89c: 2308 movs r3, #8 + f89e: 600b str r3, [r1, #0] + f8a0: 4770 bx lr + f8a2: 7883 ldrb r3, [r0, #2] + f8a4: f1a3 0230 sub.w r2, r3, #48 ; 0x30 + f8a8: 2a09 cmp r2, #9 + f8aa: d904 bls.n f8b6 <_parse_integer_fixup_radix+0x4e> + f8ac: f023 0320 bic.w r3, r3, #32 + f8b0: 3b41 subs r3, #65 ; 0x41 + f8b2: 2b05 cmp r3, #5 + f8b4: d8f2 bhi.n f89c <_parse_integer_fixup_radix+0x34> + f8b6: 2310 movs r3, #16 + f8b8: 600b str r3, [r1, #0] + f8ba: e7df b.n f87c <_parse_integer_fixup_radix+0x14> + +0000f8bc <_parse_integer>: + f8bc: b5f0 push {r4, r5, r6, r7, lr} + f8be: 7803 ldrb r3, [r0, #0] + f8c0: b323 cbz r3, f90c <_parse_integer+0x50> + f8c2: 4684 mov ip, r0 + f8c4: 2600 movs r6, #0 + f8c6: 2700 movs r7, #0 + f8c8: 2000 movs r0, #0 + f8ca: e00c b.n f8e6 <_parse_integer+0x2a> + f8cc: fba6 4501 umull r4, r5, r6, r1 + f8d0: fb01 5507 mla r5, r1, r7, r5 + f8d4: f81c 3f01 ldrb.w r3, [ip, #1]! + f8d8: eb14 060e adds.w r6, r4, lr + f8dc: f100 0001 add.w r0, r0, #1 + f8e0: f145 0700 adc.w r7, r5, #0 + f8e4: b17b cbz r3, f906 <_parse_integer+0x4a> + f8e6: f1a3 0e30 sub.w lr, r3, #48 ; 0x30 + f8ea: fa5f f48e uxtb.w r4, lr + f8ee: f043 0320 orr.w r3, r3, #32 + f8f2: 2c09 cmp r4, #9 + f8f4: f1a3 0561 sub.w r5, r3, #97 ; 0x61 + f8f8: d903 bls.n f902 <_parse_integer+0x46> + f8fa: 2d05 cmp r5, #5 + f8fc: d803 bhi.n f906 <_parse_integer+0x4a> + f8fe: f1a3 0e57 sub.w lr, r3, #87 ; 0x57 + f902: 458e cmp lr, r1 + f904: d3e2 bcc.n f8cc <_parse_integer+0x10> + f906: e9c2 6700 strd r6, r7, [r2] + f90a: bdf0 pop {r4, r5, r6, r7, pc} + f90c: 4618 mov r0, r3 + f90e: 2600 movs r6, #0 + f910: 2700 movs r7, #0 + f912: e7f8 b.n f906 <_parse_integer+0x4a> + +0000f914 : + f914: b530 push {r4, r5, lr} + f916: b085 sub sp, #20 + f918: ab04 add r3, sp, #16 + f91a: f843 2d0c str.w r2, [r3, #-12]! + f91e: 460c mov r4, r1 + f920: 4619 mov r1, r3 + f922: f7ff ffa1 bl f868 <_parse_integer_fixup_radix> + f926: 9901 ldr r1, [sp, #4] + f928: aa02 add r2, sp, #8 + f92a: 4605 mov r5, r0 + f92c: f7ff ffc6 bl f8bc <_parse_integer> + f930: f020 4000 bic.w r0, r0, #2147483648 ; 0x80000000 + f934: 4405 add r5, r0 + f936: b104 cbz r4, f93a + f938: 6025 str r5, [r4, #0] + f93a: e9dd 0102 ldrd r0, r1, [sp, #8] + f93e: b005 add sp, #20 + f940: bd30 pop {r4, r5, pc} + f942: bf00 nop + +0000f944 : + f944: b510 push {r4, lr} + f946: 7804 ldrb r4, [r0, #0] + f948: 2c2d cmp r4, #45 ; 0x2d + f94a: d003 beq.n f954 + f94c: e8bd 4010 ldmia.w sp!, {r4, lr} + f950: f7ff bfe0 b.w f914 + f954: 3001 adds r0, #1 + f956: f7ff ffdd bl f914 + f95a: 4240 negs r0, r0 + f95c: eb61 0141 sbc.w r1, r1, r1, lsl #1 + f960: bd10 pop {r4, pc} + f962: bf00 nop + +0000f964 : + f964: b508 push {r3, lr} + f966: f7ff ffd5 bl f914 + f96a: bd08 pop {r3, pc} + +0000f96c : + f96c: b510 push {r4, lr} + f96e: 7804 ldrb r4, [r0, #0] + f970: 2c2d cmp r4, #45 ; 0x2d + f972: d002 beq.n f97a + f974: f7ff ffce bl f914 + f978: bd10 pop {r4, pc} + f97a: 3001 adds r0, #1 + f97c: f7ff ffca bl f914 + f980: 4240 negs r0, r0 + f982: bd10 pop {r4, pc} + +0000f984 <_vsscanf>: + f984: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + f988: 4683 mov fp, r0 + f98a: 4688 mov r8, r1 + f98c: 4691 mov r9, r2 + f98e: 4604 mov r4, r0 + f990: 780b ldrb r3, [r1, #0] + f992: b089 sub sp, #36 ; 0x24 + f994: 2700 movs r7, #0 + f996: b1eb cbz r3, f9d4 <_vsscanf+0x50> + f998: 2b20 cmp r3, #32 + f99a: d009 beq.n f9b0 <_vsscanf+0x2c> + f99c: f1a3 0209 sub.w r2, r3, #9 + f9a0: 2a04 cmp r2, #4 + f9a2: d905 bls.n f9b0 <_vsscanf+0x2c> + f9a4: 2b2c cmp r3, #44 ; 0x2c + f9a6: d003 beq.n f9b0 <_vsscanf+0x2c> + f9a8: 2b25 cmp r3, #37 ; 0x25 + f9aa: 4645 mov r5, r8 + f9ac: d10e bne.n f9cc <_vsscanf+0x48> + f9ae: e017 b.n f9e0 <_vsscanf+0x5c> + f9b0: f108 0001 add.w r0, r8, #1 + f9b4: f7ff ff2e bl f814 + f9b8: 4605 mov r5, r0 + f9ba: 4620 mov r0, r4 + f9bc: f7ff ff2a bl f814 + f9c0: 782b ldrb r3, [r5, #0] + f9c2: 4604 mov r4, r0 + f9c4: 2b00 cmp r3, #0 + f9c6: bf18 it ne + f9c8: 2b25 cmpne r3, #37 ; 0x25 + f9ca: d007 beq.n f9dc <_vsscanf+0x58> + f9cc: 7822 ldrb r2, [r4, #0] + f9ce: 429a cmp r2, r3 + f9d0: f000 80fb beq.w fbca <_vsscanf+0x246> + f9d4: 4638 mov r0, r7 + f9d6: b009 add sp, #36 ; 0x24 + f9d8: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + f9dc: 2b00 cmp r3, #0 + f9de: d0f9 beq.n f9d4 <_vsscanf+0x50> + f9e0: 786b ldrb r3, [r5, #1] + f9e2: 3501 adds r5, #1 + f9e4: 2b2a cmp r3, #42 ; 0x2a + f9e6: f000 80f5 beq.w fbd4 <_vsscanf+0x250> + f9ea: f1a3 0230 sub.w r2, r3, #48 ; 0x30 + f9ee: 2a09 cmp r2, #9 + f9f0: f240 80cc bls.w fb8c <_vsscanf+0x208> + f9f4: 2b68 cmp r3, #104 ; 0x68 + f9f6: 469c mov ip, r3 + f9f8: f64f 76ff movw r6, #65535 ; 0xffff + f9fc: f000 80db beq.w fbb6 <_vsscanf+0x232> + fa00: f043 0220 orr.w r2, r3, #32 + fa04: 2a6c cmp r2, #108 ; 0x6c + fa06: f000 823f beq.w fe88 <_vsscanf+0x504> + fa0a: 2a7a cmp r2, #122 ; 0x7a + fa0c: bf18 it ne + fa0e: f04f 0cff movne.w ip, #255 ; 0xff + fa12: f000 8239 beq.w fe88 <_vsscanf+0x504> + fa16: 2b00 cmp r3, #0 + fa18: d0dc beq.n f9d4 <_vsscanf+0x50> + fa1a: 2b6e cmp r3, #110 ; 0x6e + fa1c: f000 821c beq.w fe58 <_vsscanf+0x4d4> + fa20: 7823 ldrb r3, [r4, #0] + fa22: 2b00 cmp r3, #0 + fa24: d0d6 beq.n f9d4 <_vsscanf+0x50> + fa26: 200a movs r0, #10 + fa28: 9007 str r0, [sp, #28] + fa2a: 782b ldrb r3, [r5, #0] + fa2c: f105 0801 add.w r8, r5, #1 + fa30: 3b25 subs r3, #37 ; 0x25 + fa32: 2b53 cmp r3, #83 ; 0x53 + fa34: d8ce bhi.n f9d4 <_vsscanf+0x50> + fa36: a101 add r1, pc, #4 ; (adr r1, fa3c <_vsscanf+0xb8>) + fa38: f851 f023 ldr.w pc, [r1, r3, lsl #2] + fa3c: 0000fe0d .word 0x0000fe0d + fa40: 0000f9d5 .word 0x0000f9d5 + fa44: 0000f9d5 .word 0x0000f9d5 + fa48: 0000f9d5 .word 0x0000f9d5 + fa4c: 0000f9d5 .word 0x0000f9d5 + fa50: 0000f9d5 .word 0x0000f9d5 + fa54: 0000f9d5 .word 0x0000f9d5 + fa58: 0000f9d5 .word 0x0000f9d5 + fa5c: 0000f9d5 .word 0x0000f9d5 + fa60: 0000f9d5 .word 0x0000f9d5 + fa64: 0000f9d5 .word 0x0000f9d5 + fa68: 0000f9d5 .word 0x0000f9d5 + fa6c: 0000f9d5 .word 0x0000f9d5 + fa70: 0000f9d5 .word 0x0000f9d5 + fa74: 0000f9d5 .word 0x0000f9d5 + fa78: 0000f9d5 .word 0x0000f9d5 + fa7c: 0000f9d5 .word 0x0000f9d5 + fa80: 0000f9d5 .word 0x0000f9d5 + fa84: 0000f9d5 .word 0x0000f9d5 + fa88: 0000f9d5 .word 0x0000f9d5 + fa8c: 0000f9d5 .word 0x0000f9d5 + fa90: 0000f9d5 .word 0x0000f9d5 + fa94: 0000f9d5 .word 0x0000f9d5 + fa98: 0000f9d5 .word 0x0000f9d5 + fa9c: 0000f9d5 .word 0x0000f9d5 + faa0: 0000f9d5 .word 0x0000f9d5 + faa4: 0000f9d5 .word 0x0000f9d5 + faa8: 0000f9d5 .word 0x0000f9d5 + faac: 0000f9d5 .word 0x0000f9d5 + fab0: 0000f9d5 .word 0x0000f9d5 + fab4: 0000f9d5 .word 0x0000f9d5 + fab8: 0000f9d5 .word 0x0000f9d5 + fabc: 0000f9d5 .word 0x0000f9d5 + fac0: 0000f9d5 .word 0x0000f9d5 + fac4: 0000f9d5 .word 0x0000f9d5 + fac8: 0000f9d5 .word 0x0000f9d5 + facc: 0000f9d5 .word 0x0000f9d5 + fad0: 0000f9d5 .word 0x0000f9d5 + fad4: 0000f9d5 .word 0x0000f9d5 + fad8: 0000f9d5 .word 0x0000f9d5 + fadc: 0000f9d5 .word 0x0000f9d5 + fae0: 0000f9d5 .word 0x0000f9d5 + fae4: 0000f9d5 .word 0x0000f9d5 + fae8: 0000f9d5 .word 0x0000f9d5 + faec: 0000f9d5 .word 0x0000f9d5 + faf0: 0000f9d5 .word 0x0000f9d5 + faf4: 0000f9d5 .word 0x0000f9d5 + faf8: 0000f9d5 .word 0x0000f9d5 + fafc: 0000f9d5 .word 0x0000f9d5 + fb00: 0000f9d5 .word 0x0000f9d5 + fb04: 0000f9d5 .word 0x0000f9d5 + fb08: 0000fe07 .word 0x0000fe07 + fb0c: 0000f9d5 .word 0x0000f9d5 + fb10: 0000f9d5 .word 0x0000f9d5 + fb14: 0000f9d5 .word 0x0000f9d5 + fb18: 0000f9d5 .word 0x0000f9d5 + fb1c: 0000f9d5 .word 0x0000f9d5 + fb20: 0000f9d5 .word 0x0000f9d5 + fb24: 0000f9d5 .word 0x0000f9d5 + fb28: 0000f9d5 .word 0x0000f9d5 + fb2c: 0000f9d5 .word 0x0000f9d5 + fb30: 0000f9d5 .word 0x0000f9d5 + fb34: 0000fdd5 .word 0x0000fdd5 + fb38: 0000fd4f .word 0x0000fd4f + fb3c: 0000f9d5 .word 0x0000f9d5 + fb40: 0000f9d5 .word 0x0000f9d5 + fb44: 0000f9d5 .word 0x0000f9d5 + fb48: 0000f9d5 .word 0x0000f9d5 + fb4c: 0000fd4b .word 0x0000fd4b + fb50: 0000f9d5 .word 0x0000f9d5 + fb54: 0000f9d5 .word 0x0000f9d5 + fb58: 0000f9d5 .word 0x0000f9d5 + fb5c: 0000f9d5 .word 0x0000f9d5 + fb60: 0000f9d5 .word 0x0000f9d5 + fb64: 0000fc29 .word 0x0000fc29 + fb68: 0000f9d5 .word 0x0000f9d5 + fb6c: 0000f9d5 .word 0x0000f9d5 + fb70: 0000f9d5 .word 0x0000f9d5 + fb74: 0000fd6d .word 0x0000fd6d + fb78: 0000f9d5 .word 0x0000f9d5 + fb7c: 0000fc2d .word 0x0000fc2d + fb80: 0000f9d5 .word 0x0000f9d5 + fb84: 0000f9d5 .word 0x0000f9d5 + fb88: 0000fe07 .word 0x0000fe07 + fb8c: 2600 movs r6, #0 + fb8e: eb06 0686 add.w r6, r6, r6, lsl #2 + fb92: eb03 0646 add.w r6, r3, r6, lsl #1 + fb96: f815 3f01 ldrb.w r3, [r5, #1]! + fb9a: 3e30 subs r6, #48 ; 0x30 + fb9c: f1a3 0230 sub.w r2, r3, #48 ; 0x30 + fba0: 2a09 cmp r2, #9 + fba2: d9f4 bls.n fb8e <_vsscanf+0x20a> + fba4: b2b6 uxth r6, r6 + fba6: b232 sxth r2, r6 + fba8: 2a00 cmp r2, #0 + fbaa: f77f af13 ble.w f9d4 <_vsscanf+0x50> + fbae: 2b68 cmp r3, #104 ; 0x68 + fbb0: 469c mov ip, r3 + fbb2: f47f af25 bne.w fa00 <_vsscanf+0x7c> + fbb6: 786b ldrb r3, [r5, #1] + fbb8: 1c6a adds r2, r5, #1 + fbba: 2b68 cmp r3, #104 ; 0x68 + fbbc: f040 81d0 bne.w ff60 <_vsscanf+0x5dc> + fbc0: 78ab ldrb r3, [r5, #2] + fbc2: f04f 0c48 mov.w ip, #72 ; 0x48 + fbc6: 3502 adds r5, #2 + fbc8: e725 b.n fa16 <_vsscanf+0x92> + fbca: 3401 adds r4, #1 + fbcc: f105 0801 add.w r8, r5, #1 + fbd0: 786b ldrb r3, [r5, #1] + fbd2: e6e0 b.n f996 <_vsscanf+0x12> + fbd4: 7821 ldrb r1, [r4, #0] + fbd6: b951 cbnz r1, fbee <_vsscanf+0x26a> + fbd8: 4638 mov r0, r7 + fbda: b009 add sp, #36 ; 0x24 + fbdc: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + fbe0: 2b2c cmp r3, #44 ; 0x2c + fbe2: d00a beq.n fbfa <_vsscanf+0x276> + fbe4: 2b25 cmp r3, #37 ; 0x25 + fbe6: d008 beq.n fbfa <_vsscanf+0x276> + fbe8: f013 0fdf tst.w r3, #223 ; 0xdf + fbec: d005 beq.n fbfa <_vsscanf+0x276> + fbee: f815 3f01 ldrb.w r3, [r5, #1]! + fbf2: f1a3 0209 sub.w r2, r3, #9 + fbf6: 2a04 cmp r2, #4 + fbf8: d8f2 bhi.n fbe0 <_vsscanf+0x25c> + fbfa: f1a1 0209 sub.w r2, r1, #9 + fbfe: 2a04 cmp r2, #4 + fc00: d910 bls.n fc24 <_vsscanf+0x2a0> + fc02: 292c cmp r1, #44 ; 0x2c + fc04: d00e beq.n fc24 <_vsscanf+0x2a0> + fc06: f011 0fdf tst.w r1, #223 ; 0xdf + fc0a: d105 bne.n fc18 <_vsscanf+0x294> + fc0c: e00a b.n fc24 <_vsscanf+0x2a0> + fc0e: 2a2c cmp r2, #44 ; 0x2c + fc10: d008 beq.n fc24 <_vsscanf+0x2a0> + fc12: f012 0fdf tst.w r2, #223 ; 0xdf + fc16: d005 beq.n fc24 <_vsscanf+0x2a0> + fc18: f814 2f01 ldrb.w r2, [r4, #1]! + fc1c: f1a2 0109 sub.w r1, r2, #9 + fc20: 2904 cmp r1, #4 + fc22: d8f4 bhi.n fc0e <_vsscanf+0x28a> + fc24: 46a8 mov r8, r5 + fc26: e6b6 b.n f996 <_vsscanf+0x12> + fc28: 2308 movs r3, #8 + fc2a: 9307 str r3, [sp, #28] + fc2c: 4620 mov r0, r4 + fc2e: f8cd c004 str.w ip, [sp, #4] + fc32: f7ff fdef bl f814 + fc36: 4604 mov r4, r0 + fc38: 7803 ldrb r3, [r0, #0] + fc3a: f8dd c004 ldr.w ip, [sp, #4] + fc3e: f04f 0a00 mov.w sl, #0 + fc42: 2b00 cmp r3, #0 + fc44: f43f aec6 beq.w f9d4 <_vsscanf+0x50> + fc48: 9a07 ldr r2, [sp, #28] + fc4a: 2a10 cmp r2, #16 + fc4c: f000 810f beq.w fe6e <_vsscanf+0x4ea> + fc50: 2a0a cmp r2, #10 + fc52: f000 80e9 beq.w fe28 <_vsscanf+0x4a4> + fc56: 2a08 cmp r2, #8 + fc58: f040 80e3 bne.w fe22 <_vsscanf+0x49e> + fc5c: 3b30 subs r3, #48 ; 0x30 + fc5e: 2b07 cmp r3, #7 + fc60: f63f aeb8 bhi.w f9d4 <_vsscanf+0x50> + fc64: 4620 mov r0, r4 + fc66: a906 add r1, sp, #24 + fc68: f8cd c004 str.w ip, [sp, #4] + fc6c: f1ba 0f00 cmp.w sl, #0 + fc70: f000 80e6 beq.w fe40 <_vsscanf+0x4bc> + fc74: f1bc 0f4c cmp.w ip, #76 ; 0x4c + fc78: f000 814d beq.w ff16 <_vsscanf+0x592> + fc7c: f7ff fe76 bl f96c + fc80: f8dd c004 ldr.w ip, [sp, #4] + fc84: 17c1 asrs r1, r0, #31 + fc86: e9cd 0102 strd r0, r1, [sp, #8] + fc8a: b236 sxth r6, r6 + fc8c: 2e00 cmp r6, #0 + fc8e: dd21 ble.n fcd4 <_vsscanf+0x350> + fc90: 9b06 ldr r3, [sp, #24] + fc92: 1b1a subs r2, r3, r4 + fc94: 42b2 cmp r2, r6 + fc96: dd1d ble.n fcd4 <_vsscanf+0x350> + fc98: 9807 ldr r0, [sp, #28] + fc9a: 2800 cmp r0, #0 + fc9c: f000 8147 beq.w ff2e <_vsscanf+0x5aa> + fca0: 4651 mov r1, sl + fca2: 3b01 subs r3, #1 + fca4: 9705 str r7, [sp, #20] + fca6: 461f mov r7, r3 + fca8: e9dd 2302 ldrd r2, r3, [sp, #8] + fcac: 2900 cmp r1, #0 + fcae: f000 80b4 beq.w fe1a <_vsscanf+0x496> + fcb2: fb92 f2f0 sdiv r2, r2, r0 + fcb6: 17d3 asrs r3, r2, #31 + fcb8: ebc4 0e07 rsb lr, r4, r7 + fcbc: 4576 cmp r6, lr + fcbe: 46ba mov sl, r7 + fcc0: f107 37ff add.w r7, r7, #4294967295 + fcc4: dbf2 blt.n fcac <_vsscanf+0x328> + fcc6: e9cd 2302 strd r2, r3, [sp, #8] + fcca: 460b mov r3, r1 + fccc: 4651 mov r1, sl + fcce: 469a mov sl, r3 + fcd0: 9f05 ldr r7, [sp, #20] + fcd2: 9106 str r1, [sp, #24] + fcd4: f1ac 0c48 sub.w ip, ip, #72 ; 0x48 + fcd8: f1bc 0f32 cmp.w ip, #50 ; 0x32 + fcdc: f200 8111 bhi.w ff02 <_vsscanf+0x57e> + fce0: e8df f01c tbh [pc, ip, lsl #1] + fce4: 010f00fb .word 0x010f00fb + fce8: 010f010f .word 0x010f010f + fcec: 010f0106 .word 0x010f0106 + fcf0: 010f010f .word 0x010f010f + fcf4: 010f010f .word 0x010f010f + fcf8: 010f010f .word 0x010f010f + fcfc: 010f010f .word 0x010f010f + fd00: 010f010f .word 0x010f010f + fd04: 010f010f .word 0x010f010f + fd08: 010f00f4 .word 0x010f00f4 + fd0c: 010f010f .word 0x010f010f + fd10: 010f010f .word 0x010f010f + fd14: 010f010f .word 0x010f010f + fd18: 010f010f .word 0x010f010f + fd1c: 010f010f .word 0x010f010f + fd20: 010f010f .word 0x010f010f + fd24: 010f00e9 .word 0x010f00e9 + fd28: 010f010f .word 0x010f010f + fd2c: 010f00d9 .word 0x010f00d9 + fd30: 010f010f .word 0x010f010f + fd34: 010f010f .word 0x010f010f + fd38: 010f010f .word 0x010f010f + fd3c: 010f010f .word 0x010f010f + fd40: 010f010f .word 0x010f010f + fd44: 010f010f .word 0x010f010f + fd48: 00f4 .short 0x00f4 + fd4a: 2000 movs r0, #0 + fd4c: 9007 str r0, [sp, #28] + fd4e: 4620 mov r0, r4 + fd50: f8cd c004 str.w ip, [sp, #4] + fd54: f7ff fd5e bl f814 + fd58: 7803 ldrb r3, [r0, #0] + fd5a: 4604 mov r4, r0 + fd5c: 2b2d cmp r3, #45 ; 0x2d + fd5e: f8dd c004 ldr.w ip, [sp, #4] + fd62: bf08 it eq + fd64: 7843 ldrbeq r3, [r0, #1] + fd66: f04f 0a01 mov.w sl, #1 + fd6a: e76a b.n fc42 <_vsscanf+0x2be> + fd6c: f647 73ff movw r3, #32767 ; 0x7fff + fd70: b232 sxth r2, r6 + fd72: 4620 mov r0, r4 + fd74: f1b2 3fff cmp.w r2, #4294967295 + fd78: bf08 it eq + fd7a: 461e moveq r6, r3 + fd7c: f7ff fd4a bl f814 + fd80: 7803 ldrb r3, [r0, #0] + fd82: 4604 mov r4, r0 + fd84: f013 0fdf tst.w r3, #223 ; 0xdf + fd88: f109 0e04 add.w lr, r9, #4 + fd8c: f8d9 2000 ldr.w r2, [r9] + fd90: d019 beq.n fdc6 <_vsscanf+0x442> + fd92: f1a3 0109 sub.w r1, r3, #9 + fd96: 2904 cmp r1, #4 + fd98: d915 bls.n fdc6 <_vsscanf+0x442> + fd9a: 2b2c cmp r3, #44 ; 0x2c + fd9c: d013 beq.n fdc6 <_vsscanf+0x442> + fd9e: b236 sxth r6, r6 + fda0: 4416 add r6, r2 + fda2: e00c b.n fdbe <_vsscanf+0x43a> + fda4: f802 3b01 strb.w r3, [r2], #1 + fda8: 7863 ldrb r3, [r4, #1] + fdaa: 460c mov r4, r1 + fdac: f013 0fdf tst.w r3, #223 ; 0xdf + fdb0: f1a3 0009 sub.w r0, r3, #9 + fdb4: d007 beq.n fdc6 <_vsscanf+0x442> + fdb6: 2804 cmp r0, #4 + fdb8: d905 bls.n fdc6 <_vsscanf+0x442> + fdba: 2b2c cmp r3, #44 ; 0x2c + fdbc: d003 beq.n fdc6 <_vsscanf+0x442> + fdbe: 42b2 cmp r2, r6 + fdc0: f104 0101 add.w r1, r4, #1 + fdc4: d1ee bne.n fda4 <_vsscanf+0x420> + fdc6: f04f 0300 mov.w r3, #0 + fdca: 7013 strb r3, [r2, #0] + fdcc: 786b ldrb r3, [r5, #1] + fdce: 3701 adds r7, #1 + fdd0: 46f1 mov r9, lr + fdd2: e5e0 b.n f996 <_vsscanf+0x12> + fdd4: b233 sxth r3, r6 + fdd6: f1b3 3fff cmp.w r3, #4294967295 + fdda: bf08 it eq + fddc: 2601 moveq r6, #1 + fdde: f8d9 2000 ldr.w r2, [r9] + fde2: 7823 ldrb r3, [r4, #0] + fde4: f109 0904 add.w r9, r9, #4 + fde8: e001 b.n fdee <_vsscanf+0x46a> + fdea: 7823 ldrb r3, [r4, #0] + fdec: b143 cbz r3, fe00 <_vsscanf+0x47c> + fdee: 3e01 subs r6, #1 + fdf0: b2b6 uxth r6, r6 + fdf2: b231 sxth r1, r6 + fdf4: 2900 cmp r1, #0 + fdf6: f104 0401 add.w r4, r4, #1 + fdfa: f802 3b01 strb.w r3, [r2], #1 + fdfe: dcf4 bgt.n fdea <_vsscanf+0x466> + fe00: 3701 adds r7, #1 + fe02: 786b ldrb r3, [r5, #1] + fe04: e5c7 b.n f996 <_vsscanf+0x12> + fe06: 2310 movs r3, #16 + fe08: 9307 str r3, [sp, #28] + fe0a: e70f b.n fc2c <_vsscanf+0x2a8> + fe0c: 7823 ldrb r3, [r4, #0] + fe0e: 2b25 cmp r3, #37 ; 0x25 + fe10: f47f ade0 bne.w f9d4 <_vsscanf+0x50> + fe14: 3401 adds r4, #1 + fe16: 786b ldrb r3, [r5, #1] + fe18: e5bd b.n f996 <_vsscanf+0x12> + fe1a: fbb2 f2f0 udiv r2, r2, r0 + fe1e: 2300 movs r3, #0 + fe20: e74a b.n fcb8 <_vsscanf+0x334> + fe22: 2a00 cmp r2, #0 + fe24: f47f af1e bne.w fc64 <_vsscanf+0x2e0> + fe28: 3b30 subs r3, #48 ; 0x30 + fe2a: 2b09 cmp r3, #9 + fe2c: f63f add2 bhi.w f9d4 <_vsscanf+0x50> + fe30: 4620 mov r0, r4 + fe32: a906 add r1, sp, #24 + fe34: f8cd c004 str.w ip, [sp, #4] + fe38: f1ba 0f00 cmp.w sl, #0 + fe3c: f47f af1a bne.w fc74 <_vsscanf+0x2f0> + fe40: f1bc 0f4c cmp.w ip, #76 ; 0x4c + fe44: d06c beq.n ff20 <_vsscanf+0x59c> + fe46: f7ff fd65 bl f914 + fe4a: 4602 mov r2, r0 + fe4c: 2300 movs r3, #0 + fe4e: e9cd 2302 strd r2, r3, [sp, #8] + fe52: f8dd c004 ldr.w ip, [sp, #4] + fe56: e718 b.n fc8a <_vsscanf+0x306> + fe58: f8d9 3000 ldr.w r3, [r9] + fe5c: ebcb 0204 rsb r2, fp, r4 + fe60: 601a str r2, [r3, #0] + fe62: f109 0904 add.w r9, r9, #4 + fe66: 786b ldrb r3, [r5, #1] + fe68: f105 0801 add.w r8, r5, #1 + fe6c: e593 b.n f996 <_vsscanf+0x12> + fe6e: f1a3 0130 sub.w r1, r3, #48 ; 0x30 + fe72: 2909 cmp r1, #9 + fe74: f67f aef6 bls.w fc64 <_vsscanf+0x2e0> + fe78: f023 0320 bic.w r3, r3, #32 + fe7c: 3b41 subs r3, #65 ; 0x41 + fe7e: b2db uxtb r3, r3 + fe80: 2b05 cmp r3, #5 + fe82: f67f aeef bls.w fc64 <_vsscanf+0x2e0> + fe86: e5a5 b.n f9d4 <_vsscanf+0x50> + fe88: 7869 ldrb r1, [r5, #1] + fe8a: 1c6a adds r2, r5, #1 + fe8c: 428b cmp r3, r1 + fe8e: d065 beq.n ff5c <_vsscanf+0x5d8> + fe90: 460b mov r3, r1 + fe92: 4615 mov r5, r2 + fe94: e5bf b.n fa16 <_vsscanf+0x92> + fe96: f8d9 3000 ldr.w r3, [r9] + fe9a: f109 0904 add.w r9, r9, #4 + fe9e: f1ba 0f00 cmp.w sl, #0 + fea2: d117 bne.n fed4 <_vsscanf+0x550> + fea4: 9a02 ldr r2, [sp, #8] + fea6: 601a str r2, [r3, #0] + fea8: 9c06 ldr r4, [sp, #24] + feaa: 3701 adds r7, #1 + feac: 2c00 cmp r4, #0 + feae: f43f ad91 beq.w f9d4 <_vsscanf+0x50> + feb2: 786b ldrb r3, [r5, #1] + feb4: e56f b.n f996 <_vsscanf+0x12> + feb6: f8d9 3000 ldr.w r3, [r9] + feba: f109 0904 add.w r9, r9, #4 + febe: f1ba 0f00 cmp.w sl, #0 + fec2: d043 beq.n ff4c <_vsscanf+0x5c8> + fec4: f8bd 2008 ldrh.w r2, [sp, #8] + fec8: 801a strh r2, [r3, #0] + feca: e7ed b.n fea8 <_vsscanf+0x524> + fecc: f8d9 3000 ldr.w r3, [r9] + fed0: f109 0904 add.w r9, r9, #4 + fed4: 9902 ldr r1, [sp, #8] + fed6: 6019 str r1, [r3, #0] + fed8: e7e6 b.n fea8 <_vsscanf+0x524> + feda: f8d9 3000 ldr.w r3, [r9] + fede: f109 0904 add.w r9, r9, #4 + fee2: f1ba 0f00 cmp.w sl, #0 + fee6: d035 beq.n ff54 <_vsscanf+0x5d0> + fee8: f89d 0008 ldrb.w r0, [sp, #8] + feec: 7018 strb r0, [r3, #0] + feee: e7db b.n fea8 <_vsscanf+0x524> + fef0: f8d9 3000 ldr.w r3, [r9] + fef4: e9dd 0102 ldrd r0, r1, [sp, #8] + fef8: f109 0904 add.w r9, r9, #4 + fefc: e9c3 0100 strd r0, r1, [r3] + ff00: e7d2 b.n fea8 <_vsscanf+0x524> + ff02: f8d9 3000 ldr.w r3, [r9] + ff06: f109 0904 add.w r9, r9, #4 + ff0a: f1ba 0f00 cmp.w sl, #0 + ff0e: d1c9 bne.n fea4 <_vsscanf+0x520> + ff10: 9802 ldr r0, [sp, #8] + ff12: 6018 str r0, [r3, #0] + ff14: e7c8 b.n fea8 <_vsscanf+0x524> + ff16: f7ff fd15 bl f944 + ff1a: f8dd c004 ldr.w ip, [sp, #4] + ff1e: e6b2 b.n fc86 <_vsscanf+0x302> + ff20: f7ff fcf8 bl f914 + ff24: f8dd c004 ldr.w ip, [sp, #4] + ff28: e9cd 0102 strd r0, r1, [sp, #8] + ff2c: e6ad b.n fc8a <_vsscanf+0x306> + ff2e: 4620 mov r0, r4 + ff30: a907 add r1, sp, #28 + ff32: f8cd c004 str.w ip, [sp, #4] + ff36: f7ff fc97 bl f868 <_parse_integer_fixup_radix> + ff3a: 9b06 ldr r3, [sp, #24] + ff3c: f8dd c004 ldr.w ip, [sp, #4] + ff40: 1b1a subs r2, r3, r4 + ff42: 4296 cmp r6, r2 + ff44: f6bf aec6 bge.w fcd4 <_vsscanf+0x350> + ff48: 9807 ldr r0, [sp, #28] + ff4a: e6a9 b.n fca0 <_vsscanf+0x31c> + ff4c: f8bd 0008 ldrh.w r0, [sp, #8] + ff50: 8018 strh r0, [r3, #0] + ff52: e7a9 b.n fea8 <_vsscanf+0x524> + ff54: f89d 1008 ldrb.w r1, [sp, #8] + ff58: 7019 strb r1, [r3, #0] + ff5a: e7a5 b.n fea8 <_vsscanf+0x524> + ff5c: 2b6c cmp r3, #108 ; 0x6c + ff5e: d001 beq.n ff64 <_vsscanf+0x5e0> + ff60: 4615 mov r5, r2 + ff62: e558 b.n fa16 <_vsscanf+0x92> + ff64: 78ab ldrb r3, [r5, #2] + ff66: f04f 0c4c mov.w ip, #76 ; 0x4c + ff6a: 3502 adds r5, #2 + ff6c: e553 b.n fa16 <_vsscanf+0x92> + ff6e: bf00 nop + +0000ff70 <_sscanf>: + ff70: b40e push {r1, r2, r3} + ff72: b500 push {lr} + ff74: b082 sub sp, #8 + ff76: ab03 add r3, sp, #12 + ff78: f853 1b04 ldr.w r1, [r3], #4 + ff7c: 461a mov r2, r3 + ff7e: 9301 str r3, [sp, #4] + ff80: f7ff fd00 bl f984 <_vsscanf> + ff84: b002 add sp, #8 + ff86: f85d eb04 ldr.w lr, [sp], #4 + ff8a: b003 add sp, #12 + ff8c: 4770 bx lr + ff8e: bf00 nop + +0000ff90 : + ff90: fbb0 f0f2 udiv r0, r0, r2 + ff94: 2100 movs r1, #0 + ff96: 4770 bx lr + +0000ff98 : + ff98: fb90 f0f2 sdiv r0, r0, r2 + ff9c: 17c1 asrs r1, r0, #31 + ff9e: 4770 bx lr + +0000ffa0 : + ffa0: 4601 mov r1, r0 + ffa2: fbb0 f0f2 udiv r0, r0, r2 + ffa6: fb02 1110 mls r1, r2, r0, r1 + ffaa: 6019 str r1, [r3, #0] + ffac: 2100 movs r1, #0 + ffae: 4770 bx lr + +0000ffb0 : + ffb0: fb90 f1f2 sdiv r1, r0, r2 + ffb4: fb02 0211 mls r2, r2, r1, r0 + ffb8: 4608 mov r0, r1 + ffba: 601a str r2, [r3, #0] + ffbc: 17c9 asrs r1, r1, #31 + ffbe: 4770 bx lr + +0000ffc0 <_strpbrk>: + ffc0: b430 push {r4, r5} + ffc2: 7804 ldrb r4, [r0, #0] + ffc4: b17c cbz r4, ffe6 <_strpbrk+0x26> + ffc6: 780d ldrb r5, [r1, #0] + ffc8: b14d cbz r5, ffde <_strpbrk+0x1e> + ffca: 42a5 cmp r5, r4 + ffcc: d00c beq.n ffe8 <_strpbrk+0x28> + ffce: 460a mov r2, r1 + ffd0: e001 b.n ffd6 <_strpbrk+0x16> + ffd2: 429c cmp r4, r3 + ffd4: d008 beq.n ffe8 <_strpbrk+0x28> + ffd6: f812 3f01 ldrb.w r3, [r2, #1]! + ffda: 2b00 cmp r3, #0 + ffdc: d1f9 bne.n ffd2 <_strpbrk+0x12> + ffde: f810 4f01 ldrb.w r4, [r0, #1]! + ffe2: 2c00 cmp r4, #0 + ffe4: d1f0 bne.n ffc8 <_strpbrk+0x8> + ffe6: 4620 mov r0, r4 + ffe8: bc30 pop {r4, r5} + ffea: 4770 bx lr + +0000ffec <_strchr>: + ffec: 7803 ldrb r3, [r0, #0] + ffee: b2c9 uxtb r1, r1 + fff0: 428b cmp r3, r1 + fff2: d006 beq.n 10002 <_strchr+0x16> + fff4: b123 cbz r3, 10000 <_strchr+0x14> + fff6: f810 3f01 ldrb.w r3, [r0, #1]! + fffa: 428b cmp r3, r1 + fffc: d1fa bne.n fff4 <_strchr+0x8> + fffe: 4770 bx lr + 10000: 4618 mov r0, r3 + 10002: 4770 bx lr + +00010004 : + 10004: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 10008: 2ac0 cmp r2, #192 ; 0xc0 + 1000a: b083 sub sp, #12 + 1000c: d00d beq.n 1002a + 1000e: f5b2 7f80 cmp.w r2, #256 ; 0x100 + 10012: f000 80f9 beq.w 10208 + 10016: 2a80 cmp r2, #128 ; 0x80 + 10018: bf04 itt eq + 1001a: 260a moveq r6, #10 + 1001c: f8c0 6200 streq.w r6, [r0, #512] ; 0x200 + 10020: d006 beq.n 10030 + 10022: 2001 movs r0, #1 + 10024: b003 add sp, #12 + 10026: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 1002a: 260c movs r6, #12 + 1002c: f8c0 6200 str.w r6, [r0, #512] ; 0x200 + 10030: 4604 mov r4, r0 + 10032: ea4f 1862 mov.w r8, r2, asr #5 + 10036: 1f05 subs r5, r0, #4 + 10038: 2300 movs r3, #0 + 1003a: 784f ldrb r7, [r1, #1] + 1003c: f891 e000 ldrb.w lr, [r1] + 10040: f891 c003 ldrb.w ip, [r1, #3] + 10044: 043f lsls r7, r7, #16 + 10046: ea47 670e orr.w r7, r7, lr, lsl #24 + 1004a: f891 e002 ldrb.w lr, [r1, #2] + 1004e: ea47 070c orr.w r7, r7, ip + 10052: 3301 adds r3, #1 + 10054: ea47 270e orr.w r7, r7, lr, lsl #8 + 10058: 4598 cmp r8, r3 + 1005a: f845 7f04 str.w r7, [r5, #4]! + 1005e: f101 0104 add.w r1, r1, #4 + 10062: dcea bgt.n 1003a + 10064: 2ac0 cmp r2, #192 ; 0xc0 + 10066: f000 8170 beq.w 1034a + 1006a: f5b2 7f80 cmp.w r2, #256 ; 0x100 + 1006e: f000 80cf beq.w 10210 + 10072: 2a80 cmp r2, #128 ; 0x80 + 10074: f000 8133 beq.w 102de + 10078: f241 7388 movw r3, #6024 ; 0x1788 + 1007c: 4680 mov r8, r0 + 1007e: f2c0 0303 movt r3, #3 + 10082: 6805 ldr r5, [r0, #0] + 10084: f642 0480 movw r4, #10368 ; 0x2880 + 10088: f500 7e88 add.w lr, r0, #272 ; 0x110 + 1008c: f108 0c10 add.w ip, r8, #16 + 10090: 4671 mov r1, lr + 10092: 4662 mov r2, ip + 10094: f2c0 0403 movt r4, #3 + 10098: f8c0 5100 str.w r5, [r0, #256] ; 0x100 + 1009c: f8d8 7004 ldr.w r7, [r8, #4] + 100a0: 2501 movs r5, #1 + 100a2: f8c0 7104 str.w r7, [r0, #260] ; 0x104 + 100a6: f8d8 7008 ldr.w r7, [r8, #8] + 100aa: f8c0 7108 str.w r7, [r0, #264] ; 0x108 + 100ae: f8d8 700c ldr.w r7, [r8, #12] + 100b2: f8c0 710c str.w r7, [r0, #268] ; 0x10c + 100b6: f852 0c20 ldr.w r0, [r2, #-32] + 100ba: 3501 adds r5, #1 + 100bc: fa5f f880 uxtb.w r8, r0 + 100c0: 0e07 lsrs r7, r0, #24 + 100c2: eb03 0888 add.w r8, r3, r8, lsl #2 + 100c6: eb03 0787 add.w r7, r3, r7, lsl #2 + 100ca: f3c0 4a07 ubfx sl, r0, #16, #8 + 100ce: f8d8 9428 ldr.w r9, [r8, #1064] ; 0x428 + 100d2: eb03 0a8a add.w sl, r3, sl, lsl #2 + 100d6: f8d7 8828 ldr.w r8, [r7, #2088] ; 0x828 + 100da: f3c0 2707 ubfx r7, r0, #8, #8 + 100de: eb04 0787 add.w r7, r4, r7, lsl #2 + 100e2: f8da 0c28 ldr.w r0, [sl, #3112] ; 0xc28 + 100e6: ea89 0808 eor.w r8, r9, r8 + 100ea: f857 7cd0 ldr.w r7, [r7, #-208] + 100ee: ea88 0000 eor.w r0, r8, r0 + 100f2: 4078 eors r0, r7 + 100f4: 6008 str r0, [r1, #0] + 100f6: f852 0c1c ldr.w r0, [r2, #-28] + 100fa: 42b5 cmp r5, r6 + 100fc: fa5f f880 uxtb.w r8, r0 + 10100: ea4f 6710 mov.w r7, r0, lsr #24 + 10104: eb03 0888 add.w r8, r3, r8, lsl #2 + 10108: eb03 0787 add.w r7, r3, r7, lsl #2 + 1010c: f3c0 4a07 ubfx sl, r0, #16, #8 + 10110: f8d8 9428 ldr.w r9, [r8, #1064] ; 0x428 + 10114: eb03 0a8a add.w sl, r3, sl, lsl #2 + 10118: f8d7 8828 ldr.w r8, [r7, #2088] ; 0x828 + 1011c: f3c0 2707 ubfx r7, r0, #8, #8 + 10120: eb04 0787 add.w r7, r4, r7, lsl #2 + 10124: f8da 0c28 ldr.w r0, [sl, #3112] ; 0xc28 + 10128: ea89 0808 eor.w r8, r9, r8 + 1012c: f857 7cd0 ldr.w r7, [r7, #-208] + 10130: ea88 0000 eor.w r0, r8, r0 + 10134: ea80 0007 eor.w r0, r0, r7 + 10138: 6048 str r0, [r1, #4] + 1013a: f852 0c18 ldr.w r0, [r2, #-24] + 1013e: f101 0110 add.w r1, r1, #16 + 10142: fa5f f880 uxtb.w r8, r0 + 10146: ea4f 6710 mov.w r7, r0, lsr #24 + 1014a: eb03 0888 add.w r8, r3, r8, lsl #2 + 1014e: eb03 0787 add.w r7, r3, r7, lsl #2 + 10152: f3c0 4a07 ubfx sl, r0, #16, #8 + 10156: f8d8 9428 ldr.w r9, [r8, #1064] ; 0x428 + 1015a: eb03 0a8a add.w sl, r3, sl, lsl #2 + 1015e: f8d7 8828 ldr.w r8, [r7, #2088] ; 0x828 + 10162: f3c0 2707 ubfx r7, r0, #8, #8 + 10166: eb04 0787 add.w r7, r4, r7, lsl #2 + 1016a: f8da 0c28 ldr.w r0, [sl, #3112] ; 0xc28 + 1016e: ea89 0808 eor.w r8, r9, r8 + 10172: f857 7cd0 ldr.w r7, [r7, #-208] + 10176: ea88 0000 eor.w r0, r8, r0 + 1017a: ea80 0007 eor.w r0, r0, r7 + 1017e: f841 0c08 str.w r0, [r1, #-8] + 10182: f852 0c14 ldr.w r0, [r2, #-20] + 10186: f1a2 0210 sub.w r2, r2, #16 + 1018a: fa5f f880 uxtb.w r8, r0 + 1018e: ea4f 6710 mov.w r7, r0, lsr #24 + 10192: eb03 0888 add.w r8, r3, r8, lsl #2 + 10196: eb03 0787 add.w r7, r3, r7, lsl #2 + 1019a: f3c0 4a07 ubfx sl, r0, #16, #8 + 1019e: f8d8 9428 ldr.w r9, [r8, #1064] ; 0x428 + 101a2: eb03 0a8a add.w sl, r3, sl, lsl #2 + 101a6: f8d7 8828 ldr.w r8, [r7, #2088] ; 0x828 + 101aa: f3c0 2707 ubfx r7, r0, #8, #8 + 101ae: eb04 0787 add.w r7, r4, r7, lsl #2 + 101b2: f8da 0c28 ldr.w r0, [sl, #3112] ; 0xc28 + 101b6: ea89 0808 eor.w r8, r9, r8 + 101ba: f857 7cd0 ldr.w r7, [r7, #-208] + 101be: ea88 0000 eor.w r0, r8, r0 + 101c2: ea80 0007 eor.w r0, r0, r7 + 101c6: f841 0c04 str.w r0, [r1, #-4] + 101ca: f47f af74 bne.w 100b6 + 101ce: 012b lsls r3, r5, #4 + 101d0: f1c3 0310 rsb r3, r3, #16 + 101d4: 449c add ip, r3 + 101d6: f105 5580 add.w r5, r5, #268435456 ; 0x10000000 + 101da: f85c 3c20 ldr.w r3, [ip, #-32] + 101de: 3d01 subs r5, #1 + 101e0: 012d lsls r5, r5, #4 + 101e2: f84e 3005 str.w r3, [lr, r5] + 101e6: f85c 3c1c ldr.w r3, [ip, #-28] + 101ea: 44ae add lr, r5 + 101ec: f8ce 3004 str.w r3, [lr, #4] + 101f0: f85c 3c18 ldr.w r3, [ip, #-24] + 101f4: 2000 movs r0, #0 + 101f6: f8ce 3008 str.w r3, [lr, #8] + 101fa: f85c 3c14 ldr.w r3, [ip, #-20] + 101fe: f8ce 300c str.w r3, [lr, #12] + 10202: b003 add sp, #12 + 10204: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 10208: 260e movs r6, #14 + 1020a: f8c0 6200 str.w r6, [r0, #512] ; 0x200 + 1020e: e70f b.n 10030 + 10210: f8df e1b8 ldr.w lr, [pc, #440] ; 103cc + 10214: f100 08e0 add.w r8, r0, #224 ; 0xe0 + 10218: f10e 0304 add.w r3, lr, #4 + 1021c: 69e7 ldr r7, [r4, #28] + 1021e: f85e af04 ldr.w sl, [lr, #4]! + 10222: 0e3d lsrs r5, r7, #24 + 10224: 6822 ldr r2, [r4, #0] + 10226: b2f9 uxtb r1, r7 + 10228: eb03 0585 add.w r5, r3, r5, lsl #2 + 1022c: eb03 0181 add.w r1, r3, r1, lsl #2 + 10230: f3c7 4907 ubfx r9, r7, #16, #8 + 10234: 6aad ldr r5, [r5, #40] ; 0x28 + 10236: ea8a 0a02 eor.w sl, sl, r2 + 1023a: f8d1 c028 ldr.w ip, [r1, #40] ; 0x28 + 1023e: eb03 0989 add.w r9, r3, r9, lsl #2 + 10242: f3c7 2107 ubfx r1, r7, #8, #8 + 10246: f8d9 2028 ldr.w r2, [r9, #40] ; 0x28 + 1024a: ea85 050a eor.w r5, r5, sl + 1024e: eb03 0181 add.w r1, r3, r1, lsl #2 + 10252: ea85 250c eor.w r5, r5, ip, lsl #8 + 10256: 6a89 ldr r1, [r1, #40] ; 0x28 + 10258: ea85 6502 eor.w r5, r5, r2, lsl #24 + 1025c: 6862 ldr r2, [r4, #4] + 1025e: ea85 4501 eor.w r5, r5, r1, lsl #16 + 10262: 68a1 ldr r1, [r4, #8] + 10264: ea85 0c02 eor.w ip, r5, r2 + 10268: 68e2 ldr r2, [r4, #12] + 1026a: ea8c 0901 eor.w r9, ip, r1 + 1026e: ea89 0a02 eor.w sl, r9, r2 + 10272: ea4f 621a mov.w r2, sl, lsr #24 + 10276: eb03 0b82 add.w fp, r3, r2, lsl #2 + 1027a: f8db 2028 ldr.w r2, [fp, #40] ; 0x28 + 1027e: fa5f f18a uxtb.w r1, sl + 10282: eb03 0181 add.w r1, r3, r1, lsl #2 + 10286: 6a89 ldr r1, [r1, #40] ; 0x28 + 10288: 9201 str r2, [sp, #4] + 1028a: 6922 ldr r2, [r4, #16] + 1028c: 6225 str r5, [r4, #32] + 1028e: ea81 0b02 eor.w fp, r1, r2 + 10292: 9a01 ldr r2, [sp, #4] + 10294: f3ca 4107 ubfx r1, sl, #16, #8 + 10298: ea8b 6b02 eor.w fp, fp, r2, lsl #24 + 1029c: eb03 0181 add.w r1, r3, r1, lsl #2 + 102a0: f3ca 2207 ubfx r2, sl, #8, #8 + 102a4: 6a89 ldr r1, [r1, #40] ; 0x28 + 102a6: eb03 0282 add.w r2, r3, r2, lsl #2 + 102aa: 6a92 ldr r2, [r2, #40] ; 0x28 + 102ac: ea8b 4b01 eor.w fp, fp, r1, lsl #16 + 102b0: 6961 ldr r1, [r4, #20] + 102b2: ea8b 2b02 eor.w fp, fp, r2, lsl #8 + 102b6: 69a2 ldr r2, [r4, #24] + 102b8: ea8b 0101 eor.w r1, fp, r1 + 102bc: 404a eors r2, r1 + 102be: 4057 eors r7, r2 + 102c0: f8c4 c024 str.w ip, [r4, #36] ; 0x24 + 102c4: f8c4 9028 str.w r9, [r4, #40] ; 0x28 + 102c8: f8c4 a02c str.w sl, [r4, #44] ; 0x2c + 102cc: f8c4 b030 str.w fp, [r4, #48] ; 0x30 + 102d0: 6361 str r1, [r4, #52] ; 0x34 + 102d2: 63e7 str r7, [r4, #60] ; 0x3c + 102d4: 63a2 str r2, [r4, #56] ; 0x38 + 102d6: 3420 adds r4, #32 + 102d8: 4544 cmp r4, r8 + 102da: d19f bne.n 1021c + 102dc: e6d2 b.n 10084 + 102de: f8df e0ec ldr.w lr, [pc, #236] ; 103cc + 102e2: f100 08a0 add.w r8, r0, #160 ; 0xa0 + 102e6: f10e 0304 add.w r3, lr, #4 + 102ea: 68e7 ldr r7, [r4, #12] + 102ec: f85e 5f04 ldr.w r5, [lr, #4]! + 102f0: 0e39 lsrs r1, r7, #24 + 102f2: 6822 ldr r2, [r4, #0] + 102f4: eb03 0181 add.w r1, r3, r1, lsl #2 + 102f8: fa5f fc87 uxtb.w ip, r7 + 102fc: f8d1 9028 ldr.w r9, [r1, #40] ; 0x28 + 10300: eb03 0c8c add.w ip, r3, ip, lsl #2 + 10304: f3c7 4107 ubfx r1, r7, #16, #8 + 10308: 406a eors r2, r5 + 1030a: eb03 0181 add.w r1, r3, r1, lsl #2 + 1030e: f8dc 5028 ldr.w r5, [ip, #40] ; 0x28 + 10312: f3c7 2c07 ubfx ip, r7, #8, #8 + 10316: ea82 0209 eor.w r2, r2, r9 + 1031a: 6a89 ldr r1, [r1, #40] ; 0x28 + 1031c: eb03 0c8c add.w ip, r3, ip, lsl #2 + 10320: ea82 2505 eor.w r5, r2, r5, lsl #8 + 10324: f8dc 2028 ldr.w r2, [ip, #40] ; 0x28 + 10328: ea85 6501 eor.w r5, r5, r1, lsl #24 + 1032c: 6861 ldr r1, [r4, #4] + 1032e: ea85 4502 eor.w r5, r5, r2, lsl #16 + 10332: 68a2 ldr r2, [r4, #8] + 10334: 4069 eors r1, r5 + 10336: 404a eors r2, r1 + 10338: 4057 eors r7, r2 + 1033a: 6125 str r5, [r4, #16] + 1033c: 6161 str r1, [r4, #20] + 1033e: 61e7 str r7, [r4, #28] + 10340: 61a2 str r2, [r4, #24] + 10342: 3410 adds r4, #16 + 10344: 4544 cmp r4, r8 + 10346: d1d0 bne.n 102ea + 10348: e69c b.n 10084 + 1034a: f8df e080 ldr.w lr, [pc, #128] ; 103cc + 1034e: f100 08c0 add.w r8, r0, #192 ; 0xc0 + 10352: f10e 0304 add.w r3, lr, #4 + 10356: 6967 ldr r7, [r4, #20] + 10358: f85e 5f04 ldr.w r5, [lr, #4]! + 1035c: 0e39 lsrs r1, r7, #24 + 1035e: 6822 ldr r2, [r4, #0] + 10360: eb03 0181 add.w r1, r3, r1, lsl #2 + 10364: fa5f fc87 uxtb.w ip, r7 + 10368: f8d1 9028 ldr.w r9, [r1, #40] ; 0x28 + 1036c: eb03 0c8c add.w ip, r3, ip, lsl #2 + 10370: f3c7 4107 ubfx r1, r7, #16, #8 + 10374: 406a eors r2, r5 + 10376: eb03 0181 add.w r1, r3, r1, lsl #2 + 1037a: f8dc 5028 ldr.w r5, [ip, #40] ; 0x28 + 1037e: f3c7 2c07 ubfx ip, r7, #8, #8 + 10382: ea82 0209 eor.w r2, r2, r9 + 10386: 6a89 ldr r1, [r1, #40] ; 0x28 + 10388: eb03 0c8c add.w ip, r3, ip, lsl #2 + 1038c: ea82 2505 eor.w r5, r2, r5, lsl #8 + 10390: f8dc 2028 ldr.w r2, [ip, #40] ; 0x28 + 10394: ea85 6501 eor.w r5, r5, r1, lsl #24 + 10398: 6861 ldr r1, [r4, #4] + 1039a: ea85 4502 eor.w r5, r5, r2, lsl #16 + 1039e: 68a2 ldr r2, [r4, #8] + 103a0: ea85 0c01 eor.w ip, r5, r1 + 103a4: 68e1 ldr r1, [r4, #12] + 103a6: ea8c 0902 eor.w r9, ip, r2 + 103aa: 6922 ldr r2, [r4, #16] + 103ac: ea89 0101 eor.w r1, r9, r1 + 103b0: 404a eors r2, r1 + 103b2: 4057 eors r7, r2 + 103b4: 61a5 str r5, [r4, #24] + 103b6: f8c4 c01c str.w ip, [r4, #28] + 103ba: f8c4 9020 str.w r9, [r4, #32] + 103be: 6261 str r1, [r4, #36] ; 0x24 + 103c0: 62e7 str r7, [r4, #44] ; 0x2c + 103c2: 62a2 str r2, [r4, #40] ; 0x28 + 103c4: 3418 adds r4, #24 + 103c6: 4544 cmp r4, r8 + 103c8: d1c5 bne.n 10356 + 103ca: e65b b.n 10084 + 103cc: 00031784 .word 0x00031784 + +000103d0 : + 103d0: f642 0380 movw r3, #10368 ; 0x2880 + 103d4: f2c0 0303 movt r3, #3 + 103d8: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 103dc: b0a7 sub sp, #156 ; 0x9c + 103de: 9020 str r0, [sp, #128] ; 0x80 + 103e0: 7848 ldrb r0, [r1, #1] + 103e2: 780f ldrb r7, [r1, #0] + 103e4: f891 a00d ldrb.w sl, [r1, #13] + 103e8: f891 8005 ldrb.w r8, [r1, #5] + 103ec: f891 e009 ldrb.w lr, [r1, #9] + 103f0: 7b0d ldrb r5, [r1, #12] + 103f2: 790c ldrb r4, [r1, #4] + 103f4: 7a0e ldrb r6, [r1, #8] + 103f6: f891 b003 ldrb.w fp, [r1, #3] + 103fa: 0400 lsls r0, r0, #16 + 103fc: ea40 6007 orr.w r0, r0, r7, lsl #24 + 10400: ea4f 4a0a mov.w sl, sl, lsl #16 + 10404: ea4f 4808 mov.w r8, r8, lsl #16 + 10408: ea4f 4e0e mov.w lr, lr, lsl #16 + 1040c: f891 900f ldrb.w r9, [r1, #15] + 10410: f891 c007 ldrb.w ip, [r1, #7] + 10414: ea4a 6a05 orr.w sl, sl, r5, lsl #24 + 10418: 7acf ldrb r7, [r1, #11] + 1041a: 7b8d ldrb r5, [r1, #14] + 1041c: ea48 6804 orr.w r8, r8, r4, lsl #24 + 10420: ea4e 6e06 orr.w lr, lr, r6, lsl #24 + 10424: 798c ldrb r4, [r1, #6] + 10426: 788e ldrb r6, [r1, #2] + 10428: ea40 000b orr.w r0, r0, fp + 1042c: f891 b00a ldrb.w fp, [r1, #10] + 10430: 9920 ldr r1, [sp, #128] ; 0x80 + 10432: ea40 2006 orr.w r0, r0, r6, lsl #8 + 10436: 6809 ldr r1, [r1, #0] + 10438: 9e20 ldr r6, [sp, #128] ; 0x80 + 1043a: 911f str r1, [sp, #124] ; 0x7c + 1043c: 9920 ldr r1, [sp, #128] ; 0x80 + 1043e: ea4a 0909 orr.w r9, sl, r9 + 10442: 68c9 ldr r1, [r1, #12] + 10444: 68b6 ldr r6, [r6, #8] + 10446: 911c str r1, [sp, #112] ; 0x70 + 10448: 9920 ldr r1, [sp, #128] ; 0x80 + 1044a: ea49 2905 orr.w r9, r9, r5, lsl #8 + 1044e: 6849 ldr r1, [r1, #4] + 10450: 9d1c ldr r5, [sp, #112] ; 0x70 + 10452: 911e str r1, [sp, #120] ; 0x78 + 10454: 991f ldr r1, [sp, #124] ; 0x7c + 10456: ea4e 0707 orr.w r7, lr, r7 + 1045a: 4048 eors r0, r1 + 1045c: 961d str r6, [sp, #116] ; 0x74 + 1045e: ea47 270b orr.w r7, r7, fp, lsl #8 + 10462: ea89 0b05 eor.w fp, r9, r5 + 10466: 991d ldr r1, [sp, #116] ; 0x74 + 10468: ea4f 6910 mov.w r9, r0, lsr #24 + 1046c: fa5f f58b uxtb.w r5, fp + 10470: ea48 0c0c orr.w ip, r8, ip + 10474: 9e1e ldr r6, [sp, #120] ; 0x78 + 10476: eb03 0989 add.w r9, r3, r9, lsl #2 + 1047a: eb03 0585 add.w r5, r3, r5, lsl #2 + 1047e: 4079 eors r1, r7 + 10480: f8d5 5730 ldr.w r5, [r5, #1840] ; 0x730 + 10484: ea4c 2404 orr.w r4, ip, r4, lsl #8 + 10488: f8d9 9330 ldr.w r9, [r9, #816] ; 0x330 + 1048c: 4074 eors r4, r6 + 1048e: ea4f 681b mov.w r8, fp, lsr #24 + 10492: fa5f fc81 uxtb.w ip, r1 + 10496: b2e6 uxtb r6, r4 + 10498: 0e0f lsrs r7, r1, #24 + 1049a: ea89 0905 eor.w r9, r9, r5 + 1049e: eb03 0888 add.w r8, r3, r8, lsl #2 + 104a2: 9d20 ldr r5, [sp, #128] ; 0x80 + 104a4: eb03 0c8c add.w ip, r3, ip, lsl #2 + 104a8: f8d8 8330 ldr.w r8, [r8, #816] ; 0x330 + 104ac: f8dc c730 ldr.w ip, [ip, #1840] ; 0x730 + 104b0: eb03 0686 add.w r6, r3, r6, lsl #2 + 104b4: eb03 0787 add.w r7, r3, r7, lsl #2 + 104b8: f8d6 6730 ldr.w r6, [r6, #1840] ; 0x730 + 104bc: f8d7 7330 ldr.w r7, [r7, #816] ; 0x330 + 104c0: ea4f 6a14 mov.w sl, r4, lsr #24 + 104c4: fa5f fe80 uxtb.w lr, r0 + 104c8: 692d ldr r5, [r5, #16] + 104ca: ea88 0c0c eor.w ip, r8, ip + 104ce: eb03 0a8a add.w sl, r3, sl, lsl #2 + 104d2: eb03 0e8e add.w lr, r3, lr, lsl #2 + 104d6: ea87 0806 eor.w r8, r7, r6 + 104da: f8de e730 ldr.w lr, [lr, #1840] ; 0x730 + 104de: f8da a330 ldr.w sl, [sl, #816] ; 0x330 + 104e2: f3c1 4607 ubfx r6, r1, #16, #8 + 104e6: 950d str r5, [sp, #52] ; 0x34 + 104e8: f8cd c088 str.w ip, [sp, #136] ; 0x88 + 104ec: f3c4 4c07 ubfx ip, r4, #16, #8 + 104f0: eb03 0c8c add.w ip, r3, ip, lsl #2 + 104f4: eb03 0686 add.w r6, r3, r6, lsl #2 + 104f8: f8dc 5b30 ldr.w r5, [ip, #2864] ; 0xb30 + 104fc: ea8a 0a0e eor.w sl, sl, lr + 10500: f8d6 eb30 ldr.w lr, [r6, #2864] ; 0xb30 + 10504: 9e0d ldr r6, [sp, #52] ; 0x34 + 10506: f3c1 2107 ubfx r1, r1, #8, #8 + 1050a: 9521 str r5, [sp, #132] ; 0x84 + 1050c: eb03 0181 add.w r1, r3, r1, lsl #2 + 10510: ea89 0906 eor.w r9, r9, r6 + 10514: f3c4 2407 ubfx r4, r4, #8, #8 + 10518: f3cb 4607 ubfx r6, fp, #16, #8 + 1051c: f3cb 2b07 ubfx fp, fp, #8, #8 + 10520: f8d1 5f30 ldr.w r5, [r1, #3888] ; 0xf30 + 10524: eb03 0484 add.w r4, r3, r4, lsl #2 + 10528: 9921 ldr r1, [sp, #132] ; 0x84 + 1052a: eb03 0686 add.w r6, r3, r6, lsl #2 + 1052e: eb03 0b8b add.w fp, r3, fp, lsl #2 + 10532: f8d6 cb30 ldr.w ip, [r6, #2864] ; 0xb30 + 10536: f8d4 6f30 ldr.w r6, [r4, #3888] ; 0xf30 + 1053a: f8db 4f30 ldr.w r4, [fp, #3888] ; 0xf30 + 1053e: f8dd b080 ldr.w fp, [sp, #128] ; 0x80 + 10542: ea89 0901 eor.w r9, r9, r1 + 10546: ea89 0505 eor.w r5, r9, r5 + 1054a: f8db 101c ldr.w r1, [fp, #28] + 1054e: f8dd 9088 ldr.w r9, [sp, #136] ; 0x88 + 10552: f3c0 4707 ubfx r7, r0, #16, #8 + 10556: eb03 0787 add.w r7, r3, r7, lsl #2 + 1055a: f8d7 7b30 ldr.w r7, [r7, #2864] ; 0xb30 + 1055e: ea89 0b01 eor.w fp, r9, r1 + 10562: f8dd 9080 ldr.w r9, [sp, #128] ; 0x80 + 10566: 9920 ldr r1, [sp, #128] ; 0x80 + 10568: ea8b 0b07 eor.w fp, fp, r7 + 1056c: f3c0 2007 ubfx r0, r0, #8, #8 + 10570: f8d9 7018 ldr.w r7, [r9, #24] + 10574: eb03 0080 add.w r0, r3, r0, lsl #2 + 10578: f8d0 0f30 ldr.w r0, [r0, #3888] ; 0xf30 + 1057c: 6949 ldr r1, [r1, #20] + 1057e: ea88 0707 eor.w r7, r8, r7 + 10582: ea8b 0b06 eor.w fp, fp, r6 + 10586: ea87 0c0c eor.w ip, r7, ip + 1058a: ea8c 0600 eor.w r6, ip, r0 + 1058e: ea8a 0a01 eor.w sl, sl, r1 + 10592: ea4f 6915 mov.w r9, r5, lsr #24 + 10596: fa5f f18b uxtb.w r1, fp + 1059a: ea4f 681b mov.w r8, fp, lsr #24 + 1059e: fa5f fc86 uxtb.w ip, r6 + 105a2: eb03 0989 add.w r9, r3, r9, lsl #2 + 105a6: eb03 0181 add.w r1, r3, r1, lsl #2 + 105aa: f8d1 1730 ldr.w r1, [r1, #1840] ; 0x730 + 105ae: f8d9 9330 ldr.w r9, [r9, #816] ; 0x330 + 105b2: eb03 0888 add.w r8, r3, r8, lsl #2 + 105b6: eb03 0c8c add.w ip, r3, ip, lsl #2 + 105ba: f8d8 8330 ldr.w r8, [r8, #816] ; 0x330 + 105be: f8dc c730 ldr.w ip, [ip, #1840] ; 0x730 + 105c2: ea8a 0e0e eor.w lr, sl, lr + 105c6: ea89 0901 eor.w r9, r9, r1 + 105ca: 9920 ldr r1, [sp, #128] ; 0x80 + 105cc: ea8e 0e04 eor.w lr, lr, r4 + 105d0: ea88 0c0c eor.w ip, r8, ip + 105d4: 6a09 ldr r1, [r1, #32] + 105d6: f8cd c08c str.w ip, [sp, #140] ; 0x8c + 105da: f3ce 4c07 ubfx ip, lr, #16, #8 + 105de: eb03 0c8c add.w ip, r3, ip, lsl #2 + 105e2: 910c str r1, [sp, #48] ; 0x30 + 105e4: ea4f 6a1e mov.w sl, lr, lsr #24 + 105e8: f8dc 1b30 ldr.w r1, [ip, #2864] ; 0xb30 + 105ec: fa5f f08e uxtb.w r0, lr + 105f0: b2ef uxtb r7, r5 + 105f2: 0e34 lsrs r4, r6, #24 + 105f4: eb03 0a8a add.w sl, r3, sl, lsl #2 + 105f8: eb03 0080 add.w r0, r3, r0, lsl #2 + 105fc: eb03 0787 add.w r7, r3, r7, lsl #2 + 10600: eb03 0484 add.w r4, r3, r4, lsl #2 + 10604: f8da a330 ldr.w sl, [sl, #816] ; 0x330 + 10608: f8d0 0730 ldr.w r0, [r0, #1840] ; 0x730 + 1060c: f8d7 7730 ldr.w r7, [r7, #1840] ; 0x730 + 10610: f8d4 4330 ldr.w r4, [r4, #816] ; 0x330 + 10614: 9121 str r1, [sp, #132] ; 0x84 + 10616: f3cb 4107 ubfx r1, fp, #16, #8 + 1061a: eb03 0181 add.w r1, r3, r1, lsl #2 + 1061e: ea84 0c00 eor.w ip, r4, r0 + 10622: ea8a 0807 eor.w r8, sl, r7 + 10626: f3c5 4407 ubfx r4, r5, #16, #8 + 1062a: 9f0c ldr r7, [sp, #48] ; 0x30 + 1062c: f3c6 4007 ubfx r0, r6, #16, #8 + 10630: f8d1 1b30 ldr.w r1, [r1, #2864] ; 0xb30 + 10634: f3c5 2507 ubfx r5, r5, #8, #8 + 10638: f3c6 2607 ubfx r6, r6, #8, #8 + 1063c: f3cb 2b07 ubfx fp, fp, #8, #8 + 10640: eb03 0080 add.w r0, r3, r0, lsl #2 + 10644: eb03 0686 add.w r6, r3, r6, lsl #2 + 10648: eb03 0585 add.w r5, r3, r5, lsl #2 + 1064c: eb03 0b8b add.w fp, r3, fp, lsl #2 + 10650: eb03 0484 add.w r4, r3, r4, lsl #2 + 10654: f8d4 4b30 ldr.w r4, [r4, #2864] ; 0xb30 + 10658: f8d0 ab30 ldr.w sl, [r0, #2864] ; 0xb30 + 1065c: ea89 0907 eor.w r9, r9, r7 + 10660: 9122 str r1, [sp, #136] ; 0x88 + 10662: f3ce 2e07 ubfx lr, lr, #8, #8 + 10666: f8d6 1f30 ldr.w r1, [r6, #3888] ; 0xf30 + 1066a: f8db 7f30 ldr.w r7, [fp, #3888] ; 0xf30 + 1066e: f8d5 6f30 ldr.w r6, [r5, #3888] ; 0xf30 + 10672: f8dd b080 ldr.w fp, [sp, #128] ; 0x80 + 10676: 9d21 ldr r5, [sp, #132] ; 0x84 + 10678: eb03 0e8e add.w lr, r3, lr, lsl #2 + 1067c: f8de 0f30 ldr.w r0, [lr, #3888] ; 0xf30 + 10680: ea89 0905 eor.w r9, r9, r5 + 10684: f8dd e08c ldr.w lr, [sp, #140] ; 0x8c + 10688: f8db 502c ldr.w r5, [fp, #44] ; 0x2c + 1068c: ea89 0101 eor.w r1, r9, r1 + 10690: ea8e 0b05 eor.w fp, lr, r5 + 10694: 9d20 ldr r5, [sp, #128] ; 0x80 + 10696: f8dd 9080 ldr.w r9, [sp, #128] ; 0x80 + 1069a: 6a6d ldr r5, [r5, #36] ; 0x24 + 1069c: ea8b 0b04 eor.w fp, fp, r4 + 106a0: f8d9 4028 ldr.w r4, [r9, #40] ; 0x28 + 106a4: ea88 0805 eor.w r8, r8, r5 + 106a8: 9d22 ldr r5, [sp, #136] ; 0x88 + 106aa: ea8c 0404 eor.w r4, ip, r4 + 106ae: ea8b 0b00 eor.w fp, fp, r0 + 106b2: ea84 0c05 eor.w ip, r4, r5 + 106b6: ea8c 0006 eor.w r0, ip, r6 + 106ba: ea4f 6911 mov.w r9, r1, lsr #24 + 106be: fa5f f48b uxtb.w r4, fp + 106c2: ea88 0a0a eor.w sl, r8, sl + 106c6: fa5f fc80 uxtb.w ip, r0 + 106ca: ea4f 681b mov.w r8, fp, lsr #24 + 106ce: eb03 0989 add.w r9, r3, r9, lsl #2 + 106d2: eb03 0484 add.w r4, r3, r4, lsl #2 + 106d6: f8d4 4730 ldr.w r4, [r4, #1840] ; 0x730 + 106da: f8d9 9330 ldr.w r9, [r9, #816] ; 0x330 + 106de: eb03 0888 add.w r8, r3, r8, lsl #2 + 106e2: eb03 0c8c add.w ip, r3, ip, lsl #2 + 106e6: f8d8 8330 ldr.w r8, [r8, #816] ; 0x330 + 106ea: f8dc c730 ldr.w ip, [ip, #1840] ; 0x730 + 106ee: ea8a 0707 eor.w r7, sl, r7 + 106f2: ea89 0904 eor.w r9, r9, r4 + 106f6: 9c20 ldr r4, [sp, #128] ; 0x80 + 106f8: ea88 0c0c eor.w ip, r8, ip + 106fc: b2fd uxtb r5, r7 + 106fe: 0e06 lsrs r6, r0, #24 + 10700: 6b24 ldr r4, [r4, #48] ; 0x30 + 10702: f8cd c088 str.w ip, [sp, #136] ; 0x88 + 10706: eb03 0585 add.w r5, r3, r5, lsl #2 + 1070a: f3c7 4c07 ubfx ip, r7, #16, #8 + 1070e: eb03 0686 add.w r6, r3, r6, lsl #2 + 10712: f8d5 5730 ldr.w r5, [r5, #1840] ; 0x730 + 10716: f8d6 6330 ldr.w r6, [r6, #816] ; 0x330 + 1071a: ea4f 6a17 mov.w sl, r7, lsr #24 + 1071e: fa5f fe81 uxtb.w lr, r1 + 10722: eb03 0c8c add.w ip, r3, ip, lsl #2 + 10726: 940b str r4, [sp, #44] ; 0x2c + 10728: eb03 0a8a add.w sl, r3, sl, lsl #2 + 1072c: f8dc 4b30 ldr.w r4, [ip, #2864] ; 0xb30 + 10730: eb03 0e8e add.w lr, r3, lr, lsl #2 + 10734: ea86 0805 eor.w r8, r6, r5 + 10738: f8da a330 ldr.w sl, [sl, #816] ; 0x330 + 1073c: f8de e730 ldr.w lr, [lr, #1840] ; 0x730 + 10740: f3c0 4507 ubfx r5, r0, #16, #8 + 10744: 9421 str r4, [sp, #132] ; 0x84 + 10746: f3c1 4607 ubfx r6, r1, #16, #8 + 1074a: eb03 0585 add.w r5, r3, r5, lsl #2 + 1074e: f3cb 4407 ubfx r4, fp, #16, #8 + 10752: f3c1 2107 ubfx r1, r1, #8, #8 + 10756: f3c0 2007 ubfx r0, r0, #8, #8 + 1075a: ea8a 0e0e eor.w lr, sl, lr + 1075e: eb03 0080 add.w r0, r3, r0, lsl #2 + 10762: f8d5 ab30 ldr.w sl, [r5, #2864] ; 0xb30 + 10766: eb03 0181 add.w r1, r3, r1, lsl #2 + 1076a: 9d0b ldr r5, [sp, #44] ; 0x2c + 1076c: eb03 0484 add.w r4, r3, r4, lsl #2 + 10770: f3c7 2707 ubfx r7, r7, #8, #8 + 10774: f3cb 2b07 ubfx fp, fp, #8, #8 + 10778: f8d4 cb30 ldr.w ip, [r4, #2864] ; 0xb30 + 1077c: eb03 0787 add.w r7, r3, r7, lsl #2 + 10780: f8d0 4f30 ldr.w r4, [r0, #3888] ; 0xf30 + 10784: eb03 0b8b add.w fp, r3, fp, lsl #2 + 10788: f8d1 0f30 ldr.w r0, [r1, #3888] ; 0xf30 + 1078c: 9921 ldr r1, [sp, #132] ; 0x84 + 1078e: ea89 0905 eor.w r9, r9, r5 + 10792: f8d7 5f30 ldr.w r5, [r7, #3888] ; 0xf30 + 10796: f8db 7f30 ldr.w r7, [fp, #3888] ; 0xf30 + 1079a: f8dd b080 ldr.w fp, [sp, #128] ; 0x80 + 1079e: ea89 0901 eor.w r9, r9, r1 + 107a2: ea89 0404 eor.w r4, r9, r4 + 107a6: f8db 103c ldr.w r1, [fp, #60] ; 0x3c + 107aa: f8dd 9088 ldr.w r9, [sp, #136] ; 0x88 + 107ae: eb03 0686 add.w r6, r3, r6, lsl #2 + 107b2: f8d6 6b30 ldr.w r6, [r6, #2864] ; 0xb30 + 107b6: ea89 0b01 eor.w fp, r9, r1 + 107ba: f8dd 9080 ldr.w r9, [sp, #128] ; 0x80 + 107be: 9920 ldr r1, [sp, #128] ; 0x80 + 107c0: ea8b 0b06 eor.w fp, fp, r6 + 107c4: 6b49 ldr r1, [r1, #52] ; 0x34 + 107c6: f8d9 6038 ldr.w r6, [r9, #56] ; 0x38 + 107ca: ea8b 0b05 eor.w fp, fp, r5 + 107ce: ea88 0606 eor.w r6, r8, r6 + 107d2: ea8e 0e01 eor.w lr, lr, r1 + 107d6: ea4f 6914 mov.w r9, r4, lsr #24 + 107da: fa5f f18b uxtb.w r1, fp + 107de: ea86 0c0c eor.w ip, r6, ip + 107e2: eb03 0989 add.w r9, r3, r9, lsl #2 + 107e6: eb03 0181 add.w r1, r3, r1, lsl #2 + 107ea: ea8c 0500 eor.w r5, ip, r0 + 107ee: f8d1 1730 ldr.w r1, [r1, #1840] ; 0x730 + 107f2: f8d9 9330 ldr.w r9, [r9, #816] ; 0x330 + 107f6: ea4f 681b mov.w r8, fp, lsr #24 + 107fa: fa5f fc85 uxtb.w ip, r5 + 107fe: ea8e 0e0a eor.w lr, lr, sl + 10802: ea89 0901 eor.w r9, r9, r1 + 10806: eb03 0888 add.w r8, r3, r8, lsl #2 + 1080a: 9920 ldr r1, [sp, #128] ; 0x80 + 1080c: eb03 0c8c add.w ip, r3, ip, lsl #2 + 10810: ea8e 0e07 eor.w lr, lr, r7 + 10814: f8d8 8330 ldr.w r8, [r8, #816] ; 0x330 + 10818: f8dc c730 ldr.w ip, [ip, #1840] ; 0x730 + 1081c: ea4f 6a1e mov.w sl, lr, lsr #24 + 10820: fa5f f08e uxtb.w r0, lr + 10824: b2e7 uxtb r7, r4 + 10826: 0e2e lsrs r6, r5, #24 + 10828: 6c09 ldr r1, [r1, #64] ; 0x40 + 1082a: ea88 0c0c eor.w ip, r8, ip + 1082e: eb03 0a8a add.w sl, r3, sl, lsl #2 + 10832: eb03 0080 add.w r0, r3, r0, lsl #2 + 10836: eb03 0787 add.w r7, r3, r7, lsl #2 + 1083a: eb03 0686 add.w r6, r3, r6, lsl #2 + 1083e: f8da a330 ldr.w sl, [sl, #816] ; 0x330 + 10842: f8d0 0730 ldr.w r0, [r0, #1840] ; 0x730 + 10846: f8d7 7730 ldr.w r7, [r7, #1840] ; 0x730 + 1084a: f8d6 6330 ldr.w r6, [r6, #816] ; 0x330 + 1084e: 910a str r1, [sp, #40] ; 0x28 + 10850: f8cd c08c str.w ip, [sp, #140] ; 0x8c + 10854: f3ce 4c07 ubfx ip, lr, #16, #8 + 10858: eb03 0c8c add.w ip, r3, ip, lsl #2 + 1085c: f8dc 1b30 ldr.w r1, [ip, #2864] ; 0xb30 + 10860: ea8a 0807 eor.w r8, sl, r7 + 10864: 9121 str r1, [sp, #132] ; 0x84 + 10866: f3cb 4107 ubfx r1, fp, #16, #8 + 1086a: eb03 0181 add.w r1, r3, r1, lsl #2 + 1086e: ea86 0c00 eor.w ip, r6, r0 + 10872: 9f0a ldr r7, [sp, #40] ; 0x28 + 10874: f8d1 1b30 ldr.w r1, [r1, #2864] ; 0xb30 + 10878: f3c4 4607 ubfx r6, r4, #16, #8 + 1087c: f3c5 4007 ubfx r0, r5, #16, #8 + 10880: f3c4 2407 ubfx r4, r4, #8, #8 + 10884: f3c5 2507 ubfx r5, r5, #8, #8 + 10888: f3cb 2b07 ubfx fp, fp, #8, #8 + 1088c: eb03 0585 add.w r5, r3, r5, lsl #2 + 10890: eb03 0484 add.w r4, r3, r4, lsl #2 + 10894: eb03 0b8b add.w fp, r3, fp, lsl #2 + 10898: 9122 str r1, [sp, #136] ; 0x88 + 1089a: ea89 0907 eor.w r9, r9, r7 + 1089e: f8d5 1f30 ldr.w r1, [r5, #3888] ; 0xf30 + 108a2: f8db 7f30 ldr.w r7, [fp, #3888] ; 0xf30 + 108a6: f8d4 5f30 ldr.w r5, [r4, #3888] ; 0xf30 + 108aa: f8dd b080 ldr.w fp, [sp, #128] ; 0x80 + 108ae: 9c21 ldr r4, [sp, #132] ; 0x84 + 108b0: f3ce 2e07 ubfx lr, lr, #8, #8 + 108b4: eb03 0e8e add.w lr, r3, lr, lsl #2 + 108b8: eb03 0080 add.w r0, r3, r0, lsl #2 + 108bc: f8d0 ab30 ldr.w sl, [r0, #2864] ; 0xb30 + 108c0: ea89 0904 eor.w r9, r9, r4 + 108c4: f8de 0f30 ldr.w r0, [lr, #3888] ; 0xf30 + 108c8: f8db 404c ldr.w r4, [fp, #76] ; 0x4c + 108cc: f8dd e08c ldr.w lr, [sp, #140] ; 0x8c + 108d0: eb03 0686 add.w r6, r3, r6, lsl #2 + 108d4: ea8e 0b04 eor.w fp, lr, r4 + 108d8: 9c20 ldr r4, [sp, #128] ; 0x80 + 108da: ea89 0101 eor.w r1, r9, r1 + 108de: f8d6 6b30 ldr.w r6, [r6, #2864] ; 0xb30 + 108e2: f8dd 9080 ldr.w r9, [sp, #128] ; 0x80 + 108e6: 6c64 ldr r4, [r4, #68] ; 0x44 + 108e8: ea8b 0b06 eor.w fp, fp, r6 + 108ec: f8d9 6048 ldr.w r6, [r9, #72] ; 0x48 + 108f0: ea88 0804 eor.w r8, r8, r4 + 108f4: 9c22 ldr r4, [sp, #136] ; 0x88 + 108f6: ea8c 0606 eor.w r6, ip, r6 + 108fa: ea8b 0b00 eor.w fp, fp, r0 + 108fe: ea86 0c04 eor.w ip, r6, r4 + 10902: ea8c 0005 eor.w r0, ip, r5 + 10906: ea4f 6911 mov.w r9, r1, lsr #24 + 1090a: fa5f f48b uxtb.w r4, fp + 1090e: ea88 0a0a eor.w sl, r8, sl + 10912: fa5f fc80 uxtb.w ip, r0 + 10916: ea4f 681b mov.w r8, fp, lsr #24 + 1091a: eb03 0989 add.w r9, r3, r9, lsl #2 + 1091e: eb03 0484 add.w r4, r3, r4, lsl #2 + 10922: f8d4 4730 ldr.w r4, [r4, #1840] ; 0x730 + 10926: f8d9 9330 ldr.w r9, [r9, #816] ; 0x330 + 1092a: eb03 0888 add.w r8, r3, r8, lsl #2 + 1092e: eb03 0c8c add.w ip, r3, ip, lsl #2 + 10932: f8d8 8330 ldr.w r8, [r8, #816] ; 0x330 + 10936: f8dc c730 ldr.w ip, [ip, #1840] ; 0x730 + 1093a: ea8a 0707 eor.w r7, sl, r7 + 1093e: ea89 0904 eor.w r9, r9, r4 + 10942: 9c20 ldr r4, [sp, #128] ; 0x80 + 10944: ea88 0c0c eor.w ip, r8, ip + 10948: b2fd uxtb r5, r7 + 1094a: 0e06 lsrs r6, r0, #24 + 1094c: 6d24 ldr r4, [r4, #80] ; 0x50 + 1094e: f8cd c088 str.w ip, [sp, #136] ; 0x88 + 10952: eb03 0585 add.w r5, r3, r5, lsl #2 + 10956: f3c7 4c07 ubfx ip, r7, #16, #8 + 1095a: eb03 0686 add.w r6, r3, r6, lsl #2 + 1095e: f8d5 5730 ldr.w r5, [r5, #1840] ; 0x730 + 10962: f8d6 6330 ldr.w r6, [r6, #816] ; 0x330 + 10966: ea4f 6a17 mov.w sl, r7, lsr #24 + 1096a: fa5f fe81 uxtb.w lr, r1 + 1096e: eb03 0c8c add.w ip, r3, ip, lsl #2 + 10972: 9409 str r4, [sp, #36] ; 0x24 + 10974: eb03 0a8a add.w sl, r3, sl, lsl #2 + 10978: f8dc 4b30 ldr.w r4, [ip, #2864] ; 0xb30 + 1097c: eb03 0e8e add.w lr, r3, lr, lsl #2 + 10980: ea86 0805 eor.w r8, r6, r5 + 10984: f8da a330 ldr.w sl, [sl, #816] ; 0x330 + 10988: f8de e730 ldr.w lr, [lr, #1840] ; 0x730 + 1098c: f3c0 4507 ubfx r5, r0, #16, #8 + 10990: 9421 str r4, [sp, #132] ; 0x84 + 10992: f3c1 4607 ubfx r6, r1, #16, #8 + 10996: eb03 0585 add.w r5, r3, r5, lsl #2 + 1099a: f3cb 4407 ubfx r4, fp, #16, #8 + 1099e: f3c1 2107 ubfx r1, r1, #8, #8 + 109a2: f3c0 2007 ubfx r0, r0, #8, #8 + 109a6: ea8a 0e0e eor.w lr, sl, lr + 109aa: eb03 0080 add.w r0, r3, r0, lsl #2 + 109ae: f8d5 ab30 ldr.w sl, [r5, #2864] ; 0xb30 + 109b2: eb03 0181 add.w r1, r3, r1, lsl #2 + 109b6: 9d09 ldr r5, [sp, #36] ; 0x24 + 109b8: eb03 0484 add.w r4, r3, r4, lsl #2 + 109bc: f3c7 2707 ubfx r7, r7, #8, #8 + 109c0: f3cb 2b07 ubfx fp, fp, #8, #8 + 109c4: f8d4 cb30 ldr.w ip, [r4, #2864] ; 0xb30 + 109c8: eb03 0787 add.w r7, r3, r7, lsl #2 + 109cc: f8d0 4f30 ldr.w r4, [r0, #3888] ; 0xf30 + 109d0: eb03 0b8b add.w fp, r3, fp, lsl #2 + 109d4: f8d1 0f30 ldr.w r0, [r1, #3888] ; 0xf30 + 109d8: 9921 ldr r1, [sp, #132] ; 0x84 + 109da: ea89 0905 eor.w r9, r9, r5 + 109de: f8d7 5f30 ldr.w r5, [r7, #3888] ; 0xf30 + 109e2: f8db 7f30 ldr.w r7, [fp, #3888] ; 0xf30 + 109e6: f8dd b080 ldr.w fp, [sp, #128] ; 0x80 + 109ea: ea89 0901 eor.w r9, r9, r1 + 109ee: ea89 0404 eor.w r4, r9, r4 + 109f2: f8db 105c ldr.w r1, [fp, #92] ; 0x5c + 109f6: f8dd 9088 ldr.w r9, [sp, #136] ; 0x88 + 109fa: eb03 0686 add.w r6, r3, r6, lsl #2 + 109fe: f8d6 6b30 ldr.w r6, [r6, #2864] ; 0xb30 + 10a02: ea89 0b01 eor.w fp, r9, r1 + 10a06: f8dd 9080 ldr.w r9, [sp, #128] ; 0x80 + 10a0a: 9920 ldr r1, [sp, #128] ; 0x80 + 10a0c: ea8b 0b06 eor.w fp, fp, r6 + 10a10: f8d9 6058 ldr.w r6, [r9, #88] ; 0x58 + 10a14: 6d49 ldr r1, [r1, #84] ; 0x54 + 10a16: ea88 0606 eor.w r6, r8, r6 + 10a1a: ea8b 0b05 eor.w fp, fp, r5 + 10a1e: ea86 0c0c eor.w ip, r6, ip + 10a22: ea8c 0500 eor.w r5, ip, r0 + 10a26: ea8e 0e01 eor.w lr, lr, r1 + 10a2a: ea4f 6914 mov.w r9, r4, lsr #24 + 10a2e: fa5f f18b uxtb.w r1, fp + 10a32: ea4f 681b mov.w r8, fp, lsr #24 + 10a36: fa5f fc85 uxtb.w ip, r5 + 10a3a: eb03 0989 add.w r9, r3, r9, lsl #2 + 10a3e: eb03 0181 add.w r1, r3, r1, lsl #2 + 10a42: f8d1 1730 ldr.w r1, [r1, #1840] ; 0x730 + 10a46: f8d9 9330 ldr.w r9, [r9, #816] ; 0x330 + 10a4a: eb03 0888 add.w r8, r3, r8, lsl #2 + 10a4e: eb03 0c8c add.w ip, r3, ip, lsl #2 + 10a52: f8d8 8330 ldr.w r8, [r8, #816] ; 0x330 + 10a56: f8dc c730 ldr.w ip, [ip, #1840] ; 0x730 + 10a5a: ea8e 0e0a eor.w lr, lr, sl + 10a5e: ea89 0901 eor.w r9, r9, r1 + 10a62: 9920 ldr r1, [sp, #128] ; 0x80 + 10a64: ea8e 0e07 eor.w lr, lr, r7 + 10a68: ea88 0c0c eor.w ip, r8, ip + 10a6c: 6e09 ldr r1, [r1, #96] ; 0x60 + 10a6e: f8cd c08c str.w ip, [sp, #140] ; 0x8c + 10a72: f3ce 4c07 ubfx ip, lr, #16, #8 + 10a76: eb03 0c8c add.w ip, r3, ip, lsl #2 + 10a7a: 9108 str r1, [sp, #32] + 10a7c: ea4f 6a1e mov.w sl, lr, lsr #24 + 10a80: f8dc 1b30 ldr.w r1, [ip, #2864] ; 0xb30 + 10a84: fa5f f08e uxtb.w r0, lr + 10a88: b2e7 uxtb r7, r4 + 10a8a: 0e2e lsrs r6, r5, #24 + 10a8c: eb03 0a8a add.w sl, r3, sl, lsl #2 + 10a90: eb03 0080 add.w r0, r3, r0, lsl #2 + 10a94: eb03 0787 add.w r7, r3, r7, lsl #2 + 10a98: eb03 0686 add.w r6, r3, r6, lsl #2 + 10a9c: f8da a330 ldr.w sl, [sl, #816] ; 0x330 + 10aa0: f8d0 0730 ldr.w r0, [r0, #1840] ; 0x730 + 10aa4: f8d7 7730 ldr.w r7, [r7, #1840] ; 0x730 + 10aa8: f8d6 6330 ldr.w r6, [r6, #816] ; 0x330 + 10aac: 9121 str r1, [sp, #132] ; 0x84 + 10aae: f3cb 4107 ubfx r1, fp, #16, #8 + 10ab2: eb03 0181 add.w r1, r3, r1, lsl #2 + 10ab6: ea86 0c00 eor.w ip, r6, r0 + 10aba: ea8a 0807 eor.w r8, sl, r7 + 10abe: f3c4 4607 ubfx r6, r4, #16, #8 + 10ac2: 9f08 ldr r7, [sp, #32] + 10ac4: f3c5 4007 ubfx r0, r5, #16, #8 + 10ac8: f8d1 1b30 ldr.w r1, [r1, #2864] ; 0xb30 + 10acc: f3c4 2407 ubfx r4, r4, #8, #8 + 10ad0: f3c5 2507 ubfx r5, r5, #8, #8 + 10ad4: f3cb 2b07 ubfx fp, fp, #8, #8 + 10ad8: eb03 0080 add.w r0, r3, r0, lsl #2 + 10adc: eb03 0585 add.w r5, r3, r5, lsl #2 + 10ae0: eb03 0484 add.w r4, r3, r4, lsl #2 + 10ae4: eb03 0b8b add.w fp, r3, fp, lsl #2 + 10ae8: eb03 0686 add.w r6, r3, r6, lsl #2 + 10aec: f8d6 6b30 ldr.w r6, [r6, #2864] ; 0xb30 + 10af0: f8d0 ab30 ldr.w sl, [r0, #2864] ; 0xb30 + 10af4: ea89 0907 eor.w r9, r9, r7 + 10af8: 9122 str r1, [sp, #136] ; 0x88 + 10afa: f3ce 2e07 ubfx lr, lr, #8, #8 + 10afe: f8d5 1f30 ldr.w r1, [r5, #3888] ; 0xf30 + 10b02: f8db 7f30 ldr.w r7, [fp, #3888] ; 0xf30 + 10b06: f8d4 5f30 ldr.w r5, [r4, #3888] ; 0xf30 + 10b0a: f8dd b080 ldr.w fp, [sp, #128] ; 0x80 + 10b0e: 9c21 ldr r4, [sp, #132] ; 0x84 + 10b10: eb03 0e8e add.w lr, r3, lr, lsl #2 + 10b14: f8de 0f30 ldr.w r0, [lr, #3888] ; 0xf30 + 10b18: ea89 0904 eor.w r9, r9, r4 + 10b1c: f8dd e08c ldr.w lr, [sp, #140] ; 0x8c + 10b20: f8db 406c ldr.w r4, [fp, #108] ; 0x6c + 10b24: ea89 0101 eor.w r1, r9, r1 + 10b28: ea8e 0b04 eor.w fp, lr, r4 + 10b2c: 9c20 ldr r4, [sp, #128] ; 0x80 + 10b2e: f8dd 9080 ldr.w r9, [sp, #128] ; 0x80 + 10b32: 6e64 ldr r4, [r4, #100] ; 0x64 + 10b34: ea8b 0b06 eor.w fp, fp, r6 + 10b38: f8d9 6068 ldr.w r6, [r9, #104] ; 0x68 + 10b3c: ea88 0804 eor.w r8, r8, r4 + 10b40: 9c22 ldr r4, [sp, #136] ; 0x88 + 10b42: ea8c 0606 eor.w r6, ip, r6 + 10b46: ea8b 0b00 eor.w fp, fp, r0 + 10b4a: ea86 0c04 eor.w ip, r6, r4 + 10b4e: ea8c 0005 eor.w r0, ip, r5 + 10b52: ea4f 6911 mov.w r9, r1, lsr #24 + 10b56: fa5f f48b uxtb.w r4, fp + 10b5a: ea88 0a0a eor.w sl, r8, sl + 10b5e: fa5f fc80 uxtb.w ip, r0 + 10b62: ea4f 681b mov.w r8, fp, lsr #24 + 10b66: eb03 0989 add.w r9, r3, r9, lsl #2 + 10b6a: eb03 0484 add.w r4, r3, r4, lsl #2 + 10b6e: f8d4 4730 ldr.w r4, [r4, #1840] ; 0x730 + 10b72: f8d9 9330 ldr.w r9, [r9, #816] ; 0x330 + 10b76: eb03 0888 add.w r8, r3, r8, lsl #2 + 10b7a: eb03 0c8c add.w ip, r3, ip, lsl #2 + 10b7e: f8d8 8330 ldr.w r8, [r8, #816] ; 0x330 + 10b82: f8dc c730 ldr.w ip, [ip, #1840] ; 0x730 + 10b86: ea8a 0707 eor.w r7, sl, r7 + 10b8a: ea89 0904 eor.w r9, r9, r4 + 10b8e: 9c20 ldr r4, [sp, #128] ; 0x80 + 10b90: ea88 0c0c eor.w ip, r8, ip + 10b94: b2fd uxtb r5, r7 + 10b96: 0e06 lsrs r6, r0, #24 + 10b98: 6f24 ldr r4, [r4, #112] ; 0x70 + 10b9a: f8cd c088 str.w ip, [sp, #136] ; 0x88 + 10b9e: eb03 0585 add.w r5, r3, r5, lsl #2 + 10ba2: f3c7 4c07 ubfx ip, r7, #16, #8 + 10ba6: eb03 0686 add.w r6, r3, r6, lsl #2 + 10baa: f8d5 5730 ldr.w r5, [r5, #1840] ; 0x730 + 10bae: f8d6 6330 ldr.w r6, [r6, #816] ; 0x330 + 10bb2: ea4f 6a17 mov.w sl, r7, lsr #24 + 10bb6: fa5f fe81 uxtb.w lr, r1 + 10bba: eb03 0c8c add.w ip, r3, ip, lsl #2 + 10bbe: 9407 str r4, [sp, #28] + 10bc0: eb03 0a8a add.w sl, r3, sl, lsl #2 + 10bc4: f8dc 4b30 ldr.w r4, [ip, #2864] ; 0xb30 + 10bc8: eb03 0e8e add.w lr, r3, lr, lsl #2 + 10bcc: ea86 0805 eor.w r8, r6, r5 + 10bd0: f8da a330 ldr.w sl, [sl, #816] ; 0x330 + 10bd4: f8de e730 ldr.w lr, [lr, #1840] ; 0x730 + 10bd8: f3c0 4607 ubfx r6, r0, #16, #8 + 10bdc: 9421 str r4, [sp, #132] ; 0x84 + 10bde: f3c1 4507 ubfx r5, r1, #16, #8 + 10be2: eb03 0686 add.w r6, r3, r6, lsl #2 + 10be6: f3cb 4407 ubfx r4, fp, #16, #8 + 10bea: f3c1 2107 ubfx r1, r1, #8, #8 + 10bee: f3c0 2007 ubfx r0, r0, #8, #8 + 10bf2: ea8a 0e0e eor.w lr, sl, lr + 10bf6: eb03 0080 add.w r0, r3, r0, lsl #2 + 10bfa: f8d6 ab30 ldr.w sl, [r6, #2864] ; 0xb30 + 10bfe: eb03 0181 add.w r1, r3, r1, lsl #2 + 10c02: 9e07 ldr r6, [sp, #28] + 10c04: eb03 0484 add.w r4, r3, r4, lsl #2 + 10c08: f3c7 2707 ubfx r7, r7, #8, #8 + 10c0c: f3cb 2b07 ubfx fp, fp, #8, #8 + 10c10: f8d4 cb30 ldr.w ip, [r4, #2864] ; 0xb30 + 10c14: eb03 0787 add.w r7, r3, r7, lsl #2 + 10c18: f8d0 4f30 ldr.w r4, [r0, #3888] ; 0xf30 + 10c1c: eb03 0b8b add.w fp, r3, fp, lsl #2 + 10c20: f8d1 0f30 ldr.w r0, [r1, #3888] ; 0xf30 + 10c24: 9921 ldr r1, [sp, #132] ; 0x84 + 10c26: ea89 0906 eor.w r9, r9, r6 + 10c2a: f8d7 6f30 ldr.w r6, [r7, #3888] ; 0xf30 + 10c2e: f8db 7f30 ldr.w r7, [fp, #3888] ; 0xf30 + 10c32: f8dd b080 ldr.w fp, [sp, #128] ; 0x80 + 10c36: ea89 0901 eor.w r9, r9, r1 + 10c3a: ea89 0404 eor.w r4, r9, r4 + 10c3e: f8db 107c ldr.w r1, [fp, #124] ; 0x7c + 10c42: f8dd 9088 ldr.w r9, [sp, #136] ; 0x88 + 10c46: eb03 0585 add.w r5, r3, r5, lsl #2 + 10c4a: f8d5 5b30 ldr.w r5, [r5, #2864] ; 0xb30 + 10c4e: ea89 0b01 eor.w fp, r9, r1 + 10c52: f8dd 9080 ldr.w r9, [sp, #128] ; 0x80 + 10c56: 9920 ldr r1, [sp, #128] ; 0x80 + 10c58: ea8b 0b05 eor.w fp, fp, r5 + 10c5c: 6f49 ldr r1, [r1, #116] ; 0x74 + 10c5e: f8d9 5078 ldr.w r5, [r9, #120] ; 0x78 + 10c62: ea8b 0b06 eor.w fp, fp, r6 + 10c66: ea88 0505 eor.w r5, r8, r5 + 10c6a: ea8e 0e01 eor.w lr, lr, r1 + 10c6e: ea4f 6914 mov.w r9, r4, lsr #24 + 10c72: fa5f f18b uxtb.w r1, fp + 10c76: ea85 0c0c eor.w ip, r5, ip + 10c7a: eb03 0989 add.w r9, r3, r9, lsl #2 + 10c7e: eb03 0181 add.w r1, r3, r1, lsl #2 + 10c82: ea8c 0600 eor.w r6, ip, r0 + 10c86: f8d1 1730 ldr.w r1, [r1, #1840] ; 0x730 + 10c8a: f8d9 9330 ldr.w r9, [r9, #816] ; 0x330 + 10c8e: ea4f 681b mov.w r8, fp, lsr #24 + 10c92: fa5f fc86 uxtb.w ip, r6 + 10c96: ea8e 0e0a eor.w lr, lr, sl + 10c9a: ea89 0901 eor.w r9, r9, r1 + 10c9e: eb03 0888 add.w r8, r3, r8, lsl #2 + 10ca2: 9920 ldr r1, [sp, #128] ; 0x80 + 10ca4: eb03 0c8c add.w ip, r3, ip, lsl #2 + 10ca8: ea8e 0e07 eor.w lr, lr, r7 + 10cac: f8d8 8330 ldr.w r8, [r8, #816] ; 0x330 + 10cb0: f8dc c730 ldr.w ip, [ip, #1840] ; 0x730 + 10cb4: ea4f 6a1e mov.w sl, lr, lsr #24 + 10cb8: fa5f f78e uxtb.w r7, lr + 10cbc: b2e0 uxtb r0, r4 + 10cbe: 0e35 lsrs r5, r6, #24 + 10cc0: f8d1 1080 ldr.w r1, [r1, #128] ; 0x80 + 10cc4: ea88 0c0c eor.w ip, r8, ip + 10cc8: eb03 0a8a add.w sl, r3, sl, lsl #2 + 10ccc: eb03 0787 add.w r7, r3, r7, lsl #2 + 10cd0: eb03 0080 add.w r0, r3, r0, lsl #2 + 10cd4: eb03 0585 add.w r5, r3, r5, lsl #2 + 10cd8: f8da a330 ldr.w sl, [sl, #816] ; 0x330 + 10cdc: f8d7 7730 ldr.w r7, [r7, #1840] ; 0x730 + 10ce0: f8d0 0730 ldr.w r0, [r0, #1840] ; 0x730 + 10ce4: f8d5 5330 ldr.w r5, [r5, #816] ; 0x330 + 10ce8: 9106 str r1, [sp, #24] + 10cea: f8cd c088 str.w ip, [sp, #136] ; 0x88 + 10cee: f3ce 4c07 ubfx ip, lr, #16, #8 + 10cf2: eb03 0c8c add.w ip, r3, ip, lsl #2 + 10cf6: f8dc 1b30 ldr.w r1, [ip, #2864] ; 0xb30 + 10cfa: ea85 0807 eor.w r8, r5, r7 + 10cfe: f3c4 4507 ubfx r5, r4, #16, #8 + 10d02: eb03 0585 add.w r5, r3, r5, lsl #2 + 10d06: f8d5 7b30 ldr.w r7, [r5, #2864] ; 0xb30 + 10d0a: 9121 str r1, [sp, #132] ; 0x84 + 10d0c: ea8a 0c00 eor.w ip, sl, r0 + 10d10: 9d06 ldr r5, [sp, #24] + 10d12: f3c6 4007 ubfx r0, r6, #16, #8 + 10d16: f3cb 4107 ubfx r1, fp, #16, #8 + 10d1a: f3ce 2e07 ubfx lr, lr, #8, #8 + 10d1e: f3c6 2607 ubfx r6, r6, #8, #8 + 10d22: eb03 0e8e add.w lr, r3, lr, lsl #2 + 10d26: eb03 0686 add.w r6, r3, r6, lsl #2 + 10d2a: f3cb 2b07 ubfx fp, fp, #8, #8 + 10d2e: eb03 0181 add.w r1, r3, r1, lsl #2 + 10d32: eb03 0080 add.w r0, r3, r0, lsl #2 + 10d36: ea89 0905 eor.w r9, r9, r5 + 10d3a: eb03 058b add.w r5, r3, fp, lsl #2 + 10d3e: f8d1 bb30 ldr.w fp, [r1, #2864] ; 0xb30 + 10d42: f8d6 1f30 ldr.w r1, [r6, #3888] ; 0xf30 + 10d46: f8de 6f30 ldr.w r6, [lr, #3888] ; 0xf30 + 10d4a: f8d0 ab30 ldr.w sl, [r0, #2864] ; 0xb30 + 10d4e: 9821 ldr r0, [sp, #132] ; 0x84 + 10d50: 9623 str r6, [sp, #140] ; 0x8c + 10d52: 9e20 ldr r6, [sp, #128] ; 0x80 + 10d54: ea89 0900 eor.w r9, r9, r0 + 10d58: ea89 0101 eor.w r1, r9, r1 + 10d5c: f8d6 008c ldr.w r0, [r6, #140] ; 0x8c + 10d60: f8dd 9088 ldr.w r9, [sp, #136] ; 0x88 + 10d64: f3c4 2407 ubfx r4, r4, #8, #8 + 10d68: ea80 0e09 eor.w lr, r0, r9 + 10d6c: f8d6 0084 ldr.w r0, [r6, #132] ; 0x84 + 10d70: ea8e 0607 eor.w r6, lr, r7 + 10d74: 9f20 ldr r7, [sp, #128] ; 0x80 + 10d76: eb03 0484 add.w r4, r3, r4, lsl #2 + 10d7a: f8d7 7088 ldr.w r7, [r7, #136] ; 0x88 + 10d7e: ea8c 0c00 eor.w ip, ip, r0 + 10d82: f8d4 4f30 ldr.w r4, [r4, #3888] ; 0xf30 + 10d86: f8d5 5f30 ldr.w r5, [r5, #3888] ; 0xf30 + 10d8a: 9705 str r7, [sp, #20] + 10d8c: 9823 ldr r0, [sp, #140] ; 0x8c + 10d8e: ea88 0707 eor.w r7, r8, r7 + 10d92: ea8c 0a0a eor.w sl, ip, sl + 10d96: ea87 0b0b eor.w fp, r7, fp + 10d9a: ea8a 0505 eor.w r5, sl, r5 + 10d9e: ea8b 0404 eor.w r4, fp, r4 + 10da2: 4070 eors r0, r6 + 10da4: 0e0f lsrs r7, r1, #24 + 10da6: b2c6 uxtb r6, r0 + 10da8: ea4f 6914 mov.w r9, r4, lsr #24 + 10dac: fa5f f885 uxtb.w r8, r5 + 10db0: eb03 0787 add.w r7, r3, r7, lsl #2 + 10db4: eb03 0686 add.w r6, r3, r6, lsl #2 + 10db8: eb03 0989 add.w r9, r3, r9, lsl #2 + 10dbc: eb03 0888 add.w r8, r3, r8, lsl #2 + 10dc0: f8d6 6730 ldr.w r6, [r6, #1840] ; 0x730 + 10dc4: f8d9 9330 ldr.w r9, [r9, #816] ; 0x330 + 10dc8: f8d7 7330 ldr.w r7, [r7, #816] ; 0x330 + 10dcc: f8d8 8730 ldr.w r8, [r8, #1840] ; 0x730 + 10dd0: 4077 eors r7, r6 + 10dd2: ea89 0808 eor.w r8, r9, r8 + 10dd6: 9e20 ldr r6, [sp, #128] ; 0x80 + 10dd8: f3c5 4907 ubfx r9, r5, #16, #8 + 10ddc: eb03 0989 add.w r9, r3, r9, lsl #2 + 10de0: f8d6 6090 ldr.w r6, [r6, #144] ; 0x90 + 10de4: ea4f 6b15 mov.w fp, r5, lsr #24 + 10de8: fa5f fa81 uxtb.w sl, r1 + 10dec: fa5f fe84 uxtb.w lr, r4 + 10df0: ea4f 6c10 mov.w ip, r0, lsr #24 + 10df4: f8cd 8088 str.w r8, [sp, #136] ; 0x88 + 10df8: f3c5 2807 ubfx r8, r5, #8, #8 + 10dfc: f8d9 5b30 ldr.w r5, [r9, #2864] ; 0xb30 + 10e00: eb03 0888 add.w r8, r3, r8, lsl #2 + 10e04: eb03 0b8b add.w fp, r3, fp, lsl #2 + 10e08: eb03 0a8a add.w sl, r3, sl, lsl #2 + 10e0c: eb03 0e8e add.w lr, r3, lr, lsl #2 + 10e10: eb03 0c8c add.w ip, r3, ip, lsl #2 + 10e14: f8db b330 ldr.w fp, [fp, #816] ; 0x330 + 10e18: f8de e730 ldr.w lr, [lr, #1840] ; 0x730 + 10e1c: f8dc c330 ldr.w ip, [ip, #816] ; 0x330 + 10e20: f8da a730 ldr.w sl, [sl, #1840] ; 0x730 + 10e24: 9603 str r6, [sp, #12] + 10e26: 9521 str r5, [sp, #132] ; 0x84 + 10e28: f8d8 5f30 ldr.w r5, [r8, #3888] ; 0xf30 + 10e2c: f8dd 8080 ldr.w r8, [sp, #128] ; 0x80 + 10e30: 9523 str r5, [sp, #140] ; 0x8c + 10e32: 9d21 ldr r5, [sp, #132] ; 0x84 + 10e34: 407e eors r6, r7 + 10e36: 406e eors r6, r5 + 10e38: f8d8 5094 ldr.w r5, [r8, #148] ; 0x94 + 10e3c: ea8b 0a0a eor.w sl, fp, sl + 10e40: ea8c 0b0e eor.w fp, ip, lr + 10e44: f3c4 4c07 ubfx ip, r4, #16, #8 + 10e48: f3c0 4e07 ubfx lr, r0, #16, #8 + 10e4c: ea8a 0a05 eor.w sl, sl, r5 + 10e50: f3c0 2007 ubfx r0, r0, #8, #8 + 10e54: 9d22 ldr r5, [sp, #136] ; 0x88 + 10e56: eb03 0c8c add.w ip, r3, ip, lsl #2 + 10e5a: 9221 str r2, [sp, #132] ; 0x84 + 10e5c: f8d8 2098 ldr.w r2, [r8, #152] ; 0x98 + 10e60: eb03 0980 add.w r9, r3, r0, lsl #2 + 10e64: f8dc cb30 ldr.w ip, [ip, #2864] ; 0xb30 + 10e68: f3c1 4007 ubfx r0, r1, #16, #8 + 10e6c: f8d9 7f30 ldr.w r7, [r9, #3888] ; 0xf30 + 10e70: f3c4 2407 ubfx r4, r4, #8, #8 + 10e74: ea85 0902 eor.w r9, r5, r2 + 10e78: eb03 0e8e add.w lr, r3, lr, lsl #2 + 10e7c: f8d8 209c ldr.w r2, [r8, #156] ; 0x9c + 10e80: f3c1 2107 ubfx r1, r1, #8, #8 + 10e84: eb03 0080 add.w r0, r3, r0, lsl #2 + 10e88: f8d8 5200 ldr.w r5, [r8, #512] ; 0x200 + 10e8c: eb03 0484 add.w r4, r3, r4, lsl #2 + 10e90: f8de eb30 ldr.w lr, [lr, #2864] ; 0xb30 + 10e94: eb03 0181 add.w r1, r3, r1, lsl #2 + 10e98: f8d0 0b30 ldr.w r0, [r0, #2864] ; 0xb30 + 10e9c: ea8a 0c0c eor.w ip, sl, ip + 10ea0: ea8b 0202 eor.w r2, fp, r2 + 10ea4: f8d4 4f30 ldr.w r4, [r4, #3888] ; 0xf30 + 10ea8: f8d1 1f30 ldr.w r1, [r1, #3888] ; 0xf30 + 10eac: ea8c 0c07 eor.w ip, ip, r7 + 10eb0: 9f23 ldr r7, [sp, #140] ; 0x8c + 10eb2: ea89 0e0e eor.w lr, r9, lr + 10eb6: 4050 eors r0, r2 + 10eb8: 2d0a cmp r5, #10 + 10eba: 9522 str r5, [sp, #136] ; 0x88 + 10ebc: ea86 0604 eor.w r6, r6, r4 + 10ec0: ea8e 0801 eor.w r8, lr, r1 + 10ec4: ea80 0b07 eor.w fp, r0, r7 + 10ec8: f300 80be bgt.w 11048 + 10ecc: 9a20 ldr r2, [sp, #128] ; 0x80 + 10ece: 3290 adds r2, #144 ; 0x90 + 10ed0: f241 7388 movw r3, #6024 ; 0x1788 + 10ed4: f2c0 0303 movt r3, #3 + 10ed8: ea4f 6a1c mov.w sl, ip, lsr #24 + 10edc: eb03 0a8a add.w sl, r3, sl, lsl #2 + 10ee0: f8da 4028 ldr.w r4, [sl, #40] ; 0x28 + 10ee4: fa5f f08b uxtb.w r0, fp + 10ee8: eb03 0080 add.w r0, r3, r0, lsl #2 + 10eec: 9422 str r4, [sp, #136] ; 0x88 + 10eee: 6a80 ldr r0, [r0, #40] ; 0x28 + 10ef0: 6914 ldr r4, [r2, #16] + 10ef2: f3cc 4907 ubfx r9, ip, #16, #8 + 10ef6: eb03 0989 add.w r9, r3, r9, lsl #2 + 10efa: fa5f fe86 uxtb.w lr, r6 + 10efe: 4044 eors r4, r0 + 10f00: f8d9 0028 ldr.w r0, [r9, #40] ; 0x28 + 10f04: eb03 0e8e add.w lr, r3, lr, lsl #2 + 10f08: 9020 str r0, [sp, #128] ; 0x80 + 10f0a: f8de e028 ldr.w lr, [lr, #40] ; 0x28 + 10f0e: 6950 ldr r0, [r2, #20] + 10f10: 0e37 lsrs r7, r6, #24 + 10f12: eb03 0787 add.w r7, r3, r7, lsl #2 + 10f16: ea8e 0e00 eor.w lr, lr, r0 + 10f1a: ea4f 601b mov.w r0, fp, lsr #24 + 10f1e: 6abf ldr r7, [r7, #40] ; 0x28 + 10f20: fa5f f18c uxtb.w r1, ip + 10f24: eb03 0080 add.w r0, r3, r0, lsl #2 + 10f28: 6a80 ldr r0, [r0, #40] ; 0x28 + 10f2a: eb03 0181 add.w r1, r3, r1, lsl #2 + 10f2e: fa5f f588 uxtb.w r5, r8 + 10f32: 6a89 ldr r1, [r1, #40] ; 0x28 + 10f34: ea4f 6a18 mov.w sl, r8, lsr #24 + 10f38: ea84 6407 eor.w r4, r4, r7, lsl #24 + 10f3c: 6997 ldr r7, [r2, #24] + 10f3e: 9023 str r0, [sp, #140] ; 0x8c + 10f40: eb03 0585 add.w r5, r3, r5, lsl #2 + 10f44: 9822 ldr r0, [sp, #136] ; 0x88 + 10f46: eb03 0a8a add.w sl, r3, sl, lsl #2 + 10f4a: 69d2 ldr r2, [r2, #28] + 10f4c: f8da a028 ldr.w sl, [sl, #40] ; 0x28 + 10f50: 6aad ldr r5, [r5, #40] ; 0x28 + 10f52: 4079 eors r1, r7 + 10f54: f3c8 4707 ubfx r7, r8, #16, #8 + 10f58: f3c8 2807 ubfx r8, r8, #8, #8 + 10f5c: eb03 0787 add.w r7, r3, r7, lsl #2 + 10f60: eb03 0888 add.w r8, r3, r8, lsl #2 + 10f64: ea8e 6e00 eor.w lr, lr, r0, lsl #24 + 10f68: 9823 ldr r0, [sp, #140] ; 0x8c + 10f6a: 4055 eors r5, r2 + 10f6c: ea81 610a eor.w r1, r1, sl, lsl #24 + 10f70: 6aba ldr r2, [r7, #40] ; 0x28 + 10f72: f3c6 4a07 ubfx sl, r6, #16, #8 + 10f76: f8d8 7028 ldr.w r7, [r8, #40] ; 0x28 + 10f7a: f3cb 4807 ubfx r8, fp, #16, #8 + 10f7e: ea85 6500 eor.w r5, r5, r0, lsl #24 + 10f82: eb03 0888 add.w r8, r3, r8, lsl #2 + 10f86: 9820 ldr r0, [sp, #128] ; 0x80 + 10f88: eb03 0a8a add.w sl, r3, sl, lsl #2 + 10f8c: f3cc 2c07 ubfx ip, ip, #8, #8 + 10f90: f3cb 2b07 ubfx fp, fp, #8, #8 + 10f94: f3c6 2607 ubfx r6, r6, #8, #8 + 10f98: eb03 0b8b add.w fp, r3, fp, lsl #2 + 10f9c: f8d8 8028 ldr.w r8, [r8, #40] ; 0x28 + 10fa0: eb03 0c8c add.w ip, r3, ip, lsl #2 + 10fa4: eb03 0686 add.w r6, r3, r6, lsl #2 + 10fa8: f8da 3028 ldr.w r3, [sl, #40] ; 0x28 + 10fac: f8db 9028 ldr.w r9, [fp, #40] ; 0x28 + 10fb0: 6ab6 ldr r6, [r6, #40] ; 0x28 + 10fb2: ea84 4400 eor.w r4, r4, r0, lsl #16 + 10fb6: f8dc c028 ldr.w ip, [ip, #40] ; 0x28 + 10fba: f8dd b084 ldr.w fp, [sp, #132] ; 0x84 + 10fbe: ea84 2707 eor.w r7, r4, r7, lsl #8 + 10fc2: ea8e 4e02 eor.w lr, lr, r2, lsl #16 + 10fc6: ea85 4303 eor.w r3, r5, r3, lsl #16 + 10fca: ea81 4108 eor.w r1, r1, r8, lsl #16 + 10fce: ea81 2106 eor.w r1, r1, r6, lsl #8 + 10fd2: ea83 2c0c eor.w ip, r3, ip, lsl #8 + 10fd6: ea8e 2909 eor.w r9, lr, r9, lsl #8 + 10fda: 0e3b lsrs r3, r7, #24 + 10fdc: ea4f 4a17 mov.w sl, r7, lsr #16 + 10fe0: ea4f 2817 mov.w r8, r7, lsr #8 + 10fe4: ea4f 6e19 mov.w lr, r9, lsr #24 + 10fe8: ea4f 4619 mov.w r6, r9, lsr #16 + 10fec: ea4f 2519 mov.w r5, r9, lsr #8 + 10ff0: f88b 3000 strb.w r3, [fp] + 10ff4: f88b 7003 strb.w r7, [fp, #3] + 10ff8: f88b 9007 strb.w r9, [fp, #7] + 10ffc: 0e0c lsrs r4, r1, #24 + 10ffe: 0c08 lsrs r0, r1, #16 + 11000: 0a0a lsrs r2, r1, #8 + 11002: ea4f 631c mov.w r3, ip, lsr #24 + 11006: ea4f 471c mov.w r7, ip, lsr #16 + 1100a: ea4f 291c mov.w r9, ip, lsr #8 + 1100e: f88b 100b strb.w r1, [fp, #11] + 11012: f88b a001 strb.w sl, [fp, #1] + 11016: f88b 8002 strb.w r8, [fp, #2] + 1101a: f88b e004 strb.w lr, [fp, #4] + 1101e: f88b 6005 strb.w r6, [fp, #5] + 11022: f88b 5006 strb.w r5, [fp, #6] + 11026: f88b 4008 strb.w r4, [fp, #8] + 1102a: f88b 0009 strb.w r0, [fp, #9] + 1102e: f88b 200a strb.w r2, [fp, #10] + 11032: f88b 300c strb.w r3, [fp, #12] + 11036: f88b 700d strb.w r7, [fp, #13] + 1103a: f88b c00f strb.w ip, [fp, #15] + 1103e: f88b 900e strb.w r9, [fp, #14] + 11042: b027 add sp, #156 ; 0x9c + 11044: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 11048: 4699 mov r9, r3 + 1104a: 0e34 lsrs r4, r6, #24 + 1104c: fa5f f28b uxtb.w r2, fp + 11050: eb03 0484 add.w r4, r3, r4, lsl #2 + 11054: eb03 0282 add.w r2, r3, r2, lsl #2 + 11058: f8d2 2730 ldr.w r2, [r2, #1840] ; 0x730 + 1105c: ea4f 601b mov.w r0, fp, lsr #24 + 11060: fa5f f188 uxtb.w r1, r8 + 11064: fa5f f78c uxtb.w r7, ip + 11068: b2f5 uxtb r5, r6 + 1106a: f8d4 4330 ldr.w r4, [r4, #816] ; 0x330 + 1106e: eb03 0787 add.w r7, r3, r7, lsl #2 + 11072: eb03 0585 add.w r5, r3, r5, lsl #2 + 11076: eb03 0080 add.w r0, r3, r0, lsl #2 + 1107a: eb03 0181 add.w r1, r3, r1, lsl #2 + 1107e: f8d7 a730 ldr.w sl, [r7, #1840] ; 0x730 + 11082: f8d0 0330 ldr.w r0, [r0, #816] ; 0x330 + 11086: f8d5 7730 ldr.w r7, [r5, #1840] ; 0x730 + 1108a: ea4f 6e1c mov.w lr, ip, lsr #24 + 1108e: f8d1 1730 ldr.w r1, [r1, #1840] ; 0x730 + 11092: ea4f 6518 mov.w r5, r8, lsr #24 + 11096: 4054 eors r4, r2 + 11098: 9a20 ldr r2, [sp, #128] ; 0x80 + 1109a: eb03 0e8e add.w lr, r3, lr, lsl #2 + 1109e: eb03 0585 add.w r5, r3, r5, lsl #2 + 110a2: f8de e330 ldr.w lr, [lr, #816] ; 0x330 + 110a6: f8d5 5330 ldr.w r5, [r5, #816] ; 0x330 + 110aa: f8d2 20a0 ldr.w r2, [r2, #160] ; 0xa0 + 110ae: 4041 eors r1, r0 + 110b0: f3cc 4007 ubfx r0, ip, #16, #8 + 110b4: eb03 0080 add.w r0, r3, r0, lsl #2 + 110b8: 9124 str r1, [sp, #144] ; 0x90 + 110ba: ea8e 0707 eor.w r7, lr, r7 + 110be: f8d0 1b30 ldr.w r1, [r0, #2864] ; 0xb30 + 110c2: ea85 0e0a eor.w lr, r5, sl + 110c6: f3c6 4007 ubfx r0, r6, #16, #8 + 110ca: 4054 eors r4, r2 + 110cc: f3cb 4507 ubfx r5, fp, #16, #8 + 110d0: f3c8 2207 ubfx r2, r8, #8, #8 + 110d4: f3cb 2b07 ubfx fp, fp, #8, #8 + 110d8: f3c8 4807 ubfx r8, r8, #16, #8 + 110dc: eb03 0080 add.w r0, r3, r0, lsl #2 + 110e0: eb03 0888 add.w r8, r3, r8, lsl #2 + 110e4: eb03 0282 add.w r2, r3, r2, lsl #2 + 110e8: eb03 0b8b add.w fp, r3, fp, lsl #2 + 110ec: 9723 str r7, [sp, #140] ; 0x8c + 110ee: f8d0 ab30 ldr.w sl, [r0, #2864] ; 0xb30 + 110f2: f8d8 7b30 ldr.w r7, [r8, #2864] ; 0xb30 + 110f6: f8db 0f30 ldr.w r0, [fp, #3888] ; 0xf30 + 110fa: f8d2 8f30 ldr.w r8, [r2, #3888] ; 0xf30 + 110fe: f8dd b080 ldr.w fp, [sp, #128] ; 0x80 + 11102: 404c eors r4, r1 + 11104: f3cc 2c07 ubfx ip, ip, #8, #8 + 11108: f8db 10ac ldr.w r1, [fp, #172] ; 0xac + 1110c: ea84 0b08 eor.w fp, r4, r8 + 11110: 9c24 ldr r4, [sp, #144] ; 0x90 + 11112: eb03 0c8c add.w ip, r3, ip, lsl #2 + 11116: f8dc 2f30 ldr.w r2, [ip, #3888] ; 0xf30 + 1111a: f8dd 8080 ldr.w r8, [sp, #128] ; 0x80 + 1111e: 4061 eors r1, r4 + 11120: ea81 0a0a eor.w sl, r1, sl + 11124: ea8a 0a02 eor.w sl, sl, r2 + 11128: f8d8 40a4 ldr.w r4, [r8, #164] ; 0xa4 + 1112c: 9923 ldr r1, [sp, #140] ; 0x8c + 1112e: f8d8 20a8 ldr.w r2, [r8, #168] ; 0xa8 + 11132: eb03 0585 add.w r5, r3, r5, lsl #2 + 11136: f3c6 2607 ubfx r6, r6, #8, #8 + 1113a: eb03 0686 add.w r6, r3, r6, lsl #2 + 1113e: f8d5 5b30 ldr.w r5, [r5, #2864] ; 0xb30 + 11142: f8d6 6f30 ldr.w r6, [r6, #3888] ; 0xf30 + 11146: 404c eors r4, r1 + 11148: ea8e 0202 eor.w r2, lr, r2 + 1114c: 4067 eors r7, r4 + 1114e: 4055 eors r5, r2 + 11150: 4075 eors r5, r6 + 11152: 4047 eors r7, r0 + 11154: ea4f 6c1b mov.w ip, fp, lsr #24 + 11158: fa5f f28a uxtb.w r2, sl + 1115c: ea4f 6e17 mov.w lr, r7, lsr #24 + 11160: fa5f f68b uxtb.w r6, fp + 11164: 0e2c lsrs r4, r5, #24 + 11166: b2f8 uxtb r0, r7 + 11168: eb03 0c8c add.w ip, r3, ip, lsl #2 + 1116c: eb03 0e8e add.w lr, r3, lr, lsl #2 + 11170: eb03 0686 add.w r6, r3, r6, lsl #2 + 11174: eb03 0484 add.w r4, r3, r4, lsl #2 + 11178: eb03 0080 add.w r0, r3, r0, lsl #2 + 1117c: eb03 0282 add.w r2, r3, r2, lsl #2 + 11180: f8dc 8330 ldr.w r8, [ip, #816] ; 0x330 + 11184: f8d2 2730 ldr.w r2, [r2, #1840] ; 0x730 + 11188: f8de c330 ldr.w ip, [lr, #816] ; 0x330 + 1118c: b2e9 uxtb r1, r5 + 1118e: f8d6 e730 ldr.w lr, [r6, #1840] ; 0x730 + 11192: f8d4 6330 ldr.w r6, [r4, #816] ; 0x330 + 11196: f8d0 4730 ldr.w r4, [r0, #1840] ; 0x730 + 1119a: ea4f 601a mov.w r0, sl, lsr #24 + 1119e: eb03 0181 add.w r1, r3, r1, lsl #2 + 111a2: eb03 0080 add.w r0, r3, r0, lsl #2 + 111a6: f8d1 1730 ldr.w r1, [r1, #1840] ; 0x730 + 111aa: f8d0 0330 ldr.w r0, [r0, #816] ; 0x330 + 111ae: ea88 0802 eor.w r8, r8, r2 + 111b2: 9a20 ldr r2, [sp, #128] ; 0x80 + 111b4: 4074 eors r4, r6 + 111b6: f8d2 20b0 ldr.w r2, [r2, #176] ; 0xb0 + 111ba: ea8c 0c0e eor.w ip, ip, lr + 111be: 9425 str r4, [sp, #148] ; 0x94 + 111c0: ea80 0e01 eor.w lr, r0, r1 + 111c4: f3c5 4407 ubfx r4, r5, #16, #8 + 111c8: f3c7 4107 ubfx r1, r7, #16, #8 + 111cc: eb03 0181 add.w r1, r3, r1, lsl #2 + 111d0: eb03 0484 add.w r4, r3, r4, lsl #2 + 111d4: f3c7 2707 ubfx r7, r7, #8, #8 + 111d8: f3c5 2507 ubfx r5, r5, #8, #8 + 111dc: f8d1 1b30 ldr.w r1, [r1, #2864] ; 0xb30 + 111e0: f3ca 4007 ubfx r0, sl, #16, #8 + 111e4: f8d4 4b30 ldr.w r4, [r4, #2864] ; 0xb30 + 111e8: eb03 0385 add.w r3, r3, r5, lsl #2 + 111ec: eb09 0687 add.w r6, r9, r7, lsl #2 + 111f0: ea88 0802 eor.w r8, r8, r2 + 111f4: eb09 0080 add.w r0, r9, r0, lsl #2 + 111f8: 9424 str r4, [sp, #144] ; 0x90 + 111fa: f8d0 0b30 ldr.w r0, [r0, #2864] ; 0xb30 + 111fe: f8d3 4f30 ldr.w r4, [r3, #3888] ; 0xf30 + 11202: f8d6 3f30 ldr.w r3, [r6, #3888] ; 0xf30 + 11206: ea88 0601 eor.w r6, r8, r1 + 1120a: f8dd 8080 ldr.w r8, [sp, #128] ; 0x80 + 1120e: 9023 str r0, [sp, #140] ; 0x8c + 11210: f8d8 00b4 ldr.w r0, [r8, #180] ; 0xb4 + 11214: f3cb 4507 ubfx r5, fp, #16, #8 + 11218: eb09 0585 add.w r5, r9, r5, lsl #2 + 1121c: ea8c 0c00 eor.w ip, ip, r0 + 11220: 9925 ldr r1, [sp, #148] ; 0x94 + 11222: f8d8 00bc ldr.w r0, [r8, #188] ; 0xbc + 11226: 4066 eors r6, r4 + 11228: f8d8 40b8 ldr.w r4, [r8, #184] ; 0xb8 + 1122c: f8d5 2b30 ldr.w r2, [r5, #2864] ; 0xb30 + 11230: f3cb 2b07 ubfx fp, fp, #8, #8 + 11234: eb09 0b8b add.w fp, r9, fp, lsl #2 + 11238: 404c eors r4, r1 + 1123a: ea8e 0100 eor.w r1, lr, r0 + 1123e: f8db 5f30 ldr.w r5, [fp, #3888] ; 0xf30 + 11242: 9824 ldr r0, [sp, #144] ; 0x90 + 11244: ea81 0b02 eor.w fp, r1, r2 + 11248: 9922 ldr r1, [sp, #136] ; 0x88 + 1124a: f3ca 2a07 ubfx sl, sl, #8, #8 + 1124e: ea8c 0c00 eor.w ip, ip, r0 + 11252: 290c cmp r1, #12 + 11254: eb09 0a8a add.w sl, r9, sl, lsl #2 + 11258: 9823 ldr r0, [sp, #140] ; 0x8c + 1125a: f8da 7f30 ldr.w r7, [sl, #3888] ; 0xf30 + 1125e: bfd8 it le + 11260: 9a20 ldrle r2, [sp, #128] ; 0x80 + 11262: ea84 0800 eor.w r8, r4, r0 + 11266: ea8c 0c07 eor.w ip, ip, r7 + 1126a: ea88 0805 eor.w r8, r8, r5 + 1126e: ea8b 0b03 eor.w fp, fp, r3 + 11272: bfd8 it le + 11274: 32b0 addle r2, #176 ; 0xb0 + 11276: f77f ae2b ble.w 10ed0 + 1127a: ea4f 6e16 mov.w lr, r6, lsr #24 + 1127e: fa5f f38b uxtb.w r3, fp + 11282: eb09 0e8e add.w lr, r9, lr, lsl #2 + 11286: eb09 0383 add.w r3, r9, r3, lsl #2 + 1128a: f8de e330 ldr.w lr, [lr, #816] ; 0x330 + 1128e: f8d3 3730 ldr.w r3, [r3, #1840] ; 0x730 + 11292: fa5f f48c uxtb.w r4, ip + 11296: ea8e 0303 eor.w r3, lr, r3 + 1129a: 9322 str r3, [sp, #136] ; 0x88 + 1129c: 9b20 ldr r3, [sp, #128] ; 0x80 + 1129e: ea4f 6118 mov.w r1, r8, lsr #24 + 112a2: eb09 0484 add.w r4, r9, r4, lsl #2 + 112a6: eb09 0181 add.w r1, r9, r1, lsl #2 + 112aa: f8d3 30c0 ldr.w r3, [r3, #192] ; 0xc0 + 112ae: ea4f 671b mov.w r7, fp, lsr #24 + 112b2: fa5f f288 uxtb.w r2, r8 + 112b6: f8d4 4730 ldr.w r4, [r4, #1840] ; 0x730 + 112ba: f8d1 1330 ldr.w r1, [r1, #816] ; 0x330 + 112be: eb09 0787 add.w r7, r9, r7, lsl #2 + 112c2: eb09 0282 add.w r2, r9, r2, lsl #2 + 112c6: 9312 str r3, [sp, #72] ; 0x48 + 112c8: ea81 0a04 eor.w sl, r1, r4 + 112cc: ea4f 651c mov.w r5, ip, lsr #24 + 112d0: b2f0 uxtb r0, r6 + 112d2: f8d7 7330 ldr.w r7, [r7, #816] ; 0x330 + 112d6: 9c12 ldr r4, [sp, #72] ; 0x48 + 112d8: f8d2 2730 ldr.w r2, [r2, #1840] ; 0x730 + 112dc: 9b22 ldr r3, [sp, #136] ; 0x88 + 112de: eb09 0585 add.w r5, r9, r5, lsl #2 + 112e2: eb09 0080 add.w r0, r9, r0, lsl #2 + 112e6: 407a eors r2, r7 + 112e8: f8d5 5330 ldr.w r5, [r5, #816] ; 0x330 + 112ec: f8d0 0730 ldr.w r0, [r0, #1840] ; 0x730 + 112f0: 4063 eors r3, r4 + 112f2: f3cb 4407 ubfx r4, fp, #16, #8 + 112f6: 9224 str r2, [sp, #144] ; 0x90 + 112f8: eb09 0484 add.w r4, r9, r4, lsl #2 + 112fc: f3cc 4207 ubfx r2, ip, #16, #8 + 11300: eb09 0282 add.w r2, r9, r2, lsl #2 + 11304: ea85 0e00 eor.w lr, r5, r0 + 11308: f8d4 4b30 ldr.w r4, [r4, #2864] ; 0xb30 + 1130c: f3c8 4007 ubfx r0, r8, #16, #8 + 11310: f3c8 2807 ubfx r8, r8, #8, #8 + 11314: f8d2 7b30 ldr.w r7, [r2, #2864] ; 0xb30 + 11318: eb09 0888 add.w r8, r9, r8, lsl #2 + 1131c: 9423 str r4, [sp, #140] ; 0x8c + 1131e: f8d8 4f30 ldr.w r4, [r8, #3888] ; 0xf30 + 11322: f8dd 8080 ldr.w r8, [sp, #128] ; 0x80 + 11326: 407b eors r3, r7 + 11328: 4063 eors r3, r4 + 1132a: f8d8 70cc ldr.w r7, [r8, #204] ; 0xcc + 1132e: 9c24 ldr r4, [sp, #144] ; 0x90 + 11330: f3c6 4107 ubfx r1, r6, #16, #8 + 11334: eb09 0181 add.w r1, r9, r1, lsl #2 + 11338: 4067 eors r7, r4 + 1133a: f8d8 40c4 ldr.w r4, [r8, #196] ; 0xc4 + 1133e: f8d1 1b30 ldr.w r1, [r1, #2864] ; 0xb30 + 11342: 9411 str r4, [sp, #68] ; 0x44 + 11344: 404f eors r7, r1 + 11346: f8d8 40c8 ldr.w r4, [r8, #200] ; 0xc8 + 1134a: 9911 ldr r1, [sp, #68] ; 0x44 + 1134c: f3cc 2c07 ubfx ip, ip, #8, #8 + 11350: eb09 0c8c add.w ip, r9, ip, lsl #2 + 11354: f3c6 2607 ubfx r6, r6, #8, #8 + 11358: ea8e 0e01 eor.w lr, lr, r1 + 1135c: eb09 0080 add.w r0, r9, r0, lsl #2 + 11360: ea8a 0104 eor.w r1, sl, r4 + 11364: eb09 0686 add.w r6, r9, r6, lsl #2 + 11368: f8dc 2f30 ldr.w r2, [ip, #3888] ; 0xf30 + 1136c: 9c23 ldr r4, [sp, #140] ; 0x8c + 1136e: f3cb 2b07 ubfx fp, fp, #8, #8 + 11372: eb09 0b8b add.w fp, r9, fp, lsl #2 + 11376: f8d6 6f30 ldr.w r6, [r6, #3888] ; 0xf30 + 1137a: f8d0 0b30 ldr.w r0, [r0, #2864] ; 0xb30 + 1137e: 407a eors r2, r7 + 11380: f8db 5f30 ldr.w r5, [fp, #3888] ; 0xf30 + 11384: 4061 eors r1, r4 + 11386: 4071 eors r1, r6 + 11388: ea8e 0000 eor.w r0, lr, r0 + 1138c: 0e1e lsrs r6, r3, #24 + 1138e: b2d4 uxtb r4, r2 + 11390: 4068 eors r0, r5 + 11392: eb09 0686 add.w r6, r9, r6, lsl #2 + 11396: eb09 0484 add.w r4, r9, r4, lsl #2 + 1139a: ea4f 6a10 mov.w sl, r0, lsr #24 + 1139e: fa5f fc83 uxtb.w ip, r3 + 113a2: f8d4 4730 ldr.w r4, [r4, #1840] ; 0x730 + 113a6: f8dd b080 ldr.w fp, [sp, #128] ; 0x80 + 113aa: f8d6 6330 ldr.w r6, [r6, #816] ; 0x330 + 113ae: ea4f 6811 mov.w r8, r1, lsr #24 + 113b2: fa5f fe80 uxtb.w lr, r0 + 113b6: eb09 0a8a add.w sl, r9, sl, lsl #2 + 113ba: eb09 0c8c add.w ip, r9, ip, lsl #2 + 113be: 4066 eors r6, r4 + 113c0: b2cd uxtb r5, r1 + 113c2: eb09 0888 add.w r8, r9, r8, lsl #2 + 113c6: eb09 0e8e add.w lr, r9, lr, lsl #2 + 113ca: 0e17 lsrs r7, r2, #24 + 113cc: f8da a330 ldr.w sl, [sl, #816] ; 0x330 + 113d0: f8db 40d0 ldr.w r4, [fp, #208] ; 0xd0 + 113d4: f8dc c730 ldr.w ip, [ip, #1840] ; 0x730 + 113d8: eb09 0585 add.w r5, r9, r5, lsl #2 + 113dc: eb09 0787 add.w r7, r9, r7, lsl #2 + 113e0: f8de e730 ldr.w lr, [lr, #1840] ; 0x730 + 113e4: f8d8 8330 ldr.w r8, [r8, #816] ; 0x330 + 113e8: f8d5 5730 ldr.w r5, [r5, #1840] ; 0x730 + 113ec: f8d7 7330 ldr.w r7, [r7, #816] ; 0x330 + 113f0: ea8a 0c0c eor.w ip, sl, ip + 113f4: 4074 eors r4, r6 + 113f6: f3c0 4a07 ubfx sl, r0, #16, #8 + 113fa: 9e20 ldr r6, [sp, #128] ; 0x80 + 113fc: f3c0 2007 ubfx r0, r0, #8, #8 + 11400: ea88 080e eor.w r8, r8, lr + 11404: eb09 0e80 add.w lr, r9, r0, lsl #2 + 11408: f3c2 4007 ubfx r0, r2, #16, #8 + 1140c: ea87 0b05 eor.w fp, r7, r5 + 11410: eb09 0080 add.w r0, r9, r0, lsl #2 + 11414: f3c1 4707 ubfx r7, r1, #16, #8 + 11418: f8d6 60d8 ldr.w r6, [r6, #216] ; 0xd8 + 1141c: f3c1 2107 ubfx r1, r1, #8, #8 + 11420: eb09 0581 add.w r5, r9, r1, lsl #2 + 11424: f3c2 2207 ubfx r2, r2, #8, #8 + 11428: f8d0 1b30 ldr.w r1, [r0, #2864] ; 0xb30 + 1142c: f3c3 4007 ubfx r0, r3, #16, #8 + 11430: f3c3 2307 ubfx r3, r3, #8, #8 + 11434: eb09 0282 add.w r2, r9, r2, lsl #2 + 11438: eb09 0a8a add.w sl, r9, sl, lsl #2 + 1143c: eb09 0787 add.w r7, r9, r7, lsl #2 + 11440: eb09 0080 add.w r0, r9, r0, lsl #2 + 11444: ea88 0806 eor.w r8, r8, r6 + 11448: eb09 0983 add.w r9, r9, r3, lsl #2 + 1144c: 9e20 ldr r6, [sp, #128] ; 0x80 + 1144e: 9b20 ldr r3, [sp, #128] ; 0x80 + 11450: f8d6 60dc ldr.w r6, [r6, #220] ; 0xdc + 11454: f8d3 30d4 ldr.w r3, [r3, #212] ; 0xd4 + 11458: f8d0 0b30 ldr.w r0, [r0, #2864] ; 0xb30 + 1145c: ea8c 0c03 eor.w ip, ip, r3 + 11460: ea8b 0b06 eor.w fp, fp, r6 + 11464: f8d2 3f30 ldr.w r3, [r2, #3888] ; 0xf30 + 11468: f8de 2f30 ldr.w r2, [lr, #3888] ; 0xf30 + 1146c: f8da ab30 ldr.w sl, [sl, #2864] ; 0xb30 + 11470: f8d7 7b30 ldr.w r7, [r7, #2864] ; 0xb30 + 11474: ea8b 0b00 eor.w fp, fp, r0 + 11478: f8d5 5f30 ldr.w r5, [r5, #3888] ; 0xf30 + 1147c: f8d9 9f30 ldr.w r9, [r9, #3888] ; 0xf30 + 11480: ea8b 0b02 eor.w fp, fp, r2 + 11484: 9a20 ldr r2, [sp, #128] ; 0x80 + 11486: ea84 040a eor.w r4, r4, sl + 1148a: ea8c 0c07 eor.w ip, ip, r7 + 1148e: ea88 0801 eor.w r8, r8, r1 + 11492: ea84 0605 eor.w r6, r4, r5 + 11496: ea8c 0c03 eor.w ip, ip, r3 + 1149a: ea88 0809 eor.w r8, r8, r9 + 1149e: 32d0 adds r2, #208 ; 0xd0 + 114a0: e516 b.n 10ed0 + 114a2: bf00 nop + +000114a4 : + 114a4: f643 1378 movw r3, #14712 ; 0x3978 + 114a8: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 114ac: 4682 mov sl, r0 + 114ae: f2c0 0303 movt r3, #3 + 114b2: f891 c005 ldrb.w ip, [r1, #5] + 114b6: 7848 ldrb r0, [r1, #1] + 114b8: b087 sub sp, #28 + 114ba: 780f ldrb r7, [r1, #0] + 114bc: ea4f 4c0c mov.w ip, ip, lsl #16 + 114c0: f8cd c000 str.w ip, [sp] + 114c4: 0400 lsls r0, r0, #16 + 114c6: 790d ldrb r5, [r1, #4] + 114c8: ea40 6007 orr.w r0, r0, r7, lsl #24 + 114cc: 9f00 ldr r7, [sp, #0] + 114ce: f891 800d ldrb.w r8, [r1, #13] + 114d2: f891 e009 ldrb.w lr, [r1, #9] + 114d6: 7b0c ldrb r4, [r1, #12] + 114d8: 7a0e ldrb r6, [r1, #8] + 114da: f891 b003 ldrb.w fp, [r1, #3] + 114de: ea47 6505 orr.w r5, r7, r5, lsl #24 + 114e2: 9500 str r5, [sp, #0] + 114e4: ea4f 4808 mov.w r8, r8, lsl #16 + 114e8: ea4f 4e0e mov.w lr, lr, lsl #16 + 114ec: 798d ldrb r5, [r1, #6] + 114ee: f891 9007 ldrb.w r9, [r1, #7] + 114f2: f891 c00f ldrb.w ip, [r1, #15] + 114f6: 7acf ldrb r7, [r1, #11] + 114f8: ea48 6804 orr.w r8, r8, r4, lsl #24 + 114fc: ea4e 6e06 orr.w lr, lr, r6, lsl #24 + 11500: 7b8c ldrb r4, [r1, #14] + 11502: 788e ldrb r6, [r1, #2] + 11504: ea40 000b orr.w r0, r0, fp + 11508: f891 b00a ldrb.w fp, [r1, #10] + 1150c: 9900 ldr r1, [sp, #0] + 1150e: ea48 0c0c orr.w ip, r8, ip + 11512: ea41 0909 orr.w r9, r1, r9 + 11516: f8da 110c ldr.w r1, [sl, #268] ; 0x10c + 1151a: ea4c 2404 orr.w r4, ip, r4, lsl #8 + 1151e: 404c eors r4, r1 + 11520: ea4e 0707 orr.w r7, lr, r7 + 11524: f8da 1108 ldr.w r1, [sl, #264] ; 0x108 + 11528: ea47 270b orr.w r7, r7, fp, lsl #8 + 1152c: 4079 eors r1, r7 + 1152e: 0e27 lsrs r7, r4, #24 + 11530: eb03 0787 add.w r7, r3, r7, lsl #2 + 11534: 9700 str r7, [sp, #0] + 11536: 0e0f lsrs r7, r1, #24 + 11538: ea49 2905 orr.w r9, r9, r5, lsl #8 + 1153c: ea40 2006 orr.w r0, r0, r6, lsl #8 + 11540: f8da 5100 ldr.w r5, [sl, #256] ; 0x100 + 11544: f8da 6104 ldr.w r6, [sl, #260] ; 0x104 + 11548: eb03 0787 add.w r7, r3, r7, lsl #2 + 1154c: 9702 str r7, [sp, #8] + 1154e: 9f00 ldr r7, [sp, #0] + 11550: ea89 0b06 eor.w fp, r9, r6 + 11554: 4068 eors r0, r5 + 11556: ea4f 6910 mov.w r9, r0, lsr #24 + 1155a: fa5f f58b uxtb.w r5, fp + 1155e: ea4f 681b mov.w r8, fp, lsr #24 + 11562: fa5f fc81 uxtb.w ip, r1 + 11566: b2e6 uxtb r6, r4 + 11568: f8d7 7238 ldr.w r7, [r7, #568] ; 0x238 + 1156c: eb03 0989 add.w r9, r3, r9, lsl #2 + 11570: eb03 0585 add.w r5, r3, r5, lsl #2 + 11574: eb03 0888 add.w r8, r3, r8, lsl #2 + 11578: eb03 0c8c add.w ip, r3, ip, lsl #2 + 1157c: eb03 0686 add.w r6, r3, r6, lsl #2 + 11580: f8d5 5638 ldr.w r5, [r5, #1592] ; 0x638 + 11584: f8d8 8238 ldr.w r8, [r8, #568] ; 0x238 + 11588: f8d9 9238 ldr.w r9, [r9, #568] ; 0x238 + 1158c: f8dc c638 ldr.w ip, [ip, #1592] ; 0x638 + 11590: 9701 str r7, [sp, #4] + 11592: f8d6 6638 ldr.w r6, [r6, #1592] ; 0x638 + 11596: fa5f fe80 uxtb.w lr, r0 + 1159a: 9603 str r6, [sp, #12] + 1159c: 9e02 ldr r6, [sp, #8] + 1159e: eb03 0e8e add.w lr, r3, lr, lsl #2 + 115a2: f8d6 7238 ldr.w r7, [r6, #568] ; 0x238 + 115a6: f8de e638 ldr.w lr, [lr, #1592] ; 0x638 + 115aa: 9e01 ldr r6, [sp, #4] + 115ac: ea88 0c0c eor.w ip, r8, ip + 115b0: f8cd c008 str.w ip, [sp, #8] + 115b4: ea86 0e0e eor.w lr, r6, lr + 115b8: f3c4 4c07 ubfx ip, r4, #16, #8 + 115bc: f3c1 4607 ubfx r6, r1, #16, #8 + 115c0: eb03 0c8c add.w ip, r3, ip, lsl #2 + 115c4: eb03 0686 add.w r6, r3, r6, lsl #2 + 115c8: f8d6 6a38 ldr.w r6, [r6, #2616] ; 0xa38 + 115cc: ea89 0905 eor.w r9, r9, r5 + 115d0: f8dc 5a38 ldr.w r5, [ip, #2616] ; 0xa38 + 115d4: 9601 str r6, [sp, #4] + 115d6: 9500 str r5, [sp, #0] + 115d8: f8da 6110 ldr.w r6, [sl, #272] ; 0x110 + 115dc: 9d03 ldr r5, [sp, #12] + 115de: f3c1 2107 ubfx r1, r1, #8, #8 + 115e2: eb03 0181 add.w r1, r3, r1, lsl #2 + 115e6: ea87 0805 eor.w r8, r7, r5 + 115ea: ea89 0906 eor.w r9, r9, r6 + 115ee: f8d1 5e38 ldr.w r5, [r1, #3640] ; 0xe38 + 115f2: f3cb 4607 ubfx r6, fp, #16, #8 + 115f6: 9900 ldr r1, [sp, #0] + 115f8: f3c4 2407 ubfx r4, r4, #8, #8 + 115fc: f3c0 4707 ubfx r7, r0, #16, #8 + 11600: eb03 0686 add.w r6, r3, r6, lsl #2 + 11604: eb03 0484 add.w r4, r3, r4, lsl #2 + 11608: f8d6 ca38 ldr.w ip, [r6, #2616] ; 0xa38 + 1160c: f8d4 4e38 ldr.w r4, [r4, #3640] ; 0xe38 + 11610: 9e02 ldr r6, [sp, #8] + 11612: ea89 0901 eor.w r9, r9, r1 + 11616: eb03 0787 add.w r7, r3, r7, lsl #2 + 1161a: f8da 1114 ldr.w r1, [sl, #276] ; 0x114 + 1161e: f3cb 2b07 ubfx fp, fp, #8, #8 + 11622: f8d7 7a38 ldr.w r7, [r7, #2616] ; 0xa38 + 11626: eb03 0b8b add.w fp, r3, fp, lsl #2 + 1162a: 9403 str r4, [sp, #12] + 1162c: f8db 4e38 ldr.w r4, [fp, #3640] ; 0xe38 + 11630: ea86 0b01 eor.w fp, r6, r1 + 11634: ea8b 0b07 eor.w fp, fp, r7 + 11638: f8da 6118 ldr.w r6, [sl, #280] ; 0x118 + 1163c: f8da 711c ldr.w r7, [sl, #284] ; 0x11c + 11640: f3c0 2007 ubfx r0, r0, #8, #8 + 11644: ea8e 0107 eor.w r1, lr, r7 + 11648: ea88 0706 eor.w r7, r8, r6 + 1164c: 9e01 ldr r6, [sp, #4] + 1164e: eb03 0080 add.w r0, r3, r0, lsl #2 + 11652: ea81 0e06 eor.w lr, r1, r6 + 11656: ea8e 0e04 eor.w lr, lr, r4 + 1165a: f8d0 0e38 ldr.w r0, [r0, #3640] ; 0xe38 + 1165e: ea87 0c0c eor.w ip, r7, ip + 11662: ea4f 641e mov.w r4, lr, lsr #24 + 11666: ea8c 0600 eor.w r6, ip, r0 + 1166a: eb03 0484 add.w r4, r3, r4, lsl #2 + 1166e: 9f03 ldr r7, [sp, #12] + 11670: 9400 str r4, [sp, #0] + 11672: 0e34 lsrs r4, r6, #24 + 11674: eb03 0484 add.w r4, r3, r4, lsl #2 + 11678: ea8b 0b07 eor.w fp, fp, r7 + 1167c: 9402 str r4, [sp, #8] + 1167e: 9c00 ldr r4, [sp, #0] + 11680: ea89 0505 eor.w r5, r9, r5 + 11684: ea4f 681b mov.w r8, fp, lsr #24 + 11688: fa5f fc86 uxtb.w ip, r6 + 1168c: ea4f 6915 mov.w r9, r5, lsr #24 + 11690: fa5f f18b uxtb.w r1, fp + 11694: fa5f f08e uxtb.w r0, lr + 11698: f8d4 4238 ldr.w r4, [r4, #568] ; 0x238 + 1169c: eb03 0888 add.w r8, r3, r8, lsl #2 + 116a0: eb03 0c8c add.w ip, r3, ip, lsl #2 + 116a4: f8d8 8238 ldr.w r8, [r8, #568] ; 0x238 + 116a8: f8dc c638 ldr.w ip, [ip, #1592] ; 0x638 + 116ac: eb03 0989 add.w r9, r3, r9, lsl #2 + 116b0: eb03 0181 add.w r1, r3, r1, lsl #2 + 116b4: eb03 0080 add.w r0, r3, r0, lsl #2 + 116b8: f8d1 1638 ldr.w r1, [r1, #1592] ; 0x638 + 116bc: f8d9 9238 ldr.w r9, [r9, #568] ; 0x238 + 116c0: 9401 str r4, [sp, #4] + 116c2: f8d0 0638 ldr.w r0, [r0, #1592] ; 0x638 + 116c6: ea88 0c0c eor.w ip, r8, ip + 116ca: 9003 str r0, [sp, #12] + 116cc: 9802 ldr r0, [sp, #8] + 116ce: f8cd c008 str.w ip, [sp, #8] + 116d2: f3ce 4c07 ubfx ip, lr, #16, #8 + 116d6: eb03 0c8c add.w ip, r3, ip, lsl #2 + 116da: ea89 0901 eor.w r9, r9, r1 + 116de: f8dc 1a38 ldr.w r1, [ip, #2616] ; 0xa38 + 116e2: b2ef uxtb r7, r5 + 116e4: 9100 str r1, [sp, #0] + 116e6: f8d0 4238 ldr.w r4, [r0, #568] ; 0x238 + 116ea: 9903 ldr r1, [sp, #12] + 116ec: eb03 0787 add.w r7, r3, r7, lsl #2 + 116f0: 9801 ldr r0, [sp, #4] + 116f2: f8d7 7638 ldr.w r7, [r7, #1592] ; 0x638 + 116f6: ea84 0c01 eor.w ip, r4, r1 + 116fa: f3cb 4107 ubfx r1, fp, #16, #8 + 116fe: ea80 0807 eor.w r8, r0, r7 + 11702: eb03 0181 add.w r1, r3, r1, lsl #2 + 11706: f3c6 4007 ubfx r0, r6, #16, #8 + 1170a: f8d1 1a38 ldr.w r1, [r1, #2616] ; 0xa38 + 1170e: f3c5 4407 ubfx r4, r5, #16, #8 + 11712: f3c6 2607 ubfx r6, r6, #8, #8 + 11716: f3c5 2507 ubfx r5, r5, #8, #8 + 1171a: eb03 0080 add.w r0, r3, r0, lsl #2 + 1171e: f8d0 0a38 ldr.w r0, [r0, #2616] ; 0xa38 + 11722: f8da 7120 ldr.w r7, [sl, #288] ; 0x120 + 11726: eb03 0686 add.w r6, r3, r6, lsl #2 + 1172a: eb03 0585 add.w r5, r3, r5, lsl #2 + 1172e: f3ce 2e07 ubfx lr, lr, #8, #8 + 11732: 9101 str r1, [sp, #4] + 11734: eb03 0e8e add.w lr, r3, lr, lsl #2 + 11738: f8d6 1e38 ldr.w r1, [r6, #3640] ; 0xe38 + 1173c: f8d5 6e38 ldr.w r6, [r5, #3640] ; 0xe38 + 11740: 9d00 ldr r5, [sp, #0] + 11742: 9003 str r0, [sp, #12] + 11744: ea89 0907 eor.w r9, r9, r7 + 11748: f8de 0e38 ldr.w r0, [lr, #3640] ; 0xe38 + 1174c: ea89 0905 eor.w r9, r9, r5 + 11750: ea89 0101 eor.w r1, r9, r1 + 11754: 9004 str r0, [sp, #16] + 11756: f8dd 9008 ldr.w r9, [sp, #8] + 1175a: f8da 5124 ldr.w r5, [sl, #292] ; 0x124 + 1175e: f8da 012c ldr.w r0, [sl, #300] ; 0x12c + 11762: eb03 0484 add.w r4, r3, r4, lsl #2 + 11766: f3cb 2b07 ubfx fp, fp, #8, #8 + 1176a: f8d4 4a38 ldr.w r4, [r4, #2616] ; 0xa38 + 1176e: eb03 0b8b add.w fp, r3, fp, lsl #2 + 11772: f8db 7e38 ldr.w r7, [fp, #3640] ; 0xe38 + 11776: ea88 0800 eor.w r8, r8, r0 + 1177a: ea89 0b05 eor.w fp, r9, r5 + 1177e: 9803 ldr r0, [sp, #12] + 11780: ea8b 0b04 eor.w fp, fp, r4 + 11784: f8da 4128 ldr.w r4, [sl, #296] ; 0x128 + 11788: ea88 0500 eor.w r5, r8, r0 + 1178c: 9801 ldr r0, [sp, #4] + 1178e: ea8c 0404 eor.w r4, ip, r4 + 11792: 406f eors r7, r5 + 11794: ea84 0c00 eor.w ip, r4, r0 + 11798: ea8c 0006 eor.w r0, ip, r6 + 1179c: 0e3e lsrs r6, r7, #24 + 1179e: eb03 0686 add.w r6, r3, r6, lsl #2 + 117a2: 9600 str r6, [sp, #0] + 117a4: 0e06 lsrs r6, r0, #24 + 117a6: 9c04 ldr r4, [sp, #16] + 117a8: eb03 0686 add.w r6, r3, r6, lsl #2 + 117ac: 9602 str r6, [sp, #8] + 117ae: 9e00 ldr r6, [sp, #0] + 117b0: ea8b 0b04 eor.w fp, fp, r4 + 117b4: ea4f 6911 mov.w r9, r1, lsr #24 + 117b8: fa5f f48b uxtb.w r4, fp + 117bc: ea4f 681b mov.w r8, fp, lsr #24 + 117c0: fa5f fc80 uxtb.w ip, r0 + 117c4: b2fd uxtb r5, r7 + 117c6: f8d6 6238 ldr.w r6, [r6, #568] ; 0x238 + 117ca: eb03 0989 add.w r9, r3, r9, lsl #2 + 117ce: eb03 0484 add.w r4, r3, r4, lsl #2 + 117d2: eb03 0888 add.w r8, r3, r8, lsl #2 + 117d6: eb03 0c8c add.w ip, r3, ip, lsl #2 + 117da: eb03 0585 add.w r5, r3, r5, lsl #2 + 117de: f8d4 4638 ldr.w r4, [r4, #1592] ; 0x638 + 117e2: f8d8 8238 ldr.w r8, [r8, #568] ; 0x238 + 117e6: f8d9 9238 ldr.w r9, [r9, #568] ; 0x238 + 117ea: f8dc c638 ldr.w ip, [ip, #1592] ; 0x638 + 117ee: 9601 str r6, [sp, #4] + 117f0: f8d5 5638 ldr.w r5, [r5, #1592] ; 0x638 + 117f4: ea88 0c0c eor.w ip, r8, ip + 117f8: 9503 str r5, [sp, #12] + 117fa: fa5f fe81 uxtb.w lr, r1 + 117fe: 9d02 ldr r5, [sp, #8] + 11800: eb03 0e8e add.w lr, r3, lr, lsl #2 + 11804: f8cd c008 str.w ip, [sp, #8] + 11808: f3c7 4c07 ubfx ip, r7, #16, #8 + 1180c: f8d5 6238 ldr.w r6, [r5, #568] ; 0x238 + 11810: f8de e638 ldr.w lr, [lr, #1592] ; 0x638 + 11814: 9d01 ldr r5, [sp, #4] + 11816: eb03 0c8c add.w ip, r3, ip, lsl #2 + 1181a: ea89 0904 eor.w r9, r9, r4 + 1181e: f8dc 4a38 ldr.w r4, [ip, #2616] ; 0xa38 + 11822: ea85 0e0e eor.w lr, r5, lr + 11826: f3c0 4507 ubfx r5, r0, #16, #8 + 1182a: 9400 str r4, [sp, #0] + 1182c: eb03 0585 add.w r5, r3, r5, lsl #2 + 11830: 9c03 ldr r4, [sp, #12] + 11832: f8d5 5a38 ldr.w r5, [r5, #2616] ; 0xa38 + 11836: ea86 0804 eor.w r8, r6, r4 + 1183a: f3c0 2007 ubfx r0, r0, #8, #8 + 1183e: f3c1 4607 ubfx r6, r1, #16, #8 + 11842: f3cb 4407 ubfx r4, fp, #16, #8 + 11846: f3c1 2107 ubfx r1, r1, #8, #8 + 1184a: 9501 str r5, [sp, #4] + 1184c: eb03 0080 add.w r0, r3, r0, lsl #2 + 11850: f8da 5130 ldr.w r5, [sl, #304] ; 0x130 + 11854: eb03 0181 add.w r1, r3, r1, lsl #2 + 11858: eb03 0484 add.w r4, r3, r4, lsl #2 + 1185c: f8d4 ca38 ldr.w ip, [r4, #2616] ; 0xa38 + 11860: f8d0 4e38 ldr.w r4, [r0, #3640] ; 0xe38 + 11864: f8d1 0e38 ldr.w r0, [r1, #3640] ; 0xe38 + 11868: 9900 ldr r1, [sp, #0] + 1186a: ea89 0905 eor.w r9, r9, r5 + 1186e: ea89 0901 eor.w r9, r9, r1 + 11872: ea89 0404 eor.w r4, r9, r4 + 11876: f8da 1134 ldr.w r1, [sl, #308] ; 0x134 + 1187a: f8dd 9008 ldr.w r9, [sp, #8] + 1187e: f3c7 2707 ubfx r7, r7, #8, #8 + 11882: f3cb 2b07 ubfx fp, fp, #8, #8 + 11886: eb03 0787 add.w r7, r3, r7, lsl #2 + 1188a: eb03 0b8b add.w fp, r3, fp, lsl #2 + 1188e: f8d7 5e38 ldr.w r5, [r7, #3640] ; 0xe38 + 11892: eb03 0686 add.w r6, r3, r6, lsl #2 + 11896: f8db 7e38 ldr.w r7, [fp, #3640] ; 0xe38 + 1189a: ea89 0b01 eor.w fp, r9, r1 + 1189e: f8da 113c ldr.w r1, [sl, #316] ; 0x13c + 118a2: f8d6 6a38 ldr.w r6, [r6, #2616] ; 0xa38 + 118a6: ea8e 0e01 eor.w lr, lr, r1 + 118aa: 9901 ldr r1, [sp, #4] + 118ac: ea8b 0b06 eor.w fp, fp, r6 + 118b0: f8da 6138 ldr.w r6, [sl, #312] ; 0x138 + 118b4: ea8e 0e01 eor.w lr, lr, r1 + 118b8: ea8e 0e07 eor.w lr, lr, r7 + 118bc: ea88 0606 eor.w r6, r8, r6 + 118c0: ea86 0c0c eor.w ip, r6, ip + 118c4: ea4f 661e mov.w r6, lr, lsr #24 + 118c8: ea8b 0b05 eor.w fp, fp, r5 + 118cc: eb03 0686 add.w r6, r3, r6, lsl #2 + 118d0: ea8c 0500 eor.w r5, ip, r0 + 118d4: 9600 str r6, [sp, #0] + 118d6: 0e2e lsrs r6, r5, #24 + 118d8: eb03 0686 add.w r6, r3, r6, lsl #2 + 118dc: 9602 str r6, [sp, #8] + 118de: 9e00 ldr r6, [sp, #0] + 118e0: ea4f 681b mov.w r8, fp, lsr #24 + 118e4: fa5f fc85 uxtb.w ip, r5 + 118e8: ea4f 6914 mov.w r9, r4, lsr #24 + 118ec: fa5f f18b uxtb.w r1, fp + 118f0: fa5f f08e uxtb.w r0, lr + 118f4: f8d6 6238 ldr.w r6, [r6, #568] ; 0x238 + 118f8: eb03 0888 add.w r8, r3, r8, lsl #2 + 118fc: eb03 0c8c add.w ip, r3, ip, lsl #2 + 11900: f8d8 8238 ldr.w r8, [r8, #568] ; 0x238 + 11904: f8dc c638 ldr.w ip, [ip, #1592] ; 0x638 + 11908: eb03 0989 add.w r9, r3, r9, lsl #2 + 1190c: eb03 0181 add.w r1, r3, r1, lsl #2 + 11910: eb03 0080 add.w r0, r3, r0, lsl #2 + 11914: f8d1 1638 ldr.w r1, [r1, #1592] ; 0x638 + 11918: f8d9 9238 ldr.w r9, [r9, #568] ; 0x238 + 1191c: 9601 str r6, [sp, #4] + 1191e: f8d0 0638 ldr.w r0, [r0, #1592] ; 0x638 + 11922: ea88 0c0c eor.w ip, r8, ip + 11926: 9003 str r0, [sp, #12] + 11928: 9802 ldr r0, [sp, #8] + 1192a: f8cd c008 str.w ip, [sp, #8] + 1192e: f3ce 4c07 ubfx ip, lr, #16, #8 + 11932: eb03 0c8c add.w ip, r3, ip, lsl #2 + 11936: ea89 0901 eor.w r9, r9, r1 + 1193a: f8dc 1a38 ldr.w r1, [ip, #2616] ; 0xa38 + 1193e: b2e7 uxtb r7, r4 + 11940: 9100 str r1, [sp, #0] + 11942: f8d0 6238 ldr.w r6, [r0, #568] ; 0x238 + 11946: 9903 ldr r1, [sp, #12] + 11948: eb03 0787 add.w r7, r3, r7, lsl #2 + 1194c: 9801 ldr r0, [sp, #4] + 1194e: f8d7 7638 ldr.w r7, [r7, #1592] ; 0x638 + 11952: ea86 0c01 eor.w ip, r6, r1 + 11956: f3cb 4107 ubfx r1, fp, #16, #8 + 1195a: ea80 0807 eor.w r8, r0, r7 + 1195e: eb03 0181 add.w r1, r3, r1, lsl #2 + 11962: f3c5 4007 ubfx r0, r5, #16, #8 + 11966: f8d1 1a38 ldr.w r1, [r1, #2616] ; 0xa38 + 1196a: f3c4 4607 ubfx r6, r4, #16, #8 + 1196e: f3c5 2507 ubfx r5, r5, #8, #8 + 11972: f3c4 2407 ubfx r4, r4, #8, #8 + 11976: eb03 0080 add.w r0, r3, r0, lsl #2 + 1197a: f8d0 0a38 ldr.w r0, [r0, #2616] ; 0xa38 + 1197e: f8da 7140 ldr.w r7, [sl, #320] ; 0x140 + 11982: eb03 0585 add.w r5, r3, r5, lsl #2 + 11986: eb03 0484 add.w r4, r3, r4, lsl #2 + 1198a: f3ce 2e07 ubfx lr, lr, #8, #8 + 1198e: 9101 str r1, [sp, #4] + 11990: eb03 0e8e add.w lr, r3, lr, lsl #2 + 11994: f8d5 1e38 ldr.w r1, [r5, #3640] ; 0xe38 + 11998: f8d4 5e38 ldr.w r5, [r4, #3640] ; 0xe38 + 1199c: 9c00 ldr r4, [sp, #0] + 1199e: 9003 str r0, [sp, #12] + 119a0: ea89 0907 eor.w r9, r9, r7 + 119a4: f8de 0e38 ldr.w r0, [lr, #3640] ; 0xe38 + 119a8: ea89 0904 eor.w r9, r9, r4 + 119ac: ea89 0101 eor.w r1, r9, r1 + 119b0: 9004 str r0, [sp, #16] + 119b2: f8dd 9008 ldr.w r9, [sp, #8] + 119b6: f8da 4144 ldr.w r4, [sl, #324] ; 0x144 + 119ba: f8da 014c ldr.w r0, [sl, #332] ; 0x14c + 119be: eb03 0686 add.w r6, r3, r6, lsl #2 + 119c2: f3cb 2b07 ubfx fp, fp, #8, #8 + 119c6: f8d6 6a38 ldr.w r6, [r6, #2616] ; 0xa38 + 119ca: eb03 0b8b add.w fp, r3, fp, lsl #2 + 119ce: f8db 7e38 ldr.w r7, [fp, #3640] ; 0xe38 + 119d2: ea88 0800 eor.w r8, r8, r0 + 119d6: ea89 0b04 eor.w fp, r9, r4 + 119da: 9803 ldr r0, [sp, #12] + 119dc: ea8b 0b06 eor.w fp, fp, r6 + 119e0: f8da 6148 ldr.w r6, [sl, #328] ; 0x148 + 119e4: ea88 0400 eor.w r4, r8, r0 + 119e8: 9801 ldr r0, [sp, #4] + 119ea: ea8c 0606 eor.w r6, ip, r6 + 119ee: ea86 0c00 eor.w ip, r6, r0 + 119f2: 9e04 ldr r6, [sp, #16] + 119f4: 4067 eors r7, r4 + 119f6: ea8b 0b06 eor.w fp, fp, r6 + 119fa: 0e3e lsrs r6, r7, #24 + 119fc: ea8c 0005 eor.w r0, ip, r5 + 11a00: eb03 0686 add.w r6, r3, r6, lsl #2 + 11a04: 9600 str r6, [sp, #0] + 11a06: 0e06 lsrs r6, r0, #24 + 11a08: eb03 0686 add.w r6, r3, r6, lsl #2 + 11a0c: 9602 str r6, [sp, #8] + 11a0e: 9e00 ldr r6, [sp, #0] + 11a10: ea4f 6911 mov.w r9, r1, lsr #24 + 11a14: fa5f f48b uxtb.w r4, fp + 11a18: ea4f 681b mov.w r8, fp, lsr #24 + 11a1c: fa5f fc80 uxtb.w ip, r0 + 11a20: b2fd uxtb r5, r7 + 11a22: f8d6 6238 ldr.w r6, [r6, #568] ; 0x238 + 11a26: eb03 0989 add.w r9, r3, r9, lsl #2 + 11a2a: eb03 0484 add.w r4, r3, r4, lsl #2 + 11a2e: eb03 0888 add.w r8, r3, r8, lsl #2 + 11a32: eb03 0c8c add.w ip, r3, ip, lsl #2 + 11a36: eb03 0585 add.w r5, r3, r5, lsl #2 + 11a3a: f8d4 4638 ldr.w r4, [r4, #1592] ; 0x638 + 11a3e: f8d8 8238 ldr.w r8, [r8, #568] ; 0x238 + 11a42: f8d9 9238 ldr.w r9, [r9, #568] ; 0x238 + 11a46: f8dc c638 ldr.w ip, [ip, #1592] ; 0x638 + 11a4a: 9601 str r6, [sp, #4] + 11a4c: f8d5 5638 ldr.w r5, [r5, #1592] ; 0x638 + 11a50: ea88 0c0c eor.w ip, r8, ip + 11a54: 9503 str r5, [sp, #12] + 11a56: fa5f fe81 uxtb.w lr, r1 + 11a5a: 9d02 ldr r5, [sp, #8] + 11a5c: eb03 0e8e add.w lr, r3, lr, lsl #2 + 11a60: f8cd c008 str.w ip, [sp, #8] + 11a64: f3c7 4c07 ubfx ip, r7, #16, #8 + 11a68: f8d5 6238 ldr.w r6, [r5, #568] ; 0x238 + 11a6c: f8de e638 ldr.w lr, [lr, #1592] ; 0x638 + 11a70: 9d01 ldr r5, [sp, #4] + 11a72: eb03 0c8c add.w ip, r3, ip, lsl #2 + 11a76: ea89 0904 eor.w r9, r9, r4 + 11a7a: f8dc 4a38 ldr.w r4, [ip, #2616] ; 0xa38 + 11a7e: ea85 0e0e eor.w lr, r5, lr + 11a82: f3c0 4507 ubfx r5, r0, #16, #8 + 11a86: 9400 str r4, [sp, #0] + 11a88: eb03 0585 add.w r5, r3, r5, lsl #2 + 11a8c: 9c03 ldr r4, [sp, #12] + 11a8e: f8d5 5a38 ldr.w r5, [r5, #2616] ; 0xa38 + 11a92: ea86 0804 eor.w r8, r6, r4 + 11a96: f3c0 2007 ubfx r0, r0, #8, #8 + 11a9a: f3c1 4607 ubfx r6, r1, #16, #8 + 11a9e: f3cb 4407 ubfx r4, fp, #16, #8 + 11aa2: f3c1 2107 ubfx r1, r1, #8, #8 + 11aa6: 9501 str r5, [sp, #4] + 11aa8: eb03 0080 add.w r0, r3, r0, lsl #2 + 11aac: f8da 5150 ldr.w r5, [sl, #336] ; 0x150 + 11ab0: eb03 0181 add.w r1, r3, r1, lsl #2 + 11ab4: eb03 0484 add.w r4, r3, r4, lsl #2 + 11ab8: f8d4 ca38 ldr.w ip, [r4, #2616] ; 0xa38 + 11abc: f8d0 4e38 ldr.w r4, [r0, #3640] ; 0xe38 + 11ac0: f8d1 0e38 ldr.w r0, [r1, #3640] ; 0xe38 + 11ac4: 9900 ldr r1, [sp, #0] + 11ac6: ea89 0905 eor.w r9, r9, r5 + 11aca: ea89 0901 eor.w r9, r9, r1 + 11ace: ea89 0404 eor.w r4, r9, r4 + 11ad2: f8da 1154 ldr.w r1, [sl, #340] ; 0x154 + 11ad6: f8dd 9008 ldr.w r9, [sp, #8] + 11ada: f3c7 2707 ubfx r7, r7, #8, #8 + 11ade: f3cb 2b07 ubfx fp, fp, #8, #8 + 11ae2: eb03 0787 add.w r7, r3, r7, lsl #2 + 11ae6: eb03 0b8b add.w fp, r3, fp, lsl #2 + 11aea: f8d7 5e38 ldr.w r5, [r7, #3640] ; 0xe38 + 11aee: eb03 0686 add.w r6, r3, r6, lsl #2 + 11af2: f8db 7e38 ldr.w r7, [fp, #3640] ; 0xe38 + 11af6: ea89 0b01 eor.w fp, r9, r1 + 11afa: f8da 115c ldr.w r1, [sl, #348] ; 0x15c + 11afe: f8d6 6a38 ldr.w r6, [r6, #2616] ; 0xa38 + 11b02: ea8e 0e01 eor.w lr, lr, r1 + 11b06: 9901 ldr r1, [sp, #4] + 11b08: ea8b 0b06 eor.w fp, fp, r6 + 11b0c: f8da 6158 ldr.w r6, [sl, #344] ; 0x158 + 11b10: ea8e 0e01 eor.w lr, lr, r1 + 11b14: ea8e 0e07 eor.w lr, lr, r7 + 11b18: ea88 0606 eor.w r6, r8, r6 + 11b1c: ea86 0c0c eor.w ip, r6, ip + 11b20: ea4f 661e mov.w r6, lr, lsr #24 + 11b24: ea8b 0b05 eor.w fp, fp, r5 + 11b28: eb03 0686 add.w r6, r3, r6, lsl #2 + 11b2c: ea8c 0500 eor.w r5, ip, r0 + 11b30: 9600 str r6, [sp, #0] + 11b32: 0e2e lsrs r6, r5, #24 + 11b34: eb03 0686 add.w r6, r3, r6, lsl #2 + 11b38: 9602 str r6, [sp, #8] + 11b3a: 9e00 ldr r6, [sp, #0] + 11b3c: ea4f 681b mov.w r8, fp, lsr #24 + 11b40: fa5f fc85 uxtb.w ip, r5 + 11b44: ea4f 6914 mov.w r9, r4, lsr #24 + 11b48: fa5f f18b uxtb.w r1, fp + 11b4c: fa5f f08e uxtb.w r0, lr + 11b50: f8d6 6238 ldr.w r6, [r6, #568] ; 0x238 + 11b54: eb03 0888 add.w r8, r3, r8, lsl #2 + 11b58: eb03 0c8c add.w ip, r3, ip, lsl #2 + 11b5c: f8d8 8238 ldr.w r8, [r8, #568] ; 0x238 + 11b60: f8dc c638 ldr.w ip, [ip, #1592] ; 0x638 + 11b64: eb03 0989 add.w r9, r3, r9, lsl #2 + 11b68: eb03 0181 add.w r1, r3, r1, lsl #2 + 11b6c: eb03 0080 add.w r0, r3, r0, lsl #2 + 11b70: f8d1 1638 ldr.w r1, [r1, #1592] ; 0x638 + 11b74: f8d9 9238 ldr.w r9, [r9, #568] ; 0x238 + 11b78: 9601 str r6, [sp, #4] + 11b7a: f8d0 0638 ldr.w r0, [r0, #1592] ; 0x638 + 11b7e: ea88 0c0c eor.w ip, r8, ip + 11b82: 9003 str r0, [sp, #12] + 11b84: 9802 ldr r0, [sp, #8] + 11b86: f8cd c008 str.w ip, [sp, #8] + 11b8a: f3ce 4c07 ubfx ip, lr, #16, #8 + 11b8e: eb03 0c8c add.w ip, r3, ip, lsl #2 + 11b92: ea89 0901 eor.w r9, r9, r1 + 11b96: f8dc 1a38 ldr.w r1, [ip, #2616] ; 0xa38 + 11b9a: b2e7 uxtb r7, r4 + 11b9c: 9100 str r1, [sp, #0] + 11b9e: f8d0 6238 ldr.w r6, [r0, #568] ; 0x238 + 11ba2: 9903 ldr r1, [sp, #12] + 11ba4: eb03 0787 add.w r7, r3, r7, lsl #2 + 11ba8: 9801 ldr r0, [sp, #4] + 11baa: f8d7 7638 ldr.w r7, [r7, #1592] ; 0x638 + 11bae: ea86 0c01 eor.w ip, r6, r1 + 11bb2: f3cb 4107 ubfx r1, fp, #16, #8 + 11bb6: ea80 0807 eor.w r8, r0, r7 + 11bba: eb03 0181 add.w r1, r3, r1, lsl #2 + 11bbe: f3c5 4007 ubfx r0, r5, #16, #8 + 11bc2: f8d1 1a38 ldr.w r1, [r1, #2616] ; 0xa38 + 11bc6: f3c4 4607 ubfx r6, r4, #16, #8 + 11bca: f3c5 2507 ubfx r5, r5, #8, #8 + 11bce: f3c4 2407 ubfx r4, r4, #8, #8 + 11bd2: eb03 0080 add.w r0, r3, r0, lsl #2 + 11bd6: f8d0 0a38 ldr.w r0, [r0, #2616] ; 0xa38 + 11bda: f8da 7160 ldr.w r7, [sl, #352] ; 0x160 + 11bde: eb03 0585 add.w r5, r3, r5, lsl #2 + 11be2: eb03 0484 add.w r4, r3, r4, lsl #2 + 11be6: f3ce 2e07 ubfx lr, lr, #8, #8 + 11bea: 9101 str r1, [sp, #4] + 11bec: eb03 0e8e add.w lr, r3, lr, lsl #2 + 11bf0: f8d5 1e38 ldr.w r1, [r5, #3640] ; 0xe38 + 11bf4: f8d4 5e38 ldr.w r5, [r4, #3640] ; 0xe38 + 11bf8: 9c00 ldr r4, [sp, #0] + 11bfa: 9003 str r0, [sp, #12] + 11bfc: ea89 0907 eor.w r9, r9, r7 + 11c00: f8de 0e38 ldr.w r0, [lr, #3640] ; 0xe38 + 11c04: ea89 0904 eor.w r9, r9, r4 + 11c08: ea89 0101 eor.w r1, r9, r1 + 11c0c: 9004 str r0, [sp, #16] + 11c0e: f8da 4164 ldr.w r4, [sl, #356] ; 0x164 + 11c12: f8dd 9008 ldr.w r9, [sp, #8] + 11c16: f8da 016c ldr.w r0, [sl, #364] ; 0x16c + 11c1a: eb03 0686 add.w r6, r3, r6, lsl #2 + 11c1e: f3cb 2b07 ubfx fp, fp, #8, #8 + 11c22: f8d6 6a38 ldr.w r6, [r6, #2616] ; 0xa38 + 11c26: eb03 0b8b add.w fp, r3, fp, lsl #2 + 11c2a: f8db 7e38 ldr.w r7, [fp, #3640] ; 0xe38 + 11c2e: ea88 0800 eor.w r8, r8, r0 + 11c32: ea89 0b04 eor.w fp, r9, r4 + 11c36: 9803 ldr r0, [sp, #12] + 11c38: ea8b 0b06 eor.w fp, fp, r6 + 11c3c: f8da 6168 ldr.w r6, [sl, #360] ; 0x168 + 11c40: ea88 0400 eor.w r4, r8, r0 + 11c44: 9801 ldr r0, [sp, #4] + 11c46: ea8c 0606 eor.w r6, ip, r6 + 11c4a: ea86 0c00 eor.w ip, r6, r0 + 11c4e: 9e04 ldr r6, [sp, #16] + 11c50: 4067 eors r7, r4 + 11c52: ea8b 0b06 eor.w fp, fp, r6 + 11c56: 0e3e lsrs r6, r7, #24 + 11c58: ea8c 0005 eor.w r0, ip, r5 + 11c5c: eb03 0686 add.w r6, r3, r6, lsl #2 + 11c60: 9600 str r6, [sp, #0] + 11c62: 0e06 lsrs r6, r0, #24 + 11c64: eb03 0686 add.w r6, r3, r6, lsl #2 + 11c68: 9601 str r6, [sp, #4] + 11c6a: 9e00 ldr r6, [sp, #0] + 11c6c: ea4f 681b mov.w r8, fp, lsr #24 + 11c70: fa5f fc80 uxtb.w ip, r0 + 11c74: ea4f 6911 mov.w r9, r1, lsr #24 + 11c78: fa5f f48b uxtb.w r4, fp + 11c7c: b2fd uxtb r5, r7 + 11c7e: f8d6 6238 ldr.w r6, [r6, #568] ; 0x238 + 11c82: eb03 0888 add.w r8, r3, r8, lsl #2 + 11c86: eb03 0c8c add.w ip, r3, ip, lsl #2 + 11c8a: f8d8 8238 ldr.w r8, [r8, #568] ; 0x238 + 11c8e: f8dc c638 ldr.w ip, [ip, #1592] ; 0x638 + 11c92: eb03 0989 add.w r9, r3, r9, lsl #2 + 11c96: eb03 0484 add.w r4, r3, r4, lsl #2 + 11c9a: eb03 0585 add.w r5, r3, r5, lsl #2 + 11c9e: f8d4 4638 ldr.w r4, [r4, #1592] ; 0x638 + 11ca2: f8d9 9238 ldr.w r9, [r9, #568] ; 0x238 + 11ca6: 9602 str r6, [sp, #8] + 11ca8: f8d5 5638 ldr.w r5, [r5, #1592] ; 0x638 + 11cac: ea88 0c0c eor.w ip, r8, ip + 11cb0: 9503 str r5, [sp, #12] + 11cb2: 9d01 ldr r5, [sp, #4] + 11cb4: f8cd c004 str.w ip, [sp, #4] + 11cb8: f3c7 4c07 ubfx ip, r7, #16, #8 + 11cbc: eb03 0c8c add.w ip, r3, ip, lsl #2 + 11cc0: fa5f fe81 uxtb.w lr, r1 + 11cc4: ea89 0904 eor.w r9, r9, r4 + 11cc8: f8dc 4a38 ldr.w r4, [ip, #2616] ; 0xa38 + 11ccc: eb03 0e8e add.w lr, r3, lr, lsl #2 + 11cd0: 9400 str r4, [sp, #0] + 11cd2: f8d5 6238 ldr.w r6, [r5, #568] ; 0x238 + 11cd6: 9c03 ldr r4, [sp, #12] + 11cd8: 9d02 ldr r5, [sp, #8] + 11cda: f8de e638 ldr.w lr, [lr, #1592] ; 0x638 + 11cde: ea86 0804 eor.w r8, r6, r4 + 11ce2: ea85 0e0e eor.w lr, r5, lr + 11ce6: f3c0 4607 ubfx r6, r0, #16, #8 + 11cea: f3c1 4507 ubfx r5, r1, #16, #8 + 11cee: f3c0 2007 ubfx r0, r0, #8, #8 + 11cf2: f3c1 2107 ubfx r1, r1, #8, #8 + 11cf6: f8da 4170 ldr.w r4, [sl, #368] ; 0x170 + 11cfa: eb03 0080 add.w r0, r3, r0, lsl #2 + 11cfe: eb03 0181 add.w r1, r3, r1, lsl #2 + 11d02: f8cd e010 str.w lr, [sp, #16] + 11d06: f8d0 ee38 ldr.w lr, [r0, #3640] ; 0xe38 + 11d0a: f8d1 0e38 ldr.w r0, [r1, #3640] ; 0xe38 + 11d0e: 9900 ldr r1, [sp, #0] + 11d10: ea89 0904 eor.w r9, r9, r4 + 11d14: ea89 0901 eor.w r9, r9, r1 + 11d18: ea89 090e eor.w r9, r9, lr + 11d1c: f8da 1174 ldr.w r1, [sl, #372] ; 0x174 + 11d20: f8dd e004 ldr.w lr, [sp, #4] + 11d24: f3cb 4407 ubfx r4, fp, #16, #8 + 11d28: f3c7 2707 ubfx r7, r7, #8, #8 + 11d2c: eb03 0585 add.w r5, r3, r5, lsl #2 + 11d30: f3cb 2b07 ubfx fp, fp, #8, #8 + 11d34: f8d5 5a38 ldr.w r5, [r5, #2616] ; 0xa38 + 11d38: eb03 0787 add.w r7, r3, r7, lsl #2 + 11d3c: eb03 0484 add.w r4, r3, r4, lsl #2 + 11d40: eb03 0b8b add.w fp, r3, fp, lsl #2 + 11d44: f8d4 ca38 ldr.w ip, [r4, #2616] ; 0xa38 + 11d48: f8d7 4e38 ldr.w r4, [r7, #3640] ; 0xe38 + 11d4c: f8db 7e38 ldr.w r7, [fp, #3640] ; 0xe38 + 11d50: ea8e 0b01 eor.w fp, lr, r1 + 11d54: ea8b 0b05 eor.w fp, fp, r5 + 11d58: f8da 117c ldr.w r1, [sl, #380] ; 0x17c + 11d5c: 9d04 ldr r5, [sp, #16] + 11d5e: eb03 0686 add.w r6, r3, r6, lsl #2 + 11d62: f8d6 6a38 ldr.w r6, [r6, #2616] ; 0xa38 + 11d66: ea85 0e01 eor.w lr, r5, r1 + 11d6a: ea8e 0e06 eor.w lr, lr, r6 + 11d6e: f8da 1178 ldr.w r1, [sl, #376] ; 0x178 + 11d72: ea8e 0e07 eor.w lr, lr, r7 + 11d76: ea88 0501 eor.w r5, r8, r1 + 11d7a: ea4f 671e mov.w r7, lr, lsr #24 + 11d7e: ea85 0c0c eor.w ip, r5, ip + 11d82: eb03 0787 add.w r7, r3, r7, lsl #2 + 11d86: fa5f f589 uxtb.w r5, r9 + 11d8a: 9700 str r7, [sp, #0] + 11d8c: eb03 0585 add.w r5, r3, r5, lsl #2 + 11d90: ea8c 0600 eor.w r6, ip, r0 + 11d94: ea8b 0b04 eor.w fp, fp, r4 + 11d98: 9502 str r5, [sp, #8] + 11d9a: 9d00 ldr r5, [sp, #0] + 11d9c: ea4f 6c1b mov.w ip, fp, lsr #24 + 11da0: b2f1 uxtb r1, r6 + 11da2: ea4f 6819 mov.w r8, r9, lsr #24 + 11da6: fa5f f48b uxtb.w r4, fp + 11daa: fa5f f08e uxtb.w r0, lr + 11dae: f8d5 5238 ldr.w r5, [r5, #568] ; 0x238 + 11db2: eb03 0c8c add.w ip, r3, ip, lsl #2 + 11db6: eb03 0181 add.w r1, r3, r1, lsl #2 + 11dba: f8dc c238 ldr.w ip, [ip, #568] ; 0x238 + 11dbe: f8d1 1638 ldr.w r1, [r1, #1592] ; 0x638 + 11dc2: eb03 0888 add.w r8, r3, r8, lsl #2 + 11dc6: eb03 0484 add.w r4, r3, r4, lsl #2 + 11dca: eb03 0080 add.w r0, r3, r0, lsl #2 + 11dce: f8d4 4638 ldr.w r4, [r4, #1592] ; 0x638 + 11dd2: f8d8 8238 ldr.w r8, [r8, #568] ; 0x238 + 11dd6: 9501 str r5, [sp, #4] + 11dd8: f8d0 0638 ldr.w r0, [r0, #1592] ; 0x638 + 11ddc: ea8c 0101 eor.w r1, ip, r1 + 11de0: 9003 str r0, [sp, #12] + 11de2: 9802 ldr r0, [sp, #8] + 11de4: 9102 str r1, [sp, #8] + 11de6: f3ce 4107 ubfx r1, lr, #16, #8 + 11dea: eb03 0181 add.w r1, r3, r1, lsl #2 + 11dee: f8d1 1a38 ldr.w r1, [r1, #2616] ; 0xa38 + 11df2: f8d0 5638 ldr.w r5, [r0, #1592] ; 0x638 + 11df6: 9100 str r1, [sp, #0] + 11df8: 9901 ldr r1, [sp, #4] + 11dfa: 0e37 lsrs r7, r6, #24 + 11dfc: ea81 0c05 eor.w ip, r1, r5 + 11e00: f3c6 4107 ubfx r1, r6, #16, #8 + 11e04: eb03 0181 add.w r1, r3, r1, lsl #2 + 11e08: f8d1 1a38 ldr.w r1, [r1, #2616] ; 0xa38 + 11e0c: eb03 0787 add.w r7, r3, r7, lsl #2 + 11e10: f8d7 7238 ldr.w r7, [r7, #568] ; 0x238 + 11e14: 9d03 ldr r5, [sp, #12] + 11e16: ea88 0804 eor.w r8, r8, r4 + 11e1a: 9103 str r1, [sp, #12] + 11e1c: f8da 4180 ldr.w r4, [sl, #384] ; 0x180 + 11e20: f3c9 4007 ubfx r0, r9, #16, #8 + 11e24: f3cb 4107 ubfx r1, fp, #16, #8 + 11e28: f3ce 2e07 ubfx lr, lr, #8, #8 + 11e2c: f3c6 2607 ubfx r6, r6, #8, #8 + 11e30: eb03 0e8e add.w lr, r3, lr, lsl #2 + 11e34: eb03 0080 add.w r0, r3, r0, lsl #2 + 11e38: f3c9 2907 ubfx r9, r9, #8, #8 + 11e3c: eb03 0686 add.w r6, r3, r6, lsl #2 + 11e40: eb03 0181 add.w r1, r3, r1, lsl #2 + 11e44: 407d eors r5, r7 + 11e46: ea88 0804 eor.w r8, r8, r4 + 11e4a: f8d0 7a38 ldr.w r7, [r0, #2616] ; 0xa38 + 11e4e: f8d6 4e38 ldr.w r4, [r6, #3640] ; 0xe38 + 11e52: eb03 0089 add.w r0, r3, r9, lsl #2 + 11e56: f8de 6e38 ldr.w r6, [lr, #3640] ; 0xe38 + 11e5a: f8d1 9a38 ldr.w r9, [r1, #2616] ; 0xa38 + 11e5e: 9900 ldr r1, [sp, #0] + 11e60: 9604 str r6, [sp, #16] + 11e62: ea88 0801 eor.w r8, r8, r1 + 11e66: 9e02 ldr r6, [sp, #8] + 11e68: f8da 1184 ldr.w r1, [sl, #388] ; 0x184 + 11e6c: 9501 str r5, [sp, #4] + 11e6e: 4071 eors r1, r6 + 11e70: ea81 0607 eor.w r6, r1, r7 + 11e74: f8da 718c ldr.w r7, [sl, #396] ; 0x18c + 11e78: 9901 ldr r1, [sp, #4] + 11e7a: ea8c 0c07 eor.w ip, ip, r7 + 11e7e: f8da 7188 ldr.w r7, [sl, #392] ; 0x188 + 11e82: f3cb 2b07 ubfx fp, fp, #8, #8 + 11e86: 404f eors r7, r1 + 11e88: eb03 0b8b add.w fp, r3, fp, lsl #2 + 11e8c: 9903 ldr r1, [sp, #12] + 11e8e: f8d0 0e38 ldr.w r0, [r0, #3640] ; 0xe38 + 11e92: ea88 0404 eor.w r4, r8, r4 + 11e96: f8db 5e38 ldr.w r5, [fp, #3640] ; 0xe38 + 11e9a: ea87 0909 eor.w r9, r7, r9 + 11e9e: ea8c 0e01 eor.w lr, ip, r1 + 11ea2: ea89 0000 eor.w r0, r9, r0 + 11ea6: 0e27 lsrs r7, r4, #24 + 11ea8: ea8e 0505 eor.w r5, lr, r5 + 11eac: eb03 0787 add.w r7, r3, r7, lsl #2 + 11eb0: fa5f fe80 uxtb.w lr, r0 + 11eb4: f8d7 7238 ldr.w r7, [r7, #568] ; 0x238 + 11eb8: eb03 0e8e add.w lr, r3, lr, lsl #2 + 11ebc: f8cd e000 str.w lr, [sp] + 11ec0: 9904 ldr r1, [sp, #16] + 11ec2: 9701 str r7, [sp, #4] + 11ec4: 9f00 ldr r7, [sp, #0] + 11ec6: 4071 eors r1, r6 + 11ec8: b2ce uxtb r6, r1 + 11eca: ea4f 6b11 mov.w fp, r1, lsr #24 + 11ece: f8d7 7638 ldr.w r7, [r7, #1592] ; 0x638 + 11ed2: eb03 0686 add.w r6, r3, r6, lsl #2 + 11ed6: eb03 0b8b add.w fp, r3, fp, lsl #2 + 11eda: f8d6 6638 ldr.w r6, [r6, #1592] ; 0x638 + 11ede: f8db b238 ldr.w fp, [fp, #568] ; 0x238 + 11ee2: 9700 str r7, [sp, #0] + 11ee4: 9f01 ldr r7, [sp, #4] + 11ee6: ea4f 6910 mov.w r9, r0, lsr #24 + 11eea: fa5f f885 uxtb.w r8, r5 + 11eee: 4077 eors r7, r6 + 11ef0: eb03 0989 add.w r9, r3, r9, lsl #2 + 11ef4: 9e00 ldr r6, [sp, #0] + 11ef6: eb03 0888 add.w r8, r3, r8, lsl #2 + 11efa: f8d9 9238 ldr.w r9, [r9, #568] ; 0x238 + 11efe: f8d8 8638 ldr.w r8, [r8, #1592] ; 0x638 + 11f02: ea8b 0b06 eor.w fp, fp, r6 + 11f06: f8cd b008 str.w fp, [sp, #8] + 11f0a: ea89 0b08 eor.w fp, r9, r8 + 11f0e: f3c5 4907 ubfx r9, r5, #16, #8 + 11f12: eb03 0989 add.w r9, r3, r9, lsl #2 + 11f16: f8da 6190 ldr.w r6, [sl, #400] ; 0x190 + 11f1a: ea4f 6c15 mov.w ip, r5, lsr #24 + 11f1e: fa5f fe84 uxtb.w lr, r4 + 11f22: f3c5 2807 ubfx r8, r5, #8, #8 + 11f26: f8d9 5a38 ldr.w r5, [r9, #2616] ; 0xa38 + 11f2a: 407e eors r6, r7 + 11f2c: eb03 0c8c add.w ip, r3, ip, lsl #2 + 11f30: f3c1 4707 ubfx r7, r1, #16, #8 + 11f34: eb03 0e8e add.w lr, r3, lr, lsl #2 + 11f38: f3c1 2107 ubfx r1, r1, #8, #8 + 11f3c: 9500 str r5, [sp, #0] + 11f3e: f8dc c238 ldr.w ip, [ip, #568] ; 0x238 + 11f42: f8de e638 ldr.w lr, [lr, #1592] ; 0x638 + 11f46: eb03 0888 add.w r8, r3, r8, lsl #2 + 11f4a: eb03 0181 add.w r1, r3, r1, lsl #2 + 11f4e: f8d8 5e38 ldr.w r5, [r8, #3640] ; 0xe38 + 11f52: f8d1 8e38 ldr.w r8, [r1, #3640] ; 0xe38 + 11f56: 9900 ldr r1, [sp, #0] + 11f58: ea8c 090e eor.w r9, ip, lr + 11f5c: f3c4 4e07 ubfx lr, r4, #16, #8 + 11f60: 404e eors r6, r1 + 11f62: eb03 0e8e add.w lr, r3, lr, lsl #2 + 11f66: f8da 1194 ldr.w r1, [sl, #404] ; 0x194 + 11f6a: 9200 str r2, [sp, #0] + 11f6c: 9a02 ldr r2, [sp, #8] + 11f6e: f3c4 2c07 ubfx ip, r4, #8, #8 + 11f72: f8de ea38 ldr.w lr, [lr, #2616] ; 0xa38 + 11f76: f3c0 4407 ubfx r4, r0, #16, #8 + 11f7a: f3c0 2007 ubfx r0, r0, #8, #8 + 11f7e: 404a eors r2, r1 + 11f80: eb03 0080 add.w r0, r3, r0, lsl #2 + 11f84: f8d0 0e38 ldr.w r0, [r0, #3640] ; 0xe38 + 11f88: ea82 0e0e eor.w lr, r2, lr + 11f8c: eb03 0484 add.w r4, r3, r4, lsl #2 + 11f90: eb03 0787 add.w r7, r3, r7, lsl #2 + 11f94: f8da 1198 ldr.w r1, [sl, #408] ; 0x198 + 11f98: f8da 219c ldr.w r2, [sl, #412] ; 0x19c + 11f9c: 9501 str r5, [sp, #4] + 11f9e: f8d4 4a38 ldr.w r4, [r4, #2616] ; 0xa38 + 11fa2: f8da 5200 ldr.w r5, [sl, #512] ; 0x200 + 11fa6: eb03 0c8c add.w ip, r3, ip, lsl #2 + 11faa: f8d7 7a38 ldr.w r7, [r7, #2616] ; 0xa38 + 11fae: ea8b 0101 eor.w r1, fp, r1 + 11fb2: f8dc ce38 ldr.w ip, [ip, #3640] ; 0xe38 + 11fb6: ea89 0202 eor.w r2, r9, r2 + 11fba: 4046 eors r6, r0 + 11fbc: 9801 ldr r0, [sp, #4] + 11fbe: 404f eors r7, r1 + 11fc0: 4054 eors r4, r2 + 11fc2: 2d0a cmp r5, #10 + 11fc4: 9502 str r5, [sp, #8] + 11fc6: ea8e 0b00 eor.w fp, lr, r0 + 11fca: ea87 0c0c eor.w ip, r7, ip + 11fce: ea84 0808 eor.w r8, r4, r8 + 11fd2: bfd8 it le + 11fd4: f50a 71c8 addle.w r1, sl, #400 ; 0x190 + 11fd8: f340 8233 ble.w 12442 + 11fdc: ea4f 641b mov.w r4, fp, lsr #24 + 11fe0: eb03 0484 add.w r4, r3, r4, lsl #2 + 11fe4: f8d4 4238 ldr.w r4, [r4, #568] ; 0x238 + 11fe8: ea4f 6918 mov.w r9, r8, lsr #24 + 11fec: eb03 0989 add.w r9, r3, r9, lsl #2 + 11ff0: 9401 str r4, [sp, #4] + 11ff2: fa5f f08c uxtb.w r0, ip + 11ff6: f8d9 4238 ldr.w r4, [r9, #568] ; 0x238 + 11ffa: eb03 0080 add.w r0, r3, r0, lsl #2 + 11ffe: 9403 str r4, [sp, #12] + 12000: f8d0 0638 ldr.w r0, [r0, #1592] ; 0x638 + 12004: 9c01 ldr r4, [sp, #4] + 12006: fa5f fe88 uxtb.w lr, r8 + 1200a: b2f7 uxtb r7, r6 + 1200c: eb03 0e8e add.w lr, r3, lr, lsl #2 + 12010: eb03 0787 add.w r7, r3, r7, lsl #2 + 12014: 4044 eors r4, r0 + 12016: f8de 9638 ldr.w r9, [lr, #1592] ; 0x638 + 1201a: 9401 str r4, [sp, #4] + 1201c: f8d7 e638 ldr.w lr, [r7, #1592] ; 0x638 + 12020: 9c03 ldr r4, [sp, #12] + 12022: 0e35 lsrs r5, r6, #24 + 12024: ea84 0e0e eor.w lr, r4, lr + 12028: fa5f f18b uxtb.w r1, fp + 1202c: f3c6 4407 ubfx r4, r6, #16, #8 + 12030: eb03 0585 add.w r5, r3, r5, lsl #2 + 12034: eb03 0181 add.w r1, r3, r1, lsl #2 + 12038: eb03 0484 add.w r4, r3, r4, lsl #2 + 1203c: f8d1 1638 ldr.w r1, [r1, #1592] ; 0x638 + 12040: f8d4 4a38 ldr.w r4, [r4, #2616] ; 0xa38 + 12044: f8d5 5238 ldr.w r5, [r5, #568] ; 0x238 + 12048: 461a mov r2, r3 + 1204a: f3c8 4007 ubfx r0, r8, #16, #8 + 1204e: 9403 str r4, [sp, #12] + 12050: 404d eors r5, r1 + 12052: eb03 0080 add.w r0, r3, r0, lsl #2 + 12056: f8da 11a0 ldr.w r1, [sl, #416] ; 0x1a0 + 1205a: f3cc 2407 ubfx r4, ip, #8, #8 + 1205e: f8d0 0a38 ldr.w r0, [r0, #2616] ; 0xa38 + 12062: eb03 0484 add.w r4, r3, r4, lsl #2 + 12066: ea4f 671c mov.w r7, ip, lsr #24 + 1206a: eb03 0787 add.w r7, r3, r7, lsl #2 + 1206e: 404d eors r5, r1 + 12070: f8d4 1e38 ldr.w r1, [r4, #3640] ; 0xe38 + 12074: f8d7 7238 ldr.w r7, [r7, #568] ; 0x238 + 12078: 4045 eors r5, r0 + 1207a: 4069 eors r1, r5 + 1207c: f8da 01a4 ldr.w r0, [sl, #420] ; 0x1a4 + 12080: 9d01 ldr r5, [sp, #4] + 12082: f8cd e010 str.w lr, [sp, #16] + 12086: f3c8 2807 ubfx r8, r8, #8, #8 + 1208a: ea87 0e09 eor.w lr, r7, r9 + 1208e: f3cb 4707 ubfx r7, fp, #16, #8 + 12092: eb03 0888 add.w r8, r3, r8, lsl #2 + 12096: eb03 0787 add.w r7, r3, r7, lsl #2 + 1209a: 4068 eors r0, r5 + 1209c: 9d03 ldr r5, [sp, #12] + 1209e: f8d7 9a38 ldr.w r9, [r7, #2616] ; 0xa38 + 120a2: f3cb 2b07 ubfx fp, fp, #8, #8 + 120a6: f8d8 7e38 ldr.w r7, [r8, #3640] ; 0xe38 + 120aa: eb03 0b8b add.w fp, r3, fp, lsl #2 + 120ae: 4068 eors r0, r5 + 120b0: f3cc 4c07 ubfx ip, ip, #16, #8 + 120b4: f8db 4e38 ldr.w r4, [fp, #3640] ; 0xe38 + 120b8: eb03 0c8c add.w ip, r3, ip, lsl #2 + 120bc: ea80 0b07 eor.w fp, r0, r7 + 120c0: f8da 51ac ldr.w r5, [sl, #428] ; 0x1ac + 120c4: 9f04 ldr r7, [sp, #16] + 120c6: f8dc ca38 ldr.w ip, [ip, #2616] ; 0xa38 + 120ca: 407d eors r5, r7 + 120cc: f8da 71a8 ldr.w r7, [sl, #424] ; 0x1a8 + 120d0: ea85 0c0c eor.w ip, r5, ip + 120d4: f3c6 2607 ubfx r6, r6, #8, #8 + 120d8: ea8e 0707 eor.w r7, lr, r7 + 120dc: eb03 0686 add.w r6, r3, r6, lsl #2 + 120e0: ea8c 0e04 eor.w lr, ip, r4 + 120e4: fa5f f48b uxtb.w r4, fp + 120e8: f8d6 6e38 ldr.w r6, [r6, #3640] ; 0xe38 + 120ec: eb03 0484 add.w r4, r3, r4, lsl #2 + 120f0: f8d4 4638 ldr.w r4, [r4, #1592] ; 0x638 + 120f4: ea87 0909 eor.w r9, r7, r9 + 120f8: ea4f 6c1b mov.w ip, fp, lsr #24 + 120fc: ea89 0906 eor.w r9, r9, r6 + 12100: eb03 0c8c add.w ip, r3, ip, lsl #2 + 12104: ea4f 6811 mov.w r8, r1, lsr #24 + 12108: fa5f f789 uxtb.w r7, r9 + 1210c: fa5f f58e uxtb.w r5, lr + 12110: ea4f 601e mov.w r0, lr, lsr #24 + 12114: 9403 str r4, [sp, #12] + 12116: f8dc 4238 ldr.w r4, [ip, #568] ; 0x238 + 1211a: eb03 0787 add.w r7, r3, r7, lsl #2 + 1211e: eb03 0585 add.w r5, r3, r5, lsl #2 + 12122: eb03 0080 add.w r0, r3, r0, lsl #2 + 12126: eb03 0888 add.w r8, r3, r8, lsl #2 + 1212a: f8d8 8238 ldr.w r8, [r8, #568] ; 0x238 + 1212e: 9401 str r4, [sp, #4] + 12130: f8d7 c638 ldr.w ip, [r7, #1592] ; 0x638 + 12134: f8d5 7638 ldr.w r7, [r5, #1592] ; 0x638 + 12138: f8d0 5238 ldr.w r5, [r0, #568] ; 0x238 + 1213c: b2c8 uxtb r0, r1 + 1213e: eb03 0080 add.w r0, r3, r0, lsl #2 + 12142: f8d0 0638 ldr.w r0, [r0, #1592] ; 0x638 + 12146: 9c03 ldr r4, [sp, #12] + 12148: 4068 eors r0, r5 + 1214a: f3c1 4507 ubfx r5, r1, #16, #8 + 1214e: eb03 0585 add.w r5, r3, r5, lsl #2 + 12152: f8d5 5a38 ldr.w r5, [r5, #2616] ; 0xa38 + 12156: ea4f 6619 mov.w r6, r9, lsr #24 + 1215a: eb03 0686 add.w r6, r3, r6, lsl #2 + 1215e: 9503 str r5, [sp, #12] + 12160: f8da 51b0 ldr.w r5, [sl, #432] ; 0x1b0 + 12164: f8d6 6238 ldr.w r6, [r6, #568] ; 0x238 + 12168: ea88 0804 eor.w r8, r8, r4 + 1216c: 9005 str r0, [sp, #20] + 1216e: f3ce 4007 ubfx r0, lr, #16, #8 + 12172: ea88 0805 eor.w r8, r8, r5 + 12176: eb03 0080 add.w r0, r3, r0, lsl #2 + 1217a: f3c9 4507 ubfx r5, r9, #16, #8 + 1217e: f3ce 2e07 ubfx lr, lr, #8, #8 + 12182: f3c9 2907 ubfx r9, r9, #8, #8 + 12186: f3c1 2107 ubfx r1, r1, #8, #8 + 1218a: 4077 eors r7, r6 + 1218c: eb03 0e8e add.w lr, r3, lr, lsl #2 + 12190: f3cb 2607 ubfx r6, fp, #8, #8 + 12194: eb03 0181 add.w r1, r3, r1, lsl #2 + 12198: eb03 0585 add.w r5, r3, r5, lsl #2 + 1219c: f8d0 0a38 ldr.w r0, [r0, #2616] ; 0xa38 + 121a0: eb03 0389 add.w r3, r3, r9, lsl #2 + 121a4: 9c01 ldr r4, [sp, #4] + 121a6: eb02 0986 add.w r9, r2, r6, lsl #2 + 121aa: f8d5 5a38 ldr.w r5, [r5, #2616] ; 0xa38 + 121ae: f8d3 6e38 ldr.w r6, [r3, #3640] ; 0xe38 + 121b2: ea88 0000 eor.w r0, r8, r0 + 121b6: 9704 str r7, [sp, #16] + 121b8: ea84 0c0c eor.w ip, r4, ip + 121bc: 9501 str r5, [sp, #4] + 121be: f3cb 4407 ubfx r4, fp, #16, #8 + 121c2: f8da 51b8 ldr.w r5, [sl, #440] ; 0x1b8 + 121c6: f8dd b010 ldr.w fp, [sp, #16] + 121ca: 4046 eors r6, r0 + 121cc: f8da 01b4 ldr.w r0, [sl, #436] ; 0x1b4 + 121d0: f8d9 3e38 ldr.w r3, [r9, #3640] ; 0xe38 + 121d4: ea8c 0c00 eor.w ip, ip, r0 + 121d8: ea8b 0905 eor.w r9, fp, r5 + 121dc: f8da 01bc ldr.w r0, [sl, #444] ; 0x1bc + 121e0: 9d05 ldr r5, [sp, #20] + 121e2: eb02 0484 add.w r4, r2, r4, lsl #2 + 121e6: f8d4 4a38 ldr.w r4, [r4, #2616] ; 0xa38 + 121ea: 4068 eors r0, r5 + 121ec: 9d03 ldr r5, [sp, #12] + 121ee: f8d1 1e38 ldr.w r1, [r1, #3640] ; 0xe38 + 121f2: ea8c 0b05 eor.w fp, ip, r5 + 121f6: ea89 0c04 eor.w ip, r9, r4 + 121fa: 9d02 ldr r5, [sp, #8] + 121fc: 9c01 ldr r4, [sp, #4] + 121fe: f8de 7e38 ldr.w r7, [lr, #3640] ; 0xe38 + 12202: ea80 0804 eor.w r8, r0, r4 + 12206: 2d0c cmp r5, #12 + 12208: ea8c 0c01 eor.w ip, ip, r1 + 1220c: ea8b 0b07 eor.w fp, fp, r7 + 12210: ea88 0803 eor.w r8, r8, r3 + 12214: bfd8 it le + 12216: f50a 71d8 addle.w r1, sl, #432 ; 0x1b0 + 1221a: f340 8112 ble.w 12442 + 1221e: ea4f 641b mov.w r4, fp, lsr #24 + 12222: fa5f f38c uxtb.w r3, ip + 12226: eb02 0484 add.w r4, r2, r4, lsl #2 + 1222a: eb02 0383 add.w r3, r2, r3, lsl #2 + 1222e: f8d4 4238 ldr.w r4, [r4, #568] ; 0x238 + 12232: f8d3 3638 ldr.w r3, [r3, #1592] ; 0x638 + 12236: ea4f 6916 mov.w r9, r6, lsr #24 + 1223a: 4063 eors r3, r4 + 1223c: 9303 str r3, [sp, #12] + 1223e: fa5f fe8b uxtb.w lr, fp + 12242: ea4f 6718 mov.w r7, r8, lsr #24 + 12246: fa5f f188 uxtb.w r1, r8 + 1224a: b2f5 uxtb r5, r6 + 1224c: ea4f 601c mov.w r0, ip, lsr #24 + 12250: f3c8 4307 ubfx r3, r8, #16, #8 + 12254: eb02 0989 add.w r9, r2, r9, lsl #2 + 12258: eb02 0e8e add.w lr, r2, lr, lsl #2 + 1225c: eb02 0787 add.w r7, r2, r7, lsl #2 + 12260: eb02 0181 add.w r1, r2, r1, lsl #2 + 12264: eb02 0585 add.w r5, r2, r5, lsl #2 + 12268: eb02 0080 add.w r0, r2, r0, lsl #2 + 1226c: eb02 0383 add.w r3, r2, r3, lsl #2 + 12270: f8d9 9238 ldr.w r9, [r9, #568] ; 0x238 + 12274: f8d1 1638 ldr.w r1, [r1, #1592] ; 0x638 + 12278: f8d5 5638 ldr.w r5, [r5, #1592] ; 0x638 + 1227c: f8d0 0238 ldr.w r0, [r0, #568] ; 0x238 + 12280: f8d3 3a38 ldr.w r3, [r3, #2616] ; 0xa38 + 12284: f8de e638 ldr.w lr, [lr, #1592] ; 0x638 + 12288: f8d7 7238 ldr.w r7, [r7, #568] ; 0x238 + 1228c: 9301 str r3, [sp, #4] + 1228e: 406f eors r7, r5 + 12290: ea89 0e0e eor.w lr, r9, lr + 12294: f3cc 4307 ubfx r3, ip, #16, #8 + 12298: ea80 0901 eor.w r9, r0, r1 + 1229c: f3c6 4107 ubfx r1, r6, #16, #8 + 122a0: 9704 str r7, [sp, #16] + 122a2: eb02 0181 add.w r1, r2, r1, lsl #2 + 122a6: eb02 0383 add.w r3, r2, r3, lsl #2 + 122aa: f8da 71c0 ldr.w r7, [sl, #448] ; 0x1c0 + 122ae: f8d1 0a38 ldr.w r0, [r1, #2616] ; 0xa38 + 122b2: f3c6 2607 ubfx r6, r6, #8, #8 + 122b6: f8d3 1a38 ldr.w r1, [r3, #2616] ; 0xa38 + 122ba: 9b01 ldr r3, [sp, #4] + 122bc: eb02 0686 add.w r6, r2, r6, lsl #2 + 122c0: ea8e 0e07 eor.w lr, lr, r7 + 122c4: f3cb 4407 ubfx r4, fp, #16, #8 + 122c8: f8d6 7e38 ldr.w r7, [r6, #3640] ; 0xe38 + 122cc: ea8e 0e03 eor.w lr, lr, r3 + 122d0: 9e03 ldr r6, [sp, #12] + 122d2: eb02 0484 add.w r4, r2, r4, lsl #2 + 122d6: f8da 31c4 ldr.w r3, [sl, #452] ; 0x1c4 + 122da: f8d4 4a38 ldr.w r4, [r4, #2616] ; 0xa38 + 122de: f3cc 2c07 ubfx ip, ip, #8, #8 + 122e2: f3cb 2b07 ubfx fp, fp, #8, #8 + 122e6: eb02 0c8c add.w ip, r2, ip, lsl #2 + 122ea: eb02 0b8b add.w fp, r2, fp, lsl #2 + 122ee: 4073 eors r3, r6 + 122f0: ea83 0600 eor.w r6, r3, r0 + 122f4: 9402 str r4, [sp, #8] + 122f6: f8db 5e38 ldr.w r5, [fp, #3640] ; 0xe38 + 122fa: f8dc 4e38 ldr.w r4, [ip, #3640] ; 0xe38 + 122fe: f8da 31c8 ldr.w r3, [sl, #456] ; 0x1c8 + 12302: f8dd b010 ldr.w fp, [sp, #16] + 12306: f8da 01cc ldr.w r0, [sl, #460] ; 0x1cc + 1230a: ea8e 0404 eor.w r4, lr, r4 + 1230e: ea8b 0e00 eor.w lr, fp, r0 + 12312: ea89 0003 eor.w r0, r9, r3 + 12316: 9b02 ldr r3, [sp, #8] + 12318: f3c8 2807 ubfx r8, r8, #8, #8 + 1231c: ea80 0903 eor.w r9, r0, r3 + 12320: ea8e 0101 eor.w r1, lr, r1 + 12324: eb02 0888 add.w r8, r2, r8, lsl #2 + 12328: 404d eors r5, r1 + 1232a: f8d8 8e38 ldr.w r8, [r8, #3640] ; 0xe38 + 1232e: ea89 0107 eor.w r1, r9, r7 + 12332: ea4f 6c11 mov.w ip, r1, lsr #24 + 12336: fa5f fe85 uxtb.w lr, r5 + 1233a: ea88 0306 eor.w r3, r8, r6 + 1233e: eb02 0c8c add.w ip, r2, ip, lsl #2 + 12342: eb02 0e8e add.w lr, r2, lr, lsl #2 + 12346: 0e1f lsrs r7, r3, #24 + 12348: f8de e638 ldr.w lr, [lr, #1592] ; 0x638 + 1234c: 0e26 lsrs r6, r4, #24 + 1234e: b2d8 uxtb r0, r3 + 12350: fa5f f981 uxtb.w r9, r1 + 12354: f8dc c238 ldr.w ip, [ip, #568] ; 0x238 + 12358: eb02 0b87 add.w fp, r2, r7, lsl #2 + 1235c: eb02 0686 add.w r6, r2, r6, lsl #2 + 12360: eb02 0080 add.w r0, r2, r0, lsl #2 + 12364: eb02 0989 add.w r9, r2, r9, lsl #2 + 12368: f8d0 0638 ldr.w r0, [r0, #1592] ; 0x638 + 1236c: f8d9 9638 ldr.w r9, [r9, #1592] ; 0x638 + 12370: f8d6 6238 ldr.w r6, [r6, #568] ; 0x238 + 12374: f8db b238 ldr.w fp, [fp, #568] ; 0x238 + 12378: ea8c 0c0e eor.w ip, ip, lr + 1237c: f3c5 4e07 ubfx lr, r5, #16, #8 + 12380: eb02 0e8e add.w lr, r2, lr, lsl #2 + 12384: ea4f 6815 mov.w r8, r5, lsr #24 + 12388: f3c5 2507 ubfx r5, r5, #8, #8 + 1238c: 4046 eors r6, r0 + 1238e: b2e7 uxtb r7, r4 + 12390: f8de 0a38 ldr.w r0, [lr, #2616] ; 0xa38 + 12394: ea8b 0b09 eor.w fp, fp, r9 + 12398: eb02 0985 add.w r9, r2, r5, lsl #2 + 1239c: f3c4 4507 ubfx r5, r4, #16, #8 + 123a0: eb02 0888 add.w r8, r2, r8, lsl #2 + 123a4: eb02 0787 add.w r7, r2, r7, lsl #2 + 123a8: eb02 0585 add.w r5, r2, r5, lsl #2 + 123ac: f8d7 7638 ldr.w r7, [r7, #1592] ; 0x638 + 123b0: f8d8 8238 ldr.w r8, [r8, #568] ; 0x238 + 123b4: 9002 str r0, [sp, #8] + 123b6: f8d5 5a38 ldr.w r5, [r5, #2616] ; 0xa38 + 123ba: ea88 0807 eor.w r8, r8, r7 + 123be: 9501 str r5, [sp, #4] + 123c0: f8da 51d4 ldr.w r5, [sl, #468] ; 0x1d4 + 123c4: f8da 01d0 ldr.w r0, [sl, #464] ; 0x1d0 + 123c8: ea8b 0b05 eor.w fp, fp, r5 + 123cc: f8da 51d8 ldr.w r5, [sl, #472] ; 0x1d8 + 123d0: f3c1 4707 ubfx r7, r1, #16, #8 + 123d4: ea8c 0c05 eor.w ip, ip, r5 + 123d8: f8da 51dc ldr.w r5, [sl, #476] ; 0x1dc + 123dc: f3c3 4e07 ubfx lr, r3, #16, #8 + 123e0: ea88 0805 eor.w r8, r8, r5 + 123e4: 9d02 ldr r5, [sp, #8] + 123e6: eb02 0787 add.w r7, r2, r7, lsl #2 + 123ea: 4070 eors r0, r6 + 123ec: eb02 0e8e add.w lr, r2, lr, lsl #2 + 123f0: f3c3 2607 ubfx r6, r3, #8, #8 + 123f4: f3c4 2407 ubfx r4, r4, #8, #8 + 123f8: f3c1 2107 ubfx r1, r1, #8, #8 + 123fc: eb02 0181 add.w r1, r2, r1, lsl #2 + 12400: eb02 0484 add.w r4, r2, r4, lsl #2 + 12404: 4068 eors r0, r5 + 12406: eb02 0286 add.w r2, r2, r6, lsl #2 + 1240a: f8d7 7a38 ldr.w r7, [r7, #2616] ; 0xa38 + 1240e: f8de 3a38 ldr.w r3, [lr, #2616] ; 0xa38 + 12412: 9d01 ldr r5, [sp, #4] + 12414: f8d1 6e38 ldr.w r6, [r1, #3640] ; 0xe38 + 12418: f8d2 2e38 ldr.w r2, [r2, #3640] ; 0xe38 + 1241c: f8d9 1e38 ldr.w r1, [r9, #3640] ; 0xe38 + 12420: f8d4 4e38 ldr.w r4, [r4, #3640] ; 0xe38 + 12424: ea8b 0b05 eor.w fp, fp, r5 + 12428: ea8c 0c03 eor.w ip, ip, r3 + 1242c: ea88 0807 eor.w r8, r8, r7 + 12430: ea8b 0b01 eor.w fp, fp, r1 + 12434: 4046 eors r6, r0 + 12436: ea8c 0c04 eor.w ip, ip, r4 + 1243a: ea88 0802 eor.w r8, r8, r2 + 1243e: f50a 71e8 add.w r1, sl, #464 ; 0x1d0 + 12442: f644 2370 movw r3, #19056 ; 0x4a70 + 12446: f2c0 0303 movt r3, #3 + 1244a: fa5f f28b uxtb.w r2, fp + 1244e: ea4f 691b mov.w r9, fp, lsr #24 + 12452: eb03 0282 add.w r2, r3, r2, lsl #2 + 12456: eb03 0989 add.w r9, r3, r9, lsl #2 + 1245a: f8d2 0140 ldr.w r0, [r2, #320] ; 0x140 + 1245e: f8d9 2140 ldr.w r2, [r9, #320] ; 0x140 + 12462: ea4f 6918 mov.w r9, r8, lsr #24 + 12466: 9202 str r2, [sp, #8] + 12468: 690a ldr r2, [r1, #16] + 1246a: eb03 0989 add.w r9, r3, r9, lsl #2 + 1246e: 4042 eors r2, r0 + 12470: fa5f fe8c uxtb.w lr, ip + 12474: f8d9 0140 ldr.w r0, [r9, #320] ; 0x140 + 12478: 0e34 lsrs r4, r6, #24 + 1247a: eb03 0e8e add.w lr, r3, lr, lsl #2 + 1247e: eb03 0484 add.w r4, r3, r4, lsl #2 + 12482: 9001 str r0, [sp, #4] + 12484: f8de e140 ldr.w lr, [lr, #320] ; 0x140 + 12488: 6948 ldr r0, [r1, #20] + 1248a: f8d4 4140 ldr.w r4, [r4, #320] ; 0x140 + 1248e: fa5f f788 uxtb.w r7, r8 + 12492: b2f5 uxtb r5, r6 + 12494: f3c8 4a07 ubfx sl, r8, #16, #8 + 12498: eb03 0a8a add.w sl, r3, sl, lsl #2 + 1249c: ea82 6404 eor.w r4, r2, r4, lsl #24 + 124a0: eb03 0787 add.w r7, r3, r7, lsl #2 + 124a4: eb03 0585 add.w r5, r3, r5, lsl #2 + 124a8: ea8e 0e00 eor.w lr, lr, r0 + 124ac: ea4f 601c mov.w r0, ip, lsr #24 + 124b0: f8da 9140 ldr.w r9, [sl, #320] ; 0x140 + 124b4: 9403 str r4, [sp, #12] + 124b6: f8d7 7140 ldr.w r7, [r7, #320] ; 0x140 + 124ba: 698c ldr r4, [r1, #24] + 124bc: f8d5 5140 ldr.w r5, [r5, #320] ; 0x140 + 124c0: 69c9 ldr r1, [r1, #28] + 124c2: eb03 0080 add.w r0, r3, r0, lsl #2 + 124c6: f3c6 4a07 ubfx sl, r6, #16, #8 + 124ca: eb03 0a8a add.w sl, r3, sl, lsl #2 + 124ce: f8d0 0140 ldr.w r0, [r0, #320] ; 0x140 + 124d2: 9a02 ldr r2, [sp, #8] + 124d4: 407c eors r4, r7 + 124d6: 4069 eors r1, r5 + 124d8: f8da 5140 ldr.w r5, [sl, #320] ; 0x140 + 124dc: f3cc 4a07 ubfx sl, ip, #16, #8 + 124e0: eb03 0a8a add.w sl, r3, sl, lsl #2 + 124e4: ea84 6000 eor.w r0, r4, r0, lsl #24 + 124e8: f3cc 2c07 ubfx ip, ip, #8, #8 + 124ec: f3cb 4407 ubfx r4, fp, #16, #8 + 124f0: f8da 7140 ldr.w r7, [sl, #320] ; 0x140 + 124f4: ea8e 6e02 eor.w lr, lr, r2, lsl #24 + 124f8: f8dd a00c ldr.w sl, [sp, #12] + 124fc: 9a01 ldr r2, [sp, #4] + 124fe: eb03 0c8c add.w ip, r3, ip, lsl #2 + 12502: eb03 0484 add.w r4, r3, r4, lsl #2 + 12506: f3c8 2807 ubfx r8, r8, #8, #8 + 1250a: f3c6 2607 ubfx r6, r6, #8, #8 + 1250e: f3cb 2b07 ubfx fp, fp, #8, #8 + 12512: f8d4 4140 ldr.w r4, [r4, #320] ; 0x140 + 12516: eb03 0888 add.w r8, r3, r8, lsl #2 + 1251a: eb03 0686 add.w r6, r3, r6, lsl #2 + 1251e: f8dc c140 ldr.w ip, [ip, #320] ; 0x140 + 12522: eb03 0b8b add.w fp, r3, fp, lsl #2 + 12526: f8db 3140 ldr.w r3, [fp, #320] ; 0x140 + 1252a: f8d6 6140 ldr.w r6, [r6, #320] ; 0x140 + 1252e: ea81 6102 eor.w r1, r1, r2, lsl #24 + 12532: f8d8 8140 ldr.w r8, [r8, #320] ; 0x140 + 12536: ea8a 4209 eor.w r2, sl, r9, lsl #16 + 1253a: f8dd b000 ldr.w fp, [sp] + 1253e: ea82 2c0c eor.w ip, r2, ip, lsl #8 + 12542: ea8e 4e05 eor.w lr, lr, r5, lsl #16 + 12546: ea80 4004 eor.w r0, r0, r4, lsl #16 + 1254a: ea81 4707 eor.w r7, r1, r7, lsl #16 + 1254e: ea80 2006 eor.w r0, r0, r6, lsl #8 + 12552: ea87 2703 eor.w r7, r7, r3, lsl #8 + 12556: ea8e 2808 eor.w r8, lr, r8, lsl #8 + 1255a: ea4f 631c mov.w r3, ip, lsr #24 + 1255e: ea4f 4a1c mov.w sl, ip, lsr #16 + 12562: ea4f 291c mov.w r9, ip, lsr #8 + 12566: ea4f 6e18 mov.w lr, r8, lsr #24 + 1256a: ea4f 4618 mov.w r6, r8, lsr #16 + 1256e: ea4f 2518 mov.w r5, r8, lsr #8 + 12572: f88b 3000 strb.w r3, [fp] + 12576: f88b c003 strb.w ip, [fp, #3] + 1257a: f88b 8007 strb.w r8, [fp, #7] + 1257e: 0e04 lsrs r4, r0, #24 + 12580: 0c01 lsrs r1, r0, #16 + 12582: 0a02 lsrs r2, r0, #8 + 12584: 0e3b lsrs r3, r7, #24 + 12586: ea4f 4c17 mov.w ip, r7, lsr #16 + 1258a: ea4f 2817 mov.w r8, r7, lsr #8 + 1258e: f88b 000b strb.w r0, [fp, #11] + 12592: f88b a001 strb.w sl, [fp, #1] + 12596: f88b 9002 strb.w r9, [fp, #2] + 1259a: f88b e004 strb.w lr, [fp, #4] + 1259e: f88b 6005 strb.w r6, [fp, #5] + 125a2: f88b 5006 strb.w r5, [fp, #6] + 125a6: f88b 4008 strb.w r4, [fp, #8] + 125aa: f88b 1009 strb.w r1, [fp, #9] + 125ae: f88b 200a strb.w r2, [fp, #10] + 125b2: f88b 300c strb.w r3, [fp, #12] + 125b6: f88b c00d strb.w ip, [fp, #13] + 125ba: f88b 700f strb.w r7, [fp, #15] + 125be: f88b 800e strb.w r8, [fp, #14] + 125c2: b007 add sp, #28 + 125c4: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +000125c8 : + 125c8: 460b mov r3, r1 + 125ca: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 125ce: f101 0b07 add.w fp, r1, #7 + 125d2: ea33 0321 bics.w r3, r3, r1, asr #32 + 125d6: bf28 it cs + 125d8: 465b movcs r3, fp + 125da: 4614 mov r4, r2 + 125dc: f24f 4765 movw r7, #62565 ; 0xf465 + 125e0: f5ad 7d55 sub.w sp, sp, #852 ; 0x354 + 125e4: 10db asrs r3, r3, #3 + 125e6: 9105 str r1, [sp, #20] + 125e8: 2280 movs r2, #128 ; 0x80 + 125ea: 99de ldr r1, [sp, #888] ; 0x378 + 125ec: 4606 mov r6, r0 + 125ee: f10d 0b1c add.w fp, sp, #28 + 125f2: a853 add r0, sp, #332 ; 0x14c + 125f4: 9303 str r3, [sp, #12] + 125f6: f2c0 0700 movt r7, #0 + 125fa: f7fd fd03 bl 10004 + 125fe: 4621 mov r1, r4 + 12600: 4658 mov r0, fp + 12602: 2208 movs r2, #8 + 12604: 47b8 blx r7 + 12606: 9b03 ldr r3, [sp, #12] + 12608: 2b00 cmp r3, #0 + 1260a: dd0b ble.n 12624 + 1260c: 4698 mov r8, r3 + 1260e: ad13 add r5, sp, #76 ; 0x4c + 12610: 2400 movs r4, #0 + 12612: 2208 movs r2, #8 + 12614: 4628 mov r0, r5 + 12616: 4631 mov r1, r6 + 12618: 3401 adds r4, #1 + 1261a: 4415 add r5, r2 + 1261c: 4416 add r6, r2 + 1261e: 47b8 blx r7 + 12620: 4544 cmp r4, r8 + 12622: d1f6 bne.n 12612 + 12624: 9b03 ldr r3, [sp, #12] + 12626: f04f 0800 mov.w r8, #0 + 1262a: b2db uxtb r3, r3 + 1262c: 9304 str r3, [sp, #16] + 1262e: f24f 5311 movw r3, #62737 ; 0xf511 + 12632: f2c0 0300 movt r3, #0 + 12636: 9301 str r3, [sp, #4] + 12638: 2306 movs r3, #6 + 1263a: 9302 str r3, [sp, #8] + 1263c: 9b03 ldr r3, [sp, #12] + 1263e: f103 0a01 add.w sl, r3, #1 + 12642: 9b03 ldr r3, [sp, #12] + 12644: 2b00 cmp r3, #0 + 12646: dd34 ble.n 126b2 + 12648: ae13 add r6, sp, #76 ; 0x4c + 1264a: 4633 mov r3, r6 + 1264c: f04f 0901 mov.w r9, #1 + 12650: 464e mov r6, r9 + 12652: 4699 mov r9, r3 + 12654: ac0f add r4, sp, #60 ; 0x3c + 12656: ad09 add r5, sp, #36 ; 0x24 + 12658: 4659 mov r1, fp + 1265a: 2208 movs r2, #8 + 1265c: a80b add r0, sp, #44 ; 0x2c + 1265e: 47b8 blx r7 + 12660: 4649 mov r1, r9 + 12662: 2208 movs r2, #8 + 12664: a80d add r0, sp, #52 ; 0x34 + 12666: 47b8 blx r7 + 12668: a853 add r0, sp, #332 ; 0x14c + 1266a: a90b add r1, sp, #44 ; 0x2c + 1266c: 4622 mov r2, r4 + 1266e: f7fd feaf bl 103d0 + 12672: 2208 movs r2, #8 + 12674: 9b01 ldr r3, [sp, #4] + 12676: 4628 mov r0, r5 + 12678: 2100 movs r1, #0 + 1267a: 4798 blx r3 + 1267c: 79ea ldrb r2, [r5, #7] + 1267e: eb08 0306 add.w r3, r8, r6 + 12682: 4313 orrs r3, r2 + 12684: 71eb strb r3, [r5, #7] + 12686: 2300 movs r3, #0 + 12688: 5ce9 ldrb r1, [r5, r3] + 1268a: 5ce2 ldrb r2, [r4, r3] + 1268c: 404a eors r2, r1 + 1268e: f80b 2003 strb.w r2, [fp, r3] + 12692: 3301 adds r3, #1 + 12694: 2b08 cmp r3, #8 + 12696: d1f7 bne.n 12688 + 12698: 2300 movs r3, #0 + 1269a: 18e2 adds r2, r4, r3 + 1269c: 7a12 ldrb r2, [r2, #8] + 1269e: f809 2003 strb.w r2, [r9, r3] + 126a2: 3301 adds r3, #1 + 126a4: 2b08 cmp r3, #8 + 126a6: d1f8 bne.n 1269a + 126a8: 3601 adds r6, #1 + 126aa: 4556 cmp r6, sl + 126ac: f109 0908 add.w r9, r9, #8 + 126b0: d1d2 bne.n 12658 + 126b2: 9b04 ldr r3, [sp, #16] + 126b4: 4498 add r8, r3 + 126b6: 9b02 ldr r3, [sp, #8] + 126b8: fa5f f888 uxtb.w r8, r8 + 126bc: 3b01 subs r3, #1 + 126be: 9302 str r3, [sp, #8] + 126c0: d1bf bne.n 12642 + 126c2: 4659 mov r1, fp + 126c4: 98e0 ldr r0, [sp, #896] ; 0x380 + 126c6: 2208 movs r2, #8 + 126c8: 47b8 blx r7 + 126ca: 9b03 ldr r3, [sp, #12] + 126cc: 2b00 cmp r3, #0 + 126ce: dd0e ble.n 126ee + 126d0: 9de0 ldr r5, [sp, #896] ; 0x380 + 126d2: 9e02 ldr r6, [sp, #8] + 126d4: f8dd 800c ldr.w r8, [sp, #12] + 126d8: 3508 adds r5, #8 + 126da: ac13 add r4, sp, #76 ; 0x4c + 126dc: 2208 movs r2, #8 + 126de: 4628 mov r0, r5 + 126e0: 4621 mov r1, r4 + 126e2: 3601 adds r6, #1 + 126e4: 4415 add r5, r2 + 126e6: 4414 add r4, r2 + 126e8: 47b8 blx r7 + 126ea: 4546 cmp r6, r8 + 126ec: d1f6 bne.n 126dc + 126ee: 9b05 ldr r3, [sp, #20] + 126f0: 9ae1 ldr r2, [sp, #900] ; 0x384 + 126f2: 3308 adds r3, #8 + 126f4: 8013 strh r3, [r2, #0] + 126f6: f50d 7d55 add.w sp, sp, #852 ; 0x354 + 126fa: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 126fe: bf00 nop + +00012700 : + 12700: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 12704: 1dcc adds r4, r1, #7 + 12706: ea14 0421 ands.w r4, r4, r1, asr #32 + 1270a: bf38 it cc + 1270c: 460c movcc r4, r1 + 1270e: 4606 mov r6, r0 + 12710: f24f 4965 movw r9, #62565 ; 0xf465 + 12714: f5ad 7d57 sub.w sp, sp, #860 ; 0x35c + 12718: 10e4 asrs r4, r4, #3 + 1271a: 1e63 subs r3, r4, #1 + 1271c: 4611 mov r1, r2 + 1271e: a855 add r0, sp, #340 ; 0x154 + 12720: 2280 movs r2, #128 ; 0x80 + 12722: f10d 0a24 add.w sl, sp, #36 ; 0x24 + 12726: 9306 str r3, [sp, #24] + 12728: f2c0 0900 movt r9, #0 + 1272c: f7fd fc6a bl 10004 + 12730: 4631 mov r1, r6 + 12732: 4650 mov r0, sl + 12734: 2208 movs r2, #8 + 12736: 47c8 blx r9 + 12738: 9b06 ldr r3, [sp, #24] + 1273a: 2b00 cmp r3, #0 + 1273c: ab15 add r3, sp, #84 ; 0x54 + 1273e: 9307 str r3, [sp, #28] + 12740: dd13 ble.n 1276a + 12742: 461f mov r7, r3 + 12744: 464b mov r3, r9 + 12746: 46a1 mov r9, r4 + 12748: 461c mov r4, r3 + 1274a: f8dd 8018 ldr.w r8, [sp, #24] + 1274e: 3608 adds r6, #8 + 12750: 2500 movs r5, #0 + 12752: 2208 movs r2, #8 + 12754: 4638 mov r0, r7 + 12756: 4631 mov r1, r6 + 12758: 3501 adds r5, #1 + 1275a: 4417 add r7, r2 + 1275c: 4416 add r6, r2 + 1275e: 47a0 blx r4 + 12760: 4545 cmp r5, r8 + 12762: d1f6 bne.n 12752 + 12764: 4623 mov r3, r4 + 12766: 464c mov r4, r9 + 12768: 4699 mov r9, r3 + 1276a: 9b06 ldr r3, [sp, #24] + 1276c: 1e61 subs r1, r4, #1 + 1276e: b2db uxtb r3, r3 + 12770: eb03 0283 add.w r2, r3, r3, lsl #2 + 12774: 9304 str r3, [sp, #16] + 12776: 9b07 ldr r3, [sp, #28] + 12778: 3c02 subs r4, #2 + 1277a: eb03 03c4 add.w r3, r3, r4, lsl #3 + 1277e: 9305 str r3, [sp, #20] + 12780: f24f 5311 movw r3, #62737 ; 0xf511 + 12784: f2c0 0300 movt r3, #0 + 12788: 464f mov r7, r9 + 1278a: 440a add r2, r1 + 1278c: b2d2 uxtb r2, r2 + 1278e: 9300 str r3, [sp, #0] + 12790: 2306 movs r3, #6 + 12792: 9403 str r4, [sp, #12] + 12794: 9202 str r2, [sp, #8] + 12796: 9301 str r3, [sp, #4] + 12798: ae0b add r6, sp, #44 ; 0x2c + 1279a: f10d 0b44 add.w fp, sp, #68 ; 0x44 + 1279e: 9b03 ldr r3, [sp, #12] + 127a0: 2b00 cmp r3, #0 + 127a2: db36 blt.n 12812 + 127a4: f8dd 9014 ldr.w r9, [sp, #20] + 127a8: 9d02 ldr r5, [sp, #8] + 127aa: 9c03 ldr r4, [sp, #12] + 127ac: 9b00 ldr r3, [sp, #0] + 127ae: 4630 mov r0, r6 + 127b0: 2100 movs r1, #0 + 127b2: 2208 movs r2, #8 + 127b4: 4798 blx r3 + 127b6: 79f3 ldrb r3, [r6, #7] + 127b8: f04f 0800 mov.w r8, #0 + 127bc: 432b orrs r3, r5 + 127be: 71f3 strb r3, [r6, #7] + 127c0: f816 2008 ldrb.w r2, [r6, r8] + 127c4: f81a 3008 ldrb.w r3, [sl, r8] + 127c8: 4053 eors r3, r2 + 127ca: f80b 3008 strb.w r3, [fp, r8] + 127ce: f108 0801 add.w r8, r8, #1 + 127d2: f1b8 0f08 cmp.w r8, #8 + 127d6: d1f3 bne.n 127c0 + 127d8: 4649 mov r1, r9 + 127da: 4642 mov r2, r8 + 127dc: a813 add r0, sp, #76 ; 0x4c + 127de: 47b8 blx r7 + 127e0: a855 add r0, sp, #340 ; 0x154 + 127e2: 4659 mov r1, fp + 127e4: aa0d add r2, sp, #52 ; 0x34 + 127e6: f7fe fe5d bl 114a4 + 127ea: 4650 mov r0, sl + 127ec: a90d add r1, sp, #52 ; 0x34 + 127ee: 4642 mov r2, r8 + 127f0: 47b8 blx r7 + 127f2: 2300 movs r3, #0 + 127f4: aa0d add r2, sp, #52 ; 0x34 + 127f6: 441a add r2, r3 + 127f8: 7a12 ldrb r2, [r2, #8] + 127fa: f809 2003 strb.w r2, [r9, r3] + 127fe: 3301 adds r3, #1 + 12800: 2b08 cmp r3, #8 + 12802: d1f7 bne.n 127f4 + 12804: 3c01 subs r4, #1 + 12806: 3d01 subs r5, #1 + 12808: 1c63 adds r3, r4, #1 + 1280a: b2ed uxtb r5, r5 + 1280c: f1a9 0908 sub.w r9, r9, #8 + 12810: d1cc bne.n 127ac + 12812: 9b02 ldr r3, [sp, #8] + 12814: 9904 ldr r1, [sp, #16] + 12816: ebc1 0903 rsb r9, r1, r3 + 1281a: 9b01 ldr r3, [sp, #4] + 1281c: fa5f f989 uxtb.w r9, r9 + 12820: 3b01 subs r3, #1 + 12822: f8cd 9008 str.w r9, [sp, #8] + 12826: 9301 str r3, [sp, #4] + 12828: d1b9 bne.n 1279e + 1282a: 4651 mov r1, sl + 1282c: 98e0 ldr r0, [sp, #896] ; 0x380 + 1282e: 2208 movs r2, #8 + 12830: 47b8 blx r7 + 12832: 9b06 ldr r3, [sp, #24] + 12834: 46b9 mov r9, r7 + 12836: 2b00 cmp r3, #0 + 12838: dd0d ble.n 12856 + 1283a: 461f mov r7, r3 + 1283c: 9ce0 ldr r4, [sp, #896] ; 0x380 + 1283e: 9e07 ldr r6, [sp, #28] + 12840: 9d01 ldr r5, [sp, #4] + 12842: 3408 adds r4, #8 + 12844: 2208 movs r2, #8 + 12846: 4620 mov r0, r4 + 12848: 4631 mov r1, r6 + 1284a: 3501 adds r5, #1 + 1284c: 4414 add r4, r2 + 1284e: 4416 add r6, r2 + 12850: 47c8 blx r9 + 12852: 42bd cmp r5, r7 + 12854: d1f6 bne.n 12844 + 12856: f50d 7d57 add.w sp, sp, #860 ; 0x35c + 1285a: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 1285e: bf00 nop + +00012860 : + 12860: 2900 cmp r1, #0 + 12862: dd15 ble.n 12890 + 12864: b410 push {r4} + 12866: f644 74b0 movw r4, #20400 ; 0x4fb0 + 1286a: f2c0 0403 movt r4, #3 + 1286e: 4401 add r1, r0 + 12870: f04f 33ff mov.w r3, #4294967295 + 12874: f810 2b01 ldrb.w r2, [r0], #1 + 12878: 405a eors r2, r3 + 1287a: b2d2 uxtb r2, r2 + 1287c: f854 2022 ldr.w r2, [r4, r2, lsl #2] + 12880: 4288 cmp r0, r1 + 12882: ea82 2313 eor.w r3, r2, r3, lsr #8 + 12886: d1f5 bne.n 12874 + 12888: 43d8 mvns r0, r3 + 1288a: f85d 4b04 ldr.w r4, [sp], #4 + 1288e: 4770 bx lr + 12890: 2000 movs r0, #0 + 12892: 4770 bx lr + +00012894 : + 12894: b470 push {r4, r5, r6} + 12896: 6802 ldr r2, [r0, #0] + 12898: f100 0308 add.w r3, r0, #8 + 1289c: 3201 adds r2, #1 + 1289e: b2d2 uxtb r2, r2 + 128a0: 5c9c ldrb r4, [r3, r2] + 128a2: 6841 ldr r1, [r0, #4] + 128a4: 4421 add r1, r4 + 128a6: b2c9 uxtb r1, r1 + 128a8: 5c5d ldrb r5, [r3, r1] + 128aa: 6041 str r1, [r0, #4] + 128ac: 192e adds r6, r5, r4 + 128ae: 6002 str r2, [r0, #0] + 128b0: 545c strb r4, [r3, r1] + 128b2: b2f0 uxtb r0, r6 + 128b4: 549d strb r5, [r3, r2] + 128b6: 5c18 ldrb r0, [r3, r0] + 128b8: bc70 pop {r4, r5, r6} + 128ba: 4770 bx lr + +000128bc : + 128bc: b5f0 push {r4, r5, r6, r7, lr} + 128be: 2400 movs r4, #0 + 128c0: 4623 mov r3, r4 + 128c2: f100 0508 add.w r5, r0, #8 + 128c6: 6004 str r4, [r0, #0] + 128c8: 6044 str r4, [r0, #4] + 128ca: 54eb strb r3, [r5, r3] + 128cc: 3301 adds r3, #1 + 128ce: f5b3 7f80 cmp.w r3, #256 ; 0x100 + 128d2: d1fa bne.n 128ca + 128d4: 2000 movs r0, #0 + 128d6: 4603 mov r3, r0 + 128d8: 462c mov r4, r5 + 128da: f505 7e80 add.w lr, r5, #256 ; 0x100 + 128de: 5ccf ldrb r7, [r1, r3] + 128e0: 7826 ldrb r6, [r4, #0] + 128e2: 3301 adds r3, #1 + 128e4: 4437 add r7, r6 + 128e6: 4438 add r0, r7 + 128e8: b2c0 uxtb r0, r0 + 128ea: 5c2f ldrb r7, [r5, r0] + 128ec: 542e strb r6, [r5, r0] + 128ee: f804 7b01 strb.w r7, [r4], #1 + 128f2: 4293 cmp r3, r2 + 128f4: bf28 it cs + 128f6: 2300 movcs r3, #0 + 128f8: 4574 cmp r4, lr + 128fa: d1f0 bne.n 128de + 128fc: bdf0 pop {r4, r5, r6, r7, pc} + 128fe: bf00 nop + +00012900 : + 12900: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} + 12904: 461e mov r6, r3 + 12906: b173 cbz r3, 12926 + 12908: 4607 mov r7, r0 + 1290a: 4688 mov r8, r1 + 1290c: 4691 mov r9, r2 + 1290e: 2400 movs r4, #0 + 12910: 4638 mov r0, r7 + 12912: f819 5004 ldrb.w r5, [r9, r4] + 12916: f7ff ffbd bl 12894 + 1291a: 4068 eors r0, r5 + 1291c: f808 0004 strb.w r0, [r8, r4] + 12920: 3401 adds r4, #1 + 12922: 42b4 cmp r4, r6 + 12924: d1f4 bne.n 12910 + 12926: e8bd 83f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} + 1292a: bf00 nop + +0001292c : + 1292c: b1b2 cbz r2, 1295c + 1292e: 4603 mov r3, r0 + 12930: b430 push {r4, r5} + 12932: 2400 movs r4, #0 + 12934: 680d ldr r5, [r1, #0] + 12936: 3304 adds r3, #4 + 12938: 5505 strb r5, [r0, r4] + 1293a: f851 5b04 ldr.w r5, [r1], #4 + 1293e: 3404 adds r4, #4 + 12940: 0a2d lsrs r5, r5, #8 + 12942: f803 5c03 strb.w r5, [r3, #-3] + 12946: f831 5c02 ldrh.w r5, [r1, #-2] + 1294a: 42a2 cmp r2, r4 + 1294c: f803 5c02 strb.w r5, [r3, #-2] + 12950: f811 5c01 ldrb.w r5, [r1, #-1] + 12954: f803 5c01 strb.w r5, [r3, #-1] + 12958: d8ec bhi.n 12934 + 1295a: bc30 pop {r4, r5} + 1295c: 4770 bx lr + 1295e: bf00 nop + +00012960 : + 12960: 460a mov r2, r1 + 12962: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 12966: b0a5 sub sp, #148 ; 0x94 + 12968: 9008 str r0, [sp, #32] + 1296a: 9b08 ldr r3, [sp, #32] + 1296c: 9c08 ldr r4, [sp, #32] + 1296e: 9d08 ldr r5, [sp, #32] + 12970: 685b ldr r3, [r3, #4] + 12972: 6800 ldr r0, [r0, #0] + 12974: 68a4 ldr r4, [r4, #8] + 12976: 68ed ldr r5, [r5, #12] + 12978: 9309 str r3, [sp, #36] ; 0x24 + 1297a: 9013 str r0, [sp, #76] ; 0x4c + 1297c: 940a str r4, [sp, #40] ; 0x28 + 1297e: 9512 str r5, [sp, #72] ; 0x48 + 12980: 2300 movs r3, #0 + 12982: 7890 ldrb r0, [r2, #2] + 12984: 7854 ldrb r4, [r2, #1] + 12986: 5ccd ldrb r5, [r1, r3] + 12988: 0400 lsls r0, r0, #16 + 1298a: ea40 2004 orr.w r0, r0, r4, lsl #8 + 1298e: 78d4 ldrb r4, [r2, #3] + 12990: 4328 orrs r0, r5 + 12992: ea40 6004 orr.w r0, r0, r4, lsl #24 + 12996: ae14 add r6, sp, #80 ; 0x50 + 12998: 50f0 str r0, [r6, r3] + 1299a: 3304 adds r3, #4 + 1299c: 2b40 cmp r3, #64 ; 0x40 + 1299e: f102 0204 add.w r2, r2, #4 + 129a2: d1ee bne.n 12982 + 129a4: f24a 4278 movw r2, #42104 ; 0xa478 + 129a8: f24b 7156 movw r1, #46934 ; 0xb756 + 129ac: f247 03db movw r3, #28891 ; 0x70db + 129b0: f64c 6aee movw sl, #52974 ; 0xceee + 129b4: f640 79af movw r9, #4015 ; 0xfaf + 129b8: f2cd 726a movt r2, #55146 ; 0xd76a + 129bc: f6ce 01c7 movt r1, #59591 ; 0xe8c7 + 129c0: f2c2 4320 movt r3, #9248 ; 0x2420 + 129c4: f2cc 1abd movt sl, #49597 ; 0xc1bd + 129c8: f2cf 597c movt r9, #62844 ; 0xf57c + 129cc: 9f09 ldr r7, [sp, #36] ; 0x24 + 129ce: 9d12 ldr r5, [sp, #72] ; 0x48 + 129d0: f24c 662a movw r6, #50730 ; 0xc62a + 129d4: ea25 0507 bic.w r5, r5, r7 + 129d8: 9f14 ldr r7, [sp, #80] ; 0x50 + 129da: 9500 str r5, [sp, #0] + 129dc: 443a add r2, r7 + 129de: 9d0a ldr r5, [sp, #40] ; 0x28 + 129e0: 9f09 ldr r7, [sp, #36] ; 0x24 + 129e2: f244 6813 movw r8, #17939 ; 0x4613 + 129e6: ea05 0b07 and.w fp, r5, r7 + 129ea: 9d13 ldr r5, [sp, #76] ; 0x4c + 129ec: 9f00 ldr r7, [sp, #0] + 129ee: 442a add r2, r5 + 129f0: ea47 050b orr.w r5, r7, fp + 129f4: 4415 add r5, r2 + 129f6: 9a09 ldr r2, [sp, #36] ; 0x24 + 129f8: 9f0a ldr r7, [sp, #40] ; 0x28 + 129fa: eb02 6575 add.w r5, r2, r5, ror #25 + 129fe: ea27 0b05 bic.w fp, r7, r5 + 12a02: 9f15 ldr r7, [sp, #84] ; 0x54 + 12a04: f249 5401 movw r4, #38145 ; 0x9501 + 12a08: 4439 add r1, r7 + 12a0a: 9f12 ldr r7, [sp, #72] ; 0x48 + 12a0c: f649 00d8 movw r0, #39128 ; 0x98d8 + 12a10: 4439 add r1, r7 + 12a12: 9f16 ldr r7, [sp, #88] ; 0x58 + 12a14: f24f 7caf movw ip, #63407 ; 0xf7af + 12a18: 443b add r3, r7 + 12a1a: 9f0a ldr r7, [sp, #40] ; 0x28 + 12a1c: f24d 7ebe movw lr, #55230 ; 0xd7be + 12a20: 443b add r3, r7 + 12a22: 9f17 ldr r7, [sp, #92] ; 0x5c + 12a24: f2c4 7687 movt r6, #18311 ; 0x4787 + 12a28: 44ba add sl, r7 + 12a2a: 9f09 ldr r7, [sp, #36] ; 0x24 + 12a2c: f6ca 0830 movt r8, #43056 ; 0xa830 + 12a30: 44ba add sl, r7 + 12a32: 9f18 ldr r7, [sp, #96] ; 0x60 + 12a34: f6cf 5446 movt r4, #64838 ; 0xfd46 + 12a38: 44b9 add r9, r7 + 12a3a: f241 1722 movw r7, #4386 ; 0x1122 + 12a3e: f6c6 3790 movt r7, #27536 ; 0x6b90 + 12a42: 9701 str r7, [sp, #4] + 12a44: f247 1793 movw r7, #29075 ; 0x7193 + 12a48: f6cf 5798 movt r7, #64920 ; 0xfd98 + 12a4c: f6c6 1080 movt r0, #27008 ; 0x6980 + 12a50: 402a ands r2, r5 + 12a52: f6c8 3c44 movt ip, #35652 ; 0x8b44 + 12a56: ea4b 0202 orr.w r2, fp, r2 + 12a5a: 440a add r2, r1 + 12a5c: 9909 ldr r1, [sp, #36] ; 0x24 + 12a5e: eb05 5232 add.w r2, r5, r2, ror #20 + 12a62: ea21 0b02 bic.w fp, r1, r2 + 12a66: ea02 0105 and.w r1, r2, r5 + 12a6a: ea4b 0101 orr.w r1, fp, r1 + 12a6e: 4419 add r1, r3 + 12a70: eb02 31f1 add.w r1, r2, r1, ror #15 + 12a74: ea25 0b01 bic.w fp, r5, r1 + 12a78: ea01 0302 and.w r3, r1, r2 + 12a7c: f6c8 1e5c movt lr, #35164 ; 0x895c + 12a80: ea4b 0303 orr.w r3, fp, r3 + 12a84: 4453 add r3, sl + 12a86: eb01 23b3 add.w r3, r1, r3, ror #10 + 12a8a: ea22 0b03 bic.w fp, r2, r3 + 12a8e: ea03 0a01 and.w sl, r3, r1 + 12a92: ea4b 0a0a orr.w sl, fp, sl + 12a96: 444d add r5, r9 + 12a98: eb05 090a add.w r9, r5, sl + 12a9c: 9d19 ldr r5, [sp, #100] ; 0x64 + 12a9e: eb03 6979 add.w r9, r3, r9, ror #25 + 12aa2: ea21 0a09 bic.w sl, r1, r9 + 12aa6: 442e add r6, r5 + 12aa8: ea09 0503 and.w r5, r9, r3 + 12aac: ea4a 0505 orr.w r5, sl, r5 + 12ab0: 4432 add r2, r6 + 12ab2: 442a add r2, r5 + 12ab4: 9d1a ldr r5, [sp, #104] ; 0x68 + 12ab6: eb09 5232 add.w r2, r9, r2, ror #20 + 12aba: ea23 0a02 bic.w sl, r3, r2 + 12abe: 44a8 add r8, r5 + 12ac0: ea02 0509 and.w r5, r2, r9 + 12ac4: ea4a 0505 orr.w r5, sl, r5 + 12ac8: 4441 add r1, r8 + 12aca: 9702 str r7, [sp, #8] + 12acc: eb01 0805 add.w r8, r1, r5 + 12ad0: 9f1b ldr r7, [sp, #108] ; 0x6c + 12ad2: eb02 38f8 add.w r8, r2, r8, ror #15 + 12ad6: ea29 0508 bic.w r5, r9, r8 + 12ada: 443c add r4, r7 + 12adc: ea08 0102 and.w r1, r8, r2 + 12ae0: 4329 orrs r1, r5 + 12ae2: 4423 add r3, r4 + 12ae4: 440b add r3, r1 + 12ae6: f244 368e movw r6, #17294 ; 0x438e + 12aea: 991c ldr r1, [sp, #112] ; 0x70 + 12aec: eb08 23b3 add.w r3, r8, r3, ror #10 + 12af0: ea22 0403 bic.w r4, r2, r3 + 12af4: 4408 add r0, r1 + 12af6: ea03 0108 and.w r1, r3, r8 + 12afa: 4321 orrs r1, r4 + 12afc: 4448 add r0, r9 + 12afe: 9c1d ldr r4, [sp, #116] ; 0x74 + 12b00: eb00 0901 add.w r9, r0, r1 + 12b04: eb03 6979 add.w r9, r3, r9, ror #25 + 12b08: ea28 0009 bic.w r0, r8, r9 + 12b0c: ea09 0103 and.w r1, r9, r3 + 12b10: 44a4 add ip, r4 + 12b12: 9f1e ldr r7, [sp, #120] ; 0x78 + 12b14: 4301 orrs r1, r0 + 12b16: 4494 add ip, r2 + 12b18: eb0c 0201 add.w r2, ip, r1 + 12b1c: eb09 5232 add.w r2, r9, r2, ror #20 + 12b20: f5a7 4524 sub.w r5, r7, #41984 ; 0xa400 + 12b24: ea23 0002 bic.w r0, r3, r2 + 12b28: ea02 0109 and.w r1, r2, r9 + 12b2c: 3d4f subs r5, #79 ; 0x4f + 12b2e: 4301 orrs r1, r0 + 12b30: 44a8 add r8, r5 + 12b32: 981f ldr r0, [sp, #124] ; 0x7c + 12b34: eb08 0501 add.w r5, r8, r1 + 12b38: eb02 35f5 add.w r5, r2, r5, ror #15 + 12b3c: ea05 0102 and.w r1, r5, r2 + 12b40: 4486 add lr, r0 + 12b42: ea29 0005 bic.w r0, r9, r5 + 12b46: 4301 orrs r1, r0 + 12b48: 449e add lr, r3 + 12b4a: 448e add lr, r1 + 12b4c: 9b01 ldr r3, [sp, #4] + 12b4e: 9920 ldr r1, [sp, #128] ; 0x80 + 12b50: eb05 24be add.w r4, r5, lr, ror #10 + 12b54: 440b add r3, r1 + 12b56: 9301 str r3, [sp, #4] + 12b58: 9f01 ldr r7, [sp, #4] + 12b5a: ea22 0104 bic.w r1, r2, r4 + 12b5e: ea04 0305 and.w r3, r4, r5 + 12b62: 430b orrs r3, r1 + 12b64: 444f add r7, r9 + 12b66: 441f add r7, r3 + 12b68: eb04 6077 add.w r0, r4, r7, ror #25 + 12b6c: f8dd 8008 ldr.w r8, [sp, #8] + 12b70: 9f21 ldr r7, [sp, #132] ; 0x84 + 12b72: ea00 0304 and.w r3, r0, r4 + 12b76: 4447 add r7, r8 + 12b78: 9702 str r7, [sp, #8] + 12b7a: f8dd a008 ldr.w sl, [sp, #8] + 12b7e: ea25 0700 bic.w r7, r5, r0 + 12b82: 433b orrs r3, r7 + 12b84: 4452 add r2, sl + 12b86: 441a add r2, r3 + 12b88: eb00 5232 add.w r2, r0, r2, ror #20 + 12b8c: 43d1 mvns r1, r2 + 12b8e: 4617 mov r7, r2 + 12b90: f2ca 6679 movt r6, #42617 ; 0xa679 + 12b94: f640 0321 movw r3, #2081 ; 0x821 + 12b98: f242 5a62 movw sl, #9570 ; 0x2562 + 12b9c: 9202 str r2, [sp, #8] + 12b9e: 9a22 ldr r2, [sp, #136] ; 0x88 + 12ba0: 4007 ands r7, r0 + 12ba2: 4416 add r6, r2 + 12ba4: ea01 0b04 and.w fp, r1, r4 + 12ba8: ea4b 0b07 orr.w fp, fp, r7 + 12bac: 4435 add r5, r6 + 12bae: 9e02 ldr r6, [sp, #8] + 12bb0: 445d add r5, fp + 12bb2: eb06 32f5 add.w r2, r6, r5, ror #15 + 12bb6: 9100 str r1, [sp, #0] + 12bb8: 43d1 mvns r1, r2 + 12bba: f6c4 13b4 movt r3, #18868 ; 0x49b4 + 12bbe: f2cf 6a1e movt sl, #63006 ; 0xf61e + 12bc2: 9101 str r1, [sp, #4] + 12bc4: 9902 ldr r1, [sp, #8] + 12bc6: f24b 3940 movw r9, #45888 ; 0xb340 + 12bca: ea02 0b01 and.w fp, r2, r1 + 12bce: 9923 ldr r1, [sp, #140] ; 0x8c + 12bd0: f2cc 0940 movt r9, #49216 ; 0xc040 + 12bd4: 440b add r3, r1 + 12bd6: 441c add r4, r3 + 12bd8: 9b01 ldr r3, [sp, #4] + 12bda: 9902 ldr r1, [sp, #8] + 12bdc: 4003 ands r3, r0 + 12bde: ea43 030b orr.w r3, r3, fp + 12be2: 4423 add r3, r4 + 12be4: eb02 23b3 add.w r3, r2, r3, ror #10 + 12be8: ea03 0b01 and.w fp, r3, r1 + 12bec: 9915 ldr r1, [sp, #84] ; 0x54 + 12bee: 9c00 ldr r4, [sp, #0] + 12bf0: 448a add sl, r1 + 12bf2: f64c 51e6 movw r1, #52710 ; 0xcde6 + 12bf6: 4014 ands r4, r2 + 12bf8: 4450 add r0, sl + 12bfa: ea4b 0404 orr.w r4, fp, r4 + 12bfe: 4404 add r4, r0 + 12c00: 9801 ldr r0, [sp, #4] + 12c02: eb03 64f4 add.w r4, r3, r4, ror #27 + 12c06: ea04 0a02 and.w sl, r4, r2 + 12c0a: 4018 ands r0, r3 + 12c0c: ea4a 0000 orr.w r0, sl, r0 + 12c10: f640 5a87 movw sl, #3463 ; 0xd87 + 12c14: f2c2 11e1 movt r1, #8673 ; 0x21e1 + 12c18: f2cf 4ad5 movt sl, #62677 ; 0xf4d5 + 12c1c: 9103 str r1, [sp, #12] + 12c1e: 991a ldr r1, [sp, #104] ; 0x68 + 12c20: f645 2851 movw r8, #23121 ; 0x5a51 + 12c24: 4489 add r9, r1 + 12c26: f240 71d6 movw r1, #2006 ; 0x7d6 + 12c2a: f8cd a014 str.w sl, [sp, #20] + 12c2e: f64e 1a05 movw sl, #59653 ; 0xe905 + 12c32: f2cc 3137 movt r1, #49975 ; 0xc337 + 12c36: f24c 7caa movw ip, #51114 ; 0xc7aa + 12c3a: f241 0e5d movw lr, #4189 ; 0x105d + 12c3e: f2c2 685e movt r8, #9822 ; 0x265e + 12c42: f6ca 1ae3 movt sl, #43491 ; 0xa9e3 + 12c46: f241 4753 movw r7, #5203 ; 0x1453 + 12c4a: f24e 6681 movw r6, #59009 ; 0xe681 + 12c4e: f64f 35c8 movw r5, #64456 ; 0xfbc8 + 12c52: 9104 str r1, [sp, #16] + 12c54: f6ce 1cb6 movt ip, #59830 ; 0xe9b6 + 12c58: 9902 ldr r1, [sp, #8] + 12c5a: f2cd 6e2f movt lr, #54831 ; 0xd62f + 12c5e: 4449 add r1, r9 + 12c60: 4408 add r0, r1 + 12c62: 991f ldr r1, [sp, #124] ; 0x7c + 12c64: eb04 50f0 add.w r0, r4, r0, ror #23 + 12c68: 4488 add r8, r1 + 12c6a: 4442 add r2, r8 + 12c6c: ea00 0103 and.w r1, r0, r3 + 12c70: ea24 0803 bic.w r8, r4, r3 + 12c74: ea41 0108 orr.w r1, r1, r8 + 12c78: f8cd a01c str.w sl, [sp, #28] + 12c7c: f241 48ed movw r8, #5357 ; 0x14ed + 12c80: f240 2ad9 movw sl, #729 ; 0x2d9 + 12c84: f2c0 2744 movt r7, #580 ; 0x244 + 12c88: f6cd 06a1 movt r6, #55457 ; 0xd8a1 + 12c8c: f2ce 75d3 movt r5, #59347 ; 0xe7d3 + 12c90: 440a add r2, r1 + 12c92: 9914 ldr r1, [sp, #80] ; 0x50 + 12c94: eb00 42b2 add.w r2, r0, r2, ror #18 + 12c98: 448c add ip, r1 + 12c9a: 4463 add r3, ip + 12c9c: ea02 0104 and.w r1, r2, r4 + 12ca0: ea20 0c04 bic.w ip, r0, r4 + 12ca4: ea41 010c orr.w r1, r1, ip + 12ca8: 440b add r3, r1 + 12caa: 9919 ldr r1, [sp, #100] ; 0x64 + 12cac: eb02 3333 add.w r3, r2, r3, ror #12 + 12cb0: 448e add lr, r1 + 12cb2: 4474 add r4, lr + 12cb4: ea03 0100 and.w r1, r3, r0 + 12cb8: ea22 0e00 bic.w lr, r2, r0 + 12cbc: ea41 010e orr.w r1, r1, lr + 12cc0: f2c4 585a movt r8, #17754 ; 0x455a + 12cc4: f2c6 7a6f movt sl, #26479 ; 0x676f + 12cc8: 440c add r4, r1 + 12cca: 991e ldr r1, [sp, #120] ; 0x78 + 12ccc: eb03 64f4 add.w r4, r3, r4, ror #27 + 12cd0: 440f add r7, r1 + 12cd2: 4438 add r0, r7 + 12cd4: ea04 0102 and.w r1, r4, r2 + 12cd8: ea23 0702 bic.w r7, r3, r2 + 12cdc: 4339 orrs r1, r7 + 12cde: 4408 add r0, r1 + 12ce0: 9923 ldr r1, [sp, #140] ; 0x8c + 12ce2: eb04 50f0 add.w r0, r4, r0, ror #23 + 12ce6: 440e add r6, r1 + 12ce8: 4432 add r2, r6 + 12cea: ea00 0103 and.w r1, r0, r3 + 12cee: ea24 0603 bic.w r6, r4, r3 + 12cf2: 4331 orrs r1, r6 + 12cf4: 440a add r2, r1 + 12cf6: 9918 ldr r1, [sp, #96] ; 0x60 + 12cf8: eb00 42b2 add.w r2, r0, r2, ror #18 + 12cfc: 440d add r5, r1 + 12cfe: 442b add r3, r5 + 12d00: ea02 0104 and.w r1, r2, r4 + 12d04: ea20 0504 bic.w r5, r0, r4 + 12d08: 4329 orrs r1, r5 + 12d0a: 440b add r3, r1 + 12d0c: 9d03 ldr r5, [sp, #12] + 12d0e: 991d ldr r1, [sp, #116] ; 0x74 + 12d10: eb02 3333 add.w r3, r2, r3, ror #12 + 12d14: 4429 add r1, r5 + 12d16: 9103 str r1, [sp, #12] + 12d18: 9d03 ldr r5, [sp, #12] + 12d1a: ea03 0100 and.w r1, r3, r0 + 12d1e: 442c add r4, r5 + 12d20: ea22 0500 bic.w r5, r2, r0 + 12d24: 4329 orrs r1, r5 + 12d26: 440c add r4, r1 + 12d28: 9d22 ldr r5, [sp, #136] ; 0x88 + 12d2a: 9904 ldr r1, [sp, #16] + 12d2c: eb03 64f4 add.w r4, r3, r4, ror #27 + 12d30: 440d add r5, r1 + 12d32: 4428 add r0, r5 + 12d34: ea04 0102 and.w r1, r4, r2 + 12d38: ea23 0502 bic.w r5, r3, r2 + 12d3c: 4329 orrs r1, r5 + 12d3e: 4408 add r0, r1 + 12d40: 9d05 ldr r5, [sp, #20] + 12d42: 9917 ldr r1, [sp, #92] ; 0x5c + 12d44: f8cd 8018 str.w r8, [sp, #24] + 12d48: 4429 add r1, r5 + 12d4a: f8cd a000 str.w sl, [sp] + 12d4e: 9105 str r1, [sp, #20] + 12d50: 9d05 ldr r5, [sp, #20] + 12d52: eb04 50f0 add.w r0, r4, r0, ror #23 + 12d56: ea00 0103 and.w r1, r0, r3 + 12d5a: 442a add r2, r5 + 12d5c: ea24 0503 bic.w r5, r4, r3 + 12d60: 4329 orrs r1, r5 + 12d62: 440a add r2, r1 + 12d64: 9d06 ldr r5, [sp, #24] + 12d66: 991c ldr r1, [sp, #112] ; 0x70 + 12d68: eb00 42b2 add.w r2, r0, r2, ror #18 + 12d6c: 4429 add r1, r5 + 12d6e: 9106 str r1, [sp, #24] + 12d70: 9d06 ldr r5, [sp, #24] + 12d72: ea02 0104 and.w r1, r2, r4 + 12d76: 442b add r3, r5 + 12d78: ea20 0504 bic.w r5, r0, r4 + 12d7c: 4329 orrs r1, r5 + 12d7e: 440b add r3, r1 + 12d80: 9d21 ldr r5, [sp, #132] ; 0x84 + 12d82: 9907 ldr r1, [sp, #28] + 12d84: f24a 3bf8 movw fp, #41976 ; 0xa3f8 + 12d88: eb02 3333 add.w r3, r2, r3, ror #12 + 12d8c: 440d add r5, r1 + 12d8e: 442c add r4, r5 + 12d90: ea03 0100 and.w r1, r3, r0 + 12d94: ea22 0500 bic.w r5, r2, r0 + 12d98: 4329 orrs r1, r5 + 12d9a: f64b 4570 movw r5, #48240 ; 0xbc70 + 12d9e: f6cf 4bef movt fp, #64751 ; 0xfcef + 12da2: f6cb 65bf movt r5, #48831 ; 0xbebf + 12da6: 440c add r4, r1 + 12da8: 9916 ldr r1, [sp, #88] ; 0x58 + 12daa: eb03 64f4 add.w r4, r3, r4, ror #27 + 12dae: 448b add fp, r1 + 12db0: 4483 add fp, r0 + 12db2: ea04 0102 and.w r1, r4, r2 + 12db6: ea23 0002 bic.w r0, r3, r2 + 12dba: 4308 orrs r0, r1 + 12dbc: 9501 str r5, [sp, #4] + 12dbe: 4458 add r0, fp + 12dc0: 9d1b ldr r5, [sp, #108] ; 0x6c + 12dc2: f8dd b000 ldr.w fp, [sp] + 12dc6: f647 61c6 movw r1, #32454 ; 0x7ec6 + 12dca: 445d add r5, fp + 12dcc: f242 7bfa movw fp, #10234 ; 0x27fa + 12dd0: f6ce 2ba1 movt fp, #60065 ; 0xeaa1 + 12dd4: f644 498a movw r9, #19594 ; 0x4c8a + 12dd8: f24f 6c81 movw ip, #63105 ; 0xf681 + 12ddc: f246 1822 movw r8, #24866 ; 0x6122 + 12de0: f8cd b010 str.w fp, [sp, #16] + 12de4: f243 0b85 movw fp, #12421 ; 0x3085 + 12de8: f6c2 019b movt r1, #10395 ; 0x289b + 12dec: f6c8 592a movt r9, #36138 ; 0x8d2a + 12df0: f2c8 7c71 movt ip, #34673 ; 0x8771 + 12df4: f6c6 589d movt r8, #28061 ; 0x6d9d + 12df8: f2cd 4bef movt fp, #54511 ; 0xd4ef + 12dfc: eb04 50f0 add.w r0, r4, r0, ror #23 + 12e00: 9103 str r1, [sp, #12] + 12e02: 442a add r2, r5 + 12e04: ea00 0103 and.w r1, r0, r3 + 12e08: ea24 0503 bic.w r5, r4, r3 + 12e0c: 4329 orrs r1, r5 + 12e0e: 440a add r2, r1 + 12e10: 9920 ldr r1, [sp, #128] ; 0x80 + 12e12: eb00 42b2 add.w r2, r0, r2, ror #18 + 12e16: 9d19 ldr r5, [sp, #100] ; 0x64 + 12e18: 4489 add r9, r1 + 12e1a: 4499 add r9, r3 + 12e1c: ea02 0104 and.w r1, r2, r4 + 12e20: ea20 0304 bic.w r3, r0, r4 + 12e24: 430b orrs r3, r1 + 12e26: f5a5 21b8 sub.w r1, r5, #376832 ; 0x5c000 + 12e2a: 444b add r3, r9 + 12e2c: f2a1 61be subw r1, r1, #1726 ; 0x6be + 12e30: eb02 3333 add.w r3, r2, r3, ror #12 + 12e34: 440c add r4, r1 + 12e36: ea82 0100 eor.w r1, r2, r0 + 12e3a: 9d1c ldr r5, [sp, #112] ; 0x70 + 12e3c: 4059 eors r1, r3 + 12e3e: 440c add r4, r1 + 12e40: eb03 7434 add.w r4, r3, r4, ror #28 + 12e44: ea83 0102 eor.w r1, r3, r2 + 12e48: 44ac add ip, r5 + 12e4a: 4061 eors r1, r4 + 12e4c: 4484 add ip, r0 + 12e4e: 448c add ip, r1 + 12e50: 991f ldr r1, [sp, #124] ; 0x7c + 12e52: f643 0e0c movw lr, #14348 ; 0x380c + 12e56: 4488 add r8, r1 + 12e58: 4490 add r8, r2 + 12e5a: f649 12e5 movw r2, #39397 ; 0x99e5 + 12e5e: f64e 2744 movw r7, #59972 ; 0xea44 + 12e62: f8cd b014 str.w fp, [sp, #20] + 12e66: f641 5b05 movw fp, #7429 ; 0x1d05 + 12e6a: f2ce 62db movt r2, #59099 ; 0xe6db + 12e6e: f6cf 5ee5 movt lr, #64997 ; 0xfde5 + 12e72: f2ca 47be movt r7, #42174 ; 0xa4be + 12e76: f2c0 4b88 movt fp, #1160 ; 0x488 + 12e7a: eb04 5c7c add.w ip, r4, ip, ror #21 + 12e7e: ea84 0103 eor.w r1, r4, r3 + 12e82: 9d22 ldr r5, [sp, #136] ; 0x88 + 12e84: ea81 010c eor.w r1, r1, ip + 12e88: 4488 add r8, r1 + 12e8a: eb0c 4038 add.w r0, ip, r8, ror #16 + 12e8e: 9207 str r2, [sp, #28] + 12e90: 44ae add lr, r5 + 12e92: ea8c 0204 eor.w r2, ip, r4 + 12e96: 9915 ldr r1, [sp, #84] ; 0x54 + 12e98: 4042 eors r2, r0 + 12e9a: 4473 add r3, lr + 12e9c: 4413 add r3, r2 + 12e9e: eb00 2373 add.w r3, r0, r3, ror #9 + 12ea2: ea80 050c eor.w r5, r0, ip + 12ea6: 440f add r7, r1 + 12ea8: f64c 76a9 movw r6, #53161 ; 0xcfa9 + 12eac: 4427 add r7, r4 + 12eae: 405d eors r5, r3 + 12eb0: f8cd b018 str.w fp, [sp, #24] + 12eb4: 443d add r5, r7 + 12eb6: f24d 0b39 movw fp, #53305 ; 0xd039 + 12eba: f242 2744 movw r7, #8772 ; 0x2244 + 12ebe: f644 3a60 movw sl, #19296 ; 0x4b60 + 12ec2: f6c4 36de movt r6, #19422 ; 0x4bde + 12ec6: f6cd 1bd4 movt fp, #55764 ; 0xd9d4 + 12eca: f2cf 4729 movt r7, #62505 ; 0xf429 + 12ece: f2cf 6abb movt sl, #63163 ; 0xf6bb + 12ed2: 9c18 ldr r4, [sp, #96] ; 0x60 + 12ed4: eb03 7535 add.w r5, r3, r5, ror #28 + 12ed8: 4426 add r6, r4 + 12eda: ea83 0400 eor.w r4, r3, r0 + 12ede: 4466 add r6, ip + 12ee0: 406c eors r4, r5 + 12ee2: f8cd b02c str.w fp, [sp, #44] ; 0x2c + 12ee6: 970d str r7, [sp, #52] ; 0x34 + 12ee8: 4434 add r4, r6 + 12eea: 9f01 ldr r7, [sp, #4] + 12eec: 9e1e ldr r6, [sp, #120] ; 0x78 + 12eee: f647 4bf8 movw fp, #31992 ; 0x7cf8 + 12ef2: 991b ldr r1, [sp, #108] ; 0x6c + 12ef4: 443e add r6, r7 + 12ef6: 448a add sl, r1 + 12ef8: f245 6265 movw r2, #22117 ; 0x5665 + 12efc: ea85 0103 eor.w r1, r5, r3 + 12f00: f64f 7897 movw r8, #65431 ; 0xff97 + 12f04: 4433 add r3, r6 + 12f06: f242 36a7 movw r6, #9127 ; 0x23a7 + 12f0a: f6c1 7ba2 movt fp, #8098 ; 0x1fa2 + 12f0e: f2cc 42ac movt r2, #50348 ; 0xc4ac + 12f12: f2c4 382a movt r8, #17194 ; 0x432a + 12f16: f6ca 3694 movt r6, #43924 ; 0xab94 + 12f1a: eb05 5474 add.w r4, r5, r4, ror #21 + 12f1e: 4061 eors r1, r4 + 12f20: 4450 add r0, sl + 12f22: 4408 add r0, r1 + 12f24: eb04 4030 add.w r0, r4, r0, ror #16 + 12f28: ea84 0105 eor.w r1, r4, r5 + 12f2c: 4041 eors r1, r0 + 12f2e: f8cd b030 str.w fp, [sp, #48] ; 0x30 + 12f32: 4419 add r1, r3 + 12f34: f8dd b084 ldr.w fp, [sp, #132] ; 0x84 + 12f38: 9b03 ldr r3, [sp, #12] + 12f3a: eb00 2171 add.w r1, r0, r1, ror #9 + 12f3e: 449b add fp, r3 + 12f40: ea80 0304 eor.w r3, r0, r4 + 12f44: 9200 str r2, [sp, #0] + 12f46: f8cd 8038 str.w r8, [sp, #56] ; 0x38 + 12f4a: 404b eors r3, r1 + 12f4c: 960f str r6, [sp, #60] ; 0x3c + 12f4e: 445d add r5, fp + 12f50: f8dd 8010 ldr.w r8, [sp, #16] + 12f54: 9f14 ldr r7, [sp, #80] ; 0x50 + 12f56: 441d add r5, r3 + 12f58: eb01 7535 add.w r5, r1, r5, ror #28 + 12f5c: 4447 add r7, r8 + 12f5e: ea81 0300 eor.w r3, r1, r0 + 12f62: 406b eors r3, r5 + 12f64: 443c add r4, r7 + 12f66: 9e05 ldr r6, [sp, #20] + 12f68: f8dd 8018 ldr.w r8, [sp, #24] + 12f6c: 9f1a ldr r7, [sp, #104] ; 0x68 + 12f6e: 441c add r4, r3 + 12f70: 9b17 ldr r3, [sp, #92] ; 0x5c + 12f72: 4447 add r7, r8 + 12f74: 4433 add r3, r6 + 12f76: 4418 add r0, r3 + 12f78: ea85 0301 eor.w r3, r5, r1 + 12f7c: 4439 add r1, r7 + 12f7e: f64c 4792 movw r7, #52370 ; 0xcc92 + 12f82: f6c8 770c movt r7, #36620 ; 0x8f0c + 12f86: eb05 5474 add.w r4, r5, r4, ror #21 + 12f8a: 4063 eors r3, r4 + 12f8c: 4418 add r0, r3 + 12f8e: eb04 4030 add.w r0, r4, r0, ror #16 + 12f92: ea84 0305 eor.w r3, r4, r5 + 12f96: 4043 eors r3, r0 + 12f98: 9e0b ldr r6, [sp, #44] ; 0x2c + 12f9a: 4419 add r1, r3 + 12f9c: f24a 0a39 movw sl, #41017 ; 0xa039 + 12fa0: 9b1d ldr r3, [sp, #116] ; 0x74 + 12fa2: eb00 2171 add.w r1, r0, r1, ror #9 + 12fa6: 4433 add r3, r6 + 12fa8: 441d add r5, r3 + 12faa: ea80 0304 eor.w r3, r0, r4 + 12fae: 404b eors r3, r1 + 12fb0: 9e07 ldr r6, [sp, #28] + 12fb2: 441d add r5, r3 + 12fb4: 9b20 ldr r3, [sp, #128] ; 0x80 + 12fb6: eb01 7535 add.w r5, r1, r5, ror #28 + 12fba: 4433 add r3, r6 + 12fbc: 441c add r4, r3 + 12fbe: ea81 0300 eor.w r3, r1, r0 + 12fc2: 406b eors r3, r5 + 12fc4: 9711 str r7, [sp, #68] ; 0x44 + 12fc6: 441c add r4, r3 + 12fc8: 9f23 ldr r7, [sp, #140] ; 0x8c + 12fca: 9b0c ldr r3, [sp, #48] ; 0x30 + 12fcc: eb05 5474 add.w r4, r5, r4, ror #21 + 12fd0: 441f add r7, r3 + 12fd2: ea85 0301 eor.w r3, r5, r1 + 12fd6: 4063 eors r3, r4 + 12fd8: 4438 add r0, r7 + 12fda: 4418 add r0, r3 + 12fdc: eb04 4030 add.w r0, r4, r0, ror #16 + 12fe0: 9002 str r0, [sp, #8] + 12fe2: f645 50d1 movw r0, #24017 ; 0x5dd1 + 12fe6: f6cf 4a93 movt sl, #64659 ; 0xfc93 + 12fea: f645 12c3 movw r2, #22979 ; 0x59c3 + 12fee: f2c8 5084 movt r0, #34180 ; 0x8584 + 12ff2: f647 6b4f movw fp, #32335 ; 0x7e4f + 12ff6: f8cd a040 str.w sl, [sp, #64] ; 0x40 + 12ffa: f24e 6ae0 movw sl, #59104 ; 0xe6e0 + 12ffe: f244 3914 movw r9, #17172 ; 0x4314 + 13002: f241 18a1 movw r8, #4513 ; 0x11a1 + 13006: 9f00 ldr r7, [sp, #0] + 13008: 9e16 ldr r6, [sp, #88] ; 0x58 + 1300a: f2c6 525b movt r2, #25947 ; 0x655b + 1300e: 443e add r6, r7 + 13010: f647 6c82 movw ip, #32386 ; 0x7e82 + 13014: 4431 add r1, r6 + 13016: 9e02 ldr r6, [sp, #8] + 13018: ea84 0305 eor.w r3, r4, r5 + 1301c: 4073 eors r3, r6 + 1301e: 9001 str r0, [sp, #4] + 13020: 9f14 ldr r7, [sp, #80] ; 0x50 + 13022: 980d ldr r0, [sp, #52] ; 0x34 + 13024: 4419 add r1, r3 + 13026: f24f 2e35 movw lr, #62005 ; 0xf235 + 1302a: eb06 2171 add.w r1, r6, r1, ror #9 + 1302e: 4407 add r7, r0 + 13030: ea61 0304 orn r3, r1, r4 + 13034: 4073 eors r3, r6 + 13036: 443d add r5, r7 + 13038: 441d add r5, r3 + 1303a: f24d 27bb movw r7, #53947 ; 0xd2bb + 1303e: eb01 65b5 add.w r5, r1, r5, ror #26 + 13042: 9100 str r1, [sp, #0] + 13044: 9b0e ldr r3, [sp, #56] ; 0x38 + 13046: 991b ldr r1, [sp, #108] ; 0x6c + 13048: 9802 ldr r0, [sp, #8] + 1304a: 4419 add r1, r3 + 1304c: 440c add r4, r1 + 1304e: f24d 3691 movw r6, #54161 ; 0xd391 + 13052: 9900 ldr r1, [sp, #0] + 13054: ea65 0300 orn r3, r5, r0 + 13058: 404b eors r3, r1 + 1305a: 980f ldr r0, [sp, #60] ; 0x3c + 1305c: 441c add r4, r3 + 1305e: 9b22 ldr r3, [sp, #136] ; 0x88 + 13060: f6c6 7ba8 movt fp, #28584 ; 0x6fa8 + 13064: 4403 add r3, r0 + 13066: 9802 ldr r0, [sp, #8] + 13068: eb05 54b4 add.w r4, r5, r4, ror #22 + 1306c: 4418 add r0, r3 + 1306e: ea64 0301 orn r3, r4, r1 + 13072: 406b eors r3, r5 + 13074: f6cf 6a2c movt sl, #65068 ; 0xfe2c + 13078: 9919 ldr r1, [sp, #100] ; 0x64 + 1307a: 4418 add r0, r3 + 1307c: 9b10 ldr r3, [sp, #64] ; 0x40 + 1307e: f2ca 3901 movt r9, #41729 ; 0xa301 + 13082: 4419 add r1, r3 + 13084: 9110 str r1, [sp, #64] ; 0x40 + 13086: 9b10 ldr r3, [sp, #64] ; 0x40 + 13088: 9900 ldr r1, [sp, #0] + 1308a: eb04 4070 add.w r0, r4, r0, ror #17 + 1308e: 4419 add r1, r3 + 13090: ea60 0305 orn r3, r0, r5 + 13094: 4063 eors r3, r4 + 13096: f6c4 6808 movt r8, #19976 ; 0x4e08 + 1309a: 4419 add r1, r3 + 1309c: 9b20 ldr r3, [sp, #128] ; 0x80 + 1309e: eb00 21f1 add.w r1, r0, r1, ror #11 + 130a2: 441a add r2, r3 + 130a4: ea61 0304 orn r3, r1, r4 + 130a8: 4043 eors r3, r0 + 130aa: 442a add r2, r5 + 130ac: f2cf 7c53 movt ip, #63315 ; 0xf753 + 130b0: 9d17 ldr r5, [sp, #92] ; 0x5c + 130b2: 441a add r2, r3 + 130b4: 9b11 ldr r3, [sp, #68] ; 0x44 + 130b6: eb01 62b2 add.w r2, r1, r2, ror #26 + 130ba: 441d add r5, r3 + 130bc: ea62 0300 orn r3, r2, r0 + 130c0: 442c add r4, r5 + 130c2: 404b eors r3, r1 + 130c4: f6cb 5e3a movt lr, #48442 ; 0xbd3a + 130c8: 4423 add r3, r4 + 130ca: 9c1e ldr r4, [sp, #120] ; 0x78 + 130cc: eb02 53b3 add.w r3, r2, r3, ror #22 + 130d0: f5a4 1580 sub.w r5, r4, #1048576 ; 0x100000 + 130d4: f6a5 3583 subw r5, r5, #2947 ; 0xb83 + 130d8: ea63 0401 orn r4, r3, r1 + 130dc: f6c2 27d7 movt r7, #10967 ; 0x2ad7 + 130e0: 4054 eors r4, r2 + 130e2: 4428 add r0, r5 + 130e4: 4420 add r0, r4 + 130e6: 9d15 ldr r5, [sp, #84] ; 0x54 + 130e8: 9c01 ldr r4, [sp, #4] + 130ea: eb03 4070 add.w r0, r3, r0, ror #17 + 130ee: 4425 add r5, r4 + 130f0: f6ce 3686 movt r6, #60294 ; 0xeb86 + 130f4: ea60 0402 orn r4, r0, r2 + 130f8: 405c eors r4, r3 + 130fa: 4429 add r1, r5 + 130fc: 4421 add r1, r4 + 130fe: 9d1c ldr r5, [sp, #112] ; 0x70 + 13100: eb00 21f1 add.w r1, r0, r1, ror #11 + 13104: 44ab add fp, r5 + 13106: ea61 0403 orn r4, r1, r3 + 1310a: 4044 eors r4, r0 + 1310c: 445a add r2, fp + 1310e: 4422 add r2, r4 + 13110: 9c23 ldr r4, [sp, #140] ; 0x8c + 13112: eb01 62b2 add.w r2, r1, r2, ror #26 + 13116: 44a2 add sl, r4 + 13118: ea62 0400 orn r4, r2, r0 + 1311c: 404c eors r4, r1 + 1311e: 4453 add r3, sl + 13120: 9d1a ldr r5, [sp, #104] ; 0x68 + 13122: 4423 add r3, r4 + 13124: eb02 53b3 add.w r3, r2, r3, ror #22 + 13128: ea63 0401 orn r4, r3, r1 + 1312c: 44a9 add r9, r5 + 1312e: 4481 add r9, r0 + 13130: 4054 eors r4, r2 + 13132: 9821 ldr r0, [sp, #132] ; 0x84 + 13134: 444c add r4, r9 + 13136: eb03 4474 add.w r4, r3, r4, ror #17 + 1313a: 4480 add r8, r0 + 1313c: ea64 0002 orn r0, r4, r2 + 13140: 4058 eors r0, r3 + 13142: 4488 add r8, r1 + 13144: 9d18 ldr r5, [sp, #96] ; 0x60 + 13146: eb08 0100 add.w r1, r8, r0 + 1314a: eb04 21f1 add.w r1, r4, r1, ror #11 + 1314e: ea61 0003 orn r0, r1, r3 + 13152: 44ac add ip, r5 + 13154: 4494 add ip, r2 + 13156: 4060 eors r0, r4 + 13158: 9a1f ldr r2, [sp, #124] ; 0x7c + 1315a: 4460 add r0, ip + 1315c: eb01 60b0 add.w r0, r1, r0, ror #26 + 13160: 4496 add lr, r2 + 13162: ea60 0204 orn r2, r0, r4 + 13166: 449e add lr, r3 + 13168: ea82 0301 eor.w r3, r2, r1 + 1316c: 9d16 ldr r5, [sp, #88] ; 0x58 + 1316e: 4473 add r3, lr + 13170: eb00 53b3 add.w r3, r0, r3, ror #22 + 13174: 442f add r7, r5 + 13176: ea63 0201 orn r2, r3, r1 + 1317a: 4042 eors r2, r0 + 1317c: 443c add r4, r7 + 1317e: 4414 add r4, r2 + 13180: 9f1d ldr r7, [sp, #116] ; 0x74 + 13182: eb03 4474 add.w r4, r3, r4, ror #17 + 13186: ea64 0500 orn r5, r4, r0 + 1318a: 443e add r6, r7 + 1318c: 405d eors r5, r3 + 1318e: 9a09 ldr r2, [sp, #36] ; 0x24 + 13190: 4431 add r1, r6 + 13192: 9f0a ldr r7, [sp, #40] ; 0x28 + 13194: 9e12 ldr r6, [sp, #72] ; 0x48 + 13196: 4429 add r1, r5 + 13198: 9d13 ldr r5, [sp, #76] ; 0x4c + 1319a: f8dd 8020 ldr.w r8, [sp, #32] + 1319e: 4422 add r2, r4 + 131a0: 4428 add r0, r5 + 131a2: 4433 add r3, r6 + 131a4: 443c add r4, r7 + 131a6: eb02 21f1 add.w r1, r2, r1, ror #11 + 131aa: f8c8 0000 str.w r0, [r8] + 131ae: f8c8 300c str.w r3, [r8, #12] + 131b2: f8c8 4008 str.w r4, [r8, #8] + 131b6: f8c8 1004 str.w r1, [r8, #4] + 131ba: b025 add sp, #148 ; 0x94 + 131bc: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +000131c0 : + 131c0: b430 push {r4, r5} + 131c2: f64a 3189 movw r1, #43913 ; 0xab89 + 131c6: f242 3401 movw r4, #8961 ; 0x2301 + 131ca: f64d 42fe movw r2, #56574 ; 0xdcfe + 131ce: f245 4376 movw r3, #21622 ; 0x5476 + 131d2: f2c6 7445 movt r4, #26437 ; 0x6745 + 131d6: f6ce 71cd movt r1, #61389 ; 0xefcd + 131da: f6c9 02ba movt r2, #39098 ; 0x98ba + 131de: f2c1 0332 movt r3, #4146 ; 0x1032 + 131e2: 2500 movs r5, #0 + 131e4: 6004 str r4, [r0, #0] + 131e6: 6145 str r5, [r0, #20] + 131e8: 6105 str r5, [r0, #16] + 131ea: 6041 str r1, [r0, #4] + 131ec: 6082 str r2, [r0, #8] + 131ee: 60c3 str r3, [r0, #12] + 131f0: bc30 pop {r4, r5} + 131f2: 4770 bx lr + +000131f4 : + 131f4: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} + 131f8: 4606 mov r6, r0 + 131fa: 4617 mov r7, r2 + 131fc: 6900 ldr r0, [r0, #16] + 131fe: 00d2 lsls r2, r2, #3 + 13200: 1813 adds r3, r2, r0 + 13202: 429a cmp r2, r3 + 13204: 6133 str r3, [r6, #16] + 13206: 6973 ldr r3, [r6, #20] + 13208: f3c0 08c5 ubfx r8, r0, #3, #6 + 1320c: bf88 it hi + 1320e: 3301 addhi r3, #1 + 13210: f1c8 0440 rsb r4, r8, #64 ; 0x40 + 13214: eb03 7357 add.w r3, r3, r7, lsr #29 + 13218: 42a7 cmp r7, r4 + 1321a: 460d mov r5, r1 + 1321c: 6173 str r3, [r6, #20] + 1321e: d20e bcs.n 1323e + 13220: f108 0818 add.w r8, r8, #24 + 13224: 4446 add r6, r8 + 13226: 2400 movs r4, #0 + 13228: 4425 add r5, r4 + 1322a: 1b3c subs r4, r7, r4 + 1322c: d005 beq.n 1323a + 1322e: 2300 movs r3, #0 + 13230: 5cea ldrb r2, [r5, r3] + 13232: 54f2 strb r2, [r6, r3] + 13234: 3301 adds r3, #1 + 13236: 42a3 cmp r3, r4 + 13238: d1fa bne.n 13230 + 1323a: e8bd 83f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} + 1323e: f108 0118 add.w r1, r8, #24 + 13242: 4431 add r1, r6 + 13244: 2300 movs r3, #0 + 13246: 5cea ldrb r2, [r5, r3] + 13248: 54ca strb r2, [r1, r3] + 1324a: 3301 adds r3, #1 + 1324c: 429c cmp r4, r3 + 1324e: d8fa bhi.n 13246 + 13250: f106 0918 add.w r9, r6, #24 + 13254: 4649 mov r1, r9 + 13256: 4630 mov r0, r6 + 13258: f1c8 087f rsb r8, r8, #127 ; 0x7f + 1325c: f7ff fb80 bl 12960 + 13260: 4547 cmp r7, r8 + 13262: d909 bls.n 13278 + 13264: 1929 adds r1, r5, r4 + 13266: 4630 mov r0, r6 + 13268: f7ff fb7a bl 12960 + 1326c: f104 037f add.w r3, r4, #127 ; 0x7f + 13270: 429f cmp r7, r3 + 13272: f104 0440 add.w r4, r4, #64 ; 0x40 + 13276: d8f5 bhi.n 13264 + 13278: 464e mov r6, r9 + 1327a: e7d5 b.n 13228 + +0001327c : + 1327c: b530 push {r4, r5, lr} + 1327e: 460c mov r4, r1 + 13280: b083 sub sp, #12 + 13282: 4605 mov r5, r0 + 13284: 3110 adds r1, #16 + 13286: 4668 mov r0, sp + 13288: 2208 movs r2, #8 + 1328a: f7ff fb4f bl 1292c + 1328e: f245 31b0 movw r1, #21424 ; 0x53b0 + 13292: 6922 ldr r2, [r4, #16] + 13294: f2c0 0103 movt r1, #3 + 13298: f3c2 02c5 ubfx r2, r2, #3, #6 + 1329c: 2a37 cmp r2, #55 ; 0x37 + 1329e: bf94 ite ls + 132a0: f1c2 0238 rsbls r2, r2, #56 ; 0x38 + 132a4: f1c2 0278 rsbhi r2, r2, #120 ; 0x78 + 132a8: 4620 mov r0, r4 + 132aa: f7ff ffa3 bl 131f4 + 132ae: 4620 mov r0, r4 + 132b0: 4669 mov r1, sp + 132b2: 2208 movs r2, #8 + 132b4: f7ff ff9e bl 131f4 + 132b8: 2210 movs r2, #16 + 132ba: 4628 mov r0, r5 + 132bc: 4621 mov r1, r4 + 132be: f7ff fb35 bl 1292c + 132c2: 2300 movs r3, #0 + 132c4: 461a mov r2, r3 + 132c6: 54e2 strb r2, [r4, r3] + 132c8: 3301 adds r3, #1 + 132ca: 2b58 cmp r3, #88 ; 0x58 + 132cc: d1fb bne.n 132c6 + 132ce: b003 add sp, #12 + 132d0: bd30 pop {r4, r5, pc} + 132d2: bf00 nop + +000132d4 : + 132d4: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 132d8: 2b40 cmp r3, #64 ; 0x40 + 132da: b0bb sub sp, #236 ; 0xec + 132dc: 4680 mov r8, r0 + 132de: 468b mov fp, r1 + 132e0: 4617 mov r7, r2 + 132e2: bfd8 it le + 132e4: ae24 addle r6, sp, #144 ; 0x90 + 132e6: dc72 bgt.n 133ce + 132e8: f10d 0407 add.w r4, sp, #7 + 132ec: a912 add r1, sp, #72 ; 0x48 + 132ee: 2200 movs r2, #0 + 132f0: f804 2f01 strb.w r2, [r4, #1]! + 132f4: 428c cmp r4, r1 + 132f6: d1fb bne.n 132f0 + 132f8: f10d 044b add.w r4, sp, #75 ; 0x4b + 132fc: aa23 add r2, sp, #140 ; 0x8c + 132fe: 2500 movs r5, #0 + 13300: f804 5f01 strb.w r5, [r4, #1]! + 13304: 4294 cmp r4, r2 + 13306: d1fb bne.n 13300 + 13308: a902 add r1, sp, #8 + 1330a: ad13 add r5, sp, #76 ; 0x4c + 1330c: b16b cbz r3, 1332a + 1330e: 2200 movs r2, #0 + 13310: a902 add r1, sp, #8 + 13312: 5cb8 ldrb r0, [r7, r2] + 13314: 5488 strb r0, [r1, r2] + 13316: 3201 adds r2, #1 + 13318: 429a cmp r2, r3 + 1331a: d1fa bne.n 13312 + 1331c: 2200 movs r2, #0 + 1331e: ad13 add r5, sp, #76 ; 0x4c + 13320: 5cb8 ldrb r0, [r7, r2] + 13322: 54a8 strb r0, [r5, r2] + 13324: 3201 adds r2, #1 + 13326: 429a cmp r2, r3 + 13328: d1fa bne.n 13320 + 1332a: 2400 movs r4, #0 + 1332c: 5d0a ldrb r2, [r1, r4] + 1332e: 5d2b ldrb r3, [r5, r4] + 13330: f082 0236 eor.w r2, r2, #54 ; 0x36 + 13334: f083 035c eor.w r3, r3, #92 ; 0x5c + 13338: 550a strb r2, [r1, r4] + 1333a: 552b strb r3, [r5, r4] + 1333c: 3401 adds r4, #1 + 1333e: 2c40 cmp r4, #64 ; 0x40 + 13340: d1f4 bne.n 1332c + 13342: f242 3c01 movw ip, #8961 ; 0x2301 + 13346: f64a 3389 movw r3, #43913 ; 0xab89 + 1334a: f64d 4afe movw sl, #56574 ; 0xdcfe + 1334e: f245 4976 movw r9, #21622 ; 0x5476 + 13352: f2c6 7c45 movt ip, #26437 ; 0x6745 + 13356: f6ce 73cd movt r3, #61389 ; 0xefcd + 1335a: f6c9 0aba movt sl, #39098 ; 0x98ba + 1335e: f2c1 0932 movt r9, #4146 ; 0x1032 + 13362: 2700 movs r7, #0 + 13364: 4630 mov r0, r6 + 13366: 4622 mov r2, r4 + 13368: e88d 1008 stmia.w sp, {r3, ip} + 1336c: f8cd c090 str.w ip, [sp, #144] ; 0x90 + 13370: 9325 str r3, [sp, #148] ; 0x94 + 13372: f8cd a098 str.w sl, [sp, #152] ; 0x98 + 13376: f8cd 909c str.w r9, [sp, #156] ; 0x9c + 1337a: 9729 str r7, [sp, #164] ; 0xa4 + 1337c: 9728 str r7, [sp, #160] ; 0xa0 + 1337e: f7ff ff39 bl 131f4 + 13382: 465a mov r2, fp + 13384: 4630 mov r0, r6 + 13386: 4641 mov r1, r8 + 13388: f7ff ff34 bl 131f4 + 1338c: 9844 ldr r0, [sp, #272] ; 0x110 + 1338e: 4631 mov r1, r6 + 13390: f7ff ff74 bl 1327c + 13394: f8dd c004 ldr.w ip, [sp, #4] + 13398: 9b00 ldr r3, [sp, #0] + 1339a: 4629 mov r1, r5 + 1339c: 4622 mov r2, r4 + 1339e: 4630 mov r0, r6 + 133a0: f8cd c090 str.w ip, [sp, #144] ; 0x90 + 133a4: 9325 str r3, [sp, #148] ; 0x94 + 133a6: f8cd a098 str.w sl, [sp, #152] ; 0x98 + 133aa: f8cd 909c str.w r9, [sp, #156] ; 0x9c + 133ae: 9729 str r7, [sp, #164] ; 0xa4 + 133b0: 9728 str r7, [sp, #160] ; 0xa0 + 133b2: f7ff ff1f bl 131f4 + 133b6: 4630 mov r0, r6 + 133b8: 9944 ldr r1, [sp, #272] ; 0x110 + 133ba: 2210 movs r2, #16 + 133bc: f7ff ff1a bl 131f4 + 133c0: 9844 ldr r0, [sp, #272] ; 0x110 + 133c2: 4631 mov r1, r6 + 133c4: f7ff ff5a bl 1327c + 133c8: b03b add sp, #236 ; 0xec + 133ca: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 133ce: f242 3c01 movw ip, #8961 ; 0x2301 + 133d2: f64a 3e89 movw lr, #43913 ; 0xab89 + 133d6: f64d 45fe movw r5, #56574 ; 0xdcfe + 133da: f245 4476 movw r4, #21622 ; 0x5476 + 133de: f2c6 7c45 movt ip, #26437 ; 0x6745 + 133e2: f6ce 7ecd movt lr, #61389 ; 0xefcd + 133e6: f6c9 05ba movt r5, #39098 ; 0x98ba + 133ea: f2c1 0432 movt r4, #4146 ; 0x1032 + 133ee: ae24 add r6, sp, #144 ; 0x90 + 133f0: 461a mov r2, r3 + 133f2: 4630 mov r0, r6 + 133f4: 2300 movs r3, #0 + 133f6: 4639 mov r1, r7 + 133f8: 9329 str r3, [sp, #164] ; 0xa4 + 133fa: 9328 str r3, [sp, #160] ; 0xa0 + 133fc: f8cd c090 str.w ip, [sp, #144] ; 0x90 + 13400: f8cd e094 str.w lr, [sp, #148] ; 0x94 + 13404: 9526 str r5, [sp, #152] ; 0x98 + 13406: 9427 str r4, [sp, #156] ; 0x9c + 13408: f7ff fef4 bl 131f4 + 1340c: 4638 mov r0, r7 + 1340e: 4631 mov r1, r6 + 13410: f7ff ff34 bl 1327c + 13414: 2310 movs r3, #16 + 13416: e767 b.n 132e8 + +00013418 : + 13418: 4603 mov r3, r0 + 1341a: 3830 subs r0, #48 ; 0x30 + 1341c: b2c0 uxtb r0, r0 + 1341e: 2809 cmp r0, #9 + 13420: d909 bls.n 13436 + 13422: f1a3 0261 sub.w r2, r3, #97 ; 0x61 + 13426: 2a05 cmp r2, #5 + 13428: d906 bls.n 13438 + 1342a: f1a3 0241 sub.w r2, r3, #65 ; 0x41 + 1342e: 2a05 cmp r2, #5 + 13430: bf88 it hi + 13432: 20ff movhi r0, #255 ; 0xff + 13434: d904 bls.n 13440 + 13436: 4770 bx lr + 13438: f1a3 0057 sub.w r0, r3, #87 ; 0x57 + 1343c: b2c0 uxtb r0, r0 + 1343e: 4770 bx lr + 13440: f1a3 0037 sub.w r0, r3, #55 ; 0x37 + 13444: b2c0 uxtb r0, r0 + 13446: 4770 bx lr + +00013448 : + 13448: 2802 cmp r0, #2 + 1344a: bf1e ittt ne + 1344c: f245 31f0 movwne r1, #21488 ; 0x53f0 + 13450: 2300 movne r3, #0 + 13452: f2c0 0103 movtne r1, #3 + 13456: d102 bne.n 1345e + 13458: e00a b.n 13470 + 1345a: 4282 cmp r2, r0 + 1345c: d005 beq.n 1346a + 1345e: 3301 adds r3, #1 + 13460: 5cca ldrb r2, [r1, r3] + 13462: 2a00 cmp r2, #0 + 13464: d1f9 bne.n 1345a + 13466: 4610 mov r0, r2 + 13468: 4770 bx lr + 1346a: 2001 movs r0, #1 + 1346c: 4098 lsls r0, r3 + 1346e: 4770 bx lr + 13470: 2001 movs r0, #1 + 13472: 4770 bx lr + +00013474 : + 13474: 7802 ldrb r2, [r0, #0] + 13476: b1c2 cbz r2, 134aa + 13478: f002 027f and.w r2, r2, #127 ; 0x7f + 1347c: 2a04 cmp r2, #4 + 1347e: bf18 it ne + 13480: 2a02 cmpne r2, #2 + 13482: d014 beq.n 134ae + 13484: 2a0b cmp r2, #11 + 13486: d012 beq.n 134ae + 13488: 2a16 cmp r2, #22 + 1348a: d108 bne.n 1349e + 1348c: e00f b.n 134ae + 1348e: 2b04 cmp r3, #4 + 13490: bf18 it ne + 13492: 2b02 cmpne r3, #2 + 13494: d00b beq.n 134ae + 13496: 2b0b cmp r3, #11 + 13498: d009 beq.n 134ae + 1349a: 2b16 cmp r3, #22 + 1349c: d007 beq.n 134ae + 1349e: f810 2f01 ldrb.w r2, [r0, #1]! + 134a2: f002 037f and.w r3, r2, #127 ; 0x7f + 134a6: 2a00 cmp r2, #0 + 134a8: d1f1 bne.n 1348e + 134aa: 4610 mov r0, r2 + 134ac: 4770 bx lr + 134ae: 2001 movs r0, #1 + 134b0: 4770 bx lr + 134b2: bf00 nop + +000134b4 : + 134b4: 7803 ldrb r3, [r0, #0] + 134b6: b16b cbz r3, 134d4 + 134b8: f003 037f and.w r3, r3, #127 ; 0x7f + 134bc: 2b02 cmp r3, #2 + 134be: bf18 it ne + 134c0: 2b04 cmpne r3, #4 + 134c2: d003 beq.n 134cc + 134c4: 2b0b cmp r3, #11 + 134c6: d001 beq.n 134cc + 134c8: 2b16 cmp r3, #22 + 134ca: d105 bne.n 134d8 + 134cc: f810 3f01 ldrb.w r3, [r0, #1]! + 134d0: 2b00 cmp r3, #0 + 134d2: d1f1 bne.n 134b8 + 134d4: 2001 movs r0, #1 + 134d6: 4770 bx lr + 134d8: 2000 movs r0, #0 + 134da: 4770 bx lr + +000134dc : + 134dc: 2a0e cmp r2, #14 + 134de: b510 push {r4, lr} + 134e0: dd06 ble.n 134f0 + 134e2: f7ff ffc7 bl 13474 + 134e6: 2801 cmp r0, #1 + 134e8: bf14 ite ne + 134ea: 2004 movne r0, #4 + 134ec: 2000 moveq r0, #0 + 134ee: bd10 pop {r4, pc} + 134f0: 4604 mov r4, r0 + 134f2: f7ff ffdf bl 134b4 + 134f6: 2801 cmp r0, #1 + 134f8: d006 beq.n 13508 + 134fa: 4620 mov r0, r4 + 134fc: f7ff ffba bl 13474 + 13500: 2801 cmp r0, #1 + 13502: bf14 ite ne + 13504: 2002 movne r0, #2 + 13506: 2003 moveq r0, #3 + 13508: bd10 pop {r4, pc} + 1350a: bf00 nop + +0001350c : + 1350c: b5f8 push {r3, r4, r5, r6, r7, lr} + 1350e: 460c mov r4, r1 + 13510: f24f 4565 movw r5, #62565 ; 0xf465 + 13514: 461e mov r6, r3 + 13516: 4607 mov r7, r0 + 13518: 4611 mov r1, r2 + 1351a: f2c0 0500 movt r5, #0 + 1351e: 4622 mov r2, r4 + 13520: 47a8 blx r5 + 13522: 6833 ldr r3, [r6, #0] + 13524: 1938 adds r0, r7, r4 + 13526: 441c add r4, r3 + 13528: 6034 str r4, [r6, #0] + 1352a: bdf8 pop {r3, r4, r5, r6, r7, pc} + +0001352c : + 1352c: b5f8 push {r3, r4, r5, r6, r7, lr} + 1352e: 4605 mov r5, r0 + 13530: 7001 strb r1, [r0, #0] + 13532: 4614 mov r4, r2 + 13534: 706a strb r2, [r5, #1] + 13536: 9e06 ldr r6, [sp, #24] + 13538: b93a cbnz r2, 1354a + 1353a: b11e cbz r6, 13544 + 1353c: 6833 ldr r3, [r6, #0] + 1353e: 3302 adds r3, #2 + 13540: 4423 add r3, r4 + 13542: 6033 str r3, [r6, #0] + 13544: 1ca0 adds r0, r4, #2 + 13546: 4428 add r0, r5 + 13548: bdf8 pop {r3, r4, r5, r6, r7, pc} + 1354a: f24f 4765 movw r7, #62565 ; 0xf465 + 1354e: 4619 mov r1, r3 + 13550: f2c0 0700 movt r7, #0 + 13554: 3002 adds r0, #2 + 13556: 47b8 blx r7 + 13558: e7ef b.n 1353a + 1355a: bf00 nop + +0001355c : + 1355c: 2b00 cmp r3, #0 + 1355e: dd14 ble.n 1358a + 13560: b430 push {r4, r5} + 13562: 2500 movs r5, #0 + 13564: 462c mov r4, r5 + 13566: 6015 str r5, [r2, #0] + 13568: e005 b.n 13576 + 1356a: 7845 ldrb r5, [r0, #1] + 1356c: 3502 adds r5, #2 + 1356e: 442c add r4, r5 + 13570: 42a3 cmp r3, r4 + 13572: 4428 add r0, r5 + 13574: dd06 ble.n 13584 + 13576: 7805 ldrb r5, [r0, #0] + 13578: 428d cmp r5, r1 + 1357a: d1f6 bne.n 1356a + 1357c: 7843 ldrb r3, [r0, #1] + 1357e: bc30 pop {r4, r5} + 13580: 6013 str r3, [r2, #0] + 13582: 4770 bx lr + 13584: 2000 movs r0, #0 + 13586: bc30 pop {r4, r5} + 13588: 4770 bx lr + 1358a: 2000 movs r0, #0 + 1358c: 4770 bx lr + 1358e: bf00 nop + +00013590 : + 13590: b538 push {r3, r4, r5, lr} + 13592: f24f 5311 movw r3, #62737 ; 0xf511 + 13596: 460c mov r4, r1 + 13598: f2c0 0300 movt r3, #0 + 1359c: 2100 movs r1, #0 + 1359e: 2210 movs r2, #16 + 135a0: 4605 mov r5, r0 + 135a2: 4798 blx r3 + 135a4: 1e61 subs r1, r4, #1 + 135a6: 2913 cmp r1, #19 + 135a8: d80e bhi.n 135c8 + 135aa: f248 030a movw r3, #32778 ; 0x800a + 135ae: f2c0 0308 movt r3, #8 + 135b2: 2201 movs r2, #1 + 135b4: fa02 f101 lsl.w r1, r2, r1 + 135b8: 400b ands r3, r1 + 135ba: b933 cbnz r3, 135ca + 135bc: f240 6384 movw r3, #1668 ; 0x684 + 135c0: 400b ands r3, r1 + 135c2: b9a3 cbnz r3, 135ee + 135c4: 07cb lsls r3, r1, #31 + 135c6: d409 bmi.n 135dc + 135c8: bd38 pop {r3, r4, r5, pc} + 135ca: f24f 4365 movw r3, #62565 ; 0xf465 + 135ce: 4628 mov r0, r5 + 135d0: f2c0 0300 movt r3, #0 + 135d4: 490c ldr r1, [pc, #48] ; (13608 ) + 135d6: 2208 movs r2, #8 + 135d8: 4798 blx r3 + 135da: bd38 pop {r3, r4, r5, pc} + 135dc: f24f 4365 movw r3, #62565 ; 0xf465 + 135e0: 4628 mov r0, r5 + 135e2: f2c0 0300 movt r3, #0 + 135e6: 4909 ldr r1, [pc, #36] ; (1360c ) + 135e8: 2204 movs r2, #4 + 135ea: 4798 blx r3 + 135ec: bd38 pop {r3, r4, r5, pc} + 135ee: f24f 4465 movw r4, #62565 ; 0xf465 + 135f2: 4628 mov r0, r5 + 135f4: f2c0 0400 movt r4, #0 + 135f8: 4904 ldr r1, [pc, #16] ; (1360c ) + 135fa: 2204 movs r2, #4 + 135fc: 47a0 blx r4 + 135fe: 1d28 adds r0, r5, #4 + 13600: 4901 ldr r1, [pc, #4] ; (13608 ) + 13602: 2208 movs r2, #8 + 13604: 47a0 blx r4 + 13606: bd38 pop {r3, r4, r5, pc} + 13608: 00035404 .word 0x00035404 + 1360c: 00035400 .word 0x00035400 + +00013610 : + 13610: 7803 ldrb r3, [r0, #0] + 13612: b14b cbz r3, 13628 + 13614: 4603 mov r3, r0 + 13616: 2000 movs r0, #0 + 13618: f813 2f01 ldrb.w r2, [r3, #1]! + 1361c: 3001 adds r0, #1 + 1361e: b112 cbz r2, 13626 + 13620: 280d cmp r0, #13 + 13622: d1f9 bne.n 13618 + 13624: 4770 bx lr + 13626: 4770 bx lr + 13628: 4618 mov r0, r3 + 1362a: e7fb b.n 13624 + +0001362c : + 1362c: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} + 13630: f1b2 0800 subs.w r8, r2, #0 + 13634: b082 sub sp, #8 + 13636: 4689 mov r9, r1 + 13638: dd28 ble.n 1368c + 1363a: f24f 4629 movw r6, #62505 ; 0xf429 + 1363e: f24f 4a65 movw sl, #62565 ; 0xf465 + 13642: 4607 mov r7, r0 + 13644: f2c0 0600 movt r6, #0 + 13648: f2c0 0a00 movt sl, #0 + 1364c: 4641 mov r1, r8 + 1364e: 4604 mov r4, r0 + 13650: 2300 movs r3, #0 + 13652: e005 b.n 13660 + 13654: 7865 ldrb r5, [r4, #1] + 13656: 3502 adds r5, #2 + 13658: 442b add r3, r5 + 1365a: 4299 cmp r1, r3 + 1365c: 442c add r4, r5 + 1365e: dd15 ble.n 1368c + 13660: 7822 ldrb r2, [r4, #0] + 13662: 2add cmp r2, #221 ; 0xdd + 13664: d1f6 bne.n 13654 + 13666: 1ca0 adds r0, r4, #2 + 13668: 4916 ldr r1, [pc, #88] ; (136c4 ) + 1366a: 2204 movs r2, #4 + 1366c: 7865 ldrb r5, [r4, #1] + 1366e: 47b0 blx r6 + 13670: b198 cbz r0, 1369a + 13672: f64f 73fe movw r3, #65534 ; 0xfffe + 13676: f6cf 73ff movt r3, #65535 ; 0xffff + 1367a: 1b39 subs r1, r7, r4 + 1367c: 1b5b subs r3, r3, r5 + 1367e: 4441 add r1, r8 + 13680: 4419 add r1, r3 + 13682: 2900 cmp r1, #0 + 13684: dd17 ble.n 136b6 + 13686: 3502 adds r5, #2 + 13688: 442c add r4, r5 + 1368a: e7e1 b.n 13650 + 1368c: 2300 movs r3, #0 + 1368e: 4618 mov r0, r3 + 13690: f8c9 3000 str.w r3, [r9] + 13694: b002 add sp, #8 + 13696: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + 1369a: f10d 0006 add.w r0, sp, #6 + 1369e: 1da1 adds r1, r4, #6 + 136a0: 2202 movs r2, #2 + 136a2: 47d0 blx sl + 136a4: f8bd 3006 ldrh.w r3, [sp, #6] + 136a8: 2b01 cmp r3, #1 + 136aa: d1e2 bne.n 13672 + 136ac: 7863 ldrb r3, [r4, #1] + 136ae: 4620 mov r0, r4 + 136b0: f8c9 3000 str.w r3, [r9] + 136b4: e7ee b.n 13694 + 136b6: 2000 movs r0, #0 + 136b8: f8c9 0000 str.w r0, [r9] + 136bc: b002 add sp, #8 + 136be: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + 136c2: bf00 nop + 136c4: 0003540c .word 0x0003540c + +000136c8 : + 136c8: 2a00 cmp r2, #0 + 136ca: dd16 ble.n 136fa + 136cc: b410 push {r4} + 136ce: 2400 movs r4, #0 + 136d0: 4623 mov r3, r4 + 136d2: 600c str r4, [r1, #0] + 136d4: e005 b.n 136e2 + 136d6: 7844 ldrb r4, [r0, #1] + 136d8: 3402 adds r4, #2 + 136da: 4423 add r3, r4 + 136dc: 429a cmp r2, r3 + 136de: 4420 add r0, r4 + 136e0: dd07 ble.n 136f2 + 136e2: 7804 ldrb r4, [r0, #0] + 136e4: 2c30 cmp r4, #48 ; 0x30 + 136e6: d1f6 bne.n 136d6 + 136e8: 7843 ldrb r3, [r0, #1] + 136ea: f85d 4b04 ldr.w r4, [sp], #4 + 136ee: 600b str r3, [r1, #0] + 136f0: 4770 bx lr + 136f2: 2000 movs r0, #0 + 136f4: f85d 4b04 ldr.w r4, [sp], #4 + 136f8: 4770 bx lr + 136fa: 2000 movs r0, #0 + 136fc: 4770 bx lr + 136fe: bf00 nop + +00013700 : + 13700: b538 push {r3, r4, r5, lr} + 13702: f24f 4429 movw r4, #62505 ; 0xf429 + 13706: 4913 ldr r1, [pc, #76] ; (13754 ) + 13708: f2c0 0400 movt r4, #0 + 1370c: 2204 movs r2, #4 + 1370e: 4605 mov r5, r0 + 13710: 47a0 blx r4 + 13712: b1c8 cbz r0, 13748 + 13714: 4628 mov r0, r5 + 13716: 4910 ldr r1, [pc, #64] ; (13758 ) + 13718: 2204 movs r2, #4 + 1371a: 47a0 blx r4 + 1371c: b190 cbz r0, 13744 + 1371e: 4628 mov r0, r5 + 13720: 490e ldr r1, [pc, #56] ; (1375c ) + 13722: 2204 movs r2, #4 + 13724: 47a0 blx r4 + 13726: b198 cbz r0, 13750 + 13728: 4628 mov r0, r5 + 1372a: 490d ldr r1, [pc, #52] ; (13760 ) + 1372c: 2204 movs r2, #4 + 1372e: 47a0 blx r4 + 13730: b160 cbz r0, 1374c + 13732: 4628 mov r0, r5 + 13734: 490b ldr r1, [pc, #44] ; (13764 ) + 13736: 2204 movs r2, #4 + 13738: 47a0 blx r4 + 1373a: 2800 cmp r0, #0 + 1373c: bf0c ite eq + 1373e: 2004 moveq r0, #4 + 13740: 2000 movne r0, #0 + 13742: bd38 pop {r3, r4, r5, pc} + 13744: 2002 movs r0, #2 + 13746: bd38 pop {r3, r4, r5, pc} + 13748: 2001 movs r0, #1 + 1374a: bd38 pop {r3, r4, r5, pc} + 1374c: 2010 movs r0, #16 + 1374e: bd38 pop {r3, r4, r5, pc} + 13750: 2008 movs r0, #8 + 13752: bd38 pop {r3, r4, r5, pc} + 13754: 00035410 .word 0x00035410 + 13758: 00035414 .word 0x00035414 + 1375c: 00035418 .word 0x00035418 + 13760: 0003541c .word 0x0003541c + 13764: 00035420 .word 0x00035420 + +00013768 : + 13768: b538 push {r3, r4, r5, lr} + 1376a: f24f 4429 movw r4, #62505 ; 0xf429 + 1376e: 4913 ldr r1, [pc, #76] ; (137bc ) + 13770: f2c0 0400 movt r4, #0 + 13774: 2204 movs r2, #4 + 13776: 4605 mov r5, r0 + 13778: 47a0 blx r4 + 1377a: b1c8 cbz r0, 137b0 + 1377c: 4628 mov r0, r5 + 1377e: 4910 ldr r1, [pc, #64] ; (137c0 ) + 13780: 2204 movs r2, #4 + 13782: 47a0 blx r4 + 13784: b190 cbz r0, 137ac + 13786: 4628 mov r0, r5 + 13788: 490e ldr r1, [pc, #56] ; (137c4 ) + 1378a: 2204 movs r2, #4 + 1378c: 47a0 blx r4 + 1378e: b198 cbz r0, 137b8 + 13790: 4628 mov r0, r5 + 13792: 490d ldr r1, [pc, #52] ; (137c8 ) + 13794: 2204 movs r2, #4 + 13796: 47a0 blx r4 + 13798: b160 cbz r0, 137b4 + 1379a: 4628 mov r0, r5 + 1379c: 490b ldr r1, [pc, #44] ; (137cc ) + 1379e: 2204 movs r2, #4 + 137a0: 47a0 blx r4 + 137a2: 2800 cmp r0, #0 + 137a4: bf0c ite eq + 137a6: 2004 moveq r0, #4 + 137a8: 2000 movne r0, #0 + 137aa: bd38 pop {r3, r4, r5, pc} + 137ac: 2002 movs r0, #2 + 137ae: bd38 pop {r3, r4, r5, pc} + 137b0: 2001 movs r0, #1 + 137b2: bd38 pop {r3, r4, r5, pc} + 137b4: 2010 movs r0, #16 + 137b6: bd38 pop {r3, r4, r5, pc} + 137b8: 2008 movs r0, #8 + 137ba: bd38 pop {r3, r4, r5, pc} + 137bc: 00035424 .word 0x00035424 + 137c0: 00035428 .word 0x00035428 + 137c4: 0003542c .word 0x0003542c + 137c8: 00035430 .word 0x00035430 + 137cc: 00035434 .word 0x00035434 + +000137d0 : + 137d0: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} + 137d4: 1e0d subs r5, r1, #0 + 137d6: b082 sub sp, #8 + 137d8: dd03 ble.n 137e2 + 137da: 4604 mov r4, r0 + 137dc: 7800 ldrb r0, [r0, #0] + 137de: 28dd cmp r0, #221 ; 0xdd + 137e0: d003 beq.n 137ea + 137e2: 2000 movs r0, #0 + 137e4: b002 add sp, #8 + 137e6: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + 137ea: 4616 mov r6, r2 + 137ec: 7861 ldrb r1, [r4, #1] + 137ee: 1eaa subs r2, r5, #2 + 137f0: b2d2 uxtb r2, r2 + 137f2: 4291 cmp r1, r2 + 137f4: d1f5 bne.n 137e2 + 137f6: f24f 4729 movw r7, #62505 ; 0xf429 + 137fa: 2204 movs r2, #4 + 137fc: 1ca0 adds r0, r4, #2 + 137fe: f2c0 0700 movt r7, #0 + 13802: 4928 ldr r1, [pc, #160] ; (138a4 ) + 13804: 9300 str r3, [sp, #0] + 13806: 47b8 blx r7 + 13808: 4602 mov r2, r0 + 1380a: 2800 cmp r0, #0 + 1380c: d1e9 bne.n 137e2 + 1380e: f1a5 0808 sub.w r8, r5, #8 + 13812: f1b8 0f03 cmp.w r8, #3 + 13816: f104 0908 add.w r9, r4, #8 + 1381a: dc09 bgt.n 13830 + 1381c: f1b8 0f00 cmp.w r8, #0 + 13820: dcdf bgt.n 137e2 + 13822: 9a0a ldr r2, [sp, #40] ; 0x28 + 13824: b112 cbz r2, 1382c + 13826: f1b8 0f05 cmp.w r8, #5 + 1382a: dc2b bgt.n 13884 + 1382c: 2001 movs r0, #1 + 1382e: e7d9 b.n 137e4 + 13830: 4648 mov r0, r9 + 13832: 9201 str r2, [sp, #4] + 13834: f7ff ff64 bl 13700 + 13838: f1a5 080c sub.w r8, r5, #12 + 1383c: f1b8 0f01 cmp.w r8, #1 + 13840: 6030 str r0, [r6, #0] + 13842: 9a01 ldr r2, [sp, #4] + 13844: 9b00 ldr r3, [sp, #0] + 13846: dd29 ble.n 1389c + 13848: 7b66 ldrb r6, [r4, #13] + 1384a: 7b21 ldrb r1, [r4, #12] + 1384c: ea51 2606 orrs.w r6, r1, r6, lsl #8 + 13850: d0c7 beq.n 137e2 + 13852: f1a5 080e sub.w r8, r5, #14 + 13856: ebb8 0f86 cmp.w r8, r6, lsl #2 + 1385a: dbc2 blt.n 137e2 + 1385c: 4692 mov sl, r2 + 1385e: 681d ldr r5, [r3, #0] + 13860: f104 090e add.w r9, r4, #14 + 13864: 4648 mov r0, r9 + 13866: 9300 str r3, [sp, #0] + 13868: f7ff ff4a bl 13700 + 1386c: f10a 0a01 add.w sl, sl, #1 + 13870: 9b00 ldr r3, [sp, #0] + 13872: 4305 orrs r5, r0 + 13874: 4556 cmp r6, sl + 13876: f1a8 0804 sub.w r8, r8, #4 + 1387a: 601d str r5, [r3, #0] + 1387c: f109 0904 add.w r9, r9, #4 + 13880: dcf0 bgt.n 13864 + 13882: e7ce b.n 13822 + 13884: f109 0002 add.w r0, r9, #2 + 13888: 4907 ldr r1, [pc, #28] ; (138a8 ) + 1388a: 2204 movs r2, #4 + 1388c: 47b8 blx r7 + 1388e: 2800 cmp r0, #0 + 13890: d1cc bne.n 1382c + 13892: 9a0a ldr r2, [sp, #40] ; 0x28 + 13894: 2301 movs r3, #1 + 13896: 4618 mov r0, r3 + 13898: 6013 str r3, [r2, #0] + 1389a: e7a3 b.n 137e4 + 1389c: f104 090c add.w r9, r4, #12 + 138a0: d09f beq.n 137e2 + 138a2: e7be b.n 13822 + 138a4: 0003540c .word 0x0003540c + 138a8: 00035438 .word 0x00035438 + +000138ac : + 138ac: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} + 138b0: 1e0d subs r5, r1, #0 + 138b2: b083 sub sp, #12 + 138b4: dd03 ble.n 138be + 138b6: 4604 mov r4, r0 + 138b8: 7800 ldrb r0, [r0, #0] + 138ba: 2830 cmp r0, #48 ; 0x30 + 138bc: d003 beq.n 138c6 + 138be: 2000 movs r0, #0 + 138c0: b003 add sp, #12 + 138c2: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + 138c6: 461e mov r6, r3 + 138c8: 7861 ldrb r1, [r4, #1] + 138ca: 1eab subs r3, r5, #2 + 138cc: b2db uxtb r3, r3 + 138ce: 4299 cmp r1, r3 + 138d0: d1f5 bne.n 138be + 138d2: 1f2f subs r7, r5, #4 + 138d4: 2f03 cmp r7, #3 + 138d6: f104 0804 add.w r8, r4, #4 + 138da: dc07 bgt.n 138ec + 138dc: 2f00 cmp r7, #0 + 138de: dcee bgt.n 138be + 138e0: 9a0a ldr r2, [sp, #40] ; 0x28 + 138e2: b10a cbz r2, 138e8 + 138e4: 2f05 cmp r7, #5 + 138e6: dc27 bgt.n 13938 + 138e8: 2001 movs r0, #1 + 138ea: e7e9 b.n 138c0 + 138ec: 4640 mov r0, r8 + 138ee: 9201 str r2, [sp, #4] + 138f0: f7ff ff3a bl 13768 + 138f4: f1a5 0708 sub.w r7, r5, #8 + 138f8: 9a01 ldr r2, [sp, #4] + 138fa: 2f01 cmp r7, #1 + 138fc: 6010 str r0, [r2, #0] + 138fe: dd2b ble.n 13958 + 13900: f894 9009 ldrb.w r9, [r4, #9] + 13904: 7a23 ldrb r3, [r4, #8] + 13906: ea53 2909 orrs.w r9, r3, r9, lsl #8 + 1390a: d0d8 beq.n 138be + 1390c: f1a5 070a sub.w r7, r5, #10 + 13910: ebb7 0f89 cmp.w r7, r9, lsl #2 + 13914: dbd3 blt.n 138be + 13916: 6835 ldr r5, [r6, #0] + 13918: f104 080a add.w r8, r4, #10 + 1391c: 2400 movs r4, #0 + 1391e: 4640 mov r0, r8 + 13920: f7ff ff22 bl 13768 + 13924: 3401 adds r4, #1 + 13926: 4305 orrs r5, r0 + 13928: 45a1 cmp r9, r4 + 1392a: f1a7 0704 sub.w r7, r7, #4 + 1392e: 6035 str r5, [r6, #0] + 13930: f108 0804 add.w r8, r8, #4 + 13934: dcf3 bgt.n 1391e + 13936: e7d3 b.n 138e0 + 13938: f24f 4329 movw r3, #62505 ; 0xf429 + 1393c: f108 0002 add.w r0, r8, #2 + 13940: f2c0 0300 movt r3, #0 + 13944: 4906 ldr r1, [pc, #24] ; (13960 ) + 13946: 2204 movs r2, #4 + 13948: 4798 blx r3 + 1394a: 2800 cmp r0, #0 + 1394c: d1cc bne.n 138e8 + 1394e: 9a0a ldr r2, [sp, #40] ; 0x28 + 13950: 2301 movs r3, #1 + 13952: 4618 mov r0, r3 + 13954: 6013 str r3, [r2, #0] + 13956: e7b3 b.n 138c0 + 13958: f104 0808 add.w r8, r4, #8 + 1395c: d0af beq.n 138be + 1395e: e7bf b.n 138e0 + 13960: 0003543c .word 0x0003543c + +00013964 : + 13964: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 13968: 290c cmp r1, #12 + 1396a: b083 sub sp, #12 + 1396c: 468b mov fp, r1 + 1396e: 4699 mov r9, r3 + 13970: d928 bls.n 139c4 + 13972: f24f 4865 movw r8, #62565 ; 0xf465 + 13976: f24f 4a29 movw sl, #62505 ; 0xf429 + 1397a: 4606 mov r6, r0 + 1397c: 4617 mov r7, r2 + 1397e: f2c0 0800 movt r8, #0 + 13982: f2c0 0a00 movt sl, #0 + 13986: 240c movs r4, #12 + 13988: e003 b.n 13992 + 1398a: 785b ldrb r3, [r3, #1] + 1398c: 441c add r4, r3 + 1398e: 45a3 cmp fp, r4 + 13990: d918 bls.n 139c4 + 13992: 5d35 ldrb r5, [r6, r4] + 13994: 1933 adds r3, r6, r4 + 13996: 2ddd cmp r5, #221 ; 0xdd + 13998: d01c beq.n 139d4 + 1399a: 2d30 cmp r5, #48 ; 0x30 + 1399c: bf18 it ne + 1399e: 3402 addne r4, #2 + 139a0: d1f3 bne.n 1398a + 139a2: 1c65 adds r5, r4, #1 + 139a4: b307 cbz r7, 139e8 + 139a6: 5d72 ldrb r2, [r6, r5] + 139a8: 4619 mov r1, r3 + 139aa: 3202 adds r2, #2 + 139ac: 4638 mov r0, r7 + 139ae: 4435 add r5, r6 + 139b0: 47c0 blx r8 + 139b2: 782b ldrb r3, [r5, #0] + 139b4: 3402 adds r4, #2 + 139b6: 3302 adds r3, #2 + 139b8: f8a9 3000 strh.w r3, [r9] + 139bc: 782b ldrb r3, [r5, #0] + 139be: 441c add r4, r3 + 139c0: 45a3 cmp fp, r4 + 139c2: d8e6 bhi.n 13992 + 139c4: 9a0d ldr r2, [sp, #52] ; 0x34 + 139c6: f8b9 0000 ldrh.w r0, [r9] + 139ca: 8813 ldrh r3, [r2, #0] + 139cc: 4418 add r0, r3 + 139ce: b003 add sp, #12 + 139d0: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 139d4: 1ca5 adds r5, r4, #2 + 139d6: 1970 adds r0, r6, r5 + 139d8: 490d ldr r1, [pc, #52] ; (13a10 ) + 139da: 2204 movs r2, #4 + 139dc: 9301 str r3, [sp, #4] + 139de: 47d0 blx sl + 139e0: 9b01 ldr r3, [sp, #4] + 139e2: b118 cbz r0, 139ec + 139e4: 462c mov r4, r5 + 139e6: e7d0 b.n 1398a + 139e8: 4435 add r5, r6 + 139ea: e7e2 b.n 139b2 + 139ec: 9a0c ldr r2, [sp, #48] ; 0x30 + 139ee: 3401 adds r4, #1 + 139f0: b162 cbz r2, 13a0c + 139f2: 5d32 ldrb r2, [r6, r4] + 139f4: 4619 mov r1, r3 + 139f6: 3202 adds r2, #2 + 139f8: 980c ldr r0, [sp, #48] ; 0x30 + 139fa: 4434 add r4, r6 + 139fc: 47c0 blx r8 + 139fe: 7823 ldrb r3, [r4, #0] + 13a00: 9a0d ldr r2, [sp, #52] ; 0x34 + 13a02: 3302 adds r3, #2 + 13a04: 8013 strh r3, [r2, #0] + 13a06: 7824 ldrb r4, [r4, #0] + 13a08: 442c add r4, r5 + 13a0a: e7c0 b.n 1398e + 13a0c: 4434 add r4, r6 + 13a0e: e7f6 b.n 139fe + 13a10: 0003540c .word 0x0003540c + +00013a14 : + 13a14: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 13a18: b083 sub sp, #12 + 13a1a: 4698 mov r8, r3 + 13a1c: 4606 mov r6, r0 + 13a1e: 468b mov fp, r1 + 13a20: 9201 str r2, [sp, #4] + 13a22: b113 cbz r3, 13a2a + 13a24: 2300 movs r3, #0 + 13a26: f8c8 3000 str.w r3, [r8] + 13a2a: b366 cbz r6, 13a86 + 13a2c: f1bb 0f00 cmp.w fp, #0 + 13a30: d029 beq.n 13a86 + 13a32: f24f 4a29 movw sl, #62505 ; 0xf429 + 13a36: 2400 movs r4, #0 + 13a38: f2c0 0a00 movt sl, #0 + 13a3c: e004 b.n 13a48 + 13a3e: 786d ldrb r5, [r5, #1] + 13a40: 3502 adds r5, #2 + 13a42: 442c add r4, r5 + 13a44: 45a3 cmp fp, r4 + 13a46: d91e bls.n 13a86 + 13a48: 5d37 ldrb r7, [r6, r4] + 13a4a: 1935 adds r5, r6, r4 + 13a4c: 2fdd cmp r7, #221 ; 0xdd + 13a4e: 46a9 mov r9, r5 + 13a50: d1f5 bne.n 13a3e + 13a52: 1ca0 adds r0, r4, #2 + 13a54: 4430 add r0, r6 + 13a56: 490f ldr r1, [pc, #60] ; (13a94 ) + 13a58: 2204 movs r2, #4 + 13a5a: 47d0 blx sl + 13a5c: 2800 cmp r0, #0 + 13a5e: d1ee bne.n 13a3e + 13a60: 9b01 ldr r3, [sp, #4] + 13a62: b143 cbz r3, 13a76 + 13a64: f24f 4465 movw r4, #62565 ; 0xf465 + 13a68: 786a ldrb r2, [r5, #1] + 13a6a: 4618 mov r0, r3 + 13a6c: f2c0 0400 movt r4, #0 + 13a70: 3202 adds r2, #2 + 13a72: 4629 mov r1, r5 + 13a74: 47a0 blx r4 + 13a76: f1b8 0f00 cmp.w r8, #0 + 13a7a: d006 beq.n 13a8a + 13a7c: 786a ldrb r2, [r5, #1] + 13a7e: 3202 adds r2, #2 + 13a80: f8c8 2000 str.w r2, [r8] + 13a84: e001 b.n 13a8a + 13a86: f04f 0900 mov.w r9, #0 + 13a8a: 4648 mov r0, r9 + 13a8c: b003 add sp, #12 + 13a8e: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 13a92: bf00 nop + 13a94: 00035440 .word 0x00035440 + +00013a98 : + 13a98: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} + 13a9c: f8dd 9028 ldr.w r9, [sp, #40] ; 0x28 + 13aa0: 4605 mov r5, r0 + 13aa2: 4688 mov r8, r1 + 13aa4: 4692 mov sl, r2 + 13aa6: 469b mov fp, r3 + 13aa8: f1b9 0f00 cmp.w r9, #0 + 13aac: d002 beq.n 13ab4 + 13aae: 2300 movs r3, #0 + 13ab0: f8c9 3000 str.w r3, [r9] + 13ab4: 782b ldrb r3, [r5, #0] + 13ab6: 2bdd cmp r3, #221 ; 0xdd + 13ab8: d12a bne.n 13b10 + 13aba: f24f 4329 movw r3, #62505 ; 0xf429 + 13abe: 1ca8 adds r0, r5, #2 + 13ac0: f2c0 0300 movt r3, #0 + 13ac4: 491f ldr r1, [pc, #124] ; (13b44 ) + 13ac6: 2204 movs r2, #4 + 13ac8: 4798 blx r3 + 13aca: bb08 cbnz r0, 13b10 + 13acc: f1b8 0f06 cmp.w r8, #6 + 13ad0: f105 0406 add.w r4, r5, #6 + 13ad4: d91c bls.n 13b10 + 13ad6: 7a2e ldrb r6, [r5, #8] + 13ad8: 7a69 ldrb r1, [r5, #9] + 13ada: 79aa ldrb r2, [r5, #6] + 13adc: 79eb ldrb r3, [r5, #7] + 13ade: ea41 2606 orr.w r6, r1, r6, lsl #8 + 13ae2: ea43 2302 orr.w r3, r3, r2, lsl #8 + 13ae6: 3604 adds r6, #4 + 13ae8: 4553 cmp r3, sl + 13aea: b2b6 uxth r6, r6 + 13aec: d10c bne.n 13b08 + 13aee: e012 b.n 13b16 + 13af0: 78a6 ldrb r6, [r4, #2] + 13af2: 78e2 ldrb r2, [r4, #3] + 13af4: 7827 ldrb r7, [r4, #0] + 13af6: 7863 ldrb r3, [r4, #1] + 13af8: ea42 2606 orr.w r6, r2, r6, lsl #8 + 13afc: ea43 2707 orr.w r7, r3, r7, lsl #8 + 13b00: 3604 adds r6, #4 + 13b02: 4557 cmp r7, sl + 13b04: b2b6 uxth r6, r6 + 13b06: d006 beq.n 13b16 + 13b08: 4434 add r4, r6 + 13b0a: 1b66 subs r6, r4, r5 + 13b0c: 4546 cmp r6, r8 + 13b0e: d3ef bcc.n 13af0 + 13b10: 2000 movs r0, #0 + 13b12: e8bd 8ff8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, pc} + 13b16: f1bb 0f00 cmp.w fp, #0 + 13b1a: d007 beq.n 13b2c + 13b1c: f24f 4365 movw r3, #62565 ; 0xf465 + 13b20: 4658 mov r0, fp + 13b22: f2c0 0300 movt r3, #0 + 13b26: 4621 mov r1, r4 + 13b28: 4632 mov r2, r6 + 13b2a: 4798 blx r3 + 13b2c: f1b9 0f00 cmp.w r9, #0 + 13b30: d004 beq.n 13b3c + 13b32: f8c9 6000 str.w r6, [r9] + 13b36: 4620 mov r0, r4 + 13b38: e8bd 8ff8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, pc} + 13b3c: 4620 mov r0, r4 + 13b3e: e8bd 8ff8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, pc} + 13b42: bf00 nop + 13b44: 00035440 .word 0x00035440 + +00013b48 : + 13b48: b570 push {r4, r5, r6, lr} + 13b4a: b084 sub sp, #16 + 13b4c: 9c08 ldr r4, [sp, #32] + 13b4e: 461d mov r5, r3 + 13b50: b10c cbz r4, 13b56 + 13b52: 2300 movs r3, #0 + 13b54: 6023 str r3, [r4, #0] + 13b56: ab03 add r3, sp, #12 + 13b58: 9300 str r3, [sp, #0] + 13b5a: 2300 movs r3, #0 + 13b5c: f7ff ff9c bl 13a98 + 13b60: b180 cbz r0, 13b84 + 13b62: 9a03 ldr r2, [sp, #12] + 13b64: b192 cbz r2, 13b8c + 13b66: b17d cbz r5, 13b88 + 13b68: f24f 4365 movw r3, #62565 ; 0xf465 + 13b6c: 1d06 adds r6, r0, #4 + 13b6e: 3a04 subs r2, #4 + 13b70: 4628 mov r0, r5 + 13b72: 4631 mov r1, r6 + 13b74: f2c0 0300 movt r3, #0 + 13b78: 4798 blx r3 + 13b7a: 4630 mov r0, r6 + 13b7c: b114 cbz r4, 13b84 + 13b7e: 9b03 ldr r3, [sp, #12] + 13b80: 3b04 subs r3, #4 + 13b82: 6023 str r3, [r4, #0] + 13b84: b004 add sp, #16 + 13b86: bd70 pop {r4, r5, r6, pc} + 13b88: 3004 adds r0, #4 + 13b8a: e7f7 b.n 13b7c + 13b8c: 4610 mov r0, r2 + 13b8e: e7f9 b.n 13b84 + +00013b90 : + 13b90: f24f 5311 movw r3, #62737 ; 0xf511 + 13b94: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + 13b98: 460f mov r7, r1 + 13b9a: 4690 mov r8, r2 + 13b9c: 4606 mov r6, r0 + 13b9e: f2c0 0300 movt r3, #0 + 13ba2: 4610 mov r0, r2 + 13ba4: 2100 movs r1, #0 + 13ba6: 22b8 movs r2, #184 ; 0xb8 + 13ba8: 4798 blx r3 + 13baa: 2f01 cmp r7, #1 + 13bac: f240 80d7 bls.w 13d5e + 13bb0: 4635 mov r5, r6 + 13bb2: 7873 ldrb r3, [r6, #1] + 13bb4: 3f02 subs r7, #2 + 13bb6: 42bb cmp r3, r7 + 13bb8: f815 4b02 ldrb.w r4, [r5], #2 + 13bbc: f200 80bd bhi.w 13d3a + 13bc0: 2000 movs r0, #0 + 13bc2: f245 02f2 movw r2, #20722 ; 0x50f2 + 13bc6: f249 0e4c movw lr, #36940 ; 0x904c + 13bca: e023 b.n 13c14 + 13bcc: 2c04 cmp r4, #4 + 13bce: f000 8082 beq.w 13cd6 + 13bd2: d865 bhi.n 13ca0 + 13bd4: 2c01 cmp r4, #1 + 13bd6: f000 80a1 beq.w 13d1c + 13bda: f0c0 809a bcc.w 13d12 + 13bde: 2c02 cmp r4, #2 + 13be0: bf04 itt eq + 13be2: f8c8 5010 streq.w r5, [r8, #16] + 13be6: f888 3014 strbeq.w r3, [r8, #20] + 13bea: d006 beq.n 13bfa + 13bec: 2c03 cmp r4, #3 + 13bee: bf04 itt eq + 13bf0: f8c8 5018 streq.w r5, [r8, #24] + 13bf4: f888 301c strbeq.w r3, [r8, #28] + 13bf8: d123 bne.n 13c42 + 13bfa: 1aff subs r7, r7, r3 + 13bfc: 2f01 cmp r7, #1 + 13bfe: eb05 0603 add.w r6, r5, r3 + 13c02: d924 bls.n 13c4e + 13c04: 5cec ldrb r4, [r5, r3] + 13c06: 7873 ldrb r3, [r6, #1] + 13c08: 3f02 subs r7, #2 + 13c0a: 429f cmp r7, r3 + 13c0c: f106 0502 add.w r5, r6, #2 + 13c10: f0c0 8093 bcc.w 13d3a + 13c14: 2c24 cmp r4, #36 ; 0x24 + 13c16: d077 beq.n 13d08 + 13c18: d9d8 bls.n 13bcc + 13c1a: 2c36 cmp r4, #54 ; 0x36 + 13c1c: d06f beq.n 13cfe + 13c1e: d81d bhi.n 13c5c + 13c20: 2c2d cmp r4, #45 ; 0x2d + 13c22: d05d beq.n 13ce0 + 13c24: d94f bls.n 13cc6 + 13c26: 2c30 cmp r4, #48 ; 0x30 + 13c28: bf04 itt eq + 13c2a: f8c8 5058 streq.w r5, [r8, #88] ; 0x58 + 13c2e: f888 305c strbeq.w r3, [r8, #92] ; 0x5c + 13c32: d0e2 beq.n 13bfa + 13c34: 2c32 cmp r4, #50 ; 0x32 + 13c36: bf04 itt eq + 13c38: f8c8 5048 streq.w r5, [r8, #72] ; 0x48 + 13c3c: f888 304c strbeq.w r3, [r8, #76] ; 0x4c + 13c40: d0db beq.n 13bfa + 13c42: 3001 adds r0, #1 + 13c44: 1aff subs r7, r7, r3 + 13c46: 2f01 cmp r7, #1 + 13c48: eb05 0603 add.w r6, r5, r3 + 13c4c: d8da bhi.n 13c04 + 13c4e: 2f00 cmp r7, #0 + 13c50: d173 bne.n 13d3a + 13c52: 3000 adds r0, #0 + 13c54: bf18 it ne + 13c56: 2001 movne r0, #1 + 13c58: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 13c5c: 2c38 cmp r4, #56 ; 0x38 + 13c5e: d067 beq.n 13d30 + 13c60: d361 bcc.n 13d26 + 13c62: 2c3d cmp r4, #61 ; 0x3d + 13c64: bf04 itt eq + 13c66: f8c8 50a8 streq.w r5, [r8, #168] ; 0xa8 + 13c6a: f888 30ac strbeq.w r3, [r8, #172] ; 0xac + 13c6e: d0c4 beq.n 13bfa + 13c70: 2cdd cmp r4, #221 ; 0xdd + 13c72: d1e6 bne.n 13c42 + 13c74: 2b03 cmp r3, #3 + 13c76: d9e4 bls.n 13c42 + 13c78: 78f1 ldrb r1, [r6, #3] + 13c7a: f896 c002 ldrb.w ip, [r6, #2] + 13c7e: 0209 lsls r1, r1, #8 + 13c80: 7934 ldrb r4, [r6, #4] + 13c82: ea41 410c orr.w r1, r1, ip, lsl #16 + 13c86: 4321 orrs r1, r4 + 13c88: 4291 cmp r1, r2 + 13c8a: d05a beq.n 13d42 + 13c8c: 4571 cmp r1, lr + 13c8e: d1d8 bne.n 13c42 + 13c90: 7971 ldrb r1, [r6, #5] + 13c92: 2933 cmp r1, #51 ; 0x33 + 13c94: d1d5 bne.n 13c42 + 13c96: f8c8 50b0 str.w r5, [r8, #176] ; 0xb0 + 13c9a: f888 30b4 strb.w r3, [r8, #180] ; 0xb4 + 13c9e: e7ac b.n 13bfa + 13ca0: 2c06 cmp r4, #6 + 13ca2: d027 beq.n 13cf4 + 13ca4: d321 bcc.n 13cea + 13ca6: 2c10 cmp r4, #16 + 13ca8: bf04 itt eq + 13caa: f8c8 5038 streq.w r5, [r8, #56] ; 0x38 + 13cae: f888 303c strbeq.w r3, [r8, #60] ; 0x3c + 13cb2: d0a2 beq.n 13bfa + 13cb4: 2c21 cmp r4, #33 ; 0x21 + 13cb6: bf04 itt eq + 13cb8: f8c8 5078 streq.w r5, [r8, #120] ; 0x78 + 13cbc: f888 307c strbeq.w r3, [r8, #124] ; 0x7c + 13cc0: d09b beq.n 13bfa + 13cc2: 3001 adds r0, #1 + 13cc4: e7be b.n 13c44 + 13cc6: 2c2a cmp r4, #42 ; 0x2a + 13cc8: bf04 itt eq + 13cca: f8c8 5040 streq.w r5, [r8, #64] ; 0x40 + 13cce: f888 3044 strbeq.w r3, [r8, #68] ; 0x44 + 13cd2: d092 beq.n 13bfa + 13cd4: e7b5 b.n 13c42 + 13cd6: f8c8 5020 str.w r5, [r8, #32] + 13cda: f888 3024 strb.w r3, [r8, #36] ; 0x24 + 13cde: e78c b.n 13bfa + 13ce0: f8c8 50a0 str.w r5, [r8, #160] ; 0xa0 + 13ce4: f888 30a4 strb.w r3, [r8, #164] ; 0xa4 + 13ce8: e787 b.n 13bfa + 13cea: f8c8 5028 str.w r5, [r8, #40] ; 0x28 + 13cee: f888 302c strb.w r3, [r8, #44] ; 0x2c + 13cf2: e782 b.n 13bfa + 13cf4: f8c8 5030 str.w r5, [r8, #48] ; 0x30 + 13cf8: f888 3034 strb.w r3, [r8, #52] ; 0x34 + 13cfc: e77d b.n 13bfa + 13cfe: f8c8 5088 str.w r5, [r8, #136] ; 0x88 + 13d02: f888 308c strb.w r3, [r8, #140] ; 0x8c + 13d06: e778 b.n 13bfa + 13d08: f8c8 5080 str.w r5, [r8, #128] ; 0x80 + 13d0c: f888 3084 strb.w r3, [r8, #132] ; 0x84 + 13d10: e773 b.n 13bfa + 13d12: f8c8 5000 str.w r5, [r8] + 13d16: f888 3004 strb.w r3, [r8, #4] + 13d1a: e76e b.n 13bfa + 13d1c: f8c8 5008 str.w r5, [r8, #8] + 13d20: f888 300c strb.w r3, [r8, #12] + 13d24: e769 b.n 13bfa + 13d26: f8c8 5090 str.w r5, [r8, #144] ; 0x90 + 13d2a: f888 3094 strb.w r3, [r8, #148] ; 0x94 + 13d2e: e764 b.n 13bfa + 13d30: f8c8 5098 str.w r5, [r8, #152] ; 0x98 + 13d34: f888 309c strb.w r3, [r8, #156] ; 0x9c + 13d38: e75f b.n 13bfa + 13d3a: f04f 30ff mov.w r0, #4294967295 + 13d3e: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 13d42: 7971 ldrb r1, [r6, #5] + 13d44: 2902 cmp r1, #2 + 13d46: d014 beq.n 13d72 + 13d48: 2904 cmp r1, #4 + 13d4a: d00d beq.n 13d68 + 13d4c: 2901 cmp r1, #1 + 13d4e: bf04 itt eq + 13d50: f8c8 5050 streq.w r5, [r8, #80] ; 0x50 + 13d54: f888 3054 strbeq.w r3, [r8, #84] ; 0x54 + 13d58: f47f af73 bne.w 13c42 + 13d5c: e74d b.n 13bfa + 13d5e: 2000 movs r0, #0 + 13d60: 2f00 cmp r7, #0 + 13d62: f43f af76 beq.w 13c52 + 13d66: e7e8 b.n 13d3a + 13d68: f8c8 5070 str.w r5, [r8, #112] ; 0x70 + 13d6c: f888 3074 strb.w r3, [r8, #116] ; 0x74 + 13d70: e743 b.n 13bfa + 13d72: 2b04 cmp r3, #4 + 13d74: f43f af65 beq.w 13c42 + 13d78: 79b1 ldrb r1, [r6, #6] + 13d7a: 2901 cmp r1, #1 + 13d7c: d908 bls.n 13d90 + 13d7e: 2902 cmp r1, #2 + 13d80: bf04 itt eq + 13d82: f8c8 5068 streq.w r5, [r8, #104] ; 0x68 + 13d86: f888 306c strbeq.w r3, [r8, #108] ; 0x6c + 13d8a: f43f af36 beq.w 13bfa + 13d8e: e758 b.n 13c42 + 13d90: f8c8 5060 str.w r5, [r8, #96] ; 0x60 + 13d94: f888 3064 strb.w r3, [r8, #100] ; 0x64 + 13d98: e72f b.n 13bfa + 13d9a: bf00 nop + +00013d9c : + 13d9c: b538 push {r3, r4, r5, lr} + 13d9e: 460d mov r5, r1 + 13da0: f7ff fb3a bl 13418 + 13da4: 4604 mov r4, r0 + 13da6: 4628 mov r0, r5 + 13da8: f7ff fb36 bl 13418 + 13dac: eb04 0484 add.w r4, r4, r4, lsl #2 + 13db0: eb00 0044 add.w r0, r0, r4, lsl #1 + 13db4: b2c0 uxtb r0, r0 + 13db6: bd38 pop {r3, r4, r5, pc} + +00013db8 : + 13db8: b538 push {r3, r4, r5, lr} + 13dba: 460d mov r5, r1 + 13dbc: f7ff fb2c bl 13418 + 13dc0: 4604 mov r4, r0 + 13dc2: 4628 mov r0, r5 + 13dc4: f7ff fb28 bl 13418 + 13dc8: ea40 1004 orr.w r0, r0, r4, lsl #4 + 13dcc: b2c0 uxtb r0, r0 + 13dce: bd38 pop {r3, r4, r5, pc} + +00013dd0 : + 13dd0: b570 push {r4, r5, r6, lr} + 13dd2: 460d mov r5, r1 + 13dd4: 4616 mov r6, r2 + 13dd6: f7ff fb1f bl 13418 + 13dda: 4604 mov r4, r0 + 13ddc: 4628 mov r0, r5 + 13dde: f7ff fb1b bl 13418 + 13de2: eb04 0484 add.w r4, r4, r4, lsl #2 + 13de6: eb00 0080 add.w r0, r0, r0, lsl #2 + 13dea: 0040 lsls r0, r0, #1 + 13dec: eb04 0484 add.w r4, r4, r4, lsl #2 + 13df0: eb00 0484 add.w r4, r0, r4, lsl #2 + 13df4: 4630 mov r0, r6 + 13df6: f7ff fb0f bl 13418 + 13dfa: b2e4 uxtb r4, r4 + 13dfc: 4420 add r0, r4 + 13dfe: b2c0 uxtb r0, r0 + 13e00: bd70 pop {r4, r5, r6, pc} + 13e02: bf00 nop + +00013e04 : + 13e04: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 13e08: f24f 4965 movw r9, #62565 ; 0xf465 + 13e0c: 461e mov r6, r3 + 13e0e: 4683 mov fp, r0 + 13e10: b093 sub sp, #76 ; 0x4c + 13e12: f8dd a070 ldr.w sl, [sp, #112] ; 0x70 + 13e16: af09 add r7, sp, #36 ; 0x24 + 13e18: 9103 str r1, [sp, #12] + 13e1a: f2c0 0900 movt r9, #0 + 13e1e: 4611 mov r1, r2 + 13e20: 4638 mov r0, r7 + 13e22: 461a mov r2, r3 + 13e24: ac12 add r4, sp, #72 ; 0x48 + 13e26: 4434 add r4, r6 + 13e28: f10d 0810 add.w r8, sp, #16 + 13e2c: 9d1d ldr r5, [sp, #116] ; 0x74 + 13e2e: 47c8 blx r9 + 13e30: ea4f 6c2a mov.w ip, sl, asr #24 + 13e34: ea4f 4e2a mov.w lr, sl, asr #16 + 13e38: 1d31 adds r1, r6, #4 + 13e3a: ea4f 262a mov.w r6, sl, asr #8 + 13e3e: f8cd 8000 str.w r8, [sp] + 13e42: 4638 mov r0, r7 + 13e44: 465a mov r2, fp + 13e46: f804 ac21 strb.w sl, [r4, #-33] + 13e4a: 9b03 ldr r3, [sp, #12] + 13e4c: f804 cc24 strb.w ip, [r4, #-36] + 13e50: f804 ec23 strb.w lr, [r4, #-35] + 13e54: f804 6c22 strb.w r6, [r4, #-34] + 13e58: f001 fd56 bl 15908 + 13e5c: 4628 mov r0, r5 + 13e5e: 4641 mov r1, r8 + 13e60: 2214 movs r2, #20 + 13e62: 47c8 blx r9 + 13e64: f640 7aff movw sl, #4095 ; 0xfff + 13e68: 4640 mov r0, r8 + 13e6a: 2114 movs r1, #20 + 13e6c: 465a mov r2, fp + 13e6e: 9b03 ldr r3, [sp, #12] + 13e70: 9700 str r7, [sp, #0] + 13e72: f001 fd49 bl 15908 + 13e76: 4640 mov r0, r8 + 13e78: 4639 mov r1, r7 + 13e7a: 2214 movs r2, #20 + 13e7c: 47c8 blx r9 + 13e7e: 2400 movs r4, #0 + 13e80: 5d2b ldrb r3, [r5, r4] + 13e82: 5d3e ldrb r6, [r7, r4] + 13e84: 405e eors r6, r3 + 13e86: 552e strb r6, [r5, r4] + 13e88: 3401 adds r4, #1 + 13e8a: 2c14 cmp r4, #20 + 13e8c: d1f8 bne.n 13e80 + 13e8e: f1ba 0a01 subs.w sl, sl, #1 + 13e92: d1e9 bne.n 13e68 + 13e94: b013 add sp, #76 ; 0x4c + 13e96: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 13e9a: bf00 nop + +00013e9c : + 13e9c: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} + 13ea0: 461e mov r6, r3 + 13ea2: 4681 mov r9, r0 + 13ea4: 4688 mov r8, r1 + 13ea6: 4617 mov r7, r2 + 13ea8: b083 sub sp, #12 + 13eaa: 9c0a ldr r4, [sp, #40] ; 0x28 + 13eac: 2501 movs r5, #1 + 13eae: 9401 str r4, [sp, #4] + 13eb0: 9500 str r5, [sp, #0] + 13eb2: f7ff ffa7 bl 13e04 + 13eb6: f104 0314 add.w r3, r4, #20 + 13eba: 2402 movs r4, #2 + 13ebc: 9301 str r3, [sp, #4] + 13ebe: 4648 mov r0, r9 + 13ec0: 4641 mov r1, r8 + 13ec2: 463a mov r2, r7 + 13ec4: 4633 mov r3, r6 + 13ec6: 9400 str r4, [sp, #0] + 13ec8: f7ff ff9c bl 13e04 + 13ecc: 4628 mov r0, r5 + 13ece: b003 add sp, #12 + 13ed0: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + +00013ed4 : + 13ed4: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 13ed8: f24f 4565 movw r5, #62565 ; 0xf465 + 13edc: 460c mov r4, r1 + 13ede: f246 6767 movw r7, #26215 ; 0x6667 + 13ee2: b0b7 sub sp, #220 ; 0xdc + 13ee4: f2c0 0500 movt r5, #0 + 13ee8: 4601 mov r1, r0 + 13eea: 4690 mov r8, r2 + 13eec: a803 add r0, sp, #12 + 13eee: 2206 movs r2, #6 + 13ef0: 4699 mov r9, r3 + 13ef2: f8dd a104 ldr.w sl, [sp, #260] ; 0x104 + 13ef6: 47a8 blx r5 + 13ef8: 4621 mov r1, r4 + 13efa: 2220 movs r2, #32 + 13efc: f10d 0012 add.w r0, sp, #18 + 13f00: 47a8 blx r5 + 13f02: f245 4150 movw r1, #21584 ; 0x5450 + 13f06: f2c6 6766 movt r7, #26214 ; 0x6666 + 13f0a: f2c0 0103 movt r1, #3 + 13f0e: 2213 movs r2, #19 + 13f10: a81d add r0, sp, #116 ; 0x74 + 13f12: 47a8 blx r5 + 13f14: 2400 movs r4, #0 + 13f16: 2226 movs r2, #38 ; 0x26 + 13f18: a903 add r1, sp, #12 + 13f1a: a822 add r0, sp, #136 ; 0x88 + 13f1c: f88d 4087 strb.w r4, [sp, #135] ; 0x87 + 13f20: 47a8 blx r5 + 13f22: f10a 0313 add.w r3, sl, #19 + 13f26: fb87 2703 smull r2, r7, r7, r3 + 13f2a: 17db asrs r3, r3, #31 + 13f2c: ebc3 07e7 rsb r7, r3, r7, asr #3 + 13f30: f10d 0b34 add.w fp, sp, #52 ; 0x34 + 13f34: 42a7 cmp r7, r4 + 13f36: bfc8 it gt + 13f38: 465e movgt r6, fp + 13f3a: dd0d ble.n 13f58 + 13f3c: f88d 40ae strb.w r4, [sp, #174] ; 0xae + 13f40: 9600 str r6, [sp, #0] + 13f42: 3401 adds r4, #1 + 13f44: a81d add r0, sp, #116 ; 0x74 + 13f46: 213b movs r1, #59 ; 0x3b + 13f48: 4642 mov r2, r8 + 13f4a: 464b mov r3, r9 + 13f4c: f001 fcdc bl 15908 + 13f50: 42bc cmp r4, r7 + 13f52: f106 0614 add.w r6, r6, #20 + 13f56: d1f1 bne.n 13f3c + 13f58: 4659 mov r1, fp + 13f5a: 4652 mov r2, sl + 13f5c: 9840 ldr r0, [sp, #256] ; 0x100 + 13f5e: 47a8 blx r5 + 13f60: b037 add sp, #220 ; 0xdc + 13f62: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 13f66: bf00 nop + +00013f68 : + 13f68: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 13f6c: 460d mov r5, r1 + 13f6e: 4604 mov r4, r0 + 13f70: 7801 ldrb r1, [r0, #0] + 13f72: 7828 ldrb r0, [r5, #0] + 13f74: b0cf sub sp, #316 ; 0x13c + 13f76: 4288 cmp r0, r1 + 13f78: 4691 mov r9, r2 + 13f7a: 469a mov sl, r3 + 13f7c: d80d bhi.n 13f9a + 13f7e: d362 bcc.n 14046 + 13f80: 4620 mov r0, r4 + 13f82: 4629 mov r1, r5 + 13f84: 2200 movs r2, #0 + 13f86: f810 7f01 ldrb.w r7, [r0, #1]! + 13f8a: f811 6f01 ldrb.w r6, [r1, #1]! + 13f8e: 3201 adds r2, #1 + 13f90: 42b7 cmp r7, r6 + 13f92: d302 bcc.n 13f9a + 13f94: d857 bhi.n 14046 + 13f96: 2a05 cmp r2, #5 + 13f98: d1f5 bne.n 13f86 + 13f9a: f24f 4865 movw r8, #62565 ; 0xf465 + 13f9e: f10d 0b08 add.w fp, sp, #8 + 13fa2: 4621 mov r1, r4 + 13fa4: 2206 movs r2, #6 + 13fa6: f2c0 0800 movt r8, #0 + 13faa: 4658 mov r0, fp + 13fac: 47c0 blx r8 + 13fae: 4629 mov r1, r5 + 13fb0: f10d 000e add.w r0, sp, #14 + 13fb4: 2206 movs r2, #6 + 13fb6: 47c0 blx r8 + 13fb8: f899 1000 ldrb.w r1, [r9] + 13fbc: f89a 2000 ldrb.w r2, [sl] + 13fc0: 4291 cmp r1, r2 + 13fc2: d30d bcc.n 13fe0 + 13fc4: d836 bhi.n 14034 + 13fc6: 464e mov r6, r9 + 13fc8: 4655 mov r5, sl + 13fca: 2400 movs r4, #0 + 13fcc: f816 2f01 ldrb.w r2, [r6, #1]! + 13fd0: f815 7f01 ldrb.w r7, [r5, #1]! + 13fd4: 3401 adds r4, #1 + 13fd6: 42ba cmp r2, r7 + 13fd8: d302 bcc.n 13fe0 + 13fda: d82b bhi.n 14034 + 13fdc: 2c1f cmp r4, #31 + 13fde: d1f5 bne.n 13fcc + 13fe0: 4649 mov r1, r9 + 13fe2: 2220 movs r2, #32 + 13fe4: a805 add r0, sp, #20 + 13fe6: 47c0 blx r8 + 13fe8: 4651 mov r1, sl + 13fea: a80d add r0, sp, #52 ; 0x34 + 13fec: 2220 movs r2, #32 + 13fee: 47c0 blx r8 + 13ff0: 491d ldr r1, [pc, #116] ; (14068 ) + 13ff2: 2216 movs r2, #22 + 13ff4: a815 add r0, sp, #84 ; 0x54 + 13ff6: 47c0 blx r8 + 13ff8: 2400 movs r4, #0 + 13ffa: 4659 mov r1, fp + 13ffc: f10d 006b add.w r0, sp, #107 ; 0x6b + 14000: 224c movs r2, #76 ; 0x4c + 14002: f88d 406a strb.w r4, [sp, #106] ; 0x6a + 14006: 47c0 blx r8 + 14008: ad2e add r5, sp, #184 ; 0xb8 + 1400a: f88d 40b7 strb.w r4, [sp, #183] ; 0xb7 + 1400e: 9500 str r5, [sp, #0] + 14010: 3401 adds r4, #1 + 14012: a815 add r0, sp, #84 ; 0x54 + 14014: 2164 movs r1, #100 ; 0x64 + 14016: 9a58 ldr r2, [sp, #352] ; 0x160 + 14018: 9b59 ldr r3, [sp, #356] ; 0x164 + 1401a: f001 fc75 bl 15908 + 1401e: 2c04 cmp r4, #4 + 14020: f105 0514 add.w r5, r5, #20 + 14024: d1f1 bne.n 1400a + 14026: a92e add r1, sp, #184 ; 0xb8 + 14028: 985a ldr r0, [sp, #360] ; 0x168 + 1402a: 9a5b ldr r2, [sp, #364] ; 0x16c + 1402c: 47c0 blx r8 + 1402e: b04f add sp, #316 ; 0x13c + 14030: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 14034: 4651 mov r1, sl + 14036: a805 add r0, sp, #20 + 14038: 2220 movs r2, #32 + 1403a: 47c0 blx r8 + 1403c: 4649 mov r1, r9 + 1403e: a80d add r0, sp, #52 ; 0x34 + 14040: 2220 movs r2, #32 + 14042: 47c0 blx r8 + 14044: e7d4 b.n 13ff0 + 14046: f24f 4865 movw r8, #62565 ; 0xf465 + 1404a: f10d 0b08 add.w fp, sp, #8 + 1404e: 4629 mov r1, r5 + 14050: f2c0 0800 movt r8, #0 + 14054: 4658 mov r0, fp + 14056: 2206 movs r2, #6 + 14058: 47c0 blx r8 + 1405a: 4621 mov r1, r4 + 1405c: f10d 000e add.w r0, sp, #14 + 14060: 2206 movs r2, #6 + 14062: 47c0 blx r8 + 14064: e7a8 b.n 13fb8 + 14066: bf00 nop + 14068: 00035464 .word 0x00035464 + +0001406c : + 1406c: f245 437c movw r3, #21628 ; 0x547c + 14070: f2c0 0303 movt r3, #3 + 14074: b470 push {r4, r5, r6} + 14076: 7b04 ldrb r4, [r0, #12] + 14078: 7b42 ldrb r2, [r0, #13] + 1407a: 7b86 ldrb r6, [r0, #14] + 1407c: 7bc5 ldrb r5, [r0, #15] + 1407e: 5c9a ldrb r2, [r3, r2] + 14080: 4419 add r1, r3 + 14082: 5d9e ldrb r6, [r3, r6] + 14084: 5d5d ldrb r5, [r3, r5] + 14086: 5d1b ldrb r3, [r3, r4] + 14088: b083 sub sp, #12 + 1408a: f891 4100 ldrb.w r4, [r1, #256] ; 0x100 + 1408e: f88d 3007 strb.w r3, [sp, #7] + 14092: f88d 2004 strb.w r2, [sp, #4] + 14096: f88d 6005 strb.w r6, [sp, #5] + 1409a: f88d 5006 strb.w r5, [sp, #6] + 1409e: 2300 movs r3, #0 + 140a0: 5cc1 ldrb r1, [r0, r3] + 140a2: 404a eors r2, r1 + 140a4: 54c2 strb r2, [r0, r3] + 140a6: 3301 adds r3, #1 + 140a8: 2b04 cmp r3, #4 + 140aa: d003 beq.n 140b4 + 140ac: 4669 mov r1, sp + 140ae: 1d1d adds r5, r3, #4 + 140b0: 5c6a ldrb r2, [r5, r1] + 140b2: e7f5 b.n 140a0 + 140b4: 4603 mov r3, r0 + 140b6: 7801 ldrb r1, [r0, #0] + 140b8: 2200 movs r2, #0 + 140ba: 4061 eors r1, r4 + 140bc: f803 1b04 strb.w r1, [r3], #4 + 140c0: f813 4b01 ldrb.w r4, [r3], #1 + 140c4: 3201 adds r2, #1 + 140c6: f813 1c05 ldrb.w r1, [r3, #-5] + 140ca: 2a04 cmp r2, #4 + 140cc: ea81 0104 eor.w r1, r1, r4 + 140d0: f803 1c01 strb.w r1, [r3, #-1] + 140d4: d1f4 bne.n 140c0 + 140d6: f100 0308 add.w r3, r0, #8 + 140da: f100 040c add.w r4, r0, #12 + 140de: f813 1b01 ldrb.w r1, [r3], #1 + 140e2: f813 2c05 ldrb.w r2, [r3, #-5] + 140e6: 42a3 cmp r3, r4 + 140e8: ea82 0201 eor.w r2, r2, r1 + 140ec: f803 2c01 strb.w r2, [r3, #-1] + 140f0: d1f5 bne.n 140de + 140f2: 3010 adds r0, #16 + 140f4: f813 1b01 ldrb.w r1, [r3], #1 + 140f8: f813 2c05 ldrb.w r2, [r3, #-5] + 140fc: 4283 cmp r3, r0 + 140fe: ea82 0201 eor.w r2, r2, r1 + 14102: f803 2c01 strb.w r2, [r3, #-1] + 14106: d1f5 bne.n 140f4 + 14108: b003 add sp, #12 + 1410a: bc70 pop {r4, r5, r6} + 1410c: 4770 bx lr + 1410e: bf00 nop + +00014110 : + 14110: 2300 movs r3, #0 + 14112: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 14116: 461d mov r5, r3 + 14118: b089 sub sp, #36 ; 0x24 + 1411a: 241b movs r4, #27 + 1411c: 56c2 ldrsb r2, [r0, r3] + 1411e: 2a00 cmp r2, #0 + 14120: bfac ite ge + 14122: 462a movge r2, r5 + 14124: 4622 movlt r2, r4 + 14126: f80d 2003 strb.w r2, [sp, r3] + 1412a: 3301 adds r3, #1 + 1412c: 2b04 cmp r3, #4 + 1412e: d1f5 bne.n 1411c + 14130: 7802 ldrb r2, [r0, #0] + 14132: 7843 ldrb r3, [r0, #1] + 14134: 7886 ldrb r6, [r0, #2] + 14136: 78c7 ldrb r7, [r0, #3] + 14138: f002 0e7f and.w lr, r2, #127 ; 0x7f + 1413c: f003 057f and.w r5, r3, #127 ; 0x7f + 14140: f006 0c7f and.w ip, r6, #127 ; 0x7f + 14144: f007 047f and.w r4, r7, #127 ; 0x7f + 14148: f88d 200e strb.w r2, [sp, #14] + 1414c: f88d 2009 strb.w r2, [sp, #9] + 14150: f88d 300f strb.w r3, [sp, #15] + 14154: f88d 300a strb.w r3, [sp, #10] + 14158: f88d 600c strb.w r6, [sp, #12] + 1415c: f88d 600b strb.w r6, [sp, #11] + 14160: f88d c012 strb.w ip, [sp, #18] + 14164: f88d 700d strb.w r7, [sp, #13] + 14168: f88d 7008 strb.w r7, [sp, #8] + 1416c: f88d 4013 strb.w r4, [sp, #19] + 14170: f88d e010 strb.w lr, [sp, #16] + 14174: f88d 5011 strb.w r5, [sp, #17] + 14178: aa04 add r2, sp, #16 + 1417a: 2303 movs r3, #3 + 1417c: f992 5002 ldrsb.w r5, [r2, #2] + 14180: 0064 lsls r4, r4, #1 + 14182: b2e4 uxtb r4, r4 + 14184: 2d00 cmp r5, #0 + 14186: 70d4 strb r4, [r2, #3] + 14188: f103 33ff add.w r3, r3, #4294967295 + 1418c: bfbc itt lt + 1418e: f044 0401 orrlt.w r4, r4, #1 + 14192: 70d4 strblt r4, [r2, #3] + 14194: 3a01 subs r2, #1 + 14196: b10b cbz r3, 1419c + 14198: 78d4 ldrb r4, [r2, #3] + 1419a: e7ef b.n 1417c + 1419c: f89d 2010 ldrb.w r2, [sp, #16] + 141a0: f89d c000 ldrb.w ip, [sp] + 141a4: 0052 lsls r2, r2, #1 + 141a6: f89d a001 ldrb.w sl, [sp, #1] + 141aa: f89d e011 ldrb.w lr, [sp, #17] + 141ae: f89d 9002 ldrb.w r9, [sp, #2] + 141b2: f89d 5012 ldrb.w r5, [sp, #18] + 141b6: f89d 8013 ldrb.w r8, [sp, #19] + 141ba: f89d 4003 ldrb.w r4, [sp, #3] + 141be: b2d2 uxtb r2, r2 + 141c0: ea8a 0e0e eor.w lr, sl, lr + 141c4: ea89 0505 eor.w r5, r9, r5 + 141c8: ea82 0c0c eor.w ip, r2, ip + 141cc: ea88 0404 eor.w r4, r8, r4 + 141d0: f88d e005 strb.w lr, [sp, #5] + 141d4: f88d 5006 strb.w r5, [sp, #6] + 141d8: f88d 2010 strb.w r2, [sp, #16] + 141dc: f88d c004 strb.w ip, [sp, #4] + 141e0: f88d 4007 strb.w r4, [sp, #7] + 141e4: f10d 0e14 add.w lr, sp, #20 + 141e8: ad01 add r5, sp, #4 + 141ea: 5cec ldrb r4, [r5, r3] + 141ec: 5cc2 ldrb r2, [r0, r3] + 141ee: 4062 eors r2, r4 + 141f0: f80e 2003 strb.w r2, [lr, r3] + 141f4: 3301 adds r3, #1 + 141f6: 2b04 cmp r3, #4 + 141f8: d1f7 bne.n 141ea + 141fa: f89d 8015 ldrb.w r8, [sp, #21] + 141fe: f89d e00d ldrb.w lr, [sp, #13] + 14202: f89d c004 ldrb.w ip, [sp, #4] + 14206: f89d 5009 ldrb.w r5, [sp, #9] + 1420a: f89d 3016 ldrb.w r3, [sp, #22] + 1420e: f89d 2017 ldrb.w r2, [sp, #23] + 14212: ea8e 0505 eor.w r5, lr, r5 + 14216: f89d 0014 ldrb.w r0, [sp, #20] + 1421a: 407e eors r6, r7 + 1421c: ea88 0c0c eor.w ip, r8, ip + 14220: f89d 700a ldrb.w r7, [sp, #10] + 14224: f89d b007 ldrb.w fp, [sp, #7] + 14228: f89d a006 ldrb.w sl, [sp, #6] + 1422c: f89d 9005 ldrb.w r9, [sp, #5] + 14230: f89d 400e ldrb.w r4, [sp, #14] + 14234: f89d 800f ldrb.w r8, [sp, #15] + 14238: f89d e00b ldrb.w lr, [sp, #11] + 1423c: 407c eors r4, r7 + 1423e: ea89 0903 eor.w r9, r9, r3 + 14242: ea80 0b0b eor.w fp, r0, fp + 14246: ea8a 0a02 eor.w sl, sl, r2 + 1424a: ea88 070e eor.w r7, r8, lr + 1424e: f88d 3015 strb.w r3, [sp, #21] + 14252: f88d 501d strb.w r5, [sp, #29] + 14256: f88d 401e strb.w r4, [sp, #30] + 1425a: f88d 601c strb.w r6, [sp, #28] + 1425e: f88d b01b strb.w fp, [sp, #27] + 14262: f88d 0017 strb.w r0, [sp, #23] + 14266: f88d a01a strb.w sl, [sp, #26] + 1426a: f88d 2016 strb.w r2, [sp, #22] + 1426e: f88d 9019 strb.w r9, [sp, #25] + 14272: f88d c018 strb.w ip, [sp, #24] + 14276: f88d 701f strb.w r7, [sp, #31] + 1427a: 2300 movs r3, #0 + 1427c: ad07 add r5, sp, #28 + 1427e: ac06 add r4, sp, #24 + 14280: 5ce8 ldrb r0, [r5, r3] + 14282: 5ce2 ldrb r2, [r4, r3] + 14284: 4042 eors r2, r0 + 14286: 54ca strb r2, [r1, r3] + 14288: 3301 adds r3, #1 + 1428a: 2b04 cmp r3, #4 + 1428c: d1f8 bne.n 14280 + 1428e: b009 add sp, #36 ; 0x24 + 14290: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +00014294 : + 14294: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} + 14298: 4691 mov r9, r2 + 1429a: 460c mov r4, r1 + 1429c: f24f 4565 movw r5, #62565 ; 0xf465 + 142a0: 4680 mov r8, r0 + 142a2: 461e mov r6, r3 + 142a4: b0c9 sub sp, #292 ; 0x124 + 142a6: 9f51 ldr r7, [sp, #324] ; 0x144 + 142a8: 1841 adds r1, r0, r1 + 142aa: f2c0 0500 movt r5, #0 + 142ae: a802 add r0, sp, #8 + 142b0: 2203 movs r2, #3 + 142b2: 444c add r4, r9 + 142b4: 47a8 blx r5 + 142b6: 4444 add r4, r8 + 142b8: 463a mov r2, r7 + 142ba: 9950 ldr r1, [sp, #320] ; 0x140 + 142bc: f10d 000b add.w r0, sp, #11 + 142c0: 47a8 blx r5 + 142c2: 4631 mov r1, r6 + 142c4: 4620 mov r0, r4 + 142c6: f7fe facb bl 12860 + 142ca: a902 add r1, sp, #8 + 142cc: 1cfa adds r2, r7, #3 + 142ce: 9001 str r0, [sp, #4] + 142d0: a806 add r0, sp, #24 + 142d2: f7fe faf3 bl 128bc + 142d6: a806 add r0, sp, #24 + 142d8: 4621 mov r1, r4 + 142da: 4622 mov r2, r4 + 142dc: 4633 mov r3, r6 + 142de: f7fe fb0f bl 12900 + 142e2: a806 add r0, sp, #24 + 142e4: 19a1 adds r1, r4, r6 + 142e6: aa01 add r2, sp, #4 + 142e8: 2304 movs r3, #4 + 142ea: f7fe fb09 bl 12900 + 142ee: b049 add sp, #292 ; 0x124 + 142f0: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + +000142f4 : + 142f4: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} + 142f8: f24f 4565 movw r5, #62565 ; 0xf465 + 142fc: 460c mov r4, r1 + 142fe: 4692 mov sl, r2 + 14300: 4680 mov r8, r0 + 14302: 461e mov r6, r3 + 14304: b0c6 sub sp, #280 ; 0x118 + 14306: 9f4f ldr r7, [sp, #316] ; 0x13c + 14308: 1841 adds r1, r0, r1 + 1430a: f2c0 0500 movt r5, #0 + 1430e: 2203 movs r2, #3 + 14310: 4668 mov r0, sp + 14312: f8dd 9140 ldr.w r9, [sp, #320] ; 0x140 + 14316: 4454 add r4, sl + 14318: 47a8 blx r5 + 1431a: 994e ldr r1, [sp, #312] ; 0x138 + 1431c: 463a mov r2, r7 + 1431e: f10d 0003 add.w r0, sp, #3 + 14322: 47a8 blx r5 + 14324: 4444 add r4, r8 + 14326: 4669 mov r1, sp + 14328: 1cfa adds r2, r7, #3 + 1432a: a804 add r0, sp, #16 + 1432c: f7fe fac6 bl 128bc + 14330: 1f35 subs r5, r6, #4 + 14332: 4633 mov r3, r6 + 14334: a804 add r0, sp, #16 + 14336: 4621 mov r1, r4 + 14338: 4622 mov r2, r4 + 1433a: f7fe fae1 bl 12900 + 1433e: 4620 mov r0, r4 + 14340: 4629 mov r1, r5 + 14342: f7fe fa8d bl 12860 + 14346: 4426 add r6, r4 + 14348: f8c9 0000 str.w r0, [r9] + 1434c: f816 3c01 ldrb.w r3, [r6, #-1] + 14350: ebb3 6f10 cmp.w r3, r0, lsr #24 + 14354: d003 beq.n 1435e + 14356: 2000 movs r0, #0 + 14358: b046 add sp, #280 ; 0x118 + 1435a: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + 1435e: f899 2002 ldrb.w r2, [r9, #2] + 14362: f816 3c02 ldrb.w r3, [r6, #-2] + 14366: 429a cmp r2, r3 + 14368: d1f5 bne.n 14356 + 1436a: f816 3c03 ldrb.w r3, [r6, #-3] + 1436e: f899 2001 ldrb.w r2, [r9, #1] + 14372: 429a cmp r2, r3 + 14374: d1ef bne.n 14356 + 14376: f899 0000 ldrb.w r0, [r9] + 1437a: 5d63 ldrb r3, [r4, r5] + 1437c: 1ac0 subs r0, r0, r3 + 1437e: fab0 f080 clz r0, r0 + 14382: 0940 lsrs r0, r0, #5 + 14384: e7e8 b.n 14358 + 14386: bf00 nop + +00014388 : + 14388: 6943 ldr r3, [r0, #20] + 1438a: 6902 ldr r2, [r0, #16] + 1438c: b410 push {r4} + 1438e: 00dc lsls r4, r3, #3 + 14390: 40a1 lsls r1, r4 + 14392: 3301 adds r3, #1 + 14394: 4311 orrs r1, r2 + 14396: 2b03 cmp r3, #3 + 14398: 6143 str r3, [r0, #20] + 1439a: 6101 str r1, [r0, #16] + 1439c: d919 bls.n 143d2 + 1439e: 6882 ldr r2, [r0, #8] + 143a0: 68c3 ldr r3, [r0, #12] + 143a2: 4051 eors r1, r2 + 143a4: ea83 33f1 eor.w r3, r3, r1, ror #15 + 143a8: 4419 add r1, r3 + 143aa: f001 22ff and.w r2, r1, #4278255360 ; 0xff00ff00 + 143ae: f001 14ff and.w r4, r1, #16711935 ; 0xff00ff + 143b2: 0a12 lsrs r2, r2, #8 + 143b4: ea42 2204 orr.w r2, r2, r4, lsl #8 + 143b8: 405a eors r2, r3 + 143ba: 4411 add r1, r2 + 143bc: ea82 7271 eor.w r2, r2, r1, ror #29 + 143c0: 4411 add r1, r2 + 143c2: ea82 02b1 eor.w r2, r2, r1, ror #2 + 143c6: 2300 movs r3, #0 + 143c8: 4411 add r1, r2 + 143ca: 6081 str r1, [r0, #8] + 143cc: 60c2 str r2, [r0, #12] + 143ce: 6103 str r3, [r0, #16] + 143d0: 6143 str r3, [r0, #20] + 143d2: f85d 4b04 ldr.w r4, [sp], #4 + 143d6: 4770 bx lr + +000143d8 : + 143d8: 2300 movs r3, #0 + 143da: b430 push {r4, r5} + 143dc: 460a mov r2, r1 + 143de: 461c mov r4, r3 + 143e0: f812 5b01 ldrb.w r5, [r2], #1 + 143e4: 409d lsls r5, r3 + 143e6: 3308 adds r3, #8 + 143e8: 2b20 cmp r3, #32 + 143ea: ea44 0405 orr.w r4, r4, r5 + 143ee: d1f7 bne.n 143e0 + 143f0: 2300 movs r3, #0 + 143f2: 461a mov r2, r3 + 143f4: 6004 str r4, [r0, #0] + 143f6: 3104 adds r1, #4 + 143f8: f811 5b01 ldrb.w r5, [r1], #1 + 143fc: 409d lsls r5, r3 + 143fe: 3308 adds r3, #8 + 14400: 2b20 cmp r3, #32 + 14402: ea42 0205 orr.w r2, r2, r5 + 14406: d1f7 bne.n 143f8 + 14408: 2300 movs r3, #0 + 1440a: 6084 str r4, [r0, #8] + 1440c: 6042 str r2, [r0, #4] + 1440e: 60c2 str r2, [r0, #12] + 14410: 6143 str r3, [r0, #20] + 14412: 6103 str r3, [r0, #16] + 14414: bc30 pop {r4, r5} + 14416: 4770 bx lr + +00014418 : + 14418: b570 push {r4, r5, r6, lr} + 1441a: 4614 mov r4, r2 + 1441c: 4606 mov r6, r0 + 1441e: 460d mov r5, r1 + 14420: b132 cbz r2, 14430 + 14422: 4630 mov r0, r6 + 14424: f815 1b01 ldrb.w r1, [r5], #1 + 14428: f7ff ffae bl 14388 + 1442c: 3c01 subs r4, #1 + 1442e: d1f8 bne.n 14422 + 14430: bd70 pop {r4, r5, r6, pc} + 14432: bf00 nop + +00014434 : + 14434: b538 push {r3, r4, r5, lr} + 14436: 4604 mov r4, r0 + 14438: 460d mov r5, r1 + 1443a: 215a movs r1, #90 ; 0x5a + 1443c: f7ff ffa4 bl 14388 + 14440: 4620 mov r0, r4 + 14442: 2100 movs r1, #0 + 14444: f7ff ffa0 bl 14388 + 14448: 4620 mov r0, r4 + 1444a: 2100 movs r1, #0 + 1444c: f7ff ff9c bl 14388 + 14450: 4620 mov r0, r4 + 14452: 2100 movs r1, #0 + 14454: f7ff ff98 bl 14388 + 14458: 4620 mov r0, r4 + 1445a: 2100 movs r1, #0 + 1445c: f7ff ff94 bl 14388 + 14460: 6963 ldr r3, [r4, #20] + 14462: 2b00 cmp r3, #0 + 14464: d1f8 bne.n 14458 + 14466: 462a mov r2, r5 + 14468: 68a0 ldr r0, [r4, #8] + 1446a: 1d2b adds r3, r5, #4 + 1446c: f802 0b01 strb.w r0, [r2], #1 + 14470: 429a cmp r2, r3 + 14472: ea4f 2010 mov.w r0, r0, lsr #8 + 14476: d1f9 bne.n 1446c + 14478: 68e2 ldr r2, [r4, #12] + 1447a: f105 0108 add.w r1, r5, #8 + 1447e: f803 2b01 strb.w r2, [r3], #1 + 14482: 428b cmp r3, r1 + 14484: ea4f 2212 mov.w r2, r2, lsr #8 + 14488: d1f9 bne.n 1447e + 1448a: e894 0006 ldmia.w r4, {r1, r2} + 1448e: 2300 movs r3, #0 + 14490: 60a1 str r1, [r4, #8] + 14492: 60e2 str r2, [r4, #12] + 14494: 6163 str r3, [r4, #20] + 14496: 6123 str r3, [r4, #16] + 14498: bd38 pop {r3, r4, r5, pc} + 1449a: bf00 nop + +0001449c : + 1449c: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 144a0: 4689 mov r9, r1 + 144a2: b089 sub sp, #36 ; 0x24 + 144a4: 4601 mov r1, r0 + 144a6: 2600 movs r6, #0 + 144a8: a802 add r0, sp, #8 + 144aa: 461c mov r4, r3 + 144ac: f89d a04c ldrb.w sl, [sp, #76] ; 0x4c + 144b0: 4615 mov r5, r2 + 144b2: f88d 6005 strb.w r6, [sp, #5] + 144b6: f88d 6006 strb.w r6, [sp, #6] + 144ba: f88d 6007 strb.w r6, [sp, #7] + 144be: 9f12 ldr r7, [sp, #72] ; 0x48 + 144c0: f7ff ff8a bl 143d8 + 144c4: f899 3001 ldrb.w r3, [r9, #1] + 144c8: f88d a004 strb.w sl, [sp, #4] + 144cc: 07d9 lsls r1, r3, #31 + 144ce: d539 bpl.n 14544 + 144d0: f109 0810 add.w r8, r9, #16 + 144d4: 4646 mov r6, r8 + 144d6: f109 0b16 add.w fp, r9, #22 + 144da: f816 1b01 ldrb.w r1, [r6], #1 + 144de: a802 add r0, sp, #8 + 144e0: f7ff ff52 bl 14388 + 144e4: 455e cmp r6, fp + 144e6: d1f8 bne.n 144da + 144e8: f899 3001 ldrb.w r3, [r9, #1] + 144ec: 079a lsls r2, r3, #30 + 144ee: d54e bpl.n 1458e + 144f0: f109 0618 add.w r6, r9, #24 + 144f4: f109 091e add.w r9, r9, #30 + 144f8: f816 1b01 ldrb.w r1, [r6], #1 + 144fc: a802 add r0, sp, #8 + 144fe: f7ff ff43 bl 14388 + 14502: 454e cmp r6, r9 + 14504: d1f8 bne.n 144f8 + 14506: 4651 mov r1, sl + 14508: ae01 add r6, sp, #4 + 1450a: f10d 0807 add.w r8, sp, #7 + 1450e: a802 add r0, sp, #8 + 14510: f7ff ff3a bl 14388 + 14514: 4546 cmp r6, r8 + 14516: d006 beq.n 14526 + 14518: f816 1f01 ldrb.w r1, [r6, #1]! + 1451c: a802 add r0, sp, #8 + 1451e: f7ff ff33 bl 14388 + 14522: 4546 cmp r6, r8 + 14524: d1f8 bne.n 14518 + 14526: b134 cbz r4, 14536 + 14528: a802 add r0, sp, #8 + 1452a: f815 1b01 ldrb.w r1, [r5], #1 + 1452e: f7ff ff2b bl 14388 + 14532: 3c01 subs r4, #1 + 14534: d1f8 bne.n 14528 + 14536: a802 add r0, sp, #8 + 14538: 4639 mov r1, r7 + 1453a: f7ff ff7b bl 14434 + 1453e: b009 add sp, #36 ; 0x24 + 14540: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 14544: f109 0604 add.w r6, r9, #4 + 14548: f109 080a add.w r8, r9, #10 + 1454c: f816 1b01 ldrb.w r1, [r6], #1 + 14550: a802 add r0, sp, #8 + 14552: f7ff ff19 bl 14388 + 14556: 4546 cmp r6, r8 + 14558: d1f8 bne.n 1454c + 1455a: f899 3001 ldrb.w r3, [r9, #1] + 1455e: 079b lsls r3, r3, #30 + 14560: d50b bpl.n 1457a + 14562: f109 0610 add.w r6, r9, #16 + 14566: f109 0916 add.w r9, r9, #22 + 1456a: f816 1b01 ldrb.w r1, [r6], #1 + 1456e: a802 add r0, sp, #8 + 14570: f7ff ff0a bl 14388 + 14574: 454e cmp r6, r9 + 14576: d1f8 bne.n 1456a + 14578: e7c5 b.n 14506 + 1457a: f109 0910 add.w r9, r9, #16 + 1457e: f818 1b01 ldrb.w r1, [r8], #1 + 14582: a802 add r0, sp, #8 + 14584: f7ff ff00 bl 14388 + 14588: 45c8 cmp r8, r9 + 1458a: d1f8 bne.n 1457e + 1458c: e7bb b.n 14506 + 1458e: f109 090a add.w r9, r9, #10 + 14592: f819 1b01 ldrb.w r1, [r9], #1 + 14596: a802 add r0, sp, #8 + 14598: f7ff fef6 bl 14388 + 1459c: 45c8 cmp r8, r9 + 1459e: d1f8 bne.n 14592 + 145a0: e7b1 b.n 14506 + 145a2: bf00 nop + +000145a4 : + 145a4: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 145a8: f245 447c movw r4, #21628 ; 0x547c + 145ac: f2c0 0403 movt r4, #3 + 145b0: b29f uxth r7, r3 + 145b2: 0c1b lsrs r3, r3, #16 + 145b4: 8007 strh r7, [r0, #0] + 145b6: 8043 strh r3, [r0, #2] + 145b8: 7815 ldrb r5, [r2, #0] + 145ba: 7856 ldrb r6, [r2, #1] + 145bc: b083 sub sp, #12 + 145be: ea45 2606 orr.w r6, r5, r6, lsl #8 + 145c2: 8086 strh r6, [r0, #4] + 145c4: f892 c003 ldrb.w ip, [r2, #3] + 145c8: 7895 ldrb r5, [r2, #2] + 145ca: f04f 0e00 mov.w lr, #0 + 145ce: ea45 250c orr.w r5, r5, ip, lsl #8 + 145d2: 80c5 strh r5, [r0, #6] + 145d4: f892 c005 ldrb.w ip, [r2, #5] + 145d8: 7912 ldrb r2, [r2, #4] + 145da: ea42 2c0c orr.w ip, r2, ip, lsl #8 + 145de: f8a0 c008 strh.w ip, [r0, #8] + 145e2: f00e 0801 and.w r8, lr, #1 + 145e6: ea4f 0248 mov.w r2, r8, lsl #1 + 145ea: f811 9018 ldrb.w r9, [r1, r8, lsl #1] + 145ee: 9200 str r2, [sp, #0] + 145f0: 3201 adds r2, #1 + 145f2: f811 a002 ldrb.w sl, [r1, r2] + 145f6: ea89 090c eor.w r9, r9, ip + 145fa: ea89 2a0a eor.w sl, r9, sl, lsl #8 + 145fe: ea4f 2a2a mov.w sl, sl, asr #8 + 14602: fa5f f989 uxtb.w r9, r9 + 14606: eb04 0a4a add.w sl, r4, sl, lsl #1 + 1460a: eb04 0949 add.w r9, r4, r9, lsl #1 + 1460e: f8ba b30c ldrh.w fp, [sl, #780] ; 0x30c + 14612: f8b9 a10c ldrh.w sl, [r9, #268] ; 0x10c + 14616: 9201 str r2, [sp, #4] + 14618: ea8b 0a0a eor.w sl, fp, sl + 1461c: 9a00 ldr r2, [sp, #0] + 1461e: 4457 add r7, sl + 14620: f102 0904 add.w r9, r2, #4 + 14624: b2bf uxth r7, r7 + 14626: 8007 strh r7, [r0, #0] + 14628: eb01 0a09 add.w sl, r1, r9 + 1462c: f89a a001 ldrb.w sl, [sl, #1] + 14630: f811 9009 ldrb.w r9, [r1, r9] + 14634: ea87 0b09 eor.w fp, r7, r9 + 14638: ea49 290a orr.w r9, r9, sl, lsl #8 + 1463c: ea89 0907 eor.w r9, r9, r7 + 14640: ea4f 2929 mov.w r9, r9, asr #8 + 14644: fa5f fb8b uxtb.w fp, fp + 14648: eb04 0949 add.w r9, r4, r9, lsl #1 + 1464c: eb04 0b4b add.w fp, r4, fp, lsl #1 + 14650: f8b9 a30c ldrh.w sl, [r9, #780] ; 0x30c + 14654: f8bb b10c ldrh.w fp, [fp, #268] ; 0x10c + 14658: f102 0908 add.w r9, r2, #8 + 1465c: ea8b 0a0a eor.w sl, fp, sl + 14660: 4453 add r3, sl + 14662: b29b uxth r3, r3 + 14664: 8043 strh r3, [r0, #2] + 14666: eb01 0a09 add.w sl, r1, r9 + 1466a: f89a a001 ldrb.w sl, [sl, #1] + 1466e: f811 9009 ldrb.w r9, [r1, r9] + 14672: 320c adds r2, #12 + 14674: ea49 2a0a orr.w sl, r9, sl, lsl #8 + 14678: ea8a 0a03 eor.w sl, sl, r3 + 1467c: ea83 0909 eor.w r9, r3, r9 + 14680: ea4f 2a2a mov.w sl, sl, asr #8 + 14684: fa5f f989 uxtb.w r9, r9 + 14688: eb04 0949 add.w r9, r4, r9, lsl #1 + 1468c: eb04 0a4a add.w sl, r4, sl, lsl #1 + 14690: f8b9 b10c ldrh.w fp, [r9, #268] ; 0x10c + 14694: f8ba a30c ldrh.w sl, [sl, #780] ; 0x30c + 14698: eb01 0902 add.w r9, r1, r2 + 1469c: ea8b 0a0a eor.w sl, fp, sl + 146a0: 4456 add r6, sl + 146a2: b2b6 uxth r6, r6 + 146a4: 8086 strh r6, [r0, #4] + 146a6: 5c8a ldrb r2, [r1, r2] + 146a8: f899 a001 ldrb.w sl, [r9, #1] + 146ac: ea86 0902 eor.w r9, r6, r2 + 146b0: ea42 220a orr.w r2, r2, sl, lsl #8 + 146b4: 4072 eors r2, r6 + 146b6: 1212 asrs r2, r2, #8 + 146b8: fa5f f989 uxtb.w r9, r9 + 146bc: eb04 0242 add.w r2, r4, r2, lsl #1 + 146c0: eb04 0949 add.w r9, r4, r9, lsl #1 + 146c4: f8b9 910c ldrh.w r9, [r9, #268] ; 0x10c + 146c8: f8b2 230c ldrh.w r2, [r2, #780] ; 0x30c + 146cc: ea89 0202 eor.w r2, r9, r2 + 146d0: 4415 add r5, r2 + 146d2: b2ad uxth r5, r5 + 146d4: 80c5 strh r5, [r0, #6] + 146d6: f811 2018 ldrb.w r2, [r1, r8, lsl #1] + 146da: f8dd 8004 ldr.w r8, [sp, #4] + 146de: f811 9008 ldrb.w r9, [r1, r8] + 146e2: ea85 0802 eor.w r8, r5, r2 + 146e6: ea42 2209 orr.w r2, r2, r9, lsl #8 + 146ea: 406a eors r2, r5 + 146ec: 1212 asrs r2, r2, #8 + 146ee: fa5f f888 uxtb.w r8, r8 + 146f2: eb04 0242 add.w r2, r4, r2, lsl #1 + 146f6: eb04 0848 add.w r8, r4, r8, lsl #1 + 146fa: f8b2 230c ldrh.w r2, [r2, #780] ; 0x30c + 146fe: f8b8 810c ldrh.w r8, [r8, #268] ; 0x10c + 14702: ea88 0202 eor.w r2, r8, r2 + 14706: 4472 add r2, lr + 14708: 4494 add ip, r2 + 1470a: f10e 0e01 add.w lr, lr, #1 + 1470e: fa1f fc8c uxth.w ip, ip + 14712: f1be 0f08 cmp.w lr, #8 + 14716: f8a0 c008 strh.w ip, [r0, #8] + 1471a: f47f af62 bne.w 145e2 + 1471e: b003 add sp, #12 + 14720: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +00014724 : + 14724: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 14728: b087 sub sp, #28 + 1472a: 2500 movs r5, #0 + 1472c: ac03 add r4, sp, #12 + 1472e: 5b56 ldrh r6, [r2, r5] + 14730: 5366 strh r6, [r4, r5] + 14732: 3502 adds r5, #2 + 14734: 2d0a cmp r5, #10 + 14736: d1fa bne.n 1472e + 14738: f245 457c movw r5, #21628 ; 0x547c + 1473c: f2c0 0503 movt r5, #3 + 14740: f8b2 9008 ldrh.w r9, [r2, #8] + 14744: 784e ldrb r6, [r1, #1] + 14746: 780a ldrb r2, [r1, #0] + 14748: 4499 add r9, r3 + 1474a: fa1f f989 uxth.w r9, r9 + 1474e: ea42 2606 orr.w r6, r2, r6, lsl #8 + 14752: ea86 0609 eor.w r6, r6, r9 + 14756: ea89 0202 eor.w r2, r9, r2 + 1475a: b2d2 uxtb r2, r2 + 1475c: 1236 asrs r6, r6, #8 + 1475e: eb05 0242 add.w r2, r5, r2, lsl #1 + 14762: eb05 0646 add.w r6, r5, r6, lsl #1 + 14766: f8b2 810c ldrh.w r8, [r2, #268] ; 0x10c + 1476a: f8b6 230c ldrh.w r2, [r6, #780] ; 0x30c + 1476e: f8bd 700c ldrh.w r7, [sp, #12] + 14772: ea88 0802 eor.w r8, r8, r2 + 14776: 78ce ldrb r6, [r1, #3] + 14778: 788a ldrb r2, [r1, #2] + 1477a: 44b8 add r8, r7 + 1477c: fa1f f888 uxth.w r8, r8 + 14780: ea42 2606 orr.w r6, r2, r6, lsl #8 + 14784: ea86 0608 eor.w r6, r6, r8 + 14788: ea88 0202 eor.w r2, r8, r2 + 1478c: b2d2 uxtb r2, r2 + 1478e: 1236 asrs r6, r6, #8 + 14790: eb05 0242 add.w r2, r5, r2, lsl #1 + 14794: eb05 0646 add.w r6, r5, r6, lsl #1 + 14798: f8b2 c10c ldrh.w ip, [r2, #268] ; 0x10c + 1479c: f8b6 230c ldrh.w r2, [r6, #780] ; 0x30c + 147a0: f8bd 700e ldrh.w r7, [sp, #14] + 147a4: ea8c 0c02 eor.w ip, ip, r2 + 147a8: 794e ldrb r6, [r1, #5] + 147aa: 790a ldrb r2, [r1, #4] + 147ac: 44bc add ip, r7 + 147ae: fa1f fc8c uxth.w ip, ip + 147b2: ea42 2606 orr.w r6, r2, r6, lsl #8 + 147b6: ea86 060c eor.w r6, r6, ip + 147ba: ea8c 0202 eor.w r2, ip, r2 + 147be: b2d2 uxtb r2, r2 + 147c0: 1236 asrs r6, r6, #8 + 147c2: eb05 0242 add.w r2, r5, r2, lsl #1 + 147c6: eb05 0646 add.w r6, r5, r6, lsl #1 + 147ca: f8b2 e10c ldrh.w lr, [r2, #268] ; 0x10c + 147ce: f8b6 230c ldrh.w r2, [r6, #780] ; 0x30c + 147d2: f8bd 7010 ldrh.w r7, [sp, #16] + 147d6: ea8e 0e02 eor.w lr, lr, r2 + 147da: 79ce ldrb r6, [r1, #7] + 147dc: 798a ldrb r2, [r1, #6] + 147de: 44be add lr, r7 + 147e0: fa1f fe8e uxth.w lr, lr + 147e4: ea42 2606 orr.w r6, r2, r6, lsl #8 + 147e8: ea86 060e eor.w r6, r6, lr + 147ec: ea8e 0202 eor.w r2, lr, r2 + 147f0: b2d2 uxtb r2, r2 + 147f2: 1236 asrs r6, r6, #8 + 147f4: eb05 0242 add.w r2, r5, r2, lsl #1 + 147f8: eb05 0646 add.w r6, r5, r6, lsl #1 + 147fc: f8b2 710c ldrh.w r7, [r2, #268] ; 0x10c + 14800: f8b6 230c ldrh.w r2, [r6, #780] ; 0x30c + 14804: f8bd 6012 ldrh.w r6, [sp, #18] + 14808: 4057 eors r7, r2 + 1480a: f891 a009 ldrb.w sl, [r1, #9] + 1480e: 7a0a ldrb r2, [r1, #8] + 14810: 4437 add r7, r6 + 14812: b2bf uxth r7, r7 + 14814: ea42 2a0a orr.w sl, r2, sl, lsl #8 + 14818: ea8a 0a07 eor.w sl, sl, r7 + 1481c: 407a eors r2, r7 + 1481e: b2d2 uxtb r2, r2 + 14820: ea4f 2a2a mov.w sl, sl, asr #8 + 14824: eb05 0242 add.w r2, r5, r2, lsl #1 + 14828: eb05 0a4a add.w sl, r5, sl, lsl #1 + 1482c: f8b2 610c ldrh.w r6, [r2, #268] ; 0x10c + 14830: f8ba 230c ldrh.w r2, [sl, #780] ; 0x30c + 14834: f8bd b014 ldrh.w fp, [sp, #20] + 14838: 4056 eors r6, r2 + 1483a: f891 a00b ldrb.w sl, [r1, #11] + 1483e: 7a8a ldrb r2, [r1, #10] + 14840: 445e add r6, fp + 14842: b2b6 uxth r6, r6 + 14844: ea42 2a0a orr.w sl, r2, sl, lsl #8 + 14848: ea8a 0a06 eor.w sl, sl, r6 + 1484c: 4072 eors r2, r6 + 1484e: ea4f 2a2a mov.w sl, sl, asr #8 + 14852: b2d2 uxtb r2, r2 + 14854: eb05 0242 add.w r2, r5, r2, lsl #1 + 14858: eb05 054a add.w r5, r5, sl, lsl #1 + 1485c: f8b2 b10c ldrh.w fp, [r2, #268] ; 0x10c + 14860: f8b5 230c ldrh.w r2, [r5, #780] ; 0x30c + 14864: f891 a00d ldrb.w sl, [r1, #13] + 14868: ea8b 0b02 eor.w fp, fp, r2 + 1486c: 7b0a ldrb r2, [r1, #12] + 1486e: 44d9 add r9, fp + 14870: fa1f f989 uxth.w r9, r9 + 14874: ea42 2a0a orr.w sl, r2, sl, lsl #8 + 14878: ea8a 0a09 eor.w sl, sl, r9 + 1487c: ea4f 0b6a mov.w fp, sl, asr #1 + 14880: ea4b 3aca orr.w sl, fp, sl, lsl #15 + 14884: 7b8a ldrb r2, [r1, #14] + 14886: f891 b00f ldrb.w fp, [r1, #15] + 1488a: 44d0 add r8, sl + 1488c: fa1f f888 uxth.w r8, r8 + 14890: ea42 2b0b orr.w fp, r2, fp, lsl #8 + 14894: ea8b 0b08 eor.w fp, fp, r8 + 14898: ea4f 0a6b mov.w sl, fp, asr #1 + 1489c: ea4a 3bcb orr.w fp, sl, fp, lsl #15 + 148a0: 44dc add ip, fp + 148a2: fa1f fc8c uxth.w ip, ip + 148a6: ea4f 0a5c mov.w sl, ip, lsr #1 + 148aa: ea4a 3acc orr.w sl, sl, ip, lsl #15 + 148ae: 44d6 add lr, sl + 148b0: fa1f fe8e uxth.w lr, lr + 148b4: ea4f 0a5e mov.w sl, lr, lsr #1 + 148b8: ea4a 3ace orr.w sl, sl, lr, lsl #15 + 148bc: 4457 add r7, sl + 148be: b2bf uxth r7, r7 + 148c0: ea4f 0b57 mov.w fp, r7, lsr #1 + 148c4: ea4f 2a13 mov.w sl, r3, lsr #8 + 148c8: ea4b 3bc7 orr.w fp, fp, r7, lsl #15 + 148cc: 445e add r6, fp + 148ce: f00a 0b5f and.w fp, sl, #95 ; 0x5f + 148d2: b2b6 uxth r6, r6 + 148d4: f04b 0b20 orr.w fp, fp, #32 + 148d8: 9000 str r0, [sp, #0] + 148da: f8ad 800c strh.w r8, [sp, #12] + 148de: f880 a000 strb.w sl, [r0] + 148e2: 7083 strb r3, [r0, #2] + 148e4: f880 b001 strb.w fp, [r0, #1] + 148e8: f8ad c00e strh.w ip, [sp, #14] + 148ec: ea4f 0c56 mov.w ip, r6, lsr #1 + 148f0: ea4c 3ac6 orr.w sl, ip, r6, lsl #15 + 148f4: 780b ldrb r3, [r1, #0] + 148f6: f891 c001 ldrb.w ip, [r1, #1] + 148fa: 44d1 add r9, sl + 148fc: fa1f f989 uxth.w r9, r9 + 14900: ea43 230c orr.w r3, r3, ip, lsl #8 + 14904: ea83 0309 eor.w r3, r3, r9 + 14908: ad06 add r5, sp, #24 + 1490a: 105b asrs r3, r3, #1 + 1490c: f8ad e010 strh.w lr, [sp, #16] + 14910: f8ad 7012 strh.w r7, [sp, #18] + 14914: f8ad 6014 strh.w r6, [sp, #20] + 14918: 70c3 strb r3, [r0, #3] + 1491a: f825 9d02 strh.w r9, [r5, #-2]! + 1491e: 4602 mov r2, r0 + 14920: e001 b.n 14926 + 14922: f834 8f02 ldrh.w r8, [r4, #2]! + 14926: ea4f 2318 mov.w r3, r8, lsr #8 + 1492a: 42ac cmp r4, r5 + 1492c: f882 8004 strb.w r8, [r2, #4] + 14930: 7153 strb r3, [r2, #5] + 14932: f102 0202 add.w r2, r2, #2 + 14936: d1f4 bne.n 14922 + 14938: b007 add sp, #28 + 1493a: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 1493e: bf00 nop + +00014940 : + 14940: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + 14944: 460e mov r6, r1 + 14946: 1845 adds r5, r0, r1 + 14948: 78a9 ldrb r1, [r5, #2] + 1494a: 4607 mov r7, r0 + 1494c: 2400 movs r4, #0 + 1494e: 5d80 ldrb r0, [r0, r6] + 14950: f361 0407 bfi r4, r1, #0, #8 + 14954: 7929 ldrb r1, [r5, #4] + 14956: f360 240f bfi r4, r0, #8, #8 + 1495a: f895 c005 ldrb.w ip, [r5, #5] + 1495e: f895 e006 ldrb.w lr, [r5, #6] + 14962: f361 4417 bfi r4, r1, #16, #8 + 14966: 79e9 ldrb r1, [r5, #7] + 14968: 18b5 adds r5, r6, r2 + 1496a: 461e mov r6, r3 + 1496c: b0cc sub sp, #304 ; 0x130 + 1496e: 2000 movs r0, #0 + 14970: f36c 641f bfi r4, ip, #24, #8 + 14974: f8dd 8148 ldr.w r8, [sp, #328] ; 0x148 + 14978: f36e 0007 bfi r0, lr, #0, #8 + 1497c: f361 200f bfi r0, r1, #8, #8 + 14980: ea4f 4e14 mov.w lr, r4, lsr #16 + 14984: ea4e 4300 orr.w r3, lr, r0, lsl #16 + 14988: 4641 mov r1, r8 + 1498a: a806 add r0, sp, #24 + 1498c: 9a54 ldr r2, [sp, #336] ; 0x150 + 1498e: 443d add r5, r7 + 14990: 9f53 ldr r7, [sp, #332] ; 0x14c + 14992: f7ff fe07 bl 145a4 + 14996: b2a3 uxth r3, r4 + 14998: aa06 add r2, sp, #24 + 1499a: 4641 mov r1, r8 + 1499c: a802 add r0, sp, #8 + 1499e: f7ff fec1 bl 14724 + 149a2: 4631 mov r1, r6 + 149a4: 4628 mov r0, r5 + 149a6: f7fd ff5b bl 12860 + 149aa: a902 add r1, sp, #8 + 149ac: 463a mov r2, r7 + 149ae: 9001 str r0, [sp, #4] + 149b0: a80a add r0, sp, #40 ; 0x28 + 149b2: f7fd ff83 bl 128bc + 149b6: a80a add r0, sp, #40 ; 0x28 + 149b8: 4629 mov r1, r5 + 149ba: 462a mov r2, r5 + 149bc: 4633 mov r3, r6 + 149be: f7fd ff9f bl 12900 + 149c2: a80a add r0, sp, #40 ; 0x28 + 149c4: 19a9 adds r1, r5, r6 + 149c6: aa01 add r2, sp, #4 + 149c8: 2304 movs r3, #4 + 149ca: f7fd ff99 bl 12900 + 149ce: b04c add sp, #304 ; 0x130 + 149d0: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +000149d4 : + 149d4: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + 149d8: 4607 mov r7, r0 + 149da: 4608 mov r0, r1 + 149dc: 461e mov r6, r3 + 149de: 187d adds r5, r7, r1 + 149e0: 78ab ldrb r3, [r5, #2] + 149e2: 5c79 ldrb r1, [r7, r1] + 149e4: 2400 movs r4, #0 + 149e6: f363 0407 bfi r4, r3, #0, #8 + 149ea: 792b ldrb r3, [r5, #4] + 149ec: f895 e005 ldrb.w lr, [r5, #5] + 149f0: f361 240f bfi r4, r1, #8, #8 + 149f4: 79a9 ldrb r1, [r5, #6] + 149f6: b0ca sub sp, #296 ; 0x128 + 149f8: 79ed ldrb r5, [r5, #7] + 149fa: f363 4417 bfi r4, r3, #16, #8 + 149fe: 2300 movs r3, #0 + 14a00: f36e 641f bfi r4, lr, #24, #8 + 14a04: f8dd 8140 ldr.w r8, [sp, #320] ; 0x140 + 14a08: f361 0307 bfi r3, r1, #0, #8 + 14a0c: f365 230f bfi r3, r5, #8, #8 + 14a10: 0c21 lsrs r1, r4, #16 + 14a12: 1885 adds r5, r0, r2 + 14a14: ea41 4303 orr.w r3, r1, r3, lsl #16 + 14a18: 4668 mov r0, sp + 14a1a: 4641 mov r1, r8 + 14a1c: 9a52 ldr r2, [sp, #328] ; 0x148 + 14a1e: 443d add r5, r7 + 14a20: 9f53 ldr r7, [sp, #332] ; 0x14c + 14a22: f7ff fdbf bl 145a4 + 14a26: b2a3 uxth r3, r4 + 14a28: 4641 mov r1, r8 + 14a2a: 466a mov r2, sp + 14a2c: a804 add r0, sp, #16 + 14a2e: f7ff fe79 bl 14724 + 14a32: a904 add r1, sp, #16 + 14a34: a808 add r0, sp, #32 + 14a36: 2210 movs r2, #16 + 14a38: f7fd ff40 bl 128bc + 14a3c: 1f34 subs r4, r6, #4 + 14a3e: 4633 mov r3, r6 + 14a40: a808 add r0, sp, #32 + 14a42: 4629 mov r1, r5 + 14a44: 462a mov r2, r5 + 14a46: f7fd ff5b bl 12900 + 14a4a: 4628 mov r0, r5 + 14a4c: 4621 mov r1, r4 + 14a4e: f7fd ff07 bl 12860 + 14a52: 442e add r6, r5 + 14a54: 6038 str r0, [r7, #0] + 14a56: f816 3c01 ldrb.w r3, [r6, #-1] + 14a5a: ebb3 6f10 cmp.w r3, r0, lsr #24 + 14a5e: d003 beq.n 14a68 + 14a60: 2000 movs r0, #0 + 14a62: b04a add sp, #296 ; 0x128 + 14a64: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 14a68: 78ba ldrb r2, [r7, #2] + 14a6a: f816 3c02 ldrb.w r3, [r6, #-2] + 14a6e: 429a cmp r2, r3 + 14a70: d1f6 bne.n 14a60 + 14a72: f816 3c03 ldrb.w r3, [r6, #-3] + 14a76: 787a ldrb r2, [r7, #1] + 14a78: 429a cmp r2, r3 + 14a7a: d1f1 bne.n 14a60 + 14a7c: 7838 ldrb r0, [r7, #0] + 14a7e: 5d2b ldrb r3, [r5, r4] + 14a80: 1ac0 subs r0, r0, r3 + 14a82: fab0 f080 clz r0, r0 + 14a86: 0940 lsrs r0, r0, #5 + 14a88: e7eb b.n 14a62 + 14a8a: bf00 nop + +00014a8c : + 14a8c: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 14a90: 468a mov sl, r1 + 14a92: 4614 mov r4, r2 + 14a94: b08d sub sp, #52 ; 0x34 + 14a96: 2300 movs r3, #0 + 14a98: f10d 0820 add.w r8, sp, #32 + 14a9c: 5cc2 ldrb r2, [r0, r3] + 14a9e: f808 2003 strb.w r2, [r8, r3] + 14aa2: 3301 adds r3, #1 + 14aa4: 2b10 cmp r3, #16 + 14aa6: d1f9 bne.n 14a9c + 14aa8: f245 497c movw r9, #21628 ; 0x547c + 14aac: f2c0 0903 movt r9, #3 + 14ab0: 2601 movs r6, #1 + 14ab2: 2700 movs r7, #0 + 14ab4: 2f00 cmp r7, #0 + 14ab6: f000 80c5 beq.w 14c44 + 14aba: 2f0a cmp r7, #10 + 14abc: f04f 0300 mov.w r3, #0 + 14ac0: d06a beq.n 14b98 + 14ac2: 5ce2 ldrb r2, [r4, r3] + 14ac4: f819 2002 ldrb.w r2, [r9, r2] + 14ac8: f80d 2003 strb.w r2, [sp, r3] + 14acc: 3301 adds r3, #1 + 14ace: 2b10 cmp r3, #16 + 14ad0: d1f7 bne.n 14ac2 + 14ad2: f89d 3000 ldrb.w r3, [sp] + 14ad6: f89d 1005 ldrb.w r1, [sp, #5] + 14ada: f89d 200a ldrb.w r2, [sp, #10] + 14ade: f88d 3010 strb.w r3, [sp, #16] + 14ae2: f89d 300f ldrb.w r3, [sp, #15] + 14ae6: f88d 1011 strb.w r1, [sp, #17] + 14aea: f89d 1004 ldrb.w r1, [sp, #4] + 14aee: f88d 2012 strb.w r2, [sp, #18] + 14af2: f88d 3013 strb.w r3, [sp, #19] + 14af6: f89d 2009 ldrb.w r2, [sp, #9] + 14afa: f89d 300e ldrb.w r3, [sp, #14] + 14afe: f88d 1014 strb.w r1, [sp, #20] + 14b02: f89d 1003 ldrb.w r1, [sp, #3] + 14b06: f88d 2015 strb.w r2, [sp, #21] + 14b0a: f88d 3016 strb.w r3, [sp, #22] + 14b0e: f89d 2008 ldrb.w r2, [sp, #8] + 14b12: f89d 300d ldrb.w r3, [sp, #13] + 14b16: f88d 1017 strb.w r1, [sp, #23] + 14b1a: f89d 1002 ldrb.w r1, [sp, #2] + 14b1e: f88d 2018 strb.w r2, [sp, #24] + 14b22: f88d 3019 strb.w r3, [sp, #25] + 14b26: f89d 2007 ldrb.w r2, [sp, #7] + 14b2a: f89d 300c ldrb.w r3, [sp, #12] + 14b2e: f88d 101a strb.w r1, [sp, #26] + 14b32: f89d 1001 ldrb.w r1, [sp, #1] + 14b36: f88d 201b strb.w r2, [sp, #27] + 14b3a: f88d 301c strb.w r3, [sp, #28] + 14b3e: f89d 2006 ldrb.w r2, [sp, #6] + 14b42: f89d 300b ldrb.w r3, [sp, #11] + 14b46: f88d 101d strb.w r1, [sp, #29] + 14b4a: a804 add r0, sp, #16 + 14b4c: 4669 mov r1, sp + 14b4e: f88d 301f strb.w r3, [sp, #31] + 14b52: f88d 201e strb.w r2, [sp, #30] + 14b56: f7ff fadb bl 14110 + 14b5a: a805 add r0, sp, #20 + 14b5c: a901 add r1, sp, #4 + 14b5e: f7ff fad7 bl 14110 + 14b62: a806 add r0, sp, #24 + 14b64: a902 add r1, sp, #8 + 14b66: f7ff fad3 bl 14110 + 14b6a: a807 add r0, sp, #28 + 14b6c: a903 add r1, sp, #12 + 14b6e: f7ff facf bl 14110 + 14b72: 2300 movs r3, #0 + 14b74: f818 5003 ldrb.w r5, [r8, r3] + 14b78: f81d 2003 ldrb.w r2, [sp, r3] + 14b7c: 406a eors r2, r5 + 14b7e: 54e2 strb r2, [r4, r3] + 14b80: 3301 adds r3, #1 + 14b82: 2b10 cmp r3, #16 + 14b84: d1f6 bne.n 14b74 + 14b86: 4640 mov r0, r8 + 14b88: 4639 mov r1, r7 + 14b8a: f7ff fa6f bl 1406c + 14b8e: 2e0b cmp r6, #11 + 14b90: d055 beq.n 14c3e + 14b92: 3701 adds r7, #1 + 14b94: 3601 adds r6, #1 + 14b96: e78d b.n 14ab4 + 14b98: 5ce2 ldrb r2, [r4, r3] + 14b9a: f819 2002 ldrb.w r2, [r9, r2] + 14b9e: f80d 2003 strb.w r2, [sp, r3] + 14ba2: 3301 adds r3, #1 + 14ba4: 2b10 cmp r3, #16 + 14ba6: d1f7 bne.n 14b98 + 14ba8: f89d 5005 ldrb.w r5, [sp, #5] + 14bac: f89d 000a ldrb.w r0, [sp, #10] + 14bb0: f89d 100f ldrb.w r1, [sp, #15] + 14bb4: f89d 3004 ldrb.w r3, [sp, #4] + 14bb8: f89d 2000 ldrb.w r2, [sp] + 14bbc: f89d b009 ldrb.w fp, [sp, #9] + 14bc0: f89d a00e ldrb.w sl, [sp, #14] + 14bc4: f89d 9003 ldrb.w r9, [sp, #3] + 14bc8: f89d c008 ldrb.w ip, [sp, #8] + 14bcc: f89d e00d ldrb.w lr, [sp, #13] + 14bd0: f89d 7002 ldrb.w r7, [sp, #2] + 14bd4: f89d 6007 ldrb.w r6, [sp, #7] + 14bd8: f88d 5011 strb.w r5, [sp, #17] + 14bdc: f88d 0012 strb.w r0, [sp, #18] + 14be0: f89d 500c ldrb.w r5, [sp, #12] + 14be4: f89d 0001 ldrb.w r0, [sp, #1] + 14be8: f88d 1013 strb.w r1, [sp, #19] + 14bec: f88d 3014 strb.w r3, [sp, #20] + 14bf0: f89d 1006 ldrb.w r1, [sp, #6] + 14bf4: f89d 300b ldrb.w r3, [sp, #11] + 14bf8: f88d 2010 strb.w r2, [sp, #16] + 14bfc: f88d 301f strb.w r3, [sp, #31] + 14c00: f88d b015 strb.w fp, [sp, #21] + 14c04: f88d a016 strb.w sl, [sp, #22] + 14c08: f88d 9017 strb.w r9, [sp, #23] + 14c0c: f88d c018 strb.w ip, [sp, #24] + 14c10: f88d e019 strb.w lr, [sp, #25] + 14c14: f88d 701a strb.w r7, [sp, #26] + 14c18: f88d 601b strb.w r6, [sp, #27] + 14c1c: f88d 501c strb.w r5, [sp, #28] + 14c20: f88d 001d strb.w r0, [sp, #29] + 14c24: f88d 101e strb.w r1, [sp, #30] + 14c28: 2300 movs r3, #0 + 14c2a: e000 b.n 14c2e + 14c2c: 5c5a ldrb r2, [r3, r1] + 14c2e: f818 0003 ldrb.w r0, [r8, r3] + 14c32: a904 add r1, sp, #16 + 14c34: 4042 eors r2, r0 + 14c36: 54e2 strb r2, [r4, r3] + 14c38: 3301 adds r3, #1 + 14c3a: 2b10 cmp r3, #16 + 14c3c: d1f6 bne.n 14c2c + 14c3e: b00d add sp, #52 ; 0x34 + 14c40: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 14c44: 463b mov r3, r7 + 14c46: f81a 1003 ldrb.w r1, [sl, r3] + 14c4a: f818 2003 ldrb.w r2, [r8, r3] + 14c4e: 404a eors r2, r1 + 14c50: 54e2 strb r2, [r4, r3] + 14c52: 3301 adds r3, #1 + 14c54: 2b10 cmp r3, #16 + 14c56: d1f6 bne.n 14c46 + 14c58: 4640 mov r0, r8 + 14c5a: 2100 movs r1, #0 + 14c5c: f7ff fa06 bl 1406c + 14c60: e797 b.n 14b92 + 14c62: bf00 nop + +00014c64 : + 14c64: b4f0 push {r4, r5, r6, r7} + 14c66: 1c0e adds r6, r1, #0 + 14c68: bf18 it ne + 14c6a: 2601 movne r6, #1 + 14c6c: 2a00 cmp r2, #0 + 14c6e: bf18 it ne + 14c70: 2900 cmpne r1, #0 + 14c72: f04f 0459 mov.w r4, #89 ; 0x59 + 14c76: 7004 strb r4, [r0, #0] + 14c78: bf18 it ne + 14c7a: 7f9f ldrbne r7, [r3, #30] + 14c7c: 9d04 ldr r5, [sp, #16] + 14c7e: bf1c itt ne + 14c80: f007 070f andne.w r7, r7, #15 + 14c84: 7047 strbne r7, [r0, #1] + 14c86: 2a00 cmp r2, #0 + 14c88: bf14 ite ne + 14c8a: 2200 movne r2, #0 + 14c8c: f006 0201 andeq.w r2, r6, #1 + 14c90: 9c05 ldr r4, [sp, #20] + 14c92: b1b2 cbz r2, 14cc2 + 14c94: 7e1a ldrb r2, [r3, #24] + 14c96: f002 020f and.w r2, r2, #15 + 14c9a: 7042 strb r2, [r0, #1] + 14c9c: 2202 movs r2, #2 + 14c9e: 1899 adds r1, r3, r2 + 14ca0: 7a09 ldrb r1, [r1, #8] + 14ca2: 5481 strb r1, [r0, r2] + 14ca4: 3201 adds r2, #1 + 14ca6: 2a08 cmp r2, #8 + 14ca8: d1f9 bne.n 14c9e + 14caa: 1da3 adds r3, r4, #6 + 14cac: f813 1d01 ldrb.w r1, [r3, #-1]! + 14cb0: 5481 strb r1, [r0, r2] + 14cb2: 3201 adds r2, #1 + 14cb4: 2a0e cmp r2, #14 + 14cb6: d1f9 bne.n 14cac + 14cb8: 0a2b lsrs r3, r5, #8 + 14cba: 73c5 strb r5, [r0, #15] + 14cbc: 7383 strb r3, [r0, #14] + 14cbe: bcf0 pop {r4, r5, r6, r7} + 14cc0: 4770 bx lr + 14cc2: 2900 cmp r1, #0 + 14cc4: d1ea bne.n 14c9c + 14cc6: 7041 strb r1, [r0, #1] + 14cc8: e7e8 b.n 14c9c + 14cca: bf00 nop + +00014ccc : + 14ccc: f101 03fd add.w r3, r1, #253 ; 0xfd + 14cd0: 3902 subs r1, #2 + 14cd2: bf58 it pl + 14cd4: 460b movpl r3, r1 + 14cd6: 121b asrs r3, r3, #8 + 14cd8: 7003 strb r3, [r0, #0] + 14cda: 7041 strb r1, [r0, #1] + 14cdc: 7813 ldrb r3, [r2, #0] + 14cde: f023 0330 bic.w r3, r3, #48 ; 0x30 + 14ce2: 7083 strb r3, [r0, #2] + 14ce4: 7853 ldrb r3, [r2, #1] + 14ce6: f023 0338 bic.w r3, r3, #56 ; 0x38 + 14cea: 70c3 strb r3, [r0, #3] + 14cec: 7913 ldrb r3, [r2, #4] + 14cee: 7103 strb r3, [r0, #4] + 14cf0: 7953 ldrb r3, [r2, #5] + 14cf2: 7143 strb r3, [r0, #5] + 14cf4: 7993 ldrb r3, [r2, #6] + 14cf6: 7183 strb r3, [r0, #6] + 14cf8: 79d3 ldrb r3, [r2, #7] + 14cfa: 71c3 strb r3, [r0, #7] + 14cfc: 7a13 ldrb r3, [r2, #8] + 14cfe: 7203 strb r3, [r0, #8] + 14d00: 7a53 ldrb r3, [r2, #9] + 14d02: 7243 strb r3, [r0, #9] + 14d04: 7a93 ldrb r3, [r2, #10] + 14d06: 7283 strb r3, [r0, #10] + 14d08: 7ad3 ldrb r3, [r2, #11] + 14d0a: 72c3 strb r3, [r0, #11] + 14d0c: 7b13 ldrb r3, [r2, #12] + 14d0e: 7303 strb r3, [r0, #12] + 14d10: 7b53 ldrb r3, [r2, #13] + 14d12: 7343 strb r3, [r0, #13] + 14d14: 7b93 ldrb r3, [r2, #14] + 14d16: 7383 strb r3, [r0, #14] + 14d18: 7bd3 ldrb r3, [r2, #15] + 14d1a: 73c3 strb r3, [r0, #15] + 14d1c: 4770 bx lr + 14d1e: bf00 nop + +00014d20 : + 14d20: b4f0 push {r4, r5, r6, r7} + 14d22: 2400 movs r4, #0 + 14d24: 4626 mov r6, r4 + 14d26: 5506 strb r6, [r0, r4] + 14d28: 3401 adds r4, #1 + 14d2a: 2c10 cmp r4, #16 + 14d2c: f04f 0500 mov.w r5, #0 + 14d30: d1f9 bne.n 14d26 + 14d32: 1b57 subs r7, r2, r5 + 14d34: bf18 it ne + 14d36: 2701 movne r7, #1 + 14d38: 42ab cmp r3, r5 + 14d3a: bf14 ite ne + 14d3c: 2400 movne r4, #0 + 14d3e: f007 0401 andeq.w r4, r7, #1 + 14d42: 7c0e ldrb r6, [r1, #16] + 14d44: 7006 strb r6, [r0, #0] + 14d46: 7c4e ldrb r6, [r1, #17] + 14d48: 7046 strb r6, [r0, #1] + 14d4a: 7c8e ldrb r6, [r1, #18] + 14d4c: 7086 strb r6, [r0, #2] + 14d4e: 7cce ldrb r6, [r1, #19] + 14d50: 70c6 strb r6, [r0, #3] + 14d52: 7d0e ldrb r6, [r1, #20] + 14d54: 7106 strb r6, [r0, #4] + 14d56: 7d4e ldrb r6, [r1, #21] + 14d58: 7185 strb r5, [r0, #6] + 14d5a: 7146 strb r6, [r0, #5] + 14d5c: 71c5 strb r5, [r0, #7] + 14d5e: bb04 cbnz r4, 14da2 + 14d60: 3300 adds r3, #0 + 14d62: bf18 it ne + 14d64: 2301 movne r3, #1 + 14d66: 2a00 cmp r2, #0 + 14d68: bf14 ite ne + 14d6a: 2200 movne r2, #0 + 14d6c: f003 0201 andeq.w r2, r3, #1 + 14d70: b12a cbz r2, 14d7e + 14d72: 7e0c ldrb r4, [r1, #24] + 14d74: 2200 movs r2, #0 + 14d76: f004 040f and.w r4, r4, #15 + 14d7a: 7204 strb r4, [r0, #8] + 14d7c: 7242 strb r2, [r0, #9] + 14d7e: 423b tst r3, r7 + 14d80: d00d beq.n 14d9e + 14d82: 2300 movs r3, #0 + 14d84: 18ca adds r2, r1, r3 + 14d86: 7e14 ldrb r4, [r2, #24] + 14d88: 18c2 adds r2, r0, r3 + 14d8a: 3301 adds r3, #1 + 14d8c: 2b06 cmp r3, #6 + 14d8e: 7214 strb r4, [r2, #8] + 14d90: d1f8 bne.n 14d84 + 14d92: 7f8a ldrb r2, [r1, #30] + 14d94: 2300 movs r3, #0 + 14d96: f002 020f and.w r2, r2, #15 + 14d9a: 7382 strb r2, [r0, #14] + 14d9c: 73c3 strb r3, [r0, #15] + 14d9e: bcf0 pop {r4, r5, r6, r7} + 14da0: 4770 bx lr + 14da2: 194c adds r4, r1, r5 + 14da4: 7e26 ldrb r6, [r4, #24] + 14da6: 1944 adds r4, r0, r5 + 14da8: 3501 adds r5, #1 + 14daa: 2d06 cmp r5, #6 + 14dac: 7226 strb r6, [r4, #8] + 14dae: d1f8 bne.n 14da2 + 14db0: e7d6 b.n 14d60 + 14db2: bf00 nop + +00014db4 : + 14db4: b4f0 push {r4, r5, r6, r7} + 14db6: 2400 movs r4, #0 + 14db8: 4625 mov r5, r4 + 14dba: 9e04 ldr r6, [sp, #16] + 14dbc: 9f05 ldr r7, [sp, #20] + 14dbe: 5505 strb r5, [r0, r4] + 14dc0: 3401 adds r4, #1 + 14dc2: 2c10 cmp r4, #16 + 14dc4: d1fb bne.n 14dbe + 14dc6: 2401 movs r4, #1 + 14dc8: 7004 strb r4, [r0, #0] + 14dca: 1c14 adds r4, r2, #0 + 14dcc: bf18 it ne + 14dce: 2401 movne r4, #1 + 14dd0: 2900 cmp r1, #0 + 14dd2: bf18 it ne + 14dd4: 2a00 cmpne r2, #0 + 14dd6: bf1e ittt ne + 14dd8: 7f9a ldrbne r2, [r3, #30] + 14dda: f002 020f andne.w r2, r2, #15 + 14dde: 7042 strbne r2, [r0, #1] + 14de0: 2900 cmp r1, #0 + 14de2: bf14 ite ne + 14de4: 2100 movne r1, #0 + 14de6: f004 0101 andeq.w r1, r4, #1 + 14dea: b119 cbz r1, 14df4 + 14dec: 7e1a ldrb r2, [r3, #24] + 14dee: f002 020f and.w r2, r2, #15 + 14df2: 7042 strb r2, [r0, #1] + 14df4: 2202 movs r2, #2 + 14df6: 1899 adds r1, r3, r2 + 14df8: 7a09 ldrb r1, [r1, #8] + 14dfa: 5481 strb r1, [r0, r2] + 14dfc: 3201 adds r2, #1 + 14dfe: 2a08 cmp r2, #8 + 14e00: d1f9 bne.n 14df6 + 14e02: 1db3 adds r3, r6, #6 + 14e04: f813 1d01 ldrb.w r1, [r3, #-1]! + 14e08: 5481 strb r1, [r0, r2] + 14e0a: 3201 adds r2, #1 + 14e0c: 2a0e cmp r2, #14 + 14e0e: d1f9 bne.n 14e04 + 14e10: f107 03ff add.w r3, r7, #255 ; 0xff + 14e14: ea13 0327 ands.w r3, r3, r7, asr #32 + 14e18: bf38 it cc + 14e1a: 463b movcc r3, r7 + 14e1c: 121b asrs r3, r3, #8 + 14e1e: 73c7 strb r7, [r0, #15] + 14e20: 7383 strb r3, [r0, #14] + 14e22: bcf0 pop {r4, r5, r6, r7} + 14e24: 4770 bx lr + 14e26: bf00 nop + +00014e28 : + 14e28: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 14e2c: f24f 5811 movw r8, #62737 ; 0xf511 + 14e30: b0ab sub sp, #172 ; 0xac + 14e32: f2c0 0800 movt r8, #0 + 14e36: 9106 str r1, [sp, #24] + 14e38: 9003 str r0, [sp, #12] + 14e3a: 9208 str r2, [sp, #32] + 14e3c: 2100 movs r1, #0 + 14e3e: 2210 movs r2, #16 + 14e40: a80e add r0, sp, #56 ; 0x38 + 14e42: f10d 0b48 add.w fp, sp, #72 ; 0x48 + 14e46: 461f mov r7, r3 + 14e48: f8dd 90d0 ldr.w r9, [sp, #208] ; 0xd0 + 14e4c: f10d 0a58 add.w sl, sp, #88 ; 0x58 + 14e50: 47c0 blx r8 + 14e52: 2100 movs r1, #0 + 14e54: 2210 movs r2, #16 + 14e56: 4658 mov r0, fp + 14e58: 47c0 blx r8 + 14e5a: 2100 movs r1, #0 + 14e5c: 2210 movs r2, #16 + 14e5e: 4650 mov r0, sl + 14e60: 47c0 blx r8 + 14e62: ac1e add r4, sp, #120 ; 0x78 + 14e64: 2100 movs r1, #0 + 14e66: 2210 movs r2, #16 + 14e68: a81a add r0, sp, #104 ; 0x68 + 14e6a: 47c0 blx r8 + 14e6c: ad22 add r5, sp, #136 ; 0x88 + 14e6e: 2100 movs r1, #0 + 14e70: 2210 movs r2, #16 + 14e72: 4620 mov r0, r4 + 14e74: 47c0 blx r8 + 14e76: ae26 add r6, sp, #152 ; 0x98 + 14e78: 2100 movs r1, #0 + 14e7a: 2210 movs r2, #16 + 14e7c: 4628 mov r0, r5 + 14e7e: 47c0 blx r8 + 14e80: 2100 movs r1, #0 + 14e82: 2210 movs r2, #16 + 14e84: 4630 mov r0, r6 + 14e86: 47c0 blx r8 + 14e88: f8dd 8018 ldr.w r8, [sp, #24] + 14e8c: f029 0220 bic.w r2, r9, #32 + 14e90: f028 0102 bic.w r1, r8, #2 + 14e94: 3918 subs r1, #24 + 14e96: f029 0380 bic.w r3, r9, #128 ; 0x80 + 14e9a: bf18 it ne + 14e9c: 2101 movne r1, #1 + 14e9e: 2b28 cmp r3, #40 ; 0x28 + 14ea0: bf18 it ne + 14ea2: 2a18 cmpne r2, #24 + 14ea4: bf08 it eq + 14ea6: f04f 0901 moveq.w r9, #1 + 14eaa: 9104 str r1, [sp, #16] + 14eac: bf08 it eq + 14eae: f8cd 901c streq.w r9, [sp, #28] + 14eb2: d010 beq.n 14ed6 + 14eb4: f029 0310 bic.w r3, r9, #16 + 14eb8: 2b88 cmp r3, #136 ; 0x88 + 14eba: bf1b ittet ne + 14ebc: f1a9 09b8 subne.w r9, r9, #184 ; 0xb8 + 14ec0: fab9 f989 clzne r9, r9 + 14ec4: f04f 0801 moveq.w r8, #1 + 14ec8: ea4f 1959 movne.w r9, r9, lsr #5 + 14ecc: bf14 ite ne + 14ece: f8cd 901c strne.w r9, [sp, #28] + 14ed2: f8cd 801c streq.w r8, [sp, #28] + 14ed6: f8dd 9018 ldr.w r9, [sp, #24] + 14eda: 9b03 ldr r3, [sp, #12] + 14edc: f8dd 800c ldr.w r8, [sp, #12] + 14ee0: 444b add r3, r9 + 14ee2: f893 c001 ldrb.w ip, [r3, #1] + 14ee6: 7918 ldrb r0, [r3, #4] + 14ee8: 7959 ldrb r1, [r3, #5] + 14eea: 799a ldrb r2, [r3, #6] + 14eec: 79db ldrb r3, [r3, #7] + 14eee: f818 e009 ldrb.w lr, [r8, r9] + 14ef2: 9305 str r3, [sp, #20] + 14ef4: 9b08 ldr r3, [sp, #32] + 14ef6: f8dd 8014 ldr.w r8, [sp, #20] + 14efa: 9300 str r3, [sp, #0] + 14efc: ab0c add r3, sp, #48 ; 0x30 + 14efe: 9301 str r3, [sp, #4] + 14f00: f88d 0032 strb.w r0, [sp, #50] ; 0x32 + 14f04: 9b03 ldr r3, [sp, #12] + 14f06: a80e add r0, sp, #56 ; 0x38 + 14f08: f88d 1033 strb.w r1, [sp, #51] ; 0x33 + 14f0c: f88d 2034 strb.w r2, [sp, #52] ; 0x34 + 14f10: 9907 ldr r1, [sp, #28] + 14f12: 9a04 ldr r2, [sp, #16] + 14f14: f88d c031 strb.w ip, [sp, #49] ; 0x31 + 14f18: f88d e030 strb.w lr, [sp, #48] ; 0x30 + 14f1c: f88d 8035 strb.w r8, [sp, #53] ; 0x35 + 14f20: f7ff fea0 bl 14c64 + 14f24: 4658 mov r0, fp + 14f26: 9906 ldr r1, [sp, #24] + 14f28: 9a03 ldr r2, [sp, #12] + 14f2a: f7ff fecf bl 14ccc + 14f2e: 9b07 ldr r3, [sp, #28] + 14f30: 4650 mov r0, sl + 14f32: 9903 ldr r1, [sp, #12] + 14f34: 9a04 ldr r2, [sp, #16] + 14f36: f7ff fef3 bl 14d20 + 14f3a: 462a mov r2, r5 + 14f3c: a90e add r1, sp, #56 ; 0x38 + 14f3e: 4638 mov r0, r7 + 14f40: f7ff fda4 bl 14a8c + 14f44: 9a08 ldr r2, [sp, #32] + 14f46: 9b08 ldr r3, [sp, #32] + 14f48: f002 020f and.w r2, r2, #15 + 14f4c: 920a str r2, [sp, #40] ; 0x28 + 14f4e: 464a mov r2, r9 + 14f50: 3208 adds r2, #8 + 14f52: ea4f 1813 mov.w r8, r3, lsr #4 + 14f56: 9205 str r2, [sp, #20] + 14f58: 2300 movs r3, #0 + 14f5a: f81b 1003 ldrb.w r1, [fp, r3] + 14f5e: 5cea ldrb r2, [r5, r3] + 14f60: 404a eors r2, r1 + 14f62: 54e2 strb r2, [r4, r3] + 14f64: 3301 adds r3, #1 + 14f66: 2b10 cmp r3, #16 + 14f68: d1f7 bne.n 14f5a + 14f6a: 4638 mov r0, r7 + 14f6c: 4621 mov r1, r4 + 14f6e: 462a mov r2, r5 + 14f70: f7ff fd8c bl 14a8c + 14f74: 2300 movs r3, #0 + 14f76: f81a 1003 ldrb.w r1, [sl, r3] + 14f7a: 5cea ldrb r2, [r5, r3] + 14f7c: 404a eors r2, r1 + 14f7e: 54e2 strb r2, [r4, r3] + 14f80: 3301 adds r3, #1 + 14f82: 2b10 cmp r3, #16 + 14f84: d1f7 bne.n 14f76 + 14f86: 4638 mov r0, r7 + 14f88: 4621 mov r1, r4 + 14f8a: 462a mov r2, r5 + 14f8c: f7ff fd7e bl 14a8c + 14f90: f1b8 0f00 cmp.w r8, #0 + 14f94: f000 8104 beq.w 151a0 + 14f98: f8dd 9014 ldr.w r9, [sp, #20] + 14f9c: f8dd a00c ldr.w sl, [sp, #12] + 14fa0: 44ca add sl, r9 + 14fa2: 46d3 mov fp, sl + 14fa4: f04f 0900 mov.w r9, #0 + 14fa8: 2300 movs r3, #0 + 14faa: f81b 1003 ldrb.w r1, [fp, r3] + 14fae: 5cea ldrb r2, [r5, r3] + 14fb0: 404a eors r2, r1 + 14fb2: 54e2 strb r2, [r4, r3] + 14fb4: 3301 adds r3, #1 + 14fb6: 2b10 cmp r3, #16 + 14fb8: d1f7 bne.n 14faa + 14fba: f109 0901 add.w r9, r9, #1 + 14fbe: 4638 mov r0, r7 + 14fc0: 4621 mov r1, r4 + 14fc2: 462a mov r2, r5 + 14fc4: f7ff fd62 bl 14a8c + 14fc8: 45c1 cmp r9, r8 + 14fca: f10b 0b10 add.w fp, fp, #16 + 14fce: d1eb bne.n 14fa8 + 14fd0: 9a05 ldr r2, [sp, #20] + 14fd2: eb02 1908 add.w r9, r2, r8, lsl #4 + 14fd6: 9b0a ldr r3, [sp, #40] ; 0x28 + 14fd8: 2b00 cmp r3, #0 + 14fda: f040 8088 bne.w 150ee + 14fde: f10d 0297 add.w r2, sp, #151 ; 0x97 + 14fe2: 920b str r2, [sp, #44] ; 0x2c + 14fe4: f10d 0ba7 add.w fp, sp, #167 ; 0xa7 + 14fe8: 9935 ldr r1, [sp, #212] ; 0xd4 + 14fea: 2200 movs r2, #0 + 14fec: 5cab ldrb r3, [r5, r2] + 14fee: 548b strb r3, [r1, r2] + 14ff0: 3201 adds r2, #1 + 14ff2: 2a08 cmp r2, #8 + 14ff4: d1fa bne.n 14fec + 14ff6: 9903 ldr r1, [sp, #12] + 14ff8: 9835 ldr r0, [sp, #212] ; 0xd4 + 14ffa: 4449 add r1, r9 + 14ffc: 2300 movs r3, #0 + 14ffe: 5cc2 ldrb r2, [r0, r3] + 15000: 54ca strb r2, [r1, r3] + 15002: 3301 adds r3, #1 + 15004: 2b08 cmp r3, #8 + 15006: d1fa bne.n 14ffe + 15008: f1b8 0f00 cmp.w r8, #0 + 1500c: d035 beq.n 1507a + 1500e: f8cd b024 str.w fp, [sp, #36] ; 0x24 + 15012: f8dd b01c ldr.w fp, [sp, #28] + 15016: f04f 0900 mov.w r9, #0 + 1501a: ab0c add r3, sp, #48 ; 0x30 + 1501c: f109 0901 add.w r9, r9, #1 + 15020: 9300 str r3, [sp, #0] + 15022: a81a add r0, sp, #104 ; 0x68 + 15024: 9b03 ldr r3, [sp, #12] + 15026: 9904 ldr r1, [sp, #16] + 15028: 465a mov r2, fp + 1502a: f8cd 9004 str.w r9, [sp, #4] + 1502e: f7ff fec1 bl 14db4 + 15032: 4638 mov r0, r7 + 15034: a91a add r1, sp, #104 ; 0x68 + 15036: 462a mov r2, r5 + 15038: f7ff fd28 bl 14a8c + 1503c: 2300 movs r3, #0 + 1503e: f81a 1003 ldrb.w r1, [sl, r3] + 15042: 5cea ldrb r2, [r5, r3] + 15044: 404a eors r2, r1 + 15046: 54e2 strb r2, [r4, r3] + 15048: 3301 adds r3, #1 + 1504a: 2b10 cmp r3, #16 + 1504c: d1f7 bne.n 1503e + 1504e: 2300 movs r3, #0 + 15050: 5ce2 ldrb r2, [r4, r3] + 15052: f80a 2003 strb.w r2, [sl, r3] + 15056: 3301 adds r3, #1 + 15058: 2b10 cmp r3, #16 + 1505a: d1f9 bne.n 15050 + 1505c: 45c1 cmp r9, r8 + 1505e: f10a 0a10 add.w sl, sl, #16 + 15062: d1da bne.n 1501a + 15064: f8dd 9014 ldr.w r9, [sp, #20] + 15068: f8dd a00c ldr.w sl, [sp, #12] + 1506c: eb09 1908 add.w r9, r9, r8, lsl #4 + 15070: f8dd b024 ldr.w fp, [sp, #36] ; 0x24 + 15074: f8cd 9014 str.w r9, [sp, #20] + 15078: 44ca add sl, r9 + 1507a: 9a0a ldr r2, [sp, #40] ; 0x28 + 1507c: 2a00 cmp r2, #0 + 1507e: d15a bne.n 15136 + 15080: aa0c add r2, sp, #48 ; 0x30 + 15082: f04f 0800 mov.w r8, #0 + 15086: 9200 str r2, [sp, #0] + 15088: 9b03 ldr r3, [sp, #12] + 1508a: 9904 ldr r1, [sp, #16] + 1508c: 9a07 ldr r2, [sp, #28] + 1508e: f8cd 8004 str.w r8, [sp, #4] + 15092: a81a add r0, sp, #104 ; 0x68 + 15094: f7ff fe8e bl 14db4 + 15098: 9b0b ldr r3, [sp, #44] ; 0x2c + 1509a: f803 8f01 strb.w r8, [r3, #1]! + 1509e: 455b cmp r3, fp + 150a0: d1fb bne.n 1509a + 150a2: 9908 ldr r1, [sp, #32] + 150a4: f8dd 8018 ldr.w r8, [sp, #24] + 150a8: 3108 adds r1, #8 + 150aa: f8dd 900c ldr.w r9, [sp, #12] + 150ae: 4441 add r1, r8 + 150b0: 4449 add r1, r9 + 150b2: 2300 movs r3, #0 + 150b4: 5cca ldrb r2, [r1, r3] + 150b6: 54f2 strb r2, [r6, r3] + 150b8: 3301 adds r3, #1 + 150ba: 2b08 cmp r3, #8 + 150bc: d1fa bne.n 150b4 + 150be: 4638 mov r0, r7 + 150c0: a91a add r1, sp, #104 ; 0x68 + 150c2: 462a mov r2, r5 + 150c4: f7ff fce2 bl 14a8c + 150c8: 2300 movs r3, #0 + 150ca: 5cf1 ldrb r1, [r6, r3] + 150cc: 5cea ldrb r2, [r5, r3] + 150ce: 404a eors r2, r1 + 150d0: 54e2 strb r2, [r4, r3] + 150d2: 3301 adds r3, #1 + 150d4: 2b10 cmp r3, #16 + 150d6: d1f8 bne.n 150ca + 150d8: 2300 movs r3, #0 + 150da: 5ce2 ldrb r2, [r4, r3] + 150dc: f80a 2003 strb.w r2, [sl, r3] + 150e0: 3301 adds r3, #1 + 150e2: 2b08 cmp r3, #8 + 150e4: d1f9 bne.n 150da + 150e6: 2001 movs r0, #1 + 150e8: b02b add sp, #172 ; 0xac + 150ea: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 150ee: f10d 0397 add.w r3, sp, #151 ; 0x97 + 150f2: 461a mov r2, r3 + 150f4: 930b str r3, [sp, #44] ; 0x2c + 150f6: f10d 0ba7 add.w fp, sp, #167 ; 0xa7 + 150fa: 2100 movs r1, #0 + 150fc: f802 1f01 strb.w r1, [r2, #1]! + 15100: 455a cmp r2, fp + 15102: d1fb bne.n 150fc + 15104: 9903 ldr r1, [sp, #12] + 15106: 980a ldr r0, [sp, #40] ; 0x28 + 15108: 2200 movs r2, #0 + 1510a: 4449 add r1, r9 + 1510c: 5c8b ldrb r3, [r1, r2] + 1510e: 54b3 strb r3, [r6, r2] + 15110: 3201 adds r2, #1 + 15112: 4282 cmp r2, r0 + 15114: d1fa bne.n 1510c + 15116: 9a0a ldr r2, [sp, #40] ; 0x28 + 15118: 4491 add r9, r2 + 1511a: 2200 movs r2, #0 + 1511c: 5cb1 ldrb r1, [r6, r2] + 1511e: 5cab ldrb r3, [r5, r2] + 15120: 404b eors r3, r1 + 15122: 54a3 strb r3, [r4, r2] + 15124: 3201 adds r2, #1 + 15126: 2a10 cmp r2, #16 + 15128: d1f8 bne.n 1511c + 1512a: 4638 mov r0, r7 + 1512c: 4621 mov r1, r4 + 1512e: 462a mov r2, r5 + 15130: f7ff fcac bl 14a8c + 15134: e758 b.n 14fe8 + 15136: f108 0301 add.w r3, r8, #1 + 1513a: 9301 str r3, [sp, #4] + 1513c: ab0c add r3, sp, #48 ; 0x30 + 1513e: 9300 str r3, [sp, #0] + 15140: 9a07 ldr r2, [sp, #28] + 15142: 9b03 ldr r3, [sp, #12] + 15144: a81a add r0, sp, #104 ; 0x68 + 15146: 9904 ldr r1, [sp, #16] + 15148: f7ff fe34 bl 14db4 + 1514c: 9b0b ldr r3, [sp, #44] ; 0x2c + 1514e: 2200 movs r2, #0 + 15150: f803 2f01 strb.w r2, [r3, #1]! + 15154: 455b cmp r3, fp + 15156: d1fb bne.n 15150 + 15158: 990a ldr r1, [sp, #40] ; 0x28 + 1515a: 2300 movs r3, #0 + 1515c: f81a 2003 ldrb.w r2, [sl, r3] + 15160: 54f2 strb r2, [r6, r3] + 15162: 3301 adds r3, #1 + 15164: 428b cmp r3, r1 + 15166: d1f9 bne.n 1515c + 15168: 4638 mov r0, r7 + 1516a: a91a add r1, sp, #104 ; 0x68 + 1516c: 462a mov r2, r5 + 1516e: f7ff fc8d bl 14a8c + 15172: 2300 movs r3, #0 + 15174: 5cf1 ldrb r1, [r6, r3] + 15176: 5cea ldrb r2, [r5, r3] + 15178: 404a eors r2, r1 + 1517a: 54e2 strb r2, [r4, r3] + 1517c: 3301 adds r3, #1 + 1517e: 2b10 cmp r3, #16 + 15180: d1f8 bne.n 15174 + 15182: 990a ldr r1, [sp, #40] ; 0x28 + 15184: 2300 movs r3, #0 + 15186: 5ce2 ldrb r2, [r4, r3] + 15188: f80a 2003 strb.w r2, [sl, r3] + 1518c: 3301 adds r3, #1 + 1518e: 428b cmp r3, r1 + 15190: d1f9 bne.n 15186 + 15192: f8dd 8014 ldr.w r8, [sp, #20] + 15196: f8dd a00c ldr.w sl, [sp, #12] + 1519a: 4498 add r8, r3 + 1519c: 44c2 add sl, r8 + 1519e: e76f b.n 15080 + 151a0: f8dd 9014 ldr.w r9, [sp, #20] + 151a4: f8dd a00c ldr.w sl, [sp, #12] + 151a8: 44ca add sl, r9 + 151aa: e714 b.n 14fd6 + +000151ac : + 151ac: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 151b0: f24f 5711 movw r7, #62737 ; 0xf511 + 151b4: 4680 mov r8, r0 + 151b6: b0b3 sub sp, #204 ; 0xcc + 151b8: f2c0 0700 movt r7, #0 + 151bc: 9107 str r1, [sp, #28] + 151be: 9208 str r2, [sp, #32] + 151c0: 2100 movs r1, #0 + 151c2: 2210 movs r2, #16 + 151c4: a816 add r0, sp, #88 ; 0x58 + 151c6: f10d 0b68 add.w fp, sp, #104 ; 0x68 + 151ca: 9303 str r3, [sp, #12] + 151cc: f8dd 90f0 ldr.w r9, [sp, #240] ; 0xf0 + 151d0: f10d 0a78 add.w sl, sp, #120 ; 0x78 + 151d4: 47b8 blx r7 + 151d6: 2100 movs r1, #0 + 151d8: 2210 movs r2, #16 + 151da: 4658 mov r0, fp + 151dc: 47b8 blx r7 + 151de: 2100 movs r1, #0 + 151e0: 2210 movs r2, #16 + 151e2: 4650 mov r0, sl + 151e4: 47b8 blx r7 + 151e6: ac26 add r4, sp, #152 ; 0x98 + 151e8: 2100 movs r1, #0 + 151ea: 2210 movs r2, #16 + 151ec: a822 add r0, sp, #136 ; 0x88 + 151ee: 47b8 blx r7 + 151f0: ad2a add r5, sp, #168 ; 0xa8 + 151f2: 2100 movs r1, #0 + 151f4: 2210 movs r2, #16 + 151f6: 4620 mov r0, r4 + 151f8: 47b8 blx r7 + 151fa: 2100 movs r1, #0 + 151fc: 2210 movs r2, #16 + 151fe: 4628 mov r0, r5 + 15200: 47b8 blx r7 + 15202: 9b07 ldr r3, [sp, #28] + 15204: 9807 ldr r0, [sp, #28] + 15206: 3304 adds r3, #4 + 15208: 930d str r3, [sp, #52] ; 0x34 + 1520a: 9b07 ldr r3, [sp, #28] + 1520c: 3001 adds r0, #1 + 1520e: 3305 adds r3, #5 + 15210: 930e str r3, [sp, #56] ; 0x38 + 15212: 9b07 ldr r3, [sp, #28] + 15214: ae2e add r6, sp, #184 ; 0xb8 + 15216: 3306 adds r3, #6 + 15218: 930f str r3, [sp, #60] ; 0x3c + 1521a: 9b07 ldr r3, [sp, #28] + 1521c: 9009 str r0, [sp, #36] ; 0x24 + 1521e: 3307 adds r3, #7 + 15220: 2100 movs r1, #0 + 15222: 2210 movs r2, #16 + 15224: 4630 mov r0, r6 + 15226: 9310 str r3, [sp, #64] ; 0x40 + 15228: 47b8 blx r7 + 1522a: f8dd c034 ldr.w ip, [sp, #52] ; 0x34 + 1522e: 9f09 ldr r7, [sp, #36] ; 0x24 + 15230: f818 200c ldrb.w r2, [r8, ip] + 15234: f8dd c03c ldr.w ip, [sp, #60] ; 0x3c + 15238: f818 1007 ldrb.w r1, [r8, r7] + 1523c: f818 e00c ldrb.w lr, [r8, ip] + 15240: 9f0e ldr r7, [sp, #56] ; 0x38 + 15242: f8dd c040 ldr.w ip, [sp, #64] ; 0x40 + 15246: f818 3007 ldrb.w r3, [r8, r7] + 1524a: f818 700c ldrb.w r7, [r8, ip] + 1524e: f8dd c01c ldr.w ip, [sp, #28] + 15252: f88d 1049 strb.w r1, [sp, #73] ; 0x49 + 15256: f818 c00c ldrb.w ip, [r8, ip] + 1525a: f88d 204a strb.w r2, [sp, #74] ; 0x4a + 1525e: f8cd c008 str.w ip, [sp, #8] + 15262: f8dd c01c ldr.w ip, [sp, #28] + 15266: f029 0220 bic.w r2, r9, #32 + 1526a: f02c 0102 bic.w r1, ip, #2 + 1526e: 3918 subs r1, #24 + 15270: f88d 304b strb.w r3, [sp, #75] ; 0x4b + 15274: f029 0380 bic.w r3, r9, #128 ; 0x80 + 15278: bf18 it ne + 1527a: 2101 movne r1, #1 + 1527c: 2b28 cmp r3, #40 ; 0x28 + 1527e: bf18 it ne + 15280: 2a18 cmpne r2, #24 + 15282: 9808 ldr r0, [sp, #32] + 15284: f88d 704d strb.w r7, [sp, #77] ; 0x4d + 15288: f1a0 0008 sub.w r0, r0, #8 + 1528c: 900b str r0, [sp, #44] ; 0x2c + 1528e: 9802 ldr r0, [sp, #8] + 15290: 9f0b ldr r7, [sp, #44] ; 0x2c + 15292: f88d 0048 strb.w r0, [sp, #72] ; 0x48 + 15296: 980b ldr r0, [sp, #44] ; 0x2c + 15298: ea4f 1717 mov.w r7, r7, lsr #4 + 1529c: 9702 str r7, [sp, #8] + 1529e: f000 000f and.w r0, r0, #15 + 152a2: bf08 it eq + 152a4: 2701 moveq r7, #1 + 152a6: f88d e04c strb.w lr, [sp, #76] ; 0x4c + 152aa: 900c str r0, [sp, #48] ; 0x30 + 152ac: 9104 str r1, [sp, #16] + 152ae: bf08 it eq + 152b0: 9705 streq r7, [sp, #20] + 152b2: d010 beq.n 152d6 + 152b4: f029 0310 bic.w r3, r9, #16 + 152b8: 2b88 cmp r3, #136 ; 0x88 + 152ba: bf1b ittet ne + 152bc: f1a9 09b8 subne.w r9, r9, #184 ; 0xb8 + 152c0: fab9 f989 clzne r9, r9 + 152c4: f04f 0c01 moveq.w ip, #1 + 152c8: ea4f 1959 movne.w r9, r9, lsr #5 + 152cc: bf14 ite ne + 152ce: f8cd 9014 strne.w r9, [sp, #20] + 152d2: f8cd c014 streq.w ip, [sp, #20] + 152d6: 9f07 ldr r7, [sp, #28] + 152d8: 9802 ldr r0, [sp, #8] + 152da: 3708 adds r7, #8 + 152dc: 970a str r7, [sp, #40] ; 0x28 + 152de: 2800 cmp r0, #0 + 152e0: f000 8166 beq.w 155b0 + 152e4: 9f0a ldr r7, [sp, #40] ; 0x28 + 152e6: a812 add r0, sp, #72 ; 0x48 + 152e8: 4447 add r7, r8 + 152ea: f04f 0900 mov.w r9, #0 + 152ee: 9006 str r0, [sp, #24] + 152f0: 9906 ldr r1, [sp, #24] + 152f2: f109 0901 add.w r9, r9, #1 + 152f6: 4643 mov r3, r8 + 152f8: 9100 str r1, [sp, #0] + 152fa: a822 add r0, sp, #136 ; 0x88 + 152fc: 9904 ldr r1, [sp, #16] + 152fe: 9a05 ldr r2, [sp, #20] + 15300: f8cd 9004 str.w r9, [sp, #4] + 15304: f7ff fd56 bl 14db4 + 15308: 9803 ldr r0, [sp, #12] + 1530a: a922 add r1, sp, #136 ; 0x88 + 1530c: 462a mov r2, r5 + 1530e: f7ff fbbd bl 14a8c + 15312: 2300 movs r3, #0 + 15314: 5cf9 ldrb r1, [r7, r3] + 15316: 5cea ldrb r2, [r5, r3] + 15318: 404a eors r2, r1 + 1531a: 54e2 strb r2, [r4, r3] + 1531c: 3301 adds r3, #1 + 1531e: 2b10 cmp r3, #16 + 15320: d1f8 bne.n 15314 + 15322: 2300 movs r3, #0 + 15324: 5ce2 ldrb r2, [r4, r3] + 15326: 54fa strb r2, [r7, r3] + 15328: 3301 adds r3, #1 + 1532a: 2b10 cmp r3, #16 + 1532c: d1fa bne.n 15324 + 1532e: 9a02 ldr r2, [sp, #8] + 15330: 3710 adds r7, #16 + 15332: 4591 cmp r9, r2 + 15334: d1dc bne.n 152f0 + 15336: 9f07 ldr r7, [sp, #28] + 15338: eb07 1902 add.w r9, r7, r2, lsl #4 + 1533c: f109 0908 add.w r9, r9, #8 + 15340: 980c ldr r0, [sp, #48] ; 0x30 + 15342: 2800 cmp r0, #0 + 15344: f040 80fe bne.w 15544 + 15348: f10d 07b7 add.w r7, sp, #183 ; 0xb7 + 1534c: 9711 str r7, [sp, #68] ; 0x44 + 1534e: f10d 07c7 add.w r7, sp, #199 ; 0xc7 + 15352: 9806 ldr r0, [sp, #24] + 15354: f04f 0900 mov.w r9, #0 + 15358: e88d 0201 stmia.w sp, {r0, r9} + 1535c: 4643 mov r3, r8 + 1535e: a822 add r0, sp, #136 ; 0x88 + 15360: 9904 ldr r1, [sp, #16] + 15362: 9a05 ldr r2, [sp, #20] + 15364: f7ff fd26 bl 14db4 + 15368: 9b11 ldr r3, [sp, #68] ; 0x44 + 1536a: f803 9f01 strb.w r9, [r3, #1]! + 1536e: 42bb cmp r3, r7 + 15370: d1fb bne.n 1536a + 15372: 9908 ldr r1, [sp, #32] + 15374: f8dd c01c ldr.w ip, [sp, #28] + 15378: 2300 movs r3, #0 + 1537a: 4461 add r1, ip + 1537c: 4441 add r1, r8 + 1537e: 5cca ldrb r2, [r1, r3] + 15380: 54f2 strb r2, [r6, r3] + 15382: 3301 adds r3, #1 + 15384: 2b08 cmp r3, #8 + 15386: d1fa bne.n 1537e + 15388: a922 add r1, sp, #136 ; 0x88 + 1538a: 9803 ldr r0, [sp, #12] + 1538c: 462a mov r2, r5 + 1538e: f7ff fb7d bl 14a8c + 15392: 2300 movs r3, #0 + 15394: 5cf1 ldrb r1, [r6, r3] + 15396: 5cea ldrb r2, [r5, r3] + 15398: 404a eors r2, r1 + 1539a: 54e2 strb r2, [r4, r3] + 1539c: 3301 adds r3, #1 + 1539e: 2b10 cmp r3, #16 + 153a0: d1f8 bne.n 15394 + 153a2: 2300 movs r3, #0 + 153a4: f10d 0950 add.w r9, sp, #80 ; 0x50 + 153a8: 5ce2 ldrb r2, [r4, r3] + 153aa: f809 2003 strb.w r2, [r9, r3] + 153ae: 3301 adds r3, #1 + 153b0: 2b08 cmp r3, #8 + 153b2: d1f9 bne.n 153a8 + 153b4: f8dd c024 ldr.w ip, [sp, #36] ; 0x24 + 153b8: 980b ldr r0, [sp, #44] ; 0x2c + 153ba: f818 200c ldrb.w r2, [r8, ip] + 153be: f8dd c034 ldr.w ip, [sp, #52] ; 0x34 + 153c2: 9906 ldr r1, [sp, #24] + 153c4: f818 300c ldrb.w r3, [r8, ip] + 153c8: f8dd c038 ldr.w ip, [sp, #56] ; 0x38 + 153cc: f88d 2049 strb.w r2, [sp, #73] ; 0x49 + 153d0: f818 c00c ldrb.w ip, [r8, ip] + 153d4: 9a04 ldr r2, [sp, #16] + 153d6: f8cd c020 str.w ip, [sp, #32] + 153da: f8dd c03c ldr.w ip, [sp, #60] ; 0x3c + 153de: f88d 304a strb.w r3, [sp, #74] ; 0x4a + 153e2: f818 c00c ldrb.w ip, [r8, ip] + 153e6: 4643 mov r3, r8 + 153e8: f8cd c024 str.w ip, [sp, #36] ; 0x24 + 153ec: f8dd c040 ldr.w ip, [sp, #64] ; 0x40 + 153f0: f818 c00c ldrb.w ip, [r8, ip] + 153f4: f8cd c034 str.w ip, [sp, #52] ; 0x34 + 153f8: f8dd c01c ldr.w ip, [sp, #28] + 153fc: f818 e00c ldrb.w lr, [r8, ip] + 15400: f8dd c020 ldr.w ip, [sp, #32] + 15404: 9000 str r0, [sp, #0] + 15406: f88d c04b strb.w ip, [sp, #75] ; 0x4b + 1540a: f8dd c024 ldr.w ip, [sp, #36] ; 0x24 + 1540e: 9101 str r1, [sp, #4] + 15410: f88d c04c strb.w ip, [sp, #76] ; 0x4c + 15414: f8dd c034 ldr.w ip, [sp, #52] ; 0x34 + 15418: a816 add r0, sp, #88 ; 0x58 + 1541a: 9905 ldr r1, [sp, #20] + 1541c: f88d c04d strb.w ip, [sp, #77] ; 0x4d + 15420: f88d e048 strb.w lr, [sp, #72] ; 0x48 + 15424: f7ff fc1e bl 14c64 + 15428: 4658 mov r0, fp + 1542a: 9907 ldr r1, [sp, #28] + 1542c: 4642 mov r2, r8 + 1542e: f7ff fc4d bl 14ccc + 15432: 9b05 ldr r3, [sp, #20] + 15434: 4650 mov r0, sl + 15436: 4641 mov r1, r8 + 15438: 9a04 ldr r2, [sp, #16] + 1543a: f7ff fc71 bl 14d20 + 1543e: 9803 ldr r0, [sp, #12] + 15440: a916 add r1, sp, #88 ; 0x58 + 15442: 462a mov r2, r5 + 15444: f7ff fb22 bl 14a8c + 15448: 2300 movs r3, #0 + 1544a: f81b 1003 ldrb.w r1, [fp, r3] + 1544e: 5cea ldrb r2, [r5, r3] + 15450: 404a eors r2, r1 + 15452: 54e2 strb r2, [r4, r3] + 15454: 3301 adds r3, #1 + 15456: 2b10 cmp r3, #16 + 15458: d1f7 bne.n 1544a + 1545a: 9803 ldr r0, [sp, #12] + 1545c: 4621 mov r1, r4 + 1545e: 462a mov r2, r5 + 15460: f7ff fb14 bl 14a8c + 15464: 2300 movs r3, #0 + 15466: f81a 1003 ldrb.w r1, [sl, r3] + 1546a: 5cea ldrb r2, [r5, r3] + 1546c: 404a eors r2, r1 + 1546e: 54e2 strb r2, [r4, r3] + 15470: 3301 adds r3, #1 + 15472: 2b10 cmp r3, #16 + 15474: d1f7 bne.n 15466 + 15476: 9803 ldr r0, [sp, #12] + 15478: 4621 mov r1, r4 + 1547a: 462a mov r2, r5 + 1547c: f7ff fb06 bl 14a8c + 15480: 9802 ldr r0, [sp, #8] + 15482: b358 cbz r0, 154dc + 15484: f8dd a028 ldr.w sl, [sp, #40] ; 0x28 + 15488: f04f 0b00 mov.w fp, #0 + 1548c: 44c2 add sl, r8 + 1548e: f8cd 8010 str.w r8, [sp, #16] + 15492: 46d8 mov r8, fp + 15494: 46d3 mov fp, sl + 15496: 4682 mov sl, r0 + 15498: 9702 str r7, [sp, #8] + 1549a: 9f03 ldr r7, [sp, #12] + 1549c: 2200 movs r2, #0 + 1549e: f81b 1002 ldrb.w r1, [fp, r2] + 154a2: 5cab ldrb r3, [r5, r2] + 154a4: 404b eors r3, r1 + 154a6: 54a3 strb r3, [r4, r2] + 154a8: 3201 adds r2, #1 + 154aa: 2a10 cmp r2, #16 + 154ac: d1f7 bne.n 1549e + 154ae: f108 0801 add.w r8, r8, #1 + 154b2: 4638 mov r0, r7 + 154b4: 4621 mov r1, r4 + 154b6: 462a mov r2, r5 + 154b8: f7ff fae8 bl 14a8c + 154bc: 45d0 cmp r8, sl + 154be: f10b 0b10 add.w fp, fp, #16 + 154c2: d1eb bne.n 1549c + 154c4: 46c3 mov fp, r8 + 154c6: f8dd c01c ldr.w ip, [sp, #28] + 154ca: f8dd 8010 ldr.w r8, [sp, #16] + 154ce: eb0c 1b0b add.w fp, ip, fp, lsl #4 + 154d2: f10b 0b08 add.w fp, fp, #8 + 154d6: 9f02 ldr r7, [sp, #8] + 154d8: f8cd b028 str.w fp, [sp, #40] ; 0x28 + 154dc: 980c ldr r0, [sp, #48] ; 0x30 + 154de: b1d8 cbz r0, 15518 + 154e0: 9b11 ldr r3, [sp, #68] ; 0x44 + 154e2: 2200 movs r2, #0 + 154e4: f803 2f01 strb.w r2, [r3, #1]! + 154e8: 42bb cmp r3, r7 + 154ea: d1fb bne.n 154e4 + 154ec: 990a ldr r1, [sp, #40] ; 0x28 + 154ee: 980c ldr r0, [sp, #48] ; 0x30 + 154f0: 4441 add r1, r8 + 154f2: 2300 movs r3, #0 + 154f4: 5cca ldrb r2, [r1, r3] + 154f6: 54f2 strb r2, [r6, r3] + 154f8: 3301 adds r3, #1 + 154fa: 4283 cmp r3, r0 + 154fc: d1fa bne.n 154f4 + 154fe: 2300 movs r3, #0 + 15500: 5cf1 ldrb r1, [r6, r3] + 15502: 5cea ldrb r2, [r5, r3] + 15504: 404a eors r2, r1 + 15506: 54e2 strb r2, [r4, r3] + 15508: 3301 adds r3, #1 + 1550a: 2b10 cmp r3, #16 + 1550c: d1f8 bne.n 15500 + 1550e: 9803 ldr r0, [sp, #12] + 15510: 4621 mov r1, r4 + 15512: 462a mov r2, r5 + 15514: f7ff faba bl 14a8c + 15518: 993d ldr r1, [sp, #244] ; 0xf4 + 1551a: 2300 movs r3, #0 + 1551c: 5cea ldrb r2, [r5, r3] + 1551e: 54ca strb r2, [r1, r3] + 15520: 3301 adds r3, #1 + 15522: 2b08 cmp r3, #8 + 15524: d1fa bne.n 1551c + 15526: 9c3d ldr r4, [sp, #244] ; 0xf4 + 15528: 2001 movs r0, #1 + 1552a: 2300 movs r3, #0 + 1552c: f819 1003 ldrb.w r1, [r9, r3] + 15530: 5ce2 ldrb r2, [r4, r3] + 15532: 3301 adds r3, #1 + 15534: 4291 cmp r1, r2 + 15536: bf18 it ne + 15538: 2000 movne r0, #0 + 1553a: 2b08 cmp r3, #8 + 1553c: d1f6 bne.n 1552c + 1553e: b033 add sp, #204 ; 0xcc + 15540: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 15544: 9b02 ldr r3, [sp, #8] + 15546: 9f06 ldr r7, [sp, #24] + 15548: 3301 adds r3, #1 + 1554a: 9700 str r7, [sp, #0] + 1554c: 9301 str r3, [sp, #4] + 1554e: 9a05 ldr r2, [sp, #20] + 15550: 4643 mov r3, r8 + 15552: f10d 0cb7 add.w ip, sp, #183 ; 0xb7 + 15556: a822 add r0, sp, #136 ; 0x88 + 15558: 9904 ldr r1, [sp, #16] + 1555a: f8cd c044 str.w ip, [sp, #68] ; 0x44 + 1555e: f7ff fc29 bl 14db4 + 15562: 9b11 ldr r3, [sp, #68] ; 0x44 + 15564: f10d 07c7 add.w r7, sp, #199 ; 0xc7 + 15568: 2200 movs r2, #0 + 1556a: f803 2f01 strb.w r2, [r3, #1]! + 1556e: 42bb cmp r3, r7 + 15570: d1fb bne.n 1556a + 15572: 990c ldr r1, [sp, #48] ; 0x30 + 15574: 44c1 add r9, r8 + 15576: 2300 movs r3, #0 + 15578: f819 2003 ldrb.w r2, [r9, r3] + 1557c: 54f2 strb r2, [r6, r3] + 1557e: 3301 adds r3, #1 + 15580: 428b cmp r3, r1 + 15582: d1f9 bne.n 15578 + 15584: 9803 ldr r0, [sp, #12] + 15586: a922 add r1, sp, #136 ; 0x88 + 15588: 462a mov r2, r5 + 1558a: f7ff fa7f bl 14a8c + 1558e: 2300 movs r3, #0 + 15590: 5cf1 ldrb r1, [r6, r3] + 15592: 5cea ldrb r2, [r5, r3] + 15594: 404a eors r2, r1 + 15596: 54e2 strb r2, [r4, r3] + 15598: 3301 adds r3, #1 + 1559a: 2b10 cmp r3, #16 + 1559c: d1f8 bne.n 15590 + 1559e: 990c ldr r1, [sp, #48] ; 0x30 + 155a0: 2300 movs r3, #0 + 155a2: 5ce2 ldrb r2, [r4, r3] + 155a4: f809 2003 strb.w r2, [r9, r3] + 155a8: 3301 adds r3, #1 + 155aa: 428b cmp r3, r1 + 155ac: d1f9 bne.n 155a2 + 155ae: e6d0 b.n 15352 + 155b0: 46b9 mov r9, r7 + 155b2: af12 add r7, sp, #72 ; 0x48 + 155b4: 9706 str r7, [sp, #24] + 155b6: e6c3 b.n 15340 + +000155b8 <_sha1_process_message_block>: + 155b8: 4603 mov r3, r0 + 155ba: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 155be: b0d5 sub sp, #340 ; 0x154 + 155c0: aa03 add r2, sp, #12 + 155c2: ae13 add r6, sp, #76 ; 0x4c + 155c4: 7fd9 ldrb r1, [r3, #31] + 155c6: 7f9c ldrb r4, [r3, #30] + 155c8: f893 5021 ldrb.w r5, [r3, #33] ; 0x21 + 155cc: 0409 lsls r1, r1, #16 + 155ce: ea41 6104 orr.w r1, r1, r4, lsl #24 + 155d2: f893 4020 ldrb.w r4, [r3, #32] + 155d6: 4329 orrs r1, r5 + 155d8: ea41 2104 orr.w r1, r1, r4, lsl #8 + 155dc: f842 1f04 str.w r1, [r2, #4]! + 155e0: 42b2 cmp r2, r6 + 155e2: f103 0304 add.w r3, r3, #4 + 155e6: d1ed bne.n 155c4 <_sha1_process_message_block+0xc> + 155e8: ab04 add r3, sp, #16 + 155ea: 2200 movs r2, #0 + 155ec: 6a19 ldr r1, [r3, #32] + 155ee: 6b5d ldr r5, [r3, #52] ; 0x34 + 155f0: ae04 add r6, sp, #16 + 155f2: 58b4 ldr r4, [r6, r2] + 155f4: 404d eors r5, r1 + 155f6: 6899 ldr r1, [r3, #8] + 155f8: 406c eors r4, r5 + 155fa: 4061 eors r1, r4 + 155fc: 3204 adds r2, #4 + 155fe: ea4f 71f1 mov.w r1, r1, ror #31 + 15602: f5b2 7f80 cmp.w r2, #256 ; 0x100 + 15606: 6419 str r1, [r3, #64] ; 0x40 + 15608: f103 0304 add.w r3, r3, #4 + 1560c: d1ee bne.n 155ec <_sha1_process_message_block+0x34> + 1560e: 6882 ldr r2, [r0, #8] + 15610: 68c3 ldr r3, [r0, #12] + 15612: 6904 ldr r4, [r0, #16] + 15614: 9201 str r2, [sp, #4] + 15616: e890 5000 ldmia.w r0, {ip, lr} + 1561a: 9302 str r3, [sp, #8] + 1561c: 9403 str r4, [sp, #12] + 1561e: a903 add r1, sp, #12 + 15620: 4666 mov r6, ip + 15622: 4672 mov r2, lr + 15624: 9d01 ldr r5, [sp, #4] + 15626: 4698 mov r8, r3 + 15628: 46a1 mov r9, r4 + 1562a: f10d 0a5c add.w sl, sp, #92 ; 0x5c + 1562e: e004 b.n 1563a <_sha1_process_message_block+0x82> + 15630: 46c1 mov r9, r8 + 15632: 4632 mov r2, r6 + 15634: 46a8 mov r8, r5 + 15636: 461e mov r6, r3 + 15638: 4625 mov r5, r4 + 1563a: f647 1399 movw r3, #31129 ; 0x7999 + 1563e: f6c5 2382 movt r3, #23170 ; 0x5a82 + 15642: f851 4f04 ldr.w r4, [r1, #4]! + 15646: ea28 0702 bic.w r7, r8, r2 + 1564a: 4423 add r3, r4 + 1564c: ea05 0402 and.w r4, r5, r2 + 15650: 433c orrs r4, r7 + 15652: eb03 63f6 add.w r3, r3, r6, ror #27 + 15656: 4423 add r3, r4 + 15658: 4551 cmp r1, sl + 1565a: 444b add r3, r9 + 1565c: ea4f 04b2 mov.w r4, r2, ror #2 + 15660: d1e6 bne.n 15630 <_sha1_process_message_block+0x78> + 15662: 4622 mov r2, r4 + 15664: f10d 095c add.w r9, sp, #92 ; 0x5c + 15668: 461c mov r4, r3 + 1566a: f10d 0aac add.w sl, sp, #172 ; 0xac + 1566e: 4613 mov r3, r2 + 15670: e004 b.n 1567c <_sha1_process_message_block+0xc4> + 15672: 46a8 mov r8, r5 + 15674: 4626 mov r6, r4 + 15676: 461d mov r5, r3 + 15678: 4614 mov r4, r2 + 1567a: 460b mov r3, r1 + 1567c: f64e 32a1 movw r2, #60321 ; 0xeba1 + 15680: f6c6 62d9 movt r2, #28377 ; 0x6ed9 + 15684: f859 7f04 ldr.w r7, [r9, #4]! + 15688: ea83 0106 eor.w r1, r3, r6 + 1568c: 443a add r2, r7 + 1568e: 4069 eors r1, r5 + 15690: eb02 62f4 add.w r2, r2, r4, ror #27 + 15694: 440a add r2, r1 + 15696: 45d1 cmp r9, sl + 15698: 4442 add r2, r8 + 1569a: ea4f 01b6 mov.w r1, r6, ror #2 + 1569e: d1e8 bne.n 15672 <_sha1_process_message_block+0xba> + 156a0: 460e mov r6, r1 + 156a2: f10d 09ac add.w r9, sp, #172 ; 0xac + 156a6: 4611 mov r1, r2 + 156a8: f10d 0afc add.w sl, sp, #252 ; 0xfc + 156ac: 4632 mov r2, r6 + 156ae: e004 b.n 156ba <_sha1_process_message_block+0x102> + 156b0: 461d mov r5, r3 + 156b2: 460c mov r4, r1 + 156b4: 4613 mov r3, r2 + 156b6: 4631 mov r1, r6 + 156b8: 4642 mov r2, r8 + 156ba: f64b 46dc movw r6, #48348 ; 0xbcdc + 156be: f6c8 761b movt r6, #36635 ; 0x8f1b + 156c2: f859 7f04 ldr.w r7, [r9, #4]! + 156c6: ea43 0802 orr.w r8, r3, r2 + 156ca: 443e add r6, r7 + 156cc: ea08 0804 and.w r8, r8, r4 + 156d0: ea03 0702 and.w r7, r3, r2 + 156d4: ea48 0707 orr.w r7, r8, r7 + 156d8: eb06 66f1 add.w r6, r6, r1, ror #27 + 156dc: 443e add r6, r7 + 156de: 45d1 cmp r9, sl + 156e0: ea4f 08b4 mov.w r8, r4, ror #2 + 156e4: 442e add r6, r5 + 156e6: d1e3 bne.n 156b0 <_sha1_process_message_block+0xf8> + 156e8: f50d 7ba6 add.w fp, sp, #332 ; 0x14c + 156ec: ad3f add r5, sp, #252 ; 0xfc + 156ee: 4681 mov r9, r0 + 156f0: e004 b.n 156fc <_sha1_process_message_block+0x144> + 156f2: 4613 mov r3, r2 + 156f4: 4631 mov r1, r6 + 156f6: 4642 mov r2, r8 + 156f8: 4626 mov r6, r4 + 156fa: 46d0 mov r8, sl + 156fc: f24c 14d6 movw r4, #49622 ; 0xc1d6 + 15700: f6cc 2462 movt r4, #51810 ; 0xca62 + 15704: f855 0f04 ldr.w r0, [r5, #4]! + 15708: ea88 0701 eor.w r7, r8, r1 + 1570c: 4404 add r4, r0 + 1570e: eb04 64f6 add.w r4, r4, r6, ror #27 + 15712: 4057 eors r7, r2 + 15714: 443c add r4, r7 + 15716: 455d cmp r5, fp + 15718: 441c add r4, r3 + 1571a: ea4f 0ab1 mov.w sl, r1, ror #2 + 1571e: d1e8 bne.n 156f2 <_sha1_process_message_block+0x13a> + 15720: 9b03 ldr r3, [sp, #12] + 15722: 9f01 ldr r7, [sp, #4] + 15724: 9902 ldr r1, [sp, #8] + 15726: 441a add r2, r3 + 15728: 4464 add r4, ip + 1572a: 4476 add r6, lr + 1572c: 4457 add r7, sl + 1572e: 4441 add r1, r8 + 15730: 2300 movs r3, #0 + 15732: e889 00d0 stmia.w r9, {r4, r6, r7} + 15736: f8c9 100c str.w r1, [r9, #12] + 1573a: f8c9 2010 str.w r2, [r9, #16] + 1573e: f8a9 301c strh.w r3, [r9, #28] + 15742: b055 add sp, #340 ; 0x154 + 15744: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +00015748 <_sha1_pad_message>: + 15748: 8b82 ldrh r2, [r0, #28] + 1574a: b5f8 push {r3, r4, r5, r6, r7, lr} + 1574c: 1c53 adds r3, r2, #1 + 1574e: b29b uxth r3, r3 + 15750: 2a37 cmp r2, #55 ; 0x37 + 15752: f04f 0180 mov.w r1, #128 ; 0x80 + 15756: 4402 add r2, r0 + 15758: 8383 strh r3, [r0, #28] + 1575a: 4604 mov r4, r0 + 1575c: 7791 strb r1, [r2, #30] + 1575e: d937 bls.n 157d0 <_sha1_pad_message+0x88> + 15760: 2b3f cmp r3, #63 ; 0x3f + 15762: bf98 it ls + 15764: 2000 movls r0, #0 + 15766: d806 bhi.n 15776 <_sha1_pad_message+0x2e> + 15768: 1c59 adds r1, r3, #1 + 1576a: 18e2 adds r2, r4, r3 + 1576c: b28b uxth r3, r1 + 1576e: 2b40 cmp r3, #64 ; 0x40 + 15770: 7790 strb r0, [r2, #30] + 15772: d1f9 bne.n 15768 <_sha1_pad_message+0x20> + 15774: 83a3 strh r3, [r4, #28] + 15776: 4620 mov r0, r4 + 15778: f7ff ff1e bl 155b8 <_sha1_process_message_block> + 1577c: 8ba3 ldrh r3, [r4, #28] + 1577e: 2b37 cmp r3, #55 ; 0x37 + 15780: bf98 it ls + 15782: 2000 movls r0, #0 + 15784: d806 bhi.n 15794 <_sha1_pad_message+0x4c> + 15786: 1c59 adds r1, r3, #1 + 15788: 18e2 adds r2, r4, r3 + 1578a: b28b uxth r3, r1 + 1578c: 2b38 cmp r3, #56 ; 0x38 + 1578e: 7790 strb r0, [r2, #30] + 15790: d1f9 bne.n 15786 <_sha1_pad_message+0x3e> + 15792: 83a3 strh r3, [r4, #28] + 15794: 69a2 ldr r2, [r4, #24] + 15796: 6963 ldr r3, [r4, #20] + 15798: ea4f 6e12 mov.w lr, r2, lsr #24 + 1579c: 0c18 lsrs r0, r3, #16 + 1579e: 0c17 lsrs r7, r2, #16 + 157a0: 0a16 lsrs r6, r2, #8 + 157a2: 0e1d lsrs r5, r3, #24 + 157a4: 0a19 lsrs r1, r3, #8 + 157a6: f884 005b strb.w r0, [r4, #91] ; 0x5b + 157aa: f884 2059 strb.w r2, [r4, #89] ; 0x59 + 157ae: f884 e056 strb.w lr, [r4, #86] ; 0x56 + 157b2: f884 7057 strb.w r7, [r4, #87] ; 0x57 + 157b6: f884 6058 strb.w r6, [r4, #88] ; 0x58 + 157ba: f884 305d strb.w r3, [r4, #93] ; 0x5d + 157be: f884 505a strb.w r5, [r4, #90] ; 0x5a + 157c2: f884 105c strb.w r1, [r4, #92] ; 0x5c + 157c6: 4620 mov r0, r4 + 157c8: e8bd 40f8 ldmia.w sp!, {r3, r4, r5, r6, r7, lr} + 157cc: f7ff bef4 b.w 155b8 <_sha1_process_message_block> + 157d0: 2b38 cmp r3, #56 ; 0x38 + 157d2: d0df beq.n 15794 <_sha1_pad_message+0x4c> + 157d4: 2000 movs r0, #0 + 157d6: 1c59 adds r1, r3, #1 + 157d8: 18e2 adds r2, r4, r3 + 157da: b28b uxth r3, r1 + 157dc: 2b38 cmp r3, #56 ; 0x38 + 157de: 7790 strb r0, [r2, #30] + 157e0: d1f9 bne.n 157d6 <_sha1_pad_message+0x8e> + 157e2: e7d6 b.n 15792 <_sha1_pad_message+0x4a> + +000157e4 : + 157e4: b310 cbz r0, 1582c + 157e6: b470 push {r4, r5, r6} + 157e8: f245 4176 movw r1, #21622 ; 0x5476 + 157ec: f242 3601 movw r6, #8961 ; 0x2301 + 157f0: f64a 3589 movw r5, #43913 ; 0xab89 + 157f4: f64d 44fe movw r4, #56574 ; 0xdcfe + 157f8: f24e 12f0 movw r2, #57840 ; 0xe1f0 + 157fc: f2c6 7645 movt r6, #26437 ; 0x6745 + 15800: f6ce 75cd movt r5, #61389 ; 0xefcd + 15804: f6c9 04ba movt r4, #39098 ; 0x98ba + 15808: f2c1 0132 movt r1, #4146 ; 0x1032 + 1580c: f2cc 32d2 movt r2, #50130 ; 0xc3d2 + 15810: 2300 movs r3, #0 + 15812: 6006 str r6, [r0, #0] + 15814: 6045 str r5, [r0, #4] + 15816: 6084 str r4, [r0, #8] + 15818: 60c1 str r1, [r0, #12] + 1581a: 6102 str r2, [r0, #16] + 1581c: 6143 str r3, [r0, #20] + 1581e: 6183 str r3, [r0, #24] + 15820: 8383 strh r3, [r0, #28] + 15822: 6603 str r3, [r0, #96] ; 0x60 + 15824: 6643 str r3, [r0, #100] ; 0x64 + 15826: bc70 pop {r4, r5, r6} + 15828: 4618 mov r0, r3 + 1582a: 4770 bx lr + 1582c: 2001 movs r0, #1 + 1582e: 4770 bx lr + +00015830 : + 15830: b17a cbz r2, 15852 + 15832: 2900 cmp r1, #0 + 15834: bf18 it ne + 15836: 2800 cmpne r0, #0 + 15838: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + 1583c: 4604 mov r4, r0 + 1583e: d005 beq.n 1584c + 15840: 6e03 ldr r3, [r0, #96] ; 0x60 + 15842: b143 cbz r3, 15856 + 15844: 2003 movs r0, #3 + 15846: 6660 str r0, [r4, #100] ; 0x64 + 15848: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 1584c: 2001 movs r0, #1 + 1584e: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 15852: 2000 movs r0, #0 + 15854: 4770 bx lr + 15856: 6e40 ldr r0, [r0, #100] ; 0x64 + 15858: 2800 cmp r0, #0 + 1585a: d1f8 bne.n 1584e + 1585c: 188f adds r7, r1, r2 + 1585e: 1c4d adds r5, r1, #1 + 15860: f04f 0801 mov.w r8, #1 + 15864: e004 b.n 15870 + 15866: 42bd cmp r5, r7 + 15868: d01a beq.n 158a0 + 1586a: 6e63 ldr r3, [r4, #100] ; 0x64 + 1586c: 3501 adds r5, #1 + 1586e: b9bb cbnz r3, 158a0 + 15870: 8ba0 ldrh r0, [r4, #28] + 15872: 6961 ldr r1, [r4, #20] + 15874: 1c43 adds r3, r0, #1 + 15876: b29b uxth r3, r3 + 15878: 83a3 strh r3, [r4, #28] + 1587a: f815 6c01 ldrb.w r6, [r5, #-1] + 1587e: 4420 add r0, r4 + 15880: 3108 adds r1, #8 + 15882: 7786 strb r6, [r0, #30] + 15884: 6161 str r1, [r4, #20] + 15886: b929 cbnz r1, 15894 + 15888: 69a2 ldr r2, [r4, #24] + 1588a: 3201 adds r2, #1 + 1588c: 61a2 str r2, [r4, #24] + 1588e: b90a cbnz r2, 15894 + 15890: f8c4 8064 str.w r8, [r4, #100] ; 0x64 + 15894: 2b40 cmp r3, #64 ; 0x40 + 15896: d1e6 bne.n 15866 + 15898: 4620 mov r0, r4 + 1589a: f7ff fe8d bl 155b8 <_sha1_process_message_block> + 1589e: e7e2 b.n 15866 + 158a0: 2000 movs r0, #0 + 158a2: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 158a6: bf00 nop + +000158a8 : + 158a8: 2900 cmp r1, #0 + 158aa: bf18 it ne + 158ac: 2800 cmpne r0, #0 + 158ae: b570 push {r4, r5, r6, lr} + 158b0: bf08 it eq + 158b2: 2601 moveq r6, #1 + 158b4: b082 sub sp, #8 + 158b6: d012 beq.n 158de + 158b8: 6e46 ldr r6, [r0, #100] ; 0x64 + 158ba: 4604 mov r4, r0 + 158bc: b97e cbnz r6, 158de + 158be: 6e03 ldr r3, [r0, #96] ; 0x60 + 158c0: b183 cbz r3, 158e4 + 158c2: 2300 movs r3, #0 + 158c4: 43da mvns r2, r3 + 158c6: 109d asrs r5, r3, #2 + 158c8: f854 5025 ldr.w r5, [r4, r5, lsl #2] + 158cc: f002 0203 and.w r2, r2, #3 + 158d0: 00d2 lsls r2, r2, #3 + 158d2: fa25 f202 lsr.w r2, r5, r2 + 158d6: 54ca strb r2, [r1, r3] + 158d8: 3301 adds r3, #1 + 158da: 2b14 cmp r3, #20 + 158dc: d1f2 bne.n 158c4 + 158de: 4630 mov r0, r6 + 158e0: b002 add sp, #8 + 158e2: bd70 pop {r4, r5, r6, pc} + 158e4: 9101 str r1, [sp, #4] + 158e6: f7ff ff2f bl 15748 <_sha1_pad_message> + 158ea: 4633 mov r3, r6 + 158ec: 4630 mov r0, r6 + 158ee: 9901 ldr r1, [sp, #4] + 158f0: 18e2 adds r2, r4, r3 + 158f2: 3301 adds r3, #1 + 158f4: 2b40 cmp r3, #64 ; 0x40 + 158f6: 7790 strb r0, [r2, #30] + 158f8: f04f 0200 mov.w r2, #0 + 158fc: d1f8 bne.n 158f0 + 158fe: 2301 movs r3, #1 + 15900: 6162 str r2, [r4, #20] + 15902: 61a2 str r2, [r4, #24] + 15904: 6623 str r3, [r4, #96] ; 0x60 + 15906: e7dc b.n 158c2 + +00015908 : + 15908: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 1590c: 2b40 cmp r3, #64 ; 0x40 + 1590e: b0c7 sub sp, #284 ; 0x11c + 15910: 4680 mov r8, r0 + 15912: 9103 str r1, [sp, #12] + 15914: bfd8 it le + 15916: af2c addle r7, sp, #176 ; 0xb0 + 15918: dc74 bgt.n 15a04 + 1591a: 2000 movs r0, #0 + 1591c: 4604 mov r4, r0 + 1591e: a90a add r1, sp, #40 ; 0x28 + 15920: ad1b add r5, sp, #108 ; 0x6c + 15922: 540c strb r4, [r1, r0] + 15924: 542c strb r4, [r5, r0] + 15926: 3001 adds r0, #1 + 15928: 2841 cmp r0, #65 ; 0x41 + 1592a: d1fa bne.n 15922 + 1592c: 2b00 cmp r3, #0 + 1592e: dd06 ble.n 1593e + 15930: 2000 movs r0, #0 + 15932: 5c14 ldrb r4, [r2, r0] + 15934: 540c strb r4, [r1, r0] + 15936: 542c strb r4, [r5, r0] + 15938: 3001 adds r0, #1 + 1593a: 4298 cmp r0, r3 + 1593c: d1f9 bne.n 15932 + 1593e: 2400 movs r4, #0 + 15940: 5d0a ldrb r2, [r1, r4] + 15942: 5d2b ldrb r3, [r5, r4] + 15944: f082 0236 eor.w r2, r2, #54 ; 0x36 + 15948: f083 035c eor.w r3, r3, #92 ; 0x5c + 1594c: 550a strb r2, [r1, r4] + 1594e: 552b strb r3, [r5, r4] + 15950: 3401 adds r4, #1 + 15952: 2c40 cmp r4, #64 ; 0x40 + 15954: d1f4 bne.n 15940 + 15956: f242 3c01 movw ip, #8961 ; 0x2301 + 1595a: f64a 3389 movw r3, #43913 ; 0xab89 + 1595e: f64d 4bfe movw fp, #56574 ; 0xdcfe + 15962: f245 4a76 movw sl, #21622 ; 0x5476 + 15966: f24e 19f0 movw r9, #57840 ; 0xe1f0 + 1596a: f2c6 7c45 movt ip, #26437 ; 0x6745 + 1596e: f6ce 73cd movt r3, #61389 ; 0xefcd + 15972: f6c9 0bba movt fp, #39098 ; 0x98ba + 15976: f2c1 0a32 movt sl, #4146 ; 0x1032 + 1597a: f2cc 39d2 movt r9, #50130 ; 0xc3d2 + 1597e: 2600 movs r6, #0 + 15980: 4622 mov r2, r4 + 15982: 4638 mov r0, r7 + 15984: f8cd c0b0 str.w ip, [sp, #176] ; 0xb0 + 15988: 932d str r3, [sp, #180] ; 0xb4 + 1598a: 9301 str r3, [sp, #4] + 1598c: f8cd c008 str.w ip, [sp, #8] + 15990: f8cd b0b8 str.w fp, [sp, #184] ; 0xb8 + 15994: f8cd a0bc str.w sl, [sp, #188] ; 0xbc + 15998: f8cd 90c0 str.w r9, [sp, #192] ; 0xc0 + 1599c: 9631 str r6, [sp, #196] ; 0xc4 + 1599e: 9632 str r6, [sp, #200] ; 0xc8 + 159a0: f8ad 60cc strh.w r6, [sp, #204] ; 0xcc + 159a4: 9644 str r6, [sp, #272] ; 0x110 + 159a6: 9645 str r6, [sp, #276] ; 0x114 + 159a8: f7ff ff42 bl 15830 + 159ac: 9a03 ldr r2, [sp, #12] + 159ae: 4641 mov r1, r8 + 159b0: 4638 mov r0, r7 + 159b2: f7ff ff3d bl 15830 + 159b6: 9950 ldr r1, [sp, #320] ; 0x140 + 159b8: 4638 mov r0, r7 + 159ba: f7ff ff75 bl 158a8 + 159be: f8dd c008 ldr.w ip, [sp, #8] + 159c2: 9b01 ldr r3, [sp, #4] + 159c4: 4629 mov r1, r5 + 159c6: 4622 mov r2, r4 + 159c8: 4638 mov r0, r7 + 159ca: f8cd c0b0 str.w ip, [sp, #176] ; 0xb0 + 159ce: 932d str r3, [sp, #180] ; 0xb4 + 159d0: f8cd b0b8 str.w fp, [sp, #184] ; 0xb8 + 159d4: f8cd a0bc str.w sl, [sp, #188] ; 0xbc + 159d8: f8cd 90c0 str.w r9, [sp, #192] ; 0xc0 + 159dc: 9631 str r6, [sp, #196] ; 0xc4 + 159de: 9632 str r6, [sp, #200] ; 0xc8 + 159e0: f8ad 60cc strh.w r6, [sp, #204] ; 0xcc + 159e4: 9644 str r6, [sp, #272] ; 0x110 + 159e6: 9645 str r6, [sp, #276] ; 0x114 + 159e8: f7ff ff22 bl 15830 + 159ec: 9950 ldr r1, [sp, #320] ; 0x140 + 159ee: 2214 movs r2, #20 + 159f0: 4638 mov r0, r7 + 159f2: f7ff ff1d bl 15830 + 159f6: 4638 mov r0, r7 + 159f8: 9950 ldr r1, [sp, #320] ; 0x140 + 159fa: f7ff ff55 bl 158a8 + 159fe: b047 add sp, #284 ; 0x11c + 15a00: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 15a04: f242 3c01 movw ip, #8961 ; 0x2301 + 15a08: f64a 3e89 movw lr, #43913 ; 0xab89 + 15a0c: f64d 46fe movw r6, #56574 ; 0xdcfe + 15a10: f245 4576 movw r5, #21622 ; 0x5476 + 15a14: f24e 14f0 movw r4, #57840 ; 0xe1f0 + 15a18: f2c6 7c45 movt ip, #26437 ; 0x6745 + 15a1c: f6ce 7ecd movt lr, #61389 ; 0xefcd + 15a20: f6c9 06ba movt r6, #39098 ; 0x98ba + 15a24: f2c1 0532 movt r5, #4146 ; 0x1032 + 15a28: f2cc 34d2 movt r4, #50130 ; 0xc3d2 + 15a2c: af2c add r7, sp, #176 ; 0xb0 + 15a2e: 4611 mov r1, r2 + 15a30: 4638 mov r0, r7 + 15a32: 461a mov r2, r3 + 15a34: 2300 movs r3, #0 + 15a36: 9331 str r3, [sp, #196] ; 0xc4 + 15a38: 9332 str r3, [sp, #200] ; 0xc8 + 15a3a: f8ad 30cc strh.w r3, [sp, #204] ; 0xcc + 15a3e: 9344 str r3, [sp, #272] ; 0x110 + 15a40: 9345 str r3, [sp, #276] ; 0x114 + 15a42: f8cd c0b0 str.w ip, [sp, #176] ; 0xb0 + 15a46: f8cd e0b4 str.w lr, [sp, #180] ; 0xb4 + 15a4a: 962e str r6, [sp, #184] ; 0xb8 + 15a4c: 952f str r5, [sp, #188] ; 0xbc + 15a4e: 9430 str r4, [sp, #192] ; 0xc0 + 15a50: f7ff feee bl 15830 + 15a54: 4638 mov r0, r7 + 15a56: a905 add r1, sp, #20 + 15a58: f7ff ff26 bl 158a8 + 15a5c: aa05 add r2, sp, #20 + 15a5e: 2314 movs r3, #20 + 15a60: e75b b.n 1591a + 15a62: bf00 nop + +00015a64 : + 15a64: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} + 15a68: b0b1 sub sp, #196 ; 0xc4 + 15a6a: 460c mov r4, r1 + 15a6c: 4615 mov r5, r2 + 15a6e: 4601 mov r1, r0 + 15a70: 2210 movs r2, #16 + 15a72: a804 add r0, sp, #16 + 15a74: 4698 mov r8, r3 + 15a76: f000 fb05 bl 16084 + 15a7a: 4607 mov r7, r0 + 15a7c: b368 cbz r0, 15ada + 15a7e: f24f 4665 movw r6, #62565 ; 0xf465 + 15a82: 4621 mov r1, r4 + 15a84: f2c0 0600 movt r6, #0 + 15a88: 4668 mov r0, sp + 15a8a: 2210 movs r2, #16 + 15a8c: 47b0 blx r6 + 15a8e: ea5f 1818 movs.w r8, r8, lsr #4 + 15a92: bf18 it ne + 15a94: f04f 0900 movne.w r9, #0 + 15a98: d018 beq.n 15acc + 15a9a: 2400 movs r4, #0 + 15a9c: f81d 3004 ldrb.w r3, [sp, r4] + 15aa0: 5d29 ldrb r1, [r5, r4] + 15aa2: 404b eors r3, r1 + 15aa4: f80d 3004 strb.w r3, [sp, r4] + 15aa8: 3401 adds r4, #1 + 15aaa: 2c10 cmp r4, #16 + 15aac: d1f6 bne.n 15a9c + 15aae: 4638 mov r0, r7 + 15ab0: 4669 mov r1, sp + 15ab2: 466a mov r2, sp + 15ab4: f000 faf2 bl 1609c + 15ab8: f109 0901 add.w r9, r9, #1 + 15abc: 4628 mov r0, r5 + 15abe: 4669 mov r1, sp + 15ac0: 4622 mov r2, r4 + 15ac2: 47b0 blx r6 + 15ac4: 45c8 cmp r8, r9 + 15ac6: f105 0510 add.w r5, r5, #16 + 15aca: d1e6 bne.n 15a9a + 15acc: 4638 mov r0, r7 + 15ace: f000 fcbf bl 16450 + 15ad2: 2000 movs r0, #0 + 15ad4: b031 add sp, #196 ; 0xc4 + 15ad6: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + 15ada: f04f 30ff mov.w r0, #4294967295 + 15ade: e7f9 b.n 15ad4 + +00015ae0 : + 15ae0: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + 15ae4: b0b4 sub sp, #208 ; 0xd0 + 15ae6: 460d mov r5, r1 + 15ae8: 4614 mov r4, r2 + 15aea: 4601 mov r1, r0 + 15aec: 2210 movs r2, #16 + 15aee: a808 add r0, sp, #32 + 15af0: 4698 mov r8, r3 + 15af2: f000 f8a1 bl 15c38 + 15af6: 4607 mov r7, r0 + 15af8: b368 cbz r0, 15b56 + 15afa: f24f 4665 movw r6, #62565 ; 0xf465 + 15afe: 4629 mov r1, r5 + 15b00: f2c0 0600 movt r6, #0 + 15b04: 4668 mov r0, sp + 15b06: 2210 movs r2, #16 + 15b08: 47b0 blx r6 + 15b0a: ea5f 1818 movs.w r8, r8, lsr #4 + 15b0e: bf18 it ne + 15b10: 2500 movne r5, #0 + 15b12: d019 beq.n 15b48 + 15b14: 4621 mov r1, r4 + 15b16: 2210 movs r2, #16 + 15b18: a804 add r0, sp, #16 + 15b1a: 47b0 blx r6 + 15b1c: 4622 mov r2, r4 + 15b1e: 4638 mov r0, r7 + 15b20: 4621 mov r1, r4 + 15b22: f000 f8f7 bl 15d14 + 15b26: 2200 movs r2, #0 + 15b28: 5ca3 ldrb r3, [r4, r2] + 15b2a: f81d 1002 ldrb.w r1, [sp, r2] + 15b2e: 404b eors r3, r1 + 15b30: 54a3 strb r3, [r4, r2] + 15b32: 3201 adds r2, #1 + 15b34: 2a10 cmp r2, #16 + 15b36: d1f7 bne.n 15b28 + 15b38: 3501 adds r5, #1 + 15b3a: 4668 mov r0, sp + 15b3c: a904 add r1, sp, #16 + 15b3e: 47b0 blx r6 + 15b40: 45a8 cmp r8, r5 + 15b42: f104 0410 add.w r4, r4, #16 + 15b46: d1e5 bne.n 15b14 + 15b48: 4638 mov r0, r7 + 15b4a: f000 fa91 bl 16070 + 15b4e: 2000 movs r0, #0 + 15b50: b034 add sp, #208 ; 0xd0 + 15b52: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 15b56: f04f 30ff mov.w r0, #4294967295 + 15b5a: e7f9 b.n 15b50 + +00015b5c : + 15b5c: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} + 15b60: f645 1488 movw r4, #22920 ; 0x5988 + 15b64: 4607 mov r7, r0 + 15b66: f2c0 0403 movt r4, #3 + 15b6a: 784e ldrb r6, [r1, #1] + 15b6c: 780b ldrb r3, [r1, #0] + 15b6e: 4602 mov r2, r0 + 15b70: 0436 lsls r6, r6, #16 + 15b72: 78c8 ldrb r0, [r1, #3] + 15b74: ea46 6603 orr.w r6, r6, r3, lsl #24 + 15b78: 788b ldrb r3, [r1, #2] + 15b7a: 4046 eors r6, r0 + 15b7c: ea46 2603 orr.w r6, r6, r3, lsl #8 + 15b80: 603e str r6, [r7, #0] + 15b82: 794d ldrb r5, [r1, #5] + 15b84: 790b ldrb r3, [r1, #4] + 15b86: 79c8 ldrb r0, [r1, #7] + 15b88: 042d lsls r5, r5, #16 + 15b8a: ea45 6503 orr.w r5, r5, r3, lsl #24 + 15b8e: 798b ldrb r3, [r1, #6] + 15b90: 4045 eors r5, r0 + 15b92: ea45 2503 orr.w r5, r5, r3, lsl #8 + 15b96: 607d str r5, [r7, #4] + 15b98: 7a48 ldrb r0, [r1, #9] + 15b9a: 7a0b ldrb r3, [r1, #8] + 15b9c: f891 e00b ldrb.w lr, [r1, #11] + 15ba0: 0400 lsls r0, r0, #16 + 15ba2: ea40 6003 orr.w r0, r0, r3, lsl #24 + 15ba6: 7a8b ldrb r3, [r1, #10] + 15ba8: ea80 000e eor.w r0, r0, lr + 15bac: ea40 2003 orr.w r0, r0, r3, lsl #8 + 15bb0: 60b8 str r0, [r7, #8] + 15bb2: 7b4b ldrb r3, [r1, #13] + 15bb4: f891 c00c ldrb.w ip, [r1, #12] + 15bb8: f891 e00f ldrb.w lr, [r1, #15] + 15bbc: 041b lsls r3, r3, #16 + 15bbe: 7b89 ldrb r1, [r1, #14] + 15bc0: ea43 630c orr.w r3, r3, ip, lsl #24 + 15bc4: ea83 030e eor.w r3, r3, lr + 15bc8: ea43 2301 orr.w r3, r3, r1, lsl #8 + 15bcc: 60fb str r3, [r7, #12] + 15bce: f504 6c80 add.w ip, r4, #1024 ; 0x400 + 15bd2: 2100 movs r1, #0 + 15bd4: e000 b.n 15bd8 + 15bd6: 3210 adds r2, #16 + 15bd8: f3c3 2e07 ubfx lr, r3, #8, #8 + 15bdc: 0e1f lsrs r7, r3, #24 + 15bde: f854 902e ldr.w r9, [r4, lr, lsl #2] + 15be2: f3c3 4807 ubfx r8, r3, #16, #8 + 15be6: fa5f fe83 uxtb.w lr, r3 + 15bea: f854 7027 ldr.w r7, [r4, r7, lsl #2] + 15bee: f854 e02e ldr.w lr, [r4, lr, lsl #2] + 15bf2: f854 8028 ldr.w r8, [r4, r8, lsl #2] + 15bf6: f409 097f and.w r9, r9, #16711680 ; 0xff0000 + 15bfa: f3c7 2707 ubfx r7, r7, #8, #8 + 15bfe: f40e 4e7f and.w lr, lr, #65280 ; 0xff00 + 15c02: ea89 0707 eor.w r7, r9, r7 + 15c06: ea4f 2808 mov.w r8, r8, lsl #8 + 15c0a: ea87 070e eor.w r7, r7, lr + 15c0e: f008 487f and.w r8, r8, #4278190080 ; 0xff000000 + 15c12: f81c e001 ldrb.w lr, [ip, r1] + 15c16: ea87 0708 eor.w r7, r7, r8 + 15c1a: ea87 670e eor.w r7, r7, lr, lsl #24 + 15c1e: 407e eors r6, r7 + 15c20: 4075 eors r5, r6 + 15c22: 4068 eors r0, r5 + 15c24: 3101 adds r1, #1 + 15c26: 4043 eors r3, r0 + 15c28: 290a cmp r1, #10 + 15c2a: 61d3 str r3, [r2, #28] + 15c2c: 6190 str r0, [r2, #24] + 15c2e: 6155 str r5, [r2, #20] + 15c30: 6116 str r6, [r2, #16] + 15c32: d1d0 bne.n 15bd6 + 15c34: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + +00015c38 : + 15c38: 2a10 cmp r2, #16 + 15c3a: d169 bne.n 15d10 + 15c3c: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} + 15c40: 4607 mov r7, r0 + 15c42: 2800 cmp r0, #0 + 15c44: d061 beq.n 15d0a + 15c46: f7ff ff89 bl 15b5c + 15c4a: 463a mov r2, r7 + 15c4c: 463b mov r3, r7 + 15c4e: 1d39 adds r1, r7, #4 + 15c50: f107 0550 add.w r5, r7, #80 ; 0x50 + 15c54: f8d3 00a0 ldr.w r0, [r3, #160] ; 0xa0 + 15c58: f851 4c04 ldr.w r4, [r1, #-4] + 15c5c: f841 0c04 str.w r0, [r1, #-4] + 15c60: f8d3 00a4 ldr.w r0, [r3, #164] ; 0xa4 + 15c64: f8c3 40a0 str.w r4, [r3, #160] ; 0xa0 + 15c68: 6854 ldr r4, [r2, #4] + 15c6a: 6050 str r0, [r2, #4] + 15c6c: f8d3 00a8 ldr.w r0, [r3, #168] ; 0xa8 + 15c70: f8c3 40a4 str.w r4, [r3, #164] ; 0xa4 + 15c74: 6894 ldr r4, [r2, #8] + 15c76: 6090 str r0, [r2, #8] + 15c78: f8d3 00ac ldr.w r0, [r3, #172] ; 0xac + 15c7c: f8c3 40a8 str.w r4, [r3, #168] ; 0xa8 + 15c80: 68d4 ldr r4, [r2, #12] + 15c82: 60d0 str r0, [r2, #12] + 15c84: 3210 adds r2, #16 + 15c86: 42aa cmp r2, r5 + 15c88: f8c3 40ac str.w r4, [r3, #172] ; 0xac + 15c8c: f101 0110 add.w r1, r1, #16 + 15c90: f1a3 0310 sub.w r3, r3, #16 + 15c94: d1de bne.n 15c54 + 15c96: f645 6494 movw r4, #24212 ; 0x5e94 + 15c9a: f645 1188 movw r1, #22920 ; 0x5988 + 15c9e: f2c0 0403 movt r4, #3 + 15ca2: f2c0 0103 movt r1, #3 + 15ca6: f107 0c90 add.w ip, r7, #144 ; 0x90 + 15caa: f107 0510 add.w r5, r7, #16 + 15cae: 46ae mov lr, r5 + 15cb0: 462a mov r2, r5 + 15cb2: 3510 adds r5, #16 + 15cb4: 6813 ldr r3, [r2, #0] + 15cb6: b2de uxtb r6, r3 + 15cb8: 0e18 lsrs r0, r3, #24 + 15cba: f851 8026 ldr.w r8, [r1, r6, lsl #2] + 15cbe: f851 6020 ldr.w r6, [r1, r0, lsl #2] + 15cc2: f3c3 4007 ubfx r0, r3, #16, #8 + 15cc6: f851 0020 ldr.w r0, [r1, r0, lsl #2] + 15cca: f3c3 2307 ubfx r3, r3, #8, #8 + 15cce: f3c6 2907 ubfx r9, r6, #8, #8 + 15cd2: f3c8 2807 ubfx r8, r8, #8, #8 + 15cd6: f851 6023 ldr.w r6, [r1, r3, lsl #2] + 15cda: f854 8028 ldr.w r8, [r4, r8, lsl #2] + 15cde: f854 3029 ldr.w r3, [r4, r9, lsl #2] + 15ce2: f3c0 2007 ubfx r0, r0, #8, #8 + 15ce6: f854 0020 ldr.w r0, [r4, r0, lsl #2] + 15cea: f3c6 2607 ubfx r6, r6, #8, #8 + 15cee: ea83 6338 eor.w r3, r3, r8, ror #24 + 15cf2: f854 6026 ldr.w r6, [r4, r6, lsl #2] + 15cf6: ea83 2330 eor.w r3, r3, r0, ror #8 + 15cfa: ea83 4336 eor.w r3, r3, r6, ror #16 + 15cfe: f842 3b04 str.w r3, [r2], #4 + 15d02: 4295 cmp r5, r2 + 15d04: d1d6 bne.n 15cb4 + 15d06: 45e6 cmp lr, ip + 15d08: d1d1 bne.n 15cae + 15d0a: 4638 mov r0, r7 + 15d0c: e8bd 83f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} + 15d10: 2000 movs r0, #0 + 15d12: 4770 bx lr + +00015d14 : + 15d14: f645 6394 movw r3, #24212 ; 0x5e94 + 15d18: f2c0 0303 movt r3, #3 + 15d1c: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 15d20: 6846 ldr r6, [r0, #4] + 15d22: f891 c007 ldrb.w ip, [r1, #7] + 15d26: f891 e00b ldrb.w lr, [r1, #11] + 15d2a: 6885 ldr r5, [r0, #8] + 15d2c: f891 800f ldrb.w r8, [r1, #15] + 15d30: 68c4 ldr r4, [r0, #12] + 15d32: f891 9003 ldrb.w r9, [r1, #3] + 15d36: ea8c 0606 eor.w r6, ip, r6 + 15d3a: ea8e 0505 eor.w r5, lr, r5 + 15d3e: f891 c004 ldrb.w ip, [r1, #4] + 15d42: f891 e008 ldrb.w lr, [r1, #8] + 15d46: 6807 ldr r7, [r0, #0] + 15d48: ea88 0404 eor.w r4, r8, r4 + 15d4c: f891 800c ldrb.w r8, [r1, #12] + 15d50: ea85 650e eor.w r5, r5, lr, lsl #24 + 15d54: ea89 0707 eor.w r7, r9, r7 + 15d58: ea86 660c eor.w r6, r6, ip, lsl #24 + 15d5c: f891 9000 ldrb.w r9, [r1] + 15d60: f891 c005 ldrb.w ip, [r1, #5] + 15d64: f891 e009 ldrb.w lr, [r1, #9] + 15d68: ea84 6408 eor.w r4, r4, r8, lsl #24 + 15d6c: f891 800d ldrb.w r8, [r1, #13] + 15d70: ea87 6709 eor.w r7, r7, r9, lsl #24 + 15d74: f891 a002 ldrb.w sl, [r1, #2] + 15d78: f891 9001 ldrb.w r9, [r1, #1] + 15d7c: ea86 460c eor.w r6, r6, ip, lsl #16 + 15d80: ea85 4e0e eor.w lr, r5, lr, lsl #16 + 15d84: f891 c006 ldrb.w ip, [r1, #6] + 15d88: 7a8d ldrb r5, [r1, #10] + 15d8a: 7b89 ldrb r1, [r1, #14] + 15d8c: ea84 4408 eor.w r4, r4, r8, lsl #16 + 15d90: ea87 4909 eor.w r9, r7, r9, lsl #16 + 15d94: ea84 2701 eor.w r7, r4, r1, lsl #8 + 15d98: 4604 mov r4, r0 + 15d9a: b085 sub sp, #20 + 15d9c: 9201 str r2, [sp, #4] + 15d9e: 461a mov r2, r3 + 15da0: 34a0 adds r4, #160 ; 0xa0 + 15da2: 9002 str r0, [sp, #8] + 15da4: ea89 290a eor.w r9, r9, sl, lsl #8 + 15da8: ea86 2c0c eor.w ip, r6, ip, lsl #8 + 15dac: ea8e 2e05 eor.w lr, lr, r5, lsl #8 + 15db0: 9403 str r4, [sp, #12] + 15db2: ea4f 6119 mov.w r1, r9, lsr #24 + 15db6: 6905 ldr r5, [r0, #16] + 15db8: f853 1021 ldr.w r1, [r3, r1, lsl #2] + 15dbc: ea4f 641c mov.w r4, ip, lsr #24 + 15dc0: 404d eors r5, r1 + 15dc2: fa5f f18c uxtb.w r1, ip + 15dc6: f853 1021 ldr.w r1, [r3, r1, lsl #2] + 15dca: f853 4024 ldr.w r4, [r3, r4, lsl #2] + 15dce: ea85 6531 eor.w r5, r5, r1, ror #24 + 15dd2: 6941 ldr r1, [r0, #20] + 15dd4: 0e3e lsrs r6, r7, #24 + 15dd6: 4061 eors r1, r4 + 15dd8: f853 6026 ldr.w r6, [r3, r6, lsl #2] + 15ddc: fa5f f48e uxtb.w r4, lr + 15de0: ea4f 681e mov.w r8, lr, lsr #24 + 15de4: f853 4024 ldr.w r4, [r3, r4, lsl #2] + 15de8: f853 a028 ldr.w sl, [r3, r8, lsl #2] + 15dec: 9600 str r6, [sp, #0] + 15dee: 6986 ldr r6, [r0, #24] + 15df0: ea81 6b34 eor.w fp, r1, r4, ror #24 + 15df4: b2f9 uxtb r1, r7 + 15df6: ea8a 0406 eor.w r4, sl, r6 + 15dfa: f853 a021 ldr.w sl, [r3, r1, lsl #2] + 15dfe: f3c7 4807 ubfx r8, r7, #16, #8 + 15e02: f3c7 2707 ubfx r7, r7, #8, #8 + 15e06: f853 1027 ldr.w r1, [r3, r7, lsl #2] + 15e0a: ea84 6a3a eor.w sl, r4, sl, ror #24 + 15e0e: 69c7 ldr r7, [r0, #28] + 15e10: fa5f f489 uxtb.w r4, r9 + 15e14: 9e00 ldr r6, [sp, #0] + 15e16: f853 4024 ldr.w r4, [r3, r4, lsl #2] + 15e1a: 407e eors r6, r7 + 15e1c: ea86 6434 eor.w r4, r6, r4, ror #24 + 15e20: f3c9 4607 ubfx r6, r9, #16, #8 + 15e24: f853 7026 ldr.w r7, [r3, r6, lsl #2] + 15e28: f853 8028 ldr.w r8, [r3, r8, lsl #2] + 15e2c: f3c9 2907 ubfx r9, r9, #8, #8 + 15e30: ea85 2538 eor.w r5, r5, r8, ror #8 + 15e34: ea8b 2b37 eor.w fp, fp, r7, ror #8 + 15e38: f3ce 2807 ubfx r8, lr, #8, #8 + 15e3c: f3cc 4707 ubfx r7, ip, #16, #8 + 15e40: f3ce 4e07 ubfx lr, lr, #16, #8 + 15e44: f853 6029 ldr.w r6, [r3, r9, lsl #2] + 15e48: f853 e02e ldr.w lr, [r3, lr, lsl #2] + 15e4c: f853 9027 ldr.w r9, [r3, r7, lsl #2] + 15e50: f3cc 2c07 ubfx ip, ip, #8, #8 + 15e54: f853 702c ldr.w r7, [r3, ip, lsl #2] + 15e58: ea84 2e3e eor.w lr, r4, lr, ror #8 + 15e5c: ea8a 2a39 eor.w sl, sl, r9, ror #8 + 15e60: ea8a 4436 eor.w r4, sl, r6, ror #16 + 15e64: ea8e 4637 eor.w r6, lr, r7, ror #16 + 15e68: 9f03 ldr r7, [sp, #12] + 15e6a: f853 8028 ldr.w r8, [r3, r8, lsl #2] + 15e6e: 3020 adds r0, #32 + 15e70: 42b8 cmp r0, r7 + 15e72: ea85 4538 eor.w r5, r5, r8, ror #16 + 15e76: ea8b 4131 eor.w r1, fp, r1, ror #16 + 15e7a: d064 beq.n 15f46 + 15e7c: ea4f 6b16 mov.w fp, r6, lsr #24 + 15e80: f852 702b ldr.w r7, [r2, fp, lsl #2] + 15e84: ea4f 6815 mov.w r8, r5, lsr #24 + 15e88: ea4f 6c11 mov.w ip, r1, lsr #24 + 15e8c: f852 9028 ldr.w r9, [r2, r8, lsl #2] + 15e90: f852 a02c ldr.w sl, [r2, ip, lsl #2] + 15e94: 9700 str r7, [sp, #0] + 15e96: fa5f fc81 uxtb.w ip, r1 + 15e9a: 6807 ldr r7, [r0, #0] + 15e9c: f852 c02c ldr.w ip, [r2, ip, lsl #2] + 15ea0: ea89 0907 eor.w r9, r9, r7 + 15ea4: ea89 693c eor.w r9, r9, ip, ror #24 + 15ea8: f3c6 4c07 ubfx ip, r6, #16, #8 + 15eac: f852 802c ldr.w r8, [r2, ip, lsl #2] + 15eb0: 6847 ldr r7, [r0, #4] + 15eb2: fa5f fc84 uxtb.w ip, r4 + 15eb6: f852 c02c ldr.w ip, [r2, ip, lsl #2] + 15eba: ea4f 6e14 mov.w lr, r4, lsr #24 + 15ebe: ea8a 0a07 eor.w sl, sl, r7 + 15ec2: ea8a 6a3c eor.w sl, sl, ip, ror #24 + 15ec6: 6887 ldr r7, [r0, #8] + 15ec8: fa5f fc86 uxtb.w ip, r6 + 15ecc: f852 e02e ldr.w lr, [r2, lr, lsl #2] + 15ed0: f852 c02c ldr.w ip, [r2, ip, lsl #2] + 15ed4: f3c6 2607 ubfx r6, r6, #8, #8 + 15ed8: ea8e 0e07 eor.w lr, lr, r7 + 15edc: f852 b026 ldr.w fp, [r2, r6, lsl #2] + 15ee0: b2ee uxtb r6, r5 + 15ee2: ea8e 6e3c eor.w lr, lr, ip, ror #24 + 15ee6: 9f00 ldr r7, [sp, #0] + 15ee8: f852 c026 ldr.w ip, [r2, r6, lsl #2] + 15eec: 68c6 ldr r6, [r0, #12] + 15eee: ea89 2938 eor.w r9, r9, r8, ror #8 + 15ef2: 4077 eors r7, r6 + 15ef4: ea87 673c eor.w r7, r7, ip, ror #24 + 15ef8: f3c5 4c07 ubfx ip, r5, #16, #8 + 15efc: f852 c02c ldr.w ip, [r2, ip, lsl #2] + 15f00: f3c4 2807 ubfx r8, r4, #8, #8 + 15f04: ea8a 2a3c eor.w sl, sl, ip, ror #8 + 15f08: f3c4 4407 ubfx r4, r4, #16, #8 + 15f0c: f3c1 4c07 ubfx ip, r1, #16, #8 + 15f10: f852 c02c ldr.w ip, [r2, ip, lsl #2] + 15f14: f852 4024 ldr.w r4, [r2, r4, lsl #2] + 15f18: f3c5 2507 ubfx r5, r5, #8, #8 + 15f1c: f3c1 2107 ubfx r1, r1, #8, #8 + 15f20: f852 6028 ldr.w r6, [r2, r8, lsl #2] + 15f24: f852 5025 ldr.w r5, [r2, r5, lsl #2] + 15f28: f852 1021 ldr.w r1, [r2, r1, lsl #2] + 15f2c: ea8e 2e3c eor.w lr, lr, ip, ror #8 + 15f30: ea87 2734 eor.w r7, r7, r4, ror #8 + 15f34: ea89 4936 eor.w r9, r9, r6, ror #16 + 15f38: ea8a 4c3b eor.w ip, sl, fp, ror #16 + 15f3c: ea8e 4e35 eor.w lr, lr, r5, ror #16 + 15f40: ea87 4731 eor.w r7, r7, r1, ror #16 + 15f44: e735 b.n 15db2 + 15f46: f645 5394 movw r3, #23956 ; 0x5d94 + 15f4a: f2c0 0303 movt r3, #3 + 15f4e: 0e28 lsrs r0, r5, #24 + 15f50: b2ca uxtb r2, r1 + 15f52: f813 e000 ldrb.w lr, [r3, r0] + 15f56: 5c9a ldrb r2, [r3, r2] + 15f58: f3c6 4007 ubfx r0, r6, #16, #8 + 15f5c: 5c18 ldrb r0, [r3, r0] + 15f5e: f8dd 8008 ldr.w r8, [sp, #8] + 15f62: f3c4 2707 ubfx r7, r4, #8, #8 + 15f66: 5ddf ldrb r7, [r3, r7] + 15f68: ea42 620e orr.w r2, r2, lr, lsl #24 + 15f6c: ea42 4200 orr.w r2, r2, r0, lsl #16 + 15f70: f8d8 00a0 ldr.w r0, [r8, #160] ; 0xa0 + 15f74: ea42 2207 orr.w r2, r2, r7, lsl #8 + 15f78: f8dd a004 ldr.w sl, [sp, #4] + 15f7c: 4042 eors r2, r0 + 15f7e: fa5f fe84 uxtb.w lr, r4 + 15f82: 0e0f lsrs r7, r1, #24 + 15f84: 5ddf ldrb r7, [r3, r7] + 15f86: f813 000e ldrb.w r0, [r3, lr] + 15f8a: ea4f 2c12 mov.w ip, r2, lsr #8 + 15f8e: f3c5 4e07 ubfx lr, r5, #16, #8 + 15f92: f88a 2003 strb.w r2, [sl, #3] + 15f96: f88a c002 strb.w ip, [sl, #2] + 15f9a: f813 e00e ldrb.w lr, [r3, lr] + 15f9e: f8dd c008 ldr.w ip, [sp, #8] + 15fa2: ea4f 6912 mov.w r9, r2, lsr #24 + 15fa6: ea4f 4812 mov.w r8, r2, lsr #16 + 15faa: f3c6 2207 ubfx r2, r6, #8, #8 + 15fae: f88a 9000 strb.w r9, [sl] + 15fb2: f88a 8001 strb.w r8, [sl, #1] + 15fb6: ea40 6007 orr.w r0, r0, r7, lsl #24 + 15fba: 5c9f ldrb r7, [r3, r2] + 15fbc: ea40 400e orr.w r0, r0, lr, lsl #16 + 15fc0: f8dc 20a4 ldr.w r2, [ip, #164] ; 0xa4 + 15fc4: ea40 2007 orr.w r0, r0, r7, lsl #8 + 15fc8: 4050 eors r0, r2 + 15fca: fa5f fe86 uxtb.w lr, r6 + 15fce: 0e27 lsrs r7, r4, #24 + 15fd0: 5ddf ldrb r7, [r3, r7] + 15fd2: f813 200e ldrb.w r2, [r3, lr] + 15fd6: ea4f 4810 mov.w r8, r0, lsr #16 + 15fda: f3c1 4e07 ubfx lr, r1, #16, #8 + 15fde: f813 e00e ldrb.w lr, [r3, lr] + 15fe2: f88a 0007 strb.w r0, [sl, #7] + 15fe6: f88a 8005 strb.w r8, [sl, #5] + 15fea: ea4f 6910 mov.w r9, r0, lsr #24 + 15fee: f8dd 8008 ldr.w r8, [sp, #8] + 15ff2: ea4f 2c10 mov.w ip, r0, lsr #8 + 15ff6: f3c5 2007 ubfx r0, r5, #8, #8 + 15ffa: f88a 9004 strb.w r9, [sl, #4] + 15ffe: f88a c006 strb.w ip, [sl, #6] + 16002: ea42 6207 orr.w r2, r2, r7, lsl #24 + 16006: 5c1f ldrb r7, [r3, r0] + 16008: ea42 420e orr.w r2, r2, lr, lsl #16 + 1600c: f8d8 00a8 ldr.w r0, [r8, #168] ; 0xa8 + 16010: 0e36 lsrs r6, r6, #24 + 16012: ea42 2207 orr.w r2, r2, r7, lsl #8 + 16016: b2ed uxtb r5, r5 + 16018: 4042 eors r2, r0 + 1601a: f813 e006 ldrb.w lr, [r3, r6] + 1601e: 5d5f ldrb r7, [r3, r5] + 16020: f3c4 4407 ubfx r4, r4, #16, #8 + 16024: 5d18 ldrb r0, [r3, r4] + 16026: 0e16 lsrs r6, r2, #24 + 16028: 0c15 lsrs r5, r2, #16 + 1602a: 0a14 lsrs r4, r2, #8 + 1602c: f3c1 2107 ubfx r1, r1, #8, #8 + 16030: 5c59 ldrb r1, [r3, r1] + 16032: f88a 200b strb.w r2, [sl, #11] + 16036: ea47 630e orr.w r3, r7, lr, lsl #24 + 1603a: f88a 6008 strb.w r6, [sl, #8] + 1603e: f88a 5009 strb.w r5, [sl, #9] + 16042: f88a 400a strb.w r4, [sl, #10] + 16046: f8d8 20ac ldr.w r2, [r8, #172] ; 0xac + 1604a: ea43 4300 orr.w r3, r3, r0, lsl #16 + 1604e: ea43 2301 orr.w r3, r3, r1, lsl #8 + 16052: 4053 eors r3, r2 + 16054: 0e18 lsrs r0, r3, #24 + 16056: 0c19 lsrs r1, r3, #16 + 16058: 0a1a lsrs r2, r3, #8 + 1605a: f88a 000c strb.w r0, [sl, #12] + 1605e: f88a 100d strb.w r1, [sl, #13] + 16062: f88a 300f strb.w r3, [sl, #15] + 16066: f88a 200e strb.w r2, [sl, #14] + 1606a: b005 add sp, #20 + 1606c: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +00016070 : + 16070: b508 push {r3, lr} + 16072: f24f 5311 movw r3, #62737 ; 0xf511 + 16076: 2100 movs r1, #0 + 16078: f2c0 0300 movt r3, #0 + 1607c: 22b0 movs r2, #176 ; 0xb0 + 1607e: 4798 blx r3 + 16080: bd08 pop {r3, pc} + 16082: bf00 nop + +00016084 : + 16084: 2a10 cmp r2, #16 + 16086: d106 bne.n 16096 + 16088: b510 push {r4, lr} + 1608a: 4604 mov r4, r0 + 1608c: b128 cbz r0, 1609a + 1608e: f7ff fd65 bl 15b5c + 16092: 4620 mov r0, r4 + 16094: bd10 pop {r4, pc} + 16096: 2000 movs r0, #0 + 16098: 4770 bx lr + 1609a: bd10 pop {r4, pc} + +0001609c : + 1609c: f645 1388 movw r3, #22920 ; 0x5988 + 160a0: f2c0 0303 movt r3, #3 + 160a4: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 160a8: 6846 ldr r6, [r0, #4] + 160aa: f891 e007 ldrb.w lr, [r1, #7] + 160ae: f891 a00b ldrb.w sl, [r1, #11] + 160b2: 6885 ldr r5, [r0, #8] + 160b4: f891 c00f ldrb.w ip, [r1, #15] + 160b8: 68c4 ldr r4, [r0, #12] + 160ba: f891 8003 ldrb.w r8, [r1, #3] + 160be: ea8e 0606 eor.w r6, lr, r6 + 160c2: ea8a 0505 eor.w r5, sl, r5 + 160c6: f891 e004 ldrb.w lr, [r1, #4] + 160ca: f891 a008 ldrb.w sl, [r1, #8] + 160ce: 6807 ldr r7, [r0, #0] + 160d0: ea8c 0404 eor.w r4, ip, r4 + 160d4: f891 c00c ldrb.w ip, [r1, #12] + 160d8: ea85 650a eor.w r5, r5, sl, lsl #24 + 160dc: ea88 0707 eor.w r7, r8, r7 + 160e0: ea86 660e eor.w r6, r6, lr, lsl #24 + 160e4: f891 8000 ldrb.w r8, [r1] + 160e8: f891 e005 ldrb.w lr, [r1, #5] + 160ec: f891 a009 ldrb.w sl, [r1, #9] + 160f0: ea84 640c eor.w r4, r4, ip, lsl #24 + 160f4: f891 c00d ldrb.w ip, [r1, #13] + 160f8: ea87 6708 eor.w r7, r7, r8, lsl #24 + 160fc: f891 b002 ldrb.w fp, [r1, #2] + 16100: f891 8001 ldrb.w r8, [r1, #1] + 16104: ea86 460e eor.w r6, r6, lr, lsl #16 + 16108: ea85 4a0a eor.w sl, r5, sl, lsl #16 + 1610c: f891 e006 ldrb.w lr, [r1, #6] + 16110: 7a8d ldrb r5, [r1, #10] + 16112: 7b89 ldrb r1, [r1, #14] + 16114: ea84 440c eor.w r4, r4, ip, lsl #16 + 16118: ea87 4808 eor.w r8, r7, r8, lsl #16 + 1611c: ea84 2701 eor.w r7, r4, r1, lsl #8 + 16120: 4604 mov r4, r0 + 16122: b087 sub sp, #28 + 16124: 9203 str r2, [sp, #12] + 16126: 461a mov r2, r3 + 16128: 34a0 adds r4, #160 ; 0xa0 + 1612a: 9004 str r0, [sp, #16] + 1612c: ea88 2b0b eor.w fp, r8, fp, lsl #8 + 16130: ea86 2e0e eor.w lr, r6, lr, lsl #8 + 16134: ea8a 2a05 eor.w sl, sl, r5, lsl #8 + 16138: 9405 str r4, [sp, #20] + 1613a: f645 1188 movw r1, #22920 ; 0x5988 + 1613e: ea4f 641b mov.w r4, fp, lsr #24 + 16142: 6905 ldr r5, [r0, #16] + 16144: f853 4024 ldr.w r4, [r3, r4, lsl #2] + 16148: ea4f 661e mov.w r6, lr, lsr #24 + 1614c: 4065 eors r5, r4 + 1614e: b2fc uxtb r4, r7 + 16150: f853 4024 ldr.w r4, [r3, r4, lsl #2] + 16154: f853 6026 ldr.w r6, [r3, r6, lsl #2] + 16158: ea85 6534 eor.w r5, r5, r4, ror #24 + 1615c: f3ce 4907 ubfx r9, lr, #16, #8 + 16160: 6944 ldr r4, [r0, #20] + 16162: f853 9029 ldr.w r9, [r3, r9, lsl #2] + 16166: 4074 eors r4, r6 + 16168: fa5f f68b uxtb.w r6, fp + 1616c: ea85 2939 eor.w r9, r5, r9, ror #8 + 16170: f853 6026 ldr.w r6, [r3, r6, lsl #2] + 16174: f3ca 2507 ubfx r5, sl, #8, #8 + 16178: f853 5025 ldr.w r5, [r3, r5, lsl #2] + 1617c: ea4f 6c1a mov.w ip, sl, lsr #24 + 16180: ea84 6436 eor.w r4, r4, r6, ror #24 + 16184: fa5f f68a uxtb.w r6, sl + 16188: f3ca 4a07 ubfx sl, sl, #16, #8 + 1618c: f853 802c ldr.w r8, [r3, ip, lsl #2] + 16190: f8cd 9004 str.w r9, [sp, #4] + 16194: 9502 str r5, [sp, #8] + 16196: f853 9026 ldr.w r9, [r3, r6, lsl #2] + 1619a: 6985 ldr r5, [r0, #24] + 1619c: f853 602a ldr.w r6, [r3, sl, lsl #2] + 161a0: ea4f 6c17 mov.w ip, r7, lsr #24 + 161a4: ea84 2436 eor.w r4, r4, r6, ror #8 + 161a8: f853 c02c ldr.w ip, [r3, ip, lsl #2] + 161ac: ea88 0605 eor.w r6, r8, r5 + 161b0: 69c5 ldr r5, [r0, #28] + 161b2: fa5f f88e uxtb.w r8, lr + 161b6: ea8c 0c05 eor.w ip, ip, r5 + 161ba: f853 8028 ldr.w r8, [r3, r8, lsl #2] + 161be: ea8c 6939 eor.w r9, ip, r9, ror #24 + 161c2: f3c7 4c07 ubfx ip, r7, #16, #8 + 161c6: ea86 6638 eor.w r6, r6, r8, ror #24 + 161ca: f853 802c ldr.w r8, [r3, ip, lsl #2] + 161ce: f3cb 4c07 ubfx ip, fp, #16, #8 + 161d2: f853 c02c ldr.w ip, [r3, ip, lsl #2] + 161d6: f3cb 2b07 ubfx fp, fp, #8, #8 + 161da: f3c7 2707 ubfx r7, r7, #8, #8 + 161de: ea86 2638 eor.w r6, r6, r8, ror #8 + 161e2: ea89 293c eor.w r9, r9, ip, ror #8 + 161e6: f853 802b ldr.w r8, [r3, fp, lsl #2] + 161ea: 9d02 ldr r5, [sp, #8] + 161ec: f853 7027 ldr.w r7, [r3, r7, lsl #2] + 161f0: f8dd c004 ldr.w ip, [sp, #4] + 161f4: f3ce 2e07 ubfx lr, lr, #8, #8 + 161f8: ea8c 4b35 eor.w fp, ip, r5, ror #16 + 161fc: ea84 4537 eor.w r5, r4, r7, ror #16 + 16200: ea86 4438 eor.w r4, r6, r8, ror #16 + 16204: 9e05 ldr r6, [sp, #20] + 16206: f853 e02e ldr.w lr, [r3, lr, lsl #2] + 1620a: 3020 adds r0, #32 + 1620c: 42b0 cmp r0, r6 + 1620e: ea89 493e eor.w r9, r9, lr, ror #16 + 16212: f2c0 0103 movt r1, #3 + 16216: d063 beq.n 162e0 + 16218: ea4f 611b mov.w r1, fp, lsr #24 + 1621c: ea4f 6719 mov.w r7, r9, lsr #24 + 16220: f852 1021 ldr.w r1, [r2, r1, lsl #2] + 16224: 6806 ldr r6, [r0, #0] + 16226: f852 7027 ldr.w r7, [r2, r7, lsl #2] + 1622a: ea4f 6c15 mov.w ip, r5, lsr #24 + 1622e: 404e eors r6, r1 + 16230: fa5f f189 uxtb.w r1, r9 + 16234: ea4f 6e14 mov.w lr, r4, lsr #24 + 16238: f852 c02c ldr.w ip, [r2, ip, lsl #2] + 1623c: 9702 str r7, [sp, #8] + 1623e: f852 7021 ldr.w r7, [r2, r1, lsl #2] + 16242: 6841 ldr r1, [r0, #4] + 16244: f852 a02e ldr.w sl, [r2, lr, lsl #2] + 16248: fa5f fe8b uxtb.w lr, fp + 1624c: ea86 6637 eor.w r6, r6, r7, ror #24 + 16250: ea8c 0101 eor.w r1, ip, r1 + 16254: f3c5 4707 ubfx r7, r5, #16, #8 + 16258: f852 c02e ldr.w ip, [r2, lr, lsl #2] + 1625c: f852 7027 ldr.w r7, [r2, r7, lsl #2] + 16260: fa5f fe84 uxtb.w lr, r4 + 16264: ea81 6c3c eor.w ip, r1, ip, ror #24 + 16268: f3c4 2107 ubfx r1, r4, #8, #8 + 1626c: f3c4 4407 ubfx r4, r4, #16, #8 + 16270: ea86 2837 eor.w r8, r6, r7, ror #8 + 16274: f852 7024 ldr.w r7, [r2, r4, lsl #2] + 16278: 6884 ldr r4, [r0, #8] + 1627a: f852 6021 ldr.w r6, [r2, r1, lsl #2] + 1627e: ea8a 0a04 eor.w sl, sl, r4 + 16282: b2ec uxtb r4, r5 + 16284: f852 4024 ldr.w r4, [r2, r4, lsl #2] + 16288: f3c5 2507 ubfx r5, r5, #8, #8 + 1628c: ea8a 6a34 eor.w sl, sl, r4, ror #24 + 16290: 68c1 ldr r1, [r0, #12] + 16292: f852 4025 ldr.w r4, [r2, r5, lsl #2] + 16296: 9d02 ldr r5, [sp, #8] + 16298: f852 e02e ldr.w lr, [r2, lr, lsl #2] + 1629c: 4069 eors r1, r5 + 1629e: f3c9 4507 ubfx r5, r9, #16, #8 + 162a2: ea81 6e3e eor.w lr, r1, lr, ror #24 + 162a6: f3c9 2107 ubfx r1, r9, #8, #8 + 162aa: f852 9025 ldr.w r9, [r2, r5, lsl #2] + 162ae: f3cb 4507 ubfx r5, fp, #16, #8 + 162b2: ea8c 2c37 eor.w ip, ip, r7, ror #8 + 162b6: f3cb 2b07 ubfx fp, fp, #8, #8 + 162ba: f852 7025 ldr.w r7, [r2, r5, lsl #2] + 162be: f852 1021 ldr.w r1, [r2, r1, lsl #2] + 162c2: f852 502b ldr.w r5, [r2, fp, lsl #2] + 162c6: ea8e 2737 eor.w r7, lr, r7, ror #8 + 162ca: ea8a 2a39 eor.w sl, sl, r9, ror #8 + 162ce: ea88 4b36 eor.w fp, r8, r6, ror #16 + 162d2: ea8c 4e31 eor.w lr, ip, r1, ror #16 + 162d6: ea8a 4a35 eor.w sl, sl, r5, ror #16 + 162da: ea87 4734 eor.w r7, r7, r4, ror #16 + 162de: e72c b.n 1613a + 162e0: 464e mov r6, r9 + 162e2: ea4f 631b mov.w r3, fp, lsr #24 + 162e6: f851 3023 ldr.w r3, [r1, r3, lsl #2] + 162ea: f3c5 4207 ubfx r2, r5, #16, #8 + 162ee: f851 0022 ldr.w r0, [r1, r2, lsl #2] + 162f2: 9f04 ldr r7, [sp, #16] + 162f4: ea4f 2e03 mov.w lr, r3, lsl #8 + 162f8: f3c4 2307 ubfx r3, r4, #8, #8 + 162fc: f8d7 20a0 ldr.w r2, [r7, #160] ; 0xa0 + 16300: f851 3023 ldr.w r3, [r1, r3, lsl #2] + 16304: f00e 4e7f and.w lr, lr, #4278190080 ; 0xff000000 + 16308: fa5f f789 uxtb.w r7, r9 + 1630c: f400 007f and.w r0, r0, #16711680 ; 0xff0000 + 16310: ea8e 0000 eor.w r0, lr, r0 + 16314: f851 7027 ldr.w r7, [r1, r7, lsl #2] + 16318: 4042 eors r2, r0 + 1631a: f403 437f and.w r3, r3, #65280 ; 0xff00 + 1631e: f8dd 800c ldr.w r8, [sp, #12] + 16322: 0e28 lsrs r0, r5, #24 + 16324: 4053 eors r3, r2 + 16326: f3c7 2707 ubfx r7, r7, #8, #8 + 1632a: 407b eors r3, r7 + 1632c: f851 2020 ldr.w r2, [r1, r0, lsl #2] + 16330: f3c4 4007 ubfx r0, r4, #16, #8 + 16334: f888 3003 strb.w r3, [r8, #3] + 16338: ea4f 6c13 mov.w ip, r3, lsr #24 + 1633c: ea4f 4e13 mov.w lr, r3, lsr #16 + 16340: 0a1f lsrs r7, r3, #8 + 16342: f851 0020 ldr.w r0, [r1, r0, lsl #2] + 16346: f3c9 2307 ubfx r3, r9, #8, #8 + 1634a: f8dd 9010 ldr.w r9, [sp, #16] + 1634e: f888 c000 strb.w ip, [r8] + 16352: f888 e001 strb.w lr, [r8, #1] + 16356: f888 7002 strb.w r7, [r8, #2] + 1635a: ea4f 2e02 mov.w lr, r2, lsl #8 + 1635e: f851 3023 ldr.w r3, [r1, r3, lsl #2] + 16362: f8d9 20a4 ldr.w r2, [r9, #164] ; 0xa4 + 16366: f00e 4e7f and.w lr, lr, #4278190080 ; 0xff000000 + 1636a: fa5f f78b uxtb.w r7, fp + 1636e: f400 007f and.w r0, r0, #16711680 ; 0xff0000 + 16372: ea8e 0000 eor.w r0, lr, r0 + 16376: f851 7027 ldr.w r7, [r1, r7, lsl #2] + 1637a: 4042 eors r2, r0 + 1637c: f403 437f and.w r3, r3, #65280 ; 0xff00 + 16380: 0e20 lsrs r0, r4, #24 + 16382: 4053 eors r3, r2 + 16384: f3c7 2707 ubfx r7, r7, #8, #8 + 16388: 407b eors r3, r7 + 1638a: f851 2020 ldr.w r2, [r1, r0, lsl #2] + 1638e: f3c6 4707 ubfx r7, r6, #16, #8 + 16392: ea4f 6c13 mov.w ip, r3, lsr #24 + 16396: ea4f 4e13 mov.w lr, r3, lsr #16 + 1639a: 0a18 lsrs r0, r3, #8 + 1639c: f851 7027 ldr.w r7, [r1, r7, lsl #2] + 163a0: f888 3007 strb.w r3, [r8, #7] + 163a4: f888 c004 strb.w ip, [r8, #4] + 163a8: f888 e005 strb.w lr, [r8, #5] + 163ac: f888 0006 strb.w r0, [r8, #6] + 163b0: ea4f 2e02 mov.w lr, r2, lsl #8 + 163b4: f3cb 2307 ubfx r3, fp, #8, #8 + 163b8: f8d9 20a8 ldr.w r2, [r9, #168] ; 0xa8 + 163bc: f851 3023 ldr.w r3, [r1, r3, lsl #2] + 163c0: f00e 4e7f and.w lr, lr, #4278190080 ; 0xff000000 + 163c4: b2e8 uxtb r0, r5 + 163c6: f407 077f and.w r7, r7, #16711680 ; 0xff0000 + 163ca: ea8e 0707 eor.w r7, lr, r7 + 163ce: f851 0020 ldr.w r0, [r1, r0, lsl #2] + 163d2: 407a eors r2, r7 + 163d4: f403 437f and.w r3, r3, #65280 ; 0xff00 + 163d8: 4053 eors r3, r2 + 163da: f3c0 2007 ubfx r0, r0, #8, #8 + 163de: 0e36 lsrs r6, r6, #24 + 163e0: 4043 eors r3, r0 + 163e2: f851 6026 ldr.w r6, [r1, r6, lsl #2] + 163e6: f3cb 4c07 ubfx ip, fp, #16, #8 + 163ea: f851 202c ldr.w r2, [r1, ip, lsl #2] + 163ee: ea4f 6e13 mov.w lr, r3, lsr #24 + 163f2: 0c1f lsrs r7, r3, #16 + 163f4: 0a18 lsrs r0, r3, #8 + 163f6: f888 300b strb.w r3, [r8, #11] + 163fa: f888 e008 strb.w lr, [r8, #8] + 163fe: f888 7009 strb.w r7, [r8, #9] + 16402: f888 000a strb.w r0, [r8, #10] + 16406: 0236 lsls r6, r6, #8 + 16408: f3c5 2507 ubfx r5, r5, #8, #8 + 1640c: f8d9 00ac ldr.w r0, [r9, #172] ; 0xac + 16410: f851 5025 ldr.w r5, [r1, r5, lsl #2] + 16414: b2e4 uxtb r4, r4 + 16416: f006 467f and.w r6, r6, #4278190080 ; 0xff000000 + 1641a: f402 037f and.w r3, r2, #16711680 ; 0xff0000 + 1641e: 4073 eors r3, r6 + 16420: f851 2024 ldr.w r2, [r1, r4, lsl #2] + 16424: 4043 eors r3, r0 + 16426: f405 417f and.w r1, r5, #65280 ; 0xff00 + 1642a: f3c2 2207 ubfx r2, r2, #8, #8 + 1642e: 404b eors r3, r1 + 16430: 4053 eors r3, r2 + 16432: 0e18 lsrs r0, r3, #24 + 16434: 0c19 lsrs r1, r3, #16 + 16436: 0a1a lsrs r2, r3, #8 + 16438: f888 000c strb.w r0, [r8, #12] + 1643c: f888 100d strb.w r1, [r8, #13] + 16440: f888 300f strb.w r3, [r8, #15] + 16444: f888 200e strb.w r2, [r8, #14] + 16448: b007 add sp, #28 + 1644a: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 1644e: bf00 nop + +00016450 : + 16450: b508 push {r3, lr} + 16452: f24f 5311 movw r3, #62737 ; 0xf511 + 16456: 2100 movs r1, #0 + 16458: f2c0 0300 movt r3, #0 + 1645c: 22b0 movs r2, #176 ; 0xb0 + 1645e: 4798 blx r3 + 16460: bd08 pop {r3, pc} + 16462: bf00 nop + +00016464 : + 16464: b538 push {r3, r4, r5, lr} + 16466: f240 63d4 movw r3, #1748 ; 0x6d4 + 1646a: f2c1 0300 movt r3, #4096 ; 0x1000 + 1646e: 4605 mov r5, r0 + 16470: 681b ldr r3, [r3, #0] + 16472: 2020 movs r0, #32 + 16474: 4798 blx r3 + 16476: 60e8 str r0, [r5, #12] + 16478: b168 cbz r0, 16496 + 1647a: 2300 movs r3, #0 + 1647c: 461c mov r4, r3 + 1647e: 50c4 str r4, [r0, r3] + 16480: 3304 adds r3, #4 + 16482: 2b20 cmp r3, #32 + 16484: f04f 0200 mov.w r2, #0 + 16488: d1f9 bne.n 1647e + 1648a: 2308 movs r3, #8 + 1648c: 602a str r2, [r5, #0] + 1648e: 60aa str r2, [r5, #8] + 16490: 4610 mov r0, r2 + 16492: 606b str r3, [r5, #4] + 16494: bd38 pop {r3, r4, r5, pc} + 16496: f06f 0001 mvn.w r0, #1 + 1649a: bd38 pop {r3, r4, r5, pc} + +0001649c : + 1649c: b510 push {r4, lr} + 1649e: 4604 mov r4, r0 + 164a0: 68c0 ldr r0, [r0, #12] + 164a2: b1c0 cbz r0, 164d6 + 164a4: 6821 ldr r1, [r4, #0] + 164a6: 2900 cmp r1, #0 + 164a8: bfc2 ittt gt + 164aa: 4603 movgt r3, r0 + 164ac: eb00 0181 addgt.w r1, r0, r1, lsl #2 + 164b0: 2200 movgt r2, #0 + 164b2: dd03 ble.n 164bc + 164b4: f843 2b04 str.w r2, [r3], #4 + 164b8: 428b cmp r3, r1 + 164ba: d1fb bne.n 164b4 + 164bc: f240 63d4 movw r3, #1748 ; 0x6d4 + 164c0: f2c1 0300 movt r3, #4096 ; 0x1000 + 164c4: 2100 movs r1, #0 + 164c6: 685b ldr r3, [r3, #4] + 164c8: 4798 blx r3 + 164ca: 2300 movs r3, #0 + 164cc: 60e3 str r3, [r4, #12] + 164ce: 6023 str r3, [r4, #0] + 164d0: 6063 str r3, [r4, #4] + 164d2: 60a3 str r3, [r4, #8] + 164d4: bd10 pop {r4, pc} + 164d6: bd10 pop {r4, pc} + +000164d8 : + 164d8: 6802 ldr r2, [r0, #0] + 164da: b1d2 cbz r2, 16512 + 164dc: 68c1 ldr r1, [r0, #12] + 164de: f102 4380 add.w r3, r2, #1073741824 ; 0x40000000 + 164e2: 3b01 subs r3, #1 + 164e4: 3a01 subs r2, #1 + 164e6: ebc2 02c2 rsb r2, r2, r2, lsl #3 + 164ea: f851 3023 ldr.w r3, [r1, r3, lsl #2] + 164ee: 0091 lsls r1, r2, #2 + 164f0: 460a mov r2, r1 + 164f2: b183 cbz r3, 16516 + 164f4: 085b lsrs r3, r3, #1 + 164f6: f102 0201 add.w r2, r2, #1 + 164fa: d1fb bne.n 164f4 + 164fc: 1dd3 adds r3, r2, #7 + 164fe: ea13 0322 ands.w r3, r3, r2, asr #32 + 16502: bf38 it cc + 16504: 4613 movcc r3, r2 + 16506: f012 0207 ands.w r2, r2, #7 + 1650a: bf18 it ne + 1650c: 2201 movne r2, #1 + 1650e: eb02 02e3 add.w r2, r2, r3, asr #3 + 16512: 4610 mov r0, r2 + 16514: 4770 bx lr + 16516: 1dca adds r2, r1, #7 + 16518: ea12 0221 ands.w r2, r2, r1, asr #32 + 1651c: bf38 it cc + 1651e: 460a movcc r2, r1 + 16520: f3c1 0180 ubfx r1, r1, #2, #1 + 16524: eb01 02e2 add.w r2, r1, r2, asr #3 + 16528: e7f3 b.n 16512 + 1652a: bf00 nop + +0001652c : + 1652c: b470 push {r4, r5, r6} + 1652e: 460c mov r4, r1 + 16530: 4606 mov r6, r0 + 16532: c80f ldmia r0, {r0, r1, r2, r3} + 16534: b085 sub sp, #20 + 16536: e88d 000f stmia.w sp, {r0, r1, r2, r3} + 1653a: e894 000f ldmia.w r4, {r0, r1, r2, r3} + 1653e: e886 000f stmia.w r6, {r0, r1, r2, r3} + 16542: e89d 000f ldmia.w sp, {r0, r1, r2, r3} + 16546: e884 000f stmia.w r4, {r0, r1, r2, r3} + 1654a: b005 add sp, #20 + 1654c: bc70 pop {r4, r5, r6} + 1654e: 4770 bx lr + +00016550 : + 16550: f240 63d4 movw r3, #1748 ; 0x6d4 + 16554: f2c1 0300 movt r3, #4096 ; 0x1000 + 16558: 17ca asrs r2, r1, #31 + 1655a: 0f52 lsrs r2, r2, #29 + 1655c: b570 push {r4, r5, r6, lr} + 1655e: 188d adds r5, r1, r2 + 16560: f005 0507 and.w r5, r5, #7 + 16564: 1aad subs r5, r5, r2 + 16566: f1c5 0510 rsb r5, r5, #16 + 1656a: 440d add r5, r1 + 1656c: 00ae lsls r6, r5, #2 + 1656e: 4604 mov r4, r0 + 16570: 681b ldr r3, [r3, #0] + 16572: 4630 mov r0, r6 + 16574: 4798 blx r3 + 16576: 60e0 str r0, [r4, #12] + 16578: b178 cbz r0, 1659a + 1657a: 2200 movs r2, #0 + 1657c: 4295 cmp r5, r2 + 1657e: bfc8 it gt + 16580: 4603 movgt r3, r0 + 16582: e884 0024 stmia.w r4, {r2, r5} + 16586: 60a2 str r2, [r4, #8] + 16588: bfc8 it gt + 1658a: 1998 addgt r0, r3, r6 + 1658c: dd03 ble.n 16596 + 1658e: f843 2b04 str.w r2, [r3], #4 + 16592: 4283 cmp r3, r0 + 16594: d1fb bne.n 1658e + 16596: 2000 movs r0, #0 + 16598: bd70 pop {r4, r5, r6, pc} + 1659a: f06f 0001 mvn.w r0, #1 + 1659e: bd70 pop {r4, r5, r6, pc} + +000165a0 : + 165a0: 4290 cmp r0, r2 + 165a2: dc22 bgt.n 165ea + 165a4: db2a blt.n 165fc + 165a6: b430 push {r4, r5} + 165a8: f100 4480 add.w r4, r0, #1073741824 ; 0x40000000 + 165ac: 680d ldr r5, [r1, #0] + 165ae: 681b ldr r3, [r3, #0] + 165b0: 3c01 subs r4, #1 + 165b2: 00a2 lsls r2, r4, #2 + 165b4: 2800 cmp r0, #0 + 165b6: eb05 0102 add.w r1, r5, r2 + 165ba: 441a add r2, r3 + 165bc: dd12 ble.n 165e4 + 165be: f855 5024 ldr.w r5, [r5, r4, lsl #2] + 165c2: f853 3024 ldr.w r3, [r3, r4, lsl #2] + 165c6: 429d cmp r5, r3 + 165c8: d811 bhi.n 165ee + 165ca: d313 bcc.n 165f4 + 165cc: 2300 movs r3, #0 + 165ce: e006 b.n 165de + 165d0: f851 5d04 ldr.w r5, [r1, #-4]! + 165d4: f852 4d04 ldr.w r4, [r2, #-4]! + 165d8: 42a5 cmp r5, r4 + 165da: d808 bhi.n 165ee + 165dc: d30a bcc.n 165f4 + 165de: 3301 adds r3, #1 + 165e0: 4283 cmp r3, r0 + 165e2: d1f5 bne.n 165d0 + 165e4: 2000 movs r0, #0 + 165e6: bc30 pop {r4, r5} + 165e8: 4770 bx lr + 165ea: 2001 movs r0, #1 + 165ec: 4770 bx lr + 165ee: 2001 movs r0, #1 + 165f0: bc30 pop {r4, r5} + 165f2: 4770 bx lr + 165f4: f04f 30ff mov.w r0, #4294967295 + 165f8: bc30 pop {r4, r5} + 165fa: 4770 bx lr + 165fc: f04f 30ff mov.w r0, #4294967295 + 16600: 4770 bx lr + 16602: bf00 nop + +00016604 : + 16604: 6882 ldr r2, [r0, #8] + 16606: 688b ldr r3, [r1, #8] + 16608: 429a cmp r2, r3 + 1660a: d005 beq.n 16618 + 1660c: 2a01 cmp r2, #1 + 1660e: bf14 ite ne + 16610: 2001 movne r0, #1 + 16612: f04f 30ff moveq.w r0, #4294967295 + 16616: 4770 bx lr + 16618: 2a01 cmp r2, #1 + 1661a: d00a beq.n 16632 + 1661c: b410 push {r4} + 1661e: 4604 mov r4, r0 + 16620: 460b mov r3, r1 + 16622: f854 0b0c ldr.w r0, [r4], #12 + 16626: f853 2b0c ldr.w r2, [r3], #12 + 1662a: 4621 mov r1, r4 + 1662c: f85d 4b04 ldr.w r4, [sp], #4 + 16630: e7b6 b.n 165a0 + 16632: 4603 mov r3, r0 + 16634: f851 0b0c ldr.w r0, [r1], #12 + 16638: f853 2b0c ldr.w r2, [r3], #12 + 1663c: e7b0 b.n 165a0 + 1663e: bf00 nop + +00016640 : + 16640: 2900 cmp r1, #0 + 16642: dd11 ble.n 16668 + 16644: b4f0 push {r4, r5, r6, r7} + 16646: 6806 ldr r6, [r0, #0] + 16648: 42b1 cmp r1, r6 + 1664a: db0e blt.n 1666a + 1664c: 6841 ldr r1, [r0, #4] + 1664e: 2300 movs r3, #0 + 16650: 4299 cmp r1, r3 + 16652: 6083 str r3, [r0, #8] + 16654: 6003 str r3, [r0, #0] + 16656: 68c2 ldr r2, [r0, #12] + 16658: dd05 ble.n 16666 + 1665a: 4618 mov r0, r3 + 1665c: 3301 adds r3, #1 + 1665e: 428b cmp r3, r1 + 16660: f842 0b04 str.w r0, [r2], #4 + 16664: d1fa bne.n 1665c + 16666: bcf0 pop {r4, r5, r6, r7} + 16668: 4770 bx lr + 1666a: 1a77 subs r7, r6, r1 + 1666c: 68c2 ldr r2, [r0, #12] + 1666e: 2f00 cmp r7, #0 + 16670: eb02 0181 add.w r1, r2, r1, lsl #2 + 16674: dd17 ble.n 166a6 + 16676: 4614 mov r4, r2 + 16678: 2300 movs r3, #0 + 1667a: f851 5b04 ldr.w r5, [r1], #4 + 1667e: 3301 adds r3, #1 + 16680: 42bb cmp r3, r7 + 16682: f844 5b04 str.w r5, [r4], #4 + 16686: d1f8 bne.n 1667a + 16688: 463b mov r3, r7 + 1668a: eb02 0287 add.w r2, r2, r7, lsl #2 + 1668e: 429e cmp r6, r3 + 16690: bfc8 it gt + 16692: 2100 movgt r1, #0 + 16694: dd04 ble.n 166a0 + 16696: 3301 adds r3, #1 + 16698: 42b3 cmp r3, r6 + 1669a: f842 1b04 str.w r1, [r2], #4 + 1669e: d1fa bne.n 16696 + 166a0: 6007 str r7, [r0, #0] + 166a2: bcf0 pop {r4, r5, r6, r7} + 166a4: e7e0 b.n 16668 + 166a6: 2300 movs r3, #0 + 166a8: e7f1 b.n 1668e + 166aa: bf00 nop + +000166ac : + 166ac: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 166b0: 0043 lsls r3, r0, #1 + 166b2: b089 sub sp, #36 ; 0x24 + 166b4: f103 0b01 add.w fp, r3, #1 + 166b8: 4605 mov r5, r0 + 166ba: 460c mov r4, r1 + 166bc: a804 add r0, sp, #16 + 166be: 4659 mov r1, fp + 166c0: 9301 str r3, [sp, #4] + 166c2: 9202 str r2, [sp, #8] + 166c4: f7ff ff44 bl 16550 + 166c8: 2800 cmp r0, #0 + 166ca: d179 bne.n 167c0 + 166cc: 2d00 cmp r5, #0 + 166ce: f8cd b010 str.w fp, [sp, #16] + 166d2: dd55 ble.n 16780 + 166d4: f8cd b00c str.w fp, [sp, #12] + 166d8: 46ab mov fp, r5 + 166da: 6823 ldr r3, [r4, #0] + 166dc: 9f07 ldr r7, [sp, #28] + 166de: ea4f 0c85 mov.w ip, r5, lsl #2 + 166e2: f1a3 0e04 sub.w lr, r3, #4 + 166e6: eb0c 060e add.w r6, ip, lr + 166ea: 44bc add ip, r7 + 166ec: 3704 adds r7, #4 + 166ee: f857 3c04 ldr.w r3, [r7, #-4] + 166f2: f8de 2004 ldr.w r2, [lr, #4] + 166f6: 4698 mov r8, r3 + 166f8: f04f 0900 mov.w r9, #0 + 166fc: fbe2 8902 umlal r8, r9, r2, r2 + 16700: 3001 adds r0, #1 + 16702: f028 4370 bic.w r3, r8, #4026531840 ; 0xf0000000 + 16706: f847 3c04 str.w r3, [r7, #-4] + 1670a: ea4f 7418 mov.w r4, r8, lsr #28 + 1670e: 4558 cmp r0, fp + 16710: f85e af04 ldr.w sl, [lr, #4]! + 16714: ea44 1409 orr.w r4, r4, r9, lsl #4 + 16718: 4639 mov r1, r7 + 1671a: da1a bge.n 16752 + 1671c: 46f0 mov r8, lr + 1671e: 4605 mov r5, r0 + 16720: 4622 mov r2, r4 + 16722: 680c ldr r4, [r1, #0] + 16724: f858 0f04 ldr.w r0, [r8, #4]! + 16728: 1912 adds r2, r2, r4 + 1672a: f04f 0300 mov.w r3, #0 + 1672e: f143 0300 adc.w r3, r3, #0 + 16732: fbea 2300 umlal r2, r3, sl, r0 + 16736: fbea 2300 umlal r2, r3, sl, r0 + 1673a: 45b0 cmp r8, r6 + 1673c: f022 4070 bic.w r0, r2, #4026531840 ; 0xf0000000 + 16740: ea4f 7412 mov.w r4, r2, lsr #28 + 16744: f841 0b04 str.w r0, [r1], #4 + 16748: ea44 1403 orr.w r4, r4, r3, lsl #4 + 1674c: d1e8 bne.n 16720 + 1674e: 4628 mov r0, r5 + 16750: 4661 mov r1, ip + 16752: 4622 mov r2, r4 + 16754: b164 cbz r4, 16770 + 16756: 680c ldr r4, [r1, #0] + 16758: 2300 movs r3, #0 + 1675a: 1912 adds r2, r2, r4 + 1675c: f022 4470 bic.w r4, r2, #4026531840 ; 0xf0000000 + 16760: f143 0300 adc.w r3, r3, #0 + 16764: 0f12 lsrs r2, r2, #28 + 16766: ea52 1203 orrs.w r2, r2, r3, lsl #4 + 1676a: f841 4b04 str.w r4, [r1], #4 + 1676e: d1f2 bne.n 16756 + 16770: 4558 cmp r0, fp + 16772: f10c 0c04 add.w ip, ip, #4 + 16776: f107 0708 add.w r7, r7, #8 + 1677a: d1b8 bne.n 166ee + 1677c: f8dd b00c ldr.w fp, [sp, #12] + 16780: f1bb 0f00 cmp.w fp, #0 + 16784: dd22 ble.n 167cc + 16786: f10b 4280 add.w r2, fp, #1073741824 ; 0x40000000 + 1678a: 9b07 ldr r3, [sp, #28] + 1678c: 3a01 subs r2, #1 + 1678e: f853 2022 ldr.w r2, [r3, r2, lsl #2] + 16792: b96a cbnz r2, 167b0 + 16794: 9a01 ldr r2, [sp, #4] + 16796: eb03 0382 add.w r3, r3, r2, lsl #2 + 1679a: e002 b.n 167a2 + 1679c: f853 2d04 ldr.w r2, [r3, #-4]! + 167a0: b98a cbnz r2, 167c6 + 167a2: f1bb 0b01 subs.w fp, fp, #1 + 167a6: d1f9 bne.n 1679c + 167a8: f8cd b010 str.w fp, [sp, #16] + 167ac: 2300 movs r3, #0 + 167ae: 9306 str r3, [sp, #24] + 167b0: 9902 ldr r1, [sp, #8] + 167b2: a804 add r0, sp, #16 + 167b4: f7ff feba bl 1652c + 167b8: a804 add r0, sp, #16 + 167ba: f7ff fe6f bl 1649c + 167be: 2000 movs r0, #0 + 167c0: b009 add sp, #36 ; 0x24 + 167c2: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 167c6: f8cd b010 str.w fp, [sp, #16] + 167ca: e7f1 b.n 167b0 + 167cc: d0ee beq.n 167ac + 167ce: e7ef b.n 167b0 + +000167d0 : + 167d0: b5f8 push {r3, r4, r5, r6, r7, lr} + 167d2: 6803 ldr r3, [r0, #0] + 167d4: 4604 mov r4, r0 + 167d6: 4293 cmp r3, r2 + 167d8: db01 blt.n 167de + 167da: 2000 movs r0, #0 + 167dc: bdf8 pop {r3, r4, r5, r6, r7, pc} + 167de: 460d mov r5, r1 + 167e0: 17d1 asrs r1, r2, #31 + 167e2: 0f49 lsrs r1, r1, #29 + 167e4: 1856 adds r6, r2, r1 + 167e6: f006 0607 and.w r6, r6, #7 + 167ea: 1a76 subs r6, r6, r1 + 167ec: f1c6 0610 rsb r6, r6, #16 + 167f0: 4416 add r6, r2 + 167f2: 00b7 lsls r7, r6, #2 + 167f4: 0099 lsls r1, r3, #2 + 167f6: 463a mov r2, r7 + 167f8: 6828 ldr r0, [r5, #0] + 167fa: f001 faa9 bl 17d50 + 167fe: b170 cbz r0, 1681e + 16800: 6823 ldr r3, [r4, #0] + 16802: 6028 str r0, [r5, #0] + 16804: 429e cmp r6, r3 + 16806: 6026 str r6, [r4, #0] + 16808: dde7 ble.n 167da + 1680a: eb00 0383 add.w r3, r0, r3, lsl #2 + 1680e: 2100 movs r1, #0 + 16810: 4438 add r0, r7 + 16812: f843 1b04 str.w r1, [r3], #4 + 16816: 4283 cmp r3, r0 + 16818: d1fb bne.n 16812 + 1681a: 2000 movs r0, #0 + 1681c: bdf8 pop {r3, r4, r5, r6, r7, pc} + 1681e: f06f 0001 mvn.w r0, #1 + 16822: bdf8 pop {r3, r4, r5, r6, r7, pc} + +00016824 : + 16824: 4288 cmp r0, r1 + 16826: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} + 1682a: 4681 mov r9, r0 + 1682c: 4688 mov r8, r1 + 1682e: d031 beq.n 16894 + 16830: 6802 ldr r2, [r0, #0] + 16832: 684b ldr r3, [r1, #4] + 16834: 4293 cmp r3, r2 + 16836: db25 blt.n 16884 + 16838: 2a00 cmp r2, #0 + 1683a: f8d9 500c ldr.w r5, [r9, #12] + 1683e: f8d8 400c ldr.w r4, [r8, #12] + 16842: dd2a ble.n 1689a + 16844: 4626 mov r6, r4 + 16846: 2300 movs r3, #0 + 16848: f855 7b04 ldr.w r7, [r5], #4 + 1684c: 3301 adds r3, #1 + 1684e: 4293 cmp r3, r2 + 16850: f846 7b04 str.w r7, [r6], #4 + 16854: d1f8 bne.n 16848 + 16856: 4613 mov r3, r2 + 16858: eb04 0482 add.w r4, r4, r2, lsl #2 + 1685c: f8d8 5000 ldr.w r5, [r8] + 16860: 42ab cmp r3, r5 + 16862: bfb8 it lt + 16864: 2100 movlt r1, #0 + 16866: da04 bge.n 16872 + 16868: 3301 adds r3, #1 + 1686a: 42ab cmp r3, r5 + 1686c: f844 1b04 str.w r1, [r4], #4 + 16870: d1fa bne.n 16868 + 16872: f8d9 3008 ldr.w r3, [r9, #8] + 16876: 2000 movs r0, #0 + 16878: f8c8 2000 str.w r2, [r8] + 1687c: f8c8 3008 str.w r3, [r8, #8] + 16880: e8bd 83f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} + 16884: 1d08 adds r0, r1, #4 + 16886: 310c adds r1, #12 + 16888: f7ff ffa2 bl 167d0 + 1688c: b918 cbnz r0, 16896 + 1688e: f8d9 2000 ldr.w r2, [r9] + 16892: e7d1 b.n 16838 + 16894: 2000 movs r0, #0 + 16896: e8bd 83f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} + 1689a: 2300 movs r3, #0 + 1689c: e7de b.n 1685c + 1689e: bf00 nop + +000168a0 : + 168a0: b570 push {r4, r5, r6, lr} + 168a2: 1e0e subs r6, r1, #0 + 168a4: dd26 ble.n 168f4 + 168a6: e890 000c ldmia.w r0, {r2, r3} + 168aa: 4432 add r2, r6 + 168ac: 4293 cmp r3, r2 + 168ae: 4605 mov r5, r0 + 168b0: db22 blt.n 168f8 + 168b2: f64f 70ff movw r0, #65535 ; 0xffff + 168b6: f6c3 70ff movt r0, #16383 ; 0x3fff + 168ba: 68ec ldr r4, [r5, #12] + 168bc: f102 4180 add.w r1, r2, #1073741824 ; 0x40000000 + 168c0: 1e53 subs r3, r2, #1 + 168c2: 1b80 subs r0, r0, r6 + 168c4: 4410 add r0, r2 + 168c6: 3901 subs r1, #1 + 168c8: 429e cmp r6, r3 + 168ca: 602a str r2, [r5, #0] + 168cc: eb04 0080 add.w r0, r4, r0, lsl #2 + 168d0: eb04 0281 add.w r2, r4, r1, lsl #2 + 168d4: dc07 bgt.n 168e6 + 168d6: 1e71 subs r1, r6, #1 + 168d8: f850 5904 ldr.w r5, [r0], #-4 + 168dc: 3b01 subs r3, #1 + 168de: 428b cmp r3, r1 + 168e0: f842 5904 str.w r5, [r2], #-4 + 168e4: d1f8 bne.n 168d8 + 168e6: 2300 movs r3, #0 + 168e8: 461a mov r2, r3 + 168ea: 3301 adds r3, #1 + 168ec: 42b3 cmp r3, r6 + 168ee: f844 2b04 str.w r2, [r4], #4 + 168f2: d1fa bne.n 168ea + 168f4: 2000 movs r0, #0 + 168f6: bd70 pop {r4, r5, r6, pc} + 168f8: 3004 adds r0, #4 + 168fa: f105 010c add.w r1, r5, #12 + 168fe: f7ff ff67 bl 167d0 + 16902: b910 cbnz r0, 1690a + 16904: 682a ldr r2, [r5, #0] + 16906: 4432 add r2, r6 + 16908: e7d3 b.n 168b2 + 1690a: bd70 pop {r4, r5, r6, pc} + +0001690c : + 1690c: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} + 16910: 680c ldr r4, [r1, #0] + 16912: 6806 ldr r6, [r0, #0] + 16914: 4615 mov r5, r2 + 16916: 42a6 cmp r6, r4 + 16918: bfc2 ittt gt + 1691a: 4633 movgt r3, r6 + 1691c: 4626 movgt r6, r4 + 1691e: 461c movgt r4, r3 + 16920: 6853 ldr r3, [r2, #4] + 16922: bfcc ite gt + 16924: 4680 movgt r8, r0 + 16926: 4688 movle r8, r1 + 16928: 429c cmp r4, r3 + 1692a: 4681 mov r9, r0 + 1692c: 460f mov r7, r1 + 1692e: bfb8 it lt + 16930: 1c62 addlt r2, r4, #1 + 16932: da63 bge.n 169fc + 16934: 2e00 cmp r6, #0 + 16936: f8d7 c00c ldr.w ip, [r7, #12] + 1693a: f8d9 000c ldr.w r0, [r9, #12] + 1693e: 682f ldr r7, [r5, #0] + 16940: f8d5 e00c ldr.w lr, [r5, #12] + 16944: 602a str r2, [r5, #0] + 16946: dd65 ble.n 16a14 + 16948: 2100 movs r1, #0 + 1694a: 460b mov r3, r1 + 1694c: 46f1 mov r9, lr + 1694e: f85c bb04 ldr.w fp, [ip], #4 + 16952: f850 ab04 ldr.w sl, [r0], #4 + 16956: 3101 adds r1, #1 + 16958: 44da add sl, fp + 1695a: 4453 add r3, sl + 1695c: f023 4a70 bic.w sl, r3, #4026531840 ; 0xf0000000 + 16960: 42b1 cmp r1, r6 + 16962: f849 ab04 str.w sl, [r9], #4 + 16966: ea4f 7313 mov.w r3, r3, lsr #28 + 1696a: d1f0 bne.n 1694e + 1696c: 46b1 mov r9, r6 + 1696e: eb0e 0c86 add.w ip, lr, r6, lsl #2 + 16972: 42a6 cmp r6, r4 + 16974: d017 beq.n 169a6 + 16976: 454c cmp r4, r9 + 16978: dd15 ble.n 169a6 + 1697a: 4661 mov r1, ip + 1697c: f8d8 600c ldr.w r6, [r8, #12] + 16980: eb06 0089 add.w r0, r6, r9, lsl #2 + 16984: eb06 0884 add.w r8, r6, r4, lsl #2 + 16988: f850 6b04 ldr.w r6, [r0], #4 + 1698c: 4433 add r3, r6 + 1698e: f023 4670 bic.w r6, r3, #4026531840 ; 0xf0000000 + 16992: 4540 cmp r0, r8 + 16994: f841 6b04 str.w r6, [r1], #4 + 16998: ea4f 7313 mov.w r3, r3, lsr #28 + 1699c: d1f4 bne.n 16988 + 1699e: ebc9 0404 rsb r4, r9, r4 + 169a2: eb0c 0c84 add.w ip, ip, r4, lsl #2 + 169a6: 42ba cmp r2, r7 + 169a8: f8cc 3000 str.w r3, [ip] + 169ac: f10c 0404 add.w r4, ip, #4 + 169b0: bfbc itt lt + 169b2: 4610 movlt r0, r2 + 169b4: 2300 movlt r3, #0 + 169b6: da04 bge.n 169c2 + 169b8: 3001 adds r0, #1 + 169ba: 42b8 cmp r0, r7 + 169bc: f844 3b04 str.w r3, [r4], #4 + 169c0: d1fa bne.n 169b8 + 169c2: 2a00 cmp r2, #0 + 169c4: dd2b ble.n 16a1e + 169c6: f102 4180 add.w r1, r2, #1073741824 ; 0x40000000 + 169ca: 3901 subs r1, #1 + 169cc: f85e 3021 ldr.w r3, [lr, r1, lsl #2] + 169d0: 0089 lsls r1, r1, #2 + 169d2: b983 cbnz r3, 169f6 + 169d4: 3104 adds r1, #4 + 169d6: 4613 mov r3, r2 + 169d8: 4471 add r1, lr + 169da: e002 b.n 169e2 + 169dc: f851 2c04 ldr.w r2, [r1, #-4] + 169e0: b942 cbnz r2, 169f4 + 169e2: 3b01 subs r3, #1 + 169e4: f1a1 0104 sub.w r1, r1, #4 + 169e8: d1f8 bne.n 169dc + 169ea: 602b str r3, [r5, #0] + 169ec: 2000 movs r0, #0 + 169ee: 60a8 str r0, [r5, #8] + 169f0: e8bd 8ff8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, pc} + 169f4: 602b str r3, [r5, #0] + 169f6: 2000 movs r0, #0 + 169f8: e8bd 8ff8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, pc} + 169fc: f104 0a01 add.w sl, r4, #1 + 16a00: 4652 mov r2, sl + 16a02: 1d28 adds r0, r5, #4 + 16a04: f105 010c add.w r1, r5, #12 + 16a08: f7ff fee2 bl 167d0 + 16a0c: 2800 cmp r0, #0 + 16a0e: d1ef bne.n 169f0 + 16a10: 4652 mov r2, sl + 16a12: e78f b.n 16934 + 16a14: f04f 0900 mov.w r9, #0 + 16a18: 464b mov r3, r9 + 16a1a: 46f4 mov ip, lr + 16a1c: e7a9 b.n 16972 + 16a1e: d0e5 beq.n 169ec + 16a20: e7e9 b.n 169f6 + 16a22: bf00 nop + +00016a24 : + 16a24: b5f8 push {r3, r4, r5, r6, r7, lr} + 16a26: 6844 ldr r4, [r0, #4] + 16a28: 2300 movs r3, #0 + 16a2a: 429c cmp r4, r3 + 16a2c: 4606 mov r6, r0 + 16a2e: 460f mov r7, r1 + 16a30: 6083 str r3, [r0, #8] + 16a32: 6003 str r3, [r0, #0] + 16a34: 68c2 ldr r2, [r0, #12] + 16a36: bfc8 it gt + 16a38: 461d movgt r5, r3 + 16a3a: dd04 ble.n 16a46 + 16a3c: 3301 adds r3, #1 + 16a3e: 42a3 cmp r3, r4 + 16a40: f842 5b04 str.w r5, [r2], #4 + 16a44: d1fa bne.n 16a3c + 16a46: f242 4493 movw r4, #9363 ; 0x2493 + 16a4a: f2c9 2449 movt r4, #37449 ; 0x9249 + 16a4e: fb84 2307 smull r2, r3, r4, r7 + 16a52: 17fc asrs r4, r7, #31 + 16a54: 443b add r3, r7 + 16a56: ebc4 1423 rsb r4, r4, r3, asr #4 + 16a5a: 1c65 adds r5, r4, #1 + 16a5c: 462a mov r2, r5 + 16a5e: 1d30 adds r0, r6, #4 + 16a60: f106 010c add.w r1, r6, #12 + 16a64: f7ff feb4 bl 167d0 + 16a68: b958 cbnz r0, 16a82 + 16a6a: ebc4 02c4 rsb r2, r4, r4, lsl #3 + 16a6e: 68f3 ldr r3, [r6, #12] + 16a70: eba7 0782 sub.w r7, r7, r2, lsl #2 + 16a74: 2201 movs r2, #1 + 16a76: fa02 f707 lsl.w r7, r2, r7 + 16a7a: 6035 str r5, [r6, #0] + 16a7c: f843 7024 str.w r7, [r3, r4, lsl #2] + 16a80: bdf8 pop {r3, r4, r5, r6, r7, pc} + 16a82: bdf8 pop {r3, r4, r5, r6, r7, pc} + +00016a84 : + 16a84: b5f8 push {r3, r4, r5, r6, r7, lr} + 16a86: 1e0e subs r6, r1, #0 + 16a88: 4615 mov r5, r2 + 16a8a: dd59 ble.n 16b40 + 16a8c: 6803 ldr r3, [r0, #0] + 16a8e: 4611 mov r1, r2 + 16a90: ebc3 03c3 rsb r3, r3, r3, lsl #3 + 16a94: ebb6 0f83 cmp.w r6, r3, lsl #2 + 16a98: da4c bge.n 16b34 + 16a9a: f7ff fec3 bl 16824 + 16a9e: 2800 cmp r0, #0 + 16aa0: d147 bne.n 16b32 + 16aa2: f242 4793 movw r7, #9363 ; 0x2493 + 16aa6: f2c9 2749 movt r7, #37449 ; 0x9249 + 16aaa: fb87 2306 smull r2, r3, r7, r6 + 16aae: 17f7 asrs r7, r6, #31 + 16ab0: 4433 add r3, r6 + 16ab2: ebc7 1723 rsb r7, r7, r3, asr #4 + 16ab6: ebc7 04c7 rsb r4, r7, r7, lsl #3 + 16aba: 00a4 lsls r4, r4, #2 + 16abc: 42b4 cmp r4, r6 + 16abe: bf0c ite eq + 16ac0: 463c moveq r4, r7 + 16ac2: 1c7c addne r4, r7, #1 + 16ac4: 682b ldr r3, [r5, #0] + 16ac6: 68e9 ldr r1, [r5, #12] + 16ac8: 429c cmp r4, r3 + 16aca: bfbc itt lt + 16acc: eb01 0484 addlt.w r4, r1, r4, lsl #2 + 16ad0: eb01 0283 addlt.w r2, r1, r3, lsl #2 + 16ad4: da03 bge.n 16ade + 16ad6: f844 0b04 str.w r0, [r4], #4 + 16ada: 4294 cmp r4, r2 + 16adc: d1fb bne.n 16ad6 + 16ade: f644 1225 movw r2, #18725 ; 0x4925 + 16ae2: f2c2 4292 movt r2, #9362 ; 0x2492 + 16ae6: 08b0 lsrs r0, r6, #2 + 16ae8: fba2 4200 umull r4, r2, r2, r0 + 16aec: ebc2 02c2 rsb r2, r2, r2, lsl #3 + 16af0: 2001 movs r0, #1 + 16af2: eba6 0682 sub.w r6, r6, r2, lsl #2 + 16af6: fa00 f606 lsl.w r6, r0, r6 + 16afa: f851 0027 ldr.w r0, [r1, r7, lsl #2] + 16afe: 3e01 subs r6, #1 + 16b00: 4030 ands r0, r6 + 16b02: 2b00 cmp r3, #0 + 16b04: f841 0027 str.w r0, [r1, r7, lsl #2] + 16b08: dd2a ble.n 16b60 + 16b0a: f103 4080 add.w r0, r3, #1073741824 ; 0x40000000 + 16b0e: 3801 subs r0, #1 + 16b10: f851 2020 ldr.w r2, [r1, r0, lsl #2] + 16b14: 0080 lsls r0, r0, #2 + 16b16: b98a cbnz r2, 16b3c + 16b18: 3004 adds r0, #4 + 16b1a: 4408 add r0, r1 + 16b1c: e002 b.n 16b24 + 16b1e: f850 4c04 ldr.w r4, [r0, #-4] + 16b22: b954 cbnz r4, 16b3a + 16b24: 3b01 subs r3, #1 + 16b26: f1a0 0004 sub.w r0, r0, #4 + 16b2a: d1f8 bne.n 16b1e + 16b2c: 602b str r3, [r5, #0] + 16b2e: 2000 movs r0, #0 + 16b30: 60a8 str r0, [r5, #8] + 16b32: bdf8 pop {r3, r4, r5, r6, r7, pc} + 16b34: e8bd 40f8 ldmia.w sp!, {r3, r4, r5, r6, r7, lr} + 16b38: e674 b.n 16824 + 16b3a: 602b str r3, [r5, #0] + 16b3c: 2000 movs r0, #0 + 16b3e: bdf8 pop {r3, r4, r5, r6, r7, pc} + 16b40: 6851 ldr r1, [r2, #4] + 16b42: 2300 movs r3, #0 + 16b44: 4299 cmp r1, r3 + 16b46: 6093 str r3, [r2, #8] + 16b48: 6013 str r3, [r2, #0] + 16b4a: bfc8 it gt + 16b4c: 4618 movgt r0, r3 + 16b4e: 68d2 ldr r2, [r2, #12] + 16b50: ddf4 ble.n 16b3c + 16b52: 3301 adds r3, #1 + 16b54: 428b cmp r3, r1 + 16b56: f842 0b04 str.w r0, [r2], #4 + 16b5a: d1fa bne.n 16b52 + 16b5c: 2000 movs r0, #0 + 16b5e: bdf8 pop {r3, r4, r5, r6, r7, pc} + 16b60: d0e5 beq.n 16b2e + 16b62: e7eb b.n 16b3c + +00016b64 : + 16b64: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} + 16b68: 1e0c subs r4, r1, #0 + 16b6a: b085 sub sp, #20 + 16b6c: 4691 mov r9, r2 + 16b6e: 4698 mov r8, r3 + 16b70: dd56 ble.n 16c20 + 16b72: 4605 mov r5, r0 + 16b74: 4668 mov r0, sp + 16b76: f7ff fc75 bl 16464 + 16b7a: 2800 cmp r0, #0 + 16b7c: d14d bne.n 16c1a + 16b7e: f1b8 0f00 cmp.w r8, #0 + 16b82: d008 beq.n 16b96 + 16b84: 4628 mov r0, r5 + 16b86: 4621 mov r1, r4 + 16b88: 466a mov r2, sp + 16b8a: f7ff ff7b bl 16a84 + 16b8e: 4606 mov r6, r0 + 16b90: 2800 cmp r0, #0 + 16b92: f040 808e bne.w 16cb2 + 16b96: 4628 mov r0, r5 + 16b98: 4649 mov r1, r9 + 16b9a: f7ff fe43 bl 16824 + 16b9e: 4605 mov r5, r0 + 16ba0: 2800 cmp r0, #0 + 16ba2: f040 808b bne.w 16cbc + 16ba6: 2c1b cmp r4, #27 + 16ba8: bfd8 it le + 16baa: 17e5 asrle r5, r4, #31 + 16bac: dc73 bgt.n 16c96 + 16bae: f242 4393 movw r3, #9363 ; 0x2493 + 16bb2: f2c9 2349 movt r3, #37449 ; 0x9249 + 16bb6: fb83 2104 smull r2, r1, r3, r4 + 16bba: 4421 add r1, r4 + 16bbc: ebc5 1121 rsb r1, r5, r1, asr #4 + 16bc0: ebc1 01c1 rsb r1, r1, r1, lsl #3 + 16bc4: ebb4 0181 subs.w r1, r4, r1, lsl #2 + 16bc8: f8d9 4000 ldr.w r4, [r9] + 16bcc: d142 bne.n 16c54 + 16bce: 2c00 cmp r4, #0 + 16bd0: dd79 ble.n 16cc6 + 16bd2: f8d9 200c ldr.w r2, [r9, #12] + 16bd6: f104 4380 add.w r3, r4, #1073741824 ; 0x40000000 + 16bda: 3b01 subs r3, #1 + 16bdc: f852 1023 ldr.w r1, [r2, r3, lsl #2] + 16be0: 009b lsls r3, r3, #2 + 16be2: 3304 adds r3, #4 + 16be4: 18d5 adds r5, r2, r3 + 16be6: b121 cbz r1, 16bf2 + 16be8: e00c b.n 16c04 + 16bea: f855 6c04 ldr.w r6, [r5, #-4] + 16bee: 2e00 cmp r6, #0 + 16bf0: d14e bne.n 16c90 + 16bf2: 3c01 subs r4, #1 + 16bf4: f1a5 0504 sub.w r5, r5, #4 + 16bf8: d1f7 bne.n 16bea + 16bfa: f8c9 4000 str.w r4, [r9] + 16bfe: 2300 movs r3, #0 + 16c00: f8c9 3008 str.w r3, [r9, #8] + 16c04: f1b8 0f00 cmp.w r8, #0 + 16c08: d003 beq.n 16c12 + 16c0a: 4641 mov r1, r8 + 16c0c: 4668 mov r0, sp + 16c0e: f7ff fc8d bl 1652c + 16c12: 4668 mov r0, sp + 16c14: f7ff fc42 bl 1649c + 16c18: 2000 movs r0, #0 + 16c1a: b005 add sp, #20 + 16c1c: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + 16c20: 4611 mov r1, r2 + 16c22: f7ff fdff bl 16824 + 16c26: f1b8 0f00 cmp.w r8, #0 + 16c2a: d0f6 beq.n 16c1a + 16c2c: f8d8 1004 ldr.w r1, [r8, #4] + 16c30: 2300 movs r3, #0 + 16c32: 4299 cmp r1, r3 + 16c34: f8c8 3008 str.w r3, [r8, #8] + 16c38: f8c8 3000 str.w r3, [r8] + 16c3c: f8d8 200c ldr.w r2, [r8, #12] + 16c40: ddeb ble.n 16c1a + 16c42: 461c mov r4, r3 + 16c44: 3301 adds r3, #1 + 16c46: 428b cmp r3, r1 + 16c48: f842 4b04 str.w r4, [r2], #4 + 16c4c: d1fa bne.n 16c44 + 16c4e: b005 add sp, #20 + 16c50: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + 16c54: f8d9 600c ldr.w r6, [r9, #12] + 16c58: f104 4380 add.w r3, r4, #1073741824 ; 0x40000000 + 16c5c: 2001 movs r0, #1 + 16c5e: 3b01 subs r3, #1 + 16c60: 4088 lsls r0, r1 + 16c62: 1e65 subs r5, r4, #1 + 16c64: eb06 0683 add.w r6, r6, r3, lsl #2 + 16c68: f100 30ff add.w r0, r0, #4294967295 + 16c6c: f1c1 0e1c rsb lr, r1, #28 + 16c70: d4ad bmi.n 16bce + 16c72: 2300 movs r3, #0 + 16c74: 6837 ldr r7, [r6, #0] + 16c76: fa03 f30e lsl.w r3, r3, lr + 16c7a: fa27 f201 lsr.w r2, r7, r1 + 16c7e: 3d01 subs r5, #1 + 16c80: 4313 orrs r3, r2 + 16c82: 1c6a adds r2, r5, #1 + 16c84: f846 3904 str.w r3, [r6], #-4 + 16c88: ea07 0300 and.w r3, r7, r0 + 16c8c: d1f2 bne.n 16c74 + 16c8e: e79e b.n 16bce + 16c90: f8c9 4000 str.w r4, [r9] + 16c94: e7b6 b.n 16c04 + 16c96: f242 4393 movw r3, #9363 ; 0x2493 + 16c9a: f2c9 2349 movt r3, #37449 ; 0x9249 + 16c9e: fb83 2304 smull r2, r3, r3, r4 + 16ca2: 17e5 asrs r5, r4, #31 + 16ca4: 1919 adds r1, r3, r4 + 16ca6: ebc5 1121 rsb r1, r5, r1, asr #4 + 16caa: 4648 mov r0, r9 + 16cac: f7ff fcc8 bl 16640 + 16cb0: e77d b.n 16bae + 16cb2: 4668 mov r0, sp + 16cb4: f7ff fbf2 bl 1649c + 16cb8: 4630 mov r0, r6 + 16cba: e7ae b.n 16c1a + 16cbc: 4668 mov r0, sp + 16cbe: f7ff fbed bl 1649c + 16cc2: 4628 mov r0, r5 + 16cc4: e7a9 b.n 16c1a + 16cc6: d09a beq.n 16bfe + 16cc8: e79c b.n 16c04 + 16cca: bf00 nop + +00016ccc : + 16ccc: 4282 cmp r2, r0 + 16cce: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + 16cd2: 4690 mov r8, r2 + 16cd4: 460c mov r4, r1 + 16cd6: d004 beq.n 16ce2 + 16cd8: 4611 mov r1, r2 + 16cda: f7ff fda3 bl 16824 + 16cde: 2800 cmp r0, #0 + 16ce0: d168 bne.n 16db4 + 16ce2: f242 4393 movw r3, #9363 ; 0x2493 + 16ce6: f2c9 2349 movt r3, #37449 ; 0x9249 + 16cea: fb83 2604 smull r2, r6, r3, r4 + 16cee: 17e5 asrs r5, r4, #31 + 16cf0: 4426 add r6, r4 + 16cf2: f8d8 2000 ldr.w r2, [r8] + 16cf6: ebc5 1626 rsb r6, r5, r6, asr #4 + 16cfa: f8d8 3004 ldr.w r3, [r8, #4] + 16cfe: 4432 add r2, r6 + 16d00: 429a cmp r2, r3 + 16d02: da5e bge.n 16dc2 + 16d04: 2c1b cmp r4, #27 + 16d06: dc67 bgt.n 16dd8 + 16d08: f242 4193 movw r1, #9363 ; 0x2493 + 16d0c: f2c9 2149 movt r1, #37449 ; 0x9249 + 16d10: fb81 3104 smull r3, r1, r1, r4 + 16d14: 4421 add r1, r4 + 16d16: ebc5 1121 rsb r1, r5, r1, asr #4 + 16d1a: ebc1 01c1 rsb r1, r1, r1, lsl #3 + 16d1e: ebb4 0181 subs.w r1, r4, r1, lsl #2 + 16d22: d11d bne.n 16d60 + 16d24: f8d8 3000 ldr.w r3, [r8] + 16d28: 2b00 cmp r3, #0 + 16d2a: dd5d ble.n 16de8 + 16d2c: f8d8 400c ldr.w r4, [r8, #12] + 16d30: f103 4280 add.w r2, r3, #1073741824 ; 0x40000000 + 16d34: 3a01 subs r2, #1 + 16d36: f854 1022 ldr.w r1, [r4, r2, lsl #2] + 16d3a: 0092 lsls r2, r2, #2 + 16d3c: 3204 adds r2, #4 + 16d3e: 4414 add r4, r2 + 16d40: b119 cbz r1, 16d4a + 16d42: e03b b.n 16dbc + 16d44: f854 5c04 ldr.w r5, [r4, #-4] + 16d48: bbb5 cbnz r5, 16db8 + 16d4a: 3b01 subs r3, #1 + 16d4c: f1a4 0404 sub.w r4, r4, #4 + 16d50: d1f8 bne.n 16d44 + 16d52: f8c8 3000 str.w r3, [r8] + 16d56: 2000 movs r0, #0 + 16d58: f8c8 0008 str.w r0, [r8, #8] + 16d5c: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 16d60: f8d8 3000 ldr.w r3, [r8] + 16d64: 2001 movs r0, #1 + 16d66: 4088 lsls r0, r1 + 16d68: 2b00 cmp r3, #0 + 16d6a: f100 30ff add.w r0, r0, #4294967295 + 16d6e: f1c1 0e1c rsb lr, r1, #28 + 16d72: f8d8 400c ldr.w r4, [r8, #12] + 16d76: dd37 ble.n 16de8 + 16d78: 2500 movs r5, #0 + 16d7a: 462a mov r2, r5 + 16d7c: 4626 mov r6, r4 + 16d7e: e000 b.n 16d82 + 16d80: 463a mov r2, r7 + 16d82: 6837 ldr r7, [r6, #0] + 16d84: 3501 adds r5, #1 + 16d86: fa07 fc01 lsl.w ip, r7, r1 + 16d8a: ea42 020c orr.w r2, r2, ip + 16d8e: f022 4270 bic.w r2, r2, #4026531840 ; 0xf0000000 + 16d92: fa27 f70e lsr.w r7, r7, lr + 16d96: 429d cmp r5, r3 + 16d98: f846 2b04 str.w r2, [r6], #4 + 16d9c: ea07 0700 and.w r7, r7, r0 + 16da0: d1ee bne.n 16d80 + 16da2: 2f00 cmp r7, #0 + 16da4: d0c4 beq.n 16d30 + 16da6: 1c5a adds r2, r3, #1 + 16da8: f8c8 2000 str.w r2, [r8] + 16dac: f844 7023 str.w r7, [r4, r3, lsl #2] + 16db0: 4613 mov r3, r2 + 16db2: e7bd b.n 16d30 + 16db4: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 16db8: f8c8 3000 str.w r3, [r8] + 16dbc: 2000 movs r0, #0 + 16dbe: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 16dc2: 3201 adds r2, #1 + 16dc4: f108 0004 add.w r0, r8, #4 + 16dc8: f108 010c add.w r1, r8, #12 + 16dcc: f7ff fd00 bl 167d0 + 16dd0: 2800 cmp r0, #0 + 16dd2: d097 beq.n 16d04 + 16dd4: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 16dd8: 4631 mov r1, r6 + 16dda: 4640 mov r0, r8 + 16ddc: f7ff fd60 bl 168a0 + 16de0: 2800 cmp r0, #0 + 16de2: d091 beq.n 16d08 + 16de4: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 16de8: 2b00 cmp r3, #0 + 16dea: d0b4 beq.n 16d56 + 16dec: e7e6 b.n 16dbc + 16dee: bf00 nop + +00016df0 : + 16df0: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} + 16df4: 4606 mov r6, r0 + 16df6: 9c08 ldr r4, [sp, #32] + 16df8: 460d mov r5, r1 + 16dfa: 6860 ldr r0, [r4, #4] + 16dfc: 4617 mov r7, r2 + 16dfe: 42b0 cmp r0, r6 + 16e00: 4698 mov r8, r3 + 16e02: db62 blt.n 16eca + 16e04: 2f00 cmp r7, #0 + 16e06: f8d4 e00c ldr.w lr, [r4, #12] + 16e0a: bfd8 it le + 16e0c: 2700 movle r7, #0 + 16e0e: f8d8 2000 ldr.w r2, [r8] + 16e12: 682d ldr r5, [r5, #0] + 16e14: 6820 ldr r0, [r4, #0] + 16e16: bfd8 it le + 16e18: 463b movle r3, r7 + 16e1a: 6026 str r6, [r4, #0] + 16e1c: bfd8 it le + 16e1e: 4672 movle r2, lr + 16e20: dd17 ble.n 16e52 + 16e22: 2100 movs r1, #0 + 16e24: 460b mov r3, r1 + 16e26: 46f0 mov r8, lr + 16e28: 46ac mov ip, r5 + 16e2a: f85c ab04 ldr.w sl, [ip], #4 + 16e2e: f852 9b04 ldr.w r9, [r2], #4 + 16e32: 3101 adds r1, #1 + 16e34: ebc9 090a rsb r9, r9, sl + 16e38: ebc3 0309 rsb r3, r3, r9 + 16e3c: f023 4970 bic.w r9, r3, #4026531840 ; 0xf0000000 + 16e40: 42b9 cmp r1, r7 + 16e42: f848 9b04 str.w r9, [r8], #4 + 16e46: ea4f 73d3 mov.w r3, r3, lsr #31 + 16e4a: d1ee bne.n 16e2a + 16e4c: 00ba lsls r2, r7, #2 + 16e4e: 4415 add r5, r2 + 16e50: 4472 add r2, lr + 16e52: 42be cmp r6, r7 + 16e54: dd11 ble.n 16e7a + 16e56: 4639 mov r1, r7 + 16e58: 4694 mov ip, r2 + 16e5a: f855 8b04 ldr.w r8, [r5], #4 + 16e5e: 3101 adds r1, #1 + 16e60: ebc3 0308 rsb r3, r3, r8 + 16e64: f023 4870 bic.w r8, r3, #4026531840 ; 0xf0000000 + 16e68: 42b1 cmp r1, r6 + 16e6a: f84c 8b04 str.w r8, [ip], #4 + 16e6e: ea4f 73d3 mov.w r3, r3, lsr #31 + 16e72: d1f2 bne.n 16e5a + 16e74: 1bf7 subs r7, r6, r7 + 16e76: eb02 0287 add.w r2, r2, r7, lsl #2 + 16e7a: 42b0 cmp r0, r6 + 16e7c: bfc2 ittt gt + 16e7e: 2300 movgt r3, #0 + 16e80: 4619 movgt r1, r3 + 16e82: 1b80 subgt r0, r0, r6 + 16e84: dd04 ble.n 16e90 + 16e86: 3301 adds r3, #1 + 16e88: 4283 cmp r3, r0 + 16e8a: f842 1b04 str.w r1, [r2], #4 + 16e8e: d1fa bne.n 16e86 + 16e90: 2e00 cmp r6, #0 + 16e92: dd24 ble.n 16ede + 16e94: f106 4380 add.w r3, r6, #1073741824 ; 0x40000000 + 16e98: 3b01 subs r3, #1 + 16e9a: f85e 2023 ldr.w r2, [lr, r3, lsl #2] + 16e9e: 009b lsls r3, r3, #2 + 16ea0: 3304 adds r3, #4 + 16ea2: 4630 mov r0, r6 + 16ea4: 4473 add r3, lr + 16ea6: b11a cbz r2, 16eb0 + 16ea8: e00c b.n 16ec4 + 16eaa: f853 2c04 ldr.w r2, [r3, #-4] + 16eae: b942 cbnz r2, 16ec2 + 16eb0: 3801 subs r0, #1 + 16eb2: f1a3 0304 sub.w r3, r3, #4 + 16eb6: d1f8 bne.n 16eaa + 16eb8: 6020 str r0, [r4, #0] + 16eba: 2000 movs r0, #0 + 16ebc: 60a0 str r0, [r4, #8] + 16ebe: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + 16ec2: 6020 str r0, [r4, #0] + 16ec4: 2000 movs r0, #0 + 16ec6: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + 16eca: 1d20 adds r0, r4, #4 + 16ecc: f104 010c add.w r1, r4, #12 + 16ed0: 4632 mov r2, r6 + 16ed2: f7ff fc7d bl 167d0 + 16ed6: 2800 cmp r0, #0 + 16ed8: d094 beq.n 16e04 + 16eda: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + 16ede: d0ec beq.n 16eba + 16ee0: e7f0 b.n 16ec4 + 16ee2: bf00 nop + +00016ee4 : + 16ee4: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} + 16ee8: 6887 ldr r7, [r0, #8] + 16eea: f8d1 a008 ldr.w sl, [r1, #8] + 16eee: b082 sub sp, #8 + 16ef0: 4557 cmp r7, sl + 16ef2: 4605 mov r5, r0 + 16ef4: 460c mov r4, r1 + 16ef6: 4616 mov r6, r2 + 16ef8: d022 beq.n 16f40 + 16efa: f100 090c add.w r9, r0, #12 + 16efe: f101 080c add.w r8, r1, #12 + 16f02: 4643 mov r3, r8 + 16f04: 4649 mov r1, r9 + 16f06: 6800 ldr r0, [r0, #0] + 16f08: 6822 ldr r2, [r4, #0] + 16f0a: f7ff fb49 bl 165a0 + 16f0e: 3001 adds r0, #1 + 16f10: d00a beq.n 16f28 + 16f12: 60b7 str r7, [r6, #8] + 16f14: 6828 ldr r0, [r5, #0] + 16f16: 6822 ldr r2, [r4, #0] + 16f18: 4649 mov r1, r9 + 16f1a: 9600 str r6, [sp, #0] + 16f1c: 4643 mov r3, r8 + 16f1e: f7ff ff67 bl 16df0 + 16f22: b002 add sp, #8 + 16f24: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + 16f28: f8c6 a008 str.w sl, [r6, #8] + 16f2c: 6820 ldr r0, [r4, #0] + 16f2e: 682a ldr r2, [r5, #0] + 16f30: 4641 mov r1, r8 + 16f32: 9600 str r6, [sp, #0] + 16f34: 464b mov r3, r9 + 16f36: f7ff ff5b bl 16df0 + 16f3a: b002 add sp, #8 + 16f3c: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + 16f40: 6097 str r7, [r2, #8] + 16f42: b002 add sp, #8 + 16f44: e8bd 47f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, lr} + 16f48: e4e0 b.n 1690c + 16f4a: bf00 nop + +00016f4c : + 16f4c: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} + 16f50: 688b ldr r3, [r1, #8] + 16f52: 6886 ldr r6, [r0, #8] + 16f54: b083 sub sp, #12 + 16f56: 429e cmp r6, r3 + 16f58: 4604 mov r4, r0 + 16f5a: 460d mov r5, r1 + 16f5c: 4617 mov r7, r2 + 16f5e: d124 bne.n 16faa + 16f60: f100 080c add.w r8, r0, #12 + 16f64: f101 090c add.w r9, r1, #12 + 16f68: 464b mov r3, r9 + 16f6a: 4641 mov r1, r8 + 16f6c: 6800 ldr r0, [r0, #0] + 16f6e: 682a ldr r2, [r5, #0] + 16f70: f7ff fb16 bl 165a0 + 16f74: 3001 adds r0, #1 + 16f76: d00a beq.n 16f8e + 16f78: 60be str r6, [r7, #8] + 16f7a: 6820 ldr r0, [r4, #0] + 16f7c: 682a ldr r2, [r5, #0] + 16f7e: 4641 mov r1, r8 + 16f80: 9700 str r7, [sp, #0] + 16f82: 464b mov r3, r9 + 16f84: f7ff ff34 bl 16df0 + 16f88: b003 add sp, #12 + 16f8a: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + 16f8e: fab6 f686 clz r6, r6 + 16f92: 0976 lsrs r6, r6, #5 + 16f94: 60be str r6, [r7, #8] + 16f96: 6828 ldr r0, [r5, #0] + 16f98: 6822 ldr r2, [r4, #0] + 16f9a: 4649 mov r1, r9 + 16f9c: 9700 str r7, [sp, #0] + 16f9e: 4643 mov r3, r8 + 16fa0: f7ff ff26 bl 16df0 + 16fa4: b003 add sp, #12 + 16fa6: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + 16faa: 6096 str r6, [r2, #8] + 16fac: b003 add sp, #12 + 16fae: e8bd 43f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, lr} + 16fb2: e4ab b.n 1690c + +00016fb4 : + 16fb4: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} + 16fb8: b090 sub sp, #64 ; 0x40 + 16fba: 4606 mov r6, r0 + 16fbc: 4668 mov r0, sp + 16fbe: 460f mov r7, r1 + 16fc0: 4691 mov r9, r2 + 16fc2: 4698 mov r8, r3 + 16fc4: f7ff fa4e bl 16464 + 16fc8: 4604 mov r4, r0 + 16fca: a804 add r0, sp, #16 + 16fcc: f7ff fa4a bl 16464 + 16fd0: 4304 orrs r4, r0 + 16fd2: a808 add r0, sp, #32 + 16fd4: f7ff fa46 bl 16464 + 16fd8: 4304 orrs r4, r0 + 16fda: a80c add r0, sp, #48 ; 0x30 + 16fdc: f7ff fa42 bl 16464 + 16fe0: 4320 orrs r0, r4 + 16fe2: f040 80b5 bne.w 17150 + 16fe6: 9b09 ldr r3, [sp, #36] ; 0x24 + 16fe8: 990b ldr r1, [sp, #44] ; 0x2c + 16fea: 2b00 cmp r3, #0 + 16fec: bfc8 it gt + 16fee: 4604 movgt r4, r0 + 16ff0: 900a str r0, [sp, #40] ; 0x28 + 16ff2: bfc4 itt gt + 16ff4: 460d movgt r5, r1 + 16ff6: 4622 movgt r2, r4 + 16ff8: dd04 ble.n 17004 + 16ffa: 3401 adds r4, #1 + 16ffc: 429c cmp r4, r3 + 16ffe: f845 2b04 str.w r2, [r5], #4 + 17002: d1fa bne.n 16ffa + 17004: f8d6 a000 ldr.w sl, [r6] + 17008: 2301 movs r3, #1 + 1700a: 600b str r3, [r1, #0] + 1700c: 9308 str r3, [sp, #32] + 1700e: f1ba 0f00 cmp.w sl, #0 + 17012: d012 beq.n 1703a + 17014: f10a 4280 add.w r2, sl, #1073741824 ; 0x40000000 + 17018: 68f1 ldr r1, [r6, #12] + 1701a: f10a 3aff add.w sl, sl, #4294967295 + 1701e: 3a01 subs r2, #1 + 17020: ebca 0aca rsb sl, sl, sl, lsl #3 + 17024: f851 4022 ldr.w r4, [r1, r2, lsl #2] + 17028: ea4f 0a8a mov.w sl, sl, lsl #2 + 1702c: 4653 mov r3, sl + 1702e: b124 cbz r4, 1703a + 17030: 0864 lsrs r4, r4, #1 + 17032: f103 0301 add.w r3, r3, #1 + 17036: d1fb bne.n 17030 + 17038: 469a mov sl, r3 + 1703a: 683d ldr r5, [r7, #0] + 1703c: b185 cbz r5, 17060 + 1703e: f105 4280 add.w r2, r5, #1073741824 ; 0x40000000 + 17042: 68f9 ldr r1, [r7, #12] + 17044: 3d01 subs r5, #1 + 17046: 3a01 subs r2, #1 + 17048: ebc5 05c5 rsb r5, r5, r5, lsl #3 + 1704c: f851 4022 ldr.w r4, [r1, r2, lsl #2] + 17050: 00ad lsls r5, r5, #2 + 17052: 462b mov r3, r5 + 17054: b124 cbz r4, 17060 + 17056: 0864 lsrs r4, r4, #1 + 17058: f103 0301 add.w r3, r3, #1 + 1705c: d1fb bne.n 17056 + 1705e: 461d mov r5, r3 + 17060: 4630 mov r0, r6 + 17062: 4669 mov r1, sp + 17064: f7ff fbde bl 16824 + 17068: 4604 mov r4, r0 + 1706a: b178 cbz r0, 1708c + 1706c: 4668 mov r0, sp + 1706e: f7ff fa15 bl 1649c + 17072: a804 add r0, sp, #16 + 17074: f7ff fa12 bl 1649c + 17078: a808 add r0, sp, #32 + 1707a: f7ff fa0f bl 1649c + 1707e: a80c add r0, sp, #48 ; 0x30 + 17080: f7ff fa0c bl 1649c + 17084: 4620 mov r0, r4 + 17086: b010 add sp, #64 ; 0x40 + 17088: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + 1708c: 4638 mov r0, r7 + 1708e: a904 add r1, sp, #16 + 17090: 9402 str r4, [sp, #8] + 17092: f7ff fbc7 bl 16824 + 17096: 4604 mov r4, r0 + 17098: 2800 cmp r0, #0 + 1709a: d1e7 bne.n 1706c + 1709c: a804 add r0, sp, #16 + 1709e: ebc5 050a rsb r5, r5, sl + 170a2: 4629 mov r1, r5 + 170a4: 4602 mov r2, r0 + 170a6: 9406 str r4, [sp, #24] + 170a8: f7ff fe10 bl 16ccc + 170ac: 4604 mov r4, r0 + 170ae: 2800 cmp r0, #0 + 170b0: d1dc bne.n 1706c + 170b2: a808 add r0, sp, #32 + 170b4: 4629 mov r1, r5 + 170b6: 4602 mov r2, r0 + 170b8: f7ff fe08 bl 16ccc + 170bc: 4604 mov r4, r0 + 170be: 2800 cmp r0, #0 + 170c0: d1d4 bne.n 1706c + 170c2: e022 b.n 1710a + 170c4: a804 add r0, sp, #16 + 170c6: 4669 mov r1, sp + 170c8: f7ff fa9c bl 16604 + 170cc: 2801 cmp r0, #1 + 170ce: d00d beq.n 170ec + 170d0: 4668 mov r0, sp + 170d2: a904 add r1, sp, #16 + 170d4: 466a mov r2, sp + 170d6: f7ff ff39 bl 16f4c + 170da: 2800 cmp r0, #0 + 170dc: d13b bne.n 17156 + 170de: a80c add r0, sp, #48 ; 0x30 + 170e0: a908 add r1, sp, #32 + 170e2: 4602 mov r2, r0 + 170e4: f7ff fefe bl 16ee4 + 170e8: 2800 cmp r0, #0 + 170ea: d134 bne.n 17156 + 170ec: a804 add r0, sp, #16 + 170ee: 2101 movs r1, #1 + 170f0: 2300 movs r3, #0 + 170f2: 4602 mov r2, r0 + 170f4: f7ff fd36 bl 16b64 + 170f8: 2101 movs r1, #1 + 170fa: 4603 mov r3, r0 + 170fc: bb68 cbnz r0, 1715a + 170fe: a808 add r0, sp, #32 + 17100: 4602 mov r2, r0 + 17102: f7ff fd2f bl 16b64 + 17106: 3d01 subs r5, #1 + 17108: bb28 cbnz r0, 17156 + 1710a: 2d00 cmp r5, #0 + 1710c: dada bge.n 170c4 + 1710e: 68b5 ldr r5, [r6, #8] + 17110: 68be ldr r6, [r7, #8] + 17112: f1b9 0f00 cmp.w r9, #0 + 17116: d00b beq.n 17130 + 17118: 4648 mov r0, r9 + 1711a: a90c add r1, sp, #48 ; 0x30 + 1711c: f7ff fa06 bl 1652c + 17120: f8d9 3000 ldr.w r3, [r9] + 17124: b113 cbz r3, 1712c + 17126: 1bab subs r3, r5, r6 + 17128: bf18 it ne + 1712a: 2301 movne r3, #1 + 1712c: f8c9 3008 str.w r3, [r9, #8] + 17130: f1b8 0f00 cmp.w r8, #0 + 17134: d09a beq.n 1706c + 17136: 4640 mov r0, r8 + 17138: 4669 mov r1, sp + 1713a: f7ff f9f7 bl 1652c + 1713e: f8d8 3000 ldr.w r3, [r8] + 17142: 2b00 cmp r3, #0 + 17144: bf14 ite ne + 17146: 462b movne r3, r5 + 17148: 2300 moveq r3, #0 + 1714a: f8c8 3008 str.w r3, [r8, #8] + 1714e: e78d b.n 1706c + 17150: f06f 0001 mvn.w r0, #1 + 17154: e797 b.n 17086 + 17156: 4604 mov r4, r0 + 17158: e788 b.n 1706c + 1715a: 4604 mov r4, r0 + 1715c: e786 b.n 1706c + 1715e: bf00 nop + +00017160 : + 17160: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 17164: f6ad 0d14 subw sp, sp, #2068 ; 0x814 + 17168: f8dd 4838 ldr.w r4, [sp, #2104] ; 0x838 + 1716c: f8dd 783c ldr.w r7, [sp, #2108] ; 0x83c + 17170: 6866 ldr r6, [r4, #4] + 17172: 4680 mov r8, r0 + 17174: 42be cmp r6, r7 + 17176: 460c mov r4, r1 + 17178: 4691 mov r9, r2 + 1717a: 461d mov r5, r3 + 1717c: f2c0 809f blt.w 172be + 17180: f8d8 b000 ldr.w fp, [r8] + 17184: f8d9 9000 ldr.w r9, [r9] + 17188: eb0b 0809 add.w r8, fp, r9 + 1718c: 45b8 cmp r8, r7 + 1718e: bfa8 it ge + 17190: 46b8 movge r8, r7 + 17192: f1b8 0f00 cmp.w r8, #0 + 17196: f340 80a4 ble.w 172e2 + 1719a: 6828 ldr r0, [r5, #0] + 1719c: f10d 0a10 add.w sl, sp, #16 + 171a0: ebc9 7189 rsb r1, r9, r9, lsl #30 + 171a4: ebca 0181 rsb r1, sl, r1, lsl #2 + 171a8: f8cd a00c str.w sl, [sp, #12] + 171ac: 4682 mov sl, r0 + 171ae: 3108 adds r1, #8 + 171b0: 6824 ldr r4, [r4, #0] + 171b2: 9102 str r1, [sp, #8] + 171b4: f1c9 0101 rsb r1, r9, #1 + 171b8: 2200 movs r2, #0 + 171ba: 2300 movs r3, #0 + 171bc: 9400 str r4, [sp, #0] + 171be: f10d 0c0c add.w ip, sp, #12 + 171c2: f04f 0e00 mov.w lr, #0 + 171c6: 9101 str r1, [sp, #4] + 171c8: 45f1 cmp r9, lr + 171ca: bfc3 ittte gt + 171cc: 2000 movgt r0, #0 + 171ce: 4607 movgt r7, r0 + 171d0: 4671 movgt r1, lr + 171d2: 9f01 ldrle r7, [sp, #4] + 171d4: bfde ittt le + 171d6: 9802 ldrle r0, [sp, #8] + 171d8: 4477 addle r7, lr + 171da: f109 31ff addle.w r1, r9, #4294967295 + 171de: ebc7 070b rsb r7, r7, fp + 171e2: bfd8 it le + 171e4: 4460 addle r0, ip + 171e6: 42b9 cmp r1, r7 + 171e8: 9c00 ldr r4, [sp, #0] + 171ea: bfb8 it lt + 171ec: 1c4f addlt r7, r1, #1 + 171ee: 2f00 cmp r7, #0 + 171f0: 4420 add r0, r4 + 171f2: eb0a 0481 add.w r4, sl, r1, lsl #2 + 171f6: dd09 ble.n 1720c + 171f8: 2100 movs r1, #0 + 171fa: f850 5b04 ldr.w r5, [r0], #4 + 171fe: f854 6904 ldr.w r6, [r4], #-4 + 17202: 3101 adds r1, #1 + 17204: 42b9 cmp r1, r7 + 17206: fbe5 2306 umlal r2, r3, r5, r6 + 1720a: d1f6 bne.n 171fa + 1720c: 0f11 lsrs r1, r2, #28 + 1720e: f10e 0e01 add.w lr, lr, #1 + 17212: ea41 1103 orr.w r1, r1, r3, lsl #4 + 17216: f022 4470 bic.w r4, r2, #4026531840 ; 0xf0000000 + 1721a: 0f18 lsrs r0, r3, #28 + 1721c: 45c6 cmp lr, r8 + 1721e: 460a mov r2, r1 + 17220: f84c 4f04 str.w r4, [ip, #4]! + 17224: 4603 mov r3, r0 + 17226: d1cf bne.n 171c8 + 17228: f8dd 4838 ldr.w r4, [sp, #2104] ; 0x838 + 1722c: f8dd 1838 ldr.w r1, [sp, #2104] ; 0x838 + 17230: f8dd a00c ldr.w sl, [sp, #12] + 17234: 68e0 ldr r0, [r4, #12] + 17236: 6824 ldr r4, [r4, #0] + 17238: f8c1 8000 str.w r8, [r1] + 1723c: 2300 movs r3, #0 + 1723e: 461a mov r2, r3 + 17240: f85a 1003 ldr.w r1, [sl, r3] + 17244: 3201 adds r2, #1 + 17246: 4590 cmp r8, r2 + 17248: 50c1 str r1, [r0, r3] + 1724a: f103 0304 add.w r3, r3, #4 + 1724e: daf7 bge.n 17240 + 17250: ea28 72e8 bic.w r2, r8, r8, asr #31 + 17254: 3201 adds r2, #1 + 17256: 4613 mov r3, r2 + 17258: eb00 0282 add.w r2, r0, r2, lsl #2 + 1725c: 42a3 cmp r3, r4 + 1725e: bfb8 it lt + 17260: 2100 movlt r1, #0 + 17262: da04 bge.n 1726e + 17264: 3301 adds r3, #1 + 17266: 42a3 cmp r3, r4 + 17268: f842 1b04 str.w r1, [r2], #4 + 1726c: d1fa bne.n 17264 + 1726e: f1b8 0f00 cmp.w r8, #0 + 17272: dd34 ble.n 172de + 17274: f108 4380 add.w r3, r8, #1073741824 ; 0x40000000 + 17278: 3b01 subs r3, #1 + 1727a: f850 1023 ldr.w r1, [r0, r3, lsl #2] + 1727e: 009a lsls r2, r3, #2 + 17280: 3204 adds r2, #4 + 17282: 4643 mov r3, r8 + 17284: 4410 add r0, r2 + 17286: b119 cbz r1, 17290 + 17288: e014 b.n 172b4 + 1728a: f850 2c04 ldr.w r2, [r0, #-4] + 1728e: b972 cbnz r2, 172ae + 17290: 3b01 subs r3, #1 + 17292: f1a0 0004 sub.w r0, r0, #4 + 17296: d1f8 bne.n 1728a + 17298: f8dd 4838 ldr.w r4, [sp, #2104] ; 0x838 + 1729c: 6023 str r3, [r4, #0] + 1729e: f8dd 4838 ldr.w r4, [sp, #2104] ; 0x838 + 172a2: 2000 movs r0, #0 + 172a4: 60a0 str r0, [r4, #8] + 172a6: f60d 0d14 addw sp, sp, #2068 ; 0x814 + 172aa: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 172ae: f8dd 4838 ldr.w r4, [sp, #2104] ; 0x838 + 172b2: 6023 str r3, [r4, #0] + 172b4: 2000 movs r0, #0 + 172b6: f60d 0d14 addw sp, sp, #2068 ; 0x814 + 172ba: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 172be: f8dd 0838 ldr.w r0, [sp, #2104] ; 0x838 + 172c2: f8dd 1838 ldr.w r1, [sp, #2104] ; 0x838 + 172c6: 3004 adds r0, #4 + 172c8: 310c adds r1, #12 + 172ca: 463a mov r2, r7 + 172cc: f7ff fa80 bl 167d0 + 172d0: 2800 cmp r0, #0 + 172d2: f43f af55 beq.w 17180 + 172d6: f60d 0d14 addw sp, sp, #2068 ; 0x814 + 172da: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 172de: d0de beq.n 1729e + 172e0: e7e8 b.n 172b4 + 172e2: f8dd 1838 ldr.w r1, [sp, #2104] ; 0x838 + 172e6: bf08 it eq + 172e8: f10d 0a10 addeq.w sl, sp, #16 + 172ec: 680c ldr r4, [r1, #0] + 172ee: 68c8 ldr r0, [r1, #12] + 172f0: f8c1 8000 str.w r8, [r1] + 172f4: d0a2 beq.n 1723c + 172f6: 4602 mov r2, r0 + 172f8: 2300 movs r3, #0 + 172fa: e7af b.n 1725c + +000172fc : + 172fc: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 17300: f5b3 7f00 cmp.w r3, #512 ; 0x200 + 17304: b089 sub sp, #36 ; 0x24 + 17306: 4698 mov r8, r3 + 17308: 460c mov r4, r1 + 1730a: 9203 str r2, [sp, #12] + 1730c: 4605 mov r5, r0 + 1730e: da06 bge.n 1731e + 17310: 6803 ldr r3, [r0, #0] + 17312: 680a ldr r2, [r1, #0] + 17314: 4293 cmp r3, r2 + 17316: bfa8 it ge + 17318: 4613 movge r3, r2 + 1731a: 2bff cmp r3, #255 ; 0xff + 1731c: dd75 ble.n 1740a + 1731e: a804 add r0, sp, #16 + 17320: 4641 mov r1, r8 + 17322: f7ff f915 bl 16550 + 17326: 2800 cmp r0, #0 + 17328: d168 bne.n 173fc + 1732a: f8d5 a000 ldr.w sl, [r5] + 1732e: f8cd 8010 str.w r8, [sp, #16] + 17332: f1ba 0f00 cmp.w sl, #0 + 17336: dd40 ble.n 173ba + 17338: 4684 mov ip, r0 + 1733a: 9807 ldr r0, [sp, #28] + 1733c: 68eb ldr r3, [r5, #12] + 1733e: 4686 mov lr, r0 + 17340: f8d4 b000 ldr.w fp, [r4] + 17344: 68e4 ldr r4, [r4, #12] + 17346: f1a3 0904 sub.w r9, r3, #4 + 1734a: 9402 str r4, [sp, #8] + 1734c: ebcc 0708 rsb r7, ip, r8 + 17350: 455f cmp r7, fp + 17352: bfa8 it ge + 17354: 465f movge r7, fp + 17356: 2f00 cmp r7, #0 + 17358: f859 0f04 ldr.w r0, [r9, #4]! + 1735c: 4673 mov r3, lr + 1735e: f04f 0200 mov.w r2, #0 + 17362: dd4e ble.n 17402 + 17364: 4614 mov r4, r2 + 17366: 4616 mov r6, r2 + 17368: 4671 mov r1, lr + 1736a: 4652 mov r2, sl + 1736c: 46e2 mov sl, ip + 1736e: 46bc mov ip, r7 + 17370: 9d02 ldr r5, [sp, #8] + 17372: f855 3b04 ldr.w r3, [r5], #4 + 17376: 2700 movs r7, #0 + 17378: fbe3 6700 umlal r6, r7, r3, r0 + 1737c: 680b ldr r3, [r1, #0] + 1737e: 3401 adds r4, #1 + 17380: 18f6 adds r6, r6, r3 + 17382: f147 0700 adc.w r7, r7, #0 + 17386: f026 4370 bic.w r3, r6, #4026531840 ; 0xf0000000 + 1738a: 4564 cmp r4, ip + 1738c: ea4f 7616 mov.w r6, r6, lsr #28 + 17390: f841 3b04 str.w r3, [r1], #4 + 17394: ea46 1607 orr.w r6, r6, r7, lsl #4 + 17398: d1eb bne.n 17372 + 1739a: 4667 mov r7, ip + 1739c: 46d4 mov ip, sl + 1739e: 4692 mov sl, r2 + 173a0: 4632 mov r2, r6 + 173a2: eb0e 0387 add.w r3, lr, r7, lsl #2 + 173a6: 4467 add r7, ip + 173a8: 45b8 cmp r8, r7 + 173aa: f10c 0c01 add.w ip, ip, #1 + 173ae: bfc8 it gt + 173b0: 601a strgt r2, [r3, #0] + 173b2: 45d4 cmp ip, sl + 173b4: f10e 0e04 add.w lr, lr, #4 + 173b8: d1c8 bne.n 1734c + 173ba: f1b8 0f00 cmp.w r8, #0 + 173be: dd31 ble.n 17424 + 173c0: f108 4380 add.w r3, r8, #1073741824 ; 0x40000000 + 173c4: 9a07 ldr r2, [sp, #28] + 173c6: 3b01 subs r3, #1 + 173c8: f852 0023 ldr.w r0, [r2, r3, lsl #2] + 173cc: 0099 lsls r1, r3, #2 + 173ce: b968 cbnz r0, 173ec + 173d0: 3104 adds r1, #4 + 173d2: 4643 mov r3, r8 + 173d4: 440a add r2, r1 + 173d6: e002 b.n 173de + 173d8: f852 1c04 ldr.w r1, [r2, #-4] + 173dc: b999 cbnz r1, 17406 + 173de: 3b01 subs r3, #1 + 173e0: f1a2 0204 sub.w r2, r2, #4 + 173e4: d1f8 bne.n 173d8 + 173e6: 9304 str r3, [sp, #16] + 173e8: 2300 movs r3, #0 + 173ea: 9306 str r3, [sp, #24] + 173ec: 9903 ldr r1, [sp, #12] + 173ee: a804 add r0, sp, #16 + 173f0: f7ff f89c bl 1652c + 173f4: a804 add r0, sp, #16 + 173f6: f7ff f851 bl 1649c + 173fa: 2000 movs r0, #0 + 173fc: b009 add sp, #36 ; 0x24 + 173fe: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 17402: 4617 mov r7, r2 + 17404: e7cf b.n 173a6 + 17406: 9304 str r3, [sp, #16] + 17408: e7f0 b.n 173ec + 1740a: 9b03 ldr r3, [sp, #12] + 1740c: 460a mov r2, r1 + 1740e: e88d 0108 stmia.w sp, {r3, r8} + 17412: f100 010c add.w r1, r0, #12 + 17416: f104 030c add.w r3, r4, #12 + 1741a: f7ff fea1 bl 17160 + 1741e: b009 add sp, #36 ; 0x24 + 17420: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 17424: d0e0 beq.n 173e8 + 17426: e7e1 b.n 173ec + +00017428 : + 17428: b5f8 push {r3, r4, r5, r6, r7, lr} + 1742a: 4614 mov r4, r2 + 1742c: 6887 ldr r7, [r0, #8] + 1742e: 688e ldr r6, [r1, #8] + 17430: 680b ldr r3, [r1, #0] + 17432: 1bbe subs r6, r7, r6 + 17434: 6807 ldr r7, [r0, #0] + 17436: bf18 it ne + 17438: 2601 movne r6, #1 + 1743a: 443b add r3, r7 + 1743c: 3301 adds r3, #1 + 1743e: f7ff ff5d bl 172fc + 17442: 6823 ldr r3, [r4, #0] + 17444: 2b00 cmp r3, #0 + 17446: bfd8 it le + 17448: 2600 movle r6, #0 + 1744a: 60a6 str r6, [r4, #8] + 1744c: bdf8 pop {r3, r4, r5, r6, r7, pc} + 1744e: bf00 nop + +00017450 : + 17450: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 17454: b089 sub sp, #36 ; 0x24 + 17456: 4604 mov r4, r0 + 17458: a804 add r0, sp, #16 + 1745a: 468a mov sl, r1 + 1745c: 9203 str r2, [sp, #12] + 1745e: f7ff f801 bl 16464 + 17462: 2800 cmp r0, #0 + 17464: d137 bne.n 174d6 + 17466: f8da 9000 ldr.w r9, [sl] + 1746a: f1b9 0f00 cmp.w r9, #0 + 1746e: d135 bne.n 174dc + 17470: f104 080c add.w r8, r4, #12 + 17474: f10a 070c add.w r7, sl, #12 + 17478: e020 b.n 174bc + 1747a: a804 add r0, sp, #16 + 1747c: 9903 ldr r1, [sp, #12] + 1747e: 4602 mov r2, r0 + 17480: f7ff ffd2 bl 17428 + 17484: 4605 mov r5, r0 + 17486: bb10 cbnz r0, 174ce + 17488: 4620 mov r0, r4 + 1748a: a904 add r1, sp, #16 + 1748c: 4622 mov r2, r4 + 1748e: f7ff fa3d bl 1690c + 17492: 4605 mov r5, r0 + 17494: b9d8 cbnz r0, 174ce + 17496: f8d4 b000 ldr.w fp, [r4] + 1749a: f8da 6000 ldr.w r6, [sl] + 1749e: 4658 mov r0, fp + 174a0: 4632 mov r2, r6 + 174a2: 4641 mov r1, r8 + 174a4: 463b mov r3, r7 + 174a6: f7ff f87b bl 165a0 + 174aa: 3001 adds r0, #1 + 174ac: d00f beq.n 174ce + 174ae: 9400 str r4, [sp, #0] + 174b0: 4658 mov r0, fp + 174b2: 4632 mov r2, r6 + 174b4: 4641 mov r1, r8 + 174b6: 463b mov r3, r7 + 174b8: f7ff fc9a bl 16df0 + 174bc: 4620 mov r0, r4 + 174be: 4649 mov r1, r9 + 174c0: aa04 add r2, sp, #16 + 174c2: 4623 mov r3, r4 + 174c4: f7ff fb4e bl 16b64 + 174c8: 4605 mov r5, r0 + 174ca: 2800 cmp r0, #0 + 174cc: d0d5 beq.n 1747a + 174ce: a804 add r0, sp, #16 + 174d0: f7fe ffe4 bl 1649c + 174d4: 4628 mov r0, r5 + 174d6: b009 add sp, #36 ; 0x24 + 174d8: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 174dc: f109 4380 add.w r3, r9, #1073741824 ; 0x40000000 + 174e0: f8da 100c ldr.w r1, [sl, #12] + 174e4: f109 39ff add.w r9, r9, #4294967295 + 174e8: 3b01 subs r3, #1 + 174ea: ebc9 09c9 rsb r9, r9, r9, lsl #3 + 174ee: f851 3023 ldr.w r3, [r1, r3, lsl #2] + 174f2: ea4f 0289 mov.w r2, r9, lsl #2 + 174f6: 4691 mov r9, r2 + 174f8: b123 cbz r3, 17504 + 174fa: 085b lsrs r3, r3, #1 + 174fc: f109 0901 add.w r9, r9, #1 + 17500: d1fb bne.n 174fa + 17502: e7b5 b.n 17470 + 17504: 4691 mov r9, r2 + 17506: e7b3 b.n 17470 + +00017508 : + 17508: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 1750c: b091 sub sp, #68 ; 0x44 + 1750e: 4682 mov sl, r0 + 17510: a808 add r0, sp, #32 + 17512: 460f mov r7, r1 + 17514: 4614 mov r4, r2 + 17516: f8d1 b000 ldr.w fp, [r1] + 1751a: f7fe ffa3 bl 16464 + 1751e: b110 cbz r0, 17526 + 17520: b011 add sp, #68 ; 0x44 + 17522: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 17526: 4650 mov r0, sl + 17528: a908 add r1, sp, #32 + 1752a: f7ff f97b bl 16824 + 1752e: 2800 cmp r0, #0 + 17530: d1f6 bne.n 17520 + 17532: a808 add r0, sp, #32 + 17534: f10b 31ff add.w r1, fp, #4294967295 + 17538: f7ff f882 bl 16640 + 1753c: f1bb 6f00 cmp.w fp, #134217728 ; 0x8000000 + 17540: f200 8088 bhi.w 17654 + 17544: 9a08 ldr r2, [sp, #32] + 17546: 6823 ldr r3, [r4, #0] + 17548: a80c add r0, sp, #48 ; 0x30 + 1754a: 18d1 adds r1, r2, r3 + 1754c: 3101 adds r1, #1 + 1754e: f7fe ffff bl 16550 + 17552: 4605 mov r5, r0 + 17554: 2800 cmp r0, #0 + 17556: f040 8093 bne.w 17680 + 1755a: 9b08 ldr r3, [sp, #32] + 1755c: f8d4 e000 ldr.w lr, [r4] + 17560: 2b00 cmp r3, #0 + 17562: eb03 020e add.w r2, r3, lr + 17566: f102 0901 add.w r9, r2, #1 + 1756a: 9203 str r2, [sp, #12] + 1756c: f8cd 9030 str.w r9, [sp, #48] ; 0x30 + 17570: dd4f ble.n 17612 + 17572: 4684 mov ip, r0 + 17574: ea4f 008b mov.w r0, fp, lsl #2 + 17578: 68e1 ldr r1, [r4, #12] + 1757a: 009c lsls r4, r3, #2 + 1757c: 4603 mov r3, r0 + 1757e: 9a0f ldr r2, [sp, #60] ; 0x3c + 17580: 9d0b ldr r5, [sp, #44] ; 0x2c + 17582: 4413 add r3, r2 + 17584: 4401 add r1, r0 + 17586: 46d8 mov r8, fp + 17588: f8cd b010 str.w fp, [sp, #16] + 1758c: f8cd 9014 str.w r9, [sp, #20] + 17590: f8cd a018 str.w sl, [sp, #24] + 17594: 9707 str r7, [sp, #28] + 17596: 46a1 mov r9, r4 + 17598: 469b mov fp, r3 + 1759a: 468a mov sl, r1 + 1759c: 462f mov r7, r5 + 1759e: eb02 028e add.w r2, r2, lr, lsl #2 + 175a2: 9202 str r2, [sp, #8] + 175a4: 45c6 cmp lr, r8 + 175a6: f857 600c ldr.w r6, [r7, ip] + 175aa: 4641 mov r1, r8 + 175ac: ebcc 040a rsb r4, ip, sl + 175b0: dd6d ble.n 1768e + 175b2: 2200 movs r2, #0 + 175b4: 4613 mov r3, r2 + 175b6: 4658 mov r0, fp + 175b8: 4652 mov r2, sl + 175ba: 465d mov r5, fp + 175bc: 469a mov sl, r3 + 175be: f854 3b04 ldr.w r3, [r4], #4 + 175c2: f04f 0b00 mov.w fp, #0 + 175c6: fbe3 ab06 umlal sl, fp, r3, r6 + 175ca: 6803 ldr r3, [r0, #0] + 175cc: 3101 adds r1, #1 + 175ce: eb1a 0a03 adds.w sl, sl, r3 + 175d2: f14b 0b00 adc.w fp, fp, #0 + 175d6: f02a 4370 bic.w r3, sl, #4026531840 ; 0xf0000000 + 175da: 4571 cmp r1, lr + 175dc: ea4f 7a1a mov.w sl, sl, lsr #28 + 175e0: f840 3b04 str.w r3, [r0], #4 + 175e4: ea4a 1a0b orr.w sl, sl, fp, lsl #4 + 175e8: d1e9 bne.n 175be + 175ea: 4653 mov r3, sl + 175ec: 46ab mov fp, r5 + 175ee: 4692 mov sl, r2 + 175f0: 461a mov r2, r3 + 175f2: 9b02 ldr r3, [sp, #8] + 175f4: 4463 add r3, ip + 175f6: f10c 0c04 add.w ip, ip, #4 + 175fa: 45cc cmp ip, r9 + 175fc: 601a str r2, [r3, #0] + 175fe: f108 38ff add.w r8, r8, #4294967295 + 17602: d1cf bne.n 175a4 + 17604: f8dd b010 ldr.w fp, [sp, #16] + 17608: f8dd 9014 ldr.w r9, [sp, #20] + 1760c: f8dd a018 ldr.w sl, [sp, #24] + 17610: 9f07 ldr r7, [sp, #28] + 17612: f1b9 0f00 cmp.w r9, #0 + 17616: dd6c ble.n 176f2 + 17618: f109 4280 add.w r2, r9, #1073741824 ; 0x40000000 + 1761c: 9b0f ldr r3, [sp, #60] ; 0x3c + 1761e: 3a01 subs r2, #1 + 17620: f853 2022 ldr.w r2, [r3, r2, lsl #2] + 17624: b972 cbnz r2, 17644 + 17626: 9a03 ldr r2, [sp, #12] + 17628: eb03 0382 add.w r3, r3, r2, lsl #2 + 1762c: e003 b.n 17636 + 1762e: f853 2d04 ldr.w r2, [r3, #-4]! + 17632: 2a00 cmp r2, #0 + 17634: d15a bne.n 176ec + 17636: f1b9 0901 subs.w r9, r9, #1 + 1763a: d1f8 bne.n 1762e + 1763c: f8cd 9030 str.w r9, [sp, #48] ; 0x30 + 17640: 2300 movs r3, #0 + 17642: 930e str r3, [sp, #56] ; 0x38 + 17644: a80c add r0, sp, #48 ; 0x30 + 17646: a908 add r1, sp, #32 + 17648: f7fe ff70 bl 1652c + 1764c: a80c add r0, sp, #48 ; 0x30 + 1764e: f7fe ff25 bl 1649c + 17652: e006 b.n 17662 + 17654: a808 add r0, sp, #32 + 17656: 4621 mov r1, r4 + 17658: 4602 mov r2, r0 + 1765a: f7ff fee5 bl 17428 + 1765e: 4605 mov r5, r0 + 17660: b970 cbnz r0, 17680 + 17662: f10b 0b01 add.w fp, fp, #1 + 17666: 4659 mov r1, fp + 17668: a808 add r0, sp, #32 + 1766a: f7fe ffe9 bl 16640 + 1766e: ebcb 01cb rsb r1, fp, fp, lsl #3 + 17672: 0089 lsls r1, r1, #2 + 17674: 4650 mov r0, sl + 17676: 4652 mov r2, sl + 17678: f7ff fa04 bl 16a84 + 1767c: 4605 mov r5, r0 + 1767e: b148 cbz r0, 17694 + 17680: a808 add r0, sp, #32 + 17682: f7fe ff0b bl 1649c + 17686: 4628 mov r0, r5 + 17688: b011 add sp, #68 ; 0x44 + 1768a: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 1768e: 465b mov r3, fp + 17690: 2200 movs r2, #0 + 17692: e7b0 b.n 175f6 + 17694: a808 add r0, sp, #32 + 17696: 4639 mov r1, r7 + 17698: 4602 mov r2, r0 + 1769a: 465b mov r3, fp + 1769c: f7ff fe2e bl 172fc + 176a0: 4605 mov r5, r0 + 176a2: 2800 cmp r0, #0 + 176a4: d1ec bne.n 17680 + 176a6: 4650 mov r0, sl + 176a8: a908 add r1, sp, #32 + 176aa: 4652 mov r2, sl + 176ac: f7ff fc4e bl 16f4c + 176b0: 4605 mov r5, r0 + 176b2: 2800 cmp r0, #0 + 176b4: d1e4 bne.n 17680 + 176b6: f8da 3008 ldr.w r3, [sl, #8] + 176ba: 2b01 cmp r3, #1 + 176bc: d01b beq.n 176f6 + 176be: f107 040c add.w r4, r7, #12 + 176c2: 46a0 mov r8, r4 + 176c4: 4654 mov r4, sl + 176c6: f10a 060c add.w r6, sl, #12 + 176ca: 4620 mov r0, r4 + 176cc: 4639 mov r1, r7 + 176ce: f7fe ff99 bl 16604 + 176d2: 3001 adds r0, #1 + 176d4: d0d4 beq.n 17680 + 176d6: 6820 ldr r0, [r4, #0] + 176d8: 683a ldr r2, [r7, #0] + 176da: 4631 mov r1, r6 + 176dc: 9400 str r4, [sp, #0] + 176de: 4643 mov r3, r8 + 176e0: f7ff fb86 bl 16df0 + 176e4: 2800 cmp r0, #0 + 176e6: d0f0 beq.n 176ca + 176e8: 4605 mov r5, r0 + 176ea: e7c9 b.n 17680 + 176ec: f8cd 9030 str.w r9, [sp, #48] ; 0x30 + 176f0: e7a8 b.n 17644 + 176f2: d0a5 beq.n 17640 + 176f4: e7a6 b.n 17644 + 176f6: 9809 ldr r0, [sp, #36] ; 0x24 + 176f8: 950a str r5, [sp, #40] ; 0x28 + 176fa: 2800 cmp r0, #0 + 176fc: 9a0b ldr r2, [sp, #44] ; 0x2c + 176fe: dd07 ble.n 17710 + 17700: 4611 mov r1, r2 + 17702: 462b mov r3, r5 + 17704: 462c mov r4, r5 + 17706: 3301 adds r3, #1 + 17708: 4283 cmp r3, r0 + 1770a: f841 4b04 str.w r4, [r1], #4 + 1770e: d1fa bne.n 17706 + 17710: 2301 movs r3, #1 + 17712: 6013 str r3, [r2, #0] + 17714: 4659 mov r1, fp + 17716: a808 add r0, sp, #32 + 17718: 9308 str r3, [sp, #32] + 1771a: f7ff f8c1 bl 168a0 + 1771e: 2800 cmp r0, #0 + 17720: d1e2 bne.n 176e8 + 17722: 4650 mov r0, sl + 17724: a908 add r1, sp, #32 + 17726: 4652 mov r2, sl + 17728: f7ff fbdc bl 16ee4 + 1772c: 2800 cmp r0, #0 + 1772e: d0c6 beq.n 176be + 17730: 4605 mov r5, r0 + 17732: e7a5 b.n 17680 + +00017734 : + 17734: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 17738: 460e mov r6, r1 + 1773a: 6809 ldr r1, [r1, #0] + 1773c: f5ad 7d0f sub.w sp, sp, #572 ; 0x23c + 17740: 4683 mov fp, r0 + 17742: 4691 mov r9, r2 + 17744: 9304 str r3, [sp, #16] + 17746: 2900 cmp r1, #0 + 17748: d049 beq.n 177de + 1774a: f101 4380 add.w r3, r1, #1073741824 ; 0x40000000 + 1774e: 68f2 ldr r2, [r6, #12] + 17750: 3b01 subs r3, #1 + 17752: 3901 subs r1, #1 + 17754: f852 3023 ldr.w r3, [r2, r3, lsl #2] + 17758: ebc1 01c1 rsb r1, r1, r1, lsl #3 + 1775c: 008a lsls r2, r1, #2 + 1775e: b11b cbz r3, 17768 + 17760: 085b lsrs r3, r3, #1 + 17762: f102 0201 add.w r2, r2, #1 + 17766: d1fb bne.n 17760 + 17768: 2a07 cmp r2, #7 + 1776a: dd38 ble.n 177de + 1776c: 2a24 cmp r2, #36 ; 0x24 + 1776e: bfd8 it le + 17770: f04f 0803 movle.w r8, #3 + 17774: dc36 bgt.n 177e4 + 17776: a812 add r0, sp, #72 ; 0x48 + 17778: f7fe fe74 bl 16464 + 1777c: bb58 cbnz r0, 177d6 + 1777e: f108 31ff add.w r1, r8, #4294967295 + 17782: 2501 movs r5, #1 + 17784: fa05 f401 lsl.w r4, r5, r1 + 17788: fa05 f508 lsl.w r5, r5, r8 + 1778c: 42ac cmp r4, r5 + 1778e: 9103 str r1, [sp, #12] + 17790: da2f bge.n 177f2 + 17792: aa0e add r2, sp, #56 ; 0x38 + 17794: eb02 1204 add.w r2, r2, r4, lsl #4 + 17798: 9202 str r2, [sp, #8] + 1779a: 4617 mov r7, r2 + 1779c: 46a2 mov sl, r4 + 1779e: e003 b.n 177a8 + 177a0: f10a 0a01 add.w sl, sl, #1 + 177a4: 45aa cmp sl, r5 + 177a6: d024 beq.n 177f2 + 177a8: 4638 mov r0, r7 + 177aa: f7fe fe5b bl 16464 + 177ae: 3710 adds r7, #16 + 177b0: 2800 cmp r0, #0 + 177b2: d0f5 beq.n 177a0 + 177b4: 4554 cmp r4, sl + 177b6: 4683 mov fp, r0 + 177b8: bfb8 it lt + 177ba: 9f02 ldrlt r7, [sp, #8] + 177bc: da07 bge.n 177ce + 177be: 4638 mov r0, r7 + 177c0: 3401 adds r4, #1 + 177c2: f7fe fe6b bl 1649c + 177c6: 4554 cmp r4, sl + 177c8: f107 0710 add.w r7, r7, #16 + 177cc: d1f7 bne.n 177be + 177ce: a812 add r0, sp, #72 ; 0x48 + 177d0: f7fe fe64 bl 1649c + 177d4: 4658 mov r0, fp + 177d6: f50d 7d0f add.w sp, sp, #572 ; 0x23c + 177da: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 177de: f04f 0802 mov.w r8, #2 + 177e2: e7c8 b.n 17776 + 177e4: 2a8d cmp r2, #141 ; 0x8d + 177e6: bfb4 ite lt + 177e8: f04f 0804 movlt.w r8, #4 + 177ec: f04f 0805 movge.w r8, #5 + 177f0: e7c1 b.n 17776 + 177f2: a806 add r0, sp, #24 + 177f4: f7fe fe36 bl 16464 + 177f8: 4607 mov r7, r0 + 177fa: b1a0 cbz r0, 17826 + 177fc: a812 add r0, sp, #72 ; 0x48 + 177fe: f7fe fe4d bl 1649c + 17802: 42ac cmp r4, r5 + 17804: da0a bge.n 1781c + 17806: ab0e add r3, sp, #56 ; 0x38 + 17808: eb03 1604 add.w r6, r3, r4, lsl #4 + 1780c: 4630 mov r0, r6 + 1780e: 3401 adds r4, #1 + 17810: f7fe fe44 bl 1649c + 17814: 42ac cmp r4, r5 + 17816: f106 0610 add.w r6, r6, #16 + 1781a: d1f7 bne.n 1780c + 1781c: 4638 mov r0, r7 + 1781e: f50d 7d0f add.w sp, sp, #572 ; 0x23c + 17822: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 17826: f8d9 3000 ldr.w r3, [r9] + 1782a: a806 add r0, sp, #24 + 1782c: ebc3 01c3 rsb r1, r3, r3, lsl #3 + 17830: 00c9 lsls r1, r1, #3 + 17832: f7ff f8f7 bl 16a24 + 17836: 4607 mov r7, r0 + 17838: b118 cbz r0, 17842 + 1783a: a806 add r0, sp, #24 + 1783c: f7fe fe2e bl 1649c + 17840: e7dc b.n 177fc + 17842: f8d9 2000 ldr.w r2, [r9] + 17846: 2a00 cmp r2, #0 + 17848: f000 80ab beq.w 179a2 + 1784c: f109 0a0c add.w sl, r9, #12 + 17850: 4653 mov r3, sl + 17852: 9806 ldr r0, [sp, #24] + 17854: a909 add r1, sp, #36 ; 0x24 + 17856: f7fe fea3 bl 165a0 + 1785a: 3001 adds r0, #1 + 1785c: d07c beq.n 17958 + 1785e: a806 add r0, sp, #24 + 17860: 463b mov r3, r7 + 17862: 4649 mov r1, r9 + 17864: 4602 mov r2, r0 + 17866: f7ff fba5 bl 16fb4 + 1786a: 4607 mov r7, r0 + 1786c: 2800 cmp r0, #0 + 1786e: d1e4 bne.n 1783a + 17870: a80a add r0, sp, #40 ; 0x28 + 17872: f7fe fdf7 bl 16464 + 17876: 4607 mov r7, r0 + 17878: 2800 cmp r0, #0 + 1787a: d1de bne.n 1783a + 1787c: f8d9 2000 ldr.w r2, [r9] + 17880: 2a00 cmp r2, #0 + 17882: f000 8088 beq.w 17996 + 17886: 4659 mov r1, fp + 17888: 4653 mov r3, sl + 1788a: f851 0b0c ldr.w r0, [r1], #12 + 1788e: f7fe fe87 bl 165a0 + 17892: 3001 adds r0, #1 + 17894: 4658 mov r0, fp + 17896: d16c bne.n 17972 + 17898: a90a add r1, sp, #40 ; 0x28 + 1789a: f7fe ffc3 bl 16824 + 1789e: 4607 mov r7, r0 + 178a0: 2800 cmp r0, #0 + 178a2: d17a bne.n 1799a + 178a4: 9a0c ldr r2, [sp, #48] ; 0x30 + 178a6: f8d9 3008 ldr.w r3, [r9, #8] + 178aa: 429a cmp r2, r3 + 178ac: d06b beq.n 17986 + 178ae: 4648 mov r0, r9 + 178b0: a90a add r1, sp, #40 ; 0x28 + 178b2: aa12 add r2, sp, #72 ; 0x48 + 178b4: f7ff fb16 bl 16ee4 + 178b8: 4607 mov r7, r0 + 178ba: a80a add r0, sp, #40 ; 0x28 + 178bc: f7fe fdee bl 1649c + 178c0: 2f00 cmp r7, #0 + 178c2: d1ba bne.n 1783a + 178c4: 0123 lsls r3, r4, #4 + 178c6: f10d 0b38 add.w fp, sp, #56 ; 0x38 + 178ca: 449b add fp, r3 + 178cc: 4659 mov r1, fp + 178ce: a812 add r0, sp, #72 ; 0x48 + 178d0: 9302 str r3, [sp, #8] + 178d2: f7fe ffa7 bl 16824 + 178d6: 4607 mov r7, r0 + 178d8: 2800 cmp r0, #0 + 178da: d1ae bne.n 1783a + 178dc: f10b 030c add.w r3, fp, #12 + 178e0: 9405 str r4, [sp, #20] + 178e2: 461c mov r4, r3 + 178e4: 4633 mov r3, r6 + 178e6: 4682 mov sl, r0 + 178e8: 465e mov r6, fp + 178ea: 469b mov fp, r3 + 178ec: 462f mov r7, r5 + 178ee: 9d03 ldr r5, [sp, #12] + 178f0: 4621 mov r1, r4 + 178f2: 6830 ldr r0, [r6, #0] + 178f4: 4632 mov r2, r6 + 178f6: f7fe fed9 bl 166ac + 178fa: 2100 movs r1, #0 + 178fc: f10a 0a01 add.w sl, sl, #1 + 17900: 60b1 str r1, [r6, #8] + 17902: 2800 cmp r0, #0 + 17904: d13b bne.n 1797e + 17906: 4630 mov r0, r6 + 17908: 4649 mov r1, r9 + 1790a: aa06 add r2, sp, #24 + 1790c: f7ff fdfc bl 17508 + 17910: 2800 cmp r0, #0 + 17912: d134 bne.n 1797e + 17914: 4555 cmp r5, sl + 17916: dceb bgt.n 178f0 + 17918: 9c05 ldr r4, [sp, #20] + 1791a: 465e mov r6, fp + 1791c: f104 0b01 add.w fp, r4, #1 + 17920: 45bb cmp fp, r7 + 17922: 463d mov r5, r7 + 17924: da40 bge.n 179a8 + 17926: 9b02 ldr r3, [sp, #8] + 17928: a80e add r0, sp, #56 ; 0x38 + 1792a: 4418 add r0, r3 + 1792c: e008 b.n 17940 + 1792e: 4638 mov r0, r7 + 17930: 4649 mov r1, r9 + 17932: aa06 add r2, sp, #24 + 17934: f7ff fde8 bl 17508 + 17938: b960 cbnz r0, 17954 + 1793a: 45ab cmp fp, r5 + 1793c: d034 beq.n 179a8 + 1793e: 4638 mov r0, r7 + 17940: f100 0710 add.w r7, r0, #16 + 17944: 463a mov r2, r7 + 17946: a912 add r1, sp, #72 ; 0x48 + 17948: f7ff fd6e bl 17428 + 1794c: f10b 0b01 add.w fp, fp, #1 + 17950: 2800 cmp r0, #0 + 17952: d0ec beq.n 1792e + 17954: 4607 mov r7, r0 + 17956: e770 b.n 1783a + 17958: 9a07 ldr r2, [sp, #28] + 1795a: 9708 str r7, [sp, #32] + 1795c: 2a00 cmp r2, #0 + 1795e: 9706 str r7, [sp, #24] + 17960: 9b09 ldr r3, [sp, #36] ; 0x24 + 17962: dd85 ble.n 17870 + 17964: 4639 mov r1, r7 + 17966: 3701 adds r7, #1 + 17968: 4297 cmp r7, r2 + 1796a: f843 1b04 str.w r1, [r3], #4 + 1796e: d1fa bne.n 17966 + 17970: e77e b.n 17870 + 17972: 463a mov r2, r7 + 17974: 4649 mov r1, r9 + 17976: ab0a add r3, sp, #40 ; 0x28 + 17978: f7ff fb1c bl 16fb4 + 1797c: e78f b.n 1789e + 1797e: 463d mov r5, r7 + 17980: 9c05 ldr r4, [sp, #20] + 17982: 4607 mov r7, r0 + 17984: e759 b.n 1783a + 17986: a80a add r0, sp, #40 ; 0x28 + 17988: a912 add r1, sp, #72 ; 0x48 + 1798a: f7fe fdcf bl 1652c + 1798e: a80a add r0, sp, #40 ; 0x28 + 17990: f7fe fd84 bl 1649c + 17994: e796 b.n 178c4 + 17996: f06f 0702 mvn.w r7, #2 + 1799a: a80a add r0, sp, #40 ; 0x28 + 1799c: f7fe fd7e bl 1649c + 179a0: e74b b.n 1783a + 179a2: f06f 0702 mvn.w r7, #2 + 179a6: e748 b.n 1783a + 179a8: a80a add r0, sp, #40 ; 0x28 + 179aa: f7fe fd5b bl 16464 + 179ae: 4607 mov r7, r0 + 179b0: 2800 cmp r0, #0 + 179b2: f47f af42 bne.w 1783a + 179b6: 9a0b ldr r2, [sp, #44] ; 0x2c + 179b8: 990d ldr r1, [sp, #52] ; 0x34 + 179ba: 2a00 cmp r2, #0 + 179bc: 900c str r0, [sp, #48] ; 0x30 + 179be: bfc8 it gt + 179c0: 460b movgt r3, r1 + 179c2: dd04 ble.n 179ce + 179c4: 3701 adds r7, #1 + 179c6: 4297 cmp r7, r2 + 179c8: f843 0b04 str.w r0, [r3], #4 + 179cc: d1fa bne.n 179c4 + 179ce: 2201 movs r2, #1 + 179d0: 6837 ldr r7, [r6, #0] + 179d2: 9202 str r2, [sp, #8] + 179d4: 600a str r2, [r1, #0] + 179d6: 920a str r2, [sp, #40] ; 0x28 + 179d8: 462a mov r2, r5 + 179da: 2300 movs r3, #0 + 179dc: 4625 mov r5, r4 + 179de: 469a mov sl, r3 + 179e0: 461c mov r4, r3 + 179e2: 4693 mov fp, r2 + 179e4: 3f01 subs r7, #1 + 179e6: 9303 str r3, [sp, #12] + 179e8: 9902 ldr r1, [sp, #8] + 179ea: 3901 subs r1, #1 + 179ec: 9102 str r1, [sp, #8] + 179ee: d108 bne.n 17a02 + 179f0: 1c7a adds r2, r7, #1 + 179f2: d052 beq.n 17a9a + 179f4: 68f2 ldr r2, [r6, #12] + 179f6: 211c movs r1, #28 + 179f8: f852 2027 ldr.w r2, [r2, r7, lsl #2] + 179fc: 9102 str r1, [sp, #8] + 179fe: 9203 str r2, [sp, #12] + 17a00: 3f01 subs r7, #1 + 17a02: 9903 ldr r1, [sp, #12] + 17a04: f3c1 62c0 ubfx r2, r1, #27, #1 + 17a08: 0049 lsls r1, r1, #1 + 17a0a: 9103 str r1, [sp, #12] + 17a0c: ea52 0103 orrs.w r1, r2, r3 + 17a10: d02f beq.n 17a72 + 17a12: f082 0101 eor.w r1, r2, #1 + 17a16: 2b01 cmp r3, #1 + 17a18: bf14 ite ne + 17a1a: 2300 movne r3, #0 + 17a1c: f001 0301 andeq.w r3, r1, #1 + 17a20: bb4b cbnz r3, 17a76 + 17a22: 3401 adds r4, #1 + 17a24: ebc4 0108 rsb r1, r4, r8 + 17a28: 408a lsls r2, r1 + 17a2a: 45a0 cmp r8, r4 + 17a2c: ea4a 0a02 orr.w sl, sl, r2 + 17a30: bf18 it ne + 17a32: 2302 movne r3, #2 + 17a34: d1d8 bne.n 179e8 + 17a36: 461c mov r4, r3 + 17a38: e007 b.n 17a4a + 17a3a: a80a add r0, sp, #40 ; 0x28 + 17a3c: 4649 mov r1, r9 + 17a3e: aa06 add r2, sp, #24 + 17a40: f7ff fd62 bl 17508 + 17a44: b958 cbnz r0, 17a5e + 17a46: 45a0 cmp r8, r4 + 17a48: dd4b ble.n 17ae2 + 17a4a: 980a ldr r0, [sp, #40] ; 0x28 + 17a4c: a90d add r1, sp, #52 ; 0x34 + 17a4e: aa0a add r2, sp, #40 ; 0x28 + 17a50: f7fe fe2c bl 166ac + 17a54: 2300 movs r3, #0 + 17a56: 3401 adds r4, #1 + 17a58: 930c str r3, [sp, #48] ; 0x30 + 17a5a: 2800 cmp r0, #0 + 17a5c: d0ed beq.n 17a3a + 17a5e: 462c mov r4, r5 + 17a60: 4603 mov r3, r0 + 17a62: 465d mov r5, fp + 17a64: a80a add r0, sp, #40 ; 0x28 + 17a66: 9301 str r3, [sp, #4] + 17a68: f7fe fd18 bl 1649c + 17a6c: 9b01 ldr r3, [sp, #4] + 17a6e: 461f mov r7, r3 + 17a70: e6e3 b.n 1783a + 17a72: 460b mov r3, r1 + 17a74: e7b8 b.n 179e8 + 17a76: aa0a add r2, sp, #40 ; 0x28 + 17a78: 980a ldr r0, [sp, #40] ; 0x28 + 17a7a: a90d add r1, sp, #52 ; 0x34 + 17a7c: f7fe fe16 bl 166ac + 17a80: 2200 movs r2, #0 + 17a82: 920c str r2, [sp, #48] ; 0x30 + 17a84: 2800 cmp r0, #0 + 17a86: d1ea bne.n 17a5e + 17a88: a80a add r0, sp, #40 ; 0x28 + 17a8a: 4649 mov r1, r9 + 17a8c: aa06 add r2, sp, #24 + 17a8e: f7ff fd3b bl 17508 + 17a92: 2800 cmp r0, #0 + 17a94: d1e3 bne.n 17a5e + 17a96: 2301 movs r3, #1 + 17a98: e7a6 b.n 179e8 + 17a9a: 465a mov r2, fp + 17a9c: 46a3 mov fp, r4 + 17a9e: f1bb 0f00 cmp.w fp, #0 + 17aa2: 462c mov r4, r5 + 17aa4: 4615 mov r5, r2 + 17aa6: dd3f ble.n 17b28 + 17aa8: 2b02 cmp r3, #2 + 17aaa: d13d bne.n 17b28 + 17aac: 9e02 ldr r6, [sp, #8] + 17aae: 4637 mov r7, r6 + 17ab0: e00b b.n 17aca + 17ab2: a80a add r0, sp, #40 ; 0x28 + 17ab4: 4649 mov r1, r9 + 17ab6: aa06 add r2, sp, #24 + 17ab8: f7ff fd26 bl 17508 + 17abc: 2800 cmp r0, #0 + 17abe: d131 bne.n 17b24 + 17ac0: ea1a 0f05 tst.w sl, r5 + 17ac4: d121 bne.n 17b0a + 17ac6: 455e cmp r6, fp + 17ac8: da2e bge.n 17b28 + 17aca: 980a ldr r0, [sp, #40] ; 0x28 + 17acc: a90d add r1, sp, #52 ; 0x34 + 17ace: aa0a add r2, sp, #40 ; 0x28 + 17ad0: f7fe fdec bl 166ac + 17ad4: ea4f 0a4a mov.w sl, sl, lsl #1 + 17ad8: 3601 adds r6, #1 + 17ada: 970c str r7, [sp, #48] ; 0x30 + 17adc: 2800 cmp r0, #0 + 17ade: d0e8 beq.n 17ab2 + 17ae0: e020 b.n 17b24 + 17ae2: aa0e add r2, sp, #56 ; 0x38 + 17ae4: a80a add r0, sp, #40 ; 0x28 + 17ae6: eb02 110a add.w r1, r2, sl, lsl #4 + 17aea: 4602 mov r2, r0 + 17aec: f7ff fc9c bl 17428 + 17af0: 2800 cmp r0, #0 + 17af2: d1b4 bne.n 17a5e + 17af4: a80a add r0, sp, #40 ; 0x28 + 17af6: 4649 mov r1, r9 + 17af8: aa06 add r2, sp, #24 + 17afa: f7ff fd05 bl 17508 + 17afe: 2800 cmp r0, #0 + 17b00: d1ad bne.n 17a5e + 17b02: 4682 mov sl, r0 + 17b04: 2301 movs r3, #1 + 17b06: 4604 mov r4, r0 + 17b08: e76e b.n 179e8 + 17b0a: a80a add r0, sp, #40 ; 0x28 + 17b0c: a912 add r1, sp, #72 ; 0x48 + 17b0e: 4602 mov r2, r0 + 17b10: f7ff fc8a bl 17428 + 17b14: b930 cbnz r0, 17b24 + 17b16: a80a add r0, sp, #40 ; 0x28 + 17b18: 4649 mov r1, r9 + 17b1a: aa06 add r2, sp, #24 + 17b1c: f7ff fcf4 bl 17508 + 17b20: 2800 cmp r0, #0 + 17b22: d0d0 beq.n 17ac6 + 17b24: 4603 mov r3, r0 + 17b26: e79d b.n 17a64 + 17b28: 9904 ldr r1, [sp, #16] + 17b2a: a80a add r0, sp, #40 ; 0x28 + 17b2c: f7fe fcfe bl 1652c + 17b30: 2300 movs r3, #0 + 17b32: e797 b.n 17a64 + +00017b34 : + 17b34: b510 push {r4, lr} + 17b36: 2010 movs r0, #16 + 17b38: f000 f92e bl 17d98 + 17b3c: 4604 mov r4, r0 + 17b3e: b160 cbz r0, 17b5a + 17b40: f7fe fc90 bl 16464 + 17b44: b908 cbnz r0, 17b4a + 17b46: 4620 mov r0, r4 + 17b48: bd10 pop {r4, pc} + 17b4a: f240 63d4 movw r3, #1748 ; 0x6d4 + 17b4e: f2c1 0300 movt r3, #4096 ; 0x1000 + 17b52: 4620 mov r0, r4 + 17b54: 685b ldr r3, [r3, #4] + 17b56: 2100 movs r1, #0 + 17b58: 4798 blx r3 + 17b5a: 2000 movs r0, #0 + 17b5c: bd10 pop {r4, pc} + 17b5e: bf00 nop + +00017b60 : + 17b60: b168 cbz r0, 17b7e + 17b62: b510 push {r4, lr} + 17b64: 4604 mov r4, r0 + 17b66: f7fe fc99 bl 1649c + 17b6a: f240 63d4 movw r3, #1748 ; 0x6d4 + 17b6e: f2c1 0300 movt r3, #4096 ; 0x1000 + 17b72: 4620 mov r0, r4 + 17b74: e8bd 4010 ldmia.w sp!, {r4, lr} + 17b78: 685b ldr r3, [r3, #4] + 17b7a: 2100 movs r1, #0 + 17b7c: 4718 bx r3 + 17b7e: 4770 bx lr + +00017b80 : + 17b80: f7fe bcaa b.w 164d8 + +00017b84 : + 17b84: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + 17b88: b084 sub sp, #16 + 17b8a: 4617 mov r7, r2 + 17b8c: 460d mov r5, r1 + 17b8e: 4604 mov r4, r0 + 17b90: f7fe fca2 bl 164d8 + 17b94: 4680 mov r8, r0 + 17b96: b13f cbz r7, 17ba8 + 17b98: 683b ldr r3, [r7, #0] + 17b9a: 4298 cmp r0, r3 + 17b9c: bf84 itt hi + 17b9e: f8c7 8000 strhi.w r8, [r7] + 17ba2: f04f 36ff movhi.w r6, #4294967295 + 17ba6: d805 bhi.n 17bb4 + 17ba8: 4668 mov r0, sp + 17baa: f7fe fc5b bl 16464 + 17bae: b128 cbz r0, 17bbc + 17bb0: f04f 36ff mov.w r6, #4294967295 + 17bb4: 4630 mov r0, r6 + 17bb6: b004 add sp, #16 + 17bb8: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 17bbc: 4620 mov r0, r4 + 17bbe: 4669 mov r1, sp + 17bc0: f7fe fe30 bl 16824 + 17bc4: 4604 mov r4, r0 + 17bc6: b148 cbz r0, 17bdc + 17bc8: e7f2 b.n 17bb0 + 17bca: 9e03 ldr r6, [sp, #12] + 17bcc: 4668 mov r0, sp + 17bce: 6836 ldr r6, [r6, #0] + 17bd0: 466a mov r2, sp + 17bd2: 552e strb r6, [r5, r4] + 17bd4: f7fe ffc6 bl 16b64 + 17bd8: 3401 adds r4, #1 + 17bda: b9e0 cbnz r0, 17c16 + 17bdc: 9e00 ldr r6, [sp, #0] + 17bde: 2108 movs r1, #8 + 17be0: 2300 movs r3, #0 + 17be2: 2e00 cmp r6, #0 + 17be4: d1f1 bne.n 17bca + 17be6: 3c01 subs r4, #1 + 17be8: 429c cmp r4, r3 + 17bea: bfc8 it gt + 17bec: 4633 movgt r3, r6 + 17bee: dd07 ble.n 17c00 + 17bf0: 5cea ldrb r2, [r5, r3] + 17bf2: 5d29 ldrb r1, [r5, r4] + 17bf4: 54e9 strb r1, [r5, r3] + 17bf6: 552a strb r2, [r5, r4] + 17bf8: 3301 adds r3, #1 + 17bfa: 3c01 subs r4, #1 + 17bfc: 42a3 cmp r3, r4 + 17bfe: dbf7 blt.n 17bf0 + 17c00: 4668 mov r0, sp + 17c02: f7fe fc4b bl 1649c + 17c06: 2f00 cmp r7, #0 + 17c08: d0d4 beq.n 17bb4 + 17c0a: 4630 mov r0, r6 + 17c0c: f8c7 8000 str.w r8, [r7] + 17c10: b004 add sp, #16 + 17c12: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 17c16: 4668 mov r0, sp + 17c18: f7fe fc40 bl 1649c + 17c1c: e7c8 b.n 17bb0 + 17c1e: bf00 nop + +00017c20 : + 17c20: b5f8 push {r3, r4, r5, r6, r7, lr} + 17c22: 6847 ldr r7, [r0, #4] + 17c24: 4604 mov r4, r0 + 17c26: 2f01 cmp r7, #1 + 17c28: 460d mov r5, r1 + 17c2a: 4616 mov r6, r2 + 17c2c: dd3f ble.n 17cae + 17c2e: 2300 movs r3, #0 + 17c30: 68c1 ldr r1, [r0, #12] + 17c32: 6083 str r3, [r0, #8] + 17c34: 6003 str r3, [r0, #0] + 17c36: 2300 movs r3, #0 + 17c38: 4618 mov r0, r3 + 17c3a: 3301 adds r3, #1 + 17c3c: 42bb cmp r3, r7 + 17c3e: f841 0b04 str.w r0, [r1], #4 + 17c42: d1fa bne.n 17c3a + 17c44: 2e00 cmp r6, #0 + 17c46: bfc8 it gt + 17c48: 1976 addgt r6, r6, r5 + 17c4a: dc0b bgt.n 17c64 + 17c4c: e028 b.n 17ca0 + 17c4e: 68e1 ldr r1, [r4, #12] + 17c50: f815 2b01 ldrb.w r2, [r5], #1 + 17c54: 6808 ldr r0, [r1, #0] + 17c56: 6823 ldr r3, [r4, #0] + 17c58: 4310 orrs r0, r2 + 17c5a: 3301 adds r3, #1 + 17c5c: 42b5 cmp r5, r6 + 17c5e: 6008 str r0, [r1, #0] + 17c60: 6023 str r3, [r4, #0] + 17c62: d009 beq.n 17c78 + 17c64: 4620 mov r0, r4 + 17c66: 2108 movs r1, #8 + 17c68: 4622 mov r2, r4 + 17c6a: f7ff f82f bl 16ccc + 17c6e: 2800 cmp r0, #0 + 17c70: d0ed beq.n 17c4e + 17c72: f04f 30ff mov.w r0, #4294967295 + 17c76: bdf8 pop {r3, r4, r5, r6, r7, pc} + 17c78: 2b00 cmp r3, #0 + 17c7a: dd27 ble.n 17ccc + 17c7c: f103 4280 add.w r2, r3, #1073741824 ; 0x40000000 + 17c80: 3a01 subs r2, #1 + 17c82: f851 0022 ldr.w r0, [r1, r2, lsl #2] + 17c86: 0092 lsls r2, r2, #2 + 17c88: b960 cbnz r0, 17ca4 + 17c8a: 3204 adds r2, #4 + 17c8c: 4411 add r1, r2 + 17c8e: e002 b.n 17c96 + 17c90: f851 2c04 ldr.w r2, [r1, #-4] + 17c94: b942 cbnz r2, 17ca8 + 17c96: 3b01 subs r3, #1 + 17c98: f1a1 0104 sub.w r1, r1, #4 + 17c9c: d1f8 bne.n 17c90 + 17c9e: 6023 str r3, [r4, #0] + 17ca0: 2300 movs r3, #0 + 17ca2: 60a3 str r3, [r4, #8] + 17ca4: 2000 movs r0, #0 + 17ca6: bdf8 pop {r3, r4, r5, r6, r7, pc} + 17ca8: 6023 str r3, [r4, #0] + 17caa: 2000 movs r0, #0 + 17cac: bdf8 pop {r3, r4, r5, r6, r7, pc} + 17cae: 3004 adds r0, #4 + 17cb0: f104 010c add.w r1, r4, #12 + 17cb4: 2202 movs r2, #2 + 17cb6: f7fe fd8b bl 167d0 + 17cba: 2800 cmp r0, #0 + 17cbc: d1d9 bne.n 17c72 + 17cbe: 6867 ldr r7, [r4, #4] + 17cc0: 60a0 str r0, [r4, #8] + 17cc2: 2f00 cmp r7, #0 + 17cc4: 6020 str r0, [r4, #0] + 17cc6: 68e1 ldr r1, [r4, #12] + 17cc8: ddbc ble.n 17c44 + 17cca: e7b4 b.n 17c36 + 17ccc: d0e8 beq.n 17ca0 + 17cce: e7e9 b.n 17ca4 + +00017cd0 : + 17cd0: f7fe bc98 b.w 16604 + +00017cd4 : + 17cd4: 6883 ldr r3, [r0, #8] + 17cd6: 2b01 cmp r3, #1 + 17cd8: d00d beq.n 17cf6 + 17cda: 6803 ldr r3, [r0, #0] + 17cdc: 2b01 cmp r3, #1 + 17cde: dd01 ble.n 17ce4 + 17ce0: 2001 movs r0, #1 + 17ce2: 4770 bx lr + 17ce4: 68c3 ldr r3, [r0, #12] + 17ce6: 681b ldr r3, [r3, #0] + 17ce8: 4299 cmp r1, r3 + 17cea: d3f9 bcc.n 17ce0 + 17cec: bf8c ite hi + 17cee: f04f 30ff movhi.w r0, #4294967295 + 17cf2: 2000 movls r0, #0 + 17cf4: 4770 bx lr + 17cf6: f04f 30ff mov.w r0, #4294967295 + 17cfa: 4770 bx lr + +00017cfc : + 17cfc: b508 push {r3, lr} + 17cfe: f7ff f8f1 bl 16ee4 + 17d02: 3000 adds r0, #0 + 17d04: bf18 it ne + 17d06: f04f 30ff movne.w r0, #4294967295 + 17d0a: bd08 pop {r3, pc} + +00017d0c : + 17d0c: b508 push {r3, lr} + 17d0e: f7ff f91d bl 16f4c + 17d12: 3000 adds r0, #0 + 17d14: bf18 it ne + 17d16: f04f 30ff movne.w r0, #4294967295 + 17d1a: bd08 pop {r3, pc} + +00017d1c : + 17d1c: b508 push {r3, lr} + 17d1e: f7ff fb83 bl 17428 + 17d22: 3000 adds r0, #0 + 17d24: bf18 it ne + 17d26: f04f 30ff movne.w r0, #4294967295 + 17d2a: bd08 pop {r3, pc} + +00017d2c : + 17d2c: b538 push {r3, r4, r5, lr} + 17d2e: 6894 ldr r4, [r2, #8] + 17d30: 2c01 cmp r4, #1 + 17d32: d009 beq.n 17d48 + 17d34: 688c ldr r4, [r1, #8] + 17d36: 2c01 cmp r4, #1 + 17d38: d006 beq.n 17d48 + 17d3a: f7ff fcfb bl 17734 + 17d3e: 3000 adds r0, #0 + 17d40: bf18 it ne + 17d42: f04f 30ff movne.w r0, #4294967295 + 17d46: bd38 pop {r3, r4, r5, pc} + 17d48: f04f 30ff mov.w r0, #4294967295 + 17d4c: bd38 pop {r3, r4, r5, pc} + 17d4e: bf00 nop + +00017d50 : + 17d50: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + 17d54: f240 64d4 movw r4, #1748 ; 0x6d4 + 17d58: f2c1 0400 movt r4, #4096 ; 0x1000 + 17d5c: 4607 mov r7, r0 + 17d5e: 6823 ldr r3, [r4, #0] + 17d60: 4610 mov r0, r2 + 17d62: 4690 mov r8, r2 + 17d64: 460e mov r6, r1 + 17d66: 4798 blx r3 + 17d68: 4605 mov r5, r0 + 17d6a: b170 cbz r0, 17d8a + 17d6c: f24f 5311 movw r3, #62737 ; 0xf511 + 17d70: 4642 mov r2, r8 + 17d72: f2c0 0300 movt r3, #0 + 17d76: 2100 movs r1, #0 + 17d78: 4798 blx r3 + 17d7a: f24f 4365 movw r3, #62565 ; 0xf465 + 17d7e: 4628 mov r0, r5 + 17d80: 4639 mov r1, r7 + 17d82: 4632 mov r2, r6 + 17d84: f2c0 0300 movt r3, #0 + 17d88: 4798 blx r3 + 17d8a: 4638 mov r0, r7 + 17d8c: 6863 ldr r3, [r4, #4] + 17d8e: 4631 mov r1, r6 + 17d90: 4798 blx r3 + 17d92: 4628 mov r0, r5 + 17d94: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +00017d98 : + 17d98: b538 push {r3, r4, r5, lr} + 17d9a: f240 63d4 movw r3, #1748 ; 0x6d4 + 17d9e: f2c1 0300 movt r3, #4096 ; 0x1000 + 17da2: 681b ldr r3, [r3, #0] + 17da4: 4605 mov r5, r0 + 17da6: 4798 blx r3 + 17da8: 4604 mov r4, r0 + 17daa: b130 cbz r0, 17dba + 17dac: f24f 5311 movw r3, #62737 ; 0xf511 + 17db0: 462a mov r2, r5 + 17db2: f2c0 0300 movt r3, #0 + 17db6: 2100 movs r1, #0 + 17db8: 4798 blx r3 + 17dba: 4620 mov r0, r4 + 17dbc: bd38 pop {r3, r4, r5, pc} + 17dbe: bf00 nop + +00017dc0 : + 17dc0: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 17dc4: 2a05 cmp r2, #5 + 17dc6: b0a9 sub sp, #164 ; 0xa4 + 17dc8: 4694 mov ip, r2 + 17dca: 9003 str r0, [sp, #12] + 17dcc: 9102 str r1, [sp, #8] + 17dce: f8dd a0c8 ldr.w sl, [sp, #200] ; 0xc8 + 17dd2: d870 bhi.n 17eb6 + 17dd4: 2940 cmp r1, #64 ; 0x40 + 17dd6: 461f mov r7, r3 + 17dd8: d90f bls.n 17dfa + 17dda: ac10 add r4, sp, #64 ; 0x40 + 17ddc: 4623 mov r3, r4 + 17dde: 2001 movs r0, #1 + 17de0: a903 add r1, sp, #12 + 17de2: aa02 add r2, sp, #8 + 17de4: f8cd c000 str.w ip, [sp] + 17de8: f000 f90e bl 18008 + 17dec: 2800 cmp r0, #0 + 17dee: f8dd c000 ldr.w ip, [sp] + 17df2: db60 blt.n 17eb6 + 17df4: 2320 movs r3, #32 + 17df6: 9403 str r4, [sp, #12] + 17df8: 9302 str r3, [sp, #8] + 17dfa: f24f 5911 movw r9, #62737 ; 0xf511 + 17dfe: f24f 4865 movw r8, #62565 ; 0xf465 + 17e02: ae18 add r6, sp, #96 ; 0x60 + 17e04: 2100 movs r1, #0 + 17e06: 2240 movs r2, #64 ; 0x40 + 17e08: f2c0 0900 movt r9, #0 + 17e0c: 4630 mov r0, r6 + 17e0e: f8cd c000 str.w ip, [sp] + 17e12: f2c0 0800 movt r8, #0 + 17e16: 47c8 blx r9 + 17e18: 4630 mov r0, r6 + 17e1a: 9903 ldr r1, [sp, #12] + 17e1c: 9a02 ldr r2, [sp, #8] + 17e1e: 47c0 blx r8 + 17e20: 4633 mov r3, r6 + 17e22: f8dd c000 ldr.w ip, [sp] + 17e26: ac28 add r4, sp, #160 ; 0xa0 + 17e28: 781a ldrb r2, [r3, #0] + 17e2a: f082 0236 eor.w r2, r2, #54 ; 0x36 + 17e2e: f803 2b01 strb.w r2, [r3], #1 + 17e32: 42a3 cmp r3, r4 + 17e34: d1f8 bne.n 17e28 + 17e36: 2340 movs r3, #64 ; 0x40 + 17e38: 930a str r3, [sp, #40] ; 0x28 + 17e3a: f10d 0b10 add.w fp, sp, #16 + 17e3e: ab0a add r3, sp, #40 ; 0x28 + 17e40: 9604 str r6, [sp, #16] + 17e42: 9301 str r3, [sp, #4] + 17e44: 465a mov r2, fp + 17e46: ea4f 0e8c mov.w lr, ip, lsl #2 + 17e4a: 2500 movs r5, #0 + 17e4c: f1bc 0f00 cmp.w ip, #0 + 17e50: d009 beq.n 17e66 + 17e52: 5978 ldr r0, [r7, r5] + 17e54: f85a 1005 ldr.w r1, [sl, r5] + 17e58: 3504 adds r5, #4 + 17e5a: 4575 cmp r5, lr + 17e5c: f842 0f04 str.w r0, [r2, #4]! + 17e60: f843 1f04 str.w r1, [r3, #4]! + 17e64: d1f5 bne.n 17e52 + 17e66: f10c 0001 add.w r0, ip, #1 + 17e6a: 4659 mov r1, fp + 17e6c: 9a01 ldr r2, [sp, #4] + 17e6e: 9b33 ldr r3, [sp, #204] ; 0xcc + 17e70: f000 f8ca bl 18008 + 17e74: 2800 cmp r0, #0 + 17e76: db1e blt.n 17eb6 + 17e78: 2100 movs r1, #0 + 17e7a: 2240 movs r2, #64 ; 0x40 + 17e7c: 4630 mov r0, r6 + 17e7e: 47c8 blx r9 + 17e80: 4630 mov r0, r6 + 17e82: 9903 ldr r1, [sp, #12] + 17e84: 9a02 ldr r2, [sp, #8] + 17e86: 47c0 blx r8 + 17e88: 4633 mov r3, r6 + 17e8a: 781a ldrb r2, [r3, #0] + 17e8c: f082 025c eor.w r2, r2, #92 ; 0x5c + 17e90: f803 2b01 strb.w r2, [r3], #1 + 17e94: 42a3 cmp r3, r4 + 17e96: d1f8 bne.n 17e8a + 17e98: 9b33 ldr r3, [sp, #204] ; 0xcc + 17e9a: 2540 movs r5, #64 ; 0x40 + 17e9c: 2420 movs r4, #32 + 17e9e: 4659 mov r1, fp + 17ea0: 9a01 ldr r2, [sp, #4] + 17ea2: 2002 movs r0, #2 + 17ea4: 9604 str r6, [sp, #16] + 17ea6: 9305 str r3, [sp, #20] + 17ea8: 950a str r5, [sp, #40] ; 0x28 + 17eaa: 940b str r4, [sp, #44] ; 0x2c + 17eac: f000 f8ac bl 18008 + 17eb0: b029 add sp, #164 ; 0xa4 + 17eb2: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 17eb6: f04f 30ff mov.w r0, #4294967295 + 17eba: e7f9 b.n 17eb0 + +00017ebc : + 17ebc: b530 push {r4, r5, lr} + 17ebe: b085 sub sp, #20 + 17ec0: 9c08 ldr r4, [sp, #32] + 17ec2: ad02 add r5, sp, #8 + 17ec4: 9203 str r2, [sp, #12] + 17ec6: 9302 str r3, [sp, #8] + 17ec8: 9401 str r4, [sp, #4] + 17eca: 9500 str r5, [sp, #0] + 17ecc: 2201 movs r2, #1 + 17ece: ab03 add r3, sp, #12 + 17ed0: f7ff ff76 bl 17dc0 + 17ed4: b005 add sp, #20 + 17ed6: bd30 pop {r4, r5, pc} + +00017ed8 : + 17ed8: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 17edc: b0cb sub sp, #300 ; 0x12c + 17ede: 9001 str r0, [sp, #4] + 17ee0: 2300 movs r3, #0 + 17ee2: 18c2 adds r2, r0, r3 + 17ee4: 6892 ldr r2, [r2, #8] + 17ee6: ac02 add r4, sp, #8 + 17ee8: 50e2 str r2, [r4, r3] + 17eea: 3304 adds r3, #4 + 17eec: 2b20 cmp r3, #32 + 17eee: d1f8 bne.n 17ee2 + 17ef0: ab09 add r3, sp, #36 ; 0x24 + 17ef2: f101 0540 add.w r5, r1, #64 ; 0x40 + 17ef6: 784a ldrb r2, [r1, #1] + 17ef8: 7808 ldrb r0, [r1, #0] + 17efa: 78cc ldrb r4, [r1, #3] + 17efc: 0412 lsls r2, r2, #16 + 17efe: ea42 6200 orr.w r2, r2, r0, lsl #24 + 17f02: 7888 ldrb r0, [r1, #2] + 17f04: 4322 orrs r2, r4 + 17f06: 3104 adds r1, #4 + 17f08: ea42 2200 orr.w r2, r2, r0, lsl #8 + 17f0c: 42a9 cmp r1, r5 + 17f0e: f843 2f04 str.w r2, [r3, #4]! + 17f12: d1f0 bne.n 17ef6 + 17f14: f10d 0a28 add.w sl, sp, #40 ; 0x28 + 17f18: 4653 mov r3, sl + 17f1a: 2200 movs r2, #0 + 17f1c: 6b98 ldr r0, [r3, #56] ; 0x38 + 17f1e: 6859 ldr r1, [r3, #4] + 17f20: f85a 4002 ldr.w r4, [sl, r2] + 17f24: ea4f 4770 mov.w r7, r0, ror #17 + 17f28: 6a5d ldr r5, [r3, #36] ; 0x24 + 17f2a: ea4f 16f1 mov.w r6, r1, ror #7 + 17f2e: ea87 47f0 eor.w r7, r7, r0, ror #19 + 17f32: ea87 2090 eor.w r0, r7, r0, lsr #10 + 17f36: 442c add r4, r5 + 17f38: ea86 46b1 eor.w r6, r6, r1, ror #18 + 17f3c: 4420 add r0, r4 + 17f3e: ea86 01d1 eor.w r1, r6, r1, lsr #3 + 17f42: 3204 adds r2, #4 + 17f44: 4401 add r1, r0 + 17f46: 2ac0 cmp r2, #192 ; 0xc0 + 17f48: 6419 str r1, [r3, #64] ; 0x40 + 17f4a: f103 0304 add.w r3, r3, #4 + 17f4e: d1e5 bne.n 17f1c + 17f50: f246 2b94 movw fp, #25236 ; 0x6294 + 17f54: 9905 ldr r1, [sp, #20] + 17f56: f2c0 0b03 movt fp, #3 + 17f5a: 9100 str r1, [sp, #0] + 17f5c: f8dd c024 ldr.w ip, [sp, #36] ; 0x24 + 17f60: 9a06 ldr r2, [sp, #24] + 17f62: f8dd e01c ldr.w lr, [sp, #28] + 17f66: 9c08 ldr r4, [sp, #32] + 17f68: 9b02 ldr r3, [sp, #8] + 17f6a: 9803 ldr r0, [sp, #12] + 17f6c: 9d04 ldr r5, [sp, #16] + 17f6e: 2100 movs r1, #0 + 17f70: e007 b.n 17f82 + 17f72: 46a4 mov ip, r4 + 17f74: 9500 str r5, [sp, #0] + 17f76: 4674 mov r4, lr + 17f78: 4605 mov r5, r0 + 17f7a: 4696 mov lr, r2 + 17f7c: 4618 mov r0, r3 + 17f7e: 463a mov r2, r7 + 17f80: 4633 mov r3, r6 + 17f82: f85a 7001 ldr.w r7, [sl, r1] + 17f86: f85b 6001 ldr.w r6, [fp, r1] + 17f8a: ea4f 19b2 mov.w r9, r2, ror #6 + 17f8e: ea8e 0804 eor.w r8, lr, r4 + 17f92: ea89 29f2 eor.w r9, r9, r2, ror #11 + 17f96: ea89 6972 eor.w r9, r9, r2, ror #25 + 17f9a: 443e add r6, r7 + 17f9c: ea08 0702 and.w r7, r8, r2 + 17fa0: 444e add r6, r9 + 17fa2: 4067 eors r7, r4 + 17fa4: ea40 0803 orr.w r8, r0, r3 + 17fa8: ea4f 09b3 mov.w r9, r3, ror #2 + 17fac: 443e add r6, r7 + 17fae: ea05 0808 and.w r8, r5, r8 + 17fb2: ea00 0703 and.w r7, r0, r3 + 17fb6: ea89 3973 eor.w r9, r9, r3, ror #13 + 17fba: ea48 0807 orr.w r8, r8, r7 + 17fbe: ea89 59b3 eor.w r9, r9, r3, ror #22 + 17fc2: 3104 adds r1, #4 + 17fc4: 9f00 ldr r7, [sp, #0] + 17fc6: 4466 add r6, ip + 17fc8: 44c8 add r8, r9 + 17fca: f5b1 7f80 cmp.w r1, #256 ; 0x100 + 17fce: 4437 add r7, r6 + 17fd0: 4446 add r6, r8 + 17fd2: d1ce bne.n 17f72 + 17fd4: 9303 str r3, [sp, #12] + 17fd6: 9901 ldr r1, [sp, #4] + 17fd8: 9409 str r4, [sp, #36] ; 0x24 + 17fda: 9207 str r2, [sp, #28] + 17fdc: f8cd e020 str.w lr, [sp, #32] + 17fe0: 9706 str r7, [sp, #24] + 17fe2: 9004 str r0, [sp, #16] + 17fe4: 9505 str r5, [sp, #20] + 17fe6: 9602 str r6, [sp, #8] + 17fe8: 2300 movs r3, #0 + 17fea: e001 b.n 17ff0 + 17fec: aa02 add r2, sp, #8 + 17fee: 58d6 ldr r6, [r2, r3] + 17ff0: 688a ldr r2, [r1, #8] + 17ff2: 3304 adds r3, #4 + 17ff4: 4432 add r2, r6 + 17ff6: 2b20 cmp r3, #32 + 17ff8: 608a str r2, [r1, #8] + 17ffa: f101 0104 add.w r1, r1, #4 + 17ffe: d1f5 bne.n 17fec + 18000: 2000 movs r0, #0 + 18002: b04b add sp, #300 ; 0x12c + 18004: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +00018008 : + 18008: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 1800c: f24f 5411 movw r4, #62737 ; 0xf511 + 18010: b09f sub sp, #124 ; 0x7c + 18012: 9000 str r0, [sp, #0] + 18014: f2c0 0400 movt r4, #0 + 18018: 4689 mov r9, r1 + 1801a: 4690 mov r8, r2 + 1801c: 2100 movs r1, #0 + 1801e: 2270 movs r2, #112 ; 0x70 + 18020: a802 add r0, sp, #8 + 18022: 9301 str r3, [sp, #4] + 18024: 47a0 blx r4 + 18026: f64c 5319 movw r3, #52505 ; 0xcd19 + 1802a: f24e 6767 movw r7, #58983 ; 0xe667 + 1802e: f64a 6685 movw r6, #44677 ; 0xae85 + 18032: f24f 3e72 movw lr, #62322 ; 0xf372 + 18036: f24f 553a movw r5, #62778 ; 0xf53a + 1803a: f245 247f movw r4, #21119 ; 0x527f + 1803e: f646 008c movw r0, #26764 ; 0x688c + 18042: f64d 12ab movw r2, #55723 ; 0xd9ab + 18046: f6c5 33e0 movt r3, #23520 ; 0x5be0 + 1804a: f6c6 2709 movt r7, #27145 ; 0x6a09 + 1804e: f6cb 3667 movt r6, #47975 ; 0xbb67 + 18052: f6c3 4e6e movt lr, #15470 ; 0x3c6e + 18056: f2ca 554f movt r5, #42319 ; 0xa54f + 1805a: f2c5 140e movt r4, #20750 ; 0x510e + 1805e: f6c9 3005 movt r0, #39685 ; 0x9b05 + 18062: f6c1 7283 movt r2, #8067 ; 0x1f83 + 18066: 930b str r3, [sp, #44] ; 0x2c + 18068: 9b00 ldr r3, [sp, #0] + 1806a: 2100 movs r1, #0 + 1806c: 9704 str r7, [sp, #16] + 1806e: 9605 str r6, [sp, #20] + 18070: f8cd e018 str.w lr, [sp, #24] + 18074: 9507 str r5, [sp, #28] + 18076: 9408 str r4, [sp, #32] + 18078: 9009 str r0, [sp, #36] ; 0x24 + 1807a: 920a str r2, [sp, #40] ; 0x28 + 1807c: 910c str r1, [sp, #48] ; 0x30 + 1807e: 9102 str r1, [sp, #8] + 18080: 9103 str r1, [sp, #12] + 18082: 2b00 cmp r3, #0 + 18084: f000 80c1 beq.w 1820a + 18088: f24f 4565 movw r5, #62565 ; 0xf465 + 1808c: 460f mov r7, r1 + 1808e: 460e mov r6, r1 + 18090: f2c0 0500 movt r5, #0 + 18094: f8d9 b000 ldr.w fp, [r9] + 18098: f8d8 4000 ldr.w r4, [r8] + 1809c: b33c cbz r4, 180ee + 1809e: a802 add r0, sp, #8 + 180a0: 4408 add r0, r1 + 180a2: f1c1 0a40 rsb sl, r1, #64 ; 0x40 + 180a6: 302c adds r0, #44 ; 0x2c + 180a8: b909 cbnz r1, 180ae + 180aa: 2c3f cmp r4, #63 ; 0x3f + 180ac: d82e bhi.n 1810c + 180ae: 45a2 cmp sl, r4 + 180b0: bf28 it cs + 180b2: 46a2 movcs sl, r4 + 180b4: 4659 mov r1, fp + 180b6: 4652 mov r2, sl + 180b8: 47a8 blx r5 + 180ba: 990c ldr r1, [sp, #48] ; 0x30 + 180bc: ebca 0404 rsb r4, sl, r4 + 180c0: 4451 add r1, sl + 180c2: 2940 cmp r1, #64 ; 0x40 + 180c4: 44d3 add fp, sl + 180c6: 910c str r1, [sp, #48] ; 0x30 + 180c8: d1e8 bne.n 1809c + 180ca: a802 add r0, sp, #8 + 180cc: a90d add r1, sp, #52 ; 0x34 + 180ce: f7ff ff03 bl 17ed8 + 180d2: 2800 cmp r0, #0 + 180d4: db15 blt.n 18102 + 180d6: e9dd 0102 ldrd r0, r1, [sp, #8] + 180da: f510 7000 adds.w r0, r0, #512 ; 0x200 + 180de: f141 0100 adc.w r1, r1, #0 + 180e2: e9cd 0102 strd r0, r1, [sp, #8] + 180e6: 960c str r6, [sp, #48] ; 0x30 + 180e8: 2100 movs r1, #0 + 180ea: 2c00 cmp r4, #0 + 180ec: d1d7 bne.n 1809e + 180ee: 9b00 ldr r3, [sp, #0] + 180f0: 3701 adds r7, #1 + 180f2: 429f cmp r7, r3 + 180f4: d01d beq.n 18132 + 180f6: 293f cmp r1, #63 ; 0x3f + 180f8: f859 bf04 ldr.w fp, [r9, #4]! + 180fc: f858 4f04 ldr.w r4, [r8, #4]! + 18100: d9cc bls.n 1809c + 18102: f04f 30ff mov.w r0, #4294967295 + 18106: b01f add sp, #124 ; 0x7c + 18108: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 1810c: a802 add r0, sp, #8 + 1810e: 4659 mov r1, fp + 18110: f7ff fee2 bl 17ed8 + 18114: 2800 cmp r0, #0 + 18116: dbf4 blt.n 18102 + 18118: e9dd 0102 ldrd r0, r1, [sp, #8] + 1811c: f510 7000 adds.w r0, r0, #512 ; 0x200 + 18120: f141 0100 adc.w r1, r1, #0 + 18124: e9cd 0102 strd r0, r1, [sp, #8] + 18128: f10b 0b40 add.w fp, fp, #64 ; 0x40 + 1812c: 990c ldr r1, [sp, #48] ; 0x30 + 1812e: 3c40 subs r4, #64 ; 0x40 + 18130: e7b4 b.n 1809c + 18132: 293f cmp r1, #63 ; 0x3f + 18134: d8e5 bhi.n 18102 + 18136: e9dd 2302 ldrd r2, r3, [sp, #8] + 1813a: 00c8 lsls r0, r1, #3 + 1813c: 1812 adds r2, r2, r0 + 1813e: ac1e add r4, sp, #120 ; 0x78 + 18140: f101 0001 add.w r0, r1, #1 + 18144: f143 0300 adc.w r3, r3, #0 + 18148: 2580 movs r5, #128 ; 0x80 + 1814a: 440c add r4, r1 + 1814c: 2838 cmp r0, #56 ; 0x38 + 1814e: e9cd 2302 strd r2, r3, [sp, #8] + 18152: 900c str r0, [sp, #48] ; 0x30 + 18154: f804 5c44 strb.w r5, [r4, #-68] + 18158: d954 bls.n 18204 + 1815a: 2840 cmp r0, #64 ; 0x40 + 1815c: d00b beq.n 18176 + 1815e: ab02 add r3, sp, #8 + 18160: 440b add r3, r1 + 18162: 332c adds r3, #44 ; 0x2c + 18164: f10d 0173 add.w r1, sp, #115 ; 0x73 + 18168: 2200 movs r2, #0 + 1816a: f803 2f01 strb.w r2, [r3, #1]! + 1816e: 428b cmp r3, r1 + 18170: d1fb bne.n 1816a + 18172: 2340 movs r3, #64 ; 0x40 + 18174: 930c str r3, [sp, #48] ; 0x30 + 18176: af0d add r7, sp, #52 ; 0x34 + 18178: 4639 mov r1, r7 + 1817a: a802 add r0, sp, #8 + 1817c: f7ff feac bl 17ed8 + 18180: e9dd 2302 ldrd r2, r3, [sp, #8] + 18184: 2000 movs r0, #0 + 18186: 2500 movs r5, #0 + 18188: 3001 adds r0, #1 + 1818a: ac02 add r4, sp, #8 + 1818c: 4404 add r4, r0 + 1818e: 2837 cmp r0, #55 ; 0x37 + 18190: f884 502b strb.w r5, [r4, #43] ; 0x2b + 18194: d9f8 bls.n 18188 + 18196: 900c str r0, [sp, #48] ; 0x30 + 18198: 0c15 lsrs r5, r2, #16 + 1819a: 0e16 lsrs r6, r2, #24 + 1819c: 0a14 lsrs r4, r2, #8 + 1819e: 4639 mov r1, r7 + 181a0: ea4f 6c13 mov.w ip, r3, lsr #24 + 181a4: ea4f 4e13 mov.w lr, r3, lsr #16 + 181a8: 0a1f lsrs r7, r3, #8 + 181aa: a802 add r0, sp, #8 + 181ac: f88d 2073 strb.w r2, [sp, #115] ; 0x73 + 181b0: f88d 5071 strb.w r5, [sp, #113] ; 0x71 + 181b4: f88d 306f strb.w r3, [sp, #111] ; 0x6f + 181b8: f88d c06c strb.w ip, [sp, #108] ; 0x6c + 181bc: f88d e06d strb.w lr, [sp, #109] ; 0x6d + 181c0: f88d 706e strb.w r7, [sp, #110] ; 0x6e + 181c4: f88d 6070 strb.w r6, [sp, #112] ; 0x70 + 181c8: f88d 4072 strb.w r4, [sp, #114] ; 0x72 + 181cc: f7ff fe84 bl 17ed8 + 181d0: f8dd b004 ldr.w fp, [sp, #4] + 181d4: aa03 add r2, sp, #12 + 181d6: f10b 0520 add.w r5, fp, #32 + 181da: f852 3f04 ldr.w r3, [r2, #4]! + 181de: f10b 0b04 add.w fp, fp, #4 + 181e2: 0e1c lsrs r4, r3, #24 + 181e4: 0c18 lsrs r0, r3, #16 + 181e6: 0a19 lsrs r1, r3, #8 + 181e8: f80b 3c01 strb.w r3, [fp, #-1] + 181ec: f80b 4c04 strb.w r4, [fp, #-4] + 181f0: f80b 0c03 strb.w r0, [fp, #-3] + 181f4: f80b 1c02 strb.w r1, [fp, #-2] + 181f8: 45ab cmp fp, r5 + 181fa: d1ee bne.n 181da + 181fc: 2000 movs r0, #0 + 181fe: b01f add sp, #124 ; 0x7c + 18200: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 18204: af0d add r7, sp, #52 ; 0x34 + 18206: d1be bne.n 18186 + 18208: e7c6 b.n 18198 + 1820a: 460a mov r2, r1 + 1820c: 460b mov r3, r1 + 1820e: af1e add r7, sp, #120 ; 0x78 + 18210: 2180 movs r1, #128 ; 0x80 + 18212: e9cd 2302 strd r2, r3, [sp, #8] + 18216: f807 1d44 strb.w r1, [r7, #-68]! + 1821a: 2001 movs r0, #1 + 1821c: e7b3 b.n 18186 + 1821e: bf00 nop + +00018220 : + 18220: 2300 movs r3, #0 + 18222: e002 b.n 1822a + 18224: 3301 adds r3, #1 + 18226: 2b20 cmp r3, #32 + 18228: d003 beq.n 18232 + 1822a: fa20 f203 lsr.w r2, r0, r3 + 1822e: 07d2 lsls r2, r2, #31 + 18230: d5f8 bpl.n 18224 + 18232: 4618 mov r0, r3 + 18234: 4770 bx lr + 18236: bf00 nop + +00018238 : + 18238: 1c50 adds r0, r2, #1 + 1823a: d016 beq.n 1826a + 1823c: f101 4180 add.w r1, r1, #1073741824 ; 0x40000000 + 18240: f501 2100 add.w r1, r1, #524288 ; 0x80000 + 18244: b430 push {r4, r5} + 18246: 2000 movs r0, #0 + 18248: 680d ldr r5, [r1, #0] + 1824a: e002 b.n 18252 + 1824c: 3001 adds r0, #1 + 1824e: 2820 cmp r0, #32 + 18250: d003 beq.n 1825a + 18252: fa22 f400 lsr.w r4, r2, r0 + 18256: 07e4 lsls r4, r4, #31 + 18258: d5f8 bpl.n 1824c + 1825a: 4083 lsls r3, r0 + 1825c: 4013 ands r3, r2 + 1825e: ea25 0202 bic.w r2, r5, r2 + 18262: 4313 orrs r3, r2 + 18264: 600b str r3, [r1, #0] + 18266: bc30 pop {r4, r5} + 18268: 4770 bx lr + 1826a: f101 4180 add.w r1, r1, #1073741824 ; 0x40000000 + 1826e: f501 2100 add.w r1, r1, #524288 ; 0x80000 + 18272: 600b str r3, [r1, #0] + 18274: 4770 bx lr + 18276: bf00 nop + +00018278 : + 18278: f101 4180 add.w r1, r1, #1073741824 ; 0x40000000 + 1827c: f501 2300 add.w r3, r1, #524288 ; 0x80000 + 18280: 6818 ldr r0, [r3, #0] + 18282: 2300 movs r3, #0 + 18284: e002 b.n 1828c + 18286: 3301 adds r3, #1 + 18288: 2b20 cmp r3, #32 + 1828a: d003 beq.n 18294 + 1828c: fa22 f103 lsr.w r1, r2, r3 + 18290: 07c9 lsls r1, r1, #31 + 18292: d5f8 bpl.n 18286 + 18294: 4010 ands r0, r2 + 18296: 40d8 lsrs r0, r3 + 18298: 4770 bx lr + 1829a: bf00 nop + +0001829c : + 1829c: b2c3 uxtb r3, r0 + 1829e: f103 0263 add.w r2, r3, #99 ; 0x63 + 182a2: b2d2 uxtb r2, r2 + 182a4: 2a76 cmp r2, #118 ; 0x76 + 182a6: d803 bhi.n 182b0 + 182a8: 2800 cmp r0, #0 + 182aa: db03 blt.n 182b4 + 182ac: 2064 movs r0, #100 ; 0x64 + 182ae: 4770 bx lr + 182b0: 2000 movs r0, #0 + 182b2: 4770 bx lr + 182b4: 3364 adds r3, #100 ; 0x64 + 182b6: b2d8 uxtb r0, r3 + 182b8: 4770 bx lr + 182ba: bf00 nop + +000182bc : + 182bc: eb00 70d0 add.w r0, r0, r0, lsr #31 + 182c0: f3c0 0047 ubfx r0, r0, #1, #8 + 182c4: b243 sxtb r3, r0 + 182c6: 2b00 cmp r3, #0 + 182c8: db01 blt.n 182ce + 182ca: 2000 movs r0, #0 + 182cc: 4770 bx lr + 182ce: 3320 adds r3, #32 + 182d0: da01 bge.n 182d6 + 182d2: 2064 movs r0, #100 ; 0x64 + 182d4: 4770 bx lr + 182d6: f06f 0302 mvn.w r3, #2 + 182da: fb00 f003 mul.w r0, r0, r3 + 182de: b2c0 uxtb r0, r0 + 182e0: 4770 bx lr + 182e2: bf00 nop + +000182e4 : + 182e4: 4603 mov r3, r0 + 182e6: 2b01 cmp r3, #1 + 182e8: 4608 mov r0, r1 + 182ea: d02b beq.n 18344 + 182ec: 2b04 cmp r3, #4 + 182ee: bf18 it ne + 182f0: 2b02 cmpne r3, #2 + 182f2: bf0c ite eq + 182f4: 2201 moveq r2, #1 + 182f6: 2200 movne r2, #0 + 182f8: d003 beq.n 18302 + 182fa: 2b08 cmp r3, #8 + 182fc: d001 beq.n 18302 + 182fe: 4610 mov r0, r2 + 18300: 4770 bx lr + 18302: f1a0 0333 sub.w r3, r0, #51 ; 0x33 + 18306: 2b31 cmp r3, #49 ; 0x31 + 18308: d801 bhi.n 1830e + 1830a: 2064 movs r0, #100 ; 0x64 + 1830c: 4770 bx lr + 1830e: f1a0 0329 sub.w r3, r0, #41 ; 0x29 + 18312: 2b09 cmp r3, #9 + 18314: d928 bls.n 18368 + 18316: f1a0 031f sub.w r3, r0, #31 + 1831a: 2b09 cmp r3, #9 + 1831c: d92a bls.n 18374 + 1831e: f1a0 0315 sub.w r3, r0, #21 + 18322: 2b09 cmp r3, #9 + 18324: d928 bls.n 18378 + 18326: f1a0 030a sub.w r3, r0, #10 + 1832a: 2b0a cmp r3, #10 + 1832c: d937 bls.n 1839e + 1832e: 1f43 subs r3, r0, #5 + 18330: 2b04 cmp r3, #4 + 18332: d942 bls.n 183ba + 18334: 1e43 subs r3, r0, #1 + 18336: 2b03 cmp r3, #3 + 18338: d83e bhi.n 183b8 + 1833a: eb03 0343 add.w r3, r3, r3, lsl #1 + 1833e: 1058 asrs r0, r3, #1 + 18340: 3006 adds r0, #6 + 18342: 4770 bx lr + 18344: f1a1 033d sub.w r3, r1, #61 ; 0x3d + 18348: 2b27 cmp r3, #39 ; 0x27 + 1834a: d908 bls.n 1835e + 1834c: f1a1 0329 sub.w r3, r1, #41 ; 0x29 + 18350: 2b13 cmp r3, #19 + 18352: d80b bhi.n 1836c + 18354: f1a1 0028 sub.w r0, r1, #40 ; 0x28 + 18358: 1040 asrs r0, r0, #1 + 1835a: 304e adds r0, #78 ; 0x4e + 1835c: 4770 bx lr + 1835e: f1a1 003c sub.w r0, r1, #60 ; 0x3c + 18362: 1080 asrs r0, r0, #2 + 18364: 305a adds r0, #90 ; 0x5a + 18366: 4770 bx lr + 18368: 0040 lsls r0, r0, #1 + 1836a: 4770 bx lr + 1836c: f1a1 031f sub.w r3, r1, #31 + 18370: 2b09 cmp r3, #9 + 18372: d803 bhi.n 1837c + 18374: 3024 adds r0, #36 ; 0x24 + 18376: 4770 bx lr + 18378: 3022 adds r0, #34 ; 0x22 + 1837a: 4770 bx lr + 1837c: f1a1 0315 sub.w r3, r1, #21 + 18380: 2b09 cmp r3, #9 + 18382: d9f9 bls.n 18378 + 18384: 1f4b subs r3, r1, #5 + 18386: 2b0f cmp r3, #15 + 18388: d909 bls.n 1839e + 1838a: 2904 cmp r1, #4 + 1838c: d01a beq.n 183c4 + 1838e: 2903 cmp r1, #3 + 18390: d01a beq.n 183c8 + 18392: 2902 cmp r1, #2 + 18394: d00f beq.n 183b6 + 18396: 2901 cmp r1, #1 + 18398: bf08 it eq + 1839a: 2009 moveq r0, #9 + 1839c: 4770 bx lr + 1839e: f245 5256 movw r2, #21846 ; 0x5556 + 183a2: f2c5 5255 movt r2, #21845 ; 0x5555 + 183a6: 005b lsls r3, r3, #1 + 183a8: fb82 1203 smull r1, r2, r2, r3 + 183ac: eba2 73e3 sub.w r3, r2, r3, asr #31 + 183b0: f103 002a add.w r0, r3, #42 ; 0x2a + 183b4: 4770 bx lr + 183b6: 2012 movs r0, #18 + 183b8: 4770 bx lr + 183ba: eb03 0343 add.w r3, r3, r3, lsl #1 + 183be: 1058 asrs r0, r3, #1 + 183c0: 3016 adds r0, #22 + 183c2: 4770 bx lr + 183c4: 2024 movs r0, #36 ; 0x24 + 183c6: 4770 bx lr + 183c8: 201b movs r0, #27 + 183ca: 4770 bx lr + +000183cc : + 183cc: b5f8 push {r3, r4, r5, r6, r7, lr} + 183ce: 4605 mov r5, r0 + 183d0: f240 64e0 movw r4, #1760 ; 0x6e0 + 183d4: 6800 ldr r0, [r0, #0] + 183d6: f44f 6140 mov.w r1, #3072 ; 0xc00 + 183da: f04f 4200 mov.w r2, #2147483648 ; 0x80000000 + 183de: 2301 movs r3, #1 + 183e0: f7ff ff2a bl 18238 + 183e4: 2301 movs r3, #1 + 183e6: 6828 ldr r0, [r5, #0] + 183e8: f44f 6150 mov.w r1, #3328 ; 0xd00 + 183ec: f04f 4200 mov.w r2, #2147483648 ; 0x80000000 + 183f0: f7ff ff22 bl 18238 + 183f4: f44f 614f mov.w r1, #3312 ; 0xcf0 + 183f8: f04f 32ff mov.w r2, #4294967295 + 183fc: 6828 ldr r0, [r5, #0] + 183fe: f7ff ff3b bl 18278 + 18402: f2c1 0400 movt r4, #4096 ; 0x1000 + 18406: 0c03 lsrs r3, r0, #16 + 18408: b286 uxth r6, r0 + 1840a: f44f 615a mov.w r1, #3488 ; 0xda0 + 1840e: 6828 ldr r0, [r5, #0] + 18410: f04f 32ff mov.w r2, #4294967295 + 18414: 6226 str r6, [r4, #32] + 18416: 6263 str r3, [r4, #36] ; 0x24 + 18418: f7ff ff2e bl 18278 + 1841c: f640 51a4 movw r1, #3492 ; 0xda4 + 18420: 0c03 lsrs r3, r0, #16 + 18422: b286 uxth r6, r0 + 18424: f04f 32ff mov.w r2, #4294967295 + 18428: 6828 ldr r0, [r5, #0] + 1842a: 62a6 str r6, [r4, #40] ; 0x28 + 1842c: 6023 str r3, [r4, #0] + 1842e: f7ff ff23 bl 18278 + 18432: f640 51a8 movw r1, #3496 ; 0xda8 + 18436: 0c03 lsrs r3, r0, #16 + 18438: b286 uxth r6, r0 + 1843a: f04f 32ff mov.w r2, #4294967295 + 1843e: 6828 ldr r0, [r5, #0] + 18440: 6066 str r6, [r4, #4] + 18442: 60a3 str r3, [r4, #8] + 18444: f7ff ff18 bl 18278 + 18448: 6822 ldr r2, [r4, #0] + 1844a: 6861 ldr r1, [r4, #4] + 1844c: 68a3 ldr r3, [r4, #8] + 1844e: 4411 add r1, r2 + 18450: 6a22 ldr r2, [r4, #32] + 18452: 4419 add r1, r3 + 18454: 6a63 ldr r3, [r4, #36] ; 0x24 + 18456: 440a add r2, r1 + 18458: b286 uxth r6, r0 + 1845a: 441a add r2, r3 + 1845c: 1997 adds r7, r2, r6 + 1845e: 6828 ldr r0, [r5, #0] + 18460: f640 212c movw r1, #2604 ; 0xa2c + 18464: f44f 5280 mov.w r2, #4096 ; 0x1000 + 18468: 2301 movs r3, #1 + 1846a: 60e6 str r6, [r4, #12] + 1846c: 6127 str r7, [r4, #16] + 1846e: f7ff fee3 bl 18238 + 18472: 2301 movs r3, #1 + 18474: 6828 ldr r0, [r5, #0] + 18476: f640 212c movw r1, #2604 ; 0xa2c + 1847a: f44f 4280 mov.w r2, #16384 ; 0x4000 + 1847e: f7ff fedb bl 18238 + 18482: f640 215c movw r1, #2652 ; 0xa5c + 18486: 22ff movs r2, #255 ; 0xff + 18488: 6828 ldr r0, [r5, #0] + 1848a: f7ff fef5 bl 18278 + 1848e: f640 2158 movw r1, #2648 ; 0xa58 + 18492: 61a0 str r0, [r4, #24] + 18494: f04f 427f mov.w r2, #4278190080 ; 0xff000000 + 18498: 6828 ldr r0, [r5, #0] + 1849a: f7ff feed bl 18278 + 1849e: 69a3 ldr r3, [r4, #24] + 184a0: 0200 lsls r0, r0, #8 + 184a2: b280 uxth r0, r0 + 184a4: 4403 add r3, r0 + 184a6: f44f 6126 mov.w r1, #2656 ; 0xa60 + 184aa: 6828 ldr r0, [r5, #0] + 184ac: f04f 32ff mov.w r2, #4294967295 + 184b0: 61a3 str r3, [r4, #24] + 184b2: f7ff fee1 bl 18278 + 184b6: 6a22 ldr r2, [r4, #32] + 184b8: 6a61 ldr r1, [r4, #36] ; 0x24 + 184ba: 6823 ldr r3, [r4, #0] + 184bc: 4411 add r1, r2 + 184be: 6862 ldr r2, [r4, #4] + 184c0: 4419 add r1, r3 + 184c2: 68a3 ldr r3, [r4, #8] + 184c4: 440a add r2, r1 + 184c6: 0206 lsls r6, r0, #8 + 184c8: 68e1 ldr r1, [r4, #12] + 184ca: eb02 0e03 add.w lr, r2, r3 + 184ce: f3c0 2007 ubfx r0, r0, #8, #8 + 184d2: 69a2 ldr r2, [r4, #24] + 184d4: 6aa3 ldr r3, [r4, #40] ; 0x28 + 184d6: b2b6 uxth r6, r6 + 184d8: 4306 orrs r6, r0 + 184da: 4471 add r1, lr + 184dc: eb01 0e02 add.w lr, r1, r2 + 184e0: 6828 ldr r0, [r5, #0] + 184e2: 18f7 adds r7, r6, r3 + 184e4: f640 410c movw r1, #3084 ; 0xc0c + 184e8: f04f 4200 mov.w r2, #2147483648 ; 0x80000000 + 184ec: 2301 movs r3, #1 + 184ee: f8c4 e01c str.w lr, [r4, #28] + 184f2: 62e6 str r6, [r4, #44] ; 0x2c + 184f4: 6327 str r7, [r4, #48] ; 0x30 + 184f6: f7ff fe9f bl 18238 + 184fa: 6828 ldr r0, [r5, #0] + 184fc: f640 410c movw r1, #3084 ; 0xc0c + 18500: f04f 4200 mov.w r2, #2147483648 ; 0x80000000 + 18504: 2300 movs r3, #0 + 18506: f7ff fe97 bl 18238 + 1850a: 6828 ldr r0, [r5, #0] + 1850c: f44f 6150 mov.w r1, #3328 ; 0xd00 + 18510: f04f 6200 mov.w r2, #134217728 ; 0x8000000 + 18514: 2301 movs r3, #1 + 18516: f7ff fe8f bl 18238 + 1851a: 6828 ldr r0, [r5, #0] + 1851c: f44f 6150 mov.w r1, #3328 ; 0xd00 + 18520: f04f 6200 mov.w r2, #134217728 ; 0x8000000 + 18524: 2300 movs r3, #0 + 18526: f7ff fe87 bl 18238 + 1852a: 6828 ldr r0, [r5, #0] + 1852c: f44f 6140 mov.w r1, #3072 ; 0xc00 + 18530: f04f 4200 mov.w r2, #2147483648 ; 0x80000000 + 18534: 2300 movs r3, #0 + 18536: f7ff fe7f bl 18238 + 1853a: 6828 ldr r0, [r5, #0] + 1853c: f44f 6150 mov.w r1, #3328 ; 0xd00 + 18540: f04f 4200 mov.w r2, #2147483648 ; 0x80000000 + 18544: 2300 movs r3, #0 + 18546: f7ff fe77 bl 18238 + 1854a: 6828 ldr r0, [r5, #0] + 1854c: f640 212c movw r1, #2604 ; 0xa2c + 18550: f44f 5240 mov.w r2, #12288 ; 0x3000 + 18554: 2300 movs r3, #0 + 18556: f7ff fe6f bl 18238 + 1855a: 6828 ldr r0, [r5, #0] + 1855c: f640 212c movw r1, #2604 ; 0xa2c + 18560: f44f 5240 mov.w r2, #12288 ; 0x3000 + 18564: 2302 movs r3, #2 + 18566: f7ff fe67 bl 18238 + 1856a: 6828 ldr r0, [r5, #0] + 1856c: f640 212c movw r1, #2604 ; 0xa2c + 18570: f44f 4240 mov.w r2, #49152 ; 0xc000 + 18574: 2300 movs r3, #0 + 18576: f7ff fe5f bl 18238 + 1857a: 6828 ldr r0, [r5, #0] + 1857c: f44f 4240 mov.w r2, #49152 ; 0xc000 + 18580: 2302 movs r3, #2 + 18582: f640 212c movw r1, #2604 ; 0xa2c + 18586: f7ff fe57 bl 18238 + 1858a: e9d4 2312 ldrd r2, r3, [r4, #72] ; 0x48 + 1858e: 2300 movs r3, #0 + 18590: f002 0208 and.w r2, r2, #8 + 18594: ea52 0003 orrs.w r0, r2, r3 + 18598: d002 beq.n 185a0 + 1859a: 6d23 ldr r3, [r4, #80] ; 0x50 + 1859c: 2b03 cmp r3, #3 + 1859e: d800 bhi.n 185a2 + 185a0: bdf8 pop {r3, r4, r5, r6, r7, pc} + 185a2: f243 40bc movw r0, #13500 ; 0x34bc + 185a6: f24f 359d movw r5, #62365 ; 0xf39d + 185aa: f2c0 0004 movt r0, #4 + 185ae: f2c0 0500 movt r5, #0 + 185b2: 47a8 blx r5 + 185b4: e9d4 2312 ldrd r2, r3, [r4, #72] ; 0x48 + 185b8: 2300 movs r3, #0 + 185ba: f002 0208 and.w r2, r2, #8 + 185be: ea52 0103 orrs.w r1, r2, r3 + 185c2: d0ed beq.n 185a0 + 185c4: 6d23 ldr r3, [r4, #80] ; 0x50 + 185c6: 2b03 cmp r3, #3 + 185c8: d9ea bls.n 185a0 + 185ca: f243 40f4 movw r0, #13556 ; 0x34f4 + 185ce: 6a62 ldr r2, [r4, #36] ; 0x24 + 185d0: 6a21 ldr r1, [r4, #32] + 185d2: f2c0 0004 movt r0, #4 + 185d6: 47a8 blx r5 + 185d8: e9d4 2312 ldrd r2, r3, [r4, #72] ; 0x48 + 185dc: 2300 movs r3, #0 + 185de: f002 0208 and.w r2, r2, #8 + 185e2: ea52 0003 orrs.w r0, r2, r3 + 185e6: d0db beq.n 185a0 + 185e8: 6d23 ldr r3, [r4, #80] ; 0x50 + 185ea: 2b03 cmp r3, #3 + 185ec: d9d8 bls.n 185a0 + 185ee: f243 502c movw r0, #13612 ; 0x352c + 185f2: 6821 ldr r1, [r4, #0] + 185f4: 6862 ldr r2, [r4, #4] + 185f6: f2c0 0004 movt r0, #4 + 185fa: 47a8 blx r5 + 185fc: e9d4 2312 ldrd r2, r3, [r4, #72] ; 0x48 + 18600: 2300 movs r3, #0 + 18602: f002 0208 and.w r2, r2, #8 + 18606: ea52 0103 orrs.w r1, r2, r3 + 1860a: d0c9 beq.n 185a0 + 1860c: 6d23 ldr r3, [r4, #80] ; 0x50 + 1860e: 2b03 cmp r3, #3 + 18610: d9c6 bls.n 185a0 + 18612: f243 5064 movw r0, #13668 ; 0x3564 + 18616: 68e2 ldr r2, [r4, #12] + 18618: 68a1 ldr r1, [r4, #8] + 1861a: f2c0 0004 movt r0, #4 + 1861e: 47a8 blx r5 + 18620: e9d4 2312 ldrd r2, r3, [r4, #72] ; 0x48 + 18624: 2300 movs r3, #0 + 18626: f002 0208 and.w r2, r2, #8 + 1862a: ea52 0003 orrs.w r0, r2, r3 + 1862e: d0b7 beq.n 185a0 + 18630: 6d23 ldr r3, [r4, #80] ; 0x50 + 18632: 2b03 cmp r3, #3 + 18634: d9b4 bls.n 185a0 + 18636: f243 5094 movw r0, #13716 ; 0x3594 + 1863a: 6aa1 ldr r1, [r4, #40] ; 0x28 + 1863c: f2c0 0004 movt r0, #4 + 18640: 47a8 blx r5 + 18642: e9d4 2312 ldrd r2, r3, [r4, #72] ; 0x48 + 18646: 2300 movs r3, #0 + 18648: f002 0208 and.w r2, r2, #8 + 1864c: ea52 0103 orrs.w r1, r2, r3 + 18650: 4626 mov r6, r4 + 18652: d0a5 beq.n 185a0 + 18654: 6d23 ldr r3, [r4, #80] ; 0x50 + 18656: 2b03 cmp r3, #3 + 18658: d9a2 bls.n 185a0 + 1865a: f243 50b4 movw r0, #13748 ; 0x35b4 + 1865e: 6ae1 ldr r1, [r4, #44] ; 0x2c + 18660: f2c0 0004 movt r0, #4 + 18664: 47a8 blx r5 + 18666: e9d4 2312 ldrd r2, r3, [r4, #72] ; 0x48 + 1866a: 2300 movs r3, #0 + 1866c: f002 0208 and.w r2, r2, #8 + 18670: ea52 0003 orrs.w r0, r2, r3 + 18674: d094 beq.n 185a0 + 18676: 6d23 ldr r3, [r4, #80] ; 0x50 + 18678: 2b03 cmp r3, #3 + 1867a: d991 bls.n 185a0 + 1867c: f243 50d4 movw r0, #13780 ; 0x35d4 + 18680: 6b21 ldr r1, [r4, #48] ; 0x30 + 18682: f2c0 0004 movt r0, #4 + 18686: 47a8 blx r5 + 18688: e9d4 2312 ldrd r2, r3, [r4, #72] ; 0x48 + 1868c: 2300 movs r3, #0 + 1868e: f002 0208 and.w r2, r2, #8 + 18692: ea52 0103 orrs.w r1, r2, r3 + 18696: d083 beq.n 185a0 + 18698: 6d23 ldr r3, [r4, #80] ; 0x50 + 1869a: 2b03 cmp r3, #3 + 1869c: d980 bls.n 185a0 + 1869e: f243 50f4 movw r0, #13812 ; 0x35f4 + 186a2: 6921 ldr r1, [r4, #16] + 186a4: f2c0 0004 movt r0, #4 + 186a8: 47a8 blx r5 + 186aa: e9d4 2312 ldrd r2, r3, [r4, #72] ; 0x48 + 186ae: 2300 movs r3, #0 + 186b0: f002 0208 and.w r2, r2, #8 + 186b4: ea52 0003 orrs.w r0, r2, r3 + 186b8: f43f af72 beq.w 185a0 + 186bc: 6d23 ldr r3, [r4, #80] ; 0x50 + 186be: 2b03 cmp r3, #3 + 186c0: f67f af6e bls.w 185a0 + 186c4: f243 6014 movw r0, #13844 ; 0x3614 + 186c8: 69a1 ldr r1, [r4, #24] + 186ca: f2c0 0004 movt r0, #4 + 186ce: 47a8 blx r5 + 186d0: e9d4 2312 ldrd r2, r3, [r4, #72] ; 0x48 + 186d4: 2300 movs r3, #0 + 186d6: f002 0208 and.w r2, r2, #8 + 186da: ea52 0103 orrs.w r1, r2, r3 + 186de: f43f af5f beq.w 185a0 + 186e2: 6d23 ldr r3, [r4, #80] ; 0x50 + 186e4: 2b03 cmp r3, #3 + 186e6: f67f af5b bls.w 185a0 + 186ea: f243 50f4 movw r0, #13812 ; 0x35f4 + 186ee: 6921 ldr r1, [r4, #16] + 186f0: f2c0 0004 movt r0, #4 + 186f4: 47a8 blx r5 + 186f6: e9d4 2312 ldrd r2, r3, [r4, #72] ; 0x48 + 186fa: 2300 movs r3, #0 + 186fc: f002 0208 and.w r2, r2, #8 + 18700: ea52 0003 orrs.w r0, r2, r3 + 18704: f43f af4c beq.w 185a0 + 18708: 6d33 ldr r3, [r6, #80] ; 0x50 + 1870a: 2b03 cmp r3, #3 + 1870c: f67f af48 bls.w 185a0 + 18710: f243 6034 movw r0, #13876 ; 0x3634 + 18714: 69f1 ldr r1, [r6, #28] + 18716: f2c0 0004 movt r0, #4 + 1871a: 47a8 blx r5 + 1871c: bdf8 pop {r3, r4, r5, r6, r7, pc} + 1871e: bf00 nop + +00018720 : + 18720: b570 push {r4, r5, r6, lr} + 18722: 4604 mov r4, r0 + 18724: 460d mov r5, r1 + 18726: b2d3 uxtb r3, r2 + 18728: 6800 ldr r0, [r0, #0] + 1872a: f640 414c movw r1, #3148 ; 0xc4c + 1872e: 22ff movs r2, #255 ; 0xff + 18730: f7ff fd82 bl 18238 + 18734: 6820 ldr r0, [r4, #0] + 18736: b2eb uxtb r3, r5 + 18738: f640 414c movw r1, #3148 ; 0xc4c + 1873c: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} + 18740: f44f 027f mov.w r2, #16711680 ; 0xff0000 + 18744: f7ff bd78 b.w 18238 + +00018748 : + 18748: b570 push {r4, r5, r6, lr} + 1874a: 4604 mov r4, r0 + 1874c: 4615 mov r5, r2 + 1874e: 460b mov r3, r1 + 18750: 6800 ldr r0, [r0, #0] + 18752: f640 0124 movw r1, #2084 ; 0x824 + 18756: 220e movs r2, #14 + 18758: f7ff fd6e bl 18238 + 1875c: 6820 ldr r0, [r4, #0] + 1875e: 462b mov r3, r5 + 18760: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} + 18764: f640 0124 movw r1, #2084 ; 0x824 + 18768: f44f 02e0 mov.w r2, #7340032 ; 0x700000 + 1876c: f7ff bd64 b.w 18238 + +00018770 : + 18770: f240 60e0 movw r0, #1760 ; 0x6e0 + 18774: f2c1 0000 movt r0, #4096 ; 0x1000 + 18778: f890 305b ldrb.w r3, [r0, #91] ; 0x5b + 1877c: 428b cmp r3, r1 + 1877e: d027 beq.n 187d0 + 18780: e9d0 2312 ldrd r2, r3, [r0, #72] ; 0x48 + 18784: b570 push {r4, r5, r6, lr} + 18786: 2460 movs r4, #96 ; 0x60 + 18788: f2c4 0400 movt r4, #16384 ; 0x4000 + 1878c: f880 105b strb.w r1, [r0, #91] ; 0x5b + 18790: 6825 ldr r5, [r4, #0] + 18792: f001 013f and.w r1, r1, #63 ; 0x3f + 18796: f025 557f bic.w r5, r5, #1069547520 ; 0x3fc00000 + 1879a: f425 1570 bic.w r5, r5, #3932160 ; 0x3c0000 + 1879e: ea41 1681 orr.w r6, r1, r1, lsl #6 + 187a2: f402 4200 and.w r2, r2, #32768 ; 0x8000 + 187a6: 2300 movs r3, #0 + 187a8: ea45 4586 orr.w r5, r5, r6, lsl #18 + 187ac: 6025 str r5, [r4, #0] + 187ae: ea52 0403 orrs.w r4, r2, r3 + 187b2: d002 beq.n 187ba + 187b4: 6d03 ldr r3, [r0, #80] ; 0x50 + 187b6: 2b03 cmp r3, #3 + 187b8: d800 bhi.n 187bc + 187ba: bd70 pop {r4, r5, r6, pc} + 187bc: f243 6058 movw r0, #13912 ; 0x3658 + 187c0: f24f 339d movw r3, #62365 ; 0xf39d + 187c4: f2c0 0004 movt r0, #4 + 187c8: f2c0 0300 movt r3, #0 + 187cc: 4798 blx r3 + 187ce: bd70 pop {r4, r5, r6, pc} + 187d0: 4770 bx lr + 187d2: bf00 nop + +000187d4 : + 187d4: f240 63e0 movw r3, #1760 ; 0x6e0 + 187d8: f2c1 0300 movt r3, #4096 ; 0x1000 + 187dc: f893 0041 ldrb.w r0, [r3, #65] ; 0x41 + 187e0: f000 003f and.w r0, r0, #63 ; 0x3f + 187e4: 4770 bx lr + 187e6: bf00 nop + +000187e8 : + 187e8: f240 63e0 movw r3, #1760 ; 0x6e0 + 187ec: f2c1 0300 movt r3, #4096 ; 0x1000 + 187f0: b410 push {r4} + 187f2: f893 2041 ldrb.w r2, [r3, #65] ; 0x41 + 187f6: 2401 movs r4, #1 + 187f8: f002 023f and.w r2, r2, #63 ; 0x3f + 187fc: f883 405a strb.w r4, [r3, #90] ; 0x5a + 18800: f883 205c strb.w r2, [r3, #92] ; 0x5c + 18804: 4611 mov r1, r2 + 18806: f85d 4b04 ldr.w r4, [sp], #4 + 1880a: f7ff bfb1 b.w 18770 + 1880e: bf00 nop + +00018810 : + 18810: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} + 18814: f240 64e0 movw r4, #1760 ; 0x6e0 + 18818: f2c1 0400 movt r4, #4096 ; 0x1000 + 1881c: 6ee1 ldr r1, [r4, #108] ; 0x6c + 1881e: 6f23 ldr r3, [r4, #112] ; 0x70 + 18820: f894 805b ldrb.w r8, [r4, #91] ; 0x5b + 18824: 4299 cmp r1, r3 + 18826: f894 a076 ldrb.w sl, [r4, #118] ; 0x76 + 1882a: f894 5077 ldrb.w r5, [r4, #119] ; 0x77 + 1882e: f000 808b beq.w 18948 + 18832: e9d4 2312 ldrd r2, r3, [r4, #72] ; 0x48 + 18836: f246 6967 movw r9, #26215 ; 0x6667 + 1883a: 4607 mov r7, r0 + 1883c: f640 4035 movw r0, #3125 ; 0xc35 + 18840: f2c6 6966 movt r9, #26214 ; 0x6666 + 18844: 6721 str r1, [r4, #112] ; 0x70 + 18846: 6e21 ldr r1, [r4, #96] ; 0x60 + 18848: f402 4200 and.w r2, r2, #32768 ; 0x8000 + 1884c: fb00 f101 mul.w r1, r0, r1 + 18850: fb89 6901 smull r6, r9, r9, r1 + 18854: 2300 movs r3, #0 + 18856: 17c9 asrs r1, r1, #31 + 18858: ea52 0003 orrs.w r0, r2, r3 + 1885c: ebc1 2969 rsb r9, r1, r9, asr #9 + 18860: d003 beq.n 1886a + 18862: 6d20 ldr r0, [r4, #80] ; 0x50 + 18864: 2803 cmp r0, #3 + 18866: f200 8090 bhi.w 1898a + 1886a: 6ea1 ldr r1, [r4, #104] ; 0x68 + 1886c: 4589 cmp r9, r1 + 1886e: bfd4 ite le + 18870: ebc9 0101 rsble r1, r9, r1 + 18874: ebc1 0109 rsbgt r1, r1, r9 + 18878: 2914 cmp r1, #20 + 1887a: dd1d ble.n 188b8 + 1887c: f240 61e0 movw r1, #1760 ; 0x6e0 + 18880: 6da0 ldr r0, [r4, #88] ; 0x58 + 18882: f2c1 0100 movt r1, #4096 ; 0x1000 + 18886: f020 407f bic.w r0, r0, #4278190080 ; 0xff000000 + 1888a: f020 00ff bic.w r0, r0, #255 ; 0xff + 1888e: b998 cbnz r0, 188b8 + 18890: ea52 0603 orrs.w r6, r2, r3 + 18894: d00b beq.n 188ae + 18896: 6d0b ldr r3, [r1, #80] ; 0x50 + 18898: 2b03 cmp r3, #3 + 1889a: d908 bls.n 188ae + 1889c: f243 7004 movw r0, #14084 ; 0x3704 + 188a0: f24f 339d movw r3, #62365 ; 0xf39d + 188a4: f2c0 0004 movt r0, #4 + 188a8: f2c0 0300 movt r3, #0 + 188ac: 4798 blx r3 + 188ae: 2301 movs r3, #1 + 188b0: f884 3059 strb.w r3, [r4, #89] ; 0x59 + 188b4: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + 188b8: f240 61e0 movw r1, #1760 ; 0x6e0 + 188bc: f894 e05a ldrb.w lr, [r4, #90] ; 0x5a + 188c0: 2000 movs r0, #0 + 188c2: f8c4 9068 str.w r9, [r4, #104] ; 0x68 + 188c6: f2c1 0100 movt r1, #4096 ; 0x1000 + 188ca: f884 0059 strb.w r0, [r4, #89] ; 0x59 + 188ce: f1be 0f00 cmp.w lr, #0 + 188d2: d130 bne.n 18936 + 188d4: 45d1 cmp r9, sl + 188d6: dd4d ble.n 18974 + 188d8: 2101 movs r1, #1 + 188da: f884 105a strb.w r1, [r4, #90] ; 0x5a + 188de: 45a9 cmp r9, r5 + 188e0: dd63 ble.n 189aa + 188e2: ebc5 0609 rsb r6, r5, r9 + 188e6: 10b6 asrs r6, r6, #2 + 188e8: 3601 adds r6, #1 + 188ea: ea52 0003 orrs.w r0, r2, r3 + 188ee: b2f6 uxtb r6, r6 + 188f0: d006 beq.n 18900 + 188f2: f240 6ae0 movw sl, #1760 ; 0x6e0 + 188f6: 6d23 ldr r3, [r4, #80] ; 0x50 + 188f8: f2c1 0a00 movt sl, #4096 ; 0x1000 + 188fc: 2b03 cmp r3, #3 + 188fe: d871 bhi.n 189e4 + 18900: 45a9 cmp r9, r5 + 18902: bfc8 it gt + 18904: 44b0 addgt r8, r6 + 18906: dd3a ble.n 1897e + 18908: f388 0106 usat r1, #6, r8 + 1890c: b2c9 uxtb r1, r1 + 1890e: 4638 mov r0, r7 + 18910: f7ff ff2e bl 18770 + 18914: e9d4 2312 ldrd r2, r3, [r4, #72] ; 0x48 + 18918: 2300 movs r3, #0 + 1891a: f402 4200 and.w r2, r2, #32768 ; 0x8000 + 1891e: ea52 0103 orrs.w r1, r2, r3 + 18922: d006 beq.n 18932 + 18924: f240 63e0 movw r3, #1760 ; 0x6e0 + 18928: 6d22 ldr r2, [r4, #80] ; 0x50 + 1892a: f2c1 0300 movt r3, #4096 ; 0x1000 + 1892e: 2a03 cmp r2, #3 + 18930: d849 bhi.n 189c6 + 18932: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + 18936: 45a9 cmp r9, r5 + 18938: dad1 bge.n 188de + 1893a: 426e negs r6, r5 + 1893c: 45b1 cmp r9, r6 + 1893e: bfc8 it gt + 18940: f881 005a strbgt.w r0, [r1, #90] ; 0x5a + 18944: dceb bgt.n 1891e + 18946: e7ca b.n 188de + 18948: e9d4 2312 ldrd r2, r3, [r4, #72] ; 0x48 + 1894c: 2300 movs r3, #0 + 1894e: f402 4200 and.w r2, r2, #32768 ; 0x8000 + 18952: ea52 0003 orrs.w r0, r2, r3 + 18956: d0ec beq.n 18932 + 18958: 6d23 ldr r3, [r4, #80] ; 0x50 + 1895a: 2b03 cmp r3, #3 + 1895c: d9e9 bls.n 18932 + 1895e: f243 6090 movw r0, #13968 ; 0x3690 + 18962: f24f 339d movw r3, #62365 ; 0xf39d + 18966: f2c0 0004 movt r0, #4 + 1896a: f2c0 0300 movt r3, #0 + 1896e: 4798 blx r3 + 18970: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + 18974: f1ca 0600 rsb r6, sl, #0 + 18978: 45b1 cmp r9, r6 + 1897a: dad0 bge.n 1891e + 1897c: e7ac b.n 188d8 + 1897e: 426d negs r5, r5 + 18980: 45a9 cmp r9, r5 + 18982: bfb8 it lt + 18984: ebc6 0808 rsblt r8, r6, r8 + 18988: e7be b.n 18908 + 1898a: f243 60d0 movw r0, #14032 ; 0x36d0 + 1898e: f24f 339d movw r3, #62365 ; 0xf39d + 18992: f2c0 0004 movt r0, #4 + 18996: f2c0 0300 movt r3, #0 + 1899a: 4649 mov r1, r9 + 1899c: 4798 blx r3 + 1899e: e9d4 2312 ldrd r2, r3, [r4, #72] ; 0x48 + 189a2: 2300 movs r3, #0 + 189a4: f402 4200 and.w r2, r2, #32768 ; 0x8000 + 189a8: e75f b.n 1886a + 189aa: 4269 negs r1, r5 + 189ac: 4589 cmp r9, r1 + 189ae: bfbf itttt lt + 189b0: ebc9 0605 rsblt r6, r9, r5 + 189b4: 10b6 asrlt r6, r6, #2 + 189b6: 3601 addlt r6, #1 + 189b8: b2f6 uxtblt r6, r6 + 189ba: bfa8 it ge + 189bc: 2601 movge r6, #1 + 189be: ea52 0003 orrs.w r0, r2, r3 + 189c2: d196 bne.n 188f2 + 189c4: e79c b.n 18900 + 189c6: f243 7078 movw r0, #14200 ; 0x3778 + 189ca: f24f 349d movw r4, #62365 ; 0xf39d + 189ce: f893 105b ldrb.w r1, [r3, #91] ; 0x5b + 189d2: f2c0 0400 movt r4, #0 + 189d6: f893 205c ldrb.w r2, [r3, #92] ; 0x5c + 189da: f2c0 0004 movt r0, #4 + 189de: 47a0 blx r4 + 189e0: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + 189e4: f243 703c movw r0, #14140 ; 0x373c + 189e8: f24f 339d movw r3, #62365 ; 0xf39d + 189ec: f2c0 0004 movt r0, #4 + 189f0: f2c0 0300 movt r3, #0 + 189f4: 4631 mov r1, r6 + 189f6: 4798 blx r3 + 189f8: f89a 305a ldrb.w r3, [sl, #90] ; 0x5a + 189fc: 2b00 cmp r3, #0 + 189fe: f47f af7f bne.w 18900 + 18a02: e9da 2312 ldrd r2, r3, [sl, #72] ; 0x48 + 18a06: 2300 movs r3, #0 + 18a08: f402 4200 and.w r2, r2, #32768 ; 0x8000 + 18a0c: e787 b.n 1891e + 18a0e: bf00 nop + +00018a10 : + 18a10: b470 push {r4, r5, r6} + 18a12: 3008 adds r0, #8 + 18a14: 3108 adds r1, #8 + 18a16: 2600 movs r6, #0 + 18a18: e951 2302 ldrd r2, r3, [r1, #-8] + 18a1c: e950 4502 ldrd r4, r5, [r0, #-8] + 18a20: 18a4 adds r4, r4, r2 + 18a22: 415d adcs r5, r3 + 18a24: e940 4502 strd r4, r5, [r0, #-8] + 18a28: e9d0 2300 ldrd r2, r3, [r0] + 18a2c: e8f1 4504 ldrd r4, r5, [r1], #16 + 18a30: 3602 adds r6, #2 + 18a32: 1912 adds r2, r2, r4 + 18a34: 416b adcs r3, r5 + 18a36: 2e0a cmp r6, #10 + 18a38: e8e0 2304 strd r2, r3, [r0], #16 + 18a3c: d1ec bne.n 18a18 + 18a3e: bc70 pop {r4, r5, r6} + 18a40: 4770 bx lr + 18a42: bf00 nop + +00018a44 : + 18a44: 6813 ldr r3, [r2, #0] + 18a46: b5f0 push {r4, r5, r6, r7, lr} + 18a48: 680c ldr r4, [r1, #0] + 18a4a: fb84 4503 smull r4, r5, r4, r3 + 18a4e: e9c0 4500 strd r4, r5, [r0] + 18a52: 6813 ldr r3, [r2, #0] + 18a54: 688c ldr r4, [r1, #8] + 18a56: 680e ldr r6, [r1, #0] + 18a58: fb84 4503 smull r4, r5, r4, r3 + 18a5c: 6893 ldr r3, [r2, #8] + 18a5e: fbc3 4506 smlal r4, r5, r3, r6 + 18a62: e9c0 4502 strd r4, r5, [r0, #8] + 18a66: 6893 ldr r3, [r2, #8] + 18a68: 688e ldr r6, [r1, #8] + 18a6a: 17dd asrs r5, r3, #31 + 18a6c: 17f7 asrs r7, r6, #31 + 18a6e: 19b6 adds r6, r6, r6 + 18a70: fb06 fe05 mul.w lr, r6, r5 + 18a74: 417f adcs r7, r7 + 18a76: fba6 4503 umull r4, r5, r6, r3 + 18a7a: fb03 e307 mla r3, r3, r7, lr + 18a7e: 6916 ldr r6, [r2, #16] + 18a80: 680f ldr r7, [r1, #0] + 18a82: 441d add r5, r3 + 18a84: fbc6 4507 smlal r4, r5, r6, r7 + 18a88: 6813 ldr r3, [r2, #0] + 18a8a: 690e ldr r6, [r1, #16] + 18a8c: fbc3 4506 smlal r4, r5, r3, r6 + 18a90: e9c0 4504 strd r4, r5, [r0, #16] + 18a94: 6893 ldr r3, [r2, #8] + 18a96: 690c ldr r4, [r1, #16] + 18a98: 688e ldr r6, [r1, #8] + 18a9a: fb84 4503 smull r4, r5, r4, r3 + 18a9e: 6913 ldr r3, [r2, #16] + 18aa0: 680f ldr r7, [r1, #0] + 18aa2: fbc3 4506 smlal r4, r5, r3, r6 + 18aa6: 6993 ldr r3, [r2, #24] + 18aa8: 698e ldr r6, [r1, #24] + 18aaa: fbc3 4507 smlal r4, r5, r3, r7 + 18aae: 6813 ldr r3, [r2, #0] + 18ab0: fbc3 4506 smlal r4, r5, r3, r6 + 18ab4: e9c0 4506 strd r4, r5, [r0, #24] + 18ab8: 6893 ldr r3, [r2, #8] + 18aba: 698c ldr r4, [r1, #24] + 18abc: 688f ldr r7, [r1, #8] + 18abe: fb84 4503 smull r4, r5, r4, r3 + 18ac2: 6996 ldr r6, [r2, #24] + 18ac4: 690b ldr r3, [r1, #16] + 18ac6: fbc6 4507 smlal r4, r5, r6, r7 + 18aca: 6916 ldr r6, [r2, #16] + 18acc: 1924 adds r4, r4, r4 + 18ace: 416d adcs r5, r5 + 18ad0: fbc6 4503 smlal r4, r5, r6, r3 + 18ad4: 680f ldr r7, [r1, #0] + 18ad6: 6a13 ldr r3, [r2, #32] + 18ad8: 6a0e ldr r6, [r1, #32] + 18ada: fbc3 4507 smlal r4, r5, r3, r7 + 18ade: 6813 ldr r3, [r2, #0] + 18ae0: fbc3 4506 smlal r4, r5, r3, r6 + 18ae4: e9c0 4508 strd r4, r5, [r0, #32] + 18ae8: 6913 ldr r3, [r2, #16] + 18aea: 698c ldr r4, [r1, #24] + 18aec: 690e ldr r6, [r1, #16] + 18aee: fb84 4503 smull r4, r5, r4, r3 + 18af2: 6993 ldr r3, [r2, #24] + 18af4: 688f ldr r7, [r1, #8] + 18af6: fbc3 4506 smlal r4, r5, r3, r6 + 18afa: 6a13 ldr r3, [r2, #32] + 18afc: 6a0e ldr r6, [r1, #32] + 18afe: fbc3 4507 smlal r4, r5, r3, r7 + 18b02: 6893 ldr r3, [r2, #8] + 18b04: 680f ldr r7, [r1, #0] + 18b06: fbc3 4506 smlal r4, r5, r3, r6 + 18b0a: 6a93 ldr r3, [r2, #40] ; 0x28 + 18b0c: 6a8e ldr r6, [r1, #40] ; 0x28 + 18b0e: fbc3 4507 smlal r4, r5, r3, r7 + 18b12: 6813 ldr r3, [r2, #0] + 18b14: fbc3 4506 smlal r4, r5, r3, r6 + 18b18: e9c0 450a strd r4, r5, [r0, #40] ; 0x28 + 18b1c: 6a93 ldr r3, [r2, #40] ; 0x28 + 18b1e: 688c ldr r4, [r1, #8] + 18b20: 698e ldr r6, [r1, #24] + 18b22: fb84 4503 smull r4, r5, r4, r3 + 18b26: 6993 ldr r3, [r2, #24] + 18b28: 6a8f ldr r7, [r1, #40] ; 0x28 + 18b2a: fbc3 4506 smlal r4, r5, r3, r6 + 18b2e: 6896 ldr r6, [r2, #8] + 18b30: 690b ldr r3, [r1, #16] + 18b32: fbc6 4507 smlal r4, r5, r6, r7 + 18b36: 6a17 ldr r7, [r2, #32] + 18b38: 1924 adds r4, r4, r4 + 18b3a: 416d adcs r5, r5 + 18b3c: fbc7 4503 smlal r4, r5, r7, r3 + 18b40: 6a0e ldr r6, [r1, #32] + 18b42: 6913 ldr r3, [r2, #16] + 18b44: 680f ldr r7, [r1, #0] + 18b46: fbc3 4506 smlal r4, r5, r3, r6 + 18b4a: 6b13 ldr r3, [r2, #48] ; 0x30 + 18b4c: 6b0e ldr r6, [r1, #48] ; 0x30 + 18b4e: fbc3 4507 smlal r4, r5, r3, r7 + 18b52: 6813 ldr r3, [r2, #0] + 18b54: fbc3 4506 smlal r4, r5, r3, r6 + 18b58: e9c0 450c strd r4, r5, [r0, #48] ; 0x30 + 18b5c: 6993 ldr r3, [r2, #24] + 18b5e: 6a0c ldr r4, [r1, #32] + 18b60: 698e ldr r6, [r1, #24] + 18b62: fb84 4503 smull r4, r5, r4, r3 + 18b66: 6a13 ldr r3, [r2, #32] + 18b68: 690f ldr r7, [r1, #16] + 18b6a: fbc3 4506 smlal r4, r5, r3, r6 + 18b6e: 6a93 ldr r3, [r2, #40] ; 0x28 + 18b70: 6a8e ldr r6, [r1, #40] ; 0x28 + 18b72: fbc3 4507 smlal r4, r5, r3, r7 + 18b76: 6913 ldr r3, [r2, #16] + 18b78: 688f ldr r7, [r1, #8] + 18b7a: fbc3 4506 smlal r4, r5, r3, r6 + 18b7e: 6b13 ldr r3, [r2, #48] ; 0x30 + 18b80: 6b0e ldr r6, [r1, #48] ; 0x30 + 18b82: fbc3 4507 smlal r4, r5, r3, r7 + 18b86: 6893 ldr r3, [r2, #8] + 18b88: 680f ldr r7, [r1, #0] + 18b8a: fbc3 4506 smlal r4, r5, r3, r6 + 18b8e: 6b93 ldr r3, [r2, #56] ; 0x38 + 18b90: 6b8e ldr r6, [r1, #56] ; 0x38 + 18b92: fbc3 4507 smlal r4, r5, r3, r7 + 18b96: 6813 ldr r3, [r2, #0] + 18b98: fbc3 4506 smlal r4, r5, r3, r6 + 18b9c: e9c0 450e strd r4, r5, [r0, #56] ; 0x38 + 18ba0: 6993 ldr r3, [r2, #24] + 18ba2: 6a8c ldr r4, [r1, #40] ; 0x28 + 18ba4: 698f ldr r7, [r1, #24] + 18ba6: fb84 4503 smull r4, r5, r4, r3 + 18baa: 6a93 ldr r3, [r2, #40] ; 0x28 + 18bac: 688e ldr r6, [r1, #8] + 18bae: fbc3 4507 smlal r4, r5, r3, r7 + 18bb2: 6b93 ldr r3, [r2, #56] ; 0x38 + 18bb4: 6b8f ldr r7, [r1, #56] ; 0x38 + 18bb6: fbc3 4506 smlal r4, r5, r3, r6 + 18bba: 6896 ldr r6, [r2, #8] + 18bbc: 6a0b ldr r3, [r1, #32] + 18bbe: fbc6 4507 smlal r4, r5, r6, r7 + 18bc2: 6a16 ldr r6, [r2, #32] + 18bc4: 1924 adds r4, r4, r4 + 18bc6: 416d adcs r5, r5 + 18bc8: fbc6 4503 smlal r4, r5, r6, r3 + 18bcc: 690f ldr r7, [r1, #16] + 18bce: 6b13 ldr r3, [r2, #48] ; 0x30 + 18bd0: 6b0e ldr r6, [r1, #48] ; 0x30 + 18bd2: fbc3 4507 smlal r4, r5, r3, r7 + 18bd6: 6913 ldr r3, [r2, #16] + 18bd8: 680f ldr r7, [r1, #0] + 18bda: fbc3 4506 smlal r4, r5, r3, r6 + 18bde: 6c13 ldr r3, [r2, #64] ; 0x40 + 18be0: 6c0e ldr r6, [r1, #64] ; 0x40 + 18be2: fbc3 4507 smlal r4, r5, r3, r7 + 18be6: 6813 ldr r3, [r2, #0] + 18be8: fbc3 4506 smlal r4, r5, r3, r6 + 18bec: e9c0 4510 strd r4, r5, [r0, #64] ; 0x40 + 18bf0: 6a13 ldr r3, [r2, #32] + 18bf2: 6a8c ldr r4, [r1, #40] ; 0x28 + 18bf4: 6a0e ldr r6, [r1, #32] + 18bf6: fb84 4503 smull r4, r5, r4, r3 + 18bfa: 6a93 ldr r3, [r2, #40] ; 0x28 + 18bfc: 698f ldr r7, [r1, #24] + 18bfe: fbc3 4506 smlal r4, r5, r3, r6 + 18c02: 6b13 ldr r3, [r2, #48] ; 0x30 + 18c04: 6b0e ldr r6, [r1, #48] ; 0x30 + 18c06: fbc3 4507 smlal r4, r5, r3, r7 + 18c0a: 6993 ldr r3, [r2, #24] + 18c0c: 690f ldr r7, [r1, #16] + 18c0e: fbc3 4506 smlal r4, r5, r3, r6 + 18c12: 6b93 ldr r3, [r2, #56] ; 0x38 + 18c14: 6b8e ldr r6, [r1, #56] ; 0x38 + 18c16: fbc3 4507 smlal r4, r5, r3, r7 + 18c1a: 6913 ldr r3, [r2, #16] + 18c1c: 688f ldr r7, [r1, #8] + 18c1e: fbc3 4506 smlal r4, r5, r3, r6 + 18c22: 6c13 ldr r3, [r2, #64] ; 0x40 + 18c24: 6c0e ldr r6, [r1, #64] ; 0x40 + 18c26: fbc3 4507 smlal r4, r5, r3, r7 + 18c2a: 6893 ldr r3, [r2, #8] + 18c2c: 680f ldr r7, [r1, #0] + 18c2e: fbc3 4506 smlal r4, r5, r3, r6 + 18c32: 6c93 ldr r3, [r2, #72] ; 0x48 + 18c34: 6c8e ldr r6, [r1, #72] ; 0x48 + 18c36: fbc3 4507 smlal r4, r5, r3, r7 + 18c3a: 6813 ldr r3, [r2, #0] + 18c3c: fbc3 4506 smlal r4, r5, r3, r6 + 18c40: e9c0 4512 strd r4, r5, [r0, #72] ; 0x48 + 18c44: 6b93 ldr r3, [r2, #56] ; 0x38 + 18c46: 698c ldr r4, [r1, #24] + 18c48: 6a8e ldr r6, [r1, #40] ; 0x28 + 18c4a: fb84 4503 smull r4, r5, r4, r3 + 18c4e: 6a93 ldr r3, [r2, #40] ; 0x28 + 18c50: 6b8f ldr r7, [r1, #56] ; 0x38 + 18c52: fbc3 4506 smlal r4, r5, r3, r6 + 18c56: 6993 ldr r3, [r2, #24] + 18c58: 688e ldr r6, [r1, #8] + 18c5a: fbc3 4507 smlal r4, r5, r3, r7 + 18c5e: 6c93 ldr r3, [r2, #72] ; 0x48 + 18c60: 6c8f ldr r7, [r1, #72] ; 0x48 + 18c62: fbc3 4506 smlal r4, r5, r3, r6 + 18c66: 6896 ldr r6, [r2, #8] + 18c68: 6a0b ldr r3, [r1, #32] + 18c6a: fbc6 4507 smlal r4, r5, r6, r7 + 18c6e: 6b17 ldr r7, [r2, #48] ; 0x30 + 18c70: 1924 adds r4, r4, r4 + 18c72: 416d adcs r5, r5 + 18c74: fbc7 4503 smlal r4, r5, r7, r3 + 18c78: 6b0e ldr r6, [r1, #48] ; 0x30 + 18c7a: 6a13 ldr r3, [r2, #32] + 18c7c: 690f ldr r7, [r1, #16] + 18c7e: fbc3 4506 smlal r4, r5, r3, r6 + 18c82: 6c13 ldr r3, [r2, #64] ; 0x40 + 18c84: 6c0e ldr r6, [r1, #64] ; 0x40 + 18c86: fbc3 4507 smlal r4, r5, r3, r7 + 18c8a: 6913 ldr r3, [r2, #16] + 18c8c: fbc3 4506 smlal r4, r5, r3, r6 + 18c90: e9c0 4514 strd r4, r5, [r0, #80] ; 0x50 + 18c94: 6a93 ldr r3, [r2, #40] ; 0x28 + 18c96: 6b0c ldr r4, [r1, #48] ; 0x30 + 18c98: 6a8e ldr r6, [r1, #40] ; 0x28 + 18c9a: fb84 4503 smull r4, r5, r4, r3 + 18c9e: 6b13 ldr r3, [r2, #48] ; 0x30 + 18ca0: 6a0f ldr r7, [r1, #32] + 18ca2: fbc3 4506 smlal r4, r5, r3, r6 + 18ca6: 6b93 ldr r3, [r2, #56] ; 0x38 + 18ca8: 6b8e ldr r6, [r1, #56] ; 0x38 + 18caa: fbc3 4507 smlal r4, r5, r3, r7 + 18cae: 6a13 ldr r3, [r2, #32] + 18cb0: 698f ldr r7, [r1, #24] + 18cb2: fbc3 4506 smlal r4, r5, r3, r6 + 18cb6: 6c13 ldr r3, [r2, #64] ; 0x40 + 18cb8: 6c0e ldr r6, [r1, #64] ; 0x40 + 18cba: fbc3 4507 smlal r4, r5, r3, r7 + 18cbe: 6993 ldr r3, [r2, #24] + 18cc0: 690f ldr r7, [r1, #16] + 18cc2: fbc3 4506 smlal r4, r5, r3, r6 + 18cc6: 6c93 ldr r3, [r2, #72] ; 0x48 + 18cc8: 6c8e ldr r6, [r1, #72] ; 0x48 + 18cca: fbc3 4507 smlal r4, r5, r3, r7 + 18cce: 6913 ldr r3, [r2, #16] + 18cd0: fbc3 4506 smlal r4, r5, r3, r6 + 18cd4: e9c0 4516 strd r4, r5, [r0, #88] ; 0x58 + 18cd8: 6a93 ldr r3, [r2, #40] ; 0x28 + 18cda: 6b8c ldr r4, [r1, #56] ; 0x38 + 18cdc: 6a8f ldr r7, [r1, #40] ; 0x28 + 18cde: fb84 4503 smull r4, r5, r4, r3 + 18ce2: 6b93 ldr r3, [r2, #56] ; 0x38 + 18ce4: 698e ldr r6, [r1, #24] + 18ce6: fbc3 4507 smlal r4, r5, r3, r7 + 18cea: 6c93 ldr r3, [r2, #72] ; 0x48 + 18cec: 6c8f ldr r7, [r1, #72] ; 0x48 + 18cee: fbc3 4506 smlal r4, r5, r3, r6 + 18cf2: 6996 ldr r6, [r2, #24] + 18cf4: 6b0b ldr r3, [r1, #48] ; 0x30 + 18cf6: fbc6 4507 smlal r4, r5, r6, r7 + 18cfa: 6b16 ldr r6, [r2, #48] ; 0x30 + 18cfc: 1924 adds r4, r4, r4 + 18cfe: 416d adcs r5, r5 + 18d00: fbc6 4503 smlal r4, r5, r6, r3 + 18d04: 6a0f ldr r7, [r1, #32] + 18d06: 6c13 ldr r3, [r2, #64] ; 0x40 + 18d08: 6c0e ldr r6, [r1, #64] ; 0x40 + 18d0a: fbc3 4507 smlal r4, r5, r3, r7 + 18d0e: 6a13 ldr r3, [r2, #32] + 18d10: fbc3 4506 smlal r4, r5, r3, r6 + 18d14: e9c0 4518 strd r4, r5, [r0, #96] ; 0x60 + 18d18: 6b13 ldr r3, [r2, #48] ; 0x30 + 18d1a: 6b8c ldr r4, [r1, #56] ; 0x38 + 18d1c: 6b0e ldr r6, [r1, #48] ; 0x30 + 18d1e: fb84 4503 smull r4, r5, r4, r3 + 18d22: 6b93 ldr r3, [r2, #56] ; 0x38 + 18d24: 6a8f ldr r7, [r1, #40] ; 0x28 + 18d26: fbc3 4506 smlal r4, r5, r3, r6 + 18d2a: 6c13 ldr r3, [r2, #64] ; 0x40 + 18d2c: 6c0e ldr r6, [r1, #64] ; 0x40 + 18d2e: fbc3 4507 smlal r4, r5, r3, r7 + 18d32: 6a93 ldr r3, [r2, #40] ; 0x28 + 18d34: 6a0f ldr r7, [r1, #32] + 18d36: fbc3 4506 smlal r4, r5, r3, r6 + 18d3a: 6c93 ldr r3, [r2, #72] ; 0x48 + 18d3c: 6c8e ldr r6, [r1, #72] ; 0x48 + 18d3e: fbc3 4507 smlal r4, r5, r3, r7 + 18d42: 6a13 ldr r3, [r2, #32] + 18d44: fbc3 4506 smlal r4, r5, r3, r6 + 18d48: e9c0 451a strd r4, r5, [r0, #104] ; 0x68 + 18d4c: 6c93 ldr r3, [r2, #72] ; 0x48 + 18d4e: 6a8c ldr r4, [r1, #40] ; 0x28 + 18d50: 6b8e ldr r6, [r1, #56] ; 0x38 + 18d52: fb84 4503 smull r4, r5, r4, r3 + 18d56: 6b93 ldr r3, [r2, #56] ; 0x38 + 18d58: 6c8f ldr r7, [r1, #72] ; 0x48 + 18d5a: fbc3 4506 smlal r4, r5, r3, r6 + 18d5e: 6a96 ldr r6, [r2, #40] ; 0x28 + 18d60: 6b0b ldr r3, [r1, #48] ; 0x30 + 18d62: fbc6 4507 smlal r4, r5, r6, r7 + 18d66: 6c17 ldr r7, [r2, #64] ; 0x40 + 18d68: 1924 adds r4, r4, r4 + 18d6a: 416d adcs r5, r5 + 18d6c: fbc7 4503 smlal r4, r5, r7, r3 + 18d70: 6c0e ldr r6, [r1, #64] ; 0x40 + 18d72: 6b13 ldr r3, [r2, #48] ; 0x30 + 18d74: fbc3 4506 smlal r4, r5, r3, r6 + 18d78: e9c0 451c strd r4, r5, [r0, #112] ; 0x70 + 18d7c: 6b93 ldr r3, [r2, #56] ; 0x38 + 18d7e: 6c0c ldr r4, [r1, #64] ; 0x40 + 18d80: 6b8e ldr r6, [r1, #56] ; 0x38 + 18d82: fb84 4503 smull r4, r5, r4, r3 + 18d86: 6c13 ldr r3, [r2, #64] ; 0x40 + 18d88: 6b0f ldr r7, [r1, #48] ; 0x30 + 18d8a: fbc3 4506 smlal r4, r5, r3, r6 + 18d8e: 6c93 ldr r3, [r2, #72] ; 0x48 + 18d90: 6c8e ldr r6, [r1, #72] ; 0x48 + 18d92: fbc3 4507 smlal r4, r5, r3, r7 + 18d96: 6b13 ldr r3, [r2, #48] ; 0x30 + 18d98: fbc3 4506 smlal r4, r5, r3, r6 + 18d9c: e9c0 451e strd r4, r5, [r0, #120] ; 0x78 + 18da0: 6b93 ldr r3, [r2, #56] ; 0x38 + 18da2: 6c8c ldr r4, [r1, #72] ; 0x48 + 18da4: 6c96 ldr r6, [r2, #72] ; 0x48 + 18da6: fb84 4503 smull r4, r5, r4, r3 + 18daa: 6b8f ldr r7, [r1, #56] ; 0x38 + 18dac: 6c0b ldr r3, [r1, #64] ; 0x40 + 18dae: fbc6 4507 smlal r4, r5, r6, r7 + 18db2: 6c16 ldr r6, [r2, #64] ; 0x40 + 18db4: 1924 adds r4, r4, r4 + 18db6: 416d adcs r5, r5 + 18db8: fbc6 4503 smlal r4, r5, r6, r3 + 18dbc: e9c0 4520 strd r4, r5, [r0, #128] ; 0x80 + 18dc0: 6c13 ldr r3, [r2, #64] ; 0x40 + 18dc2: 6c8c ldr r4, [r1, #72] ; 0x48 + 18dc4: 6c0e ldr r6, [r1, #64] ; 0x40 + 18dc6: fb84 4503 smull r4, r5, r4, r3 + 18dca: 6c93 ldr r3, [r2, #72] ; 0x48 + 18dcc: fbc3 4506 smlal r4, r5, r3, r6 + 18dd0: e9c0 4522 strd r4, r5, [r0, #136] ; 0x88 + 18dd4: 6c8c ldr r4, [r1, #72] ; 0x48 + 18dd6: 6c91 ldr r1, [r2, #72] ; 0x48 + 18dd8: 17e5 asrs r5, r4, #31 + 18dda: 17cb asrs r3, r1, #31 + 18ddc: 1924 adds r4, r4, r4 + 18dde: fb04 f603 mul.w r6, r4, r3 + 18de2: 416d adcs r5, r5 + 18de4: fba4 2301 umull r2, r3, r4, r1 + 18de8: fb01 6105 mla r1, r1, r5, r6 + 18dec: 440b add r3, r1 + 18dee: e9c0 2324 strd r2, r3, [r0, #144] ; 0x90 + 18df2: bdf0 pop {r4, r5, r6, r7, pc} + +00018df4 : + 18df4: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 18df8: 2400 movs r4, #0 + 18dfa: 2500 movs r5, #0 + 18dfc: 46a0 mov r8, r4 + 18dfe: 46a9 mov r9, r5 + 18e00: 4642 mov r2, r8 + 18e02: 464b mov r3, r9 + 18e04: 46a2 mov sl, r4 + 18e06: 46ab mov fp, r5 + 18e08: b09d sub sp, #116 ; 0x74 + 18e0a: e9cd 2304 strd r2, r3, [sp, #16] + 18e0e: e9cd 231a strd r2, r3, [sp, #104] ; 0x68 + 18e12: 6f41 ldr r1, [r0, #116] ; 0x74 + 18e14: 6ec2 ldr r2, [r0, #108] ; 0x6c + 18e16: e9cd ab08 strd sl, fp, [sp, #32] + 18e1a: f8d0 3094 ldr.w r3, [r0, #148] ; 0x94 + 18e1e: f8d0 b084 ldr.w fp, [r0, #132] ; 0x84 + 18e22: f8d0 e07c ldr.w lr, [r0, #124] ; 0x7c + 18e26: f8d0 a08c ldr.w sl, [r0, #140] ; 0x8c + 18e2a: 0109 lsls r1, r1, #4 + 18e2c: 0112 lsls r2, r2, #4 + 18e2e: e9cd 4506 strd r4, r5, [sp, #24] + 18e32: 9105 str r1, [sp, #20] + 18e34: 9207 str r2, [sp, #28] + 18e36: f8d0 1090 ldr.w r1, [r0, #144] ; 0x90 + 18e3a: f8d0 2088 ldr.w r2, [r0, #136] ; 0x88 + 18e3e: 011d lsls r5, r3, #4 + 18e40: ea4f 170b mov.w r7, fp, lsl #4 + 18e44: 6e43 ldr r3, [r0, #100] ; 0x64 + 18e46: ea4f 1b0e mov.w fp, lr, lsl #4 + 18e4a: f8d0 e05c ldr.w lr, [r0, #92] ; 0x5c + 18e4e: ea4f 190a mov.w r9, sl, lsl #4 + 18e52: ea45 7511 orr.w r5, r5, r1, lsr #28 + 18e56: ea49 7912 orr.w r9, r9, r2, lsr #28 + 18e5a: 9905 ldr r1, [sp, #20] + 18e5c: 6f02 ldr r2, [r0, #112] ; 0x70 + 18e5e: 011b lsls r3, r3, #4 + 18e60: ea4f 1e0e mov.w lr, lr, lsl #4 + 18e64: 9309 str r3, [sp, #36] ; 0x24 + 18e66: f8cd e06c str.w lr, [sp, #108] ; 0x6c + 18e6a: f8d0 3080 ldr.w r3, [r0, #128] ; 0x80 + 18e6e: f8d0 e078 ldr.w lr, [r0, #120] ; 0x78 + 18e72: ea41 7112 orr.w r1, r1, r2, lsr #28 + 18e76: ea47 7713 orr.w r7, r7, r3, lsr #28 + 18e7a: 6e02 ldr r2, [r0, #96] ; 0x60 + 18e7c: 9b07 ldr r3, [sp, #28] + 18e7e: ea4b 7b1e orr.w fp, fp, lr, lsr #28 + 18e82: 9105 str r1, [sp, #20] + 18e84: f8d0 e068 ldr.w lr, [r0, #104] ; 0x68 + 18e88: 9909 ldr r1, [sp, #36] ; 0x24 + 18e8a: ea43 731e orr.w r3, r3, lr, lsr #28 + 18e8e: ea41 7112 orr.w r1, r1, r2, lsr #28 + 18e92: f8d0 e058 ldr.w lr, [r0, #88] ; 0x58 + 18e96: 9307 str r3, [sp, #28] + 18e98: 9109 str r1, [sp, #36] ; 0x24 + 18e9a: 9b1b ldr r3, [sp, #108] ; 0x6c + 18e9c: f8d0 1090 ldr.w r1, [r0, #144] ; 0x90 + 18ea0: ea43 731e orr.w r3, r3, lr, lsr #28 + 18ea4: 010c lsls r4, r1, #4 + 18ea6: 6f01 ldr r1, [r0, #112] ; 0x70 + 18ea8: f8d0 2088 ldr.w r2, [r0, #136] ; 0x88 + 18eac: 931b str r3, [sp, #108] ; 0x6c + 18eae: f8d0 3080 ldr.w r3, [r0, #128] ; 0x80 + 18eb2: 0109 lsls r1, r1, #4 + 18eb4: f8d0 e078 ldr.w lr, [r0, #120] ; 0x78 + 18eb8: ea4f 1802 mov.w r8, r2, lsl #4 + 18ebc: 9104 str r1, [sp, #16] + 18ebe: 011e lsls r6, r3, #4 + 18ec0: 6e82 ldr r2, [r0, #104] ; 0x68 + 18ec2: 6e03 ldr r3, [r0, #96] ; 0x60 + 18ec4: 0112 lsls r2, r2, #4 + 18ec6: 011b lsls r3, r3, #4 + 18ec8: 9206 str r2, [sp, #24] + 18eca: 9308 str r3, [sp, #32] + 18ecc: e9d0 2310 ldrd r2, r3, [r0, #64] ; 0x40 + 18ed0: 1912 adds r2, r2, r4 + 18ed2: 416b adcs r3, r5 + 18ed4: e9d0 4524 ldrd r4, r5, [r0, #144] ; 0x90 + 18ed8: 1924 adds r4, r4, r4 + 18eda: 416d adcs r5, r5 + 18edc: e9cd 4514 strd r4, r5, [sp, #80] ; 0x50 + 18ee0: e9d0 450e ldrd r4, r5, [r0, #56] ; 0x38 + 18ee4: eb14 0408 adds.w r4, r4, r8 + 18ee8: eb45 0509 adc.w r5, r5, r9 + 18eec: ea4f 1a0e mov.w sl, lr, lsl #4 + 18ef0: e9cd 230a strd r2, r3, [sp, #40] ; 0x28 + 18ef4: e9d0 230c ldrd r2, r3, [r0, #48] ; 0x30 + 18ef8: e9d0 8904 ldrd r8, r9, [r0, #16] + 18efc: 1992 adds r2, r2, r6 + 18efe: 417b adcs r3, r7 + 18f00: e9cd 450c strd r4, r5, [sp, #48] ; 0x30 + 18f04: e9d0 450a ldrd r4, r5, [r0, #40] ; 0x28 + 18f08: e9d0 6702 ldrd r6, r7, [r0, #8] + 18f0c: eb14 040a adds.w r4, r4, sl + 18f10: eb45 050b adc.w r5, r5, fp + 18f14: f8d0 e058 ldr.w lr, [r0, #88] ; 0x58 + 18f18: e9dd ab04 ldrd sl, fp, [sp, #16] + 18f1c: e9cd 230e strd r2, r3, [sp, #56] ; 0x38 + 18f20: e9d0 2308 ldrd r2, r3, [r0, #32] + 18f24: eb1a 0a02 adds.w sl, sl, r2 + 18f28: eb4b 0b03 adc.w fp, fp, r3 + 18f2c: e9cd 4510 strd r4, r5, [sp, #64] ; 0x40 + 18f30: e9d0 4506 ldrd r4, r5, [r0, #24] + 18f34: e9dd 2308 ldrd r2, r3, [sp, #32] + 18f38: e9cd ab12 strd sl, fp, [sp, #72] ; 0x48 + 18f3c: e9dd ab06 ldrd sl, fp, [sp, #24] + 18f40: ea4f 1e0e mov.w lr, lr, lsl #4 + 18f44: eb1a 0a04 adds.w sl, sl, r4 + 18f48: f8cd e068 str.w lr, [sp, #104] ; 0x68 + 18f4c: eb4b 0b05 adc.w fp, fp, r5 + 18f50: eb12 0208 adds.w r2, r2, r8 + 18f54: e9dd 451a ldrd r4, r5, [sp, #104] ; 0x68 + 18f58: eb43 0309 adc.w r3, r3, r9 + 18f5c: 19a4 adds r4, r4, r6 + 18f5e: 417d adcs r5, r7 + 18f60: e9d0 8922 ldrd r8, r9, [r0, #136] ; 0x88 + 18f64: eb18 0808 adds.w r8, r8, r8 + 18f68: e9d0 6720 ldrd r6, r7, [r0, #128] ; 0x80 + 18f6c: eb49 0909 adc.w r9, r9, r9 + 18f70: 19b6 adds r6, r6, r6 + 18f72: e9cd 451a strd r4, r5, [sp, #104] ; 0x68 + 18f76: e9d0 451e ldrd r4, r5, [r0, #120] ; 0x78 + 18f7a: 417f adcs r7, r7 + 18f7c: 1924 adds r4, r4, r4 + 18f7e: e9cd 2318 strd r2, r3, [sp, #96] ; 0x60 + 18f82: e9d0 231c ldrd r2, r3, [r0, #112] ; 0x70 + 18f86: 416d adcs r5, r5 + 18f88: 1892 adds r2, r2, r2 + 18f8a: 415b adcs r3, r3 + 18f8c: e9cd ab16 strd sl, fp, [sp, #88] ; 0x58 + 18f90: e9cd 4502 strd r4, r5, [sp, #8] + 18f94: e9cd 2300 strd r2, r3, [sp] + 18f98: e9dd ab0a ldrd sl, fp, [sp, #40] ; 0x28 + 18f9c: e9dd 2314 ldrd r2, r3, [sp, #80] ; 0x50 + 18fa0: eb1a 0a02 adds.w sl, sl, r2 + 18fa4: eb4b 0b03 adc.w fp, fp, r3 + 18fa8: e9d0 231a ldrd r2, r3, [r0, #104] ; 0x68 + 18fac: 1892 adds r2, r2, r2 + 18fae: e9cd ab04 strd sl, fp, [sp, #16] + 18fb2: e9dd ab0c ldrd sl, fp, [sp, #48] ; 0x30 + 18fb6: e9dd 4510 ldrd r4, r5, [sp, #64] ; 0x40 + 18fba: 415b adcs r3, r3 + 18fbc: eb1a 0a08 adds.w sl, sl, r8 + 18fc0: eb4b 0b09 adc.w fp, fp, r9 + 18fc4: e9d0 8918 ldrd r8, r9, [r0, #96] ; 0x60 + 18fc8: eb18 0808 adds.w r8, r8, r8 + 18fcc: e9cd ab06 strd sl, fp, [sp, #24] + 18fd0: e9dd ab0e ldrd sl, fp, [sp, #56] ; 0x38 + 18fd4: eb49 0909 adc.w r9, r9, r9 + 18fd8: eb1a 0a06 adds.w sl, sl, r6 + 18fdc: eb4b 0b07 adc.w fp, fp, r7 + 18fe0: e9d0 6716 ldrd r6, r7, [r0, #88] ; 0x58 + 18fe4: 19b6 adds r6, r6, r6 + 18fe6: e9cd ab08 strd sl, fp, [sp, #32] + 18fea: e9dd ab02 ldrd sl, fp, [sp, #8] + 18fee: 417f adcs r7, r7 + 18ff0: eb1a 0a04 adds.w sl, sl, r4 + 18ff4: eb4b 0b05 adc.w fp, fp, r5 + 18ff8: e9cd ab0c strd sl, fp, [sp, #48] ; 0x30 + 18ffc: e9dd 4512 ldrd r4, r5, [sp, #72] ; 0x48 + 19000: e9dd ab00 ldrd sl, fp, [sp] + 19004: eb1a 0a04 adds.w sl, sl, r4 + 19008: eb4b 0b05 adc.w fp, fp, r5 + 1900c: e9dd 4516 ldrd r4, r5, [sp, #88] ; 0x58 + 19010: 18a4 adds r4, r4, r2 + 19012: 415d adcs r5, r3 + 19014: e9dd 2318 ldrd r2, r3, [sp, #96] ; 0x60 + 19018: eb18 0802 adds.w r8, r8, r2 + 1901c: e9cd 450a strd r4, r5, [sp, #40] ; 0x28 + 19020: e9dd 451a ldrd r4, r5, [sp, #104] ; 0x68 + 19024: eb49 0903 adc.w r9, r9, r3 + 19028: 1936 adds r6, r6, r4 + 1902a: e9d0 2324 ldrd r2, r3, [r0, #144] ; 0x90 + 1902e: 416f adcs r7, r5 + 19030: e9dd 4504 ldrd r4, r5, [sp, #16] + 19034: 1912 adds r2, r2, r4 + 19036: 416b adcs r3, r5 + 19038: e9c0 2310 strd r2, r3, [r0, #64] ; 0x40 + 1903c: e9dd 4506 ldrd r4, r5, [sp, #24] + 19040: e9d0 2322 ldrd r2, r3, [r0, #136] ; 0x88 + 19044: 1912 adds r2, r2, r4 + 19046: 416b adcs r3, r5 + 19048: e9c0 230e strd r2, r3, [r0, #56] ; 0x38 + 1904c: e9dd 4508 ldrd r4, r5, [sp, #32] + 19050: e9d0 2320 ldrd r2, r3, [r0, #128] ; 0x80 + 19054: 1912 adds r2, r2, r4 + 19056: 416b adcs r3, r5 + 19058: e9c0 230c strd r2, r3, [r0, #48] ; 0x30 + 1905c: e9dd 450c ldrd r4, r5, [sp, #48] ; 0x30 + 19060: e9d0 231e ldrd r2, r3, [r0, #120] ; 0x78 + 19064: 1912 adds r2, r2, r4 + 19066: 416b adcs r3, r5 + 19068: e9c0 230a strd r2, r3, [r0, #40] ; 0x28 + 1906c: e9d0 231c ldrd r2, r3, [r0, #112] ; 0x70 + 19070: e9d0 451a ldrd r4, r5, [r0, #104] ; 0x68 + 19074: eb12 020a adds.w r2, r2, sl + 19078: eb43 030b adc.w r3, r3, fp + 1907c: e9dd ab0a ldrd sl, fp, [sp, #40] ; 0x28 + 19080: eb14 040a adds.w r4, r4, sl + 19084: eb45 050b adc.w r5, r5, fp + 19088: e9c0 2308 strd r2, r3, [r0, #32] + 1908c: e9c0 4506 strd r4, r5, [r0, #24] + 19090: e9d0 2318 ldrd r2, r3, [r0, #96] ; 0x60 + 19094: e9d0 4516 ldrd r4, r5, [r0, #88] ; 0x58 + 19098: eb18 0802 adds.w r8, r8, r2 + 1909c: eb49 0903 adc.w r9, r9, r3 + 190a0: 1936 adds r6, r6, r4 + 190a2: 416f adcs r7, r5 + 190a4: e9d0 4514 ldrd r4, r5, [r0, #80] ; 0x50 + 190a8: 012b lsls r3, r5, #4 + 190aa: 0122 lsls r2, r4, #4 + 190ac: e9d0 ab00 ldrd sl, fp, [r0] + 190b0: ea43 7314 orr.w r3, r3, r4, lsr #28 + 190b4: eb12 020a adds.w r2, r2, sl + 190b8: eb43 030b adc.w r3, r3, fp + 190bc: eb14 0a04 adds.w sl, r4, r4 + 190c0: eb45 0b05 adc.w fp, r5, r5 + 190c4: eb12 020a adds.w r2, r2, sl + 190c8: eb43 030b adc.w r3, r3, fp + 190cc: 1912 adds r2, r2, r4 + 190ce: 416b adcs r3, r5 + 190d0: e9c0 8904 strd r8, r9, [r0, #16] + 190d4: e9c0 6702 strd r6, r7, [r0, #8] + 190d8: e9c0 2300 strd r2, r3, [r0] + 190dc: b01d add sp, #116 ; 0x74 + 190de: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 190e2: bf00 nop + +000190e4 : + 190e4: 4601 mov r1, r0 + 190e6: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 190ea: 2400 movs r4, #0 + 190ec: 2500 movs r5, #0 + 190ee: e9c0 4514 strd r4, r5, [r0, #80] ; 0x50 + 190f2: 4684 mov ip, r0 + 190f4: e8f1 ab04 ldrd sl, fp, [r1], #16 + 190f8: 460e mov r6, r1 + 190fa: b085 sub sp, #20 + 190fc: f04f 0e00 mov.w lr, #0 + 19100: ea4f 71eb mov.w r1, fp, asr #31 + 19104: 0989 lsrs r1, r1, #6 + 19106: eb1a 0401 adds.w r4, sl, r1 + 1910a: f14b 0500 adc.w r5, fp, #0 + 1910e: ea4f 6894 mov.w r8, r4, lsr #26 + 19112: ea48 1885 orr.w r8, r8, r5, lsl #6 + 19116: e956 0102 ldrd r0, r1, [r6, #-8] + 1911a: ea4f 69a5 mov.w r9, r5, asr #26 + 1911e: eb18 0400 adds.w r4, r8, r0 + 19122: eb49 0501 adc.w r5, r9, r1 + 19126: 17ef asrs r7, r5, #31 + 19128: 09ff lsrs r7, r7, #7 + 1912a: 19e0 adds r0, r4, r7 + 1912c: f145 0100 adc.w r1, r5, #0 + 19130: 0e42 lsrs r2, r0, #25 + 19132: 164b asrs r3, r1, #25 + 19134: ea4f 6089 mov.w r0, r9, lsl #26 + 19138: ea42 12c1 orr.w r2, r2, r1, lsl #7 + 1913c: ea40 1098 orr.w r0, r0, r8, lsr #6 + 19140: 0659 lsls r1, r3, #25 + 19142: 9001 str r0, [sp, #4] + 19144: ea41 11d2 orr.w r1, r1, r2, lsr #7 + 19148: ea4f 6088 mov.w r0, r8, lsl #26 + 1914c: 9103 str r1, [sp, #12] + 1914e: 9000 str r0, [sp, #0] + 19150: 0651 lsls r1, r2, #25 + 19152: 9102 str r1, [sp, #8] + 19154: e9dd 0100 ldrd r0, r1, [sp] + 19158: ebba 0000 subs.w r0, sl, r0 + 1915c: eb6b 0101 sbc.w r1, fp, r1 + 19160: e946 0104 strd r0, r1, [r6, #-16] + 19164: e9dd 0102 ldrd r0, r1, [sp, #8] + 19168: e9d6 ab00 ldrd sl, fp, [r6] + 1916c: 1a20 subs r0, r4, r0 + 1916e: eb65 0101 sbc.w r1, r5, r1 + 19172: f10e 0e02 add.w lr, lr, #2 + 19176: eb1a 0a02 adds.w sl, sl, r2 + 1917a: eb4b 0b03 adc.w fp, fp, r3 + 1917e: f1be 0f0a cmp.w lr, #10 + 19182: e946 0102 strd r0, r1, [r6, #-8] + 19186: e8e6 ab04 strd sl, fp, [r6], #16 + 1918a: d1b9 bne.n 19100 + 1918c: e9dc 6714 ldrd r6, r7, [ip, #80] ; 0x50 + 19190: e9dc 2300 ldrd r2, r3, [ip] + 19194: e9dc 4502 ldrd r4, r5, [ip, #8] + 19198: ea4f 1806 mov.w r8, r6, lsl #4 + 1919c: ea4f 1907 mov.w r9, r7, lsl #4 + 191a0: eb12 0208 adds.w r2, r2, r8 + 191a4: ea49 7916 orr.w r9, r9, r6, lsr #28 + 191a8: eb43 0309 adc.w r3, r3, r9 + 191ac: eb16 0a06 adds.w sl, r6, r6 + 191b0: eb47 0b07 adc.w fp, r7, r7 + 191b4: eb12 020a adds.w r2, r2, sl + 191b8: eb43 030b adc.w r3, r3, fp + 191bc: 18b6 adds r6, r6, r2 + 191be: 415f adcs r7, r3 + 191c0: 17fb asrs r3, r7, #31 + 191c2: 099b lsrs r3, r3, #6 + 191c4: eb16 0803 adds.w r8, r6, r3 + 191c8: f147 0900 adc.w r9, r7, #0 + 191cc: ea4f 6298 mov.w r2, r8, lsr #26 + 191d0: ea42 1289 orr.w r2, r2, r9, lsl #6 + 191d4: 18a4 adds r4, r4, r2 + 191d6: ea4f 63a9 mov.w r3, r9, asr #26 + 191da: ea4f 71e4 mov.w r1, r4, asr #31 + 191de: 415d adcs r5, r3 + 191e0: ea4f 6983 mov.w r9, r3, lsl #26 + 191e4: eb04 13d1 add.w r3, r4, r1, lsr #7 + 191e8: 165b asrs r3, r3, #25 + 191ea: ea4f 6882 mov.w r8, r2, lsl #26 + 191ee: ebb6 0608 subs.w r6, r6, r8 + 191f2: ea49 1992 orr.w r9, r9, r2, lsr #6 + 191f6: ea4f 6243 mov.w r2, r3, lsl #25 + 191fa: eb67 0709 sbc.w r7, r7, r9 + 191fe: 1aa4 subs r4, r4, r2 + 19200: eb65 75e2 sbc.w r5, r5, r2, asr #31 + 19204: e9dc 8904 ldrd r8, r9, [ip, #16] + 19208: eb18 0803 adds.w r8, r8, r3 + 1920c: eb49 79e3 adc.w r9, r9, r3, asr #31 + 19210: 2200 movs r2, #0 + 19212: 2300 movs r3, #0 + 19214: e9cc 6700 strd r6, r7, [ip] + 19218: e9cc 4502 strd r4, r5, [ip, #8] + 1921c: e9cc 8904 strd r8, r9, [ip, #16] + 19220: e9cc 2314 strd r2, r3, [ip, #80] ; 0x50 + 19224: b005 add sp, #20 + 19226: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 1922a: bf00 nop + +0001922c : + 1922c: b4f0 push {r4, r5, r6, r7} + 1922e: 4252 negs r2, r2 + 19230: 2300 movs r3, #0 + 19232: 6806 ldr r6, [r0, #0] + 19234: 680c ldr r4, [r1, #0] + 19236: 3301 adds r3, #1 + 19238: 4074 eors r4, r6 + 1923a: 4014 ands r4, r2 + 1923c: 4066 eors r6, r4 + 1923e: 17f7 asrs r7, r6, #31 + 19240: e8e0 6702 strd r6, r7, [r0], #8 + 19244: f851 5b08 ldr.w r5, [r1], #8 + 19248: 2b0a cmp r3, #10 + 1924a: ea84 0405 eor.w r4, r4, r5 + 1924e: ea4f 75e4 mov.w r5, r4, asr #31 + 19252: e941 4502 strd r4, r5, [r1, #-8] + 19256: d1ec bne.n 19232 + 19258: bcf0 pop {r4, r5, r6, r7} + 1925a: 4770 bx lr + +0001925c : + 1925c: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 19260: 6a8f ldr r7, [r1, #40] ; 0x28 + 19262: f8d1 8008 ldr.w r8, [r1, #8] + 19266: 463c mov r4, r7 + 19268: 4642 mov r2, r8 + 1926a: b0c5 sub sp, #276 ; 0x114 + 1926c: 17fd asrs r5, r7, #31 + 1926e: e9cd 4504 strd r4, r5, [sp, #16] + 19272: 680d ldr r5, [r1, #0] + 19274: 698e ldr r6, [r1, #24] + 19276: 46aa mov sl, r5 + 19278: ea4f 73e8 mov.w r3, r8, asr #31 + 1927c: e9cd 2318 strd r2, r3, [sp, #96] ; 0x60 + 19280: fb86 2307 smull r2, r3, r6, r7 + 19284: 9507 str r5, [sp, #28] + 19286: ea4f 7be5 mov.w fp, r5, asr #31 + 1928a: 6b8d ldr r5, [r1, #56] ; 0x38 + 1928c: e9cd ab08 strd sl, fp, [sp, #32] + 19290: fbc5 2308 smlal r2, r3, r5, r8 + 19294: eb12 0a02 adds.w sl, r2, r2 + 19298: eb43 0b03 adc.w fp, r3, r3 + 1929c: e9dd 2318 ldrd r2, r3, [sp, #96] ; 0x60 + 192a0: 1892 adds r2, r2, r2 + 192a2: 415b adcs r3, r3 + 192a4: f8d1 c048 ldr.w ip, [r1, #72] ; 0x48 + 192a8: e9cd 230c strd r2, r3, [sp, #48] ; 0x30 + 192ac: e9dd 2304 ldrd r2, r3, [sp, #16] + 192b0: 1892 adds r2, r2, r2 + 192b2: 415b adcs r3, r3 + 192b4: e9cd 230a strd r2, r3, [sp, #40] ; 0x28 + 192b8: fb88 230c smull r2, r3, r8, ip + 192bc: fbc5 2306 smlal r2, r3, r5, r6 + 192c0: e9cd ab10 strd sl, fp, [sp, #64] ; 0x40 + 192c4: eb12 0a02 adds.w sl, r2, r2 + 192c8: 4662 mov r2, ip + 192ca: eb43 0b03 adc.w fp, r3, r3 + 192ce: ea4f 73ec mov.w r3, ip, asr #31 + 192d2: 6a0c ldr r4, [r1, #32] + 192d4: e9cd 231c strd r2, r3, [sp, #112] ; 0x70 + 192d8: e9dd 2308 ldrd r2, r3, [sp, #32] + 192dc: 1892 adds r2, r2, r2 + 192de: 415b adcs r3, r3 + 192e0: e9cd 230e strd r2, r3, [sp, #56] ; 0x38 + 192e4: 4622 mov r2, r4 + 192e6: e9cd ab12 strd sl, fp, [sp, #72] ; 0x48 + 192ea: 46b2 mov sl, r6 + 192ec: 17e3 asrs r3, r4, #31 + 192ee: e9cd 2316 strd r2, r3, [sp, #88] ; 0x58 + 192f2: fb86 230c smull r2, r3, r6, ip + 192f6: fbc5 2307 smlal r2, r3, r5, r7 + 192fa: f8d1 9010 ldr.w r9, [r1, #16] + 192fe: ea4f 7be6 mov.w fp, r6, asr #31 + 19302: e9cd ab14 strd sl, fp, [sp, #80] ; 0x50 + 19306: eb12 0a02 adds.w sl, r2, r2 + 1930a: eb43 0b03 adc.w fp, r3, r3 + 1930e: fb89 2304 smull r2, r3, r9, r4 + 19312: f8d1 e030 ldr.w lr, [r1, #48] ; 0x30 + 19316: fbc6 2306 smlal r2, r3, r6, r6 + 1931a: 6c09 ldr r1, [r1, #64] ; 0x40 + 1931c: e9cd ab08 strd sl, fp, [sp, #32] + 19320: 9106 str r1, [sp, #24] + 19322: 9907 ldr r1, [sp, #28] + 19324: fbce 2301 smlal r2, r3, lr, r1 + 19328: e9cd 2302 strd r2, r3, [sp, #8] + 1932c: 9a06 ldr r2, [sp, #24] + 1932e: fb81 ab02 smull sl, fp, r1, r2 + 19332: e9dd 2310 ldrd r2, r3, [sp, #64] ; 0x40 + 19336: fbce ab09 smlal sl, fp, lr, r9 + 1933a: eb12 020a adds.w r2, r2, sl + 1933e: eb43 030b adc.w r3, r3, fp + 19342: e9cd 231a strd r2, r3, [sp, #104] ; 0x68 + 19346: e9dd ab12 ldrd sl, fp, [sp, #72] ; 0x48 + 1934a: fb84 230e smull r2, r3, r4, lr + 1934e: fbc7 2307 smlal r2, r3, r7, r7 + 19352: 9906 ldr r1, [sp, #24] + 19354: fbc1 2309 smlal r2, r3, r1, r9 + 19358: eb1a 0a02 adds.w sl, sl, r2 + 1935c: eb4b 0b03 adc.w fp, fp, r3 + 19360: e9cd ab12 strd sl, fp, [sp, #72] ; 0x48 + 19364: 9b0d ldr r3, [sp, #52] ; 0x34 + 19366: 9905 ldr r1, [sp, #20] + 19368: fb07 f303 mul.w r3, r7, r3 + 1936c: 9a0c ldr r2, [sp, #48] ; 0x30 + 1936e: fb02 3b01 mla fp, r2, r1, r3 + 19372: fba7 2302 umull r2, r3, r7, r2 + 19376: 445b add r3, fp + 19378: e9dd ab02 ldrd sl, fp, [sp, #8] + 1937c: eb1a 0a02 adds.w sl, sl, r2 + 19380: eb4b 0b03 adc.w fp, fp, r3 + 19384: e9cd ab10 strd sl, fp, [sp, #64] ; 0x40 + 19388: f8dd b02c ldr.w fp, [sp, #44] ; 0x2c + 1938c: 9a0a ldr r2, [sp, #40] ; 0x28 + 1938e: fb0c f30b mul.w r3, ip, fp + 19392: 991d ldr r1, [sp, #116] ; 0x74 + 19394: fbac ab02 umull sl, fp, ip, r2 + 19398: fb02 3301 mla r3, r2, r1, r3 + 1939c: 9a06 ldr r2, [sp, #24] + 1939e: 9906 ldr r1, [sp, #24] + 193a0: e9cd ab0a strd sl, fp, [sp, #40] ; 0x28 + 193a4: 449b add fp, r3 + 193a6: 17d3 asrs r3, r2, #31 + 193a8: e9cd 2304 strd r2, r3, [sp, #16] + 193ac: fb8e 2301 smull r2, r3, lr, r1 + 193b0: fbc5 2305 smlal r2, r3, r5, r5 + 193b4: f8cd b02c str.w fp, [sp, #44] ; 0x2c + 193b8: e9dd ab0a ldrd sl, fp, [sp, #40] ; 0x28 + 193bc: 9919 ldr r1, [sp, #100] ; 0x64 + 193be: eb1a 0a02 adds.w sl, sl, r2 + 193c2: eb4b 0b03 adc.w fp, fp, r3 + 193c6: e9cd ab0a strd sl, fp, [sp, #40] ; 0x28 + 193ca: ea4f 0b81 mov.w fp, r1, lsl #2 + 193ce: ea4b 7b98 orr.w fp, fp, r8, lsr #30 + 193d2: fb06 fb0b mul.w fp, r6, fp + 193d6: 9b15 ldr r3, [sp, #84] ; 0x54 + 193d8: ea4f 0288 mov.w r2, r8, lsl #2 + 193dc: fb02 bb03 mla fp, r2, r3, fp + 193e0: f8cd b050 str.w fp, [sp, #80] ; 0x50 + 193e4: fba6 ab02 umull sl, fp, r6, r2 + 193e8: 990e ldr r1, [sp, #56] ; 0x38 + 193ea: 9a17 ldr r2, [sp, #92] ; 0x5c + 193ec: e9cd ab02 strd sl, fp, [sp, #8] + 193f0: e9dd ab04 ldrd sl, fp, [sp, #16] + 193f4: fb01 f102 mul.w r1, r1, r2 + 193f8: 9b03 ldr r3, [sp, #12] + 193fa: 9a14 ldr r2, [sp, #80] ; 0x50 + 193fc: 9116 str r1, [sp, #88] ; 0x58 + 193fe: 4413 add r3, r2 + 19400: eb1a 0a0a adds.w sl, sl, sl + 19404: 9906 ldr r1, [sp, #24] + 19406: 9303 str r3, [sp, #12] + 19408: 9b0e ldr r3, [sp, #56] ; 0x38 + 1940a: eb4b 0b0b adc.w fp, fp, fp + 1940e: e9cd ab0c strd sl, fp, [sp, #48] ; 0x30 + 19412: e9dd ab08 ldrd sl, fp, [sp, #32] + 19416: fba3 2304 umull r2, r3, r3, r4 + 1941a: fbc1 ab04 smlal sl, fp, r1, r4 + 1941e: e9cd ab08 strd sl, fp, [sp, #32] + 19422: f8dd a03c ldr.w sl, [sp, #60] ; 0x3c + 19426: f8dd b058 ldr.w fp, [sp, #88] ; 0x58 + 1942a: e9cd 2300 strd r2, r3, [sp] + 1942e: e9dd 231a ldrd r2, r3, [sp, #104] ; 0x68 + 19432: 1892 adds r2, r2, r2 + 19434: 415b adcs r3, r3 + 19436: e9cd 2304 strd r2, r3, [sp, #16] + 1943a: e9dd 2308 ldrd r2, r3, [sp, #32] + 1943e: 1892 adds r2, r2, r2 + 19440: 415b adcs r3, r3 + 19442: e9cd 2308 strd r2, r3, [sp, #32] + 19446: fb86 230e smull r2, r3, r6, lr + 1944a: fb04 b10a mla r1, r4, sl, fp + 1944e: e9dd ab02 ldrd sl, fp, [sp, #8] + 19452: fbc7 2304 smlal r2, r3, r7, r4 + 19456: fbc9 ab09 smlal sl, fp, r9, r9 + 1945a: fbc5 2309 smlal r2, r3, r5, r9 + 1945e: e9cd ab14 strd sl, fp, [sp, #80] ; 0x50 + 19462: f8dd b004 ldr.w fp, [sp, #4] + 19466: 448b add fp, r1 + 19468: 9906 ldr r1, [sp, #24] + 1946a: f8cd b004 str.w fp, [sp, #4] + 1946e: fbc1 2308 smlal r2, r3, r1, r8 + 19472: e9dd ab00 ldrd sl, fp, [sp] + 19476: 9907 ldr r1, [sp, #28] + 19478: fbcc 2301 smlal r2, r3, ip, r1 + 1947c: e9cd 2316 strd r2, r3, [sp, #88] ; 0x58 + 19480: e9dd 2314 ldrd r2, r3, [sp, #80] ; 0x50 + 19484: eb12 020a adds.w r2, r2, sl + 19488: eb43 030b adc.w r3, r3, fp + 1948c: fb89 ab07 smull sl, fp, r9, r7 + 19490: fbc4 ab06 smlal sl, fp, r4, r6 + 19494: e9cd 2326 strd r2, r3, [sp, #152] ; 0x98 + 19498: e9dd 2310 ldrd r2, r3, [sp, #64] ; 0x40 + 1949c: fbce ab08 smlal sl, fp, lr, r8 + 194a0: 1892 adds r2, r2, r2 + 194a2: 415b adcs r3, r3 + 194a4: e9cd 232a strd r2, r3, [sp, #168] ; 0xa8 + 194a8: e9dd 230a ldrd r2, r3, [sp, #40] ; 0x28 + 194ac: 1892 adds r2, r2, r2 + 194ae: 415b adcs r3, r3 + 194b0: fbc5 ab01 smlal sl, fp, r5, r1 + 194b4: e9cd 233a strd r2, r3, [sp, #232] ; 0xe8 + 194b8: e9dd 2316 ldrd r2, r3, [sp, #88] ; 0x58 + 194bc: 1892 adds r2, r2, r2 + 194be: 415b adcs r3, r3 + 194c0: e9cd 2330 strd r2, r3, [sp, #192] ; 0xc0 + 194c4: e9dd 2312 ldrd r2, r3, [sp, #72] ; 0x48 + 194c8: 1892 adds r2, r2, r2 + 194ca: 415b adcs r3, r3 + 194cc: e9cd 2332 strd r2, r3, [sp, #200] ; 0xc8 + 194d0: eb1a 020a adds.w r2, sl, sl + 194d4: eb4b 030b adc.w r3, fp, fp + 194d8: e9cd 232c strd r2, r3, [sp, #176] ; 0xb0 + 194dc: fb84 2305 smull r2, r3, r4, r5 + 194e0: fbce 2307 smlal r2, r3, lr, r7 + 194e4: 9906 ldr r1, [sp, #24] + 194e6: fbc1 2306 smlal r2, r3, r1, r6 + 194ea: fbcc 2309 smlal r2, r3, ip, r9 + 194ee: eb12 0a02 adds.w sl, r2, r2 + 194f2: 462a mov r2, r5 + 194f4: eb43 0b03 adc.w fp, r3, r3 + 194f8: e9cd ab34 strd sl, fp, [sp, #208] ; 0xd0 + 194fc: fb88 ab04 smull sl, fp, r8, r4 + 19500: fbc6 ab09 smlal sl, fp, r6, r9 + 19504: 17eb asrs r3, r5, #31 + 19506: e9cd 230a strd r2, r3, [sp, #40] ; 0x28 + 1950a: 9b07 ldr r3, [sp, #28] + 1950c: fbc7 ab03 smlal sl, fp, r7, r3 + 19510: eb1a 020a adds.w r2, sl, sl + 19514: eb4b 030b adc.w r3, fp, fp + 19518: e9cd 2328 strd r2, r3, [sp, #160] ; 0xa0 + 1951c: fb87 2301 smull r2, r3, r7, r1 + 19520: fbc5 230e smlal r2, r3, r5, lr + 19524: fbcc 2304 smlal r2, r3, ip, r4 + 19528: eb12 0a02 adds.w sl, r2, r2 + 1952c: eb43 0b03 adc.w fp, r3, r3 + 19530: fb8e 230c smull r2, r3, lr, ip + 19534: 9f06 ldr r7, [sp, #24] + 19536: e9cd ab38 strd sl, fp, [sp, #224] ; 0xe0 + 1953a: fbc7 2305 smlal r2, r3, r7, r5 + 1953e: eb12 0a02 adds.w sl, r2, r2 + 19542: 9a07 ldr r2, [sp, #28] + 19544: f8dd b02c ldr.w fp, [sp, #44] ; 0x2c + 19548: fb82 6706 smull r6, r7, r2, r6 + 1954c: ea4f 018b mov.w r1, fp, lsl #2 + 19550: eb43 0b03 adc.w fp, r3, r3 + 19554: fb82 2309 smull r2, r3, r2, r9 + 19558: fbc9 6708 smlal r6, r7, r9, r8 + 1955c: fbc8 2308 smlal r2, r3, r8, r8 + 19560: e9cd ab3c strd sl, fp, [sp, #240] ; 0xf0 + 19564: eb16 0a06 adds.w sl, r6, r6 + 19568: eb47 0b07 adc.w fp, r7, r7 + 1956c: 1896 adds r6, r2, r2 + 1956e: eb43 0703 adc.w r7, r3, r3 + 19572: fb8c 230c smull r2, r3, ip, ip + 19576: e9cd ab24 strd sl, fp, [sp, #144] ; 0x90 + 1957a: e9cd 6722 strd r6, r7, [sp, #136] ; 0x88 + 1957e: f8dd b064 ldr.w fp, [sp, #100] ; 0x64 + 19582: 9f0e ldr r7, [sp, #56] ; 0x38 + 19584: 1896 adds r6, r2, r2 + 19586: fb07 f90b mul.w r9, r7, fp + 1958a: eb43 0703 adc.w r7, r3, r3 + 1958e: f50d 7b84 add.w fp, sp, #264 ; 0x108 + 19592: ea41 7195 orr.w r1, r1, r5, lsr #30 + 19596: e9cb 6700 strd r6, r7, [fp] + 1959a: e9dd 6704 ldrd r6, r7, [sp, #16] + 1959e: fbc4 6704 smlal r6, r7, r4, r4 + 195a2: 4604 mov r4, r0 + 195a4: fb0c fa01 mul.w sl, ip, r1 + 195a8: 991d ldr r1, [sp, #116] ; 0x74 + 195aa: 00ad lsls r5, r5, #2 + 195ac: fb05 aa01 mla sl, r5, r1, sl + 195b0: 9a0e ldr r2, [sp, #56] ; 0x38 + 195b2: 990f ldr r1, [sp, #60] ; 0x3c + 195b4: e9cd 6704 strd r6, r7, [sp, #16] + 195b8: e9dd 6708 ldrd r6, r7, [sp, #32] + 195bc: fb08 9301 mla r3, r8, r1, r9 + 195c0: fba2 8908 umull r8, r9, r2, r8 + 195c4: fbce 670e smlal r6, r7, lr, lr + 195c8: 4499 add r9, r3 + 195ca: fbac 2305 umull r2, r3, ip, r5 + 195ce: e9cd 6708 strd r6, r7, [sp, #32] + 195d2: 9f06 ldr r7, [sp, #24] + 195d4: 4453 add r3, sl + 195d6: fbc7 2307 smlal r2, r3, r7, r7 + 195da: e9dd ab04 ldrd sl, fp, [sp, #16] + 195de: e9dd 6708 ldrd r6, r7, [sp, #32] + 195e2: e9cd ab2e strd sl, fp, [sp, #184] ; 0xb8 + 195e6: f8dd b034 ldr.w fp, [sp, #52] ; 0x34 + 195ea: e9cd 233e strd r2, r3, [sp, #248] ; 0xf8 + 195ee: fb0c f10b mul.w r1, ip, fp + 195f2: 981d ldr r0, [sp, #116] ; 0x74 + 195f4: 9a0c ldr r2, [sp, #48] ; 0x30 + 195f6: e9cd 6736 strd r6, r7, [sp, #216] ; 0xd8 + 195fa: fb02 1100 mla r1, r2, r0, r1 + 195fe: fbac 2302 umull r2, r3, ip, r2 + 19602: 9f07 ldr r7, [sp, #28] + 19604: 440b add r3, r1 + 19606: ad40 add r5, sp, #256 ; 0x100 + 19608: e9c5 2300 strd r2, r3, [r5] + 1960c: fb87 2307 smull r2, r3, r7, r7 + 19610: a81e add r0, sp, #120 ; 0x78 + 19612: e9cd 231e strd r2, r3, [sp, #120] ; 0x78 + 19616: e9cd 8920 strd r8, r9, [sp, #128] ; 0x80 + 1961a: f7ff fbeb bl 18df4 + 1961e: a81e add r0, sp, #120 ; 0x78 + 19620: f7ff fd60 bl 190e4 + 19624: 4620 mov r0, r4 + 19626: a91e add r1, sp, #120 ; 0x78 + 19628: 2250 movs r2, #80 ; 0x50 + 1962a: f7f5 ff1b bl f464 <_memcpy> + 1962e: b045 add sp, #276 ; 0x114 + 19630: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +00019634 : + 19634: b510 push {r4, lr} + 19636: 4604 mov r4, r0 + 19638: b0a6 sub sp, #152 ; 0x98 + 1963a: 4668 mov r0, sp + 1963c: f7ff fa02 bl 18a44 + 19640: 4668 mov r0, sp + 19642: f7ff fbd7 bl 18df4 + 19646: 4668 mov r0, sp + 19648: f7ff fd4c bl 190e4 + 1964c: 4620 mov r0, r4 + 1964e: 4669 mov r1, sp + 19650: 2250 movs r2, #80 ; 0x50 + 19652: f7f5 ff07 bl f464 <_memcpy> + 19656: b026 add sp, #152 ; 0x98 + 19658: bd10 pop {r4, pc} + 1965a: bf00 nop + +0001965c : + 1965c: f246 3394 movw r3, #25492 ; 0x6394 + 19660: f2c0 0303 movt r3, #3 + 19664: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 19668: f6ad 2d8c subw sp, sp, #2700 ; 0xa8c + 1966c: ac24 add r4, sp, #144 ; 0x90 + 1966e: 2a00 cmp r2, #0 + 19670: bf08 it eq + 19672: 461a moveq r2, r3 + 19674: 9013 str r0, [sp, #76] ; 0x4c + 19676: 2300 movs r3, #0 + 19678: 9412 str r4, [sp, #72] ; 0x48 + 1967a: 5cc8 ldrb r0, [r1, r3] + 1967c: ad24 add r5, sp, #144 ; 0x90 + 1967e: 54e8 strb r0, [r5, r3] + 19680: 3301 adds r3, #1 + 19682: 2b20 cmp r3, #32 + 19684: d1f9 bne.n 1967a + 19686: 7d16 ldrb r6, [r2, #20] + 19688: f892 8015 ldrb.w r8, [r2, #21] + 1968c: f892 a004 ldrb.w sl, [r2, #4] + 19690: 2700 movs r7, #0 + 19692: e9cd 6702 strd r6, r7, [sp, #8] + 19696: 79d4 ldrb r4, [r2, #7] + 19698: f04f 0900 mov.w r9, #0 + 1969c: f04f 0b00 mov.w fp, #0 + 196a0: e9cd 8906 strd r8, r9, [sp, #24] + 196a4: e9cd ab00 strd sl, fp, [sp] + 196a8: 7a16 ldrb r6, [r2, #8] + 196aa: f892 a00a ldrb.w sl, [r2, #10] + 196ae: f8dd 8008 ldr.w r8, [sp, #8] + 196b2: 2500 movs r5, #0 + 196b4: f8dd 9018 ldr.w r9, [sp, #24] + 196b8: e9cd 4514 strd r4, r5, [sp, #80] ; 0x50 + 196bc: 2700 movs r7, #0 + 196be: 7ad4 ldrb r4, [r2, #11] + 196c0: f04f 0b00 mov.w fp, #0 + 196c4: 7950 ldrb r0, [r2, #5] + 196c6: e9cd 6716 strd r6, r7, [sp, #88] ; 0x58 + 196ca: e9cd ab18 strd sl, fp, [sp, #96] ; 0x60 + 196ce: ea4f 6718 mov.w r7, r8, lsr #24 + 196d2: f892 a001 ldrb.w sl, [r2, #1] + 196d6: ea4f 2608 mov.w r6, r8, lsl #8 + 196da: 2500 movs r5, #0 + 196dc: f892 8002 ldrb.w r8, [r2, #2] + 196e0: e9cd 451a strd r4, r5, [sp, #104] ; 0x68 + 196e4: 2100 movs r1, #0 + 196e6: ea4f 4519 mov.w r5, r9, lsr #16 + 196ea: ea4f 4409 mov.w r4, r9, lsl #16 + 196ee: f04f 0b00 mov.w fp, #0 + 196f2: f04f 0900 mov.w r9, #0 + 196f6: 9b16 ldr r3, [sp, #88] ; 0x58 + 196f8: e9cd 0104 strd r0, r1, [sp, #16] + 196fc: e9cd ab10 strd sl, fp, [sp, #64] ; 0x40 + 19700: 7c50 ldrb r0, [r2, #17] + 19702: ea46 0a04 orr.w sl, r6, r4 + 19706: e9cd 8920 strd r8, r9, [sp, #128] ; 0x80 + 1970a: 7c94 ldrb r4, [r2, #18] + 1970c: f892 8013 ldrb.w r8, [r2, #19] + 19710: ea47 0b05 orr.w fp, r7, r5 + 19714: 2100 movs r1, #0 + 19716: 2500 movs r5, #0 + 19718: f04f 0900 mov.w r9, #0 + 1971c: 0c1b lsrs r3, r3, #16 + 1971e: f8dd e050 ldr.w lr, [sp, #80] ; 0x50 + 19722: e9cd ab22 strd sl, fp, [sp, #136] ; 0x88 + 19726: e9cd 011c strd r0, r1, [sp, #112] ; 0x70 + 1972a: f8dd a010 ldr.w sl, [sp, #16] + 1972e: e9cd 451e strd r4, r5, [sp, #120] ; 0x78 + 19732: e9cd 8906 strd r8, r9, [sp, #24] + 19736: f8dd 9000 ldr.w r9, [sp] + 1973a: 930b str r3, [sp, #44] ; 0x2c + 1973c: 9c18 ldr r4, [sp, #96] ; 0x60 + 1973e: 9d1a ldr r5, [sp, #104] ; 0x68 + 19740: 9e00 ldr r6, [sp, #0] + 19742: 0e24 lsrs r4, r4, #24 + 19744: 0c2d lsrs r5, r5, #16 + 19746: 9409 str r4, [sp, #36] ; 0x24 + 19748: 950d str r5, [sp, #52] ; 0x34 + 1974a: 9b16 ldr r3, [sp, #88] ; 0x58 + 1974c: 9c18 ldr r4, [sp, #96] ; 0x60 + 1974e: 9d1a ldr r5, [sp, #104] ; 0x68 + 19750: ea4f 480a mov.w r8, sl, lsl #16 + 19754: 0230 lsls r0, r6, #8 + 19756: ea40 0608 orr.w r6, r0, r8 + 1975a: ea4f 6119 mov.w r1, r9, lsr #24 + 1975e: f892 8003 ldrb.w r8, [r2, #3] + 19762: ea4f 491a mov.w r9, sl, lsr #16 + 19766: 041b lsls r3, r3, #16 + 19768: 0224 lsls r4, r4, #8 + 1976a: 042d lsls r5, r5, #16 + 1976c: 9408 str r4, [sp, #32] + 1976e: ea41 0709 orr.w r7, r1, r9 + 19772: ea4f 6b1e mov.w fp, lr, lsr #24 + 19776: ea4f 2a0e mov.w sl, lr, lsl #8 + 1977a: 930a str r3, [sp, #40] ; 0x28 + 1977c: 950c str r5, [sp, #48] ; 0x30 + 1977e: f04f 0900 mov.w r9, #0 + 19782: e9dd 450a ldrd r4, r5, [sp, #40] ; 0x28 + 19786: e9cd 8900 strd r8, r9, [sp] + 1978a: e9dd 8908 ldrd r8, r9, [sp, #32] + 1978e: ea44 040a orr.w r4, r4, sl + 19792: ea45 050b orr.w r5, r5, fp + 19796: e9dd ab0c ldrd sl, fp, [sp, #48] ; 0x30 + 1979a: ea49 090b orr.w r9, r9, fp + 1979e: f8dd b040 ldr.w fp, [sp, #64] ; 0x40 + 197a2: 7990 ldrb r0, [r2, #6] + 197a4: 2100 movs r1, #0 + 197a6: ea4f 6b1b mov.w fp, fp, lsr #24 + 197aa: f8dd e080 ldr.w lr, [sp, #128] ; 0x80 + 197ae: e9cd 6716 strd r6, r7, [sp, #88] ; 0x58 + 197b2: e9cd 0104 strd r0, r1, [sp, #16] + 197b6: 7b56 ldrb r6, [r2, #13] + 197b8: 981c ldr r0, [sp, #112] ; 0x70 + 197ba: ea48 080a orr.w r8, r8, sl + 197be: f8cd b00c str.w fp, [sp, #12] + 197c2: 991e ldr r1, [sp, #120] ; 0x78 + 197c4: 9b10 ldr r3, [sp, #64] ; 0x40 + 197c6: f8dd b078 ldr.w fp, [sp, #120] ; 0x78 + 197ca: e9cd 891a strd r8, r9, [sp, #104] ; 0x68 + 197ce: 2700 movs r7, #0 + 197d0: f892 800e ldrb.w r8, [r2, #14] + 197d4: e9cd 4518 strd r4, r5, [sp, #96] ; 0x60 + 197d8: e9cd 6714 strd r6, r7, [sp, #80] ; 0x50 + 197dc: ea4f 440e mov.w r4, lr, lsl #16 + 197e0: 0206 lsls r6, r0, #8 + 197e2: 0c09 lsrs r1, r1, #16 + 197e4: 021b lsls r3, r3, #8 + 197e6: f04f 0900 mov.w r9, #0 + 197ea: ea4f 4b0b mov.w fp, fp, lsl #16 + 197ee: ea4f 451e mov.w r5, lr, lsr #16 + 197f2: 0e07 lsrs r7, r0, #24 + 197f4: 910f str r1, [sp, #60] ; 0x3c + 197f6: 9302 str r3, [sp, #8] + 197f8: e9cd 8908 strd r8, r9, [sp, #32] + 197fc: f8cd b038 str.w fp, [sp, #56] ; 0x38 + 19800: e9dd 0102 ldrd r0, r1, [sp, #8] + 19804: e9dd 890e ldrd r8, r9, [sp, #56] ; 0x38 + 19808: 4320 orrs r0, r4 + 1980a: ea48 0806 orr.w r8, r8, r6 + 1980e: 7d94 ldrb r4, [r2, #22] + 19810: 7816 ldrb r6, [r2, #0] + 19812: 4329 orrs r1, r5 + 19814: ea49 0907 orr.w r9, r9, r7 + 19818: 2500 movs r5, #0 + 1981a: 2700 movs r7, #0 + 1981c: f892 a009 ldrb.w sl, [r2, #9] + 19820: e9cd 010c strd r0, r1, [sp, #48] ; 0x30 + 19824: e9dd 0122 ldrd r0, r1, [sp, #136] ; 0x88 + 19828: e9cd 450a strd r4, r5, [sp, #40] ; 0x28 + 1982c: e9dd 4506 ldrd r4, r5, [sp, #24] + 19830: e9cd 670e strd r6, r7, [sp, #56] ; 0x38 + 19834: e9dd 6700 ldrd r6, r7, [sp] + 19838: 4320 orrs r0, r4 + 1983a: 4329 orrs r1, r5 + 1983c: e9dd 4516 ldrd r4, r5, [sp, #88] ; 0x58 + 19840: 4334 orrs r4, r6 + 19842: 433d orrs r5, r7 + 19844: e9cd 8910 strd r8, r9, [sp, #64] ; 0x40 + 19848: e9dd 6704 ldrd r6, r7, [sp, #16] + 1984c: f892 8010 ldrb.w r8, [r2, #16] + 19850: f04f 0b00 mov.w fp, #0 + 19854: e9cd 4516 strd r4, r5, [sp, #88] ; 0x58 + 19858: e9dd 4518 ldrd r4, r5, [sp, #96] ; 0x60 + 1985c: 4334 orrs r4, r6 + 1985e: 433d orrs r5, r7 + 19860: f04f 0900 mov.w r9, #0 + 19864: e9cd 4518 strd r4, r5, [sp, #96] ; 0x60 + 19868: e9dd 451a ldrd r4, r5, [sp, #104] ; 0x68 + 1986c: ea44 040a orr.w r4, r4, sl + 19870: ea45 050b orr.w r5, r5, fp + 19874: e9cd 891c strd r8, r9, [sp, #112] ; 0x70 + 19878: f8dd e020 ldr.w lr, [sp, #32] + 1987c: f8dd 9050 ldr.w r9, [sp, #80] ; 0x50 + 19880: 7b16 ldrb r6, [r2, #12] + 19882: e9cd 451a strd r4, r5, [sp, #104] ; 0x68 + 19886: 9d14 ldr r5, [sp, #80] ; 0x50 + 19888: 2700 movs r7, #0 + 1988a: e9cd 011e strd r0, r1, [sp, #120] ; 0x78 + 1988e: ea4f 480e mov.w r8, lr, lsl #16 + 19892: ea4f 6119 mov.w r1, r9, lsr #24 + 19896: 0228 lsls r0, r5, #8 + 19898: ea4f 491e mov.w r9, lr, lsr #16 + 1989c: e9cd 6702 strd r6, r7, [sp, #8] + 198a0: 9f0a ldr r7, [sp, #40] ; 0x28 + 198a2: ea40 0408 orr.w r4, r0, r8 + 198a6: ea41 0509 orr.w r5, r1, r9 + 198aa: e9dd 010e ldrd r0, r1, [sp, #56] ; 0x38 + 198ae: e9dd 890c ldrd r8, r9, [sp, #48] ; 0x30 + 198b2: ea48 0800 orr.w r8, r8, r0 + 198b6: ea49 0901 orr.w r9, r9, r1 + 198ba: e9cd 4514 strd r4, r5, [sp, #80] ; 0x50 + 198be: e9cd 8920 strd r8, r9, [sp, #128] ; 0x80 + 198c2: e9dd 891c ldrd r8, r9, [sp, #112] ; 0x70 + 198c6: 0a3d lsrs r5, r7, #8 + 198c8: 063c lsls r4, r7, #24 + 198ca: e9dd 6710 ldrd r6, r7, [sp, #64] ; 0x40 + 198ce: ea46 0608 orr.w r6, r6, r8 + 198d2: ea47 0709 orr.w r7, r7, r9 + 198d6: e9cd 671c strd r6, r7, [sp, #112] ; 0x70 + 198da: e9dd 011e ldrd r0, r1, [sp, #120] ; 0x78 + 198de: 4320 orrs r0, r4 + 198e0: 4329 orrs r1, r5 + 198e2: 7bd4 ldrb r4, [r2, #15] + 198e4: e9cd 011e strd r0, r1, [sp, #120] ; 0x78 + 198e8: 2500 movs r5, #0 + 198ea: ea4f 211a mov.w r1, sl, lsr #8 + 198ee: ea4f 600a mov.w r0, sl, lsl #24 + 198f2: e9cd 4510 strd r4, r5, [sp, #64] ; 0x40 + 198f6: e9dd 4518 ldrd r4, r5, [sp, #96] ; 0x60 + 198fa: e9dd ab16 ldrd sl, fp, [sp, #88] ; 0x58 + 198fe: 4304 orrs r4, r0 + 19900: 430d orrs r5, r1 + 19902: 9800 ldr r0, [sp, #0] + 19904: 9906 ldr r1, [sp, #24] + 19906: 0600 lsls r0, r0, #24 + 19908: 0609 lsls r1, r1, #24 + 1990a: 9008 str r0, [sp, #32] + 1990c: 910e str r1, [sp, #56] ; 0x38 + 1990e: e9dd 011e ldrd r0, r1, [sp, #120] ; 0x78 + 19912: 1049 asrs r1, r1, #1 + 19914: ea4f 0030 mov.w r0, r0, rrx + 19918: f8dd 8010 ldr.w r8, [sp, #16] + 1991c: f8dd e008 ldr.w lr, [sp, #8] + 19920: ea4f 2718 mov.w r7, r8, lsr #8 + 19924: ea4f 6608 mov.w r6, r8, lsl #24 + 19928: ea4f 291e mov.w r9, lr, lsr #8 + 1992c: ea4f 680e mov.w r8, lr, lsl #24 + 19930: ea4a 0a06 orr.w sl, sl, r6 + 19934: ea4b 0b07 orr.w fp, fp, r7 + 19938: e9cd ab04 strd sl, fp, [sp, #16] + 1993c: e9dd 671a ldrd r6, r7, [sp, #104] ; 0x68 + 19940: e9dd ab02 ldrd sl, fp, [sp, #8] + 19944: ea46 0608 orr.w r6, r6, r8 + 19948: ea47 0709 orr.w r7, r7, r9 + 1994c: f8dd e018 ldr.w lr, [sp, #24] + 19950: e9dd 8914 ldrd r8, r9, [sp, #80] ; 0x50 + 19954: ea49 090b orr.w r9, r9, fp + 19958: f8dd b000 ldr.w fp, [sp] + 1995c: ea4f 2e1e mov.w lr, lr, lsr #8 + 19960: ea4f 2b1b mov.w fp, fp, lsr #8 + 19964: f8cd b024 str.w fp, [sp, #36] ; 0x24 + 19968: ea48 080a orr.w r8, r8, sl + 1996c: f8cd e03c str.w lr, [sp, #60] ; 0x3c + 19970: e9dd ab0e ldrd sl, fp, [sp, #56] ; 0x38 + 19974: e9cd 450c strd r4, r5, [sp, #48] ; 0x30 + 19978: e9dd 4520 ldrd r4, r5, [sp, #128] ; 0x80 + 1997c: e9cd 6716 strd r6, r7, [sp, #88] ; 0x58 + 19980: e9dd 6708 ldrd r6, r7, [sp, #32] + 19984: e9cd 8902 strd r8, r9, [sp, #8] + 19988: e9dd 891c ldrd r8, r9, [sp, #112] ; 0x70 + 1998c: e9cd 0108 strd r0, r1, [sp, #32] + 19990: ea48 080a orr.w r8, r8, sl + 19994: 9910 ldr r1, [sp, #64] ; 0x40 + 19996: ea49 090b orr.w r9, r9, fp + 1999a: 4334 orrs r4, r6 + 1999c: e9cd 8906 strd r8, r9, [sp, #24] + 199a0: 9b04 ldr r3, [sp, #16] + 199a2: 9e0c ldr r6, [sp, #48] ; 0x30 + 199a4: f8dd 8058 ldr.w r8, [sp, #88] ; 0x58 + 199a8: 433d orrs r5, r7 + 199aa: ea4f 2b11 mov.w fp, r1, lsr #8 + 199ae: e9cd 4500 strd r4, r5, [sp] + 199b2: f8dd e034 ldr.w lr, [sp, #52] ; 0x34 + 199b6: 089c lsrs r4, r3, #2 + 199b8: 08f0 lsrs r0, r6, #3 + 199ba: 9b17 ldr r3, [sp, #92] ; 0x5c + 199bc: ea4f 1658 mov.w r6, r8, lsr #5 + 199c0: e9dd 8902 ldrd r8, r9, [sp, #8] + 199c4: ea4b 0b09 orr.w fp, fp, r9 + 199c8: f8dd 9014 ldr.w r9, [sp, #20] + 199cc: ea40 704e orr.w r0, r0, lr, lsl #29 + 199d0: ea44 7489 orr.w r4, r4, r9, lsl #30 + 199d4: ea46 66c3 orr.w r6, r6, r3, lsl #27 + 199d8: ea4f 6a01 mov.w sl, r1, lsl #24 + 199dc: ea4a 0a08 orr.w sl, sl, r8 + 199e0: f04f 0900 mov.w r9, #0 + 199e4: f024 487e bic.w r8, r4, #4261412864 ; 0xfe000000 + 199e8: 2100 movs r1, #0 + 199ea: f020 447c bic.w r4, r0, #4227858432 ; 0xfc000000 + 199ee: f026 407e bic.w r0, r6, #4261412864 ; 0xfe000000 + 199f2: e9cd 890c strd r8, r9, [sp, #48] ; 0x30 + 199f6: e9dd 8900 ldrd r8, r9, [sp] + 199fa: e9dd 6708 ldrd r6, r7, [sp, #32] + 199fe: e9cd 0104 strd r0, r1, [sp, #16] + 19a02: 2500 movs r5, #0 + 19a04: f89d 00af ldrb.w r0, [sp, #175] ; 0xaf + 19a08: e9cd 4500 strd r4, r5, [sp] + 19a0c: e9dd 4506 ldrd r4, r5, [sp, #24] + 19a10: f89d 1090 ldrb.w r1, [sp, #144] ; 0x90 + 19a14: f024 447e bic.w r4, r4, #4261412864 ; 0xfe000000 + 19a18: 2500 movs r5, #0 + 19a1a: e9cd 4502 strd r4, r5, [sp, #8] + 19a1e: e9dd 4500 ldrd r4, r5, [sp] + 19a22: f026 467c bic.w r6, r6, #4227858432 ; 0xfc000000 + 19a26: e9cd 4530 strd r4, r5, [sp, #192] ; 0xc0 + 19a2a: 2700 movs r7, #0 + 19a2c: 7dd4 ldrb r4, [r2, #23] + 19a2e: f000 007f and.w r0, r0, #127 ; 0x7f + 19a32: e9cd 6706 strd r6, r7, [sp, #24] + 19a36: f028 487c bic.w r8, r8, #4227858432 ; 0xfc000000 + 19a3a: ea4f 16ab mov.w r6, fp, asr #6 + 19a3e: f04f 0900 mov.w r9, #0 + 19a42: f040 0040 orr.w r0, r0, #64 ; 0x40 + 19a46: f021 0107 bic.w r1, r1, #7 + 19a4a: 2500 movs r5, #0 + 19a4c: ea4f 139a mov.w r3, sl, lsr #6 + 19a50: e9cd 892c strd r8, r9, [sp, #176] ; 0xb0 + 19a54: e9dd 8904 ldrd r8, r9, [sp, #16] + 19a58: 9635 str r6, [sp, #212] ; 0xd4 + 19a5a: e9cd 8932 strd r8, r9, [sp, #200] ; 0xc8 + 19a5e: 7e16 ldrb r6, [r2, #24] + 19a60: f892 801a ldrb.w r8, [r2, #26] + 19a64: e9cd 4504 strd r4, r5, [sp, #16] + 19a68: f88d 00af strb.w r0, [sp, #175] ; 0xaf + 19a6c: 7f54 ldrb r4, [r2, #29] + 19a6e: f88d 1090 strb.w r1, [sp, #144] ; 0x90 + 19a72: e9dd 0106 ldrd r0, r1, [sp, #24] + 19a76: e9cd 0138 strd r0, r1, [sp, #224] ; 0xe0 + 19a7a: 7ed0 ldrb r0, [r2, #27] + 19a7c: ea43 638b orr.w r3, r3, fp, lsl #26 + 19a80: 2700 movs r7, #0 + 19a82: f04f 0900 mov.w r9, #0 + 19a86: 2100 movs r1, #0 + 19a88: 2500 movs r5, #0 + 19a8a: e9dd ab0c ldrd sl, fp, [sp, #48] ; 0x30 + 19a8e: e9cd 8906 strd r8, r9, [sp, #24] + 19a92: e9cd 0108 strd r0, r1, [sp, #32] + 19a96: e9cd ab2e strd sl, fp, [sp, #184] ; 0xb8 + 19a9a: e9dd ab02 ldrd sl, fp, [sp, #8] + 19a9e: 9334 str r3, [sp, #208] ; 0xd0 + 19aa0: e9cd ab36 strd sl, fp, [sp, #216] ; 0xd8 + 19aa4: e9cd 6702 strd r6, r7, [sp, #8] + 19aa8: e9cd 450c strd r4, r5, [sp, #48] ; 0x30 + 19aac: 7f96 ldrb r6, [r2, #30] + 19aae: f8dd 9010 ldr.w r9, [sp, #16] + 19ab2: 2700 movs r7, #0 + 19ab4: e9cd 670e strd r6, r7, [sp, #56] ; 0x38 + 19ab8: f8dd b018 ldr.w fp, [sp, #24] + 19abc: ea4f 6719 mov.w r7, r9, lsr #24 + 19ac0: f8dd e030 ldr.w lr, [sp, #48] ; 0x30 + 19ac4: ea4f 4910 mov.w r9, r0, lsr #16 + 19ac8: 980e ldr r0, [sp, #56] ; 0x38 + 19aca: 9904 ldr r1, [sp, #16] + 19acc: ea4f 6b1b mov.w fp, fp, lsr #24 + 19ad0: f8dd a008 ldr.w sl, [sp, #8] + 19ad4: f8cd b044 str.w fp, [sp, #68] ; 0x44 + 19ad8: 0c00 lsrs r0, r0, #16 + 19ada: ea4f 6b1e mov.w fp, lr, lsr #24 + 19ade: 9b0e ldr r3, [sp, #56] ; 0x38 + 19ae0: f8dd e018 ldr.w lr, [sp, #24] + 19ae4: 9001 str r0, [sp, #4] + 19ae6: 020e lsls r6, r1, #8 + 19ae8: 9808 ldr r0, [sp, #32] + 19aea: 990c ldr r1, [sp, #48] ; 0x30 + 19aec: ea4f 2e0e mov.w lr, lr, lsl #8 + 19af0: ea4f 451a mov.w r5, sl, lsr #16 + 19af4: ea4f 440a mov.w r4, sl, lsl #16 + 19af8: 041b lsls r3, r3, #16 + 19afa: f8cd e040 str.w lr, [sp, #64] ; 0x40 + 19afe: 9300 str r3, [sp, #0] + 19b00: ea4f 4800 mov.w r8, r0, lsl #16 + 19b04: ea4f 2a01 mov.w sl, r1, lsl #8 + 19b08: ea46 0004 orr.w r0, r6, r4 + 19b0c: ea47 0105 orr.w r1, r7, r5 + 19b10: e9cd 0104 strd r0, r1, [sp, #16] + 19b14: e9dd 6710 ldrd r6, r7, [sp, #64] ; 0x40 + 19b18: 7e54 ldrb r4, [r2, #25] + 19b1a: 7f10 ldrb r0, [r2, #28] + 19b1c: ea46 0608 orr.w r6, r6, r8 + 19b20: ea47 0709 orr.w r7, r7, r9 + 19b24: e9dd 8900 ldrd r8, r9, [sp] + 19b28: ea48 080a orr.w r8, r8, sl + 19b2c: ea49 090b orr.w r9, r9, fp + 19b30: e9cd 6702 strd r6, r7, [sp, #8] + 19b34: e9dd ab04 ldrd sl, fp, [sp, #16] + 19b38: e9dd 670a ldrd r6, r7, [sp, #40] ; 0x28 + 19b3c: e9cd 8906 strd r8, r9, [sp, #24] + 19b40: e9dd 8902 ldrd r8, r9, [sp, #8] + 19b44: ea4a 0a06 orr.w sl, sl, r6 + 19b48: ea4b 0b07 orr.w fp, fp, r7 + 19b4c: 2500 movs r5, #0 + 19b4e: 2100 movs r1, #0 + 19b50: 7fd2 ldrb r2, [r2, #31] + 19b52: e9cd ab00 strd sl, fp, [sp] + 19b56: e9dd ab06 ldrd sl, fp, [sp, #24] + 19b5a: ea48 0804 orr.w r8, r8, r4 + 19b5e: ea49 0905 orr.w r9, r9, r5 + 19b62: ea4a 0a00 orr.w sl, sl, r0 + 19b66: ea4b 0b01 orr.w fp, fp, r1 + 19b6a: e9cd 8904 strd r8, r9, [sp, #16] + 19b6e: e9cd ab02 strd sl, fp, [sp, #8] + 19b72: ea4f 6a00 mov.w sl, r0, lsl #24 + 19b76: ea4f 2b10 mov.w fp, r0, lsr #8 + 19b7a: 0a17 lsrs r7, r2, #8 + 19b7c: ea4f 6804 mov.w r8, r4, lsl #24 + 19b80: 0616 lsls r6, r2, #24 + 19b82: e9dd 2304 ldrd r2, r3, [sp, #16] + 19b86: ea4a 0a02 orr.w sl, sl, r2 + 19b8a: ea4b 0b03 orr.w fp, fp, r3 + 19b8e: e9dd 0100 ldrd r0, r1, [sp] + 19b92: ea4f 2914 mov.w r9, r4, lsr #8 + 19b96: ea48 0800 orr.w r8, r8, r0 + 19b9a: e9dd 4502 ldrd r4, r5, [sp, #8] + 19b9e: ea4f 101a mov.w r0, sl, lsr #4 + 19ba2: 4326 orrs r6, r4 + 19ba4: ea49 0901 orr.w r9, r9, r1 + 19ba8: 432f orrs r7, r5 + 19baa: ea40 700b orr.w r0, r0, fp, lsl #28 + 19bae: ea4f 04d8 mov.w r4, r8, lsr #3 + 19bb2: 09b2 lsrs r2, r6, #6 + 19bb4: ea44 7449 orr.w r4, r4, r9, lsl #29 + 19bb8: ea42 6287 orr.w r2, r2, r7, lsl #26 + 19bbc: f020 467c bic.w r6, r0, #4227858432 ; 0xfc000000 + 19bc0: 2700 movs r7, #0 + 19bc2: e9cd 673c strd r6, r7, [sp, #240] ; 0xf0 + 19bc6: f024 487e bic.w r8, r4, #4261412864 ; 0xfe000000 + 19bca: af8e add r7, sp, #568 ; 0x238 + 19bcc: f022 4a7e bic.w sl, r2, #4261412864 ; 0xfe000000 + 19bd0: f04f 0900 mov.w r9, #0 + 19bd4: f04f 0b00 mov.w fp, #0 + 19bd8: 2100 movs r1, #0 + 19bda: 2298 movs r2, #152 ; 0x98 + 19bdc: a868 add r0, sp, #416 ; 0x1a0 + 19bde: e9cd 893a strd r8, r9, [sp, #232] ; 0xe8 + 19be2: e9cd ab3e strd sl, fp, [sp, #248] ; 0xf8 + 19be6: f50d 7834 add.w r8, sp, #720 ; 0x2d0 + 19bea: f7f5 fc91 bl f510 <_memset> + 19bee: 4638 mov r0, r7 + 19bf0: 2100 movs r1, #0 + 19bf2: 2298 movs r2, #152 ; 0x98 + 19bf4: f7f5 fc8c bl f510 <_memset> + 19bf8: 2401 movs r4, #1 + 19bfa: 2500 movs r5, #0 + 19bfc: 4640 mov r0, r8 + 19bfe: 2100 movs r1, #0 + 19c00: 2298 movs r2, #152 ; 0x98 + 19c02: e9c7 4500 strd r4, r5, [r7] + 19c06: f7f5 fc83 bl f510 <_memset> + 19c0a: 2100 movs r1, #0 + 19c0c: 2298 movs r2, #152 ; 0x98 + 19c0e: a8da add r0, sp, #872 ; 0x368 + 19c10: e9c8 4500 strd r4, r5, [r8] + 19c14: f7f5 fc7c bl f510 <_memset> + 19c18: 2100 movs r1, #0 + 19c1a: 2298 movs r2, #152 ; 0x98 + 19c1c: f50d 6080 add.w r0, sp, #1024 ; 0x400 + 19c20: f7f5 fc76 bl f510 <_memset> + 19c24: 2100 movs r1, #0 + 19c26: 2298 movs r2, #152 ; 0x98 + 19c28: f50d 6093 add.w r0, sp, #1176 ; 0x498 + 19c2c: f7f5 fc70 bl f510 <_memset> + 19c30: f50d 6993 add.w r9, sp, #1176 ; 0x498 + 19c34: 2100 movs r1, #0 + 19c36: 2298 movs r2, #152 ; 0x98 + 19c38: f50d 60a6 add.w r0, sp, #1328 ; 0x530 + 19c3c: e9c9 4500 strd r4, r5, [r9] + 19c40: f50d 6bb9 add.w fp, sp, #1480 ; 0x5c8 + 19c44: f7f5 fc64 bl f510 <_memset> + 19c48: 2100 movs r1, #0 + 19c4a: 2298 movs r2, #152 ; 0x98 + 19c4c: f50d 60b9 add.w r0, sp, #1480 ; 0x5c8 + 19c50: f7f5 fc5e bl f510 <_memset> + 19c54: e9cb 4500 strd r4, r5, [fp] + 19c58: a868 add r0, sp, #416 ; 0x1a0 + 19c5a: f50d 7b5a add.w fp, sp, #872 ; 0x368 + 19c5e: a92c add r1, sp, #176 ; 0xb0 + 19c60: 2250 movs r2, #80 ; 0x50 + 19c62: 9702 str r7, [sp, #8] + 19c64: f64d 3641 movw r6, #56129 ; 0xdb41 + 19c68: 9004 str r0, [sp, #16] + 19c6a: f7f5 fbfb bl f464 <_memcpy> + 19c6e: 465b mov r3, fp + 19c70: ad2c add r5, sp, #176 ; 0xb0 + 19c72: 9510 str r5, [sp, #64] ; 0x40 + 19c74: f50d 65a6 add.w r5, sp, #1328 ; 0x530 + 19c78: 46ab mov fp, r5 + 19c7a: f2c0 0601 movt r6, #1 + 19c7e: 461d mov r5, r3 + 19c80: f50d 67b9 add.w r7, sp, #1480 ; 0x5c8 + 19c84: f50d 6980 add.w r9, sp, #1024 ; 0x400 + 19c88: 46c2 mov sl, r8 + 19c8a: f50d 6893 add.w r8, sp, #1176 ; 0x498 + 19c8e: 9700 str r7, [sp, #0] + 19c90: f8cd 8028 str.w r8, [sp, #40] ; 0x28 + 19c94: f8cd 9020 str.w r9, [sp, #32] + 19c98: f50d 78a4 add.w r8, sp, #328 ; 0x148 + 19c9c: af66 add r7, sp, #408 ; 0x198 + 19c9e: f50d 69e8 add.w r9, sp, #1856 ; 0x740 + 19ca2: f50d 64fb add.w r4, sp, #2008 ; 0x7d8 + 19ca6: 9810 ldr r0, [sp, #64] ; 0x40 + 19ca8: 2108 movs r1, #8 + 19caa: f810 ed01 ldrb.w lr, [r0, #-1]! + 19cae: 910e str r1, [sp, #56] ; 0x38 + 19cb0: 9010 str r0, [sp, #64] ; 0x40 + 19cb2: f8cd e030 str.w lr, [sp, #48] ; 0x30 + 19cb6: 9a0c ldr r2, [sp, #48] ; 0x30 + 19cb8: 2100 movs r1, #0 + 19cba: 09d3 lsrs r3, r2, #7 + 19cbc: b2d8 uxtb r0, r3 + 19cbe: e9cd 0106 strd r0, r1, [sp, #24] + 19cc2: e9dd 2306 ldrd r2, r3, [sp, #24] + 19cc6: 4650 mov r0, sl + 19cc8: 9904 ldr r1, [sp, #16] + 19cca: f7ff faaf bl 1922c + 19cce: e9dd 2306 ldrd r2, r3, [sp, #24] + 19cd2: 4628 mov r0, r5 + 19cd4: 9902 ldr r1, [sp, #8] + 19cd6: f7ff faa9 bl 1922c + 19cda: 4651 mov r1, sl + 19cdc: 2250 movs r2, #80 ; 0x50 + 19cde: a840 add r0, sp, #256 ; 0x100 + 19ce0: f7f5 fbc0 bl f464 <_memcpy> + 19ce4: 4650 mov r0, sl + 19ce6: 4629 mov r1, r5 + 19ce8: f7fe fe92 bl 18a10 + 19cec: 46ae mov lr, r5 + 19cee: f10d 0cf8 add.w ip, sp, #248 ; 0xf8 + 19cf2: e9de 0100 ldrd r0, r1, [lr] + 19cf6: e9fc 2302 ldrd r2, r3, [ip, #8]! + 19cfa: 1a12 subs r2, r2, r0 + 19cfc: eb63 0301 sbc.w r3, r3, r1 + 19d00: 45c4 cmp ip, r8 + 19d02: e8ee 2302 strd r2, r3, [lr], #8 + 19d06: d1f4 bne.n 19cf2 + 19d08: 9904 ldr r1, [sp, #16] + 19d0a: 2250 movs r2, #80 ; 0x50 + 19d0c: a854 add r0, sp, #336 ; 0x150 + 19d0e: f7f5 fba9 bl f464 <_memcpy> + 19d12: 9804 ldr r0, [sp, #16] + 19d14: 9902 ldr r1, [sp, #8] + 19d16: f7fe fe7b bl 18a10 + 19d1a: 46c6 mov lr, r8 + 19d1c: f8dd c008 ldr.w ip, [sp, #8] + 19d20: e9dc 0100 ldrd r0, r1, [ip] + 19d24: e9fe 2302 ldrd r2, r3, [lr, #8]! + 19d28: 1a12 subs r2, r2, r0 + 19d2a: eb63 0301 sbc.w r3, r3, r1 + 19d2e: 45be cmp lr, r7 + 19d30: e8ec 2302 strd r2, r3, [ip], #8 + 19d34: d1f4 bne.n 19d20 + 19d36: f60d 0028 addw r0, sp, #2088 ; 0x828 + 19d3a: 9904 ldr r1, [sp, #16] + 19d3c: 462a mov r2, r5 + 19d3e: f7fe fe81 bl 18a44 + 19d42: 4651 mov r1, sl + 19d44: 9a02 ldr r2, [sp, #8] + 19d46: f50d 600c add.w r0, sp, #2240 ; 0x8c0 + 19d4a: f7fe fe7b bl 18a44 + 19d4e: f60d 0028 addw r0, sp, #2088 ; 0x828 + 19d52: f7ff f84f bl 18df4 + 19d56: f60d 0028 addw r0, sp, #2088 ; 0x828 + 19d5a: f7ff f9c3 bl 190e4 + 19d5e: f50d 600c add.w r0, sp, #2240 ; 0x8c0 + 19d62: f7ff f847 bl 18df4 + 19d66: f50d 600c add.w r0, sp, #2240 ; 0x8c0 + 19d6a: f7ff f9bb bl 190e4 + 19d6e: f60d 0128 addw r1, sp, #2088 ; 0x828 + 19d72: 2250 movs r2, #80 ; 0x50 + 19d74: a854 add r0, sp, #336 ; 0x150 + 19d76: f7f5 fb75 bl f464 <_memcpy> + 19d7a: f60d 0028 addw r0, sp, #2088 ; 0x828 + 19d7e: f50d 610c add.w r1, sp, #2240 ; 0x8c0 + 19d82: f7fe fe45 bl 18a10 + 19d86: 46c6 mov lr, r8 + 19d88: f50d 6c0c add.w ip, sp, #2240 ; 0x8c0 + 19d8c: e9dc 0100 ldrd r0, r1, [ip] + 19d90: e9fe 2302 ldrd r2, r3, [lr, #8]! + 19d94: 1a12 subs r2, r2, r0 + 19d96: eb63 0301 sbc.w r3, r3, r1 + 19d9a: 45be cmp lr, r7 + 19d9c: e8ec 2302 strd r2, r3, [ip], #8 + 19da0: d1f4 bne.n 19d8c + 19da2: f50d 601f add.w r0, sp, #2544 ; 0x9f0 + 19da6: f60d 0128 addw r1, sp, #2088 ; 0x828 + 19daa: f7ff fa57 bl 1925c + 19dae: f60d 1058 addw r0, sp, #2392 ; 0x958 + 19db2: f50d 610c add.w r1, sp, #2240 ; 0x8c0 + 19db6: f7ff fa51 bl 1925c + 19dba: f60d 1158 addw r1, sp, #2392 ; 0x958 + 19dbe: aa2c add r2, sp, #176 ; 0xb0 + 19dc0: f50d 600c add.w r0, sp, #2240 ; 0x8c0 + 19dc4: f7fe fe3e bl 18a44 + 19dc8: f50d 600c add.w r0, sp, #2240 ; 0x8c0 + 19dcc: f7ff f812 bl 18df4 + 19dd0: f50d 600c add.w r0, sp, #2240 ; 0x8c0 + 19dd4: f7ff f986 bl 190e4 + 19dd8: f50d 611f add.w r1, sp, #2544 ; 0x9f0 + 19ddc: 2250 movs r2, #80 ; 0x50 + 19dde: 9808 ldr r0, [sp, #32] + 19de0: f7f5 fb40 bl f464 <_memcpy> + 19de4: 2250 movs r2, #80 ; 0x50 + 19de6: f50d 610c add.w r1, sp, #2240 ; 0x8c0 + 19dea: 980a ldr r0, [sp, #40] ; 0x28 + 19dec: f7f5 fb3a bl f464 <_memcpy> + 19df0: f50d 60df add.w r0, sp, #1784 ; 0x6f8 + 19df4: 4651 mov r1, sl + 19df6: f7ff fa31 bl 1925c + 19dfa: f50d 60f2 add.w r0, sp, #1936 ; 0x790 + 19dfe: 4629 mov r1, r5 + 19e00: f7ff fa2c bl 1925c + 19e04: f50d 61df add.w r1, sp, #1784 ; 0x6f8 + 19e08: f50d 62f2 add.w r2, sp, #1936 ; 0x790 + 19e0c: 4658 mov r0, fp + 19e0e: f7fe fe19 bl 18a44 + 19e12: 4658 mov r0, fp + 19e14: f7fe ffee bl 18df4 + 19e18: 4658 mov r0, fp + 19e1a: f7ff f963 bl 190e4 + 19e1e: f50d 6cde add.w ip, sp, #1776 ; 0x6f0 + 19e22: f50d 6ef2 add.w lr, sp, #1936 ; 0x790 + 19e26: e9de 0100 ldrd r0, r1, [lr] + 19e2a: e9fc 2302 ldrd r2, r3, [ip, #8]! + 19e2e: 1a12 subs r2, r2, r0 + 19e30: eb63 0301 sbc.w r3, r3, r1 + 19e34: 45cc cmp ip, r9 + 19e36: e8ee 2302 strd r2, r3, [lr], #8 + 19e3a: d1f4 bne.n 19e26 + 19e3c: 2100 movs r1, #0 + 19e3e: f50d 60d6 add.w r0, sp, #1712 ; 0x6b0 + 19e42: 2248 movs r2, #72 ; 0x48 + 19e44: f7f5 fb64 bl f510 <_memset> + 19e48: f50d 61f1 add.w r1, sp, #1928 ; 0x788 + 19e4c: f50d 6ecb add.w lr, sp, #1624 ; 0x658 + 19e50: 3108 adds r1, #8 + 19e52: 680a ldr r2, [r1, #0] + 19e54: 6848 ldr r0, [r1, #4] + 19e56: fba2 2306 umull r2, r3, r2, r6 + 19e5a: fb06 3300 mla r3, r6, r0, r3 + 19e5e: 42a1 cmp r1, r4 + 19e60: e9ee 2302 strd r2, r3, [lr, #8]! + 19e64: d1f4 bne.n 19e50 + 19e66: f50d 60cc add.w r0, sp, #1632 ; 0x660 + 19e6a: f7ff f93b bl 190e4 + 19e6e: f50d 60cc add.w r0, sp, #1632 ; 0x660 + 19e72: f50d 61df add.w r1, sp, #1784 ; 0x6f8 + 19e76: f7fe fdcb bl 18a10 + 19e7a: f50d 61f2 add.w r1, sp, #1936 ; 0x790 + 19e7e: f50d 62cc add.w r2, sp, #1632 ; 0x660 + 19e82: 9800 ldr r0, [sp, #0] + 19e84: f7fe fdde bl 18a44 + 19e88: 9800 ldr r0, [sp, #0] + 19e8a: f7fe ffb3 bl 18df4 + 19e8e: 9800 ldr r0, [sp, #0] + 19e90: f7ff f928 bl 190e4 + 19e94: e9dd 2306 ldrd r2, r3, [sp, #24] + 19e98: 4658 mov r0, fp + 19e9a: 9908 ldr r1, [sp, #32] + 19e9c: f7ff f9c6 bl 1922c + 19ea0: e9dd 2306 ldrd r2, r3, [sp, #24] + 19ea4: 990a ldr r1, [sp, #40] ; 0x28 + 19ea6: 9800 ldr r0, [sp, #0] + 19ea8: f7ff f9c0 bl 1922c + 19eac: 990c ldr r1, [sp, #48] ; 0x30 + 19eae: 9a0e ldr r2, [sp, #56] ; 0x38 + 19eb0: 004b lsls r3, r1, #1 + 19eb2: b2db uxtb r3, r3 + 19eb4: 3a01 subs r2, #1 + 19eb6: 930c str r3, [sp, #48] ; 0x30 + 19eb8: 920e str r2, [sp, #56] ; 0x38 + 19eba: d00e beq.n 19eda + 19ebc: 4629 mov r1, r5 + 19ebe: 4653 mov r3, sl + 19ec0: 9802 ldr r0, [sp, #8] + 19ec2: 9d0a ldr r5, [sp, #40] ; 0x28 + 19ec4: 9a04 ldr r2, [sp, #16] + 19ec6: 900a str r0, [sp, #40] ; 0x28 + 19ec8: 9808 ldr r0, [sp, #32] + 19eca: 9502 str r5, [sp, #8] + 19ecc: 46da mov sl, fp + 19ece: 9d00 ldr r5, [sp, #0] + 19ed0: 9004 str r0, [sp, #16] + 19ed2: 9100 str r1, [sp, #0] + 19ed4: 9208 str r2, [sp, #32] + 19ed6: 469b mov fp, r3 + 19ed8: e6ed b.n 19cb6 + 19eda: 9910 ldr r1, [sp, #64] ; 0x40 + 19edc: 9a12 ldr r2, [sp, #72] ; 0x48 + 19ede: 4291 cmp r1, r2 + 19ee0: d00e beq.n 19f00 + 19ee2: 462a mov r2, r5 + 19ee4: 4653 mov r3, sl + 19ee6: 9d0a ldr r5, [sp, #40] ; 0x28 + 19ee8: 9802 ldr r0, [sp, #8] + 19eea: 9904 ldr r1, [sp, #16] + 19eec: 9502 str r5, [sp, #8] + 19eee: 9d08 ldr r5, [sp, #32] + 19ef0: 46da mov sl, fp + 19ef2: 9504 str r5, [sp, #16] + 19ef4: 900a str r0, [sp, #40] ; 0x28 + 19ef6: 9d00 ldr r5, [sp, #0] + 19ef8: 9108 str r1, [sp, #32] + 19efa: 9200 str r2, [sp, #0] + 19efc: 469b mov fp, r3 + 19efe: e6d2 b.n 19ca6 + 19f00: 4659 mov r1, fp + 19f02: 2250 movs r2, #80 ; 0x50 + 19f04: a854 add r0, sp, #336 ; 0x150 + 19f06: f7f5 faad bl f464 <_memcpy> + 19f0a: 2250 movs r2, #80 ; 0x50 + 19f0c: 9900 ldr r1, [sp, #0] + 19f0e: f50d 601f add.w r0, sp, #2544 ; 0x9f0 + 19f12: f7f5 faa7 bl f464 <_memcpy> + 19f16: f50d 6080 add.w r0, sp, #1024 ; 0x400 + 19f1a: f50d 611f add.w r1, sp, #2544 ; 0x9f0 + 19f1e: f7ff f99d bl 1925c + 19f22: f60d 1058 addw r0, sp, #2392 ; 0x958 + 19f26: f50d 6180 add.w r1, sp, #1024 ; 0x400 + 19f2a: f7ff f997 bl 1925c + 19f2e: f50d 600c add.w r0, sp, #2240 ; 0x8c0 + 19f32: f60d 1158 addw r1, sp, #2392 ; 0x958 + 19f36: f7ff f991 bl 1925c + 19f3a: f50d 6093 add.w r0, sp, #1176 ; 0x498 + 19f3e: f50d 610c add.w r1, sp, #2240 ; 0x8c0 + 19f42: f50d 621f add.w r2, sp, #2544 ; 0x9f0 + 19f46: f7ff fb75 bl 19634 + 19f4a: f50d 6280 add.w r2, sp, #1024 ; 0x400 + 19f4e: f50d 60a6 add.w r0, sp, #1328 ; 0x530 + 19f52: f50d 6193 add.w r1, sp, #1176 ; 0x498 + 19f56: f7ff fb6d bl 19634 + 19f5a: f50d 600c add.w r0, sp, #2240 ; 0x8c0 + 19f5e: f50d 61a6 add.w r1, sp, #1328 ; 0x530 + 19f62: f7ff f97b bl 1925c + 19f66: f50d 6293 add.w r2, sp, #1176 ; 0x498 + 19f6a: f50d 60b9 add.w r0, sp, #1480 ; 0x5c8 + 19f6e: f50d 610c add.w r1, sp, #2240 ; 0x8c0 + 19f72: f7ff fb5f bl 19634 + 19f76: f50d 600c add.w r0, sp, #2240 ; 0x8c0 + 19f7a: f50d 61b9 add.w r1, sp, #1480 ; 0x5c8 + 19f7e: f7ff f96d bl 1925c + 19f82: f60d 1058 addw r0, sp, #2392 ; 0x958 + 19f86: f50d 610c add.w r1, sp, #2240 ; 0x8c0 + 19f8a: f7ff f967 bl 1925c + 19f8e: f50d 600c add.w r0, sp, #2240 ; 0x8c0 + 19f92: f60d 1158 addw r1, sp, #2392 ; 0x958 + 19f96: f7ff f961 bl 1925c + 19f9a: f60d 1058 addw r0, sp, #2392 ; 0x958 + 19f9e: f50d 610c add.w r1, sp, #2240 ; 0x8c0 + 19fa2: f7ff f95b bl 1925c + 19fa6: f50d 600c add.w r0, sp, #2240 ; 0x8c0 + 19faa: f60d 1158 addw r1, sp, #2392 ; 0x958 + 19fae: f7ff f955 bl 1925c + 19fb2: f50d 62b9 add.w r2, sp, #1480 ; 0x5c8 + 19fb6: f50d 60cc add.w r0, sp, #1632 ; 0x660 + 19fba: f50d 610c add.w r1, sp, #2240 ; 0x8c0 + 19fbe: f7ff fb39 bl 19634 + 19fc2: f50d 600c add.w r0, sp, #2240 ; 0x8c0 + 19fc6: f50d 61cc add.w r1, sp, #1632 ; 0x660 + 19fca: f7ff f947 bl 1925c + 19fce: f60d 1058 addw r0, sp, #2392 ; 0x958 + 19fd2: f50d 610c add.w r1, sp, #2240 ; 0x8c0 + 19fd6: f7ff f941 bl 1925c + 19fda: 2404 movs r4, #4 + 19fdc: f50d 600c add.w r0, sp, #2240 ; 0x8c0 + 19fe0: f60d 1158 addw r1, sp, #2392 ; 0x958 + 19fe4: f7ff f93a bl 1925c + 19fe8: f60d 1058 addw r0, sp, #2392 ; 0x958 + 19fec: f50d 610c add.w r1, sp, #2240 ; 0x8c0 + 19ff0: f7ff f934 bl 1925c + 19ff4: 3c01 subs r4, #1 + 19ff6: d1f1 bne.n 19fdc + 19ff8: f50d 62cc add.w r2, sp, #1632 ; 0x660 + 19ffc: f50d 60df add.w r0, sp, #1784 ; 0x6f8 + 1a000: f60d 1158 addw r1, sp, #2392 ; 0x958 + 1a004: f7ff fb16 bl 19634 + 1a008: f50d 600c add.w r0, sp, #2240 ; 0x8c0 + 1a00c: f50d 61df add.w r1, sp, #1784 ; 0x6f8 + 1a010: f7ff f924 bl 1925c + 1a014: f60d 1058 addw r0, sp, #2392 ; 0x958 + 1a018: f50d 610c add.w r1, sp, #2240 ; 0x8c0 + 1a01c: f7ff f91e bl 1925c + 1a020: 2409 movs r4, #9 + 1a022: f50d 600c add.w r0, sp, #2240 ; 0x8c0 + 1a026: f60d 1158 addw r1, sp, #2392 ; 0x958 + 1a02a: f7ff f917 bl 1925c + 1a02e: f60d 1058 addw r0, sp, #2392 ; 0x958 + 1a032: f50d 610c add.w r1, sp, #2240 ; 0x8c0 + 1a036: f7ff f911 bl 1925c + 1a03a: 3c01 subs r4, #1 + 1a03c: d1f1 bne.n 1a022 + 1a03e: f50d 62df add.w r2, sp, #1784 ; 0x6f8 + 1a042: f50d 600c add.w r0, sp, #2240 ; 0x8c0 + 1a046: f60d 1158 addw r1, sp, #2392 ; 0x958 + 1a04a: f7ff faf3 bl 19634 + 1a04e: f60d 1058 addw r0, sp, #2392 ; 0x958 + 1a052: f50d 610c add.w r1, sp, #2240 ; 0x8c0 + 1a056: f7ff f901 bl 1925c + 1a05a: f50d 600c add.w r0, sp, #2240 ; 0x8c0 + 1a05e: f60d 1158 addw r1, sp, #2392 ; 0x958 + 1a062: f7ff f8fb bl 1925c + 1a066: 2404 movs r4, #4 + 1a068: f60d 1058 addw r0, sp, #2392 ; 0x958 + 1a06c: f50d 610c add.w r1, sp, #2240 ; 0x8c0 + 1a070: f7ff f8f4 bl 1925c + 1a074: f50d 600c add.w r0, sp, #2240 ; 0x8c0 + 1a078: f60d 1158 addw r1, sp, #2392 ; 0x958 + 1a07c: f7ff f8ee bl 1925c + 1a080: 3c01 subs r4, #1 + 1a082: d1f1 bne.n 1a068 + 1a084: f50d 62cc add.w r2, sp, #1632 ; 0x660 + 1a088: f50d 60f2 add.w r0, sp, #1936 ; 0x790 + 1a08c: f50d 610c add.w r1, sp, #2240 ; 0x8c0 + 1a090: f7ff fad0 bl 19634 + 1a094: f50d 600c add.w r0, sp, #2240 ; 0x8c0 + 1a098: f50d 61f2 add.w r1, sp, #1936 ; 0x790 + 1a09c: f7ff f8de bl 1925c + 1a0a0: f60d 1058 addw r0, sp, #2392 ; 0x958 + 1a0a4: f50d 610c add.w r1, sp, #2240 ; 0x8c0 + 1a0a8: f7ff f8d8 bl 1925c + 1a0ac: 2418 movs r4, #24 + 1a0ae: f50d 600c add.w r0, sp, #2240 ; 0x8c0 + 1a0b2: f60d 1158 addw r1, sp, #2392 ; 0x958 + 1a0b6: f7ff f8d1 bl 1925c + 1a0ba: f60d 1058 addw r0, sp, #2392 ; 0x958 + 1a0be: f50d 610c add.w r1, sp, #2240 ; 0x8c0 + 1a0c2: f7ff f8cb bl 1925c + 1a0c6: 3c01 subs r4, #1 + 1a0c8: d1f1 bne.n 1a0ae + 1a0ca: f50d 62f2 add.w r2, sp, #1936 ; 0x790 + 1a0ce: f60d 0028 addw r0, sp, #2088 ; 0x828 + 1a0d2: f60d 1158 addw r1, sp, #2392 ; 0x958 + 1a0d6: f7ff faad bl 19634 + 1a0da: f60d 1058 addw r0, sp, #2392 ; 0x958 + 1a0de: f60d 0128 addw r1, sp, #2088 ; 0x828 + 1a0e2: f7ff f8bb bl 1925c + 1a0e6: f50d 600c add.w r0, sp, #2240 ; 0x8c0 + 1a0ea: f60d 1158 addw r1, sp, #2392 ; 0x958 + 1a0ee: f7ff f8b5 bl 1925c + 1a0f2: 2431 movs r4, #49 ; 0x31 + 1a0f4: f60d 1058 addw r0, sp, #2392 ; 0x958 + 1a0f8: f50d 610c add.w r1, sp, #2240 ; 0x8c0 + 1a0fc: f7ff f8ae bl 1925c + 1a100: f50d 600c add.w r0, sp, #2240 ; 0x8c0 + 1a104: f60d 1158 addw r1, sp, #2392 ; 0x958 + 1a108: f7ff f8a8 bl 1925c + 1a10c: 3c01 subs r4, #1 + 1a10e: d1f1 bne.n 1a0f4 + 1a110: f60d 0228 addw r2, sp, #2088 ; 0x828 + 1a114: f60d 1058 addw r0, sp, #2392 ; 0x958 + 1a118: f50d 610c add.w r1, sp, #2240 ; 0x8c0 + 1a11c: f7ff fa8a bl 19634 + 1a120: f50d 600c add.w r0, sp, #2240 ; 0x8c0 + 1a124: f60d 1158 addw r1, sp, #2392 ; 0x958 + 1a128: f7ff f898 bl 1925c + 1a12c: f60d 1058 addw r0, sp, #2392 ; 0x958 + 1a130: f50d 610c add.w r1, sp, #2240 ; 0x8c0 + 1a134: f7ff f892 bl 1925c + 1a138: 2418 movs r4, #24 + 1a13a: f50d 600c add.w r0, sp, #2240 ; 0x8c0 + 1a13e: f60d 1158 addw r1, sp, #2392 ; 0x958 + 1a142: f7ff f88b bl 1925c + 1a146: f60d 1058 addw r0, sp, #2392 ; 0x958 + 1a14a: f50d 610c add.w r1, sp, #2240 ; 0x8c0 + 1a14e: f7ff f885 bl 1925c + 1a152: 3c01 subs r4, #1 + 1a154: d1f1 bne.n 1a13a + 1a156: f50d 62f2 add.w r2, sp, #1936 ; 0x790 + 1a15a: f50d 600c add.w r0, sp, #2240 ; 0x8c0 + 1a15e: f60d 1158 addw r1, sp, #2392 ; 0x958 + 1a162: f7ff fa67 bl 19634 + 1a166: f60d 1058 addw r0, sp, #2392 ; 0x958 + 1a16a: f50d 610c add.w r1, sp, #2240 ; 0x8c0 + 1a16e: f7ff f875 bl 1925c + 1a172: f50d 600c add.w r0, sp, #2240 ; 0x8c0 + 1a176: f60d 1158 addw r1, sp, #2392 ; 0x958 + 1a17a: f7ff f86f bl 1925c + 1a17e: f60d 1058 addw r0, sp, #2392 ; 0x958 + 1a182: f50d 610c add.w r1, sp, #2240 ; 0x8c0 + 1a186: f7ff f869 bl 1925c + 1a18a: f50d 600c add.w r0, sp, #2240 ; 0x8c0 + 1a18e: f60d 1158 addw r1, sp, #2392 ; 0x958 + 1a192: f7ff f863 bl 1925c + 1a196: f60d 1058 addw r0, sp, #2392 ; 0x958 + 1a19a: f50d 610c add.w r1, sp, #2240 ; 0x8c0 + 1a19e: f7ff f85d bl 1925c + 1a1a2: a8da add r0, sp, #872 ; 0x368 + 1a1a4: f60d 1158 addw r1, sp, #2392 ; 0x958 + 1a1a8: f50d 62a6 add.w r2, sp, #1328 ; 0x530 + 1a1ac: f7ff fa42 bl 19634 + 1a1b0: aada add r2, sp, #872 ; 0x368 + 1a1b2: f50d 601f add.w r0, sp, #2544 ; 0x9f0 + 1a1b6: a954 add r1, sp, #336 ; 0x150 + 1a1b8: f7ff fa3c bl 19634 + 1a1bc: f50d 661f add.w r6, sp, #2544 ; 0x9f0 + 1a1c0: f50d 601f add.w r0, sp, #2544 ; 0x9f0 + 1a1c4: f7fe ff8e bl 190e4 + 1a1c8: e9d6 2300 ldrd r2, r3, [r6] + 1a1cc: f06f 0712 mvn.w r7, #18 + 1a1d0: 2602 movs r6, #2 + 1a1d2: f60d 14f8 addw r4, sp, #2552 ; 0x9f8 + 1a1d6: 2500 movs r5, #0 + 1a1d8: e001 b.n 1a1de + 1a1da: e8f4 2302 ldrd r2, r3, [r4], #8 + 1a1de: ea02 7ee2 and.w lr, r2, r2, asr #31 + 1a1e2: ea02 73e2 and.w r3, r2, r2, asr #31 + 1a1e6: 169b asrs r3, r3, #26 + 1a1e8: ea4f 6e6e mov.w lr, lr, asr #25 + 1a1ec: 07e9 lsls r1, r5, #31 + 1a1ee: eba2 604e sub.w r0, r2, lr, lsl #25 + 1a1f2: eba2 6283 sub.w r2, r2, r3, lsl #26 + 1a1f6: bf55 itete pl + 1a1f8: 4610 movpl r0, r2 + 1a1fa: 6823 ldrmi r3, [r4, #0] + 1a1fc: 6822 ldrpl r2, [r4, #0] + 1a1fe: 4473 addmi r3, lr + 1a200: bf58 it pl + 1a202: 189b addpl r3, r3, r2 + 1a204: 461a mov r2, r3 + 1a206: f105 0501 add.w r5, r5, #1 + 1a20a: bf4c ite mi + 1a20c: 17c1 asrmi r1, r0, #31 + 1a20e: 17c1 asrpl r1, r0, #31 + 1a210: 17db asrs r3, r3, #31 + 1a212: 2d09 cmp r5, #9 + 1a214: e944 0102 strd r0, r1, [r4, #-8] + 1a218: e9c4 2300 strd r2, r3, [r4] + 1a21c: d1dd bne.n 1a1da + 1a21e: f8dd 3a38 ldr.w r3, [sp, #2616] ; 0xa38 + 1a222: f8dd 19f0 ldr.w r1, [sp, #2544] ; 0x9f0 + 1a226: ea03 72e3 and.w r2, r3, r3, asr #31 + 1a22a: 1652 asrs r2, r2, #25 + 1a22c: 4252 negs r2, r2 + 1a22e: fb07 1e02 mla lr, r7, r2, r1 + 1a232: eb03 6342 add.w r3, r3, r2, lsl #25 + 1a236: 4618 mov r0, r3 + 1a238: 4672 mov r2, lr + 1a23a: 17d9 asrs r1, r3, #31 + 1a23c: f60d 2438 addw r4, sp, #2616 ; 0xa38 + 1a240: ea4f 73ee mov.w r3, lr, asr #31 + 1a244: f50d 651f add.w r5, sp, #2544 ; 0x9f0 + 1a248: 3e01 subs r6, #1 + 1a24a: e9c4 0100 strd r0, r1, [r4] + 1a24e: e9c5 2300 strd r2, r3, [r5] + 1a252: d1be bne.n 1a1d2 + 1a254: f50d 6622 add.w r6, sp, #2592 ; 0xa20 + 1a258: e9d6 8900 ldrd r8, r9, [r6] + 1a25c: ea0e 7cee and.w ip, lr, lr, asr #31 + 1a260: f8dd 69f8 ldr.w r6, [sp, #2552] ; 0x9f8 + 1a264: ea4f 6cac mov.w ip, ip, asr #26 + 1a268: f8dd 5a00 ldr.w r5, [sp, #2560] ; 0xa00 + 1a26c: 4466 add r6, ip + 1a26e: f8dd a04c ldr.w sl, [sp, #76] ; 0x4c + 1a272: ebae 6e8c sub.w lr, lr, ip, lsl #26 + 1a276: 00b6 lsls r6, r6, #2 + 1a278: f8dd 4a08 ldr.w r4, [sp, #2568] ; 0xa08 + 1a27c: 00ed lsls r5, r5, #3 + 1a27e: ea46 6c1e orr.w ip, r6, lr, lsr #24 + 1a282: f8dd 1a10 ldr.w r1, [sp, #2576] ; 0xa10 + 1a286: ea4f 2916 mov.w r9, r6, lsr #8 + 1a28a: f8dd b04c ldr.w fp, [sp, #76] ; 0x4c + 1a28e: f88a c003 strb.w ip, [sl, #3] + 1a292: f88a 9004 strb.w r9, [sl, #4] + 1a296: f8dd 7a18 ldr.w r7, [sp, #2584] ; 0xa18 + 1a29a: 0164 lsls r4, r4, #5 + 1a29c: f8dd 2a28 ldr.w r2, [sp, #2600] ; 0xa28 + 1a2a0: f8dd 3a30 ldr.w r3, [sp, #2608] ; 0xa30 + 1a2a4: ea4f 4c16 mov.w ip, r6, lsr #16 + 1a2a8: ea4f 291e mov.w r9, lr, lsr #8 + 1a2ac: ea45 6616 orr.w r6, r5, r6, lsr #24 + 1a2b0: f88a e000 strb.w lr, [sl] + 1a2b4: f88a c005 strb.w ip, [sl, #5] + 1a2b8: f88a 6006 strb.w r6, [sl, #6] + 1a2bc: f88a 9001 strb.w r9, [sl, #1] + 1a2c0: eb18 0808 adds.w r8, r8, r8 + 1a2c4: 0189 lsls r1, r1, #6 + 1a2c6: ea4f 2c15 mov.w ip, r5, lsr #8 + 1a2ca: 0c2e lsrs r6, r5, #16 + 1a2cc: ea4f 2914 mov.w r9, r4, lsr #8 + 1a2d0: ea44 6515 orr.w r5, r4, r5, lsr #24 + 1a2d4: ea4f 4e1e mov.w lr, lr, lsr #16 + 1a2d8: f88a e002 strb.w lr, [sl, #2] + 1a2dc: f88a c007 strb.w ip, [sl, #7] + 1a2e0: f88a 6008 strb.w r6, [sl, #8] + 1a2e4: f88a 5009 strb.w r5, [sl, #9] + 1a2e8: 0180 lsls r0, r0, #6 + 1a2ea: 00d2 lsls r2, r2, #3 + 1a2ec: 011b lsls r3, r3, #4 + 1a2ee: ea48 6a17 orr.w sl, r8, r7, lsr #24 + 1a2f2: ea4f 4e14 mov.w lr, r4, lsr #16 + 1a2f6: ea4f 2c11 mov.w ip, r1, lsr #8 + 1a2fa: ea41 6414 orr.w r4, r1, r4, lsr #24 + 1a2fe: 0c0e lsrs r6, r1, #16 + 1a300: f88b 900a strb.w r9, [fp, #10] + 1a304: 0e09 lsrs r1, r1, #24 + 1a306: ea4f 2918 mov.w r9, r8, lsr #8 + 1a30a: f88b e00b strb.w lr, [fp, #11] + 1a30e: 0a15 lsrs r5, r2, #8 + 1a310: ea4f 4e18 mov.w lr, r8, lsr #16 + 1a314: f88b 400c strb.w r4, [fp, #12] + 1a318: ea42 6818 orr.w r8, r2, r8, lsr #24 + 1a31c: 0c14 lsrs r4, r2, #16 + 1a31e: f88b c00d strb.w ip, [fp, #13] + 1a322: ea43 6212 orr.w r2, r3, r2, lsr #24 + 1a326: ea4f 2c17 mov.w ip, r7, lsr #8 + 1a32a: f88b 600e strb.w r6, [fp, #14] + 1a32e: f88b 100f strb.w r1, [fp, #15] + 1a332: 0c3e lsrs r6, r7, #16 + 1a334: 0a19 lsrs r1, r3, #8 + 1a336: f88b 7010 strb.w r7, [fp, #16] + 1a33a: f88b a013 strb.w sl, [fp, #19] + 1a33e: 0c1f lsrs r7, r3, #16 + 1a340: ea4f 2a10 mov.w sl, r0, lsr #8 + 1a344: ea40 6313 orr.w r3, r0, r3, lsr #24 + 1a348: f88b 9014 strb.w r9, [fp, #20] + 1a34c: ea4f 4910 mov.w r9, r0, lsr #16 + 1a350: 0e00 lsrs r0, r0, #24 + 1a352: f88b e015 strb.w lr, [fp, #21] + 1a356: f88b 8016 strb.w r8, [fp, #22] + 1a35a: f88b 5017 strb.w r5, [fp, #23] + 1a35e: f88b 4018 strb.w r4, [fp, #24] + 1a362: f88b c011 strb.w ip, [fp, #17] + 1a366: f88b 6012 strb.w r6, [fp, #18] + 1a36a: f88b 2019 strb.w r2, [fp, #25] + 1a36e: f88b 101a strb.w r1, [fp, #26] + 1a372: f88b 701b strb.w r7, [fp, #27] + 1a376: f88b 301c strb.w r3, [fp, #28] + 1a37a: f88b a01d strb.w sl, [fp, #29] + 1a37e: f88b 901e strb.w r9, [fp, #30] + 1a382: f88b 001f strb.w r0, [fp, #31] + 1a386: f60d 2d8c addw sp, sp, #2700 ; 0xa8c + 1a38a: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 1a38e: bf00 nop + +0001a390 : + 1a390: 1f03 subs r3, r0, #4 + 1a392: 2b0c cmp r3, #12 + 1a394: d823 bhi.n 1a3de + 1a396: b5f0 push {r4, r5, r6, r7, lr} + 1a398: 2600 movs r6, #0 + 1a39a: b085 sub sp, #20 + 1a39c: 466a mov r2, sp + 1a39e: 4637 mov r7, r6 + 1a3a0: 4633 mov r3, r6 + 1a3a2: 1e45 subs r5, r0, #1 + 1a3a4: 4254 negs r4, r2 + 1a3a6: 402c ands r4, r5 + 1a3a8: ea02 0105 and.w r1, r2, r5 + 1a3ac: f10d 0e00 add.w lr, sp, #0 + 1a3b0: 441c add r4, r3 + 1a3b2: 1a59 subs r1, r3, r1 + 1a3b4: 4474 add r4, lr + 1a3b6: 4471 add r1, lr + 1a3b8: 428c cmp r4, r1 + 1a3ba: eb01 0e00 add.w lr, r1, r0 + 1a3be: bf08 it eq + 1a3c0: 3701 addeq r7, #1 + 1a3c2: d002 beq.n 1a3ca + 1a3c4: 4574 cmp r4, lr + 1a3c6: d107 bne.n 1a3d8 + 1a3c8: 3601 adds r6, #1 + 1a3ca: 3301 adds r3, #1 + 1a3cc: 4283 cmp r3, r0 + 1a3ce: f102 0201 add.w r2, r2, #1 + 1a3d2: d1e7 bne.n 1a3a4 + 1a3d4: 2f01 cmp r7, #1 + 1a3d6: d004 beq.n 1a3e2 + 1a3d8: 2001 movs r0, #1 + 1a3da: b005 add sp, #20 + 1a3dc: bdf0 pop {r4, r5, r6, r7, pc} + 1a3de: 2001 movs r0, #1 + 1a3e0: 4770 bx lr + 1a3e2: 1b70 subs r0, r6, r5 + 1a3e4: bf18 it ne + 1a3e6: 2001 movne r0, #1 + 1a3e8: e7f7 b.n 1a3da + 1a3ea: bf00 nop + +0001a3ec : + 1a3ec: 2300 movs r3, #0 + 1a3ee: f880 3206 strb.w r3, [r0, #518] ; 0x206 + 1a3f2: 4618 mov r0, r3 + 1a3f4: 4770 bx lr + 1a3f6: bf00 nop + +0001a3f8 : + 1a3f8: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + 1a3fc: f012 080f ands.w r8, r2, #15 + 1a400: bf18 it ne + 1a402: f04f 0801 movne.w r8, #1 + 1a406: d10f bne.n 1a428 + 1a408: 1116 asrs r6, r2, #4 + 1a40a: 4604 mov r4, r0 + 1a40c: 460d mov r5, r1 + 1a40e: 461f mov r7, r3 + 1a410: d00a beq.n 1a428 + 1a412: 4621 mov r1, r4 + 1a414: 462a mov r2, r5 + 1a416: 4638 mov r0, r7 + 1a418: f7f5 ffda bl 103d0 + 1a41c: 3e01 subs r6, #1 + 1a41e: f104 0410 add.w r4, r4, #16 + 1a422: f105 0510 add.w r5, r5, #16 + 1a426: d1f4 bne.n 1a412 + 1a428: 4640 mov r0, r8 + 1a42a: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 1a42e: bf00 nop + +0001a430 : + 1a430: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + 1a434: f012 080f ands.w r8, r2, #15 + 1a438: bf18 it ne + 1a43a: f04f 0801 movne.w r8, #1 + 1a43e: d10f bne.n 1a460 + 1a440: 1116 asrs r6, r2, #4 + 1a442: 4604 mov r4, r0 + 1a444: 460d mov r5, r1 + 1a446: 461f mov r7, r3 + 1a448: d00a beq.n 1a460 + 1a44a: 4621 mov r1, r4 + 1a44c: 462a mov r2, r5 + 1a44e: 4638 mov r0, r7 + 1a450: f7f7 f828 bl 114a4 + 1a454: 3e01 subs r6, #1 + 1a456: f104 0410 add.w r4, r4, #16 + 1a45a: f105 0510 add.w r5, r5, #16 + 1a45e: d1f4 bne.n 1a44a + 1a460: 4640 mov r0, r8 + 1a462: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 1a466: bf00 nop + +0001a468 : + 1a468: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} + 1a46c: f012 090f ands.w r9, r2, #15 + 1a470: f8dd 8020 ldr.w r8, [sp, #32] + 1a474: bf18 it ne + 1a476: f04f 0901 movne.w r9, #1 + 1a47a: d126 bne.n 1a4ca + 1a47c: 461c mov r4, r3 + 1a47e: 4303 orrs r3, r0 + 1a480: 079b lsls r3, r3, #30 + 1a482: 4605 mov r5, r0 + 1a484: 460e mov r6, r1 + 1a486: ea4f 1722 mov.w r7, r2, asr #4 + 1a48a: d121 bne.n 1a4d0 + 1a48c: b1ef cbz r7, 1a4ca + 1a48e: 682b ldr r3, [r5, #0] + 1a490: 6821 ldr r1, [r4, #0] + 1a492: 6862 ldr r2, [r4, #4] + 1a494: 404b eors r3, r1 + 1a496: 6023 str r3, [r4, #0] + 1a498: 686b ldr r3, [r5, #4] + 1a49a: 68a1 ldr r1, [r4, #8] + 1a49c: 4053 eors r3, r2 + 1a49e: 6063 str r3, [r4, #4] + 1a4a0: 68ab ldr r3, [r5, #8] + 1a4a2: 68e2 ldr r2, [r4, #12] + 1a4a4: 404b eors r3, r1 + 1a4a6: 60a3 str r3, [r4, #8] + 1a4a8: 68eb ldr r3, [r5, #12] + 1a4aa: 4640 mov r0, r8 + 1a4ac: 4053 eors r3, r2 + 1a4ae: 60e3 str r3, [r4, #12] + 1a4b0: 4621 mov r1, r4 + 1a4b2: 4622 mov r2, r4 + 1a4b4: f7f5 ff8c bl 103d0 + 1a4b8: 2210 movs r2, #16 + 1a4ba: 4630 mov r0, r6 + 1a4bc: 4621 mov r1, r4 + 1a4be: 4415 add r5, r2 + 1a4c0: 4416 add r6, r2 + 1a4c2: f7f4 ffcf bl f464 <_memcpy> + 1a4c6: 3f01 subs r7, #1 + 1a4c8: d1e1 bne.n 1a48e + 1a4ca: 4648 mov r0, r9 + 1a4cc: e8bd 83f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} + 1a4d0: 2f00 cmp r7, #0 + 1a4d2: d0fa beq.n 1a4ca + 1a4d4: 7829 ldrb r1, [r5, #0] + 1a4d6: 7822 ldrb r2, [r4, #0] + 1a4d8: 7863 ldrb r3, [r4, #1] + 1a4da: 404a eors r2, r1 + 1a4dc: 7022 strb r2, [r4, #0] + 1a4de: 7869 ldrb r1, [r5, #1] + 1a4e0: 78a2 ldrb r2, [r4, #2] + 1a4e2: 404b eors r3, r1 + 1a4e4: 7063 strb r3, [r4, #1] + 1a4e6: 78a9 ldrb r1, [r5, #2] + 1a4e8: 78e3 ldrb r3, [r4, #3] + 1a4ea: 404a eors r2, r1 + 1a4ec: 70a2 strb r2, [r4, #2] + 1a4ee: 78e9 ldrb r1, [r5, #3] + 1a4f0: 7922 ldrb r2, [r4, #4] + 1a4f2: 404b eors r3, r1 + 1a4f4: 70e3 strb r3, [r4, #3] + 1a4f6: 7929 ldrb r1, [r5, #4] + 1a4f8: 7963 ldrb r3, [r4, #5] + 1a4fa: 404a eors r2, r1 + 1a4fc: 7122 strb r2, [r4, #4] + 1a4fe: 7969 ldrb r1, [r5, #5] + 1a500: 79a2 ldrb r2, [r4, #6] + 1a502: 404b eors r3, r1 + 1a504: 7163 strb r3, [r4, #5] + 1a506: 79a9 ldrb r1, [r5, #6] + 1a508: 79e3 ldrb r3, [r4, #7] + 1a50a: 404a eors r2, r1 + 1a50c: 71a2 strb r2, [r4, #6] + 1a50e: 79e9 ldrb r1, [r5, #7] + 1a510: 7a22 ldrb r2, [r4, #8] + 1a512: 404b eors r3, r1 + 1a514: 71e3 strb r3, [r4, #7] + 1a516: 7a29 ldrb r1, [r5, #8] + 1a518: 7a63 ldrb r3, [r4, #9] + 1a51a: 404a eors r2, r1 + 1a51c: 7222 strb r2, [r4, #8] + 1a51e: 7a69 ldrb r1, [r5, #9] + 1a520: 7aa2 ldrb r2, [r4, #10] + 1a522: 404b eors r3, r1 + 1a524: 7263 strb r3, [r4, #9] + 1a526: 7aa9 ldrb r1, [r5, #10] + 1a528: 7ae3 ldrb r3, [r4, #11] + 1a52a: 404a eors r2, r1 + 1a52c: 72a2 strb r2, [r4, #10] + 1a52e: 7aea ldrb r2, [r5, #11] + 1a530: 4640 mov r0, r8 + 1a532: 4053 eors r3, r2 + 1a534: 72e3 strb r3, [r4, #11] + 1a536: 7b29 ldrb r1, [r5, #12] + 1a538: 7b22 ldrb r2, [r4, #12] + 1a53a: 7b63 ldrb r3, [r4, #13] + 1a53c: 404a eors r2, r1 + 1a53e: 7322 strb r2, [r4, #12] + 1a540: 7b69 ldrb r1, [r5, #13] + 1a542: 7ba2 ldrb r2, [r4, #14] + 1a544: 404b eors r3, r1 + 1a546: 7363 strb r3, [r4, #13] + 1a548: 7ba9 ldrb r1, [r5, #14] + 1a54a: 7be3 ldrb r3, [r4, #15] + 1a54c: 404a eors r2, r1 + 1a54e: 73a2 strb r2, [r4, #14] + 1a550: 7bea ldrb r2, [r5, #15] + 1a552: 4621 mov r1, r4 + 1a554: 4053 eors r3, r2 + 1a556: 73e3 strb r3, [r4, #15] + 1a558: 4622 mov r2, r4 + 1a55a: f7f5 ff39 bl 103d0 + 1a55e: 2210 movs r2, #16 + 1a560: 4630 mov r0, r6 + 1a562: 4621 mov r1, r4 + 1a564: 4415 add r5, r2 + 1a566: 4416 add r6, r2 + 1a568: f7f4 ff7c bl f464 <_memcpy> + 1a56c: 3f01 subs r7, #1 + 1a56e: d1b1 bne.n 1a4d4 + 1a570: 4648 mov r0, r9 + 1a572: e8bd 83f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} + 1a576: bf00 nop + +0001a578 : + 1a578: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 1a57c: 461d mov r5, r3 + 1a57e: b087 sub sp, #28 + 1a580: f012 030f ands.w r3, r2, #15 + 1a584: 9301 str r3, [sp, #4] + 1a586: bf18 it ne + 1a588: 2301 movne r3, #1 + 1a58a: f8dd 9040 ldr.w r9, [sp, #64] ; 0x40 + 1a58e: bf18 it ne + 1a590: 9301 strne r3, [sp, #4] + 1a592: d136 bne.n 1a602 + 1a594: 460c mov r4, r1 + 1a596: 4329 orrs r1, r5 + 1a598: 1113 asrs r3, r2, #4 + 1a59a: 460a mov r2, r1 + 1a59c: 0792 lsls r2, r2, #30 + 1a59e: 4606 mov r6, r0 + 1a5a0: d133 bne.n 1a60a + 1a5a2: f104 0710 add.w r7, r4, #16 + 1a5a6: 469b mov fp, r3 + 1a5a8: 46ba mov sl, r7 + 1a5aa: f10d 0808 add.w r8, sp, #8 + 1a5ae: b90b cbnz r3, 1a5b4 + 1a5b0: e027 b.n 1a602 + 1a5b2: 3710 adds r7, #16 + 1a5b4: 4631 mov r1, r6 + 1a5b6: 2210 movs r2, #16 + 1a5b8: 4640 mov r0, r8 + 1a5ba: f7f4 ff53 bl f464 <_memcpy> + 1a5be: 4631 mov r1, r6 + 1a5c0: 4622 mov r2, r4 + 1a5c2: 4648 mov r0, r9 + 1a5c4: f7f6 ff6e bl 114a4 + 1a5c8: f85a 1c10 ldr.w r1, [sl, #-16] + 1a5cc: 682a ldr r2, [r5, #0] + 1a5ce: 4628 mov r0, r5 + 1a5d0: 404a eors r2, r1 + 1a5d2: f84a 2c10 str.w r2, [sl, #-16] + 1a5d6: 6861 ldr r1, [r4, #4] + 1a5d8: 686a ldr r2, [r5, #4] + 1a5da: 68a3 ldr r3, [r4, #8] + 1a5dc: 404a eors r2, r1 + 1a5de: 6062 str r2, [r4, #4] + 1a5e0: 68aa ldr r2, [r5, #8] + 1a5e2: 4641 mov r1, r8 + 1a5e4: 405a eors r2, r3 + 1a5e6: 60a2 str r2, [r4, #8] + 1a5e8: 68e3 ldr r3, [r4, #12] + 1a5ea: 68ea ldr r2, [r5, #12] + 1a5ec: 405a eors r2, r3 + 1a5ee: 60e2 str r2, [r4, #12] + 1a5f0: 2210 movs r2, #16 + 1a5f2: 4416 add r6, r2 + 1a5f4: 4492 add sl, r2 + 1a5f6: f7f4 ff35 bl f464 <_memcpy> + 1a5fa: f1bb 0b01 subs.w fp, fp, #1 + 1a5fe: 463c mov r4, r7 + 1a600: d1d7 bne.n 1a5b2 + 1a602: 9801 ldr r0, [sp, #4] + 1a604: b007 add sp, #28 + 1a606: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 1a60a: f104 0710 add.w r7, r4, #16 + 1a60e: 469b mov fp, r3 + 1a610: 46ba mov sl, r7 + 1a612: f10d 0808 add.w r8, sp, #8 + 1a616: b90b cbnz r3, 1a61c + 1a618: e7f3 b.n 1a602 + 1a61a: 3710 adds r7, #16 + 1a61c: 4631 mov r1, r6 + 1a61e: 2210 movs r2, #16 + 1a620: 4640 mov r0, r8 + 1a622: f7f4 ff1f bl f464 <_memcpy> + 1a626: 4631 mov r1, r6 + 1a628: 4622 mov r2, r4 + 1a62a: 4648 mov r0, r9 + 1a62c: f7f6 ff3a bl 114a4 + 1a630: f81a 1c10 ldrb.w r1, [sl, #-16] + 1a634: 782a ldrb r2, [r5, #0] + 1a636: 4628 mov r0, r5 + 1a638: 404a eors r2, r1 + 1a63a: f80a 2c10 strb.w r2, [sl, #-16] + 1a63e: 786a ldrb r2, [r5, #1] + 1a640: f894 e001 ldrb.w lr, [r4, #1] + 1a644: 78a1 ldrb r1, [r4, #2] + 1a646: ea8e 0202 eor.w r2, lr, r2 + 1a64a: 7062 strb r2, [r4, #1] + 1a64c: 78aa ldrb r2, [r5, #2] + 1a64e: f894 e003 ldrb.w lr, [r4, #3] + 1a652: 404a eors r2, r1 + 1a654: 70a2 strb r2, [r4, #2] + 1a656: 78ea ldrb r2, [r5, #3] + 1a658: 7921 ldrb r1, [r4, #4] + 1a65a: ea8e 0202 eor.w r2, lr, r2 + 1a65e: 70e2 strb r2, [r4, #3] + 1a660: 792a ldrb r2, [r5, #4] + 1a662: f894 e005 ldrb.w lr, [r4, #5] + 1a666: 404a eors r2, r1 + 1a668: 7122 strb r2, [r4, #4] + 1a66a: 796a ldrb r2, [r5, #5] + 1a66c: 79a1 ldrb r1, [r4, #6] + 1a66e: ea8e 0202 eor.w r2, lr, r2 + 1a672: 7162 strb r2, [r4, #5] + 1a674: 79aa ldrb r2, [r5, #6] + 1a676: f894 e007 ldrb.w lr, [r4, #7] + 1a67a: 404a eors r2, r1 + 1a67c: 71a2 strb r2, [r4, #6] + 1a67e: 79ea ldrb r2, [r5, #7] + 1a680: 7a21 ldrb r1, [r4, #8] + 1a682: ea8e 0202 eor.w r2, lr, r2 + 1a686: 71e2 strb r2, [r4, #7] + 1a688: 7a2a ldrb r2, [r5, #8] + 1a68a: f894 e009 ldrb.w lr, [r4, #9] + 1a68e: 404a eors r2, r1 + 1a690: 7222 strb r2, [r4, #8] + 1a692: 7a6a ldrb r2, [r5, #9] + 1a694: 7aa1 ldrb r1, [r4, #10] + 1a696: ea8e 0202 eor.w r2, lr, r2 + 1a69a: 7262 strb r2, [r4, #9] + 1a69c: 7aaa ldrb r2, [r5, #10] + 1a69e: f894 e00b ldrb.w lr, [r4, #11] + 1a6a2: 404a eors r2, r1 + 1a6a4: 72a2 strb r2, [r4, #10] + 1a6a6: 7aea ldrb r2, [r5, #11] + 1a6a8: f894 c00f ldrb.w ip, [r4, #15] + 1a6ac: ea8e 0202 eor.w r2, lr, r2 + 1a6b0: 72e2 strb r2, [r4, #11] + 1a6b2: 7b2a ldrb r2, [r5, #12] + 1a6b4: f894 e00c ldrb.w lr, [r4, #12] + 1a6b8: 4641 mov r1, r8 + 1a6ba: ea8e 0202 eor.w r2, lr, r2 + 1a6be: 7322 strb r2, [r4, #12] + 1a6c0: 7b6a ldrb r2, [r5, #13] + 1a6c2: f894 e00d ldrb.w lr, [r4, #13] + 1a6c6: 3610 adds r6, #16 + 1a6c8: ea8e 0202 eor.w r2, lr, r2 + 1a6cc: 7362 strb r2, [r4, #13] + 1a6ce: f894 e00e ldrb.w lr, [r4, #14] + 1a6d2: 7baa ldrb r2, [r5, #14] + 1a6d4: f10a 0a10 add.w sl, sl, #16 + 1a6d8: ea8e 0202 eor.w r2, lr, r2 + 1a6dc: 73a2 strb r2, [r4, #14] + 1a6de: f895 e00f ldrb.w lr, [r5, #15] + 1a6e2: 2210 movs r2, #16 + 1a6e4: ea8c 0e0e eor.w lr, ip, lr + 1a6e8: f884 e00f strb.w lr, [r4, #15] + 1a6ec: f7f4 feba bl f464 <_memcpy> + 1a6f0: f1bb 0b01 subs.w fp, fp, #1 + 1a6f4: 463c mov r4, r7 + 1a6f6: d190 bne.n 1a61a + 1a6f8: 9801 ldr r0, [sp, #4] + 1a6fa: b007 add sp, #28 + 1a6fc: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +0001a700 : + 1a700: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 1a704: b085 sub sp, #20 + 1a706: f8dd 9038 ldr.w r9, [sp, #56] ; 0x38 + 1a70a: 4606 mov r6, r0 + 1a70c: f899 4206 ldrb.w r4, [r9, #518] ; 0x206 + 1a710: 460f mov r7, r1 + 1a712: 4693 mov fp, r2 + 1a714: 4698 mov r8, r3 + 1a716: 2c00 cmp r4, #0 + 1a718: f000 8111 beq.w 1a93e + 1a71c: 2a00 cmp r2, #0 + 1a71e: bfcc ite gt + 1a720: 2501 movgt r5, #1 + 1a722: 2500 movle r5, #0 + 1a724: 2c0f cmp r4, #15 + 1a726: bfc8 it gt + 1a728: 2500 movgt r5, #0 + 1a72a: b1b5 cbz r5, 1a75a + 1a72c: 4423 add r3, r4 + 1a72e: 2500 movs r5, #0 + 1a730: 3501 adds r5, #1 + 1a732: 45ab cmp fp, r5 + 1a734: 7818 ldrb r0, [r3, #0] + 1a736: f816 2b01 ldrb.w r2, [r6], #1 + 1a73a: f104 0401 add.w r4, r4, #1 + 1a73e: bfcc ite gt + 1a740: 2101 movgt r1, #1 + 1a742: 2100 movle r1, #0 + 1a744: 2c0f cmp r4, #15 + 1a746: ea82 0200 eor.w r2, r2, r0 + 1a74a: bfc8 it gt + 1a74c: 2100 movgt r1, #0 + 1a74e: f803 2b01 strb.w r2, [r3], #1 + 1a752: f807 2b01 strb.w r2, [r7], #1 + 1a756: 2900 cmp r1, #0 + 1a758: d1ea bne.n 1a730 + 1a75a: 2c10 cmp r4, #16 + 1a75c: bf08 it eq + 1a75e: 2400 moveq r4, #0 + 1a760: ebc5 030b rsb r3, r5, fp + 1a764: 091b lsrs r3, r3, #4 + 1a766: f000 80b6 beq.w 1a8d6 + 1a76a: 07b2 lsls r2, r6, #30 + 1a76c: f000 80f1 beq.w 1a952 + 1a770: f105 030f add.w r3, r5, #15 + 1a774: 459b cmp fp, r3 + 1a776: f340 80ae ble.w 1a8d6 + 1a77a: f1ab 0310 sub.w r3, fp, #16 + 1a77e: 1b5b subs r3, r3, r5 + 1a780: 091b lsrs r3, r3, #4 + 1a782: 461a mov r2, r3 + 1a784: 3201 adds r2, #1 + 1a786: 0112 lsls r2, r2, #4 + 1a788: 9301 str r3, [sp, #4] + 1a78a: 4613 mov r3, r2 + 1a78c: 4433 add r3, r6 + 1a78e: 9403 str r4, [sp, #12] + 1a790: 469a mov sl, r3 + 1a792: 463c mov r4, r7 + 1a794: 9202 str r2, [sp, #8] + 1a796: 4641 mov r1, r8 + 1a798: 4642 mov r2, r8 + 1a79a: 4648 mov r0, r9 + 1a79c: f7f5 fe18 bl 103d0 + 1a7a0: 7831 ldrb r1, [r6, #0] + 1a7a2: f898 2000 ldrb.w r2, [r8] + 1a7a6: 3610 adds r6, #16 + 1a7a8: 404a eors r2, r1 + 1a7aa: f888 2000 strb.w r2, [r8] + 1a7ae: 7022 strb r2, [r4, #0] + 1a7b0: f816 1c0f ldrb.w r1, [r6, #-15] + 1a7b4: f898 2001 ldrb.w r2, [r8, #1] + 1a7b8: 3410 adds r4, #16 + 1a7ba: 404a eors r2, r1 + 1a7bc: f888 2001 strb.w r2, [r8, #1] + 1a7c0: f804 2c0f strb.w r2, [r4, #-15] + 1a7c4: f816 1c0e ldrb.w r1, [r6, #-14] + 1a7c8: f898 2002 ldrb.w r2, [r8, #2] + 1a7cc: 404a eors r2, r1 + 1a7ce: f888 2002 strb.w r2, [r8, #2] + 1a7d2: f804 2c0e strb.w r2, [r4, #-14] + 1a7d6: f816 1c0d ldrb.w r1, [r6, #-13] + 1a7da: f898 2003 ldrb.w r2, [r8, #3] + 1a7de: 404a eors r2, r1 + 1a7e0: f888 2003 strb.w r2, [r8, #3] + 1a7e4: f804 2c0d strb.w r2, [r4, #-13] + 1a7e8: f816 1c0c ldrb.w r1, [r6, #-12] + 1a7ec: f898 2004 ldrb.w r2, [r8, #4] + 1a7f0: 404a eors r2, r1 + 1a7f2: f888 2004 strb.w r2, [r8, #4] + 1a7f6: f804 2c0c strb.w r2, [r4, #-12] + 1a7fa: f816 1c0b ldrb.w r1, [r6, #-11] + 1a7fe: f898 2005 ldrb.w r2, [r8, #5] + 1a802: 404a eors r2, r1 + 1a804: f888 2005 strb.w r2, [r8, #5] + 1a808: f804 2c0b strb.w r2, [r4, #-11] + 1a80c: f816 1c0a ldrb.w r1, [r6, #-10] + 1a810: f898 2006 ldrb.w r2, [r8, #6] + 1a814: 404a eors r2, r1 + 1a816: f888 2006 strb.w r2, [r8, #6] + 1a81a: f804 2c0a strb.w r2, [r4, #-10] + 1a81e: f816 1c09 ldrb.w r1, [r6, #-9] + 1a822: f898 2007 ldrb.w r2, [r8, #7] + 1a826: 404a eors r2, r1 + 1a828: f888 2007 strb.w r2, [r8, #7] + 1a82c: f804 2c09 strb.w r2, [r4, #-9] + 1a830: f816 1c08 ldrb.w r1, [r6, #-8] + 1a834: f898 2008 ldrb.w r2, [r8, #8] + 1a838: 404a eors r2, r1 + 1a83a: f888 2008 strb.w r2, [r8, #8] + 1a83e: f804 2c08 strb.w r2, [r4, #-8] + 1a842: f816 1c07 ldrb.w r1, [r6, #-7] + 1a846: f898 2009 ldrb.w r2, [r8, #9] + 1a84a: 404a eors r2, r1 + 1a84c: f888 2009 strb.w r2, [r8, #9] + 1a850: f804 2c07 strb.w r2, [r4, #-7] + 1a854: f816 1c06 ldrb.w r1, [r6, #-6] + 1a858: f898 200a ldrb.w r2, [r8, #10] + 1a85c: 404a eors r2, r1 + 1a85e: f888 200a strb.w r2, [r8, #10] + 1a862: f804 2c06 strb.w r2, [r4, #-6] + 1a866: f816 1c05 ldrb.w r1, [r6, #-5] + 1a86a: f898 200b ldrb.w r2, [r8, #11] + 1a86e: 404a eors r2, r1 + 1a870: f888 200b strb.w r2, [r8, #11] + 1a874: f804 2c05 strb.w r2, [r4, #-5] + 1a878: f816 1c04 ldrb.w r1, [r6, #-4] + 1a87c: f898 200c ldrb.w r2, [r8, #12] + 1a880: 404a eors r2, r1 + 1a882: f888 200c strb.w r2, [r8, #12] + 1a886: f804 2c04 strb.w r2, [r4, #-4] + 1a88a: f816 1c03 ldrb.w r1, [r6, #-3] + 1a88e: f898 200d ldrb.w r2, [r8, #13] + 1a892: 404a eors r2, r1 + 1a894: f888 200d strb.w r2, [r8, #13] + 1a898: f804 2c03 strb.w r2, [r4, #-3] + 1a89c: f816 1c02 ldrb.w r1, [r6, #-2] + 1a8a0: f898 200e ldrb.w r2, [r8, #14] + 1a8a4: 404a eors r2, r1 + 1a8a6: f888 200e strb.w r2, [r8, #14] + 1a8aa: f804 2c02 strb.w r2, [r4, #-2] + 1a8ae: f816 1c01 ldrb.w r1, [r6, #-1] + 1a8b2: f898 200f ldrb.w r2, [r8, #15] + 1a8b6: 4556 cmp r6, sl + 1a8b8: ea82 0201 eor.w r2, r2, r1 + 1a8bc: f888 200f strb.w r2, [r8, #15] + 1a8c0: f804 2c01 strb.w r2, [r4, #-1] + 1a8c4: f47f af67 bne.w 1a796 + 1a8c8: 9c03 ldr r4, [sp, #12] + 1a8ca: 9b01 ldr r3, [sp, #4] + 1a8cc: 3510 adds r5, #16 + 1a8ce: eb05 1503 add.w r5, r5, r3, lsl #4 + 1a8d2: 9b02 ldr r3, [sp, #8] + 1a8d4: 441f add r7, r3 + 1a8d6: 45ab cmp fp, r5 + 1a8d8: dd2a ble.n 1a930 + 1a8da: 2c00 cmp r4, #0 + 1a8dc: d035 beq.n 1a94a + 1a8de: 4648 mov r0, r9 + 1a8e0: 4641 mov r1, r8 + 1a8e2: 4642 mov r2, r8 + 1a8e4: f7f5 fd74 bl 103d0 + 1a8e8: 2c0f cmp r4, #15 + 1a8ea: bfd4 ite le + 1a8ec: 2301 movle r3, #1 + 1a8ee: 2300 movgt r3, #0 + 1a8f0: 45ab cmp fp, r5 + 1a8f2: bfd8 it le + 1a8f4: 2300 movle r3, #0 + 1a8f6: b1bb cbz r3, 1a928 + 1a8f8: eb08 0304 add.w r3, r8, r4 + 1a8fc: 3501 adds r5, #1 + 1a8fe: 45ab cmp fp, r5 + 1a900: f893 e000 ldrb.w lr, [r3] + 1a904: f816 1b01 ldrb.w r1, [r6], #1 + 1a908: f104 0401 add.w r4, r4, #1 + 1a90c: bfcc ite gt + 1a90e: 2201 movgt r2, #1 + 1a910: 2200 movle r2, #0 + 1a912: 2c0f cmp r4, #15 + 1a914: ea8e 0e01 eor.w lr, lr, r1 + 1a918: bfc8 it gt + 1a91a: 2200 movgt r2, #0 + 1a91c: f803 eb01 strb.w lr, [r3], #1 + 1a920: f807 eb01 strb.w lr, [r7], #1 + 1a924: 2a00 cmp r2, #0 + 1a926: d1e9 bne.n 1a8fc + 1a928: 2c10 cmp r4, #16 + 1a92a: d00a beq.n 1a942 + 1a92c: 45ab cmp fp, r5 + 1a92e: dcd6 bgt.n 1a8de + 1a930: b2e4 uxtb r4, r4 + 1a932: 2000 movs r0, #0 + 1a934: f889 4206 strb.w r4, [r9, #518] ; 0x206 + 1a938: b005 add sp, #20 + 1a93a: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 1a93e: 4625 mov r5, r4 + 1a940: e70e b.n 1a760 + 1a942: 45ab cmp fp, r5 + 1a944: bfd8 it le + 1a946: 2400 movle r4, #0 + 1a948: ddf3 ble.n 1a932 + 1a94a: 2001 movs r0, #1 + 1a94c: b005 add sp, #20 + 1a94e: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 1a952: ea47 0308 orr.w r3, r7, r8 + 1a956: 079b lsls r3, r3, #30 + 1a958: f47f af0a bne.w 1a770 + 1a95c: f105 030f add.w r3, r5, #15 + 1a960: 459b cmp fp, r3 + 1a962: ddb8 ble.n 1a8d6 + 1a964: f1ab 0310 sub.w r3, fp, #16 + 1a968: 1b5b subs r3, r3, r5 + 1a96a: 091b lsrs r3, r3, #4 + 1a96c: 461a mov r2, r3 + 1a96e: 3201 adds r2, #1 + 1a970: 0112 lsls r2, r2, #4 + 1a972: 9301 str r3, [sp, #4] + 1a974: 4613 mov r3, r2 + 1a976: 46ba mov sl, r7 + 1a978: 4433 add r3, r6 + 1a97a: 9403 str r4, [sp, #12] + 1a97c: 462f mov r7, r5 + 1a97e: 461c mov r4, r3 + 1a980: 4655 mov r5, sl + 1a982: 9202 str r2, [sp, #8] + 1a984: 4641 mov r1, r8 + 1a986: 4642 mov r2, r8 + 1a988: 4648 mov r0, r9 + 1a98a: f7f5 fd21 bl 103d0 + 1a98e: 6831 ldr r1, [r6, #0] + 1a990: f8d8 2000 ldr.w r2, [r8] + 1a994: 3610 adds r6, #16 + 1a996: 404a eors r2, r1 + 1a998: f8c8 2000 str.w r2, [r8] + 1a99c: 602a str r2, [r5, #0] + 1a99e: f856 1c0c ldr.w r1, [r6, #-12] + 1a9a2: f8d8 2004 ldr.w r2, [r8, #4] + 1a9a6: 3510 adds r5, #16 + 1a9a8: 404a eors r2, r1 + 1a9aa: f8c8 2004 str.w r2, [r8, #4] + 1a9ae: f845 2c0c str.w r2, [r5, #-12] + 1a9b2: f856 1c08 ldr.w r1, [r6, #-8] + 1a9b6: f8d8 2008 ldr.w r2, [r8, #8] + 1a9ba: 404a eors r2, r1 + 1a9bc: f8c8 2008 str.w r2, [r8, #8] + 1a9c0: f845 2c08 str.w r2, [r5, #-8] + 1a9c4: f856 1c04 ldr.w r1, [r6, #-4] + 1a9c8: f8d8 200c ldr.w r2, [r8, #12] + 1a9cc: 42a6 cmp r6, r4 + 1a9ce: ea82 0201 eor.w r2, r2, r1 + 1a9d2: f8c8 200c str.w r2, [r8, #12] + 1a9d6: f845 2c04 str.w r2, [r5, #-4] + 1a9da: d1d3 bne.n 1a984 + 1a9dc: 463d mov r5, r7 + 1a9de: 9c03 ldr r4, [sp, #12] + 1a9e0: 4657 mov r7, sl + 1a9e2: e772 b.n 1a8ca + +0001a9e4 : + 1a9e4: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 1a9e8: b085 sub sp, #20 + 1a9ea: f8dd 9038 ldr.w r9, [sp, #56] ; 0x38 + 1a9ee: 4606 mov r6, r0 + 1a9f0: f899 4206 ldrb.w r4, [r9, #518] ; 0x206 + 1a9f4: 460f mov r7, r1 + 1a9f6: 4693 mov fp, r2 + 1a9f8: 4698 mov r8, r3 + 1a9fa: 2c00 cmp r4, #0 + 1a9fc: f000 8110 beq.w 1ac20 + 1aa00: 2a00 cmp r2, #0 + 1aa02: bfcc ite gt + 1aa04: 2501 movgt r5, #1 + 1aa06: 2500 movle r5, #0 + 1aa08: 2c0f cmp r4, #15 + 1aa0a: bfc8 it gt + 1aa0c: 2500 movgt r5, #0 + 1aa0e: b1b5 cbz r5, 1aa3e + 1aa10: 4423 add r3, r4 + 1aa12: 2500 movs r5, #0 + 1aa14: 3501 adds r5, #1 + 1aa16: 45ab cmp fp, r5 + 1aa18: f816 2b01 ldrb.w r2, [r6], #1 + 1aa1c: 7818 ldrb r0, [r3, #0] + 1aa1e: f104 0401 add.w r4, r4, #1 + 1aa22: bfcc ite gt + 1aa24: 2101 movgt r1, #1 + 1aa26: 2100 movle r1, #0 + 1aa28: 2c0f cmp r4, #15 + 1aa2a: ea80 0002 eor.w r0, r0, r2 + 1aa2e: bfc8 it gt + 1aa30: 2100 movgt r1, #0 + 1aa32: f807 0b01 strb.w r0, [r7], #1 + 1aa36: f803 2b01 strb.w r2, [r3], #1 + 1aa3a: 2900 cmp r1, #0 + 1aa3c: d1ea bne.n 1aa14 + 1aa3e: 2c10 cmp r4, #16 + 1aa40: bf08 it eq + 1aa42: 2400 moveq r4, #0 + 1aa44: ebc5 030b rsb r3, r5, fp + 1aa48: 091b lsrs r3, r3, #4 + 1aa4a: f000 80b6 beq.w 1abba + 1aa4e: 07b2 lsls r2, r6, #30 + 1aa50: f000 80f0 beq.w 1ac34 + 1aa54: f105 030f add.w r3, r5, #15 + 1aa58: 459b cmp fp, r3 + 1aa5a: f340 80ae ble.w 1abba + 1aa5e: f1ab 0310 sub.w r3, fp, #16 + 1aa62: 1b5b subs r3, r3, r5 + 1aa64: 091b lsrs r3, r3, #4 + 1aa66: 461a mov r2, r3 + 1aa68: 3201 adds r2, #1 + 1aa6a: 0112 lsls r2, r2, #4 + 1aa6c: 9301 str r3, [sp, #4] + 1aa6e: 4613 mov r3, r2 + 1aa70: 4433 add r3, r6 + 1aa72: 9403 str r4, [sp, #12] + 1aa74: 469a mov sl, r3 + 1aa76: 463c mov r4, r7 + 1aa78: 9202 str r2, [sp, #8] + 1aa7a: 4641 mov r1, r8 + 1aa7c: 4642 mov r2, r8 + 1aa7e: 4648 mov r0, r9 + 1aa80: f7f5 fca6 bl 103d0 + 1aa84: 7832 ldrb r2, [r6, #0] + 1aa86: f898 1000 ldrb.w r1, [r8] + 1aa8a: 3610 adds r6, #16 + 1aa8c: 4051 eors r1, r2 + 1aa8e: 7021 strb r1, [r4, #0] + 1aa90: f888 2000 strb.w r2, [r8] + 1aa94: f816 2c0f ldrb.w r2, [r6, #-15] + 1aa98: f898 1001 ldrb.w r1, [r8, #1] + 1aa9c: 3410 adds r4, #16 + 1aa9e: 4051 eors r1, r2 + 1aaa0: f804 1c0f strb.w r1, [r4, #-15] + 1aaa4: f888 2001 strb.w r2, [r8, #1] + 1aaa8: f816 2c0e ldrb.w r2, [r6, #-14] + 1aaac: f898 1002 ldrb.w r1, [r8, #2] + 1aab0: 4051 eors r1, r2 + 1aab2: f804 1c0e strb.w r1, [r4, #-14] + 1aab6: f888 2002 strb.w r2, [r8, #2] + 1aaba: f816 2c0d ldrb.w r2, [r6, #-13] + 1aabe: f898 1003 ldrb.w r1, [r8, #3] + 1aac2: 4051 eors r1, r2 + 1aac4: f804 1c0d strb.w r1, [r4, #-13] + 1aac8: f888 2003 strb.w r2, [r8, #3] + 1aacc: f816 2c0c ldrb.w r2, [r6, #-12] + 1aad0: f898 1004 ldrb.w r1, [r8, #4] + 1aad4: 4051 eors r1, r2 + 1aad6: f804 1c0c strb.w r1, [r4, #-12] + 1aada: f888 2004 strb.w r2, [r8, #4] + 1aade: f816 2c0b ldrb.w r2, [r6, #-11] + 1aae2: f898 1005 ldrb.w r1, [r8, #5] + 1aae6: 4051 eors r1, r2 + 1aae8: f804 1c0b strb.w r1, [r4, #-11] + 1aaec: f888 2005 strb.w r2, [r8, #5] + 1aaf0: f816 2c0a ldrb.w r2, [r6, #-10] + 1aaf4: f898 1006 ldrb.w r1, [r8, #6] + 1aaf8: 4051 eors r1, r2 + 1aafa: f804 1c0a strb.w r1, [r4, #-10] + 1aafe: f888 2006 strb.w r2, [r8, #6] + 1ab02: f816 2c09 ldrb.w r2, [r6, #-9] + 1ab06: f898 1007 ldrb.w r1, [r8, #7] + 1ab0a: 4051 eors r1, r2 + 1ab0c: f804 1c09 strb.w r1, [r4, #-9] + 1ab10: f888 2007 strb.w r2, [r8, #7] + 1ab14: f816 2c08 ldrb.w r2, [r6, #-8] + 1ab18: f898 1008 ldrb.w r1, [r8, #8] + 1ab1c: 4051 eors r1, r2 + 1ab1e: f804 1c08 strb.w r1, [r4, #-8] + 1ab22: f888 2008 strb.w r2, [r8, #8] + 1ab26: f816 2c07 ldrb.w r2, [r6, #-7] + 1ab2a: f898 1009 ldrb.w r1, [r8, #9] + 1ab2e: 4051 eors r1, r2 + 1ab30: f804 1c07 strb.w r1, [r4, #-7] + 1ab34: f888 2009 strb.w r2, [r8, #9] + 1ab38: f816 2c06 ldrb.w r2, [r6, #-6] + 1ab3c: f898 100a ldrb.w r1, [r8, #10] + 1ab40: 4051 eors r1, r2 + 1ab42: f804 1c06 strb.w r1, [r4, #-6] + 1ab46: f888 200a strb.w r2, [r8, #10] + 1ab4a: f816 2c05 ldrb.w r2, [r6, #-5] + 1ab4e: f898 100b ldrb.w r1, [r8, #11] + 1ab52: 4051 eors r1, r2 + 1ab54: f804 1c05 strb.w r1, [r4, #-5] + 1ab58: f888 200b strb.w r2, [r8, #11] + 1ab5c: f816 2c04 ldrb.w r2, [r6, #-4] + 1ab60: f898 100c ldrb.w r1, [r8, #12] + 1ab64: 4051 eors r1, r2 + 1ab66: f804 1c04 strb.w r1, [r4, #-4] + 1ab6a: f888 200c strb.w r2, [r8, #12] + 1ab6e: f816 2c03 ldrb.w r2, [r6, #-3] + 1ab72: f898 100d ldrb.w r1, [r8, #13] + 1ab76: 4051 eors r1, r2 + 1ab78: f804 1c03 strb.w r1, [r4, #-3] + 1ab7c: f888 200d strb.w r2, [r8, #13] + 1ab80: f816 2c02 ldrb.w r2, [r6, #-2] + 1ab84: f898 100e ldrb.w r1, [r8, #14] + 1ab88: 4051 eors r1, r2 + 1ab8a: f804 1c02 strb.w r1, [r4, #-2] + 1ab8e: f888 200e strb.w r2, [r8, #14] + 1ab92: f816 2c01 ldrb.w r2, [r6, #-1] + 1ab96: f898 100f ldrb.w r1, [r8, #15] + 1ab9a: 4556 cmp r6, sl + 1ab9c: ea81 0102 eor.w r1, r1, r2 + 1aba0: f804 1c01 strb.w r1, [r4, #-1] + 1aba4: f888 200f strb.w r2, [r8, #15] + 1aba8: f47f af67 bne.w 1aa7a + 1abac: 9c03 ldr r4, [sp, #12] + 1abae: 9b01 ldr r3, [sp, #4] + 1abb0: 3510 adds r5, #16 + 1abb2: eb05 1503 add.w r5, r5, r3, lsl #4 + 1abb6: 9b02 ldr r3, [sp, #8] + 1abb8: 441f add r7, r3 + 1abba: 45ab cmp fp, r5 + 1abbc: dd29 ble.n 1ac12 + 1abbe: 2c00 cmp r4, #0 + 1abc0: d034 beq.n 1ac2c + 1abc2: 4648 mov r0, r9 + 1abc4: 4641 mov r1, r8 + 1abc6: 4642 mov r2, r8 + 1abc8: f7f5 fc02 bl 103d0 + 1abcc: 2c0f cmp r4, #15 + 1abce: bfd4 ite le + 1abd0: 2301 movle r3, #1 + 1abd2: 2300 movgt r3, #0 + 1abd4: 45ab cmp fp, r5 + 1abd6: bfd8 it le + 1abd8: 2300 movle r3, #0 + 1abda: b1b3 cbz r3, 1ac0a + 1abdc: eb08 0304 add.w r3, r8, r4 + 1abe0: 3501 adds r5, #1 + 1abe2: 45ab cmp fp, r5 + 1abe4: f816 eb01 ldrb.w lr, [r6], #1 + 1abe8: 7819 ldrb r1, [r3, #0] + 1abea: f104 0401 add.w r4, r4, #1 + 1abee: bfcc ite gt + 1abf0: 2201 movgt r2, #1 + 1abf2: 2200 movle r2, #0 + 1abf4: 2c0f cmp r4, #15 + 1abf6: ea81 010e eor.w r1, r1, lr + 1abfa: bfc8 it gt + 1abfc: 2200 movgt r2, #0 + 1abfe: f807 1b01 strb.w r1, [r7], #1 + 1ac02: f803 eb01 strb.w lr, [r3], #1 + 1ac06: 2a00 cmp r2, #0 + 1ac08: d1ea bne.n 1abe0 + 1ac0a: 2c10 cmp r4, #16 + 1ac0c: d00a beq.n 1ac24 + 1ac0e: 45ab cmp fp, r5 + 1ac10: dcd7 bgt.n 1abc2 + 1ac12: b2e4 uxtb r4, r4 + 1ac14: 2000 movs r0, #0 + 1ac16: f889 4206 strb.w r4, [r9, #518] ; 0x206 + 1ac1a: b005 add sp, #20 + 1ac1c: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 1ac20: 4625 mov r5, r4 + 1ac22: e70f b.n 1aa44 + 1ac24: 45ab cmp fp, r5 + 1ac26: bfd8 it le + 1ac28: 2400 movle r4, #0 + 1ac2a: ddf3 ble.n 1ac14 + 1ac2c: 2001 movs r0, #1 + 1ac2e: b005 add sp, #20 + 1ac30: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 1ac34: ea47 0308 orr.w r3, r7, r8 + 1ac38: 079b lsls r3, r3, #30 + 1ac3a: f47f af0b bne.w 1aa54 + 1ac3e: f105 030f add.w r3, r5, #15 + 1ac42: 459b cmp fp, r3 + 1ac44: ddb9 ble.n 1abba + 1ac46: f1ab 0310 sub.w r3, fp, #16 + 1ac4a: 1b5b subs r3, r3, r5 + 1ac4c: 091b lsrs r3, r3, #4 + 1ac4e: 461a mov r2, r3 + 1ac50: 3201 adds r2, #1 + 1ac52: 0112 lsls r2, r2, #4 + 1ac54: 9301 str r3, [sp, #4] + 1ac56: 4613 mov r3, r2 + 1ac58: 46ba mov sl, r7 + 1ac5a: 4433 add r3, r6 + 1ac5c: 9403 str r4, [sp, #12] + 1ac5e: 462f mov r7, r5 + 1ac60: 461c mov r4, r3 + 1ac62: 4655 mov r5, sl + 1ac64: 9202 str r2, [sp, #8] + 1ac66: 4641 mov r1, r8 + 1ac68: 4642 mov r2, r8 + 1ac6a: 4648 mov r0, r9 + 1ac6c: f7f5 fbb0 bl 103d0 + 1ac70: 6832 ldr r2, [r6, #0] + 1ac72: f8d8 1000 ldr.w r1, [r8] + 1ac76: 3610 adds r6, #16 + 1ac78: 4051 eors r1, r2 + 1ac7a: 6029 str r1, [r5, #0] + 1ac7c: f8c8 2000 str.w r2, [r8] + 1ac80: f856 2c0c ldr.w r2, [r6, #-12] + 1ac84: f8d8 1004 ldr.w r1, [r8, #4] + 1ac88: 3510 adds r5, #16 + 1ac8a: 4051 eors r1, r2 + 1ac8c: f845 1c0c str.w r1, [r5, #-12] + 1ac90: f8c8 2004 str.w r2, [r8, #4] + 1ac94: f856 2c08 ldr.w r2, [r6, #-8] + 1ac98: f8d8 1008 ldr.w r1, [r8, #8] + 1ac9c: 4051 eors r1, r2 + 1ac9e: f845 1c08 str.w r1, [r5, #-8] + 1aca2: f8c8 2008 str.w r2, [r8, #8] + 1aca6: f856 2c04 ldr.w r2, [r6, #-4] + 1acaa: f8d8 100c ldr.w r1, [r8, #12] + 1acae: 42a6 cmp r6, r4 + 1acb0: ea81 0102 eor.w r1, r1, r2 + 1acb4: f845 1c04 str.w r1, [r5, #-4] + 1acb8: f8c8 200c str.w r2, [r8, #12] + 1acbc: d1d3 bne.n 1ac66 + 1acbe: 463d mov r5, r7 + 1acc0: 9c03 ldr r4, [sp, #12] + 1acc2: 4657 mov r7, sl + 1acc4: e773 b.n 1abae + 1acc6: bf00 nop + +0001acc8 : + 1acc8: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 1accc: b085 sub sp, #20 + 1acce: f8dd 9038 ldr.w r9, [sp, #56] ; 0x38 + 1acd2: 4604 mov r4, r0 + 1acd4: f899 b206 ldrb.w fp, [r9, #518] ; 0x206 + 1acd8: 460d mov r5, r1 + 1acda: 4616 mov r6, r2 + 1acdc: 461f mov r7, r3 + 1acde: 46da mov sl, fp + 1ace0: f1bb 0f00 cmp.w fp, #0 + 1ace4: d029 beq.n 1ad3a + 1ace6: 2a00 cmp r2, #0 + 1ace8: bfcc ite gt + 1acea: 2301 movgt r3, #1 + 1acec: 2300 movle r3, #0 + 1acee: f1bb 0f0f cmp.w fp, #15 + 1acf2: bfc8 it gt + 1acf4: 2300 movgt r3, #0 + 1acf6: 2b00 cmp r3, #0 + 1acf8: f000 813e beq.w 1af78 + 1acfc: f04f 0a00 mov.w sl, #0 + 1ad00: eb07 0e0b add.w lr, r7, fp + 1ad04: f81e 100a ldrb.w r1, [lr, sl] + 1ad08: f10a 0a01 add.w sl, sl, #1 + 1ad0c: 4556 cmp r6, sl + 1ad0e: f814 2b01 ldrb.w r2, [r4], #1 + 1ad12: f10b 0b01 add.w fp, fp, #1 + 1ad16: bfcc ite gt + 1ad18: 2301 movgt r3, #1 + 1ad1a: 2300 movle r3, #0 + 1ad1c: f1bb 0f0f cmp.w fp, #15 + 1ad20: ea82 0201 eor.w r2, r2, r1 + 1ad24: bfc8 it gt + 1ad26: 2300 movgt r3, #0 + 1ad28: f805 2b01 strb.w r2, [r5], #1 + 1ad2c: 2b00 cmp r3, #0 + 1ad2e: d1e9 bne.n 1ad04 + 1ad30: f1bb 0f10 cmp.w fp, #16 + 1ad34: bf08 it eq + 1ad36: f04f 0b00 moveq.w fp, #0 + 1ad3a: ebca 0206 rsb r2, sl, r6 + 1ad3e: 0912 lsrs r2, r2, #4 + 1ad40: f000 808f beq.w 1ae62 + 1ad44: 07a2 lsls r2, r4, #30 + 1ad46: f000 80d9 beq.w 1aefc + 1ad4a: f10a 020f add.w r2, sl, #15 + 1ad4e: 4296 cmp r6, r2 + 1ad50: f340 8087 ble.w 1ae62 + 1ad54: f1a6 0310 sub.w r3, r6, #16 + 1ad58: ebca 0303 rsb r3, sl, r3 + 1ad5c: 091b lsrs r3, r3, #4 + 1ad5e: 461a mov r2, r3 + 1ad60: 3201 adds r2, #1 + 1ad62: 0112 lsls r2, r2, #4 + 1ad64: 9301 str r3, [sp, #4] + 1ad66: 4613 mov r3, r2 + 1ad68: 4423 add r3, r4 + 1ad6a: 46a8 mov r8, r5 + 1ad6c: 9503 str r5, [sp, #12] + 1ad6e: 461d mov r5, r3 + 1ad70: 463b mov r3, r7 + 1ad72: 4637 mov r7, r6 + 1ad74: 461e mov r6, r3 + 1ad76: 9202 str r2, [sp, #8] + 1ad78: 4631 mov r1, r6 + 1ad7a: 4632 mov r2, r6 + 1ad7c: 4648 mov r0, r9 + 1ad7e: f7f5 fb27 bl 103d0 + 1ad82: 7821 ldrb r1, [r4, #0] + 1ad84: 7832 ldrb r2, [r6, #0] + 1ad86: 3410 adds r4, #16 + 1ad88: 404a eors r2, r1 + 1ad8a: f888 2000 strb.w r2, [r8] + 1ad8e: f814 1c0f ldrb.w r1, [r4, #-15] + 1ad92: 7872 ldrb r2, [r6, #1] + 1ad94: f108 0810 add.w r8, r8, #16 + 1ad98: 404a eors r2, r1 + 1ad9a: f808 2c0f strb.w r2, [r8, #-15] + 1ad9e: f814 1c0e ldrb.w r1, [r4, #-14] + 1ada2: 78b2 ldrb r2, [r6, #2] + 1ada4: 404a eors r2, r1 + 1ada6: f808 2c0e strb.w r2, [r8, #-14] + 1adaa: f814 1c0d ldrb.w r1, [r4, #-13] + 1adae: 78f2 ldrb r2, [r6, #3] + 1adb0: 404a eors r2, r1 + 1adb2: f808 2c0d strb.w r2, [r8, #-13] + 1adb6: f814 1c0c ldrb.w r1, [r4, #-12] + 1adba: 7932 ldrb r2, [r6, #4] + 1adbc: 404a eors r2, r1 + 1adbe: f808 2c0c strb.w r2, [r8, #-12] + 1adc2: f814 1c0b ldrb.w r1, [r4, #-11] + 1adc6: 7972 ldrb r2, [r6, #5] + 1adc8: 404a eors r2, r1 + 1adca: f808 2c0b strb.w r2, [r8, #-11] + 1adce: f814 1c0a ldrb.w r1, [r4, #-10] + 1add2: 79b2 ldrb r2, [r6, #6] + 1add4: 404a eors r2, r1 + 1add6: f808 2c0a strb.w r2, [r8, #-10] + 1adda: f814 1c09 ldrb.w r1, [r4, #-9] + 1adde: 79f2 ldrb r2, [r6, #7] + 1ade0: 404a eors r2, r1 + 1ade2: f808 2c09 strb.w r2, [r8, #-9] + 1ade6: f814 1c08 ldrb.w r1, [r4, #-8] + 1adea: 7a32 ldrb r2, [r6, #8] + 1adec: 404a eors r2, r1 + 1adee: f808 2c08 strb.w r2, [r8, #-8] + 1adf2: f814 1c07 ldrb.w r1, [r4, #-7] + 1adf6: 7a72 ldrb r2, [r6, #9] + 1adf8: 404a eors r2, r1 + 1adfa: f808 2c07 strb.w r2, [r8, #-7] + 1adfe: f814 1c06 ldrb.w r1, [r4, #-6] + 1ae02: 7ab2 ldrb r2, [r6, #10] + 1ae04: 404a eors r2, r1 + 1ae06: f808 2c06 strb.w r2, [r8, #-6] + 1ae0a: f814 1c05 ldrb.w r1, [r4, #-5] + 1ae0e: 7af2 ldrb r2, [r6, #11] + 1ae10: 404a eors r2, r1 + 1ae12: f808 2c05 strb.w r2, [r8, #-5] + 1ae16: f814 1c04 ldrb.w r1, [r4, #-4] + 1ae1a: 7b32 ldrb r2, [r6, #12] + 1ae1c: 404a eors r2, r1 + 1ae1e: f808 2c04 strb.w r2, [r8, #-4] + 1ae22: f814 1c03 ldrb.w r1, [r4, #-3] + 1ae26: 7b72 ldrb r2, [r6, #13] + 1ae28: 404a eors r2, r1 + 1ae2a: f808 2c03 strb.w r2, [r8, #-3] + 1ae2e: f814 1c02 ldrb.w r1, [r4, #-2] + 1ae32: 7bb2 ldrb r2, [r6, #14] + 1ae34: 404a eors r2, r1 + 1ae36: f808 2c02 strb.w r2, [r8, #-2] + 1ae3a: f814 1c01 ldrb.w r1, [r4, #-1] + 1ae3e: 7bf2 ldrb r2, [r6, #15] + 1ae40: 42ac cmp r4, r5 + 1ae42: ea82 0201 eor.w r2, r2, r1 + 1ae46: f808 2c01 strb.w r2, [r8, #-1] + 1ae4a: d195 bne.n 1ad78 + 1ae4c: 4633 mov r3, r6 + 1ae4e: 9a01 ldr r2, [sp, #4] + 1ae50: 463e mov r6, r7 + 1ae52: 461f mov r7, r3 + 1ae54: f10a 0310 add.w r3, sl, #16 + 1ae58: 9d03 ldr r5, [sp, #12] + 1ae5a: eb03 1a02 add.w sl, r3, r2, lsl #4 + 1ae5e: 9b02 ldr r3, [sp, #8] + 1ae60: 441d add r5, r3 + 1ae62: 4556 cmp r6, sl + 1ae64: bfd8 it le + 1ae66: fa5f fc8b uxtble.w ip, fp + 1ae6a: dd41 ble.n 1aef0 + 1ae6c: 46b8 mov r8, r7 + 1ae6e: f1bb 0f00 cmp.w fp, #0 + 1ae72: d037 beq.n 1aee4 + 1ae74: 4648 mov r0, r9 + 1ae76: 4641 mov r1, r8 + 1ae78: 4642 mov r2, r8 + 1ae7a: f7f5 faa9 bl 103d0 + 1ae7e: f1bb 0f0f cmp.w fp, #15 + 1ae82: bfd4 ite le + 1ae84: 2301 movle r3, #1 + 1ae86: 2300 movgt r3, #0 + 1ae88: 4556 cmp r6, sl + 1ae8a: bfd8 it le + 1ae8c: 2300 movle r3, #0 + 1ae8e: 46dc mov ip, fp + 1ae90: b1fb cbz r3, 1aed2 + 1ae92: 4653 mov r3, sl + 1ae94: ebca 010b rsb r1, sl, fp + 1ae98: 4441 add r1, r8 + 1ae9a: 5cca ldrb r2, [r1, r3] + 1ae9c: 3301 adds r3, #1 + 1ae9e: 429e cmp r6, r3 + 1aea0: f814 eb01 ldrb.w lr, [r4], #1 + 1aea4: f10c 0c01 add.w ip, ip, #1 + 1aea8: bfcc ite gt + 1aeaa: 2701 movgt r7, #1 + 1aeac: 2700 movle r7, #0 + 1aeae: f1bc 0f0f cmp.w ip, #15 + 1aeb2: ea82 0e0e eor.w lr, r2, lr + 1aeb6: bfc8 it gt + 1aeb8: 2700 movgt r7, #0 + 1aeba: f805 eb01 strb.w lr, [r5], #1 + 1aebe: 2f00 cmp r7, #0 + 1aec0: d1eb bne.n 1ae9a + 1aec2: f1bc 0f10 cmp.w ip, #16 + 1aec6: d008 beq.n 1aeda + 1aec8: 429e cmp r6, r3 + 1aeca: dd0f ble.n 1aeec + 1aecc: 46e3 mov fp, ip + 1aece: 469a mov sl, r3 + 1aed0: e7d0 b.n 1ae74 + 1aed2: f1bc 0f10 cmp.w ip, #16 + 1aed6: 4653 mov r3, sl + 1aed8: d1f6 bne.n 1aec8 + 1aeda: 429e cmp r6, r3 + 1aedc: bfd8 it le + 1aede: f04f 0c00 movle.w ip, #0 + 1aee2: dd05 ble.n 1aef0 + 1aee4: 2001 movs r0, #1 + 1aee6: b005 add sp, #20 + 1aee8: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 1aeec: fa5f fc8c uxtb.w ip, ip + 1aef0: 2000 movs r0, #0 + 1aef2: f889 c206 strb.w ip, [r9, #518] ; 0x206 + 1aef6: b005 add sp, #20 + 1aef8: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 1aefc: ea45 0207 orr.w r2, r5, r7 + 1af00: 0793 lsls r3, r2, #30 + 1af02: f47f af22 bne.w 1ad4a + 1af06: f10a 020f add.w r2, sl, #15 + 1af0a: 4296 cmp r6, r2 + 1af0c: dda9 ble.n 1ae62 + 1af0e: f1a6 0310 sub.w r3, r6, #16 + 1af12: ebca 0303 rsb r3, sl, r3 + 1af16: 091b lsrs r3, r3, #4 + 1af18: 461a mov r2, r3 + 1af1a: 3201 adds r2, #1 + 1af1c: 0112 lsls r2, r2, #4 + 1af1e: 9301 str r3, [sp, #4] + 1af20: 4613 mov r3, r2 + 1af22: 4423 add r3, r4 + 1af24: 46a8 mov r8, r5 + 1af26: 9503 str r5, [sp, #12] + 1af28: 461d mov r5, r3 + 1af2a: 463b mov r3, r7 + 1af2c: 4637 mov r7, r6 + 1af2e: 461e mov r6, r3 + 1af30: 9202 str r2, [sp, #8] + 1af32: 4631 mov r1, r6 + 1af34: 4632 mov r2, r6 + 1af36: 4648 mov r0, r9 + 1af38: f7f5 fa4a bl 103d0 + 1af3c: 6821 ldr r1, [r4, #0] + 1af3e: 6832 ldr r2, [r6, #0] + 1af40: 3410 adds r4, #16 + 1af42: 404a eors r2, r1 + 1af44: f8c8 2000 str.w r2, [r8] + 1af48: f854 1c0c ldr.w r1, [r4, #-12] + 1af4c: 6872 ldr r2, [r6, #4] + 1af4e: f108 0810 add.w r8, r8, #16 + 1af52: 404a eors r2, r1 + 1af54: f848 2c0c str.w r2, [r8, #-12] + 1af58: f854 1c08 ldr.w r1, [r4, #-8] + 1af5c: 68b2 ldr r2, [r6, #8] + 1af5e: 404a eors r2, r1 + 1af60: f848 2c08 str.w r2, [r8, #-8] + 1af64: f854 1c04 ldr.w r1, [r4, #-4] + 1af68: 68f2 ldr r2, [r6, #12] + 1af6a: 42ac cmp r4, r5 + 1af6c: ea82 0201 eor.w r2, r2, r1 + 1af70: f848 2c04 str.w r2, [r8, #-4] + 1af74: d1dd bne.n 1af32 + 1af76: e769 b.n 1ae4c + 1af78: 469a mov sl, r3 + 1af7a: e6d9 b.n 1ad30 + +0001af7c : + 1af7c: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 1af80: b0a5 sub sp, #148 ; 0x94 + 1af82: 4604 mov r4, r0 + 1af84: 982f ldr r0, [sp, #188] ; 0xbc + 1af86: 460e mov r6, r1 + 1af88: f890 5206 ldrb.w r5, [r0, #518] ; 0x206 + 1af8c: 9203 str r2, [sp, #12] + 1af8e: 461f mov r7, r3 + 1af90: 2d00 cmp r5, #0 + 1af92: f040 8134 bne.w 1b1fe + 1af96: 9903 ldr r1, [sp, #12] + 1af98: 2900 cmp r1, #0 + 1af9a: f000 8173 beq.w 1b284 + 1af9e: aa04 add r2, sp, #16 + 1afa0: 9202 str r2, [sp, #8] + 1afa2: 2500 movs r5, #0 + 1afa4: f8dd 900c ldr.w r9, [sp, #12] + 1afa8: 9a03 ldr r2, [sp, #12] + 1afaa: f1b9 0f80 cmp.w r9, #128 ; 0x80 + 1afae: bfa8 it ge + 1afb0: f04f 0980 movge.w r9, #128 ; 0x80 + 1afb4: ea4f 1b29 mov.w fp, r9, asr #4 + 1afb8: ebc9 0202 rsb r2, r9, r2 + 1afbc: f1bb 0f00 cmp.w fp, #0 + 1afc0: 9203 str r2, [sp, #12] + 1afc2: f340 8111 ble.w 1b1e8 + 1afc6: f04f 0a00 mov.w sl, #0 + 1afca: 9401 str r4, [sp, #4] + 1afcc: f8dd 8008 ldr.w r8, [sp, #8] + 1afd0: 4654 mov r4, sl + 1afd2: f8dd a0b8 ldr.w sl, [sp, #184] ; 0xb8 + 1afd6: 4640 mov r0, r8 + 1afd8: 4639 mov r1, r7 + 1afda: 2210 movs r2, #16 + 1afdc: f7f4 fa42 bl f464 <_memcpy> + 1afe0: 3401 adds r4, #1 + 1afe2: 4638 mov r0, r7 + 1afe4: 47d0 blx sl + 1afe6: 455c cmp r4, fp + 1afe8: f108 0810 add.w r8, r8, #16 + 1afec: d1f3 bne.n 1afd6 + 1afee: 9b02 ldr r3, [sp, #8] + 1aff0: 9c01 ldr r4, [sp, #4] + 1aff2: eb03 100b add.w r0, r3, fp, lsl #4 + 1aff6: f019 0f0f tst.w r9, #15 + 1affa: f040 80ee bne.w 1b1da + 1affe: 9802 ldr r0, [sp, #8] + 1b000: ea4f 120b mov.w r2, fp, lsl #4 + 1b004: 4601 mov r1, r0 + 1b006: 9b2f ldr r3, [sp, #188] ; 0xbc + 1b008: f7ff f9f6 bl 1a3f8 + 1b00c: 2800 cmp r0, #0 + 1b00e: f040 8104 bne.w 1b21a + 1b012: ea46 0304 orr.w r3, r6, r4 + 1b016: f013 0303 ands.w r3, r3, #3 + 1b01a: d157 bne.n 1b0cc + 1b01c: f1b9 0f0f cmp.w r9, #15 + 1b020: f340 80ff ble.w 1b222 + 1b024: 4623 mov r3, r4 + 1b026: 46b6 mov lr, r6 + 1b028: 46a0 mov r8, r4 + 1b02a: f1a9 0110 sub.w r1, r9, #16 + 1b02e: ea4f 1b11 mov.w fp, r1, lsr #4 + 1b032: f104 0c10 add.w ip, r4, #16 + 1b036: 9a02 ldr r2, [sp, #8] + 1b038: eb0c 1c0b add.w ip, ip, fp, lsl #4 + 1b03c: 681c ldr r4, [r3, #0] + 1b03e: 6811 ldr r1, [r2, #0] + 1b040: 6850 ldr r0, [r2, #4] + 1b042: 404c eors r4, r1 + 1b044: f8ce 4000 str.w r4, [lr] + 1b048: 685c ldr r4, [r3, #4] + 1b04a: 6891 ldr r1, [r2, #8] + 1b04c: 4060 eors r0, r4 + 1b04e: f8ce 0004 str.w r0, [lr, #4] + 1b052: 689c ldr r4, [r3, #8] + 1b054: 68d0 ldr r0, [r2, #12] + 1b056: 4061 eors r1, r4 + 1b058: f8ce 1008 str.w r1, [lr, #8] + 1b05c: 68d9 ldr r1, [r3, #12] + 1b05e: 3310 adds r3, #16 + 1b060: 4041 eors r1, r0 + 1b062: 4563 cmp r3, ip + 1b064: f8ce 100c str.w r1, [lr, #12] + 1b068: f102 0210 add.w r2, r2, #16 + 1b06c: f10e 0e10 add.w lr, lr, #16 + 1b070: d1e4 bne.n 1b03c + 1b072: 4644 mov r4, r8 + 1b074: f10b 0b01 add.w fp, fp, #1 + 1b078: f8dd c008 ldr.w ip, [sp, #8] + 1b07c: ea4f 1b0b mov.w fp, fp, lsl #4 + 1b080: eb04 0e0b add.w lr, r4, fp + 1b084: 445e add r6, fp + 1b086: 44dc add ip, fp + 1b088: f10b 0801 add.w r8, fp, #1 + 1b08c: 45d9 cmp r9, fp + 1b08e: 4674 mov r4, lr + 1b090: dd10 ble.n 1b0b4 + 1b092: 3401 adds r4, #1 + 1b094: 4623 mov r3, r4 + 1b096: 3501 adds r5, #1 + 1b098: f813 2d01 ldrb.w r2, [r3, #-1]! + 1b09c: eb0c 0105 add.w r1, ip, r5 + 1b0a0: f811 1c01 ldrb.w r1, [r1, #-1] + 1b0a4: 4443 add r3, r8 + 1b0a6: ebce 0303 rsb r3, lr, r3 + 1b0aa: 404a eors r2, r1 + 1b0ac: 4599 cmp r9, r3 + 1b0ae: f806 2b01 strb.w r2, [r6], #1 + 1b0b2: dcee bgt.n 1b092 + 1b0b4: 9803 ldr r0, [sp, #12] + 1b0b6: 2800 cmp r0, #0 + 1b0b8: f47f af74 bne.w 1afa4 + 1b0bc: b2ed uxtb r5, r5 + 1b0be: 9c2f ldr r4, [sp, #188] ; 0xbc + 1b0c0: 2000 movs r0, #0 + 1b0c2: f884 5206 strb.w r5, [r4, #518] ; 0x206 + 1b0c6: b025 add sp, #148 ; 0x94 + 1b0c8: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 1b0cc: f1b9 0f0f cmp.w r9, #15 + 1b0d0: f340 808e ble.w 1b1f0 + 1b0d4: 4623 mov r3, r4 + 1b0d6: 4631 mov r1, r6 + 1b0d8: f1a9 0b10 sub.w fp, r9, #16 + 1b0dc: ea4f 1b1b mov.w fp, fp, lsr #4 + 1b0e0: f104 0810 add.w r8, r4, #16 + 1b0e4: 9a02 ldr r2, [sp, #8] + 1b0e6: eb08 180b add.w r8, r8, fp, lsl #4 + 1b0ea: f893 c000 ldrb.w ip, [r3] + 1b0ee: f892 e000 ldrb.w lr, [r2] + 1b0f2: 7850 ldrb r0, [r2, #1] + 1b0f4: ea8c 0e0e eor.w lr, ip, lr + 1b0f8: f881 e000 strb.w lr, [r1] + 1b0fc: f893 c001 ldrb.w ip, [r3, #1] + 1b100: f892 e002 ldrb.w lr, [r2, #2] + 1b104: ea8c 0000 eor.w r0, ip, r0 + 1b108: 7048 strb r0, [r1, #1] + 1b10a: f893 c002 ldrb.w ip, [r3, #2] + 1b10e: 78d0 ldrb r0, [r2, #3] + 1b110: ea8c 0e0e eor.w lr, ip, lr + 1b114: f881 e002 strb.w lr, [r1, #2] + 1b118: f893 c003 ldrb.w ip, [r3, #3] + 1b11c: f892 e004 ldrb.w lr, [r2, #4] + 1b120: ea8c 0000 eor.w r0, ip, r0 + 1b124: 70c8 strb r0, [r1, #3] + 1b126: f893 c004 ldrb.w ip, [r3, #4] + 1b12a: 7950 ldrb r0, [r2, #5] + 1b12c: ea8c 0e0e eor.w lr, ip, lr + 1b130: f881 e004 strb.w lr, [r1, #4] + 1b134: f893 c005 ldrb.w ip, [r3, #5] + 1b138: f892 e006 ldrb.w lr, [r2, #6] + 1b13c: ea8c 0000 eor.w r0, ip, r0 + 1b140: 7148 strb r0, [r1, #5] + 1b142: f893 c006 ldrb.w ip, [r3, #6] + 1b146: 79d0 ldrb r0, [r2, #7] + 1b148: ea8c 0e0e eor.w lr, ip, lr + 1b14c: f881 e006 strb.w lr, [r1, #6] + 1b150: f893 c007 ldrb.w ip, [r3, #7] + 1b154: f892 e008 ldrb.w lr, [r2, #8] + 1b158: ea8c 0000 eor.w r0, ip, r0 + 1b15c: 71c8 strb r0, [r1, #7] + 1b15e: f893 c008 ldrb.w ip, [r3, #8] + 1b162: 7a50 ldrb r0, [r2, #9] + 1b164: ea8c 0e0e eor.w lr, ip, lr + 1b168: f881 e008 strb.w lr, [r1, #8] + 1b16c: f893 c009 ldrb.w ip, [r3, #9] + 1b170: f892 e00a ldrb.w lr, [r2, #10] + 1b174: ea8c 0000 eor.w r0, ip, r0 + 1b178: 7248 strb r0, [r1, #9] + 1b17a: f893 c00a ldrb.w ip, [r3, #10] + 1b17e: 7ad0 ldrb r0, [r2, #11] + 1b180: ea8c 0e0e eor.w lr, ip, lr + 1b184: f881 e00a strb.w lr, [r1, #10] + 1b188: f893 e00b ldrb.w lr, [r3, #11] + 1b18c: 3310 adds r3, #16 + 1b18e: ea8e 0000 eor.w r0, lr, r0 + 1b192: 72c8 strb r0, [r1, #11] + 1b194: f813 cc04 ldrb.w ip, [r3, #-4] + 1b198: f892 e00c ldrb.w lr, [r2, #12] + 1b19c: 7b50 ldrb r0, [r2, #13] + 1b19e: ea8c 0e0e eor.w lr, ip, lr + 1b1a2: f881 e00c strb.w lr, [r1, #12] + 1b1a6: f813 cc03 ldrb.w ip, [r3, #-3] + 1b1aa: f892 e00e ldrb.w lr, [r2, #14] + 1b1ae: ea8c 0000 eor.w r0, ip, r0 + 1b1b2: 7348 strb r0, [r1, #13] + 1b1b4: f813 cc02 ldrb.w ip, [r3, #-2] + 1b1b8: 7bd0 ldrb r0, [r2, #15] + 1b1ba: ea8c 0e0e eor.w lr, ip, lr + 1b1be: f881 e00e strb.w lr, [r1, #14] + 1b1c2: f813 ec01 ldrb.w lr, [r3, #-1] + 1b1c6: 4543 cmp r3, r8 + 1b1c8: ea8e 0000 eor.w r0, lr, r0 + 1b1cc: 73c8 strb r0, [r1, #15] + 1b1ce: f102 0210 add.w r2, r2, #16 + 1b1d2: f101 0110 add.w r1, r1, #16 + 1b1d6: d188 bne.n 1b0ea + 1b1d8: e74c b.n 1b074 + 1b1da: 4639 mov r1, r7 + 1b1dc: 2210 movs r2, #16 + 1b1de: f7f4 f941 bl f464 <_memcpy> + 1b1e2: f10b 0b01 add.w fp, fp, #1 + 1b1e6: e70a b.n 1affe + 1b1e8: 9802 ldr r0, [sp, #8] + 1b1ea: f04f 0b00 mov.w fp, #0 + 1b1ee: e702 b.n 1aff6 + 1b1f0: 46a6 mov lr, r4 + 1b1f2: 4683 mov fp, r0 + 1b1f4: f04f 0801 mov.w r8, #1 + 1b1f8: f8dd c008 ldr.w ip, [sp, #8] + 1b1fc: e746 b.n 1b08c + 1b1fe: a904 add r1, sp, #16 + 1b200: 9102 str r1, [sp, #8] + 1b202: 4608 mov r0, r1 + 1b204: 2210 movs r2, #16 + 1b206: 4619 mov r1, r3 + 1b208: f7f4 f92c bl f464 <_memcpy> + 1b20c: 9802 ldr r0, [sp, #8] + 1b20e: 2210 movs r2, #16 + 1b210: 4601 mov r1, r0 + 1b212: 9b2f ldr r3, [sp, #188] ; 0xbc + 1b214: f7ff f8f0 bl 1a3f8 + 1b218: b150 cbz r0, 1b230 + 1b21a: 2001 movs r0, #1 + 1b21c: b025 add sp, #148 ; 0x94 + 1b21e: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 1b222: 46a6 mov lr, r4 + 1b224: 469b mov fp, r3 + 1b226: f04f 0801 mov.w r8, #1 + 1b22a: f8dd c008 ldr.w ip, [sp, #8] + 1b22e: e72d b.n 1b08c + 1b230: 9a03 ldr r2, [sp, #12] + 1b232: 1c13 adds r3, r2, #0 + 1b234: bf18 it ne + 1b236: 2301 movne r3, #1 + 1b238: 2d0f cmp r5, #15 + 1b23a: bfc8 it gt + 1b23c: 2300 movgt r3, #0 + 1b23e: b1cb cbz r3, 1b274 + 1b240: 4613 mov r3, r2 + 1b242: f8dd e008 ldr.w lr, [sp, #8] + 1b246: 3b01 subs r3, #1 + 1b248: f105 0501 add.w r5, r5, #1 + 1b24c: bf14 ite ne + 1b24e: 2201 movne r2, #1 + 1b250: 2200 moveq r2, #0 + 1b252: 2d0f cmp r5, #15 + 1b254: bfcc ite gt + 1b256: 2200 movgt r2, #0 + 1b258: f002 0201 andle.w r2, r2, #1 + 1b25c: eb0e 0105 add.w r1, lr, r5 + 1b260: f811 0c01 ldrb.w r0, [r1, #-1] + 1b264: f814 1b01 ldrb.w r1, [r4], #1 + 1b268: 4041 eors r1, r0 + 1b26a: f806 1b01 strb.w r1, [r6], #1 + 1b26e: 2a00 cmp r2, #0 + 1b270: d1e9 bne.n 1b246 + 1b272: 9303 str r3, [sp, #12] + 1b274: 9b03 ldr r3, [sp, #12] + 1b276: 2b00 cmp r3, #0 + 1b278: f43f af20 beq.w 1b0bc + 1b27c: 4638 mov r0, r7 + 1b27e: 992e ldr r1, [sp, #184] ; 0xb8 + 1b280: 4788 blx r1 + 1b282: e68e b.n 1afa2 + 1b284: 9d03 ldr r5, [sp, #12] + 1b286: e71a b.n 1b0be + +0001b288 : + 1b288: b510 push {r4, lr} + 1b28a: 460c mov r4, r1 + 1b28c: 2280 movs r2, #128 ; 0x80 + 1b28e: 4601 mov r1, r0 + 1b290: 4620 mov r0, r4 + 1b292: f7f4 feb7 bl 10004 + 1b296: 2000 movs r0, #0 + 1b298: 23a0 movs r3, #160 ; 0xa0 + 1b29a: f8c4 0204 str.w r0, [r4, #516] ; 0x204 + 1b29e: f884 3204 strb.w r3, [r4, #516] ; 0x204 + 1b2a2: bd10 pop {r4, pc} + +0001b2a4 : + 1b2a4: b510 push {r4, lr} + 1b2a6: 460c mov r4, r1 + 1b2a8: 22c0 movs r2, #192 ; 0xc0 + 1b2aa: 4601 mov r1, r0 + 1b2ac: 4620 mov r0, r4 + 1b2ae: f7f4 fea9 bl 10004 + 1b2b2: 2000 movs r0, #0 + 1b2b4: 23c0 movs r3, #192 ; 0xc0 + 1b2b6: f8c4 0204 str.w r0, [r4, #516] ; 0x204 + 1b2ba: f884 3204 strb.w r3, [r4, #516] ; 0x204 + 1b2be: bd10 pop {r4, pc} + +0001b2c0 : + 1b2c0: b510 push {r4, lr} + 1b2c2: 460c mov r4, r1 + 1b2c4: f44f 7280 mov.w r2, #256 ; 0x100 + 1b2c8: 4601 mov r1, r0 + 1b2ca: 4620 mov r0, r4 + 1b2cc: f7f4 fe9a bl 10004 + 1b2d0: 2000 movs r0, #0 + 1b2d2: 23e0 movs r3, #224 ; 0xe0 + 1b2d4: f8c4 0204 str.w r0, [r4, #516] ; 0x204 + 1b2d8: f884 3204 strb.w r3, [r4, #516] ; 0x204 + 1b2dc: bd10 pop {r4, pc} + 1b2de: bf00 nop + +0001b2e0 : + 1b2e0: 2920 cmp r1, #32 + 1b2e2: b510 push {r4, lr} + 1b2e4: 4614 mov r4, r2 + 1b2e6: d025 beq.n 1b334 + 1b2e8: dd08 ble.n 1b2fc + 1b2ea: 29c0 cmp r1, #192 ; 0xc0 + 1b2ec: d00a beq.n 1b304 + 1b2ee: f5b1 7f80 cmp.w r1, #256 ; 0x100 + 1b2f2: d01f beq.n 1b334 + 1b2f4: 2980 cmp r1, #128 ; 0x80 + 1b2f6: d011 beq.n 1b31c + 1b2f8: 2001 movs r0, #1 + 1b2fa: bd10 pop {r4, pc} + 1b2fc: 2910 cmp r1, #16 + 1b2fe: d00d beq.n 1b31c + 1b300: 2918 cmp r1, #24 + 1b302: d1f9 bne.n 1b2f8 + 1b304: 4601 mov r1, r0 + 1b306: 22c0 movs r2, #192 ; 0xc0 + 1b308: 4620 mov r0, r4 + 1b30a: f7f4 fe7b bl 10004 + 1b30e: 2000 movs r0, #0 + 1b310: 23c0 movs r3, #192 ; 0xc0 + 1b312: f8c4 0204 str.w r0, [r4, #516] ; 0x204 + 1b316: f884 3204 strb.w r3, [r4, #516] ; 0x204 + 1b31a: bd10 pop {r4, pc} + 1b31c: 4601 mov r1, r0 + 1b31e: 2280 movs r2, #128 ; 0x80 + 1b320: 4620 mov r0, r4 + 1b322: f7f4 fe6f bl 10004 + 1b326: 2000 movs r0, #0 + 1b328: 23a0 movs r3, #160 ; 0xa0 + 1b32a: f8c4 0204 str.w r0, [r4, #516] ; 0x204 + 1b32e: f884 3204 strb.w r3, [r4, #516] ; 0x204 + 1b332: bd10 pop {r4, pc} + 1b334: 4601 mov r1, r0 + 1b336: f44f 7280 mov.w r2, #256 ; 0x100 + 1b33a: 4620 mov r0, r4 + 1b33c: f7f4 fe62 bl 10004 + 1b340: 2000 movs r0, #0 + 1b342: 23e0 movs r3, #224 ; 0xe0 + 1b344: f8c4 0204 str.w r0, [r4, #516] ; 0x204 + 1b348: f884 3204 strb.w r3, [r4, #516] ; 0x204 + 1b34c: bd10 pop {r4, pc} + 1b34e: bf00 nop + +0001b350 : + 1b350: b510 push {r4, lr} + 1b352: 460c mov r4, r1 + 1b354: 2280 movs r2, #128 ; 0x80 + 1b356: 4601 mov r1, r0 + 1b358: 4620 mov r0, r4 + 1b35a: f7f4 fe53 bl 10004 + 1b35e: 2000 movs r0, #0 + 1b360: 23a0 movs r3, #160 ; 0xa0 + 1b362: f8c4 0204 str.w r0, [r4, #516] ; 0x204 + 1b366: f884 3204 strb.w r3, [r4, #516] ; 0x204 + 1b36a: bd10 pop {r4, pc} + +0001b36c : + 1b36c: b510 push {r4, lr} + 1b36e: 460c mov r4, r1 + 1b370: 22c0 movs r2, #192 ; 0xc0 + 1b372: 4601 mov r1, r0 + 1b374: 4620 mov r0, r4 + 1b376: f7f4 fe45 bl 10004 + 1b37a: 2000 movs r0, #0 + 1b37c: 23c0 movs r3, #192 ; 0xc0 + 1b37e: f8c4 0204 str.w r0, [r4, #516] ; 0x204 + 1b382: f884 3204 strb.w r3, [r4, #516] ; 0x204 + 1b386: bd10 pop {r4, pc} + +0001b388 : + 1b388: b510 push {r4, lr} + 1b38a: 460c mov r4, r1 + 1b38c: f44f 7280 mov.w r2, #256 ; 0x100 + 1b390: 4601 mov r1, r0 + 1b392: 4620 mov r0, r4 + 1b394: f7f4 fe36 bl 10004 + 1b398: 2000 movs r0, #0 + 1b39a: 23e0 movs r3, #224 ; 0xe0 + 1b39c: f8c4 0204 str.w r0, [r4, #516] ; 0x204 + 1b3a0: f884 3204 strb.w r3, [r4, #516] ; 0x204 + 1b3a4: bd10 pop {r4, pc} + 1b3a6: bf00 nop + +0001b3a8 : + 1b3a8: 2920 cmp r1, #32 + 1b3aa: b510 push {r4, lr} + 1b3ac: 4614 mov r4, r2 + 1b3ae: d025 beq.n 1b3fc + 1b3b0: dd08 ble.n 1b3c4 + 1b3b2: 29c0 cmp r1, #192 ; 0xc0 + 1b3b4: d00a beq.n 1b3cc + 1b3b6: f5b1 7f80 cmp.w r1, #256 ; 0x100 + 1b3ba: d01f beq.n 1b3fc + 1b3bc: 2980 cmp r1, #128 ; 0x80 + 1b3be: d011 beq.n 1b3e4 + 1b3c0: 2001 movs r0, #1 + 1b3c2: bd10 pop {r4, pc} + 1b3c4: 2910 cmp r1, #16 + 1b3c6: d00d beq.n 1b3e4 + 1b3c8: 2918 cmp r1, #24 + 1b3ca: d1f9 bne.n 1b3c0 + 1b3cc: 4601 mov r1, r0 + 1b3ce: 22c0 movs r2, #192 ; 0xc0 + 1b3d0: 4620 mov r0, r4 + 1b3d2: f7f4 fe17 bl 10004 + 1b3d6: 2000 movs r0, #0 + 1b3d8: 23c0 movs r3, #192 ; 0xc0 + 1b3da: f8c4 0204 str.w r0, [r4, #516] ; 0x204 + 1b3de: f884 3204 strb.w r3, [r4, #516] ; 0x204 + 1b3e2: bd10 pop {r4, pc} + 1b3e4: 4601 mov r1, r0 + 1b3e6: 2280 movs r2, #128 ; 0x80 + 1b3e8: 4620 mov r0, r4 + 1b3ea: f7f4 fe0b bl 10004 + 1b3ee: 2000 movs r0, #0 + 1b3f0: 23a0 movs r3, #160 ; 0xa0 + 1b3f2: f8c4 0204 str.w r0, [r4, #516] ; 0x204 + 1b3f6: f884 3204 strb.w r3, [r4, #516] ; 0x204 + 1b3fa: bd10 pop {r4, pc} + 1b3fc: 4601 mov r1, r0 + 1b3fe: f44f 7280 mov.w r2, #256 ; 0x100 + 1b402: 4620 mov r0, r4 + 1b404: f7f4 fdfe bl 10004 + 1b408: 2000 movs r0, #0 + 1b40a: 23e0 movs r3, #224 ; 0xe0 + 1b40c: f8c4 0204 str.w r0, [r4, #516] ; 0x204 + 1b410: f884 3204 strb.w r3, [r4, #516] ; 0x204 + 1b414: bd10 pop {r4, pc} + 1b416: bf00 nop + +0001b418 : + 1b418: 2000 movs r0, #0 + 1b41a: 4770 bx lr + +0001b41c : + 1b41c: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 1b420: f246 456e movw r5, #25710 ; 0x646e + 1b424: f647 0665 movw r6, #30821 ; 0x7865 + 1b428: f642 5432 movw r4, #11570 ; 0x2d32 + 1b42c: f246 5b74 movw fp, #25972 ; 0x6574 + 1b430: f2c3 3520 movt r5, #13088 ; 0x3320 + 1b434: f2c6 1670 movt r6, #24944 ; 0x6170 + 1b438: f6c7 1462 movt r4, #31074 ; 0x7962 + 1b43c: f6c6 3b20 movt fp, #27424 ; 0x6b20 + 1b440: b0bf sub sp, #252 ; 0xfc + 1b442: f893 9002 ldrb.w r9, [r3, #2] + 1b446: f893 a001 ldrb.w sl, [r3, #1] + 1b44a: 920a str r2, [sp, #40] ; 0x28 + 1b44c: 7d9a ldrb r2, [r3, #22] + 1b44e: f893 8006 ldrb.w r8, [r3, #6] + 1b452: 7c9f ldrb r7, [r3, #18] + 1b454: ea4f 4909 mov.w r9, r9, lsl #16 + 1b458: ea49 2a0a orr.w sl, r9, sl, lsl #8 + 1b45c: 0412 lsls r2, r2, #16 + 1b45e: f893 9005 ldrb.w r9, [r3, #5] + 1b462: f893 c00a ldrb.w ip, [r3, #10] + 1b466: 9203 str r2, [sp, #12] + 1b468: 043f lsls r7, r7, #16 + 1b46a: 781a ldrb r2, [r3, #0] + 1b46c: ea4f 4808 mov.w r8, r8, lsl #16 + 1b470: 9706 str r7, [sp, #24] + 1b472: ea48 2809 orr.w r8, r8, r9, lsl #8 + 1b476: 78df ldrb r7, [r3, #3] + 1b478: f893 9009 ldrb.w r9, [r3, #9] + 1b47c: f893 e00e ldrb.w lr, [r3, #14] + 1b480: ea4f 4c0c mov.w ip, ip, lsl #16 + 1b484: ea4a 0202 orr.w r2, sl, r2 + 1b488: ea42 6207 orr.w r2, r2, r7, lsl #24 + 1b48c: ea4c 2909 orr.w r9, ip, r9, lsl #8 + 1b490: f893 c00d ldrb.w ip, [r3, #13] + 1b494: ea4f 4e0e mov.w lr, lr, lsl #16 + 1b498: 9212 str r2, [sp, #72] ; 0x48 + 1b49a: 791a ldrb r2, [r3, #4] + 1b49c: ea4e 2c0c orr.w ip, lr, ip, lsl #8 + 1b4a0: f893 a011 ldrb.w sl, [r3, #17] + 1b4a4: f893 e007 ldrb.w lr, [r3, #7] + 1b4a8: 9f06 ldr r7, [sp, #24] + 1b4aa: ea48 0202 orr.w r2, r8, r2 + 1b4ae: ea47 2a0a orr.w sl, r7, sl, lsl #8 + 1b4b2: f893 8015 ldrb.w r8, [r3, #21] + 1b4b6: ea42 6e0e orr.w lr, r2, lr, lsl #24 + 1b4ba: 7a1f ldrb r7, [r3, #8] + 1b4bc: 9a03 ldr r2, [sp, #12] + 1b4be: ea49 0707 orr.w r7, r9, r7 + 1b4c2: ea42 2808 orr.w r8, r2, r8, lsl #8 + 1b4c6: f893 9010 ldrb.w r9, [r3, #16] + 1b4ca: 7b1a ldrb r2, [r3, #12] + 1b4cc: ea4a 0909 orr.w r9, sl, r9 + 1b4d0: ea4c 0202 orr.w r2, ip, r2 + 1b4d4: f893 a00b ldrb.w sl, [r3, #11] + 1b4d8: f893 c014 ldrb.w ip, [r3, #20] + 1b4dc: ea47 670a orr.w r7, r7, sl, lsl #24 + 1b4e0: ea48 0c0c orr.w ip, r8, ip + 1b4e4: f893 a013 ldrb.w sl, [r3, #19] + 1b4e8: f893 800f ldrb.w r8, [r3, #15] + 1b4ec: ea49 690a orr.w r9, r9, sl, lsl #24 + 1b4f0: ea42 6208 orr.w r2, r2, r8, lsl #24 + 1b4f4: f8dd a120 ldr.w sl, [sp, #288] ; 0x120 + 1b4f8: f893 8017 ldrb.w r8, [r3, #23] + 1b4fc: f8cd e04c str.w lr, [sp, #76] ; 0x4c + 1b500: 9714 str r7, [sp, #80] ; 0x50 + 1b502: 950f str r5, [sp, #60] ; 0x3c + 1b504: 7e9d ldrb r5, [r3, #26] + 1b506: 960e str r6, [sp, #56] ; 0x38 + 1b508: 9410 str r4, [sp, #64] ; 0x40 + 1b50a: 7e5e ldrb r6, [r3, #25] + 1b50c: 7f9c ldrb r4, [r3, #30] + 1b50e: ea4c 6c08 orr.w ip, ip, r8, lsl #24 + 1b512: 042d lsls r5, r5, #16 + 1b514: f8cd 9058 str.w r9, [sp, #88] ; 0x58 + 1b518: f89a 7006 ldrb.w r7, [sl, #6] + 1b51c: f893 901d ldrb.w r9, [r3, #29] + 1b520: ea45 2606 orr.w r6, r5, r6, lsl #8 + 1b524: 0424 lsls r4, r4, #16 + 1b526: 7e1d ldrb r5, [r3, #24] + 1b528: f8cd c05c str.w ip, [sp, #92] ; 0x5c + 1b52c: f89a e005 ldrb.w lr, [sl, #5] + 1b530: f89a c002 ldrb.w ip, [sl, #2] + 1b534: 043f lsls r7, r7, #16 + 1b536: ea44 2909 orr.w r9, r4, r9, lsl #8 + 1b53a: f89a 8001 ldrb.w r8, [sl, #1] + 1b53e: 7f1c ldrb r4, [r3, #28] + 1b540: ea4f 4c0c mov.w ip, ip, lsl #16 + 1b544: ea47 2e0e orr.w lr, r7, lr, lsl #8 + 1b548: 4335 orrs r5, r6 + 1b54a: f89a 7004 ldrb.w r7, [sl, #4] + 1b54e: 7ede ldrb r6, [r3, #27] + 1b550: 7fdb ldrb r3, [r3, #31] + 1b552: ea4c 2808 orr.w r8, ip, r8, lsl #8 + 1b556: ea49 0904 orr.w r9, r9, r4 + 1b55a: f89a c000 ldrb.w ip, [sl] + 1b55e: f89a 4007 ldrb.w r4, [sl, #7] + 1b562: ea4e 0707 orr.w r7, lr, r7 + 1b566: ea45 6506 orr.w r5, r5, r6, lsl #24 + 1b56a: f8cd b044 str.w fp, [sp, #68] ; 0x44 + 1b56e: ea49 6603 orr.w r6, r9, r3, lsl #24 + 1b572: f89a b003 ldrb.w fp, [sl, #3] + 1b576: 2300 movs r3, #0 + 1b578: ea47 6404 orr.w r4, r7, r4, lsl #24 + 1b57c: ea48 0c0c orr.w ip, r8, ip + 1b580: 9f49 ldr r7, [sp, #292] ; 0x124 + 1b582: 931b str r3, [sp, #108] ; 0x6c + 1b584: 9b0a ldr r3, [sp, #40] ; 0x28 + 1b586: 9215 str r2, [sp, #84] ; 0x54 + 1b588: ea4c 620b orr.w r2, ip, fp, lsl #24 + 1b58c: 900b str r0, [sp, #44] ; 0x2c + 1b58e: 910c str r1, [sp, #48] ; 0x30 + 1b590: 971a str r7, [sp, #104] ; 0x68 + 1b592: 9518 str r5, [sp, #96] ; 0x60 + 1b594: 9619 str r6, [sp, #100] ; 0x64 + 1b596: 921c str r2, [sp, #112] ; 0x70 + 1b598: 941d str r4, [sp, #116] ; 0x74 + 1b59a: 2b00 cmp r3, #0 + 1b59c: f000 8174 beq.w 1b888 + 1b5a0: ad3d add r5, sp, #244 ; 0xf4 + 1b5a2: 9502 str r5, [sp, #8] + 1b5a4: 9e0a ldr r6, [sp, #40] ; 0x28 + 1b5a6: a90e add r1, sp, #56 ; 0x38 + 1b5a8: 2e3f cmp r6, #63 ; 0x3f + 1b5aa: bf86 itte hi + 1b5ac: f1a6 0740 subhi.w r7, r6, #64 ; 0x40 + 1b5b0: 2340 movhi r3, #64 ; 0x40 + 1b5b2: 2500 movls r5, #0 + 1b5b4: f04f 0240 mov.w r2, #64 ; 0x40 + 1b5b8: a82e add r0, sp, #184 ; 0xb8 + 1b5ba: bf86 itte hi + 1b5bc: 970d strhi r7, [sp, #52] ; 0x34 + 1b5be: 930a strhi r3, [sp, #40] ; 0x28 + 1b5c0: 950d strls r5, [sp, #52] ; 0x34 + 1b5c2: f7f3 ff4f bl f464 <_memcpy> + 1b5c6: 9934 ldr r1, [sp, #208] ; 0xd0 + 1b5c8: 9837 ldr r0, [sp, #220] ; 0xdc + 1b5ca: 9105 str r1, [sp, #20] + 1b5cc: 9938 ldr r1, [sp, #224] ; 0xe0 + 1b5ce: f8dd 80c4 ldr.w r8, [sp, #196] ; 0xc4 + 1b5d2: 9106 str r1, [sp, #24] + 1b5d4: 9939 ldr r1, [sp, #228] ; 0xe4 + 1b5d6: f04f 0e0a mov.w lr, #10 + 1b5da: 9004 str r0, [sp, #16] + 1b5dc: f8dd c0f4 ldr.w ip, [sp, #244] ; 0xf4 + 1b5e0: 983c ldr r0, [sp, #240] ; 0xf0 + 1b5e2: f8cd e01c str.w lr, [sp, #28] + 1b5e6: f8dd b0b8 ldr.w fp, [sp, #184] ; 0xb8 + 1b5ea: 46c6 mov lr, r8 + 1b5ec: 9a32 ldr r2, [sp, #200] ; 0xc8 + 1b5ee: 4688 mov r8, r1 + 1b5f0: 9e3a ldr r6, [sp, #232] ; 0xe8 + 1b5f2: 9d36 ldr r5, [sp, #216] ; 0xd8 + 1b5f4: f8dd a0bc ldr.w sl, [sp, #188] ; 0xbc + 1b5f8: 9b33 ldr r3, [sp, #204] ; 0xcc + 1b5fa: 9f3b ldr r7, [sp, #236] ; 0xec + 1b5fc: f8dd 90c0 ldr.w r9, [sp, #192] ; 0xc0 + 1b600: 9c35 ldr r4, [sp, #212] ; 0xd4 + 1b602: 9905 ldr r1, [sp, #20] + 1b604: 9003 str r0, [sp, #12] + 1b606: f8cd c004 str.w ip, [sp, #4] + 1b60a: 9803 ldr r0, [sp, #12] + 1b60c: 44a6 add lr, r4 + 1b60e: f8cd e000 str.w lr, [sp] + 1b612: 4493 add fp, r2 + 1b614: 4489 add r9, r1 + 1b616: ea86 0e0b eor.w lr, r6, fp + 1b61a: ea80 0c09 eor.w ip, r0, r9 + 1b61e: e89d 0041 ldmia.w sp, {r0, r6} + 1b622: 4046 eors r6, r0 + 1b624: 9603 str r6, [sp, #12] + 1b626: ea4f 463e mov.w r6, lr, ror #16 + 1b62a: 449a add sl, r3 + 1b62c: 4435 add r5, r6 + 1b62e: f8dd e00c ldr.w lr, [sp, #12] + 1b632: ea87 070a eor.w r7, r7, sl + 1b636: 9503 str r5, [sp, #12] + 1b638: 9d04 ldr r5, [sp, #16] + 1b63a: ea4f 4737 mov.w r7, r7, ror #16 + 1b63e: 443d add r5, r7 + 1b640: 9504 str r5, [sp, #16] + 1b642: 9d03 ldr r5, [sp, #12] + 1b644: ea4f 403e mov.w r0, lr, ror #16 + 1b648: f8dd e018 ldr.w lr, [sp, #24] + 1b64c: ea4f 4c3c mov.w ip, ip, ror #16 + 1b650: 406a eors r2, r5 + 1b652: 9d04 ldr r5, [sp, #16] + 1b654: 44e6 add lr, ip + 1b656: 406b eors r3, r5 + 1b658: 4675 mov r5, lr + 1b65a: 4480 add r8, r0 + 1b65c: 4069 eors r1, r5 + 1b65e: 4645 mov r5, r8 + 1b660: ea4f 5333 mov.w r3, r3, ror #20 + 1b664: 449a add sl, r3 + 1b666: ea8a 0707 eor.w r7, sl, r7 + 1b66a: ea4f 5131 mov.w r1, r1, ror #20 + 1b66e: ea4f 6737 mov.w r7, r7, ror #24 + 1b672: f8cd e014 str.w lr, [sp, #20] + 1b676: 4489 add r9, r1 + 1b678: f8dd e000 ldr.w lr, [sp] + 1b67c: 9700 str r7, [sp, #0] + 1b67e: f8cd 8024 str.w r8, [sp, #36] ; 0x24 + 1b682: f8cd 9020 str.w r9, [sp, #32] + 1b686: f8dd 8000 ldr.w r8, [sp] + 1b68a: 406c eors r4, r5 + 1b68c: ea89 050c eor.w r5, r9, ip + 1b690: f8dd 9010 ldr.w r9, [sp, #16] + 1b694: ea4f 5232 mov.w r2, r2, ror #20 + 1b698: 4493 add fp, r2 + 1b69a: 44c1 add r9, r8 + 1b69c: f8dd 8014 ldr.w r8, [sp, #20] + 1b6a0: 9f03 ldr r7, [sp, #12] + 1b6a2: ea8b 0606 eor.w r6, fp, r6 + 1b6a6: ea4f 6535 mov.w r5, r5, ror #24 + 1b6aa: 44a8 add r8, r5 + 1b6ac: ea4f 6636 mov.w r6, r6, ror #24 + 1b6b0: 4437 add r7, r6 + 1b6b2: ea88 0101 eor.w r1, r8, r1 + 1b6b6: ea4f 5434 mov.w r4, r4, ror #20 + 1b6ba: 407a eors r2, r7 + 1b6bc: ea4f 6171 mov.w r1, r1, ror #25 + 1b6c0: 448a add sl, r1 + 1b6c2: 44a6 add lr, r4 + 1b6c4: ea4f 6272 mov.w r2, r2, ror #25 + 1b6c8: f8dd c024 ldr.w ip, [sp, #36] ; 0x24 + 1b6cc: ea8e 0000 eor.w r0, lr, r0 + 1b6d0: 9209 str r2, [sp, #36] ; 0x24 + 1b6d2: 4496 add lr, r2 + 1b6d4: 4652 mov r2, sl + 1b6d6: ea4f 6030 mov.w r0, r0, ror #24 + 1b6da: 4484 add ip, r0 + 1b6dc: 9706 str r7, [sp, #24] + 1b6de: ea8c 0404 eor.w r4, ip, r4 + 1b6e2: 9f08 ldr r7, [sp, #32] + 1b6e4: ea89 0303 eor.w r3, r9, r3 + 1b6e8: ea4f 6474 mov.w r4, r4, ror #25 + 1b6ec: 4427 add r7, r4 + 1b6ee: ea4f 6373 mov.w r3, r3, ror #25 + 1b6f2: 449b add fp, r3 + 1b6f4: 9703 str r7, [sp, #12] + 1b6f6: 4056 eors r6, r2 + 1b6f8: 9f00 ldr r7, [sp, #0] + 1b6fa: ea8b 0200 eor.w r2, fp, r0 + 1b6fe: 9803 ldr r0, [sp, #12] + 1b700: ea8e 0505 eor.w r5, lr, r5 + 1b704: f8cd a004 str.w sl, [sp, #4] + 1b708: 4047 eors r7, r0 + 1b70a: f8dd a024 ldr.w sl, [sp, #36] ; 0x24 + 1b70e: ea4f 4032 mov.w r0, r2, ror #16 + 1b712: ea4f 4636 mov.w r6, r6, ror #16 + 1b716: ea4f 4535 mov.w r5, r5, ror #16 + 1b71a: 9a06 ldr r2, [sp, #24] + 1b71c: 44a9 add r9, r5 + 1b71e: 44b4 add ip, r6 + 1b720: ea4f 4737 mov.w r7, r7, ror #16 + 1b724: f8cd c020 str.w ip, [sp, #32] + 1b728: 443a add r2, r7 + 1b72a: ea8a 0c09 eor.w ip, sl, r9 + 1b72e: 9205 str r2, [sp, #20] + 1b730: ea4f 5c3c mov.w ip, ip, ror #20 + 1b734: 9a08 ldr r2, [sp, #32] + 1b736: 44e6 add lr, ip + 1b738: f8cd 9010 str.w r9, [sp, #16] + 1b73c: 4051 eors r1, r2 + 1b73e: ea8e 0505 eor.w r5, lr, r5 + 1b742: 9a05 ldr r2, [sp, #20] + 1b744: f8cd c024 str.w ip, [sp, #36] ; 0x24 + 1b748: f8dd c010 ldr.w ip, [sp, #16] + 1b74c: ea4f 6535 mov.w r5, r5, ror #24 + 1b750: f8dd 900c ldr.w r9, [sp, #12] + 1b754: 9503 str r5, [sp, #12] + 1b756: 4465 add r5, ip + 1b758: 9504 str r5, [sp, #16] + 1b75a: 4615 mov r5, r2 + 1b75c: 4480 add r8, r0 + 1b75e: ea88 0303 eor.w r3, r8, r3 + 1b762: ea4f 5333 mov.w r3, r3, ror #20 + 1b766: 449b add fp, r3 + 1b768: ea8b 0000 eor.w r0, fp, r0 + 1b76c: ea4f 6030 mov.w r0, r0, ror #24 + 1b770: f8dd a004 ldr.w sl, [sp, #4] + 1b774: 9001 str r0, [sp, #4] + 1b776: 4440 add r0, r8 + 1b778: 4054 eors r4, r2 + 1b77a: 9006 str r0, [sp, #24] + 1b77c: 9a04 ldr r2, [sp, #16] + 1b77e: 9809 ldr r0, [sp, #36] ; 0x24 + 1b780: ea4f 5131 mov.w r1, r1, ror #20 + 1b784: ea4f 5434 mov.w r4, r4, ror #20 + 1b788: 4050 eors r0, r2 + 1b78a: 448a add sl, r1 + 1b78c: 44a1 add r9, r4 + 1b78e: 9a06 ldr r2, [sp, #24] + 1b790: ea8a 0606 eor.w r6, sl, r6 + 1b794: ea89 0707 eor.w r7, r9, r7 + 1b798: f8dd 8020 ldr.w r8, [sp, #32] + 1b79c: 4053 eors r3, r2 + 1b79e: ea4f 6636 mov.w r6, r6, ror #24 + 1b7a2: ea4f 6737 mov.w r7, r7, ror #24 + 1b7a6: ea4f 6270 mov.w r2, r0, ror #25 + 1b7aa: 9807 ldr r0, [sp, #28] + 1b7ac: 44b0 add r8, r6 + 1b7ae: 443d add r5, r7 + 1b7b0: ea88 0101 eor.w r1, r8, r1 + 1b7b4: 406c eors r4, r5 + 1b7b6: 3801 subs r0, #1 + 1b7b8: ea4f 6373 mov.w r3, r3, ror #25 + 1b7bc: ea4f 6171 mov.w r1, r1, ror #25 + 1b7c0: ea4f 6474 mov.w r4, r4, ror #25 + 1b7c4: 9007 str r0, [sp, #28] + 1b7c6: f47f af20 bne.w 1b60a + 1b7ca: 9105 str r1, [sp, #20] + 1b7cc: 4641 mov r1, r8 + 1b7ce: f8dd c004 ldr.w ip, [sp, #4] + 1b7d2: 9232 str r2, [sp, #200] ; 0xc8 + 1b7d4: 963a str r6, [sp, #232] ; 0xe8 + 1b7d6: 9a04 ldr r2, [sp, #16] + 1b7d8: 9536 str r5, [sp, #216] ; 0xd8 + 1b7da: 9333 str r3, [sp, #204] ; 0xcc + 1b7dc: 9d03 ldr r5, [sp, #12] + 1b7de: 9b05 ldr r3, [sp, #20] + 1b7e0: 9e06 ldr r6, [sp, #24] + 1b7e2: 9237 str r2, [sp, #220] ; 0xdc + 1b7e4: f8cd b0b8 str.w fp, [sp, #184] ; 0xb8 + 1b7e8: f8cd a0bc str.w sl, [sp, #188] ; 0xbc + 1b7ec: 973b str r7, [sp, #236] ; 0xec + 1b7ee: f8cd 90c0 str.w r9, [sp, #192] ; 0xc0 + 1b7f2: 9334 str r3, [sp, #208] ; 0xd0 + 1b7f4: 953c str r5, [sp, #240] ; 0xf0 + 1b7f6: 9638 str r6, [sp, #224] ; 0xe0 + 1b7f8: f8cd e0c4 str.w lr, [sp, #196] ; 0xc4 + 1b7fc: 9435 str r4, [sp, #212] ; 0xd4 + 1b7fe: f8cd c0f4 str.w ip, [sp, #244] ; 0xf4 + 1b802: 9139 str r1, [sp, #228] ; 0xe4 + 1b804: 465a mov r2, fp + 1b806: e001 b.n 1b80c + 1b808: f858 2000 ldr.w r2, [r8, r0] + 1b80c: af0e add r7, sp, #56 ; 0x38 + 1b80e: 583b ldr r3, [r7, r0] + 1b810: f10d 08b8 add.w r8, sp, #184 ; 0xb8 + 1b814: 4413 add r3, r2 + 1b816: f848 3000 str.w r3, [r8, r0] + 1b81a: 3004 adds r0, #4 + 1b81c: 2840 cmp r0, #64 ; 0x40 + 1b81e: d1f3 bne.n 1b808 + 1b820: a92d add r1, sp, #180 ; 0xb4 + 1b822: ab1e add r3, sp, #120 ; 0x78 + 1b824: f851 2f04 ldr.w r2, [r1, #4]! + 1b828: f8dd 9008 ldr.w r9, [sp, #8] + 1b82c: 0a14 lsrs r4, r2, #8 + 1b82e: 0c10 lsrs r0, r2, #16 + 1b830: 701a strb r2, [r3, #0] + 1b832: 4549 cmp r1, r9 + 1b834: ea4f 6212 mov.w r2, r2, lsr #24 + 1b838: 705c strb r4, [r3, #1] + 1b83a: 7098 strb r0, [r3, #2] + 1b83c: 70da strb r2, [r3, #3] + 1b83e: f103 0304 add.w r3, r3, #4 + 1b842: d1ef bne.n 1b824 + 1b844: 980b ldr r0, [sp, #44] ; 0x2c + 1b846: 9c0c ldr r4, [sp, #48] ; 0x30 + 1b848: 9d0a ldr r5, [sp, #40] ; 0x28 + 1b84a: 2300 movs r3, #0 + 1b84c: f10d 0a78 add.w sl, sp, #120 ; 0x78 + 1b850: 5ce2 ldrb r2, [r4, r3] + 1b852: f81a 1003 ldrb.w r1, [sl, r3] + 1b856: 404a eors r2, r1 + 1b858: 54c2 strb r2, [r0, r3] + 1b85a: 3301 adds r3, #1 + 1b85c: 429d cmp r5, r3 + 1b85e: d8f5 bhi.n 1b84c + 1b860: 9b1a ldr r3, [sp, #104] ; 0x68 + 1b862: 9e0b ldr r6, [sp, #44] ; 0x2c + 1b864: 9d0a ldr r5, [sp, #40] ; 0x28 + 1b866: f8dd 8030 ldr.w r8, [sp, #48] ; 0x30 + 1b86a: 442e add r6, r5 + 1b86c: 3301 adds r3, #1 + 1b86e: 44a8 add r8, r5 + 1b870: 960b str r6, [sp, #44] ; 0x2c + 1b872: f8cd 8030 str.w r8, [sp, #48] ; 0x30 + 1b876: 931a str r3, [sp, #104] ; 0x68 + 1b878: b913 cbnz r3, 1b880 + 1b87a: 9b1b ldr r3, [sp, #108] ; 0x6c + 1b87c: 3301 adds r3, #1 + 1b87e: 931b str r3, [sp, #108] ; 0x6c + 1b880: 9b0d ldr r3, [sp, #52] ; 0x34 + 1b882: b10b cbz r3, 1b888 + 1b884: 930a str r3, [sp, #40] ; 0x28 + 1b886: e68d b.n 1b5a4 + 1b888: b03f add sp, #252 ; 0xfc + 1b88a: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 1b88e: bf00 nop + +0001b890 : + 1b890: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 1b894: 2a0f cmp r2, #15 + 1b896: b0a5 sub sp, #148 ; 0x94 + 1b898: f240 8124 bls.w 1bae4 + 1b89c: 6a43 ldr r3, [r0, #36] ; 0x24 + 1b89e: 6805 ldr r5, [r0, #0] + 1b8a0: 6a06 ldr r6, [r0, #32] + 1b8a2: 69c7 ldr r7, [r0, #28] + 1b8a4: 9302 str r3, [sp, #8] + 1b8a6: 9506 str r5, [sp, #24] + 1b8a8: 6983 ldr r3, [r0, #24] + 1b8aa: 6945 ldr r5, [r0, #20] + 1b8ac: 6a84 ldr r4, [r0, #40] ; 0x28 + 1b8ae: 9607 str r6, [sp, #28] + 1b8b0: 9710 str r7, [sp, #64] ; 0x40 + 1b8b2: 9314 str r3, [sp, #80] ; 0x50 + 1b8b4: 951a str r5, [sp, #104] ; 0x68 + 1b8b6: 6846 ldr r6, [r0, #4] + 1b8b8: 6887 ldr r7, [r0, #8] + 1b8ba: 68c3 ldr r3, [r0, #12] + 1b8bc: 6905 ldr r5, [r0, #16] + 1b8be: 940f str r4, [sp, #60] ; 0x3c + 1b8c0: f8d0 b02c ldr.w fp, [r0, #44] ; 0x2c + 1b8c4: 6b04 ldr r4, [r0, #48] ; 0x30 + 1b8c6: f8d0 e034 ldr.w lr, [r0, #52] ; 0x34 + 1b8ca: 960e str r6, [sp, #56] ; 0x38 + 1b8cc: 9711 str r7, [sp, #68] ; 0x44 + 1b8ce: 9315 str r3, [sp, #84] ; 0x54 + 1b8d0: 951b str r5, [sp, #108] ; 0x6c + 1b8d2: 798b ldrb r3, [r1, #6] + 1b8d4: 794d ldrb r5, [r1, #5] + 1b8d6: f891 a00a ldrb.w sl, [r1, #10] + 1b8da: 041b lsls r3, r3, #16 + 1b8dc: ea43 2305 orr.w r3, r3, r5, lsl #8 + 1b8e0: 7a4d ldrb r5, [r1, #9] + 1b8e2: ea4f 4a0a mov.w sl, sl, lsl #16 + 1b8e6: 790e ldrb r6, [r1, #4] + 1b8e8: f891 c00e ldrb.w ip, [r1, #14] + 1b8ec: ea4a 2a05 orr.w sl, sl, r5, lsl #8 + 1b8f0: 7a0d ldrb r5, [r1, #8] + 1b8f2: 7b4f ldrb r7, [r1, #13] + 1b8f4: 4333 orrs r3, r6 + 1b8f6: ea4a 0a05 orr.w sl, sl, r5 + 1b8fa: 79ce ldrb r6, [r1, #7] + 1b8fc: 7b0d ldrb r5, [r1, #12] + 1b8fe: ea4f 4c0c mov.w ip, ip, lsl #16 + 1b902: ea4c 2c07 orr.w ip, ip, r7, lsl #8 + 1b906: ea43 6306 orr.w r3, r3, r6, lsl #24 + 1b90a: ea4c 0c05 orr.w ip, ip, r5 + 1b90e: 7ace ldrb r6, [r1, #11] + 1b910: 7bcd ldrb r5, [r1, #15] + 1b912: ea4a 6a06 orr.w sl, sl, r6, lsl #24 + 1b916: ea4c 6c05 orr.w ip, ip, r5, lsl #24 + 1b91a: 2600 movs r6, #0 + 1b91c: 788d ldrb r5, [r1, #2] + 1b91e: 9604 str r6, [sp, #16] + 1b920: 9608 str r6, [sp, #32] + 1b922: 960a str r6, [sp, #40] ; 0x28 + 1b924: 784e ldrb r6, [r1, #1] + 1b926: 780f ldrb r7, [r1, #0] + 1b928: 042d lsls r5, r5, #16 + 1b92a: ea45 2506 orr.w r5, r5, r6, lsl #8 + 1b92e: 78ce ldrb r6, [r1, #3] + 1b930: f8cd a024 str.w sl, [sp, #36] ; 0x24 + 1b934: f8cd c02c str.w ip, [sp, #44] ; 0x2c + 1b938: 433d orrs r5, r7 + 1b93a: ea4f 2c1c mov.w ip, ip, lsr #8 + 1b93e: ea45 6506 orr.w r5, r5, r6, lsl #24 + 1b942: e9dd 8908 ldrd r8, r9, [sp, #32] + 1b946: e9dd 670a ldrd r6, r7, [sp, #40] ; 0x28 + 1b94a: ea48 0803 orr.w r8, r8, r3 + 1b94e: ea46 060a orr.w r6, r6, sl + 1b952: f04c 7c80 orr.w ip, ip, #16777216 ; 0x1000000 + 1b956: 9305 str r3, [sp, #20] + 1b958: 44f4 add ip, lr + 1b95a: ea4f 5318 mov.w r3, r8, lsr #20 + 1b95e: ea4f 3e96 mov.w lr, r6, lsr #14 + 1b962: ea43 3309 orr.w r3, r3, r9, lsl #12 + 1b966: ea4e 4e87 orr.w lr, lr, r7, lsl #18 + 1b96a: e9dd 8904 ldrd r8, r9, [sp, #16] + 1b96e: ea48 0805 orr.w r8, r8, r5 + 1b972: f023 4a7c bic.w sl, r3, #4227858432 ; 0xfc000000 + 1b976: f02e 4e7c bic.w lr, lr, #4227858432 ; 0xfc000000 + 1b97a: ea4f 6398 mov.w r3, r8, lsr #26 + 1b97e: 44da add sl, fp + 1b980: ea43 1389 orr.w r3, r3, r9, lsl #6 + 1b984: 44a6 add lr, r4 + 1b986: f8dd b008 ldr.w fp, [sp, #8] + 1b98a: 9c0f ldr r4, [sp, #60] ; 0x3c + 1b98c: f025 457c bic.w r5, r5, #4227858432 ; 0xfc000000 + 1b990: f023 437c bic.w r3, r3, #4227858432 ; 0xfc000000 + 1b994: 3a10 subs r2, #16 + 1b996: 3110 adds r1, #16 + 1b998: 44ab add fp, r5 + 1b99a: 4423 add r3, r4 + 1b99c: 9f06 ldr r7, [sp, #24] + 1b99e: 9d07 ldr r5, [sp, #28] + 1b9a0: fbab 6707 umull r6, r7, fp, r7 + 1b9a4: 9c0e ldr r4, [sp, #56] ; 0x38 + 1b9a6: fbe5 6703 umlal r6, r7, r5, r3 + 1b9aa: fbab 8904 umull r8, r9, fp, r4 + 1b9ae: e9cd 6702 strd r6, r7, [sp, #8] + 1b9b2: e9dd 4502 ldrd r4, r5, [sp, #8] + 1b9b6: 9e06 ldr r6, [sp, #24] + 1b9b8: 9f07 ldr r7, [sp, #28] + 1b9ba: fbe6 8903 umlal r8, r9, r6, r3 + 1b9be: 9e10 ldr r6, [sp, #64] ; 0x40 + 1b9c0: fbe7 890a umlal r8, r9, r7, sl + 1b9c4: fbe6 450a umlal r4, r5, r6, sl + 1b9c8: 9e14 ldr r6, [sp, #80] ; 0x50 + 1b9ca: 9f10 ldr r7, [sp, #64] ; 0x40 + 1b9cc: fbe6 450e umlal r4, r5, r6, lr + 1b9d0: 9e1a ldr r6, [sp, #104] ; 0x68 + 1b9d2: fbe7 890e umlal r8, r9, r7, lr + 1b9d6: fbe6 450c umlal r4, r5, r6, ip + 1b9da: 9f14 ldr r7, [sp, #80] ; 0x50 + 1b9dc: e9cd 4502 strd r4, r5, [sp, #8] + 1b9e0: fbe7 890c umlal r8, r9, r7, ip + 1b9e4: 9e03 ldr r6, [sp, #12] + 1b9e6: 0ea4 lsrs r4, r4, #26 + 1b9e8: ea44 1585 orr.w r5, r4, r5, lsl #6 + 1b9ec: 0eb6 lsrs r6, r6, #26 + 1b9ee: 9613 str r6, [sp, #76] ; 0x4c + 1b9f0: 9512 str r5, [sp, #72] ; 0x48 + 1b9f2: e9dd 4512 ldrd r4, r5, [sp, #72] ; 0x48 + 1b9f6: eb14 0408 adds.w r4, r4, r8 + 1b9fa: eb45 0509 adc.w r5, r5, r9 + 1b9fe: e9cd 4500 strd r4, r5, [sp] + 1ba02: 9d11 ldr r5, [sp, #68] ; 0x44 + 1ba04: 9c0e ldr r4, [sp, #56] ; 0x38 + 1ba06: fbab 6705 umull r6, r7, fp, r5 + 1ba0a: fbe4 6703 umlal r6, r7, r4, r3 + 1ba0e: 9d06 ldr r5, [sp, #24] + 1ba10: 9c07 ldr r4, [sp, #28] + 1ba12: fbe5 670a umlal r6, r7, r5, sl + 1ba16: fbe4 670e umlal r6, r7, r4, lr + 1ba1a: 9d10 ldr r5, [sp, #64] ; 0x40 + 1ba1c: f8dd 8000 ldr.w r8, [sp] + 1ba20: fbe5 670c umlal r6, r7, r5, ip + 1ba24: f8dd 9004 ldr.w r9, [sp, #4] + 1ba28: ea4f 6498 mov.w r4, r8, lsr #26 + 1ba2c: ea44 1489 orr.w r4, r4, r9, lsl #6 + 1ba30: eb16 0804 adds.w r8, r6, r4 + 1ba34: 9e15 ldr r6, [sp, #84] ; 0x54 + 1ba36: f147 0900 adc.w r9, r7, #0 + 1ba3a: fbab 4506 umull r4, r5, fp, r6 + 1ba3e: 9f11 ldr r7, [sp, #68] ; 0x44 + 1ba40: 9e0e ldr r6, [sp, #56] ; 0x38 + 1ba42: fbe7 4503 umlal r4, r5, r7, r3 + 1ba46: fbe6 450a umlal r4, r5, r6, sl + 1ba4a: 9f06 ldr r7, [sp, #24] + 1ba4c: 9e07 ldr r6, [sp, #28] + 1ba4e: fbe7 450e umlal r4, r5, r7, lr + 1ba52: fbe6 450c umlal r4, r5, r6, ip + 1ba56: ea4f 6698 mov.w r6, r8, lsr #26 + 1ba5a: ea46 1689 orr.w r6, r6, r9, lsl #6 + 1ba5e: e9cd 8916 strd r8, r9, [sp, #88] ; 0x58 + 1ba62: eb14 0806 adds.w r8, r4, r6 + 1ba66: 9e1b ldr r6, [sp, #108] ; 0x6c + 1ba68: f145 0900 adc.w r9, r5, #0 + 1ba6c: fbab 4506 umull r4, r5, fp, r6 + 1ba70: 9f15 ldr r7, [sp, #84] ; 0x54 + 1ba72: 9e0e ldr r6, [sp, #56] ; 0x38 + 1ba74: fbe7 4503 umlal r4, r5, r7, r3 + 1ba78: 9b11 ldr r3, [sp, #68] ; 0x44 + 1ba7a: 9f06 ldr r7, [sp, #24] + 1ba7c: fbe3 450a umlal r4, r5, r3, sl + 1ba80: fbe6 450e umlal r4, r5, r6, lr + 1ba84: fbe7 450c umlal r4, r5, r7, ip + 1ba88: ea4f 6398 mov.w r3, r8, lsr #26 + 1ba8c: ea43 1389 orr.w r3, r3, r9, lsl #6 + 1ba90: 18e6 adds r6, r4, r3 + 1ba92: e9cd 8918 strd r8, r9, [sp, #96] ; 0x60 + 1ba96: f145 0700 adc.w r7, r5, #0 + 1ba9a: f8dd 8008 ldr.w r8, [sp, #8] + 1ba9e: 0eb5 lsrs r5, r6, #26 + 1baa0: 9c00 ldr r4, [sp, #0] + 1baa2: ea45 1587 orr.w r5, r5, r7, lsl #6 + 1baa6: f028 437c bic.w r3, r8, #4227858432 ; 0xfc000000 + 1baaa: eb05 0585 add.w r5, r5, r5, lsl #2 + 1baae: 18eb adds r3, r5, r3 + 1bab0: f024 447c bic.w r4, r4, #4227858432 ; 0xfc000000 + 1bab4: 940f str r4, [sp, #60] ; 0x3c + 1bab6: 9302 str r3, [sp, #8] + 1bab8: f8dd 8058 ldr.w r8, [sp, #88] ; 0x58 + 1babc: f8dd 9060 ldr.w r9, [sp, #96] ; 0x60 + 1bac0: 9b0f ldr r3, [sp, #60] ; 0x3c + 1bac2: 9d02 ldr r5, [sp, #8] + 1bac4: f028 4b7c bic.w fp, r8, #4227858432 ; 0xfc000000 + 1bac8: f029 447c bic.w r4, r9, #4227858432 ; 0xfc000000 + 1bacc: f026 4e7c bic.w lr, r6, #4227858432 ; 0xfc000000 + 1bad0: 2a0f cmp r2, #15 + 1bad2: 6283 str r3, [r0, #40] ; 0x28 + 1bad4: f8c0 b02c str.w fp, [r0, #44] ; 0x2c + 1bad8: 6304 str r4, [r0, #48] ; 0x30 + 1bada: 6245 str r5, [r0, #36] ; 0x24 + 1badc: f8c0 e034 str.w lr, [r0, #52] ; 0x34 + 1bae0: f63f aef7 bhi.w 1b8d2 + 1bae4: 2a00 cmp r2, #0 + 1bae6: f000 8099 beq.w 1bc1c + 1baea: 2300 movs r3, #0 + 1baec: 5ccc ldrb r4, [r1, r3] + 1baee: ae20 add r6, sp, #128 ; 0x80 + 1baf0: 54f4 strb r4, [r6, r3] + 1baf2: 3301 adds r3, #1 + 1baf4: 4293 cmp r3, r2 + 1baf6: d1f9 bne.n 1baec + 1baf8: 2501 movs r5, #1 + 1bafa: 195a adds r2, r3, r5 + 1bafc: ac24 add r4, sp, #144 ; 0x90 + 1bafe: 2a0f cmp r2, #15 + 1bb00: 441c add r4, r3 + 1bb02: f804 5c10 strb.w r5, [r4, #-16] + 1bb06: bf9f itttt ls + 1bb08: ad20 addls r5, sp, #128 ; 0x80 + 1bb0a: 195b addls r3, r3, r5 + 1bb0c: f10d 048f addls.w r4, sp, #143 ; 0x8f + 1bb10: 2200 movls r2, #0 + 1bb12: d803 bhi.n 1bb1c + 1bb14: f803 2f01 strb.w r2, [r3, #1]! + 1bb18: 42a3 cmp r3, r4 + 1bb1a: d1fb bne.n 1bb14 + 1bb1c: f89d 408e ldrb.w r4, [sp, #142] ; 0x8e + 1bb20: f89d 3086 ldrb.w r3, [sp, #134] ; 0x86 + 1bb24: f89d c08d ldrb.w ip, [sp, #141] ; 0x8d + 1bb28: f89d 608c ldrb.w r6, [sp, #140] ; 0x8c + 1bb2c: f89d 2085 ldrb.w r2, [sp, #133] ; 0x85 + 1bb30: f89d 508a ldrb.w r5, [sp, #138] ; 0x8a + 1bb34: 0424 lsls r4, r4, #16 + 1bb36: 041b lsls r3, r3, #16 + 1bb38: f89d 7089 ldrb.w r7, [sp, #137] ; 0x89 + 1bb3c: ea44 2c0c orr.w ip, r4, ip, lsl #8 + 1bb40: f89d 408f ldrb.w r4, [sp, #143] ; 0x8f + 1bb44: ea43 2202 orr.w r2, r3, r2, lsl #8 + 1bb48: 042d lsls r5, r5, #16 + 1bb4a: f89d 3088 ldrb.w r3, [sp, #136] ; 0x88 + 1bb4e: ea4c 0c06 orr.w ip, ip, r6 + 1bb52: ea45 2707 orr.w r7, r5, r7, lsl #8 + 1bb56: ea4c 6c04 orr.w ip, ip, r4, lsl #24 + 1bb5a: f89d 508b ldrb.w r5, [sp, #139] ; 0x8b + 1bb5e: f89d 4082 ldrb.w r4, [sp, #130] ; 0x82 + 1bb62: f89d 6081 ldrb.w r6, [sp, #129] ; 0x81 + 1bb66: f89d 8084 ldrb.w r8, [sp, #132] ; 0x84 + 1bb6a: 433b orrs r3, r7 + 1bb6c: ea43 6305 orr.w r3, r3, r5, lsl #24 + 1bb70: f89d e087 ldrb.w lr, [sp, #135] ; 0x87 + 1bb74: f89d 5080 ldrb.w r5, [sp, #128] ; 0x80 + 1bb78: 0424 lsls r4, r4, #16 + 1bb7a: 2700 movs r7, #0 + 1bb7c: ea44 2406 orr.w r4, r4, r6, lsl #8 + 1bb80: f89d b083 ldrb.w fp, [sp, #131] ; 0x83 + 1bb84: ea42 0208 orr.w r2, r2, r8 + 1bb88: ea42 620e orr.w r2, r2, lr, lsl #24 + 1bb8c: 931d str r3, [sp, #116] ; 0x74 + 1bb8e: f8cd c07c str.w ip, [sp, #124] ; 0x7c + 1bb92: 971e str r7, [sp, #120] ; 0x78 + 1bb94: 971c str r7, [sp, #112] ; 0x70 + 1bb96: 432c orrs r4, r5 + 1bb98: 970c str r7, [sp, #48] ; 0x30 + 1bb9a: ea44 6b0b orr.w fp, r4, fp, lsl #24 + 1bb9e: 920d str r2, [sp, #52] ; 0x34 + 1bba0: e9dd 671c ldrd r6, r7, [sp, #112] ; 0x70 + 1bba4: e9dd 451e ldrd r4, r5, [sp, #120] ; 0x78 + 1bba8: ea46 0602 orr.w r6, r6, r2 + 1bbac: ea44 0403 orr.w r4, r4, r3 + 1bbb0: ea4f 5a16 mov.w sl, r6, lsr #20 + 1bbb4: e9dd 230c ldrd r2, r3, [sp, #48] ; 0x30 + 1bbb8: ea4f 3e94 mov.w lr, r4, lsr #14 + 1bbbc: ea42 020b orr.w r2, r2, fp + 1bbc0: 0e96 lsrs r6, r2, #26 + 1bbc2: ea4a 3a07 orr.w sl, sl, r7, lsl #12 + 1bbc6: ea4e 4e85 orr.w lr, lr, r5, lsl #18 + 1bbca: 6b47 ldr r7, [r0, #52] ; 0x34 + 1bbcc: 6b05 ldr r5, [r0, #48] ; 0x30 + 1bbce: ea46 1683 orr.w r6, r6, r3, lsl #6 + 1bbd2: f02e 4e7c bic.w lr, lr, #4227858432 ; 0xfc000000 + 1bbd6: 6804 ldr r4, [r0, #0] + 1bbd8: f026 437c bic.w r3, r6, #4227858432 ; 0xfc000000 + 1bbdc: eb07 2c1c add.w ip, r7, ip, lsr #8 + 1bbe0: 6ac6 ldr r6, [r0, #44] ; 0x2c + 1bbe2: 6a47 ldr r7, [r0, #36] ; 0x24 + 1bbe4: 44ae add lr, r5 + 1bbe6: 6a05 ldr r5, [r0, #32] + 1bbe8: f02a 4a7c bic.w sl, sl, #4227858432 ; 0xfc000000 + 1bbec: f02b 4b7c bic.w fp, fp, #4227858432 ; 0xfc000000 + 1bbf0: 6a82 ldr r2, [r0, #40] ; 0x28 + 1bbf2: 9406 str r4, [sp, #24] + 1bbf4: 44b2 add sl, r6 + 1bbf6: 9507 str r5, [sp, #28] + 1bbf8: 44bb add fp, r7 + 1bbfa: 69c6 ldr r6, [r0, #28] + 1bbfc: 6987 ldr r7, [r0, #24] + 1bbfe: 6944 ldr r4, [r0, #20] + 1bc00: 9610 str r6, [sp, #64] ; 0x40 + 1bc02: 9714 str r7, [sp, #80] ; 0x50 + 1bc04: 941a str r4, [sp, #104] ; 0x68 + 1bc06: 6845 ldr r5, [r0, #4] + 1bc08: 6886 ldr r6, [r0, #8] + 1bc0a: 68c7 ldr r7, [r0, #12] + 1bc0c: 6904 ldr r4, [r0, #16] + 1bc0e: 4413 add r3, r2 + 1bc10: 950e str r5, [sp, #56] ; 0x38 + 1bc12: 2200 movs r2, #0 + 1bc14: 9611 str r6, [sp, #68] ; 0x44 + 1bc16: 9715 str r7, [sp, #84] ; 0x54 + 1bc18: 941b str r4, [sp, #108] ; 0x6c + 1bc1a: e6bf b.n 1b99c + 1bc1c: b025 add sp, #148 ; 0x94 + 1bc1e: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 1bc22: bf00 nop + +0001bc24 : + 1bc24: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 1bc28: 798d ldrb r5, [r1, #6] + 1bc2a: 7a8c ldrb r4, [r1, #10] + 1bc2c: 7b8a ldrb r2, [r1, #14] + 1bc2e: f891 c005 ldrb.w ip, [r1, #5] + 1bc32: f891 e009 ldrb.w lr, [r1, #9] + 1bc36: 7b4f ldrb r7, [r1, #13] + 1bc38: 788b ldrb r3, [r1, #2] + 1bc3a: f891 b001 ldrb.w fp, [r1, #1] + 1bc3e: 790e ldrb r6, [r1, #4] + 1bc40: f891 a008 ldrb.w sl, [r1, #8] + 1bc44: f891 900c ldrb.w r9, [r1, #12] + 1bc48: 042d lsls r5, r5, #16 + 1bc4a: 0424 lsls r4, r4, #16 + 1bc4c: 0412 lsls r2, r2, #16 + 1bc4e: f891 8000 ldrb.w r8, [r1] + 1bc52: ea45 250c orr.w r5, r5, ip, lsl #8 + 1bc56: ea44 240e orr.w r4, r4, lr, lsl #8 + 1bc5a: f891 c007 ldrb.w ip, [r1, #7] + 1bc5e: f891 e00b ldrb.w lr, [r1, #11] + 1bc62: ea42 2207 orr.w r2, r2, r7, lsl #8 + 1bc66: 041b lsls r3, r3, #16 + 1bc68: 7bcf ldrb r7, [r1, #15] + 1bc6a: ea43 230b orr.w r3, r3, fp, lsl #8 + 1bc6e: 4335 orrs r5, r6 + 1bc70: ea44 040a orr.w r4, r4, sl + 1bc74: 78ce ldrb r6, [r1, #3] + 1bc76: ea42 0209 orr.w r2, r2, r9 + 1bc7a: ea45 650c orr.w r5, r5, ip, lsl #24 + 1bc7e: ea43 0308 orr.w r3, r3, r8 + 1bc82: ea44 640e orr.w r4, r4, lr, lsl #24 + 1bc86: ea42 6207 orr.w r2, r2, r7, lsl #24 + 1bc8a: ea43 6306 orr.w r3, r3, r6, lsl #24 + 1bc8e: ea4f 3e04 mov.w lr, r4, lsl #12 + 1bc92: 0497 lsls r7, r2, #18 + 1bc94: 01ae lsls r6, r5, #6 + 1bc96: ea46 6693 orr.w r6, r6, r3, lsr #26 + 1bc9a: ea4e 5515 orr.w r5, lr, r5, lsr #20 + 1bc9e: ea47 3494 orr.w r4, r7, r4, lsr #14 + 1bca2: f026 467c bic.w r6, r6, #4227858432 ; 0xfc000000 + 1bca6: f025 457c bic.w r5, r5, #4227858432 ; 0xfc000000 + 1bcaa: f024 447c bic.w r4, r4, #4227858432 ; 0xfc000000 + 1bcae: f026 06fc bic.w r6, r6, #252 ; 0xfc + 1bcb2: f425 557c bic.w r5, r5, #16128 ; 0x3f00 + 1bcb6: f424 247c bic.w r4, r4, #1032192 ; 0xfc000 + 1bcba: f3c2 2213 ubfx r2, r2, #8, #20 + 1bcbe: f023 497c bic.w r9, r3, #4227858432 ; 0xfc000000 + 1bcc2: eb02 0782 add.w r7, r2, r2, lsl #2 + 1bcc6: 2300 movs r3, #0 + 1bcc8: eb06 0886 add.w r8, r6, r6, lsl #2 + 1bccc: eb05 0c85 add.w ip, r5, r5, lsl #2 + 1bcd0: eb04 0e84 add.w lr, r4, r4, lsl #2 + 1bcd4: f8c0 9000 str.w r9, [r0] + 1bcd8: 6046 str r6, [r0, #4] + 1bcda: f8c0 8014 str.w r8, [r0, #20] + 1bcde: 6085 str r5, [r0, #8] + 1bce0: 60c4 str r4, [r0, #12] + 1bce2: f8c0 e01c str.w lr, [r0, #28] + 1bce6: 6102 str r2, [r0, #16] + 1bce8: 6207 str r7, [r0, #32] + 1bcea: f8c0 c018 str.w ip, [r0, #24] + 1bcee: 6243 str r3, [r0, #36] ; 0x24 + 1bcf0: 6283 str r3, [r0, #40] ; 0x28 + 1bcf2: 62c3 str r3, [r0, #44] ; 0x2c + 1bcf4: 6303 str r3, [r0, #48] ; 0x30 + 1bcf6: 6343 str r3, [r0, #52] ; 0x34 + 1bcf8: 6483 str r3, [r0, #72] ; 0x48 + 1bcfa: 3110 adds r1, #16 + 1bcfc: 304c adds r0, #76 ; 0x4c + 1bcfe: 2210 movs r2, #16 + 1bd00: e8bd 4ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 1bd04: f7f3 bbae b.w f464 <_memcpy> + +0001bd08 : + 1bd08: b5f8 push {r3, r4, r5, r6, r7, lr} + 1bd0a: f8d0 e048 ldr.w lr, [r0, #72] ; 0x48 + 1bd0e: 4607 mov r7, r0 + 1bd10: 460c mov r4, r1 + 1bd12: 4616 mov r6, r2 + 1bd14: f1be 0f00 cmp.w lr, #0 + 1bd18: d017 beq.n 1bd4a + 1bd1a: f1ce 0010 rsb r0, lr, #16 + 1bd1e: 4290 cmp r0, r2 + 1bd20: bf28 it cs + 1bd22: 4610 movcs r0, r2 + 1bd24: 2300 movs r3, #0 + 1bd26: eb07 020e add.w r2, r7, lr + 1bd2a: b130 cbz r0, 1bd3a + 1bd2c: 5ce5 ldrb r5, [r4, r3] + 1bd2e: 18d1 adds r1, r2, r3 + 1bd30: 3301 adds r3, #1 + 1bd32: 4283 cmp r3, r0 + 1bd34: f881 5038 strb.w r5, [r1, #56] ; 0x38 + 1bd38: d1f8 bne.n 1bd2c + 1bd3a: eb00 020e add.w r2, r0, lr + 1bd3e: 2a10 cmp r2, #16 + 1bd40: 64ba str r2, [r7, #72] ; 0x48 + 1bd42: eba6 0600 sub.w r6, r6, r0 + 1bd46: 4404 add r4, r0 + 1bd48: d017 beq.n 1bd7a + 1bd4a: 2e0f cmp r6, #15 + 1bd4c: d80a bhi.n 1bd64 + 1bd4e: b146 cbz r6, 1bd62 + 1bd50: 2300 movs r3, #0 + 1bd52: 5ce5 ldrb r5, [r4, r3] + 1bd54: 18f9 adds r1, r7, r3 + 1bd56: 3301 adds r3, #1 + 1bd58: 42b3 cmp r3, r6 + 1bd5a: f881 5038 strb.w r5, [r1, #56] ; 0x38 + 1bd5e: d1f8 bne.n 1bd52 + 1bd60: 64bb str r3, [r7, #72] ; 0x48 + 1bd62: bdf8 pop {r3, r4, r5, r6, r7, pc} + 1bd64: f026 050f bic.w r5, r6, #15 + 1bd68: 4621 mov r1, r4 + 1bd6a: 462a mov r2, r5 + 1bd6c: 4638 mov r0, r7 + 1bd6e: f7ff fd8f bl 1b890 + 1bd72: f006 060f and.w r6, r6, #15 + 1bd76: 442c add r4, r5 + 1bd78: e7e9 b.n 1bd4e + 1bd7a: 4638 mov r0, r7 + 1bd7c: f107 0138 add.w r1, r7, #56 ; 0x38 + 1bd80: f7ff fd86 bl 1b890 + 1bd84: 2300 movs r3, #0 + 1bd86: 64bb str r3, [r7, #72] ; 0x48 + 1bd88: e7df b.n 1bd4a + 1bd8a: bf00 nop + +0001bd8c : + 1bd8c: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 1bd90: 6c82 ldr r2, [r0, #72] ; 0x48 + 1bd92: b089 sub sp, #36 ; 0x24 + 1bd94: 4680 mov r8, r0 + 1bd96: 4689 mov r9, r1 + 1bd98: b11a cbz r2, 1bda2 + 1bd9a: f100 0138 add.w r1, r0, #56 ; 0x38 + 1bd9e: f7ff fd77 bl 1b890 + 1bda2: f8d8 5024 ldr.w r5, [r8, #36] ; 0x24 + 1bda6: f8d8 4028 ldr.w r4, [r8, #40] ; 0x28 + 1bdaa: f8d8 202c ldr.w r2, [r8, #44] ; 0x2c + 1bdae: f8d8 1030 ldr.w r1, [r8, #48] ; 0x30 + 1bdb2: eb04 6495 add.w r4, r4, r5, lsr #26 + 1bdb6: eb02 6294 add.w r2, r2, r4, lsr #26 + 1bdba: f8d8 7034 ldr.w r7, [r8, #52] ; 0x34 + 1bdbe: eb01 6c92 add.w ip, r1, r2, lsr #26 + 1bdc2: eb07 679c add.w r7, r7, ip, lsr #26 + 1bdc6: 0ebb lsrs r3, r7, #26 + 1bdc8: eb03 0383 add.w r3, r3, r3, lsl #2 + 1bdcc: f025 457c bic.w r5, r5, #4227858432 ; 0xfc000000 + 1bdd0: 441d add r5, r3 + 1bdd2: 1d6b adds r3, r5, #5 + 1bdd4: f024 447c bic.w r4, r4, #4227858432 ; 0xfc000000 + 1bdd8: eb04 6e93 add.w lr, r4, r3, lsr #26 + 1bddc: f027 477c bic.w r7, r7, #4227858432 ; 0xfc000000 + 1bde0: f898 a04e ldrb.w sl, [r8, #78] ; 0x4e + 1bde4: f022 427c bic.w r2, r2, #4227858432 ; 0xfc000000 + 1bde8: 9706 str r7, [sp, #24] + 1bdea: eb02 609e add.w r0, r2, lr, lsr #26 + 1bdee: f02c 4c7c bic.w ip, ip, #4227858432 ; 0xfc000000 + 1bdf2: f107 467c add.w r6, r7, #4227858432 ; 0xfc000000 + 1bdf6: f898 704d ldrb.w r7, [r8, #77] ; 0x4d + 1bdfa: eb0c 6190 add.w r1, ip, r0, lsr #26 + 1bdfe: ea4f 4a0a mov.w sl, sl, lsl #16 + 1be02: eb06 6691 add.w r6, r6, r1, lsr #26 + 1be06: ea4a 2a07 orr.w sl, sl, r7, lsl #8 + 1be0a: f898 704c ldrb.w r7, [r8, #76] ; 0x4c + 1be0e: 9607 str r6, [sp, #28] + 1be10: f898 b04f ldrb.w fp, [r8, #79] ; 0x4f + 1be14: 0ff6 lsrs r6, r6, #31 + 1be16: 3e01 subs r6, #1 + 1be18: ea4a 0a07 orr.w sl, sl, r7 + 1be1c: f023 437c bic.w r3, r3, #4227858432 ; 0xfc000000 + 1be20: 43f7 mvns r7, r6 + 1be22: 9601 str r6, [sp, #4] + 1be24: 4033 ands r3, r6 + 1be26: ea4a 660b orr.w r6, sl, fp, lsl #24 + 1be2a: 46b2 mov sl, r6 + 1be2c: f04f 0b00 mov.w fp, #0 + 1be30: e9cd ab02 strd sl, fp, [sp, #8] + 1be34: f8dd b004 ldr.w fp, [sp, #4] + 1be38: 403d ands r5, r7 + 1be3a: 432b orrs r3, r5 + 1be3c: 465d mov r5, fp + 1be3e: f02e 4e7c bic.w lr, lr, #4227858432 ; 0xfc000000 + 1be42: 403c ands r4, r7 + 1be44: ea0e 0e0b and.w lr, lr, fp + 1be48: ea44 0e0e orr.w lr, r4, lr + 1be4c: f898 4052 ldrb.w r4, [r8, #82] ; 0x52 + 1be50: f8c8 3024 str.w r3, [r8, #36] ; 0x24 + 1be54: f898 3051 ldrb.w r3, [r8, #81] ; 0x51 + 1be58: 0424 lsls r4, r4, #16 + 1be5a: ea44 2403 orr.w r4, r4, r3, lsl #8 + 1be5e: f898 3050 ldrb.w r3, [r8, #80] ; 0x50 + 1be62: f8d8 6024 ldr.w r6, [r8, #36] ; 0x24 + 1be66: 431c orrs r4, r3 + 1be68: f898 3053 ldrb.w r3, [r8, #83] ; 0x53 + 1be6c: f020 407c bic.w r0, r0, #4227858432 ; 0xfc000000 + 1be70: 403a ands r2, r7 + 1be72: 4028 ands r0, r5 + 1be74: ea44 6403 orr.w r4, r4, r3, lsl #24 + 1be78: ea46 638e orr.w r3, r6, lr, lsl #26 + 1be7c: e9dd ab02 ldrd sl, fp, [sp, #8] + 1be80: 4310 orrs r0, r2 + 1be82: eb1a 0a03 adds.w sl, sl, r3 + 1be86: ea4f 139e mov.w r3, lr, lsr #6 + 1be8a: f14b 0b00 adc.w fp, fp, #0 + 1be8e: ea43 5300 orr.w r3, r3, r0, lsl #20 + 1be92: 2600 movs r6, #0 + 1be94: 9605 str r6, [sp, #20] + 1be96: f8cd b010 str.w fp, [sp, #16] + 1be9a: 18e4 adds r4, r4, r3 + 1be9c: f04f 0500 mov.w r5, #0 + 1bea0: e9cd ab02 strd sl, fp, [sp, #8] + 1bea4: e9dd ab04 ldrd sl, fp, [sp, #16] + 1bea8: f145 0500 adc.w r5, r5, #0 + 1beac: eb14 040a adds.w r4, r4, sl + 1beb0: eb45 050b adc.w r5, r5, fp + 1beb4: 46aa mov sl, r5 + 1beb6: 46b3 mov fp, r6 + 1beb8: f898 2056 ldrb.w r2, [r8, #86] ; 0x56 + 1bebc: f898 3055 ldrb.w r3, [r8, #85] ; 0x55 + 1bec0: 0412 lsls r2, r2, #16 + 1bec2: f8c8 002c str.w r0, [r8, #44] ; 0x2c + 1bec6: ea42 2203 orr.w r2, r2, r3, lsl #8 + 1beca: 9801 ldr r0, [sp, #4] + 1becc: f898 3054 ldrb.w r3, [r8, #84] ; 0x54 + 1bed0: f8d8 602c ldr.w r6, [r8, #44] ; 0x2c + 1bed4: f021 417c bic.w r1, r1, #4227858432 ; 0xfc000000 + 1bed8: ea07 0c0c and.w ip, r7, ip + 1bedc: 4001 ands r1, r0 + 1bede: 431a orrs r2, r3 + 1bee0: f898 3057 ldrb.w r3, [r8, #87] ; 0x57 + 1bee4: ea4c 0101 orr.w r1, ip, r1 + 1bee8: 0b35 lsrs r5, r6, #12 + 1beea: ea45 3581 orr.w r5, r5, r1, lsl #14 + 1beee: ea42 6203 orr.w r2, r2, r3, lsl #24 + 1bef2: 1952 adds r2, r2, r5 + 1bef4: f04f 0300 mov.w r3, #0 + 1bef8: f143 0300 adc.w r3, r3, #0 + 1befc: eb12 020a adds.w r2, r2, sl + 1bf00: eb43 030b adc.w r3, r3, fp + 1bf04: 469a mov sl, r3 + 1bf06: 4603 mov r3, r0 + 1bf08: f898 c05a ldrb.w ip, [r8, #90] ; 0x5a + 1bf0c: f898 5059 ldrb.w r5, [r8, #89] ; 0x59 + 1bf10: 9e06 ldr r6, [sp, #24] + 1bf12: ea4f 4c0c mov.w ip, ip, lsl #16 + 1bf16: 9807 ldr r0, [sp, #28] + 1bf18: ea4c 2c05 orr.w ip, ip, r5, lsl #8 + 1bf1c: f898 5058 ldrb.w r5, [r8, #88] ; 0x58 + 1bf20: 4037 ands r7, r6 + 1bf22: f898 605b ldrb.w r6, [r8, #91] ; 0x5b + 1bf26: ea4c 0505 orr.w r5, ip, r5 + 1bf2a: 4003 ands r3, r0 + 1bf2c: 433b orrs r3, r7 + 1bf2e: ea45 6606 orr.w r6, r5, r6, lsl #24 + 1bf32: 0c8d lsrs r5, r1, #18 + 1bf34: ea45 2503 orr.w r5, r5, r3, lsl #8 + 1bf38: 1976 adds r6, r6, r5 + 1bf3a: f8c8 e028 str.w lr, [r8, #40] ; 0x28 + 1bf3e: eb16 060a adds.w r6, r6, sl + 1bf42: f8dd a008 ldr.w sl, [sp, #8] + 1bf46: f89d 0008 ldrb.w r0, [sp, #8] + 1bf4a: f8c8 1030 str.w r1, [r8, #48] ; 0x30 + 1bf4e: f8c8 3034 str.w r3, [r8, #52] ; 0x34 + 1bf52: ea4f 2c14 mov.w ip, r4, lsr #8 + 1bf56: 0c21 lsrs r1, r4, #16 + 1bf58: ea4f 231a mov.w r3, sl, lsr #8 + 1bf5c: 0e27 lsrs r7, r4, #24 + 1bf5e: 0a35 lsrs r5, r6, #8 + 1bf60: f889 4004 strb.w r4, [r9, #4] + 1bf64: ea4f 4e1a mov.w lr, sl, lsr #16 + 1bf68: ea4f 641a mov.w r4, sl, lsr #24 + 1bf6c: f889 0000 strb.w r0, [r9] + 1bf70: ea4f 4816 mov.w r8, r6, lsr #16 + 1bf74: 0e30 lsrs r0, r6, #24 + 1bf76: f889 c005 strb.w ip, [r9, #5] + 1bf7a: f889 1006 strb.w r1, [r9, #6] + 1bf7e: ea4f 2c12 mov.w ip, r2, lsr #8 + 1bf82: 0c11 lsrs r1, r2, #16 + 1bf84: f889 3001 strb.w r3, [r9, #1] + 1bf88: 0e13 lsrs r3, r2, #24 + 1bf8a: f889 e002 strb.w lr, [r9, #2] + 1bf8e: f889 4003 strb.w r4, [r9, #3] + 1bf92: f889 7007 strb.w r7, [r9, #7] + 1bf96: f889 500d strb.w r5, [r9, #13] + 1bf9a: f889 600c strb.w r6, [r9, #12] + 1bf9e: f889 2008 strb.w r2, [r9, #8] + 1bfa2: f889 800e strb.w r8, [r9, #14] + 1bfa6: f889 000f strb.w r0, [r9, #15] + 1bfaa: f889 c009 strb.w ip, [r9, #9] + 1bfae: f889 100a strb.w r1, [r9, #10] + 1bfb2: f889 300b strb.w r3, [r9, #11] + 1bfb6: b009 add sp, #36 ; 0x24 + 1bfb8: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 1bfbc: 0000 movs r0, r0 + ... + +0001bfc0 : + 1bfc0: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 1bfc4: 460f mov r7, r1 + 1bfc6: f2ad 4db4 subw sp, sp, #1204 ; 0x4b4 + 1bfca: 907d str r0, [sp, #500] ; 0x1f4 + 1bfcc: ae8a add r6, sp, #552 ; 0x228 + 1bfce: f04f 0800 mov.w r8, #0 + 1bfd2: eb07 0ec8 add.w lr, r7, r8, lsl #3 + 1bfd6: f817 0038 ldrb.w r0, [r7, r8, lsl #3] + 1bfda: f89e 2001 ldrb.w r2, [lr, #1] + 1bfde: f04f 0a00 mov.w sl, #0 + 1bfe2: ea4f 6b00 mov.w fp, r0, lsl #24 + 1bfe6: f89e 4007 ldrb.w r4, [lr, #7] + 1bfea: 0410 lsls r0, r2, #16 + 1bfec: 2500 movs r5, #0 + 1bfee: f89e 2002 ldrb.w r2, [lr, #2] + 1bff2: 9017 str r0, [sp, #92] ; 0x5c + 1bff4: f8cd a058 str.w sl, [sp, #88] ; 0x58 + 1bff8: ea45 050b orr.w r5, r5, fp + 1bffc: 0211 lsls r1, r2, #8 + 1bffe: ea44 040a orr.w r4, r4, sl + 1c002: e9dd 2316 ldrd r2, r3, [sp, #88] ; 0x58 + 1c006: 431d orrs r5, r3 + 1c008: f89e 3003 ldrb.w r3, [lr, #3] + 1c00c: 9119 str r1, [sp, #100] ; 0x64 + 1c00e: 4314 orrs r4, r2 + 1c010: f8cd a060 str.w sl, [sp, #96] ; 0x60 + 1c014: 931b str r3, [sp, #108] ; 0x6c + 1c016: e9dd 2318 ldrd r2, r3, [sp, #96] ; 0x60 + 1c01a: 4314 orrs r4, r2 + 1c01c: f89e 2004 ldrb.w r2, [lr, #4] + 1c020: 431d orrs r5, r3 + 1c022: f8cd a068 str.w sl, [sp, #104] ; 0x68 + 1c026: e9dd 011a ldrd r0, r1, [sp, #104] ; 0x68 + 1c02a: ea4f 6902 mov.w r9, r2, lsl #24 + 1c02e: 4304 orrs r4, r0 + 1c030: 430d orrs r5, r1 + 1c032: f89e 0005 ldrb.w r0, [lr, #5] + 1c036: 0a11 lsrs r1, r2, #8 + 1c038: 9109 str r1, [sp, #36] ; 0x24 + 1c03a: f8cd 9020 str.w r9, [sp, #32] + 1c03e: e9dd 2308 ldrd r2, r3, [sp, #32] + 1c042: ea4f 4900 mov.w r9, r0, lsl #16 + 1c046: 4314 orrs r4, r2 + 1c048: 431d orrs r5, r3 + 1c04a: f89e 2006 ldrb.w r2, [lr, #6] + 1c04e: 0c03 lsrs r3, r0, #16 + 1c050: 9311 str r3, [sp, #68] ; 0x44 + 1c052: f8cd 9040 str.w r9, [sp, #64] ; 0x40 + 1c056: e9dd 0110 ldrd r0, r1, [sp, #64] ; 0x40 + 1c05a: ea4f 2902 mov.w r9, r2, lsl #8 + 1c05e: 430d orrs r5, r1 + 1c060: 0e11 lsrs r1, r2, #24 + 1c062: 4304 orrs r4, r0 + 1c064: 9115 str r1, [sp, #84] ; 0x54 + 1c066: f8cd 9050 str.w r9, [sp, #80] ; 0x50 + 1c06a: f108 0801 add.w r8, r8, #1 + 1c06e: e9dd 2314 ldrd r2, r3, [sp, #80] ; 0x50 + 1c072: f1b8 0f10 cmp.w r8, #16 + 1c076: ea44 0402 orr.w r4, r4, r2 + 1c07a: ea45 0503 orr.w r5, r5, r3 + 1c07e: e9e6 4502 strd r4, r5, [r6, #8]! + 1c082: d1a6 bne.n 1bfd2 + 1c084: f50d 7b0a add.w fp, sp, #552 ; 0x228 + 1c088: f50d 7a1c add.w sl, sp, #624 ; 0x270 + 1c08c: f50d 7c26 add.w ip, sp, #664 ; 0x298 + 1c090: f50d 7e0c add.w lr, sp, #560 ; 0x230 + 1c094: f50d 792a add.w r9, sp, #680 ; 0x2a8 + 1c098: f8cd b020 str.w fp, [sp, #32] + 1c09c: f8cd a040 str.w sl, [sp, #64] ; 0x40 + 1c0a0: f85c 4f08 ldr.w r4, [ip, #8]! + 1c0a4: 9d08 ldr r5, [sp, #32] + 1c0a6: f8dc 6004 ldr.w r6, [ip, #4] + 1c0aa: 00e0 lsls r0, r4, #3 + 1c0ac: 0ce1 lsrs r1, r4, #19 + 1c0ae: ea40 7056 orr.w r0, r0, r6, lsr #29 + 1c0b2: ea41 3146 orr.w r1, r1, r6, lsl #13 + 1c0b6: 9012 str r0, [sp, #72] ; 0x48 + 1c0b8: 910e str r1, [sp, #56] ; 0x38 + 1c0ba: 00f0 lsls r0, r6, #3 + 1c0bc: 0cf1 lsrs r1, r6, #19 + 1c0be: e9f5 2302 ldrd r2, r3, [r5, #8]! + 1c0c2: ea40 7054 orr.w r0, r0, r4, lsr #29 + 1c0c6: ea41 3144 orr.w r1, r1, r4, lsl #13 + 1c0ca: 9508 str r5, [sp, #32] + 1c0cc: f85e 5f08 ldr.w r5, [lr, #8]! + 1c0d0: 910f str r1, [sp, #60] ; 0x3c + 1c0d2: 9013 str r0, [sp, #76] ; 0x4c + 1c0d4: e9dd ab0e ldrd sl, fp, [sp, #56] ; 0x38 + 1c0d8: e9dd 0112 ldrd r0, r1, [sp, #72] ; 0x48 + 1c0dc: ea80 000a eor.w r0, r0, sl + 1c0e0: ea4f 1a94 mov.w sl, r4, lsr #6 + 1c0e4: f8de 4004 ldr.w r4, [lr, #4] + 1c0e8: ea81 010b eor.w r1, r1, fp + 1c0ec: ea4a 6a86 orr.w sl, sl, r6, lsl #26 + 1c0f0: ea4f 1b96 mov.w fp, r6, lsr #6 + 1c0f4: 0a2e lsrs r6, r5, #8 + 1c0f6: ea46 6604 orr.w r6, r6, r4, lsl #24 + 1c0fa: 960a str r6, [sp, #40] ; 0x28 + 1c0fc: 086e lsrs r6, r5, #1 + 1c0fe: ea46 76c4 orr.w r6, r6, r4, lsl #31 + 1c102: ea81 070b eor.w r7, r1, fp + 1c106: 960c str r6, [sp, #48] ; 0x30 + 1c108: ea80 060a eor.w r6, r0, sl + 1c10c: e9cd 6714 strd r6, r7, [sp, #80] ; 0x50 + 1c110: 9e10 ldr r6, [sp, #64] ; 0x40 + 1c112: f108 0801 add.w r8, r8, #1 + 1c116: e9f6 0102 ldrd r0, r1, [r6, #8]! + 1c11a: 1880 adds r0, r0, r2 + 1c11c: 4159 adcs r1, r3 + 1c11e: 0a23 lsrs r3, r4, #8 + 1c120: ea43 6305 orr.w r3, r3, r5, lsl #24 + 1c124: 930b str r3, [sp, #44] ; 0x2c + 1c126: 0863 lsrs r3, r4, #1 + 1c128: ea43 73c5 orr.w r3, r3, r5, lsl #31 + 1c12c: 930d str r3, [sp, #52] ; 0x34 + 1c12e: 09ed lsrs r5, r5, #7 + 1c130: e9dd 230a ldrd r2, r3, [sp, #40] ; 0x28 + 1c134: 9610 str r6, [sp, #64] ; 0x40 + 1c136: e9dd 670c ldrd r6, r7, [sp, #48] ; 0x30 + 1c13a: 407b eors r3, r7 + 1c13c: ea45 6744 orr.w r7, r5, r4, lsl #25 + 1c140: 09e4 lsrs r4, r4, #7 + 1c142: 4072 eors r2, r6 + 1c144: 9407 str r4, [sp, #28] + 1c146: 9706 str r7, [sp, #24] + 1c148: e9dd 4514 ldrd r4, r5, [sp, #80] ; 0x50 + 1c14c: e9dd 6706 ldrd r6, r7, [sp, #24] + 1c150: 1900 adds r0, r0, r4 + 1c152: ea82 0206 eor.w r2, r2, r6 + 1c156: 4169 adcs r1, r5 + 1c158: 407b eors r3, r7 + 1c15a: 1812 adds r2, r2, r0 + 1c15c: 414b adcs r3, r1 + 1c15e: f1b8 0f50 cmp.w r8, #80 ; 0x50 + 1c162: e9e9 2302 strd r2, r3, [r9, #8]! + 1c166: d19b bne.n 1c0a0 + 1c168: 987d ldr r0, [sp, #500] ; 0x1f4 + 1c16a: aa80 add r2, sp, #512 ; 0x200 + 1c16c: f100 0120 add.w r1, r0, #32 + 1c170: e9d1 0100 ldrd r0, r1, [r1] + 1c174: e9c2 0100 strd r0, r1, [r2] + 1c178: 9a7d ldr r2, [sp, #500] ; 0x1f4 + 1c17a: ac82 add r4, sp, #520 ; 0x208 + 1c17c: f102 0328 add.w r3, r2, #40 ; 0x28 + 1c180: e9d3 2300 ldrd r2, r3, [r3] + 1c184: e9c4 2300 strd r2, r3, [r4] + 1c188: 9c7d ldr r4, [sp, #500] ; 0x1f4 + 1c18a: f8dd a1f4 ldr.w sl, [sp, #500] ; 0x1f4 + 1c18e: ae84 add r6, sp, #528 ; 0x210 + 1c190: f104 0530 add.w r5, r4, #48 ; 0x30 + 1c194: e9d5 4500 ldrd r4, r5, [r5] + 1c198: f50d 7efc add.w lr, sp, #504 ; 0x1f8 + 1c19c: e9c6 4500 strd r4, r5, [r6] + 1c1a0: f10a 0b18 add.w fp, sl, #24 + 1c1a4: e9db ab00 ldrd sl, fp, [fp] + 1c1a8: 9e7d ldr r6, [sp, #500] ; 0x1f4 + 1c1aa: e9ce ab00 strd sl, fp, [lr] + 1c1ae: f106 0738 add.w r7, r6, #56 ; 0x38 + 1c1b2: e9d7 6700 ldrd r6, r7, [r7] + 1c1b6: f50d 7a06 add.w sl, sp, #536 ; 0x218 + 1c1ba: e9ca 6700 strd r6, r7, [sl] + 1c1be: f8dd a1f4 ldr.w sl, [sp, #500] ; 0x1f4 + 1c1c2: f50d 7e08 add.w lr, sp, #544 ; 0x220 + 1c1c6: 987d ldr r0, [sp, #500] ; 0x1f4 + 1c1c8: f10a 0b40 add.w fp, sl, #64 ; 0x40 + 1c1cc: e9db ab00 ldrd sl, fp, [fp] + 1c1d0: aa8a add r2, sp, #552 ; 0x228 + 1c1d2: e9ce ab00 strd sl, fp, [lr] + 1c1d6: f100 0148 add.w r1, r0, #72 ; 0x48 + 1c1da: e9d1 0100 ldrd r0, r1, [r1] + 1c1de: f8dd 91f4 ldr.w r9, [sp, #500] ; 0x1f4 + 1c1e2: e9c2 0100 strd r0, r1, [r2] + 1c1e6: e9d9 8904 ldrd r8, r9, [r9, #16] + 1c1ea: a97e add r1, sp, #504 ; 0x1f8 + 1c1ec: e9d1 2300 ldrd r2, r3, [r1] + 1c1f0: ac80 add r4, sp, #512 ; 0x200 + 1c1f2: af82 add r7, sp, #520 ; 0x208 + 1c1f4: a984 add r1, sp, #528 ; 0x210 + 1c1f6: ad86 add r5, sp, #536 ; 0x218 + 1c1f8: e9d4 ab00 ldrd sl, fp, [r4] + 1c1fc: e9d1 0100 ldrd r0, r1, [r1] + 1c200: e9cd 891a strd r8, r9, [sp, #104] ; 0x68 + 1c204: e9d7 6700 ldrd r6, r7, [r7] + 1c208: e9d5 4500 ldrd r4, r5, [r5] + 1c20c: e9cd 010e strd r0, r1, [sp, #56] ; 0x38 + 1c210: e9cd 6706 strd r6, r7, [sp, #24] + 1c214: e9de 6700 ldrd r6, r7, [lr] + 1c218: e9cd 450a strd r4, r5, [sp, #40] ; 0x28 + 1c21c: e9cd 670c strd r6, r7, [sp, #48] ; 0x30 + 1c220: e9cd ab12 strd sl, fp, [sp, #72] ; 0x48 + 1c224: 46c2 mov sl, r8 + 1c226: 46cb mov fp, r9 + 1c228: 4690 mov r8, r2 + 1c22a: 4699 mov r9, r3 + 1c22c: a98a add r1, sp, #552 ; 0x228 + 1c22e: e9d1 0100 ldrd r0, r1, [r1] + 1c232: e9cd 0108 strd r0, r1, [sp, #32] + 1c236: f8df cae0 ldr.w ip, [pc, #2784] ; 1cd18 + 1c23a: f50d 7e1a add.w lr, sp, #616 ; 0x268 + 1c23e: 9b0e ldr r3, [sp, #56] ; 0x38 + 1c240: 9c0f ldr r4, [sp, #60] ; 0x3c + 1c242: 0c9a lsrs r2, r3, #18 + 1c244: 0b9b lsrs r3, r3, #14 + 1c246: 9f0e ldr r7, [sp, #56] ; 0x38 + 1c248: ea42 3284 orr.w r2, r2, r4, lsl #14 + 1c24c: ea43 4384 orr.w r3, r3, r4, lsl #18 + 1c250: 921c str r2, [sp, #112] ; 0x70 + 1c252: 931e str r3, [sp, #120] ; 0x78 + 1c254: 0ca2 lsrs r2, r4, #18 + 1c256: 0ba3 lsrs r3, r4, #14 + 1c258: ea42 3287 orr.w r2, r2, r7, lsl #14 + 1c25c: ea43 4387 orr.w r3, r3, r7, lsl #18 + 1c260: 921d str r2, [sp, #116] ; 0x74 + 1c262: 931f str r3, [sp, #124] ; 0x7c + 1c264: e9dd 450a ldrd r4, r5, [sp, #40] ; 0x28 + 1c268: e9dd 231e ldrd r2, r3, [sp, #120] ; 0x78 + 1c26c: e9dd 011c ldrd r0, r1, [sp, #112] ; 0x70 + 1c270: 4050 eors r0, r2 + 1c272: 4059 eors r1, r3 + 1c274: e9dd 230c ldrd r2, r3, [sp, #48] ; 0x30 + 1c278: 406b eors r3, r5 + 1c27a: 9d0e ldr r5, [sp, #56] ; 0x38 + 1c27c: 4062 eors r2, r4 + 1c27e: 05ec lsls r4, r5, #23 + 1c280: 9d0f ldr r5, [sp, #60] ; 0x3c + 1c282: e95e 670e ldrd r6, r7, [lr, #-56] ; 0x38 + 1c286: ea44 2455 orr.w r4, r4, r5, lsr #9 + 1c28a: 9420 str r4, [sp, #128] ; 0x80 + 1c28c: 05ec lsls r4, r5, #23 + 1c28e: 9d0e ldr r5, [sp, #56] ; 0x38 + 1c290: ea44 2455 orr.w r4, r4, r5, lsr #9 + 1c294: 9421 str r4, [sp, #132] ; 0x84 + 1c296: e9dd 4520 ldrd r4, r5, [sp, #128] ; 0x80 + 1c29a: 4060 eors r0, r4 + 1c29c: 4069 eors r1, r5 + 1c29e: e95c 450e ldrd r4, r5, [ip, #-56] ; 0x38 + 1c2a2: 19a4 adds r4, r4, r6 + 1c2a4: 417d adcs r5, r7 + 1c2a6: e9dd 670e ldrd r6, r7, [sp, #56] ; 0x38 + 1c2aa: 4032 ands r2, r6 + 1c2ac: ea4f 768a mov.w r6, sl, lsl #30 + 1c2b0: ea46 069b orr.w r6, r6, fp, lsr #2 + 1c2b4: 9622 str r6, [sp, #136] ; 0x88 + 1c2b6: ea4f 761a mov.w r6, sl, lsr #28 + 1c2ba: ea46 160b orr.w r6, r6, fp, lsl #4 + 1c2be: 9624 str r6, [sp, #144] ; 0x90 + 1c2c0: ea4f 768b mov.w r6, fp, lsl #30 + 1c2c4: ea46 069a orr.w r6, r6, sl, lsr #2 + 1c2c8: 1824 adds r4, r4, r0 + 1c2ca: 9623 str r6, [sp, #140] ; 0x8c + 1c2cc: ea4f 761b mov.w r6, fp, lsr #28 + 1c2d0: 414d adcs r5, r1 + 1c2d2: ea46 160a orr.w r6, r6, sl, lsl #4 + 1c2d6: e9dd 010c ldrd r0, r1, [sp, #48] ; 0x30 + 1c2da: 403b ands r3, r7 + 1c2dc: 4042 eors r2, r0 + 1c2de: 404b eors r3, r1 + 1c2e0: 18a4 adds r4, r4, r2 + 1c2e2: 9625 str r6, [sp, #148] ; 0x94 + 1c2e4: e9dd 6724 ldrd r6, r7, [sp, #144] ; 0x90 + 1c2e8: 415d adcs r5, r3 + 1c2ea: e9dd 2322 ldrd r2, r3, [sp, #136] ; 0x88 + 1c2ee: 4072 eors r2, r6 + 1c2f0: 407b eors r3, r7 + 1c2f2: e9dd 6708 ldrd r6, r7, [sp, #32] + 1c2f6: 19a4 adds r4, r4, r6 + 1c2f8: 417d adcs r5, r7 + 1c2fa: ea4f 674a mov.w r7, sl, lsl #25 + 1c2fe: ea47 17db orr.w r7, r7, fp, lsr #7 + 1c302: 9726 str r7, [sp, #152] ; 0x98 + 1c304: ea4f 674b mov.w r7, fp, lsl #25 + 1c308: ea47 17da orr.w r7, r7, sl, lsr #7 + 1c30c: ea48 000a orr.w r0, r8, sl + 1c310: ea49 010b orr.w r1, r9, fp + 1c314: e9cd 2310 strd r2, r3, [sp, #64] ; 0x40 + 1c318: e9dd 2312 ldrd r2, r3, [sp, #72] ; 0x48 + 1c31c: 9727 str r7, [sp, #156] ; 0x9c + 1c31e: e9dd 6726 ldrd r6, r7, [sp, #152] ; 0x98 + 1c322: 4002 ands r2, r0 + 1c324: 400b ands r3, r1 + 1c326: e9dd 0110 ldrd r0, r1, [sp, #64] ; 0x40 + 1c32a: 4070 eors r0, r6 + 1c32c: 4079 eors r1, r7 + 1c32e: e9cd 2314 strd r2, r3, [sp, #80] ; 0x50 + 1c332: e9cd 0110 strd r0, r1, [sp, #64] ; 0x40 + 1c336: e9dd 6706 ldrd r6, r7, [sp, #24] + 1c33a: e9dd 0114 ldrd r0, r1, [sp, #80] ; 0x50 + 1c33e: 1936 adds r6, r6, r4 + 1c340: ea08 020a and.w r2, r8, sl + 1c344: 416f adcs r7, r5 + 1c346: ea09 030b and.w r3, r9, fp + 1c34a: 4302 orrs r2, r0 + 1c34c: e9cd 6708 strd r6, r7, [sp, #32] + 1c350: e9dd 6710 ldrd r6, r7, [sp, #64] ; 0x40 + 1c354: 430b orrs r3, r1 + 1c356: 18b6 adds r6, r6, r2 + 1c358: e9dd 010e ldrd r0, r1, [sp, #56] ; 0x38 + 1c35c: 415f adcs r7, r3 + 1c35e: e9dd 230a ldrd r2, r3, [sp, #40] ; 0x28 + 1c362: 4042 eors r2, r0 + 1c364: 404b eors r3, r1 + 1c366: 1930 adds r0, r6, r4 + 1c368: eb47 0105 adc.w r1, r7, r5 + 1c36c: e95e 670c ldrd r6, r7, [lr, #-48] ; 0x30 + 1c370: e9dd 4508 ldrd r4, r5, [sp, #32] + 1c374: 4022 ands r2, r4 + 1c376: 402b ands r3, r5 + 1c378: e95c 450c ldrd r4, r5, [ip, #-48] ; 0x30 + 1c37c: 19a4 adds r4, r4, r6 + 1c37e: 417d adcs r5, r7 + 1c380: 9f08 ldr r7, [sp, #32] + 1c382: 9e09 ldr r6, [sp, #36] ; 0x24 + 1c384: e9cd 0106 strd r0, r1, [sp, #24] + 1c388: 0cb8 lsrs r0, r7, #18 + 1c38a: 0bb9 lsrs r1, r7, #14 + 1c38c: ea40 3086 orr.w r0, r0, r6, lsl #14 + 1c390: 9f08 ldr r7, [sp, #32] + 1c392: ea41 4186 orr.w r1, r1, r6, lsl #18 + 1c396: 9028 str r0, [sp, #160] ; 0xa0 + 1c398: 912a str r1, [sp, #168] ; 0xa8 + 1c39a: 0cb0 lsrs r0, r6, #18 + 1c39c: 0bb1 lsrs r1, r6, #14 + 1c39e: ea40 3087 orr.w r0, r0, r7, lsl #14 + 1c3a2: ea41 4187 orr.w r1, r1, r7, lsl #18 + 1c3a6: 9029 str r0, [sp, #164] ; 0xa4 + 1c3a8: 912b str r1, [sp, #172] ; 0xac + 1c3aa: e9dd 012a ldrd r0, r1, [sp, #168] ; 0xa8 + 1c3ae: e9dd 6728 ldrd r6, r7, [sp, #160] ; 0xa0 + 1c3b2: 4046 eors r6, r0 + 1c3b4: 404f eors r7, r1 + 1c3b6: e9cd 6710 strd r6, r7, [sp, #64] ; 0x40 + 1c3ba: e9dd 670a ldrd r6, r7, [sp, #40] ; 0x28 + 1c3be: e9dd 010c ldrd r0, r1, [sp, #48] ; 0x30 + 1c3c2: 4056 eors r6, r2 + 1c3c4: 9a08 ldr r2, [sp, #32] + 1c3c6: 405f eors r7, r3 + 1c3c8: 9b09 ldr r3, [sp, #36] ; 0x24 + 1c3ca: e9cd 6714 strd r6, r7, [sp, #80] ; 0x50 + 1c3ce: 05d6 lsls r6, r2, #23 + 1c3d0: ea46 2653 orr.w r6, r6, r3, lsr #9 + 1c3d4: 9f07 ldr r7, [sp, #28] + 1c3d6: 962c str r6, [sp, #176] ; 0xb0 + 1c3d8: 05de lsls r6, r3, #23 + 1c3da: 9b06 ldr r3, [sp, #24] + 1c3dc: ea46 2652 orr.w r6, r6, r2, lsr #9 + 1c3e0: 962d str r6, [sp, #180] ; 0xb4 + 1c3e2: 463a mov r2, r7 + 1c3e4: 079e lsls r6, r3, #30 + 1c3e6: ea46 0697 orr.w r6, r6, r7, lsr #2 + 1c3ea: 962e str r6, [sp, #184] ; 0xb8 + 1c3ec: 07be lsls r6, r7, #30 + 1c3ee: 461f mov r7, r3 + 1c3f0: ea46 0693 orr.w r6, r6, r3, lsr #2 + 1c3f4: 962f str r6, [sp, #188] ; 0xbc + 1c3f6: 0f1e lsrs r6, r3, #28 + 1c3f8: ea46 1602 orr.w r6, r6, r2, lsl #4 + 1c3fc: 9630 str r6, [sp, #192] ; 0xc0 + 1c3fe: 0f16 lsrs r6, r2, #28 + 1c400: 1824 adds r4, r4, r0 + 1c402: ea46 1607 orr.w r6, r6, r7, lsl #4 + 1c406: 414d adcs r5, r1 + 1c408: e9dd 0106 ldrd r0, r1, [sp, #24] + 1c40c: 9631 str r6, [sp, #196] ; 0xc4 + 1c40e: e9dd 2310 ldrd r2, r3, [sp, #64] ; 0x40 + 1c412: e9dd 672c ldrd r6, r7, [sp, #176] ; 0xb0 + 1c416: 4072 eors r2, r6 + 1c418: 407b eors r3, r7 + 1c41a: e9cd 230c strd r2, r3, [sp, #48] ; 0x30 + 1c41e: e9dd 2314 ldrd r2, r3, [sp, #80] ; 0x50 + 1c422: e9dd 672e ldrd r6, r7, [sp, #184] ; 0xb8 + 1c426: 18a4 adds r4, r4, r2 + 1c428: ea40 000a orr.w r0, r0, sl + 1c42c: ea41 010b orr.w r1, r1, fp + 1c430: 415d adcs r5, r3 + 1c432: e9dd 2330 ldrd r2, r3, [sp, #192] ; 0xc0 + 1c436: 4056 eors r6, r2 + 1c438: 405f eors r7, r3 + 1c43a: e9cd 6714 strd r6, r7, [sp, #80] ; 0x50 + 1c43e: e9dd 2306 ldrd r2, r3, [sp, #24] + 1c442: ea00 0608 and.w r6, r0, r8 + 1c446: ea01 0709 and.w r7, r1, r9 + 1c44a: e9cd 6716 strd r6, r7, [sp, #88] ; 0x58 + 1c44e: 9f06 ldr r7, [sp, #24] + 1c450: 9807 ldr r0, [sp, #28] + 1c452: 0679 lsls r1, r7, #25 + 1c454: ea41 11d0 orr.w r1, r1, r0, lsr #7 + 1c458: 9132 str r1, [sp, #200] ; 0xc8 + 1c45a: 0641 lsls r1, r0, #25 + 1c45c: ea41 11d7 orr.w r1, r1, r7, lsr #7 + 1c460: 9133 str r1, [sp, #204] ; 0xcc + 1c462: e9dd 010c ldrd r0, r1, [sp, #48] ; 0x30 + 1c466: 1824 adds r4, r4, r0 + 1c468: 414d adcs r5, r1 + 1c46a: e9dd 6714 ldrd r6, r7, [sp, #80] ; 0x50 + 1c46e: e9dd 0132 ldrd r0, r1, [sp, #200] ; 0xc8 + 1c472: ea02 020a and.w r2, r2, sl + 1c476: 4046 eors r6, r0 + 1c478: 404f eors r7, r1 + 1c47a: e9cd 6710 strd r6, r7, [sp, #64] ; 0x40 + 1c47e: e9dd 0112 ldrd r0, r1, [sp, #72] ; 0x48 + 1c482: e9dd 6716 ldrd r6, r7, [sp, #88] ; 0x58 + 1c486: 1900 adds r0, r0, r4 + 1c488: ea42 0206 orr.w r2, r2, r6 + 1c48c: ea03 030b and.w r3, r3, fp + 1c490: 4169 adcs r1, r5 + 1c492: 433b orrs r3, r7 + 1c494: e9dd 6710 ldrd r6, r7, [sp, #64] ; 0x40 + 1c498: 18b6 adds r6, r6, r2 + 1c49a: e9cd 010c strd r0, r1, [sp, #48] ; 0x30 + 1c49e: e9dd 010e ldrd r0, r1, [sp, #56] ; 0x38 + 1c4a2: 415f adcs r7, r3 + 1c4a4: e9dd 2308 ldrd r2, r3, [sp, #32] + 1c4a8: 4042 eors r2, r0 + 1c4aa: 404b eors r3, r1 + 1c4ac: 1930 adds r0, r6, r4 + 1c4ae: eb47 0105 adc.w r1, r7, r5 + 1c4b2: e95e 670a ldrd r6, r7, [lr, #-40] ; 0x28 + 1c4b6: e9dd 450c ldrd r4, r5, [sp, #48] ; 0x30 + 1c4ba: 4022 ands r2, r4 + 1c4bc: 402b ands r3, r5 + 1c4be: e95c 450a ldrd r4, r5, [ip, #-40] ; 0x28 + 1c4c2: 19a4 adds r4, r4, r6 + 1c4c4: 417d adcs r5, r7 + 1c4c6: 9f0c ldr r7, [sp, #48] ; 0x30 + 1c4c8: 9e0d ldr r6, [sp, #52] ; 0x34 + 1c4ca: e9cd 0112 strd r0, r1, [sp, #72] ; 0x48 + 1c4ce: 0cb8 lsrs r0, r7, #18 + 1c4d0: 0bb9 lsrs r1, r7, #14 + 1c4d2: ea40 3086 orr.w r0, r0, r6, lsl #14 + 1c4d6: 9f0c ldr r7, [sp, #48] ; 0x30 + 1c4d8: ea41 4186 orr.w r1, r1, r6, lsl #18 + 1c4dc: 9034 str r0, [sp, #208] ; 0xd0 + 1c4de: 9136 str r1, [sp, #216] ; 0xd8 + 1c4e0: 0cb0 lsrs r0, r6, #18 + 1c4e2: 0bb1 lsrs r1, r6, #14 + 1c4e4: ea40 3087 orr.w r0, r0, r7, lsl #14 + 1c4e8: ea41 4187 orr.w r1, r1, r7, lsl #18 + 1c4ec: 9035 str r0, [sp, #212] ; 0xd4 + 1c4ee: 9137 str r1, [sp, #220] ; 0xdc + 1c4f0: e9dd 0136 ldrd r0, r1, [sp, #216] ; 0xd8 + 1c4f4: e9dd 6734 ldrd r6, r7, [sp, #208] ; 0xd0 + 1c4f8: 4046 eors r6, r0 + 1c4fa: 404f eors r7, r1 + 1c4fc: e9dd 010a ldrd r0, r1, [sp, #40] ; 0x28 + 1c500: 1824 adds r4, r4, r0 + 1c502: e9cd 6710 strd r6, r7, [sp, #64] ; 0x40 + 1c506: e9dd 670e ldrd r6, r7, [sp, #56] ; 0x38 + 1c50a: 414d adcs r5, r1 + 1c50c: 4056 eors r6, r2 + 1c50e: 405f eors r7, r3 + 1c510: e9dd 0112 ldrd r0, r1, [sp, #72] ; 0x48 + 1c514: e9dd 2306 ldrd r2, r3, [sp, #24] + 1c518: 4319 orrs r1, r3 + 1c51a: 9b0c ldr r3, [sp, #48] ; 0x30 + 1c51c: e9cd 6714 strd r6, r7, [sp, #80] ; 0x50 + 1c520: 9f0d ldr r7, [sp, #52] ; 0x34 + 1c522: 05de lsls r6, r3, #23 + 1c524: ea46 2657 orr.w r6, r6, r7, lsr #9 + 1c528: 4310 orrs r0, r2 + 1c52a: 9638 str r6, [sp, #224] ; 0xe0 + 1c52c: 9a13 ldr r2, [sp, #76] ; 0x4c + 1c52e: 05fe lsls r6, r7, #23 + 1c530: 9f12 ldr r7, [sp, #72] ; 0x48 + 1c532: ea46 2653 orr.w r6, r6, r3, lsr #9 + 1c536: 9639 str r6, [sp, #228] ; 0xe4 + 1c538: 4613 mov r3, r2 + 1c53a: 07be lsls r6, r7, #30 + 1c53c: ea46 0692 orr.w r6, r6, r2, lsr #2 + 1c540: 963a str r6, [sp, #232] ; 0xe8 + 1c542: 0796 lsls r6, r2, #30 + 1c544: 463a mov r2, r7 + 1c546: ea46 0697 orr.w r6, r6, r7, lsr #2 + 1c54a: 963b str r6, [sp, #236] ; 0xec + 1c54c: 0f3e lsrs r6, r7, #28 + 1c54e: ea46 1603 orr.w r6, r6, r3, lsl #4 + 1c552: 963c str r6, [sp, #240] ; 0xf0 + 1c554: 0f1e lsrs r6, r3, #28 + 1c556: ea46 1602 orr.w r6, r6, r2, lsl #4 + 1c55a: 963d str r6, [sp, #244] ; 0xf4 + 1c55c: e9dd 2338 ldrd r2, r3, [sp, #224] ; 0xe0 + 1c560: e9dd 6710 ldrd r6, r7, [sp, #64] ; 0x40 + 1c564: 4056 eors r6, r2 + 1c566: 405f eors r7, r3 + 1c568: e9cd 670a strd r6, r7, [sp, #40] ; 0x28 + 1c56c: e9dd 6714 ldrd r6, r7, [sp, #80] ; 0x50 + 1c570: e9dd 233a ldrd r2, r3, [sp, #232] ; 0xe8 + 1c574: 19a4 adds r4, r4, r6 + 1c576: 417d adcs r5, r7 + 1c578: e9dd 673c ldrd r6, r7, [sp, #240] ; 0xf0 + 1c57c: 4072 eors r2, r6 + 1c57e: 407b eors r3, r7 + 1c580: e9cd 2314 strd r2, r3, [sp, #80] ; 0x50 + 1c584: e9dd 6706 ldrd r6, r7, [sp, #24] + 1c588: ea00 020a and.w r2, r0, sl + 1c58c: ea01 030b and.w r3, r1, fp + 1c590: e9cd 2316 strd r2, r3, [sp, #88] ; 0x58 + 1c594: e9dd 2312 ldrd r2, r3, [sp, #72] ; 0x48 + 1c598: 403b ands r3, r7 + 1c59a: 9f12 ldr r7, [sp, #72] ; 0x48 + 1c59c: 9813 ldr r0, [sp, #76] ; 0x4c + 1c59e: 0679 lsls r1, r7, #25 + 1c5a0: ea41 11d0 orr.w r1, r1, r0, lsr #7 + 1c5a4: 913e str r1, [sp, #248] ; 0xf8 + 1c5a6: 0641 lsls r1, r0, #25 + 1c5a8: ea41 11d7 orr.w r1, r1, r7, lsr #7 + 1c5ac: 913f str r1, [sp, #252] ; 0xfc + 1c5ae: e9dd 010a ldrd r0, r1, [sp, #40] ; 0x28 + 1c5b2: 1824 adds r4, r4, r0 + 1c5b4: 414d adcs r5, r1 + 1c5b6: 4032 ands r2, r6 + 1c5b8: e9dd 013e ldrd r0, r1, [sp, #248] ; 0xf8 + 1c5bc: e9dd 6714 ldrd r6, r7, [sp, #80] ; 0x50 + 1c5c0: 4046 eors r6, r0 + 1c5c2: 404f eors r7, r1 + 1c5c4: e9cd 6710 strd r6, r7, [sp, #64] ; 0x40 + 1c5c8: e9dd 6716 ldrd r6, r7, [sp, #88] ; 0x58 + 1c5cc: e95e 0108 ldrd r0, r1, [lr, #-32] + 1c5d0: 4332 orrs r2, r6 + 1c5d2: eb14 0608 adds.w r6, r4, r8 + 1c5d6: ea43 0307 orr.w r3, r3, r7 + 1c5da: eb45 0709 adc.w r7, r5, r9 + 1c5de: e9cd 670a strd r6, r7, [sp, #40] ; 0x28 + 1c5e2: e9dd 6710 ldrd r6, r7, [sp, #64] ; 0x40 + 1c5e6: e9dd 8908 ldrd r8, r9, [sp, #32] + 1c5ea: 18b6 adds r6, r6, r2 + 1c5ec: 415f adcs r7, r3 + 1c5ee: e9dd 230c ldrd r2, r3, [sp, #48] ; 0x30 + 1c5f2: ea82 0208 eor.w r2, r2, r8 + 1c5f6: ea83 0309 eor.w r3, r3, r9 + 1c5fa: eb16 0804 adds.w r8, r6, r4 + 1c5fe: 9e0a ldr r6, [sp, #40] ; 0x28 + 1c600: eb47 0905 adc.w r9, r7, r5 + 1c604: 9f0b ldr r7, [sp, #44] ; 0x2c + 1c606: e9dd 450a ldrd r4, r5, [sp, #40] ; 0x28 + 1c60a: 4022 ands r2, r4 + 1c60c: 402b ands r3, r5 + 1c60e: e95c 4508 ldrd r4, r5, [ip, #-32] + 1c612: 1824 adds r4, r4, r0 + 1c614: 414d adcs r5, r1 + 1c616: 0cb0 lsrs r0, r6, #18 + 1c618: 0bb1 lsrs r1, r6, #14 + 1c61a: ea40 3087 orr.w r0, r0, r7, lsl #14 + 1c61e: 9e0a ldr r6, [sp, #40] ; 0x28 + 1c620: ea41 4187 orr.w r1, r1, r7, lsl #18 + 1c624: 9040 str r0, [sp, #256] ; 0x100 + 1c626: 9142 str r1, [sp, #264] ; 0x108 + 1c628: 0cb8 lsrs r0, r7, #18 + 1c62a: 0bb9 lsrs r1, r7, #14 + 1c62c: ea40 3086 orr.w r0, r0, r6, lsl #14 + 1c630: ea41 4186 orr.w r1, r1, r6, lsl #18 + 1c634: 9143 str r1, [sp, #268] ; 0x10c + 1c636: 9041 str r0, [sp, #260] ; 0x104 + 1c638: af40 add r7, sp, #256 ; 0x100 + 1c63a: ae42 add r6, sp, #264 ; 0x108 + 1c63c: e9d7 0100 ldrd r0, r1, [r7] + 1c640: cec0 ldmia r6, {r6, r7} + 1c642: 4070 eors r0, r6 + 1c644: 4079 eors r1, r7 + 1c646: e9cd 0110 strd r0, r1, [sp, #64] ; 0x40 + 1c64a: e9dd 0108 ldrd r0, r1, [sp, #32] + 1c64e: 4050 eors r0, r2 + 1c650: 4059 eors r1, r3 + 1c652: e9dd 230e ldrd r2, r3, [sp, #56] ; 0x38 + 1c656: 18a4 adds r4, r4, r2 + 1c658: 415d adcs r5, r3 + 1c65a: 9b0a ldr r3, [sp, #40] ; 0x28 + 1c65c: 9f0b ldr r7, [sp, #44] ; 0x2c + 1c65e: 05de lsls r6, r3, #23 + 1c660: ea46 2657 orr.w r6, r6, r7, lsr #9 + 1c664: 9644 str r6, [sp, #272] ; 0x110 + 1c666: 05fe lsls r6, r7, #23 + 1c668: ea46 2653 orr.w r6, r6, r3, lsr #9 + 1c66c: 9645 str r6, [sp, #276] ; 0x114 + 1c66e: ea4f 7688 mov.w r6, r8, lsl #30 + 1c672: ea46 0699 orr.w r6, r6, r9, lsr #2 + 1c676: 9646 str r6, [sp, #280] ; 0x118 + 1c678: ea4f 7689 mov.w r6, r9, lsl #30 + 1c67c: ea46 0698 orr.w r6, r6, r8, lsr #2 + 1c680: 9647 str r6, [sp, #284] ; 0x11c + 1c682: ea4f 7618 mov.w r6, r8, lsr #28 + 1c686: ea46 1609 orr.w r6, r6, r9, lsl #4 + 1c68a: 9648 str r6, [sp, #288] ; 0x120 + 1c68c: ea4f 7619 mov.w r6, r9, lsr #28 + 1c690: ea46 1608 orr.w r6, r6, r8, lsl #4 + 1c694: ab44 add r3, sp, #272 ; 0x110 + 1c696: e9d3 2300 ldrd r2, r3, [r3] + 1c69a: e9cd 0114 strd r0, r1, [sp, #80] ; 0x50 + 1c69e: e9dd 0112 ldrd r0, r1, [sp, #72] ; 0x48 + 1c6a2: 9649 str r6, [sp, #292] ; 0x124 + 1c6a4: e9dd 6710 ldrd r6, r7, [sp, #64] ; 0x40 + 1c6a8: 4056 eors r6, r2 + 1c6aa: 405f eors r7, r3 + 1c6ac: e9cd 670e strd r6, r7, [sp, #56] ; 0x38 + 1c6b0: e9dd 6714 ldrd r6, r7, [sp, #80] ; 0x50 + 1c6b4: 19a4 adds r4, r4, r6 + 1c6b6: 417d adcs r5, r7 + 1c6b8: ae48 add r6, sp, #288 ; 0x120 + 1c6ba: af46 add r7, sp, #280 ; 0x118 + 1c6bc: e9d7 2300 ldrd r2, r3, [r7] + 1c6c0: cec0 ldmia r6, {r6, r7} + 1c6c2: 407b eors r3, r7 + 1c6c4: ea4f 6748 mov.w r7, r8, lsl #25 + 1c6c8: 4072 eors r2, r6 + 1c6ca: ea47 17d9 orr.w r7, r7, r9, lsr #7 + 1c6ce: e9cd 2314 strd r2, r3, [sp, #80] ; 0x50 + 1c6d2: e9dd 2306 ldrd r2, r3, [sp, #24] + 1c6d6: 974a str r7, [sp, #296] ; 0x128 + 1c6d8: ea4f 6749 mov.w r7, r9, lsl #25 + 1c6dc: ea47 17d8 orr.w r7, r7, r8, lsr #7 + 1c6e0: ea40 0008 orr.w r0, r0, r8 + 1c6e4: ea41 0109 orr.w r1, r1, r9 + 1c6e8: 974b str r7, [sp, #300] ; 0x12c + 1c6ea: e9dd 670e ldrd r6, r7, [sp, #56] ; 0x38 + 1c6ee: 19a4 adds r4, r4, r6 + 1c6f0: 417d adcs r5, r7 + 1c6f2: 4002 ands r2, r0 + 1c6f4: 400b ands r3, r1 + 1c6f6: af4a add r7, sp, #296 ; 0x128 + 1c6f8: e9d7 6700 ldrd r6, r7, [r7] + 1c6fc: e9cd 2316 strd r2, r3, [sp, #88] ; 0x58 + 1c700: e9dd 0114 ldrd r0, r1, [sp, #80] ; 0x50 + 1c704: e9dd 2312 ldrd r2, r3, [sp, #72] ; 0x48 + 1c708: 4070 eors r0, r6 + 1c70a: 4079 eors r1, r7 + 1c70c: eb14 060a adds.w r6, r4, sl + 1c710: ea02 0208 and.w r2, r2, r8 + 1c714: e9cd 010e strd r0, r1, [sp, #56] ; 0x38 + 1c718: e9dd 0116 ldrd r0, r1, [sp, #88] ; 0x58 + 1c71c: eb45 070b adc.w r7, r5, fp + 1c720: 4302 orrs r2, r0 + 1c722: ea03 0309 and.w r3, r3, r9 + 1c726: e9cd 6710 strd r6, r7, [sp, #64] ; 0x40 + 1c72a: e9dd 670e ldrd r6, r7, [sp, #56] ; 0x38 + 1c72e: e9dd ab0c ldrd sl, fp, [sp, #48] ; 0x30 + 1c732: 18b6 adds r6, r6, r2 + 1c734: ea43 0301 orr.w r3, r3, r1 + 1c738: 415f adcs r7, r3 + 1c73a: e9dd 230a ldrd r2, r3, [sp, #40] ; 0x28 + 1c73e: ea82 020a eor.w r2, r2, sl + 1c742: eb16 0a04 adds.w sl, r6, r4 + 1c746: e95c 0106 ldrd r0, r1, [ip, #-24] + 1c74a: ea83 030b eor.w r3, r3, fp + 1c74e: eb47 0b05 adc.w fp, r7, r5 + 1c752: e95e 4506 ldrd r4, r5, [lr, #-24] + 1c756: 1824 adds r4, r4, r0 + 1c758: 414d adcs r5, r1 + 1c75a: e9dd 0110 ldrd r0, r1, [sp, #64] ; 0x40 + 1c75e: 400b ands r3, r1 + 1c760: 9910 ldr r1, [sp, #64] ; 0x40 + 1c762: 9e11 ldr r6, [sp, #68] ; 0x44 + 1c764: 4002 ands r2, r0 + 1c766: 0c88 lsrs r0, r1, #18 + 1c768: 0b89 lsrs r1, r1, #14 + 1c76a: ea40 3086 orr.w r0, r0, r6, lsl #14 + 1c76e: ea41 4186 orr.w r1, r1, r6, lsl #18 + 1c772: 904c str r0, [sp, #304] ; 0x130 + 1c774: 914e str r1, [sp, #312] ; 0x138 + 1c776: 0cb0 lsrs r0, r6, #18 + 1c778: 0bb1 lsrs r1, r6, #14 + 1c77a: e9dd 6708 ldrd r6, r7, [sp, #32] + 1c77e: 19a4 adds r4, r4, r6 + 1c780: 417d adcs r5, r7 + 1c782: 9f10 ldr r7, [sp, #64] ; 0x40 + 1c784: e9cd ab0e strd sl, fp, [sp, #56] ; 0x38 + 1c788: 05fe lsls r6, r7, #23 + 1c78a: 9f11 ldr r7, [sp, #68] ; 0x44 + 1c78c: f8dd b040 ldr.w fp, [sp, #64] ; 0x40 + 1c790: ea46 2657 orr.w r6, r6, r7, lsr #9 + 1c794: 9650 str r6, [sp, #320] ; 0x140 + 1c796: 05fe lsls r6, r7, #23 + 1c798: 9f10 ldr r7, [sp, #64] ; 0x40 + 1c79a: ea40 308b orr.w r0, r0, fp, lsl #14 + 1c79e: ea41 418b orr.w r1, r1, fp, lsl #18 + 1c7a2: 904d str r0, [sp, #308] ; 0x134 + 1c7a4: 914f str r1, [sp, #316] ; 0x13c + 1c7a6: ea46 2657 orr.w r6, r6, r7, lsr #9 + 1c7aa: a94c add r1, sp, #304 ; 0x130 + 1c7ac: a84e add r0, sp, #312 ; 0x138 + 1c7ae: e9dd ab0c ldrd sl, fp, [sp, #48] ; 0x30 + 1c7b2: ea82 020a eor.w r2, r2, sl + 1c7b6: ea83 030b eor.w r3, r3, fp + 1c7ba: e9d1 ab00 ldrd sl, fp, [r1] + 1c7be: c803 ldmia r0, {r0, r1} + 1c7c0: ea8a 0a00 eor.w sl, sl, r0 + 1c7c4: ea8b 0b01 eor.w fp, fp, r1 + 1c7c8: e9dd 010e ldrd r0, r1, [sp, #56] ; 0x38 + 1c7cc: 9651 str r6, [sp, #324] ; 0x144 + 1c7ce: 9f0e ldr r7, [sp, #56] ; 0x38 + 1c7d0: 18a4 adds r4, r4, r2 + 1c7d2: ea4f 7687 mov.w r6, r7, lsl #30 + 1c7d6: 9f0f ldr r7, [sp, #60] ; 0x3c + 1c7d8: 415d adcs r5, r3 + 1c7da: ea46 0697 orr.w r6, r6, r7, lsr #2 + 1c7de: 9652 str r6, [sp, #328] ; 0x148 + 1c7e0: 07be lsls r6, r7, #30 + 1c7e2: 9f0e ldr r7, [sp, #56] ; 0x38 + 1c7e4: ea40 0008 orr.w r0, r0, r8 + 1c7e8: ea46 0697 orr.w r6, r6, r7, lsr #2 + 1c7ec: 9653 str r6, [sp, #332] ; 0x14c + 1c7ee: 0f3e lsrs r6, r7, #28 + 1c7f0: 9f0f ldr r7, [sp, #60] ; 0x3c + 1c7f2: ea41 0109 orr.w r1, r1, r9 + 1c7f6: ea46 1607 orr.w r6, r6, r7, lsl #4 + 1c7fa: 9654 str r6, [sp, #336] ; 0x150 + 1c7fc: 0f3e lsrs r6, r7, #28 + 1c7fe: 9f0e ldr r7, [sp, #56] ; 0x38 + 1c800: ea46 1607 orr.w r6, r6, r7, lsl #4 + 1c804: 9655 str r6, [sp, #340] ; 0x154 + 1c806: ae50 add r6, sp, #320 ; 0x140 + 1c808: e9d6 2300 ldrd r2, r3, [r6] + 1c80c: ea82 020a eor.w r2, r2, sl + 1c810: ea83 030b eor.w r3, r3, fp + 1c814: f50d 7aa8 add.w sl, sp, #336 ; 0x150 + 1c818: f50d 7ba4 add.w fp, sp, #328 ; 0x148 + 1c81c: e9db 6700 ldrd r6, r7, [fp] + 1c820: e89a 0c00 ldmia.w sl, {sl, fp} + 1c824: ea87 070b eor.w r7, r7, fp + 1c828: f8dd b038 ldr.w fp, [sp, #56] ; 0x38 + 1c82c: ea86 060a eor.w r6, r6, sl + 1c830: ea4f 6a4b mov.w sl, fp, lsl #25 + 1c834: f8dd b03c ldr.w fp, [sp, #60] ; 0x3c + 1c838: e9cd 2308 strd r2, r3, [sp, #32] + 1c83c: e9dd 2312 ldrd r2, r3, [sp, #72] ; 0x48 + 1c840: ea4a 1adb orr.w sl, sl, fp, lsr #7 + 1c844: f8cd a158 str.w sl, [sp, #344] ; 0x158 + 1c848: ea4f 6a4b mov.w sl, fp, lsl #25 + 1c84c: f8dd b038 ldr.w fp, [sp, #56] ; 0x38 + 1c850: 4010 ands r0, r2 + 1c852: ea4a 1adb orr.w sl, sl, fp, lsr #7 + 1c856: f8cd a15c str.w sl, [sp, #348] ; 0x15c + 1c85a: e9dd ab08 ldrd sl, fp, [sp, #32] + 1c85e: eb14 040a adds.w r4, r4, sl + 1c862: eb45 050b adc.w r5, r5, fp + 1c866: 4019 ands r1, r3 + 1c868: f50d 7bac add.w fp, sp, #344 ; 0x158 + 1c86c: e9dd 230e ldrd r2, r3, [sp, #56] ; 0x38 + 1c870: ea02 0208 and.w r2, r2, r8 + 1c874: e9db ab00 ldrd sl, fp, [fp] + 1c878: 4302 orrs r2, r0 + 1c87a: ea03 0309 and.w r3, r3, r9 + 1c87e: ea86 060a eor.w r6, r6, sl + 1c882: ea87 070b eor.w r7, r7, fp + 1c886: e9dd ab06 ldrd sl, fp, [sp, #24] + 1c88a: eb1a 0a04 adds.w sl, sl, r4 + 1c88e: eb4b 0b05 adc.w fp, fp, r5 + 1c892: 430b orrs r3, r1 + 1c894: 18b6 adds r6, r6, r2 + 1c896: e9cd ab08 strd sl, fp, [sp, #32] + 1c89a: e95c 0104 ldrd r0, r1, [ip, #-16] + 1c89e: 415f adcs r7, r3 + 1c8a0: eb16 0a04 adds.w sl, r6, r4 + 1c8a4: eb47 0b05 adc.w fp, r7, r5 + 1c8a8: e95e 2302 ldrd r2, r3, [lr, #-8] + 1c8ac: e9dd 450a ldrd r4, r5, [sp, #40] ; 0x28 + 1c8b0: e9cd 2318 strd r2, r3, [sp, #96] ; 0x60 + 1c8b4: e9dd 2310 ldrd r2, r3, [sp, #64] ; 0x40 + 1c8b8: e95e 6704 ldrd r6, r7, [lr, #-16] + 1c8bc: 4062 eors r2, r4 + 1c8be: 406b eors r3, r5 + 1c8c0: 9c08 ldr r4, [sp, #32] + 1c8c2: 9d09 ldr r5, [sp, #36] ; 0x24 + 1c8c4: e9cd ab06 strd sl, fp, [sp, #24] + 1c8c8: e9dd ab08 ldrd sl, fp, [sp, #32] + 1c8cc: 1836 adds r6, r6, r0 + 1c8ce: 414f adcs r7, r1 + 1c8d0: ea02 020a and.w r2, r2, sl + 1c8d4: e9dd 010e ldrd r0, r1, [sp, #56] ; 0x38 + 1c8d8: ea03 030b and.w r3, r3, fp + 1c8dc: e9dd ab06 ldrd sl, fp, [sp, #24] + 1c8e0: ea4a 0a00 orr.w sl, sl, r0 + 1c8e4: ea4b 0b01 orr.w fp, fp, r1 + 1c8e8: 4628 mov r0, r5 + 1c8ea: 0ca1 lsrs r1, r4, #18 + 1c8ec: ea41 3185 orr.w r1, r1, r5, lsl #14 + 1c8f0: 9158 str r1, [sp, #352] ; 0x160 + 1c8f2: 0ca9 lsrs r1, r5, #18 + 1c8f4: 4625 mov r5, r4 + 1c8f6: ea41 3184 orr.w r1, r1, r4, lsl #14 + 1c8fa: 9159 str r1, [sp, #356] ; 0x164 + 1c8fc: 0ba1 lsrs r1, r4, #14 + 1c8fe: ea41 4180 orr.w r1, r1, r0, lsl #18 + 1c902: 9c07 ldr r4, [sp, #28] + 1c904: 915a str r1, [sp, #360] ; 0x168 + 1c906: 0b81 lsrs r1, r0, #14 + 1c908: 9806 ldr r0, [sp, #24] + 1c90a: ea41 4185 orr.w r1, r1, r5, lsl #18 + 1c90e: 915b str r1, [sp, #364] ; 0x16c + 1c910: 4625 mov r5, r4 + 1c912: 0781 lsls r1, r0, #30 + 1c914: ea41 0194 orr.w r1, r1, r4, lsr #2 + 1c918: 915e str r1, [sp, #376] ; 0x178 + 1c91a: 07a1 lsls r1, r4, #30 + 1c91c: 4604 mov r4, r0 + 1c91e: ea41 0190 orr.w r1, r1, r0, lsr #2 + 1c922: 915f str r1, [sp, #380] ; 0x17c + 1c924: 0f01 lsrs r1, r0, #28 + 1c926: ea41 1105 orr.w r1, r1, r5, lsl #4 + 1c92a: 9160 str r1, [sp, #384] ; 0x180 + 1c92c: 0f29 lsrs r1, r5, #28 + 1c92e: ea41 1104 orr.w r1, r1, r4, lsl #4 + 1c932: 9161 str r1, [sp, #388] ; 0x184 + 1c934: e9dd 010c ldrd r0, r1, [sp, #48] ; 0x30 + 1c938: 1836 adds r6, r6, r0 + 1c93a: 414f adcs r7, r1 + 1c93c: e9dd 450a ldrd r4, r5, [sp, #40] ; 0x28 + 1c940: a958 add r1, sp, #352 ; 0x160 + 1c942: 4054 eors r4, r2 + 1c944: 405d eors r5, r3 + 1c946: ea0a 0208 and.w r2, sl, r8 + 1c94a: ea0b 0309 and.w r3, fp, r9 + 1c94e: a85a add r0, sp, #360 ; 0x168 + 1c950: f50d 7bbc add.w fp, sp, #376 ; 0x178 + 1c954: f50d 7ac0 add.w sl, sp, #384 ; 0x180 + 1c958: e9cd 450c strd r4, r5, [sp, #48] ; 0x30 + 1c95c: e9d1 4500 ldrd r4, r5, [r1] + 1c960: c803 ldmia r0, {r0, r1} + 1c962: e9cd 2314 strd r2, r3, [sp, #80] ; 0x50 + 1c966: e9db 2300 ldrd r2, r3, [fp] + 1c96a: e89a 0c00 ldmia.w sl, {sl, fp} + 1c96e: 4044 eors r4, r0 + 1c970: 404d eors r5, r1 + 1c972: ea82 020a eor.w r2, r2, sl + 1c976: e9dd 0106 ldrd r0, r1, [sp, #24] + 1c97a: ea83 030b eor.w r3, r3, fp + 1c97e: e9dd ab0e ldrd sl, fp, [sp, #56] ; 0x38 + 1c982: ea01 010b and.w r1, r1, fp + 1c986: f8dd b020 ldr.w fp, [sp, #32] + 1c98a: ea00 000a and.w r0, r0, sl + 1c98e: ea4f 5acb mov.w sl, fp, lsl #23 + 1c992: f8dd b024 ldr.w fp, [sp, #36] ; 0x24 + 1c996: ea4a 2a5b orr.w sl, sl, fp, lsr #9 + 1c99a: f8cd a170 str.w sl, [sp, #368] ; 0x170 + 1c99e: ea4f 5acb mov.w sl, fp, lsl #23 + 1c9a2: f8dd b020 ldr.w fp, [sp, #32] + 1c9a6: ea4a 2a5b orr.w sl, sl, fp, lsr #9 + 1c9aa: f8dd b018 ldr.w fp, [sp, #24] + 1c9ae: f8cd a174 str.w sl, [sp, #372] ; 0x174 + 1c9b2: ea4f 6a4b mov.w sl, fp, lsl #25 + 1c9b6: f8dd b01c ldr.w fp, [sp, #28] + 1c9ba: ea4a 1adb orr.w sl, sl, fp, lsr #7 + 1c9be: f8cd a188 str.w sl, [sp, #392] ; 0x188 + 1c9c2: ea4f 6a4b mov.w sl, fp, lsl #25 + 1c9c6: f8dd b018 ldr.w fp, [sp, #24] + 1c9ca: ea4a 1adb orr.w sl, sl, fp, lsr #7 + 1c9ce: f8cd a18c str.w sl, [sp, #396] ; 0x18c + 1c9d2: e9dd ab0c ldrd sl, fp, [sp, #48] ; 0x30 + 1c9d6: eb16 060a adds.w r6, r6, sl + 1c9da: eb47 070b adc.w r7, r7, fp + 1c9de: f50d 7bb8 add.w fp, sp, #368 ; 0x170 + 1c9e2: e9db ab00 ldrd sl, fp, [fp] + 1c9e6: ea84 040a eor.w r4, r4, sl + 1c9ea: ea85 050b eor.w r5, r5, fp + 1c9ee: f50d 7bc4 add.w fp, sp, #392 ; 0x188 + 1c9f2: 19a4 adds r4, r4, r6 + 1c9f4: e9db ab00 ldrd sl, fp, [fp] + 1c9f8: ea82 020a eor.w r2, r2, sl + 1c9fc: ea83 030b eor.w r3, r3, fp + 1ca00: e9dd ab14 ldrd sl, fp, [sp, #80] ; 0x50 + 1ca04: ea40 000a orr.w r0, r0, sl + 1ca08: 417d adcs r5, r7 + 1ca0a: ea41 010b orr.w r1, r1, fp + 1ca0e: 1812 adds r2, r2, r0 + 1ca10: e95c 6702 ldrd r6, r7, [ip, #-8] + 1ca14: 414b adcs r3, r1 + 1ca16: e8fe 0110 ldrd r0, r1, [lr], #64 ; 0x40 + 1ca1a: e9cd 0116 strd r0, r1, [sp, #88] ; 0x58 + 1ca1e: e9dd ab12 ldrd sl, fp, [sp, #72] ; 0x48 + 1ca22: eb1a 0a04 adds.w sl, sl, r4 + 1ca26: eb4b 0b05 adc.w fp, fp, r5 + 1ca2a: 1910 adds r0, r2, r4 + 1ca2c: eb43 0105 adc.w r1, r3, r5 + 1ca30: e9cd ab0c strd sl, fp, [sp, #48] ; 0x30 + 1ca34: e9dd 2310 ldrd r2, r3, [sp, #64] ; 0x40 + 1ca38: e9dd 4506 ldrd r4, r5, [sp, #24] + 1ca3c: e9cd 0112 strd r0, r1, [sp, #72] ; 0x48 + 1ca40: e9dd 0108 ldrd r0, r1, [sp, #32] + 1ca44: 4050 eors r0, r2 + 1ca46: 4059 eors r1, r3 + 1ca48: e9dd 2318 ldrd r2, r3, [sp, #96] ; 0x60 + 1ca4c: 1992 adds r2, r2, r6 + 1ca4e: 417b adcs r3, r7 + 1ca50: ea00 000a and.w r0, r0, sl + 1ca54: e9dd 6712 ldrd r6, r7, [sp, #72] ; 0x48 + 1ca58: 4326 orrs r6, r4 + 1ca5a: ea4f 449a mov.w r4, sl, lsr #18 + 1ca5e: f8dd a030 ldr.w sl, [sp, #48] ; 0x30 + 1ca62: ea01 010b and.w r1, r1, fp + 1ca66: ea44 348b orr.w r4, r4, fp, lsl #14 + 1ca6a: 46d3 mov fp, sl + 1ca6c: 432f orrs r7, r5 + 1ca6e: 9d0d ldr r5, [sp, #52] ; 0x34 + 1ca70: 9464 str r4, [sp, #400] ; 0x190 + 1ca72: 0cac lsrs r4, r5, #18 + 1ca74: ea44 348a orr.w r4, r4, sl, lsl #14 + 1ca78: 9465 str r4, [sp, #404] ; 0x194 + 1ca7a: ea4f 349a mov.w r4, sl, lsr #14 + 1ca7e: ea44 4485 orr.w r4, r4, r5, lsl #18 + 1ca82: f8dd a04c ldr.w sl, [sp, #76] ; 0x4c + 1ca86: 9466 str r4, [sp, #408] ; 0x198 + 1ca88: 0bac lsrs r4, r5, #14 + 1ca8a: 9d12 ldr r5, [sp, #72] ; 0x48 + 1ca8c: ea44 448b orr.w r4, r4, fp, lsl #18 + 1ca90: 9467 str r4, [sp, #412] ; 0x19c + 1ca92: 46d3 mov fp, sl + 1ca94: 07ac lsls r4, r5, #30 + 1ca96: ea44 049a orr.w r4, r4, sl, lsr #2 + 1ca9a: 946a str r4, [sp, #424] ; 0x1a8 + 1ca9c: ea4f 748a mov.w r4, sl, lsl #30 + 1caa0: 46aa mov sl, r5 + 1caa2: ea44 0495 orr.w r4, r4, r5, lsr #2 + 1caa6: 946b str r4, [sp, #428] ; 0x1ac + 1caa8: 0f2c lsrs r4, r5, #28 + 1caaa: ea44 140b orr.w r4, r4, fp, lsl #4 + 1caae: 946c str r4, [sp, #432] ; 0x1b0 + 1cab0: ea4f 741b mov.w r4, fp, lsr #28 + 1cab4: ea44 140a orr.w r4, r4, sl, lsl #4 + 1cab8: 946d str r4, [sp, #436] ; 0x1b4 + 1caba: e9dd ab10 ldrd sl, fp, [sp, #64] ; 0x40 + 1cabe: e9dd 450a ldrd r4, r5, [sp, #40] ; 0x28 + 1cac2: ea8a 0a00 eor.w sl, sl, r0 + 1cac6: 1912 adds r2, r2, r4 + 1cac8: ea8b 0b01 eor.w fp, fp, r1 + 1cacc: 416b adcs r3, r5 + 1cace: e9cd ab0a strd sl, fp, [sp, #40] ; 0x28 + 1cad2: e9dd ab0e ldrd sl, fp, [sp, #56] ; 0x38 + 1cad6: ad64 add r5, sp, #400 ; 0x190 + 1cad8: ea0a 0a06 and.w sl, sl, r6 + 1cadc: ea0b 0b07 and.w fp, fp, r7 + 1cae0: ac66 add r4, sp, #408 ; 0x198 + 1cae2: af6a add r7, sp, #424 ; 0x1a8 + 1cae4: ae6c add r6, sp, #432 ; 0x1b0 + 1cae6: e9d5 0100 ldrd r0, r1, [r5] + 1caea: e9cd ab14 strd sl, fp, [sp, #80] ; 0x50 + 1caee: cc30 ldmia r4, {r4, r5} + 1caf0: e9dd ab06 ldrd sl, fp, [sp, #24] + 1caf4: 4060 eors r0, r4 + 1caf6: 4069 eors r1, r5 + 1caf8: e9d7 4500 ldrd r4, r5, [r7] + 1cafc: cec0 ldmia r6, {r6, r7} + 1cafe: 4074 eors r4, r6 + 1cb00: 407d eors r5, r7 + 1cb02: e9dd 6712 ldrd r6, r7, [sp, #72] ; 0x48 + 1cb06: ea07 070b and.w r7, r7, fp + 1cb0a: f8dd b030 ldr.w fp, [sp, #48] ; 0x30 + 1cb0e: ea06 060a and.w r6, r6, sl + 1cb12: ea4f 5acb mov.w sl, fp, lsl #23 + 1cb16: f8dd b034 ldr.w fp, [sp, #52] ; 0x34 + 1cb1a: ea4a 2a5b orr.w sl, sl, fp, lsr #9 + 1cb1e: f8cd a1a0 str.w sl, [sp, #416] ; 0x1a0 + 1cb22: ea4f 5acb mov.w sl, fp, lsl #23 + 1cb26: f8dd b030 ldr.w fp, [sp, #48] ; 0x30 + 1cb2a: ea4a 2a5b orr.w sl, sl, fp, lsr #9 + 1cb2e: f8dd b048 ldr.w fp, [sp, #72] ; 0x48 + 1cb32: f8cd a1a4 str.w sl, [sp, #420] ; 0x1a4 + 1cb36: ea4f 6a4b mov.w sl, fp, lsl #25 + 1cb3a: f8dd b04c ldr.w fp, [sp, #76] ; 0x4c + 1cb3e: ea4a 1adb orr.w sl, sl, fp, lsr #7 + 1cb42: f8cd a1b8 str.w sl, [sp, #440] ; 0x1b8 + 1cb46: ea4f 6a4b mov.w sl, fp, lsl #25 + 1cb4a: f8dd b048 ldr.w fp, [sp, #72] ; 0x48 + 1cb4e: ea4a 1adb orr.w sl, sl, fp, lsr #7 + 1cb52: f8cd a1bc str.w sl, [sp, #444] ; 0x1bc + 1cb56: e9dd ab0a ldrd sl, fp, [sp, #40] ; 0x28 + 1cb5a: eb12 020a adds.w r2, r2, sl + 1cb5e: eb43 030b adc.w r3, r3, fp + 1cb62: f50d 7bd0 add.w fp, sp, #416 ; 0x1a0 + 1cb66: e9db ab00 ldrd sl, fp, [fp] + 1cb6a: ea80 000a eor.w r0, r0, sl + 1cb6e: ea81 010b eor.w r1, r1, fp + 1cb72: f50d 7bdc add.w fp, sp, #440 ; 0x1b8 + 1cb76: 1812 adds r2, r2, r0 + 1cb78: e9db ab00 ldrd sl, fp, [fp] + 1cb7c: ea84 040a eor.w r4, r4, sl + 1cb80: ea85 050b eor.w r5, r5, fp + 1cb84: e9dd ab14 ldrd sl, fp, [sp, #80] ; 0x50 + 1cb88: ea46 060a orr.w r6, r6, sl + 1cb8c: 414b adcs r3, r1 + 1cb8e: ea47 070b orr.w r7, r7, fp + 1cb92: 19a4 adds r4, r4, r6 + 1cb94: 417d adcs r5, r7 + 1cb96: eb12 0608 adds.w r6, r2, r8 + 1cb9a: eb43 0709 adc.w r7, r3, r9 + 1cb9e: e9cd 670a strd r6, r7, [sp, #40] ; 0x28 + 1cba2: e8fc 0110 ldrd r0, r1, [ip], #64 ; 0x40 + 1cba6: e9dd ab08 ldrd sl, fp, [sp, #32] + 1cbaa: eb14 0802 adds.w r8, r4, r2 + 1cbae: 9c0a ldr r4, [sp, #40] ; 0x28 + 1cbb0: eb45 0903 adc.w r9, r5, r3 + 1cbb4: e9dd 6716 ldrd r6, r7, [sp, #88] ; 0x58 + 1cbb8: 9d0b ldr r5, [sp, #44] ; 0x2c + 1cbba: e9dd 230c ldrd r2, r3, [sp, #48] ; 0x30 + 1cbbe: 1836 adds r6, r6, r0 + 1cbc0: ea82 020a eor.w r2, r2, sl + 1cbc4: ea83 030b eor.w r3, r3, fp + 1cbc8: 414f adcs r7, r1 + 1cbca: e9dd 010a ldrd r0, r1, [sp, #40] ; 0x28 + 1cbce: 4002 ands r2, r0 + 1cbd0: 400b ands r3, r1 + 1cbd2: 0c81 lsrs r1, r0, #18 + 1cbd4: 0ba0 lsrs r0, r4, #14 + 1cbd6: ea4f 7488 mov.w r4, r8, lsl #30 + 1cbda: ea41 3185 orr.w r1, r1, r5, lsl #14 + 1cbde: ea44 0499 orr.w r4, r4, r9, lsr #2 + 1cbe2: 9170 str r1, [sp, #448] ; 0x1c0 + 1cbe4: ea40 4085 orr.w r0, r0, r5, lsl #18 + 1cbe8: 0ca9 lsrs r1, r5, #18 + 1cbea: 9476 str r4, [sp, #472] ; 0x1d8 + 1cbec: 0bac lsrs r4, r5, #14 + 1cbee: 9d0a ldr r5, [sp, #40] ; 0x28 + 1cbf0: 9072 str r0, [sp, #456] ; 0x1c8 + 1cbf2: ea4f 7018 mov.w r0, r8, lsr #28 + 1cbf6: ea41 3185 orr.w r1, r1, r5, lsl #14 + 1cbfa: ea40 1009 orr.w r0, r0, r9, lsl #4 + 1cbfe: 9171 str r1, [sp, #452] ; 0x1c4 + 1cc00: 9078 str r0, [sp, #480] ; 0x1e0 + 1cc02: ea4f 7119 mov.w r1, r9, lsr #28 + 1cc06: ea4f 7089 mov.w r0, r9, lsl #30 + 1cc0a: ea40 0098 orr.w r0, r0, r8, lsr #2 + 1cc0e: ea41 1108 orr.w r1, r1, r8, lsl #4 + 1cc12: e9dd ab12 ldrd sl, fp, [sp, #72] ; 0x48 + 1cc16: ea44 4485 orr.w r4, r4, r5, lsl #18 + 1cc1a: ea4a 0a08 orr.w sl, sl, r8 + 1cc1e: ea4b 0b09 orr.w fp, fp, r9 + 1cc22: 9077 str r0, [sp, #476] ; 0x1dc + 1cc24: 9179 str r1, [sp, #484] ; 0x1e4 + 1cc26: e9dd 0110 ldrd r0, r1, [sp, #64] ; 0x40 + 1cc2a: 1836 adds r6, r6, r0 + 1cc2c: 9473 str r4, [sp, #460] ; 0x1cc + 1cc2e: 414f adcs r7, r1 + 1cc30: e9dd 4508 ldrd r4, r5, [sp, #32] + 1cc34: a970 add r1, sp, #448 ; 0x1c0 + 1cc36: 4054 eors r4, r2 + 1cc38: 405d eors r5, r3 + 1cc3a: a872 add r0, sp, #456 ; 0x1c8 + 1cc3c: e9dd 2306 ldrd r2, r3, [sp, #24] + 1cc40: ea02 020a and.w r2, r2, sl + 1cc44: ea03 030b and.w r3, r3, fp + 1cc48: f50d 7af0 add.w sl, sp, #480 ; 0x1e0 + 1cc4c: f50d 7bec add.w fp, sp, #472 ; 0x1d8 + 1cc50: e9cd 4510 strd r4, r5, [sp, #64] ; 0x40 + 1cc54: e9d1 4500 ldrd r4, r5, [r1] + 1cc58: c803 ldmia r0, {r0, r1} + 1cc5a: e9cd 2314 strd r2, r3, [sp, #80] ; 0x50 + 1cc5e: e9db 2300 ldrd r2, r3, [fp] + 1cc62: e89a 0c00 ldmia.w sl, {sl, fp} + 1cc66: ea83 030b eor.w r3, r3, fp + 1cc6a: f8dd b028 ldr.w fp, [sp, #40] ; 0x28 + 1cc6e: ea82 020a eor.w r2, r2, sl + 1cc72: ea4f 5acb mov.w sl, fp, lsl #23 + 1cc76: f8dd b02c ldr.w fp, [sp, #44] ; 0x2c + 1cc7a: 4044 eors r4, r0 + 1cc7c: ea4a 2a5b orr.w sl, sl, fp, lsr #9 + 1cc80: f8cd a1d0 str.w sl, [sp, #464] ; 0x1d0 + 1cc84: ea4f 5acb mov.w sl, fp, lsl #23 + 1cc88: f8dd b028 ldr.w fp, [sp, #40] ; 0x28 + 1cc8c: 404d eors r5, r1 + 1cc8e: ea4a 2a5b orr.w sl, sl, fp, lsr #9 + 1cc92: f8cd a1d4 str.w sl, [sp, #468] ; 0x1d4 + 1cc96: ea4f 6a48 mov.w sl, r8, lsl #25 + 1cc9a: ea4a 1ad9 orr.w sl, sl, r9, lsr #7 + 1cc9e: f8cd a1e8 str.w sl, [sp, #488] ; 0x1e8 + 1cca2: ea4f 6a49 mov.w sl, r9, lsl #25 + 1cca6: ea4a 1ad8 orr.w sl, sl, r8, lsr #7 + 1ccaa: f8cd a1ec str.w sl, [sp, #492] ; 0x1ec + 1ccae: e9dd ab10 ldrd sl, fp, [sp, #64] ; 0x40 + 1ccb2: eb16 060a adds.w r6, r6, sl + 1ccb6: eb47 070b adc.w r7, r7, fp + 1ccba: f50d 7be8 add.w fp, sp, #464 ; 0x1d0 + 1ccbe: e9db ab00 ldrd sl, fp, [fp] + 1ccc2: e9dd 0112 ldrd r0, r1, [sp, #72] ; 0x48 + 1ccc6: ea84 040a eor.w r4, r4, sl + 1ccca: ea85 050b eor.w r5, r5, fp + 1ccce: ea00 0008 and.w r0, r0, r8 + 1ccd2: f50d 7bf4 add.w fp, sp, #488 ; 0x1e8 + 1ccd6: 19a4 adds r4, r4, r6 + 1ccd8: e9db ab00 ldrd sl, fp, [fp] + 1ccdc: ea01 0109 and.w r1, r1, r9 + 1cce0: ea82 020a eor.w r2, r2, sl + 1cce4: ea83 030b eor.w r3, r3, fp + 1cce8: e9dd ab14 ldrd sl, fp, [sp, #80] ; 0x50 + 1ccec: ea40 000a orr.w r0, r0, sl + 1ccf0: ea41 010b orr.w r1, r1, fp + 1ccf4: 417d adcs r5, r7 + 1ccf6: 1812 adds r2, r2, r0 + 1ccf8: 414b adcs r3, r1 + 1ccfa: e9dd 010e ldrd r0, r1, [sp, #56] ; 0x38 + 1ccfe: 1900 adds r0, r0, r4 + 1cd00: 4169 adcs r1, r5 + 1cd02: e9cd 010e strd r0, r1, [sp, #56] ; 0x38 + 1cd06: 4905 ldr r1, [pc, #20] ; (1cd1c ) + 1cd08: eb12 0a04 adds.w sl, r2, r4 + 1cd0c: eb43 0b05 adc.w fp, r3, r5 + 1cd10: 458c cmp ip, r1 + 1cd12: f47f aa94 bne.w 1c23e + 1cd16: e003 b.n 1cd20 + 1cd18: 000363f0 .word 0x000363f0 + 1cd1c: 00036670 .word 0x00036670 + 1cd20: e9dd 451a ldrd r4, r5, [sp, #104] ; 0x68 + 1cd24: 4642 mov r2, r8 + 1cd26: 46d0 mov r8, sl + 1cd28: 464b mov r3, r9 + 1cd2a: 46d9 mov r9, fp + 1cd2c: e9dd ab12 ldrd sl, fp, [sp, #72] ; 0x48 + 1cd30: eb14 0408 adds.w r4, r4, r8 + 1cd34: f50d 78fc add.w r8, sp, #504 ; 0x1f8 + 1cd38: eb45 0509 adc.w r5, r5, r9 + 1cd3c: e9d8 6700 ldrd r6, r7, [r8] + 1cd40: 18b6 adds r6, r6, r2 + 1cd42: aa80 add r2, sp, #512 ; 0x200 + 1cd44: e9cd 4504 strd r4, r5, [sp, #16] + 1cd48: e9d2 0100 ldrd r0, r1, [r2] + 1cd4c: 415f adcs r7, r3 + 1cd4e: ad82 add r5, sp, #520 ; 0x208 + 1cd50: eb10 000a adds.w r0, r0, sl + 1cd54: e9cd 6702 strd r6, r7, [sp, #8] + 1cd58: e9d5 4500 ldrd r4, r5, [r5] + 1cd5c: eb41 010b adc.w r1, r1, fp + 1cd60: af84 add r7, sp, #528 ; 0x210 + 1cd62: e9dd ab06 ldrd sl, fp, [sp, #24] + 1cd66: eb1a 0a04 adds.w sl, sl, r4 + 1cd6a: eb4b 0b05 adc.w fp, fp, r5 + 1cd6e: e9d7 6700 ldrd r6, r7, [r7] + 1cd72: e9cd 0100 strd r0, r1, [sp] + 1cd76: e9dd 010e ldrd r0, r1, [sp, #56] ; 0x38 + 1cd7a: e9dd 450a ldrd r4, r5, [sp, #40] ; 0x28 + 1cd7e: 1980 adds r0, r0, r6 + 1cd80: f50d 7906 add.w r9, sp, #536 ; 0x218 + 1cd84: 4179 adcs r1, r7 + 1cd86: e9d9 8900 ldrd r8, r9, [r9] + 1cd8a: ab88 add r3, sp, #544 ; 0x220 + 1cd8c: eb14 0408 adds.w r4, r4, r8 + 1cd90: e9d3 2300 ldrd r2, r3, [r3] + 1cd94: eb45 0509 adc.w r5, r5, r9 + 1cd98: e9dd 670c ldrd r6, r7, [sp, #48] ; 0x30 + 1cd9c: 18b6 adds r6, r6, r2 + 1cd9e: 415f adcs r7, r3 + 1cda0: ab8a add r3, sp, #552 ; 0x228 + 1cda2: f8dd e1f4 ldr.w lr, [sp, #500] ; 0x1f4 + 1cda6: e9d3 2300 ldrd r2, r3, [r3] + 1cdaa: e9dd 8908 ldrd r8, r9, [sp, #32] + 1cdae: eb18 0802 adds.w r8, r8, r2 + 1cdb2: eb49 0903 adc.w r9, r9, r3 + 1cdb6: e9ce ab0a strd sl, fp, [lr, #40] ; 0x28 + 1cdba: e9dd 2304 ldrd r2, r3, [sp, #16] + 1cdbe: e9ce 010c strd r0, r1, [lr, #48] ; 0x30 + 1cdc2: e9ce 2304 strd r2, r3, [lr, #16] + 1cdc6: e9dd 2302 ldrd r2, r3, [sp, #8] + 1cdca: e9ce 450e strd r4, r5, [lr, #56] ; 0x38 + 1cdce: e9ce 2306 strd r2, r3, [lr, #24] + 1cdd2: e9dd 2300 ldrd r2, r3, [sp] + 1cdd6: e9ce 6710 strd r6, r7, [lr, #64] ; 0x40 + 1cdda: e9ce 2308 strd r2, r3, [lr, #32] + 1cdde: e9ce 8912 strd r8, r9, [lr, #72] ; 0x48 + 1cde2: f20d 4db4 addw sp, sp, #1204 ; 0x4b4 + 1cde6: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 1cdea: bf00 nop + +0001cdec : + 1cdec: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 1cdf0: e9d0 8900 ldrd r8, r9, [r0] + 1cdf4: 2500 movs r5, #0 + 1cdf6: eb12 0608 adds.w r6, r2, r8 + 1cdfa: eb45 0709 adc.w r7, r5, r9 + 1cdfe: 42af cmp r7, r5 + 1ce00: f008 087f and.w r8, r8, #127 ; 0x7f + 1ce04: bf08 it eq + 1ce06: 4296 cmpeq r6, r2 + 1ce08: b083 sub sp, #12 + 1ce0a: 4693 mov fp, r2 + 1ce0c: 4682 mov sl, r0 + 1ce0e: 4689 mov r9, r1 + 1ce10: e9c0 6700 strd r6, r7, [r0] + 1ce14: f1c8 0380 rsb r3, r8, #128 ; 0x80 + 1ce18: d208 bcs.n 1ce2c + 1ce1a: f100 0108 add.w r1, r0, #8 + 1ce1e: e9d1 0100 ldrd r0, r1, [r1] + 1ce22: 3001 adds r0, #1 + 1ce24: f141 0100 adc.w r1, r1, #0 + 1ce28: e9ca 0102 strd r0, r1, [sl, #8] + 1ce2c: 455b cmp r3, fp + 1ce2e: bf8c ite hi + 1ce30: 2200 movhi r2, #0 + 1ce32: 2201 movls r2, #1 + 1ce34: f1b8 0f00 cmp.w r8, #0 + 1ce38: bf08 it eq + 1ce3a: 2200 moveq r2, #0 + 1ce3c: bb2a cbnz r2, 1ce8a + 1ce3e: f1bb 0f7f cmp.w fp, #127 ; 0x7f + 1ce42: d912 bls.n 1ce6a + 1ce44: 465d mov r5, fp + 1ce46: 464c mov r4, r9 + 1ce48: 4621 mov r1, r4 + 1ce4a: 3d80 subs r5, #128 ; 0x80 + 1ce4c: 4650 mov r0, sl + 1ce4e: f7ff f8b7 bl 1bfc0 + 1ce52: 2d7f cmp r5, #127 ; 0x7f + 1ce54: f104 0480 add.w r4, r4, #128 ; 0x80 + 1ce58: d8f6 bhi.n 1ce48 + 1ce5a: f1ab 0380 sub.w r3, fp, #128 ; 0x80 + 1ce5e: f023 037f bic.w r3, r3, #127 ; 0x7f + 1ce62: 3380 adds r3, #128 ; 0x80 + 1ce64: 4499 add r9, r3 + 1ce66: f00b 0b7f and.w fp, fp, #127 ; 0x7f + 1ce6a: f1bb 0f00 cmp.w fp, #0 + 1ce6e: d102 bne.n 1ce76 + 1ce70: b003 add sp, #12 + 1ce72: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 1ce76: 4649 mov r1, r9 + 1ce78: 465a mov r2, fp + 1ce7a: f108 0050 add.w r0, r8, #80 ; 0x50 + 1ce7e: 4450 add r0, sl + 1ce80: b003 add sp, #12 + 1ce82: e8bd 4ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 1ce86: f7f2 baed b.w f464 <_memcpy> + 1ce8a: f108 0050 add.w r0, r8, #80 ; 0x50 + 1ce8e: 4649 mov r1, r9 + 1ce90: 461a mov r2, r3 + 1ce92: 4450 add r0, sl + 1ce94: 9301 str r3, [sp, #4] + 1ce96: f7f2 fae5 bl f464 <_memcpy> + 1ce9a: 4650 mov r0, sl + 1ce9c: f10a 0150 add.w r1, sl, #80 ; 0x50 + 1cea0: f7ff f88e bl 1bfc0 + 1cea4: 9b01 ldr r3, [sp, #4] + 1cea6: f04f 0800 mov.w r8, #0 + 1ceaa: ebc3 0b0b rsb fp, r3, fp + 1ceae: 4499 add r9, r3 + 1ceb0: e7c5 b.n 1ce3e + 1ceb2: bf00 nop + +0001ceb4 : + 1ceb4: 2200 movs r2, #0 + 1ceb6: 2300 movs r3, #0 + 1ceb8: e92d 0ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp} + 1cebc: e9c0 2300 strd r2, r3, [r0] + 1cec0: e9c0 2302 strd r2, r3, [r0, #8] + 1cec4: 2900 cmp r1, #0 + 1cec6: d02e beq.n 1cf26 + 1cec8: a32f add r3, pc, #188 ; (adr r3, 1cf88 ) + 1ceca: e9d3 2300 ldrd r2, r3, [r3] + 1cece: a530 add r5, pc, #192 ; (adr r5, 1cf90 ) + 1ced0: e9d5 4500 ldrd r4, r5, [r5] + 1ced4: f20f 0bc0 addw fp, pc, #192 ; 0xc0 + 1ced8: e9db ab00 ldrd sl, fp, [fp] + 1cedc: f20f 09c0 addw r9, pc, #192 ; 0xc0 + 1cee0: e9d9 8900 ldrd r8, r9, [r9] + 1cee4: a730 add r7, pc, #192 ; (adr r7, 1cfa8 ) + 1cee6: e9d7 6700 ldrd r6, r7, [r7] + 1ceea: e9c0 2304 strd r2, r3, [r0, #16] + 1ceee: a330 add r3, pc, #192 ; (adr r3, 1cfb0 ) + 1cef0: e9d3 2300 ldrd r2, r3, [r3] + 1cef4: e9c0 4506 strd r4, r5, [r0, #24] + 1cef8: a52f add r5, pc, #188 ; (adr r5, 1cfb8 ) + 1cefa: e9d5 4500 ldrd r4, r5, [r5] + 1cefe: e9c0 2308 strd r2, r3, [r0, #32] + 1cf02: a32f add r3, pc, #188 ; (adr r3, 1cfc0 ) + 1cf04: e9d3 2300 ldrd r2, r3, [r3] + 1cf08: e9c0 ab0a strd sl, fp, [r0, #40] ; 0x28 + 1cf0c: e9c0 890c strd r8, r9, [r0, #48] ; 0x30 + 1cf10: e9c0 670e strd r6, r7, [r0, #56] ; 0x38 + 1cf14: e9c0 4510 strd r4, r5, [r0, #64] ; 0x40 + 1cf18: e8bd 0ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp} + 1cf1c: e9c0 2312 strd r2, r3, [r0, #72] ; 0x48 + 1cf20: f8c0 11d0 str.w r1, [r0, #464] ; 0x1d0 + 1cf24: 4770 bx lr + 1cf26: a728 add r7, pc, #160 ; (adr r7, 1cfc8 ) + 1cf28: e9d7 6700 ldrd r6, r7, [r7] + 1cf2c: a528 add r5, pc, #160 ; (adr r5, 1cfd0 ) + 1cf2e: e9d5 4500 ldrd r4, r5, [r5] + 1cf32: a329 add r3, pc, #164 ; (adr r3, 1cfd8 ) + 1cf34: e9d3 2300 ldrd r2, r3, [r3] + 1cf38: f20f 09a4 addw r9, pc, #164 ; 0xa4 + 1cf3c: e9d9 8900 ldrd r8, r9, [r9] + 1cf40: f20f 0ba4 addw fp, pc, #164 ; 0xa4 + 1cf44: e9db ab00 ldrd sl, fp, [fp] + 1cf48: e9c0 6704 strd r6, r7, [r0, #16] + 1cf4c: a728 add r7, pc, #160 ; (adr r7, 1cff0 ) + 1cf4e: e9d7 6700 ldrd r6, r7, [r7] + 1cf52: e9c0 4506 strd r4, r5, [r0, #24] + 1cf56: a528 add r5, pc, #160 ; (adr r5, 1cff8 ) + 1cf58: e9d5 4500 ldrd r4, r5, [r5] + 1cf5c: e9c0 2308 strd r2, r3, [r0, #32] + 1cf60: a327 add r3, pc, #156 ; (adr r3, 1d000 ) + 1cf62: e9d3 2300 ldrd r2, r3, [r3] + 1cf66: e9c0 890a strd r8, r9, [r0, #40] ; 0x28 + 1cf6a: e9c0 ab0c strd sl, fp, [r0, #48] ; 0x30 + 1cf6e: e9c0 6710 strd r6, r7, [r0, #64] ; 0x40 + 1cf72: e9c0 4512 strd r4, r5, [r0, #72] ; 0x48 + 1cf76: e8bd 0ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp} + 1cf7a: e9c0 230e strd r2, r3, [r0, #56] ; 0x38 + 1cf7e: f8c0 11d0 str.w r1, [r0, #464] ; 0x1d0 + 1cf82: 4770 bx lr + 1cf84: f3af 8000 nop.w + 1cf88: c1059ed8 .word 0xc1059ed8 + 1cf8c: cbbb9d5d .word 0xcbbb9d5d + 1cf90: 367cd507 .word 0x367cd507 + 1cf94: 629a292a .word 0x629a292a + 1cf98: f70e5939 .word 0xf70e5939 + 1cf9c: 152fecd8 .word 0x152fecd8 + 1cfa0: ffc00b31 .word 0xffc00b31 + 1cfa4: 67332667 .word 0x67332667 + 1cfa8: 68581511 .word 0x68581511 + 1cfac: 8eb44a87 .word 0x8eb44a87 + 1cfb0: 3070dd17 .word 0x3070dd17 + 1cfb4: 9159015a .word 0x9159015a + 1cfb8: 64f98fa7 .word 0x64f98fa7 + 1cfbc: db0c2e0d .word 0xdb0c2e0d + 1cfc0: befa4fa4 .word 0xbefa4fa4 + 1cfc4: 47b5481d .word 0x47b5481d + 1cfc8: f3bcc908 .word 0xf3bcc908 + 1cfcc: 6a09e667 .word 0x6a09e667 + 1cfd0: 84caa73b .word 0x84caa73b + 1cfd4: bb67ae85 .word 0xbb67ae85 + 1cfd8: fe94f82b .word 0xfe94f82b + 1cfdc: 3c6ef372 .word 0x3c6ef372 + 1cfe0: 5f1d36f1 .word 0x5f1d36f1 + 1cfe4: a54ff53a .word 0xa54ff53a + 1cfe8: ade682d1 .word 0xade682d1 + 1cfec: 510e527f .word 0x510e527f + 1cff0: fb41bd6b .word 0xfb41bd6b + 1cff4: 1f83d9ab .word 0x1f83d9ab + 1cff8: 137e2179 .word 0x137e2179 + 1cffc: 5be0cd19 .word 0x5be0cd19 + 1d000: 2b3e6c1f .word 0x2b3e6c1f + 1d004: 9b05688c .word 0x9b05688c + +0001d008 : + 1d008: b102 cbz r2, 1d00c + 1d00a: e6ef b.n 1cdec + 1d00c: 4770 bx lr + 1d00e: bf00 nop + +0001d010 : + 1d010: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 1d014: 4606 mov r6, r0 + 1d016: 6887 ldr r7, [r0, #8] + 1d018: 68f4 ldr r4, [r6, #12] + 1d01a: 6840 ldr r0, [r0, #4] + 1d01c: 00fa lsls r2, r7, #3 + 1d01e: 00e3 lsls r3, r4, #3 + 1d020: 0f44 lsrs r4, r0, #29 + 1d022: 4314 orrs r4, r2 + 1d024: ea43 7357 orr.w r3, r3, r7, lsr #29 + 1d028: 6832 ldr r2, [r6, #0] + 1d02a: 2500 movs r5, #0 + 1d02c: 431d orrs r5, r3 + 1d02e: 00c3 lsls r3, r0, #3 + 1d030: ea43 7352 orr.w r3, r3, r2, lsr #29 + 1d034: b087 sub sp, #28 + 1d036: 0e1f lsrs r7, r3, #24 + 1d038: 9701 str r7, [sp, #4] + 1d03a: 460f mov r7, r1 + 1d03c: 00d0 lsls r0, r2, #3 + 1d03e: f002 027f and.w r2, r2, #127 ; 0x7f + 1d042: 2a6f cmp r2, #111 ; 0x6f + 1d044: ea4f 4c14 mov.w ip, r4, lsr #16 + 1d048: ea4f 2e14 mov.w lr, r4, lsr #8 + 1d04c: ea4f 4a15 mov.w sl, r5, lsr #16 + 1d050: ea4f 2915 mov.w r9, r5, lsr #8 + 1d054: ea4f 2113 mov.w r1, r3, lsr #8 + 1d058: ea4f 6814 mov.w r8, r4, lsr #24 + 1d05c: f88d 400f strb.w r4, [sp, #15] + 1d060: f88d 3013 strb.w r3, [sp, #19] + 1d064: ea4f 4413 mov.w r4, r3, lsr #16 + 1d068: 9b01 ldr r3, [sp, #4] + 1d06a: bf94 ite ls + 1d06c: f1c2 0270 rsbls r2, r2, #112 ; 0x70 + 1d070: f1c2 02f0 rsbhi r2, r2, #240 ; 0xf0 + 1d074: ea4f 6b15 mov.w fp, r5, lsr #24 + 1d078: f88d 500b strb.w r5, [sp, #11] + 1d07c: f88d a009 strb.w sl, [sp, #9] + 1d080: 0e05 lsrs r5, r0, #24 + 1d082: ea4f 4a10 mov.w sl, r0, lsr #16 + 1d086: f88d 900a strb.w r9, [sp, #10] + 1d08a: f88d 1012 strb.w r1, [sp, #18] + 1d08e: ea4f 2910 mov.w r9, r0, lsr #8 + 1d092: f88d 0017 strb.w r0, [sp, #23] + 1d096: 4971 ldr r1, [pc, #452] ; (1d25c ) + 1d098: 4630 mov r0, r6 + 1d09a: f88d 3010 strb.w r3, [sp, #16] + 1d09e: f88d c00d strb.w ip, [sp, #13] + 1d0a2: f88d e00e strb.w lr, [sp, #14] + 1d0a6: f88d b008 strb.w fp, [sp, #8] + 1d0aa: f88d 800c strb.w r8, [sp, #12] + 1d0ae: f88d 4011 strb.w r4, [sp, #17] + 1d0b2: f88d 5014 strb.w r5, [sp, #20] + 1d0b6: f88d a015 strb.w sl, [sp, #21] + 1d0ba: f88d 9016 strb.w r9, [sp, #22] + 1d0be: f7ff fe95 bl 1cdec + 1d0c2: 4630 mov r0, r6 + 1d0c4: a902 add r1, sp, #8 + 1d0c6: 2210 movs r2, #16 + 1d0c8: f7ff fe90 bl 1cdec + 1d0cc: 7df3 ldrb r3, [r6, #23] + 1d0ce: 703b strb r3, [r7, #0] + 1d0d0: 8af3 ldrh r3, [r6, #22] + 1d0d2: 707b strb r3, [r7, #1] + 1d0d4: 6973 ldr r3, [r6, #20] + 1d0d6: 0a1b lsrs r3, r3, #8 + 1d0d8: 70bb strb r3, [r7, #2] + 1d0da: 6973 ldr r3, [r6, #20] + 1d0dc: 70fb strb r3, [r7, #3] + 1d0de: 7cf3 ldrb r3, [r6, #19] + 1d0e0: 713b strb r3, [r7, #4] + 1d0e2: 8a73 ldrh r3, [r6, #18] + 1d0e4: 717b strb r3, [r7, #5] + 1d0e6: 6933 ldr r3, [r6, #16] + 1d0e8: 0a1b lsrs r3, r3, #8 + 1d0ea: 71bb strb r3, [r7, #6] + 1d0ec: 6933 ldr r3, [r6, #16] + 1d0ee: 71fb strb r3, [r7, #7] + 1d0f0: 7ff3 ldrb r3, [r6, #31] + 1d0f2: 723b strb r3, [r7, #8] + 1d0f4: 8bf3 ldrh r3, [r6, #30] + 1d0f6: 727b strb r3, [r7, #9] + 1d0f8: 69f3 ldr r3, [r6, #28] + 1d0fa: 0a1b lsrs r3, r3, #8 + 1d0fc: 72bb strb r3, [r7, #10] + 1d0fe: 69f3 ldr r3, [r6, #28] + 1d100: 72fb strb r3, [r7, #11] + 1d102: 7ef3 ldrb r3, [r6, #27] + 1d104: 733b strb r3, [r7, #12] + 1d106: 8b73 ldrh r3, [r6, #26] + 1d108: 737b strb r3, [r7, #13] + 1d10a: 69b3 ldr r3, [r6, #24] + 1d10c: 0a1b lsrs r3, r3, #8 + 1d10e: 73bb strb r3, [r7, #14] + 1d110: 69b3 ldr r3, [r6, #24] + 1d112: 73fb strb r3, [r7, #15] + 1d114: f896 3027 ldrb.w r3, [r6, #39] ; 0x27 + 1d118: 743b strb r3, [r7, #16] + 1d11a: 8cf3 ldrh r3, [r6, #38] ; 0x26 + 1d11c: 747b strb r3, [r7, #17] + 1d11e: 6a73 ldr r3, [r6, #36] ; 0x24 + 1d120: 0a1b lsrs r3, r3, #8 + 1d122: 74bb strb r3, [r7, #18] + 1d124: 6a73 ldr r3, [r6, #36] ; 0x24 + 1d126: 74fb strb r3, [r7, #19] + 1d128: f896 3023 ldrb.w r3, [r6, #35] ; 0x23 + 1d12c: 753b strb r3, [r7, #20] + 1d12e: 8c73 ldrh r3, [r6, #34] ; 0x22 + 1d130: 757b strb r3, [r7, #21] + 1d132: 6a33 ldr r3, [r6, #32] + 1d134: 0a1b lsrs r3, r3, #8 + 1d136: 75bb strb r3, [r7, #22] + 1d138: 6a33 ldr r3, [r6, #32] + 1d13a: 75fb strb r3, [r7, #23] + 1d13c: f896 302f ldrb.w r3, [r6, #47] ; 0x2f + 1d140: 763b strb r3, [r7, #24] + 1d142: 8df3 ldrh r3, [r6, #46] ; 0x2e + 1d144: 767b strb r3, [r7, #25] + 1d146: 6af3 ldr r3, [r6, #44] ; 0x2c + 1d148: 0a1b lsrs r3, r3, #8 + 1d14a: 76bb strb r3, [r7, #26] + 1d14c: 6af3 ldr r3, [r6, #44] ; 0x2c + 1d14e: 76fb strb r3, [r7, #27] + 1d150: f896 302b ldrb.w r3, [r6, #43] ; 0x2b + 1d154: 773b strb r3, [r7, #28] + 1d156: 8d73 ldrh r3, [r6, #42] ; 0x2a + 1d158: 777b strb r3, [r7, #29] + 1d15a: 6ab3 ldr r3, [r6, #40] ; 0x28 + 1d15c: 0a1b lsrs r3, r3, #8 + 1d15e: 77bb strb r3, [r7, #30] + 1d160: 6ab3 ldr r3, [r6, #40] ; 0x28 + 1d162: 77fb strb r3, [r7, #31] + 1d164: f896 3037 ldrb.w r3, [r6, #55] ; 0x37 + 1d168: f887 3020 strb.w r3, [r7, #32] + 1d16c: 8ef3 ldrh r3, [r6, #54] ; 0x36 + 1d16e: f887 3021 strb.w r3, [r7, #33] ; 0x21 + 1d172: 6b73 ldr r3, [r6, #52] ; 0x34 + 1d174: 0a1b lsrs r3, r3, #8 + 1d176: f887 3022 strb.w r3, [r7, #34] ; 0x22 + 1d17a: 6b73 ldr r3, [r6, #52] ; 0x34 + 1d17c: f887 3023 strb.w r3, [r7, #35] ; 0x23 + 1d180: f896 3033 ldrb.w r3, [r6, #51] ; 0x33 + 1d184: f887 3024 strb.w r3, [r7, #36] ; 0x24 + 1d188: 8e73 ldrh r3, [r6, #50] ; 0x32 + 1d18a: f887 3025 strb.w r3, [r7, #37] ; 0x25 + 1d18e: 6b33 ldr r3, [r6, #48] ; 0x30 + 1d190: 0a1b lsrs r3, r3, #8 + 1d192: f887 3026 strb.w r3, [r7, #38] ; 0x26 + 1d196: 6b33 ldr r3, [r6, #48] ; 0x30 + 1d198: f887 3027 strb.w r3, [r7, #39] ; 0x27 + 1d19c: f896 303f ldrb.w r3, [r6, #63] ; 0x3f + 1d1a0: f887 3028 strb.w r3, [r7, #40] ; 0x28 + 1d1a4: 8ff3 ldrh r3, [r6, #62] ; 0x3e + 1d1a6: f887 3029 strb.w r3, [r7, #41] ; 0x29 + 1d1aa: 6bf3 ldr r3, [r6, #60] ; 0x3c + 1d1ac: 0a1b lsrs r3, r3, #8 + 1d1ae: f887 302a strb.w r3, [r7, #42] ; 0x2a + 1d1b2: 6bf3 ldr r3, [r6, #60] ; 0x3c + 1d1b4: f887 302b strb.w r3, [r7, #43] ; 0x2b + 1d1b8: f896 303b ldrb.w r3, [r6, #59] ; 0x3b + 1d1bc: f887 302c strb.w r3, [r7, #44] ; 0x2c + 1d1c0: 8f73 ldrh r3, [r6, #58] ; 0x3a + 1d1c2: f887 302d strb.w r3, [r7, #45] ; 0x2d + 1d1c6: 6bb3 ldr r3, [r6, #56] ; 0x38 + 1d1c8: 0a1b lsrs r3, r3, #8 + 1d1ca: f887 302e strb.w r3, [r7, #46] ; 0x2e + 1d1ce: 6bb3 ldr r3, [r6, #56] ; 0x38 + 1d1d0: f887 302f strb.w r3, [r7, #47] ; 0x2f + 1d1d4: f8d6 31d0 ldr.w r3, [r6, #464] ; 0x1d0 + 1d1d8: 2b00 cmp r3, #0 + 1d1da: d13b bne.n 1d254 + 1d1dc: f896 3047 ldrb.w r3, [r6, #71] ; 0x47 + 1d1e0: f887 3030 strb.w r3, [r7, #48] ; 0x30 + 1d1e4: f8b6 3046 ldrh.w r3, [r6, #70] ; 0x46 + 1d1e8: f887 3031 strb.w r3, [r7, #49] ; 0x31 + 1d1ec: 6c73 ldr r3, [r6, #68] ; 0x44 + 1d1ee: 0a1b lsrs r3, r3, #8 + 1d1f0: f887 3032 strb.w r3, [r7, #50] ; 0x32 + 1d1f4: 6c73 ldr r3, [r6, #68] ; 0x44 + 1d1f6: f887 3033 strb.w r3, [r7, #51] ; 0x33 + 1d1fa: f896 3043 ldrb.w r3, [r6, #67] ; 0x43 + 1d1fe: f887 3034 strb.w r3, [r7, #52] ; 0x34 + 1d202: f8b6 3042 ldrh.w r3, [r6, #66] ; 0x42 + 1d206: f887 3035 strb.w r3, [r7, #53] ; 0x35 + 1d20a: 6c33 ldr r3, [r6, #64] ; 0x40 + 1d20c: 0a1b lsrs r3, r3, #8 + 1d20e: f887 3036 strb.w r3, [r7, #54] ; 0x36 + 1d212: 6c33 ldr r3, [r6, #64] ; 0x40 + 1d214: f887 3037 strb.w r3, [r7, #55] ; 0x37 + 1d218: f896 304f ldrb.w r3, [r6, #79] ; 0x4f + 1d21c: f887 3038 strb.w r3, [r7, #56] ; 0x38 + 1d220: f8b6 304e ldrh.w r3, [r6, #78] ; 0x4e + 1d224: f887 3039 strb.w r3, [r7, #57] ; 0x39 + 1d228: 6cf3 ldr r3, [r6, #76] ; 0x4c + 1d22a: 0a1b lsrs r3, r3, #8 + 1d22c: f887 303a strb.w r3, [r7, #58] ; 0x3a + 1d230: 6cf3 ldr r3, [r6, #76] ; 0x4c + 1d232: f887 303b strb.w r3, [r7, #59] ; 0x3b + 1d236: f896 304b ldrb.w r3, [r6, #75] ; 0x4b + 1d23a: f887 303c strb.w r3, [r7, #60] ; 0x3c + 1d23e: f8b6 304a ldrh.w r3, [r6, #74] ; 0x4a + 1d242: f887 303d strb.w r3, [r7, #61] ; 0x3d + 1d246: 6cb3 ldr r3, [r6, #72] ; 0x48 + 1d248: 0a1b lsrs r3, r3, #8 + 1d24a: f887 303e strb.w r3, [r7, #62] ; 0x3e + 1d24e: 6cb3 ldr r3, [r6, #72] ; 0x48 + 1d250: f887 303f strb.w r3, [r7, #63] ; 0x3f + 1d254: b007 add sp, #28 + 1d256: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 1d25a: bf00 nop + 1d25c: 00036638 .word 0x00036638 + +0001d260 : + 1d260: b570 push {r4, r5, r6, lr} + 1d262: 460c mov r4, r1 + 1d264: b0f6 sub sp, #472 ; 0x1d8 + 1d266: 4606 mov r6, r0 + 1d268: 4619 mov r1, r3 + 1d26a: 4668 mov r0, sp + 1d26c: 4615 mov r5, r2 + 1d26e: f7ff fe21 bl 1ceb4 + 1d272: b124 cbz r4, 1d27e + 1d274: 4631 mov r1, r6 + 1d276: 4622 mov r2, r4 + 1d278: 4668 mov r0, sp + 1d27a: f7ff fdb7 bl 1cdec + 1d27e: 4629 mov r1, r5 + 1d280: 4668 mov r0, sp + 1d282: f7ff fec5 bl 1d010 + 1d286: 4668 mov r0, sp + 1d288: 2100 movs r1, #0 + 1d28a: f44f 72ec mov.w r2, #472 ; 0x1d8 + 1d28e: f7f2 f93f bl f510 <_memset> + 1d292: b076 add sp, #472 ; 0x1d8 + 1d294: bd70 pop {r4, r5, r6, pc} + 1d296: bf00 nop + +0001d298 : + 1d298: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 1d29c: 2a80 cmp r2, #128 ; 0x80 + 1d29e: b093 sub sp, #76 ; 0x4c + 1d2a0: 4690 mov r8, r2 + 1d2a2: 4681 mov r9, r0 + 1d2a4: 460e mov r6, r1 + 1d2a6: d838 bhi.n 1d31a + 1d2a8: f100 0ad0 add.w sl, r0, #208 ; 0xd0 + 1d2ac: 2136 movs r1, #54 ; 0x36 + 1d2ae: 2280 movs r2, #128 ; 0x80 + 1d2b0: 4650 mov r0, sl + 1d2b2: 9301 str r3, [sp, #4] + 1d2b4: f7f2 f92c bl f510 <_memset> + 1d2b8: f509 70a8 add.w r0, r9, #336 ; 0x150 + 1d2bc: 215c movs r1, #92 ; 0x5c + 1d2be: 2280 movs r2, #128 ; 0x80 + 1d2c0: f7f2 f926 bl f510 <_memset> + 1d2c4: f10d 0b08 add.w fp, sp, #8 + 1d2c8: f8dd c004 ldr.w ip, [sp, #4] + 1d2cc: f1b8 0f00 cmp.w r8, #0 + 1d2d0: d012 beq.n 1d2f8 + 1d2d2: 464c mov r4, r9 + 1d2d4: 2500 movs r5, #0 + 1d2d6: 5d73 ldrb r3, [r6, r5] + 1d2d8: f894 20d0 ldrb.w r2, [r4, #208] ; 0xd0 + 1d2dc: f894 7150 ldrb.w r7, [r4, #336] ; 0x150 + 1d2e0: 4053 eors r3, r2 + 1d2e2: f884 30d0 strb.w r3, [r4, #208] ; 0xd0 + 1d2e6: 5d73 ldrb r3, [r6, r5] + 1d2e8: 3501 adds r5, #1 + 1d2ea: 405f eors r7, r3 + 1d2ec: 45a8 cmp r8, r5 + 1d2ee: f884 7150 strb.w r7, [r4, #336] ; 0x150 + 1d2f2: f104 0401 add.w r4, r4, #1 + 1d2f6: d8ee bhi.n 1d2d6 + 1d2f8: 4661 mov r1, ip + 1d2fa: 4648 mov r0, r9 + 1d2fc: f7ff fdda bl 1ceb4 + 1d300: 4648 mov r0, r9 + 1d302: 4651 mov r1, sl + 1d304: 2280 movs r2, #128 ; 0x80 + 1d306: f7ff fd71 bl 1cdec + 1d30a: 4658 mov r0, fp + 1d30c: 2100 movs r1, #0 + 1d30e: 2240 movs r2, #64 ; 0x40 + 1d310: f7f2 f8fe bl f510 <_memset> + 1d314: b013 add sp, #76 ; 0x4c + 1d316: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 1d31a: f10d 0b08 add.w fp, sp, #8 + 1d31e: 4608 mov r0, r1 + 1d320: f109 0ad0 add.w sl, r9, #208 ; 0xd0 + 1d324: 4611 mov r1, r2 + 1d326: 465a mov r2, fp + 1d328: 9301 str r3, [sp, #4] + 1d32a: f7ff ff99 bl 1d260 + 1d32e: 2136 movs r1, #54 ; 0x36 + 1d330: 2280 movs r2, #128 ; 0x80 + 1d332: 4650 mov r0, sl + 1d334: f7f2 f8ec bl f510 <_memset> + 1d338: f509 70a8 add.w r0, r9, #336 ; 0x150 + 1d33c: 215c movs r1, #92 ; 0x5c + 1d33e: 2280 movs r2, #128 ; 0x80 + 1d340: f7f2 f8e6 bl f510 <_memset> + 1d344: f8dd c004 ldr.w ip, [sp, #4] + 1d348: 465e mov r6, fp + 1d34a: f1bc 0f00 cmp.w ip, #0 + 1d34e: bf0c ite eq + 1d350: f04f 0840 moveq.w r8, #64 ; 0x40 + 1d354: f04f 0830 movne.w r8, #48 ; 0x30 + 1d358: e7bb b.n 1d2d2 + 1d35a: bf00 nop + +0001d35c : + 1d35c: b902 cbnz r2, 1d360 + 1d35e: 4770 bx lr + 1d360: e544 b.n 1cdec + 1d362: bf00 nop + +0001d364 : + 1d364: b570 push {r4, r5, r6, lr} + 1d366: 4604 mov r4, r0 + 1d368: b090 sub sp, #64 ; 0x40 + 1d36a: f8d0 51d0 ldr.w r5, [r0, #464] ; 0x1d0 + 1d36e: 460e mov r6, r1 + 1d370: 4669 mov r1, sp + 1d372: f7ff fe4d bl 1d010 + 1d376: 4629 mov r1, r5 + 1d378: 2d00 cmp r5, #0 + 1d37a: bf14 ite ne + 1d37c: 2530 movne r5, #48 ; 0x30 + 1d37e: 2540 moveq r5, #64 ; 0x40 + 1d380: 4620 mov r0, r4 + 1d382: f7ff fd97 bl 1ceb4 + 1d386: 4620 mov r0, r4 + 1d388: f504 71a8 add.w r1, r4, #336 ; 0x150 + 1d38c: 2280 movs r2, #128 ; 0x80 + 1d38e: f7ff fd2d bl 1cdec + 1d392: 462a mov r2, r5 + 1d394: 4620 mov r0, r4 + 1d396: 4669 mov r1, sp + 1d398: f7ff fd28 bl 1cdec + 1d39c: 4620 mov r0, r4 + 1d39e: 4631 mov r1, r6 + 1d3a0: f7ff fe36 bl 1d010 + 1d3a4: 4668 mov r0, sp + 1d3a6: 2100 movs r1, #0 + 1d3a8: 2240 movs r2, #64 ; 0x40 + 1d3aa: f7f2 f8b1 bl f510 <_memset> + 1d3ae: b010 add sp, #64 ; 0x40 + 1d3b0: bd70 pop {r4, r5, r6, pc} + 1d3b2: bf00 nop + +0001d3b4 : + 1d3b4: b510 push {r4, lr} + 1d3b6: 4604 mov r4, r0 + 1d3b8: f8d0 11d0 ldr.w r1, [r0, #464] ; 0x1d0 + 1d3bc: f7ff fd7a bl 1ceb4 + 1d3c0: 4620 mov r0, r4 + 1d3c2: f104 01d0 add.w r1, r4, #208 ; 0xd0 + 1d3c6: 2280 movs r2, #128 ; 0x80 + 1d3c8: e8bd 4010 ldmia.w sp!, {r4, lr} + 1d3cc: e50e b.n 1cdec + 1d3ce: bf00 nop + +0001d3d0 : + 1d3d0: b570 push {r4, r5, r6, lr} + 1d3d2: 460d mov r5, r1 + 1d3d4: 461c mov r4, r3 + 1d3d6: b0f6 sub sp, #472 ; 0x1d8 + 1d3d8: 4601 mov r1, r0 + 1d3da: 4616 mov r6, r2 + 1d3dc: 4668 mov r0, sp + 1d3de: 462a mov r2, r5 + 1d3e0: 9b7b ldr r3, [sp, #492] ; 0x1ec + 1d3e2: 9d7a ldr r5, [sp, #488] ; 0x1e8 + 1d3e4: f7ff ff58 bl 1d298 + 1d3e8: b124 cbz r4, 1d3f4 + 1d3ea: 4631 mov r1, r6 + 1d3ec: 4622 mov r2, r4 + 1d3ee: 4668 mov r0, sp + 1d3f0: f7ff fcfc bl 1cdec + 1d3f4: 4629 mov r1, r5 + 1d3f6: 4668 mov r0, sp + 1d3f8: f7ff ffb4 bl 1d364 + 1d3fc: 4668 mov r0, sp + 1d3fe: 2100 movs r1, #0 + 1d400: f44f 72ec mov.w r2, #472 ; 0x1d8 + 1d404: f7f2 f884 bl f510 <_memset> + 1d408: b076 add sp, #472 ; 0x1d8 + 1d40a: bd70 pop {r4, r5, r6, pc} + +0001d40c : + 1d40c: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 1d410: f5ad 7d1b sub.w sp, sp, #620 ; 0x26c + 1d414: 4605 mov r5, r0 + 1d416: 460c mov r4, r1 + 1d418: f8dd b290 ldr.w fp, [sp, #656] ; 0x290 + 1d41c: 9ea5 ldr r6, [sp, #660] ; 0x294 + 1d41e: f8dd 9298 ldr.w r9, [sp, #664] ; 0x298 + 1d422: 2a00 cmp r2, #0 + 1d424: d061 beq.n 1d4ea + 1d426: f04f 0e00 mov.w lr, #0 + 1d42a: af04 add r7, sp, #16 + 1d42c: 4619 mov r1, r3 + 1d42e: 4610 mov r0, r2 + 1d430: 4623 mov r3, r4 + 1d432: 462a mov r2, r5 + 1d434: e88d 4080 stmia.w sp, {r7, lr} + 1d438: 45f3 cmp fp, lr + 1d43a: bf08 it eq + 1d43c: 4676 moveq r6, lr + 1d43e: f7ff ffc7 bl 1d3d0 + 1d442: 99a7 ldr r1, [sp, #668] ; 0x29c + 1d444: 2900 cmp r1, #0 + 1d446: d058 beq.n 1d4fa + 1d448: f1b9 0f00 cmp.w r9, #0 + 1d44c: d055 beq.n 1d4fa + 1d44e: ea4f 1891 mov.w r8, r1, lsr #6 + 1d452: 068b lsls r3, r1, #26 + 1d454: bf18 it ne + 1d456: f108 0801 addne.w r8, r8, #1 + 1d45a: f1b8 0fff cmp.w r8, #255 ; 0xff + 1d45e: dc4c bgt.n 1d4fa + 1d460: f1b8 0f00 cmp.w r8, #0 + 1d464: d03c beq.n 1d4e0 + 1d466: a824 add r0, sp, #144 ; 0x90 + 1d468: 2501 movs r5, #1 + 1d46a: 4639 mov r1, r7 + 1d46c: 2240 movs r2, #64 ; 0x40 + 1d46e: 2300 movs r3, #0 + 1d470: f88d 500f strb.w r5, [sp, #15] + 1d474: ea4f 1a88 mov.w sl, r8, lsl #6 + 1d478: f7ff ff0e bl 1d298 + 1d47c: 2400 movs r4, #0 + 1d47e: bb4e cbnz r6, 1d4d4 + 1d480: 2201 movs r2, #1 + 1d482: a824 add r0, sp, #144 ; 0x90 + 1d484: f10d 010f add.w r1, sp, #15 + 1d488: f7ff fcb0 bl 1cdec + 1d48c: a824 add r0, sp, #144 ; 0x90 + 1d48e: a914 add r1, sp, #80 ; 0x50 + 1d490: f7ff ff68 bl 1d364 + 1d494: 45a8 cmp r8, r5 + 1d496: bf0a itet eq + 1d498: 9ba7 ldreq r3, [sp, #668] ; 0x29c + 1d49a: 2240 movne r2, #64 ; 0x40 + 1d49c: 1b1a subeq r2, r3, r4 + 1d49e: eb09 0004 add.w r0, r9, r4 + 1d4a2: a914 add r1, sp, #80 ; 0x50 + 1d4a4: 3440 adds r4, #64 ; 0x40 + 1d4a6: f7f1 ffdd bl f464 <_memcpy> + 1d4aa: 4554 cmp r4, sl + 1d4ac: f105 0501 add.w r5, r5, #1 + 1d4b0: f04f 0240 mov.w r2, #64 ; 0x40 + 1d4b4: f04f 0300 mov.w r3, #0 + 1d4b8: d012 beq.n 1d4e0 + 1d4ba: a824 add r0, sp, #144 ; 0x90 + 1d4bc: 4639 mov r1, r7 + 1d4be: f88d 500f strb.w r5, [sp, #15] + 1d4c2: f7ff fee9 bl 1d298 + 1d4c6: a824 add r0, sp, #144 ; 0x90 + 1d4c8: a914 add r1, sp, #80 ; 0x50 + 1d4ca: 2240 movs r2, #64 ; 0x40 + 1d4cc: f7ff fc8e bl 1cdec + 1d4d0: 2e00 cmp r6, #0 + 1d4d2: d0d5 beq.n 1d480 + 1d4d4: a824 add r0, sp, #144 ; 0x90 + 1d4d6: 4659 mov r1, fp + 1d4d8: 4632 mov r2, r6 + 1d4da: f7ff fc87 bl 1cdec + 1d4de: e7cf b.n 1d480 + 1d4e0: 2000 movs r0, #0 + 1d4e2: f50d 7d1b add.w sp, sp, #620 ; 0x26c + 1d4e6: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 1d4ea: 4611 mov r1, r2 + 1d4ec: a824 add r0, sp, #144 ; 0x90 + 1d4ee: 2240 movs r2, #64 ; 0x40 + 1d4f0: f7f2 f80e bl f510 <_memset> + 1d4f4: aa24 add r2, sp, #144 ; 0x90 + 1d4f6: 2340 movs r3, #64 ; 0x40 + 1d4f8: e795 b.n 1d426 + 1d4fa: 2001 movs r0, #1 + 1d4fc: e7f1 b.n 1d4e2 + 1d4fe: bf00 nop + +0001d500 : + 1d500: f000 b80e b.w 1d520 + +0001d504 : + 1d504: b510 push {r4, lr} + 1d506: b084 sub sp, #16 + 1d508: 9c06 ldr r4, [sp, #24] + 1d50a: e9cd 2300 strd r2, r3, [sp] + 1d50e: 9402 str r4, [sp, #8] + 1d510: 460a mov r2, r1 + 1d512: 2100 movs r1, #0 + 1d514: f000 f830 bl 1d578 + 1d518: b004 add sp, #16 + 1d51a: bd10 pop {r4, pc} + +0001d51c : + 1d51c: f000 b89a b.w 1d654 + +0001d520 : + 1d520: b570 push {r4, r5, r6, lr} + 1d522: 4616 mov r6, r2 + 1d524: 460c mov r4, r1 + 1d526: 4605 mov r5, r0 + 1d528: b0a8 sub sp, #160 ; 0xa0 + 1d52a: 460a mov r2, r1 + 1d52c: 4630 mov r0, r6 + 1d52e: 2120 movs r1, #32 + 1d530: 2300 movs r3, #0 + 1d532: f7ff fe95 bl 1d260 + 1d536: 7fe3 ldrb r3, [r4, #31] + 1d538: 7822 ldrb r2, [r4, #0] + 1d53a: f003 033f and.w r3, r3, #63 ; 0x3f + 1d53e: f043 0340 orr.w r3, r3, #64 ; 0x40 + 1d542: f022 0207 bic.w r2, r2, #7 + 1d546: 77e3 strb r3, [r4, #31] + 1d548: 7022 strb r2, [r4, #0] + 1d54a: 4621 mov r1, r4 + 1d54c: 4668 mov r0, sp + 1d54e: f003 f967 bl 20820 + 1d552: 4628 mov r0, r5 + 1d554: 4669 mov r1, sp + 1d556: f003 f93d bl 207d4 + 1d55a: 4631 mov r1, r6 + 1d55c: 4620 mov r0, r4 + 1d55e: 2220 movs r2, #32 + 1d560: f7f1 ff80 bl f464 <_memcpy> + 1d564: f104 0020 add.w r0, r4, #32 + 1d568: 4629 mov r1, r5 + 1d56a: 2220 movs r2, #32 + 1d56c: f7f1 ff7a bl f464 <_memcpy> + 1d570: 2000 movs r0, #0 + 1d572: b028 add sp, #160 ; 0xa0 + 1d574: bd70 pop {r4, r5, r6, pc} + 1d576: bf00 nop + +0001d578 : + 1d578: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + 1d57c: 4617 mov r7, r2 + 1d57e: 4604 mov r4, r0 + 1d580: 4688 mov r8, r1 + 1d582: f5ad 7d56 sub.w sp, sp, #856 ; 0x358 + 1d586: 9dde ldr r5, [sp, #888] ; 0x378 + 1d588: 2220 movs r2, #32 + 1d58a: f105 0120 add.w r1, r5, #32 + 1d58e: 4668 mov r0, sp + 1d590: 9edc ldr r6, [sp, #880] ; 0x370 + 1d592: f7f1 ff67 bl f464 <_memcpy> + 1d596: 4628 mov r0, r5 + 1d598: aa08 add r2, sp, #32 + 1d59a: 2120 movs r1, #32 + 1d59c: 2300 movs r3, #0 + 1d59e: f7ff fe5f bl 1d260 + 1d5a2: f89d 303f ldrb.w r3, [sp, #63] ; 0x3f + 1d5a6: f89d 2020 ldrb.w r2, [sp, #32] + 1d5aa: f003 033f and.w r3, r3, #63 ; 0x3f + 1d5ae: f043 0340 orr.w r3, r3, #64 ; 0x40 + 1d5b2: f022 0207 bic.w r2, r2, #7 + 1d5b6: a860 add r0, sp, #384 ; 0x180 + 1d5b8: 2100 movs r1, #0 + 1d5ba: f88d 303f strb.w r3, [sp, #63] ; 0x3f + 1d5be: f88d 2020 strb.w r2, [sp, #32] + 1d5c2: f7ff fc77 bl 1ceb4 + 1d5c6: a860 add r0, sp, #384 ; 0x180 + 1d5c8: a910 add r1, sp, #64 ; 0x40 + 1d5ca: 2220 movs r2, #32 + 1d5cc: f7ff fd1c bl 1d008 + 1d5d0: 4632 mov r2, r6 + 1d5d2: a860 add r0, sp, #384 ; 0x180 + 1d5d4: 4639 mov r1, r7 + 1d5d6: f7ff fd17 bl 1d008 + 1d5da: f104 0520 add.w r5, r4, #32 + 1d5de: a860 add r0, sp, #384 ; 0x180 + 1d5e0: a918 add r1, sp, #96 ; 0x60 + 1d5e2: f7ff fd15 bl 1d010 + 1d5e6: 2220 movs r2, #32 + 1d5e8: 4669 mov r1, sp + 1d5ea: 4628 mov r0, r5 + 1d5ec: f7f1 ff3a bl f464 <_memcpy> + 1d5f0: a818 add r0, sp, #96 ; 0x60 + 1d5f2: f008 fd23 bl 2603c + 1d5f6: a918 add r1, sp, #96 ; 0x60 + 1d5f8: a838 add r0, sp, #224 ; 0xe0 + 1d5fa: f003 f911 bl 20820 + 1d5fe: 4620 mov r0, r4 + 1d600: a938 add r1, sp, #224 ; 0xe0 + 1d602: f003 f8e7 bl 207d4 + 1d606: a860 add r0, sp, #384 ; 0x180 + 1d608: 2100 movs r1, #0 + 1d60a: f7ff fc53 bl 1ceb4 + 1d60e: a860 add r0, sp, #384 ; 0x180 + 1d610: 4621 mov r1, r4 + 1d612: 2240 movs r2, #64 ; 0x40 + 1d614: f7ff fcf8 bl 1d008 + 1d618: 4632 mov r2, r6 + 1d61a: a860 add r0, sp, #384 ; 0x180 + 1d61c: 4639 mov r1, r7 + 1d61e: f7ff fcf3 bl 1d008 + 1d622: a928 add r1, sp, #160 ; 0xa0 + 1d624: a860 add r0, sp, #384 ; 0x180 + 1d626: f7ff fcf3 bl 1d010 + 1d62a: a828 add r0, sp, #160 ; 0xa0 + 1d62c: f008 fd06 bl 2603c + 1d630: 4628 mov r0, r5 + 1d632: a928 add r1, sp, #160 ; 0xa0 + 1d634: aa08 add r2, sp, #32 + 1d636: ab18 add r3, sp, #96 ; 0x60 + 1d638: f003 f9f8 bl 20a2c + 1d63c: f1b8 0f00 cmp.w r8, #0 + 1d640: d003 beq.n 1d64a + 1d642: 2240 movs r2, #64 ; 0x40 + 1d644: 2300 movs r3, #0 + 1d646: e9c8 2300 strd r2, r3, [r8] + 1d64a: 2000 movs r0, #0 + 1d64c: f50d 7d56 add.w sp, sp, #856 ; 0x358 + 1d650: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +0001d654 : + 1d654: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} + 1d658: f890 303f ldrb.w r3, [r0, #63] ; 0x3f + 1d65c: f5ad 7d55 sub.w sp, sp, #852 ; 0x354 + 1d660: f013 0fe0 tst.w r3, #224 ; 0xe0 + 1d664: 4606 mov r6, r0 + 1d666: 9fdc ldr r7, [sp, #880] ; 0x370 + 1d668: f040 814f bne.w 1d90a + 1d66c: 4689 mov r9, r1 + 1d66e: a836 add r0, sp, #216 ; 0xd8 + 1d670: 4639 mov r1, r7 + 1d672: 4690 mov r8, r2 + 1d674: f002 fade bl 1fc34 + 1d678: 2800 cmp r0, #0 + 1d67a: f040 8146 bne.w 1d90a + 1d67e: 4603 mov r3, r0 + 1d680: 4604 mov r4, r0 + 1d682: 5d3d ldrb r5, [r7, r4] + 1d684: 3401 adds r4, #1 + 1d686: 432b orrs r3, r5 + 1d688: 2c20 cmp r4, #32 + 1d68a: b2db uxtb r3, r3 + 1d68c: d1f9 bne.n 1d682 + 1d68e: 2b00 cmp r3, #0 + 1d690: f000 813b beq.w 1d90a + 1d694: a85e add r0, sp, #376 ; 0x178 + 1d696: 2100 movs r1, #0 + 1d698: f7ff fc0c bl 1ceb4 + 1d69c: 4622 mov r2, r4 + 1d69e: a85e add r0, sp, #376 ; 0x178 + 1d6a0: 4631 mov r1, r6 + 1d6a2: f7ff fcb1 bl 1d008 + 1d6a6: 4639 mov r1, r7 + 1d6a8: 4622 mov r2, r4 + 1d6aa: a85e add r0, sp, #376 ; 0x178 + 1d6ac: f7ff fcac bl 1d008 + 1d6b0: 4642 mov r2, r8 + 1d6b2: 4649 mov r1, r9 + 1d6b4: a85e add r0, sp, #376 ; 0x178 + 1d6b6: f7ff fca7 bl 1d008 + 1d6ba: a908 add r1, sp, #32 + 1d6bc: a85e add r0, sp, #376 ; 0x178 + 1d6be: f7ff fca7 bl 1d010 + 1d6c2: a808 add r0, sp, #32 + 1d6c4: f008 fcba bl 2603c + 1d6c8: aa36 add r2, sp, #216 ; 0xd8 + 1d6ca: f106 0320 add.w r3, r6, #32 + 1d6ce: a908 add r1, sp, #32 + 1d6d0: a818 add r0, sp, #96 ; 0x60 + 1d6d2: f002 f8cb bl 1f86c + 1d6d6: a918 add r1, sp, #96 ; 0x60 + 1d6d8: 4668 mov r0, sp + 1d6da: f003 f981 bl 209e0 + 1d6de: f89d 3001 ldrb.w r3, [sp, #1] + 1d6e2: f89d 1000 ldrb.w r1, [sp] + 1d6e6: 7835 ldrb r5, [r6, #0] + 1d6e8: f896 9001 ldrb.w r9, [r6, #1] + 1d6ec: f89d 2002 ldrb.w r2, [sp, #2] + 1d6f0: 466c mov r4, sp + 1d6f2: 78b0 ldrb r0, [r6, #2] + 1d6f4: 404d eors r5, r1 + 1d6f6: ea89 0903 eor.w r9, r9, r3 + 1d6fa: f896 8003 ldrb.w r8, [r6, #3] + 1d6fe: f89d 3003 ldrb.w r3, [sp, #3] + 1d702: 4050 eors r0, r2 + 1d704: ea49 0905 orr.w r9, r9, r5 + 1d708: f89d 7004 ldrb.w r7, [sp, #4] + 1d70c: f896 e004 ldrb.w lr, [r6, #4] + 1d710: ea88 0803 eor.w r8, r8, r3 + 1d714: ea49 0900 orr.w r9, r9, r0 + 1d718: f896 c005 ldrb.w ip, [r6, #5] + 1d71c: f89d 0005 ldrb.w r0, [sp, #5] + 1d720: ea8e 0e07 eor.w lr, lr, r7 + 1d724: ea49 0908 orr.w r9, r9, r8 + 1d728: f89d 7006 ldrb.w r7, [sp, #6] + 1d72c: f896 8006 ldrb.w r8, [r6, #6] + 1d730: ea8c 0c00 eor.w ip, ip, r0 + 1d734: ea49 090e orr.w r9, r9, lr + 1d738: f89d 0007 ldrb.w r0, [sp, #7] + 1d73c: f896 e007 ldrb.w lr, [r6, #7] + 1d740: ea88 0807 eor.w r8, r8, r7 + 1d744: ea49 090c orr.w r9, r9, ip + 1d748: f89d 7008 ldrb.w r7, [sp, #8] + 1d74c: f896 c008 ldrb.w ip, [r6, #8] + 1d750: ea8e 0e00 eor.w lr, lr, r0 + 1d754: ea49 0908 orr.w r9, r9, r8 + 1d758: f89d 0009 ldrb.w r0, [sp, #9] + 1d75c: f896 8009 ldrb.w r8, [r6, #9] + 1d760: ea8c 0c07 eor.w ip, ip, r7 + 1d764: ea49 090e orr.w r9, r9, lr + 1d768: f89d 700a ldrb.w r7, [sp, #10] + 1d76c: f896 e00a ldrb.w lr, [r6, #10] + 1d770: ea88 0800 eor.w r8, r8, r0 + 1d774: ea49 090c orr.w r9, r9, ip + 1d778: f89d 000b ldrb.w r0, [sp, #11] + 1d77c: f896 c00b ldrb.w ip, [r6, #11] + 1d780: ea8e 0e07 eor.w lr, lr, r7 + 1d784: ea49 0908 orr.w r9, r9, r8 + 1d788: f89d 700c ldrb.w r7, [sp, #12] + 1d78c: f896 800c ldrb.w r8, [r6, #12] + 1d790: ea8c 0c00 eor.w ip, ip, r0 + 1d794: ea49 090e orr.w r9, r9, lr + 1d798: f89d 000d ldrb.w r0, [sp, #13] + 1d79c: f896 e00d ldrb.w lr, [r6, #13] + 1d7a0: ea88 0807 eor.w r8, r8, r7 + 1d7a4: ea49 090c orr.w r9, r9, ip + 1d7a8: f89d 700e ldrb.w r7, [sp, #14] + 1d7ac: f896 c00e ldrb.w ip, [r6, #14] + 1d7b0: ea8e 0e00 eor.w lr, lr, r0 + 1d7b4: ea49 0908 orr.w r9, r9, r8 + 1d7b8: f89d 000f ldrb.w r0, [sp, #15] + 1d7bc: f896 800f ldrb.w r8, [r6, #15] + 1d7c0: ea8c 0c07 eor.w ip, ip, r7 + 1d7c4: ea49 090e orr.w r9, r9, lr + 1d7c8: f89d 7010 ldrb.w r7, [sp, #16] + 1d7cc: f896 e010 ldrb.w lr, [r6, #16] + 1d7d0: ea88 0800 eor.w r8, r8, r0 + 1d7d4: ea49 090c orr.w r9, r9, ip + 1d7d8: f89d 0011 ldrb.w r0, [sp, #17] + 1d7dc: f896 c011 ldrb.w ip, [r6, #17] + 1d7e0: ea8e 0e07 eor.w lr, lr, r7 + 1d7e4: ea49 0908 orr.w r9, r9, r8 + 1d7e8: f89d 7012 ldrb.w r7, [sp, #18] + 1d7ec: f896 8012 ldrb.w r8, [r6, #18] + 1d7f0: ea8c 0c00 eor.w ip, ip, r0 + 1d7f4: ea49 090e orr.w r9, r9, lr + 1d7f8: f89d 0013 ldrb.w r0, [sp, #19] + 1d7fc: f896 e013 ldrb.w lr, [r6, #19] + 1d800: ea88 0807 eor.w r8, r8, r7 + 1d804: ea49 090c orr.w r9, r9, ip + 1d808: f89d 7014 ldrb.w r7, [sp, #20] + 1d80c: f896 c014 ldrb.w ip, [r6, #20] + 1d810: ea8e 0e00 eor.w lr, lr, r0 + 1d814: ea49 0908 orr.w r9, r9, r8 + 1d818: f89d 0015 ldrb.w r0, [sp, #21] + 1d81c: f896 8015 ldrb.w r8, [r6, #21] + 1d820: ea8c 0c07 eor.w ip, ip, r7 + 1d824: ea49 090e orr.w r9, r9, lr + 1d828: f89d 7016 ldrb.w r7, [sp, #22] + 1d82c: f896 e016 ldrb.w lr, [r6, #22] + 1d830: ea88 0800 eor.w r8, r8, r0 + 1d834: ea49 090c orr.w r9, r9, ip + 1d838: f89d 0017 ldrb.w r0, [sp, #23] + 1d83c: f896 c017 ldrb.w ip, [r6, #23] + 1d840: ea8e 0e07 eor.w lr, lr, r7 + 1d844: ea49 0908 orr.w r9, r9, r8 + 1d848: f89d 7018 ldrb.w r7, [sp, #24] + 1d84c: f896 8018 ldrb.w r8, [r6, #24] + 1d850: ea8c 0c00 eor.w ip, ip, r0 + 1d854: ea49 090e orr.w r9, r9, lr + 1d858: f89d 0019 ldrb.w r0, [sp, #25] + 1d85c: f896 e019 ldrb.w lr, [r6, #25] + 1d860: ea88 0807 eor.w r8, r8, r7 + 1d864: ea49 090c orr.w r9, r9, ip + 1d868: f89d 701a ldrb.w r7, [sp, #26] + 1d86c: f896 c01a ldrb.w ip, [r6, #26] + 1d870: ea8e 0e00 eor.w lr, lr, r0 + 1d874: ea49 0908 orr.w r9, r9, r8 + 1d878: f89d 001b ldrb.w r0, [sp, #27] + 1d87c: f896 801b ldrb.w r8, [r6, #27] + 1d880: ea8c 0c07 eor.w ip, ip, r7 + 1d884: ea49 090e orr.w r9, r9, lr + 1d888: f89d 701c ldrb.w r7, [sp, #28] + 1d88c: f896 e01c ldrb.w lr, [r6, #28] + 1d890: ea88 0800 eor.w r8, r8, r0 + 1d894: ea49 090c orr.w r9, r9, ip + 1d898: f89d 001d ldrb.w r0, [sp, #29] + 1d89c: f896 c01d ldrb.w ip, [r6, #29] + 1d8a0: ea8e 0e07 eor.w lr, lr, r7 + 1d8a4: ea49 0908 orr.w r9, r9, r8 + 1d8a8: 7fb7 ldrb r7, [r6, #30] + 1d8aa: f89d 801e ldrb.w r8, [sp, #30] + 1d8ae: ea49 090e orr.w r9, r9, lr + 1d8b2: ea8c 0c00 eor.w ip, ip, r0 + 1d8b6: f89d e01f ldrb.w lr, [sp, #31] + 1d8ba: 7ff0 ldrb r0, [r6, #31] + 1d8bc: ea49 0c0c orr.w ip, r9, ip + 1d8c0: ea87 0708 eor.w r7, r7, r8 + 1d8c4: ea4c 0707 orr.w r7, ip, r7 + 1d8c8: ea80 000e eor.w r0, r0, lr + 1d8cc: 42a6 cmp r6, r4 + 1d8ce: ea40 0007 orr.w r0, r0, r7 + 1d8d2: f04f 35ff mov.w r5, #4294967295 + 1d8d6: f04f 0200 mov.w r2, #0 + 1d8da: bf18 it ne + 1d8dc: 2500 movne r5, #0 + 1d8de: 4240 negs r0, r0 + 1d8e0: 4613 mov r3, r2 + 1d8e2: ea45 70e0 orr.w r0, r5, r0, asr #31 + 1d8e6: e000 b.n 1d8ea + 1d8e8: 5ce1 ldrb r1, [r4, r3] + 1d8ea: 5cf5 ldrb r5, [r6, r3] + 1d8ec: 3301 adds r3, #1 + 1d8ee: 4069 eors r1, r5 + 1d8f0: 2b20 cmp r3, #32 + 1d8f2: ea42 0201 orr.w r2, r2, r1 + 1d8f6: d1f7 bne.n 1d8e8 + 1d8f8: 1e53 subs r3, r2, #1 + 1d8fa: f3c3 2300 ubfx r3, r3, #8, #1 + 1d8fe: 3b01 subs r3, #1 + 1d900: 4318 orrs r0, r3 + 1d902: f50d 7d55 add.w sp, sp, #852 ; 0x354 + 1d906: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + 1d90a: f04f 30ff mov.w r0, #4294967295 + 1d90e: f50d 7d55 add.w sp, sp, #852 ; 0x354 + 1d912: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + 1d916: bf00 nop + +0001d918 : + 1d918: 6853 ldr r3, [r2, #4] + 1d91a: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 1d91e: f8d1 e004 ldr.w lr, [r1, #4] + 1d922: 6897 ldr r7, [r2, #8] + 1d924: 449e add lr, r3 + 1d926: 688b ldr r3, [r1, #8] + 1d928: 690c ldr r4, [r1, #16] + 1d92a: 441f add r7, r3 + 1d92c: 6913 ldr r3, [r2, #16] + 1d92e: 68ce ldr r6, [r1, #12] + 1d930: 68d5 ldr r5, [r2, #12] + 1d932: b083 sub sp, #12 + 1d934: 4423 add r3, r4 + 1d936: 4435 add r5, r6 + 1d938: 9301 str r3, [sp, #4] + 1d93a: 694e ldr r6, [r1, #20] + 1d93c: 6953 ldr r3, [r2, #20] + 1d93e: f8d1 9018 ldr.w r9, [r1, #24] + 1d942: 441e add r6, r3 + 1d944: 6993 ldr r3, [r2, #24] + 1d946: f8d1 c01c ldr.w ip, [r1, #28] + 1d94a: 4499 add r9, r3 + 1d94c: 69d3 ldr r3, [r2, #28] + 1d94e: 6a0c ldr r4, [r1, #32] + 1d950: f8d2 8020 ldr.w r8, [r2, #32] + 1d954: f8d1 a024 ldr.w sl, [r1, #36] ; 0x24 + 1d958: f8d2 b000 ldr.w fp, [r2] + 1d95c: 6809 ldr r1, [r1, #0] + 1d95e: 6a52 ldr r2, [r2, #36] ; 0x24 + 1d960: 449c add ip, r3 + 1d962: 9b01 ldr r3, [sp, #4] + 1d964: 4444 add r4, r8 + 1d966: 4459 add r1, fp + 1d968: 4452 add r2, sl + 1d96a: e880 4002 stmia.w r0, {r1, lr} + 1d96e: 6087 str r7, [r0, #8] + 1d970: 60c5 str r5, [r0, #12] + 1d972: 6103 str r3, [r0, #16] + 1d974: 6146 str r6, [r0, #20] + 1d976: f8c0 9018 str.w r9, [r0, #24] + 1d97a: f8c0 c01c str.w ip, [r0, #28] + 1d97e: 6204 str r4, [r0, #32] + 1d980: 6242 str r2, [r0, #36] ; 0x24 + 1d982: b003 add sp, #12 + 1d984: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +0001d988 : + 1d988: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 1d98c: e891 5000 ldmia.w r1, {ip, lr} + 1d990: f8d1 8010 ldr.w r8, [r1, #16] + 1d994: 694f ldr r7, [r1, #20] + 1d996: 69cd ldr r5, [r1, #28] + 1d998: 6a0b ldr r3, [r1, #32] + 1d99a: f8d1 9008 ldr.w r9, [r1, #8] + 1d99e: 68ce ldr r6, [r1, #12] + 1d9a0: f8d1 a018 ldr.w sl, [r1, #24] + 1d9a4: f8d1 b024 ldr.w fp, [r1, #36] ; 0x24 + 1d9a8: 6801 ldr r1, [r0, #0] + 1d9aa: 6844 ldr r4, [r0, #4] + 1d9ac: ea81 0c0c eor.w ip, r1, ip + 1d9b0: 6881 ldr r1, [r0, #8] + 1d9b2: 4252 negs r2, r2 + 1d9b4: ea84 0e0e eor.w lr, r4, lr + 1d9b8: ea81 0909 eor.w r9, r1, r9 + 1d9bc: 68c1 ldr r1, [r0, #12] + 1d9be: ea0e 0e02 and.w lr, lr, r2 + 1d9c2: 404e eors r6, r1 + 1d9c4: ea8e 0e04 eor.w lr, lr, r4 + 1d9c8: 6801 ldr r1, [r0, #0] + 1d9ca: 6904 ldr r4, [r0, #16] + 1d9cc: ea0c 0c02 and.w ip, ip, r2 + 1d9d0: ea8c 0c01 eor.w ip, ip, r1 + 1d9d4: ea84 0108 eor.w r1, r4, r8 + 1d9d8: 6944 ldr r4, [r0, #20] + 1d9da: ea09 0902 and.w r9, r9, r2 + 1d9de: ea84 0807 eor.w r8, r4, r7 + 1d9e2: 6884 ldr r4, [r0, #8] + 1d9e4: 4016 ands r6, r2 + 1d9e6: ea89 0704 eor.w r7, r9, r4 + 1d9ea: 68c4 ldr r4, [r0, #12] + 1d9ec: 4011 ands r1, r2 + 1d9ee: 4066 eors r6, r4 + 1d9f0: 6984 ldr r4, [r0, #24] + 1d9f2: ea08 0802 and.w r8, r8, r2 + 1d9f6: ea84 0a0a eor.w sl, r4, sl + 1d9fa: 69c4 ldr r4, [r0, #28] + 1d9fc: ea0a 0a02 and.w sl, sl, r2 + 1da00: ea84 0905 eor.w r9, r4, r5 + 1da04: 6905 ldr r5, [r0, #16] + 1da06: ea09 0902 and.w r9, r9, r2 + 1da0a: 404d eors r5, r1 + 1da0c: 6941 ldr r1, [r0, #20] + 1da0e: e880 5000 stmia.w r0, {ip, lr} + 1da12: ea88 0401 eor.w r4, r8, r1 + 1da16: 6a01 ldr r1, [r0, #32] + 1da18: 6087 str r7, [r0, #8] + 1da1a: ea81 0803 eor.w r8, r1, r3 + 1da1e: 6a43 ldr r3, [r0, #36] ; 0x24 + 1da20: 6981 ldr r1, [r0, #24] + 1da22: ea83 0b0b eor.w fp, r3, fp + 1da26: 69c3 ldr r3, [r0, #28] + 1da28: ea08 0802 and.w r8, r8, r2 + 1da2c: ea89 0903 eor.w r9, r9, r3 + 1da30: 6a03 ldr r3, [r0, #32] + 1da32: ea8a 0a01 eor.w sl, sl, r1 + 1da36: ea88 0103 eor.w r1, r8, r3 + 1da3a: 6a43 ldr r3, [r0, #36] ; 0x24 + 1da3c: ea0b 0202 and.w r2, fp, r2 + 1da40: 405a eors r2, r3 + 1da42: 60c6 str r6, [r0, #12] + 1da44: 6105 str r5, [r0, #16] + 1da46: 6144 str r4, [r0, #20] + 1da48: f8c0 a018 str.w sl, [r0, #24] + 1da4c: f8c0 901c str.w r9, [r0, #28] + 1da50: 6201 str r1, [r0, #32] + 1da52: 6242 str r2, [r0, #36] ; 0x24 + 1da54: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +0001da58 : + 1da58: 460b mov r3, r1 + 1da5a: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 1da5e: 6849 ldr r1, [r1, #4] + 1da60: f8d2 900c ldr.w r9, [r2, #12] + 1da64: 004c lsls r4, r1, #1 + 1da66: fb89 6704 smull r6, r7, r9, r4 + 1da6a: b0c5 sub sp, #276 ; 0x114 + 1da6c: f8d3 8000 ldr.w r8, [r3] + 1da70: 9118 str r1, [sp, #96] ; 0x60 + 1da72: 6911 ldr r1, [r2, #16] + 1da74: f8d3 c008 ldr.w ip, [r3, #8] + 1da78: fbc1 6708 smlal r6, r7, r1, r8 + 1da7c: 6895 ldr r5, [r2, #8] + 1da7e: e9cd 6706 strd r6, r7, [sp, #24] + 1da82: e9dd ab06 ldrd sl, fp, [sp, #24] + 1da86: fbcc ab05 smlal sl, fp, ip, r5 + 1da8a: 68de ldr r6, [r3, #12] + 1da8c: 940a str r4, [sp, #40] ; 0x28 + 1da8e: 6854 ldr r4, [r2, #4] + 1da90: e9cd ab06 strd sl, fp, [sp, #24] + 1da94: ea4f 0b46 mov.w fp, r6, lsl #1 + 1da98: 9620 str r6, [sp, #128] ; 0x80 + 1da9a: e9dd 6706 ldrd r6, r7, [sp, #24] + 1da9e: fbcb 6704 smlal r6, r7, fp, r4 + 1daa2: f8d3 e010 ldr.w lr, [r3, #16] + 1daa6: 9108 str r1, [sp, #32] + 1daa8: 6811 ldr r1, [r2, #0] + 1daaa: e9cd 6706 strd r6, r7, [sp, #24] + 1daae: f8cd b098 str.w fp, [sp, #152] ; 0x98 + 1dab2: 6a56 ldr r6, [r2, #36] ; 0x24 + 1dab4: e9dd ab06 ldrd sl, fp, [sp, #24] + 1dab8: fbce ab01 smlal sl, fp, lr, r1 + 1dabc: 9639 str r6, [sp, #228] ; 0xe4 + 1dabe: 695e ldr r6, [r3, #20] + 1dac0: e9cd ab06 strd sl, fp, [sp, #24] + 1dac4: 9f39 ldr r7, [sp, #228] ; 0xe4 + 1dac6: ea4f 0a46 mov.w sl, r6, lsl #1 + 1daca: f8cd a0b0 str.w sl, [sp, #176] ; 0xb0 + 1dace: f8dd b0b0 ldr.w fp, [sp, #176] ; 0xb0 + 1dad2: 9101 str r1, [sp, #4] + 1dad4: eb07 01c7 add.w r1, r7, r7, lsl #3 + 1dad8: eb07 0141 add.w r1, r7, r1, lsl #1 + 1dadc: 9622 str r6, [sp, #136] ; 0x88 + 1dade: e9dd 6706 ldrd r6, r7, [sp, #24] + 1dae2: fbcb 6701 smlal r6, r7, fp, r1 + 1dae6: 9110 str r1, [sp, #64] ; 0x40 + 1dae8: e9cd 6706 strd r6, r7, [sp, #24] + 1daec: e9dd ab06 ldrd sl, fp, [sp, #24] + 1daf0: 6a11 ldr r1, [r2, #32] + 1daf2: 699e ldr r6, [r3, #24] + 1daf4: eb01 07c1 add.w r7, r1, r1, lsl #3 + 1daf8: 9603 str r6, [sp, #12] + 1dafa: eb01 0747 add.w r7, r1, r7, lsl #1 + 1dafe: 9116 str r1, [sp, #88] ; 0x58 + 1db00: 9903 ldr r1, [sp, #12] + 1db02: 971c str r7, [sp, #112] ; 0x70 + 1db04: fbc1 ab07 smlal sl, fp, r1, r7 + 1db08: 69d7 ldr r7, [r2, #28] + 1db0a: 69d9 ldr r1, [r3, #28] + 1db0c: 463e mov r6, r7 + 1db0e: 9733 str r7, [sp, #204] ; 0xcc + 1db10: eb07 07c7 add.w r7, r7, r7, lsl #3 + 1db14: eb06 0747 add.w r7, r6, r7, lsl #1 + 1db18: 971e str r7, [sp, #120] ; 0x78 + 1db1a: 9124 str r1, [sp, #144] ; 0x90 + 1db1c: 004f lsls r7, r1, #1 + 1db1e: 991e ldr r1, [sp, #120] ; 0x78 + 1db20: 972e str r7, [sp, #184] ; 0xb8 + 1db22: fbc7 ab01 smlal sl, fp, r7, r1 + 1db26: 6997 ldr r7, [r2, #24] + 1db28: e9cd ab06 strd sl, fp, [sp, #24] + 1db2c: 6a19 ldr r1, [r3, #32] + 1db2e: eb07 0ac7 add.w sl, r7, r7, lsl #3 + 1db32: eb07 0a4a add.w sl, r7, sl, lsl #1 + 1db36: 970e str r7, [sp, #56] ; 0x38 + 1db38: e9dd 6706 ldrd r6, r7, [sp, #24] + 1db3c: fbc1 670a smlal r6, r7, r1, sl + 1db40: 6a5b ldr r3, [r3, #36] ; 0x24 + 1db42: 6952 ldr r2, [r2, #20] + 1db44: 9332 str r3, [sp, #200] ; 0xc8 + 1db46: e9cd 6706 strd r6, r7, [sp, #24] + 1db4a: 9f32 ldr r7, [sp, #200] ; 0xc8 + 1db4c: 9212 str r2, [sp, #72] ; 0x48 + 1db4e: 9e12 ldr r6, [sp, #72] ; 0x48 + 1db50: 9a18 ldr r2, [sp, #96] ; 0x60 + 1db52: 9102 str r1, [sp, #8] + 1db54: 007f lsls r7, r7, #1 + 1db56: 9908 ldr r1, [sp, #32] + 1db58: 9737 str r7, [sp, #220] ; 0xdc + 1db5a: f8cd a0d8 str.w sl, [sp, #216] ; 0xd8 + 1db5e: eb06 03c6 add.w r3, r6, r6, lsl #3 + 1db62: fb81 ab02 smull sl, fp, r1, r2 + 1db66: 9a37 ldr r2, [sp, #220] ; 0xdc + 1db68: eb06 0343 add.w r3, r6, r3, lsl #1 + 1db6c: e9dd 6706 ldrd r6, r7, [sp, #24] + 1db70: fbc2 6703 smlal r6, r7, r2, r3 + 1db74: 9338 str r3, [sp, #224] ; 0xe0 + 1db76: e9cd 6706 strd r6, r7, [sp, #24] + 1db7a: 9b12 ldr r3, [sp, #72] ; 0x48 + 1db7c: 9901 ldr r1, [sp, #4] + 1db7e: fbc3 ab08 smlal sl, fp, r3, r8 + 1db82: fbcc ab09 smlal sl, fp, ip, r9 + 1db86: 9b20 ldr r3, [sp, #128] ; 0x80 + 1db88: 9a22 ldr r2, [sp, #136] ; 0x88 + 1db8a: fbc3 ab05 smlal sl, fp, r3, r5 + 1db8e: fbce ab04 smlal sl, fp, lr, r4 + 1db92: fbc2 ab01 smlal sl, fp, r2, r1 + 1db96: 9b03 ldr r3, [sp, #12] + 1db98: 9910 ldr r1, [sp, #64] ; 0x40 + 1db9a: 9a24 ldr r2, [sp, #144] ; 0x90 + 1db9c: fbc3 ab01 smlal sl, fp, r3, r1 + 1dba0: 9b1c ldr r3, [sp, #112] ; 0x70 + 1dba2: 9902 ldr r1, [sp, #8] + 1dba4: fbc2 ab03 smlal sl, fp, r2, r3 + 1dba8: 9a1e ldr r2, [sp, #120] ; 0x78 + 1dbaa: 9b32 ldr r3, [sp, #200] ; 0xc8 + 1dbac: fbc1 ab02 smlal sl, fp, r1, r2 + 1dbb0: 9936 ldr r1, [sp, #216] ; 0xd8 + 1dbb2: f116 7600 adds.w r6, r6, #33554432 ; 0x2000000 + 1dbb6: fbc3 ab01 smlal sl, fp, r3, r1 + 1dbba: f147 0700 adc.w r7, r7, #0 + 1dbbe: 0eb2 lsrs r2, r6, #26 + 1dbc0: ea42 1387 orr.w r3, r2, r7, lsl #6 + 1dbc4: 16b9 asrs r1, r7, #26 + 1dbc6: 9115 str r1, [sp, #84] ; 0x54 + 1dbc8: 9314 str r3, [sp, #80] ; 0x50 + 1dbca: e9dd 2314 ldrd r2, r3, [sp, #80] ; 0x50 + 1dbce: eb12 020a adds.w r2, r2, sl + 1dbd2: eb43 030b adc.w r3, r3, fp + 1dbd6: e9cd 233e strd r2, r3, [sp, #248] ; 0xf8 + 1dbda: 9e0a ldr r6, [sp, #40] ; 0x28 + 1dbdc: 9b12 ldr r3, [sp, #72] ; 0x48 + 1dbde: 9f0e ldr r7, [sp, #56] ; 0x38 + 1dbe0: fb83 ab06 smull sl, fp, r3, r6 + 1dbe4: fbc7 ab08 smlal sl, fp, r7, r8 + 1dbe8: e9dd 673e ldrd r6, r7, [sp, #248] ; 0xf8 + 1dbec: 9b08 ldr r3, [sp, #32] + 1dbee: 9926 ldr r1, [sp, #152] ; 0x98 + 1dbf0: fbcc ab03 smlal sl, fp, ip, r3 + 1dbf4: fbc1 ab09 smlal sl, fp, r1, r9 + 1dbf8: fbce ab05 smlal sl, fp, lr, r5 + 1dbfc: 9a2c ldr r2, [sp, #176] ; 0xb0 + 1dbfe: 9b01 ldr r3, [sp, #4] + 1dc00: fbc2 ab04 smlal sl, fp, r2, r4 + 1dc04: 9903 ldr r1, [sp, #12] + 1dc06: 9a10 ldr r2, [sp, #64] ; 0x40 + 1dc08: fbc1 ab03 smlal sl, fp, r1, r3 + 1dc0c: 9b2e ldr r3, [sp, #184] ; 0xb8 + 1dc0e: 9902 ldr r1, [sp, #8] + 1dc10: fbc3 ab02 smlal sl, fp, r3, r2 + 1dc14: 9a1c ldr r2, [sp, #112] ; 0x70 + 1dc16: f116 7680 adds.w r6, r6, #16777216 ; 0x1000000 + 1dc1a: fbc1 ab02 smlal sl, fp, r1, r2 + 1dc1e: 9b1e ldr r3, [sp, #120] ; 0x78 + 1dc20: 9937 ldr r1, [sp, #220] ; 0xdc + 1dc22: f147 0700 adc.w r7, r7, #0 + 1dc26: 0e72 lsrs r2, r6, #25 + 1dc28: fbc1 ab03 smlal sl, fp, r1, r3 + 1dc2c: ea42 13c7 orr.w r3, r2, r7, lsl #7 + 1dc30: 9328 str r3, [sp, #160] ; 0xa0 + 1dc32: 9a10 ldr r2, [sp, #64] ; 0x40 + 1dc34: 9b0a ldr r3, [sp, #40] ; 0x28 + 1dc36: a940 add r1, sp, #256 ; 0x100 + 1dc38: fb83 2302 smull r2, r3, r3, r2 + 1dc3c: e9cd 2304 strd r2, r3, [sp, #16] + 1dc40: 167b asrs r3, r7, #25 + 1dc42: 9329 str r3, [sp, #164] ; 0xa4 + 1dc44: e9dd 6728 ldrd r6, r7, [sp, #160] ; 0xa0 + 1dc48: eb16 060a adds.w r6, r6, sl + 1dc4c: eb47 070b adc.w r7, r7, fp + 1dc50: e9c1 6700 strd r6, r7, [r1] + 1dc54: e9dd 2304 ldrd r2, r3, [sp, #16] + 1dc58: 9e01 ldr r6, [sp, #4] + 1dc5a: 9f1c ldr r7, [sp, #112] ; 0x70 + 1dc5c: fbc6 2308 smlal r2, r3, r6, r8 + 1dc60: fbc7 230c smlal r2, r3, r7, ip + 1dc64: f8dd a098 ldr.w sl, [sp, #152] ; 0x98 + 1dc68: f8dd b078 ldr.w fp, [sp, #120] ; 0x78 + 1dc6c: 9936 ldr r1, [sp, #216] ; 0xd8 + 1dc6e: fbcb 230a smlal r2, r3, fp, sl + 1dc72: fbc1 230e smlal r2, r3, r1, lr + 1dc76: 9e2c ldr r6, [sp, #176] ; 0xb0 + 1dc78: 9f38 ldr r7, [sp, #224] ; 0xe0 + 1dc7a: 9908 ldr r1, [sp, #32] + 1dc7c: fbc7 2306 smlal r2, r3, r7, r6 + 1dc80: e9cd 2304 strd r2, r3, [sp, #16] + 1dc84: eb01 03c1 add.w r3, r1, r1, lsl #3 + 1dc88: eb01 0343 add.w r3, r1, r3, lsl #1 + 1dc8c: 933a str r3, [sp, #232] ; 0xe8 + 1dc8e: 9e03 ldr r6, [sp, #12] + 1dc90: 9f3a ldr r7, [sp, #232] ; 0xe8 + 1dc92: e9dd 2304 ldrd r2, r3, [sp, #16] + 1dc96: fbc7 2306 smlal r2, r3, r7, r6 + 1dc9a: e9cd 2304 strd r2, r3, [sp, #16] + 1dc9e: e9dd ab04 ldrd sl, fp, [sp, #16] + 1dca2: eb09 03c9 add.w r3, r9, r9, lsl #3 + 1dca6: 990e ldr r1, [sp, #56] ; 0x38 + 1dca8: 9e18 ldr r6, [sp, #96] ; 0x60 + 1dcaa: eb09 0343 add.w r3, r9, r3, lsl #1 + 1dcae: 933b str r3, [sp, #236] ; 0xec + 1dcb0: fb81 2306 smull r2, r3, r1, r6 + 1dcb4: 992e ldr r1, [sp, #184] ; 0xb8 + 1dcb6: 9e3b ldr r6, [sp, #236] ; 0xec + 1dcb8: 9f33 ldr r7, [sp, #204] ; 0xcc + 1dcba: fbc6 ab01 smlal sl, fp, r6, r1 + 1dcbe: e9cd ab04 strd sl, fp, [sp, #16] + 1dcc2: eb05 0ac5 add.w sl, r5, r5, lsl #3 + 1dcc6: eb05 0a4a add.w sl, r5, sl, lsl #1 + 1dcca: f8cd a0d0 str.w sl, [sp, #208] ; 0xd0 + 1dcce: 9902 ldr r1, [sp, #8] + 1dcd0: 9e34 ldr r6, [sp, #208] ; 0xd0 + 1dcd2: e9dd ab04 ldrd sl, fp, [sp, #16] + 1dcd6: fbc6 ab01 smlal sl, fp, r6, r1 + 1dcda: a940 add r1, sp, #256 ; 0x100 + 1dcdc: e9cd ab04 strd sl, fp, [sp, #16] + 1dce0: e9d1 ab00 ldrd sl, fp, [r1] + 1dce4: f11a 7a00 adds.w sl, sl, #33554432 ; 0x2000000 + 1dce8: f14b 0b00 adc.w fp, fp, #0 + 1dcec: e9cd ab30 strd sl, fp, [sp, #192] ; 0xc0 + 1dcf0: 9937 ldr r1, [sp, #220] ; 0xdc + 1dcf2: eb04 0ac4 add.w sl, r4, r4, lsl #3 + 1dcf6: eb04 064a add.w r6, r4, sl, lsl #1 + 1dcfa: fbc7 2308 smlal r2, r3, r7, r8 + 1dcfe: e9dd ab04 ldrd sl, fp, [sp, #16] + 1dd02: fbc6 ab01 smlal sl, fp, r6, r1 + 1dd06: 9f12 ldr r7, [sp, #72] ; 0x48 + 1dd08: e9cd ab04 strd sl, fp, [sp, #16] + 1dd0c: fbcc 2307 smlal r2, r3, ip, r7 + 1dd10: 9e01 ldr r6, [sp, #4] + 1dd12: 9f18 ldr r7, [sp, #96] ; 0x60 + 1dd14: 9908 ldr r1, [sp, #32] + 1dd16: fb86 ab07 smull sl, fp, r6, r7 + 1dd1a: 9e20 ldr r6, [sp, #128] ; 0x80 + 1dd1c: fbc4 ab08 smlal sl, fp, r4, r8 + 1dd20: fbc6 2301 smlal r2, r3, r6, r1 + 1dd24: e9dd 6704 ldrd r6, r7, [sp, #16] + 1dd28: f116 7600 adds.w r6, r6, #33554432 ; 0x2000000 + 1dd2c: f147 0700 adc.w r7, r7, #0 + 1dd30: e9cd 671a strd r6, r7, [sp, #104] ; 0x68 + 1dd34: 9f10 ldr r7, [sp, #64] ; 0x40 + 1dd36: 9e1c ldr r6, [sp, #112] ; 0x70 + 1dd38: fbcc ab07 smlal sl, fp, ip, r7 + 1dd3c: 9920 ldr r1, [sp, #128] ; 0x80 + 1dd3e: fbce 2309 smlal r2, r3, lr, r9 + 1dd42: 9f22 ldr r7, [sp, #136] ; 0x88 + 1dd44: fbc1 ab06 smlal sl, fp, r1, r6 + 1dd48: fbc7 2305 smlal r2, r3, r7, r5 + 1dd4c: 991e ldr r1, [sp, #120] ; 0x78 + 1dd4e: 9e03 ldr r6, [sp, #12] + 1dd50: fbce ab01 smlal sl, fp, lr, r1 + 1dd54: fbc6 2304 smlal r2, r3, r6, r4 + 1dd58: 9936 ldr r1, [sp, #216] ; 0xd8 + 1dd5a: 9e01 ldr r6, [sp, #4] + 1dd5c: fbc7 ab01 smlal sl, fp, r7, r1 + 1dd60: 9f24 ldr r7, [sp, #144] ; 0x90 + 1dd62: 9903 ldr r1, [sp, #12] + 1dd64: fbc7 2306 smlal r2, r3, r7, r6 + 1dd68: 9e38 ldr r6, [sp, #224] ; 0xe0 + 1dd6a: 9f02 ldr r7, [sp, #8] + 1dd6c: fbc1 ab06 smlal sl, fp, r1, r6 + 1dd70: 9910 ldr r1, [sp, #64] ; 0x40 + 1dd72: 9e24 ldr r6, [sp, #144] ; 0x90 + 1dd74: fbc7 2301 smlal r2, r3, r7, r1 + 1dd78: 9f3a ldr r7, [sp, #232] ; 0xe8 + 1dd7a: 9932 ldr r1, [sp, #200] ; 0xc8 + 1dd7c: fbc6 ab07 smlal sl, fp, r6, r7 + 1dd80: 9e1c ldr r6, [sp, #112] ; 0x70 + 1dd82: 9f30 ldr r7, [sp, #192] ; 0xc0 + 1dd84: fbc1 2306 smlal r2, r3, r1, r6 + 1dd88: 9931 ldr r1, [sp, #196] ; 0xc4 + 1dd8a: 9e31 ldr r6, [sp, #196] ; 0xc4 + 1dd8c: 0ebf lsrs r7, r7, #26 + 1dd8e: ea47 1181 orr.w r1, r7, r1, lsl #6 + 1dd92: 912a str r1, [sp, #168] ; 0xa8 + 1dd94: 9f02 ldr r7, [sp, #8] + 1dd96: 993b ldr r1, [sp, #236] ; 0xec + 1dd98: 16b6 asrs r6, r6, #26 + 1dd9a: 962b str r6, [sp, #172] ; 0xac + 1dd9c: fbc7 ab01 smlal sl, fp, r7, r1 + 1dda0: e9dd 672a ldrd r6, r7, [sp, #168] ; 0xa8 + 1dda4: 18b6 adds r6, r6, r2 + 1dda6: 415f adcs r7, r3 + 1dda8: a942 add r1, sp, #264 ; 0x108 + 1ddaa: e9c1 6700 strd r6, r7, [r1] + 1ddae: 9e1a ldr r6, [sp, #104] ; 0x68 + 1ddb0: 9f1b ldr r7, [sp, #108] ; 0x6c + 1ddb2: 9b34 ldr r3, [sp, #208] ; 0xd0 + 1ddb4: 9a32 ldr r2, [sp, #200] ; 0xc8 + 1ddb6: 0eb6 lsrs r6, r6, #26 + 1ddb8: ea46 1787 orr.w r7, r6, r7, lsl #6 + 1ddbc: 970c str r7, [sp, #48] ; 0x30 + 1ddbe: fbc2 ab03 smlal sl, fp, r2, r3 + 1ddc2: 991b ldr r1, [sp, #108] ; 0x6c + 1ddc4: 9e0a ldr r6, [sp, #40] ; 0x28 + 1ddc6: 1689 asrs r1, r1, #26 + 1ddc8: 910d str r1, [sp, #52] ; 0x34 + 1ddca: e9dd 230c ldrd r2, r3, [sp, #48] ; 0x30 + 1ddce: eb12 020a adds.w r2, r2, sl + 1ddd2: eb43 030b adc.w r3, r3, fp + 1ddd6: e9cd 233c strd r2, r3, [sp, #240] ; 0xf0 + 1ddda: 9b33 ldr r3, [sp, #204] ; 0xcc + 1dddc: 9f16 ldr r7, [sp, #88] ; 0x58 + 1ddde: fb83 ab06 smull sl, fp, r3, r6 + 1dde2: ae42 add r6, sp, #264 ; 0x108 + 1dde4: e9d6 2300 ldrd r2, r3, [r6] + 1dde8: fbc7 ab08 smlal sl, fp, r7, r8 + 1ddec: f112 7280 adds.w r2, r2, #16777216 ; 0x1000000 + 1ddf0: f143 0300 adc.w r3, r3, #0 + 1ddf4: e9cd 2334 strd r2, r3, [sp, #208] ; 0xd0 + 1ddf8: 9e0a ldr r6, [sp, #40] ; 0x28 + 1ddfa: 9b0e ldr r3, [sp, #56] ; 0x38 + 1ddfc: 9926 ldr r1, [sp, #152] ; 0x98 + 1ddfe: fbcc ab03 smlal sl, fp, ip, r3 + 1de02: fb84 2306 smull r2, r3, r4, r6 + 1de06: fbc5 2308 smlal r2, r3, r5, r8 + 1de0a: 9f12 ldr r7, [sp, #72] ; 0x48 + 1de0c: 9e01 ldr r6, [sp, #4] + 1de0e: fbc1 ab07 smlal sl, fp, r1, r7 + 1de12: fbcc 2306 smlal r2, r3, ip, r6 + 1de16: e9dd 673c ldrd r6, r7, [sp, #240] ; 0xf0 + 1de1a: f116 7680 adds.w r6, r6, #16777216 ; 0x1000000 + 1de1e: f147 0700 adc.w r7, r7, #0 + 1de22: e9cd 6730 strd r6, r7, [sp, #192] ; 0xc0 + 1de26: 9f08 ldr r7, [sp, #32] + 1de28: 9e1c ldr r6, [sp, #112] ; 0x70 + 1de2a: fbce ab07 smlal sl, fp, lr, r7 + 1de2e: 9f10 ldr r7, [sp, #64] ; 0x40 + 1de30: fbc1 2307 smlal r2, r3, r1, r7 + 1de34: 992c ldr r1, [sp, #176] ; 0xb0 + 1de36: 9f03 ldr r7, [sp, #12] + 1de38: fbc1 ab09 smlal sl, fp, r1, r9 + 1de3c: fbce 2306 smlal r2, r3, lr, r6 + 1de40: fbc7 ab05 smlal sl, fp, r7, r5 + 1de44: 9e1e ldr r6, [sp, #120] ; 0x78 + 1de46: 9f2e ldr r7, [sp, #184] ; 0xb8 + 1de48: fbc1 2306 smlal r2, r3, r1, r6 + 1de4c: fbc7 ab04 smlal sl, fp, r7, r4 + 1de50: 9e36 ldr r6, [sp, #216] ; 0xd8 + 1de52: 9903 ldr r1, [sp, #12] + 1de54: 9f01 ldr r7, [sp, #4] + 1de56: fbc1 2306 smlal r2, r3, r1, r6 + 1de5a: 9902 ldr r1, [sp, #8] + 1de5c: 9e38 ldr r6, [sp, #224] ; 0xe0 + 1de5e: fbc1 ab07 smlal sl, fp, r1, r7 + 1de62: 9f2e ldr r7, [sp, #184] ; 0xb8 + 1de64: 9910 ldr r1, [sp, #64] ; 0x40 + 1de66: fbc7 2306 smlal r2, r3, r7, r6 + 1de6a: 9e37 ldr r6, [sp, #220] ; 0xdc + 1de6c: 9f34 ldr r7, [sp, #208] ; 0xd0 + 1de6e: fbc6 ab01 smlal sl, fp, r6, r1 + 1de72: 9935 ldr r1, [sp, #212] ; 0xd4 + 1de74: 0e7f lsrs r7, r7, #25 + 1de76: ea47 11c1 orr.w r1, r7, r1, lsl #7 + 1de7a: 911a str r1, [sp, #104] ; 0x68 + 1de7c: 9e35 ldr r6, [sp, #212] ; 0xd4 + 1de7e: 993a ldr r1, [sp, #232] ; 0xe8 + 1de80: 9f02 ldr r7, [sp, #8] + 1de82: 1676 asrs r6, r6, #25 + 1de84: 961b str r6, [sp, #108] ; 0x6c + 1de86: fbc7 2301 smlal r2, r3, r7, r1 + 1de8a: e9dd 671a ldrd r6, r7, [sp, #104] ; 0x68 + 1de8e: eb16 060a adds.w r6, r6, sl + 1de92: eb47 070b adc.w r7, r7, fp + 1de96: e9cd 672e strd r6, r7, [sp, #184] ; 0xb8 + 1de9a: f8dd a0dc ldr.w sl, [sp, #220] ; 0xdc + 1de9e: 9f3b ldr r7, [sp, #236] ; 0xec + 1dea0: f8dd b0c0 ldr.w fp, [sp, #192] ; 0xc0 + 1dea4: fbca 2307 smlal r2, r3, sl, r7 + 1dea8: 9931 ldr r1, [sp, #196] ; 0xc4 + 1deaa: 9e31 ldr r6, [sp, #196] ; 0xc4 + 1deac: ea4f 6b5b mov.w fp, fp, lsr #25 + 1deb0: ea4b 11c1 orr.w r1, fp, r1, lsl #7 + 1deb4: 1676 asrs r6, r6, #25 + 1deb6: 910a str r1, [sp, #40] ; 0x28 + 1deb8: 960b str r6, [sp, #44] ; 0x2c + 1deba: e9dd ab0a ldrd sl, fp, [sp, #40] ; 0x28 + 1debe: 9916 ldr r1, [sp, #88] ; 0x58 + 1dec0: eb1a 0a02 adds.w sl, sl, r2 + 1dec4: 9a18 ldr r2, [sp, #96] ; 0x60 + 1dec6: eb4b 0b03 adc.w fp, fp, r3 + 1deca: e9cd ab2c strd sl, fp, [sp, #176] ; 0xb0 + 1dece: e9dd 672e ldrd r6, r7, [sp, #184] ; 0xb8 + 1ded2: fb81 ab02 smull sl, fp, r1, r2 + 1ded6: 9b39 ldr r3, [sp, #228] ; 0xe4 + 1ded8: f116 7600 adds.w r6, r6, #33554432 ; 0x2000000 + 1dedc: f147 0700 adc.w r7, r7, #0 + 1dee0: e9cd 6726 strd r6, r7, [sp, #152] ; 0x98 + 1dee4: fbc3 ab08 smlal sl, fp, r3, r8 + 1dee8: 9e18 ldr r6, [sp, #96] ; 0x60 + 1deea: 9f33 ldr r7, [sp, #204] ; 0xcc + 1deec: fb85 2306 smull r2, r3, r5, r6 + 1def0: fbcc ab07 smlal sl, fp, ip, r7 + 1def4: 990e ldr r1, [sp, #56] ; 0x38 + 1def6: 9e20 ldr r6, [sp, #128] ; 0x80 + 1def8: fbc9 2308 smlal r2, r3, r9, r8 + 1defc: fbc6 ab01 smlal sl, fp, r6, r1 + 1df00: e9dd 672c ldrd r6, r7, [sp, #176] ; 0xb0 + 1df04: f116 7600 adds.w r6, r6, #33554432 ; 0x2000000 + 1df08: f147 0700 adc.w r7, r7, #0 + 1df0c: e9cd 6718 strd r6, r7, [sp, #96] ; 0x60 + 1df10: fbcc 2304 smlal r2, r3, ip, r4 + 1df14: 9f12 ldr r7, [sp, #72] ; 0x48 + 1df16: 9901 ldr r1, [sp, #4] + 1df18: 9e20 ldr r6, [sp, #128] ; 0x80 + 1df1a: fbce ab07 smlal sl, fp, lr, r7 + 1df1e: fbc6 2301 smlal r2, r3, r6, r1 + 1df22: 9f08 ldr r7, [sp, #32] + 1df24: 9922 ldr r1, [sp, #136] ; 0x88 + 1df26: 9e10 ldr r6, [sp, #64] ; 0x40 + 1df28: fbc1 ab07 smlal sl, fp, r1, r7 + 1df2c: fbce 2306 smlal r2, r3, lr, r6 + 1df30: 9f03 ldr r7, [sp, #12] + 1df32: f8dd c070 ldr.w ip, [sp, #112] ; 0x70 + 1df36: fbc7 ab09 smlal sl, fp, r7, r9 + 1df3a: fbc1 230c smlal r2, r3, r1, ip + 1df3e: 9924 ldr r1, [sp, #144] ; 0x90 + 1df40: 9e02 ldr r6, [sp, #8] + 1df42: fbc1 ab05 smlal sl, fp, r1, r5 + 1df46: 9d1e ldr r5, [sp, #120] ; 0x78 + 1df48: fbc6 ab04 smlal sl, fp, r6, r4 + 1df4c: fbc7 2305 smlal r2, r3, r7, r5 + 1df50: 9f36 ldr r7, [sp, #216] ; 0xd8 + 1df52: 9d26 ldr r5, [sp, #152] ; 0x98 + 1df54: 9e27 ldr r6, [sp, #156] ; 0x9c + 1df56: 9c32 ldr r4, [sp, #200] ; 0xc8 + 1df58: fbc1 2307 smlal r2, r3, r1, r7 + 1df5c: 0ead lsrs r5, r5, #26 + 1df5e: 9901 ldr r1, [sp, #4] + 1df60: ea45 1686 orr.w r6, r5, r6, lsl #6 + 1df64: 9616 str r6, [sp, #88] ; 0x58 + 1df66: fbc4 ab01 smlal sl, fp, r4, r1 + 1df6a: 9f27 ldr r7, [sp, #156] ; 0x9c + 1df6c: 9c38 ldr r4, [sp, #224] ; 0xe0 + 1df6e: 9902 ldr r1, [sp, #8] + 1df70: 16bf asrs r7, r7, #26 + 1df72: 9717 str r7, [sp, #92] ; 0x5c + 1df74: e9dd 6716 ldrd r6, r7, [sp, #88] ; 0x58 + 1df78: fbc1 2304 smlal r2, r3, r1, r4 + 1df7c: eb16 060a adds.w r6, r6, sl + 1df80: eb47 070b adc.w r7, r7, fp + 1df84: e9cd 6722 strd r6, r7, [sp, #136] ; 0x88 + 1df88: f8dd a0e8 ldr.w sl, [sp, #232] ; 0xe8 + 1df8c: 9f32 ldr r7, [sp, #200] ; 0xc8 + 1df8e: f8dd b060 ldr.w fp, [sp, #96] ; 0x60 + 1df92: fbc7 230a smlal r2, r3, r7, sl + 1df96: e9dd 6722 ldrd r6, r7, [sp, #136] ; 0x88 + 1df9a: f8dd c064 ldr.w ip, [sp, #100] ; 0x64 + 1df9e: f8dd e064 ldr.w lr, [sp, #100] ; 0x64 + 1dfa2: ea4f 6b9b mov.w fp, fp, lsr #26 + 1dfa6: ea4b 1c8c orr.w ip, fp, ip, lsl #6 + 1dfaa: ea4f 6eae mov.w lr, lr, asr #26 + 1dfae: f8cd c038 str.w ip, [sp, #56] ; 0x38 + 1dfb2: f8cd e03c str.w lr, [sp, #60] ; 0x3c + 1dfb6: e9dd 450e ldrd r4, r5, [sp, #56] ; 0x38 + 1dfba: 18a4 adds r4, r4, r2 + 1dfbc: 415d adcs r5, r3 + 1dfbe: f8dd c054 ldr.w ip, [sp, #84] ; 0x54 + 1dfc2: 9b0c ldr r3, [sp, #48] ; 0x30 + 1dfc4: e9cd 4518 strd r4, r5, [sp, #96] ; 0x60 + 1dfc8: 9d0d ldr r5, [sp, #52] ; 0x34 + 1dfca: f116 7680 adds.w r6, r6, #16777216 ; 0x1000000 + 1dfce: ea4f 698c mov.w r9, ip, lsl #26 + 1dfd2: f8dd c050 ldr.w ip, [sp, #80] ; 0x50 + 1dfd6: f147 0700 adc.w r7, r7, #0 + 1dfda: ea4f 6b85 mov.w fp, r5, lsl #26 + 1dfde: ea4f 6a83 mov.w sl, r3, lsl #26 + 1dfe2: e9dd 4518 ldrd r4, r5, [sp, #96] ; 0x60 + 1dfe6: f114 7480 adds.w r4, r4, #16777216 ; 0x1000000 + 1dfea: f145 0500 adc.w r5, r5, #0 + 1dfee: ea4b 1b93 orr.w fp, fp, r3, lsr #6 + 1dff2: ea4f 688c mov.w r8, ip, lsl #26 + 1dff6: e9dd 2304 ldrd r2, r3, [sp, #16] + 1dffa: 0e71 lsrs r1, r6, #25 + 1dffc: ebb2 0a0a subs.w sl, r2, sl + 1e000: eb63 0b0b sbc.w fp, r3, fp + 1e004: ea41 11c7 orr.w r1, r1, r7, lsl #7 + 1e008: e9dd 2306 ldrd r2, r3, [sp, #24] + 1e00c: 2613 movs r6, #19 + 1e00e: ebb2 0808 subs.w r8, r2, r8 + 1e012: ea49 199c orr.w r9, r9, ip, lsr #6 + 1e016: eb63 0909 sbc.w r9, r3, r9 + 1e01a: fba1 2306 umull r2, r3, r1, r6 + 1e01e: ea4f 6e67 mov.w lr, r7, asr #25 + 1e022: fb06 330e mla r3, r6, lr, r3 + 1e026: 0e66 lsrs r6, r4, #25 + 1e028: ea46 17c5 orr.w r7, r6, r5, lsl #7 + 1e02c: eb12 040a adds.w r4, r2, sl + 1e030: ea4f 6c65 mov.w ip, r5, asr #25 + 1e034: f04f 0200 mov.w r2, #0 + 1e038: eb43 050b adc.w r5, r3, fp + 1e03c: f8cd c024 str.w ip, [sp, #36] ; 0x24 + 1e040: 9708 str r7, [sp, #32] + 1e042: 2300 movs r3, #0 + 1e044: e9dd 6708 ldrd r6, r7, [sp, #32] + 1e048: 4692 mov sl, r2 + 1e04a: eb16 0608 adds.w r6, r6, r8 + 1e04e: 469b mov fp, r3 + 1e050: eb47 0709 adc.w r7, r7, r9 + 1e054: 4699 mov r9, r3 + 1e056: e9cd 4524 strd r4, r5, [sp, #144] ; 0x90 + 1e05a: f114 7400 adds.w r4, r4, #33554432 ; 0x2000000 + 1e05e: e9cd 6720 strd r6, r7, [sp, #128] ; 0x80 + 1e062: f145 0500 adc.w r5, r5, #0 + 1e066: f116 7600 adds.w r6, r6, #33554432 ; 0x2000000 + 1e06a: e9cd 451e strd r4, r5, [sp, #120] ; 0x78 + 1e06e: f147 0700 adc.w r7, r7, #0 + 1e072: 4654 mov r4, sl + 1e074: 465d mov r5, fp + 1e076: e9cd 671c strd r6, r7, [sp, #112] ; 0x70 + 1e07a: 4616 mov r6, r2 + 1e07c: 464f mov r7, r9 + 1e07e: 4690 mov r8, r2 + 1e080: f8dd b02c ldr.w fp, [sp, #44] ; 0x2c + 1e084: e9cd 450c strd r4, r5, [sp, #48] ; 0x30 + 1e088: 9d29 ldr r5, [sp, #164] ; 0xa4 + 1e08a: e9cd 6706 strd r6, r7, [sp, #24] + 1e08e: e9cd 6712 strd r6, r7, [sp, #72] ; 0x48 + 1e092: 9f0a ldr r7, [sp, #40] ; 0x28 + 1e094: 4614 mov r4, r2 + 1e096: ea4f 634b mov.w r3, fp, lsl #25 + 1e09a: ea4f 6b45 mov.w fp, r5, lsl #25 + 1e09e: 464d mov r5, r9 + 1e0a0: 4646 mov r6, r8 + 1e0a2: ea43 13d7 orr.w r3, r3, r7, lsr #7 + 1e0a6: 067a lsls r2, r7, #25 + 1e0a8: 464f mov r7, r9 + 1e0aa: f8dd c0a0 ldr.w ip, [sp, #160] ; 0xa0 + 1e0ae: e9cd 4510 strd r4, r5, [sp, #64] ; 0x40 + 1e0b2: e9cd 4514 strd r4, r5, [sp, #80] ; 0x50 + 1e0b6: e9dd 453c ldrd r4, r5, [sp, #240] ; 0xf0 + 1e0ba: ea4f 6a4c mov.w sl, ip, lsl #25 + 1e0be: 1aa2 subs r2, r4, r2 + 1e0c0: e9cd 670a strd r6, r7, [sp, #40] ; 0x28 + 1e0c4: e9dd 673e ldrd r6, r7, [sp, #248] ; 0xf8 + 1e0c8: eb65 0303 sbc.w r3, r5, r3 + 1e0cc: ea4b 1bdc orr.w fp, fp, ip, lsr #7 + 1e0d0: ebb6 060a subs.w r6, r6, sl + 1e0d4: f8dd a070 ldr.w sl, [sp, #112] ; 0x70 + 1e0d8: eb67 070b sbc.w r7, r7, fp + 1e0dc: e9cd 6726 strd r6, r7, [sp, #152] ; 0x98 + 1e0e0: ea4f 649a mov.w r4, sl, lsr #26 + 1e0e4: 9f1e ldr r7, [sp, #120] ; 0x78 + 1e0e6: f8dd a0ac ldr.w sl, [sp, #172] ; 0xac + 1e0ea: f8dd b07c ldr.w fp, [sp, #124] ; 0x7c + 1e0ee: f8dd c074 ldr.w ip, [sp, #116] ; 0x74 + 1e0f2: ea4f 6897 mov.w r8, r7, lsr #26 + 1e0f6: ea4f 6a8a mov.w sl, sl, lsl #26 + 1e0fa: ea48 188b orr.w r8, r8, fp, lsl #6 + 1e0fe: f8cd a034 str.w sl, [sp, #52] ; 0x34 + 1e102: ea4f 69ab mov.w r9, fp, asr #26 + 1e106: f8dd a06c ldr.w sl, [sp, #108] ; 0x6c + 1e10a: f8dd b03c ldr.w fp, [sp, #60] ; 0x3c + 1e10e: ea4f 65ac mov.w r5, ip, asr #26 + 1e112: ea44 148c orr.w r4, r4, ip, lsl #6 + 1e116: ea4f 6e85 mov.w lr, r5, lsl #26 + 1e11a: f8dd c024 ldr.w ip, [sp, #36] ; 0x24 + 1e11e: ea4f 6b8b mov.w fp, fp, lsl #26 + 1e122: ea4f 6a4a mov.w sl, sl, lsl #25 + 1e126: f8cd b01c str.w fp, [sp, #28] + 1e12a: f8cd e04c str.w lr, [sp, #76] ; 0x4c + 1e12e: f8cd a054 str.w sl, [sp, #84] ; 0x54 + 1e132: f8dd e034 ldr.w lr, [sp, #52] ; 0x34 + 1e136: f8dd a0a8 ldr.w sl, [sp, #168] ; 0xa8 + 1e13a: f8dd b05c ldr.w fp, [sp, #92] ; 0x5c + 1e13e: ea4f 6689 mov.w r6, r9, lsl #26 + 1e142: ea4f 6c4c mov.w ip, ip, lsl #25 + 1e146: f8cd c044 str.w ip, [sp, #68] ; 0x44 + 1e14a: ea4e 1e9a orr.w lr, lr, sl, lsr #6 + 1e14e: ea46 1c98 orr.w ip, r6, r8, lsr #6 + 1e152: ea4f 6b8b mov.w fp, fp, lsl #26 + 1e156: f8dd a020 ldr.w sl, [sp, #32] + 1e15a: f8cd b02c str.w fp, [sp, #44] ; 0x2c + 1e15e: f8cd c014 str.w ip, [sp, #20] + 1e162: f8dd b01c ldr.w fp, [sp, #28] + 1e166: f8dd c038 ldr.w ip, [sp, #56] ; 0x38 + 1e16a: f8cd e034 str.w lr, [sp, #52] ; 0x34 + 1e16e: f8dd e044 ldr.w lr, [sp, #68] ; 0x44 + 1e172: ea4b 1b9c orr.w fp, fp, ip, lsr #6 + 1e176: ea4e 1eda orr.w lr, lr, sl, lsr #7 + 1e17a: f8cd b01c str.w fp, [sp, #28] + 1e17e: f8cd e044 str.w lr, [sp, #68] ; 0x44 + 1e182: f8dd c054 ldr.w ip, [sp, #84] ; 0x54 + 1e186: f8dd e068 ldr.w lr, [sp, #104] ; 0x68 + 1e18a: f8dd b04c ldr.w fp, [sp, #76] ; 0x4c + 1e18e: ea4c 1cde orr.w ip, ip, lr, lsr #7 + 1e192: f8dd e0a8 ldr.w lr, [sp, #168] ; 0xa8 + 1e196: ea4b 1b94 orr.w fp, fp, r4, lsr #6 + 1e19a: ea4f 6e8e mov.w lr, lr, lsl #26 + 1e19e: f8cd e030 str.w lr, [sp, #48] ; 0x30 + 1e1a2: f8dd e058 ldr.w lr, [sp, #88] ; 0x58 + 1e1a6: f8cd b04c str.w fp, [sp, #76] ; 0x4c + 1e1aa: ea4f 6e8e mov.w lr, lr, lsl #26 + 1e1ae: f8cd e028 str.w lr, [sp, #40] ; 0x28 + 1e1b2: 4686 mov lr, r0 + 1e1b4: f8dd a02c ldr.w sl, [sp, #44] ; 0x2c + 1e1b8: f8dd b058 ldr.w fp, [sp, #88] ; 0x58 + 1e1bc: 064e lsls r6, r1, #25 + 1e1be: ea4a 1a9b orr.w sl, sl, fp, lsr #6 + 1e1c2: f8cd a02c str.w sl, [sp, #44] ; 0x2c + 1e1c6: 990e ldr r1, [sp, #56] ; 0x38 + 1e1c8: f8dd a020 ldr.w sl, [sp, #32] + 1e1cc: f8cd c054 str.w ip, [sp, #84] ; 0x54 + 1e1d0: ea4f 6c88 mov.w ip, r8, lsl #26 + 1e1d4: f8cd c010 str.w ip, [sp, #16] + 1e1d8: ea4f 6b84 mov.w fp, r4, lsl #26 + 1e1dc: 0689 lsls r1, r1, #26 + 1e1de: ea4f 6a4a mov.w sl, sl, lsl #25 + 1e1e2: 9106 str r1, [sp, #24] + 1e1e4: f8cd a040 str.w sl, [sp, #64] ; 0x40 + 1e1e8: e9dd 0104 ldrd r0, r1, [sp, #16] + 1e1ec: f8cd b048 str.w fp, [sp, #72] ; 0x48 + 1e1f0: e9dd ab24 ldrd sl, fp, [sp, #144] ; 0x90 + 1e1f4: ebba 0a00 subs.w sl, sl, r0 + 1e1f8: eb6b 0b01 sbc.w fp, fp, r1 + 1e1fc: e9cd ab04 strd sl, fp, [sp, #16] + 1e200: eb12 0a08 adds.w sl, r2, r8 + 1e204: eb43 0b09 adc.w fp, r3, r9 + 1e208: ab40 add r3, sp, #256 ; 0x100 + 1e20a: e9d3 0100 ldrd r0, r1, [r3] + 1e20e: e9dd 230c ldrd r2, r3, [sp, #48] ; 0x30 + 1e212: 1a80 subs r0, r0, r2 + 1e214: eb61 0103 sbc.w r1, r1, r3 + 1e218: f8dd c068 ldr.w ip, [sp, #104] ; 0x68 + 1e21c: e9dd 2306 ldrd r2, r3, [sp, #24] + 1e220: e9cd ab08 strd sl, fp, [sp, #32] + 1e224: e9dd ab2c ldrd sl, fp, [sp, #176] ; 0xb0 + 1e228: e9dd 8920 ldrd r8, r9, [sp, #128] ; 0x80 + 1e22c: ebba 0a02 subs.w sl, sl, r2 + 1e230: eb6b 0b03 sbc.w fp, fp, r3 + 1e234: e9cd 010c strd r0, r1, [sp, #48] ; 0x30 + 1e238: e9dd 2310 ldrd r2, r3, [sp, #64] ; 0x40 + 1e23c: e9dd 010a ldrd r0, r1, [sp, #40] ; 0x28 + 1e240: e9cd ab06 strd sl, fp, [sp, #24] + 1e244: e9dd ab18 ldrd sl, fp, [sp, #96] ; 0x60 + 1e248: 9904 ldr r1, [sp, #16] + 1e24a: ebba 0a02 subs.w sl, sl, r2 + 1e24e: ea4f 6c4c mov.w ip, ip, lsl #25 + 1e252: eb6b 0b03 sbc.w fp, fp, r3 + 1e256: f8cd c050 str.w ip, [sp, #80] ; 0x50 + 1e25a: ab42 add r3, sp, #264 ; 0x108 + 1e25c: e9cd ab0e strd sl, fp, [sp, #56] ; 0x38 + 1e260: e9dd ab26 ldrd sl, fp, [sp, #152] ; 0x98 + 1e264: eb1a 0a04 adds.w sl, sl, r4 + 1e268: e9dd 4512 ldrd r4, r5, [sp, #72] ; 0x48 + 1e26c: ebb8 0804 subs.w r8, r8, r4 + 1e270: e9d3 4500 ldrd r4, r5, [r3] + 1e274: e9dd 2314 ldrd r2, r3, [sp, #80] ; 0x50 + 1e278: 1aa4 subs r4, r4, r2 + 1e27a: e9dd 2322 ldrd r2, r3, [sp, #136] ; 0x88 + 1e27e: 1b96 subs r6, r2, r6 + 1e280: e9dd 232e ldrd r2, r3, [sp, #184] ; 0xb8 + 1e284: f8ce 1000 str.w r1, [lr] + 1e288: 1a12 subs r2, r2, r0 + 1e28a: 990c ldr r1, [sp, #48] ; 0x30 + 1e28c: 9808 ldr r0, [sp, #32] + 1e28e: f8ce 1018 str.w r1, [lr, #24] + 1e292: f8ce 0004 str.w r0, [lr, #4] + 1e296: 990e ldr r1, [sp, #56] ; 0x38 + 1e298: 9806 ldr r0, [sp, #24] + 1e29a: f8ce 100c str.w r1, [lr, #12] + 1e29e: f8ce 0008 str.w r0, [lr, #8] + 1e2a2: f8ce a014 str.w sl, [lr, #20] + 1e2a6: f8ce 8010 str.w r8, [lr, #16] + 1e2aa: f8ce 6024 str.w r6, [lr, #36] ; 0x24 + 1e2ae: f8ce 401c str.w r4, [lr, #28] + 1e2b2: f8ce 2020 str.w r2, [lr, #32] + 1e2b6: b045 add sp, #276 ; 0x114 + 1e2b8: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +0001e2bc : + 1e2bc: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} + 1e2c0: f8d1 c004 ldr.w ip, [r1, #4] + 1e2c4: f8d1 e008 ldr.w lr, [r1, #8] + 1e2c8: 68cf ldr r7, [r1, #12] + 1e2ca: 690e ldr r6, [r1, #16] + 1e2cc: 694d ldr r5, [r1, #20] + 1e2ce: 698c ldr r4, [r1, #24] + 1e2d0: 6a0a ldr r2, [r1, #32] + 1e2d2: 6a4b ldr r3, [r1, #36] ; 0x24 + 1e2d4: f8d1 8000 ldr.w r8, [r1] + 1e2d8: f8d1 901c ldr.w r9, [r1, #28] + 1e2dc: f1cc 0c00 rsb ip, ip, #0 + 1e2e0: f1ce 0e00 rsb lr, lr, #0 + 1e2e4: 427f negs r7, r7 + 1e2e6: 4276 negs r6, r6 + 1e2e8: 426d negs r5, r5 + 1e2ea: 4264 negs r4, r4 + 1e2ec: f1c9 0100 rsb r1, r9, #0 + 1e2f0: 4252 negs r2, r2 + 1e2f2: f1c8 0800 rsb r8, r8, #0 + 1e2f6: 425b negs r3, r3 + 1e2f8: e880 5100 stmia.w r0, {r8, ip, lr} + 1e2fc: 60c7 str r7, [r0, #12] + 1e2fe: 6106 str r6, [r0, #16] + 1e300: 6145 str r5, [r0, #20] + 1e302: 6184 str r4, [r0, #24] + 1e304: 61c1 str r1, [r0, #28] + 1e306: 6202 str r2, [r0, #32] + 1e308: 6243 str r3, [r0, #36] ; 0x24 + 1e30a: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + 1e30e: bf00 nop + +0001e310 : + 1e310: 460b mov r3, r1 + 1e312: 6849 ldr r1, [r1, #4] + 1e314: 68da ldr r2, [r3, #12] + 1e316: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 1e31a: ea4f 0c41 mov.w ip, r1, lsl #1 + 1e31e: 0054 lsls r4, r2, #1 + 1e320: fb8c 6704 smull r6, r7, ip, r4 + 1e324: b0b9 sub sp, #228 ; 0xe4 + 1e326: f8d3 a000 ldr.w sl, [r3] + 1e32a: e9cd 6708 strd r6, r7, [sp, #32] + 1e32e: e9dd 8908 ldrd r8, r9, [sp, #32] + 1e332: 691f ldr r7, [r3, #16] + 1e334: ea4f 0e4a mov.w lr, sl, lsl #1 + 1e338: fbc7 890e smlal r8, r9, r7, lr + 1e33c: 9224 str r2, [sp, #144] ; 0x90 + 1e33e: 689a ldr r2, [r3, #8] + 1e340: e9cd 8908 strd r8, r9, [sp, #32] + 1e344: 9110 str r1, [sp, #64] ; 0x40 + 1e346: 9402 str r4, [sp, #8] + 1e348: 6a59 ldr r1, [r3, #36] ; 0x24 + 1e34a: e9dd 4508 ldrd r4, r5, [sp, #32] + 1e34e: fbc2 4502 smlal r4, r5, r2, r2 + 1e352: f04f 0b26 mov.w fp, #38 ; 0x26 + 1e356: fb0b f901 mul.w r9, fp, r1 + 1e35a: 921a str r2, [sp, #104] ; 0x68 + 1e35c: 9128 str r1, [sp, #160] ; 0xa0 + 1e35e: 6a1a ldr r2, [r3, #32] + 1e360: 6959 ldr r1, [r3, #20] + 1e362: e9cd 4508 strd r4, r5, [sp, #32] + 1e366: 911c str r1, [sp, #112] ; 0x70 + 1e368: 004c lsls r4, r1, #1 + 1e36a: 4611 mov r1, r2 + 1e36c: 9401 str r4, [sp, #4] + 1e36e: 9e01 ldr r6, [sp, #4] + 1e370: e9dd 4508 ldrd r4, r5, [sp, #32] + 1e374: fbc9 4506 smlal r4, r5, r9, r6 + 1e378: 699e ldr r6, [r3, #24] + 1e37a: 69db ldr r3, [r3, #28] + 1e37c: 9203 str r2, [sp, #12] + 1e37e: 9320 str r3, [sp, #128] ; 0x80 + 1e380: eb02 02c2 add.w r2, r2, r2, lsl #3 + 1e384: eb01 0842 add.w r8, r1, r2, lsl #1 + 1e388: 9a20 ldr r2, [sp, #128] ; 0x80 + 1e38a: 0073 lsls r3, r6, #1 + 1e38c: fb0b f202 mul.w r2, fp, r2 + 1e390: fbc3 4508 smlal r4, r5, r3, r8 + 1e394: 9b20 ldr r3, [sp, #128] ; 0x80 + 1e396: 9222 str r2, [sp, #136] ; 0x88 + 1e398: fbc2 4503 smlal r4, r5, r2, r3 + 1e39c: fb87 230c smull r2, r3, r7, ip + 1e3a0: e9cd 4508 strd r4, r5, [sp, #32] + 1e3a4: f114 7400 adds.w r4, r4, #33554432 ; 0x2000000 + 1e3a8: f145 0500 adc.w r5, r5, #0 + 1e3ac: e9cd 4506 strd r4, r5, [sp, #24] + 1e3b0: 9c1c ldr r4, [sp, #112] ; 0x70 + 1e3b2: 9d1a ldr r5, [sp, #104] ; 0x68 + 1e3b4: fbc4 230e smlal r2, r3, r4, lr + 1e3b8: 006d lsls r5, r5, #1 + 1e3ba: 951e str r5, [sp, #120] ; 0x78 + 1e3bc: 9924 ldr r1, [sp, #144] ; 0x90 + 1e3be: 9c20 ldr r4, [sp, #128] ; 0x80 + 1e3c0: fbc5 2301 smlal r2, r3, r5, r1 + 1e3c4: fbc9 2306 smlal r2, r3, r9, r6 + 1e3c8: 9d06 ldr r5, [sp, #24] + 1e3ca: 0064 lsls r4, r4, #1 + 1e3cc: fbc8 2304 smlal r2, r3, r8, r4 + 1e3d0: 9907 ldr r1, [sp, #28] + 1e3d2: 940a str r4, [sp, #40] ; 0x28 + 1e3d4: 9c07 ldr r4, [sp, #28] + 1e3d6: 0ead lsrs r5, r5, #26 + 1e3d8: ea45 1181 orr.w r1, r5, r1, lsl #6 + 1e3dc: 16a4 asrs r4, r4, #26 + 1e3de: 910c str r1, [sp, #48] ; 0x30 + 1e3e0: 940d str r4, [sp, #52] ; 0x34 + 1e3e2: e9dd 450c ldrd r4, r5, [sp, #48] ; 0x30 + 1e3e6: 18a4 adds r4, r4, r2 + 1e3e8: 415d adcs r5, r3 + 1e3ea: e9cd 452e strd r4, r5, [sp, #184] ; 0xb8 + 1e3ee: f114 7480 adds.w r4, r4, #16777216 ; 0x1000000 + 1e3f2: f145 0500 adc.w r5, r5, #0 + 1e3f6: e9cd 4506 strd r4, r5, [sp, #24] + 1e3fa: 9c01 ldr r4, [sp, #4] + 1e3fc: 9d1e ldr r5, [sp, #120] ; 0x78 + 1e3fe: fb8c 2304 smull r2, r3, ip, r4 + 1e402: fbc6 230e smlal r2, r3, r6, lr + 1e406: fbc5 2307 smlal r2, r3, r5, r7 + 1e40a: 9924 ldr r1, [sp, #144] ; 0x90 + 1e40c: 9c02 ldr r4, [sp, #8] + 1e40e: 9d0a ldr r5, [sp, #40] ; 0x28 + 1e410: fbc4 2301 smlal r2, r3, r4, r1 + 1e414: fbc9 2305 smlal r2, r3, r9, r5 + 1e418: 9903 ldr r1, [sp, #12] + 1e41a: 9c06 ldr r4, [sp, #24] + 1e41c: fbc8 2301 smlal r2, r3, r8, r1 + 1e420: 9d07 ldr r5, [sp, #28] + 1e422: 9907 ldr r1, [sp, #28] + 1e424: 0e64 lsrs r4, r4, #25 + 1e426: ea44 15c5 orr.w r5, r4, r5, lsl #7 + 1e42a: 1649 asrs r1, r1, #25 + 1e42c: 910f str r1, [sp, #60] ; 0x3c + 1e42e: 950e str r5, [sp, #56] ; 0x38 + 1e430: e9dd 450e ldrd r4, r5, [sp, #56] ; 0x38 + 1e434: 18a4 adds r4, r4, r2 + 1e436: 415d adcs r5, r3 + 1e438: fb8c 2309 smull r2, r3, ip, r9 + 1e43c: fbca 230a smlal r2, r3, sl, sl + 1e440: e9cd 4532 strd r4, r5, [sp, #200] ; 0xc8 + 1e444: 9c1e ldr r4, [sp, #120] ; 0x78 + 1e446: 9d02 ldr r5, [sp, #8] + 1e448: fbc8 2304 smlal r2, r3, r8, r4 + 1e44c: f8dd a088 ldr.w sl, [sp, #136] ; 0x88 + 1e450: eb06 04c6 add.w r4, r6, r6, lsl #3 + 1e454: fbca 2305 smlal r2, r3, sl, r5 + 1e458: 0079 lsls r1, r7, #1 + 1e45a: e9cd 2306 strd r2, r3, [sp, #24] + 1e45e: eb06 0444 add.w r4, r6, r4, lsl #1 + 1e462: 9a1c ldr r2, [sp, #112] ; 0x70 + 1e464: 912a str r1, [sp, #168] ; 0xa8 + 1e466: 9414 str r4, [sp, #80] ; 0x50 + 1e468: fb0b f102 mul.w r1, fp, r2 + 1e46c: e9dd 4506 ldrd r4, r5, [sp, #24] + 1e470: f8dd a0a8 ldr.w sl, [sp, #168] ; 0xa8 + 1e474: f8dd b050 ldr.w fp, [sp, #80] ; 0x50 + 1e478: fbcb 450a smlal r4, r5, fp, sl + 1e47c: e9cd 4506 strd r4, r5, [sp, #24] + 1e480: e9dd 2332 ldrd r2, r3, [sp, #200] ; 0xc8 + 1e484: e9dd ab06 ldrd sl, fp, [sp, #24] + 1e488: f112 7200 adds.w r2, r2, #33554432 ; 0x2000000 + 1e48c: f143 0300 adc.w r3, r3, #0 + 1e490: e9cd 2316 strd r2, r3, [sp, #88] ; 0x58 + 1e494: 9a1c ldr r2, [sp, #112] ; 0x70 + 1e496: 9d20 ldr r5, [sp, #128] ; 0x80 + 1e498: fbc1 ab02 smlal sl, fp, r1, r2 + 1e49c: fb86 230c smull r2, r3, r6, ip + 1e4a0: fbc5 230e smlal r2, r3, r5, lr + 1e4a4: 991c ldr r1, [sp, #112] ; 0x70 + 1e4a6: 9c1e ldr r4, [sp, #120] ; 0x78 + 1e4a8: e9cd ab06 strd sl, fp, [sp, #24] + 1e4ac: fbc4 2301 smlal r2, r3, r4, r1 + 1e4b0: 991a ldr r1, [sp, #104] ; 0x68 + 1e4b2: f11a 7a00 adds.w sl, sl, #33554432 ; 0x2000000 + 1e4b6: fb81 4509 smull r4, r5, r1, r9 + 1e4ba: f14b 0b00 adc.w fp, fp, #0 + 1e4be: 9910 ldr r1, [sp, #64] ; 0x40 + 1e4c0: e9cd ab12 strd sl, fp, [sp, #72] ; 0x48 + 1e4c4: f8dd a008 ldr.w sl, [sp, #8] + 1e4c8: fbc1 450e smlal r4, r5, r1, lr + 1e4cc: fbca 2307 smlal r2, r3, sl, r7 + 1e4d0: 9903 ldr r1, [sp, #12] + 1e4d2: fbc8 450a smlal r4, r5, r8, sl + 1e4d6: f8dd a058 ldr.w sl, [sp, #88] ; 0x58 + 1e4da: fbc9 2301 smlal r2, r3, r9, r1 + 1e4de: f8dd b05c ldr.w fp, [sp, #92] ; 0x5c + 1e4e2: 9917 ldr r1, [sp, #92] ; 0x5c + 1e4e4: ea4f 6a9a mov.w sl, sl, lsr #26 + 1e4e8: ea4a 1b8b orr.w fp, sl, fp, lsl #6 + 1e4ec: 1689 asrs r1, r1, #26 + 1e4ee: f8dd a088 ldr.w sl, [sp, #136] ; 0x88 + 1e4f2: 9119 str r1, [sp, #100] ; 0x64 + 1e4f4: f8cd b060 str.w fp, [sp, #96] ; 0x60 + 1e4f8: fbca 4507 smlal r4, r5, sl, r7 + 1e4fc: e9dd ab18 ldrd sl, fp, [sp, #96] ; 0x60 + 1e500: eb1a 0a02 adds.w sl, sl, r2 + 1e504: eb4b 0b03 adc.w fp, fp, r3 + 1e508: e9cd ab34 strd sl, fp, [sp, #208] ; 0xd0 + 1e50c: 9914 ldr r1, [sp, #80] ; 0x50 + 1e50e: f8dd b004 ldr.w fp, [sp, #4] + 1e512: 9a12 ldr r2, [sp, #72] ; 0x48 + 1e514: fbc1 450b smlal r4, r5, r1, fp + 1e518: 9b13 ldr r3, [sp, #76] ; 0x4c + 1e51a: f8dd a04c ldr.w sl, [sp, #76] ; 0x4c + 1e51e: 0e92 lsrs r2, r2, #26 + 1e520: ea42 1383 orr.w r3, r2, r3, lsl #6 + 1e524: ea4f 6aaa mov.w sl, sl, asr #26 + 1e528: f8cd a014 str.w sl, [sp, #20] + 1e52c: 9304 str r3, [sp, #16] + 1e52e: e9dd 2304 ldrd r2, r3, [sp, #16] + 1e532: 1912 adds r2, r2, r4 + 1e534: 416b adcs r3, r5 + 1e536: f8dd b028 ldr.w fp, [sp, #40] ; 0x28 + 1e53a: e9dd 4534 ldrd r4, r5, [sp, #208] ; 0xd0 + 1e53e: f114 7480 adds.w r4, r4, #16777216 ; 0x1000000 + 1e542: f145 0500 adc.w r5, r5, #0 + 1e546: e9cd 4526 strd r4, r5, [sp, #152] ; 0x98 + 1e54a: e9cd 232c strd r2, r3, [sp, #176] ; 0xb0 + 1e54e: fb8c 450b smull r4, r5, ip, fp + 1e552: f112 7280 adds.w r2, r2, #16777216 ; 0x1000000 + 1e556: f143 0300 adc.w r3, r3, #0 + 1e55a: e9cd 2316 strd r2, r3, [sp, #88] ; 0x58 + 1e55e: 9b03 ldr r3, [sp, #12] + 1e560: f8dd a078 ldr.w sl, [sp, #120] ; 0x78 + 1e564: fbc3 450e smlal r4, r5, r3, lr + 1e568: fbca 4506 smlal r4, r5, sl, r6 + 1e56c: f8dd b008 ldr.w fp, [sp, #8] + 1e570: 9901 ldr r1, [sp, #4] + 1e572: f8dd a0a8 ldr.w sl, [sp, #168] ; 0xa8 + 1e576: fbc1 450b smlal r4, r5, r1, fp + 1e57a: 9910 ldr r1, [sp, #64] ; 0x40 + 1e57c: fbc7 4507 smlal r4, r5, r7, r7 + 1e580: fb81 230c smull r2, r3, r1, ip + 1e584: 991a ldr r1, [sp, #104] ; 0x68 + 1e586: fbc1 230e smlal r2, r3, r1, lr + 1e58a: fbc9 230b smlal r2, r3, r9, fp + 1e58e: fbca 2308 smlal r2, r3, sl, r8 + 1e592: f8dd a098 ldr.w sl, [sp, #152] ; 0x98 + 1e596: f8dd b09c ldr.w fp, [sp, #156] ; 0x9c + 1e59a: 9928 ldr r1, [sp, #160] ; 0xa0 + 1e59c: ea4f 6a5a mov.w sl, sl, lsr #25 + 1e5a0: ea4a 1bcb orr.w fp, sl, fp, lsl #7 + 1e5a4: f8cd b048 str.w fp, [sp, #72] ; 0x48 + 1e5a8: fbc9 4501 smlal r4, r5, r9, r1 + 1e5ac: 9927 ldr r1, [sp, #156] ; 0x9c + 1e5ae: f8dd a004 ldr.w sl, [sp, #4] + 1e5b2: f8dd b088 ldr.w fp, [sp, #136] ; 0x88 + 1e5b6: 1649 asrs r1, r1, #25 + 1e5b8: 9113 str r1, [sp, #76] ; 0x4c + 1e5ba: fbcb 230a smlal r2, r3, fp, sl + 1e5be: e9dd ab12 ldrd sl, fp, [sp, #72] ; 0x48 + 1e5c2: eb1a 0a04 adds.w sl, sl, r4 + 1e5c6: eb4b 0b05 adc.w fp, fp, r5 + 1e5ca: e9cd ab36 strd sl, fp, [sp, #216] ; 0xd8 + 1e5ce: f8dd b050 ldr.w fp, [sp, #80] ; 0x50 + 1e5d2: 9916 ldr r1, [sp, #88] ; 0x58 + 1e5d4: fbcb 2306 smlal r2, r3, fp, r6 + 1e5d8: 9c17 ldr r4, [sp, #92] ; 0x5c + 1e5da: 9d17 ldr r5, [sp, #92] ; 0x5c + 1e5dc: 0e49 lsrs r1, r1, #25 + 1e5de: ea41 14c4 orr.w r4, r1, r4, lsl #7 + 1e5e2: 166d asrs r5, r5, #25 + 1e5e4: 940a str r4, [sp, #40] ; 0x28 + 1e5e6: 950b str r5, [sp, #44] ; 0x2c + 1e5e8: e9dd ab0a ldrd sl, fp, [sp, #40] ; 0x28 + 1e5ec: eb1a 0a02 adds.w sl, sl, r2 + 1e5f0: eb4b 0b03 adc.w fp, fp, r3 + 1e5f4: 9c03 ldr r4, [sp, #12] + 1e5f6: e9dd 2336 ldrd r2, r3, [sp, #216] ; 0xd8 + 1e5fa: f112 7200 adds.w r2, r2, #33554432 ; 0x2000000 + 1e5fe: f143 0300 adc.w r3, r3, #0 + 1e602: e9cd 2326 strd r2, r3, [sp, #152] ; 0x98 + 1e606: fb84 230c smull r2, r3, r4, ip + 1e60a: 9d28 ldr r5, [sp, #160] ; 0xa0 + 1e60c: 991a ldr r1, [sp, #104] ; 0x68 + 1e60e: fbc5 230e smlal r2, r3, r5, lr + 1e612: fb81 450c smull r4, r5, r1, ip + 1e616: 9920 ldr r1, [sp, #128] ; 0x80 + 1e618: f8dd c078 ldr.w ip, [sp, #120] ; 0x78 + 1e61c: e9cd ab30 strd sl, fp, [sp, #192] ; 0xc0 + 1e620: fbcc 2301 smlal r2, r3, ip, r1 + 1e624: 9924 ldr r1, [sp, #144] ; 0x90 + 1e626: f8dd c008 ldr.w ip, [sp, #8] + 1e62a: fbc1 450e smlal r4, r5, r1, lr + 1e62e: fbcc 2306 smlal r2, r3, ip, r6 + 1e632: 991c ldr r1, [sp, #112] ; 0x70 + 1e634: fbc9 4507 smlal r4, r5, r9, r7 + 1e638: 9f2a ldr r7, [sp, #168] ; 0xa8 + 1e63a: f8dd 9098 ldr.w r9, [sp, #152] ; 0x98 + 1e63e: fbc7 2301 smlal r2, r3, r7, r1 + 1e642: f8dd c09c ldr.w ip, [sp, #156] ; 0x9c + 1e646: f8dd e09c ldr.w lr, [sp, #156] ; 0x9c + 1e64a: ea4f 6999 mov.w r9, r9, lsr #26 + 1e64e: 9901 ldr r1, [sp, #4] + 1e650: ea49 1c8c orr.w ip, r9, ip, lsl #6 + 1e654: ea4f 6eae mov.w lr, lr, asr #26 + 1e658: f11a 7a00 adds.w sl, sl, #33554432 ; 0x2000000 + 1e65c: f8cd c050 str.w ip, [sp, #80] ; 0x50 + 1e660: f8cd e054 str.w lr, [sp, #84] ; 0x54 + 1e664: f14b 0b00 adc.w fp, fp, #0 + 1e668: fbc8 4501 smlal r4, r5, r8, r1 + 1e66c: e9dd 8914 ldrd r8, r9, [sp, #80] ; 0x50 + 1e670: eb18 0802 adds.w r8, r8, r2 + 1e674: eb49 0903 adc.w r9, r9, r3 + 1e678: e9cd 8924 strd r8, r9, [sp, #144] ; 0x90 + 1e67c: f8dd 9088 ldr.w r9, [sp, #136] ; 0x88 + 1e680: ea4f 6c9a mov.w ip, sl, lsr #26 + 1e684: fbc9 4506 smlal r4, r5, r9, r6 + 1e688: ea4c 1e8b orr.w lr, ip, fp, lsl #6 + 1e68c: ea4f 61ab mov.w r1, fp, asr #26 + 1e690: f8cd e040 str.w lr, [sp, #64] ; 0x40 + 1e694: 9111 str r1, [sp, #68] ; 0x44 + 1e696: e9dd 2310 ldrd r2, r3, [sp, #64] ; 0x40 + 1e69a: 1912 adds r2, r2, r4 + 1e69c: 416b adcs r3, r5 + 1e69e: 9d0d ldr r5, [sp, #52] ; 0x34 + 1e6a0: f8dd b030 ldr.w fp, [sp, #48] ; 0x30 + 1e6a4: f8dd a010 ldr.w sl, [sp, #16] + 1e6a8: 9c05 ldr r4, [sp, #20] + 1e6aa: ea4f 6985 mov.w r9, r5, lsl #26 + 1e6ae: e9cd 231e strd r2, r3, [sp, #120] ; 0x78 + 1e6b2: e9dd 6724 ldrd r6, r7, [sp, #144] ; 0x90 + 1e6b6: ea49 199b orr.w r9, r9, fp, lsr #6 + 1e6ba: f116 7680 adds.w r6, r6, #16777216 ; 0x1000000 + 1e6be: f8dd b030 ldr.w fp, [sp, #48] ; 0x30 + 1e6c2: f147 0700 adc.w r7, r7, #0 + 1e6c6: ea4f 628a mov.w r2, sl, lsl #26 + 1e6ca: 06a3 lsls r3, r4, #26 + 1e6cc: e9dd 451e ldrd r4, r5, [sp, #120] ; 0x78 + 1e6d0: f114 7480 adds.w r4, r4, #16777216 ; 0x1000000 + 1e6d4: f145 0500 adc.w r5, r5, #0 + 1e6d8: ea43 139a orr.w r3, r3, sl, lsr #6 + 1e6dc: ea4f 688b mov.w r8, fp, lsl #26 + 1e6e0: 0e71 lsrs r1, r6, #25 + 1e6e2: e9dd ab06 ldrd sl, fp, [sp, #24] + 1e6e6: ebba 0a02 subs.w sl, sl, r2 + 1e6ea: eb6b 0b03 sbc.w fp, fp, r3 + 1e6ee: ea41 11c7 orr.w r1, r1, r7, lsl #7 + 1e6f2: e9dd 2308 ldrd r2, r3, [sp, #32] + 1e6f6: 2613 movs r6, #19 + 1e6f8: ebb2 0808 subs.w r8, r2, r8 + 1e6fc: eb63 0909 sbc.w r9, r3, r9 + 1e700: fba1 2306 umull r2, r3, r1, r6 + 1e704: ea4f 6e67 mov.w lr, r7, asr #25 + 1e708: fb06 330e mla r3, r6, lr, r3 + 1e70c: 0e66 lsrs r6, r4, #25 + 1e70e: ea46 17c5 orr.w r7, r6, r5, lsl #7 + 1e712: ea4f 6c65 mov.w ip, r5, asr #25 + 1e716: eb12 040a adds.w r4, r2, sl + 1e71a: f8cd c014 str.w ip, [sp, #20] + 1e71e: 9704 str r7, [sp, #16] + 1e720: eb43 050b adc.w r5, r3, fp + 1e724: e9dd 6704 ldrd r6, r7, [sp, #16] + 1e728: eb16 0608 adds.w r6, r6, r8 + 1e72c: e9cd 4522 strd r4, r5, [sp, #136] ; 0x88 + 1e730: eb47 0709 adc.w r7, r7, r9 + 1e734: f114 7400 adds.w r4, r4, #33554432 ; 0x2000000 + 1e738: f8dd c028 ldr.w ip, [sp, #40] ; 0x28 + 1e73c: f8dd 802c ldr.w r8, [sp, #44] ; 0x2c + 1e740: f8dd 903c ldr.w r9, [sp, #60] ; 0x3c + 1e744: f145 0500 adc.w r5, r5, #0 + 1e748: e9cd 451c strd r4, r5, [sp, #112] ; 0x70 + 1e74c: 9c0e ldr r4, [sp, #56] ; 0x38 + 1e74e: e9cd 6720 strd r6, r7, [sp, #128] ; 0x80 + 1e752: ea4f 624c mov.w r2, ip, lsl #25 + 1e756: f116 7600 adds.w r6, r6, #33554432 ; 0x2000000 + 1e75a: ea4f 6348 mov.w r3, r8, lsl #25 + 1e75e: ea4f 6b49 mov.w fp, r9, lsl #25 + 1e762: f04f 0800 mov.w r8, #0 + 1e766: f04f 0900 mov.w r9, #0 + 1e76a: f147 0700 adc.w r7, r7, #0 + 1e76e: ea43 13dc orr.w r3, r3, ip, lsr #7 + 1e772: e9cd 8906 strd r8, r9, [sp, #24] + 1e776: e9dd 892c ldrd r8, r9, [sp, #176] ; 0xb0 + 1e77a: ea4f 6a44 mov.w sl, r4, lsl #25 + 1e77e: ebb8 0802 subs.w r8, r8, r2 + 1e782: f04f 0500 mov.w r5, #0 + 1e786: eb69 0903 sbc.w r9, r9, r3 + 1e78a: ea4b 1bd4 orr.w fp, fp, r4, lsr #7 + 1e78e: e9dd 232e ldrd r2, r3, [sp, #184] ; 0xb8 + 1e792: 2400 movs r4, #0 + 1e794: ebb2 020a subs.w r2, r2, sl + 1e798: eb63 030b sbc.w r3, r3, fp + 1e79c: 46a2 mov sl, r4 + 1e79e: 46ab mov fp, r5 + 1e7a0: e9cd 8928 strd r8, r9, [sp, #160] ; 0xa0 + 1e7a4: 46a0 mov r8, r4 + 1e7a6: 46a9 mov r9, r5 + 1e7a8: e9cd 232a strd r2, r3, [sp, #168] ; 0xa8 + 1e7ac: 4622 mov r2, r4 + 1e7ae: 462b mov r3, r5 + 1e7b0: e9cd ab0a strd sl, fp, [sp, #40] ; 0x28 + 1e7b4: f8dd a074 ldr.w sl, [sp, #116] ; 0x74 + 1e7b8: e9cd 890c strd r8, r9, [sp, #48] ; 0x30 + 1e7bc: ea4f 69aa mov.w r9, sl, asr #26 + 1e7c0: ea4f 6b89 mov.w fp, r9, lsl #26 + 1e7c4: e9cd 4516 strd r4, r5, [sp, #88] ; 0x58 + 1e7c8: e9cd 4508 strd r4, r5, [sp, #32] + 1e7cc: e9cd 230e strd r2, r3, [sp, #56] ; 0x38 + 1e7d0: 9b1c ldr r3, [sp, #112] ; 0x70 + 1e7d2: f8cd b01c str.w fp, [sp, #28] + 1e7d6: f8dd c064 ldr.w ip, [sp, #100] ; 0x64 + 1e7da: ea4f 6893 mov.w r8, r3, lsr #26 + 1e7de: 0eb4 lsrs r4, r6, #26 + 1e7e0: ea4f 638c mov.w r3, ip, lsl #26 + 1e7e4: 9e05 ldr r6, [sp, #20] + 1e7e6: f8dd c04c ldr.w ip, [sp, #76] ; 0x4c + 1e7ea: 16bd asrs r5, r7, #26 + 1e7ec: ea4f 6e4e mov.w lr, lr, lsl #25 + 1e7f0: ea44 1487 orr.w r4, r4, r7, lsl #6 + 1e7f4: f8cd e05c str.w lr, [sp, #92] ; 0x5c + 1e7f8: 06af lsls r7, r5, #26 + 1e7fa: f8dd e044 ldr.w lr, [sp, #68] ; 0x44 + 1e7fe: 0676 lsls r6, r6, #25 + 1e800: ea4f 6c4c mov.w ip, ip, lsl #25 + 1e804: 9609 str r6, [sp, #36] ; 0x24 + 1e806: 970d str r7, [sp, #52] ; 0x34 + 1e808: f8cd c02c str.w ip, [sp, #44] ; 0x2c + 1e80c: 9e07 ldr r6, [sp, #28] + 1e80e: 9f17 ldr r7, [sp, #92] ; 0x5c + 1e810: f8dd c060 ldr.w ip, [sp, #96] ; 0x60 + 1e814: ea48 188a orr.w r8, r8, sl, lsl #6 + 1e818: ea4f 6b8e mov.w fp, lr, lsl #26 + 1e81c: f8dd e054 ldr.w lr, [sp, #84] ; 0x54 + 1e820: ea46 1698 orr.w r6, r6, r8, lsr #6 + 1e824: ea47 17d1 orr.w r7, r7, r1, lsr #7 + 1e828: ea43 139c orr.w r3, r3, ip, lsr #6 + 1e82c: f8dd c034 ldr.w ip, [sp, #52] ; 0x34 + 1e830: 9607 str r6, [sp, #28] + 1e832: 9717 str r7, [sp, #92] ; 0x5c + 1e834: 9e09 ldr r6, [sp, #36] ; 0x24 + 1e836: 9f04 ldr r7, [sp, #16] + 1e838: ea4f 6e8e mov.w lr, lr, lsl #26 + 1e83c: f8cd e03c str.w lr, [sp, #60] ; 0x3c + 1e840: ea4c 1c94 orr.w ip, ip, r4, lsr #6 + 1e844: f8dd e040 ldr.w lr, [sp, #64] ; 0x40 + 1e848: ea46 16d7 orr.w r6, r6, r7, lsr #7 + 1e84c: f8cd c034 str.w ip, [sp, #52] ; 0x34 + 1e850: 9f0f ldr r7, [sp, #60] ; 0x3c + 1e852: f8dd c050 ldr.w ip, [sp, #80] ; 0x50 + 1e856: ea4b 1b9e orr.w fp, fp, lr, lsr #6 + 1e85a: 9609 str r6, [sp, #36] ; 0x24 + 1e85c: f8dd e02c ldr.w lr, [sp, #44] ; 0x2c + 1e860: 9e12 ldr r6, [sp, #72] ; 0x48 + 1e862: ea47 179c orr.w r7, r7, ip, lsr #6 + 1e866: 970f str r7, [sp, #60] ; 0x3c + 1e868: 9f04 ldr r7, [sp, #16] + 1e86a: ea4e 1ed6 orr.w lr, lr, r6, lsr #7 + 1e86e: f8cd e02c str.w lr, [sp, #44] ; 0x2c + 1e872: ea4f 6c84 mov.w ip, r4, lsl #26 + 1e876: ea4f 6e88 mov.w lr, r8, lsl #26 + 1e87a: 0649 lsls r1, r1, #25 + 1e87c: 067f lsls r7, r7, #25 + 1e87e: 9e10 ldr r6, [sp, #64] ; 0x40 + 1e880: f8cd e018 str.w lr, [sp, #24] + 1e884: 9116 str r1, [sp, #88] ; 0x58 + 1e886: 9708 str r7, [sp, #32] + 1e888: 9918 ldr r1, [sp, #96] ; 0x60 + 1e88a: f8cd c030 str.w ip, [sp, #48] ; 0x30 + 1e88e: f8dd e048 ldr.w lr, [sp, #72] ; 0x48 + 1e892: 068a lsls r2, r1, #26 + 1e894: ea4f 6e4e mov.w lr, lr, lsl #25 + 1e898: f8cd e028 str.w lr, [sp, #40] ; 0x28 + 1e89c: 4686 mov lr, r0 + 1e89e: 9914 ldr r1, [sp, #80] ; 0x50 + 1e8a0: ea4f 6a86 mov.w sl, r6, lsl #26 + 1e8a4: 0689 lsls r1, r1, #26 + 1e8a6: 910e str r1, [sp, #56] ; 0x38 + 1e8a8: e9dd 6722 ldrd r6, r7, [sp, #136] ; 0x88 + 1e8ac: e9dd 0106 ldrd r0, r1, [sp, #24] + 1e8b0: 1a36 subs r6, r6, r0 + 1e8b2: eb67 0701 sbc.w r7, r7, r1 + 1e8b6: e9cd 6706 strd r6, r7, [sp, #24] + 1e8ba: e9dd 6728 ldrd r6, r7, [sp, #160] ; 0xa0 + 1e8be: e9dd 010e ldrd r0, r1, [sp, #56] ; 0x38 + 1e8c2: eb16 0608 adds.w r6, r6, r8 + 1e8c6: eb47 0709 adc.w r7, r7, r9 + 1e8ca: e9dd 8932 ldrd r8, r9, [sp, #200] ; 0xc8 + 1e8ce: ebb8 0802 subs.w r8, r8, r2 + 1e8d2: eb69 0903 sbc.w r9, r9, r3 + 1e8d6: e9dd 2330 ldrd r2, r3, [sp, #192] ; 0xc0 + 1e8da: ebb2 020a subs.w r2, r2, sl + 1e8de: e9cd 6704 strd r6, r7, [sp, #16] + 1e8e2: e9dd 671e ldrd r6, r7, [sp, #120] ; 0x78 + 1e8e6: e9cd 8918 strd r8, r9, [sp, #96] ; 0x60 + 1e8ea: e9dd 8908 ldrd r8, r9, [sp, #32] + 1e8ee: eb63 030b sbc.w r3, r3, fp + 1e8f2: 9906 ldr r1, [sp, #24] + 1e8f4: ebb6 0608 subs.w r6, r6, r8 + 1e8f8: eb67 0709 sbc.w r7, r7, r9 + 1e8fc: e9cd 2310 strd r2, r3, [sp, #64] ; 0x40 + 1e900: e9dd ab2a ldrd sl, fp, [sp, #168] ; 0xa8 + 1e904: e9dd 230c ldrd r2, r3, [sp, #48] ; 0x30 + 1e908: e9cd 6708 strd r6, r7, [sp, #32] + 1e90c: e9dd 8920 ldrd r8, r9, [sp, #128] ; 0x80 + 1e910: e9dd 6724 ldrd r6, r7, [sp, #144] ; 0x90 + 1e914: eb1a 0a04 adds.w sl, sl, r4 + 1e918: f8ce 1000 str.w r1, [lr] + 1e91c: ebb8 0802 subs.w r8, r8, r2 + 1e920: e9dd 450a ldrd r4, r5, [sp, #40] ; 0x28 + 1e924: 9918 ldr r1, [sp, #96] ; 0x60 + 1e926: e9dd 2334 ldrd r2, r3, [sp, #208] ; 0xd0 + 1e92a: 1b12 subs r2, r2, r4 + 1e92c: e9dd 4516 ldrd r4, r5, [sp, #88] ; 0x58 + 1e930: 1b36 subs r6, r6, r4 + 1e932: e9dd 4536 ldrd r4, r5, [sp, #216] ; 0xd8 + 1e936: 1a24 subs r4, r4, r0 + 1e938: 9804 ldr r0, [sp, #16] + 1e93a: f8ce 1018 str.w r1, [lr, #24] + 1e93e: f8ce 0004 str.w r0, [lr, #4] + 1e942: 9908 ldr r1, [sp, #32] + 1e944: 9810 ldr r0, [sp, #64] ; 0x40 + 1e946: f8ce 0008 str.w r0, [lr, #8] + 1e94a: f8ce 100c str.w r1, [lr, #12] + 1e94e: f8ce a014 str.w sl, [lr, #20] + 1e952: f8ce 8010 str.w r8, [lr, #16] + 1e956: f8ce 6024 str.w r6, [lr, #36] ; 0x24 + 1e95a: f8ce 201c str.w r2, [lr, #28] + 1e95e: f8ce 4020 str.w r4, [lr, #32] + 1e962: b039 add sp, #228 ; 0xe4 + 1e964: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +0001e968 : + 1e968: b530 push {r4, r5, lr} + 1e96a: 460c mov r4, r1 + 1e96c: b0a9 sub sp, #164 ; 0xa4 + 1e96e: 4605 mov r5, r0 + 1e970: 4668 mov r0, sp + 1e972: f7ff fccd bl 1e310 + 1e976: 4669 mov r1, sp + 1e978: a80a add r0, sp, #40 ; 0x28 + 1e97a: f7ff fcc9 bl 1e310 + 1e97e: a80a add r0, sp, #40 ; 0x28 + 1e980: 4601 mov r1, r0 + 1e982: f7ff fcc5 bl 1e310 + 1e986: a80a add r0, sp, #40 ; 0x28 + 1e988: 4621 mov r1, r4 + 1e98a: 4602 mov r2, r0 + 1e98c: f7ff f864 bl 1da58 + 1e990: aa0a add r2, sp, #40 ; 0x28 + 1e992: 4668 mov r0, sp + 1e994: 4669 mov r1, sp + 1e996: f7ff f85f bl 1da58 + 1e99a: 4669 mov r1, sp + 1e99c: a814 add r0, sp, #80 ; 0x50 + 1e99e: f7ff fcb7 bl 1e310 + 1e9a2: a80a add r0, sp, #40 ; 0x28 + 1e9a4: 4601 mov r1, r0 + 1e9a6: aa14 add r2, sp, #80 ; 0x50 + 1e9a8: f7ff f856 bl 1da58 + 1e9ac: a814 add r0, sp, #80 ; 0x50 + 1e9ae: a90a add r1, sp, #40 ; 0x28 + 1e9b0: f7ff fcae bl 1e310 + 1e9b4: 2404 movs r4, #4 + 1e9b6: a814 add r0, sp, #80 ; 0x50 + 1e9b8: 4601 mov r1, r0 + 1e9ba: f7ff fca9 bl 1e310 + 1e9be: 3c01 subs r4, #1 + 1e9c0: d1f9 bne.n 1e9b6 + 1e9c2: a80a add r0, sp, #40 ; 0x28 + 1e9c4: 4602 mov r2, r0 + 1e9c6: a914 add r1, sp, #80 ; 0x50 + 1e9c8: f7ff f846 bl 1da58 + 1e9cc: a814 add r0, sp, #80 ; 0x50 + 1e9ce: a90a add r1, sp, #40 ; 0x28 + 1e9d0: f7ff fc9e bl 1e310 + 1e9d4: 2409 movs r4, #9 + 1e9d6: a814 add r0, sp, #80 ; 0x50 + 1e9d8: 4601 mov r1, r0 + 1e9da: f7ff fc99 bl 1e310 + 1e9de: 3c01 subs r4, #1 + 1e9e0: d1f9 bne.n 1e9d6 + 1e9e2: a814 add r0, sp, #80 ; 0x50 + 1e9e4: 4601 mov r1, r0 + 1e9e6: aa0a add r2, sp, #40 ; 0x28 + 1e9e8: f7ff f836 bl 1da58 + 1e9ec: a81e add r0, sp, #120 ; 0x78 + 1e9ee: a914 add r1, sp, #80 ; 0x50 + 1e9f0: f7ff fc8e bl 1e310 + 1e9f4: 2413 movs r4, #19 + 1e9f6: a81e add r0, sp, #120 ; 0x78 + 1e9f8: 4601 mov r1, r0 + 1e9fa: f7ff fc89 bl 1e310 + 1e9fe: 3c01 subs r4, #1 + 1ea00: d1f9 bne.n 1e9f6 + 1ea02: a814 add r0, sp, #80 ; 0x50 + 1ea04: 4602 mov r2, r0 + 1ea06: a91e add r1, sp, #120 ; 0x78 + 1ea08: f7ff f826 bl 1da58 + 1ea0c: a814 add r0, sp, #80 ; 0x50 + 1ea0e: 4601 mov r1, r0 + 1ea10: f7ff fc7e bl 1e310 + 1ea14: 2409 movs r4, #9 + 1ea16: a814 add r0, sp, #80 ; 0x50 + 1ea18: 4601 mov r1, r0 + 1ea1a: f7ff fc79 bl 1e310 + 1ea1e: 3c01 subs r4, #1 + 1ea20: d1f9 bne.n 1ea16 + 1ea22: a80a add r0, sp, #40 ; 0x28 + 1ea24: 4602 mov r2, r0 + 1ea26: a914 add r1, sp, #80 ; 0x50 + 1ea28: f7ff f816 bl 1da58 + 1ea2c: a814 add r0, sp, #80 ; 0x50 + 1ea2e: a90a add r1, sp, #40 ; 0x28 + 1ea30: f7ff fc6e bl 1e310 + 1ea34: 2431 movs r4, #49 ; 0x31 + 1ea36: a814 add r0, sp, #80 ; 0x50 + 1ea38: 4601 mov r1, r0 + 1ea3a: f7ff fc69 bl 1e310 + 1ea3e: 3c01 subs r4, #1 + 1ea40: d1f9 bne.n 1ea36 + 1ea42: a814 add r0, sp, #80 ; 0x50 + 1ea44: 4601 mov r1, r0 + 1ea46: aa0a add r2, sp, #40 ; 0x28 + 1ea48: f7ff f806 bl 1da58 + 1ea4c: a81e add r0, sp, #120 ; 0x78 + 1ea4e: a914 add r1, sp, #80 ; 0x50 + 1ea50: f7ff fc5e bl 1e310 + 1ea54: 2463 movs r4, #99 ; 0x63 + 1ea56: a81e add r0, sp, #120 ; 0x78 + 1ea58: 4601 mov r1, r0 + 1ea5a: f7ff fc59 bl 1e310 + 1ea5e: 3c01 subs r4, #1 + 1ea60: d1f9 bne.n 1ea56 + 1ea62: a814 add r0, sp, #80 ; 0x50 + 1ea64: 4602 mov r2, r0 + 1ea66: a91e add r1, sp, #120 ; 0x78 + 1ea68: f7fe fff6 bl 1da58 + 1ea6c: a814 add r0, sp, #80 ; 0x50 + 1ea6e: 4601 mov r1, r0 + 1ea70: f7ff fc4e bl 1e310 + 1ea74: 2431 movs r4, #49 ; 0x31 + 1ea76: a814 add r0, sp, #80 ; 0x50 + 1ea78: 4601 mov r1, r0 + 1ea7a: f7ff fc49 bl 1e310 + 1ea7e: 3c01 subs r4, #1 + 1ea80: d1f9 bne.n 1ea76 + 1ea82: a80a add r0, sp, #40 ; 0x28 + 1ea84: 4602 mov r2, r0 + 1ea86: a914 add r1, sp, #80 ; 0x50 + 1ea88: f7fe ffe6 bl 1da58 + 1ea8c: a80a add r0, sp, #40 ; 0x28 + 1ea8e: 4601 mov r1, r0 + 1ea90: f7ff fc3e bl 1e310 + 1ea94: 2404 movs r4, #4 + 1ea96: a80a add r0, sp, #40 ; 0x28 + 1ea98: 4601 mov r1, r0 + 1ea9a: f7ff fc39 bl 1e310 + 1ea9e: 3c01 subs r4, #1 + 1eaa0: d1f9 bne.n 1ea96 + 1eaa2: 4628 mov r0, r5 + 1eaa4: a90a add r1, sp, #40 ; 0x28 + 1eaa6: 466a mov r2, sp + 1eaa8: f7fe ffd6 bl 1da58 + 1eaac: b029 add sp, #164 ; 0xa4 + 1eaae: bd30 pop {r4, r5, pc} + +0001eab0 : + 1eab0: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 1eab4: 684b ldr r3, [r1, #4] + 1eab6: 6854 ldr r4, [r2, #4] + 1eab8: 6897 ldr r7, [r2, #8] + 1eaba: ebc4 0e03 rsb lr, r4, r3 + 1eabe: 688b ldr r3, [r1, #8] + 1eac0: 690c ldr r4, [r1, #16] + 1eac2: 1bdf subs r7, r3, r7 + 1eac4: 6913 ldr r3, [r2, #16] + 1eac6: b083 sub sp, #12 + 1eac8: 1ae4 subs r4, r4, r3 + 1eaca: 9401 str r4, [sp, #4] + 1eacc: 6a0c ldr r4, [r1, #32] + 1eace: 68ce ldr r6, [r1, #12] + 1ead0: 694b ldr r3, [r1, #20] + 1ead2: 68d5 ldr r5, [r2, #12] + 1ead4: 9400 str r4, [sp, #0] + 1ead6: 6954 ldr r4, [r2, #20] + 1ead8: 1b75 subs r5, r6, r5 + 1eada: 1b1e subs r6, r3, r4 + 1eadc: 698b ldr r3, [r1, #24] + 1eade: 6994 ldr r4, [r2, #24] + 1eae0: f8d1 c01c ldr.w ip, [r1, #28] + 1eae4: ebc4 0903 rsb r9, r4, r3 + 1eae8: 69d3 ldr r3, [r2, #28] + 1eaea: f8d2 8020 ldr.w r8, [r2, #32] + 1eaee: ebc3 0c0c rsb ip, r3, ip + 1eaf2: 9b00 ldr r3, [sp, #0] + 1eaf4: f8d1 a024 ldr.w sl, [r1, #36] ; 0x24 + 1eaf8: f8d2 b000 ldr.w fp, [r2] + 1eafc: 6809 ldr r1, [r1, #0] + 1eafe: 6a52 ldr r2, [r2, #36] ; 0x24 + 1eb00: ebc8 0403 rsb r4, r8, r3 + 1eb04: 9b01 ldr r3, [sp, #4] + 1eb06: ebcb 0101 rsb r1, fp, r1 + 1eb0a: ebc2 020a rsb r2, r2, sl + 1eb0e: e880 4002 stmia.w r0, {r1, lr} + 1eb12: 6087 str r7, [r0, #8] + 1eb14: 60c5 str r5, [r0, #12] + 1eb16: 6103 str r3, [r0, #16] + 1eb18: 6146 str r6, [r0, #20] + 1eb1a: f8c0 9018 str.w r9, [r0, #24] + 1eb1e: f8c0 c01c str.w ip, [r0, #28] + 1eb22: 6204 str r4, [r0, #32] + 1eb24: 6242 str r2, [r0, #36] ; 0x24 + 1eb26: b003 add sp, #12 + 1eb28: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +0001eb2c : + 1eb2c: 6a4b ldr r3, [r1, #36] ; 0x24 + 1eb2e: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 1eb32: eb03 02c3 add.w r2, r3, r3, lsl #3 + 1eb36: f8d1 e000 ldr.w lr, [r1] + 1eb3a: eb03 0242 add.w r2, r3, r2, lsl #1 + 1eb3e: f8d1 9004 ldr.w r9, [r1, #4] + 1eb42: f102 7280 add.w r2, r2, #16777216 ; 0x1000000 + 1eb46: 688f ldr r7, [r1, #8] + 1eb48: eb0e 6262 add.w r2, lr, r2, asr #25 + 1eb4c: 68cd ldr r5, [r1, #12] + 1eb4e: eb09 62a2 add.w r2, r9, r2, asr #26 + 1eb52: eb07 6862 add.w r8, r7, r2, asr #25 + 1eb56: 690a ldr r2, [r1, #16] + 1eb58: 694e ldr r6, [r1, #20] + 1eb5a: eb05 68a8 add.w r8, r5, r8, asr #26 + 1eb5e: 698c ldr r4, [r1, #24] + 1eb60: eb02 6868 add.w r8, r2, r8, asr #25 + 1eb64: f8d1 c01c ldr.w ip, [r1, #28] + 1eb68: eb06 68a8 add.w r8, r6, r8, asr #26 + 1eb6c: 6a09 ldr r1, [r1, #32] + 1eb6e: eb04 6868 add.w r8, r4, r8, asr #25 + 1eb72: eb0c 68a8 add.w r8, ip, r8, asr #26 + 1eb76: b085 sub sp, #20 + 1eb78: eb01 6868 add.w r8, r1, r8, asr #25 + 1eb7c: 9101 str r1, [sp, #4] + 1eb7e: eb03 61a8 add.w r1, r3, r8, asr #26 + 1eb82: 1649 asrs r1, r1, #25 + 1eb84: eb01 0bc1 add.w fp, r1, r1, lsl #3 + 1eb88: eb01 0b4b add.w fp, r1, fp, lsl #1 + 1eb8c: 44f3 add fp, lr + 1eb8e: ea4f 6aab mov.w sl, fp, asr #26 + 1eb92: 44d1 add r9, sl + 1eb94: ea4f 6869 mov.w r8, r9, asr #25 + 1eb98: eb07 0e08 add.w lr, r7, r8 + 1eb9c: ea4f 67ae mov.w r7, lr, asr #26 + 1eba0: 443d add r5, r7 + 1eba2: 1669 asrs r1, r5, #25 + 1eba4: 9103 str r1, [sp, #12] + 1eba6: 4411 add r1, r2 + 1eba8: 168a asrs r2, r1, #26 + 1ebaa: 4416 add r6, r2 + 1ebac: 9502 str r5, [sp, #8] + 1ebae: 1675 asrs r5, r6, #25 + 1ebb0: ebab 6a8a sub.w sl, fp, sl, lsl #26 + 1ebb4: 9100 str r1, [sp, #0] + 1ebb6: f8dd b008 ldr.w fp, [sp, #8] + 1ebba: 9903 ldr r1, [sp, #12] + 1ebbc: 442c add r4, r5 + 1ebbe: eba9 6848 sub.w r8, r9, r8, lsl #25 + 1ebc2: ea4f 69a4 mov.w r9, r4, asr #26 + 1ebc6: ebae 6787 sub.w r7, lr, r7, lsl #26 + 1ebca: 44cc add ip, r9 + 1ebcc: ebab 6e41 sub.w lr, fp, r1, lsl #25 + 1ebd0: f8dd b004 ldr.w fp, [sp, #4] + 1ebd4: eba6 6545 sub.w r5, r6, r5, lsl #25 + 1ebd8: ea4f 666c mov.w r6, ip, asr #25 + 1ebdc: eba4 6489 sub.w r4, r4, r9, lsl #26 + 1ebe0: 9900 ldr r1, [sp, #0] + 1ebe2: ea4f 292a mov.w r9, sl, asr #8 + 1ebe6: 44b3 add fp, r6 + 1ebe8: ebac 6c46 sub.w ip, ip, r6, lsl #25 + 1ebec: f880 9001 strb.w r9, [r0, #1] + 1ebf0: ea4f 66ab mov.w r6, fp, asr #26 + 1ebf4: ea4f 5967 mov.w r9, r7, asr #21 + 1ebf8: ebab 6b86 sub.w fp, fp, r6, lsl #26 + 1ebfc: eba1 6282 sub.w r2, r1, r2, lsl #26 + 1ec00: f880 a000 strb.w sl, [r0] + 1ec04: ea49 194e orr.w r9, r9, lr, lsl #5 + 1ec08: 4433 add r3, r6 + 1ec0a: ea4f 51a8 mov.w r1, r8, asr #22 + 1ec0e: ea4f 662a mov.w r6, sl, asr #24 + 1ec12: ea4f 4a2a mov.w sl, sl, asr #16 + 1ec16: ea46 0688 orr.w r6, r6, r8, lsl #2 + 1ec1a: ea41 01c7 orr.w r1, r1, r7, lsl #3 + 1ec1e: f880 a002 strb.w sl, [r0, #2] + 1ec22: f880 9009 strb.w r9, [r0, #9] + 1ec26: ea4f 4aee mov.w sl, lr, asr #19 + 1ec2a: ea4f 09ee mov.w r9, lr, asr #3 + 1ec2e: ea4a 1a82 orr.w sl, sl, r2, lsl #6 + 1ec32: 70c6 strb r6, [r0, #3] + 1ec34: 7181 strb r1, [r0, #6] + 1ec36: ea4f 16a8 mov.w r6, r8, asr #6 + 1ec3a: 1179 asrs r1, r7, #5 + 1ec3c: f880 900a strb.w r9, [r0, #10] + 1ec40: ea4f 38a8 mov.w r8, r8, asr #14 + 1ec44: ea4f 09a2 mov.w r9, r2, asr #2 + 1ec48: 137f asrs r7, r7, #13 + 1ec4a: ea4f 2eee mov.w lr, lr, asr #11 + 1ec4e: f023 437e bic.w r3, r3, #4261412864 ; 0xfe000000 + 1ec52: 7106 strb r6, [r0, #4] + 1ec54: f880 8005 strb.w r8, [r0, #5] + 1ec58: 71c1 strb r1, [r0, #7] + 1ec5a: 7207 strb r7, [r0, #8] + 1ec5c: f880 e00b strb.w lr, [r0, #11] + 1ec60: f880 a00c strb.w sl, [r0, #12] + 1ec64: ea4f 2ea2 mov.w lr, r2, asr #10 + 1ec68: ea4f 2a25 mov.w sl, r5, asr #8 + 1ec6c: f880 900d strb.w r9, [r0, #13] + 1ec70: 162e asrs r6, r5, #24 + 1ec72: ea4f 4925 mov.w r9, r5, asr #16 + 1ec76: ea4f 58e4 mov.w r8, r4, asr #23 + 1ec7a: ea4f 516c mov.w r1, ip, asr #21 + 1ec7e: ea4f 572b mov.w r7, fp, asr #20 + 1ec82: 1492 asrs r2, r2, #18 + 1ec84: f880 e00e strb.w lr, [r0, #14] + 1ec88: ea46 0644 orr.w r6, r6, r4, lsl #1 + 1ec8c: ea48 08cc orr.w r8, r8, ip, lsl #3 + 1ec90: ea41 110b orr.w r1, r1, fp, lsl #4 + 1ec94: ea47 1783 orr.w r7, r7, r3, lsl #6 + 1ec98: ea4f 1ee4 mov.w lr, r4, asr #7 + 1ec9c: 73c2 strb r2, [r0, #15] + 1ec9e: 13e4 asrs r4, r4, #15 + 1eca0: ea4f 126c mov.w r2, ip, asr #5 + 1eca4: 7405 strb r5, [r0, #16] + 1eca6: ea4f 3c6c mov.w ip, ip, asr #13 + 1ecaa: ea4f 152b mov.w r5, fp, asr #4 + 1ecae: f880 a011 strb.w sl, [r0, #17] + 1ecb2: ea4f 3b2b mov.w fp, fp, asr #12 + 1ecb6: ea4f 0aa3 mov.w sl, r3, asr #2 + 1ecba: f880 9012 strb.w r9, [r0, #18] + 1ecbe: ea4f 29a3 mov.w r9, r3, asr #10 + 1ecc2: 149b asrs r3, r3, #18 + 1ecc4: 74c6 strb r6, [r0, #19] + 1ecc6: f880 e014 strb.w lr, [r0, #20] + 1ecca: 7544 strb r4, [r0, #21] + 1eccc: f880 8016 strb.w r8, [r0, #22] + 1ecd0: 75c2 strb r2, [r0, #23] + 1ecd2: f880 c018 strb.w ip, [r0, #24] + 1ecd6: 7641 strb r1, [r0, #25] + 1ecd8: 7685 strb r5, [r0, #26] + 1ecda: f880 b01b strb.w fp, [r0, #27] + 1ecde: 7707 strb r7, [r0, #28] + 1ece0: f880 a01d strb.w sl, [r0, #29] + 1ece4: f880 901e strb.w r9, [r0, #30] + 1ece8: 77c3 strb r3, [r0, #31] + 1ecea: b005 add sp, #20 + 1ecec: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +0001ecf0 : + 1ecf0: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} + 1ecf4: 460e mov r6, r1 + 1ecf6: 4604 mov r4, r0 + 1ecf8: 4690 mov r8, r2 + 1ecfa: f101 0928 add.w r9, r1, #40 ; 0x28 + 1ecfe: b08b sub sp, #44 ; 0x2c + 1ed00: f100 0528 add.w r5, r0, #40 ; 0x28 + 1ed04: 4649 mov r1, r9 + 1ed06: 4632 mov r2, r6 + 1ed08: f7fe fe06 bl 1d918 + 1ed0c: f104 0750 add.w r7, r4, #80 ; 0x50 + 1ed10: 4649 mov r1, r9 + 1ed12: 4628 mov r0, r5 + 1ed14: 4632 mov r2, r6 + 1ed16: f7ff fecb bl 1eab0 + 1ed1a: 4638 mov r0, r7 + 1ed1c: 4621 mov r1, r4 + 1ed1e: 4642 mov r2, r8 + 1ed20: f7fe fe9a bl 1da58 + 1ed24: f104 0978 add.w r9, r4, #120 ; 0x78 + 1ed28: 4628 mov r0, r5 + 1ed2a: 4629 mov r1, r5 + 1ed2c: f108 0228 add.w r2, r8, #40 ; 0x28 + 1ed30: f7fe fe92 bl 1da58 + 1ed34: 4648 mov r0, r9 + 1ed36: f108 0178 add.w r1, r8, #120 ; 0x78 + 1ed3a: f106 0278 add.w r2, r6, #120 ; 0x78 + 1ed3e: f7fe fe8b bl 1da58 + 1ed42: 4620 mov r0, r4 + 1ed44: f106 0150 add.w r1, r6, #80 ; 0x50 + 1ed48: f108 0250 add.w r2, r8, #80 ; 0x50 + 1ed4c: f7fe fe84 bl 1da58 + 1ed50: 4621 mov r1, r4 + 1ed52: 4622 mov r2, r4 + 1ed54: 4668 mov r0, sp + 1ed56: f7fe fddf bl 1d918 + 1ed5a: 4620 mov r0, r4 + 1ed5c: 4639 mov r1, r7 + 1ed5e: 462a mov r2, r5 + 1ed60: f7ff fea6 bl 1eab0 + 1ed64: 4628 mov r0, r5 + 1ed66: 4639 mov r1, r7 + 1ed68: 462a mov r2, r5 + 1ed6a: f7fe fdd5 bl 1d918 + 1ed6e: 4638 mov r0, r7 + 1ed70: 4669 mov r1, sp + 1ed72: 464a mov r2, r9 + 1ed74: f7fe fdd0 bl 1d918 + 1ed78: 4648 mov r0, r9 + 1ed7a: 4669 mov r1, sp + 1ed7c: 464a mov r2, r9 + 1ed7e: f7ff fe97 bl 1eab0 + 1ed82: b00b add sp, #44 ; 0x2c + 1ed84: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + +0001ed88 : + 1ed88: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 1ed8c: 2300 movs r3, #0 + 1ed8e: 10da asrs r2, r3, #3 + 1ed90: 5c8c ldrb r4, [r1, r2] + 1ed92: f003 0207 and.w r2, r3, #7 + 1ed96: fa44 f202 asr.w r2, r4, r2 + 1ed9a: f002 0201 and.w r2, r2, #1 + 1ed9e: 54c2 strb r2, [r0, r3] + 1eda0: 3301 adds r3, #1 + 1eda2: f5b3 7f80 cmp.w r3, #256 ; 0x100 + 1eda6: d1f2 bne.n 1ed8e + 1eda8: f04f 0c01 mov.w ip, #1 + 1edac: 46e2 mov sl, ip + 1edae: 4686 mov lr, r0 + 1edb0: f240 1901 movw r9, #257 ; 0x101 + 1edb4: f100 38ff add.w r8, r0, #4294967295 + 1edb8: 2600 movs r6, #0 + 1edba: f918 3f01 ldrsb.w r3, [r8, #1]! + 1edbe: f10e 0e01 add.w lr, lr, #1 + 1edc2: b1eb cbz r3, 1ee00 + 1edc4: 4647 mov r7, r8 + 1edc6: 4664 mov r4, ip + 1edc8: 2501 movs r5, #1 + 1edca: 2cff cmp r4, #255 ; 0xff + 1edcc: 4622 mov r2, r4 + 1edce: dc17 bgt.n 1ee00 + 1edd0: f817 3f01 ldrb.w r3, [r7, #1]! + 1edd4: b17b cbz r3, 1edf6 + 1edd6: f81e 0c01 ldrb.w r0, [lr, #-1] + 1edda: b25b sxtb r3, r3 + 1eddc: fa03 f105 lsl.w r1, r3, r5 + 1ede0: b243 sxtb r3, r0 + 1ede2: eb03 0b01 add.w fp, r3, r1 + 1ede6: f1bb 0f0f cmp.w fp, #15 + 1edea: dc0f bgt.n 1ee0c + 1edec: 4401 add r1, r0 + 1edee: f80e 1c01 strb.w r1, [lr, #-1] + 1edf2: f808 6005 strb.w r6, [r8, r5] + 1edf6: 3501 adds r5, #1 + 1edf8: 2d07 cmp r5, #7 + 1edfa: f104 0401 add.w r4, r4, #1 + 1edfe: d1e4 bne.n 1edca + 1ee00: f10c 0c01 add.w ip, ip, #1 + 1ee04: 45cc cmp ip, r9 + 1ee06: d1d8 bne.n 1edba + 1ee08: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 1ee0c: 1a5b subs r3, r3, r1 + 1ee0e: 330f adds r3, #15 + 1ee10: dbf6 blt.n 1ee00 + 1ee12: 1a41 subs r1, r0, r1 + 1ee14: 463b mov r3, r7 + 1ee16: f80e 1c01 strb.w r1, [lr, #-1] + 1ee1a: e004 b.n 1ee26 + 1ee1c: f5b2 7f80 cmp.w r2, #256 ; 0x100 + 1ee20: f803 6c01 strb.w r6, [r3, #-1] + 1ee24: d0e7 beq.n 1edf6 + 1ee26: f993 0000 ldrsb.w r0, [r3] + 1ee2a: 4619 mov r1, r3 + 1ee2c: 3201 adds r2, #1 + 1ee2e: 3301 adds r3, #1 + 1ee30: 2800 cmp r0, #0 + 1ee32: d1f3 bne.n 1ee1c + 1ee34: f881 a000 strb.w sl, [r1] + 1ee38: e7dd b.n 1edf6 + 1ee3a: bf00 nop + +0001ee3c : + 1ee3c: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} + 1ee40: 460e mov r6, r1 + 1ee42: 4605 mov r5, r0 + 1ee44: 4691 mov r9, r2 + 1ee46: f101 0828 add.w r8, r1, #40 ; 0x28 + 1ee4a: b08b sub sp, #44 ; 0x2c + 1ee4c: f100 0428 add.w r4, r0, #40 ; 0x28 + 1ee50: 4641 mov r1, r8 + 1ee52: 4632 mov r2, r6 + 1ee54: f7fe fd60 bl 1d918 + 1ee58: f105 0750 add.w r7, r5, #80 ; 0x50 + 1ee5c: 4641 mov r1, r8 + 1ee5e: 4620 mov r0, r4 + 1ee60: 4632 mov r2, r6 + 1ee62: f7ff fe25 bl 1eab0 + 1ee66: 4638 mov r0, r7 + 1ee68: 4629 mov r1, r5 + 1ee6a: 464a mov r2, r9 + 1ee6c: f7fe fdf4 bl 1da58 + 1ee70: f105 0878 add.w r8, r5, #120 ; 0x78 + 1ee74: 4620 mov r0, r4 + 1ee76: 4621 mov r1, r4 + 1ee78: f109 0228 add.w r2, r9, #40 ; 0x28 + 1ee7c: f7fe fdec bl 1da58 + 1ee80: f109 0150 add.w r1, r9, #80 ; 0x50 + 1ee84: 4640 mov r0, r8 + 1ee86: f106 0278 add.w r2, r6, #120 ; 0x78 + 1ee8a: f7fe fde5 bl 1da58 + 1ee8e: f106 0150 add.w r1, r6, #80 ; 0x50 + 1ee92: 460a mov r2, r1 + 1ee94: 4668 mov r0, sp + 1ee96: f7fe fd3f bl 1d918 + 1ee9a: 4628 mov r0, r5 + 1ee9c: 4639 mov r1, r7 + 1ee9e: 4622 mov r2, r4 + 1eea0: f7ff fe06 bl 1eab0 + 1eea4: 4620 mov r0, r4 + 1eea6: 4639 mov r1, r7 + 1eea8: 4622 mov r2, r4 + 1eeaa: f7fe fd35 bl 1d918 + 1eeae: 4638 mov r0, r7 + 1eeb0: 4669 mov r1, sp + 1eeb2: 4642 mov r2, r8 + 1eeb4: f7fe fd30 bl 1d918 + 1eeb8: 4640 mov r0, r8 + 1eeba: 4669 mov r1, sp + 1eebc: 4642 mov r2, r8 + 1eebe: f7ff fdf7 bl 1eab0 + 1eec2: b00b add sp, #44 ; 0x2c + 1eec4: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + +0001eec8 : + 1eec8: b5f8 push {r3, r4, r5, r6, r7, lr} + 1eeca: 4605 mov r5, r0 + 1eecc: 460c mov r4, r1 + 1eece: f101 0778 add.w r7, r1, #120 ; 0x78 + 1eed2: f101 0650 add.w r6, r1, #80 ; 0x50 + 1eed6: 463a mov r2, r7 + 1eed8: f7fe fdbe bl 1da58 + 1eedc: f104 0128 add.w r1, r4, #40 ; 0x28 + 1eee0: 4632 mov r2, r6 + 1eee2: f105 0028 add.w r0, r5, #40 ; 0x28 + 1eee6: f7fe fdb7 bl 1da58 + 1eeea: 4631 mov r1, r6 + 1eeec: 463a mov r2, r7 + 1eeee: f105 0050 add.w r0, r5, #80 ; 0x50 + 1eef2: e8bd 40f8 ldmia.w sp!, {r3, r4, r5, r6, r7, lr} + 1eef6: f7fe bdaf b.w 1da58 + 1eefa: bf00 nop + +0001eefc : + 1eefc: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + 1ef00: 4605 mov r5, r0 + 1ef02: 460c mov r4, r1 + 1ef04: f101 0878 add.w r8, r1, #120 ; 0x78 + 1ef08: f101 0750 add.w r7, r1, #80 ; 0x50 + 1ef0c: f101 0628 add.w r6, r1, #40 ; 0x28 + 1ef10: 4642 mov r2, r8 + 1ef12: f7fe fda1 bl 1da58 + 1ef16: 4631 mov r1, r6 + 1ef18: 463a mov r2, r7 + 1ef1a: f105 0028 add.w r0, r5, #40 ; 0x28 + 1ef1e: f7fe fd9b bl 1da58 + 1ef22: 4639 mov r1, r7 + 1ef24: 4642 mov r2, r8 + 1ef26: f105 0050 add.w r0, r5, #80 ; 0x50 + 1ef2a: f7fe fd95 bl 1da58 + 1ef2e: 4632 mov r2, r6 + 1ef30: f105 0078 add.w r0, r5, #120 ; 0x78 + 1ef34: 4621 mov r1, r4 + 1ef36: e8bd 41f0 ldmia.w sp!, {r4, r5, r6, r7, r8, lr} + 1ef3a: f7fe bd8d b.w 1da58 + 1ef3e: bf00 nop + +0001ef40 : + 1ef40: 4603 mov r3, r0 + 1ef42: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 1ef46: 460c mov r4, r1 + 1ef48: b0bd sub sp, #244 ; 0xf4 + 1ef4a: 3350 adds r3, #80 ; 0x50 + 1ef4c: f101 0528 add.w r5, r1, #40 ; 0x28 + 1ef50: 932a str r3, [sp, #168] ; 0xa8 + 1ef52: 900b str r0, [sp, #44] ; 0x2c + 1ef54: 952b str r5, [sp, #172] ; 0xac + 1ef56: f7ff f9db bl 1e310 + 1ef5a: 982a ldr r0, [sp, #168] ; 0xa8 + 1ef5c: 992b ldr r1, [sp, #172] ; 0xac + 1ef5e: f7ff f9d7 bl 1e310 + 1ef62: 6f66 ldr r6, [r4, #116] ; 0x74 + 1ef64: 2326 movs r3, #38 ; 0x26 + 1ef66: fb03 fe06 mul.w lr, r3, r6 + 1ef6a: 6d67 ldr r7, [r4, #84] ; 0x54 + 1ef6c: 6de0 ldr r0, [r4, #92] ; 0x5c + 1ef6e: ea4f 0a47 mov.w sl, r7, lsl #1 + 1ef72: fb8a 670e smull r6, r7, sl, lr + 1ef76: ea4f 0840 mov.w r8, r0, lsl #1 + 1ef7a: 6d22 ldr r2, [r4, #80] ; 0x50 + 1ef7c: fb8a 0108 smull r0, r1, sl, r8 + 1ef80: ea4f 0942 mov.w r9, r2, lsl #1 + 1ef84: fbc2 6702 smlal r6, r7, r2, r2 + 1ef88: 6f22 ldr r2, [r4, #112] ; 0x70 + 1ef8a: f8d4 b060 ldr.w fp, [r4, #96] ; 0x60 + 1ef8e: 6da5 ldr r5, [r4, #88] ; 0x58 + 1ef90: eb02 0cc2 add.w ip, r2, r2, lsl #3 + 1ef94: eb02 0c4c add.w ip, r2, ip, lsl #1 + 1ef98: fbcb 0109 smlal r0, r1, fp, r9 + 1ef9c: 006d lsls r5, r5, #1 + 1ef9e: 9510 str r5, [sp, #64] ; 0x40 + 1efa0: fbcc 6705 smlal r6, r7, ip, r5 + 1efa4: 6ee5 ldr r5, [r4, #108] ; 0x6c + 1efa6: 6da2 ldr r2, [r4, #88] ; 0x58 + 1efa8: fb03 f505 mul.w r5, r3, r5 + 1efac: fbc2 0102 smlal r0, r1, r2, r2 + 1efb0: 6e62 ldr r2, [r4, #100] ; 0x64 + 1efb2: 950e str r5, [sp, #56] ; 0x38 + 1efb4: 0052 lsls r2, r2, #1 + 1efb6: 6ea5 ldr r5, [r4, #104] ; 0x68 + 1efb8: 9208 str r2, [sp, #32] + 1efba: fbce 0102 smlal r0, r1, lr, r2 + 1efbe: 9a0e ldr r2, [sp, #56] ; 0x38 + 1efc0: fbc2 6708 smlal r6, r7, r2, r8 + 1efc4: eb05 02c5 add.w r2, r5, r5, lsl #3 + 1efc8: 920c str r2, [sp, #48] ; 0x30 + 1efca: 006a lsls r2, r5, #1 + 1efcc: 9202 str r2, [sp, #8] + 1efce: ea4f 024b mov.w r2, fp, lsl #1 + 1efd2: 9220 str r2, [sp, #128] ; 0x80 + 1efd4: 9a0c ldr r2, [sp, #48] ; 0x30 + 1efd6: eb05 0242 add.w r2, r5, r2, lsl #1 + 1efda: 9200 str r2, [sp, #0] + 1efdc: 9a02 ldr r2, [sp, #8] + 1efde: fbc2 010c smlal r0, r1, r2, ip + 1efe2: 6e62 ldr r2, [r4, #100] ; 0x64 + 1efe4: fb03 f202 mul.w r2, r3, r2 + 1efe8: 9b20 ldr r3, [sp, #128] ; 0x80 + 1efea: 9202 str r2, [sp, #8] + 1efec: 9a00 ldr r2, [sp, #0] + 1efee: fbc2 6703 smlal r6, r7, r2, r3 + 1eff2: 6ee3 ldr r3, [r4, #108] ; 0x6c + 1eff4: 9a0e ldr r2, [sp, #56] ; 0x38 + 1eff6: fbc2 0103 smlal r0, r1, r2, r3 + 1effa: 6e63 ldr r3, [r4, #100] ; 0x64 + 1effc: 9a02 ldr r2, [sp, #8] + 1effe: fbc2 6703 smlal r6, r7, r2, r3 + 1f002: 1802 adds r2, r0, r0 + 1f004: eb41 0301 adc.w r3, r1, r1 + 1f008: 19b0 adds r0, r6, r6 + 1f00a: eb47 0107 adc.w r1, r7, r7 + 1f00e: e9cd 0124 strd r0, r1, [sp, #144] ; 0x90 + 1f012: 6da1 ldr r1, [r4, #88] ; 0x58 + 1f014: e9cd 2322 strd r2, r3, [sp, #136] ; 0x88 + 1f018: fb81 230e smull r2, r3, r1, lr + 1f01c: 6d66 ldr r6, [r4, #84] ; 0x54 + 1f01e: fb8b 010a smull r0, r1, fp, sl + 1f022: 6e67 ldr r7, [r4, #100] ; 0x64 + 1f024: fbc6 2309 smlal r2, r3, r6, r9 + 1f028: fbc7 0109 smlal r0, r1, r7, r9 + 1f02c: 6de6 ldr r6, [r4, #92] ; 0x5c + 1f02e: 9f10 ldr r7, [sp, #64] ; 0x40 + 1f030: fbcc 2308 smlal r2, r3, ip, r8 + 1f034: fbc7 0106 smlal r0, r1, r7, r6 + 1f038: 9e0e ldr r6, [sp, #56] ; 0x38 + 1f03a: 6ee7 ldr r7, [r4, #108] ; 0x6c + 1f03c: fbc6 230b smlal r2, r3, r6, fp + 1f040: 007f lsls r7, r7, #1 + 1f042: 971a str r7, [sp, #104] ; 0x68 + 1f044: fbce 0105 smlal r0, r1, lr, r5 + 1f048: 9e08 ldr r6, [sp, #32] + 1f04a: 9f00 ldr r7, [sp, #0] + 1f04c: fbc7 2306 smlal r2, r3, r7, r6 + 1f050: 9e1a ldr r6, [sp, #104] ; 0x68 + 1f052: fbcc 0106 smlal r0, r1, ip, r6 + 1f056: e9dd 6724 ldrd r6, r7, [sp, #144] ; 0x90 + 1f05a: f116 7600 adds.w r6, r6, #33554432 ; 0x2000000 + 1f05e: f147 0700 adc.w r7, r7, #0 + 1f062: e9cd 6704 strd r6, r7, [sp, #16] + 1f066: e9dd 6722 ldrd r6, r7, [sp, #136] ; 0x88 + 1f06a: f116 7600 adds.w r6, r6, #33554432 ; 0x2000000 + 1f06e: f147 0700 adc.w r7, r7, #0 + 1f072: 1892 adds r2, r2, r2 + 1f074: e9cd 671c strd r6, r7, [sp, #112] ; 0x70 + 1f078: 415b adcs r3, r3 + 1f07a: 1806 adds r6, r0, r0 + 1f07c: eb41 0701 adc.w r7, r1, r1 + 1f080: e9cd 6726 strd r6, r7, [sp, #152] ; 0x98 + 1f084: 981c ldr r0, [sp, #112] ; 0x70 + 1f086: 9f04 ldr r7, [sp, #16] + 1f088: 9e05 ldr r6, [sp, #20] + 1f08a: 0ebf lsrs r7, r7, #26 + 1f08c: 0e80 lsrs r0, r0, #26 + 1f08e: ea47 1186 orr.w r1, r7, r6, lsl #6 + 1f092: 4607 mov r7, r0 + 1f094: 981d ldr r0, [sp, #116] ; 0x74 + 1f096: 910c str r1, [sp, #48] ; 0x30 + 1f098: 16b1 asrs r1, r6, #26 + 1f09a: ea47 1780 orr.w r7, r7, r0, lsl #6 + 1f09e: 910d str r1, [sp, #52] ; 0x34 + 1f0a0: 1686 asrs r6, r0, #26 + 1f0a2: 9702 str r7, [sp, #8] + 1f0a4: e9dd 010c ldrd r0, r1, [sp, #48] ; 0x30 + 1f0a8: 9603 str r6, [sp, #12] + 1f0aa: 1880 adds r0, r0, r2 + 1f0ac: e9dd 6702 ldrd r6, r7, [sp, #8] + 1f0b0: 4159 adcs r1, r3 + 1f0b2: e9dd 2326 ldrd r2, r3, [sp, #152] ; 0x98 + 1f0b6: 1992 adds r2, r2, r6 + 1f0b8: 417b adcs r3, r7 + 1f0ba: 6d67 ldr r7, [r4, #84] ; 0x54 + 1f0bc: e9cd 011c strd r0, r1, [sp, #112] ; 0x70 + 1f0c0: e9cd 2326 strd r2, r3, [sp, #152] ; 0x98 + 1f0c4: 9808 ldr r0, [sp, #32] + 1f0c6: fb87 230a smull r2, r3, r7, sl + 1f0ca: 6da1 ldr r1, [r4, #88] ; 0x58 + 1f0cc: fb8a 6700 smull r6, r7, sl, r0 + 1f0d0: fbc1 2309 smlal r2, r3, r1, r9 + 1f0d4: fbc5 6709 smlal r6, r7, r5, r9 + 1f0d8: 9810 ldr r0, [sp, #64] ; 0x40 + 1f0da: fbce 2308 smlal r2, r3, lr, r8 + 1f0de: 9920 ldr r1, [sp, #128] ; 0x80 + 1f0e0: fbc0 670b smlal r6, r7, r0, fp + 1f0e4: fbc1 230c smlal r2, r3, r1, ip + 1f0e8: 6de0 ldr r0, [r4, #92] ; 0x5c + 1f0ea: 9908 ldr r1, [sp, #32] + 1f0ec: fbc8 6700 smlal r6, r7, r8, r0 + 1f0f0: 980e ldr r0, [sp, #56] ; 0x38 + 1f0f2: fbc0 2301 smlal r2, r3, r0, r1 + 1f0f6: 991a ldr r1, [sp, #104] ; 0x68 + 1f0f8: 9800 ldr r0, [sp, #0] + 1f0fa: fbce 6701 smlal r6, r7, lr, r1 + 1f0fe: 6f21 ldr r1, [r4, #112] ; 0x70 + 1f100: fbc0 2305 smlal r2, r3, r0, r5 + 1f104: fbcc 6701 smlal r6, r7, ip, r1 + 1f108: e9dd 011c ldrd r0, r1, [sp, #112] ; 0x70 + 1f10c: f110 7080 adds.w r0, r0, #16777216 ; 0x1000000 + 1f110: f141 0100 adc.w r1, r1, #0 + 1f114: e9cd 0106 strd r0, r1, [sp, #24] + 1f118: 1890 adds r0, r2, r2 + 1f11a: eb43 0103 adc.w r1, r3, r3 + 1f11e: 19b6 adds r6, r6, r6 + 1f120: e9cd 0128 strd r0, r1, [sp, #160] ; 0xa0 + 1f124: e9dd 2326 ldrd r2, r3, [sp, #152] ; 0x98 + 1f128: 417f adcs r7, r7 + 1f12a: 2000 movs r0, #0 + 1f12c: f112 7280 adds.w r2, r2, #16777216 ; 0x1000000 + 1f130: f04f 0100 mov.w r1, #0 + 1f134: e9cd 0100 strd r0, r1, [sp] + 1f138: 9906 ldr r1, [sp, #24] + 1f13a: ea4f 6052 mov.w r0, r2, lsr #25 + 1f13e: 9000 str r0, [sp, #0] + 1f140: 9807 ldr r0, [sp, #28] + 1f142: ea4f 6151 mov.w r1, r1, lsr #25 + 1f146: ea41 11c0 orr.w r1, r1, r0, lsl #7 + 1f14a: 9104 str r1, [sp, #16] + 1f14c: 9900 ldr r1, [sp, #0] + 1f14e: f143 0300 adc.w r3, r3, #0 + 1f152: ea41 11c3 orr.w r1, r1, r3, lsl #7 + 1f156: 1640 asrs r0, r0, #25 + 1f158: 9100 str r1, [sp, #0] + 1f15a: 9005 str r0, [sp, #20] + 1f15c: 1659 asrs r1, r3, #25 + 1f15e: 9101 str r1, [sp, #4] + 1f160: e9dd 2328 ldrd r2, r3, [sp, #160] ; 0xa0 + 1f164: e9dd 0104 ldrd r0, r1, [sp, #16] + 1f168: 1812 adds r2, r2, r0 + 1f16a: 414b adcs r3, r1 + 1f16c: e9cd 2328 strd r2, r3, [sp, #160] ; 0xa0 + 1f170: e9dd 2300 ldrd r2, r3, [sp] + 1f174: 1992 adds r2, r2, r6 + 1f176: 6da6 ldr r6, [r4, #88] ; 0x58 + 1f178: 417b adcs r3, r7 + 1f17a: e9cd 232c strd r2, r3, [sp, #176] ; 0xb0 + 1f17e: fb86 230a smull r2, r3, r6, sl + 1f182: 6de7 ldr r7, [r4, #92] ; 0x5c + 1f184: 6ee0 ldr r0, [r4, #108] ; 0x6c + 1f186: fbc7 2309 smlal r2, r3, r7, r9 + 1f18a: fb85 670a smull r6, r7, r5, sl + 1f18e: fbc0 6709 smlal r6, r7, r0, r9 + 1f192: 6e61 ldr r1, [r4, #100] ; 0x64 + 1f194: 9810 ldr r0, [sp, #64] ; 0x40 + 1f196: fbce 230b smlal r2, r3, lr, fp + 1f19a: fbc0 6701 smlal r6, r7, r0, r1 + 1f19e: 9908 ldr r1, [sp, #32] + 1f1a0: fbc8 670b smlal r6, r7, r8, fp + 1f1a4: fbcc 2301 smlal r2, r3, ip, r1 + 1f1a8: f8dd c038 ldr.w ip, [sp, #56] ; 0x38 + 1f1ac: 6f20 ldr r0, [r4, #112] ; 0x70 + 1f1ae: fbcc 2305 smlal r2, r3, ip, r5 + 1f1b2: fbce 6700 smlal r6, r7, lr, r0 + 1f1b6: 1890 adds r0, r2, r2 + 1f1b8: eb43 0103 adc.w r1, r3, r3 + 1f1bc: 19b2 adds r2, r6, r6 + 1f1be: eb47 0307 adc.w r3, r7, r7 + 1f1c2: e9cd 2312 strd r2, r3, [sp, #72] ; 0x48 + 1f1c6: e9dd 2328 ldrd r2, r3, [sp, #160] ; 0xa0 + 1f1ca: f112 7200 adds.w r2, r2, #33554432 ; 0x2000000 + 1f1ce: f143 0300 adc.w r3, r3, #0 + 1f1d2: e9cd 0116 strd r0, r1, [sp, #88] ; 0x58 + 1f1d6: e9dd 012c ldrd r0, r1, [sp, #176] ; 0xb0 + 1f1da: f110 7000 adds.w r0, r0, #33554432 ; 0x2000000 + 1f1de: f141 0100 adc.w r1, r1, #0 + 1f1e2: 0e87 lsrs r7, r0, #26 + 1f1e4: ea4f 6c92 mov.w ip, r2, lsr #26 + 1f1e8: ea47 1681 orr.w r6, r7, r1, lsl #6 + 1f1ec: ea4c 1783 orr.w r7, ip, r3, lsl #6 + 1f1f0: ea4f 6ca1 mov.w ip, r1, asr #26 + 1f1f4: 960e str r6, [sp, #56] ; 0x38 + 1f1f6: f8cd c03c str.w ip, [sp, #60] ; 0x3c + 1f1fa: 9706 str r7, [sp, #24] + 1f1fc: 1698 asrs r0, r3, #26 + 1f1fe: e9dd 6712 ldrd r6, r7, [sp, #72] ; 0x48 + 1f202: e9dd 230e ldrd r2, r3, [sp, #56] ; 0x38 + 1f206: 1992 adds r2, r2, r6 + 1f208: 417b adcs r3, r7 + 1f20a: 9007 str r0, [sp, #28] + 1f20c: e9cd 2330 strd r2, r3, [sp, #192] ; 0xc0 + 1f210: e9dd 0116 ldrd r0, r1, [sp, #88] ; 0x58 + 1f214: e9dd 2306 ldrd r2, r3, [sp, #24] + 1f218: 9e1a ldr r6, [sp, #104] ; 0x68 + 1f21a: 1880 adds r0, r0, r2 + 1f21c: 4159 adcs r1, r3 + 1f21e: fb8a 2306 smull r2, r3, sl, r6 + 1f222: 6f27 ldr r7, [r4, #112] ; 0x70 + 1f224: f8dd c040 ldr.w ip, [sp, #64] ; 0x40 + 1f228: fbc7 2309 smlal r2, r3, r7, r9 + 1f22c: fbcc 2305 smlal r2, r3, ip, r5 + 1f230: e9cd 012e strd r0, r1, [sp, #184] ; 0xb8 + 1f234: 9808 ldr r0, [sp, #32] + 1f236: 6f61 ldr r1, [r4, #116] ; 0x74 + 1f238: fbc0 2308 smlal r2, r3, r0, r8 + 1f23c: fbcb 230b smlal r2, r3, fp, fp + 1f240: fbce 2301 smlal r2, r3, lr, r1 + 1f244: 9f02 ldr r7, [sp, #8] + 1f246: 9e03 ldr r6, [sp, #12] + 1f248: 06b8 lsls r0, r7, #26 + 1f24a: 06b1 lsls r1, r6, #26 + 1f24c: 1896 adds r6, r2, r2 + 1f24e: ea41 1197 orr.w r1, r1, r7, lsr #6 + 1f252: eb43 0703 adc.w r7, r3, r3 + 1f256: e9dd 2322 ldrd r2, r3, [sp, #136] ; 0x88 + 1f25a: 1a12 subs r2, r2, r0 + 1f25c: eb63 0301 sbc.w r3, r3, r1 + 1f260: e9dd 0130 ldrd r0, r1, [sp, #192] ; 0xc0 + 1f264: f110 7080 adds.w r0, r0, #16777216 ; 0x1000000 + 1f268: e9cd 6716 strd r6, r7, [sp, #88] ; 0x58 + 1f26c: f141 0100 adc.w r1, r1, #0 + 1f270: 0e47 lsrs r7, r0, #25 + 1f272: e9cd 231a strd r2, r3, [sp, #104] ; 0x68 + 1f276: e9dd 232e ldrd r2, r3, [sp, #184] ; 0xb8 + 1f27a: ea47 1ec1 orr.w lr, r7, r1, lsl #7 + 1f27e: f112 7280 adds.w r2, r2, #16777216 ; 0x1000000 + 1f282: ea4f 6761 mov.w r7, r1, asr #25 + 1f286: f143 0300 adc.w r3, r3, #0 + 1f28a: f8cd e020 str.w lr, [sp, #32] + 1f28e: 9709 str r7, [sp, #36] ; 0x24 + 1f290: ea4f 6c52 mov.w ip, r2, lsr #25 + 1f294: ea4c 16c3 orr.w r6, ip, r3, lsl #7 + 1f298: e9dd 0116 ldrd r0, r1, [sp, #88] ; 0x58 + 1f29c: ea4f 6c63 mov.w ip, r3, asr #25 + 1f2a0: e9dd 2308 ldrd r2, r3, [sp, #32] + 1f2a4: 1880 adds r0, r0, r2 + 1f2a6: 9602 str r6, [sp, #8] + 1f2a8: f8cd c00c str.w ip, [sp, #12] + 1f2ac: 4159 adcs r1, r3 + 1f2ae: e9dd 671a ldrd r6, r7, [sp, #104] ; 0x68 + 1f2b2: e9cd 0122 strd r0, r1, [sp, #136] ; 0x88 + 1f2b6: e9dd 0102 ldrd r0, r1, [sp, #8] + 1f2ba: 1836 adds r6, r6, r0 + 1f2bc: 414f adcs r7, r1 + 1f2be: 6f21 ldr r1, [r4, #112] ; 0x70 + 1f2c0: 6f62 ldr r2, [r4, #116] ; 0x74 + 1f2c2: fb81 ab0a smull sl, fp, r1, sl + 1f2c6: fbc2 ab09 smlal sl, fp, r2, r9 + 1f2ca: e9cd 671a strd r6, r7, [sp, #104] ; 0x68 + 1f2ce: 6ee3 ldr r3, [r4, #108] ; 0x6c + 1f2d0: 9e10 ldr r6, [sp, #64] ; 0x40 + 1f2d2: 6e67 ldr r7, [r4, #100] ; 0x64 + 1f2d4: fbc6 ab03 smlal sl, fp, r6, r3 + 1f2d8: fbc8 ab05 smlal sl, fp, r8, r5 + 1f2dc: e9dd 8924 ldrd r8, r9, [sp, #144] ; 0x90 + 1f2e0: f8dd c080 ldr.w ip, [sp, #128] ; 0x80 + 1f2e4: f8dd e034 ldr.w lr, [sp, #52] ; 0x34 + 1f2e8: fbcc ab07 smlal sl, fp, ip, r7 + 1f2ec: f8dd c030 ldr.w ip, [sp, #48] ; 0x30 + 1f2f0: 9805 ldr r0, [sp, #20] + 1f2f2: 9d01 ldr r5, [sp, #4] + 1f2f4: ea4f 668c mov.w r6, ip, lsl #26 + 1f2f8: ea4f 678e mov.w r7, lr, lsl #26 + 1f2fc: f8dd e010 ldr.w lr, [sp, #16] + 1f300: ebb8 0806 subs.w r8, r8, r6 + 1f304: ea47 179c orr.w r7, r7, ip, lsr #6 + 1f308: eb69 0907 sbc.w r9, r9, r7 + 1f30c: ea4f 624e mov.w r2, lr, lsl #25 + 1f310: eb1a 0a0a adds.w sl, sl, sl + 1f314: ea4f 6340 mov.w r3, r0, lsl #25 + 1f318: ea4f 6145 mov.w r1, r5, lsl #25 + 1f31c: 9d00 ldr r5, [sp, #0] + 1f31e: e9dd 671c ldrd r6, r7, [sp, #112] ; 0x70 + 1f322: ea43 13de orr.w r3, r3, lr, lsr #7 + 1f326: eb4b 0b0b adc.w fp, fp, fp + 1f32a: 1ab6 subs r6, r6, r2 + 1f32c: eb67 0703 sbc.w r7, r7, r3 + 1f330: 0668 lsls r0, r5, #25 + 1f332: e9cd 671c strd r6, r7, [sp, #112] ; 0x70 + 1f336: e9dd 2326 ldrd r2, r3, [sp, #152] ; 0x98 + 1f33a: e9dd 671a ldrd r6, r7, [sp, #104] ; 0x68 + 1f33e: 1a12 subs r2, r2, r0 + 1f340: ea41 11d5 orr.w r1, r1, r5, lsr #7 + 1f344: eb63 0301 sbc.w r3, r3, r1 + 1f348: f116 7600 adds.w r6, r6, #33554432 ; 0x2000000 + 1f34c: e9cd 2324 strd r2, r3, [sp, #144] ; 0x90 + 1f350: e9dd 2322 ldrd r2, r3, [sp, #136] ; 0x88 + 1f354: f147 0700 adc.w r7, r7, #0 + 1f358: f112 7200 adds.w r2, r2, #33554432 ; 0x2000000 + 1f35c: f143 0300 adc.w r3, r3, #0 + 1f360: 0e90 lsrs r0, r2, #26 + 1f362: ea40 1083 orr.w r0, r0, r3, lsl #6 + 1f366: eb1a 0200 adds.w r2, sl, r0 + 1f36a: ea4f 61a3 mov.w r1, r3, asr #26 + 1f36e: eb4b 0301 adc.w r3, fp, r1 + 1f372: e9cd 231e strd r2, r3, [sp, #120] ; 0x78 + 1f376: f112 7280 adds.w r2, r2, #16777216 ; 0x1000000 + 1f37a: f143 0300 adc.w r3, r3, #0 + 1f37e: 0e55 lsrs r5, r2, #25 + 1f380: ea45 15c3 orr.w r5, r5, r3, lsl #7 + 1f384: 2213 movs r2, #19 + 1f386: e9cd 6718 strd r6, r7, [sp, #96] ; 0x60 + 1f38a: fba5 6702 umull r6, r7, r5, r2 + 1f38e: ea4f 6e63 mov.w lr, r3, asr #25 + 1f392: fb02 770e mla r7, r2, lr, r7 + 1f396: eb18 0206 adds.w r2, r8, r6 + 1f39a: eb49 0307 adc.w r3, r9, r7 + 1f39e: e9cd 2320 strd r2, r3, [sp, #128] ; 0x80 + 1f3a2: e9dd 6720 ldrd r6, r7, [sp, #128] ; 0x80 + 1f3a6: f116 7600 adds.w r6, r6, #33554432 ; 0x2000000 + 1f3aa: f04f 0200 mov.w r2, #0 + 1f3ae: f04f 0300 mov.w r3, #0 + 1f3b2: f147 0700 adc.w r7, r7, #0 + 1f3b6: e9cd 6716 strd r6, r7, [sp, #88] ; 0x58 + 1f3ba: 4616 mov r6, r2 + 1f3bc: 461f mov r7, r3 + 1f3be: e9cd 6700 strd r6, r7, [sp] + 1f3c2: e9cd 670c strd r6, r7, [sp, #48] ; 0x30 + 1f3c6: 9f16 ldr r7, [sp, #88] ; 0x58 + 1f3c8: e9cd 2310 strd r2, r3, [sp, #64] ; 0x40 + 1f3cc: e9cd 2314 strd r2, r3, [sp, #80] ; 0x50 + 1f3d0: e9cd 2312 strd r2, r3, [sp, #72] ; 0x48 + 1f3d4: 0eba lsrs r2, r7, #26 + 1f3d6: 9f19 ldr r7, [sp, #100] ; 0x64 + 1f3d8: f8dd c060 ldr.w ip, [sp, #96] ; 0x60 + 1f3dc: ea4f 69a7 mov.w r9, r7, asr #26 + 1f3e0: ea4f 689c mov.w r8, ip, lsr #26 + 1f3e4: ea4f 6c89 mov.w ip, r9, lsl #26 + 1f3e8: f8cd c004 str.w ip, [sp, #4] + 1f3ec: f8dd c01c ldr.w ip, [sp, #28] + 1f3f0: ea4f 6e4e mov.w lr, lr, lsl #25 + 1f3f4: f8cd e044 str.w lr, [sp, #68] ; 0x44 + 1f3f8: ea4f 6c8c mov.w ip, ip, lsl #26 + 1f3fc: f8cd c034 str.w ip, [sp, #52] ; 0x34 + 1f400: f8dd c044 ldr.w ip, [sp, #68] ; 0x44 + 1f404: ea4f 6e81 mov.w lr, r1, lsl #26 + 1f408: f8cd e054 str.w lr, [sp, #84] ; 0x54 + 1f40c: ea4c 1cd5 orr.w ip, ip, r5, lsr #7 + 1f410: 9e17 ldr r6, [sp, #92] ; 0x5c + 1f412: f8cd c044 str.w ip, [sp, #68] ; 0x44 + 1f416: f8dd c054 ldr.w ip, [sp, #84] ; 0x54 + 1f41a: ea42 1286 orr.w r2, r2, r6, lsl #6 + 1f41e: 16b3 asrs r3, r6, #26 + 1f420: f8dd e004 ldr.w lr, [sp, #4] + 1f424: 9e03 ldr r6, [sp, #12] + 1f426: ea4c 1c90 orr.w ip, ip, r0, lsr #6 + 1f42a: ea48 1887 orr.w r8, r8, r7, lsl #6 + 1f42e: f8cd c054 str.w ip, [sp, #84] ; 0x54 + 1f432: 9f09 ldr r7, [sp, #36] ; 0x24 + 1f434: f8dd c008 ldr.w ip, [sp, #8] + 1f438: ea4e 1e98 orr.w lr, lr, r8, lsr #6 + 1f43c: 0676 lsls r6, r6, #25 + 1f43e: f8cd e004 str.w lr, [sp, #4] + 1f442: 067f lsls r7, r7, #25 + 1f444: ea46 1edc orr.w lr, r6, ip, lsr #7 + 1f448: 9713 str r7, [sp, #76] ; 0x4c + 1f44a: f8cd e014 str.w lr, [sp, #20] + 1f44e: f8dd c020 ldr.w ip, [sp, #32] + 1f452: f8dd e04c ldr.w lr, [sp, #76] ; 0x4c + 1f456: 9906 ldr r1, [sp, #24] + 1f458: ea4e 1edc orr.w lr, lr, ip, lsr #7 + 1f45c: f8cd e04c str.w lr, [sp, #76] ; 0x4c + 1f460: f8dd c018 ldr.w ip, [sp, #24] + 1f464: f8dd e034 ldr.w lr, [sp, #52] ; 0x34 + 1f468: 0689 lsls r1, r1, #26 + 1f46a: ea4e 1e9c orr.w lr, lr, ip, lsr #6 + 1f46e: ea4f 6c80 mov.w ip, r0, lsl #26 + 1f472: 9808 ldr r0, [sp, #32] + 1f474: 910c str r1, [sp, #48] ; 0x30 + 1f476: 0640 lsls r0, r0, #25 + 1f478: 9012 str r0, [sp, #72] ; 0x48 + 1f47a: e9dd 011c ldrd r0, r1, [sp, #112] ; 0x70 + 1f47e: 1880 adds r0, r0, r2 + 1f480: 4159 adcs r1, r3 + 1f482: ea4f 6a82 mov.w sl, r2, lsl #26 + 1f486: ea4f 6b83 mov.w fp, r3, lsl #26 + 1f48a: e9cd 0106 strd r0, r1, [sp, #24] + 1f48e: e9dd 0120 ldrd r0, r1, [sp, #128] ; 0x80 + 1f492: ea4b 1b92 orr.w fp, fp, r2, lsr #6 + 1f496: ebb0 000a subs.w r0, r0, sl + 1f49a: ea4f 6545 mov.w r5, r5, lsl #25 + 1f49e: 9510 str r5, [sp, #64] ; 0x40 + 1f4a0: eb61 010b sbc.w r1, r1, fp + 1f4a4: e9dd 2310 ldrd r2, r3, [sp, #64] ; 0x40 + 1f4a8: f8cd e034 str.w lr, [sp, #52] ; 0x34 + 1f4ac: f8dd e008 ldr.w lr, [sp, #8] + 1f4b0: e9cd 0102 strd r0, r1, [sp, #8] + 1f4b4: e9dd 011e ldrd r0, r1, [sp, #120] ; 0x78 + 1f4b8: e9dd ab30 ldrd sl, fp, [sp, #192] ; 0xc0 + 1f4bc: 1a80 subs r0, r0, r2 + 1f4be: eb61 0103 sbc.w r1, r1, r3 + 1f4c2: ea4f 6588 mov.w r5, r8, lsl #26 + 1f4c6: e9cd 0110 strd r0, r1, [sp, #64] ; 0x40 + 1f4ca: e9dd 0124 ldrd r0, r1, [sp, #144] ; 0x90 + 1f4ce: eb10 0008 adds.w r0, r0, r8 + 1f4d2: 9500 str r5, [sp, #0] + 1f4d4: eb41 0109 adc.w r1, r1, r9 + 1f4d8: e9dd 2300 ldrd r2, r3, [sp] + 1f4dc: 9d0e ldr r5, [sp, #56] ; 0x38 + 1f4de: e9cd 010e strd r0, r1, [sp, #56] ; 0x38 + 1f4e2: e9dd 011a ldrd r0, r1, [sp, #104] ; 0x68 + 1f4e6: e9dd 8928 ldrd r8, r9, [sp, #160] ; 0xa0 + 1f4ea: 1a80 subs r0, r0, r2 + 1f4ec: f8cd c050 str.w ip, [sp, #80] ; 0x50 + 1f4f0: eb61 0103 sbc.w r1, r1, r3 + 1f4f4: ea4f 6e4e mov.w lr, lr, lsl #25 + 1f4f8: e9dd 2314 ldrd r2, r3, [sp, #80] ; 0x50 + 1f4fc: e9cd 0100 strd r0, r1, [sp] + 1f500: e9dd 0122 ldrd r0, r1, [sp, #136] ; 0x88 + 1f504: 1a80 subs r0, r0, r2 + 1f506: f8cd e010 str.w lr, [sp, #16] + 1f50a: eb61 0103 sbc.w r1, r1, r3 + 1f50e: e9cd 0108 strd r0, r1, [sp, #32] + 1f512: e9dd 2304 ldrd r2, r3, [sp, #16] + 1f516: e9dd 012e ldrd r0, r1, [sp, #184] ; 0xb8 + 1f51a: 4621 mov r1, r4 + 1f51c: 1a80 subs r0, r0, r2 + 1f51e: 9c0b ldr r4, [sp, #44] ; 0x2c + 1f520: e9dd 2312 ldrd r2, r3, [sp, #72] ; 0x48 + 1f524: ebba 0a02 subs.w sl, sl, r2 + 1f528: e9dd 230c ldrd r2, r3, [sp, #48] ; 0x30 + 1f52c: ebb8 0802 subs.w r8, r8, r2 + 1f530: e9dd 232c ldrd r2, r3, [sp, #176] ; 0xb0 + 1f534: 9b06 ldr r3, [sp, #24] + 1f536: 06ae lsls r6, r5, #26 + 1f538: 1b96 subs r6, r2, r6 + 1f53a: 9d0b ldr r5, [sp, #44] ; 0x2c + 1f53c: 9a2b ldr r2, [sp, #172] ; 0xac + 1f53e: 67e3 str r3, [r4, #124] ; 0x7c + 1f540: 9b02 ldr r3, [sp, #8] + 1f542: 3528 adds r5, #40 ; 0x28 + 1f544: 67a3 str r3, [r4, #120] ; 0x78 + 1f546: 9b10 ldr r3, [sp, #64] ; 0x40 + 1f548: f8c4 0084 str.w r0, [r4, #132] ; 0x84 + 1f54c: f8c4 309c str.w r3, [r4, #156] ; 0x9c + 1f550: 9b0e ldr r3, [sp, #56] ; 0x38 + 1f552: f8c4 a094 str.w sl, [r4, #148] ; 0x94 + 1f556: f8c4 308c str.w r3, [r4, #140] ; 0x8c + 1f55a: 9b00 ldr r3, [sp, #0] + 1f55c: f8c4 8080 str.w r8, [r4, #128] ; 0x80 + 1f560: f8c4 3088 str.w r3, [r4, #136] ; 0x88 + 1f564: 9b08 ldr r3, [sp, #32] + 1f566: f8c4 6090 str.w r6, [r4, #144] ; 0x90 + 1f56a: f8c4 3098 str.w r3, [r4, #152] ; 0x98 + 1f56e: 4628 mov r0, r5 + 1f570: f7fe f9d2 bl 1d918 + 1f574: 4629 mov r1, r5 + 1f576: a832 add r0, sp, #200 ; 0xc8 + 1f578: f7fe feca bl 1e310 + 1f57c: 4628 mov r0, r5 + 1f57e: 992a ldr r1, [sp, #168] ; 0xa8 + 1f580: 9a0b ldr r2, [sp, #44] ; 0x2c + 1f582: f7fe f9c9 bl 1d918 + 1f586: 982a ldr r0, [sp, #168] ; 0xa8 + 1f588: 9a0b ldr r2, [sp, #44] ; 0x2c + 1f58a: 4601 mov r1, r0 + 1f58c: f7ff fa90 bl 1eab0 + 1f590: 980b ldr r0, [sp, #44] ; 0x2c + 1f592: a932 add r1, sp, #200 ; 0xc8 + 1f594: 4604 mov r4, r0 + 1f596: 462a mov r2, r5 + 1f598: 3478 adds r4, #120 ; 0x78 + 1f59a: f7ff fa89 bl 1eab0 + 1f59e: 4620 mov r0, r4 + 1f5a0: 4621 mov r1, r4 + 1f5a2: 9a2a ldr r2, [sp, #168] ; 0xa8 + 1f5a4: f7ff fa84 bl 1eab0 + 1f5a8: b03d add sp, #244 ; 0xf4 + 1f5aa: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 1f5ae: bf00 nop + +0001f5b0 : + 1f5b0: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} + 1f5b4: 460c mov r4, r1 + 1f5b6: 4605 mov r5, r0 + 1f5b8: f101 0628 add.w r6, r1, #40 ; 0x28 + 1f5bc: 4631 mov r1, r6 + 1f5be: 4622 mov r2, r4 + 1f5c0: f7fe f9aa bl 1d918 + 1f5c4: 4631 mov r1, r6 + 1f5c6: f105 0028 add.w r0, r5, #40 ; 0x28 + 1f5ca: 4622 mov r2, r4 + 1f5cc: f7ff fa70 bl 1eab0 + 1f5d0: f246 62b8 movw r2, #26296 ; 0x66b8 + 1f5d4: 6f20 ldr r0, [r4, #112] ; 0x70 + 1f5d6: 6f61 ldr r1, [r4, #116] ; 0x74 + 1f5d8: f8d4 b050 ldr.w fp, [r4, #80] ; 0x50 + 1f5dc: f8d4 a054 ldr.w sl, [r4, #84] ; 0x54 + 1f5e0: f8d4 9058 ldr.w r9, [r4, #88] ; 0x58 + 1f5e4: f8d4 805c ldr.w r8, [r4, #92] ; 0x5c + 1f5e8: f8d4 c060 ldr.w ip, [r4, #96] ; 0x60 + 1f5ec: 6e63 ldr r3, [r4, #100] ; 0x64 + 1f5ee: 6ea7 ldr r7, [r4, #104] ; 0x68 + 1f5f0: 6ee6 ldr r6, [r4, #108] ; 0x6c + 1f5f2: f2c0 0203 movt r2, #3 + 1f5f6: 6769 str r1, [r5, #116] ; 0x74 + 1f5f8: 6728 str r0, [r5, #112] ; 0x70 + 1f5fa: f104 0178 add.w r1, r4, #120 ; 0x78 + 1f5fe: f8c5 b050 str.w fp, [r5, #80] ; 0x50 + 1f602: f8c5 a054 str.w sl, [r5, #84] ; 0x54 + 1f606: f8c5 9058 str.w r9, [r5, #88] ; 0x58 + 1f60a: f8c5 805c str.w r8, [r5, #92] ; 0x5c + 1f60e: f8c5 c060 str.w ip, [r5, #96] ; 0x60 + 1f612: 666b str r3, [r5, #100] ; 0x64 + 1f614: 66af str r7, [r5, #104] ; 0x68 + 1f616: 66ee str r6, [r5, #108] ; 0x6c + 1f618: f105 0078 add.w r0, r5, #120 ; 0x78 + 1f61c: e8bd 4ff8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} + 1f620: f7fe ba1a b.w 1da58 + +0001f624 : + 1f624: b570 push {r4, r5, r6, lr} + 1f626: 4606 mov r6, r0 + 1f628: 460d mov r5, r1 + 1f62a: 4614 mov r4, r2 + 1f62c: f7fe f9ac bl 1d988 + 1f630: f106 0028 add.w r0, r6, #40 ; 0x28 + 1f634: f105 0128 add.w r1, r5, #40 ; 0x28 + 1f638: 4622 mov r2, r4 + 1f63a: f7fe f9a5 bl 1d988 + 1f63e: f106 0050 add.w r0, r6, #80 ; 0x50 + 1f642: f105 0150 add.w r1, r5, #80 ; 0x50 + 1f646: 4622 mov r2, r4 + 1f648: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} + 1f64c: f7fe b99c b.w 1d988 + +0001f650 : + 1f650: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} + 1f654: 4680 mov r8, r0 + 1f656: b254 sxtb r4, r2 + 1f658: 17e5 asrs r5, r4, #31 + 1f65a: ea4f 79d5 mov.w r9, r5, lsr #31 + 1f65e: f1c9 0600 rsb r6, r9, #0 + 1f662: 4016 ands r6, r2 + 1f664: eba2 0646 sub.w r6, r2, r6, lsl #1 + 1f668: b2f6 uxtb r6, r6 + 1f66a: 4c5d ldr r4, [pc, #372] ; (1f7e0 ) + 1f66c: ebc1 1101 rsb r1, r1, r1, lsl #4 + 1f670: f086 0201 eor.w r2, r6, #1 + 1f674: 2300 movs r3, #0 + 1f676: 018d lsls r5, r1, #6 + 1f678: 2701 movs r7, #1 + 1f67a: 3a01 subs r2, #1 + 1f67c: b09f sub sp, #124 ; 0x7c + 1f67e: 6043 str r3, [r0, #4] + 1f680: 6083 str r3, [r0, #8] + 1f682: 60c3 str r3, [r0, #12] + 1f684: 6103 str r3, [r0, #16] + 1f686: 6143 str r3, [r0, #20] + 1f688: 6183 str r3, [r0, #24] + 1f68a: 61c3 str r3, [r0, #28] + 1f68c: 6203 str r3, [r0, #32] + 1f68e: 6243 str r3, [r0, #36] ; 0x24 + 1f690: 62c3 str r3, [r0, #44] ; 0x2c + 1f692: 6303 str r3, [r0, #48] ; 0x30 + 1f694: 6343 str r3, [r0, #52] ; 0x34 + 1f696: 6383 str r3, [r0, #56] ; 0x38 + 1f698: 63c3 str r3, [r0, #60] ; 0x3c + 1f69a: 6403 str r3, [r0, #64] ; 0x40 + 1f69c: 6443 str r3, [r0, #68] ; 0x44 + 1f69e: 6483 str r3, [r0, #72] ; 0x48 + 1f6a0: 64c3 str r3, [r0, #76] ; 0x4c + 1f6a2: 6503 str r3, [r0, #80] ; 0x50 + 1f6a4: 6543 str r3, [r0, #84] ; 0x54 + 1f6a6: 6583 str r3, [r0, #88] ; 0x58 + 1f6a8: 65c3 str r3, [r0, #92] ; 0x5c + 1f6aa: 6603 str r3, [r0, #96] ; 0x60 + 1f6ac: 6643 str r3, [r0, #100] ; 0x64 + 1f6ae: 6683 str r3, [r0, #104] ; 0x68 + 1f6b0: 66c3 str r3, [r0, #108] ; 0x6c + 1f6b2: 6703 str r3, [r0, #112] ; 0x70 + 1f6b4: 6743 str r3, [r0, #116] ; 0x74 + 1f6b6: 1961 adds r1, r4, r5 + 1f6b8: 6007 str r7, [r0, #0] + 1f6ba: 6287 str r7, [r0, #40] ; 0x28 + 1f6bc: 0fd2 lsrs r2, r2, #31 + 1f6be: f7ff ffb1 bl 1f624 + 1f6c2: f086 0202 eor.w r2, r6, #2 + 1f6c6: f105 0178 add.w r1, r5, #120 ; 0x78 + 1f6ca: 3a01 subs r2, #1 + 1f6cc: 4640 mov r0, r8 + 1f6ce: 4421 add r1, r4 + 1f6d0: 0fd2 lsrs r2, r2, #31 + 1f6d2: f7ff ffa7 bl 1f624 + 1f6d6: f086 0203 eor.w r2, r6, #3 + 1f6da: f105 01f0 add.w r1, r5, #240 ; 0xf0 + 1f6de: 3a01 subs r2, #1 + 1f6e0: 4640 mov r0, r8 + 1f6e2: 4421 add r1, r4 + 1f6e4: 0fd2 lsrs r2, r2, #31 + 1f6e6: f7ff ff9d bl 1f624 + 1f6ea: f086 0204 eor.w r2, r6, #4 + 1f6ee: f505 71b4 add.w r1, r5, #360 ; 0x168 + 1f6f2: 3a01 subs r2, #1 + 1f6f4: 4640 mov r0, r8 + 1f6f6: 4421 add r1, r4 + 1f6f8: 0fd2 lsrs r2, r2, #31 + 1f6fa: f7ff ff93 bl 1f624 + 1f6fe: f086 0205 eor.w r2, r6, #5 + 1f702: f505 71f0 add.w r1, r5, #480 ; 0x1e0 + 1f706: 3a01 subs r2, #1 + 1f708: 4640 mov r0, r8 + 1f70a: 4421 add r1, r4 + 1f70c: 0fd2 lsrs r2, r2, #31 + 1f70e: f7ff ff89 bl 1f624 + 1f712: f086 0206 eor.w r2, r6, #6 + 1f716: f505 7116 add.w r1, r5, #600 ; 0x258 + 1f71a: 3a01 subs r2, #1 + 1f71c: 4640 mov r0, r8 + 1f71e: 4421 add r1, r4 + 1f720: 0fd2 lsrs r2, r2, #31 + 1f722: f7ff ff7f bl 1f624 + 1f726: f086 0207 eor.w r2, r6, #7 + 1f72a: f505 7134 add.w r1, r5, #720 ; 0x2d0 + 1f72e: 3a01 subs r2, #1 + 1f730: 4640 mov r0, r8 + 1f732: 4421 add r1, r4 + 1f734: 0fd2 lsrs r2, r2, #31 + 1f736: f086 0608 eor.w r6, r6, #8 + 1f73a: f7ff ff73 bl 1f624 + 1f73e: 1e72 subs r2, r6, #1 + 1f740: f505 7152 add.w r1, r5, #840 ; 0x348 + 1f744: 4421 add r1, r4 + 1f746: 4640 mov r0, r8 + 1f748: 0fd2 lsrs r2, r2, #31 + 1f74a: f7ff ff6b bl 1f624 + 1f74e: 4641 mov r1, r8 + 1f750: f8d8 302c ldr.w r3, [r8, #44] ; 0x2c + 1f754: f851 2b50 ldr.w r2, [r1], #80 + 1f758: 9301 str r3, [sp, #4] + 1f75a: f8d8 3040 ldr.w r3, [r8, #64] ; 0x40 + 1f75e: f8d8 7030 ldr.w r7, [r8, #48] ; 0x30 + 1f762: 9306 str r3, [sp, #24] + 1f764: f8d8 3044 ldr.w r3, [r8, #68] ; 0x44 + 1f768: f8d8 6034 ldr.w r6, [r8, #52] ; 0x34 + 1f76c: 9307 str r3, [sp, #28] + 1f76e: f8d8 3028 ldr.w r3, [r8, #40] ; 0x28 + 1f772: f8d8 5038 ldr.w r5, [r8, #56] ; 0x38 + 1f776: 9300 str r3, [sp, #0] + 1f778: f8d8 3004 ldr.w r3, [r8, #4] + 1f77c: f8d8 403c ldr.w r4, [r8, #60] ; 0x3c + 1f780: f8d8 004c ldr.w r0, [r8, #76] ; 0x4c + 1f784: 920a str r2, [sp, #40] ; 0x28 + 1f786: 9702 str r7, [sp, #8] + 1f788: f8d8 2048 ldr.w r2, [r8, #72] ; 0x48 + 1f78c: f8d8 700c ldr.w r7, [r8, #12] + 1f790: 9603 str r6, [sp, #12] + 1f792: 9504 str r5, [sp, #16] + 1f794: f8d8 6010 ldr.w r6, [r8, #16] + 1f798: 930b str r3, [sp, #44] ; 0x2c + 1f79a: f8d8 5014 ldr.w r5, [r8, #20] + 1f79e: f8d8 3008 ldr.w r3, [r8, #8] + 1f7a2: 9405 str r4, [sp, #20] + 1f7a4: 9208 str r2, [sp, #32] + 1f7a6: f8d8 4018 ldr.w r4, [r8, #24] + 1f7aa: f8d8 2024 ldr.w r2, [r8, #36] ; 0x24 + 1f7ae: 9009 str r0, [sp, #36] ; 0x24 + 1f7b0: 930c str r3, [sp, #48] ; 0x30 + 1f7b2: 970d str r7, [sp, #52] ; 0x34 + 1f7b4: 960e str r6, [sp, #56] ; 0x38 + 1f7b6: 950f str r5, [sp, #60] ; 0x3c + 1f7b8: f8d8 301c ldr.w r3, [r8, #28] + 1f7bc: a814 add r0, sp, #80 ; 0x50 + 1f7be: 9311 str r3, [sp, #68] ; 0x44 + 1f7c0: f8d8 3020 ldr.w r3, [r8, #32] + 1f7c4: 9213 str r2, [sp, #76] ; 0x4c + 1f7c6: 9312 str r3, [sp, #72] ; 0x48 + 1f7c8: 9410 str r4, [sp, #64] ; 0x40 + 1f7ca: f7fe fd77 bl 1e2bc + 1f7ce: 4640 mov r0, r8 + 1f7d0: 4669 mov r1, sp + 1f7d2: 464a mov r2, r9 + 1f7d4: f7ff ff26 bl 1f624 + 1f7d8: b01f add sp, #124 ; 0x7c + 1f7da: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + 1f7de: bf00 nop + 1f7e0: 000366e0 .word 0x000366e0 + +0001f7e4 : + 1f7e4: 7803 ldrb r3, [r0, #0] + 1f7e6: 7841 ldrb r1, [r0, #1] + 1f7e8: 7882 ldrb r2, [r0, #2] + 1f7ea: 4319 orrs r1, r3 + 1f7ec: 78c3 ldrb r3, [r0, #3] + 1f7ee: 4311 orrs r1, r2 + 1f7f0: 7902 ldrb r2, [r0, #4] + 1f7f2: 4319 orrs r1, r3 + 1f7f4: 7943 ldrb r3, [r0, #5] + 1f7f6: 4311 orrs r1, r2 + 1f7f8: 7982 ldrb r2, [r0, #6] + 1f7fa: 4319 orrs r1, r3 + 1f7fc: 79c3 ldrb r3, [r0, #7] + 1f7fe: 4311 orrs r1, r2 + 1f800: 7a02 ldrb r2, [r0, #8] + 1f802: 4319 orrs r1, r3 + 1f804: 7a43 ldrb r3, [r0, #9] + 1f806: 4311 orrs r1, r2 + 1f808: 7a82 ldrb r2, [r0, #10] + 1f80a: 4319 orrs r1, r3 + 1f80c: 7ac3 ldrb r3, [r0, #11] + 1f80e: 4311 orrs r1, r2 + 1f810: 7b02 ldrb r2, [r0, #12] + 1f812: 4319 orrs r1, r3 + 1f814: 7b43 ldrb r3, [r0, #13] + 1f816: 4311 orrs r1, r2 + 1f818: 7b82 ldrb r2, [r0, #14] + 1f81a: 4319 orrs r1, r3 + 1f81c: 7bc3 ldrb r3, [r0, #15] + 1f81e: 4311 orrs r1, r2 + 1f820: 7c02 ldrb r2, [r0, #16] + 1f822: 4319 orrs r1, r3 + 1f824: 7c43 ldrb r3, [r0, #17] + 1f826: 4311 orrs r1, r2 + 1f828: 7c82 ldrb r2, [r0, #18] + 1f82a: 4319 orrs r1, r3 + 1f82c: 7cc3 ldrb r3, [r0, #19] + 1f82e: 4311 orrs r1, r2 + 1f830: 7d02 ldrb r2, [r0, #20] + 1f832: 4319 orrs r1, r3 + 1f834: 7d43 ldrb r3, [r0, #21] + 1f836: 4311 orrs r1, r2 + 1f838: 7d82 ldrb r2, [r0, #22] + 1f83a: 4319 orrs r1, r3 + 1f83c: 7dc3 ldrb r3, [r0, #23] + 1f83e: 4311 orrs r1, r2 + 1f840: 7e02 ldrb r2, [r0, #24] + 1f842: 4319 orrs r1, r3 + 1f844: 7e43 ldrb r3, [r0, #25] + 1f846: 4311 orrs r1, r2 + 1f848: 7e82 ldrb r2, [r0, #26] + 1f84a: 4319 orrs r1, r3 + 1f84c: 7ec3 ldrb r3, [r0, #27] + 1f84e: 4311 orrs r1, r2 + 1f850: 7f02 ldrb r2, [r0, #28] + 1f852: 4319 orrs r1, r3 + 1f854: 7f43 ldrb r3, [r0, #29] + 1f856: 4311 orrs r1, r2 + 1f858: 7f82 ldrb r2, [r0, #30] + 1f85a: 4319 orrs r1, r3 + 1f85c: 7fc3 ldrb r3, [r0, #31] + 1f85e: ea41 0002 orr.w r0, r1, r2 + 1f862: 4318 orrs r0, r3 + 1f864: 4240 negs r0, r0 + 1f866: 17c0 asrs r0, r0, #31 + 1f868: 4770 bx lr + 1f86a: bf00 nop + +0001f86c : + 1f86c: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} + 1f870: 461d mov r5, r3 + 1f872: 4692 mov sl, r2 + 1f874: f6ad 1d08 subw sp, sp, #2312 ; 0x908 + 1f878: f50d 7802 add.w r8, sp, #520 ; 0x208 + 1f87c: 4604 mov r4, r0 + 1f87e: f50d 7942 add.w r9, sp, #776 ; 0x308 + 1f882: 4640 mov r0, r8 + 1f884: f7ff fa80 bl 1ed88 + 1f888: 4629 mov r1, r5 + 1f88a: 4648 mov r0, r9 + 1f88c: f7ff fa7c bl 1ed88 + 1f890: 4651 mov r1, sl + 1f892: f50d 6081 add.w r0, sp, #1032 ; 0x408 + 1f896: f7ff fe8b bl 1f5b0 + 1f89a: f8da 0004 ldr.w r0, [sl, #4] + 1f89e: f8da 700c ldr.w r7, [sl, #12] + 1f8a2: 905b str r0, [sp, #364] ; 0x16c + 1f8a4: f8da 0000 ldr.w r0, [sl] + 1f8a8: f8da 6010 ldr.w r6, [sl, #16] + 1f8ac: 905a str r0, [sp, #360] ; 0x168 + 1f8ae: f8da 0024 ldr.w r0, [sl, #36] ; 0x24 + 1f8b2: f8da 5014 ldr.w r5, [sl, #20] + 1f8b6: f8da 3008 ldr.w r3, [sl, #8] + 1f8ba: f8da 1020 ldr.w r1, [sl, #32] + 1f8be: 9063 str r0, [sp, #396] ; 0x18c + 1f8c0: f8da 0028 ldr.w r0, [sl, #40] ; 0x28 + 1f8c4: f8da 201c ldr.w r2, [sl, #28] + 1f8c8: 935c str r3, [sp, #368] ; 0x170 + 1f8ca: 975d str r7, [sp, #372] ; 0x174 + 1f8cc: f8da 3018 ldr.w r3, [sl, #24] + 1f8d0: f8da 702c ldr.w r7, [sl, #44] ; 0x2c + 1f8d4: 965e str r6, [sp, #376] ; 0x178 + 1f8d6: 955f str r5, [sp, #380] ; 0x17c + 1f8d8: f8da 6030 ldr.w r6, [sl, #48] ; 0x30 + 1f8dc: f8da 5034 ldr.w r5, [sl, #52] ; 0x34 + 1f8e0: 9162 str r1, [sp, #392] ; 0x188 + 1f8e2: 9064 str r0, [sp, #400] ; 0x190 + 1f8e4: f10a 0138 add.w r1, sl, #56 ; 0x38 + 1f8e8: f10a 0044 add.w r0, sl, #68 ; 0x44 + 1f8ec: 9360 str r3, [sp, #384] ; 0x180 + 1f8ee: 9261 str r2, [sp, #388] ; 0x184 + 1f8f0: 9765 str r7, [sp, #404] ; 0x194 + 1f8f2: c90e ldmia r1, {r1, r2, r3} + 1f8f4: 9666 str r6, [sp, #408] ; 0x198 + 1f8f6: c8c1 ldmia r0, {r0, r6, r7} + 1f8f8: 9567 str r5, [sp, #412] ; 0x19c + 1f8fa: 9168 str r1, [sp, #416] ; 0x1a0 + 1f8fc: 906b str r0, [sp, #428] ; 0x1ac + 1f8fe: f8da 1054 ldr.w r1, [sl, #84] ; 0x54 + 1f902: f8da 0060 ldr.w r0, [sl, #96] ; 0x60 + 1f906: f8da 5050 ldr.w r5, [sl, #80] ; 0x50 + 1f90a: 9072 str r0, [sp, #456] ; 0x1c8 + 1f90c: 916f str r1, [sp, #444] ; 0x1bc + 1f90e: f8da 0074 ldr.w r0, [sl, #116] ; 0x74 + 1f912: f8da 1070 ldr.w r1, [sl, #112] ; 0x70 + 1f916: 9269 str r2, [sp, #420] ; 0x1a4 + 1f918: 936a str r3, [sp, #424] ; 0x1a8 + 1f91a: f8da 2058 ldr.w r2, [sl, #88] ; 0x58 + 1f91e: f8da 305c ldr.w r3, [sl, #92] ; 0x5c + 1f922: 966c str r6, [sp, #432] ; 0x1b0 + 1f924: 976d str r7, [sp, #436] ; 0x1b4 + 1f926: f8da 6064 ldr.w r6, [sl, #100] ; 0x64 + 1f92a: f8da 7068 ldr.w r7, [sl, #104] ; 0x68 + 1f92e: 956e str r5, [sp, #440] ; 0x1b8 + 1f930: f8da 506c ldr.w r5, [sl, #108] ; 0x6c + 1f934: 9176 str r1, [sp, #472] ; 0x1d8 + 1f936: 9077 str r0, [sp, #476] ; 0x1dc + 1f938: a95a add r1, sp, #360 ; 0x168 + 1f93a: a80a add r0, sp, #40 ; 0x28 + 1f93c: 9371 str r3, [sp, #452] ; 0x1c4 + 1f93e: 9270 str r2, [sp, #448] ; 0x1c0 + 1f940: 9575 str r5, [sp, #468] ; 0x1d4 + 1f942: 9673 str r6, [sp, #460] ; 0x1cc + 1f944: 9774 str r7, [sp, #464] ; 0x1d0 + 1f946: f7ff fafb bl 1ef40 + 1f94a: a85a add r0, sp, #360 ; 0x168 + 1f94c: a90a add r1, sp, #40 ; 0x28 + 1f94e: f7ff fad5 bl 1eefc + 1f952: f50d 6281 add.w r2, sp, #1032 ; 0x408 + 1f956: a80a add r0, sp, #40 ; 0x28 + 1f958: a95a add r1, sp, #360 ; 0x168 + 1f95a: f7ff f9c9 bl 1ecf0 + 1f95e: a90a add r1, sp, #40 ; 0x28 + 1f960: a832 add r0, sp, #200 ; 0xc8 + 1f962: f7ff facb bl 1eefc + 1f966: a932 add r1, sp, #200 ; 0xc8 + 1f968: f50d 6095 add.w r0, sp, #1192 ; 0x4a8 + 1f96c: f7ff fe20 bl 1f5b0 + 1f970: f50d 6295 add.w r2, sp, #1192 ; 0x4a8 + 1f974: a80a add r0, sp, #40 ; 0x28 + 1f976: a95a add r1, sp, #360 ; 0x168 + 1f978: f7ff f9ba bl 1ecf0 + 1f97c: a832 add r0, sp, #200 ; 0xc8 + 1f97e: a90a add r1, sp, #40 ; 0x28 + 1f980: f7ff fabc bl 1eefc + 1f984: a932 add r1, sp, #200 ; 0xc8 + 1f986: f50d 60a9 add.w r0, sp, #1352 ; 0x548 + 1f98a: f7ff fe11 bl 1f5b0 + 1f98e: f50d 62a9 add.w r2, sp, #1352 ; 0x548 + 1f992: a80a add r0, sp, #40 ; 0x28 + 1f994: a95a add r1, sp, #360 ; 0x168 + 1f996: f7ff f9ab bl 1ecf0 + 1f99a: a832 add r0, sp, #200 ; 0xc8 + 1f99c: a90a add r1, sp, #40 ; 0x28 + 1f99e: f7ff faad bl 1eefc + 1f9a2: a932 add r1, sp, #200 ; 0xc8 + 1f9a4: f50d 60bd add.w r0, sp, #1512 ; 0x5e8 + 1f9a8: f7ff fe02 bl 1f5b0 + 1f9ac: f50d 62bd add.w r2, sp, #1512 ; 0x5e8 + 1f9b0: a80a add r0, sp, #40 ; 0x28 + 1f9b2: a95a add r1, sp, #360 ; 0x168 + 1f9b4: f7ff f99c bl 1ecf0 + 1f9b8: a832 add r0, sp, #200 ; 0xc8 + 1f9ba: a90a add r1, sp, #40 ; 0x28 + 1f9bc: f7ff fa9e bl 1eefc + 1f9c0: a932 add r1, sp, #200 ; 0xc8 + 1f9c2: f50d 60d1 add.w r0, sp, #1672 ; 0x688 + 1f9c6: f7ff fdf3 bl 1f5b0 + 1f9ca: f50d 62d1 add.w r2, sp, #1672 ; 0x688 + 1f9ce: a80a add r0, sp, #40 ; 0x28 + 1f9d0: a95a add r1, sp, #360 ; 0x168 + 1f9d2: f7ff f98d bl 1ecf0 + 1f9d6: a832 add r0, sp, #200 ; 0xc8 + 1f9d8: a90a add r1, sp, #40 ; 0x28 + 1f9da: f7ff fa8f bl 1eefc + 1f9de: a932 add r1, sp, #200 ; 0xc8 + 1f9e0: f50d 60e5 add.w r0, sp, #1832 ; 0x728 + 1f9e4: f7ff fde4 bl 1f5b0 + 1f9e8: f50d 62e5 add.w r2, sp, #1832 ; 0x728 + 1f9ec: a80a add r0, sp, #40 ; 0x28 + 1f9ee: a95a add r1, sp, #360 ; 0x168 + 1f9f0: f7ff f97e bl 1ecf0 + 1f9f4: a832 add r0, sp, #200 ; 0xc8 + 1f9f6: a90a add r1, sp, #40 ; 0x28 + 1f9f8: f7ff fa80 bl 1eefc + 1f9fc: a932 add r1, sp, #200 ; 0xc8 + 1f9fe: f50d 60f9 add.w r0, sp, #1992 ; 0x7c8 + 1fa02: f7ff fdd5 bl 1f5b0 + 1fa06: f50d 62f9 add.w r2, sp, #1992 ; 0x7c8 + 1fa0a: a80a add r0, sp, #40 ; 0x28 + 1fa0c: a95a add r1, sp, #360 ; 0x168 + 1fa0e: f7ff f96f bl 1ecf0 + 1fa12: a832 add r0, sp, #200 ; 0xc8 + 1fa14: a90a add r1, sp, #40 ; 0x28 + 1fa16: f7ff fa71 bl 1eefc + 1fa1a: a932 add r1, sp, #200 ; 0xc8 + 1fa1c: f60d 0068 addw r0, sp, #2152 ; 0x868 + 1fa20: f7ff fdc6 bl 1f5b0 + 1fa24: 2300 movs r3, #0 + 1fa26: 2201 movs r2, #1 + 1fa28: 6023 str r3, [r4, #0] + 1fa2a: 6063 str r3, [r4, #4] + 1fa2c: 60a3 str r3, [r4, #8] + 1fa2e: 60e3 str r3, [r4, #12] + 1fa30: 6123 str r3, [r4, #16] + 1fa32: 6163 str r3, [r4, #20] + 1fa34: 61a3 str r3, [r4, #24] + 1fa36: 61e3 str r3, [r4, #28] + 1fa38: 6223 str r3, [r4, #32] + 1fa3a: 6263 str r3, [r4, #36] ; 0x24 + 1fa3c: 62e3 str r3, [r4, #44] ; 0x2c + 1fa3e: 6323 str r3, [r4, #48] ; 0x30 + 1fa40: 6363 str r3, [r4, #52] ; 0x34 + 1fa42: 63a3 str r3, [r4, #56] ; 0x38 + 1fa44: 63e3 str r3, [r4, #60] ; 0x3c + 1fa46: 6423 str r3, [r4, #64] ; 0x40 + 1fa48: 6463 str r3, [r4, #68] ; 0x44 + 1fa4a: 64a3 str r3, [r4, #72] ; 0x48 + 1fa4c: 64e3 str r3, [r4, #76] ; 0x4c + 1fa4e: 6563 str r3, [r4, #84] ; 0x54 + 1fa50: 65a3 str r3, [r4, #88] ; 0x58 + 1fa52: 65e3 str r3, [r4, #92] ; 0x5c + 1fa54: 6623 str r3, [r4, #96] ; 0x60 + 1fa56: 6663 str r3, [r4, #100] ; 0x64 + 1fa58: 66a3 str r3, [r4, #104] ; 0x68 + 1fa5a: 66e3 str r3, [r4, #108] ; 0x6c + 1fa5c: 6723 str r3, [r4, #112] ; 0x70 + 1fa5e: 6763 str r3, [r4, #116] ; 0x74 + 1fa60: 62a2 str r2, [r4, #40] ; 0x28 + 1fa62: 6522 str r2, [r4, #80] ; 0x50 + 1fa64: 25ff movs r5, #255 ; 0xff + 1fa66: e006 b.n 1fa76 + 1fa68: f919 3005 ldrsb.w r3, [r9, r5] + 1fa6c: b93b cbnz r3, 1fa7e + 1fa6e: f115 35ff adds.w r5, r5, #4294967295 + 1fa72: f0c0 80d8 bcc.w 1fc26 + 1fa76: f918 3005 ldrsb.w r3, [r8, r5] + 1fa7a: 2b00 cmp r3, #0 + 1fa7c: d0f4 beq.n 1fa68 + 1fa7e: 44a8 add r8, r5 + 1fa80: 44a9 add r9, r5 + 1fa82: 4e6b ldr r6, [pc, #428] ; (1fc30 ) + 1fa84: e030 b.n 1fae8 + 1fa86: a832 add r0, sp, #200 ; 0xc8 + 1fa88: a90a add r1, sp, #40 ; 0x28 + 1fa8a: f7ff fa37 bl 1eefc + 1fa8e: f998 2001 ldrsb.w r2, [r8, #1] + 1fa92: f50d 6181 add.w r1, sp, #1032 ; 0x408 + 1fa96: eb02 72d2 add.w r2, r2, r2, lsr #31 + 1fa9a: 1052 asrs r2, r2, #1 + 1fa9c: eb02 0282 add.w r2, r2, r2, lsl #2 + 1faa0: eb01 1242 add.w r2, r1, r2, lsl #5 + 1faa4: a80a add r0, sp, #40 ; 0x28 + 1faa6: a932 add r1, sp, #200 ; 0xc8 + 1faa8: f7ff f922 bl 1ecf0 + 1faac: f819 3901 ldrb.w r3, [r9], #-1 + 1fab0: b25a sxtb r2, r3 + 1fab2: 2a00 cmp r2, #0 + 1fab4: dd72 ble.n 1fb9c + 1fab6: a832 add r0, sp, #200 ; 0xc8 + 1fab8: a90a add r1, sp, #40 ; 0x28 + 1faba: f7ff fa1f bl 1eefc + 1fabe: f999 2001 ldrsb.w r2, [r9, #1] + 1fac2: a80a add r0, sp, #40 ; 0x28 + 1fac4: eb02 72d2 add.w r2, r2, r2, lsr #31 + 1fac8: 1052 asrs r2, r2, #1 + 1faca: ebc2 1202 rsb r2, r2, r2, lsl #4 + 1face: eb06 02c2 add.w r2, r6, r2, lsl #3 + 1fad2: a932 add r1, sp, #200 ; 0xc8 + 1fad4: f7ff f9b2 bl 1ee3c + 1fad8: 3d01 subs r5, #1 + 1fada: 4620 mov r0, r4 + 1fadc: a90a add r1, sp, #40 ; 0x28 + 1fade: f7ff f9f3 bl 1eec8 + 1fae2: 1c6b adds r3, r5, #1 + 1fae4: f000 809f beq.w 1fc26 + 1fae8: a80a add r0, sp, #40 ; 0x28 + 1faea: 4621 mov r1, r4 + 1faec: f7ff fa28 bl 1ef40 + 1faf0: f818 3901 ldrb.w r3, [r8], #-1 + 1faf4: b25a sxtb r2, r3 + 1faf6: 2a00 cmp r2, #0 + 1faf8: dcc5 bgt.n 1fa86 + 1fafa: 2b00 cmp r3, #0 + 1fafc: d0d6 beq.n 1faac + 1fafe: a832 add r0, sp, #200 ; 0xc8 + 1fb00: a90a add r1, sp, #40 ; 0x28 + 1fb02: f7ff f9fb bl 1eefc + 1fb06: f998 7001 ldrsb.w r7, [r8, #1] + 1fb0a: f50d 6381 add.w r3, sp, #1032 ; 0x408 + 1fb0e: eb07 77d7 add.w r7, r7, r7, lsr #31 + 1fb12: 107f asrs r7, r7, #1 + 1fb14: 427f negs r7, r7 + 1fb16: a80a add r0, sp, #40 ; 0x28 + 1fb18: a93c add r1, sp, #240 ; 0xf0 + 1fb1a: aa32 add r2, sp, #200 ; 0xc8 + 1fb1c: eb07 0787 add.w r7, r7, r7, lsl #2 + 1fb20: eb03 1747 add.w r7, r3, r7, lsl #5 + 1fb24: f7fd fef8 bl 1d918 + 1fb28: a814 add r0, sp, #80 ; 0x50 + 1fb2a: a93c add r1, sp, #240 ; 0xf0 + 1fb2c: aa32 add r2, sp, #200 ; 0xc8 + 1fb2e: f7fe ffbf bl 1eab0 + 1fb32: a81e add r0, sp, #120 ; 0x78 + 1fb34: a90a add r1, sp, #40 ; 0x28 + 1fb36: f107 0228 add.w r2, r7, #40 ; 0x28 + 1fb3a: f7fd ff8d bl 1da58 + 1fb3e: a814 add r0, sp, #80 ; 0x50 + 1fb40: 4601 mov r1, r0 + 1fb42: 463a mov r2, r7 + 1fb44: f7fd ff88 bl 1da58 + 1fb48: a828 add r0, sp, #160 ; 0xa0 + 1fb4a: f107 0178 add.w r1, r7, #120 ; 0x78 + 1fb4e: aa50 add r2, sp, #320 ; 0x140 + 1fb50: f7fd ff82 bl 1da58 + 1fb54: a80a add r0, sp, #40 ; 0x28 + 1fb56: f107 0250 add.w r2, r7, #80 ; 0x50 + 1fb5a: a946 add r1, sp, #280 ; 0x118 + 1fb5c: f7fd ff7c bl 1da58 + 1fb60: a90a add r1, sp, #40 ; 0x28 + 1fb62: 460a mov r2, r1 + 1fb64: 4668 mov r0, sp + 1fb66: f7fd fed7 bl 1d918 + 1fb6a: a80a add r0, sp, #40 ; 0x28 + 1fb6c: a91e add r1, sp, #120 ; 0x78 + 1fb6e: aa14 add r2, sp, #80 ; 0x50 + 1fb70: f7fe ff9e bl 1eab0 + 1fb74: a814 add r0, sp, #80 ; 0x50 + 1fb76: 4602 mov r2, r0 + 1fb78: a91e add r1, sp, #120 ; 0x78 + 1fb7a: f7fd fecd bl 1d918 + 1fb7e: a81e add r0, sp, #120 ; 0x78 + 1fb80: 4669 mov r1, sp + 1fb82: aa28 add r2, sp, #160 ; 0xa0 + 1fb84: f7fe ff94 bl 1eab0 + 1fb88: a828 add r0, sp, #160 ; 0xa0 + 1fb8a: 4602 mov r2, r0 + 1fb8c: 4669 mov r1, sp + 1fb8e: f7fd fec3 bl 1d918 + 1fb92: f819 3901 ldrb.w r3, [r9], #-1 + 1fb96: b25a sxtb r2, r3 + 1fb98: 2a00 cmp r2, #0 + 1fb9a: dc8c bgt.n 1fab6 + 1fb9c: 2b00 cmp r3, #0 + 1fb9e: d09b beq.n 1fad8 + 1fba0: a832 add r0, sp, #200 ; 0xc8 + 1fba2: a90a add r1, sp, #40 ; 0x28 + 1fba4: f7ff f9aa bl 1eefc + 1fba8: f999 3001 ldrsb.w r3, [r9, #1] + 1fbac: a80a add r0, sp, #40 ; 0x28 + 1fbae: eb03 73d3 add.w r3, r3, r3, lsr #31 + 1fbb2: 105b asrs r3, r3, #1 + 1fbb4: 425b negs r3, r3 + 1fbb6: ebc3 1303 rsb r3, r3, r3, lsl #4 + 1fbba: a93c add r1, sp, #240 ; 0xf0 + 1fbbc: aa32 add r2, sp, #200 ; 0xc8 + 1fbbe: eb06 07c3 add.w r7, r6, r3, lsl #3 + 1fbc2: f7fd fea9 bl 1d918 + 1fbc6: a814 add r0, sp, #80 ; 0x50 + 1fbc8: a93c add r1, sp, #240 ; 0xf0 + 1fbca: aa32 add r2, sp, #200 ; 0xc8 + 1fbcc: f7fe ff70 bl 1eab0 + 1fbd0: a81e add r0, sp, #120 ; 0x78 + 1fbd2: a90a add r1, sp, #40 ; 0x28 + 1fbd4: f107 0228 add.w r2, r7, #40 ; 0x28 + 1fbd8: f7fd ff3e bl 1da58 + 1fbdc: a814 add r0, sp, #80 ; 0x50 + 1fbde: 4601 mov r1, r0 + 1fbe0: 463a mov r2, r7 + 1fbe2: f7fd ff39 bl 1da58 + 1fbe6: a828 add r0, sp, #160 ; 0xa0 + 1fbe8: f107 0150 add.w r1, r7, #80 ; 0x50 + 1fbec: aa50 add r2, sp, #320 ; 0x140 + 1fbee: f7fd ff33 bl 1da58 + 1fbf2: a946 add r1, sp, #280 ; 0x118 + 1fbf4: 460a mov r2, r1 + 1fbf6: 4668 mov r0, sp + 1fbf8: f7fd fe8e bl 1d918 + 1fbfc: a80a add r0, sp, #40 ; 0x28 + 1fbfe: a91e add r1, sp, #120 ; 0x78 + 1fc00: aa14 add r2, sp, #80 ; 0x50 + 1fc02: f7fe ff55 bl 1eab0 + 1fc06: a814 add r0, sp, #80 ; 0x50 + 1fc08: a91e add r1, sp, #120 ; 0x78 + 1fc0a: 4602 mov r2, r0 + 1fc0c: f7fd fe84 bl 1d918 + 1fc10: a81e add r0, sp, #120 ; 0x78 + 1fc12: 4669 mov r1, sp + 1fc14: aa28 add r2, sp, #160 ; 0xa0 + 1fc16: f7fe ff4b bl 1eab0 + 1fc1a: a828 add r0, sp, #160 ; 0xa0 + 1fc1c: 4669 mov r1, sp + 1fc1e: 4602 mov r2, r0 + 1fc20: f7fd fe7a bl 1d918 + 1fc24: e758 b.n 1fad8 + 1fc26: f60d 1d08 addw sp, sp, #2312 ; 0x908 + 1fc2a: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + 1fc2e: bf00 nop + 1fc30: 0003dee0 .word 0x0003dee0 + +0001fc34 : + 1fc34: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 1fc38: 460e mov r6, r1 + 1fc3a: 7f8a ldrb r2, [r1, #30] + 1fc3c: 7fcc ldrb r4, [r1, #31] + 1fc3e: b0f9 sub sp, #484 ; 0x1e4 + 1fc40: f891 a012 ldrb.w sl, [r1, #18] + 1fc44: 2300 movs r3, #0 + 1fc46: 2500 movs r5, #0 + 1fc48: e9cd 2304 strd r2, r3, [sp, #16] + 1fc4c: e9cd 4508 strd r4, r5, [sp, #32] + 1fc50: f04f 0b00 mov.w fp, #0 + 1fc54: e9cd ab02 strd sl, fp, [sp, #8] + 1fc58: 9f08 ldr r7, [sp, #32] + 1fc5a: f8dd a010 ldr.w sl, [sp, #16] + 1fc5e: 9b04 ldr r3, [sp, #16] + 1fc60: 043a lsls r2, r7, #16 + 1fc62: ea4f 240a mov.w r4, sl, lsl #8 + 1fc66: ea44 0a02 orr.w sl, r4, r2 + 1fc6a: 0e1d lsrs r5, r3, #24 + 1fc6c: 798c ldrb r4, [r1, #6] + 1fc6e: 0c3b lsrs r3, r7, #16 + 1fc70: ea45 0b03 orr.w fp, r5, r3 + 1fc74: 2500 movs r5, #0 + 1fc76: e9cd 450e strd r4, r5, [sp, #56] ; 0x38 + 1fc7a: 7b0c ldrb r4, [r1, #12] + 1fc7c: e9cd ab18 strd sl, fp, [sp, #96] ; 0x60 + 1fc80: 2500 movs r5, #0 + 1fc82: f891 a00b ldrb.w sl, [r1, #11] + 1fc86: f891 8011 ldrb.w r8, [r1, #17] + 1fc8a: e9cd 4524 strd r4, r5, [sp, #144] ; 0x90 + 1fc8e: f04f 0b00 mov.w fp, #0 + 1fc92: 7e4c ldrb r4, [r1, #25] + 1fc94: 9f02 ldr r7, [sp, #8] + 1fc96: e9cd ab14 strd sl, fp, [sp, #80] ; 0x50 + 1fc9a: 2500 movs r5, #0 + 1fc9c: f891 a018 ldrb.w sl, [r1, #24] + 1fca0: e9cd 4512 strd r4, r5, [sp, #72] ; 0x48 + 1fca4: ea4f 2c08 mov.w ip, r8, lsl #8 + 1fca8: ea4f 6518 mov.w r5, r8, lsr #24 + 1fcac: f04f 0b00 mov.w fp, #0 + 1fcb0: e9cd ab0c strd sl, fp, [sp, #48] ; 0x30 + 1fcb4: f8cd c018 str.w ip, [sp, #24] + 1fcb8: ea4f 4a07 mov.w sl, r7, lsl #16 + 1fcbc: 9507 str r5, [sp, #28] + 1fcbe: 7f4a ldrb r2, [r1, #29] + 1fcc0: ea4f 4b17 mov.w fp, r7, lsr #16 + 1fcc4: f896 8010 ldrb.w r8, [r6, #16] + 1fcc8: e9dd 4506 ldrd r4, r5, [sp, #24] + 1fccc: ea44 040a orr.w r4, r4, sl + 1fcd0: f896 a001 ldrb.w sl, [r6, #1] + 1fcd4: ea45 050b orr.w r5, r5, fp + 1fcd8: 2300 movs r3, #0 + 1fcda: f04f 0900 mov.w r9, #0 + 1fcde: f04f 0b00 mov.w fp, #0 + 1fce2: e9cd 2316 strd r2, r3, [sp, #88] ; 0x58 + 1fce6: e9cd 8910 strd r8, r9, [sp, #64] ; 0x40 + 1fcea: 794a ldrb r2, [r1, #5] + 1fcec: e9cd 452a strd r4, r5, [sp, #168] ; 0xa8 + 1fcf0: e9cd ab22 strd sl, fp, [sp, #136] ; 0x88 + 1fcf4: e9dd ab16 ldrd sl, fp, [sp, #88] ; 0x58 + 1fcf8: f896 8002 ldrb.w r8, [r6, #2] + 1fcfc: f04f 0900 mov.w r9, #0 + 1fd00: e9cd 891a strd r8, r9, [sp, #104] ; 0x68 + 1fd04: e9dd 8918 ldrd r8, r9, [sp, #96] ; 0x60 + 1fd08: ea49 090b orr.w r9, r9, fp + 1fd0c: f8dd b038 ldr.w fp, [sp, #56] ; 0x38 + 1fd10: ea48 080a orr.w r8, r8, sl + 1fd14: ea4f 4b1b mov.w fp, fp, lsr #16 + 1fd18: f8dd a048 ldr.w sl, [sp, #72] ; 0x48 + 1fd1c: f8cd b00c str.w fp, [sp, #12] + 1fd20: f8dd c050 ldr.w ip, [sp, #80] ; 0x50 + 1fd24: f8dd b038 ldr.w fp, [sp, #56] ; 0x38 + 1fd28: ea4f 4a1a mov.w sl, sl, lsr #16 + 1fd2c: f8cd a02c str.w sl, [sp, #44] ; 0x2c + 1fd30: ea4f 6c1c mov.w ip, ip, lsr #24 + 1fd34: f896 a00a ldrb.w sl, [r6, #10] + 1fd38: ea4f 4b0b mov.w fp, fp, lsl #16 + 1fd3c: e9cd 893a strd r8, r9, [sp, #232] ; 0xe8 + 1fd40: f8cd c014 str.w ip, [sp, #20] + 1fd44: ea4f 6912 mov.w r9, r2, lsr #24 + 1fd48: ea4f 2802 mov.w r8, r2, lsl #8 + 1fd4c: f8cd b008 str.w fp, [sp, #8] + 1fd50: 9f0c ldr r7, [sp, #48] ; 0x30 + 1fd52: f8dd c050 ldr.w ip, [sp, #80] ; 0x50 + 1fd56: 9a0c ldr r2, [sp, #48] ; 0x30 + 1fd58: 9b12 ldr r3, [sp, #72] ; 0x48 + 1fd5a: f04f 0b00 mov.w fp, #0 + 1fd5e: 9924 ldr r1, [sp, #144] ; 0x90 + 1fd60: e9cd ab32 strd sl, fp, [sp, #200] ; 0xc8 + 1fd64: f896 a017 ldrb.w sl, [r6, #23] + 1fd68: 0e3f lsrs r7, r7, #24 + 1fd6a: ea4f 2c0c mov.w ip, ip, lsl #8 + 1fd6e: 0212 lsls r2, r2, #8 + 1fd70: 041b lsls r3, r3, #16 + 1fd72: f04f 0b00 mov.w fp, #0 + 1fd76: 9709 str r7, [sp, #36] ; 0x24 + 1fd78: f8cd c010 str.w ip, [sp, #16] + 1fd7c: 9208 str r2, [sp, #32] + 1fd7e: 930a str r3, [sp, #40] ; 0x28 + 1fd80: 0c0d lsrs r5, r1, #16 + 1fd82: 040c lsls r4, r1, #16 + 1fd84: e9cd ab36 strd sl, fp, [sp, #216] ; 0xd8 + 1fd88: e9dd ab02 ldrd sl, fp, [sp, #8] + 1fd8c: ea4a 0a08 orr.w sl, sl, r8 + 1fd90: ea4b 0b09 orr.w fp, fp, r9 + 1fd94: e9cd ab2c strd sl, fp, [sp, #176] ; 0xb0 + 1fd98: e9dd 8904 ldrd r8, r9, [sp, #16] + 1fd9c: e9dd ab08 ldrd sl, fp, [sp, #32] + 1fda0: ea44 0408 orr.w r4, r4, r8 + 1fda4: ea45 0509 orr.w r5, r5, r9 + 1fda8: e9dd 890a ldrd r8, r9, [sp, #40] ; 0x28 + 1fdac: ea4a 0a08 orr.w sl, sl, r8 + 1fdb0: ea4b 0b09 orr.w fp, fp, r9 + 1fdb4: e9cd ab38 strd sl, fp, [sp, #224] ; 0xe0 + 1fdb8: f896 a008 ldrb.w sl, [r6, #8] + 1fdbc: f04f 0b00 mov.w fp, #0 + 1fdc0: 7932 ldrb r2, [r6, #4] + 1fdc2: e9cd ab14 strd sl, fp, [sp, #80] ; 0x50 + 1fdc6: f896 8009 ldrb.w r8, [r6, #9] + 1fdca: f896 a00e ldrb.w sl, [r6, #14] + 1fdce: f04f 0900 mov.w r9, #0 + 1fdd2: f04f 0b00 mov.w fp, #0 + 1fdd6: e9cd 8916 strd r8, r9, [sp, #88] ; 0x58 + 1fdda: e9cd ab18 strd sl, fp, [sp, #96] ; 0x60 + 1fdde: f896 800f ldrb.w r8, [r6, #15] + 1fde2: f896 a013 ldrb.w sl, [r6, #19] + 1fde6: f04f 0900 mov.w r9, #0 + 1fdea: f04f 0b00 mov.w fp, #0 + 1fdee: e9cd 891c strd r8, r9, [sp, #112] ; 0x70 + 1fdf2: e9cd ab1e strd sl, fp, [sp, #120] ; 0x78 + 1fdf6: f896 8015 ldrb.w r8, [r6, #21] + 1fdfa: f896 a016 ldrb.w sl, [r6, #22] + 1fdfe: f04f 0900 mov.w r9, #0 + 1fe02: f04f 0b00 mov.w fp, #0 + 1fe06: e9cd 8920 strd r8, r9, [sp, #128] ; 0x80 + 1fe0a: e9cd ab26 strd sl, fp, [sp, #152] ; 0x98 + 1fe0e: f896 801b ldrb.w r8, [r6, #27] + 1fe12: f896 a01c ldrb.w sl, [r6, #28] + 1fe16: f04f 0900 mov.w r9, #0 + 1fe1a: f04f 0b00 mov.w fp, #0 + 1fe1e: e9cd 8928 strd r8, r9, [sp, #160] ; 0xa0 + 1fe22: e9dd 8910 ldrd r8, r9, [sp, #64] ; 0x40 + 1fe26: e9cd ab2e strd sl, fp, [sp, #184] ; 0xb8 + 1fe2a: e9dd ab2a ldrd sl, fp, [sp, #168] ; 0xa8 + 1fe2e: ea4a 0a08 orr.w sl, sl, r8 + 1fe32: ea4b 0b09 orr.w fp, fp, r9 + 1fe36: e9cd ab34 strd sl, fp, [sp, #208] ; 0xd0 + 1fe3a: f8dd 9088 ldr.w r9, [sp, #136] ; 0x88 + 1fe3e: f8dd b088 ldr.w fp, [sp, #136] ; 0x88 + 1fe42: f8dd c068 ldr.w ip, [sp, #104] ; 0x68 + 1fe46: ea4f 6b1b mov.w fp, fp, lsr #24 + 1fe4a: ea4f 2909 mov.w r9, r9, lsl #8 + 1fe4e: f8cd b01c str.w fp, [sp, #28] + 1fe52: f8cd 9018 str.w r9, [sp, #24] + 1fe56: ea4f 4a0c mov.w sl, ip, lsl #16 + 1fe5a: e9dd 8906 ldrd r8, r9, [sp, #24] + 1fe5e: ea4f 4b1c mov.w fp, ip, lsr #16 + 1fe62: ea48 080a orr.w r8, r8, sl + 1fe66: f896 a000 ldrb.w sl, [r6] + 1fe6a: ea49 090b orr.w r9, r9, fp + 1fe6e: f04f 0b00 mov.w fp, #0 + 1fe72: e9cd ab2a strd sl, fp, [sp, #168] ; 0xa8 + 1fe76: f64f 7aff movw sl, #65535 ; 0xffff + 1fe7a: f2c0 0a7f movt sl, #127 ; 0x7f + 1fe7e: 2300 movs r3, #0 + 1fe80: f04f 0b00 mov.w fp, #0 + 1fe84: e9cd 8930 strd r8, r9, [sp, #192] ; 0xc0 + 1fe88: e9dd 893a ldrd r8, r9, [sp, #232] ; 0xe8 + 1fe8c: ea08 080a and.w r8, r8, sl + 1fe90: ea09 090b and.w r9, r9, fp + 1fe94: e9dd ab2c ldrd sl, fp, [sp, #176] ; 0xb0 + 1fe98: ea4a 0a02 orr.w sl, sl, r2 + 1fe9c: ea4b 0b03 orr.w fp, fp, r3 + 1fea0: e9cd ab06 strd sl, fp, [sp, #24] + 1fea4: e9dd 2338 ldrd r2, r3, [sp, #224] ; 0xe0 + 1fea8: e9dd ab32 ldrd sl, fp, [sp, #200] ; 0xc8 + 1feac: ea4a 0a04 orr.w sl, sl, r4 + 1feb0: ea4b 0b05 orr.w fp, fp, r5 + 1feb4: e9dd 4536 ldrd r4, r5, [sp, #216] ; 0xd8 + 1feb8: 432b orrs r3, r5 + 1feba: 9d14 ldr r5, [sp, #80] ; 0x50 + 1febc: e9cd ab32 strd sl, fp, [sp, #200] ; 0xc8 + 1fec0: 0e2d lsrs r5, r5, #24 + 1fec2: 9503 str r5, [sp, #12] + 1fec4: 9f16 ldr r7, [sp, #88] ; 0x58 + 1fec6: f8dd b060 ldr.w fp, [sp, #96] ; 0x60 + 1feca: 9d28 ldr r5, [sp, #160] ; 0xa0 + 1fecc: 0c3f lsrs r7, r7, #16 + 1fece: ea4f 6b1b mov.w fp, fp, lsr #24 + 1fed2: 0e2d lsrs r5, r5, #24 + 1fed4: 4322 orrs r2, r4 + 1fed6: 9705 str r7, [sp, #20] + 1fed8: f8dd a078 ldr.w sl, [sp, #120] ; 0x78 + 1fedc: f8cd b024 str.w fp, [sp, #36] ; 0x24 + 1fee0: f8dd c070 ldr.w ip, [sp, #112] ; 0x70 + 1fee4: 9920 ldr r1, [sp, #128] ; 0x80 + 1fee6: 9c26 ldr r4, [sp, #152] ; 0x98 + 1fee8: 9511 str r5, [sp, #68] ; 0x44 + 1feea: 9f2e ldr r7, [sp, #184] ; 0xb8 + 1feec: f8dd b058 ldr.w fp, [sp, #88] ; 0x58 + 1fef0: 9d1e ldr r5, [sp, #120] ; 0x78 + 1fef2: ea4f 2a1a mov.w sl, sl, lsr #8 + 1fef6: ea4f 4c1c mov.w ip, ip, lsr #16 + 1fefa: 0e09 lsrs r1, r1, #24 + 1fefc: 0c24 lsrs r4, r4, #16 + 1fefe: 0c3f lsrs r7, r7, #16 + 1ff00: ea4f 4b0b mov.w fp, fp, lsl #16 + 1ff04: 062d lsls r5, r5, #24 + 1ff06: f8cd a03c str.w sl, [sp, #60] ; 0x3c + 1ff0a: f8cd c02c str.w ip, [sp, #44] ; 0x2c + 1ff0e: 910d str r1, [sp, #52] ; 0x34 + 1ff10: 9413 str r4, [sp, #76] ; 0x4c + 1ff12: 9701 str r7, [sp, #4] + 1ff14: f8dd a050 ldr.w sl, [sp, #80] ; 0x50 + 1ff18: f8cd b010 str.w fp, [sp, #16] + 1ff1c: 950e str r5, [sp, #56] ; 0x38 + 1ff1e: f8dd b060 ldr.w fp, [sp, #96] ; 0x60 + 1ff22: f8dd c070 ldr.w ip, [sp, #112] ; 0x70 + 1ff26: 9920 ldr r1, [sp, #128] ; 0x80 + 1ff28: 9c26 ldr r4, [sp, #152] ; 0x98 + 1ff2a: 9d28 ldr r5, [sp, #160] ; 0xa0 + 1ff2c: 9f2e ldr r7, [sp, #184] ; 0xb8 + 1ff2e: ea4f 2a0a mov.w sl, sl, lsl #8 + 1ff32: ea4f 2b0b mov.w fp, fp, lsl #8 + 1ff36: ea4f 4c0c mov.w ip, ip, lsl #16 + 1ff3a: 0209 lsls r1, r1, #8 + 1ff3c: 0424 lsls r4, r4, #16 + 1ff3e: 022d lsls r5, r5, #8 + 1ff40: 043f lsls r7, r7, #16 + 1ff42: f8cd a008 str.w sl, [sp, #8] + 1ff46: f8cd b020 str.w fp, [sp, #32] + 1ff4a: f8cd c028 str.w ip, [sp, #40] ; 0x28 + 1ff4e: 910c str r1, [sp, #48] ; 0x30 + 1ff50: 9412 str r4, [sp, #72] ; 0x48 + 1ff52: 9510 str r5, [sp, #64] ; 0x40 + 1ff54: 9700 str r7, [sp, #0] + 1ff56: f896 a007 ldrb.w sl, [r6, #7] + 1ff5a: 7b74 ldrb r4, [r6, #13] + 1ff5c: f04f 0b00 mov.w fp, #0 + 1ff60: 2500 movs r5, #0 + 1ff62: e9cd ab1c strd sl, fp, [sp, #112] ; 0x70 + 1ff66: e9cd 451e strd r4, r5, [sp, #120] ; 0x78 + 1ff6a: f896 a014 ldrb.w sl, [r6, #20] + 1ff6e: 7eb4 ldrb r4, [r6, #26] + 1ff70: f04f 0b00 mov.w fp, #0 + 1ff74: 2500 movs r5, #0 + 1ff76: e9cd ab20 strd sl, fp, [sp, #128] ; 0x80 + 1ff7a: e9dd ab02 ldrd sl, fp, [sp, #8] + 1ff7e: e9cd 452c strd r4, r5, [sp, #176] ; 0xb0 + 1ff82: e9dd 4504 ldrd r4, r5, [sp, #16] + 1ff86: ea4a 0a04 orr.w sl, sl, r4 + 1ff8a: ea4b 0b05 orr.w fp, fp, r5 + 1ff8e: e9cd ab02 strd sl, fp, [sp, #8] + 1ff92: e9dd 450e ldrd r4, r5, [sp, #56] ; 0x38 + 1ff96: e9dd ab34 ldrd sl, fp, [sp, #208] ; 0xd0 + 1ff9a: ea4a 0a04 orr.w sl, sl, r4 + 1ff9e: ea4b 0b05 orr.w fp, fp, r5 + 1ffa2: e9cd ab2e strd sl, fp, [sp, #184] ; 0xb8 + 1ffa6: e9dd 450a ldrd r4, r5, [sp, #40] ; 0x28 + 1ffaa: e9dd ab08 ldrd sl, fp, [sp, #32] + 1ffae: ea4a 0a04 orr.w sl, sl, r4 + 1ffb2: ea4b 0b05 orr.w fp, fp, r5 + 1ffb6: e9cd ab04 strd sl, fp, [sp, #16] + 1ffba: e9dd 4512 ldrd r4, r5, [sp, #72] ; 0x48 + 1ffbe: e9dd ab0c ldrd sl, fp, [sp, #48] ; 0x30 + 1ffc2: ea4a 0a04 orr.w sl, sl, r4 + 1ffc6: ea4b 0b05 orr.w fp, fp, r5 + 1ffca: e9cd ab08 strd sl, fp, [sp, #32] + 1ffce: e9dd 4500 ldrd r4, r5, [sp] + 1ffd2: e9dd ab10 ldrd sl, fp, [sp, #64] ; 0x40 + 1ffd6: ea4a 0a04 orr.w sl, sl, r4 + 1ffda: ea4b 0b05 orr.w fp, fp, r5 + 1ffde: e9cd ab10 strd sl, fp, [sp, #64] ; 0x40 + 1ffe2: e9dd 4530 ldrd r4, r5, [sp, #192] ; 0xc0 + 1ffe6: f896 a003 ldrb.w sl, [r6, #3] + 1ffea: f04f 0b00 mov.w fp, #0 + 1ffee: e9cd ab26 strd sl, fp, [sp, #152] ; 0x98 + 1fff2: e9dd ab2a ldrd sl, fp, [sp, #168] ; 0xa8 + 1fff6: ea45 050b orr.w r5, r5, fp + 1fffa: ea4f 0b89 mov.w fp, r9, lsl #2 + 1fffe: ea4b 7c98 orr.w ip, fp, r8, lsr #30 + 20002: ea4f 0188 mov.w r1, r8, lsl #2 + 20006: ea44 040a orr.w r4, r4, sl + 2000a: f8cd c094 str.w ip, [sp, #148] ; 0x94 + 2000e: 9124 str r1, [sp, #144] ; 0x90 + 20010: e9cd 4528 strd r4, r5, [sp, #160] ; 0xa0 + 20014: e9dd 4524 ldrd r4, r5, [sp, #144] ; 0x90 + 20018: f114 7480 adds.w r4, r4, #16777216 ; 0x1000000 + 2001c: f145 0500 adc.w r5, r5, #0 + 20020: e9cd 4516 strd r4, r5, [sp, #88] ; 0x58 + 20024: 9d07 ldr r5, [sp, #28] + 20026: f8dd a018 ldr.w sl, [sp, #24] + 2002a: 01ad lsls r5, r5, #6 + 2002c: ea45 699a orr.w r9, r5, sl, lsr #26 + 20030: 9f33 ldr r7, [sp, #204] ; 0xcc + 20032: ea4f 148a mov.w r4, sl, lsl #6 + 20036: f8cd 908c str.w r9, [sp, #140] ; 0x8c + 2003a: f8dd c0c8 ldr.w ip, [sp, #200] ; 0xc8 + 2003e: ea4f 1843 mov.w r8, r3, lsl #5 + 20042: 9422 str r4, [sp, #136] ; 0x88 + 20044: 00ff lsls r7, r7, #3 + 20046: ea47 7b5c orr.w fp, r7, ip, lsr #29 + 2004a: ea48 61d2 orr.w r1, r8, r2, lsr #27 + 2004e: e9dd 8922 ldrd r8, r9, [sp, #136] ; 0x88 + 20052: f118 7880 adds.w r8, r8, #16777216 ; 0x1000000 + 20056: f8cd b06c str.w fp, [sp, #108] ; 0x6c + 2005a: f149 0900 adc.w r9, r9, #0 + 2005e: f04f 0a00 mov.w sl, #0 + 20062: f04f 0b00 mov.w fp, #0 + 20066: e9cd 8918 strd r8, r9, [sp, #96] ; 0x60 + 2006a: 46d0 mov r8, sl + 2006c: 46d9 mov r9, fp + 2006e: ea4f 05cc mov.w r5, ip, lsl #3 + 20072: 951a str r5, [sp, #104] ; 0x68 + 20074: 0157 lsls r7, r2, #5 + 20076: e9dd 451c ldrd r4, r5, [sp, #112] ; 0x70 + 2007a: e9dd 2302 ldrd r2, r3, [sp, #8] + 2007e: 4322 orrs r2, r4 + 20080: 432b orrs r3, r5 + 20082: e9cd ab06 strd sl, fp, [sp, #24] + 20086: e9dd ab04 ldrd sl, fp, [sp, #16] + 2008a: e9dd 4508 ldrd r4, r5, [sp, #32] + 2008e: e9cd 230e strd r2, r3, [sp, #56] ; 0x38 + 20092: e9dd 231e ldrd r2, r3, [sp, #120] ; 0x78 + 20096: ea4a 0a02 orr.w sl, sl, r2 + 2009a: ea4b 0b03 orr.w fp, fp, r3 + 2009e: e9cd 890a strd r8, r9, [sp, #40] ; 0x28 + 200a2: e9dd 232c ldrd r2, r3, [sp, #176] ; 0xb0 + 200a6: e9dd 8920 ldrd r8, r9, [sp, #128] ; 0x80 + 200aa: e9cd ab0c strd sl, fp, [sp, #48] ; 0x30 + 200ae: e9dd ab10 ldrd sl, fp, [sp, #64] ; 0x40 + 200b2: ea44 0408 orr.w r4, r4, r8 + 200b6: ea45 0509 orr.w r5, r5, r9 + 200ba: f04f 0800 mov.w r8, #0 + 200be: f04f 0900 mov.w r9, #0 + 200c2: ea4a 0a02 orr.w sl, sl, r2 + 200c6: ea4b 0b03 orr.w fp, fp, r3 + 200ca: e9cd ab10 strd sl, fp, [sp, #64] ; 0x40 + 200ce: e9dd 232e ldrd r2, r3, [sp, #184] ; 0xb8 + 200d2: 46c2 mov sl, r8 + 200d4: 46cb mov fp, r9 + 200d6: e9cd 4512 strd r4, r5, [sp, #72] ; 0x48 + 200da: e9dd 451a ldrd r4, r5, [sp, #104] ; 0x68 + 200de: f114 7480 adds.w r4, r4, #16777216 ; 0x1000000 + 200e2: f145 0500 adc.w r5, r5, #0 + 200e6: e9cd 451c strd r4, r5, [sp, #112] ; 0x70 + 200ea: 4644 mov r4, r8 + 200ec: 464d mov r5, r9 + 200ee: f8dd c098 ldr.w ip, [sp, #152] ; 0x98 + 200f2: f112 7280 adds.w r2, r2, #16777216 ; 0x1000000 + 200f6: 9115 str r1, [sp, #84] ; 0x54 + 200f8: 9714 str r7, [sp, #80] ; 0x50 + 200fa: e9cd ab2c strd sl, fp, [sp, #176] ; 0xb0 + 200fe: f143 0300 adc.w r3, r3, #0 + 20102: e9cd ab08 strd sl, fp, [sp, #32] + 20106: e9cd 8902 strd r8, r9, [sp, #8] + 2010a: e9dd 8914 ldrd r8, r9, [sp, #80] ; 0x50 + 2010e: ea4f 2b1c mov.w fp, ip, lsr #8 + 20112: f118 7880 adds.w r8, r8, #16777216 ; 0x1000000 + 20116: ea4f 6a0c mov.w sl, ip, lsl #24 + 2011a: f149 0900 adc.w r9, r9, #0 + 2011e: e9cd 231e strd r2, r3, [sp, #120] ; 0x78 + 20122: e9dd 2328 ldrd r2, r3, [sp, #160] ; 0xa0 + 20126: ea42 020a orr.w r2, r2, sl + 2012a: ea43 030b orr.w r3, r3, fp + 2012e: e9cd 4504 strd r4, r5, [sp, #16] + 20132: e9cd 8920 strd r8, r9, [sp, #128] ; 0x80 + 20136: e9cd 2326 strd r2, r3, [sp, #152] ; 0x98 + 2013a: 9b16 ldr r3, [sp, #88] ; 0x58 + 2013c: 9c17 ldr r4, [sp, #92] ; 0x5c + 2013e: 0e59 lsrs r1, r3, #25 + 20140: ea41 11c4 orr.w r1, r1, r4, lsl #7 + 20144: f04f 0c13 mov.w ip, #19 + 20148: 9d18 ldr r5, [sp, #96] ; 0x60 + 2014a: fba1 890c umull r8, r9, r1, ip + 2014e: f8dd a070 ldr.w sl, [sp, #112] ; 0x70 + 20152: f8dd b034 ldr.w fp, [sp, #52] ; 0x34 + 20156: 0e6d lsrs r5, r5, #25 + 20158: 9506 str r5, [sp, #24] + 2015a: 9f0f ldr r7, [sp, #60] ; 0x3c + 2015c: ea4f 6a5a mov.w sl, sl, lsr #25 + 20160: ea4f 0b8b mov.w fp, fp, lsl #2 + 20164: ea4f 6e64 mov.w lr, r4, asr #25 + 20168: f8cd a008 str.w sl, [sp, #8] + 2016c: f8cd b0b4 str.w fp, [sp, #180] ; 0xb4 + 20170: f8dd a018 ldr.w sl, [sp, #24] + 20174: f8dd b064 ldr.w fp, [sp, #100] ; 0x64 + 20178: fb0c 990e mla r9, ip, lr, r9 + 2017c: 017f lsls r7, r7, #5 + 2017e: f8dd c078 ldr.w ip, [sp, #120] ; 0x78 + 20182: 9b20 ldr r3, [sp, #128] ; 0x80 + 20184: 970b str r7, [sp, #44] ; 0x2c + 20186: ea4a 1acb orr.w sl, sl, fp, lsl #7 + 2018a: 9f11 ldr r7, [sp, #68] ; 0x44 + 2018c: f8dd b074 ldr.w fp, [sp, #116] ; 0x74 + 20190: ea4f 6c5c mov.w ip, ip, lsr #25 + 20194: 0e5b lsrs r3, r3, #25 + 20196: f8cd a018 str.w sl, [sp, #24] + 2019a: f8dd a008 ldr.w sl, [sp, #8] + 2019e: f8cd c010 str.w ip, [sp, #16] + 201a2: 9308 str r3, [sp, #32] + 201a4: f8dd c02c ldr.w ip, [sp, #44] ; 0x2c + 201a8: 013b lsls r3, r7, #4 + 201aa: 9f0e ldr r7, [sp, #56] ; 0x38 + 201ac: ea4a 1acb orr.w sl, sl, fp, lsl #7 + 201b0: ea4c 6cd7 orr.w ip, ip, r7, lsr #27 + 201b4: f8dd b07c ldr.w fp, [sp, #124] ; 0x7c + 201b8: f8cd a008 str.w sl, [sp, #8] + 201bc: f8dd a010 ldr.w sl, [sp, #16] + 201c0: 9f0c ldr r7, [sp, #48] ; 0x30 + 201c2: f8cd c02c str.w ip, [sp, #44] ; 0x2c + 201c6: f8dd c0b4 ldr.w ip, [sp, #180] ; 0xb4 + 201ca: ea4a 1acb orr.w sl, sl, fp, lsl #7 + 201ce: ea4c 7c97 orr.w ip, ip, r7, lsr #30 + 201d2: f8cd a010 str.w sl, [sp, #16] + 201d6: 9f08 ldr r7, [sp, #32] + 201d8: f8dd a084 ldr.w sl, [sp, #132] ; 0x84 + 201dc: 9a13 ldr r2, [sp, #76] ; 0x4c + 201de: ea47 17ca orr.w r7, r7, sl, lsl #7 + 201e2: f8cd c0b4 str.w ip, [sp, #180] ; 0xb4 + 201e6: f8dd c048 ldr.w ip, [sp, #72] ; 0x48 + 201ea: 9708 str r7, [sp, #32] + 201ec: f8dd b040 ldr.w fp, [sp, #64] ; 0x40 + 201f0: f8dd a074 ldr.w sl, [sp, #116] ; 0x74 + 201f4: ea43 731b orr.w r3, r3, fp, lsr #28 + 201f8: f8dd b030 ldr.w fp, [sp, #48] ; 0x30 + 201fc: ea4f 6a6a mov.w sl, sl, asr #25 + 20200: f8cd a00c str.w sl, [sp, #12] + 20204: 01d5 lsls r5, r2, #7 + 20206: ea4f 0b8b mov.w fp, fp, lsl #2 + 2020a: f8dd a084 ldr.w sl, [sp, #132] ; 0x84 + 2020e: f8cd b0b0 str.w fp, [sp, #176] ; 0xb0 + 20212: ea45 655c orr.w r5, r5, ip, lsr #25 + 20216: f8dd b040 ldr.w fp, [sp, #64] ; 0x40 + 2021a: f8dd c064 ldr.w ip, [sp, #100] ; 0x64 + 2021e: 9f0e ldr r7, [sp, #56] ; 0x38 + 20220: ea4f 6a6a mov.w sl, sl, asr #25 + 20224: f8cd a024 str.w sl, [sp, #36] ; 0x24 + 20228: ea4f 120b mov.w r2, fp, lsl #4 + 2022c: ea4f 6c6c mov.w ip, ip, asr #25 + 20230: e9dd ab26 ldrd sl, fp, [sp, #152] ; 0x98 + 20234: 017f lsls r7, r7, #5 + 20236: eb1a 0a08 adds.w sl, sl, r8 + 2023a: eb4b 0b09 adc.w fp, fp, r9 + 2023e: f8cd c01c str.w ip, [sp, #28] + 20242: 970a str r7, [sp, #40] ; 0x28 + 20244: f8dd c07c ldr.w ip, [sp, #124] ; 0x7c + 20248: e9cd ab2a strd sl, fp, [sp, #168] ; 0xa8 + 2024c: e9dd 890a ldrd r8, r9, [sp, #40] ; 0x28 + 20250: e9dd ab06 ldrd sl, fp, [sp, #24] + 20254: eb18 080a adds.w r8, r8, sl + 20258: eb49 090b adc.w r9, r9, fp + 2025c: 9f12 ldr r7, [sp, #72] ; 0x48 + 2025e: e9dd ab2c ldrd sl, fp, [sp, #176] ; 0xb0 + 20262: e9cd 8930 strd r8, r9, [sp, #192] ; 0xc0 + 20266: e9dd 8902 ldrd r8, r9, [sp, #8] + 2026a: ea4f 6c6c mov.w ip, ip, asr #25 + 2026e: eb18 080a adds.w r8, r8, sl + 20272: eb49 090b adc.w r9, r9, fp + 20276: f8cd c014 str.w ip, [sp, #20] + 2027a: 01fc lsls r4, r7, #7 + 2027c: e9cd 892c strd r8, r9, [sp, #176] ; 0xb0 + 20280: e9dd 8904 ldrd r8, r9, [sp, #16] + 20284: e9dd ab08 ldrd sl, fp, [sp, #32] + 20288: eb18 0804 adds.w r8, r8, r4 + 2028c: eb49 0905 adc.w r9, r9, r5 + 20290: eb1a 0a02 adds.w sl, sl, r2 + 20294: eb4b 0b03 adc.w fp, fp, r3 + 20298: 2200 movs r2, #0 + 2029a: 2300 movs r3, #0 + 2029c: e9cd 230c strd r2, r3, [sp, #48] ; 0x30 + 202a0: e9dd 232a ldrd r2, r3, [sp, #168] ; 0xa8 + 202a4: e9dd 4530 ldrd r4, r5, [sp, #192] ; 0xc0 + 202a8: f112 7200 adds.w r2, r2, #33554432 ; 0x2000000 + 202ac: f143 0300 adc.w r3, r3, #0 + 202b0: f114 7400 adds.w r4, r4, #33554432 ; 0x2000000 + 202b4: f145 0500 adc.w r5, r5, #0 + 202b8: e9cd ab34 strd sl, fp, [sp, #208] ; 0xd0 + 202bc: e9dd ab2c ldrd sl, fp, [sp, #176] ; 0xb0 + 202c0: f11a 7a00 adds.w sl, sl, #33554432 ; 0x2000000 + 202c4: f14b 0b00 adc.w fp, fp, #0 + 202c8: e9cd 451e strd r4, r5, [sp, #120] ; 0x78 + 202cc: e9cd 8932 strd r8, r9, [sp, #200] ; 0xc8 + 202d0: e9cd 231c strd r2, r3, [sp, #112] ; 0x70 + 202d4: e9cd ab20 strd sl, fp, [sp, #128] ; 0x80 + 202d8: e9dd 2332 ldrd r2, r3, [sp, #200] ; 0xc8 + 202dc: e9dd 8934 ldrd r8, r9, [sp, #208] ; 0xd0 + 202e0: f112 7200 adds.w r2, r2, #33554432 ; 0x2000000 + 202e4: f143 0300 adc.w r3, r3, #0 + 202e8: f118 7800 adds.w r8, r8, #33554432 ; 0x2000000 + 202ec: f149 0900 adc.w r9, r9, #0 + 202f0: f8dd c00c ldr.w ip, [sp, #12] + 202f4: e9cd 8928 strd r8, r9, [sp, #160] ; 0xa0 + 202f8: f8dd 8008 ldr.w r8, [sp, #8] + 202fc: e9cd 2326 strd r2, r3, [sp, #152] ; 0x98 + 20300: ea4f 6c4c mov.w ip, ip, lsl #25 + 20304: 9a05 ldr r2, [sp, #20] + 20306: 9b09 ldr r3, [sp, #36] ; 0x24 + 20308: ea4c 17d8 orr.w r7, ip, r8, lsr #7 + 2030c: f8dd c010 ldr.w ip, [sp, #16] + 20310: 0652 lsls r2, r2, #25 + 20312: 065b lsls r3, r3, #25 + 20314: ea42 19dc orr.w r9, r2, ip, lsr #7 + 20318: 461a mov r2, r3 + 2031a: f8dd b01c ldr.w fp, [sp, #28] + 2031e: 9d06 ldr r5, [sp, #24] + 20320: ea4f 6b4b mov.w fp, fp, lsl #25 + 20324: f8cd b034 str.w fp, [sp, #52] ; 0x34 + 20328: 9c0d ldr r4, [sp, #52] ; 0x34 + 2032a: 9b08 ldr r3, [sp, #32] + 2032c: ea44 14d5 orr.w r4, r4, r5, lsr #7 + 20330: f8cd 9044 str.w r9, [sp, #68] ; 0x44 + 20334: f8dd 9020 ldr.w r9, [sp, #32] + 20338: 940d str r4, [sp, #52] ; 0x34 + 2033a: ea42 12d3 orr.w r2, r2, r3, lsr #7 + 2033e: 066c lsls r4, r5, #25 + 20340: 9b02 ldr r3, [sp, #8] + 20342: 940c str r4, [sp, #48] ; 0x30 + 20344: ea4f 654c mov.w r5, ip, lsl #25 + 20348: ea4f 6949 mov.w r9, r9, lsl #25 + 2034c: ea4f 6b4e mov.w fp, lr, lsl #25 + 20350: ea4f 6a41 mov.w sl, r1, lsl #25 + 20354: 9510 str r5, [sp, #64] ; 0x40 + 20356: 065b lsls r3, r3, #25 + 20358: e9dd 4522 ldrd r4, r5, [sp, #136] ; 0x88 + 2035c: f8cd 9058 str.w r9, [sp, #88] ; 0x58 + 20360: e9dd 890c ldrd r8, r9, [sp, #48] ; 0x30 + 20364: ebb4 0408 subs.w r4, r4, r8 + 20368: eb65 0509 sbc.w r5, r5, r9 + 2036c: ea4b 1bd1 orr.w fp, fp, r1, lsr #7 + 20370: 9713 str r7, [sp, #76] ; 0x4c + 20372: 9312 str r3, [sp, #72] ; 0x48 + 20374: 9217 str r2, [sp, #92] ; 0x5c + 20376: e9dd 2324 ldrd r2, r3, [sp, #144] ; 0x90 + 2037a: ebb2 020a subs.w r2, r2, sl + 2037e: eb63 030b sbc.w r3, r3, fp + 20382: e9dd 8912 ldrd r8, r9, [sp, #72] ; 0x48 + 20386: e9cd 450c strd r4, r5, [sp, #48] ; 0x30 + 2038a: e9dd 451a ldrd r4, r5, [sp, #104] ; 0x68 + 2038e: e9dd ab2e ldrd sl, fp, [sp, #184] ; 0xb8 + 20392: ebb4 0408 subs.w r4, r4, r8 + 20396: eb65 0509 sbc.w r5, r5, r9 + 2039a: e9cd 2322 strd r2, r3, [sp, #136] ; 0x88 + 2039e: e9dd 2310 ldrd r2, r3, [sp, #64] ; 0x40 + 203a2: ebba 0a02 subs.w sl, sl, r2 + 203a6: eb6b 0b03 sbc.w fp, fp, r3 + 203aa: e9cd 451a strd r4, r5, [sp, #104] ; 0x68 + 203ae: e9cd ab24 strd sl, fp, [sp, #144] ; 0x90 + 203b2: e9dd 8916 ldrd r8, r9, [sp, #88] ; 0x58 + 203b6: e9dd 4514 ldrd r4, r5, [sp, #80] ; 0x50 + 203ba: 9926 ldr r1, [sp, #152] ; 0x98 + 203bc: f8dd c080 ldr.w ip, [sp, #128] ; 0x80 + 203c0: 0e89 lsrs r1, r1, #26 + 203c2: ea4f 629c mov.w r2, ip, lsr #26 + 203c6: 468c mov ip, r1 + 203c8: f8dd a070 ldr.w sl, [sp, #112] ; 0x70 + 203cc: ebb4 0408 subs.w r4, r4, r8 + 203d0: f8dd b078 ldr.w fp, [sp, #120] ; 0x78 + 203d4: eb65 0509 sbc.w r5, r5, r9 + 203d8: ea4f 689a mov.w r8, sl, lsr #26 + 203dc: f8dd a07c ldr.w sl, [sp, #124] ; 0x7c + 203e0: e9cd 4514 strd r4, r5, [sp, #80] ; 0x50 + 203e4: ea4f 6b9b mov.w fp, fp, lsr #26 + 203e8: 9d1d ldr r5, [sp, #116] ; 0x74 + 203ea: ea4b 178a orr.w r7, fp, sl, lsl #6 + 203ee: 9c28 ldr r4, [sp, #160] ; 0xa0 + 203f0: ea48 1885 orr.w r8, r8, r5, lsl #6 + 203f4: 9927 ldr r1, [sp, #156] ; 0x9c + 203f6: 9d29 ldr r5, [sp, #164] ; 0xa4 + 203f8: 970a str r7, [sp, #40] ; 0x28 + 203fa: 9f1d ldr r7, [sp, #116] ; 0x74 + 203fc: 0ea4 lsrs r4, r4, #26 + 203fe: f8dd b084 ldr.w fp, [sp, #132] ; 0x84 + 20402: ea4f 69a7 mov.w r9, r7, asr #26 + 20406: ea4c 1c81 orr.w ip, ip, r1, lsl #6 + 2040a: ea44 1485 orr.w r4, r4, r5, lsl #6 + 2040e: f8cd c038 str.w ip, [sp, #56] ; 0x38 + 20412: 9436 str r4, [sp, #216] ; 0xd8 + 20414: ea4f 6ca1 mov.w ip, r1, asr #26 + 20418: ea4f 6aaa mov.w sl, sl, asr #26 + 2041c: ea4f 6489 mov.w r4, r9, lsl #26 + 20420: ea4f 63ab mov.w r3, fp, asr #26 + 20424: 16a9 asrs r1, r5, #26 + 20426: f8cd a02c str.w sl, [sp, #44] ; 0x2c + 2042a: ea4f 658a mov.w r5, sl, lsl #26 + 2042e: f8cd c03c str.w ip, [sp, #60] ; 0x3c + 20432: ea4f 6a8c mov.w sl, ip, lsl #26 + 20436: ea44 1c98 orr.w ip, r4, r8, lsr #6 + 2043a: 9c0a ldr r4, [sp, #40] ; 0x28 + 2043c: ea42 128b orr.w r2, r2, fp, lsl #6 + 20440: 069f lsls r7, r3, #26 + 20442: 9137 str r1, [sp, #220] ; 0xdc + 20444: ea4f 6b81 mov.w fp, r1, lsl #26 + 20448: ea45 1194 orr.w r1, r5, r4, lsr #6 + 2044c: ea47 1592 orr.w r5, r7, r2, lsr #6 + 20450: 4657 mov r7, sl + 20452: f8dd a038 ldr.w sl, [sp, #56] ; 0x38 + 20456: f8cd c01c str.w ip, [sp, #28] + 2045a: ea47 179a orr.w r7, r7, sl, lsr #6 + 2045e: 4682 mov sl, r0 + 20460: f8dd c0d8 ldr.w ip, [sp, #216] ; 0xd8 + 20464: 9503 str r5, [sp, #12] + 20466: 9d0e ldr r5, [sp, #56] ; 0x38 + 20468: ea4b 1b9c orr.w fp, fp, ip, lsr #6 + 2046c: ea4f 6088 mov.w r0, r8, lsl #26 + 20470: 9119 str r1, [sp, #100] ; 0x64 + 20472: 9705 str r7, [sp, #20] + 20474: 06a1 lsls r1, r4, #26 + 20476: ea4f 678c mov.w r7, ip, lsl #26 + 2047a: 0694 lsls r4, r2, #26 + 2047c: 06ad lsls r5, r5, #26 + 2047e: 9006 str r0, [sp, #24] + 20480: 9118 str r1, [sp, #96] ; 0x60 + 20482: 9402 str r4, [sp, #8] + 20484: 9504 str r5, [sp, #16] + 20486: f8cd b024 str.w fp, [sp, #36] ; 0x24 + 2048a: 9708 str r7, [sp, #32] + 2048c: e9dd 0106 ldrd r0, r1, [sp, #24] + 20490: e9dd 452a ldrd r4, r5, [sp, #168] ; 0xa8 + 20494: 1a24 subs r4, r4, r0 + 20496: eb65 0501 sbc.w r5, r5, r1 + 2049a: e9cd 4510 strd r4, r5, [sp, #64] ; 0x40 + 2049e: e9dd 450c ldrd r4, r5, [sp, #48] ; 0x30 + 204a2: eb14 0408 adds.w r4, r4, r8 + 204a6: eb45 0509 adc.w r5, r5, r9 + 204aa: e9cd 4506 strd r4, r5, [sp, #24] + 204ae: e9dd 8930 ldrd r8, r9, [sp, #192] ; 0xc0 + 204b2: e9dd 4518 ldrd r4, r5, [sp, #96] ; 0x60 + 204b6: ebb8 0804 subs.w r8, r8, r4 + 204ba: eb69 0905 sbc.w r9, r9, r5 + 204be: e9cd 890c strd r8, r9, [sp, #48] ; 0x30 + 204c2: e9dd 450a ldrd r4, r5, [sp, #40] ; 0x28 + 204c6: e9dd 891a ldrd r8, r9, [sp, #104] ; 0x68 + 204ca: eb18 0804 adds.w r8, r8, r4 + 204ce: eb49 0905 adc.w r9, r9, r5 + 204d2: e9cd 890a strd r8, r9, [sp, #40] ; 0x28 + 204d6: e9dd 4502 ldrd r4, r5, [sp, #8] + 204da: e9dd 892c ldrd r8, r9, [sp, #176] ; 0xb0 + 204de: ebb8 0804 subs.w r8, r8, r4 + 204e2: eb69 0905 sbc.w r9, r9, r5 + 204e6: e9cd 8902 strd r8, r9, [sp, #8] + 204ea: e9dd 8924 ldrd r8, r9, [sp, #144] ; 0x90 + 204ee: e9dd 4504 ldrd r4, r5, [sp, #16] + 204f2: eb18 0802 adds.w r8, r8, r2 + 204f6: eb49 0903 adc.w r9, r9, r3 + 204fa: e9dd 2332 ldrd r2, r3, [sp, #200] ; 0xc8 + 204fe: 1b12 subs r2, r2, r4 + 20500: eb63 0305 sbc.w r3, r3, r5 + 20504: e9cd 891a strd r8, r9, [sp, #104] ; 0x68 + 20508: e9dd 4522 ldrd r4, r5, [sp, #136] ; 0x88 + 2050c: e9dd 8914 ldrd r8, r9, [sp, #80] ; 0x50 + 20510: e9cd 2312 strd r2, r3, [sp, #72] ; 0x48 + 20514: e9dd 230e ldrd r2, r3, [sp, #56] ; 0x38 + 20518: eb18 0802 adds.w r8, r8, r2 + 2051c: e9dd 2336 ldrd r2, r3, [sp, #216] ; 0xd8 + 20520: 18a4 adds r4, r4, r2 + 20522: 415d adcs r5, r3 + 20524: e9dd 2308 ldrd r2, r3, [sp, #32] + 20528: 9b10 ldr r3, [sp, #64] ; 0x40 + 2052a: 9806 ldr r0, [sp, #24] + 2052c: f8ca 3028 str.w r3, [sl, #40] ; 0x28 + 20530: 9b0c ldr r3, [sp, #48] ; 0x30 + 20532: e9cd 4504 strd r4, r5, [sp, #16] + 20536: e9dd 4534 ldrd r4, r5, [sp, #208] ; 0xd0 + 2053a: f8ca 3030 str.w r3, [sl, #48] ; 0x30 + 2053e: 9b0a ldr r3, [sp, #40] ; 0x28 + 20540: f8ca 002c str.w r0, [sl, #44] ; 0x2c + 20544: f8ca 3034 str.w r3, [sl, #52] ; 0x34 + 20548: 9b02 ldr r3, [sp, #8] + 2054a: 1aa4 subs r4, r4, r2 + 2054c: f8ca 3038 str.w r3, [sl, #56] ; 0x38 + 20550: 9b1a ldr r3, [sp, #104] ; 0x68 + 20552: 2200 movs r2, #0 + 20554: f8ca 303c str.w r3, [sl, #60] ; 0x3c + 20558: 9b12 ldr r3, [sp, #72] ; 0x48 + 2055a: 2701 movs r7, #1 + 2055c: f8ca 3040 str.w r3, [sl, #64] ; 0x40 + 20560: 9b04 ldr r3, [sp, #16] + 20562: f10a 0528 add.w r5, sl, #40 ; 0x28 + 20566: f8ca 304c str.w r3, [sl, #76] ; 0x4c + 2056a: 4629 mov r1, r5 + 2056c: a83c add r0, sp, #240 ; 0xf0 + 2056e: f8ca 4048 str.w r4, [sl, #72] ; 0x48 + 20572: f8ca 2054 str.w r2, [sl, #84] ; 0x54 + 20576: f8ca 2058 str.w r2, [sl, #88] ; 0x58 + 2057a: f8ca 205c str.w r2, [sl, #92] ; 0x5c + 2057e: f8ca 2060 str.w r2, [sl, #96] ; 0x60 + 20582: f8ca 2064 str.w r2, [sl, #100] ; 0x64 + 20586: f8ca 2068 str.w r2, [sl, #104] ; 0x68 + 2058a: f8ca 206c str.w r2, [sl, #108] ; 0x6c + 2058e: f8ca 2070 str.w r2, [sl, #112] ; 0x70 + 20592: f8ca 2074 str.w r2, [sl, #116] ; 0x74 + 20596: f8ca 8044 str.w r8, [sl, #68] ; 0x44 + 2059a: f8ca 7050 str.w r7, [sl, #80] ; 0x50 + 2059e: f7fd feb7 bl 1e310 + 205a2: a93c add r1, sp, #240 ; 0xf0 + 205a4: a846 add r0, sp, #280 ; 0x118 + 205a6: 4a89 ldr r2, [pc, #548] ; (207cc ) + 205a8: f7fd fa56 bl 1da58 + 205ac: f10a 0450 add.w r4, sl, #80 ; 0x50 + 205b0: a83c add r0, sp, #240 ; 0xf0 + 205b2: 4622 mov r2, r4 + 205b4: 4601 mov r1, r0 + 205b6: f7fe fa7b bl 1eab0 + 205ba: a846 add r0, sp, #280 ; 0x118 + 205bc: 4622 mov r2, r4 + 205be: 4601 mov r1, r0 + 205c0: f7fd f9aa bl 1d918 + 205c4: a946 add r1, sp, #280 ; 0x118 + 205c6: a850 add r0, sp, #320 ; 0x140 + 205c8: f7fd fea2 bl 1e310 + 205cc: a850 add r0, sp, #320 ; 0x140 + 205ce: 4601 mov r1, r0 + 205d0: aa46 add r2, sp, #280 ; 0x118 + 205d2: f7fd fa41 bl 1da58 + 205d6: 4650 mov r0, sl + 205d8: a950 add r1, sp, #320 ; 0x140 + 205da: f7fd fe99 bl 1e310 + 205de: 4650 mov r0, sl + 205e0: 4651 mov r1, sl + 205e2: aa46 add r2, sp, #280 ; 0x118 + 205e4: f7fd fa38 bl 1da58 + 205e8: aa3c add r2, sp, #240 ; 0xf0 + 205ea: 4650 mov r0, sl + 205ec: 4651 mov r1, sl + 205ee: f7fd fa33 bl 1da58 + 205f2: 4651 mov r1, sl + 205f4: a85a add r0, sp, #360 ; 0x168 + 205f6: f7fd fe8b bl 1e310 + 205fa: a95a add r1, sp, #360 ; 0x168 + 205fc: a864 add r0, sp, #400 ; 0x190 + 205fe: f7fd fe87 bl 1e310 + 20602: a864 add r0, sp, #400 ; 0x190 + 20604: 4601 mov r1, r0 + 20606: f7fd fe83 bl 1e310 + 2060a: a864 add r0, sp, #400 ; 0x190 + 2060c: 4602 mov r2, r0 + 2060e: 4651 mov r1, sl + 20610: f7fd fa22 bl 1da58 + 20614: a85a add r0, sp, #360 ; 0x168 + 20616: 4601 mov r1, r0 + 20618: aa64 add r2, sp, #400 ; 0x190 + 2061a: f7fd fa1d bl 1da58 + 2061e: a85a add r0, sp, #360 ; 0x168 + 20620: 4601 mov r1, r0 + 20622: f7fd fe75 bl 1e310 + 20626: a85a add r0, sp, #360 ; 0x168 + 20628: 4602 mov r2, r0 + 2062a: a964 add r1, sp, #400 ; 0x190 + 2062c: f7fd fa14 bl 1da58 + 20630: a864 add r0, sp, #400 ; 0x190 + 20632: a95a add r1, sp, #360 ; 0x168 + 20634: f7fd fe6c bl 1e310 + 20638: 2404 movs r4, #4 + 2063a: a864 add r0, sp, #400 ; 0x190 + 2063c: 4601 mov r1, r0 + 2063e: f7fd fe67 bl 1e310 + 20642: 3c01 subs r4, #1 + 20644: d1f9 bne.n 2063a + 20646: a85a add r0, sp, #360 ; 0x168 + 20648: 4602 mov r2, r0 + 2064a: a964 add r1, sp, #400 ; 0x190 + 2064c: f7fd fa04 bl 1da58 + 20650: a864 add r0, sp, #400 ; 0x190 + 20652: a95a add r1, sp, #360 ; 0x168 + 20654: f7fd fe5c bl 1e310 + 20658: 2409 movs r4, #9 + 2065a: a864 add r0, sp, #400 ; 0x190 + 2065c: 4601 mov r1, r0 + 2065e: f7fd fe57 bl 1e310 + 20662: 3c01 subs r4, #1 + 20664: d1f9 bne.n 2065a + 20666: a864 add r0, sp, #400 ; 0x190 + 20668: 4601 mov r1, r0 + 2066a: aa5a add r2, sp, #360 ; 0x168 + 2066c: f7fd f9f4 bl 1da58 + 20670: a86e add r0, sp, #440 ; 0x1b8 + 20672: a964 add r1, sp, #400 ; 0x190 + 20674: f7fd fe4c bl 1e310 + 20678: 2413 movs r4, #19 + 2067a: a86e add r0, sp, #440 ; 0x1b8 + 2067c: 4601 mov r1, r0 + 2067e: f7fd fe47 bl 1e310 + 20682: 3c01 subs r4, #1 + 20684: d1f9 bne.n 2067a + 20686: a864 add r0, sp, #400 ; 0x190 + 20688: 4602 mov r2, r0 + 2068a: a96e add r1, sp, #440 ; 0x1b8 + 2068c: f7fd f9e4 bl 1da58 + 20690: a864 add r0, sp, #400 ; 0x190 + 20692: 4601 mov r1, r0 + 20694: f7fd fe3c bl 1e310 + 20698: 2409 movs r4, #9 + 2069a: a864 add r0, sp, #400 ; 0x190 + 2069c: 4601 mov r1, r0 + 2069e: f7fd fe37 bl 1e310 + 206a2: 3c01 subs r4, #1 + 206a4: d1f9 bne.n 2069a + 206a6: a85a add r0, sp, #360 ; 0x168 + 206a8: 4602 mov r2, r0 + 206aa: a964 add r1, sp, #400 ; 0x190 + 206ac: f7fd f9d4 bl 1da58 + 206b0: a864 add r0, sp, #400 ; 0x190 + 206b2: a95a add r1, sp, #360 ; 0x168 + 206b4: f7fd fe2c bl 1e310 + 206b8: 2431 movs r4, #49 ; 0x31 + 206ba: a864 add r0, sp, #400 ; 0x190 + 206bc: 4601 mov r1, r0 + 206be: f7fd fe27 bl 1e310 + 206c2: 3c01 subs r4, #1 + 206c4: d1f9 bne.n 206ba + 206c6: a864 add r0, sp, #400 ; 0x190 + 206c8: 4601 mov r1, r0 + 206ca: aa5a add r2, sp, #360 ; 0x168 + 206cc: f7fd f9c4 bl 1da58 + 206d0: a86e add r0, sp, #440 ; 0x1b8 + 206d2: a964 add r1, sp, #400 ; 0x190 + 206d4: f7fd fe1c bl 1e310 + 206d8: 2463 movs r4, #99 ; 0x63 + 206da: a86e add r0, sp, #440 ; 0x1b8 + 206dc: 4601 mov r1, r0 + 206de: f7fd fe17 bl 1e310 + 206e2: 3c01 subs r4, #1 + 206e4: d1f9 bne.n 206da + 206e6: a864 add r0, sp, #400 ; 0x190 + 206e8: 4602 mov r2, r0 + 206ea: a96e add r1, sp, #440 ; 0x1b8 + 206ec: f7fd f9b4 bl 1da58 + 206f0: a864 add r0, sp, #400 ; 0x190 + 206f2: 4601 mov r1, r0 + 206f4: f7fd fe0c bl 1e310 + 206f8: 2431 movs r4, #49 ; 0x31 + 206fa: a864 add r0, sp, #400 ; 0x190 + 206fc: 4601 mov r1, r0 + 206fe: f7fd fe07 bl 1e310 + 20702: 3c01 subs r4, #1 + 20704: d1f9 bne.n 206fa + 20706: a85a add r0, sp, #360 ; 0x168 + 20708: 4602 mov r2, r0 + 2070a: a964 add r1, sp, #400 ; 0x190 + 2070c: f7fd f9a4 bl 1da58 + 20710: a85a add r0, sp, #360 ; 0x168 + 20712: 4601 mov r1, r0 + 20714: f7fd fdfc bl 1e310 + 20718: a85a add r0, sp, #360 ; 0x168 + 2071a: 4601 mov r1, r0 + 2071c: f7fd fdf8 bl 1e310 + 20720: 4650 mov r0, sl + 20722: a95a add r1, sp, #360 ; 0x168 + 20724: 4652 mov r2, sl + 20726: f7fd f997 bl 1da58 + 2072a: 4650 mov r0, sl + 2072c: 4651 mov r1, sl + 2072e: aa50 add r2, sp, #320 ; 0x140 + 20730: f7fd f992 bl 1da58 + 20734: aa3c add r2, sp, #240 ; 0xf0 + 20736: 4650 mov r0, sl + 20738: 4651 mov r1, sl + 2073a: f7fd f98d bl 1da58 + 2073e: a864 add r0, sp, #400 ; 0x190 + 20740: 4651 mov r1, sl + 20742: f7fd fde5 bl 1e310 + 20746: a864 add r0, sp, #400 ; 0x190 + 20748: 4601 mov r1, r0 + 2074a: aa46 add r2, sp, #280 ; 0x118 + 2074c: f7fd f984 bl 1da58 + 20750: a86e add r0, sp, #440 ; 0x1b8 + 20752: a964 add r1, sp, #400 ; 0x190 + 20754: aa3c add r2, sp, #240 ; 0xf0 + 20756: f7fe f9ab bl 1eab0 + 2075a: a85a add r0, sp, #360 ; 0x168 + 2075c: a96e add r1, sp, #440 ; 0x1b8 + 2075e: f7fe f9e5 bl 1eb2c + 20762: a85a add r0, sp, #360 ; 0x168 + 20764: f7ff f83e bl 1f7e4 + 20768: b188 cbz r0, 2078e + 2076a: a964 add r1, sp, #400 ; 0x190 + 2076c: aa3c add r2, sp, #240 ; 0xf0 + 2076e: a86e add r0, sp, #440 ; 0x1b8 + 20770: f7fd f8d2 bl 1d918 + 20774: a85a add r0, sp, #360 ; 0x168 + 20776: a96e add r1, sp, #440 ; 0x1b8 + 20778: f7fe f9d8 bl 1eb2c + 2077c: a85a add r0, sp, #360 ; 0x168 + 2077e: f7ff f831 bl 1f7e4 + 20782: b9d0 cbnz r0, 207ba + 20784: 4650 mov r0, sl + 20786: 4651 mov r1, sl + 20788: 4a11 ldr r2, [pc, #68] ; (207d0 ) + 2078a: f7fd f965 bl 1da58 + 2078e: a85a add r0, sp, #360 ; 0x168 + 20790: 4651 mov r1, sl + 20792: f7fe f9cb bl 1eb2c + 20796: f89d 3168 ldrb.w r3, [sp, #360] ; 0x168 + 2079a: 7ff2 ldrb r2, [r6, #31] + 2079c: f003 0301 and.w r3, r3, #1 + 207a0: ebb3 1fd2 cmp.w r3, r2, lsr #7 + 207a4: d00c beq.n 207c0 + 207a6: f10a 0078 add.w r0, sl, #120 ; 0x78 + 207aa: 462a mov r2, r5 + 207ac: 4651 mov r1, sl + 207ae: f7fd f953 bl 1da58 + 207b2: 2000 movs r0, #0 + 207b4: b079 add sp, #484 ; 0x1e4 + 207b6: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 207ba: f04f 30ff mov.w r0, #4294967295 + 207be: e7f9 b.n 207b4 + 207c0: 4650 mov r0, sl + 207c2: 4651 mov r1, sl + 207c4: f7fd fd7a bl 1e2bc + 207c8: e7ed b.n 207a6 + 207ca: bf00 nop + 207cc: 0003e2a0 .word 0x0003e2a0 + 207d0: 0003e2c8 .word 0x0003e2c8 + +000207d4 : + 207d4: b530 push {r4, r5, lr} + 207d6: 460d mov r5, r1 + 207d8: 4604 mov r4, r0 + 207da: b0a7 sub sp, #156 ; 0x9c + 207dc: a808 add r0, sp, #32 + 207de: 3150 adds r1, #80 ; 0x50 + 207e0: f7fe f8c2 bl 1e968 + 207e4: 4629 mov r1, r5 + 207e6: aa08 add r2, sp, #32 + 207e8: a812 add r0, sp, #72 ; 0x48 + 207ea: f7fd f935 bl 1da58 + 207ee: aa08 add r2, sp, #32 + 207f0: f105 0128 add.w r1, r5, #40 ; 0x28 + 207f4: a81c add r0, sp, #112 ; 0x70 + 207f6: f7fd f92f bl 1da58 + 207fa: 4620 mov r0, r4 + 207fc: a91c add r1, sp, #112 ; 0x70 + 207fe: f7fe f995 bl 1eb2c + 20802: a912 add r1, sp, #72 ; 0x48 + 20804: 4668 mov r0, sp + 20806: 7fe5 ldrb r5, [r4, #31] + 20808: f7fe f990 bl 1eb2c + 2080c: f89d 3000 ldrb.w r3, [sp] + 20810: f003 0301 and.w r3, r3, #1 + 20814: ea85 15c3 eor.w r5, r5, r3, lsl #7 + 20818: 77e5 strb r5, [r4, #31] + 2081a: b027 add sp, #156 ; 0x9c + 2081c: bd30 pop {r4, r5, pc} + 2081e: bf00 nop + +00020820 : + 20820: b5f0 push {r4, r5, r6, r7, lr} + 20822: b0f5 sub sp, #468 ; 0x1d4 + 20824: 4604 mov r4, r0 + 20826: 466b mov r3, sp + 20828: 3901 subs r1, #1 + 2082a: ad10 add r5, sp, #64 ; 0x40 + 2082c: f811 2f01 ldrb.w r2, [r1, #1]! + 20830: 3302 adds r3, #2 + 20832: f002 000f and.w r0, r2, #15 + 20836: 0912 lsrs r2, r2, #4 + 20838: f803 0c02 strb.w r0, [r3, #-2] + 2083c: f803 2c01 strb.w r2, [r3, #-1] + 20840: 42ab cmp r3, r5 + 20842: d1f3 bne.n 2082c + 20844: ab00 add r3, sp, #0 + 20846: 461e mov r6, r3 + 20848: 2200 movs r2, #0 + 2084a: 363f adds r6, #63 ; 0x3f + 2084c: 7819 ldrb r1, [r3, #0] + 2084e: 440a add r2, r1 + 20850: b2d1 uxtb r1, r2 + 20852: f101 0208 add.w r2, r1, #8 + 20856: f342 1203 sbfx r2, r2, #4, #4 + 2085a: b2d2 uxtb r2, r2 + 2085c: b2d0 uxtb r0, r2 + 2085e: eba1 1100 sub.w r1, r1, r0, lsl #4 + 20862: f803 1b01 strb.w r1, [r3], #1 + 20866: 42b3 cmp r3, r6 + 20868: d1f0 bne.n 2084c + 2086a: 2201 movs r2, #1 + 2086c: 4616 mov r6, r2 + 2086e: f89d 103f ldrb.w r1, [sp, #63] ; 0x3f + 20872: 2300 movs r3, #0 + 20874: 4408 add r0, r1 + 20876: f88d 003f strb.w r0, [sp, #63] ; 0x3f + 2087a: 62a2 str r2, [r4, #40] ; 0x28 + 2087c: 6522 str r2, [r4, #80] ; 0x50 + 2087e: 6023 str r3, [r4, #0] + 20880: 6063 str r3, [r4, #4] + 20882: 60a3 str r3, [r4, #8] + 20884: 60e3 str r3, [r4, #12] + 20886: 6123 str r3, [r4, #16] + 20888: 6163 str r3, [r4, #20] + 2088a: 61a3 str r3, [r4, #24] + 2088c: 61e3 str r3, [r4, #28] + 2088e: 6223 str r3, [r4, #32] + 20890: 6263 str r3, [r4, #36] ; 0x24 + 20892: 62e3 str r3, [r4, #44] ; 0x2c + 20894: 6323 str r3, [r4, #48] ; 0x30 + 20896: 6363 str r3, [r4, #52] ; 0x34 + 20898: 63a3 str r3, [r4, #56] ; 0x38 + 2089a: 63e3 str r3, [r4, #60] ; 0x3c + 2089c: 6423 str r3, [r4, #64] ; 0x40 + 2089e: 6463 str r3, [r4, #68] ; 0x44 + 208a0: 64a3 str r3, [r4, #72] ; 0x48 + 208a2: 64e3 str r3, [r4, #76] ; 0x4c + 208a4: 6563 str r3, [r4, #84] ; 0x54 + 208a6: 65a3 str r3, [r4, #88] ; 0x58 + 208a8: 65e3 str r3, [r4, #92] ; 0x5c + 208aa: 6623 str r3, [r4, #96] ; 0x60 + 208ac: 6663 str r3, [r4, #100] ; 0x64 + 208ae: 66a3 str r3, [r4, #104] ; 0x68 + 208b0: 66e3 str r3, [r4, #108] ; 0x6c + 208b2: 6723 str r3, [r4, #112] ; 0x70 + 208b4: 6763 str r3, [r4, #116] ; 0x74 + 208b6: 67a3 str r3, [r4, #120] ; 0x78 + 208b8: 67e3 str r3, [r4, #124] ; 0x7c + 208ba: f8c4 3080 str.w r3, [r4, #128] ; 0x80 + 208be: f8c4 3084 str.w r3, [r4, #132] ; 0x84 + 208c2: f8c4 3088 str.w r3, [r4, #136] ; 0x88 + 208c6: f8c4 308c str.w r3, [r4, #140] ; 0x8c + 208ca: f8c4 3090 str.w r3, [r4, #144] ; 0x90 + 208ce: f8c4 3094 str.w r3, [r4, #148] ; 0x94 + 208d2: f8c4 3098 str.w r3, [r4, #152] ; 0x98 + 208d6: f8c4 309c str.w r3, [r4, #156] ; 0x9c + 208da: 1071 asrs r1, r6, #1 + 208dc: f91d 2006 ldrsb.w r2, [sp, r6] + 208e0: 4628 mov r0, r5 + 208e2: f7fe feb5 bl 1f650 + 208e6: a84c add r0, sp, #304 ; 0x130 + 208e8: 4621 mov r1, r4 + 208ea: 462a mov r2, r5 + 208ec: f7fe faa6 bl 1ee3c + 208f0: 3602 adds r6, #2 + 208f2: 4620 mov r0, r4 + 208f4: a94c add r1, sp, #304 ; 0x130 + 208f6: f7fe fb01 bl 1eefc + 208fa: 2e41 cmp r6, #65 ; 0x41 + 208fc: d1ed bne.n 208da + 208fe: 6963 ldr r3, [r4, #20] + 20900: f104 0008 add.w r0, r4, #8 + 20904: 9333 str r3, [sp, #204] ; 0xcc + 20906: 69a3 ldr r3, [r4, #24] + 20908: c807 ldmia r0, {r0, r1, r2} + 2090a: e894 00c0 ldmia.w r4, {r6, r7} + 2090e: 9030 str r0, [sp, #192] ; 0xc0 + 20910: 972f str r7, [sp, #188] ; 0xbc + 20912: 6ae0 ldr r0, [r4, #44] ; 0x2c + 20914: 6a67 ldr r7, [r4, #36] ; 0x24 + 20916: 9334 str r3, [sp, #208] ; 0xd0 + 20918: 69e3 ldr r3, [r4, #28] + 2091a: 962e str r6, [sp, #184] ; 0xb8 + 2091c: 6aa6 ldr r6, [r4, #40] ; 0x28 + 2091e: 9131 str r1, [sp, #196] ; 0xc4 + 20920: 9232 str r2, [sp, #200] ; 0xc8 + 20922: 6b21 ldr r1, [r4, #48] ; 0x30 + 20924: 6b62 ldr r2, [r4, #52] ; 0x34 + 20926: 9335 str r3, [sp, #212] ; 0xd4 + 20928: 9737 str r7, [sp, #220] ; 0xdc + 2092a: 6a23 ldr r3, [r4, #32] + 2092c: 9039 str r0, [sp, #228] ; 0xe4 + 2092e: 6ba7 ldr r7, [r4, #56] ; 0x38 + 20930: 6c20 ldr r0, [r4, #64] ; 0x40 + 20932: 9638 str r6, [sp, #224] ; 0xe0 + 20934: 6be6 ldr r6, [r4, #60] ; 0x3c + 20936: 9336 str r3, [sp, #216] ; 0xd8 + 20938: 913a str r1, [sp, #232] ; 0xe8 + 2093a: 923b str r2, [sp, #236] ; 0xec + 2093c: 6c61 ldr r1, [r4, #68] ; 0x44 + 2093e: 6d22 ldr r2, [r4, #80] ; 0x50 + 20940: 973c str r7, [sp, #240] ; 0xf0 + 20942: 903e str r0, [sp, #248] ; 0xf8 + 20944: 6ca0 ldr r0, [r4, #72] ; 0x48 + 20946: 963d str r6, [sp, #244] ; 0xf4 + 20948: 6e26 ldr r6, [r4, #96] ; 0x60 + 2094a: 9040 str r0, [sp, #256] ; 0x100 + 2094c: 6d60 ldr r0, [r4, #84] ; 0x54 + 2094e: 6ee3 ldr r3, [r4, #108] ; 0x6c + 20950: 9646 str r6, [sp, #280] ; 0x118 + 20952: 6e66 ldr r6, [r4, #100] ; 0x64 + 20954: 913f str r1, [sp, #252] ; 0xfc + 20956: 9043 str r0, [sp, #268] ; 0x10c + 20958: 6ce1 ldr r1, [r4, #76] ; 0x4c + 2095a: 6da0 ldr r0, [r4, #88] ; 0x58 + 2095c: 6de7 ldr r7, [r4, #92] ; 0x5c + 2095e: 9242 str r2, [sp, #264] ; 0x108 + 20960: 9647 str r6, [sp, #284] ; 0x11c + 20962: 6f62 ldr r2, [r4, #116] ; 0x74 + 20964: 6ea6 ldr r6, [r4, #104] ; 0x68 + 20966: 9349 str r3, [sp, #292] ; 0x124 + 20968: 6f23 ldr r3, [r4, #112] ; 0x70 + 2096a: 9141 str r1, [sp, #260] ; 0x104 + 2096c: 9044 str r0, [sp, #272] ; 0x110 + 2096e: a92e add r1, sp, #184 ; 0xb8 + 20970: a84c add r0, sp, #304 ; 0x130 + 20972: 934a str r3, [sp, #296] ; 0x128 + 20974: 924b str r2, [sp, #300] ; 0x12c + 20976: 9648 str r6, [sp, #288] ; 0x120 + 20978: 9745 str r7, [sp, #276] ; 0x114 + 2097a: f7fe fae1 bl 1ef40 + 2097e: a82e add r0, sp, #184 ; 0xb8 + 20980: a94c add r1, sp, #304 ; 0x130 + 20982: f7fe faa1 bl 1eec8 + 20986: a84c add r0, sp, #304 ; 0x130 + 20988: a92e add r1, sp, #184 ; 0xb8 + 2098a: f7fe fad9 bl 1ef40 + 2098e: a82e add r0, sp, #184 ; 0xb8 + 20990: a94c add r1, sp, #304 ; 0x130 + 20992: f7fe fa99 bl 1eec8 + 20996: a84c add r0, sp, #304 ; 0x130 + 20998: a92e add r1, sp, #184 ; 0xb8 + 2099a: f7fe fad1 bl 1ef40 + 2099e: a82e add r0, sp, #184 ; 0xb8 + 209a0: a94c add r1, sp, #304 ; 0x130 + 209a2: f7fe fa91 bl 1eec8 + 209a6: a84c add r0, sp, #304 ; 0x130 + 209a8: a92e add r1, sp, #184 ; 0xb8 + 209aa: f7fe fac9 bl 1ef40 + 209ae: 4620 mov r0, r4 + 209b0: a94c add r1, sp, #304 ; 0x130 + 209b2: f7fe faa3 bl 1eefc + 209b6: 2600 movs r6, #0 + 209b8: 1071 asrs r1, r6, #1 + 209ba: f91d 2006 ldrsb.w r2, [sp, r6] + 209be: 4628 mov r0, r5 + 209c0: f7fe fe46 bl 1f650 + 209c4: a84c add r0, sp, #304 ; 0x130 + 209c6: 4621 mov r1, r4 + 209c8: 462a mov r2, r5 + 209ca: f7fe fa37 bl 1ee3c + 209ce: 3602 adds r6, #2 + 209d0: 4620 mov r0, r4 + 209d2: a94c add r1, sp, #304 ; 0x130 + 209d4: f7fe fa92 bl 1eefc + 209d8: 2e40 cmp r6, #64 ; 0x40 + 209da: d1ed bne.n 209b8 + 209dc: b075 add sp, #468 ; 0x1d4 + 209de: bdf0 pop {r4, r5, r6, r7, pc} + +000209e0 : + 209e0: b530 push {r4, r5, lr} + 209e2: 460d mov r5, r1 + 209e4: 4604 mov r4, r0 + 209e6: b0a7 sub sp, #156 ; 0x9c + 209e8: a808 add r0, sp, #32 + 209ea: 3150 adds r1, #80 ; 0x50 + 209ec: f7fd ffbc bl 1e968 + 209f0: 4629 mov r1, r5 + 209f2: aa08 add r2, sp, #32 + 209f4: a812 add r0, sp, #72 ; 0x48 + 209f6: f7fd f82f bl 1da58 + 209fa: aa08 add r2, sp, #32 + 209fc: f105 0128 add.w r1, r5, #40 ; 0x28 + 20a00: a81c add r0, sp, #112 ; 0x70 + 20a02: f7fd f829 bl 1da58 + 20a06: 4620 mov r0, r4 + 20a08: a91c add r1, sp, #112 ; 0x70 + 20a0a: f7fe f88f bl 1eb2c + 20a0e: a912 add r1, sp, #72 ; 0x48 + 20a10: 4668 mov r0, sp + 20a12: 7fe5 ldrb r5, [r4, #31] + 20a14: f7fe f88a bl 1eb2c + 20a18: f89d 3000 ldrb.w r3, [sp] + 20a1c: f003 0301 and.w r3, r3, #1 + 20a20: ea85 15c3 eor.w r5, r5, r3, lsl #7 + 20a24: 77e5 strb r5, [r4, #31] + 20a26: b027 add sp, #156 ; 0x9c + 20a28: bd30 pop {r4, r5, pc} + 20a2a: bf00 nop + +00020a2c : + 20a2c: 4694 mov ip, r2 + 20a2e: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 20a32: 468e mov lr, r1 + 20a34: b0e7 sub sp, #412 ; 0x19c + 20a36: 9308 str r3, [sp, #32] + 20a38: 9b08 ldr r3, [sp, #32] + 20a3a: 9f08 ldr r7, [sp, #32] + 20a3c: f892 8010 ldrb.w r8, [r2, #16] + 20a40: f892 a011 ldrb.w sl, [r2, #17] + 20a44: 7c1a ldrb r2, [r3, #16] + 20a46: 7c7e ldrb r6, [r7, #17] + 20a48: 2300 movs r3, #0 + 20a4a: e9cd 2314 strd r2, r3, [sp, #80] ; 0x50 + 20a4e: 2700 movs r7, #0 + 20a50: ea4f 431a mov.w r3, sl, lsr #16 + 20a54: ea4f 420a mov.w r2, sl, lsl #16 + 20a58: f89c a00f ldrb.w sl, [ip, #15] + 20a5c: e9cd 6716 strd r6, r7, [sp, #88] ; 0x58 + 20a60: ea4f 2408 mov.w r4, r8, lsl #8 + 20a64: 78ce ldrb r6, [r1, #3] + 20a66: f04f 0b00 mov.w fp, #0 + 20a6a: e9cd ab04 strd sl, fp, [sp, #16] + 20a6e: ea4f 6518 mov.w r5, r8, lsr #24 + 20a72: f89c a00e ldrb.w sl, [ip, #14] + 20a76: ea44 0802 orr.w r8, r4, r2 + 20a7a: 2700 movs r7, #0 + 20a7c: 788a ldrb r2, [r1, #2] + 20a7e: e9cd 6710 strd r6, r7, [sp, #64] ; 0x40 + 20a82: ea45 0903 orr.w r9, r5, r3 + 20a86: 790e ldrb r6, [r1, #4] + 20a88: 2300 movs r3, #0 + 20a8a: f04f 0b00 mov.w fp, #0 + 20a8e: e9cd 2312 strd r2, r3, [sp, #72] ; 0x48 + 20a92: e9cd ab20 strd sl, fp, [sp, #128] ; 0x80 + 20a96: 9a14 ldr r2, [sp, #80] ; 0x50 + 20a98: f8dd b050 ldr.w fp, [sp, #80] ; 0x50 + 20a9c: 2700 movs r7, #0 + 20a9e: e9cd 671a strd r6, r7, [sp, #104] ; 0x68 + 20aa2: 784e ldrb r6, [r1, #1] + 20aa4: 9916 ldr r1, [sp, #88] ; 0x58 + 20aa6: 2700 movs r7, #0 + 20aa8: ea4f 6b1b mov.w fp, fp, lsr #24 + 20aac: 0212 lsls r2, r2, #8 + 20aae: f8cd b004 str.w fp, [sp, #4] + 20ab2: 9200 str r2, [sp, #0] + 20ab4: e9cd 670c strd r6, r7, [sp, #48] ; 0x30 + 20ab8: e9dd 4500 ldrd r4, r5, [sp] + 20abc: 0c0f lsrs r7, r1, #16 + 20abe: e9cd 891c strd r8, r9, [sp, #112] ; 0x70 + 20ac2: 433d orrs r5, r7 + 20ac4: f8dd 9020 ldr.w r9, [sp, #32] + 20ac8: 9f08 ldr r7, [sp, #32] + 20aca: 040e lsls r6, r1, #16 + 20acc: 4334 orrs r4, r6 + 20ace: f899 800e ldrb.w r8, [r9, #14] + 20ad2: 7bfe ldrb r6, [r7, #15] + 20ad4: f04f 0900 mov.w r9, #0 + 20ad8: 2700 movs r7, #0 + 20ada: e9cd 6700 strd r6, r7, [sp] + 20ade: e9cd 452a strd r4, r5, [sp, #168] ; 0xa8 + 20ae2: e9cd 8922 strd r8, r9, [sp, #136] ; 0x88 + 20ae6: e9dd 4504 ldrd r4, r5, [sp, #16] + 20aea: f89c a012 ldrb.w sl, [ip, #18] + 20aee: f04f 0b00 mov.w fp, #0 + 20af2: e9cd ab16 strd sl, fp, [sp, #88] ; 0x58 + 20af6: 991a ldr r1, [sp, #104] ; 0x68 + 20af8: f8dd b040 ldr.w fp, [sp, #64] ; 0x40 + 20afc: f8dd 9040 ldr.w r9, [sp, #64] ; 0x40 + 20b00: f8dd a068 ldr.w sl, [sp, #104] ; 0x68 + 20b04: f89c 200b ldrb.w r2, [ip, #11] + 20b08: f89c 600c ldrb.w r6, [ip, #12] + 20b0c: ea4f 6b1b mov.w fp, fp, lsr #24 + 20b10: 0c09 lsrs r1, r1, #16 + 20b12: 2300 movs r3, #0 + 20b14: ea4f 2909 mov.w r9, r9, lsl #8 + 20b18: ea4f 4a0a mov.w sl, sl, lsl #16 + 20b1c: 910f str r1, [sp, #60] ; 0x3c + 20b1e: f8cd a038 str.w sl, [sp, #56] ; 0x38 + 20b22: f8cd b02c str.w fp, [sp, #44] ; 0x2c + 20b26: f8cd 9028 str.w r9, [sp, #40] ; 0x28 + 20b2a: e9cd 2318 strd r2, r3, [sp, #96] ; 0x60 + 20b2e: e9dd 231c ldrd r2, r3, [sp, #112] ; 0x70 + 20b32: e9dd 890e ldrd r8, r9, [sp, #56] ; 0x38 + 20b36: 4322 orrs r2, r4 + 20b38: 432b orrs r3, r5 + 20b3a: 2700 movs r7, #0 + 20b3c: e9cd 233a strd r2, r3, [sp, #232] ; 0xe8 + 20b40: e9cd 6726 strd r6, r7, [sp, #152] ; 0x98 + 20b44: e9dd 670a ldrd r6, r7, [sp, #40] ; 0x28 + 20b48: f8dd a030 ldr.w sl, [sp, #48] ; 0x30 + 20b4c: ea47 0709 orr.w r7, r7, r9 + 20b50: 9912 ldr r1, [sp, #72] ; 0x48 + 20b52: f8dd 9048 ldr.w r9, [sp, #72] ; 0x48 + 20b56: 9a0c ldr r2, [sp, #48] ; 0x30 + 20b58: f8dd b080 ldr.w fp, [sp, #128] ; 0x80 + 20b5c: 9b20 ldr r3, [sp, #128] ; 0x80 + 20b5e: ea4f 4919 mov.w r9, r9, lsr #16 + 20b62: ea4f 6a1a mov.w sl, sl, lsr #24 + 20b66: 0409 lsls r1, r1, #16 + 20b68: 0212 lsls r2, r2, #8 + 20b6a: f8cd 901c str.w r9, [sp, #28] + 20b6e: f8cd a00c str.w sl, [sp, #12] + 20b72: 9106 str r1, [sp, #24] + 20b74: 9202 str r2, [sp, #8] + 20b76: ea46 0608 orr.w r6, r6, r8 + 20b7a: e9cd 670e strd r6, r7, [sp, #56] ; 0x38 + 20b7e: e9dd 6702 ldrd r6, r7, [sp, #8] + 20b82: ea4f 691b mov.w r9, fp, lsr #24 + 20b86: ea4f 2803 mov.w r8, r3, lsl #8 + 20b8a: ea4f 4b14 mov.w fp, r4, lsr #16 + 20b8e: e9dd 2306 ldrd r2, r3, [sp, #24] + 20b92: 9c04 ldr r4, [sp, #16] + 20b94: 4316 orrs r6, r2 + 20b96: 431f orrs r7, r3 + 20b98: e9cd 672c strd r6, r7, [sp, #176] ; 0xb0 + 20b9c: ea49 070b orr.w r7, r9, fp + 20ba0: f8dd b020 ldr.w fp, [sp, #32] + 20ba4: ea4f 4a04 mov.w sl, r4, lsl #16 + 20ba8: ea48 060a orr.w r6, r8, sl + 20bac: f89c 800d ldrb.w r8, [ip, #13] + 20bb0: f89b a012 ldrb.w sl, [fp, #18] + 20bb4: f89e 4000 ldrb.w r4, [lr] + 20bb8: e9cd 673c strd r6, r7, [sp, #240] ; 0xf0 + 20bbc: 9b08 ldr r3, [sp, #32] + 20bbe: 9f08 ldr r7, [sp, #32] + 20bc0: f04f 0900 mov.w r9, #0 + 20bc4: f04f 0b00 mov.w fp, #0 + 20bc8: e9cd 8902 strd r8, r9, [sp, #8] + 20bcc: e9dd 892a ldrd r8, r9, [sp, #168] ; 0xa8 + 20bd0: e9cd ab30 strd sl, fp, [sp, #192] ; 0xc0 + 20bd4: e9dd ab00 ldrd sl, fp, [sp] + 20bd8: 2500 movs r5, #0 + 20bda: ea48 080a orr.w r8, r8, sl + 20bde: ea49 090b orr.w r9, r9, fp + 20be2: f50d 7b84 add.w fp, sp, #264 ; 0x108 + 20be6: 9922 ldr r1, [sp, #136] ; 0x88 + 20be8: e9cd 4528 strd r4, r5, [sp, #160] ; 0xa0 + 20bec: 7ada ldrb r2, [r3, #11] + 20bee: 9c00 ldr r4, [sp, #0] + 20bf0: 7b3e ldrb r6, [r7, #12] + 20bf2: e9cb 8900 strd r8, r9, [fp] + 20bf6: f8dd 9020 ldr.w r9, [sp, #32] + 20bfa: 2300 movs r3, #0 + 20bfc: 2700 movs r7, #0 + 20bfe: e9cd 2324 strd r2, r3, [sp, #144] ; 0x90 + 20c02: e9cd 6734 strd r6, r7, [sp, #208] ; 0xd0 + 20c06: f899 800d ldrb.w r8, [r9, #13] + 20c0a: 0422 lsls r2, r4, #16 + 20c0c: 020e lsls r6, r1, #8 + 20c0e: 0c23 lsrs r3, r4, #16 + 20c10: 4316 orrs r6, r2 + 20c12: 0e0f lsrs r7, r1, #24 + 20c14: f89e 2005 ldrb.w r2, [lr, #5] + 20c18: f04f 0900 mov.w r9, #0 + 20c1c: e9cd 891a strd r8, r9, [sp, #104] ; 0x68 + 20c20: f8dd a058 ldr.w sl, [sp, #88] ; 0x58 + 20c24: f89e 8007 ldrb.w r8, [lr, #7] + 20c28: 431f orrs r7, r3 + 20c2a: 2300 movs r3, #0 + 20c2c: e9cd 2304 strd r2, r3, [sp, #16] + 20c30: f04f 0900 mov.w r9, #0 + 20c34: f89e 2006 ldrb.w r2, [lr, #6] + 20c38: e9cd 8900 strd r8, r9, [sp] + 20c3c: ea4f 251a mov.w r5, sl, lsr #8 + 20c40: f8dd 9060 ldr.w r9, [sp, #96] ; 0x60 + 20c44: f8dd a098 ldr.w sl, [sp, #152] ; 0x98 + 20c48: 2300 movs r3, #0 + 20c4a: e9cd 232a strd r2, r3, [sp, #168] ; 0xa8 + 20c4e: f89e 2008 ldrb.w r2, [lr, #8] + 20c52: ea4f 6919 mov.w r9, r9, lsr #24 + 20c56: ea4f 4a1a mov.w sl, sl, lsr #16 + 20c5a: 2300 movs r3, #0 + 20c5c: f8cd 9054 str.w r9, [sp, #84] ; 0x54 + 20c60: f8cd a07c str.w sl, [sp, #124] ; 0x7c + 20c64: e9cd 2332 strd r2, r3, [sp, #200] ; 0xc8 + 20c68: f89c 8008 ldrb.w r8, [ip, #8] + 20c6c: f04f 0900 mov.w r9, #0 + 20c70: f89e a009 ldrb.w sl, [lr, #9] + 20c74: e9cd 8938 strd r8, r9, [sp, #224] ; 0xe0 + 20c78: f8dd 9058 ldr.w r9, [sp, #88] ; 0x58 + 20c7c: f89c 2009 ldrb.w r2, [ip, #9] + 20c80: f04f 0b00 mov.w fp, #0 + 20c84: e9cd ab2e strd sl, fp, [sp, #184] ; 0xb8 + 20c88: ea4f 6409 mov.w r4, r9, lsl #24 + 20c8c: f8dd a060 ldr.w sl, [sp, #96] ; 0x60 + 20c90: f8dd b098 ldr.w fp, [sp, #152] ; 0x98 + 20c94: 2300 movs r3, #0 + 20c96: e9dd 8912 ldrd r8, r9, [sp, #72] ; 0x48 + 20c9a: e9cd 2336 strd r2, r3, [sp, #216] ; 0xd8 + 20c9e: e9dd 233a ldrd r2, r3, [sp, #232] ; 0xe8 + 20ca2: 4322 orrs r2, r4 + 20ca4: 432b orrs r3, r5 + 20ca6: e9dd 450e ldrd r4, r5, [sp, #56] ; 0x38 + 20caa: ea44 0408 orr.w r4, r4, r8 + 20cae: ea45 0509 orr.w r5, r5, r9 + 20cb2: e9cd 4512 strd r4, r5, [sp, #72] ; 0x48 + 20cb6: e9dd 892c ldrd r8, r9, [sp, #176] ; 0xb0 + 20cba: f89c 400a ldrb.w r4, [ip, #10] + 20cbe: ea4f 2a0a mov.w sl, sl, lsl #8 + 20cc2: ea4f 4b0b mov.w fp, fp, lsl #16 + 20cc6: f8cd b078 str.w fp, [sp, #120] ; 0x78 + 20cca: f8cd a050 str.w sl, [sp, #80] ; 0x50 + 20cce: 2500 movs r5, #0 + 20cd0: e9dd ab14 ldrd sl, fp, [sp, #80] ; 0x50 + 20cd4: e9cd 2318 strd r2, r3, [sp, #96] ; 0x60 + 20cd8: e9dd 231e ldrd r2, r3, [sp, #120] ; 0x78 + 20cdc: e9cd 450e strd r4, r5, [sp, #56] ; 0x38 + 20ce0: e9dd 4502 ldrd r4, r5, [sp, #8] + 20ce4: ea4a 0a02 orr.w sl, sl, r2 + 20ce8: ea4b 0b03 orr.w fp, fp, r3 + 20cec: e9dd 233c ldrd r2, r3, [sp, #240] ; 0xf0 + 20cf0: 4322 orrs r2, r4 + 20cf2: 432b orrs r3, r5 + 20cf4: ad4a add r5, sp, #296 ; 0x128 + 20cf6: e9c5 2300 strd r2, r3, [r5] + 20cfa: e9cd ab3e strd sl, fp, [sp, #248] ; 0xf8 + 20cfe: e9dd ab28 ldrd sl, fp, [sp, #160] ; 0xa0 + 20d02: 9b08 ldr r3, [sp, #32] + 20d04: ea48 080a orr.w r8, r8, sl + 20d08: ea49 090b orr.w r9, r9, fp + 20d0c: f50d 7b90 add.w fp, sp, #288 ; 0x120 + 20d10: e9cb 8900 strd r8, r9, [fp] + 20d14: f8dd b090 ldr.w fp, [sp, #144] ; 0x90 + 20d18: 9934 ldr r1, [sp, #208] ; 0xd0 + 20d1a: 7a1a ldrb r2, [r3, #8] + 20d1c: ea4f 6b1b mov.w fp, fp, lsr #24 + 20d20: 2300 movs r3, #0 + 20d22: f8dd a0c0 ldr.w sl, [sp, #192] ; 0xc0 + 20d26: f8cd b084 str.w fp, [sp, #132] ; 0x84 + 20d2a: e9cd 233c strd r2, r3, [sp, #240] ; 0xf0 + 20d2e: ea4f 4b11 mov.w fp, r1, lsr #16 + 20d32: 9924 ldr r1, [sp, #144] ; 0x90 + 20d34: 9b08 ldr r3, [sp, #32] + 20d36: 0209 lsls r1, r1, #8 + 20d38: 9120 str r1, [sp, #128] ; 0x80 + 20d3a: ea4f 291a mov.w r9, sl, lsr #8 + 20d3e: a942 add r1, sp, #264 ; 0x108 + 20d40: e9d1 4500 ldrd r4, r5, [r1] + 20d44: 7a5a ldrb r2, [r3, #9] + 20d46: ea45 0509 orr.w r5, r5, r9 + 20d4a: f8dd 9020 ldr.w r9, [sp, #32] + 20d4e: ea4f 680a mov.w r8, sl, lsl #24 + 20d52: 2300 movs r3, #0 + 20d54: e9cd 233a strd r2, r3, [sp, #232] ; 0xe8 + 20d58: ea44 0408 orr.w r4, r4, r8 + 20d5c: 9a34 ldr r2, [sp, #208] ; 0xd0 + 20d5e: f899 800a ldrb.w r8, [r9, #10] + 20d62: f04f 0900 mov.w r9, #0 + 20d66: e9cd 8914 strd r8, r9, [sp, #80] ; 0x50 + 20d6a: ea4f 4a02 mov.w sl, r2, lsl #16 + 20d6e: f8dd 80b8 ldr.w r8, [sp, #184] ; 0xb8 + 20d72: f8dd 90e0 ldr.w r9, [sp, #224] ; 0xe0 + 20d76: e9dd 2320 ldrd r2, r3, [sp, #128] ; 0x80 + 20d7a: ea42 020a orr.w r2, r2, sl + 20d7e: ea43 030b orr.w r3, r3, fp + 20d82: e9c1 2300 strd r2, r3, [r1] + 20d86: e9dd ab1a ldrd sl, fp, [sp, #104] ; 0x68 + 20d8a: e9cd 4524 strd r4, r5, [sp, #144] ; 0x90 + 20d8e: ea4a 0a06 orr.w sl, sl, r6 + 20d92: 9c04 ldr r4, [sp, #16] + 20d94: ea4b 0b07 orr.w fp, fp, r7 + 20d98: a946 add r1, sp, #280 ; 0x118 + 20d9a: 9d00 ldr r5, [sp, #0] + 20d9c: ea4f 4818 mov.w r8, r8, lsr #16 + 20da0: ea4f 6919 mov.w r9, r9, lsr #24 + 20da4: e9c1 ab00 strd sl, fp, [r1] + 20da8: 9e2a ldr r6, [sp, #168] ; 0xa8 + 20daa: 9f32 ldr r7, [sp, #200] ; 0xc8 + 20dac: f8cd 8044 str.w r8, [sp, #68] ; 0x44 + 20db0: f8cd 908c str.w r9, [sp, #140] ; 0x8c + 20db4: f8dd a0d8 ldr.w sl, [sp, #216] ; 0xd8 + 20db8: f8dd 8000 ldr.w r8, [sp] + 20dbc: f8dd 90a8 ldr.w r9, [sp, #168] ; 0xa8 + 20dc0: 0a23 lsrs r3, r4, #8 + 20dc2: 0c2d lsrs r5, r5, #16 + 20dc4: f89e 400b ldrb.w r4, [lr, #11] + 20dc8: 950b str r5, [sp, #44] ; 0x2c + 20dca: 0e36 lsrs r6, r6, #24 + 20dcc: 0e3f lsrs r7, r7, #24 + 20dce: ea4f 4a1a mov.w sl, sl, lsr #16 + 20dd2: 2500 movs r5, #0 + 20dd4: ea4f 4808 mov.w r8, r8, lsl #16 + 20dd8: ea4f 2909 mov.w r9, r9, lsl #8 + 20ddc: e9cd 4534 strd r4, r5, [sp, #208] ; 0xd0 + 20de0: 9607 str r6, [sp, #28] + 20de2: 970d str r7, [sp, #52] ; 0x34 + 20de4: f8cd a074 str.w sl, [sp, #116] ; 0x74 + 20de8: 9f04 ldr r7, [sp, #16] + 20dea: f8cd 8028 str.w r8, [sp, #40] ; 0x28 + 20dee: f8cd 9018 str.w r9, [sp, #24] + 20df2: f89e a00c ldrb.w sl, [lr, #12] + 20df6: f04f 0b00 mov.w fp, #0 + 20dfa: e9cd ab2c strd sl, fp, [sp, #176] ; 0xb0 + 20dfe: e9dd 8912 ldrd r8, r9, [sp, #72] ; 0x48 + 20e02: 9d36 ldr r5, [sp, #216] ; 0xd8 + 20e04: f8dd b0c8 ldr.w fp, [sp, #200] ; 0xc8 + 20e08: 992e ldr r1, [sp, #184] ; 0xb8 + 20e0a: 9c38 ldr r4, [sp, #224] ; 0xe0 + 20e0c: 9e18 ldr r6, [sp, #96] ; 0x60 + 20e0e: 063a lsls r2, r7, #24 + 20e10: ea48 0802 orr.w r8, r8, r2 + 20e14: ea49 0903 orr.w r9, r9, r3 + 20e18: ea4f 2b0b mov.w fp, fp, lsl #8 + 20e1c: 0409 lsls r1, r1, #16 + 20e1e: 0224 lsls r4, r4, #8 + 20e20: 042d lsls r5, r5, #16 + 20e22: e9dd 230a ldrd r2, r3, [sp, #40] ; 0x28 + 20e26: f8cd b030 str.w fp, [sp, #48] ; 0x30 + 20e2a: 9422 str r4, [sp, #136] ; 0x88 + 20e2c: 9110 str r1, [sp, #64] ; 0x40 + 20e2e: 951c str r5, [sp, #112] ; 0x70 + 20e30: e9dd ab06 ldrd sl, fp, [sp, #24] + 20e34: e9cd 891e strd r8, r9, [sp, #120] ; 0x78 + 20e38: e9dd 890e ldrd r8, r9, [sp, #56] ; 0x38 + 20e3c: ea4a 0a02 orr.w sl, sl, r2 + 20e40: ea4b 0b03 orr.w fp, fp, r3 + 20e44: 09b4 lsrs r4, r6, #6 + 20e46: e9dd 673e ldrd r6, r7, [sp, #248] ; 0xf8 + 20e4a: ea46 0608 orr.w r6, r6, r8 + 20e4e: ea47 0709 orr.w r7, r7, r9 + 20e52: f50d 7980 add.w r9, sp, #256 ; 0x100 + 20e56: e9dd 2310 ldrd r2, r3, [sp, #64] ; 0x40 + 20e5a: e9cd ab36 strd sl, fp, [sp, #216] ; 0xd8 + 20e5e: e9dd ab0c ldrd sl, fp, [sp, #48] ; 0x30 + 20e62: e9c9 6700 strd r6, r7, [r9] + 20e66: e9dd 6722 ldrd r6, r7, [sp, #136] ; 0x88 + 20e6a: e9dd 891c ldrd r8, r9, [sp, #112] ; 0x70 + 20e6e: ea4a 0a02 orr.w sl, sl, r2 + 20e72: ea46 0608 orr.w r6, r6, r8 + 20e76: ea47 0709 orr.w r7, r7, r9 + 20e7a: f64f 72ff movw r2, #65535 ; 0xffff + 20e7e: e9cd 673e strd r6, r7, [sp, #248] ; 0xf8 + 20e82: f64f 76ff movw r6, #65535 ; 0xffff + 20e86: ea4b 0b03 orr.w fp, fp, r3 + 20e8a: e9cd ab0c strd sl, fp, [sp, #48] ; 0x30 + 20e8e: f89c a007 ldrb.w sl, [ip, #7] + 20e92: f04f 0b00 mov.w fp, #0 + 20e96: f2c0 021f movt r2, #31 + 20e9a: e9cd ab0a strd sl, fp, [sp, #40] ; 0x28 + 20e9e: f2c0 061f movt r6, #31 + 20ea2: f50d 7a94 add.w sl, sp, #296 ; 0x128 + 20ea6: e9da 8900 ldrd r8, r9, [sl] + 20eaa: ea5f 0959 movs.w r9, r9, lsr #1 + 20eae: ea4f 0838 mov.w r8, r8, rrx + 20eb2: f8dd b064 ldr.w fp, [sp, #100] ; 0x64 + 20eb6: af48 add r7, sp, #288 ; 0x120 + 20eb8: ea44 648b orr.w r4, r4, fp, lsl #26 + 20ebc: ea4f 159b mov.w r5, fp, lsr #6 + 20ec0: 2300 movs r3, #0 + 20ec2: f8dd b0f0 ldr.w fp, [sp, #240] ; 0xf0 + 20ec6: 4022 ands r2, r4 + 20ec8: 402b ands r3, r5 + 20eca: e9d7 4500 ldrd r4, r5, [r7] + 20ece: 2700 movs r7, #0 + 20ed0: 4034 ands r4, r6 + 20ed2: 403d ands r5, r7 + 20ed4: f50d 7aa4 add.w sl, sp, #328 ; 0x148 + 20ed8: ea4f 6b1b mov.w fp, fp, lsr #24 + 20edc: e9cd 2322 strd r2, r3, [sp, #136] ; 0x88 + 20ee0: e9cd 4512 strd r4, r5, [sp, #72] ; 0x48 + 20ee4: e9ca 8900 strd r8, r9, [sl] + 20ee8: f8cd b09c str.w fp, [sp, #156] ; 0x9c + 20eec: 993a ldr r1, [sp, #232] ; 0xe8 + 20eee: 9a3c ldr r2, [sp, #240] ; 0xf0 + 20ef0: 9b3a ldr r3, [sp, #232] ; 0xe8 + 20ef2: 9c24 ldr r4, [sp, #144] ; 0x90 + 20ef4: 0c09 lsrs r1, r1, #16 + 20ef6: 0212 lsls r2, r2, #8 + 20ef8: 041b lsls r3, r3, #16 + 20efa: 9129 str r1, [sp, #164] ; 0xa4 + 20efc: 9328 str r3, [sp, #160] ; 0xa0 + 20efe: 9226 str r2, [sp, #152] ; 0x98 + 20f00: e9dd 2326 ldrd r2, r3, [sp, #152] ; 0x98 + 20f04: ea4f 1894 mov.w r8, r4, lsr #6 + 20f08: e9dd 4528 ldrd r4, r5, [sp, #160] ; 0xa0 + 20f0c: 4322 orrs r2, r4 + 20f0e: 432b orrs r3, r5 + 20f10: e9cd 233c strd r2, r3, [sp, #240] ; 0xf0 + 20f14: f64f 72ff movw r2, #65535 ; 0xffff + 20f18: f2c0 021f movt r2, #31 + 20f1c: f50d 7b84 add.w fp, sp, #264 ; 0x108 + 20f20: e9db 6700 ldrd r6, r7, [fp] + 20f24: e9dd ab14 ldrd sl, fp, [sp, #80] ; 0x50 + 20f28: ea46 060a orr.w r6, r6, sl + 20f2c: ea47 070b orr.w r7, r7, fp + 20f30: f8dd a094 ldr.w sl, [sp, #148] ; 0x94 + 20f34: e9cd 673a strd r6, r7, [sp, #232] ; 0xe8 + 20f38: 9f08 ldr r7, [sp, #32] + 20f3a: ea48 688a orr.w r8, r8, sl, lsl #26 + 20f3e: 79fe ldrb r6, [r7, #7] + 20f40: ea02 0208 and.w r2, r2, r8 + 20f44: 2700 movs r7, #0 + 20f46: f50d 788c add.w r8, sp, #280 ; 0x118 + 20f4a: e9cd 6710 strd r6, r7, [sp, #64] ; 0x40 + 20f4e: e9d8 6700 ldrd r6, r7, [r8] + 20f52: 087f lsrs r7, r7, #1 + 20f54: ea4f 0636 mov.w r6, r6, rrx + 20f58: ea4f 199a mov.w r9, sl, lsr #6 + 20f5c: 2300 movs r3, #0 + 20f5e: ea03 0309 and.w r3, r3, r9 + 20f62: ac44 add r4, sp, #272 ; 0x110 + 20f64: e9c4 2300 strd r2, r3, [r4] + 20f68: 9d34 ldr r5, [sp, #208] ; 0xd0 + 20f6a: f89c 2006 ldrb.w r2, [ip, #6] + 20f6e: f8dd 9008 ldr.w r9, [sp, #8] + 20f72: ac42 add r4, sp, #264 ; 0x108 + 20f74: 2300 movs r3, #0 + 20f76: e9c4 2300 strd r2, r3, [r4] + 20f7a: 0e2d lsrs r5, r5, #24 + 20f7c: f89c 4003 ldrb.w r4, [ip, #3] + 20f80: e9c8 6700 strd r6, r7, [r8] + 20f84: 9521 str r5, [sp, #132] ; 0x84 + 20f86: ea4f 2719 mov.w r7, r9, lsr #8 + 20f8a: 2500 movs r5, #0 + 20f8c: f8dd 90d0 ldr.w r9, [sp, #208] ; 0xd0 + 20f90: f89e a00a ldrb.w sl, [lr, #10] + 20f94: e9cd 4538 strd r4, r5, [sp, #224] ; 0xe0 + 20f98: f89c 2004 ldrb.w r2, [ip, #4] + 20f9c: 9d02 ldr r5, [sp, #8] + 20f9e: f04f 0b00 mov.w fp, #0 + 20fa2: ea4f 2909 mov.w r9, r9, lsl #8 + 20fa6: 2300 movs r3, #0 + 20fa8: e9cd ab06 strd sl, fp, [sp, #24] + 20fac: f8dd 80b0 ldr.w r8, [sp, #176] ; 0xb0 + 20fb0: 062e lsls r6, r5, #24 + 20fb2: f8cd 9080 str.w r9, [sp, #128] ; 0x80 + 20fb6: e9cd 2334 strd r2, r3, [sp, #208] ; 0xd0 + 20fba: 9d1e ldr r5, [sp, #120] ; 0x78 + 20fbc: 9b2c ldr r3, [sp, #176] ; 0xb0 + 20fbe: ea4f 4b18 mov.w fp, r8, lsr #16 + 20fc2: a940 add r1, sp, #256 ; 0x100 + 20fc4: e9dd 8936 ldrd r8, r9, [sp, #216] ; 0xd8 + 20fc8: 096a lsrs r2, r5, #5 + 20fca: e9dd 4504 ldrd r4, r5, [sp, #16] + 20fce: ea48 0804 orr.w r8, r8, r4 + 20fd2: ea49 0905 orr.w r9, r9, r5 + 20fd6: e9cd 891c strd r8, r9, [sp, #112] ; 0x70 + 20fda: e9dd 450c ldrd r4, r5, [sp, #48] ; 0x30 + 20fde: e9d1 8900 ldrd r8, r9, [r1] + 20fe2: ea48 0806 orr.w r8, r8, r6 + 20fe6: ea49 0907 orr.w r9, r9, r7 + 20fea: e9dd 6700 ldrd r6, r7, [sp] + 20fee: 4334 orrs r4, r6 + 20ff0: 433d orrs r5, r7 + 20ff2: af48 add r7, sp, #288 ; 0x120 + 20ff4: ea4f 4a03 mov.w sl, r3, lsl #16 + 20ff8: e9cd 892c strd r8, r9, [sp, #176] ; 0xb0 + 20ffc: e9dd 893e ldrd r8, r9, [sp, #248] ; 0xf8 + 21000: e9c7 4500 strd r4, r5, [r7] + 21004: e9dd 450a ldrd r4, r5, [sp, #40] ; 0x28 + 21008: e9dd 6720 ldrd r6, r7, [sp, #128] ; 0x80 + 2100c: ea48 0804 orr.w r8, r8, r4 + 21010: ea49 0905 orr.w r9, r9, r5 + 21014: ad4e add r5, sp, #312 ; 0x138 + 21016: e9c5 8900 strd r8, r9, [r5] + 2101a: ea46 060a orr.w r6, r6, sl + 2101e: ea47 070b orr.w r7, r7, fp + 21022: f50d 7894 add.w r8, sp, #296 ; 0x128 + 21026: e9c8 6700 strd r6, r7, [r8] + 2102a: f64f 76ff movw r6, #65535 ; 0xffff + 2102e: f89e a00f ldrb.w sl, [lr, #15] + 21032: f04f 0b00 mov.w fp, #0 + 21036: e9cd ab0c strd sl, fp, [sp, #48] ; 0x30 + 2103a: f64f 7aff movw sl, #65535 ; 0xffff + 2103e: f2c0 061f movt r6, #31 + 21042: f2c0 0a1f movt sl, #31 + 21046: f8dd 907c ldr.w r9, [sp, #124] ; 0x7c + 2104a: f89e 400e ldrb.w r4, [lr, #14] + 2104e: ea42 62c9 orr.w r2, r2, r9, lsl #27 + 21052: ea4f 1359 mov.w r3, r9, lsr #5 + 21056: 2700 movs r7, #0 + 21058: 4016 ands r6, r2 + 2105a: 401f ands r7, r3 + 2105c: 2500 movs r5, #0 + 2105e: e9cd 4500 strd r4, r5, [sp] + 21062: e9cd 6704 strd r6, r7, [sp, #16] + 21066: 9c23 ldr r4, [sp, #140] ; 0x8c + 21068: 9e1a ldr r6, [sp, #104] ; 0x68 + 2106a: 9b12 ldr r3, [sp, #72] ; 0x48 + 2106c: f50d 7ba4 add.w fp, sp, #328 ; 0x148 + 21070: e9db 8900 ldrd r8, r9, [fp] + 21074: 0a35 lsrs r5, r6, #8 + 21076: f04f 0b00 mov.w fp, #0 + 2107a: fb03 f304 mul.w r3, r3, r4 + 2107e: 0634 lsls r4, r6, #24 + 21080: ea08 080a and.w r8, r8, sl + 21084: ea09 090b and.w r9, r9, fp + 21088: e9dd ab3a ldrd sl, fp, [sp, #232] ; 0xe8 + 2108c: ea4a 0a04 orr.w sl, sl, r4 + 21090: ea4b 0b05 orr.w fp, fp, r5 + 21094: e9cd 8920 strd r8, r9, [sp, #128] ; 0x80 + 21098: 9f13 ldr r7, [sp, #76] ; 0x4c + 2109a: f8dd 8088 ldr.w r8, [sp, #136] ; 0x88 + 2109e: e9cd ab3e strd sl, fp, [sp, #248] ; 0xf8 + 210a2: f8dd b048 ldr.w fp, [sp, #72] ; 0x48 + 210a6: fb08 3307 mla r3, r8, r7, r3 + 210aa: e9dd 673c ldrd r6, r7, [sp, #240] ; 0xf0 + 210ae: fbab 4508 umull r4, r5, fp, r8 + 210b2: e9dd 8910 ldrd r8, r9, [sp, #64] ; 0x40 + 210b6: ea46 0608 orr.w r6, r6, r8 + 210ba: ea47 0709 orr.w r7, r7, r9 + 210be: f50d 79a8 add.w r9, sp, #336 ; 0x150 + 210c2: e9c9 6700 strd r6, r7, [r9] + 210c6: 9a08 ldr r2, [sp, #32] + 210c8: 441d add r5, r3 + 210ca: 7992 ldrb r2, [r2, #6] + 210cc: ae4c add r6, sp, #304 ; 0x130 + 210ce: f50d 7888 add.w r8, sp, #272 ; 0x110 + 210d2: 2300 movs r3, #0 + 210d4: e9c6 2300 strd r2, r3, [r6] + 210d8: e9d8 6700 ldrd r6, r7, [r8] + 210dc: 1936 adds r6, r6, r4 + 210de: ac46 add r4, sp, #280 ; 0x118 + 210e0: e9d4 2300 ldrd r2, r3, [r4] + 210e4: f64f 74ff movw r4, #65535 ; 0xffff + 210e8: 416f adcs r7, r5 + 210ea: f50d 78b4 add.w r8, sp, #360 ; 0x168 + 210ee: f04f 0a00 mov.w sl, #0 + 210f2: f04f 0b00 mov.w fp, #0 + 210f6: f2c0 041f movt r4, #31 + 210fa: e9c8 6700 strd r6, r7, [r8] + 210fe: 4656 mov r6, sl + 21100: 465f mov r7, fp + 21102: 2500 movs r5, #0 + 21104: 4022 ands r2, r4 + 21106: 402b ands r3, r5 + 21108: ad5c add r5, sp, #368 ; 0x170 + 2110a: e9c5 2300 strd r2, r3, [r5] + 2110e: 4632 mov r2, r6 + 21110: 463b mov r3, r7 + 21112: f8dd 8020 ldr.w r8, [sp, #32] + 21116: f50d 7aa4 add.w sl, sp, #328 ; 0x148 + 2111a: f898 8003 ldrb.w r8, [r8, #3] + 2111e: f04f 0900 mov.w r9, #0 + 21122: e9ca 8900 strd r8, r9, [sl] + 21126: f8dd a020 ldr.w sl, [sp, #32] + 2112a: a946 add r1, sp, #280 ; 0x118 + 2112c: f89a a004 ldrb.w sl, [sl, #4] + 21130: f04f 0b00 mov.w fp, #0 + 21134: e9c1 ab00 strd sl, fp, [r1] + 21138: e9cd 2302 strd r2, r3, [sp, #8] + 2113c: 9c0e ldr r4, [sp, #56] ; 0x38 + 2113e: 9b06 ldr r3, [sp, #24] + 21140: 9d42 ldr r5, [sp, #264] ; 0x108 + 21142: 9e0a ldr r6, [sp, #40] ; 0x28 + 21144: 9f38 ldr r7, [sp, #224] ; 0xe0 + 21146: f8dd 80d0 ldr.w r8, [sp, #208] ; 0xd0 + 2114a: f8dd 9018 ldr.w r9, [sp, #24] + 2114e: f8dd a038 ldr.w sl, [sp, #56] ; 0x38 + 21152: f8dd b108 ldr.w fp, [sp, #264] ; 0x108 + 21156: 990a ldr r1, [sp, #40] ; 0x28 + 21158: 0a1b lsrs r3, r3, #8 + 2115a: 0a24 lsrs r4, r4, #8 + 2115c: 0e2d lsrs r5, r5, #24 + 2115e: 0c36 lsrs r6, r6, #16 + 21160: 0e3f lsrs r7, r7, #24 + 21162: ea4f 4818 mov.w r8, r8, lsr #16 + 21166: ea4f 6909 mov.w r9, r9, lsl #24 + 2116a: ea4f 6a0a mov.w sl, sl, lsl #24 + 2116e: ea4f 2b0b mov.w fp, fp, lsl #8 + 21172: 0409 lsls r1, r1, #16 + 21174: 9319 str r3, [sp, #100] ; 0x64 + 21176: 942f str r4, [sp, #188] ; 0xbc + 21178: 952b str r5, [sp, #172] ; 0xac + 2117a: 9633 str r6, [sp, #204] ; 0xcc + 2117c: 9729 str r7, [sp, #164] ; 0xa4 + 2117e: f8cd 8094 str.w r8, [sp, #148] ; 0x94 + 21182: f8cd 9060 str.w r9, [sp, #96] ; 0x60 + 21186: f8cd a0b8 str.w sl, [sp, #184] ; 0xb8 + 2118a: f8cd b0a8 str.w fp, [sp, #168] ; 0xa8 + 2118e: 9132 str r1, [sp, #200] ; 0xc8 + 21190: 9b34 ldr r3, [sp, #208] ; 0xd0 + 21192: f89c a014 ldrb.w sl, [ip, #20] + 21196: 9a38 ldr r2, [sp, #224] ; 0xe0 + 21198: f89c 4013 ldrb.w r4, [ip, #19] + 2119c: a940 add r1, sp, #256 ; 0x100 + 2119e: f04f 0b00 mov.w fp, #0 + 211a2: e9c1 ab00 strd sl, fp, [r1] + 211a6: ae42 add r6, sp, #264 ; 0x108 + 211a8: f50d 7b90 add.w fp, sp, #288 ; 0x120 + 211ac: 0212 lsls r2, r2, #8 + 211ae: 041b lsls r3, r3, #16 + 211b0: 2500 movs r5, #0 + 211b2: 9228 str r2, [sp, #160] ; 0xa0 + 211b4: 9324 str r3, [sp, #144] ; 0x90 + 211b6: 9a1c ldr r2, [sp, #112] ; 0x70 + 211b8: 9b2c ldr r3, [sp, #176] ; 0xb0 + 211ba: e9c6 4500 strd r4, r5, [r6] + 211be: e9db 4500 ldrd r4, r5, [fp] + 211c2: e9dd ab18 ldrd sl, fp, [sp, #96] ; 0x60 + 211c6: ea44 040a orr.w r4, r4, sl + 211ca: ea45 050b orr.w r5, r5, fp + 211ce: e9cd 451a strd r4, r5, [sp, #104] ; 0x68 + 211d2: ad4e add r5, sp, #312 ; 0x138 + 211d4: ea4f 0892 mov.w r8, r2, lsr #2 + 211d8: 091e lsrs r6, r3, #4 + 211da: e9d5 2300 ldrd r2, r3, [r5] + 211de: e9dd 452e ldrd r4, r5, [sp, #184] ; 0xb8 + 211e2: 4322 orrs r2, r4 + 211e4: 432b orrs r3, r5 + 211e6: e9cd 2334 strd r2, r3, [sp, #208] ; 0xd0 + 211ea: e9dd 452a ldrd r4, r5, [sp, #168] ; 0xa8 + 211ee: aa4a add r2, sp, #296 ; 0x128 + 211f0: e9d2 ab00 ldrd sl, fp, [r2] + 211f4: e9dd 2306 ldrd r2, r3, [sp, #24] + 211f8: ea4a 0a02 orr.w sl, sl, r2 + 211fc: ea4b 0b03 orr.w fp, fp, r3 + 21200: f89e 200d ldrb.w r2, [lr, #13] + 21204: ab4e add r3, sp, #312 ; 0x138 + 21206: e9c3 ab00 strd sl, fp, [r3] + 2120a: e9dd ab32 ldrd sl, fp, [sp, #200] ; 0xc8 + 2120e: 2300 movs r3, #0 + 21210: ea44 040a orr.w r4, r4, sl + 21214: ea45 050b orr.w r5, r5, fp + 21218: f50d 7bac add.w fp, sp, #344 ; 0x158 + 2121c: e9cb 4500 strd r4, r5, [fp] + 21220: e9dd ab24 ldrd sl, fp, [sp, #144] ; 0x90 + 21224: e9dd 4528 ldrd r4, r5, [sp, #160] ; 0xa0 + 21228: e9cd 230e strd r2, r3, [sp, #56] ; 0x38 + 2122c: ea44 040a orr.w r4, r4, sl + 21230: ea45 050b orr.w r5, r5, fp + 21234: 9a00 ldr r2, [sp, #0] + 21236: f50d 7ba0 add.w fp, sp, #320 ; 0x140 + 2123a: e9cb 4500 strd r4, r5, [fp] + 2123e: f89e 4010 ldrb.w r4, [lr, #16] + 21242: 2500 movs r5, #0 + 21244: 0e12 lsrs r2, r2, #24 + 21246: f8dd a0b4 ldr.w sl, [sp, #180] ; 0xb4 + 2124a: 990c ldr r1, [sp, #48] ; 0x30 + 2124c: e9cd 4518 strd r4, r5, [sp, #96] ; 0x60 + 21250: 9d1d ldr r5, [sp, #116] ; 0x74 + 21252: 9227 str r2, [sp, #156] ; 0x9c + 21254: 9c00 ldr r4, [sp, #0] + 21256: ea48 7885 orr.w r8, r8, r5, lsl #30 + 2125a: 0224 lsls r4, r4, #8 + 2125c: 9426 str r4, [sp, #152] ; 0x98 + 2125e: f64f 74ff movw r4, #65535 ; 0xffff + 21262: f2c0 041f movt r4, #31 + 21266: ea04 0408 and.w r4, r4, r8 + 2126a: f64f 78ff movw r8, #65535 ; 0xffff + 2126e: f2c0 081f movt r8, #31 + 21272: ea4f 0995 mov.w r9, r5, lsr #2 + 21276: 2500 movs r5, #0 + 21278: ea46 760a orr.w r6, r6, sl, lsl #28 + 2127c: ea4f 171a mov.w r7, sl, lsr #4 + 21280: ea05 0509 and.w r5, r5, r9 + 21284: f04f 0900 mov.w r9, #0 + 21288: ea08 0806 and.w r8, r8, r6 + 2128c: ea09 0907 and.w r9, r9, r7 + 21290: f89c 6018 ldrb.w r6, [ip, #24] + 21294: e9cd 891e strd r8, r9, [sp, #120] ; 0x78 + 21298: 2700 movs r7, #0 + 2129a: f50d 7890 add.w r8, sp, #288 ; 0x120 + 2129e: e9c8 6700 strd r6, r7, [r8] + 212a2: 9f14 ldr r7, [sp, #80] ; 0x50 + 212a4: 9e4c ldr r6, [sp, #304] ; 0x130 + 212a6: 0a3f lsrs r7, r7, #8 + 212a8: 973b str r7, [sp, #236] ; 0xec + 212aa: 9f10 ldr r7, [sp, #64] ; 0x40 + 212ac: 0236 lsls r6, r6, #8 + 212ae: f89e 2011 ldrb.w r2, [lr, #17] + 212b2: 9636 str r6, [sp, #216] ; 0xd8 + 212b4: 043f lsls r7, r7, #16 + 212b6: f89c 6005 ldrb.w r6, [ip, #5] + 212ba: ea4f 4b11 mov.w fp, r1, lsr #16 + 212be: ea4f 4a01 mov.w sl, r1, lsl #16 + 212c2: 973c str r7, [sp, #240] ; 0xf0 + 212c4: 2300 movs r3, #0 + 212c6: 2700 movs r7, #0 + 212c8: e9cd 4500 strd r4, r5, [sp] + 212cc: 9914 ldr r1, [sp, #80] ; 0x50 + 212ce: e9cd 232e strd r2, r3, [sp, #184] ; 0xb8 + 212d2: e9dd 2326 ldrd r2, r3, [sp, #152] ; 0x98 + 212d6: e9cd 6714 strd r6, r7, [sp, #80] ; 0x50 + 212da: ea42 020a orr.w r2, r2, sl + 212de: ea43 030b orr.w r3, r3, fp + 212e2: ac44 add r4, sp, #272 ; 0x110 + 212e4: 9f3e ldr r7, [sp, #248] ; 0xf8 + 212e6: e9c4 2300 strd r2, r3, [r4] + 212ea: f8dd b118 ldr.w fp, [sp, #280] ; 0x118 + 212ee: f89c 2019 ldrb.w r2, [ip, #25] + 212f2: f8dd 8130 ldr.w r8, [sp, #304] ; 0x130 + 212f6: f8dd 9040 ldr.w r9, [sp, #64] ; 0x40 + 212fa: f8dd a148 ldr.w sl, [sp, #328] ; 0x148 + 212fe: ac4a add r4, sp, #296 ; 0x128 + 21300: f89c 6002 ldrb.w r6, [ip, #2] + 21304: 2300 movs r3, #0 + 21306: 0609 lsls r1, r1, #24 + 21308: 093f lsrs r7, r7, #4 + 2130a: e9c4 2300 strd r2, r3, [r4] + 2130e: 913a str r1, [sp, #232] ; 0xe8 + 21310: ea4f 431b mov.w r3, fp, lsr #16 + 21314: ea4f 420b mov.w r2, fp, lsl #16 + 21318: 9702 str r7, [sp, #8] + 2131a: f50d 7ba8 add.w fp, sp, #336 ; 0x150 + 2131e: ea4f 6818 mov.w r8, r8, lsr #24 + 21322: ea4f 4919 mov.w r9, r9, lsr #16 + 21326: 2700 movs r7, #0 + 21328: f8cd 80dc str.w r8, [sp, #220] ; 0xdc + 2132c: f8cd 90f4 str.w r9, [sp, #244] ; 0xf4 + 21330: ea4f 651a mov.w r5, sl, lsr #24 + 21334: e9db 8900 ldrd r8, r9, [fp] + 21338: ea4f 240a mov.w r4, sl, lsl #8 + 2133c: e9dd ab3a ldrd sl, fp, [sp, #232] ; 0xe8 + 21340: e9cd 6710 strd r6, r7, [sp, #64] ; 0x40 + 21344: e9dd 673c ldrd r6, r7, [sp, #240] ; 0xf0 + 21348: ea49 090b orr.w r9, r9, fp + 2134c: ea48 080a orr.w r8, r8, sl + 21350: e9dd ab36 ldrd sl, fp, [sp, #216] ; 0xd8 + 21354: ea4a 0a06 orr.w sl, sl, r6 + 21358: ea4b 0b07 orr.w fp, fp, r7 + 2135c: af58 add r7, sp, #352 ; 0x160 + 2135e: e9c7 ab00 strd sl, fp, [r7] + 21362: a954 add r1, sp, #336 ; 0x150 + 21364: ea44 0a02 orr.w sl, r4, r2 + 21368: ea45 0b03 orr.w fp, r5, r3 + 2136c: e9c1 ab00 strd sl, fp, [r1] + 21370: 9a21 ldr r2, [sp, #132] ; 0x84 + 21372: 9b04 ldr r3, [sp, #16] + 21374: 9912 ldr r1, [sp, #72] ; 0x48 + 21376: fb03 f302 mul.w r3, r3, r2 + 2137a: fb01 f102 mul.w r1, r1, r2 + 2137e: 9d20 ldr r5, [sp, #128] ; 0x80 + 21380: 9c05 ldr r4, [sp, #20] + 21382: 9e13 ldr r6, [sp, #76] ; 0x4c + 21384: 9a04 ldr r2, [sp, #16] + 21386: fb05 1106 mla r1, r5, r6, r1 + 2138a: fb05 3304 mla r3, r5, r4, r3 + 2138e: 462e mov r6, r5 + 21390: fba2 4505 umull r4, r5, r2, r5 + 21394: f8dd a0fc ldr.w sl, [sp, #252] ; 0xfc + 21398: 9f02 ldr r7, [sp, #8] + 2139a: aa5a add r2, sp, #360 ; 0x168 + 2139c: ea4f 1b1a mov.w fp, sl, lsr #4 + 213a0: f8cd b00c str.w fp, [sp, #12] + 213a4: ea47 770a orr.w r7, r7, sl, lsl #28 + 213a8: 441d add r5, r3 + 213aa: e9d2 ab00 ldrd sl, fp, [r2] + 213ae: eb1a 0a04 adds.w sl, sl, r4 + 213b2: eb4b 0b05 adc.w fp, fp, r5 + 213b6: aa5e add r2, sp, #376 ; 0x178 + 213b8: e9c2 ab00 strd sl, fp, [r2] + 213bc: f64f 7aff movw sl, #65535 ; 0xffff + 213c0: f2c0 0a1f movt sl, #31 + 213c4: 9c12 ldr r4, [sp, #72] ; 0x48 + 213c6: 9702 str r7, [sp, #8] + 213c8: fba4 2306 umull r2, r3, r4, r6 + 213cc: e9dd 6702 ldrd r6, r7, [sp, #8] + 213d0: f04f 0b00 mov.w fp, #0 + 213d4: ea06 060a and.w r6, r6, sl + 213d8: ea07 070b and.w r7, r7, fp + 213dc: f50d 7bb4 add.w fp, sp, #360 ; 0x168 + 213e0: e9cb 6700 strd r6, r7, [fp] + 213e4: ae5c add r6, sp, #368 ; 0x170 + 213e6: e9d6 4500 ldrd r4, r5, [r6] + 213ea: 440b add r3, r1 + 213ec: 18a4 adds r4, r4, r2 + 213ee: 415d adcs r5, r3 + 213f0: e9c6 4500 strd r4, r5, [r6] + 213f4: f8dd b020 ldr.w fp, [sp, #32] + 213f8: 9c08 ldr r4, [sp, #32] + 213fa: f89b a013 ldrb.w sl, [fp, #19] + 213fe: 7d24 ldrb r4, [r4, #20] + 21400: ae52 add r6, sp, #328 ; 0x148 + 21402: f04f 0b00 mov.w fp, #0 + 21406: 2500 movs r5, #0 + 21408: e9cd ab3e strd sl, fp, [sp, #248] ; 0xf8 + 2140c: e9c6 4500 strd r4, r5, [r6] + 21410: f8dd a020 ldr.w sl, [sp, #32] + 21414: 9c08 ldr r4, [sp, #32] + 21416: f89a a018 ldrb.w sl, [sl, #24] + 2141a: 7e64 ldrb r4, [r4, #25] + 2141c: a946 add r1, sp, #280 ; 0x118 + 2141e: ae60 add r6, sp, #384 ; 0x180 + 21420: 2200 movs r2, #0 + 21422: 2300 movs r3, #0 + 21424: f04f 0b00 mov.w fp, #0 + 21428: 2500 movs r5, #0 + 2142a: e9c1 ab00 strd sl, fp, [r1] + 2142e: 461f mov r7, r3 + 21430: e9c6 4500 strd r4, r5, [r6] + 21434: 4616 mov r6, r2 + 21436: 9b2e ldr r3, [sp, #184] ; 0xb8 + 21438: 9d4a ldr r5, [sp, #296] ; 0x128 + 2143a: f8dd b020 ldr.w fp, [sp, #32] + 2143e: 9c48 ldr r4, [sp, #288] ; 0x120 + 21440: e9cd 670a strd r6, r7, [sp, #40] ; 0x28 + 21444: 9a18 ldr r2, [sp, #96] ; 0x60 + 21446: 9e0e ldr r6, [sp, #56] ; 0x38 + 21448: 9f18 ldr r7, [sp, #96] ; 0x60 + 2144a: 0c1b lsrs r3, r3, #16 + 2144c: 0c2d lsrs r5, r5, #16 + 2144e: f89b a005 ldrb.w sl, [fp, #5] + 21452: 990e ldr r1, [sp, #56] ; 0x38 + 21454: 9325 str r3, [sp, #148] ; 0x94 + 21456: 952d str r5, [sp, #180] ; 0xb4 + 21458: 9b08 ldr r3, [sp, #32] + 2145a: 9d4a ldr r5, [sp, #296] ; 0x128 + 2145c: 0e24 lsrs r4, r4, #24 + 2145e: 9433 str r4, [sp, #204] ; 0xcc + 21460: f04f 0b00 mov.w fp, #0 + 21464: 9c48 ldr r4, [sp, #288] ; 0x120 + 21466: 0e12 lsrs r2, r2, #24 + 21468: 0636 lsls r6, r6, #24 + 2146a: 023f lsls r7, r7, #8 + 2146c: e9cd ab28 strd sl, fp, [sp, #160] ; 0xa0 + 21470: 9606 str r6, [sp, #24] + 21472: 921d str r2, [sp, #116] ; 0x74 + 21474: 971c str r7, [sp, #112] ; 0x70 + 21476: 789a ldrb r2, [r3, #2] + 21478: f8dd a0b8 ldr.w sl, [sp, #184] ; 0xb8 + 2147c: 9e42 ldr r6, [sp, #264] ; 0x108 + 2147e: 9f40 ldr r7, [sp, #256] ; 0x100 + 21480: 0a09 lsrs r1, r1, #8 + 21482: 042d lsls r5, r5, #16 + 21484: 9107 str r1, [sp, #28] + 21486: 952c str r5, [sp, #176] ; 0xb0 + 21488: 2300 movs r3, #0 + 2148a: ad4e add r5, sp, #312 ; 0x138 + 2148c: 0224 lsls r4, r4, #8 + 2148e: e9cd 2326 strd r2, r3, [sp, #152] ; 0x98 + 21492: e9d5 2300 ldrd r2, r3, [r5] + 21496: 9432 str r4, [sp, #200] ; 0xc8 + 21498: ea4f 4a0a mov.w sl, sl, lsl #16 + 2149c: e9dd 4506 ldrd r4, r5, [sp, #24] + 214a0: 0e36 lsrs r6, r6, #24 + 214a2: 4322 orrs r2, r4 + 214a4: 432b orrs r3, r5 + 214a6: 0c3f lsrs r7, r7, #16 + 214a8: ad56 add r5, sp, #344 ; 0x158 + 214aa: 9934 ldr r1, [sp, #208] ; 0xd0 + 214ac: f8cd a090 str.w sl, [sp, #144] ; 0x90 + 214b0: 9639 str r6, [sp, #228] ; 0xe4 + 214b2: f8dd a068 ldr.w sl, [sp, #104] ; 0x68 + 214b6: 972b str r7, [sp, #172] ; 0xac + 214b8: e9cd 2318 strd r2, r3, [sp, #96] ; 0x60 + 214bc: e9d5 2300 ldrd r2, r3, [r5] + 214c0: e9dd 4514 ldrd r4, r5, [sp, #80] ; 0x50 + 214c4: 4322 orrs r2, r4 + 214c6: 432b orrs r3, r5 + 214c8: ac50 add r4, sp, #320 ; 0x140 + 214ca: e9cd 232e strd r2, r3, [sp, #184] ; 0xb8 + 214ce: e9d4 2300 ldrd r2, r3, [r4] + 214d2: e9dd 4510 ldrd r4, r5, [sp, #64] ; 0x40 + 214d6: 4322 orrs r2, r4 + 214d8: 432b orrs r3, r5 + 214da: ad4a add r5, sp, #296 ; 0x128 + 214dc: e9c5 2300 strd r2, r3, [r5] + 214e0: e9dd 4524 ldrd r4, r5, [sp, #144] ; 0x90 + 214e4: e9dd 231c ldrd r2, r3, [sp, #112] ; 0x70 + 214e8: 4322 orrs r2, r4 + 214ea: 432b orrs r3, r5 + 214ec: ad48 add r5, sp, #288 ; 0x120 + 214ee: e9c5 2300 strd r2, r3, [r5] + 214f2: e9dd 452c ldrd r4, r5, [sp, #176] ; 0xb0 + 214f6: e9dd 2332 ldrd r2, r3, [sp, #200] ; 0xc8 + 214fa: 4322 orrs r2, r4 + 214fc: 432b orrs r3, r5 + 214fe: ad4c add r5, sp, #304 ; 0x130 + 21500: e9c5 2300 strd r2, r3, [r5] + 21504: ea4f 16da mov.w r6, sl, lsr #7 + 21508: 9a40 ldr r2, [sp, #256] ; 0x100 + 2150a: ea4f 1ad1 mov.w sl, r1, lsr #7 + 2150e: 9942 ldr r1, [sp, #264] ; 0x108 + 21510: 9b1b ldr r3, [sp, #108] ; 0x6c + 21512: 9c35 ldr r4, [sp, #212] ; 0xd4 + 21514: 0209 lsls r1, r1, #8 + 21516: 0412 lsls r2, r2, #16 + 21518: 9138 str r1, [sp, #224] ; 0xe0 + 2151a: 922a str r2, [sp, #168] ; 0xa8 + 2151c: ea46 6643 orr.w r6, r6, r3, lsl #25 + 21520: ea4a 6a44 orr.w sl, sl, r4, lsl #25 + 21524: e9dd 2338 ldrd r2, r3, [sp, #224] ; 0xe0 + 21528: e9dd 452a ldrd r4, r5, [sp, #168] ; 0xa8 + 2152c: 432b orrs r3, r5 + 2152e: 9d1b ldr r5, [sp, #108] ; 0x6c + 21530: 4322 orrs r2, r4 + 21532: 09ef lsrs r7, r5, #7 + 21534: 2400 movs r4, #0 + 21536: 2500 movs r5, #0 + 21538: e9cd 4506 strd r4, r5, [sp, #24] + 2153c: f64f 74ff movw r4, #65535 ; 0xffff + 21540: f2c0 041f movt r4, #31 + 21544: 4034 ands r4, r6 + 21546: f64f 76ff movw r6, #65535 ; 0xffff + 2154a: f2c0 061f movt r6, #31 + 2154e: e9cd 232c strd r2, r3, [sp, #176] ; 0xb0 + 21552: 9b35 ldr r3, [sp, #212] ; 0xd4 + 21554: 9d1f ldr r5, [sp, #124] ; 0x7c + 21556: ea4f 1bd3 mov.w fp, r3, lsr #7 + 2155a: 9b00 ldr r3, [sp, #0] + 2155c: ea06 060a and.w r6, r6, sl + 21560: fb03 f305 mul.w r3, r3, r5 + 21564: 2500 movs r5, #0 + 21566: 403d ands r5, r7 + 21568: 2700 movs r7, #0 + 2156a: ea07 070b and.w r7, r7, fp + 2156e: e9cd 4502 strd r4, r5, [sp, #8] + 21572: e9cd 671a strd r6, r7, [sp, #104] ; 0x68 + 21576: ac44 add r4, sp, #272 ; 0x110 + 21578: f89c 6017 ldrb.w r6, [ip, #23] + 2157c: e9d4 ab00 ldrd sl, fp, [r4] + 21580: 2700 movs r7, #0 + 21582: e9dd 450e ldrd r4, r5, [sp, #56] ; 0x38 + 21586: ea4a 0a04 orr.w sl, sl, r4 + 2158a: ea4b 0b05 orr.w fp, fp, r5 + 2158e: ad44 add r5, sp, #272 ; 0x110 + 21590: e9c5 ab00 strd sl, fp, [r5] + 21594: 9912 ldr r1, [sp, #72] ; 0x48 + 21596: 9d1f ldr r5, [sp, #124] ; 0x7c + 21598: e9cd 671c strd r6, r7, [sp, #112] ; 0x70 + 2159c: f8dd a078 ldr.w sl, [sp, #120] ; 0x78 + 215a0: 9f01 ldr r7, [sp, #4] + 215a2: fb01 f105 mul.w r1, r1, r5 + 215a6: fb0a 3307 mla r3, sl, r7, r3 + 215aa: f8dd b04c ldr.w fp, [sp, #76] ; 0x4c + 215ae: 9332 str r3, [sp, #200] ; 0xc8 + 215b0: fb0a 110b mla r1, sl, fp, r1 + 215b4: 9b3e ldr r3, [sp, #248] ; 0xf8 + 215b6: f8dd b118 ldr.w fp, [sp, #280] ; 0x118 + 215ba: 9f3e ldr r7, [sp, #248] ; 0xf8 + 215bc: 9c52 ldr r4, [sp, #328] ; 0x148 + 215be: f8dd a148 ldr.w sl, [sp, #328] ; 0x148 + 215c2: 0e1b lsrs r3, r3, #24 + 215c4: ea4f 2b0b mov.w fp, fp, lsl #8 + 215c8: 9337 str r3, [sp, #220] ; 0xdc + 215ca: f8cd b0e8 str.w fp, [sp, #232] ; 0xe8 + 215ce: 9b60 ldr r3, [sp, #384] ; 0x180 + 215d0: ea4f 1bd8 mov.w fp, r8, lsr #7 + 215d4: f8cd b028 str.w fp, [sp, #40] ; 0x28 + 215d8: 0c24 lsrs r4, r4, #16 + 215da: f50d 7bb0 add.w fp, sp, #352 ; 0x160 + 215de: 023f lsls r7, r7, #8 + 215e0: ea4f 4a0a mov.w sl, sl, lsl #16 + 215e4: 943d str r4, [sp, #244] ; 0xf4 + 215e6: 9736 str r7, [sp, #216] ; 0xd8 + 215e8: f8cd a0f0 str.w sl, [sp, #240] ; 0xf0 + 215ec: 041c lsls r4, r3, #16 + 215ee: e9db 2300 ldrd r2, r3, [fp] + 215f2: e9dd ab28 ldrd sl, fp, [sp, #160] ; 0xa0 + 215f6: ea42 020a orr.w r2, r2, sl + 215fa: ea43 030b orr.w r3, r3, fp + 215fe: e9cd 233e strd r2, r3, [sp, #248] ; 0xf8 + 21602: e9dd ab3c ldrd sl, fp, [sp, #240] ; 0xf0 + 21606: e9dd 2336 ldrd r2, r3, [sp, #216] ; 0xd8 + 2160a: ea42 020a orr.w r2, r2, sl + 2160e: ea43 030b orr.w r3, r3, fp + 21612: f50d 7b84 add.w fp, sp, #264 ; 0x108 + 21616: e9cb 2300 strd r2, r3, [fp] + 2161a: 9f04 ldr r7, [sp, #16] + 2161c: 9a1f ldr r2, [sp, #124] ; 0x7c + 2161e: 9b05 ldr r3, [sp, #20] + 21620: fb07 f702 mul.w r7, r7, r2 + 21624: f8dd a078 ldr.w sl, [sp, #120] ; 0x78 + 21628: 9d46 ldr r5, [sp, #280] ; 0x118 + 2162a: 9e60 ldr r6, [sp, #384] ; 0x180 + 2162c: fb0a 7703 mla r7, sl, r3, r7 + 21630: 0e2d lsrs r5, r5, #24 + 21632: f50d 7aa8 add.w sl, sp, #336 ; 0x150 + 21636: 953b str r5, [sp, #236] ; 0xec + 21638: e9da 2300 ldrd r2, r3, [sl] + 2163c: 0c35 lsrs r5, r6, #16 + 2163e: e9dd ab26 ldrd sl, fp, [sp, #152] ; 0x98 + 21642: ea42 020a orr.w r2, r2, sl + 21646: ea43 030b orr.w r3, r3, fp + 2164a: f50d 7b80 add.w fp, sp, #256 ; 0x100 + 2164e: e9cb 2300 strd r2, r3, [fp] + 21652: e9dd 233a ldrd r2, r3, [sp, #232] ; 0xe8 + 21656: f50d 7a9c add.w sl, sp, #312 ; 0x138 + 2165a: 4322 orrs r2, r4 + 2165c: 432b orrs r3, r5 + 2165e: f89c 6001 ldrb.w r6, [ip, #1] + 21662: e9ca 2300 strd r2, r3, [sl] + 21666: f8dd 8078 ldr.w r8, [sp, #120] ; 0x78 + 2166a: 9b00 ldr r3, [sp, #0] + 2166c: f8dd a048 ldr.w sl, [sp, #72] ; 0x48 + 21670: ea4f 12d9 mov.w r2, r9, lsr #7 + 21674: fba3 4508 umull r4, r5, r3, r8 + 21678: 920b str r2, [sp, #44] ; 0x2c + 2167a: fbaa 2308 umull r2, r3, sl, r8 + 2167e: f8dd b028 ldr.w fp, [sp, #40] ; 0x28 + 21682: 440b add r3, r1 + 21684: ea4b 6b49 orr.w fp, fp, r9, lsl #25 + 21688: f8dd 90c8 ldr.w r9, [sp, #200] ; 0xc8 + 2168c: f8cd b028 str.w fp, [sp, #40] ; 0x28 + 21690: 991e ldr r1, [sp, #120] ; 0x78 + 21692: f8dd b010 ldr.w fp, [sp, #16] + 21696: f50d 7abc add.w sl, sp, #376 ; 0x178 + 2169a: 444d add r5, r9 + 2169c: e9da 8900 ldrd r8, r9, [sl] + 216a0: eb18 0804 adds.w r8, r8, r4 + 216a4: eb49 0905 adc.w r9, r9, r5 + 216a8: fbab 4501 umull r4, r5, fp, r1 + 216ac: f50d 7aa0 add.w sl, sp, #320 ; 0x140 + 216b0: a95a add r1, sp, #360 ; 0x168 + 216b2: e9ca 8900 strd r8, r9, [sl] + 216b6: e9d1 ab00 ldrd sl, fp, [r1] + 216ba: f50d 78b8 add.w r8, sp, #368 ; 0x170 + 216be: eb1a 0a02 adds.w sl, sl, r2 + 216c2: eb4b 0b03 adc.w fp, fp, r3 + 216c6: 443d add r5, r7 + 216c8: e9d8 2300 ldrd r2, r3, [r8] + 216cc: 1912 adds r2, r2, r4 + 216ce: 416b adcs r3, r5 + 216d0: f50d 78b0 add.w r8, sp, #352 ; 0x160 + 216d4: e9c8 2300 strd r2, r3, [r8] + 216d8: f64f 72ff movw r2, #65535 ; 0xffff + 216dc: f2c0 021f movt r2, #31 + 216e0: 9d08 ldr r5, [sp, #32] + 216e2: f8dd 8020 ldr.w r8, [sp, #32] + 216e6: 7dec ldrb r4, [r5, #23] + 216e8: a954 add r1, sp, #336 ; 0x150 + 216ea: 2300 movs r3, #0 + 216ec: e9c1 ab00 strd sl, fp, [r1] + 216f0: e9dd ab0a ldrd sl, fp, [sp, #40] ; 0x28 + 216f4: 2500 movs r5, #0 + 216f6: ea0a 0a02 and.w sl, sl, r2 + 216fa: ea0b 0b03 and.w fp, fp, r3 + 216fe: ab56 add r3, sp, #344 ; 0x158 + 21700: e9c3 ab00 strd sl, fp, [r3] + 21704: e9cd 4532 strd r4, r5, [sp, #200] ; 0xc8 + 21708: 9b14 ldr r3, [sp, #80] ; 0x50 + 2170a: f898 4001 ldrb.w r4, [r8, #1] + 2170e: f8dd 9060 ldr.w r9, [sp, #96] ; 0x60 + 21712: f8dd 8050 ldr.w r8, [sp, #80] ; 0x50 + 21716: 0a1b lsrs r3, r3, #8 + 21718: ea4f 6808 mov.w r8, r8, lsl #24 + 2171c: ea4f 1919 mov.w r9, r9, lsr #4 + 21720: 9325 str r3, [sp, #148] ; 0x94 + 21722: f8cd 8090 str.w r8, [sp, #144] ; 0x90 + 21726: f8cd 9018 str.w r9, [sp, #24] + 2172a: f50d 7994 add.w r9, sp, #296 ; 0x128 + 2172e: e9d9 2300 ldrd r2, r3, [r9] + 21732: e9dd 8924 ldrd r8, r9, [sp, #144] ; 0x90 + 21736: ea42 0208 orr.w r2, r2, r8 + 2173a: ea43 0309 orr.w r3, r3, r9 + 2173e: f50d 7890 add.w r8, sp, #288 ; 0x120 + 21742: 992e ldr r1, [sp, #184] ; 0xb8 + 21744: e9cd 2314 strd r2, r3, [sp, #80] ; 0x50 + 21748: e9d8 2300 ldrd r2, r3, [r8] + 2174c: e9dd 890c ldrd r8, r9, [sp, #48] ; 0x30 + 21750: ea42 0208 orr.w r2, r2, r8 + 21754: ea43 0309 orr.w r3, r3, r9 + 21758: f50d 7898 add.w r8, sp, #304 ; 0x130 + 2175c: f50d 7990 add.w r9, sp, #288 ; 0x120 + 21760: e9c9 2300 strd r2, r3, [r9] + 21764: e9d8 2300 ldrd r2, r3, [r8] + 21768: e9dd 891c ldrd r8, r9, [sp, #112] ; 0x70 + 2176c: ea42 0208 orr.w r2, r2, r8 + 21770: ea43 0309 orr.w r3, r3, r9 + 21774: f50d 798c add.w r9, sp, #280 ; 0x118 + 21778: e9c9 2300 strd r2, r3, [r9] + 2177c: f8dd 8040 ldr.w r8, [sp, #64] ; 0x40 + 21780: f8dd 9018 ldr.w r9, [sp, #24] + 21784: ea4f 0a91 mov.w sl, r1, lsr #2 + 21788: 9919 ldr r1, [sp, #100] ; 0x64 + 2178a: 9a2f ldr r2, [sp, #188] ; 0xbc + 2178c: ea49 7901 orr.w r9, r9, r1, lsl #28 + 21790: 0e33 lsrs r3, r6, #24 + 21792: ea4f 4818 mov.w r8, r8, lsr #16 + 21796: f8cd 9018 str.w r9, [sp, #24] + 2179a: 930f str r3, [sp, #60] ; 0x3c + 2179c: f8cd 80ac str.w r8, [sp, #172] ; 0xac + 217a0: ea4a 7a82 orr.w sl, sl, r2, lsl #30 + 217a4: e9dd 8916 ldrd r8, r9, [sp, #88] ; 0x58 + 217a8: e9dd 232c ldrd r2, r3, [sp, #176] ; 0xb0 + 217ac: ea42 0208 orr.w r2, r2, r8 + 217b0: ea43 0309 orr.w r3, r3, r9 + 217b4: e9cd 232c strd r2, r3, [sp, #176] ; 0xb0 + 217b8: f89e 2012 ldrb.w r2, [lr, #18] + 217bc: 2300 movs r3, #0 + 217be: e9cd 2324 strd r2, r3, [sp, #144] ; 0x90 + 217c2: 9b2f ldr r3, [sp, #188] ; 0xbc + 217c4: f89c 201a ldrb.w r2, [ip, #26] + 217c8: ea4f 0b93 mov.w fp, r3, lsr #2 + 217cc: 2300 movs r3, #0 + 217ce: e9cd 2318 strd r2, r3, [sp, #96] ; 0x60 + 217d2: f64f 72ff movw r2, #65535 ; 0xffff + 217d6: f2c0 021f movt r2, #31 + 217da: 9b10 ldr r3, [sp, #64] ; 0x40 + 217dc: ea4f 1911 mov.w r9, r1, lsr #4 + 217e0: 041b lsls r3, r3, #16 + 217e2: f8cd 901c str.w r9, [sp, #28] + 217e6: 932a str r3, [sp, #168] ; 0xa8 + 217e8: ea4f 2906 mov.w r9, r6, lsl #8 + 217ec: 2300 movs r3, #0 + 217ee: f8cd 9038 str.w r9, [sp, #56] ; 0x38 + 217f2: 9f1b ldr r7, [sp, #108] ; 0x6c + 217f4: e9dd 8906 ldrd r8, r9, [sp, #24] + 217f8: 9902 ldr r1, [sp, #8] + 217fa: ea08 0802 and.w r8, r8, r2 + 217fe: ea09 0903 and.w r9, r9, r3 + 21802: e9cd 8906 strd r8, r9, [sp, #24] + 21806: f50d 7888 add.w r8, sp, #272 ; 0x110 + 2180a: fb01 f107 mul.w r1, r1, r7 + 2180e: e9d8 6700 ldrd r6, r7, [r8] + 21812: 087f lsrs r7, r7, #1 + 21814: ea4f 0636 mov.w r6, r6, rrx + 21818: ea02 020a and.w r2, r2, sl + 2181c: e9c8 6700 strd r6, r7, [r8] + 21820: ea03 030b and.w r3, r3, fp + 21824: f89c 601c ldrb.w r6, [ip, #28] + 21828: e9dd ab0e ldrd sl, fp, [sp, #56] ; 0x38 + 2182c: e9cd 2316 strd r2, r3, [sp, #88] ; 0x58 + 21830: e9dd 232a ldrd r2, r3, [sp, #168] ; 0xa8 + 21834: 2700 movs r7, #0 + 21836: ea4a 0a02 orr.w sl, sl, r2 + 2183a: ea4b 0b03 orr.w fp, fp, r3 + 2183e: ab52 add r3, sp, #328 ; 0x148 + 21840: e9c3 ab00 strd sl, fp, [r3] + 21844: e9cd 672a strd r6, r7, [sp, #168] ; 0xa8 + 21848: f8dd a068 ldr.w sl, [sp, #104] ; 0x68 + 2184c: f8dd 900c ldr.w r9, [sp, #12] + 21850: f8dd b008 ldr.w fp, [sp, #8] + 21854: fb0a 1109 mla r1, sl, r9, r1 + 21858: fbab 230a umull r2, r3, fp, sl + 2185c: f89c 801b ldrb.w r8, [ip, #27] + 21860: f8dd a0f8 ldr.w sl, [sp, #248] ; 0xf8 + 21864: 9e28 ldr r6, [sp, #160] ; 0xa0 + 21866: 9f28 ldr r7, [sp, #160] ; 0xa0 + 21868: f04f 0900 mov.w r9, #0 + 2186c: e9cd 892e strd r8, r9, [sp, #184] ; 0xb8 + 21870: 0a36 lsrs r6, r6, #8 + 21872: 063f lsls r7, r7, #24 + 21874: ea4f 089a mov.w r8, sl, lsr #2 + 21878: f50d 7a84 add.w sl, sp, #264 ; 0x108 + 2187c: 963b str r6, [sp, #236] ; 0xec + 2187e: 973a str r7, [sp, #232] ; 0xe8 + 21880: e9da 6700 ldrd r6, r7, [sl] + 21884: e9dd ab30 ldrd sl, fp, [sp, #192] ; 0xc0 + 21888: ea46 060a orr.w r6, r6, sl + 2188c: ea47 070b orr.w r7, r7, fp + 21890: f50d 7b84 add.w fp, sp, #264 ; 0x108 + 21894: e9cb 6700 strd r6, r7, [fp] + 21898: af40 add r7, sp, #256 ; 0x100 + 2189a: e9d7 ab00 ldrd sl, fp, [r7] + 2189e: e9dd 673a ldrd r6, r7, [sp, #232] ; 0xe8 + 218a2: ea4a 0a06 orr.w sl, sl, r6 + 218a6: ea4b 0b07 orr.w fp, fp, r7 + 218aa: e9cd ab3a strd sl, fp, [sp, #232] ; 0xe8 + 218ae: f89c a016 ldrb.w sl, [ip, #22] + 218b2: ae40 add r6, sp, #256 ; 0x100 + 218b4: f04f 0b00 mov.w fp, #0 + 218b8: e9c6 ab00 strd sl, fp, [r6] + 218bc: ae4e add r6, sp, #312 ; 0x138 + 218be: e9d6 ab00 ldrd sl, fp, [r6] + 218c2: e9dd 6732 ldrd r6, r7, [sp, #200] ; 0xc8 + 218c6: ea4a 0a06 orr.w sl, sl, r6 + 218ca: ea4b 0b07 orr.w fp, fp, r7 + 218ce: af4e add r7, sp, #312 ; 0x138 + 218d0: e9c7 ab00 strd sl, fp, [r7] + 218d4: f8dd b098 ldr.w fp, [sp, #152] ; 0x98 + 218d8: 9f3f ldr r7, [sp, #252] ; 0xfc + 218da: ea4f 4b1b mov.w fp, fp, lsr #16 + 218de: ea48 7887 orr.w r8, r8, r7, lsl #30 + 218e2: ea4f 6a14 mov.w sl, r4, lsr #24 + 218e6: f8cd b0f4 str.w fp, [sp, #244] ; 0xf4 + 218ea: 440b add r3, r1 + 218ec: ea4f 0997 mov.w r9, r7, lsr #2 + 218f0: 991b ldr r1, [sp, #108] ; 0x6c + 218f2: 0227 lsls r7, r4, #8 + 218f4: f8dd b098 ldr.w fp, [sp, #152] ; 0x98 + 218f8: 9c04 ldr r4, [sp, #16] + 218fa: ea4f 4b0b mov.w fp, fp, lsl #16 + 218fe: fb04 f401 mul.w r4, r4, r1 + 21902: a950 add r1, sp, #320 ; 0x140 + 21904: f8cd a0d4 str.w sl, [sp, #212] ; 0xd4 + 21908: f8cd b0f0 str.w fp, [sp, #240] ; 0xf0 + 2190c: e9d1 ab00 ldrd sl, fp, [r1] + 21910: eb1a 0a02 adds.w sl, sl, r2 + 21914: f64f 72ff movw r2, #65535 ; 0xffff + 21918: f2c0 021f movt r2, #31 + 2191c: 9d05 ldr r5, [sp, #20] + 2191e: 9e1a ldr r6, [sp, #104] ; 0x68 + 21920: eb4b 0b03 adc.w fp, fp, r3 + 21924: a95a add r1, sp, #360 ; 0x168 + 21926: 9734 str r7, [sp, #208] ; 0xd0 + 21928: 2300 movs r3, #0 + 2192a: e9c1 ab00 strd sl, fp, [r1] + 2192e: f89c a000 ldrb.w sl, [ip] + 21932: fb06 4405 mla r4, r6, r5, r4 + 21936: e9dd 6734 ldrd r6, r7, [sp, #208] ; 0xd0 + 2193a: ea02 0208 and.w r2, r2, r8 + 2193e: ea03 0309 and.w r3, r3, r9 + 21942: a94a add r1, sp, #296 ; 0x128 + 21944: e9dd 893c ldrd r8, r9, [sp, #240] ; 0xf0 + 21948: f04f 0b00 mov.w fp, #0 + 2194c: ea46 0608 orr.w r6, r6, r8 + 21950: ea47 0709 orr.w r7, r7, r9 + 21954: f50d 7998 add.w r9, sp, #304 ; 0x130 + 21958: e9c9 6700 strd r6, r7, [r9] + 2195c: e9c1 ab00 strd sl, fp, [r1] + 21960: 9e1a ldr r6, [sp, #104] ; 0x68 + 21962: f8dd a010 ldr.w sl, [sp, #16] + 21966: ad50 add r5, sp, #320 ; 0x140 + 21968: e9c5 2300 strd r2, r3, [r5] + 2196c: 9912 ldr r1, [sp, #72] ; 0x48 + 2196e: 9a1b ldr r2, [sp, #108] ; 0x6c + 21970: 9d00 ldr r5, [sp, #0] + 21972: fbaa 8906 umull r8, r9, sl, r6 + 21976: fb05 f502 mul.w r5, r5, r2 + 2197a: fb01 f102 mul.w r1, r1, r2 + 2197e: 9b01 ldr r3, [sp, #4] + 21980: 9f13 ldr r7, [sp, #76] ; 0x4c + 21982: 44a1 add r9, r4 + 21984: ac54 add r4, sp, #336 ; 0x150 + 21986: fb06 5503 mla r5, r6, r3, r5 + 2198a: e9d4 2300 ldrd r2, r3, [r4] + 2198e: fb06 1107 mla r1, r6, r7, r1 + 21992: eb12 0208 adds.w r2, r2, r8 + 21996: 9f1a ldr r7, [sp, #104] ; 0x68 + 21998: 9e00 ldr r6, [sp, #0] + 2199a: eb43 0309 adc.w r3, r3, r9 + 2199e: e9c4 2300 strd r2, r3, [r4] + 219a2: fba6 2307 umull r2, r3, r6, r7 + 219a6: f50d 7ab0 add.w sl, sp, #352 ; 0x160 + 219aa: f8dd b048 ldr.w fp, [sp, #72] ; 0x48 + 219ae: e9da 8900 ldrd r8, r9, [sl] + 219b2: 442b add r3, r5 + 219b4: eb18 0802 adds.w r8, r8, r2 + 219b8: eb49 0903 adc.w r9, r9, r3 + 219bc: fbab 2307 umull r2, r3, fp, r7 + 219c0: f8dd b020 ldr.w fp, [sp, #32] + 219c4: e9ca 8900 strd r8, r9, [sl] + 219c8: f50d 78ac add.w r8, sp, #344 ; 0x158 + 219cc: f89b a01a ldrb.w sl, [fp, #26] + 219d0: e9d8 6700 ldrd r6, r7, [r8] + 219d4: 440b add r3, r1 + 219d6: 18b6 adds r6, r6, r2 + 219d8: f04f 0b00 mov.w fp, #0 + 219dc: 415f adcs r7, r3 + 219de: e9cd ab26 strd sl, fp, [sp, #152] ; 0x98 + 219e2: f04f 0a00 mov.w sl, #0 + 219e6: f04f 0b00 mov.w fp, #0 + 219ea: e9c8 6700 strd r6, r7, [r8] + 219ee: 4656 mov r6, sl + 219f0: 465f mov r7, fp + 219f2: 9b08 ldr r3, [sp, #32] + 219f4: 9d08 ldr r5, [sp, #32] + 219f6: e9cd 6710 strd r6, r7, [sp, #64] ; 0x40 + 219fa: 9f24 ldr r7, [sp, #144] ; 0x90 + 219fc: 7f1a ldrb r2, [r3, #28] + 219fe: 7eec ldrb r4, [r5, #27] + 21a00: 2300 movs r3, #0 + 21a02: 2500 movs r5, #0 + 21a04: 0a3f lsrs r7, r7, #8 + 21a06: e9cd 2334 strd r2, r3, [sp, #208] ; 0xd0 + 21a0a: e9cd 453e strd r4, r5, [sp, #248] ; 0xf8 + 21a0e: 970b str r7, [sp, #44] ; 0x2c + 21a10: 9a2a ldr r2, [sp, #168] ; 0xa8 + 21a12: f8dd b090 ldr.w fp, [sp, #144] ; 0x90 + 21a16: f8dd a0b8 ldr.w sl, [sp, #184] ; 0xb8 + 21a1a: f8dd 8060 ldr.w r8, [sp, #96] ; 0x60 + 21a1e: f8dd 90a8 ldr.w r9, [sp, #168] ; 0xa8 + 21a22: 0412 lsls r2, r2, #16 + 21a24: 9236 str r2, [sp, #216] ; 0xd8 + 21a26: 9b2e ldr r3, [sp, #184] ; 0xb8 + 21a28: 9918 ldr r1, [sp, #96] ; 0x60 + 21a2a: 9a08 ldr r2, [sp, #32] + 21a2c: ea4f 6b0b mov.w fp, fp, lsl #24 + 21a30: f8cd b028 str.w fp, [sp, #40] ; 0x28 + 21a34: 9c14 ldr r4, [sp, #80] ; 0x50 + 21a36: f50d 7b90 add.w fp, sp, #288 ; 0x120 + 21a3a: ea4f 2818 mov.w r8, r8, lsr #8 + 21a3e: ea4f 4919 mov.w r9, r9, lsr #16 + 21a42: ea4f 6a1a mov.w sl, sl, lsr #24 + 21a46: f8cd 80e4 str.w r8, [sp, #228] ; 0xe4 + 21a4a: f8cd 90dc str.w r9, [sp, #220] ; 0xdc + 21a4e: f8cd a03c str.w sl, [sp, #60] ; 0x3c + 21a52: e9db 8900 ldrd r8, r9, [fp] + 21a56: 7d92 ldrb r2, [r2, #22] + 21a58: e9dd ab0a ldrd sl, fp, [sp, #40] ; 0x28 + 21a5c: 0609 lsls r1, r1, #24 + 21a5e: ea48 080a orr.w r8, r8, sl + 21a62: ea49 090b orr.w r9, r9, fp + 21a66: 021b lsls r3, r3, #8 + 21a68: 9138 str r1, [sp, #224] ; 0xe0 + 21a6a: 930e str r3, [sp, #56] ; 0x38 + 21a6c: e9cd 892e strd r8, r9, [sp, #184] ; 0xb8 + 21a70: 0966 lsrs r6, r4, #5 + 21a72: f50d 798c add.w r9, sp, #280 ; 0x118 + 21a76: ac5c add r4, sp, #368 ; 0x170 + 21a78: 2300 movs r3, #0 + 21a7a: e9c4 2300 strd r2, r3, [r4] + 21a7e: e9d9 4500 ldrd r4, r5, [r9] + 21a82: e9dd 8938 ldrd r8, r9, [sp, #224] ; 0xe0 + 21a86: ea44 0408 orr.w r4, r4, r8 + 21a8a: f8dd 8020 ldr.w r8, [sp, #32] + 21a8e: ea45 0509 orr.w r5, r5, r9 + 21a92: f898 8000 ldrb.w r8, [r8] + 21a96: f50d 7a8c add.w sl, sp, #280 ; 0x118 + 21a9a: f04f 0900 mov.w r9, #0 + 21a9e: e9ca 8900 strd r8, r9, [sl] + 21aa2: e9dd 230e ldrd r2, r3, [sp, #56] ; 0x38 + 21aa6: f8dd a100 ldr.w sl, [sp, #256] ; 0x100 + 21aaa: f8dd b070 ldr.w fp, [sp, #112] ; 0x70 + 21aae: ea4f 6a1a mov.w sl, sl, lsr #24 + 21ab2: f8cd a0a4 str.w sl, [sp, #164] ; 0xa4 + 21ab6: f64f 7aff movw sl, #65535 ; 0xffff + 21aba: f2c0 0a1f movt sl, #31 + 21abe: e9cd 4538 strd r4, r5, [sp, #224] ; 0xe0 + 21ac2: e9dd 4536 ldrd r4, r5, [sp, #216] ; 0xd8 + 21ac6: ea4f 4b1b mov.w fp, fp, lsr #16 + 21aca: 4322 orrs r2, r4 + 21acc: 432b orrs r3, r5 + 21ace: ad48 add r5, sp, #288 ; 0x120 + 21ad0: f8dd 9054 ldr.w r9, [sp, #84] ; 0x54 + 21ad4: e9c5 2300 strd r2, r3, [r5] + 21ad8: f8cd b0c4 str.w fp, [sp, #196] ; 0xc4 + 21adc: 9c1c ldr r4, [sp, #112] ; 0x70 + 21ade: 9b40 ldr r3, [sp, #256] ; 0x100 + 21ae0: 9d17 ldr r5, [sp, #92] ; 0x5c + 21ae2: 9906 ldr r1, [sp, #24] + 21ae4: 0424 lsls r4, r4, #16 + 21ae6: 9430 str r4, [sp, #192] ; 0xc0 + 21ae8: 021b lsls r3, r3, #8 + 21aea: ac52 add r4, sp, #328 ; 0x148 + 21aec: fb01 f105 mul.w r1, r1, r5 + 21af0: ad4a add r5, sp, #296 ; 0x128 + 21af2: 9328 str r3, [sp, #160] ; 0xa0 + 21af4: e9d4 2300 ldrd r2, r3, [r4] + 21af8: e9d5 4500 ldrd r4, r5, [r5] + 21afc: 4322 orrs r2, r4 + 21afe: 432b orrs r3, r5 + 21b00: ad4a add r5, sp, #296 ; 0x128 + 21b02: e9c5 2300 strd r2, r3, [r5] + 21b06: f50d 7b88 add.w fp, sp, #272 ; 0x110 + 21b0a: 9b16 ldr r3, [sp, #88] ; 0x58 + 21b0c: 9d06 ldr r5, [sp, #24] + 21b0e: ea46 66c9 orr.w r6, r6, r9, lsl #27 + 21b12: ea4f 1759 mov.w r7, r9, lsr #5 + 21b16: e9db 8900 ldrd r8, r9, [fp] + 21b1a: f04f 0b00 mov.w fp, #0 + 21b1e: fba5 4503 umull r4, r5, r5, r3 + 21b22: ea08 080a and.w r8, r8, sl + 21b26: ea09 090b and.w r9, r9, fp + 21b2a: ea0a 0a06 and.w sl, sl, r6 + 21b2e: ea0b 0b07 and.w fp, fp, r7 + 21b32: 9e17 ldr r6, [sp, #92] ; 0x5c + 21b34: 9f00 ldr r7, [sp, #0] + 21b36: e9cd 450c strd r4, r5, [sp, #48] ; 0x30 + 21b3a: fb07 f706 mul.w r7, r7, r6 + 21b3e: 9d01 ldr r5, [sp, #4] + 21b40: 9a07 ldr r2, [sp, #28] + 21b42: fb03 7705 mla r7, r3, r5, r7 + 21b46: fb03 1102 mla r1, r3, r2, r1 + 21b4a: 9752 str r7, [sp, #328] ; 0x148 + 21b4c: 9a3e ldr r2, [sp, #248] ; 0xf8 + 21b4e: 9f34 ldr r7, [sp, #208] ; 0xd0 + 21b50: 9e42 ldr r6, [sp, #264] ; 0x108 + 21b52: 9b26 ldr r3, [sp, #152] ; 0x98 + 21b54: e9cd 890a strd r8, r9, [sp, #40] ; 0x28 + 21b58: e9dd 8928 ldrd r8, r9, [sp, #160] ; 0xa0 + 21b5c: e9cd ab14 strd sl, fp, [sp, #80] ; 0x50 + 21b60: e9dd ab30 ldrd sl, fp, [sp, #192] ; 0xc0 + 21b64: ea48 080a orr.w r8, r8, sl + 21b68: ea49 090b orr.w r9, r9, fp + 21b6c: f50d 7b80 add.w fp, sp, #256 ; 0x100 + 21b70: e9cb 8900 strd r8, r9, [fp] + 21b74: ea4f 4a07 mov.w sl, r7, lsl #16 + 21b78: ea4f 4b17 mov.w fp, r7, lsr #16 + 21b7c: ea4f 2802 mov.w r8, r2, lsl #8 + 21b80: 9f3a ldr r7, [sp, #232] ; 0xe8 + 21b82: 08f6 lsrs r6, r6, #3 + 21b84: 9610 str r6, [sp, #64] ; 0x40 + 21b86: ea4f 6912 mov.w r9, r2, lsr #24 + 21b8a: ea48 060a orr.w r6, r8, sl + 21b8e: 061c lsls r4, r3, #24 + 21b90: f50d 7a9c add.w sl, sp, #312 ; 0x138 + 21b94: 097a lsrs r2, r7, #5 + 21b96: ea49 070b orr.w r7, r9, fp + 21b9a: e9da 8900 ldrd r8, r9, [sl] + 21b9e: f8dd b040 ldr.w fp, [sp, #64] ; 0x40 + 21ba2: ea48 0804 orr.w r8, r8, r4 + 21ba6: 9c43 ldr r4, [sp, #268] ; 0x10c + 21ba8: 0a1d lsrs r5, r3, #8 + 21baa: ea49 0905 orr.w r9, r9, r5 + 21bae: ea4b 7b44 orr.w fp, fp, r4, lsl #29 + 21bb2: e9cd 673e strd r6, r7, [sp, #248] ; 0xf8 + 21bb6: e9cd 8936 strd r8, r9, [sp, #216] ; 0xd8 + 21bba: f8cd b040 str.w fp, [sp, #64] ; 0x40 + 21bbe: 9e5c ldr r6, [sp, #368] ; 0x170 + 21bc0: 9f0d ldr r7, [sp, #52] ; 0x34 + 21bc2: 0e36 lsrs r6, r6, #24 + 21bc4: 963d str r6, [sp, #244] ; 0xf4 + 21bc6: 440f add r7, r1 + 21bc8: 9e02 ldr r6, [sp, #8] + 21bca: 9917 ldr r1, [sp, #92] ; 0x5c + 21bcc: 9d3b ldr r5, [sp, #236] ; 0xec + 21bce: fb06 f601 mul.w r6, r6, r1 + 21bd2: ea42 62c5 orr.w r2, r2, r5, lsl #27 + 21bd6: ea4f 08d4 mov.w r8, r4, lsr #3 + 21bda: 096b lsrs r3, r5, #5 + 21bdc: 9c03 ldr r4, [sp, #12] + 21bde: 9d16 ldr r5, [sp, #88] ; 0x58 + 21be0: 970d str r7, [sp, #52] ; 0x34 + 21be2: fb05 6604 mla r6, r5, r4, r6 + 21be6: 9c04 ldr r4, [sp, #16] + 21be8: 9f05 ldr r7, [sp, #20] + 21bea: fb04 f401 mul.w r4, r4, r1 + 21bee: 9912 ldr r1, [sp, #72] ; 0x48 + 21bf0: fb05 4407 mla r4, r5, r7, r4 + 21bf4: 9d17 ldr r5, [sp, #92] ; 0x5c + 21bf6: 9f13 ldr r7, [sp, #76] ; 0x4c + 21bf8: fb01 f105 mul.w r1, r1, r5 + 21bfc: f8cd 8044 str.w r8, [sp, #68] ; 0x44 + 21c00: f8dd a0b4 ldr.w sl, [sp, #180] ; 0xb4 + 21c04: f8dd 8058 ldr.w r8, [sp, #88] ; 0x58 + 21c08: f8dd b170 ldr.w fp, [sp, #368] ; 0x170 + 21c0c: fb08 1107 mla r1, r8, r7, r1 + 21c10: ea4f 0ada mov.w sl, sl, lsr #3 + 21c14: f50d 78b4 add.w r8, sp, #360 ; 0x168 + 21c18: ea4f 2b0b mov.w fp, fp, lsl #8 + 21c1c: f8cd a0c0 str.w sl, [sp, #192] ; 0xc0 + 21c20: f8cd b0f0 str.w fp, [sp, #240] ; 0xf0 + 21c24: e9d8 ab00 ldrd sl, fp, [r8] + 21c28: e9dd 890c ldrd r8, r9, [sp, #48] ; 0x30 + 21c2c: eb1a 0a08 adds.w sl, sl, r8 + 21c30: eb4b 0b09 adc.w fp, fp, r9 + 21c34: f50d 7988 add.w r9, sp, #272 ; 0x110 + 21c38: e9c9 ab00 strd sl, fp, [r9] + 21c3c: f64f 7aff movw sl, #65535 ; 0xffff + 21c40: f2c0 0a1f movt sl, #31 + 21c44: f04f 0b00 mov.w fp, #0 + 21c48: ea0a 0a02 and.w sl, sl, r2 + 21c4c: ea0b 0b03 and.w fp, fp, r3 + 21c50: ad42 add r5, sp, #264 ; 0x108 + 21c52: e9c5 ab00 strd sl, fp, [r5] + 21c56: f50d 7b98 add.w fp, sp, #304 ; 0x130 + 21c5a: f50d 7a8c add.w sl, sp, #280 ; 0x118 + 21c5e: e9db 8900 ldrd r8, r9, [fp] + 21c62: e89a 0c00 ldmia.w sl, {sl, fp} + 21c66: ea48 080a orr.w r8, r8, sl + 21c6a: ea49 090b orr.w r9, r9, fp + 21c6e: e9cd 893a strd r8, r9, [sp, #232] ; 0xe8 + 21c72: f89c 8015 ldrb.w r8, [ip, #21] + 21c76: f04f 0900 mov.w r9, #0 + 21c7a: 9a30 ldr r2, [sp, #192] ; 0xc0 + 21c7c: e9cd 891c strd r8, r9, [sp, #112] ; 0x70 + 21c80: 9d12 ldr r5, [sp, #72] ; 0x48 + 21c82: f8dd 90b0 ldr.w r9, [sp, #176] ; 0xb0 + 21c86: f8dd a0b4 ldr.w sl, [sp, #180] ; 0xb4 + 21c8a: fb05 f502 mul.w r5, r5, r2 + 21c8e: ea4f 09d9 mov.w r9, r9, lsr #3 + 21c92: ea49 794a orr.w r9, r9, sl, lsl #29 + 21c96: f8cd 90a0 str.w r9, [sp, #160] ; 0xa0 + 21c9a: 9b16 ldr r3, [sp, #88] ; 0x58 + 21c9c: 9a00 ldr r2, [sp, #0] + 21c9e: fb09 5507 mla r5, r9, r7, r5 + 21ca2: fba2 8903 umull r8, r9, r2, r3 + 21ca6: aa54 add r2, sp, #336 ; 0x150 + 21ca8: e9d2 ab00 ldrd sl, fp, [r2] + 21cac: eb1a 0a08 adds.w sl, sl, r8 + 21cb0: 4698 mov r8, r3 + 21cb2: 9f52 ldr r7, [sp, #328] ; 0x148 + 21cb4: aa4c add r2, sp, #304 ; 0x130 + 21cb6: 44b9 add r9, r7 + 21cb8: 9f02 ldr r7, [sp, #8] + 21cba: eb4b 0b09 adc.w fp, fp, r9 + 21cbe: e9c2 ab00 strd sl, fp, [r2] + 21cc2: fba7 2303 umull r2, r3, r7, r3 + 21cc6: 9f04 ldr r7, [sp, #16] + 21cc8: 4433 add r3, r6 + 21cca: ae58 add r6, sp, #352 ; 0x160 + 21ccc: e9d6 ab00 ldrd sl, fp, [r6] + 21cd0: eb1a 0a02 adds.w sl, sl, r2 + 21cd4: eb4b 0b03 adc.w fp, fp, r3 + 21cd8: fba7 2308 umull r2, r3, r7, r8 + 21cdc: ae4e add r6, sp, #312 ; 0x138 + 21cde: e9c6 ab00 strd sl, fp, [r6] + 21ce2: 4423 add r3, r4 + 21ce4: 9e12 ldr r6, [sp, #72] ; 0x48 + 21ce6: ac56 add r4, sp, #344 ; 0x158 + 21ce8: e9d4 ab00 ldrd sl, fp, [r4] + 21cec: eb1a 0a02 adds.w sl, sl, r2 + 21cf0: eb4b 0b03 adc.w fp, fp, r3 + 21cf4: fba6 2308 umull r2, r3, r6, r8 + 21cf8: ac46 add r4, sp, #280 ; 0x118 + 21cfa: e9c4 ab00 strd sl, fp, [r4] + 21cfe: f50d 7aa0 add.w sl, sp, #320 ; 0x140 + 21d02: e9da 8900 ldrd r8, r9, [sl] + 21d06: 440b add r3, r1 + 21d08: eb18 0802 adds.w r8, r8, r2 + 21d0c: 9928 ldr r1, [sp, #160] ; 0xa0 + 21d0e: eb49 0903 adc.w r9, r9, r3 + 21d12: f50d 7aa4 add.w sl, sp, #328 ; 0x148 + 21d16: e9ca 8900 strd r8, r9, [sl] + 21d1a: e9dd 2310 ldrd r2, r3, [sp, #64] ; 0x40 + 21d1e: fba6 8901 umull r8, r9, r6, r1 + 21d22: 9e08 ldr r6, [sp, #32] + 21d24: eb12 0208 adds.w r2, r2, r8 + 21d28: 44a9 add r9, r5 + 21d2a: eb43 0309 adc.w r3, r3, r9 + 21d2e: 9938 ldr r1, [sp, #224] ; 0xe0 + 21d30: ac50 add r4, sp, #320 ; 0x140 + 21d32: 7d76 ldrb r6, [r6, #21] + 21d34: e9c4 2300 strd r2, r3, [r4] + 21d38: f50d 78c8 add.w r8, sp, #400 ; 0x190 + 21d3c: 9c39 ldr r4, [sp, #228] ; 0xe4 + 21d3e: f50d 7b90 add.w fp, sp, #288 ; 0x120 + 21d42: 2700 movs r7, #0 + 21d44: e9c8 6700 strd r6, r7, [r8] + 21d48: e9db 8900 ldrd r8, r9, [fp] + 21d4c: e9dd ab18 ldrd sl, fp, [sp, #96] ; 0x60 + 21d50: ea48 080a orr.w r8, r8, sl + 21d54: ea4f 1a51 mov.w sl, r1, lsr #5 + 21d58: ea49 090b orr.w r9, r9, fp + 21d5c: ea4a 6ac4 orr.w sl, sl, r4, lsl #27 + 21d60: ea4f 1b54 mov.w fp, r4, lsr #5 + 21d64: f64f 74ff movw r4, #65535 ; 0xffff + 21d68: f2c0 041f movt r4, #31 + 21d6c: 9f2e ldr r7, [sp, #184] ; 0xb8 + 21d6e: 9b2f ldr r3, [sp, #188] ; 0xbc + 21d70: 09bf lsrs r7, r7, #6 + 21d72: ea47 6283 orr.w r2, r7, r3, lsl #26 + 21d76: 099d lsrs r5, r3, #6 + 21d78: 920e str r2, [sp, #56] ; 0x38 + 21d7a: 950f str r5, [sp, #60] ; 0x3c + 21d7c: 2500 movs r5, #0 + 21d7e: 9f15 ldr r7, [sp, #84] ; 0x54 + 21d80: e9cd 890c strd r8, r9, [sp, #48] ; 0x30 + 21d84: e9dd 890e ldrd r8, r9, [sp, #56] ; 0x38 + 21d88: 9b0a ldr r3, [sp, #40] ; 0x28 + 21d8a: ea08 0804 and.w r8, r8, r4 + 21d8e: ea09 0905 and.w r9, r9, r5 + 21d92: e9cd 890e strd r8, r9, [sp, #56] ; 0x38 + 21d96: f50d 7894 add.w r8, sp, #296 ; 0x128 + 21d9a: fb03 f307 mul.w r3, r3, r7 + 21d9e: e9d8 6700 ldrd r6, r7, [r8] + 21da2: 4026 ands r6, r4 + 21da4: 402f ands r7, r5 + 21da6: e9cd 6710 strd r6, r7, [sp, #64] ; 0x40 + 21daa: 9a15 ldr r2, [sp, #84] ; 0x54 + 21dac: 9902 ldr r1, [sp, #8] + 21dae: ea04 040a and.w r4, r4, sl + 21db2: ea05 050b and.w r5, r5, fp + 21db6: af40 add r7, sp, #256 ; 0x100 + 21db8: fb01 f102 mul.w r1, r1, r2 + 21dbc: e9cd 4518 strd r4, r5, [sp, #96] ; 0x60 + 21dc0: e9d7 4500 ldrd r4, r5, [r7] + 21dc4: e9dd 671c ldrd r6, r7, [sp, #112] ; 0x70 + 21dc8: 4334 orrs r4, r6 + 21dca: 433d orrs r5, r7 + 21dcc: e9cd 452c strd r4, r5, [sp, #176] ; 0xb0 + 21dd0: f8dd 900c ldr.w r9, [sp, #12] + 21dd4: 9d14 ldr r5, [sp, #80] ; 0x50 + 21dd6: 9c0b ldr r4, [sp, #44] ; 0x2c + 21dd8: f8dd b008 ldr.w fp, [sp, #8] + 21ddc: fb05 1109 mla r1, r5, r9, r1 + 21de0: e9dd 8926 ldrd r8, r9, [sp, #152] ; 0x98 + 21de4: fb05 3304 mla r3, r5, r4, r3 + 21de8: fbab ab05 umull sl, fp, fp, r5 + 21dec: 9f06 ldr r7, [sp, #24] + 21dee: 9e0a ldr r6, [sp, #40] ; 0x28 + 21df0: fb07 f702 mul.w r7, r7, r2 + 21df4: 9340 str r3, [sp, #256] ; 0x100 + 21df6: 9138 str r1, [sp, #224] ; 0xe0 + 21df8: fba6 2305 umull r2, r3, r6, r5 + 21dfc: 9915 ldr r1, [sp, #84] ; 0x54 + 21dfe: 9e00 ldr r6, [sp, #0] + 21e00: e9cd ab1c strd sl, fp, [sp, #112] ; 0x70 + 21e04: f8dd b01c ldr.w fp, [sp, #28] + 21e08: fb06 f601 mul.w r6, r6, r1 + 21e0c: fb05 770b mla r7, r5, fp, r7 + 21e10: e9dd 453e ldrd r4, r5, [sp, #248] ; 0xf8 + 21e14: ea44 0408 orr.w r4, r4, r8 + 21e18: ea45 0509 orr.w r5, r5, r9 + 21e1c: f8dd 8050 ldr.w r8, [sp, #80] ; 0x50 + 21e20: e9cd 452e strd r4, r5, [sp, #184] ; 0xb8 + 21e24: 9c01 ldr r4, [sp, #4] + 21e26: 9d04 ldr r5, [sp, #16] + 21e28: fb08 6604 mla r6, r8, r4, r6 + 21e2c: fb05 f501 mul.w r5, r5, r1 + 21e30: 9c04 ldr r4, [sp, #16] + 21e32: 9923 ldr r1, [sp, #140] ; 0x8c + 21e34: f8dd 9014 ldr.w r9, [sp, #20] + 21e38: fb04 f401 mul.w r4, r4, r1 + 21e3c: fb08 5509 mla r5, r8, r9, r5 + 21e40: f8dd 8088 ldr.w r8, [sp, #136] ; 0x88 + 21e44: 9912 ldr r1, [sp, #72] ; 0x48 + 21e46: fb08 4409 mla r4, r8, r9, r4 + 21e4a: 9426 str r4, [sp, #152] ; 0x98 + 21e4c: 9c15 ldr r4, [sp, #84] ; 0x54 + 21e4e: f8dd 804c ldr.w r8, [sp, #76] ; 0x4c + 21e52: fb01 f104 mul.w r1, r1, r4 + 21e56: f8dd 9050 ldr.w r9, [sp, #80] ; 0x50 + 21e5a: f8dd a0d8 ldr.w sl, [sp, #216] ; 0xd8 + 21e5e: f8dd b0dc ldr.w fp, [sp, #220] ; 0xdc + 21e62: fb09 1108 mla r1, r9, r8, r1 + 21e66: ea4f 185a mov.w r8, sl, lsr #5 + 21e6a: ea48 68cb orr.w r8, r8, fp, lsl #27 + 21e6e: f8dd a0e0 ldr.w sl, [sp, #224] ; 0xe0 + 21e72: f8dd b074 ldr.w fp, [sp, #116] ; 0x74 + 21e76: 9c40 ldr r4, [sp, #256] ; 0x100 + 21e78: 44da add sl, fp + 21e7a: f8cd a074 str.w sl, [sp, #116] ; 0x74 + 21e7e: 4423 add r3, r4 + 21e80: 9c37 ldr r4, [sp, #220] ; 0xdc + 21e82: ea4f 1954 mov.w r9, r4, lsr #5 + 21e86: ac44 add r4, sp, #272 ; 0x110 + 21e88: e9d4 ab00 ldrd sl, fp, [r4] + 21e8c: eb1a 0a02 adds.w sl, sl, r2 + 21e90: eb4b 0b03 adc.w fp, fp, r3 + 21e94: ac4a add r4, sp, #296 ; 0x128 + 21e96: aa4c add r2, sp, #304 ; 0x130 + 21e98: e9c4 ab00 strd sl, fp, [r4] + 21e9c: e9d2 ab00 ldrd sl, fp, [r2] + 21ea0: e9dd 231c ldrd r2, r3, [sp, #112] ; 0x70 + 21ea4: eb1a 0a02 adds.w sl, sl, r2 + 21ea8: f64f 72ff movw r2, #65535 ; 0xffff + 21eac: f2c0 021f movt r2, #31 + 21eb0: eb4b 0b03 adc.w fp, fp, r3 + 21eb4: ab40 add r3, sp, #256 ; 0x100 + 21eb6: e9c3 ab00 strd sl, fp, [r3] + 21eba: e9dd ab3a ldrd sl, fp, [sp, #232] ; 0xe8 + 21ebe: 2300 movs r3, #0 + 21ec0: ea0a 0a02 and.w sl, sl, r2 + 21ec4: ea0b 0b03 and.w fp, fp, r3 + 21ec8: ea02 0208 and.w r2, r2, r8 + 21ecc: ea03 0309 and.w r3, r3, r9 + 21ed0: f8dd 8018 ldr.w r8, [sp, #24] + 21ed4: f8dd 9050 ldr.w r9, [sp, #80] ; 0x50 + 21ed8: ac44 add r4, sp, #272 ; 0x110 + 21eda: e9c4 2300 strd r2, r3, [r4] + 21ede: fba8 2309 umull r2, r3, r8, r9 + 21ee2: ac4e add r4, sp, #312 ; 0x138 + 21ee4: 443b add r3, r7 + 21ee6: 9f00 ldr r7, [sp, #0] + 21ee8: e9cd ab38 strd sl, fp, [sp, #224] ; 0xe0 + 21eec: e9d4 ab00 ldrd sl, fp, [r4] + 21ef0: eb1a 0a02 adds.w sl, sl, r2 + 21ef4: eb4b 0b03 adc.w fp, fp, r3 + 21ef8: fba7 2309 umull r2, r3, r7, r9 + 21efc: 464f mov r7, r9 + 21efe: ac48 add r4, sp, #288 ; 0x120 + 21f00: e9c4 ab00 strd sl, fp, [r4] + 21f04: ac46 add r4, sp, #280 ; 0x118 + 21f06: e9d4 ab00 ldrd sl, fp, [r4] + 21f0a: 4433 add r3, r6 + 21f0c: eb1a 0a02 adds.w sl, sl, r2 + 21f10: 9e04 ldr r6, [sp, #16] + 21f12: eb4b 0b03 adc.w fp, fp, r3 + 21f16: e9cd ab3e strd sl, fp, [sp, #248] ; 0xf8 + 21f1a: fba6 2309 umull r2, r3, r6, r9 + 21f1e: f8dd a088 ldr.w sl, [sp, #136] ; 0x88 + 21f22: 442b add r3, r5 + 21f24: fba6 890a umull r8, r9, r6, sl + 21f28: f8dd a048 ldr.w sl, [sp, #72] ; 0x48 + 21f2c: ae52 add r6, sp, #328 ; 0x148 + 21f2e: e9d6 4500 ldrd r4, r5, [r6] + 21f32: fbaa 6707 umull r6, r7, sl, r7 + 21f36: 18a4 adds r4, r4, r2 + 21f38: f8dd b098 ldr.w fp, [sp, #152] ; 0x98 + 21f3c: 415d adcs r5, r3 + 21f3e: e9cd 453a strd r4, r5, [sp, #232] ; 0xe8 + 21f42: ac50 add r4, sp, #320 ; 0x140 + 21f44: e9d4 2300 ldrd r2, r3, [r4] + 21f48: 44d9 add r9, fp + 21f4a: eb12 0208 adds.w r2, r2, r8 + 21f4e: eb43 0309 adc.w r3, r3, r9 + 21f52: 440f add r7, r1 + 21f54: ac4c add r4, sp, #304 ; 0x130 + 21f56: 990c ldr r1, [sp, #48] ; 0x30 + 21f58: e9c4 2300 strd r2, r3, [r4] + 21f5c: f50d 7a84 add.w sl, sp, #264 ; 0x108 + 21f60: 9a0d ldr r2, [sp, #52] ; 0x34 + 21f62: e9da 8900 ldrd r8, r9, [sl] + 21f66: ea4f 0a91 mov.w sl, r1, lsr #2 + 21f6a: ea4a 7a82 orr.w sl, sl, r2, lsl #30 + 21f6e: ea4f 0b92 mov.w fp, r2, lsr #2 + 21f72: f64f 72ff movw r2, #65535 ; 0xffff + 21f76: f2c0 021f movt r2, #31 + 21f7a: ea02 020a and.w r2, r2, sl + 21f7e: f64f 7aff movw sl, #65535 ; 0xffff + 21f82: f2c0 0a1f movt sl, #31 + 21f86: eb18 0806 adds.w r8, r8, r6 + 21f8a: 9b11 ldr r3, [sp, #68] ; 0x44 + 21f8c: eb49 0907 adc.w r9, r9, r7 + 21f90: 9c06 ldr r4, [sp, #24] + 21f92: 9d0a ldr r5, [sp, #40] ; 0x28 + 21f94: 990e ldr r1, [sp, #56] ; 0x38 + 21f96: 9f02 ldr r7, [sp, #8] + 21f98: 9e00 ldr r6, [sp, #0] + 21f9a: e9cd 8936 strd r8, r9, [sp, #216] ; 0xd8 + 21f9e: fb01 f103 mul.w r1, r1, r3 + 21fa2: fb04 f903 mul.w r9, r4, r3 + 21fa6: fb05 f803 mul.w r8, r5, r3 + 21faa: fb07 f703 mul.w r7, r7, r3 + 21fae: fb06 f603 mul.w r6, r6, r3 + 21fb2: 2300 movs r3, #0 + 21fb4: ea03 030b and.w r3, r3, fp + 21fb8: f04f 0b00 mov.w fp, #0 + 21fbc: e9cd 2326 strd r2, r3, [sp, #152] ; 0x98 + 21fc0: e9dd 452c ldrd r4, r5, [sp, #176] ; 0xb0 + 21fc4: ea04 040a and.w r4, r4, sl + 21fc8: ea05 050b and.w r5, r5, fp + 21fcc: e9cd 451c strd r4, r5, [sp, #112] ; 0x70 + 21fd0: 9b21 ldr r3, [sp, #132] ; 0x84 + 21fd2: 9c00 ldr r4, [sp, #0] + 21fd4: f8dd b040 ldr.w fp, [sp, #64] ; 0x40 + 21fd8: 9a11 ldr r2, [sp, #68] ; 0x44 + 21fda: 9d04 ldr r5, [sp, #16] + 21fdc: fb04 f403 mul.w r4, r4, r3 + 21fe0: 9b0e ldr r3, [sp, #56] ; 0x38 + 21fe2: f8dd a03c ldr.w sl, [sp, #60] ; 0x3c + 21fe6: fb05 f502 mul.w r5, r5, r2 + 21fea: fba3 230b umull r2, r3, r3, fp + 21fee: fb0b 110a mla r1, fp, sl, r1 + 21ff2: e9cd 230c strd r2, r3, [sp, #48] ; 0x30 + 21ff6: 9b07 ldr r3, [sp, #28] + 21ff8: 9142 str r1, [sp, #264] ; 0x108 + 21ffa: fb0b 9903 mla r9, fp, r3, r9 + 21ffe: 9906 ldr r1, [sp, #24] + 22000: 9b10 ldr r3, [sp, #64] ; 0x40 + 22002: fba1 ab0b umull sl, fp, r1, fp + 22006: 4619 mov r1, r3 + 22008: 9a0b ldr r2, [sp, #44] ; 0x2c + 2200a: 44cb add fp, r9 + 2200c: fb03 8802 mla r8, r3, r2, r8 + 22010: 9a01 ldr r2, [sp, #4] + 22012: f8cd 8140 str.w r8, [sp, #320] ; 0x140 + 22016: f8dd 800c ldr.w r8, [sp, #12] + 2201a: fb03 6602 mla r6, r3, r2, r6 + 2201e: fb03 7708 mla r7, r3, r8, r7 + 22022: 9b05 ldr r3, [sp, #20] + 22024: f8dd 8080 ldr.w r8, [sp, #128] ; 0x80 + 22028: fb01 5503 mla r5, r1, r3, r5 + 2202c: fb08 4402 mla r4, r8, r2, r4 + 22030: 9912 ldr r1, [sp, #72] ; 0x48 + 22032: 9a11 ldr r2, [sp, #68] ; 0x44 + 22034: 9b13 ldr r3, [sp, #76] ; 0x4c + 22036: fb01 f102 mul.w r1, r1, r2 + 2203a: 9454 str r4, [sp, #336] ; 0x150 + 2203c: 9c10 ldr r4, [sp, #64] ; 0x40 + 2203e: 954e str r5, [sp, #312] ; 0x138 + 22040: fb04 1103 mla r1, r4, r3, r1 + 22044: 9d19 ldr r5, [sp, #100] ; 0x64 + 22046: 912c str r1, [sp, #176] ; 0xb0 + 22048: 9912 ldr r1, [sp, #72] ; 0x48 + 2204a: 9a18 ldr r2, [sp, #96] ; 0x60 + 2204c: fb01 f105 mul.w r1, r1, r5 + 22050: fb02 1103 mla r1, r2, r3, r1 + 22054: 9c2e ldr r4, [sp, #184] ; 0xb8 + 22056: 9156 str r1, [sp, #344] ; 0x158 + 22058: f8dd 8108 ldr.w r8, [sp, #264] ; 0x108 + 2205c: 990d ldr r1, [sp, #52] ; 0x34 + 2205e: 9d2f ldr r5, [sp, #188] ; 0xbc + 22060: 4488 add r8, r1 + 22062: 08a2 lsrs r2, r4, #2 + 22064: ac4a add r4, sp, #296 ; 0x128 + 22066: f8cd 8034 str.w r8, [sp, #52] ; 0x34 + 2206a: ea42 7285 orr.w r2, r2, r5, lsl #30 + 2206e: e9d4 8900 ldrd r8, r9, [r4] + 22072: 08ab lsrs r3, r5, #2 + 22074: e9dd 450c ldrd r4, r5, [sp, #48] ; 0x30 + 22078: eb18 0804 adds.w r8, r8, r4 + 2207c: f64f 74ff movw r4, #65535 ; 0xffff + 22080: f2c0 041f movt r4, #31 + 22084: eb49 0905 adc.w r9, r9, r5 + 22088: a940 add r1, sp, #256 ; 0x100 + 2208a: ad46 add r5, sp, #280 ; 0x118 + 2208c: e9c5 8900 strd r8, r9, [r5] + 22090: e9d1 8900 ldrd r8, r9, [r1] + 22094: 2500 movs r5, #0 + 22096: eb18 080a adds.w r8, r8, sl + 2209a: eb49 090b adc.w r9, r9, fp + 2209e: a952 add r1, sp, #328 ; 0x148 + 220a0: 4014 ands r4, r2 + 220a2: 401d ands r5, r3 + 220a4: e9c1 8900 strd r8, r9, [r1] + 220a8: e9cd 450c strd r4, r5, [sp, #48] ; 0x30 + 220ac: f8dd 8040 ldr.w r8, [sp, #64] ; 0x40 + 220b0: 9d0a ldr r5, [sp, #40] ; 0x28 + 220b2: f8dd 9140 ldr.w r9, [sp, #320] ; 0x140 + 220b6: fba5 2308 umull r2, r3, r5, r8 + 220ba: 4645 mov r5, r8 + 220bc: 9c02 ldr r4, [sp, #8] + 220be: a948 add r1, sp, #288 ; 0x120 + 220c0: e9d1 ab00 ldrd sl, fp, [r1] + 220c4: 444b add r3, r9 + 220c6: eb1a 0a02 adds.w sl, sl, r2 + 220ca: eb4b 0b03 adc.w fp, fp, r3 + 220ce: fba4 2308 umull r2, r3, r4, r8 + 220d2: e9dd 893e ldrd r8, r9, [sp, #248] ; 0xf8 + 220d6: a95c add r1, sp, #368 ; 0x170 + 220d8: e9c1 ab00 strd sl, fp, [r1] + 220dc: f8dd b000 ldr.w fp, [sp] + 220e0: eb18 0802 adds.w r8, r8, r2 + 220e4: 443b add r3, r7 + 220e6: eb49 0903 adc.w r9, r9, r3 + 220ea: fbab 2305 umull r2, r3, fp, r5 + 220ee: 9c04 ldr r4, [sp, #16] + 220f0: 9920 ldr r1, [sp, #128] ; 0x80 + 220f2: f50d 7ab4 add.w sl, sp, #360 ; 0x168 + 220f6: e9ca 8900 strd r8, r9, [sl] + 220fa: e9dd 893a ldrd r8, r9, [sp, #232] ; 0xe8 + 220fe: 4433 add r3, r6 + 22100: eb18 0802 adds.w r8, r8, r2 + 22104: fba4 6705 umull r6, r7, r4, r5 + 22108: eb49 0903 adc.w r9, r9, r3 + 2210c: fbab 2301 umull r2, r3, fp, r1 + 22110: f50d 7a94 add.w sl, sp, #296 ; 0x128 + 22114: 9d4e ldr r5, [sp, #312] ; 0x138 + 22116: e9ca 8900 strd r8, r9, [sl] + 2211a: 9c54 ldr r4, [sp, #336] ; 0x150 + 2211c: f8dd 8048 ldr.w r8, [sp, #72] ; 0x48 + 22120: f8dd 9040 ldr.w r9, [sp, #64] ; 0x40 + 22124: 442f add r7, r5 + 22126: 4423 add r3, r4 + 22128: fba8 4509 umull r4, r5, r8, r9 + 2212c: e9dd 8936 ldrd r8, r9, [sp, #216] ; 0xd8 + 22130: f8dd b048 ldr.w fp, [sp, #72] ; 0x48 + 22134: 9918 ldr r1, [sp, #96] ; 0x60 + 22136: eb18 0806 adds.w r8, r8, r6 + 2213a: f8dd a0b0 ldr.w sl, [sp, #176] ; 0xb0 + 2213e: eb49 0907 adc.w r9, r9, r7 + 22142: fbab 6701 umull r6, r7, fp, r1 + 22146: 4455 add r5, sl + 22148: f50d 7ab0 add.w sl, sp, #352 ; 0x160 + 2214c: e9ca 8900 strd r8, r9, [sl] + 22150: e9dd ab38 ldrd sl, fp, [sp, #224] ; 0xe0 + 22154: f8dd 8158 ldr.w r8, [sp, #344] ; 0x158 + 22158: eb1a 0a04 adds.w sl, sl, r4 + 2215c: 4447 add r7, r8 + 2215e: f50d 7898 add.w r8, sp, #304 ; 0x130 + 22162: eb4b 0b05 adc.w fp, fp, r5 + 22166: a948 add r1, sp, #288 ; 0x120 + 22168: e9d8 4500 ldrd r4, r5, [r8] + 2216c: f50d 7988 add.w r9, sp, #272 ; 0x110 + 22170: 18a4 adds r4, r4, r2 + 22172: e9c1 ab00 strd sl, fp, [r1] + 22176: 415d adcs r5, r3 + 22178: f8dd a048 ldr.w sl, [sp, #72] ; 0x48 + 2217c: e9d9 2300 ldrd r2, r3, [r9] + 22180: 991d ldr r1, [sp, #116] ; 0x74 + 22182: 1992 adds r2, r2, r6 + 22184: 9e04 ldr r6, [sp, #16] + 22186: f8dd b09c ldr.w fp, [sp, #156] ; 0x9c + 2218a: fb06 f601 mul.w r6, r6, r1 + 2218e: 4651 mov r1, sl + 22190: f50d 789c add.w r8, sp, #312 ; 0x138 + 22194: e9c8 4500 strd r4, r5, [r8] + 22198: fb0a f80b mul.w r8, sl, fp + 2219c: 417b adcs r3, r7 + 2219e: 9c1d ldr r4, [sp, #116] ; 0x74 + 221a0: 9f26 ldr r7, [sp, #152] ; 0x98 + 221a2: 9d13 ldr r5, [sp, #76] ; 0x4c + 221a4: f8dd b070 ldr.w fp, [sp, #112] ; 0x70 + 221a8: fb07 8805 mla r8, r7, r5, r8 + 221ac: fb01 f104 mul.w r1, r1, r4 + 221b0: fbaa 4507 umull r4, r5, sl, r7 + 221b4: f8dd a014 ldr.w sl, [sp, #20] + 221b8: 4445 add r5, r8 + 221ba: fb0b 690a mla r9, fp, sl, r6 + 221be: 9e13 ldr r6, [sp, #76] ; 0x4c + 221c0: f8dd a010 ldr.w sl, [sp, #16] + 221c4: fb0b 1106 mla r1, fp, r6, r1 + 221c8: fbaa 670b umull r6, r7, sl, fp + 221cc: 444f add r7, r9 + 221ce: f8dd 9048 ldr.w r9, [sp, #72] ; 0x48 + 221d2: fba9 890b umull r8, r9, r9, fp + 221d6: e9cd 893a strd r8, r9, [sp, #232] ; 0xe8 + 221da: e9dd ab0c ldrd sl, fp, [sp, #48] ; 0x30 + 221de: eb14 040a adds.w r4, r4, sl + 221e2: eb45 050b adc.w r5, r5, fp + 221e6: 4489 add r9, r1 + 221e8: eb12 0806 adds.w r8, r2, r6 + 221ec: 9919 ldr r1, [sp, #100] ; 0x64 + 221ee: 9e04 ldr r6, [sp, #16] + 221f0: 9a30 ldr r2, [sp, #192] ; 0xc0 + 221f2: f8cd 90ec str.w r9, [sp, #236] ; 0xec + 221f6: fb06 f601 mul.w r6, r6, r1 + 221fa: eb43 0907 adc.w r9, r3, r7 + 221fe: 9f00 ldr r7, [sp, #0] + 22200: e9cd 890c strd r8, r9, [sp, #48] ; 0x30 + 22204: 9b05 ldr r3, [sp, #20] + 22206: f8dd 8060 ldr.w r8, [sp, #96] ; 0x60 + 2220a: f8dd 9010 ldr.w r9, [sp, #16] + 2220e: fb07 f702 mul.w r7, r7, r2 + 22212: 9904 ldr r1, [sp, #16] + 22214: fb08 6603 mla r6, r8, r3, r6 + 22218: f8dd b004 ldr.w fp, [sp, #4] + 2221c: fb01 f102 mul.w r1, r1, r2 + 22220: fba9 2308 umull r2, r3, r9, r8 + 22224: f8dd 80a0 ldr.w r8, [sp, #160] ; 0xa0 + 22228: 4433 add r3, r6 + 2222a: fb08 7a0b mla sl, r8, fp, r7 + 2222e: f8dd b000 ldr.w fp, [sp] + 22232: f8dd 9014 ldr.w r9, [sp, #20] + 22236: fbab 6708 umull r6, r7, fp, r8 + 2223a: f8dd b010 ldr.w fp, [sp, #16] + 2223e: 4457 add r7, sl + 22240: f8dd a0a0 ldr.w sl, [sp, #160] ; 0xa0 + 22244: fb08 1109 mla r1, r8, r9, r1 + 22248: fbab ab0a umull sl, fp, fp, sl + 2224c: eb12 0804 adds.w r8, r2, r4 + 22250: eb43 0905 adc.w r9, r3, r5 + 22254: e9dd 230c ldrd r2, r3, [sp, #48] ; 0x30 + 22258: 18b6 adds r6, r6, r2 + 2225a: e9cd ab3e strd sl, fp, [sp, #248] ; 0xf8 + 2225e: 415f adcs r7, r3 + 22260: 9c1d ldr r4, [sp, #116] ; 0x74 + 22262: 9b00 ldr r3, [sp, #0] + 22264: 9d23 ldr r5, [sp, #140] ; 0x8c + 22266: 448b add fp, r1 + 22268: 9902 ldr r1, [sp, #8] + 2226a: e9cd 892c strd r8, r9, [sp, #176] ; 0xb0 + 2226e: fb01 f105 mul.w r1, r1, r5 + 22272: fb03 f804 mul.w r8, r3, r4 + 22276: f8dd a070 ldr.w sl, [sp, #112] ; 0x70 + 2227a: 9a22 ldr r2, [sp, #136] ; 0x88 + 2227c: f8dd 9004 ldr.w r9, [sp, #4] + 22280: f8cd b0fc str.w fp, [sp, #252] ; 0xfc + 22284: f8dd b00c ldr.w fp, [sp, #12] + 22288: fb0a 8809 mla r8, sl, r9, r8 + 2228c: fb02 190b mla r9, r2, fp, r1 + 22290: 4619 mov r1, r3 + 22292: fba3 450a umull r4, r5, r3, sl + 22296: 9b23 ldr r3, [sp, #140] ; 0x8c + 22298: f8dd a004 ldr.w sl, [sp, #4] + 2229c: fb01 f103 mul.w r1, r1, r3 + 222a0: f8dd b088 ldr.w fp, [sp, #136] ; 0x88 + 222a4: fb02 110a mla r1, r2, sl, r1 + 222a8: e9dd 232c ldrd r2, r3, [sp, #176] ; 0xb0 + 222ac: f8dd a008 ldr.w sl, [sp, #8] + 222b0: 1912 adds r2, r2, r4 + 222b2: 4445 add r5, r8 + 222b4: 416b adcs r3, r5 + 222b6: f50d 7888 add.w r8, sp, #272 ; 0x110 + 222ba: e9c8 2300 strd r2, r3, [r8] + 222be: fbaa 230b umull r2, r3, sl, fp + 222c2: 18b4 adds r4, r6, r2 + 222c4: 444b add r3, r9 + 222c6: eb47 0503 adc.w r5, r7, r3 + 222ca: f50d 7880 add.w r8, sp, #256 ; 0x100 + 222ce: e9c8 4500 strd r4, r5, [r8] + 222d2: f8dd b000 ldr.w fp, [sp] + 222d6: f8dd a088 ldr.w sl, [sp, #136] ; 0x88 + 222da: aa42 add r2, sp, #264 ; 0x108 + 222dc: fbab ab0a umull sl, fp, fp, sl + 222e0: 9f02 ldr r7, [sp, #8] + 222e2: e9c2 ab00 strd sl, fp, [r2] + 222e6: 448b add fp, r1 + 222e8: 9930 ldr r1, [sp, #192] ; 0xc0 + 222ea: f8dd 900c ldr.w r9, [sp, #12] + 222ee: fb07 f701 mul.w r7, r7, r1 + 222f2: f8dd a0a0 ldr.w sl, [sp, #160] ; 0xa0 + 222f6: f89e 4013 ldrb.w r4, [lr, #19] + 222fa: f89e 8017 ldrb.w r8, [lr, #23] + 222fe: fb0a 7709 mla r7, sl, r9, r7 + 22302: ae54 add r6, sp, #336 ; 0x150 + 22304: 2500 movs r5, #0 + 22306: f04f 0900 mov.w r9, #0 + 2230a: e9c6 4500 strd r4, r5, [r6] + 2230e: e9cd 890c strd r8, r9, [sp, #48] ; 0x30 + 22312: 9e21 ldr r6, [sp, #132] ; 0x84 + 22314: f89e 8016 ldrb.w r8, [lr, #22] + 22318: 9d06 ldr r5, [sp, #24] + 2231a: a94c add r1, sp, #304 ; 0x130 + 2231c: f04f 0900 mov.w r9, #0 + 22320: e9c1 8900 strd r8, r9, [r1] + 22324: fb05 f506 mul.w r5, r5, r6 + 22328: 9902 ldr r1, [sp, #8] + 2232a: f8dd 8080 ldr.w r8, [sp, #128] ; 0x80 + 2232e: f89e 4014 ldrb.w r4, [lr, #20] + 22332: 9750 str r7, [sp, #320] ; 0x140 + 22334: fb01 f106 mul.w r1, r1, r6 + 22338: 9f07 ldr r7, [sp, #28] + 2233a: 9e54 ldr r6, [sp, #336] ; 0x150 + 2233c: f89e 2018 ldrb.w r2, [lr, #24] + 22340: fb08 5507 mla r5, r8, r7, r5 + 22344: f8dd 900c ldr.w r9, [sp, #12] + 22348: 0c27 lsrs r7, r4, #16 + 2234a: 0e36 lsrs r6, r6, #24 + 2234c: 962f str r6, [sp, #188] ; 0xbc + 2234e: 972d str r7, [sp, #180] ; 0xb4 + 22350: 9e02 ldr r6, [sp, #8] + 22352: 9f28 ldr r7, [sp, #160] ; 0xa0 + 22354: f8cd b10c str.w fp, [sp, #268] ; 0x10c + 22358: fb08 1b09 mla fp, r8, r9, r1 + 2235c: 0e11 lsrs r1, r2, #24 + 2235e: 9137 str r1, [sp, #220] ; 0xdc + 22360: 0211 lsls r1, r2, #8 + 22362: fba6 2307 umull r2, r3, r6, r7 + 22366: 9136 str r1, [sp, #216] ; 0xd8 + 22368: 9950 ldr r1, [sp, #320] ; 0x140 + 2236a: f89e a019 ldrb.w sl, [lr, #25] + 2236e: 440b add r3, r1 + 22370: a944 add r1, sp, #272 ; 0x110 + 22372: e9d1 6700 ldrd r6, r7, [r1] + 22376: 18b6 adds r6, r6, r2 + 22378: 415f adcs r7, r3 + 2237a: a950 add r1, sp, #320 ; 0x140 + 2237c: e9c1 6700 strd r6, r7, [r1] + 22380: 9e06 ldr r6, [sp, #24] + 22382: a940 add r1, sp, #256 ; 0x100 + 22384: fba6 2308 umull r2, r3, r6, r8 + 22388: e9d1 6700 ldrd r6, r7, [r1] + 2238c: 442b add r3, r5 + 2238e: 18b6 adds r6, r6, r2 + 22390: 415f adcs r7, r3 + 22392: 9b02 ldr r3, [sp, #8] + 22394: a944 add r1, sp, #272 ; 0x110 + 22396: fba3 2308 umull r2, r3, r3, r8 + 2239a: e9c1 6700 strd r6, r7, [r1] + 2239e: 9f54 ldr r7, [sp, #336] ; 0x150 + 223a0: ea4f 491a mov.w r9, sl, lsr #16 + 223a4: ae40 add r6, sp, #256 ; 0x100 + 223a6: ea4f 480a mov.w r8, sl, lsl #16 + 223aa: 023f lsls r7, r7, #8 + 223ac: ea4f 4a04 mov.w sl, r4, lsl #16 + 223b0: e9c6 2300 strd r2, r3, [r6] + 223b4: 972e str r7, [sp, #184] ; 0xb8 + 223b6: f8cd a0b0 str.w sl, [sp, #176] ; 0xb0 + 223ba: 445b add r3, fp + 223bc: e9dd 672e ldrd r6, r7, [sp, #184] ; 0xb8 + 223c0: 9341 str r3, [sp, #260] ; 0x104 + 223c2: ac5e add r4, sp, #376 ; 0x178 + 223c4: e9dd 2336 ldrd r2, r3, [sp, #216] ; 0xd8 + 223c8: ea42 0208 orr.w r2, r2, r8 + 223cc: ea43 0309 orr.w r3, r3, r9 + 223d0: e9dd 892c ldrd r8, r9, [sp, #176] ; 0xb0 + 223d4: ea46 0608 orr.w r6, r6, r8 + 223d8: ea47 0709 orr.w r7, r7, r9 + 223dc: e9c4 2300 strd r2, r3, [r4] + 223e0: e9cd 672e strd r6, r7, [sp, #184] ; 0xb8 + 223e4: 9a1f ldr r2, [sp, #124] ; 0x7c + 223e6: 9f02 ldr r7, [sp, #8] + 223e8: 990c ldr r1, [sp, #48] ; 0x30 + 223ea: fb07 f702 mul.w r7, r7, r2 + 223ee: 0409 lsls r1, r1, #16 + 223f0: 9b03 ldr r3, [sp, #12] + 223f2: 9c1e ldr r4, [sp, #120] ; 0x78 + 223f4: 9138 str r1, [sp, #224] ; 0xe0 + 223f6: 9d06 ldr r5, [sp, #24] + 223f8: 9923 ldr r1, [sp, #140] ; 0x8c + 223fa: fb04 7703 mla r7, r4, r3, r7 + 223fe: fb05 f501 mul.w r5, r5, r1 + 22402: 9c0a ldr r4, [sp, #40] ; 0x28 + 22404: 991f ldr r1, [sp, #124] ; 0x7c + 22406: 9a07 ldr r2, [sp, #28] + 22408: 9b22 ldr r3, [sp, #136] ; 0x88 + 2240a: f8dd 9030 ldr.w r9, [sp, #48] ; 0x30 + 2240e: fb04 f401 mul.w r4, r4, r1 + 22412: fb03 5502 mla r5, r3, r2, r5 + 22416: f89e 8015 ldrb.w r8, [lr, #21] + 2241a: 9a0b ldr r2, [sp, #44] ; 0x2c + 2241c: 9b1e ldr r3, [sp, #120] ; 0x78 + 2241e: ea4f 4919 mov.w r9, r9, lsr #16 + 22422: f8cd 90e4 str.w r9, [sp, #228] ; 0xe4 + 22426: a956 add r1, sp, #344 ; 0x158 + 22428: f04f 0900 mov.w r9, #0 + 2242c: f89c a01d ldrb.w sl, [ip, #29] + 22430: f89c 601e ldrb.w r6, [ip, #30] + 22434: fb03 4402 mla r4, r3, r2, r4 + 22438: e9c1 8900 strd r8, r9, [r1] + 2243c: 9a1f ldr r2, [sp, #124] ; 0x7c + 2243e: 9906 ldr r1, [sp, #24] + 22440: f8dd 8078 ldr.w r8, [sp, #120] ; 0x78 + 22444: fb01 f102 mul.w r1, r1, r2 + 22448: 9b07 ldr r3, [sp, #28] + 2244a: f8dd 9008 ldr.w r9, [sp, #8] + 2244e: fb08 1b03 mla fp, r8, r3, r1 + 22452: fba9 2308 umull r2, r3, r9, r8 + 22456: a94e add r1, sp, #312 ; 0x138 + 22458: e9d1 8900 ldrd r8, r9, [r1] + 2245c: 443b add r3, r7 + 2245e: eb18 0802 adds.w r8, r8, r2 + 22462: eb49 0903 adc.w r9, r9, r3 + 22466: e9cd 892c strd r8, r9, [sp, #176] ; 0xb0 + 2246a: f8dd 8018 ldr.w r8, [sp, #24] + 2246e: f8dd 9088 ldr.w r9, [sp, #136] ; 0x88 + 22472: a950 add r1, sp, #320 ; 0x140 + 22474: fba8 2309 umull r2, r3, r8, r9 + 22478: e9d1 8900 ldrd r8, r9, [r1] + 2247c: 442b add r3, r5 + 2247e: eb18 0802 adds.w r8, r8, r2 + 22482: eb49 0903 adc.w r9, r9, r3 + 22486: a954 add r1, sp, #336 ; 0x150 + 22488: e9c1 8900 strd r8, r9, [r1] + 2248c: 9d0a ldr r5, [sp, #40] ; 0x28 + 2248e: f8dd 8078 ldr.w r8, [sp, #120] ; 0x78 + 22492: a944 add r1, sp, #272 ; 0x110 + 22494: fba5 2308 umull r2, r3, r5, r8 + 22498: f50d 7888 add.w r8, sp, #272 ; 0x110 + 2249c: 4423 add r3, r4 + 2249e: e9d8 4500 ldrd r4, r5, [r8] + 224a2: 18a4 adds r4, r4, r2 + 224a4: 415d adcs r5, r3 + 224a6: f50d 78a0 add.w r8, sp, #320 ; 0x140 + 224aa: e9c8 4500 strd r4, r5, [r8] + 224ae: 9b06 ldr r3, [sp, #24] + 224b0: 9a1e ldr r2, [sp, #120] ; 0x78 + 224b2: 9c08 ldr r4, [sp, #32] + 224b4: fba3 2302 umull r2, r3, r3, r2 + 224b8: 7f64 ldrb r4, [r4, #29] + 224ba: f50d 789c add.w r8, sp, #312 ; 0x138 + 224be: 2500 movs r5, #0 + 224c0: e9c8 4500 strd r4, r5, [r8] + 224c4: f8dd 8020 ldr.w r8, [sp, #32] + 224c8: e9cd 2336 strd r2, r3, [sp, #216] ; 0xd8 + 224cc: f898 801e ldrb.w r8, [r8, #30] + 224d0: 445b add r3, fp + 224d2: ac5e add r4, sp, #376 ; 0x178 + 224d4: cc30 ldmia r4, {r4, r5} + 224d6: 9337 str r3, [sp, #220] ; 0xdc + 224d8: f04f 0900 mov.w r9, #0 + 224dc: e9dd 230c ldrd r2, r3, [sp, #48] ; 0x30 + 224e0: 4322 orrs r2, r4 + 224e2: 432b orrs r3, r5 + 224e4: ad5e add r5, sp, #376 ; 0x178 + 224e6: e9c1 8900 strd r8, r9, [r1] + 224ea: e9dd 892e ldrd r8, r9, [sp, #184] ; 0xb8 + 224ee: e9c5 2300 strd r2, r3, [r5] + 224f2: e9dd 2324 ldrd r2, r3, [sp, #144] ; 0x90 + 224f6: ea4f 651a mov.w r5, sl, lsr #24 + 224fa: ea49 0903 orr.w r9, r9, r3 + 224fe: 0c33 lsrs r3, r6, #16 + 22500: 431d orrs r5, r3 + 22502: 9906 ldr r1, [sp, #24] + 22504: 9b1b ldr r3, [sp, #108] ; 0x6c + 22506: 9f1a ldr r7, [sp, #104] ; 0x68 + 22508: fb01 f103 mul.w r1, r1, r3 + 2250c: ea48 0802 orr.w r8, r8, r2 + 22510: ea4f 240a mov.w r4, sl, lsl #8 + 22514: 0432 lsls r2, r6, #16 + 22516: f8dd a01c ldr.w sl, [sp, #28] + 2251a: 9e06 ldr r6, [sp, #24] + 2251c: fb07 110a mla r1, r7, sl, r1 + 22520: 4314 orrs r4, r2 + 22522: fba6 2307 umull r2, r3, r6, r7 + 22526: e9dd 672c ldrd r6, r7, [sp, #176] ; 0xb0 + 2252a: 440b add r3, r1 + 2252c: 18b6 adds r6, r6, r2 + 2252e: 415f adcs r7, r3 + 22530: e9cd 6724 strd r6, r7, [sp, #144] ; 0x90 + 22534: 9921 ldr r1, [sp, #132] ; 0x84 + 22536: 9b0a ldr r3, [sp, #40] ; 0x28 + 22538: 9a0b ldr r2, [sp, #44] ; 0x2c + 2253a: fb03 f301 mul.w r3, r3, r1 + 2253e: 9f1b ldr r7, [sp, #108] ; 0x6c + 22540: 9e20 ldr r6, [sp, #128] ; 0x80 + 22542: 990a ldr r1, [sp, #40] ; 0x28 + 22544: f89e a01a ldrb.w sl, [lr, #26] + 22548: fb06 3302 mla r3, r6, r2, r3 + 2254c: fb01 f107 mul.w r1, r1, r7 + 22550: 9e0e ldr r6, [sp, #56] ; 0x38 + 22552: f04f 0b00 mov.w fp, #0 + 22556: e9cd ab2e strd sl, fp, [sp, #184] ; 0xb8 + 2255a: fb06 f607 mul.w r6, r6, r7 + 2255e: f8dd b068 ldr.w fp, [sp, #104] ; 0x68 + 22562: f8dd a03c ldr.w sl, [sp, #60] ; 0x3c + 22566: fb0b 1102 mla r1, fp, r2, r1 + 2256a: 9f20 ldr r7, [sp, #128] ; 0x80 + 2256c: 9a0a ldr r2, [sp, #40] ; 0x28 + 2256e: fb0b 660a mla r6, fp, sl, r6 + 22572: fba2 ab07 umull sl, fp, r2, r7 + 22576: af54 add r7, sp, #336 ; 0x150 + 22578: 449b add fp, r3 + 2257a: e9d7 2300 ldrd r2, r3, [r7] + 2257e: eb12 020a adds.w r2, r2, sl + 22582: eb43 030b adc.w r3, r3, fp + 22586: f8dd a038 ldr.w sl, [sp, #56] ; 0x38 + 2258a: f8dd b068 ldr.w fp, [sp, #104] ; 0x68 + 2258e: af62 add r7, sp, #392 ; 0x188 + 22590: e9c7 2300 strd r2, r3, [r7] + 22594: fbaa 230b umull r2, r3, sl, fp + 22598: f50d 7aa0 add.w sl, sp, #320 ; 0x140 + 2259c: 4433 add r3, r6 + 2259e: e9da 6700 ldrd r6, r7, [sl] + 225a2: 18b6 adds r6, r6, r2 + 225a4: 415f adcs r7, r3 + 225a6: 9b0a ldr r3, [sp, #40] ; 0x28 + 225a8: f50d 7ac0 add.w sl, sp, #384 ; 0x180 + 225ac: fba3 230b umull r2, r3, r3, fp + 225b0: e9cd 230c strd r2, r3, [sp, #48] ; 0x30 + 225b4: 440b add r3, r1 + 225b6: 930d str r3, [sp, #52] ; 0x34 + 225b8: 990a ldr r1, [sp, #40] ; 0x28 + 225ba: 9b17 ldr r3, [sp, #92] ; 0x5c + 225bc: e9ca 6700 strd r6, r7, [sl] + 225c0: e9dd ab2a ldrd sl, fp, [sp, #168] ; 0xa8 + 225c4: fb01 f103 mul.w r1, r1, r3 + 225c8: 9e0b ldr r6, [sp, #44] ; 0x2c + 225ca: ea4a 0a04 orr.w sl, sl, r4 + 225ce: ea4b 0b05 orr.w fp, fp, r5 + 225d2: 9c0a ldr r4, [sp, #40] ; 0x28 + 225d4: 9d16 ldr r5, [sp, #88] ; 0x58 + 225d6: ea4f 07d9 mov.w r7, r9, lsr #3 + 225da: fba4 2305 umull r2, r3, r4, r5 + 225de: fb05 1106 mla r1, r5, r6, r1 + 225e2: e9dd 4524 ldrd r4, r5, [sp, #144] ; 0x90 + 225e6: 440b add r3, r1 + 225e8: 18a4 adds r4, r4, r2 + 225ea: 415d adcs r5, r3 + 225ec: ae54 add r6, sp, #336 ; 0x150 + 225ee: e9c6 4500 strd r4, r5, [r6] + 225f2: 991f ldr r1, [sp, #124] ; 0x7c + 225f4: 9e0e ldr r6, [sp, #56] ; 0x38 + 225f6: f89c 401f ldrb.w r4, [ip, #31] + 225fa: fb06 f601 mul.w r6, r6, r1 + 225fe: 9a0f ldr r2, [sp, #60] ; 0x3c + 22600: 9b1e ldr r3, [sp, #120] ; 0x78 + 22602: ea4f 0cd8 mov.w ip, r8, lsr #3 + 22606: f8dd 805c ldr.w r8, [sp, #92] ; 0x5c + 2260a: fb03 6602 mla r6, r3, r2, r6 + 2260e: 4642 mov r2, r8 + 22610: ea4c 7c49 orr.w ip, ip, r9, lsl #29 + 22614: 972a str r7, [sp, #168] ; 0xa8 + 22616: fb0c f708 mul.w r7, ip, r8 + 2261a: f8dd 9058 ldr.w r9, [sp, #88] ; 0x58 + 2261e: 992a ldr r1, [sp, #168] ; 0xa8 + 22620: 9b0f ldr r3, [sp, #60] ; 0x3c + 22622: fb01 7709 mla r7, r1, r9, r7 + 22626: 990e ldr r1, [sp, #56] ; 0x38 + 22628: f50d 78a0 add.w r8, sp, #320 ; 0x140 + 2262c: fb01 f102 mul.w r1, r1, r2 + 22630: 0622 lsls r2, r4, #24 + 22632: fb09 1103 mla r1, r9, r3, r1 + 22636: 0a23 lsrs r3, r4, #8 + 22638: 9c08 ldr r4, [sp, #32] + 2263a: 2500 movs r5, #0 + 2263c: 7fe4 ldrb r4, [r4, #31] + 2263e: ea4b 0903 orr.w r9, fp, r3 + 22642: e9c8 4500 strd r4, r5, [r8] + 22646: ea4a 0802 orr.w r8, sl, r2 + 2264a: e9cd 892c strd r8, r9, [sp, #176] ; 0xb0 + 2264e: f8dd a078 ldr.w sl, [sp, #120] ; 0x78 + 22652: f8dd 9038 ldr.w r9, [sp, #56] ; 0x38 + 22656: 9b16 ldr r3, [sp, #88] ; 0x58 + 22658: fba9 450a umull r4, r5, r9, sl + 2265c: fbac 8903 umull r8, r9, ip, r3 + 22660: aa62 add r2, sp, #392 ; 0x188 + 22662: e9d2 ab00 ldrd sl, fp, [r2] + 22666: 4435 add r5, r6 + 22668: eb1a 0a04 adds.w sl, sl, r4 + 2266c: ae60 add r6, sp, #384 ; 0x180 + 2266e: eb4b 0b05 adc.w fp, fp, r5 + 22672: 44b9 add r9, r7 + 22674: e9d6 4500 ldrd r4, r5, [r6] + 22678: eb14 0408 adds.w r4, r4, r8 + 2267c: eb45 0509 adc.w r5, r5, r9 + 22680: f8dd 9038 ldr.w r9, [sp, #56] ; 0x38 + 22684: 9a15 ldr r2, [sp, #84] ; 0x54 + 22686: fba9 8903 umull r8, r9, r9, r3 + 2268a: e9cd 8924 strd r8, r9, [sp, #144] ; 0x90 + 2268e: 4489 add r9, r1 + 22690: 990e ldr r1, [sp, #56] ; 0x38 + 22692: e9c6 4500 strd r4, r5, [r6] + 22696: fb01 f102 mul.w r1, r1, r2 + 2269a: 9d14 ldr r5, [sp, #80] ; 0x50 + 2269c: 9c0e ldr r4, [sp, #56] ; 0x38 + 2269e: 9e0f ldr r6, [sp, #60] ; 0x3c + 226a0: fba4 2305 umull r2, r3, r4, r5 + 226a4: fb05 1106 mla r1, r5, r6, r1 + 226a8: 9f15 ldr r7, [sp, #84] ; 0x54 + 226aa: 440b add r3, r1 + 226ac: 991b ldr r1, [sp, #108] ; 0x6c + 226ae: f8cd 9094 str.w r9, [sp, #148] ; 0x94 + 226b2: fb0c f601 mul.w r6, ip, r1 + 226b6: fb0c f107 mul.w r1, ip, r7 + 226ba: f50d 79a8 add.w r9, sp, #336 ; 0x150 + 226be: e9d9 8900 ldrd r8, r9, [r9] + 226c2: 9d2a ldr r5, [sp, #168] ; 0xa8 + 226c4: eb12 0208 adds.w r2, r2, r8 + 226c8: 9c1a ldr r4, [sp, #104] ; 0x68 + 226ca: f8dd 8050 ldr.w r8, [sp, #80] ; 0x50 + 226ce: fb05 6604 mla r6, r5, r4, r6 + 226d2: fb05 1108 mla r1, r5, r8, r1 + 226d6: fbac 4504 umull r4, r5, ip, r4 + 226da: eb43 0309 adc.w r3, r3, r9 + 226de: 4435 add r5, r6 + 226e0: f8dd 9050 ldr.w r9, [sp, #80] ; 0x50 + 226e4: eb1a 0604 adds.w r6, sl, r4 + 226e8: eb4b 0705 adc.w r7, fp, r5 + 226ec: f50d 78c4 add.w r8, sp, #392 ; 0x188 + 226f0: e9c8 6700 strd r6, r7, [r8] + 226f4: fbac 6709 umull r6, r7, ip, r9 + 226f8: f8dd a044 ldr.w sl, [sp, #68] ; 0x44 + 226fc: 440f add r7, r1 + 226fe: fb0c f10a mul.w r1, ip, sl + 22702: f8dd b040 ldr.w fp, [sp, #64] ; 0x40 + 22706: f8dd 80a8 ldr.w r8, [sp, #168] ; 0xa8 + 2270a: fbac 450b umull r4, r5, ip, fp + 2270e: fb08 110b mla r1, r8, fp, r1 + 22712: eb12 0a04 adds.w sl, r2, r4 + 22716: 440d add r5, r1 + 22718: eb43 0b05 adc.w fp, r3, r5 + 2271c: a954 add r1, sp, #336 ; 0x150 + 2271e: e9c1 ab00 strd sl, fp, [r1] + 22722: f64f 7aff movw sl, #65535 ; 0xffff + 22726: f2c0 0a1f movt sl, #31 + 2272a: 9c32 ldr r4, [sp, #200] ; 0xc8 + 2272c: f50d 79c8 add.w r9, sp, #400 ; 0x190 + 22730: 0422 lsls r2, r4, #16 + 22732: 0c23 lsrs r3, r4, #16 + 22734: e9dd 453c ldrd r4, r5, [sp, #240] ; 0xf0 + 22738: 4314 orrs r4, r2 + 2273a: e9d9 8900 ldrd r8, r9, [r9] + 2273e: 431d orrs r5, r3 + 22740: ea44 0408 orr.w r4, r4, r8 + 22744: ea45 0509 orr.w r5, r5, r9 + 22748: f04f 0b00 mov.w fp, #0 + 2274c: ea04 040a and.w r4, r4, sl + 22750: e9dd 233a ldrd r2, r3, [sp, #232] ; 0xe8 + 22754: ea05 050b and.w r5, r5, fp + 22758: 18a4 adds r4, r4, r2 + 2275a: e9dd 893e ldrd r8, r9, [sp, #248] ; 0xf8 + 2275e: 415d adcs r5, r3 + 22760: f50d 7b84 add.w fp, sp, #264 ; 0x108 + 22764: eb14 0408 adds.w r4, r4, r8 + 22768: e9db ab00 ldrd sl, fp, [fp] + 2276c: f8dd 8130 ldr.w r8, [sp, #304] ; 0x130 + 22770: eb45 0509 adc.w r5, r5, r9 + 22774: ab40 add r3, sp, #256 ; 0x100 + 22776: eb14 040a adds.w r4, r4, sl + 2277a: e9d3 2300 ldrd r2, r3, [r3] + 2277e: eb45 050b adc.w r5, r5, fp + 22782: 18a4 adds r4, r4, r2 + 22784: 415d adcs r5, r3 + 22786: ea4f 6b18 mov.w fp, r8, lsr #24 + 2278a: ea4f 2a08 mov.w sl, r8, lsl #8 + 2278e: e9dd 8936 ldrd r8, r9, [sp, #216] ; 0xd8 + 22792: eb14 0408 adds.w r4, r4, r8 + 22796: eb45 0509 adc.w r5, r5, r9 + 2279a: e9dd 890c ldrd r8, r9, [sp, #48] ; 0x30 + 2279e: eb14 0408 adds.w r4, r4, r8 + 227a2: eb45 0509 adc.w r5, r5, r9 + 227a6: f8dd 90b8 ldr.w r9, [sp, #184] ; 0xb8 + 227aa: e9dd 2338 ldrd r2, r3, [sp, #224] ; 0xe0 + 227ae: ea4a 0a02 orr.w sl, sl, r2 + 227b2: ea4b 0b03 orr.w fp, fp, r3 + 227b6: ab56 add r3, sp, #344 ; 0x158 + 227b8: e9d3 2300 ldrd r2, r3, [r3] + 227bc: ea4a 0a02 orr.w sl, sl, r2 + 227c0: ea4b 0b03 orr.w fp, fp, r3 + 227c4: ea4f 6209 mov.w r2, r9, lsl #24 + 227c8: ea4f 2319 mov.w r3, r9, lsr #8 + 227cc: f50d 79bc add.w r9, sp, #376 ; 0x178 + 227d0: e9d9 8900 ldrd r8, r9, [r9] + 227d4: ea42 0208 orr.w r2, r2, r8 + 227d8: f64f 78ff movw r8, #65535 ; 0xffff + 227dc: f2c0 081f movt r8, #31 + 227e0: ea43 0309 orr.w r3, r3, r9 + 227e4: f04f 0900 mov.w r9, #0 + 227e8: ea08 080a and.w r8, r8, sl + 227ec: ea09 090b and.w r9, r9, fp + 227f0: e9cd 8908 strd r8, r9, [sp, #32] + 227f4: e9dd ab24 ldrd sl, fp, [sp, #144] ; 0x90 + 227f8: eb14 040a adds.w r4, r4, sl + 227fc: f64f 7aff movw sl, #65535 ; 0xffff + 22800: f2c0 0a1f movt sl, #31 + 22804: ea4f 1852 mov.w r8, r2, lsr #5 + 22808: 9915 ldr r1, [sp, #84] ; 0x54 + 2280a: ea48 68c3 orr.w r8, r8, r3, lsl #27 + 2280e: ea4f 1953 mov.w r9, r3, lsr #5 + 22812: 9b08 ldr r3, [sp, #32] + 22814: eb45 050b adc.w r5, r5, fp + 22818: fb03 f301 mul.w r3, r3, r1 + 2281c: f04f 0b00 mov.w fp, #0 + 22820: ea0a 0a08 and.w sl, sl, r8 + 22824: ea0b 0b09 and.w fp, fp, r9 + 22828: e9cd ab0c strd sl, fp, [sp, #48] ; 0x30 + 2282c: 9914 ldr r1, [sp, #80] ; 0x50 + 2282e: f8dd b024 ldr.w fp, [sp, #36] ; 0x24 + 22832: 9a08 ldr r2, [sp, #32] + 22834: fb01 330b mla r3, r1, fp, r3 + 22838: fba2 8901 umull r8, r9, r2, r1 + 2283c: a960 add r1, sp, #384 ; 0x180 + 2283e: e9d1 ab00 ldrd sl, fp, [r1] + 22842: 4499 add r9, r3 + 22844: eb1a 0a08 adds.w sl, sl, r8 + 22848: eb4b 0b09 adc.w fp, fp, r9 + 2284c: 19a2 adds r2, r4, r6 + 2284e: eb45 0307 adc.w r3, r5, r7 + 22852: e9cd 2336 strd r2, r3, [sp, #216] ; 0xd8 + 22856: 9c0c ldr r4, [sp, #48] ; 0x30 + 22858: 9b11 ldr r3, [sp, #68] ; 0x44 + 2285a: 9d11 ldr r5, [sp, #68] ; 0x44 + 2285c: fb04 f403 mul.w r4, r4, r3 + 22860: 9b08 ldr r3, [sp, #32] + 22862: f8dd 8040 ldr.w r8, [sp, #64] ; 0x40 + 22866: 9e17 ldr r6, [sp, #92] ; 0x5c + 22868: 9f0d ldr r7, [sp, #52] ; 0x34 + 2286a: f8dd 9030 ldr.w r9, [sp, #48] ; 0x30 + 2286e: 9908 ldr r1, [sp, #32] + 22870: fb03 f305 mul.w r3, r3, r5 + 22874: fb08 4407 mla r4, r8, r7, r4 + 22878: fb01 f106 mul.w r1, r1, r6 + 2287c: fba9 6708 umull r6, r7, r9, r8 + 22880: f8dd 90b4 ldr.w r9, [sp, #180] ; 0xb4 + 22884: e9cd ab3a strd sl, fp, [sp, #232] ; 0xe8 + 22888: 9d08 ldr r5, [sp, #32] + 2288a: f8dd b024 ldr.w fp, [sp, #36] ; 0x24 + 2288e: ea4f 19d9 mov.w r9, r9, lsr #7 + 22892: fb08 3a0b mla sl, r8, fp, r3 + 22896: fba5 2308 umull r2, r3, r5, r8 + 2289a: 464d mov r5, r9 + 2289c: f8dd 8058 ldr.w r8, [sp, #88] ; 0x58 + 228a0: f8cd 90c8 str.w r9, [sp, #200] ; 0xc8 + 228a4: fb08 1b0b mla fp, r8, fp, r1 + 228a8: f8dd 9058 ldr.w r9, [sp, #88] ; 0x58 + 228ac: f8dd 8020 ldr.w r8, [sp, #32] + 228b0: 9912 ldr r1, [sp, #72] ; 0x48 + 228b2: 4427 add r7, r4 + 228b4: fb01 f105 mul.w r1, r1, r5 + 228b8: fba8 4509 umull r4, r5, r8, r9 + 228bc: 4453 add r3, sl + 228be: 445d add r5, fp + 228c0: e9dd ab3a ldrd sl, fp, [sp, #232] ; 0xe8 + 228c4: eb1a 0a06 adds.w sl, sl, r6 + 228c8: eb4b 0b07 adc.w fp, fp, r7 + 228cc: f50d 7880 add.w r8, sp, #256 ; 0x100 + 228d0: 9f2c ldr r7, [sp, #176] ; 0xb0 + 228d2: e9c8 ab00 strd sl, fp, [r8] + 228d6: e9dd ab36 ldrd sl, fp, [sp, #216] ; 0xd8 + 228da: f8dd 80b4 ldr.w r8, [sp, #180] ; 0xb4 + 228de: eb1a 0a02 adds.w sl, sl, r2 + 228e2: ae62 add r6, sp, #392 ; 0x188 + 228e4: eb4b 0b03 adc.w fp, fp, r3 + 228e8: 09ff lsrs r7, r7, #7 + 228ea: e9d6 2300 ldrd r2, r3, [r6] + 228ee: 1912 adds r2, r2, r4 + 228f0: ea47 6748 orr.w r7, r7, r8, lsl #25 + 228f4: 416b adcs r3, r5 + 228f6: e9cd ab38 strd sl, fp, [sp, #224] ; 0xe0 + 228fa: e9cd 2336 strd r2, r3, [sp, #216] ; 0xd8 + 228fe: 9724 str r7, [sp, #144] ; 0x90 + 22900: f8dd 904c ldr.w r9, [sp, #76] ; 0x4c + 22904: f8dd b048 ldr.w fp, [sp, #72] ; 0x48 + 22908: fb07 1109 mla r1, r7, r9, r1 + 2290c: fbab ab07 umull sl, fp, fp, r7 + 22910: 9b04 ldr r3, [sp, #16] + 22912: e9cd ab12 strd sl, fp, [sp, #72] ; 0x48 + 22916: 448b add fp, r1 + 22918: 9927 ldr r1, [sp, #156] ; 0x9c + 2291a: 9a05 ldr r2, [sp, #20] + 2291c: fb03 f301 mul.w r3, r3, r1 + 22920: 9c26 ldr r4, [sp, #152] ; 0x98 + 22922: 9f04 ldr r7, [sp, #16] + 22924: fb04 3302 mla r3, r4, r2, r3 + 22928: fba7 6704 umull r6, r7, r7, r4 + 2292c: e9cd 672c strd r6, r7, [sp, #176] ; 0xb0 + 22930: 441f add r7, r3 + 22932: 972d str r7, [sp, #180] ; 0xb4 + 22934: 9b00 ldr r3, [sp, #0] + 22936: 9f19 ldr r7, [sp, #100] ; 0x64 + 22938: 9a04 ldr r2, [sp, #16] + 2293a: 9932 ldr r1, [sp, #200] ; 0xc8 + 2293c: fb03 f307 mul.w r3, r3, r7 + 22940: f8dd 8004 ldr.w r8, [sp, #4] + 22944: f8dd 9060 ldr.w r9, [sp, #96] ; 0x60 + 22948: fb02 f201 mul.w r2, r2, r1 + 2294c: 9c05 ldr r4, [sp, #20] + 2294e: 9d24 ldr r5, [sp, #144] ; 0x90 + 22950: fb09 3308 mla r3, r9, r8, r3 + 22954: f8dd 8010 ldr.w r8, [sp, #16] + 22958: fb05 2204 mla r2, r5, r4, r2 + 2295c: fba8 6705 umull r6, r7, r8, r5 + 22960: 9d26 ldr r5, [sp, #152] ; 0x98 + 22962: f8dd 9000 ldr.w r9, [sp] + 22966: 46aa mov sl, r5 + 22968: f8dd 8060 ldr.w r8, [sp, #96] ; 0x60 + 2296c: 9900 ldr r1, [sp, #0] + 2296e: fba9 8908 umull r8, r9, r9, r8 + 22972: 4417 add r7, r2 + 22974: 9a27 ldr r2, [sp, #156] ; 0x9c + 22976: e9cd 8904 strd r8, r9, [sp, #16] + 2297a: fb01 f102 mul.w r1, r1, r2 + 2297e: 4499 add r9, r3 + 22980: 9c01 ldr r4, [sp, #4] + 22982: f8cd 9014 str.w r9, [sp, #20] + 22986: f8dd 9000 ldr.w r9, [sp] + 2298a: fb05 1104 mla r1, r5, r4, r1 + 2298e: fba9 2305 umull r2, r3, r9, r5 + 22992: 9c02 ldr r4, [sp, #8] + 22994: 440b add r3, r1 + 22996: 991d ldr r1, [sp, #116] ; 0x74 + 22998: 18b6 adds r6, r6, r2 + 2299a: fb04 f401 mul.w r4, r4, r1 + 2299e: 9a03 ldr r2, [sp, #12] + 229a0: 415f adcs r7, r3 + 229a2: 9b1c ldr r3, [sp, #112] ; 0x70 + 229a4: 9d19 ldr r5, [sp, #100] ; 0x64 + 229a6: fb03 4402 mla r4, r3, r2, r4 + 229aa: 9b02 ldr r3, [sp, #8] + 229ac: f8dd 9060 ldr.w r9, [sp, #96] ; 0x60 + 229b0: fb03 f305 mul.w r3, r3, r5 + 229b4: 9902 ldr r1, [sp, #8] + 229b6: fb09 3802 mla r8, r9, r2, r3 + 229ba: 9a27 ldr r2, [sp, #156] ; 0x9c + 229bc: 9d00 ldr r5, [sp, #0] + 229be: fb01 f102 mul.w r1, r1, r2 + 229c2: 9a32 ldr r2, [sp, #200] ; 0xc8 + 229c4: 9b03 ldr r3, [sp, #12] + 229c6: fb05 f502 mul.w r5, r5, r2 + 229ca: f8dd 9090 ldr.w r9, [sp, #144] ; 0x90 + 229ce: fb0a 1103 mla r1, sl, r3, r1 + 229d2: 9b01 ldr r3, [sp, #4] + 229d4: f8dd a000 ldr.w sl, [sp] + 229d8: fb09 5503 mla r5, r9, r3, r5 + 229dc: f8cd b04c str.w fp, [sp, #76] ; 0x4c + 229e0: fbaa 2309 umull r2, r3, sl, r9 + 229e4: f8dd b008 ldr.w fp, [sp, #8] + 229e8: f8dd a070 ldr.w sl, [sp, #112] ; 0x70 + 229ec: 442b add r3, r5 + 229ee: fbab ab0a umull sl, fp, fp, sl + 229f2: e9cd ab00 strd sl, fp, [sp] + 229f6: 44a3 add fp, r4 + 229f8: f8cd b004 str.w fp, [sp, #4] + 229fc: f8dd 9060 ldr.w r9, [sp, #96] ; 0x60 + 22a00: f8dd b008 ldr.w fp, [sp, #8] + 22a04: f8dd a098 ldr.w sl, [sp, #152] ; 0x98 + 22a08: fbab 4509 umull r4, r5, fp, r9 + 22a0c: 1936 adds r6, r6, r4 + 22a0e: 4445 add r5, r8 + 22a10: 416f adcs r7, r5 + 22a12: fbab 450a umull r4, r5, fp, sl + 22a16: eb12 0804 adds.w r8, r2, r4 + 22a1a: 440d add r5, r1 + 22a1c: 9a06 ldr r2, [sp, #24] + 22a1e: 9930 ldr r1, [sp, #192] ; 0xc0 + 22a20: eb43 0905 adc.w r9, r3, r5 + 22a24: fb02 f201 mul.w r2, r2, r1 + 22a28: 9b07 ldr r3, [sp, #28] + 22a2a: 9c28 ldr r4, [sp, #160] ; 0xa0 + 22a2c: 9d1d ldr r5, [sp, #116] ; 0x74 + 22a2e: fb04 2203 mla r2, r4, r3, r2 + 22a32: 9906 ldr r1, [sp, #24] + 22a34: 9c19 ldr r4, [sp, #100] ; 0x64 + 22a36: 9b06 ldr r3, [sp, #24] + 22a38: fb01 f104 mul.w r1, r1, r4 + 22a3c: fb03 f305 mul.w r3, r3, r5 + 22a40: e9cd 893a strd r8, r9, [sp, #232] ; 0xe8 + 22a44: 9d18 ldr r5, [sp, #96] ; 0x60 + 22a46: f8dd 801c ldr.w r8, [sp, #28] + 22a4a: f8dd 9070 ldr.w r9, [sp, #112] ; 0x70 + 22a4e: fb05 1108 mla r1, r5, r8, r1 + 22a52: fb09 3308 mla r3, r9, r8, r3 + 22a56: f8dd 8018 ldr.w r8, [sp, #24] + 22a5a: f8dd 90a0 ldr.w r9, [sp, #160] ; 0xa0 + 22a5e: fba8 ab09 umull sl, fp, r8, r9 + 22a62: 4493 add fp, r2 + 22a64: 9a1c ldr r2, [sp, #112] ; 0x70 + 22a66: fba8 4502 umull r4, r5, r8, r2 + 22a6a: eb16 0804 adds.w r8, r6, r4 + 22a6e: 441d add r5, r3 + 22a70: eb47 0905 adc.w r9, r7, r5 + 22a74: 9a4e ldr r2, [sp, #312] ; 0x138 + 22a76: 9b44 ldr r3, [sp, #272] ; 0x110 + 22a78: e9cd 893c strd r8, r9, [sp, #240] ; 0xf0 + 22a7c: f8dd 9140 ldr.w r9, [sp, #320] ; 0x140 + 22a80: ea4f 2802 mov.w r8, r2, lsl #8 + 22a84: 041e lsls r6, r3, #16 + 22a86: ea4f 2519 mov.w r5, r9, lsr #8 + 22a8a: ea4f 6409 mov.w r4, r9, lsl #24 + 22a8e: 0c1f lsrs r7, r3, #16 + 22a90: ea4f 6912 mov.w r9, r2, lsr #24 + 22a94: ea46 0608 orr.w r6, r6, r8 + 22a98: ea47 0709 orr.w r7, r7, r9 + 22a9c: e9dd 8934 ldrd r8, r9, [sp, #208] ; 0xd0 + 22aa0: ea46 0608 orr.w r6, r6, r8 + 22aa4: ea47 0709 orr.w r7, r7, r9 + 22aa8: 4334 orrs r4, r6 + 22aaa: 433d orrs r5, r7 + 22aac: 09e2 lsrs r2, r4, #7 + 22aae: ea42 6245 orr.w r2, r2, r5, lsl #25 + 22ab2: e9dd 6712 ldrd r6, r7, [sp, #72] ; 0x48 + 22ab6: 09eb lsrs r3, r5, #7 + 22ab8: 18b6 adds r6, r6, r2 + 22aba: 415f adcs r7, r3 + 22abc: e9dd 232c ldrd r2, r3, [sp, #176] ; 0xb0 + 22ac0: 18b6 adds r6, r6, r2 + 22ac2: e9dd 4504 ldrd r4, r5, [sp, #16] + 22ac6: 415f adcs r7, r3 + 22ac8: 1936 adds r6, r6, r4 + 22aca: e9dd 8900 ldrd r8, r9, [sp] + 22ace: 416f adcs r7, r5 + 22ad0: eb16 0608 adds.w r6, r6, r8 + 22ad4: eb47 0709 adc.w r7, r7, r9 + 22ad8: 9c18 ldr r4, [sp, #96] ; 0x60 + 22ada: f8dd 9018 ldr.w r9, [sp, #24] + 22ade: eb16 080a adds.w r8, r6, sl + 22ae2: fba9 2304 umull r2, r3, r9, r4 + 22ae6: eb47 090b adc.w r9, r7, fp + 22aea: 440b add r3, r1 + 22aec: e9dd 673a ldrd r6, r7, [sp, #232] ; 0xe8 + 22af0: 18b6 adds r6, r6, r2 + 22af2: 415f adcs r7, r3 + 22af4: 9930 ldr r1, [sp, #192] ; 0xc0 + 22af6: 9b0a ldr r3, [sp, #40] ; 0x28 + 22af8: 9c1d ldr r4, [sp, #116] ; 0x74 + 22afa: fb03 f301 mul.w r3, r3, r1 + 22afe: 990a ldr r1, [sp, #40] ; 0x28 + 22b00: e9cd 6700 strd r6, r7, [sp] + 22b04: 9a0a ldr r2, [sp, #40] ; 0x28 + 22b06: 9f23 ldr r7, [sp, #140] ; 0x8c + 22b08: fb01 f104 mul.w r1, r1, r4 + 22b0c: 9d0b ldr r5, [sp, #44] ; 0x2c + 22b0e: f8dd a070 ldr.w sl, [sp, #112] ; 0x70 + 22b12: fb02 f207 mul.w r2, r2, r7 + 22b16: f8dd b028 ldr.w fp, [sp, #40] ; 0x28 + 22b1a: 9e22 ldr r6, [sp, #136] ; 0x88 + 22b1c: 9f28 ldr r7, [sp, #160] ; 0xa0 + 22b1e: fb0a 1105 mla r1, sl, r5, r1 + 22b22: f8dd a0a0 ldr.w sl, [sp, #160] ; 0xa0 + 22b26: fb06 2205 mla r2, r6, r5, r2 + 22b2a: fb07 3305 mla r3, r7, r5, r3 + 22b2e: fbab 450a umull r4, r5, fp, sl + 22b32: fbab 6706 umull r6, r7, fp, r6 + 22b36: f8dd a070 ldr.w sl, [sp, #112] ; 0x70 + 22b3a: 4417 add r7, r2 + 22b3c: 441d add r5, r3 + 22b3e: fbab 230a umull r2, r3, fp, sl + 22b42: eb18 0a06 adds.w sl, r8, r6 + 22b46: eb49 0b07 adc.w fp, r9, r7 + 22b4a: e9cd ab04 strd sl, fp, [sp, #16] + 22b4e: e9dd 673c ldrd r6, r7, [sp, #240] ; 0xf0 + 22b52: e9dd 8900 ldrd r8, r9, [sp] + 22b56: 1936 adds r6, r6, r4 + 22b58: 416f adcs r7, r5 + 22b5a: 440b add r3, r1 + 22b5c: eb18 0802 adds.w r8, r8, r2 + 22b60: 9921 ldr r1, [sp, #132] ; 0x84 + 22b62: 9a0e ldr r2, [sp, #56] ; 0x38 + 22b64: eb49 0903 adc.w r9, r9, r3 + 22b68: 9c23 ldr r4, [sp, #140] ; 0x8c + 22b6a: 9d30 ldr r5, [sp, #192] ; 0xc0 + 22b6c: 9b0e ldr r3, [sp, #56] ; 0x38 + 22b6e: fb02 f201 mul.w r2, r2, r1 + 22b72: 990e ldr r1, [sp, #56] ; 0x38 + 22b74: f89e a01c ldrb.w sl, [lr, #28] + 22b78: fb03 f304 mul.w r3, r3, r4 + 22b7c: fb01 f105 mul.w r1, r1, r5 + 22b80: f04f 0b00 mov.w fp, #0 + 22b84: e9cd 6734 strd r6, r7, [sp, #208] ; 0xd0 + 22b88: e9cd ab12 strd sl, fp, [sp, #72] ; 0x48 + 22b8c: 9e0f ldr r6, [sp, #60] ; 0x3c + 22b8e: 9f20 ldr r7, [sp, #128] ; 0x80 + 22b90: f8dd a088 ldr.w sl, [sp, #136] ; 0x88 + 22b94: f8dd b0a0 ldr.w fp, [sp, #160] ; 0xa0 + 22b98: fb07 2206 mla r2, r7, r6, r2 + 22b9c: fb0a 3306 mla r3, sl, r6, r3 + 22ba0: fb0b 1106 mla r1, fp, r6, r1 + 22ba4: e9dd ab04 ldrd sl, fp, [sp, #16] + 22ba8: 9e0e ldr r6, [sp, #56] ; 0x38 + 22baa: e9cd 893c strd r8, r9, [sp, #240] ; 0xf0 + 22bae: fba6 4507 umull r4, r5, r6, r7 + 22bb2: eb1a 0a04 adds.w sl, sl, r4 + 22bb6: 4415 add r5, r2 + 22bb8: eb4b 0b05 adc.w fp, fp, r5 + 22bbc: e9cd ab00 strd sl, fp, [sp] + 22bc0: 46b3 mov fp, r6 + 22bc2: 9a22 ldr r2, [sp, #136] ; 0x88 + 22bc4: f89e 801b ldrb.w r8, [lr, #27] + 22bc8: fba6 4502 umull r4, r5, r6, r2 + 22bcc: 9e28 ldr r6, [sp, #160] ; 0xa0 + 22bce: 441d add r5, r3 + 22bd0: fbab 2306 umull r2, r3, fp, r6 + 22bd4: e9dd ab34 ldrd sl, fp, [sp, #208] ; 0xd0 + 22bd8: eb1a 0a04 adds.w sl, sl, r4 + 22bdc: eb4b 0b05 adc.w fp, fp, r5 + 22be0: e9cd ab2c strd sl, fp, [sp, #176] ; 0xb0 + 22be4: e9dd 453c ldrd r4, r5, [sp, #240] ; 0xf0 + 22be8: ea4f 6b18 mov.w fp, r8, lsr #24 + 22bec: ea4f 2a08 mov.w sl, r8, lsl #8 + 22bf0: f89e 801d ldrb.w r8, [lr, #29] + 22bf4: f04f 0900 mov.w r9, #0 + 22bf8: e9cd 8904 strd r8, r9, [sp, #16] + 22bfc: f8dd 907c ldr.w r9, [sp, #124] ; 0x7c + 22c00: 440b add r3, r1 + 22c02: fb0c f109 mul.w r1, ip, r9 + 22c06: 18a4 adds r4, r4, r2 + 22c08: 415d adcs r5, r3 + 22c0a: 9a1e ldr r2, [sp, #120] ; 0x78 + 22c0c: 9b2a ldr r3, [sp, #168] ; 0xa8 + 22c0e: e9cd 453c strd r4, r5, [sp, #240] ; 0xf0 + 22c12: fb03 1102 mla r1, r3, r2, r1 + 22c16: 9d12 ldr r5, [sp, #72] ; 0x48 + 22c18: 042e lsls r6, r5, #16 + 22c1a: ea4a 0a06 orr.w sl, sl, r6 + 22c1e: f89e 601e ldrb.w r6, [lr, #30] + 22c22: 9134 str r1, [sp, #208] ; 0xd0 + 22c24: 9c21 ldr r4, [sp, #132] ; 0x84 + 22c26: 0c2f lsrs r7, r5, #16 + 22c28: f8dd 808c ldr.w r8, [sp, #140] ; 0x8c + 22c2c: ea4b 0b07 orr.w fp, fp, r7 + 22c30: fb0c f704 mul.w r7, ip, r4 + 22c34: 9d20 ldr r5, [sp, #128] ; 0x80 + 22c36: fb0c f108 mul.w r1, ip, r8 + 22c3a: fb03 7705 mla r7, r3, r5, r7 + 22c3e: f8dd 9088 ldr.w r9, [sp, #136] ; 0x88 + 22c42: fbac 4502 umull r4, r5, ip, r2 + 22c46: fb03 1109 mla r1, r3, r9, r1 + 22c4a: e9dd 8900 ldrd r8, r9, [sp] + 22c4e: 9b34 ldr r3, [sp, #208] ; 0xd0 + 22c50: eb18 0804 adds.w r8, r8, r4 + 22c54: 441d add r5, r3 + 22c56: eb49 0905 adc.w r9, r9, r5 + 22c5a: e9cd 8900 strd r8, r9, [sp] + 22c5e: e9dd 232c ldrd r2, r3, [sp, #176] ; 0xb0 + 22c62: f8dd 9080 ldr.w r9, [sp, #128] ; 0x80 + 22c66: fbac 4509 umull r4, r5, ip, r9 + 22c6a: e9dd 893c ldrd r8, r9, [sp, #240] ; 0xf0 + 22c6e: 1912 adds r2, r2, r4 + 22c70: 443d add r5, r7 + 22c72: 416b adcs r3, r5 + 22c74: e9cd 2334 strd r2, r3, [sp, #208] ; 0xd0 + 22c78: 9b22 ldr r3, [sp, #136] ; 0x88 + 22c7a: 0432 lsls r2, r6, #16 + 22c7c: fbac 4503 umull r4, r5, ip, r3 + 22c80: eb18 0804 adds.w r8, r8, r4 + 22c84: 440d add r5, r1 + 22c86: 9904 ldr r1, [sp, #16] + 22c88: eb49 0905 adc.w r9, r9, r5 + 22c8c: e9cd 892c strd r8, r9, [sp, #176] ; 0xb0 + 22c90: e9dd 452e ldrd r4, r5, [sp, #184] ; 0xb8 + 22c94: ea4f 6911 mov.w r9, r1, lsr #24 + 22c98: 0c33 lsrs r3, r6, #16 + 22c9a: ea49 0703 orr.w r7, r9, r3 + 22c9e: ea4f 2801 mov.w r8, r1, lsl #8 + 22ca2: 9b08 ldr r3, [sp, #32] + 22ca4: 991f ldr r1, [sp, #124] ; 0x7c + 22ca6: ea48 0602 orr.w r6, r8, r2 + 22caa: e9cd 6704 strd r6, r7, [sp, #16] + 22cae: ea4a 0a04 orr.w sl, sl, r4 + 22cb2: 9f1b ldr r7, [sp, #108] ; 0x6c + 22cb4: 9c21 ldr r4, [sp, #132] ; 0x84 + 22cb6: 9a08 ldr r2, [sp, #32] + 22cb8: fb03 f301 mul.w r3, r3, r1 + 22cbc: 9908 ldr r1, [sp, #32] + 22cbe: fb02 f207 mul.w r2, r2, r7 + 22cc2: fb01 f104 mul.w r1, r1, r4 + 22cc6: 9e1a ldr r6, [sp, #104] ; 0x68 + 22cc8: 9f1e ldr r7, [sp, #120] ; 0x78 + 22cca: ea4b 0b05 orr.w fp, fp, r5 + 22cce: f8dd 8080 ldr.w r8, [sp, #128] ; 0x80 + 22cd2: 9d09 ldr r5, [sp, #36] ; 0x24 + 22cd4: 9c08 ldr r4, [sp, #32] + 22cd6: fb06 2205 mla r2, r6, r5, r2 + 22cda: fb07 3305 mla r3, r7, r5, r3 + 22cde: fb08 1105 mla r1, r8, r5, r1 + 22ce2: fba4 8906 umull r8, r9, r4, r6 + 22ce6: fba4 4507 umull r4, r5, r4, r7 + 22cea: 9e08 ldr r6, [sp, #32] + 22cec: 9f20 ldr r7, [sp, #128] ; 0x80 + 22cee: 4491 add r9, r2 + 22cf0: 441d add r5, r3 + 22cf2: fba6 2307 umull r2, r3, r6, r7 + 22cf6: e9dd 6700 ldrd r6, r7, [sp] + 22cfa: eb16 0608 adds.w r6, r6, r8 + 22cfe: eb47 0709 adc.w r7, r7, r9 + 22d02: e9dd 8934 ldrd r8, r9, [sp, #208] ; 0xd0 + 22d06: eb18 0804 adds.w r8, r8, r4 + 22d0a: eb49 0905 adc.w r9, r9, r5 + 22d0e: 440b add r3, r1 + 22d10: e9dd 452c ldrd r4, r5, [sp, #176] ; 0xb0 + 22d14: 18a4 adds r4, r4, r2 + 22d16: 415d adcs r5, r3 + 22d18: e9cd 6700 strd r6, r7, [sp] + 22d1c: e9cd 892e strd r8, r9, [sp, #184] ; 0xb8 + 22d20: e9cd 4534 strd r4, r5, [sp, #208] ; 0xd0 + 22d24: e9dd 4512 ldrd r4, r5, [sp, #72] ; 0x48 + 22d28: e9dd 8904 ldrd r8, r9, [sp, #16] + 22d2c: ea48 0804 orr.w r8, r8, r4 + 22d30: ea49 0905 orr.w r9, r9, r5 + 22d34: e9cd 8904 strd r8, r9, [sp, #16] + 22d38: f64f 78ff movw r8, #65535 ; 0xffff + 22d3c: f2c0 081f movt r8, #31 + 22d40: ea4f 069a mov.w r6, sl, lsr #2 + 22d44: ea46 768b orr.w r6, r6, fp, lsl #30 + 22d48: ea4f 079b mov.w r7, fp, lsr #2 + 22d4c: f04f 0900 mov.w r9, #0 + 22d50: ea08 0806 and.w r8, r8, r6 + 22d54: ea09 0907 and.w r9, r9, r7 + 22d58: e9cd 8912 strd r8, r9, [sp, #72] ; 0x48 + 22d5c: f8dd 9030 ldr.w r9, [sp, #48] ; 0x30 + 22d60: f8dd a05c ldr.w sl, [sp, #92] ; 0x5c + 22d64: 4649 mov r1, r9 + 22d66: 464b mov r3, r9 + 22d68: 46c8 mov r8, r9 + 22d6a: f89e 201f ldrb.w r2, [lr, #31] + 22d6e: 9c1b ldr r4, [sp, #108] ; 0x6c + 22d70: 9d1f ldr r5, [sp, #124] ; 0x7c + 22d72: fb09 fe0a mul.w lr, r9, sl + 22d76: 9e0d ldr r6, [sp, #52] ; 0x34 + 22d78: 9f16 ldr r7, [sp, #88] ; 0x58 + 22d7a: fb01 f104 mul.w r1, r1, r4 + 22d7e: fb03 f305 mul.w r3, r3, r5 + 22d82: f8dd a078 ldr.w sl, [sp, #120] ; 0x78 + 22d86: fba9 4507 umull r4, r5, r9, r7 + 22d8a: fb07 ee06 mla lr, r7, r6, lr + 22d8e: f8dd 9068 ldr.w r9, [sp, #104] ; 0x68 + 22d92: fb0a 3306 mla r3, sl, r6, r3 + 22d96: fb09 1106 mla r1, r9, r6, r1 + 22d9a: fba8 ab09 umull sl, fp, r8, r9 + 22d9e: 4475 add r5, lr + 22da0: f8dd e054 ldr.w lr, [sp, #84] ; 0x54 + 22da4: 448b add fp, r1 + 22da6: 4671 mov r1, lr + 22da8: f8dd 9078 ldr.w r9, [sp, #120] ; 0x78 + 22dac: fba8 6709 umull r6, r7, r8, r9 + 22db0: e9dd 8900 ldrd r8, r9, [sp] + 22db4: eb18 0804 adds.w r8, r8, r4 + 22db8: eb49 0905 adc.w r9, r9, r5 + 22dbc: e9dd 452e ldrd r4, r5, [sp, #184] ; 0xb8 + 22dc0: eb14 040a adds.w r4, r4, sl + 22dc4: eb45 050b adc.w r5, r5, fp + 22dc8: 441f add r7, r3 + 22dca: e9cd 8900 strd r8, r9, [sp] + 22dce: e9dd 8934 ldrd r8, r9, [sp, #208] ; 0xd0 + 22dd2: e9dd ab04 ldrd sl, fp, [sp, #16] + 22dd6: eb18 0806 adds.w r8, r8, r6 + 22dda: eb49 0907 adc.w r9, r9, r7 + 22dde: e9cd 893c strd r8, r9, [sp, #240] ; 0xf0 + 22de2: 9b12 ldr r3, [sp, #72] ; 0x48 + 22de4: ea4f 2912 mov.w r9, r2, lsr #8 + 22de8: ea4f 6802 mov.w r8, r2, lsl #24 + 22dec: 9a12 ldr r2, [sp, #72] ; 0x48 + 22dee: fb03 f301 mul.w r3, r3, r1 + 22df2: 4611 mov r1, r2 + 22df4: ea4a 0a08 orr.w sl, sl, r8 + 22df8: ea4b 0b09 orr.w fp, fp, r9 + 22dfc: 9f14 ldr r7, [sp, #80] ; 0x50 + 22dfe: e9cd ab04 strd sl, fp, [sp, #16] + 22e02: f8dd a04c ldr.w sl, [sp, #76] ; 0x4c + 22e06: f8dd b030 ldr.w fp, [sp, #48] ; 0x30 + 22e0a: e9cd 452c strd r4, r5, [sp, #176] ; 0xb0 + 22e0e: fb07 330a mla r3, r7, sl, r3 + 22e12: 9c17 ldr r4, [sp, #92] ; 0x5c + 22e14: 9d1b ldr r5, [sp, #108] ; 0x6c + 22e16: fb0b f80e mul.w r8, fp, lr + 22e1a: 9e0d ldr r6, [sp, #52] ; 0x34 + 22e1c: fb02 fe04 mul.w lr, r2, r4 + 22e20: fb01 f105 mul.w r1, r1, r5 + 22e24: fbab 4507 umull r4, r5, fp, r7 + 22e28: 4693 mov fp, r2 + 22e2a: fb07 8806 mla r8, r7, r6, r8 + 22e2e: 9334 str r3, [sp, #208] ; 0xd0 + 22e30: fba2 2307 umull r2, r3, r2, r7 + 22e34: 4657 mov r7, sl + 22e36: f8cd 80b8 str.w r8, [sp, #184] ; 0xb8 + 22e3a: f8dd 8058 ldr.w r8, [sp, #88] ; 0x58 + 22e3e: f8dd 9068 ldr.w r9, [sp, #104] ; 0x68 + 22e42: fb08 ee0a mla lr, r8, sl, lr + 22e46: fbab ab08 umull sl, fp, fp, r8 + 22e4a: f8dd 8048 ldr.w r8, [sp, #72] ; 0x48 + 22e4e: fb09 1107 mla r1, r9, r7, r1 + 22e52: fba8 6709 umull r6, r7, r8, r9 + 22e56: f8dd 90b8 ldr.w r9, [sp, #184] ; 0xb8 + 22e5a: f8dd 80d0 ldr.w r8, [sp, #208] ; 0xd0 + 22e5e: 444d add r5, r9 + 22e60: 4443 add r3, r8 + 22e62: e9dd 8936 ldrd r8, r9, [sp, #216] ; 0xd8 + 22e66: eb18 0804 adds.w r8, r8, r4 + 22e6a: eb49 0905 adc.w r9, r9, r5 + 22e6e: e9cd 892e strd r8, r9, [sp, #184] ; 0xb8 + 22e72: e9dd 4500 ldrd r4, r5, [sp] + 22e76: e9dd 892c ldrd r8, r9, [sp, #176] ; 0xb0 + 22e7a: 18a4 adds r4, r4, r2 + 22e7c: 415d adcs r5, r3 + 22e7e: 44f3 add fp, lr + 22e80: eb18 080a adds.w r8, r8, sl + 22e84: 9a11 ldr r2, [sp, #68] ; 0x44 + 22e86: eb49 090b adc.w r9, r9, fp + 22e8a: 440f add r7, r1 + 22e8c: e9dd ab3c ldrd sl, fp, [sp, #240] ; 0xf0 + 22e90: 9912 ldr r1, [sp, #72] ; 0x48 + 22e92: eb1a 0a06 adds.w sl, sl, r6 + 22e96: eb4b 0b07 adc.w fp, fp, r7 + 22e9a: e9cd 8936 strd r8, r9, [sp, #216] ; 0xd8 + 22e9e: e9cd ab3c strd sl, fp, [sp, #240] ; 0xf0 + 22ea2: fb01 f802 mul.w r8, r1, r2 + 22ea6: f8dd b010 ldr.w fp, [sp, #16] + 22eaa: f8dd e014 ldr.w lr, [sp, #20] + 22eae: e9cd 4534 strd r4, r5, [sp, #208] ; 0xd0 + 22eb2: f8dd a04c ldr.w sl, [sp, #76] ; 0x4c + 22eb6: 9d17 ldr r5, [sp, #92] ; 0x5c + 22eb8: ea4f 19db mov.w r9, fp, lsr #7 + 22ebc: f8dd b040 ldr.w fp, [sp, #64] ; 0x40 + 22ec0: ea49 694e orr.w r9, r9, lr, lsl #25 + 22ec4: fb0b 880a mla r8, fp, sl, r8 + 22ec8: fb09 f705 mul.w r7, r9, r5 + 22ecc: 9d05 ldr r5, [sp, #20] + 22ece: 9c15 ldr r4, [sp, #84] ; 0x54 + 22ed0: fb09 f302 mul.w r3, r9, r2 + 22ed4: 09ed lsrs r5, r5, #7 + 22ed6: 9504 str r5, [sp, #16] + 22ed8: fb09 fe04 mul.w lr, r9, r4 + 22edc: 9a06 ldr r2, [sp, #24] + 22ede: 9c27 ldr r4, [sp, #156] ; 0x9c + 22ee0: f8cd 80e8 str.w r8, [sp, #232] ; 0xe8 + 22ee4: f8dd 8010 ldr.w r8, [sp, #16] + 22ee8: 9e02 ldr r6, [sp, #8] + 22eea: 9932 ldr r1, [sp, #200] ; 0xc8 + 22eec: fb08 330b mla r3, r8, fp, r3 + 22ef0: fb02 f204 mul.w r2, r2, r4 + 22ef4: fb06 f601 mul.w r6, r6, r1 + 22ef8: 9912 ldr r1, [sp, #72] ; 0x48 + 22efa: 9242 str r2, [sp, #264] ; 0x108 + 22efc: fba1 450b umull r4, r5, r1, fp + 22f00: 932c str r3, [sp, #176] ; 0xb0 + 22f02: fba9 230b umull r2, r3, r9, fp + 22f06: f8dd b050 ldr.w fp, [sp, #80] ; 0x50 + 22f0a: 9916 ldr r1, [sp, #88] ; 0x58 + 22f0c: fb08 ee0b mla lr, r8, fp, lr + 22f10: fba9 ab0b umull sl, fp, r9, fp + 22f14: e9cd ab3e strd sl, fp, [sp, #248] ; 0xf8 + 22f18: fba9 ab01 umull sl, fp, r9, r1 + 22f1c: fb08 7701 mla r7, r8, r1, r7 + 22f20: e9cd ab00 strd sl, fp, [sp] + 22f24: f8dd 8090 ldr.w r8, [sp, #144] ; 0x90 + 22f28: f8dd b008 ldr.w fp, [sp, #8] + 22f2c: 9903 ldr r1, [sp, #12] + 22f2e: fbab ab08 umull sl, fp, fp, r8 + 22f32: fb08 6601 mla r6, r8, r1, r6 + 22f36: e9cd ab02 strd sl, fp, [sp, #8] + 22f3a: f8dd 8098 ldr.w r8, [sp, #152] ; 0x98 + 22f3e: f8dd b01c ldr.w fp, [sp, #28] + 22f42: f8dd a108 ldr.w sl, [sp, #264] ; 0x108 + 22f46: fb08 a10b mla r1, r8, fp, sl + 22f4a: f8dd b018 ldr.w fp, [sp, #24] + 22f4e: fbab ab08 umull sl, fp, fp, r8 + 22f52: e9cd ab10 strd sl, fp, [sp, #64] ; 0x40 + 22f56: f8dd b0e8 ldr.w fp, [sp, #232] ; 0xe8 + 22f5a: f8dd a0fc ldr.w sl, [sp, #252] ; 0xfc + 22f5e: 445d add r5, fp + 22f60: 44f2 add sl, lr + 22f62: f8dd b004 ldr.w fp, [sp, #4] + 22f66: f8dd e00c ldr.w lr, [sp, #12] + 22f6a: f8dd 80b0 ldr.w r8, [sp, #176] ; 0xb0 + 22f6e: 44bb add fp, r7 + 22f70: 44b6 add lr, r6 + 22f72: 9e11 ldr r6, [sp, #68] ; 0x44 + 22f74: f8cd a0fc str.w sl, [sp, #252] ; 0xfc + 22f78: f8cd b004 str.w fp, [sp, #4] + 22f7c: e9dd ab2e ldrd sl, fp, [sp, #184] ; 0xb8 + 22f80: eb1a 0a04 adds.w sl, sl, r4 + 22f84: eb4b 0b05 adc.w fp, fp, r5 + 22f88: 4443 add r3, r8 + 22f8a: e9dd 4534 ldrd r4, r5, [sp, #208] ; 0xd0 + 22f8e: 440e add r6, r1 + 22f90: 18a4 adds r4, r4, r2 + 22f92: 9611 str r6, [sp, #68] ; 0x44 + 22f94: 415d adcs r5, r3 + 22f96: e9dd 6736 ldrd r6, r7, [sp, #216] ; 0xd8 + 22f9a: e9cd ab14 strd sl, fp, [sp, #80] ; 0x50 + 22f9e: e9dd ab3e ldrd sl, fp, [sp, #248] ; 0xf8 + 22fa2: e9dd 233c ldrd r2, r3, [sp, #240] ; 0xf0 + 22fa6: eb16 060a adds.w r6, r6, sl + 22faa: f8cd e00c str.w lr, [sp, #12] + 22fae: eb47 070b adc.w r7, r7, fp + 22fb2: e9cd 4516 strd r4, r5, [sp, #88] ; 0x58 + 22fb6: e9dd 4500 ldrd r4, r5, [sp] + 22fba: e9dd ab02 ldrd sl, fp, [sp, #8] + 22fbe: 1912 adds r2, r2, r4 + 22fc0: 416b adcs r3, r5 + 22fc2: e9cd 6736 strd r6, r7, [sp, #216] ; 0xd8 + 22fc6: e9dd 6710 ldrd r6, r7, [sp, #64] ; 0x40 + 22fca: eb1a 0a06 adds.w sl, sl, r6 + 22fce: eb4b 0b07 adc.w fp, fp, r7 + 22fd2: 9919 ldr r1, [sp, #100] ; 0x64 + 22fd4: 9f0a ldr r7, [sp, #40] ; 0x28 + 22fd6: ad4c add r5, sp, #304 ; 0x130 + 22fd8: fb07 f701 mul.w r7, r7, r1 + 22fdc: 9e0b ldr r6, [sp, #44] ; 0x2c + 22fde: e9c5 2300 strd r2, r3, [r5] + 22fe2: 9d18 ldr r5, [sp, #96] ; 0x60 + 22fe4: 9c0a ldr r4, [sp, #40] ; 0x28 + 22fe6: fb05 7706 mla r7, r5, r6, r7 + 22fea: 9932 ldr r1, [sp, #200] ; 0xc8 + 22fec: 9e06 ldr r6, [sp, #24] + 22fee: fba4 2305 umull r2, r3, r4, r5 + 22ff2: fb06 f601 mul.w r6, r6, r1 + 22ff6: 4621 mov r1, r4 + 22ff8: 9c27 ldr r4, [sp, #156] ; 0x9c + 22ffa: 443b add r3, r7 + 22ffc: fb01 f104 mul.w r1, r1, r4 + 23000: eb1a 0402 adds.w r4, sl, r2 + 23004: eb4b 0503 adc.w r5, fp, r3 + 23008: 9f24 ldr r7, [sp, #144] ; 0x90 + 2300a: f8dd b098 ldr.w fp, [sp, #152] ; 0x98 + 2300e: e9cd 4510 strd r4, r5, [sp, #64] ; 0x40 + 23012: f8dd 8018 ldr.w r8, [sp, #24] + 23016: 9d07 ldr r5, [sp, #28] + 23018: f8dd a02c ldr.w sl, [sp, #44] ; 0x2c + 2301c: f8dd e028 ldr.w lr, [sp, #40] ; 0x28 + 23020: fb07 6605 mla r6, r7, r5, r6 + 23024: fbae 230b umull r2, r3, lr, fp + 23028: fba8 4507 umull r4, r5, r8, r7 + 2302c: fb0b 110a mla r1, fp, sl, r1 + 23030: 4435 add r5, r6 + 23032: 440b add r3, r1 + 23034: 18a6 adds r6, r4, r2 + 23036: eb45 0703 adc.w r7, r5, r3 + 2303a: e9cd 6702 strd r6, r7, [sp, #8] + 2303e: 9f0e ldr r7, [sp, #56] ; 0x38 + 23040: 9927 ldr r1, [sp, #156] ; 0x9c + 23042: 463b mov r3, r7 + 23044: fb03 f301 mul.w r3, r3, r1 + 23048: 4659 mov r1, fp + 2304a: f8dd a074 ldr.w sl, [sp, #116] ; 0x74 + 2304e: 9c32 ldr r4, [sp, #200] ; 0xc8 + 23050: fb07 f80a mul.w r8, r7, sl + 23054: f8dd a03c ldr.w sl, [sp, #60] ; 0x3c + 23058: 9e1c ldr r6, [sp, #112] ; 0x70 + 2305a: fb0b 3b0a mla fp, fp, sl, r3 + 2305e: fba7 2301 umull r2, r3, r7, r1 + 23062: 9d0f ldr r5, [sp, #60] ; 0x3c + 23064: fb0e fe04 mul.w lr, lr, r4 + 23068: e9cd 2306 strd r2, r3, [sp, #24] + 2306c: fb06 8805 mla r8, r6, r5, r8 + 23070: 9b0b ldr r3, [sp, #44] ; 0x2c + 23072: fba7 4506 umull r4, r5, r7, r6 + 23076: f8dd a028 ldr.w sl, [sp, #40] ; 0x28 + 2307a: 9e24 ldr r6, [sp, #144] ; 0x90 + 2307c: 9a19 ldr r2, [sp, #100] ; 0x64 + 2307e: fb06 ee03 mla lr, r6, r3, lr + 23082: 9b07 ldr r3, [sp, #28] + 23084: fbaa 6706 umull r6, r7, sl, r6 + 23088: 990e ldr r1, [sp, #56] ; 0x38 + 2308a: 445b add r3, fp + 2308c: 9307 str r3, [sp, #28] + 2308e: e9dd ab10 ldrd sl, fp, [sp, #64] ; 0x40 + 23092: 4445 add r5, r8 + 23094: eb1a 0a04 adds.w sl, sl, r4 + 23098: eb4b 0b05 adc.w fp, fp, r5 + 2309c: 4477 add r7, lr + 2309e: fb01 f102 mul.w r1, r1, r2 + 230a2: e9dd 2306 ldrd r2, r3, [sp, #24] + 230a6: 1992 adds r2, r2, r6 + 230a8: 417b adcs r3, r7 + 230aa: 9c18 ldr r4, [sp, #96] ; 0x60 + 230ac: e9cd 2306 strd r2, r3, [sp, #24] + 230b0: e9dd 6702 ldrd r6, r7, [sp, #8] + 230b4: 9b0f ldr r3, [sp, #60] ; 0x3c + 230b6: 9d0e ldr r5, [sp, #56] ; 0x38 + 230b8: fb04 1103 mla r1, r4, r3, r1 + 230bc: fba5 2304 umull r2, r3, r5, r4 + 230c0: e9cd ab00 strd sl, fp, [sp] + 230c4: 18b6 adds r6, r6, r2 + 230c6: f8dd 80c0 ldr.w r8, [sp, #192] ; 0xc0 + 230ca: f8dd a064 ldr.w sl, [sp, #100] ; 0x64 + 230ce: 440b add r3, r1 + 230d0: 415f adcs r7, r3 + 230d2: e9cd 6702 strd r6, r7, [sp, #8] + 230d6: fb0c f708 mul.w r7, ip, r8 + 230da: fb0c f60a mul.w r6, ip, sl + 230de: f8dd b0a8 ldr.w fp, [sp, #168] ; 0xa8 + 230e2: f8dd e0a0 ldr.w lr, [sp, #160] ; 0xa0 + 230e6: 9918 ldr r1, [sp, #96] ; 0x60 + 230e8: fbac 450e umull r4, r5, ip, lr + 230ec: fbac 2301 umull r2, r3, ip, r1 + 230f0: fb0e 770b mla r7, lr, fp, r7 + 230f4: fb0b 6601 mla r6, fp, r1, r6 + 230f8: f8dd a074 ldr.w sl, [sp, #116] ; 0x74 + 230fc: f8dd b038 ldr.w fp, [sp, #56] ; 0x38 + 23100: 9932 ldr r1, [sp, #200] ; 0xc8 + 23102: fb0c f80a mul.w r8, ip, sl + 23106: 443d add r5, r7 + 23108: f8dd a09c ldr.w sl, [sp, #156] ; 0x9c + 2310c: 4433 add r3, r6 + 2310e: e9dd 6700 ldrd r6, r7, [sp] + 23112: 1936 adds r6, r6, r4 + 23114: 416f adcs r7, r5 + 23116: e9cd 6700 strd r6, r7, [sp] + 2311a: fb0b fe01 mul.w lr, fp, r1 + 2311e: fb0c f10a mul.w r1, ip, sl + 23122: e9dd ab06 ldrd sl, fp, [sp, #24] + 23126: eb1a 0a02 adds.w sl, sl, r2 + 2312a: eb4b 0b03 adc.w fp, fp, r3 + 2312e: 9c2a ldr r4, [sp, #168] ; 0xa8 + 23130: e9cd ab0a strd sl, fp, [sp, #40] ; 0x28 + 23134: f8dd b070 ldr.w fp, [sp, #112] ; 0x70 + 23138: f8dd a038 ldr.w sl, [sp, #56] ; 0x38 + 2313c: fbac 230b umull r2, r3, ip, fp + 23140: fb04 880b mla r8, r4, fp, r8 + 23144: 9d0f ldr r5, [sp, #60] ; 0x3c + 23146: f8dd b098 ldr.w fp, [sp, #152] ; 0x98 + 2314a: 9e24 ldr r6, [sp, #144] ; 0x90 + 2314c: fb04 110b mla r1, r4, fp, r1 + 23150: fb06 ee05 mla lr, r6, r5, lr + 23154: fbac 450b umull r4, r5, ip, fp + 23158: fbaa 6706 umull r6, r7, sl, r6 + 2315c: e9dd ab02 ldrd sl, fp, [sp, #8] + 23160: 4443 add r3, r8 + 23162: eb1a 0a02 adds.w sl, sl, r2 + 23166: eb4b 0b03 adc.w fp, fp, r3 + 2316a: 4477 add r7, lr + 2316c: 1932 adds r2, r6, r4 + 2316e: 440d add r5, r1 + 23170: eb47 0305 adc.w r3, r7, r5 + 23174: e9cd 2310 strd r2, r3, [sp, #64] ; 0x40 + 23178: 9c23 ldr r4, [sp, #140] ; 0x8c + 2317a: 9b08 ldr r3, [sp, #32] + 2317c: e9cd ab06 strd sl, fp, [sp, #24] + 23180: fb03 fa04 mul.w sl, r3, r4 + 23184: f8dd b024 ldr.w fp, [sp, #36] ; 0x24 + 23188: f8dd e088 ldr.w lr, [sp, #136] ; 0x88 + 2318c: 9d1d ldr r5, [sp, #116] ; 0x74 + 2318e: fb0e aa0b mla sl, lr, fp, sl + 23192: fb03 f305 mul.w r3, r3, r5 + 23196: f8cd a008 str.w sl, [sp, #8] + 2319a: f8dd a070 ldr.w sl, [sp, #112] ; 0x70 + 2319e: 9a08 ldr r2, [sp, #32] + 231a0: fb0a 330b mla r3, sl, fp, r3 + 231a4: 9f27 ldr r7, [sp, #156] ; 0x9c + 231a6: 930e str r3, [sp, #56] ; 0x38 + 231a8: 9908 ldr r1, [sp, #32] + 231aa: 4613 mov r3, r2 + 231ac: fb01 f107 mul.w r1, r1, r7 + 231b0: 465f mov r7, fp + 231b2: 9e32 ldr r6, [sp, #200] ; 0xc8 + 231b4: fba2 450e umull r4, r5, r2, lr + 231b8: fb0c f806 mul.w r8, ip, r6 + 231bc: f8dd e098 ldr.w lr, [sp, #152] ; 0x98 + 231c0: 9e24 ldr r6, [sp, #144] ; 0x90 + 231c2: fba3 230a umull r2, r3, r3, sl + 231c6: fbac ab06 umull sl, fp, ip, r6 + 231ca: fb0e 1c07 mla ip, lr, r7, r1 + 231ce: 9908 ldr r1, [sp, #32] + 231d0: e9cd 232e strd r2, r3, [sp, #184] ; 0xb8 + 231d4: 460a mov r2, r1 + 231d6: 9b2a ldr r3, [sp, #168] ; 0xa8 + 231d8: fb06 8803 mla r8, r6, r3, r8 + 231dc: 9b30 ldr r3, [sp, #192] ; 0xc0 + 231de: fba1 670e umull r6, r7, r1, lr + 231e2: fb02 f203 mul.w r2, r2, r3 + 231e6: 922c str r2, [sp, #176] ; 0xb0 + 231e8: 9a19 ldr r2, [sp, #100] ; 0x64 + 231ea: f8dd e038 ldr.w lr, [sp, #56] ; 0x38 + 231ee: fb01 f102 mul.w r1, r1, r2 + 231f2: 9a2f ldr r2, [sp, #188] ; 0xbc + 231f4: 9b02 ldr r3, [sp, #8] + 231f6: 4472 add r2, lr + 231f8: 922f str r2, [sp, #188] ; 0xbc + 231fa: 441d add r5, r3 + 231fc: e9dd 2300 ldrd r2, r3, [sp] + 23200: 1912 adds r2, r2, r4 + 23202: 416b adcs r3, r5 + 23204: e9cd 2300 strd r2, r3, [sp] + 23208: e9dd 450a ldrd r4, r5, [sp, #40] ; 0x28 + 2320c: e9dd 232e ldrd r2, r3, [sp, #184] ; 0xb8 + 23210: 18a4 adds r4, r4, r2 + 23212: 415d adcs r5, r3 + 23214: e9cd 450a strd r4, r5, [sp, #40] ; 0x28 + 23218: 44c3 add fp, r8 + 2321a: eb1a 0406 adds.w r4, sl, r6 + 2321e: 4467 add r7, ip + 23220: eb4b 0507 adc.w r5, fp, r7 + 23224: 9e28 ldr r6, [sp, #160] ; 0xa0 + 23226: 9f2c ldr r7, [sp, #176] ; 0xb0 + 23228: f8dd 8020 ldr.w r8, [sp, #32] + 2322c: e9cd 452a strd r4, r5, [sp, #168] ; 0xa8 + 23230: 9d09 ldr r5, [sp, #36] ; 0x24 + 23232: f8dd a060 ldr.w sl, [sp, #96] ; 0x60 + 23236: fba8 2306 umull r2, r3, r8, r6 + 2323a: fb06 7e05 mla lr, r6, r5, r7 + 2323e: e9dd 6706 ldrd r6, r7, [sp, #24] + 23242: fb0a 1105 mla r1, sl, r5, r1 + 23246: fba8 450a umull r4, r5, r8, sl + 2324a: e9dd ab10 ldrd sl, fp, [sp, #64] ; 0x40 + 2324e: 18b6 adds r6, r6, r2 + 23250: 4473 add r3, lr + 23252: f8dd c030 ldr.w ip, [sp, #48] ; 0x30 + 23256: 415f adcs r7, r3 + 23258: 440d add r5, r1 + 2325a: eb1a 0a04 adds.w sl, sl, r4 + 2325e: 9930 ldr r1, [sp, #192] ; 0xc0 + 23260: eb4b 0b05 adc.w fp, fp, r5 + 23264: e9cd 6702 strd r6, r7, [sp, #8] + 23268: e9cd ab0e strd sl, fp, [sp, #56] ; 0x38 + 2326c: 4666 mov r6, ip + 2326e: fb0c fa01 mul.w sl, ip, r1 + 23272: 4661 mov r1, ip + 23274: f8dd e084 ldr.w lr, [sp, #132] ; 0x84 + 23278: 9b0d ldr r3, [sp, #52] ; 0x34 + 2327a: fb0c fb0e mul.w fp, ip, lr + 2327e: 9f28 ldr r7, [sp, #160] ; 0xa0 + 23280: 9a19 ldr r2, [sp, #100] ; 0x64 + 23282: 9c20 ldr r4, [sp, #128] ; 0x80 + 23284: fb07 aa03 mla sl, r7, r3, sl + 23288: fb04 bb03 mla fp, r4, r3, fp + 2328c: fb01 f102 mul.w r1, r1, r2 + 23290: fbac 2307 umull r2, r3, ip, r7 + 23294: 4637 mov r7, r6 + 23296: fbac 4504 umull r4, r5, ip, r4 + 2329a: f8dd c060 ldr.w ip, [sp, #96] ; 0x60 + 2329e: f8dd 8034 ldr.w r8, [sp, #52] ; 0x34 + 232a2: fba7 670c umull r6, r7, r7, ip + 232a6: fb0c 1108 mla r1, ip, r8, r1 + 232aa: e9cd 6710 strd r6, r7, [sp, #64] ; 0x40 + 232ae: 9f0c ldr r7, [sp, #48] ; 0x30 + 232b0: 9106 str r1, [sp, #24] + 232b2: 4639 mov r1, r7 + 232b4: 9e27 ldr r6, [sp, #156] ; 0x9c + 232b6: f8dd c08c ldr.w ip, [sp, #140] ; 0x8c + 232ba: fb01 f106 mul.w r1, r1, r6 + 232be: f8dd e074 ldr.w lr, [sp, #116] ; 0x74 + 232c2: 445d add r5, fp + 232c4: 4453 add r3, sl + 232c6: f8dd b044 ldr.w fp, [sp, #68] ; 0x44 + 232ca: f8dd a018 ldr.w sl, [sp, #24] + 232ce: fb07 f80c mul.w r8, r7, ip + 232d2: 912c str r1, [sp, #176] ; 0xb0 + 232d4: fb07 fc0e mul.w ip, r7, lr + 232d8: 9908 ldr r1, [sp, #32] + 232da: 9f32 ldr r7, [sp, #200] ; 0xc8 + 232dc: 44d3 add fp, sl + 232de: f8cd b044 str.w fp, [sp, #68] ; 0x44 + 232e2: fb01 f107 mul.w r1, r1, r7 + 232e6: e9dd 6700 ldrd r6, r7, [sp] + 232ea: e9dd ab0a ldrd sl, fp, [sp, #40] ; 0x28 + 232ee: 1936 adds r6, r6, r4 + 232f0: 416f adcs r7, r5 + 232f2: eb1a 0a02 adds.w sl, sl, r2 + 232f6: e9dd 4510 ldrd r4, r5, [sp, #64] ; 0x40 + 232fa: eb4b 0b03 adc.w fp, fp, r3 + 232fe: e9dd 232a ldrd r2, r3, [sp, #168] ; 0xa8 + 23302: 1912 adds r2, r2, r4 + 23304: e9cd ab06 strd sl, fp, [sp, #24] + 23308: 416b adcs r3, r5 + 2330a: f8dd b070 ldr.w fp, [sp, #112] ; 0x70 + 2330e: 9d0d ldr r5, [sp, #52] ; 0x34 + 23310: e9cd 6700 strd r6, r7, [sp] + 23314: fb0b cc05 mla ip, fp, r5, ip + 23318: 9f0c ldr r7, [sp, #48] ; 0x30 + 2331a: f8cd c0a8 str.w ip, [sp, #168] ; 0xa8 + 2331e: 46aa mov sl, r5 + 23320: 46bc mov ip, r7 + 23322: 9e22 ldr r6, [sp, #136] ; 0x88 + 23324: e9cd 2310 strd r2, r3, [sp, #64] ; 0x40 + 23328: fb06 8805 mla r8, r6, r5, r8 + 2332c: fba7 2306 umull r2, r3, r7, r6 + 23330: fba7 450b umull r4, r5, r7, fp + 23334: f8cd 8028 str.w r8, [sp, #40] ; 0x28 + 23338: 9f26 ldr r7, [sp, #152] ; 0x98 + 2333a: f8dd 80b0 ldr.w r8, [sp, #176] ; 0xb0 + 2333e: 9e08 ldr r6, [sp, #32] + 23340: fb07 8e0a mla lr, r7, sl, r8 + 23344: fbac ab07 umull sl, fp, ip, r7 + 23348: f8dd c090 ldr.w ip, [sp, #144] ; 0x90 + 2334c: e9cd ab2c strd sl, fp, [sp, #176] ; 0xb0 + 23350: f8dd b024 ldr.w fp, [sp, #36] ; 0x24 + 23354: 9f0a ldr r7, [sp, #40] ; 0x28 + 23356: fb0c 110b mla r1, ip, fp, r1 + 2335a: fba6 ab0c umull sl, fp, r6, ip + 2335e: f8dd c0b4 ldr.w ip, [sp, #180] ; 0xb4 + 23362: f8dd 80a8 ldr.w r8, [sp, #168] ; 0xa8 + 23366: 443b add r3, r7 + 23368: 44f4 add ip, lr + 2336a: e9dd 6702 ldrd r6, r7, [sp, #8] + 2336e: 18b6 adds r6, r6, r2 + 23370: f8cd c0b4 str.w ip, [sp, #180] ; 0xb4 + 23374: 415f adcs r7, r3 + 23376: 4445 add r5, r8 + 23378: e9dd 230e ldrd r2, r3, [sp, #56] ; 0x38 + 2337c: 1912 adds r2, r2, r4 + 2337e: 416b adcs r3, r5 + 23380: 448b add fp, r1 + 23382: e9dd 452c ldrd r4, r5, [sp, #176] ; 0xb0 + 23386: eb14 040a adds.w r4, r4, sl + 2338a: eb45 050b adc.w r5, r5, fp + 2338e: e9cd 452a strd r4, r5, [sp, #168] ; 0xa8 + 23392: 9d12 ldr r5, [sp, #72] ; 0x48 + 23394: e9cd 230e strd r2, r3, [sp, #56] ; 0x38 + 23398: 462b mov r3, r5 + 2339a: f8dd c074 ldr.w ip, [sp, #116] ; 0x74 + 2339e: e9cd 6702 strd r6, r7, [sp, #8] + 233a2: fb05 f80c mul.w r8, r5, ip + 233a6: 9e1f ldr r6, [sp, #124] ; 0x7c + 233a8: 9f23 ldr r7, [sp, #140] ; 0x8c + 233aa: f8dd e04c ldr.w lr, [sp, #76] ; 0x4c + 233ae: fb05 fa06 mul.w sl, r5, r6 + 233b2: fb03 f307 mul.w r3, r3, r7 + 233b6: 9e12 ldr r6, [sp, #72] ; 0x48 + 233b8: 9f1c ldr r7, [sp, #112] ; 0x70 + 233ba: 9a22 ldr r2, [sp, #136] ; 0x88 + 233bc: fb07 880e mla r8, r7, lr, r8 + 233c0: 4637 mov r7, r6 + 233c2: fb02 3b0e mla fp, r2, lr, r3 + 233c6: fba6 2302 umull r2, r3, r6, r2 + 233ca: 9e1c ldr r6, [sp, #112] ; 0x70 + 233cc: 991e ldr r1, [sp, #120] ; 0x78 + 233ce: fba7 6706 umull r6, r7, r7, r6 + 233d2: e9cd 672c strd r6, r7, [sp, #176] ; 0xb0 + 233d6: 9f12 ldr r7, [sp, #72] ; 0x48 + 233d8: fb01 aa0e mla sl, r1, lr, sl + 233dc: fba5 4501 umull r4, r5, r5, r1 + 233e0: 4639 mov r1, r7 + 233e2: 9e30 ldr r6, [sp, #192] ; 0xc0 + 233e4: f8dd e084 ldr.w lr, [sp, #132] ; 0x84 + 233e8: fb01 f106 mul.w r1, r1, r6 + 233ec: 9108 str r1, [sp, #32] + 233ee: 4639 mov r1, r7 + 233f0: fb07 fc0e mul.w ip, r7, lr + 233f4: 4455 add r5, sl + 233f6: 9f19 ldr r7, [sp, #100] ; 0x64 + 233f8: f8dd a0b4 ldr.w sl, [sp, #180] ; 0xb4 + 233fc: fb01 f107 mul.w r1, r1, r7 + 23400: e9dd 6700 ldrd r6, r7, [sp] + 23404: 44c2 add sl, r8 + 23406: 1936 adds r6, r6, r4 + 23408: f8cd a0b4 str.w sl, [sp, #180] ; 0xb4 + 2340c: 416f adcs r7, r5 + 2340e: 445b add r3, fp + 23410: e9dd ab06 ldrd sl, fp, [sp, #24] + 23414: eb1a 0a02 adds.w sl, sl, r2 + 23418: e9dd 452c ldrd r4, r5, [sp, #176] ; 0xb0 + 2341c: eb4b 0b03 adc.w fp, fp, r3 + 23420: e9dd 2310 ldrd r2, r3, [sp, #64] ; 0x40 + 23424: 1912 adds r2, r2, r4 + 23426: e9cd 6700 strd r6, r7, [sp] + 2342a: 416b adcs r3, r5 + 2342c: 9f12 ldr r7, [sp, #72] ; 0x48 + 2342e: 9d13 ldr r5, [sp, #76] ; 0x4c + 23430: 9e20 ldr r6, [sp, #128] ; 0x80 + 23432: f8dd 80a0 ldr.w r8, [sp, #160] ; 0xa0 + 23436: e9cd ab0a strd sl, fp, [sp, #40] ; 0x28 + 2343a: f8dd a020 ldr.w sl, [sp, #32] + 2343e: fb06 cc05 mla ip, r6, r5, ip + 23442: f8dd b04c ldr.w fp, [sp, #76] ; 0x4c + 23446: e9cd 2310 strd r2, r3, [sp, #64] ; 0x40 + 2344a: fba7 2306 umull r2, r3, r7, r6 + 2344e: 9e18 ldr r6, [sp, #96] ; 0x60 + 23450: fb08 ae05 mla lr, r8, r5, sl + 23454: fba7 4508 umull r4, r5, r7, r8 + 23458: fb06 110b mla r1, r6, fp, r1 + 2345c: fba7 ab06 umull sl, fp, r7, r6 + 23460: e9dd 6702 ldrd r6, r7, [sp, #8] + 23464: 4463 add r3, ip + 23466: 18b6 adds r6, r6, r2 + 23468: 415f adcs r7, r3 + 2346a: 4475 add r5, lr + 2346c: e9dd 230e ldrd r2, r3, [sp, #56] ; 0x38 + 23470: 1912 adds r2, r2, r4 + 23472: 416b adcs r3, r5 + 23474: 448b add fp, r1 + 23476: e9dd 452a ldrd r4, r5, [sp, #168] ; 0xa8 + 2347a: eb14 040a adds.w r4, r4, sl + 2347e: eb45 050b adc.w r5, r5, fp + 23482: e9cd 6706 strd r6, r7, [sp, #24] + 23486: e9cd 452a strd r4, r5, [sp, #168] ; 0xa8 + 2348a: 9e21 ldr r6, [sp, #132] ; 0x84 + 2348c: 9d1b ldr r5, [sp, #108] ; 0x6c + 2348e: fb09 f106 mul.w r1, r9, r6 + 23492: fb09 fa05 mul.w sl, r9, r5 + 23496: f8dd c010 ldr.w ip, [sp, #16] + 2349a: f8dd b068 ldr.w fp, [sp, #104] ; 0x68 + 2349e: 9e20 ldr r6, [sp, #128] ; 0x80 + 234a0: 9f30 ldr r7, [sp, #192] ; 0xc0 + 234a2: fb0c 1106 mla r1, ip, r6, r1 + 234a6: fb0c aa0b mla sl, ip, fp, sl + 234aa: fb09 f807 mul.w r8, r9, r7 + 234ae: e9cd 2308 strd r2, r3, [sp, #32] + 234b2: f8cd a008 str.w sl, [sp, #8] + 234b6: 910e str r1, [sp, #56] ; 0x38 + 234b8: 9f28 ldr r7, [sp, #160] ; 0xa0 + 234ba: f8dd e07c ldr.w lr, [sp, #124] ; 0x7c + 234be: 9923 ldr r1, [sp, #140] ; 0x8c + 234c0: fba9 450b umull r4, r5, r9, fp + 234c4: fba9 2306 umull r2, r3, r9, r6 + 234c8: fba9 ab07 umull sl, fp, r9, r7 + 234cc: fb07 880c mla r8, r7, ip, r8 + 234d0: 9e1d ldr r6, [sp, #116] ; 0x74 + 234d2: fb09 fc0e mul.w ip, r9, lr + 234d6: 9f0c ldr r7, [sp, #48] ; 0x30 + 234d8: fb09 fe01 mul.w lr, r9, r1 + 234dc: 9932 ldr r1, [sp, #200] ; 0xc8 + 234de: fb09 f606 mul.w r6, r9, r6 + 234e2: fb07 f701 mul.w r7, r7, r1 + 234e6: 961a str r6, [sp, #104] ; 0x68 + 234e8: 9720 str r7, [sp, #128] ; 0x80 + 234ea: 9e12 ldr r6, [sp, #72] ; 0x48 + 234ec: 9f27 ldr r7, [sp, #156] ; 0x9c + 234ee: 9902 ldr r1, [sp, #8] + 234f0: fb06 f607 mul.w r6, r6, r7 + 234f4: 9628 str r6, [sp, #160] ; 0xa0 + 234f6: 9e0e ldr r6, [sp, #56] ; 0x38 + 234f8: 440d add r5, r1 + 234fa: 4433 add r3, r6 + 234fc: e9dd 6700 ldrd r6, r7, [sp] + 23500: 1936 adds r6, r6, r4 + 23502: 416f adcs r7, r5 + 23504: e9dd 450a ldrd r4, r5, [sp, #40] ; 0x28 + 23508: 18a4 adds r4, r4, r2 + 2350a: 415d adcs r5, r3 + 2350c: 44c3 add fp, r8 + 2350e: e9cd 673c strd r6, r7, [sp, #240] ; 0xf0 + 23512: e9dd 6710 ldrd r6, r7, [sp, #64] ; 0x40 + 23516: eb16 060a adds.w r6, r6, sl + 2351a: eb47 070b adc.w r7, r7, fp + 2351e: f8dd 8010 ldr.w r8, [sp, #16] + 23522: e9cd 673e strd r6, r7, [sp, #248] ; 0xf8 + 23526: 9f1e ldr r7, [sp, #120] ; 0x78 + 23528: f8dd a088 ldr.w sl, [sp, #136] ; 0x88 + 2352c: fba9 2307 umull r2, r3, r9, r7 + 23530: fb08 cc07 mla ip, r8, r7, ip + 23534: 9f1c ldr r7, [sp, #112] ; 0x70 + 23536: fb08 ee0a mla lr, r8, sl, lr + 2353a: fba9 6707 umull r6, r7, r9, r7 + 2353e: f8dd b068 ldr.w fp, [sp, #104] ; 0x68 + 23542: e9cd 453a strd r4, r5, [sp, #232] ; 0xe8 + 23546: fba9 450a umull r4, r5, r9, sl + 2354a: f8dd a070 ldr.w sl, [sp, #112] ; 0x70 + 2354e: e9cd 670a strd r6, r7, [sp, #40] ; 0x28 + 23552: 990d ldr r1, [sp, #52] ; 0x34 + 23554: fb08 b70a mla r7, r8, sl, fp + 23558: f8dd 8090 ldr.w r8, [sp, #144] ; 0x90 + 2355c: f8dd a080 ldr.w sl, [sp, #128] ; 0x80 + 23560: f8dd b030 ldr.w fp, [sp, #48] ; 0x30 + 23564: fb08 a601 mla r6, r8, r1, sl + 23568: fbab ab08 umull sl, fp, fp, r8 + 2356c: f8dd 8098 ldr.w r8, [sp, #152] ; 0x98 + 23570: e9cd ab00 strd sl, fp, [sp] + 23574: f8dd b04c ldr.w fp, [sp, #76] ; 0x4c + 23578: f8dd a0a0 ldr.w sl, [sp, #160] ; 0xa0 + 2357c: 4463 add r3, ip + 2357e: fb08 a10b mla r1, r8, fp, sl + 23582: f8dd b048 ldr.w fp, [sp, #72] ; 0x48 + 23586: 4475 add r5, lr + 23588: fbab ab08 umull sl, fp, fp, r8 + 2358c: e9cd ab02 strd sl, fp, [sp, #8] + 23590: f8dd c004 ldr.w ip, [sp, #4] + 23594: f8dd b02c ldr.w fp, [sp, #44] ; 0x2c + 23598: f8dd e00c ldr.w lr, [sp, #12] + 2359c: 44bb add fp, r7 + 2359e: 44b4 add ip, r6 + 235a0: e9dd 6706 ldrd r6, r7, [sp, #24] + 235a4: 18b6 adds r6, r6, r2 + 235a6: f8cd b02c str.w fp, [sp, #44] ; 0x2c + 235aa: 415f adcs r7, r3 + 235ac: e9dd ab08 ldrd sl, fp, [sp, #32] + 235b0: 448e add lr, r1 + 235b2: eb1a 0a04 adds.w sl, sl, r4 + 235b6: f8cd c004 str.w ip, [sp, #4] + 235ba: e9dd 232a ldrd r2, r3, [sp, #168] ; 0xa8 + 235be: f8cd e00c str.w lr, [sp, #12] + 235c2: eb4b 0b05 adc.w fp, fp, r5 + 235c6: f50d 78ac add.w r8, sp, #344 ; 0x158 + 235ca: e9dd 450a ldrd r4, r5, [sp, #40] ; 0x28 + 235ce: f50d 7cbc add.w ip, sp, #376 ; 0x178 + 235d2: 1912 adds r2, r2, r4 + 235d4: e9c8 6700 strd r6, r7, [r8] + 235d8: e9dd 6700 ldrd r6, r7, [sp] + 235dc: 416b adcs r3, r5 + 235de: e9cc ab00 strd sl, fp, [ip] + 235e2: e9dd ab02 ldrd sl, fp, [sp, #8] + 235e6: eb16 060a adds.w r6, r6, sl + 235ea: eb47 070b adc.w r7, r7, fp + 235ee: ad64 add r5, sp, #400 ; 0x190 + 235f0: f8dd b064 ldr.w fp, [sp, #100] ; 0x64 + 235f4: e9c5 2300 strd r2, r3, [r5] + 235f8: e9dd 4514 ldrd r4, r5, [sp, #80] ; 0x50 + 235fc: f514 1480 adds.w r4, r4, #1048576 ; 0x100000 + 23600: fb09 f30b mul.w r3, r9, fp + 23604: e9dd ab36 ldrd sl, fp, [sp, #216] ; 0xd8 + 23608: f145 0500 adc.w r5, r5, #0 + 2360c: f51a 1a80 adds.w sl, sl, #1048576 ; 0x100000 + 23610: e9cd 4500 strd r4, r5, [sp] + 23614: e9dd 4538 ldrd r4, r5, [sp, #224] ; 0xe0 + 23618: f14b 0b00 adc.w fp, fp, #0 + 2361c: f514 1480 adds.w r4, r4, #1048576 ; 0x100000 + 23620: e9cd ab30 strd sl, fp, [sp, #192] ; 0xc0 + 23624: e9dd ab3c ldrd sl, fp, [sp, #240] ; 0xf0 + 23628: f145 0500 adc.w r5, r5, #0 + 2362c: f50d 788c add.w r8, sp, #280 ; 0x118 + 23630: f51a 1a80 adds.w sl, sl, #1048576 ; 0x100000 + 23634: e9cd 452a strd r4, r5, [sp, #168] ; 0xa8 + 23638: e9d8 4500 ldrd r4, r5, [r8] + 2363c: f14b 0b00 adc.w fp, fp, #0 + 23640: f514 1480 adds.w r4, r4, #1048576 ; 0x100000 + 23644: e9cd ab2e strd sl, fp, [sp, #184] ; 0xb8 + 23648: e9dd ab3a ldrd sl, fp, [sp, #232] ; 0xe8 + 2364c: f145 0500 adc.w r5, r5, #0 + 23650: f50d 78a4 add.w r8, sp, #328 ; 0x148 + 23654: f51a 1a80 adds.w sl, sl, #1048576 ; 0x100000 + 23658: e9cd 4528 strd r4, r5, [sp, #160] ; 0xa0 + 2365c: e9d8 4500 ldrd r4, r5, [r8] + 23660: f14b 0b00 adc.w fp, fp, #0 + 23664: f514 1480 adds.w r4, r4, #1048576 ; 0x100000 + 23668: e9cd ab34 strd sl, fp, [sp, #208] ; 0xd0 + 2366c: e9dd ab3e ldrd sl, fp, [sp, #248] ; 0xf8 + 23670: f145 0500 adc.w r5, r5, #0 + 23674: f50d 7894 add.w r8, sp, #296 ; 0x128 + 23678: f51a 1a80 adds.w sl, sl, #1048576 ; 0x100000 + 2367c: e9cd 4522 strd r4, r5, [sp, #136] ; 0x88 + 23680: e9d8 4500 ldrd r4, r5, [r8] + 23684: f14b 0b00 adc.w fp, fp, #0 + 23688: f514 1480 adds.w r4, r4, #1048576 ; 0x100000 + 2368c: f145 0500 adc.w r5, r5, #0 + 23690: e9cd ab2c strd sl, fp, [sp, #176] ; 0xb0 + 23694: e9cd 4520 strd r4, r5, [sp, #128] ; 0x80 + 23698: f8dd e060 ldr.w lr, [sp, #96] ; 0x60 + 2369c: 9a04 ldr r2, [sp, #16] + 2369e: f50d 7c90 add.w ip, sp, #288 ; 0x120 + 236a2: fb02 310e mla r1, r2, lr, r3 + 236a6: e9dc ab00 ldrd sl, fp, [ip] + 236aa: fba9 230e umull r2, r3, r9, lr + 236ae: f51a 1a80 adds.w sl, sl, #1048576 ; 0x100000 + 236b2: f14b 0b00 adc.w fp, fp, #0 + 236b6: 440b add r3, r1 + 236b8: 18b4 adds r4, r6, r2 + 236ba: eb47 0503 adc.w r5, r7, r3 + 236be: f50d 7884 add.w r8, sp, #264 ; 0x108 + 236c2: e9c8 4500 strd r4, r5, [r8] + 236c6: 9912 ldr r1, [sp, #72] ; 0x48 + 236c8: 9a32 ldr r2, [sp, #200] ; 0xc8 + 236ca: 9c27 ldr r4, [sp, #156] ; 0x9c + 236cc: 9d00 ldr r5, [sp, #0] + 236ce: fb09 f304 mul.w r3, r9, r4 + 236d2: fb01 f102 mul.w r1, r1, r2 + 236d6: 9e01 ldr r6, [sp, #4] + 236d8: f8dd 8090 ldr.w r8, [sp, #144] ; 0x90 + 236dc: f8dd c048 ldr.w ip, [sp, #72] ; 0x48 + 236e0: 9c04 ldr r4, [sp, #16] + 236e2: e9cd ab1e strd sl, fp, [sp, #120] ; 0x78 + 236e6: 9f13 ldr r7, [sp, #76] ; 0x4c + 236e8: 9a26 ldr r2, [sp, #152] ; 0x98 + 236ea: ea4f 5a55 mov.w sl, r5, lsr #21 + 236ee: 9d01 ldr r5, [sp, #4] + 236f0: ea4a 2ac6 orr.w sl, sl, r6, lsl #11 + 236f4: fb08 1107 mla r1, r8, r7, r1 + 236f8: fb04 3e02 mla lr, r4, r2, r3 + 236fc: fbac 6708 umull r6, r7, ip, r8 + 23700: fba9 2302 umull r2, r3, r9, r2 + 23704: ea4f 5b65 mov.w fp, r5, asr #21 + 23708: e9dd 4516 ldrd r4, r5, [sp, #88] ; 0x58 + 2370c: eb14 040a adds.w r4, r4, sl + 23710: eb45 050b adc.w r5, r5, fp + 23714: f50d 7888 add.w r8, sp, #272 ; 0x110 + 23718: e9c8 4500 strd r4, r5, [r8] + 2371c: ea4f 544a mov.w r4, sl, lsl #21 + 23720: ea4f 554b mov.w r5, fp, lsl #21 + 23724: ea45 25da orr.w r5, r5, sl, lsr #11 + 23728: e9dd ab14 ldrd sl, fp, [sp, #80] ; 0x50 + 2372c: ebba 0a04 subs.w sl, sl, r4 + 23730: eb6b 0b05 sbc.w fp, fp, r5 + 23734: 440f add r7, r1 + 23736: 18b4 adds r4, r6, r2 + 23738: 4473 add r3, lr + 2373a: eb47 0503 adc.w r5, r7, r3 + 2373e: f50d 7cc4 add.w ip, sp, #392 ; 0x188 + 23742: f50d 78c0 add.w r8, sp, #384 ; 0x180 + 23746: e9cc ab00 strd sl, fp, [ip] + 2374a: e9c8 4500 strd r4, r5, [r8] + 2374e: f8dd a0c8 ldr.w sl, [sp, #200] ; 0xc8 + 23752: 9d24 ldr r5, [sp, #144] ; 0x90 + 23754: f04f 0800 mov.w r8, #0 + 23758: fba9 4505 umull r4, r5, r9, r5 + 2375c: fb09 f30a mul.w r3, r9, sl + 23760: f04f 0900 mov.w r9, #0 + 23764: 4649 mov r1, r9 + 23766: 9012 str r0, [sp, #72] ; 0x48 + 23768: 4640 mov r0, r8 + 2376a: 9e04 ldr r6, [sp, #16] + 2376c: 9f24 ldr r7, [sp, #144] ; 0x90 + 2376e: e9cd 451c strd r4, r5, [sp, #112] ; 0x70 + 23772: fb07 3306 mla r3, r7, r6, r3 + 23776: 46c2 mov sl, r8 + 23778: 46cb mov fp, r9 + 2377a: 4642 mov r2, r8 + 2377c: 4606 mov r6, r0 + 2377e: 460f mov r7, r1 + 23780: 441d add r5, r3 + 23782: 464b mov r3, r9 + 23784: 951d str r5, [sp, #116] ; 0x74 + 23786: 4644 mov r4, r8 + 23788: 464d mov r5, r9 + 2378a: e9cd ab04 strd sl, fp, [sp, #16] + 2378e: e9cd 2318 strd r2, r3, [sp, #96] ; 0x60 + 23792: e9cd 6710 strd r6, r7, [sp, #64] ; 0x40 + 23796: e9cd 890c strd r8, r9, [sp, #48] ; 0x30 + 2379a: e9cd ab14 strd sl, fp, [sp, #80] ; 0x50 + 2379e: e9cd 0108 strd r0, r1, [sp, #32] + 237a2: f8dd a0a8 ldr.w sl, [sp, #168] ; 0xa8 + 237a6: e9cd 890a strd r8, r9, [sp, #40] ; 0x28 + 237aa: f8dd c0a0 ldr.w ip, [sp, #160] ; 0xa0 + 237ae: f8dd 90c0 ldr.w r9, [sp, #192] ; 0xc0 + 237b2: f8dd 80c4 ldr.w r8, [sp, #196] ; 0xc4 + 237b6: ea4f 5a5a mov.w sl, sl, lsr #21 + 237ba: f8cd a010 str.w sl, [sp, #16] + 237be: ea4f 5959 mov.w r9, r9, lsr #21 + 237c2: ea4f 5c5c mov.w ip, ip, lsr #21 + 237c6: f8cd c060 str.w ip, [sp, #96] ; 0x60 + 237ca: e9cd 671a strd r6, r7, [sp, #104] ; 0x68 + 237ce: f8dd c0ac ldr.w ip, [sp, #172] ; 0xac + 237d2: ea49 27c8 orr.w r7, r9, r8, lsl #11 + 237d6: f8dd 9010 ldr.w r9, [sp, #16] + 237da: e9cd 2316 strd r2, r3, [sp, #88] ; 0x58 + 237de: 9822 ldr r0, [sp, #136] ; 0x88 + 237e0: 9a20 ldr r2, [sp, #128] ; 0x80 + 237e2: 9e1e ldr r6, [sp, #120] ; 0x78 + 237e4: f8dd e0d0 ldr.w lr, [sp, #208] ; 0xd0 + 237e8: f8dd b0b8 ldr.w fp, [sp, #184] ; 0xb8 + 237ec: ea49 29cc orr.w r9, r9, ip, lsl #11 + 237f0: e9cd 450e strd r4, r5, [sp, #56] ; 0x38 + 237f4: f8dd c08c ldr.w ip, [sp, #140] ; 0x8c + 237f8: f8cd 9010 str.w r9, [sp, #16] + 237fc: 0d44 lsrs r4, r0, #21 + 237fe: f8dd 90d4 ldr.w r9, [sp, #212] ; 0xd4 + 23802: 0d50 lsrs r0, r2, #21 + 23804: 0d72 lsrs r2, r6, #21 + 23806: 9e2f ldr r6, [sp, #188] ; 0xbc + 23808: f8dd 80a4 ldr.w r8, [sp, #164] ; 0xa4 + 2380c: 992c ldr r1, [sp, #176] ; 0xb0 + 2380e: 9700 str r7, [sp, #0] + 23810: ea4f 5b5b mov.w fp, fp, lsr #21 + 23814: 9f18 ldr r7, [sp, #96] ; 0x60 + 23816: ea4f 5a5e mov.w sl, lr, lsr #21 + 2381a: ea4a 2ac9 orr.w sl, sl, r9, lsl #11 + 2381e: ea44 24cc orr.w r4, r4, ip, lsl #11 + 23822: ea4b 2ec6 orr.w lr, fp, r6, lsl #11 + 23826: f8dd 90c4 ldr.w r9, [sp, #196] ; 0xc4 + 2382a: 9e2d ldr r6, [sp, #180] ; 0xb4 + 2382c: f8dd c0ac ldr.w ip, [sp, #172] ; 0xac + 23830: ea47 27c8 orr.w r7, r7, r8, lsl #11 + 23834: 0d49 lsrs r1, r1, #21 + 23836: f8dd 807c ldr.w r8, [sp, #124] ; 0x7c + 2383a: f8cd e008 str.w lr, [sp, #8] + 2383e: 9718 str r7, [sp, #96] ; 0x60 + 23840: ea41 2ec6 orr.w lr, r1, r6, lsl #11 + 23844: 9f21 ldr r7, [sp, #132] ; 0x84 + 23846: ea4f 5969 mov.w r9, r9, asr #21 + 2384a: ea4f 5c6c mov.w ip, ip, asr #21 + 2384e: ea42 22c8 orr.w r2, r2, r8, lsl #11 + 23852: f8cd e090 str.w lr, [sp, #144] ; 0x90 + 23856: f8cd 9004 str.w r9, [sp, #4] + 2385a: f8cd c014 str.w ip, [sp, #20] + 2385e: f8dd 808c ldr.w r8, [sp, #140] ; 0x8c + 23862: 9e29 ldr r6, [sp, #164] ; 0xa4 + 23864: f8dd 90b4 ldr.w r9, [sp, #180] ; 0xb4 + 23868: ea40 20c7 orr.w r0, r0, r7, lsl #11 + 2386c: 9f35 ldr r7, [sp, #212] ; 0xd4 + 2386e: ea4f 5568 mov.w r5, r8, asr #21 + 23872: 1576 asrs r6, r6, #21 + 23874: f50d 7898 add.w r8, sp, #304 ; 0x130 + 23878: ea4f 5969 mov.w r9, r9, asr #21 + 2387c: 9619 str r6, [sp, #100] ; 0x64 + 2387e: ea4f 5b67 mov.w fp, r7, asr #21 + 23882: f8cd 9094 str.w r9, [sp, #148] ; 0x94 + 23886: e9d8 6700 ldrd r6, r7, [r8] + 2388a: e9dd 8900 ldrd r8, r9, [sp] + 2388e: eb16 0608 adds.w r6, r6, r8 + 23892: eb47 0709 adc.w r7, r7, r9 + 23896: f50d 79a0 add.w r9, sp, #320 ; 0x140 + 2389a: e9c9 6700 strd r6, r7, [r9] + 2389e: f8dd 9004 ldr.w r9, [sp, #4] + 238a2: f50d 7880 add.w r8, sp, #256 ; 0x100 + 238a6: ea4f 5949 mov.w r9, r9, lsl #21 + 238aa: e9d8 6700 ldrd r6, r7, [r8] + 238ae: f8cd 9044 str.w r9, [sp, #68] ; 0x44 + 238b2: e9dd 8904 ldrd r8, r9, [sp, #16] + 238b6: eb16 0608 adds.w r6, r6, r8 + 238ba: eb47 0709 adc.w r7, r7, r9 + 238be: f8dd e0bc ldr.w lr, [sp, #188] ; 0xbc + 238c2: f50d 799c add.w r9, sp, #312 ; 0x138 + 238c6: e9c9 6700 strd r6, r7, [r9] + 238ca: f8dd 9014 ldr.w r9, [sp, #20] + 238ce: ea4f 5e6e mov.w lr, lr, asr #21 + 238d2: f8cd e00c str.w lr, [sp, #12] + 238d6: f50d 78ac add.w r8, sp, #344 ; 0x158 + 238da: ea4f 5949 mov.w r9, r9, lsl #21 + 238de: e9d8 6700 ldrd r6, r7, [r8] + 238e2: f8cd 9034 str.w r9, [sp, #52] ; 0x34 + 238e6: e9dd 8902 ldrd r8, r9, [sp, #8] + 238ea: eb16 0608 adds.w r6, r6, r8 + 238ee: eb47 0709 adc.w r7, r7, r9 + 238f2: f50d 79ac add.w r9, sp, #344 ; 0x158 + 238f6: e9c9 6700 strd r6, r7, [r9] + 238fa: f8dd 900c ldr.w r9, [sp, #12] + 238fe: f50d 78a8 add.w r8, sp, #336 ; 0x150 + 23902: ea4f 5949 mov.w r9, r9, lsl #21 + 23906: e9d8 6700 ldrd r6, r7, [r8] + 2390a: f8cd 9054 str.w r9, [sp, #84] ; 0x54 + 2390e: e9dd 8918 ldrd r8, r9, [sp, #96] ; 0x60 + 23912: eb16 0608 adds.w r6, r6, r8 + 23916: eb47 0709 adc.w r7, r7, r9 + 2391a: f50d 78bc add.w r8, sp, #376 ; 0x178 + 2391e: f50d 7998 add.w r9, sp, #304 ; 0x130 + 23922: e9c9 6700 strd r6, r7, [r9] + 23926: e9d8 6700 ldrd r6, r7, [r8] + 2392a: eb16 060a adds.w r6, r6, sl + 2392e: eb47 070b adc.w r7, r7, fp + 23932: f50d 78a8 add.w r8, sp, #336 ; 0x150 + 23936: e9c8 6700 strd r6, r7, [r8] + 2393a: f8dd 9064 ldr.w r9, [sp, #100] ; 0x64 + 2393e: f50d 78b8 add.w r8, sp, #368 ; 0x170 + 23942: e9d8 6700 ldrd r6, r7, [r8] + 23946: ea4f 5949 mov.w r9, r9, lsl #21 + 2394a: 1936 adds r6, r6, r4 + 2394c: f8dd c084 ldr.w ip, [sp, #132] ; 0x84 + 23950: 416f adcs r7, r5 + 23952: f8cd 9024 str.w r9, [sp, #36] ; 0x24 + 23956: f50d 7880 add.w r8, sp, #256 ; 0x100 + 2395a: ea4f 594b mov.w r9, fp, lsl #21 + 2395e: f8dd e07c ldr.w lr, [sp, #124] ; 0x7c + 23962: f8cd 905c str.w r9, [sp, #92] ; 0x5c + 23966: e9c8 6700 strd r6, r7, [r8] + 2396a: f50d 78b4 add.w r8, sp, #360 ; 0x168 + 2396e: ea4f 516c mov.w r1, ip, asr #21 + 23972: e9d8 6700 ldrd r6, r7, [r8] + 23976: 1836 adds r6, r6, r0 + 23978: 414f adcs r7, r1 + 2397a: f8dd c094 ldr.w ip, [sp, #148] ; 0x94 + 2397e: f50d 78b0 add.w r8, sp, #352 ; 0x160 + 23982: ea4f 536e mov.w r3, lr, asr #21 + 23986: e9cd 672c strd r6, r7, [sp, #176] ; 0xb0 + 2398a: e9d8 6700 ldrd r6, r7, [r8] + 2398e: 18b6 adds r6, r6, r2 + 23990: 415f adcs r7, r3 + 23992: ea4f 5c4c mov.w ip, ip, lsl #21 + 23996: f8cd c06c str.w ip, [sp, #108] ; 0x6c + 2399a: e9cd 6734 strd r6, r7, [sp, #208] ; 0xd0 + 2399e: f8dd c044 ldr.w ip, [sp, #68] ; 0x44 + 239a2: f8dd e000 ldr.w lr, [sp] + 239a6: 9e0d ldr r6, [sp, #52] ; 0x34 + 239a8: 9f04 ldr r7, [sp, #16] + 239aa: ea4c 2cde orr.w ip, ip, lr, lsr #11 + 239ae: ea46 26d7 orr.w r6, r6, r7, lsr #11 + 239b2: f8dd e008 ldr.w lr, [sp, #8] + 239b6: 9f18 ldr r7, [sp, #96] ; 0x60 + 239b8: f8cd c044 str.w ip, [sp, #68] ; 0x44 + 239bc: 960d str r6, [sp, #52] ; 0x34 + 239be: f8dd c054 ldr.w ip, [sp, #84] ; 0x54 + 239c2: 9e09 ldr r6, [sp, #36] ; 0x24 + 239c4: ea4f 5945 mov.w r9, r5, lsl #21 + 239c8: f8cd 903c str.w r9, [sp, #60] ; 0x3c + 239cc: ea4c 2cde orr.w ip, ip, lr, lsr #11 + 239d0: ea46 26d7 orr.w r6, r6, r7, lsr #11 + 239d4: f8dd e03c ldr.w lr, [sp, #60] ; 0x3c + 239d8: 9f24 ldr r7, [sp, #144] ; 0x90 + 239da: f8cd c054 str.w ip, [sp, #84] ; 0x54 + 239de: 9609 str r6, [sp, #36] ; 0x24 + 239e0: f8dd c05c ldr.w ip, [sp, #92] ; 0x5c + 239e4: 9e1b ldr r6, [sp, #108] ; 0x6c + 239e6: ea4f 5941 mov.w r9, r1, lsl #21 + 239ea: f8cd 902c str.w r9, [sp, #44] ; 0x2c + 239ee: ea4c 2cda orr.w ip, ip, sl, lsr #11 + 239f2: ea4e 2ed4 orr.w lr, lr, r4, lsr #11 + 239f6: ea46 26d7 orr.w r6, r6, r7, lsr #11 + 239fa: f8cd c05c str.w ip, [sp, #92] ; 0x5c + 239fe: f8cd e03c str.w lr, [sp, #60] ; 0x3c + 23a02: f8dd c02c ldr.w ip, [sp, #44] ; 0x2c + 23a06: 961b str r6, [sp, #108] ; 0x6c + 23a08: f8dd e000 ldr.w lr, [sp] + 23a0c: 9e04 ldr r6, [sp, #16] + 23a0e: 9f02 ldr r7, [sp, #8] + 23a10: ea4c 2cd0 orr.w ip, ip, r0, lsr #11 + 23a14: ea4f 5e4e mov.w lr, lr, lsl #21 + 23a18: 0576 lsls r6, r6, #21 + 23a1a: 057f lsls r7, r7, #21 + 23a1c: f8cd c02c str.w ip, [sp, #44] ; 0x2c + 23a20: f8cd e040 str.w lr, [sp, #64] ; 0x40 + 23a24: 960c str r6, [sp, #48] ; 0x30 + 23a26: 9714 str r7, [sp, #80] ; 0x50 + 23a28: 9f24 ldr r7, [sp, #144] ; 0x90 + 23a2a: f8dd c060 ldr.w ip, [sp, #96] ; 0x60 + 23a2e: ea4f 5943 mov.w r9, r3, lsl #21 + 23a32: ea49 29d2 orr.w r9, r9, r2, lsr #11 + 23a36: ea4f 5e4a mov.w lr, sl, lsl #21 + 23a3a: 0566 lsls r6, r4, #21 + 23a3c: ea4f 5a40 mov.w sl, r0, lsl #21 + 23a40: e9dd 4510 ldrd r4, r5, [sp, #64] ; 0x40 + 23a44: ea4f 5842 mov.w r8, r2, lsl #21 + 23a48: 057f lsls r7, r7, #21 + 23a4a: e9dd 2336 ldrd r2, r3, [sp, #216] ; 0xd8 + 23a4e: 1b12 subs r2, r2, r4 + 23a50: 960e str r6, [sp, #56] ; 0x38 + 23a52: 971a str r7, [sp, #104] ; 0x68 + 23a54: f8cd a028 str.w sl, [sp, #40] ; 0x28 + 23a58: e9dd 6738 ldrd r6, r7, [sp, #224] ; 0xe0 + 23a5c: e9dd ab0c ldrd sl, fp, [sp, #48] ; 0x30 + 23a60: eb63 0305 sbc.w r3, r3, r5 + 23a64: ea4f 5c4c mov.w ip, ip, lsl #21 + 23a68: ebb6 060a subs.w r6, r6, sl + 23a6c: ad5a add r5, sp, #360 ; 0x168 + 23a6e: e9c5 2300 strd r2, r3, [r5] + 23a72: e9dd 4514 ldrd r4, r5, [sp, #80] ; 0x50 + 23a76: e9dd 233c ldrd r2, r3, [sp, #240] ; 0xf0 + 23a7a: f8cd c020 str.w ip, [sp, #32] + 23a7e: eb67 070b sbc.w r7, r7, fp + 23a82: f50d 7a8c add.w sl, sp, #280 ; 0x118 + 23a86: 1b12 subs r2, r2, r4 + 23a88: f50d 7bb0 add.w fp, sp, #352 ; 0x160 + 23a8c: e9cb 6700 strd r6, r7, [fp] + 23a90: e9da 6700 ldrd r6, r7, [sl] + 23a94: e9dd ab08 ldrd sl, fp, [sp, #32] + 23a98: f8cd e058 str.w lr, [sp, #88] ; 0x58 + 23a9c: eb63 0305 sbc.w r3, r3, r5 + 23aa0: ebb6 060a subs.w r6, r6, sl + 23aa4: ad5c add r5, sp, #368 ; 0x170 + 23aa6: e9c5 2300 strd r2, r3, [r5] + 23aaa: e9dd 4516 ldrd r4, r5, [sp, #88] ; 0x58 + 23aae: e9dd 233a ldrd r2, r3, [sp, #232] ; 0xe8 + 23ab2: eb67 070b sbc.w r7, r7, fp + 23ab6: f50d 7aa4 add.w sl, sp, #328 ; 0x148 + 23aba: 1b12 subs r2, r2, r4 + 23abc: f50d 7b8c add.w fp, sp, #280 ; 0x118 + 23ac0: e9cb 6700 strd r6, r7, [fp] + 23ac4: e9da 6700 ldrd r6, r7, [sl] + 23ac8: e9dd ab0e ldrd sl, fp, [sp, #56] ; 0x38 + 23acc: eb63 0305 sbc.w r3, r3, r5 + 23ad0: ebb6 060a subs.w r6, r6, sl + 23ad4: ad5e add r5, sp, #376 ; 0x178 + 23ad6: e9c5 2300 strd r2, r3, [r5] + 23ada: eb67 070b sbc.w r7, r7, fp + 23ade: ab64 add r3, sp, #400 ; 0x190 + 23ae0: f50d 7ba4 add.w fp, sp, #328 ; 0x148 + 23ae4: e9cb 6700 strd r6, r7, [fp] + 23ae8: e9d3 0100 ldrd r0, r1, [r3] + 23aec: e9dd 2324 ldrd r2, r3, [sp, #144] ; 0x90 + 23af0: af4a add r7, sp, #296 ; 0x128 + 23af2: 1880 adds r0, r0, r2 + 23af4: 4159 adcs r1, r3 + 23af6: e9d7 4500 ldrd r4, r5, [r7] + 23afa: f50d 7c90 add.w ip, sp, #288 ; 0x120 + 23afe: e9dd 670a ldrd r6, r7, [sp, #40] ; 0x28 + 23b02: 1ba4 subs r4, r4, r6 + 23b04: eb65 0507 sbc.w r5, r5, r7 + 23b08: e9dc ab00 ldrd sl, fp, [ip] + 23b0c: ebba 0a08 subs.w sl, sl, r8 + 23b10: eb6b 0b09 sbc.w fp, fp, r9 + 23b14: e9dd 233e ldrd r2, r3, [sp, #248] ; 0xf8 + 23b18: e9cd 453a strd r4, r5, [sp, #232] ; 0xe8 + 23b1c: e9dd 451a ldrd r4, r5, [sp, #104] ; 0x68 + 23b20: 1b12 subs r2, r2, r4 + 23b22: eb63 0305 sbc.w r3, r3, r5 + 23b26: af42 add r7, sp, #264 ; 0x108 + 23b28: e9cd 0138 strd r0, r1, [sp, #224] ; 0xe0 + 23b2c: e9cd ab3c strd sl, fp, [sp, #240] ; 0xf0 + 23b30: f50d 7c88 add.w ip, sp, #272 ; 0x110 + 23b34: e9cd 233e strd r2, r3, [sp, #248] ; 0xf8 + 23b38: e9d7 8900 ldrd r8, r9, [r7] + 23b3c: e9dc ab00 ldrd sl, fp, [ip] + 23b40: f518 1880 adds.w r8, r8, #1048576 ; 0x100000 + 23b44: f149 0900 adc.w r9, r9, #0 + 23b48: f51a 1a80 adds.w sl, sl, #1048576 ; 0x100000 + 23b4c: f14b 0b00 adc.w fp, fp, #0 + 23b50: e9cd ab08 strd sl, fp, [sp, #32] + 23b54: f04f 0a00 mov.w sl, #0 + 23b58: 4654 mov r4, sl + 23b5a: aa50 add r2, sp, #320 ; 0x140 + 23b5c: e9d2 0100 ldrd r0, r1, [r2] + 23b60: f510 1080 adds.w r0, r0, #1048576 ; 0x100000 + 23b64: f04f 0b00 mov.w fp, #0 + 23b68: f141 0100 adc.w r1, r1, #0 + 23b6c: e9cd 0130 strd r0, r1, [sp, #192] ; 0xc0 + 23b70: 465d mov r5, fp + 23b72: 4620 mov r0, r4 + 23b74: f50d 7a9c add.w sl, sp, #312 ; 0x138 + 23b78: e9da 6700 ldrd r6, r7, [sl] + 23b7c: f516 1680 adds.w r6, r6, #1048576 ; 0x100000 + 23b80: f147 0700 adc.w r7, r7, #0 + 23b84: e9cd 672a strd r6, r7, [sp, #168] ; 0xa8 + 23b88: 4606 mov r6, r0 + 23b8a: 462f mov r7, r5 + 23b8c: 4659 mov r1, fp + 23b8e: e9cd 4506 strd r4, r5, [sp, #24] + 23b92: ac56 add r4, sp, #344 ; 0x158 + 23b94: e9d4 2300 ldrd r2, r3, [r4] + 23b98: f50d 7c98 add.w ip, sp, #304 ; 0x130 + 23b9c: f512 1280 adds.w r2, r2, #1048576 ; 0x100000 + 23ba0: e9dc ab00 ldrd sl, fp, [ip] + 23ba4: f143 0300 adc.w r3, r3, #0 + 23ba8: f51a 1a80 adds.w sl, sl, #1048576 ; 0x100000 + 23bac: f14b 0b00 adc.w fp, fp, #0 + 23bb0: ac54 add r4, sp, #336 ; 0x150 + 23bb2: e9cd ab24 strd sl, fp, [sp, #144] ; 0x90 + 23bb6: e9cd 2332 strd r2, r3, [sp, #200] ; 0xc8 + 23bba: e9d4 2300 ldrd r2, r3, [r4] + 23bbe: f50d 7a80 add.w sl, sp, #256 ; 0x100 + 23bc2: f512 1280 adds.w r2, r2, #1048576 ; 0x100000 + 23bc6: e9cd 670a strd r6, r7, [sp, #40] ; 0x28 + 23bca: e9da 6700 ldrd r6, r7, [sl] + 23bce: f143 0300 adc.w r3, r3, #0 + 23bd2: f516 1680 adds.w r6, r6, #1048576 ; 0x100000 + 23bd6: e9cd 0102 strd r0, r1, [sp, #8] + 23bda: e9cd 0100 strd r0, r1, [sp] + 23bde: e9dd 012c ldrd r0, r1, [sp, #176] ; 0xb0 + 23be2: f147 0700 adc.w r7, r7, #0 + 23be6: f510 1080 adds.w r0, r0, #1048576 ; 0x100000 + 23bea: e9cd 232e strd r2, r3, [sp, #184] ; 0xb8 + 23bee: e9dd 2334 ldrd r2, r3, [sp, #208] ; 0xd0 + 23bf2: f141 0100 adc.w r1, r1, #0 + 23bf6: f512 1280 adds.w r2, r2, #1048576 ; 0x100000 + 23bfa: f143 0300 adc.w r3, r3, #0 + 23bfe: e9cd 230e strd r2, r3, [sp, #56] ; 0x38 + 23c02: ea4f 5358 mov.w r3, r8, lsr #21 + 23c06: ea43 24c9 orr.w r4, r3, r9, lsl #11 + 23c0a: ea4f 5569 mov.w r5, r9, asr #21 + 23c0e: 9404 str r4, [sp, #16] + 23c10: 9505 str r5, [sp, #20] + 23c12: e9cd 6728 strd r6, r7, [sp, #160] ; 0xa0 + 23c16: e9dd 671c ldrd r6, r7, [sp, #112] ; 0x70 + 23c1a: f50d 7bc0 add.w fp, sp, #384 ; 0x180 + 23c1e: f516 1680 adds.w r6, r6, #1048576 ; 0x100000 + 23c22: e9db 8900 ldrd r8, r9, [fp] + 23c26: f147 0700 adc.w r7, r7, #0 + 23c2a: e9dd ab04 ldrd sl, fp, [sp, #16] + 23c2e: eb18 080a adds.w r8, r8, sl + 23c32: e9cd 0126 strd r0, r1, [sp, #152] ; 0x98 + 23c36: eb49 090b adc.w r9, r9, fp + 23c3a: 2000 movs r0, #0 + 23c3c: 2100 movs r1, #0 + 23c3e: e9cd 6718 strd r6, r7, [sp, #96] ; 0x60 + 23c42: e9cd 8936 strd r8, r9, [sp, #216] ; 0xd8 + 23c46: 4604 mov r4, r0 + 23c48: 460d mov r5, r1 + 23c4a: 4606 mov r6, r0 + 23c4c: 460f mov r7, r1 + 23c4e: 4680 mov r8, r0 + 23c50: 4689 mov r9, r1 + 23c52: aa48 add r2, sp, #288 ; 0x120 + 23c54: e9c2 0100 strd r0, r1, [r2] + 23c58: 460b mov r3, r1 + 23c5a: 4602 mov r2, r0 + 23c5c: 4682 mov sl, r0 + 23c5e: 468b mov fp, r1 + 23c60: e9cd 451e strd r4, r5, [sp, #120] ; 0x78 + 23c64: e9cd 671a strd r6, r7, [sp, #104] ; 0x68 + 23c68: e9cd 8920 strd r8, r9, [sp, #128] ; 0x80 + 23c6c: f8dd 80c0 ldr.w r8, [sp, #192] ; 0xc0 + 23c70: f8dd 90a8 ldr.w r9, [sp, #168] ; 0xa8 + 23c74: f8dd c0c8 ldr.w ip, [sp, #200] ; 0xc8 + 23c78: f8dd e090 ldr.w lr, [sp, #144] ; 0x90 + 23c7c: e9cd 670c strd r6, r7, [sp, #48] ; 0x30 + 23c80: ea4f 5858 mov.w r8, r8, lsr #21 + 23c84: 9f08 ldr r7, [sp, #32] + 23c86: ea4f 5959 mov.w r9, r9, lsr #21 + 23c8a: f8cd 8018 str.w r8, [sp, #24] + 23c8e: f8cd 9008 str.w r9, [sp, #8] + 23c92: e9cd 0122 strd r0, r1, [sp, #136] ; 0x88 + 23c96: e9cd 2314 strd r2, r3, [sp, #80] ; 0x50 + 23c9a: e9cd 4510 strd r4, r5, [sp, #64] ; 0x40 + 23c9e: 982e ldr r0, [sp, #184] ; 0xb8 + 23ca0: 9a28 ldr r2, [sp, #160] ; 0xa0 + 23ca2: 9c26 ldr r4, [sp, #152] ; 0x98 + 23ca4: f8dd 8038 ldr.w r8, [sp, #56] ; 0x38 + 23ca8: f8dd 9024 ldr.w r9, [sp, #36] ; 0x24 + 23cac: ea4f 5c5c mov.w ip, ip, lsr #21 + 23cb0: ea4f 5e5e mov.w lr, lr, lsr #21 + 23cb4: f8cd c028 str.w ip, [sp, #40] ; 0x28 + 23cb8: f8cd e000 str.w lr, [sp] + 23cbc: e9cd ab16 strd sl, fp, [sp, #88] ; 0x58 + 23cc0: f8dd c018 ldr.w ip, [sp, #24] + 23cc4: f8dd e0c4 ldr.w lr, [sp, #196] ; 0xc4 + 23cc8: ea4f 5a57 mov.w sl, r7, lsr #21 + 23ccc: ea4a 2ac9 orr.w sl, sl, r9, lsl #11 + 23cd0: 0d46 lsrs r6, r0, #21 + 23cd2: f8dd 90ac ldr.w r9, [sp, #172] ; 0xac + 23cd6: 0d50 lsrs r0, r2, #21 + 23cd8: 0d62 lsrs r2, r4, #21 + 23cda: ea4f 5458 mov.w r4, r8, lsr #21 + 23cde: f8dd 8008 ldr.w r8, [sp, #8] + 23ce2: ea4c 2cce orr.w ip, ip, lr, lsl #11 + 23ce6: f8cd c018 str.w ip, [sp, #24] + 23cea: f8dd e0cc ldr.w lr, [sp, #204] ; 0xcc + 23cee: f8dd c028 ldr.w ip, [sp, #40] ; 0x28 + 23cf2: ea48 28c9 orr.w r8, r8, r9, lsl #11 + 23cf6: f8cd 8008 str.w r8, [sp, #8] + 23cfa: f8dd 9094 ldr.w r9, [sp, #148] ; 0x94 + 23cfe: f8dd 8000 ldr.w r8, [sp] + 23d02: ea4c 2cce orr.w ip, ip, lr, lsl #11 + 23d06: f8cd c028 str.w ip, [sp, #40] ; 0x28 + 23d0a: ea48 28c9 orr.w r8, r8, r9, lsl #11 + 23d0e: f8dd c0bc ldr.w ip, [sp, #188] ; 0xbc + 23d12: f8dd 903c ldr.w r9, [sp, #60] ; 0x3c + 23d16: f8cd 8000 str.w r8, [sp] + 23d1a: f8dd 809c ldr.w r8, [sp, #156] ; 0x9c + 23d1e: ea46 26cc orr.w r6, r6, ip, lsl #11 + 23d22: f8dd e0a4 ldr.w lr, [sp, #164] ; 0xa4 + 23d26: f8dd c024 ldr.w ip, [sp, #36] ; 0x24 + 23d2a: ea42 22c8 orr.w r2, r2, r8, lsl #11 + 23d2e: ea44 24c9 orr.w r4, r4, r9, lsl #11 + 23d32: f04f 0800 mov.w r8, #0 + 23d36: f04f 0900 mov.w r9, #0 + 23d3a: e9cd 8908 strd r8, r9, [sp, #32] + 23d3e: ea40 20ce orr.w r0, r0, lr, lsl #11 + 23d42: ea4f 5b6c mov.w fp, ip, asr #21 + 23d46: f8dd e0cc ldr.w lr, [sp, #204] ; 0xcc + 23d4a: f8dd c0ac ldr.w ip, [sp, #172] ; 0xac + 23d4e: f8dd 90c4 ldr.w r9, [sp, #196] ; 0xc4 + 23d52: ea4f 5c6c mov.w ip, ip, asr #21 + 23d56: ea4f 5e6e mov.w lr, lr, asr #21 + 23d5a: f8cd c00c str.w ip, [sp, #12] + 23d5e: f8cd e02c str.w lr, [sp, #44] ; 0x2c + 23d62: f8dd c0a4 ldr.w ip, [sp, #164] ; 0xa4 + 23d66: f8dd e09c ldr.w lr, [sp, #156] ; 0x9c + 23d6a: f8dd 8094 ldr.w r8, [sp, #148] ; 0x94 + 23d6e: ea4f 5969 mov.w r9, r9, asr #21 + 23d72: f8cd 901c str.w r9, [sp, #28] + 23d76: ea4f 516c mov.w r1, ip, asr #21 + 23d7a: f8dd 90bc ldr.w r9, [sp, #188] ; 0xbc + 23d7e: ea4f 536e mov.w r3, lr, asr #21 + 23d82: f8dd c01c ldr.w ip, [sp, #28] + 23d86: f8dd e00c ldr.w lr, [sp, #12] + 23d8a: ea4f 5868 mov.w r8, r8, asr #21 + 23d8e: f8cd 8004 str.w r8, [sp, #4] + 23d92: f8dd 803c ldr.w r8, [sp, #60] ; 0x3c + 23d96: ea4f 5769 mov.w r7, r9, asr #21 + 23d9a: ea4f 5c4c mov.w ip, ip, lsl #21 + 23d9e: ea4f 594b mov.w r9, fp, lsl #21 + 23da2: ea4f 5e4e mov.w lr, lr, lsl #21 + 23da6: f8cd 9124 str.w r9, [sp, #292] ; 0x124 + 23daa: f8cd c07c str.w ip, [sp, #124] ; 0x7c + 23dae: ea4f 5568 mov.w r5, r8, asr #21 + 23db2: f8cd e06c str.w lr, [sp, #108] ; 0x6c + 23db6: f8dd 802c ldr.w r8, [sp, #44] ; 0x2c + 23dba: f8dd 9004 ldr.w r9, [sp, #4] + 23dbe: ea4f 5c47 mov.w ip, r7, lsl #21 + 23dc2: ea4f 5e41 mov.w lr, r1, lsl #21 + 23dc6: f8cd c08c str.w ip, [sp, #140] ; 0x8c + 23dca: f8cd e054 str.w lr, [sp, #84] ; 0x54 + 23dce: f8dd c014 ldr.w ip, [sp, #20] + 23dd2: f8dd e124 ldr.w lr, [sp, #292] ; 0x124 + 23dd6: ea4f 5848 mov.w r8, r8, lsl #21 + 23dda: ea4f 5949 mov.w r9, r9, lsl #21 + 23dde: f8cd 8084 str.w r8, [sp, #132] ; 0x84 + 23de2: f8cd 905c str.w r9, [sp, #92] ; 0x5c + 23de6: ea4f 5843 mov.w r8, r3, lsl #21 + 23dea: ea4f 5945 mov.w r9, r5, lsl #21 + 23dee: ea4e 2eda orr.w lr, lr, sl, lsr #11 + 23df2: ea4f 5c4c mov.w ip, ip, lsl #21 + 23df6: f8cd 8044 str.w r8, [sp, #68] ; 0x44 + 23dfa: f8cd 9034 str.w r9, [sp, #52] ; 0x34 + 23dfe: f8dd 807c ldr.w r8, [sp, #124] ; 0x7c + 23e02: f8dd 9018 ldr.w r9, [sp, #24] + 23e06: f8cd c024 str.w ip, [sp, #36] ; 0x24 + 23e0a: f8cd e124 str.w lr, [sp, #292] ; 0x124 + 23e0e: f8dd c06c ldr.w ip, [sp, #108] ; 0x6c + 23e12: f8dd e008 ldr.w lr, [sp, #8] + 23e16: ea48 28d9 orr.w r8, r8, r9, lsr #11 + 23e1a: ea4c 2cde orr.w ip, ip, lr, lsr #11 + 23e1e: f8cd 807c str.w r8, [sp, #124] ; 0x7c + 23e22: f8cd c06c str.w ip, [sp, #108] ; 0x6c + 23e26: f8dd 8084 ldr.w r8, [sp, #132] ; 0x84 + 23e2a: f8dd 9028 ldr.w r9, [sp, #40] ; 0x28 + 23e2e: f8dd c05c ldr.w ip, [sp, #92] ; 0x5c + 23e32: f8dd e000 ldr.w lr, [sp] + 23e36: ea48 28d9 orr.w r8, r8, r9, lsr #11 + 23e3a: f8cd 8084 str.w r8, [sp, #132] ; 0x84 + 23e3e: f8dd 9054 ldr.w r9, [sp, #84] ; 0x54 + 23e42: f8dd 808c ldr.w r8, [sp, #140] ; 0x8c + 23e46: ea4c 2cde orr.w ip, ip, lr, lsr #11 + 23e4a: f8cd c05c str.w ip, [sp, #92] ; 0x5c + 23e4e: f8dd c044 ldr.w ip, [sp, #68] ; 0x44 + 23e52: f8dd e034 ldr.w lr, [sp, #52] ; 0x34 + 23e56: ea48 28d6 orr.w r8, r8, r6, lsr #11 + 23e5a: ea49 29d0 orr.w r9, r9, r0, lsr #11 + 23e5e: f8cd 808c str.w r8, [sp, #140] ; 0x8c + 23e62: f8cd 9054 str.w r9, [sp, #84] ; 0x54 + 23e66: f8dd 8024 ldr.w r8, [sp, #36] ; 0x24 + 23e6a: f8dd 9010 ldr.w r9, [sp, #16] + 23e6e: ea4c 2cd2 orr.w ip, ip, r2, lsr #11 + 23e72: f8cd c044 str.w ip, [sp, #68] ; 0x44 + 23e76: ea4e 2ed4 orr.w lr, lr, r4, lsr #11 + 23e7a: ea4f 5c4a mov.w ip, sl, lsl #21 + 23e7e: f8cd e034 str.w lr, [sp, #52] ; 0x34 + 23e82: ea48 28d9 orr.w r8, r8, r9, lsr #11 + 23e86: f8cd c120 str.w ip, [sp, #288] ; 0x120 + 23e8a: f8dd e018 ldr.w lr, [sp, #24] + 23e8e: f8dd c000 ldr.w ip, [sp] + 23e92: f8cd 8024 str.w r8, [sp, #36] ; 0x24 + 23e96: f8dd 9028 ldr.w r9, [sp, #40] ; 0x28 + 23e9a: f8dd 8008 ldr.w r8, [sp, #8] + 23e9e: ea4f 5e4e mov.w lr, lr, lsl #21 + 23ea2: ea4f 5c4c mov.w ip, ip, lsl #21 + 23ea6: f8cd e078 str.w lr, [sp, #120] ; 0x78 + 23eaa: f8cd c058 str.w ip, [sp, #88] ; 0x58 + 23eae: ea4f 5e46 mov.w lr, r6, lsl #21 + 23eb2: ea4f 5c44 mov.w ip, r4, lsl #21 + 23eb6: ea4f 5848 mov.w r8, r8, lsl #21 + 23eba: ea4f 5949 mov.w r9, r9, lsl #21 + 23ebe: f8cd 8068 str.w r8, [sp, #104] ; 0x68 + 23ec2: f8cd 9080 str.w r9, [sp, #128] ; 0x80 + 23ec6: f8cd e088 str.w lr, [sp, #136] ; 0x88 + 23eca: ea4f 5840 mov.w r8, r0, lsl #21 + 23ece: ea4f 5942 mov.w r9, r2, lsl #21 + 23ed2: f8cd c030 str.w ip, [sp, #48] ; 0x30 + 23ed6: f8dd e010 ldr.w lr, [sp, #16] + 23eda: f50d 7cb4 add.w ip, sp, #360 ; 0x168 + 23ede: f8cd 8050 str.w r8, [sp, #80] ; 0x50 + 23ee2: f8cd 9040 str.w r9, [sp, #64] ; 0x40 + 23ee6: e9dc 8900 ldrd r8, r9, [ip] + 23eea: eb18 080a adds.w r8, r8, sl + 23eee: eb49 090b adc.w r9, r9, fp + 23ef2: ea4f 5e4e mov.w lr, lr, lsl #21 + 23ef6: f50d 7b88 add.w fp, sp, #272 ; 0x110 + 23efa: f50d 7a90 add.w sl, sp, #288 ; 0x120 + 23efe: f8cd e020 str.w lr, [sp, #32] + 23f02: e9cd 8928 strd r8, r9, [sp, #160] ; 0xa0 + 23f06: e9db 8900 ldrd r8, r9, [fp] + 23f0a: e89a 0c00 ldmia.w sl, {sl, fp} + 23f0e: ebb8 080a subs.w r8, r8, sl + 23f12: eb69 090b sbc.w r9, r9, fp + 23f16: f50d 7bb8 add.w fp, sp, #368 ; 0x170 + 23f1a: e9cd 8924 strd r8, r9, [sp, #144] ; 0x90 + 23f1e: e9db 8900 ldrd r8, r9, [fp] + 23f22: e9dd ab06 ldrd sl, fp, [sp, #24] + 23f26: eb18 080a adds.w r8, r8, sl + 23f2a: eb49 090b adc.w r9, r9, fp + 23f2e: f8dd c064 ldr.w ip, [sp, #100] ; 0x64 + 23f32: e9cd 892a strd r8, r9, [sp, #168] ; 0xa8 + 23f36: f8dd 8060 ldr.w r8, [sp, #96] ; 0x60 + 23f3a: f8dd 9064 ldr.w r9, [sp, #100] ; 0x64 + 23f3e: ea4f 5c6c mov.w ip, ip, asr #21 + 23f42: f8cd c038 str.w ip, [sp, #56] ; 0x38 + 23f46: ea4f 5e4c mov.w lr, ip, lsl #21 + 23f4a: ea4f 5c58 mov.w ip, r8, lsr #21 + 23f4e: ea4c 2cc9 orr.w ip, ip, r9, lsl #11 + 23f52: ea4f 5b4c mov.w fp, ip, lsl #21 + 23f56: ea4e 2adc orr.w sl, lr, ip, lsr #11 + 23f5a: f8cd b110 str.w fp, [sp, #272] ; 0x110 + 23f5e: f50d 7ba0 add.w fp, sp, #320 ; 0x140 + 23f62: e9db 8900 ldrd r8, r9, [fp] + 23f66: f8cd a114 str.w sl, [sp, #276] ; 0x114 + 23f6a: e9dd ab1e ldrd sl, fp, [sp, #120] ; 0x78 + 23f6e: ebb8 080a subs.w r8, r8, sl + 23f72: eb69 090b sbc.w r9, r9, fp + 23f76: f50d 7bc4 add.w fp, sp, #392 ; 0x188 + 23f7a: e9cd 8930 strd r8, r9, [sp, #192] ; 0xc0 + 23f7e: e9db 8900 ldrd r8, r9, [fp] + 23f82: e9dd ab02 ldrd sl, fp, [sp, #8] + 23f86: eb18 080a adds.w r8, r8, sl + 23f8a: eb49 090b adc.w r9, r9, fp + 23f8e: f50d 7b9c add.w fp, sp, #312 ; 0x138 + 23f92: e9cd 891e strd r8, r9, [sp, #120] ; 0x78 + 23f96: e9db 8900 ldrd r8, r9, [fp] + 23f9a: e9dd ab1a ldrd sl, fp, [sp, #104] ; 0x68 + 23f9e: ebb8 080a subs.w r8, r8, sl + 23fa2: eb69 090b sbc.w r9, r9, fp + 23fa6: f50d 7bbc add.w fp, sp, #376 ; 0x178 + 23faa: e9cd 8918 strd r8, r9, [sp, #96] ; 0x60 + 23fae: e9db 8900 ldrd r8, r9, [fp] + 23fb2: e9dd ab0a ldrd sl, fp, [sp, #40] ; 0x28 + 23fb6: eb18 080a adds.w r8, r8, sl + 23fba: eb49 090b adc.w r9, r9, fp + 23fbe: f50d 7aac add.w sl, sp, #344 ; 0x158 + 23fc2: e9cd 8932 strd r8, r9, [sp, #200] ; 0xc8 + 23fc6: e9da 8900 ldrd r8, r9, [sl] + 23fca: e9dd ab20 ldrd sl, fp, [sp, #128] ; 0x80 + 23fce: ebb8 080a subs.w r8, r8, sl + 23fd2: eb69 090b sbc.w r9, r9, fp + 23fd6: f50d 7b90 add.w fp, sp, #288 ; 0x120 + 23fda: e9cb 8900 strd r8, r9, [fp] + 23fde: f50d 7bb0 add.w fp, sp, #352 ; 0x160 + 23fe2: e9db 8900 ldrd r8, r9, [fp] + 23fe6: e9dd ab00 ldrd sl, fp, [sp] + 23fea: eb18 080a adds.w r8, r8, sl + 23fee: eb49 090b adc.w r9, r9, fp + 23ff2: f50d 7b98 add.w fp, sp, #304 ; 0x130 + 23ff6: e9cd 891a strd r8, r9, [sp, #104] ; 0x68 + 23ffa: e9db 8900 ldrd r8, r9, [fp] + 23ffe: e9dd ab16 ldrd sl, fp, [sp, #88] ; 0x58 + 24002: ebb8 080a subs.w r8, r8, sl + 24006: eb69 090b sbc.w r9, r9, fp + 2400a: e9cd 8926 strd r8, r9, [sp, #152] ; 0x98 + 2400e: e9dd 893e ldrd r8, r9, [sp, #248] ; 0xf8 + 24012: eb18 0806 adds.w r8, r8, r6 + 24016: eb49 0907 adc.w r9, r9, r7 + 2401a: ae54 add r6, sp, #336 ; 0x150 + 2401c: e9cd 8904 strd r8, r9, [sp, #16] + 24020: e9d6 ab00 ldrd sl, fp, [r6] + 24024: e9dd 6722 ldrd r6, r7, [sp, #136] ; 0x88 + 24028: ebba 0a06 subs.w sl, sl, r6 + 2402c: eb6b 0b07 sbc.w fp, fp, r7 + 24030: af4a add r7, sp, #296 ; 0x128 + 24032: e9c7 ab00 strd sl, fp, [r7] + 24036: f50d 7a8c add.w sl, sp, #280 ; 0x118 + 2403a: e9da 8900 ldrd r8, r9, [sl] + 2403e: ae40 add r6, sp, #256 ; 0x100 + 24040: eb18 0800 adds.w r8, r8, r0 + 24044: eb49 0901 adc.w r9, r9, r1 + 24048: f50d 7aa4 add.w sl, sp, #328 ; 0x148 + 2404c: e9d6 0100 ldrd r0, r1, [r6] + 24050: e9dd 6714 ldrd r6, r7, [sp, #80] ; 0x50 + 24054: 1b80 subs r0, r0, r6 + 24056: eb61 0107 sbc.w r1, r1, r7 + 2405a: e9cd 8920 strd r8, r9, [sp, #128] ; 0x80 + 2405e: e9da 8900 ldrd r8, r9, [sl] + 24062: e9dd ab0c ldrd sl, fp, [sp, #48] ; 0x30 + 24066: eb18 0802 adds.w r8, r8, r2 + 2406a: af40 add r7, sp, #256 ; 0x100 + 2406c: eb49 0903 adc.w r9, r9, r3 + 24070: e9c7 0100 strd r0, r1, [r7] + 24074: e9dd 2310 ldrd r2, r3, [sp, #64] ; 0x40 + 24078: e9dd 012c ldrd r0, r1, [sp, #176] ; 0xb0 + 2407c: 1a80 subs r0, r0, r2 + 2407e: eb61 0103 sbc.w r1, r1, r3 + 24082: e9dd 673a ldrd r6, r7, [sp, #232] ; 0xe8 + 24086: 1936 adds r6, r6, r4 + 24088: 416f adcs r7, r5 + 2408a: e9cd 893e strd r8, r9, [sp, #248] ; 0xf8 + 2408e: e9dd 8934 ldrd r8, r9, [sp, #208] ; 0xd0 + 24092: ab42 add r3, sp, #264 ; 0x108 + 24094: ebb8 080a subs.w r8, r8, sl + 24098: f642 4e13 movw lr, #11283 ; 0x2c13 + 2409c: eb69 090b sbc.w r9, r9, fp + 240a0: e9cd 012c strd r0, r1, [sp, #176] ; 0xb0 + 240a4: e9d3 0100 ldrd r0, r1, [r3] + 240a8: e9dd 2308 ldrd r2, r3, [sp, #32] + 240ac: ad44 add r5, sp, #272 ; 0x110 + 240ae: 1a80 subs r0, r0, r2 + 240b0: eb61 0103 sbc.w r1, r1, r3 + 240b4: e9dd ab1c ldrd sl, fp, [sp, #112] ; 0x70 + 240b8: e9d5 4500 ldrd r4, r5, [r5] + 240bc: ebba 0a04 subs.w sl, sl, r4 + 240c0: eb6b 0b05 sbc.w fp, fp, r5 + 240c4: e9cd 672e strd r6, r7, [sp, #184] ; 0xb8 + 240c8: e9dd 6738 ldrd r6, r7, [sp, #224] ; 0xe0 + 240cc: e9dd 4536 ldrd r4, r5, [sp, #216] ; 0xd8 + 240d0: f516 1680 adds.w r6, r6, #1048576 ; 0x100000 + 240d4: f147 0700 adc.w r7, r7, #0 + 240d8: e9cd 6700 strd r6, r7, [sp] + 240dc: f64f 3667 movw r6, #64359 ; 0xfb67 + 240e0: f642 5718 movw r7, #11544 ; 0x2d18 + 240e4: f2c0 0e0a movt lr, #10 + 240e8: f2c0 0609 movt r6, #9 + 240ec: f2c0 0707 movt r7, #7 + 240f0: f514 1480 adds.w r4, r4, #1048576 ; 0x100000 + 240f4: e9cd 8934 strd r8, r9, [sp, #208] ; 0xd0 + 240f8: f145 0500 adc.w r5, r5, #0 + 240fc: ea4f 5854 mov.w r8, r4, lsr #21 + 24100: ea48 28c5 orr.w r8, r8, r5, lsl #11 + 24104: e9cd 0108 strd r0, r1, [sp, #32] + 24108: ea4f 5965 mov.w r9, r5, asr #21 + 2410c: eb1a 0008 adds.w r0, sl, r8 + 24110: f8dd a000 ldr.w sl, [sp] + 24114: eb4b 0109 adc.w r1, fp, r9 + 24118: ea4f 5349 mov.w r3, r9, lsl #21 + 2411c: f8dd b004 ldr.w fp, [sp, #4] + 24120: e9cd 0102 strd r0, r1, [sp, #8] + 24124: ea43 23d8 orr.w r3, r3, r8, lsr #11 + 24128: ea4f 5248 mov.w r2, r8, lsl #21 + 2412c: ea4f 505a mov.w r0, sl, lsr #21 + 24130: fbac 890e umull r8, r9, ip, lr + 24134: ea40 20cb orr.w r0, r0, fp, lsl #11 + 24138: ea4f 516b mov.w r1, fp, asr #21 + 2413c: e9dd ab36 ldrd sl, fp, [sp, #216] ; 0xd8 + 24140: ebba 0a02 subs.w sl, sl, r2 + 24144: eb6b 0b03 sbc.w fp, fp, r3 + 24148: e9dd 2308 ldrd r2, r3, [sp, #32] + 2414c: 1812 adds r2, r2, r0 + 2414e: 414b adcs r3, r1 + 24150: e9cd 890a strd r8, r9, [sp, #40] ; 0x28 + 24154: e9cd ab06 strd sl, fp, [sp, #24] + 24158: e9cd 2300 strd r2, r3, [sp] + 2415c: 9b02 ldr r3, [sp, #8] + 2415e: fbac 8906 umull r8, r9, ip, r6 + 24162: fbac ab07 umull sl, fp, ip, r7 + 24166: fba3 230e umull r2, r3, r3, lr + 2416a: e9cd 8908 strd r8, r9, [sp, #32] + 2416e: e9cd ab10 strd sl, fp, [sp, #64] ; 0x40 + 24172: e9cd 230c strd r2, r3, [sp, #48] ; 0x30 + 24176: f8dd a02c ldr.w sl, [sp, #44] ; 0x2c + 2417a: 9a09 ldr r2, [sp, #36] ; 0x24 + 2417c: f8dd 9038 ldr.w r9, [sp, #56] ; 0x38 + 24180: f8dd b038 ldr.w fp, [sp, #56] ; 0x38 + 24184: fb0e a909 mla r9, lr, r9, sl + 24188: fb06 2b0b mla fp, r6, fp, r2 + 2418c: f8cd 902c str.w r9, [sp, #44] ; 0x2c + 24190: f8cd b024 str.w fp, [sp, #36] ; 0x24 + 24194: f8dd 9044 ldr.w r9, [sp, #68] ; 0x44 + 24198: f8dd b034 ldr.w fp, [sp, #52] ; 0x34 + 2419c: 9b0e ldr r3, [sp, #56] ; 0x38 + 2419e: f8dd a00c ldr.w sl, [sp, #12] + 241a2: fb07 9303 mla r3, r7, r3, r9 + 241a6: fb0e ba0a mla sl, lr, sl, fp + 241aa: 9311 str r3, [sp, #68] ; 0x44 + 241ac: f8cd a034 str.w sl, [sp, #52] ; 0x34 + 241b0: e9dd 230a ldrd r2, r3, [sp, #40] ; 0x28 + 241b4: e9dd ab24 ldrd sl, fp, [sp, #144] ; 0x90 + 241b8: eb12 020a adds.w r2, r2, sl + 241bc: eb43 030b adc.w r3, r3, fp + 241c0: e9cd 2322 strd r2, r3, [sp, #136] ; 0x88 + 241c4: e9dd ab30 ldrd sl, fp, [sp, #192] ; 0xc0 + 241c8: e9dd 2308 ldrd r2, r3, [sp, #32] + 241cc: eb12 020a adds.w r2, r2, sl + 241d0: eb43 030b adc.w r3, r3, fp + 241d4: e9cd 2324 strd r2, r3, [sp, #144] ; 0x90 + 241d8: e9dd ab10 ldrd sl, fp, [sp, #64] ; 0x40 + 241dc: e9dd 2328 ldrd r2, r3, [sp, #160] ; 0xa0 + 241e0: eb12 020a adds.w r2, r2, sl + 241e4: eb43 030b adc.w r3, r3, fp + 241e8: e9cd 231c strd r2, r3, [sp, #112] ; 0x70 + 241ec: e9dd ab1e ldrd sl, fp, [sp, #120] ; 0x78 + 241f0: e9dd 230c ldrd r2, r3, [sp, #48] ; 0x30 + 241f4: eb12 020a adds.w r2, r2, sl + 241f8: eb43 030b adc.w r3, r3, fp + 241fc: e9cd 2328 strd r2, r3, [sp, #160] ; 0xa0 + 24200: 9b06 ldr r3, [sp, #24] + 24202: ea4f 5b41 mov.w fp, r1, lsl #21 + 24206: fba3 230e umull r2, r3, r3, lr + 2420a: 9902 ldr r1, [sp, #8] + 2420c: e9cd 2310 strd r2, r3, [sp, #64] ; 0x40 + 24210: 9b02 ldr r3, [sp, #8] + 24212: ea4b 2bd0 orr.w fp, fp, r0, lsr #11 + 24216: fba3 2306 umull r2, r3, r3, r6 + 2421a: ea4f 5a40 mov.w sl, r0, lsl #21 + 2421e: fba1 0107 umull r0, r1, r1, r7 + 24222: e9cd 0108 strd r0, r1, [sp, #32] + 24226: e9dd 0138 ldrd r0, r1, [sp, #224] ; 0xe0 + 2422a: e9cd 230c strd r2, r3, [sp, #48] ; 0x30 + 2422e: f642 4213 movw r2, #11283 ; 0x2c13 + 24232: f24c 6453 movw r4, #50771 ; 0xc653 + 24236: f2c0 020a movt r2, #10 + 2423a: f6cf 74f0 movt r4, #65520 ; 0xfff0 + 2423e: ebb0 0a0a subs.w sl, r0, sl + 24242: 9b00 ldr r3, [sp, #0] + 24244: eb61 0b0b sbc.w fp, r1, fp + 24248: 9906 ldr r1, [sp, #24] + 2424a: fba3 2302 umull r2, r3, r3, r2 + 2424e: fba1 0107 umull r0, r1, r1, r7 + 24252: e9cd 2316 strd r2, r3, [sp, #88] ; 0x58 + 24256: 9b02 ldr r3, [sp, #8] + 24258: e9cd 0114 strd r0, r1, [sp, #80] ; 0x50 + 2425c: 9903 ldr r1, [sp, #12] + 2425e: 425b negs r3, r3 + 24260: fb04 3001 mla r0, r4, r1, r3 + 24264: 931e str r3, [sp, #120] ; 0x78 + 24266: 9b02 ldr r3, [sp, #8] + 24268: f1cc 0900 rsb r9, ip, #0 + 2426c: fba3 2304 umull r2, r3, r3, r4 + 24270: e9cd 2336 strd r2, r3, [sp, #216] ; 0xd8 + 24274: fbac 2304 umull r2, r3, ip, r4 + 24278: e9cd 230a strd r2, r3, [sp, #40] ; 0x28 + 2427c: 9b0e ldr r3, [sp, #56] ; 0x38 + 2427e: 9a03 ldr r2, [sp, #12] + 24280: fb04 9103 mla r1, r4, r3, r9 + 24284: 9b09 ldr r3, [sp, #36] ; 0x24 + 24286: f241 55d1 movw r5, #5585 ; 0x15d1 + 2428a: fb07 3202 mla r2, r7, r2, r3 + 2428e: 9b11 ldr r3, [sp, #68] ; 0x44 + 24290: 9209 str r2, [sp, #36] ; 0x24 + 24292: 9a07 ldr r2, [sp, #28] + 24294: f2c0 0502 movt r5, #2 + 24298: fb0e 3e02 mla lr, lr, r2, r3 + 2429c: 9a0d ldr r2, [sp, #52] ; 0x34 + 2429e: f8cd e044 str.w lr, [sp, #68] ; 0x44 + 242a2: f8dd e00c ldr.w lr, [sp, #12] + 242a6: 9b07 ldr r3, [sp, #28] + 242a8: fb06 2e0e mla lr, r6, lr, r2 + 242ac: f8cd e034 str.w lr, [sp, #52] ; 0x34 + 242b0: f8dd e054 ldr.w lr, [sp, #84] ; 0x54 + 242b4: 9a01 ldr r2, [sp, #4] + 242b6: fb07 e703 mla r7, r7, r3, lr + 242ba: f642 4313 movw r3, #11283 ; 0x2c13 + 242be: f2c0 030a movt r3, #10 + 242c2: 9715 str r7, [sp, #84] ; 0x54 + 242c4: 9f17 ldr r7, [sp, #92] ; 0x5c + 242c6: f8dd e0dc ldr.w lr, [sp, #220] ; 0xdc + 242ca: fb03 7202 mla r2, r3, r2, r7 + 242ce: 4486 add lr, r0 + 242d0: 980b ldr r0, [sp, #44] ; 0x2c + 242d2: 9217 str r2, [sp, #92] ; 0x5c + 242d4: 4408 add r0, r1 + 242d6: e9dd 2308 ldrd r2, r3, [sp, #32] + 242da: 900b str r0, [sp, #44] ; 0x2c + 242dc: e9dd 0122 ldrd r0, r1, [sp, #136] ; 0x88 + 242e0: 1812 adds r2, r2, r0 + 242e2: f8cd e0dc str.w lr, [sp, #220] ; 0xdc + 242e6: 414b adcs r3, r1 + 242e8: e9cd 2330 strd r2, r3, [sp, #192] ; 0xc0 + 242ec: e9dd 0136 ldrd r0, r1, [sp, #216] ; 0xd8 + 242f0: e9dd 2324 ldrd r2, r3, [sp, #144] ; 0x90 + 242f4: 1812 adds r2, r2, r0 + 242f6: 414b adcs r3, r1 + 242f8: e9cd 2324 strd r2, r3, [sp, #144] ; 0x90 + 242fc: e9dd 0118 ldrd r0, r1, [sp, #96] ; 0x60 + 24300: e9dd 2310 ldrd r2, r3, [sp, #64] ; 0x40 + 24304: 1812 adds r2, r2, r0 + 24306: 414b adcs r3, r1 + 24308: e9cd 2318 strd r2, r3, [sp, #96] ; 0x60 + 2430c: e9dd 011c ldrd r0, r1, [sp, #112] ; 0x70 + 24310: e9dd 230c ldrd r2, r3, [sp, #48] ; 0x30 + 24314: 1812 adds r2, r2, r0 + 24316: 414b adcs r3, r1 + 24318: e9cd 231c strd r2, r3, [sp, #112] ; 0x70 + 2431c: e9dd 012a ldrd r0, r1, [sp, #168] ; 0xa8 + 24320: e9dd 230a ldrd r2, r3, [sp, #40] ; 0x28 + 24324: 1812 adds r2, r2, r0 + 24326: 414b adcs r3, r1 + 24328: e9cd 2322 strd r2, r3, [sp, #136] ; 0x88 + 2432c: e9dd 0128 ldrd r0, r1, [sp, #160] ; 0xa0 + 24330: e9dd 2314 ldrd r2, r3, [sp, #80] ; 0x50 + 24334: 1812 adds r2, r2, r0 + 24336: 414b adcs r3, r1 + 24338: e9cd 2328 strd r2, r3, [sp, #160] ; 0xa0 + 2433c: e9dd 011a ldrd r0, r1, [sp, #104] ; 0x68 + 24340: e9dd 2316 ldrd r2, r3, [sp, #88] ; 0x58 + 24344: 1812 adds r2, r2, r0 + 24346: 414b adcs r3, r1 + 24348: e9cd 2338 strd r2, r3, [sp, #224] ; 0xe0 + 2434c: 9b06 ldr r3, [sp, #24] + 2434e: f241 50d1 movw r0, #5585 ; 0x15d1 + 24352: fba3 2306 umull r2, r3, r3, r6 + 24356: e9cd 230c strd r2, r3, [sp, #48] ; 0x30 + 2435a: f642 5218 movw r2, #11544 ; 0x2d18 + 2435e: f2c0 0207 movt r2, #7 + 24362: f2c0 0002 movt r0, #2 + 24366: 9b00 ldr r3, [sp, #0] + 24368: 9906 ldr r1, [sp, #24] + 2436a: fba3 2302 umull r2, r3, r3, r2 + 2436e: fba1 0100 umull r0, r1, r1, r0 + 24372: e9cd 2314 strd r2, r3, [sp, #80] ; 0x50 + 24376: 9b02 ldr r3, [sp, #8] + 24378: e9cd 0110 strd r0, r1, [sp, #64] ; 0x40 + 2437c: fba3 2305 umull r2, r3, r3, r5 + 24380: fbac 0105 umull r0, r1, ip, r5 + 24384: e9cd 2308 strd r2, r3, [sp, #32] + 24388: f642 5318 movw r3, #11544 ; 0x2d18 + 2438c: e9cd 010a strd r0, r1, [sp, #40] ; 0x28 + 24390: f64f 3067 movw r0, #64359 ; 0xfb67 + 24394: f2c0 0307 movt r3, #7 + 24398: f2c0 0009 movt r0, #9 + 2439c: 9900 ldr r1, [sp, #0] + 2439e: fbaa 2303 umull r2, r3, sl, r3 + 243a2: fba1 0100 umull r0, r1, r1, r0 + 243a6: 9f06 ldr r7, [sp, #24] + 243a8: e9cd 231a strd r2, r3, [sp, #104] ; 0x68 + 243ac: 9a07 ldr r2, [sp, #28] + 243ae: e9cd 0116 strd r0, r1, [sp, #88] ; 0x58 + 243b2: 4279 negs r1, r7 + 243b4: fb04 1002 mla r0, r4, r2, r1 + 243b8: fba7 2304 umull r2, r3, r7, r4 + 243bc: 9f0d ldr r7, [sp, #52] ; 0x34 + 243be: 9c07 ldr r4, [sp, #28] + 243c0: 4403 add r3, r0 + 243c2: fb06 7604 mla r6, r6, r4, r7 + 243c6: 960d str r6, [sp, #52] ; 0x34 + 243c8: f241 56d1 movw r6, #5585 ; 0x15d1 + 243cc: f2c0 0602 movt r6, #2 + 243d0: 9f11 ldr r7, [sp, #68] ; 0x44 + 243d2: f249 0883 movw r8, #36995 ; 0x9083 + 243d6: fb06 7404 mla r4, r6, r4, r7 + 243da: f642 5618 movw r6, #11544 ; 0x2d18 + 243de: f2c0 0607 movt r6, #7 + 243e2: 9411 str r4, [sp, #68] ; 0x44 + 243e4: 9f15 ldr r7, [sp, #84] ; 0x54 + 243e6: 9c01 ldr r4, [sp, #4] + 243e8: f6cf 78f5 movt r8, #65525 ; 0xfff5 + 243ec: fb06 7404 mla r4, r6, r4, r7 + 243f0: 9e0b ldr r6, [sp, #44] ; 0x2c + 243f2: 9415 str r4, [sp, #84] ; 0x54 + 243f4: 9c0e ldr r4, [sp, #56] ; 0x38 + 243f6: 9f03 ldr r7, [sp, #12] + 243f8: fb05 6404 mla r4, r5, r4, r6 + 243fc: f64f 3667 movw r6, #64359 ; 0xfb67 + 24400: 940b str r4, [sp, #44] ; 0x2c + 24402: 9c09 ldr r4, [sp, #36] ; 0x24 + 24404: f2c0 0609 movt r6, #9 + 24408: fb05 4507 mla r5, r5, r7, r4 + 2440c: f642 5418 movw r4, #11544 ; 0x2d18 + 24410: f2c0 0407 movt r4, #7 + 24414: 9f17 ldr r7, [sp, #92] ; 0x5c + 24416: 9509 str r5, [sp, #36] ; 0x24 + 24418: 9d01 ldr r5, [sp, #4] + 2441a: 46c6 mov lr, r8 + 2441c: fb06 7505 mla r5, r6, r5, r7 + 24420: e9dd 670c ldrd r6, r7, [sp, #48] ; 0x30 + 24424: 9517 str r5, [sp, #92] ; 0x5c + 24426: 9d1b ldr r5, [sp, #108] ; 0x6c + 24428: fb04 540b mla r4, r4, fp, r5 + 2442c: 941b str r4, [sp, #108] ; 0x6c + 2442e: e9dd 4530 ldrd r4, r5, [sp, #192] ; 0xc0 + 24432: 1936 adds r6, r6, r4 + 24434: 416f adcs r7, r5 + 24436: e9cd 672a strd r6, r7, [sp, #168] ; 0xa8 + 2443a: e9dd 4524 ldrd r4, r5, [sp, #144] ; 0x90 + 2443e: e9dd 6710 ldrd r6, r7, [sp, #64] ; 0x40 + 24442: 1936 adds r6, r6, r4 + 24444: 416f adcs r7, r5 + 24446: e9cd 6724 strd r6, r7, [sp, #144] ; 0x90 + 2444a: e9dd 4518 ldrd r4, r5, [sp, #96] ; 0x60 + 2444e: e9dd 6714 ldrd r6, r7, [sp, #80] ; 0x50 + 24452: 1936 adds r6, r6, r4 + 24454: 416f adcs r7, r5 + 24456: e9cd 6730 strd r6, r7, [sp, #192] ; 0xc0 + 2445a: e9dd 671c ldrd r6, r7, [sp, #112] ; 0x70 + 2445e: ad48 add r5, sp, #288 ; 0x120 + 24460: 18b6 adds r6, r6, r2 + 24462: 415f adcs r7, r3 + 24464: e9d5 4500 ldrd r4, r5, [r5] + 24468: e9dd 230a ldrd r2, r3, [sp, #40] ; 0x28 + 2446c: 1912 adds r2, r2, r4 + 2446e: 416b adcs r3, r5 + 24470: e9cd 6718 strd r6, r7, [sp, #96] ; 0x60 + 24474: e9dd 6708 ldrd r6, r7, [sp, #32] + 24478: e9dd 4516 ldrd r4, r5, [sp, #88] ; 0x58 + 2447c: e9cd 231c strd r2, r3, [sp, #112] ; 0x70 + 24480: e9dd 2322 ldrd r2, r3, [sp, #136] ; 0x88 + 24484: 18b6 adds r6, r6, r2 + 24486: 415f adcs r7, r3 + 24488: e9cd 6722 strd r6, r7, [sp, #136] ; 0x88 + 2448c: e9dd 6728 ldrd r6, r7, [sp, #160] ; 0xa0 + 24490: 19a4 adds r4, r4, r6 + 24492: 417d adcs r5, r7 + 24494: f64f 3767 movw r7, #64359 ; 0xfb67 + 24498: f2c0 0709 movt r7, #9 + 2449c: e9cd 4528 strd r4, r5, [sp, #160] ; 0xa0 + 244a0: e9dd 4538 ldrd r4, r5, [sp, #224] ; 0xe0 + 244a4: e9dd 231a ldrd r2, r3, [sp, #104] ; 0x68 + 244a8: 1912 adds r2, r2, r4 + 244aa: 416b adcs r3, r5 + 244ac: e9cd 233a strd r2, r3, [sp, #232] ; 0xe8 + 244b0: f241 52d1 movw r2, #5585 ; 0x15d1 + 244b4: fbaa 6707 umull r6, r7, sl, r7 + 244b8: e9cd 670c strd r6, r7, [sp, #48] ; 0x30 + 244bc: f64f 3667 movw r6, #64359 ; 0xfb67 + 244c0: f2c0 0202 movt r2, #2 + 244c4: f2c0 0609 movt r6, #9 + 244c8: 9b00 ldr r3, [sp, #0] + 244ca: f642 4513 movw r5, #11283 ; 0x2c13 + 244ce: fba3 2302 umull r2, r3, r3, r2 + 244d2: 9f04 ldr r7, [sp, #16] + 244d4: e9cd 230a strd r2, r3, [sp, #40] ; 0x28 + 244d8: f642 4213 movw r2, #11283 ; 0x2c13 + 244dc: fba7 6706 umull r6, r7, r7, r6 + 244e0: e9cd 6714 strd r6, r7, [sp, #80] ; 0x50 + 244e4: f24c 6753 movw r7, #50771 ; 0xc653 + 244e8: f2c0 050a movt r5, #10 + 244ec: f2c0 020a movt r2, #10 + 244f0: f6cf 77f0 movt r7, #65520 ; 0xfff0 + 244f4: fbaa 4505 umull r4, r5, sl, r5 + 244f8: 9b04 ldr r3, [sp, #16] + 244fa: e9cd 4508 strd r4, r5, [sp, #32] + 244fe: fba3 2302 umull r2, r3, r3, r2 + 24502: 9c00 ldr r4, [sp, #0] + 24504: 9e01 ldr r6, [sp, #4] + 24506: e9cd 2310 strd r2, r3, [sp, #64] ; 0x40 + 2450a: f1ca 0500 rsb r5, sl, #0 + 2450e: 4263 negs r3, r4 + 24510: fb07 3206 mla r2, r7, r6, r3 + 24514: 9516 str r5, [sp, #88] ; 0x58 + 24516: 9e03 ldr r6, [sp, #12] + 24518: fba4 4507 umull r4, r5, r4, r7 + 2451c: 9f1e ldr r7, [sp, #120] ; 0x78 + 2451e: 9801 ldr r0, [sp, #4] + 24520: fb08 7606 mla r6, r8, r6, r7 + 24524: fb08 3300 mla r3, r8, r0, r3 + 24528: 9800 ldr r0, [sp, #0] + 2452a: 961e str r6, [sp, #120] ; 0x78 + 2452c: fba0 6708 umull r6, r7, r0, r8 + 24530: 9807 ldr r0, [sp, #28] + 24532: 4415 add r5, r2 + 24534: fb08 1100 mla r1, r8, r0, r1 + 24538: 9136 str r1, [sp, #216] ; 0xd8 + 2453a: 9902 ldr r1, [sp, #8] + 2453c: 441f add r7, r3 + 2453e: fba1 0108 umull r0, r1, r1, r8 + 24542: e9cd 0102 strd r0, r1, [sp, #8] + 24546: 980e ldr r0, [sp, #56] ; 0x38 + 24548: 9906 ldr r1, [sp, #24] + 2454a: fb08 9900 mla r9, r8, r0, r9 + 2454e: f8cd 9068 str.w r9, [sp, #104] ; 0x68 + 24552: fbac 8908 umull r8, r9, ip, r8 + 24556: f24c 6c53 movw ip, #50771 ; 0xc653 + 2455a: f6cf 7cf0 movt ip, #65520 ; 0xfff0 + 2455e: fba1 010e umull r0, r1, r1, lr + 24562: e9cd 0106 strd r0, r1, [sp, #24] + 24566: 9816 ldr r0, [sp, #88] ; 0x58 + 24568: f24c 6153 movw r1, #50771 ; 0xc653 + 2456c: fb0c 0c0b mla ip, ip, fp, r0 + 24570: f8cd c0e0 str.w ip, [sp, #224] ; 0xe0 + 24574: f64f 3c67 movw ip, #64359 ; 0xfb67 + 24578: f6cf 71f0 movt r1, #65520 ; 0xfff0 + 2457c: f2c0 0c09 movt ip, #9 + 24580: fbaa 0101 umull r0, r1, sl, r1 + 24584: e9cd 010e strd r0, r1, [sp, #56] ; 0x38 + 24588: 980d ldr r0, [sp, #52] ; 0x34 + 2458a: 9901 ldr r1, [sp, #4] + 2458c: fb0c 0c0b mla ip, ip, fp, r0 + 24590: f8cd c034 str.w ip, [sp, #52] ; 0x34 + 24594: f241 5cd1 movw ip, #5585 ; 0x15d1 + 24598: f2c0 0c02 movt ip, #2 + 2459c: 980b ldr r0, [sp, #44] ; 0x2c + 2459e: fb0c 0101 mla r1, ip, r1, r0 + 245a2: 910b str r1, [sp, #44] ; 0x2c + 245a4: f642 4113 movw r1, #11283 ; 0x2c13 + 245a8: f2c0 010a movt r1, #10 + 245ac: f8dd c024 ldr.w ip, [sp, #36] ; 0x24 + 245b0: 9805 ldr r0, [sp, #20] + 245b2: fb01 c10b mla r1, r1, fp, ip + 245b6: 9109 str r1, [sp, #36] ; 0x24 + 245b8: f64f 3167 movw r1, #64359 ; 0xfb67 + 245bc: f2c0 0109 movt r1, #9 + 245c0: f8dd c054 ldr.w ip, [sp, #84] ; 0x54 + 245c4: 9a1a ldr r2, [sp, #104] ; 0x68 + 245c6: fb01 c000 mla r0, r1, r0, ip + 245ca: f642 4113 movw r1, #11283 ; 0x2c13 + 245ce: f2c0 010a movt r1, #10 + 245d2: f8dd c044 ldr.w ip, [sp, #68] ; 0x44 + 245d6: 9015 str r0, [sp, #84] ; 0x54 + 245d8: 9805 ldr r0, [sp, #20] + 245da: 9b36 ldr r3, [sp, #216] ; 0xd8 + 245dc: fb01 c000 mla r0, r1, r0, ip + 245e0: 9903 ldr r1, [sp, #12] + 245e2: 9011 str r0, [sp, #68] ; 0x44 + 245e4: 981e ldr r0, [sp, #120] ; 0x78 + 245e6: f8dd c01c ldr.w ip, [sp, #28] + 245ea: 4408 add r0, r1 + 245ec: 9003 str r0, [sp, #12] + 245ee: 990f ldr r1, [sp, #60] ; 0x3c + 245f0: 9838 ldr r0, [sp, #224] ; 0xe0 + 245f2: 4491 add r9, r2 + 245f4: 449c add ip, r3 + 245f6: e9dd 232a ldrd r2, r3, [sp, #168] ; 0xa8 + 245fa: 1912 adds r2, r2, r4 + 245fc: 416b adcs r3, r5 + 245fe: 4401 add r1, r0 + 24600: e9dd 4524 ldrd r4, r5, [sp, #144] ; 0x90 + 24604: 19a4 adds r4, r4, r6 + 24606: 417d adcs r5, r7 + 24608: 910f str r1, [sp, #60] ; 0x3c + 2460a: e9dd 670c ldrd r6, r7, [sp, #48] ; 0x30 + 2460e: e9dd 0130 ldrd r0, r1, [sp, #192] ; 0xc0 + 24612: 1836 adds r6, r6, r0 + 24614: 414f adcs r7, r1 + 24616: e9cd 231a strd r2, r3, [sp, #104] ; 0x68 + 2461a: e9dd 230a ldrd r2, r3, [sp, #40] ; 0x28 + 2461e: e9dd 011c ldrd r0, r1, [sp, #112] ; 0x70 + 24622: e9cd 4536 strd r4, r5, [sp, #216] ; 0xd8 + 24626: e9dd 4518 ldrd r4, r5, [sp, #96] ; 0x60 + 2462a: 1912 adds r2, r2, r4 + 2462c: 416b adcs r3, r5 + 2462e: e9cd 670c strd r6, r7, [sp, #48] ; 0x30 + 24632: e9dd 6702 ldrd r6, r7, [sp, #8] + 24636: 1836 adds r6, r6, r0 + 24638: f8cd c01c str.w ip, [sp, #28] + 2463c: 414f adcs r7, r1 + 2463e: e9cd 230a strd r2, r3, [sp, #40] ; 0x28 + 24642: e9dd 2332 ldrd r2, r3, [sp, #200] ; 0xc8 + 24646: e9dd 4506 ldrd r4, r5, [sp, #24] + 2464a: eb12 0208 adds.w r2, r2, r8 + 2464e: eb43 0309 adc.w r3, r3, r9 + 24652: e9cd 6738 strd r6, r7, [sp, #224] ; 0xe0 + 24656: e9dd 6722 ldrd r6, r7, [sp, #136] ; 0x88 + 2465a: 19a4 adds r4, r4, r6 + 2465c: 417d adcs r5, r7 + 2465e: e9cd 231c strd r2, r3, [sp, #112] ; 0x70 + 24662: e9cd 4518 strd r4, r5, [sp, #96] ; 0x60 + 24666: e9dd 8908 ldrd r8, r9, [sp, #32] + 2466a: e9dd 0126 ldrd r0, r1, [sp, #152] ; 0x98 + 2466e: eb18 0800 adds.w r8, r8, r0 + 24672: e9dd 4528 ldrd r4, r5, [sp, #160] ; 0xa0 + 24676: e9dd 230e ldrd r2, r3, [sp, #56] ; 0x38 + 2467a: eb49 0901 adc.w r9, r9, r1 + 2467e: 1912 adds r2, r2, r4 + 24680: e9dd 6714 ldrd r6, r7, [sp, #80] ; 0x50 + 24684: e9cd 8908 strd r8, r9, [sp, #32] + 24688: e9dd 893a ldrd r8, r9, [sp, #232] ; 0xe8 + 2468c: e9dd 0110 ldrd r0, r1, [sp, #64] ; 0x40 + 24690: 416b adcs r3, r5 + 24692: eb16 0608 adds.w r6, r6, r8 + 24696: eb47 0709 adc.w r7, r7, r9 + 2469a: e9cd 6724 strd r6, r7, [sp, #144] ; 0x90 + 2469e: f642 5618 movw r6, #11544 ; 0x2d18 + 246a2: f241 54d1 movw r4, #5585 ; 0x15d1 + 246a6: e9cd 230e strd r2, r3, [sp, #56] ; 0x38 + 246aa: e9dd 2320 ldrd r2, r3, [sp, #128] ; 0x80 + 246ae: 1880 adds r0, r0, r2 + 246b0: 4159 adcs r1, r3 + 246b2: e9cd 0128 strd r0, r1, [sp, #160] ; 0xa0 + 246b6: f24c 6c53 movw ip, #50771 ; 0xc653 + 246ba: f241 51d1 movw r1, #5585 ; 0x15d1 + 246be: f642 5318 movw r3, #11544 ; 0x2d18 + 246c2: f2c0 0607 movt r6, #7 + 246c6: f2c0 0402 movt r4, #2 + 246ca: f6cf 7cf0 movt ip, #65520 ; 0xfff0 + 246ce: f2c0 0307 movt r3, #7 + 246d2: f2c0 0102 movt r1, #2 + 246d6: 9f04 ldr r7, [sp, #16] + 246d8: 9d04 ldr r5, [sp, #16] + 246da: fba7 6706 umull r6, r7, r7, r6 + 246de: fba5 4504 umull r4, r5, r5, r4 + 246e2: e9cd 6714 strd r6, r7, [sp, #80] ; 0x50 + 246e6: 9f04 ldr r7, [sp, #16] + 246e8: e9cd 4506 strd r4, r5, [sp, #24] + 246ec: f8dd 9014 ldr.w r9, [sp, #20] + 246f0: 9c15 ldr r4, [sp, #84] ; 0x54 + 246f2: 427f negs r7, r7 + 246f4: fb0c 7809 mla r8, ip, r9, r7 + 246f8: fb01 5109 mla r1, r1, r9, r5 + 246fc: fb03 4209 mla r2, r3, r9, r4 + 24700: f241 59d1 movw r9, #5585 ; 0x15d1 + 24704: f2c0 0902 movt r9, #2 + 24708: 9804 ldr r0, [sp, #16] + 2470a: 971e str r7, [sp, #120] ; 0x78 + 2470c: fba0 670c umull r6, r7, r0, ip + 24710: 9107 str r1, [sp, #28] + 24712: e9dd 0124 ldrd r0, r1, [sp, #144] ; 0x90 + 24716: f510 1080 adds.w r0, r0, #1048576 ; 0x100000 + 2471a: 9215 str r2, [sp, #84] ; 0x54 + 2471c: f141 0100 adc.w r1, r1, #0 + 24720: e9dd 2328 ldrd r2, r3, [sp, #160] ; 0xa0 + 24724: f512 1280 adds.w r2, r2, #1048576 ; 0x100000 + 24728: fbaa 4509 umull r4, r5, sl, r9 + 2472c: f143 0300 adc.w r3, r3, #0 + 24730: 4447 add r7, r8 + 24732: e9dd 890c ldrd r8, r9, [sp, #48] ; 0x30 + 24736: eb18 0806 adds.w r8, r8, r6 + 2473a: eb49 0907 adc.w r9, r9, r7 + 2473e: e9cd 890c strd r8, r9, [sp, #48] ; 0x30 + 24742: e9dd 6706 ldrd r6, r7, [sp, #24] + 24746: e9dd 890e ldrd r8, r9, [sp, #56] ; 0x38 + 2474a: eb16 0608 adds.w r6, r6, r8 + 2474e: eb47 0709 adc.w r7, r7, r9 + 24752: e9cd 672a strd r6, r7, [sp, #168] ; 0xa8 + 24756: e9dd 8914 ldrd r8, r9, [sp, #80] ; 0x50 + 2475a: e9dd 6708 ldrd r6, r7, [sp, #32] + 2475e: eb16 0608 adds.w r6, r6, r8 + 24762: eb47 0709 adc.w r7, r7, r9 + 24766: f241 59d1 movw r9, #5585 ; 0x15d1 + 2476a: f2c0 0902 movt r9, #2 + 2476e: fb09 550b mla r5, r9, fp, r5 + 24772: e9cd 670e strd r6, r7, [sp, #56] ; 0x38 + 24776: e9dd 671a ldrd r6, r7, [sp, #104] ; 0x68 + 2477a: 1936 adds r6, r6, r4 + 2477c: 416f adcs r7, r5 + 2477e: e9cd 6706 strd r6, r7, [sp, #24] + 24782: 9f16 ldr r7, [sp, #88] ; 0x58 + 24784: ea4f 5850 mov.w r8, r0, lsr #21 + 24788: fb0e 740b mla r4, lr, fp, r7 + 2478c: fbaa ab0e umull sl, fp, sl, lr + 24790: ea48 2cc1 orr.w ip, r8, r1, lsl #11 + 24794: ea4f 5952 mov.w r9, r2, lsr #21 + 24798: 154e asrs r6, r1, #21 + 2479a: 9603 str r6, [sp, #12] + 2479c: f8cd c008 str.w ip, [sp, #8] + 247a0: ea49 25c3 orr.w r5, r9, r3, lsl #11 + 247a4: 44a3 add fp, r4 + 247a6: e9dd 890a ldrd r8, r9, [sp, #40] ; 0x28 + 247aa: eb18 080a adds.w r8, r8, sl + 247ae: e9dd 010c ldrd r0, r1, [sp, #48] ; 0x30 + 247b2: eb49 090b adc.w r9, r9, fp + 247b6: 155f asrs r7, r3, #21 + 247b8: e9dd ab02 ldrd sl, fp, [sp, #8] + 247bc: eb1a 0a00 adds.w sl, sl, r0 + 247c0: 9500 str r5, [sp, #0] + 247c2: eb4b 0b01 adc.w fp, fp, r1 + 247c6: e9dd 232a ldrd r2, r3, [sp, #168] ; 0xa8 + 247ca: 9701 str r7, [sp, #4] + 247cc: f512 1280 adds.w r2, r2, #1048576 ; 0x100000 + 247d0: e9dd 6700 ldrd r6, r7, [sp] + 247d4: f143 0300 adc.w r3, r3, #0 + 247d8: e9dd 450e ldrd r4, r5, [sp, #56] ; 0x38 + 247dc: 19a4 adds r4, r4, r6 + 247de: e9cd 8926 strd r8, r9, [sp, #152] ; 0x98 + 247e2: 417d adcs r5, r7 + 247e4: f8dd 8078 ldr.w r8, [sp, #120] ; 0x78 + 247e8: 9f05 ldr r7, [sp, #20] + 247ea: e9cd ab32 strd sl, fp, [sp, #200] ; 0xc8 + 247ee: e9dd 0132 ldrd r0, r1, [sp, #200] ; 0xc8 + 247f2: f04f 0a00 mov.w sl, #0 + 247f6: fb0e 8c07 mla ip, lr, r7, r8 + 247fa: e9dd 6718 ldrd r6, r7, [sp, #96] ; 0x60 + 247fe: 46d0 mov r8, sl + 24800: f8dd 9010 ldr.w r9, [sp, #16] + 24804: e9cd 4530 strd r4, r5, [sp, #192] ; 0xc0 + 24808: fba9 450e umull r4, r5, r9, lr + 2480c: f516 1680 adds.w r6, r6, #1048576 ; 0x100000 + 24810: f04f 0b00 mov.w fp, #0 + 24814: 46d9 mov r9, fp + 24816: e9dd ab06 ldrd sl, fp, [sp, #24] + 2481a: f147 0700 adc.w r7, r7, #0 + 2481e: 4465 add r5, ip + 24820: eb1a 0a04 adds.w sl, sl, r4 + 24824: eb4b 0b05 adc.w fp, fp, r5 + 24828: e9cd ab3a strd sl, fp, [sp, #232] ; 0xe8 + 2482c: e9dd 4526 ldrd r4, r5, [sp, #152] ; 0x98 + 24830: 46c2 mov sl, r8 + 24832: f510 1080 adds.w r0, r0, #1048576 ; 0x100000 + 24836: f141 0100 adc.w r1, r1, #0 + 2483a: f514 1480 adds.w r4, r4, #1048576 ; 0x100000 + 2483e: f145 0500 adc.w r5, r5, #0 + 24842: e9cd 4516 strd r4, r5, [sp, #88] ; 0x58 + 24846: 4654 mov r4, sl + 24848: 464d mov r5, r9 + 2484a: e9cd 671a strd r6, r7, [sp, #104] ; 0x68 + 2484e: e9dd 6730 ldrd r6, r7, [sp, #192] ; 0xc0 + 24852: f516 1680 adds.w r6, r6, #1048576 ; 0x100000 + 24856: f147 0700 adc.w r7, r7, #0 + 2485a: ea4f 5852 mov.w r8, r2, lsr #21 + 2485e: ea48 28c3 orr.w r8, r8, r3, lsl #11 + 24862: e9cd 0122 strd r0, r1, [sp, #136] ; 0x88 + 24866: e9cd 6720 strd r6, r7, [sp, #128] ; 0x80 + 2486a: 4622 mov r2, r4 + 2486c: 4650 mov r0, sl + 2486e: e9dd ab1c ldrd sl, fp, [sp, #112] ; 0x70 + 24872: 4649 mov r1, r9 + 24874: 4626 mov r6, r4 + 24876: ea4f 5963 mov.w r9, r3, asr #21 + 2487a: 462f mov r7, r5 + 2487c: 462b mov r3, r5 + 2487e: f51a 1a80 adds.w sl, sl, #1048576 ; 0x100000 + 24882: f14b 0b00 adc.w fp, fp, #0 + 24886: e9cd ab1e strd sl, fp, [sp, #120] ; 0x78 + 2488a: f8dd b00c ldr.w fp, [sp, #12] + 2488e: e9cd 0108 strd r0, r1, [sp, #32] + 24892: e9cd 2306 strd r2, r3, [sp, #24] + 24896: e9cd 4514 strd r4, r5, [sp, #80] ; 0x50 + 2489a: 9d1a ldr r5, [sp, #104] ; 0x68 + 2489c: e9cd 670c strd r6, r7, [sp, #48] ; 0x30 + 248a0: f8dd a008 ldr.w sl, [sp, #8] + 248a4: ea4f 5b4b mov.w fp, fp, lsl #21 + 248a8: ea4b 27da orr.w r7, fp, sl, lsr #11 + 248ac: e9cd 2310 strd r2, r3, [sp, #64] ; 0x40 + 248b0: ea4f 5c49 mov.w ip, r9, lsl #21 + 248b4: ea4f 534a mov.w r3, sl, lsl #21 + 248b8: 981b ldr r0, [sp, #108] ; 0x6c + 248ba: 970b str r7, [sp, #44] ; 0x2c + 248bc: 930a str r3, [sp, #40] ; 0x28 + 248be: ea4c 2bd8 orr.w fp, ip, r8, lsr #11 + 248c2: f8cd b03c str.w fp, [sp, #60] ; 0x3c + 248c6: e9dd 6724 ldrd r6, r7, [sp, #144] ; 0x90 + 248ca: e9dd ab0a ldrd sl, fp, [sp, #40] ; 0x28 + 248ce: ea4f 5448 mov.w r4, r8, lsl #21 + 248d2: ebb6 060a subs.w r6, r6, sl + 248d6: ea4f 5555 mov.w r5, r5, lsr #21 + 248da: ea45 2cc0 orr.w ip, r5, r0, lsl #11 + 248de: 940e str r4, [sp, #56] ; 0x38 + 248e0: eb67 070b sbc.w r7, r7, fp + 248e4: 1545 asrs r5, r0, #21 + 248e6: e9dd 013a ldrd r0, r1, [sp, #232] ; 0xe8 + 248ea: eb10 0008 adds.w r0, r0, r8 + 248ee: 9505 str r5, [sp, #20] + 248f0: f8cd c010 str.w ip, [sp, #16] + 248f4: e9dd 450e ldrd r4, r5, [sp, #56] ; 0x38 + 248f8: eb41 0109 adc.w r1, r1, r9 + 248fc: e9dd 232a ldrd r2, r3, [sp, #168] ; 0xa8 + 24900: 1b12 subs r2, r2, r4 + 24902: e9dd 8904 ldrd r8, r9, [sp, #16] + 24906: eb63 0305 sbc.w r3, r3, r5 + 2490a: e9cd 6702 strd r6, r7, [sp, #8] + 2490e: e9dd 6738 ldrd r6, r7, [sp, #224] ; 0xe0 + 24912: eb16 0608 adds.w r6, r6, r8 + 24916: eb47 0709 adc.w r7, r7, r9 + 2491a: f8dd 9088 ldr.w r9, [sp, #136] ; 0x88 + 2491e: f8dd c058 ldr.w ip, [sp, #88] ; 0x58 + 24922: ea4f 5a59 mov.w sl, r9, lsr #21 + 24926: f8dd 905c ldr.w r9, [sp, #92] ; 0x5c + 2492a: f8dd 808c ldr.w r8, [sp, #140] ; 0x8c + 2492e: e9cd 230e strd r2, r3, [sp, #56] ; 0x38 + 24932: 9a20 ldr r2, [sp, #128] ; 0x80 + 24934: ea4f 5569 mov.w r5, r9, asr #21 + 24938: ea4f 545c mov.w r4, ip, lsr #21 + 2493c: ea4a 2ac8 orr.w sl, sl, r8, lsl #11 + 24940: ea44 24c9 orr.w r4, r4, r9, lsl #11 + 24944: f8dd c084 ldr.w ip, [sp, #132] ; 0x84 + 24948: e9cd 011a strd r0, r1, [sp, #104] ; 0x68 + 2494c: ea4f 5b68 mov.w fp, r8, asr #21 + 24950: f8dd 9004 ldr.w r9, [sp, #4] + 24954: ea4f 5845 mov.w r8, r5, lsl #21 + 24958: 0d50 lsrs r0, r2, #21 + 2495a: 9a1f ldr r2, [sp, #124] ; 0x7c + 2495c: f8cd 8024 str.w r8, [sp, #36] ; 0x24 + 24960: f8dd 8014 ldr.w r8, [sp, #20] + 24964: e9cd 670a strd r6, r7, [sp, #40] ; 0x28 + 24968: ea4f 516c mov.w r1, ip, asr #21 + 2496c: 1557 asrs r7, r2, #21 + 2496e: ea4f 5949 mov.w r9, r9, lsl #21 + 24972: ea40 20cc orr.w r0, r0, ip, lsl #11 + 24976: f8cd 901c str.w r9, [sp, #28] + 2497a: ea4f 5c41 mov.w ip, r1, lsl #21 + 2497e: ea4f 5947 mov.w r9, r7, lsl #21 + 24982: ea4f 5848 mov.w r8, r8, lsl #21 + 24986: 9b1e ldr r3, [sp, #120] ; 0x78 + 24988: f8cd c054 str.w ip, [sp, #84] ; 0x54 + 2498c: f8cd 8034 str.w r8, [sp, #52] ; 0x34 + 24990: f8cd 9044 str.w r9, [sp, #68] ; 0x44 + 24994: f8dd 801c ldr.w r8, [sp, #28] + 24998: f8dd 9000 ldr.w r9, [sp] + 2499c: f8dd c024 ldr.w ip, [sp, #36] ; 0x24 + 249a0: ea48 28d9 orr.w r8, r8, r9, lsr #11 + 249a4: f8cd 801c str.w r8, [sp, #28] + 249a8: f8dd 9010 ldr.w r9, [sp, #16] + 249ac: f8dd 8034 ldr.w r8, [sp, #52] ; 0x34 + 249b0: 0d5e lsrs r6, r3, #21 + 249b2: ea48 28d9 orr.w r8, r8, r9, lsr #11 + 249b6: f8cd 8034 str.w r8, [sp, #52] ; 0x34 + 249ba: f8dd 9000 ldr.w r9, [sp] + 249be: ea4f 5844 mov.w r8, r4, lsl #21 + 249c2: f8cd 8020 str.w r8, [sp, #32] + 249c6: f8dd 8010 ldr.w r8, [sp, #16] + 249ca: ea46 26c2 orr.w r6, r6, r2, lsl #11 + 249ce: ea4f 5949 mov.w r9, r9, lsl #21 + 249d2: f8cd 9018 str.w r9, [sp, #24] + 249d6: ea4c 2cd4 orr.w ip, ip, r4, lsr #11 + 249da: ea4f 524a mov.w r2, sl, lsl #21 + 249de: ea4f 5946 mov.w r9, r6, lsl #21 + 249e2: ea4f 534b mov.w r3, fp, lsl #21 + 249e6: ea4f 5848 mov.w r8, r8, lsl #21 + 249ea: f8cd c024 str.w ip, [sp, #36] ; 0x24 + 249ee: ea43 23da orr.w r3, r3, sl, lsr #11 + 249f2: f8dd c054 ldr.w ip, [sp, #84] ; 0x54 + 249f6: f8cd 8030 str.w r8, [sp, #48] ; 0x30 + 249fa: f8cd 9040 str.w r9, [sp, #64] ; 0x40 + 249fe: e9dd 8932 ldrd r8, r9, [sp, #200] ; 0xc8 + 24a02: ebb8 0802 subs.w r8, r8, r2 + 24a06: eb69 0903 sbc.w r9, r9, r3 + 24a0a: e9dd 230e ldrd r2, r3, [sp, #56] ; 0x38 + 24a0e: eb12 020a adds.w r2, r2, sl + 24a12: eb43 030b adc.w r3, r3, fp + 24a16: ea4c 2cd0 orr.w ip, ip, r0, lsr #11 + 24a1a: e9cd 892a strd r8, r9, [sp, #168] ; 0xa8 + 24a1e: e9dd 8936 ldrd r8, r9, [sp, #216] ; 0xd8 + 24a22: e9dd ab26 ldrd sl, fp, [sp, #152] ; 0x98 + 24a26: eb18 0804 adds.w r8, r8, r4 + 24a2a: eb49 0905 adc.w r9, r9, r5 + 24a2e: f8cd c054 str.w ip, [sp, #84] ; 0x54 + 24a32: e9cd 2324 strd r2, r3, [sp, #144] ; 0x90 + 24a36: e9dd 2308 ldrd r2, r3, [sp, #32] + 24a3a: e9dd 4528 ldrd r4, r5, [sp, #160] ; 0xa0 + 24a3e: ebba 0a02 subs.w sl, sl, r2 + 24a42: f8dd c044 ldr.w ip, [sp, #68] ; 0x44 + 24a46: eb6b 0b03 sbc.w fp, fp, r3 + 24a4a: e9cd 8916 strd r8, r9, [sp, #88] ; 0x58 + 24a4e: e9dd 8906 ldrd r8, r9, [sp, #24] + 24a52: ebb4 0408 subs.w r4, r4, r8 + 24a56: eb65 0509 sbc.w r5, r5, r9 + 24a5a: ea4c 2cd6 orr.w ip, ip, r6, lsr #11 + 24a5e: e9cd ab20 strd sl, fp, [sp, #128] ; 0x80 + 24a62: e9dd ab02 ldrd sl, fp, [sp, #8] + 24a66: eb1a 0a00 adds.w sl, sl, r0 + 24a6a: eb4b 0b01 adc.w fp, fp, r1 + 24a6e: f8cd c044 str.w ip, [sp, #68] ; 0x44 + 24a72: ea4f 5c40 mov.w ip, r0, lsl #21 + 24a76: f8cd c050 str.w ip, [sp, #80] ; 0x50 + 24a7a: e9cd 450e strd r4, r5, [sp, #56] ; 0x38 + 24a7e: e9cd ab22 strd sl, fp, [sp, #136] ; 0x88 + 24a82: e9dd 2314 ldrd r2, r3, [sp, #80] ; 0x50 + 24a86: e9dd 0130 ldrd r0, r1, [sp, #192] ; 0xc0 + 24a8a: 1a80 subs r0, r0, r2 + 24a8c: e9dd 890c ldrd r8, r9, [sp, #48] ; 0x30 + 24a90: e9dd 4518 ldrd r4, r5, [sp, #96] ; 0x60 + 24a94: eb61 0103 sbc.w r1, r1, r3 + 24a98: f50d 7b94 add.w fp, sp, #296 ; 0x128 + 24a9c: ebb4 0408 subs.w r4, r4, r8 + 24aa0: e9db ab00 ldrd sl, fp, [fp] + 24aa4: eb65 0509 sbc.w r5, r5, r9 + 24aa8: eb16 060a adds.w r6, r6, sl + 24aac: eb47 070b adc.w r7, r7, fp + 24ab0: e9cd 0108 strd r0, r1, [sp, #32] + 24ab4: e9dd 0110 ldrd r0, r1, [sp, #64] ; 0x40 + 24ab8: e9dd 231a ldrd r2, r3, [sp, #104] ; 0x68 + 24abc: e9cd 450c strd r4, r5, [sp, #48] ; 0x30 + 24ac0: e9dd 451c ldrd r4, r5, [sp, #112] ; 0x70 + 24ac4: 1a24 subs r4, r4, r0 + 24ac6: eb65 0501 sbc.w r5, r5, r1 + 24aca: f512 1280 adds.w r2, r2, #1048576 ; 0x100000 + 24ace: f143 0300 adc.w r3, r3, #0 + 24ad2: e9cd 2304 strd r2, r3, [sp, #16] + 24ad6: e9dd 010a ldrd r0, r1, [sp, #40] ; 0x28 + 24ada: f642 4313 movw r3, #11283 ; 0x2c13 + 24ade: f2c0 030a movt r3, #10 + 24ae2: fba6 8903 umull r8, r9, r6, r3 + 24ae6: f64f 3367 movw r3, #64359 ; 0xfb67 + 24aea: f2c0 0309 movt r3, #9 + 24aee: f510 1080 adds.w r0, r0, #1048576 ; 0x100000 + 24af2: f141 0100 adc.w r1, r1, #0 + 24af6: ea4f 5a50 mov.w sl, r0, lsr #21 + 24afa: ea4a 2ac1 orr.w sl, sl, r1, lsl #11 + 24afe: eb14 000a adds.w r0, r4, sl + 24b02: fba6 2303 umull r2, r3, r6, r3 + 24b06: ea4f 5b61 mov.w fp, r1, asr #21 + 24b0a: eb45 010b adc.w r1, r5, fp + 24b0e: e9dd 4516 ldrd r4, r5, [sp, #88] ; 0x58 + 24b12: f514 1480 adds.w r4, r4, #1048576 ; 0x100000 + 24b16: f145 0500 adc.w r5, r5, #0 + 24b1a: e9cd 4518 strd r4, r5, [sp, #96] ; 0x60 + 24b1e: f642 5518 movw r5, #11544 ; 0x2d18 + 24b22: e9cd 2306 strd r2, r3, [sp, #24] + 24b26: f642 4c13 movw ip, #11283 ; 0x2c13 + 24b2a: f64f 3267 movw r2, #64359 ; 0xfb67 + 24b2e: f2c0 0507 movt r5, #7 + 24b32: f2c0 0c0a movt ip, #10 + 24b36: f2c0 0209 movt r2, #9 + 24b3a: e9cd 0100 strd r0, r1, [sp] + 24b3e: fba6 0105 umull r0, r1, r6, r5 + 24b42: fb0c 9907 mla r9, ip, r7, r9 + 24b46: fb02 3207 mla r2, r2, r7, r3 + 24b4a: f50d 7c80 add.w ip, sp, #256 ; 0x100 + 24b4e: fb05 1107 mla r1, r5, r7, r1 + 24b52: e9dc 4500 ldrd r4, r5, [ip] + 24b56: eb14 0408 adds.w r4, r4, r8 + 24b5a: eb45 0509 adc.w r5, r5, r9 + 24b5e: 9207 str r2, [sp, #28] + 24b60: e9dd 2306 ldrd r2, r3, [sp, #24] + 24b64: e9cd 4510 strd r4, r5, [sp, #64] ; 0x40 + 24b68: e9dd 4508 ldrd r4, r5, [sp, #32] + 24b6c: e9dd 890e ldrd r8, r9, [sp, #56] ; 0x38 + 24b70: 1912 adds r2, r2, r4 + 24b72: 416b adcs r3, r5 + 24b74: eb18 0800 adds.w r8, r8, r0 + 24b78: eb49 0901 adc.w r9, r9, r1 + 24b7c: e9cd 8914 strd r8, r9, [sp, #80] ; 0x50 + 24b80: e9dd 450a ldrd r4, r5, [sp, #40] ; 0x28 + 24b84: f8dd 8060 ldr.w r8, [sp, #96] ; 0x60 + 24b88: e9cd 231c strd r2, r3, [sp, #112] ; 0x70 + 24b8c: ea4f 524a mov.w r2, sl, lsl #21 + 24b90: 1aa2 subs r2, r4, r2 + 24b92: ea4f 5458 mov.w r4, r8, lsr #21 + 24b96: f642 4813 movw r8, #11283 ; 0x2c13 + 24b9a: f2c0 080a movt r8, #10 + 24b9e: f64f 3067 movw r0, #64359 ; 0xfb67 + 24ba2: ea4f 534b mov.w r3, fp, lsl #21 + 24ba6: f8dd 9000 ldr.w r9, [sp] + 24baa: ea43 23da orr.w r3, r3, sl, lsr #11 + 24bae: f642 5a18 movw sl, #11544 ; 0x2d18 + 24bb2: fba9 8908 umull r8, r9, r9, r8 + 24bb6: e9cd 8930 strd r8, r9, [sp, #192] ; 0xc0 + 24bba: f24c 6853 movw r8, #50771 ; 0xc653 + 24bbe: f2c0 0009 movt r0, #9 + 24bc2: f2c0 0a07 movt sl, #7 + 24bc6: f6cf 78f0 movt r8, #65520 ; 0xfff0 + 24bca: 9900 ldr r1, [sp, #0] + 24bcc: f8dd b000 ldr.w fp, [sp] + 24bd0: fba1 0100 umull r0, r1, r1, r0 + 24bd4: fbab ab0a umull sl, fp, fp, sl + 24bd8: e9cd 010e strd r0, r1, [sp, #56] ; 0x38 + 24bdc: 9800 ldr r0, [sp, #0] + 24bde: f8dd 9064 ldr.w r9, [sp, #100] ; 0x64 + 24be2: f1c0 0000 rsb r0, r0, #0 + 24be6: eb65 0303 sbc.w r3, r5, r3 + 24bea: ea44 24c9 orr.w r4, r4, r9, lsl #11 + 24bee: e9cd ab0a strd sl, fp, [sp, #40] ; 0x28 + 24bf2: ea4f 5569 mov.w r5, r9, asr #21 + 24bf6: 901e str r0, [sp, #120] ; 0x78 + 24bf8: 9901 ldr r1, [sp, #4] + 24bfa: f8dd 9078 ldr.w r9, [sp, #120] ; 0x78 + 24bfe: 4270 negs r0, r6 + 24c00: 9032 str r0, [sp, #200] ; 0xc8 + 24c02: fb08 9b01 mla fp, r8, r1, r9 + 24c06: f8dd 90c8 ldr.w r9, [sp, #200] ; 0xc8 + 24c0a: f8dd c004 ldr.w ip, [sp, #4] + 24c0e: fb08 9a07 mla sl, r8, r7, r9 + 24c12: f24c 6953 movw r9, #50771 ; 0xc653 + 24c16: f6cf 79f0 movt r9, #65520 ; 0xfff0 + 24c1a: fba6 8909 umull r8, r9, r6, r9 + 24c1e: e9cd 8906 strd r8, r9, [sp, #24] + 24c22: f642 5818 movw r8, #11544 ; 0x2d18 + 24c26: f2c0 0807 movt r8, #7 + 24c2a: f8dd 902c ldr.w r9, [sp, #44] ; 0x2c + 24c2e: f24c 6053 movw r0, #50771 ; 0xc653 + 24c32: fb08 9c0c mla ip, r8, ip, r9 + 24c36: f64f 3867 movw r8, #64359 ; 0xfb67 + 24c3a: f2c0 0809 movt r8, #9 + 24c3e: f8dd 903c ldr.w r9, [sp, #60] ; 0x3c + 24c42: f8cd c02c str.w ip, [sp, #44] ; 0x2c + 24c46: f8dd c004 ldr.w ip, [sp, #4] + 24c4a: f6cf 70f0 movt r0, #65520 ; 0xfff0 + 24c4e: fb08 9c0c mla ip, r8, ip, r9 + 24c52: f642 4813 movw r8, #11283 ; 0x2c13 + 24c56: f2c0 080a movt r8, #10 + 24c5a: 9900 ldr r1, [sp, #0] + 24c5c: f8dd 90c4 ldr.w r9, [sp, #196] ; 0xc4 + 24c60: f8cd c03c str.w ip, [sp, #60] ; 0x3c + 24c64: f8dd c004 ldr.w ip, [sp, #4] + 24c68: fba1 0100 umull r0, r1, r1, r0 + 24c6c: fb08 9c0c mla ip, r8, ip, r9 + 24c70: e9cd 0108 strd r0, r1, [sp, #32] + 24c74: e9dd 010c ldrd r0, r1, [sp, #48] ; 0x30 + 24c78: f8cd c0c4 str.w ip, [sp, #196] ; 0xc4 + 24c7c: f8dd c024 ldr.w ip, [sp, #36] ; 0x24 + 24c80: f8dd 801c ldr.w r8, [sp, #28] + 24c84: 44dc add ip, fp + 24c86: 1900 adds r0, r0, r4 + 24c88: f8cd c024 str.w ip, [sp, #36] ; 0x24 + 24c8c: 44d0 add r8, sl + 24c8e: 4169 adcs r1, r5 + 24c90: f8cd 801c str.w r8, [sp, #28] + 24c94: e9dd ab08 ldrd sl, fp, [sp, #32] + 24c98: e9dd 891c ldrd r8, r9, [sp, #112] ; 0x70 + 24c9c: eb1a 0a08 adds.w sl, sl, r8 + 24ca0: eb4b 0b09 adc.w fp, fp, r9 + 24ca4: e9cd ab28 strd sl, fp, [sp, #160] ; 0xa0 + 24ca8: e9dd 8910 ldrd r8, r9, [sp, #64] ; 0x40 + 24cac: e9dd ab0a ldrd sl, fp, [sp, #40] ; 0x28 + 24cb0: eb1a 0a08 adds.w sl, sl, r8 + 24cb4: eb4b 0b09 adc.w fp, fp, r9 + 24cb8: e9cd ab18 strd sl, fp, [sp, #96] ; 0x60 + 24cbc: e9dd 8922 ldrd r8, r9, [sp, #136] ; 0x88 + 24cc0: e9dd ab06 ldrd sl, fp, [sp, #24] + 24cc4: eb1a 0a08 adds.w sl, sl, r8 + 24cc8: eb4b 0b09 adc.w fp, fp, r9 + 24ccc: e9cd ab22 strd sl, fp, [sp, #136] ; 0x88 + 24cd0: e9dd 8914 ldrd r8, r9, [sp, #80] ; 0x50 + 24cd4: e9dd ab0e ldrd sl, fp, [sp, #56] ; 0x38 + 24cd8: eb1a 0a08 adds.w sl, sl, r8 + 24cdc: eb4b 0b09 adc.w fp, fp, r9 + 24ce0: e9cd ab26 strd sl, fp, [sp, #152] ; 0x98 + 24ce4: e9dd 8930 ldrd r8, r9, [sp, #192] ; 0xc0 + 24ce8: e9dd ab3e ldrd sl, fp, [sp, #248] ; 0xf8 + 24cec: eb1a 0a08 adds.w sl, sl, r8 + 24cf0: eb4b 0b09 adc.w fp, fp, r9 + 24cf4: ea4f 5945 mov.w r9, r5, lsl #21 + 24cf8: f241 55d1 movw r5, #5585 ; 0x15d1 + 24cfc: f2c0 0502 movt r5, #2 + 24d00: ea49 29d4 orr.w r9, r9, r4, lsr #11 + 24d04: ea4f 5844 mov.w r8, r4, lsl #21 + 24d08: fba6 4505 umull r4, r5, r6, r5 + 24d0c: e9cd ab1c strd sl, fp, [sp, #112] ; 0x70 + 24d10: e9cd 4530 strd r4, r5, [sp, #192] ; 0xc0 + 24d14: f64f 3567 movw r5, #64359 ; 0xfb67 + 24d18: f2c0 0509 movt r5, #9 + 24d1c: f8dd a010 ldr.w sl, [sp, #16] + 24d20: f8dd b014 ldr.w fp, [sp, #20] + 24d24: fba2 4505 umull r4, r5, r2, r5 + 24d28: ea4f 5a5a mov.w sl, sl, lsr #21 + 24d2c: ea4a 2bcb orr.w fp, sl, fp, lsl #11 + 24d30: f8cd b008 str.w fp, [sp, #8] + 24d34: f241 5bd1 movw fp, #5585 ; 0x15d1 + 24d38: e9cd 450c strd r4, r5, [sp, #48] ; 0x30 + 24d3c: f241 54d1 movw r4, #5585 ; 0x15d1 + 24d40: f2c0 0b02 movt fp, #2 + 24d44: f2c0 0402 movt r4, #2 + 24d48: 9d00 ldr r5, [sp, #0] + 24d4a: fba2 ab0b umull sl, fp, r2, fp + 24d4e: f8dd c014 ldr.w ip, [sp, #20] + 24d52: fba5 4504 umull r4, r5, r5, r4 + 24d56: ea4f 5c6c mov.w ip, ip, asr #21 + 24d5a: e9cd ab14 strd sl, fp, [sp, #80] ; 0x50 + 24d5e: e9dd ab16 ldrd sl, fp, [sp, #88] ; 0x58 + 24d62: f8cd c00c str.w ip, [sp, #12] + 24d66: ebba 0808 subs.w r8, sl, r8 + 24d6a: eb6b 0909 sbc.w r9, fp, r9 + 24d6e: e9cd 450a strd r4, r5, [sp, #40] ; 0x28 + 24d72: e9dd ab20 ldrd sl, fp, [sp, #128] ; 0x80 + 24d76: e9dd 4502 ldrd r4, r5, [sp, #8] + 24d7a: eb1a 0a04 adds.w sl, sl, r4 + 24d7e: eb4b 0b05 adc.w fp, fp, r5 + 24d82: e9cd ab04 strd sl, fp, [sp, #16] + 24d86: f642 4b13 movw fp, #11283 ; 0x2c13 + 24d8a: f2c0 0b0a movt fp, #10 + 24d8e: f642 5518 movw r5, #11544 ; 0x2d18 + 24d92: fba2 ab0b umull sl, fp, r2, fp + 24d96: e9cd ab0e strd sl, fp, [sp, #56] ; 0x38 + 24d9a: f24c 6a53 movw sl, #50771 ; 0xc653 + 24d9e: f24c 6b53 movw fp, #50771 ; 0xc653 + 24da2: f2c0 0507 movt r5, #7 + 24da6: f6cf 7af0 movt sl, #65520 ; 0xfff0 + 24daa: f6cf 7bf0 movt fp, #65520 ; 0xfff0 + 24dae: fba2 4505 umull r4, r5, r2, r5 + 24db2: e9cd 4508 strd r4, r5, [sp, #32] + 24db6: 4254 negs r4, r2 + 24db8: fb0a 4503 mla r5, sl, r3, r4 + 24dbc: fba2 ab0b umull sl, fp, r2, fp + 24dc0: e9cd ab10 strd sl, fp, [sp, #64] ; 0x40 + 24dc4: f642 4b13 movw fp, #11283 ; 0x2c13 + 24dc8: f2c0 0b0a movt fp, #10 + 24dcc: f241 5cd1 movw ip, #5585 ; 0x15d1 + 24dd0: fba0 ab0b umull sl, fp, r0, fp + 24dd4: e9cd ab16 strd sl, fp, [sp, #88] ; 0x58 + 24dd8: f241 5ad1 movw sl, #5585 ; 0x15d1 + 24ddc: f2c0 0c02 movt ip, #2 + 24de0: f2c0 0a02 movt sl, #2 + 24de4: 9436 str r4, [sp, #216] ; 0xd8 + 24de6: 9c31 ldr r4, [sp, #196] ; 0xc4 + 24de8: f8dd b054 ldr.w fp, [sp, #84] ; 0x54 + 24dec: fb0c 4c07 mla ip, ip, r7, r4 + 24df0: f8cd c0c4 str.w ip, [sp, #196] ; 0xc4 + 24df4: f64f 3c67 movw ip, #64359 ; 0xfb67 + 24df8: fb0a ba03 mla sl, sl, r3, fp + 24dfc: f241 5bd1 movw fp, #5585 ; 0x15d1 + 24e00: f2c0 0c09 movt ip, #9 + 24e04: f2c0 0b02 movt fp, #2 + 24e08: 9c0d ldr r4, [sp, #52] ; 0x34 + 24e0a: f8cd a054 str.w sl, [sp, #84] ; 0x54 + 24e0e: fb0c 4c03 mla ip, ip, r3, r4 + 24e12: f8dd a004 ldr.w sl, [sp, #4] + 24e16: f8cd c034 str.w ip, [sp, #52] ; 0x34 + 24e1a: f8dd c02c ldr.w ip, [sp, #44] ; 0x2c + 24e1e: f642 4413 movw r4, #11283 ; 0x2c13 + 24e22: fb0b ca0a mla sl, fp, sl, ip + 24e26: f642 5b18 movw fp, #11544 ; 0x2d18 + 24e2a: f2c0 0b07 movt fp, #7 + 24e2e: f8dd c024 ldr.w ip, [sp, #36] ; 0x24 + 24e32: f2c0 040a movt r4, #10 + 24e36: fb0b cb03 mla fp, fp, r3, ip + 24e3a: f642 4c13 movw ip, #11283 ; 0x2c13 + 24e3e: f2c0 0c0a movt ip, #10 + 24e42: f8cd a02c str.w sl, [sp, #44] ; 0x2c + 24e46: f8dd a03c ldr.w sl, [sp, #60] ; 0x3c + 24e4a: f8cd b024 str.w fp, [sp, #36] ; 0x24 + 24e4e: fb04 a403 mla r4, r4, r3, sl + 24e52: f8dd b044 ldr.w fp, [sp, #68] ; 0x44 + 24e56: 940f str r4, [sp, #60] ; 0x3c + 24e58: 44ab add fp, r5 + 24e5a: f8cd b044 str.w fp, [sp, #68] ; 0x44 + 24e5e: 9c17 ldr r4, [sp, #92] ; 0x5c + 24e60: e9dd ab2a ldrd sl, fp, [sp, #168] ; 0xa8 + 24e64: fb0c 4c01 mla ip, ip, r1, r4 + 24e68: e9dd 4530 ldrd r4, r5, [sp, #192] ; 0xc0 + 24e6c: eb1a 0a04 adds.w sl, sl, r4 + 24e70: eb4b 0b05 adc.w fp, fp, r5 + 24e74: e9cd ab20 strd sl, fp, [sp, #128] ; 0x80 + 24e78: e9dd 4528 ldrd r4, r5, [sp, #160] ; 0xa0 + 24e7c: e9dd ab14 ldrd sl, fp, [sp, #80] ; 0x50 + 24e80: eb1a 0a04 adds.w sl, sl, r4 + 24e84: eb4b 0b05 adc.w fp, fp, r5 + 24e88: e9cd ab38 strd sl, fp, [sp, #224] ; 0xe0 + 24e8c: e9dd 4518 ldrd r4, r5, [sp, #96] ; 0x60 + 24e90: e9dd ab0c ldrd sl, fp, [sp, #48] ; 0x30 + 24e94: eb1a 0a04 adds.w sl, sl, r4 + 24e98: eb4b 0b05 adc.w fp, fp, r5 + 24e9c: e9cd ab2a strd sl, fp, [sp, #168] ; 0xa8 + 24ea0: e9dd 4522 ldrd r4, r5, [sp, #136] ; 0x88 + 24ea4: e9dd ab0a ldrd sl, fp, [sp, #40] ; 0x28 + 24ea8: eb1a 0a04 adds.w sl, sl, r4 + 24eac: eb4b 0b05 adc.w fp, fp, r5 + 24eb0: e9cd ab18 strd sl, fp, [sp, #96] ; 0x60 + 24eb4: e9dd 4526 ldrd r4, r5, [sp, #152] ; 0x98 + 24eb8: e9dd ab10 ldrd sl, fp, [sp, #64] ; 0x40 + 24ebc: eb1a 0a04 adds.w sl, sl, r4 + 24ec0: eb4b 0b05 adc.w fp, fp, r5 + 24ec4: e9cd ab30 strd sl, fp, [sp, #192] ; 0xc0 + 24ec8: e9dd 452c ldrd r4, r5, [sp, #176] ; 0xb0 + 24ecc: e9dd ab0e ldrd sl, fp, [sp, #56] ; 0x38 + 24ed0: eb1a 0a04 adds.w sl, sl, r4 + 24ed4: eb4b 0b05 adc.w fp, fp, r5 + 24ed8: e9cd ab26 strd sl, fp, [sp, #152] ; 0x98 + 24edc: e9dd 451c ldrd r4, r5, [sp, #112] ; 0x70 + 24ee0: e9dd ab08 ldrd sl, fp, [sp, #32] + 24ee4: eb1a 0a04 adds.w sl, sl, r4 + 24ee8: f8cd c05c str.w ip, [sp, #92] ; 0x5c + 24eec: eb4b 0b05 adc.w fp, fp, r5 + 24ef0: e9cd ab28 strd sl, fp, [sp, #160] ; 0xa0 + 24ef4: e9dd 452e ldrd r4, r5, [sp, #184] ; 0xb8 + 24ef8: e9dd ab16 ldrd sl, fp, [sp, #88] ; 0x58 + 24efc: eb1a 0a04 adds.w sl, sl, r4 + 24f00: eb4b 0b05 adc.w fp, fp, r5 + 24f04: e9cd ab2e strd sl, fp, [sp, #184] ; 0xb8 + 24f08: f241 5bd1 movw fp, #5585 ; 0x15d1 + 24f0c: f2c0 0b02 movt fp, #2 + 24f10: fba0 ab0b umull sl, fp, r0, fp + 24f14: e9cd ab0c strd sl, fp, [sp, #48] ; 0x30 + 24f18: f64f 3b67 movw fp, #64359 ; 0xfb67 + 24f1c: f642 5518 movw r5, #11544 ; 0x2d18 + 24f20: f2c0 0b09 movt fp, #9 + 24f24: f2c0 0507 movt r5, #7 + 24f28: fba0 ab0b umull sl, fp, r0, fp + 24f2c: e9cd ab0e strd sl, fp, [sp, #56] ; 0x38 + 24f30: f642 4a13 movw sl, #11283 ; 0x2c13 + 24f34: fba0 4505 umull r4, r5, r0, r5 + 24f38: e9cd 450a strd r4, r5, [sp, #40] ; 0x28 + 24f3c: f642 4513 movw r5, #11283 ; 0x2c13 + 24f40: f2c0 0a0a movt sl, #10 + 24f44: f2c0 050a movt r5, #10 + 24f48: f8dd b010 ldr.w fp, [sp, #16] + 24f4c: f8dd c078 ldr.w ip, [sp, #120] ; 0x78 + 24f50: fbab ab0a umull sl, fp, fp, sl + 24f54: e9cd ab16 strd sl, fp, [sp, #88] ; 0x58 + 24f58: f8dd b004 ldr.w fp, [sp, #4] + 24f5c: fba8 4505 umull r4, r5, r8, r5 + 24f60: fb0e cb0b mla fp, lr, fp, ip + 24f64: e9cd 4514 strd r4, r5, [sp, #80] ; 0x50 + 24f68: f8cd b078 str.w fp, [sp, #120] ; 0x78 + 24f6c: 9c00 ldr r4, [sp, #0] + 24f6e: 4245 negs r5, r0 + 24f70: fba4 ab0e umull sl, fp, r4, lr + 24f74: f24c 6453 movw r4, #50771 ; 0xc653 + 24f78: f6cf 74f0 movt r4, #65520 ; 0xfff0 + 24f7c: fb0e 5c01 mla ip, lr, r1, r5 + 24f80: fb04 5501 mla r5, r4, r1, r5 + 24f84: 952c str r5, [sp, #176] ; 0xb0 + 24f86: fba0 450e umull r4, r5, r0, lr + 24f8a: e9cd 4510 strd r4, r5, [sp, #64] ; 0x40 + 24f8e: f24c 6553 movw r5, #50771 ; 0xc653 + 24f92: f6cf 75f0 movt r5, #65520 ; 0xfff0 + 24f96: fba0 4505 umull r4, r5, r0, r5 + 24f9a: f8cd c088 str.w ip, [sp, #136] ; 0x88 + 24f9e: f8dd c0c8 ldr.w ip, [sp, #200] ; 0xc8 + 24fa2: e9cd 4508 strd r4, r5, [sp, #32] + 24fa6: fb0e cc07 mla ip, lr, r7, ip + 24faa: fba6 450e umull r4, r5, r6, lr + 24fae: f8cd c070 str.w ip, [sp, #112] ; 0x70 + 24fb2: e9cd 4500 strd r4, r5, [sp] + 24fb6: f642 5c18 movw ip, #11544 ; 0x2d18 + 24fba: 9d36 ldr r5, [sp, #216] ; 0xd8 + 24fbc: f2c0 0c07 movt ip, #7 + 24fc0: fb0e 5403 mla r4, lr, r3, r5 + 24fc4: f241 55d1 movw r5, #5585 ; 0x15d1 + 24fc8: f2c0 0502 movt r5, #2 + 24fcc: fba8 670c umull r6, r7, r8, ip + 24fd0: f8dd c034 ldr.w ip, [sp, #52] ; 0x34 + 24fd4: f642 4013 movw r0, #11283 ; 0x2c13 + 24fd8: fb05 c501 mla r5, r5, r1, ip + 24fdc: 950d str r5, [sp, #52] ; 0x34 + 24fde: f642 5518 movw r5, #11544 ; 0x2d18 + 24fe2: f2c0 0507 movt r5, #7 + 24fe6: f8dd c02c ldr.w ip, [sp, #44] ; 0x2c + 24fea: f2c0 000a movt r0, #10 + 24fee: fb05 c501 mla r5, r5, r1, ip + 24ff2: 950b str r5, [sp, #44] ; 0x2c + 24ff4: f64f 3567 movw r5, #64359 ; 0xfb67 + 24ff8: f2c0 0509 movt r5, #9 + 24ffc: f8dd c03c ldr.w ip, [sp, #60] ; 0x3c + 25000: fba2 230e umull r2, r3, r2, lr + 25004: fb05 c501 mla r5, r5, r1, ip + 25008: f642 4c13 movw ip, #11283 ; 0x2c13 + 2500c: f2c0 0c0a movt ip, #10 + 25010: 9915 ldr r1, [sp, #84] ; 0x54 + 25012: 950f str r5, [sp, #60] ; 0x3c + 25014: fb00 1009 mla r0, r0, r9, r1 + 25018: 9d05 ldr r5, [sp, #20] + 2501a: 9015 str r0, [sp, #84] ; 0x54 + 2501c: 9817 ldr r0, [sp, #92] ; 0x5c + 2501e: 9903 ldr r1, [sp, #12] + 25020: fb0c 0505 mla r5, ip, r5, r0 + 25024: 9517 str r5, [sp, #92] ; 0x5c + 25026: 9d02 ldr r5, [sp, #8] + 25028: f8dd c078 ldr.w ip, [sp, #120] ; 0x78 + 2502c: 0549 lsls r1, r1, #21 + 2502e: ea41 25d5 orr.w r5, r1, r5, lsr #11 + 25032: 9507 str r5, [sp, #28] + 25034: 44e3 add fp, ip + 25036: 9d2c ldr r5, [sp, #176] ; 0xb0 + 25038: f8dd c024 ldr.w ip, [sp, #36] ; 0x24 + 2503c: 9911 ldr r1, [sp, #68] ; 0x44 + 2503e: 44ac add ip, r5 + 25040: f642 5518 movw r5, #11544 ; 0x2d18 + 25044: f2c0 0507 movt r5, #7 + 25048: 9822 ldr r0, [sp, #136] ; 0x88 + 2504a: 4423 add r3, r4 + 2504c: 4408 add r0, r1 + 2504e: 9011 str r0, [sp, #68] ; 0x44 + 25050: 9901 ldr r1, [sp, #4] + 25052: 981c ldr r0, [sp, #112] ; 0x70 + 25054: 9c02 ldr r4, [sp, #8] + 25056: 4401 add r1, r0 + 25058: 0564 lsls r4, r4, #21 + 2505a: f8cd c024 str.w ip, [sp, #36] ; 0x24 + 2505e: 9101 str r1, [sp, #4] + 25060: 9406 str r4, [sp, #24] + 25062: e9dd 0120 ldrd r0, r1, [sp, #128] ; 0x80 + 25066: eb10 000a adds.w r0, r0, sl + 2506a: fb05 7709 mla r7, r5, r9, r7 + 2506e: e9dd 4510 ldrd r4, r5, [sp, #64] ; 0x40 + 25072: eb41 010b adc.w r1, r1, fp + 25076: e9dd ab38 ldrd sl, fp, [sp, #224] ; 0xe0 + 2507a: eb14 040a adds.w r4, r4, sl + 2507e: eb45 050b adc.w r5, r5, fp + 25082: e9cd 0132 strd r0, r1, [sp, #200] ; 0xc8 + 25086: e9dd 0108 ldrd r0, r1, [sp, #32] + 2508a: e9dd ab00 ldrd sl, fp, [sp] + 2508e: e9cd 452c strd r4, r5, [sp, #176] ; 0xb0 + 25092: e9dd 452a ldrd r4, r5, [sp, #168] ; 0xa8 + 25096: 1900 adds r0, r0, r4 + 25098: 4169 adcs r1, r5 + 2509a: e9cd 0108 strd r0, r1, [sp, #32] + 2509e: e9dd 0124 ldrd r0, r1, [sp, #144] ; 0x90 + 250a2: e9dd 4518 ldrd r4, r5, [sp, #96] ; 0x60 + 250a6: eb1a 0a00 adds.w sl, sl, r0 + 250aa: eb4b 0b01 adc.w fp, fp, r1 + 250ae: 18a4 adds r4, r4, r2 + 250b0: e9dd 0130 ldrd r0, r1, [sp, #192] ; 0xc0 + 250b4: 415d adcs r5, r3 + 250b6: e9cd ab22 strd sl, fp, [sp, #136] ; 0x88 + 250ba: e9dd ab0c ldrd sl, fp, [sp, #48] ; 0x30 + 250be: e9dd 231a ldrd r2, r3, [sp, #104] ; 0x68 + 250c2: eb1a 0a00 adds.w sl, sl, r0 + 250c6: eb4b 0b01 adc.w fp, fp, r1 + 250ca: e9cd 451c strd r4, r5, [sp, #112] ; 0x70 + 250ce: e9dd 4506 ldrd r4, r5, [sp, #24] + 250d2: e9dd 0126 ldrd r0, r1, [sp, #152] ; 0x98 + 250d6: 1b12 subs r2, r2, r4 + 250d8: eb63 0305 sbc.w r3, r3, r5 + 250dc: e9cd ab0c strd sl, fp, [sp, #48] ; 0x30 + 250e0: e9dd ab0a ldrd sl, fp, [sp, #40] ; 0x28 + 250e4: e9dd 4528 ldrd r4, r5, [sp, #160] ; 0xa0 + 250e8: eb1a 0a00 adds.w sl, sl, r0 + 250ec: eb4b 0b01 adc.w fp, fp, r1 + 250f0: e9cd 2330 strd r2, r3, [sp, #192] ; 0xc0 + 250f4: e9dd 230e ldrd r2, r3, [sp, #56] ; 0x38 + 250f8: e9dd 0134 ldrd r0, r1, [sp, #208] ; 0xd0 + 250fc: 1912 adds r2, r2, r4 + 250fe: 416b adcs r3, r5 + 25100: e9cd ab02 strd sl, fp, [sp, #8] + 25104: e9dd ab14 ldrd sl, fp, [sp, #80] ; 0x50 + 25108: e9dd 453c ldrd r4, r5, [sp, #240] ; 0xf0 + 2510c: eb1a 0a00 adds.w sl, sl, r0 + 25110: eb4b 0b01 adc.w fp, fp, r1 + 25114: e9cd 2306 strd r2, r3, [sp, #24] + 25118: e9dd 2316 ldrd r2, r3, [sp, #88] ; 0x58 + 2511c: 1912 adds r2, r2, r4 + 2511e: 416b adcs r3, r5 + 25120: e9cd 2326 strd r2, r3, [sp, #152] ; 0x98 + 25124: f64f 3267 movw r2, #64359 ; 0xfb67 + 25128: f642 5018 movw r0, #11544 ; 0x2d18 + 2512c: f24c 6553 movw r5, #50771 ; 0xc653 + 25130: f2c0 0209 movt r2, #9 + 25134: f2c0 0007 movt r0, #7 + 25138: f6cf 75f0 movt r5, #65520 ; 0xfff0 + 2513c: f8dd c010 ldr.w ip, [sp, #16] + 25140: e9cd ab0a strd sl, fp, [sp, #40] ; 0x28 + 25144: e9dd ab2e ldrd sl, fp, [sp, #184] ; 0xb8 + 25148: fbac 2302 umull r2, r3, ip, r2 + 2514c: eb1a 0a06 adds.w sl, sl, r6 + 25150: eb4b 0b07 adc.w fp, fp, r7 + 25154: e9cd ab0e strd sl, fp, [sp, #56] ; 0x38 + 25158: fbac ab00 umull sl, fp, ip, r0 + 2515c: e9cd 2316 strd r2, r3, [sp, #88] ; 0x58 + 25160: f8dd c014 ldr.w ip, [sp, #20] + 25164: f1c8 0300 rsb r3, r8, #0 + 25168: fb00 bb0c mla fp, r0, ip, fp + 2516c: f64f 3067 movw r0, #64359 ; 0xfb67 + 25170: fb05 3409 mla r4, r5, r9, r3 + 25174: fba8 6705 umull r6, r7, r8, r5 + 25178: f64f 3567 movw r5, #64359 ; 0xfb67 + 2517c: f2c0 0009 movt r0, #9 + 25180: f2c0 0509 movt r5, #9 + 25184: 9917 ldr r1, [sp, #92] ; 0x5c + 25186: 9314 str r3, [sp, #80] ; 0x50 + 25188: fb00 100c mla r0, r0, ip, r1 + 2518c: e9dd 2326 ldrd r2, r3, [sp, #152] ; 0x98 + 25190: 9017 str r0, [sp, #92] ; 0x5c + 25192: f512 1280 adds.w r2, r2, #1048576 ; 0x100000 + 25196: f04f 0000 mov.w r0, #0 + 2519a: f04f 0100 mov.w r1, #0 + 2519e: e9cd 0100 strd r0, r1, [sp] + 251a2: f143 0300 adc.w r3, r3, #0 + 251a6: fba8 0105 umull r0, r1, r8, r5 + 251aa: 4427 add r7, r4 + 251ac: e9dd 450a ldrd r4, r5, [sp, #40] ; 0x28 + 251b0: eb14 040a adds.w r4, r4, sl + 251b4: eb45 050b adc.w r5, r5, fp + 251b8: e9dd ab06 ldrd sl, fp, [sp, #24] + 251bc: eb1a 0a06 adds.w sl, sl, r6 + 251c0: e9cd 450a strd r4, r5, [sp, #40] ; 0x28 + 251c4: e9dd 4516 ldrd r4, r5, [sp, #88] ; 0x58 + 251c8: eb4b 0b07 adc.w fp, fp, r7 + 251cc: e9dd 670e ldrd r6, r7, [sp, #56] ; 0x38 + 251d0: 1936 adds r6, r6, r4 + 251d2: 416f adcs r7, r5 + 251d4: f64f 3567 movw r5, #64359 ; 0xfb67 + 251d8: f2c0 0509 movt r5, #9 + 251dc: e9cd 6728 strd r6, r7, [sp, #160] ; 0xa0 + 251e0: e9dd 6702 ldrd r6, r7, [sp, #8] + 251e4: 1836 adds r6, r6, r0 + 251e6: f241 50d1 movw r0, #5585 ; 0x15d1 + 251ea: fb05 1109 mla r1, r5, r9, r1 + 251ee: f241 55d1 movw r5, #5585 ; 0x15d1 + 251f2: f2c0 0002 movt r0, #2 + 251f6: f2c0 0502 movt r5, #2 + 251fa: f8dd c010 ldr.w ip, [sp, #16] + 251fe: 414f adcs r7, r1 + 25200: e9cd 670e strd r6, r7, [sp, #56] ; 0x38 + 25204: fbac 6700 umull r6, r7, ip, r0 + 25208: 9c05 ldr r4, [sp, #20] + 2520a: 9914 ldr r1, [sp, #80] ; 0x50 + 2520c: fb05 7704 mla r7, r5, r4, r7 + 25210: f241 55d1 movw r5, #5585 ; 0x15d1 + 25214: f2c0 0502 movt r5, #2 + 25218: 0d54 lsrs r4, r2, #21 + 2521a: 9400 str r4, [sp, #0] + 2521c: fba8 4505 umull r4, r5, r8, r5 + 25220: fb0e 1c09 mla ip, lr, r9, r1 + 25224: fba8 010e umull r0, r1, r8, lr + 25228: e9cd 4502 strd r4, r5, [sp, #8] + 2522c: 9c00 ldr r4, [sp, #0] + 2522e: 4461 add r1, ip + 25230: ea44 24c3 orr.w r4, r4, r3, lsl #11 + 25234: 155d asrs r5, r3, #21 + 25236: e9dd 230c ldrd r2, r3, [sp, #48] ; 0x30 + 2523a: 1812 adds r2, r2, r0 + 2523c: 9400 str r4, [sp, #0] + 2523e: 9501 str r5, [sp, #4] + 25240: 414b adcs r3, r1 + 25242: eb16 040a adds.w r4, r6, sl + 25246: eb47 050b adc.w r5, r7, fp + 2524a: e9dd ab00 ldrd sl, fp, [sp] + 2524e: e9dd 670a ldrd r6, r7, [sp, #40] ; 0x28 + 25252: eb16 060a adds.w r6, r6, sl + 25256: eb47 070b adc.w r7, r7, fp + 2525a: e9cd 672a strd r6, r7, [sp, #168] ; 0xa8 + 2525e: f241 57d1 movw r7, #5585 ; 0x15d1 + 25262: f24c 6c53 movw ip, #50771 ; 0xc653 + 25266: f2c0 0702 movt r7, #2 + 2526a: f6cf 7cf0 movt ip, #65520 ; 0xfff0 + 2526e: e9cd 4524 strd r4, r5, [sp, #144] ; 0x90 + 25272: f8dd a00c ldr.w sl, [sp, #12] + 25276: 9d04 ldr r5, [sp, #16] + 25278: f8dd b014 ldr.w fp, [sp, #20] + 2527c: 9e04 ldr r6, [sp, #16] + 2527e: e9cd 2318 strd r2, r3, [sp, #96] ; 0x60 + 25282: fb07 a709 mla r7, r7, r9, sl + 25286: 426b negs r3, r5 + 25288: fba6 010c umull r0, r1, r6, ip + 2528c: e9dd 4528 ldrd r4, r5, [sp, #160] ; 0xa0 + 25290: fb0c 320b mla r2, ip, fp, r3 + 25294: f514 1480 adds.w r4, r4, #1048576 ; 0x100000 + 25298: 9703 str r7, [sp, #12] + 2529a: f145 0500 adc.w r5, r5, #0 + 2529e: e9dd 8922 ldrd r8, r9, [sp, #136] ; 0x88 + 252a2: f518 1880 adds.w r8, r8, #1048576 ; 0x100000 + 252a6: e9dd 670e ldrd r6, r7, [sp, #56] ; 0x38 + 252aa: f149 0900 adc.w r9, r9, #0 + 252ae: 4411 add r1, r2 + 252b0: 1836 adds r6, r6, r0 + 252b2: e9dd ab08 ldrd sl, fp, [sp, #32] + 252b6: e9cd 891e strd r8, r9, [sp, #120] ; 0x78 + 252ba: e9dd 8902 ldrd r8, r9, [sp, #8] + 252be: 414f adcs r7, r1 + 252c0: eb18 080a adds.w r8, r8, sl + 252c4: eb49 090b adc.w r9, r9, fp + 252c8: e9dd 0124 ldrd r0, r1, [sp, #144] ; 0x90 + 252cc: f510 1080 adds.w r0, r0, #1048576 ; 0x100000 + 252d0: e9cd 892e strd r8, r9, [sp, #184] ; 0xb8 + 252d4: e9dd 892a ldrd r8, r9, [sp, #168] ; 0xa8 + 252d8: f141 0100 adc.w r1, r1, #0 + 252dc: f518 1880 adds.w r8, r8, #1048576 ; 0x100000 + 252e0: e9cd 0114 strd r0, r1, [sp, #80] ; 0x50 + 252e4: e9dd 0118 ldrd r0, r1, [sp, #96] ; 0x60 + 252e8: f149 0900 adc.w r9, r9, #0 + 252ec: f510 1080 adds.w r0, r0, #1048576 ; 0x100000 + 252f0: e9cd 6734 strd r6, r7, [sp, #208] ; 0xd0 + 252f4: f141 0100 adc.w r1, r1, #0 + 252f8: 2700 movs r7, #0 + 252fa: 2600 movs r6, #0 + 252fc: e9cd 8920 strd r8, r9, [sp, #128] ; 0x80 + 25300: e9cd 0116 strd r0, r1, [sp, #88] ; 0x58 + 25304: 46b9 mov r9, r7 + 25306: 4630 mov r0, r6 + 25308: 4639 mov r1, r7 + 2530a: e9dd 671c ldrd r6, r7, [sp, #112] ; 0x70 + 2530e: f516 1680 adds.w r6, r6, #1048576 ; 0x100000 + 25312: f147 0700 adc.w r7, r7, #0 + 25316: f8dd 8010 ldr.w r8, [sp, #16] + 2531a: e9cd 671a strd r6, r7, [sp, #104] ; 0x68 + 2531e: 9f05 ldr r7, [sp, #20] + 25320: ea4f 5a54 mov.w sl, r4, lsr #21 + 25324: fb0e 3c07 mla ip, lr, r7, r3 + 25328: ea4a 2ac5 orr.w sl, sl, r5, lsl #11 + 2532c: fba8 230e umull r2, r3, r8, lr + 25330: ea4f 5b65 mov.w fp, r5, asr #21 + 25334: 4680 mov r8, r0 + 25336: 464d mov r5, r9 + 25338: 4689 mov r9, r1 + 2533a: 4604 mov r4, r0 + 2533c: 4606 mov r6, r0 + 2533e: 460f mov r7, r1 + 25340: e9cd 8908 strd r8, r9, [sp, #32] + 25344: f8dd 9078 ldr.w r9, [sp, #120] ; 0x78 + 25348: e9cd 4504 strd r4, r5, [sp, #16] + 2534c: 9d1f ldr r5, [sp, #124] ; 0x7c + 2534e: e9cd 6710 strd r6, r7, [sp, #64] ; 0x40 + 25352: ea4f 5959 mov.w r9, r9, lsr #21 + 25356: ea4f 574b mov.w r7, fp, lsl #21 + 2535a: e9cd 010c strd r0, r1, [sp, #48] ; 0x30 + 2535e: ea49 24c5 orr.w r4, r9, r5, lsl #11 + 25362: ea47 21da orr.w r1, r7, sl, lsr #11 + 25366: e9dd 892e ldrd r8, r9, [sp, #184] ; 0xb8 + 2536a: ea4f 564a mov.w r6, sl, lsl #21 + 2536e: eb12 0208 adds.w r2, r2, r8 + 25372: 4463 add r3, ip + 25374: 910b str r1, [sp, #44] ; 0x2c + 25376: eb43 0309 adc.w r3, r3, r9 + 2537a: e9dd 0134 ldrd r0, r1, [sp, #208] ; 0xd0 + 2537e: 960a str r6, [sp, #40] ; 0x28 + 25380: eb10 000a adds.w r0, r0, sl + 25384: ea4f 5765 mov.w r7, r5, asr #21 + 25388: 9406 str r4, [sp, #24] + 2538a: 9707 str r7, [sp, #28] + 2538c: e9dd 4528 ldrd r4, r5, [sp, #160] ; 0xa0 + 25390: e9dd 670a ldrd r6, r7, [sp, #40] ; 0x28 + 25394: eb41 010b adc.w r1, r1, fp + 25398: 1ba4 subs r4, r4, r6 + 2539a: e9dd ab06 ldrd sl, fp, [sp, #24] + 2539e: eb65 0507 sbc.w r5, r5, r7 + 253a2: e9dd 8930 ldrd r8, r9, [sp, #192] ; 0xc0 + 253a6: eb18 080a adds.w r8, r8, sl + 253aa: eb49 090b adc.w r9, r9, fp + 253ae: e9cd 011e strd r0, r1, [sp, #120] ; 0x78 + 253b2: e9cd 4528 strd r4, r5, [sp, #160] ; 0xa0 + 253b6: e9cd 8934 strd r8, r9, [sp, #208] ; 0xd0 + 253ba: f8dd c080 ldr.w ip, [sp, #128] ; 0x80 + 253be: 9d1a ldr r5, [sp, #104] ; 0x68 + 253c0: f8dd b050 ldr.w fp, [sp, #80] ; 0x50 + 253c4: 9c16 ldr r4, [sp, #88] ; 0x58 + 253c6: f8dd a054 ldr.w sl, [sp, #84] ; 0x54 + 253ca: ea4f 5b5b mov.w fp, fp, lsr #21 + 253ce: ea4f 585c mov.w r8, ip, lsr #21 + 253d2: 0d6e lsrs r6, r5, #21 + 253d4: f8dd c05c ldr.w ip, [sp, #92] ; 0x5c + 253d8: 9d15 ldr r5, [sp, #84] ; 0x54 + 253da: ea4b 2aca orr.w sl, fp, sl, lsl #11 + 253de: 0d60 lsrs r0, r4, #21 + 253e0: f8dd b084 ldr.w fp, [sp, #132] ; 0x84 + 253e4: 9c1b ldr r4, [sp, #108] ; 0x6c + 253e6: ea4f 516c mov.w r1, ip, asr #21 + 253ea: 156d asrs r5, r5, #21 + 253ec: f8cd a008 str.w sl, [sp, #8] + 253f0: ea48 28cb orr.w r8, r8, fp, lsl #11 + 253f4: ea46 26c4 orr.w r6, r6, r4, lsl #11 + 253f8: ea4f 596b mov.w r9, fp, asr #21 + 253fc: 1567 asrs r7, r4, #21 + 253fe: 9503 str r5, [sp, #12] + 25400: 056c lsls r4, r5, #21 + 25402: ea4f 5b41 mov.w fp, r1, lsl #21 + 25406: 9d01 ldr r5, [sp, #4] + 25408: ea40 20cc orr.w r0, r0, ip, lsl #11 + 2540c: f8cd b024 str.w fp, [sp, #36] ; 0x24 + 25410: f8dd c01c ldr.w ip, [sp, #28] + 25414: f8dd b008 ldr.w fp, [sp, #8] + 25418: ea4f 5a49 mov.w sl, r9, lsl #21 + 2541c: 056d lsls r5, r5, #21 + 2541e: 9505 str r5, [sp, #20] + 25420: f8cd a044 str.w sl, [sp, #68] ; 0x44 + 25424: ea4f 5c4c mov.w ip, ip, lsl #21 + 25428: ea44 2adb orr.w sl, r4, fp, lsr #11 + 2542c: f8cd c034 str.w ip, [sp, #52] ; 0x34 + 25430: f8dd b044 ldr.w fp, [sp, #68] ; 0x44 + 25434: f8dd c014 ldr.w ip, [sp, #20] + 25438: f8cd a03c str.w sl, [sp, #60] ; 0x3c + 2543c: f8dd a000 ldr.w sl, [sp] + 25440: ea4b 2bd8 orr.w fp, fp, r8, lsr #11 + 25444: ea4c 2cda orr.w ip, ip, sl, lsr #11 + 25448: f8cd c014 str.w ip, [sp, #20] + 2544c: f8dd a034 ldr.w sl, [sp, #52] ; 0x34 + 25450: f8dd c024 ldr.w ip, [sp, #36] ; 0x24 + 25454: f8cd b044 str.w fp, [sp, #68] ; 0x44 + 25458: f8dd b018 ldr.w fp, [sp, #24] + 2545c: ea4c 2cd0 orr.w ip, ip, r0, lsr #11 + 25460: ea4a 2adb orr.w sl, sl, fp, lsr #11 + 25464: f8cd c024 str.w ip, [sp, #36] ; 0x24 + 25468: f8cd a034 str.w sl, [sp, #52] ; 0x34 + 2546c: f8dd c008 ldr.w ip, [sp, #8] + 25470: f8dd a000 ldr.w sl, [sp] + 25474: ea4f 5b48 mov.w fp, r8, lsl #21 + 25478: ea4f 5c4c mov.w ip, ip, lsl #21 + 2547c: ea4f 5a4a mov.w sl, sl, lsl #21 + 25480: f8cd c038 str.w ip, [sp, #56] ; 0x38 + 25484: f8cd a010 str.w sl, [sp, #16] + 25488: f8cd b040 str.w fp, [sp, #64] ; 0x40 + 2548c: f8dd a018 ldr.w sl, [sp, #24] + 25490: ea4f 5c40 mov.w ip, r0, lsl #21 + 25494: ea4f 5a4a mov.w sl, sl, lsl #21 + 25498: f8cd a030 str.w sl, [sp, #48] ; 0x30 + 2549c: e9dd ab02 ldrd sl, fp, [sp, #8] + 254a0: eb1a 0a02 adds.w sl, sl, r2 + 254a4: eb4b 0b03 adc.w fp, fp, r3 + 254a8: e9cd ab0a strd sl, fp, [sp, #40] ; 0x28 + 254ac: e9dd 2324 ldrd r2, r3, [sp, #144] ; 0x90 + 254b0: e9dd ab0e ldrd sl, fp, [sp, #56] ; 0x38 + 254b4: ebb2 020a subs.w r2, r2, sl + 254b8: eb63 030b sbc.w r3, r3, fp + 254bc: e9cd 2306 strd r2, r3, [sp, #24] + 254c0: e9dd ab04 ldrd sl, fp, [sp, #16] + 254c4: e9dd 2326 ldrd r2, r3, [sp, #152] ; 0x98 + 254c8: ebb2 020a subs.w r2, r2, sl + 254cc: eb63 030b sbc.w r3, r3, fp + 254d0: e9cd 2304 strd r2, r3, [sp, #16] + 254d4: e9dd ab10 ldrd sl, fp, [sp, #64] ; 0x40 + 254d8: e9dd 232a ldrd r2, r3, [sp, #168] ; 0xa8 + 254dc: ebb2 020a subs.w r2, r2, sl + 254e0: eb63 030b sbc.w r3, r3, fp + 254e4: e9cd 2300 strd r2, r3, [sp] + 254e8: e9dd 2328 ldrd r2, r3, [sp, #160] ; 0xa0 + 254ec: e9dd ab18 ldrd sl, fp, [sp, #96] ; 0x60 + 254f0: eb12 0208 adds.w r2, r2, r8 + 254f4: f8cd c020 str.w ip, [sp, #32] + 254f8: eb43 0309 adc.w r3, r3, r9 + 254fc: e9dd 892c ldrd r8, r9, [sp, #176] ; 0xb0 + 25500: eb18 0800 adds.w r8, r8, r0 + 25504: eb49 0901 adc.w r9, r9, r1 + 25508: e9dd 0108 ldrd r0, r1, [sp, #32] + 2550c: ebba 0a00 subs.w sl, sl, r0 + 25510: eb6b 0b01 sbc.w fp, fp, r1 + 25514: 0574 lsls r4, r6, #21 + 25516: e9cd 2302 strd r2, r3, [sp, #8] + 2551a: e9dd 2332 ldrd r2, r3, [sp, #200] ; 0xc8 + 2551e: 057d lsls r5, r7, #21 + 25520: 1992 adds r2, r2, r6 + 25522: 417b adcs r3, r7 + 25524: ea45 25d6 orr.w r5, r5, r6, lsr #11 + 25528: e9dd 671c ldrd r6, r7, [sp, #112] ; 0x70 + 2552c: 1b36 subs r6, r6, r4 + 2552e: eb67 0705 sbc.w r7, r7, r5 + 25532: e9cd 890e strd r8, r9, [sp, #56] ; 0x38 + 25536: e9dd 8922 ldrd r8, r9, [sp, #136] ; 0x88 + 2553a: e9dd 451e ldrd r4, r5, [sp, #120] ; 0x78 + 2553e: e9cd ab08 strd sl, fp, [sp, #32] + 25542: e9dd ab0c ldrd sl, fp, [sp, #48] ; 0x30 + 25546: ebb8 080a subs.w r8, r8, sl + 2554a: eb69 090b sbc.w r9, r9, fp + 2554e: f642 4b13 movw fp, #11283 ; 0x2c13 + 25552: f642 5c18 movw ip, #11544 ; 0x2d18 + 25556: f2c0 0b0a movt fp, #10 + 2555a: f2c0 0c07 movt ip, #7 + 2555e: f514 1480 adds.w r4, r4, #1048576 ; 0x100000 + 25562: f145 0500 adc.w r5, r5, #0 + 25566: e9cd 232e strd r2, r3, [sp, #184] ; 0xb8 + 2556a: e9dd 2334 ldrd r2, r3, [sp, #208] ; 0xd0 + 2556e: f512 1280 adds.w r2, r2, #1048576 ; 0x100000 + 25572: e9cd 672c strd r6, r7, [sp, #176] ; 0xb0 + 25576: f143 0300 adc.w r3, r3, #0 + 2557a: 0d56 lsrs r6, r2, #21 + 2557c: ea46 26c3 orr.w r6, r6, r3, lsl #11 + 25580: fba6 010b umull r0, r1, r6, fp + 25584: 155f asrs r7, r3, #21 + 25586: fb0b 1107 mla r1, fp, r7, r1 + 2558a: f64f 3b67 movw fp, #64359 ; 0xfb67 + 2558e: fba6 230c umull r2, r3, r6, ip + 25592: e9cd 8938 strd r8, r9, [sp, #224] ; 0xe0 + 25596: e9dd 8904 ldrd r8, r9, [sp, #16] + 2559a: eb18 0800 adds.w r8, r8, r0 + 2559e: eb49 0901 adc.w r9, r9, r1 + 255a2: e9cd 8922 strd r8, r9, [sp, #136] ; 0x88 + 255a6: e9dd 8900 ldrd r8, r9, [sp] + 255aa: fb0c 3307 mla r3, ip, r7, r3 + 255ae: f8dd c088 ldr.w ip, [sp, #136] ; 0x88 + 255b2: eb18 0802 adds.w r8, r8, r2 + 255b6: 9a23 ldr r2, [sp, #140] ; 0x8c + 255b8: ea4f 5c5c mov.w ip, ip, lsr #21 + 255bc: ea4c 22c2 orr.w r2, ip, r2, lsl #11 + 255c0: 9204 str r2, [sp, #16] + 255c2: eb49 0903 adc.w r9, r9, r3 + 255c6: 9b23 ldr r3, [sp, #140] ; 0x8c + 255c8: f2c0 0b09 movt fp, #9 + 255cc: 155b asrs r3, r3, #21 + 255ce: 9305 str r3, [sp, #20] + 255d0: e9dd 2304 ldrd r2, r3, [sp, #16] + 255d4: eb12 0208 adds.w r2, r2, r8 + 255d8: eb43 0309 adc.w r3, r3, r9 + 255dc: f24c 6853 movw r8, #50771 ; 0xc653 + 255e0: f24c 6953 movw r9, #50771 ; 0xc653 + 255e4: f6cf 78f0 movt r8, #65520 ; 0xfff0 + 255e8: f6cf 79f0 movt r9, #65520 ; 0xfff0 + 255ec: fba6 010b umull r0, r1, r6, fp + 255f0: fb0b 1107 mla r1, fp, r7, r1 + 255f4: e9cd 231c strd r2, r3, [sp, #112] ; 0x70 + 255f8: e9dd 2302 ldrd r2, r3, [sp, #8] + 255fc: ea4f 5a54 mov.w sl, r4, lsr #21 + 25600: 1812 adds r2, r2, r0 + 25602: ea4a 2ac5 orr.w sl, sl, r5, lsl #11 + 25606: ea4f 5b65 mov.w fp, r5, asr #21 + 2560a: 414b adcs r3, r1 + 2560c: e9cd 2302 strd r2, r3, [sp, #8] + 25610: e9dd 451e ldrd r4, r5, [sp, #120] ; 0x78 + 25614: ea4f 524a mov.w r2, sl, lsl #21 + 25618: ea4f 534b mov.w r3, fp, lsl #21 + 2561c: 1aa4 subs r4, r4, r2 + 2561e: ea43 23da orr.w r3, r3, sl, lsr #11 + 25622: eb65 0503 sbc.w r5, r5, r3 + 25626: e9cd 450c strd r4, r5, [sp, #48] ; 0x30 + 2562a: 9d1c ldr r5, [sp, #112] ; 0x70 + 2562c: f1c6 0c00 rsb ip, r6, #0 + 25630: 981d ldr r0, [sp, #116] ; 0x74 + 25632: 991d ldr r1, [sp, #116] ; 0x74 + 25634: fba6 2308 umull r2, r3, r6, r8 + 25638: 0d6d lsrs r5, r5, #21 + 2563a: fb09 c807 mla r8, r9, r7, ip + 2563e: ea45 20c0 orr.w r0, r5, r0, lsl #11 + 25642: 1549 asrs r1, r1, #21 + 25644: 9000 str r0, [sp, #0] + 25646: 9101 str r1, [sp, #4] + 25648: e9dd 4500 ldrd r4, r5, [sp] + 2564c: e9dd 0102 ldrd r0, r1, [sp, #8] + 25650: 1824 adds r4, r4, r0 + 25652: 414d adcs r5, r1 + 25654: 4443 add r3, r8 + 25656: e9dd 890c ldrd r8, r9, [sp, #48] ; 0x30 + 2565a: eb18 0802 adds.w r8, r8, r2 + 2565e: f241 52d1 movw r2, #5585 ; 0x15d1 + 25662: e9dd 0106 ldrd r0, r1, [sp, #24] + 25666: f2c0 0202 movt r2, #2 + 2566a: eb49 0903 adc.w r9, r9, r3 + 2566e: e9cd 890c strd r8, r9, [sp, #48] ; 0x30 + 25672: e9dd 890a ldrd r8, r9, [sp, #40] ; 0x28 + 25676: f518 1880 adds.w r8, r8, #1048576 ; 0x100000 + 2567a: e9cd 4518 strd r4, r5, [sp, #96] ; 0x60 + 2567e: f149 0900 adc.w r9, r9, #0 + 25682: eb10 000a adds.w r0, r0, sl + 25686: eb41 010b adc.w r1, r1, fp + 2568a: 9b18 ldr r3, [sp, #96] ; 0x60 + 2568c: e9cd 0110 strd r0, r1, [sp, #64] ; 0x40 + 25690: e9dd ab0c ldrd sl, fp, [sp, #48] ; 0x30 + 25694: fba6 0102 umull r0, r1, r6, r2 + 25698: 9c19 ldr r4, [sp, #100] ; 0x64 + 2569a: 9d19 ldr r5, [sp, #100] ; 0x64 + 2569c: 0d5b lsrs r3, r3, #21 + 2569e: ea43 24c4 orr.w r4, r3, r4, lsl #11 + 256a2: 156d asrs r5, r5, #21 + 256a4: 9402 str r4, [sp, #8] + 256a6: 9503 str r5, [sp, #12] + 256a8: fb02 1107 mla r1, r2, r7, r1 + 256ac: e9dd 2302 ldrd r2, r3, [sp, #8] + 256b0: eb1a 0a02 adds.w sl, sl, r2 + 256b4: eb4b 0b03 adc.w fp, fp, r3 + 256b8: ea4f 5458 mov.w r4, r8, lsr #21 + 256bc: e9cd ab26 strd sl, fp, [sp, #152] ; 0x98 + 256c0: ea44 24c9 orr.w r4, r4, r9, lsl #11 + 256c4: ea4f 5569 mov.w r5, r9, asr #21 + 256c8: f04f 0a00 mov.w sl, #0 + 256cc: f04f 0b00 mov.w fp, #0 + 256d0: e9cd ab06 strd sl, fp, [sp, #24] + 256d4: e9dd ab10 ldrd sl, fp, [sp, #64] ; 0x40 + 256d8: 056b lsls r3, r5, #21 + 256da: eb1a 0a00 adds.w sl, sl, r0 + 256de: ea4f 5244 mov.w r2, r4, lsl #21 + 256e2: eb4b 0b01 adc.w fp, fp, r1 + 256e6: ea43 23d4 orr.w r3, r3, r4, lsr #11 + 256ea: e9dd 010a ldrd r0, r1, [sp, #40] ; 0x28 + 256ee: 1a82 subs r2, r0, r2 + 256f0: eb61 0303 sbc.w r3, r1, r3 + 256f4: 9926 ldr r1, [sp, #152] ; 0x98 + 256f6: fb0e cc07 mla ip, lr, r7, ip + 256fa: 0d49 lsrs r1, r1, #21 + 256fc: 9106 str r1, [sp, #24] + 256fe: f8dd 909c ldr.w r9, [sp, #156] ; 0x9c + 25702: f8dd 8018 ldr.w r8, [sp, #24] + 25706: fba6 010e umull r0, r1, r6, lr + 2570a: ea48 28c9 orr.w r8, r8, r9, lsl #11 + 2570e: ea4f 5e69 mov.w lr, r9, asr #21 + 25712: f8cd e01c str.w lr, [sp, #28] + 25716: f8cd 8018 str.w r8, [sp, #24] + 2571a: e9dd 8906 ldrd r8, r9, [sp, #24] + 2571e: eb18 080a adds.w r8, r8, sl + 25722: eb49 090b adc.w r9, r9, fp + 25726: e9cd 8928 strd r8, r9, [sp, #160] ; 0xa0 + 2572a: f8dd e0a4 ldr.w lr, [sp, #164] ; 0xa4 + 2572e: ea4f 5b58 mov.w fp, r8, lsr #21 + 25732: 4461 add r1, ip + 25734: ea4f 5e6e mov.w lr, lr, asr #21 + 25738: ea4b 2cc9 orr.w ip, fp, r9, lsl #11 + 2573c: 1812 adds r2, r2, r0 + 2573e: f8cd c028 str.w ip, [sp, #40] ; 0x28 + 25742: f8cd e02c str.w lr, [sp, #44] ; 0x2c + 25746: 414b adcs r3, r1 + 25748: e9dd 010a ldrd r0, r1, [sp, #40] ; 0x28 + 2574c: 1880 adds r0, r0, r2 + 2574e: 4159 adcs r1, r3 + 25750: e9cd 0124 strd r0, r1, [sp, #144] ; 0x90 + 25754: e9dd 890e ldrd r8, r9, [sp, #56] ; 0x38 + 25758: e9dd 0108 ldrd r0, r1, [sp, #32] + 2575c: f518 1880 adds.w r8, r8, #1048576 ; 0x100000 + 25760: 9a24 ldr r2, [sp, #144] ; 0x90 + 25762: f149 0900 adc.w r9, r9, #0 + 25766: 1900 adds r0, r0, r4 + 25768: 9c25 ldr r4, [sp, #148] ; 0x94 + 2576a: ea4f 5a52 mov.w sl, r2, lsr #21 + 2576e: ea4a 2ac4 orr.w sl, sl, r4, lsl #11 + 25772: ea4f 5258 mov.w r2, r8, lsr #21 + 25776: 4169 adcs r1, r5 + 25778: ea42 22c9 orr.w r2, r2, r9, lsl #11 + 2577c: eb10 080a adds.w r8, r0, sl + 25780: ea4f 5b64 mov.w fp, r4, asr #21 + 25784: ea4f 5369 mov.w r3, r9, asr #21 + 25788: ea4f 5543 mov.w r5, r3, lsl #21 + 2578c: eb41 090b adc.w r9, r1, fp + 25790: 0554 lsls r4, r2, #21 + 25792: e9dd 010e ldrd r0, r1, [sp, #56] ; 0x38 + 25796: e9cd 892a strd r8, r9, [sp, #168] ; 0xa8 + 2579a: 1b04 subs r4, r0, r4 + 2579c: ea45 25d2 orr.w r5, r5, r2, lsr #11 + 257a0: eb61 0505 sbc.w r5, r1, r5 + 257a4: 992a ldr r1, [sp, #168] ; 0xa8 + 257a6: 057f lsls r7, r7, #21 + 257a8: ea4f 5851 mov.w r8, r1, lsr #21 + 257ac: e9dd 012e ldrd r0, r1, [sp, #184] ; 0xb8 + 257b0: f510 1080 adds.w r0, r0, #1048576 ; 0x100000 + 257b4: f141 0100 adc.w r1, r1, #0 + 257b8: e9cd 0132 strd r0, r1, [sp, #200] ; 0xc8 + 257bc: 992b ldr r1, [sp, #172] ; 0xac + 257be: 2000 movs r0, #0 + 257c0: ea48 28c1 orr.w r8, r8, r1, lsl #11 + 257c4: ea4f 5961 mov.w r9, r1, asr #21 + 257c8: 2100 movs r1, #0 + 257ca: e9cd 0108 strd r0, r1, [sp, #32] + 257ce: e9cd 010c strd r0, r1, [sp, #48] ; 0x30 + 257d2: e9cd 0114 strd r0, r1, [sp, #80] ; 0x50 + 257d6: e9cd 0110 strd r0, r1, [sp, #64] ; 0x40 + 257da: e9cd 0116 strd r0, r1, [sp, #88] ; 0x58 + 257de: e9cd 011a strd r0, r1, [sp, #104] ; 0x68 + 257e2: e9cd 011e strd r0, r1, [sp, #120] ; 0x78 + 257e6: eb14 0008 adds.w r0, r4, r8 + 257ea: eb45 0109 adc.w r1, r5, r9 + 257ee: 2400 movs r4, #0 + 257f0: 2500 movs r5, #0 + 257f2: e9cd 0130 strd r0, r1, [sp, #192] ; 0xc0 + 257f6: 4620 mov r0, r4 + 257f8: 4629 mov r1, r5 + 257fa: e9dd 452c ldrd r4, r5, [sp, #176] ; 0xb0 + 257fe: 1912 adds r2, r2, r4 + 25800: f8dd c0cc ldr.w ip, [sp, #204] ; 0xcc + 25804: e9cd 010e strd r0, r1, [sp, #56] ; 0x38 + 25808: 416b adcs r3, r5 + 2580a: 9d32 ldr r5, [sp, #200] ; 0xc8 + 2580c: 9709 str r7, [sp, #36] ; 0x24 + 2580e: 9f07 ldr r7, [sp, #28] + 25810: f8dd e014 ldr.w lr, [sp, #20] + 25814: 0d68 lsrs r0, r5, #21 + 25816: 057f lsls r7, r7, #21 + 25818: ea40 20cc orr.w r0, r0, ip, lsl #11 + 2581c: 9717 str r7, [sp, #92] ; 0x5c + 2581e: ea4f 516c mov.w r1, ip, asr #21 + 25822: 9f30 ldr r7, [sp, #192] ; 0xc0 + 25824: f8dd c02c ldr.w ip, [sp, #44] ; 0x2c + 25828: ea4f 5e4e mov.w lr, lr, lsl #21 + 2582c: f8cd e034 str.w lr, [sp, #52] ; 0x34 + 25830: 9c03 ldr r4, [sp, #12] + 25832: ea4f 5e4b mov.w lr, fp, lsl #21 + 25836: ea4f 5c4c mov.w ip, ip, lsl #21 + 2583a: 0d7f lsrs r7, r7, #21 + 2583c: f8cd c06c str.w ip, [sp, #108] ; 0x6c + 25840: f8cd e07c str.w lr, [sp, #124] ; 0x7c + 25844: 970e str r7, [sp, #56] ; 0x38 + 25846: f8dd c024 ldr.w ip, [sp, #36] ; 0x24 + 2584a: f8dd e034 ldr.w lr, [sp, #52] ; 0x34 + 2584e: 9f04 ldr r7, [sp, #16] + 25850: 0564 lsls r4, r4, #21 + 25852: 9415 str r4, [sp, #84] ; 0x54 + 25854: 9d01 ldr r5, [sp, #4] + 25856: ea4c 2cd6 orr.w ip, ip, r6, lsr #11 + 2585a: ea4e 2ed7 orr.w lr, lr, r7, lsr #11 + 2585e: f8cd c024 str.w ip, [sp, #36] ; 0x24 + 25862: f8cd e034 str.w lr, [sp, #52] ; 0x34 + 25866: f8dd c054 ldr.w ip, [sp, #84] ; 0x54 + 2586a: f8dd e008 ldr.w lr, [sp, #8] + 2586e: 056d lsls r5, r5, #21 + 25870: 9511 str r5, [sp, #68] ; 0x44 + 25872: ea4c 2cde orr.w ip, ip, lr, lsr #11 + 25876: 9f11 ldr r7, [sp, #68] ; 0x44 + 25878: f8cd c054 str.w ip, [sp, #84] ; 0x54 + 2587c: f8dd c000 ldr.w ip, [sp] + 25880: f8dd e05c ldr.w lr, [sp, #92] ; 0x5c + 25884: ea47 27dc orr.w r7, r7, ip, lsr #11 + 25888: 9711 str r7, [sp, #68] ; 0x44 + 2588a: 9f06 ldr r7, [sp, #24] + 2588c: f8dd c06c ldr.w ip, [sp, #108] ; 0x6c + 25890: ea4e 2ed7 orr.w lr, lr, r7, lsr #11 + 25894: 9f1f ldr r7, [sp, #124] ; 0x7c + 25896: f8cd e05c str.w lr, [sp, #92] ; 0x5c + 2589a: f8dd e028 ldr.w lr, [sp, #40] ; 0x28 + 2589e: ea47 27da orr.w r7, r7, sl, lsr #11 + 258a2: ea4c 2cde orr.w ip, ip, lr, lsr #11 + 258a6: 971f str r7, [sp, #124] ; 0x7c + 258a8: f8dd e038 ldr.w lr, [sp, #56] ; 0x38 + 258ac: 9f31 ldr r7, [sp, #196] ; 0xc4 + 258ae: ea4f 5449 mov.w r4, r9, lsl #21 + 258b2: f8cd c06c str.w ip, [sp, #108] ; 0x6c + 258b6: ea4e 2ec7 orr.w lr, lr, r7, lsl #11 + 258ba: ea44 2cd8 orr.w ip, r4, r8, lsr #11 + 258be: f8cd c084 str.w ip, [sp, #132] ; 0x84 + 258c2: f8cd e038 str.w lr, [sp, #56] ; 0x38 + 258c6: 9f06 ldr r7, [sp, #24] + 258c8: 0576 lsls r6, r6, #21 + 258ca: 9608 str r6, [sp, #32] + 258cc: 057f lsls r7, r7, #21 + 258ce: 9e00 ldr r6, [sp, #0] + 258d0: 9716 str r7, [sp, #88] ; 0x58 + 258d2: f8dd c010 ldr.w ip, [sp, #16] + 258d6: 9f31 ldr r7, [sp, #196] ; 0xc4 + 258d8: f8dd e008 ldr.w lr, [sp, #8] + 258dc: 0576 lsls r6, r6, #21 + 258de: 9610 str r6, [sp, #64] ; 0x40 + 258e0: ea4f 5c4c mov.w ip, ip, lsl #21 + 258e4: ea4f 5648 mov.w r6, r8, lsl #21 + 258e8: 157f asrs r7, r7, #21 + 258ea: e9dd 8908 ldrd r8, r9, [sp, #32] + 258ee: f8cd c030 str.w ip, [sp, #48] ; 0x30 + 258f2: 9620 str r6, [sp, #128] ; 0x80 + 258f4: 970f str r7, [sp, #60] ; 0x3c + 258f6: ea4f 5e4e mov.w lr, lr, lsl #21 + 258fa: e9dd 6734 ldrd r6, r7, [sp, #208] ; 0xd0 + 258fe: ebb6 0608 subs.w r6, r6, r8 + 25902: f8cd e050 str.w lr, [sp, #80] ; 0x50 + 25906: eb67 0709 sbc.w r7, r7, r9 + 2590a: ea4f 5e4a mov.w lr, sl, lsl #21 + 2590e: e9dd 890c ldrd r8, r9, [sp, #48] ; 0x30 + 25912: e9dd ab22 ldrd sl, fp, [sp, #136] ; 0x88 + 25916: ebba 0a08 subs.w sl, sl, r8 + 2591a: eb6b 0b09 sbc.w fp, fp, r9 + 2591e: e9cd ab06 strd sl, fp, [sp, #24] + 25922: e9dd 8914 ldrd r8, r9, [sp, #80] ; 0x50 + 25926: e9dd ab18 ldrd sl, fp, [sp, #96] ; 0x60 + 2592a: ebba 0a08 subs.w sl, sl, r8 + 2592e: eb6b 0b09 sbc.w fp, fp, r9 + 25932: f8dd c028 ldr.w ip, [sp, #40] ; 0x28 + 25936: e9dd 8910 ldrd r8, r9, [sp, #64] ; 0x40 + 2593a: e9cd ab08 strd sl, fp, [sp, #32] + 2593e: e9dd ab1c ldrd sl, fp, [sp, #112] ; 0x70 + 25942: ebba 0a08 subs.w sl, sl, r8 + 25946: eb6b 0b09 sbc.w fp, fp, r9 + 2594a: e9cd ab0a strd sl, fp, [sp, #40] ; 0x28 + 2594e: e9dd 8916 ldrd r8, r9, [sp, #88] ; 0x58 + 25952: e9dd ab26 ldrd sl, fp, [sp, #152] ; 0x98 + 25956: ea4f 5c4c mov.w ip, ip, lsl #21 + 2595a: ebba 0a08 subs.w sl, sl, r8 + 2595e: f8cd c068 str.w ip, [sp, #104] ; 0x68 + 25962: eb6b 0b09 sbc.w fp, fp, r9 + 25966: e9cd ab0c strd sl, fp, [sp, #48] ; 0x30 + 2596a: e9dd 891a ldrd r8, r9, [sp, #104] ; 0x68 + 2596e: e9dd ab28 ldrd sl, fp, [sp, #160] ; 0xa0 + 25972: ebba 0a08 subs.w sl, sl, r8 + 25976: f8cd e078 str.w lr, [sp, #120] ; 0x78 + 2597a: eb6b 0b09 sbc.w fp, fp, r9 + 2597e: e9cd ab18 strd sl, fp, [sp, #96] ; 0x60 + 25982: e9dd 891e ldrd r8, r9, [sp, #120] ; 0x78 + 25986: e9dd ab24 ldrd sl, fp, [sp, #144] ; 0x90 + 2598a: ebba 0a08 subs.w sl, sl, r8 + 2598e: eb6b 0b09 sbc.w fp, fp, r9 + 25992: e9cd ab26 strd sl, fp, [sp, #152] ; 0x98 + 25996: e9dd 8938 ldrd r8, r9, [sp, #224] ; 0xe0 + 2599a: e9dd ab2e ldrd sl, fp, [sp, #184] ; 0xb8 + 2599e: eb18 0800 adds.w r8, r8, r0 + 259a2: ea4f 5541 mov.w r5, r1, lsl #21 + 259a6: ea4f 5440 mov.w r4, r0, lsl #21 + 259aa: eb49 0901 adc.w r9, r9, r1 + 259ae: ea45 25d0 orr.w r5, r5, r0, lsr #11 + 259b2: ebba 0404 subs.w r4, sl, r4 + 259b6: e9dd 0120 ldrd r0, r1, [sp, #128] ; 0x80 + 259ba: eb6b 0505 sbc.w r5, fp, r5 + 259be: e9dd ab2a ldrd sl, fp, [sp, #168] ; 0xa8 + 259c2: ebba 0a00 subs.w sl, sl, r0 + 259c6: eb6b 0b01 sbc.w fp, fp, r1 + 259ca: e9cd ab28 strd sl, fp, [sp, #160] ; 0xa0 + 259ce: e9dd ab0e ldrd sl, fp, [sp, #56] ; 0x38 + 259d2: eb1a 0a02 adds.w sl, sl, r2 + 259d6: eb4b 0b03 adc.w fp, fp, r3 + 259da: e9cd ab10 strd sl, fp, [sp, #64] ; 0x40 + 259de: f8dd c044 ldr.w ip, [sp, #68] ; 0x44 + 259e2: f8dd e044 ldr.w lr, [sp, #68] ; 0x44 + 259e6: ea4f 5b5a mov.w fp, sl, lsr #21 + 259ea: ea4b 2ccc orr.w ip, fp, ip, lsl #11 + 259ee: ea4f 5e6e mov.w lr, lr, asr #21 + 259f2: f8cd c010 str.w ip, [sp, #16] + 259f6: f8cd e014 str.w lr, [sp, #20] + 259fa: f642 4213 movw r2, #11283 ; 0x2c13 + 259fe: e9dd 0104 ldrd r0, r1, [sp, #16] + 25a02: 1900 adds r0, r0, r4 + 25a04: 4169 adcs r1, r5 + 25a06: 0d43 lsrs r3, r0, #21 + 25a08: ea43 24c1 orr.w r4, r3, r1, lsl #11 + 25a0c: f642 5318 movw r3, #11544 ; 0x2d18 + 25a10: e9cd 0114 strd r0, r1, [sp, #80] ; 0x50 + 25a14: f64f 3067 movw r0, #64359 ; 0xfb67 + 25a18: f2c0 020a movt r2, #10 + 25a1c: f2c0 0307 movt r3, #7 + 25a20: f2c0 0009 movt r0, #9 + 25a24: 9d15 ldr r5, [sp, #84] ; 0x54 + 25a26: 9400 str r4, [sp, #0] + 25a28: 156d asrs r5, r5, #21 + 25a2a: 9501 str r5, [sp, #4] + 25a2c: e9dd ab00 ldrd sl, fp, [sp] + 25a30: eb1a 0a08 adds.w sl, sl, r8 + 25a34: eb4b 0b09 adc.w fp, fp, r9 + 25a38: e9cd ab16 strd sl, fp, [sp, #88] ; 0x58 + 25a3c: 9d17 ldr r5, [sp, #92] ; 0x5c + 25a3e: ea4f 515a mov.w r1, sl, lsr #21 + 25a42: ea41 24cb orr.w r4, r1, fp, lsl #11 + 25a46: 156d asrs r5, r5, #21 + 25a48: 9402 str r4, [sp, #8] + 25a4a: 9503 str r5, [sp, #12] + 25a4c: e9dd 8902 ldrd r8, r9, [sp, #8] + 25a50: eb18 0806 adds.w r8, r8, r6 + 25a54: eb49 0907 adc.w r9, r9, r7 + 25a58: ea4f 5158 mov.w r1, r8, lsr #21 + 25a5c: ea41 21c9 orr.w r1, r1, r9, lsl #11 + 25a60: fba1 ab02 umull sl, fp, r1, r2 + 25a64: e9cd 891a strd r8, r9, [sp, #104] ; 0x68 + 25a68: f8dd 906c ldr.w r9, [sp, #108] ; 0x6c + 25a6c: fba1 6703 umull r6, r7, r1, r3 + 25a70: ea4f 5e69 mov.w lr, r9, asr #21 + 25a74: fb02 bb0e mla fp, r2, lr, fp + 25a78: e9dd 890a ldrd r8, r9, [sp, #40] ; 0x28 + 25a7c: fb03 770e mla r7, r3, lr, r7 + 25a80: e9dd 2306 ldrd r2, r3, [sp, #24] + 25a84: eb12 020a adds.w r2, r2, sl + 25a88: eb43 030b adc.w r3, r3, fp + 25a8c: e9cd 231e strd r2, r3, [sp, #120] ; 0x78 + 25a90: fba1 2300 umull r2, r3, r1, r0 + 25a94: eb16 0608 adds.w r6, r6, r8 + 25a98: f24c 6853 movw r8, #50771 ; 0xc653 + 25a9c: fb00 330e mla r3, r0, lr, r3 + 25aa0: f241 50d1 movw r0, #5585 ; 0x15d1 + 25aa4: eb47 0709 adc.w r7, r7, r9 + 25aa8: f8dd 9078 ldr.w r9, [sp, #120] ; 0x78 + 25aac: f8dd a07c ldr.w sl, [sp, #124] ; 0x7c + 25ab0: f8dd b07c ldr.w fp, [sp, #124] ; 0x7c + 25ab4: ea4f 5959 mov.w r9, r9, lsr #21 + 25ab8: ea49 2aca orr.w sl, r9, sl, lsl #11 + 25abc: ea4f 5b6b mov.w fp, fp, asr #21 + 25ac0: f8cd a018 str.w sl, [sp, #24] + 25ac4: f8cd b01c str.w fp, [sp, #28] + 25ac8: e9dd 4506 ldrd r4, r5, [sp, #24] + 25acc: 19a4 adds r4, r4, r6 + 25ace: 417d adcs r5, r7 + 25ad0: e9cd 4520 strd r4, r5, [sp, #128] ; 0x80 + 25ad4: e9dd ab08 ldrd sl, fp, [sp, #32] + 25ad8: f8dd c084 ldr.w ip, [sp, #132] ; 0x84 + 25adc: eb12 020a adds.w r2, r2, sl + 25ae0: 9e21 ldr r6, [sp, #132] ; 0x84 + 25ae2: eb43 030b adc.w r3, r3, fp + 25ae6: ea4f 5b54 mov.w fp, r4, lsr #21 + 25aea: ea4b 2ccc orr.w ip, fp, ip, lsl #11 + 25aee: 1576 asrs r6, r6, #21 + 25af0: f8cd c028 str.w ip, [sp, #40] ; 0x28 + 25af4: 960b str r6, [sp, #44] ; 0x2c + 25af6: e9dd ab0a ldrd sl, fp, [sp, #40] ; 0x28 + 25afa: eb1a 0a02 adds.w sl, sl, r2 + 25afe: eb4b 0b03 adc.w fp, fp, r3 + 25b02: f249 0383 movw r3, #36995 ; 0x9083 + 25b06: e9dd 670c ldrd r6, r7, [sp, #48] ; 0x30 + 25b0a: f6cf 78f0 movt r8, #65520 ; 0xfff0 + 25b0e: f2c0 0002 movt r0, #2 + 25b12: f6cf 73f5 movt r3, #65525 ; 0xfff5 + 25b16: 424d negs r5, r1 + 25b18: fb08 540e mla r4, r8, lr, r5 + 25b1c: fba1 8908 umull r8, r9, r1, r8 + 25b20: e9cd ab22 strd sl, fp, [sp, #136] ; 0x88 + 25b24: fba1 ab00 umull sl, fp, r1, r0 + 25b28: eb18 0806 adds.w r8, r8, r6 + 25b2c: 44a1 add r9, r4 + 25b2e: eb49 0907 adc.w r9, r9, r7 + 25b32: 9f22 ldr r7, [sp, #136] ; 0x88 + 25b34: f8dd c08c ldr.w ip, [sp, #140] ; 0x8c + 25b38: fb00 bb0e mla fp, r0, lr, fp + 25b3c: 9823 ldr r0, [sp, #140] ; 0x8c + 25b3e: 0d7f lsrs r7, r7, #21 + 25b40: ea47 2ccc orr.w ip, r7, ip, lsl #11 + 25b44: 1540 asrs r0, r0, #21 + 25b46: f8cd c020 str.w ip, [sp, #32] + 25b4a: 9009 str r0, [sp, #36] ; 0x24 + 25b4c: e9dd 6708 ldrd r6, r7, [sp, #32] + 25b50: eb16 0608 adds.w r6, r6, r8 + 25b54: eb47 0709 adc.w r7, r7, r9 + 25b58: e9cd 671c strd r6, r7, [sp, #112] ; 0x70 + 25b5c: e9dd 6718 ldrd r6, r7, [sp, #96] ; 0x60 + 25b60: eb1a 0a06 adds.w sl, sl, r6 + 25b64: eb4b 0b07 adc.w fp, fp, r7 + 25b68: 9f1c ldr r7, [sp, #112] ; 0x70 + 25b6a: f04f 0800 mov.w r8, #0 + 25b6e: f04f 0900 mov.w r9, #0 + 25b72: 0d7f lsrs r7, r7, #21 + 25b74: e9cd 890c strd r8, r9, [sp, #48] ; 0x30 + 25b78: 970c str r7, [sp, #48] ; 0x30 + 25b7a: f8dd 9074 ldr.w r9, [sp, #116] ; 0x74 + 25b7e: f8dd 8030 ldr.w r8, [sp, #48] ; 0x30 + 25b82: fba1 6703 umull r6, r7, r1, r3 + 25b86: fb03 530e mla r3, r3, lr, r5 + 25b8a: ea4f 5c69 mov.w ip, r9, asr #21 + 25b8e: ea48 28c9 orr.w r8, r8, r9, lsl #11 + 25b92: f8cd 8030 str.w r8, [sp, #48] ; 0x30 + 25b96: f8cd c034 str.w ip, [sp, #52] ; 0x34 + 25b9a: e9dd 450c ldrd r4, r5, [sp, #48] ; 0x30 + 25b9e: eb14 040a adds.w r4, r4, sl + 25ba2: e9dd 8926 ldrd r8, r9, [sp, #152] ; 0x98 + 25ba6: eb45 050b adc.w r5, r5, fp + 25baa: 441f add r7, r3 + 25bac: eb18 0806 adds.w r8, r8, r6 + 25bb0: eb49 0907 adc.w r9, r9, r7 + 25bb4: f8dd a038 ldr.w sl, [sp, #56] ; 0x38 + 25bb8: e9cd 892a strd r8, r9, [sp, #168] ; 0xa8 + 25bbc: e9dd 2330 ldrd r2, r3, [sp, #192] ; 0xc0 + 25bc0: e9dd 6710 ldrd r6, r7, [sp, #64] ; 0x40 + 25bc4: f8dd 903c ldr.w r9, [sp, #60] ; 0x3c + 25bc8: e9cd 4518 strd r4, r5, [sp, #96] ; 0x60 + 25bcc: ea4f 544a mov.w r4, sl, lsl #21 + 25bd0: ea4f 5549 mov.w r5, r9, lsl #21 + 25bd4: 1b12 subs r2, r2, r4 + 25bd6: ea45 25da orr.w r5, r5, sl, lsr #11 + 25bda: eb63 0305 sbc.w r3, r3, r5 + 25bde: 9c04 ldr r4, [sp, #16] + 25be0: e9cd 2326 strd r2, r3, [sp, #152] ; 0x98 + 25be4: 9b05 ldr r3, [sp, #20] + 25be6: ea4f 5844 mov.w r8, r4, lsl #21 + 25bea: ea4f 5943 mov.w r9, r3, lsl #21 + 25bee: ebb6 0608 subs.w r6, r6, r8 + 25bf2: ea49 29d4 orr.w r9, r9, r4, lsr #11 + 25bf6: eb67 0709 sbc.w r7, r7, r9 + 25bfa: e9cd 6710 strd r6, r7, [sp, #64] ; 0x40 + 25bfe: e9dd ab14 ldrd sl, fp, [sp, #80] ; 0x50 + 25c02: e9dd 4516 ldrd r4, r5, [sp, #88] ; 0x58 + 25c06: f8dd 8000 ldr.w r8, [sp] + 25c0a: 9f01 ldr r7, [sp, #4] + 25c0c: ea4f 5248 mov.w r2, r8, lsl #21 + 25c10: 057b lsls r3, r7, #21 + 25c12: ebba 0a02 subs.w sl, sl, r2 + 25c16: ea43 23d8 orr.w r3, r3, r8, lsr #11 + 25c1a: eb6b 0b03 sbc.w fp, fp, r3 + 25c1e: e9cd ab14 strd sl, fp, [sp, #80] ; 0x50 + 25c22: 9b02 ldr r3, [sp, #8] + 25c24: f8dd b00c ldr.w fp, [sp, #12] + 25c28: ea4f 5843 mov.w r8, r3, lsl #21 + 25c2c: ea4f 594b mov.w r9, fp, lsl #21 + 25c30: ebb4 0408 subs.w r4, r4, r8 + 25c34: ea49 29d3 orr.w r9, r9, r3, lsr #11 + 25c38: eb65 0509 sbc.w r5, r5, r9 + 25c3c: e9cd 4524 strd r4, r5, [sp, #144] ; 0x90 + 25c40: 9d07 ldr r5, [sp, #28] + 25c42: f8dd 802c ldr.w r8, [sp, #44] ; 0x2c + 25c46: f8dd 9030 ldr.w r9, [sp, #48] ; 0x30 + 25c4a: ea4f 5b45 mov.w fp, r5, lsl #21 + 25c4e: ea4f 554e mov.w r5, lr, lsl #21 + 25c52: f8dd e018 ldr.w lr, [sp, #24] + 25c56: ea45 25d1 orr.w r5, r5, r1, lsr #11 + 25c5a: 054c lsls r4, r1, #21 + 25c5c: ea4f 5748 mov.w r7, r8, lsl #21 + 25c60: 990c ldr r1, [sp, #48] ; 0x30 + 25c62: f8dd 8020 ldr.w r8, [sp, #32] + 25c66: ea4f 5c4c mov.w ip, ip, lsl #21 + 25c6a: ea4c 29d9 orr.w r9, ip, r9, lsr #11 + 25c6e: 0543 lsls r3, r0, #21 + 25c70: ea4f 5a4e mov.w sl, lr, lsl #21 + 25c74: 980a ldr r0, [sp, #40] ; 0x28 + 25c76: f8cd 9014 str.w r9, [sp, #20] + 25c7a: ea4b 2bde orr.w fp, fp, lr, lsr #11 + 25c7e: ea43 23d8 orr.w r3, r3, r8, lsr #11 + 25c82: ea4f 5248 mov.w r2, r8, lsl #21 + 25c86: 0549 lsls r1, r1, #21 + 25c88: e9dd 891e ldrd r8, r9, [sp, #120] ; 0x78 + 25c8c: ebb8 0a0a subs.w sl, r8, sl + 25c90: 9104 str r1, [sp, #16] + 25c92: eb69 0b0b sbc.w fp, r9, fp + 25c96: ea47 27d0 orr.w r7, r7, r0, lsr #11 + 25c9a: 0546 lsls r6, r0, #21 + 25c9c: e9dd 011a ldrd r0, r1, [sp, #104] ; 0x68 + 25ca0: 1b00 subs r0, r0, r4 + 25ca2: eb61 0105 sbc.w r1, r1, r5 + 25ca6: e9dd 4520 ldrd r4, r5, [sp, #128] ; 0x80 + 25caa: 1ba6 subs r6, r4, r6 + 25cac: e9dd 8922 ldrd r8, r9, [sp, #136] ; 0x88 + 25cb0: eb65 0707 sbc.w r7, r5, r7 + 25cb4: ebb8 0202 subs.w r2, r8, r2 + 25cb8: e9dd 4504 ldrd r4, r5, [sp, #16] + 25cbc: eb69 0303 sbc.w r3, r9, r3 + 25cc0: e9cd 011a strd r0, r1, [sp, #104] ; 0x68 + 25cc4: e9dd 011c ldrd r0, r1, [sp, #112] ; 0x70 + 25cc8: 1b00 subs r0, r0, r4 + 25cca: eb61 0105 sbc.w r1, r1, r5 + 25cce: e9cd 0104 strd r0, r1, [sp, #16] + 25cd2: 0cf0 lsrs r0, r6, #19 + 25cd4: ea40 3047 orr.w r0, r0, r7, lsl #13 + 25cd8: 9d04 ldr r5, [sp, #16] + 25cda: ea40 0082 orr.w r0, r0, r2, lsl #2 + 25cde: f8dd 8014 ldr.w r8, [sp, #20] + 25ce2: 9020 str r0, [sp, #128] ; 0x80 + 25ce4: ea4f 441a mov.w r4, sl, lsr #16 + 25ce8: 9804 ldr r0, [sp, #16] + 25cea: 0b91 lsrs r1, r2, #14 + 25cec: ea44 440b orr.w r4, r4, fp, lsl #16 + 25cf0: ea41 4183 orr.w r1, r1, r3, lsl #18 + 25cf4: 0c6d lsrs r5, r5, #17 + 25cf6: ea45 35c8 orr.w r5, r5, r8, lsl #15 + 25cfa: ea44 1446 orr.w r4, r4, r6, lsl #5 + 25cfe: ea4f 09d6 mov.w r9, r6, lsr #3 + 25d02: ea4f 2cd6 mov.w ip, r6, lsr #11 + 25d06: ea4f 1e92 mov.w lr, r2, lsr #6 + 25d0a: ea41 11c0 orr.w r1, r1, r0, lsl #7 + 25d0e: 9516 str r5, [sp, #88] ; 0x58 + 25d10: 941e str r4, [sp, #120] ; 0x78 + 25d12: f8cd 9070 str.w r9, [sp, #112] ; 0x70 + 25d16: f8cd c0c0 str.w ip, [sp, #192] ; 0xc0 + 25d1a: f8cd e0c8 str.w lr, [sp, #200] ; 0xc8 + 25d1e: 9122 str r1, [sp, #136] ; 0x88 + 25d20: 9a12 ldr r2, [sp, #72] ; 0x48 + 25d22: ea4f 231a mov.w r3, sl, lsr #8 + 25d26: 7053 strb r3, [r2, #1] + 25d28: 9b18 ldr r3, [sp, #96] ; 0x60 + 25d2a: 9c19 ldr r4, [sp, #100] ; 0x64 + 25d2c: ea4f 5853 mov.w r8, r3, lsr #21 + 25d30: ea48 28c4 orr.w r8, r8, r4, lsl #11 + 25d34: ea4f 5964 mov.w r9, r4, asr #21 + 25d38: e9dd 672a ldrd r6, r7, [sp, #168] ; 0xa8 + 25d3c: eb16 0608 adds.w r6, r6, r8 + 25d40: eb47 0709 adc.w r7, r7, r9 + 25d44: e9cd 670e strd r6, r7, [sp, #56] ; 0x38 + 25d48: e9dd 4526 ldrd r4, r5, [sp, #152] ; 0x98 + 25d4c: f882 a000 strb.w sl, [r2] + 25d50: f8dd a038 ldr.w sl, [sp, #56] ; 0x38 + 25d54: f8dd b03c ldr.w fp, [sp, #60] ; 0x3c + 25d58: ea4f 565a mov.w r6, sl, lsr #21 + 25d5c: ea46 26cb orr.w r6, r6, fp, lsl #11 + 25d60: 0a41 lsrs r1, r0, #9 + 25d62: ea4f 576b mov.w r7, fp, asr #21 + 25d66: 912e str r1, [sp, #184] ; 0xb8 + 25d68: e9dd 0128 ldrd r0, r1, [sp, #160] ; 0xa0 + 25d6c: 1980 adds r0, r0, r6 + 25d6e: 4179 adcs r1, r7 + 25d70: e9cd 0108 strd r0, r1, [sp, #32] + 25d74: e9dd ab10 ldrd sl, fp, [sp, #64] ; 0x40 + 25d78: 9a08 ldr r2, [sp, #32] + 25d7a: 9b09 ldr r3, [sp, #36] ; 0x24 + 25d7c: 0d50 lsrs r0, r2, #21 + 25d7e: ea40 20c3 orr.w r0, r0, r3, lsl #11 + 25d82: 1824 adds r4, r4, r0 + 25d84: ea4f 5163 mov.w r1, r3, asr #21 + 25d88: 414d adcs r5, r1 + 25d8a: e9cd 450c strd r4, r5, [sp, #48] ; 0x30 + 25d8e: 0d62 lsrs r2, r4, #21 + 25d90: ea42 22c5 orr.w r2, r2, r5, lsl #11 + 25d94: 9d0d ldr r5, [sp, #52] ; 0x34 + 25d96: eb1a 0a02 adds.w sl, sl, r2 + 25d9a: ea4f 5365 mov.w r3, r5, asr #21 + 25d9e: eb4b 0b03 adc.w fp, fp, r3 + 25da2: e9cd ab10 strd sl, fp, [sp, #64] ; 0x40 + 25da6: ea4f 545a mov.w r4, sl, lsr #21 + 25daa: ea44 24cb orr.w r4, r4, fp, lsl #11 + 25dae: f8dd b044 ldr.w fp, [sp, #68] ; 0x44 + 25db2: f04f 0a00 mov.w sl, #0 + 25db6: ea4f 556b mov.w r5, fp, asr #21 + 25dba: f04f 0b00 mov.w fp, #0 + 25dbe: e9cd ab00 strd sl, fp, [sp] + 25dc2: e9cd ab02 strd sl, fp, [sp, #8] + 25dc6: e9cd ab06 strd sl, fp, [sp, #24] + 25dca: e9dd ab14 ldrd sl, fp, [sp, #80] ; 0x50 + 25dce: eb1a 0a04 adds.w sl, sl, r4 + 25dd2: eb4b 0b05 adc.w fp, fp, r5 + 25dd6: e9cd ab14 strd sl, fp, [sp, #80] ; 0x50 + 25dda: f04f 0a00 mov.w sl, #0 + 25dde: f04f 0b00 mov.w fp, #0 + 25de2: e9cd ab0a strd sl, fp, [sp, #40] ; 0x28 + 25de6: ea4f 5c47 mov.w ip, r7, lsl #21 + 25dea: ea4f 5b49 mov.w fp, r9, lsl #21 + 25dee: f8cd b004 str.w fp, [sp, #4] + 25df2: f8cd c00c str.w ip, [sp, #12] + 25df6: ea4f 5e41 mov.w lr, r1, lsl #21 + 25dfa: ea4f 5c45 mov.w ip, r5, lsl #21 + 25dfe: f8cd e01c str.w lr, [sp, #28] + 25e02: f8cd c02c str.w ip, [sp, #44] ; 0x2c + 25e06: f8dd e004 ldr.w lr, [sp, #4] + 25e0a: f8dd c00c ldr.w ip, [sp, #12] + 25e0e: ea4e 2ed8 orr.w lr, lr, r8, lsr #11 + 25e12: ea4c 2cd6 orr.w ip, ip, r6, lsr #11 + 25e16: f8cd e004 str.w lr, [sp, #4] + 25e1a: f8cd c00c str.w ip, [sp, #12] + 25e1e: f8dd e01c ldr.w lr, [sp, #28] + 25e22: f8dd c02c ldr.w ip, [sp, #44] ; 0x2c + 25e26: ea4e 2ed0 orr.w lr, lr, r0, lsr #11 + 25e2a: f8cd e01c str.w lr, [sp, #28] + 25e2e: ea4f 5e48 mov.w lr, r8, lsl #21 + 25e32: f8cd e000 str.w lr, [sp] + 25e36: ea4f 5846 mov.w r8, r6, lsl #21 + 25e3a: f8cd 8008 str.w r8, [sp, #8] + 25e3e: ea4c 2cd4 orr.w ip, ip, r4, lsr #11 + 25e42: ea4f 5940 mov.w r9, r0, lsl #21 + 25e46: ea4f 5a42 mov.w sl, r2, lsl #21 + 25e4a: e9dd 0118 ldrd r0, r1, [sp, #96] ; 0x60 + 25e4e: e9dd 2300 ldrd r2, r3, [sp] + 25e52: 1a80 subs r0, r0, r2 + 25e54: e9dd 670e ldrd r6, r7, [sp, #56] ; 0x38 + 25e58: f8cd c02c str.w ip, [sp, #44] ; 0x2c + 25e5c: f8cd 9018 str.w r9, [sp, #24] + 25e60: eb61 0103 sbc.w r1, r1, r3 + 25e64: ea4f 5c44 mov.w ip, r4, lsl #21 + 25e68: e9dd 4502 ldrd r4, r5, [sp, #8] + 25e6c: 1b36 subs r6, r6, r4 + 25e6e: e9dd 8906 ldrd r8, r9, [sp, #24] + 25e72: f8cd c028 str.w ip, [sp, #40] ; 0x28 + 25e76: e9dd 2308 ldrd r2, r3, [sp, #32] + 25e7a: eb67 0705 sbc.w r7, r7, r5 + 25e7e: ebb2 0208 subs.w r2, r2, r8 + 25e82: e9dd 450c ldrd r4, r5, [sp, #48] ; 0x30 + 25e86: eb63 0309 sbc.w r3, r3, r9 + 25e8a: ebb4 040a subs.w r4, r4, sl + 25e8e: e9dd 890a ldrd r8, r9, [sp, #40] ; 0x28 + 25e92: e9dd ab10 ldrd sl, fp, [sp, #64] ; 0x40 + 25e96: ebba 0a08 subs.w sl, sl, r8 + 25e9a: eb6b 0b09 sbc.w fp, fp, r9 + 25e9e: e9dd 8904 ldrd r8, r9, [sp, #16] + 25ea2: ea5f 0969 movs.w r9, r9, asr #1 + 25ea6: ea4f 0838 mov.w r8, r8, rrx + 25eaa: e9cd 8904 strd r8, r9, [sp, #16] + 25eae: f8dd 9058 ldr.w r9, [sp, #88] ; 0x58 + 25eb2: ea4f 5810 mov.w r8, r0, lsr #20 + 25eb6: ea49 1900 orr.w r9, r9, r0, lsl #4 + 25eba: f8cd 9000 str.w r9, [sp] + 25ebe: ea4f 1910 mov.w r9, r0, lsr #4 + 25ec2: f8cd 9038 str.w r9, [sp, #56] ; 0x38 + 25ec6: ea4f 3ed6 mov.w lr, r6, lsr #15 + 25eca: ea4f 3910 mov.w r9, r0, lsr #12 + 25ece: 0c95 lsrs r5, r2, #18 + 25ed0: 09f0 lsrs r0, r6, #7 + 25ed2: ea48 3801 orr.w r8, r8, r1, lsl #12 + 25ed6: 0891 lsrs r1, r2, #2 + 25ed8: ea48 0846 orr.w r8, r8, r6, lsl #1 + 25edc: 900c str r0, [sp, #48] ; 0x30 + 25ede: 9110 str r1, [sp, #64] ; 0x40 + 25ee0: 981e ldr r0, [sp, #120] ; 0x78 + 25ee2: 9912 ldr r1, [sp, #72] ; 0x48 + 25ee4: ea4e 4e47 orr.w lr, lr, r7, lsl #17 + 25ee8: ea45 3583 orr.w r5, r5, r3, lsl #14 + 25eec: f8cd 8008 str.w r8, [sp, #8] + 25ef0: ea4e 1e82 orr.w lr, lr, r2, lsl #6 + 25ef4: 0a96 lsrs r6, r2, #10 + 25ef6: ea45 05c4 orr.w r5, r5, r4, lsl #3 + 25efa: 0967 lsrs r7, r4, #5 + 25efc: ea4f 3854 mov.w r8, r4, lsr #13 + 25f00: f8cd 9020 str.w r9, [sp, #32] + 25f04: f8cd e018 str.w lr, [sp, #24] + 25f08: 9616 str r6, [sp, #88] ; 0x58 + 25f0a: 950a str r5, [sp, #40] ; 0x28 + 25f0c: 9718 str r7, [sp, #96] ; 0x60 + 25f0e: f8cd 8098 str.w r8, [sp, #152] ; 0x98 + 25f12: 7088 strb r0, [r1, #2] + 25f14: 9e14 ldr r6, [sp, #80] ; 0x50 + 25f16: 9f15 ldr r7, [sp, #84] ; 0x54 + 25f18: 9a1c ldr r2, [sp, #112] ; 0x70 + 25f1a: 9b30 ldr r3, [sp, #192] ; 0xc0 + 25f1c: 9c20 ldr r4, [sp, #128] ; 0x80 + 25f1e: 9d32 ldr r5, [sp, #200] ; 0xc8 + 25f20: 0d70 lsrs r0, r6, #21 + 25f22: 70ca strb r2, [r1, #3] + 25f24: 710b strb r3, [r1, #4] + 25f26: 714c strb r4, [r1, #5] + 25f28: 718d strb r5, [r1, #6] + 25f2a: ea40 20c7 orr.w r0, r0, r7, lsl #11 + 25f2e: 1579 asrs r1, r7, #21 + 25f30: e9dd 8924 ldrd r8, r9, [sp, #144] ; 0x90 + 25f34: ea4f 4c1a mov.w ip, sl, lsr #16 + 25f38: eb18 0800 adds.w r8, r8, r0 + 25f3c: ea4f 5341 mov.w r3, r1, lsl #21 + 25f40: ea4f 5240 mov.w r2, r0, lsl #21 + 25f44: eb49 0901 adc.w r9, r9, r1 + 25f48: ea4c 4c0b orr.w ip, ip, fp, lsl #16 + 25f4c: ea43 23d0 orr.w r3, r3, r0, lsr #11 + 25f50: e9dd 0114 ldrd r0, r1, [sp, #80] ; 0x50 + 25f54: 1a82 subs r2, r0, r2 + 25f56: eb61 0303 sbc.w r3, r1, r3 + 25f5a: ea4c 1c42 orr.w ip, ip, r2, lsl #5 + 25f5e: 9922 ldr r1, [sp, #136] ; 0x88 + 25f60: ea4f 0ed2 mov.w lr, r2, lsr #3 + 25f64: 0ad7 lsrs r7, r2, #11 + 25f66: 0cd6 lsrs r6, r2, #19 + 25f68: 9a12 ldr r2, [sp, #72] ; 0x48 + 25f6a: ea46 3643 orr.w r6, r6, r3, lsl #13 + 25f6e: 71d1 strb r1, [r2, #7] + 25f70: ea4f 5258 mov.w r2, r8, lsr #21 + 25f74: ea42 22c9 orr.w r2, r2, r9, lsl #11 + 25f78: ea4f 5369 mov.w r3, r9, asr #21 + 25f7c: e9dd 451a ldrd r4, r5, [sp, #104] ; 0x68 + 25f80: 0559 lsls r1, r3, #21 + 25f82: 18a4 adds r4, r4, r2 + 25f84: ea4f 5042 mov.w r0, r2, lsl #21 + 25f88: 415d adcs r5, r3 + 25f8a: ea41 21d2 orr.w r1, r1, r2, lsr #11 + 25f8e: ebb8 0000 subs.w r0, r8, r0 + 25f92: eb69 0101 sbc.w r1, r9, r1 + 25f96: 106b asrs r3, r5, #1 + 25f98: ea4f 0234 mov.w r2, r4, rrx + 25f9c: 9d12 ldr r5, [sp, #72] ; 0x48 + 25f9e: f8dd 8048 ldr.w r8, [sp, #72] ; 0x48 + 25fa2: f885 a015 strb.w sl, [r5, #21] + 25fa6: f89d 5010 ldrb.w r5, [sp, #16] + 25faa: 0b83 lsrs r3, r0, #14 + 25fac: f888 5008 strb.w r5, [r8, #8] + 25fb0: 9d2e ldr r5, [sp, #184] ; 0xb8 + 25fb2: ea43 4381 orr.w r3, r3, r1, lsl #18 + 25fb6: f888 5009 strb.w r5, [r8, #9] + 25fba: 9d00 ldr r5, [sp, #0] + 25fbc: ea46 0680 orr.w r6, r6, r0, lsl #2 + 25fc0: f888 500a strb.w r5, [r8, #10] + 25fc4: 9d0e ldr r5, [sp, #56] ; 0x38 + 25fc6: ea43 13c4 orr.w r3, r3, r4, lsl #7 + 25fca: f888 500b strb.w r5, [r8, #11] + 25fce: 9d08 ldr r5, [sp, #32] + 25fd0: 0a61 lsrs r1, r4, #9 + 25fd2: f888 500c strb.w r5, [r8, #12] + 25fd6: 9d02 ldr r5, [sp, #8] + 25fd8: ea4f 2b1a mov.w fp, sl, lsr #8 + 25fdc: f888 500d strb.w r5, [r8, #13] + 25fe0: 9d0c ldr r5, [sp, #48] ; 0x30 + 25fe2: 0980 lsrs r0, r0, #6 + 25fe4: f888 500e strb.w r5, [r8, #14] + 25fe8: 9d06 ldr r5, [sp, #24] + 25fea: 0c64 lsrs r4, r4, #17 + 25fec: f888 500f strb.w r5, [r8, #15] + 25ff0: 9d10 ldr r5, [sp, #64] ; 0x40 + 25ff2: f888 b016 strb.w fp, [r8, #22] + 25ff6: f888 5010 strb.w r5, [r8, #16] + 25ffa: 9d16 ldr r5, [sp, #88] ; 0x58 + 25ffc: f888 c017 strb.w ip, [r8, #23] + 26000: f888 5011 strb.w r5, [r8, #17] + 26004: 9d0a ldr r5, [sp, #40] ; 0x28 + 26006: f888 e018 strb.w lr, [r8, #24] + 2600a: f888 5012 strb.w r5, [r8, #18] + 2600e: 9d18 ldr r5, [sp, #96] ; 0x60 + 26010: f888 7019 strb.w r7, [r8, #25] + 26014: f888 5013 strb.w r5, [r8, #19] + 26018: 9d26 ldr r5, [sp, #152] ; 0x98 + 2601a: f888 601a strb.w r6, [r8, #26] + 2601e: f888 5014 strb.w r5, [r8, #20] + 26022: f888 001b strb.w r0, [r8, #27] + 26026: f888 301c strb.w r3, [r8, #28] + 2602a: f888 201d strb.w r2, [r8, #29] + 2602e: f888 101e strb.w r1, [r8, #30] + 26032: f888 401f strb.w r4, [r8, #31] + 26036: b067 add sp, #412 ; 0x19c + 26038: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +0002603c : + 2603c: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 26040: f890 203a ldrb.w r2, [r0, #58] ; 0x3a + 26044: b0cb sub sp, #300 ; 0x12c + 26046: 2300 movs r3, #0 + 26048: e9cd 230e strd r2, r3, [sp, #56] ; 0x38 + 2604c: 7f44 ldrb r4, [r0, #29] + 2604e: f890 6021 ldrb.w r6, [r0, #33] ; 0x21 + 26052: f890 a03b ldrb.w sl, [r0, #59] ; 0x3b + 26056: f8dd c038 ldr.w ip, [sp, #56] ; 0x38 + 2605a: f890 801e ldrb.w r8, [r0, #30] + 2605e: 2500 movs r5, #0 + 26060: 2700 movs r7, #0 + 26062: e9cd 4508 strd r4, r5, [sp, #32] + 26066: e9cd 671e strd r6, r7, [sp, #120] ; 0x78 + 2606a: f890 4020 ldrb.w r4, [r0, #32] + 2606e: 9f0e ldr r7, [sp, #56] ; 0x38 + 26070: f04f 0900 mov.w r9, #0 + 26074: e9cd 8906 strd r8, r9, [sp, #24] + 26078: ea4f 460a mov.w r6, sl, lsl #16 + 2607c: ea4f 280c mov.w r8, ip, lsl #8 + 26080: 2500 movs r5, #0 + 26082: e9cd 4516 strd r4, r5, [sp, #88] ; 0x58 + 26086: ea4f 6917 mov.w r9, r7, lsr #24 + 2608a: ea48 0406 orr.w r4, r8, r6 + 2608e: ea4f 471a mov.w r7, sl, lsr #16 + 26092: f890 6039 ldrb.w r6, [r0, #57] ; 0x39 + 26096: f890 8038 ldrb.w r8, [r0, #56] ; 0x38 + 2609a: ea49 0507 orr.w r5, r9, r7 + 2609e: 2700 movs r7, #0 + 260a0: f04f 0900 mov.w r9, #0 + 260a4: e9cd 670e strd r6, r7, [sp, #56] ; 0x38 + 260a8: e9cd 8926 strd r8, r9, [sp, #152] ; 0x98 + 260ac: 9f08 ldr r7, [sp, #32] + 260ae: f8dd 8018 ldr.w r8, [sp, #24] + 260b2: f8dd e020 ldr.w lr, [sp, #32] + 260b6: f890 203d ldrb.w r2, [r0, #61] ; 0x3d + 260ba: f890 a03e ldrb.w sl, [r0, #62] ; 0x3e + 260be: e9cd 452e strd r4, r5, [sp, #184] ; 0xb8 + 260c2: 7ec4 ldrb r4, [r0, #27] + 260c4: 2300 movs r3, #0 + 260c6: f04f 0b00 mov.w fp, #0 + 260ca: 2500 movs r5, #0 + 260cc: 0e3f lsrs r7, r7, #24 + 260ce: ea4f 4818 mov.w r8, r8, lsr #16 + 260d2: ea4f 2e0e mov.w lr, lr, lsl #8 + 260d6: f8dd 9058 ldr.w r9, [sp, #88] ; 0x58 + 260da: f8dd c078 ldr.w ip, [sp, #120] ; 0x78 + 260de: e9cd 2322 strd r2, r3, [sp, #136] ; 0x88 + 260e2: e9cd ab2a strd sl, fp, [sp, #168] ; 0xa8 + 260e6: e9cd 4514 strd r4, r5, [sp, #80] ; 0x50 + 260ea: f890 a01c ldrb.w sl, [r0, #28] + 260ee: 9713 str r7, [sp, #76] ; 0x4c + 260f0: f8cd 8044 str.w r8, [sp, #68] ; 0x44 + 260f4: f8cd e048 str.w lr, [sp, #72] ; 0x48 + 260f8: 9906 ldr r1, [sp, #24] + 260fa: ea4f 6519 mov.w r5, r9, lsr #24 + 260fe: 0409 lsls r1, r1, #16 + 26100: 9110 str r1, [sp, #64] ; 0x40 + 26102: ea4f 431c mov.w r3, ip, lsr #16 + 26106: ea4f 2409 mov.w r4, r9, lsl #8 + 2610a: ea4f 420c mov.w r2, ip, lsl #16 + 2610e: e9dd 6710 ldrd r6, r7, [sp, #64] ; 0x40 + 26112: e9dd 8912 ldrd r8, r9, [sp, #72] ; 0x48 + 26116: ea48 0806 orr.w r8, r8, r6 + 2611a: ea49 0907 orr.w r9, r9, r7 + 2611e: ea44 0602 orr.w r6, r4, r2 + 26122: ea45 0703 orr.w r7, r5, r3 + 26126: e9cd 8930 strd r8, r9, [sp, #192] ; 0xc0 + 2612a: e9dd 450e ldrd r4, r5, [sp, #56] ; 0x38 + 2612e: f890 801f ldrb.w r8, [r0, #31] + 26132: e9cd 6732 strd r6, r7, [sp, #200] ; 0xc8 + 26136: f890 2023 ldrb.w r2, [r0, #35] ; 0x23 + 2613a: f890 603c ldrb.w r6, [r0, #60] ; 0x3c + 2613e: f04f 0900 mov.w r9, #0 + 26142: 2300 movs r3, #0 + 26144: 2700 movs r7, #0 + 26146: e9cd 8912 strd r8, r9, [sp, #72] ; 0x48 + 2614a: e9cd 2324 strd r2, r3, [sp, #144] ; 0x90 + 2614e: f890 8024 ldrb.w r8, [r0, #36] ; 0x24 + 26152: e9cd 6708 strd r6, r7, [sp, #32] + 26156: f890 2035 ldrb.w r2, [r0, #53] ; 0x35 + 2615a: f890 6036 ldrb.w r6, [r0, #54] ; 0x36 + 2615e: f04f 0900 mov.w r9, #0 + 26162: 2300 movs r3, #0 + 26164: 2700 movs r7, #0 + 26166: e9cd 8906 strd r8, r9, [sp, #24] + 2616a: e9cd 672c strd r6, r7, [sp, #176] ; 0xb0 + 2616e: e9cd 2320 strd r2, r3, [sp, #128] ; 0x80 + 26172: e9dd 232e ldrd r2, r3, [sp, #184] ; 0xb8 + 26176: 9f22 ldr r7, [sp, #136] ; 0x88 + 26178: f8dd 80a8 ldr.w r8, [sp, #168] ; 0xa8 + 2617c: 432b orrs r3, r5 + 2617e: 9e2a ldr r6, [sp, #168] ; 0xa8 + 26180: 9d22 ldr r5, [sp, #136] ; 0x88 + 26182: 0e3f lsrs r7, r7, #24 + 26184: ea4f 4818 mov.w r8, r8, lsr #16 + 26188: 022d lsls r5, r5, #8 + 2618a: 0436 lsls r6, r6, #16 + 2618c: 970b str r7, [sp, #44] ; 0x2c + 2618e: f8cd 8064 str.w r8, [sp, #100] ; 0x64 + 26192: 950a str r5, [sp, #40] ; 0x28 + 26194: 9618 str r6, [sp, #96] ; 0x60 + 26196: 4322 orrs r2, r4 + 26198: e9dd 890a ldrd r8, r9, [sp, #40] ; 0x28 + 2619c: e9cd 233e strd r2, r3, [sp, #248] ; 0xf8 + 261a0: e9dd 2318 ldrd r2, r3, [sp, #96] ; 0x60 + 261a4: 0c27 lsrs r7, r4, #16 + 261a6: ea49 0903 orr.w r9, r9, r3 + 261aa: 9c0e ldr r4, [sp, #56] ; 0x38 + 261ac: 9b26 ldr r3, [sp, #152] ; 0x98 + 261ae: ea48 0802 orr.w r8, r8, r2 + 261b2: e9cd 8938 strd r8, r9, [sp, #224] ; 0xe0 + 261b6: 0426 lsls r6, r4, #16 + 261b8: ea4f 2803 mov.w r8, r3, lsl #8 + 261bc: ea4f 6913 mov.w r9, r3, lsr #24 + 261c0: ea48 0206 orr.w r2, r8, r6 + 261c4: ea49 0307 orr.w r3, r9, r7 + 261c8: ac40 add r4, sp, #256 ; 0x100 + 261ca: e9c4 2300 strd r2, r3, [r4] + 261ce: f890 4022 ldrb.w r4, [r0, #34] ; 0x22 + 261d2: 2500 movs r5, #0 + 261d4: f890 6037 ldrb.w r6, [r0, #55] ; 0x37 + 261d8: f8dd 8050 ldr.w r8, [sp, #80] ; 0x50 + 261dc: e9cd 4510 strd r4, r5, [sp, #64] ; 0x40 + 261e0: f890 2026 ldrb.w r2, [r0, #38] ; 0x26 + 261e4: 9c14 ldr r4, [sp, #80] ; 0x50 + 261e6: 2700 movs r7, #0 + 261e8: 2300 movs r3, #0 + 261ea: e9cd 670a strd r6, r7, [sp, #40] ; 0x28 + 261ee: e9cd 232a strd r2, r3, [sp, #168] ; 0xa8 + 261f2: f890 6025 ldrb.w r6, [r0, #37] ; 0x25 + 261f6: 7e82 ldrb r2, [r0, #26] + 261f8: ea4f 471a mov.w r7, sl, lsr #16 + 261fc: ea4f 430a mov.w r3, sl, lsl #16 + 26200: ea4f 6818 mov.w r8, r8, lsr #24 + 26204: 0224 lsls r4, r4, #8 + 26206: 971b str r7, [sp, #108] ; 0x6c + 26208: 931a str r3, [sp, #104] ; 0x68 + 2620a: 940c str r4, [sp, #48] ; 0x30 + 2620c: f8cd 8034 str.w r8, [sp, #52] ; 0x34 + 26210: 2700 movs r7, #0 + 26212: 2300 movs r3, #0 + 26214: e9dd 890c ldrd r8, r9, [sp, #48] ; 0x30 + 26218: e9cd 6726 strd r6, r7, [sp, #152] ; 0x98 + 2621c: e9dd 671a ldrd r6, r7, [sp, #104] ; 0x68 + 26220: e9dd 4530 ldrd r4, r5, [sp, #192] ; 0xc0 + 26224: ea48 0806 orr.w r8, r8, r6 + 26228: ea49 0907 orr.w r9, r9, r7 + 2622c: e9cd 2314 strd r2, r3, [sp, #80] ; 0x50 + 26230: e9dd 6732 ldrd r6, r7, [sp, #200] ; 0xc8 + 26234: e9dd 2312 ldrd r2, r3, [sp, #72] ; 0x48 + 26238: 4316 orrs r6, r2 + 2623a: 431f orrs r7, r3 + 2623c: e9cd 673a strd r6, r7, [sp, #232] ; 0xe8 + 26240: 9e24 ldr r6, [sp, #144] ; 0x90 + 26242: 9b06 ldr r3, [sp, #24] + 26244: f04f 0b00 mov.w fp, #0 + 26248: 0e36 lsrs r6, r6, #24 + 2624a: 9617 str r6, [sp, #92] ; 0x5c + 2624c: ea44 040a orr.w r4, r4, sl + 26250: ea45 050b orr.w r5, r5, fp + 26254: 9e24 ldr r6, [sp, #144] ; 0x90 + 26256: e9cd 4536 strd r4, r5, [sp, #216] ; 0xd8 + 2625a: 0c1d lsrs r5, r3, #16 + 2625c: 9b06 ldr r3, [sp, #24] + 2625e: 0236 lsls r6, r6, #8 + 26260: 7e42 ldrb r2, [r0, #25] + 26262: 041c lsls r4, r3, #16 + 26264: 9616 str r6, [sp, #88] ; 0x58 + 26266: e9dd 6716 ldrd r6, r7, [sp, #88] ; 0x58 + 2626a: 2300 movs r3, #0 + 2626c: 4326 orrs r6, r4 + 2626e: 432f orrs r7, r5 + 26270: f890 a018 ldrb.w sl, [r0, #24] + 26274: e9cd 231a strd r2, r3, [sp, #104] ; 0x68 + 26278: e9cd 673c strd r6, r7, [sp, #240] ; 0xf0 + 2627c: 9f08 ldr r7, [sp, #32] + 2627e: f890 4032 ldrb.w r4, [r0, #50] ; 0x32 + 26282: f890 603f ldrb.w r6, [r0, #63] ; 0x3f + 26286: 0a3f lsrs r7, r7, #8 + 26288: 971d str r7, [sp, #116] ; 0x74 + 2628a: 2500 movs r5, #0 + 2628c: 2700 movs r7, #0 + 2628e: e9cd 4530 strd r4, r5, [sp, #192] ; 0xc0 + 26292: e9cd 672e strd r6, r7, [sp, #184] ; 0xb8 + 26296: f8dd c080 ldr.w ip, [sp, #128] ; 0x80 + 2629a: 9d08 ldr r5, [sp, #32] + 2629c: 9f20 ldr r7, [sp, #128] ; 0x80 + 2629e: f8dd e0b0 ldr.w lr, [sp, #176] ; 0xb0 + 262a2: f890 6033 ldrb.w r6, [r0, #51] ; 0x33 + 262a6: ea4f 6c1c mov.w ip, ip, lsr #24 + 262aa: 062d lsls r5, r5, #24 + 262ac: 023f lsls r7, r7, #8 + 262ae: f8cd c0a4 str.w ip, [sp, #164] ; 0xa4 + 262b2: 9728 str r7, [sp, #160] ; 0xa0 + 262b4: 951c str r5, [sp, #112] ; 0x70 + 262b6: ea4f 431e mov.w r3, lr, lsr #16 + 262ba: ea4f 420e mov.w r2, lr, lsl #16 + 262be: 2700 movs r7, #0 + 262c0: e9dd 453e ldrd r4, r5, [sp, #248] ; 0xf8 + 262c4: e9cd 6732 strd r6, r7, [sp, #200] ; 0xc8 + 262c8: e9dd 671c ldrd r6, r7, [sp, #112] ; 0x70 + 262cc: 4334 orrs r4, r6 + 262ce: 433d orrs r5, r7 + 262d0: e9dd 6728 ldrd r6, r7, [sp, #160] ; 0xa0 + 262d4: 4316 orrs r6, r2 + 262d6: 431f orrs r7, r3 + 262d8: e9cd 673e strd r6, r7, [sp, #248] ; 0xf8 + 262dc: e9dd 2338 ldrd r2, r3, [sp, #224] ; 0xe0 + 262e0: f890 6034 ldrb.w r6, [r0, #52] ; 0x34 + 262e4: 2700 movs r7, #0 + 262e6: e9cd 6728 strd r6, r7, [sp, #160] ; 0xa0 + 262ea: f8dd c040 ldr.w ip, [sp, #64] ; 0x40 + 262ee: 9f12 ldr r7, [sp, #72] ; 0x48 + 262f0: f8dd e098 ldr.w lr, [sp, #152] ; 0x98 + 262f4: e9cd 452c strd r4, r5, [sp, #176] ; 0xb0 + 262f8: e9dd 4508 ldrd r4, r5, [sp, #32] + 262fc: 4322 orrs r2, r4 + 262fe: 432b orrs r3, r5 + 26300: ac40 add r4, sp, #256 ; 0x100 + 26302: e9cd 2338 strd r2, r3, [sp, #224] ; 0xe0 + 26306: e9d4 2300 ldrd r2, r3, [r4] + 2630a: e9dd 450a ldrd r4, r5, [sp, #40] ; 0x28 + 2630e: 0a3f lsrs r7, r7, #8 + 26310: 4322 orrs r2, r4 + 26312: 432b orrs r3, r5 + 26314: ea4f 2c1c mov.w ip, ip, lsr #8 + 26318: ad44 add r5, sp, #272 ; 0x110 + 2631a: ea4f 6e1e mov.w lr, lr, lsr #24 + 2631e: e9c5 2300 strd r2, r3, [r5] + 26322: 9719 str r7, [sp, #100] ; 0x64 + 26324: f8cd c10c str.w ip, [sp, #268] ; 0x10c + 26328: f8cd e07c str.w lr, [sp, #124] ; 0x7c + 2632c: 9b1a ldr r3, [sp, #104] ; 0x68 + 2632e: ea4f 621a mov.w r2, sl, lsr #24 + 26332: f8dd c048 ldr.w ip, [sp, #72] ; 0x48 + 26336: 920d str r2, [sp, #52] ; 0x34 + 26338: 0c1d lsrs r5, r3, #16 + 2633a: 9a2a ldr r2, [sp, #168] ; 0xa8 + 2633c: ea4f 230a mov.w r3, sl, lsl #8 + 26340: f8dd a068 ldr.w sl, [sp, #104] ; 0x68 + 26344: f8dd e040 ldr.w lr, [sp, #64] ; 0x40 + 26348: ea4f 6c0c mov.w ip, ip, lsl #24 + 2634c: f8cd c060 str.w ip, [sp, #96] ; 0x60 + 26350: 930c str r3, [sp, #48] ; 0x30 + 26352: 0416 lsls r6, r2, #16 + 26354: ea4f 440a mov.w r4, sl, lsl #16 + 26358: e9dd 2314 ldrd r2, r3, [sp, #80] ; 0x50 + 2635c: f50d 7a8c add.w sl, sp, #280 ; 0x118 + 26360: ea42 0208 orr.w r2, r2, r8 + 26364: ea43 0309 orr.w r3, r3, r9 + 26368: e9ca 2300 strd r2, r3, [sl] + 2636c: e9dd 8918 ldrd r8, r9, [sp, #96] ; 0x60 + 26370: e9dd 2336 ldrd r2, r3, [sp, #216] ; 0xd8 + 26374: ea4f 6e0e mov.w lr, lr, lsl #24 + 26378: ea42 0208 orr.w r2, r2, r8 + 2637c: ea43 0309 orr.w r3, r3, r9 + 26380: f8cd e108 str.w lr, [sp, #264] ; 0x108 + 26384: e9cd 231c strd r2, r3, [sp, #112] ; 0x70 + 26388: e9dd ab3a ldrd sl, fp, [sp, #232] ; 0xe8 + 2638c: ab42 add r3, sp, #264 ; 0x108 + 2638e: e9d3 2300 ldrd r2, r3, [r3] + 26392: 992a ldr r1, [sp, #168] ; 0xa8 + 26394: ea4a 0a02 orr.w sl, sl, r2 + 26398: ea4b 0b03 orr.w fp, fp, r3 + 2639c: e9cd ab24 strd sl, fp, [sp, #144] ; 0x90 + 263a0: e9dd ab0c ldrd sl, fp, [sp, #48] ; 0x30 + 263a4: ea4a 0a04 orr.w sl, sl, r4 + 263a8: ea4b 0b05 orr.w fp, fp, r5 + 263ac: e9cd ab34 strd sl, fp, [sp, #208] ; 0xd0 + 263b0: e9dd 453c ldrd r4, r5, [sp, #240] ; 0xf0 + 263b4: f890 a016 ldrb.w sl, [r0, #22] + 263b8: 0c0f lsrs r7, r1, #16 + 263ba: 9926 ldr r1, [sp, #152] ; 0x98 + 263bc: f04f 0b00 mov.w fp, #0 + 263c0: e9cd ab2a strd sl, fp, [sp, #168] ; 0xa8 + 263c4: f8dd c0c8 ldr.w ip, [sp, #200] ; 0xc8 + 263c8: f8dd b0c0 ldr.w fp, [sp, #192] ; 0xc0 + 263cc: 0209 lsls r1, r1, #8 + 263ce: 911e str r1, [sp, #120] ; 0x78 + 263d0: 7dc2 ldrb r2, [r0, #23] + 263d2: e9dd 891e ldrd r8, r9, [sp, #120] ; 0x78 + 263d6: 2300 movs r3, #0 + 263d8: ea48 0806 orr.w r8, r8, r6 + 263dc: ea49 0907 orr.w r9, r9, r7 + 263e0: ea4f 6b1b mov.w fp, fp, lsr #24 + 263e4: e9dd 6710 ldrd r6, r7, [sp, #64] ; 0x40 + 263e8: ea4f 4c1c mov.w ip, ip, lsr #16 + 263ec: 4334 orrs r4, r6 + 263ee: 433d orrs r5, r7 + 263f0: af42 add r7, sp, #264 ; 0x108 + 263f2: e9cd 2308 strd r2, r3, [sp, #32] + 263f6: e9c7 4500 strd r4, r5, [r7] + 263fa: e9cd 8936 strd r8, r9, [sp, #216] ; 0xd8 + 263fe: f8cd b05c str.w fp, [sp, #92] ; 0x5c + 26402: f8cd c084 str.w ip, [sp, #132] ; 0x84 + 26406: 9930 ldr r1, [sp, #192] ; 0xc0 + 26408: 9a32 ldr r2, [sp, #200] ; 0xc8 + 2640a: 9d2c ldr r5, [sp, #176] ; 0xb0 + 2640c: 0209 lsls r1, r1, #8 + 2640e: 0412 lsls r2, r2, #16 + 26410: 9116 str r1, [sp, #88] ; 0x58 + 26412: 9220 str r2, [sp, #128] ; 0x80 + 26414: e9dd ab16 ldrd sl, fp, [sp, #88] ; 0x58 + 26418: 09aa lsrs r2, r5, #6 + 2641a: e9dd 4520 ldrd r4, r5, [sp, #128] ; 0x80 + 2641e: ea4a 0a04 orr.w sl, sl, r4 + 26422: f64f 74ff movw r4, #65535 ; 0xffff + 26426: e9dd 8928 ldrd r8, r9, [sp, #160] ; 0xa0 + 2642a: e9dd 673e ldrd r6, r7, [sp, #248] ; 0xf8 + 2642e: f2c0 041f movt r4, #31 + 26432: f8dd e0b8 ldr.w lr, [sp, #184] ; 0xb8 + 26436: 9b2e ldr r3, [sp, #184] ; 0xb8 + 26438: ea4f 2e1e mov.w lr, lr, lsr #8 + 2643c: 061b lsls r3, r3, #24 + 2643e: f8cd e08c str.w lr, [sp, #140] ; 0x8c + 26442: 9322 str r3, [sp, #136] ; 0x88 + 26444: ea46 0608 orr.w r6, r6, r8 + 26448: ea47 0709 orr.w r7, r7, r9 + 2644c: ea4b 0b05 orr.w fp, fp, r5 + 26450: f50d 7980 add.w r9, sp, #256 ; 0x100 + 26454: e9c9 6700 strd r6, r7, [r9] + 26458: e9dd 8938 ldrd r8, r9, [sp, #224] ; 0xe0 + 2645c: e9cd ab3e strd sl, fp, [sp, #248] ; 0xf8 + 26460: e9dd ab22 ldrd sl, fp, [sp, #136] ; 0x88 + 26464: ea49 090b orr.w r9, r9, fp + 26468: f8dd b0b4 ldr.w fp, [sp, #180] ; 0xb4 + 2646c: f890 6031 ldrb.w r6, [r0, #49] ; 0x31 + 26470: ea42 628b orr.w r2, r2, fp, lsl #26 + 26474: ea4f 139b mov.w r3, fp, lsr #6 + 26478: 2700 movs r7, #0 + 2647a: 2500 movs r5, #0 + 2647c: e9cd 671e strd r6, r7, [sp, #120] ; 0x78 + 26480: 4014 ands r4, r2 + 26482: 401d ands r5, r3 + 26484: f642 5618 movw r6, #11544 ; 0x2d18 + 26488: e9cd 450c strd r4, r5, [sp, #48] ; 0x30 + 2648c: f642 4513 movw r5, #11283 ; 0x2c13 + 26490: ea48 080a orr.w r8, r8, sl + 26494: f50d 7a88 add.w sl, sp, #272 ; 0x110 + 26498: e9cd 8922 strd r8, r9, [sp, #136] ; 0x88 + 2649c: e9da 8900 ldrd r8, r9, [sl] + 264a0: f2c0 0607 movt r6, #7 + 264a4: ea5f 0959 movs.w r9, r9, lsr #1 + 264a8: ea4f 0838 mov.w r8, r8, rrx + 264ac: f2c0 050a movt r5, #10 + 264b0: f890 2027 ldrb.w r2, [r0, #39] ; 0x27 + 264b4: 2300 movs r3, #0 + 264b6: e9cd 2316 strd r2, r3, [sp, #88] ; 0x58 + 264ba: 9c1c ldr r4, [sp, #112] ; 0x70 + 264bc: 9b46 ldr r3, [sp, #280] ; 0x118 + 264be: f8dd a090 ldr.w sl, [sp, #144] ; 0x90 + 264c2: e9cd 8938 strd r8, r9, [sp, #224] ; 0xe0 + 264c6: 9612 str r6, [sp, #72] ; 0x48 + 264c8: ea4f 0893 mov.w r8, r3, lsr #2 + 264cc: 09e6 lsrs r6, r4, #7 + 264ce: e9dd 2336 ldrd r2, r3, [sp, #216] ; 0xd8 + 264d2: ea4f 141a mov.w r4, sl, lsr #4 + 264d6: e9dd ab06 ldrd sl, fp, [sp, #24] + 264da: ea42 020a orr.w r2, r2, sl + 264de: ea43 030b orr.w r3, r3, fp + 264e2: 950e str r5, [sp, #56] ; 0x38 + 264e4: e9cd 233c strd r2, r3, [sp, #240] ; 0xf0 + 264e8: e9dd 2308 ldrd r2, r3, [sp, #32] + 264ec: e9dd ab34 ldrd sl, fp, [sp, #208] ; 0xd0 + 264f0: ea4b 0b03 orr.w fp, fp, r3 + 264f4: 9b47 ldr r3, [sp, #284] ; 0x11c + 264f6: ea4a 0a02 orr.w sl, sl, r2 + 264fa: ea48 7883 orr.w r8, r8, r3, lsl #30 + 264fe: 9b47 ldr r3, [sp, #284] ; 0x11c + 26500: e9cd ab32 strd sl, fp, [sp, #200] ; 0xc8 + 26504: f8dd e0a8 ldr.w lr, [sp, #168] ; 0xa8 + 26508: f8dd b094 ldr.w fp, [sp, #148] ; 0x94 + 2650c: ea4f 4c12 mov.w ip, r2, lsr #16 + 26510: 7c02 ldrb r2, [r0, #16] + 26512: ea4f 0993 mov.w r9, r3, lsr #2 + 26516: 2300 movs r3, #0 + 26518: ea44 740b orr.w r4, r4, fp, lsl #28 + 2651c: ea4f 6b1e mov.w fp, lr, lsr #24 + 26520: f8dd e094 ldr.w lr, [sp, #148] ; 0x94 + 26524: e9cd 2324 strd r2, r3, [sp, #144] ; 0x90 + 26528: f64f 72ff movw r2, #65535 ; 0xffff + 2652c: f2c0 021f movt r2, #31 + 26530: f8dd a074 ldr.w sl, [sp, #116] ; 0x74 + 26534: 9b2a ldr r3, [sp, #168] ; 0xa8 + 26536: ea46 664a orr.w r6, r6, sl, lsl #25 + 2653a: ea4f 17da mov.w r7, sl, lsr #7 + 2653e: ea4f 2a03 mov.w sl, r3, lsl #8 + 26542: 2300 movs r3, #0 + 26544: ea02 0208 and.w r2, r2, r8 + 26548: ea03 0309 and.w r3, r3, r9 + 2654c: f64f 78ff movw r8, #65535 ; 0xffff + 26550: e9cd 232e strd r2, r3, [sp, #184] ; 0xb8 + 26554: f64f 72ff movw r2, #65535 ; 0xffff + 26558: f2c0 081f movt r8, #31 + 2655c: f2c0 021f movt r2, #31 + 26560: ea4f 151e mov.w r5, lr, lsr #4 + 26564: ea08 0806 and.w r8, r8, r6 + 26568: 2300 movs r3, #0 + 2656a: ae42 add r6, sp, #264 ; 0x108 + 2656c: 4022 ands r2, r4 + 2656e: 402b ands r3, r5 + 26570: e9d6 4500 ldrd r4, r5, [r6] + 26574: 086d lsrs r5, r5, #1 + 26576: ea4f 0434 mov.w r4, r4, rrx + 2657a: ae48 add r6, sp, #288 ; 0x120 + 2657c: f04f 0900 mov.w r9, #0 + 26580: e9c6 4500 strd r4, r5, [r6] + 26584: 9908 ldr r1, [sp, #32] + 26586: ea09 0907 and.w r9, r9, r7 + 2658a: 9d0a ldr r5, [sp, #40] ; 0x28 + 2658c: 9f0a ldr r7, [sp, #40] ; 0x28 + 2658e: e9cd 233a strd r2, r3, [sp, #232] ; 0xe8 + 26592: 7d42 ldrb r2, [r0, #21] + 26594: ac42 add r4, sp, #264 ; 0x108 + 26596: 0409 lsls r1, r1, #16 + 26598: 2300 movs r3, #0 + 2659a: 0a2d lsrs r5, r5, #8 + 2659c: 063f lsls r7, r7, #24 + 2659e: f8cd c064 str.w ip, [sp, #100] ; 0x64 + 265a2: 9118 str r1, [sp, #96] ; 0x60 + 265a4: e9c4 2300 strd r2, r3, [r4] + 265a8: 9527 str r5, [sp, #156] ; 0x9c + 265aa: 9726 str r7, [sp, #152] ; 0x98 + 265ac: ab40 add r3, sp, #256 ; 0x100 + 265ae: e9cd 8934 strd r8, r9, [sp, #208] ; 0xd0 + 265b2: e9dd 8918 ldrd r8, r9, [sp, #96] ; 0x60 + 265b6: e9dd 673e ldrd r6, r7, [sp, #248] ; 0xf8 + 265ba: ea48 080a orr.w r8, r8, sl + 265be: ea49 090b orr.w r9, r9, fp + 265c2: e9d3 ab00 ldrd sl, fp, [r3] + 265c6: e9dd 2326 ldrd r2, r3, [sp, #152] ; 0x98 + 265ca: ea4a 0a02 orr.w sl, sl, r2 + 265ce: ea4b 0b03 orr.w fp, fp, r3 + 265d2: f50d 7c88 add.w ip, sp, #272 ; 0x110 + 265d6: e9cd ab02 strd sl, fp, [sp, #8] + 265da: e9dd ab1e ldrd sl, fp, [sp, #120] ; 0x78 + 265de: 2400 movs r4, #0 + 265e0: ea46 060a orr.w r6, r6, sl + 265e4: ea47 070b orr.w r7, r7, fp + 265e8: 2500 movs r5, #0 + 265ea: f50d 7b8c add.w fp, sp, #280 ; 0x118 + 265ee: e9cc 8900 strd r8, r9, [ip] + 265f2: e9cd 4506 strd r4, r5, [sp, #24] + 265f6: f890 8011 ldrb.w r8, [r0, #17] + 265fa: e9cb 6700 strd r6, r7, [fp] + 265fe: e9dd 4538 ldrd r4, r5, [sp, #224] ; 0xe0 + 26602: f64f 76ff movw r6, #65535 ; 0xffff + 26606: 2700 movs r7, #0 + 26608: 403d ands r5, r7 + 2660a: f64f 3767 movw r7, #64359 ; 0xfb67 + 2660e: f2c0 061f movt r6, #31 + 26612: f2c0 0709 movt r7, #9 + 26616: f8dd c088 ldr.w ip, [sp, #136] ; 0x88 + 2661a: f8dd e08c ldr.w lr, [sp, #140] ; 0x8c + 2661e: 990c ldr r1, [sp, #48] ; 0x30 + 26620: 9a0e ldr r2, [sp, #56] ; 0x38 + 26622: ea4f 0cdc mov.w ip, ip, lsr #3 + 26626: ea4c 7c4e orr.w ip, ip, lr, lsl #29 + 2662a: fba1 ab02 umull sl, fp, r1, r2 + 2662e: fbac 2302 umull r2, r3, ip, r2 + 26632: 9924 ldr r1, [sp, #144] ; 0x90 + 26634: e9cd 231c strd r2, r3, [sp, #112] ; 0x70 + 26638: 9b12 ldr r3, [sp, #72] ; 0x48 + 2663a: 4034 ands r4, r6 + 2663c: f8cd c068 str.w ip, [sp, #104] ; 0x68 + 26640: e9cd 450a strd r4, r5, [sp, #40] ; 0x28 + 26644: 9e23 ldr r6, [sp, #140] ; 0x8c + 26646: fbac 4503 umull r4, r5, ip, r3 + 2664a: 0e09 lsrs r1, r1, #24 + 2664c: f8dd c050 ldr.w ip, [sp, #80] ; 0x50 + 26650: 9b0e ldr r3, [sp, #56] ; 0x38 + 26652: 9109 str r1, [sp, #36] ; 0x24 + 26654: 991d ldr r1, [sp, #116] ; 0x74 + 26656: 08f6 lsrs r6, r6, #3 + 26658: ea4f 2c1c mov.w ip, ip, lsr #8 + 2665c: f8cd c014 str.w ip, [sp, #20] + 26660: fb03 1c06 mla ip, r3, r6, r1 + 26664: 9a0d ldr r2, [sp, #52] ; 0x34 + 26666: 9710 str r7, [sp, #64] ; 0x40 + 26668: fb03 bb02 mla fp, r3, r2, fp + 2666c: 9a24 ldr r2, [sp, #144] ; 0x90 + 2666e: 9f16 ldr r7, [sp, #88] ; 0x58 + 26670: f8cd c074 str.w ip, [sp, #116] ; 0x74 + 26674: f8dd c058 ldr.w ip, [sp, #88] ; 0x58 + 26678: 9b12 ldr r3, [sp, #72] ; 0x48 + 2667a: 0212 lsls r2, r2, #8 + 2667c: 9914 ldr r1, [sp, #80] ; 0x50 + 2667e: 9208 str r2, [sp, #32] + 26680: 0a3f lsrs r7, r7, #8 + 26682: f890 2030 ldrb.w r2, [r0, #48] ; 0x30 + 26686: ea4f 6c0c mov.w ip, ip, lsl #24 + 2668a: 9721 str r7, [sp, #132] ; 0x84 + 2668c: fb03 5506 mla r5, r3, r6, r5 + 26690: f8cd c080 str.w ip, [sp, #128] ; 0x80 + 26694: 2300 movs r3, #0 + 26696: 9618 str r6, [sp, #96] ; 0x60 + 26698: ea4f 4718 mov.w r7, r8, lsr #16 + 2669c: e9cd 2336 strd r2, r3, [sp, #216] ; 0xd8 + 266a0: e9dd 233c ldrd r2, r3, [sp, #240] ; 0xf0 + 266a4: ea4f 4608 mov.w r6, r8, lsl #16 + 266a8: 0609 lsls r1, r1, #24 + 266aa: e9dd 8920 ldrd r8, r9, [sp, #128] ; 0x80 + 266ae: ea42 0208 orr.w r2, r2, r8 + 266b2: ea43 0309 orr.w r3, r3, r9 + 266b6: 9104 str r1, [sp, #16] + 266b8: e9cd 2320 strd r2, r3, [sp, #128] ; 0x80 + 266bc: e9dd 8932 ldrd r8, r9, [sp, #200] ; 0xc8 + 266c0: e9dd 2304 ldrd r2, r3, [sp, #16] + 266c4: ea42 0208 orr.w r2, r2, r8 + 266c8: ea43 0309 orr.w r3, r3, r9 + 266cc: e9cd 2304 strd r2, r3, [sp, #16] + 266d0: e9dd 2308 ldrd r2, r3, [sp, #32] + 266d4: 4332 orrs r2, r6 + 266d6: 433b orrs r3, r7 + 266d8: e9dd 672e ldrd r6, r7, [sp, #184] ; 0xb8 + 266dc: eb16 060a adds.w r6, r6, sl + 266e0: eb47 070b adc.w r7, r7, fp + 266e4: f50d 7880 add.w r8, sp, #256 ; 0x100 + 266e8: e9c8 6700 strd r6, r7, [r8] + 266ec: e9dd ab1c ldrd sl, fp, [sp, #112] ; 0x70 + 266f0: e9dd 6734 ldrd r6, r7, [sp, #208] ; 0xd0 + 266f4: f64f 78ff movw r8, #65535 ; 0xffff + 266f8: f2c0 081f movt r8, #31 + 266fc: eb1a 0a06 adds.w sl, sl, r6 + 26700: eb4b 0b07 adc.w fp, fp, r7 + 26704: e9cd ab3c strd sl, fp, [sp, #240] ; 0xf0 + 26708: e9dd ab3a ldrd sl, fp, [sp, #232] ; 0xe8 + 2670c: f50d 7990 add.w r9, sp, #288 ; 0x120 + 26710: eb1a 0a04 adds.w sl, sl, r4 + 26714: f890 4029 ldrb.w r4, [r0, #41] ; 0x29 + 26718: eb4b 0b05 adc.w fp, fp, r5 + 2671c: e9d9 6700 ldrd r6, r7, [r9] + 26720: 2500 movs r5, #0 + 26722: f04f 0900 mov.w r9, #0 + 26726: e9cd 452e strd r4, r5, [sp, #184] ; 0xb8 + 2672a: ea06 0608 and.w r6, r6, r8 + 2672e: ea07 0709 and.w r7, r7, r9 + 26732: ac44 add r4, sp, #272 ; 0x110 + 26734: ad42 add r5, sp, #264 ; 0x108 + 26736: e9cd 673a strd r6, r7, [sp, #232] ; 0xe8 + 2673a: e9cd ab3e strd sl, fp, [sp, #248] ; 0xf8 + 2673e: e9d4 ab00 ldrd sl, fp, [r4] + 26742: e9d5 4500 ldrd r4, r5, [r5] + 26746: 7bc6 ldrb r6, [r0, #15] + 26748: ea4a 0a04 orr.w sl, sl, r4 + 2674c: ea4b 0b05 orr.w fp, fp, r5 + 26750: f890 402b ldrb.w r4, [r0, #43] ; 0x2b + 26754: ad44 add r5, sp, #272 ; 0x110 + 26756: e9c5 ab00 strd sl, fp, [r5] + 2675a: 2700 movs r7, #0 + 2675c: f8dd b078 ldr.w fp, [sp, #120] ; 0x78 + 26760: 2500 movs r5, #0 + 26762: e9cd 6714 strd r6, r7, [sp, #80] ; 0x50 + 26766: e9cd 4534 strd r4, r5, [sp, #208] ; 0xd0 + 2676a: 9f28 ldr r7, [sp, #160] ; 0xa0 + 2676c: f8dd c0a0 ldr.w ip, [sp, #160] ; 0xa0 + 26770: 9c1e ldr r4, [sp, #120] ; 0x78 + 26772: f8dd a0d8 ldr.w sl, [sp, #216] ; 0xd8 + 26776: f890 802c ldrb.w r8, [r0, #44] ; 0x2c + 2677a: ea4f 4b1b mov.w fp, fp, lsr #16 + 2677e: f8cd b0ac str.w fp, [sp, #172] ; 0xac + 26782: f04f 0900 mov.w r9, #0 + 26786: f50d 7b8c add.w fp, sp, #280 ; 0x118 + 2678a: 0a3f lsrs r7, r7, #8 + 2678c: ea4f 6c0c mov.w ip, ip, lsl #24 + 26790: 0424 lsls r4, r4, #16 + 26792: e9cd 2338 strd r2, r3, [sp, #224] ; 0xe0 + 26796: e9cd 891c strd r8, r9, [sp, #112] ; 0x70 + 2679a: f890 2028 ldrb.w r2, [r0, #40] ; 0x28 + 2679e: 9731 str r7, [sp, #196] ; 0xc4 + 267a0: ea4f 691a mov.w r9, sl, lsr #24 + 267a4: f8cd c0c0 str.w ip, [sp, #192] ; 0xc0 + 267a8: ea4f 280a mov.w r8, sl, lsl #8 + 267ac: 942a str r4, [sp, #168] ; 0xa8 + 267ae: e9db 6700 ldrd r6, r7, [fp] + 267b2: e9dd ab30 ldrd sl, fp, [sp, #192] ; 0xc0 + 267b6: ea46 060a orr.w r6, r6, sl + 267ba: ea47 070b orr.w r7, r7, fp + 267be: e9cd 6728 strd r6, r7, [sp, #160] ; 0xa0 + 267c2: e9dd 672a ldrd r6, r7, [sp, #168] ; 0xa8 + 267c6: ea46 0608 orr.w r6, r6, r8 + 267ca: ea47 0709 orr.w r7, r7, r9 + 267ce: e9cd 6730 strd r6, r7, [sp, #192] ; 0xc0 + 267d2: f64f 76ff movw r6, #65535 ; 0xffff + 267d6: f2c0 061f movt r6, #31 + 267da: 9d02 ldr r5, [sp, #8] + 267dc: f8dd 800c ldr.w r8, [sp, #12] + 267e0: 092d lsrs r5, r5, #4 + 267e2: 9506 str r5, [sp, #24] + 267e4: 9f06 ldr r7, [sp, #24] + 267e6: ea4f 1918 mov.w r9, r8, lsr #4 + 267ea: ea47 7708 orr.w r7, r7, r8, lsl #28 + 267ee: 9706 str r7, [sp, #24] + 267f0: f8cd 901c str.w r9, [sp, #28] + 267f4: f8dd a028 ldr.w sl, [sp, #40] ; 0x28 + 267f8: f8dd b048 ldr.w fp, [sp, #72] ; 0x48 + 267fc: 2700 movs r7, #0 + 267fe: e9dd 4506 ldrd r4, r5, [sp, #24] + 26802: 4034 ands r4, r6 + 26804: 403d ands r5, r7 + 26806: fbaa 890b umull r8, r9, sl, fp + 2680a: e9cd 4506 strd r4, r5, [sp, #24] + 2680e: f8dd b030 ldr.w fp, [sp, #48] ; 0x30 + 26812: f8dd a048 ldr.w sl, [sp, #72] ; 0x48 + 26816: 9d0c ldr r5, [sp, #48] ; 0x30 + 26818: 9c10 ldr r4, [sp, #64] ; 0x40 + 2681a: fbab ab0a umull sl, fp, fp, sl + 2681e: fba5 4504 umull r4, r5, r5, r4 + 26822: e9cd ab1e strd sl, fp, [sp, #120] ; 0x78 + 26826: e9cd 4522 strd r4, r5, [sp, #136] ; 0x88 + 2682a: 0e15 lsrs r5, r2, #24 + 2682c: 9912 ldr r1, [sp, #72] ; 0x48 + 2682e: 9525 str r5, [sp, #148] ; 0x94 + 26830: 9e2e ldr r6, [sp, #184] ; 0xb8 + 26832: 9d1f ldr r5, [sp, #124] ; 0x7c + 26834: 9f0b ldr r7, [sp, #44] ; 0x2c + 26836: 9c0d ldr r4, [sp, #52] ; 0x34 + 26838: fb01 9907 mla r9, r1, r7, r9 + 2683c: fb01 5404 mla r4, r1, r4, r5 + 26840: 9f10 ldr r7, [sp, #64] ; 0x40 + 26842: 9923 ldr r1, [sp, #140] ; 0x8c + 26844: ea4f 4b16 mov.w fp, r6, lsr #16 + 26848: 9e0d ldr r6, [sp, #52] ; 0x34 + 2684a: 9d2e ldr r5, [sp, #184] ; 0xb8 + 2684c: fb07 1606 mla r6, r7, r6, r1 + 26850: 941f str r4, [sp, #124] ; 0x7c + 26852: 0214 lsls r4, r2, #8 + 26854: 9424 str r4, [sp, #144] ; 0x90 + 26856: ea4f 4a05 mov.w sl, r5, lsl #16 + 2685a: 9623 str r6, [sp, #140] ; 0x8c + 2685c: a942 add r1, sp, #264 ; 0x108 + 2685e: e9dd 6724 ldrd r6, r7, [sp, #144] ; 0x90 + 26862: ea46 060a orr.w r6, r6, sl + 26866: ea47 070b orr.w r7, r7, fp + 2686a: e9c1 6700 strd r6, r7, [r1] + 2686e: e9dd ab38 ldrd sl, fp, [sp, #224] ; 0xe0 + 26872: 9a20 ldr r2, [sp, #128] ; 0x80 + 26874: 9b04 ldr r3, [sp, #16] + 26876: 0996 lsrs r6, r2, #6 + 26878: 095c lsrs r4, r3, #5 + 2687a: e9dd 2314 ldrd r2, r3, [sp, #80] ; 0x50 + 2687e: ea4a 0a02 orr.w sl, sl, r2 + 26882: ea4b 0b03 orr.w fp, fp, r3 + 26886: e9cd ab38 strd sl, fp, [sp, #224] ; 0xe0 + 2688a: f890 a02f ldrb.w sl, [r0, #47] ; 0x2f + 2688e: f04f 0b00 mov.w fp, #0 + 26892: e9cd ab24 strd sl, fp, [sp, #144] ; 0x90 + 26896: f8dd b084 ldr.w fp, [sp, #132] ; 0x84 + 2689a: 991c ldr r1, [sp, #112] ; 0x70 + 2689c: ea46 668b orr.w r6, r6, fp, lsl #26 + 268a0: ea4f 179b mov.w r7, fp, lsr #6 + 268a4: f8dd b070 ldr.w fp, [sp, #112] ; 0x70 + 268a8: 9a34 ldr r2, [sp, #208] ; 0xd0 + 268aa: ea4f 4b0b mov.w fp, fp, lsl #16 + 268ae: 9b05 ldr r3, [sp, #20] + 268b0: f8cd b0b0 str.w fp, [sp, #176] ; 0xb0 + 268b4: f8dd a068 ldr.w sl, [sp, #104] ; 0x68 + 268b8: f8dd b040 ldr.w fp, [sp, #64] ; 0x40 + 268bc: 0c09 lsrs r1, r1, #16 + 268be: 912d str r1, [sp, #180] ; 0xb4 + 268c0: 0e12 lsrs r2, r2, #24 + 268c2: 9934 ldr r1, [sp, #208] ; 0xd0 + 268c4: 9227 str r2, [sp, #156] ; 0x9c + 268c6: ea44 64c3 orr.w r4, r4, r3, lsl #27 + 268ca: 095d lsrs r5, r3, #5 + 268cc: fbaa 230b umull r2, r3, sl, fp + 268d0: 0209 lsls r1, r1, #8 + 268d2: 9126 str r1, [sp, #152] ; 0x98 + 268d4: 9918 ldr r1, [sp, #96] ; 0x60 + 268d6: f24c 6e53 movw lr, #50771 ; 0xc653 + 268da: fb0b 3301 mla r3, fp, r1, r3 + 268de: a940 add r1, sp, #256 ; 0x100 + 268e0: e9d1 ab00 ldrd sl, fp, [r1] + 268e4: eb1a 0a08 adds.w sl, sl, r8 + 268e8: eb4b 0b09 adc.w fp, fp, r9 + 268ec: e9c1 ab00 strd sl, fp, [r1] + 268f0: e9dd 891e ldrd r8, r9, [sp, #120] ; 0x78 + 268f4: e9dd ab3c ldrd sl, fp, [sp, #240] ; 0xf0 + 268f8: eb18 080a adds.w r8, r8, sl + 268fc: eb49 090b adc.w r9, r9, fp + 26900: e9cd 893c strd r8, r9, [sp, #240] ; 0xf0 + 26904: e9dd ab3e ldrd sl, fp, [sp, #248] ; 0xf8 + 26908: e9dd 8922 ldrd r8, r9, [sp, #136] ; 0x88 + 2690c: eb18 080a adds.w r8, r8, sl + 26910: eb49 090b adc.w r9, r9, fp + 26914: e9cd 893e strd r8, r9, [sp, #248] ; 0xf8 + 26918: e9dd 893a ldrd r8, r9, [sp, #232] ; 0xe8 + 2691c: eb18 0802 adds.w r8, r8, r2 + 26920: f64f 72ff movw r2, #65535 ; 0xffff + 26924: f2c0 021f movt r2, #31 + 26928: eb49 0903 adc.w r9, r9, r3 + 2692c: 2300 movs r3, #0 + 2692e: 4032 ands r2, r6 + 26930: 403b ands r3, r7 + 26932: e9cd 2336 strd r2, r3, [sp, #216] ; 0xd8 + 26936: e9dd 6726 ldrd r6, r7, [sp, #152] ; 0x98 + 2693a: f64f 72ff movw r2, #65535 ; 0xffff + 2693e: f2c0 021f movt r2, #31 + 26942: f890 a013 ldrb.w sl, [r0, #19] + 26946: e9cd 893a strd r8, r9, [sp, #232] ; 0xe8 + 2694a: e9dd 892c ldrd r8, r9, [sp, #176] ; 0xb0 + 2694e: ab44 add r3, sp, #272 ; 0x110 + 26950: ea46 0608 orr.w r6, r6, r8 + 26954: ea47 0709 orr.w r7, r7, r9 + 26958: f04f 0b00 mov.w fp, #0 + 2695c: f50d 798c add.w r9, sp, #280 ; 0x118 + 26960: e9cd ab20 strd sl, fp, [sp, #128] ; 0x80 + 26964: e9c9 6700 strd r6, r7, [r9] + 26968: e9d3 ab00 ldrd sl, fp, [r3] + 2696c: 7c86 ldrb r6, [r0, #18] + 2696e: ea0a 0a02 and.w sl, sl, r2 + 26972: 2300 movs r3, #0 + 26974: 4022 ands r2, r4 + 26976: 7d04 ldrb r4, [r0, #20] + 26978: ea0b 0b03 and.w fp, fp, r3 + 2697c: 2700 movs r7, #0 + 2697e: 402b ands r3, r5 + 26980: 2500 movs r5, #0 + 26982: e9cd 452a strd r4, r5, [sp, #168] ; 0xa8 + 26986: e9dd 4530 ldrd r4, r5, [sp, #192] ; 0xc0 + 2698a: e9cd 671e strd r6, r7, [sp, #120] ; 0x78 + 2698e: e9dd 6724 ldrd r6, r7, [sp, #144] ; 0x90 + 26992: 4334 orrs r4, r6 + 26994: 433d orrs r5, r7 + 26996: e9cd 4526 strd r4, r5, [sp, #152] ; 0x98 + 2699a: f64f 74ff movw r4, #65535 ; 0xffff + 2699e: f2c0 041f movt r4, #31 + 269a2: f890 800e ldrb.w r8, [r0, #14] + 269a6: e9cd 2334 strd r2, r3, [sp, #208] ; 0xd0 + 269aa: f04f 0900 mov.w r9, #0 + 269ae: 9a28 ldr r2, [sp, #160] ; 0xa0 + 269b0: f6cf 7ef0 movt lr, #65520 ; 0xfff0 + 269b4: e9cd 8922 strd r8, r9, [sp, #136] ; 0x88 + 269b8: f8dd 80a4 ldr.w r8, [sp, #164] ; 0xa4 + 269bc: 09d2 lsrs r2, r2, #7 + 269be: ea42 6748 orr.w r7, r2, r8, lsl #25 + 269c2: 9708 str r7, [sp, #32] + 269c4: e9cd ab2e strd sl, fp, [sp, #184] ; 0xb8 + 269c8: 9f0a ldr r7, [sp, #40] ; 0x28 + 269ca: f890 a02a ldrb.w sl, [r0, #42] ; 0x2a + 269ce: 9e10 ldr r6, [sp, #64] ; 0x40 + 269d0: a944 add r1, sp, #272 ; 0x110 + 269d2: f04f 0b00 mov.w fp, #0 + 269d6: e9c1 ab00 strd sl, fp, [r1] + 269da: fba7 6706 umull r6, r7, r7, r6 + 269de: f8dd b018 ldr.w fp, [sp, #24] + 269e2: f8dd a040 ldr.w sl, [sp, #64] ; 0x40 + 269e6: ea4f 19d8 mov.w r9, r8, lsr #7 + 269ea: fbab ab0a umull sl, fp, fp, sl + 269ee: f8cd 9024 str.w r9, [sp, #36] ; 0x24 + 269f2: 2500 movs r5, #0 + 269f4: e9dd 2308 ldrd r2, r3, [sp, #32] + 269f8: e9cd 6728 strd r6, r7, [sp, #160] ; 0xa0 + 269fc: 4022 ands r2, r4 + 269fe: 402b ands r3, r5 + 26a00: 9f0a ldr r7, [sp, #40] ; 0x28 + 26a02: 990c ldr r1, [sp, #48] ; 0x30 + 26a04: e9cd 2308 strd r2, r3, [sp, #32] + 26a08: 9a20 ldr r2, [sp, #128] ; 0x80 + 26a0a: e9cd ab2c strd sl, fp, [sp, #176] ; 0xb0 + 26a0e: 427f negs r7, r7 + 26a10: 4249 negs r1, r1 + 26a12: 9732 str r7, [sp, #200] ; 0xc8 + 26a14: 9130 str r1, [sp, #192] ; 0xc0 + 26a16: 0e17 lsrs r7, r2, #24 + 26a18: 9910 ldr r1, [sp, #64] ; 0x40 + 26a1a: 9a2d ldr r2, [sp, #180] ; 0xb4 + 26a1c: 9d07 ldr r5, [sp, #28] + 26a1e: 9b2a ldr r3, [sp, #168] ; 0xa8 + 26a20: fb01 2505 mla r5, r1, r5, r2 + 26a24: 9c1e ldr r4, [sp, #120] ; 0x78 + 26a26: ea4f 4913 mov.w r9, r3, lsr #16 + 26a2a: 952d str r5, [sp, #180] ; 0xb4 + 26a2c: ea4f 2b14 mov.w fp, r4, lsr #8 + 26a30: 9b0b ldr r3, [sp, #44] ; 0x2c + 26a32: 9c29 ldr r4, [sp, #164] ; 0xa4 + 26a34: 9d20 ldr r5, [sp, #128] ; 0x80 + 26a36: fb01 4303 mla r3, r1, r3, r4 + 26a3a: 9a1e ldr r2, [sp, #120] ; 0x78 + 26a3c: 992a ldr r1, [sp, #168] ; 0xa8 + 26a3e: 9329 str r3, [sp, #164] ; 0xa4 + 26a40: ab42 add r3, sp, #264 ; 0x108 + 26a42: 022e lsls r6, r5, #8 + 26a44: ea4f 4801 mov.w r8, r1, lsl #16 + 26a48: e9d3 4500 ldrd r4, r5, [r3] + 26a4c: ea4f 6a02 mov.w sl, r2, lsl #24 + 26a50: e9dd 2316 ldrd r2, r3, [sp, #88] ; 0x58 + 26a54: 4314 orrs r4, r2 + 26a56: 431d orrs r5, r3 + 26a58: e9cd 4520 strd r4, r5, [sp, #128] ; 0x80 + 26a5c: e9dd 2338 ldrd r2, r3, [sp, #224] ; 0xe0 + 26a60: ea46 0408 orr.w r4, r6, r8 + 26a64: ea47 0509 orr.w r5, r7, r9 + 26a68: a942 add r1, sp, #264 ; 0x108 + 26a6a: ea43 030b orr.w r3, r3, fp + 26a6e: f50d 7b80 add.w fp, sp, #256 ; 0x100 + 26a72: 9e22 ldr r6, [sp, #136] ; 0x88 + 26a74: e9c1 4500 strd r4, r5, [r1] + 26a78: e9dd 892c ldrd r8, r9, [sp, #176] ; 0xb0 + 26a7c: 9c14 ldr r4, [sp, #80] ; 0x50 + 26a7e: ea42 020a orr.w r2, r2, sl + 26a82: e9db ab00 ldrd sl, fp, [fp] + 26a86: eb18 080a adds.w r8, r8, sl + 26a8a: eb49 090b adc.w r9, r9, fp + 26a8e: e9cd 2304 strd r2, r3, [sp, #16] + 26a92: 0e35 lsrs r5, r6, #24 + 26a94: 0c23 lsrs r3, r4, #16 + 26a96: 0422 lsls r2, r4, #16 + 26a98: e9cd 8938 strd r8, r9, [sp, #224] ; 0xe0 + 26a9c: e9dd 893c ldrd r8, r9, [sp, #240] ; 0xf0 + 26aa0: 0234 lsls r4, r6, #8 + 26aa2: e9dd 6728 ldrd r6, r7, [sp, #160] ; 0xa0 + 26aa6: eb16 0608 adds.w r6, r6, r8 + 26aaa: eb47 0709 adc.w r7, r7, r9 + 26aae: f8dd a0c8 ldr.w sl, [sp, #200] ; 0xc8 + 26ab2: f8dd 902c ldr.w r9, [sp, #44] ; 0x2c + 26ab6: f50d 788c add.w r8, sp, #280 ; 0x118 + 26aba: fb0e a109 mla r1, lr, r9, sl + 26abe: f50d 7988 add.w r9, sp, #272 ; 0x110 + 26ac2: e9cd 673c strd r6, r7, [sp, #240] ; 0xf0 + 26ac6: e9d8 6700 ldrd r6, r7, [r8] + 26aca: e9d9 8900 ldrd r8, r9, [r9] + 26ace: ea46 0608 orr.w r6, r6, r8 + 26ad2: ea47 0709 orr.w r7, r7, r9 + 26ad6: f50d 7988 add.w r9, sp, #272 ; 0x110 + 26ada: f8dd 8038 ldr.w r8, [sp, #56] ; 0x38 + 26ade: e9c9 6700 strd r6, r7, [r9] + 26ae2: 9f06 ldr r7, [sp, #24] + 26ae4: ea44 0a02 orr.w sl, r4, r2 + 26ae8: ea45 0b03 orr.w fp, r5, r3 + 26aec: fba7 4508 umull r4, r5, r7, r8 + 26af0: f8dd 901c ldr.w r9, [sp, #28] + 26af4: ae48 add r6, sp, #288 ; 0x120 + 26af6: fb08 5509 mla r5, r8, r9, r5 + 26afa: e9c6 ab00 strd sl, fp, [r6] + 26afe: e9dd ab2e ldrd sl, fp, [sp, #184] ; 0xb8 + 26b02: e9dd 6734 ldrd r6, r7, [sp, #208] ; 0xd0 + 26b06: eb1a 0a04 adds.w sl, sl, r4 + 26b0a: 9c0a ldr r4, [sp, #40] ; 0x28 + 26b0c: eb4b 0b05 adc.w fp, fp, r5 + 26b10: aa40 add r2, sp, #256 ; 0x100 + 26b12: e9c2 ab00 strd sl, fp, [r2] + 26b16: fba4 2308 umull r2, r3, r4, r8 + 26b1a: 9d0b ldr r5, [sp, #44] ; 0x2c + 26b1c: 18b6 adds r6, r6, r2 + 26b1e: fb08 3305 mla r3, r8, r5, r3 + 26b22: fba4 450e umull r4, r5, r4, lr + 26b26: 415f adcs r7, r3 + 26b28: e9cd 672e strd r6, r7, [sp, #184] ; 0xb8 + 26b2c: e9dd ab3e ldrd sl, fp, [sp, #248] ; 0xf8 + 26b30: 440d add r5, r1 + 26b32: eb1a 0a04 adds.w sl, sl, r4 + 26b36: eb4b 0b05 adc.w fp, fp, r5 + 26b3a: e9cd ab34 strd sl, fp, [sp, #208] ; 0xd0 + 26b3e: 9a30 ldr r2, [sp, #192] ; 0xc0 + 26b40: f8dd b034 ldr.w fp, [sp, #52] ; 0x34 + 26b44: 9d0c ldr r5, [sp, #48] ; 0x30 + 26b46: fb0e 240b mla r4, lr, fp, r2 + 26b4a: e9dd ab36 ldrd sl, fp, [sp, #216] ; 0xd8 + 26b4e: fba5 230e umull r2, r3, r5, lr + 26b52: 9f1a ldr r7, [sp, #104] ; 0x68 + 26b54: 4423 add r3, r4 + 26b56: 427f negs r7, r7 + 26b58: 972c str r7, [sp, #176] ; 0xb0 + 26b5a: e9dd 673a ldrd r6, r7, [sp, #232] ; 0xe8 + 26b5e: 18b6 adds r6, r6, r2 + 26b60: 415f adcs r7, r3 + 26b62: e9cd 672a strd r6, r7, [sp, #168] ; 0xa8 + 26b66: f8dd 8060 ldr.w r8, [sp, #96] ; 0x60 + 26b6a: 9f1a ldr r7, [sp, #104] ; 0x68 + 26b6c: f8dd 90b0 ldr.w r9, [sp, #176] ; 0xb0 + 26b70: fba7 230e umull r2, r3, r7, lr + 26b74: fb0e 9408 mla r4, lr, r8, r9 + 26b78: eb1a 0a02 adds.w sl, sl, r2 + 26b7c: 4423 add r3, r4 + 26b7e: eb4b 0b03 adc.w fp, fp, r3 + 26b82: e9cd ab22 strd sl, fp, [sp, #136] ; 0x88 + 26b86: f64f 7aff movw sl, #65535 ; 0xffff + 26b8a: f241 5cd1 movw ip, #5585 ; 0x15d1 + 26b8e: f2c0 0a1f movt sl, #31 + 26b92: f2c0 0c02 movt ip, #2 + 26b96: f8dd 909c ldr.w r9, [sp, #156] ; 0x9c + 26b9a: 7b46 ldrb r6, [r0, #13] + 26b9c: f8dd 8098 ldr.w r8, [sp, #152] ; 0x98 + 26ba0: 2200 movs r2, #0 + 26ba2: 2300 movs r3, #0 + 26ba4: 2700 movs r7, #0 + 26ba6: e9cd 2314 strd r2, r3, [sp, #80] ; 0x50 + 26baa: e9cd 6728 strd r6, r7, [sp, #160] ; 0xa0 + 26bae: 9a08 ldr r2, [sp, #32] + 26bb0: ea4f 0799 mov.w r7, r9, lsr #2 + 26bb4: 9b06 ldr r3, [sp, #24] + 26bb6: f04f 0b00 mov.w fp, #0 + 26bba: ea0b 0b07 and.w fp, fp, r7 + 26bbe: 9c09 ldr r4, [sp, #36] ; 0x24 + 26bc0: 9d08 ldr r5, [sp, #32] + 26bc2: 9f20 ldr r7, [sp, #128] ; 0x80 + 26bc4: ea4f 0698 mov.w r6, r8, lsr #2 + 26bc8: ea46 7689 orr.w r6, r6, r9, lsl #30 + 26bcc: 4252 negs r2, r2 + 26bce: 425b negs r3, r3 + 26bd0: ea0a 0a06 and.w sl, sl, r6 + 26bd4: 9201 str r2, [sp, #4] + 26bd6: fb0e 2604 mla r6, lr, r4, r2 + 26bda: 9302 str r3, [sp, #8] + 26bdc: 08ff lsrs r7, r7, #3 + 26bde: fba5 230e umull r2, r3, r5, lr + 26be2: ad42 add r5, sp, #264 ; 0x108 + 26be4: 9714 str r7, [sp, #80] ; 0x50 + 26be6: e9d5 8900 ldrd r8, r9, [r5] + 26bea: e9dd 451e ldrd r4, r5, [sp, #120] ; 0x78 + 26bee: ea48 0804 orr.w r8, r8, r4 + 26bf2: ea49 0905 orr.w r9, r9, r5 + 26bf6: e9cd 891e strd r8, r9, [sp, #120] ; 0x78 + 26bfa: f8dd 9084 ldr.w r9, [sp, #132] ; 0x84 + 26bfe: f8dd 8050 ldr.w r8, [sp, #80] ; 0x50 + 26c02: 9f04 ldr r7, [sp, #16] + 26c04: ea48 7849 orr.w r8, r8, r9, lsl #29 + 26c08: f8cd 8050 str.w r8, [sp, #80] ; 0x50 + 26c0c: 4433 add r3, r6 + 26c0e: 9d05 ldr r5, [sp, #20] + 26c10: 9e07 ldr r6, [sp, #28] + 26c12: f8dd 8008 ldr.w r8, [sp, #8] + 26c16: 09bf lsrs r7, r7, #6 + 26c18: ea47 6485 orr.w r4, r7, r5, lsl #26 + 26c1c: fb0e 8706 mla r7, lr, r6, r8 + 26c20: 9e06 ldr r6, [sp, #24] + 26c22: 9416 str r4, [sp, #88] ; 0x58 + 26c24: 09ac lsrs r4, r5, #6 + 26c26: 9417 str r4, [sp, #92] ; 0x5c + 26c28: fba6 450c umull r4, r5, r6, ip + 26c2c: f8dd 801c ldr.w r8, [sp, #28] + 26c30: ea4f 09d9 mov.w r9, r9, lsr #3 + 26c34: f8cd 9054 str.w r9, [sp, #84] ; 0x54 + 26c38: fb0c 5508 mla r5, ip, r8, r5 + 26c3c: e9dd 8938 ldrd r8, r9, [sp, #224] ; 0xe0 + 26c40: eb18 0802 adds.w r8, r8, r2 + 26c44: 9a06 ldr r2, [sp, #24] + 26c46: eb49 0903 adc.w r9, r9, r3 + 26c4a: ae46 add r6, sp, #280 ; 0x118 + 26c4c: e9c6 8900 strd r8, r9, [r6] + 26c50: fba2 890e umull r8, r9, r2, lr + 26c54: 9e0a ldr r6, [sp, #40] ; 0x28 + 26c56: 44b9 add r9, r7 + 26c58: fba6 230c umull r2, r3, r6, ip + 26c5c: 9f0b ldr r7, [sp, #44] ; 0x2c + 26c5e: f249 0183 movw r1, #36995 ; 0x9083 + 26c62: fb0c 3307 mla r3, ip, r7, r3 + 26c66: e9dd 673c ldrd r6, r7, [sp, #240] ; 0xf0 + 26c6a: eb16 0608 adds.w r6, r6, r8 + 26c6e: eb47 0709 adc.w r7, r7, r9 + 26c72: e9cd 6738 strd r6, r7, [sp, #224] ; 0xe0 + 26c76: e9dd 8934 ldrd r8, r9, [sp, #208] ; 0xd0 + 26c7a: 9f1a ldr r7, [sp, #104] ; 0x68 + 26c7c: eb18 0804 adds.w r8, r8, r4 + 26c80: eb49 0905 adc.w r9, r9, r5 + 26c84: ae42 add r6, sp, #264 ; 0x108 + 26c86: fba7 450c umull r4, r5, r7, ip + 26c8a: e9c6 8900 strd r8, r9, [r6] + 26c8e: e9dd 672a ldrd r6, r7, [sp, #168] ; 0xa8 + 26c92: 18b6 adds r6, r6, r2 + 26c94: 415f adcs r7, r3 + 26c96: f8dd 8060 ldr.w r8, [sp, #96] ; 0x60 + 26c9a: e9cd 673e strd r6, r7, [sp, #248] ; 0xf8 + 26c9e: 9f0c ldr r7, [sp, #48] ; 0x30 + 26ca0: fb0c 5508 mla r5, ip, r8, r5 + 26ca4: fba7 230c umull r2, r3, r7, ip + 26ca8: e9dd 6714 ldrd r6, r7, [sp, #80] ; 0x50 + 26cac: f8dd 8034 ldr.w r8, [sp, #52] ; 0x34 + 26cb0: 1936 adds r6, r6, r4 + 26cb2: fb0c 3308 mla r3, ip, r8, r3 + 26cb6: 416f adcs r7, r5 + 26cb8: f8dd 8048 ldr.w r8, [sp, #72] ; 0x48 + 26cbc: e9cd 673a strd r6, r7, [sp, #232] ; 0xe8 + 26cc0: 9f08 ldr r7, [sp, #32] + 26cc2: f8dd 9024 ldr.w r9, [sp, #36] ; 0x24 + 26cc6: fba7 4508 umull r4, r5, r7, r8 + 26cca: e9dd 6722 ldrd r6, r7, [sp, #136] ; 0x88 + 26cce: 18b6 adds r6, r6, r2 + 26cd0: 415f adcs r7, r3 + 26cd2: e9cd 673c strd r6, r7, [sp, #240] ; 0xf0 + 26cd6: 9f06 ldr r7, [sp, #24] + 26cd8: fb08 5509 mla r5, r8, r9, r5 + 26cdc: fba7 2308 umull r2, r3, r7, r8 + 26ce0: f8dd 901c ldr.w r9, [sp, #28] + 26ce4: f6cf 71f5 movt r1, #65525 ; 0xfff5 + 26ce8: fb08 3309 mla r3, r8, r9, r3 + 26cec: f64f 78ff movw r8, #65535 ; 0xffff + 26cf0: f2c0 081f movt r8, #31 + 26cf4: f50d 7988 add.w r9, sp, #272 ; 0x110 + 26cf8: e9d9 6700 ldrd r6, r7, [r9] + 26cfc: f04f 0900 mov.w r9, #0 + 26d00: ea06 0608 and.w r6, r6, r8 + 26d04: ea07 0709 and.w r7, r7, r9 + 26d08: f50d 7880 add.w r8, sp, #256 ; 0x100 + 26d0c: e9cd 6736 strd r6, r7, [sp, #216] ; 0xd8 + 26d10: e9d8 6700 ldrd r6, r7, [r8] + 26d14: 1936 adds r6, r6, r4 + 26d16: 416f adcs r7, r5 + 26d18: f50d 7888 add.w r8, sp, #272 ; 0x110 + 26d1c: e9dd 452e ldrd r4, r5, [sp, #184] ; 0xb8 + 26d20: 18a4 adds r4, r4, r2 + 26d22: e9c8 6700 strd r6, r7, [r8] + 26d26: 415d adcs r5, r3 + 26d28: ae40 add r6, sp, #256 ; 0x100 + 26d2a: e9c6 4500 strd r4, r5, [r6] + 26d2e: e9dd 4516 ldrd r4, r5, [sp, #88] ; 0x58 + 26d32: f64f 76ff movw r6, #65535 ; 0xffff + 26d36: f2c0 061f movt r6, #31 + 26d3a: 2700 movs r7, #0 + 26d3c: 4034 ands r4, r6 + 26d3e: f890 602e ldrb.w r6, [r0, #46] ; 0x2e + 26d42: 403d ands r5, r7 + 26d44: 2700 movs r7, #0 + 26d46: e9cd 452a strd r4, r5, [sp, #168] ; 0xa8 + 26d4a: e9cd 6734 strd r6, r7, [sp, #208] ; 0xd0 + 26d4e: 9d07 ldr r5, [sp, #28] + 26d50: 9e02 ldr r6, [sp, #8] + 26d52: aa48 add r2, sp, #288 ; 0x120 + 26d54: fb01 6505 mla r5, r1, r5, r6 + 26d58: e9d2 8900 ldrd r8, r9, [r2] + 26d5c: e9dd 2328 ldrd r2, r3, [sp, #160] ; 0xa0 + 26d60: ea48 0802 orr.w r8, r8, r2 + 26d64: ea49 0903 orr.w r9, r9, r3 + 26d68: f890 202d ldrb.w r2, [r0, #45] ; 0x2d + 26d6c: ab48 add r3, sp, #288 ; 0x120 + 26d6e: e9c3 8900 strd r8, r9, [r3] + 26d72: 2300 movs r3, #0 + 26d74: e9cd 232e strd r2, r3, [sp, #184] ; 0xb8 + 26d78: 9c01 ldr r4, [sp, #4] + 26d7a: 9b09 ldr r3, [sp, #36] ; 0x24 + 26d7c: 9504 str r5, [sp, #16] + 26d7e: 9d06 ldr r5, [sp, #24] + 26d80: 9a08 ldr r2, [sp, #32] + 26d82: fb01 4303 mla r3, r1, r3, r4 + 26d86: fba5 4501 umull r4, r5, r5, r1 + 26d8a: fba2 890c umull r8, r9, r2, ip + 26d8e: 9f0b ldr r7, [sp, #44] ; 0x2c + 26d90: 9a32 ldr r2, [sp, #200] ; 0xc8 + 26d92: e9cd 4526 strd r4, r5, [sp, #152] ; 0x98 + 26d96: 9e0d ldr r6, [sp, #52] ; 0x34 + 26d98: 9c0c ldr r4, [sp, #48] ; 0x30 + 26d9a: 9322 str r3, [sp, #136] ; 0x88 + 26d9c: 9d0a ldr r5, [sp, #40] ; 0x28 + 26d9e: fb01 2307 mla r3, r1, r7, r2 + 26da2: 9f30 ldr r7, [sp, #192] ; 0xc0 + 26da4: fb01 7206 mla r2, r1, r6, r7 + 26da8: fba4 6701 umull r6, r7, r4, r1 + 26dac: fba5 4501 umull r4, r5, r5, r1 + 26db0: e9cd 4506 strd r4, r5, [sp, #24] + 26db4: 9d2c ldr r5, [sp, #176] ; 0xb0 + 26db6: 9c18 ldr r4, [sp, #96] ; 0x60 + 26db8: 4417 add r7, r2 + 26dba: fb01 5404 mla r4, r1, r4, r5 + 26dbe: 940c str r4, [sp, #48] ; 0x30 + 26dc0: 9c09 ldr r4, [sp, #36] ; 0x24 + 26dc2: 9d1e ldr r5, [sp, #120] ; 0x78 + 26dc4: fb0c 9904 mla r9, ip, r4, r9 + 26dc8: 9c1f ldr r4, [sp, #124] ; 0x7c + 26dca: 08ed lsrs r5, r5, #3 + 26dcc: ea45 7444 orr.w r4, r5, r4, lsl #29 + 26dd0: 9414 str r4, [sp, #80] ; 0x50 + 26dd2: 9c27 ldr r4, [sp, #156] ; 0x9c + 26dd4: 9d04 ldr r5, [sp, #16] + 26dd6: 9a1f ldr r2, [sp, #124] ; 0x7c + 26dd8: 442c add r4, r5 + 26dda: 9d07 ldr r5, [sp, #28] + 26ddc: 9427 str r4, [sp, #156] ; 0x9c + 26dde: 441d add r5, r3 + 26de0: 9507 str r5, [sp, #28] + 26de2: e9dd 4538 ldrd r4, r5, [sp, #224] ; 0xe0 + 26de6: eb14 0408 adds.w r4, r4, r8 + 26dea: f8dd 8020 ldr.w r8, [sp, #32] + 26dee: eb45 0509 adc.w r5, r5, r9 + 26df2: e9cd 451e strd r4, r5, [sp, #120] ; 0x78 + 26df6: fba8 4501 umull r4, r5, r8, r1 + 26dfa: f8dd 9088 ldr.w r9, [sp, #136] ; 0x88 + 26dfe: f50d 7884 add.w r8, sp, #264 ; 0x108 + 26e02: 08d2 lsrs r2, r2, #3 + 26e04: 9215 str r2, [sp, #84] ; 0x54 + 26e06: 444d add r5, r9 + 26e08: e9d8 2300 ldrd r2, r3, [r8] + 26e0c: 1912 adds r2, r2, r4 + 26e0e: 416b adcs r3, r5 + 26e10: e9cd 2322 strd r2, r3, [sp, #136] ; 0x88 + 26e14: e9dd 8926 ldrd r8, r9, [sp, #152] ; 0x98 + 26e18: 9b08 ldr r3, [sp, #32] + 26e1a: 9a10 ldr r2, [sp, #64] ; 0x40 + 26e1c: 9c09 ldr r4, [sp, #36] ; 0x24 + 26e1e: fba3 2302 umull r2, r3, r3, r2 + 26e22: 9d10 ldr r5, [sp, #64] ; 0x40 + 26e24: e9cd 230a strd r2, r3, [sp, #40] ; 0x28 + 26e28: fb05 3304 mla r3, r5, r4, r3 + 26e2c: 9d08 ldr r5, [sp, #32] + 26e2e: 9c0e ldr r4, [sp, #56] ; 0x38 + 26e30: 930b str r3, [sp, #44] ; 0x2c + 26e32: fba5 4504 umull r4, r5, r5, r4 + 26e36: e9dd 233e ldrd r2, r3, [sp, #248] ; 0xf8 + 26e3a: eb18 0802 adds.w r8, r8, r2 + 26e3e: eb49 0903 adc.w r9, r9, r3 + 26e42: ab42 add r3, sp, #264 ; 0x108 + 26e44: e9c3 8900 strd r8, r9, [r3] + 26e48: f8dd 8024 ldr.w r8, [sp, #36] ; 0x24 + 26e4c: f8dd 9038 ldr.w r9, [sp, #56] ; 0x38 + 26e50: e9cd 4530 strd r4, r5, [sp, #192] ; 0xc0 + 26e54: fb09 5508 mla r5, r9, r8, r5 + 26e58: fbaa 230c umull r2, r3, sl, ip + 26e5c: 9531 str r5, [sp, #196] ; 0xc4 + 26e5e: e9dd 453a ldrd r4, r5, [sp, #232] ; 0xe8 + 26e62: 19a4 adds r4, r4, r6 + 26e64: e9cd 2308 strd r2, r3, [sp, #32] + 26e68: 417d adcs r5, r7 + 26e6a: fb0c 330b mla r3, ip, fp, r3 + 26e6e: fbaa 6709 umull r6, r7, sl, r9 + 26e72: 9309 str r3, [sp, #36] ; 0x24 + 26e74: fb09 770b mla r7, r9, fp, r7 + 26e78: e9dd 233c ldrd r2, r3, [sp, #240] ; 0xf0 + 26e7c: e9dd 8906 ldrd r8, r9, [sp, #24] + 26e80: eb18 0802 adds.w r8, r8, r2 + 26e84: eb49 0903 adc.w r9, r9, r3 + 26e88: e9cd 4538 strd r4, r5, [sp, #224] ; 0xe0 + 26e8c: e9cd 892c strd r8, r9, [sp, #176] ; 0xb0 + 26e90: 9c1a ldr r4, [sp, #104] ; 0x68 + 26e92: f8dd 8040 ldr.w r8, [sp, #64] ; 0x40 + 26e96: fba4 2301 umull r2, r3, r4, r1 + 26e9a: fbaa 4508 umull r4, r5, sl, r8 + 26e9e: f8dd 9030 ldr.w r9, [sp, #48] ; 0x30 + 26ea2: fb08 550b mla r5, r8, fp, r5 + 26ea6: 444b add r3, r9 + 26ea8: e9dd 8936 ldrd r8, r9, [sp, #216] ; 0xd8 + 26eac: eb18 0802 adds.w r8, r8, r2 + 26eb0: eb49 0903 adc.w r9, r9, r3 + 26eb4: e9cd 8926 strd r8, r9, [sp, #152] ; 0x98 + 26eb8: e9dd 230a ldrd r2, r3, [sp, #40] ; 0x28 + 26ebc: f50d 7980 add.w r9, sp, #256 ; 0x100 + 26ec0: e9d9 8900 ldrd r8, r9, [r9] + 26ec4: eb12 0208 adds.w r2, r2, r8 + 26ec8: eb43 0309 adc.w r3, r3, r9 + 26ecc: e9cd 2318 strd r2, r3, [sp, #96] ; 0x60 + 26ed0: e9dd 8930 ldrd r8, r9, [sp, #192] ; 0xc0 + 26ed4: e9dd 2314 ldrd r2, r3, [sp, #80] ; 0x50 + 26ed8: eb12 0208 adds.w r2, r2, r8 + 26edc: eb43 0309 adc.w r3, r3, r9 + 26ee0: f50d 7890 add.w r8, sp, #288 ; 0x120 + 26ee4: e9cd 231a strd r2, r3, [sp, #104] ; 0x68 + 26ee8: e9d8 2300 ldrd r2, r3, [r8] + 26eec: 085b lsrs r3, r3, #1 + 26eee: ea4f 0232 mov.w r2, r2, rrx + 26ef2: f50d 798c add.w r9, sp, #280 ; 0x118 + 26ef6: e9c8 2300 strd r2, r3, [r8] + 26efa: e9dd 232a ldrd r2, r3, [sp, #168] ; 0xa8 + 26efe: e9d9 8900 ldrd r8, r9, [r9] + 26f02: 1992 adds r2, r2, r6 + 26f04: 417b adcs r3, r7 + 26f06: e9dd 6708 ldrd r6, r7, [sp, #32] + 26f0a: eb16 0608 adds.w r6, r6, r8 + 26f0e: eb47 0709 adc.w r7, r7, r9 + 26f12: e9cd 6732 strd r6, r7, [sp, #200] ; 0xc8 + 26f16: ae44 add r6, sp, #272 ; 0x110 + 26f18: e9cd 232a strd r2, r3, [sp, #168] ; 0xa8 + 26f1c: e9d6 2300 ldrd r2, r3, [r6] + 26f20: 1912 adds r2, r2, r4 + 26f22: 416b adcs r3, r5 + 26f24: f8dd 90b8 ldr.w r9, [sp, #184] ; 0xb8 + 26f28: e9cd 2330 strd r2, r3, [sp, #192] ; 0xc0 + 26f2c: 9a34 ldr r2, [sp, #208] ; 0xd0 + 26f2e: f8dd 80d0 ldr.w r8, [sp, #208] ; 0xd0 + 26f32: ea4f 2909 mov.w r9, r9, lsl #8 + 26f36: f8cd 9058 str.w r9, [sp, #88] ; 0x58 + 26f3a: 0412 lsls r2, r2, #16 + 26f3c: f8dd 9048 ldr.w r9, [sp, #72] ; 0x48 + 26f40: 9220 str r2, [sp, #128] ; 0x80 + 26f42: 9f2e ldr r7, [sp, #184] ; 0xb8 + 26f44: f1ca 0200 rsb r2, sl, #0 + 26f48: ea4f 4818 mov.w r8, r8, lsr #16 + 26f4c: fb01 230b mla r3, r1, fp, r2 + 26f50: f8cd 8084 str.w r8, [sp, #132] ; 0x84 + 26f54: fbaa 8909 umull r8, r9, sl, r9 + 26f58: 0e3f lsrs r7, r7, #24 + 26f5a: 9717 str r7, [sp, #92] ; 0x5c + 26f5c: e9dd 4516 ldrd r4, r5, [sp, #88] ; 0x58 + 26f60: e9dd 6720 ldrd r6, r7, [sp, #128] ; 0x80 + 26f64: 4334 orrs r4, r6 + 26f66: 433d orrs r5, r7 + 26f68: e9cd 4516 strd r4, r5, [sp, #88] ; 0x58 + 26f6c: e9cd 890c strd r8, r9, [sp, #48] ; 0x30 + 26f70: 9314 str r3, [sp, #80] ; 0x50 + 26f72: 9d0d ldr r5, [sp, #52] ; 0x34 + 26f74: 9c12 ldr r4, [sp, #72] ; 0x48 + 26f76: fb0e 220b mla r2, lr, fp, r2 + 26f7a: fb04 540b mla r4, r4, fp, r5 + 26f7e: fbaa 8901 umull r8, r9, sl, r1 + 26f82: fbaa 670e umull r6, r7, sl, lr + 26f86: e9dd ab32 ldrd sl, fp, [sp, #200] ; 0xc8 + 26f8a: f51a 1a80 adds.w sl, sl, #1048576 ; 0x100000 + 26f8e: 9208 str r2, [sp, #32] + 26f90: f14b 0b00 adc.w fp, fp, #0 + 26f94: e9cd ab20 strd sl, fp, [sp, #128] ; 0x80 + 26f98: e9dd 232a ldrd r2, r3, [sp, #168] ; 0xa8 + 26f9c: 940d str r4, [sp, #52] ; 0x34 + 26f9e: f8dd b050 ldr.w fp, [sp, #80] ; 0x50 + 26fa2: f8dd a020 ldr.w sl, [sp, #32] + 26fa6: e9dd 4530 ldrd r4, r5, [sp, #192] ; 0xc0 + 26faa: f514 1480 adds.w r4, r4, #1048576 ; 0x100000 + 26fae: f145 0500 adc.w r5, r5, #0 + 26fb2: f512 1280 adds.w r2, r2, #1048576 ; 0x100000 + 26fb6: f143 0300 adc.w r3, r3, #0 + 26fba: 44d9 add r9, fp + 26fbc: 4457 add r7, sl + 26fbe: e9dd ab1e ldrd sl, fp, [sp, #120] ; 0x78 + 26fc2: eb1a 0a08 adds.w sl, sl, r8 + 26fc6: eb4b 0b09 adc.w fp, fp, r9 + 26fca: e9cd ab14 strd sl, fp, [sp, #80] ; 0x50 + 26fce: e9dd ab18 ldrd sl, fp, [sp, #96] ; 0x60 + 26fd2: e9dd 891a ldrd r8, r9, [sp, #104] ; 0x68 + 26fd6: eb1a 0a06 adds.w sl, sl, r6 + 26fda: eb4b 0b07 adc.w fp, fp, r7 + 26fde: e9dd 670c ldrd r6, r7, [sp, #48] ; 0x30 + 26fe2: eb16 0608 adds.w r6, r6, r8 + 26fe6: eb47 0709 adc.w r7, r7, r9 + 26fea: e9cd 670c strd r6, r7, [sp, #48] ; 0x30 + 26fee: e9dd 8916 ldrd r8, r9, [sp, #88] ; 0x58 + 26ff2: 7ac6 ldrb r6, [r0, #11] + 26ff4: 2700 movs r7, #0 + 26ff6: e9cd 673e strd r6, r7, [sp, #248] ; 0xf8 + 26ffa: 9f20 ldr r7, [sp, #128] ; 0x80 + 26ffc: e9cd ab18 strd sl, fp, [sp, #96] ; 0x60 + 27000: e9dd ab1c ldrd sl, fp, [sp, #112] ; 0x70 + 27004: ea48 080a orr.w r8, r8, sl + 27008: f890 a00c ldrb.w sl, [r0, #12] + 2700c: ea49 090b orr.w r9, r9, fp + 27010: ae40 add r6, sp, #256 ; 0x100 + 27012: f04f 0b00 mov.w fp, #0 + 27016: 0d7f lsrs r7, r7, #21 + 27018: e9c6 ab00 strd sl, fp, [r6] + 2701c: 463e mov r6, r7 + 2701e: 9f21 ldr r7, [sp, #132] ; 0x84 + 27020: ea4f 5a54 mov.w sl, r4, lsr #21 + 27024: ea46 26c7 orr.w r6, r6, r7, lsl #11 + 27028: 960a str r6, [sp, #40] ; 0x28 + 2702a: 157e asrs r6, r7, #21 + 2702c: 960b str r6, [sp, #44] ; 0x2c + 2702e: ea4a 2ac5 orr.w sl, sl, r5, lsl #11 + 27032: ea4f 5b52 mov.w fp, r2, lsr #21 + 27036: f8cd a018 str.w sl, [sp, #24] + 2703a: ea4b 2bc3 orr.w fp, fp, r3, lsl #11 + 2703e: 156f asrs r7, r5, #21 + 27040: ea4f 5a63 mov.w sl, r3, asr #21 + 27044: e9dd 450a ldrd r4, r5, [sp, #40] ; 0x28 + 27048: e9dd 2314 ldrd r2, r3, [sp, #80] ; 0x50 + 2704c: 1912 adds r2, r2, r4 + 2704e: 416b adcs r3, r5 + 27050: f8cd b020 str.w fp, [sp, #32] + 27054: 9707 str r7, [sp, #28] + 27056: f8cd a024 str.w sl, [sp, #36] ; 0x24 + 2705a: e9cd 2336 strd r2, r3, [sp, #216] ; 0xd8 + 2705e: e9dd 6722 ldrd r6, r7, [sp, #136] ; 0x88 + 27062: e9dd 2306 ldrd r2, r3, [sp, #24] + 27066: f516 1680 adds.w r6, r6, #1048576 ; 0x100000 + 2706a: e9dd ab18 ldrd sl, fp, [sp, #96] ; 0x60 + 2706e: f147 0700 adc.w r7, r7, #0 + 27072: eb1a 0a02 adds.w sl, sl, r2 + 27076: eb4b 0b03 adc.w fp, fp, r3 + 2707a: e9cd ab34 strd sl, fp, [sp, #208] ; 0xd0 + 2707e: e9dd 450c ldrd r4, r5, [sp, #48] ; 0x30 + 27082: f8dd a090 ldr.w sl, [sp, #144] ; 0x90 + 27086: e9cd 6716 strd r6, r7, [sp, #88] ; 0x58 + 2708a: e9dd 6708 ldrd r6, r7, [sp, #32] + 2708e: 19a4 adds r4, r4, r6 + 27090: 417d adcs r5, r7 + 27092: ea4f 660a mov.w r6, sl, lsl #24 + 27096: ea4f 271a mov.w r7, sl, lsr #8 + 2709a: ea47 0709 orr.w r7, r7, r9 + 2709e: ea46 0608 orr.w r6, r6, r8 + 270a2: f04f 0900 mov.w r9, #0 + 270a6: f04f 0800 mov.w r8, #0 + 270aa: 4642 mov r2, r8 + 270ac: 464b mov r3, r9 + 270ae: 46c2 mov sl, r8 + 270b0: 46cb mov fp, r9 + 270b2: e9cd 2324 strd r2, r3, [sp, #144] ; 0x90 + 270b6: 7a02 ldrb r2, [r0, #8] + 270b8: 2300 movs r3, #0 + 270ba: e9cd 233a strd r2, r3, [sp, #232] ; 0xe8 + 270be: 7a82 ldrb r2, [r0, #10] + 270c0: e9cd 452e strd r4, r5, [sp, #184] ; 0xb8 + 270c4: e9dd 452c ldrd r4, r5, [sp, #176] ; 0xb0 + 270c8: 2300 movs r3, #0 + 270ca: f514 1480 adds.w r4, r4, #1048576 ; 0x100000 + 270ce: e9cd 231e strd r2, r3, [sp, #120] ; 0x78 + 270d2: f145 0500 adc.w r5, r5, #0 + 270d6: 9b16 ldr r3, [sp, #88] ; 0x58 + 270d8: e9cd 451c strd r4, r5, [sp, #112] ; 0x70 + 270dc: e9cd ab04 strd sl, fp, [sp, #16] + 270e0: ea4f 5a53 mov.w sl, r3, lsr #21 + 270e4: 9b1c ldr r3, [sp, #112] ; 0x70 + 270e6: 9a07 ldr r2, [sp, #28] + 270e8: e9cd 890c strd r8, r9, [sp, #48] ; 0x30 + 270ec: 9d0b ldr r5, [sp, #44] ; 0x2c + 270ee: f890 8009 ldrb.w r8, [r0, #9] + 270f2: 0d5b lsrs r3, r3, #21 + 270f4: 930c str r3, [sp, #48] ; 0x30 + 270f6: f04f 0900 mov.w r9, #0 + 270fa: 9b0a ldr r3, [sp, #40] ; 0x28 + 270fc: 0552 lsls r2, r2, #21 + 270fe: 9225 str r2, [sp, #148] ; 0x94 + 27100: e9cd 893c strd r8, r9, [sp, #240] ; 0xf0 + 27104: 0972 lsrs r2, r6, #5 + 27106: ea4f 5945 mov.w r9, r5, lsl #21 + 2710a: 9204 str r2, [sp, #16] + 2710c: ea49 29d3 orr.w r9, r9, r3, lsr #11 + 27110: 9a25 ldr r2, [sp, #148] ; 0x94 + 27112: 9b06 ldr r3, [sp, #24] + 27114: 9c17 ldr r4, [sp, #92] ; 0x5c + 27116: ea42 22d3 orr.w r2, r2, r3, lsr #11 + 2711a: 9225 str r2, [sp, #148] ; 0x94 + 2711c: 9b1d ldr r3, [sp, #116] ; 0x74 + 2711e: 9a0c ldr r2, [sp, #48] ; 0x30 + 27120: ea4a 2ac4 orr.w sl, sl, r4, lsl #11 + 27124: ea42 22c3 orr.w r2, r2, r3, lsl #11 + 27128: 920c str r2, [sp, #48] ; 0x30 + 2712a: 9a04 ldr r2, [sp, #16] + 2712c: 9b0a ldr r3, [sp, #40] ; 0x28 + 2712e: ea42 62c7 orr.w r2, r2, r7, lsl #27 + 27132: 9204 str r2, [sp, #16] + 27134: ea4f 5843 mov.w r8, r3, lsl #21 + 27138: e9dd 2336 ldrd r2, r3, [sp, #216] ; 0xd8 + 2713c: f512 1280 adds.w r2, r2, #1048576 ; 0x100000 + 27140: f143 0300 adc.w r3, r3, #0 + 27144: e9cd 2320 strd r2, r3, [sp, #128] ; 0x80 + 27148: 9b06 ldr r3, [sp, #24] + 2714a: 9a1d ldr r2, [sp, #116] ; 0x74 + 2714c: 055b lsls r3, r3, #21 + 2714e: 9324 str r3, [sp, #144] ; 0x90 + 27150: 1552 asrs r2, r2, #21 + 27152: 097b lsrs r3, r7, #5 + 27154: e9dd 6732 ldrd r6, r7, [sp, #200] ; 0xc8 + 27158: ebb6 0608 subs.w r6, r6, r8 + 2715c: 920d str r2, [sp, #52] ; 0x34 + 2715e: eb67 0709 sbc.w r7, r7, r9 + 27162: aa44 add r2, sp, #272 ; 0x110 + 27164: e9c2 6700 strd r6, r7, [r2] + 27168: e9dd 6734 ldrd r6, r7, [sp, #208] ; 0xd0 + 2716c: aa42 add r2, sp, #264 ; 0x108 + 2716e: e9d2 8900 ldrd r8, r9, [r2] + 27172: ea4f 5b64 mov.w fp, r4, asr #21 + 27176: eb18 080a adds.w r8, r8, sl + 2717a: eb49 090b adc.w r9, r9, fp + 2717e: ea4f 544a mov.w r4, sl, lsl #21 + 27182: f516 1680 adds.w r6, r6, #1048576 ; 0x100000 + 27186: ea4f 554b mov.w r5, fp, lsl #21 + 2718a: ea45 25da orr.w r5, r5, sl, lsr #11 + 2718e: e9cd 8932 strd r8, r9, [sp, #200] ; 0xc8 + 27192: e9dd 8922 ldrd r8, r9, [sp, #136] ; 0x88 + 27196: f147 0700 adc.w r7, r7, #0 + 2719a: ebb8 0804 subs.w r8, r8, r4 + 2719e: 9305 str r3, [sp, #20] + 271a0: eb69 0905 sbc.w r9, r9, r5 + 271a4: e9dd 2330 ldrd r2, r3, [sp, #192] ; 0xc0 + 271a8: e9dd 4524 ldrd r4, r5, [sp, #144] ; 0x90 + 271ac: 1b12 subs r2, r2, r4 + 271ae: eb63 0305 sbc.w r3, r3, r5 + 271b2: ad42 add r5, sp, #264 ; 0x108 + 271b4: e9c5 2300 strd r2, r3, [r5] + 271b8: e9dd 4504 ldrd r4, r5, [sp, #16] + 271bc: f64f 72ff movw r2, #65535 ; 0xffff + 271c0: f2c0 021f movt r2, #31 + 271c4: e9cd 6716 strd r6, r7, [sp, #88] ; 0x58 + 271c8: e9dd 672e ldrd r6, r7, [sp, #184] ; 0xb8 + 271cc: f516 1680 adds.w r6, r6, #1048576 ; 0x100000 + 271d0: f147 0700 adc.w r7, r7, #0 + 271d4: 2300 movs r3, #0 + 271d6: e9cd 6724 strd r6, r7, [sp, #144] ; 0x90 + 271da: f50d 7a8c add.w sl, sp, #280 ; 0x118 + 271de: 402b ands r3, r5 + 271e0: 9e3c ldr r6, [sp, #240] ; 0xf0 + 271e2: 9d3a ldr r5, [sp, #232] ; 0xe8 + 271e4: 9f3a ldr r7, [sp, #232] ; 0xe8 + 271e6: e9ca 8900 strd r8, r9, [sl] + 271ea: e9dd ab0c ldrd sl, fp, [sp, #48] ; 0x30 + 271ee: e9dd 8938 ldrd r8, r9, [sp, #224] ; 0xe0 + 271f2: 4022 ands r2, r4 + 271f4: eb18 080a adds.w r8, r8, sl + 271f8: eb49 090b adc.w r9, r9, fp + 271fc: e9cd 2330 strd r2, r3, [sp, #192] ; 0xc0 + 27200: 0e2d lsrs r5, r5, #24 + 27202: 2200 movs r2, #0 + 27204: 2300 movs r3, #0 + 27206: 0c36 lsrs r6, r6, #16 + 27208: 023f lsls r7, r7, #8 + 2720a: e9cd 8922 strd r8, r9, [sp, #136] ; 0x88 + 2720e: 951b str r5, [sp, #108] ; 0x6c + 27210: 9619 str r6, [sp, #100] ; 0x64 + 27212: 971a str r7, [sp, #104] ; 0x68 + 27214: 4616 mov r6, r2 + 27216: e9dd ab26 ldrd sl, fp, [sp, #152] ; 0x98 + 2721a: 461f mov r7, r3 + 2721c: e9dd 231a ldrd r2, r3, [sp, #104] ; 0x68 + 27220: f8dd 80f0 ldr.w r8, [sp, #240] ; 0xf0 + 27224: 46b9 mov r9, r7 + 27226: ea4f 4808 mov.w r8, r8, lsl #16 + 2722a: f8cd 8060 str.w r8, [sp, #96] ; 0x60 + 2722e: 46b0 mov r8, r6 + 27230: e9dd 4518 ldrd r4, r5, [sp, #96] ; 0x60 + 27234: 4322 orrs r2, r4 + 27236: 432b orrs r3, r5 + 27238: e9cd 2338 strd r2, r3, [sp, #224] ; 0xe0 + 2723c: 4632 mov r2, r6 + 2723e: 463b mov r3, r7 + 27240: 4634 mov r4, r6 + 27242: 463d mov r5, r7 + 27244: e9cd 890a strd r8, r9, [sp, #40] ; 0x28 + 27248: f8dd 9090 ldr.w r9, [sp, #144] ; 0x90 + 2724c: e9cd 673a strd r6, r7, [sp, #232] ; 0xe8 + 27250: e9cd 6718 strd r6, r7, [sp, #96] ; 0x60 + 27254: 9f20 ldr r7, [sp, #128] ; 0x80 + 27256: e9cd 2314 strd r2, r3, [sp, #80] ; 0x50 + 2725a: f8dd 8058 ldr.w r8, [sp, #88] ; 0x58 + 2725e: ea4f 5259 mov.w r2, r9, lsr #21 + 27262: f8dd 9084 ldr.w r9, [sp, #132] ; 0x84 + 27266: 0d7f lsrs r7, r7, #21 + 27268: e9cd 451a strd r4, r5, [sp, #104] ; 0x68 + 2726c: ea4f 5458 mov.w r4, r8, lsr #21 + 27270: ea47 28c9 orr.w r8, r7, r9, lsl #11 + 27274: f8cd 8018 str.w r8, [sp, #24] + 27278: f8dd 805c ldr.w r8, [sp, #92] ; 0x5c + 2727c: f8dd 9094 ldr.w r9, [sp, #148] ; 0x94 + 27280: ea44 24c8 orr.w r4, r4, r8, lsl #11 + 27284: f8dd 8084 ldr.w r8, [sp, #132] ; 0x84 + 27288: ea42 22c9 orr.w r2, r2, r9, lsl #11 + 2728c: f51a 1a80 adds.w sl, sl, #1048576 ; 0x100000 + 27290: f8dd 905c ldr.w r9, [sp, #92] ; 0x5c + 27294: ea4f 5868 mov.w r8, r8, asr #21 + 27298: f14b 0b00 adc.w fp, fp, #0 + 2729c: f8cd 801c str.w r8, [sp, #28] + 272a0: ea4f 565a mov.w r6, sl, lsr #21 + 272a4: f890 8007 ldrb.w r8, [r0, #7] + 272a8: f890 a006 ldrb.w sl, [r0, #6] + 272ac: ea46 26cb orr.w r6, r6, fp, lsl #11 + 272b0: ea4f 5569 mov.w r5, r9, asr #21 + 272b4: ea4f 576b mov.w r7, fp, asr #21 + 272b8: f04f 0900 mov.w r9, #0 + 272bc: f04f 0b00 mov.w fp, #0 + 272c0: e9cd 8916 strd r8, r9, [sp, #88] ; 0x58 + 272c4: e9cd ab20 strd sl, fp, [sp, #128] ; 0x80 + 272c8: f8dd 9094 ldr.w r9, [sp, #148] ; 0x94 + 272cc: f8dd a01c ldr.w sl, [sp, #28] + 272d0: ea4f 5369 mov.w r3, r9, asr #21 + 272d4: ea4f 594a mov.w r9, sl, lsl #21 + 272d8: f8dd a024 ldr.w sl, [sp, #36] ; 0x24 + 272dc: ea4f 5b45 mov.w fp, r5, lsl #21 + 272e0: ea4f 5a4a mov.w sl, sl, lsl #21 + 272e4: f8cd a02c str.w sl, [sp, #44] ; 0x2c + 272e8: f8dd a034 ldr.w sl, [sp, #52] ; 0x34 + 272ec: f8cd b0ec str.w fp, [sp, #236] ; 0xec + 272f0: ea4f 5b43 mov.w fp, r3, lsl #21 + 272f4: f8cd b054 str.w fp, [sp, #84] ; 0x54 + 272f8: ea4f 5a4a mov.w sl, sl, lsl #21 + 272fc: ea4f 5b47 mov.w fp, r7, lsl #21 + 27300: f8cd a06c str.w sl, [sp, #108] ; 0x6c + 27304: f8cd b064 str.w fp, [sp, #100] ; 0x64 + 27308: f8dd b0ec ldr.w fp, [sp, #236] ; 0xec + 2730c: f8dd a018 ldr.w sl, [sp, #24] + 27310: ea4b 2bd4 orr.w fp, fp, r4, lsr #11 + 27314: f8cd b0ec str.w fp, [sp, #236] ; 0xec + 27318: ea49 29da orr.w r9, r9, sl, lsr #11 + 2731c: f8dd b020 ldr.w fp, [sp, #32] + 27320: f8dd a02c ldr.w sl, [sp, #44] ; 0x2c + 27324: ea4a 2adb orr.w sl, sl, fp, lsr #11 + 27328: f8cd a02c str.w sl, [sp, #44] ; 0x2c + 2732c: f8dd a054 ldr.w sl, [sp, #84] ; 0x54 + 27330: f8dd b06c ldr.w fp, [sp, #108] ; 0x6c + 27334: ea4a 2ad2 orr.w sl, sl, r2, lsr #11 + 27338: f8cd a054 str.w sl, [sp, #84] ; 0x54 + 2733c: f8dd a030 ldr.w sl, [sp, #48] ; 0x30 + 27340: ea4b 2bda orr.w fp, fp, sl, lsr #11 + 27344: f8dd a018 ldr.w sl, [sp, #24] + 27348: f8cd b06c str.w fp, [sp, #108] ; 0x6c + 2734c: ea4f 584a mov.w r8, sl, lsl #21 + 27350: f8dd b064 ldr.w fp, [sp, #100] ; 0x64 + 27354: f8dd a020 ldr.w sl, [sp, #32] + 27358: ea4b 2bd6 orr.w fp, fp, r6, lsr #11 + 2735c: ea4f 5a4a mov.w sl, sl, lsl #21 + 27360: f8cd a028 str.w sl, [sp, #40] ; 0x28 + 27364: f8cd b064 str.w fp, [sp, #100] ; 0x64 + 27368: f8dd a030 ldr.w sl, [sp, #48] ; 0x30 + 2736c: ea4f 5b44 mov.w fp, r4, lsl #21 + 27370: f8cd b0e8 str.w fp, [sp, #232] ; 0xe8 + 27374: ea4f 5b42 mov.w fp, r2, lsl #21 + 27378: f8cd b050 str.w fp, [sp, #80] ; 0x50 + 2737c: ea4f 5a4a mov.w sl, sl, lsl #21 + 27380: ea4f 5b46 mov.w fp, r6, lsl #21 + 27384: f8cd a068 str.w sl, [sp, #104] ; 0x68 + 27388: f8cd b060 str.w fp, [sp, #96] ; 0x60 + 2738c: e9dd ab36 ldrd sl, fp, [sp, #216] ; 0xd8 + 27390: ebba 0a08 subs.w sl, sl, r8 + 27394: eb6b 0b09 sbc.w fp, fp, r9 + 27398: e9cd ab3c strd sl, fp, [sp, #240] ; 0xf0 + 2739c: f50d 7b8c add.w fp, sp, #280 ; 0x118 + 273a0: e9db 8900 ldrd r8, r9, [fp] + 273a4: e9dd ab06 ldrd sl, fp, [sp, #24] + 273a8: eb18 080a adds.w r8, r8, sl + 273ac: eb49 090b adc.w r9, r9, fp + 273b0: f50d 7a88 add.w sl, sp, #272 ; 0x110 + 273b4: e9cd 8908 strd r8, r9, [sp, #32] + 273b8: e9da 8900 ldrd r8, r9, [sl] + 273bc: e9dd ab2a ldrd sl, fp, [sp, #168] ; 0xa8 + 273c0: eb18 0804 adds.w r8, r8, r4 + 273c4: eb49 0905 adc.w r9, r9, r5 + 273c8: e9cd 8936 strd r8, r9, [sp, #216] ; 0xd8 + 273cc: e9dd 4534 ldrd r4, r5, [sp, #208] ; 0xd0 + 273d0: e9dd 893a ldrd r8, r9, [sp, #232] ; 0xe8 + 273d4: ebb4 0408 subs.w r4, r4, r8 + 273d8: eb65 0509 sbc.w r5, r5, r9 + 273dc: e9cd 453a strd r4, r5, [sp, #232] ; 0xe8 + 273e0: e9dd 450a ldrd r4, r5, [sp, #40] ; 0x28 + 273e4: ebba 0a04 subs.w sl, sl, r4 + 273e8: eb6b 0b05 sbc.w fp, fp, r5 + 273ec: e9cd ab2a strd sl, fp, [sp, #168] ; 0xa8 + 273f0: e9dd 4514 ldrd r4, r5, [sp, #80] ; 0x50 + 273f4: f50d 7a84 add.w sl, sp, #264 ; 0x108 + 273f8: e9da 8900 ldrd r8, r9, [sl] + 273fc: eb18 0802 adds.w r8, r8, r2 + 27400: eb49 0903 adc.w r9, r9, r3 + 27404: e9dd 232e ldrd r2, r3, [sp, #184] ; 0xb8 + 27408: 1b12 subs r2, r2, r4 + 2740a: e9dd ab1a ldrd sl, fp, [sp, #104] ; 0x68 + 2740e: eb63 0305 sbc.w r3, r3, r5 + 27412: e9cd 8934 strd r8, r9, [sp, #208] ; 0xd0 + 27416: e9dd 892c ldrd r8, r9, [sp, #176] ; 0xb0 + 2741a: e9dd 4518 ldrd r4, r5, [sp, #96] ; 0x60 + 2741e: ebb8 080a subs.w r8, r8, sl + 27422: eb69 090b sbc.w r9, r9, fp + 27426: e9cd 232e strd r2, r3, [sp, #184] ; 0xb8 + 2742a: e9dd 2326 ldrd r2, r3, [sp, #152] ; 0x98 + 2742e: e9dd ab30 ldrd sl, fp, [sp, #192] ; 0xc0 + 27432: 1b12 subs r2, r2, r4 + 27434: eb63 0305 sbc.w r3, r3, r5 + 27438: e9cd 892c strd r8, r9, [sp, #176] ; 0xb0 + 2743c: e9cd 230a strd r2, r3, [sp, #40] ; 0x28 + 27440: f8dd 8058 ldr.w r8, [sp, #88] ; 0x58 + 27444: f8dd 9080 ldr.w r9, [sp, #128] ; 0x80 + 27448: 9a16 ldr r2, [sp, #88] ; 0x58 + 2744a: 9b20 ldr r3, [sp, #128] ; 0x80 + 2744c: ea4f 4818 mov.w r8, r8, lsr #16 + 27450: ea4f 6919 mov.w r9, r9, lsr #24 + 27454: 0412 lsls r2, r2, #16 + 27456: 021b lsls r3, r3, #8 + 27458: eb1a 0a06 adds.w sl, sl, r6 + 2745c: f8cd 9074 str.w r9, [sp, #116] ; 0x74 + 27460: 9224 str r2, [sp, #144] ; 0x90 + 27462: 931c str r3, [sp, #112] ; 0x70 + 27464: f8cd 8094 str.w r8, [sp, #148] ; 0x94 + 27468: eb4b 0b07 adc.w fp, fp, r7 + 2746c: e9dd 8924 ldrd r8, r9, [sp, #144] ; 0x90 + 27470: e9dd 6732 ldrd r6, r7, [sp, #200] ; 0xc8 + 27474: e9dd 451c ldrd r4, r5, [sp, #112] ; 0x70 + 27478: f516 1680 adds.w r6, r6, #1048576 ; 0x100000 + 2747c: ea44 0408 orr.w r4, r4, r8 + 27480: ea45 0509 orr.w r5, r5, r9 + 27484: 78c2 ldrb r2, [r0, #3] + 27486: e9dd 8916 ldrd r8, r9, [sp, #88] ; 0x58 + 2748a: f147 0700 adc.w r7, r7, #0 + 2748e: e9cd 4514 strd r4, r5, [sp, #80] ; 0x50 + 27492: e9dd 4538 ldrd r4, r5, [sp, #224] ; 0xe0 + 27496: ea44 0408 orr.w r4, r4, r8 + 2749a: f890 8005 ldrb.w r8, [r0, #5] + 2749e: e9cd 6706 strd r6, r7, [sp, #24] + 274a2: e9dd 6722 ldrd r6, r7, [sp, #136] ; 0x88 + 274a6: ea45 0509 orr.w r5, r5, r9 + 274aa: f516 1680 adds.w r6, r6, #1048576 ; 0x100000 + 274ae: f04f 0300 mov.w r3, #0 + 274b2: f04f 0900 mov.w r9, #0 + 274b6: f147 0700 adc.w r7, r7, #0 + 274ba: e9cd 4538 strd r4, r5, [sp, #224] ; 0xe0 + 274be: e9cd 230c strd r2, r3, [sp, #48] ; 0x30 + 274c2: 7904 ldrb r4, [r0, #4] + 274c4: e9cd 8918 strd r8, r9, [sp, #96] ; 0x60 + 274c8: e9dd 230a ldrd r2, r3, [sp, #40] ; 0x28 + 274cc: ea4f 5856 mov.w r8, r6, lsr #21 + 274d0: ea48 28c7 orr.w r8, r8, r7, lsl #11 + 274d4: eb12 0208 adds.w r2, r2, r8 + 274d8: ea4f 5967 mov.w r9, r7, asr #21 + 274dc: eb43 0309 adc.w r3, r3, r9 + 274e0: e9cd 230a strd r2, r3, [sp, #40] ; 0x28 + 274e4: 9e0c ldr r6, [sp, #48] ; 0x30 + 274e6: 9b0c ldr r3, [sp, #48] ; 0x30 + 274e8: 0236 lsls r6, r6, #8 + 274ea: 0e1b lsrs r3, r3, #24 + 274ec: 9317 str r3, [sp, #92] ; 0x5c + 274ee: 9616 str r6, [sp, #88] ; 0x58 + 274f0: 0c23 lsrs r3, r4, #16 + 274f2: e9dd 6718 ldrd r6, r7, [sp, #96] ; 0x60 + 274f6: 0422 lsls r2, r4, #16 + 274f8: e9dd 4514 ldrd r4, r5, [sp, #80] ; 0x50 + 274fc: 4334 orrs r4, r6 + 274fe: 433d orrs r5, r7 + 27500: e9cd 4526 strd r4, r5, [sp, #152] ; 0x98 + 27504: e9dd 4516 ldrd r4, r5, [sp, #88] ; 0x58 + 27508: 4314 orrs r4, r2 + 2750a: 431d orrs r5, r3 + 2750c: 2200 movs r2, #0 + 2750e: e9cd 451c strd r4, r5, [sp, #112] ; 0x70 + 27512: 4614 mov r4, r2 + 27514: f64f 72ff movw r2, #65535 ; 0xffff + 27518: f2c0 021f movt r2, #31 + 2751c: 2300 movs r3, #0 + 2751e: 461d mov r5, r3 + 27520: ab48 add r3, sp, #288 ; 0x120 + 27522: e9d3 6700 ldrd r6, r7, [r3] + 27526: 2300 movs r3, #0 + 27528: 4016 ands r6, r2 + 2752a: 7842 ldrb r2, [r0, #1] + 2752c: 401f ands r7, r3 + 2752e: 2300 movs r3, #0 + 27530: e9cd 2320 strd r2, r3, [sp, #128] ; 0x80 + 27534: ea4f 5349 mov.w r3, r9, lsl #21 + 27538: f8dd 9038 ldr.w r9, [sp, #56] ; 0x38 + 2753c: ea43 23d8 orr.w r3, r3, r8, lsr #11 + 27540: ea4f 5248 mov.w r2, r8, lsl #21 + 27544: fbaa 8909 umull r8, r9, sl, r9 + 27548: e9cd 6716 strd r6, r7, [sp, #88] ; 0x58 + 2754c: 7886 ldrb r6, [r0, #2] + 2754e: e9cd 8914 strd r8, r9, [sp, #80] ; 0x50 + 27552: e9dd 8922 ldrd r8, r9, [sp, #136] ; 0x88 + 27556: 2700 movs r7, #0 + 27558: ebb8 0802 subs.w r8, r8, r2 + 2755c: eb69 0903 sbc.w r9, r9, r3 + 27560: e9cd 671a strd r6, r7, [sp, #104] ; 0x68 + 27564: 9b10 ldr r3, [sp, #64] ; 0x40 + 27566: 9e06 ldr r6, [sp, #24] + 27568: 9f07 ldr r7, [sp, #28] + 2756a: e9cd 450c strd r4, r5, [sp, #48] ; 0x30 + 2756e: fbaa 2303 umull r2, r3, sl, r3 + 27572: 0d74 lsrs r4, r6, #21 + 27574: ea44 24c7 orr.w r4, r4, r7, lsl #11 + 27578: 157d asrs r5, r7, #21 + 2757a: e9dd 672c ldrd r6, r7, [sp, #176] ; 0xb0 + 2757e: 1936 adds r6, r6, r4 + 27580: 416f adcs r7, r5 + 27582: e9cd 2322 strd r2, r3, [sp, #136] ; 0x88 + 27586: e9cd 6706 strd r6, r7, [sp, #24] + 2758a: 9a15 ldr r2, [sp, #84] ; 0x54 + 2758c: 9f0e ldr r7, [sp, #56] ; 0x38 + 2758e: 9e10 ldr r6, [sp, #64] ; 0x40 + 27590: fb07 270b mla r7, r7, fp, r2 + 27594: fb06 330b mla r3, r6, fp, r3 + 27598: 9715 str r7, [sp, #84] ; 0x54 + 2759a: 9f26 ldr r7, [sp, #152] ; 0x98 + 2759c: 9323 str r3, [sp, #140] ; 0x8c + 2759e: 08bf lsrs r7, r7, #2 + 275a0: 970c str r7, [sp, #48] ; 0x30 + 275a2: e9dd 671a ldrd r6, r7, [sp, #104] ; 0x68 + 275a6: e9dd 231c ldrd r2, r3, [sp, #112] ; 0x70 + 275aa: 4332 orrs r2, r6 + 275ac: 433b orrs r3, r7 + 275ae: e9cd 2324 strd r2, r3, [sp, #144] ; 0x90 + 275b2: 9f0c ldr r7, [sp, #48] ; 0x30 + 275b4: 9a27 ldr r2, [sp, #156] ; 0x9c + 275b6: ea47 7782 orr.w r7, r7, r2, lsl #30 + 275ba: 0893 lsrs r3, r2, #2 + 275bc: 970c str r7, [sp, #48] ; 0x30 + 275be: 930d str r3, [sp, #52] ; 0x34 + 275c0: e9dd 6714 ldrd r6, r7, [sp, #80] ; 0x50 + 275c4: e9dd 2316 ldrd r2, r3, [sp, #88] ; 0x58 + 275c8: 18b6 adds r6, r6, r2 + 275ca: 415f adcs r7, r3 + 275cc: e9cd 6714 strd r6, r7, [sp, #80] ; 0x50 + 275d0: e9dd 2322 ldrd r2, r3, [sp, #136] ; 0x88 + 275d4: e9dd 672e ldrd r6, r7, [sp, #184] ; 0xb8 + 275d8: 18b6 adds r6, r6, r2 + 275da: f64f 72ff movw r2, #65535 ; 0xffff + 275de: f2c0 021f movt r2, #31 + 275e2: 415f adcs r7, r3 + 275e4: 2300 movs r3, #0 + 275e6: e9cd 671c strd r6, r7, [sp, #112] ; 0x70 + 275ea: e9dd 670c ldrd r6, r7, [sp, #48] ; 0x30 + 275ee: 4016 ands r6, r2 + 275f0: 401f ands r7, r3 + 275f2: e9cd 670c strd r6, r7, [sp, #48] ; 0x30 + 275f6: 9e12 ldr r6, [sp, #72] ; 0x48 + 275f8: fbaa 2306 umull r2, r3, sl, r6 + 275fc: fb06 330b mla r3, r6, fp, r3 + 27600: e9dd 672a ldrd r6, r7, [sp, #168] ; 0xa8 + 27604: 18b6 adds r6, r6, r2 + 27606: f642 4213 movw r2, #11283 ; 0x2c13 + 2760a: 415f adcs r7, r3 + 2760c: e9cd 6716 strd r6, r7, [sp, #88] ; 0x58 + 27610: f642 4713 movw r7, #11283 ; 0x2c13 + 27614: f2c0 020a movt r2, #10 + 27618: f2c0 070a movt r7, #10 + 2761c: 9b0a ldr r3, [sp, #40] ; 0x28 + 2761e: 9e0b ldr r6, [sp, #44] ; 0x2c + 27620: fba3 2302 umull r2, r3, r3, r2 + 27624: e9cd 2310 strd r2, r3, [sp, #64] ; 0x40 + 27628: fb07 3306 mla r3, r7, r6, r3 + 2762c: 0566 lsls r6, r4, #21 + 2762e: 056f lsls r7, r5, #21 + 27630: 7802 ldrb r2, [r0, #0] + 27632: ea47 27d4 orr.w r7, r7, r4, lsr #11 + 27636: e9dd 4532 ldrd r4, r5, [sp, #200] ; 0xc8 + 2763a: 1ba4 subs r4, r4, r6 + 2763c: 9e18 ldr r6, [sp, #96] ; 0x60 + 2763e: 9311 str r3, [sp, #68] ; 0x44 + 27640: f04f 0300 mov.w r3, #0 + 27644: e9cd 232e strd r2, r3, [sp, #184] ; 0xb8 + 27648: ea4f 2316 mov.w r3, r6, lsr #8 + 2764c: eb65 0507 sbc.w r5, r5, r7 + 27650: 0632 lsls r2, r6, #24 + 27652: e9dd 6724 ldrd r6, r7, [sp, #144] ; 0x90 + 27656: 431f orrs r7, r3 + 27658: f642 5318 movw r3, #11544 ; 0x2d18 + 2765c: f2c0 0307 movt r3, #7 + 27660: e9cd 450e strd r4, r5, [sp, #56] ; 0x38 + 27664: 9d0a ldr r5, [sp, #40] ; 0x28 + 27666: 4316 orrs r6, r2 + 27668: 9a0a ldr r2, [sp, #40] ; 0x28 + 2766a: 426d negs r5, r5 + 2766c: 9544 str r5, [sp, #272] ; 0x110 + 2766e: fba2 4503 umull r4, r5, r2, r3 + 27672: 9a0b ldr r2, [sp, #44] ; 0x2c + 27674: fb03 5502 mla r5, r3, r2, r5 + 27678: e9dd 2314 ldrd r2, r3, [sp, #80] ; 0x50 + 2767c: 1912 adds r2, r2, r4 + 2767e: 416b adcs r3, r5 + 27680: f64f 3567 movw r5, #64359 ; 0xfb67 + 27684: f2c0 0509 movt r5, #9 + 27688: e9cd 2324 strd r2, r3, [sp, #144] ; 0x90 + 2768c: 9c0a ldr r4, [sp, #40] ; 0x28 + 2768e: fba4 2305 umull r2, r3, r4, r5 + 27692: 9c0b ldr r4, [sp, #44] ; 0x2c + 27694: fb05 3304 mla r3, r5, r4, r3 + 27698: e9dd 4516 ldrd r4, r5, [sp, #88] ; 0x58 + 2769c: 18a4 adds r4, r4, r2 + 2769e: 415d adcs r5, r3 + 276a0: e9cd 452c strd r4, r5, [sp, #176] ; 0xb0 + 276a4: f642 4413 movw r4, #11283 ; 0x2c13 + 276a8: f2c0 040a movt r4, #10 + 276ac: 9d06 ldr r5, [sp, #24] + 276ae: fba5 2304 umull r2, r3, r5, r4 + 276b2: 9d07 ldr r5, [sp, #28] + 276b4: fb04 3305 mla r3, r4, r5, r3 + 276b8: e9dd 450c ldrd r4, r5, [sp, #48] ; 0x30 + 276bc: 18a4 adds r4, r4, r2 + 276be: 415d adcs r5, r3 + 276c0: f642 4313 movw r3, #11283 ; 0x2c13 + 276c4: e9cd 452a strd r4, r5, [sp, #168] ; 0xa8 + 276c8: f642 4413 movw r4, #11283 ; 0x2c13 + 276cc: f2c0 030a movt r3, #10 + 276d0: f2c0 040a movt r4, #10 + 276d4: fba8 2303 umull r2, r3, r8, r3 + 276d8: e9cd 230c strd r2, r3, [sp, #48] ; 0x30 + 276dc: fb04 3409 mla r4, r4, r9, r3 + 276e0: f642 5318 movw r3, #11544 ; 0x2d18 + 276e4: 940d str r4, [sp, #52] ; 0x34 + 276e6: f642 5418 movw r4, #11544 ; 0x2d18 + 276ea: f2c0 0307 movt r3, #7 + 276ee: f2c0 0407 movt r4, #7 + 276f2: fba8 2303 umull r2, r3, r8, r3 + 276f6: e9cd 2318 strd r2, r3, [sp, #96] ; 0x60 + 276fa: fb04 3409 mla r4, r4, r9, r3 + 276fe: f24c 6353 movw r3, #50771 ; 0xc653 + 27702: f6cf 73f0 movt r3, #65520 ; 0xfff0 + 27706: 9419 str r4, [sp, #100] ; 0x64 + 27708: 9a0b ldr r2, [sp, #44] ; 0x2c + 2770a: 9c44 ldr r4, [sp, #272] ; 0x110 + 2770c: f1ca 0500 rsb r5, sl, #0 + 27710: fb03 4202 mla r2, r3, r2, r4 + 27714: f24c 6453 movw r4, #50771 ; 0xc653 + 27718: f6cf 74f0 movt r4, #65520 ; 0xfff0 + 2771c: 9542 str r5, [sp, #264] ; 0x108 + 2771e: 9d0a ldr r5, [sp, #40] ; 0x28 + 27720: 9214 str r2, [sp, #80] ; 0x50 + 27722: fba5 2304 umull r2, r3, r5, r4 + 27726: 9d14 ldr r5, [sp, #80] ; 0x50 + 27728: 442b add r3, r5 + 2772a: e9dd 451c ldrd r4, r5, [sp, #112] ; 0x70 + 2772e: 18a4 adds r4, r4, r2 + 27730: 415d adcs r5, r3 + 27732: e9cd 4516 strd r4, r5, [sp, #88] ; 0x58 + 27736: 9d42 ldr r5, [sp, #264] ; 0x108 + 27738: fbaa 230e umull r2, r3, sl, lr + 2773c: fb0e 540b mla r4, lr, fp, r5 + 27740: 4423 add r3, r4 + 27742: e9dd 4534 ldrd r4, r5, [sp, #208] ; 0xd0 + 27746: 18a4 adds r4, r4, r2 + 27748: 415d adcs r5, r3 + 2774a: fbaa 230c umull r2, r3, sl, ip + 2774e: fb0c 3c0b mla ip, ip, fp, r3 + 27752: e9cd 4514 strd r4, r5, [sp, #80] ; 0x50 + 27756: e9cd 231c strd r2, r3, [sp, #112] ; 0x70 + 2775a: 0974 lsrs r4, r6, #5 + 2775c: f8cd c074 str.w ip, [sp, #116] ; 0x74 + 27760: e9dd 231c ldrd r2, r3, [sp, #112] ; 0x70 + 27764: ea44 64c7 orr.w r4, r4, r7, lsl #27 + 27768: 097d lsrs r5, r7, #5 + 2776a: e9dd 673a ldrd r6, r7, [sp, #232] ; 0xe8 + 2776e: 18b6 adds r6, r6, r2 + 27770: 415f adcs r7, r3 + 27772: f241 53d1 movw r3, #5585 ; 0x15d1 + 27776: f64f 72ff movw r2, #65535 ; 0xffff + 2777a: f2c0 0302 movt r3, #2 + 2777e: f2c0 021f movt r2, #31 + 27782: e9cd 671c strd r6, r7, [sp, #112] ; 0x70 + 27786: fba8 6703 umull r6, r7, r8, r3 + 2778a: fb03 7709 mla r7, r3, r9, r7 + 2778e: 2300 movs r3, #0 + 27790: 4022 ands r2, r4 + 27792: 402b ands r3, r5 + 27794: e9dd 4516 ldrd r4, r5, [sp, #88] ; 0x58 + 27798: 19a4 adds r4, r4, r6 + 2779a: f64f 3667 movw r6, #64359 ; 0xfb67 + 2779e: f2c0 0609 movt r6, #9 + 277a2: 417d adcs r5, r7 + 277a4: e9cd 4530 strd r4, r5, [sp, #192] ; 0xc0 + 277a8: fba8 4506 umull r4, r5, r8, r6 + 277ac: fb06 5509 mla r5, r6, r9, r5 + 277b0: e9cd 2326 strd r2, r3, [sp, #152] ; 0x98 + 277b4: e9dd 2324 ldrd r2, r3, [sp, #144] ; 0x90 + 277b8: 1912 adds r2, r2, r4 + 277ba: 416b adcs r3, r5 + 277bc: f241 55d1 movw r5, #5585 ; 0x15d1 + 277c0: f2c0 0502 movt r5, #2 + 277c4: 9c0a ldr r4, [sp, #40] ; 0x28 + 277c6: e9cd 2322 strd r2, r3, [sp, #136] ; 0x88 + 277ca: fba4 2305 umull r2, r3, r4, r5 + 277ce: 9e0b ldr r6, [sp, #44] ; 0x2c + 277d0: 468e mov lr, r1 + 277d2: fb05 3306 mla r3, r5, r6, r3 + 277d6: e9dd 4514 ldrd r4, r5, [sp, #80] ; 0x50 + 277da: f642 5618 movw r6, #11544 ; 0x2d18 + 277de: f2c0 0607 movt r6, #7 + 277e2: 18a4 adds r4, r4, r2 + 277e4: 415d adcs r5, r3 + 277e6: e9cd 4524 strd r4, r5, [sp, #144] ; 0x90 + 277ea: 9d0e ldr r5, [sp, #56] ; 0x38 + 277ec: 9f0f ldr r7, [sp, #60] ; 0x3c + 277ee: fba5 2306 umull r2, r3, r5, r6 + 277f2: e9dd 452a ldrd r4, r5, [sp, #168] ; 0xa8 + 277f6: fb06 3307 mla r3, r6, r7, r3 + 277fa: f642 5618 movw r6, #11544 ; 0x2d18 + 277fe: 18a4 adds r4, r4, r2 + 27800: f642 5218 movw r2, #11544 ; 0x2d18 + 27804: f2c0 0607 movt r6, #7 + 27808: f2c0 0207 movt r2, #7 + 2780c: 9f06 ldr r7, [sp, #24] + 2780e: f8dd c01c ldr.w ip, [sp, #28] + 27812: fba7 6706 umull r6, r7, r7, r6 + 27816: 415d adcs r5, r3 + 27818: e9cd 6714 strd r6, r7, [sp, #80] ; 0x50 + 2781c: e9cd 4532 strd r4, r5, [sp, #200] ; 0xc8 + 27820: fb02 770c mla r7, r2, ip, r7 + 27824: f64f 3467 movw r4, #64359 ; 0xfb67 + 27828: 9715 str r7, [sp, #84] ; 0x54 + 2782a: f64f 3767 movw r7, #64359 ; 0xfb67 + 2782e: f2c0 0409 movt r4, #9 + 27832: f2c0 0709 movt r7, #9 + 27836: 9d06 ldr r5, [sp, #24] + 27838: 9e06 ldr r6, [sp, #24] + 2783a: fba5 4504 umull r4, r5, r5, r4 + 2783e: e9cd 4516 strd r4, r5, [sp, #88] ; 0x58 + 27842: fb07 550c mla r5, r7, ip, r5 + 27846: f24c 6c53 movw ip, #50771 ; 0xc653 + 2784a: f6cf 7cf0 movt ip, #65520 ; 0xfff0 + 2784e: f1c8 0700 rsb r7, r8, #0 + 27852: fba8 230c umull r2, r3, r8, ip + 27856: 9517 str r5, [sp, #92] ; 0x5c + 27858: fb0c 7509 mla r5, ip, r9, r7 + 2785c: 442b add r3, r5 + 2785e: e9dd 452c ldrd r4, r5, [sp, #176] ; 0xb0 + 27862: 18a4 adds r4, r4, r2 + 27864: 415d adcs r5, r3 + 27866: e9cd 452a strd r4, r5, [sp, #168] ; 0xa8 + 2786a: 9a0b ldr r2, [sp, #44] ; 0x2c + 2786c: 9b44 ldr r3, [sp, #272] ; 0x110 + 2786e: 9c0a ldr r4, [sp, #40] ; 0x28 + 27870: 4275 negs r5, r6 + 27872: 9e42 ldr r6, [sp, #264] ; 0x108 + 27874: fb01 3c02 mla ip, r1, r2, r3 + 27878: fba4 2301 umull r2, r3, r4, r1 + 2787c: fb0e 7409 mla r4, lr, r9, r7 + 27880: fb01 610b mla r1, r1, fp, r6 + 27884: fba8 670e umull r6, r7, r8, lr + 27888: f24c 6853 movw r8, #50771 ; 0xc653 + 2788c: f6cf 78f0 movt r8, #65520 ; 0xfff0 + 27890: e9cd 6712 strd r6, r7, [sp, #72] ; 0x48 + 27894: f8dd 904c ldr.w r9, [sp, #76] ; 0x4c + 27898: 9f07 ldr r7, [sp, #28] + 2789a: 44a1 add r9, r4 + 2789c: fb0e 5607 mla r6, lr, r7, r5 + 278a0: 4463 add r3, ip + 278a2: fb08 5507 mla r5, r8, r7, r5 + 278a6: f8cd 904c str.w r9, [sp, #76] ; 0x4c + 278aa: e9dd 891c ldrd r8, r9, [sp, #112] ; 0x70 + 278ae: eb18 0802 adds.w r8, r8, r2 + 278b2: eb49 0903 adc.w r9, r9, r3 + 278b6: e9cd 892c strd r8, r9, [sp, #176] ; 0xb0 + 278ba: f24c 6853 movw r8, #50771 ; 0xc653 + 278be: f6cf 78f0 movt r8, #65520 ; 0xfff0 + 278c2: f8dd 9018 ldr.w r9, [sp, #24] + 278c6: fbaa ab0e umull sl, fp, sl, lr + 278ca: fba9 230e umull r2, r3, r9, lr + 278ce: 4433 add r3, r6 + 278d0: e9dd 6730 ldrd r6, r7, [sp, #192] ; 0xc0 + 278d4: 18b6 adds r6, r6, r2 + 278d6: 415f adcs r7, r3 + 278d8: fba9 2308 umull r2, r3, r9, r8 + 278dc: e9dd 8938 ldrd r8, r9, [sp, #224] ; 0xe0 + 278e0: e9cd 6730 strd r6, r7, [sp, #192] ; 0xc0 + 278e4: 442b add r3, r5 + 278e6: 9e1e ldr r6, [sp, #120] ; 0x78 + 278e8: e9dd 4522 ldrd r4, r5, [sp, #136] ; 0x88 + 278ec: 18a4 adds r4, r4, r2 + 278ee: 415d adcs r5, r3 + 278f0: e9cd 4522 strd r4, r5, [sp, #136] ; 0x88 + 278f4: 0634 lsls r4, r6, #24 + 278f6: ea44 0408 orr.w r4, r4, r8 + 278fa: 09e2 lsrs r2, r4, #7 + 278fc: f64f 74ff movw r4, #65535 ; 0xffff + 27900: f2c0 041f movt r4, #31 + 27904: 0a35 lsrs r5, r6, #8 + 27906: ea45 0509 orr.w r5, r5, r9 + 2790a: ea42 6245 orr.w r2, r2, r5, lsl #25 + 2790e: 4022 ands r2, r4 + 27910: f642 4413 movw r4, #11283 ; 0x2c13 + 27914: e9dd 670c ldrd r6, r7, [sp, #48] ; 0x30 + 27918: e9dd 8914 ldrd r8, r9, [sp, #80] ; 0x50 + 2791c: 448b add fp, r1 + 2791e: f241 51d1 movw r1, #5585 ; 0x15d1 + 27922: f2c0 040a movt r4, #10 + 27926: f2c0 0102 movt r1, #2 + 2792a: 09eb lsrs r3, r5, #7 + 2792c: 2500 movs r5, #0 + 2792e: 1992 adds r2, r2, r6 + 27930: ea03 0305 and.w r3, r3, r5 + 27934: 417b adcs r3, r7 + 27936: eb18 0802 adds.w r8, r8, r2 + 2793a: eb49 0903 adc.w r9, r9, r3 + 2793e: e9cd 890a strd r8, r9, [sp, #40] ; 0x28 + 27942: 9d0e ldr r5, [sp, #56] ; 0x38 + 27944: 9a07 ldr r2, [sp, #28] + 27946: fba5 4504 umull r4, r5, r5, r4 + 2794a: f8dd c018 ldr.w ip, [sp, #24] + 2794e: e9cd 4506 strd r4, r5, [sp, #24] + 27952: f64f 3467 movw r4, #64359 ; 0xfb67 + 27956: f642 4713 movw r7, #11283 ; 0x2c13 + 2795a: fbac 8901 umull r8, r9, ip, r1 + 2795e: fb01 9902 mla r9, r1, r2, r9 + 27962: e9dd 2336 ldrd r2, r3, [sp, #216] ; 0xd8 + 27966: f64f 3167 movw r1, #64359 ; 0xfb67 + 2796a: f2c0 0409 movt r4, #9 + 2796e: f2c0 070a movt r7, #10 + 27972: f2c0 0109 movt r1, #9 + 27976: eb12 020a adds.w r2, r2, sl + 2797a: eb43 030b adc.w r3, r3, fp + 2797e: e9cd 231c strd r2, r3, [sp, #112] ; 0x70 + 27982: 9b0e ldr r3, [sp, #56] ; 0x38 + 27984: 9e0f ldr r6, [sp, #60] ; 0x3c + 27986: fba3 ab04 umull sl, fp, r3, r4 + 2798a: e9dd 2324 ldrd r2, r3, [sp, #144] ; 0x90 + 2798e: fb04 bb06 mla fp, r4, r6, fp + 27992: fb07 5506 mla r5, r7, r6, r5 + 27996: e9dd 6712 ldrd r6, r7, [sp, #72] ; 0x48 + 2799a: 18b6 adds r6, r6, r2 + 2799c: 415f adcs r7, r3 + 2799e: e9cd 6724 strd r6, r7, [sp, #144] ; 0x90 + 279a2: 9b3e ldr r3, [sp, #248] ; 0xf8 + 279a4: 9e40 ldr r6, [sp, #256] ; 0x100 + 279a6: 9f3e ldr r7, [sp, #248] ; 0xf8 + 279a8: 9507 str r5, [sp, #28] + 279aa: 0432 lsls r2, r6, #16 + 279ac: 0e1d lsrs r5, r3, #24 + 279ae: 023c lsls r4, r7, #8 + 279b0: 0c33 lsrs r3, r6, #16 + 279b2: 9e28 ldr r6, [sp, #160] ; 0xa0 + 279b4: 4314 orrs r4, r2 + 279b6: 431d orrs r5, r3 + 279b8: e9dd 231e ldrd r2, r3, [sp, #120] ; 0x78 + 279bc: 4314 orrs r4, r2 + 279be: 0632 lsls r2, r6, #24 + 279c0: 4314 orrs r4, r2 + 279c2: 9a0e ldr r2, [sp, #56] ; 0x38 + 279c4: f8dd c020 ldr.w ip, [sp, #32] + 279c8: 4252 negs r2, r2 + 279ca: 921e str r2, [sp, #120] ; 0x78 + 279cc: f642 4213 movw r2, #11283 ; 0x2c13 + 279d0: 431d orrs r5, r3 + 279d2: 0a33 lsrs r3, r6, #8 + 279d4: fbac 6701 umull r6, r7, ip, r1 + 279d8: f24c 6153 movw r1, #50771 ; 0xc653 + 279dc: f2c0 020a movt r2, #10 + 279e0: f6cf 71f0 movt r1, #65520 ; 0xfff0 + 279e4: 431d orrs r5, r3 + 279e6: fbac 2302 umull r2, r3, ip, r2 + 279ea: e9cd 2312 strd r2, r3, [sp, #72] ; 0x48 + 279ee: 9b0f ldr r3, [sp, #60] ; 0x3c + 279f0: 9a1e ldr r2, [sp, #120] ; 0x78 + 279f2: fb01 2c03 mla ip, r1, r3, r2 + 279f6: f64f 3167 movw r1, #64359 ; 0xfb67 + 279fa: f642 4213 movw r2, #11283 ; 0x2c13 + 279fe: f2c0 0109 movt r1, #9 + 27a02: f2c0 020a movt r2, #10 + 27a06: 9b09 ldr r3, [sp, #36] ; 0x24 + 27a08: fb01 7703 mla r7, r1, r3, r7 + 27a0c: 9913 ldr r1, [sp, #76] ; 0x4c + 27a0e: fb02 1203 mla r2, r2, r3, r1 + 27a12: 9213 str r2, [sp, #76] ; 0x4c + 27a14: e9dd 232a ldrd r2, r3, [sp, #168] ; 0xa8 + 27a18: eb12 0208 adds.w r2, r2, r8 + 27a1c: f64f 78ff movw r8, #65535 ; 0xffff + 27a20: f2c0 081f movt r8, #31 + 27a24: eb43 0309 adc.w r3, r3, r9 + 27a28: e9cd 2314 strd r2, r3, [sp, #80] ; 0x50 + 27a2c: 0922 lsrs r2, r4, #4 + 27a2e: ea42 7205 orr.w r2, r2, r5, lsl #28 + 27a32: 092b lsrs r3, r5, #4 + 27a34: ea08 0802 and.w r8, r8, r2 + 27a38: f04f 0900 mov.w r9, #0 + 27a3c: e9dd 4510 ldrd r4, r5, [sp, #64] ; 0x40 + 27a40: ea09 0903 and.w r9, r9, r3 + 27a44: eb18 0804 adds.w r8, r8, r4 + 27a48: e9dd 2318 ldrd r2, r3, [sp, #96] ; 0x60 + 27a4c: eb49 0905 adc.w r9, r9, r5 + 27a50: eb18 0802 adds.w r8, r8, r2 + 27a54: eb49 0903 adc.w r9, r9, r3 + 27a58: e9dd 4516 ldrd r4, r5, [sp, #88] ; 0x58 + 27a5c: eb14 0408 adds.w r4, r4, r8 + 27a60: eb45 0509 adc.w r5, r5, r9 + 27a64: f24c 6953 movw r9, #50771 ; 0xc653 + 27a68: e9dd 2306 ldrd r2, r3, [sp, #24] + 27a6c: f6cf 79f0 movt r9, #65520 ; 0xfff0 + 27a70: f8dd 8038 ldr.w r8, [sp, #56] ; 0x38 + 27a74: e9cd 450c strd r4, r5, [sp, #48] ; 0x30 + 27a78: fba8 4509 umull r4, r5, r8, r9 + 27a7c: e9dd 8926 ldrd r8, r9, [sp, #152] ; 0x98 + 27a80: eb12 0208 adds.w r2, r2, r8 + 27a84: eb43 0309 adc.w r3, r3, r9 + 27a88: e9cd 2310 strd r2, r3, [sp, #64] ; 0x40 + 27a8c: e9dd 230a ldrd r2, r3, [sp, #40] ; 0x28 + 27a90: e9dd 890c ldrd r8, r9, [sp, #48] ; 0x30 + 27a94: eb12 020a adds.w r2, r2, sl + 27a98: eb43 030b adc.w r3, r3, fp + 27a9c: 4465 add r5, ip + 27a9e: eb18 0804 adds.w r8, r8, r4 + 27aa2: f241 5cd1 movw ip, #5585 ; 0x15d1 + 27aa6: e9dd ab32 ldrd sl, fp, [sp, #200] ; 0xc8 + 27aaa: f642 5118 movw r1, #11544 ; 0x2d18 + 27aae: eb49 0905 adc.w r9, r9, r5 + 27ab2: eb1a 0a06 adds.w sl, sl, r6 + 27ab6: eb4b 0b07 adc.w fp, fp, r7 + 27aba: f24c 6753 movw r7, #50771 ; 0xc653 + 27abe: e9cd ab0a strd sl, fp, [sp, #40] ; 0x28 + 27ac2: f8dd b020 ldr.w fp, [sp, #32] + 27ac6: f2c0 0c02 movt ip, #2 + 27aca: f2c0 0107 movt r1, #7 + 27ace: e9cd 2306 strd r2, r3, [sp, #24] + 27ad2: 465a mov r2, fp + 27ad4: f6cf 77f0 movt r7, #65520 ; 0xfff0 + 27ad8: e9cd 890c strd r8, r9, [sp, #48] ; 0x30 + 27adc: fbab 4501 umull r4, r5, fp, r1 + 27ae0: fbab 890c umull r8, r9, fp, ip + 27ae4: 9e09 ldr r6, [sp, #36] ; 0x24 + 27ae6: 46da mov sl, fp + 27ae8: f24c 6b53 movw fp, #50771 ; 0xc653 + 27aec: 4252 negs r2, r2 + 27aee: fb07 2306 mla r3, r7, r6, r2 + 27af2: 9216 str r2, [sp, #88] ; 0x58 + 27af4: f642 5218 movw r2, #11544 ; 0x2d18 + 27af8: f6cf 7bf0 movt fp, #65520 ; 0xfff0 + 27afc: f2c0 0207 movt r2, #7 + 27b00: 9909 ldr r1, [sp, #36] ; 0x24 + 27b02: fbaa 670b umull r6, r7, sl, fp + 27b06: e9dd ab0a ldrd sl, fp, [sp, #40] ; 0x28 + 27b0a: f51a 1a80 adds.w sl, sl, #1048576 ; 0x100000 + 27b0e: fb0c 9901 mla r9, ip, r1, r9 + 27b12: f14b 0b00 adc.w fp, fp, #0 + 27b16: e9cd ab26 strd sl, fp, [sp, #152] ; 0x98 + 27b1a: fb02 5501 mla r5, r2, r1, r5 + 27b1e: f8dd b038 ldr.w fp, [sp, #56] ; 0x38 + 27b22: 441f add r7, r3 + 27b24: fbab 230c umull r2, r3, fp, ip + 27b28: e9dd ab0c ldrd sl, fp, [sp, #48] ; 0x30 + 27b2c: eb1a 0a08 adds.w sl, sl, r8 + 27b30: eb4b 0b09 adc.w fp, fp, r9 + 27b34: e9dd 8910 ldrd r8, r9, [sp, #64] ; 0x40 + 27b38: eb18 0804 adds.w r8, r8, r4 + 27b3c: eb49 0905 adc.w r9, r9, r5 + 27b40: e9cd ab0c strd sl, fp, [sp, #48] ; 0x30 + 27b44: e9dd 4522 ldrd r4, r5, [sp, #136] ; 0x88 + 27b48: f8dd a03c ldr.w sl, [sp, #60] ; 0x3c + 27b4c: e9cd 8910 strd r8, r9, [sp, #64] ; 0x40 + 27b50: e9dd 8906 ldrd r8, r9, [sp, #24] + 27b54: eb18 0806 adds.w r8, r8, r6 + 27b58: 9e1e ldr r6, [sp, #120] ; 0x78 + 27b5a: fb0c 330a mla r3, ip, sl, r3 + 27b5e: fb0e 6c0a mla ip, lr, sl, r6 + 27b62: f64f 76ff movw r6, #65535 ; 0xffff + 27b66: f2c0 061f movt r6, #31 + 27b6a: f8dd a068 ldr.w sl, [sp, #104] ; 0x68 + 27b6e: eb49 0907 adc.w r9, r9, r7 + 27b72: 18a4 adds r4, r4, r2 + 27b74: 9f20 ldr r7, [sp, #128] ; 0x80 + 27b76: 415d adcs r5, r3 + 27b78: e9cd 4518 strd r4, r5, [sp, #96] ; 0x60 + 27b7c: ea4f 420a mov.w r2, sl, lsl #16 + 27b80: 023c lsls r4, r7, #8 + 27b82: ea4f 431a mov.w r3, sl, lsr #16 + 27b86: 0e3d lsrs r5, r7, #24 + 27b88: 4314 orrs r4, r2 + 27b8a: 431d orrs r5, r3 + 27b8c: e9dd 232e ldrd r2, r3, [sp, #184] ; 0xb8 + 27b90: 4314 orrs r4, r2 + 27b92: 4034 ands r4, r6 + 27b94: 431d orrs r5, r3 + 27b96: 2700 movs r7, #0 + 27b98: 9b0e ldr r3, [sp, #56] ; 0x38 + 27b9a: e9dd ab12 ldrd sl, fp, [sp, #72] ; 0x48 + 27b9e: 403d ands r5, r7 + 27ba0: eb1a 0a04 adds.w sl, sl, r4 + 27ba4: fba3 670e umull r6, r7, r3, lr + 27ba8: eb4b 0b05 adc.w fp, fp, r5 + 27bac: e9cd ab28 strd sl, fp, [sp, #160] ; 0xa0 + 27bb0: f51a 1480 adds.w r4, sl, #1048576 ; 0x100000 + 27bb4: f8dd a098 ldr.w sl, [sp, #152] ; 0x98 + 27bb8: 9927 ldr r1, [sp, #156] ; 0x9c + 27bba: f14b 0500 adc.w r5, fp, #0 + 27bbe: ea4f 525a mov.w r2, sl, lsr #21 + 27bc2: ea4f 5b54 mov.w fp, r4, lsr #21 + 27bc6: ea42 22c1 orr.w r2, r2, r1, lsl #11 + 27bca: ea4b 2ac5 orr.w sl, fp, r5, lsl #11 + 27bce: 4467 add r7, ip + 27bd0: ea4f 5c65 mov.w ip, r5, asr #21 + 27bd4: e9dd 4514 ldrd r4, r5, [sp, #80] ; 0x50 + 27bd8: 19a4 adds r4, r4, r6 + 27bda: ea4f 5361 mov.w r3, r1, asr #21 + 27bde: 417d adcs r5, r7 + 27be0: eb18 0602 adds.w r6, r8, r2 + 27be4: eb49 0703 adc.w r7, r9, r3 + 27be8: f8cd a048 str.w sl, [sp, #72] ; 0x48 + 27bec: f8cd c04c str.w ip, [sp, #76] ; 0x4c + 27bf0: e9cd 451e strd r4, r5, [sp, #120] ; 0x78 + 27bf4: e9dd ab0c ldrd sl, fp, [sp, #48] ; 0x30 + 27bf8: e9dd 8910 ldrd r8, r9, [sp, #64] ; 0x40 + 27bfc: f51a 1a80 adds.w sl, sl, #1048576 ; 0x100000 + 27c00: e9dd 4512 ldrd r4, r5, [sp, #72] ; 0x48 + 27c04: f14b 0b00 adc.w fp, fp, #0 + 27c08: eb18 0804 adds.w r8, r8, r4 + 27c0c: eb49 0905 adc.w r9, r9, r5 + 27c10: e9cd 8920 strd r8, r9, [sp, #128] ; 0x80 + 27c14: f8dd 9020 ldr.w r9, [sp, #32] + 27c18: e9cd 6726 strd r6, r7, [sp, #152] ; 0x98 + 27c1c: fba9 890e umull r8, r9, r9, lr + 27c20: 9e16 ldr r6, [sp, #88] ; 0x58 + 27c22: 9d09 ldr r5, [sp, #36] ; 0x24 + 27c24: e9cd 8910 strd r8, r9, [sp, #64] ; 0x40 + 27c28: fb0e 6105 mla r1, lr, r5, r6 + 27c2c: e9dd 451c ldrd r4, r5, [sp, #112] ; 0x70 + 27c30: 9f11 ldr r7, [sp, #68] ; 0x44 + 27c32: f514 1480 adds.w r4, r4, #1048576 ; 0x100000 + 27c36: 440f add r7, r1 + 27c38: 9711 str r7, [sp, #68] ; 0x44 + 27c3a: f145 0500 adc.w r5, r5, #0 + 27c3e: e9cd 4506 strd r4, r5, [sp, #24] + 27c42: e9dd 8910 ldrd r8, r9, [sp, #64] ; 0x40 + 27c46: e9dd 4518 ldrd r4, r5, [sp, #96] ; 0x60 + 27c4a: eb18 0804 adds.w r8, r8, r4 + 27c4e: eb49 0905 adc.w r9, r9, r5 + 27c52: e9dd 6726 ldrd r6, r7, [sp, #152] ; 0x98 + 27c56: f516 1680 adds.w r6, r6, #1048576 ; 0x100000 + 27c5a: f147 0700 adc.w r7, r7, #0 + 27c5e: e9cd 6716 strd r6, r7, [sp, #88] ; 0x58 + 27c62: e9dd 6720 ldrd r6, r7, [sp, #128] ; 0x80 + 27c66: f516 1680 adds.w r6, r6, #1048576 ; 0x100000 + 27c6a: f147 0700 adc.w r7, r7, #0 + 27c6e: e9cd 6714 strd r6, r7, [sp, #80] ; 0x50 + 27c72: e9dd 671e ldrd r6, r7, [sp, #120] ; 0x78 + 27c76: f516 1680 adds.w r6, r6, #1048576 ; 0x100000 + 27c7a: f147 0700 adc.w r7, r7, #0 + 27c7e: e9cd 8922 strd r8, r9, [sp, #136] ; 0x88 + 27c82: e9dd 8924 ldrd r8, r9, [sp, #144] ; 0x90 + 27c86: e9cd 671a strd r6, r7, [sp, #104] ; 0x68 + 27c8a: f518 1880 adds.w r8, r8, #1048576 ; 0x100000 + 27c8e: ea4f 5642 mov.w r6, r2, lsl #21 + 27c92: ea4f 545a mov.w r4, sl, lsr #21 + 27c96: ea4f 5743 mov.w r7, r3, lsl #21 + 27c9a: ea44 24cb orr.w r4, r4, fp, lsl #11 + 27c9e: ea4f 556b mov.w r5, fp, asr #21 + 27ca2: f149 0900 adc.w r9, r9, #0 + 27ca6: f8dd a018 ldr.w sl, [sp, #24] + 27caa: ea47 27d2 orr.w r7, r7, r2, lsr #11 + 27cae: e9dd 230a ldrd r2, r3, [sp, #40] ; 0x28 + 27cb2: 1b92 subs r2, r2, r6 + 27cb4: e9cd 8918 strd r8, r9, [sp, #96] ; 0x60 + 27cb8: eb63 0307 sbc.w r3, r3, r7 + 27cbc: f8dd b01c ldr.w fp, [sp, #28] + 27cc0: e9dd 6722 ldrd r6, r7, [sp, #136] ; 0x88 + 27cc4: ea4f 5945 mov.w r9, r5, lsl #21 + 27cc8: 1936 adds r6, r6, r4 + 27cca: 416f adcs r7, r5 + 27ccc: ea49 29d4 orr.w r9, r9, r4, lsr #11 + 27cd0: 2500 movs r5, #0 + 27cd2: ea4f 5844 mov.w r8, r4, lsl #21 + 27cd6: ea4f 5a5a mov.w sl, sl, lsr #21 + 27cda: 2400 movs r4, #0 + 27cdc: e9cd 232a strd r2, r3, [sp, #168] ; 0xa8 + 27ce0: f8dd c01c ldr.w ip, [sp, #28] + 27ce4: 4622 mov r2, r4 + 27ce6: 462b mov r3, r5 + 27ce8: ea4a 2bcb orr.w fp, sl, fp, lsl #11 + 27cec: f8cd b038 str.w fp, [sp, #56] ; 0x38 + 27cf0: e9dd ab0c ldrd sl, fp, [sp, #48] ; 0x30 + 27cf4: ebba 0a08 subs.w sl, sl, r8 + 27cf8: eb6b 0b09 sbc.w fp, fp, r9 + 27cfc: ea4f 5c6c mov.w ip, ip, asr #21 + 27d00: f8cd c03c str.w ip, [sp, #60] ; 0x3c + 27d04: e9cd 6722 strd r6, r7, [sp, #136] ; 0x88 + 27d08: e9cd ab32 strd sl, fp, [sp, #200] ; 0xc8 + 27d0c: e9dd 890e ldrd r8, r9, [sp, #56] ; 0x38 + 27d10: e9dd 673c ldrd r6, r7, [sp, #240] ; 0xf0 + 27d14: 46a2 mov sl, r4 + 27d16: 46ab mov fp, r5 + 27d18: eb16 0608 adds.w r6, r6, r8 + 27d1c: e9cd 4506 strd r4, r5, [sp, #24] + 27d20: eb47 0709 adc.w r7, r7, r9 + 27d24: 9c14 ldr r4, [sp, #80] ; 0x50 + 27d26: e9cd 2334 strd r2, r3, [sp, #208] ; 0xd0 + 27d2a: e9cd 230c strd r2, r3, [sp, #48] ; 0x30 + 27d2e: f8dd c054 ldr.w ip, [sp, #84] ; 0x54 + 27d32: e9cd 6736 strd r6, r7, [sp, #216] ; 0xd8 + 27d36: 9b16 ldr r3, [sp, #88] ; 0x58 + 27d38: 9e18 ldr r6, [sp, #96] ; 0x60 + 27d3a: f8dd 805c ldr.w r8, [sp, #92] ; 0x5c + 27d3e: 991b ldr r1, [sp, #108] ; 0x6c + 27d40: 9d1a ldr r5, [sp, #104] ; 0x68 + 27d42: 0d64 lsrs r4, r4, #21 + 27d44: ea44 29cc orr.w r9, r4, ip, lsl #11 + 27d48: 0d5b lsrs r3, r3, #21 + 27d4a: 9c19 ldr r4, [sp, #100] ; 0x64 + 27d4c: 0d72 lsrs r2, r6, #21 + 27d4e: ea4f 566c mov.w r6, ip, asr #21 + 27d52: f8dd c04c ldr.w ip, [sp, #76] ; 0x4c + 27d56: e9cd ab0a strd sl, fp, [sp, #40] ; 0x28 + 27d5a: ea43 27c8 orr.w r7, r3, r8, lsl #11 + 27d5e: ea4f 5b61 mov.w fp, r1, asr #21 + 27d62: ea4f 5a55 mov.w sl, r5, lsr #21 + 27d66: ea4f 5568 mov.w r5, r8, asr #21 + 27d6a: ea4a 2ac1 orr.w sl, sl, r1, lsl #11 + 27d6e: 9708 str r7, [sp, #32] + 27d70: 1563 asrs r3, r4, #21 + 27d72: 9509 str r5, [sp, #36] ; 0x24 + 27d74: 0571 lsls r1, r6, #21 + 27d76: ea4f 584b mov.w r8, fp, lsl #21 + 27d7a: 056f lsls r7, r5, #21 + 27d7c: ea4f 554c mov.w r5, ip, lsl #21 + 27d80: f8dd c03c ldr.w ip, [sp, #60] ; 0x3c + 27d84: 9135 str r1, [sp, #212] ; 0xd4 + 27d86: f8cd 801c str.w r8, [sp, #28] + 27d8a: f8cd 9040 str.w r9, [sp, #64] ; 0x40 + 27d8e: 9908 ldr r1, [sp, #32] + 27d90: f8dd 8048 ldr.w r8, [sp, #72] ; 0x48 + 27d94: ea4f 5943 mov.w r9, r3, lsl #21 + 27d98: f8cd 902c str.w r9, [sp, #44] ; 0x2c + 27d9c: ea4f 5c4c mov.w ip, ip, lsl #21 + 27da0: f8dd 90d4 ldr.w r9, [sp, #212] ; 0xd4 + 27da4: f8cd c034 str.w ip, [sp, #52] ; 0x34 + 27da8: ea47 27d1 orr.w r7, r7, r1, lsr #11 + 27dac: f8dd c040 ldr.w ip, [sp, #64] ; 0x40 + 27db0: 9907 ldr r1, [sp, #28] + 27db2: ea45 25d8 orr.w r5, r5, r8, lsr #11 + 27db6: f8dd 802c ldr.w r8, [sp, #44] ; 0x2c + 27dba: ea42 22c4 orr.w r2, r2, r4, lsl #11 + 27dbe: ea49 29dc orr.w r9, r9, ip, lsr #11 + 27dc2: ea41 21da orr.w r1, r1, sl, lsr #11 + 27dc6: ea48 28d2 orr.w r8, r8, r2, lsr #11 + 27dca: 9611 str r6, [sp, #68] ; 0x44 + 27dcc: f8cd 90d4 str.w r9, [sp, #212] ; 0xd4 + 27dd0: 9107 str r1, [sp, #28] + 27dd2: f8cd 802c str.w r8, [sp, #44] ; 0x2c + 27dd6: f8dd c038 ldr.w ip, [sp, #56] ; 0x38 + 27dda: f8dd 9034 ldr.w r9, [sp, #52] ; 0x34 + 27dde: f8dd 8048 ldr.w r8, [sp, #72] ; 0x48 + 27de2: ea49 29dc orr.w r9, r9, ip, lsr #11 + 27de6: f8cd 9034 str.w r9, [sp, #52] ; 0x34 + 27dea: 9908 ldr r1, [sp, #32] + 27dec: f8dd 9040 ldr.w r9, [sp, #64] ; 0x40 + 27df0: ea4f 5448 mov.w r4, r8, lsl #21 + 27df4: f8dd 8038 ldr.w r8, [sp, #56] ; 0x38 + 27df8: 054e lsls r6, r1, #21 + 27dfa: ea4f 5949 mov.w r9, r9, lsl #21 + 27dfe: ea4f 5848 mov.w r8, r8, lsl #21 + 27e02: f8cd 90d0 str.w r9, [sp, #208] ; 0xd0 + 27e06: f8cd 8030 str.w r8, [sp, #48] ; 0x30 + 27e0a: e9dd 8926 ldrd r8, r9, [sp, #152] ; 0x98 + 27e0e: ebb8 0806 subs.w r8, r8, r6 + 27e12: eb69 0907 sbc.w r9, r9, r7 + 27e16: e9cd 892e strd r8, r9, [sp, #184] ; 0xb8 + 27e1a: e9dd 6732 ldrd r6, r7, [sp, #200] ; 0xc8 + 27e1e: e9dd 8908 ldrd r8, r9, [sp, #32] + 27e22: eb16 0608 adds.w r6, r6, r8 + 27e26: eb47 0709 adc.w r7, r7, r9 + 27e2a: e9cd 6716 strd r6, r7, [sp, #88] ; 0x58 + 27e2e: e9dd 6728 ldrd r6, r7, [sp, #160] ; 0xa0 + 27e32: e9dd 892a ldrd r8, r9, [sp, #168] ; 0xa8 + 27e36: 1b36 subs r6, r6, r4 + 27e38: eb67 0705 sbc.w r7, r7, r5 + 27e3c: e9dd 4510 ldrd r4, r5, [sp, #64] ; 0x40 + 27e40: eb18 0804 adds.w r8, r8, r4 + 27e44: eb49 0905 adc.w r9, r9, r5 + 27e48: ea4f 5c4a mov.w ip, sl, lsl #21 + 27e4c: e9cd 670e strd r6, r7, [sp, #56] ; 0x38 + 27e50: e9dd 6720 ldrd r6, r7, [sp, #128] ; 0x80 + 27e54: e9dd 4530 ldrd r4, r5, [sp, #192] ; 0xc0 + 27e58: e9cd 8910 strd r8, r9, [sp, #64] ; 0x40 + 27e5c: e9dd 8934 ldrd r8, r9, [sp, #208] ; 0xd0 + 27e60: ebb6 0608 subs.w r6, r6, r8 + 27e64: f8cd c018 str.w ip, [sp, #24] + 27e68: eb67 0709 sbc.w r7, r7, r9 + 27e6c: eb14 040a adds.w r4, r4, sl + 27e70: eb45 050b adc.w r5, r5, fp + 27e74: e9dd 891e ldrd r8, r9, [sp, #120] ; 0x78 + 27e78: e9dd ab06 ldrd sl, fp, [sp, #24] + 27e7c: 0551 lsls r1, r2, #21 + 27e7e: ebb8 080a subs.w r8, r8, sl + 27e82: 910a str r1, [sp, #40] ; 0x28 + 27e84: eb69 090b sbc.w r9, r9, fp + 27e88: e9cd 451a strd r4, r5, [sp, #104] ; 0x68 + 27e8c: e9dd 452c ldrd r4, r5, [sp, #176] ; 0xb0 + 27e90: e9dd ab0a ldrd sl, fp, [sp, #40] ; 0x28 + 27e94: 18a4 adds r4, r4, r2 + 27e96: 415d adcs r5, r3 + 27e98: e9cd 8918 strd r8, r9, [sp, #96] ; 0x60 + 27e9c: e9dd 8924 ldrd r8, r9, [sp, #144] ; 0x90 + 27ea0: e9dd 231c ldrd r2, r3, [sp, #112] ; 0x70 + 27ea4: ebb8 080a subs.w r8, r8, sl + 27ea8: f642 4a13 movw sl, #11283 ; 0x2c13 + 27eac: eb69 090b sbc.w r9, r9, fp + 27eb0: f642 5b18 movw fp, #11544 ; 0x2d18 + 27eb4: f2c0 0a0a movt sl, #10 + 27eb8: f2c0 0b07 movt fp, #7 + 27ebc: e9cd 4534 strd r4, r5, [sp, #208] ; 0xd0 + 27ec0: e9dd 450c ldrd r4, r5, [sp, #48] ; 0x30 + 27ec4: 1b12 subs r2, r2, r4 + 27ec6: eb63 0305 sbc.w r3, r3, r5 + 27eca: e9cd 8914 strd r8, r9, [sp, #80] ; 0x50 + 27ece: e9cd 233a strd r2, r3, [sp, #232] ; 0xe8 + 27ed2: e9dd 8922 ldrd r8, r9, [sp, #136] ; 0x88 + 27ed6: e9dd 2336 ldrd r2, r3, [sp, #216] ; 0xd8 + 27eda: f518 1880 adds.w r8, r8, #1048576 ; 0x100000 + 27ede: f149 0900 adc.w r9, r9, #0 + 27ee2: f512 1280 adds.w r2, r2, #1048576 ; 0x100000 + 27ee6: f143 0300 adc.w r3, r3, #0 + 27eea: 0d51 lsrs r1, r2, #21 + 27eec: ea41 21c3 orr.w r1, r1, r3, lsl #11 + 27ef0: fba1 450a umull r4, r5, r1, sl + 27ef4: ea4f 5c63 mov.w ip, r3, asr #21 + 27ef8: fba1 230b umull r2, r3, r1, fp + 27efc: fb0a 550c mla r5, sl, ip, r5 + 27f00: fb0b 330c mla r3, fp, ip, r3 + 27f04: e9dd ab0e ldrd sl, fp, [sp, #56] ; 0x38 + 27f08: eb1a 0a04 adds.w sl, sl, r4 + 27f0c: eb4b 0b05 adc.w fp, fp, r5 + 27f10: 1992 adds r2, r2, r6 + 27f12: f64f 3667 movw r6, #64359 ; 0xfb67 + 27f16: f2c0 0609 movt r6, #9 + 27f1a: e9cd ab24 strd sl, fp, [sp, #144] ; 0x90 + 27f1e: 417b adcs r3, r7 + 27f20: ea4f 575a mov.w r7, sl, lsr #21 + 27f24: fba1 4506 umull r4, r5, r1, r6 + 27f28: ea47 2acb orr.w sl, r7, fp, lsl #11 + 27f2c: f8dd b094 ldr.w fp, [sp, #148] ; 0x94 + 27f30: f8cd a038 str.w sl, [sp, #56] ; 0x38 + 27f34: ea4f 5b6b mov.w fp, fp, asr #21 + 27f38: f8cd b03c str.w fp, [sp, #60] ; 0x3c + 27f3c: fb06 550c mla r5, r6, ip, r5 + 27f40: e9dd 670e ldrd r6, r7, [sp, #56] ; 0x38 + 27f44: 18b6 adds r6, r6, r2 + 27f46: 415f adcs r7, r3 + 27f48: e9cd 6720 strd r6, r7, [sp, #128] ; 0x80 + 27f4c: e9dd 2310 ldrd r2, r3, [sp, #64] ; 0x40 + 27f50: f24c 6753 movw r7, #50771 ; 0xc653 + 27f54: f6cf 77f0 movt r7, #65520 ; 0xfff0 + 27f58: f04f 0a00 mov.w sl, #0 + 27f5c: f04f 0b00 mov.w fp, #0 + 27f60: 0d76 lsrs r6, r6, #21 + 27f62: e9cd ab12 strd sl, fp, [sp, #72] ; 0x48 + 27f66: 18a4 adds r4, r4, r2 + 27f68: 9612 str r6, [sp, #72] ; 0x48 + 27f6a: f8dd b084 ldr.w fp, [sp, #132] ; 0x84 + 27f6e: 415d adcs r5, r3 + 27f70: f8dd a048 ldr.w sl, [sp, #72] ; 0x48 + 27f74: 424b negs r3, r1 + 27f76: fb07 360c mla r6, r7, ip, r3 + 27f7a: 930a str r3, [sp, #40] ; 0x28 + 27f7c: fba1 2307 umull r2, r3, r1, r7 + 27f80: ea4a 2acb orr.w sl, sl, fp, lsl #11 + 27f84: ea4f 576b mov.w r7, fp, asr #21 + 27f88: 9713 str r7, [sp, #76] ; 0x4c + 27f8a: f8cd a048 str.w sl, [sp, #72] ; 0x48 + 27f8e: e9dd ab12 ldrd sl, fp, [sp, #72] ; 0x48 + 27f92: eb1a 0a04 adds.w sl, sl, r4 + 27f96: eb4b 0b05 adc.w fp, fp, r5 + 27f9a: 4433 add r3, r6 + 27f9c: e9dd 672e ldrd r6, r7, [sp, #184] ; 0xb8 + 27fa0: 18b6 adds r6, r6, r2 + 27fa2: 415f adcs r7, r3 + 27fa4: e9cd 6708 strd r6, r7, [sp, #32] + 27fa8: f241 57d1 movw r7, #5585 ; 0x15d1 + 27fac: f2c0 0702 movt r7, #2 + 27fb0: e9cd ab26 strd sl, fp, [sp, #152] ; 0x98 + 27fb4: fba1 4507 umull r4, r5, r1, r7 + 27fb8: f8dd a098 ldr.w sl, [sp, #152] ; 0x98 + 27fbc: f8dd b09c ldr.w fp, [sp, #156] ; 0x9c + 27fc0: 9a27 ldr r2, [sp, #156] ; 0x9c + 27fc2: ea4f 5a5a mov.w sl, sl, lsr #21 + 27fc6: fb07 550c mla r5, r7, ip, r5 + 27fca: e9dd 6708 ldrd r6, r7, [sp, #32] + 27fce: ea4a 2bcb orr.w fp, sl, fp, lsl #11 + 27fd2: 1552 asrs r2, r2, #21 + 27fd4: f8cd b040 str.w fp, [sp, #64] ; 0x40 + 27fd8: 9211 str r2, [sp, #68] ; 0x44 + 27fda: ea4f 5a58 mov.w sl, r8, lsr #21 + 27fde: e9dd 2310 ldrd r2, r3, [sp, #64] ; 0x40 + 27fe2: ea4a 2ac9 orr.w sl, sl, r9, lsl #11 + 27fe6: 18b6 adds r6, r6, r2 + 27fe8: ea4f 5b69 mov.w fp, r9, asr #21 + 27fec: 415f adcs r7, r3 + 27fee: e9dd 8916 ldrd r8, r9, [sp, #88] ; 0x58 + 27ff2: ea4f 524a mov.w r2, sl, lsl #21 + 27ff6: eb18 0804 adds.w r8, r8, r4 + 27ffa: ea4f 534b mov.w r3, fp, lsl #21 + 27ffe: eb49 0905 adc.w r9, r9, r5 + 28002: ea43 23da orr.w r3, r3, sl, lsr #11 + 28006: e9dd 4522 ldrd r4, r5, [sp, #136] ; 0x88 + 2800a: 1aa4 subs r4, r4, r2 + 2800c: e9cd 672c strd r6, r7, [sp, #176] ; 0xb0 + 28010: eb65 0503 sbc.w r5, r5, r3 + 28014: 2600 movs r6, #0 + 28016: 2700 movs r7, #0 + 28018: e9cd 6708 strd r6, r7, [sp, #32] + 2801c: e9cd 8906 strd r8, r9, [sp, #24] + 28020: e9cd 450c strd r4, r5, [sp, #48] ; 0x30 + 28024: 9d2c ldr r5, [sp, #176] ; 0xb0 + 28026: f8dd 90b4 ldr.w r9, [sp, #180] ; 0xb4 + 2802a: 0d6d lsrs r5, r5, #21 + 2802c: 9508 str r5, [sp, #32] + 2802e: f8dd 8020 ldr.w r8, [sp, #32] + 28032: 9f0a ldr r7, [sp, #40] ; 0x28 + 28034: ea4f 5269 mov.w r2, r9, asr #21 + 28038: ea48 28c9 orr.w r8, r8, r9, lsl #11 + 2803c: fba1 450e umull r4, r5, r1, lr + 28040: fb0e 760c mla r6, lr, ip, r7 + 28044: 9209 str r2, [sp, #36] ; 0x24 + 28046: f8cd 8020 str.w r8, [sp, #32] + 2804a: e9dd 2306 ldrd r2, r3, [sp, #24] + 2804e: e9dd 8908 ldrd r8, r9, [sp, #32] + 28052: eb18 0802 adds.w r8, r8, r2 + 28056: eb49 0903 adc.w r9, r9, r3 + 2805a: e9cd 8922 strd r8, r9, [sp, #136] ; 0x88 + 2805e: e9dd 230c ldrd r2, r3, [sp, #48] ; 0x30 + 28062: 4435 add r5, r6 + 28064: 1912 adds r2, r2, r4 + 28066: f8dd 9088 ldr.w r9, [sp, #136] ; 0x88 + 2806a: 416b adcs r3, r5 + 2806c: 9c23 ldr r4, [sp, #140] ; 0x8c + 2806e: 9d23 ldr r5, [sp, #140] ; 0x8c + 28070: ea4f 5959 mov.w r9, r9, lsr #21 + 28074: ea49 24c4 orr.w r4, r9, r4, lsl #11 + 28078: 156d asrs r5, r5, #21 + 2807a: 9406 str r4, [sp, #24] + 2807c: 9507 str r5, [sp, #28] + 2807e: e9dd 6706 ldrd r6, r7, [sp, #24] + 28082: 18b6 adds r6, r6, r2 + 28084: 415f adcs r7, r3 + 28086: e9cd 672a strd r6, r7, [sp, #168] ; 0xa8 + 2808a: e9dd 891a ldrd r8, r9, [sp, #104] ; 0x68 + 2808e: e9dd 6718 ldrd r6, r7, [sp, #96] ; 0x60 + 28092: f518 1880 adds.w r8, r8, #1048576 ; 0x100000 + 28096: f149 0900 adc.w r9, r9, #0 + 2809a: eb16 060a adds.w r6, r6, sl + 2809e: f8dd a0a8 ldr.w sl, [sp, #168] ; 0xa8 + 280a2: eb47 070b adc.w r7, r7, fp + 280a6: 9a2b ldr r2, [sp, #172] ; 0xac + 280a8: f8dd b0ac ldr.w fp, [sp, #172] ; 0xac + 280ac: ea4f 5a5a mov.w sl, sl, lsr #21 + 280b0: ea4a 2bcb orr.w fp, sl, fp, lsl #11 + 280b4: 1552 asrs r2, r2, #21 + 280b6: f8cd b028 str.w fp, [sp, #40] ; 0x28 + 280ba: 920b str r2, [sp, #44] ; 0x2c + 280bc: ea4f 5458 mov.w r4, r8, lsr #21 + 280c0: ea44 24c9 orr.w r4, r4, r9, lsl #11 + 280c4: ea4f 5569 mov.w r5, r9, asr #21 + 280c8: e9dd 890a ldrd r8, r9, [sp, #40] ; 0x28 + 280cc: eb18 0806 adds.w r8, r8, r6 + 280d0: eb49 0907 adc.w r9, r9, r7 + 280d4: 056b lsls r3, r5, #21 + 280d6: 0562 lsls r2, r4, #21 + 280d8: e9cd 8930 strd r8, r9, [sp, #192] ; 0xc0 + 280dc: e9dd ab1a ldrd sl, fp, [sp, #104] ; 0x68 + 280e0: ea43 23d4 orr.w r3, r3, r4, lsr #11 + 280e4: ebba 0202 subs.w r2, sl, r2 + 280e8: eb6b 0303 sbc.w r3, fp, r3 + 280ec: f8dd b0c0 ldr.w fp, [sp, #192] ; 0xc0 + 280f0: 9e31 ldr r6, [sp, #196] ; 0xc4 + 280f2: ea4f 585b mov.w r8, fp, lsr #21 + 280f6: ea48 28c6 orr.w r8, r8, r6, lsl #11 + 280fa: eb12 0a08 adds.w sl, r2, r8 + 280fe: ea4f 5966 mov.w r9, r6, asr #21 + 28102: eb43 0b09 adc.w fp, r3, r9 + 28106: e9cd ab32 strd sl, fp, [sp, #200] ; 0xc8 + 2810a: e9dd 6734 ldrd r6, r7, [sp, #208] ; 0xd0 + 2810e: e9dd ab14 ldrd sl, fp, [sp, #80] ; 0x50 + 28112: f516 1680 adds.w r6, r6, #1048576 ; 0x100000 + 28116: f147 0700 adc.w r7, r7, #0 + 2811a: eb1a 0a04 adds.w sl, sl, r4 + 2811e: 9c32 ldr r4, [sp, #200] ; 0xc8 + 28120: eb4b 0b05 adc.w fp, fp, r5 + 28124: 9d33 ldr r5, [sp, #204] ; 0xcc + 28126: 0d62 lsrs r2, r4, #21 + 28128: ea42 22c5 orr.w r2, r2, r5, lsl #11 + 2812c: 156b asrs r3, r5, #21 + 2812e: 2400 movs r4, #0 + 28130: 2500 movs r5, #0 + 28132: e9cd 451a strd r4, r5, [sp, #104] ; 0x68 + 28136: 0d74 lsrs r4, r6, #21 + 28138: eb1a 0602 adds.w r6, sl, r2 + 2813c: ea44 24c7 orr.w r4, r4, r7, lsl #11 + 28140: f04f 0a00 mov.w sl, #0 + 28144: ea4f 5567 mov.w r5, r7, asr #21 + 28148: eb4b 0703 adc.w r7, fp, r3 + 2814c: f04f 0b00 mov.w fp, #0 + 28150: e9cd 672e strd r6, r7, [sp, #184] ; 0xb8 + 28154: 4656 mov r6, sl + 28156: 465f mov r7, fp + 28158: ea4f 5c4c mov.w ip, ip, lsl #21 + 2815c: e9cd ab38 strd sl, fp, [sp, #224] ; 0xe0 + 28160: e9cd ab14 strd sl, fp, [sp, #80] ; 0x50 + 28164: e9cd ab1e strd sl, fp, [sp, #120] ; 0x78 + 28168: e9cd ab1c strd sl, fp, [sp, #112] ; 0x70 + 2816c: f8cd c06c str.w ip, [sp, #108] ; 0x6c + 28170: f8dd a03c ldr.w sl, [sp, #60] ; 0x3c + 28174: f8dd c04c ldr.w ip, [sp, #76] ; 0x4c + 28178: e9cd 6718 strd r6, r7, [sp, #96] ; 0x60 + 2817c: e9cd 6716 strd r6, r7, [sp, #88] ; 0x58 + 28180: e9cd 6728 strd r6, r7, [sp, #160] ; 0xa0 + 28184: e9cd 670c strd r6, r7, [sp, #48] ; 0x30 + 28188: ea4f 5c4c mov.w ip, ip, lsl #21 + 2818c: ea4f 574a mov.w r7, sl, lsl #21 + 28190: f8dd a024 ldr.w sl, [sp, #36] ; 0x24 + 28194: f8cd c064 str.w ip, [sp, #100] ; 0x64 + 28198: f8dd b044 ldr.w fp, [sp, #68] ; 0x44 + 2819c: f8dd c02c ldr.w ip, [sp, #44] ; 0x2c + 281a0: ea4f 5a4a mov.w sl, sl, lsl #21 + 281a4: f8cd a054 str.w sl, [sp, #84] ; 0x54 + 281a8: ea4f 5b4b mov.w fp, fp, lsl #21 + 281ac: ea4f 5a49 mov.w sl, r9, lsl #21 + 281b0: ea4f 5c4c mov.w ip, ip, lsl #21 + 281b4: f8cd b0e4 str.w fp, [sp, #228] ; 0xe4 + 281b8: f8cd c07c str.w ip, [sp, #124] ; 0x7c + 281bc: f8dd b01c ldr.w fp, [sp, #28] + 281c0: f8cd a0a4 str.w sl, [sp, #164] ; 0xa4 + 281c4: f8dd c0b8 ldr.w ip, [sp, #184] ; 0xb8 + 281c8: f8dd a06c ldr.w sl, [sp, #108] ; 0x6c + 281cc: ea4f 5b4b mov.w fp, fp, lsl #21 + 281d0: ea4a 2ad1 orr.w sl, sl, r1, lsr #11 + 281d4: ea4f 5c5c mov.w ip, ip, lsr #21 + 281d8: f8cd b05c str.w fp, [sp, #92] ; 0x5c + 281dc: f8cd c030 str.w ip, [sp, #48] ; 0x30 + 281e0: ea4f 5b43 mov.w fp, r3, lsl #21 + 281e4: f8dd c0e4 ldr.w ip, [sp, #228] ; 0xe4 + 281e8: f8cd a06c str.w sl, [sp, #108] ; 0x6c + 281ec: f8dd a040 ldr.w sl, [sp, #64] ; 0x40 + 281f0: f8cd b074 str.w fp, [sp, #116] ; 0x74 + 281f4: f8dd b038 ldr.w fp, [sp, #56] ; 0x38 + 281f8: ea4c 2cda orr.w ip, ip, sl, lsr #11 + 281fc: ea47 27db orr.w r7, r7, fp, lsr #11 + 28200: f8cd c0e4 str.w ip, [sp, #228] ; 0xe4 + 28204: f8dd b064 ldr.w fp, [sp, #100] ; 0x64 + 28208: f8dd c048 ldr.w ip, [sp, #72] ; 0x48 + 2820c: 0549 lsls r1, r1, #21 + 2820e: ea4b 2bdc orr.w fp, fp, ip, lsr #11 + 28212: f8cd b064 str.w fp, [sp, #100] ; 0x64 + 28216: f8dd a054 ldr.w sl, [sp, #84] ; 0x54 + 2821a: f8dd b020 ldr.w fp, [sp, #32] + 2821e: f8dd c05c ldr.w ip, [sp, #92] ; 0x5c + 28222: ea4a 2adb orr.w sl, sl, fp, lsr #11 + 28226: f8cd a054 str.w sl, [sp, #84] ; 0x54 + 2822a: f8dd a018 ldr.w sl, [sp, #24] + 2822e: f8dd b07c ldr.w fp, [sp, #124] ; 0x7c + 28232: ea4c 2cda orr.w ip, ip, sl, lsr #11 + 28236: f8cd c05c str.w ip, [sp, #92] ; 0x5c + 2823a: f8dd c028 ldr.w ip, [sp, #40] ; 0x28 + 2823e: f8dd a0a4 ldr.w sl, [sp, #164] ; 0xa4 + 28242: ea4b 2bdc orr.w fp, fp, ip, lsr #11 + 28246: f8cd b07c str.w fp, [sp, #124] ; 0x7c + 2824a: ea4a 2ad8 orr.w sl, sl, r8, lsr #11 + 2824e: f8dd b074 ldr.w fp, [sp, #116] ; 0x74 + 28252: f8dd c030 ldr.w ip, [sp, #48] ; 0x30 + 28256: f8cd a0a4 str.w sl, [sp, #164] ; 0xa4 + 2825a: f8dd a0bc ldr.w sl, [sp, #188] ; 0xbc + 2825e: ea4b 2bd2 orr.w fp, fp, r2, lsr #11 + 28262: f8cd b074 str.w fp, [sp, #116] ; 0x74 + 28266: ea4c 2cca orr.w ip, ip, sl, lsl #11 + 2826a: f8dd b038 ldr.w fp, [sp, #56] ; 0x38 + 2826e: f8cd c030 str.w ip, [sp, #48] ; 0x30 + 28272: f8dd c040 ldr.w ip, [sp, #64] ; 0x40 + 28276: 911a str r1, [sp, #104] ; 0x68 + 28278: ea4f 564b mov.w r6, fp, lsl #21 + 2827c: 9912 ldr r1, [sp, #72] ; 0x48 + 2827e: f8dd a020 ldr.w sl, [sp, #32] + 28282: f8dd b018 ldr.w fp, [sp, #24] + 28286: ea4f 5c4c mov.w ip, ip, lsl #21 + 2828a: f8cd c0e0 str.w ip, [sp, #224] ; 0xe0 + 2828e: f8dd 90bc ldr.w r9, [sp, #188] ; 0xbc + 28292: f8dd c028 ldr.w ip, [sp, #40] ; 0x28 + 28296: 0549 lsls r1, r1, #21 + 28298: ea4f 5a4a mov.w sl, sl, lsl #21 + 2829c: ea4f 5b4b mov.w fp, fp, lsl #21 + 282a0: 9118 str r1, [sp, #96] ; 0x60 + 282a2: f8cd a050 str.w sl, [sp, #80] ; 0x50 + 282a6: f8cd b058 str.w fp, [sp, #88] ; 0x58 + 282aa: ea4f 5148 mov.w r1, r8, lsl #21 + 282ae: e9dd ab36 ldrd sl, fp, [sp, #216] ; 0xd8 + 282b2: ea4f 5842 mov.w r8, r2, lsl #21 + 282b6: e9dd 231a ldrd r2, r3, [sp, #104] ; 0x68 + 282ba: ebba 0a02 subs.w sl, sl, r2 + 282be: eb6b 0b03 sbc.w fp, fp, r3 + 282c2: 0562 lsls r2, r4, #21 + 282c4: ea4f 5c4c mov.w ip, ip, lsl #21 + 282c8: ea4f 5969 mov.w r9, r9, asr #21 + 282cc: 056b lsls r3, r5, #21 + 282ce: f8cd c078 str.w ip, [sp, #120] ; 0x78 + 282d2: 9128 str r1, [sp, #160] ; 0xa0 + 282d4: f8cd 8070 str.w r8, [sp, #112] ; 0x70 + 282d8: f8cd 9034 str.w r9, [sp, #52] ; 0x34 + 282dc: ea43 23d4 orr.w r3, r3, r4, lsr #11 + 282e0: e9cd ab0e strd sl, fp, [sp, #56] ; 0x38 + 282e4: e9dd 8934 ldrd r8, r9, [sp, #208] ; 0xd0 + 282e8: e9dd ab24 ldrd sl, fp, [sp, #144] ; 0x90 + 282ec: ebb8 0802 subs.w r8, r8, r2 + 282f0: eb69 0903 sbc.w r9, r9, r3 + 282f4: ebba 0a06 subs.w sl, sl, r6 + 282f8: e9dd 2326 ldrd r2, r3, [sp, #152] ; 0x98 + 282fc: eb6b 0b07 sbc.w fp, fp, r7 + 28300: e9dd 6738 ldrd r6, r7, [sp, #224] ; 0xe0 + 28304: 1b92 subs r2, r2, r6 + 28306: eb63 0307 sbc.w r3, r3, r7 + 2830a: e9cd ab12 strd sl, fp, [sp, #72] ; 0x48 + 2830e: e9dd ab20 ldrd sl, fp, [sp, #128] ; 0x80 + 28312: e9dd 672c ldrd r6, r7, [sp, #176] ; 0xb0 + 28316: e9cd 2308 strd r2, r3, [sp, #32] + 2831a: e9dd 2318 ldrd r2, r3, [sp, #96] ; 0x60 + 2831e: ebba 0a02 subs.w sl, sl, r2 + 28322: eb6b 0b03 sbc.w fp, fp, r3 + 28326: e9cd ab10 strd sl, fp, [sp, #64] ; 0x40 + 2832a: e9dd ab14 ldrd sl, fp, [sp, #80] ; 0x50 + 2832e: e9dd 2322 ldrd r2, r3, [sp, #136] ; 0x88 + 28332: ebb6 060a subs.w r6, r6, sl + 28336: eb67 070b sbc.w r7, r7, fp + 2833a: e9cd 6706 strd r6, r7, [sp, #24] + 2833e: e9dd 6716 ldrd r6, r7, [sp, #88] ; 0x58 + 28342: e9dd ab2a ldrd sl, fp, [sp, #168] ; 0xa8 + 28346: 1b92 subs r2, r2, r6 + 28348: eb63 0307 sbc.w r3, r3, r7 + 2834c: e9cd 2324 strd r2, r3, [sp, #144] ; 0x90 + 28350: e9dd 231e ldrd r2, r3, [sp, #120] ; 0x78 + 28354: e9dd 6730 ldrd r6, r7, [sp, #192] ; 0xc0 + 28358: ebba 0a02 subs.w sl, sl, r2 + 2835c: eb6b 0b03 sbc.w fp, fp, r3 + 28360: e9cd ab20 strd sl, fp, [sp, #128] ; 0x80 + 28364: e9dd ab28 ldrd sl, fp, [sp, #160] ; 0xa0 + 28368: e9dd 2332 ldrd r2, r3, [sp, #200] ; 0xc8 + 2836c: ebb6 060a subs.w r6, r6, sl + 28370: eb67 070b sbc.w r7, r7, fp + 28374: e9cd 6726 strd r6, r7, [sp, #152] ; 0x98 + 28378: e9dd 671c ldrd r6, r7, [sp, #112] ; 0x70 + 2837c: e9dd ab0c ldrd sl, fp, [sp, #48] ; 0x30 + 28380: 1b92 subs r2, r2, r6 + 28382: eb63 0307 sbc.w r3, r3, r7 + 28386: e9cd 232c strd r2, r3, [sp, #176] ; 0xb0 + 2838a: e9dd 233a ldrd r2, r3, [sp, #232] ; 0xe8 + 2838e: e9dd 670e ldrd r6, r7, [sp, #56] ; 0x38 + 28392: 1912 adds r2, r2, r4 + 28394: 416b adcs r3, r5 + 28396: eb1a 0a08 adds.w sl, sl, r8 + 2839a: eb4b 0b09 adc.w fp, fp, r9 + 2839e: e9cd ab0a strd sl, fp, [sp, #40] ; 0x28 + 283a2: f8dd c028 ldr.w ip, [sp, #40] ; 0x28 + 283a6: 990b ldr r1, [sp, #44] ; 0x2c + 283a8: ea4f 5a5c mov.w sl, ip, lsr #21 + 283ac: ea4a 2ac1 orr.w sl, sl, r1, lsl #11 + 283b0: eb12 040a adds.w r4, r2, sl + 283b4: ea4f 5b61 mov.w fp, r1, asr #21 + 283b8: eb43 050b adc.w r5, r3, fp + 283bc: e9cd 451a strd r4, r5, [sp, #104] ; 0x68 + 283c0: ea4f 5854 mov.w r8, r4, lsr #21 + 283c4: ea48 28c5 orr.w r8, r8, r5, lsl #11 + 283c8: 9d1b ldr r5, [sp, #108] ; 0x6c + 283ca: eb16 0608 adds.w r6, r6, r8 + 283ce: ea4f 5965 mov.w r9, r5, asr #21 + 283d2: eb47 0709 adc.w r7, r7, r9 + 283d6: 0d71 lsrs r1, r6, #21 + 283d8: ea41 21c7 orr.w r1, r1, r7, lsl #11 + 283dc: e9cd 6718 strd r6, r7, [sp, #96] ; 0x60 + 283e0: f642 4713 movw r7, #11283 ; 0x2c13 + 283e4: f2c0 070a movt r7, #10 + 283e8: f642 5318 movw r3, #11544 ; 0x2d18 + 283ec: fba1 4507 umull r4, r5, r1, r7 + 283f0: f8dd c064 ldr.w ip, [sp, #100] ; 0x64 + 283f4: f2c0 0307 movt r3, #7 + 283f8: ea4f 566c mov.w r6, ip, asr #21 + 283fc: fb07 5506 mla r5, r7, r6, r5 + 28400: f642 5718 movw r7, #11544 ; 0x2d18 + 28404: f2c0 0707 movt r7, #7 + 28408: fba1 2303 umull r2, r3, r1, r3 + 2840c: fb07 3706 mla r7, r7, r6, r3 + 28410: e9cd 2316 strd r2, r3, [sp, #88] ; 0x58 + 28414: e9dd 2312 ldrd r2, r3, [sp, #72] ; 0x48 + 28418: 1912 adds r2, r2, r4 + 2841a: 9717 str r7, [sp, #92] ; 0x5c + 2841c: 416b adcs r3, r5 + 2841e: e9cd 2314 strd r2, r3, [sp, #80] ; 0x50 + 28422: e9dd 4510 ldrd r4, r5, [sp, #64] ; 0x40 + 28426: e9dd 2316 ldrd r2, r3, [sp, #88] ; 0x58 + 2842a: 1912 adds r2, r2, r4 + 2842c: 416b adcs r3, r5 + 2842e: e9cd 2310 strd r2, r3, [sp, #64] ; 0x40 + 28432: f64f 3367 movw r3, #64359 ; 0xfb67 + 28436: f64f 3c67 movw ip, #64359 ; 0xfb67 + 2843a: f2c0 0309 movt r3, #9 + 2843e: f2c0 0c09 movt ip, #9 + 28442: fba1 2303 umull r2, r3, r1, r3 + 28446: 9c14 ldr r4, [sp, #80] ; 0x50 + 28448: 9d15 ldr r5, [sp, #84] ; 0x54 + 2844a: 9f15 ldr r7, [sp, #84] ; 0x54 + 2844c: 0d64 lsrs r4, r4, #21 + 2844e: fb0c 3c06 mla ip, ip, r6, r3 + 28452: ea44 25c5 orr.w r5, r4, r5, lsl #11 + 28456: 157f asrs r7, r7, #21 + 28458: 950e str r5, [sp, #56] ; 0x38 + 2845a: 970f str r7, [sp, #60] ; 0x3c + 2845c: e9cd 231c strd r2, r3, [sp, #112] ; 0x70 + 28460: e9dd 4510 ldrd r4, r5, [sp, #64] ; 0x40 + 28464: e9dd 230e ldrd r2, r3, [sp, #56] ; 0x38 + 28468: 1912 adds r2, r2, r4 + 2846a: 416b adcs r3, r5 + 2846c: f8cd c074 str.w ip, [sp, #116] ; 0x74 + 28470: e9cd 2316 strd r2, r3, [sp, #88] ; 0x58 + 28474: e9dd 4508 ldrd r4, r5, [sp, #32] + 28478: 2200 movs r2, #0 + 2847a: 2300 movs r3, #0 + 2847c: e9cd 2312 strd r2, r3, [sp, #72] ; 0x48 + 28480: e9dd 231c ldrd r2, r3, [sp, #112] ; 0x70 + 28484: 18a4 adds r4, r4, r2 + 28486: 415d adcs r5, r3 + 28488: 9b16 ldr r3, [sp, #88] ; 0x58 + 2848a: e9cd 4508 strd r4, r5, [sp, #32] + 2848e: 0d5b lsrs r3, r3, #21 + 28490: 9312 str r3, [sp, #72] ; 0x48 + 28492: f24c 6353 movw r3, #50771 ; 0xc653 + 28496: f24c 6453 movw r4, #50771 ; 0xc653 + 2849a: f6cf 73f0 movt r3, #65520 ; 0xfff0 + 2849e: f6cf 74f0 movt r4, #65520 ; 0xfff0 + 284a2: fba1 2303 umull r2, r3, r1, r3 + 284a6: 424f negs r7, r1 + 284a8: fb04 7c06 mla ip, r4, r6, r7 + 284ac: 9d17 ldr r5, [sp, #92] ; 0x5c + 284ae: 9c12 ldr r4, [sp, #72] ; 0x48 + 284b0: e9cd 231c strd r2, r3, [sp, #112] ; 0x70 + 284b4: ea44 24c5 orr.w r4, r4, r5, lsl #11 + 284b8: 156a asrs r2, r5, #21 + 284ba: 9213 str r2, [sp, #76] ; 0x4c + 284bc: 9412 str r4, [sp, #72] ; 0x48 + 284be: e9dd 2308 ldrd r2, r3, [sp, #32] + 284c2: e9dd 4512 ldrd r4, r5, [sp, #72] ; 0x48 + 284c6: 18a4 adds r4, r4, r2 + 284c8: 415d adcs r5, r3 + 284ca: e9cd 451e strd r4, r5, [sp, #120] ; 0x78 + 284ce: e9dd 2306 ldrd r2, r3, [sp, #24] + 284d2: 9d1d ldr r5, [sp, #116] ; 0x74 + 284d4: fb0e 7706 mla r7, lr, r6, r7 + 284d8: 4465 add r5, ip + 284da: 951d str r5, [sp, #116] ; 0x74 + 284dc: e9dd 451c ldrd r4, r5, [sp, #112] ; 0x70 + 284e0: 1912 adds r2, r2, r4 + 284e2: 416b adcs r3, r5 + 284e4: e9cd 2306 strd r2, r3, [sp, #24] + 284e8: f241 53d1 movw r3, #5585 ; 0x15d1 + 284ec: f241 5cd1 movw ip, #5585 ; 0x15d1 + 284f0: f2c0 0302 movt r3, #2 + 284f4: f2c0 0c02 movt ip, #2 + 284f8: fba1 2303 umull r2, r3, r1, r3 + 284fc: 9c1e ldr r4, [sp, #120] ; 0x78 + 284fe: e9cd 231c strd r2, r3, [sp, #112] ; 0x70 + 28502: 9d1f ldr r5, [sp, #124] ; 0x7c + 28504: 9a1f ldr r2, [sp, #124] ; 0x7c + 28506: fb0c 3c06 mla ip, ip, r6, r3 + 2850a: 0d64 lsrs r4, r4, #21 + 2850c: ea44 25c5 orr.w r5, r4, r5, lsl #11 + 28510: 1552 asrs r2, r2, #21 + 28512: 9211 str r2, [sp, #68] ; 0x44 + 28514: 9510 str r5, [sp, #64] ; 0x40 + 28516: e9dd 2306 ldrd r2, r3, [sp, #24] + 2851a: e9dd 4510 ldrd r4, r5, [sp, #64] ; 0x40 + 2851e: 18a4 adds r4, r4, r2 + 28520: f8cd c074 str.w ip, [sp, #116] ; 0x74 + 28524: 415d adcs r5, r3 + 28526: e9cd 4528 strd r4, r5, [sp, #160] ; 0xa0 + 2852a: e9dd 2324 ldrd r2, r3, [sp, #144] ; 0x90 + 2852e: e9dd 451c ldrd r4, r5, [sp, #112] ; 0x70 + 28532: 1912 adds r2, r2, r4 + 28534: 416b adcs r3, r5 + 28536: e9cd 2306 strd r2, r3, [sp, #24] + 2853a: fba1 230e umull r2, r3, r1, lr + 2853e: 9d28 ldr r5, [sp, #160] ; 0xa0 + 28540: 9c29 ldr r4, [sp, #164] ; 0xa4 + 28542: 0d6d lsrs r5, r5, #21 + 28544: e9cd 2322 strd r2, r3, [sp, #136] ; 0x88 + 28548: ea45 23c4 orr.w r3, r5, r4, lsl #11 + 2854c: 1565 asrs r5, r4, #21 + 2854e: 9509 str r5, [sp, #36] ; 0x24 + 28550: 9308 str r3, [sp, #32] + 28552: e9dd 4506 ldrd r4, r5, [sp, #24] + 28556: e9dd 2308 ldrd r2, r3, [sp, #32] + 2855a: 1912 adds r2, r2, r4 + 2855c: 416b adcs r3, r5 + 2855e: e9cd 231c strd r2, r3, [sp, #112] ; 0x70 + 28562: 9b23 ldr r3, [sp, #140] ; 0x8c + 28564: f8dd c074 ldr.w ip, [sp, #116] ; 0x74 + 28568: 443b add r3, r7 + 2856a: 9323 str r3, [sp, #140] ; 0x8c + 2856c: e9dd 4522 ldrd r4, r5, [sp, #136] ; 0x88 + 28570: e9dd 2320 ldrd r2, r3, [sp, #128] ; 0x80 + 28574: 1912 adds r2, r2, r4 + 28576: 416b adcs r3, r5 + 28578: 9d1c ldr r5, [sp, #112] ; 0x70 + 2857a: 9f1d ldr r7, [sp, #116] ; 0x74 + 2857c: 0d6d lsrs r5, r5, #21 + 2857e: ea45 27c7 orr.w r7, r5, r7, lsl #11 + 28582: ea4f 5c6c mov.w ip, ip, asr #21 + 28586: 9706 str r7, [sp, #24] + 28588: f8cd c01c str.w ip, [sp, #28] + 2858c: e9dd 4506 ldrd r4, r5, [sp, #24] + 28590: f8dd c030 ldr.w ip, [sp, #48] ; 0x30 + 28594: 18a4 adds r4, r4, r2 + 28596: 9f0d ldr r7, [sp, #52] ; 0x34 + 28598: 415d adcs r5, r3 + 2859a: e9cd 4524 strd r4, r5, [sp, #144] ; 0x90 + 2859e: e9dd 232e ldrd r2, r3, [sp, #184] ; 0xb8 + 285a2: ea4f 544c mov.w r4, ip, lsl #21 + 285a6: 057d lsls r5, r7, #21 + 285a8: 1b12 subs r2, r2, r4 + 285aa: ea45 25dc orr.w r5, r5, ip, lsr #11 + 285ae: eb63 0305 sbc.w r3, r3, r5 + 285b2: e9cd 230c strd r2, r3, [sp, #48] ; 0x30 + 285b6: e9dd 450a ldrd r4, r5, [sp, #40] ; 0x28 + 285ba: ea4f 524a mov.w r2, sl, lsl #21 + 285be: ea4f 534b mov.w r3, fp, lsl #21 + 285c2: 1aa4 subs r4, r4, r2 + 285c4: ea43 23da orr.w r3, r3, sl, lsr #11 + 285c8: ea4f 5b49 mov.w fp, r9, lsl #21 + 285cc: ea4f 5a48 mov.w sl, r8, lsl #21 + 285d0: eb65 0503 sbc.w r5, r5, r3 + 285d4: ea4b 2bd8 orr.w fp, fp, r8, lsr #11 + 285d8: e9dd 891a ldrd r8, r9, [sp, #104] ; 0x68 + 285dc: ebb8 080a subs.w r8, r8, sl + 285e0: eb69 090b sbc.w r9, r9, fp + 285e4: e9cd 8922 strd r8, r9, [sp, #136] ; 0x88 + 285e8: e9dd 2318 ldrd r2, r3, [sp, #96] ; 0x60 + 285ec: ea4f 5841 mov.w r8, r1, lsl #21 + 285f0: ea4f 5946 mov.w r9, r6, lsl #21 + 285f4: ebb2 0208 subs.w r2, r2, r8 + 285f8: ea49 29d1 orr.w r9, r9, r1, lsr #11 + 285fc: eb63 0309 sbc.w r3, r3, r9 + 28600: f8dd 804c ldr.w r8, [sp, #76] ; 0x4c + 28604: e9cd 232a strd r2, r3, [sp, #168] ; 0xa8 + 28608: f8dd 9044 ldr.w r9, [sp, #68] ; 0x44 + 2860c: 9b0f ldr r3, [sp, #60] ; 0x3c + 2860e: ea4f 5748 mov.w r7, r8, lsl #21 + 28612: f8dd 8048 ldr.w r8, [sp, #72] ; 0x48 + 28616: e9cd 4520 strd r4, r5, [sp, #128] ; 0x80 + 2861a: 055d lsls r5, r3, #21 + 2861c: ea4f 5349 mov.w r3, r9, lsl #21 + 28620: f8dd 9040 ldr.w r9, [sp, #64] ; 0x40 + 28624: ea47 27d8 orr.w r7, r7, r8, lsr #11 + 28628: f8dd 8038 ldr.w r8, [sp, #56] ; 0x38 + 2862c: 990e ldr r1, [sp, #56] ; 0x38 + 2862e: ea43 23d9 orr.w r3, r3, r9, lsr #11 + 28632: f8dd 9048 ldr.w r9, [sp, #72] ; 0x48 + 28636: ea4f 5448 mov.w r4, r8, lsl #21 + 2863a: ea45 25d1 orr.w r5, r5, r1, lsr #11 + 2863e: ea4f 5649 mov.w r6, r9, lsl #21 + 28642: e9dd 8914 ldrd r8, r9, [sp, #80] ; 0x50 + 28646: ebb8 0804 subs.w r8, r8, r4 + 2864a: eb69 0905 sbc.w r9, r9, r5 + 2864e: 9d24 ldr r5, [sp, #144] ; 0x90 + 28650: 9906 ldr r1, [sp, #24] + 28652: f8dd c024 ldr.w ip, [sp, #36] ; 0x24 + 28656: f8dd e01c ldr.w lr, [sp, #28] + 2865a: e9cd 8906 strd r8, r9, [sp, #24] + 2865e: f8dd 8094 ldr.w r8, [sp, #148] ; 0x94 + 28662: f8dd 9094 ldr.w r9, [sp, #148] ; 0x94 + 28666: 0d6d lsrs r5, r5, #21 + 28668: ea45 28c8 orr.w r8, r5, r8, lsl #11 + 2866c: ea4f 5b4c mov.w fp, ip, lsl #21 + 28670: ea4f 5969 mov.w r9, r9, asr #21 + 28674: f8dd c020 ldr.w ip, [sp, #32] + 28678: f8cd 8038 str.w r8, [sp, #56] ; 0x38 + 2867c: f8cd 903c str.w r9, [sp, #60] ; 0x3c + 28680: ea4f 5e4e mov.w lr, lr, lsl #21 + 28684: e9dd 890e ldrd r8, r9, [sp, #56] ; 0x38 + 28688: e9dd 4526 ldrd r4, r5, [sp, #152] ; 0x98 + 2868c: ea4b 2bdc orr.w fp, fp, ip, lsr #11 + 28690: eb14 0408 adds.w r4, r4, r8 + 28694: f8dd c040 ldr.w ip, [sp, #64] ; 0x40 + 28698: ea4e 2ed1 orr.w lr, lr, r1, lsr #11 + 2869c: eb45 0509 adc.w r5, r5, r9 + 286a0: f8cd e02c str.w lr, [sp, #44] ; 0x2c + 286a4: f8dd e020 ldr.w lr, [sp, #32] + 286a8: ea4f 524c mov.w r2, ip, lsl #21 + 286ac: e9cd 451a strd r4, r5, [sp, #104] ; 0x68 + 286b0: e9dd 4516 ldrd r4, r5, [sp, #88] ; 0x58 + 286b4: e9dd 891e ldrd r8, r9, [sp, #120] ; 0x78 + 286b8: 1ba6 subs r6, r4, r6 + 286ba: eb65 0707 sbc.w r7, r5, r7 + 286be: ea4f 5a4e mov.w sl, lr, lsl #21 + 286c2: ebb8 0802 subs.w r8, r8, r2 + 286c6: eb69 0903 sbc.w r9, r9, r3 + 286ca: e9dd 2328 ldrd r2, r3, [sp, #160] ; 0xa0 + 286ce: ebb2 020a subs.w r2, r2, sl + 286d2: eb63 030b sbc.w r3, r3, fp + 286d6: 0549 lsls r1, r1, #21 + 286d8: 910a str r1, [sp, #40] ; 0x28 + 286da: e9cd 2310 strd r2, r3, [sp, #64] ; 0x40 + 286de: e9dd 450a ldrd r4, r5, [sp, #40] ; 0x28 + 286e2: e9dd 231c ldrd r2, r3, [sp, #112] ; 0x70 + 286e6: 1b12 subs r2, r2, r4 + 286e8: eb63 0305 sbc.w r3, r3, r5 + 286ec: 9d06 ldr r5, [sp, #24] + 286ee: f8dd b040 ldr.w fp, [sp, #64] ; 0x40 + 286f2: ea4f 4a15 mov.w sl, r5, lsr #16 + 286f6: 9d07 ldr r5, [sp, #28] + 286f8: ea4f 4cd6 mov.w ip, r6, lsr #19 + 286fc: ea4a 4a05 orr.w sl, sl, r5, lsl #16 + 28700: ea4a 1a46 orr.w sl, sl, r6, lsl #5 + 28704: f8cd a070 str.w sl, [sp, #112] ; 0x70 + 28708: 08f5 lsrs r5, r6, #3 + 2870a: ea4f 2ad6 mov.w sl, r6, lsr #11 + 2870e: ea4f 415b mov.w r1, fp, lsr #17 + 28712: 9e1a ldr r6, [sp, #104] ; 0x68 + 28714: f8dd b044 ldr.w fp, [sp, #68] ; 0x44 + 28718: ea4c 3c47 orr.w ip, ip, r7, lsl #13 + 2871c: 9f1b ldr r7, [sp, #108] ; 0x6c + 2871e: ea4c 0c88 orr.w ip, ip, r8, lsl #2 + 28722: ea4f 3e98 mov.w lr, r8, lsr #14 + 28726: ea41 31cb orr.w r1, r1, fp, lsl #15 + 2872a: ea4f 1b98 mov.w fp, r8, lsr #6 + 2872e: ea4f 5856 mov.w r8, r6, lsr #21 + 28732: ea48 28c7 orr.w r8, r8, r7, lsl #11 + 28736: f8cd a0d0 str.w sl, [sp, #208] ; 0xd0 + 2873a: f8cd b0d8 str.w fp, [sp, #216] ; 0xd8 + 2873e: 0d14 lsrs r4, r2, #20 + 28740: e9dd ab2c ldrd sl, fp, [sp, #176] ; 0xb0 + 28744: ea4e 4e89 orr.w lr, lr, r9, lsl #18 + 28748: eb1a 0a08 adds.w sl, sl, r8 + 2874c: ea4f 5967 mov.w r9, r7, asr #21 + 28750: eb4b 0b09 adc.w fp, fp, r9 + 28754: ea44 3403 orr.w r4, r4, r3, lsl #12 + 28758: e9cd ab18 strd sl, fp, [sp, #96] ; 0x60 + 2875c: 9428 str r4, [sp, #160] ; 0xa0 + 2875e: ea4f 565a mov.w r6, sl, lsr #21 + 28762: 9c06 ldr r4, [sp, #24] + 28764: ea46 26cb orr.w r6, r6, fp, lsl #11 + 28768: f8dd b064 ldr.w fp, [sp, #100] ; 0x64 + 2876c: 0a23 lsrs r3, r4, #8 + 2876e: ea41 1102 orr.w r1, r1, r2, lsl #4 + 28772: ea4f 576b mov.w r7, fp, asr #21 + 28776: 9132 str r1, [sp, #200] ; 0xc8 + 28778: 0b14 lsrs r4, r2, #12 + 2877a: 0911 lsrs r1, r2, #4 + 2877c: 7043 strb r3, [r0, #1] + 2877e: e9dd 230c ldrd r2, r3, [sp, #48] ; 0x30 + 28782: 1992 adds r2, r2, r6 + 28784: 417b adcs r3, r7 + 28786: e9cd 2314 strd r2, r3, [sp, #80] ; 0x50 + 2878a: e9dd ab20 ldrd sl, fp, [sp, #128] ; 0x80 + 2878e: 943e str r4, [sp, #248] ; 0xf8 + 28790: 0d54 lsrs r4, r2, #21 + 28792: ea44 24c3 orr.w r4, r4, r3, lsl #11 + 28796: 952e str r5, [sp, #184] ; 0xb8 + 28798: 9b15 ldr r3, [sp, #84] ; 0x54 + 2879a: f89d 5018 ldrb.w r5, [sp, #24] + 2879e: eb1a 0a04 adds.w sl, sl, r4 + 287a2: 7005 strb r5, [r0, #0] + 287a4: ea4f 5563 mov.w r5, r3, asr #21 + 287a8: eb4b 0b05 adc.w fp, fp, r5 + 287ac: e9cd ab16 strd sl, fp, [sp, #88] ; 0x58 + 287b0: f8cd c098 str.w ip, [sp, #152] ; 0x98 + 287b4: ea4f 525a mov.w r2, sl, lsr #21 + 287b8: f8dd c040 ldr.w ip, [sp, #64] ; 0x40 + 287bc: ea42 22cb orr.w r2, r2, fp, lsl #11 + 287c0: f8dd b05c ldr.w fp, [sp, #92] ; 0x5c + 287c4: ea4e 1ecc orr.w lr, lr, ip, lsl #7 + 287c8: ea4f 536b mov.w r3, fp, asr #21 + 287cc: f04f 0a00 mov.w sl, #0 + 287d0: f04f 0b00 mov.w fp, #0 + 287d4: f8cd e0c0 str.w lr, [sp, #192] ; 0xc0 + 287d8: ea4f 2e5c mov.w lr, ip, lsr #9 + 287dc: f8cd e0e8 str.w lr, [sp, #232] ; 0xe8 + 287e0: 913c str r1, [sp, #240] ; 0xf0 + 287e2: e9cd ab08 strd sl, fp, [sp, #32] + 287e6: e9cd ab06 strd sl, fp, [sp, #24] + 287ea: e9cd ab0a strd sl, fp, [sp, #40] ; 0x28 + 287ee: e9dd ab22 ldrd sl, fp, [sp, #136] ; 0x88 + 287f2: eb1a 0a02 adds.w sl, sl, r2 + 287f6: eb4b 0b03 adc.w fp, fp, r3 + 287fa: f8dd c03c ldr.w ip, [sp, #60] ; 0x3c + 287fe: e9cd ab1e strd sl, fp, [sp, #120] ; 0x78 + 28802: ea4f 5e49 mov.w lr, r9, lsl #21 + 28806: f04f 0a00 mov.w sl, #0 + 2880a: f04f 0b00 mov.w fp, #0 + 2880e: 0579 lsls r1, r7, #21 + 28810: e9cd ab0c strd sl, fp, [sp, #48] ; 0x30 + 28814: e9cd ab12 strd sl, fp, [sp, #72] ; 0x48 + 28818: f8cd e024 str.w lr, [sp, #36] ; 0x24 + 2881c: 9107 str r1, [sp, #28] + 2881e: ea4f 5e43 mov.w lr, r3, lsl #21 + 28822: 991e ldr r1, [sp, #120] ; 0x78 + 28824: ea4f 5b4c mov.w fp, ip, lsl #21 + 28828: ea4f 5c45 mov.w ip, r5, lsl #21 + 2882c: f8cd c02c str.w ip, [sp, #44] ; 0x2c + 28830: f8cd e034 str.w lr, [sp, #52] ; 0x34 + 28834: f8dd c038 ldr.w ip, [sp, #56] ; 0x38 + 28838: f8dd e024 ldr.w lr, [sp, #36] ; 0x24 + 2883c: 0d49 lsrs r1, r1, #21 + 2883e: 9112 str r1, [sp, #72] ; 0x48 + 28840: ea4e 2ed8 orr.w lr, lr, r8, lsr #11 + 28844: 9907 ldr r1, [sp, #28] + 28846: ea4b 2bdc orr.w fp, fp, ip, lsr #11 + 2884a: f8dd c02c ldr.w ip, [sp, #44] ; 0x2c + 2884e: f8cd e024 str.w lr, [sp, #36] ; 0x24 + 28852: f8dd e034 ldr.w lr, [sp, #52] ; 0x34 + 28856: ea41 21d6 orr.w r1, r1, r6, lsr #11 + 2885a: ea4c 2cd4 orr.w ip, ip, r4, lsr #11 + 2885e: 9107 str r1, [sp, #28] + 28860: f8cd c02c str.w ip, [sp, #44] ; 0x2c + 28864: 9912 ldr r1, [sp, #72] ; 0x48 + 28866: f8dd c07c ldr.w ip, [sp, #124] ; 0x7c + 2886a: ea4e 2ed2 orr.w lr, lr, r2, lsr #11 + 2886e: f8cd e034 str.w lr, [sp, #52] ; 0x34 + 28872: f8dd e038 ldr.w lr, [sp, #56] ; 0x38 + 28876: ea41 21cc orr.w r1, r1, ip, lsl #11 + 2887a: 9112 str r1, [sp, #72] ; 0x48 + 2887c: ea4f 5a4e mov.w sl, lr, lsl #21 + 28880: ea4f 5148 mov.w r1, r8, lsl #21 + 28884: 9108 str r1, [sp, #32] + 28886: ea4f 5846 mov.w r8, r6, lsl #21 + 2888a: ea4f 5c42 mov.w ip, r2, lsl #21 + 2888e: e9dd 2324 ldrd r2, r3, [sp, #144] ; 0x90 + 28892: ebb2 0a0a subs.w sl, r2, sl + 28896: f8cd 8018 str.w r8, [sp, #24] + 2889a: eb63 0b0b sbc.w fp, r3, fp + 2889e: e9dd 671a ldrd r6, r7, [sp, #104] ; 0x68 + 288a2: ea4f 5944 mov.w r9, r4, lsl #21 + 288a6: f8dd e07c ldr.w lr, [sp, #124] ; 0x7c + 288aa: e9dd 4508 ldrd r4, r5, [sp, #32] + 288ae: 1b36 subs r6, r6, r4 + 288b0: e9dd 2306 ldrd r2, r3, [sp, #24] + 288b4: eb67 0705 sbc.w r7, r7, r5 + 288b8: f8cd 9028 str.w r9, [sp, #40] ; 0x28 + 288bc: e9dd 8918 ldrd r8, r9, [sp, #96] ; 0x60 + 288c0: ebb8 0802 subs.w r8, r8, r2 + 288c4: eb69 0903 sbc.w r9, r9, r3 + 288c8: ea4f 5e6e mov.w lr, lr, asr #21 + 288cc: f8cd c030 str.w ip, [sp, #48] ; 0x30 + 288d0: f8cd e04c str.w lr, [sp, #76] ; 0x4c + 288d4: e9cd 8920 strd r8, r9, [sp, #128] ; 0x80 + 288d8: e9dd 890a ldrd r8, r9, [sp, #40] ; 0x28 + 288dc: e9dd 4514 ldrd r4, r5, [sp, #80] ; 0x50 + 288e0: ebb4 0408 subs.w r4, r4, r8 + 288e4: eb65 0509 sbc.w r5, r5, r9 + 288e8: e9cd 450e strd r4, r5, [sp, #56] ; 0x38 + 288ec: e9dd 2316 ldrd r2, r3, [sp, #88] ; 0x58 + 288f0: e9dd 450c ldrd r4, r5, [sp, #48] ; 0x30 + 288f4: 1b12 subs r2, r2, r4 + 288f6: e9dd 8912 ldrd r8, r9, [sp, #72] ; 0x48 + 288fa: eb63 0305 sbc.w r3, r3, r5 + 288fe: e9dd 452a ldrd r4, r5, [sp, #168] ; 0xa8 + 28902: eb14 0408 adds.w r4, r4, r8 + 28906: eb45 0509 adc.w r5, r5, r9 + 2890a: e9dd 8910 ldrd r8, r9, [sp, #64] ; 0x40 + 2890e: ea5f 0969 movs.w r9, r9, asr #1 + 28912: ea4f 0838 mov.w r8, r8, rrx + 28916: e9cd 8910 strd r8, r9, [sp, #64] ; 0x40 + 2891a: ea5f 0965 movs.w r9, r5, asr #1 + 2891e: ea4f 0834 mov.w r8, r4, rrx + 28922: e9cd 890c strd r8, r9, [sp, #48] ; 0x30 + 28926: f8dd 9038 ldr.w r9, [sp, #56] ; 0x38 + 2892a: ea4f 3eda mov.w lr, sl, lsr #15 + 2892e: ea4f 4c19 mov.w ip, r9, lsr #16 + 28932: f8dd 90a0 ldr.w r9, [sp, #160] ; 0xa0 + 28936: f8dd 803c ldr.w r8, [sp, #60] ; 0x3c + 2893a: 0cb5 lsrs r5, r6, #18 + 2893c: ea4e 4e4b orr.w lr, lr, fp, lsl #17 + 28940: f8dd b080 ldr.w fp, [sp, #128] ; 0x80 + 28944: ea49 094a orr.w r9, r9, sl, lsl #1 + 28948: ea4e 1e86 orr.w lr, lr, r6, lsl #6 + 2894c: ea45 3587 orr.w r5, r5, r7, lsl #14 + 28950: 9f0e ldr r7, [sp, #56] ; 0x38 + 28952: f8cd 9020 str.w r9, [sp, #32] + 28956: f8cd e018 str.w lr, [sp, #24] + 2895a: ea4f 0996 mov.w r9, r6, lsr #2 + 2895e: ea4f 1e5b mov.w lr, fp, lsr #5 + 28962: 0cd1 lsrs r1, r2, #19 + 28964: ea4c 4c08 orr.w ip, ip, r8, lsl #16 + 28968: ea4f 18da mov.w r8, sl, lsr #7 + 2896c: ea4f 2a96 mov.w sl, r6, lsr #10 + 28970: f8cd 8068 str.w r8, [sp, #104] ; 0x68 + 28974: f8cd 9060 str.w r9, [sp, #96] ; 0x60 + 28978: f8cd a050 str.w sl, [sp, #80] ; 0x50 + 2897c: ea45 05cb orr.w r5, r5, fp, lsl #3 + 28980: f8dd a04c ldr.w sl, [sp, #76] ; 0x4c + 28984: f8cd e058 str.w lr, [sp, #88] ; 0x58 + 28988: ea4f 395b mov.w r9, fp, lsr #13 + 2898c: ea4f 2817 mov.w r8, r7, lsr #8 + 28990: f8dd b048 ldr.w fp, [sp, #72] ; 0x48 + 28994: ea4c 1c42 orr.w ip, ip, r2, lsl #5 + 28998: ea4f 0ed2 mov.w lr, r2, lsr #3 + 2899c: 0ad7 lsrs r7, r2, #11 + 2899e: ea41 3143 orr.w r1, r1, r3, lsl #13 + 289a2: 9a1c ldr r2, [sp, #112] ; 0x70 + 289a4: 9b2e ldr r3, [sp, #184] ; 0xb8 + 289a6: 7082 strb r2, [r0, #2] + 289a8: 70c3 strb r3, [r0, #3] + 289aa: ea4f 524b mov.w r2, fp, lsl #21 + 289ae: ea4f 534a mov.w r3, sl, lsl #21 + 289b2: ea43 23db orr.w r3, r3, fp, lsr #11 + 289b6: e9dd ab1e ldrd sl, fp, [sp, #120] ; 0x78 + 289ba: ebba 0202 subs.w r2, sl, r2 + 289be: eb6b 0303 sbc.w r3, fp, r3 + 289c2: ea4f 3b92 mov.w fp, r2, lsr #14 + 289c6: ea4b 4b83 orr.w fp, fp, r3, lsl #18 + 289ca: 9b34 ldr r3, [sp, #208] ; 0xd0 + 289cc: 950a str r5, [sp, #40] ; 0x28 + 289ce: 7103 strb r3, [r0, #4] + 289d0: 9b26 ldr r3, [sp, #152] ; 0x98 + 289d2: 0a66 lsrs r6, r4, #9 + 289d4: 7143 strb r3, [r0, #5] + 289d6: 9b36 ldr r3, [sp, #216] ; 0xd8 + 289d8: 0c65 lsrs r5, r4, #17 + 289da: 7183 strb r3, [r0, #6] + 289dc: 9b30 ldr r3, [sp, #192] ; 0xc0 + 289de: ea41 0182 orr.w r1, r1, r2, lsl #2 + 289e2: 71c3 strb r3, [r0, #7] + 289e4: f89d 3038 ldrb.w r3, [sp, #56] ; 0x38 + 289e8: ea4b 14c4 orr.w r4, fp, r4, lsl #7 + 289ec: 7543 strb r3, [r0, #21] + 289ee: f89d 3040 ldrb.w r3, [sp, #64] ; 0x40 + 289f2: f880 9014 strb.w r9, [r0, #20] + 289f6: 7203 strb r3, [r0, #8] + 289f8: 9b3a ldr r3, [sp, #232] ; 0xe8 + 289fa: f880 8016 strb.w r8, [r0, #22] + 289fe: 7243 strb r3, [r0, #9] + 28a00: 9b32 ldr r3, [sp, #200] ; 0xc8 + 28a02: f880 c017 strb.w ip, [r0, #23] + 28a06: 7283 strb r3, [r0, #10] + 28a08: 9b3c ldr r3, [sp, #240] ; 0xf0 + 28a0a: f880 e018 strb.w lr, [r0, #24] + 28a0e: 72c3 strb r3, [r0, #11] + 28a10: 9b3e ldr r3, [sp, #248] ; 0xf8 + 28a12: 7647 strb r7, [r0, #25] + 28a14: 7303 strb r3, [r0, #12] + 28a16: 9b08 ldr r3, [sp, #32] + 28a18: 0992 lsrs r2, r2, #6 + 28a1a: 7343 strb r3, [r0, #13] + 28a1c: 9b1a ldr r3, [sp, #104] ; 0x68 + 28a1e: 7383 strb r3, [r0, #14] + 28a20: 9b06 ldr r3, [sp, #24] + 28a22: 73c3 strb r3, [r0, #15] + 28a24: 9b18 ldr r3, [sp, #96] ; 0x60 + 28a26: 7403 strb r3, [r0, #16] + 28a28: 9b14 ldr r3, [sp, #80] ; 0x50 + 28a2a: 7443 strb r3, [r0, #17] + 28a2c: 9b0a ldr r3, [sp, #40] ; 0x28 + 28a2e: 7483 strb r3, [r0, #18] + 28a30: 9b16 ldr r3, [sp, #88] ; 0x58 + 28a32: 74c3 strb r3, [r0, #19] + 28a34: 7681 strb r1, [r0, #26] + 28a36: 7704 strb r4, [r0, #28] + 28a38: f89d 4030 ldrb.w r4, [sp, #48] ; 0x30 + 28a3c: 76c2 strb r2, [r0, #27] + 28a3e: 7744 strb r4, [r0, #29] + 28a40: 7786 strb r6, [r0, #30] + 28a42: 77c5 strb r5, [r0, #31] + 28a44: b04b add sp, #300 ; 0x12c + 28a46: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 28a4a: bf00 nop + +00028a4c <__rtl_memchr_v1_00>: + 28a4c: 0783 lsls r3, r0, #30 + 28a4e: b470 push {r4, r5, r6} + 28a50: b2c9 uxtb r1, r1 + 28a52: d040 beq.n 28ad6 <__rtl_memchr_v1_00+0x8a> + 28a54: 1e54 subs r4, r2, #1 + 28a56: b32a cbz r2, 28aa4 <__rtl_memchr_v1_00+0x58> + 28a58: 7803 ldrb r3, [r0, #0] + 28a5a: 428b cmp r3, r1 + 28a5c: d023 beq.n 28aa6 <__rtl_memchr_v1_00+0x5a> + 28a5e: 1c43 adds r3, r0, #1 + 28a60: e004 b.n 28a6c <__rtl_memchr_v1_00+0x20> + 28a62: b1fc cbz r4, 28aa4 <__rtl_memchr_v1_00+0x58> + 28a64: 7804 ldrb r4, [r0, #0] + 28a66: 428c cmp r4, r1 + 28a68: d01d beq.n 28aa6 <__rtl_memchr_v1_00+0x5a> + 28a6a: 4614 mov r4, r2 + 28a6c: f013 0f03 tst.w r3, #3 + 28a70: 4618 mov r0, r3 + 28a72: f104 32ff add.w r2, r4, #4294967295 + 28a76: f103 0301 add.w r3, r3, #1 + 28a7a: d1f2 bne.n 28a62 <__rtl_memchr_v1_00+0x16> + 28a7c: 2c03 cmp r4, #3 + 28a7e: d814 bhi.n 28aaa <__rtl_memchr_v1_00+0x5e> + 28a80: 1e65 subs r5, r4, #1 + 28a82: b354 cbz r4, 28ada <__rtl_memchr_v1_00+0x8e> + 28a84: 7803 ldrb r3, [r0, #0] + 28a86: 428b cmp r3, r1 + 28a88: d00d beq.n 28aa6 <__rtl_memchr_v1_00+0x5a> + 28a8a: 1c42 adds r2, r0, #1 + 28a8c: 2300 movs r3, #0 + 28a8e: e002 b.n 28a96 <__rtl_memchr_v1_00+0x4a> + 28a90: 7804 ldrb r4, [r0, #0] + 28a92: 428c cmp r4, r1 + 28a94: d007 beq.n 28aa6 <__rtl_memchr_v1_00+0x5a> + 28a96: 42ab cmp r3, r5 + 28a98: 4610 mov r0, r2 + 28a9a: f103 0301 add.w r3, r3, #1 + 28a9e: f102 0201 add.w r2, r2, #1 + 28aa2: d1f5 bne.n 28a90 <__rtl_memchr_v1_00+0x44> + 28aa4: 2000 movs r0, #0 + 28aa6: bc70 pop {r4, r5, r6} + 28aa8: 4770 bx lr + 28aaa: 4603 mov r3, r0 + 28aac: ea41 2601 orr.w r6, r1, r1, lsl #8 + 28ab0: ea46 4606 orr.w r6, r6, r6, lsl #16 + 28ab4: 681a ldr r2, [r3, #0] + 28ab6: 4618 mov r0, r3 + 28ab8: 4072 eors r2, r6 + 28aba: f1a2 3501 sub.w r5, r2, #16843009 ; 0x1010101 + 28abe: ea25 0202 bic.w r2, r5, r2 + 28ac2: f012 3f80 tst.w r2, #2155905152 ; 0x80808080 + 28ac6: f103 0304 add.w r3, r3, #4 + 28aca: d1d9 bne.n 28a80 <__rtl_memchr_v1_00+0x34> + 28acc: 3c04 subs r4, #4 + 28ace: 2c03 cmp r4, #3 + 28ad0: 4618 mov r0, r3 + 28ad2: d8ef bhi.n 28ab4 <__rtl_memchr_v1_00+0x68> + 28ad4: e7d4 b.n 28a80 <__rtl_memchr_v1_00+0x34> + 28ad6: 4614 mov r4, r2 + 28ad8: e7d0 b.n 28a7c <__rtl_memchr_v1_00+0x30> + 28ada: 4620 mov r0, r4 + 28adc: e7e3 b.n 28aa6 <__rtl_memchr_v1_00+0x5a> + 28ade: bf00 nop + +00028ae0 <__rtl_memcmp_v1_00>: + 28ae0: 2a03 cmp r2, #3 + 28ae2: b470 push {r4, r5, r6} + 28ae4: d914 bls.n 28b10 <__rtl_memcmp_v1_00+0x30> + 28ae6: ea40 0301 orr.w r3, r0, r1 + 28aea: 079b lsls r3, r3, #30 + 28aec: d111 bne.n 28b12 <__rtl_memcmp_v1_00+0x32> + 28aee: 460c mov r4, r1 + 28af0: 4603 mov r3, r0 + 28af2: 6825 ldr r5, [r4, #0] + 28af4: 681e ldr r6, [r3, #0] + 28af6: 4621 mov r1, r4 + 28af8: 42ae cmp r6, r5 + 28afa: 4618 mov r0, r3 + 28afc: f104 0404 add.w r4, r4, #4 + 28b00: f103 0304 add.w r3, r3, #4 + 28b04: d104 bne.n 28b10 <__rtl_memcmp_v1_00+0x30> + 28b06: 3a04 subs r2, #4 + 28b08: 2a03 cmp r2, #3 + 28b0a: 4618 mov r0, r3 + 28b0c: 4621 mov r1, r4 + 28b0e: d8f0 bhi.n 28af2 <__rtl_memcmp_v1_00+0x12> + 28b10: b1c2 cbz r2, 28b44 <__rtl_memcmp_v1_00+0x64> + 28b12: 7805 ldrb r5, [r0, #0] + 28b14: 780c ldrb r4, [r1, #0] + 28b16: 42a5 cmp r5, r4 + 28b18: bf04 itt eq + 28b1a: f102 32ff addeq.w r2, r2, #4294967295 + 28b1e: 2300 moveq r3, #0 + 28b20: d006 beq.n 28b30 <__rtl_memcmp_v1_00+0x50> + 28b22: e00c b.n 28b3e <__rtl_memcmp_v1_00+0x5e> + 28b24: f810 5f01 ldrb.w r5, [r0, #1]! + 28b28: f811 4f01 ldrb.w r4, [r1, #1]! + 28b2c: 42a5 cmp r5, r4 + 28b2e: d106 bne.n 28b3e <__rtl_memcmp_v1_00+0x5e> + 28b30: 4293 cmp r3, r2 + 28b32: f103 0301 add.w r3, r3, #1 + 28b36: d1f5 bne.n 28b24 <__rtl_memcmp_v1_00+0x44> + 28b38: 2000 movs r0, #0 + 28b3a: bc70 pop {r4, r5, r6} + 28b3c: 4770 bx lr + 28b3e: 1b28 subs r0, r5, r4 + 28b40: bc70 pop {r4, r5, r6} + 28b42: 4770 bx lr + 28b44: 4610 mov r0, r2 + 28b46: e7f8 b.n 28b3a <__rtl_memcmp_v1_00+0x5a> + +00028b48 <__rtl_memcpy_v1_00>: + 28b48: 2a0f cmp r2, #15 + 28b4a: b5f0 push {r4, r5, r6, r7, lr} + 28b4c: d942 bls.n 28bd4 <__rtl_memcpy_v1_00+0x8c> + 28b4e: ea40 0301 orr.w r3, r0, r1 + 28b52: 079b lsls r3, r3, #30 + 28b54: d142 bne.n 28bdc <__rtl_memcpy_v1_00+0x94> + 28b56: 460c mov r4, r1 + 28b58: 4603 mov r3, r0 + 28b5a: f1a2 0710 sub.w r7, r2, #16 + 28b5e: 093f lsrs r7, r7, #4 + 28b60: eb00 1607 add.w r6, r0, r7, lsl #4 + 28b64: 3610 adds r6, #16 + 28b66: 6825 ldr r5, [r4, #0] + 28b68: 3310 adds r3, #16 + 28b6a: f843 5c10 str.w r5, [r3, #-16] + 28b6e: 6865 ldr r5, [r4, #4] + 28b70: 3410 adds r4, #16 + 28b72: f843 5c0c str.w r5, [r3, #-12] + 28b76: f854 5c08 ldr.w r5, [r4, #-8] + 28b7a: f843 5c08 str.w r5, [r3, #-8] + 28b7e: f854 5c04 ldr.w r5, [r4, #-4] + 28b82: f843 5c04 str.w r5, [r3, #-4] + 28b86: 42b3 cmp r3, r6 + 28b88: d1ed bne.n 28b66 <__rtl_memcpy_v1_00+0x1e> + 28b8a: 1c7b adds r3, r7, #1 + 28b8c: f002 0e0f and.w lr, r2, #15 + 28b90: 011b lsls r3, r3, #4 + 28b92: f1be 0f03 cmp.w lr, #3 + 28b96: 4419 add r1, r3 + 28b98: 4403 add r3, r0 + 28b9a: d922 bls.n 28be2 <__rtl_memcpy_v1_00+0x9a> + 28b9c: 460e mov r6, r1 + 28b9e: 461d mov r5, r3 + 28ba0: 4674 mov r4, lr + 28ba2: f856 7b04 ldr.w r7, [r6], #4 + 28ba6: 3c04 subs r4, #4 + 28ba8: 2c03 cmp r4, #3 + 28baa: f845 7b04 str.w r7, [r5], #4 + 28bae: d8f8 bhi.n 28ba2 <__rtl_memcpy_v1_00+0x5a> + 28bb0: f1ae 0404 sub.w r4, lr, #4 + 28bb4: f024 0403 bic.w r4, r4, #3 + 28bb8: 3404 adds r4, #4 + 28bba: f002 0203 and.w r2, r2, #3 + 28bbe: 4423 add r3, r4 + 28bc0: 4421 add r1, r4 + 28bc2: b16a cbz r2, 28be0 <__rtl_memcpy_v1_00+0x98> + 28bc4: 440a add r2, r1 + 28bc6: f811 4b01 ldrb.w r4, [r1], #1 + 28bca: 4291 cmp r1, r2 + 28bcc: f803 4b01 strb.w r4, [r3], #1 + 28bd0: d1f9 bne.n 28bc6 <__rtl_memcpy_v1_00+0x7e> + 28bd2: bdf0 pop {r4, r5, r6, r7, pc} + 28bd4: 4603 mov r3, r0 + 28bd6: 2a00 cmp r2, #0 + 28bd8: d1f4 bne.n 28bc4 <__rtl_memcpy_v1_00+0x7c> + 28bda: e001 b.n 28be0 <__rtl_memcpy_v1_00+0x98> + 28bdc: 4603 mov r3, r0 + 28bde: e7f1 b.n 28bc4 <__rtl_memcpy_v1_00+0x7c> + 28be0: bdf0 pop {r4, r5, r6, r7, pc} + 28be2: 4672 mov r2, lr + 28be4: 2a00 cmp r2, #0 + 28be6: d1ed bne.n 28bc4 <__rtl_memcpy_v1_00+0x7c> + 28be8: e7fa b.n 28be0 <__rtl_memcpy_v1_00+0x98> + 28bea: bf00 nop + +00028bec <__rtl_memmove_v1_00>: + 28bec: 4288 cmp r0, r1 + 28bee: b5f0 push {r4, r5, r6, r7, lr} + 28bf0: d910 bls.n 28c14 <__rtl_memmove_v1_00+0x28> + 28bf2: 188c adds r4, r1, r2 + 28bf4: 42a0 cmp r0, r4 + 28bf6: d20d bcs.n 28c14 <__rtl_memmove_v1_00+0x28> + 28bf8: 1885 adds r5, r0, r2 + 28bfa: 1e53 subs r3, r2, #1 + 28bfc: 2a00 cmp r2, #0 + 28bfe: d04d beq.n 28c9c <__rtl_memmove_v1_00+0xb0> + 28c00: 4621 mov r1, r4 + 28c02: 462a mov r2, r5 + 28c04: f811 4d01 ldrb.w r4, [r1, #-1]! + 28c08: 3b01 subs r3, #1 + 28c0a: f802 4d01 strb.w r4, [r2, #-1]! + 28c0e: 1c5c adds r4, r3, #1 + 28c10: d1f8 bne.n 28c04 <__rtl_memmove_v1_00+0x18> + 28c12: bdf0 pop {r4, r5, r6, r7, pc} + 28c14: 2a0f cmp r2, #15 + 28c16: d942 bls.n 28c9e <__rtl_memmove_v1_00+0xb2> + 28c18: ea40 0301 orr.w r3, r0, r1 + 28c1c: 079b lsls r3, r3, #30 + 28c1e: d142 bne.n 28ca6 <__rtl_memmove_v1_00+0xba> + 28c20: 460c mov r4, r1 + 28c22: 4603 mov r3, r0 + 28c24: f1a2 0710 sub.w r7, r2, #16 + 28c28: 093f lsrs r7, r7, #4 + 28c2a: eb00 1607 add.w r6, r0, r7, lsl #4 + 28c2e: 3610 adds r6, #16 + 28c30: 6825 ldr r5, [r4, #0] + 28c32: 3310 adds r3, #16 + 28c34: f843 5c10 str.w r5, [r3, #-16] + 28c38: 6865 ldr r5, [r4, #4] + 28c3a: 3410 adds r4, #16 + 28c3c: f843 5c0c str.w r5, [r3, #-12] + 28c40: f854 5c08 ldr.w r5, [r4, #-8] + 28c44: f843 5c08 str.w r5, [r3, #-8] + 28c48: f854 5c04 ldr.w r5, [r4, #-4] + 28c4c: f843 5c04 str.w r5, [r3, #-4] + 28c50: 42b3 cmp r3, r6 + 28c52: d1ed bne.n 28c30 <__rtl_memmove_v1_00+0x44> + 28c54: 1c7b adds r3, r7, #1 + 28c56: f002 0e0f and.w lr, r2, #15 + 28c5a: 011b lsls r3, r3, #4 + 28c5c: f1be 0f03 cmp.w lr, #3 + 28c60: 4419 add r1, r3 + 28c62: 4403 add r3, r0 + 28c64: d922 bls.n 28cac <__rtl_memmove_v1_00+0xc0> + 28c66: 460e mov r6, r1 + 28c68: 461d mov r5, r3 + 28c6a: 4674 mov r4, lr + 28c6c: f856 7b04 ldr.w r7, [r6], #4 + 28c70: 3c04 subs r4, #4 + 28c72: 2c03 cmp r4, #3 + 28c74: f845 7b04 str.w r7, [r5], #4 + 28c78: d8f8 bhi.n 28c6c <__rtl_memmove_v1_00+0x80> + 28c7a: f1ae 0404 sub.w r4, lr, #4 + 28c7e: f024 0403 bic.w r4, r4, #3 + 28c82: 3404 adds r4, #4 + 28c84: f002 0203 and.w r2, r2, #3 + 28c88: 4423 add r3, r4 + 28c8a: 4421 add r1, r4 + 28c8c: b16a cbz r2, 28caa <__rtl_memmove_v1_00+0xbe> + 28c8e: 441a add r2, r3 + 28c90: f811 4b01 ldrb.w r4, [r1], #1 + 28c94: f803 4b01 strb.w r4, [r3], #1 + 28c98: 4293 cmp r3, r2 + 28c9a: d1f9 bne.n 28c90 <__rtl_memmove_v1_00+0xa4> + 28c9c: bdf0 pop {r4, r5, r6, r7, pc} + 28c9e: 4603 mov r3, r0 + 28ca0: 2a00 cmp r2, #0 + 28ca2: d1f4 bne.n 28c8e <__rtl_memmove_v1_00+0xa2> + 28ca4: e001 b.n 28caa <__rtl_memmove_v1_00+0xbe> + 28ca6: 4603 mov r3, r0 + 28ca8: e7f1 b.n 28c8e <__rtl_memmove_v1_00+0xa2> + 28caa: bdf0 pop {r4, r5, r6, r7, pc} + 28cac: 4672 mov r2, lr + 28cae: 2a00 cmp r2, #0 + 28cb0: d1ed bne.n 28c8e <__rtl_memmove_v1_00+0xa2> + 28cb2: e7fa b.n 28caa <__rtl_memmove_v1_00+0xbe> + +00028cb4 <__rtl_memset_v1_00>: + 28cb4: b4f0 push {r4, r5, r6, r7} + 28cb6: 0784 lsls r4, r0, #30 + 28cb8: d042 beq.n 28d40 <__rtl_memset_v1_00+0x8c> + 28cba: 1e54 subs r4, r2, #1 + 28cbc: 2a00 cmp r2, #0 + 28cbe: d03d beq.n 28d3c <__rtl_memset_v1_00+0x88> + 28cc0: b2cd uxtb r5, r1 + 28cc2: 4603 mov r3, r0 + 28cc4: e002 b.n 28ccc <__rtl_memset_v1_00+0x18> + 28cc6: 1e62 subs r2, r4, #1 + 28cc8: b3c4 cbz r4, 28d3c <__rtl_memset_v1_00+0x88> + 28cca: 4614 mov r4, r2 + 28ccc: f803 5b01 strb.w r5, [r3], #1 + 28cd0: 079a lsls r2, r3, #30 + 28cd2: d1f8 bne.n 28cc6 <__rtl_memset_v1_00+0x12> + 28cd4: 2c03 cmp r4, #3 + 28cd6: d92a bls.n 28d2e <__rtl_memset_v1_00+0x7a> + 28cd8: b2cd uxtb r5, r1 + 28cda: ea45 2505 orr.w r5, r5, r5, lsl #8 + 28cde: 2c0f cmp r4, #15 + 28ce0: ea45 4505 orr.w r5, r5, r5, lsl #16 + 28ce4: d915 bls.n 28d12 <__rtl_memset_v1_00+0x5e> + 28ce6: 461a mov r2, r3 + 28ce8: f1a4 0710 sub.w r7, r4, #16 + 28cec: 093f lsrs r7, r7, #4 + 28cee: f103 0610 add.w r6, r3, #16 + 28cf2: eb06 1607 add.w r6, r6, r7, lsl #4 + 28cf6: 6015 str r5, [r2, #0] + 28cf8: 6055 str r5, [r2, #4] + 28cfa: 6095 str r5, [r2, #8] + 28cfc: 60d5 str r5, [r2, #12] + 28cfe: 3210 adds r2, #16 + 28d00: 42b2 cmp r2, r6 + 28d02: d1f8 bne.n 28cf6 <__rtl_memset_v1_00+0x42> + 28d04: f004 040f and.w r4, r4, #15 + 28d08: 3701 adds r7, #1 + 28d0a: 2c03 cmp r4, #3 + 28d0c: eb03 1307 add.w r3, r3, r7, lsl #4 + 28d10: d90d bls.n 28d2e <__rtl_memset_v1_00+0x7a> + 28d12: 461e mov r6, r3 + 28d14: 4622 mov r2, r4 + 28d16: 3a04 subs r2, #4 + 28d18: 2a03 cmp r2, #3 + 28d1a: f846 5b04 str.w r5, [r6], #4 + 28d1e: d8fa bhi.n 28d16 <__rtl_memset_v1_00+0x62> + 28d20: 1f22 subs r2, r4, #4 + 28d22: f022 0203 bic.w r2, r2, #3 + 28d26: 3204 adds r2, #4 + 28d28: 4413 add r3, r2 + 28d2a: f004 0403 and.w r4, r4, #3 + 28d2e: b12c cbz r4, 28d3c <__rtl_memset_v1_00+0x88> + 28d30: b2c9 uxtb r1, r1 + 28d32: 441c add r4, r3 + 28d34: f803 1b01 strb.w r1, [r3], #1 + 28d38: 42a3 cmp r3, r4 + 28d3a: d1fb bne.n 28d34 <__rtl_memset_v1_00+0x80> + 28d3c: bcf0 pop {r4, r5, r6, r7} + 28d3e: 4770 bx lr + 28d40: 4614 mov r4, r2 + 28d42: 4603 mov r3, r0 + 28d44: e7c6 b.n 28cd4 <__rtl_memset_v1_00+0x20> + 28d46: bf00 nop + +00028d48 <__rtl_strcat_v1_00>: + 28d48: b538 push {r3, r4, r5, lr} + 28d4a: 0783 lsls r3, r0, #30 + 28d4c: 4605 mov r5, r0 + 28d4e: d111 bne.n 28d74 <__rtl_strcat_v1_00+0x2c> + 28d50: 682b ldr r3, [r5, #0] + 28d52: 4628 mov r0, r5 + 28d54: f1a3 3201 sub.w r2, r3, #16843009 ; 0x1010101 + 28d58: ea22 0303 bic.w r3, r2, r3 + 28d5c: f013 3f80 tst.w r3, #2155905152 ; 0x80808080 + 28d60: d108 bne.n 28d74 <__rtl_strcat_v1_00+0x2c> + 28d62: f850 2f04 ldr.w r2, [r0, #4]! + 28d66: f1a2 3401 sub.w r4, r2, #16843009 ; 0x1010101 + 28d6a: ea24 0202 bic.w r2, r4, r2 + 28d6e: f012 3f80 tst.w r2, #2155905152 ; 0x80808080 + 28d72: d0f6 beq.n 28d62 <__rtl_strcat_v1_00+0x1a> + 28d74: 7802 ldrb r2, [r0, #0] + 28d76: b11a cbz r2, 28d80 <__rtl_strcat_v1_00+0x38> + 28d78: f810 2f01 ldrb.w r2, [r0, #1]! + 28d7c: 2a00 cmp r2, #0 + 28d7e: d1fb bne.n 28d78 <__rtl_strcat_v1_00+0x30> + 28d80: f648 62c9 movw r2, #36553 ; 0x8ec9 + 28d84: f2c0 0202 movt r2, #2 + 28d88: 4790 blx r2 + 28d8a: 4628 mov r0, r5 + 28d8c: bd38 pop {r3, r4, r5, pc} + 28d8e: bf00 nop + +00028d90 <__rtl_strchr_v1_00>: + 28d90: b2c9 uxtb r1, r1 + 28d92: b470 push {r4, r5, r6} + 28d94: b3a1 cbz r1, 28e00 <__rtl_strchr_v1_00+0x70> + 28d96: 0785 lsls r5, r0, #30 + 28d98: d00d beq.n 28db6 <__rtl_strchr_v1_00+0x26> + 28d9a: 7802 ldrb r2, [r0, #0] + 28d9c: b36a cbz r2, 28dfa <__rtl_strchr_v1_00+0x6a> + 28d9e: 4291 cmp r1, r2 + 28da0: d02c beq.n 28dfc <__rtl_strchr_v1_00+0x6c> + 28da2: 1c43 adds r3, r0, #1 + 28da4: e004 b.n 28db0 <__rtl_strchr_v1_00+0x20> + 28da6: f813 2b01 ldrb.w r2, [r3], #1 + 28daa: b332 cbz r2, 28dfa <__rtl_strchr_v1_00+0x6a> + 28dac: 4291 cmp r1, r2 + 28dae: d025 beq.n 28dfc <__rtl_strchr_v1_00+0x6c> + 28db0: 079a lsls r2, r3, #30 + 28db2: 4618 mov r0, r3 + 28db4: d1f7 bne.n 28da6 <__rtl_strchr_v1_00+0x16> + 28db6: ea41 2601 orr.w r6, r1, r1, lsl #8 + 28dba: 6803 ldr r3, [r0, #0] + 28dbc: ea46 4606 orr.w r6, r6, r6, lsl #16 + 28dc0: e001 b.n 28dc6 <__rtl_strchr_v1_00+0x36> + 28dc2: f850 3f04 ldr.w r3, [r0, #4]! + 28dc6: ea83 0206 eor.w r2, r3, r6 + 28dca: f1a2 3501 sub.w r5, r2, #16843009 ; 0x1010101 + 28dce: f1a3 3401 sub.w r4, r3, #16843009 ; 0x1010101 + 28dd2: ea25 0202 bic.w r2, r5, r2 + 28dd6: ea24 0303 bic.w r3, r4, r3 + 28dda: 4313 orrs r3, r2 + 28ddc: f013 3f80 tst.w r3, #2155905152 ; 0x80808080 + 28de0: d0ef beq.n 28dc2 <__rtl_strchr_v1_00+0x32> + 28de2: 7803 ldrb r3, [r0, #0] + 28de4: 2b00 cmp r3, #0 + 28de6: d033 beq.n 28e50 <__rtl_strchr_v1_00+0xc0> + 28de8: 4299 cmp r1, r3 + 28dea: d102 bne.n 28df2 <__rtl_strchr_v1_00+0x62> + 28dec: e006 b.n 28dfc <__rtl_strchr_v1_00+0x6c> + 28dee: 4291 cmp r1, r2 + 28df0: d004 beq.n 28dfc <__rtl_strchr_v1_00+0x6c> + 28df2: f810 2f01 ldrb.w r2, [r0, #1]! + 28df6: 2a00 cmp r2, #0 + 28df8: d1f9 bne.n 28dee <__rtl_strchr_v1_00+0x5e> + 28dfa: 4610 mov r0, r2 + 28dfc: bc70 pop {r4, r5, r6} + 28dfe: 4770 bx lr + 28e00: 0784 lsls r4, r0, #30 + 28e02: d00b beq.n 28e1c <__rtl_strchr_v1_00+0x8c> + 28e04: 7803 ldrb r3, [r0, #0] + 28e06: 2b00 cmp r3, #0 + 28e08: d0f8 beq.n 28dfc <__rtl_strchr_v1_00+0x6c> + 28e0a: 1c43 adds r3, r0, #1 + 28e0c: e003 b.n 28e16 <__rtl_strchr_v1_00+0x86> + 28e0e: 7802 ldrb r2, [r0, #0] + 28e10: 3301 adds r3, #1 + 28e12: 2a00 cmp r2, #0 + 28e14: d0f2 beq.n 28dfc <__rtl_strchr_v1_00+0x6c> + 28e16: 0799 lsls r1, r3, #30 + 28e18: 4618 mov r0, r3 + 28e1a: d1f8 bne.n 28e0e <__rtl_strchr_v1_00+0x7e> + 28e1c: 6803 ldr r3, [r0, #0] + 28e1e: f1a3 3201 sub.w r2, r3, #16843009 ; 0x1010101 + 28e22: ea22 0303 bic.w r3, r2, r3 + 28e26: f013 3f80 tst.w r3, #2155905152 ; 0x80808080 + 28e2a: d108 bne.n 28e3e <__rtl_strchr_v1_00+0xae> + 28e2c: f850 3f04 ldr.w r3, [r0, #4]! + 28e30: f1a3 3201 sub.w r2, r3, #16843009 ; 0x1010101 + 28e34: ea22 0303 bic.w r3, r2, r3 + 28e38: f013 3f80 tst.w r3, #2155905152 ; 0x80808080 + 28e3c: d0f6 beq.n 28e2c <__rtl_strchr_v1_00+0x9c> + 28e3e: 7803 ldrb r3, [r0, #0] + 28e40: 2b00 cmp r3, #0 + 28e42: d0db beq.n 28dfc <__rtl_strchr_v1_00+0x6c> + 28e44: f810 3f01 ldrb.w r3, [r0, #1]! + 28e48: 2b00 cmp r3, #0 + 28e4a: d1fb bne.n 28e44 <__rtl_strchr_v1_00+0xb4> + 28e4c: bc70 pop {r4, r5, r6} + 28e4e: 4770 bx lr + 28e50: 4618 mov r0, r3 + 28e52: e7d3 b.n 28dfc <__rtl_strchr_v1_00+0x6c> + +00028e54 <__rtl_strcmp_v1_00>: + 28e54: ea40 0301 orr.w r3, r0, r1 + 28e58: f013 0303 ands.w r3, r3, #3 + 28e5c: b470 push {r4, r5, r6} + 28e5e: d11d bne.n 28e9c <__rtl_strcmp_v1_00+0x48> + 28e60: 6802 ldr r2, [r0, #0] + 28e62: 680c ldr r4, [r1, #0] + 28e64: 42a2 cmp r2, r4 + 28e66: d119 bne.n 28e9c <__rtl_strcmp_v1_00+0x48> + 28e68: f1a2 3401 sub.w r4, r2, #16843009 ; 0x1010101 + 28e6c: ea24 0202 bic.w r2, r4, r2 + 28e70: f012 3f80 tst.w r2, #2155905152 ; 0x80808080 + 28e74: d125 bne.n 28ec2 <__rtl_strcmp_v1_00+0x6e> + 28e76: 1d04 adds r4, r0, #4 + 28e78: 1d0a adds r2, r1, #4 + 28e7a: e002 b.n 28e82 <__rtl_strcmp_v1_00+0x2e> + 28e7c: f016 3f80 tst.w r6, #2155905152 ; 0x80808080 + 28e80: d11c bne.n 28ebc <__rtl_strcmp_v1_00+0x68> + 28e82: 6815 ldr r5, [r2, #0] + 28e84: 4620 mov r0, r4 + 28e86: f854 3b04 ldr.w r3, [r4], #4 + 28e8a: 4611 mov r1, r2 + 28e8c: f1a3 3601 sub.w r6, r3, #16843009 ; 0x1010101 + 28e90: 42ab cmp r3, r5 + 28e92: f102 0204 add.w r2, r2, #4 + 28e96: ea26 0603 bic.w r6, r6, r3 + 28e9a: d0ef beq.n 28e7c <__rtl_strcmp_v1_00+0x28> + 28e9c: 7803 ldrb r3, [r0, #0] + 28e9e: 780a ldrb r2, [r1, #0] + 28ea0: b92b cbnz r3, 28eae <__rtl_strcmp_v1_00+0x5a> + 28ea2: e006 b.n 28eb2 <__rtl_strcmp_v1_00+0x5e> + 28ea4: f810 3f01 ldrb.w r3, [r0, #1]! + 28ea8: b133 cbz r3, 28eb8 <__rtl_strcmp_v1_00+0x64> + 28eaa: f811 2f01 ldrb.w r2, [r1, #1]! + 28eae: 4293 cmp r3, r2 + 28eb0: d0f8 beq.n 28ea4 <__rtl_strcmp_v1_00+0x50> + 28eb2: 1a98 subs r0, r3, r2 + 28eb4: bc70 pop {r4, r5, r6} + 28eb6: 4770 bx lr + 28eb8: 784a ldrb r2, [r1, #1] + 28eba: e7fa b.n 28eb2 <__rtl_strcmp_v1_00+0x5e> + 28ebc: 2000 movs r0, #0 + 28ebe: bc70 pop {r4, r5, r6} + 28ec0: 4770 bx lr + 28ec2: 4618 mov r0, r3 + 28ec4: e7f6 b.n 28eb4 <__rtl_strcmp_v1_00+0x60> + 28ec6: bf00 nop + +00028ec8 <__rtl_strcpy_v1_00>: + 28ec8: ea40 0301 orr.w r3, r0, r1 + 28ecc: 079b lsls r3, r3, #30 + 28ece: b430 push {r4, r5} + 28ed0: bf18 it ne + 28ed2: 4603 movne r3, r0 + 28ed4: d115 bne.n 28f02 <__rtl_strcpy_v1_00+0x3a> + 28ed6: 680a ldr r2, [r1, #0] + 28ed8: f1a2 3301 sub.w r3, r2, #16843009 ; 0x1010101 + 28edc: ea23 0302 bic.w r3, r3, r2 + 28ee0: f013 3f80 tst.w r3, #2155905152 ; 0x80808080 + 28ee4: 4603 mov r3, r0 + 28ee6: d10c bne.n 28f02 <__rtl_strcpy_v1_00+0x3a> + 28ee8: 1d0c adds r4, r1, #4 + 28eea: f843 2b04 str.w r2, [r3], #4 + 28eee: 4621 mov r1, r4 + 28ef0: f854 2b04 ldr.w r2, [r4], #4 + 28ef4: f1a2 3501 sub.w r5, r2, #16843009 ; 0x1010101 + 28ef8: ea25 0502 bic.w r5, r5, r2 + 28efc: f015 3f80 tst.w r5, #2155905152 ; 0x80808080 + 28f00: d0f3 beq.n 28eea <__rtl_strcpy_v1_00+0x22> + 28f02: f811 2b01 ldrb.w r2, [r1], #1 + 28f06: f803 2b01 strb.w r2, [r3], #1 + 28f0a: 2a00 cmp r2, #0 + 28f0c: d1f9 bne.n 28f02 <__rtl_strcpy_v1_00+0x3a> + 28f0e: bc30 pop {r4, r5} + 28f10: 4770 bx lr + 28f12: bf00 nop + +00028f14 <__rtl_strlen_v1_00>: + 28f14: 0783 lsls r3, r0, #30 + 28f16: d022 beq.n 28f5e <__rtl_strlen_v1_00+0x4a> + 28f18: 7803 ldrb r3, [r0, #0] + 28f1a: 1c42 adds r2, r0, #1 + 28f1c: b91b cbnz r3, 28f26 <__rtl_strlen_v1_00+0x12> + 28f1e: e020 b.n 28f62 <__rtl_strlen_v1_00+0x4e> + 28f20: 7819 ldrb r1, [r3, #0] + 28f22: 3201 adds r2, #1 + 28f24: b1c9 cbz r1, 28f5a <__rtl_strlen_v1_00+0x46> + 28f26: 0791 lsls r1, r2, #30 + 28f28: 4613 mov r3, r2 + 28f2a: d1f9 bne.n 28f20 <__rtl_strlen_v1_00+0xc> + 28f2c: 681a ldr r2, [r3, #0] + 28f2e: f1a2 3101 sub.w r1, r2, #16843009 ; 0x1010101 + 28f32: ea21 0202 bic.w r2, r1, r2 + 28f36: f012 3f80 tst.w r2, #2155905152 ; 0x80808080 + 28f3a: d108 bne.n 28f4e <__rtl_strlen_v1_00+0x3a> + 28f3c: f853 2f04 ldr.w r2, [r3, #4]! + 28f40: f1a2 3101 sub.w r1, r2, #16843009 ; 0x1010101 + 28f44: ea21 0202 bic.w r2, r1, r2 + 28f48: f012 3f80 tst.w r2, #2155905152 ; 0x80808080 + 28f4c: d0f6 beq.n 28f3c <__rtl_strlen_v1_00+0x28> + 28f4e: 781a ldrb r2, [r3, #0] + 28f50: b11a cbz r2, 28f5a <__rtl_strlen_v1_00+0x46> + 28f52: f813 2f01 ldrb.w r2, [r3, #1]! + 28f56: 2a00 cmp r2, #0 + 28f58: d1fb bne.n 28f52 <__rtl_strlen_v1_00+0x3e> + 28f5a: 1a18 subs r0, r3, r0 + 28f5c: 4770 bx lr + 28f5e: 4603 mov r3, r0 + 28f60: e7e4 b.n 28f2c <__rtl_strlen_v1_00+0x18> + 28f62: 4618 mov r0, r3 + 28f64: 4770 bx lr + 28f66: bf00 nop + +00028f68 <__rtl_strncat_v1_00>: + 28f68: 0783 lsls r3, r0, #30 + 28f6a: b430 push {r4, r5} + 28f6c: bf18 it ne + 28f6e: 4603 movne r3, r0 + 28f70: d111 bne.n 28f96 <__rtl_strncat_v1_00+0x2e> + 28f72: 6803 ldr r3, [r0, #0] + 28f74: f1a3 3401 sub.w r4, r3, #16843009 ; 0x1010101 + 28f78: ea24 0303 bic.w r3, r4, r3 + 28f7c: f013 3f80 tst.w r3, #2155905152 ; 0x80808080 + 28f80: 4603 mov r3, r0 + 28f82: d108 bne.n 28f96 <__rtl_strncat_v1_00+0x2e> + 28f84: f853 4f04 ldr.w r4, [r3, #4]! + 28f88: f1a4 3501 sub.w r5, r4, #16843009 ; 0x1010101 + 28f8c: ea25 0404 bic.w r4, r5, r4 + 28f90: f014 3f80 tst.w r4, #2155905152 ; 0x80808080 + 28f94: d0f6 beq.n 28f84 <__rtl_strncat_v1_00+0x1c> + 28f96: 781c ldrb r4, [r3, #0] + 28f98: b11c cbz r4, 28fa2 <__rtl_strncat_v1_00+0x3a> + 28f9a: f813 4f01 ldrb.w r4, [r3, #1]! + 28f9e: 2c00 cmp r4, #0 + 28fa0: d1fb bne.n 28f9a <__rtl_strncat_v1_00+0x32> + 28fa2: 3b01 subs r3, #1 + 28fa4: 188d adds r5, r1, r2 + 28fa6: e005 b.n 28fb4 <__rtl_strncat_v1_00+0x4c> + 28fa8: f811 4b01 ldrb.w r4, [r1], #1 + 28fac: f803 4f01 strb.w r4, [r3, #1]! + 28fb0: b124 cbz r4, 28fbc <__rtl_strncat_v1_00+0x54> + 28fb2: b12a cbz r2, 28fc0 <__rtl_strncat_v1_00+0x58> + 28fb4: 42a9 cmp r1, r5 + 28fb6: f102 32ff add.w r2, r2, #4294967295 + 28fba: d1f5 bne.n 28fa8 <__rtl_strncat_v1_00+0x40> + 28fbc: bc30 pop {r4, r5} + 28fbe: 4770 bx lr + 28fc0: 705a strb r2, [r3, #1] + 28fc2: e7f7 b.n 28fb4 <__rtl_strncat_v1_00+0x4c> + +00028fc4 <__rtl_strncmp_v1_00>: + 28fc4: 2a00 cmp r2, #0 + 28fc6: d04b beq.n 29060 <__rtl_strncmp_v1_00+0x9c> + 28fc8: ea40 0301 orr.w r3, r0, r1 + 28fcc: f013 0303 ands.w r3, r3, #3 + 28fd0: b430 push {r4, r5} + 28fd2: d12d bne.n 29030 <__rtl_strncmp_v1_00+0x6c> + 28fd4: 2a03 cmp r2, #3 + 28fd6: d92b bls.n 29030 <__rtl_strncmp_v1_00+0x6c> + 28fd8: 6804 ldr r4, [r0, #0] + 28fda: 680d ldr r5, [r1, #0] + 28fdc: 42ac cmp r4, r5 + 28fde: d127 bne.n 29030 <__rtl_strncmp_v1_00+0x6c> + 28fe0: 3a04 subs r2, #4 + 28fe2: d042 beq.n 2906a <__rtl_strncmp_v1_00+0xa6> + 28fe4: f1a4 3501 sub.w r5, r4, #16843009 ; 0x1010101 + 28fe8: ea25 0404 bic.w r4, r5, r4 + 28fec: f014 3f80 tst.w r4, #2155905152 ; 0x80808080 + 28ff0: d13d bne.n 2906e <__rtl_strncmp_v1_00+0xaa> + 28ff2: 460c mov r4, r1 + 28ff4: 4603 mov r3, r0 + 28ff6: e00e b.n 29016 <__rtl_strncmp_v1_00+0x52> + 28ff8: 685b ldr r3, [r3, #4] + 28ffa: 6864 ldr r4, [r4, #4] + 28ffc: f1a3 3501 sub.w r5, r3, #16843009 ; 0x1010101 + 29000: 42a3 cmp r3, r4 + 29002: ea25 0503 bic.w r5, r5, r3 + 29006: d113 bne.n 29030 <__rtl_strncmp_v1_00+0x6c> + 29008: 3a04 subs r2, #4 + 2900a: d02e beq.n 2906a <__rtl_strncmp_v1_00+0xa6> + 2900c: f015 3f80 tst.w r5, #2155905152 ; 0x80808080 + 29010: d128 bne.n 29064 <__rtl_strncmp_v1_00+0xa0> + 29012: 4603 mov r3, r0 + 29014: 460c mov r4, r1 + 29016: 2a03 cmp r2, #3 + 29018: f100 0004 add.w r0, r0, #4 + 2901c: f101 0104 add.w r1, r1, #4 + 29020: d8ea bhi.n 28ff8 <__rtl_strncmp_v1_00+0x34> + 29022: 1e55 subs r5, r2, #1 + 29024: b92a cbnz r2, 29032 <__rtl_strncmp_v1_00+0x6e> + 29026: 7918 ldrb r0, [r3, #4] + 29028: 7922 ldrb r2, [r4, #4] + 2902a: 1a80 subs r0, r0, r2 + 2902c: bc30 pop {r4, r5} + 2902e: 4770 bx lr + 29030: 1e55 subs r5, r2, #1 + 29032: 7803 ldrb r3, [r0, #0] + 29034: 780a ldrb r2, [r1, #0] + 29036: 4293 cmp r3, r2 + 29038: d11b bne.n 29072 <__rtl_strncmp_v1_00+0xae> + 2903a: b1e5 cbz r5, 29076 <__rtl_strncmp_v1_00+0xb2> + 2903c: b1bb cbz r3, 2906e <__rtl_strncmp_v1_00+0xaa> + 2903e: 1c6c adds r4, r5, #1 + 29040: 440c add r4, r1 + 29042: 1c8b adds r3, r1, #2 + 29044: 4601 mov r1, r0 + 29046: e004 b.n 29052 <__rtl_strncmp_v1_00+0x8e> + 29048: 42a3 cmp r3, r4 + 2904a: d00b beq.n 29064 <__rtl_strncmp_v1_00+0xa0> + 2904c: 3301 adds r3, #1 + 2904e: 2800 cmp r0, #0 + 29050: d0ec beq.n 2902c <__rtl_strncmp_v1_00+0x68> + 29052: f811 0f01 ldrb.w r0, [r1, #1]! + 29056: f813 2c01 ldrb.w r2, [r3, #-1] + 2905a: 4290 cmp r0, r2 + 2905c: d0f4 beq.n 29048 <__rtl_strncmp_v1_00+0x84> + 2905e: e7e4 b.n 2902a <__rtl_strncmp_v1_00+0x66> + 29060: 4610 mov r0, r2 + 29062: 4770 bx lr + 29064: 2000 movs r0, #0 + 29066: bc30 pop {r4, r5} + 29068: 4770 bx lr + 2906a: 4610 mov r0, r2 + 2906c: e7de b.n 2902c <__rtl_strncmp_v1_00+0x68> + 2906e: 4618 mov r0, r3 + 29070: e7dc b.n 2902c <__rtl_strncmp_v1_00+0x68> + 29072: 4618 mov r0, r3 + 29074: e7d9 b.n 2902a <__rtl_strncmp_v1_00+0x66> + 29076: 4628 mov r0, r5 + 29078: e7d8 b.n 2902c <__rtl_strncmp_v1_00+0x68> + 2907a: bf00 nop + +0002907c <__rtl_strncpy_v1_00>: + 2907c: ea40 0301 orr.w r3, r0, r1 + 29080: 079b lsls r3, r3, #30 + 29082: b470 push {r4, r5, r6} + 29084: d12c bne.n 290e0 <__rtl_strncpy_v1_00+0x64> + 29086: 2a03 cmp r2, #3 + 29088: bf84 itt hi + 2908a: 460c movhi r4, r1 + 2908c: 4603 movhi r3, r0 + 2908e: d927 bls.n 290e0 <__rtl_strncpy_v1_00+0x64> + 29090: 4621 mov r1, r4 + 29092: f854 5b04 ldr.w r5, [r4], #4 + 29096: f1a5 3601 sub.w r6, r5, #16843009 ; 0x1010101 + 2909a: ea26 0605 bic.w r6, r6, r5 + 2909e: f016 3f80 tst.w r6, #2155905152 ; 0x80808080 + 290a2: d105 bne.n 290b0 <__rtl_strncpy_v1_00+0x34> + 290a4: 3a04 subs r2, #4 + 290a6: 2a03 cmp r2, #3 + 290a8: f843 5b04 str.w r5, [r3], #4 + 290ac: 4621 mov r1, r4 + 290ae: d8ef bhi.n 29090 <__rtl_strncpy_v1_00+0x14> + 290b0: b1a2 cbz r2, 290dc <__rtl_strncpy_v1_00+0x60> + 290b2: 780c ldrb r4, [r1, #0] + 290b4: 3a01 subs r2, #1 + 290b6: 701c strb r4, [r3, #0] + 290b8: 3101 adds r1, #1 + 290ba: 3301 adds r3, #1 + 290bc: b13c cbz r4, 290ce <__rtl_strncpy_v1_00+0x52> + 290be: b16a cbz r2, 290dc <__rtl_strncpy_v1_00+0x60> + 290c0: f811 4b01 ldrb.w r4, [r1], #1 + 290c4: 3a01 subs r2, #1 + 290c6: f803 4b01 strb.w r4, [r3], #1 + 290ca: 2c00 cmp r4, #0 + 290cc: d1f7 bne.n 290be <__rtl_strncpy_v1_00+0x42> + 290ce: b12a cbz r2, 290dc <__rtl_strncpy_v1_00+0x60> + 290d0: 441a add r2, r3 + 290d2: 2100 movs r1, #0 + 290d4: f803 1b01 strb.w r1, [r3], #1 + 290d8: 4293 cmp r3, r2 + 290da: d1fb bne.n 290d4 <__rtl_strncpy_v1_00+0x58> + 290dc: bc70 pop {r4, r5, r6} + 290de: 4770 bx lr + 290e0: 4603 mov r3, r0 + 290e2: e7e5 b.n 290b0 <__rtl_strncpy_v1_00+0x34> + +000290e4 <__rtl_critical_factorization_v1_00>: + 290e4: f04f 0c01 mov.w ip, #1 + 290e8: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + 290ec: 4664 mov r4, ip + 290ee: 2500 movs r5, #0 + 290f0: f04f 36ff mov.w r6, #4294967295 + 290f4: 1963 adds r3, r4, r5 + 290f6: 428b cmp r3, r1 + 290f8: eb00 0706 add.w r7, r0, r6 + 290fc: d20d bcs.n 2911a <__rtl_critical_factorization_v1_00+0x36> + 290fe: 5d3f ldrb r7, [r7, r4] + 29100: f810 e003 ldrb.w lr, [r0, r3] + 29104: 45be cmp lr, r7 + 29106: d22d bcs.n 29164 <__rtl_critical_factorization_v1_00+0x80> + 29108: 461d mov r5, r3 + 2910a: 2401 movs r4, #1 + 2910c: ebc6 0c03 rsb ip, r6, r3 + 29110: 1963 adds r3, r4, r5 + 29112: 428b cmp r3, r1 + 29114: eb00 0706 add.w r7, r0, r6 + 29118: d3f1 bcc.n 290fe <__rtl_critical_factorization_v1_00+0x1a> + 2911a: f04f 0801 mov.w r8, #1 + 2911e: 4644 mov r4, r8 + 29120: f8c2 c000 str.w ip, [r2] + 29124: 2500 movs r5, #0 + 29126: f04f 37ff mov.w r7, #4294967295 + 2912a: 1963 adds r3, r4, r5 + 2912c: 4299 cmp r1, r3 + 2912e: eb00 0e07 add.w lr, r0, r7 + 29132: d90e bls.n 29152 <__rtl_critical_factorization_v1_00+0x6e> + 29134: f81e e004 ldrb.w lr, [lr, r4] + 29138: f810 c003 ldrb.w ip, [r0, r3] + 2913c: 45f4 cmp ip, lr + 2913e: d918 bls.n 29172 <__rtl_critical_factorization_v1_00+0x8e> + 29140: 461d mov r5, r3 + 29142: 2401 movs r4, #1 + 29144: ebc7 0803 rsb r8, r7, r3 + 29148: 1963 adds r3, r4, r5 + 2914a: 4299 cmp r1, r3 + 2914c: eb00 0e07 add.w lr, r0, r7 + 29150: d8f0 bhi.n 29134 <__rtl_critical_factorization_v1_00+0x50> + 29152: 3701 adds r7, #1 + 29154: 1c70 adds r0, r6, #1 + 29156: 4287 cmp r7, r0 + 29158: bf24 itt cs + 2915a: 4638 movcs r0, r7 + 2915c: f8c2 8000 strcs.w r8, [r2] + 29160: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 29164: d00c beq.n 29180 <__rtl_critical_factorization_v1_00+0x9c> + 29166: f04f 0c01 mov.w ip, #1 + 2916a: 462e mov r6, r5 + 2916c: 4664 mov r4, ip + 2916e: 4465 add r5, ip + 29170: e7c0 b.n 290f4 <__rtl_critical_factorization_v1_00+0x10> + 29172: d00c beq.n 2918e <__rtl_critical_factorization_v1_00+0xaa> + 29174: f04f 0801 mov.w r8, #1 + 29178: 462f mov r7, r5 + 2917a: 4644 mov r4, r8 + 2917c: 4445 add r5, r8 + 2917e: e7d4 b.n 2912a <__rtl_critical_factorization_v1_00+0x46> + 29180: 4564 cmp r4, ip + 29182: bf18 it ne + 29184: 3401 addne r4, #1 + 29186: d1b5 bne.n 290f4 <__rtl_critical_factorization_v1_00+0x10> + 29188: 461d mov r5, r3 + 2918a: 2401 movs r4, #1 + 2918c: e7b2 b.n 290f4 <__rtl_critical_factorization_v1_00+0x10> + 2918e: 4544 cmp r4, r8 + 29190: bf18 it ne + 29192: 3401 addne r4, #1 + 29194: d1c9 bne.n 2912a <__rtl_critical_factorization_v1_00+0x46> + 29196: 461d mov r5, r3 + 29198: 2401 movs r4, #1 + 2919a: e7c6 b.n 2912a <__rtl_critical_factorization_v1_00+0x46> + +0002919c <__rtl_two_way_long_needle_v1_00>: + 2919c: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 291a0: f2ad 4d24 subw sp, sp, #1060 ; 0x424 + 291a4: 4616 mov r6, r2 + 291a6: 4680 mov r8, r0 + 291a8: 460c mov r4, r1 + 291aa: 4610 mov r0, r2 + 291ac: 4619 mov r1, r3 + 291ae: aa07 add r2, sp, #28 + 291b0: 461d mov r5, r3 + 291b2: f7ff ff97 bl 290e4 <__rtl_critical_factorization_v1_00> + 291b6: ab07 add r3, sp, #28 + 291b8: 9003 str r0, [sp, #12] + 291ba: f20d 421c addw r2, sp, #1052 ; 0x41c + 291be: f843 5f04 str.w r5, [r3, #4]! + 291c2: 4293 cmp r3, r2 + 291c4: d1fb bne.n 291be <__rtl_two_way_long_needle_v1_00+0x22> + 291c6: 1e6f subs r7, r5, #1 + 291c8: 2300 movs r3, #0 + 291ca: a808 add r0, sp, #32 + 291cc: b135 cbz r5, 291dc <__rtl_two_way_long_needle_v1_00+0x40> + 291ce: 5cf2 ldrb r2, [r6, r3] + 291d0: 1af9 subs r1, r7, r3 + 291d2: 3301 adds r3, #1 + 291d4: 42ab cmp r3, r5 + 291d6: f840 1022 str.w r1, [r0, r2, lsl #2] + 291da: d1f8 bne.n 291ce <__rtl_two_way_long_needle_v1_00+0x32> + 291dc: f648 23e1 movw r3, #35553 ; 0x8ae1 + 291e0: 9907 ldr r1, [sp, #28] + 291e2: f2c0 0302 movt r3, #2 + 291e6: 4431 add r1, r6 + 291e8: 4630 mov r0, r6 + 291ea: 9a03 ldr r2, [sp, #12] + 291ec: 4798 blx r3 + 291ee: 2800 cmp r0, #0 + 291f0: f040 8081 bne.w 292f6 <__rtl_two_way_long_needle_v1_00+0x15a> + 291f4: 9b03 ldr r3, [sp, #12] + 291f6: 4683 mov fp, r0 + 291f8: 3b01 subs r3, #1 + 291fa: 9302 str r3, [sp, #8] + 291fc: f648 234d movw r3, #35405 ; 0x8a4d + 29200: f2c0 0302 movt r3, #2 + 29204: 4682 mov sl, r0 + 29206: 4620 mov r0, r4 + 29208: 9301 str r3, [sp, #4] + 2920a: 9b02 ldr r3, [sp, #8] + 2920c: 1e6f subs r7, r5, #1 + 2920e: 4433 add r3, r6 + 29210: 9304 str r3, [sp, #16] + 29212: 9b03 ldr r3, [sp, #12] + 29214: f1c3 0301 rsb r3, r3, #1 + 29218: 9305 str r3, [sp, #20] + 2921a: eb0a 0405 add.w r4, sl, r5 + 2921e: 1a22 subs r2, r4, r0 + 29220: 2100 movs r1, #0 + 29222: 4440 add r0, r8 + 29224: 9b01 ldr r3, [sp, #4] + 29226: 4798 blx r3 + 29228: 2800 cmp r0, #0 + 2922a: d15f bne.n 292ec <__rtl_two_way_long_needle_v1_00+0x150> + 2922c: 2c00 cmp r4, #0 + 2922e: d05d beq.n 292ec <__rtl_two_way_long_needle_v1_00+0x150> + 29230: eb08 0304 add.w r3, r8, r4 + 29234: f813 3c01 ldrb.w r3, [r3, #-1] + 29238: f10d 0e20 add.w lr, sp, #32 + 2923c: f85e 3023 ldr.w r3, [lr, r3, lsl #2] + 29240: b15b cbz r3, 2925a <__rtl_two_way_long_needle_v1_00+0xbe> + 29242: f1bb 0f00 cmp.w fp, #0 + 29246: d003 beq.n 29250 <__rtl_two_way_long_needle_v1_00+0xb4> + 29248: 9a07 ldr r2, [sp, #28] + 2924a: 4293 cmp r3, r2 + 2924c: bf38 it cc + 2924e: 1aab subcc r3, r5, r2 + 29250: 449a add sl, r3 + 29252: f04f 0b00 mov.w fp, #0 + 29256: 4620 mov r0, r4 + 29258: e7df b.n 2921a <__rtl_two_way_long_needle_v1_00+0x7e> + 2925a: 9a03 ldr r2, [sp, #12] + 2925c: 455a cmp r2, fp + 2925e: bf38 it cc + 29260: 465a movcc r2, fp + 29262: 42ba cmp r2, r7 + 29264: d211 bcs.n 2928a <__rtl_two_way_long_needle_v1_00+0xee> + 29266: eb08 030a add.w r3, r8, sl + 2926a: 5c98 ldrb r0, [r3, r2] + 2926c: f816 e002 ldrb.w lr, [r6, r2] + 29270: 18b1 adds r1, r6, r2 + 29272: 4586 cmp lr, r0 + 29274: d006 beq.n 29284 <__rtl_two_way_long_needle_v1_00+0xe8> + 29276: e032 b.n 292de <__rtl_two_way_long_needle_v1_00+0x142> + 29278: f811 0f01 ldrb.w r0, [r1, #1]! + 2927c: f813 e002 ldrb.w lr, [r3, r2] + 29280: 4586 cmp lr, r0 + 29282: d12c bne.n 292de <__rtl_two_way_long_needle_v1_00+0x142> + 29284: 3201 adds r2, #1 + 29286: 42ba cmp r2, r7 + 29288: d3f6 bcc.n 29278 <__rtl_two_way_long_needle_v1_00+0xdc> + 2928a: 9b03 ldr r3, [sp, #12] + 2928c: 9802 ldr r0, [sp, #8] + 2928e: 459b cmp fp, r3 + 29290: bf28 it cs + 29292: 4618 movcs r0, r3 + 29294: d219 bcs.n 292ca <__rtl_two_way_long_needle_v1_00+0x12e> + 29296: 9902 ldr r1, [sp, #8] + 29298: f8dd e010 ldr.w lr, [sp, #16] + 2929c: eb08 030a add.w r3, r8, sl + 292a0: 5c5a ldrb r2, [r3, r1] + 292a2: f89e 1000 ldrb.w r1, [lr] + 292a6: 4291 cmp r1, r2 + 292a8: f040 808a bne.w 293c0 <__rtl_two_way_long_needle_v1_00+0x224> + 292ac: 4672 mov r2, lr + 292ae: eb06 090b add.w r9, r6, fp + 292b2: e006 b.n 292c2 <__rtl_two_way_long_needle_v1_00+0x126> + 292b4: f812 cd01 ldrb.w ip, [r2, #-1]! + 292b8: f813 e001 ldrb.w lr, [r3, r1] + 292bc: 45f4 cmp ip, lr + 292be: d104 bne.n 292ca <__rtl_two_way_long_needle_v1_00+0x12e> + 292c0: 4608 mov r0, r1 + 292c2: 454a cmp r2, r9 + 292c4: f100 31ff add.w r1, r0, #4294967295 + 292c8: d1f4 bne.n 292b4 <__rtl_two_way_long_needle_v1_00+0x118> + 292ca: f10b 0b01 add.w fp, fp, #1 + 292ce: 4583 cmp fp, r0 + 292d0: d878 bhi.n 293c4 <__rtl_two_way_long_needle_v1_00+0x228> + 292d2: 9b07 ldr r3, [sp, #28] + 292d4: 4620 mov r0, r4 + 292d6: 449a add sl, r3 + 292d8: ebc3 0b05 rsb fp, r3, r5 + 292dc: e79d b.n 2921a <__rtl_two_way_long_needle_v1_00+0x7e> + 292de: 9b05 ldr r3, [sp, #20] + 292e0: f04f 0b00 mov.w fp, #0 + 292e4: 449a add sl, r3 + 292e6: 4492 add sl, r2 + 292e8: 4620 mov r0, r4 + 292ea: e796 b.n 2921a <__rtl_two_way_long_needle_v1_00+0x7e> + 292ec: 2000 movs r0, #0 + 292ee: f20d 4d24 addw sp, sp, #1060 ; 0x424 + 292f2: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 292f6: 9903 ldr r1, [sp, #12] + 292f8: f648 224d movw r2, #35405 ; 0x8a4d + 292fc: 1a6b subs r3, r5, r1 + 292fe: 428b cmp r3, r1 + 29300: bf38 it cc + 29302: 460b movcc r3, r1 + 29304: 3301 adds r3, #1 + 29306: 9307 str r3, [sp, #28] + 29308: 1e4b subs r3, r1, #1 + 2930a: 9302 str r3, [sp, #8] + 2930c: 9b03 ldr r3, [sp, #12] + 2930e: f2c0 0202 movt r2, #2 + 29312: f1c3 0301 rsb r3, r3, #1 + 29316: 9305 str r3, [sp, #20] + 29318: 4633 mov r3, r6 + 2931a: 4431 add r1, r6 + 2931c: 4620 mov r0, r4 + 2931e: 4646 mov r6, r8 + 29320: 4698 mov r8, r3 + 29322: f8dd a00c ldr.w sl, [sp, #12] + 29326: 9201 str r2, [sp, #4] + 29328: f04f 0b00 mov.w fp, #0 + 2932c: f10d 0920 add.w r9, sp, #32 + 29330: 1e6f subs r7, r5, #1 + 29332: 9104 str r1, [sp, #16] + 29334: eb0b 0405 add.w r4, fp, r5 + 29338: 1a22 subs r2, r4, r0 + 2933a: 2100 movs r1, #0 + 2933c: 4430 add r0, r6 + 2933e: 9b01 ldr r3, [sp, #4] + 29340: 4798 blx r3 + 29342: 2800 cmp r0, #0 + 29344: d1d2 bne.n 292ec <__rtl_two_way_long_needle_v1_00+0x150> + 29346: 2c00 cmp r4, #0 + 29348: d0d0 beq.n 292ec <__rtl_two_way_long_needle_v1_00+0x150> + 2934a: 1933 adds r3, r6, r4 + 2934c: f813 3c01 ldrb.w r3, [r3, #-1] + 29350: f859 3023 ldr.w r3, [r9, r3, lsl #2] + 29354: bb5b cbnz r3, 293ae <__rtl_two_way_long_needle_v1_00+0x212> + 29356: 45ba cmp sl, r7 + 29358: eb06 000b add.w r0, r6, fp + 2935c: d215 bcs.n 2938a <__rtl_two_way_long_needle_v1_00+0x1ee> + 2935e: f8dd e010 ldr.w lr, [sp, #16] + 29362: f810 300a ldrb.w r3, [r0, sl] + 29366: f89e 2000 ldrb.w r2, [lr] + 2936a: 429a cmp r2, r3 + 2936c: bf18 it ne + 2936e: 4653 movne r3, sl + 29370: d120 bne.n 293b4 <__rtl_two_way_long_needle_v1_00+0x218> + 29372: 9a04 ldr r2, [sp, #16] + 29374: 4653 mov r3, sl + 29376: e005 b.n 29384 <__rtl_two_way_long_needle_v1_00+0x1e8> + 29378: f812 1f01 ldrb.w r1, [r2, #1]! + 2937c: f810 e003 ldrb.w lr, [r0, r3] + 29380: 458e cmp lr, r1 + 29382: d117 bne.n 293b4 <__rtl_two_way_long_needle_v1_00+0x218> + 29384: 3301 adds r3, #1 + 29386: 42bb cmp r3, r7 + 29388: d3f6 bcc.n 29378 <__rtl_two_way_long_needle_v1_00+0x1dc> + 2938a: 9b02 ldr r3, [sp, #8] + 2938c: 1c5a adds r2, r3, #1 + 2938e: d0ae beq.n 292ee <__rtl_two_way_long_needle_v1_00+0x152> + 29390: 9a02 ldr r2, [sp, #8] + 29392: f818 1002 ldrb.w r1, [r8, r2] + 29396: 5c82 ldrb r2, [r0, r2] + 29398: 4291 cmp r1, r2 + 2939a: d107 bne.n 293ac <__rtl_two_way_long_needle_v1_00+0x210> + 2939c: f113 33ff adds.w r3, r3, #4294967295 + 293a0: d3a5 bcc.n 292ee <__rtl_two_way_long_needle_v1_00+0x152> + 293a2: f818 1003 ldrb.w r1, [r8, r3] + 293a6: 5cc2 ldrb r2, [r0, r3] + 293a8: 4291 cmp r1, r2 + 293aa: d0f7 beq.n 2939c <__rtl_two_way_long_needle_v1_00+0x200> + 293ac: 9b07 ldr r3, [sp, #28] + 293ae: 449b add fp, r3 + 293b0: 4620 mov r0, r4 + 293b2: e7bf b.n 29334 <__rtl_two_way_long_needle_v1_00+0x198> + 293b4: f8dd e014 ldr.w lr, [sp, #20] + 293b8: 4620 mov r0, r4 + 293ba: 44f3 add fp, lr + 293bc: 449b add fp, r3 + 293be: e7b9 b.n 29334 <__rtl_two_way_long_needle_v1_00+0x198> + 293c0: 9803 ldr r0, [sp, #12] + 293c2: e782 b.n 292ca <__rtl_two_way_long_needle_v1_00+0x12e> + 293c4: eb08 000a add.w r0, r8, sl + 293c8: e791 b.n 292ee <__rtl_two_way_long_needle_v1_00+0x152> + 293ca: bf00 nop + +000293cc <__rtl_strstr_v1_00>: + 293cc: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 293d0: 7803 ldrb r3, [r0, #0] + 293d2: b087 sub sp, #28 + 293d4: 4681 mov r9, r0 + 293d6: 460e mov r6, r1 + 293d8: 2b00 cmp r3, #0 + 293da: f000 810e beq.w 295fa <__rtl_strstr_v1_00+0x22e> + 293de: 780a ldrb r2, [r1, #0] + 293e0: b19a cbz r2, 2940a <__rtl_strstr_v1_00+0x3e> + 293e2: 4686 mov lr, r0 + 293e4: 3101 adds r1, #1 + 293e6: 2401 movs r4, #1 + 293e8: e002 b.n 293f0 <__rtl_strstr_v1_00+0x24> + 293ea: f811 2b01 ldrb.w r2, [r1], #1 + 293ee: b15a cbz r2, 29408 <__rtl_strstr_v1_00+0x3c> + 293f0: 4293 cmp r3, r2 + 293f2: bf14 ite ne + 293f4: 2400 movne r4, #0 + 293f6: f004 0401 andeq.w r4, r4, #1 + 293fa: f81e 3f01 ldrb.w r3, [lr, #1]! + 293fe: 460d mov r5, r1 + 29400: 2b00 cmp r3, #0 + 29402: d1f2 bne.n 293ea <__rtl_strstr_v1_00+0x1e> + 29404: 782b ldrb r3, [r5, #0] + 29406: bb1b cbnz r3, 29450 <__rtl_strstr_v1_00+0x84> + 29408: b11c cbz r4, 29412 <__rtl_strstr_v1_00+0x46> + 2940a: 4648 mov r0, r9 + 2940c: b007 add sp, #28 + 2940e: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 29412: f648 5391 movw r3, #36241 ; 0x8d91 + 29416: f109 0001 add.w r0, r9, #1 + 2941a: f2c0 0302 movt r3, #2 + 2941e: 7831 ldrb r1, [r6, #0] + 29420: 4798 blx r3 + 29422: 1bad subs r5, r5, r6 + 29424: 2d01 cmp r5, #1 + 29426: bf18 it ne + 29428: 2800 cmpne r0, #0 + 2942a: 4607 mov r7, r0 + 2942c: d0ee beq.n 2940c <__rtl_strstr_v1_00+0x40> + 2942e: 44a9 add r9, r5 + 29430: 454f cmp r7, r9 + 29432: bf94 ite ls + 29434: ebc7 0409 rsbls r4, r7, r9 + 29438: 2401 movhi r4, #1 + 2943a: 2d1f cmp r5, #31 + 2943c: d90c bls.n 29458 <__rtl_strstr_v1_00+0x8c> + 2943e: 4638 mov r0, r7 + 29440: 4621 mov r1, r4 + 29442: 4632 mov r2, r6 + 29444: 462b mov r3, r5 + 29446: f7ff fea9 bl 2919c <__rtl_two_way_long_needle_v1_00> + 2944a: b007 add sp, #28 + 2944c: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 29450: 2000 movs r0, #0 + 29452: b007 add sp, #28 + 29454: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 29458: 4629 mov r1, r5 + 2945a: aa05 add r2, sp, #20 + 2945c: 4630 mov r0, r6 + 2945e: f7ff fe41 bl 290e4 <__rtl_critical_factorization_v1_00> + 29462: f648 23e1 movw r3, #35553 ; 0x8ae1 + 29466: 9905 ldr r1, [sp, #20] + 29468: 4680 mov r8, r0 + 2946a: 4602 mov r2, r0 + 2946c: f2c0 0302 movt r3, #2 + 29470: 4431 add r1, r6 + 29472: 4630 mov r0, r6 + 29474: 4798 blx r3 + 29476: 2800 cmp r0, #0 + 29478: d15b bne.n 29532 <__rtl_strstr_v1_00+0x166> + 2947a: f108 33ff add.w r3, r8, #4294967295 + 2947e: 9301 str r3, [sp, #4] + 29480: f648 234d movw r3, #35405 ; 0x8a4d + 29484: f2c0 0302 movt r3, #2 + 29488: 4683 mov fp, r0 + 2948a: 4681 mov r9, r0 + 2948c: 4620 mov r0, r4 + 2948e: 9300 str r3, [sp, #0] + 29490: 9b01 ldr r3, [sp, #4] + 29492: 4433 add r3, r6 + 29494: 9302 str r3, [sp, #8] + 29496: f1c8 0301 rsb r3, r8, #1 + 2949a: 9303 str r3, [sp, #12] + 2949c: eb09 0405 add.w r4, r9, r5 + 294a0: 1a22 subs r2, r4, r0 + 294a2: 2100 movs r1, #0 + 294a4: 4438 add r0, r7 + 294a6: 9b00 ldr r3, [sp, #0] + 294a8: 4798 blx r3 + 294aa: 2800 cmp r0, #0 + 294ac: d1d0 bne.n 29450 <__rtl_strstr_v1_00+0x84> + 294ae: 2c00 cmp r4, #0 + 294b0: d0ce beq.n 29450 <__rtl_strstr_v1_00+0x84> + 294b2: 45c3 cmp fp, r8 + 294b4: 465b mov r3, fp + 294b6: bf38 it cc + 294b8: 4643 movcc r3, r8 + 294ba: 429d cmp r5, r3 + 294bc: d914 bls.n 294e8 <__rtl_strstr_v1_00+0x11c> + 294be: 18fa adds r2, r7, r3 + 294c0: f812 1009 ldrb.w r1, [r2, r9] + 294c4: 5cf0 ldrb r0, [r6, r3] + 294c6: 18f2 adds r2, r6, r3 + 294c8: 4288 cmp r0, r1 + 294ca: f040 808f bne.w 295ec <__rtl_strstr_v1_00+0x220> + 294ce: eb07 0e09 add.w lr, r7, r9 + 294d2: e006 b.n 294e2 <__rtl_strstr_v1_00+0x116> + 294d4: f812 1f01 ldrb.w r1, [r2, #1]! + 294d8: f81e 0003 ldrb.w r0, [lr, r3] + 294dc: 4288 cmp r0, r1 + 294de: f040 8085 bne.w 295ec <__rtl_strstr_v1_00+0x220> + 294e2: 3301 adds r3, #1 + 294e4: 429d cmp r5, r3 + 294e6: d8f5 bhi.n 294d4 <__rtl_strstr_v1_00+0x108> + 294e8: 45d8 cmp r8, fp + 294ea: 9901 ldr r1, [sp, #4] + 294ec: f240 8088 bls.w 29600 <__rtl_strstr_v1_00+0x234> + 294f0: 9802 ldr r0, [sp, #8] + 294f2: eb07 0c09 add.w ip, r7, r9 + 294f6: f81c 3001 ldrb.w r3, [ip, r1] + 294fa: 7802 ldrb r2, [r0, #0] + 294fc: 429a cmp r2, r3 + 294fe: d17f bne.n 29600 <__rtl_strstr_v1_00+0x234> + 29500: 4603 mov r3, r0 + 29502: eb06 0a0b add.w sl, r6, fp + 29506: e006 b.n 29516 <__rtl_strstr_v1_00+0x14a> + 29508: f813 ed01 ldrb.w lr, [r3, #-1]! + 2950c: f81c 0002 ldrb.w r0, [ip, r2] + 29510: 4586 cmp lr, r0 + 29512: d104 bne.n 2951e <__rtl_strstr_v1_00+0x152> + 29514: 4611 mov r1, r2 + 29516: 4553 cmp r3, sl + 29518: f101 32ff add.w r2, r1, #4294967295 + 2951c: d1f4 bne.n 29508 <__rtl_strstr_v1_00+0x13c> + 2951e: f10b 0b01 add.w fp, fp, #1 + 29522: 458b cmp fp, r1 + 29524: d86e bhi.n 29604 <__rtl_strstr_v1_00+0x238> + 29526: 9b05 ldr r3, [sp, #20] + 29528: 4620 mov r0, r4 + 2952a: 4499 add r9, r3 + 2952c: ebc3 0b05 rsb fp, r3, r5 + 29530: e7b4 b.n 2949c <__rtl_strstr_v1_00+0xd0> + 29532: f648 204d movw r0, #35405 ; 0x8a4d + 29536: f2c0 0002 movt r0, #2 + 2953a: ebc8 0305 rsb r3, r8, r5 + 2953e: 4543 cmp r3, r8 + 29540: bf38 it cc + 29542: 4643 movcc r3, r8 + 29544: 9000 str r0, [sp, #0] + 29546: 4620 mov r0, r4 + 29548: 3301 adds r3, #1 + 2954a: 9305 str r3, [sp, #20] + 2954c: eb07 0308 add.w r3, r7, r8 + 29550: 9301 str r3, [sp, #4] + 29552: f1c8 0301 rsb r3, r8, #1 + 29556: f04f 0b00 mov.w fp, #0 + 2955a: eb06 0a08 add.w sl, r6, r8 + 2955e: 9302 str r3, [sp, #8] + 29560: f108 39ff add.w r9, r8, #4294967295 + 29564: eb0b 0405 add.w r4, fp, r5 + 29568: 1a22 subs r2, r4, r0 + 2956a: 2100 movs r1, #0 + 2956c: 4438 add r0, r7 + 2956e: 9b00 ldr r3, [sp, #0] + 29570: 4798 blx r3 + 29572: 2800 cmp r0, #0 + 29574: f47f af6c bne.w 29450 <__rtl_strstr_v1_00+0x84> + 29578: 2c00 cmp r4, #0 + 2957a: f43f af69 beq.w 29450 <__rtl_strstr_v1_00+0x84> + 2957e: 4545 cmp r5, r8 + 29580: bf98 it ls + 29582: eb07 000b addls.w r0, r7, fp + 29586: d914 bls.n 295b2 <__rtl_strstr_v1_00+0x1e6> + 29588: 9801 ldr r0, [sp, #4] + 2958a: f89a 2000 ldrb.w r2, [sl] + 2958e: f810 300b ldrb.w r3, [r0, fp] + 29592: 429a cmp r2, r3 + 29594: d124 bne.n 295e0 <__rtl_strstr_v1_00+0x214> + 29596: 4652 mov r2, sl + 29598: 4643 mov r3, r8 + 2959a: eb07 000b add.w r0, r7, fp + 2959e: e005 b.n 295ac <__rtl_strstr_v1_00+0x1e0> + 295a0: f812 1f01 ldrb.w r1, [r2, #1]! + 295a4: f810 e003 ldrb.w lr, [r0, r3] + 295a8: 458e cmp lr, r1 + 295aa: d11a bne.n 295e2 <__rtl_strstr_v1_00+0x216> + 295ac: 3301 adds r3, #1 + 295ae: 429d cmp r5, r3 + 295b0: d8f6 bhi.n 295a0 <__rtl_strstr_v1_00+0x1d4> + 295b2: f1b9 3fff cmp.w r9, #4294967295 + 295b6: 464b mov r3, r9 + 295b8: f43f af28 beq.w 2940c <__rtl_strstr_v1_00+0x40> + 295bc: f816 1009 ldrb.w r1, [r6, r9] + 295c0: f810 2009 ldrb.w r2, [r0, r9] + 295c4: 4291 cmp r1, r2 + 295c6: d107 bne.n 295d8 <__rtl_strstr_v1_00+0x20c> + 295c8: f113 33ff adds.w r3, r3, #4294967295 + 295cc: f4ff af1e bcc.w 2940c <__rtl_strstr_v1_00+0x40> + 295d0: 5cf1 ldrb r1, [r6, r3] + 295d2: 5cc2 ldrb r2, [r0, r3] + 295d4: 4291 cmp r1, r2 + 295d6: d0f7 beq.n 295c8 <__rtl_strstr_v1_00+0x1fc> + 295d8: 9b05 ldr r3, [sp, #20] + 295da: 4620 mov r0, r4 + 295dc: 449b add fp, r3 + 295de: e7c1 b.n 29564 <__rtl_strstr_v1_00+0x198> + 295e0: 4643 mov r3, r8 + 295e2: 9a02 ldr r2, [sp, #8] + 295e4: 4620 mov r0, r4 + 295e6: 4493 add fp, r2 + 295e8: 449b add fp, r3 + 295ea: e7bb b.n 29564 <__rtl_strstr_v1_00+0x198> + 295ec: 9903 ldr r1, [sp, #12] + 295ee: f04f 0b00 mov.w fp, #0 + 295f2: 4489 add r9, r1 + 295f4: 4499 add r9, r3 + 295f6: 4620 mov r0, r4 + 295f8: e750 b.n 2949c <__rtl_strstr_v1_00+0xd0> + 295fa: 460d mov r5, r1 + 295fc: 2401 movs r4, #1 + 295fe: e701 b.n 29404 <__rtl_strstr_v1_00+0x38> + 29600: 4641 mov r1, r8 + 29602: e78c b.n 2951e <__rtl_strstr_v1_00+0x152> + 29604: eb07 0009 add.w r0, r7, r9 + 29608: e700 b.n 2940c <__rtl_strstr_v1_00+0x40> + 2960a: bf00 nop + +0002960c <__rtl_strsep_v1_00>: + 2960c: 4602 mov r2, r0 + 2960e: 2300 movs r3, #0 + 29610: 6800 ldr r0, [r0, #0] + 29612: f000 b80b b.w 2962c <__rtl__strtok_r_v1_00> + 29616: bf00 nop + +00029618 <__rtl_strtok_v1_00>: + 29618: f641 4360 movw r3, #7264 ; 0x1c60 + 2961c: f2c1 0300 movt r3, #4096 ; 0x1000 + 29620: 681a ldr r2, [r3, #0] + 29622: 2301 movs r3, #1 + 29624: 325c adds r2, #92 ; 0x5c + 29626: f000 b801 b.w 2962c <__rtl__strtok_r_v1_00> + 2962a: bf00 nop + +0002962c <__rtl__strtok_r_v1_00>: + 2962c: b4f0 push {r4, r5, r6, r7} + 2962e: b320 cbz r0, 2967a <__rtl__strtok_r_v1_00+0x4e> + 29630: 4607 mov r7, r0 + 29632: 460d mov r5, r1 + 29634: f817 6b01 ldrb.w r6, [r7], #1 + 29638: e001 b.n 2963e <__rtl__strtok_r_v1_00+0x12> + 2963a: 42a6 cmp r6, r4 + 2963c: d016 beq.n 2966c <__rtl__strtok_r_v1_00+0x40> + 2963e: f815 4b01 ldrb.w r4, [r5], #1 + 29642: 2c00 cmp r4, #0 + 29644: d1f9 bne.n 2963a <__rtl__strtok_r_v1_00+0xe> + 29646: b1ee cbz r6, 29684 <__rtl__strtok_r_v1_00+0x58> + 29648: 463e mov r6, r7 + 2964a: 460c mov r4, r1 + 2964c: f816 5b01 ldrb.w r5, [r6], #1 + 29650: e000 b.n 29654 <__rtl__strtok_r_v1_00+0x28> + 29652: b173 cbz r3, 29672 <__rtl__strtok_r_v1_00+0x46> + 29654: f814 3b01 ldrb.w r3, [r4], #1 + 29658: 42ab cmp r3, r5 + 2965a: d1fa bne.n 29652 <__rtl__strtok_r_v1_00+0x26> + 2965c: b15d cbz r5, 29676 <__rtl__strtok_r_v1_00+0x4a> + 2965e: 2300 movs r3, #0 + 29660: 703b strb r3, [r7, #0] + 29662: 6016 str r6, [r2, #0] + 29664: 4606 mov r6, r0 + 29666: 4630 mov r0, r6 + 29668: bcf0 pop {r4, r5, r6, r7} + 2966a: 4770 bx lr + 2966c: b163 cbz r3, 29688 <__rtl__strtok_r_v1_00+0x5c> + 2966e: 4638 mov r0, r7 + 29670: e7de b.n 29630 <__rtl__strtok_r_v1_00+0x4> + 29672: 4637 mov r7, r6 + 29674: e7e8 b.n 29648 <__rtl__strtok_r_v1_00+0x1c> + 29676: 462e mov r6, r5 + 29678: e7f3 b.n 29662 <__rtl__strtok_r_v1_00+0x36> + 2967a: 6810 ldr r0, [r2, #0] + 2967c: 2800 cmp r0, #0 + 2967e: d1d7 bne.n 29630 <__rtl__strtok_r_v1_00+0x4> + 29680: 4606 mov r6, r0 + 29682: e7f0 b.n 29666 <__rtl__strtok_r_v1_00+0x3a> + 29684: 6016 str r6, [r2, #0] + 29686: e7ee b.n 29666 <__rtl__strtok_r_v1_00+0x3a> + 29688: 6017 str r7, [r2, #0] + 2968a: 4606 mov r6, r0 + 2968c: 7003 strb r3, [r0, #0] + 2968e: e7ea b.n 29666 <__rtl__strtok_r_v1_00+0x3a> + +00029690 <__rtl_strtok_r_v1_00>: + 29690: 2301 movs r3, #1 + 29692: f7ff bfcb b.w 2962c <__rtl__strtok_r_v1_00> + 29696: bf00 nop + +00029698 <__rtl_close_v1_00>: + 29698: f240 7360 movw r3, #1888 ; 0x760 + 2969c: f2c1 0300 movt r3, #4096 ; 0x1000 + 296a0: 681b ldr r3, [r3, #0] + 296a2: b103 cbz r3, 296a6 <__rtl_close_v1_00+0xe> + 296a4: 4718 bx r3 + 296a6: f04f 30ff mov.w r0, #4294967295 + 296aa: 4770 bx lr + +000296ac <__rtl_fstat_v1_00>: + 296ac: f240 7360 movw r3, #1888 ; 0x760 + 296b0: f2c1 0300 movt r3, #4096 ; 0x1000 + 296b4: 685b ldr r3, [r3, #4] + 296b6: b103 cbz r3, 296ba <__rtl_fstat_v1_00+0xe> + 296b8: 4718 bx r3 + 296ba: f04f 30ff mov.w r0, #4294967295 + 296be: 4770 bx lr + +000296c0 <__rtl_isatty_v1_00>: + 296c0: f240 7360 movw r3, #1888 ; 0x760 + 296c4: f2c1 0300 movt r3, #4096 ; 0x1000 + 296c8: 689b ldr r3, [r3, #8] + 296ca: b103 cbz r3, 296ce <__rtl_isatty_v1_00+0xe> + 296cc: 4718 bx r3 + 296ce: 4618 mov r0, r3 + 296d0: 4770 bx lr + 296d2: bf00 nop + +000296d4 <__rtl_lseek_v1_00>: + 296d4: f240 7360 movw r3, #1888 ; 0x760 + 296d8: f2c1 0300 movt r3, #4096 ; 0x1000 + 296dc: 68db ldr r3, [r3, #12] + 296de: b103 cbz r3, 296e2 <__rtl_lseek_v1_00+0xe> + 296e0: 4718 bx r3 + 296e2: f04f 30ff mov.w r0, #4294967295 + 296e6: 4770 bx lr + +000296e8 <__rtl_open_v1_00>: + 296e8: f240 7360 movw r3, #1888 ; 0x760 + 296ec: f2c1 0300 movt r3, #4096 ; 0x1000 + 296f0: 691b ldr r3, [r3, #16] + 296f2: b103 cbz r3, 296f6 <__rtl_open_v1_00+0xe> + 296f4: 4718 bx r3 + 296f6: f04f 30ff mov.w r0, #4294967295 + 296fa: 4770 bx lr + +000296fc <__rtl_read_v1_00>: + 296fc: f240 7360 movw r3, #1888 ; 0x760 + 29700: f2c1 0300 movt r3, #4096 ; 0x1000 + 29704: 695b ldr r3, [r3, #20] + 29706: b103 cbz r3, 2970a <__rtl_read_v1_00+0xe> + 29708: 4718 bx r3 + 2970a: f04f 30ff mov.w r0, #4294967295 + 2970e: 4770 bx lr + +00029710 <__rtl_write_v1_00>: + 29710: f240 7360 movw r3, #1888 ; 0x760 + 29714: f2c1 0300 movt r3, #4096 ; 0x1000 + 29718: 699b ldr r3, [r3, #24] + 2971a: b103 cbz r3, 2971e <__rtl_write_v1_00+0xe> + 2971c: 4718 bx r3 + 2971e: f04f 30ff mov.w r0, #4294967295 + 29722: 4770 bx lr + +00029724 <__rtl_sbrk_v1_00>: + 29724: f240 7360 movw r3, #1888 ; 0x760 + 29728: f2c1 0300 movt r3, #4096 ; 0x1000 + 2972c: 69db ldr r3, [r3, #28] + 2972e: b103 cbz r3, 29732 <__rtl_sbrk_v1_00+0xe> + 29730: 4718 bx r3 + 29732: 4618 mov r0, r3 + 29734: 4770 bx lr + 29736: bf00 nop + +00029738 <__rtl_div64_32>: + 29738: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} + 2973c: e9d0 6700 ldrd r6, r7, [r0] + 29740: 428f cmp r7, r1 + 29742: 460a mov r2, r1 + 29744: f04f 0300 mov.w r3, #0 + 29748: d30b bcc.n 29762 <__rtl_div64_32+0x2a> + 2974a: fbb7 fef1 udiv lr, r7, r1 + 2974e: fb01 f50e mul.w r5, r1, lr + 29752: f04f 0800 mov.w r8, #0 + 29756: ebb6 0608 subs.w r6, r6, r8 + 2975a: 46f1 mov r9, lr + 2975c: eb67 0705 sbc.w r7, r7, r5 + 29760: e003 b.n 2976a <__rtl_div64_32+0x32> + 29762: f04f 0800 mov.w r8, #0 + 29766: f04f 0900 mov.w r9, #0 + 2976a: 2401 movs r4, #1 + 2976c: 2500 movs r5, #0 + 2976e: 2a01 cmp r2, #1 + 29770: f173 0100 sbcs.w r1, r3, #0 + 29774: db08 blt.n 29788 <__rtl_div64_32+0x50> + 29776: 42bb cmp r3, r7 + 29778: bf08 it eq + 2977a: 42b2 cmpeq r2, r6 + 2977c: d204 bcs.n 29788 <__rtl_div64_32+0x50> + 2977e: 1892 adds r2, r2, r2 + 29780: 415b adcs r3, r3 + 29782: 1924 adds r4, r4, r4 + 29784: 416d adcs r5, r5 + 29786: e7f2 b.n 2976e <__rtl_div64_32+0x36> + 29788: 429f cmp r7, r3 + 2978a: bf08 it eq + 2978c: 4296 cmpeq r6, r2 + 2978e: d306 bcc.n 2979e <__rtl_div64_32+0x66> + 29790: 1ab6 subs r6, r6, r2 + 29792: eb67 0703 sbc.w r7, r7, r3 + 29796: eb18 0804 adds.w r8, r8, r4 + 2979a: eb49 0905 adc.w r9, r9, r5 + 2979e: 086d lsrs r5, r5, #1 + 297a0: ea4f 0434 mov.w r4, r4, rrx + 297a4: 085b lsrs r3, r3, #1 + 297a6: ea4f 0232 mov.w r2, r2, rrx + 297aa: ea54 0105 orrs.w r1, r4, r5 + 297ae: d1eb bne.n 29788 <__rtl_div64_32+0x50> + 297b0: e9c0 8900 strd r8, r9, [r0] + 297b4: 4630 mov r0, r6 + 297b6: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + 297ba: bf00 nop + +000297bc <__rtl_ltoa_v1_00>: + 297bc: 2900 cmp r1, #0 + 297be: d046 beq.n 2984e <__rtl_ltoa_v1_00+0x92> + 297c0: 1e93 subs r3, r2, #2 + 297c2: 2b22 cmp r3, #34 ; 0x22 + 297c4: d841 bhi.n 2984a <__rtl_ltoa_v1_00+0x8e> + 297c6: b5f0 push {r4, r5, r6, r7, lr} + 297c8: ea4f 7ed0 mov.w lr, r0, lsr #31 + 297cc: 2a0a cmp r2, #10 + 297ce: bf14 ite ne + 297d0: f04f 0e00 movne.w lr, #0 + 297d4: f00e 0e01 andeq.w lr, lr, #1 + 297d8: b08b sub sp, #44 ; 0x2c + 297da: 4604 mov r4, r0 + 297dc: f1be 0f00 cmp.w lr, #0 + 297e0: d000 beq.n 297e4 <__rtl_ltoa_v1_00+0x28> + 297e2: 4244 negs r4, r0 + 297e4: af01 add r7, sp, #4 + 297e6: 463b mov r3, r7 + 297e8: b93c cbnz r4, 297fa <__rtl_ltoa_v1_00+0x3e> + 297ea: 42bb cmp r3, r7 + 297ec: d112 bne.n 29814 <__rtl_ltoa_v1_00+0x58> + 297ee: 4625 mov r5, r4 + 297f0: 3530 adds r5, #48 ; 0x30 + 297f2: 701d strb r5, [r3, #0] + 297f4: 3301 adds r3, #1 + 297f6: 2c00 cmp r4, #0 + 297f8: d0f7 beq.n 297ea <__rtl_ltoa_v1_00+0x2e> + 297fa: fbb4 f6f2 udiv r6, r4, r2 + 297fe: fb02 4516 mls r5, r2, r6, r4 + 29802: 2d09 cmp r5, #9 + 29804: bfc4 itt gt + 29806: 3557 addgt r5, #87 ; 0x57 + 29808: 701d strbgt r5, [r3, #0] + 2980a: 4634 mov r4, r6 + 2980c: bfc8 it gt + 2980e: 3301 addgt r3, #1 + 29810: dcea bgt.n 297e8 <__rtl_ltoa_v1_00+0x2c> + 29812: e7ed b.n 297f0 <__rtl_ltoa_v1_00+0x34> + 29814: 460e mov r6, r1 + 29816: f1be 0f00 cmp.w lr, #0 + 2981a: d112 bne.n 29842 <__rtl_ltoa_v1_00+0x86> + 2981c: 42bb cmp r3, r7 + 2981e: d90b bls.n 29838 <__rtl_ltoa_v1_00+0x7c> + 29820: 461c mov r4, r3 + 29822: 4632 mov r2, r6 + 29824: 1bd8 subs r0, r3, r7 + 29826: 4430 add r0, r6 + 29828: f814 5d01 ldrb.w r5, [r4, #-1]! + 2982c: f802 5b01 strb.w r5, [r2], #1 + 29830: 4282 cmp r2, r0 + 29832: d1f9 bne.n 29828 <__rtl_ltoa_v1_00+0x6c> + 29834: 1bdb subs r3, r3, r7 + 29836: 441e add r6, r3 + 29838: 4608 mov r0, r1 + 2983a: 2300 movs r3, #0 + 2983c: 7033 strb r3, [r6, #0] + 2983e: b00b add sp, #44 ; 0x2c + 29840: bdf0 pop {r4, r5, r6, r7, pc} + 29842: 222d movs r2, #45 ; 0x2d + 29844: 700a strb r2, [r1, #0] + 29846: 1c4e adds r6, r1, #1 + 29848: e7e8 b.n 2981c <__rtl_ltoa_v1_00+0x60> + 2984a: 2000 movs r0, #0 + 2984c: 4770 bx lr + 2984e: 4608 mov r0, r1 + 29850: 4770 bx lr + 29852: bf00 nop + +00029854 <__rtl_ultoa_v1_00>: + 29854: b399 cbz r1, 298be <__rtl_ultoa_v1_00+0x6a> + 29856: 1e93 subs r3, r2, #2 + 29858: 2b22 cmp r3, #34 ; 0x22 + 2985a: d82c bhi.n 298b6 <__rtl_ultoa_v1_00+0x62> + 2985c: b470 push {r4, r5, r6} + 2985e: b08b sub sp, #44 ; 0x2c + 29860: ae01 add r6, sp, #4 + 29862: 4633 mov r3, r6 + 29864: b938 cbnz r0, 29876 <__rtl_ultoa_v1_00+0x22> + 29866: 42b3 cmp r3, r6 + 29868: d112 bne.n 29890 <__rtl_ultoa_v1_00+0x3c> + 2986a: 4604 mov r4, r0 + 2986c: 3430 adds r4, #48 ; 0x30 + 2986e: 701c strb r4, [r3, #0] + 29870: 3301 adds r3, #1 + 29872: 2800 cmp r0, #0 + 29874: d0f7 beq.n 29866 <__rtl_ultoa_v1_00+0x12> + 29876: fbb0 f5f2 udiv r5, r0, r2 + 2987a: fb02 0415 mls r4, r2, r5, r0 + 2987e: 2c09 cmp r4, #9 + 29880: bfc4 itt gt + 29882: 3457 addgt r4, #87 ; 0x57 + 29884: 701c strbgt r4, [r3, #0] + 29886: 4628 mov r0, r5 + 29888: bfc8 it gt + 2988a: 3301 addgt r3, #1 + 2988c: dcea bgt.n 29864 <__rtl_ultoa_v1_00+0x10> + 2988e: e7ed b.n 2986c <__rtl_ultoa_v1_00+0x18> + 29890: d913 bls.n 298ba <__rtl_ultoa_v1_00+0x66> + 29892: 461c mov r4, r3 + 29894: 460a mov r2, r1 + 29896: 1b98 subs r0, r3, r6 + 29898: 4408 add r0, r1 + 2989a: f814 5d01 ldrb.w r5, [r4, #-1]! + 2989e: f802 5b01 strb.w r5, [r2], #1 + 298a2: 4282 cmp r2, r0 + 298a4: d1f9 bne.n 2989a <__rtl_ultoa_v1_00+0x46> + 298a6: 1b9b subs r3, r3, r6 + 298a8: 440b add r3, r1 + 298aa: 4608 mov r0, r1 + 298ac: 2200 movs r2, #0 + 298ae: 701a strb r2, [r3, #0] + 298b0: b00b add sp, #44 ; 0x2c + 298b2: bc70 pop {r4, r5, r6} + 298b4: 4770 bx lr + 298b6: 2000 movs r0, #0 + 298b8: 4770 bx lr + 298ba: 460b mov r3, r1 + 298bc: e7f5 b.n 298aa <__rtl_ultoa_v1_00+0x56> + 298be: 4608 mov r0, r1 + 298c0: 4770 bx lr + 298c2: bf00 nop + +000298c4 <__rtl_dtoi_v1_00>: + 298c4: f64f 73ff movw r3, #65535 ; 0xffff + 298c8: f2c0 030f movt r3, #15 + 298cc: b470 push {r4, r5, r6} + 298ce: f3c1 550a ubfx r5, r1, #20, #11 + 298d2: f5c5 6486 rsb r4, r5, #1072 ; 0x430 + 298d6: 3403 adds r4, #3 + 298d8: 0fce lsrs r6, r1, #31 + 298da: f04f 32ff mov.w r2, #4294967295 + 298de: 2c14 cmp r4, #20 + 298e0: ea01 0103 and.w r1, r1, r3 + 298e4: ea00 0002 and.w r0, r0, r2 + 298e8: b2f3 uxtb r3, r6 + 298ea: dc10 bgt.n 2990e <__rtl_dtoi_v1_00+0x4a> + 298ec: ea50 0201 orrs.w r2, r0, r1 + 298f0: f240 71ff movw r1, #2047 ; 0x7ff + 298f4: bf14 ite ne + 298f6: 2201 movne r2, #1 + 298f8: 2200 moveq r2, #0 + 298fa: 428d cmp r5, r1 + 298fc: bf14 ite ne + 298fe: 2500 movne r5, #0 + 29900: f002 0501 andeq.w r5, r2, #1 + 29904: b1c5 cbz r5, 29938 <__rtl_dtoi_v1_00+0x74> + 29906: f06f 4000 mvn.w r0, #2147483648 ; 0x80000000 + 2990a: bc70 pop {r4, r5, r6} + 2990c: 4770 bx lr + 2990e: 2c34 cmp r4, #52 ; 0x34 + 29910: bfc8 it gt + 29912: 2000 movgt r0, #0 + 29914: dcf9 bgt.n 2990a <__rtl_dtoi_v1_00+0x46> + 29916: f441 1180 orr.w r1, r1, #1048576 ; 0x100000 + 2991a: f1c4 0220 rsb r2, r4, #32 + 2991e: 40e0 lsrs r0, r4 + 29920: fa01 f202 lsl.w r2, r1, r2 + 29924: 3c20 subs r4, #32 + 29926: 4310 orrs r0, r2 + 29928: fa21 f404 lsr.w r4, r1, r4 + 2992c: 4320 orrs r0, r4 + 2992e: b103 cbz r3, 29932 <__rtl_dtoi_v1_00+0x6e> + 29930: 4240 negs r0, r0 + 29932: ebb6 7fd0 cmp.w r6, r0, lsr #31 + 29936: d0e8 beq.n 2990a <__rtl_dtoi_v1_00+0x46> + 29938: f04f 4000 mov.w r0, #2147483648 ; 0x80000000 + 2993c: 2b00 cmp r3, #0 + 2993e: d0e2 beq.n 29906 <__rtl_dtoi_v1_00+0x42> + 29940: bc70 pop {r4, r5, r6} + 29942: 4770 bx lr + +00029944 <__rtl_dtoi64_v1_00>: + 29944: f64f 73ff movw r3, #65535 ; 0xffff + 29948: f2c0 030f movt r3, #15 + 2994c: b4f0 push {r4, r5, r6, r7} + 2994e: f3c1 550a ubfx r5, r1, #20, #11 + 29952: f5c5 6486 rsb r4, r5, #1072 ; 0x430 + 29956: 3403 adds r4, #3 + 29958: 0fce lsrs r6, r1, #31 + 2995a: f04f 32ff mov.w r2, #4294967295 + 2995e: 2c14 cmp r4, #20 + 29960: ea00 0002 and.w r0, r0, r2 + 29964: ea01 0103 and.w r1, r1, r3 + 29968: b2f7 uxtb r7, r6 + 2996a: dc11 bgt.n 29990 <__rtl_dtoi64_v1_00+0x4c> + 2996c: f240 72ff movw r2, #2047 ; 0x7ff + 29970: ea50 0301 orrs.w r3, r0, r1 + 29974: bf14 ite ne + 29976: 2301 movne r3, #1 + 29978: 2300 moveq r3, #0 + 2997a: 4295 cmp r5, r2 + 2997c: bf14 ite ne + 2997e: 2500 movne r5, #0 + 29980: f003 0501 andeq.w r5, r3, #1 + 29984: b305 cbz r5, 299c8 <__rtl_dtoi64_v1_00+0x84> + 29986: f04f 30ff mov.w r0, #4294967295 + 2998a: 4601 mov r1, r0 + 2998c: bcf0 pop {r4, r5, r6, r7} + 2998e: 4770 bx lr + 29990: 2c34 cmp r4, #52 ; 0x34 + 29992: bfc4 itt gt + 29994: 2000 movgt r0, #0 + 29996: 4601 movgt r1, r0 + 29998: dcf8 bgt.n 2998c <__rtl_dtoi64_v1_00+0x48> + 2999a: f441 1180 orr.w r1, r1, #1048576 ; 0x100000 + 2999e: f1c4 0520 rsb r5, r4, #32 + 299a2: fa20 f204 lsr.w r2, r0, r4 + 299a6: fa01 f505 lsl.w r5, r1, r5 + 299aa: f1a4 0020 sub.w r0, r4, #32 + 299ae: 432a orrs r2, r5 + 299b0: fa21 f000 lsr.w r0, r1, r0 + 299b4: 4302 orrs r2, r0 + 299b6: fa21 f304 lsr.w r3, r1, r4 + 299ba: b117 cbz r7, 299c2 <__rtl_dtoi64_v1_00+0x7e> + 299bc: 4252 negs r2, r2 + 299be: eb63 0343 sbc.w r3, r3, r3, lsl #1 + 299c2: ebb6 7fd3 cmp.w r6, r3, lsr #31 + 299c6: d006 beq.n 299d6 <__rtl_dtoi64_v1_00+0x92> + 299c8: 2000 movs r0, #0 + 299ca: f04f 4100 mov.w r1, #2147483648 ; 0x80000000 + 299ce: 2f00 cmp r7, #0 + 299d0: d0d9 beq.n 29986 <__rtl_dtoi64_v1_00+0x42> + 299d2: bcf0 pop {r4, r5, r6, r7} + 299d4: 4770 bx lr + 299d6: 4610 mov r0, r2 + 299d8: 4619 mov r1, r3 + 299da: e7d7 b.n 2998c <__rtl_dtoi64_v1_00+0x48> + +000299dc <__rtl_dtoui_v1_00>: + 299dc: b508 push {r3, lr} + 299de: f7ff ffb1 bl 29944 <__rtl_dtoi64_v1_00> + 299e2: bd08 pop {r3, pc} + +000299e4 <__rtl_ftol_v1_00>: + 299e4: f3c0 53c7 ubfx r3, r0, #23, #8 + 299e8: b410 push {r4} + 299ea: f1b3 049e subs.w r4, r3, #158 ; 0x9e + 299ee: f3c0 0116 ubfx r1, r0, #0, #23 + 299f2: ea4f 72d0 mov.w r2, r0, lsr #31 + 299f6: d41a bmi.n 29a2e <__rtl_ftol_v1_00+0x4a> + 299f8: f1b0 4f4f cmp.w r0, #3472883712 ; 0xcf000000 + 299fc: d024 beq.n 29a48 <__rtl_ftol_v1_00+0x64> + 299fe: b922 cbnz r2, 29a0a <__rtl_ftol_v1_00+0x26> + 29a00: f06f 4000 mvn.w r0, #2147483648 ; 0x80000000 + 29a04: f85d 4b04 ldr.w r4, [sp], #4 + 29a08: 4770 bx lr + 29a0a: f1a3 03ff sub.w r3, r3, #255 ; 0xff + 29a0e: fab3 f383 clz r3, r3 + 29a12: 2900 cmp r1, #0 + 29a14: ea4f 1353 mov.w r3, r3, lsr #5 + 29a18: bf08 it eq + 29a1a: 2300 moveq r3, #0 + 29a1c: 2b00 cmp r3, #0 + 29a1e: bf0c ite eq + 29a20: f04f 4000 moveq.w r0, #2147483648 ; 0x80000000 + 29a24: f06f 4000 mvnne.w r0, #2147483648 ; 0x80000000 + 29a28: f85d 4b04 ldr.w r4, [sp], #4 + 29a2c: 4770 bx lr + 29a2e: 2b7e cmp r3, #126 ; 0x7e + 29a30: bfd8 it le + 29a32: 2000 movle r0, #0 + 29a34: dde6 ble.n 29a04 <__rtl_ftol_v1_00+0x20> + 29a36: f441 0000 orr.w r0, r1, #8388608 ; 0x800000 + 29a3a: 0200 lsls r0, r0, #8 + 29a3c: 4264 negs r4, r4 + 29a3e: 40e0 lsrs r0, r4 + 29a40: 2a00 cmp r2, #0 + 29a42: d0df beq.n 29a04 <__rtl_ftol_v1_00+0x20> + 29a44: 4240 negs r0, r0 + 29a46: e7dd b.n 29a04 <__rtl_ftol_v1_00+0x20> + 29a48: f04f 4000 mov.w r0, #2147483648 ; 0x80000000 + 29a4c: e7da b.n 29a04 <__rtl_ftol_v1_00+0x20> + 29a4e: bf00 nop + +00029a50 <__rtl_itof_v1_00>: + 29a50: 2800 cmp r0, #0 + 29a52: d042 beq.n 29ada <__rtl_itof_v1_00+0x8a> + 29a54: f1b0 4f00 cmp.w r0, #2147483648 ; 0x80000000 + 29a58: d03c beq.n 29ad4 <__rtl_itof_v1_00+0x84> + 29a5a: f241 52a0 movw r2, #5536 ; 0x15a0 + 29a5e: b410 push {r4} + 29a60: 0fc4 lsrs r4, r0, #31 + 29a62: bf18 it ne + 29a64: 4240 negne r0, r0 + 29a66: f5b0 3f80 cmp.w r0, #65536 ; 0x10000 + 29a6a: bf28 it cs + 29a6c: 4603 movcs r3, r0 + 29a6e: f2c0 0203 movt r2, #3 + 29a72: bf3a itte cc + 29a74: 0403 lslcc r3, r0, #16 + 29a76: 2110 movcc r1, #16 + 29a78: 2100 movcs r1, #0 + 29a7a: f1b3 7f80 cmp.w r3, #16777216 ; 0x1000000 + 29a7e: bf3c itt cc + 29a80: 021b lslcc r3, r3, #8 + 29a82: 3108 addcc r1, #8 + 29a84: ea4f 6313 mov.w r3, r3, lsr #24 + 29a88: 5cd3 ldrb r3, [r2, r3] + 29a8a: bf38 it cc + 29a8c: b2c9 uxtbcc r1, r1 + 29a8e: 3901 subs r1, #1 + 29a90: 4419 add r1, r3 + 29a92: b2c9 uxtb r1, r1 + 29a94: f1c1 029c rsb r2, r1, #156 ; 0x9c + 29a98: b292 uxth r2, r2 + 29a9a: b293 uxth r3, r2 + 29a9c: 4088 lsls r0, r1 + 29a9e: 0419 lsls r1, r3, #16 + 29aa0: d50e bpl.n 29ac0 <__rtl_itof_v1_00+0x70> + 29aa2: 4252 negs r2, r2 + 29aa4: b212 sxth r2, r2 + 29aa6: 2a1f cmp r2, #31 + 29aa8: dc19 bgt.n 29ade <__rtl_itof_v1_00+0x8e> + 29aaa: 4253 negs r3, r2 + 29aac: f003 031f and.w r3, r3, #31 + 29ab0: fa10 f303 lsls.w r3, r0, r3 + 29ab4: fa20 f002 lsr.w r0, r0, r2 + 29ab8: bf18 it ne + 29aba: f040 0001 orrne.w r0, r0, #1 + 29abe: 2300 movs r3, #0 + 29ac0: 09c0 lsrs r0, r0, #7 + 29ac2: bf0c ite eq + 29ac4: 4603 moveq r3, r0 + 29ac6: 05db lslne r3, r3, #23 + 29ac8: eba0 70c4 sub.w r0, r0, r4, lsl #31 + 29acc: 4418 add r0, r3 + 29ace: f85d 4b04 ldr.w r4, [sp], #4 + 29ad2: 4770 bx lr + 29ad4: f04f 404f mov.w r0, #3472883712 ; 0xcf000000 + 29ad8: 4770 bx lr + 29ada: 2000 movs r0, #0 + 29adc: 4770 bx lr + 29ade: 3000 adds r0, #0 + 29ae0: bf18 it ne + 29ae2: 2001 movne r0, #1 + 29ae4: 2300 movs r3, #0 + 29ae6: e7eb b.n 29ac0 <__rtl_itof_v1_00+0x70> + +00029ae8 <__rtl_itod_v1_00>: + 29ae8: 2800 cmp r0, #0 + 29aea: d042 beq.n 29b72 <__rtl_itod_v1_00+0x8a> + 29aec: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} + 29af0: f241 5ea0 movw lr, #5536 ; 0x15a0 + 29af4: ea5f 79d0 movs.w r9, r0, lsr #31 + 29af8: bf18 it ne + 29afa: 4240 negne r0, r0 + 29afc: f5b0 3f80 cmp.w r0, #65536 ; 0x10000 + 29b00: bf28 it cs + 29b02: 4684 movcs ip, r0 + 29b04: f2c0 0e03 movt lr, #3 + 29b08: bf3a itte cc + 29b0a: ea4f 4c00 movcc.w ip, r0, lsl #16 + 29b0e: f04f 0810 movcc.w r8, #16 + 29b12: f04f 0800 movcs.w r8, #0 + 29b16: f1bc 7f80 cmp.w ip, #16777216 ; 0x1000000 + 29b1a: bf3c itt cc + 29b1c: ea4f 2c0c movcc.w ip, ip, lsl #8 + 29b20: f108 0808 addcc.w r8, r8, #8 + 29b24: ea4f 6c1c mov.w ip, ip, lsr #24 + 29b28: f81e e00c ldrb.w lr, [lr, ip] + 29b2c: bf38 it cc + 29b2e: fa5f f888 uxtbcc.w r8, r8 + 29b32: f108 0115 add.w r1, r8, #21 + 29b36: 4471 add r1, lr + 29b38: b2c9 uxtb r1, r1 + 29b3a: f1a1 0c20 sub.w ip, r1, #32 + 29b3e: f1c1 0e20 rsb lr, r1, #32 + 29b42: fa00 f30c lsl.w r3, r0, ip + 29b46: fa20 fe0e lsr.w lr, r0, lr + 29b4a: f5c1 6c86 rsb ip, r1, #1072 ; 0x430 + 29b4e: fa00 f201 lsl.w r2, r0, r1 + 29b52: 2400 movs r4, #0 + 29b54: 1912 adds r2, r2, r4 + 29b56: ea43 030e orr.w r3, r3, lr + 29b5a: ea4f 75c9 mov.w r5, r9, lsl #31 + 29b5e: f10c 0e02 add.w lr, ip, #2 + 29b62: 416b adcs r3, r5 + 29b64: ea4f 570e mov.w r7, lr, lsl #20 + 29b68: 1910 adds r0, r2, r4 + 29b6a: eb43 0107 adc.w r1, r3, r7 + 29b6e: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + 29b72: 2000 movs r0, #0 + 29b74: 2100 movs r1, #0 + 29b76: 4770 bx lr + +00029b78 <__rtl_i64tod_v1_00>: + 29b78: ea50 0301 orrs.w r3, r0, r1 + 29b7c: d05a beq.n 29c34 <__rtl_i64tod_v1_00+0xbc> + 29b7e: f1b1 4f00 cmp.w r1, #2147483648 ; 0x80000000 + 29b82: bf08 it eq + 29b84: 2800 cmpeq r0, #0 + 29b86: d058 beq.n 29c3a <__rtl_i64tod_v1_00+0xc2> + 29b88: 2800 cmp r0, #0 + 29b8a: f171 0300 sbcs.w r3, r1, #0 + 29b8e: b5f0 push {r4, r5, r6, r7, lr} + 29b90: bfa4 itt ge + 29b92: 2600 movge r6, #0 + 29b94: 2700 movge r7, #0 + 29b96: db55 blt.n 29c44 <__rtl_i64tod_v1_00+0xcc> + 29b98: f241 55a0 movw r5, #5536 ; 0x15a0 + 29b9c: 2901 cmp r1, #1 + 29b9e: bf08 it eq + 29ba0: 2800 cmpeq r0, #0 + 29ba2: bf2c ite cs + 29ba4: 460c movcs r4, r1 + 29ba6: 4604 movcc r4, r0 + 29ba8: f2c0 0503 movt r5, #3 + 29bac: bf2c ite cs + 29bae: f04f 0eff movcs.w lr, #255 ; 0xff + 29bb2: f04f 0e1f movcc.w lr, #31 + 29bb6: f5b4 3f80 cmp.w r4, #65536 ; 0x10000 + 29bba: bf3a itte cc + 29bbc: 0424 lslcc r4, r4, #16 + 29bbe: f04f 0c10 movcc.w ip, #16 + 29bc2: f04f 0c00 movcs.w ip, #0 + 29bc6: f1b4 7f80 cmp.w r4, #16777216 ; 0x1000000 + 29bca: bf3c itt cc + 29bcc: 0224 lslcc r4, r4, #8 + 29bce: f10c 0c08 addcc.w ip, ip, #8 + 29bd2: ea4f 6414 mov.w r4, r4, lsr #24 + 29bd6: 5d2c ldrb r4, [r5, r4] + 29bd8: bf38 it cc + 29bda: fa5f fc8c uxtbcc.w ip, ip + 29bde: 44e6 add lr, ip + 29be0: 44a6 add lr, r4 + 29be2: fa5f fe8e uxtb.w lr, lr + 29be6: f1ae 0520 sub.w r5, lr, #32 + 29bea: fa00 f505 lsl.w r5, r0, r5 + 29bee: fa01 f10e lsl.w r1, r1, lr + 29bf2: f1ce 0420 rsb r4, lr, #32 + 29bf6: fa20 f404 lsr.w r4, r0, r4 + 29bfa: 4329 orrs r1, r5 + 29bfc: fa00 f00e lsl.w r0, r0, lr + 29c00: 4321 orrs r1, r4 + 29c02: 0a82 lsrs r2, r0, #10 + 29c04: ea42 5281 orr.w r2, r2, r1, lsl #22 + 29c08: 0a8b lsrs r3, r1, #10 + 29c0a: ea52 0103 orrs.w r1, r2, r3 + 29c0e: bf07 ittee eq + 29c10: 4614 moveq r4, r2 + 29c12: 461d moveq r5, r3 + 29c14: f5ce 6e87 rsbne lr, lr, #1080 ; 0x438 + 29c18: f10e 0e04 addne.w lr, lr, #4 + 29c1c: bf1f itttt ne + 29c1e: 2400 movne r4, #0 + 29c20: 2500 movne r5, #0 + 29c22: 2400 movne r4, #0 + 29c24: ea4f 550e movne.w r5, lr, lsl #20 + 29c28: 1992 adds r2, r2, r6 + 29c2a: 417b adcs r3, r7 + 29c2c: 1910 adds r0, r2, r4 + 29c2e: eb43 0105 adc.w r1, r3, r5 + 29c32: bdf0 pop {r4, r5, r6, r7, pc} + 29c34: 2000 movs r0, #0 + 29c36: 2100 movs r1, #0 + 29c38: 4770 bx lr + 29c3a: 2100 movs r1, #0 + 29c3c: 2000 movs r0, #0 + 29c3e: f2cc 31e0 movt r1, #50144 ; 0xc3e0 + 29c42: 4770 bx lr + 29c44: 4240 negs r0, r0 + 29c46: eb61 0141 sbc.w r1, r1, r1, lsl #1 + 29c4a: 2600 movs r6, #0 + 29c4c: f04f 4700 mov.w r7, #2147483648 ; 0x80000000 + 29c50: e7a2 b.n 29b98 <__rtl_i64tod_v1_00+0x20> + 29c52: bf00 nop + +00029c54 <__rtl_uitod_v1_00>: + 29c54: 4602 mov r2, r0 + 29c56: 2300 movs r3, #0 + 29c58: ea52 0103 orrs.w r1, r2, r3 + 29c5c: d05b beq.n 29d16 <__rtl_uitod_v1_00+0xc2> + 29c5e: f1b3 4f00 cmp.w r3, #2147483648 ; 0x80000000 + 29c62: bf08 it eq + 29c64: 2800 cmpeq r0, #0 + 29c66: d051 beq.n 29d0c <__rtl_uitod_v1_00+0xb8> + 29c68: 2800 cmp r0, #0 + 29c6a: f173 0100 sbcs.w r1, r3, #0 + 29c6e: b5f0 push {r4, r5, r6, r7, lr} + 29c70: bfa4 itt ge + 29c72: 2000 movge r0, #0 + 29c74: 2100 movge r1, #0 + 29c76: db51 blt.n 29d1c <__rtl_uitod_v1_00+0xc8> + 29c78: f241 57a0 movw r7, #5536 ; 0x15a0 + 29c7c: 2b01 cmp r3, #1 + 29c7e: bf08 it eq + 29c80: 2a00 cmpeq r2, #0 + 29c82: bf2c ite cs + 29c84: 461e movcs r6, r3 + 29c86: 4616 movcc r6, r2 + 29c88: f2c0 0703 movt r7, #3 + 29c8c: bf2c ite cs + 29c8e: f04f 0cff movcs.w ip, #255 ; 0xff + 29c92: f04f 0c1f movcc.w ip, #31 + 29c96: f5b6 3f80 cmp.w r6, #65536 ; 0x10000 + 29c9a: bf3a itte cc + 29c9c: 0436 lslcc r6, r6, #16 + 29c9e: f04f 0e10 movcc.w lr, #16 + 29ca2: f04f 0e00 movcs.w lr, #0 + 29ca6: f1b6 7f80 cmp.w r6, #16777216 ; 0x1000000 + 29caa: bf3c itt cc + 29cac: 0236 lslcc r6, r6, #8 + 29cae: f10e 0e08 addcc.w lr, lr, #8 + 29cb2: ea4f 6616 mov.w r6, r6, lsr #24 + 29cb6: bf38 it cc + 29cb8: fa5f fe8e uxtbcc.w lr, lr + 29cbc: 5dbf ldrb r7, [r7, r6] + 29cbe: eb0e 060c add.w r6, lr, ip + 29cc2: 443e add r6, r7 + 29cc4: b2f6 uxtb r6, r6 + 29cc6: f1a6 0e20 sub.w lr, r6, #32 + 29cca: 40b3 lsls r3, r6 + 29ccc: f1c6 0720 rsb r7, r6, #32 + 29cd0: fa02 fe0e lsl.w lr, r2, lr + 29cd4: fa22 f707 lsr.w r7, r2, r7 + 29cd8: ea43 030e orr.w r3, r3, lr + 29cdc: 40b2 lsls r2, r6 + 29cde: 433b orrs r3, r7 + 29ce0: 0a94 lsrs r4, r2, #10 + 29ce2: ea44 5483 orr.w r4, r4, r3, lsl #22 + 29ce6: 0a9d lsrs r5, r3, #10 + 29ce8: ea54 0305 orrs.w r3, r4, r5 + 29cec: bf07 ittee eq + 29cee: 4622 moveq r2, r4 + 29cf0: 462b moveq r3, r5 + 29cf2: f5c6 6687 rsbne r6, r6, #1080 ; 0x438 + 29cf6: 3604 addne r6, #4 + 29cf8: bf1f itttt ne + 29cfa: 2200 movne r2, #0 + 29cfc: 2300 movne r3, #0 + 29cfe: 2200 movne r2, #0 + 29d00: 0533 lslne r3, r6, #20 + 29d02: 1900 adds r0, r0, r4 + 29d04: 4169 adcs r1, r5 + 29d06: 1880 adds r0, r0, r2 + 29d08: 4159 adcs r1, r3 + 29d0a: bdf0 pop {r4, r5, r6, r7, pc} + 29d0c: 2100 movs r1, #0 + 29d0e: 2000 movs r0, #0 + 29d10: f2cc 31e0 movt r1, #50144 ; 0xc3e0 + 29d14: 4770 bx lr + 29d16: 2000 movs r0, #0 + 29d18: 2100 movs r1, #0 + 29d1a: 4770 bx lr + 29d1c: 4252 negs r2, r2 + 29d1e: eb63 0343 sbc.w r3, r3, r3, lsl #1 + 29d22: 2000 movs r0, #0 + 29d24: f04f 4100 mov.w r1, #2147483648 ; 0x80000000 + 29d28: e7a6 b.n 29c78 <__rtl_uitod_v1_00+0x24> + 29d2a: bf00 nop + +00029d2c <__rtl_ftod_v1_00>: + 29d2c: b5f0 push {r4, r5, r6, r7, lr} + 29d2e: f3c0 5ec7 ubfx lr, r0, #23, #8 + 29d32: f1be 0fff cmp.w lr, #255 ; 0xff + 29d36: f3c0 0716 ubfx r7, r0, #0, #23 + 29d3a: ea4f 76d0 mov.w r6, r0, lsr #31 + 29d3e: d025 beq.n 29d8c <__rtl_ftod_v1_00+0x60> + 29d40: f1be 0f00 cmp.w lr, #0 + 29d44: d113 bne.n 29d6e <__rtl_ftod_v1_00+0x42> + 29d46: 2f00 cmp r7, #0 + 29d48: d048 beq.n 29ddc <__rtl_ftod_v1_00+0xb0> + 29d4a: f5b7 3f80 cmp.w r7, #65536 ; 0x10000 + 29d4e: d33b bcc.n 29dc8 <__rtl_ftod_v1_00+0x9c> + 29d50: 463a mov r2, r7 + 29d52: 0212 lsls r2, r2, #8 + 29d54: f241 53a0 movw r3, #5536 ; 0x15a0 + 29d58: f2c0 0303 movt r3, #3 + 29d5c: 0e12 lsrs r2, r2, #24 + 29d5e: 5c9b ldrb r3, [r3, r2] + 29d60: 4473 add r3, lr + 29d62: b2db uxtb r3, r3 + 29d64: f1c3 0e00 rsb lr, r3, #0 + 29d68: 409f lsls r7, r3 + 29d6a: fa1f fe8e uxth.w lr, lr + 29d6e: 2200 movs r2, #0 + 29d70: 077c lsls r4, r7, #29 + 29d72: 18a4 adds r4, r4, r2 + 29d74: f50e 7e60 add.w lr, lr, #896 ; 0x380 + 29d78: ea4f 05d7 mov.w r5, r7, lsr #3 + 29d7c: ea4f 73c6 mov.w r3, r6, lsl #31 + 29d80: 415d adcs r5, r3 + 29d82: ea4f 510e mov.w r1, lr, lsl #20 + 29d86: 1910 adds r0, r2, r4 + 29d88: 4169 adcs r1, r5 + 29d8a: bdf0 pop {r4, r5, r6, r7, pc} + 29d8c: b1a7 cbz r7, 29db8 <__rtl_ftod_v1_00+0x8c> + 29d8e: 0742 lsls r2, r0, #29 + 29d90: f3c0 03d3 ubfx r3, r0, #3, #20 + 29d94: ea52 0103 orrs.w r1, r2, r3 + 29d98: f04f 0000 mov.w r0, #0 + 29d9c: f04f 0100 mov.w r1, #0 + 29da0: d01f beq.n 29de2 <__rtl_ftod_v1_00+0xb6> + 29da2: 2500 movs r5, #0 + 29da4: f6c7 75f0 movt r5, #32752 ; 0x7ff0 + 29da8: 07f1 lsls r1, r6, #31 + 29daa: 2000 movs r0, #0 + 29dac: 4310 orrs r0, r2 + 29dae: 4319 orrs r1, r3 + 29db0: 2400 movs r4, #0 + 29db2: 4320 orrs r0, r4 + 29db4: 4329 orrs r1, r5 + 29db6: bdf0 pop {r4, r5, r6, r7, pc} + 29db8: 2100 movs r1, #0 + 29dba: f6c7 71f0 movt r1, #32752 ; 0x7ff0 + 29dbe: 2000 movs r0, #0 + 29dc0: 07f3 lsls r3, r6, #31 + 29dc2: 19c0 adds r0, r0, r7 + 29dc4: 4159 adcs r1, r3 + 29dc6: bdf0 pop {r4, r5, r6, r7, pc} + 29dc8: 043a lsls r2, r7, #16 + 29dca: f1b2 7f80 cmp.w r2, #16777216 ; 0x1000000 + 29dce: bf38 it cc + 29dd0: f04f 0e10 movcc.w lr, #16 + 29dd4: d3bd bcc.n 29d52 <__rtl_ftod_v1_00+0x26> + 29dd6: f04f 0e08 mov.w lr, #8 + 29dda: e7bb b.n 29d54 <__rtl_ftod_v1_00+0x28> + 29ddc: 07f1 lsls r1, r6, #31 + 29dde: 4638 mov r0, r7 + 29de0: bdf0 pop {r4, r5, r6, r7, pc} + 29de2: f6c7 71f8 movt r1, #32760 ; 0x7ff8 + 29de6: bdf0 pop {r4, r5, r6, r7, pc} + +00029de8 <__rtl_dtof_v1_00>: + 29de8: b430 push {r4, r5} + 29dea: f64f 75ff movw r5, #65535 ; 0xffff + 29dee: f2c0 050f movt r5, #15 + 29df2: f04f 34ff mov.w r4, #4294967295 + 29df6: 4004 ands r4, r0 + 29df8: 02a3 lsls r3, r4, #10 + 29dfa: ea4f 5294 mov.w r2, r4, lsr #22 + 29dfe: ea05 0501 and.w r5, r5, r1 + 29e02: bf14 ite ne + 29e04: 2001 movne r0, #1 + 29e06: 2000 moveq r0, #0 + 29e08: ea42 2285 orr.w r2, r2, r5, lsl #10 + 29e0c: 4302 orrs r2, r0 + 29e0e: f3c1 500a ubfx r0, r1, #20, #11 + 29e12: 2800 cmp r0, #0 + 29e14: bf08 it eq + 29e16: 2a00 cmpeq r2, #0 + 29e18: ea4f 71d1 mov.w r1, r1, lsr #31 + 29e1c: bf14 ite ne + 29e1e: 2401 movne r4, #1 + 29e20: 2400 moveq r4, #0 + 29e22: d020 beq.n 29e66 <__rtl_dtof_v1_00+0x7e> + 29e24: f46f 7360 mvn.w r3, #896 ; 0x380 + 29e28: 4418 add r0, r3 + 29e2a: b283 uxth r3, r0 + 29e2c: 2bfc cmp r3, #252 ; 0xfc + 29e2e: f042 4280 orr.w r2, r2, #1073741824 ; 0x40000000 + 29e32: b29c uxth r4, r3 + 29e34: bf9c itt ls + 29e36: 09d2 lsrls r2, r2, #7 + 29e38: b224 sxthls r4, r4 + 29e3a: d906 bls.n 29e4a <__rtl_dtof_v1_00+0x62> + 29e3c: b224 sxth r4, r4 + 29e3e: 2cfd cmp r4, #253 ; 0xfd + 29e40: dc09 bgt.n 29e56 <__rtl_dtof_v1_00+0x6e> + 29e42: 2c00 cmp r4, #0 + 29e44: bfa8 it ge + 29e46: 09d2 lsrge r2, r2, #7 + 29e48: db10 blt.n 29e6c <__rtl_dtof_v1_00+0x84> + 29e4a: 05e0 lsls r0, r4, #23 + 29e4c: 4410 add r0, r2 + 29e4e: eba0 70c1 sub.w r0, r0, r1, lsl #31 + 29e52: bc30 pop {r4, r5} + 29e54: 4770 bx lr + 29e56: f64f 70ff movw r0, #65535 ; 0xffff + 29e5a: bc30 pop {r4, r5} + 29e5c: f6c7 707f movt r0, #32639 ; 0x7f7f + 29e60: 07c9 lsls r1, r1, #31 + 29e62: 4408 add r0, r1 + 29e64: 4770 bx lr + 29e66: 4620 mov r0, r4 + 29e68: 4622 mov r2, r4 + 29e6a: e7ef b.n 29e4c <__rtl_dtof_v1_00+0x64> + 29e6c: 425b negs r3, r3 + 29e6e: b21b sxth r3, r3 + 29e70: 2b1f cmp r3, #31 + 29e72: bfc4 itt gt + 29e74: 2000 movgt r0, #0 + 29e76: 4602 movgt r2, r0 + 29e78: dce8 bgt.n 29e4c <__rtl_dtof_v1_00+0x64> + 29e7a: 40da lsrs r2, r3 + 29e7c: 09d0 lsrs r0, r2, #7 + 29e7e: 4602 mov r2, r0 + 29e80: d0e4 beq.n 29e4c <__rtl_dtof_v1_00+0x64> + 29e82: 2400 movs r4, #0 + 29e84: e7e1 b.n 29e4a <__rtl_dtof_v1_00+0x62> + 29e86: bf00 nop + +00029e88 <__rtl_uitof_v1_00>: + 29e88: 4602 mov r2, r0 + 29e8a: 2300 movs r3, #0 + 29e8c: ea52 0103 orrs.w r1, r2, r3 + 29e90: bf04 itt eq + 29e92: 2000 moveq r0, #0 + 29e94: 2100 moveq r1, #0 + 29e96: d055 beq.n 29f44 <__rtl_uitof_v1_00+0xbc> + 29e98: f1b3 4f00 cmp.w r3, #2147483648 ; 0x80000000 + 29e9c: bf08 it eq + 29e9e: 2a00 cmpeq r2, #0 + 29ea0: d052 beq.n 29f48 <__rtl_uitof_v1_00+0xc0> + 29ea2: 2a00 cmp r2, #0 + 29ea4: f173 0100 sbcs.w r1, r3, #0 + 29ea8: b5f0 push {r4, r5, r6, r7, lr} + 29eaa: bfa4 itt ge + 29eac: 2000 movge r0, #0 + 29eae: 2100 movge r1, #0 + 29eb0: db50 blt.n 29f54 <__rtl_uitof_v1_00+0xcc> + 29eb2: f241 57a0 movw r7, #5536 ; 0x15a0 + 29eb6: 2b01 cmp r3, #1 + 29eb8: bf08 it eq + 29eba: 2a00 cmpeq r2, #0 + 29ebc: bf2c ite cs + 29ebe: 461e movcs r6, r3 + 29ec0: 4616 movcc r6, r2 + 29ec2: f2c0 0703 movt r7, #3 + 29ec6: bf2c ite cs + 29ec8: f04f 0cff movcs.w ip, #255 ; 0xff + 29ecc: f04f 0c1f movcc.w ip, #31 + 29ed0: f5b6 3f80 cmp.w r6, #65536 ; 0x10000 + 29ed4: bf3a itte cc + 29ed6: 0436 lslcc r6, r6, #16 + 29ed8: f04f 0e10 movcc.w lr, #16 + 29edc: f04f 0e00 movcs.w lr, #0 + 29ee0: f1b6 7f80 cmp.w r6, #16777216 ; 0x1000000 + 29ee4: bf3c itt cc + 29ee6: 0236 lslcc r6, r6, #8 + 29ee8: f10e 0e08 addcc.w lr, lr, #8 + 29eec: ea4f 6616 mov.w r6, r6, lsr #24 + 29ef0: bf38 it cc + 29ef2: fa5f fe8e uxtbcc.w lr, lr + 29ef6: 5dbf ldrb r7, [r7, r6] + 29ef8: eb0e 060c add.w r6, lr, ip + 29efc: 443e add r6, r7 + 29efe: b2f6 uxtb r6, r6 + 29f00: f1a6 0e20 sub.w lr, r6, #32 + 29f04: 40b3 lsls r3, r6 + 29f06: f1c6 0720 rsb r7, r6, #32 + 29f0a: fa02 fe0e lsl.w lr, r2, lr + 29f0e: fa22 f707 lsr.w r7, r2, r7 + 29f12: ea43 030e orr.w r3, r3, lr + 29f16: 40b2 lsls r2, r6 + 29f18: 433b orrs r3, r7 + 29f1a: 0a94 lsrs r4, r2, #10 + 29f1c: ea44 5483 orr.w r4, r4, r3, lsl #22 + 29f20: 0a9d lsrs r5, r3, #10 + 29f22: ea54 0305 orrs.w r3, r4, r5 + 29f26: bf07 ittee eq + 29f28: 4622 moveq r2, r4 + 29f2a: 462b moveq r3, r5 + 29f2c: f5c6 6687 rsbne r6, r6, #1080 ; 0x438 + 29f30: 3604 addne r6, #4 + 29f32: bf1c itt ne + 29f34: 0533 lslne r3, r6, #20 + 29f36: 2200 movne r2, #0 + 29f38: 1900 adds r0, r0, r4 + 29f3a: 4169 adcs r1, r5 + 29f3c: 1880 adds r0, r0, r2 + 29f3e: 4159 adcs r1, r3 + 29f40: e8bd 40f0 ldmia.w sp!, {r4, r5, r6, r7, lr} + 29f44: f7ff bf50 b.w 29de8 <__rtl_dtof_v1_00> + 29f48: 2100 movs r1, #0 + 29f4a: 2000 movs r0, #0 + 29f4c: f2cc 31e0 movt r1, #50144 ; 0xc3e0 + 29f50: f7ff bf4a b.w 29de8 <__rtl_dtof_v1_00> + 29f54: 4252 negs r2, r2 + 29f56: eb63 0343 sbc.w r3, r3, r3, lsl #1 + 29f5a: 2000 movs r0, #0 + 29f5c: f04f 4100 mov.w r1, #2147483648 ; 0x80000000 + 29f60: e7a7 b.n 29eb2 <__rtl_uitof_v1_00+0x2a> + 29f62: bf00 nop + +00029f64 <__rtl_fadd_v1_00>: + 29f64: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + 29f68: 0fc4 lsrs r4, r0, #31 + 29f6a: b2e2 uxtb r2, r4 + 29f6c: ebb2 7fd1 cmp.w r2, r1, lsr #31 + 29f70: 4603 mov r3, r0 + 29f72: f000 80a9 beq.w 2a0c8 <__rtl_fadd_v1_00+0x164> + 29f76: f3c1 56c7 ubfx r6, r1, #23, #8 + 29f7a: f3c0 54c7 ubfx r4, r0, #23, #8 + 29f7e: fa1f fe84 uxth.w lr, r4 + 29f82: fa1f f886 uxth.w r8, r6 + 29f86: ebc8 0c0e rsb ip, r8, lr + 29f8a: fa1f fc8c uxth.w ip, ip + 29f8e: fa1f f58c uxth.w r5, ip + 29f92: b22f sxth r7, r5 + 29f94: f3c0 0316 ubfx r3, r0, #0, #23 + 29f98: f3c1 0116 ubfx r1, r1, #0, #23 + 29f9c: 2f00 cmp r7, #0 + 29f9e: ea4f 13c3 mov.w r3, r3, lsl #7 + 29fa2: ea4f 11c1 mov.w r1, r1, lsl #7 + 29fa6: dd40 ble.n 2a02a <__rtl_fadd_v1_00+0xc6> + 29fa8: 2cff cmp r4, #255 ; 0xff + 29faa: d04d beq.n 2a048 <__rtl_fadd_v1_00+0xe4> + 29fac: 2e00 cmp r6, #0 + 29fae: d14d bne.n 2a04c <__rtl_fadd_v1_00+0xe8> + 29fb0: f10c 35ff add.w r5, ip, #4294967295 + 29fb4: b2ad uxth r5, r5 + 29fb6: b22f sxth r7, r5 + 29fb8: 2d00 cmp r5, #0 + 29fba: d149 bne.n 2a050 <__rtl_fadd_v1_00+0xec> + 29fbc: f043 4380 orr.w r3, r3, #1073741824 ; 0x40000000 + 29fc0: 1a59 subs r1, r3, r1 + 29fc2: f241 55a0 movw r5, #5536 ; 0x15a0 + 29fc6: f5b1 3f80 cmp.w r1, #65536 ; 0x10000 + 29fca: bf28 it cs + 29fcc: 4608 movcs r0, r1 + 29fce: f2c0 0503 movt r5, #3 + 29fd2: bf3a itte cc + 29fd4: 0408 lslcc r0, r1, #16 + 29fd6: 2310 movcc r3, #16 + 29fd8: 2300 movcs r3, #0 + 29fda: f1b0 7f80 cmp.w r0, #16777216 ; 0x1000000 + 29fde: bf3c itt cc + 29fe0: 0200 lslcc r0, r0, #8 + 29fe2: 3308 addcc r3, #8 + 29fe4: ea4f 6010 mov.w r0, r0, lsr #24 + 29fe8: bf38 it cc + 29fea: b2db uxtbcc r3, r3 + 29fec: 5c28 ldrb r0, [r5, r0] + 29fee: 3b01 subs r3, #1 + 29ff0: 4403 add r3, r0 + 29ff2: f10e 34ff add.w r4, lr, #4294967295 + 29ff6: b2db uxtb r3, r3 + 29ff8: b2a4 uxth r4, r4 + 29ffa: 1ae4 subs r4, r4, r3 + 29ffc: b2a4 uxth r4, r4 + 29ffe: 2cfc cmp r4, #252 ; 0xfc + 2a000: fa01 f103 lsl.w r1, r1, r3 + 2a004: b2a0 uxth r0, r4 + 2a006: d907 bls.n 2a018 <__rtl_fadd_v1_00+0xb4> + 2a008: b203 sxth r3, r0 + 2a00a: 2bfe cmp r3, #254 ; 0xfe + 2a00c: d02f beq.n 2a06e <__rtl_fadd_v1_00+0x10a> + 2a00e: 2bfd cmp r3, #253 ; 0xfd + 2a010: d02b beq.n 2a06a <__rtl_fadd_v1_00+0x106> + 2a012: 2b00 cmp r3, #0 + 2a014: f2c0 80bf blt.w 2a196 <__rtl_fadd_v1_00+0x232> + 2a018: 09c9 lsrs r1, r1, #7 + 2a01a: bf0c ite eq + 2a01c: 4608 moveq r0, r1 + 2a01e: 05c0 lslne r0, r0, #23 + 2a020: eba1 71c2 sub.w r1, r1, r2, lsl #31 + 2a024: 4408 add r0, r1 + 2a026: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 2a02a: bb65 cbnz r5, 2a086 <__rtl_fadd_v1_00+0x122> + 2a02c: b90c cbnz r4, 2a032 <__rtl_fadd_v1_00+0xce> + 2a02e: 2601 movs r6, #1 + 2a030: 4634 mov r4, r6 + 2a032: 428b cmp r3, r1 + 2a034: bf88 it hi + 2a036: fa1f fe84 uxthhi.w lr, r4 + 2a03a: d8c1 bhi.n 29fc0 <__rtl_fadd_v1_00+0x5c> + 2a03c: bf38 it cc + 2a03e: fa1f fe86 uxthcc.w lr, r6 + 2a042: d33d bcc.n 2a0c0 <__rtl_fadd_v1_00+0x15c> + 2a044: f04f 4000 mov.w r0, #2147483648 ; 0x80000000 + 2a048: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 2a04c: f041 4180 orr.w r1, r1, #1073741824 ; 0x40000000 + 2a050: 2f1f cmp r7, #31 + 2a052: dc14 bgt.n 2a07e <__rtl_fadd_v1_00+0x11a> + 2a054: 4278 negs r0, r7 + 2a056: f000 001f and.w r0, r0, #31 + 2a05a: fa11 f000 lsls.w r0, r1, r0 + 2a05e: fa21 f107 lsr.w r1, r1, r7 + 2a062: bf18 it ne + 2a064: f041 0101 orrne.w r1, r1, #1 + 2a068: e7a8 b.n 29fbc <__rtl_fadd_v1_00+0x58> + 2a06a: 2900 cmp r1, #0 + 2a06c: dad4 bge.n 2a018 <__rtl_fadd_v1_00+0xb4> + 2a06e: f64f 70ff movw r0, #65535 ; 0xffff + 2a072: f6c7 707f movt r0, #32639 ; 0x7f7f + 2a076: 07d2 lsls r2, r2, #31 + 2a078: 4410 add r0, r2 + 2a07a: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 2a07e: 3100 adds r1, #0 + 2a080: bf18 it ne + 2a082: 2101 movne r1, #1 + 2a084: e79a b.n 29fbc <__rtl_fadd_v1_00+0x58> + 2a086: 2eff cmp r6, #255 ; 0xff + 2a088: f000 80bd beq.w 2a206 <__rtl_fadd_v1_00+0x2a2> + 2a08c: 2c00 cmp r4, #0 + 2a08e: f040 80c4 bne.w 2a21a <__rtl_fadd_v1_00+0x2b6> + 2a092: f10c 0501 add.w r5, ip, #1 + 2a096: b2ad uxth r5, r5 + 2a098: 426d negs r5, r5 + 2a09a: b2ad uxth r5, r5 + 2a09c: b16d cbz r5, 2a0ba <__rtl_fadd_v1_00+0x156> + 2a09e: b22d sxth r5, r5 + 2a0a0: 2d1f cmp r5, #31 + 2a0a2: f300 80c8 bgt.w 2a236 <__rtl_fadd_v1_00+0x2d2> + 2a0a6: 4268 negs r0, r5 + 2a0a8: f000 001f and.w r0, r0, #31 + 2a0ac: fa13 f000 lsls.w r0, r3, r0 + 2a0b0: fa23 f305 lsr.w r3, r3, r5 + 2a0b4: bf18 it ne + 2a0b6: f043 0301 orrne.w r3, r3, #1 + 2a0ba: 46c6 mov lr, r8 + 2a0bc: f041 4180 orr.w r1, r1, #1073741824 ; 0x40000000 + 2a0c0: 1ac9 subs r1, r1, r3 + 2a0c2: f082 0201 eor.w r2, r2, #1 + 2a0c6: e77c b.n 29fc2 <__rtl_fadd_v1_00+0x5e> + 2a0c8: f3c0 52c7 ubfx r2, r0, #23, #8 + 2a0cc: f3c1 55c7 ubfx r5, r1, #23, #8 + 2a0d0: b296 uxth r6, r2 + 2a0d2: fa1f fc85 uxth.w ip, r5 + 2a0d6: ebcc 0e06 rsb lr, ip, r6 + 2a0da: fa1f fe8e uxth.w lr, lr + 2a0de: fa1f f08e uxth.w r0, lr + 2a0e2: b207 sxth r7, r0 + 2a0e4: f3c1 0116 ubfx r1, r1, #0, #23 + 2a0e8: f3c3 0816 ubfx r8, r3, #0, #23 + 2a0ec: 2f00 cmp r7, #0 + 2a0ee: ea4f 1181 mov.w r1, r1, lsl #6 + 2a0f2: ea4f 1888 mov.w r8, r8, lsl #6 + 2a0f6: dd44 ble.n 2a182 <__rtl_fadd_v1_00+0x21e> + 2a0f8: 2aff cmp r2, #255 ; 0xff + 2a0fa: f000 808b beq.w 2a214 <__rtl_fadd_v1_00+0x2b0> + 2a0fe: 2d00 cmp r5, #0 + 2a100: d130 bne.n 2a164 <__rtl_fadd_v1_00+0x200> + 2a102: f10e 30ff add.w r0, lr, #4294967295 + 2a106: b280 uxth r0, r0 + 2a108: b207 sxth r7, r0 + 2a10a: bb68 cbnz r0, 2a168 <__rtl_fadd_v1_00+0x204> + 2a10c: f048 5800 orr.w r8, r8, #536870912 ; 0x20000000 + 2a110: 4441 add r1, r8 + 2a112: 0048 lsls r0, r1, #1 + 2a114: bf4f iteee mi + 2a116: 4608 movmi r0, r1 + 2a118: f106 36ff addpl.w r6, r6, #4294967295 + 2a11c: b2b6 uxthpl r6, r6 + 2a11e: b2b2 uxthpl r2, r6 + 2a120: 2efc cmp r6, #252 ; 0xfc + 2a122: d916 bls.n 2a152 <__rtl_fadd_v1_00+0x1ee> + 2a124: b213 sxth r3, r2 + 2a126: 2bfe cmp r3, #254 ; 0xfe + 2a128: d049 beq.n 2a1be <__rtl_fadd_v1_00+0x25a> + 2a12a: 3301 adds r3, #1 + 2a12c: d111 bne.n 2a152 <__rtl_fadd_v1_00+0x1ee> + 2a12e: 4273 negs r3, r6 + 2a130: b21b sxth r3, r3 + 2a132: 2b1f cmp r3, #31 + 2a134: bfc4 itt gt + 2a136: 2200 movgt r2, #0 + 2a138: 4610 movgt r0, r2 + 2a13a: dc0e bgt.n 2a15a <__rtl_fadd_v1_00+0x1f6> + 2a13c: 425a negs r2, r3 + 2a13e: f002 021f and.w r2, r2, #31 + 2a142: fa10 f202 lsls.w r2, r0, r2 + 2a146: fa20 f003 lsr.w r0, r0, r3 + 2a14a: bf18 it ne + 2a14c: f040 0001 orrne.w r0, r0, #1 + 2a150: 2200 movs r2, #0 + 2a152: 09c0 lsrs r0, r0, #7 + 2a154: bf0c ite eq + 2a156: 4602 moveq r2, r0 + 2a158: 05d2 lslne r2, r2, #23 + 2a15a: 4410 add r0, r2 + 2a15c: eba0 70c4 sub.w r0, r0, r4, lsl #31 + 2a160: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 2a164: f041 5100 orr.w r1, r1, #536870912 ; 0x20000000 + 2a168: 2f1f cmp r7, #31 + 2a16a: dc24 bgt.n 2a1b6 <__rtl_fadd_v1_00+0x252> + 2a16c: 427b negs r3, r7 + 2a16e: f003 031f and.w r3, r3, #31 + 2a172: fa11 f303 lsls.w r3, r1, r3 + 2a176: fa21 f107 lsr.w r1, r1, r7 + 2a17a: bf18 it ne + 2a17c: f041 0101 orrne.w r1, r1, #1 + 2a180: e7c4 b.n 2a10c <__rtl_fadd_v1_00+0x1a8> + 2a182: bb20 cbnz r0, 2a1ce <__rtl_fadd_v1_00+0x26a> + 2a184: 2aff cmp r2, #255 ; 0xff + 2a186: d045 beq.n 2a214 <__rtl_fadd_v1_00+0x2b0> + 2a188: 2a00 cmp r2, #0 + 2a18a: d049 beq.n 2a220 <__rtl_fadd_v1_00+0x2bc> + 2a18c: f101 4180 add.w r1, r1, #1073741824 ; 0x40000000 + 2a190: eb01 0008 add.w r0, r1, r8 + 2a194: e7c4 b.n 2a120 <__rtl_fadd_v1_00+0x1bc> + 2a196: 4264 negs r4, r4 + 2a198: b224 sxth r4, r4 + 2a19a: 2c1f cmp r4, #31 + 2a19c: dc46 bgt.n 2a22c <__rtl_fadd_v1_00+0x2c8> + 2a19e: 4263 negs r3, r4 + 2a1a0: f003 031f and.w r3, r3, #31 + 2a1a4: fa11 f303 lsls.w r3, r1, r3 + 2a1a8: fa21 f104 lsr.w r1, r1, r4 + 2a1ac: bf18 it ne + 2a1ae: f041 0101 orrne.w r1, r1, #1 + 2a1b2: 2000 movs r0, #0 + 2a1b4: e730 b.n 2a018 <__rtl_fadd_v1_00+0xb4> + 2a1b6: 3100 adds r1, #0 + 2a1b8: bf18 it ne + 2a1ba: 2101 movne r1, #1 + 2a1bc: e7a6 b.n 2a10c <__rtl_fadd_v1_00+0x1a8> + 2a1be: f64f 70ff movw r0, #65535 ; 0xffff + 2a1c2: f6c7 707f movt r0, #32639 ; 0x7f7f + 2a1c6: 07e4 lsls r4, r4, #31 + 2a1c8: 4420 add r0, r4 + 2a1ca: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 2a1ce: 2dff cmp r5, #255 ; 0xff + 2a1d0: d040 beq.n 2a254 <__rtl_fadd_v1_00+0x2f0> + 2a1d2: bba2 cbnz r2, 2a23e <__rtl_fadd_v1_00+0x2da> + 2a1d4: f10e 0001 add.w r0, lr, #1 + 2a1d8: b280 uxth r0, r0 + 2a1da: 4243 negs r3, r0 + 2a1dc: b29b uxth r3, r3 + 2a1de: 4666 mov r6, ip + 2a1e0: 462a mov r2, r5 + 2a1e2: 2b00 cmp r3, #0 + 2a1e4: d092 beq.n 2a10c <__rtl_fadd_v1_00+0x1a8> + 2a1e6: b21b sxth r3, r3 + 2a1e8: 2b1f cmp r3, #31 + 2a1ea: dc2b bgt.n 2a244 <__rtl_fadd_v1_00+0x2e0> + 2a1ec: 425a negs r2, r3 + 2a1ee: f002 021f and.w r2, r2, #31 + 2a1f2: fa18 f202 lsls.w r2, r8, r2 + 2a1f6: fa28 f803 lsr.w r8, r8, r3 + 2a1fa: 4666 mov r6, ip + 2a1fc: 462a mov r2, r5 + 2a1fe: bf18 it ne + 2a200: f048 0801 orrne.w r8, r8, #1 + 2a204: e782 b.n 2a10c <__rtl_fadd_v1_00+0x1a8> + 2a206: f082 0201 eor.w r2, r2, #1 + 2a20a: 07d0 lsls r0, r2, #31 + 2a20c: f100 40ff add.w r0, r0, #2139095040 ; 0x7f800000 + 2a210: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 2a214: 4618 mov r0, r3 + 2a216: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 2a21a: f043 4380 orr.w r3, r3, #1073741824 ; 0x40000000 + 2a21e: e73b b.n 2a098 <__rtl_fadd_v1_00+0x134> + 2a220: 4441 add r1, r8 + 2a222: 07e4 lsls r4, r4, #31 + 2a224: eb04 1091 add.w r0, r4, r1, lsr #6 + 2a228: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 2a22c: 3100 adds r1, #0 + 2a22e: bf18 it ne + 2a230: 2101 movne r1, #1 + 2a232: 2000 movs r0, #0 + 2a234: e6f0 b.n 2a018 <__rtl_fadd_v1_00+0xb4> + 2a236: 3300 adds r3, #0 + 2a238: bf18 it ne + 2a23a: 2301 movne r3, #1 + 2a23c: e73d b.n 2a0ba <__rtl_fadd_v1_00+0x156> + 2a23e: f048 5800 orr.w r8, r8, #536870912 ; 0x20000000 + 2a242: e7ca b.n 2a1da <__rtl_fadd_v1_00+0x276> + 2a244: f118 0800 adds.w r8, r8, #0 + 2a248: bf18 it ne + 2a24a: f04f 0801 movne.w r8, #1 + 2a24e: 4666 mov r6, ip + 2a250: 462a mov r2, r5 + 2a252: e75b b.n 2a10c <__rtl_fadd_v1_00+0x1a8> + 2a254: 07e0 lsls r0, r4, #31 + 2a256: f100 40ff add.w r0, r0, #2139095040 ; 0x7f800000 + 2a25a: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 2a25e: bf00 nop + +0002a260 <__rtl_fsub_v1_00>: + 2a260: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + 2a264: 0fc4 lsrs r4, r0, #31 + 2a266: b2e5 uxtb r5, r4 + 2a268: ebb5 7fd1 cmp.w r5, r1, lsr #31 + 2a26c: 4603 mov r3, r0 + 2a26e: f3c0 52c7 ubfx r2, r0, #23, #8 + 2a272: f000 8082 beq.w 2a37a <__rtl_fsub_v1_00+0x11a> + 2a276: f3c1 55c7 ubfx r5, r1, #23, #8 + 2a27a: b296 uxth r6, r2 + 2a27c: fa1f fc85 uxth.w ip, r5 + 2a280: ebcc 0e06 rsb lr, ip, r6 + 2a284: fa1f fe8e uxth.w lr, lr + 2a288: fa1f f08e uxth.w r0, lr + 2a28c: b207 sxth r7, r0 + 2a28e: f3c1 0116 ubfx r1, r1, #0, #23 + 2a292: f3c3 0816 ubfx r8, r3, #0, #23 + 2a296: 2f00 cmp r7, #0 + 2a298: ea4f 1181 mov.w r1, r1, lsl #6 + 2a29c: ea4f 1888 mov.w r8, r8, lsl #6 + 2a2a0: dd31 ble.n 2a306 <__rtl_fsub_v1_00+0xa6> + 2a2a2: 2aff cmp r2, #255 ; 0xff + 2a2a4: d03e beq.n 2a324 <__rtl_fsub_v1_00+0xc4> + 2a2a6: b9fd cbnz r5, 2a2e8 <__rtl_fsub_v1_00+0x88> + 2a2a8: f10e 30ff add.w r0, lr, #4294967295 + 2a2ac: b280 uxth r0, r0 + 2a2ae: b207 sxth r7, r0 + 2a2b0: b9e0 cbnz r0, 2a2ec <__rtl_fsub_v1_00+0x8c> + 2a2b2: f048 5800 orr.w r8, r8, #536870912 ; 0x20000000 + 2a2b6: 4441 add r1, r8 + 2a2b8: 0048 lsls r0, r1, #1 + 2a2ba: bf4f iteee mi + 2a2bc: 4608 movmi r0, r1 + 2a2be: f106 36ff addpl.w r6, r6, #4294967295 + 2a2c2: b2b6 uxthpl r6, r6 + 2a2c4: b2b2 uxthpl r2, r6 + 2a2c6: 2efc cmp r6, #252 ; 0xfc + 2a2c8: d905 bls.n 2a2d6 <__rtl_fsub_v1_00+0x76> + 2a2ca: b213 sxth r3, r2 + 2a2cc: 2bfe cmp r3, #254 ; 0xfe + 2a2ce: d02c beq.n 2a32a <__rtl_fsub_v1_00+0xca> + 2a2d0: 3301 adds r3, #1 + 2a2d2: f000 80d8 beq.w 2a486 <__rtl_fsub_v1_00+0x226> + 2a2d6: 09c0 lsrs r0, r0, #7 + 2a2d8: bf0c ite eq + 2a2da: 4602 moveq r2, r0 + 2a2dc: 05d2 lslne r2, r2, #23 + 2a2de: 4410 add r0, r2 + 2a2e0: eba0 70c4 sub.w r0, r0, r4, lsl #31 + 2a2e4: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 2a2e8: f041 5100 orr.w r1, r1, #536870912 ; 0x20000000 + 2a2ec: 2f1f cmp r7, #31 + 2a2ee: dc15 bgt.n 2a31c <__rtl_fsub_v1_00+0xbc> + 2a2f0: 427b negs r3, r7 + 2a2f2: f003 031f and.w r3, r3, #31 + 2a2f6: fa11 f303 lsls.w r3, r1, r3 + 2a2fa: fa21 f107 lsr.w r1, r1, r7 + 2a2fe: bf18 it ne + 2a300: f041 0101 orrne.w r1, r1, #1 + 2a304: e7d5 b.n 2a2b2 <__rtl_fsub_v1_00+0x52> + 2a306: b9c0 cbnz r0, 2a33a <__rtl_fsub_v1_00+0xda> + 2a308: 2aff cmp r2, #255 ; 0xff + 2a30a: d00b beq.n 2a324 <__rtl_fsub_v1_00+0xc4> + 2a30c: 2a00 cmp r2, #0 + 2a30e: f000 80fe beq.w 2a50e <__rtl_fsub_v1_00+0x2ae> + 2a312: f101 4180 add.w r1, r1, #1073741824 ; 0x40000000 + 2a316: eb01 0008 add.w r0, r1, r8 + 2a31a: e7d4 b.n 2a2c6 <__rtl_fsub_v1_00+0x66> + 2a31c: 3100 adds r1, #0 + 2a31e: bf18 it ne + 2a320: 2101 movne r1, #1 + 2a322: e7c6 b.n 2a2b2 <__rtl_fsub_v1_00+0x52> + 2a324: 4618 mov r0, r3 + 2a326: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 2a32a: f64f 70ff movw r0, #65535 ; 0xffff + 2a32e: f6c7 707f movt r0, #32639 ; 0x7f7f + 2a332: 07e4 lsls r4, r4, #31 + 2a334: 4420 add r0, r4 + 2a336: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 2a33a: 2dff cmp r5, #255 ; 0xff + 2a33c: f000 80e2 beq.w 2a504 <__rtl_fsub_v1_00+0x2a4> + 2a340: 2a00 cmp r2, #0 + 2a342: f040 80eb bne.w 2a51c <__rtl_fsub_v1_00+0x2bc> + 2a346: f10e 0001 add.w r0, lr, #1 + 2a34a: b280 uxth r0, r0 + 2a34c: 4240 negs r0, r0 + 2a34e: b280 uxth r0, r0 + 2a350: 4666 mov r6, ip + 2a352: 462a mov r2, r5 + 2a354: 2800 cmp r0, #0 + 2a356: d0ac beq.n 2a2b2 <__rtl_fsub_v1_00+0x52> + 2a358: b200 sxth r0, r0 + 2a35a: 281f cmp r0, #31 + 2a35c: f300 80e1 bgt.w 2a522 <__rtl_fsub_v1_00+0x2c2> + 2a360: 4243 negs r3, r0 + 2a362: f003 031f and.w r3, r3, #31 + 2a366: fa18 f303 lsls.w r3, r8, r3 + 2a36a: fa28 f800 lsr.w r8, r8, r0 + 2a36e: 4666 mov r6, ip + 2a370: 462a mov r2, r5 + 2a372: bf18 it ne + 2a374: f048 0801 orrne.w r8, r8, #1 + 2a378: e79b b.n 2a2b2 <__rtl_fsub_v1_00+0x52> + 2a37a: f3c1 56c7 ubfx r6, r1, #23, #8 + 2a37e: fa1f fe82 uxth.w lr, r2 + 2a382: fa1f f886 uxth.w r8, r6 + 2a386: ebc8 0c0e rsb ip, r8, lr + 2a38a: fa1f fc8c uxth.w ip, ip + 2a38e: fa1f f48c uxth.w r4, ip + 2a392: b227 sxth r7, r4 + 2a394: f3c0 0316 ubfx r3, r0, #0, #23 + 2a398: f3c1 0116 ubfx r1, r1, #0, #23 + 2a39c: 2f00 cmp r7, #0 + 2a39e: ea4f 13c3 mov.w r3, r3, lsl #7 + 2a3a2: ea4f 11c1 mov.w r1, r1, lsl #7 + 2a3a6: dd5d ble.n 2a464 <__rtl_fsub_v1_00+0x204> + 2a3a8: 2aff cmp r2, #255 ; 0xff + 2a3aa: d0bc beq.n 2a326 <__rtl_fsub_v1_00+0xc6> + 2a3ac: 2e00 cmp r6, #0 + 2a3ae: d14a bne.n 2a446 <__rtl_fsub_v1_00+0x1e6> + 2a3b0: f10c 34ff add.w r4, ip, #4294967295 + 2a3b4: b2a4 uxth r4, r4 + 2a3b6: b227 sxth r7, r4 + 2a3b8: 2c00 cmp r4, #0 + 2a3ba: d146 bne.n 2a44a <__rtl_fsub_v1_00+0x1ea> + 2a3bc: f043 4380 orr.w r3, r3, #1073741824 ; 0x40000000 + 2a3c0: 1a59 subs r1, r3, r1 + 2a3c2: f241 53a0 movw r3, #5536 ; 0x15a0 + 2a3c6: f5b1 3f80 cmp.w r1, #65536 ; 0x10000 + 2a3ca: bf28 it cs + 2a3cc: 460a movcs r2, r1 + 2a3ce: f2c0 0303 movt r3, #3 + 2a3d2: bf3a itte cc + 2a3d4: 040a lslcc r2, r1, #16 + 2a3d6: 2010 movcc r0, #16 + 2a3d8: 2000 movcs r0, #0 + 2a3da: f1b2 7f80 cmp.w r2, #16777216 ; 0x1000000 + 2a3de: bf3c itt cc + 2a3e0: 0212 lslcc r2, r2, #8 + 2a3e2: 3008 addcc r0, #8 + 2a3e4: ea4f 6212 mov.w r2, r2, lsr #24 + 2a3e8: bf38 it cc + 2a3ea: b2c0 uxtbcc r0, r0 + 2a3ec: 5c9b ldrb r3, [r3, r2] + 2a3ee: 3801 subs r0, #1 + 2a3f0: 4403 add r3, r0 + 2a3f2: f10e 36ff add.w r6, lr, #4294967295 + 2a3f6: b2db uxtb r3, r3 + 2a3f8: b2b6 uxth r6, r6 + 2a3fa: 1af2 subs r2, r6, r3 + 2a3fc: b292 uxth r2, r2 + 2a3fe: 2afc cmp r2, #252 ; 0xfc + 2a400: fa01 f103 lsl.w r1, r1, r3 + 2a404: b290 uxth r0, r2 + 2a406: d915 bls.n 2a434 <__rtl_fsub_v1_00+0x1d4> + 2a408: b203 sxth r3, r0 + 2a40a: 2bfd cmp r3, #253 ; 0xfd + 2a40c: dc51 bgt.n 2a4b2 <__rtl_fsub_v1_00+0x252> + 2a40e: d04e beq.n 2a4ae <__rtl_fsub_v1_00+0x24e> + 2a410: 2b00 cmp r3, #0 + 2a412: da0f bge.n 2a434 <__rtl_fsub_v1_00+0x1d4> + 2a414: 4253 negs r3, r2 + 2a416: b21b sxth r3, r3 + 2a418: 2b1f cmp r3, #31 + 2a41a: f300 808d bgt.w 2a538 <__rtl_fsub_v1_00+0x2d8> + 2a41e: 425a negs r2, r3 + 2a420: f002 021f and.w r2, r2, #31 + 2a424: fa11 f202 lsls.w r2, r1, r2 + 2a428: fa21 f103 lsr.w r1, r1, r3 + 2a42c: bf18 it ne + 2a42e: f041 0101 orrne.w r1, r1, #1 + 2a432: 2000 movs r0, #0 + 2a434: 09c9 lsrs r1, r1, #7 + 2a436: bf0c ite eq + 2a438: 4608 moveq r0, r1 + 2a43a: 05c0 lslne r0, r0, #23 + 2a43c: eba1 71c5 sub.w r1, r1, r5, lsl #31 + 2a440: 4408 add r0, r1 + 2a442: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 2a446: f041 4180 orr.w r1, r1, #1073741824 ; 0x40000000 + 2a44a: 2f1f cmp r7, #31 + 2a44c: dc39 bgt.n 2a4c2 <__rtl_fsub_v1_00+0x262> + 2a44e: 427a negs r2, r7 + 2a450: f002 021f and.w r2, r2, #31 + 2a454: fa11 f202 lsls.w r2, r1, r2 + 2a458: fa21 f107 lsr.w r1, r1, r7 + 2a45c: bf18 it ne + 2a45e: f041 0101 orrne.w r1, r1, #1 + 2a462: e7ab b.n 2a3bc <__rtl_fsub_v1_00+0x15c> + 2a464: bb8c cbnz r4, 2a4ca <__rtl_fsub_v1_00+0x26a> + 2a466: b90a cbnz r2, 2a46c <__rtl_fsub_v1_00+0x20c> + 2a468: 2601 movs r6, #1 + 2a46a: 4632 mov r2, r6 + 2a46c: 428b cmp r3, r1 + 2a46e: bf88 it hi + 2a470: fa1f fe82 uxthhi.w lr, r2 + 2a474: d8a4 bhi.n 2a3c0 <__rtl_fsub_v1_00+0x160> + 2a476: bf38 it cc + 2a478: fa1f fe86 uxthcc.w lr, r6 + 2a47c: d33e bcc.n 2a4fc <__rtl_fsub_v1_00+0x29c> + 2a47e: f04f 4000 mov.w r0, #2147483648 ; 0x80000000 + 2a482: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 2a486: 4276 negs r6, r6 + 2a488: b236 sxth r6, r6 + 2a48a: 2e1f cmp r6, #31 + 2a48c: bfc4 itt gt + 2a48e: 2200 movgt r2, #0 + 2a490: 4610 movgt r0, r2 + 2a492: f73f af24 bgt.w 2a2de <__rtl_fsub_v1_00+0x7e> + 2a496: 4273 negs r3, r6 + 2a498: f003 031f and.w r3, r3, #31 + 2a49c: fa10 f303 lsls.w r3, r0, r3 + 2a4a0: fa20 f006 lsr.w r0, r0, r6 + 2a4a4: bf18 it ne + 2a4a6: f040 0001 orrne.w r0, r0, #1 + 2a4aa: 2200 movs r2, #0 + 2a4ac: e713 b.n 2a2d6 <__rtl_fsub_v1_00+0x76> + 2a4ae: 2900 cmp r1, #0 + 2a4b0: dac0 bge.n 2a434 <__rtl_fsub_v1_00+0x1d4> + 2a4b2: f64f 70ff movw r0, #65535 ; 0xffff + 2a4b6: f6c7 707f movt r0, #32639 ; 0x7f7f + 2a4ba: 07ed lsls r5, r5, #31 + 2a4bc: 4428 add r0, r5 + 2a4be: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 2a4c2: 3100 adds r1, #0 + 2a4c4: bf18 it ne + 2a4c6: 2101 movne r1, #1 + 2a4c8: e778 b.n 2a3bc <__rtl_fsub_v1_00+0x15c> + 2a4ca: 2eff cmp r6, #255 ; 0xff + 2a4cc: d039 beq.n 2a542 <__rtl_fsub_v1_00+0x2e2> + 2a4ce: bb82 cbnz r2, 2a532 <__rtl_fsub_v1_00+0x2d2> + 2a4d0: f10c 0401 add.w r4, ip, #1 + 2a4d4: b2a4 uxth r4, r4 + 2a4d6: 4262 negs r2, r4 + 2a4d8: b292 uxth r2, r2 + 2a4da: b162 cbz r2, 2a4f6 <__rtl_fsub_v1_00+0x296> + 2a4dc: b212 sxth r2, r2 + 2a4de: 2a1f cmp r2, #31 + 2a4e0: dc36 bgt.n 2a550 <__rtl_fsub_v1_00+0x2f0> + 2a4e2: 4250 negs r0, r2 + 2a4e4: f000 001f and.w r0, r0, #31 + 2a4e8: fa13 f000 lsls.w r0, r3, r0 + 2a4ec: fa23 f302 lsr.w r3, r3, r2 + 2a4f0: bf18 it ne + 2a4f2: f043 0301 orrne.w r3, r3, #1 + 2a4f6: 46c6 mov lr, r8 + 2a4f8: f041 4180 orr.w r1, r1, #1073741824 ; 0x40000000 + 2a4fc: 1ac9 subs r1, r1, r3 + 2a4fe: f085 0501 eor.w r5, r5, #1 + 2a502: e75e b.n 2a3c2 <__rtl_fsub_v1_00+0x162> + 2a504: 07e0 lsls r0, r4, #31 + 2a506: f100 40ff add.w r0, r0, #2139095040 ; 0x7f800000 + 2a50a: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 2a50e: eb08 0001 add.w r0, r8, r1 + 2a512: 07e4 lsls r4, r4, #31 + 2a514: eb04 1090 add.w r0, r4, r0, lsr #6 + 2a518: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 2a51c: f048 5800 orr.w r8, r8, #536870912 ; 0x20000000 + 2a520: e714 b.n 2a34c <__rtl_fsub_v1_00+0xec> + 2a522: f118 0800 adds.w r8, r8, #0 + 2a526: bf18 it ne + 2a528: f04f 0801 movne.w r8, #1 + 2a52c: 4666 mov r6, ip + 2a52e: 462a mov r2, r5 + 2a530: e6bf b.n 2a2b2 <__rtl_fsub_v1_00+0x52> + 2a532: f043 4380 orr.w r3, r3, #1073741824 ; 0x40000000 + 2a536: e7ce b.n 2a4d6 <__rtl_fsub_v1_00+0x276> + 2a538: 3100 adds r1, #0 + 2a53a: bf18 it ne + 2a53c: 2101 movne r1, #1 + 2a53e: 2000 movs r0, #0 + 2a540: e778 b.n 2a434 <__rtl_fsub_v1_00+0x1d4> + 2a542: f085 0001 eor.w r0, r5, #1 + 2a546: 07c0 lsls r0, r0, #31 + 2a548: f100 40ff add.w r0, r0, #2139095040 ; 0x7f800000 + 2a54c: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 2a550: 3300 adds r3, #0 + 2a552: bf18 it ne + 2a554: 2301 movne r3, #1 + 2a556: e7ce b.n 2a4f6 <__rtl_fsub_v1_00+0x296> + +0002a558 <__rtl_fmul_v1_00>: + 2a558: b4f0 push {r4, r5, r6, r7} + 2a55a: 0fcf lsrs r7, r1, #31 + 2a55c: f3c0 56c7 ubfx r6, r0, #23, #8 + 2a560: ea87 77d0 eor.w r7, r7, r0, lsr #31 + 2a564: f3c1 0516 ubfx r5, r1, #0, #23 + 2a568: f3c0 0016 ubfx r0, r0, #0, #23 + 2a56c: f3c1 51c7 ubfx r1, r1, #23, #8 + 2a570: b996 cbnz r6, 2a598 <__rtl_fmul_v1_00+0x40> + 2a572: 2800 cmp r0, #0 + 2a574: d060 beq.n 2a638 <__rtl_fmul_v1_00+0xe0> + 2a576: f5b0 3f80 cmp.w r0, #65536 ; 0x10000 + 2a57a: d360 bcc.n 2a63e <__rtl_fmul_v1_00+0xe6> + 2a57c: 4602 mov r2, r0 + 2a57e: 0212 lsls r2, r2, #8 + 2a580: f241 53a0 movw r3, #5536 ; 0x15a0 + 2a584: f2c0 0303 movt r3, #3 + 2a588: 0e12 lsrs r2, r2, #24 + 2a58a: 5c9b ldrb r3, [r3, r2] + 2a58c: 4433 add r3, r6 + 2a58e: b2db uxtb r3, r3 + 2a590: f1c3 0601 rsb r6, r3, #1 + 2a594: 4098 lsls r0, r3 + 2a596: b2b6 uxth r6, r6 + 2a598: 2900 cmp r1, #0 + 2a59a: d02e beq.n 2a5fa <__rtl_fmul_v1_00+0xa2> + 2a59c: 29ff cmp r1, #255 ; 0xff + 2a59e: d05e beq.n 2a65e <__rtl_fmul_v1_00+0x106> + 2a5a0: 2eff cmp r6, #255 ; 0xff + 2a5a2: d03f beq.n 2a624 <__rtl_fmul_v1_00+0xcc> + 2a5a4: f445 0500 orr.w r5, r5, #8388608 ; 0x800000 + 2a5a8: f440 0000 orr.w r0, r0, #8388608 ; 0x800000 + 2a5ac: 01c0 lsls r0, r0, #7 + 2a5ae: 022c lsls r4, r5, #8 + 2a5b0: fba4 4500 umull r4, r5, r4, r0 + 2a5b4: 462a mov r2, r5 + 2a5b6: 3400 adds r4, #0 + 2a5b8: bf18 it ne + 2a5ba: 2401 movne r4, #1 + 2a5bc: 4322 orrs r2, r4 + 2a5be: 1894 adds r4, r2, r2 + 2a5c0: 4431 add r1, r6 + 2a5c2: 2c00 cmp r4, #0 + 2a5c4: b289 uxth r1, r1 + 2a5c6: bfb5 itete lt + 2a5c8: 397f sublt r1, #127 ; 0x7f + 2a5ca: 3980 subge r1, #128 ; 0x80 + 2a5cc: b289 uxthlt r1, r1 + 2a5ce: b289 uxthge r1, r1 + 2a5d0: b28b uxth r3, r1 + 2a5d2: 4620 mov r0, r4 + 2a5d4: bfb8 it lt + 2a5d6: 4610 movlt r0, r2 + 2a5d8: 2bfc cmp r3, #252 ; 0xfc + 2a5da: d905 bls.n 2a5e8 <__rtl_fmul_v1_00+0x90> + 2a5dc: b20a sxth r2, r1 + 2a5de: 2afd cmp r2, #253 ; 0xfd + 2a5e0: dc22 bgt.n 2a628 <__rtl_fmul_v1_00+0xd0> + 2a5e2: d04f beq.n 2a684 <__rtl_fmul_v1_00+0x12c> + 2a5e4: 2a00 cmp r2, #0 + 2a5e6: db3d blt.n 2a664 <__rtl_fmul_v1_00+0x10c> + 2a5e8: 09c0 lsrs r0, r0, #7 + 2a5ea: bf0c ite eq + 2a5ec: 4601 moveq r1, r0 + 2a5ee: 05c9 lslne r1, r1, #23 + 2a5f0: eba0 70c7 sub.w r0, r0, r7, lsl #31 + 2a5f4: 4408 add r0, r1 + 2a5f6: bcf0 pop {r4, r5, r6, r7} + 2a5f8: 4770 bx lr + 2a5fa: b1ed cbz r5, 2a638 <__rtl_fmul_v1_00+0xe0> + 2a5fc: f5b5 3f80 cmp.w r5, #65536 ; 0x10000 + 2a600: d325 bcc.n 2a64e <__rtl_fmul_v1_00+0xf6> + 2a602: 462a mov r2, r5 + 2a604: 0212 lsls r2, r2, #8 + 2a606: f241 53a0 movw r3, #5536 ; 0x15a0 + 2a60a: f2c0 0303 movt r3, #3 + 2a60e: 0e12 lsrs r2, r2, #24 + 2a610: 5c9b ldrb r3, [r3, r2] + 2a612: 2eff cmp r6, #255 ; 0xff + 2a614: 440b add r3, r1 + 2a616: b2db uxtb r3, r3 + 2a618: f1c3 0101 rsb r1, r3, #1 + 2a61c: fa05 f503 lsl.w r5, r5, r3 + 2a620: b289 uxth r1, r1 + 2a622: d1bf bne.n 2a5a4 <__rtl_fmul_v1_00+0x4c> + 2a624: 2800 cmp r0, #0 + 2a626: d1bd bne.n 2a5a4 <__rtl_fmul_v1_00+0x4c> + 2a628: f64f 70ff movw r0, #65535 ; 0xffff + 2a62c: f6c7 707f movt r0, #32639 ; 0x7f7f + 2a630: 07ff lsls r7, r7, #31 + 2a632: 4438 add r0, r7 + 2a634: bcf0 pop {r4, r5, r6, r7} + 2a636: 4770 bx lr + 2a638: 07f8 lsls r0, r7, #31 + 2a63a: bcf0 pop {r4, r5, r6, r7} + 2a63c: 4770 bx lr + 2a63e: 0402 lsls r2, r0, #16 + 2a640: f1b2 7f80 cmp.w r2, #16777216 ; 0x1000000 + 2a644: bf38 it cc + 2a646: 2610 movcc r6, #16 + 2a648: d399 bcc.n 2a57e <__rtl_fmul_v1_00+0x26> + 2a64a: 2608 movs r6, #8 + 2a64c: e798 b.n 2a580 <__rtl_fmul_v1_00+0x28> + 2a64e: 042a lsls r2, r5, #16 + 2a650: f1b2 7f80 cmp.w r2, #16777216 ; 0x1000000 + 2a654: bf38 it cc + 2a656: 2110 movcc r1, #16 + 2a658: d3d4 bcc.n 2a604 <__rtl_fmul_v1_00+0xac> + 2a65a: 2108 movs r1, #8 + 2a65c: e7d3 b.n 2a606 <__rtl_fmul_v1_00+0xae> + 2a65e: 2d00 cmp r5, #0 + 2a660: d19e bne.n 2a5a0 <__rtl_fmul_v1_00+0x48> + 2a662: e7e1 b.n 2a628 <__rtl_fmul_v1_00+0xd0> + 2a664: 425b negs r3, r3 + 2a666: b21b sxth r3, r3 + 2a668: 2b1f cmp r3, #31 + 2a66a: dc0e bgt.n 2a68a <__rtl_fmul_v1_00+0x132> + 2a66c: 425a negs r2, r3 + 2a66e: f002 021f and.w r2, r2, #31 + 2a672: fa10 f202 lsls.w r2, r0, r2 + 2a676: fa20 f003 lsr.w r0, r0, r3 + 2a67a: bf18 it ne + 2a67c: f040 0001 orrne.w r0, r0, #1 + 2a680: 2100 movs r1, #0 + 2a682: e7b1 b.n 2a5e8 <__rtl_fmul_v1_00+0x90> + 2a684: 2800 cmp r0, #0 + 2a686: daaf bge.n 2a5e8 <__rtl_fmul_v1_00+0x90> + 2a688: e7ce b.n 2a628 <__rtl_fmul_v1_00+0xd0> + 2a68a: 3000 adds r0, #0 + 2a68c: bf18 it ne + 2a68e: 2001 movne r0, #1 + 2a690: 2100 movs r1, #0 + 2a692: e7a9 b.n 2a5e8 <__rtl_fmul_v1_00+0x90> + +0002a694 <__rtl_fdiv_v1_00>: + 2a694: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} + 2a698: f3c0 53c7 ubfx r3, r0, #23, #8 + 2a69c: ea4f 78d1 mov.w r8, r1, lsr #31 + 2a6a0: 2bff cmp r3, #255 ; 0xff + 2a6a2: b082 sub sp, #8 + 2a6a4: ea88 78d0 eor.w r8, r8, r0, lsr #31 + 2a6a8: f3c1 52c7 ubfx r2, r1, #23, #8 + 2a6ac: d076 beq.n 2a79c <__rtl_fdiv_v1_00+0x108> + 2a6ae: 2aff cmp r2, #255 ; 0xff + 2a6b0: d07b beq.n 2a7aa <__rtl_fdiv_v1_00+0x116> + 2a6b2: f3c1 0116 ubfx r1, r1, #0, #23 + 2a6b6: b9c2 cbnz r2, 2a6ea <__rtl_fdiv_v1_00+0x56> + 2a6b8: 2900 cmp r1, #0 + 2a6ba: d06f beq.n 2a79c <__rtl_fdiv_v1_00+0x108> + 2a6bc: f5b1 3f80 cmp.w r1, #65536 ; 0x10000 + 2a6c0: f080 8082 bcs.w 2a7c8 <__rtl_fdiv_v1_00+0x134> + 2a6c4: 040d lsls r5, r1, #16 + 2a6c6: f1b5 7f80 cmp.w r5, #16777216 ; 0x1000000 + 2a6ca: bf38 it cc + 2a6cc: 2210 movcc r2, #16 + 2a6ce: d37c bcc.n 2a7ca <__rtl_fdiv_v1_00+0x136> + 2a6d0: 2208 movs r2, #8 + 2a6d2: f241 54a0 movw r4, #5536 ; 0x15a0 + 2a6d6: f2c0 0403 movt r4, #3 + 2a6da: 0e2d lsrs r5, r5, #24 + 2a6dc: 5d64 ldrb r4, [r4, r5] + 2a6de: 4414 add r4, r2 + 2a6e0: b2e4 uxtb r4, r4 + 2a6e2: f1c4 0201 rsb r2, r4, #1 + 2a6e6: 40a1 lsls r1, r4 + 2a6e8: b292 uxth r2, r2 + 2a6ea: f3c0 0016 ubfx r0, r0, #0, #23 + 2a6ee: 2b00 cmp r3, #0 + 2a6f0: d03c beq.n 2a76c <__rtl_fdiv_v1_00+0xd8> + 2a6f2: f441 0100 orr.w r1, r1, #8388608 ; 0x800000 + 2a6f6: ea4f 2901 mov.w r9, r1, lsl #8 + 2a6fa: 1a9b subs r3, r3, r2 + 2a6fc: f440 0000 orr.w r0, r0, #8388608 ; 0x800000 + 2a700: ebb9 2f00 cmp.w r9, r0, lsl #8 + 2a704: b29b uxth r3, r3 + 2a706: ea4f 11c0 mov.w r1, r0, lsl #7 + 2a70a: bf8e itee hi + 2a70c: 337d addhi r3, #125 ; 0x7d + 2a70e: 337e addls r3, #126 ; 0x7e + 2a710: 0849 lsrls r1, r1, #1 + 2a712: f04f 0400 mov.w r4, #0 + 2a716: bf8c ite hi + 2a718: fa1f fa83 uxthhi.w sl, r3 + 2a71c: fa1f fa83 uxthls.w sl, r3 + 2a720: 460a mov r2, r1 + 2a722: 4623 mov r3, r4 + 2a724: 460d mov r5, r1 + 2a726: ea52 0103 orrs.w r1, r2, r3 + 2a72a: e9cd 4500 strd r4, r5, [sp] + 2a72e: bf08 it eq + 2a730: 462e moveq r6, r5 + 2a732: d166 bne.n 2a802 <__rtl_fdiv_v1_00+0x16e> + 2a734: 429d cmp r5, r3 + 2a736: bf08 it eq + 2a738: 4294 cmpeq r4, r2 + 2a73a: bf18 it ne + 2a73c: f046 0601 orrne.w r6, r6, #1 + 2a740: fa1f f38a uxth.w r3, sl + 2a744: 2bfc cmp r3, #252 ; 0xfc + 2a746: d906 bls.n 2a756 <__rtl_fdiv_v1_00+0xc2> + 2a748: fa0f f28a sxth.w r2, sl + 2a74c: 2afd cmp r2, #253 ; 0xfd + 2a74e: dc33 bgt.n 2a7b8 <__rtl_fdiv_v1_00+0x124> + 2a750: d030 beq.n 2a7b4 <__rtl_fdiv_v1_00+0x120> + 2a752: 2a00 cmp r2, #0 + 2a754: db3e blt.n 2a7d4 <__rtl_fdiv_v1_00+0x140> + 2a756: 09f6 lsrs r6, r6, #7 + 2a758: bf0c ite eq + 2a75a: 4630 moveq r0, r6 + 2a75c: ea4f 50ca movne.w r0, sl, lsl #23 + 2a760: eba6 76c8 sub.w r6, r6, r8, lsl #31 + 2a764: 4430 add r0, r6 + 2a766: b002 add sp, #8 + 2a768: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + 2a76c: b1e8 cbz r0, 2a7aa <__rtl_fdiv_v1_00+0x116> + 2a76e: f5b0 3f80 cmp.w r0, #65536 ; 0x10000 + 2a772: d22c bcs.n 2a7ce <__rtl_fdiv_v1_00+0x13a> + 2a774: 0405 lsls r5, r0, #16 + 2a776: f1b5 7f80 cmp.w r5, #16777216 ; 0x1000000 + 2a77a: bf38 it cc + 2a77c: 2310 movcc r3, #16 + 2a77e: d327 bcc.n 2a7d0 <__rtl_fdiv_v1_00+0x13c> + 2a780: 2308 movs r3, #8 + 2a782: f241 54a0 movw r4, #5536 ; 0x15a0 + 2a786: f2c0 0403 movt r4, #3 + 2a78a: 0e2d lsrs r5, r5, #24 + 2a78c: 5d64 ldrb r4, [r4, r5] + 2a78e: 441c add r4, r3 + 2a790: b2e4 uxtb r4, r4 + 2a792: f1c4 0301 rsb r3, r4, #1 + 2a796: 40a0 lsls r0, r4 + 2a798: b29b uxth r3, r3 + 2a79a: e7aa b.n 2a6f2 <__rtl_fdiv_v1_00+0x5e> + 2a79c: ea4f 78c8 mov.w r8, r8, lsl #31 + 2a7a0: f108 40ff add.w r0, r8, #2139095040 ; 0x7f800000 + 2a7a4: b002 add sp, #8 + 2a7a6: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + 2a7aa: ea4f 70c8 mov.w r0, r8, lsl #31 + 2a7ae: b002 add sp, #8 + 2a7b0: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + 2a7b4: 2e00 cmp r6, #0 + 2a7b6: dace bge.n 2a756 <__rtl_fdiv_v1_00+0xc2> + 2a7b8: f64f 70ff movw r0, #65535 ; 0xffff + 2a7bc: f6c7 707f movt r0, #32639 ; 0x7f7f + 2a7c0: ea4f 78c8 mov.w r8, r8, lsl #31 + 2a7c4: 4440 add r0, r8 + 2a7c6: e7ed b.n 2a7a4 <__rtl_fdiv_v1_00+0x110> + 2a7c8: 460d mov r5, r1 + 2a7ca: 022d lsls r5, r5, #8 + 2a7cc: e781 b.n 2a6d2 <__rtl_fdiv_v1_00+0x3e> + 2a7ce: 4605 mov r5, r0 + 2a7d0: 022d lsls r5, r5, #8 + 2a7d2: e7d6 b.n 2a782 <__rtl_fdiv_v1_00+0xee> + 2a7d4: 425b negs r3, r3 + 2a7d6: b21b sxth r3, r3 + 2a7d8: 2b1f cmp r3, #31 + 2a7da: dc0c bgt.n 2a7f6 <__rtl_fdiv_v1_00+0x162> + 2a7dc: 425a negs r2, r3 + 2a7de: f002 021f and.w r2, r2, #31 + 2a7e2: fa16 f202 lsls.w r2, r6, r2 + 2a7e6: fa26 f603 lsr.w r6, r6, r3 + 2a7ea: bf18 it ne + 2a7ec: f046 0601 orrne.w r6, r6, #1 + 2a7f0: f04f 0a00 mov.w sl, #0 + 2a7f4: e7af b.n 2a756 <__rtl_fdiv_v1_00+0xc2> + 2a7f6: 3600 adds r6, #0 + 2a7f8: bf18 it ne + 2a7fa: 2601 movne r6, #1 + 2a7fc: f04f 0a00 mov.w sl, #0 + 2a800: e7a9 b.n 2a756 <__rtl_fdiv_v1_00+0xc2> + 2a802: 4649 mov r1, r9 + 2a804: 4668 mov r0, sp + 2a806: f7fe ff97 bl 29738 <__rtl_div64_32> + 2a80a: e9dd 6700 ldrd r6, r7, [sp] + 2a80e: 2300 movs r3, #0 + 2a810: f006 023f and.w r2, r6, #63 ; 0x3f + 2a814: ea52 0103 orrs.w r1, r2, r3 + 2a818: d192 bne.n 2a740 <__rtl_fdiv_v1_00+0xac> + 2a81a: fba9 2306 umull r2, r3, r9, r6 + 2a81e: fb09 3307 mla r3, r9, r7, r3 + 2a822: e787 b.n 2a734 <__rtl_fdiv_v1_00+0xa0> + +0002a824 <__rtl_dadd_v1_00>: + 2a824: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 2a828: b087 sub sp, #28 + 2a82a: e9cd 0104 strd r0, r1, [sp, #16] + 2a82e: e9dd ab04 ldrd sl, fp, [sp, #16] + 2a832: ea4f 74db mov.w r4, fp, lsr #31 + 2a836: fa5f fe84 uxtb.w lr, r4 + 2a83a: ebbe 7fd3 cmp.w lr, r3, lsr #31 + 2a83e: 4690 mov r8, r2 + 2a840: 4699 mov r9, r3 + 2a842: f000 815c beq.w 2aafe <__rtl_dadd_v1_00+0x2da> + 2a846: f64f 73ff movw r3, #65535 ; 0xffff + 2a84a: f2c0 030f movt r3, #15 + 2a84e: f04f 32ff mov.w r2, #4294967295 + 2a852: ea08 0002 and.w r0, r8, r2 + 2a856: ea09 0103 and.w r1, r9, r3 + 2a85a: ea0b 0703 and.w r7, fp, r3 + 2a85e: f3c9 590a ubfx r9, r9, #20, #11 + 2a862: f3cb 530a ubfx r3, fp, #20, #11 + 2a866: e9cd 0102 strd r0, r1, [sp, #8] + 2a86a: fa1f f883 uxth.w r8, r3 + 2a86e: fa1f f189 uxth.w r1, r9 + 2a872: ea0a 0602 and.w r6, sl, r2 + 2a876: ebc1 0a08 rsb sl, r1, r8 + 2a87a: f8dd b00c ldr.w fp, [sp, #12] + 2a87e: fa1f fa8a uxth.w sl, sl + 2a882: fa1f f28a uxth.w r2, sl + 2a886: 9101 str r1, [sp, #4] + 2a888: fa0f fc82 sxth.w ip, r2 + 2a88c: ea4f 218b mov.w r1, fp, lsl #10 + 2a890: f8dd b008 ldr.w fp, [sp, #8] + 2a894: 02bd lsls r5, r7, #10 + 2a896: f1bc 0f00 cmp.w ip, #0 + 2a89a: ea45 5596 orr.w r5, r5, r6, lsr #22 + 2a89e: ea41 519b orr.w r1, r1, fp, lsr #22 + 2a8a2: ea4f 2486 mov.w r4, r6, lsl #10 + 2a8a6: ea4f 208b mov.w r0, fp, lsl #10 + 2a8aa: f340 80a7 ble.w 2a9fc <__rtl_dadd_v1_00+0x1d8> + 2a8ae: f240 72ff movw r2, #2047 ; 0x7ff + 2a8b2: 4293 cmp r3, r2 + 2a8b4: f000 80d4 beq.w 2aa60 <__rtl_dadd_v1_00+0x23c> + 2a8b8: f1b9 0f00 cmp.w r9, #0 + 2a8bc: d16c bne.n 2a998 <__rtl_dadd_v1_00+0x174> + 2a8be: f10a 32ff add.w r2, sl, #4294967295 + 2a8c2: b292 uxth r2, r2 + 2a8c4: fa0f fc82 sxth.w ip, r2 + 2a8c8: 2a00 cmp r2, #0 + 2a8ca: d167 bne.n 2a99c <__rtl_dadd_v1_00+0x178> + 2a8cc: f045 4580 orr.w r5, r5, #1073741824 ; 0x40000000 + 2a8d0: 1a20 subs r0, r4, r0 + 2a8d2: eb65 0101 sbc.w r1, r5, r1 + 2a8d6: f241 55a0 movw r5, #5536 ; 0x15a0 + 2a8da: 2901 cmp r1, #1 + 2a8dc: bf08 it eq + 2a8de: 2800 cmpeq r0, #0 + 2a8e0: bf2c ite cs + 2a8e2: 460c movcs r4, r1 + 2a8e4: 4604 movcc r4, r0 + 2a8e6: f2c0 0503 movt r5, #3 + 2a8ea: f240 77fc movw r7, #2044 ; 0x7fc + 2a8ee: bf2c ite cs + 2a8f0: f04f 0cff movcs.w ip, #255 ; 0xff + 2a8f4: f04f 0c1f movcc.w ip, #31 + 2a8f8: f5b4 3f80 cmp.w r4, #65536 ; 0x10000 + 2a8fc: bf3a itte cc + 2a8fe: 0424 lslcc r4, r4, #16 + 2a900: 2610 movcc r6, #16 + 2a902: 2600 movcs r6, #0 + 2a904: f1b4 7f80 cmp.w r4, #16777216 ; 0x1000000 + 2a908: bf3c itt cc + 2a90a: 0224 lslcc r4, r4, #8 + 2a90c: 3608 addcc r6, #8 + 2a90e: ea4f 6414 mov.w r4, r4, lsr #24 + 2a912: bf38 it cc + 2a914: b2f6 uxtbcc r6, r6 + 2a916: 5d2d ldrb r5, [r5, r4] + 2a918: eb06 040c add.w r4, r6, ip + 2a91c: 442c add r4, r5 + 2a91e: b2e4 uxtb r4, r4 + 2a920: f108 38ff add.w r8, r8, #4294967295 + 2a924: fa1f f888 uxth.w r8, r8 + 2a928: f1a4 0520 sub.w r5, r4, #32 + 2a92c: fa00 f505 lsl.w r5, r0, r5 + 2a930: fa01 f304 lsl.w r3, r1, r4 + 2a934: ebc4 0808 rsb r8, r4, r8 + 2a938: 432b orrs r3, r5 + 2a93a: f1c4 0120 rsb r1, r4, #32 + 2a93e: fa1f f588 uxth.w r5, r8 + 2a942: fa20 f101 lsr.w r1, r0, r1 + 2a946: 42bd cmp r5, r7 + 2a948: ea43 0301 orr.w r3, r3, r1 + 2a94c: fa00 f204 lsl.w r2, r0, r4 + 2a950: b2ae uxth r6, r5 + 2a952: d90a bls.n 2a96a <__rtl_dadd_v1_00+0x146> + 2a954: f240 70fe movw r0, #2046 ; 0x7fe + 2a958: b231 sxth r1, r6 + 2a95a: 4281 cmp r1, r0 + 2a95c: d06a beq.n 2aa34 <__rtl_dadd_v1_00+0x210> + 2a95e: 3801 subs r0, #1 + 2a960: 4281 cmp r1, r0 + 2a962: d063 beq.n 2aa2c <__rtl_dadd_v1_00+0x208> + 2a964: 2900 cmp r1, #0 + 2a966: f2c0 81c8 blt.w 2acfa <__rtl_dadd_v1_00+0x4d6> + 2a96a: 0a90 lsrs r0, r2, #10 + 2a96c: ea40 5083 orr.w r0, r0, r3, lsl #22 + 2a970: 0a99 lsrs r1, r3, #10 + 2a972: ea50 0b01 orrs.w fp, r0, r1 + 2a976: bf04 itt eq + 2a978: 4604 moveq r4, r0 + 2a97a: 460d moveq r5, r1 + 2a97c: f04f 0200 mov.w r2, #0 + 2a980: bf1c itt ne + 2a982: 0535 lslne r5, r6, #20 + 2a984: 2400 movne r4, #0 + 2a986: ea4f 73ce mov.w r3, lr, lsl #31 + 2a98a: 1880 adds r0, r0, r2 + 2a98c: 4159 adcs r1, r3 + 2a98e: 1900 adds r0, r0, r4 + 2a990: 4169 adcs r1, r5 + 2a992: b007 add sp, #28 + 2a994: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 2a998: f041 4180 orr.w r1, r1, #1073741824 ; 0x40000000 + 2a99c: f1bc 0f3f cmp.w ip, #63 ; 0x3f + 2a9a0: dc56 bgt.n 2aa50 <__rtl_dadd_v1_00+0x22c> + 2a9a2: f1cc 0700 rsb r7, ip, #0 + 2a9a6: f007 073f and.w r7, r7, #63 ; 0x3f + 2a9aa: f1a7 0a20 sub.w sl, r7, #32 + 2a9ae: fa01 f607 lsl.w r6, r1, r7 + 2a9b2: fa00 fa0a lsl.w sl, r0, sl + 2a9b6: f1c7 0920 rsb r9, r7, #32 + 2a9ba: fa20 f909 lsr.w r9, r0, r9 + 2a9be: ea46 060a orr.w r6, r6, sl + 2a9c2: ea46 0609 orr.w r6, r6, r9 + 2a9c6: f1cc 0920 rsb r9, ip, #32 + 2a9ca: fa00 f707 lsl.w r7, r0, r7 + 2a9ce: fa20 f20c lsr.w r2, r0, ip + 2a9d2: fa01 f909 lsl.w r9, r1, r9 + 2a9d6: f1ac 0020 sub.w r0, ip, #32 + 2a9da: 433e orrs r6, r7 + 2a9dc: fa21 f000 lsr.w r0, r1, r0 + 2a9e0: ea42 0209 orr.w r2, r2, r9 + 2a9e4: bf14 ite ne + 2a9e6: 2601 movne r6, #1 + 2a9e8: 2600 moveq r6, #0 + 2a9ea: 4302 orrs r2, r0 + 2a9ec: 2700 movs r7, #0 + 2a9ee: fa21 f30c lsr.w r3, r1, ip + 2a9f2: ea46 0002 orr.w r0, r6, r2 + 2a9f6: ea47 0103 orr.w r1, r7, r3 + 2a9fa: e767 b.n 2a8cc <__rtl_dadd_v1_00+0xa8> + 2a9fc: bbaa cbnz r2, 2aa6a <__rtl_dadd_v1_00+0x246> + 2a9fe: b913 cbnz r3, 2aa06 <__rtl_dadd_v1_00+0x1e2> + 2aa00: f04f 0901 mov.w r9, #1 + 2aa04: 464b mov r3, r9 + 2aa06: 42a9 cmp r1, r5 + 2aa08: bf08 it eq + 2aa0a: 42a0 cmpeq r0, r4 + 2aa0c: bf38 it cc + 2aa0e: fa1f f883 uxthcc.w r8, r3 + 2aa12: f4ff af5d bcc.w 2a8d0 <__rtl_dadd_v1_00+0xac> + 2aa16: 428d cmp r5, r1 + 2aa18: bf08 it eq + 2aa1a: 4284 cmpeq r4, r0 + 2aa1c: bf38 it cc + 2aa1e: fa1f f889 uxthcc.w r8, r9 + 2aa22: d366 bcc.n 2aaf2 <__rtl_dadd_v1_00+0x2ce> + 2aa24: 2000 movs r0, #0 + 2aa26: f04f 4100 mov.w r1, #2147483648 ; 0x80000000 + 2aa2a: e7b2 b.n 2a992 <__rtl_dadd_v1_00+0x16e> + 2aa2c: 2a00 cmp r2, #0 + 2aa2e: f173 0700 sbcs.w r7, r3, #0 + 2aa32: da9a bge.n 2a96a <__rtl_dadd_v1_00+0x146> + 2aa34: f64f 71ff movw r1, #65535 ; 0xffff + 2aa38: f6c7 71ef movt r1, #32751 ; 0x7fef + 2aa3c: 2200 movs r2, #0 + 2aa3e: f04f 30ff mov.w r0, #4294967295 + 2aa42: 1880 adds r0, r0, r2 + 2aa44: ea4f 73ce mov.w r3, lr, lsl #31 + 2aa48: 4159 adcs r1, r3 + 2aa4a: b007 add sp, #28 + 2aa4c: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 2aa50: ea50 0201 orrs.w r2, r0, r1 + 2aa54: bf14 ite ne + 2aa56: 2001 movne r0, #1 + 2aa58: 2000 moveq r0, #0 + 2aa5a: b2c0 uxtb r0, r0 + 2aa5c: 2100 movs r1, #0 + 2aa5e: e735 b.n 2a8cc <__rtl_dadd_v1_00+0xa8> + 2aa60: e9dd 0104 ldrd r0, r1, [sp, #16] + 2aa64: b007 add sp, #28 + 2aa66: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 2aa6a: f240 76ff movw r6, #2047 ; 0x7ff + 2aa6e: 45b1 cmp r9, r6 + 2aa70: f000 81d5 beq.w 2ae1e <__rtl_dadd_v1_00+0x5fa> + 2aa74: 2b00 cmp r3, #0 + 2aa76: f040 81e1 bne.w 2ae3c <__rtl_dadd_v1_00+0x618> + 2aa7a: f10a 0201 add.w r2, sl, #1 + 2aa7e: b292 uxth r2, r2 + 2aa80: 4252 negs r2, r2 + 2aa82: b292 uxth r2, r2 + 2aa84: b38a cbz r2, 2aaea <__rtl_dadd_v1_00+0x2c6> + 2aa86: fa0f fc82 sxth.w ip, r2 + 2aa8a: f1bc 0f3f cmp.w ip, #63 ; 0x3f + 2aa8e: f300 81ed bgt.w 2ae6c <__rtl_dadd_v1_00+0x648> + 2aa92: f1cc 0700 rsb r7, ip, #0 + 2aa96: f007 073f and.w r7, r7, #63 ; 0x3f + 2aa9a: f1a7 0920 sub.w r9, r7, #32 + 2aa9e: fa05 f607 lsl.w r6, r5, r7 + 2aaa2: fa04 f909 lsl.w r9, r4, r9 + 2aaa6: f1c7 0820 rsb r8, r7, #32 + 2aaaa: fa24 f808 lsr.w r8, r4, r8 + 2aaae: ea46 0609 orr.w r6, r6, r9 + 2aab2: ea46 0608 orr.w r6, r6, r8 + 2aab6: f1cc 0820 rsb r8, ip, #32 + 2aaba: fa04 f707 lsl.w r7, r4, r7 + 2aabe: fa24 f20c lsr.w r2, r4, ip + 2aac2: fa05 f808 lsl.w r8, r5, r8 + 2aac6: f1ac 0420 sub.w r4, ip, #32 + 2aaca: 433e orrs r6, r7 + 2aacc: fa25 f404 lsr.w r4, r5, r4 + 2aad0: ea42 0208 orr.w r2, r2, r8 + 2aad4: bf14 ite ne + 2aad6: 2601 movne r6, #1 + 2aad8: 2600 moveq r6, #0 + 2aada: 4322 orrs r2, r4 + 2aadc: 2700 movs r7, #0 + 2aade: fa25 f30c lsr.w r3, r5, ip + 2aae2: ea46 0402 orr.w r4, r6, r2 + 2aae6: ea47 0503 orr.w r5, r7, r3 + 2aaea: f8dd 8004 ldr.w r8, [sp, #4] + 2aaee: f041 4180 orr.w r1, r1, #1073741824 ; 0x40000000 + 2aaf2: 1b00 subs r0, r0, r4 + 2aaf4: eb61 0105 sbc.w r1, r1, r5 + 2aaf8: f08e 0e01 eor.w lr, lr, #1 + 2aafc: e6eb b.n 2a8d6 <__rtl_dadd_v1_00+0xb2> + 2aafe: f64f 71ff movw r1, #65535 ; 0xffff + 2ab02: f2c0 010f movt r1, #15 + 2ab06: f04f 30ff mov.w r0, #4294967295 + 2ab0a: ea08 0600 and.w r6, r8, r0 + 2ab0e: ea09 0701 and.w r7, r9, r1 + 2ab12: e9cd 6704 strd r6, r7, [sp, #16] + 2ab16: f3cb 550a ubfx r5, fp, #20, #11 + 2ab1a: f3c9 570a ubfx r7, r9, #20, #11 + 2ab1e: fa1f f987 uxth.w r9, r7 + 2ab22: ea01 010b and.w r1, r1, fp + 2ab26: fa1f fc85 uxth.w ip, r5 + 2ab2a: ea4f 2e41 mov.w lr, r1, lsl #9 + 2ab2e: 2200 movs r2, #0 + 2ab30: 2300 movs r3, #0 + 2ab32: ebc9 080c rsb r8, r9, ip + 2ab36: f8cd 9004 str.w r9, [sp, #4] + 2ab3a: f8dd 9014 ldr.w r9, [sp, #20] + 2ab3e: e9cd 2302 strd r2, r3, [sp, #8] + 2ab42: f8cd e00c str.w lr, [sp, #12] + 2ab46: ea4f 2349 mov.w r3, r9, lsl #9 + 2ab4a: f8dd 900c ldr.w r9, [sp, #12] + 2ab4e: ea00 000a and.w r0, r0, sl + 2ab52: ea49 59d0 orr.w r9, r9, r0, lsr #23 + 2ab56: fa1f f888 uxth.w r8, r8 + 2ab5a: f8cd 900c str.w r9, [sp, #12] + 2ab5e: f8dd 9010 ldr.w r9, [sp, #16] + 2ab62: fa1f f688 uxth.w r6, r8 + 2ab66: fa0f fe86 sxth.w lr, r6 + 2ab6a: ea43 53d9 orr.w r3, r3, r9, lsr #23 + 2ab6e: ea4f 2940 mov.w r9, r0, lsl #9 + 2ab72: 9804 ldr r0, [sp, #16] + 2ab74: f1be 0f00 cmp.w lr, #0 + 2ab78: f8cd 9008 str.w r9, [sp, #8] + 2ab7c: ea4f 2240 mov.w r2, r0, lsl #9 + 2ab80: f240 71ff movw r1, #2047 ; 0x7ff + 2ab84: f340 80a8 ble.w 2acd8 <__rtl_dadd_v1_00+0x4b4> + 2ab88: 428d cmp r5, r1 + 2ab8a: f000 8154 beq.w 2ae36 <__rtl_dadd_v1_00+0x612> + 2ab8e: 2f00 cmp r7, #0 + 2ab90: d170 bne.n 2ac74 <__rtl_dadd_v1_00+0x450> + 2ab92: f108 36ff add.w r6, r8, #4294967295 + 2ab96: b2b6 uxth r6, r6 + 2ab98: 2e00 cmp r6, #0 + 2ab9a: f040 8199 bne.w 2aed0 <__rtl_dadd_v1_00+0x6ac> + 2ab9e: e9dd 0102 ldrd r0, r1, [sp, #8] + 2aba2: 1812 adds r2, r2, r0 + 2aba4: f041 5100 orr.w r1, r1, #536870912 ; 0x20000000 + 2aba8: 414b adcs r3, r1 + 2abaa: 1890 adds r0, r2, r2 + 2abac: eb43 0103 adc.w r1, r3, r3 + 2abb0: 2800 cmp r0, #0 + 2abb2: f171 0600 sbcs.w r6, r1, #0 + 2abb6: bfb9 ittee lt + 2abb8: 4610 movlt r0, r2 + 2abba: 4619 movlt r1, r3 + 2abbc: f10c 3cff addge.w ip, ip, #4294967295 + 2abc0: fa1f fc8c uxthge.w ip, ip + 2abc4: bfa8 it ge + 2abc6: fa1f f58c uxthge.w r5, ip + 2abca: f240 73fc movw r3, #2044 ; 0x7fc + 2abce: 459c cmp ip, r3 + 2abd0: d93a bls.n 2ac48 <__rtl_dadd_v1_00+0x424> + 2abd2: f240 72fe movw r2, #2046 ; 0x7fe + 2abd6: b22b sxth r3, r5 + 2abd8: 4293 cmp r3, r2 + 2abda: f000 80c8 beq.w 2ad6e <__rtl_dadd_v1_00+0x54a> + 2abde: 3301 adds r3, #1 + 2abe0: d132 bne.n 2ac48 <__rtl_dadd_v1_00+0x424> + 2abe2: f1cc 0500 rsb r5, ip, #0 + 2abe6: b22d sxth r5, r5 + 2abe8: 2d3f cmp r5, #63 ; 0x3f + 2abea: f300 8147 bgt.w 2ae7c <__rtl_dadd_v1_00+0x658> + 2abee: 426f negs r7, r5 + 2abf0: f007 073f and.w r7, r7, #63 ; 0x3f + 2abf4: f1a7 0c20 sub.w ip, r7, #32 + 2abf8: fa01 f607 lsl.w r6, r1, r7 + 2abfc: fa00 fc0c lsl.w ip, r0, ip + 2ac00: f1c7 0e20 rsb lr, r7, #32 + 2ac04: fa20 fe0e lsr.w lr, r0, lr + 2ac08: ea46 060c orr.w r6, r6, ip + 2ac0c: ea46 060e orr.w r6, r6, lr + 2ac10: fa00 f707 lsl.w r7, r0, r7 + 2ac14: 433e orrs r6, r7 + 2ac16: f04f 0700 mov.w r7, #0 + 2ac1a: fa20 f205 lsr.w r2, r0, r5 + 2ac1e: f1c5 0e20 rsb lr, r5, #32 + 2ac22: f1a5 0020 sub.w r0, r5, #32 + 2ac26: fa21 f305 lsr.w r3, r1, r5 + 2ac2a: 463d mov r5, r7 + 2ac2c: fa01 fe0e lsl.w lr, r1, lr + 2ac30: fa21 f000 lsr.w r0, r1, r0 + 2ac34: ea42 020e orr.w r2, r2, lr + 2ac38: bf14 ite ne + 2ac3a: 2601 movne r6, #1 + 2ac3c: 2600 moveq r6, #0 + 2ac3e: 4302 orrs r2, r0 + 2ac40: ea46 0002 orr.w r0, r6, r2 + 2ac44: ea47 0103 orr.w r1, r7, r3 + 2ac48: 0a86 lsrs r6, r0, #10 + 2ac4a: ea46 5681 orr.w r6, r6, r1, lsl #22 + 2ac4e: 0a8f lsrs r7, r1, #10 + 2ac50: ea56 0907 orrs.w r9, r6, r7 + 2ac54: bf1c itt ne + 2ac56: 0529 lslne r1, r5, #20 + 2ac58: 2000 movne r0, #0 + 2ac5a: d101 bne.n 2ac60 <__rtl_dadd_v1_00+0x43c> + 2ac5c: 4630 mov r0, r6 + 2ac5e: 4639 mov r1, r7 + 2ac60: 1980 adds r0, r0, r6 + 2ac62: f04f 0200 mov.w r2, #0 + 2ac66: 4179 adcs r1, r7 + 2ac68: 07e3 lsls r3, r4, #31 + 2ac6a: 1880 adds r0, r0, r2 + 2ac6c: 4159 adcs r1, r3 + 2ac6e: b007 add sp, #28 + 2ac70: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 2ac74: f043 5300 orr.w r3, r3, #536870912 ; 0x20000000 + 2ac78: f1be 0f3f cmp.w lr, #63 ; 0x3f + 2ac7c: dc6f bgt.n 2ad5e <__rtl_dadd_v1_00+0x53a> + 2ac7e: f1ce 0700 rsb r7, lr, #0 + 2ac82: f007 073f and.w r7, r7, #63 ; 0x3f + 2ac86: f1a7 0920 sub.w r9, r7, #32 + 2ac8a: fa03 f607 lsl.w r6, r3, r7 + 2ac8e: fa02 f909 lsl.w r9, r2, r9 + 2ac92: f1c7 0820 rsb r8, r7, #32 + 2ac96: fa22 f808 lsr.w r8, r2, r8 + 2ac9a: ea46 0609 orr.w r6, r6, r9 + 2ac9e: ea46 0608 orr.w r6, r6, r8 + 2aca2: f1ce 0820 rsb r8, lr, #32 + 2aca6: fa02 f707 lsl.w r7, r2, r7 + 2acaa: fa22 f00e lsr.w r0, r2, lr + 2acae: fa03 f808 lsl.w r8, r3, r8 + 2acb2: f1ae 0220 sub.w r2, lr, #32 + 2acb6: 433e orrs r6, r7 + 2acb8: fa23 f202 lsr.w r2, r3, r2 + 2acbc: ea40 0008 orr.w r0, r0, r8 + 2acc0: bf14 ite ne + 2acc2: 2601 movne r6, #1 + 2acc4: 2600 moveq r6, #0 + 2acc6: 4310 orrs r0, r2 + 2acc8: 2700 movs r7, #0 + 2acca: fa23 f10e lsr.w r1, r3, lr + 2acce: ea46 0200 orr.w r2, r6, r0 + 2acd2: ea47 0301 orr.w r3, r7, r1 + 2acd6: e762 b.n 2ab9e <__rtl_dadd_v1_00+0x37a> + 2acd8: 2e00 cmp r6, #0 + 2acda: d153 bne.n 2ad84 <__rtl_dadd_v1_00+0x560> + 2acdc: b228 sxth r0, r5 + 2acde: 4288 cmp r0, r1 + 2ace0: f000 80a9 beq.w 2ae36 <__rtl_dadd_v1_00+0x612> + 2ace4: 2d00 cmp r5, #0 + 2ace6: f000 80ac beq.w 2ae42 <__rtl_dadd_v1_00+0x61e> + 2acea: e9dd 0102 ldrd r0, r1, [sp, #8] + 2acee: 3200 adds r2, #0 + 2acf0: f143 4380 adc.w r3, r3, #1073741824 ; 0x40000000 + 2acf4: 1880 adds r0, r0, r2 + 2acf6: 4159 adcs r1, r3 + 2acf8: e767 b.n 2abca <__rtl_dadd_v1_00+0x3a6> + 2acfa: 426d negs r5, r5 + 2acfc: b22e sxth r6, r5 + 2acfe: 2e3f cmp r6, #63 ; 0x3f + 2ad00: f300 80ab bgt.w 2ae5a <__rtl_dadd_v1_00+0x636> + 2ad04: 4275 negs r5, r6 + 2ad06: f005 053f and.w r5, r5, #63 ; 0x3f + 2ad0a: f1a5 0c20 sub.w ip, r5, #32 + 2ad0e: fa03 f405 lsl.w r4, r3, r5 + 2ad12: fa02 fc0c lsl.w ip, r2, ip + 2ad16: f1c5 0720 rsb r7, r5, #32 + 2ad1a: fa22 f707 lsr.w r7, r2, r7 + 2ad1e: ea44 040c orr.w r4, r4, ip + 2ad22: 433c orrs r4, r7 + 2ad24: f1c6 0720 rsb r7, r6, #32 + 2ad28: fa02 f505 lsl.w r5, r2, r5 + 2ad2c: fa22 f006 lsr.w r0, r2, r6 + 2ad30: fa03 f707 lsl.w r7, r3, r7 + 2ad34: f1a6 0220 sub.w r2, r6, #32 + 2ad38: 432c orrs r4, r5 + 2ad3a: fa23 f202 lsr.w r2, r3, r2 + 2ad3e: ea40 0007 orr.w r0, r0, r7 + 2ad42: f04f 0500 mov.w r5, #0 + 2ad46: fa23 f106 lsr.w r1, r3, r6 + 2ad4a: bf14 ite ne + 2ad4c: 2401 movne r4, #1 + 2ad4e: 2400 moveq r4, #0 + 2ad50: 4310 orrs r0, r2 + 2ad52: ea44 0200 orr.w r2, r4, r0 + 2ad56: ea45 0301 orr.w r3, r5, r1 + 2ad5a: 462e mov r6, r5 + 2ad5c: e605 b.n 2a96a <__rtl_dadd_v1_00+0x146> + 2ad5e: ea52 0103 orrs.w r1, r2, r3 + 2ad62: bf14 ite ne + 2ad64: 2201 movne r2, #1 + 2ad66: 2200 moveq r2, #0 + 2ad68: b2d2 uxtb r2, r2 + 2ad6a: 2300 movs r3, #0 + 2ad6c: e717 b.n 2ab9e <__rtl_dadd_v1_00+0x37a> + 2ad6e: f64f 71ff movw r1, #65535 ; 0xffff + 2ad72: f6c7 71ef movt r1, #32751 ; 0x7fef + 2ad76: f04f 30ff mov.w r0, #4294967295 + 2ad7a: 2200 movs r2, #0 + 2ad7c: 07e3 lsls r3, r4, #31 + 2ad7e: 1880 adds r0, r0, r2 + 2ad80: 4159 adcs r1, r3 + 2ad82: e606 b.n 2a992 <__rtl_dadd_v1_00+0x16e> + 2ad84: 428f cmp r7, r1 + 2ad86: f000 8089 beq.w 2ae9c <__rtl_dadd_v1_00+0x678> + 2ad8a: 2d00 cmp r5, #0 + 2ad8c: d17f bne.n 2ae8e <__rtl_dadd_v1_00+0x66a> + 2ad8e: f108 0601 add.w r6, r8, #1 + 2ad92: b2b6 uxth r6, r6 + 2ad94: 4271 negs r1, r6 + 2ad96: b289 uxth r1, r1 + 2ad98: 2900 cmp r1, #0 + 2ad9a: d074 beq.n 2ae86 <__rtl_dadd_v1_00+0x662> + 2ad9c: b20d sxth r5, r1 + 2ad9e: 2d3f cmp r5, #63 ; 0x3f + 2ada0: f300 8085 bgt.w 2aeae <__rtl_dadd_v1_00+0x68a> + 2ada4: f8dd b008 ldr.w fp, [sp, #8] + 2ada8: f1c5 0e00 rsb lr, r5, #0 + 2adac: f8dd 900c ldr.w r9, [sp, #12] + 2adb0: f00e 0e3f and.w lr, lr, #63 ; 0x3f + 2adb4: 9902 ldr r1, [sp, #8] + 2adb6: 4658 mov r0, fp + 2adb8: f1ae 0820 sub.w r8, lr, #32 + 2adbc: fa01 f808 lsl.w r8, r1, r8 + 2adc0: 4649 mov r1, r9 + 2adc2: fa09 f60e lsl.w r6, r9, lr + 2adc6: f1ce 0c20 rsb ip, lr, #32 + 2adca: fa2b fc0c lsr.w ip, fp, ip + 2adce: ea46 0608 orr.w r6, r6, r8 + 2add2: ea46 060c orr.w r6, r6, ip + 2add6: fa0b fe0e lsl.w lr, fp, lr + 2adda: ea5e 0606 orrs.w r6, lr, r6 + 2adde: f1c5 0e20 rsb lr, r5, #32 + 2ade2: fa20 f005 lsr.w r0, r0, r5 + 2ade6: f1a5 0620 sub.w r6, r5, #32 + 2adea: fa09 fe0e lsl.w lr, r9, lr + 2adee: fa29 f606 lsr.w r6, r9, r6 + 2adf2: ea40 000e orr.w r0, r0, lr + 2adf6: fa21 f105 lsr.w r1, r1, r5 + 2adfa: bf14 ite ne + 2adfc: f04f 0a01 movne.w sl, #1 + 2ae00: f04f 0a00 moveq.w sl, #0 + 2ae04: 4330 orrs r0, r6 + 2ae06: f04f 0b00 mov.w fp, #0 + 2ae0a: 463d mov r5, r7 + 2ae0c: ea4a 0600 orr.w r6, sl, r0 + 2ae10: ea4b 0701 orr.w r7, fp, r1 + 2ae14: f8dd c004 ldr.w ip, [sp, #4] + 2ae18: e9cd 6702 strd r6, r7, [sp, #8] + 2ae1c: e6bf b.n 2ab9e <__rtl_dadd_v1_00+0x37a> + 2ae1e: 2100 movs r1, #0 + 2ae20: f6c7 71f0 movt r1, #32752 ; 0x7ff0 + 2ae24: 2000 movs r0, #0 + 2ae26: f08e 0e01 eor.w lr, lr, #1 + 2ae2a: 2200 movs r2, #0 + 2ae2c: ea4f 73ce mov.w r3, lr, lsl #31 + 2ae30: 1880 adds r0, r0, r2 + 2ae32: 4159 adcs r1, r3 + 2ae34: e5ad b.n 2a992 <__rtl_dadd_v1_00+0x16e> + 2ae36: 4650 mov r0, sl + 2ae38: 4659 mov r1, fp + 2ae3a: e5aa b.n 2a992 <__rtl_dadd_v1_00+0x16e> + 2ae3c: f045 4580 orr.w r5, r5, #1073741824 ; 0x40000000 + 2ae40: e61e b.n 2aa80 <__rtl_dadd_v1_00+0x25c> + 2ae42: e9dd 0102 ldrd r0, r1, [sp, #8] + 2ae46: 1812 adds r2, r2, r0 + 2ae48: 414b adcs r3, r1 + 2ae4a: 0a56 lsrs r6, r2, #9 + 2ae4c: ea46 56c3 orr.w r6, r6, r3, lsl #23 + 2ae50: 07e1 lsls r1, r4, #31 + 2ae52: 0a5f lsrs r7, r3, #9 + 2ae54: 19a8 adds r0, r5, r6 + 2ae56: 4179 adcs r1, r7 + 2ae58: e59b b.n 2a992 <__rtl_dadd_v1_00+0x16e> + 2ae5a: ea52 0903 orrs.w r9, r2, r3 + 2ae5e: bf14 ite ne + 2ae60: 2201 movne r2, #1 + 2ae62: 2200 moveq r2, #0 + 2ae64: b2d2 uxtb r2, r2 + 2ae66: 2300 movs r3, #0 + 2ae68: 2600 movs r6, #0 + 2ae6a: e57e b.n 2a96a <__rtl_dadd_v1_00+0x146> + 2ae6c: ea54 0c05 orrs.w ip, r4, r5 + 2ae70: bf14 ite ne + 2ae72: 2401 movne r4, #1 + 2ae74: 2400 moveq r4, #0 + 2ae76: b2e4 uxtb r4, r4 + 2ae78: 2500 movs r5, #0 + 2ae7a: e636 b.n 2aaea <__rtl_dadd_v1_00+0x2c6> + 2ae7c: 2000 movs r0, #0 + 2ae7e: 2100 movs r1, #0 + 2ae80: 4606 mov r6, r0 + 2ae82: 460f mov r7, r1 + 2ae84: e6ec b.n 2ac60 <__rtl_dadd_v1_00+0x43c> + 2ae86: f8dd c004 ldr.w ip, [sp, #4] + 2ae8a: 463d mov r5, r7 + 2ae8c: e687 b.n 2ab9e <__rtl_dadd_v1_00+0x37a> + 2ae8e: e9dd 0102 ldrd r0, r1, [sp, #8] + 2ae92: f041 5100 orr.w r1, r1, #536870912 ; 0x20000000 + 2ae96: e9cd 0102 strd r0, r1, [sp, #8] + 2ae9a: e77b b.n 2ad94 <__rtl_dadd_v1_00+0x570> + 2ae9c: 2100 movs r1, #0 + 2ae9e: f6c7 71f0 movt r1, #32752 ; 0x7ff0 + 2aea2: 2000 movs r0, #0 + 2aea4: 2200 movs r2, #0 + 2aea6: 07e3 lsls r3, r4, #31 + 2aea8: 1880 adds r0, r0, r2 + 2aeaa: 4159 adcs r1, r3 + 2aeac: e571 b.n 2a992 <__rtl_dadd_v1_00+0x16e> + 2aeae: f8dd 9008 ldr.w r9, [sp, #8] + 2aeb2: f8dd b00c ldr.w fp, [sp, #12] + 2aeb6: 463d mov r5, r7 + 2aeb8: ea59 090b orrs.w r9, r9, fp + 2aebc: bf14 ite ne + 2aebe: 2101 movne r1, #1 + 2aec0: 2100 moveq r1, #0 + 2aec2: b2ce uxtb r6, r1 + 2aec4: 2700 movs r7, #0 + 2aec6: f8dd c004 ldr.w ip, [sp, #4] + 2aeca: e9cd 6702 strd r6, r7, [sp, #8] + 2aece: e666 b.n 2ab9e <__rtl_dadd_v1_00+0x37a> + 2aed0: fa0f fe86 sxth.w lr, r6 + 2aed4: e6d0 b.n 2ac78 <__rtl_dadd_v1_00+0x454> + 2aed6: bf00 nop + +0002aed8 <__rtl_dsub_v1_00>: + 2aed8: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 2aedc: b087 sub sp, #28 + 2aede: e9cd 0100 strd r0, r1, [sp] + 2aee2: 9c01 ldr r4, [sp, #4] + 2aee4: ea4f 7cd4 mov.w ip, r4, lsr #31 + 2aee8: fa5f fe8c uxtb.w lr, ip + 2aeec: ebbe 7fd3 cmp.w lr, r3, lsr #31 + 2aef0: f000 8111 beq.w 2b116 <__rtl_dsub_v1_00+0x23e> + 2aef4: e9dd 4500 ldrd r4, r5, [sp] + 2aef8: f64f 77ff movw r7, #65535 ; 0xffff + 2aefc: f2c0 070f movt r7, #15 + 2af00: ea03 0107 and.w r1, r3, r7 + 2af04: 402f ands r7, r5 + 2af06: 9d01 ldr r5, [sp, #4] + 2af08: f3c3 590a ubfx r9, r3, #20, #11 + 2af0c: f3c5 5e0a ubfx lr, r5, #20, #11 + 2af10: fa1f fb89 uxth.w fp, r9 + 2af14: f04f 36ff mov.w r6, #4294967295 + 2af18: fa1f f88e uxth.w r8, lr + 2af1c: ea02 0006 and.w r0, r2, r6 + 2af20: ebcb 0208 rsb r2, fp, r8 + 2af24: b292 uxth r2, r2 + 2af26: b293 uxth r3, r2 + 2af28: f8cd b008 str.w fp, [sp, #8] + 2af2c: ea4f 2b47 mov.w fp, r7, lsl #9 + 2af30: b21f sxth r7, r3 + 2af32: 4026 ands r6, r4 + 2af34: 024d lsls r5, r1, #9 + 2af36: 2f00 cmp r7, #0 + 2af38: ea4b 5bd6 orr.w fp, fp, r6, lsr #23 + 2af3c: ea45 55d0 orr.w r5, r5, r0, lsr #23 + 2af40: ea4f 2a46 mov.w sl, r6, lsl #9 + 2af44: ea4f 2440 mov.w r4, r0, lsl #9 + 2af48: dd75 ble.n 2b036 <__rtl_dsub_v1_00+0x15e> + 2af4a: f240 73ff movw r3, #2047 ; 0x7ff + 2af4e: 459e cmp lr, r3 + 2af50: f000 808c beq.w 2b06c <__rtl_dsub_v1_00+0x194> + 2af54: f1b9 0f00 cmp.w r9, #0 + 2af58: d13e bne.n 2afd8 <__rtl_dsub_v1_00+0x100> + 2af5a: 1e53 subs r3, r2, #1 + 2af5c: b29b uxth r3, r3 + 2af5e: b21f sxth r7, r3 + 2af60: 2b00 cmp r3, #0 + 2af62: d13b bne.n 2afdc <__rtl_dsub_v1_00+0x104> + 2af64: eb14 040a adds.w r4, r4, sl + 2af68: f04b 5300 orr.w r3, fp, #536870912 ; 0x20000000 + 2af6c: 415d adcs r5, r3 + 2af6e: 1920 adds r0, r4, r4 + 2af70: eb45 0105 adc.w r1, r5, r5 + 2af74: 2800 cmp r0, #0 + 2af76: f171 0600 sbcs.w r6, r1, #0 + 2af7a: bfb9 ittee lt + 2af7c: 4620 movlt r0, r4 + 2af7e: 4629 movlt r1, r5 + 2af80: f108 38ff addge.w r8, r8, #4294967295 + 2af84: fa1f f888 uxthge.w r8, r8 + 2af88: bfa8 it ge + 2af8a: fa1f fe88 uxthge.w lr, r8 + 2af8e: f240 73fc movw r3, #2044 ; 0x7fc + 2af92: 4598 cmp r8, r3 + 2af94: d908 bls.n 2afa8 <__rtl_dsub_v1_00+0xd0> + 2af96: f240 72fe movw r2, #2046 ; 0x7fe + 2af9a: fa0f f38e sxth.w r3, lr + 2af9e: 4293 cmp r3, r2 + 2afa0: d069 beq.n 2b076 <__rtl_dsub_v1_00+0x19e> + 2afa2: 3301 adds r3, #1 + 2afa4: f000 81e8 beq.w 2b378 <__rtl_dsub_v1_00+0x4a0> + 2afa8: 0a82 lsrs r2, r0, #10 + 2afaa: ea42 5281 orr.w r2, r2, r1, lsl #22 + 2afae: 0a8b lsrs r3, r1, #10 + 2afb0: ea52 0703 orrs.w r7, r2, r3 + 2afb4: bf1c itt ne + 2afb6: ea4f 510e movne.w r1, lr, lsl #20 + 2afba: 2000 movne r0, #0 + 2afbc: d101 bne.n 2afc2 <__rtl_dsub_v1_00+0xea> + 2afbe: 4610 mov r0, r2 + 2afc0: 4619 mov r1, r3 + 2afc2: 1880 adds r0, r0, r2 + 2afc4: f04f 0400 mov.w r4, #0 + 2afc8: 4159 adcs r1, r3 + 2afca: ea4f 75cc mov.w r5, ip, lsl #31 + 2afce: 1900 adds r0, r0, r4 + 2afd0: 4169 adcs r1, r5 + 2afd2: b007 add sp, #28 + 2afd4: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 2afd8: f045 5500 orr.w r5, r5, #536870912 ; 0x20000000 + 2afdc: 2f3f cmp r7, #63 ; 0x3f + 2afde: dc3d bgt.n 2b05c <__rtl_dsub_v1_00+0x184> + 2afe0: 4278 negs r0, r7 + 2afe2: f000 003f and.w r0, r0, #63 ; 0x3f + 2afe6: f1a0 0920 sub.w r9, r0, #32 + 2afea: fa05 f100 lsl.w r1, r5, r0 + 2afee: fa04 f909 lsl.w r9, r4, r9 + 2aff2: f1c0 0620 rsb r6, r0, #32 + 2aff6: fa24 f606 lsr.w r6, r4, r6 + 2affa: ea41 0109 orr.w r1, r1, r9 + 2affe: 4331 orrs r1, r6 + 2b000: f1c7 0620 rsb r6, r7, #32 + 2b004: fa04 f000 lsl.w r0, r4, r0 + 2b008: fa24 f207 lsr.w r2, r4, r7 + 2b00c: fa05 f606 lsl.w r6, r5, r6 + 2b010: f1a7 0420 sub.w r4, r7, #32 + 2b014: 4301 orrs r1, r0 + 2b016: fa25 f404 lsr.w r4, r5, r4 + 2b01a: ea42 0206 orr.w r2, r2, r6 + 2b01e: bf14 ite ne + 2b020: 2001 movne r0, #1 + 2b022: 2000 moveq r0, #0 + 2b024: 4322 orrs r2, r4 + 2b026: 2100 movs r1, #0 + 2b028: fa25 f307 lsr.w r3, r5, r7 + 2b02c: ea40 0402 orr.w r4, r0, r2 + 2b030: ea41 0503 orr.w r5, r1, r3 + 2b034: e796 b.n 2af64 <__rtl_dsub_v1_00+0x8c> + 2b036: bb63 cbnz r3, 2b092 <__rtl_dsub_v1_00+0x1ba> + 2b038: f240 73ff movw r3, #2047 ; 0x7ff + 2b03c: fa0f f28e sxth.w r2, lr + 2b040: 429a cmp r2, r3 + 2b042: d013 beq.n 2b06c <__rtl_dsub_v1_00+0x194> + 2b044: f1be 0f00 cmp.w lr, #0 + 2b048: f000 8238 beq.w 2b4bc <__rtl_dsub_v1_00+0x5e4> + 2b04c: 3400 adds r4, #0 + 2b04e: f145 4580 adc.w r5, r5, #1073741824 ; 0x40000000 + 2b052: eb14 000a adds.w r0, r4, sl + 2b056: eb45 010b adc.w r1, r5, fp + 2b05a: e798 b.n 2af8e <__rtl_dsub_v1_00+0xb6> + 2b05c: ea54 0105 orrs.w r1, r4, r5 + 2b060: bf14 ite ne + 2b062: 2401 movne r4, #1 + 2b064: 2400 moveq r4, #0 + 2b066: b2e4 uxtb r4, r4 + 2b068: 2500 movs r5, #0 + 2b06a: e77b b.n 2af64 <__rtl_dsub_v1_00+0x8c> + 2b06c: e9dd 0100 ldrd r0, r1, [sp] + 2b070: b007 add sp, #28 + 2b072: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 2b076: f64f 71ff movw r1, #65535 ; 0xffff + 2b07a: f6c7 71ef movt r1, #32751 ; 0x7fef + 2b07e: 2200 movs r2, #0 + 2b080: f04f 30ff mov.w r0, #4294967295 + 2b084: 1880 adds r0, r0, r2 + 2b086: ea4f 73cc mov.w r3, ip, lsl #31 + 2b08a: 4159 adcs r1, r3 + 2b08c: b007 add sp, #28 + 2b08e: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 2b092: f240 71ff movw r1, #2047 ; 0x7ff + 2b096: 4589 cmp r9, r1 + 2b098: f000 8206 beq.w 2b4a8 <__rtl_dsub_v1_00+0x5d0> + 2b09c: f1be 0f00 cmp.w lr, #0 + 2b0a0: f040 821e bne.w 2b4e0 <__rtl_dsub_v1_00+0x608> + 2b0a4: 1c53 adds r3, r2, #1 + 2b0a6: b29b uxth r3, r3 + 2b0a8: 425b negs r3, r3 + 2b0aa: b29b uxth r3, r3 + 2b0ac: 2b00 cmp r3, #0 + 2b0ae: f000 8213 beq.w 2b4d8 <__rtl_dsub_v1_00+0x600> + 2b0b2: b21e sxth r6, r3 + 2b0b4: 2e3f cmp r6, #63 ; 0x3f + 2b0b6: f300 821b bgt.w 2b4f0 <__rtl_dsub_v1_00+0x618> + 2b0ba: 4270 negs r0, r6 + 2b0bc: f000 003f and.w r0, r0, #63 ; 0x3f + 2b0c0: f1a0 0e20 sub.w lr, r0, #32 + 2b0c4: fa0a fe0e lsl.w lr, sl, lr + 2b0c8: fa0b f100 lsl.w r1, fp, r0 + 2b0cc: f1c0 0720 rsb r7, r0, #32 + 2b0d0: fa2a f707 lsr.w r7, sl, r7 + 2b0d4: ea41 010e orr.w r1, r1, lr + 2b0d8: f1c6 0e20 rsb lr, r6, #32 + 2b0dc: fa0a f000 lsl.w r0, sl, r0 + 2b0e0: 4339 orrs r1, r7 + 2b0e2: fa0b fe0e lsl.w lr, fp, lr + 2b0e6: fa2a f206 lsr.w r2, sl, r6 + 2b0ea: f1a6 0720 sub.w r7, r6, #32 + 2b0ee: 4301 orrs r1, r0 + 2b0f0: ea42 020e orr.w r2, r2, lr + 2b0f4: fa2b f707 lsr.w r7, fp, r7 + 2b0f8: bf14 ite ne + 2b0fa: 2001 movne r0, #1 + 2b0fc: 2000 moveq r0, #0 + 2b0fe: 433a orrs r2, r7 + 2b100: 2100 movs r1, #0 + 2b102: fa2b f306 lsr.w r3, fp, r6 + 2b106: f8dd 8008 ldr.w r8, [sp, #8] + 2b10a: 46ce mov lr, r9 + 2b10c: ea40 0a02 orr.w sl, r0, r2 + 2b110: ea41 0b03 orr.w fp, r1, r3 + 2b114: e726 b.n 2af64 <__rtl_dsub_v1_00+0x8c> + 2b116: f64f 75ff movw r5, #65535 ; 0xffff + 2b11a: 4606 mov r6, r0 + 2b11c: f2c0 050f movt r5, #15 + 2b120: 460f mov r7, r1 + 2b122: f04f 34ff mov.w r4, #4294967295 + 2b126: 4026 ands r6, r4 + 2b128: 402f ands r7, r5 + 2b12a: e9cd 6702 strd r6, r7, [sp, #8] + 2b12e: ea02 0604 and.w r6, r2, r4 + 2b132: ea03 0705 and.w r7, r3, r5 + 2b136: e9cd 6704 strd r6, r7, [sp, #16] + 2b13a: 9f01 ldr r7, [sp, #4] + 2b13c: f3c3 590a ubfx r9, r3, #20, #11 + 2b140: f3c7 520a ubfx r2, r7, #20, #11 + 2b144: fa1f fb89 uxth.w fp, r9 + 2b148: fa1f f882 uxth.w r8, r2 + 2b14c: ebcb 0a08 rsb sl, fp, r8 + 2b150: f8cd b000 str.w fp, [sp] + 2b154: f8dd b014 ldr.w fp, [sp, #20] + 2b158: f8dd c00c ldr.w ip, [sp, #12] + 2b15c: ea4f 258b mov.w r5, fp, lsl #10 + 2b160: f8dd b008 ldr.w fp, [sp, #8] + 2b164: ea4f 278c mov.w r7, ip, lsl #10 + 2b168: ea47 579b orr.w r7, r7, fp, lsr #22 + 2b16c: f8dd b010 ldr.w fp, [sp, #16] + 2b170: fa1f fa8a uxth.w sl, sl + 2b174: ea45 559b orr.w r5, r5, fp, lsr #22 + 2b178: f8dd b008 ldr.w fp, [sp, #8] + 2b17c: fa1f f38a uxth.w r3, sl + 2b180: fa0f fc83 sxth.w ip, r3 + 2b184: ea4f 268b mov.w r6, fp, lsl #10 + 2b188: f8dd b010 ldr.w fp, [sp, #16] + 2b18c: f1bc 0f00 cmp.w ip, #0 + 2b190: ea4f 248b mov.w r4, fp, lsl #10 + 2b194: f340 80d6 ble.w 2b344 <__rtl_dsub_v1_00+0x46c> + 2b198: f240 73ff movw r3, #2047 ; 0x7ff + 2b19c: 429a cmp r2, r3 + 2b19e: f43f af18 beq.w 2afd2 <__rtl_dsub_v1_00+0xfa> + 2b1a2: f1b9 0f00 cmp.w r9, #0 + 2b1a6: f040 809a bne.w 2b2de <__rtl_dsub_v1_00+0x406> + 2b1aa: f10a 33ff add.w r3, sl, #4294967295 + 2b1ae: b29b uxth r3, r3 + 2b1b0: fa0f fc83 sxth.w ip, r3 + 2b1b4: 2b00 cmp r3, #0 + 2b1b6: f040 8094 bne.w 2b2e2 <__rtl_dsub_v1_00+0x40a> + 2b1ba: f047 4780 orr.w r7, r7, #1073741824 ; 0x40000000 + 2b1be: 1b34 subs r4, r6, r4 + 2b1c0: eb67 0505 sbc.w r5, r7, r5 + 2b1c4: f241 51a0 movw r1, #5536 ; 0x15a0 + 2b1c8: 2d01 cmp r5, #1 + 2b1ca: bf08 it eq + 2b1cc: 2c00 cmpeq r4, #0 + 2b1ce: bf34 ite cc + 2b1d0: 4623 movcc r3, r4 + 2b1d2: 462b movcs r3, r5 + 2b1d4: f2c0 0103 movt r1, #3 + 2b1d8: f240 76fc movw r6, #2044 ; 0x7fc + 2b1dc: bf2c ite cs + 2b1de: 27ff movcs r7, #255 ; 0xff + 2b1e0: 271f movcc r7, #31 + 2b1e2: f5b3 3f80 cmp.w r3, #65536 ; 0x10000 + 2b1e6: bf3a itte cc + 2b1e8: 041b lslcc r3, r3, #16 + 2b1ea: 2010 movcc r0, #16 + 2b1ec: 2000 movcs r0, #0 + 2b1ee: f1b3 7f80 cmp.w r3, #16777216 ; 0x1000000 + 2b1f2: bf3c itt cc + 2b1f4: 021b lslcc r3, r3, #8 + 2b1f6: 3008 addcc r0, #8 + 2b1f8: ea4f 6313 mov.w r3, r3, lsr #24 + 2b1fc: bf38 it cc + 2b1fe: b2c0 uxtbcc r0, r0 + 2b200: 5cc9 ldrb r1, [r1, r3] + 2b202: 19c3 adds r3, r0, r7 + 2b204: 440b add r3, r1 + 2b206: f108 32ff add.w r2, r8, #4294967295 + 2b20a: b2db uxtb r3, r3 + 2b20c: b292 uxth r2, r2 + 2b20e: f1a3 0020 sub.w r0, r3, #32 + 2b212: 1ad2 subs r2, r2, r3 + 2b214: fa04 f000 lsl.w r0, r4, r0 + 2b218: b292 uxth r2, r2 + 2b21a: fa05 fb03 lsl.w fp, r5, r3 + 2b21e: f1c3 0120 rsb r1, r3, #32 + 2b222: fa24 f101 lsr.w r1, r4, r1 + 2b226: ea4b 0b00 orr.w fp, fp, r0 + 2b22a: 42b2 cmp r2, r6 + 2b22c: fa04 fa03 lsl.w sl, r4, r3 + 2b230: ea4b 0b01 orr.w fp, fp, r1 + 2b234: b294 uxth r4, r2 + 2b236: d939 bls.n 2b2ac <__rtl_dsub_v1_00+0x3d4> + 2b238: f240 71fd movw r1, #2045 ; 0x7fd + 2b23c: b223 sxth r3, r4 + 2b23e: 428b cmp r3, r1 + 2b240: f300 80d5 bgt.w 2b3ee <__rtl_dsub_v1_00+0x516> + 2b244: f000 80cd beq.w 2b3e2 <__rtl_dsub_v1_00+0x50a> + 2b248: 2b00 cmp r3, #0 + 2b24a: da2f bge.n 2b2ac <__rtl_dsub_v1_00+0x3d4> + 2b24c: 4252 negs r2, r2 + 2b24e: b214 sxth r4, r2 + 2b250: 2c3f cmp r4, #63 ; 0x3f + 2b252: f300 815d bgt.w 2b510 <__rtl_dsub_v1_00+0x638> + 2b256: 4260 negs r0, r4 + 2b258: f000 003f and.w r0, r0, #63 ; 0x3f + 2b25c: f1a0 0620 sub.w r6, r0, #32 + 2b260: fa0a f606 lsl.w r6, sl, r6 + 2b264: fa0b f100 lsl.w r1, fp, r0 + 2b268: f1c0 0520 rsb r5, r0, #32 + 2b26c: fa2a f505 lsr.w r5, sl, r5 + 2b270: 4331 orrs r1, r6 + 2b272: fa0a f000 lsl.w r0, sl, r0 + 2b276: 4329 orrs r1, r5 + 2b278: 4301 orrs r1, r0 + 2b27a: f04f 0100 mov.w r1, #0 + 2b27e: fa2a f204 lsr.w r2, sl, r4 + 2b282: f1c4 0620 rsb r6, r4, #32 + 2b286: f1a4 0520 sub.w r5, r4, #32 + 2b28a: fa2b f304 lsr.w r3, fp, r4 + 2b28e: 460c mov r4, r1 + 2b290: fa0b f606 lsl.w r6, fp, r6 + 2b294: fa2b f505 lsr.w r5, fp, r5 + 2b298: ea42 0206 orr.w r2, r2, r6 + 2b29c: bf14 ite ne + 2b29e: 2001 movne r0, #1 + 2b2a0: 2000 moveq r0, #0 + 2b2a2: 432a orrs r2, r5 + 2b2a4: ea40 0a02 orr.w sl, r0, r2 + 2b2a8: ea41 0b03 orr.w fp, r1, r3 + 2b2ac: ea4f 229a mov.w r2, sl, lsr #10 + 2b2b0: ea42 528b orr.w r2, r2, fp, lsl #22 + 2b2b4: ea4f 239b mov.w r3, fp, lsr #10 + 2b2b8: ea52 0503 orrs.w r5, r2, r3 + 2b2bc: bf06 itte eq + 2b2be: 4610 moveq r0, r2 + 2b2c0: 4619 moveq r1, r3 + 2b2c2: 0521 lslne r1, r4, #20 + 2b2c4: f04f 0400 mov.w r4, #0 + 2b2c8: bf18 it ne + 2b2ca: 2000 movne r0, #0 + 2b2cc: ea4f 75ce mov.w r5, lr, lsl #31 + 2b2d0: 1912 adds r2, r2, r4 + 2b2d2: 416b adcs r3, r5 + 2b2d4: 1880 adds r0, r0, r2 + 2b2d6: 4159 adcs r1, r3 + 2b2d8: b007 add sp, #28 + 2b2da: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 2b2de: f045 4580 orr.w r5, r5, #1073741824 ; 0x40000000 + 2b2e2: f1bc 0f3f cmp.w ip, #63 ; 0x3f + 2b2e6: f300 808e bgt.w 2b406 <__rtl_dsub_v1_00+0x52e> + 2b2ea: f1cc 0000 rsb r0, ip, #0 + 2b2ee: f000 003f and.w r0, r0, #63 ; 0x3f + 2b2f2: f1a0 0a20 sub.w sl, r0, #32 + 2b2f6: fa05 f100 lsl.w r1, r5, r0 + 2b2fa: fa04 fa0a lsl.w sl, r4, sl + 2b2fe: f1c0 0920 rsb r9, r0, #32 + 2b302: fa24 f909 lsr.w r9, r4, r9 + 2b306: ea41 010a orr.w r1, r1, sl + 2b30a: ea41 0109 orr.w r1, r1, r9 + 2b30e: f1cc 0920 rsb r9, ip, #32 + 2b312: fa04 f000 lsl.w r0, r4, r0 + 2b316: fa24 f20c lsr.w r2, r4, ip + 2b31a: fa05 f909 lsl.w r9, r5, r9 + 2b31e: f1ac 0420 sub.w r4, ip, #32 + 2b322: 4301 orrs r1, r0 + 2b324: fa25 f404 lsr.w r4, r5, r4 + 2b328: ea42 0209 orr.w r2, r2, r9 + 2b32c: bf14 ite ne + 2b32e: 2001 movne r0, #1 + 2b330: 2000 moveq r0, #0 + 2b332: 4322 orrs r2, r4 + 2b334: 2100 movs r1, #0 + 2b336: fa25 f30c lsr.w r3, r5, ip + 2b33a: ea40 0402 orr.w r4, r0, r2 + 2b33e: ea41 0503 orr.w r5, r1, r3 + 2b342: e73a b.n 2b1ba <__rtl_dsub_v1_00+0x2e2> + 2b344: 2b00 cmp r3, #0 + 2b346: d166 bne.n 2b416 <__rtl_dsub_v1_00+0x53e> + 2b348: b912 cbnz r2, 2b350 <__rtl_dsub_v1_00+0x478> + 2b34a: f04f 0901 mov.w r9, #1 + 2b34e: 464a mov r2, r9 + 2b350: 42bd cmp r5, r7 + 2b352: bf08 it eq + 2b354: 42b4 cmpeq r4, r6 + 2b356: bf38 it cc + 2b358: fa1f f882 uxthcc.w r8, r2 + 2b35c: f4ff af2f bcc.w 2b1be <__rtl_dsub_v1_00+0x2e6> + 2b360: 42af cmp r7, r5 + 2b362: bf08 it eq + 2b364: 42a6 cmpeq r6, r4 + 2b366: bf38 it cc + 2b368: fa1f f889 uxthcc.w r8, r9 + 2b36c: f0c0 8096 bcc.w 2b49c <__rtl_dsub_v1_00+0x5c4> + 2b370: 2000 movs r0, #0 + 2b372: f04f 4100 mov.w r1, #2147483648 ; 0x80000000 + 2b376: e62c b.n 2afd2 <__rtl_dsub_v1_00+0xfa> + 2b378: f1c8 0800 rsb r8, r8, #0 + 2b37c: fa0f f888 sxth.w r8, r8 + 2b380: f1b8 0f3f cmp.w r8, #63 ; 0x3f + 2b384: f300 80af bgt.w 2b4e6 <__rtl_dsub_v1_00+0x60e> + 2b388: f1c8 0500 rsb r5, r8, #0 + 2b38c: f005 053f and.w r5, r5, #63 ; 0x3f + 2b390: f1a5 0720 sub.w r7, r5, #32 + 2b394: fa01 f405 lsl.w r4, r1, r5 + 2b398: fa00 f707 lsl.w r7, r0, r7 + 2b39c: f1c5 0620 rsb r6, r5, #32 + 2b3a0: fa20 f606 lsr.w r6, r0, r6 + 2b3a4: 433c orrs r4, r7 + 2b3a6: 4334 orrs r4, r6 + 2b3a8: f1c8 0620 rsb r6, r8, #32 + 2b3ac: fa00 f505 lsl.w r5, r0, r5 + 2b3b0: fa20 f208 lsr.w r2, r0, r8 + 2b3b4: fa01 f606 lsl.w r6, r1, r6 + 2b3b8: f1a8 0020 sub.w r0, r8, #32 + 2b3bc: 432c orrs r4, r5 + 2b3be: fa21 f000 lsr.w r0, r1, r0 + 2b3c2: ea42 0206 orr.w r2, r2, r6 + 2b3c6: f04f 0500 mov.w r5, #0 + 2b3ca: bf14 ite ne + 2b3cc: 2401 movne r4, #1 + 2b3ce: 2400 moveq r4, #0 + 2b3d0: 4302 orrs r2, r0 + 2b3d2: fa21 f308 lsr.w r3, r1, r8 + 2b3d6: ea44 0002 orr.w r0, r4, r2 + 2b3da: ea45 0103 orr.w r1, r5, r3 + 2b3de: 46ae mov lr, r5 + 2b3e0: e5e2 b.n 2afa8 <__rtl_dsub_v1_00+0xd0> + 2b3e2: f1ba 0f00 cmp.w sl, #0 + 2b3e6: f17b 0300 sbcs.w r3, fp, #0 + 2b3ea: f6bf af5f bge.w 2b2ac <__rtl_dsub_v1_00+0x3d4> + 2b3ee: f64f 71ff movw r1, #65535 ; 0xffff + 2b3f2: f6c7 71ef movt r1, #32751 ; 0x7fef + 2b3f6: f04f 30ff mov.w r0, #4294967295 + 2b3fa: 2200 movs r2, #0 + 2b3fc: ea4f 73ce mov.w r3, lr, lsl #31 + 2b400: 1880 adds r0, r0, r2 + 2b402: 4159 adcs r1, r3 + 2b404: e5e5 b.n 2afd2 <__rtl_dsub_v1_00+0xfa> + 2b406: ea54 0105 orrs.w r1, r4, r5 + 2b40a: bf14 ite ne + 2b40c: 2401 movne r4, #1 + 2b40e: 2400 moveq r4, #0 + 2b410: b2e4 uxtb r4, r4 + 2b412: 2500 movs r5, #0 + 2b414: e6d1 b.n 2b1ba <__rtl_dsub_v1_00+0x2e2> + 2b416: f240 71ff movw r1, #2047 ; 0x7ff + 2b41a: 4589 cmp r9, r1 + 2b41c: f000 8085 beq.w 2b52a <__rtl_dsub_v1_00+0x652> + 2b420: 2a00 cmp r2, #0 + 2b422: d172 bne.n 2b50a <__rtl_dsub_v1_00+0x632> + 2b424: f10a 0301 add.w r3, sl, #1 + 2b428: b29b uxth r3, r3 + 2b42a: 425b negs r3, r3 + 2b42c: b29b uxth r3, r3 + 2b42e: b38b cbz r3, 2b494 <__rtl_dsub_v1_00+0x5bc> + 2b430: fa0f fc83 sxth.w ip, r3 + 2b434: f1bc 0f3f cmp.w ip, #63 ; 0x3f + 2b438: f300 8083 bgt.w 2b542 <__rtl_dsub_v1_00+0x66a> + 2b43c: f1cc 0000 rsb r0, ip, #0 + 2b440: f000 003f and.w r0, r0, #63 ; 0x3f + 2b444: f1a0 0920 sub.w r9, r0, #32 + 2b448: fa07 f100 lsl.w r1, r7, r0 + 2b44c: fa06 f909 lsl.w r9, r6, r9 + 2b450: f1c0 0820 rsb r8, r0, #32 + 2b454: fa26 f808 lsr.w r8, r6, r8 + 2b458: ea41 0109 orr.w r1, r1, r9 + 2b45c: ea41 0108 orr.w r1, r1, r8 + 2b460: f1cc 0820 rsb r8, ip, #32 + 2b464: fa06 f000 lsl.w r0, r6, r0 + 2b468: fa26 f20c lsr.w r2, r6, ip + 2b46c: fa07 f808 lsl.w r8, r7, r8 + 2b470: f1ac 0620 sub.w r6, ip, #32 + 2b474: 4301 orrs r1, r0 + 2b476: fa27 f606 lsr.w r6, r7, r6 + 2b47a: ea42 0208 orr.w r2, r2, r8 + 2b47e: bf14 ite ne + 2b480: 2001 movne r0, #1 + 2b482: 2000 moveq r0, #0 + 2b484: 4332 orrs r2, r6 + 2b486: 2100 movs r1, #0 + 2b488: fa27 f30c lsr.w r3, r7, ip + 2b48c: ea40 0602 orr.w r6, r0, r2 + 2b490: ea41 0703 orr.w r7, r1, r3 + 2b494: f8dd 8000 ldr.w r8, [sp] + 2b498: f045 4580 orr.w r5, r5, #1073741824 ; 0x40000000 + 2b49c: 1ba4 subs r4, r4, r6 + 2b49e: eb65 0507 sbc.w r5, r5, r7 + 2b4a2: f08e 0e01 eor.w lr, lr, #1 + 2b4a6: e68d b.n 2b1c4 <__rtl_dsub_v1_00+0x2ec> + 2b4a8: 2100 movs r1, #0 + 2b4aa: f6c7 71f0 movt r1, #32752 ; 0x7ff0 + 2b4ae: 2000 movs r0, #0 + 2b4b0: 2200 movs r2, #0 + 2b4b2: ea4f 73cc mov.w r3, ip, lsl #31 + 2b4b6: 1880 adds r0, r0, r2 + 2b4b8: 4159 adcs r1, r3 + 2b4ba: e58a b.n 2afd2 <__rtl_dsub_v1_00+0xfa> + 2b4bc: eb14 040a adds.w r4, r4, sl + 2b4c0: eb45 050b adc.w r5, r5, fp + 2b4c4: 0a60 lsrs r0, r4, #9 + 2b4c6: ea40 50c5 orr.w r0, r0, r5, lsl #23 + 2b4ca: ea4f 73cc mov.w r3, ip, lsl #31 + 2b4ce: 0a69 lsrs r1, r5, #9 + 2b4d0: eb10 000e adds.w r0, r0, lr + 2b4d4: 4159 adcs r1, r3 + 2b4d6: e57c b.n 2afd2 <__rtl_dsub_v1_00+0xfa> + 2b4d8: f8dd 8008 ldr.w r8, [sp, #8] + 2b4dc: 46ce mov lr, r9 + 2b4de: e541 b.n 2af64 <__rtl_dsub_v1_00+0x8c> + 2b4e0: f04b 5b00 orr.w fp, fp, #536870912 ; 0x20000000 + 2b4e4: e5e0 b.n 2b0a8 <__rtl_dsub_v1_00+0x1d0> + 2b4e6: 2000 movs r0, #0 + 2b4e8: 2100 movs r1, #0 + 2b4ea: 4602 mov r2, r0 + 2b4ec: 460b mov r3, r1 + 2b4ee: e568 b.n 2afc2 <__rtl_dsub_v1_00+0xea> + 2b4f0: ea5a 030b orrs.w r3, sl, fp + 2b4f4: bf14 ite ne + 2b4f6: 2301 movne r3, #1 + 2b4f8: 2300 moveq r3, #0 + 2b4fa: f8dd 8008 ldr.w r8, [sp, #8] + 2b4fe: 46ce mov lr, r9 + 2b500: fa5f fa83 uxtb.w sl, r3 + 2b504: f04f 0b00 mov.w fp, #0 + 2b508: e52c b.n 2af64 <__rtl_dsub_v1_00+0x8c> + 2b50a: f047 4780 orr.w r7, r7, #1073741824 ; 0x40000000 + 2b50e: e78c b.n 2b42a <__rtl_dsub_v1_00+0x552> + 2b510: ea5a 040b orrs.w r4, sl, fp + 2b514: bf14 ite ne + 2b516: f04f 0a01 movne.w sl, #1 + 2b51a: f04f 0a00 moveq.w sl, #0 + 2b51e: fa5f fa8a uxtb.w sl, sl + 2b522: f04f 0b00 mov.w fp, #0 + 2b526: 2400 movs r4, #0 + 2b528: e6c0 b.n 2b2ac <__rtl_dsub_v1_00+0x3d4> + 2b52a: 2100 movs r1, #0 + 2b52c: f6c7 71f0 movt r1, #32752 ; 0x7ff0 + 2b530: 2000 movs r0, #0 + 2b532: f08e 0e01 eor.w lr, lr, #1 + 2b536: 2200 movs r2, #0 + 2b538: ea4f 73ce mov.w r3, lr, lsl #31 + 2b53c: 1880 adds r0, r0, r2 + 2b53e: 4159 adcs r1, r3 + 2b540: e547 b.n 2afd2 <__rtl_dsub_v1_00+0xfa> + 2b542: ea56 0c07 orrs.w ip, r6, r7 + 2b546: bf14 ite ne + 2b548: 2601 movne r6, #1 + 2b54a: 2600 moveq r6, #0 + 2b54c: b2f6 uxtb r6, r6 + 2b54e: 2700 movs r7, #0 + 2b550: e7a0 b.n 2b494 <__rtl_dsub_v1_00+0x5bc> + 2b552: bf00 nop + +0002b554 <__rtl_dmul_v1_00>: + 2b554: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 2b558: f64f 77ff movw r7, #65535 ; 0xffff + 2b55c: f2c0 070f movt r7, #15 + 2b560: ea4f 7ad3 mov.w sl, r3, lsr #31 + 2b564: ea8a 7ad1 eor.w sl, sl, r1, lsr #31 + 2b568: b087 sub sp, #28 + 2b56a: f04f 36ff mov.w r6, #4294967295 + 2b56e: f3c1 5e0a ubfx lr, r1, #20, #11 + 2b572: f8cd a004 str.w sl, [sp, #4] + 2b576: 4030 ands r0, r6 + 2b578: 4039 ands r1, r7 + 2b57a: f1be 0f00 cmp.w lr, #0 + 2b57e: d140 bne.n 2b602 <__rtl_dmul_v1_00+0xae> + 2b580: ea50 0401 orrs.w r4, r0, r1 + 2b584: bf04 itt eq + 2b586: ea4f 71ca moveq.w r1, sl, lsl #31 + 2b58a: 4670 moveq r0, lr + 2b58c: d102 bne.n 2b594 <__rtl_dmul_v1_00+0x40> + 2b58e: b007 add sp, #28 + 2b590: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 2b594: f241 55a0 movw r5, #5536 ; 0x15a0 + 2b598: 2901 cmp r1, #1 + 2b59a: bf08 it eq + 2b59c: 2800 cmpeq r0, #0 + 2b59e: bf2c ite cs + 2b5a0: 460c movcs r4, r1 + 2b5a2: 4604 movcc r4, r0 + 2b5a4: f2c0 0503 movt r5, #3 + 2b5a8: bf2c ite cs + 2b5aa: f04f 0ef5 movcs.w lr, #245 ; 0xf5 + 2b5ae: f04f 0e15 movcc.w lr, #21 + 2b5b2: f5b4 3f80 cmp.w r4, #65536 ; 0x10000 + 2b5b6: bf3a itte cc + 2b5b8: 0424 lslcc r4, r4, #16 + 2b5ba: 2610 movcc r6, #16 + 2b5bc: 2600 movcs r6, #0 + 2b5be: f1b4 7f80 cmp.w r4, #16777216 ; 0x1000000 + 2b5c2: bf3c itt cc + 2b5c4: 0224 lslcc r4, r4, #8 + 2b5c6: 3608 addcc r6, #8 + 2b5c8: ea4f 6414 mov.w r4, r4, lsr #24 + 2b5cc: 5d2c ldrb r4, [r5, r4] + 2b5ce: bf38 it cc + 2b5d0: b2f6 uxtbcc r6, r6 + 2b5d2: 44b6 add lr, r6 + 2b5d4: 44a6 add lr, r4 + 2b5d6: fa5f fe8e uxtb.w lr, lr + 2b5da: f1ae 0620 sub.w r6, lr, #32 + 2b5de: f1ce 0420 rsb r4, lr, #32 + 2b5e2: fa00 f70e lsl.w r7, r0, lr + 2b5e6: fa00 f606 lsl.w r6, r0, r6 + 2b5ea: fa20 f404 lsr.w r4, r0, r4 + 2b5ee: 4638 mov r0, r7 + 2b5f0: fa01 f50e lsl.w r5, r1, lr + 2b5f4: 4335 orrs r5, r6 + 2b5f6: f1ce 0e01 rsb lr, lr, #1 + 2b5fa: ea45 0104 orr.w r1, r5, r4 + 2b5fe: fa1f fe8e uxth.w lr, lr + 2b602: f64f 75ff movw r5, #65535 ; 0xffff + 2b606: f2c0 050f movt r5, #15 + 2b60a: f04f 34ff mov.w r4, #4294967295 + 2b60e: f3c3 5c0a ubfx ip, r3, #20, #11 + 2b612: 4022 ands r2, r4 + 2b614: 402b ands r3, r5 + 2b616: f1bc 0f00 cmp.w ip, #0 + 2b61a: f000 80a7 beq.w 2b76c <__rtl_dmul_v1_00+0x218> + 2b61e: f240 74ff movw r4, #2047 ; 0x7ff + 2b622: 45a6 cmp lr, r4 + 2b624: f000 80ad beq.w 2b782 <__rtl_dmul_v1_00+0x22e> + 2b628: f240 74ff movw r4, #2047 ; 0x7ff + 2b62c: 45a4 cmp ip, r4 + 2b62e: d103 bne.n 2b638 <__rtl_dmul_v1_00+0xe4> + 2b630: ea52 0a03 orrs.w sl, r2, r3 + 2b634: f000 80a9 beq.w 2b78a <__rtl_dmul_v1_00+0x236> + 2b638: f441 1780 orr.w r7, r1, #1048576 ; 0x100000 + 2b63c: f443 1380 orr.w r3, r3, #1048576 ; 0x100000 + 2b640: 02b9 lsls r1, r7, #10 + 2b642: ea41 5190 orr.w r1, r1, r0, lsr #22 + 2b646: 02dd lsls r5, r3, #11 + 2b648: 0280 lsls r0, r0, #10 + 2b64a: ea45 5552 orr.w r5, r5, r2, lsr #21 + 2b64e: 02d4 lsls r4, r2, #11 + 2b650: 4602 mov r2, r0 + 2b652: fba4 ab01 umull sl, fp, r4, r1 + 2b656: fba5 8900 umull r8, r9, r5, r0 + 2b65a: e9cd ab04 strd sl, fp, [sp, #16] + 2b65e: e9cd 8902 strd r8, r9, [sp, #8] + 2b662: f8dd 8014 ldr.w r8, [sp, #20] + 2b666: 2300 movs r3, #0 + 2b668: 2700 movs r7, #0 + 2b66a: fb05 9b03 mla fp, r5, r3, r9 + 2b66e: fb01 8807 mla r8, r1, r7, r8 + 2b672: fb04 f003 mul.w r0, r4, r3 + 2b676: f8cd b00c str.w fp, [sp, #12] + 2b67a: fb02 0007 mla r0, r2, r7, r0 + 2b67e: e9dd ab02 ldrd sl, fp, [sp, #8] + 2b682: fba4 2302 umull r2, r3, r4, r2 + 2b686: f8cd 8014 str.w r8, [sp, #20] + 2b68a: e9dd 8904 ldrd r8, r9, [sp, #16] + 2b68e: eb1a 0a08 adds.w sl, sl, r8 + 2b692: eb4b 0b09 adc.w fp, fp, r9 + 2b696: fba5 6701 umull r6, r7, r5, r1 + 2b69a: 45cb cmp fp, r9 + 2b69c: e9cd ab02 strd sl, fp, [sp, #8] + 2b6a0: 9902 ldr r1, [sp, #8] + 2b6a2: bf08 it eq + 2b6a4: 45c2 cmpeq sl, r8 + 2b6a6: 4403 add r3, r0 + 2b6a8: 9c03 ldr r4, [sp, #12] + 2b6aa: f04f 0000 mov.w r0, #0 + 2b6ae: bf34 ite cc + 2b6b0: f04f 0901 movcc.w r9, #1 + 2b6b4: f04f 0900 movcs.w r9, #0 + 2b6b8: 1812 adds r2, r2, r0 + 2b6ba: 414b adcs r3, r1 + 2b6bc: 19a4 adds r4, r4, r6 + 2b6be: eb40 0507 adc.w r5, r0, r7 + 2b6c2: 428b cmp r3, r1 + 2b6c4: bf08 it eq + 2b6c6: 4282 cmpeq r2, r0 + 2b6c8: bf2c ite cs + 2b6ca: 4601 movcs r1, r0 + 2b6cc: 2101 movcc r1, #1 + 2b6ce: 1864 adds r4, r4, r1 + 2b6d0: f04f 0800 mov.w r8, #0 + 2b6d4: f145 0500 adc.w r5, r5, #0 + 2b6d8: eb14 0408 adds.w r4, r4, r8 + 2b6dc: eb45 0509 adc.w r5, r5, r9 + 2b6e0: ea52 0903 orrs.w r9, r2, r3 + 2b6e4: bf08 it eq + 2b6e6: 4603 moveq r3, r0 + 2b6e8: f240 72fc movw r2, #2044 ; 0x7fc + 2b6ec: bf18 it ne + 2b6ee: 2301 movne r3, #1 + 2b6f0: 431c orrs r4, r3 + 2b6f2: 1920 adds r0, r4, r4 + 2b6f4: eb45 0105 adc.w r1, r5, r5 + 2b6f8: 44e6 add lr, ip + 2b6fa: 2800 cmp r0, #0 + 2b6fc: f171 0a00 sbcs.w sl, r1, #0 + 2b700: fa1f fe8e uxth.w lr, lr + 2b704: bfb5 itete lt + 2b706: f2ae 3eff subwlt lr, lr, #1023 ; 0x3ff + 2b70a: f5ae 6e80 subge.w lr, lr, #1024 ; 0x400 + 2b70e: fa1f fe8e uxthlt.w lr, lr + 2b712: fa1f fe8e uxthge.w lr, lr + 2b716: fa1f f38e uxth.w r3, lr + 2b71a: bfbc itt lt + 2b71c: 4620 movlt r0, r4 + 2b71e: 4629 movlt r1, r5 + 2b720: 4293 cmp r3, r2 + 2b722: d908 bls.n 2b736 <__rtl_dmul_v1_00+0x1e2> + 2b724: f240 74fd movw r4, #2045 ; 0x7fd + 2b728: fa0f f28e sxth.w r2, lr + 2b72c: 42a2 cmp r2, r4 + 2b72e: dc76 bgt.n 2b81e <__rtl_dmul_v1_00+0x2ca> + 2b730: d071 beq.n 2b816 <__rtl_dmul_v1_00+0x2c2> + 2b732: 2a00 cmp r2, #0 + 2b734: db7f blt.n 2b836 <__rtl_dmul_v1_00+0x2e2> + 2b736: 0a82 lsrs r2, r0, #10 + 2b738: ea42 5281 orr.w r2, r2, r1, lsl #22 + 2b73c: 0a8b lsrs r3, r1, #10 + 2b73e: ea52 0803 orrs.w r8, r2, r3 + 2b742: bf04 itt eq + 2b744: 4616 moveq r6, r2 + 2b746: 461f moveq r7, r3 + 2b748: f8dd 9004 ldr.w r9, [sp, #4] + 2b74c: f04f 0400 mov.w r4, #0 + 2b750: bf1c itt ne + 2b752: ea4f 570e movne.w r7, lr, lsl #20 + 2b756: 2600 movne r6, #0 + 2b758: ea4f 75c9 mov.w r5, r9, lsl #31 + 2b75c: 1910 adds r0, r2, r4 + 2b75e: eb43 0105 adc.w r1, r3, r5 + 2b762: 1980 adds r0, r0, r6 + 2b764: 4179 adcs r1, r7 + 2b766: b007 add sp, #28 + 2b768: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 2b76c: ea52 0503 orrs.w r5, r2, r3 + 2b770: d119 bne.n 2b7a6 <__rtl_dmul_v1_00+0x252> + 2b772: 4660 mov r0, ip + 2b774: f8dd 8004 ldr.w r8, [sp, #4] + 2b778: ea4f 71c8 mov.w r1, r8, lsl #31 + 2b77c: b007 add sp, #28 + 2b77e: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 2b782: ea50 0901 orrs.w r9, r0, r1 + 2b786: f47f af4f bne.w 2b628 <__rtl_dmul_v1_00+0xd4> + 2b78a: f64f 71ff movw r1, #65535 ; 0xffff + 2b78e: f6c7 71ef movt r1, #32751 ; 0x7fef + 2b792: f8dd b004 ldr.w fp, [sp, #4] + 2b796: f04f 30ff mov.w r0, #4294967295 + 2b79a: 2200 movs r2, #0 + 2b79c: ea4f 73cb mov.w r3, fp, lsl #31 + 2b7a0: 1880 adds r0, r0, r2 + 2b7a2: 4159 adcs r1, r3 + 2b7a4: e6f3 b.n 2b58e <__rtl_dmul_v1_00+0x3a> + 2b7a6: f241 55a0 movw r5, #5536 ; 0x15a0 + 2b7aa: 2b01 cmp r3, #1 + 2b7ac: bf08 it eq + 2b7ae: 2a00 cmpeq r2, #0 + 2b7b0: bf2c ite cs + 2b7b2: 461c movcs r4, r3 + 2b7b4: 4614 movcc r4, r2 + 2b7b6: f2c0 0503 movt r5, #3 + 2b7ba: bf2c ite cs + 2b7bc: f04f 0cf5 movcs.w ip, #245 ; 0xf5 + 2b7c0: f04f 0c15 movcc.w ip, #21 + 2b7c4: f5b4 3f80 cmp.w r4, #65536 ; 0x10000 + 2b7c8: bf3a itte cc + 2b7ca: 0424 lslcc r4, r4, #16 + 2b7cc: 2610 movcc r6, #16 + 2b7ce: 2600 movcs r6, #0 + 2b7d0: f1b4 7f80 cmp.w r4, #16777216 ; 0x1000000 + 2b7d4: bf3c itt cc + 2b7d6: 0224 lslcc r4, r4, #8 + 2b7d8: 3608 addcc r6, #8 + 2b7da: ea4f 6414 mov.w r4, r4, lsr #24 + 2b7de: 5d2c ldrb r4, [r5, r4] + 2b7e0: bf38 it cc + 2b7e2: b2f6 uxtbcc r6, r6 + 2b7e4: 44b4 add ip, r6 + 2b7e6: 44a4 add ip, r4 + 2b7e8: fa5f fc8c uxtb.w ip, ip + 2b7ec: f1ac 0620 sub.w r6, ip, #32 + 2b7f0: fa03 f50c lsl.w r5, r3, ip + 2b7f4: f1cc 0420 rsb r4, ip, #32 + 2b7f8: fa02 f606 lsl.w r6, r2, r6 + 2b7fc: fa22 f404 lsr.w r4, r2, r4 + 2b800: fa02 f70c lsl.w r7, r2, ip + 2b804: 4335 orrs r5, r6 + 2b806: f1cc 0c01 rsb ip, ip, #1 + 2b80a: 463a mov r2, r7 + 2b80c: ea45 0304 orr.w r3, r5, r4 + 2b810: fa1f fc8c uxth.w ip, ip + 2b814: e703 b.n 2b61e <__rtl_dmul_v1_00+0xca> + 2b816: 2800 cmp r0, #0 + 2b818: f171 0b00 sbcs.w fp, r1, #0 + 2b81c: da8b bge.n 2b736 <__rtl_dmul_v1_00+0x1e2> + 2b81e: f64f 71ff movw r1, #65535 ; 0xffff + 2b822: f6c7 71ef movt r1, #32751 ; 0x7fef + 2b826: 9c01 ldr r4, [sp, #4] + 2b828: f04f 30ff mov.w r0, #4294967295 + 2b82c: 2200 movs r2, #0 + 2b82e: 07e3 lsls r3, r4, #31 + 2b830: 1880 adds r0, r0, r2 + 2b832: 4159 adcs r1, r3 + 2b834: e6ab b.n 2b58e <__rtl_dmul_v1_00+0x3a> + 2b836: 425b negs r3, r3 + 2b838: b21e sxth r6, r3 + 2b83a: 2e3f cmp r6, #63 ; 0x3f + 2b83c: dc2c bgt.n 2b898 <__rtl_dmul_v1_00+0x344> + 2b83e: 4275 negs r5, r6 + 2b840: f005 053f and.w r5, r5, #63 ; 0x3f + 2b844: f1a5 0e20 sub.w lr, r5, #32 + 2b848: fa00 fe0e lsl.w lr, r0, lr + 2b84c: fa01 f405 lsl.w r4, r1, r5 + 2b850: f1c5 0720 rsb r7, r5, #32 + 2b854: fa20 f707 lsr.w r7, r0, r7 + 2b858: ea44 040e orr.w r4, r4, lr + 2b85c: 433c orrs r4, r7 + 2b85e: f1c6 0720 rsb r7, r6, #32 + 2b862: fa00 f505 lsl.w r5, r0, r5 + 2b866: fa20 f206 lsr.w r2, r0, r6 + 2b86a: fa01 f707 lsl.w r7, r1, r7 + 2b86e: f1a6 0020 sub.w r0, r6, #32 + 2b872: 432c orrs r4, r5 + 2b874: fa21 f000 lsr.w r0, r1, r0 + 2b878: ea42 0207 orr.w r2, r2, r7 + 2b87c: f04f 0500 mov.w r5, #0 + 2b880: bf14 ite ne + 2b882: 2401 movne r4, #1 + 2b884: 2400 moveq r4, #0 + 2b886: 4302 orrs r2, r0 + 2b888: fa21 f306 lsr.w r3, r1, r6 + 2b88c: ea44 0002 orr.w r0, r4, r2 + 2b890: ea45 0103 orr.w r1, r5, r3 + 2b894: 46ae mov lr, r5 + 2b896: e74e b.n 2b736 <__rtl_dmul_v1_00+0x1e2> + 2b898: ea50 0501 orrs.w r5, r0, r1 + 2b89c: bf14 ite ne + 2b89e: 2001 movne r0, #1 + 2b8a0: 2000 moveq r0, #0 + 2b8a2: b2c0 uxtb r0, r0 + 2b8a4: 2100 movs r1, #0 + 2b8a6: f04f 0e00 mov.w lr, #0 + 2b8aa: e744 b.n 2b736 <__rtl_dmul_v1_00+0x1e2> + +0002b8ac <__rtl_ddiv_v1_00>: + 2b8ac: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 2b8b0: f240 76ff movw r6, #2047 ; 0x7ff + 2b8b4: ea4f 78d3 mov.w r8, r3, lsr #31 + 2b8b8: f3c1 550a ubfx r5, r1, #20, #11 + 2b8bc: b093 sub sp, #76 ; 0x4c + 2b8be: ea88 78d1 eor.w r8, r8, r1, lsr #31 + 2b8c2: 42b5 cmp r5, r6 + 2b8c4: f8cd 8020 str.w r8, [sp, #32] + 2b8c8: f3c3 540a ubfx r4, r3, #20, #11 + 2b8cc: f000 8105 beq.w 2bada <__rtl_ddiv_v1_00+0x22e> + 2b8d0: b227 sxth r7, r4 + 2b8d2: 42b7 cmp r7, r6 + 2b8d4: f000 810d beq.w 2baf2 <__rtl_ddiv_v1_00+0x246> + 2b8d8: f64f 77ff movw r7, #65535 ; 0xffff + 2b8dc: f2c0 070f movt r7, #15 + 2b8e0: f04f 36ff mov.w r6, #4294967295 + 2b8e4: 4032 ands r2, r6 + 2b8e6: 403b ands r3, r7 + 2b8e8: b1a4 cbz r4, 2b914 <__rtl_ddiv_v1_00+0x68> + 2b8ea: f64f 77ff movw r7, #65535 ; 0xffff + 2b8ee: f2c0 070f movt r7, #15 + 2b8f2: f04f 36ff mov.w r6, #4294967295 + 2b8f6: 4030 ands r0, r6 + 2b8f8: 4039 ands r1, r7 + 2b8fa: 2d00 cmp r5, #0 + 2b8fc: d150 bne.n 2b9a0 <__rtl_ddiv_v1_00+0xf4> + 2b8fe: ea50 0801 orrs.w r8, r0, r1 + 2b902: d116 bne.n 2b932 <__rtl_ddiv_v1_00+0x86> + 2b904: 4628 mov r0, r5 + 2b906: f8dd 9020 ldr.w r9, [sp, #32] + 2b90a: ea4f 71c9 mov.w r1, r9, lsl #31 + 2b90e: b013 add sp, #76 ; 0x4c + 2b910: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 2b914: ea52 0603 orrs.w r6, r2, r3 + 2b918: f040 80a7 bne.w 2ba6a <__rtl_ddiv_v1_00+0x1be> + 2b91c: 2100 movs r1, #0 + 2b91e: f6c7 71f0 movt r1, #32752 ; 0x7ff0 + 2b922: 9f08 ldr r7, [sp, #32] + 2b924: 2000 movs r0, #0 + 2b926: 07fb lsls r3, r7, #31 + 2b928: 1900 adds r0, r0, r4 + 2b92a: 4159 adcs r1, r3 + 2b92c: b013 add sp, #76 ; 0x4c + 2b92e: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 2b932: f241 56a0 movw r6, #5536 ; 0x15a0 + 2b936: 2901 cmp r1, #1 + 2b938: bf08 it eq + 2b93a: 2800 cmpeq r0, #0 + 2b93c: bf2c ite cs + 2b93e: 460d movcs r5, r1 + 2b940: 4605 movcc r5, r0 + 2b942: f2c0 0603 movt r6, #3 + 2b946: bf2c ite cs + 2b948: f04f 0ef5 movcs.w lr, #245 ; 0xf5 + 2b94c: f04f 0e15 movcc.w lr, #21 + 2b950: f5b5 3f80 cmp.w r5, #65536 ; 0x10000 + 2b954: bf3a itte cc + 2b956: 042d lslcc r5, r5, #16 + 2b958: 2710 movcc r7, #16 + 2b95a: 2700 movcs r7, #0 + 2b95c: f1b5 7f80 cmp.w r5, #16777216 ; 0x1000000 + 2b960: bf3c itt cc + 2b962: 022d lslcc r5, r5, #8 + 2b964: 3708 addcc r7, #8 + 2b966: ea4f 6515 mov.w r5, r5, lsr #24 + 2b96a: 5d76 ldrb r6, [r6, r5] + 2b96c: bf38 it cc + 2b96e: b2ff uxtbcc r7, r7 + 2b970: eb07 050e add.w r5, r7, lr + 2b974: 4435 add r5, r6 + 2b976: b2ed uxtb r5, r5 + 2b978: f1a5 0e20 sub.w lr, r5, #32 + 2b97c: f1c5 0620 rsb r6, r5, #32 + 2b980: fa00 fc05 lsl.w ip, r0, r5 + 2b984: fa00 fe0e lsl.w lr, r0, lr + 2b988: fa20 f606 lsr.w r6, r0, r6 + 2b98c: 4660 mov r0, ip + 2b98e: fa01 f705 lsl.w r7, r1, r5 + 2b992: ea47 070e orr.w r7, r7, lr + 2b996: f1c5 0501 rsb r5, r5, #1 + 2b99a: ea47 0106 orr.w r1, r7, r6 + 2b99e: b2ad uxth r5, r5 + 2b9a0: f441 1180 orr.w r1, r1, #1048576 ; 0x100000 + 2b9a4: ea4f 2981 mov.w r9, r1, lsl #10 + 2b9a8: f443 1380 orr.w r3, r3, #1048576 ; 0x100000 + 2b9ac: ea4f 2880 mov.w r8, r0, lsl #10 + 2b9b0: ea49 5990 orr.w r9, r9, r0, lsr #22 + 2b9b4: ea4f 2bc3 mov.w fp, r3, lsl #11 + 2b9b8: eb18 0008 adds.w r0, r8, r8 + 2b9bc: eb49 0109 adc.w r1, r9, r9 + 2b9c0: ea4b 5b52 orr.w fp, fp, r2, lsr #21 + 2b9c4: ea4f 2ac2 mov.w sl, r2, lsl #11 + 2b9c8: 4559 cmp r1, fp + 2b9ca: eba5 0404 sub.w r4, r5, r4 + 2b9ce: bf08 it eq + 2b9d0: 4550 cmpeq r0, sl + 2b9d2: b2a4 uxth r4, r4 + 2b9d4: d240 bcs.n 2ba58 <__rtl_ddiv_v1_00+0x1ac> + 2b9d6: f204 34fd addw r4, r4, #1021 ; 0x3fd + 2b9da: b2a4 uxth r4, r4 + 2b9dc: 9409 str r4, [sp, #36] ; 0x24 + 2b9de: 45d9 cmp r9, fp + 2b9e0: bf08 it eq + 2b9e2: 45d0 cmpeq r8, sl + 2b9e4: bf24 itt cs + 2b9e6: f04f 32ff movcs.w r2, #4294967295 + 2b9ea: f04f 33ff movcs.w r3, #4294967295 + 2b9ee: f0c0 8086 bcc.w 2bafe <__rtl_ddiv_v1_00+0x252> + 2b9f2: f240 70fc movw r0, #2044 ; 0x7fc + 2b9f6: f8dd 8024 ldr.w r8, [sp, #36] ; 0x24 + 2b9fa: fa1f f188 uxth.w r1, r8 + 2b9fe: 4281 cmp r1, r0 + 2ba00: d90b bls.n 2ba1a <__rtl_ddiv_v1_00+0x16e> + 2ba02: f240 74fd movw r4, #2045 ; 0x7fd + 2ba06: fa0f f088 sxth.w r0, r8 + 2ba0a: 42a0 cmp r0, r4 + 2ba0c: f300 81b4 bgt.w 2bd78 <__rtl_ddiv_v1_00+0x4cc> + 2ba10: f000 81ad beq.w 2bd6e <__rtl_ddiv_v1_00+0x4c2> + 2ba14: 2800 cmp r0, #0 + 2ba16: f2c0 81c5 blt.w 2bda4 <__rtl_ddiv_v1_00+0x4f8> + 2ba1a: 0a94 lsrs r4, r2, #10 + 2ba1c: ea44 5483 orr.w r4, r4, r3, lsl #22 + 2ba20: 0a9d lsrs r5, r3, #10 + 2ba22: ea54 0605 orrs.w r6, r4, r5 + 2ba26: bf06 itte eq + 2ba28: 4626 moveq r6, r4 + 2ba2a: 462f moveq r7, r5 + 2ba2c: f8dd 8024 ldrne.w r8, [sp, #36] ; 0x24 + 2ba30: f8dd 9020 ldr.w r9, [sp, #32] + 2ba34: f04f 0200 mov.w r2, #0 + 2ba38: bf1f itttt ne + 2ba3a: 2600 movne r6, #0 + 2ba3c: 2700 movne r7, #0 + 2ba3e: 2600 movne r6, #0 + 2ba40: ea4f 5708 movne.w r7, r8, lsl #20 + 2ba44: ea4f 73c9 mov.w r3, r9, lsl #31 + 2ba48: 18a0 adds r0, r4, r2 + 2ba4a: eb45 0103 adc.w r1, r5, r3 + 2ba4e: 1980 adds r0, r0, r6 + 2ba50: 4179 adcs r1, r7 + 2ba52: b013 add sp, #76 ; 0x4c + 2ba54: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 2ba58: f204 34fe addw r4, r4, #1022 ; 0x3fe + 2ba5c: b2a4 uxth r4, r4 + 2ba5e: ea5f 0959 movs.w r9, r9, lsr #1 + 2ba62: ea4f 0838 mov.w r8, r8, rrx + 2ba66: 9409 str r4, [sp, #36] ; 0x24 + 2ba68: e7b9 b.n 2b9de <__rtl_ddiv_v1_00+0x132> + 2ba6a: f241 56a0 movw r6, #5536 ; 0x15a0 + 2ba6e: 2b01 cmp r3, #1 + 2ba70: bf08 it eq + 2ba72: 2a00 cmpeq r2, #0 + 2ba74: bf2c ite cs + 2ba76: 461c movcs r4, r3 + 2ba78: 4614 movcc r4, r2 + 2ba7a: f2c0 0603 movt r6, #3 + 2ba7e: bf2c ite cs + 2ba80: f04f 0ef5 movcs.w lr, #245 ; 0xf5 + 2ba84: f04f 0e15 movcc.w lr, #21 + 2ba88: f5b4 3f80 cmp.w r4, #65536 ; 0x10000 + 2ba8c: bf3a itte cc + 2ba8e: 0424 lslcc r4, r4, #16 + 2ba90: 2710 movcc r7, #16 + 2ba92: 2700 movcs r7, #0 + 2ba94: f1b4 7f80 cmp.w r4, #16777216 ; 0x1000000 + 2ba98: bf3c itt cc + 2ba9a: 0224 lslcc r4, r4, #8 + 2ba9c: 3708 addcc r7, #8 + 2ba9e: ea4f 6414 mov.w r4, r4, lsr #24 + 2baa2: 5d36 ldrb r6, [r6, r4] + 2baa4: bf38 it cc + 2baa6: b2ff uxtbcc r7, r7 + 2baa8: eb07 040e add.w r4, r7, lr + 2baac: 4434 add r4, r6 + 2baae: b2e4 uxtb r4, r4 + 2bab0: f1a4 0e20 sub.w lr, r4, #32 + 2bab4: fa03 f704 lsl.w r7, r3, r4 + 2bab8: f1c4 0620 rsb r6, r4, #32 + 2babc: fa02 fe0e lsl.w lr, r2, lr + 2bac0: fa22 f606 lsr.w r6, r2, r6 + 2bac4: fa02 fc04 lsl.w ip, r2, r4 + 2bac8: ea47 070e orr.w r7, r7, lr + 2bacc: f1c4 0401 rsb r4, r4, #1 + 2bad0: 4662 mov r2, ip + 2bad2: ea47 0306 orr.w r3, r7, r6 + 2bad6: b2a4 uxth r4, r4 + 2bad8: e707 b.n 2b8ea <__rtl_ddiv_v1_00+0x3e> + 2bada: 2100 movs r1, #0 + 2badc: f6c7 71f0 movt r1, #32752 ; 0x7ff0 + 2bae0: 2200 movs r2, #0 + 2bae2: 2000 movs r0, #0 + 2bae4: 1880 adds r0, r0, r2 + 2bae6: ea4f 73c8 mov.w r3, r8, lsl #31 + 2baea: 4159 adcs r1, r3 + 2baec: b013 add sp, #76 ; 0x4c + 2baee: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 2baf2: 9a08 ldr r2, [sp, #32] + 2baf4: 2000 movs r0, #0 + 2baf6: 07d1 lsls r1, r2, #31 + 2baf8: b013 add sp, #76 ; 0x4c + 2bafa: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 2bafe: 2400 movs r4, #0 + 2bb00: 464a mov r2, r9 + 2bb02: 4623 mov r3, r4 + 2bb04: ea52 0503 orrs.w r5, r2, r3 + 2bb08: f8cd b008 str.w fp, [sp, #8] + 2bb0c: 9403 str r4, [sp, #12] + 2bb0e: e9cd 8910 strd r8, r9, [sp, #64] ; 0x40 + 2bb12: 46dc mov ip, fp + 2bb14: f040 818b bne.w 2be2e <__rtl_ddiv_v1_00+0x582> + 2bb18: fbb8 f3fb udiv r3, r8, fp + 2bb1c: 9310 str r3, [sp, #64] ; 0x40 + 2bb1e: 9f02 ldr r7, [sp, #8] + 2bb20: 2000 movs r0, #0 + 2bb22: 9707 str r7, [sp, #28] + 2bb24: 9006 str r0, [sp, #24] + 2bb26: e9dd 2306 ldrd r2, r3, [sp, #24] + 2bb2a: 4599 cmp r9, r3 + 2bb2c: bf08 it eq + 2bb2e: 4590 cmpeq r8, r2 + 2bb30: f080 8130 bcs.w 2bd94 <__rtl_ddiv_v1_00+0x4e8> + 2bb34: 9d10 ldr r5, [sp, #64] ; 0x40 + 2bb36: 920a str r2, [sp, #40] ; 0x28 + 2bb38: 4629 mov r1, r5 + 2bb3a: 950b str r5, [sp, #44] ; 0x2c + 2bb3c: 4652 mov r2, sl + 2bb3e: 2300 movs r3, #0 + 2bb40: e9cd 2304 strd r2, r3, [sp, #16] + 2bb44: 9c04 ldr r4, [sp, #16] + 2bb46: 9d05 ldr r5, [sp, #20] + 2bb48: fba1 2304 umull r2, r3, r1, r4 + 2bb4c: fb01 3305 mla r3, r1, r5, r3 + 2bb50: 4617 mov r7, r2 + 2bb52: 461c mov r4, r3 + 2bb54: f8dd e008 ldr.w lr, [sp, #8] + 2bb58: 9803 ldr r0, [sp, #12] + 2bb5a: fba1 230e umull r2, r3, r1, lr + 2bb5e: fb01 3300 mla r3, r1, r0, r3 + 2bb62: 2600 movs r6, #0 + 2bb64: ebb8 0202 subs.w r2, r8, r2 + 2bb68: eb69 0303 sbc.w r3, r9, r3 + 2bb6c: 1bb9 subs r1, r7, r6 + 2bb6e: bf18 it ne + 2bb70: 2101 movne r1, #1 + 2bb72: 1b12 subs r2, r2, r4 + 2bb74: eb63 0306 sbc.w r3, r3, r6 + 2bb78: 1a52 subs r2, r2, r1 + 2bb7a: f163 0300 sbc.w r3, r3, #0 + 2bb7e: 4274 negs r4, r6 + 2bb80: eb67 0547 sbc.w r5, r7, r7, lsl #1 + 2bb84: 2a00 cmp r2, #0 + 2bb86: f173 0100 sbcs.w r1, r3, #0 + 2bb8a: f280 8141 bge.w 2be10 <__rtl_ddiv_v1_00+0x564> + 2bb8e: 4651 mov r1, sl + 2bb90: 4630 mov r0, r6 + 2bb92: e9dd 670a ldrd r6, r7, [sp, #40] ; 0x28 + 2bb96: e9cd ab0e strd sl, fp, [sp, #56] ; 0x38 + 2bb9a: e9cd 890c strd r8, r9, [sp, #48] ; 0x30 + 2bb9e: e9dd 8902 ldrd r8, r9, [sp, #8] + 2bba2: 4682 mov sl, r0 + 2bba4: 468b mov fp, r1 + 2bba6: e001 b.n 2bbac <__rtl_ddiv_v1_00+0x300> + 2bba8: 4604 mov r4, r0 + 2bbaa: 460d mov r5, r1 + 2bbac: eb14 000a adds.w r0, r4, sl + 2bbb0: eb45 010b adc.w r1, r5, fp + 2bbb4: 3600 adds r6, #0 + 2bbb6: f147 37ff adc.w r7, r7, #4294967295 + 2bbba: 42a9 cmp r1, r5 + 2bbbc: bf08 it eq + 2bbbe: 42a0 cmpeq r0, r4 + 2bbc0: bf34 ite cc + 2bbc2: f04f 0e01 movcc.w lr, #1 + 2bbc6: f04f 0e00 movcs.w lr, #0 + 2bbca: eb18 040e adds.w r4, r8, lr + 2bbce: f149 0500 adc.w r5, r9, #0 + 2bbd2: 1912 adds r2, r2, r4 + 2bbd4: 416b adcs r3, r5 + 2bbd6: 2a00 cmp r2, #0 + 2bbd8: f173 0400 sbcs.w r4, r3, #0 + 2bbdc: dbe4 blt.n 2bba8 <__rtl_ddiv_v1_00+0x2fc> + 2bbde: e9cd 670a strd r6, r7, [sp, #40] ; 0x28 + 2bbe2: e9dd 890c ldrd r8, r9, [sp, #48] ; 0x30 + 2bbe6: e9dd ab0e ldrd sl, fp, [sp, #56] ; 0x38 + 2bbea: 2600 movs r6, #0 + 2bbec: 4617 mov r7, r2 + 2bbee: 4635 mov r5, r6 + 2bbf0: 433d orrs r5, r7 + 2bbf2: 460c mov r4, r1 + 2bbf4: 462a mov r2, r5 + 2bbf6: 4633 mov r3, r6 + 2bbf8: 4334 orrs r4, r6 + 2bbfa: ea52 0e03 orrs.w lr, r2, r3 + 2bbfe: e9cd 4510 strd r4, r5, [sp, #64] ; 0x40 + 2bc02: f040 811d bne.w 2be40 <__rtl_ddiv_v1_00+0x594> + 2bc06: fbb4 f3fc udiv r3, r4, ip + 2bc0a: 9611 str r6, [sp, #68] ; 0x44 + 2bc0c: 9310 str r3, [sp, #64] ; 0x40 + 2bc0e: e9dd 2306 ldrd r2, r3, [sp, #24] + 2bc12: 429d cmp r5, r3 + 2bc14: bf08 it eq + 2bc16: 4294 cmpeq r4, r2 + 2bc18: bf24 itt cs + 2bc1a: f04f 32ff movcs.w r2, #4294967295 + 2bc1e: 2300 movcs r3, #0 + 2bc20: d201 bcs.n 2bc26 <__rtl_ddiv_v1_00+0x37a> + 2bc22: e9dd 2310 ldrd r2, r3, [sp, #64] ; 0x40 + 2bc26: e9dd 450a ldrd r4, r5, [sp, #40] ; 0x28 + 2bc2a: f240 10ff movw r0, #511 ; 0x1ff + 2bc2e: 432b orrs r3, r5 + 2bc30: 2100 movs r1, #0 + 2bc32: 4322 orrs r2, r4 + 2bc34: 4019 ands r1, r3 + 2bc36: 4010 ands r0, r2 + 2bc38: 2900 cmp r1, #0 + 2bc3a: bf08 it eq + 2bc3c: 2803 cmpeq r0, #3 + 2bc3e: f4bf aed8 bcs.w 2b9f2 <__rtl_ddiv_v1_00+0x146> + 2bc42: 9904 ldr r1, [sp, #16] + 2bc44: 9e03 ldr r6, [sp, #12] + 2bc46: fba3 0101 umull r0, r1, r3, r1 + 2bc4a: fb02 fe06 mul.w lr, r2, r6 + 2bc4e: f8dd c014 ldr.w ip, [sp, #20] + 2bc52: 9e02 ldr r6, [sp, #8] + 2bc54: 2500 movs r5, #0 + 2bc56: fb03 1c0c mla ip, r3, ip, r1 + 2bc5a: fb06 ee05 mla lr, r6, r5, lr + 2bc5e: fba2 6706 umull r6, r7, r2, r6 + 2bc62: e9cd 0106 strd r0, r1, [sp, #24] + 2bc66: f8cd c01c str.w ip, [sp, #28] + 2bc6a: 4477 add r7, lr + 2bc6c: e9dd 0106 ldrd r0, r1, [sp, #24] + 2bc70: 1980 adds r0, r0, r6 + 2bc72: 4179 adcs r1, r7 + 2bc74: e9cd 0106 strd r0, r1, [sp, #24] + 2bc78: 9905 ldr r1, [sp, #20] + 2bc7a: f8dd c010 ldr.w ip, [sp, #16] + 2bc7e: fb02 f101 mul.w r1, r2, r1 + 2bc82: fb0c 1e05 mla lr, ip, r5, r1 + 2bc86: fba2 010c umull r0, r1, r2, ip + 2bc8a: f8dd c008 ldr.w ip, [sp, #8] + 2bc8e: e9cd 0104 strd r0, r1, [sp, #16] + 2bc92: fba3 450c umull r4, r5, r3, ip + 2bc96: 4471 add r1, lr + 2bc98: 9105 str r1, [sp, #20] + 2bc9a: f8dd e00c ldr.w lr, [sp, #12] + 2bc9e: e9dd 0106 ldrd r0, r1, [sp, #24] + 2bca2: 42b9 cmp r1, r7 + 2bca4: bf08 it eq + 2bca6: 42b0 cmpeq r0, r6 + 2bca8: fb03 550e mla r5, r3, lr, r5 + 2bcac: f0c0 80ab bcc.w 2be06 <__rtl_ddiv_v1_00+0x55a> + 2bcb0: 2000 movs r0, #0 + 2bcb2: 2100 movs r1, #0 + 2bcb4: e9cd 010c strd r0, r1, [sp, #48] ; 0x30 + 2bcb8: 9906 ldr r1, [sp, #24] + 2bcba: 2700 movs r7, #0 + 2bcbc: ebb8 0004 subs.w r0, r8, r4 + 2bcc0: 9103 str r1, [sp, #12] + 2bcc2: 9702 str r7, [sp, #8] + 2bcc4: 9e07 ldr r6, [sp, #28] + 2bcc6: eb69 0105 sbc.w r1, r9, r5 + 2bcca: e9dd 8904 ldrd r8, r9, [sp, #16] + 2bcce: e9dd 4502 ldrd r4, r5, [sp, #8] + 2bcd2: eb14 0408 adds.w r4, r4, r8 + 2bcd6: eb45 0509 adc.w r5, r5, r9 + 2bcda: 960a str r6, [sp, #40] ; 0x28 + 2bcdc: 970b str r7, [sp, #44] ; 0x2c + 2bcde: 4266 negs r6, r4 + 2bce0: e9dd 890a ldrd r8, r9, [sp, #40] ; 0x28 + 2bce4: eb65 0745 sbc.w r7, r5, r5, lsl #1 + 2bce8: ebb0 0008 subs.w r0, r0, r8 + 2bcec: eb61 0109 sbc.w r1, r1, r9 + 2bcf0: ea54 0905 orrs.w r9, r4, r5 + 2bcf4: bf14 ite ne + 2bcf6: f04f 0e01 movne.w lr, #1 + 2bcfa: f04f 0e00 moveq.w lr, #0 + 2bcfe: ebb0 000e subs.w r0, r0, lr + 2bd02: f161 0100 sbc.w r1, r1, #0 + 2bd06: e9dd 8902 ldrd r8, r9, [sp, #8] + 2bd0a: 454d cmp r5, r9 + 2bd0c: bf08 it eq + 2bd0e: 4544 cmpeq r4, r8 + 2bd10: bf34 ite cc + 2bd12: 2401 movcc r4, #1 + 2bd14: 2400 movcs r4, #0 + 2bd16: 1b00 subs r0, r0, r4 + 2bd18: f161 0100 sbc.w r1, r1, #0 + 2bd1c: e9dd 450c ldrd r4, r5, [sp, #48] ; 0x30 + 2bd20: 1b00 subs r0, r0, r4 + 2bd22: eb61 0105 sbc.w r1, r1, r5 + 2bd26: 2800 cmp r0, #0 + 2bd28: f171 0500 sbcs.w r5, r1, #0 + 2bd2c: db02 blt.n 2bd34 <__rtl_ddiv_v1_00+0x488> + 2bd2e: e071 b.n 2be14 <__rtl_ddiv_v1_00+0x568> + 2bd30: 4626 mov r6, r4 + 2bd32: 462f mov r7, r5 + 2bd34: eb16 040a adds.w r4, r6, sl + 2bd38: eb47 050b adc.w r5, r7, fp + 2bd3c: f112 32ff adds.w r2, r2, #4294967295 + 2bd40: f143 33ff adc.w r3, r3, #4294967295 + 2bd44: 42bd cmp r5, r7 + 2bd46: bf08 it eq + 2bd48: 42b4 cmpeq r4, r6 + 2bd4a: bf34 ite cc + 2bd4c: 2601 movcc r6, #1 + 2bd4e: 2600 movcs r6, #0 + 2bd50: 1980 adds r0, r0, r6 + 2bd52: f141 0100 adc.w r1, r1, #0 + 2bd56: 2800 cmp r0, #0 + 2bd58: f171 0600 sbcs.w r6, r1, #0 + 2bd5c: dbe8 blt.n 2bd30 <__rtl_ddiv_v1_00+0x484> + 2bd5e: ea54 0705 orrs.w r7, r4, r5 + 2bd62: bf14 ite ne + 2bd64: 2101 movne r1, #1 + 2bd66: 2100 moveq r1, #0 + 2bd68: ea42 0201 orr.w r2, r2, r1 + 2bd6c: e641 b.n 2b9f2 <__rtl_ddiv_v1_00+0x146> + 2bd6e: 2a00 cmp r2, #0 + 2bd70: f173 0900 sbcs.w r9, r3, #0 + 2bd74: f6bf ae51 bge.w 2ba1a <__rtl_ddiv_v1_00+0x16e> + 2bd78: f64f 71ff movw r1, #65535 ; 0xffff + 2bd7c: f6c7 71ef movt r1, #32751 ; 0x7fef + 2bd80: f8dd c020 ldr.w ip, [sp, #32] + 2bd84: f04f 30ff mov.w r0, #4294967295 + 2bd88: 2200 movs r2, #0 + 2bd8a: ea4f 73cc mov.w r3, ip, lsl #31 + 2bd8e: 1880 adds r0, r0, r2 + 2bd90: 4159 adcs r1, r3 + 2bd92: e5cb b.n 2b92c <__rtl_ddiv_v1_00+0x80> + 2bd94: 2600 movs r6, #0 + 2bd96: f04f 37ff mov.w r7, #4294967295 + 2bd9a: e9cd 670a strd r6, r7, [sp, #40] ; 0x28 + 2bd9e: f04f 31ff mov.w r1, #4294967295 + 2bda2: e6cb b.n 2bb3c <__rtl_ddiv_v1_00+0x290> + 2bda4: 4249 negs r1, r1 + 2bda6: b20e sxth r6, r1 + 2bda8: 2e3f cmp r6, #63 ; 0x3f + 2bdaa: dc36 bgt.n 2be1a <__rtl_ddiv_v1_00+0x56e> + 2bdac: 4275 negs r5, r6 + 2bdae: f005 053f and.w r5, r5, #63 ; 0x3f + 2bdb2: f1a5 0e20 sub.w lr, r5, #32 + 2bdb6: fa03 f405 lsl.w r4, r3, r5 + 2bdba: fa02 fe0e lsl.w lr, r2, lr + 2bdbe: f1c5 0720 rsb r7, r5, #32 + 2bdc2: fa22 f707 lsr.w r7, r2, r7 + 2bdc6: ea44 040e orr.w r4, r4, lr + 2bdca: 433c orrs r4, r7 + 2bdcc: f1c6 0720 rsb r7, r6, #32 + 2bdd0: fa02 f505 lsl.w r5, r2, r5 + 2bdd4: fa22 f006 lsr.w r0, r2, r6 + 2bdd8: fa03 f707 lsl.w r7, r3, r7 + 2bddc: f1a6 0220 sub.w r2, r6, #32 + 2bde0: 432c orrs r4, r5 + 2bde2: fa23 f202 lsr.w r2, r3, r2 + 2bde6: ea40 0007 orr.w r0, r0, r7 + 2bdea: f04f 0500 mov.w r5, #0 + 2bdee: bf14 ite ne + 2bdf0: 2401 movne r4, #1 + 2bdf2: 2400 moveq r4, #0 + 2bdf4: 4310 orrs r0, r2 + 2bdf6: fa23 f106 lsr.w r1, r3, r6 + 2bdfa: ea44 0200 orr.w r2, r4, r0 + 2bdfe: ea45 0301 orr.w r3, r5, r1 + 2be02: 9509 str r5, [sp, #36] ; 0x24 + 2be04: e609 b.n 2ba1a <__rtl_ddiv_v1_00+0x16e> + 2be06: 2600 movs r6, #0 + 2be08: 2701 movs r7, #1 + 2be0a: e9cd 670c strd r6, r7, [sp, #48] ; 0x30 + 2be0e: e753 b.n 2bcb8 <__rtl_ddiv_v1_00+0x40c> + 2be10: 4629 mov r1, r5 + 2be12: e6ea b.n 2bbea <__rtl_ddiv_v1_00+0x33e> + 2be14: 4634 mov r4, r6 + 2be16: 463d mov r5, r7 + 2be18: e7a1 b.n 2bd5e <__rtl_ddiv_v1_00+0x4b2> + 2be1a: ea52 0e03 orrs.w lr, r2, r3 + 2be1e: bf14 ite ne + 2be20: 2201 movne r2, #1 + 2be22: 2200 moveq r2, #0 + 2be24: 2400 movs r4, #0 + 2be26: b2d2 uxtb r2, r2 + 2be28: 2300 movs r3, #0 + 2be2a: 9409 str r4, [sp, #36] ; 0x24 + 2be2c: e5f5 b.n 2ba1a <__rtl_ddiv_v1_00+0x16e> + 2be2e: a810 add r0, sp, #64 ; 0x40 + 2be30: 9902 ldr r1, [sp, #8] + 2be32: f8cd b004 str.w fp, [sp, #4] + 2be36: f7fd fc7f bl 29738 <__rtl_div64_32> + 2be3a: f8dd c004 ldr.w ip, [sp, #4] + 2be3e: e66e b.n 2bb1e <__rtl_ddiv_v1_00+0x272> + 2be40: 4661 mov r1, ip + 2be42: a810 add r0, sp, #64 ; 0x40 + 2be44: f7fd fc78 bl 29738 <__rtl_div64_32> + 2be48: e6e1 b.n 2bc0e <__rtl_ddiv_v1_00+0x362> + 2be4a: bf00 nop + +0002be4c <__rtl_dcmpeq_v1_00>: + 2be4c: b470 push {r4, r5, r6} + 2be4e: f240 74ff movw r4, #2047 ; 0x7ff + 2be52: f3c1 550a ubfx r5, r1, #20, #11 + 2be56: 42a5 cmp r5, r4 + 2be58: d015 beq.n 2be86 <__rtl_dcmpeq_v1_00+0x3a> + 2be5a: f240 74ff movw r4, #2047 ; 0x7ff + 2be5e: f3c3 550a ubfx r5, r3, #20, #11 + 2be62: 42a5 cmp r5, r4 + 2be64: d01d beq.n 2bea2 <__rtl_dcmpeq_v1_00+0x56> + 2be66: 4299 cmp r1, r3 + 2be68: bf04 itt eq + 2be6a: 4290 cmpeq r0, r2 + 2be6c: 2001 moveq r0, #1 + 2be6e: d008 beq.n 2be82 <__rtl_dcmpeq_v1_00+0x36> + 2be70: 4302 orrs r2, r0 + 2be72: 430b orrs r3, r1 + 2be74: 1892 adds r2, r2, r2 + 2be76: 415b adcs r3, r3 + 2be78: ea52 0103 orrs.w r1, r2, r3 + 2be7c: bf0c ite eq + 2be7e: 2001 moveq r0, #1 + 2be80: 2000 movne r0, #0 + 2be82: bc70 pop {r4, r5, r6} + 2be84: 4770 bx lr + 2be86: f64f 75ff movw r5, #65535 ; 0xffff + 2be8a: f2c0 050f movt r5, #15 + 2be8e: f04f 34ff mov.w r4, #4294967295 + 2be92: 4004 ands r4, r0 + 2be94: 400d ands r5, r1 + 2be96: ea54 0605 orrs.w r6, r4, r5 + 2be9a: d0de beq.n 2be5a <__rtl_dcmpeq_v1_00+0xe> + 2be9c: bc70 pop {r4, r5, r6} + 2be9e: 2000 movs r0, #0 + 2bea0: 4770 bx lr + 2bea2: f64f 75ff movw r5, #65535 ; 0xffff + 2bea6: f2c0 050f movt r5, #15 + 2beaa: f04f 34ff mov.w r4, #4294967295 + 2beae: 4014 ands r4, r2 + 2beb0: 401d ands r5, r3 + 2beb2: ea54 0605 orrs.w r6, r4, r5 + 2beb6: d0d6 beq.n 2be66 <__rtl_dcmpeq_v1_00+0x1a> + 2beb8: e7f0 b.n 2be9c <__rtl_dcmpeq_v1_00+0x50> + 2beba: bf00 nop + +0002bebc <__rtl_dcmplt_v1_00>: + 2bebc: b470 push {r4, r5, r6} + 2bebe: f240 74ff movw r4, #2047 ; 0x7ff + 2bec2: f3c1 550a ubfx r5, r1, #20, #11 + 2bec6: 42a5 cmp r5, r4 + 2bec8: d018 beq.n 2befc <__rtl_dcmplt_v1_00+0x40> + 2beca: f240 74ff movw r4, #2047 ; 0x7ff + 2bece: f3c3 550a ubfx r5, r3, #20, #11 + 2bed2: 42a5 cmp r5, r4 + 2bed4: d020 beq.n 2bf18 <__rtl_dcmplt_v1_00+0x5c> + 2bed6: 0fcc lsrs r4, r1, #31 + 2bed8: ebb4 7fd3 cmp.w r4, r3, lsr #31 + 2bedc: d02b beq.n 2bf36 <__rtl_dcmplt_v1_00+0x7a> + 2bede: b914 cbnz r4, 2bee6 <__rtl_dcmplt_v1_00+0x2a> + 2bee0: 4620 mov r0, r4 + 2bee2: bc70 pop {r4, r5, r6} + 2bee4: 4770 bx lr + 2bee6: 4302 orrs r2, r0 + 2bee8: 430b orrs r3, r1 + 2beea: 1892 adds r2, r2, r2 + 2beec: 415b adcs r3, r3 + 2beee: ea52 0103 orrs.w r1, r2, r3 + 2bef2: bf14 ite ne + 2bef4: 2001 movne r0, #1 + 2bef6: 2000 moveq r0, #0 + 2bef8: bc70 pop {r4, r5, r6} + 2befa: 4770 bx lr + 2befc: f64f 75ff movw r5, #65535 ; 0xffff + 2bf00: f2c0 050f movt r5, #15 + 2bf04: f04f 34ff mov.w r4, #4294967295 + 2bf08: 4004 ands r4, r0 + 2bf0a: 400d ands r5, r1 + 2bf0c: ea54 0605 orrs.w r6, r4, r5 + 2bf10: d0db beq.n 2beca <__rtl_dcmplt_v1_00+0xe> + 2bf12: bc70 pop {r4, r5, r6} + 2bf14: 2000 movs r0, #0 + 2bf16: 4770 bx lr + 2bf18: f64f 75ff movw r5, #65535 ; 0xffff + 2bf1c: f2c0 050f movt r5, #15 + 2bf20: f04f 34ff mov.w r4, #4294967295 + 2bf24: 4014 ands r4, r2 + 2bf26: 401d ands r5, r3 + 2bf28: ea54 0605 orrs.w r6, r4, r5 + 2bf2c: d1f1 bne.n 2bf12 <__rtl_dcmplt_v1_00+0x56> + 2bf2e: 0fcc lsrs r4, r1, #31 + 2bf30: ebb4 7fd3 cmp.w r4, r3, lsr #31 + 2bf34: d1d3 bne.n 2bede <__rtl_dcmplt_v1_00+0x22> + 2bf36: 4299 cmp r1, r3 + 2bf38: bf08 it eq + 2bf3a: 4290 cmpeq r0, r2 + 2bf3c: d0e9 beq.n 2bf12 <__rtl_dcmplt_v1_00+0x56> + 2bf3e: bf34 ite cc + 2bf40: 2001 movcc r0, #1 + 2bf42: 2000 movcs r0, #0 + 2bf44: 1a20 subs r0, r4, r0 + 2bf46: bf18 it ne + 2bf48: 2001 movne r0, #1 + 2bf4a: bc70 pop {r4, r5, r6} + 2bf4c: 4770 bx lr + 2bf4e: bf00 nop + +0002bf50 <__rtl_dcmpgt_v1_00>: + 2bf50: b5f0 push {r4, r5, r6, r7, lr} + 2bf52: f240 74ff movw r4, #2047 ; 0x7ff + 2bf56: f3c1 560a ubfx r6, r1, #20, #11 + 2bf5a: 42a6 cmp r6, r4 + 2bf5c: d04e beq.n 2bffc <__rtl_dcmpgt_v1_00+0xac> + 2bf5e: f240 74ff movw r4, #2047 ; 0x7ff + 2bf62: f3c3 5e0a ubfx lr, r3, #20, #11 + 2bf66: 45a6 cmp lr, r4 + 2bf68: d055 beq.n 2c016 <__rtl_dcmpgt_v1_00+0xc6> + 2bf6a: 0fcf lsrs r7, r1, #31 + 2bf6c: ebb7 7fd3 cmp.w r7, r3, lsr #31 + 2bf70: d05e beq.n 2c030 <__rtl_dcmpgt_v1_00+0xe0> + 2bf72: b9cf cbnz r7, 2bfa8 <__rtl_dcmpgt_v1_00+0x58> + 2bf74: f240 74ff movw r4, #2047 ; 0x7ff + 2bf78: 42a6 cmp r6, r4 + 2bf7a: d024 beq.n 2bfc6 <__rtl_dcmpgt_v1_00+0x76> + 2bf7c: f240 74ff movw r4, #2047 ; 0x7ff + 2bf80: 45a6 cmp lr, r4 + 2bf82: d02f beq.n 2bfe4 <__rtl_dcmpgt_v1_00+0x94> + 2bf84: 4299 cmp r1, r3 + 2bf86: bf04 itt eq + 2bf88: 4290 cmpeq r0, r2 + 2bf8a: 2001 moveq r0, #1 + 2bf8c: d008 beq.n 2bfa0 <__rtl_dcmpgt_v1_00+0x50> + 2bf8e: 4302 orrs r2, r0 + 2bf90: 430b orrs r3, r1 + 2bf92: 1892 adds r2, r2, r2 + 2bf94: 415b adcs r3, r3 + 2bf96: ea52 0103 orrs.w r1, r2, r3 + 2bf9a: bf0c ite eq + 2bf9c: 2001 moveq r0, #1 + 2bf9e: 2000 movne r0, #0 + 2bfa0: 4307 orrs r7, r0 + 2bfa2: f087 0001 eor.w r0, r7, #1 + 2bfa6: bdf0 pop {r4, r5, r6, r7, pc} + 2bfa8: ea40 0402 orr.w r4, r0, r2 + 2bfac: 1924 adds r4, r4, r4 + 2bfae: ea41 0503 orr.w r5, r1, r3 + 2bfb2: 416d adcs r5, r5 + 2bfb4: ea54 0705 orrs.w r7, r4, r5 + 2bfb8: f240 74ff movw r4, #2047 ; 0x7ff + 2bfbc: bf14 ite ne + 2bfbe: 2701 movne r7, #1 + 2bfc0: 2700 moveq r7, #0 + 2bfc2: 42a6 cmp r6, r4 + 2bfc4: d1da bne.n 2bf7c <__rtl_dcmpgt_v1_00+0x2c> + 2bfc6: f64f 75ff movw r5, #65535 ; 0xffff + 2bfca: f2c0 050f movt r5, #15 + 2bfce: f04f 34ff mov.w r4, #4294967295 + 2bfd2: 4004 ands r4, r0 + 2bfd4: 400d ands r5, r1 + 2bfd6: ea54 0605 orrs.w r6, r4, r5 + 2bfda: d1e2 bne.n 2bfa2 <__rtl_dcmpgt_v1_00+0x52> + 2bfdc: f240 74ff movw r4, #2047 ; 0x7ff + 2bfe0: 45a6 cmp lr, r4 + 2bfe2: d1cf bne.n 2bf84 <__rtl_dcmpgt_v1_00+0x34> + 2bfe4: f64f 75ff movw r5, #65535 ; 0xffff + 2bfe8: f2c0 050f movt r5, #15 + 2bfec: f04f 34ff mov.w r4, #4294967295 + 2bff0: 4014 ands r4, r2 + 2bff2: 401d ands r5, r3 + 2bff4: ea54 0605 orrs.w r6, r4, r5 + 2bff8: d0c4 beq.n 2bf84 <__rtl_dcmpgt_v1_00+0x34> + 2bffa: e7d2 b.n 2bfa2 <__rtl_dcmpgt_v1_00+0x52> + 2bffc: f64f 75ff movw r5, #65535 ; 0xffff + 2c000: f2c0 050f movt r5, #15 + 2c004: f04f 34ff mov.w r4, #4294967295 + 2c008: 4004 ands r4, r0 + 2c00a: 400d ands r5, r1 + 2c00c: ea54 0705 orrs.w r7, r4, r5 + 2c010: d0a5 beq.n 2bf5e <__rtl_dcmpgt_v1_00+0xe> + 2c012: 2001 movs r0, #1 + 2c014: bdf0 pop {r4, r5, r6, r7, pc} + 2c016: f64f 75ff movw r5, #65535 ; 0xffff + 2c01a: f2c0 050f movt r5, #15 + 2c01e: f04f 34ff mov.w r4, #4294967295 + 2c022: 4014 ands r4, r2 + 2c024: 401d ands r5, r3 + 2c026: ea54 0705 orrs.w r7, r4, r5 + 2c02a: d09e beq.n 2bf6a <__rtl_dcmpgt_v1_00+0x1a> + 2c02c: 2700 movs r7, #0 + 2c02e: e7a1 b.n 2bf74 <__rtl_dcmpgt_v1_00+0x24> + 2c030: 4299 cmp r1, r3 + 2c032: bf08 it eq + 2c034: 4290 cmpeq r0, r2 + 2c036: d0f9 beq.n 2c02c <__rtl_dcmpgt_v1_00+0xdc> + 2c038: bf34 ite cc + 2c03a: 2401 movcc r4, #1 + 2c03c: 2400 movcs r4, #0 + 2c03e: 1b3f subs r7, r7, r4 + 2c040: bf18 it ne + 2c042: 2701 movne r7, #1 + 2c044: e796 b.n 2bf74 <__rtl_dcmpgt_v1_00+0x24> + 2c046: bf00 nop + +0002c048 <__rtl_dcmple_v1_00>: + 2c048: b5f0 push {r4, r5, r6, r7, lr} + 2c04a: f240 74ff movw r4, #2047 ; 0x7ff + 2c04e: f3c1 560a ubfx r6, r1, #20, #11 + 2c052: 42a6 cmp r6, r4 + 2c054: d03e beq.n 2c0d4 <__rtl_dcmple_v1_00+0x8c> + 2c056: f240 74ff movw r4, #2047 ; 0x7ff + 2c05a: f3c3 5e0a ubfx lr, r3, #20, #11 + 2c05e: 45a6 cmp lr, r4 + 2c060: d045 beq.n 2c0ee <__rtl_dcmple_v1_00+0xa6> + 2c062: 0fcf lsrs r7, r1, #31 + 2c064: ebb7 7fd3 cmp.w r7, r3, lsr #31 + 2c068: d05a beq.n 2c120 <__rtl_dcmple_v1_00+0xd8> + 2c06a: b9bf cbnz r7, 2c09c <__rtl_dcmple_v1_00+0x54> + 2c06c: f240 74ff movw r4, #2047 ; 0x7ff + 2c070: 42a6 cmp r6, r4 + 2c072: d022 beq.n 2c0ba <__rtl_dcmple_v1_00+0x72> + 2c074: f240 74ff movw r4, #2047 ; 0x7ff + 2c078: 45a6 cmp lr, r4 + 2c07a: d045 beq.n 2c108 <__rtl_dcmple_v1_00+0xc0> + 2c07c: 4299 cmp r1, r3 + 2c07e: bf04 itt eq + 2c080: 4290 cmpeq r0, r2 + 2c082: 2001 moveq r0, #1 + 2c084: d008 beq.n 2c098 <__rtl_dcmple_v1_00+0x50> + 2c086: 4302 orrs r2, r0 + 2c088: 430b orrs r3, r1 + 2c08a: 1892 adds r2, r2, r2 + 2c08c: 415b adcs r3, r3 + 2c08e: ea52 0103 orrs.w r1, r2, r3 + 2c092: bf0c ite eq + 2c094: 2001 moveq r0, #1 + 2c096: 2000 movne r0, #0 + 2c098: 4338 orrs r0, r7 + 2c09a: bdf0 pop {r4, r5, r6, r7, pc} + 2c09c: ea40 0402 orr.w r4, r0, r2 + 2c0a0: 1924 adds r4, r4, r4 + 2c0a2: ea41 0503 orr.w r5, r1, r3 + 2c0a6: 416d adcs r5, r5 + 2c0a8: ea54 0705 orrs.w r7, r4, r5 + 2c0ac: f240 74ff movw r4, #2047 ; 0x7ff + 2c0b0: bf14 ite ne + 2c0b2: 2701 movne r7, #1 + 2c0b4: 2700 moveq r7, #0 + 2c0b6: 42a6 cmp r6, r4 + 2c0b8: d1dc bne.n 2c074 <__rtl_dcmple_v1_00+0x2c> + 2c0ba: f64f 75ff movw r5, #65535 ; 0xffff + 2c0be: f2c0 050f movt r5, #15 + 2c0c2: f04f 34ff mov.w r4, #4294967295 + 2c0c6: 4004 ands r4, r0 + 2c0c8: 400d ands r5, r1 + 2c0ca: ea54 0605 orrs.w r6, r4, r5 + 2c0ce: d0d1 beq.n 2c074 <__rtl_dcmple_v1_00+0x2c> + 2c0d0: 4638 mov r0, r7 + 2c0d2: bdf0 pop {r4, r5, r6, r7, pc} + 2c0d4: f64f 75ff movw r5, #65535 ; 0xffff + 2c0d8: f2c0 050f movt r5, #15 + 2c0dc: f04f 34ff mov.w r4, #4294967295 + 2c0e0: 4004 ands r4, r0 + 2c0e2: 400d ands r5, r1 + 2c0e4: ea54 0705 orrs.w r7, r4, r5 + 2c0e8: d0b5 beq.n 2c056 <__rtl_dcmple_v1_00+0xe> + 2c0ea: 2000 movs r0, #0 + 2c0ec: bdf0 pop {r4, r5, r6, r7, pc} + 2c0ee: f64f 75ff movw r5, #65535 ; 0xffff + 2c0f2: f2c0 050f movt r5, #15 + 2c0f6: f04f 34ff mov.w r4, #4294967295 + 2c0fa: 4014 ands r4, r2 + 2c0fc: 401d ands r5, r3 + 2c0fe: ea54 0705 orrs.w r7, r4, r5 + 2c102: d0ae beq.n 2c062 <__rtl_dcmple_v1_00+0x1a> + 2c104: 2700 movs r7, #0 + 2c106: e7b1 b.n 2c06c <__rtl_dcmple_v1_00+0x24> + 2c108: f64f 75ff movw r5, #65535 ; 0xffff + 2c10c: f2c0 050f movt r5, #15 + 2c110: f04f 34ff mov.w r4, #4294967295 + 2c114: 4014 ands r4, r2 + 2c116: 401d ands r5, r3 + 2c118: ea54 0605 orrs.w r6, r4, r5 + 2c11c: d0ae beq.n 2c07c <__rtl_dcmple_v1_00+0x34> + 2c11e: e7d7 b.n 2c0d0 <__rtl_dcmple_v1_00+0x88> + 2c120: 4299 cmp r1, r3 + 2c122: bf08 it eq + 2c124: 4290 cmpeq r0, r2 + 2c126: d0ed beq.n 2c104 <__rtl_dcmple_v1_00+0xbc> + 2c128: bf34 ite cc + 2c12a: 2401 movcc r4, #1 + 2c12c: 2400 movcs r4, #0 + 2c12e: 1b3f subs r7, r7, r4 + 2c130: bf18 it ne + 2c132: 2701 movne r7, #1 + 2c134: e79a b.n 2c06c <__rtl_dcmple_v1_00+0x24> + 2c136: bf00 nop + +0002c138 <__rtl_fcmplt_v1_00>: + 2c138: f3c0 53c7 ubfx r3, r0, #23, #8 + 2c13c: 2bff cmp r3, #255 ; 0xff + 2c13e: d011 beq.n 2c164 <__rtl_fcmplt_v1_00+0x2c> + 2c140: f3c1 53c7 ubfx r3, r1, #23, #8 + 2c144: 2bff cmp r3, #255 ; 0xff + 2c146: d013 beq.n 2c170 <__rtl_fcmplt_v1_00+0x38> + 2c148: 0fc2 lsrs r2, r0, #31 + 2c14a: b2d3 uxtb r3, r2 + 2c14c: ebb3 7fd1 cmp.w r3, r1, lsr #31 + 2c150: d017 beq.n 2c182 <__rtl_fcmplt_v1_00+0x4a> + 2c152: b12b cbz r3, 2c160 <__rtl_fcmplt_v1_00+0x28> + 2c154: 4308 orrs r0, r1 + 2c156: 0040 lsls r0, r0, #1 + 2c158: bf14 ite ne + 2c15a: 2001 movne r0, #1 + 2c15c: 2000 moveq r0, #0 + 2c15e: 4770 bx lr + 2c160: 4618 mov r0, r3 + 2c162: 4770 bx lr + 2c164: f3c0 0316 ubfx r3, r0, #0, #23 + 2c168: 2b00 cmp r3, #0 + 2c16a: d0e9 beq.n 2c140 <__rtl_fcmplt_v1_00+0x8> + 2c16c: 2000 movs r0, #0 + 2c16e: 4770 bx lr + 2c170: f3c1 0316 ubfx r3, r1, #0, #23 + 2c174: 2b00 cmp r3, #0 + 2c176: d1f9 bne.n 2c16c <__rtl_fcmplt_v1_00+0x34> + 2c178: 0fc2 lsrs r2, r0, #31 + 2c17a: b2d3 uxtb r3, r2 + 2c17c: ebb3 7fd1 cmp.w r3, r1, lsr #31 + 2c180: d1e7 bne.n 2c152 <__rtl_fcmplt_v1_00+0x1a> + 2c182: 4288 cmp r0, r1 + 2c184: d0f2 beq.n 2c16c <__rtl_fcmplt_v1_00+0x34> + 2c186: bf34 ite cc + 2c188: 2001 movcc r0, #1 + 2c18a: 2000 movcs r0, #0 + 2c18c: 1a10 subs r0, r2, r0 + 2c18e: bf18 it ne + 2c190: 2001 movne r0, #1 + 2c192: 4770 bx lr + +0002c194 <__rtl_fcmpgt_v1_00>: + 2c194: f3c0 52c7 ubfx r2, r0, #23, #8 + 2c198: 2aff cmp r2, #255 ; 0xff + 2c19a: b430 push {r4, r5} + 2c19c: d02e beq.n 2c1fc <__rtl_fcmpgt_v1_00+0x68> + 2c19e: f3c1 54c7 ubfx r4, r1, #23, #8 + 2c1a2: 2cff cmp r4, #255 ; 0xff + 2c1a4: d031 beq.n 2c20a <__rtl_fcmpgt_v1_00+0x76> + 2c1a6: 0fc5 lsrs r5, r0, #31 + 2c1a8: b2eb uxtb r3, r5 + 2c1aa: ebb3 7fd1 cmp.w r3, r1, lsr #31 + 2c1ae: d032 beq.n 2c216 <__rtl_fcmpgt_v1_00+0x82> + 2c1b0: b98b cbnz r3, 2c1d6 <__rtl_fcmpgt_v1_00+0x42> + 2c1b2: 2aff cmp r2, #255 ; 0xff + 2c1b4: d017 beq.n 2c1e6 <__rtl_fcmpgt_v1_00+0x52> + 2c1b6: 2cff cmp r4, #255 ; 0xff + 2c1b8: d01b beq.n 2c1f2 <__rtl_fcmpgt_v1_00+0x5e> + 2c1ba: 4288 cmp r0, r1 + 2c1bc: bf08 it eq + 2c1be: 2001 moveq r0, #1 + 2c1c0: d004 beq.n 2c1cc <__rtl_fcmpgt_v1_00+0x38> + 2c1c2: 4308 orrs r0, r1 + 2c1c4: 0040 lsls r0, r0, #1 + 2c1c6: bf0c ite eq + 2c1c8: 2001 moveq r0, #1 + 2c1ca: 2000 movne r0, #0 + 2c1cc: 4303 orrs r3, r0 + 2c1ce: f083 0001 eor.w r0, r3, #1 + 2c1d2: bc30 pop {r4, r5} + 2c1d4: 4770 bx lr + 2c1d6: ea40 0301 orr.w r3, r0, r1 + 2c1da: 005b lsls r3, r3, #1 + 2c1dc: bf14 ite ne + 2c1de: 2301 movne r3, #1 + 2c1e0: 2300 moveq r3, #0 + 2c1e2: 2aff cmp r2, #255 ; 0xff + 2c1e4: d1e7 bne.n 2c1b6 <__rtl_fcmpgt_v1_00+0x22> + 2c1e6: f3c0 0216 ubfx r2, r0, #0, #23 + 2c1ea: 2a00 cmp r2, #0 + 2c1ec: d1ef bne.n 2c1ce <__rtl_fcmpgt_v1_00+0x3a> + 2c1ee: 2cff cmp r4, #255 ; 0xff + 2c1f0: d1e3 bne.n 2c1ba <__rtl_fcmpgt_v1_00+0x26> + 2c1f2: f3c1 0216 ubfx r2, r1, #0, #23 + 2c1f6: 2a00 cmp r2, #0 + 2c1f8: d0df beq.n 2c1ba <__rtl_fcmpgt_v1_00+0x26> + 2c1fa: e7e8 b.n 2c1ce <__rtl_fcmpgt_v1_00+0x3a> + 2c1fc: f3c0 0316 ubfx r3, r0, #0, #23 + 2c200: 2b00 cmp r3, #0 + 2c202: d0cc beq.n 2c19e <__rtl_fcmpgt_v1_00+0xa> + 2c204: bc30 pop {r4, r5} + 2c206: 2001 movs r0, #1 + 2c208: 4770 bx lr + 2c20a: f3c1 0316 ubfx r3, r1, #0, #23 + 2c20e: 2b00 cmp r3, #0 + 2c210: d0c9 beq.n 2c1a6 <__rtl_fcmpgt_v1_00+0x12> + 2c212: 2300 movs r3, #0 + 2c214: e7cd b.n 2c1b2 <__rtl_fcmpgt_v1_00+0x1e> + 2c216: 4288 cmp r0, r1 + 2c218: d0fb beq.n 2c212 <__rtl_fcmpgt_v1_00+0x7e> + 2c21a: bf34 ite cc + 2c21c: 2301 movcc r3, #1 + 2c21e: 2300 movcs r3, #0 + 2c220: 1aeb subs r3, r5, r3 + 2c222: bf18 it ne + 2c224: 2301 movne r3, #1 + 2c226: e7c4 b.n 2c1b2 <__rtl_fcmpgt_v1_00+0x1e> + +0002c228 <__rtl_cos_f32_v1_00>: + 2c228: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 2c22c: f64f 1183 movw r1, #63875 ; 0xf983 + 2c230: f24a 5859 movw r8, #42329 ; 0xa559 + 2c234: b085 sub sp, #20 + 2c236: f6c3 6122 movt r1, #15906 ; 0x3e22 + 2c23a: f2c0 0802 movt r8, #2 + 2c23e: 4605 mov r5, r0 + 2c240: 47c0 blx r8 + 2c242: f649 13e5 movw r3, #39397 ; 0x99e5 + 2c246: f2c0 0302 movt r3, #2 + 2c24a: 4606 mov r6, r0 + 2c24c: 4798 blx r3 + 2c24e: f24c 1339 movw r3, #49465 ; 0xc139 + 2c252: 4604 mov r4, r0 + 2c254: 2100 movs r1, #0 + 2c256: 4628 mov r0, r5 + 2c258: f2c0 0302 movt r3, #2 + 2c25c: 4798 blx r3 + 2c25e: f649 2351 movw r3, #39505 ; 0x9a51 + 2c262: 2801 cmp r0, #1 + 2c264: bf08 it eq + 2c266: f104 34ff addeq.w r4, r4, #4294967295 + 2c26a: f2c0 0302 movt r3, #2 + 2c26e: 4620 mov r0, r4 + 2c270: 4798 blx r3 + 2c272: f24a 2561 movw r5, #41569 ; 0xa261 + 2c276: 4601 mov r1, r0 + 2c278: f2c0 0502 movt r5, #2 + 2c27c: 4630 mov r0, r6 + 2c27e: 47a8 blx r5 + 2c280: f649 4355 movw r3, #40021 ; 0x9c55 + 2c284: 4681 mov r9, r0 + 2c286: f2c0 0302 movt r3, #2 + 2c28a: f44f 7080 mov.w r0, #256 ; 0x100 + 2c28e: 4798 blx r3 + 2c290: f649 532d movw r3, #40237 ; 0x9d2d + 2c294: 4606 mov r6, r0 + 2c296: f2c0 0302 movt r3, #2 + 2c29a: 4648 mov r0, r9 + 2c29c: 460f mov r7, r1 + 2c29e: f24b 5455 movw r4, #46421 ; 0xb555 + 2c2a2: 4798 blx r3 + 2c2a4: f2c0 0402 movt r4, #2 + 2c2a8: 4602 mov r2, r0 + 2c2aa: 460b mov r3, r1 + 2c2ac: 4630 mov r0, r6 + 2c2ae: 4639 mov r1, r7 + 2c2b0: 47a0 blx r4 + 2c2b2: f649 13dd movw r3, #39389 ; 0x99dd + 2c2b6: f2c0 0302 movt r3, #2 + 2c2ba: 4798 blx r3 + 2c2bc: f649 6689 movw r6, #40585 ; 0x9e89 + 2c2c0: 4607 mov r7, r0 + 2c2c2: f2c0 0602 movt r6, #2 + 2c2c6: f44f 7080 mov.w r0, #256 ; 0x100 + 2c2ca: 47b0 blx r6 + 2c2cc: 4649 mov r1, r9 + 2c2ce: 47c0 blx r8 + 2c2d0: 4680 mov r8, r0 + 2c2d2: 4638 mov r0, r7 + 2c2d4: 47b0 blx r6 + 2c2d6: 4601 mov r1, r0 + 2c2d8: 4640 mov r0, r8 + 2c2da: 47a8 blx r5 + 2c2dc: f24a 5459 movw r4, #42329 ; 0xa559 + 2c2e0: f5b7 7f81 cmp.w r7, #258 ; 0x102 + 2c2e4: 4606 mov r6, r0 + 2c2e6: f2c0 0402 movt r4, #2 + 2c2ea: bf88 it hi + 2c2ec: 2000 movhi r0, #0 + 2c2ee: f200 809e bhi.w 2c42e <__rtl_cos_f32_v1_00+0x206> + 2c2f2: f24e 23f0 movw r3, #58096 ; 0xe2f0 + 2c2f6: f2c0 0303 movt r3, #3 + 2c2fa: f64a 20ab movw r0, #43691 ; 0xaaab + 2c2fe: eb03 0287 add.w r2, r3, r7, lsl #2 + 2c302: f853 3027 ldr.w r3, [r3, r7, lsl #2] + 2c306: f8d2 a004 ldr.w sl, [r2, #4] + 2c30a: f8d2 9008 ldr.w r9, [r2, #8] + 2c30e: 68d2 ldr r2, [r2, #12] + 2c310: 4631 mov r1, r6 + 2c312: 9300 str r3, [sp, #0] + 2c314: f6c3 602a movt r0, #15914 ; 0x3e2a + 2c318: 9203 str r2, [sp, #12] + 2c31a: 47a0 blx r4 + 2c31c: 4631 mov r1, r6 + 2c31e: 4680 mov r8, r0 + 2c320: 4630 mov r0, r6 + 2c322: 47a0 blx r4 + 2c324: 4607 mov r7, r0 + 2c326: 4640 mov r0, r8 + 2c328: 4639 mov r1, r7 + 2c32a: 47a0 blx r4 + 2c32c: 4639 mov r1, r7 + 2c32e: 4680 mov r8, r0 + 2c330: f04f 507c mov.w r0, #1056964608 ; 0x3f000000 + 2c334: 47a0 blx r4 + 2c336: 4607 mov r7, r0 + 2c338: f64a 20ab movw r0, #43691 ; 0xaaab + 2c33c: 4631 mov r1, r6 + 2c33e: f6c3 60aa movt r0, #16042 ; 0x3eaa + 2c342: 47a0 blx r4 + 2c344: 4601 mov r1, r0 + 2c346: 4638 mov r0, r7 + 2c348: 47a8 blx r5 + 2c34a: 4641 mov r1, r8 + 2c34c: 47a8 blx r5 + 2c34e: 4631 mov r1, r6 + 2c350: 4683 mov fp, r0 + 2c352: f04f 507c mov.w r0, #1056964608 ; 0x3f000000 + 2c356: 47a0 blx r4 + 2c358: 4631 mov r1, r6 + 2c35a: 4680 mov r8, r0 + 2c35c: 4630 mov r0, r6 + 2c35e: 47a0 blx r4 + 2c360: 4602 mov r2, r0 + 2c362: 4640 mov r0, r8 + 2c364: 4611 mov r1, r2 + 2c366: 9201 str r2, [sp, #4] + 2c368: 47a0 blx r4 + 2c36a: 9a01 ldr r2, [sp, #4] + 2c36c: f649 7765 movw r7, #40805 ; 0x9f65 + 2c370: 4611 mov r1, r2 + 2c372: 47a8 blx r5 + 2c374: 4602 mov r2, r0 + 2c376: f2c0 0702 movt r7, #2 + 2c37a: f108 4000 add.w r0, r8, #2147483648 ; 0x80000000 + 2c37e: f04f 517e mov.w r1, #1065353216 ; 0x3f800000 + 2c382: 9201 str r2, [sp, #4] + 2c384: 47b8 blx r7 + 2c386: 9a01 ldr r2, [sp, #4] + 2c388: 4601 mov r1, r0 + 2c38a: 4610 mov r0, r2 + 2c38c: 47b8 blx r7 + 2c38e: 4602 mov r2, r0 + 2c390: 4631 mov r1, r6 + 2c392: 9201 str r2, [sp, #4] + 2c394: f04f 507c mov.w r0, #1056964608 ; 0x3f000000 + 2c398: 47a0 blx r4 + 2c39a: 4684 mov ip, r0 + 2c39c: 4631 mov r1, r6 + 2c39e: 4630 mov r0, r6 + 2c3a0: f8cd c008 str.w ip, [sp, #8] + 2c3a4: 47a0 blx r4 + 2c3a6: 4680 mov r8, r0 + 2c3a8: f8dd c008 ldr.w ip, [sp, #8] + 2c3ac: 4641 mov r1, r8 + 2c3ae: 4660 mov r0, ip + 2c3b0: 47a0 blx r4 + 2c3b2: 4684 mov ip, r0 + 2c3b4: 4641 mov r1, r8 + 2c3b6: f8cd c008 str.w ip, [sp, #8] + 2c3ba: f04f 507c mov.w r0, #1056964608 ; 0x3f000000 + 2c3be: 47a0 blx r4 + 2c3c0: 4631 mov r1, r6 + 2c3c2: 47b8 blx r7 + 2c3c4: f8dd c008 ldr.w ip, [sp, #8] + 2c3c8: 4601 mov r1, r0 + 2c3ca: f10c 4000 add.w r0, ip, #2147483648 ; 0x80000000 + 2c3ce: 47b8 blx r7 + 2c3d0: 4684 mov ip, r0 + 2c3d2: f64a 20ab movw r0, #43691 ; 0xaaab + 2c3d6: f8cd c008 str.w ip, [sp, #8] + 2c3da: 4631 mov r1, r6 + 2c3dc: f6c3 602a movt r0, #15914 ; 0x3e2a + 2c3e0: 47a0 blx r4 + 2c3e2: 4631 mov r1, r6 + 2c3e4: 4680 mov r8, r0 + 2c3e6: 4630 mov r0, r6 + 2c3e8: 47a0 blx r4 + 2c3ea: 4601 mov r1, r0 + 2c3ec: 4640 mov r0, r8 + 2c3ee: 47a0 blx r4 + 2c3f0: 4641 mov r1, r8 + 2c3f2: 47a8 blx r5 + 2c3f4: 9b00 ldr r3, [sp, #0] + 2c3f6: 4606 mov r6, r0 + 2c3f8: 4659 mov r1, fp + 2c3fa: 4618 mov r0, r3 + 2c3fc: 47a0 blx r4 + 2c3fe: 9a01 ldr r2, [sp, #4] + 2c400: 4605 mov r5, r0 + 2c402: 4611 mov r1, r2 + 2c404: 4650 mov r0, sl + 2c406: 47a0 blx r4 + 2c408: 4601 mov r1, r0 + 2c40a: 4628 mov r0, r5 + 2c40c: 47b8 blx r7 + 2c40e: f8dd c008 ldr.w ip, [sp, #8] + 2c412: 4605 mov r5, r0 + 2c414: 4661 mov r1, ip + 2c416: 4648 mov r0, r9 + 2c418: 47a0 blx r4 + 2c41a: 4601 mov r1, r0 + 2c41c: 4628 mov r0, r5 + 2c41e: 47b8 blx r7 + 2c420: 4631 mov r1, r6 + 2c422: 4605 mov r5, r0 + 2c424: 9803 ldr r0, [sp, #12] + 2c426: 47a0 blx r4 + 2c428: 4601 mov r1, r0 + 2c42a: 4628 mov r0, r5 + 2c42c: 47b8 blx r7 + 2c42e: b005 add sp, #20 + 2c430: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +0002c434 <__rtl_sin_f32_v1_00>: + 2c434: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 2c438: f64f 1183 movw r1, #63875 ; 0xf983 + 2c43c: f24a 5459 movw r4, #42329 ; 0xa559 + 2c440: b085 sub sp, #20 + 2c442: f2c0 0402 movt r4, #2 + 2c446: f6c3 6122 movt r1, #15906 ; 0x3e22 + 2c44a: 4607 mov r7, r0 + 2c44c: 47a0 blx r4 + 2c44e: f649 13e5 movw r3, #39397 ; 0x99e5 + 2c452: f2c0 0302 movt r3, #2 + 2c456: 4606 mov r6, r0 + 2c458: 4798 blx r3 + 2c45a: f24c 1339 movw r3, #49465 ; 0xc139 + 2c45e: 4605 mov r5, r0 + 2c460: 2100 movs r1, #0 + 2c462: 4638 mov r0, r7 + 2c464: f2c0 0302 movt r3, #2 + 2c468: 4798 blx r3 + 2c46a: f649 2351 movw r3, #39505 ; 0x9a51 + 2c46e: 2801 cmp r0, #1 + 2c470: bf08 it eq + 2c472: f105 35ff addeq.w r5, r5, #4294967295 + 2c476: f2c0 0302 movt r3, #2 + 2c47a: 4628 mov r0, r5 + 2c47c: 4798 blx r3 + 2c47e: f24a 2761 movw r7, #41569 ; 0xa261 + 2c482: 4601 mov r1, r0 + 2c484: f2c0 0702 movt r7, #2 + 2c488: 4630 mov r0, r6 + 2c48a: 47b8 blx r7 + 2c48c: f649 4355 movw r3, #40021 ; 0x9c55 + 2c490: 4606 mov r6, r0 + 2c492: f2c0 0302 movt r3, #2 + 2c496: f44f 7080 mov.w r0, #256 ; 0x100 + 2c49a: 4798 blx r3 + 2c49c: f649 532d movw r3, #40237 ; 0x9d2d + 2c4a0: 4680 mov r8, r0 + 2c4a2: f2c0 0302 movt r3, #2 + 2c4a6: 4630 mov r0, r6 + 2c4a8: 4689 mov r9, r1 + 2c4aa: f24b 5555 movw r5, #46421 ; 0xb555 + 2c4ae: 4798 blx r3 + 2c4b0: f2c0 0502 movt r5, #2 + 2c4b4: 4602 mov r2, r0 + 2c4b6: 460b mov r3, r1 + 2c4b8: 4640 mov r0, r8 + 2c4ba: 4649 mov r1, r9 + 2c4bc: 47a8 blx r5 + 2c4be: f649 13dd movw r3, #39389 ; 0x99dd + 2c4c2: f2c0 0302 movt r3, #2 + 2c4c6: 4798 blx r3 + 2c4c8: f649 6589 movw r5, #40585 ; 0x9e89 + 2c4cc: 4680 mov r8, r0 + 2c4ce: f2c0 0502 movt r5, #2 + 2c4d2: f44f 7080 mov.w r0, #256 ; 0x100 + 2c4d6: 47a8 blx r5 + 2c4d8: 4631 mov r1, r6 + 2c4da: 47a0 blx r4 + 2c4dc: 4606 mov r6, r0 + 2c4de: 4640 mov r0, r8 + 2c4e0: 47a8 blx r5 + 2c4e2: 4601 mov r1, r0 + 2c4e4: 4630 mov r0, r6 + 2c4e6: 47b8 blx r7 + 2c4e8: f24e 23f0 movw r3, #58096 ; 0xe2f0 + 2c4ec: f2c0 0303 movt r3, #3 + 2c4f0: 4605 mov r5, r0 + 2c4f2: 4601 mov r1, r0 + 2c4f4: f64a 20ab movw r0, #43691 ; 0xaaab + 2c4f8: ea4f 0888 mov.w r8, r8, lsl #2 + 2c4fc: f203 420c addw r2, r3, #1036 ; 0x40c + 2c500: 4442 add r2, r8 + 2c502: 4498 add r8, r3 + 2c504: f8d8 340c ldr.w r3, [r8, #1036] ; 0x40c + 2c508: f8d2 a004 ldr.w sl, [r2, #4] + 2c50c: f8d2 9008 ldr.w r9, [r2, #8] + 2c510: 68d2 ldr r2, [r2, #12] + 2c512: f6c3 602a movt r0, #15914 ; 0x3e2a + 2c516: 9300 str r3, [sp, #0] + 2c518: 9203 str r2, [sp, #12] + 2c51a: 47a0 blx r4 + 2c51c: 4629 mov r1, r5 + 2c51e: 4683 mov fp, r0 + 2c520: 4628 mov r0, r5 + 2c522: 47a0 blx r4 + 2c524: 4680 mov r8, r0 + 2c526: 4658 mov r0, fp + 2c528: 4641 mov r1, r8 + 2c52a: 47a0 blx r4 + 2c52c: 4683 mov fp, r0 + 2c52e: f64a 20ab movw r0, #43691 ; 0xaaab + 2c532: 4629 mov r1, r5 + 2c534: f6c3 60aa movt r0, #16042 ; 0x3eaa + 2c538: 47a0 blx r4 + 2c53a: f649 7665 movw r6, #40805 ; 0x9f65 + 2c53e: 4601 mov r1, r0 + 2c540: f2c0 0602 movt r6, #2 + 2c544: 4658 mov r0, fp + 2c546: 47b0 blx r6 + 2c548: 4683 mov fp, r0 + 2c54a: 4641 mov r1, r8 + 2c54c: f04f 507c mov.w r0, #1056964608 ; 0x3f000000 + 2c550: 47a0 blx r4 + 2c552: 4659 mov r1, fp + 2c554: 47b8 blx r7 + 2c556: 4629 mov r1, r5 + 2c558: 4683 mov fp, r0 + 2c55a: f04f 507c mov.w r0, #1056964608 ; 0x3f000000 + 2c55e: 47a0 blx r4 + 2c560: 4629 mov r1, r5 + 2c562: 4680 mov r8, r0 + 2c564: 4628 mov r0, r5 + 2c566: 47a0 blx r4 + 2c568: 4602 mov r2, r0 + 2c56a: 4640 mov r0, r8 + 2c56c: 4611 mov r1, r2 + 2c56e: 9201 str r2, [sp, #4] + 2c570: 47a0 blx r4 + 2c572: 4684 mov ip, r0 + 2c574: 9a01 ldr r2, [sp, #4] + 2c576: f8cd c008 str.w ip, [sp, #8] + 2c57a: 4611 mov r1, r2 + 2c57c: 4640 mov r0, r8 + 2c57e: 47b0 blx r6 + 2c580: f8dd c008 ldr.w ip, [sp, #8] + 2c584: 4601 mov r1, r0 + 2c586: 4660 mov r0, ip + 2c588: 47b8 blx r7 + 2c58a: f04f 517e mov.w r1, #1065353216 ; 0x3f800000 + 2c58e: 47b0 blx r6 + 2c590: 4602 mov r2, r0 + 2c592: 4629 mov r1, r5 + 2c594: f04f 507c mov.w r0, #1056964608 ; 0x3f000000 + 2c598: 9201 str r2, [sp, #4] + 2c59a: 47a0 blx r4 + 2c59c: 4684 mov ip, r0 + 2c59e: 4629 mov r1, r5 + 2c5a0: 4628 mov r0, r5 + 2c5a2: f8cd c008 str.w ip, [sp, #8] + 2c5a6: 47a0 blx r4 + 2c5a8: 4680 mov r8, r0 + 2c5aa: f8dd c008 ldr.w ip, [sp, #8] + 2c5ae: 4641 mov r1, r8 + 2c5b0: 4660 mov r0, ip + 2c5b2: 47a0 blx r4 + 2c5b4: 4684 mov ip, r0 + 2c5b6: 4641 mov r1, r8 + 2c5b8: f04f 507c mov.w r0, #1056964608 ; 0x3f000000 + 2c5bc: f8cd c008 str.w ip, [sp, #8] + 2c5c0: 47a0 blx r4 + 2c5c2: 4629 mov r1, r5 + 2c5c4: 47b0 blx r6 + 2c5c6: f8dd c008 ldr.w ip, [sp, #8] + 2c5ca: 4601 mov r1, r0 + 2c5cc: f10c 4000 add.w r0, ip, #2147483648 ; 0x80000000 + 2c5d0: 47b0 blx r6 + 2c5d2: 4684 mov ip, r0 + 2c5d4: f64a 20ab movw r0, #43691 ; 0xaaab + 2c5d8: 4629 mov r1, r5 + 2c5da: f6c3 602a movt r0, #15914 ; 0x3e2a + 2c5de: f8cd c008 str.w ip, [sp, #8] + 2c5e2: 47a0 blx r4 + 2c5e4: 4629 mov r1, r5 + 2c5e6: 4680 mov r8, r0 + 2c5e8: 4628 mov r0, r5 + 2c5ea: 47a0 blx r4 + 2c5ec: 4601 mov r1, r0 + 2c5ee: 4640 mov r0, r8 + 2c5f0: 47a0 blx r4 + 2c5f2: 4641 mov r1, r8 + 2c5f4: 47b8 blx r7 + 2c5f6: 9b00 ldr r3, [sp, #0] + 2c5f8: 4607 mov r7, r0 + 2c5fa: 4659 mov r1, fp + 2c5fc: 4618 mov r0, r3 + 2c5fe: 47a0 blx r4 + 2c600: 9a01 ldr r2, [sp, #4] + 2c602: 4605 mov r5, r0 + 2c604: 4611 mov r1, r2 + 2c606: 4650 mov r0, sl + 2c608: 47a0 blx r4 + 2c60a: 4601 mov r1, r0 + 2c60c: 4628 mov r0, r5 + 2c60e: 47b0 blx r6 + 2c610: f8dd c008 ldr.w ip, [sp, #8] + 2c614: 4605 mov r5, r0 + 2c616: 4661 mov r1, ip + 2c618: 4648 mov r0, r9 + 2c61a: 47a0 blx r4 + 2c61c: 4601 mov r1, r0 + 2c61e: 4628 mov r0, r5 + 2c620: 47b0 blx r6 + 2c622: 4639 mov r1, r7 + 2c624: 4605 mov r5, r0 + 2c626: 9803 ldr r0, [sp, #12] + 2c628: 47a0 blx r4 + 2c62a: 4601 mov r1, r0 + 2c62c: 4628 mov r0, r5 + 2c62e: 47b0 blx r6 + 2c630: b005 add sp, #20 + 2c632: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 2c636: bf00 nop + +0002c638 <__rtl_fabs_v1_00>: + 2c638: f021 4100 bic.w r1, r1, #2147483648 ; 0x80000000 + 2c63c: 4770 bx lr + 2c63e: bf00 nop + +0002c640 <__rtl_fabsf_v1_00>: + 2c640: f020 4000 bic.w r0, r0, #2147483648 ; 0x80000000 + 2c644: 4770 bx lr + 2c646: bf00 nop + +0002c648 : + 2c648: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 2c64c: 6903 ldr r3, [r0, #16] + 2c64e: 690d ldr r5, [r1, #16] + 2c650: 4683 mov fp, r0 + 2c652: 429d cmp r5, r3 + 2c654: b083 sub sp, #12 + 2c656: bfc8 it gt + 2c658: 2000 movgt r0, #0 + 2c65a: f300 808c bgt.w 2c776 + 2c65e: 3d01 subs r5, #1 + 2c660: f101 0414 add.w r4, r1, #20 + 2c664: f10b 0a14 add.w sl, fp, #20 + 2c668: f854 2025 ldr.w r2, [r4, r5, lsl #2] + 2c66c: f85a 3025 ldr.w r3, [sl, r5, lsl #2] + 2c670: 3201 adds r2, #1 + 2c672: fbb3 f8f2 udiv r8, r3, r2 + 2c676: 00aa lsls r2, r5, #2 + 2c678: 4691 mov r9, r2 + 2c67a: 9200 str r2, [sp, #0] + 2c67c: 4452 add r2, sl + 2c67e: 44a1 add r9, r4 + 2c680: 9201 str r2, [sp, #4] + 2c682: f1b8 0f00 cmp.w r8, #0 + 2c686: d03e beq.n 2c706 + 2c688: 2600 movs r6, #0 + 2c68a: 4630 mov r0, r6 + 2c68c: 4622 mov r2, r4 + 2c68e: 4653 mov r3, sl + 2c690: 468c mov ip, r1 + 2c692: f852 7b04 ldr.w r7, [r2], #4 + 2c696: 6819 ldr r1, [r3, #0] + 2c698: fa1f fe87 uxth.w lr, r7 + 2c69c: 0c3f lsrs r7, r7, #16 + 2c69e: fb0e 6e08 mla lr, lr, r8, r6 + 2c6a2: fb07 f608 mul.w r6, r7, r8 + 2c6a6: eb06 461e add.w r6, r6, lr, lsr #16 + 2c6aa: fa1f fe8e uxth.w lr, lr + 2c6ae: ebce 0e00 rsb lr, lr, r0 + 2c6b2: b28f uxth r7, r1 + 2c6b4: b2b0 uxth r0, r6 + 2c6b6: 4477 add r7, lr + 2c6b8: ebc0 4011 rsb r0, r0, r1, lsr #16 + 2c6bc: eb00 4027 add.w r0, r0, r7, asr #16 + 2c6c0: b2bf uxth r7, r7 + 2c6c2: ea47 4700 orr.w r7, r7, r0, lsl #16 + 2c6c6: 4591 cmp r9, r2 + 2c6c8: f843 7b04 str.w r7, [r3], #4 + 2c6cc: ea4f 4020 mov.w r0, r0, asr #16 + 2c6d0: ea4f 4616 mov.w r6, r6, lsr #16 + 2c6d4: d2dd bcs.n 2c692 + 2c6d6: 9a00 ldr r2, [sp, #0] + 2c6d8: 4661 mov r1, ip + 2c6da: f85a 3002 ldr.w r3, [sl, r2] + 2c6de: b993 cbnz r3, 2c706 + 2c6e0: 9a01 ldr r2, [sp, #4] + 2c6e2: 1f13 subs r3, r2, #4 + 2c6e4: 459a cmp sl, r3 + 2c6e6: d20c bcs.n 2c702 + 2c6e8: f852 3c04 ldr.w r3, [r2, #-4] + 2c6ec: b94b cbnz r3, 2c702 + 2c6ee: f1a2 0308 sub.w r3, r2, #8 + 2c6f2: e002 b.n 2c6fa + 2c6f4: 681a ldr r2, [r3, #0] + 2c6f6: 3b04 subs r3, #4 + 2c6f8: b91a cbnz r2, 2c702 + 2c6fa: 459a cmp sl, r3 + 2c6fc: f105 35ff add.w r5, r5, #4294967295 + 2c700: d3f8 bcc.n 2c6f4 + 2c702: f8cb 5010 str.w r5, [fp, #16] + 2c706: f64e 13bd movw r3, #59837 ; 0xe9bd + 2c70a: 4658 mov r0, fp + 2c70c: f2c0 0302 movt r3, #2 + 2c710: 4798 blx r3 + 2c712: 2800 cmp r0, #0 + 2c714: db2e blt.n 2c774 + 2c716: 4653 mov r3, sl + 2c718: f108 0801 add.w r8, r8, #1 + 2c71c: 2200 movs r2, #0 + 2c71e: f854 6b04 ldr.w r6, [r4], #4 + 2c722: 6818 ldr r0, [r3, #0] + 2c724: b2b1 uxth r1, r6 + 2c726: 1a51 subs r1, r2, r1 + 2c728: b287 uxth r7, r0 + 2c72a: 0c36 lsrs r6, r6, #16 + 2c72c: 4439 add r1, r7 + 2c72e: ebc6 4010 rsb r0, r6, r0, lsr #16 + 2c732: eb00 4221 add.w r2, r0, r1, asr #16 + 2c736: b289 uxth r1, r1 + 2c738: ea41 4102 orr.w r1, r1, r2, lsl #16 + 2c73c: 45a1 cmp r9, r4 + 2c73e: f843 1b04 str.w r1, [r3], #4 + 2c742: ea4f 4222 mov.w r2, r2, asr #16 + 2c746: d2ea bcs.n 2c71e + 2c748: f85a 2025 ldr.w r2, [sl, r5, lsl #2] + 2c74c: eb0a 0385 add.w r3, sl, r5, lsl #2 + 2c750: b982 cbnz r2, 2c774 + 2c752: 1f1a subs r2, r3, #4 + 2c754: 4592 cmp sl, r2 + 2c756: d20b bcs.n 2c770 + 2c758: f853 2c04 ldr.w r2, [r3, #-4] + 2c75c: b942 cbnz r2, 2c770 + 2c75e: 3b08 subs r3, #8 + 2c760: e002 b.n 2c768 + 2c762: 681a ldr r2, [r3, #0] + 2c764: 3b04 subs r3, #4 + 2c766: b91a cbnz r2, 2c770 + 2c768: 459a cmp sl, r3 + 2c76a: f105 35ff add.w r5, r5, #4294967295 + 2c76e: d3f8 bcc.n 2c762 + 2c770: f8cb 5010 str.w r5, [fp, #16] + 2c774: 4640 mov r0, r8 + 2c776: b003 add sp, #12 + 2c778: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +0002c77c <__rtl_dtoa_r_v1_00>: + 2c77c: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 2c780: 6c01 ldr r1, [r0, #64] ; 0x40 + 2c782: b0a7 sub sp, #156 ; 0x9c + 2c784: 4680 mov r8, r0 + 2c786: 4692 mov sl, r2 + 2c788: 469b mov fp, r3 + 2c78a: 9c33 ldr r4, [sp, #204] ; 0xcc + 2c78c: b161 cbz r1, 2c7a8 <__rtl_dtoa_r_v1_00+0x2c> + 2c78e: f24e 5671 movw r6, #58737 ; 0xe571 + 2c792: 6c43 ldr r3, [r0, #68] ; 0x44 + 2c794: 2201 movs r2, #1 + 2c796: 409a lsls r2, r3 + 2c798: 604b str r3, [r1, #4] + 2c79a: 608a str r2, [r1, #8] + 2c79c: f2c0 0602 movt r6, #2 + 2c7a0: 47b0 blx r6 + 2c7a2: 2300 movs r3, #0 + 2c7a4: f8c8 3040 str.w r3, [r8, #64] ; 0x40 + 2c7a8: f1bb 0f00 cmp.w fp, #0 + 2c7ac: bfb5 itete lt + 2c7ae: 2301 movlt r3, #1 + 2c7b0: 2300 movge r3, #0 + 2c7b2: 6023 strlt r3, [r4, #0] + 2c7b4: 6023 strge r3, [r4, #0] + 2c7b6: f04f 0300 mov.w r3, #0 + 2c7ba: 46d9 mov r9, fp + 2c7bc: f6c7 73f0 movt r3, #32752 ; 0x7ff0 + 2c7c0: f04f 0200 mov.w r2, #0 + 2c7c4: f6c7 72f0 movt r2, #32752 ; 0x7ff0 + 2c7c8: bfb8 it lt + 2c7ca: f02b 4900 biclt.w r9, fp, #2147483648 ; 0x80000000 + 2c7ce: ea09 0303 and.w r3, r9, r3 + 2c7d2: bfb8 it lt + 2c7d4: 46cb movlt fp, r9 + 2c7d6: 4293 cmp r3, r2 + 2c7d8: d01b beq.n 2c812 <__rtl_dtoa_r_v1_00+0x96> + 2c7da: f64b 674d movw r7, #48717 ; 0xbe4d + 2c7de: f2c0 0702 movt r7, #2 + 2c7e2: 4650 mov r0, sl + 2c7e4: 4659 mov r1, fp + 2c7e6: 2200 movs r2, #0 + 2c7e8: 2300 movs r3, #0 + 2c7ea: 9704 str r7, [sp, #16] + 2c7ec: 47b8 blx r7 + 2c7ee: 4654 mov r4, sl + 2c7f0: 465d mov r5, fp + 2c7f2: 4607 mov r7, r0 + 2c7f4: 2800 cmp r0, #0 + 2c7f6: d033 beq.n 2c860 <__rtl_dtoa_r_v1_00+0xe4> + 2c7f8: 9c32 ldr r4, [sp, #200] ; 0xc8 + 2c7fa: 9d34 ldr r5, [sp, #208] ; 0xd0 + 2c7fc: 2301 movs r3, #1 + 2c7fe: 6023 str r3, [r4, #0] + 2c800: 2d00 cmp r5, #0 + 2c802: f000 8246 beq.w 2cc92 <__rtl_dtoa_r_v1_00+0x516> + 2c806: 4880 ldr r0, [pc, #512] ; (2ca08 <__rtl_dtoa_r_v1_00+0x28c>) + 2c808: 6028 str r0, [r5, #0] + 2c80a: 3801 subs r0, #1 + 2c80c: b027 add sp, #156 ; 0x9c + 2c80e: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 2c812: f242 730f movw r3, #9999 ; 0x270f + 2c816: f243 70d4 movw r0, #14292 ; 0x37d4 + 2c81a: 9c32 ldr r4, [sp, #200] ; 0xc8 + 2c81c: f2c0 0004 movt r0, #4 + 2c820: 6023 str r3, [r4, #0] + 2c822: f1ba 0f00 cmp.w sl, #0 + 2c826: d10d bne.n 2c844 <__rtl_dtoa_r_v1_00+0xc8> + 2c828: f243 72c8 movw r2, #14280 ; 0x37c8 + 2c82c: f243 73d4 movw r3, #14292 ; 0x37d4 + 2c830: f2c0 0204 movt r2, #4 + 2c834: f2c0 0304 movt r3, #4 + 2c838: f3c9 0013 ubfx r0, r9, #0, #20 + 2c83c: 2800 cmp r0, #0 + 2c83e: bf0c ite eq + 2c840: 4610 moveq r0, r2 + 2c842: 4618 movne r0, r3 + 2c844: 9d34 ldr r5, [sp, #208] ; 0xd0 + 2c846: 2d00 cmp r5, #0 + 2c848: d0e0 beq.n 2c80c <__rtl_dtoa_r_v1_00+0x90> + 2c84a: 78c3 ldrb r3, [r0, #3] + 2c84c: b133 cbz r3, 2c85c <__rtl_dtoa_r_v1_00+0xe0> + 2c84e: f100 0308 add.w r3, r0, #8 + 2c852: 9e34 ldr r6, [sp, #208] ; 0xd0 + 2c854: 6033 str r3, [r6, #0] + 2c856: b027 add sp, #156 ; 0x9c + 2c858: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 2c85c: 1cc3 adds r3, r0, #3 + 2c85e: e7f8 b.n 2c852 <__rtl_dtoa_r_v1_00+0xd6> + 2c860: f64e 0145 movw r1, #59461 ; 0xe845 + 2c864: aa25 add r2, sp, #148 ; 0x94 + 2c866: ab24 add r3, sp, #144 ; 0x90 + 2c868: e88d 000c stmia.w sp, {r2, r3} + 2c86c: f2c0 0102 movt r1, #2 + 2c870: 4640 mov r0, r8 + 2c872: 4652 mov r2, sl + 2c874: 465b mov r3, fp + 2c876: 4788 blx r1 + 2c878: ea5f 5619 movs.w r6, r9, lsr #20 + 2c87c: 9017 str r0, [sp, #92] ; 0x5c + 2c87e: f000 8093 beq.w 2c9a8 <__rtl_dtoa_r_v1_00+0x22c> + 2c882: e9cd 4512 strd r4, r5, [sp, #72] ; 0x48 + 2c886: f8dd e04c ldr.w lr, [sp, #76] ; 0x4c + 2c88a: f2a6 36ff subw r6, r6, #1023 ; 0x3ff + 2c88e: f3ce 0313 ubfx r3, lr, #0, #20 + 2c892: f043 537f orr.w r3, r3, #1069547520 ; 0x3fc00000 + 2c896: f443 1340 orr.w r3, r3, #3145728 ; 0x300000 + 2c89a: 9313 str r3, [sp, #76] ; 0x4c + 2c89c: 9721 str r7, [sp, #132] ; 0x84 + 2c89e: f64a 0525 movw r5, #43045 ; 0xa825 + 2c8a2: e9dd 0112 ldrd r0, r1, [sp, #72] ; 0x48 + 2c8a6: f24b 5455 movw r4, #46421 ; 0xb555 + 2c8aa: 9510 str r5, [sp, #64] ; 0x40 + 2c8ac: f649 05c5 movw r5, #39109 ; 0x98c5 + 2c8b0: 9408 str r4, [sp, #32] + 2c8b2: 950e str r5, [sp, #56] ; 0x38 + 2c8b4: f649 24e9 movw r4, #39657 ; 0x9ae9 + 2c8b8: f64a 65d9 movw r5, #44761 ; 0xaed9 + 2c8bc: 9407 str r4, [sp, #28] + 2c8be: f2c0 0502 movt r5, #2 + 2c8c2: f64b 64bd movw r4, #48829 ; 0xbebd + 2c8c6: 2300 movs r3, #0 + 2c8c8: 2200 movs r2, #0 + 2c8ca: f6c3 73f8 movt r3, #16376 ; 0x3ff8 + 2c8ce: 940c str r4, [sp, #48] ; 0x30 + 2c8d0: 950b str r5, [sp, #44] ; 0x2c + 2c8d2: 47a8 blx r5 + 2c8d4: a346 add r3, pc, #280 ; (adr r3, 2c9f0 <__rtl_dtoa_r_v1_00+0x274>) + 2c8d6: e9d3 2300 ldrd r2, r3, [r3] + 2c8da: 9c08 ldr r4, [sp, #32] + 2c8dc: f2c0 0402 movt r4, #2 + 2c8e0: 9408 str r4, [sp, #32] + 2c8e2: 47a0 blx r4 + 2c8e4: a344 add r3, pc, #272 ; (adr r3, 2c9f8 <__rtl_dtoa_r_v1_00+0x27c>) + 2c8e6: e9d3 2300 ldrd r2, r3, [r3] + 2c8ea: 9d10 ldr r5, [sp, #64] ; 0x40 + 2c8ec: f2c0 0502 movt r5, #2 + 2c8f0: 9510 str r5, [sp, #64] ; 0x40 + 2c8f2: 47a8 blx r5 + 2c8f4: 9c07 ldr r4, [sp, #28] + 2c8f6: e9cd 0112 strd r0, r1, [sp, #72] ; 0x48 + 2c8fa: f2c0 0402 movt r4, #2 + 2c8fe: 4630 mov r0, r6 + 2c900: 9407 str r4, [sp, #28] + 2c902: 47a0 blx r4 + 2c904: a33e add r3, pc, #248 ; (adr r3, 2ca00 <__rtl_dtoa_r_v1_00+0x284>) + 2c906: e9d3 2300 ldrd r2, r3, [r3] + 2c90a: 9d08 ldr r5, [sp, #32] + 2c90c: 47a8 blx r5 + 2c90e: 9c10 ldr r4, [sp, #64] ; 0x40 + 2c910: 4602 mov r2, r0 + 2c912: 460b mov r3, r1 + 2c914: e9dd 0112 ldrd r0, r1, [sp, #72] ; 0x48 + 2c918: 47a0 blx r4 + 2c91a: 9d0e ldr r5, [sp, #56] ; 0x38 + 2c91c: e9cd 0112 strd r0, r1, [sp, #72] ; 0x48 + 2c920: f2c0 0502 movt r5, #2 + 2c924: 950e str r5, [sp, #56] ; 0x38 + 2c926: 47a8 blx r5 + 2c928: 9c0c ldr r4, [sp, #48] ; 0x30 + 2c92a: 900a str r0, [sp, #40] ; 0x28 + 2c92c: f2c0 0402 movt r4, #2 + 2c930: e9dd 0112 ldrd r0, r1, [sp, #72] ; 0x48 + 2c934: 2200 movs r2, #0 + 2c936: 2300 movs r3, #0 + 2c938: 940c str r4, [sp, #48] ; 0x30 + 2c93a: 47a0 blx r4 + 2c93c: 2801 cmp r0, #1 + 2c93e: f000 8437 beq.w 2d1b0 <__rtl_dtoa_r_v1_00+0xa34> + 2c942: 9c0a ldr r4, [sp, #40] ; 0x28 + 2c944: 2c16 cmp r4, #22 + 2c946: bf84 itt hi + 2c948: 2501 movhi r5, #1 + 2c94a: 951f strhi r5, [sp, #124] ; 0x7c + 2c94c: f240 8301 bls.w 2cf52 <__rtl_dtoa_r_v1_00+0x7d6> + 2c950: 9b24 ldr r3, [sp, #144] ; 0x90 + 2c952: 1b9e subs r6, r3, r6 + 2c954: 3e01 subs r6, #1 + 2c956: bf44 itt mi + 2c958: 4275 negmi r5, r6 + 2c95a: 9516 strmi r5, [sp, #88] ; 0x58 + 2c95c: 9d0a ldr r5, [sp, #40] ; 0x28 + 2c95e: 960f str r6, [sp, #60] ; 0x3c + 2c960: bf53 iteet pl + 2c962: 2400 movpl r4, #0 + 2c964: 2600 movmi r6, #0 + 2c966: 960f strmi r6, [sp, #60] ; 0x3c + 2c968: 9416 strpl r4, [sp, #88] ; 0x58 + 2c96a: 2d00 cmp r5, #0 + 2c96c: f2c0 8305 blt.w 2cf7a <__rtl_dtoa_r_v1_00+0x7fe> + 2c970: 9e0f ldr r6, [sp, #60] ; 0x3c + 2c972: 2400 movs r4, #0 + 2c974: 442e add r6, r5 + 2c976: 960f str r6, [sp, #60] ; 0x3c + 2c978: 951d str r5, [sp, #116] ; 0x74 + 2c97a: 941b str r4, [sp, #108] ; 0x6c + 2c97c: 9e30 ldr r6, [sp, #192] ; 0xc0 + 2c97e: 2e09 cmp r6, #9 + 2c980: d844 bhi.n 2ca0c <__rtl_dtoa_r_v1_00+0x290> + 2c982: 2e05 cmp r6, #5 + 2c984: bfc4 itt gt + 2c986: 3e04 subgt r6, #4 + 2c988: 9630 strgt r6, [sp, #192] ; 0xc0 + 2c98a: 9d30 ldr r5, [sp, #192] ; 0xc0 + 2c98c: bfc8 it gt + 2c98e: 2400 movgt r4, #0 + 2c990: f1a5 0302 sub.w r3, r5, #2 + 2c994: bfd8 it le + 2c996: 2401 movle r4, #1 + 2c998: 2b03 cmp r3, #3 + 2c99a: d839 bhi.n 2ca10 <__rtl_dtoa_r_v1_00+0x294> + 2c99c: e8df f013 tbh [pc, r3, lsl #1] + 2c9a0: 01b00216 .word 0x01b00216 + 2c9a4: 05900225 .word 0x05900225 + 2c9a8: 9e24 ldr r6, [sp, #144] ; 0x90 + 2c9aa: 9b25 ldr r3, [sp, #148] ; 0x94 + 2c9ac: f46f 6282 mvn.w r2, #1040 ; 0x410 + 2c9b0: 441e add r6, r3 + 2c9b2: 4296 cmp r6, r2 + 2c9b4: f2c0 8172 blt.w 2cc9c <__rtl_dtoa_r_v1_00+0x520> + 2c9b8: f64f 430e movw r3, #64526 ; 0xfc0e + 2c9bc: f6cf 73ff movt r3, #65535 ; 0xffff + 2c9c0: f206 4212 addw r2, r6, #1042 ; 0x412 + 2c9c4: 1b9b subs r3, r3, r6 + 2c9c6: fa09 f303 lsl.w r3, r9, r3 + 2c9ca: fa2a f202 lsr.w r2, sl, r2 + 2c9ce: ea43 0002 orr.w r0, r3, r2 + 2c9d2: f649 4355 movw r3, #40021 ; 0x9c55 + 2c9d6: f2c0 0302 movt r3, #2 + 2c9da: 4798 blx r3 + 2c9dc: e9cd 0112 strd r0, r1, [sp, #72] ; 0x48 + 2c9e0: 9813 ldr r0, [sp, #76] ; 0x4c + 2c9e2: 2401 movs r4, #1 + 2c9e4: f1a0 70f8 sub.w r0, r0, #32505856 ; 0x1f00000 + 2c9e8: 3e01 subs r6, #1 + 2c9ea: 9013 str r0, [sp, #76] ; 0x4c + 2c9ec: 9421 str r4, [sp, #132] ; 0x84 + 2c9ee: e756 b.n 2c89e <__rtl_dtoa_r_v1_00+0x122> + 2c9f0: 636f4361 .word 0x636f4361 + 2c9f4: 3fd287a7 .word 0x3fd287a7 + 2c9f8: 8b60c8b3 .word 0x8b60c8b3 + 2c9fc: 3fc68a28 .word 0x3fc68a28 + 2ca00: 509f79fb .word 0x509f79fb + 2ca04: 3fd34413 .word 0x3fd34413 + 2ca08: 000437d9 .word 0x000437d9 + 2ca0c: 2500 movs r5, #0 + 2ca0e: 9530 str r5, [sp, #192] ; 0xc0 + 2ca10: f24e 5615 movw r6, #58645 ; 0xe515 + 2ca14: f2c0 0602 movt r6, #2 + 2ca18: 2400 movs r4, #0 + 2ca1a: f8c8 4044 str.w r4, [r8, #68] ; 0x44 + 2ca1e: 4621 mov r1, r4 + 2ca20: 4640 mov r0, r8 + 2ca22: 961a str r6, [sp, #104] ; 0x68 + 2ca24: 47b0 blx r6 + 2ca26: f04f 37ff mov.w r7, #4294967295 + 2ca2a: 9431 str r4, [sp, #196] ; 0xc4 + 2ca2c: 2401 movs r4, #1 + 2ca2e: 9006 str r0, [sp, #24] + 2ca30: 971e str r7, [sp, #120] ; 0x78 + 2ca32: f8c8 0040 str.w r0, [r8, #64] ; 0x40 + 2ca36: 9711 str r7, [sp, #68] ; 0x44 + 2ca38: 941c str r4, [sp, #112] ; 0x70 + 2ca3a: 9b25 ldr r3, [sp, #148] ; 0x94 + 2ca3c: 2b00 cmp r3, #0 + 2ca3e: db65 blt.n 2cb0c <__rtl_dtoa_r_v1_00+0x390> + 2ca40: 9d0a ldr r5, [sp, #40] ; 0x28 + 2ca42: 2d0e cmp r5, #14 + 2ca44: dc62 bgt.n 2cb0c <__rtl_dtoa_r_v1_00+0x390> + 2ca46: f64e 3308 movw r3, #60168 ; 0xeb08 + 2ca4a: 9e31 ldr r6, [sp, #196] ; 0xc4 + 2ca4c: 9c11 ldr r4, [sp, #68] ; 0x44 + 2ca4e: 0ff2 lsrs r2, r6, #31 + 2ca50: f2c0 0303 movt r3, #3 + 2ca54: 2c00 cmp r4, #0 + 2ca56: bfcc ite gt + 2ca58: 2200 movgt r2, #0 + 2ca5a: f002 0201 andle.w r2, r2, #1 + 2ca5e: eb03 03c5 add.w r3, r3, r5, lsl #3 + 2ca62: e9d3 6700 ldrd r6, r7, [r3] + 2ca66: e9cd 670c strd r6, r7, [sp, #48] ; 0x30 + 2ca6a: 2a00 cmp r2, #0 + 2ca6c: f000 83f1 beq.w 2d252 <__rtl_dtoa_r_v1_00+0xad6> + 2ca70: 2c00 cmp r4, #0 + 2ca72: f040 85a2 bne.w 2d5ba <__rtl_dtoa_r_v1_00+0xe3e> + 2ca76: 2100 movs r1, #0 + 2ca78: 4632 mov r2, r6 + 2ca7a: 463b mov r3, r7 + 2ca7c: 2000 movs r0, #0 + 2ca7e: f2c4 0114 movt r1, #16404 ; 0x4014 + 2ca82: 9e08 ldr r6, [sp, #32] + 2ca84: 47b0 blx r6 + 2ca86: f64b 7451 movw r4, #48977 ; 0xbf51 + 2ca8a: 4602 mov r2, r0 + 2ca8c: 460b mov r3, r1 + 2ca8e: 4650 mov r0, sl + 2ca90: 4659 mov r1, fp + 2ca92: f2c0 0402 movt r4, #2 + 2ca96: 47a0 blx r4 + 2ca98: 2800 cmp r0, #0 + 2ca9a: f000 860c beq.w 2d6b6 <__rtl_dtoa_r_v1_00+0xf3a> + 2ca9e: f24e 5671 movw r6, #58737 ; 0xe571 + 2caa2: 9c11 ldr r4, [sp, #68] ; 0x44 + 2caa4: f2c0 0602 movt r6, #2 + 2caa8: 46a1 mov r9, r4 + 2caaa: 9404 str r4, [sp, #16] + 2caac: 9d0a ldr r5, [sp, #40] ; 0x28 + 2caae: 9c06 ldr r4, [sp, #24] + 2cab0: 3501 adds r5, #1 + 2cab2: 950a str r5, [sp, #40] ; 0x28 + 2cab4: 4625 mov r5, r4 + 2cab6: 2331 movs r3, #49 ; 0x31 + 2cab8: 3501 adds r5, #1 + 2caba: 7023 strb r3, [r4, #0] + 2cabc: 2700 movs r7, #0 + 2cabe: 9506 str r5, [sp, #24] + 2cac0: f24e 5571 movw r5, #58737 ; 0xe571 + 2cac4: 9904 ldr r1, [sp, #16] + 2cac6: 4640 mov r0, r8 + 2cac8: f2c0 0502 movt r5, #2 + 2cacc: 47b0 blx r6 + 2cace: f1b9 0f00 cmp.w r9, #0 + 2cad2: d007 beq.n 2cae4 <__rtl_dtoa_r_v1_00+0x368> + 2cad4: 454f cmp r7, r9 + 2cad6: bf18 it ne + 2cad8: 2f00 cmpne r7, #0 + 2cada: f040 8330 bne.w 2d13e <__rtl_dtoa_r_v1_00+0x9c2> + 2cade: 4649 mov r1, r9 + 2cae0: 4640 mov r0, r8 + 2cae2: 47b0 blx r6 + 2cae4: 4640 mov r0, r8 + 2cae6: 9917 ldr r1, [sp, #92] ; 0x5c + 2cae8: 47b0 blx r6 + 2caea: 9b0a ldr r3, [sp, #40] ; 0x28 + 2caec: 9d06 ldr r5, [sp, #24] + 2caee: 9e32 ldr r6, [sp, #200] ; 0xc8 + 2caf0: 9f34 ldr r7, [sp, #208] ; 0xd0 + 2caf2: 3301 adds r3, #1 + 2caf4: 2200 movs r2, #0 + 2caf6: 702a strb r2, [r5, #0] + 2caf8: 4620 mov r0, r4 + 2cafa: 6033 str r3, [r6, #0] + 2cafc: 2f00 cmp r7, #0 + 2cafe: f43f ae85 beq.w 2c80c <__rtl_dtoa_r_v1_00+0x90> + 2cb02: 4620 mov r0, r4 + 2cb04: 603d str r5, [r7, #0] + 2cb06: b027 add sp, #156 ; 0x9c + 2cb08: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 2cb0c: 9f1c ldr r7, [sp, #112] ; 0x70 + 2cb0e: 2f00 cmp r7, #0 + 2cb10: f040 80cc bne.w 2ccac <__rtl_dtoa_r_v1_00+0x530> + 2cb14: f24e 5485 movw r4, #58757 ; 0xe585 + 2cb18: f2c0 0402 movt r4, #2 + 2cb1c: 9d1b ldr r5, [sp, #108] ; 0x6c + 2cb1e: 9f16 ldr r7, [sp, #88] ; 0x58 + 2cb20: f8dd 9070 ldr.w r9, [sp, #112] ; 0x70 + 2cb24: 9e0f ldr r6, [sp, #60] ; 0x3c + 2cb26: 2e00 cmp r6, #0 + 2cb28: bfc8 it gt + 2cb2a: 2f00 cmpgt r7, #0 + 2cb2c: dd0a ble.n 2cb44 <__rtl_dtoa_r_v1_00+0x3c8> + 2cb2e: 42be cmp r6, r7 + 2cb30: 4633 mov r3, r6 + 2cb32: bfa8 it ge + 2cb34: 463b movge r3, r7 + 2cb36: 9e16 ldr r6, [sp, #88] ; 0x58 + 2cb38: 1aff subs r7, r7, r3 + 2cb3a: 1af6 subs r6, r6, r3 + 2cb3c: 9616 str r6, [sp, #88] ; 0x58 + 2cb3e: 9e0f ldr r6, [sp, #60] ; 0x3c + 2cb40: 1af6 subs r6, r6, r3 + 2cb42: 960f str r6, [sp, #60] ; 0x3c + 2cb44: 9e1b ldr r6, [sp, #108] ; 0x6c + 2cb46: 2e00 cmp r6, #0 + 2cb48: bfdc itt le + 2cb4a: f24e 5671 movwle r6, #58737 ; 0xe571 + 2cb4e: f2c0 0602 movtle r6, #2 + 2cb52: dd2c ble.n 2cbae <__rtl_dtoa_r_v1_00+0x432> + 2cb54: 9e1c ldr r6, [sp, #112] ; 0x70 + 2cb56: 2e00 cmp r6, #0 + 2cb58: f000 84b5 beq.w 2d4c6 <__rtl_dtoa_r_v1_00+0xd4a> + 2cb5c: 2d00 cmp r5, #0 + 2cb5e: bfdc itt le + 2cb60: f24e 5671 movwle r6, #58737 ; 0xe571 + 2cb64: f2c0 0602 movtle r6, #2 + 2cb68: dd1b ble.n 2cba2 <__rtl_dtoa_r_v1_00+0x426> + 2cb6a: f24e 7369 movw r3, #59241 ; 0xe769 + 2cb6e: 4649 mov r1, r9 + 2cb70: f2c0 0302 movt r3, #2 + 2cb74: 462a mov r2, r5 + 2cb76: 4640 mov r0, r8 + 2cb78: 4798 blx r3 + 2cb7a: f24e 6329 movw r3, #58921 ; 0xe629 + 2cb7e: 4681 mov r9, r0 + 2cb80: 9a17 ldr r2, [sp, #92] ; 0x5c + 2cb82: 4649 mov r1, r9 + 2cb84: f2c0 0302 movt r3, #2 + 2cb88: 4640 mov r0, r8 + 2cb8a: 4798 blx r3 + 2cb8c: f24e 5671 movw r6, #58737 ; 0xe571 + 2cb90: 4603 mov r3, r0 + 2cb92: 9917 ldr r1, [sp, #92] ; 0x5c + 2cb94: 9303 str r3, [sp, #12] + 2cb96: 4640 mov r0, r8 + 2cb98: f2c0 0602 movt r6, #2 + 2cb9c: 47b0 blx r6 + 2cb9e: 9b03 ldr r3, [sp, #12] + 2cba0: 9317 str r3, [sp, #92] ; 0x5c + 2cba2: f8dd e06c ldr.w lr, [sp, #108] ; 0x6c + 2cba6: ebbe 0205 subs.w r2, lr, r5 + 2cbaa: f040 84f2 bne.w 2d592 <__rtl_dtoa_r_v1_00+0xe16> + 2cbae: 4640 mov r0, r8 + 2cbb0: 2101 movs r1, #1 + 2cbb2: 47a0 blx r4 + 2cbb4: 9c1d ldr r4, [sp, #116] ; 0x74 + 2cbb6: 9004 str r0, [sp, #16] + 2cbb8: 2c00 cmp r4, #0 + 2cbba: dd08 ble.n 2cbce <__rtl_dtoa_r_v1_00+0x452> + 2cbbc: f24e 7369 movw r3, #59241 ; 0xe769 + 2cbc0: 4601 mov r1, r0 + 2cbc2: f2c0 0302 movt r3, #2 + 2cbc6: 4640 mov r0, r8 + 2cbc8: 4622 mov r2, r4 + 2cbca: 4798 blx r3 + 2cbcc: 9004 str r0, [sp, #16] + 2cbce: 9d30 ldr r5, [sp, #192] ; 0xc0 + 2cbd0: 2d01 cmp r5, #1 + 2cbd2: f340 83bb ble.w 2d34c <__rtl_dtoa_r_v1_00+0xbd0> + 2cbd6: 2500 movs r5, #0 + 2cbd8: 9c1d ldr r4, [sp, #116] ; 0x74 + 2cbda: 2001 movs r0, #1 + 2cbdc: 2c00 cmp r4, #0 + 2cbde: f040 8302 bne.w 2d1e6 <__rtl_dtoa_r_v1_00+0xa6a> + 2cbe2: 9b0f ldr r3, [sp, #60] ; 0x3c + 2cbe4: 4403 add r3, r0 + 2cbe6: f013 031f ands.w r3, r3, #31 + 2cbea: f000 8226 beq.w 2d03a <__rtl_dtoa_r_v1_00+0x8be> + 2cbee: f1c3 0220 rsb r2, r3, #32 + 2cbf2: 2a04 cmp r2, #4 + 2cbf4: f340 85e5 ble.w 2d7c2 <__rtl_dtoa_r_v1_00+0x1046> + 2cbf8: f1c3 031c rsb r3, r3, #28 + 2cbfc: 9c16 ldr r4, [sp, #88] ; 0x58 + 2cbfe: 441f add r7, r3 + 2cc00: 441c add r4, r3 + 2cc02: 9416 str r4, [sp, #88] ; 0x58 + 2cc04: 9c0f ldr r4, [sp, #60] ; 0x3c + 2cc06: 441c add r4, r3 + 2cc08: 940f str r4, [sp, #60] ; 0x3c + 2cc0a: 9c16 ldr r4, [sp, #88] ; 0x58 + 2cc0c: 2c00 cmp r4, #0 + 2cc0e: dd08 ble.n 2cc22 <__rtl_dtoa_r_v1_00+0x4a6> + 2cc10: f64e 1301 movw r3, #59649 ; 0xe901 + 2cc14: 9917 ldr r1, [sp, #92] ; 0x5c + 2cc16: 4622 mov r2, r4 + 2cc18: f2c0 0302 movt r3, #2 + 2cc1c: 4640 mov r0, r8 + 2cc1e: 4798 blx r3 + 2cc20: 9017 str r0, [sp, #92] ; 0x5c + 2cc22: 9c0f ldr r4, [sp, #60] ; 0x3c + 2cc24: 2c00 cmp r4, #0 + 2cc26: dd08 ble.n 2cc3a <__rtl_dtoa_r_v1_00+0x4be> + 2cc28: f64e 1301 movw r3, #59649 ; 0xe901 + 2cc2c: 9904 ldr r1, [sp, #16] + 2cc2e: 4622 mov r2, r4 + 2cc30: f2c0 0302 movt r3, #2 + 2cc34: 4640 mov r0, r8 + 2cc36: 4798 blx r3 + 2cc38: 9004 str r0, [sp, #16] + 2cc3a: 9c1f ldr r4, [sp, #124] ; 0x7c + 2cc3c: 2c00 cmp r4, #0 + 2cc3e: f040 82df bne.w 2d200 <__rtl_dtoa_r_v1_00+0xa84> + 2cc42: 9c30 ldr r4, [sp, #192] ; 0xc0 + 2cc44: 9811 ldr r0, [sp, #68] ; 0x44 + 2cc46: 2c02 cmp r4, #2 + 2cc48: bfcc ite gt + 2cc4a: 2301 movgt r3, #1 + 2cc4c: 2300 movle r3, #0 + 2cc4e: 2800 cmp r0, #0 + 2cc50: bfc8 it gt + 2cc52: 2300 movgt r3, #0 + 2cc54: 2b00 cmp r3, #0 + 2cc56: f000 8199 beq.w 2cf8c <__rtl_dtoa_r_v1_00+0x810> + 2cc5a: 9c11 ldr r4, [sp, #68] ; 0x44 + 2cc5c: b99c cbnz r4, 2cc86 <__rtl_dtoa_r_v1_00+0x50a> + 2cc5e: f24e 5499 movw r4, #58777 ; 0xe599 + 2cc62: 9904 ldr r1, [sp, #16] + 2cc64: 9b11 ldr r3, [sp, #68] ; 0x44 + 2cc66: 2205 movs r2, #5 + 2cc68: f2c0 0402 movt r4, #2 + 2cc6c: 4640 mov r0, r8 + 2cc6e: 47a0 blx r4 + 2cc70: f64e 13bd movw r3, #59837 ; 0xe9bd + 2cc74: 9004 str r0, [sp, #16] + 2cc76: 9904 ldr r1, [sp, #16] + 2cc78: 9817 ldr r0, [sp, #92] ; 0x5c + 2cc7a: f2c0 0302 movt r3, #2 + 2cc7e: 4798 blx r3 + 2cc80: 2800 cmp r0, #0 + 2cc82: f73f af13 bgt.w 2caac <__rtl_dtoa_r_v1_00+0x330> + 2cc86: 9f31 ldr r7, [sp, #196] ; 0xc4 + 2cc88: 9c06 ldr r4, [sp, #24] + 2cc8a: 43ff mvns r7, r7 + 2cc8c: 970a str r7, [sp, #40] ; 0x28 + 2cc8e: 2700 movs r7, #0 + 2cc90: e716 b.n 2cac0 <__rtl_dtoa_r_v1_00+0x344> + 2cc92: f243 70d8 movw r0, #14296 ; 0x37d8 + 2cc96: f2c0 0004 movt r0, #4 + 2cc9a: e5b7 b.n 2c80c <__rtl_dtoa_r_v1_00+0x90> + 2cc9c: f64f 30ee movw r0, #64494 ; 0xfbee + 2cca0: f6cf 70ff movt r0, #65535 ; 0xffff + 2cca4: 1b80 subs r0, r0, r6 + 2cca6: fa0a f000 lsl.w r0, sl, r0 + 2ccaa: e692 b.n 2c9d2 <__rtl_dtoa_r_v1_00+0x256> + 2ccac: 9c30 ldr r4, [sp, #192] ; 0xc0 + 2ccae: 2c01 cmp r4, #1 + 2ccb0: f340 848c ble.w 2d5cc <__rtl_dtoa_r_v1_00+0xe50> + 2ccb4: 9e11 ldr r6, [sp, #68] ; 0x44 + 2ccb6: 9f1b ldr r7, [sp, #108] ; 0x6c + 2ccb8: 1e75 subs r5, r6, #1 + 2ccba: 42af cmp r7, r5 + 2ccbc: bfbf itttt lt + 2ccbe: 9c1b ldrlt r4, [sp, #108] ; 0x6c + 2ccc0: 951b strlt r5, [sp, #108] ; 0x6c + 2ccc2: 1b2b sublt r3, r5, r4 + 2ccc4: 9d1d ldrlt r5, [sp, #116] ; 0x74 + 2ccc6: 9e11 ldr r6, [sp, #68] ; 0x44 + 2ccc8: bfb7 itett lt + 2ccca: 18ed addlt r5, r5, r3 + 2cccc: 1b7d subge r5, r7, r5 + 2ccce: 951d strlt r5, [sp, #116] ; 0x74 + 2ccd0: 2500 movlt r5, #0 + 2ccd2: 2e00 cmp r6, #0 + 2ccd4: bfb3 iteet lt + 2ccd6: 9c16 ldrlt r4, [sp, #88] ; 0x58 + 2ccd8: 9f16 ldrge r7, [sp, #88] ; 0x58 + 2ccda: 9b11 ldrge r3, [sp, #68] ; 0x44 + 2ccdc: 1ba7 sublt r7, r4, r6 + 2ccde: bfb8 it lt + 2cce0: 2300 movlt r3, #0 + 2cce2: f24e 5485 movw r4, #58757 ; 0xe585 + 2cce6: 9e16 ldr r6, [sp, #88] ; 0x58 + 2cce8: 4640 mov r0, r8 + 2ccea: 441e add r6, r3 + 2ccec: 9616 str r6, [sp, #88] ; 0x58 + 2ccee: 9e0f ldr r6, [sp, #60] ; 0x3c + 2ccf0: f2c0 0402 movt r4, #2 + 2ccf4: 441e add r6, r3 + 2ccf6: 2101 movs r1, #1 + 2ccf8: 960f str r6, [sp, #60] ; 0x3c + 2ccfa: 47a0 blx r4 + 2ccfc: 4681 mov r9, r0 + 2ccfe: e711 b.n 2cb24 <__rtl_dtoa_r_v1_00+0x3a8> + 2cd00: 2500 movs r5, #0 + 2cd02: 951c str r5, [sp, #112] ; 0x70 + 2cd04: 9e31 ldr r6, [sp, #196] ; 0xc4 + 2cd06: 9d0a ldr r5, [sp, #40] ; 0x28 + 2cd08: 442e add r6, r5 + 2cd0a: 961e str r6, [sp, #120] ; 0x78 + 2cd0c: 3601 adds r6, #1 + 2cd0e: 2e00 cmp r6, #0 + 2cd10: 9611 str r6, [sp, #68] ; 0x44 + 2cd12: f340 83f0 ble.w 2d4f6 <__rtl_dtoa_r_v1_00+0xd7a> + 2cd16: 9e11 ldr r6, [sp, #68] ; 0x44 + 2cd18: 2e0e cmp r6, #14 + 2cd1a: bf8c ite hi + 2cd1c: 2400 movhi r4, #0 + 2cd1e: f004 0401 andls.w r4, r4, #1 + 2cd22: 4630 mov r0, r6 + 2cd24: 2300 movs r3, #0 + 2cd26: 2817 cmp r0, #23 + 2cd28: f8c8 3044 str.w r3, [r8, #68] ; 0x44 + 2cd2c: d90b bls.n 2cd46 <__rtl_dtoa_r_v1_00+0x5ca> + 2cd2e: 2201 movs r2, #1 + 2cd30: 2304 movs r3, #4 + 2cd32: 005b lsls r3, r3, #1 + 2cd34: f103 0114 add.w r1, r3, #20 + 2cd38: 4281 cmp r1, r0 + 2cd3a: 4617 mov r7, r2 + 2cd3c: f102 0201 add.w r2, r2, #1 + 2cd40: d9f7 bls.n 2cd32 <__rtl_dtoa_r_v1_00+0x5b6> + 2cd42: f8c8 7044 str.w r7, [r8, #68] ; 0x44 + 2cd46: f24e 5515 movw r5, #58645 ; 0xe515 + 2cd4a: f2c0 0502 movt r5, #2 + 2cd4e: 4639 mov r1, r7 + 2cd50: 4640 mov r0, r8 + 2cd52: 951a str r5, [sp, #104] ; 0x68 + 2cd54: 47a8 blx r5 + 2cd56: 9006 str r0, [sp, #24] + 2cd58: f8c8 0040 str.w r0, [r8, #64] ; 0x40 + 2cd5c: 2c00 cmp r4, #0 + 2cd5e: f43f ae6c beq.w 2ca3a <__rtl_dtoa_r_v1_00+0x2be> + 2cd62: 465f mov r7, fp + 2cd64: 4656 mov r6, sl + 2cd66: e9cd 6712 strd r6, r7, [sp, #72] ; 0x48 + 2cd6a: 9f0a ldr r7, [sp, #40] ; 0x28 + 2cd6c: e9cd ab14 strd sl, fp, [sp, #80] ; 0x50 + 2cd70: 2f00 cmp r7, #0 + 2cd72: f340 822e ble.w 2d1d2 <__rtl_dtoa_r_v1_00+0xa56> + 2cd76: f64e 3308 movw r3, #60168 ; 0xeb08 + 2cd7a: f2c0 0303 movt r3, #3 + 2cd7e: f007 020f and.w r2, r7, #15 + 2cd82: 113f asrs r7, r7, #4 + 2cd84: eb03 03c2 add.w r3, r3, r2, lsl #3 + 2cd88: 06fa lsls r2, r7, #27 + 2cd8a: e9d3 4500 ldrd r4, r5, [r3] + 2cd8e: f100 8386 bmi.w 2d49e <__rtl_dtoa_r_v1_00+0xd22> + 2cd92: e9dd 0114 ldrd r0, r1, [sp, #80] ; 0x50 + 2cd96: f64b 06ad movw r6, #47277 ; 0xb8ad + 2cd9a: f2c0 0602 movt r6, #2 + 2cd9e: e9cd 0118 strd r0, r1, [sp, #96] ; 0x60 + 2cda2: f04f 0902 mov.w r9, #2 + 2cda6: b32f cbz r7, 2cdf4 <__rtl_dtoa_r_v1_00+0x678> + 2cda8: 4620 mov r0, r4 + 2cdaa: f8df a9dc ldr.w sl, [pc, #2524] ; 2d788 <__rtl_dtoa_r_v1_00+0x100c> + 2cdae: 4629 mov r1, r5 + 2cdb0: 9c08 ldr r4, [sp, #32] + 2cdb2: e003 b.n 2cdbc <__rtl_dtoa_r_v1_00+0x640> + 2cdb4: 107f asrs r7, r7, #1 + 2cdb6: f10a 0a08 add.w sl, sl, #8 + 2cdba: d019 beq.n 2cdf0 <__rtl_dtoa_r_v1_00+0x674> + 2cdbc: 07fb lsls r3, r7, #31 + 2cdbe: d5f9 bpl.n 2cdb4 <__rtl_dtoa_r_v1_00+0x638> + 2cdc0: e9da 2300 ldrd r2, r3, [sl] + 2cdc4: 47a0 blx r4 + 2cdc6: f109 0901 add.w r9, r9, #1 + 2cdca: e7f3 b.n 2cdb4 <__rtl_dtoa_r_v1_00+0x638> + 2cdcc: 2500 movs r5, #0 + 2cdce: 951c str r5, [sp, #112] ; 0x70 + 2cdd0: 9e31 ldr r6, [sp, #196] ; 0xc4 + 2cdd2: 2e00 cmp r6, #0 + 2cdd4: f340 8386 ble.w 2d4e4 <__rtl_dtoa_r_v1_00+0xd68> + 2cdd8: 2e0e cmp r6, #14 + 2cdda: bf8c ite hi + 2cddc: 2400 movhi r4, #0 + 2cdde: f004 0401 andls.w r4, r4, #1 + 2cde2: 4630 mov r0, r6 + 2cde4: 961e str r6, [sp, #120] ; 0x78 + 2cde6: 9611 str r6, [sp, #68] ; 0x44 + 2cde8: e79c b.n 2cd24 <__rtl_dtoa_r_v1_00+0x5a8> + 2cdea: 2501 movs r5, #1 + 2cdec: 951c str r5, [sp, #112] ; 0x70 + 2cdee: e7ef b.n 2cdd0 <__rtl_dtoa_r_v1_00+0x654> + 2cdf0: 4604 mov r4, r0 + 2cdf2: 460d mov r5, r1 + 2cdf4: e9dd 0118 ldrd r0, r1, [sp, #96] ; 0x60 + 2cdf8: 4622 mov r2, r4 + 2cdfa: 462b mov r3, r5 + 2cdfc: 47b0 blx r6 + 2cdfe: 4606 mov r6, r0 + 2ce00: 460f mov r7, r1 + 2ce02: 4682 mov sl, r0 + 2ce04: 468b mov fp, r1 + 2ce06: 9c1f ldr r4, [sp, #124] ; 0x7c + 2ce08: b154 cbz r4, 2ce20 <__rtl_dtoa_r_v1_00+0x6a4> + 2ce0a: 2300 movs r3, #0 + 2ce0c: 4630 mov r0, r6 + 2ce0e: 4639 mov r1, r7 + 2ce10: 2200 movs r2, #0 + 2ce12: f6c3 73f0 movt r3, #16368 ; 0x3ff0 + 2ce16: 9d0c ldr r5, [sp, #48] ; 0x30 + 2ce18: 47a8 blx r5 + 2ce1a: 2801 cmp r0, #1 + 2ce1c: f000 8385 beq.w 2d52a <__rtl_dtoa_r_v1_00+0xdae> + 2ce20: 9c07 ldr r4, [sp, #28] + 2ce22: 4648 mov r0, r9 + 2ce24: 47a0 blx r4 + 2ce26: 4632 mov r2, r6 + 2ce28: 463b mov r3, r7 + 2ce2a: 9d08 ldr r5, [sp, #32] + 2ce2c: 47a8 blx r5 + 2ce2e: 2300 movs r3, #0 + 2ce30: 9c10 ldr r4, [sp, #64] ; 0x40 + 2ce32: 2200 movs r2, #0 + 2ce34: f2c4 031c movt r3, #16412 ; 0x401c + 2ce38: 47a0 blx r4 + 2ce3a: 4604 mov r4, r0 + 2ce3c: 9811 ldr r0, [sp, #68] ; 0x44 + 2ce3e: f1a1 7550 sub.w r5, r1, #54525952 ; 0x3400000 + 2ce42: 2800 cmp r0, #0 + 2ce44: f000 818f beq.w 2d166 <__rtl_dtoa_r_v1_00+0x9ea> + 2ce48: 9e0a ldr r6, [sp, #40] ; 0x28 + 2ce4a: f8dd c044 ldr.w ip, [sp, #68] ; 0x44 + 2ce4e: 9622 str r6, [sp, #136] ; 0x88 + 2ce50: f64e 3308 movw r3, #60168 ; 0xeb08 + 2ce54: 9f1c ldr r7, [sp, #112] ; 0x70 + 2ce56: f2c0 0303 movt r3, #3 + 2ce5a: 2f00 cmp r7, #0 + 2ce5c: f000 80ef beq.w 2d03e <__rtl_dtoa_r_v1_00+0x8c2> + 2ce60: f64b 06ad movw r6, #47277 ; 0xb8ad + 2ce64: f64a 67d9 movw r7, #44761 ; 0xaed9 + 2ce68: eb03 03cc add.w r3, r3, ip, lsl #3 + 2ce6c: 2100 movs r1, #0 + 2ce6e: e953 2302 ldrd r2, r3, [r3, #-8] + 2ce72: f8cd c00c str.w ip, [sp, #12] + 2ce76: f2c0 0602 movt r6, #2 + 2ce7a: 2000 movs r0, #0 + 2ce7c: f6c3 71e0 movt r1, #16352 ; 0x3fe0 + 2ce80: 9714 str r7, [sp, #80] ; 0x50 + 2ce82: 47b0 blx r6 + 2ce84: 4622 mov r2, r4 + 2ce86: 462b mov r3, r5 + 2ce88: 9c0b ldr r4, [sp, #44] ; 0x2c + 2ce8a: 47a0 blx r4 + 2ce8c: f64b 67bd movw r7, #48829 ; 0xbebd + 2ce90: 9e14 ldr r6, [sp, #80] ; 0x50 + 2ce92: 4604 mov r4, r0 + 2ce94: 460d mov r5, r1 + 2ce96: f2c0 0602 movt r6, #2 + 2ce9a: 4650 mov r0, sl + 2ce9c: 4659 mov r1, fp + 2ce9e: f2c0 0702 movt r7, #2 + 2cea2: f8dd c00c ldr.w ip, [sp, #12] + 2cea6: 9614 str r6, [sp, #80] ; 0x50 + 2cea8: 46a2 mov sl, r4 + 2ceaa: 46ab mov fp, r5 + 2ceac: f8cd 808c str.w r8, [sp, #140] ; 0x8c + 2ceb0: 9718 str r7, [sp, #96] ; 0x60 + 2ceb2: f8dd 9018 ldr.w r9, [sp, #24] + 2ceb6: 46e0 mov r8, ip + 2ceb8: 9e08 ldr r6, [sp, #32] + 2ceba: 4604 mov r4, r0 + 2cebc: 460d mov r5, r1 + 2cebe: e026 b.n 2cf0e <__rtl_dtoa_r_v1_00+0x792> + 2cec0: 2100 movs r1, #0 + 2cec2: 4622 mov r2, r4 + 2cec4: 462b mov r3, r5 + 2cec6: 9f14 ldr r7, [sp, #80] ; 0x50 + 2cec8: 2000 movs r0, #0 + 2ceca: f6c3 71f0 movt r1, #16368 ; 0x3ff0 + 2cece: 47b8 blx r7 + 2ced0: 465b mov r3, fp + 2ced2: 4652 mov r2, sl + 2ced4: 9f18 ldr r7, [sp, #96] ; 0x60 + 2ced6: 47b8 blx r7 + 2ced8: 9906 ldr r1, [sp, #24] + 2ceda: 2801 cmp r0, #1 + 2cedc: ebc1 0309 rsb r3, r1, r9 + 2cee0: f000 837e beq.w 2d5e0 <__rtl_dtoa_r_v1_00+0xe64> + 2cee4: 4543 cmp r3, r8 + 2cee6: f280 837f bge.w 2d5e8 <__rtl_dtoa_r_v1_00+0xe6c> + 2ceea: 2300 movs r3, #0 + 2ceec: 4650 mov r0, sl + 2ceee: 4659 mov r1, fp + 2cef0: 2200 movs r2, #0 + 2cef2: f2c4 0324 movt r3, #16420 ; 0x4024 + 2cef6: 47b0 blx r6 + 2cef8: 2300 movs r3, #0 + 2cefa: 4682 mov sl, r0 + 2cefc: 468b mov fp, r1 + 2cefe: 4620 mov r0, r4 + 2cf00: 4629 mov r1, r5 + 2cf02: 2200 movs r2, #0 + 2cf04: f2c4 0324 movt r3, #16420 ; 0x4024 + 2cf08: 47b0 blx r6 + 2cf0a: 4604 mov r4, r0 + 2cf0c: 460d mov r5, r1 + 2cf0e: 9f0e ldr r7, [sp, #56] ; 0x38 + 2cf10: 47b8 blx r7 + 2cf12: 9a07 ldr r2, [sp, #28] + 2cf14: 4607 mov r7, r0 + 2cf16: 4790 blx r2 + 2cf18: 4602 mov r2, r0 + 2cf1a: 460b mov r3, r1 + 2cf1c: 4620 mov r0, r4 + 2cf1e: 4629 mov r1, r5 + 2cf20: 9c0b ldr r4, [sp, #44] ; 0x2c + 2cf22: 47a0 blx r4 + 2cf24: 3730 adds r7, #48 ; 0x30 + 2cf26: f809 7b01 strb.w r7, [r9], #1 + 2cf2a: 4652 mov r2, sl + 2cf2c: 465b mov r3, fp + 2cf2e: 9f0c ldr r7, [sp, #48] ; 0x30 + 2cf30: 4604 mov r4, r0 + 2cf32: 460d mov r5, r1 + 2cf34: 47b8 blx r7 + 2cf36: 2801 cmp r0, #1 + 2cf38: d1c2 bne.n 2cec0 <__rtl_dtoa_r_v1_00+0x744> + 2cf3a: f24e 5671 movw r6, #58737 ; 0xe571 + 2cf3e: 9d22 ldr r5, [sp, #136] ; 0x88 + 2cf40: 9c06 ldr r4, [sp, #24] + 2cf42: f8dd 808c ldr.w r8, [sp, #140] ; 0x8c + 2cf46: 950a str r5, [sp, #40] ; 0x28 + 2cf48: f8cd 9018 str.w r9, [sp, #24] + 2cf4c: f2c0 0602 movt r6, #2 + 2cf50: e5c8 b.n 2cae4 <__rtl_dtoa_r_v1_00+0x368> + 2cf52: f64e 3308 movw r3, #60168 ; 0xeb08 + 2cf56: f2c0 0303 movt r3, #3 + 2cf5a: eb03 03c4 add.w r3, r3, r4, lsl #3 + 2cf5e: e9d3 2300 ldrd r2, r3, [r3] + 2cf62: 4650 mov r0, sl + 2cf64: 4659 mov r1, fp + 2cf66: 9d0c ldr r5, [sp, #48] ; 0x30 + 2cf68: 47a8 blx r5 + 2cf6a: 2801 cmp r0, #1 + 2cf6c: bf04 itt eq + 2cf6e: f104 34ff addeq.w r4, r4, #4294967295 + 2cf72: 940a streq r4, [sp, #40] ; 0x28 + 2cf74: 2400 movs r4, #0 + 2cf76: 941f str r4, [sp, #124] ; 0x7c + 2cf78: e4ea b.n 2c950 <__rtl_dtoa_r_v1_00+0x1d4> + 2cf7a: 9d16 ldr r5, [sp, #88] ; 0x58 + 2cf7c: 9e0a ldr r6, [sp, #40] ; 0x28 + 2cf7e: 1bad subs r5, r5, r6 + 2cf80: 9516 str r5, [sp, #88] ; 0x58 + 2cf82: 4274 negs r4, r6 + 2cf84: 2500 movs r5, #0 + 2cf86: 941b str r4, [sp, #108] ; 0x6c + 2cf88: 951d str r5, [sp, #116] ; 0x74 + 2cf8a: e4f7 b.n 2c97c <__rtl_dtoa_r_v1_00+0x200> + 2cf8c: 9c1c ldr r4, [sp, #112] ; 0x70 + 2cf8e: 2c00 cmp r4, #0 + 2cf90: f040 81f5 bne.w 2d37e <__rtl_dtoa_r_v1_00+0xc02> + 2cf94: f64e 15bd movw r5, #59837 ; 0xe9bd + 2cf98: f2c0 0502 movt r5, #2 + 2cf9c: 9508 str r5, [sp, #32] + 2cf9e: f24e 5799 movw r7, #58777 ; 0xe599 + 2cfa2: 9c06 ldr r4, [sp, #24] + 2cfa4: 9605 str r6, [sp, #20] + 2cfa6: f2c0 0702 movt r7, #2 + 2cfaa: f8dd a010 ldr.w sl, [sp, #16] + 2cfae: f8dd b044 ldr.w fp, [sp, #68] ; 0x44 + 2cfb2: 4625 mov r5, r4 + 2cfb4: 9e17 ldr r6, [sp, #92] ; 0x5c + 2cfb6: e003 b.n 2cfc0 <__rtl_dtoa_r_v1_00+0x844> + 2cfb8: 4631 mov r1, r6 + 2cfba: 4640 mov r0, r8 + 2cfbc: 47b8 blx r7 + 2cfbe: 4606 mov r6, r0 + 2cfc0: 4630 mov r0, r6 + 2cfc2: 4651 mov r1, sl + 2cfc4: f7ff fb40 bl 2c648 + 2cfc8: 3030 adds r0, #48 ; 0x30 + 2cfca: f804 0b01 strb.w r0, [r4], #1 + 2cfce: 1b63 subs r3, r4, r5 + 2cfd0: 455b cmp r3, fp + 2cfd2: f04f 020a mov.w r2, #10 + 2cfd6: f04f 0300 mov.w r3, #0 + 2cfda: dbed blt.n 2cfb8 <__rtl_dtoa_r_v1_00+0x83c> + 2cfdc: f8dd a018 ldr.w sl, [sp, #24] + 2cfe0: 9c11 ldr r4, [sp, #68] ; 0x44 + 2cfe2: 4605 mov r5, r0 + 2cfe4: 2c01 cmp r4, #1 + 2cfe6: bfac ite ge + 2cfe8: 44a2 addge sl, r4 + 2cfea: f10a 0a01 addlt.w sl, sl, #1 + 2cfee: 461f mov r7, r3 + 2cff0: 9617 str r6, [sp, #92] ; 0x5c + 2cff2: 9e05 ldr r6, [sp, #20] + 2cff4: f64e 1301 movw r3, #59649 ; 0xe901 + 2cff8: 9917 ldr r1, [sp, #92] ; 0x5c + 2cffa: f2c0 0302 movt r3, #2 + 2cffe: 2201 movs r2, #1 + 2d000: 4640 mov r0, r8 + 2d002: 4798 blx r3 + 2d004: 9904 ldr r1, [sp, #16] + 2d006: 9c08 ldr r4, [sp, #32] + 2d008: 9017 str r0, [sp, #92] ; 0x5c + 2d00a: 47a0 blx r4 + 2d00c: 2800 cmp r0, #0 + 2d00e: f340 833e ble.w 2d68e <__rtl_dtoa_r_v1_00+0xf12> + 2d012: f81a 2c01 ldrb.w r2, [sl, #-1] + 2d016: 9906 ldr r1, [sp, #24] + 2d018: e005 b.n 2d026 <__rtl_dtoa_r_v1_00+0x8aa> + 2d01a: 4299 cmp r1, r3 + 2d01c: f000 82c3 beq.w 2d5a6 <__rtl_dtoa_r_v1_00+0xe2a> + 2d020: 469a mov sl, r3 + 2d022: f813 2c01 ldrb.w r2, [r3, #-1] + 2d026: 2a39 cmp r2, #57 ; 0x39 + 2d028: f10a 33ff add.w r3, sl, #4294967295 + 2d02c: d0f5 beq.n 2d01a <__rtl_dtoa_r_v1_00+0x89e> + 2d02e: 3201 adds r2, #1 + 2d030: 9c06 ldr r4, [sp, #24] + 2d032: 701a strb r2, [r3, #0] + 2d034: f8cd a018 str.w sl, [sp, #24] + 2d038: e542 b.n 2cac0 <__rtl_dtoa_r_v1_00+0x344> + 2d03a: 231c movs r3, #28 + 2d03c: e5de b.n 2cbfc <__rtl_dtoa_r_v1_00+0x480> + 2d03e: eb03 03cc add.w r3, r3, ip, lsl #3 + 2d042: 4629 mov r1, r5 + 2d044: e953 2302 ldrd r2, r3, [r3, #-8] + 2d048: f8cd c00c str.w ip, [sp, #12] + 2d04c: 9d08 ldr r5, [sp, #32] + 2d04e: 4620 mov r0, r4 + 2d050: 47a8 blx r5 + 2d052: f8dd c00c ldr.w ip, [sp, #12] + 2d056: e9cd 0114 strd r0, r1, [sp, #80] ; 0x50 + 2d05a: 9e06 ldr r6, [sp, #24] + 2d05c: 4650 mov r0, sl + 2d05e: 4659 mov r1, fp + 2d060: 46e1 mov r9, ip + 2d062: f8cd 8060 str.w r8, [sp, #96] ; 0x60 + 2d066: 9d0b ldr r5, [sp, #44] ; 0x2c + 2d068: e00b b.n 2d082 <__rtl_dtoa_r_v1_00+0x906> + 2d06a: 2300 movs r3, #0 + 2d06c: f8cd c00c str.w ip, [sp, #12] + 2d070: 2200 movs r2, #0 + 2d072: f2c4 0324 movt r3, #16420 ; 0x4024 + 2d076: 9c08 ldr r4, [sp, #32] + 2d078: 47a0 blx r4 + 2d07a: 4682 mov sl, r0 + 2d07c: 468b mov fp, r1 + 2d07e: f8dd c00c ldr.w ip, [sp, #12] + 2d082: f8cd c00c str.w ip, [sp, #12] + 2d086: 9c0e ldr r4, [sp, #56] ; 0x38 + 2d088: 47a0 blx r4 + 2d08a: 9c07 ldr r4, [sp, #28] + 2d08c: 4680 mov r8, r0 + 2d08e: 47a0 blx r4 + 2d090: f64a 67d9 movw r7, #44761 ; 0xaed9 + 2d094: 4602 mov r2, r0 + 2d096: 460b mov r3, r1 + 2d098: 4650 mov r0, sl + 2d09a: 4659 mov r1, fp + 2d09c: 47a8 blx r5 + 2d09e: f108 0830 add.w r8, r8, #48 ; 0x30 + 2d0a2: 9c06 ldr r4, [sp, #24] + 2d0a4: f806 8b01 strb.w r8, [r6], #1 + 2d0a8: ebc4 0e06 rsb lr, r4, r6 + 2d0ac: 45ce cmp lr, r9 + 2d0ae: f2c0 0702 movt r7, #2 + 2d0b2: f8dd c00c ldr.w ip, [sp, #12] + 2d0b6: d1d8 bne.n 2d06a <__rtl_dtoa_r_v1_00+0x8ee> + 2d0b8: 460d mov r5, r1 + 2d0ba: e9dd 2314 ldrd r2, r3, [sp, #80] ; 0x50 + 2d0be: 2100 movs r1, #0 + 2d0c0: 4604 mov r4, r0 + 2d0c2: 9e10 ldr r6, [sp, #64] ; 0x40 + 2d0c4: 2000 movs r0, #0 + 2d0c6: f6c3 71e0 movt r1, #16352 ; 0x3fe0 + 2d0ca: f8dd 8060 ldr.w r8, [sp, #96] ; 0x60 + 2d0ce: 47b0 blx r6 + 2d0d0: f64b 7651 movw r6, #48977 ; 0xbf51 + 2d0d4: f8dd c00c ldr.w ip, [sp, #12] + 2d0d8: f8dd 9018 ldr.w r9, [sp, #24] + 2d0dc: 4602 mov r2, r0 + 2d0de: 460b mov r3, r1 + 2d0e0: 4620 mov r0, r4 + 2d0e2: 4629 mov r1, r5 + 2d0e4: f2c0 0602 movt r6, #2 + 2d0e8: 44e1 add r9, ip + 2d0ea: 47b0 blx r6 + 2d0ec: 2801 cmp r0, #1 + 2d0ee: f000 821a beq.w 2d526 <__rtl_dtoa_r_v1_00+0xdaa> + 2d0f2: e9dd 2314 ldrd r2, r3, [sp, #80] ; 0x50 + 2d0f6: 2100 movs r1, #0 + 2d0f8: 2000 movs r0, #0 + 2d0fa: f6c3 71e0 movt r1, #16352 ; 0x3fe0 + 2d0fe: 47b8 blx r7 + 2d100: 9f0c ldr r7, [sp, #48] ; 0x30 + 2d102: 4602 mov r2, r0 + 2d104: 460b mov r3, r1 + 2d106: 4620 mov r0, r4 + 2d108: 4629 mov r1, r5 + 2d10a: 47b8 blx r7 + 2d10c: 2801 cmp r0, #1 + 2d10e: d006 beq.n 2d11e <__rtl_dtoa_r_v1_00+0x9a2> + 2d110: e9dd 4512 ldrd r4, r5, [sp, #72] ; 0x48 + 2d114: e9cd 4514 strd r4, r5, [sp, #80] ; 0x50 + 2d118: e9dd ab14 ldrd sl, fp, [sp, #80] ; 0x50 + 2d11c: e48d b.n 2ca3a <__rtl_dtoa_r_v1_00+0x2be> + 2d11e: f819 2c01 ldrb.w r2, [r9, #-1] + 2d122: 464b mov r3, r9 + 2d124: 2a30 cmp r2, #48 ; 0x30 + 2d126: f109 39ff add.w r9, r9, #4294967295 + 2d12a: d0f8 beq.n 2d11e <__rtl_dtoa_r_v1_00+0x9a2> + 2d12c: f24e 5671 movw r6, #58737 ; 0xe571 + 2d130: 9f22 ldr r7, [sp, #136] ; 0x88 + 2d132: 9c06 ldr r4, [sp, #24] + 2d134: 970a str r7, [sp, #40] ; 0x28 + 2d136: 9306 str r3, [sp, #24] + 2d138: f2c0 0602 movt r6, #2 + 2d13c: e4d2 b.n 2cae4 <__rtl_dtoa_r_v1_00+0x368> + 2d13e: 4639 mov r1, r7 + 2d140: 4640 mov r0, r8 + 2d142: 47a8 blx r5 + 2d144: e4cb b.n 2cade <__rtl_dtoa_r_v1_00+0x362> + 2d146: 9c07 ldr r4, [sp, #28] + 2d148: 4648 mov r0, r9 + 2d14a: 47a0 blx r4 + 2d14c: 4632 mov r2, r6 + 2d14e: 463b mov r3, r7 + 2d150: 9d08 ldr r5, [sp, #32] + 2d152: 47a8 blx r5 + 2d154: 2300 movs r3, #0 + 2d156: 9c10 ldr r4, [sp, #64] ; 0x40 + 2d158: 2200 movs r2, #0 + 2d15a: f2c4 031c movt r3, #16412 ; 0x401c + 2d15e: 47a0 blx r4 + 2d160: 4604 mov r4, r0 + 2d162: f1a1 7550 sub.w r5, r1, #54525952 ; 0x3400000 + 2d166: 2300 movs r3, #0 + 2d168: 4630 mov r0, r6 + 2d16a: 4639 mov r1, r7 + 2d16c: 2200 movs r2, #0 + 2d16e: f2c4 0314 movt r3, #16404 ; 0x4014 + 2d172: 9e0b ldr r6, [sp, #44] ; 0x2c + 2d174: 47b0 blx r6 + 2d176: f64b 7c51 movw ip, #48977 ; 0xbf51 + 2d17a: 4622 mov r2, r4 + 2d17c: 462b mov r3, r5 + 2d17e: f2c0 0c02 movt ip, #2 + 2d182: 4606 mov r6, r0 + 2d184: 460f mov r7, r1 + 2d186: 47e0 blx ip + 2d188: 2801 cmp r0, #1 + 2d18a: f000 81f9 beq.w 2d580 <__rtl_dtoa_r_v1_00+0xe04> + 2d18e: 4639 mov r1, r7 + 2d190: 4622 mov r2, r4 + 2d192: f105 4300 add.w r3, r5, #2147483648 ; 0x80000000 + 2d196: 4630 mov r0, r6 + 2d198: 9f0c ldr r7, [sp, #48] ; 0x30 + 2d19a: 47b8 blx r7 + 2d19c: 2801 cmp r0, #1 + 2d19e: d1b7 bne.n 2d110 <__rtl_dtoa_r_v1_00+0x994> + 2d1a0: f24e 5671 movw r6, #58737 ; 0xe571 + 2d1a4: 2500 movs r5, #0 + 2d1a6: 9504 str r5, [sp, #16] + 2d1a8: f2c0 0602 movt r6, #2 + 2d1ac: 46a9 mov r9, r5 + 2d1ae: e56a b.n 2cc86 <__rtl_dtoa_r_v1_00+0x50a> + 2d1b0: 980a ldr r0, [sp, #40] ; 0x28 + 2d1b2: 9d07 ldr r5, [sp, #28] + 2d1b4: 47a8 blx r5 + 2d1b6: 9c04 ldr r4, [sp, #16] + 2d1b8: 4602 mov r2, r0 + 2d1ba: 460b mov r3, r1 + 2d1bc: e9dd 0112 ldrd r0, r1, [sp, #72] ; 0x48 + 2d1c0: 47a0 blx r4 + 2d1c2: 2800 cmp r0, #0 + 2d1c4: f43f abbd beq.w 2c942 <__rtl_dtoa_r_v1_00+0x1c6> + 2d1c8: 9d0a ldr r5, [sp, #40] ; 0x28 + 2d1ca: 3d01 subs r5, #1 + 2d1cc: 950a str r5, [sp, #40] ; 0x28 + 2d1ce: f7ff bbb8 b.w 2c942 <__rtl_dtoa_r_v1_00+0x1c6> + 2d1d2: 9d0a ldr r5, [sp, #40] ; 0x28 + 2d1d4: 426c negs r4, r5 + 2d1d6: 2c00 cmp r4, #0 + 2d1d8: f040 8231 bne.w 2d63e <__rtl_dtoa_r_v1_00+0xec2> + 2d1dc: e9dd 6714 ldrd r6, r7, [sp, #80] ; 0x50 + 2d1e0: f04f 0902 mov.w r9, #2 + 2d1e4: e60f b.n 2ce06 <__rtl_dtoa_r_v1_00+0x68a> + 2d1e6: f64e 0309 movw r3, #59401 ; 0xe809 + 2d1ea: 9c04 ldr r4, [sp, #16] + 2d1ec: f2c0 0302 movt r3, #2 + 2d1f0: 6922 ldr r2, [r4, #16] + 2d1f2: eb04 0282 add.w r2, r4, r2, lsl #2 + 2d1f6: 6910 ldr r0, [r2, #16] + 2d1f8: 4798 blx r3 + 2d1fa: f1c0 0020 rsb r0, r0, #32 + 2d1fe: e4f0 b.n 2cbe2 <__rtl_dtoa_r_v1_00+0x466> + 2d200: f64e 14bd movw r4, #59837 ; 0xe9bd + 2d204: f2c0 0402 movt r4, #2 + 2d208: 9817 ldr r0, [sp, #92] ; 0x5c + 2d20a: 9904 ldr r1, [sp, #16] + 2d20c: 9408 str r4, [sp, #32] + 2d20e: 47a0 blx r4 + 2d210: 2800 cmp r0, #0 + 2d212: f6bf ad16 bge.w 2cc42 <__rtl_dtoa_r_v1_00+0x4c6> + 2d216: f24e 5499 movw r4, #58777 ; 0xe599 + 2d21a: f8dd e028 ldr.w lr, [sp, #40] ; 0x28 + 2d21e: 9917 ldr r1, [sp, #92] ; 0x5c + 2d220: f10e 3eff add.w lr, lr, #4294967295 + 2d224: f2c0 0402 movt r4, #2 + 2d228: 4640 mov r0, r8 + 2d22a: 220a movs r2, #10 + 2d22c: 2300 movs r3, #0 + 2d22e: f8cd e028 str.w lr, [sp, #40] ; 0x28 + 2d232: 47a0 blx r4 + 2d234: 9017 str r0, [sp, #92] ; 0x5c + 2d236: 981c ldr r0, [sp, #112] ; 0x70 + 2d238: 2800 cmp r0, #0 + 2d23a: f040 82a7 bne.w 2d78c <__rtl_dtoa_r_v1_00+0x1010> + 2d23e: 9d30 ldr r5, [sp, #192] ; 0xc0 + 2d240: 2d02 cmp r5, #2 + 2d242: dd03 ble.n 2d24c <__rtl_dtoa_r_v1_00+0xad0> + 2d244: 9f1e ldr r7, [sp, #120] ; 0x78 + 2d246: 2f00 cmp r7, #0 + 2d248: f340 82b7 ble.w 2d7ba <__rtl_dtoa_r_v1_00+0x103e> + 2d24c: 9c1e ldr r4, [sp, #120] ; 0x78 + 2d24e: 9411 str r4, [sp, #68] ; 0x44 + 2d250: e6a5 b.n 2cf9e <__rtl_dtoa_r_v1_00+0x822> + 2d252: f64b 06ad movw r6, #47277 ; 0xb8ad + 2d256: f24b 5755 movw r7, #46421 ; 0xb555 + 2d25a: f2c0 0602 movt r6, #2 + 2d25e: f2c0 0702 movt r7, #2 + 2d262: 4654 mov r4, sl + 2d264: 465d mov r5, fp + 2d266: e9dd ab0c ldrd sl, fp, [sp, #48] ; 0x30 + 2d26a: f8cd 8024 str.w r8, [sp, #36] ; 0x24 + 2d26e: 9705 str r7, [sp, #20] + 2d270: f8dd 9018 ldr.w r9, [sp, #24] + 2d274: f8dd 8044 ldr.w r8, [sp, #68] ; 0x44 + 2d278: 960f str r6, [sp, #60] ; 0x3c + 2d27a: e00e b.n 2d29a <__rtl_dtoa_r_v1_00+0xb1e> + 2d27c: 2300 movs r3, #0 + 2d27e: 2200 movs r2, #0 + 2d280: f2c4 0324 movt r3, #16420 ; 0x4024 + 2d284: 9d05 ldr r5, [sp, #20] + 2d286: 47a8 blx r5 + 2d288: 2200 movs r2, #0 + 2d28a: 2300 movs r3, #0 + 2d28c: 9e04 ldr r6, [sp, #16] + 2d28e: 4604 mov r4, r0 + 2d290: 460d mov r5, r1 + 2d292: 47b0 blx r6 + 2d294: 2800 cmp r0, #0 + 2d296: f040 8133 bne.w 2d500 <__rtl_dtoa_r_v1_00+0xd84> + 2d29a: 4652 mov r2, sl + 2d29c: 465b mov r3, fp + 2d29e: 4620 mov r0, r4 + 2d2a0: 4629 mov r1, r5 + 2d2a2: 9e0f ldr r6, [sp, #60] ; 0x3c + 2d2a4: 47b0 blx r6 + 2d2a6: 9e0e ldr r6, [sp, #56] ; 0x38 + 2d2a8: 47b0 blx r6 + 2d2aa: 9e07 ldr r6, [sp, #28] + 2d2ac: 4607 mov r7, r0 + 2d2ae: 47b0 blx r6 + 2d2b0: 4652 mov r2, sl + 2d2b2: 465b mov r3, fp + 2d2b4: 9e08 ldr r6, [sp, #32] + 2d2b6: 47b0 blx r6 + 2d2b8: 4602 mov r2, r0 + 2d2ba: 460b mov r3, r1 + 2d2bc: 4620 mov r0, r4 + 2d2be: 4629 mov r1, r5 + 2d2c0: 9c0b ldr r4, [sp, #44] ; 0x2c + 2d2c2: 47a0 blx r4 + 2d2c4: f107 0430 add.w r4, r7, #48 ; 0x30 + 2d2c8: 9d06 ldr r5, [sp, #24] + 2d2ca: f809 4b01 strb.w r4, [r9], #1 + 2d2ce: ebc5 0409 rsb r4, r5, r9 + 2d2d2: 4544 cmp r4, r8 + 2d2d4: 4602 mov r2, r0 + 2d2d6: 460b mov r3, r1 + 2d2d8: d1d0 bne.n 2d27c <__rtl_dtoa_r_v1_00+0xb00> + 2d2da: 9e10 ldr r6, [sp, #64] ; 0x40 + 2d2dc: f64b 7451 movw r4, #48977 ; 0xbf51 + 2d2e0: f8dd 8024 ldr.w r8, [sp, #36] ; 0x24 + 2d2e4: 47b0 blx r6 + 2d2e6: e9dd 230c ldrd r2, r3, [sp, #48] ; 0x30 + 2d2ea: f2c0 0402 movt r4, #2 + 2d2ee: 4682 mov sl, r0 + 2d2f0: 468b mov fp, r1 + 2d2f2: 47a0 blx r4 + 2d2f4: 2801 cmp r0, #1 + 2d2f6: f000 8203 beq.w 2d700 <__rtl_dtoa_r_v1_00+0xf84> + 2d2fa: e9dd 230c ldrd r2, r3, [sp, #48] ; 0x30 + 2d2fe: 4650 mov r0, sl + 2d300: 4659 mov r1, fp + 2d302: 9c04 ldr r4, [sp, #16] + 2d304: 47a0 blx r4 + 2d306: 2800 cmp r0, #0 + 2d308: f040 80fc bne.w 2d504 <__rtl_dtoa_r_v1_00+0xd88> + 2d30c: 07f9 lsls r1, r7, #31 + 2d30e: f140 80f9 bpl.w 2d504 <__rtl_dtoa_r_v1_00+0xd88> + 2d312: 9f0a ldr r7, [sp, #40] ; 0x28 + 2d314: 9906 ldr r1, [sp, #24] + 2d316: 9722 str r7, [sp, #136] ; 0x88 + 2d318: e003 b.n 2d322 <__rtl_dtoa_r_v1_00+0xba6> + 2d31a: 4299 cmp r1, r3 + 2d31c: f000 80fb beq.w 2d516 <__rtl_dtoa_r_v1_00+0xd9a> + 2d320: 4699 mov r9, r3 + 2d322: f819 2c01 ldrb.w r2, [r9, #-1] + 2d326: f109 33ff add.w r3, r9, #4294967295 + 2d32a: 2a39 cmp r2, #57 ; 0x39 + 2d32c: d0f5 beq.n 2d31a <__rtl_dtoa_r_v1_00+0xb9e> + 2d32e: 9c22 ldr r4, [sp, #136] ; 0x88 + 2d330: 3201 adds r2, #1 + 2d332: 9106 str r1, [sp, #24] + 2d334: 940a str r4, [sp, #40] ; 0x28 + 2d336: b2d2 uxtb r2, r2 + 2d338: f24e 5671 movw r6, #58737 ; 0xe571 + 2d33c: 9c06 ldr r4, [sp, #24] + 2d33e: 701a strb r2, [r3, #0] + 2d340: f8cd 9018 str.w r9, [sp, #24] + 2d344: f2c0 0602 movt r6, #2 + 2d348: f7ff bbcc b.w 2cae4 <__rtl_dtoa_r_v1_00+0x368> + 2d34c: f1ba 0f00 cmp.w sl, #0 + 2d350: f47f ac41 bne.w 2cbd6 <__rtl_dtoa_r_v1_00+0x45a> + 2d354: f3cb 0313 ubfx r3, fp, #0, #20 + 2d358: 4655 mov r5, sl + 2d35a: 2b00 cmp r3, #0 + 2d35c: f47f ac3c bne.w 2cbd8 <__rtl_dtoa_r_v1_00+0x45c> + 2d360: f02b 4500 bic.w r5, fp, #2147483648 ; 0x80000000 + 2d364: 0d2d lsrs r5, r5, #20 + 2d366: 052d lsls r5, r5, #20 + 2d368: 2d00 cmp r5, #0 + 2d36a: f43f ac35 beq.w 2cbd8 <__rtl_dtoa_r_v1_00+0x45c> + 2d36e: 9c16 ldr r4, [sp, #88] ; 0x58 + 2d370: 9d0f ldr r5, [sp, #60] ; 0x3c + 2d372: 3401 adds r4, #1 + 2d374: 3501 adds r5, #1 + 2d376: 950f str r5, [sp, #60] ; 0x3c + 2d378: 9416 str r4, [sp, #88] ; 0x58 + 2d37a: 2501 movs r5, #1 + 2d37c: e42c b.n 2cbd8 <__rtl_dtoa_r_v1_00+0x45c> + 2d37e: f64e 14bd movw r4, #59837 ; 0xe9bd + 2d382: f2c0 0402 movt r4, #2 + 2d386: 9408 str r4, [sp, #32] + 2d388: 2f00 cmp r7, #0 + 2d38a: dd08 ble.n 2d39e <__rtl_dtoa_r_v1_00+0xc22> + 2d38c: f64e 1301 movw r3, #59649 ; 0xe901 + 2d390: 4649 mov r1, r9 + 2d392: 463a mov r2, r7 + 2d394: f2c0 0302 movt r3, #2 + 2d398: 4640 mov r0, r8 + 2d39a: 4798 blx r3 + 2d39c: 4681 mov r9, r0 + 2d39e: 46cc mov ip, r9 + 2d3a0: 2d00 cmp r5, #0 + 2d3a2: f040 8191 bne.w 2d6c8 <__rtl_dtoa_r_v1_00+0xf4c> + 2d3a6: f64e 2701 movw r7, #59905 ; 0xea01 + 2d3aa: f64e 14bd movw r4, #59837 ; 0xe9bd + 2d3ae: f2c0 0702 movt r7, #2 + 2d3b2: f2c0 0402 movt r4, #2 + 2d3b6: f24e 5599 movw r5, #58777 ; 0xe599 + 2d3ba: 9709 str r7, [sp, #36] ; 0x24 + 2d3bc: 940e str r4, [sp, #56] ; 0x38 + 2d3be: 9f06 ldr r7, [sp, #24] + 2d3c0: 9c11 ldr r4, [sp, #68] ; 0x44 + 2d3c2: 960b str r6, [sp, #44] ; 0x2c + 2d3c4: 4427 add r7, r4 + 2d3c6: f00a 0401 and.w r4, sl, #1 + 2d3ca: 940f str r4, [sp, #60] ; 0x3c + 2d3cc: 9c06 ldr r4, [sp, #24] + 2d3ce: 9710 str r7, [sp, #64] ; 0x40 + 2d3d0: f2c0 0502 movt r5, #2 + 2d3d4: 3401 adds r4, #1 + 2d3d6: 4667 mov r7, ip + 2d3d8: 9e17 ldr r6, [sp, #92] ; 0x5c + 2d3da: e008 b.n 2d3ee <__rtl_dtoa_r_v1_00+0xc72> + 2d3dc: 47a8 blx r5 + 2d3de: 4639 mov r1, r7 + 2d3e0: 4681 mov r9, r0 + 2d3e2: 220a movs r2, #10 + 2d3e4: 4640 mov r0, r8 + 2d3e6: 2300 movs r3, #0 + 2d3e8: 47a8 blx r5 + 2d3ea: 4607 mov r7, r0 + 2d3ec: 3401 adds r4, #1 + 2d3ee: 9904 ldr r1, [sp, #16] + 2d3f0: 4630 mov r0, r6 + 2d3f2: f7ff f929 bl 2c648 + 2d3f6: 4649 mov r1, r9 + 2d3f8: 4682 mov sl, r0 + 2d3fa: 9a08 ldr r2, [sp, #32] + 2d3fc: 4630 mov r0, r6 + 2d3fe: 4790 blx r2 + 2d400: 463a mov r2, r7 + 2d402: 9b09 ldr r3, [sp, #36] ; 0x24 + 2d404: 4683 mov fp, r0 + 2d406: 9904 ldr r1, [sp, #16] + 2d408: 4640 mov r0, r8 + 2d40a: 4798 blx r3 + 2d40c: 68c2 ldr r2, [r0, #12] + 2d40e: 4603 mov r3, r0 + 2d410: f10a 0e30 add.w lr, sl, #48 ; 0x30 + 2d414: 1e60 subs r0, r4, #1 + 2d416: f8cd e01c str.w lr, [sp, #28] + 2d41a: 900c str r0, [sp, #48] ; 0x30 + 2d41c: 2a00 cmp r2, #0 + 2d41e: d13c bne.n 2d49a <__rtl_dtoa_r_v1_00+0xd1e> + 2d420: 4619 mov r1, r3 + 2d422: 9303 str r3, [sp, #12] + 2d424: 9a0e ldr r2, [sp, #56] ; 0x38 + 2d426: 4630 mov r0, r6 + 2d428: 4790 blx r2 + 2d42a: 4602 mov r2, r0 + 2d42c: 9b03 ldr r3, [sp, #12] + 2d42e: 4619 mov r1, r3 + 2d430: 4640 mov r0, r8 + 2d432: 9203 str r2, [sp, #12] + 2d434: 9b0b ldr r3, [sp, #44] ; 0x2c + 2d436: 4798 blx r3 + 2d438: 9a03 ldr r2, [sp, #12] + 2d43a: 9830 ldr r0, [sp, #192] ; 0xc0 + 2d43c: 4310 orrs r0, r2 + 2d43e: d103 bne.n 2d448 <__rtl_dtoa_r_v1_00+0xccc> + 2d440: 990f ldr r1, [sp, #60] ; 0x3c + 2d442: 2900 cmp r1, #0 + 2d444: f000 8188 beq.w 2d758 <__rtl_dtoa_r_v1_00+0xfdc> + 2d448: f1bb 0f00 cmp.w fp, #0 + 2d44c: f2c0 80cf blt.w 2d5ee <__rtl_dtoa_r_v1_00+0xe72> + 2d450: 9830 ldr r0, [sp, #192] ; 0xc0 + 2d452: ea5b 0000 orrs.w r0, fp, r0 + 2d456: d103 bne.n 2d460 <__rtl_dtoa_r_v1_00+0xce4> + 2d458: 990f ldr r1, [sp, #60] ; 0x3c + 2d45a: 2900 cmp r1, #0 + 2d45c: f000 80c7 beq.w 2d5ee <__rtl_dtoa_r_v1_00+0xe72> + 2d460: 2a00 cmp r2, #0 + 2d462: f300 815f bgt.w 2d724 <__rtl_dtoa_r_v1_00+0xfa8> + 2d466: 9b10 ldr r3, [sp, #64] ; 0x40 + 2d468: 9a07 ldr r2, [sp, #28] + 2d46a: 429c cmp r4, r3 + 2d46c: f804 2c01 strb.w r2, [r4, #-1] + 2d470: 46a2 mov sl, r4 + 2d472: f000 8150 beq.w 2d716 <__rtl_dtoa_r_v1_00+0xf9a> + 2d476: 4631 mov r1, r6 + 2d478: 220a movs r2, #10 + 2d47a: 2300 movs r3, #0 + 2d47c: 4640 mov r0, r8 + 2d47e: 47a8 blx r5 + 2d480: 45b9 cmp r9, r7 + 2d482: 4606 mov r6, r0 + 2d484: 4649 mov r1, r9 + 2d486: 4640 mov r0, r8 + 2d488: f04f 020a mov.w r2, #10 + 2d48c: f04f 0300 mov.w r3, #0 + 2d490: d1a4 bne.n 2d3dc <__rtl_dtoa_r_v1_00+0xc60> + 2d492: 47a8 blx r5 + 2d494: 4681 mov r9, r0 + 2d496: 4607 mov r7, r0 + 2d498: e7a8 b.n 2d3ec <__rtl_dtoa_r_v1_00+0xc70> + 2d49a: 2201 movs r2, #1 + 2d49c: e7c7 b.n 2d42e <__rtl_dtoa_r_v1_00+0xcb2> + 2d49e: f64b 06ad movw r6, #47277 ; 0xb8ad + 2d4a2: a3b7 add r3, pc, #732 ; (adr r3, 2d780 <__rtl_dtoa_r_v1_00+0x1004>) + 2d4a4: e9d3 2300 ldrd r2, r3, [r3] + 2d4a8: 4650 mov r0, sl + 2d4aa: 4659 mov r1, fp + 2d4ac: f2c0 0602 movt r6, #2 + 2d4b0: 47b0 blx r6 + 2d4b2: f007 070f and.w r7, r7, #15 + 2d4b6: e9cd 0118 strd r0, r1, [sp, #96] ; 0x60 + 2d4ba: f04f 0903 mov.w r9, #3 + 2d4be: e472 b.n 2cda6 <__rtl_dtoa_r_v1_00+0x62a> + 2d4c0: 2601 movs r6, #1 + 2d4c2: 961c str r6, [sp, #112] ; 0x70 + 2d4c4: e41e b.n 2cd04 <__rtl_dtoa_r_v1_00+0x588> + 2d4c6: f24e 7369 movw r3, #59241 ; 0xe769 + 2d4ca: 9917 ldr r1, [sp, #92] ; 0x5c + 2d4cc: 9a1b ldr r2, [sp, #108] ; 0x6c + 2d4ce: f2c0 0302 movt r3, #2 + 2d4d2: 4640 mov r0, r8 + 2d4d4: f24e 5671 movw r6, #58737 ; 0xe571 + 2d4d8: 4798 blx r3 + 2d4da: f2c0 0602 movt r6, #2 + 2d4de: 9017 str r0, [sp, #92] ; 0x5c + 2d4e0: f7ff bb65 b.w 2cbae <__rtl_dtoa_r_v1_00+0x432> + 2d4e4: 2301 movs r3, #1 + 2d4e6: 9331 str r3, [sp, #196] ; 0xc4 + 2d4e8: 931e str r3, [sp, #120] ; 0x78 + 2d4ea: 9311 str r3, [sp, #68] ; 0x44 + 2d4ec: 2200 movs r2, #0 + 2d4ee: 401c ands r4, r3 + 2d4f0: f8c8 2044 str.w r2, [r8, #68] ; 0x44 + 2d4f4: e427 b.n 2cd46 <__rtl_dtoa_r_v1_00+0x5ca> + 2d4f6: 2e0e cmp r6, #14 + 2d4f8: bf8c ite hi + 2d4fa: 2300 movhi r3, #0 + 2d4fc: 2301 movls r3, #1 + 2d4fe: e7f5 b.n 2d4ec <__rtl_dtoa_r_v1_00+0xd70> + 2d500: f8dd 8024 ldr.w r8, [sp, #36] ; 0x24 + 2d504: f24e 5671 movw r6, #58737 ; 0xe571 + 2d508: 9c06 ldr r4, [sp, #24] + 2d50a: f2c0 0602 movt r6, #2 + 2d50e: f8cd 9018 str.w r9, [sp, #24] + 2d512: f7ff bae7 b.w 2cae4 <__rtl_dtoa_r_v1_00+0x368> + 2d516: 9d22 ldr r5, [sp, #136] ; 0x88 + 2d518: 2230 movs r2, #48 ; 0x30 + 2d51a: 3501 adds r5, #1 + 2d51c: 700a strb r2, [r1, #0] + 2d51e: 9106 str r1, [sp, #24] + 2d520: 950a str r5, [sp, #40] ; 0x28 + 2d522: 2231 movs r2, #49 ; 0x31 + 2d524: e708 b.n 2d338 <__rtl_dtoa_r_v1_00+0xbbc> + 2d526: 9906 ldr r1, [sp, #24] + 2d528: e6fb b.n 2d322 <__rtl_dtoa_r_v1_00+0xba6> + 2d52a: 9c11 ldr r4, [sp, #68] ; 0x44 + 2d52c: 2c00 cmp r4, #0 + 2d52e: f43f ae0a beq.w 2d146 <__rtl_dtoa_r_v1_00+0x9ca> + 2d532: 9d1e ldr r5, [sp, #120] ; 0x78 + 2d534: 2d00 cmp r5, #0 + 2d536: f77f adef ble.w 2d118 <__rtl_dtoa_r_v1_00+0x99c> + 2d53a: 2300 movs r3, #0 + 2d53c: 2200 movs r2, #0 + 2d53e: f2c4 0324 movt r3, #16420 ; 0x4024 + 2d542: 4630 mov r0, r6 + 2d544: 4639 mov r1, r7 + 2d546: 9e08 ldr r6, [sp, #32] + 2d548: 47b0 blx r6 + 2d54a: 4606 mov r6, r0 + 2d54c: 460f mov r7, r1 + 2d54e: 9c07 ldr r4, [sp, #28] + 2d550: f109 0001 add.w r0, r9, #1 + 2d554: 47a0 blx r4 + 2d556: 4632 mov r2, r6 + 2d558: 463b mov r3, r7 + 2d55a: 9d08 ldr r5, [sp, #32] + 2d55c: 47a8 blx r5 + 2d55e: 2300 movs r3, #0 + 2d560: 9c10 ldr r4, [sp, #64] ; 0x40 + 2d562: 2200 movs r2, #0 + 2d564: f2c4 031c movt r3, #16412 ; 0x401c + 2d568: 47a0 blx r4 + 2d56a: 46b2 mov sl, r6 + 2d56c: 9e0a ldr r6, [sp, #40] ; 0x28 + 2d56e: 4604 mov r4, r0 + 2d570: 3e01 subs r6, #1 + 2d572: 46bb mov fp, r7 + 2d574: f1a1 7550 sub.w r5, r1, #54525952 ; 0x3400000 + 2d578: 9622 str r6, [sp, #136] ; 0x88 + 2d57a: f8dd c078 ldr.w ip, [sp, #120] ; 0x78 + 2d57e: e467 b.n 2ce50 <__rtl_dtoa_r_v1_00+0x6d4> + 2d580: f24e 5671 movw r6, #58737 ; 0xe571 + 2d584: 2400 movs r4, #0 + 2d586: 9404 str r4, [sp, #16] + 2d588: f2c0 0602 movt r6, #2 + 2d58c: 46a1 mov r9, r4 + 2d58e: f7ff ba8d b.w 2caac <__rtl_dtoa_r_v1_00+0x330> + 2d592: f24e 7369 movw r3, #59241 ; 0xe769 + 2d596: 9917 ldr r1, [sp, #92] ; 0x5c + 2d598: f2c0 0302 movt r3, #2 + 2d59c: 4640 mov r0, r8 + 2d59e: 4798 blx r3 + 2d5a0: 9017 str r0, [sp, #92] ; 0x5c + 2d5a2: f7ff bb04 b.w 2cbae <__rtl_dtoa_r_v1_00+0x432> + 2d5a6: 9d0a ldr r5, [sp, #40] ; 0x28 + 2d5a8: 9c06 ldr r4, [sp, #24] + 2d5aa: 2331 movs r3, #49 ; 0x31 + 2d5ac: 3501 adds r5, #1 + 2d5ae: 950a str r5, [sp, #40] ; 0x28 + 2d5b0: 7023 strb r3, [r4, #0] + 2d5b2: f8cd a018 str.w sl, [sp, #24] + 2d5b6: f7ff ba83 b.w 2cac0 <__rtl_dtoa_r_v1_00+0x344> + 2d5ba: f24e 5671 movw r6, #58737 ; 0xe571 + 2d5be: 2400 movs r4, #0 + 2d5c0: 9404 str r4, [sp, #16] + 2d5c2: f2c0 0602 movt r6, #2 + 2d5c6: 46a1 mov r9, r4 + 2d5c8: f7ff bb5d b.w 2cc86 <__rtl_dtoa_r_v1_00+0x50a> + 2d5cc: 9d21 ldr r5, [sp, #132] ; 0x84 + 2d5ce: 2d00 cmp r5, #0 + 2d5d0: f000 809a beq.w 2d708 <__rtl_dtoa_r_v1_00+0xf8c> + 2d5d4: f203 4333 addw r3, r3, #1075 ; 0x433 + 2d5d8: 9d1b ldr r5, [sp, #108] ; 0x6c + 2d5da: 9f16 ldr r7, [sp, #88] ; 0x58 + 2d5dc: f7ff bb81 b.w 2cce2 <__rtl_dtoa_r_v1_00+0x566> + 2d5e0: 9906 ldr r1, [sp, #24] + 2d5e2: f8dd 808c ldr.w r8, [sp, #140] ; 0x8c + 2d5e6: e69c b.n 2d322 <__rtl_dtoa_r_v1_00+0xba6> + 2d5e8: f8dd 808c ldr.w r8, [sp, #140] ; 0x8c + 2d5ec: e590 b.n 2d110 <__rtl_dtoa_r_v1_00+0x994> + 2d5ee: 9d07 ldr r5, [sp, #28] + 2d5f0: 2a00 cmp r2, #0 + 2d5f2: 9617 str r6, [sp, #92] ; 0x5c + 2d5f4: 46bc mov ip, r7 + 2d5f6: 9e0b ldr r6, [sp, #44] ; 0x2c + 2d5f8: 462c mov r4, r5 + 2d5fa: dd16 ble.n 2d62a <__rtl_dtoa_r_v1_00+0xeae> + 2d5fc: f64e 1301 movw r3, #59649 ; 0xe901 + 2d600: 9917 ldr r1, [sp, #92] ; 0x5c + 2d602: f2c0 0302 movt r3, #2 + 2d606: 2201 movs r2, #1 + 2d608: 9703 str r7, [sp, #12] + 2d60a: 4640 mov r0, r8 + 2d60c: 4798 blx r3 + 2d60e: 9904 ldr r1, [sp, #16] + 2d610: 9f08 ldr r7, [sp, #32] + 2d612: 9017 str r0, [sp, #92] ; 0x5c + 2d614: 47b8 blx r7 + 2d616: 2800 cmp r0, #0 + 2d618: f8dd c00c ldr.w ip, [sp, #12] + 2d61c: f340 80a8 ble.w 2d770 <__rtl_dtoa_r_v1_00+0xff4> + 2d620: 2c39 cmp r4, #57 ; 0x39 + 2d622: f10a 0531 add.w r5, sl, #49 ; 0x31 + 2d626: f000 808e beq.w 2d746 <__rtl_dtoa_r_v1_00+0xfca> + 2d62a: 9b0c ldr r3, [sp, #48] ; 0x30 + 2d62c: 9c06 ldr r4, [sp, #24] + 2d62e: 3301 adds r3, #1 + 2d630: f803 5c01 strb.w r5, [r3, #-1] + 2d634: 464f mov r7, r9 + 2d636: 9306 str r3, [sp, #24] + 2d638: 46e1 mov r9, ip + 2d63a: f7ff ba41 b.w 2cac0 <__rtl_dtoa_r_v1_00+0x344> + 2d63e: f64e 3508 movw r5, #60168 ; 0xeb08 + 2d642: e9dd 0114 ldrd r0, r1, [sp, #80] ; 0x50 + 2d646: f2c0 0503 movt r5, #3 + 2d64a: f004 030f and.w r3, r4, #15 + 2d64e: eb05 03c3 add.w r3, r5, r3, lsl #3 + 2d652: 9e08 ldr r6, [sp, #32] + 2d654: e9d3 2300 ldrd r2, r3, [r3] + 2d658: 47b0 blx r6 + 2d65a: 1124 asrs r4, r4, #4 + 2d65c: 4606 mov r6, r0 + 2d65e: 460f mov r7, r1 + 2d660: 4682 mov sl, r0 + 2d662: 468b mov fp, r1 + 2d664: f000 80a1 beq.w 2d7aa <__rtl_dtoa_r_v1_00+0x102e> + 2d668: 35c8 adds r5, #200 ; 0xc8 + 2d66a: f04f 0902 mov.w r9, #2 + 2d66e: 9e08 ldr r6, [sp, #32] + 2d670: e003 b.n 2d67a <__rtl_dtoa_r_v1_00+0xefe> + 2d672: 1064 asrs r4, r4, #1 + 2d674: f105 0508 add.w r5, r5, #8 + 2d678: d019 beq.n 2d6ae <__rtl_dtoa_r_v1_00+0xf32> + 2d67a: 07e7 lsls r7, r4, #31 + 2d67c: d5f9 bpl.n 2d672 <__rtl_dtoa_r_v1_00+0xef6> + 2d67e: e9d5 2300 ldrd r2, r3, [r5] + 2d682: 47b0 blx r6 + 2d684: f109 0901 add.w r9, r9, #1 + 2d688: 4682 mov sl, r0 + 2d68a: 468b mov fp, r1 + 2d68c: e7f1 b.n 2d672 <__rtl_dtoa_r_v1_00+0xef6> + 2d68e: d102 bne.n 2d696 <__rtl_dtoa_r_v1_00+0xf1a> + 2d690: 07eb lsls r3, r5, #31 + 2d692: f53f acbe bmi.w 2d012 <__rtl_dtoa_r_v1_00+0x896> + 2d696: 4651 mov r1, sl + 2d698: f811 2c01 ldrb.w r2, [r1, #-1] + 2d69c: 460b mov r3, r1 + 2d69e: 2a30 cmp r2, #48 ; 0x30 + 2d6a0: f101 31ff add.w r1, r1, #4294967295 + 2d6a4: d0f8 beq.n 2d698 <__rtl_dtoa_r_v1_00+0xf1c> + 2d6a6: 9c06 ldr r4, [sp, #24] + 2d6a8: 9306 str r3, [sp, #24] + 2d6aa: f7ff ba09 b.w 2cac0 <__rtl_dtoa_r_v1_00+0x344> + 2d6ae: 4606 mov r6, r0 + 2d6b0: 460f mov r7, r1 + 2d6b2: f7ff bba8 b.w 2ce06 <__rtl_dtoa_r_v1_00+0x68a> + 2d6b6: f24e 5671 movw r6, #58737 ; 0xe571 + 2d6ba: 9d11 ldr r5, [sp, #68] ; 0x44 + 2d6bc: f2c0 0602 movt r6, #2 + 2d6c0: 9504 str r5, [sp, #16] + 2d6c2: 46a9 mov r9, r5 + 2d6c4: f7ff badf b.w 2cc86 <__rtl_dtoa_r_v1_00+0x50a> + 2d6c8: f8d9 1004 ldr.w r1, [r9, #4] + 2d6cc: 4640 mov r0, r8 + 2d6ce: 9d1a ldr r5, [sp, #104] ; 0x68 + 2d6d0: 47a8 blx r5 + 2d6d2: f648 3349 movw r3, #35657 ; 0x8b49 + 2d6d6: f8d9 2010 ldr.w r2, [r9, #16] + 2d6da: 4604 mov r4, r0 + 2d6dc: 3202 adds r2, #2 + 2d6de: 0092 lsls r2, r2, #2 + 2d6e0: f2c0 0302 movt r3, #2 + 2d6e4: f109 010c add.w r1, r9, #12 + 2d6e8: 300c adds r0, #12 + 2d6ea: 4798 blx r3 + 2d6ec: f64e 1301 movw r3, #59649 ; 0xe901 + 2d6f0: 4640 mov r0, r8 + 2d6f2: 4621 mov r1, r4 + 2d6f4: 2201 movs r2, #1 + 2d6f6: f2c0 0302 movt r3, #2 + 2d6fa: 4798 blx r3 + 2d6fc: 4684 mov ip, r0 + 2d6fe: e652 b.n 2d3a6 <__rtl_dtoa_r_v1_00+0xc2a> + 2d700: 9e0a ldr r6, [sp, #40] ; 0x28 + 2d702: 9906 ldr r1, [sp, #24] + 2d704: 9622 str r6, [sp, #136] ; 0x88 + 2d706: e60c b.n 2d322 <__rtl_dtoa_r_v1_00+0xba6> + 2d708: 9b24 ldr r3, [sp, #144] ; 0x90 + 2d70a: 9d1b ldr r5, [sp, #108] ; 0x6c + 2d70c: f1c3 0336 rsb r3, r3, #54 ; 0x36 + 2d710: 9f16 ldr r7, [sp, #88] ; 0x58 + 2d712: f7ff bae6 b.w 2cce2 <__rtl_dtoa_r_v1_00+0x566> + 2d716: 46bc mov ip, r7 + 2d718: 9617 str r6, [sp, #92] ; 0x5c + 2d71a: 464f mov r7, r9 + 2d71c: 9d07 ldr r5, [sp, #28] + 2d71e: 9e0b ldr r6, [sp, #44] ; 0x2c + 2d720: 46e1 mov r9, ip + 2d722: e467 b.n 2cff4 <__rtl_dtoa_r_v1_00+0x878> + 2d724: 9d07 ldr r5, [sp, #28] + 2d726: 9617 str r6, [sp, #92] ; 0x5c + 2d728: 2d39 cmp r5, #57 ; 0x39 + 2d72a: 46bc mov ip, r7 + 2d72c: 9e0b ldr r6, [sp, #44] ; 0x2c + 2d72e: d00a beq.n 2d746 <__rtl_dtoa_r_v1_00+0xfca> + 2d730: 9f0c ldr r7, [sp, #48] ; 0x30 + 2d732: 3501 adds r5, #1 + 2d734: 703d strb r5, [r7, #0] + 2d736: 9d0c ldr r5, [sp, #48] ; 0x30 + 2d738: 9c06 ldr r4, [sp, #24] + 2d73a: 3501 adds r5, #1 + 2d73c: 464f mov r7, r9 + 2d73e: 9506 str r5, [sp, #24] + 2d740: 46e1 mov r9, ip + 2d742: f7ff b9bd b.w 2cac0 <__rtl_dtoa_r_v1_00+0x344> + 2d746: 9c0c ldr r4, [sp, #48] ; 0x30 + 2d748: 2239 movs r2, #57 ; 0x39 + 2d74a: 464f mov r7, r9 + 2d74c: 7022 strb r2, [r4, #0] + 2d74e: 46e1 mov r9, ip + 2d750: f104 0a01 add.w sl, r4, #1 + 2d754: 9906 ldr r1, [sp, #24] + 2d756: e466 b.n 2d026 <__rtl_dtoa_r_v1_00+0x8aa> + 2d758: 9d07 ldr r5, [sp, #28] + 2d75a: 9617 str r6, [sp, #92] ; 0x5c + 2d75c: 2d39 cmp r5, #57 ; 0x39 + 2d75e: 46bc mov ip, r7 + 2d760: 9e0b ldr r6, [sp, #44] ; 0x2c + 2d762: 465f mov r7, fp + 2d764: d0ef beq.n 2d746 <__rtl_dtoa_r_v1_00+0xfca> + 2d766: 2f00 cmp r7, #0 + 2d768: bfc8 it gt + 2d76a: f10a 0531 addgt.w r5, sl, #49 ; 0x31 + 2d76e: e75c b.n 2d62a <__rtl_dtoa_r_v1_00+0xeae> + 2d770: f47f af5b bne.w 2d62a <__rtl_dtoa_r_v1_00+0xeae> + 2d774: 07ea lsls r2, r5, #31 + 2d776: f57f af58 bpl.w 2d62a <__rtl_dtoa_r_v1_00+0xeae> + 2d77a: e751 b.n 2d620 <__rtl_dtoa_r_v1_00+0xea4> + 2d77c: f3af 8000 nop.w + 2d780: 7f73bf3c .word 0x7f73bf3c + 2d784: 75154fdd .word 0x75154fdd + 2d788: 0003ebd0 .word 0x0003ebd0 + 2d78c: 4649 mov r1, r9 + 2d78e: 4640 mov r0, r8 + 2d790: 220a movs r2, #10 + 2d792: 2300 movs r3, #0 + 2d794: 47a0 blx r4 + 2d796: 9c30 ldr r4, [sp, #192] ; 0xc0 + 2d798: 4681 mov r9, r0 + 2d79a: 2c02 cmp r4, #2 + 2d79c: dd02 ble.n 2d7a4 <__rtl_dtoa_r_v1_00+0x1028> + 2d79e: 9c1e ldr r4, [sp, #120] ; 0x78 + 2d7a0: 2c00 cmp r4, #0 + 2d7a2: dd06 ble.n 2d7b2 <__rtl_dtoa_r_v1_00+0x1036> + 2d7a4: 9c1e ldr r4, [sp, #120] ; 0x78 + 2d7a6: 9411 str r4, [sp, #68] ; 0x44 + 2d7a8: e5ee b.n 2d388 <__rtl_dtoa_r_v1_00+0xc0c> + 2d7aa: f04f 0902 mov.w r9, #2 + 2d7ae: f7ff bb2a b.w 2ce06 <__rtl_dtoa_r_v1_00+0x68a> + 2d7b2: 9c1e ldr r4, [sp, #120] ; 0x78 + 2d7b4: 9411 str r4, [sp, #68] ; 0x44 + 2d7b6: f7ff ba50 b.w 2cc5a <__rtl_dtoa_r_v1_00+0x4de> + 2d7ba: 9d1e ldr r5, [sp, #120] ; 0x78 + 2d7bc: 9511 str r5, [sp, #68] ; 0x44 + 2d7be: f7ff ba4c b.w 2cc5a <__rtl_dtoa_r_v1_00+0x4de> + 2d7c2: f43f aa22 beq.w 2cc0a <__rtl_dtoa_r_v1_00+0x48e> + 2d7c6: f1c3 033c rsb r3, r3, #60 ; 0x3c + 2d7ca: f7ff ba17 b.w 2cbfc <__rtl_dtoa_r_v1_00+0x480> + 2d7ce: bf00 nop + +0002d7d0 <__rom_mallocr_init_v1_00>: + 2d7d0: f240 7080 movw r0, #1920 ; 0x780 + 2d7d4: f2c1 0000 movt r0, #4096 ; 0x1000 + 2d7d8: 4601 mov r1, r0 + 2d7da: 4603 mov r3, r0 + 2d7dc: b410 push {r4} + 2d7de: 2400 movs r4, #0 + 2d7e0: f500 727e add.w r2, r0, #1016 ; 0x3f8 + 2d7e4: 6004 str r4, [r0, #0] + 2d7e6: 6044 str r4, [r0, #4] + 2d7e8: 609b str r3, [r3, #8] + 2d7ea: 60db str r3, [r3, #12] + 2d7ec: 3308 adds r3, #8 + 2d7ee: 4293 cmp r3, r2 + 2d7f0: d1fa bne.n 2d7e8 <__rom_mallocr_init_v1_00+0x18> + 2d7f2: 2300 movs r3, #0 + 2d7f4: f44f 3000 mov.w r0, #131072 ; 0x20000 + 2d7f8: f04f 32ff mov.w r2, #4294967295 + 2d7fc: f8c1 0408 str.w r0, [r1, #1032] ; 0x408 + 2d800: f8c1 340c str.w r3, [r1, #1036] ; 0x40c + 2d804: f8c1 3414 str.w r3, [r1, #1044] ; 0x414 + 2d808: f8c1 3418 str.w r3, [r1, #1048] ; 0x418 + 2d80c: f8c1 341c str.w r3, [r1, #1052] ; 0x41c + 2d810: f8c1 3420 str.w r3, [r1, #1056] ; 0x420 + 2d814: f8c1 3424 str.w r3, [r1, #1060] ; 0x424 + 2d818: f8c1 3428 str.w r3, [r1, #1064] ; 0x428 + 2d81c: f8c1 342c str.w r3, [r1, #1068] ; 0x42c + 2d820: f8c1 3430 str.w r3, [r1, #1072] ; 0x430 + 2d824: f8c1 3434 str.w r3, [r1, #1076] ; 0x434 + 2d828: f8c1 3438 str.w r3, [r1, #1080] ; 0x438 + 2d82c: f8c1 343c str.w r3, [r1, #1084] ; 0x43c + 2d830: f8c1 3440 str.w r3, [r1, #1088] ; 0x440 + 2d834: f8c1 2410 str.w r2, [r1, #1040] ; 0x410 + 2d838: f85d 4b04 ldr.w r4, [sp], #4 + 2d83c: 4770 bx lr + 2d83e: bf00 nop + +0002d840 <__rtl_free_r_v1_00>: + 2d840: 2900 cmp r1, #0 + 2d842: f000 80c7 beq.w 2d9d4 <__rtl_free_r_v1_00+0x194> + 2d846: f240 7380 movw r3, #1920 ; 0x780 + 2d84a: f2c1 0300 movt r3, #4096 ; 0x1000 + 2d84e: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + 2d852: f851 6c04 ldr.w r6, [r1, #-4] + 2d856: f1a1 0408 sub.w r4, r1, #8 + 2d85a: f026 0201 bic.w r2, r6, #1 + 2d85e: 18a5 adds r5, r4, r2 + 2d860: 4680 mov r8, r0 + 2d862: 6898 ldr r0, [r3, #8] + 2d864: 686f ldr r7, [r5, #4] + 2d866: 42a8 cmp r0, r5 + 2d868: f027 0703 bic.w r7, r7, #3 + 2d86c: d072 beq.n 2d954 <__rtl_free_r_v1_00+0x114> + 2d86e: f016 0601 ands.w r6, r6, #1 + 2d872: 606f str r7, [r5, #4] + 2d874: bf18 it ne + 2d876: 2600 movne r6, #0 + 2d878: d10c bne.n 2d894 <__rtl_free_r_v1_00+0x54> + 2d87a: f851 0c08 ldr.w r0, [r1, #-8] + 2d87e: f103 0e08 add.w lr, r3, #8 + 2d882: 1a24 subs r4, r4, r0 + 2d884: 68a1 ldr r1, [r4, #8] + 2d886: 4402 add r2, r0 + 2d888: 4571 cmp r1, lr + 2d88a: bf17 itett ne + 2d88c: 68e0 ldrne r0, [r4, #12] + 2d88e: 2601 moveq r6, #1 + 2d890: 60c8 strne r0, [r1, #12] + 2d892: 6081 strne r1, [r0, #8] + 2d894: 19e9 adds r1, r5, r7 + 2d896: 6849 ldr r1, [r1, #4] + 2d898: 07c9 lsls r1, r1, #31 + 2d89a: d405 bmi.n 2d8a8 <__rtl_free_r_v1_00+0x68> + 2d89c: 443a add r2, r7 + 2d89e: b34e cbz r6, 2d8f4 <__rtl_free_r_v1_00+0xb4> + 2d8a0: 68a9 ldr r1, [r5, #8] + 2d8a2: 68e8 ldr r0, [r5, #12] + 2d8a4: 60c8 str r0, [r1, #12] + 2d8a6: 6081 str r1, [r0, #8] + 2d8a8: f042 0101 orr.w r1, r2, #1 + 2d8ac: 6061 str r1, [r4, #4] + 2d8ae: 50a2 str r2, [r4, r2] + 2d8b0: b9f6 cbnz r6, 2d8f0 <__rtl_free_r_v1_00+0xb0> + 2d8b2: f5b2 7f00 cmp.w r2, #512 ; 0x200 + 2d8b6: d33c bcc.n 2d932 <__rtl_free_r_v1_00+0xf2> + 2d8b8: 0a51 lsrs r1, r2, #9 + 2d8ba: 2904 cmp r1, #4 + 2d8bc: d82d bhi.n 2d91a <__rtl_free_r_v1_00+0xda> + 2d8be: 0995 lsrs r5, r2, #6 + 2d8c0: 3538 adds r5, #56 ; 0x38 + 2d8c2: 0068 lsls r0, r5, #1 + 2d8c4: f240 7180 movw r1, #1920 ; 0x780 + 2d8c8: eb03 0080 add.w r0, r3, r0, lsl #2 + 2d8cc: 6883 ldr r3, [r0, #8] + 2d8ce: f2c1 0100 movt r1, #4096 ; 0x1000 + 2d8d2: 4283 cmp r3, r0 + 2d8d4: d07f beq.n 2d9d6 <__rtl_free_r_v1_00+0x196> + 2d8d6: 6859 ldr r1, [r3, #4] + 2d8d8: f021 0103 bic.w r1, r1, #3 + 2d8dc: 428a cmp r2, r1 + 2d8de: d202 bcs.n 2d8e6 <__rtl_free_r_v1_00+0xa6> + 2d8e0: 689b ldr r3, [r3, #8] + 2d8e2: 4298 cmp r0, r3 + 2d8e4: d1f7 bne.n 2d8d6 <__rtl_free_r_v1_00+0x96> + 2d8e6: 68da ldr r2, [r3, #12] + 2d8e8: 60e2 str r2, [r4, #12] + 2d8ea: 60a3 str r3, [r4, #8] + 2d8ec: 6094 str r4, [r2, #8] + 2d8ee: 60dc str r4, [r3, #12] + 2d8f0: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 2d8f4: f240 7080 movw r0, #1920 ; 0x780 + 2d8f8: f2c1 0000 movt r0, #4096 ; 0x1000 + 2d8fc: 68a9 ldr r1, [r5, #8] + 2d8fe: f100 0708 add.w r7, r0, #8 + 2d902: 42b9 cmp r1, r7 + 2d904: d1cd bne.n 2d8a2 <__rtl_free_r_v1_00+0x62> + 2d906: f042 0301 orr.w r3, r2, #1 + 2d90a: 6144 str r4, [r0, #20] + 2d90c: 6104 str r4, [r0, #16] + 2d90e: 60e1 str r1, [r4, #12] + 2d910: 60a1 str r1, [r4, #8] + 2d912: 6063 str r3, [r4, #4] + 2d914: 50a2 str r2, [r4, r2] + 2d916: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 2d91a: 2914 cmp r1, #20 + 2d91c: bf9c itt ls + 2d91e: f101 055b addls.w r5, r1, #91 ; 0x5b + 2d922: 0068 lslls r0, r5, #1 + 2d924: d9ce bls.n 2d8c4 <__rtl_free_r_v1_00+0x84> + 2d926: 2954 cmp r1, #84 ; 0x54 + 2d928: d85d bhi.n 2d9e6 <__rtl_free_r_v1_00+0x1a6> + 2d92a: 0b15 lsrs r5, r2, #12 + 2d92c: 356e adds r5, #110 ; 0x6e + 2d92e: 0068 lsls r0, r5, #1 + 2d930: e7c8 b.n 2d8c4 <__rtl_free_r_v1_00+0x84> + 2d932: 08d2 lsrs r2, r2, #3 + 2d934: eb03 01c2 add.w r1, r3, r2, lsl #3 + 2d938: 2001 movs r0, #1 + 2d93a: 685d ldr r5, [r3, #4] + 2d93c: 1092 asrs r2, r2, #2 + 2d93e: fa00 f202 lsl.w r2, r0, r2 + 2d942: 6888 ldr r0, [r1, #8] + 2d944: 4315 orrs r5, r2 + 2d946: 60a0 str r0, [r4, #8] + 2d948: 60e1 str r1, [r4, #12] + 2d94a: 605d str r5, [r3, #4] + 2d94c: 608c str r4, [r1, #8] + 2d94e: 60c4 str r4, [r0, #12] + 2d950: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 2d954: 07f0 lsls r0, r6, #31 + 2d956: 443a add r2, r7 + 2d958: d407 bmi.n 2d96a <__rtl_free_r_v1_00+0x12a> + 2d95a: f851 5c08 ldr.w r5, [r1, #-8] + 2d95e: 1b64 subs r4, r4, r5 + 2d960: 68e1 ldr r1, [r4, #12] + 2d962: 68a0 ldr r0, [r4, #8] + 2d964: 442a add r2, r5 + 2d966: 60c1 str r1, [r0, #12] + 2d968: 6088 str r0, [r1, #8] + 2d96a: f240 7580 movw r5, #1920 ; 0x780 + 2d96e: f8d3 0408 ldr.w r0, [r3, #1032] ; 0x408 + 2d972: f042 0101 orr.w r1, r2, #1 + 2d976: 4282 cmp r2, r0 + 2d978: 6061 str r1, [r4, #4] + 2d97a: f2c1 0500 movt r5, #4096 ; 0x1000 + 2d97e: 609c str r4, [r3, #8] + 2d980: d3b6 bcc.n 2d8f0 <__rtl_free_r_v1_00+0xb0> + 2d982: f8d5 340c ldr.w r3, [r5, #1036] ; 0x40c + 2d986: f021 0403 bic.w r4, r1, #3 + 2d98a: 1ae3 subs r3, r4, r3 + 2d98c: f603 76ef addw r6, r3, #4079 ; 0xfef + 2d990: 0b36 lsrs r6, r6, #12 + 2d992: 3e01 subs r6, #1 + 2d994: 0336 lsls r6, r6, #12 + 2d996: f5b6 5f80 cmp.w r6, #4096 ; 0x1000 + 2d99a: dba9 blt.n 2d8f0 <__rtl_free_r_v1_00+0xb0> + 2d99c: f64e 4741 movw r7, #60481 ; 0xec41 + 2d9a0: 4640 mov r0, r8 + 2d9a2: f2c0 0702 movt r7, #2 + 2d9a6: 2100 movs r1, #0 + 2d9a8: 47b8 blx r7 + 2d9aa: 68ab ldr r3, [r5, #8] + 2d9ac: 4423 add r3, r4 + 2d9ae: 4298 cmp r0, r3 + 2d9b0: d19e bne.n 2d8f0 <__rtl_free_r_v1_00+0xb0> + 2d9b2: 4640 mov r0, r8 + 2d9b4: 4271 negs r1, r6 + 2d9b6: 47b8 blx r7 + 2d9b8: 3001 adds r0, #1 + 2d9ba: d026 beq.n 2da0a <__rtl_free_r_v1_00+0x1ca> + 2d9bc: f8d5 241c ldr.w r2, [r5, #1052] ; 0x41c + 2d9c0: 1ba1 subs r1, r4, r6 + 2d9c2: 68ab ldr r3, [r5, #8] + 2d9c4: f041 0101 orr.w r1, r1, #1 + 2d9c8: 1b92 subs r2, r2, r6 + 2d9ca: 6059 str r1, [r3, #4] + 2d9cc: f8c5 241c str.w r2, [r5, #1052] ; 0x41c + 2d9d0: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 2d9d4: 4770 bx lr + 2d9d6: 684a ldr r2, [r1, #4] + 2d9d8: 10ad asrs r5, r5, #2 + 2d9da: 2001 movs r0, #1 + 2d9dc: 40a8 lsls r0, r5 + 2d9de: 4302 orrs r2, r0 + 2d9e0: 604a str r2, [r1, #4] + 2d9e2: 461a mov r2, r3 + 2d9e4: e780 b.n 2d8e8 <__rtl_free_r_v1_00+0xa8> + 2d9e6: f5b1 7faa cmp.w r1, #340 ; 0x154 + 2d9ea: d803 bhi.n 2d9f4 <__rtl_free_r_v1_00+0x1b4> + 2d9ec: 0bd5 lsrs r5, r2, #15 + 2d9ee: 3577 adds r5, #119 ; 0x77 + 2d9f0: 0068 lsls r0, r5, #1 + 2d9f2: e767 b.n 2d8c4 <__rtl_free_r_v1_00+0x84> + 2d9f4: f240 5054 movw r0, #1364 ; 0x554 + 2d9f8: 4281 cmp r1, r0 + 2d9fa: bf9d ittte ls + 2d9fc: 0c95 lsrls r5, r2, #18 + 2d9fe: 357c addls r5, #124 ; 0x7c + 2da00: 0068 lslls r0, r5, #1 + 2da02: 20fc movhi r0, #252 ; 0xfc + 2da04: bf88 it hi + 2da06: 257e movhi r5, #126 ; 0x7e + 2da08: e75c b.n 2d8c4 <__rtl_free_r_v1_00+0x84> + 2da0a: 4640 mov r0, r8 + 2da0c: 2100 movs r1, #0 + 2da0e: 47b8 blx r7 + 2da10: 68ab ldr r3, [r5, #8] + 2da12: 1ac2 subs r2, r0, r3 + 2da14: 2a0f cmp r2, #15 + 2da16: f77f af6b ble.w 2d8f0 <__rtl_free_r_v1_00+0xb0> + 2da1a: f8d5 1410 ldr.w r1, [r5, #1040] ; 0x410 + 2da1e: f042 0201 orr.w r2, r2, #1 + 2da22: 1a41 subs r1, r0, r1 + 2da24: 605a str r2, [r3, #4] + 2da26: f8c5 141c str.w r1, [r5, #1052] ; 0x41c + 2da2a: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 2da2e: bf00 nop + +0002da30 <__rtl_malloc_r_v1_00>: + 2da30: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 2da34: f101 040b add.w r4, r1, #11 + 2da38: 2c16 cmp r4, #22 + 2da3a: b083 sub sp, #12 + 2da3c: 4607 mov r7, r0 + 2da3e: d820 bhi.n 2da82 <__rtl_malloc_r_v1_00+0x52> + 2da40: 2910 cmp r1, #16 + 2da42: f200 80e4 bhi.w 2dc0e <__rtl_malloc_r_v1_00+0x1de> + 2da46: 2410 movs r4, #16 + 2da48: f240 7680 movw r6, #1920 ; 0x780 + 2da4c: f2c1 0600 movt r6, #4096 ; 0x1000 + 2da50: ea4f 0ed4 mov.w lr, r4, lsr #3 + 2da54: eb06 02ce add.w r2, r6, lr, lsl #3 + 2da58: 68d3 ldr r3, [r2, #12] + 2da5a: 4293 cmp r3, r2 + 2da5c: f000 8140 beq.w 2dce0 <__rtl_malloc_r_v1_00+0x2b0> + 2da60: 685a ldr r2, [r3, #4] + 2da62: 68d9 ldr r1, [r3, #12] + 2da64: f022 0203 bic.w r2, r2, #3 + 2da68: 441a add r2, r3 + 2da6a: 6850 ldr r0, [r2, #4] + 2da6c: 689c ldr r4, [r3, #8] + 2da6e: f040 0501 orr.w r5, r0, #1 + 2da72: 60e1 str r1, [r4, #12] + 2da74: f103 0008 add.w r0, r3, #8 + 2da78: 608c str r4, [r1, #8] + 2da7a: 6055 str r5, [r2, #4] + 2da7c: b003 add sp, #12 + 2da7e: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 2da82: f024 0407 bic.w r4, r4, #7 + 2da86: 42a1 cmp r1, r4 + 2da88: bf94 ite ls + 2da8a: 2100 movls r1, #0 + 2da8c: 2101 movhi r1, #1 + 2da8e: ea51 71d4 orrs.w r1, r1, r4, lsr #31 + 2da92: f040 80bc bne.w 2dc0e <__rtl_malloc_r_v1_00+0x1de> + 2da96: f5b4 7ffc cmp.w r4, #504 ; 0x1f8 + 2da9a: d3d5 bcc.n 2da48 <__rtl_malloc_r_v1_00+0x18> + 2da9c: ea5f 2e54 movs.w lr, r4, lsr #9 + 2daa0: bf04 itt eq + 2daa2: 257e moveq r5, #126 ; 0x7e + 2daa4: f04f 0e3f moveq.w lr, #63 ; 0x3f + 2daa8: d018 beq.n 2dadc <__rtl_malloc_r_v1_00+0xac> + 2daaa: f1be 0f04 cmp.w lr, #4 + 2daae: d94e bls.n 2db4e <__rtl_malloc_r_v1_00+0x11e> + 2dab0: f1be 0f14 cmp.w lr, #20 + 2dab4: bf9c itt ls + 2dab6: f10e 0e5b addls.w lr, lr, #91 ; 0x5b + 2daba: ea4f 054e movls.w r5, lr, lsl #1 + 2dabe: d90d bls.n 2dadc <__rtl_malloc_r_v1_00+0xac> + 2dac0: f1be 0f54 cmp.w lr, #84 ; 0x54 + 2dac4: f240 8135 bls.w 2dd32 <__rtl_malloc_r_v1_00+0x302> + 2dac8: f5be 7faa cmp.w lr, #340 ; 0x154 + 2dacc: f200 81e6 bhi.w 2de9c <__rtl_malloc_r_v1_00+0x46c> + 2dad0: ea4f 3ed4 mov.w lr, r4, lsr #15 + 2dad4: f10e 0e77 add.w lr, lr, #119 ; 0x77 + 2dad8: ea4f 054e mov.w r5, lr, lsl #1 + 2dadc: f240 7680 movw r6, #1920 ; 0x780 + 2dae0: f2c1 0600 movt r6, #4096 ; 0x1000 + 2dae4: eb06 0585 add.w r5, r6, r5, lsl #2 + 2dae8: 68eb ldr r3, [r5, #12] + 2daea: 429d cmp r5, r3 + 2daec: d106 bne.n 2dafc <__rtl_malloc_r_v1_00+0xcc> + 2daee: e00d b.n 2db0c <__rtl_malloc_r_v1_00+0xdc> + 2daf0: 2a00 cmp r2, #0 + 2daf2: f280 8092 bge.w 2dc1a <__rtl_malloc_r_v1_00+0x1ea> + 2daf6: 68db ldr r3, [r3, #12] + 2daf8: 429d cmp r5, r3 + 2dafa: d007 beq.n 2db0c <__rtl_malloc_r_v1_00+0xdc> + 2dafc: 6859 ldr r1, [r3, #4] + 2dafe: f021 0103 bic.w r1, r1, #3 + 2db02: 1b0a subs r2, r1, r4 + 2db04: 2a0f cmp r2, #15 + 2db06: ddf3 ble.n 2daf0 <__rtl_malloc_r_v1_00+0xc0> + 2db08: f10e 3eff add.w lr, lr, #4294967295 + 2db0c: f10e 0e01 add.w lr, lr, #1 + 2db10: f240 7280 movw r2, #1920 ; 0x780 + 2db14: f2c1 0200 movt r2, #4096 ; 0x1000 + 2db18: 6930 ldr r0, [r6, #16] + 2db1a: f102 0508 add.w r5, r2, #8 + 2db1e: 42a8 cmp r0, r5 + 2db20: bf08 it eq + 2db22: 6852 ldreq r2, [r2, #4] + 2db24: d03f beq.n 2dba6 <__rtl_malloc_r_v1_00+0x176> + 2db26: 6841 ldr r1, [r0, #4] + 2db28: f021 0103 bic.w r1, r1, #3 + 2db2c: 1b0b subs r3, r1, r4 + 2db2e: 2b0f cmp r3, #15 + 2db30: f300 8081 bgt.w 2dc36 <__rtl_malloc_r_v1_00+0x206> + 2db34: 2b00 cmp r3, #0 + 2db36: 6155 str r5, [r2, #20] + 2db38: 6115 str r5, [r2, #16] + 2db3a: db0f blt.n 2db5c <__rtl_malloc_r_v1_00+0x12c> + 2db3c: 4401 add r1, r0 + 2db3e: 684b ldr r3, [r1, #4] + 2db40: 3008 adds r0, #8 + 2db42: f043 0301 orr.w r3, r3, #1 + 2db46: 604b str r3, [r1, #4] + 2db48: b003 add sp, #12 + 2db4a: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 2db4e: ea4f 1e94 mov.w lr, r4, lsr #6 + 2db52: f10e 0e38 add.w lr, lr, #56 ; 0x38 + 2db56: ea4f 054e mov.w r5, lr, lsl #1 + 2db5a: e7bf b.n 2dadc <__rtl_malloc_r_v1_00+0xac> + 2db5c: f5b1 7f00 cmp.w r1, #512 ; 0x200 + 2db60: f0c0 80c8 bcc.w 2dcf4 <__rtl_malloc_r_v1_00+0x2c4> + 2db64: 0a4b lsrs r3, r1, #9 + 2db66: 2b04 cmp r3, #4 + 2db68: f200 81a7 bhi.w 2deba <__rtl_malloc_r_v1_00+0x48a> + 2db6c: 098a lsrs r2, r1, #6 + 2db6e: 3238 adds r2, #56 ; 0x38 + 2db70: ea4f 0c42 mov.w ip, r2, lsl #1 + 2db74: f240 7880 movw r8, #1920 ; 0x780 + 2db78: eb06 0c8c add.w ip, r6, ip, lsl #2 + 2db7c: f8dc 3008 ldr.w r3, [ip, #8] + 2db80: f2c1 0800 movt r8, #4096 ; 0x1000 + 2db84: 4563 cmp r3, ip + 2db86: f000 81ac beq.w 2dee2 <__rtl_malloc_r_v1_00+0x4b2> + 2db8a: 685a ldr r2, [r3, #4] + 2db8c: f022 0203 bic.w r2, r2, #3 + 2db90: 4291 cmp r1, r2 + 2db92: d202 bcs.n 2db9a <__rtl_malloc_r_v1_00+0x16a> + 2db94: 689b ldr r3, [r3, #8] + 2db96: 459c cmp ip, r3 + 2db98: d1f7 bne.n 2db8a <__rtl_malloc_r_v1_00+0x15a> + 2db9a: 68d9 ldr r1, [r3, #12] + 2db9c: 6872 ldr r2, [r6, #4] + 2db9e: 60c1 str r1, [r0, #12] + 2dba0: 6083 str r3, [r0, #8] + 2dba2: 6088 str r0, [r1, #8] + 2dba4: 60d8 str r0, [r3, #12] + 2dba6: ea4f 03ae mov.w r3, lr, asr #2 + 2dbaa: 2001 movs r0, #1 + 2dbac: 4098 lsls r0, r3 + 2dbae: 4290 cmp r0, r2 + 2dbb0: d851 bhi.n 2dc56 <__rtl_malloc_r_v1_00+0x226> + 2dbb2: 4202 tst r2, r0 + 2dbb4: f000 80b5 beq.w 2dd22 <__rtl_malloc_r_v1_00+0x2f2> + 2dbb8: eb06 08ce add.w r8, r6, lr, lsl #3 + 2dbbc: 46c4 mov ip, r8 + 2dbbe: 46f1 mov r9, lr + 2dbc0: f8dc 200c ldr.w r2, [ip, #12] + 2dbc4: 4594 cmp ip, r2 + 2dbc6: d107 bne.n 2dbd8 <__rtl_malloc_r_v1_00+0x1a8> + 2dbc8: e0ba b.n 2dd40 <__rtl_malloc_r_v1_00+0x310> + 2dbca: 2900 cmp r1, #0 + 2dbcc: f280 80e2 bge.w 2dd94 <__rtl_malloc_r_v1_00+0x364> + 2dbd0: 68d2 ldr r2, [r2, #12] + 2dbd2: 4594 cmp ip, r2 + 2dbd4: f000 80b4 beq.w 2dd40 <__rtl_malloc_r_v1_00+0x310> + 2dbd8: 6853 ldr r3, [r2, #4] + 2dbda: f023 0303 bic.w r3, r3, #3 + 2dbde: 1b19 subs r1, r3, r4 + 2dbe0: 290f cmp r1, #15 + 2dbe2: ddf2 ble.n 2dbca <__rtl_malloc_r_v1_00+0x19a> + 2dbe4: 4610 mov r0, r2 + 2dbe6: 68d3 ldr r3, [r2, #12] + 2dbe8: f850 7f08 ldr.w r7, [r0, #8]! + 2dbec: f044 0c01 orr.w ip, r4, #1 + 2dbf0: f041 0e01 orr.w lr, r1, #1 + 2dbf4: 4414 add r4, r2 + 2dbf6: f8c2 c004 str.w ip, [r2, #4] + 2dbfa: 60fb str r3, [r7, #12] + 2dbfc: 609f str r7, [r3, #8] + 2dbfe: 6174 str r4, [r6, #20] + 2dc00: 6134 str r4, [r6, #16] + 2dc02: 60e5 str r5, [r4, #12] + 2dc04: 60a5 str r5, [r4, #8] + 2dc06: f8c4 e004 str.w lr, [r4, #4] + 2dc0a: 5061 str r1, [r4, r1] + 2dc0c: e736 b.n 2da7c <__rtl_malloc_r_v1_00+0x4c> + 2dc0e: 230c movs r3, #12 + 2dc10: 2000 movs r0, #0 + 2dc12: 603b str r3, [r7, #0] + 2dc14: b003 add sp, #12 + 2dc16: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 2dc1a: 4419 add r1, r3 + 2dc1c: 6848 ldr r0, [r1, #4] + 2dc1e: 68da ldr r2, [r3, #12] + 2dc20: 689c ldr r4, [r3, #8] + 2dc22: f040 0501 orr.w r5, r0, #1 + 2dc26: f103 0008 add.w r0, r3, #8 + 2dc2a: 60e2 str r2, [r4, #12] + 2dc2c: 6094 str r4, [r2, #8] + 2dc2e: 604d str r5, [r1, #4] + 2dc30: b003 add sp, #12 + 2dc32: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 2dc36: f044 0601 orr.w r6, r4, #1 + 2dc3a: 6046 str r6, [r0, #4] + 2dc3c: 4404 add r4, r0 + 2dc3e: f043 0101 orr.w r1, r3, #1 + 2dc42: 3008 adds r0, #8 + 2dc44: 6154 str r4, [r2, #20] + 2dc46: 6114 str r4, [r2, #16] + 2dc48: 60e5 str r5, [r4, #12] + 2dc4a: 60a5 str r5, [r4, #8] + 2dc4c: 6061 str r1, [r4, #4] + 2dc4e: 50e3 str r3, [r4, r3] + 2dc50: b003 add sp, #12 + 2dc52: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 2dc56: 68b5 ldr r5, [r6, #8] + 2dc58: 686b ldr r3, [r5, #4] + 2dc5a: f023 0903 bic.w r9, r3, #3 + 2dc5e: 454c cmp r4, r9 + 2dc60: d803 bhi.n 2dc6a <__rtl_malloc_r_v1_00+0x23a> + 2dc62: ebc4 0309 rsb r3, r4, r9 + 2dc66: 2b0f cmp r3, #15 + 2dc68: dc2f bgt.n 2dcca <__rtl_malloc_r_v1_00+0x29a> + 2dc6a: f64e 4a41 movw sl, #60481 ; 0xec41 + 2dc6e: f8d6 340c ldr.w r3, [r6, #1036] ; 0x40c + 2dc72: f8d6 1410 ldr.w r1, [r6, #1040] ; 0x410 + 2dc76: 4423 add r3, r4 + 2dc78: 3101 adds r1, #1 + 2dc7a: bf1e ittt ne + 2dc7c: f503 5380 addne.w r3, r3, #4096 ; 0x1000 + 2dc80: 330f addne r3, #15 + 2dc82: f423 637f bicne.w r3, r3, #4080 ; 0xff0 + 2dc86: eb05 0209 add.w r2, r5, r9 + 2dc8a: bf0c ite eq + 2dc8c: f103 0b10 addeq.w fp, r3, #16 + 2dc90: f023 0b0f bicne.w fp, r3, #15 + 2dc94: 9201 str r2, [sp, #4] + 2dc96: 4638 mov r0, r7 + 2dc98: f2c0 0a02 movt sl, #2 + 2dc9c: 4659 mov r1, fp + 2dc9e: 47d0 blx sl + 2dca0: f1b0 3fff cmp.w r0, #4294967295 + 2dca4: 4680 mov r8, r0 + 2dca6: 9a01 ldr r2, [sp, #4] + 2dca8: d003 beq.n 2dcb2 <__rtl_malloc_r_v1_00+0x282> + 2dcaa: 4282 cmp r2, r0 + 2dcac: d97e bls.n 2ddac <__rtl_malloc_r_v1_00+0x37c> + 2dcae: 42b5 cmp r5, r6 + 2dcb0: d07c beq.n 2ddac <__rtl_malloc_r_v1_00+0x37c> + 2dcb2: 68b5 ldr r5, [r6, #8] + 2dcb4: 686a ldr r2, [r5, #4] + 2dcb6: f022 0203 bic.w r2, r2, #3 + 2dcba: 4294 cmp r4, r2 + 2dcbc: eba2 0304 sub.w r3, r2, r4 + 2dcc0: f200 811b bhi.w 2defa <__rtl_malloc_r_v1_00+0x4ca> + 2dcc4: 2b0f cmp r3, #15 + 2dcc6: f340 8118 ble.w 2defa <__rtl_malloc_r_v1_00+0x4ca> + 2dcca: f044 0201 orr.w r2, r4, #1 + 2dcce: f043 0301 orr.w r3, r3, #1 + 2dcd2: 442c add r4, r5 + 2dcd4: 606a str r2, [r5, #4] + 2dcd6: f105 0008 add.w r0, r5, #8 + 2dcda: 60b4 str r4, [r6, #8] + 2dcdc: 6063 str r3, [r4, #4] + 2dcde: e6cd b.n 2da7c <__rtl_malloc_r_v1_00+0x4c> + 2dce0: f103 0208 add.w r2, r3, #8 + 2dce4: 695b ldr r3, [r3, #20] + 2dce6: 429a cmp r2, r3 + 2dce8: bf08 it eq + 2dcea: f10e 0e02 addeq.w lr, lr, #2 + 2dcee: f43f af0f beq.w 2db10 <__rtl_malloc_r_v1_00+0xe0> + 2dcf2: e6b5 b.n 2da60 <__rtl_malloc_r_v1_00+0x30> + 2dcf4: 08cb lsrs r3, r1, #3 + 2dcf6: eb02 01c3 add.w r1, r2, r3, lsl #3 + 2dcfa: ea4f 0ca3 mov.w ip, r3, asr #2 + 2dcfe: f04f 0801 mov.w r8, #1 + 2dd02: 6853 ldr r3, [r2, #4] + 2dd04: fa08 f80c lsl.w r8, r8, ip + 2dd08: f8d1 c008 ldr.w ip, [r1, #8] + 2dd0c: ea48 0303 orr.w r3, r8, r3 + 2dd10: f8c0 c008 str.w ip, [r0, #8] + 2dd14: 60c1 str r1, [r0, #12] + 2dd16: 6053 str r3, [r2, #4] + 2dd18: 6088 str r0, [r1, #8] + 2dd1a: 461a mov r2, r3 + 2dd1c: f8cc 000c str.w r0, [ip, #12] + 2dd20: e741 b.n 2dba6 <__rtl_malloc_r_v1_00+0x176> + 2dd22: f02e 0e03 bic.w lr, lr, #3 + 2dd26: 0040 lsls r0, r0, #1 + 2dd28: 4202 tst r2, r0 + 2dd2a: f10e 0e04 add.w lr, lr, #4 + 2dd2e: d0fa beq.n 2dd26 <__rtl_malloc_r_v1_00+0x2f6> + 2dd30: e742 b.n 2dbb8 <__rtl_malloc_r_v1_00+0x188> + 2dd32: ea4f 3e14 mov.w lr, r4, lsr #12 + 2dd36: f10e 0e6e add.w lr, lr, #110 ; 0x6e + 2dd3a: ea4f 054e mov.w r5, lr, lsl #1 + 2dd3e: e6cd b.n 2dadc <__rtl_malloc_r_v1_00+0xac> + 2dd40: f109 0901 add.w r9, r9, #1 + 2dd44: f019 0f03 tst.w r9, #3 + 2dd48: f10c 0c08 add.w ip, ip, #8 + 2dd4c: f47f af38 bne.w 2dbc0 <__rtl_malloc_r_v1_00+0x190> + 2dd50: e004 b.n 2dd5c <__rtl_malloc_r_v1_00+0x32c> + 2dd52: f8d8 8000 ldr.w r8, [r8] + 2dd56: 4598 cmp r8, r3 + 2dd58: f040 80f9 bne.w 2df4e <__rtl_malloc_r_v1_00+0x51e> + 2dd5c: f01e 0f03 tst.w lr, #3 + 2dd60: f1a8 0308 sub.w r3, r8, #8 + 2dd64: f10e 3eff add.w lr, lr, #4294967295 + 2dd68: d1f3 bne.n 2dd52 <__rtl_malloc_r_v1_00+0x322> + 2dd6a: 6873 ldr r3, [r6, #4] + 2dd6c: ea23 0300 bic.w r3, r3, r0 + 2dd70: 6073 str r3, [r6, #4] + 2dd72: 0040 lsls r0, r0, #1 + 2dd74: 4298 cmp r0, r3 + 2dd76: f63f af6e bhi.w 2dc56 <__rtl_malloc_r_v1_00+0x226> + 2dd7a: 2800 cmp r0, #0 + 2dd7c: f43f af6b beq.w 2dc56 <__rtl_malloc_r_v1_00+0x226> + 2dd80: 4203 tst r3, r0 + 2dd82: 46ce mov lr, r9 + 2dd84: f47f af18 bne.w 2dbb8 <__rtl_malloc_r_v1_00+0x188> + 2dd88: 0040 lsls r0, r0, #1 + 2dd8a: 4203 tst r3, r0 + 2dd8c: f10e 0e04 add.w lr, lr, #4 + 2dd90: d0fa beq.n 2dd88 <__rtl_malloc_r_v1_00+0x358> + 2dd92: e711 b.n 2dbb8 <__rtl_malloc_r_v1_00+0x188> + 2dd94: 4610 mov r0, r2 + 2dd96: 4413 add r3, r2 + 2dd98: 685c ldr r4, [r3, #4] + 2dd9a: 68d2 ldr r2, [r2, #12] + 2dd9c: f850 1f08 ldr.w r1, [r0, #8]! + 2dda0: f044 0401 orr.w r4, r4, #1 + 2dda4: 605c str r4, [r3, #4] + 2dda6: 60ca str r2, [r1, #12] + 2dda8: 6091 str r1, [r2, #8] + 2ddaa: e667 b.n 2da7c <__rtl_malloc_r_v1_00+0x4c> + 2ddac: f240 7180 movw r1, #1920 ; 0x780 + 2ddb0: f8d6 341c ldr.w r3, [r6, #1052] ; 0x41c + 2ddb4: 4542 cmp r2, r8 + 2ddb6: 445b add r3, fp + 2ddb8: f2c1 0100 movt r1, #4096 ; 0x1000 + 2ddbc: f8c6 341c str.w r3, [r6, #1052] ; 0x41c + 2ddc0: f000 809d beq.w 2defe <__rtl_malloc_r_v1_00+0x4ce> + 2ddc4: f240 7080 movw r0, #1920 ; 0x780 + 2ddc8: f2c1 0000 movt r0, #4096 ; 0x1000 + 2ddcc: f8d6 1410 ldr.w r1, [r6, #1040] ; 0x410 + 2ddd0: 3101 adds r1, #1 + 2ddd2: bf1b ittet ne + 2ddd4: ebc2 0208 rsbne r2, r2, r8 + 2ddd8: 189b addne r3, r3, r2 + 2ddda: f8c0 8410 streq.w r8, [r0, #1040] ; 0x410 + 2ddde: f8c0 341c strne.w r3, [r0, #1052] ; 0x41c + 2dde2: f018 0307 ands.w r3, r8, #7 + 2dde6: bf1f itttt ne + 2dde8: f1c3 0208 rsbne r2, r3, #8 + 2ddec: 4490 addne r8, r2 + 2ddee: f5c3 5380 rsbne r3, r3, #4096 ; 0x1000 + 2ddf2: f103 0208 addne.w r2, r3, #8 + 2ddf6: eb08 030b add.w r3, r8, fp + 2ddfa: bf08 it eq + 2ddfc: f44f 5280 moveq.w r2, #4096 ; 0x1000 + 2de00: f3c3 030b ubfx r3, r3, #0, #12 + 2de04: ebc3 0b02 rsb fp, r3, r2 + 2de08: 4659 mov r1, fp + 2de0a: 4638 mov r0, r7 + 2de0c: 47d0 blx sl + 2de0e: f240 7a80 movw sl, #1920 ; 0x780 + 2de12: 1c43 adds r3, r0, #1 + 2de14: bf18 it ne + 2de16: ebc8 0200 rsbne r2, r8, r0 + 2de1a: f8d6 341c ldr.w r3, [r6, #1052] ; 0x41c + 2de1e: bf15 itete ne + 2de20: 445a addne r2, fp + 2de22: f04f 0b00 moveq.w fp, #0 + 2de26: f042 0201 orrne.w r2, r2, #1 + 2de2a: 2201 moveq r2, #1 + 2de2c: 445b add r3, fp + 2de2e: 42b5 cmp r5, r6 + 2de30: f8c6 8008 str.w r8, [r6, #8] + 2de34: f8c6 341c str.w r3, [r6, #1052] ; 0x41c + 2de38: f8c8 2004 str.w r2, [r8, #4] + 2de3c: f2c1 0a00 movt sl, #4096 ; 0x1000 + 2de40: d013 beq.n 2de6a <__rtl_malloc_r_v1_00+0x43a> + 2de42: f1b9 0f0f cmp.w r9, #15 + 2de46: d947 bls.n 2ded8 <__rtl_malloc_r_v1_00+0x4a8> + 2de48: 686a ldr r2, [r5, #4] + 2de4a: f1a9 010c sub.w r1, r9, #12 + 2de4e: f021 0107 bic.w r1, r1, #7 + 2de52: f002 0201 and.w r2, r2, #1 + 2de56: ea41 0e02 orr.w lr, r1, r2 + 2de5a: 2005 movs r0, #5 + 2de5c: 186a adds r2, r5, r1 + 2de5e: 290f cmp r1, #15 + 2de60: f8c5 e004 str.w lr, [r5, #4] + 2de64: 6050 str r0, [r2, #4] + 2de66: 6090 str r0, [r2, #8] + 2de68: d854 bhi.n 2df14 <__rtl_malloc_r_v1_00+0x4e4> + 2de6a: f240 7280 movw r2, #1920 ; 0x780 + 2de6e: f2c1 0200 movt r2, #4096 ; 0x1000 + 2de72: f8d6 1414 ldr.w r1, [r6, #1044] ; 0x414 + 2de76: 428b cmp r3, r1 + 2de78: bf88 it hi + 2de7a: f8c2 3414 strhi.w r3, [r2, #1044] ; 0x414 + 2de7e: f240 7280 movw r2, #1920 ; 0x780 + 2de82: f2c1 0200 movt r2, #4096 ; 0x1000 + 2de86: f8d6 1418 ldr.w r1, [r6, #1048] ; 0x418 + 2de8a: 6895 ldr r5, [r2, #8] + 2de8c: 428b cmp r3, r1 + 2de8e: bf88 it hi + 2de90: f8c2 3418 strhi.w r3, [r2, #1048] ; 0x418 + 2de94: 686a ldr r2, [r5, #4] + 2de96: f022 0203 bic.w r2, r2, #3 + 2de9a: e70e b.n 2dcba <__rtl_malloc_r_v1_00+0x28a> + 2de9c: f240 5354 movw r3, #1364 ; 0x554 + 2dea0: 459e cmp lr, r3 + 2dea2: bf9d ittte ls + 2dea4: ea4f 4e94 movls.w lr, r4, lsr #18 + 2dea8: f10e 0e7c addls.w lr, lr, #124 ; 0x7c + 2deac: ea4f 054e movls.w r5, lr, lsl #1 + 2deb0: 25fc movhi r5, #252 ; 0xfc + 2deb2: bf88 it hi + 2deb4: f04f 0e7e movhi.w lr, #126 ; 0x7e + 2deb8: e610 b.n 2dadc <__rtl_malloc_r_v1_00+0xac> + 2deba: 2b14 cmp r3, #20 + 2debc: bf9c itt ls + 2debe: f103 025b addls.w r2, r3, #91 ; 0x5b + 2dec2: ea4f 0c42 movls.w ip, r2, lsl #1 + 2dec6: f67f ae55 bls.w 2db74 <__rtl_malloc_r_v1_00+0x144> + 2deca: 2b54 cmp r3, #84 ; 0x54 + 2decc: d82a bhi.n 2df24 <__rtl_malloc_r_v1_00+0x4f4> + 2dece: 0b0a lsrs r2, r1, #12 + 2ded0: 326e adds r2, #110 ; 0x6e + 2ded2: ea4f 0c42 mov.w ip, r2, lsl #1 + 2ded6: e64d b.n 2db74 <__rtl_malloc_r_v1_00+0x144> + 2ded8: 2301 movs r3, #1 + 2deda: f8c8 3004 str.w r3, [r8, #4] + 2dede: 2000 movs r0, #0 + 2dee0: e5cc b.n 2da7c <__rtl_malloc_r_v1_00+0x4c> + 2dee2: 1091 asrs r1, r2, #2 + 2dee4: f04f 0c01 mov.w ip, #1 + 2dee8: f8d8 2004 ldr.w r2, [r8, #4] + 2deec: fa0c f101 lsl.w r1, ip, r1 + 2def0: 430a orrs r2, r1 + 2def2: f8c8 2004 str.w r2, [r8, #4] + 2def6: 4619 mov r1, r3 + 2def8: e651 b.n 2db9e <__rtl_malloc_r_v1_00+0x16e> + 2defa: 2000 movs r0, #0 + 2defc: e5be b.n 2da7c <__rtl_malloc_r_v1_00+0x4c> + 2defe: f3c2 000b ubfx r0, r2, #0, #12 + 2df02: 2800 cmp r0, #0 + 2df04: f47f af5e bne.w 2ddc4 <__rtl_malloc_r_v1_00+0x394> + 2df08: 688a ldr r2, [r1, #8] + 2df0a: 44d9 add r9, fp + 2df0c: f049 0101 orr.w r1, r9, #1 + 2df10: 6051 str r1, [r2, #4] + 2df12: e7aa b.n 2de6a <__rtl_malloc_r_v1_00+0x43a> + 2df14: 4638 mov r0, r7 + 2df16: f105 0108 add.w r1, r5, #8 + 2df1a: f7ff fc91 bl 2d840 <__rtl_free_r_v1_00> + 2df1e: f8da 341c ldr.w r3, [sl, #1052] ; 0x41c + 2df22: e7a2 b.n 2de6a <__rtl_malloc_r_v1_00+0x43a> + 2df24: f5b3 7faa cmp.w r3, #340 ; 0x154 + 2df28: d804 bhi.n 2df34 <__rtl_malloc_r_v1_00+0x504> + 2df2a: 0bca lsrs r2, r1, #15 + 2df2c: 3277 adds r2, #119 ; 0x77 + 2df2e: ea4f 0c42 mov.w ip, r2, lsl #1 + 2df32: e61f b.n 2db74 <__rtl_malloc_r_v1_00+0x144> + 2df34: f240 5254 movw r2, #1364 ; 0x554 + 2df38: 4293 cmp r3, r2 + 2df3a: bf9d ittte ls + 2df3c: 0c8a lsrls r2, r1, #18 + 2df3e: 327c addls r2, #124 ; 0x7c + 2df40: ea4f 0c42 movls.w ip, r2, lsl #1 + 2df44: f04f 0cfc movhi.w ip, #252 ; 0xfc + 2df48: bf88 it hi + 2df4a: 227e movhi r2, #126 ; 0x7e + 2df4c: e612 b.n 2db74 <__rtl_malloc_r_v1_00+0x144> + 2df4e: 6873 ldr r3, [r6, #4] + 2df50: e70f b.n 2dd72 <__rtl_malloc_r_v1_00+0x342> + 2df52: bf00 nop + +0002df54 <__rtl_realloc_r_v1_00>: + 2df54: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} + 2df58: 460c mov r4, r1 + 2df5a: 2900 cmp r1, #0 + 2df5c: f000 816f beq.w 2e23e <__rtl_realloc_r_v1_00+0x2ea> + 2df60: f102 060b add.w r6, r2, #11 + 2df64: 2e16 cmp r6, #22 + 2df66: 4681 mov r9, r0 + 2df68: bf99 ittee ls + 2df6a: 2010 movls r0, #16 + 2df6c: 4606 movls r6, r0 + 2df6e: f026 0607 bichi.w r6, r6, #7 + 2df72: ea4f 7cd6 movhi.w ip, r6, lsr #31 + 2df76: bf94 ite ls + 2df78: f04f 0c00 movls.w ip, #0 + 2df7c: 4630 movhi r0, r6 + 2df7e: 4296 cmp r6, r2 + 2df80: bf38 it cc + 2df82: f04c 0c01 orrcc.w ip, ip, #1 + 2df86: f851 3c04 ldr.w r3, [r1, #-4] + 2df8a: f1a1 0708 sub.w r7, r1, #8 + 2df8e: f023 0503 bic.w r5, r3, #3 + 2df92: f1bc 0f00 cmp.w ip, #0 + 2df96: f040 8122 bne.w 2e1de <__rtl_realloc_r_v1_00+0x28a> + 2df9a: 4285 cmp r5, r0 + 2df9c: db0f blt.n 2dfbe <__rtl_realloc_r_v1_00+0x6a> + 2df9e: 4688 mov r8, r1 + 2dfa0: 1baa subs r2, r5, r6 + 2dfa2: 2a0f cmp r2, #15 + 2dfa4: f003 0301 and.w r3, r3, #1 + 2dfa8: d874 bhi.n 2e094 <__rtl_realloc_r_v1_00+0x140> + 2dfaa: 432b orrs r3, r5 + 2dfac: 607b str r3, [r7, #4] + 2dfae: 443d add r5, r7 + 2dfb0: 686b ldr r3, [r5, #4] + 2dfb2: f043 0301 orr.w r3, r3, #1 + 2dfb6: 606b str r3, [r5, #4] + 2dfb8: 4640 mov r0, r8 + 2dfba: e8bd 8ff8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, pc} + 2dfbe: f240 7880 movw r8, #1920 ; 0x780 + 2dfc2: f2c1 0800 movt r8, #4096 ; 0x1000 + 2dfc6: f8d8 e008 ldr.w lr, [r8, #8] + 2dfca: 1979 adds r1, r7, r5 + 2dfcc: 458e cmp lr, r1 + 2dfce: f000 810c beq.w 2e1ea <__rtl_realloc_r_v1_00+0x296> + 2dfd2: f8d1 a004 ldr.w sl, [r1, #4] + 2dfd6: f02a 0b01 bic.w fp, sl, #1 + 2dfda: 448b add fp, r1 + 2dfdc: f8db b004 ldr.w fp, [fp, #4] + 2dfe0: f01b 0f01 tst.w fp, #1 + 2dfe4: bf18 it ne + 2dfe6: 4661 movne r1, ip + 2dfe8: d066 beq.n 2e0b8 <__rtl_realloc_r_v1_00+0x164> + 2dfea: 07db lsls r3, r3, #31 + 2dfec: f100 80b0 bmi.w 2e150 <__rtl_realloc_r_v1_00+0x1fc> + 2dff0: f854 3c08 ldr.w r3, [r4, #-8] + 2dff4: ebc3 0a07 rsb sl, r3, r7 + 2dff8: f8da 3004 ldr.w r3, [sl, #4] + 2dffc: f023 0303 bic.w r3, r3, #3 + 2e000: 442b add r3, r5 + 2e002: 2900 cmp r1, #0 + 2e004: d065 beq.n 2e0d2 <__rtl_realloc_r_v1_00+0x17e> + 2e006: 4571 cmp r1, lr + 2e008: f000 8125 beq.w 2e256 <__rtl_realloc_r_v1_00+0x302> + 2e00c: 449c add ip, r3 + 2e00e: 4584 cmp ip, r0 + 2e010: db5f blt.n 2e0d2 <__rtl_realloc_r_v1_00+0x17e> + 2e012: 46d0 mov r8, sl + 2e014: 68cb ldr r3, [r1, #12] + 2e016: 6889 ldr r1, [r1, #8] + 2e018: 1f2a subs r2, r5, #4 + 2e01a: 60cb str r3, [r1, #12] + 2e01c: 6099 str r1, [r3, #8] + 2e01e: f858 1f08 ldr.w r1, [r8, #8]! + 2e022: f8da 300c ldr.w r3, [sl, #12] + 2e026: 2a24 cmp r2, #36 ; 0x24 + 2e028: 60cb str r3, [r1, #12] + 2e02a: 6099 str r1, [r3, #8] + 2e02c: f200 816b bhi.w 2e306 <__rtl_realloc_r_v1_00+0x3b2> + 2e030: 2a13 cmp r2, #19 + 2e032: bf98 it ls + 2e034: 4643 movls r3, r8 + 2e036: d922 bls.n 2e07e <__rtl_realloc_r_v1_00+0x12a> + 2e038: 6823 ldr r3, [r4, #0] + 2e03a: 2a1b cmp r2, #27 + 2e03c: f8ca 3008 str.w r3, [sl, #8] + 2e040: 6863 ldr r3, [r4, #4] + 2e042: bf98 it ls + 2e044: 3408 addls r4, #8 + 2e046: f8ca 300c str.w r3, [sl, #12] + 2e04a: bf98 it ls + 2e04c: f10a 0310 addls.w r3, sl, #16 + 2e050: d915 bls.n 2e07e <__rtl_realloc_r_v1_00+0x12a> + 2e052: 68a3 ldr r3, [r4, #8] + 2e054: 2a24 cmp r2, #36 ; 0x24 + 2e056: f8ca 3010 str.w r3, [sl, #16] + 2e05a: 68e3 ldr r3, [r4, #12] + 2e05c: bf18 it ne + 2e05e: 3410 addne r4, #16 + 2e060: f8ca 3014 str.w r3, [sl, #20] + 2e064: bf09 itett eq + 2e066: 6922 ldreq r2, [r4, #16] + 2e068: f10a 0318 addne.w r3, sl, #24 + 2e06c: f8ca 2018 streq.w r2, [sl, #24] + 2e070: 6962 ldreq r2, [r4, #20] + 2e072: bf02 ittt eq + 2e074: f10a 0320 addeq.w r3, sl, #32 + 2e078: 3418 addeq r4, #24 + 2e07a: f8ca 201c streq.w r2, [sl, #28] + 2e07e: 6822 ldr r2, [r4, #0] + 2e080: 4665 mov r5, ip + 2e082: 601a str r2, [r3, #0] + 2e084: 6862 ldr r2, [r4, #4] + 2e086: 4657 mov r7, sl + 2e088: 605a str r2, [r3, #4] + 2e08a: 68a2 ldr r2, [r4, #8] + 2e08c: 609a str r2, [r3, #8] + 2e08e: f8da 3004 ldr.w r3, [sl, #4] + 2e092: e785 b.n 2dfa0 <__rtl_realloc_r_v1_00+0x4c> + 2e094: 19b9 adds r1, r7, r6 + 2e096: 4333 orrs r3, r6 + 2e098: f042 0001 orr.w r0, r2, #1 + 2e09c: 607b str r3, [r7, #4] + 2e09e: 440a add r2, r1 + 2e0a0: 6048 str r0, [r1, #4] + 2e0a2: 6853 ldr r3, [r2, #4] + 2e0a4: 4648 mov r0, r9 + 2e0a6: f043 0301 orr.w r3, r3, #1 + 2e0aa: 3108 adds r1, #8 + 2e0ac: 6053 str r3, [r2, #4] + 2e0ae: f7ff fbc7 bl 2d840 <__rtl_free_r_v1_00> + 2e0b2: 4640 mov r0, r8 + 2e0b4: e8bd 8ff8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, pc} + 2e0b8: f02a 0c03 bic.w ip, sl, #3 + 2e0bc: eb0c 0a05 add.w sl, ip, r5 + 2e0c0: 4582 cmp sl, r0 + 2e0c2: db92 blt.n 2dfea <__rtl_realloc_r_v1_00+0x96> + 2e0c4: 68ca ldr r2, [r1, #12] + 2e0c6: 6889 ldr r1, [r1, #8] + 2e0c8: 46a0 mov r8, r4 + 2e0ca: 60ca str r2, [r1, #12] + 2e0cc: 4655 mov r5, sl + 2e0ce: 6091 str r1, [r2, #8] + 2e0d0: e766 b.n 2dfa0 <__rtl_realloc_r_v1_00+0x4c> + 2e0d2: 4283 cmp r3, r0 + 2e0d4: db3c blt.n 2e150 <__rtl_realloc_r_v1_00+0x1fc> + 2e0d6: 46d0 mov r8, sl + 2e0d8: f8da 100c ldr.w r1, [sl, #12] + 2e0dc: f858 0f08 ldr.w r0, [r8, #8]! + 2e0e0: 1f2a subs r2, r5, #4 + 2e0e2: 2a24 cmp r2, #36 ; 0x24 + 2e0e4: 60c1 str r1, [r0, #12] + 2e0e6: 6088 str r0, [r1, #8] + 2e0e8: f200 809d bhi.w 2e226 <__rtl_realloc_r_v1_00+0x2d2> + 2e0ec: 2a13 cmp r2, #19 + 2e0ee: bf98 it ls + 2e0f0: 4642 movls r2, r8 + 2e0f2: d922 bls.n 2e13a <__rtl_realloc_r_v1_00+0x1e6> + 2e0f4: 6821 ldr r1, [r4, #0] + 2e0f6: 2a1b cmp r2, #27 + 2e0f8: f8ca 1008 str.w r1, [sl, #8] + 2e0fc: 6861 ldr r1, [r4, #4] + 2e0fe: bf98 it ls + 2e100: f10a 0210 addls.w r2, sl, #16 + 2e104: f8ca 100c str.w r1, [sl, #12] + 2e108: bf98 it ls + 2e10a: 3408 addls r4, #8 + 2e10c: d915 bls.n 2e13a <__rtl_realloc_r_v1_00+0x1e6> + 2e10e: 68a1 ldr r1, [r4, #8] + 2e110: 2a24 cmp r2, #36 ; 0x24 + 2e112: f8ca 1010 str.w r1, [sl, #16] + 2e116: 68e1 ldr r1, [r4, #12] + 2e118: bf18 it ne + 2e11a: f10a 0218 addne.w r2, sl, #24 + 2e11e: f8ca 1014 str.w r1, [sl, #20] + 2e122: bf09 itett eq + 2e124: 6921 ldreq r1, [r4, #16] + 2e126: 3410 addne r4, #16 + 2e128: f8ca 1018 streq.w r1, [sl, #24] + 2e12c: 6961 ldreq r1, [r4, #20] + 2e12e: bf02 ittt eq + 2e130: f10a 0220 addeq.w r2, sl, #32 + 2e134: 3418 addeq r4, #24 + 2e136: f8ca 101c streq.w r1, [sl, #28] + 2e13a: 6821 ldr r1, [r4, #0] + 2e13c: 461d mov r5, r3 + 2e13e: 6011 str r1, [r2, #0] + 2e140: 6861 ldr r1, [r4, #4] + 2e142: 4657 mov r7, sl + 2e144: 6051 str r1, [r2, #4] + 2e146: 68a3 ldr r3, [r4, #8] + 2e148: 6093 str r3, [r2, #8] + 2e14a: f8da 3004 ldr.w r3, [sl, #4] + 2e14e: e727 b.n 2dfa0 <__rtl_realloc_r_v1_00+0x4c> + 2e150: 4611 mov r1, r2 + 2e152: 4648 mov r0, r9 + 2e154: f7ff fc6c bl 2da30 <__rtl_malloc_r_v1_00> + 2e158: 4680 mov r8, r0 + 2e15a: 2800 cmp r0, #0 + 2e15c: f43f af2c beq.w 2dfb8 <__rtl_realloc_r_v1_00+0x64> + 2e160: f854 3c04 ldr.w r3, [r4, #-4] + 2e164: f1a0 0108 sub.w r1, r0, #8 + 2e168: f023 0201 bic.w r2, r3, #1 + 2e16c: 443a add r2, r7 + 2e16e: 4291 cmp r1, r2 + 2e170: f000 80c2 beq.w 2e2f8 <__rtl_realloc_r_v1_00+0x3a4> + 2e174: 1f2a subs r2, r5, #4 + 2e176: 2a24 cmp r2, #36 ; 0x24 + 2e178: d866 bhi.n 2e248 <__rtl_realloc_r_v1_00+0x2f4> + 2e17a: 2a13 cmp r2, #19 + 2e17c: bf9c itt ls + 2e17e: 4603 movls r3, r0 + 2e180: 4622 movls r2, r4 + 2e182: d91f bls.n 2e1c4 <__rtl_realloc_r_v1_00+0x270> + 2e184: 6823 ldr r3, [r4, #0] + 2e186: 2a1b cmp r2, #27 + 2e188: 6003 str r3, [r0, #0] + 2e18a: 6863 ldr r3, [r4, #4] + 2e18c: bf98 it ls + 2e18e: f104 0208 addls.w r2, r4, #8 + 2e192: 6043 str r3, [r0, #4] + 2e194: bf98 it ls + 2e196: f100 0308 addls.w r3, r0, #8 + 2e19a: d913 bls.n 2e1c4 <__rtl_realloc_r_v1_00+0x270> + 2e19c: 68a3 ldr r3, [r4, #8] + 2e19e: 2a24 cmp r2, #36 ; 0x24 + 2e1a0: 6083 str r3, [r0, #8] + 2e1a2: 68e3 ldr r3, [r4, #12] + 2e1a4: bf18 it ne + 2e1a6: f104 0210 addne.w r2, r4, #16 + 2e1aa: 60c3 str r3, [r0, #12] + 2e1ac: bf09 itett eq + 2e1ae: 6922 ldreq r2, [r4, #16] + 2e1b0: f100 0310 addne.w r3, r0, #16 + 2e1b4: 6102 streq r2, [r0, #16] + 2e1b6: 6961 ldreq r1, [r4, #20] + 2e1b8: bf02 ittt eq + 2e1ba: f100 0318 addeq.w r3, r0, #24 + 2e1be: f104 0218 addeq.w r2, r4, #24 + 2e1c2: 6141 streq r1, [r0, #20] + 2e1c4: 6811 ldr r1, [r2, #0] + 2e1c6: 6019 str r1, [r3, #0] + 2e1c8: 6851 ldr r1, [r2, #4] + 2e1ca: 6059 str r1, [r3, #4] + 2e1cc: 6892 ldr r2, [r2, #8] + 2e1ce: 609a str r2, [r3, #8] + 2e1d0: 4648 mov r0, r9 + 2e1d2: 4621 mov r1, r4 + 2e1d4: f7ff fb34 bl 2d840 <__rtl_free_r_v1_00> + 2e1d8: 4640 mov r0, r8 + 2e1da: e8bd 8ff8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, pc} + 2e1de: 230c movs r3, #12 + 2e1e0: f8c9 3000 str.w r3, [r9] + 2e1e4: 2000 movs r0, #0 + 2e1e6: e8bd 8ff8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, pc} + 2e1ea: f8de 1004 ldr.w r1, [lr, #4] + 2e1ee: f106 0a10 add.w sl, r6, #16 + 2e1f2: f021 0c03 bic.w ip, r1, #3 + 2e1f6: eb0c 0105 add.w r1, ip, r5 + 2e1fa: 4551 cmp r1, sl + 2e1fc: bfb8 it lt + 2e1fe: 4671 movlt r1, lr + 2e200: f6ff aef3 blt.w 2dfea <__rtl_realloc_r_v1_00+0x96> + 2e204: 1b8b subs r3, r1, r6 + 2e206: 4437 add r7, r6 + 2e208: f043 0301 orr.w r3, r3, #1 + 2e20c: f8c8 7008 str.w r7, [r8, #8] + 2e210: 607b str r3, [r7, #4] + 2e212: f854 3c04 ldr.w r3, [r4, #-4] + 2e216: 4620 mov r0, r4 + 2e218: f003 0301 and.w r3, r3, #1 + 2e21c: 431e orrs r6, r3 + 2e21e: f844 6c04 str.w r6, [r4, #-4] + 2e222: e8bd 8ff8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, pc} + 2e226: f648 37ed movw r7, #35821 ; 0x8bed + 2e22a: 4621 mov r1, r4 + 2e22c: f2c0 0702 movt r7, #2 + 2e230: 4640 mov r0, r8 + 2e232: 461d mov r5, r3 + 2e234: 47b8 blx r7 + 2e236: f8da 3004 ldr.w r3, [sl, #4] + 2e23a: 4657 mov r7, sl + 2e23c: e6b0 b.n 2dfa0 <__rtl_realloc_r_v1_00+0x4c> + 2e23e: 4611 mov r1, r2 + 2e240: e8bd 4ff8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} + 2e244: f7ff bbf4 b.w 2da30 <__rtl_malloc_r_v1_00> + 2e248: f648 33ed movw r3, #35821 ; 0x8bed + 2e24c: 4621 mov r1, r4 + 2e24e: f2c0 0302 movt r3, #2 + 2e252: 4798 blx r3 + 2e254: e7bc b.n 2e1d0 <__rtl_realloc_r_v1_00+0x27c> + 2e256: eb0c 0b03 add.w fp, ip, r3 + 2e25a: f106 0110 add.w r1, r6, #16 + 2e25e: 458b cmp fp, r1 + 2e260: f6ff af37 blt.w 2e0d2 <__rtl_realloc_r_v1_00+0x17e> + 2e264: 4657 mov r7, sl + 2e266: f8da 300c ldr.w r3, [sl, #12] + 2e26a: f857 1f08 ldr.w r1, [r7, #8]! + 2e26e: 1f2a subs r2, r5, #4 + 2e270: 2a24 cmp r2, #36 ; 0x24 + 2e272: 60cb str r3, [r1, #12] + 2e274: 6099 str r1, [r3, #8] + 2e276: d852 bhi.n 2e31e <__rtl_realloc_r_v1_00+0x3ca> + 2e278: 2a13 cmp r2, #19 + 2e27a: bf98 it ls + 2e27c: 463b movls r3, r7 + 2e27e: d922 bls.n 2e2c6 <__rtl_realloc_r_v1_00+0x372> + 2e280: 6823 ldr r3, [r4, #0] + 2e282: 2a1b cmp r2, #27 + 2e284: f8ca 3008 str.w r3, [sl, #8] + 2e288: 6863 ldr r3, [r4, #4] + 2e28a: bf98 it ls + 2e28c: 3408 addls r4, #8 + 2e28e: f8ca 300c str.w r3, [sl, #12] + 2e292: bf98 it ls + 2e294: f10a 0310 addls.w r3, sl, #16 + 2e298: d915 bls.n 2e2c6 <__rtl_realloc_r_v1_00+0x372> + 2e29a: 68a3 ldr r3, [r4, #8] + 2e29c: 2a24 cmp r2, #36 ; 0x24 + 2e29e: f8ca 3010 str.w r3, [sl, #16] + 2e2a2: 68e3 ldr r3, [r4, #12] + 2e2a4: bf18 it ne + 2e2a6: 3410 addne r4, #16 + 2e2a8: f8ca 3014 str.w r3, [sl, #20] + 2e2ac: bf09 itett eq + 2e2ae: 6922 ldreq r2, [r4, #16] + 2e2b0: f10a 0318 addne.w r3, sl, #24 + 2e2b4: f8ca 2018 streq.w r2, [sl, #24] + 2e2b8: 6962 ldreq r2, [r4, #20] + 2e2ba: bf02 ittt eq + 2e2bc: f10a 0320 addeq.w r3, sl, #32 + 2e2c0: 3418 addeq r4, #24 + 2e2c2: f8ca 201c streq.w r2, [sl, #28] + 2e2c6: 6822 ldr r2, [r4, #0] + 2e2c8: 601a str r2, [r3, #0] + 2e2ca: 6862 ldr r2, [r4, #4] + 2e2cc: 605a str r2, [r3, #4] + 2e2ce: 68a2 ldr r2, [r4, #8] + 2e2d0: 609a str r2, [r3, #8] + 2e2d2: ebc6 020b rsb r2, r6, fp + 2e2d6: eb0a 0306 add.w r3, sl, r6 + 2e2da: f042 0201 orr.w r2, r2, #1 + 2e2de: f8c8 3008 str.w r3, [r8, #8] + 2e2e2: 605a str r2, [r3, #4] + 2e2e4: f8da 3004 ldr.w r3, [sl, #4] + 2e2e8: 4638 mov r0, r7 + 2e2ea: f003 0301 and.w r3, r3, #1 + 2e2ee: 431e orrs r6, r3 + 2e2f0: f8ca 6004 str.w r6, [sl, #4] + 2e2f4: e8bd 8ff8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, pc} + 2e2f8: f850 2c04 ldr.w r2, [r0, #-4] + 2e2fc: 46a0 mov r8, r4 + 2e2fe: f022 0203 bic.w r2, r2, #3 + 2e302: 4415 add r5, r2 + 2e304: e64c b.n 2dfa0 <__rtl_realloc_r_v1_00+0x4c> + 2e306: f648 33ed movw r3, #35821 ; 0x8bed + 2e30a: 4621 mov r1, r4 + 2e30c: f2c0 0302 movt r3, #2 + 2e310: 4640 mov r0, r8 + 2e312: 4665 mov r5, ip + 2e314: 4657 mov r7, sl + 2e316: 4798 blx r3 + 2e318: f8da 3004 ldr.w r3, [sl, #4] + 2e31c: e640 b.n 2dfa0 <__rtl_realloc_r_v1_00+0x4c> + 2e31e: f648 33ed movw r3, #35821 ; 0x8bed + 2e322: 4621 mov r1, r4 + 2e324: f2c0 0302 movt r3, #2 + 2e328: 4638 mov r0, r7 + 2e32a: 4798 blx r3 + 2e32c: e7d1 b.n 2e2d2 <__rtl_realloc_r_v1_00+0x37e> + 2e32e: bf00 nop + +0002e330 <__rtl_memalign_r_v1_00>: + 2e330: 2908 cmp r1, #8 + 2e332: b5f8 push {r3, r4, r5, r6, r7, lr} + 2e334: 460c mov r4, r1 + 2e336: d95a bls.n 2e3ee <__rtl_memalign_r_v1_00+0xbe> + 2e338: f102 050b add.w r5, r2, #11 + 2e33c: 290f cmp r1, #15 + 2e33e: bf98 it ls + 2e340: 2410 movls r4, #16 + 2e342: 2d16 cmp r5, #22 + 2e344: bf87 ittee hi + 2e346: f025 0507 bichi.w r5, r5, #7 + 2e34a: 0feb lsrhi r3, r5, #31 + 2e34c: 2300 movls r3, #0 + 2e34e: 2510 movls r5, #16 + 2e350: 4295 cmp r5, r2 + 2e352: bf2c ite cs + 2e354: 461a movcs r2, r3 + 2e356: f043 0201 orrcc.w r2, r3, #1 + 2e35a: 4607 mov r7, r0 + 2e35c: 2a00 cmp r2, #0 + 2e35e: d15b bne.n 2e418 <__rtl_memalign_r_v1_00+0xe8> + 2e360: f104 0110 add.w r1, r4, #16 + 2e364: 4429 add r1, r5 + 2e366: f7ff fb63 bl 2da30 <__rtl_malloc_r_v1_00> + 2e36a: 4603 mov r3, r0 + 2e36c: 2800 cmp r0, #0 + 2e36e: d055 beq.n 2e41c <__rtl_memalign_r_v1_00+0xec> + 2e370: fbb0 f2f4 udiv r2, r0, r4 + 2e374: fb04 0212 mls r2, r4, r2, r0 + 2e378: f1a0 0608 sub.w r6, r0, #8 + 2e37c: b942 cbnz r2, 2e390 <__rtl_memalign_r_v1_00+0x60> + 2e37e: 6873 ldr r3, [r6, #4] + 2e380: f023 0303 bic.w r3, r3, #3 + 2e384: 1b5b subs r3, r3, r5 + 2e386: 2b0f cmp r3, #15 + 2e388: dc36 bgt.n 2e3f8 <__rtl_memalign_r_v1_00+0xc8> + 2e38a: f106 0008 add.w r0, r6, #8 + 2e38e: bdf8 pop {r3, r4, r5, r6, r7, pc} + 2e390: 1e62 subs r2, r4, #1 + 2e392: 4261 negs r1, r4 + 2e394: 4402 add r2, r0 + 2e396: 400a ands r2, r1 + 2e398: 3a08 subs r2, #8 + 2e39a: ebc6 0e02 rsb lr, r6, r2 + 2e39e: f1be 0f0f cmp.w lr, #15 + 2e3a2: bfdc itt le + 2e3a4: 1912 addle r2, r2, r4 + 2e3a6: ebc6 0e02 rsble lr, r6, r2 + 2e3aa: f850 6c04 ldr.w r6, [r0, #-4] + 2e3ae: 4601 mov r1, r0 + 2e3b0: f026 0603 bic.w r6, r6, #3 + 2e3b4: ebce 0606 rsb r6, lr, r6 + 2e3b8: f046 0001 orr.w r0, r6, #1 + 2e3bc: 6050 str r0, [r2, #4] + 2e3be: 4416 add r6, r2 + 2e3c0: 6874 ldr r4, [r6, #4] + 2e3c2: 4638 mov r0, r7 + 2e3c4: f044 0401 orr.w r4, r4, #1 + 2e3c8: 6074 str r4, [r6, #4] + 2e3ca: 4616 mov r6, r2 + 2e3cc: f853 4c04 ldr.w r4, [r3, #-4] + 2e3d0: f004 0401 and.w r4, r4, #1 + 2e3d4: ea4e 0404 orr.w r4, lr, r4 + 2e3d8: f843 4c04 str.w r4, [r3, #-4] + 2e3dc: f7ff fa30 bl 2d840 <__rtl_free_r_v1_00> + 2e3e0: 6873 ldr r3, [r6, #4] + 2e3e2: f023 0303 bic.w r3, r3, #3 + 2e3e6: 1b5b subs r3, r3, r5 + 2e3e8: 2b0f cmp r3, #15 + 2e3ea: ddce ble.n 2e38a <__rtl_memalign_r_v1_00+0x5a> + 2e3ec: e004 b.n 2e3f8 <__rtl_memalign_r_v1_00+0xc8> + 2e3ee: 4611 mov r1, r2 + 2e3f0: e8bd 40f8 ldmia.w sp!, {r3, r4, r5, r6, r7, lr} + 2e3f4: f7ff bb1c b.w 2da30 <__rtl_malloc_r_v1_00> + 2e3f8: 1971 adds r1, r6, r5 + 2e3fa: f043 0301 orr.w r3, r3, #1 + 2e3fe: 604b str r3, [r1, #4] + 2e400: 6873 ldr r3, [r6, #4] + 2e402: 4638 mov r0, r7 + 2e404: f003 0301 and.w r3, r3, #1 + 2e408: 431d orrs r5, r3 + 2e40a: 3108 adds r1, #8 + 2e40c: 6075 str r5, [r6, #4] + 2e40e: f7ff fa17 bl 2d840 <__rtl_free_r_v1_00> + 2e412: f106 0008 add.w r0, r6, #8 + 2e416: bdf8 pop {r3, r4, r5, r6, r7, pc} + 2e418: 230c movs r3, #12 + 2e41a: 6003 str r3, [r0, #0] + 2e41c: 2000 movs r0, #0 + 2e41e: bdf8 pop {r3, r4, r5, r6, r7, pc} + +0002e420 <__rtl_valloc_r_v1_00>: + 2e420: 460a mov r2, r1 + 2e422: f44f 5180 mov.w r1, #4096 ; 0x1000 + 2e426: f7ff bf83 b.w 2e330 <__rtl_memalign_r_v1_00> + 2e42a: bf00 nop + +0002e42c <__rtl_pvalloc_r_v1_00>: + 2e42c: f601 72ff addw r2, r1, #4095 ; 0xfff + 2e430: f422 627f bic.w r2, r2, #4080 ; 0xff0 + 2e434: f022 020f bic.w r2, r2, #15 + 2e438: f44f 5180 mov.w r1, #4096 ; 0x1000 + 2e43c: f7ff bf78 b.w 2e330 <__rtl_memalign_r_v1_00> + +0002e440 <__rtl_calloc_r_v1_00>: + 2e440: b510 push {r4, lr} + 2e442: fb02 f101 mul.w r1, r2, r1 + 2e446: f7ff faf3 bl 2da30 <__rtl_malloc_r_v1_00> + 2e44a: 4604 mov r4, r0 + 2e44c: b170 cbz r0, 2e46c <__rtl_calloc_r_v1_00+0x2c> + 2e44e: f850 2c04 ldr.w r2, [r0, #-4] + 2e452: f022 0203 bic.w r2, r2, #3 + 2e456: 3a04 subs r2, #4 + 2e458: 2a24 cmp r2, #36 ; 0x24 + 2e45a: d81c bhi.n 2e496 <__rtl_calloc_r_v1_00+0x56> + 2e45c: 2a13 cmp r2, #19 + 2e45e: bf98 it ls + 2e460: 4603 movls r3, r0 + 2e462: d805 bhi.n 2e470 <__rtl_calloc_r_v1_00+0x30> + 2e464: 2200 movs r2, #0 + 2e466: 601a str r2, [r3, #0] + 2e468: 605a str r2, [r3, #4] + 2e46a: 609a str r2, [r3, #8] + 2e46c: 4620 mov r0, r4 + 2e46e: bd10 pop {r4, pc} + 2e470: 2300 movs r3, #0 + 2e472: 2a1b cmp r2, #27 + 2e474: 6003 str r3, [r0, #0] + 2e476: 6043 str r3, [r0, #4] + 2e478: bf98 it ls + 2e47a: f100 0308 addls.w r3, r0, #8 + 2e47e: d9f1 bls.n 2e464 <__rtl_calloc_r_v1_00+0x24> + 2e480: 2a24 cmp r2, #36 ; 0x24 + 2e482: 6083 str r3, [r0, #8] + 2e484: 60c3 str r3, [r0, #12] + 2e486: bf05 ittet eq + 2e488: 6103 streq r3, [r0, #16] + 2e48a: 6143 streq r3, [r0, #20] + 2e48c: f100 0310 addne.w r3, r0, #16 + 2e490: f100 0318 addeq.w r3, r0, #24 + 2e494: e7e6 b.n 2e464 <__rtl_calloc_r_v1_00+0x24> + 2e496: f648 43b5 movw r3, #36021 ; 0x8cb5 + 2e49a: 2100 movs r1, #0 + 2e49c: f2c0 0302 movt r3, #2 + 2e4a0: 4798 blx r3 + 2e4a2: 4620 mov r0, r4 + 2e4a4: bd10 pop {r4, pc} + 2e4a6: bf00 nop + +0002e4a8 <__rtl_cfree_r_v1_00>: + 2e4a8: f241 0398 movw r3, #4248 ; 0x1098 + 2e4ac: f6c1 73ff movt r3, #8191 ; 0x1fff + 2e4b0: 4601 mov r1, r0 + 2e4b2: 6818 ldr r0, [r3, #0] + 2e4b4: f7ff b9c4 b.w 2d840 <__rtl_free_r_v1_00> + +0002e4b8 <__rtl_lo0bits>: + 2e4b8: 6803 ldr r3, [r0, #0] + 2e4ba: f013 0207 ands.w r2, r3, #7 + 2e4be: d00b beq.n 2e4d8 <__rtl_lo0bits+0x20> + 2e4c0: 07d9 lsls r1, r3, #31 + 2e4c2: d424 bmi.n 2e50e <__rtl_lo0bits+0x56> + 2e4c4: 079a lsls r2, r3, #30 + 2e4c6: bf4b itete mi + 2e4c8: 085b lsrmi r3, r3, #1 + 2e4ca: 089b lsrpl r3, r3, #2 + 2e4cc: 6003 strmi r3, [r0, #0] + 2e4ce: 6003 strpl r3, [r0, #0] + 2e4d0: bf4c ite mi + 2e4d2: 2001 movmi r0, #1 + 2e4d4: 2002 movpl r0, #2 + 2e4d6: 4770 bx lr + 2e4d8: b299 uxth r1, r3 + 2e4da: b909 cbnz r1, 2e4e0 <__rtl_lo0bits+0x28> + 2e4dc: 0c1b lsrs r3, r3, #16 + 2e4de: 2210 movs r2, #16 + 2e4e0: f013 0fff tst.w r3, #255 ; 0xff + 2e4e4: bf04 itt eq + 2e4e6: 0a1b lsreq r3, r3, #8 + 2e4e8: 3208 addeq r2, #8 + 2e4ea: 0719 lsls r1, r3, #28 + 2e4ec: bf04 itt eq + 2e4ee: 091b lsreq r3, r3, #4 + 2e4f0: 3204 addeq r2, #4 + 2e4f2: 0799 lsls r1, r3, #30 + 2e4f4: bf04 itt eq + 2e4f6: 089b lsreq r3, r3, #2 + 2e4f8: 3202 addeq r2, #2 + 2e4fa: 07d9 lsls r1, r3, #31 + 2e4fc: d404 bmi.n 2e508 <__rtl_lo0bits+0x50> + 2e4fe: 085b lsrs r3, r3, #1 + 2e500: d101 bne.n 2e506 <__rtl_lo0bits+0x4e> + 2e502: 2020 movs r0, #32 + 2e504: 4770 bx lr + 2e506: 3201 adds r2, #1 + 2e508: 6003 str r3, [r0, #0] + 2e50a: 4610 mov r0, r2 + 2e50c: 4770 bx lr + 2e50e: 2000 movs r0, #0 + 2e510: 4770 bx lr + 2e512: bf00 nop + +0002e514 <__rtl_Balloc_v1_00>: + 2e514: 6cc2 ldr r2, [r0, #76] ; 0x4c + 2e516: b570 push {r4, r5, r6, lr} + 2e518: 4605 mov r5, r0 + 2e51a: 460c mov r4, r1 + 2e51c: b152 cbz r2, 2e534 <__rtl_Balloc_v1_00+0x20> + 2e51e: f852 3024 ldr.w r3, [r2, r4, lsl #2] + 2e522: b1a3 cbz r3, 2e54e <__rtl_Balloc_v1_00+0x3a> + 2e524: 6819 ldr r1, [r3, #0] + 2e526: f842 1024 str.w r1, [r2, r4, lsl #2] + 2e52a: 2200 movs r2, #0 + 2e52c: 4618 mov r0, r3 + 2e52e: 611a str r2, [r3, #16] + 2e530: 60da str r2, [r3, #12] + 2e532: bd70 pop {r4, r5, r6, pc} + 2e534: f24e 4341 movw r3, #58433 ; 0xe441 + 2e538: 2221 movs r2, #33 ; 0x21 + 2e53a: 2104 movs r1, #4 + 2e53c: f2c0 0302 movt r3, #2 + 2e540: 4798 blx r3 + 2e542: 64e8 str r0, [r5, #76] ; 0x4c + 2e544: 4602 mov r2, r0 + 2e546: 2800 cmp r0, #0 + 2e548: d1e9 bne.n 2e51e <__rtl_Balloc_v1_00+0xa> + 2e54a: 2000 movs r0, #0 + 2e54c: bd70 pop {r4, r5, r6, pc} + 2e54e: f24e 4341 movw r3, #58433 ; 0xe441 + 2e552: 2101 movs r1, #1 + 2e554: fa01 f604 lsl.w r6, r1, r4 + 2e558: 1d72 adds r2, r6, #5 + 2e55a: f2c0 0302 movt r3, #2 + 2e55e: 4628 mov r0, r5 + 2e560: 0092 lsls r2, r2, #2 + 2e562: 4798 blx r3 + 2e564: 4603 mov r3, r0 + 2e566: 2800 cmp r0, #0 + 2e568: d0ef beq.n 2e54a <__rtl_Balloc_v1_00+0x36> + 2e56a: 6044 str r4, [r0, #4] + 2e56c: 6086 str r6, [r0, #8] + 2e56e: e7dc b.n 2e52a <__rtl_Balloc_v1_00+0x16> + +0002e570 <__rtl_Bfree_v1_00>: + 2e570: b131 cbz r1, 2e580 <__rtl_Bfree_v1_00+0x10> + 2e572: 6cc3 ldr r3, [r0, #76] ; 0x4c + 2e574: 684a ldr r2, [r1, #4] + 2e576: f853 0022 ldr.w r0, [r3, r2, lsl #2] + 2e57a: 6008 str r0, [r1, #0] + 2e57c: f843 1022 str.w r1, [r3, r2, lsl #2] + 2e580: 4770 bx lr + 2e582: bf00 nop + +0002e584 <__rtl_i2b_v1_00>: + 2e584: b510 push {r4, lr} + 2e586: 460c mov r4, r1 + 2e588: 2101 movs r1, #1 + 2e58a: f7ff ffc3 bl 2e514 <__rtl_Balloc_v1_00> + 2e58e: 2201 movs r2, #1 + 2e590: 6144 str r4, [r0, #20] + 2e592: 6102 str r2, [r0, #16] + 2e594: bd10 pop {r4, pc} + 2e596: bf00 nop + +0002e598 <__rtl_multadd_v1_00>: + 2e598: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} + 2e59c: 460f mov r7, r1 + 2e59e: 4680 mov r8, r0 + 2e5a0: f8d1 9010 ldr.w r9, [r1, #16] + 2e5a4: b083 sub sp, #12 + 2e5a6: f101 0514 add.w r5, r1, #20 + 2e5aa: 2400 movs r4, #0 + 2e5ac: 682e ldr r6, [r5, #0] + 2e5ae: 3401 adds r4, #1 + 2e5b0: b2b1 uxth r1, r6 + 2e5b2: 0c36 lsrs r6, r6, #16 + 2e5b4: fb02 3301 mla r3, r2, r1, r3 + 2e5b8: fb02 f606 mul.w r6, r2, r6 + 2e5bc: b299 uxth r1, r3 + 2e5be: eb06 4313 add.w r3, r6, r3, lsr #16 + 2e5c2: eb01 4103 add.w r1, r1, r3, lsl #16 + 2e5c6: 45a1 cmp r9, r4 + 2e5c8: f845 1b04 str.w r1, [r5], #4 + 2e5cc: ea4f 4313 mov.w r3, r3, lsr #16 + 2e5d0: dcec bgt.n 2e5ac <__rtl_multadd_v1_00+0x14> + 2e5d2: b143 cbz r3, 2e5e6 <__rtl_multadd_v1_00+0x4e> + 2e5d4: 68ba ldr r2, [r7, #8] + 2e5d6: 4591 cmp r9, r2 + 2e5d8: da09 bge.n 2e5ee <__rtl_multadd_v1_00+0x56> + 2e5da: eb07 0189 add.w r1, r7, r9, lsl #2 + 2e5de: f109 0201 add.w r2, r9, #1 + 2e5e2: 614b str r3, [r1, #20] + 2e5e4: 613a str r2, [r7, #16] + 2e5e6: 4638 mov r0, r7 + 2e5e8: b003 add sp, #12 + 2e5ea: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + 2e5ee: 6879 ldr r1, [r7, #4] + 2e5f0: 4640 mov r0, r8 + 2e5f2: 3101 adds r1, #1 + 2e5f4: 9301 str r3, [sp, #4] + 2e5f6: f7ff ff8d bl 2e514 <__rtl_Balloc_v1_00> + 2e5fa: f648 3449 movw r4, #35657 ; 0x8b49 + 2e5fe: 4605 mov r5, r0 + 2e600: 693a ldr r2, [r7, #16] + 2e602: f107 010c add.w r1, r7, #12 + 2e606: 3202 adds r2, #2 + 2e608: 0092 lsls r2, r2, #2 + 2e60a: 300c adds r0, #12 + 2e60c: f2c0 0402 movt r4, #2 + 2e610: 47a0 blx r4 + 2e612: f8d8 204c ldr.w r2, [r8, #76] ; 0x4c + 2e616: 6879 ldr r1, [r7, #4] + 2e618: 9b01 ldr r3, [sp, #4] + 2e61a: f852 0021 ldr.w r0, [r2, r1, lsl #2] + 2e61e: 6038 str r0, [r7, #0] + 2e620: f842 7021 str.w r7, [r2, r1, lsl #2] + 2e624: 462f mov r7, r5 + 2e626: e7d8 b.n 2e5da <__rtl_multadd_v1_00+0x42> + +0002e628 <__rtl_mult_v1_00>: + 2e628: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 2e62c: 690f ldr r7, [r1, #16] + 2e62e: 6915 ldr r5, [r2, #16] + 2e630: b085 sub sp, #20 + 2e632: 42af cmp r7, r5 + 2e634: 460c mov r4, r1 + 2e636: 4692 mov sl, r2 + 2e638: da04 bge.n 2e644 <__rtl_mult_v1_00+0x1c> + 2e63a: 463a mov r2, r7 + 2e63c: 4654 mov r4, sl + 2e63e: 462f mov r7, r5 + 2e640: 468a mov sl, r1 + 2e642: 4615 mov r5, r2 + 2e644: 68a3 ldr r3, [r4, #8] + 2e646: eb07 0805 add.w r8, r7, r5 + 2e64a: 6861 ldr r1, [r4, #4] + 2e64c: 4598 cmp r8, r3 + 2e64e: bfc8 it gt + 2e650: 3101 addgt r1, #1 + 2e652: f7ff ff5f bl 2e514 <__rtl_Balloc_v1_00> + 2e656: f100 0914 add.w r9, r0, #20 + 2e65a: eb09 0b88 add.w fp, r9, r8, lsl #2 + 2e65e: 45d9 cmp r9, fp + 2e660: 9001 str r0, [sp, #4] + 2e662: bf3c itt cc + 2e664: 464b movcc r3, r9 + 2e666: 2000 movcc r0, #0 + 2e668: d203 bcs.n 2e672 <__rtl_mult_v1_00+0x4a> + 2e66a: f843 0b04 str.w r0, [r3], #4 + 2e66e: 459b cmp fp, r3 + 2e670: d8fb bhi.n 2e66a <__rtl_mult_v1_00+0x42> + 2e672: f10a 0a14 add.w sl, sl, #20 + 2e676: eb0a 0585 add.w r5, sl, r5, lsl #2 + 2e67a: 45aa cmp sl, r5 + 2e67c: f104 0414 add.w r4, r4, #20 + 2e680: bf3c itt cc + 2e682: f8cd b008 strcc.w fp, [sp, #8] + 2e686: f8cd 800c strcc.w r8, [sp, #12] + 2e68a: eb04 0787 add.w r7, r4, r7, lsl #2 + 2e68e: bf3c itt cc + 2e690: 46ab movcc fp, r5 + 2e692: 46a0 movcc r8, r4 + 2e694: d251 bcs.n 2e73a <__rtl_mult_v1_00+0x112> + 2e696: f85a 6b04 ldr.w r6, [sl], #4 + 2e69a: b2b5 uxth r5, r6 + 2e69c: b30d cbz r5, 2e6e2 <__rtl_mult_v1_00+0xba> + 2e69e: 4641 mov r1, r8 + 2e6a0: 464a mov r2, r9 + 2e6a2: 2600 movs r6, #0 + 2e6a4: 46ae mov lr, r5 + 2e6a6: e000 b.n 2e6aa <__rtl_mult_v1_00+0x82> + 2e6a8: 461a mov r2, r3 + 2e6aa: 4613 mov r3, r2 + 2e6ac: f851 5b04 ldr.w r5, [r1], #4 + 2e6b0: 6814 ldr r4, [r2, #0] + 2e6b2: b2a8 uxth r0, r5 + 2e6b4: fa1f fc84 uxth.w ip, r4 + 2e6b8: fb0e cc00 mla ip, lr, r0, ip + 2e6bc: 0c2d lsrs r5, r5, #16 + 2e6be: 0c20 lsrs r0, r4, #16 + 2e6c0: fb0e 0005 mla r0, lr, r5, r0 + 2e6c4: 4466 add r6, ip + 2e6c6: eb00 4016 add.w r0, r0, r6, lsr #16 + 2e6ca: b2b6 uxth r6, r6 + 2e6cc: ea46 4400 orr.w r4, r6, r0, lsl #16 + 2e6d0: 428f cmp r7, r1 + 2e6d2: ea4f 4610 mov.w r6, r0, lsr #16 + 2e6d6: f843 4b04 str.w r4, [r3], #4 + 2e6da: d8e5 bhi.n 2e6a8 <__rtl_mult_v1_00+0x80> + 2e6dc: 6056 str r6, [r2, #4] + 2e6de: f85a 6c04 ldr.w r6, [sl, #-4] + 2e6e2: 0c36 lsrs r6, r6, #16 + 2e6e4: d021 beq.n 2e72a <__rtl_mult_v1_00+0x102> + 2e6e6: f8d9 1000 ldr.w r1, [r9] + 2e6ea: 4648 mov r0, r9 + 2e6ec: 460c mov r4, r1 + 2e6ee: 4643 mov r3, r8 + 2e6f0: f04f 0e00 mov.w lr, #0 + 2e6f4: e000 b.n 2e6f8 <__rtl_mult_v1_00+0xd0> + 2e6f6: 4610 mov r0, r2 + 2e6f8: 4602 mov r2, r0 + 2e6fa: 881d ldrh r5, [r3, #0] + 2e6fc: 0c24 lsrs r4, r4, #16 + 2e6fe: fb06 4405 mla r4, r6, r5, r4 + 2e702: b289 uxth r1, r1 + 2e704: 44a6 add lr, r4 + 2e706: ea41 410e orr.w r1, r1, lr, lsl #16 + 2e70a: f842 1b04 str.w r1, [r2], #4 + 2e70e: f853 1b04 ldr.w r1, [r3], #4 + 2e712: 6844 ldr r4, [r0, #4] + 2e714: 0c09 lsrs r1, r1, #16 + 2e716: b2a5 uxth r5, r4 + 2e718: fb06 5101 mla r1, r6, r1, r5 + 2e71c: 429f cmp r7, r3 + 2e71e: eb01 411e add.w r1, r1, lr, lsr #16 + 2e722: ea4f 4e11 mov.w lr, r1, lsr #16 + 2e726: d8e6 bhi.n 2e6f6 <__rtl_mult_v1_00+0xce> + 2e728: 6041 str r1, [r0, #4] + 2e72a: 45d3 cmp fp, sl + 2e72c: f109 0904 add.w r9, r9, #4 + 2e730: d8b1 bhi.n 2e696 <__rtl_mult_v1_00+0x6e> + 2e732: f8dd b008 ldr.w fp, [sp, #8] + 2e736: f8dd 800c ldr.w r8, [sp, #12] + 2e73a: f1b8 0f00 cmp.w r8, #0 + 2e73e: dd0b ble.n 2e758 <__rtl_mult_v1_00+0x130> + 2e740: f85b 3c04 ldr.w r3, [fp, #-4] + 2e744: f1ab 0b04 sub.w fp, fp, #4 + 2e748: b11b cbz r3, 2e752 <__rtl_mult_v1_00+0x12a> + 2e74a: e005 b.n 2e758 <__rtl_mult_v1_00+0x130> + 2e74c: f85b 3d04 ldr.w r3, [fp, #-4]! + 2e750: b913 cbnz r3, 2e758 <__rtl_mult_v1_00+0x130> + 2e752: f1b8 0801 subs.w r8, r8, #1 + 2e756: d1f9 bne.n 2e74c <__rtl_mult_v1_00+0x124> + 2e758: 9b01 ldr r3, [sp, #4] + 2e75a: 4618 mov r0, r3 + 2e75c: f8c3 8010 str.w r8, [r3, #16] + 2e760: b005 add sp, #20 + 2e762: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 2e766: bf00 nop + +0002e768 <__rtl_pow5mult_v1_00>: + 2e768: f012 0303 ands.w r3, r2, #3 + 2e76c: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + 2e770: 4614 mov r4, r2 + 2e772: 4607 mov r7, r0 + 2e774: 460e mov r6, r1 + 2e776: d12d bne.n 2e7d4 <__rtl_pow5mult_v1_00+0x6c> + 2e778: 10a4 asrs r4, r4, #2 + 2e77a: d01c beq.n 2e7b6 <__rtl_pow5mult_v1_00+0x4e> + 2e77c: 6cbd ldr r5, [r7, #72] ; 0x48 + 2e77e: b3ad cbz r5, 2e7ec <__rtl_pow5mult_v1_00+0x84> + 2e780: 07e3 lsls r3, r4, #31 + 2e782: f04f 0800 mov.w r8, #0 + 2e786: d406 bmi.n 2e796 <__rtl_pow5mult_v1_00+0x2e> + 2e788: 1064 asrs r4, r4, #1 + 2e78a: d014 beq.n 2e7b6 <__rtl_pow5mult_v1_00+0x4e> + 2e78c: 6828 ldr r0, [r5, #0] + 2e78e: b1a8 cbz r0, 2e7bc <__rtl_pow5mult_v1_00+0x54> + 2e790: 4605 mov r5, r0 + 2e792: 07e3 lsls r3, r4, #31 + 2e794: d5f8 bpl.n 2e788 <__rtl_pow5mult_v1_00+0x20> + 2e796: 4638 mov r0, r7 + 2e798: 4631 mov r1, r6 + 2e79a: 462a mov r2, r5 + 2e79c: f7ff ff44 bl 2e628 <__rtl_mult_v1_00> + 2e7a0: b1b6 cbz r6, 2e7d0 <__rtl_pow5mult_v1_00+0x68> + 2e7a2: 6872 ldr r2, [r6, #4] + 2e7a4: 6cfb ldr r3, [r7, #76] ; 0x4c + 2e7a6: 1064 asrs r4, r4, #1 + 2e7a8: f853 1022 ldr.w r1, [r3, r2, lsl #2] + 2e7ac: 6031 str r1, [r6, #0] + 2e7ae: f843 6022 str.w r6, [r3, r2, lsl #2] + 2e7b2: 4606 mov r6, r0 + 2e7b4: d1ea bne.n 2e78c <__rtl_pow5mult_v1_00+0x24> + 2e7b6: 4630 mov r0, r6 + 2e7b8: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 2e7bc: 4629 mov r1, r5 + 2e7be: 462a mov r2, r5 + 2e7c0: 4638 mov r0, r7 + 2e7c2: f7ff ff31 bl 2e628 <__rtl_mult_v1_00> + 2e7c6: 6028 str r0, [r5, #0] + 2e7c8: f8c0 8000 str.w r8, [r0] + 2e7cc: 4605 mov r5, r0 + 2e7ce: e7e0 b.n 2e792 <__rtl_pow5mult_v1_00+0x2a> + 2e7d0: 4606 mov r6, r0 + 2e7d2: e7d9 b.n 2e788 <__rtl_pow5mult_v1_00+0x20> + 2e7d4: f64e 32f8 movw r2, #60408 ; 0xebf8 + 2e7d8: f2c0 0203 movt r2, #3 + 2e7dc: 3b01 subs r3, #1 + 2e7de: f852 2023 ldr.w r2, [r2, r3, lsl #2] + 2e7e2: 2300 movs r3, #0 + 2e7e4: f7ff fed8 bl 2e598 <__rtl_multadd_v1_00> + 2e7e8: 4606 mov r6, r0 + 2e7ea: e7c5 b.n 2e778 <__rtl_pow5mult_v1_00+0x10> + 2e7ec: 2101 movs r1, #1 + 2e7ee: 4638 mov r0, r7 + 2e7f0: f7ff fe90 bl 2e514 <__rtl_Balloc_v1_00> + 2e7f4: f240 2171 movw r1, #625 ; 0x271 + 2e7f8: 2201 movs r2, #1 + 2e7fa: 2300 movs r3, #0 + 2e7fc: 6141 str r1, [r0, #20] + 2e7fe: 6102 str r2, [r0, #16] + 2e800: 4605 mov r5, r0 + 2e802: 64b8 str r0, [r7, #72] ; 0x48 + 2e804: 6003 str r3, [r0, #0] + 2e806: e7bb b.n 2e780 <__rtl_pow5mult_v1_00+0x18> + +0002e808 <__rtl_hi0bits_v1_00>: + 2e808: 0c03 lsrs r3, r0, #16 + 2e80a: bf06 itte eq + 2e80c: 0400 lsleq r0, r0, #16 + 2e80e: 2310 moveq r3, #16 + 2e810: 2300 movne r3, #0 + 2e812: f010 4f7f tst.w r0, #4278190080 ; 0xff000000 + 2e816: bf04 itt eq + 2e818: 0200 lsleq r0, r0, #8 + 2e81a: 3308 addeq r3, #8 + 2e81c: f010 4f70 tst.w r0, #4026531840 ; 0xf0000000 + 2e820: bf04 itt eq + 2e822: 0100 lsleq r0, r0, #4 + 2e824: 3304 addeq r3, #4 + 2e826: f010 4f40 tst.w r0, #3221225472 ; 0xc0000000 + 2e82a: bf04 itt eq + 2e82c: 0080 lsleq r0, r0, #2 + 2e82e: 3302 addeq r3, #2 + 2e830: 2800 cmp r0, #0 + 2e832: db05 blt.n 2e840 <__rtl_hi0bits_v1_00+0x38> + 2e834: 0042 lsls r2, r0, #1 + 2e836: d401 bmi.n 2e83c <__rtl_hi0bits_v1_00+0x34> + 2e838: 2020 movs r0, #32 + 2e83a: 4770 bx lr + 2e83c: 1c58 adds r0, r3, #1 + 2e83e: 4770 bx lr + 2e840: 4618 mov r0, r3 + 2e842: 4770 bx lr + +0002e844 <__rtl_d2b_v1_00>: + 2e844: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} + 2e848: 2101 movs r1, #1 + 2e84a: b083 sub sp, #12 + 2e84c: 461d mov r5, r3 + 2e84e: f3c3 560a ubfx r6, r3, #20, #11 + 2e852: 4614 mov r4, r2 + 2e854: 9f0a ldr r7, [sp, #40] ; 0x28 + 2e856: f7ff fe5d bl 2e514 <__rtl_Balloc_v1_00> + 2e85a: f3c5 0313 ubfx r3, r5, #0, #20 + 2e85e: 4680 mov r8, r0 + 2e860: b10e cbz r6, 2e866 <__rtl_d2b_v1_00+0x22> + 2e862: f443 1380 orr.w r3, r3, #1048576 ; 0x100000 + 2e866: 9301 str r3, [sp, #4] + 2e868: b324 cbz r4, 2e8b4 <__rtl_d2b_v1_00+0x70> + 2e86a: a802 add r0, sp, #8 + 2e86c: f840 4d08 str.w r4, [r0, #-8]! + 2e870: 4668 mov r0, sp + 2e872: f7ff fe21 bl 2e4b8 <__rtl_lo0bits> + 2e876: 2800 cmp r0, #0 + 2e878: d136 bne.n 2e8e8 <__rtl_d2b_v1_00+0xa4> + 2e87a: e89d 000c ldmia.w sp, {r2, r3} + 2e87e: f8c8 2014 str.w r2, [r8, #20] + 2e882: 2b00 cmp r3, #0 + 2e884: bf0c ite eq + 2e886: 2401 moveq r4, #1 + 2e888: 2402 movne r4, #2 + 2e88a: f8c8 3018 str.w r3, [r8, #24] + 2e88e: f8c8 4010 str.w r4, [r8, #16] + 2e892: b9e6 cbnz r6, 2e8ce <__rtl_d2b_v1_00+0x8a> + 2e894: eb08 0384 add.w r3, r8, r4, lsl #2 + 2e898: f2a0 4032 subw r0, r0, #1074 ; 0x432 + 2e89c: 6038 str r0, [r7, #0] + 2e89e: 6918 ldr r0, [r3, #16] + 2e8a0: f7ff ffb2 bl 2e808 <__rtl_hi0bits_v1_00> + 2e8a4: 9b0b ldr r3, [sp, #44] ; 0x2c + 2e8a6: ebc0 1044 rsb r0, r0, r4, lsl #5 + 2e8aa: 6018 str r0, [r3, #0] + 2e8ac: 4640 mov r0, r8 + 2e8ae: b003 add sp, #12 + 2e8b0: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + 2e8b4: a801 add r0, sp, #4 + 2e8b6: f7ff fdff bl 2e4b8 <__rtl_lo0bits> + 2e8ba: 9b01 ldr r3, [sp, #4] + 2e8bc: 2201 movs r2, #1 + 2e8be: 4614 mov r4, r2 + 2e8c0: 3020 adds r0, #32 + 2e8c2: f8c8 2010 str.w r2, [r8, #16] + 2e8c6: f8c8 3014 str.w r3, [r8, #20] + 2e8ca: 2e00 cmp r6, #0 + 2e8cc: d0e2 beq.n 2e894 <__rtl_d2b_v1_00+0x50> + 2e8ce: f2a6 4933 subw r9, r6, #1075 ; 0x433 + 2e8d2: eb09 0300 add.w r3, r9, r0 + 2e8d6: 603b str r3, [r7, #0] + 2e8d8: 9b0b ldr r3, [sp, #44] ; 0x2c + 2e8da: f1c0 0035 rsb r0, r0, #53 ; 0x35 + 2e8de: 6018 str r0, [r3, #0] + 2e8e0: 4640 mov r0, r8 + 2e8e2: b003 add sp, #12 + 2e8e4: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + 2e8e8: 9b01 ldr r3, [sp, #4] + 2e8ea: f1c0 0120 rsb r1, r0, #32 + 2e8ee: 9a00 ldr r2, [sp, #0] + 2e8f0: fa03 f101 lsl.w r1, r3, r1 + 2e8f4: 430a orrs r2, r1 + 2e8f6: 40c3 lsrs r3, r0 + 2e8f8: 9301 str r3, [sp, #4] + 2e8fa: f8c8 2014 str.w r2, [r8, #20] + 2e8fe: e7c0 b.n 2e882 <__rtl_d2b_v1_00+0x3e> + +0002e900 <__rtl_lshift_v1_00>: + 2e900: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} + 2e904: 690b ldr r3, [r1, #16] + 2e906: ea4f 1b62 mov.w fp, r2, asr #5 + 2e90a: eb0b 0903 add.w r9, fp, r3 + 2e90e: 688b ldr r3, [r1, #8] + 2e910: f109 0601 add.w r6, r9, #1 + 2e914: 429e cmp r6, r3 + 2e916: 460f mov r7, r1 + 2e918: 4692 mov sl, r2 + 2e91a: 4680 mov r8, r0 + 2e91c: 6849 ldr r1, [r1, #4] + 2e91e: dd04 ble.n 2e92a <__rtl_lshift_v1_00+0x2a> + 2e920: 005b lsls r3, r3, #1 + 2e922: 429e cmp r6, r3 + 2e924: f101 0101 add.w r1, r1, #1 + 2e928: dcfa bgt.n 2e920 <__rtl_lshift_v1_00+0x20> + 2e92a: 4640 mov r0, r8 + 2e92c: f7ff fdf2 bl 2e514 <__rtl_Balloc_v1_00> + 2e930: f1bb 0f00 cmp.w fp, #0 + 2e934: f100 0414 add.w r4, r0, #20 + 2e938: dd09 ble.n 2e94e <__rtl_lshift_v1_00+0x4e> + 2e93a: 2300 movs r3, #0 + 2e93c: 461a mov r2, r3 + 2e93e: 4625 mov r5, r4 + 2e940: 3301 adds r3, #1 + 2e942: 455b cmp r3, fp + 2e944: f845 2b04 str.w r2, [r5], #4 + 2e948: d1fa bne.n 2e940 <__rtl_lshift_v1_00+0x40> + 2e94a: eb04 0483 add.w r4, r4, r3, lsl #2 + 2e94e: 693a ldr r2, [r7, #16] + 2e950: f107 0314 add.w r3, r7, #20 + 2e954: f01a 0a1f ands.w sl, sl, #31 + 2e958: eb03 0e82 add.w lr, r3, r2, lsl #2 + 2e95c: d021 beq.n 2e9a2 <__rtl_lshift_v1_00+0xa2> + 2e95e: f1ca 0c20 rsb ip, sl, #32 + 2e962: 2100 movs r1, #0 + 2e964: e000 b.n 2e968 <__rtl_lshift_v1_00+0x68> + 2e966: 462c mov r4, r5 + 2e968: 4625 mov r5, r4 + 2e96a: 681a ldr r2, [r3, #0] + 2e96c: fa02 f20a lsl.w r2, r2, sl + 2e970: 4311 orrs r1, r2 + 2e972: f845 1b04 str.w r1, [r5], #4 + 2e976: f853 1b04 ldr.w r1, [r3], #4 + 2e97a: 459e cmp lr, r3 + 2e97c: fa21 f10c lsr.w r1, r1, ip + 2e980: d8f1 bhi.n 2e966 <__rtl_lshift_v1_00+0x66> + 2e982: 6061 str r1, [r4, #4] + 2e984: b109 cbz r1, 2e98a <__rtl_lshift_v1_00+0x8a> + 2e986: f109 0602 add.w r6, r9, #2 + 2e98a: f8d8 304c ldr.w r3, [r8, #76] ; 0x4c + 2e98e: 687a ldr r2, [r7, #4] + 2e990: 3e01 subs r6, #1 + 2e992: f853 1022 ldr.w r1, [r3, r2, lsl #2] + 2e996: 6106 str r6, [r0, #16] + 2e998: 6039 str r1, [r7, #0] + 2e99a: f843 7022 str.w r7, [r3, r2, lsl #2] + 2e99e: e8bd 8ff8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, pc} + 2e9a2: f853 2b04 ldr.w r2, [r3], #4 + 2e9a6: 459e cmp lr, r3 + 2e9a8: f844 2b04 str.w r2, [r4], #4 + 2e9ac: d9ed bls.n 2e98a <__rtl_lshift_v1_00+0x8a> + 2e9ae: f853 2b04 ldr.w r2, [r3], #4 + 2e9b2: 459e cmp lr, r3 + 2e9b4: f844 2b04 str.w r2, [r4], #4 + 2e9b8: d8f3 bhi.n 2e9a2 <__rtl_lshift_v1_00+0xa2> + 2e9ba: e7e6 b.n 2e98a <__rtl_lshift_v1_00+0x8a> + +0002e9bc <__rtl_cmp_v1_00>: + 2e9bc: 6902 ldr r2, [r0, #16] + 2e9be: 690b ldr r3, [r1, #16] + 2e9c0: 1ad2 subs r2, r2, r3 + 2e9c2: d116 bne.n 2e9f2 <__rtl_cmp_v1_00+0x36> + 2e9c4: 009b lsls r3, r3, #2 + 2e9c6: 3014 adds r0, #20 + 2e9c8: 3114 adds r1, #20 + 2e9ca: 4419 add r1, r3 + 2e9cc: b410 push {r4} + 2e9ce: 4403 add r3, r0 + 2e9d0: e001 b.n 2e9d6 <__rtl_cmp_v1_00+0x1a> + 2e9d2: 4298 cmp r0, r3 + 2e9d4: d20f bcs.n 2e9f6 <__rtl_cmp_v1_00+0x3a> + 2e9d6: f853 2d04 ldr.w r2, [r3, #-4]! + 2e9da: f851 4d04 ldr.w r4, [r1, #-4]! + 2e9de: 42a2 cmp r2, r4 + 2e9e0: d0f7 beq.n 2e9d2 <__rtl_cmp_v1_00+0x16> + 2e9e2: 4294 cmp r4, r2 + 2e9e4: bf94 ite ls + 2e9e6: 2001 movls r0, #1 + 2e9e8: f04f 30ff movhi.w r0, #4294967295 + 2e9ec: f85d 4b04 ldr.w r4, [sp], #4 + 2e9f0: 4770 bx lr + 2e9f2: 4610 mov r0, r2 + 2e9f4: 4770 bx lr + 2e9f6: 2000 movs r0, #0 + 2e9f8: f85d 4b04 ldr.w r4, [sp], #4 + 2e9fc: 4770 bx lr + 2e9fe: bf00 nop + +0002ea00 <__rtl_diff_v1_00>: + 2ea00: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} + 2ea04: 460c mov r4, r1 + 2ea06: 4605 mov r5, r0 + 2ea08: 4611 mov r1, r2 + 2ea0a: 4620 mov r0, r4 + 2ea0c: 4617 mov r7, r2 + 2ea0e: f7ff ffd5 bl 2e9bc <__rtl_cmp_v1_00> + 2ea12: 1e06 subs r6, r0, #0 + 2ea14: d05e beq.n 2ead4 <__rtl_diff_v1_00+0xd4> + 2ea16: bfbc itt lt + 2ea18: 4623 movlt r3, r4 + 2ea1a: 463c movlt r4, r7 + 2ea1c: 4628 mov r0, r5 + 2ea1e: 6861 ldr r1, [r4, #4] + 2ea20: bfb6 itet lt + 2ea22: 461f movlt r7, r3 + 2ea24: f04f 0900 movge.w r9, #0 + 2ea28: f04f 0901 movlt.w r9, #1 + 2ea2c: f7ff fd72 bl 2e514 <__rtl_Balloc_v1_00> + 2ea30: f107 0214 add.w r2, r7, #20 + 2ea34: 4680 mov r8, r0 + 2ea36: 4616 mov r6, r2 + 2ea38: f8d4 e010 ldr.w lr, [r4, #16] + 2ea3c: 6938 ldr r0, [r7, #16] + 2ea3e: f104 0c14 add.w ip, r4, #20 + 2ea42: 4665 mov r5, ip + 2ea44: f8c8 900c str.w r9, [r8, #12] + 2ea48: f108 0314 add.w r3, r8, #20 + 2ea4c: eb0c 0c8e add.w ip, ip, lr, lsl #2 + 2ea50: eb02 0080 add.w r0, r2, r0, lsl #2 + 2ea54: 2100 movs r1, #0 + 2ea56: f855 4b04 ldr.w r4, [r5], #4 + 2ea5a: f856 7b04 ldr.w r7, [r6], #4 + 2ea5e: b2a2 uxth r2, r4 + 2ea60: 440a add r2, r1 + 2ea62: fa1f f987 uxth.w r9, r7 + 2ea66: 0c3f lsrs r7, r7, #16 + 2ea68: ebc9 0202 rsb r2, r9, r2 + 2ea6c: ebc7 4114 rsb r1, r7, r4, lsr #16 + 2ea70: eb01 4122 add.w r1, r1, r2, asr #16 + 2ea74: b292 uxth r2, r2 + 2ea76: ea42 4201 orr.w r2, r2, r1, lsl #16 + 2ea7a: 42b0 cmp r0, r6 + 2ea7c: f843 2b04 str.w r2, [r3], #4 + 2ea80: ea4f 4121 mov.w r1, r1, asr #16 + 2ea84: 462c mov r4, r5 + 2ea86: d8e6 bhi.n 2ea56 <__rtl_diff_v1_00+0x56> + 2ea88: 45ac cmp ip, r5 + 2ea8a: 4618 mov r0, r3 + 2ea8c: d915 bls.n 2eaba <__rtl_diff_v1_00+0xba> + 2ea8e: f854 6b04 ldr.w r6, [r4], #4 + 2ea92: b2b2 uxth r2, r6 + 2ea94: 4411 add r1, r2 + 2ea96: 0c36 lsrs r6, r6, #16 + 2ea98: eb06 4621 add.w r6, r6, r1, asr #16 + 2ea9c: b289 uxth r1, r1 + 2ea9e: ea41 4206 orr.w r2, r1, r6, lsl #16 + 2eaa2: 45a4 cmp ip, r4 + 2eaa4: f843 2b04 str.w r2, [r3], #4 + 2eaa8: ea4f 4126 mov.w r1, r6, asr #16 + 2eaac: d8ef bhi.n 2ea8e <__rtl_diff_v1_00+0x8e> + 2eaae: 43eb mvns r3, r5 + 2eab0: 4463 add r3, ip + 2eab2: f023 0303 bic.w r3, r3, #3 + 2eab6: 3304 adds r3, #4 + 2eab8: 4403 add r3, r0 + 2eaba: 3b04 subs r3, #4 + 2eabc: b92a cbnz r2, 2eaca <__rtl_diff_v1_00+0xca> + 2eabe: f853 2d04 ldr.w r2, [r3, #-4]! + 2eac2: f10e 3eff add.w lr, lr, #4294967295 + 2eac6: 2a00 cmp r2, #0 + 2eac8: d0f9 beq.n 2eabe <__rtl_diff_v1_00+0xbe> + 2eaca: 4640 mov r0, r8 + 2eacc: f8c8 e010 str.w lr, [r8, #16] + 2ead0: e8bd 83f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} + 2ead4: 4628 mov r0, r5 + 2ead6: 4631 mov r1, r6 + 2ead8: f7ff fd1c bl 2e514 <__rtl_Balloc_v1_00> + 2eadc: 2301 movs r3, #1 + 2eade: 6146 str r6, [r0, #20] + 2eae0: 6103 str r3, [r0, #16] + 2eae2: e8bd 83f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} + 2eae6: bf00 nop + +0002eae8 <__rtl_sread_v1_00>: + 2eae8: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + 2eaec: f640 34c4 movw r4, #3012 ; 0xbc4 + 2eaf0: f249 65fd movw r5, #38653 ; 0x96fd + 2eaf4: f2c1 0400 movt r4, #4096 ; 0x1000 + 2eaf8: f9b1 700e ldrsh.w r7, [r1, #14] + 2eafc: 460e mov r6, r1 + 2eafe: 4680 mov r8, r0 + 2eb00: 4611 mov r1, r2 + 2eb02: 4638 mov r0, r7 + 2eb04: 461a mov r2, r3 + 2eb06: f2c0 0502 movt r5, #2 + 2eb0a: 2300 movs r3, #0 + 2eb0c: 6023 str r3, [r4, #0] + 2eb0e: 47a8 blx r5 + 2eb10: 1c43 adds r3, r0, #1 + 2eb12: d006 beq.n 2eb22 <__rtl_sread_v1_00+0x3a> + 2eb14: 2800 cmp r0, #0 + 2eb16: db08 blt.n 2eb2a <__rtl_sread_v1_00+0x42> + 2eb18: 6d33 ldr r3, [r6, #80] ; 0x50 + 2eb1a: 4403 add r3, r0 + 2eb1c: 6533 str r3, [r6, #80] ; 0x50 + 2eb1e: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 2eb22: 6823 ldr r3, [r4, #0] + 2eb24: b10b cbz r3, 2eb2a <__rtl_sread_v1_00+0x42> + 2eb26: f8c8 3000 str.w r3, [r8] + 2eb2a: 89b3 ldrh r3, [r6, #12] + 2eb2c: f423 5380 bic.w r3, r3, #4096 ; 0x1000 + 2eb30: 81b3 strh r3, [r6, #12] + 2eb32: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 2eb36: bf00 nop + +0002eb38 <__rtl_seofread_v1_00>: + 2eb38: 2000 movs r0, #0 + 2eb3a: 4770 bx lr + +0002eb3c <__rtl_swrite_v1_00>: + 2eb3c: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} + 2eb40: f640 35c4 movw r5, #3012 ; 0xbc4 + 2eb44: 898f ldrh r7, [r1, #12] + 2eb46: 4690 mov r8, r2 + 2eb48: 05fa lsls r2, r7, #23 + 2eb4a: 460c mov r4, r1 + 2eb4c: 4681 mov r9, r0 + 2eb4e: 469a mov sl, r3 + 2eb50: bf58 it pl + 2eb52: f2c1 0500 movtpl r5, #4096 ; 0x1000 + 2eb56: d415 bmi.n 2eb84 <__rtl_swrite_v1_00+0x48> + 2eb58: f249 7611 movw r6, #38673 ; 0x9711 + 2eb5c: f427 5780 bic.w r7, r7, #4096 ; 0x1000 + 2eb60: 2300 movs r3, #0 + 2eb62: f9b4 000e ldrsh.w r0, [r4, #14] + 2eb66: 81a7 strh r7, [r4, #12] + 2eb68: 4641 mov r1, r8 + 2eb6a: 4652 mov r2, sl + 2eb6c: f2c0 0602 movt r6, #2 + 2eb70: 602b str r3, [r5, #0] + 2eb72: 47b0 blx r6 + 2eb74: f640 34c4 movw r4, #3012 ; 0xbc4 + 2eb78: 1c43 adds r3, r0, #1 + 2eb7a: f2c1 0400 movt r4, #4096 ; 0x1000 + 2eb7e: d017 beq.n 2ebb0 <__rtl_swrite_v1_00+0x74> + 2eb80: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + 2eb84: f249 63d5 movw r3, #38613 ; 0x96d5 + 2eb88: f2c1 0500 movt r5, #4096 ; 0x1000 + 2eb8c: 2600 movs r6, #0 + 2eb8e: f9b1 000e ldrsh.w r0, [r1, #14] + 2eb92: f2c0 0302 movt r3, #2 + 2eb96: 4631 mov r1, r6 + 2eb98: 2202 movs r2, #2 + 2eb9a: 602e str r6, [r5, #0] + 2eb9c: 4798 blx r3 + 2eb9e: 3001 adds r0, #1 + 2eba0: 89a7 ldrh r7, [r4, #12] + 2eba2: d1d9 bne.n 2eb58 <__rtl_swrite_v1_00+0x1c> + 2eba4: 682b ldr r3, [r5, #0] + 2eba6: 2b00 cmp r3, #0 + 2eba8: d0d6 beq.n 2eb58 <__rtl_swrite_v1_00+0x1c> + 2ebaa: f8c9 3000 str.w r3, [r9] + 2ebae: e7d3 b.n 2eb58 <__rtl_swrite_v1_00+0x1c> + 2ebb0: 6823 ldr r3, [r4, #0] + 2ebb2: 2b00 cmp r3, #0 + 2ebb4: d0e4 beq.n 2eb80 <__rtl_swrite_v1_00+0x44> + 2ebb6: f8c9 3000 str.w r3, [r9] + 2ebba: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + 2ebbe: bf00 nop + +0002ebc0 <__rtl_sseek_v1_00>: + 2ebc0: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + 2ebc4: f640 35c4 movw r5, #3012 ; 0xbc4 + 2ebc8: f249 66d5 movw r6, #38613 ; 0x96d5 + 2ebcc: f2c1 0500 movt r5, #4096 ; 0x1000 + 2ebd0: f9b1 700e ldrsh.w r7, [r1, #14] + 2ebd4: 460c mov r4, r1 + 2ebd6: 4680 mov r8, r0 + 2ebd8: 4611 mov r1, r2 + 2ebda: 4638 mov r0, r7 + 2ebdc: 461a mov r2, r3 + 2ebde: f2c0 0602 movt r6, #2 + 2ebe2: 2300 movs r3, #0 + 2ebe4: 602b str r3, [r5, #0] + 2ebe6: 47b0 blx r6 + 2ebe8: 1c43 adds r3, r0, #1 + 2ebea: d006 beq.n 2ebfa <__rtl_sseek_v1_00+0x3a> + 2ebec: 89a3 ldrh r3, [r4, #12] + 2ebee: 6520 str r0, [r4, #80] ; 0x50 + 2ebf0: f443 5380 orr.w r3, r3, #4096 ; 0x1000 + 2ebf4: 81a3 strh r3, [r4, #12] + 2ebf6: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 2ebfa: 682b ldr r3, [r5, #0] + 2ebfc: b10b cbz r3, 2ec02 <__rtl_sseek_v1_00+0x42> + 2ebfe: f8c8 3000 str.w r3, [r8] + 2ec02: 89a3 ldrh r3, [r4, #12] + 2ec04: f423 5380 bic.w r3, r3, #4096 ; 0x1000 + 2ec08: 81a3 strh r3, [r4, #12] + 2ec0a: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 2ec0e: bf00 nop + +0002ec10 <__rtl_sclose_v1_00>: + 2ec10: b538 push {r3, r4, r5, lr} + 2ec12: f640 34c4 movw r4, #3012 ; 0xbc4 + 2ec16: f249 6399 movw r3, #38553 ; 0x9699 + 2ec1a: f2c1 0400 movt r4, #4096 ; 0x1000 + 2ec1e: f9b1 100e ldrsh.w r1, [r1, #14] + 2ec22: 2200 movs r2, #0 + 2ec24: f2c0 0302 movt r3, #2 + 2ec28: 4605 mov r5, r0 + 2ec2a: 4608 mov r0, r1 + 2ec2c: 6022 str r2, [r4, #0] + 2ec2e: 4798 blx r3 + 2ec30: 1c43 adds r3, r0, #1 + 2ec32: d000 beq.n 2ec36 <__rtl_sclose_v1_00+0x26> + 2ec34: bd38 pop {r3, r4, r5, pc} + 2ec36: 6823 ldr r3, [r4, #0] + 2ec38: 2b00 cmp r3, #0 + 2ec3a: d0fb beq.n 2ec34 <__rtl_sclose_v1_00+0x24> + 2ec3c: 602b str r3, [r5, #0] + 2ec3e: bd38 pop {r3, r4, r5, pc} + +0002ec40 <__rtl_sbrk_r_v1_00>: + 2ec40: b538 push {r3, r4, r5, lr} + 2ec42: f640 34c4 movw r4, #3012 ; 0xbc4 + 2ec46: f249 7325 movw r3, #38693 ; 0x9725 + 2ec4a: f2c1 0400 movt r4, #4096 ; 0x1000 + 2ec4e: 2200 movs r2, #0 + 2ec50: f2c0 0302 movt r3, #2 + 2ec54: 4605 mov r5, r0 + 2ec56: 4608 mov r0, r1 + 2ec58: 6022 str r2, [r4, #0] + 2ec5a: 4798 blx r3 + 2ec5c: 1c43 adds r3, r0, #1 + 2ec5e: d000 beq.n 2ec62 <__rtl_sbrk_r_v1_00+0x22> + 2ec60: bd38 pop {r3, r4, r5, pc} + 2ec62: 6823 ldr r3, [r4, #0] + 2ec64: 2b00 cmp r3, #0 + 2ec66: d0fb beq.n 2ec60 <__rtl_sbrk_r_v1_00+0x20> + 2ec68: 602b str r3, [r5, #0] + 2ec6a: bd38 pop {r3, r4, r5, pc} + +0002ec6c <__rtl_sflush_r_v1_00>: + 2ec6c: 898b ldrh r3, [r1, #12] + 2ec6e: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} + 2ec72: b29a uxth r2, r3 + 2ec74: 460d mov r5, r1 + 2ec76: 0711 lsls r1, r2, #28 + 2ec78: 4680 mov r8, r0 + 2ec7a: d43f bmi.n 2ecfc <__rtl_sflush_r_v1_00+0x90> + 2ec7c: 686a ldr r2, [r5, #4] + 2ec7e: f443 6300 orr.w r3, r3, #2048 ; 0x800 + 2ec82: 2a00 cmp r2, #0 + 2ec84: 81ab strh r3, [r5, #12] + 2ec86: dd5c ble.n 2ed42 <__rtl_sflush_r_v1_00+0xd6> + 2ec88: 6aac ldr r4, [r5, #40] ; 0x28 + 2ec8a: 2c00 cmp r4, #0 + 2ec8c: d04e beq.n 2ed2c <__rtl_sflush_r_v1_00+0xc0> + 2ec8e: b29b uxth r3, r3 + 2ec90: f403 5680 and.w r6, r3, #4096 ; 0x1000 + 2ec94: 2200 movs r2, #0 + 2ec96: b2b6 uxth r6, r6 + 2ec98: f8d8 7000 ldr.w r7, [r8] + 2ec9c: f8c8 2000 str.w r2, [r8] + 2eca0: 2e00 cmp r6, #0 + 2eca2: d052 beq.n 2ed4a <__rtl_sflush_r_v1_00+0xde> + 2eca4: 6d2a ldr r2, [r5, #80] ; 0x50 + 2eca6: 075e lsls r6, r3, #29 + 2eca8: d505 bpl.n 2ecb6 <__rtl_sflush_r_v1_00+0x4a> + 2ecaa: 6869 ldr r1, [r5, #4] + 2ecac: 6b2b ldr r3, [r5, #48] ; 0x30 + 2ecae: 1a52 subs r2, r2, r1 + 2ecb0: b10b cbz r3, 2ecb6 <__rtl_sflush_r_v1_00+0x4a> + 2ecb2: 6beb ldr r3, [r5, #60] ; 0x3c + 2ecb4: 1ad2 subs r2, r2, r3 + 2ecb6: 4640 mov r0, r8 + 2ecb8: 69e9 ldr r1, [r5, #28] + 2ecba: 2300 movs r3, #0 + 2ecbc: 47a0 blx r4 + 2ecbe: 1c44 adds r4, r0, #1 + 2ecc0: d04e beq.n 2ed60 <__rtl_sflush_r_v1_00+0xf4> + 2ecc2: 89ab ldrh r3, [r5, #12] + 2ecc4: 692a ldr r2, [r5, #16] + 2ecc6: f423 6300 bic.w r3, r3, #2048 ; 0x800 + 2ecca: b29b uxth r3, r3 + 2eccc: 2100 movs r1, #0 + 2ecce: 602a str r2, [r5, #0] + 2ecd0: 04da lsls r2, r3, #19 + 2ecd2: 81ab strh r3, [r5, #12] + 2ecd4: 6069 str r1, [r5, #4] + 2ecd6: d450 bmi.n 2ed7a <__rtl_sflush_r_v1_00+0x10e> + 2ecd8: 6b29 ldr r1, [r5, #48] ; 0x30 + 2ecda: f8c8 7000 str.w r7, [r8] + 2ecde: b329 cbz r1, 2ed2c <__rtl_sflush_r_v1_00+0xc0> + 2ece0: f105 0340 add.w r3, r5, #64 ; 0x40 + 2ece4: 4299 cmp r1, r3 + 2ece6: d005 beq.n 2ecf4 <__rtl_sflush_r_v1_00+0x88> + 2ece8: f64d 0341 movw r3, #55361 ; 0xd841 + 2ecec: 4640 mov r0, r8 + 2ecee: f2c0 0302 movt r3, #2 + 2ecf2: 4798 blx r3 + 2ecf4: 2000 movs r0, #0 + 2ecf6: 6328 str r0, [r5, #48] ; 0x30 + 2ecf8: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 2ecfc: 692e ldr r6, [r5, #16] + 2ecfe: b1ae cbz r6, 2ed2c <__rtl_sflush_r_v1_00+0xc0> + 2ed00: 0791 lsls r1, r2, #30 + 2ed02: 682c ldr r4, [r5, #0] + 2ed04: bf0c ite eq + 2ed06: 696b ldreq r3, [r5, #20] + 2ed08: 2300 movne r3, #0 + 2ed0a: 602e str r6, [r5, #0] + 2ed0c: 1ba4 subs r4, r4, r6 + 2ed0e: 60ab str r3, [r5, #8] + 2ed10: e00a b.n 2ed28 <__rtl_sflush_r_v1_00+0xbc> + 2ed12: 4632 mov r2, r6 + 2ed14: 4623 mov r3, r4 + 2ed16: 6a6f ldr r7, [r5, #36] ; 0x24 + 2ed18: 4640 mov r0, r8 + 2ed1a: 69e9 ldr r1, [r5, #28] + 2ed1c: 47b8 blx r7 + 2ed1e: 2800 cmp r0, #0 + 2ed20: eba4 0400 sub.w r4, r4, r0 + 2ed24: 4406 add r6, r0 + 2ed26: dd04 ble.n 2ed32 <__rtl_sflush_r_v1_00+0xc6> + 2ed28: 2c00 cmp r4, #0 + 2ed2a: dcf2 bgt.n 2ed12 <__rtl_sflush_r_v1_00+0xa6> + 2ed2c: 2000 movs r0, #0 + 2ed2e: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 2ed32: 89ab ldrh r3, [r5, #12] + 2ed34: f04f 30ff mov.w r0, #4294967295 + 2ed38: f043 0340 orr.w r3, r3, #64 ; 0x40 + 2ed3c: 81ab strh r3, [r5, #12] + 2ed3e: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 2ed42: 6bea ldr r2, [r5, #60] ; 0x3c + 2ed44: 2a00 cmp r2, #0 + 2ed46: dc9f bgt.n 2ec88 <__rtl_sflush_r_v1_00+0x1c> + 2ed48: e7f0 b.n 2ed2c <__rtl_sflush_r_v1_00+0xc0> + 2ed4a: 4632 mov r2, r6 + 2ed4c: 2301 movs r3, #1 + 2ed4e: 4640 mov r0, r8 + 2ed50: 69e9 ldr r1, [r5, #28] + 2ed52: 47a0 blx r4 + 2ed54: 1c43 adds r3, r0, #1 + 2ed56: 4602 mov r2, r0 + 2ed58: d01e beq.n 2ed98 <__rtl_sflush_r_v1_00+0x12c> + 2ed5a: 89ab ldrh r3, [r5, #12] + 2ed5c: 6aac ldr r4, [r5, #40] ; 0x28 + 2ed5e: e7a2 b.n 2eca6 <__rtl_sflush_r_v1_00+0x3a> + 2ed60: f8d8 3000 ldr.w r3, [r8] + 2ed64: b95b cbnz r3, 2ed7e <__rtl_sflush_r_v1_00+0x112> + 2ed66: 89aa ldrh r2, [r5, #12] + 2ed68: 6929 ldr r1, [r5, #16] + 2ed6a: f422 6200 bic.w r2, r2, #2048 ; 0x800 + 2ed6e: b292 uxth r2, r2 + 2ed70: 606b str r3, [r5, #4] + 2ed72: 04d3 lsls r3, r2, #19 + 2ed74: 81aa strh r2, [r5, #12] + 2ed76: 6029 str r1, [r5, #0] + 2ed78: d5ae bpl.n 2ecd8 <__rtl_sflush_r_v1_00+0x6c> + 2ed7a: 6528 str r0, [r5, #80] ; 0x50 + 2ed7c: e7ac b.n 2ecd8 <__rtl_sflush_r_v1_00+0x6c> + 2ed7e: 2b1d cmp r3, #29 + 2ed80: d001 beq.n 2ed86 <__rtl_sflush_r_v1_00+0x11a> + 2ed82: 2b16 cmp r3, #22 + 2ed84: d115 bne.n 2edb2 <__rtl_sflush_r_v1_00+0x146> + 2ed86: 89a9 ldrh r1, [r5, #12] + 2ed88: 692b ldr r3, [r5, #16] + 2ed8a: f421 6100 bic.w r1, r1, #2048 ; 0x800 + 2ed8e: 2200 movs r2, #0 + 2ed90: 81a9 strh r1, [r5, #12] + 2ed92: 602b str r3, [r5, #0] + 2ed94: 606a str r2, [r5, #4] + 2ed96: e79f b.n 2ecd8 <__rtl_sflush_r_v1_00+0x6c> + 2ed98: f8d8 3000 ldr.w r3, [r8] + 2ed9c: 2b00 cmp r3, #0 + 2ed9e: d0dc beq.n 2ed5a <__rtl_sflush_r_v1_00+0xee> + 2eda0: 2b1d cmp r3, #29 + 2eda2: bf18 it ne + 2eda4: 2b16 cmpne r3, #22 + 2eda6: d1c4 bne.n 2ed32 <__rtl_sflush_r_v1_00+0xc6> + 2eda8: f8c8 7000 str.w r7, [r8] + 2edac: 4630 mov r0, r6 + 2edae: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 2edb2: 89ab ldrh r3, [r5, #12] + 2edb4: f043 0340 orr.w r3, r3, #64 ; 0x40 + 2edb8: 81ab strh r3, [r5, #12] + 2edba: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + 2edbe: bf00 nop + +0002edc0 <__rtl_sinit.part.3>: + 2edc0: f64e 7251 movw r2, #61265 ; 0xef51 + 2edc4: f648 43b5 movw r3, #36021 ; 0x8cb5 + 2edc8: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 2edcc: f64e 2be9 movw fp, #60137 ; 0xeae9 + 2edd0: f64e 3a3d movw sl, #60221 ; 0xeb3d + 2edd4: f64e 39c1 movw r9, #60353 ; 0xebc1 + 2edd8: f64e 4811 movw r8, #60433 ; 0xec11 + 2eddc: 4607 mov r7, r0 + 2edde: f2c0 0302 movt r3, #2 + 2ede2: f2c0 0202 movt r2, #2 + 2ede6: f2c0 0b02 movt fp, #2 + 2edea: f2c0 0a02 movt sl, #2 + 2edee: f2c0 0902 movt r9, #2 + 2edf2: f2c0 0802 movt r8, #2 + 2edf6: 6845 ldr r5, [r0, #4] + 2edf8: 2400 movs r4, #0 + 2edfa: b083 sub sp, #12 + 2edfc: 2603 movs r6, #3 + 2edfe: f500 703b add.w r0, r0, #748 ; 0x2ec + 2ee02: 2104 movs r1, #4 + 2ee04: 63fa str r2, [r7, #60] ; 0x3c + 2ee06: f8c7 62e4 str.w r6, [r7, #740] ; 0x2e4 + 2ee0a: f8c7 02e8 str.w r0, [r7, #744] ; 0x2e8 + 2ee0e: f8c7 42e0 str.w r4, [r7, #736] ; 0x2e0 + 2ee12: f105 005c add.w r0, r5, #92 ; 0x5c + 2ee16: 602c str r4, [r5, #0] + 2ee18: 606c str r4, [r5, #4] + 2ee1a: 60ac str r4, [r5, #8] + 2ee1c: 666c str r4, [r5, #100] ; 0x64 + 2ee1e: 81ec strh r4, [r5, #14] + 2ee20: 612c str r4, [r5, #16] + 2ee22: 616c str r4, [r5, #20] + 2ee24: 61ac str r4, [r5, #24] + 2ee26: 81a9 strh r1, [r5, #12] + 2ee28: 2208 movs r2, #8 + 2ee2a: 4621 mov r1, r4 + 2ee2c: 9301 str r3, [sp, #4] + 2ee2e: 4798 blx r3 + 2ee30: 68be ldr r6, [r7, #8] + 2ee32: f04f 0c01 mov.w ip, #1 + 2ee36: 2209 movs r2, #9 + 2ee38: f8c5 b020 str.w fp, [r5, #32] + 2ee3c: f8c5 a024 str.w sl, [r5, #36] ; 0x24 + 2ee40: f8c5 9028 str.w r9, [r5, #40] ; 0x28 + 2ee44: f8c5 802c str.w r8, [r5, #44] ; 0x2c + 2ee48: 61ed str r5, [r5, #28] + 2ee4a: 4621 mov r1, r4 + 2ee4c: f8a6 c00e strh.w ip, [r6, #14] + 2ee50: 81b2 strh r2, [r6, #12] + 2ee52: 6034 str r4, [r6, #0] + 2ee54: 6074 str r4, [r6, #4] + 2ee56: 60b4 str r4, [r6, #8] + 2ee58: 6674 str r4, [r6, #100] ; 0x64 + 2ee5a: 6134 str r4, [r6, #16] + 2ee5c: 6174 str r4, [r6, #20] + 2ee5e: 61b4 str r4, [r6, #24] + 2ee60: 9b01 ldr r3, [sp, #4] + 2ee62: f8cd c000 str.w ip, [sp] + 2ee66: f106 005c add.w r0, r6, #92 ; 0x5c + 2ee6a: 2208 movs r2, #8 + 2ee6c: 4798 blx r3 + 2ee6e: 68fd ldr r5, [r7, #12] + 2ee70: 2012 movs r0, #18 + 2ee72: 2202 movs r2, #2 + 2ee74: 61f6 str r6, [r6, #28] + 2ee76: f8c6 b020 str.w fp, [r6, #32] + 2ee7a: f8c6 a024 str.w sl, [r6, #36] ; 0x24 + 2ee7e: f8c6 9028 str.w r9, [r6, #40] ; 0x28 + 2ee82: f8c6 802c str.w r8, [r6, #44] ; 0x2c + 2ee86: 4621 mov r1, r4 + 2ee88: 81a8 strh r0, [r5, #12] + 2ee8a: 81ea strh r2, [r5, #14] + 2ee8c: 602c str r4, [r5, #0] + 2ee8e: 606c str r4, [r5, #4] + 2ee90: 60ac str r4, [r5, #8] + 2ee92: 666c str r4, [r5, #100] ; 0x64 + 2ee94: 612c str r4, [r5, #16] + 2ee96: 616c str r4, [r5, #20] + 2ee98: 61ac str r4, [r5, #24] + 2ee9a: f105 005c add.w r0, r5, #92 ; 0x5c + 2ee9e: 2208 movs r2, #8 + 2eea0: 9b01 ldr r3, [sp, #4] + 2eea2: 4798 blx r3 + 2eea4: f8dd c000 ldr.w ip, [sp] + 2eea8: 61ed str r5, [r5, #28] + 2eeaa: f8c5 b020 str.w fp, [r5, #32] + 2eeae: f8c5 a024 str.w sl, [r5, #36] ; 0x24 + 2eeb2: f8c5 9028 str.w r9, [r5, #40] ; 0x28 + 2eeb6: f8c5 802c str.w r8, [r5, #44] ; 0x2c + 2eeba: f8c7 c038 str.w ip, [r7, #56] ; 0x38 + 2eebe: b003 add sp, #12 + 2eec0: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +0002eec4 <__rtl_fclose_r>: + 2eec4: b570 push {r4, r5, r6, lr} + 2eec6: 460c mov r4, r1 + 2eec8: b139 cbz r1, 2eeda <__rtl_fclose_r+0x16> + 2eeca: 4605 mov r5, r0 + 2eecc: b110 cbz r0, 2eed4 <__rtl_fclose_r+0x10> + 2eece: 6b83 ldr r3, [r0, #56] ; 0x38 + 2eed0: 2b00 cmp r3, #0 + 2eed2: d032 beq.n 2ef3a <__rtl_fclose_r+0x76> + 2eed4: f9b4 300c ldrsh.w r3, [r4, #12] + 2eed8: b90b cbnz r3, 2eede <__rtl_fclose_r+0x1a> + 2eeda: 2000 movs r0, #0 + 2eedc: bd70 pop {r4, r5, r6, pc} + 2eede: 4628 mov r0, r5 + 2eee0: 4621 mov r1, r4 + 2eee2: f7ff fec3 bl 2ec6c <__rtl_sflush_r_v1_00> + 2eee6: 6ae3 ldr r3, [r4, #44] ; 0x2c + 2eee8: 4606 mov r6, r0 + 2eeea: b13b cbz r3, 2eefc <__rtl_fclose_r+0x38> + 2eeec: 4628 mov r0, r5 + 2eeee: 69e1 ldr r1, [r4, #28] + 2eef0: 4798 blx r3 + 2eef2: ea36 0620 bics.w r6, r6, r0, asr #32 + 2eef6: bf28 it cs + 2eef8: f04f 36ff movcs.w r6, #4294967295 + 2eefc: 89a3 ldrh r3, [r4, #12] + 2eefe: 061b lsls r3, r3, #24 + 2ef00: d41e bmi.n 2ef40 <__rtl_fclose_r+0x7c> + 2ef02: 6b21 ldr r1, [r4, #48] ; 0x30 + 2ef04: b159 cbz r1, 2ef1e <__rtl_fclose_r+0x5a> + 2ef06: f104 0340 add.w r3, r4, #64 ; 0x40 + 2ef0a: 4299 cmp r1, r3 + 2ef0c: d005 beq.n 2ef1a <__rtl_fclose_r+0x56> + 2ef0e: f64d 0341 movw r3, #55361 ; 0xd841 + 2ef12: 4628 mov r0, r5 + 2ef14: f2c0 0302 movt r3, #2 + 2ef18: 4798 blx r3 + 2ef1a: 2300 movs r3, #0 + 2ef1c: 6323 str r3, [r4, #48] ; 0x30 + 2ef1e: 6c61 ldr r1, [r4, #68] ; 0x44 + 2ef20: b139 cbz r1, 2ef32 <__rtl_fclose_r+0x6e> + 2ef22: f64d 0341 movw r3, #55361 ; 0xd841 + 2ef26: 4628 mov r0, r5 + 2ef28: f2c0 0302 movt r3, #2 + 2ef2c: 4798 blx r3 + 2ef2e: 2300 movs r3, #0 + 2ef30: 6463 str r3, [r4, #68] ; 0x44 + 2ef32: 2300 movs r3, #0 + 2ef34: 4630 mov r0, r6 + 2ef36: 81a3 strh r3, [r4, #12] + 2ef38: bd70 pop {r4, r5, r6, pc} + 2ef3a: f7ff ff41 bl 2edc0 <__rtl_sinit.part.3> + 2ef3e: e7c9 b.n 2eed4 <__rtl_fclose_r+0x10> + 2ef40: f64d 0341 movw r3, #55361 ; 0xd841 + 2ef44: 4628 mov r0, r5 + 2ef46: f2c0 0302 movt r3, #2 + 2ef4a: 6921 ldr r1, [r4, #16] + 2ef4c: 4798 blx r3 + 2ef4e: e7d8 b.n 2ef02 <__rtl_fclose_r+0x3e> + +0002ef50 <__rtl_cleanup_r>: + 2ef50: b5f8 push {r3, r4, r5, r6, r7, lr} + 2ef52: f510 7638 adds.w r6, r0, #736 ; 0x2e0 + 2ef56: 4607 mov r7, r0 + 2ef58: d017 beq.n 2ef8a <__rtl_cleanup_r+0x3a> + 2ef5a: 6875 ldr r5, [r6, #4] + 2ef5c: 68b4 ldr r4, [r6, #8] + 2ef5e: 3d01 subs r5, #1 + 2ef60: d40f bmi.n 2ef82 <__rtl_cleanup_r+0x32> + 2ef62: 89a3 ldrh r3, [r4, #12] + 2ef64: 3d01 subs r5, #1 + 2ef66: 2b01 cmp r3, #1 + 2ef68: d907 bls.n 2ef7a <__rtl_cleanup_r+0x2a> + 2ef6a: f9b4 300e ldrsh.w r3, [r4, #14] + 2ef6e: 3301 adds r3, #1 + 2ef70: d003 beq.n 2ef7a <__rtl_cleanup_r+0x2a> + 2ef72: 4638 mov r0, r7 + 2ef74: 4621 mov r1, r4 + 2ef76: f7ff ffa5 bl 2eec4 <__rtl_fclose_r> + 2ef7a: 1c6b adds r3, r5, #1 + 2ef7c: f104 0468 add.w r4, r4, #104 ; 0x68 + 2ef80: d1ef bne.n 2ef62 <__rtl_cleanup_r+0x12> + 2ef82: 6836 ldr r6, [r6, #0] + 2ef84: 2e00 cmp r6, #0 + 2ef86: d1e8 bne.n 2ef5a <__rtl_cleanup_r+0xa> + 2ef88: bdf8 pop {r3, r4, r5, r6, r7, pc} + 2ef8a: bdf8 pop {r3, r4, r5, r6, r7, pc} + +0002ef8c <__rtl_fflush_r_v1_00>: + 2ef8c: b510 push {r4, lr} + 2ef8e: 4604 mov r4, r0 + 2ef90: b082 sub sp, #8 + 2ef92: b108 cbz r0, 2ef98 <__rtl_fflush_r_v1_00+0xc> + 2ef94: 6b83 ldr r3, [r0, #56] ; 0x38 + 2ef96: b14b cbz r3, 2efac <__rtl_fflush_r_v1_00+0x20> + 2ef98: f9b1 000c ldrsh.w r0, [r1, #12] + 2ef9c: b908 cbnz r0, 2efa2 <__rtl_fflush_r_v1_00+0x16> + 2ef9e: b002 add sp, #8 + 2efa0: bd10 pop {r4, pc} + 2efa2: 4620 mov r0, r4 + 2efa4: b002 add sp, #8 + 2efa6: e8bd 4010 ldmia.w sp!, {r4, lr} + 2efaa: e65f b.n 2ec6c <__rtl_sflush_r_v1_00> + 2efac: 9101 str r1, [sp, #4] + 2efae: f7ff ff07 bl 2edc0 <__rtl_sinit.part.3> + 2efb2: 9901 ldr r1, [sp, #4] + 2efb4: e7f0 b.n 2ef98 <__rtl_fflush_r_v1_00+0xc> + 2efb6: bf00 nop + +0002efb8 <__rtl_swsetup_r>: + 2efb8: f641 4360 movw r3, #7264 ; 0x1c60 + 2efbc: f2c1 0300 movt r3, #4096 ; 0x1000 + 2efc0: b5f0 push {r4, r5, r6, r7, lr} + 2efc2: 681b ldr r3, [r3, #0] + 2efc4: b091 sub sp, #68 ; 0x44 + 2efc6: 4606 mov r6, r0 + 2efc8: 460c mov r4, r1 + 2efca: b11b cbz r3, 2efd4 <__rtl_swsetup_r+0x1c> + 2efcc: 6b9a ldr r2, [r3, #56] ; 0x38 + 2efce: 2a00 cmp r2, #0 + 2efd0: f000 808f beq.w 2f0f2 <__rtl_swsetup_r+0x13a> + 2efd4: 89a2 ldrh r2, [r4, #12] + 2efd6: b293 uxth r3, r2 + 2efd8: 071f lsls r7, r3, #28 + 2efda: d50e bpl.n 2effa <__rtl_swsetup_r+0x42> + 2efdc: 6925 ldr r5, [r4, #16] + 2efde: b1c5 cbz r5, 2f012 <__rtl_swsetup_r+0x5a> + 2efe0: f013 0201 ands.w r2, r3, #1 + 2efe4: d05d beq.n 2f0a2 <__rtl_swsetup_r+0xea> + 2efe6: 6963 ldr r3, [r4, #20] + 2efe8: 2200 movs r2, #0 + 2efea: 425b negs r3, r3 + 2efec: 61a3 str r3, [r4, #24] + 2efee: 60a2 str r2, [r4, #8] + 2eff0: 2d00 cmp r5, #0 + 2eff2: d05c beq.n 2f0ae <__rtl_swsetup_r+0xf6> + 2eff4: 2000 movs r0, #0 + 2eff6: b011 add sp, #68 ; 0x44 + 2eff8: bdf0 pop {r4, r5, r6, r7, pc} + 2effa: 06dd lsls r5, r3, #27 + 2effc: f140 8084 bpl.w 2f108 <__rtl_swsetup_r+0x150> + 2f000: 0758 lsls r0, r3, #29 + 2f002: d45e bmi.n 2f0c2 <__rtl_swsetup_r+0x10a> + 2f004: 6925 ldr r5, [r4, #16] + 2f006: f042 0208 orr.w r2, r2, #8 + 2f00a: 81a2 strh r2, [r4, #12] + 2f00c: b293 uxth r3, r2 + 2f00e: 2d00 cmp r5, #0 + 2f010: d1e6 bne.n 2efe0 <__rtl_swsetup_r+0x28> + 2f012: f403 7120 and.w r1, r3, #640 ; 0x280 + 2f016: f5b1 7f00 cmp.w r1, #512 ; 0x200 + 2f01a: d0e1 beq.n 2efe0 <__rtl_swsetup_r+0x28> + 2f01c: 0799 lsls r1, r3, #30 + 2f01e: d46c bmi.n 2f0fa <__rtl_swsetup_r+0x142> + 2f020: f9b4 000e ldrsh.w r0, [r4, #14] + 2f024: 2800 cmp r0, #0 + 2f026: db7c blt.n 2f122 <__rtl_swsetup_r+0x16a> + 2f028: f640 37c4 movw r7, #3012 ; 0xbc4 + 2f02c: f249 63ad movw r3, #38573 ; 0x96ad + 2f030: f2c1 0700 movt r7, #4096 ; 0x1000 + 2f034: f2c0 0302 movt r3, #2 + 2f038: a901 add r1, sp, #4 + 2f03a: 603d str r5, [r7, #0] + 2f03c: 4798 blx r3 + 2f03e: 1c43 adds r3, r0, #1 + 2f040: d06a beq.n 2f118 <__rtl_swsetup_r+0x160> + 2f042: 2800 cmp r0, #0 + 2f044: db6b blt.n 2f11e <__rtl_swsetup_r+0x166> + 2f046: 9b02 ldr r3, [sp, #8] + 2f048: f403 4370 and.w r3, r3, #61440 ; 0xf000 + 2f04c: f5a3 5700 sub.w r7, r3, #8192 ; 0x2000 + 2f050: fab7 f787 clz r7, r7 + 2f054: f5b3 4f00 cmp.w r3, #32768 ; 0x8000 + 2f058: ea4f 1757 mov.w r7, r7, lsr #5 + 2f05c: f000 8099 beq.w 2f192 <__rtl_swsetup_r+0x1da> + 2f060: 89a3 ldrh r3, [r4, #12] + 2f062: f44f 6580 mov.w r5, #1024 ; 0x400 + 2f066: f443 6300 orr.w r3, r3, #2048 ; 0x800 + 2f06a: 81a3 strh r3, [r4, #12] + 2f06c: f64d 2331 movw r3, #55857 ; 0xda31 + 2f070: 4630 mov r0, r6 + 2f072: f2c0 0302 movt r3, #2 + 2f076: 4629 mov r1, r5 + 2f078: 4798 blx r3 + 2f07a: 2800 cmp r0, #0 + 2f07c: d06f beq.n 2f15e <__rtl_swsetup_r+0x1a6> + 2f07e: f64e 7351 movw r3, #61265 ; 0xef51 + 2f082: f2c0 0302 movt r3, #2 + 2f086: 89a2 ldrh r2, [r4, #12] + 2f088: 63f3 str r3, [r6, #60] ; 0x3c + 2f08a: f042 0380 orr.w r3, r2, #128 ; 0x80 + 2f08e: b29b uxth r3, r3 + 2f090: 6020 str r0, [r4, #0] + 2f092: 6120 str r0, [r4, #16] + 2f094: 6165 str r5, [r4, #20] + 2f096: 81a3 strh r3, [r4, #12] + 2f098: 2f00 cmp r7, #0 + 2f09a: d14d bne.n 2f138 <__rtl_swsetup_r+0x180> + 2f09c: b29b uxth r3, r3 + 2f09e: 4605 mov r5, r0 + 2f0a0: e79e b.n 2efe0 <__rtl_swsetup_r+0x28> + 2f0a2: 0799 lsls r1, r3, #30 + 2f0a4: bf58 it pl + 2f0a6: 6962 ldrpl r2, [r4, #20] + 2f0a8: 60a2 str r2, [r4, #8] + 2f0aa: 2d00 cmp r5, #0 + 2f0ac: d1a2 bne.n 2eff4 <__rtl_swsetup_r+0x3c> + 2f0ae: 89a3 ldrh r3, [r4, #12] + 2f0b0: 061a lsls r2, r3, #24 + 2f0b2: bf42 ittt mi + 2f0b4: f043 0340 orrmi.w r3, r3, #64 ; 0x40 + 2f0b8: 81a3 strhmi r3, [r4, #12] + 2f0ba: f04f 30ff movmi.w r0, #4294967295 + 2f0be: d49a bmi.n 2eff6 <__rtl_swsetup_r+0x3e> + 2f0c0: e798 b.n 2eff4 <__rtl_swsetup_r+0x3c> + 2f0c2: 6b21 ldr r1, [r4, #48] ; 0x30 + 2f0c4: b161 cbz r1, 2f0e0 <__rtl_swsetup_r+0x128> + 2f0c6: f104 0340 add.w r3, r4, #64 ; 0x40 + 2f0ca: 4299 cmp r1, r3 + 2f0cc: d006 beq.n 2f0dc <__rtl_swsetup_r+0x124> + 2f0ce: f64d 0341 movw r3, #55361 ; 0xd841 + 2f0d2: 4630 mov r0, r6 + 2f0d4: f2c0 0302 movt r3, #2 + 2f0d8: 4798 blx r3 + 2f0da: 89a2 ldrh r2, [r4, #12] + 2f0dc: 2300 movs r3, #0 + 2f0de: 6323 str r3, [r4, #48] ; 0x30 + 2f0e0: f022 0224 bic.w r2, r2, #36 ; 0x24 + 2f0e4: 6925 ldr r5, [r4, #16] + 2f0e6: 0412 lsls r2, r2, #16 + 2f0e8: 2300 movs r3, #0 + 2f0ea: 0c12 lsrs r2, r2, #16 + 2f0ec: 6025 str r5, [r4, #0] + 2f0ee: 6063 str r3, [r4, #4] + 2f0f0: e789 b.n 2f006 <__rtl_swsetup_r+0x4e> + 2f0f2: 4618 mov r0, r3 + 2f0f4: f7ff fe64 bl 2edc0 <__rtl_sinit.part.3> + 2f0f8: e76c b.n 2efd4 <__rtl_swsetup_r+0x1c> + 2f0fa: f104 0543 add.w r5, r4, #67 ; 0x43 + 2f0fe: 2201 movs r2, #1 + 2f100: 6025 str r5, [r4, #0] + 2f102: 6125 str r5, [r4, #16] + 2f104: 6162 str r2, [r4, #20] + 2f106: e76b b.n 2efe0 <__rtl_swsetup_r+0x28> + 2f108: f042 0240 orr.w r2, r2, #64 ; 0x40 + 2f10c: 2309 movs r3, #9 + 2f10e: 6033 str r3, [r6, #0] + 2f110: f04f 30ff mov.w r0, #4294967295 + 2f114: 81a2 strh r2, [r4, #12] + 2f116: e76e b.n 2eff6 <__rtl_swsetup_r+0x3e> + 2f118: 683b ldr r3, [r7, #0] + 2f11a: b103 cbz r3, 2f11e <__rtl_swsetup_r+0x166> + 2f11c: 6033 str r3, [r6, #0] + 2f11e: 89a2 ldrh r2, [r4, #12] + 2f120: b293 uxth r3, r2 + 2f122: f013 0f80 tst.w r3, #128 ; 0x80 + 2f126: f442 6200 orr.w r2, r2, #2048 ; 0x800 + 2f12a: 81a2 strh r2, [r4, #12] + 2f12c: bf14 ite ne + 2f12e: 2540 movne r5, #64 ; 0x40 + 2f130: f44f 6580 moveq.w r5, #1024 ; 0x400 + 2f134: 2700 movs r7, #0 + 2f136: e799 b.n 2f06c <__rtl_swsetup_r+0xb4> + 2f138: f640 35c4 movw r5, #3012 ; 0xbc4 + 2f13c: f249 63c1 movw r3, #38593 ; 0x96c1 + 2f140: f2c1 0500 movt r5, #4096 ; 0x1000 + 2f144: 2200 movs r2, #0 + 2f146: f9b4 000e ldrsh.w r0, [r4, #14] + 2f14a: f2c0 0302 movt r3, #2 + 2f14e: 602a str r2, [r5, #0] + 2f150: 4798 blx r3 + 2f152: 1c47 adds r7, r0, #1 + 2f154: d012 beq.n 2f17c <__rtl_swsetup_r+0x1c4> + 2f156: b9a0 cbnz r0, 2f182 <__rtl_swsetup_r+0x1ca> + 2f158: 89a3 ldrh r3, [r4, #12] + 2f15a: 6925 ldr r5, [r4, #16] + 2f15c: e740 b.n 2efe0 <__rtl_swsetup_r+0x28> + 2f15e: 89a2 ldrh r2, [r4, #12] + 2f160: b293 uxth r3, r2 + 2f162: 0599 lsls r1, r3, #22 + 2f164: d4f9 bmi.n 2f15a <__rtl_swsetup_r+0x1a2> + 2f166: f042 0302 orr.w r3, r2, #2 + 2f16a: f104 0543 add.w r5, r4, #67 ; 0x43 + 2f16e: 2201 movs r2, #1 + 2f170: 81a3 strh r3, [r4, #12] + 2f172: 6025 str r5, [r4, #0] + 2f174: b29b uxth r3, r3 + 2f176: 6125 str r5, [r4, #16] + 2f178: 6162 str r2, [r4, #20] + 2f17a: e731 b.n 2efe0 <__rtl_swsetup_r+0x28> + 2f17c: 682b ldr r3, [r5, #0] + 2f17e: b103 cbz r3, 2f182 <__rtl_swsetup_r+0x1ca> + 2f180: 6033 str r3, [r6, #0] + 2f182: 89a3 ldrh r3, [r4, #12] + 2f184: 6925 ldr r5, [r4, #16] + 2f186: f043 0301 orr.w r3, r3, #1 + 2f18a: b29b uxth r3, r3 + 2f18c: 81a3 strh r3, [r4, #12] + 2f18e: b29b uxth r3, r3 + 2f190: e726 b.n 2efe0 <__rtl_swsetup_r+0x28> + 2f192: f64e 33c1 movw r3, #60353 ; 0xebc1 + 2f196: f2c0 0302 movt r3, #2 + 2f19a: 6aa2 ldr r2, [r4, #40] ; 0x28 + 2f19c: 429a cmp r2, r3 + 2f19e: f47f af5f bne.w 2f060 <__rtl_swsetup_r+0xa8> + 2f1a2: 89a3 ldrh r3, [r4, #12] + 2f1a4: f44f 6580 mov.w r5, #1024 ; 0x400 + 2f1a8: 432b orrs r3, r5 + 2f1aa: 81a3 strh r3, [r4, #12] + 2f1ac: 64e5 str r5, [r4, #76] ; 0x4c + 2f1ae: e75d b.n 2f06c <__rtl_swsetup_r+0xb4> + +0002f1b0 <__rtl_swbuf_r_v1_00>: + 2f1b0: b5f8 push {r3, r4, r5, r6, r7, lr} + 2f1b2: 460d mov r5, r1 + 2f1b4: 4614 mov r4, r2 + 2f1b6: 4607 mov r7, r0 + 2f1b8: b110 cbz r0, 2f1c0 <__rtl_swbuf_r_v1_00+0x10> + 2f1ba: 6b83 ldr r3, [r0, #56] ; 0x38 + 2f1bc: 2b00 cmp r3, #0 + 2f1be: d045 beq.n 2f24c <__rtl_swbuf_r_v1_00+0x9c> + 2f1c0: 89a2 ldrh r2, [r4, #12] + 2f1c2: 69a0 ldr r0, [r4, #24] + 2f1c4: b293 uxth r3, r2 + 2f1c6: 60a0 str r0, [r4, #8] + 2f1c8: 0718 lsls r0, r3, #28 + 2f1ca: d52c bpl.n 2f226 <__rtl_swbuf_r_v1_00+0x76> + 2f1cc: 6926 ldr r6, [r4, #16] + 2f1ce: b356 cbz r6, 2f226 <__rtl_swbuf_r_v1_00+0x76> + 2f1d0: 0499 lsls r1, r3, #18 + 2f1d2: bf5f itttt pl + 2f1d4: 6e63 ldrpl r3, [r4, #100] ; 0x64 + 2f1d6: f442 5200 orrpl.w r2, r2, #8192 ; 0x2000 + 2f1da: f423 5300 bicpl.w r3, r3, #8192 ; 0x2000 + 2f1de: 6663 strpl r3, [r4, #100] ; 0x64 + 2f1e0: 6823 ldr r3, [r4, #0] + 2f1e2: bf58 it pl + 2f1e4: 81a2 strhpl r2, [r4, #12] + 2f1e6: 6962 ldr r2, [r4, #20] + 2f1e8: 1b9e subs r6, r3, r6 + 2f1ea: 4296 cmp r6, r2 + 2f1ec: b2ed uxtb r5, r5 + 2f1ee: bfb8 it lt + 2f1f0: 3601 addlt r6, #1 + 2f1f2: da22 bge.n 2f23a <__rtl_swbuf_r_v1_00+0x8a> + 2f1f4: 68a2 ldr r2, [r4, #8] + 2f1f6: 1c59 adds r1, r3, #1 + 2f1f8: 3a01 subs r2, #1 + 2f1fa: 60a2 str r2, [r4, #8] + 2f1fc: 6021 str r1, [r4, #0] + 2f1fe: 701d strb r5, [r3, #0] + 2f200: 6963 ldr r3, [r4, #20] + 2f202: 42b3 cmp r3, r6 + 2f204: d006 beq.n 2f214 <__rtl_swbuf_r_v1_00+0x64> + 2f206: 89a3 ldrh r3, [r4, #12] + 2f208: 07db lsls r3, r3, #31 + 2f20a: d501 bpl.n 2f210 <__rtl_swbuf_r_v1_00+0x60> + 2f20c: 2d0a cmp r5, #10 + 2f20e: d001 beq.n 2f214 <__rtl_swbuf_r_v1_00+0x64> + 2f210: 4628 mov r0, r5 + 2f212: bdf8 pop {r3, r4, r5, r6, r7, pc} + 2f214: 4638 mov r0, r7 + 2f216: 4621 mov r1, r4 + 2f218: f7ff feb8 bl 2ef8c <__rtl_fflush_r_v1_00> + 2f21c: 2800 cmp r0, #0 + 2f21e: d0f7 beq.n 2f210 <__rtl_swbuf_r_v1_00+0x60> + 2f220: f04f 30ff mov.w r0, #4294967295 + 2f224: bdf8 pop {r3, r4, r5, r6, r7, pc} + 2f226: 4638 mov r0, r7 + 2f228: 4621 mov r1, r4 + 2f22a: f7ff fec5 bl 2efb8 <__rtl_swsetup_r> + 2f22e: 2800 cmp r0, #0 + 2f230: d1f6 bne.n 2f220 <__rtl_swbuf_r_v1_00+0x70> + 2f232: 89a2 ldrh r2, [r4, #12] + 2f234: 6926 ldr r6, [r4, #16] + 2f236: b293 uxth r3, r2 + 2f238: e7ca b.n 2f1d0 <__rtl_swbuf_r_v1_00+0x20> + 2f23a: 4638 mov r0, r7 + 2f23c: 4621 mov r1, r4 + 2f23e: f7ff fea5 bl 2ef8c <__rtl_fflush_r_v1_00> + 2f242: 2800 cmp r0, #0 + 2f244: d1ec bne.n 2f220 <__rtl_swbuf_r_v1_00+0x70> + 2f246: 6823 ldr r3, [r4, #0] + 2f248: 2601 movs r6, #1 + 2f24a: e7d3 b.n 2f1f4 <__rtl_swbuf_r_v1_00+0x44> + 2f24c: f7ff fdb8 bl 2edc0 <__rtl_sinit.part.3> + 2f250: e7b6 b.n 2f1c0 <__rtl_swbuf_r_v1_00+0x10> + 2f252: bf00 nop + +0002f254 <__rtl_sprint_r_v1_00.part.9>: + 2f254: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 2f258: 6e4b ldr r3, [r1, #100] ; 0x64 + 2f25a: b087 sub sp, #28 + 2f25c: f413 5f00 tst.w r3, #8192 ; 0x2000 + 2f260: 460c mov r4, r1 + 2f262: 4605 mov r5, r0 + 2f264: 4690 mov r8, r2 + 2f266: 6893 ldr r3, [r2, #8] + 2f268: d067 beq.n 2f33a <__rtl_sprint_r_v1_00.part.9+0xe6> + 2f26a: 6812 ldr r2, [r2, #0] + 2f26c: f102 0908 add.w r9, r2, #8 + 2f270: 2b00 cmp r3, #0 + 2f272: d04b beq.n 2f30c <__rtl_sprint_r_v1_00.part.9+0xb8> + 2f274: e919 0084 ldmdb r9, {r2, r7} + 2f278: 08bf lsrs r7, r7, #2 + 2f27a: bf1c itt ne + 2f27c: f1a2 0b04 subne.w fp, r2, #4 + 2f280: f04f 0a00 movne.w sl, #0 + 2f284: d03a beq.n 2f2fc <__rtl_sprint_r_v1_00.part.9+0xa8> + 2f286: 89a3 ldrh r3, [r4, #12] + 2f288: f85b 6f04 ldr.w r6, [fp, #4]! + 2f28c: 049a lsls r2, r3, #18 + 2f28e: bf5f itttt pl + 2f290: 6e62 ldrpl r2, [r4, #100] ; 0x64 + 2f292: f443 5300 orrpl.w r3, r3, #8192 ; 0x2000 + 2f296: f442 5200 orrpl.w r2, r2, #8192 ; 0x2000 + 2f29a: 81a3 strhpl r3, [r4, #12] + 2f29c: f106 33ff add.w r3, r6, #4294967295 + 2f2a0: bf58 it pl + 2f2a2: 6662 strpl r2, [r4, #100] ; 0x64 + 2f2a4: 2bfe cmp r3, #254 ; 0xfe + 2f2a6: bf98 it ls + 2f2a8: b2f1 uxtbls r1, r6 + 2f2aa: d914 bls.n 2f2d6 <__rtl_sprint_r_v1_00.part.9+0x82> + 2f2ac: 2eff cmp r6, #255 ; 0xff + 2f2ae: d911 bls.n 2f2d4 <__rtl_sprint_r_v1_00.part.9+0x80> + 2f2b0: 89a3 ldrh r3, [r4, #12] + 2f2b2: 2100 movs r1, #0 + 2f2b4: f043 0340 orr.w r3, r3, #64 ; 0x40 + 2f2b8: 2254 movs r2, #84 ; 0x54 + 2f2ba: 65e1 str r1, [r4, #92] ; 0x5c + 2f2bc: 602a str r2, [r5, #0] + 2f2be: 81a3 strh r3, [r4, #12] + 2f2c0: f04f 30ff mov.w r0, #4294967295 + 2f2c4: 2300 movs r3, #0 + 2f2c6: f8c8 3008 str.w r3, [r8, #8] + 2f2ca: f8c8 3004 str.w r3, [r8, #4] + 2f2ce: b007 add sp, #28 + 2f2d0: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 2f2d4: 2100 movs r1, #0 + 2f2d6: 68a2 ldr r2, [r4, #8] + 2f2d8: 3a01 subs r2, #1 + 2f2da: 2a00 cmp r2, #0 + 2f2dc: 60a2 str r2, [r4, #8] + 2f2de: db17 blt.n 2f310 <__rtl_sprint_r_v1_00.part.9+0xbc> + 2f2e0: 6823 ldr r3, [r4, #0] + 2f2e2: 7019 strb r1, [r3, #0] + 2f2e4: 6823 ldr r3, [r4, #0] + 2f2e6: 3301 adds r3, #1 + 2f2e8: 6023 str r3, [r4, #0] + 2f2ea: 1c73 adds r3, r6, #1 + 2f2ec: f000 81b5 beq.w 2f65a <__rtl_sprint_r_v1_00.part.9+0x406> + 2f2f0: f10a 0a01 add.w sl, sl, #1 + 2f2f4: 4557 cmp r7, sl + 2f2f6: d1c6 bne.n 2f286 <__rtl_sprint_r_v1_00.part.9+0x32> + 2f2f8: f8d8 3008 ldr.w r3, [r8, #8] + 2f2fc: eba3 0387 sub.w r3, r3, r7, lsl #2 + 2f300: f8c8 3008 str.w r3, [r8, #8] + 2f304: f109 0908 add.w r9, r9, #8 + 2f308: 2b00 cmp r3, #0 + 2f30a: d1b3 bne.n 2f274 <__rtl_sprint_r_v1_00.part.9+0x20> + 2f30c: 2000 movs r0, #0 + 2f30e: e7d9 b.n 2f2c4 <__rtl_sprint_r_v1_00.part.9+0x70> + 2f310: 69a3 ldr r3, [r4, #24] + 2f312: 429a cmp r2, r3 + 2f314: db05 blt.n 2f322 <__rtl_sprint_r_v1_00.part.9+0xce> + 2f316: 6823 ldr r3, [r4, #0] + 2f318: 7019 strb r1, [r3, #0] + 2f31a: 6823 ldr r3, [r4, #0] + 2f31c: 7819 ldrb r1, [r3, #0] + 2f31e: 290a cmp r1, #10 + 2f320: d1e1 bne.n 2f2e6 <__rtl_sprint_r_v1_00.part.9+0x92> + 2f322: 4628 mov r0, r5 + 2f324: 4622 mov r2, r4 + 2f326: f7ff ff43 bl 2f1b0 <__rtl_swbuf_r_v1_00> + 2f32a: f1a0 30ff sub.w r0, r0, #4294967295 + 2f32e: fab0 f080 clz r0, r0 + 2f332: 0940 lsrs r0, r0, #5 + 2f334: 2800 cmp r0, #0 + 2f336: d0d8 beq.n 2f2ea <__rtl_sprint_r_v1_00.part.9+0x96> + 2f338: e7c2 b.n 2f2c0 <__rtl_sprint_r_v1_00.part.9+0x6c> + 2f33a: 2b00 cmp r3, #0 + 2f33c: d0e6 beq.n 2f30c <__rtl_sprint_r_v1_00.part.9+0xb8> + 2f33e: 8988 ldrh r0, [r1, #12] + 2f340: 0706 lsls r6, r0, #28 + 2f342: f140 80d7 bpl.w 2f4f4 <__rtl_sprint_r_v1_00.part.9+0x2a0> + 2f346: 690b ldr r3, [r1, #16] + 2f348: 2b00 cmp r3, #0 + 2f34a: f000 80d3 beq.w 2f4f4 <__rtl_sprint_r_v1_00.part.9+0x2a0> + 2f34e: f000 0302 and.w r3, r0, #2 + 2f352: b29b uxth r3, r3 + 2f354: f8d8 6000 ldr.w r6, [r8] + 2f358: b323 cbz r3, 2f3a4 <__rtl_sprint_r_v1_00.part.9+0x150> + 2f35a: f04f 0a00 mov.w sl, #0 + 2f35e: f44f 4b7c mov.w fp, #64512 ; 0xfc00 + 2f362: 4657 mov r7, sl + 2f364: f6c7 7bff movt fp, #32767 ; 0x7fff + 2f368: 46a9 mov r9, r5 + 2f36a: b1b7 cbz r7, 2f39a <__rtl_sprint_r_v1_00.part.9+0x146> + 2f36c: 455f cmp r7, fp + 2f36e: 463b mov r3, r7 + 2f370: 4648 mov r0, r9 + 2f372: bf28 it cs + 2f374: 465b movcs r3, fp + 2f376: 69e1 ldr r1, [r4, #28] + 2f378: 4652 mov r2, sl + 2f37a: 6a65 ldr r5, [r4, #36] ; 0x24 + 2f37c: 47a8 blx r5 + 2f37e: 2800 cmp r0, #0 + 2f380: f340 80b1 ble.w 2f4e6 <__rtl_sprint_r_v1_00.part.9+0x292> + 2f384: f8d8 2008 ldr.w r2, [r8, #8] + 2f388: 4482 add sl, r0 + 2f38a: 1a12 subs r2, r2, r0 + 2f38c: 1a3f subs r7, r7, r0 + 2f38e: f8c8 2008 str.w r2, [r8, #8] + 2f392: 2a00 cmp r2, #0 + 2f394: d0ba beq.n 2f30c <__rtl_sprint_r_v1_00.part.9+0xb8> + 2f396: 2f00 cmp r7, #0 + 2f398: d1e8 bne.n 2f36c <__rtl_sprint_r_v1_00.part.9+0x118> + 2f39a: f8d6 a000 ldr.w sl, [r6] + 2f39e: 6877 ldr r7, [r6, #4] + 2f3a0: 3608 adds r6, #8 + 2f3a2: e7e2 b.n 2f36a <__rtl_sprint_r_v1_00.part.9+0x116> + 2f3a4: f010 0a01 ands.w sl, r0, #1 + 2f3a8: f000 80b2 beq.w 2f510 <__rtl_sprint_r_v1_00.part.9+0x2bc> + 2f3ac: f648 37ed movw r7, #35821 ; 0x8bed + 2f3b0: f2c0 0702 movt r7, #2 + 2f3b4: 9703 str r7, [sp, #12] + 2f3b6: f648 274d movw r7, #35405 ; 0x8a4d + 2f3ba: f2c0 0702 movt r7, #2 + 2f3be: 469a mov sl, r3 + 2f3c0: 469b mov fp, r3 + 2f3c2: 4699 mov r9, r3 + 2f3c4: 9302 str r3, [sp, #8] + 2f3c6: 9704 str r7, [sp, #16] + 2f3c8: f1b9 0f00 cmp.w r9, #0 + 2f3cc: d02b beq.n 2f426 <__rtl_sprint_r_v1_00.part.9+0x1d2> + 2f3ce: 9f02 ldr r7, [sp, #8] + 2f3d0: 2f00 cmp r7, #0 + 2f3d2: d04b beq.n 2f46c <__rtl_sprint_r_v1_00.part.9+0x218> + 2f3d4: 45ca cmp sl, r9 + 2f3d6: 46d4 mov ip, sl + 2f3d8: bf28 it cs + 2f3da: 46cc movcs ip, r9 + 2f3dc: 6820 ldr r0, [r4, #0] + 2f3de: 6921 ldr r1, [r4, #16] + 2f3e0: 4667 mov r7, ip + 2f3e2: 4288 cmp r0, r1 + 2f3e4: 68a3 ldr r3, [r4, #8] + 2f3e6: 6962 ldr r2, [r4, #20] + 2f3e8: d902 bls.n 2f3f0 <__rtl_sprint_r_v1_00.part.9+0x19c> + 2f3ea: 4413 add r3, r2 + 2f3ec: 459c cmp ip, r3 + 2f3ee: dc4a bgt.n 2f486 <__rtl_sprint_r_v1_00.part.9+0x232> + 2f3f0: 4594 cmp ip, r2 + 2f3f2: db20 blt.n 2f436 <__rtl_sprint_r_v1_00.part.9+0x1e2> + 2f3f4: 4613 mov r3, r2 + 2f3f6: 6a67 ldr r7, [r4, #36] ; 0x24 + 2f3f8: 4628 mov r0, r5 + 2f3fa: 69e1 ldr r1, [r4, #28] + 2f3fc: 465a mov r2, fp + 2f3fe: 47b8 blx r7 + 2f400: 1e07 subs r7, r0, #0 + 2f402: dd70 ble.n 2f4e6 <__rtl_sprint_r_v1_00.part.9+0x292> + 2f404: ebba 0a07 subs.w sl, sl, r7 + 2f408: d027 beq.n 2f45a <__rtl_sprint_r_v1_00.part.9+0x206> + 2f40a: f8d8 3008 ldr.w r3, [r8, #8] + 2f40e: 44bb add fp, r7 + 2f410: 1bdb subs r3, r3, r7 + 2f412: ebc7 0909 rsb r9, r7, r9 + 2f416: f8c8 3008 str.w r3, [r8, #8] + 2f41a: 2b00 cmp r3, #0 + 2f41c: f43f af76 beq.w 2f30c <__rtl_sprint_r_v1_00.part.9+0xb8> + 2f420: f1b9 0f00 cmp.w r9, #0 + 2f424: d1d3 bne.n 2f3ce <__rtl_sprint_r_v1_00.part.9+0x17a> + 2f426: 2700 movs r7, #0 + 2f428: f8d6 b000 ldr.w fp, [r6] + 2f42c: f8d6 9004 ldr.w r9, [r6, #4] + 2f430: 9702 str r7, [sp, #8] + 2f432: 3608 adds r6, #8 + 2f434: e7c8 b.n 2f3c8 <__rtl_sprint_r_v1_00.part.9+0x174> + 2f436: 4662 mov r2, ip + 2f438: f8cd c004 str.w ip, [sp, #4] + 2f43c: 9b03 ldr r3, [sp, #12] + 2f43e: 4659 mov r1, fp + 2f440: 4798 blx r3 + 2f442: f8dd c004 ldr.w ip, [sp, #4] + 2f446: 68a2 ldr r2, [r4, #8] + 2f448: 6823 ldr r3, [r4, #0] + 2f44a: ebcc 0202 rsb r2, ip, r2 + 2f44e: 4463 add r3, ip + 2f450: ebba 0a07 subs.w sl, sl, r7 + 2f454: 60a2 str r2, [r4, #8] + 2f456: 6023 str r3, [r4, #0] + 2f458: d1d7 bne.n 2f40a <__rtl_sprint_r_v1_00.part.9+0x1b6> + 2f45a: 4628 mov r0, r5 + 2f45c: 4621 mov r1, r4 + 2f45e: f7ff fd95 bl 2ef8c <__rtl_fflush_r_v1_00> + 2f462: 2800 cmp r0, #0 + 2f464: d13f bne.n 2f4e6 <__rtl_sprint_r_v1_00.part.9+0x292> + 2f466: f8cd a008 str.w sl, [sp, #8] + 2f46a: e7ce b.n 2f40a <__rtl_sprint_r_v1_00.part.9+0x1b6> + 2f46c: 4658 mov r0, fp + 2f46e: 210a movs r1, #10 + 2f470: 464a mov r2, r9 + 2f472: 9f04 ldr r7, [sp, #16] + 2f474: 47b8 blx r7 + 2f476: 2800 cmp r0, #0 + 2f478: d045 beq.n 2f506 <__rtl_sprint_r_v1_00.part.9+0x2b2> + 2f47a: 3001 adds r0, #1 + 2f47c: 2701 movs r7, #1 + 2f47e: ebcb 0a00 rsb sl, fp, r0 + 2f482: 9702 str r7, [sp, #8] + 2f484: e7a6 b.n 2f3d4 <__rtl_sprint_r_v1_00.part.9+0x180> + 2f486: 461a mov r2, r3 + 2f488: 4659 mov r1, fp + 2f48a: 9301 str r3, [sp, #4] + 2f48c: 9f03 ldr r7, [sp, #12] + 2f48e: 47b8 blx r7 + 2f490: 9b01 ldr r3, [sp, #4] + 2f492: 6822 ldr r2, [r4, #0] + 2f494: 4628 mov r0, r5 + 2f496: 441a add r2, r3 + 2f498: 6022 str r2, [r4, #0] + 2f49a: 4621 mov r1, r4 + 2f49c: 9301 str r3, [sp, #4] + 2f49e: f7ff fd75 bl 2ef8c <__rtl_fflush_r_v1_00> + 2f4a2: 9b01 ldr r3, [sp, #4] + 2f4a4: b9f8 cbnz r0, 2f4e6 <__rtl_sprint_r_v1_00.part.9+0x292> + 2f4a6: 461f mov r7, r3 + 2f4a8: e7ac b.n 2f404 <__rtl_sprint_r_v1_00.part.9+0x1b0> + 2f4aa: 6820 ldr r0, [r4, #0] + 2f4ac: 6923 ldr r3, [r4, #16] + 2f4ae: 4298 cmp r0, r3 + 2f4b0: d803 bhi.n 2f4ba <__rtl_sprint_r_v1_00.part.9+0x266> + 2f4b2: 6963 ldr r3, [r4, #20] + 2f4b4: 429f cmp r7, r3 + 2f4b6: f080 80a2 bcs.w 2f5fe <__rtl_sprint_r_v1_00.part.9+0x3aa> + 2f4ba: 45b9 cmp r9, r7 + 2f4bc: bf28 it cs + 2f4be: 46b9 movcs r9, r7 + 2f4c0: 4651 mov r1, sl + 2f4c2: 464a mov r2, r9 + 2f4c4: 9d02 ldr r5, [sp, #8] + 2f4c6: 47a8 blx r5 + 2f4c8: 68a3 ldr r3, [r4, #8] + 2f4ca: 6822 ldr r2, [r4, #0] + 2f4cc: ebc9 0303 rsb r3, r9, r3 + 2f4d0: 444a add r2, r9 + 2f4d2: 60a3 str r3, [r4, #8] + 2f4d4: 6022 str r2, [r4, #0] + 2f4d6: 2b00 cmp r3, #0 + 2f4d8: d15a bne.n 2f590 <__rtl_sprint_r_v1_00.part.9+0x33c> + 2f4da: 9800 ldr r0, [sp, #0] + 2f4dc: 4621 mov r1, r4 + 2f4de: f7ff fd55 bl 2ef8c <__rtl_fflush_r_v1_00> + 2f4e2: 2800 cmp r0, #0 + 2f4e4: d054 beq.n 2f590 <__rtl_sprint_r_v1_00.part.9+0x33c> + 2f4e6: 89a3 ldrh r3, [r4, #12] + 2f4e8: f043 0340 orr.w r3, r3, #64 ; 0x40 + 2f4ec: 81a3 strh r3, [r4, #12] + 2f4ee: f04f 30ff mov.w r0, #4294967295 + 2f4f2: e6e7 b.n 2f2c4 <__rtl_sprint_r_v1_00.part.9+0x70> + 2f4f4: 4628 mov r0, r5 + 2f4f6: 4621 mov r1, r4 + 2f4f8: f7ff fd5e bl 2efb8 <__rtl_swsetup_r> + 2f4fc: 2800 cmp r0, #0 + 2f4fe: f47f aedf bne.w 2f2c0 <__rtl_sprint_r_v1_00.part.9+0x6c> + 2f502: 89a0 ldrh r0, [r4, #12] + 2f504: e723 b.n 2f34e <__rtl_sprint_r_v1_00.part.9+0xfa> + 2f506: 2701 movs r7, #1 + 2f508: f109 0a01 add.w sl, r9, #1 + 2f50c: 9702 str r7, [sp, #8] + 2f50e: e761 b.n 2f3d4 <__rtl_sprint_r_v1_00.part.9+0x180> + 2f510: f648 37ed movw r7, #35821 ; 0x8bed + 2f514: f2c0 0702 movt r7, #2 + 2f518: 9702 str r7, [sp, #8] + 2f51a: f64d 7755 movw r7, #57173 ; 0xdf55 + 2f51e: f2c0 0702 movt r7, #2 + 2f522: 9703 str r7, [sp, #12] + 2f524: f64d 2731 movw r7, #55857 ; 0xda31 + 2f528: f2c0 0702 movt r7, #2 + 2f52c: 9704 str r7, [sp, #16] + 2f52e: f648 3749 movw r7, #35657 ; 0x8b49 + 2f532: f2c0 0702 movt r7, #2 + 2f536: 9705 str r7, [sp, #20] + 2f538: 4657 mov r7, sl + 2f53a: 9500 str r5, [sp, #0] + 2f53c: b31f cbz r7, 2f586 <__rtl_sprint_r_v1_00.part.9+0x332> + 2f53e: 0585 lsls r5, r0, #22 + 2f540: f8d4 9008 ldr.w r9, [r4, #8] + 2f544: d5b1 bpl.n 2f4aa <__rtl_sprint_r_v1_00.part.9+0x256> + 2f546: 454f cmp r7, r9 + 2f548: d324 bcc.n 2f594 <__rtl_sprint_r_v1_00.part.9+0x340> + 2f54a: f410 6f90 tst.w r0, #1152 ; 0x480 + 2f54e: d125 bne.n 2f59c <__rtl_sprint_r_v1_00.part.9+0x348> + 2f550: 46cb mov fp, r9 + 2f552: 6820 ldr r0, [r4, #0] + 2f554: 465a mov r2, fp + 2f556: 4651 mov r1, sl + 2f558: 9d02 ldr r5, [sp, #8] + 2f55a: 47a8 blx r5 + 2f55c: 6823 ldr r3, [r4, #0] + 2f55e: 68a2 ldr r2, [r4, #8] + 2f560: 445b add r3, fp + 2f562: 6023 str r3, [r4, #0] + 2f564: 463b mov r3, r7 + 2f566: ebc9 0202 rsb r2, r9, r2 + 2f56a: 60a2 str r2, [r4, #8] + 2f56c: f8d8 2008 ldr.w r2, [r8, #8] + 2f570: 449a add sl, r3 + 2f572: 1ad2 subs r2, r2, r3 + 2f574: 1aff subs r7, r7, r3 + 2f576: f8c8 2008 str.w r2, [r8, #8] + 2f57a: 2a00 cmp r2, #0 + 2f57c: f43f aec6 beq.w 2f30c <__rtl_sprint_r_v1_00.part.9+0xb8> + 2f580: 89a0 ldrh r0, [r4, #12] + 2f582: 2f00 cmp r7, #0 + 2f584: d1db bne.n 2f53e <__rtl_sprint_r_v1_00.part.9+0x2ea> + 2f586: f8d6 a000 ldr.w sl, [r6] + 2f58a: 6877 ldr r7, [r6, #4] + 2f58c: 3608 adds r6, #8 + 2f58e: e7d5 b.n 2f53c <__rtl_sprint_r_v1_00.part.9+0x2e8> + 2f590: 464b mov r3, r9 + 2f592: e7eb b.n 2f56c <__rtl_sprint_r_v1_00.part.9+0x318> + 2f594: 46b9 mov r9, r7 + 2f596: 46bb mov fp, r7 + 2f598: 6820 ldr r0, [r4, #0] + 2f59a: e7db b.n 2f554 <__rtl_sprint_r_v1_00.part.9+0x300> + 2f59c: 6822 ldr r2, [r4, #0] + 2f59e: 6921 ldr r1, [r4, #16] + 2f5a0: 6963 ldr r3, [r4, #20] + 2f5a2: ebc1 0902 rsb r9, r1, r2 + 2f5a6: eb03 0b43 add.w fp, r3, r3, lsl #1 + 2f5aa: f109 0201 add.w r2, r9, #1 + 2f5ae: eb0b 7bdb add.w fp, fp, fp, lsr #31 + 2f5b2: 443a add r2, r7 + 2f5b4: ea4f 0b6b mov.w fp, fp, asr #1 + 2f5b8: 4593 cmp fp, r2 + 2f5ba: bf34 ite cc + 2f5bc: 4693 movcc fp, r2 + 2f5be: 465a movcs r2, fp + 2f5c0: 0540 lsls r0, r0, #21 + 2f5c2: d52f bpl.n 2f624 <__rtl_sprint_r_v1_00.part.9+0x3d0> + 2f5c4: 9d04 ldr r5, [sp, #16] + 2f5c6: 4611 mov r1, r2 + 2f5c8: 9800 ldr r0, [sp, #0] + 2f5ca: 47a8 blx r5 + 2f5cc: 4605 mov r5, r0 + 2f5ce: 2800 cmp r0, #0 + 2f5d0: d03e beq.n 2f650 <__rtl_sprint_r_v1_00.part.9+0x3fc> + 2f5d2: 464a mov r2, r9 + 2f5d4: 6921 ldr r1, [r4, #16] + 2f5d6: 9b05 ldr r3, [sp, #20] + 2f5d8: 4798 blx r3 + 2f5da: 89a2 ldrh r2, [r4, #12] + 2f5dc: f422 6290 bic.w r2, r2, #1152 ; 0x480 + 2f5e0: f042 0280 orr.w r2, r2, #128 ; 0x80 + 2f5e4: 81a2 strh r2, [r4, #12] + 2f5e6: ebc9 020b rsb r2, r9, fp + 2f5ea: eb05 0009 add.w r0, r5, r9 + 2f5ee: f8c4 b014 str.w fp, [r4, #20] + 2f5f2: 6125 str r5, [r4, #16] + 2f5f4: 6020 str r0, [r4, #0] + 2f5f6: 60a2 str r2, [r4, #8] + 2f5f8: 46b9 mov r9, r7 + 2f5fa: 46bb mov fp, r7 + 2f5fc: e7aa b.n 2f554 <__rtl_sprint_r_v1_00.part.9+0x300> + 2f5fe: f06f 4200 mvn.w r2, #2147483648 ; 0x80000000 + 2f602: 42ba cmp r2, r7 + 2f604: bf28 it cs + 2f606: 463a movcs r2, r7 + 2f608: fb92 f2f3 sdiv r2, r2, r3 + 2f60c: 9800 ldr r0, [sp, #0] + 2f60e: fb02 f303 mul.w r3, r2, r3 + 2f612: 69e1 ldr r1, [r4, #28] + 2f614: 4652 mov r2, sl + 2f616: 6a65 ldr r5, [r4, #36] ; 0x24 + 2f618: 47a8 blx r5 + 2f61a: 2800 cmp r0, #0 + 2f61c: f77f af63 ble.w 2f4e6 <__rtl_sprint_r_v1_00.part.9+0x292> + 2f620: 4603 mov r3, r0 + 2f622: e7a3 b.n 2f56c <__rtl_sprint_r_v1_00.part.9+0x318> + 2f624: 9d03 ldr r5, [sp, #12] + 2f626: 9800 ldr r0, [sp, #0] + 2f628: 47a8 blx r5 + 2f62a: 4605 mov r5, r0 + 2f62c: 2800 cmp r0, #0 + 2f62e: d1da bne.n 2f5e6 <__rtl_sprint_r_v1_00.part.9+0x392> + 2f630: f64d 0341 movw r3, #55361 ; 0xd841 + 2f634: 9d00 ldr r5, [sp, #0] + 2f636: f2c0 0302 movt r3, #2 + 2f63a: 4628 mov r0, r5 + 2f63c: 6921 ldr r1, [r4, #16] + 2f63e: 4798 blx r3 + 2f640: 89a3 ldrh r3, [r4, #12] + 2f642: 220c movs r2, #12 + 2f644: f023 0380 bic.w r3, r3, #128 ; 0x80 + 2f648: 041b lsls r3, r3, #16 + 2f64a: 0c1b lsrs r3, r3, #16 + 2f64c: 602a str r2, [r5, #0] + 2f64e: e74b b.n 2f4e8 <__rtl_sprint_r_v1_00.part.9+0x294> + 2f650: 9d00 ldr r5, [sp, #0] + 2f652: 230c movs r3, #12 + 2f654: 602b str r3, [r5, #0] + 2f656: 89a3 ldrh r3, [r4, #12] + 2f658: e746 b.n 2f4e8 <__rtl_sprint_r_v1_00.part.9+0x294> + 2f65a: 4630 mov r0, r6 + 2f65c: e632 b.n 2f2c4 <__rtl_sprint_r_v1_00.part.9+0x70> + 2f65e: bf00 nop + +0002f660 <__rtl_vfprintf_r_v1_00>: + 2f660: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} + 2f664: f648 7415 movw r4, #36629 ; 0x8f15 + 2f668: b0c7 sub sp, #284 ; 0x11c + 2f66a: 900c str r0, [sp, #48] ; 0x30 + 2f66c: f643 0020 movw r0, #14368 ; 0x3820 + 2f670: f2c0 0402 movt r4, #2 + 2f674: f2c0 0004 movt r0, #4 + 2f678: 9413 str r4, [sp, #76] ; 0x4c + 2f67a: 9109 str r1, [sp, #36] ; 0x24 + 2f67c: 4692 mov sl, r2 + 2f67e: 930f str r3, [sp, #60] ; 0x3c + 2f680: 47a0 blx r4 + 2f682: 9d0c ldr r5, [sp, #48] ; 0x30 + 2f684: 901c str r0, [sp, #112] ; 0x70 + 2f686: b11d cbz r5, 2f690 <__rtl_vfprintf_r_v1_00+0x30> + 2f688: 6bab ldr r3, [r5, #56] ; 0x38 + 2f68a: 2b00 cmp r3, #0 + 2f68c: f000 80e4 beq.w 2f858 <__rtl_vfprintf_r_v1_00+0x1f8> + 2f690: 9c09 ldr r4, [sp, #36] ; 0x24 + 2f692: 89a2 ldrh r2, [r4, #12] + 2f694: b293 uxth r3, r2 + 2f696: 049f lsls r7, r3, #18 + 2f698: d407 bmi.n 2f6aa <__rtl_vfprintf_r_v1_00+0x4a> + 2f69a: 6e61 ldr r1, [r4, #100] ; 0x64 + 2f69c: f442 5300 orr.w r3, r2, #8192 ; 0x2000 + 2f6a0: f421 5100 bic.w r1, r1, #8192 ; 0x2000 + 2f6a4: 81a3 strh r3, [r4, #12] + 2f6a6: 6661 str r1, [r4, #100] ; 0x64 + 2f6a8: b29b uxth r3, r3 + 2f6aa: 071e lsls r6, r3, #28 + 2f6ac: f140 80c8 bpl.w 2f840 <__rtl_vfprintf_r_v1_00+0x1e0> + 2f6b0: 9d09 ldr r5, [sp, #36] ; 0x24 + 2f6b2: 692b ldr r3, [r5, #16] + 2f6b4: 2b00 cmp r3, #0 + 2f6b6: f000 80c3 beq.w 2f840 <__rtl_vfprintf_r_v1_00+0x1e0> + 2f6ba: f64e 4404 movw r4, #60420 ; 0xec04 + 2f6be: f2c0 0403 movt r4, #3 + 2f6c2: 9412 str r4, [sp, #72] ; 0x48 + 2f6c4: 9c12 ldr r4, [sp, #72] ; 0x48 + 2f6c6: f643 0520 movw r5, #14368 ; 0x3820 + 2f6ca: f104 0910 add.w r9, r4, #16 + 2f6ce: f64b 644d movw r4, #48717 ; 0xbe4d + 2f6d2: f2c0 0402 movt r4, #2 + 2f6d6: 9415 str r4, [sp, #84] ; 0x54 + 2f6d8: f643 0424 movw r4, #14372 ; 0x3824 + 2f6dc: f2c0 0404 movt r4, #4 + 2f6e0: f10d 08d8 add.w r8, sp, #216 ; 0xd8 + 2f6e4: f2c0 0504 movt r5, #4 + 2f6e8: 9417 str r4, [sp, #92] ; 0x5c + 2f6ea: 46d3 mov fp, sl + 2f6ec: 4644 mov r4, r8 + 2f6ee: 2300 movs r3, #0 + 2f6f0: 930d str r3, [sp, #52] ; 0x34 + 2f6f2: 932b str r3, [sp, #172] ; 0xac + 2f6f4: 932a str r3, [sp, #168] ; 0xa8 + 2f6f6: 931a str r3, [sp, #104] ; 0x68 + 2f6f8: 931b str r3, [sp, #108] ; 0x6c + 2f6fa: 9318 str r3, [sp, #96] ; 0x60 + 2f6fc: 931d str r3, [sp, #116] ; 0x74 + 2f6fe: 9311 str r3, [sp, #68] ; 0x44 + 2f700: 9516 str r5, [sp, #88] ; 0x58 + 2f702: f8cd 80a4 str.w r8, [sp, #164] ; 0xa4 + 2f706: f89b 3000 ldrb.w r3, [fp] + 2f70a: 465d mov r5, fp + 2f70c: 2b25 cmp r3, #37 ; 0x25 + 2f70e: bf18 it ne + 2f710: 2b00 cmpne r3, #0 + 2f712: d01d beq.n 2f750 <__rtl_vfprintf_r_v1_00+0xf0> + 2f714: f815 3f01 ldrb.w r3, [r5, #1]! + 2f718: 2b25 cmp r3, #37 ; 0x25 + 2f71a: bf18 it ne + 2f71c: 2b00 cmpne r3, #0 + 2f71e: d1f9 bne.n 2f714 <__rtl_vfprintf_r_v1_00+0xb4> + 2f720: ebb5 060b subs.w r6, r5, fp + 2f724: d014 beq.n 2f750 <__rtl_vfprintf_r_v1_00+0xf0> + 2f726: 9b2a ldr r3, [sp, #168] ; 0xa8 + 2f728: 9a2b ldr r2, [sp, #172] ; 0xac + 2f72a: 3301 adds r3, #1 + 2f72c: 4432 add r2, r6 + 2f72e: 2b07 cmp r3, #7 + 2f730: f8c4 b000 str.w fp, [r4] + 2f734: 6066 str r6, [r4, #4] + 2f736: 922b str r2, [sp, #172] ; 0xac + 2f738: 932a str r3, [sp, #168] ; 0xa8 + 2f73a: bfd8 it le + 2f73c: 3408 addle r4, #8 + 2f73e: dd04 ble.n 2f74a <__rtl_vfprintf_r_v1_00+0xea> + 2f740: 2a00 cmp r2, #0 + 2f742: f040 808d bne.w 2f860 <__rtl_vfprintf_r_v1_00+0x200> + 2f746: 4644 mov r4, r8 + 2f748: 922a str r2, [sp, #168] ; 0xa8 + 2f74a: 9811 ldr r0, [sp, #68] ; 0x44 + 2f74c: 4430 add r0, r6 + 2f74e: 9011 str r0, [sp, #68] ; 0x44 + 2f750: 782b ldrb r3, [r5, #0] + 2f752: 2b00 cmp r3, #0 + 2f754: f000 8406 beq.w 2ff64 <__rtl_vfprintf_r_v1_00+0x904> + 2f758: 2300 movs r3, #0 + 2f75a: f04f 3cff mov.w ip, #4294967295 + 2f75e: 461a mov r2, r3 + 2f760: 4619 mov r1, r3 + 2f762: 4660 mov r0, ip + 2f764: 3501 adds r5, #1 + 2f766: f88d 3087 strb.w r3, [sp, #135] ; 0x87 + 2f76a: 930b str r3, [sp, #44] ; 0x2c + 2f76c: 9308 str r3, [sp, #32] + 2f76e: 782f ldrb r7, [r5, #0] + 2f770: f105 0b01 add.w fp, r5, #1 + 2f774: f1a7 0320 sub.w r3, r7, #32 + 2f778: 2b58 cmp r3, #88 ; 0x58 + 2f77a: f200 8390 bhi.w 2fe9e <__rtl_vfprintf_r_v1_00+0x83e> + 2f77e: e8df f013 tbh [pc, r3, lsl #1] + 2f782: 02b0 .short 0x02b0 + 2f784: 038e038e .word 0x038e038e + 2f788: 038e02b5 .word 0x038e02b5 + 2f78c: 038e038e .word 0x038e038e + 2f790: 038e038e .word 0x038e038e + 2f794: 02bb038e .word 0x02bb038e + 2f798: 038e01ed .word 0x038e01ed + 2f79c: 0373007e .word 0x0373007e + 2f7a0: 01fb038e .word 0x01fb038e + 2f7a4: 030d030d .word 0x030d030d + 2f7a8: 030d030d .word 0x030d030d + 2f7ac: 030d030d .word 0x030d030d + 2f7b0: 030d030d .word 0x030d030d + 2f7b4: 038e030d .word 0x038e030d + 2f7b8: 038e038e .word 0x038e038e + 2f7bc: 038e038e .word 0x038e038e + 2f7c0: 038e038e .word 0x038e038e + 2f7c4: 038e038e .word 0x038e038e + 2f7c8: 031b038e .word 0x031b038e + 2f7cc: 038e0332 .word 0x038e0332 + 2f7d0: 038e0332 .word 0x038e0332 + 2f7d4: 038e038e .word 0x038e038e + 2f7d8: 02aa038e .word 0x02aa038e + 2f7dc: 038e038e .word 0x038e038e + 2f7e0: 038e0201 .word 0x038e0201 + 2f7e4: 038e038e .word 0x038e038e + 2f7e8: 038e038e .word 0x038e038e + 2f7ec: 038e0219 .word 0x038e0219 + 2f7f0: 022d038e .word 0x022d038e + 2f7f4: 038e038e .word 0x038e038e + 2f7f8: 038e038e .word 0x038e038e + 2f7fc: 038e038e .word 0x038e038e + 2f800: 038e038e .word 0x038e038e + 2f804: 038e038e .word 0x038e038e + 2f808: 0260024c .word 0x0260024c + 2f80c: 03320332 .word 0x03320332 + 2f810: 02760332 .word 0x02760332 + 2f814: 038e0260 .word 0x038e0260 + 2f818: 0059038e .word 0x0059038e + 2f81c: 0299038e .word 0x0299038e + 2f820: 02f50084 .word 0x02f50084 + 2f824: 038e0059 .word 0x038e0059 + 2f828: 038e02c5 .word 0x038e02c5 + 2f82c: 038e01f0 .word 0x038e01f0 + 2f830: 027c038e .word 0x027c038e + 2f834: 9d08 ldr r5, [sp, #32] + 2f836: f045 0510 orr.w r5, r5, #16 + 2f83a: 9508 str r5, [sp, #32] + 2f83c: 465d mov r5, fp + 2f83e: e796 b.n 2f76e <__rtl_vfprintf_r_v1_00+0x10e> + 2f840: 980c ldr r0, [sp, #48] ; 0x30 + 2f842: 9909 ldr r1, [sp, #36] ; 0x24 + 2f844: f7ff fbb8 bl 2efb8 <__rtl_swsetup_r> + 2f848: 2800 cmp r0, #0 + 2f84a: f43f af36 beq.w 2f6ba <__rtl_vfprintf_r_v1_00+0x5a> + 2f84e: f04f 30ff mov.w r0, #4294967295 + 2f852: b047 add sp, #284 ; 0x11c + 2f854: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 2f858: 4628 mov r0, r5 + 2f85a: f7ff fab1 bl 2edc0 <__rtl_sinit.part.3> + 2f85e: e717 b.n 2f690 <__rtl_vfprintf_r_v1_00+0x30> + 2f860: 980c ldr r0, [sp, #48] ; 0x30 + 2f862: 9909 ldr r1, [sp, #36] ; 0x24 + 2f864: aa29 add r2, sp, #164 ; 0xa4 + 2f866: f7ff fcf5 bl 2f254 <__rtl_sprint_r_v1_00.part.9> + 2f86a: 2800 cmp r0, #0 + 2f86c: f040 8381 bne.w 2ff72 <__rtl_vfprintf_r_v1_00+0x912> + 2f870: 9811 ldr r0, [sp, #68] ; 0x44 + 2f872: 4644 mov r4, r8 + 2f874: 4430 add r0, r6 + 2f876: 9011 str r0, [sp, #68] ; 0x44 + 2f878: e76a b.n 2f750 <__rtl_vfprintf_r_v1_00+0xf0> + 2f87a: 930f str r3, [sp, #60] ; 0x3c + 2f87c: 4249 negs r1, r1 + 2f87e: 9d08 ldr r5, [sp, #32] + 2f880: f045 0504 orr.w r5, r5, #4 + 2f884: 9508 str r5, [sp, #32] + 2f886: 465d mov r5, fp + 2f888: e771 b.n 2f76e <__rtl_vfprintf_r_v1_00+0x10e> + 2f88a: 9d08 ldr r5, [sp, #32] + 2f88c: 910b str r1, [sp, #44] ; 0x2c + 2f88e: f015 0310 ands.w r3, r5, #16 + 2f892: 4684 mov ip, r0 + 2f894: f000 8181 beq.w 2fb9a <__rtl_vfprintf_r_v1_00+0x53a> + 2f898: 9d0f ldr r5, [sp, #60] ; 0x3c + 2f89a: 2100 movs r1, #0 + 2f89c: 682b ldr r3, [r5, #0] + 2f89e: 3504 adds r5, #4 + 2f8a0: 950f str r5, [sp, #60] ; 0x3c + 2f8a2: 2000 movs r0, #0 + 2f8a4: 4602 mov r2, r0 + 2f8a6: f88d 0087 strb.w r0, [sp, #135] ; 0x87 + 2f8aa: f1bc 0f00 cmp.w ip, #0 + 2f8ae: bfa2 ittt ge + 2f8b0: 9d08 ldrge r5, [sp, #32] + 2f8b2: f025 0580 bicge.w r5, r5, #128 ; 0x80 + 2f8b6: 9508 strge r5, [sp, #32] + 2f8b8: 2b00 cmp r3, #0 + 2f8ba: bf08 it eq + 2f8bc: f1bc 0f00 cmpeq.w ip, #0 + 2f8c0: bf14 ite ne + 2f8c2: 2001 movne r0, #1 + 2f8c4: 2000 moveq r0, #0 + 2f8c6: f000 8369 beq.w 2ff9c <__rtl_vfprintf_r_v1_00+0x93c> + 2f8ca: 2901 cmp r1, #1 + 2f8cc: f000 841a beq.w 30104 <__rtl_vfprintf_r_v1_00+0xaa4> + 2f8d0: 2902 cmp r1, #2 + 2f8d2: f10d 01d7 add.w r1, sp, #215 ; 0xd7 + 2f8d6: f040 8128 bne.w 2fb2a <__rtl_vfprintf_r_v1_00+0x4ca> + 2f8da: 9d18 ldr r5, [sp, #96] ; 0x60 + 2f8dc: 460e mov r6, r1 + 2f8de: f003 010f and.w r1, r3, #15 + 2f8e2: 5c68 ldrb r0, [r5, r1] + 2f8e4: 091b lsrs r3, r3, #4 + 2f8e6: f106 31ff add.w r1, r6, #4294967295 + 2f8ea: 7030 strb r0, [r6, #0] + 2f8ec: d1f6 bne.n 2f8dc <__rtl_vfprintf_r_v1_00+0x27c> + 2f8ee: ebc6 0508 rsb r5, r6, r8 + 2f8f2: 9510 str r5, [sp, #64] ; 0x40 + 2f8f4: 9d10 ldr r5, [sp, #64] ; 0x40 + 2f8f6: 4565 cmp r5, ip + 2f8f8: bfb8 it lt + 2f8fa: 4665 movlt r5, ip + 2f8fc: 950a str r5, [sp, #40] ; 0x28 + 2f8fe: 2500 movs r5, #0 + 2f900: 9519 str r5, [sp, #100] ; 0x64 + 2f902: b112 cbz r2, 2f90a <__rtl_vfprintf_r_v1_00+0x2aa> + 2f904: 9d0a ldr r5, [sp, #40] ; 0x28 + 2f906: 3501 adds r5, #1 + 2f908: 950a str r5, [sp, #40] ; 0x28 + 2f90a: 9d08 ldr r5, [sp, #32] + 2f90c: f015 0302 ands.w r3, r5, #2 + 2f910: bf1e ittt ne + 2f912: 9d0a ldrne r5, [sp, #40] ; 0x28 + 2f914: 3502 addne r5, #2 + 2f916: 950a strne r5, [sp, #40] ; 0x28 + 2f918: 9d08 ldr r5, [sp, #32] + 2f91a: f015 0584 ands.w r5, r5, #132 ; 0x84 + 2f91e: 9514 str r5, [sp, #80] ; 0x50 + 2f920: d142 bne.n 2f9a8 <__rtl_vfprintf_r_v1_00+0x348> + 2f922: 980b ldr r0, [sp, #44] ; 0x2c + 2f924: 990a ldr r1, [sp, #40] ; 0x28 + 2f926: 1a45 subs r5, r0, r1 + 2f928: 2d00 cmp r5, #0 + 2f92a: dd3d ble.n 2f9a8 <__rtl_vfprintf_r_v1_00+0x348> + 2f92c: 2d10 cmp r5, #16 + 2f92e: f340 8775 ble.w 3081c <__rtl_vfprintf_r_v1_00+0x11bc> + 2f932: f64e 4104 movw r1, #60420 ; 0xec04 + 2f936: f2c0 0103 movt r1, #3 + 2f93a: f8cd c078 str.w ip, [sp, #120] ; 0x78 + 2f93e: 910e str r1, [sp, #56] ; 0x38 + 2f940: 46a4 mov ip, r4 + 2f942: 9a2b ldr r2, [sp, #172] ; 0xac + 2f944: 982a ldr r0, [sp, #168] ; 0xa8 + 2f946: f04f 0a10 mov.w sl, #16 + 2f94a: 931f str r3, [sp, #124] ; 0x7c + 2f94c: 9c12 ldr r4, [sp, #72] ; 0x48 + 2f94e: e007 b.n 2f960 <__rtl_vfprintf_r_v1_00+0x300> + 2f950: f100 0e02 add.w lr, r0, #2 + 2f954: 4608 mov r0, r1 + 2f956: f10c 0c08 add.w ip, ip, #8 + 2f95a: 3d10 subs r5, #16 + 2f95c: 2d10 cmp r5, #16 + 2f95e: dd11 ble.n 2f984 <__rtl_vfprintf_r_v1_00+0x324> + 2f960: 1c41 adds r1, r0, #1 + 2f962: 3210 adds r2, #16 + 2f964: 2907 cmp r1, #7 + 2f966: 922b str r2, [sp, #172] ; 0xac + 2f968: e88c 0410 stmia.w ip, {r4, sl} + 2f96c: 912a str r1, [sp, #168] ; 0xa8 + 2f96e: ddef ble.n 2f950 <__rtl_vfprintf_r_v1_00+0x2f0> + 2f970: 2a00 cmp r2, #0 + 2f972: f040 82b9 bne.w 2fee8 <__rtl_vfprintf_r_v1_00+0x888> + 2f976: 3d10 subs r5, #16 + 2f978: 2d10 cmp r5, #16 + 2f97a: 4610 mov r0, r2 + 2f97c: f04f 0e01 mov.w lr, #1 + 2f980: 46c4 mov ip, r8 + 2f982: dced bgt.n 2f960 <__rtl_vfprintf_r_v1_00+0x300> + 2f984: 4664 mov r4, ip + 2f986: 9b1f ldr r3, [sp, #124] ; 0x7c + 2f988: f8dd c078 ldr.w ip, [sp, #120] ; 0x78 + 2f98c: 980e ldr r0, [sp, #56] ; 0x38 + 2f98e: 442a add r2, r5 + 2f990: f1be 0f07 cmp.w lr, #7 + 2f994: 922b str r2, [sp, #172] ; 0xac + 2f996: e884 0021 stmia.w r4, {r0, r5} + 2f99a: f8cd e0a8 str.w lr, [sp, #168] ; 0xa8 + 2f99e: f300 83bd bgt.w 3011c <__rtl_vfprintf_r_v1_00+0xabc> + 2f9a2: f89d 2087 ldrb.w r2, [sp, #135] ; 0x87 + 2f9a6: 3408 adds r4, #8 + 2f9a8: b19a cbz r2, 2f9d2 <__rtl_vfprintf_r_v1_00+0x372> + 2f9aa: 9a2a ldr r2, [sp, #168] ; 0xa8 + 2f9ac: 992b ldr r1, [sp, #172] ; 0xac + 2f9ae: 3201 adds r2, #1 + 2f9b0: 3101 adds r1, #1 + 2f9b2: f10d 0587 add.w r5, sp, #135 ; 0x87 + 2f9b6: 2001 movs r0, #1 + 2f9b8: 2a07 cmp r2, #7 + 2f9ba: 6025 str r5, [r4, #0] + 2f9bc: 6060 str r0, [r4, #4] + 2f9be: 912b str r1, [sp, #172] ; 0xac + 2f9c0: 922a str r2, [sp, #168] ; 0xa8 + 2f9c2: bfd8 it le + 2f9c4: 3408 addle r4, #8 + 2f9c6: dd04 ble.n 2f9d2 <__rtl_vfprintf_r_v1_00+0x372> + 2f9c8: 2900 cmp r1, #0 + 2f9ca: f040 8478 bne.w 302be <__rtl_vfprintf_r_v1_00+0xc5e> + 2f9ce: 4644 mov r4, r8 + 2f9d0: 912a str r1, [sp, #168] ; 0xa8 + 2f9d2: b193 cbz r3, 2f9fa <__rtl_vfprintf_r_v1_00+0x39a> + 2f9d4: 9b2a ldr r3, [sp, #168] ; 0xa8 + 2f9d6: 9a2b ldr r2, [sp, #172] ; 0xac + 2f9d8: 3301 adds r3, #1 + 2f9da: 3202 adds r2, #2 + 2f9dc: a822 add r0, sp, #136 ; 0x88 + 2f9de: 2102 movs r1, #2 + 2f9e0: 2b07 cmp r3, #7 + 2f9e2: e884 0003 stmia.w r4, {r0, r1} + 2f9e6: 922b str r2, [sp, #172] ; 0xac + 2f9e8: 932a str r3, [sp, #168] ; 0xa8 + 2f9ea: bfd8 it le + 2f9ec: 3408 addle r4, #8 + 2f9ee: dd04 ble.n 2f9fa <__rtl_vfprintf_r_v1_00+0x39a> + 2f9f0: 2a00 cmp r2, #0 + 2f9f2: f040 8475 bne.w 302e0 <__rtl_vfprintf_r_v1_00+0xc80> + 2f9f6: 4644 mov r4, r8 + 2f9f8: 922a str r2, [sp, #168] ; 0xa8 + 2f9fa: 9b14 ldr r3, [sp, #80] ; 0x50 + 2f9fc: 2b80 cmp r3, #128 ; 0x80 + 2f9fe: f000 8332 beq.w 30066 <__rtl_vfprintf_r_v1_00+0xa06> + 2fa02: 9b10 ldr r3, [sp, #64] ; 0x40 + 2fa04: ebc3 050c rsb r5, r3, ip + 2fa08: 2d00 cmp r5, #0 + 2fa0a: dd34 ble.n 2fa76 <__rtl_vfprintf_r_v1_00+0x416> + 2fa0c: 2d10 cmp r5, #16 + 2fa0e: f340 85d2 ble.w 305b6 <__rtl_vfprintf_r_v1_00+0xf56> + 2fa12: 4aa7 ldr r2, [pc, #668] ; (2fcb0 <__rtl_vfprintf_r_v1_00+0x650>) + 2fa14: 46a6 mov lr, r4 + 2fa16: 9b2b ldr r3, [sp, #172] ; 0xac + 2fa18: 992a ldr r1, [sp, #168] ; 0xa8 + 2fa1a: 920e str r2, [sp, #56] ; 0x38 + 2fa1c: f04f 0a10 mov.w sl, #16 + 2fa20: 9c0c ldr r4, [sp, #48] ; 0x30 + 2fa22: e006 b.n 2fa32 <__rtl_vfprintf_r_v1_00+0x3d2> + 2fa24: 1c88 adds r0, r1, #2 + 2fa26: 4611 mov r1, r2 + 2fa28: f10e 0e08 add.w lr, lr, #8 + 2fa2c: 3d10 subs r5, #16 + 2fa2e: 2d10 cmp r5, #16 + 2fa30: dd11 ble.n 2fa56 <__rtl_vfprintf_r_v1_00+0x3f6> + 2fa32: 1c4a adds r2, r1, #1 + 2fa34: 3310 adds r3, #16 + 2fa36: 2a07 cmp r2, #7 + 2fa38: 932b str r3, [sp, #172] ; 0xac + 2fa3a: e88e 0600 stmia.w lr, {r9, sl} + 2fa3e: 922a str r2, [sp, #168] ; 0xa8 + 2fa40: ddf0 ble.n 2fa24 <__rtl_vfprintf_r_v1_00+0x3c4> + 2fa42: 2b00 cmp r3, #0 + 2fa44: f040 8244 bne.w 2fed0 <__rtl_vfprintf_r_v1_00+0x870> + 2fa48: 3d10 subs r5, #16 + 2fa4a: 2d10 cmp r5, #16 + 2fa4c: f04f 0001 mov.w r0, #1 + 2fa50: 4619 mov r1, r3 + 2fa52: 46c6 mov lr, r8 + 2fa54: dced bgt.n 2fa32 <__rtl_vfprintf_r_v1_00+0x3d2> + 2fa56: 4674 mov r4, lr + 2fa58: 990e ldr r1, [sp, #56] ; 0x38 + 2fa5a: 442b add r3, r5 + 2fa5c: 2807 cmp r0, #7 + 2fa5e: e884 0022 stmia.w r4, {r1, r5} + 2fa62: 932b str r3, [sp, #172] ; 0xac + 2fa64: 902a str r0, [sp, #168] ; 0xa8 + 2fa66: bfd8 it le + 2fa68: 3408 addle r4, #8 + 2fa6a: dd04 ble.n 2fa76 <__rtl_vfprintf_r_v1_00+0x416> + 2fa6c: 2b00 cmp r3, #0 + 2fa6e: f040 8467 bne.w 30340 <__rtl_vfprintf_r_v1_00+0xce0> + 2fa72: 4644 mov r4, r8 + 2fa74: 932a str r3, [sp, #168] ; 0xa8 + 2fa76: 9d08 ldr r5, [sp, #32] + 2fa78: 05e9 lsls r1, r5, #23 + 2fa7a: f100 82a1 bmi.w 2ffc0 <__rtl_vfprintf_r_v1_00+0x960> + 2fa7e: 9a2a ldr r2, [sp, #168] ; 0xa8 + 2fa80: 9b2b ldr r3, [sp, #172] ; 0xac + 2fa82: 9d10 ldr r5, [sp, #64] ; 0x40 + 2fa84: 3201 adds r2, #1 + 2fa86: 442b add r3, r5 + 2fa88: 2a07 cmp r2, #7 + 2fa8a: 6026 str r6, [r4, #0] + 2fa8c: 6065 str r5, [r4, #4] + 2fa8e: 932b str r3, [sp, #172] ; 0xac + 2fa90: 922a str r2, [sp, #168] ; 0xa8 + 2fa92: f300 824a bgt.w 2ff2a <__rtl_vfprintf_r_v1_00+0x8ca> + 2fa96: 3408 adds r4, #8 + 2fa98: 9d08 ldr r5, [sp, #32] + 2fa9a: 076a lsls r2, r5, #29 + 2fa9c: f140 824e bpl.w 2ff3c <__rtl_vfprintf_r_v1_00+0x8dc> + 2faa0: 980b ldr r0, [sp, #44] ; 0x2c + 2faa2: 990a ldr r1, [sp, #40] ; 0x28 + 2faa4: 1a45 subs r5, r0, r1 + 2faa6: 2d00 cmp r5, #0 + 2faa8: f340 8248 ble.w 2ff3c <__rtl_vfprintf_r_v1_00+0x8dc> + 2faac: 2d10 cmp r5, #16 + 2faae: f340 8775 ble.w 3099c <__rtl_vfprintf_r_v1_00+0x133c> + 2fab2: f64e 4004 movw r0, #60420 ; 0xec04 + 2fab6: f2c0 0003 movt r0, #3 + 2faba: 46a6 mov lr, r4 + 2fabc: 900e str r0, [sp, #56] ; 0x38 + 2fabe: 992a ldr r1, [sp, #168] ; 0xa8 + 2fac0: 2610 movs r6, #16 + 2fac2: 9f0c ldr r7, [sp, #48] ; 0x30 + 2fac4: f8dd a024 ldr.w sl, [sp, #36] ; 0x24 + 2fac8: 9c12 ldr r4, [sp, #72] ; 0x48 + 2faca: e006 b.n 2fada <__rtl_vfprintf_r_v1_00+0x47a> + 2facc: 1c88 adds r0, r1, #2 + 2face: 4611 mov r1, r2 + 2fad0: f10e 0e08 add.w lr, lr, #8 + 2fad4: 3d10 subs r5, #16 + 2fad6: 2d10 cmp r5, #16 + 2fad8: dd11 ble.n 2fafe <__rtl_vfprintf_r_v1_00+0x49e> + 2fada: 1c4a adds r2, r1, #1 + 2fadc: 3310 adds r3, #16 + 2fade: 2a07 cmp r2, #7 + 2fae0: 932b str r3, [sp, #172] ; 0xac + 2fae2: e88e 0050 stmia.w lr, {r4, r6} + 2fae6: 922a str r2, [sp, #168] ; 0xa8 + 2fae8: ddf0 ble.n 2facc <__rtl_vfprintf_r_v1_00+0x46c> + 2faea: 2b00 cmp r3, #0 + 2faec: f040 824a bne.w 2ff84 <__rtl_vfprintf_r_v1_00+0x924> + 2faf0: 3d10 subs r5, #16 + 2faf2: 2d10 cmp r5, #16 + 2faf4: f04f 0001 mov.w r0, #1 + 2faf8: 4619 mov r1, r3 + 2fafa: 46c6 mov lr, r8 + 2fafc: dced bgt.n 2fada <__rtl_vfprintf_r_v1_00+0x47a> + 2fafe: 4674 mov r4, lr + 2fb00: 990e ldr r1, [sp, #56] ; 0x38 + 2fb02: 442b add r3, r5 + 2fb04: 2807 cmp r0, #7 + 2fb06: 932b str r3, [sp, #172] ; 0xac + 2fb08: e884 0022 stmia.w r4, {r1, r5} + 2fb0c: 902a str r0, [sp, #168] ; 0xa8 + 2fb0e: f340 8215 ble.w 2ff3c <__rtl_vfprintf_r_v1_00+0x8dc> + 2fb12: 2b00 cmp r3, #0 + 2fb14: f040 8656 bne.w 307c4 <__rtl_vfprintf_r_v1_00+0x1164> + 2fb18: 9c11 ldr r4, [sp, #68] ; 0x44 + 2fb1a: 980a ldr r0, [sp, #40] ; 0x28 + 2fb1c: 9d0b ldr r5, [sp, #44] ; 0x2c + 2fb1e: 42a8 cmp r0, r5 + 2fb20: bfac ite ge + 2fb22: 1824 addge r4, r4, r0 + 2fb24: 1964 addlt r4, r4, r5 + 2fb26: 9411 str r4, [sp, #68] ; 0x44 + 2fb28: e217 b.n 2ff5a <__rtl_vfprintf_r_v1_00+0x8fa> + 2fb2a: f003 0007 and.w r0, r3, #7 + 2fb2e: 3030 adds r0, #48 ; 0x30 + 2fb30: 08db lsrs r3, r3, #3 + 2fb32: 460e mov r6, r1 + 2fb34: 7008 strb r0, [r1, #0] + 2fb36: f101 31ff add.w r1, r1, #4294967295 + 2fb3a: d1f6 bne.n 2fb2a <__rtl_vfprintf_r_v1_00+0x4ca> + 2fb3c: 9d08 ldr r5, [sp, #32] + 2fb3e: 4633 mov r3, r6 + 2fb40: 07ed lsls r5, r5, #31 + 2fb42: f140 82e6 bpl.w 30112 <__rtl_vfprintf_r_v1_00+0xab2> + 2fb46: 2830 cmp r0, #48 ; 0x30 + 2fb48: f43f aed1 beq.w 2f8ee <__rtl_vfprintf_r_v1_00+0x28e> + 2fb4c: 460e mov r6, r1 + 2fb4e: 2130 movs r1, #48 ; 0x30 + 2fb50: ebc6 0508 rsb r5, r6, r8 + 2fb54: 9510 str r5, [sp, #64] ; 0x40 + 2fb56: f803 1c01 strb.w r1, [r3, #-1] + 2fb5a: e6cb b.n 2f8f4 <__rtl_vfprintf_r_v1_00+0x294> + 2fb5c: 222b movs r2, #43 ; 0x2b + 2fb5e: 465d mov r5, fp + 2fb60: e605 b.n 2f76e <__rtl_vfprintf_r_v1_00+0x10e> + 2fb62: 9d08 ldr r5, [sp, #32] + 2fb64: 910b str r1, [sp, #44] ; 0x2c + 2fb66: 06ea lsls r2, r5, #27 + 2fb68: 4684 mov ip, r0 + 2fb6a: d52c bpl.n 2fbc6 <__rtl_vfprintf_r_v1_00+0x566> + 2fb6c: 9d0f ldr r5, [sp, #60] ; 0x3c + 2fb6e: 2101 movs r1, #1 + 2fb70: 682b ldr r3, [r5, #0] + 2fb72: 3504 adds r5, #4 + 2fb74: 950f str r5, [sp, #60] ; 0x3c + 2fb76: e694 b.n 2f8a2 <__rtl_vfprintf_r_v1_00+0x242> + 2fb78: 9d08 ldr r5, [sp, #32] + 2fb7a: f045 0580 orr.w r5, r5, #128 ; 0x80 + 2fb7e: 9508 str r5, [sp, #32] + 2fb80: 465d mov r5, fp + 2fb82: e5f4 b.n 2f76e <__rtl_vfprintf_r_v1_00+0x10e> + 2fb84: 9d08 ldr r5, [sp, #32] + 2fb86: 910b str r1, [sp, #44] ; 0x2c + 2fb88: f045 0510 orr.w r5, r5, #16 + 2fb8c: 9508 str r5, [sp, #32] + 2fb8e: 9d08 ldr r5, [sp, #32] + 2fb90: 4684 mov ip, r0 + 2fb92: f015 0310 ands.w r3, r5, #16 + 2fb96: f47f ae7f bne.w 2f898 <__rtl_vfprintf_r_v1_00+0x238> + 2fb9a: 9d08 ldr r5, [sp, #32] + 2fb9c: f015 0140 ands.w r1, r5, #64 ; 0x40 + 2fba0: bf15 itete ne + 2fba2: 9d0f ldrne r5, [sp, #60] ; 0x3c + 2fba4: 9d0f ldreq r5, [sp, #60] ; 0x3c + 2fba6: 4619 movne r1, r3 + 2fba8: 682b ldreq r3, [r5, #0] + 2fbaa: bf18 it ne + 2fbac: 882b ldrhne r3, [r5, #0] + 2fbae: 3504 adds r5, #4 + 2fbb0: 950f str r5, [sp, #60] ; 0x3c + 2fbb2: e676 b.n 2f8a2 <__rtl_vfprintf_r_v1_00+0x242> + 2fbb4: 9d08 ldr r5, [sp, #32] + 2fbb6: 910b str r1, [sp, #44] ; 0x2c + 2fbb8: f045 0510 orr.w r5, r5, #16 + 2fbbc: 9508 str r5, [sp, #32] + 2fbbe: 9d08 ldr r5, [sp, #32] + 2fbc0: 4684 mov ip, r0 + 2fbc2: 06ea lsls r2, r5, #27 + 2fbc4: d4d2 bmi.n 2fb6c <__rtl_vfprintf_r_v1_00+0x50c> + 2fbc6: 9d08 ldr r5, [sp, #32] + 2fbc8: 2101 movs r1, #1 + 2fbca: f015 0f40 tst.w r5, #64 ; 0x40 + 2fbce: 9d0f ldr r5, [sp, #60] ; 0x3c + 2fbd0: bf14 ite ne + 2fbd2: 882b ldrhne r3, [r5, #0] + 2fbd4: 682b ldreq r3, [r5, #0] + 2fbd6: 3504 adds r5, #4 + 2fbd8: 950f str r5, [sp, #60] ; 0x3c + 2fbda: e662 b.n 2f8a2 <__rtl_vfprintf_r_v1_00+0x242> + 2fbdc: f243 75f0 movw r5, #14320 ; 0x37f0 + 2fbe0: f2c0 0504 movt r5, #4 + 2fbe4: 9518 str r5, [sp, #96] ; 0x60 + 2fbe6: 9d08 ldr r5, [sp, #32] + 2fbe8: 910b str r1, [sp, #44] ; 0x2c + 2fbea: 06eb lsls r3, r5, #27 + 2fbec: 4684 mov ip, r0 + 2fbee: f88d 2087 strb.w r2, [sp, #135] ; 0x87 + 2fbf2: d54e bpl.n 2fc92 <__rtl_vfprintf_r_v1_00+0x632> + 2fbf4: 9d0f ldr r5, [sp, #60] ; 0x3c + 2fbf6: 682b ldr r3, [r5, #0] + 2fbf8: 3504 adds r5, #4 + 2fbfa: 950f str r5, [sp, #60] ; 0x3c + 2fbfc: 9d08 ldr r5, [sp, #32] + 2fbfe: 07ee lsls r6, r5, #31 + 2fc00: d553 bpl.n 2fcaa <__rtl_vfprintf_r_v1_00+0x64a> + 2fc02: 2b00 cmp r3, #0 + 2fc04: d051 beq.n 2fcaa <__rtl_vfprintf_r_v1_00+0x64a> + 2fc06: 2230 movs r2, #48 ; 0x30 + 2fc08: f045 0502 orr.w r5, r5, #2 + 2fc0c: f88d 7089 strb.w r7, [sp, #137] ; 0x89 + 2fc10: 9508 str r5, [sp, #32] + 2fc12: f88d 2088 strb.w r2, [sp, #136] ; 0x88 + 2fc16: 2102 movs r1, #2 + 2fc18: e643 b.n 2f8a2 <__rtl_vfprintf_r_v1_00+0x242> + 2fc1a: 2501 movs r5, #1 + 2fc1c: 910b str r1, [sp, #44] ; 0x2c + 2fc1e: 950a str r5, [sp, #40] ; 0x28 + 2fc20: 990f ldr r1, [sp, #60] ; 0x3c + 2fc22: 9d0f ldr r5, [sp, #60] ; 0x3c + 2fc24: 6809 ldr r1, [r1, #0] + 2fc26: 3504 adds r5, #4 + 2fc28: 2300 movs r3, #0 + 2fc2a: 950f str r5, [sp, #60] ; 0x3c + 2fc2c: 2501 movs r5, #1 + 2fc2e: 461a mov r2, r3 + 2fc30: f88d 10b0 strb.w r1, [sp, #176] ; 0xb0 + 2fc34: f88d 3087 strb.w r3, [sp, #135] ; 0x87 + 2fc38: 469c mov ip, r3 + 2fc3a: 9319 str r3, [sp, #100] ; 0x64 + 2fc3c: 9510 str r5, [sp, #64] ; 0x40 + 2fc3e: ae2c add r6, sp, #176 ; 0xb0 + 2fc40: e663 b.n 2f90a <__rtl_vfprintf_r_v1_00+0x2aa> + 2fc42: 9d08 ldr r5, [sp, #32] + 2fc44: 910b str r1, [sp, #44] ; 0x2c + 2fc46: 06ed lsls r5, r5, #27 + 2fc48: 4684 mov ip, r0 + 2fc4a: f88d 2087 strb.w r2, [sp, #135] ; 0x87 + 2fc4e: f140 80bf bpl.w 2fdd0 <__rtl_vfprintf_r_v1_00+0x770> + 2fc52: 9d0f ldr r5, [sp, #60] ; 0x3c + 2fc54: 682b ldr r3, [r5, #0] + 2fc56: 3504 adds r5, #4 + 2fc58: 950f str r5, [sp, #60] ; 0x3c + 2fc5a: 2b00 cmp r3, #0 + 2fc5c: bfb7 itett lt + 2fc5e: 222d movlt r2, #45 ; 0x2d + 2fc60: f89d 2087 ldrbge.w r2, [sp, #135] ; 0x87 + 2fc64: 425b neglt r3, r3 + 2fc66: f88d 2087 strblt.w r2, [sp, #135] ; 0x87 + 2fc6a: 2101 movs r1, #1 + 2fc6c: e61d b.n 2f8aa <__rtl_vfprintf_r_v1_00+0x24a> + 2fc6e: 9d08 ldr r5, [sp, #32] + 2fc70: f045 0540 orr.w r5, r5, #64 ; 0x40 + 2fc74: 9508 str r5, [sp, #32] + 2fc76: 465d mov r5, fp + 2fc78: e579 b.n 2f76e <__rtl_vfprintf_r_v1_00+0x10e> + 2fc7a: f643 0504 movw r5, #14340 ; 0x3804 + 2fc7e: f2c0 0504 movt r5, #4 + 2fc82: 9518 str r5, [sp, #96] ; 0x60 + 2fc84: 9d08 ldr r5, [sp, #32] + 2fc86: 910b str r1, [sp, #44] ; 0x2c + 2fc88: 06eb lsls r3, r5, #27 + 2fc8a: 4684 mov ip, r0 + 2fc8c: f88d 2087 strb.w r2, [sp, #135] ; 0x87 + 2fc90: d4b0 bmi.n 2fbf4 <__rtl_vfprintf_r_v1_00+0x594> + 2fc92: 9d08 ldr r5, [sp, #32] + 2fc94: f015 0f40 tst.w r5, #64 ; 0x40 + 2fc98: 9d0f ldr r5, [sp, #60] ; 0x3c + 2fc9a: bf14 ite ne + 2fc9c: 882b ldrhne r3, [r5, #0] + 2fc9e: 682b ldreq r3, [r5, #0] + 2fca0: 3504 adds r5, #4 + 2fca2: 950f str r5, [sp, #60] ; 0x3c + 2fca4: 9d08 ldr r5, [sp, #32] + 2fca6: 07ee lsls r6, r5, #31 + 2fca8: d4ab bmi.n 2fc02 <__rtl_vfprintf_r_v1_00+0x5a2> + 2fcaa: 2102 movs r1, #2 + 2fcac: e5f9 b.n 2f8a2 <__rtl_vfprintf_r_v1_00+0x242> + 2fcae: bf00 nop + 2fcb0: 0003ec14 .word 0x0003ec14 + 2fcb4: 9d08 ldr r5, [sp, #32] + 2fcb6: f88d 2087 strb.w r2, [sp, #135] ; 0x87 + 2fcba: 06e8 lsls r0, r5, #27 + 2fcbc: f100 8101 bmi.w 2fec2 <__rtl_vfprintf_r_v1_00+0x862> + 2fcc0: 9d08 ldr r5, [sp, #32] + 2fcc2: 0669 lsls r1, r5, #25 + 2fcc4: f140 80fd bpl.w 2fec2 <__rtl_vfprintf_r_v1_00+0x862> + 2fcc8: 9d0f ldr r5, [sp, #60] ; 0x3c + 2fcca: 682b ldr r3, [r5, #0] + 2fccc: 3504 adds r5, #4 + 2fcce: 950f str r5, [sp, #60] ; 0x3c + 2fcd0: 9d11 ldr r5, [sp, #68] ; 0x44 + 2fcd2: 801d strh r5, [r3, #0] + 2fcd4: e517 b.n 2f706 <__rtl_vfprintf_r_v1_00+0xa6> + 2fcd6: 9d08 ldr r5, [sp, #32] + 2fcd8: f045 0508 orr.w r5, r5, #8 + 2fcdc: 9508 str r5, [sp, #32] + 2fcde: 465d mov r5, fp + 2fce0: e545 b.n 2f76e <__rtl_vfprintf_r_v1_00+0x10e> + 2fce2: 2a00 cmp r2, #0 + 2fce4: bf08 it eq + 2fce6: 2220 moveq r2, #32 + 2fce8: 465d mov r5, fp + 2fcea: e540 b.n 2f76e <__rtl_vfprintf_r_v1_00+0x10e> + 2fcec: 9d08 ldr r5, [sp, #32] + 2fcee: f045 0501 orr.w r5, r5, #1 + 2fcf2: 9508 str r5, [sp, #32] + 2fcf4: 465d mov r5, fp + 2fcf6: e53a b.n 2f76e <__rtl_vfprintf_r_v1_00+0x10e> + 2fcf8: 9d0f ldr r5, [sp, #60] ; 0x3c + 2fcfa: 462b mov r3, r5 + 2fcfc: 6829 ldr r1, [r5, #0] + 2fcfe: 3304 adds r3, #4 + 2fd00: 2900 cmp r1, #0 + 2fd02: f6ff adba blt.w 2f87a <__rtl_vfprintf_r_v1_00+0x21a> + 2fd06: 930f str r3, [sp, #60] ; 0x3c + 2fd08: 465d mov r5, fp + 2fd0a: e530 b.n 2f76e <__rtl_vfprintf_r_v1_00+0x10e> + 2fd0c: 9d0f ldr r5, [sp, #60] ; 0x3c + 2fd0e: 4684 mov ip, r0 + 2fd10: 682e ldr r6, [r5, #0] + 2fd12: 980f ldr r0, [sp, #60] ; 0x3c + 2fd14: 2500 movs r5, #0 + 2fd16: 910b str r1, [sp, #44] ; 0x2c + 2fd18: f88d 5087 strb.w r5, [sp, #135] ; 0x87 + 2fd1c: f100 0a04 add.w sl, r0, #4 + 2fd20: 2e00 cmp r6, #0 + 2fd22: f000 85fb beq.w 3091c <__rtl_vfprintf_r_v1_00+0x12bc> + 2fd26: f1bc 0f00 cmp.w ip, #0 + 2fd2a: f2c0 8565 blt.w 307f8 <__rtl_vfprintf_r_v1_00+0x1198> + 2fd2e: f648 234d movw r3, #35405 ; 0x8a4d + 2fd32: 4662 mov r2, ip + 2fd34: f8cd c018 str.w ip, [sp, #24] + 2fd38: 4630 mov r0, r6 + 2fd3a: f2c0 0302 movt r3, #2 + 2fd3e: 4629 mov r1, r5 + 2fd40: 4798 blx r3 + 2fd42: f8dd c018 ldr.w ip, [sp, #24] + 2fd46: 2800 cmp r0, #0 + 2fd48: f000 8638 beq.w 309bc <__rtl_vfprintf_r_v1_00+0x135c> + 2fd4c: 1b80 subs r0, r0, r6 + 2fd4e: 4560 cmp r0, ip + 2fd50: bfa8 it ge + 2fd52: 4660 movge r0, ip + 2fd54: 46ac mov ip, r5 + 2fd56: ea20 75e0 bic.w r5, r0, r0, asr #31 + 2fd5a: 9010 str r0, [sp, #64] ; 0x40 + 2fd5c: f8cd a03c str.w sl, [sp, #60] ; 0x3c + 2fd60: 950a str r5, [sp, #40] ; 0x28 + 2fd62: f8cd c064 str.w ip, [sp, #100] ; 0x64 + 2fd66: f89d 2087 ldrb.w r2, [sp, #135] ; 0x87 + 2fd6a: e5ca b.n 2f902 <__rtl_vfprintf_r_v1_00+0x2a2> + 2fd6c: 9d08 ldr r5, [sp, #32] + 2fd6e: 9b0f ldr r3, [sp, #60] ; 0x3c + 2fd70: f045 0502 orr.w r5, r5, #2 + 2fd74: 9508 str r5, [sp, #32] + 2fd76: 9d0f ldr r5, [sp, #60] ; 0x3c + 2fd78: 2230 movs r2, #48 ; 0x30 + 2fd7a: 3504 adds r5, #4 + 2fd7c: 950f str r5, [sp, #60] ; 0x3c + 2fd7e: f643 0504 movw r5, #14340 ; 0x3804 + 2fd82: f2c0 0504 movt r5, #4 + 2fd86: 2778 movs r7, #120 ; 0x78 + 2fd88: 910b str r1, [sp, #44] ; 0x2c + 2fd8a: 4684 mov ip, r0 + 2fd8c: 681b ldr r3, [r3, #0] + 2fd8e: 9518 str r5, [sp, #96] ; 0x60 + 2fd90: f88d 2088 strb.w r2, [sp, #136] ; 0x88 + 2fd94: f88d 7089 strb.w r7, [sp, #137] ; 0x89 + 2fd98: 2102 movs r1, #2 + 2fd9a: e582 b.n 2f8a2 <__rtl_vfprintf_r_v1_00+0x242> + 2fd9c: f1a7 0330 sub.w r3, r7, #48 ; 0x30 + 2fda0: 2100 movs r1, #0 + 2fda2: f81b 7b01 ldrb.w r7, [fp], #1 + 2fda6: eb01 0181 add.w r1, r1, r1, lsl #2 + 2fdaa: eb03 0141 add.w r1, r3, r1, lsl #1 + 2fdae: f1a7 0330 sub.w r3, r7, #48 ; 0x30 + 2fdb2: 2b09 cmp r3, #9 + 2fdb4: d9f5 bls.n 2fda2 <__rtl_vfprintf_r_v1_00+0x742> + 2fdb6: e4dd b.n 2f774 <__rtl_vfprintf_r_v1_00+0x114> + 2fdb8: 9d08 ldr r5, [sp, #32] + 2fdba: 910b str r1, [sp, #44] ; 0x2c + 2fdbc: f045 0510 orr.w r5, r5, #16 + 2fdc0: 9508 str r5, [sp, #32] + 2fdc2: 9d08 ldr r5, [sp, #32] + 2fdc4: 4684 mov ip, r0 + 2fdc6: 06ed lsls r5, r5, #27 + 2fdc8: f88d 2087 strb.w r2, [sp, #135] ; 0x87 + 2fdcc: f53f af41 bmi.w 2fc52 <__rtl_vfprintf_r_v1_00+0x5f2> + 2fdd0: 9d08 ldr r5, [sp, #32] + 2fdd2: f015 0f40 tst.w r5, #64 ; 0x40 + 2fdd6: 9d0f ldr r5, [sp, #60] ; 0x3c + 2fdd8: bf14 ite ne + 2fdda: f9b5 3000 ldrshne.w r3, [r5] + 2fdde: 682b ldreq r3, [r5, #0] + 2fde0: 3504 adds r5, #4 + 2fde2: 950f str r5, [sp, #60] ; 0x3c + 2fde4: e739 b.n 2fc5a <__rtl_vfprintf_r_v1_00+0x5fa> + 2fde6: 9d08 ldr r5, [sp, #32] + 2fde8: 9b0f ldr r3, [sp, #60] ; 0x3c + 2fdea: 4684 mov ip, r0 + 2fdec: 3307 adds r3, #7 + 2fdee: 0728 lsls r0, r5, #28 + 2fdf0: 910b str r1, [sp, #44] ; 0x2c + 2fdf2: f88d 2087 strb.w r2, [sp, #135] ; 0x87 + 2fdf6: f023 0307 bic.w r3, r3, #7 + 2fdfa: f140 8323 bpl.w 30444 <__rtl_vfprintf_r_v1_00+0xde4> + 2fdfe: f103 0508 add.w r5, r3, #8 + 2fe02: 950f str r5, [sp, #60] ; 0x3c + 2fe04: 681d ldr r5, [r3, #0] + 2fe06: 685b ldr r3, [r3, #4] + 2fe08: 951a str r5, [sp, #104] ; 0x68 + 2fe0a: 931b str r3, [sp, #108] ; 0x6c + 2fe0c: 981a ldr r0, [sp, #104] ; 0x68 + 2fe0e: 991b ldr r1, [sp, #108] ; 0x6c + 2fe10: f8cd c018 str.w ip, [sp, #24] + 2fe14: f000 fefe bl 30c14 <__rtl_fpclassifyd> + 2fe18: 2801 cmp r0, #1 + 2fe1a: f8dd c018 ldr.w ip, [sp, #24] + 2fe1e: 981a ldr r0, [sp, #104] ; 0x68 + 2fe20: f000 8497 beq.w 30752 <__rtl_vfprintf_r_v1_00+0x10f2> + 2fe24: 991b ldr r1, [sp, #108] ; 0x6c + 2fe26: f8cd c018 str.w ip, [sp, #24] + 2fe2a: f000 fef3 bl 30c14 <__rtl_fpclassifyd> + 2fe2e: f8dd c018 ldr.w ip, [sp, #24] + 2fe32: 2800 cmp r0, #0 + 2fe34: f040 8321 bne.w 3047a <__rtl_vfprintf_r_v1_00+0xe1a> + 2fe38: f243 76ec movw r6, #14316 ; 0x37ec + 2fe3c: f243 73e8 movw r3, #14312 ; 0x37e8 + 2fe40: f2c0 0604 movt r6, #4 + 2fe44: f2c0 0304 movt r3, #4 + 2fe48: 2503 movs r5, #3 + 2fe4a: 950a str r5, [sp, #40] ; 0x28 + 2fe4c: 9d08 ldr r5, [sp, #32] + 2fe4e: 4684 mov ip, r0 + 2fe50: f025 0580 bic.w r5, r5, #128 ; 0x80 + 2fe54: 9508 str r5, [sp, #32] + 2fe56: 2503 movs r5, #3 + 2fe58: 2f47 cmp r7, #71 ; 0x47 + 2fe5a: bfd8 it le + 2fe5c: 461e movle r6, r3 + 2fe5e: 9019 str r0, [sp, #100] ; 0x64 + 2fe60: 9510 str r5, [sp, #64] ; 0x40 + 2fe62: f89d 2087 ldrb.w r2, [sp, #135] ; 0x87 + 2fe66: e54c b.n 2f902 <__rtl_vfprintf_r_v1_00+0x2a2> + 2fe68: f89b 7000 ldrb.w r7, [fp] + 2fe6c: f10b 0b01 add.w fp, fp, #1 + 2fe70: 2f2a cmp r7, #42 ; 0x2a + 2fe72: f000 8676 beq.w 30b62 <__rtl_vfprintf_r_v1_00+0x1502> + 2fe76: f1a7 0330 sub.w r3, r7, #48 ; 0x30 + 2fe7a: 2b09 cmp r3, #9 + 2fe7c: f04f 0000 mov.w r0, #0 + 2fe80: f63f ac78 bhi.w 2f774 <__rtl_vfprintf_r_v1_00+0x114> + 2fe84: f81b 7b01 ldrb.w r7, [fp], #1 + 2fe88: eb00 0080 add.w r0, r0, r0, lsl #2 + 2fe8c: eb03 0040 add.w r0, r3, r0, lsl #1 + 2fe90: f1a7 0330 sub.w r3, r7, #48 ; 0x30 + 2fe94: 2b09 cmp r3, #9 + 2fe96: d9f5 bls.n 2fe84 <__rtl_vfprintf_r_v1_00+0x824> + 2fe98: ea40 70e0 orr.w r0, r0, r0, asr #31 + 2fe9c: e46a b.n 2f774 <__rtl_vfprintf_r_v1_00+0x114> + 2fe9e: 910b str r1, [sp, #44] ; 0x2c + 2fea0: f88d 2087 strb.w r2, [sp, #135] ; 0x87 + 2fea4: 2f00 cmp r7, #0 + 2fea6: d05d beq.n 2ff64 <__rtl_vfprintf_r_v1_00+0x904> + 2fea8: 2300 movs r3, #0 + 2feaa: 2501 movs r5, #1 + 2feac: 461a mov r2, r3 + 2feae: 950a str r5, [sp, #40] ; 0x28 + 2feb0: f88d 70b0 strb.w r7, [sp, #176] ; 0xb0 + 2feb4: f88d 3087 strb.w r3, [sp, #135] ; 0x87 + 2feb8: 469c mov ip, r3 + 2feba: 9319 str r3, [sp, #100] ; 0x64 + 2febc: 9510 str r5, [sp, #64] ; 0x40 + 2febe: ae2c add r6, sp, #176 ; 0xb0 + 2fec0: e523 b.n 2f90a <__rtl_vfprintf_r_v1_00+0x2aa> + 2fec2: 9d0f ldr r5, [sp, #60] ; 0x3c + 2fec4: 682b ldr r3, [r5, #0] + 2fec6: 3504 adds r5, #4 + 2fec8: 950f str r5, [sp, #60] ; 0x3c + 2feca: 9d11 ldr r5, [sp, #68] ; 0x44 + 2fecc: 601d str r5, [r3, #0] + 2fece: e41a b.n 2f706 <__rtl_vfprintf_r_v1_00+0xa6> + 2fed0: 4620 mov r0, r4 + 2fed2: 9909 ldr r1, [sp, #36] ; 0x24 + 2fed4: aa29 add r2, sp, #164 ; 0xa4 + 2fed6: f7ff f9bd bl 2f254 <__rtl_sprint_r_v1_00.part.9> + 2feda: 2800 cmp r0, #0 + 2fedc: d149 bne.n 2ff72 <__rtl_vfprintf_r_v1_00+0x912> + 2fede: 992a ldr r1, [sp, #168] ; 0xa8 + 2fee0: 46c6 mov lr, r8 + 2fee2: 9b2b ldr r3, [sp, #172] ; 0xac + 2fee4: 1c48 adds r0, r1, #1 + 2fee6: e5a1 b.n 2fa2c <__rtl_vfprintf_r_v1_00+0x3cc> + 2fee8: 980c ldr r0, [sp, #48] ; 0x30 + 2feea: 9909 ldr r1, [sp, #36] ; 0x24 + 2feec: aa29 add r2, sp, #164 ; 0xa4 + 2feee: f7ff f9b1 bl 2f254 <__rtl_sprint_r_v1_00.part.9> + 2fef2: 2800 cmp r0, #0 + 2fef4: d13d bne.n 2ff72 <__rtl_vfprintf_r_v1_00+0x912> + 2fef6: 982a ldr r0, [sp, #168] ; 0xa8 + 2fef8: 46c4 mov ip, r8 + 2fefa: 9a2b ldr r2, [sp, #172] ; 0xac + 2fefc: f100 0e01 add.w lr, r0, #1 + 2ff00: e52b b.n 2f95a <__rtl_vfprintf_r_v1_00+0x2fa> + 2ff02: 980c ldr r0, [sp, #48] ; 0x30 + 2ff04: 9909 ldr r1, [sp, #36] ; 0x24 + 2ff06: aa29 add r2, sp, #164 ; 0xa4 + 2ff08: f7ff f9a4 bl 2f254 <__rtl_sprint_r_v1_00.part.9> + 2ff0c: 2800 cmp r0, #0 + 2ff0e: d130 bne.n 2ff72 <__rtl_vfprintf_r_v1_00+0x912> + 2ff10: 4644 mov r4, r8 + 2ff12: 982a ldr r0, [sp, #168] ; 0xa8 + 2ff14: 9b2b ldr r3, [sp, #172] ; 0xac + 2ff16: 3001 adds r0, #1 + 2ff18: 9d0d ldr r5, [sp, #52] ; 0x34 + 2ff1a: 2807 cmp r0, #7 + 2ff1c: 442b add r3, r5 + 2ff1e: 932b str r3, [sp, #172] ; 0xac + 2ff20: 6026 str r6, [r4, #0] + 2ff22: 6065 str r5, [r4, #4] + 2ff24: 902a str r0, [sp, #168] ; 0xa8 + 2ff26: f77f adb6 ble.w 2fa96 <__rtl_vfprintf_r_v1_00+0x436> + 2ff2a: 2b00 cmp r3, #0 + 2ff2c: f040 8213 bne.w 30356 <__rtl_vfprintf_r_v1_00+0xcf6> + 2ff30: 9d08 ldr r5, [sp, #32] + 2ff32: 932a str r3, [sp, #168] ; 0xa8 + 2ff34: 076a lsls r2, r5, #29 + 2ff36: 4644 mov r4, r8 + 2ff38: f53f adb2 bmi.w 2faa0 <__rtl_vfprintf_r_v1_00+0x440> + 2ff3c: 9c11 ldr r4, [sp, #68] ; 0x44 + 2ff3e: 980a ldr r0, [sp, #40] ; 0x28 + 2ff40: 9d0b ldr r5, [sp, #44] ; 0x2c + 2ff42: 42a8 cmp r0, r5 + 2ff44: bfac ite ge + 2ff46: 1824 addge r4, r4, r0 + 2ff48: 1964 addlt r4, r4, r5 + 2ff4a: 9411 str r4, [sp, #68] ; 0x44 + 2ff4c: b12b cbz r3, 2ff5a <__rtl_vfprintf_r_v1_00+0x8fa> + 2ff4e: 980c ldr r0, [sp, #48] ; 0x30 + 2ff50: 9909 ldr r1, [sp, #36] ; 0x24 + 2ff52: aa29 add r2, sp, #164 ; 0xa4 + 2ff54: f7ff f97e bl 2f254 <__rtl_sprint_r_v1_00.part.9> + 2ff58: b958 cbnz r0, 2ff72 <__rtl_vfprintf_r_v1_00+0x912> + 2ff5a: 2300 movs r3, #0 + 2ff5c: 932a str r3, [sp, #168] ; 0xa8 + 2ff5e: 4644 mov r4, r8 + 2ff60: f7ff bbd1 b.w 2f706 <__rtl_vfprintf_r_v1_00+0xa6> + 2ff64: 9b2b ldr r3, [sp, #172] ; 0xac + 2ff66: b123 cbz r3, 2ff72 <__rtl_vfprintf_r_v1_00+0x912> + 2ff68: 980c ldr r0, [sp, #48] ; 0x30 + 2ff6a: 9909 ldr r1, [sp, #36] ; 0x24 + 2ff6c: aa29 add r2, sp, #164 ; 0xa4 + 2ff6e: f7ff f971 bl 2f254 <__rtl_sprint_r_v1_00.part.9> + 2ff72: 9c09 ldr r4, [sp, #36] ; 0x24 + 2ff74: 89a3 ldrh r3, [r4, #12] + 2ff76: 065b lsls r3, r3, #25 + 2ff78: f53f ac69 bmi.w 2f84e <__rtl_vfprintf_r_v1_00+0x1ee> + 2ff7c: 9811 ldr r0, [sp, #68] ; 0x44 + 2ff7e: b047 add sp, #284 ; 0x11c + 2ff80: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + 2ff84: 4638 mov r0, r7 + 2ff86: 4651 mov r1, sl + 2ff88: aa29 add r2, sp, #164 ; 0xa4 + 2ff8a: f7ff f963 bl 2f254 <__rtl_sprint_r_v1_00.part.9> + 2ff8e: 2800 cmp r0, #0 + 2ff90: d1ef bne.n 2ff72 <__rtl_vfprintf_r_v1_00+0x912> + 2ff92: 992a ldr r1, [sp, #168] ; 0xa8 + 2ff94: 46c6 mov lr, r8 + 2ff96: 9b2b ldr r3, [sp, #172] ; 0xac + 2ff98: 1c48 adds r0, r1, #1 + 2ff9a: e59b b.n 2fad4 <__rtl_vfprintf_r_v1_00+0x474> + 2ff9c: 2900 cmp r1, #0 + 2ff9e: f040 80ad bne.w 300fc <__rtl_vfprintf_r_v1_00+0xa9c> + 2ffa2: 9d08 ldr r5, [sp, #32] + 2ffa4: 07e8 lsls r0, r5, #31 + 2ffa6: bf5c itt pl + 2ffa8: 9110 strpl r1, [sp, #64] ; 0x40 + 2ffaa: 4646 movpl r6, r8 + 2ffac: f57f aca2 bpl.w 2f8f4 <__rtl_vfprintf_r_v1_00+0x294> + 2ffb0: ae46 add r6, sp, #280 ; 0x118 + 2ffb2: 2330 movs r3, #48 ; 0x30 + 2ffb4: f806 3d41 strb.w r3, [r6, #-65]! + 2ffb8: ebc6 0308 rsb r3, r6, r8 + 2ffbc: 9310 str r3, [sp, #64] ; 0x40 + 2ffbe: e499 b.n 2f8f4 <__rtl_vfprintf_r_v1_00+0x294> + 2ffc0: 2f65 cmp r7, #101 ; 0x65 + 2ffc2: f300 8102 bgt.w 301ca <__rtl_vfprintf_r_v1_00+0xb6a> + 2ffc6: 9d0d ldr r5, [sp, #52] ; 0x34 + 2ffc8: 9b2b ldr r3, [sp, #172] ; 0xac + 2ffca: 2d01 cmp r5, #1 + 2ffcc: f340 8197 ble.w 302fe <__rtl_vfprintf_r_v1_00+0xc9e> + 2ffd0: 992a ldr r1, [sp, #168] ; 0xa8 + 2ffd2: 3301 adds r3, #1 + 2ffd4: 1c4a adds r2, r1, #1 + 2ffd6: 2a07 cmp r2, #7 + 2ffd8: f04f 0001 mov.w r0, #1 + 2ffdc: 6026 str r6, [r4, #0] + 2ffde: 6060 str r0, [r4, #4] + 2ffe0: 932b str r3, [sp, #172] ; 0xac + 2ffe2: 922a str r2, [sp, #168] ; 0xa8 + 2ffe4: bfdc itt le + 2ffe6: 3408 addle r4, #8 + 2ffe8: 3102 addle r1, #2 + 2ffea: f340 80ab ble.w 30144 <__rtl_vfprintf_r_v1_00+0xae4> + 2ffee: 2b00 cmp r3, #0 + 2fff0: f040 809c bne.w 3012c <__rtl_vfprintf_r_v1_00+0xacc> + 2fff4: 9c16 ldr r4, [sp, #88] ; 0x58 + 2fff6: 9d1c ldr r5, [sp, #112] ; 0x70 + 2fff8: 9436 str r4, [sp, #216] ; 0xd8 + 2fffa: 4644 mov r4, r8 + 2fffc: 9537 str r5, [sp, #220] ; 0xdc + 2fffe: 952b str r5, [sp, #172] ; 0xac + 30000: 902a str r0, [sp, #168] ; 0xa8 + 30002: 3408 adds r4, #8 + 30004: 981a ldr r0, [sp, #104] ; 0x68 + 30006: 991b ldr r1, [sp, #108] ; 0x6c + 30008: 2200 movs r2, #0 + 3000a: 2300 movs r3, #0 + 3000c: 9d15 ldr r5, [sp, #84] ; 0x54 + 3000e: 47a8 blx r5 + 30010: 2800 cmp r0, #0 + 30012: f000 80a8 beq.w 30166 <__rtl_vfprintf_r_v1_00+0xb06> + 30016: 9b2b ldr r3, [sp, #172] ; 0xac + 30018: 982a ldr r0, [sp, #168] ; 0xa8 + 3001a: 9d0d ldr r5, [sp, #52] ; 0x34 + 3001c: 1c42 adds r2, r0, #1 + 3001e: 3b01 subs r3, #1 + 30020: 3601 adds r6, #1 + 30022: 442b add r3, r5 + 30024: 1e69 subs r1, r5, #1 + 30026: 2a07 cmp r2, #7 + 30028: 6026 str r6, [r4, #0] + 3002a: 932b str r3, [sp, #172] ; 0xac + 3002c: 922a str r2, [sp, #168] ; 0xa8 + 3002e: 6061 str r1, [r4, #4] + 30030: f300 8137 bgt.w 302a2 <__rtl_vfprintf_r_v1_00+0xc42> + 30034: 3408 adds r4, #8 + 30036: 3002 adds r0, #2 + 30038: 9d1d ldr r5, [sp, #116] ; 0x74 + 3003a: aa25 add r2, sp, #148 ; 0x94 + 3003c: 442b add r3, r5 + 3003e: 2807 cmp r0, #7 + 30040: 932b str r3, [sp, #172] ; 0xac + 30042: 6065 str r5, [r4, #4] + 30044: 902a str r0, [sp, #168] ; 0xa8 + 30046: 6022 str r2, [r4, #0] + 30048: f77f ad25 ble.w 2fa96 <__rtl_vfprintf_r_v1_00+0x436> + 3004c: 2b00 cmp r3, #0 + 3004e: f43f af6f beq.w 2ff30 <__rtl_vfprintf_r_v1_00+0x8d0> + 30052: 980c ldr r0, [sp, #48] ; 0x30 + 30054: 9909 ldr r1, [sp, #36] ; 0x24 + 30056: aa29 add r2, sp, #164 ; 0xa4 + 30058: f7ff f8fc bl 2f254 <__rtl_sprint_r_v1_00.part.9> + 3005c: 2800 cmp r0, #0 + 3005e: d188 bne.n 2ff72 <__rtl_vfprintf_r_v1_00+0x912> + 30060: 4644 mov r4, r8 + 30062: 9b2b ldr r3, [sp, #172] ; 0xac + 30064: e518 b.n 2fa98 <__rtl_vfprintf_r_v1_00+0x438> + 30066: 980b ldr r0, [sp, #44] ; 0x2c + 30068: 990a ldr r1, [sp, #40] ; 0x28 + 3006a: 1a45 subs r5, r0, r1 + 3006c: 2d00 cmp r5, #0 + 3006e: f77f acc8 ble.w 2fa02 <__rtl_vfprintf_r_v1_00+0x3a2> + 30072: 2d10 cmp r5, #16 + 30074: f340 849b ble.w 309ae <__rtl_vfprintf_r_v1_00+0x134e> + 30078: 48b0 ldr r0, [pc, #704] ; (3033c <__rtl_vfprintf_r_v1_00+0xcdc>) + 3007a: 46a6 mov lr, r4 + 3007c: 9b2b ldr r3, [sp, #172] ; 0xac + 3007e: 462c mov r4, r5 + 30080: 992a ldr r1, [sp, #168] ; 0xa8 + 30082: 900e str r0, [sp, #56] ; 0x38 + 30084: f04f 0a10 mov.w sl, #16 + 30088: 4665 mov r5, ip + 3008a: e006 b.n 3009a <__rtl_vfprintf_r_v1_00+0xa3a> + 3008c: 1c88 adds r0, r1, #2 + 3008e: 4611 mov r1, r2 + 30090: f10e 0e08 add.w lr, lr, #8 + 30094: 3c10 subs r4, #16 + 30096: 2c10 cmp r4, #16 + 30098: dd0f ble.n 300ba <__rtl_vfprintf_r_v1_00+0xa5a> + 3009a: 1c4a adds r2, r1, #1 + 3009c: 3310 adds r3, #16 + 3009e: 2a07 cmp r2, #7 + 300a0: 932b str r3, [sp, #172] ; 0xac + 300a2: e88e 0600 stmia.w lr, {r9, sl} + 300a6: 922a str r2, [sp, #168] ; 0xa8 + 300a8: ddf0 ble.n 3008c <__rtl_vfprintf_r_v1_00+0xa2c> + 300aa: b9d3 cbnz r3, 300e2 <__rtl_vfprintf_r_v1_00+0xa82> + 300ac: 3c10 subs r4, #16 + 300ae: 2c10 cmp r4, #16 + 300b0: f04f 0001 mov.w r0, #1 + 300b4: 4619 mov r1, r3 + 300b6: 46c6 mov lr, r8 + 300b8: dcef bgt.n 3009a <__rtl_vfprintf_r_v1_00+0xa3a> + 300ba: 46ac mov ip, r5 + 300bc: 4625 mov r5, r4 + 300be: 4674 mov r4, lr + 300c0: 990e ldr r1, [sp, #56] ; 0x38 + 300c2: 442b add r3, r5 + 300c4: 2807 cmp r0, #7 + 300c6: e884 0022 stmia.w r4, {r1, r5} + 300ca: 932b str r3, [sp, #172] ; 0xac + 300cc: 902a str r0, [sp, #168] ; 0xa8 + 300ce: bfd8 it le + 300d0: 3408 addle r4, #8 + 300d2: f77f ac96 ble.w 2fa02 <__rtl_vfprintf_r_v1_00+0x3a2> + 300d6: 2b00 cmp r3, #0 + 300d8: f040 837f bne.w 307da <__rtl_vfprintf_r_v1_00+0x117a> + 300dc: 932a str r3, [sp, #168] ; 0xa8 + 300de: 4644 mov r4, r8 + 300e0: e48f b.n 2fa02 <__rtl_vfprintf_r_v1_00+0x3a2> + 300e2: 980c ldr r0, [sp, #48] ; 0x30 + 300e4: 9909 ldr r1, [sp, #36] ; 0x24 + 300e6: aa29 add r2, sp, #164 ; 0xa4 + 300e8: f7ff f8b4 bl 2f254 <__rtl_sprint_r_v1_00.part.9> + 300ec: 2800 cmp r0, #0 + 300ee: f47f af40 bne.w 2ff72 <__rtl_vfprintf_r_v1_00+0x912> + 300f2: 992a ldr r1, [sp, #168] ; 0xa8 + 300f4: 46c6 mov lr, r8 + 300f6: 9b2b ldr r3, [sp, #172] ; 0xac + 300f8: 1c48 adds r0, r1, #1 + 300fa: e7cb b.n 30094 <__rtl_vfprintf_r_v1_00+0xa34> + 300fc: 9010 str r0, [sp, #64] ; 0x40 + 300fe: 4646 mov r6, r8 + 30100: f7ff bbf8 b.w 2f8f4 <__rtl_vfprintf_r_v1_00+0x294> + 30104: 2b09 cmp r3, #9 + 30106: f200 8132 bhi.w 3036e <__rtl_vfprintf_r_v1_00+0xd0e> + 3010a: ae46 add r6, sp, #280 ; 0x118 + 3010c: 3330 adds r3, #48 ; 0x30 + 3010e: f806 3d41 strb.w r3, [r6, #-65]! + 30112: ebc6 0308 rsb r3, r6, r8 + 30116: 9310 str r3, [sp, #64] ; 0x40 + 30118: f7ff bbec b.w 2f8f4 <__rtl_vfprintf_r_v1_00+0x294> + 3011c: 2a00 cmp r2, #0 + 3011e: f040 8199 bne.w 30454 <__rtl_vfprintf_r_v1_00+0xdf4> + 30122: 922a str r2, [sp, #168] ; 0xa8 + 30124: 4644 mov r4, r8 + 30126: f89d 2087 ldrb.w r2, [sp, #135] ; 0x87 + 3012a: e43d b.n 2f9a8 <__rtl_vfprintf_r_v1_00+0x348> + 3012c: 980c ldr r0, [sp, #48] ; 0x30 + 3012e: 9909 ldr r1, [sp, #36] ; 0x24 + 30130: aa29 add r2, sp, #164 ; 0xa4 + 30132: f7ff f88f bl 2f254 <__rtl_sprint_r_v1_00.part.9> + 30136: 2800 cmp r0, #0 + 30138: f47f af1b bne.w 2ff72 <__rtl_vfprintf_r_v1_00+0x912> + 3013c: 4644 mov r4, r8 + 3013e: 992a ldr r1, [sp, #168] ; 0xa8 + 30140: 9b2b ldr r3, [sp, #172] ; 0xac + 30142: 3101 adds r1, #1 + 30144: 9d1c ldr r5, [sp, #112] ; 0x70 + 30146: 2907 cmp r1, #7 + 30148: 442b add r3, r5 + 3014a: 9d16 ldr r5, [sp, #88] ; 0x58 + 3014c: 932b str r3, [sp, #172] ; 0xac + 3014e: 6025 str r5, [r4, #0] + 30150: 9d1c ldr r5, [sp, #112] ; 0x70 + 30152: 912a str r1, [sp, #168] ; 0xa8 + 30154: 6065 str r5, [r4, #4] + 30156: f77f af54 ble.w 30002 <__rtl_vfprintf_r_v1_00+0x9a2> + 3015a: 2b00 cmp r3, #0 + 3015c: f040 8168 bne.w 30430 <__rtl_vfprintf_r_v1_00+0xdd0> + 30160: 932a str r3, [sp, #168] ; 0xa8 + 30162: 4644 mov r4, r8 + 30164: e74e b.n 30004 <__rtl_vfprintf_r_v1_00+0x9a4> + 30166: 980d ldr r0, [sp, #52] ; 0x34 + 30168: 1e45 subs r5, r0, #1 + 3016a: 2d00 cmp r5, #0 + 3016c: f340 80e1 ble.w 30332 <__rtl_vfprintf_r_v1_00+0xcd2> + 30170: 2d10 cmp r5, #16 + 30172: f340 8085 ble.w 30280 <__rtl_vfprintf_r_v1_00+0xc20> + 30176: 4a71 ldr r2, [pc, #452] ; (3033c <__rtl_vfprintf_r_v1_00+0xcdc>) + 30178: 9b2b ldr r3, [sp, #172] ; 0xac + 3017a: 992a ldr r1, [sp, #168] ; 0xa8 + 3017c: 920e str r2, [sp, #56] ; 0x38 + 3017e: 2610 movs r6, #16 + 30180: 9f0c ldr r7, [sp, #48] ; 0x30 + 30182: f8dd a024 ldr.w sl, [sp, #36] ; 0x24 + 30186: e005 b.n 30194 <__rtl_vfprintf_r_v1_00+0xb34> + 30188: 1c88 adds r0, r1, #2 + 3018a: 4611 mov r1, r2 + 3018c: 3408 adds r4, #8 + 3018e: 3d10 subs r5, #16 + 30190: 2d10 cmp r5, #16 + 30192: dd7a ble.n 3028a <__rtl_vfprintf_r_v1_00+0xc2a> + 30194: 1c4a adds r2, r1, #1 + 30196: 3310 adds r3, #16 + 30198: 2a07 cmp r2, #7 + 3019a: 932b str r3, [sp, #172] ; 0xac + 3019c: f8c4 9000 str.w r9, [r4] + 301a0: 6066 str r6, [r4, #4] + 301a2: 922a str r2, [sp, #168] ; 0xa8 + 301a4: ddf0 ble.n 30188 <__rtl_vfprintf_r_v1_00+0xb28> + 301a6: b91b cbnz r3, 301b0 <__rtl_vfprintf_r_v1_00+0xb50> + 301a8: 4619 mov r1, r3 + 301aa: 2001 movs r0, #1 + 301ac: 4644 mov r4, r8 + 301ae: e7ee b.n 3018e <__rtl_vfprintf_r_v1_00+0xb2e> + 301b0: 4638 mov r0, r7 + 301b2: 4651 mov r1, sl + 301b4: aa29 add r2, sp, #164 ; 0xa4 + 301b6: f7ff f84d bl 2f254 <__rtl_sprint_r_v1_00.part.9> + 301ba: 2800 cmp r0, #0 + 301bc: f47f aed9 bne.w 2ff72 <__rtl_vfprintf_r_v1_00+0x912> + 301c0: 992a ldr r1, [sp, #168] ; 0xa8 + 301c2: 4644 mov r4, r8 + 301c4: 9b2b ldr r3, [sp, #172] ; 0xac + 301c6: 1c48 adds r0, r1, #1 + 301c8: e7e1 b.n 3018e <__rtl_vfprintf_r_v1_00+0xb2e> + 301ca: 981a ldr r0, [sp, #104] ; 0x68 + 301cc: 991b ldr r1, [sp, #108] ; 0x6c + 301ce: 2200 movs r2, #0 + 301d0: 2300 movs r3, #0 + 301d2: 9d15 ldr r5, [sp, #84] ; 0x54 + 301d4: 47a8 blx r5 + 301d6: 2800 cmp r0, #0 + 301d8: f000 80df beq.w 3039a <__rtl_vfprintf_r_v1_00+0xd3a> + 301dc: 9a2a ldr r2, [sp, #168] ; 0xa8 + 301de: 9b2b ldr r3, [sp, #172] ; 0xac + 301e0: 3201 adds r2, #1 + 301e2: 9d17 ldr r5, [sp, #92] ; 0x5c + 301e4: 3301 adds r3, #1 + 301e6: 2101 movs r1, #1 + 301e8: 2a07 cmp r2, #7 + 301ea: 6025 str r5, [r4, #0] + 301ec: 6061 str r1, [r4, #4] + 301ee: 932b str r3, [sp, #172] ; 0xac + 301f0: 922a str r2, [sp, #168] ; 0xa8 + 301f2: bfd8 it le + 301f4: 3408 addle r4, #8 + 301f6: dd04 ble.n 30202 <__rtl_vfprintf_r_v1_00+0xba2> + 301f8: 2b00 cmp r3, #0 + 301fa: f040 83fc bne.w 309f6 <__rtl_vfprintf_r_v1_00+0x1396> + 301fe: 4644 mov r4, r8 + 30200: 932a str r3, [sp, #168] ; 0xa8 + 30202: 9a23 ldr r2, [sp, #140] ; 0x8c + 30204: 9d0d ldr r5, [sp, #52] ; 0x34 + 30206: 42aa cmp r2, r5 + 30208: f280 81dc bge.w 305c4 <__rtl_vfprintf_r_v1_00+0xf64> + 3020c: 9d1c ldr r5, [sp, #112] ; 0x70 + 3020e: 9a2a ldr r2, [sp, #168] ; 0xa8 + 30210: 442b add r3, r5 + 30212: 9d16 ldr r5, [sp, #88] ; 0x58 + 30214: 3201 adds r2, #1 + 30216: 6025 str r5, [r4, #0] + 30218: 9d1c ldr r5, [sp, #112] ; 0x70 + 3021a: 2a07 cmp r2, #7 + 3021c: 6065 str r5, [r4, #4] + 3021e: 932b str r3, [sp, #172] ; 0xac + 30220: 922a str r2, [sp, #168] ; 0xa8 + 30222: bfd8 it le + 30224: 3408 addle r4, #8 + 30226: dd04 ble.n 30232 <__rtl_vfprintf_r_v1_00+0xbd2> + 30228: 2b00 cmp r3, #0 + 3022a: f040 83f0 bne.w 30a0e <__rtl_vfprintf_r_v1_00+0x13ae> + 3022e: 4644 mov r4, r8 + 30230: 932a str r3, [sp, #168] ; 0xa8 + 30232: 980d ldr r0, [sp, #52] ; 0x34 + 30234: 1e45 subs r5, r0, #1 + 30236: 2d00 cmp r5, #0 + 30238: f77f ac2e ble.w 2fa98 <__rtl_vfprintf_r_v1_00+0x438> + 3023c: 2d10 cmp r5, #16 + 3023e: f340 8279 ble.w 30734 <__rtl_vfprintf_r_v1_00+0x10d4> + 30242: 4a3e ldr r2, [pc, #248] ; (3033c <__rtl_vfprintf_r_v1_00+0xcdc>) + 30244: 992a ldr r1, [sp, #168] ; 0xa8 + 30246: 920e str r2, [sp, #56] ; 0x38 + 30248: 2610 movs r6, #16 + 3024a: 9f0c ldr r7, [sp, #48] ; 0x30 + 3024c: f8dd a024 ldr.w sl, [sp, #36] ; 0x24 + 30250: e006 b.n 30260 <__rtl_vfprintf_r_v1_00+0xc00> + 30252: 1c88 adds r0, r1, #2 + 30254: 4611 mov r1, r2 + 30256: 3408 adds r4, #8 + 30258: 3d10 subs r5, #16 + 3025a: 2d10 cmp r5, #16 + 3025c: f340 826e ble.w 3073c <__rtl_vfprintf_r_v1_00+0x10dc> + 30260: 1c4a adds r2, r1, #1 + 30262: 3310 adds r3, #16 + 30264: 2a07 cmp r2, #7 + 30266: 932b str r3, [sp, #172] ; 0xac + 30268: f8c4 9000 str.w r9, [r4] + 3026c: 6066 str r6, [r4, #4] + 3026e: 922a str r2, [sp, #168] ; 0xa8 + 30270: ddef ble.n 30252 <__rtl_vfprintf_r_v1_00+0xbf2> + 30272: 2b00 cmp r3, #0 + 30274: f040 8237 bne.w 306e6 <__rtl_vfprintf_r_v1_00+0x1086> + 30278: 2001 movs r0, #1 + 3027a: 4619 mov r1, r3 + 3027c: 4644 mov r4, r8 + 3027e: e7eb b.n 30258 <__rtl_vfprintf_r_v1_00+0xbf8> + 30280: 982a ldr r0, [sp, #168] ; 0xa8 + 30282: 492e ldr r1, [pc, #184] ; (3033c <__rtl_vfprintf_r_v1_00+0xcdc>) + 30284: 9b2b ldr r3, [sp, #172] ; 0xac + 30286: 3001 adds r0, #1 + 30288: 910e str r1, [sp, #56] ; 0x38 + 3028a: 990e ldr r1, [sp, #56] ; 0x38 + 3028c: 2807 cmp r0, #7 + 3028e: 442b add r3, r5 + 30290: e884 0022 stmia.w r4, {r1, r5} + 30294: 902a str r0, [sp, #168] ; 0xa8 + 30296: 932b str r3, [sp, #172] ; 0xac + 30298: bfdc itt le + 3029a: 3408 addle r4, #8 + 3029c: 3001 addle r0, #1 + 3029e: f77f aecb ble.w 30038 <__rtl_vfprintf_r_v1_00+0x9d8> + 302a2: 2b00 cmp r3, #0 + 302a4: f040 8281 bne.w 307aa <__rtl_vfprintf_r_v1_00+0x114a> + 302a8: 9d1d ldr r5, [sp, #116] ; 0x74 + 302aa: 2301 movs r3, #1 + 302ac: aa25 add r2, sp, #148 ; 0x94 + 302ae: 932a str r3, [sp, #168] ; 0xa8 + 302b0: 9537 str r5, [sp, #220] ; 0xdc + 302b2: 952b str r5, [sp, #172] ; 0xac + 302b4: 9236 str r2, [sp, #216] ; 0xd8 + 302b6: 462b mov r3, r5 + 302b8: 4644 mov r4, r8 + 302ba: f7ff bbec b.w 2fa96 <__rtl_vfprintf_r_v1_00+0x436> + 302be: 980c ldr r0, [sp, #48] ; 0x30 + 302c0: 9909 ldr r1, [sp, #36] ; 0x24 + 302c2: aa29 add r2, sp, #164 ; 0xa4 + 302c4: 9307 str r3, [sp, #28] + 302c6: f8cd c018 str.w ip, [sp, #24] + 302ca: f7fe ffc3 bl 2f254 <__rtl_sprint_r_v1_00.part.9> + 302ce: 9b07 ldr r3, [sp, #28] + 302d0: f8dd c018 ldr.w ip, [sp, #24] + 302d4: 2800 cmp r0, #0 + 302d6: f47f ae4c bne.w 2ff72 <__rtl_vfprintf_r_v1_00+0x912> + 302da: 4644 mov r4, r8 + 302dc: f7ff bb79 b.w 2f9d2 <__rtl_vfprintf_r_v1_00+0x372> + 302e0: 980c ldr r0, [sp, #48] ; 0x30 + 302e2: 9909 ldr r1, [sp, #36] ; 0x24 + 302e4: aa29 add r2, sp, #164 ; 0xa4 + 302e6: f8cd c018 str.w ip, [sp, #24] + 302ea: f7fe ffb3 bl 2f254 <__rtl_sprint_r_v1_00.part.9> + 302ee: f8dd c018 ldr.w ip, [sp, #24] + 302f2: 2800 cmp r0, #0 + 302f4: f47f ae3d bne.w 2ff72 <__rtl_vfprintf_r_v1_00+0x912> + 302f8: 4644 mov r4, r8 + 302fa: f7ff bb7e b.w 2f9fa <__rtl_vfprintf_r_v1_00+0x39a> + 302fe: 9d08 ldr r5, [sp, #32] + 30300: 07e9 lsls r1, r5, #31 + 30302: f53f ae65 bmi.w 2ffd0 <__rtl_vfprintf_r_v1_00+0x970> + 30306: 982a ldr r0, [sp, #168] ; 0xa8 + 30308: 3301 adds r3, #1 + 3030a: 1c42 adds r2, r0, #1 + 3030c: 2101 movs r1, #1 + 3030e: 2a07 cmp r2, #7 + 30310: 6026 str r6, [r4, #0] + 30312: 932b str r3, [sp, #172] ; 0xac + 30314: 922a str r2, [sp, #168] ; 0xa8 + 30316: 6061 str r1, [r4, #4] + 30318: f77f ae8c ble.w 30034 <__rtl_vfprintf_r_v1_00+0x9d4> + 3031c: 2b00 cmp r3, #0 + 3031e: d0c3 beq.n 302a8 <__rtl_vfprintf_r_v1_00+0xc48> + 30320: 980c ldr r0, [sp, #48] ; 0x30 + 30322: 9909 ldr r1, [sp, #36] ; 0x24 + 30324: aa29 add r2, sp, #164 ; 0xa4 + 30326: f7fe ff95 bl 2f254 <__rtl_sprint_r_v1_00.part.9> + 3032a: 2800 cmp r0, #0 + 3032c: f47f ae21 bne.w 2ff72 <__rtl_vfprintf_r_v1_00+0x912> + 30330: 4644 mov r4, r8 + 30332: 982a ldr r0, [sp, #168] ; 0xa8 + 30334: 9b2b ldr r3, [sp, #172] ; 0xac + 30336: 3001 adds r0, #1 + 30338: e67e b.n 30038 <__rtl_vfprintf_r_v1_00+0x9d8> + 3033a: bf00 nop + 3033c: 0003ec14 .word 0x0003ec14 + 30340: 980c ldr r0, [sp, #48] ; 0x30 + 30342: 9909 ldr r1, [sp, #36] ; 0x24 + 30344: aa29 add r2, sp, #164 ; 0xa4 + 30346: f7fe ff85 bl 2f254 <__rtl_sprint_r_v1_00.part.9> + 3034a: 2800 cmp r0, #0 + 3034c: f47f ae11 bne.w 2ff72 <__rtl_vfprintf_r_v1_00+0x912> + 30350: 4644 mov r4, r8 + 30352: f7ff bb90 b.w 2fa76 <__rtl_vfprintf_r_v1_00+0x416> + 30356: 980c ldr r0, [sp, #48] ; 0x30 + 30358: 9909 ldr r1, [sp, #36] ; 0x24 + 3035a: aa29 add r2, sp, #164 ; 0xa4 + 3035c: f7fe ff7a bl 2f254 <__rtl_sprint_r_v1_00.part.9> + 30360: 2800 cmp r0, #0 + 30362: f47f ae06 bne.w 2ff72 <__rtl_vfprintf_r_v1_00+0x912> + 30366: 9b2b ldr r3, [sp, #172] ; 0xac + 30368: 4644 mov r4, r8 + 3036a: f7ff bb95 b.w 2fa98 <__rtl_vfprintf_r_v1_00+0x438> + 3036e: f64c 4ecd movw lr, #52429 ; 0xcccd + 30372: f6cc 4ecc movt lr, #52428 ; 0xcccc + 30376: f10d 00d7 add.w r0, sp, #215 ; 0xd7 + 3037a: fbae 5103 umull r5, r1, lr, r3 + 3037e: 08c9 lsrs r1, r1, #3 + 30380: eb01 0581 add.w r5, r1, r1, lsl #2 + 30384: 4606 mov r6, r0 + 30386: eba3 0045 sub.w r0, r3, r5, lsl #1 + 3038a: 460b mov r3, r1 + 3038c: f100 0130 add.w r1, r0, #48 ; 0x30 + 30390: 7031 strb r1, [r6, #0] + 30392: 1e70 subs r0, r6, #1 + 30394: 2b00 cmp r3, #0 + 30396: d1f0 bne.n 3037a <__rtl_vfprintf_r_v1_00+0xd1a> + 30398: e6bb b.n 30112 <__rtl_vfprintf_r_v1_00+0xab2> + 3039a: 9d23 ldr r5, [sp, #140] ; 0x8c + 3039c: 2d00 cmp r5, #0 + 3039e: f340 825e ble.w 3085e <__rtl_vfprintf_r_v1_00+0x11fe> + 303a2: 9d0d ldr r5, [sp, #52] ; 0x34 + 303a4: 9819 ldr r0, [sp, #100] ; 0x64 + 303a6: f8dd a034 ldr.w sl, [sp, #52] ; 0x34 + 303aa: 4285 cmp r5, r0 + 303ac: bfa8 it ge + 303ae: 4605 movge r5, r0 + 303b0: 2d00 cmp r5, #0 + 303b2: 44b2 add sl, r6 + 303b4: 9b2b ldr r3, [sp, #172] ; 0xac + 303b6: dd0f ble.n 303d8 <__rtl_vfprintf_r_v1_00+0xd78> + 303b8: 9a2a ldr r2, [sp, #168] ; 0xa8 + 303ba: 442b add r3, r5 + 303bc: 3201 adds r2, #1 + 303be: 2a07 cmp r2, #7 + 303c0: 6026 str r6, [r4, #0] + 303c2: 6065 str r5, [r4, #4] + 303c4: 932b str r3, [sp, #172] ; 0xac + 303c6: 922a str r2, [sp, #168] ; 0xa8 + 303c8: bfd8 it le + 303ca: 3408 addle r4, #8 + 303cc: dd04 ble.n 303d8 <__rtl_vfprintf_r_v1_00+0xd78> + 303ce: 2b00 cmp r3, #0 + 303d0: f040 8385 bne.w 30ade <__rtl_vfprintf_r_v1_00+0x147e> + 303d4: 4644 mov r4, r8 + 303d6: 932a str r3, [sp, #168] ; 0xa8 + 303d8: 9919 ldr r1, [sp, #100] ; 0x64 + 303da: 2d00 cmp r5, #0 + 303dc: bfa8 it ge + 303de: 1b49 subge r1, r1, r5 + 303e0: 2900 cmp r1, #0 + 303e2: 460d mov r5, r1 + 303e4: f340 8125 ble.w 30632 <__rtl_vfprintf_r_v1_00+0xfd2> + 303e8: 2910 cmp r1, #16 + 303ea: f340 83f6 ble.w 30bda <__rtl_vfprintf_r_v1_00+0x157a> + 303ee: 4887 ldr r0, [pc, #540] ; (3060c <__rtl_vfprintf_r_v1_00+0xfac>) + 303f0: 46a6 mov lr, r4 + 303f2: 992a ldr r1, [sp, #168] ; 0xa8 + 303f4: 462c mov r4, r5 + 303f6: 900e str r0, [sp, #56] ; 0x38 + 303f8: 2710 movs r7, #16 + 303fa: 9d09 ldr r5, [sp, #36] ; 0x24 + 303fc: e007 b.n 3040e <__rtl_vfprintf_r_v1_00+0xdae> + 303fe: 1c88 adds r0, r1, #2 + 30400: 4611 mov r1, r2 + 30402: f10e 0e08 add.w lr, lr, #8 + 30406: 3c10 subs r4, #16 + 30408: 2c10 cmp r4, #16 + 3040a: f340 8101 ble.w 30610 <__rtl_vfprintf_r_v1_00+0xfb0> + 3040e: 1c4a adds r2, r1, #1 + 30410: 3310 adds r3, #16 + 30412: 2a07 cmp r2, #7 + 30414: 932b str r3, [sp, #172] ; 0xac + 30416: f8ce 9000 str.w r9, [lr] + 3041a: f8ce 7004 str.w r7, [lr, #4] + 3041e: 922a str r2, [sp, #168] ; 0xa8 + 30420: dded ble.n 303fe <__rtl_vfprintf_r_v1_00+0xd9e> + 30422: 2b00 cmp r3, #0 + 30424: f040 816c bne.w 30700 <__rtl_vfprintf_r_v1_00+0x10a0> + 30428: 4619 mov r1, r3 + 3042a: 2001 movs r0, #1 + 3042c: 46c6 mov lr, r8 + 3042e: e7ea b.n 30406 <__rtl_vfprintf_r_v1_00+0xda6> + 30430: 980c ldr r0, [sp, #48] ; 0x30 + 30432: 9909 ldr r1, [sp, #36] ; 0x24 + 30434: aa29 add r2, sp, #164 ; 0xa4 + 30436: f7fe ff0d bl 2f254 <__rtl_sprint_r_v1_00.part.9> + 3043a: 2800 cmp r0, #0 + 3043c: f47f ad99 bne.w 2ff72 <__rtl_vfprintf_r_v1_00+0x912> + 30440: 4644 mov r4, r8 + 30442: e5df b.n 30004 <__rtl_vfprintf_r_v1_00+0x9a4> + 30444: 681d ldr r5, [r3, #0] + 30446: 3308 adds r3, #8 + 30448: 951a str r5, [sp, #104] ; 0x68 + 3044a: f853 5c04 ldr.w r5, [r3, #-4] + 3044e: 930f str r3, [sp, #60] ; 0x3c + 30450: 951b str r5, [sp, #108] ; 0x6c + 30452: e4db b.n 2fe0c <__rtl_vfprintf_r_v1_00+0x7ac> + 30454: 980c ldr r0, [sp, #48] ; 0x30 + 30456: 9909 ldr r1, [sp, #36] ; 0x24 + 30458: aa29 add r2, sp, #164 ; 0xa4 + 3045a: 9307 str r3, [sp, #28] + 3045c: f8cd c018 str.w ip, [sp, #24] + 30460: f7fe fef8 bl 2f254 <__rtl_sprint_r_v1_00.part.9> + 30464: 9b07 ldr r3, [sp, #28] + 30466: f8dd c018 ldr.w ip, [sp, #24] + 3046a: 2800 cmp r0, #0 + 3046c: f47f ad81 bne.w 2ff72 <__rtl_vfprintf_r_v1_00+0x912> + 30470: 4644 mov r4, r8 + 30472: f89d 2087 ldrb.w r2, [sp, #135] ; 0x87 + 30476: f7ff ba97 b.w 2f9a8 <__rtl_vfprintf_r_v1_00+0x348> + 3047a: f027 0520 bic.w r5, r7, #32 + 3047e: f1bc 3fff cmp.w ip, #4294967295 + 30482: 950a str r5, [sp, #40] ; 0x28 + 30484: bf08 it eq + 30486: f04f 0c06 moveq.w ip, #6 + 3048a: d006 beq.n 3049a <__rtl_vfprintf_r_v1_00+0xe3a> + 3048c: 2d47 cmp r5, #71 ; 0x47 + 3048e: d104 bne.n 3049a <__rtl_vfprintf_r_v1_00+0xe3a> + 30490: f1bc 0f00 cmp.w ip, #0 + 30494: bf08 it eq + 30496: f04f 0c01 moveq.w ip, #1 + 3049a: 9b1b ldr r3, [sp, #108] ; 0x6c + 3049c: 9d08 ldr r5, [sp, #32] + 3049e: 2b00 cmp r3, #0 + 304a0: f445 7580 orr.w r5, r5, #256 ; 0x100 + 304a4: 9514 str r5, [sp, #80] ; 0x50 + 304a6: bfb7 itett lt + 304a8: 461d movlt r5, r3 + 304aa: 9d1b ldrge r5, [sp, #108] ; 0x6c + 304ac: f105 4500 addlt.w r5, r5, #2147483648 ; 0x80000000 + 304b0: 950d strlt r5, [sp, #52] ; 0x34 + 304b2: bfaa itet ge + 304b4: 950d strge r5, [sp, #52] ; 0x34 + 304b6: 252d movlt r5, #45 ; 0x2d + 304b8: 2500 movge r5, #0 + 304ba: 950e str r5, [sp, #56] ; 0x38 + 304bc: 9d0a ldr r5, [sp, #40] ; 0x28 + 304be: f1a5 0a46 sub.w sl, r5, #70 ; 0x46 + 304c2: faba fa8a clz sl, sl + 304c6: ea4f 1a5a mov.w sl, sl, lsr #5 + 304ca: f1ba 0f00 cmp.w sl, #0 + 304ce: d07e beq.n 305ce <__rtl_vfprintf_r_v1_00+0xf6e> + 304d0: 2103 movs r1, #3 + 304d2: a823 add r0, sp, #140 ; 0x8c + 304d4: 9100 str r1, [sp, #0] + 304d6: 9002 str r0, [sp, #8] + 304d8: a924 add r1, sp, #144 ; 0x90 + 304da: a827 add r0, sp, #156 ; 0x9c + 304dc: f8cd c004 str.w ip, [sp, #4] + 304e0: 9004 str r0, [sp, #16] + 304e2: 9a1a ldr r2, [sp, #104] ; 0x68 + 304e4: 9b0d ldr r3, [sp, #52] ; 0x34 + 304e6: 9103 str r1, [sp, #12] + 304e8: 980c ldr r0, [sp, #48] ; 0x30 + 304ea: f8cd c018 str.w ip, [sp, #24] + 304ee: f7fc f945 bl 2c77c <__rtl_dtoa_r_v1_00> + 304f2: 9d0a ldr r5, [sp, #40] ; 0x28 + 304f4: 4606 mov r6, r0 + 304f6: 2d47 cmp r5, #71 ; 0x47 + 304f8: f8dd c018 ldr.w ip, [sp, #24] + 304fc: d103 bne.n 30506 <__rtl_vfprintf_r_v1_00+0xea6> + 304fe: 9d08 ldr r5, [sp, #32] + 30500: 07e9 lsls r1, r5, #31 + 30502: f140 8196 bpl.w 30832 <__rtl_vfprintf_r_v1_00+0x11d2> + 30506: eb06 050c add.w r5, r6, ip + 3050a: 9510 str r5, [sp, #64] ; 0x40 + 3050c: f1ba 0f00 cmp.w sl, #0 + 30510: f000 82e0 beq.w 30ad4 <__rtl_vfprintf_r_v1_00+0x1474> + 30514: 7833 ldrb r3, [r6, #0] + 30516: 2b30 cmp r3, #48 ; 0x30 + 30518: f000 834a beq.w 30bb0 <__rtl_vfprintf_r_v1_00+0x1550> + 3051c: f64b 6a4d movw sl, #48717 ; 0xbe4d + 30520: f2c0 0a02 movt sl, #2 + 30524: 9b23 ldr r3, [sp, #140] ; 0x8c + 30526: 9d10 ldr r5, [sp, #64] ; 0x40 + 30528: 441d add r5, r3 + 3052a: 9510 str r5, [sp, #64] ; 0x40 + 3052c: f8cd c018 str.w ip, [sp, #24] + 30530: 981a ldr r0, [sp, #104] ; 0x68 + 30532: 990d ldr r1, [sp, #52] ; 0x34 + 30534: 2200 movs r2, #0 + 30536: 2300 movs r3, #0 + 30538: 47d0 blx sl + 3053a: f8dd c018 ldr.w ip, [sp, #24] + 3053e: 2800 cmp r0, #0 + 30540: f040 81ff bne.w 30942 <__rtl_vfprintf_r_v1_00+0x12e2> + 30544: 9b27 ldr r3, [sp, #156] ; 0x9c + 30546: 9d10 ldr r5, [sp, #64] ; 0x40 + 30548: 429d cmp r5, r3 + 3054a: d906 bls.n 3055a <__rtl_vfprintf_r_v1_00+0xefa> + 3054c: 2130 movs r1, #48 ; 0x30 + 3054e: 1c5a adds r2, r3, #1 + 30550: 9227 str r2, [sp, #156] ; 0x9c + 30552: 7019 strb r1, [r3, #0] + 30554: 9b27 ldr r3, [sp, #156] ; 0x9c + 30556: 429d cmp r5, r3 + 30558: d8f9 bhi.n 3054e <__rtl_vfprintf_r_v1_00+0xeee> + 3055a: 9d0a ldr r5, [sp, #40] ; 0x28 + 3055c: 1b9b subs r3, r3, r6 + 3055e: 2d47 cmp r5, #71 ; 0x47 + 30560: 930d str r3, [sp, #52] ; 0x34 + 30562: f000 8169 beq.w 30838 <__rtl_vfprintf_r_v1_00+0x11d8> + 30566: 2f65 cmp r7, #101 ; 0x65 + 30568: f340 834f ble.w 30c0a <__rtl_vfprintf_r_v1_00+0x15aa> + 3056c: 9d23 ldr r5, [sp, #140] ; 0x8c + 3056e: 2f66 cmp r7, #102 ; 0x66 + 30570: 9519 str r5, [sp, #100] ; 0x64 + 30572: f000 8270 beq.w 30a56 <__rtl_vfprintf_r_v1_00+0x13f6> + 30576: 9d19 ldr r5, [sp, #100] ; 0x64 + 30578: 980d ldr r0, [sp, #52] ; 0x34 + 3057a: 4285 cmp r5, r0 + 3057c: f2c0 822d blt.w 309da <__rtl_vfprintf_r_v1_00+0x137a> + 30580: 9d08 ldr r5, [sp, #32] + 30582: 2767 movs r7, #103 ; 0x67 + 30584: f015 0f01 tst.w r5, #1 + 30588: 9d19 ldr r5, [sp, #100] ; 0x64 + 3058a: bf13 iteet ne + 3058c: 3501 addne r5, #1 + 3058e: ea25 73e5 biceq.w r3, r5, r5, asr #31 + 30592: 9510 streq r5, [sp, #64] ; 0x40 + 30594: 9510 strne r5, [sp, #64] ; 0x40 + 30596: bf18 it ne + 30598: ea25 73e5 bicne.w r3, r5, r5, asr #31 + 3059c: 9d0e ldr r5, [sp, #56] ; 0x38 + 3059e: 2d00 cmp r5, #0 + 305a0: f040 8153 bne.w 3084a <__rtl_vfprintf_r_v1_00+0x11ea> + 305a4: 9d14 ldr r5, [sp, #80] ; 0x50 + 305a6: 930a str r3, [sp, #40] ; 0x28 + 305a8: 9508 str r5, [sp, #32] + 305aa: f8dd c038 ldr.w ip, [sp, #56] ; 0x38 + 305ae: f89d 2087 ldrb.w r2, [sp, #135] ; 0x87 + 305b2: f7ff b9a6 b.w 2f902 <__rtl_vfprintf_r_v1_00+0x2a2> + 305b6: 982a ldr r0, [sp, #168] ; 0xa8 + 305b8: 4914 ldr r1, [pc, #80] ; (3060c <__rtl_vfprintf_r_v1_00+0xfac>) + 305ba: 9b2b ldr r3, [sp, #172] ; 0xac + 305bc: 3001 adds r0, #1 + 305be: 910e str r1, [sp, #56] ; 0x38 + 305c0: f7ff ba4a b.w 2fa58 <__rtl_vfprintf_r_v1_00+0x3f8> + 305c4: 9d08 ldr r5, [sp, #32] + 305c6: 07ea lsls r2, r5, #31 + 305c8: f57f aa66 bpl.w 2fa98 <__rtl_vfprintf_r_v1_00+0x438> + 305cc: e61e b.n 3020c <__rtl_vfprintf_r_v1_00+0xbac> + 305ce: 2d45 cmp r5, #69 ; 0x45 + 305d0: f040 8201 bne.w 309d6 <__rtl_vfprintf_r_v1_00+0x1376> + 305d4: f10c 0501 add.w r5, ip, #1 + 305d8: 2002 movs r0, #2 + 305da: a923 add r1, sp, #140 ; 0x8c + 305dc: e88d 0021 stmia.w sp, {r0, r5} + 305e0: 9102 str r1, [sp, #8] + 305e2: a824 add r0, sp, #144 ; 0x90 + 305e4: a927 add r1, sp, #156 ; 0x9c + 305e6: 9003 str r0, [sp, #12] + 305e8: 9a1a ldr r2, [sp, #104] ; 0x68 + 305ea: 9b0d ldr r3, [sp, #52] ; 0x34 + 305ec: 9104 str r1, [sp, #16] + 305ee: 980c ldr r0, [sp, #48] ; 0x30 + 305f0: f8cd c018 str.w ip, [sp, #24] + 305f4: f7fc f8c2 bl 2c77c <__rtl_dtoa_r_v1_00> + 305f8: f64b 6a4d movw sl, #48717 ; 0xbe4d + 305fc: 4405 add r5, r0 + 305fe: 4606 mov r6, r0 + 30600: 9510 str r5, [sp, #64] ; 0x40 + 30602: f2c0 0a02 movt sl, #2 + 30606: f8dd c018 ldr.w ip, [sp, #24] + 3060a: e78f b.n 3052c <__rtl_vfprintf_r_v1_00+0xecc> + 3060c: 0003ec14 .word 0x0003ec14 + 30610: 4625 mov r5, r4 + 30612: 4674 mov r4, lr + 30614: 990e ldr r1, [sp, #56] ; 0x38 + 30616: 442b add r3, r5 + 30618: 2807 cmp r0, #7 + 3061a: e884 0022 stmia.w r4, {r1, r5} + 3061e: 932b str r3, [sp, #172] ; 0xac + 30620: 902a str r0, [sp, #168] ; 0xa8 + 30622: bfd8 it le + 30624: 3408 addle r4, #8 + 30626: dd04 ble.n 30632 <__rtl_vfprintf_r_v1_00+0xfd2> + 30628: 2b00 cmp r3, #0 + 3062a: f040 8263 bne.w 30af4 <__rtl_vfprintf_r_v1_00+0x1494> + 3062e: 4644 mov r4, r8 + 30630: 932a str r3, [sp, #168] ; 0xa8 + 30632: 9d19 ldr r5, [sp, #100] ; 0x64 + 30634: 9a23 ldr r2, [sp, #140] ; 0x8c + 30636: 442e add r6, r5 + 30638: 9d0d ldr r5, [sp, #52] ; 0x34 + 3063a: 42aa cmp r2, r5 + 3063c: db02 blt.n 30644 <__rtl_vfprintf_r_v1_00+0xfe4> + 3063e: 9d08 ldr r5, [sp, #32] + 30640: 07e8 lsls r0, r5, #31 + 30642: d512 bpl.n 3066a <__rtl_vfprintf_r_v1_00+0x100a> + 30644: 9d1c ldr r5, [sp, #112] ; 0x70 + 30646: 992a ldr r1, [sp, #168] ; 0xa8 + 30648: 442b add r3, r5 + 3064a: 9d16 ldr r5, [sp, #88] ; 0x58 + 3064c: 3101 adds r1, #1 + 3064e: 6025 str r5, [r4, #0] + 30650: 9d1c ldr r5, [sp, #112] ; 0x70 + 30652: 2907 cmp r1, #7 + 30654: 6065 str r5, [r4, #4] + 30656: 932b str r3, [sp, #172] ; 0xac + 30658: 912a str r1, [sp, #168] ; 0xa8 + 3065a: bfd8 it le + 3065c: 3408 addle r4, #8 + 3065e: dd04 ble.n 3066a <__rtl_vfprintf_r_v1_00+0x100a> + 30660: 2b00 cmp r3, #0 + 30662: f040 8264 bne.w 30b2e <__rtl_vfprintf_r_v1_00+0x14ce> + 30666: 4644 mov r4, r8 + 30668: 932a str r3, [sp, #168] ; 0xa8 + 3066a: 980d ldr r0, [sp, #52] ; 0x34 + 3066c: ebc6 050a rsb r5, r6, sl + 30670: 1a82 subs r2, r0, r2 + 30672: 4295 cmp r5, r2 + 30674: bfa8 it ge + 30676: 4615 movge r5, r2 + 30678: 2d00 cmp r5, #0 + 3067a: dd0f ble.n 3069c <__rtl_vfprintf_r_v1_00+0x103c> + 3067c: 992a ldr r1, [sp, #168] ; 0xa8 + 3067e: 442b add r3, r5 + 30680: 3101 adds r1, #1 + 30682: 2907 cmp r1, #7 + 30684: 6026 str r6, [r4, #0] + 30686: 6065 str r5, [r4, #4] + 30688: 932b str r3, [sp, #172] ; 0xac + 3068a: 912a str r1, [sp, #168] ; 0xa8 + 3068c: bfd8 it le + 3068e: 3408 addle r4, #8 + 30690: dd04 ble.n 3069c <__rtl_vfprintf_r_v1_00+0x103c> + 30692: 2b00 cmp r3, #0 + 30694: f040 8257 bne.w 30b46 <__rtl_vfprintf_r_v1_00+0x14e6> + 30698: 4644 mov r4, r8 + 3069a: 932a str r3, [sp, #168] ; 0xa8 + 3069c: 2d00 cmp r5, #0 + 3069e: bfb4 ite lt + 306a0: 4615 movlt r5, r2 + 306a2: 1b55 subge r5, r2, r5 + 306a4: 2d00 cmp r5, #0 + 306a6: f77f a9f7 ble.w 2fa98 <__rtl_vfprintf_r_v1_00+0x438> + 306aa: 2d10 cmp r5, #16 + 306ac: dd42 ble.n 30734 <__rtl_vfprintf_r_v1_00+0x10d4> + 306ae: 4aa6 ldr r2, [pc, #664] ; (30948 <__rtl_vfprintf_r_v1_00+0x12e8>) + 306b0: 992a ldr r1, [sp, #168] ; 0xa8 + 306b2: 920e str r2, [sp, #56] ; 0x38 + 306b4: 2610 movs r6, #16 + 306b6: 9f0c ldr r7, [sp, #48] ; 0x30 + 306b8: f8dd a024 ldr.w sl, [sp, #36] ; 0x24 + 306bc: e005 b.n 306ca <__rtl_vfprintf_r_v1_00+0x106a> + 306be: 1c88 adds r0, r1, #2 + 306c0: 4611 mov r1, r2 + 306c2: 3408 adds r4, #8 + 306c4: 3d10 subs r5, #16 + 306c6: 2d10 cmp r5, #16 + 306c8: dd38 ble.n 3073c <__rtl_vfprintf_r_v1_00+0x10dc> + 306ca: 1c4a adds r2, r1, #1 + 306cc: 3310 adds r3, #16 + 306ce: 2a07 cmp r2, #7 + 306d0: 932b str r3, [sp, #172] ; 0xac + 306d2: f8c4 9000 str.w r9, [r4] + 306d6: 6066 str r6, [r4, #4] + 306d8: 922a str r2, [sp, #168] ; 0xa8 + 306da: ddf0 ble.n 306be <__rtl_vfprintf_r_v1_00+0x105e> + 306dc: b9eb cbnz r3, 3071a <__rtl_vfprintf_r_v1_00+0x10ba> + 306de: 4619 mov r1, r3 + 306e0: 2001 movs r0, #1 + 306e2: 4644 mov r4, r8 + 306e4: e7ee b.n 306c4 <__rtl_vfprintf_r_v1_00+0x1064> + 306e6: 4638 mov r0, r7 + 306e8: 4651 mov r1, sl + 306ea: aa29 add r2, sp, #164 ; 0xa4 + 306ec: f7fe fdb2 bl 2f254 <__rtl_sprint_r_v1_00.part.9> + 306f0: 2800 cmp r0, #0 + 306f2: f47f ac3e bne.w 2ff72 <__rtl_vfprintf_r_v1_00+0x912> + 306f6: 992a ldr r1, [sp, #168] ; 0xa8 + 306f8: 4644 mov r4, r8 + 306fa: 9b2b ldr r3, [sp, #172] ; 0xac + 306fc: 1c48 adds r0, r1, #1 + 306fe: e5ab b.n 30258 <__rtl_vfprintf_r_v1_00+0xbf8> + 30700: 980c ldr r0, [sp, #48] ; 0x30 + 30702: 4629 mov r1, r5 + 30704: aa29 add r2, sp, #164 ; 0xa4 + 30706: f7fe fda5 bl 2f254 <__rtl_sprint_r_v1_00.part.9> + 3070a: 2800 cmp r0, #0 + 3070c: f47f ac31 bne.w 2ff72 <__rtl_vfprintf_r_v1_00+0x912> + 30710: 992a ldr r1, [sp, #168] ; 0xa8 + 30712: 46c6 mov lr, r8 + 30714: 9b2b ldr r3, [sp, #172] ; 0xac + 30716: 1c48 adds r0, r1, #1 + 30718: e675 b.n 30406 <__rtl_vfprintf_r_v1_00+0xda6> + 3071a: 4638 mov r0, r7 + 3071c: 4651 mov r1, sl + 3071e: aa29 add r2, sp, #164 ; 0xa4 + 30720: f7fe fd98 bl 2f254 <__rtl_sprint_r_v1_00.part.9> + 30724: 2800 cmp r0, #0 + 30726: f47f ac24 bne.w 2ff72 <__rtl_vfprintf_r_v1_00+0x912> + 3072a: 992a ldr r1, [sp, #168] ; 0xa8 + 3072c: 4644 mov r4, r8 + 3072e: 9b2b ldr r3, [sp, #172] ; 0xac + 30730: 1c48 adds r0, r1, #1 + 30732: e7c7 b.n 306c4 <__rtl_vfprintf_r_v1_00+0x1064> + 30734: 982a ldr r0, [sp, #168] ; 0xa8 + 30736: 4984 ldr r1, [pc, #528] ; (30948 <__rtl_vfprintf_r_v1_00+0x12e8>) + 30738: 3001 adds r0, #1 + 3073a: 910e str r1, [sp, #56] ; 0x38 + 3073c: 990e ldr r1, [sp, #56] ; 0x38 + 3073e: 442b add r3, r5 + 30740: 2807 cmp r0, #7 + 30742: 932b str r3, [sp, #172] ; 0xac + 30744: e884 0022 stmia.w r4, {r1, r5} + 30748: 902a str r0, [sp, #168] ; 0xa8 + 3074a: f73f abee bgt.w 2ff2a <__rtl_vfprintf_r_v1_00+0x8ca> + 3074e: f7ff b9a2 b.w 2fa96 <__rtl_vfprintf_r_v1_00+0x436> + 30752: f64b 65bd movw r5, #48829 ; 0xbebd + 30756: 2300 movs r3, #0 + 30758: 2200 movs r2, #0 + 3075a: f2c0 0502 movt r5, #2 + 3075e: 991b ldr r1, [sp, #108] ; 0x6c + 30760: 47a8 blx r5 + 30762: 2801 cmp r0, #1 + 30764: bf02 ittt eq + 30766: 232d moveq r3, #45 ; 0x2d + 30768: 461a moveq r2, r3 + 3076a: f88d 3087 strbeq.w r3, [sp, #135] ; 0x87 + 3076e: f243 76e4 movw r6, #14308 ; 0x37e4 + 30772: f243 73e0 movw r3, #14304 ; 0x37e0 + 30776: f2c0 0604 movt r6, #4 + 3077a: f2c0 0304 movt r3, #4 + 3077e: f04f 0503 mov.w r5, #3 + 30782: 950a str r5, [sp, #40] ; 0x28 + 30784: 9d08 ldr r5, [sp, #32] + 30786: f04f 0c00 mov.w ip, #0 + 3078a: f025 0580 bic.w r5, r5, #128 ; 0x80 + 3078e: 9508 str r5, [sp, #32] + 30790: f04f 0503 mov.w r5, #3 + 30794: bf18 it ne + 30796: f89d 2087 ldrbne.w r2, [sp, #135] ; 0x87 + 3079a: 9510 str r5, [sp, #64] ; 0x40 + 3079c: 2f47 cmp r7, #71 ; 0x47 + 3079e: bfd8 it le + 307a0: 461e movle r6, r3 + 307a2: f8cd c064 str.w ip, [sp, #100] ; 0x64 + 307a6: f7ff b8ac b.w 2f902 <__rtl_vfprintf_r_v1_00+0x2a2> + 307aa: 980c ldr r0, [sp, #48] ; 0x30 + 307ac: 9909 ldr r1, [sp, #36] ; 0x24 + 307ae: aa29 add r2, sp, #164 ; 0xa4 + 307b0: f7fe fd50 bl 2f254 <__rtl_sprint_r_v1_00.part.9> + 307b4: 2800 cmp r0, #0 + 307b6: f47f abdc bne.w 2ff72 <__rtl_vfprintf_r_v1_00+0x912> + 307ba: 982a ldr r0, [sp, #168] ; 0xa8 + 307bc: 9b2b ldr r3, [sp, #172] ; 0xac + 307be: 3001 adds r0, #1 + 307c0: 4644 mov r4, r8 + 307c2: e439 b.n 30038 <__rtl_vfprintf_r_v1_00+0x9d8> + 307c4: 980c ldr r0, [sp, #48] ; 0x30 + 307c6: 9909 ldr r1, [sp, #36] ; 0x24 + 307c8: aa29 add r2, sp, #164 ; 0xa4 + 307ca: f7fe fd43 bl 2f254 <__rtl_sprint_r_v1_00.part.9> + 307ce: 2800 cmp r0, #0 + 307d0: f47f abcf bne.w 2ff72 <__rtl_vfprintf_r_v1_00+0x912> + 307d4: 9b2b ldr r3, [sp, #172] ; 0xac + 307d6: f7ff bbb1 b.w 2ff3c <__rtl_vfprintf_r_v1_00+0x8dc> + 307da: 980c ldr r0, [sp, #48] ; 0x30 + 307dc: 9909 ldr r1, [sp, #36] ; 0x24 + 307de: aa29 add r2, sp, #164 ; 0xa4 + 307e0: f8cd c018 str.w ip, [sp, #24] + 307e4: f7fe fd36 bl 2f254 <__rtl_sprint_r_v1_00.part.9> + 307e8: f8dd c018 ldr.w ip, [sp, #24] + 307ec: 2800 cmp r0, #0 + 307ee: f47f abc0 bne.w 2ff72 <__rtl_vfprintf_r_v1_00+0x912> + 307f2: 4644 mov r4, r8 + 307f4: f7ff b905 b.w 2fa02 <__rtl_vfprintf_r_v1_00+0x3a2> + 307f8: 9506 str r5, [sp, #24] + 307fa: 4630 mov r0, r6 + 307fc: 9d13 ldr r5, [sp, #76] ; 0x4c + 307fe: 47a8 blx r5 + 30800: f8dd c018 ldr.w ip, [sp, #24] + 30804: ea20 75e0 bic.w r5, r0, r0, asr #31 + 30808: 9010 str r0, [sp, #64] ; 0x40 + 3080a: f8cd a03c str.w sl, [sp, #60] ; 0x3c + 3080e: 950a str r5, [sp, #40] ; 0x28 + 30810: f8cd c064 str.w ip, [sp, #100] ; 0x64 + 30814: f89d 2087 ldrb.w r2, [sp, #135] ; 0x87 + 30818: f7ff b873 b.w 2f902 <__rtl_vfprintf_r_v1_00+0x2a2> + 3081c: f64e 4004 movw r0, #60420 ; 0xec04 + 30820: f2c0 0003 movt r0, #3 + 30824: 9a2a ldr r2, [sp, #168] ; 0xa8 + 30826: 900e str r0, [sp, #56] ; 0x38 + 30828: f102 0e01 add.w lr, r2, #1 + 3082c: 9a2b ldr r2, [sp, #172] ; 0xac + 3082e: f7ff b8ad b.w 2f98c <__rtl_vfprintf_r_v1_00+0x32c> + 30832: 9b27 ldr r3, [sp, #156] ; 0x9c + 30834: 1a1b subs r3, r3, r0 + 30836: 930d str r3, [sp, #52] ; 0x34 + 30838: 9b23 ldr r3, [sp, #140] ; 0x8c + 3083a: 1cda adds r2, r3, #3 + 3083c: f2c0 8086 blt.w 3094c <__rtl_vfprintf_r_v1_00+0x12ec> + 30840: 459c cmp ip, r3 + 30842: f2c0 8083 blt.w 3094c <__rtl_vfprintf_r_v1_00+0x12ec> + 30846: 9319 str r3, [sp, #100] ; 0x64 + 30848: e695 b.n 30576 <__rtl_vfprintf_r_v1_00+0xf16> + 3084a: 9d14 ldr r5, [sp, #80] ; 0x50 + 3084c: 222d movs r2, #45 ; 0x2d + 3084e: 930a str r3, [sp, #40] ; 0x28 + 30850: 9508 str r5, [sp, #32] + 30852: f88d 2087 strb.w r2, [sp, #135] ; 0x87 + 30856: f04f 0c00 mov.w ip, #0 + 3085a: f7ff b853 b.w 2f904 <__rtl_vfprintf_r_v1_00+0x2a4> + 3085e: 9a2a ldr r2, [sp, #168] ; 0xa8 + 30860: 9b2b ldr r3, [sp, #172] ; 0xac + 30862: 3201 adds r2, #1 + 30864: 9817 ldr r0, [sp, #92] ; 0x5c + 30866: 3301 adds r3, #1 + 30868: 2101 movs r1, #1 + 3086a: 2a07 cmp r2, #7 + 3086c: 6020 str r0, [r4, #0] + 3086e: 6061 str r1, [r4, #4] + 30870: 932b str r3, [sp, #172] ; 0xac + 30872: 922a str r2, [sp, #168] ; 0xa8 + 30874: bfd8 it le + 30876: 3408 addle r4, #8 + 30878: dd04 ble.n 30884 <__rtl_vfprintf_r_v1_00+0x1224> + 3087a: 2b00 cmp r3, #0 + 3087c: f040 818c bne.w 30b98 <__rtl_vfprintf_r_v1_00+0x1538> + 30880: 4644 mov r4, r8 + 30882: 932a str r3, [sp, #168] ; 0xa8 + 30884: b92d cbnz r5, 30892 <__rtl_vfprintf_r_v1_00+0x1232> + 30886: 990d ldr r1, [sp, #52] ; 0x34 + 30888: b919 cbnz r1, 30892 <__rtl_vfprintf_r_v1_00+0x1232> + 3088a: 9a08 ldr r2, [sp, #32] + 3088c: 07d7 lsls r7, r2, #31 + 3088e: f57f a903 bpl.w 2fa98 <__rtl_vfprintf_r_v1_00+0x438> + 30892: 982a ldr r0, [sp, #168] ; 0xa8 + 30894: 991c ldr r1, [sp, #112] ; 0x70 + 30896: 9a16 ldr r2, [sp, #88] ; 0x58 + 30898: 440b add r3, r1 + 3089a: 6022 str r2, [r4, #0] + 3089c: 1c41 adds r1, r0, #1 + 3089e: 9a1c ldr r2, [sp, #112] ; 0x70 + 308a0: 2907 cmp r1, #7 + 308a2: 6062 str r2, [r4, #4] + 308a4: 932b str r3, [sp, #172] ; 0xac + 308a6: 912a str r1, [sp, #168] ; 0xa8 + 308a8: bfdc itt le + 308aa: 3408 addle r4, #8 + 308ac: 3002 addle r0, #2 + 308ae: dd05 ble.n 308bc <__rtl_vfprintf_r_v1_00+0x125c> + 308b0: 2b00 cmp r3, #0 + 308b2: f040 8163 bne.w 30b7c <__rtl_vfprintf_r_v1_00+0x151c> + 308b6: 4619 mov r1, r3 + 308b8: 4644 mov r4, r8 + 308ba: 2001 movs r0, #1 + 308bc: 426d negs r5, r5 + 308be: 2d00 cmp r5, #0 + 308c0: f77f ab2a ble.w 2ff18 <__rtl_vfprintf_r_v1_00+0x8b8> + 308c4: 2d10 cmp r5, #16 + 308c6: bfdc itt le + 308c8: 491f ldrle r1, [pc, #124] ; (30948 <__rtl_vfprintf_r_v1_00+0x12e8>) + 308ca: 910e strle r1, [sp, #56] ; 0x38 + 308cc: f340 80aa ble.w 30a24 <__rtl_vfprintf_r_v1_00+0x13c4> + 308d0: 4a1d ldr r2, [pc, #116] ; (30948 <__rtl_vfprintf_r_v1_00+0x12e8>) + 308d2: 2710 movs r7, #16 + 308d4: 920e str r2, [sp, #56] ; 0x38 + 308d6: e006 b.n 308e6 <__rtl_vfprintf_r_v1_00+0x1286> + 308d8: 1c88 adds r0, r1, #2 + 308da: 4611 mov r1, r2 + 308dc: 3408 adds r4, #8 + 308de: 3d10 subs r5, #16 + 308e0: 2d10 cmp r5, #16 + 308e2: f340 809f ble.w 30a24 <__rtl_vfprintf_r_v1_00+0x13c4> + 308e6: 1c4a adds r2, r1, #1 + 308e8: 3310 adds r3, #16 + 308ea: 2a07 cmp r2, #7 + 308ec: 932b str r3, [sp, #172] ; 0xac + 308ee: f8c4 9000 str.w r9, [r4] + 308f2: 6067 str r7, [r4, #4] + 308f4: 922a str r2, [sp, #168] ; 0xa8 + 308f6: ddef ble.n 308d8 <__rtl_vfprintf_r_v1_00+0x1278> + 308f8: b91b cbnz r3, 30902 <__rtl_vfprintf_r_v1_00+0x12a2> + 308fa: 4619 mov r1, r3 + 308fc: 2001 movs r0, #1 + 308fe: 4644 mov r4, r8 + 30900: e7ed b.n 308de <__rtl_vfprintf_r_v1_00+0x127e> + 30902: 980c ldr r0, [sp, #48] ; 0x30 + 30904: 9909 ldr r1, [sp, #36] ; 0x24 + 30906: aa29 add r2, sp, #164 ; 0xa4 + 30908: f7fe fca4 bl 2f254 <__rtl_sprint_r_v1_00.part.9> + 3090c: 2800 cmp r0, #0 + 3090e: f47f ab30 bne.w 2ff72 <__rtl_vfprintf_r_v1_00+0x912> + 30912: 992a ldr r1, [sp, #168] ; 0xa8 + 30914: 4644 mov r4, r8 + 30916: 9b2b ldr r3, [sp, #172] ; 0xac + 30918: 1c48 adds r0, r1, #1 + 3091a: e7e0 b.n 308de <__rtl_vfprintf_r_v1_00+0x127e> + 3091c: 2306 movs r3, #6 + 3091e: 4563 cmp r3, ip + 30920: bf28 it cs + 30922: 4663 movcs r3, ip + 30924: 4632 mov r2, r6 + 30926: f643 0618 movw r6, #14360 ; 0x3818 + 3092a: ea23 75e3 bic.w r5, r3, r3, asr #31 + 3092e: 9310 str r3, [sp, #64] ; 0x40 + 30930: 4694 mov ip, r2 + 30932: f8cd a03c str.w sl, [sp, #60] ; 0x3c + 30936: 9219 str r2, [sp, #100] ; 0x64 + 30938: 950a str r5, [sp, #40] ; 0x28 + 3093a: f2c0 0604 movt r6, #4 + 3093e: f7fe bfe0 b.w 2f902 <__rtl_vfprintf_r_v1_00+0x2a2> + 30942: 9b10 ldr r3, [sp, #64] ; 0x40 + 30944: e609 b.n 3055a <__rtl_vfprintf_r_v1_00+0xefa> + 30946: bf00 nop + 30948: 0003ec14 .word 0x0003ec14 + 3094c: 3f02 subs r7, #2 + 3094e: 3b01 subs r3, #1 + 30950: 2b00 cmp r3, #0 + 30952: 9323 str r3, [sp, #140] ; 0x8c + 30954: bfba itte lt + 30956: 425b neglt r3, r3 + 30958: 222d movlt r2, #45 ; 0x2d + 3095a: 222b movge r2, #43 ; 0x2b + 3095c: 2b09 cmp r3, #9 + 3095e: f88d 7094 strb.w r7, [sp, #148] ; 0x94 + 30962: f88d 2095 strb.w r2, [sp, #149] ; 0x95 + 30966: f300 8084 bgt.w 30a72 <__rtl_vfprintf_r_v1_00+0x1412> + 3096a: 3330 adds r3, #48 ; 0x30 + 3096c: 2230 movs r2, #48 ; 0x30 + 3096e: f88d 3097 strb.w r3, [sp, #151] ; 0x97 + 30972: f88d 2096 strb.w r2, [sp, #150] ; 0x96 + 30976: ab26 add r3, sp, #152 ; 0x98 + 30978: aa25 add r2, sp, #148 ; 0x94 + 3097a: 9d0d ldr r5, [sp, #52] ; 0x34 + 3097c: 1a9a subs r2, r3, r2 + 3097e: 4415 add r5, r2 + 30980: 9510 str r5, [sp, #64] ; 0x40 + 30982: 9d0d ldr r5, [sp, #52] ; 0x34 + 30984: 921d str r2, [sp, #116] ; 0x74 + 30986: 2d01 cmp r5, #1 + 30988: f340 80c7 ble.w 30b1a <__rtl_vfprintf_r_v1_00+0x14ba> + 3098c: 9b10 ldr r3, [sp, #64] ; 0x40 + 3098e: 2500 movs r5, #0 + 30990: 3301 adds r3, #1 + 30992: 9310 str r3, [sp, #64] ; 0x40 + 30994: 9519 str r5, [sp, #100] ; 0x64 + 30996: ea23 73e3 bic.w r3, r3, r3, asr #31 + 3099a: e5ff b.n 3059c <__rtl_vfprintf_r_v1_00+0xf3c> + 3099c: f64e 4204 movw r2, #60420 ; 0xec04 + 309a0: f2c0 0203 movt r2, #3 + 309a4: 982a ldr r0, [sp, #168] ; 0xa8 + 309a6: 920e str r2, [sp, #56] ; 0x38 + 309a8: 3001 adds r0, #1 + 309aa: f7ff b8a9 b.w 2fb00 <__rtl_vfprintf_r_v1_00+0x4a0> + 309ae: 982a ldr r0, [sp, #168] ; 0xa8 + 309b0: 4a97 ldr r2, [pc, #604] ; (30c10 <__rtl_vfprintf_r_v1_00+0x15b0>) + 309b2: 9b2b ldr r3, [sp, #172] ; 0xac + 309b4: 3001 adds r0, #1 + 309b6: 920e str r2, [sp, #56] ; 0x38 + 309b8: f7ff bb82 b.w 300c0 <__rtl_vfprintf_r_v1_00+0xa60> + 309bc: ea2c 75ec bic.w r5, ip, ip, asr #31 + 309c0: f8cd c040 str.w ip, [sp, #64] ; 0x40 + 309c4: 950a str r5, [sp, #40] ; 0x28 + 309c6: 4684 mov ip, r0 + 309c8: f8cd a03c str.w sl, [sp, #60] ; 0x3c + 309cc: 9019 str r0, [sp, #100] ; 0x64 + 309ce: f89d 2087 ldrb.w r2, [sp, #135] ; 0x87 + 309d2: f7fe bf96 b.w 2f902 <__rtl_vfprintf_r_v1_00+0x2a2> + 309d6: 2102 movs r1, #2 + 309d8: e57b b.n 304d2 <__rtl_vfprintf_r_v1_00+0xe72> + 309da: 9d19 ldr r5, [sp, #100] ; 0x64 + 309dc: 2767 movs r7, #103 ; 0x67 + 309de: 2d00 cmp r5, #0 + 309e0: bfd8 it le + 309e2: f1c5 0302 rsble r3, r5, #2 + 309e6: 9d0d ldr r5, [sp, #52] ; 0x34 + 309e8: bfc8 it gt + 309ea: 2301 movgt r3, #1 + 309ec: 441d add r5, r3 + 309ee: 9510 str r5, [sp, #64] ; 0x40 + 309f0: ea25 73e5 bic.w r3, r5, r5, asr #31 + 309f4: e5d2 b.n 3059c <__rtl_vfprintf_r_v1_00+0xf3c> + 309f6: 980c ldr r0, [sp, #48] ; 0x30 + 309f8: 9909 ldr r1, [sp, #36] ; 0x24 + 309fa: aa29 add r2, sp, #164 ; 0xa4 + 309fc: f7fe fc2a bl 2f254 <__rtl_sprint_r_v1_00.part.9> + 30a00: 2800 cmp r0, #0 + 30a02: f47f aab6 bne.w 2ff72 <__rtl_vfprintf_r_v1_00+0x912> + 30a06: 4644 mov r4, r8 + 30a08: 9b2b ldr r3, [sp, #172] ; 0xac + 30a0a: f7ff bbfa b.w 30202 <__rtl_vfprintf_r_v1_00+0xba2> + 30a0e: 980c ldr r0, [sp, #48] ; 0x30 + 30a10: 9909 ldr r1, [sp, #36] ; 0x24 + 30a12: aa29 add r2, sp, #164 ; 0xa4 + 30a14: f7fe fc1e bl 2f254 <__rtl_sprint_r_v1_00.part.9> + 30a18: 2800 cmp r0, #0 + 30a1a: f47f aaaa bne.w 2ff72 <__rtl_vfprintf_r_v1_00+0x912> + 30a1e: 4644 mov r4, r8 + 30a20: 9b2b ldr r3, [sp, #172] ; 0xac + 30a22: e406 b.n 30232 <__rtl_vfprintf_r_v1_00+0xbd2> + 30a24: 990e ldr r1, [sp, #56] ; 0x38 + 30a26: 2807 cmp r0, #7 + 30a28: 442b add r3, r5 + 30a2a: e884 0022 stmia.w r4, {r1, r5} + 30a2e: 902a str r0, [sp, #168] ; 0xa8 + 30a30: 932b str r3, [sp, #172] ; 0xac + 30a32: bfdc itt le + 30a34: 3408 addle r4, #8 + 30a36: 3001 addle r0, #1 + 30a38: f77f aa6e ble.w 2ff18 <__rtl_vfprintf_r_v1_00+0x8b8> + 30a3c: 2b00 cmp r3, #0 + 30a3e: f47f aa60 bne.w 2ff02 <__rtl_vfprintf_r_v1_00+0x8a2> + 30a42: 9c0d ldr r4, [sp, #52] ; 0x34 + 30a44: 2301 movs r3, #1 + 30a46: 9437 str r4, [sp, #220] ; 0xdc + 30a48: 942b str r4, [sp, #172] ; 0xac + 30a4a: 932a str r3, [sp, #168] ; 0xa8 + 30a4c: 9636 str r6, [sp, #216] ; 0xd8 + 30a4e: 4623 mov r3, r4 + 30a50: 4644 mov r4, r8 + 30a52: f7ff b820 b.w 2fa96 <__rtl_vfprintf_r_v1_00+0x436> + 30a56: 2d00 cmp r5, #0 + 30a58: f340 80c4 ble.w 30be4 <__rtl_vfprintf_r_v1_00+0x1584> + 30a5c: f1bc 0f00 cmp.w ip, #0 + 30a60: d153 bne.n 30b0a <__rtl_vfprintf_r_v1_00+0x14aa> + 30a62: 9d08 ldr r5, [sp, #32] + 30a64: 07eb lsls r3, r5, #31 + 30a66: d450 bmi.n 30b0a <__rtl_vfprintf_r_v1_00+0x14aa> + 30a68: 9d19 ldr r5, [sp, #100] ; 0x64 + 30a6a: ea25 73e5 bic.w r3, r5, r5, asr #31 + 30a6e: 9510 str r5, [sp, #64] ; 0x40 + 30a70: e594 b.n 3059c <__rtl_vfprintf_r_v1_00+0xf3c> + 30a72: f246 6e67 movw lr, #26215 ; 0x6667 + 30a76: f2c6 6e66 movt lr, #26214 ; 0x6666 + 30a7a: f10d 00a2 add.w r0, sp, #162 ; 0xa2 + 30a7e: fb8e 2103 smull r2, r1, lr, r3 + 30a82: 17da asrs r2, r3, #31 + 30a84: ebc2 01a1 rsb r1, r2, r1, asr #2 + 30a88: eb01 0581 add.w r5, r1, r1, lsl #2 + 30a8c: 4602 mov r2, r0 + 30a8e: eba3 0045 sub.w r0, r3, r5, lsl #1 + 30a92: 460b mov r3, r1 + 30a94: f100 0130 add.w r1, r0, #48 ; 0x30 + 30a98: 2b09 cmp r3, #9 + 30a9a: 7011 strb r1, [r2, #0] + 30a9c: f102 30ff add.w r0, r2, #4294967295 + 30aa0: dced bgt.n 30a7e <__rtl_vfprintf_r_v1_00+0x141e> + 30aa2: 3330 adds r3, #48 ; 0x30 + 30aa4: f10d 05a3 add.w r5, sp, #163 ; 0xa3 + 30aa8: b2d9 uxtb r1, r3 + 30aaa: 4285 cmp r5, r0 + 30aac: f802 1c01 strb.w r1, [r2, #-1] + 30ab0: f240 80a8 bls.w 30c04 <__rtl_vfprintf_r_v1_00+0x15a4> + 30ab4: f10d 0096 add.w r0, sp, #150 ; 0x96 + 30ab8: 4613 mov r3, r2 + 30aba: e001 b.n 30ac0 <__rtl_vfprintf_r_v1_00+0x1460> + 30abc: f813 1b01 ldrb.w r1, [r3], #1 + 30ac0: 42ab cmp r3, r5 + 30ac2: f800 1b01 strb.w r1, [r0], #1 + 30ac6: d1f9 bne.n 30abc <__rtl_vfprintf_r_v1_00+0x145c> + 30ac8: ab29 add r3, sp, #164 ; 0xa4 + 30aca: 1a9b subs r3, r3, r2 + 30acc: f10d 0596 add.w r5, sp, #150 ; 0x96 + 30ad0: 442b add r3, r5 + 30ad2: e751 b.n 30978 <__rtl_vfprintf_r_v1_00+0x1318> + 30ad4: f64b 6a4d movw sl, #48717 ; 0xbe4d + 30ad8: f2c0 0a02 movt sl, #2 + 30adc: e526 b.n 3052c <__rtl_vfprintf_r_v1_00+0xecc> + 30ade: 980c ldr r0, [sp, #48] ; 0x30 + 30ae0: 9909 ldr r1, [sp, #36] ; 0x24 + 30ae2: aa29 add r2, sp, #164 ; 0xa4 + 30ae4: f7fe fbb6 bl 2f254 <__rtl_sprint_r_v1_00.part.9> + 30ae8: 2800 cmp r0, #0 + 30aea: f47f aa42 bne.w 2ff72 <__rtl_vfprintf_r_v1_00+0x912> + 30aee: 4644 mov r4, r8 + 30af0: 9b2b ldr r3, [sp, #172] ; 0xac + 30af2: e471 b.n 303d8 <__rtl_vfprintf_r_v1_00+0xd78> + 30af4: 980c ldr r0, [sp, #48] ; 0x30 + 30af6: 9909 ldr r1, [sp, #36] ; 0x24 + 30af8: aa29 add r2, sp, #164 ; 0xa4 + 30afa: f7fe fbab bl 2f254 <__rtl_sprint_r_v1_00.part.9> + 30afe: 2800 cmp r0, #0 + 30b00: f47f aa37 bne.w 2ff72 <__rtl_vfprintf_r_v1_00+0x912> + 30b04: 4644 mov r4, r8 + 30b06: 9b2b ldr r3, [sp, #172] ; 0xac + 30b08: e593 b.n 30632 <__rtl_vfprintf_r_v1_00+0xfd2> + 30b0a: 9d19 ldr r5, [sp, #100] ; 0x64 + 30b0c: f10c 0301 add.w r3, ip, #1 + 30b10: 441d add r5, r3 + 30b12: 9510 str r5, [sp, #64] ; 0x40 + 30b14: ea25 73e5 bic.w r3, r5, r5, asr #31 + 30b18: e540 b.n 3059c <__rtl_vfprintf_r_v1_00+0xf3c> + 30b1a: 9d08 ldr r5, [sp, #32] + 30b1c: f015 0301 ands.w r3, r5, #1 + 30b20: f47f af34 bne.w 3098c <__rtl_vfprintf_r_v1_00+0x132c> + 30b24: 9d10 ldr r5, [sp, #64] ; 0x40 + 30b26: 9319 str r3, [sp, #100] ; 0x64 + 30b28: ea25 73e5 bic.w r3, r5, r5, asr #31 + 30b2c: e536 b.n 3059c <__rtl_vfprintf_r_v1_00+0xf3c> + 30b2e: 980c ldr r0, [sp, #48] ; 0x30 + 30b30: 9909 ldr r1, [sp, #36] ; 0x24 + 30b32: aa29 add r2, sp, #164 ; 0xa4 + 30b34: f7fe fb8e bl 2f254 <__rtl_sprint_r_v1_00.part.9> + 30b38: 2800 cmp r0, #0 + 30b3a: f47f aa1a bne.w 2ff72 <__rtl_vfprintf_r_v1_00+0x912> + 30b3e: 9a23 ldr r2, [sp, #140] ; 0x8c + 30b40: 9b2b ldr r3, [sp, #172] ; 0xac + 30b42: 4644 mov r4, r8 + 30b44: e591 b.n 3066a <__rtl_vfprintf_r_v1_00+0x100a> + 30b46: 980c ldr r0, [sp, #48] ; 0x30 + 30b48: 9909 ldr r1, [sp, #36] ; 0x24 + 30b4a: aa29 add r2, sp, #164 ; 0xa4 + 30b4c: f7fe fb82 bl 2f254 <__rtl_sprint_r_v1_00.part.9> + 30b50: 2800 cmp r0, #0 + 30b52: f47f aa0e bne.w 2ff72 <__rtl_vfprintf_r_v1_00+0x912> + 30b56: 9c0d ldr r4, [sp, #52] ; 0x34 + 30b58: 9a23 ldr r2, [sp, #140] ; 0x8c + 30b5a: 9b2b ldr r3, [sp, #172] ; 0xac + 30b5c: 1aa2 subs r2, r4, r2 + 30b5e: 4644 mov r4, r8 + 30b60: e59c b.n 3069c <__rtl_vfprintf_r_v1_00+0x103c> + 30b62: 9d0f ldr r5, [sp, #60] ; 0x3c + 30b64: 462b mov r3, r5 + 30b66: 6828 ldr r0, [r5, #0] + 30b68: 3304 adds r3, #4 + 30b6a: 2800 cmp r0, #0 + 30b6c: f6bf a8cb bge.w 2fd06 <__rtl_vfprintf_r_v1_00+0x6a6> + 30b70: 930f str r3, [sp, #60] ; 0x3c + 30b72: f04f 30ff mov.w r0, #4294967295 + 30b76: 465d mov r5, fp + 30b78: f7fe bdf9 b.w 2f76e <__rtl_vfprintf_r_v1_00+0x10e> + 30b7c: 980c ldr r0, [sp, #48] ; 0x30 + 30b7e: 9909 ldr r1, [sp, #36] ; 0x24 + 30b80: aa29 add r2, sp, #164 ; 0xa4 + 30b82: f7fe fb67 bl 2f254 <__rtl_sprint_r_v1_00.part.9> + 30b86: 2800 cmp r0, #0 + 30b88: f47f a9f3 bne.w 2ff72 <__rtl_vfprintf_r_v1_00+0x912> + 30b8c: 992a ldr r1, [sp, #168] ; 0xa8 + 30b8e: 4644 mov r4, r8 + 30b90: 9d23 ldr r5, [sp, #140] ; 0x8c + 30b92: 9b2b ldr r3, [sp, #172] ; 0xac + 30b94: 1c48 adds r0, r1, #1 + 30b96: e691 b.n 308bc <__rtl_vfprintf_r_v1_00+0x125c> + 30b98: 980c ldr r0, [sp, #48] ; 0x30 + 30b9a: 9909 ldr r1, [sp, #36] ; 0x24 + 30b9c: aa29 add r2, sp, #164 ; 0xa4 + 30b9e: f7fe fb59 bl 2f254 <__rtl_sprint_r_v1_00.part.9> + 30ba2: 2800 cmp r0, #0 + 30ba4: f47f a9e5 bne.w 2ff72 <__rtl_vfprintf_r_v1_00+0x912> + 30ba8: 4644 mov r4, r8 + 30baa: 9d23 ldr r5, [sp, #140] ; 0x8c + 30bac: 9b2b ldr r3, [sp, #172] ; 0xac + 30bae: e669 b.n 30884 <__rtl_vfprintf_r_v1_00+0x1224> + 30bb0: f8cd c018 str.w ip, [sp, #24] + 30bb4: 981a ldr r0, [sp, #104] ; 0x68 + 30bb6: 990d ldr r1, [sp, #52] ; 0x34 + 30bb8: 2200 movs r2, #0 + 30bba: 2300 movs r3, #0 + 30bbc: 9d15 ldr r5, [sp, #84] ; 0x54 + 30bbe: f64b 6a4d movw sl, #48717 ; 0xbe4d + 30bc2: 47a8 blx r5 + 30bc4: f2c0 0a02 movt sl, #2 + 30bc8: f8dd c018 ldr.w ip, [sp, #24] + 30bcc: b908 cbnz r0, 30bd2 <__rtl_vfprintf_r_v1_00+0x1572> + 30bce: 9b23 ldr r3, [sp, #140] ; 0x8c + 30bd0: e4a9 b.n 30526 <__rtl_vfprintf_r_v1_00+0xec6> + 30bd2: f1cc 0301 rsb r3, ip, #1 + 30bd6: 9323 str r3, [sp, #140] ; 0x8c + 30bd8: e4a5 b.n 30526 <__rtl_vfprintf_r_v1_00+0xec6> + 30bda: 982a ldr r0, [sp, #168] ; 0xa8 + 30bdc: 4a0c ldr r2, [pc, #48] ; (30c10 <__rtl_vfprintf_r_v1_00+0x15b0>) + 30bde: 3001 adds r0, #1 + 30be0: 920e str r2, [sp, #56] ; 0x38 + 30be2: e517 b.n 30614 <__rtl_vfprintf_r_v1_00+0xfb4> + 30be4: f1bc 0f00 cmp.w ip, #0 + 30be8: d106 bne.n 30bf8 <__rtl_vfprintf_r_v1_00+0x1598> + 30bea: 9d08 ldr r5, [sp, #32] + 30bec: 07ed lsls r5, r5, #31 + 30bee: bf5c itt pl + 30bf0: 2301 movpl r3, #1 + 30bf2: 9310 strpl r3, [sp, #64] ; 0x40 + 30bf4: f57f acd2 bpl.w 3059c <__rtl_vfprintf_r_v1_00+0xf3c> + 30bf8: f10c 0302 add.w r3, ip, #2 + 30bfc: 9310 str r3, [sp, #64] ; 0x40 + 30bfe: ea23 73e3 bic.w r3, r3, r3, asr #31 + 30c02: e4cb b.n 3059c <__rtl_vfprintf_r_v1_00+0xf3c> + 30c04: f10d 0396 add.w r3, sp, #150 ; 0x96 + 30c08: e6b6 b.n 30978 <__rtl_vfprintf_r_v1_00+0x1318> + 30c0a: 9b23 ldr r3, [sp, #140] ; 0x8c + 30c0c: e69f b.n 3094e <__rtl_vfprintf_r_v1_00+0x12ee> + 30c0e: bf00 nop + 30c10: 0003ec14 .word 0x0003ec14 + +00030c14 <__rtl_fpclassifyd>: + 30c14: ea50 0301 orrs.w r3, r0, r1 + 30c18: d101 bne.n 30c1e <__rtl_fpclassifyd+0xa> + 30c1a: 2002 movs r0, #2 + 30c1c: 4770 bx lr + 30c1e: fab0 f380 clz r3, r0 + 30c22: f1b1 4f00 cmp.w r1, #2147483648 ; 0x80000000 + 30c26: bf08 it eq + 30c28: 2800 cmpeq r0, #0 + 30c2a: ea4f 1353 mov.w r3, r3, lsr #5 + 30c2e: d0f4 beq.n 30c1a <__rtl_fpclassifyd+0x6> + 30c30: f64f 72ff movw r2, #65535 ; 0xffff + 30c34: f6c7 72df movt r2, #32735 ; 0x7fdf + 30c38: f021 4100 bic.w r1, r1, #2147483648 ; 0x80000000 + 30c3c: f5a1 1080 sub.w r0, r1, #1048576 ; 0x100000 + 30c40: 4290 cmp r0, r2 + 30c42: d801 bhi.n 30c48 <__rtl_fpclassifyd+0x34> + 30c44: 2004 movs r0, #4 + 30c46: 4770 bx lr + 30c48: f5b1 1f80 cmp.w r1, #1048576 ; 0x100000 + 30c4c: d201 bcs.n 30c52 <__rtl_fpclassifyd+0x3e> + 30c4e: 2003 movs r0, #3 + 30c50: 4770 bx lr + 30c52: 2000 movs r0, #0 + 30c54: f6c7 70f0 movt r0, #32752 ; 0x7ff0 + 30c58: 4281 cmp r1, r0 + 30c5a: bf14 ite ne + 30c5c: 2000 movne r0, #0 + 30c5e: f003 0001 andeq.w r0, r3, #1 + 30c62: 4770 bx lr + 30c64: 0000 movs r0, r0 + ... + +00030c68 : + 30c68: c200 0beb e100 05f5 f080 02fa 7840 017d ............@x}. + 30c78: bc20 00be 0900 003d .....=. + +00030c80 : + 30c80: 7923 8816 00ff 0000 #y...... + +00030c88 : + 30c88: 9999 9696 cc3f fc66 33c0 03cc dce5 6231 ....?.f..3....1b + +00030c98 : + 30c98: 0101 005e 0101 0000 0201 0023 0501 0005 ..^.......#..... + +00030ca8 : + 30ca8: 04b0 0000 2580 0000 3840 0000 4b00 0000 .....%..@8...K.. + 30cb8: 7080 0000 9600 0000 e100 0000 2c00 0001 .p...........,.. + 30cc8: c200 0001 f400 0001 5800 0002 8400 0003 .........X...... + 30cd8: 0800 0007 a120 0007 1000 000e 4240 000f .... .......@B.. + 30ce8: 1800 0015 0a30 0016 e360 0016 2000 001c ....0...`.... .. + 30cf8: 8480 001e 0b20 0020 3000 002a c6c0 002d .... . ..0*...-. + 30d08: 9750 0031 570c 0038 3870 0039 0900 003d P.1..W8.p89...=. + 30d18: 8d80 005b ..[. + +00030d1c : + 30d1c: 000b 0000 000d 0000 0013 0000 000a 0000 ................ + 30d2c: 0014 0000 000a 0000 0014 0000 0011 0000 ................ + 30d3c: 000b 0000 000a 0000 0011 0000 000a 0000 ................ + 30d4c: 000a 0000 000d 0000 0012 0000 000d 0000 ................ + 30d5c: 0014 0000 0013 0000 000d 0000 000f 0000 ................ + 30d6c: 000d 0000 000d 0000 000f 0000 000d 0000 ................ + 30d7c: 000c 0000 000b 0000 000b 0000 0014 0000 ................ + 30d8c: 000d 0000 .... + +00030d90
: + 30d90: 17d9 0000 0283 0000 0125 0000 01b2 0000 ........%....... + 30da0: 008e 0000 00d9 0000 0047 0000 003e 0000 ........G...>... + 30db0: 0041 0000 003e 0000 001f 0000 0022 0000 A...>......."... + 30dc0: 0011 0000 000c 0000 0005 0000 0006 0000 ................ + 30dd0: 0003 0000 0003 0000 0004 0000 0003 0000 ................ + 30de0: 0003 0000 0003 0000 0002 0000 0002 0000 ................ + 30df0: 0002 0000 0002 0000 0002 0000 0001 0000 ................ + 30e00: 0001 0000 .... + +00030e04 : + 30e04: 024a 0000 0555 0000 03bb 0000 0000 0000 J...U........... + 30e14: 024a 0000 0000 0000 024a 0000 0555 0000 J.......J...U... + 30e24: 0008 0000 0555 0000 0555 0000 05ad 0000 ....U...U....... + 30e34: 05ad 0000 07ef 0000 0020 0000 07ef 0000 ........ ....... + 30e44: 0020 0000 0444 0000 07ef 0000 0080 0000 ...D........... + 30e54: 07ef 0000 0444 0000 0080 0000 07ef 0000 ....D........... + 30e64: 06fb 0000 0122 0000 0010 0000 05f7 0000 ...."........... + 30e74: 07ef 0000 .... + +00030e78 <__AES_rcon>: + 30e78: 0000 0100 0000 0200 0000 0400 0000 0800 ................ + 30e88: 0000 1000 0000 2000 0000 4000 0000 8000 ....... ...@.... + 30e98: 0000 1b00 0000 3600 .......6 + +00030ea0 <__AES_Te4>: + 30ea0: 6363 6363 7c7c 7c7c 7777 7777 7b7b 7b7b cccc||||wwww{{{{ + 30eb0: f2f2 f2f2 6b6b 6b6b 6f6f 6f6f c5c5 c5c5 ....kkkkoooo.... + 30ec0: 3030 3030 0101 0101 6767 6767 2b2b 2b2b 0000....gggg++++ + 30ed0: fefe fefe d7d7 d7d7 abab abab 7676 7676 ............vvvv + 30ee0: caca caca 8282 8282 c9c9 c9c9 7d7d 7d7d ............}}}} + 30ef0: fafa fafa 5959 5959 4747 4747 f0f0 f0f0 ....YYYYGGGG.... + 30f00: adad adad d4d4 d4d4 a2a2 a2a2 afaf afaf ................ + 30f10: 9c9c 9c9c a4a4 a4a4 7272 7272 c0c0 c0c0 ........rrrr.... + 30f20: b7b7 b7b7 fdfd fdfd 9393 9393 2626 2626 ............&&&& + 30f30: 3636 3636 3f3f 3f3f f7f7 f7f7 cccc cccc 6666????........ + 30f40: 3434 3434 a5a5 a5a5 e5e5 e5e5 f1f1 f1f1 4444............ + 30f50: 7171 7171 d8d8 d8d8 3131 3131 1515 1515 qqqq....1111.... + 30f60: 0404 0404 c7c7 c7c7 2323 2323 c3c3 c3c3 ........####.... + 30f70: 1818 1818 9696 9696 0505 0505 9a9a 9a9a ................ + 30f80: 0707 0707 1212 1212 8080 8080 e2e2 e2e2 ................ + 30f90: ebeb ebeb 2727 2727 b2b2 b2b2 7575 7575 ....''''....uuuu + 30fa0: 0909 0909 8383 8383 2c2c 2c2c 1a1a 1a1a ........,,,,.... + 30fb0: 1b1b 1b1b 6e6e 6e6e 5a5a 5a5a a0a0 a0a0 ....nnnnZZZZ.... + 30fc0: 5252 5252 3b3b 3b3b d6d6 d6d6 b3b3 b3b3 RRRR;;;;........ + 30fd0: 2929 2929 e3e3 e3e3 2f2f 2f2f 8484 8484 ))))....////.... + 30fe0: 5353 5353 d1d1 d1d1 0000 0000 eded eded SSSS............ + 30ff0: 2020 2020 fcfc fcfc b1b1 b1b1 5b5b 5b5b ........[[[[ + 31000: 6a6a 6a6a cbcb cbcb bebe bebe 3939 3939 jjjj........9999 + 31010: 4a4a 4a4a 4c4c 4c4c 5858 5858 cfcf cfcf JJJJLLLLXXXX.... + 31020: d0d0 d0d0 efef efef aaaa aaaa fbfb fbfb ................ + 31030: 4343 4343 4d4d 4d4d 3333 3333 8585 8585 CCCCMMMM3333.... + 31040: 4545 4545 f9f9 f9f9 0202 0202 7f7f 7f7f EEEE............ + 31050: 5050 5050 3c3c 3c3c 9f9f 9f9f a8a8 a8a8 PPPP<<<<........ + 31060: 5151 5151 a3a3 a3a3 4040 4040 8f8f 8f8f QQQQ....@@@@.... + 31070: 9292 9292 9d9d 9d9d 3838 3838 f5f5 f5f5 ........8888.... + 31080: bcbc bcbc b6b6 b6b6 dada dada 2121 2121 ............!!!! + 31090: 1010 1010 ffff ffff f3f3 f3f3 d2d2 d2d2 ................ + 310a0: cdcd cdcd 0c0c 0c0c 1313 1313 ecec ecec ................ + 310b0: 5f5f 5f5f 9797 9797 4444 4444 1717 1717 ____....DDDD.... + 310c0: c4c4 c4c4 a7a7 a7a7 7e7e 7e7e 3d3d 3d3d ........~~~~==== + 310d0: 6464 6464 5d5d 5d5d 1919 1919 7373 7373 dddd]]]]....ssss + 310e0: 6060 6060 8181 8181 4f4f 4f4f dcdc dcdc ````....OOOO.... + 310f0: 2222 2222 2a2a 2a2a 9090 9090 8888 8888 """"****........ + 31100: 4646 4646 eeee eeee b8b8 b8b8 1414 1414 FFFF............ + 31110: dede dede 5e5e 5e5e 0b0b 0b0b dbdb dbdb ....^^^^........ + 31120: e0e0 e0e0 3232 3232 3a3a 3a3a 0a0a 0a0a ....2222::::.... + 31130: 4949 4949 0606 0606 2424 2424 5c5c 5c5c IIII....$$$$\\\\ + 31140: c2c2 c2c2 d3d3 d3d3 acac acac 6262 6262 ............bbbb + 31150: 9191 9191 9595 9595 e4e4 e4e4 7979 7979 ............yyyy + 31160: e7e7 e7e7 c8c8 c8c8 3737 3737 6d6d 6d6d ........7777mmmm + 31170: 8d8d 8d8d d5d5 d5d5 4e4e 4e4e a9a9 a9a9 ........NNNN.... + 31180: 6c6c 6c6c 5656 5656 f4f4 f4f4 eaea eaea llllVVVV........ + 31190: 6565 6565 7a7a 7a7a aeae aeae 0808 0808 eeeezzzz........ + 311a0: baba baba 7878 7878 2525 2525 2e2e 2e2e ....xxxx%%%%.... + 311b0: 1c1c 1c1c a6a6 a6a6 b4b4 b4b4 c6c6 c6c6 ................ + 311c0: e8e8 e8e8 dddd dddd 7474 7474 1f1f 1f1f ........tttt.... + 311d0: 4b4b 4b4b bdbd bdbd 8b8b 8b8b 8a8a 8a8a KKKK............ + 311e0: 7070 7070 3e3e 3e3e b5b5 b5b5 6666 6666 pppp>>>>....ffff + 311f0: 4848 4848 0303 0303 f6f6 f6f6 0e0e 0e0e HHHH............ + 31200: 6161 6161 3535 3535 5757 5757 b9b9 b9b9 aaaa5555WWWW.... + 31210: 8686 8686 c1c1 c1c1 1d1d 1d1d 9e9e 9e9e ................ + 31220: e1e1 e1e1 f8f8 f8f8 9898 9898 1111 1111 ................ + 31230: 6969 6969 d9d9 d9d9 8e8e 8e8e 9494 9494 iiii............ + 31240: 9b9b 9b9b 1e1e 1e1e 8787 8787 e9e9 e9e9 ................ + 31250: cece cece 5555 5555 2828 2828 dfdf dfdf ....UUUU((((.... + 31260: 8c8c 8c8c a1a1 a1a1 8989 8989 0d0d 0d0d ................ + 31270: bfbf bfbf e6e6 e6e6 4242 4242 6868 6868 ........BBBBhhhh + 31280: 4141 4141 9999 9999 2d2d 2d2d 0f0f 0f0f AAAA....----.... + 31290: b0b0 b0b0 5454 5454 bbbb bbbb 1616 1616 ....TTTT........ + +000312a0 : + 312a0: 0000 0101 0202 0404 0808 1010 2020 4040 ............ @@ + 312b0: 8080 ffff .... + +000312b4 <_GPIO_PinMap_Chip2IP_8195a>: + 312b4: 0000 0101 2002 2103 2204 2305 2406 2507 ..... .!.".#.$.% + 312c4: 2610 2711 2812 0213 0314 2915 0416 0517 .&.'.(.....).... + 312d4: 2a20 0621 2b22 0723 0824 0925 0a26 0b27 *!."+#.$.%.&.'. + 312e4: 0c28 0d29 2c30 0e31 2d32 0f33 1034 1135 (.).0,1.2-3.4.5. + 312f4: 1236 1337 2e38 1439 2f40 1541 1642 1743 6.7.8.9.@/A.B.C. + 31304: 3044 1845 1946 1a47 1b48 3149 324a 3350 D0E.F.G.H.I1J2P3 + 31314: 3451 3552 3653 3754 3855 3960 3a61 3b62 Q4R5S6T7U8`9a:b; + 31324: 1c63 3c64 3d65 3e66 3f67 4070 1d71 4172 c.dg?p@q.rA + 31334: 1e73 4274 1f75 4376 4477 4580 4681 4782 s.tBu.vCwD.E.F.G + 31344: 4883 4984 4a85 4b86 4c87 4d90 4e91 4f92 .H.I.J.K.L.M.N.O + 31354: 5093 5194 5295 5396 54a0 55a1 56a2 57a3 .P.Q.R.S.T.U.V.W + 31364: 58a4 59a5 5aa6 ffff .X.Y.Z.. + +0003136c <_GPIO_PinMap_PullCtrl_8195a>: + 3136c: 0000 0330 0000 0001 0330 0002 0002 0330 ..0.....0.....0. + 3137c: 0004 0003 0330 0006 0004 0330 0008 0005 ....0.....0..... + 3138c: 0330 000a 0006 0330 000c 0007 0330 000e 0.....0.....0... + 3139c: 0010 0330 0010 0011 0330 0012 0012 0330 ..0.....0.....0. + 313ac: 0014 0013 0330 0016 0014 0330 0018 0015 ....0.....0..... + 313bc: 0330 001a 0016 0330 001c 0017 0330 001e 0.....0.....0... + 313cc: 0020 0334 0000 0021 0334 0002 0022 0334 .4...!.4...".4. + 313dc: 0004 0023 0334 0006 0024 0334 0008 0025 ..#.4...$.4...%. + 313ec: 0334 000a 0026 0334 000c 0027 0334 000e 4...&.4...'.4... + 313fc: 0028 0348 0000 0029 0348 0002 0030 0334 (.H...).H...0.4. + 3140c: 0010 0031 0334 0012 0032 0334 0014 0033 ..1.4...2.4...3. + 3141c: 0334 0016 0034 0334 0018 0035 0334 001a 4...4.4...5.4... + 3142c: 0036 0334 001c 0037 0334 001e 0038 0348 6.4...7.4...8.H. + 3143c: 0010 0039 0348 0012 0040 0338 0000 0041 ..9.H...@.8...A. + 3144c: 0338 0002 0042 0338 0004 0043 0338 0006 8...B.8...C.8... + 3145c: 0044 0338 0008 0045 0338 000a 0046 0338 D.8...E.8...F.8. + 3146c: 000c 0047 0338 000e 0048 0344 0010 0049 ..G.8...H.D...I. + 3147c: 0344 0012 004a 0344 0014 0050 0338 0010 D...J.D...P.8... + 3148c: 0051 0338 0012 0052 0338 0014 0053 0338 Q.8...R.8...S.8. + 3149c: 0016 0054 0338 0018 0055 0338 001a 0060 ..T.8...U.8...`. + 314ac: 033c 0000 0061 033c 0002 0062 033c 0004 <...a.<...b.<... + 314bc: 0063 033c 0006 0064 033c 0008 0065 033c c.<...d.<...e.<. + 314cc: 000a 0066 033c 000c 0067 033c 000e 0070 ..f.<...g.<...p. + 314dc: 033c 0010 0071 033c 0012 0072 033c 0014 <...q.<...r.<... + 314ec: 0073 033c 0016 0074 033c 0018 0075 033c s.<...t.<...u.<. + 314fc: 001a 0076 033c 001c 0077 033c 001e 0080 ..v.<...w.<..... + 3150c: 0340 0000 0081 0340 0002 0082 0340 0004 @.....@.....@... + 3151c: 0083 0340 0006 0084 0340 0008 0085 0340 ..@.....@.....@. + 3152c: 000a 0086 0340 000c 0087 0340 000e 0090 ....@.....@..... + 3153c: 0340 0010 0091 0340 0012 0092 0340 0014 @.....@.....@... + 3154c: 0093 0340 0016 0094 0340 0018 0095 0340 ..@.....@.....@. + 3155c: 001a 0096 0340 001c 00a0 0344 0000 00a1 ....@.....D..... + 3156c: 0344 0002 00a2 0344 0004 00a3 0344 0006 D.....D.....D... + 3157c: 00a4 0344 0008 00a5 0344 000a 00a6 0344 ..D.....D.....D. + 3158c: 000c ffff ffff ffff ........ + +00031594 <_GPIO_SWPORT_DDR_TBL>: + 31594: 1004 001c .... + +00031598 <_GPIO_EXT_PORT_TBL>: + 31598: 5450 0058 PTX. + +0003159c <_GPIO_SWPORT_DR_TBL>: + 3159c: 0c00 0018 .... + +000315a0 <__countLeadingZerosHigh>: + 315a0: 0708 0606 0505 0505 0404 0404 0404 0404 ................ + 315b0: 0303 0303 0303 0303 0303 0303 0303 0303 ................ + 315c0: 0202 0202 0202 0202 0202 0202 0202 0202 ................ + 315d0: 0202 0202 0202 0202 0202 0202 0202 0202 ................ + 315e0: 0101 0101 0101 0101 0101 0101 0101 0101 ................ + 315f0: 0101 0101 0101 0101 0101 0101 0101 0101 ................ + 31600: 0101 0101 0101 0101 0101 0101 0101 0101 ................ + 31610: 0101 0101 0101 0101 0101 0101 0101 0101 ................ + ... + +000316a0 : + 316a0: 31fc 0004 0000 0000 e419 0000 3200 0004 .1...........2.. + 316b0: 3228 0004 0002 0000 e6f5 0000 322c 0004 (2..........,2.. + 316c0: 327c 0004 0002 0000 e505 0000 3280 0004 |2...........2.. + 316d0: 32dc 0004 0002 0000 e5f1 0000 32e0 0004 .2...........2.. + 316e0: 3330 0004 0002 0000 e491 0000 3334 0004 03..........43.. + 316f0: 33d8 0004 0002 0000 e751 0000 33e4 0004 .3......Q....3.. + +00031700 <_HalRuartOp>: + 31700: 4a4d 0000 4add 0000 4bc9 0000 5775 0000 MJ...J...K..uW.. + 31710: 5829 0000 4855 0000 4281 0000 53b1 0000 )X..UH...B...S.. + 31720: 4d09 0000 4e35 0000 4f89 0000 429d 0000 .M..5N...O...B.. + 31730: 5599 0000 504d 0000 51ad 0000 52cd 0000 .U..MP...Q...R.. + 31740: 43e1 0000 442d 0000 42e1 0000 4681 0000 .C..-D...B...F.. + 31750: 42bd 0000 49d1 0000 4985 0000 4845 0000 .B...I...I..EH.. + +00031760 <_HalGdmaOp>: + 31760: 5df1 0000 5e91 0000 5ebd 0000 60dd 0000 .]...^...^...`.. + 31770: 5e6d 0000 5e51 0000 5e0d 0000 6419 0000 m^..Q^...^...d.. + 31780: 64a1 0000 6501 0000 .d...e.. + +00031788 : + 31788: 0000 0100 0000 0200 0000 0400 0000 0800 ................ + 31798: 0000 1000 0000 2000 0000 4000 0000 8000 ....... ...@.... + 317a8: 0000 1b00 0000 3600 .......6 + +000317b0 : + 317b0: 0063 0000 007c 0000 0077 0000 007b 0000 c...|...w...{... + 317c0: 00f2 0000 006b 0000 006f 0000 00c5 0000 ....k...o....... + 317d0: 0030 0000 0001 0000 0067 0000 002b 0000 0.......g...+... + 317e0: 00fe 0000 00d7 0000 00ab 0000 0076 0000 ............v... + 317f0: 00ca 0000 0082 0000 00c9 0000 007d 0000 ............}... + 31800: 00fa 0000 0059 0000 0047 0000 00f0 0000 ....Y...G....... + 31810: 00ad 0000 00d4 0000 00a2 0000 00af 0000 ................ + 31820: 009c 0000 00a4 0000 0072 0000 00c0 0000 ........r....... + 31830: 00b7 0000 00fd 0000 0093 0000 0026 0000 ............&... + 31840: 0036 0000 003f 0000 00f7 0000 00cc 0000 6...?........... + 31850: 0034 0000 00a5 0000 00e5 0000 00f1 0000 4............... + 31860: 0071 0000 00d8 0000 0031 0000 0015 0000 q.......1....... + 31870: 0004 0000 00c7 0000 0023 0000 00c3 0000 ........#....... + 31880: 0018 0000 0096 0000 0005 0000 009a 0000 ................ + 31890: 0007 0000 0012 0000 0080 0000 00e2 0000 ................ + 318a0: 00eb 0000 0027 0000 00b2 0000 0075 0000 ....'.......u... + 318b0: 0009 0000 0083 0000 002c 0000 001a 0000 ........,....... + 318c0: 001b 0000 006e 0000 005a 0000 00a0 0000 ....n...Z....... + 318d0: 0052 0000 003b 0000 00d6 0000 00b3 0000 R...;........... + 318e0: 0029 0000 00e3 0000 002f 0000 0084 0000 )......./....... + 318f0: 0053 0000 00d1 0000 0000 0000 00ed 0000 S............... + 31900: 0020 0000 00fc 0000 00b1 0000 005b 0000 ...........[... + 31910: 006a 0000 00cb 0000 00be 0000 0039 0000 j...........9... + 31920: 004a 0000 004c 0000 0058 0000 00cf 0000 J...L...X....... + 31930: 00d0 0000 00ef 0000 00aa 0000 00fb 0000 ................ + 31940: 0043 0000 004d 0000 0033 0000 0085 0000 C...M...3....... + 31950: 0045 0000 00f9 0000 0002 0000 007f 0000 E............... + 31960: 0050 0000 003c 0000 009f 0000 00a8 0000 P...<........... + 31970: 0051 0000 00a3 0000 0040 0000 008f 0000 Q.......@....... + 31980: 0092 0000 009d 0000 0038 0000 00f5 0000 ........8....... + 31990: 00bc 0000 00b6 0000 00da 0000 0021 0000 ............!... + 319a0: 0010 0000 00ff 0000 00f3 0000 00d2 0000 ................ + 319b0: 00cd 0000 000c 0000 0013 0000 00ec 0000 ................ + 319c0: 005f 0000 0097 0000 0044 0000 0017 0000 _.......D....... + 319d0: 00c4 0000 00a7 0000 007e 0000 003d 0000 ........~...=... + 319e0: 0064 0000 005d 0000 0019 0000 0073 0000 d...].......s... + 319f0: 0060 0000 0081 0000 004f 0000 00dc 0000 `.......O....... + 31a00: 0022 0000 002a 0000 0090 0000 0088 0000 "...*........... + 31a10: 0046 0000 00ee 0000 00b8 0000 0014 0000 F............... + 31a20: 00de 0000 005e 0000 000b 0000 00db 0000 ....^........... + 31a30: 00e0 0000 0032 0000 003a 0000 000a 0000 ....2...:....... + 31a40: 0049 0000 0006 0000 0024 0000 005c 0000 I.......$...\... + 31a50: 00c2 0000 00d3 0000 00ac 0000 0062 0000 ............b... + 31a60: 0091 0000 0095 0000 00e4 0000 0079 0000 ............y... + 31a70: 00e7 0000 00c8 0000 0037 0000 006d 0000 ........7...m... + 31a80: 008d 0000 00d5 0000 004e 0000 00a9 0000 ........N....... + 31a90: 006c 0000 0056 0000 00f4 0000 00ea 0000 l...V........... + 31aa0: 0065 0000 007a 0000 00ae 0000 0008 0000 e...z........... + 31ab0: 00ba 0000 0078 0000 0025 0000 002e 0000 ....x...%....... + 31ac0: 001c 0000 00a6 0000 00b4 0000 00c6 0000 ................ + 31ad0: 00e8 0000 00dd 0000 0074 0000 001f 0000 ........t....... + 31ae0: 004b 0000 00bd 0000 008b 0000 008a 0000 K............... + 31af0: 0070 0000 003e 0000 00b5 0000 0066 0000 p...>.......f... + 31b00: 0048 0000 0003 0000 00f6 0000 000e 0000 H............... + 31b10: 0061 0000 0035 0000 0057 0000 00b9 0000 a...5...W....... + 31b20: 0086 0000 00c1 0000 001d 0000 009e 0000 ................ + 31b30: 00e1 0000 00f8 0000 0098 0000 0011 0000 ................ + 31b40: 0069 0000 00d9 0000 008e 0000 0094 0000 i............... + 31b50: 009b 0000 001e 0000 0087 0000 00e9 0000 ................ + 31b60: 00ce 0000 0055 0000 0028 0000 00df 0000 ....U...(....... + 31b70: 008c 0000 00a1 0000 0089 0000 000d 0000 ................ + 31b80: 00bf 0000 00e6 0000 0042 0000 0068 0000 ........B...h... + 31b90: 0041 0000 0099 0000 002d 0000 000f 0000 A.......-....... + 31ba0: 00b0 0000 0054 0000 00bb 0000 0016 0000 ....T........... + +00031bb0 : + 31bb0: 0000 0000 0b0e 090d 161c 121a 1d12 1b17 ................ + 31bc0: 2c38 2434 2736 2d39 3a24 362e 312a 3f23 8,4$6'9-$:.6*1#? + 31bd0: 5870 4868 537e 4165 4e6c 5a72 4562 537f pXhH~SeAlNrZbE.S + 31be0: 7448 6c5c 7f46 6551 6254 7e46 695a 774b Ht\lF.QeTbF~ZiKw + 31bf0: b0e0 90d0 bbee 99dd a6fc 82ca adf2 8bc7 ................ + 31c00: 9cd8 b4e4 97d6 bde9 8ac4 a6fe 81ca aff3 ................ + 31c10: e890 d8b8 e39e d1b5 fe8c caa2 f582 c3af ................ + 31c20: c4a8 fc8c cfa6 f581 d2b4 ee96 d9ba e79b ................ + 31c30: 7bdb 3bbb 70d5 32b6 6dc7 29a1 66c9 20ac .{.;.p.2.m.).f. + 31c40: 57e3 1f8f 5ced 1682 41ff 0d95 4af1 0498 .W...\...A...J.. + 31c50: 23ab 73d3 28a5 7ade 35b7 61c9 3eb9 68c4 .#.s.(.z.5.a.>.h + 31c60: 0f93 57e7 049d 5eea 198f 45fd 1281 4cf0 ...W...^...E...L + 31c70: cb3b ab6b c035 a266 dd27 b971 d629 b07c ;.k.5.f.'.q.).|. + 31c80: e703 8f5f ec0d 8652 f11f 9d45 fa11 9448 .._...R...E...H. + 31c90: 934b e303 9845 ea0e 8557 f119 8e59 f814 K...E...W...Y... + 31ca0: bf73 c737 b47d ce3a a96f d52d a261 dc20 s.7.}.:.o.-.a. . + 31cb0: f6ad 766d fda3 7f60 e0b1 6477 ebbf 6d7a ..mv..`...wd..zm + 31cc0: da95 5259 d19b 5b54 cc89 4043 c787 494e ..YR..T[..C@..NI + 31cd0: aedd 3e05 a5d3 3708 b8c1 2c1f b3cf 2512 ...>...7...,...% + 31ce0: 82e5 1a31 89eb 133c 94f9 082b 9ff7 0126 ..1...<...+...&. + 31cf0: 464d e6bd 4d43 efb0 5051 f4a7 5b5f fdaa MF..CM..QP.._[.. + 31d00: 6a75 c289 617b cb84 7c69 d093 7767 d99e uj..{a..i|..gw.. + 31d10: 1e3d aed5 1533 a7d8 0821 bccf 032f b5c2 =...3...!.../... + 31d20: 3205 8ae1 390b 83ec 2419 98fb 2f17 91f6 .2...9...$.../.. + 31d30: 8d76 4dd6 8678 44db 9b6a 5fcc 9064 56c1 v..Mx..Dj.._d..V + 31d40: a14e 69e2 aa40 60ef b752 7bf8 bc5c 72f5 N..i@..`R..{\..r + 31d50: d506 05be de08 0cb3 c31a 17a4 c814 1ea9 ................ + 31d60: f93e 218a f230 2887 ef22 3390 e42c 3a9d >..!0..("..3,..: + 31d70: 3d96 dd06 3698 d40b 2b8a cf1c 2084 c611 .=...6...+... .. + 31d80: 11ae f932 1aa0 f03f 07b2 eb28 0cbc e225 ..2...?...(...%. + 31d90: 65e6 956e 6ee8 9c63 73fa 8774 78f4 8e79 .en..nc..st..xy. + 31da0: 49de b15a 42d0 b857 5fc2 a340 54cc aa4d .IZ..BW.._@..TM. + 31db0: f741 ecda fc4f e5d7 e15d fec0 ea53 f7cd A...O...]...S... + 31dc0: db79 c8ee d077 c1e3 cd65 daf4 c66b d3f9 y...w...e...k... + 31dd0: af31 a4b2 a43f adbf b92d b6a8 b223 bfa5 1...?...-...#... + 31de0: 8309 8086 8807 898b 9515 929c 9e1b 9b91 ................ + 31df0: 47a1 7c0a 4caf 7507 51bd 6e10 5ab3 671d .G.|.L.u.Q.n.Z.g + 31e00: 6b99 583e 6097 5133 7d85 4a24 768b 4329 .k>X.`3Q.}$J.v)C + 31e10: 1fd1 3462 14df 3d6f 09cd 2678 02c3 2f75 ..b4..o=..x&..u/ + 31e20: 33e9 1056 38e7 195b 25f5 024c 2efb 0b41 .3V..8[..%L...A. + 31e30: 8c9a d761 8794 de6c 9a86 c57b 9188 cc76 ..a...l...{...v. + 31e40: a0a2 f355 abac fa58 b6be e14f bdb0 e842 ..U...X...O...B. + 31e50: d4ea 9f09 dfe4 9604 c2f6 8d13 c9f8 841e ................ + 31e60: f8d2 bb3d f3dc b230 eece a927 e5c0 a02a ..=...0...'...*. + 31e70: 3c7a 47b1 3774 4ebc 2a66 55ab 2168 5ca6 z<.Gt7.Nf*.Uh!.\ + 31e80: 1042 6385 1b4c 6a88 065e 719f 0d50 7892 B..cL..j^..qP..x + 31e90: 640a 0fd9 6f04 06d4 7216 1dc3 7918 14ce .d...o...r...y.. + 31ea0: 4832 2bed 433c 22e0 5e2e 39f7 5520 30fa 2H.+: + 31fb0: 0000 0000 0d0b 0e09 1a16 1c12 171d 121b ................ + 31fc0: 342c 3824 3927 362d 2e3a 2436 2331 2a3f ,4$8'9-6:.6$1#?* + 31fd0: 6858 7048 6553 7e41 724e 6c5a 7f45 6253 XhHpSeA~NrZlE.Sb + 31fe0: 5c74 486c 517f 4665 4662 547e 4b69 5a77 t\lH.QeFbF~TiKwZ + 31ff0: d0b0 e090 ddbb ee99 caa6 fc82 c7ad f28b ................ + 32000: e49c d8b4 e997 d6bd fe8a c4a6 f381 caaf ................ + 32010: b8e8 90d8 b5e3 9ed1 a2fe 8cca aff5 82c3 ................ + 32020: 8cc4 a8fc 81cf a6f5 96d2 b4ee 9bd9 bae7 ................ + 32030: bb7b db3b b670 d532 a16d c729 ac66 c920 {.;.p.2.m.).f. . + 32040: 8f57 e31f 825c ed16 9541 ff0d 984a f104 W...\...A...J... + 32050: d323 ab73 de28 a57a c935 b761 c43e b968 #.s.(.z.5.a.>.h. + 32060: e70f 9357 ea04 9d5e fd19 8f45 f012 814c ..W...^...E...L. + 32070: 6bcb 3bab 66c0 35a2 71dd 27b9 7cd6 29b0 .k.;.f.5.q.'.|.) + 32080: 5fe7 038f 52ec 0d86 45f1 1f9d 48fa 1194 ._...R...E...H.. + 32090: 0393 4be3 0e98 45ea 1985 57f1 148e 59f8 ...K...E...W...Y + 320a0: 37bf 73c7 3ab4 7dce 2da9 6fd5 20a2 61dc .7.s.:.}.-.o. .a + 320b0: 6df6 ad76 60fd a37f 77e0 b164 7aeb bf6d .mv..`...wd..zm. + 320c0: 59da 9552 54d1 9b5b 43cc 8940 4ec7 8749 .YR..T[..C@..NI. + 320d0: 05ae dd3e 08a5 d337 1fb8 c12c 12b3 cf25 ..>...7...,...%. + 320e0: 3182 e51a 3c89 eb13 2b94 f908 269f f701 .1...<...+...&.. + 320f0: bd46 4de6 b04d 43ef a750 51f4 aa5b 5ffd F..MM..CP..Q[.._ + 32100: 896a 75c2 8461 7bcb 937c 69d0 9e77 67d9 j..ua..{|..iw..g + 32110: d51e 3dae d815 33a7 cf08 21bc c203 2fb5 ...=...3...!.../ + 32120: e132 058a ec39 0b83 fb24 1998 f62f 1791 2...9...$.../... + 32130: d68d 764d db86 7844 cc9b 6a5f c190 6456 ..Mv..Dx.._j..Vd + 32140: e2a1 4e69 efaa 4060 f8b7 527b f5bc 5c72 ..iN..`@..{R..r\ + 32150: bed5 0605 b3de 080c a4c3 1a17 a9c8 141e ................ + 32160: 8af9 3e21 87f2 3028 90ef 2233 9de4 2c3a ..!>..(0..3"..:, + 32170: 063d 96dd 0b36 98d4 1c2b 8acf 1120 84c6 =...6...+... ... + 32180: 3211 aef9 3f1a a0f0 2807 b2eb 250c bce2 .2...?...(...%.. + 32190: 6e65 e695 636e e89c 7473 fa87 7978 f48e en..nc..st..xy.. + 321a0: 5a49 deb1 5742 d0b8 405f c2a3 4d54 ccaa IZ..BW.._@..TM.. + 321b0: daf7 41ec d7fc 4fe5 c0e1 5dfe cdea 53f7 ...A...O...]...S + 321c0: eedb 79c8 e3d0 77c1 f4cd 65da f9c6 6bd3 ...y...w...e...k + 321d0: b2af 31a4 bfa4 3fad a8b9 2db6 a5b2 23bf ...1...?...-...# + 321e0: 8683 0980 8b88 0789 9c95 1592 919e 1b9b ................ + 321f0: 0a47 a17c 074c af75 1051 bd6e 1d5a b367 G.|.L.u.Q.n.Z.g. + 32200: 3e6b 9958 3360 9751 247d 854a 2976 8b43 k>X.`3Q.}$J.v)C. + 32210: 621f d134 6f14 df3d 7809 cd26 7502 c32f .b4..o=..x&..u/. + 32220: 5633 e910 5b38 e719 4c25 f502 412e fb0b 3V..8[..%L...A.. + 32230: 618c 9ad7 6c87 94de 7b9a 86c5 7691 88cc .a...l...{...v.. + 32240: 55a0 a2f3 58ab acfa 4fb6 bee1 42bd b0e8 .U...X...O...B.. + 32250: 09d4 ea9f 04df e496 13c2 f68d 1ec9 f884 ................ + 32260: 3df8 d2bb 30f3 dcb2 27ee cea9 2ae5 c0a0 .=...0...'...*.. + 32270: b13c 7a47 bc37 744e ab2a 6655 a621 685c <.Gz7.Nt*.Uf!.\h + 32280: 8510 4263 881b 4c6a 9f06 5e71 920d 5078 ..cB..jL..q^..xP + 32290: d964 0a0f d46f 0406 c372 161d ce79 1814 d...o...r...y... + 322a0: ed48 322b e043 3c22 f75e 2e39 fa55 2030 H.+2C."<^.9.U.0 + 322b0: b701 ec9a ba0a e293 ad17 f088 a01c fe81 ................ + 322c0: 832d d4be 8e26 dab7 993b c8ac 9430 c6a5 -...&...;...0... + 322d0: df59 9cd2 d252 92db c54f 80c0 c844 8ec9 Y...R...O...D... + 322e0: eb75 a4f6 e67e aaff f163 b8e4 fc68 b6ed u...~...c...h... + 322f0: 67b1 0c0a 6aba 0203 7da7 1018 70ac 1e11 .g...j...}...p.. + 32300: 539d 342e 5e96 3a27 498b 283c 4480 2635 .S.4.^':.I<(.D5& + 32310: 0fe9 7c42 02e2 724b 15ff 6050 18f4 6e59 ..B|..Kr..P`..Yn + 32320: 3bc5 4466 36ce 4a6f 21d3 5874 2cd8 567d .;fD.6oJ.!tX.,}V + 32330: 0c7a 37a1 0171 39a8 166c 2bb3 1b67 25ba z..7q..9l..+g..% + 32340: 3856 0f85 355d 018c 2240 1397 2f4b 1d9e V8..]5..@"..K/.. + 32350: 6422 47e9 6929 49e0 7e34 5bfb 733f 55f2 "d.G)i.I4~.[?s.U + 32360: 500e 7fcd 5d05 71c4 4a18 63df 4713 6dd6 .P...].q.J.c.G.m + 32370: dcca d731 d1c1 d938 c6dc cb23 cbd7 c52a ..1...8...#...*. + 32380: e8e6 ef15 e5ed e11c f2f0 f307 fffb fd0e ................ + 32390: b492 a779 b999 a970 ae84 bb6b a38f b562 ..y...p...k...b. + 323a0: 80be 9f5d 8db5 9154 9aa8 834f 97a3 8d46 ..]...T...O...F. + +000323b0 : + 323b0: 0000 0000 090d 0b0e 121a 161c 1b17 1d12 ................ + 323c0: 2434 2c38 2d39 2736 362e 3a24 3f23 312a 4$8,9-6'.6$:#?*1 + 323d0: 4868 5870 4165 537e 5a72 4e6c 537f 4562 hHpXeA~SrZlN.SbE + 323e0: 6c5c 7448 6551 7f46 7e46 6254 774b 695a \lHtQeF.F~TbKwZi + 323f0: 90d0 b0e0 99dd bbee 82ca a6fc 8bc7 adf2 ................ + 32400: b4e4 9cd8 bde9 97d6 a6fe 8ac4 aff3 81ca ................ + 32410: d8b8 e890 d1b5 e39e caa2 fe8c c3af f582 ................ + 32420: fc8c c4a8 f581 cfa6 ee96 d2b4 e79b d9ba ................ + 32430: 3bbb 7bdb 32b6 70d5 29a1 6dc7 20ac 66c9 .;.{.2.p.).m. .f + 32440: 1f8f 57e3 1682 5ced 0d95 41ff 0498 4af1 ...W...\...A...J + 32450: 73d3 23ab 7ade 28a5 61c9 35b7 68c4 3eb9 .s.#.z.(.a.5.h.> + 32460: 57e7 0f93 5eea 049d 45fd 198f 4cf0 1281 .W...^...E...L.. + 32470: ab6b cb3b a266 c035 b971 dd27 b07c d629 k.;.f.5.q.'.|.). + 32480: 8f5f e703 8652 ec0d 9d45 f11f 9448 fa11 _...R...E...H... + 32490: e303 934b ea0e 9845 f119 8557 f814 8e59 ..K...E...W...Y. + 324a0: c737 bf73 ce3a b47d d52d a96f dc20 a261 7.s.:.}.-.o. .a. + 324b0: 766d f6ad 7f60 fda3 6477 e0b1 6d7a ebbf mv..`...wd..zm.. + 324c0: 5259 da95 5b54 d19b 4043 cc89 494e c787 YR..T[..C@..NI.. + 324d0: 3e05 aedd 3708 a5d3 2c1f b8c1 2512 b3cf .>...7...,...%.. + 324e0: 1a31 82e5 133c 89eb 082b 94f9 0126 9ff7 1...<...+...&... + 324f0: e6bd 464d efb0 4d43 f4a7 5051 fdaa 5b5f ..MF..CM..QP.._[ + 32500: c289 6a75 cb84 617b d093 7c69 d99e 7767 ..uj..{a..i|..gw + 32510: aed5 1e3d a7d8 1533 bccf 0821 b5c2 032f ..=...3...!.../. + 32520: 8ae1 3205 83ec 390b 98fb 2419 91f6 2f17 ...2...9...$.../ + 32530: 4dd6 8d76 44db 8678 5fcc 9b6a 56c1 9064 .Mv..Dx.._j..Vd. + 32540: 69e2 a14e 60ef aa40 7bf8 b752 72f5 bc5c .iN..`@..{R..r\. + 32550: 05be d506 0cb3 de08 17a4 c31a 1ea9 c814 ................ + 32560: 218a f93e 2887 f230 3390 ef22 3a9d e42c .!>..(0..3"..:,. + 32570: dd06 3d96 d40b 3698 cf1c 2b8a c611 2084 ...=...6...+... + 32580: f932 11ae f03f 1aa0 eb28 07b2 e225 0cbc 2...?...(...%... + 32590: 956e 65e6 9c63 6ee8 8774 73fa 8e79 78f4 n..ec..nt..sy..x + 325a0: b15a 49de b857 42d0 a340 5fc2 aa4d 54cc Z..IW..B@.._M..T + 325b0: ecda f741 e5d7 fc4f fec0 e15d f7cd ea53 ..A...O...]...S. + 325c0: c8ee db79 c1e3 d077 daf4 cd65 d3f9 c66b ..y...w...e...k. + 325d0: a4b2 af31 adbf a43f b6a8 b92d bfa5 b223 ..1...?...-...#. + 325e0: 8086 8309 898b 8807 929c 9515 9b91 9e1b ................ + 325f0: 7c0a 47a1 7507 4caf 6e10 51bd 671d 5ab3 .|.G.u.L.n.Q.g.Z + 32600: 583e 6b99 5133 6097 4a24 7d85 4329 768b >X.k3Q.`$J.})C.v + 32610: 3462 1fd1 3d6f 14df 2678 09cd 2f75 02c3 b4..o=..x&..u/.. + 32620: 1056 33e9 195b 38e7 024c 25f5 0b41 2efb V..3[..8L..%A... + 32630: d761 8c9a de6c 8794 c57b 9a86 cc76 9188 a...l...{...v... + 32640: f355 a0a2 fa58 abac e14f b6be e842 bdb0 U...X...O...B... + 32650: 9f09 d4ea 9604 dfe4 8d13 c2f6 841e c9f8 ................ + 32660: bb3d f8d2 b230 f3dc a927 eece a02a e5c0 =...0...'...*... + 32670: 47b1 3c7a 4ebc 3774 55ab 2a66 5ca6 2168 .Gz<.Nt7.Uf*.\h! + 32680: 6385 1042 6a88 1b4c 719f 065e 7892 0d50 .cB..jL..q^..xP. + 32690: 0fd9 640a 06d4 6f04 1dc3 7216 14ce 7918 ...d...o...r...y + 326a0: 2bed 4832 22e0 433c 39f7 5e2e 30fa 5520 .+2H.": + 327b0: 0000 0000 0e09 0d0b 1c12 1a16 121b 171d ................ + 327c0: 3824 342c 362d 3927 2436 2e3a 2a3f 2331 $8,4-6'96$:.?*1# + 327d0: 7048 6858 7e41 6553 6c5a 724e 6253 7f45 HpXhA~SeZlNrSbE. + 327e0: 486c 5c74 4665 517f 547e 4662 5a77 4b69 lHt\eF.Q~TbFwZiK + 327f0: e090 d0b0 ee99 ddbb fc82 caa6 f28b c7ad ................ + 32800: d8b4 e49c d6bd e997 c4a6 fe8a caaf f381 ................ + 32810: 90d8 b8e8 9ed1 b5e3 8cca a2fe 82c3 aff5 ................ + 32820: a8fc 8cc4 a6f5 81cf b4ee 96d2 bae7 9bd9 ................ + 32830: db3b bb7b d532 b670 c729 a16d c920 ac66 ;.{.2.p.).m. .f. + 32840: e31f 8f57 ed16 825c ff0d 9541 f104 984a ..W...\...A...J. + 32850: ab73 d323 a57a de28 b761 c935 b968 c43e s.#.z.(.a.5.h.>. + 32860: 9357 e70f 9d5e ea04 8f45 fd19 814c f012 W...^...E...L... + 32870: 3bab 6bcb 35a2 66c0 27b9 71dd 29b0 7cd6 .;.k.5.f.'.q.).| + +00032880 <.LANCHOR1>: + 32880: 5fe7038f .word 0x5fe7038f + 32884: 52ec0d86 .word 0x52ec0d86 + 32888: 45f11f9d .word 0x45f11f9d + 3288c: 48fa1194 .word 0x48fa1194 + 32890: 03934be3 .word 0x03934be3 + 32894: 0e9845ea .word 0x0e9845ea + 32898: 198557f1 .word 0x198557f1 + 3289c: 148e59f8 .word 0x148e59f8 + 328a0: 37bf73c7 .word 0x37bf73c7 + 328a4: 3ab47dce .word 0x3ab47dce + 328a8: 2da96fd5 .word 0x2da96fd5 + 328ac: 20a261dc .word 0x20a261dc + 328b0: 6df6ad76 .word 0x6df6ad76 + 328b4: 60fda37f .word 0x60fda37f + 328b8: 77e0b164 .word 0x77e0b164 + 328bc: 7aebbf6d .word 0x7aebbf6d + 328c0: 59da9552 .word 0x59da9552 + 328c4: 54d19b5b .word 0x54d19b5b + 328c8: 43cc8940 .word 0x43cc8940 + 328cc: 4ec78749 .word 0x4ec78749 + 328d0: 05aedd3e .word 0x05aedd3e + 328d4: 08a5d337 .word 0x08a5d337 + 328d8: 1fb8c12c .word 0x1fb8c12c + 328dc: 12b3cf25 .word 0x12b3cf25 + 328e0: 3182e51a .word 0x3182e51a + 328e4: 3c89eb13 .word 0x3c89eb13 + 328e8: 2b94f908 .word 0x2b94f908 + 328ec: 269ff701 .word 0x269ff701 + 328f0: bd464de6 .word 0xbd464de6 + 328f4: b04d43ef .word 0xb04d43ef + 328f8: a75051f4 .word 0xa75051f4 + 328fc: aa5b5ffd .word 0xaa5b5ffd + 32900: 896a75c2 .word 0x896a75c2 + 32904: 84617bcb .word 0x84617bcb + 32908: 937c69d0 .word 0x937c69d0 + 3290c: 9e7767d9 .word 0x9e7767d9 + 32910: d51e3dae .word 0xd51e3dae + 32914: d81533a7 .word 0xd81533a7 + 32918: cf0821bc .word 0xcf0821bc + 3291c: c2032fb5 .word 0xc2032fb5 + 32920: e132058a .word 0xe132058a + 32924: ec390b83 .word 0xec390b83 + 32928: fb241998 .word 0xfb241998 + 3292c: f62f1791 .word 0xf62f1791 + 32930: d68d764d .word 0xd68d764d + 32934: db867844 .word 0xdb867844 + 32938: cc9b6a5f .word 0xcc9b6a5f + 3293c: c1906456 .word 0xc1906456 + 32940: e2a14e69 .word 0xe2a14e69 + 32944: efaa4060 .word 0xefaa4060 + 32948: f8b7527b .word 0xf8b7527b + 3294c: f5bc5c72 .word 0xf5bc5c72 + 32950: bed50605 .word 0xbed50605 + 32954: b3de080c .word 0xb3de080c + 32958: a4c31a17 .word 0xa4c31a17 + 3295c: a9c8141e .word 0xa9c8141e + 32960: 8af93e21 .word 0x8af93e21 + 32964: 87f23028 .word 0x87f23028 + 32968: 90ef2233 .word 0x90ef2233 + 3296c: 9de42c3a .word 0x9de42c3a + 32970: 063d96dd .word 0x063d96dd + 32974: 0b3698d4 .word 0x0b3698d4 + 32978: 1c2b8acf .word 0x1c2b8acf + 3297c: 112084c6 .word 0x112084c6 + 32980: 3211aef9 .word 0x3211aef9 + 32984: 3f1aa0f0 .word 0x3f1aa0f0 + 32988: 2807b2eb .word 0x2807b2eb + 3298c: 250cbce2 .word 0x250cbce2 + 32990: 6e65e695 .word 0x6e65e695 + 32994: 636ee89c .word 0x636ee89c + 32998: 7473fa87 .word 0x7473fa87 + 3299c: 7978f48e .word 0x7978f48e + 329a0: 5a49deb1 .word 0x5a49deb1 + 329a4: 5742d0b8 .word 0x5742d0b8 + 329a8: 405fc2a3 .word 0x405fc2a3 + 329ac: 4d54ccaa .word 0x4d54ccaa + 329b0: daf741ec .word 0xdaf741ec + 329b4: d7fc4fe5 .word 0xd7fc4fe5 + 329b8: c0e15dfe .word 0xc0e15dfe + 329bc: cdea53f7 .word 0xcdea53f7 + 329c0: eedb79c8 .word 0xeedb79c8 + 329c4: e3d077c1 .word 0xe3d077c1 + 329c8: f4cd65da .word 0xf4cd65da + 329cc: f9c66bd3 .word 0xf9c66bd3 + 329d0: b2af31a4 .word 0xb2af31a4 + 329d4: bfa43fad .word 0xbfa43fad + 329d8: a8b92db6 .word 0xa8b92db6 + 329dc: a5b223bf .word 0xa5b223bf + 329e0: 86830980 .word 0x86830980 + 329e4: 8b880789 .word 0x8b880789 + 329e8: 9c951592 .word 0x9c951592 + 329ec: 919e1b9b .word 0x919e1b9b + 329f0: 0a47a17c .word 0x0a47a17c + 329f4: 074caf75 .word 0x074caf75 + 329f8: 1051bd6e .word 0x1051bd6e + 329fc: 1d5ab367 .word 0x1d5ab367 + 32a00: 3e6b9958 .word 0x3e6b9958 + 32a04: 33609751 .word 0x33609751 + 32a08: 247d854a .word 0x247d854a + 32a0c: 29768b43 .word 0x29768b43 + 32a10: 621fd134 .word 0x621fd134 + 32a14: 6f14df3d .word 0x6f14df3d + 32a18: 7809cd26 .word 0x7809cd26 + 32a1c: 7502c32f .word 0x7502c32f + 32a20: 5633e910 .word 0x5633e910 + 32a24: 5b38e719 .word 0x5b38e719 + 32a28: 4c25f502 .word 0x4c25f502 + 32a2c: 412efb0b .word 0x412efb0b + 32a30: 618c9ad7 .word 0x618c9ad7 + 32a34: 6c8794de .word 0x6c8794de + 32a38: 7b9a86c5 .word 0x7b9a86c5 + 32a3c: 769188cc .word 0x769188cc + 32a40: 55a0a2f3 .word 0x55a0a2f3 + 32a44: 58abacfa .word 0x58abacfa + 32a48: 4fb6bee1 .word 0x4fb6bee1 + 32a4c: 42bdb0e8 .word 0x42bdb0e8 + 32a50: 09d4ea9f .word 0x09d4ea9f + 32a54: 04dfe496 .word 0x04dfe496 + 32a58: 13c2f68d .word 0x13c2f68d + 32a5c: 1ec9f884 .word 0x1ec9f884 + 32a60: 3df8d2bb .word 0x3df8d2bb + 32a64: 30f3dcb2 .word 0x30f3dcb2 + 32a68: 27eecea9 .word 0x27eecea9 + 32a6c: 2ae5c0a0 .word 0x2ae5c0a0 + 32a70: b13c7a47 .word 0xb13c7a47 + 32a74: bc37744e .word 0xbc37744e + 32a78: ab2a6655 .word 0xab2a6655 + 32a7c: a621685c .word 0xa621685c + 32a80: 85104263 .word 0x85104263 + 32a84: 881b4c6a .word 0x881b4c6a + 32a88: 9f065e71 .word 0x9f065e71 + 32a8c: 920d5078 .word 0x920d5078 + 32a90: d9640a0f .word 0xd9640a0f + 32a94: d46f0406 .word 0xd46f0406 + 32a98: c372161d .word 0xc372161d + 32a9c: ce791814 .word 0xce791814 + 32aa0: ed48322b .word 0xed48322b + 32aa4: e0433c22 .word 0xe0433c22 + 32aa8: f75e2e39 .word 0xf75e2e39 + 32aac: fa552030 .word 0xfa552030 + 32ab0: b701ec9a .word 0xb701ec9a + 32ab4: ba0ae293 .word 0xba0ae293 + 32ab8: ad17f088 .word 0xad17f088 + 32abc: a01cfe81 .word 0xa01cfe81 + 32ac0: 832dd4be .word 0x832dd4be + 32ac4: 8e26dab7 .word 0x8e26dab7 + 32ac8: 993bc8ac .word 0x993bc8ac + 32acc: 9430c6a5 .word 0x9430c6a5 + 32ad0: df599cd2 .word 0xdf599cd2 + 32ad4: d25292db .word 0xd25292db + 32ad8: c54f80c0 .word 0xc54f80c0 + 32adc: c8448ec9 .word 0xc8448ec9 + 32ae0: eb75a4f6 .word 0xeb75a4f6 + 32ae4: e67eaaff .word 0xe67eaaff + 32ae8: f163b8e4 .word 0xf163b8e4 + 32aec: fc68b6ed .word 0xfc68b6ed + 32af0: 67b10c0a .word 0x67b10c0a + 32af4: 6aba0203 .word 0x6aba0203 + 32af8: 7da71018 .word 0x7da71018 + 32afc: 70ac1e11 .word 0x70ac1e11 + 32b00: 539d342e .word 0x539d342e + 32b04: 5e963a27 .word 0x5e963a27 + 32b08: 498b283c .word 0x498b283c + 32b0c: 44802635 .word 0x44802635 + 32b10: 0fe97c42 .word 0x0fe97c42 + 32b14: 02e2724b .word 0x02e2724b + 32b18: 15ff6050 .word 0x15ff6050 + 32b1c: 18f46e59 .word 0x18f46e59 + 32b20: 3bc54466 .word 0x3bc54466 + 32b24: 36ce4a6f .word 0x36ce4a6f + 32b28: 21d35874 .word 0x21d35874 + 32b2c: 2cd8567d .word 0x2cd8567d + 32b30: 0c7a37a1 .word 0x0c7a37a1 + 32b34: 017139a8 .word 0x017139a8 + 32b38: 166c2bb3 .word 0x166c2bb3 + 32b3c: 1b6725ba .word 0x1b6725ba + 32b40: 38560f85 .word 0x38560f85 + 32b44: 355d018c .word 0x355d018c + 32b48: 22401397 .word 0x22401397 + 32b4c: 2f4b1d9e .word 0x2f4b1d9e + 32b50: 642247e9 .word 0x642247e9 + 32b54: 692949e0 .word 0x692949e0 + 32b58: 7e345bfb .word 0x7e345bfb + 32b5c: 733f55f2 .word 0x733f55f2 + 32b60: 500e7fcd .word 0x500e7fcd + 32b64: 5d0571c4 .word 0x5d0571c4 + 32b68: 4a1863df .word 0x4a1863df + 32b6c: 47136dd6 .word 0x47136dd6 + 32b70: dccad731 .word 0xdccad731 + 32b74: d1c1d938 .word 0xd1c1d938 + 32b78: c6dccb23 .word 0xc6dccb23 + 32b7c: cbd7c52a .word 0xcbd7c52a + 32b80: e8e6ef15 .word 0xe8e6ef15 + 32b84: e5ede11c .word 0xe5ede11c + 32b88: f2f0f307 .word 0xf2f0f307 + 32b8c: fffbfd0e .word 0xfffbfd0e + 32b90: b492a779 .word 0xb492a779 + 32b94: b999a970 .word 0xb999a970 + 32b98: ae84bb6b .word 0xae84bb6b + 32b9c: a38fb562 .word 0xa38fb562 + 32ba0: 80be9f5d .word 0x80be9f5d + 32ba4: 8db59154 .word 0x8db59154 + 32ba8: 9aa8834f .word 0x9aa8834f + 32bac: 97a38d46 .word 0x97a38d46 + +00032bb0 : + 32bb0: c66363a5 f87c7c84 ee777799 f67b7b8d .cc..||..ww..{{. + 32bc0: fff2f20d d66b6bbd de6f6fb1 91c5c554 .....kk..oo.T... + 32bd0: 60303050 02010103 ce6767a9 562b2b7d P00`.....gg.}++V + 32be0: e7fefe19 b5d7d762 4dababe6 ec76769a ....b......M.vv. + 32bf0: 8fcaca45 1f82829d 89c9c940 fa7d7d87 E.......@....}}. + 32c00: effafa15 b25959eb 8e4747c9 fbf0f00b .....YY..GG..... + 32c10: 41adadec b3d4d467 5fa2a2fd 45afafea ...Ag......_...E + 32c20: 239c9cbf 53a4a4f7 e4727296 9bc0c05b ...#...S.rr.[... + 32c30: 75b7b7c2 e1fdfd1c 3d9393ae 4c26266a ...u.......=j&&L + 32c40: 6c36365a 7e3f3f41 f5f7f702 83cccc4f Z66lA??~....O... + 32c50: 6834345c 51a5a5f4 d1e5e534 f9f1f108 \44h...Q4....... + 32c60: e2717193 abd8d873 62313153 2a15153f .qq.s...S11b?..* + 32c70: 0804040c 95c7c752 46232365 9dc3c35e ....R...e##F^... + 32c80: 30181828 379696a1 0a05050f 2f9a9ab5 (..0...7......./ + 32c90: 0e070709 24121236 1b80809b dfe2e23d ....6..$....=... + 32ca0: cdebeb26 4e272769 7fb2b2cd ea75759f &...i''N.....uu. + 32cb0: 1209091b 1d83839e 582c2c74 341a1a2e ........t,,X...4 + 32cc0: 361b1b2d dc6e6eb2 b45a5aee 5ba0a0fb -..6.nn..ZZ....[ + 32cd0: a45252f6 763b3b4d b7d6d661 7db3b3ce .RR.M;;va......} + 32ce0: 5229297b dde3e33e 5e2f2f71 13848497 {))R>...q//^.... + 32cf0: a65353f5 b9d1d168 00000000 c1eded2c .SS.h.......,... + 32d00: 40202060 e3fcfc1f 79b1b1c8 b65b5bed ` @.......y.[[. + 32d10: d46a6abe 8dcbcb46 67bebed9 7239394b .jj.F......gK99r + 32d20: 944a4ade 984c4cd4 b05858e8 85cfcf4a .JJ..LL..XX.J... + 32d30: bbd0d06b c5efef2a 4faaaae5 edfbfb16 k...*......O.... + 32d40: 864343c5 9a4d4dd7 66333355 11858594 .CC..MM.U33f.... + 32d50: 8a4545cf e9f9f910 04020206 fe7f7f81 .EE............. + 32d60: a05050f0 783c3c44 259f9fba 4ba8a8e3 .PP.D< + 32ee0: 964b4bdd 61bdbddc 0d8b8b86 0f8a8a85 .KK....a........ + 32ef0: e0707090 7c3e3e42 71b5b5c4 cc6666aa .pp.B>>|...q.ff. + 32f00: 904848d8 06030305 f7f6f601 1c0e0e12 .HH............. + 32f10: c26161a3 6a35355f ae5757f9 69b9b9d0 .aa._55j.WW....i + 32f20: 17868691 99c1c158 3a1d1d27 279e9eb9 ....X...'..:...' + 32f30: d9e1e138 ebf8f813 2b9898b3 22111133 8..........+3.." + 32f40: d26969bb a9d9d970 078e8e89 339494a7 .ii.p..........3 + 32f50: 2d9b9bb6 3c1e1e22 15878792 c9e9e920 ...-"..<.... ... + 32f60: 87cece49 aa5555ff 50282878 a5dfdf7a I....UU.x((Pz... + 32f70: 038c8c8f 59a1a1f8 09898980 1a0d0d17 .......Y........ + 32f80: 65bfbfda d7e6e631 844242c6 d06868b8 ...e1....BB..hh. + 32f90: 824141c3 299999b0 5a2d2d77 1e0f0f11 .AA....)w--Z.... + 32fa0: 7bb0b0cb a85454fc 6dbbbbd6 2c16163a ...{.TT....m:.., + +00032fb0 : + 32fb0: 6363a5c6 7c7c84f8 777799ee 7b7b8df6 ..cc..||..ww..{{ + 32fc0: f2f20dff 6b6bbdd6 6f6fb1de c5c55491 ......kk..oo.T.. + 32fd0: 30305060 01010302 6767a9ce 2b2b7d56 `P00......ggV}++ + 32fe0: fefe19e7 d7d762b5 ababe64d 76769aec .....b..M.....vv + 32ff0: caca458f 82829d1f c9c94089 7d7d87fa .E.......@....}} + 33000: fafa15ef 5959ebb2 4747c98e f0f00bfb ......YY..GG.... + 33010: adadec41 d4d467b3 a2a2fd5f afafea45 A....g.._...E... + 33020: 9c9cbf23 a4a4f753 727296e4 c0c05b9b #...S.....rr.[.. + 33030: b7b7c275 fdfd1ce1 9393ae3d 26266a4c u.......=...Lj&& + 33040: 36365a6c 3f3f417e f7f702f5 cccc4f83 lZ66~A??.....O.. + 33050: 34345c68 a5a5f451 e5e534d1 f1f108f9 h\44Q....4...... + 33060: 717193e2 d8d873ab 31315362 15153f2a ..qq.s..bS11*?.. + 33070: 04040c08 c7c75295 23236546 c3c35e9d .....R..Fe##.^.. + 33080: 18182830 9696a137 05050f0a 9a9ab52f 0(..7......./... + 33090: 0707090e 12123624 80809b1b e2e23ddf ....$6.......=.. + 330a0: ebeb26cd 2727694e b2b2cd7f 75759fea .&..Ni''......uu + 330b0: 09091b12 83839e1d 2c2c7458 1a1a2e34 ........Xt,,4... + 330c0: 1b1b2d36 6e6eb2dc 5a5aeeb4 a0a0fb5b 6-....nn..ZZ[... + 330d0: 5252f6a4 3b3b4d76 d6d661b7 b3b3ce7d ..RRvM;;.a..}... + 330e0: 29297b52 e3e33edd 2f2f715e 84849713 R{)).>..^q//.... + 330f0: 5353f5a6 d1d168b9 00000000 eded2cc1 ..SS.h.......,.. + 33100: 20206040 fcfc1fe3 b1b1c879 5b5bedb6 @` ....y.....[[ + 33110: 6a6abed4 cbcb468d bebed967 39394b72 ..jj.F..g...rK99 + 33120: 4a4ade94 4c4cd498 5858e8b0 cfcf4a85 ..JJ..LL..XX.J.. + 33130: d0d06bbb efef2ac5 aaaae54f fbfb16ed .k...*..O....... + 33140: 4343c586 4d4dd79a 33335566 85859411 ..CC..MMfU33.... + 33150: 4545cf8a f9f910e9 02020604 7f7f81fe ..EE............ + 33160: 5050f0a0 3c3c4478 9f9fba25 a8a8e34b ..PPxD<<%...K... + 33170: 5151f3a2 a3a3fe5d 4040c080 8f8f8a05 ..QQ].....@@.... + 33180: 9292ad3f 9d9dbc21 38384870 f5f504f1 ?...!...pH88.... + 33190: bcbcdf63 b6b6c177 dada75af 21216342 c...w....u..Bc!! + 331a0: 10103020 ffff1ae5 f3f30efd d2d26dbf 0...........m.. + 331b0: cdcd4c81 0c0c1418 13133526 ecec2fc3 .L......&5.../.. + 331c0: 5f5fe1be 9797a235 4444cc88 1717392e ..__5.....DD.9.. + 331d0: c4c45793 a7a7f255 7e7e82fc 3d3d477a .W..U.....~~zG== + 331e0: 6464acc8 5d5de7ba 19192b32 737395e6 ..dd..]]2+....ss + 331f0: 6060a0c0 81819819 4f4fd19e dcdc7fa3 ..``......OO.... + 33200: 22226644 2a2a7e54 9090ab3b 8888830b Df""T~**;....... + 33210: 4646ca8c eeee29c7 b8b8d36b 14143c28 ..FF.)..k...(<.. + 33220: dede79a7 5e5ee2bc 0b0b1d16 dbdb76ad .y....^^.....v.. + 33230: e0e03bdb 32325664 3a3a4e74 0a0a1e14 .;..dV22tN::.... + 33240: 4949db92 06060a0c 24246c48 5c5ce4b8 ..II....Hl$$..\\ + 33250: c2c25d9f d3d36ebd acacef43 6262a6c4 .]...n..C.....bb + 33260: 9191a839 9595a431 e4e437d3 79798bf2 9...1....7....yy + 33270: e7e732d5 c8c8438b 3737596e 6d6db7da .2...C..nY77..mm + 33280: 8d8d8c01 d5d564b1 4e4ed29c a9a9e049 .....d....NNI... + 33290: 6c6cb4d8 5656faac f4f407f3 eaea25cf ..ll..VV.....%.. + 332a0: 6565afca 7a7a8ef4 aeaee947 08081810 ..ee..zzG....... + 332b0: babad56f 787888f0 25256f4a 2e2e725c o.....xxJo%%\r.. + 332c0: 1c1c2438 a6a6f157 b4b4c773 c6c65197 8$..W...s....Q.. + 332d0: e8e823cb dddd7ca1 74749ce8 1f1f213e .#...|....tt>!.. + 332e0: 4b4bdd96 bdbddc61 8b8b860d 8a8a850f ..KKa........... + 332f0: 707090e0 3e3e427c b5b5c471 6666aacc ..pp|B>>q.....ff + 33300: 4848d890 03030506 f6f601f7 0e0e121c ..HH............ + 33310: 6161a3c2 35355f6a 5757f9ae b9b9d069 ..aaj_55..WWi... + 33320: 86869117 c1c15899 1d1d273a 9e9eb927 .....X..:'..'... + 33330: e1e138d9 f8f813eb 9898b32b 11113322 .8......+..."3.. + 33340: 6969bbd2 d9d970a9 8e8e8907 9494a733 ..ii.p......3... + 33350: 9b9bb62d 1e1e223c 87879215 e9e920c9 -...<"....... .. + 33360: cece4987 5555ffaa 28287850 dfdf7aa5 .I....UUPx((.z.. + 33370: 8c8c8f03 a1a1f859 89898009 0d0d171a ....Y........... + 33380: bfbfda65 e6e631d7 4242c684 6868b8d0 e....1....BB..hh + 33390: 4141c382 9999b029 2d2d775a 0f0f111e ..AA)...Zw--.... + 333a0: b0b0cb7b 5454fca8 bbbbd66d 16163a2c {.....TTm...,:.. + +000333b0 : + 333b0: a5c66363 84f87c7c 99ee7777 8df67b7b cc..||..ww..{{.. + 333c0: 0dfff2f2 bdd66b6b b1de6f6f 5491c5c5 ....kk..oo.....T + 333d0: 50603030 03020101 a9ce6767 7d562b2b 00`P....gg..++V} + 333e0: 19e7fefe 62b5d7d7 e64dabab 9aec7676 .......b..M.vv.. + 333f0: 458fcaca 9d1f8282 4089c9c9 87fa7d7d ...E.......@}}.. + 33400: 15effafa ebb25959 c98e4747 0bfbf0f0 ....YY..GG...... + 33410: ec41adad 67b3d4d4 fd5fa2a2 ea45afaf ..A....g.._...E. + 33420: bf239c9c f753a4a4 96e47272 5b9bc0c0 ..#...S.rr.....[ + 33430: c275b7b7 1ce1fdfd ae3d9393 6a4c2626 ..u.......=.&&Lj + 33440: 5a6c3636 417e3f3f 02f5f7f7 4f83cccc 66lZ??~A.......O + 33450: 5c683434 f451a5a5 34d1e5e5 08f9f1f1 44h\..Q....4.... + 33460: 93e27171 73abd8d8 53623131 3f2a1515 qq.....s11bS..*? + 33470: 0c080404 5295c7c7 65462323 5e9dc3c3 .......R##Fe...^ + 33480: 28301818 a1379696 0f0a0505 b52f9a9a ..0(..7......./. + 33490: 090e0707 36241212 9b1b8080 3ddfe2e2 ......$6.......= + 334a0: 26cdebeb 694e2727 cd7fb2b2 9fea7575 ...&''Ni....uu.. + 334b0: 1b120909 9e1d8383 74582c2c 2e341a1a ........,,Xt..4. + 334c0: 2d361b1b b2dc6e6e eeb45a5a fb5ba0a0 ..6-nn..ZZ....[. + 334d0: f6a45252 4d763b3b 61b7d6d6 ce7db3b3 RR..;;vM...a..}. + 334e0: 7b522929 3edde3e3 715e2f2f 97138484 ))R{...>//^q.... + 334f0: f5a65353 68b9d1d1 00000000 2cc1eded SS.....h......., + 33500: 60402020 1fe3fcfc c879b1b1 edb65b5b @`......y.[[.. + 33510: bed46a6a 468dcbcb d967bebe 4b723939 jj.....F..g.99rK + 33520: de944a4a d4984c4c e8b05858 4a85cfcf JJ..LL..XX.....J + 33530: 6bbbd0d0 2ac5efef e54faaaa 16edfbfb ...k...*..O..... + 33540: c5864343 d79a4d4d 55663333 94118585 CC..MM..33fU.... + 33550: cf8a4545 10e9f9f9 06040202 81fe7f7f EE.............. + 33560: f0a05050 44783c3c ba259f9f e34ba8a8 PP..<! + 336e0: dd964b4b dc61bdbd 860d8b8b 850f8a8a KK....a......... + 336f0: 90e07070 427c3e3e c471b5b5 aacc6666 pp..>>|B..q.ff.. + 33700: d8904848 05060303 01f7f6f6 121c0e0e HH.............. + 33710: a3c26161 5f6a3535 f9ae5757 d069b9b9 aa..55j_WW....i. + 33720: 91178686 5899c1c1 273a1d1d b9279e9e .......X..:'..'. + 33730: 38d9e1e1 13ebf8f8 b32b9898 33221111 ...8......+..."3 + 33740: bbd26969 70a9d9d9 89078e8e a7339494 ii.....p......3. + 33750: b62d9b9b 223c1e1e 92158787 20c9e9e9 ..-...<"....... + 33760: 4987cece ffaa5555 78502828 7aa5dfdf ...IUU..((Px...z + 33770: 8f038c8c f859a1a1 80098989 171a0d0d ......Y......... + 33780: da65bfbf 31d7e6e6 c6844242 b8d06868 ..e....1BB..hh.. + 33790: c3824141 b0299999 775a2d2d 111e0f0f AA....).--Zw.... + 337a0: cb7bb0b0 fca85454 d66dbbbb 3a2c1616 ..{.TT....m...,: + +000337b0 : + 337b0: 63a5c663 7c84f87c 7799ee77 7b8df67b c..c|..|w..w{..{ + 337c0: f20dfff2 6bbdd66b 6fb1de6f c55491c5 ....k..ko..o..T. + 337d0: 30506030 01030201 67a9ce67 2b7d562b 0`P0....g..g+V}+ + 337e0: fe19e7fe d762b5d7 abe64dab 769aec76 ......b..M..v..v + 337f0: ca458fca 829d1f82 c94089c9 7d87fa7d ..E.......@.}..} + 33800: fa15effa 59ebb259 47c98e47 f00bfbf0 ....Y..YG..G.... + 33810: adec41ad d467b3d4 a2fd5fa2 afea45af .A....g.._...E.. + 33820: 9cbf239c a4f753a4 7296e472 c05b9bc0 .#...S..r..r..[. + 33830: b7c275b7 fd1ce1fd 93ae3d93 266a4c26 .u.......=..&Lj& + 33840: 365a6c36 3f417e3f f702f5f7 cc4f83cc 6lZ6?~A?......O. + 33850: 345c6834 a5f451a5 e534d1e5 f108f9f1 4h\4.Q....4..... + 33860: 7193e271 d873abd8 31536231 153f2a15 q..q..s.1bS1.*?. + 33870: 040c0804 c75295c7 23654623 c35e9dc3 ......R.#Fe#..^. + 33880: 18283018 96a13796 050f0a05 9ab52f9a .0(..7......./.. + 33890: 07090e07 12362412 809b1b80 e23ddfe2 .....$6.......=. + 338a0: eb26cdeb 27694e27 b2cd7fb2 759fea75 ..&.'Ni'....u..u + 338b0: 091b1209 839e1d83 2c74582c 1a2e341a ........,Xt,.4.. + 338c0: 1b2d361b 6eb2dc6e 5aeeb45a a0fb5ba0 .6-.n..nZ..Z.[.. + 338d0: 52f6a452 3b4d763b d661b7d6 b3ce7db3 R..R;vM;..a..}.. + 338e0: 297b5229 e33edde3 2f715e2f 84971384 )R{)..>./^q/.... + 338f0: 53f5a653 d168b9d1 00000000 ed2cc1ed S..S..h.......,. + 33900: 20604020 fc1fe3fc b1c879b1 5bedb65b @` .....y..[..[ + 33910: 6abed46a cb468dcb bed967be 394b7239 j..j..F..g..9rK9 + 33920: 4ade944a 4cd4984c 58e8b058 cf4a85cf J..JL..LX..X..J. + 33930: d06bbbd0 ef2ac5ef aae54faa fb16edfb ..k...*..O...... + 33940: 43c58643 4dd79a4d 33556633 85941185 C..CM..M3fU3.... + 33950: 45cf8a45 f910e9f9 02060402 7f81fe7f E..E............ + 33960: 50f0a050 3c44783c 9fba259f a8e34ba8 P..P: + 33978: 40c08040 .word 0x40c08040 + 3397c: 8f8a058f .word 0x8f8a058f + 33980: 92ad3f92 .word 0x92ad3f92 + 33984: 9dbc219d .word 0x9dbc219d + 33988: 38487038 .word 0x38487038 + 3398c: f504f1f5 .word 0xf504f1f5 + 33990: bcdf63bc .word 0xbcdf63bc + 33994: b6c177b6 .word 0xb6c177b6 + 33998: da75afda .word 0xda75afda + 3399c: 21634221 .word 0x21634221 + 339a0: 10302010 .word 0x10302010 + 339a4: ff1ae5ff .word 0xff1ae5ff + 339a8: f30efdf3 .word 0xf30efdf3 + 339ac: d26dbfd2 .word 0xd26dbfd2 + 339b0: cd4c81cd .word 0xcd4c81cd + 339b4: 0c14180c .word 0x0c14180c + 339b8: 13352613 .word 0x13352613 + 339bc: ec2fc3ec .word 0xec2fc3ec + 339c0: 5fe1be5f .word 0x5fe1be5f + 339c4: 97a23597 .word 0x97a23597 + 339c8: 44cc8844 .word 0x44cc8844 + 339cc: 17392e17 .word 0x17392e17 + 339d0: c45793c4 .word 0xc45793c4 + 339d4: a7f255a7 .word 0xa7f255a7 + 339d8: 7e82fc7e .word 0x7e82fc7e + 339dc: 3d477a3d .word 0x3d477a3d + 339e0: 64acc864 .word 0x64acc864 + 339e4: 5de7ba5d .word 0x5de7ba5d + 339e8: 192b3219 .word 0x192b3219 + 339ec: 7395e673 .word 0x7395e673 + 339f0: 60a0c060 .word 0x60a0c060 + 339f4: 81981981 .word 0x81981981 + 339f8: 4fd19e4f .word 0x4fd19e4f + 339fc: dc7fa3dc .word 0xdc7fa3dc + 33a00: 22664422 .word 0x22664422 + 33a04: 2a7e542a .word 0x2a7e542a + 33a08: 90ab3b90 .word 0x90ab3b90 + 33a0c: 88830b88 .word 0x88830b88 + 33a10: 46ca8c46 .word 0x46ca8c46 + 33a14: ee29c7ee .word 0xee29c7ee + 33a18: b8d36bb8 .word 0xb8d36bb8 + 33a1c: 143c2814 .word 0x143c2814 + 33a20: de79a7de .word 0xde79a7de + 33a24: 5ee2bc5e .word 0x5ee2bc5e + 33a28: 0b1d160b .word 0x0b1d160b + 33a2c: db76addb .word 0xdb76addb + 33a30: e03bdbe0 .word 0xe03bdbe0 + 33a34: 32566432 .word 0x32566432 + 33a38: 3a4e743a .word 0x3a4e743a + 33a3c: 0a1e140a .word 0x0a1e140a + 33a40: 49db9249 .word 0x49db9249 + 33a44: 060a0c06 .word 0x060a0c06 + 33a48: 246c4824 .word 0x246c4824 + 33a4c: 5ce4b85c .word 0x5ce4b85c + 33a50: c25d9fc2 .word 0xc25d9fc2 + 33a54: d36ebdd3 .word 0xd36ebdd3 + 33a58: acef43ac .word 0xacef43ac + 33a5c: 62a6c462 .word 0x62a6c462 + 33a60: 91a83991 .word 0x91a83991 + 33a64: 95a43195 .word 0x95a43195 + 33a68: e437d3e4 .word 0xe437d3e4 + 33a6c: 798bf279 .word 0x798bf279 + 33a70: e732d5e7 .word 0xe732d5e7 + 33a74: c8438bc8 .word 0xc8438bc8 + 33a78: 37596e37 .word 0x37596e37 + 33a7c: 6db7da6d .word 0x6db7da6d + 33a80: 8d8c018d .word 0x8d8c018d + 33a84: d564b1d5 .word 0xd564b1d5 + 33a88: 4ed29c4e .word 0x4ed29c4e + 33a8c: a9e049a9 .word 0xa9e049a9 + 33a90: 6cb4d86c .word 0x6cb4d86c + 33a94: 56faac56 .word 0x56faac56 + 33a98: f407f3f4 .word 0xf407f3f4 + 33a9c: ea25cfea .word 0xea25cfea + 33aa0: 65afca65 .word 0x65afca65 + 33aa4: 7a8ef47a .word 0x7a8ef47a + 33aa8: aee947ae .word 0xaee947ae + 33aac: 08181008 .word 0x08181008 + 33ab0: bad56fba .word 0xbad56fba + 33ab4: 7888f078 .word 0x7888f078 + 33ab8: 256f4a25 .word 0x256f4a25 + 33abc: 2e725c2e .word 0x2e725c2e + 33ac0: 1c24381c .word 0x1c24381c + 33ac4: a6f157a6 .word 0xa6f157a6 + 33ac8: b4c773b4 .word 0xb4c773b4 + 33acc: c65197c6 .word 0xc65197c6 + 33ad0: e823cbe8 .word 0xe823cbe8 + 33ad4: dd7ca1dd .word 0xdd7ca1dd + 33ad8: 749ce874 .word 0x749ce874 + 33adc: 1f213e1f .word 0x1f213e1f + 33ae0: 4bdd964b .word 0x4bdd964b + 33ae4: bddc61bd .word 0xbddc61bd + 33ae8: 8b860d8b .word 0x8b860d8b + 33aec: 8a850f8a .word 0x8a850f8a + 33af0: 7090e070 .word 0x7090e070 + 33af4: 3e427c3e .word 0x3e427c3e + 33af8: b5c471b5 .word 0xb5c471b5 + 33afc: 66aacc66 .word 0x66aacc66 + 33b00: 48d89048 .word 0x48d89048 + 33b04: 03050603 .word 0x03050603 + 33b08: f601f7f6 .word 0xf601f7f6 + 33b0c: 0e121c0e .word 0x0e121c0e + 33b10: 61a3c261 .word 0x61a3c261 + 33b14: 355f6a35 .word 0x355f6a35 + 33b18: 57f9ae57 .word 0x57f9ae57 + 33b1c: b9d069b9 .word 0xb9d069b9 + 33b20: 86911786 .word 0x86911786 + 33b24: c15899c1 .word 0xc15899c1 + 33b28: 1d273a1d .word 0x1d273a1d + 33b2c: 9eb9279e .word 0x9eb9279e + 33b30: e138d9e1 .word 0xe138d9e1 + 33b34: f813ebf8 .word 0xf813ebf8 + 33b38: 98b32b98 .word 0x98b32b98 + 33b3c: 11332211 .word 0x11332211 + 33b40: 69bbd269 .word 0x69bbd269 + 33b44: d970a9d9 .word 0xd970a9d9 + 33b48: 8e89078e .word 0x8e89078e + 33b4c: 94a73394 .word 0x94a73394 + 33b50: 9bb62d9b .word 0x9bb62d9b + 33b54: 1e223c1e .word 0x1e223c1e + 33b58: 87921587 .word 0x87921587 + 33b5c: e920c9e9 .word 0xe920c9e9 + 33b60: ce4987ce .word 0xce4987ce + 33b64: 55ffaa55 .word 0x55ffaa55 + 33b68: 28785028 .word 0x28785028 + 33b6c: df7aa5df .word 0xdf7aa5df + 33b70: 8c8f038c .word 0x8c8f038c + 33b74: a1f859a1 .word 0xa1f859a1 + 33b78: 89800989 .word 0x89800989 + 33b7c: 0d171a0d .word 0x0d171a0d + 33b80: bfda65bf .word 0xbfda65bf + 33b84: e631d7e6 .word 0xe631d7e6 + 33b88: 42c68442 .word 0x42c68442 + 33b8c: 68b8d068 .word 0x68b8d068 + 33b90: 41c38241 .word 0x41c38241 + 33b94: 99b02999 .word 0x99b02999 + 33b98: 2d775a2d .word 0x2d775a2d + 33b9c: 0f111e0f .word 0x0f111e0f + 33ba0: b0cb7bb0 .word 0xb0cb7bb0 + 33ba4: 54fca854 .word 0x54fca854 + 33ba8: bbd66dbb .word 0xbbd66dbb + 33bac: 163a2c16 .word 0x163a2c16 + +00033bb0 : + 33bb0: 51f4a750 7e416553 1a17a4c3 3a275e96 P..QSeA~.....^': + 33bc0: 3bab6bcb 1f9d45f1 acfa58ab 4be30393 .k.;.E...X.....K + 33bd0: 2030fa55 ad766df6 88cc7691 f5024c25 U.0 .mv..v..%L.. + 33be0: 4fe5d7fc c52acbd7 26354480 b562a38f ...O..*..D5&..b. + 33bf0: deb15a49 25ba1b67 45ea0e98 5dfec0e1 IZ..g..%...E...] + 33c00: c32f7502 814cf012 8d4697a3 6bd3f9c6 .u/...L...F....k + 33c10: 038f5fe7 15929c95 bf6d7aeb 955259da ._.......zm..YR. + 33c20: d4be832d 587421d3 49e06929 8ec9c844 -....!tX)i.ID... + 33c30: 75c2896a f48e7978 99583e6b 27b971dd j..uxy..k>X..q.' + 33c40: bee14fb6 f088ad17 c920ac66 7dce3ab4 .O......f. ..:.} + 33c50: 63df4a18 e51a3182 97513360 62537f45 .J.c.1..`3Q.E.Sb + 33c60: b16477e0 bb6bae84 fe81a01c f9082b94 .wd...k......+.. + 33c70: 70486858 8f45fd19 94de6c87 527bf8b7 XhHp..E..l....{R + 33c80: ab73d323 724b02e2 e31f8f57 6655ab2a #.s...KrW...*.Uf + 33c90: b2eb2807 2fb5c203 86c57b9a d33708a5 .(...../.{....7. + 33ca0: 302887f2 23bfa5b2 02036aba ed16825c ..(0...#.j..\... + 33cb0: 8acf1c2b a779b492 f307f2f0 4e69e2a1 +.....y.......iN + 33cc0: 65daf4cd 0605bed5 d134621f c4a6fe8a ...e.....b4..... + 33cd0: 342e539d a2f355a0 058ae132 a4f6eb75 .S.4.U..2...u... + 33ce0: 0b83ec39 4060efaa 5e719f06 bd6e1051 9.....`@..q^Q.n. + 33cf0: 3e218af9 96dd063d dd3e05ae 4de6bd46 ..!>=.....>.F..M + 33d00: 91548db5 71c45d05 0406d46f 605015ff ..T..].qo.....P` + 33d10: 1998fb24 d6bde997 894043cc 67d99e77 $........C@.w..g + 33d20: b0e842bd 07898b88 e7195b38 79c8eedb .B......8[.....y + 33d30: a17c0a47 7c420fe9 f8841ec9 00000000 G.|...B|........ + 33d40: 09808683 322bed48 1e1170ac 6c5a724e ....H.+2.p..NrZl + 33d50: fd0efffb 0f853856 3daed51e 362d3927 ....V8.....='9-6 + 33d60: 0a0fd964 685ca621 9b5b54d1 24362e3a d...!.\h.T[.:.6$ + 33d70: 0c0a67b1 9357e70f b4ee96d2 1b9b919e .g....W......... + 33d80: 80c0c54f 61dc20a2 5a774b69 1c121a16 O.... .aiKwZ.... + 33d90: e293ba0a c0a02ae5 3c22e043 121b171d .....*..C."<.... + 33da0: 0e090d0b f28bc7ad 2db6a8b9 141ea9c8 ...........-.... + 33db0: 57f11985 af75074c ee99ddbb a37f60fd ...WL.u......`.. + 33dc0: f701269f 5c72f5bc 44663bc5 5bfb7e34 .&....r\.;fD4~.[ + 33dd0: 8b432976 cb23c6dc b6edfc68 b8e4f163 v)C...#.h...c... + 33de0: d731dcca 42638510 13972240 84c61120 ..1...cB@".. ... + 33df0: 854a247d d2bb3df8 aef93211 c729a16d }$J..=...2..m.). + 33e00: 1d9e2f4b dcb230f3 0d8652ec 77c1e3d0 K/...0...R.....w + 33e10: 2bb3166c a970b999 119448fa 47e96422 l..+..p..H.."d.G + 33e20: a8fc8cc4 a0f03f1a 567d2cd8 223390ef .....?...,}V..3" + 33e30: 87494ec7 d938d1c1 8ccaa2fe 98d40b36 .NI...8.....6... + 33e40: a6f581cf a57ade28 dab78e26 3fadbfa4 ....(.z.&......? + 33e50: 2c3a9de4 5078920d 6a5fcc9b 547e4662 ..:,..xP.._jbF~T + 33e60: f68d13c2 90d8b8e8 2e39f75e 82c3aff5 ........^.9..... + 33e70: 9f5d80be 69d0937c 6fd52da9 cf2512b3 ..].|..i.-.o..%. + 33e80: c8ac993b 10187da7 e89c636e db3bbb7b ;....}..nc..{.;. + 33e90: cd267809 6e5918f4 ec9ab701 834f9aa8 .x&...Yn......O. + 33ea0: e6956e65 aaffe67e 21bccf08 ef15e8e6 en..~......!.... + 33eb0: bae79bd9 4a6f36ce ea9f09d4 29b07cd6 .....6oJ.....|.) + 33ec0: 31a4b2af 2a3f2331 c6a59430 35a266c0 ...11#?*0....f.5 + 33ed0: 744ebc37 fc82caa6 e090d0b0 33a7d815 7.Nt...........3 + 33ee0: f104984a 41ecdaf7 7fcd500e 1791f62f J......A.P../... + 33ef0: 764dd68d 43efb04d ccaa4d54 e49604df ..MvM..CTM...... + 33f00: 9ed1b5e3 4c6a881b c12c1fb8 4665517f ......jL..,..QeF + 33f10: 9d5eea04 018c355d fa877473 fb0b412e ..^.]5..st...A.. + 33f20: b3671d5a 92dbd252 e9105633 6dd64713 Z.g.R...3V...G.m + 33f30: 9ad7618c 37a10c7a 59f8148e eb133c89 .a..z..7...Y.<.. + 33f40: cea927ee b761c935 e11ce5ed 7a47b13c .'..5.a.....<.Gz + 33f50: 9cd2df59 55f2733f 1814ce79 73c737bf Y...?s.Uy....7.s + 33f60: 53f7cdea 5ffdaa5b df3d6f14 7844db86 ...S[.._.o=...Dx + 33f70: caaff381 b968c43e 3824342c c2a3405f ....>.h.,4$8_@.. + 33f80: 161dc372 bce2250c 283c498b ff0d9541 r....%...I<(A... + 33f90: 39a80171 080cb3de d8b4e49c 6456c190 q..9..........Vd + 33fa0: 7bcb8461 d532b670 486c5c74 d0b85742 a..{p.2.t\lHBW.. + +00033fb0 : + 33fb0: f4a75051 4165537e 17a4c31a 275e963a QP..~SeA....:.^' + 33fc0: ab6bcb3b 9d45f11f fa58abac e303934b ;.k...E...X.K... + 33fd0: 30fa5520 766df6ad cc769188 024c25f5 U.0..mv..v..%L. + 33fe0: e5d7fc4f 2acbd7c5 35448026 62a38fb5 O......*&.D5...b + 33ff0: b15a49de ba1b6725 ea0e9845 fec0e15d .IZ.%g..E...]... + 34000: 2f7502c3 4cf01281 4697a38d d3f9c66b ..u/...L...Fk... + 34010: 8f5fe703 929c9515 6d7aebbf 5259da95 .._.......zm..YR + 34020: be832dd4 7421d358 e0692949 c9c8448e .-..X.!tI)i..D.. + 34030: c2896a75 8e7978f4 583e6b99 b971dd27 uj...xy..k>X'.q. + 34040: e14fb6be 88ad17f0 20ac66c9 ce3ab47d ..O......f. }.:. + 34050: df4a1863 1a3182e5 51336097 537f4562 c.J...1..`3QbE.S + 34060: 6477e0b1 6bae84bb 81a01cfe 082b94f9 ..wd...k......+. + 34070: 48685870 45fd198f de6c8794 7bf8b752 pXhH...E..l.R..{ + 34080: 73d323ab 4b02e272 1f8f57e3 55ab2a66 .#.sr..K.W..f*.U + 34090: eb2807b2 b5c2032f c57b9a86 3708a5d3 ..(./.....{....7 + 340a0: 2887f230 bfa5b223 036aba02 16825ced 0..(#.....j..\.. + 340b0: cf1c2b8a 79b492a7 07f2f0f3 69e2a14e .+.....y....N..i + 340c0: daf4cd65 05bed506 34621fd1 a6fe8ac4 e.........b4.... + 340d0: 2e539d34 f355a0a2 8ae13205 f6eb75a4 4.S...U..2...u.. + 340e0: 83ec390b 60efaa40 719f065e 6e1051bd .9..@..`^..q.Q.n + 340f0: 218af93e dd063d96 3e05aedd e6bd464d >..!.=.....>MF.. + 34100: 548db591 c45d0571 06d46f04 5015ff60 ...Tq.]..o..`..P + 34110: 98fb2419 bde997d6 4043cc89 d99e7767 .$........C@gw.. + 34120: e842bdb0 898b8807 195b38e7 c8eedb79 ..B......8[.y... + 34130: 7c0a47a1 420fe97c 841ec9f8 00000000 .G.||..B........ + 34140: 80868309 2bed4832 1170ac1e 5a724e6c ....2H.+..p.lNrZ + 34150: 0efffbfd 8538560f aed51e3d 2d392736 .....V8.=...6'9- + 34160: 0fd9640a 5ca62168 5b54d19b 362e3a24 .d..h!.\..T[$:.6 + 34170: 0a67b10c 57e70f93 ee96d2b4 9b919e1b ..g....W........ + 34180: c0c54f80 dc20a261 774b695a 121a161c .O..a. .ZiKw.... + 34190: 93ba0ae2 a02ae5c0 22e0433c 1b171d12 ......*..h8,4$._@. + 34380: 1dc37216 e2250cbc 3c498b28 0d9541ff .r....%.(.I<.A.. + 34390: a8017139 0cb3de08 b4e49cd8 56c19064 9q..........d..V + 343a0: cb84617b 32b670d5 6c5c7448 b85742d0 {a...p.2Ht\l.BW. + +000343b0 : + 343b0: 5051f4a7 537e4165 c31a17a4 963a275e ..QPeA~S....^':. + 343c0: cb3bab6b f11f9d45 abacfa58 934be303 k.;.E...X.....K. + 343d0: 552030fa f6ad766d 9188cc76 25f5024c .0 Umv..v...L..% + 343e0: fc4fe5d7 d7c52acb 80263544 8fb562a3 ..O..*..D5&..b.. + 343f0: 49deb15a 6725ba1b 9845ea0e e15dfec0 Z..I..%g..E...]. + 34400: 02c32f75 12814cf0 a38d4697 c66bd3f9 u/...L...F....k. + 34410: e7038f5f 9515929c ebbf6d7a da955259 _.......zm..YR.. + 34420: 2dd4be83 d3587421 2949e069 448ec9c8 ...-!tX.i.I)...D + 34430: 6a75c289 78f48e79 6b99583e dd27b971 ..ujy..x>X.kq.'. + 34440: b6bee14f 17f088ad 66c920ac b47dce3a O........ .f:.}. + 34450: 1863df4a 82e51a31 60975133 4562537f J.c.1...3Q.`.SbE + 34460: e0b16477 84bb6bae 1cfe81a0 94f9082b wd...k......+... + 34470: 58704868 198f45fd 8794de6c b7527bf8 hHpX.E..l....{R. + 34480: 23ab73d3 e2724b02 57e31f8f 2a6655ab .s.#.Kr....W.Uf* + 34490: 07b2eb28 032fb5c2 9a86c57b a5d33708 (...../.{....7.. + 344a0: f2302887 b223bfa5 ba02036a 5ced1682 .(0...#.j......\ + 344b0: 2b8acf1c 92a779b4 f0f307f2 a14e69e2 ...+.y.......iN. + 344c0: cd65daf4 d50605be 1fd13462 8ac4a6fe ..e.....b4...... + 344d0: 9d342e53 a0a2f355 32058ae1 75a4f6eb S.4.U......2...u + 344e0: 390b83ec aa4060ef 065e719f 51bd6e10 ...9.`@..q^..n.Q + 344f0: f93e218a 3d96dd06 aedd3e05 464de6bd .!>....=.>....MF + 34500: b591548d 0571c45d 6f0406d4 ff605015 .T..].q....o.P`. + 34510: 241998fb 97d6bde9 cc894043 7767d99e ...$....C@....gw + 34520: bdb0e842 8807898b 38e7195b db79c8ee B.......[..8..y. + 34530: 47a17c0a e97c420f c9f8841e 00000000 .|.G.B|......... + 34540: 83098086 48322bed ac1e1170 4e6c5a72 .....+2Hp...rZlN + 34550: fbfd0eff 560f8538 1e3daed5 27362d39 ....8..V..=.9-6' + 34560: 640a0fd9 21685ca6 d19b5b54 3a24362e ...d.\h!T[...6$: + 34570: b10c0a67 0f9357e7 d2b4ee96 9e1b9b91 g....W.......... + 34580: 4f80c0c5 a261dc20 695a774b 161c121a ...O .a.KwZi.... + 34590: 0ae293ba e5c0a02a 433c22e0 1d121b17 ....*...."4$8,@.._ + 34780: 72161dc3 0cbce225 8b283c49 41ff0d95 ...r%...I<(....A + 34790: 7139a801 de080cb3 9cd8b4e4 906456c1 ..9q.........Vd. + 347a0: 617bcb84 70d532b6 74486c5c 42d0b857 ..{a.2.p\lHtW..B + +000347b0 : + 347b0: a75051f4 65537e41 a4c31a17 5e963a27 .QP.A~Se....':.^ + 347c0: 6bcb3bab 45f11f9d 58abacfa 03934be3 .;.k...E...X.K.. + 347d0: fa552030 6df6ad76 769188cc 4c25f502 0 U.v..m...v..%L + 347e0: d7fc4fe5 cbd7c52a 44802635 a38fb562 .O..*...5&.Db... + 347f0: 5a49deb1 1b6725ba 0e9845ea c0e15dfe ..IZ.%g..E...].. + 34800: 7502c32f f012814c 97a38d46 f9c66bd3 /..uL...F....k.. + 34810: 5fe7038f 9c951592 7aebbf6d 59da9552 ..._....m..zR..Y + 34820: 832dd4be 21d35874 692949e0 c8448ec9 ..-.tX.!.I)i..D. + 34830: 896a75c2 7978f48e 3e6b9958 71dd27b9 .uj...xyX.k>.'.q + 34840: 4fb6bee1 ad17f088 ac66c920 3ab47dce ...O.... .f..}.: + 34850: 4a1863df 3182e51a 33609751 7f456253 .c.J...1Q.`3SbE. + 34860: 77e0b164 ae84bb6b a01cfe81 2b94f908 d..wk..........+ + 34870: 68587048 fd198f45 6c8794de f8b7527b HpXhE......l{R.. + 34880: d323ab73 02e2724b 8f57e31f ab2a6655 s.#.Kr....W.Uf*. + 34890: 2807b2eb c2032fb5 7b9a86c5 08a5d337 ...(./.....{7... + 348a0: 87f23028 a5b223bf 6aba0203 825ced16 (0...#.....j..\. + 348b0: 1c2b8acf b492a779 f2f0f307 e2a14e69 ..+.y.......iN.. + 348c0: f4cd65da bed50605 621fd134 fe8ac4a6 .e......4..b.... + 348d0: 539d342e 55a0a2f3 e132058a eb75a4f6 .4.S...U..2...u. + 348e0: ec390b83 efaa4060 9f065e71 1051bd6e ..9.`@..q^..n.Q. + 348f0: 8af93e21 063d96dd 05aedd3e bd464de6 !>....=.>....MF. + 34900: 8db59154 5d0571c4 d46f0406 15ff6050 T....q.]..o.P`.. + 34910: fb241998 e997d6bd 43cc8940 9e7767d9 ..$.....@..C.gw. + 34920: 42bdb0e8 8b880789 5b38e719 eedb79c8 ...B......8[.y.. + 34930: 0a47a17c 0fe97c42 1ec9f884 00000000 |.G.B|.......... + 34940: 86830980 ed48322b 70ac1e11 724e6c5a ....+2H....pZlNr + 34950: fffbfd0e 38560f85 d51e3dae 3927362d ......V8.=..-6'9 + 34960: d9640a0f a621685c 54d19b5b 2e3a2436 ..d.\h!.[..T6$:. + 34970: 67b10c0a e70f9357 96d2b4ee 919e1b9b ...gW........... + 34980: c54f80c0 20a261dc 4b695a77 1a161c12 ..O..a. wZiK.... + 34990: ba0ae293 2ae5c0a0 e0433c22 171d121b .......*": + 34a70: 80be9f5d .word 0x80be9f5d + 34a74: 937c69d0 .word 0x937c69d0 + 34a78: 2da96fd5 .word 0x2da96fd5 + 34a7c: 12b3cf25 .word 0x12b3cf25 + 34a80: 993bc8ac .word 0x993bc8ac + 34a84: 7da71018 .word 0x7da71018 + 34a88: 636ee89c .word 0x636ee89c + 34a8c: bb7bdb3b .word 0xbb7bdb3b + 34a90: 7809cd26 .word 0x7809cd26 + 34a94: 18f46e59 .word 0x18f46e59 + 34a98: b701ec9a .word 0xb701ec9a + 34a9c: 9aa8834f .word 0x9aa8834f + 34aa0: 6e65e695 .word 0x6e65e695 + 34aa4: e67eaaff .word 0xe67eaaff + 34aa8: cf0821bc .word 0xcf0821bc + 34aac: e8e6ef15 .word 0xe8e6ef15 + 34ab0: 9bd9bae7 .word 0x9bd9bae7 + 34ab4: 36ce4a6f .word 0x36ce4a6f + 34ab8: 09d4ea9f .word 0x09d4ea9f + 34abc: 7cd629b0 .word 0x7cd629b0 + 34ac0: b2af31a4 .word 0xb2af31a4 + 34ac4: 23312a3f .word 0x23312a3f + 34ac8: 9430c6a5 .word 0x9430c6a5 + 34acc: 66c035a2 .word 0x66c035a2 + 34ad0: bc37744e .word 0xbc37744e + 34ad4: caa6fc82 .word 0xcaa6fc82 + 34ad8: d0b0e090 .word 0xd0b0e090 + 34adc: d81533a7 .word 0xd81533a7 + 34ae0: 984af104 .word 0x984af104 + 34ae4: daf741ec .word 0xdaf741ec + 34ae8: 500e7fcd .word 0x500e7fcd + 34aec: f62f1791 .word 0xf62f1791 + 34af0: d68d764d .word 0xd68d764d + 34af4: b04d43ef .word 0xb04d43ef + 34af8: 4d54ccaa .word 0x4d54ccaa + 34afc: 04dfe496 .word 0x04dfe496 + 34b00: b5e39ed1 .word 0xb5e39ed1 + 34b04: 881b4c6a .word 0x881b4c6a + 34b08: 1fb8c12c .word 0x1fb8c12c + 34b0c: 517f4665 .word 0x517f4665 + 34b10: ea049d5e .word 0xea049d5e + 34b14: 355d018c .word 0x355d018c + 34b18: 7473fa87 .word 0x7473fa87 + 34b1c: 412efb0b .word 0x412efb0b + 34b20: 1d5ab367 .word 0x1d5ab367 + 34b24: d25292db .word 0xd25292db + 34b28: 5633e910 .word 0x5633e910 + 34b2c: 47136dd6 .word 0x47136dd6 + 34b30: 618c9ad7 .word 0x618c9ad7 + 34b34: 0c7a37a1 .word 0x0c7a37a1 + 34b38: 148e59f8 .word 0x148e59f8 + 34b3c: 3c89eb13 .word 0x3c89eb13 + 34b40: 27eecea9 .word 0x27eecea9 + 34b44: c935b761 .word 0xc935b761 + 34b48: e5ede11c .word 0xe5ede11c + 34b4c: b13c7a47 .word 0xb13c7a47 + 34b50: df599cd2 .word 0xdf599cd2 + 34b54: 733f55f2 .word 0x733f55f2 + 34b58: ce791814 .word 0xce791814 + 34b5c: 37bf73c7 .word 0x37bf73c7 + 34b60: cdea53f7 .word 0xcdea53f7 + 34b64: aa5b5ffd .word 0xaa5b5ffd + 34b68: 6f14df3d .word 0x6f14df3d + 34b6c: db867844 .word 0xdb867844 + 34b70: f381caaf .word 0xf381caaf + 34b74: c43eb968 .word 0xc43eb968 + 34b78: 342c3824 .word 0x342c3824 + 34b7c: 405fc2a3 .word 0x405fc2a3 + 34b80: c372161d .word 0xc372161d + 34b84: 250cbce2 .word 0x250cbce2 + 34b88: 498b283c .word 0x498b283c + 34b8c: 9541ff0d .word 0x9541ff0d + 34b90: 017139a8 .word 0x017139a8 + 34b94: b3de080c .word 0xb3de080c + 34b98: e49cd8b4 .word 0xe49cd8b4 + 34b9c: c1906456 .word 0xc1906456 + 34ba0: 84617bcb .word 0x84617bcb + 34ba4: b670d532 .word 0xb670d532 + 34ba8: 5c74486c .word 0x5c74486c + 34bac: 5742d0b8 .word 0x5742d0b8 + +00034bb0 : + 34bb0: 00000052 00000009 0000006a 000000d5 R.......j....... + 34bc0: 00000030 00000036 000000a5 00000038 0...6.......8... + 34bd0: 000000bf 00000040 000000a3 0000009e ....@........... + 34be0: 00000081 000000f3 000000d7 000000fb ................ + 34bf0: 0000007c 000000e3 00000039 00000082 |.......9....... + 34c00: 0000009b 0000002f 000000ff 00000087 ..../........... + 34c10: 00000034 0000008e 00000043 00000044 4.......C...D... + 34c20: 000000c4 000000de 000000e9 000000cb ................ + 34c30: 00000054 0000007b 00000094 00000032 T...{.......2... + 34c40: 000000a6 000000c2 00000023 0000003d ........#...=... + 34c50: 000000ee 0000004c 00000095 0000000b ....L........... + 34c60: 00000042 000000fa 000000c3 0000004e B...........N... + 34c70: 00000008 0000002e 000000a1 00000066 ............f... + 34c80: 00000028 000000d9 00000024 000000b2 (.......$....... + 34c90: 00000076 0000005b 000000a2 00000049 v...[.......I... + 34ca0: 0000006d 0000008b 000000d1 00000025 m...........%... + 34cb0: 00000072 000000f8 000000f6 00000064 r...........d... + 34cc0: 00000086 00000068 00000098 00000016 ....h........... + 34cd0: 000000d4 000000a4 0000005c 000000cc ........\....... + 34ce0: 0000005d 00000065 000000b6 00000092 ]...e........... + 34cf0: 0000006c 00000070 00000048 00000050 l...p...H...P... + 34d00: 000000fd 000000ed 000000b9 000000da ................ + 34d10: 0000005e 00000015 00000046 00000057 ^.......F...W... + 34d20: 000000a7 0000008d 0000009d 00000084 ................ + 34d30: 00000090 000000d8 000000ab 00000000 ................ + 34d40: 0000008c 000000bc 000000d3 0000000a ................ + 34d50: 000000f7 000000e4 00000058 00000005 ........X....... + 34d60: 000000b8 000000b3 00000045 00000006 ........E....... + 34d70: 000000d0 0000002c 0000001e 0000008f ....,........... + 34d80: 000000ca 0000003f 0000000f 00000002 ....?........... + 34d90: 000000c1 000000af 000000bd 00000003 ................ + 34da0: 00000001 00000013 0000008a 0000006b ............k... + 34db0: 0000003a 00000091 00000011 00000041 :...........A... + 34dc0: 0000004f 00000067 000000dc 000000ea O...g........... + 34dd0: 00000097 000000f2 000000cf 000000ce ................ + 34de0: 000000f0 000000b4 000000e6 00000073 ............s... + 34df0: 00000096 000000ac 00000074 00000022 ........t..."... + 34e00: 000000e7 000000ad 00000035 00000085 ........5....... + 34e10: 000000e2 000000f9 00000037 000000e8 ........7....... + 34e20: 0000001c 00000075 000000df 0000006e ....u.......n... + 34e30: 00000047 000000f1 0000001a 00000071 G...........q... + 34e40: 0000001d 00000029 000000c5 00000089 ....)........... + 34e50: 0000006f 000000b7 00000062 0000000e o.......b....... + 34e60: 000000aa 00000018 000000be 0000001b ................ + 34e70: 000000fc 00000056 0000003e 0000004b ....V...>...K... + 34e80: 000000c6 000000d2 00000079 00000020 ........y... ... + 34e90: 0000009a 000000db 000000c0 000000fe ................ + 34ea0: 00000078 000000cd 0000005a 000000f4 x.......Z....... + 34eb0: 0000001f 000000dd 000000a8 00000033 ............3... + 34ec0: 00000088 00000007 000000c7 00000031 ............1... + 34ed0: 000000b1 00000012 00000010 00000059 ............Y... + 34ee0: 00000027 00000080 000000ec 0000005f '..........._... + 34ef0: 00000060 00000051 0000007f 000000a9 `...Q........... + 34f00: 00000019 000000b5 0000004a 0000000d ........J....... + 34f10: 0000002d 000000e5 0000007a 0000009f -.......z....... + 34f20: 00000093 000000c9 0000009c 000000ef ................ + 34f30: 000000a0 000000e0 0000003b 0000004d ........;...M... + 34f40: 000000ae 0000002a 000000f5 000000b0 ....*........... + 34f50: 000000c8 000000eb 000000bb 0000003c ............<... + 34f60: 00000083 00000053 00000099 00000061 ....S.......a... + 34f70: 00000017 0000002b 00000004 0000007e ....+.......~... + 34f80: 000000ba 00000077 000000d6 00000026 ....w.......&... + 34f90: 000000e1 00000069 00000014 00000063 ....i.......c... + 34fa0: 00000055 00000021 0000000c 0000007d U...!.......}... + +00034fb0 : + 34fb0: 00000000 77073096 ee0e612c 990951ba .....0.w,a...Q.. + 34fc0: 076dc419 706af48f e963a535 9e6495a3 ..m...jp5.c...d. + 34fd0: 0edb8832 79dcb8a4 e0d5e91e 97d2d988 2......y........ + 34fe0: 09b64c2b 7eb17cbd e7b82d07 90bf1d91 +L...|.~.-...... + 34ff0: 1db71064 6ab020f2 f3b97148 84be41de d.... .jHq...A.. + 35000: 1adad47d 6ddde4eb f4d4b551 83d385c7 }......mQ....... + 35010: 136c9856 646ba8c0 fd62f97a 8a65c9ec V.l...kdz.b...e. + 35020: 14015c4f 63066cd9 fa0f3d63 8d080df5 O\...l.cc=...... + 35030: 3b6e20c8 4c69105e d56041e4 a2677172 . n;^.iL.A`.rqg. + 35040: 3c03e4d1 4b04d447 d20d85fd a50ab56b ...jm..Zjz + 351e0: e40ecf0b 9309ff9d 0a00ae27 7d079eb1 ........'......} + 351f0: f00f9344 8708a3d2 1e01f268 6906c2fe D.......h......i + 35200: f762575d 806567cb 196c3671 6e6b06e7 ]Wb..ge.q6l...kn + 35210: fed41b76 89d32be0 10da7a5a 67dd4acc v....+..Zz...J.g + 35220: f9b9df6f 8ebeeff9 17b7be43 60b08ed5 o.......C......` + 35230: d6d6a3e8 a1d1937e 38d8c2c4 4fdff252 ....~......8R..O + 35240: d1bb67f1 a6bc5767 3fb506dd 48b2364b .g..gW.....?K6.H + 35250: d80d2bda af0a1b4c 36034af6 41047a60 .+..L....J.6`z.A + 35260: df60efc3 a867df55 316e8eef 4669be79 ..`.U.g...n1y.iF + 35270: cb61b38c bc66831a 256fd2a0 5268e236 ..a...f...o%6.hR + 35280: cc0c7795 bb0b4703 220216b9 5505262f .w...G....."/&.U + 35290: c5ba3bbe b2bd0b28 2bb45a92 5cb36a04 .;..(....Z.+.j.\ + 352a0: c2d7ffa7 b5d0cf31 2cd99e8b 5bdeae1d ....1......,...[ + 352b0: 9b64c2b0 ec63f226 756aa39c 026d930a ..d.&.c...ju..m. + 352c0: 9c0906a9 eb0e363f 72076785 05005713 ....?6...g.r.W.. + 352d0: 95bf4a82 e2b87a14 7bb12bae 0cb61b38 .J...z...+.{8... + 352e0: 92d28e9b e5d5be0d 7cdcefb7 0bdbdf21 ...........|!... + 352f0: 86d3d2d4 f1d4e242 68ddb3f8 1fda836e ....B......hn... + 35300: 81be16cd f6b9265b 6fb077e1 18b74777 ....[&...w.owG.. + 35310: 88085ae6 ff0f6a70 66063bca 11010b5c .Z..pj...;.f\... + 35320: 8f659eff f862ae69 616bffd3 166ccf45 ..e.i.b...kaE.l. + 35330: a00ae278 d70dd2ee 4e048354 3903b3c2 x.......T..N...9 + 35340: a7672661 d06016f7 4969474d 3e6e77db a&g...`.MGiI.wn> + 35350: aed16a4a d9d65adc 40df0b66 37d83bf0 Jj...Z..f..@.;.7 + 35360: a9bcae53 debb9ec5 47b2cf7f 30b5ffe9 S..........G...0 + 35370: bdbdf21c cabac28a 53b39330 24b4a3a6 ........0..S...$ + 35380: bad03605 cdd70693 54de5729 23d967bf .6......)W.T.g.# + 35390: b3667a2e c4614ab8 5d681b02 2a6f2b94 .zf..Ja...h].+o* + 353a0: b40bbe37 c30c8ea1 5a05df1b 2d02ef8d 7..........Z...- + +000353b0 : + 353b0: 00000080 00000000 00000000 00000000 ................ + ... + +000353f0 : + 353f0: 160b0402 2418120c 6c604830 00000000 .......$0H`l.... + +00035400 : + 35400: 968b8482 .... + +00035404 : + 35404: 2418120c 6c604830 ...$0H`l + +0003540c : + 3540c: 01f25000 .P.. + +00035410 : + 35410: 00f25000 .P.. + +00035414 : + 35414: 01f25000 .P.. + +00035418 : + 35418: 02f25000 .P.. + +0003541c : + 3541c: 04f25000 .P.. + +00035420 : + 35420: 05f25000 .P.. + +00035424 : + 35424: 00ac0f00 .... + +00035428 : + 35428: 01ac0f00 .... + +0003542c : + 3542c: 02ac0f00 .... + +00035430 : + 35430: 04ac0f00 .... + +00035434 : + 35434: 05ac0f00 .... + +00035438 : + 35438: 01f25000 .P.. + +0003543c : + 3543c: 01ac0f00 .... + +00035440 : + 35440: 04f25000 .P.. + +00035444 : + 35444: 02ac0f00 .... + +00035448 : + 35448: 01ac0f00 .... + +0003544c : + 3544c: 00000001 .... + +00035450 : + 35450: 756f7247 656b2070 78652079 736e6170 Group key expans + 35460: 006e6f69 ion. + +00035464 : + 35464: 72696150 65736977 79656b20 70786520 Pairwise key exp + 35474: 69736e61 00006e6f ansion.. + +0003547c : + 3547c: 7b777c63 c56f6bf2 2b670130 76abd7fe c|w{.ko.0.g+...v + 3548c: 7dc982ca f04759fa afa2d4ad c072a49c ...}.YG.......r. + 3549c: 2693fdb7 ccf73f36 f1e5a534 1531d871 ...&6?..4...q.1. + 354ac: c323c704 9a059618 e2801207 75b227eb ..#..........'.u + 354bc: 1a2c8309 a05a6e1b b3d63b52 842fe329 ..,..nZ.R;..)./. + 354cc: ed00d153 5bb1fc20 39becb6a cf584c4a S... ..[j..9JLX. + 354dc: fbaaefd0 85334d43 7f02f945 a89f3c50 ....CM3.E...P<.. + 354ec: 8f40a351 f5389d92 21dab6bc d2f3ff10 Q.@...8....!.... + 354fc: ec130ccd 1744975f 3d7ea7c4 73195d64 ...._.D...~=d].s + 3550c: dc4f8160 88902a22 14b8ee46 db0b5ede `.O."*..F....^.. + 3551c: 0a3a32e0 5c240649 62acd3c2 79e49591 .2:.I.$\...b...y + 3552c: 6d37c8e7 a94ed58d eaf4566c 08ae7a65 ..7m..N.lV..ez.. + 3553c: 2e2578ba c6b4a61c 1f74dde8 8a8bbd4b .x%.......t.K... + 3554c: 66b53e70 0ef60348 b9573561 9e1dc186 p>.fH...a5W..... + 3555c: 1198f8e1 948ed969 e9871e9b df2855ce ....i........U(. + 3556c: 0d89a18c 6842e6bf 0f2d9941 16bb54b0 ......BhA.-..T.. + +0003557c : + 3557c: 08040201 80402010 3636361b ..... @..666 + +00035588 : + 35588: f884c6a5 f68dee99 d6bdff0d 9154deb1 ..............T. + 35598: 02036050 567dcea9 b562e719 ec9a4de6 P`....}V..b..M.. + 355a8: 1f9d8f45 fa878940 b2ebef15 fb0b8ec9 E...@........... + 355b8: b36741ec 45ea5ffd 53f723bf 9b5be496 .Ag.._.E.#.S..[. + 355c8: e11c75c2 4c6a3dae 7e416c5a 834ff502 .u...=jLZlA~..O. + 355d8: 51f4685c f908d134 ab73e293 2a3f6253 \h.Q4.....s.Sb?* + 355e8: 9552080c 9d5e4665 37a13028 2fb50a0f ..R.eF^.(0.7.../ + 355f8: 24360e09 df3d1b9b 4e69cd26 ea9f7fcd ..6$..=.&.iN.... + 35608: 1d9e121b 342e5874 dcb2362d 5bfbb4ee ....tX.4-6.....[ + 35618: 764da4f6 7dceb761 dd3e527b 13975e71 ..Mva..}{R>.q^.. + 35628: b968a6f5 c12c0000 e31f4060 b6ed79c8 ..h...,.`@...y.. + 35638: 8d46d4be 724b67d9 98d494de 854ab0e8 ..F..gKr......J. + 35648: c52abb6b ed164fe5 9ad786c5 11946655 k.*..O......Uf.. + 35658: e9108acf fe810406 7844a0f0 4be325ba ..........Dx.%.K + 35668: 5dfea2f3 058a80c0 21bc3fad f1047048 ...].....?.!Hp.. + 35678: 77c163df 4263af75 e51a2030 bf6dfd0e .c.wu.cB0 ....m. + 35688: 1814814c c32f2635 35a2bee1 2e3988cc L...5&/....5..9. + 35698: 55f29357 7a47fc82 bae7c8ac e695322b W..U..Gz....+2.. + 356a8: 1998c0a0 a37f9ed1 547e4466 0b833bab ........fD~T.;.. + 356b8: c7298cca 283c6bd3 bce2a779 ad76161d ..)..k<(y.....v. + 356c8: 6456db3b 141e744e 0c0a92db b8e4486c ;.VdNt......lH.. + 356d8: bd6e9f5d c4a643ef 31a439a8 f28bd337 ].n..C...9.17... + 356e8: 8b43d532 dab76e59 b164018c 49e09cd2 2.C.Yn....d....I + 356f8: acfad8b4 cf25f307 f48ecaaf 101847e9 ......%......G.. + 35708: f0886fd5 5c724a6f 57f13824 975173c7 .o..oJr\$8.W.sQ. + 35718: a17ccb23 3e21e89c 61dc96dd 0f850d86 #.|...!>...a.... + 35728: 7c42e090 ccaa71c4 060590d8 1c12f701 ..B|.q.......... + 35738: 6a5fc2a3 69d0aef9 99581791 27b93a27 .._j...i..X.':.' + 35748: eb13d938 22332bb3 a970d2bb 33a70789 8....+3"..p....3 + 35758: 3c222db6 c9201592 aaff8749 a57a5078 .-"<.. .I...xPz. + 35768: 59f8038f 1a170980 d73165da d0b884c6 ...Y.....e1..... + 35778: 29b082c3 1e115a77 a8fc7bcb 2c3a6dd6 ...)wZ...{...m:, + 35788: 84f8a5c6 8df699ee bdd60dff 5491b1de ...............T + 35798: 03025060 7d56a9ce 62b519e7 9aece64d `P....V}...bM... + 357a8: 9d1f458f 87fa4089 ebb215ef 0bfbc98e .E...@.......... + 357b8: 67b3ec41 ea45fd5f f753bf23 5b9b96e4 A..g_.E.#.S....[ + 357c8: 1ce1c275 6a4cae3d 417e5a6c 4f8302f5 u...=.LjlZ~A...O + 357d8: f4515c68 08f934d1 73ab93e2 3f2a5362 h\Q..4.....sbS*? + 357e8: 52950c08 5e9d6546 a1372830 b52f0f0a ...RFe.^0(7.../. + 357f8: 3624090e 3ddf9b1b 694e26cd 9feacd7f ..$6...=.&Ni.... + 35808: 9e1d1b12 2e347458 b2dc2d36 fb5beeb4 ....Xt4.6-....[. + 35818: 4d76f6a4 ce7d61b7 3edd7b52 9713715e ..vM.a}.R{.>^q.. + 35828: 68b9f5a6 2cc10000 1fe36040 edb6c879 ...h...,@`..y... + 35838: 468dbed4 4b72d967 d498de94 4a85e8b0 ...Fg.rK.......J + 35848: 2ac56bbb 16ede54f d79ac586 94115566 .k.*O.......fU.. + 35858: 10e9cf8a 81fe0604 4478f0a0 e34bba25 ..........xD%.K. + 35868: fe5df3a2 8a05c080 bc21ad3f 04f14870 ..].....?.!.pH.. + 35878: c177df63 634275af 1ae53020 6dbf0efd c.w..uBc 0.....m + 35888: 14184c81 2fc33526 a235e1be 392ecc88 .L..&5./..5....9 + 35898: f2555793 477a82fc e7baacc8 95e62b32 .WU...zG....2+.. + 358a8: 9819a0c0 7fa3d19e 7e546644 830bab3b ........DfT~;... + 358b8: 29c7ca8c 3c28d36b e2bc79a7 76ad1d16 ...)k.(<.y.....v + 358c8: 56643bdb 1e144e74 0a0cdb92 e4b86c48 .;dVtN......Hl.. + 358d8: 6ebd5d9f a6c4ef43 a431a839 8bf237d3 .].nC...9.1..7.. + 358e8: 438b32d5 b7da596e 64b18c01 e049d29c .2.CnY.....d..I. + 358f8: faacb4d8 25cf07f3 8ef4afca 1810e947 .......%....G... + 35908: 88f0d56f 725c6f4a f1572438 5197c773 o...Jo\r8$W.s..Q + 35918: 7ca123cb 213e9ce8 dc61dd96 850f860d .#.|..>!..a..... + 35928: 427c90e0 aaccc471 0506d890 121c01f7 ..|Bq........... + 35938: 5f6aa3c2 d069f9ae 58999117 b927273a ..j_..i....X:''. + 35948: 13eb38d9 3322b32b 70a9bbd2 a7338907 .8..+."3...p..3. + 35958: 223cb62d 20c99215 ffaa4987 7aa57850 -.<"... .I..Px.z + 35968: f8598f03 171a8009 31d7da65 b8d0c684 ..Y.....e..1.... + 35978: b029c382 111e775a fca8cb7b 3a2cd66d ..).Zw..{...m.,: + +00035988 : + 35988: c66363a5 f87c7c84 ee777799 f67b7b8d .cc..||..ww..{{. + 35998: fff2f20d d66b6bbd de6f6fb1 91c5c554 .....kk..oo.T... + 359a8: 60303050 02010103 ce6767a9 562b2b7d P00`.....gg.}++V + 359b8: e7fefe19 b5d7d762 4dababe6 ec76769a ....b......M.vv. + 359c8: 8fcaca45 1f82829d 89c9c940 fa7d7d87 E.......@....}}. + 359d8: effafa15 b25959eb 8e4747c9 fbf0f00b .....YY..GG..... + 359e8: 41adadec b3d4d467 5fa2a2fd 45afafea ...Ag......_...E + 359f8: 239c9cbf 53a4a4f7 e4727296 9bc0c05b ...#...S.rr.[... + 35a08: 75b7b7c2 e1fdfd1c 3d9393ae 4c26266a ...u.......=j&&L + 35a18: 6c36365a 7e3f3f41 f5f7f702 83cccc4f Z66lA??~....O... + 35a28: 6834345c 51a5a5f4 d1e5e534 f9f1f108 \44h...Q4....... + 35a38: e2717193 abd8d873 62313153 2a15153f .qq.s...S11b?..* + 35a48: 0804040c 95c7c752 46232365 9dc3c35e ....R...e##F^... + 35a58: 30181828 379696a1 0a05050f 2f9a9ab5 (..0...7......./ + 35a68: 0e070709 24121236 1b80809b dfe2e23d ....6..$....=... + 35a78: cdebeb26 4e272769 7fb2b2cd ea75759f &...i''N.....uu. + 35a88: 1209091b 1d83839e 582c2c74 341a1a2e ........t,,X...4 + 35a98: 361b1b2d dc6e6eb2 b45a5aee 5ba0a0fb -..6.nn..ZZ....[ + 35aa8: a45252f6 763b3b4d b7d6d661 7db3b3ce .RR.M;;va......} + 35ab8: 5229297b dde3e33e 5e2f2f71 13848497 {))R>...q//^.... + 35ac8: a65353f5 b9d1d168 00000000 c1eded2c .SS.h.......,... + 35ad8: 40202060 e3fcfc1f 79b1b1c8 b65b5bed ` @.......y.[[. + 35ae8: d46a6abe 8dcbcb46 67bebed9 7239394b .jj.F......gK99r + 35af8: 944a4ade 984c4cd4 b05858e8 85cfcf4a .JJ..LL..XX.J... + 35b08: bbd0d06b c5efef2a 4faaaae5 edfbfb16 k...*......O.... + 35b18: 864343c5 9a4d4dd7 66333355 11858594 .CC..MM.U33f.... + 35b28: 8a4545cf e9f9f910 04020206 fe7f7f81 .EE............. + 35b38: a05050f0 783c3c44 259f9fba 4ba8a8e3 .PP.D< + 35cb8: 964b4bdd 61bdbddc 0d8b8b86 0f8a8a85 .KK....a........ + 35cc8: e0707090 7c3e3e42 71b5b5c4 cc6666aa .pp.B>>|...q.ff. + 35cd8: 904848d8 06030305 f7f6f601 1c0e0e12 .HH............. + 35ce8: c26161a3 6a35355f ae5757f9 69b9b9d0 .aa._55j.WW....i + 35cf8: 17868691 99c1c158 3a1d1d27 279e9eb9 ....X...'..:...' + 35d08: d9e1e138 ebf8f813 2b9898b3 22111133 8..........+3.." + 35d18: d26969bb a9d9d970 078e8e89 339494a7 .ii.p..........3 + 35d28: 2d9b9bb6 3c1e1e22 15878792 c9e9e920 ...-"..<.... ... + 35d38: 87cece49 aa5555ff 50282878 a5dfdf7a I....UU.x((Pz... + 35d48: 038c8c8f 59a1a1f8 09898980 1a0d0d17 .......Y........ + 35d58: 65bfbfda d7e6e631 844242c6 d06868b8 ...e1....BB..hh. + 35d68: 824141c3 299999b0 5a2d2d77 1e0f0f11 .AA....)w--Z.... + 35d78: 7bb0b0cb a85454fc 6dbbbbd6 2c16163a ...{.TT....m:.., + +00035d88 : + 35d88: 08040201 80402010 0000361b ..... @..6.. + +00035d94 : + 35d94: d56a0952 38a53630 9ea340bf fbd7f381 R.j.06.8.@...... + 35da4: 8239e37c 87ff2f9b 44438e34 cbe9dec4 |.9../..4.CD.... + 35db4: 32947b54 3d23c2a6 0b954cee 4ec3fa42 T{.2..#=.L..B..N + 35dc4: 66a12e08 b224d928 49a25b76 25d18b6d ...f(.$.v[.Im..% + 35dd4: 64f6f872 16986886 cc5ca4d4 92b6655d r..d.h....\.]e.. + 35de4: 5048706c dab9edfd 5746155e 849d8da7 lpHP....^.FW.... + 35df4: 00abd890 0ad3bc8c 0558e4f7 0645b3b8 ..........X...E. + 35e04: 8f1e2cd0 020f3fca 03bdafc1 6b8a1301 .,...?.........k + 35e14: 4111913a eadc674f cecff297 73e6b4f0 :..AOg.........s + 35e24: 2274ac96 8535ade7 e837f9e2 6edf751c ..t"..5...7..u.n + 35e34: 711af147 89c5291d 0e62b76f 1bbe18aa G..q.)..o.b..... + 35e44: 4b3e56fc 2079d2c6 fec0db9a f45acd78 .V>K..y ....x.Z. + 35e54: 33a8dd1f 31c70788 591012b1 5fec8027 ...3...1...Y'.._ + 35e64: a97f5160 0d4ab519 9f7ae52d ef9cc993 `Q....J.-.z..... + 35e74: 4d3be0a0 b0f52aae 3cbbebc8 61995383 ..;M.*.....<.S.a + 35e84: 7e042b17 26d677ba 631469e1 7d0c2155 .+.~.w.&.i.cU!.} + +00035e94 : + 35e94: 51f4a750 7e416553 1a17a4c3 3a275e96 P..QSeA~.....^': + 35ea4: 3bab6bcb 1f9d45f1 acfa58ab 4be30393 .k.;.E...X.....K + 35eb4: 2030fa55 ad766df6 88cc7691 f5024c25 U.0 .mv..v..%L.. + 35ec4: 4fe5d7fc c52acbd7 26354480 b562a38f ...O..*..D5&..b. + 35ed4: deb15a49 25ba1b67 45ea0e98 5dfec0e1 IZ..g..%...E...] + 35ee4: c32f7502 814cf012 8d4697a3 6bd3f9c6 .u/...L...F....k + 35ef4: 038f5fe7 15929c95 bf6d7aeb 955259da ._.......zm..YR. + 35f04: d4be832d 587421d3 49e06929 8ec9c844 -....!tX)i.ID... + 35f14: 75c2896a f48e7978 99583e6b 27b971dd j..uxy..k>X..q.' + 35f24: bee14fb6 f088ad17 c920ac66 7dce3ab4 .O......f. ..:.} + 35f34: 63df4a18 e51a3182 97513360 62537f45 .J.c.1..`3Q.E.Sb + 35f44: b16477e0 bb6bae84 fe81a01c f9082b94 .wd...k......+.. + 35f54: 70486858 8f45fd19 94de6c87 527bf8b7 XhHp..E..l....{R + 35f64: ab73d323 724b02e2 e31f8f57 6655ab2a #.s...KrW...*.Uf + 35f74: b2eb2807 2fb5c203 86c57b9a d33708a5 .(...../.{....7. + 35f84: 302887f2 23bfa5b2 02036aba ed16825c ..(0...#.j..\... + 35f94: 8acf1c2b a779b492 f307f2f0 4e69e2a1 +.....y.......iN + 35fa4: 65daf4cd 0605bed5 d134621f c4a6fe8a ...e.....b4..... + 35fb4: 342e539d a2f355a0 058ae132 a4f6eb75 .S.4.U..2...u... + 35fc4: 0b83ec39 4060efaa 5e719f06 bd6e1051 9.....`@..q^Q.n. + 35fd4: 3e218af9 96dd063d dd3e05ae 4de6bd46 ..!>=.....>.F..M + 35fe4: 91548db5 71c45d05 0406d46f 605015ff ..T..].qo.....P` + 35ff4: 1998fb24 d6bde997 894043cc 67d99e77 $........C@.w..g + 36004: b0e842bd 07898b88 e7195b38 79c8eedb .B......8[.....y + 36014: a17c0a47 7c420fe9 f8841ec9 00000000 G.|...B|........ + 36024: 09808683 322bed48 1e1170ac 6c5a724e ....H.+2.p..NrZl + 36034: fd0efffb 0f853856 3daed51e 362d3927 ....V8.....='9-6 + 36044: 0a0fd964 685ca621 9b5b54d1 24362e3a d...!.\h.T[.:.6$ + 36054: 0c0a67b1 9357e70f b4ee96d2 1b9b919e .g....W......... + 36064: 80c0c54f 61dc20a2 5a774b69 1c121a16 O.... .aiKwZ.... + 36074: e293ba0a c0a02ae5 3c22e043 121b171d .....*..C."<.... + 36084: 0e090d0b f28bc7ad 2db6a8b9 141ea9c8 ...........-.... + 36094: 57f11985 af75074c ee99ddbb a37f60fd ...WL.u......`.. + 360a4: f701269f 5c72f5bc 44663bc5 5bfb7e34 .&....r\.;fD4~.[ + 360b4: 8b432976 cb23c6dc b6edfc68 b8e4f163 v)C...#.h...c... + 360c4: d731dcca 42638510 13972240 84c61120 ..1...cB@".. ... + 360d4: 854a247d d2bb3df8 aef93211 c729a16d }$J..=...2..m.). + 360e4: 1d9e2f4b dcb230f3 0d8652ec 77c1e3d0 K/...0...R.....w + 360f4: 2bb3166c a970b999 119448fa 47e96422 l..+..p..H.."d.G + 36104: a8fc8cc4 a0f03f1a 567d2cd8 223390ef .....?...,}V..3" + 36114: 87494ec7 d938d1c1 8ccaa2fe 98d40b36 .NI...8.....6... + 36124: a6f581cf a57ade28 dab78e26 3fadbfa4 ....(.z.&......? + 36134: 2c3a9de4 5078920d 6a5fcc9b 547e4662 ..:,..xP.._jbF~T + 36144: f68d13c2 90d8b8e8 2e39f75e 82c3aff5 ........^.9..... + 36154: 9f5d80be 69d0937c 6fd52da9 cf2512b3 ..].|..i.-.o..%. + 36164: c8ac993b 10187da7 e89c636e db3bbb7b ;....}..nc..{.;. + 36174: cd267809 6e5918f4 ec9ab701 834f9aa8 .x&...Yn......O. + 36184: e6956e65 aaffe67e 21bccf08 ef15e8e6 en..~......!.... + 36194: bae79bd9 4a6f36ce ea9f09d4 29b07cd6 .....6oJ.....|.) + 361a4: 31a4b2af 2a3f2331 c6a59430 35a266c0 ...11#?*0....f.5 + 361b4: 744ebc37 fc82caa6 e090d0b0 33a7d815 7.Nt...........3 + 361c4: f104984a 41ecdaf7 7fcd500e 1791f62f J......A.P../... + 361d4: 764dd68d 43efb04d ccaa4d54 e49604df ..MvM..CTM...... + 361e4: 9ed1b5e3 4c6a881b c12c1fb8 4665517f ......jL..,..QeF + 361f4: 9d5eea04 018c355d fa877473 fb0b412e ..^.]5..st...A.. + 36204: b3671d5a 92dbd252 e9105633 6dd64713 Z.g.R...3V...G.m + 36214: 9ad7618c 37a10c7a 59f8148e eb133c89 .a..z..7...Y.<.. + 36224: cea927ee b761c935 e11ce5ed 7a47b13c .'..5.a.....<.Gz + 36234: 9cd2df59 55f2733f 1814ce79 73c737bf Y...?s.Uy....7.s + 36244: 53f7cdea 5ffdaa5b df3d6f14 7844db86 ...S[.._.o=...Dx + 36254: caaff381 b968c43e 3824342c c2a3405f ....>.h.,4$8_@.. + 36264: 161dc372 bce2250c 283c498b ff0d9541 r....%...I<(A... + 36274: 39a80171 080cb3de d8b4e49c 6456c190 q..9..........Vd + 36284: 7bcb8461 d532b670 486c5c74 d0b85742 a..{p.2.t\lHBW.. + +00036294 : + 36294: 428a2f98 71374491 b5c0fbcf e9b5dba5 ./.B.D7q........ + 362a4: 3956c25b 59f111f1 923f82a4 ab1c5ed5 [.V9...Y..?..^.. + 362b4: d807aa98 12835b01 243185be 550c7dc3 .....[....1$.}.U + 362c4: 72be5d74 80deb1fe 9bdc06a7 c19bf174 t].r........t... + 362d4: e49b69c1 efbe4786 0fc19dc6 240ca1cc .i...G.........$ + 362e4: 2de92c6f 4a7484aa 5cb0a9dc 76f988da o,.-..tJ...\...v + 362f4: 983e5152 a831c66d b00327c8 bf597fc7 RQ>.m.1..'....Y. + 36304: c6e00bf3 d5a79147 06ca6351 14292967 ....G...Qc..g)). + 36314: 27b70a85 2e1b2138 4d2c6dfc 53380d13 ...'8!...m,M..8S + 36324: 650a7354 766a0abb 81c2c92e 92722c85 Ts.e..jv.....,r. + 36334: a2bfe8a1 a81a664b c24b8b70 c76c51a3 ....Kf..p.K..Ql. + 36344: d192e819 d6990624 f40e3585 106aa070 ....$....5..p.j. + 36354: 19a4c116 1e376c08 2748774c 34b0bcb5 .....l7.LwH'...4 + 36364: 391c0cb3 4ed8aa4a 5b9cca4f 682e6ff3 ...9J..NO..[.o.h + 36374: 748f82ee 78a5636f 84c87814 8cc70208 ...toc.x.x...... + 36384: 90befffa a4506ceb bef9a3f7 c67178f2 .....lP......xq. + +00036394 : + 36394: 00000009 00000000 00000000 00000000 ................ + ... + +000363b8 : + 363b8: d728ae22 428a2f98 23ef65cd 71374491 ".(../.B.e.#.D7q + 363c8: ec4d3b2f b5c0fbcf 8189dbbc e9b5dba5 /;M............. + 363d8: f348b538 3956c25b b605d019 59f111f1 8.H.[.V9.......Y + 363e8: af194f9b 923f82a4 da6d8118 ab1c5ed5 .O....?...m..^.. + 363f8: a3030242 d807aa98 45706fbe 12835b01 B........opE.[.. + 36408: 4ee4b28c 243185be d5ffb4e2 550c7dc3 ...N..1$.....}.U + 36418: f27b896f 72be5d74 3b1696b1 80deb1fe o.{.t].r...;.... + 36428: 25c71235 9bdc06a7 cf692694 c19bf174 5..%.....&i.t... + 36438: 9ef14ad2 e49b69c1 384f25e3 efbe4786 .J...i...%O8.G.. + 36448: 8b8cd5b5 0fc19dc6 77ac9c65 240ca1cc ........e..w...$ + 36458: 592b0275 2de92c6f 6ea6e483 4a7484aa u.+Yo,.-...n..tJ + 36468: bd41fbd4 5cb0a9dc 831153b5 76f988da ..A....\.S.....v + 36478: ee66dfab 983e5152 2db43210 a831c66d ..f.RQ>..2.-m.1. + 36488: 98fb213f b00327c8 beef0ee4 bf597fc7 ?!...'........Y. + 36498: 3da88fc2 c6e00bf3 930aa725 d5a79147 ...=....%...G... + 364a8: e003826f 06ca6351 0a0e6e70 14292967 o...Qc..pn..g)). + 364b8: 46d22ffc 27b70a85 5c26c926 2e1b2138 ./.F...'&.&\8!.. + 364c8: 5ac42aed 4d2c6dfc 9d95b3df 53380d13 .*.Z.m,M......8S + 364d8: 8baf63de 650a7354 3c77b2a8 766a0abb .c..Ts.e..w<..jv + 364e8: 47edaee6 81c2c92e 1482353b 92722c85 ...G....;5...,r. + 364f8: 4cf10364 a2bfe8a1 bc423001 a81a664b d..L.....0B.Kf.. + 36508: d0f89791 c24b8b70 0654be30 c76c51a3 ....p.K.0.T..Ql. + 36518: d6ef5218 d192e819 5565a910 d6990624 .R........eU$... + 36528: 5771202a f40e3585 32bbd1b8 106aa070 * qW.5.....2p.j. + 36538: b8d2d0c8 19a4c116 5141ab53 1e376c08 ........S.AQ.l7. + 36548: df8eeb99 2748774c e19b48a8 34b0bcb5 ....LwH'.H.....4 + 36558: c5c95a63 391c0cb3 e3418acb 4ed8aa4a cZ.....9..A.J..N + 36568: 7763e373 5b9cca4f d6b2b8a3 682e6ff3 s.cwO..[.....o.h + 36578: 5defb2fc 748f82ee 43172f60 78a5636f ...]...t`/.Coc.x + 36588: a1f0ab72 84c87814 1a6439ec 8cc70208 r....x...9d..... + 36598: 23631e28 90befffa de82bde9 a4506ceb (.c#.........lP. + 365a8: b2c67915 bef9a3f7 e372532b c67178f2 .y......+Sr..xq. + 365b8: ea26619c ca273ece 21c0c207 d186b8c7 .a&..>'....!.... + 365c8: cde0eb1e eada7dd6 ee6ed178 f57d4f7f .....}..x.n..O}. + 365d8: 72176fba 06f067aa a2c898a6 0a637dc5 .o.r.g.......}c. + 365e8: bef90dae 113f9804 131c471b 1b710b35 ......?..G..5.q. + 365f8: 23047d84 28db77f5 40c72493 32caab7b .}.#.w.(.$.@{..2 + 36608: 15c9bebc 3c9ebe0a 9c100d4c 431d67c4 ...........L*~e..).Y + 36628: 3ad6faec 5fcb6fab 4a475817 6c44198c ...:.o._.XGJ..Dl + +00036638 : + 36638: 00000080 00000000 00000000 00000000 ................ + ... + +000366b8 : + 366b8: feb2f159 ffa6e50a fe2add7b 00d4141e Y.......{.*..... + 366c8: 00038052 00f3d130 ff407977 ff9ce332 R...0...wy@.2... + 366d8: 01c56e00 00901b67 .n..g... + +000366e0 : + 366e0: 018c3b85 ff24f1bd 01c325f8 0037dc60 .;....$..%..`.7. + 366f0: ff3e4cb7 003d42c3 01a44c32 ff4ca4e1 .L>..B=.2L....L. + 36700: ffa33d4c 001f3e75 ff409151 000e4176 L=..u>..Q.@.vA.. + 36710: ffd673a2 002e8a06 fff4e67c 008f8a0a .s......|....... + 36720: 00c21a34 004cf4b8 01298f81 ff13f4be 4.....L...)..... + 36730: ff7aaa7b 00448162 0093d579 ff1e6556 {.z.b.D.y...Ve.. + 36740: 009b67a1 ff43598c 01bee5ef 00b50b43 .g...YC.....C... + 36750: fe89f0c6 ffbc45ee ff3c71ea ff39ff25 .....E...q<.%.9. + 36760: feb6b245 00b3d080 fe7d1a76 ffd60703 E.......v.}..... + 36770: ff4d32f1 ffc5cb55 fffa87d3 ff643019 .2M.U........0d. + 36780: feb4d5bb 00695811 019ed153 00627305 .....Xi.S....sb. + 36790: fe3cae04 ff6e37ab ff11b5d9 00aabc14 ..<..7n......... + 367a0: fe669c92 ffaed657 019b7a72 00aa2ce9 ..f.W...rz...,.. + 367b0: 01ef087f 00eaecd6 00db05af ff3d6a31 ............1j=. + 367c0: ffd04206 ff6e6a02 ff13ea51 ffc06bd7 .B...jn.Q....k.. + 367d0: 00ee9743 ff6c2a13 017155e5 ff874432 C....*l..Uq.2D.. + 367e0: 00096a11 ff016732 01a80150 ff1e9823 .j..2g..P...#... + 367f0: 01b9a810 ffe85938 00fcd265 0047fa29 ....8Y..e...).G. + 36800: ff4faacc ffef2e0e 00ef4d50 ff4bd6bd ..O.....PM....K. + 36810: 00f98d11 ff4c5026 007555be 00aae456 ....&PL..Uu.V... + 36820: 01d0d89c ffa4cfc3 ff4c4296 ff10e1af .........BL..... + 36830: 0162508d 00f2db4c 0072a2c6 0098da2e .Pb.L.....r..... + 36840: fef12b9b ff68a09b fefc09b2 00d46e64 .+....h.....dn.. + 36850: 00a7050e ffa3efe9 019d971c ff0a9265 ............e... + 36860: fe469efe 00e4f947 00321e58 ffa03a44 ..F.G...X.2.D:.. + 36870: 016818bf ff814281 ff5532c0 ff8ab308 ..h..B...2U..... + 36880: 00c9fa26 00a05073 0071e683 0093587d &...sP....q.}X.. + 36890: 00c7445a 009e4cfd 0076ff1c 00fefa71 ZD...L....v.q... + 368a0: 002e4b42 002bdae6 01ba78e5 002b4494 BK....+..x...D+. + 368b0: 01ee7c88 ffc56bbb fff63554 fffe7433 .|...k..T5..3t.. + 368c0: 00a5bb33 00af1102 01a05442 001e3af7 3.......BT...:.. + 368d0: fe354123 00bfec45 01f5862d 00dd7ba3 #A5.E...-....{.. + 368e0: ff146e20 00a51734 0047d6ba 0060b0e9 n..4.....G...`. + 368f0: 0136eff2 008a5939 ff540053 0064a088 ..6.9Y..S.T...d. + 36900: fe788e5c 00be7c68 ff3eb1b5 005529fa \.x.h|....>..)U. + 36910: 012a8298 00f6fc60 fe3f9797 003e85ef ..*.`.....?...>. + 36920: 009c3820 ffbda72d 01b3858e 00d35683 8..-........V.. + 36930: fe96b3bb ff0eaafa ff157144 ff3bbade ........Dq....;. + 36940: 01f10742 00480645 fe6c9c56 0059a737 B...E.H.V.l.7.Y. + 36950: fedb346d ff17b00d ff6a2cc4 ff4795ef m4.......,j...G. + 36960: ff7d8ca4 0001ad9f 00e72933 00213e91 ..}.....3)...>!. + 36970: 015d6f8a 004553b9 002e7390 ff109761 .o]..SE..s..a... + 36980: 001ae418 00e2d931 feea4b71 ff0c99c1 ....1...qK...... + 36990: ff6030b6 001a0d0e fef9c380 003bc145 .0`.........E.;. + 369a0: fe512584 003c6a7d 01a9f0d6 0042e3a4 .%Q.}j<.......B. + 369b0: 004ea3d2 00973425 001a4d63 ffd59cee ..N.%4..cM...... + 369c0: 01d1c0d5 00542e49 01294114 004fce36 ....I.T..A).6.O. + 369d0: fe9283c9 ff186faa fe3221b1 ffcb26ab .....o...!2..&.. + 369e0: 0074f74e 0099ddd1 01b28085 00192c3a N.t.........:,.. + 369f0: 013b27c9 00fc13bd 01d2e531 0075bb75 .';.....1...u.u. + 36a00: 01b8b3b5 00db7200 00935e30 003829f5 .....r..0^...)8. + 36a10: fecc0d7d 0077adf4 fe20dd2c 0014ea54 }.....w.,. .T... + 36a20: 01c6a0f9 ffea7eec 00dd3e8f ffd65981 .....~...>...Y.. + 36a30: fe058b37 ffbf1444 01b2cc0e 00d9c323 7...D.......#... + 36a40: 01ce332f 00a5f626 fe061bce 0024579e /3..&........W$. + 36a50: ff9234d9 ffd77b7d ff1f3c55 00070dab .4..}{..U<...... + 36a60: fe58f5da 003c23fc ffa0d637 00386585 ..X..#<.7....e8. + 36a70: fe1320e0 00ea4093 01a2911a 007d7672 . ...@......rv}. + 36a80: 00fafcf8 ffc45e65 fee28dc6 00b62a33 ....e^......3*.. + 36a90: fe090c87 ffd2ac6d 01c2ecc5 009a41f1 ....m........A.. + 36aa0: ff2f9c30 ff374399 fe22a5da 00b3b44a 0./..C7...".J... + 36ab0: 014742da 00637a58 ffdbb5d4 ffe72a5c .BG.Xzc.....\*.. + 36ac0: 009a00ef ffb74df5 01aa515e 00d8d512 .....M..^Q...... + 36ad0: 00475dab 00f85e34 fea19712 ff42d1c5 .]G.4^........B. + 36ae0: fe0ff4ae 00b730a2 fef03d31 00c35db6 .....0..1=...].. + 36af0: 0106e4c7 ff1105c8 ffed2d89 0004946c .........-..l... + 36b00: ffed4f5a ff4d3f27 01cf5235 ff76168e ZO..'?M.5R....v. + 36b10: 0112e865 00431a5c ff58c805 ff8aa821 e...\.C...X.!... + 36b20: 0048e195 ff1bd102 01a8f52c ff11eddc ..H.....,....... + 36b30: fe69d31e 00ddee8d fef55080 000efe6f ..i......P..o... + 36b40: 01be5fde 00f109df ffd44c92 ff68cd6c ._.......L..l.h. + 36b50: 0099753f 00304590 006fe423 ffc121c0 ?u...E0.#.o..!.. + 36b60: febed670 00979873 00586617 00f84a33 p...s....fX.3J.. + 36b70: fe8fc7e2 ff65a2cc 01bd61d0 001268f5 ......e..a...h.. + 36b80: ff1ef6e6 00459417 fe34586e ff59b5e2 ......E.nX4...Y. + 36b90: fe5a2fd0 ff50a172 00f87421 ff5798b3 ./Z.r.P.!t....W. + 36ba0: 01b19045 ff1aee58 0171203a 00454d01 E...X...: q..ME. + 36bb0: ff34793b 0053ee98 00c10834 ffe927e7 ;y4...S.4....'.. + 36bc0: 008a22c7 00ad44de fef2395b ff7fd2dc ."...D..[9...... + 36bd0: fef607c0 00bb2397 00a5ecc3 00ce5d6f .....#......o].. + 36be0: 0185f7d4 ffd1859a 000ae79b 00264e40 ............@N&. + 36bf0: 0164f97a ff61131e 01f95b3e 004d85f8 z.d...a.>[....M. + 36c00: fea83fc5 00520a74 fe71ecb8 ffc2cbd4 .?..t.R...q..... + 36c10: fefc643d ffca0524 ff995b77 001d4f81 =d..$...w[...O.. + 36c20: feab6767 ff6fd7ed 004535d8 0017f0ef gg....o..5E..... + 36c30: ffdd95c2 00dee126 feb4ffe8 ff855276 ....&.......vR.. + 36c40: 01b1d139 0085e88b fe2eb09e 002e73c2 9............s.. + 36c50: 01e5f758 00bf671c feafdedd 002ceb95 X....g........,. + 36c60: fe19e497 006769da 00d2558e ffbe8195 .....ig..U...... + 36c70: fe5e41d5 ffe08675 0075c652 00dcdd9d .A^.u...R.u..... + 36c80: 002465a3 002572c5 fea6ac68 0000b60b .e$..r%.h....... + 36c90: ffbc4851 ff10bc61 000a0645 ff9193c7 QH..a...E....... + 36ca0: 01730908 ffafd641 00d1add9 00a67f50 ..s.A.......P... + 36cb0: fe04e5f7 ff7cb7a7 fecc1c5a fff03baf ......|.Z....;.. + 36cc0: 01f8290b ff33286c fec3b190 007efa96 .)..l(3.......~. + 36cd0: 01415b8a ffde3c78 00efc1f5 ffbdd61d .[A.x<.......... + 36ce0: 00190280 00a29a50 016bdc4d ff4acdea ....P...M.k...J. + 36cf0: ff67a636 00094874 ff2f5ee4 ff19c81e 6.g.tH...^/..... + 36d00: ff59d623 ff8cb03d ffa3e253 00ac824b #.Y.=...S...K... + 36d10: 00112680 ff98895f 019f7cd7 00005d4f .&.._....|..O].. + 36d20: fe9d5294 fffb82c3 ff4cca28 00e07efb .R......(.L..~.. + 36d30: fe3e639d ffe107cf 00c34460 ff9dba8c .c>.....`D...... + 36d40: ffe71383 00fe802a fe3ddb34 0048cb66 ....*...4.=.f.H. + 36d50: ff0b078d 00d5a4ba 00777a1f 0091f285 .........zw..... + 36d60: ffe8fcd0 ffb6d55b fefa048f 004ad7f9 ....[.........J. + 36d70: 016f1ea5 00df09ab 01227be5 ff1a825c ..o......{".\... + 36d80: 012d9b4d ff1c8bc3 004ee03b 00f71188 M.-.....;.N..... + 36d90: 0020796c ffbdfa4f fefce360 003ef126 ly .O...`...&.>. + 36da0: ff7dae3e ff5d6f9b 01cee60a ff28c561 >.}..o].....a.(. + 36db0: fe393100 000dfa41 ff96fb12 ffd26ddc .19.A........m.. + 36dc0: fea6ae05 00bd812c ff9323eb ff8df725 ....,....#..%... + 36dd0: ff048d48 00ff6b67 00045af7 002a2c35 H...gk...Z..5,*. + 36de0: 00f01e02 003f3b04 00244e58 00b4a771 .....;?.XN$.q... + 36df0: ffc147be ffa49ec7 00ac083a 000c214d .G......:...M!.. + 36e00: 00033f41 ff214d99 0166feac ff04dde4 A?...M!...f..... + 36e10: 01fe1e57 ff562992 feefcc8a ff118d6c W....)V.....l... + 36e20: 0087f2bb 007fd0d2 fe0e2d44 003e6049 ........D-..I`>. + 36e30: ff183c51 ff2406aa 001af903 006dd523 Q<....$.....#.m. + 36e40: ff368116 ffe12315 ff383dea 0006d93a ..6..#...=8.:... + 36e50: 00587c8f 00427eec ffb726d1 ff06ee22 .|X..~B..&.."... + 36e60: 006691ae 00d3165f fe990fc4 ffe8542e ..f._........T.. + 36e70: 01922275 ff4afae7 0164861b ffc3bb5c u"....J...d.\... + 36e80: 0070c6aa 002a1c78 004346d1 001f511d ..p.x.*..FC..Q.. + 36e90: 0164a81d 00a0ada9 0075236b ff3b603e ..d.....k#u.>`;. + 36ea0: 01450c51 ffbeef87 0012fcdc ff3adca3 Q.E...........:. + 36eb0: ffbc8989 006d6653 004c0660 ffd2deea ....Sfm.`.L..... + 36ec0: 01cdaeb9 ffd59e3c 00d6f10d 008c81ac ....<........... + 36ed0: 00f2685d 00fb9cc0 001e752b 009e51e1 ]h......+u...Q.. + 36ee0: 00dae87f 00cb1ce2 ff971be9 ff052b75 ............u+.. + 36ef0: ff2f0ef2 00061421 fe2cfb89 fff51f1b ../.!.....,..... + 36f00: fe7dd6b7 00957928 ffd59eba 00e30859 ..}.(y......Y... + 36f10: fe005845 00e187cb 00cbaec9 00b84793 EX...........G.. + 36f20: fe297912 004e055e fef0d6e0 00b40524 .y).^.N.....$... + 36f30: 01e787fb 00d48aa3 fe74f9d2 00bb8158 ..........t.X... + 36f40: fe310813 ff900e3e 00d34c9f 005233d6 ..1.>....L...3R. + 36f50: fee4756d ffcbdf67 010ffc4b ffdc479a mu..g...K....G.. + 36f60: 015b0d17 ff60a88d 0085b6b5 003733fa ..[...`......37. + 36f70: fed4eaea 009e3faf 0134f027 ff24bd9e .....?..'.4...$. + 36f80: 015528d5 fff7b420 011a6613 ff611854 .(U. ....f..T.a. + 36f90: 00de1545 ff7a8b94 01ebd5dc 00ffcbe8 E.....z......... + 36fa0: 00933979 009a07e3 01931635 00e10148 y9......5...H... + 36fb0: fe308652 ff9d3c53 00a94891 00ef6722 R.0.S<...H.."g.. + 36fc0: 002fe9c6 ff041374 ff096ab8 005381b7 ../.t....j....S. + 36fd0: 01e6b024 00486722 0086a2db 009e2af5 $..."gH......*.. + 36fe0: fe609520 00902ca5 fe48efca 000596d7 .`..,....H..... + 36ff0: 0124422a 00afd784 ff56ae56 ff9cc51a *B$.....V.V..... + 37000: fe87e831 0052b667 01b080fd 007ab299 1...g.R.......z. + 37010: 000afaf5 00b218ec 00846a89 00291d28 .........j..(.). + 37020: ff981e32 0026697c 004bbfe6 00aa2b8f 2...|i&...K..+.. + 37030: ff14832c ff170d2c 019bffed ff646d9f ,...,........md. + 37040: ff18b570 006cdc68 0083d337 ffd50c63 p...h.l.7...c... + 37050: ff919798 009f05ee 00089b61 00516c21 ........a...!lQ. + 37060: 00670301 ff226d3e 00b49bfa ffc34720 ..g.>m"..... G.. + 37070: 01914626 00f55f9f 0165e545 00f01c88 &F..._..E.e..... + 37080: 0019e04f ff796e4e 007ca8f8 00f780bb O...Nny...|..... + 37090: feeb9302 00840b4f 010c3a46 ffa308b5 ....O...F:...... + 370a0: ff85894f ff0baa25 ff55f38d ffd7e7b0 O...%.....U..... + 370b0: ffa496cc ff27d7ef fe9c572e ff58a308 ......'..W....X. + 370c0: 00e822ac ff662c42 fe29361b ff5763ec ."..B,f..6)..cW. + 370d0: 01a97b29 002b7234 00288675 001a869b ){..4r+.u.(..... + 370e0: fe5bcfe7 ff268423 fe7d6613 ff85e324 ..[.#.&..f}.$... + 370f0: ff710376 007c0d1d 014a6098 ffce9258 v.q...|..`J.X... + 37100: fedcbfa7 ff5812a2 001764b6 0034751f ......X..d...u4. + 37110: 016a2e51 0007020c 01c95045 00acf6d1 Q.j.....EP...... + 37120: 018d300c 0058d3e0 009fe274 0082627a .0....X.t...zb.. + 37130: 01eaec41 ff09e2e1 017be2cf 003bd659 A.........{.Y.;. + 37140: 01588770 ffcbf45a 01260b31 00ba6c81 p.X.Z...1.&..l.. + 37150: 010f7059 ffcc2e65 fe2dcc7f ffddff4f Yp..e.....-.O... + 37160: ff124933 ff652a7f 00ca15f1 0007e3a0 3I...*e......... + 37170: 00ec3269 ffc5344f 01d0ca68 00100fb4 i2..O4..h....... + 37180: ff4ec565 00cb4d62 01f1b929 007cc123 e.N.bM..)...#.|. + 37190: ff179b23 00c035cf 01a37d0b ffb99ef9 #....5...}...... + 371a0: 00308304 ff6f5d15 01e7793d ff24c845 ..0..]o.=y..E.$. + 371b0: ffb930b9 ff15ee6f ff193227 ffa3d763 .0..o...'2..c... + 371c0: ff1ed457 ff0593a4 01230680 ff6edf6c W.........#.l.n. + 371d0: 00b24cc2 00b4654a 00302ff3 ff2b19ae .L..Je.../0...+. + 371e0: 01fdad52 ffc07236 005b3728 ffb06cd7 R...6r..(7[..l.. + 371f0: 0007380b 004ce9e0 feca62d1 007d19f2 .8....L..b....}. + 37200: fe5dc12c 00b108cb 0013b087 ffd54770 ,.].........pG.. + 37210: 01b03bce 001a4304 fed58f0e ffd0372a .;...C......*7.. + 37220: 0078433c 00a315c1 0073a463 0076140a ..n.......6... + 373d0: feb6ccdd ff419eb3 00039d51 009fdac2 ......A.Q....... + 373e0: 0000dfaa ff200be0 0062c526 0025a4a8 ...... .&.b...%. + 373f0: 01075817 006ebaa4 00862460 00e5f2ea .X....n.`$...... + 37400: 001379fa ff70fef2 015e2f03 ff06ef09 .y....p../^..... + 37410: fe998651 ffa8fdd6 00e07c43 004a5ff5 Q.......C|..._J. + 37420: fe2c1e1c ffdc6d01 005959b2 004c24fc ..,..m...YY..$L. + 37430: ff2ec618 006f4d4c ff88ea86 001d5e27 ....LMo.....'^.. + 37440: ffea48b9 ff874446 fe0766e7 008ce74d .H..FD...f..M... + 37450: 013a2fa7 ff766194 01e11b10 ff8fcea6 ./:..av......... + 37460: ffd6b26e 00a283b4 01e18d8f ff4eda0d n.............N. + 37470: 01219972 00cc6862 017572af 004bcea7 r.!.bh...ru...K. + 37480: 0153c4ca 0043403a 016f2f8a ff80f7c4 ..S.:@C../o..... + 37490: fee0e089 00cf709e 01ff649a 006b2586 .....p...d...%k. + 374a0: ff4f80c6 ff9bd17f feb9fea3 00f30e3c ..O.........<... + 374b0: fe70db1f 0041d91d fe740dc8 ffc43c7b ..p...A...t.{<.. + 374c0: feb83be0 00c459f2 fe4b107b 00ce1095 .;...Y..{.K..... + 374d0: 0130fe45 ffdf74e7 0141a0d1 006250c8 E.0..t....A..Pb. + 374e0: feb8c225 00223f94 ff41f08b ff8490d9 %....?"...A..... + 374f0: fe2d2638 00d278c7 ffa6b16c 0004dea0 8&-..x..l....... + 37500: fe777edc ffa06ba5 01f8dc52 0088aff1 .~w..k..R....... + 37510: ff178d90 00548aa9 ff4e89a0 ff5076e2 ......T...N..vP. + 37520: ff841b34 ff8b603f 0027fa98 000f9bbc 4...?`....'..... + 37530: fe9633e8 ffe80f28 ff09e5f0 ff1baf89 .3..(........... + 37540: 0161494b 000bd4da 01a20587 00d5b96b KIa.........k... + 37550: ff6bf902 0046f228 0019c8db 000d9d19 ..k.(.F......... + 37560: ff505243 ff17f9c4 00951491 00924832 CRP.........2H.. + 37570: 01944c5e 0041fb18 0017c01f ffc9d4b8 ^L....A......... + 37580: 01a2e97b 0048adf7 fedb57a2 0059867e {.....H..W..~.Y. + 37590: fe0c0b9f 001d69a6 01e41b49 ffb77871 .....i..I...qx.. + 375a0: 016da342 ff0b8fd4 01a8e79f 005a80ff B.m...........Z. + 375b0: fe3a0e39 ff0a3459 01a308fd ffd29100 9.:.Y4.......... + 375c0: 0155810a 001bb52e fea08867 ffd1bc7e ..U.....g...~... + 375d0: 006f2322 ff18dbd7 fed60bd4 00760565 "#o.........e.v. + 375e0: ff85c5e8 ff6da7df ff5650ed 005e8b46 ......m..PV.F.^. + 375f0: 01bfc19e ff330f9b 0073be0f ffcf874e ......3...s.N... + 37600: 011b0af9 00e97db5 fe0dac5f ffa1d5aa .....}.._....... + 37610: ff8aec27 ff575d5f 005f80be 00ce0f7d '..._]W..._.}... + 37620: 009f96a6 ff9e0fe3 ff789ece 00808d2a ..........x.*... + 37630: 0178b265 00836d9c fe2c0eda ffcea8f7 e.x..m....,..... + 37640: 001c70d4 ffe41170 0125105a 006cdec5 .p..p...Z.%...l. + 37650: ff53cffe fff35a09 00acf4f3 ff73581a ..S..Z.......Xs. + 37660: 007a74cd 00c1e6bf 010b64b4 ff6025d9 .tz......d...%`. + 37670: 009c4e9a ff1feaeb ffb2b2ce 00fbc095 .N.............. + 37680: 0087fab6 006916f6 ff6dc17c ff95d202 ......i.|.m..... + 37690: 00aa11a9 ff6e6000 01080975 ff287b32 .....`n.u...2{(. + 376a0: 0063bdc1 00a0e322 fe465030 00ec33d3 ..c."...0PF..3.. + 376b0: fef57a2d 0008ae2c ffe925ad 00ab419e -z..,....%...A.. + 376c0: ffd7457a ff02505a fe606a83 008772e3 zE..ZP...j`..r.. + 376d0: fe7731cd ff403eb0 ff113352 fff314f1 .1w..>@.R3...... + 376e0: fe080d82 fff3d980 fe011ba2 00f1765a ............Zv.. + 376f0: fff6c6f6 ff761037 009d9fc8 000111a3 ....7.v......... + 37700: 00796b8c ff76a155 00950026 00ee2f9c .ky.U.v.&..../.. + 37710: 01a6a609 ffb5624b 00194a32 002f0f42 ....Kb..2J..B./. + 37720: 009fe18b ff8e034c 00b8ee0e ff35cf0b ....L.........5. + 37730: 01bac0b7 ffae20ab 01dd4cbf 00dbaaf7 ..... ...L...... + 37740: fe32ac19 00e909d9 ff447ecb 00305cb7 ..2......~D..\0. + 37750: 01b7a77f 00fe3141 017f3f10 ffaa15fe ....A1...?...... + 37760: fe7fe03b ff3f3016 fe824e1b 001dc328 ;....0?..N..(... + 37770: fe7084fa 0090cb23 00a8a968 ff1efdcf ..p.#...h....... + 37780: fe262868 0058e45e ff8010ce ff7a37d4 h(&.^.X......7z. + 37790: 00ea16df 007fc5df 01b5b5fd 00766691 .............fv. + 377a0: ff2499ec ff48d9d4 fe182614 003e3e8a ..$...H..&...>>. + 377b0: 00048c98 ff63dce6 ffd41501 00e7c994 ......c......... + 377c0: fe097bf4 00d2ab00 ff253a33 ff0eff01 .{......3:%..... + 377d0: fe91b7f4 00a6f200 00844a16 0029d879 .........J..y.). + 377e0: fe72c35f ff971885 ffe7e29c ff4d05f7 _.r...........M. + 377f0: fe7394f6 ff515ce1 fef650de ff597baa ..s..\Q..P...{Y. + 37800: 008dc74a ff08141d ff46888a 005c4b5d J.........F.]K\. + 37810: fe3193dd 00e27e34 00177ce5 00b5092e ..1.4~...|...... + 37820: 013440cd 001cfe83 00d49e97 004e4083 .@4..........@N. + 37830: 00ab19ce 008be600 fe6efdbf 00a7f767 ..........n.g... + 37840: 01282840 fff1a52a fee44b3b ffbdf37c @((.*...;K..|... + 37850: ffb25cc4 ff568c82 0138598d ff05c693 .\....V..Y8..... + 37860: fe9ef8cb 008da290 00e2ac0b ff152a82 .............*.. + 37870: ff8fa701 ff242490 fea45830 00dcaaa8 .....$$.0X...... + 37880: 00d64762 004fd05b 01c94c9f ffd62aa6 bG..[.O..L...*.. + 37890: ff00ff45 ff7d8006 008c01be ffda5392 E.....}......S.. + 378a0: 0148eed7 00357f7a ffa574bd ff420854 ..H.z.5..t..T.B. + 378b0: ffd003d6 00856ed5 012ca8c3 0045e79e .....n....,...E. + 378c0: fec840a2 00683a5b febb3ab6 0088e4f9 .@..[:h..:...... + 378d0: fe4c86cb 00e9dd63 fed6fe4b 009a4550 ..L.c...K...PE.. + 378e0: fef89840 ffca88ec fe99699d 0014af95 @........i...... + 378f0: ff132316 00e9797c fec6faba 008be584 .#..|y.......... + 37900: ffae5089 00447da5 fe94ca90 00f8efeb .P...}D......... + 37910: 0076b887 ff115e65 fe46487a 00928245 ..v.e^..zHF.E... + 37920: 01f8de7f ff767f45 fed7521e ff134abc ....E.v..R...J.. + 37930: fec2a7e5 ff421975 fe38ea41 009c16d5 ....u.B.A.8..... + 37940: fe5d3b97 ff1b1c2d ffa47eba 00ef0620 .;].-....~.. ... + 37950: 0163727f ff0234db fea66063 ff7ebe3e .rc..4..c`..>.~. + 37960: 01a8de6c 00aee24b 00c7e2e6 ffda753c l...K........ + 37a40: fe6b2814 ffc79a8a ffe2df5e 0026ab9d .(k.....^.....&. + 37a50: fe19b1a3 ff03762d 0117de0e ff51bed1 ....-v........Q. + 37a60: 01e87b76 ff65d50d fe7b377b 00a5f61b v{....e.{7{..... + 37a70: ff4c6332 ff20d68c ff434161 001c0c18 2cL... .aAC..... + 37a80: 014e56ae 0060f740 004387a0 fff33742 .VN.@.`...C.B7.. + 37a90: ff60cc93 ff21061a 01533362 ffd0d599 ..`...!.b3S..... + 37aa0: ff36b802 000bda19 fef64331 ff489512 ..6.....1C....H. + 37ab0: 0048190d 00d64f2a 0126042a ff908b1b ..H.*O..*.&..... + 37ac0: 0017bb95 0084a412 feb854f5 ff68c678 .........T..x.h. + 37ad0: 0060da7e ffea7538 fed61d0d ff0a2f44 ~.`.8u......D/.. + 37ae0: fe849aa7 00c62698 ff59b242 ffab2ec8 .....&..B.Y..... + 37af0: ff53630d fffdbbd2 012a2daa 007cd18a .cS......-*...|. + 37b00: 008da2d6 009ce60c fe702466 00439303 ........f$p...C. + 37b10: ff7bd734 ff36abe9 003e8962 ff27daf7 4.{...6.b.>...'. + 37b20: 00ecdae7 007fbff7 005492c3 ff5cb0a5 ..........T...\. + 37b30: ff5ed413 00e34a11 01992858 ff0193c6 ..^..J..X(...... + 37b40: fef543ce ffda03f0 ffd58d3d 006ab761 .C......=...a.j. + 37b50: feebe8c3 009a565f fecd30d1 fff1d176 ...._V...0..v... + 37b60: 01df78f0 009f1dd5 ff937fa3 005dda0d .x............]. + 37b70: fe441855 ff501446 018c05bd fffe6152 U.D.F.P.....Ra.. + 37b80: ffbf6363 ff855484 ff74da6b 002e7a70 cc...T..k.t.pz.. + 37b90: 00201169 ff3fa0c2 0127de44 005cfdd8 i. ...?.D.'...\. + 37ba0: ffcd69b1 00c3c995 ff0be12a 0073a228 .i......*...(.s. + 37bb0: 00510709 00dbdaa5 fe0016b4 fffc921d ..Q............. + 37bc0: 01e1cf92 006087b4 0070a31f ffdb0bb1 ......`...p..... + 37bd0: fec10c85 00324e2b 01797141 ff06d93b ....+N2.Aqy.;... + 37be0: 01185e6e 006fac70 00600f07 007b5524 n^..p.o...`.$U{. + 37bf0: ff159647 00bc49d0 01a70bc0 0022f5d5 G....I........". + 37c00: 005ce609 ff278ea2 001b5ad7 00596162 ..\...'..Z..baY. + 37c10: 00d34f5e 00f09d5a 017edc5f 00e2b066 ^O..Z..._.~.f... + 37c20: fee01e24 007f1f23 0173e8e7 00825355 $...#.....s.US.. + 37c30: fff549d2 ff728f2f 00c54144 ff3e483b .I../.r.DA..;H>. + 37c40: fead85b7 ff76795d ff51b13b ffad45ea ....]yv.;.Q..E.. + 37c50: 00b180cd 0033f4dc 01d1f41a ff4dde49 ......3.....I.M. + 37c60: fe6008a3 00d39596 01cbfe9e 008b7f36 ..`.........6... + 37c70: 003be0a1 ff166d04 ff2d2ade ff6692d0 ..;..m...*-...f. + 37c80: 00bb8eec fff5cd32 fe594a0a 008e4f30 ....2....JY.0O.. + 37c90: ff824cde 003fa61e ff0d0cec 00f4b831 .L....?.....1... + 37ca0: 006671bb 00fd65da feb63999 002a9620 .qf..e...9.. .*. + 37cb0: 0192c619 0038f1ed 0005448c ffaca45b ......8..D..[... + 37cc0: feba914e 00cd3443 0181cfdb 0011736d N...C4......ms.. + 37cd0: 013a8f36 ff78f815 001effb3 ff42ecc1 6.:...x.......B. + 37ce0: ff07ff01 ff30c0fd 01d94513 ff00d603 ......0..E...... + 37cf0: 01926540 ff237ddf ffb349eb 00e2a7f9 @e...}#..I...... + 37d00: 010aafe1 003aa261 01ab706a ff05ac54 ....a.:.jp..T... + 37d10: ffb28c85 008ef586 ff7d5a61 ffb9cbba ........aZ}..... + 37d20: ff174ddf 006a5cc0 ff73c60f 00f898d9 .M...\j...s..... + 37d30: ff78b2ab 003586e4 01c136b0 0035fbfa ..x...5..6....5. + 37d40: 01640ad5 006ac722 fef41f97 ff57e0ac ..d.".j.......W. + 37d50: ff17ed0e ff1a55fd ff74277f 006468ac .....U...'t..hd. + 37d60: ff460efb ff8ad0d4 00fad3fd 00a531b0 ..F..........1.. + 37d70: ff7b4c0f ffa0da25 0110875c ff727e0a .L{.%...\....~r. + 37d80: ffe00546 008df9f7 013c1444 ffbdd2f1 F.......D.<..... + 37d90: 01bbd9c3 00710397 00ae5c97 ffb23ee7 ......q..\...>.. + 37da0: 00e1b7db ff211717 0050b5cd fff8b839 ......!...P.9... + 37db0: ff01b443 ff5d7b5a ffa20027 ff34f860 C...Z{].'...`.4. + 37dc0: 008c4254 ffe47f22 01078ac2 00bc6ea6 TB.."........n.. + 37dd0: 019b1115 ffc6be9a ff3b50d6 008f0712 .........P;..... + 37de0: 01e21d48 00f9d9c7 0147a1e8 00c9be95 H.........G..... + 37df0: fe5fafd9 ff439371 ffc78f8a 0001cc7f .._.q.C......... + 37e00: 0153b61d ff9be6ce 003cccba ff557d0a ..S.......<..}U. + 37e10: ff1960e8 fff759ff 01affed5 0051c1e8 .`...Y........Q. + 37e20: fe9c2b1c 0008450c 00f81893 0031c612 .+...E........1. + 37e30: 00233c86 ff12f676 fefe5831 ffba15e4 .<#.v...1X...... + 37e40: 017041b6 ff0116db ff347e16 ff3135bd .Ap......~4..51. + 37e50: 008f1970 ff377f26 fea365e2 ff3d85d0 p...&.7..e....=. + 37e60: 01ae4589 ff9176be ffdb623c fff50dd9 .E...v...!. + 37f80: 01d37308 ff8061a2 fe17b807 ffa81c74 .s...a......t... + 37f90: ff978af8 00f0f462 008276ba ffebf872 ....b....v..r... + 37fa0: 01c8ad69 ff477ca0 01a4245e ff9241af i....|G.^$...A.. + 37fb0: feaaf1ee 00c5c6ca fe8a47e4 ff6df62d .........G..-.m. + 37fc0: 009e34c2 00b0bb85 fe9afc53 ffddbd59 .4......S...Y... + 37fd0: 00fc49aa 007d3a94 fe334424 ffb1452a .I...:}.$D3.*E.. + 37fe0: ff564ca8 ffcc6426 00233526 006113af .LV.&d..&5#...a. + 37ff0: fffdeee1 00875151 feff1bd2 006b49eb ....QQ.......Ik. + 38000: 0073cf08 00887f52 fe156354 008813cf ..s.R...Tc...... + 38010: 0065a464 ff4dd050 ffedcf84 ff0f030f d.e.P.M......... + 38020: 006ea621 ff555f9c 016fb925 ff236a96 !.n.._U.%.o..j#. + 38030: 004c97a6 ff875772 0040c29f ff1f7a0c ..L.rW....@..z.. + 38040: fe6507e8 006277ad fedc479a ff3539bf ..e..wb..G...95. + 38050: ffa0e8a8 ff6320e0 00a59cda 00a39997 ..... c......... + 38060: 01940dd9 005971c5 fea11c95 001e17cf .....qY......... + 38070: ffe38469 ff5ee636 ffccad85 ff9db75c i...6.^.....\... + 38080: fefc9058 005a2166 0003619f ff9bdab5 X...f!Z..a...... + 38090: 007772f0 ff35d66a 0173bea5 ffe15b98 .rw.j.5...s..[.. + 380a0: ff2c6a58 00713dd0 007c3497 ff9c1bbf Xj,..=q..4|..... + 380b0: 01ec366e ffa61e0e 01cf7f27 001cc7e5 n6......'....... + 380c0: febce4bc 00eb9d64 01b7daf6 ffc1166b ....d.......k... + 380d0: 005fa0ce 0093ef4c 0075a1cf ff02a633 .._.L.....u.3... + 380e0: fe0a7534 ffe33849 00e1c198 ff885e84 4u..I8.......^.. + 380f0: 00d1bf65 ffe56b20 01b42bc6 0076d264 e... k...+..d.v. + 38100: ff994372 ff1a5817 015c9a59 ff8c78dc rC...X..Y.\..x.. + 38110: ffcf7290 fffa73fc 0048ce22 ff7f858a .r...s..".H..... + 38120: 017cb208 00614b57 fe5ce50f ff8343f0 ..|.WKa...\..C.. + 38130: fee37b76 ff687892 01ffd591 ff46bb81 v{...xh.......F. + 38140: 003677db 00ad1301 0194962d 004853f8 .w6.....-....SH. + 38150: 01a9e9cb 00386b8e 0126f9f7 ff50f22d .....k8...&.-.P. + 38160: 0067e91e 00465260 006fc917 ff1e2751 ..g.`RF...o.Q'.. + 38170: ff4eb7a1 ff21eac2 fe8ce344 0074ced8 ..N...!.D.....t. + 38180: ffeb1b46 004f9068 fe5de6a4 009c87d6 F...h.O...]..... + 38190: fef2bb9a ff8314bc 00ae6d24 00f1709f ........$m...p.. + 381a0: 01956e05 00daa524 01131da6 00492eb2 .n..$.........I. + 381b0: fe202b5d 00edbdf8 008d9b66 ffc35dc9 ]+ .....f....].. + 381c0: fffd8bf1 ff626f0f fea3416c ffbe4f9b .....ob.lA...O.. + 381d0: fec1ae49 ff3028f6 fe0b586b ff5561ca I....(0.kX...aU. + 381e0: ff12ccfd 0042f271 fec2a06e 00ba12d0 ....q.B.n....... + 381f0: 003c1551 ffa768bc fe61a67c 008e85d2 Q.<..h..|.a..... + 38200: fe89f238 00826f29 013a976f ff8dd56f 8...)o..o.:.o... + 38210: fff1acb7 ffc40626 ff7b07b9 00f60b2e ....&.....{..... + 38220: 017769f5 ffa1020f ff2dce08 ff4aca12 .iw.......-...J. + 38230: 01737c53 009d8dd4 fed10853 ffe80f8b S|s.....S....... + 38240: fead36ac 0084f732 00d5bdd6 0069b890 .6..2.........i. + 38250: 00f8fedf fff093ff 0048bc17 00363307 ..........H..36. + 38260: feb419bc ff00b4dc 0014a053 fff3bda3 ........S....... + 38270: ffc2d13a 003c4957 0031186a 00dcf9f5 :...WI<.j.1..... + 38280: 00a7ad16 ffc30b76 00ed7e13 ff259f6e ....v....~..n.%. + 38290: 002f523b 0056bbb4 01d094bc ff852564 ;R/...V.....d%.. + 382a0: 00c17007 ff9cbc81 ff816a54 00cae185 .p......Tj...... + 382b0: ff6fec0e 00651428 fe31acac ff4a3633 ..o.(.e...1.36J. + 382c0: ffb8b9fb ffe09b5d 01e0f9b4 0092b2e6 ....]........... + 382d0: fe363948 00b83eb2 0048cd77 fffdefb9 H96..>..w.H..... + 382e0: 00da0f3d ff3843c4 01ab20ea 00e4db2e =....C8.. ...... + 382f0: ffea6cd0 ffe83f14 01c735a5 ff05e485 .l...?...5...... + 38300: 006bcd34 ff8cee4a fedb9c96 ffb2acef 4.k.J........... + 38310: fedfbdfb ffd38e20 018a0fda 0050c4f1 .... .........P. + 38320: fe62241c 00c7ea16 ffdced3d 002539f6 .$b.....=....9%. + 38330: ff8e118e 001a3e9d fe5fee2b ff06d903 .....>..+._..... + 38340: 01f019d5 ffaedc27 fe30cd9a ffc00d13 ....'.....0..... + 38350: fe3622f4 009b108c fe05b5f0 003cc19b ."6...........<. + 38360: ff0480a6 ff389124 00dbf096 00913378 ....$.8.....x3.. + 38370: 012a9952 0092ec8c 01f85c6b 00030abd R.*.....k\...... + 38380: 00f2883f 001827d3 01a1ca13 ffba1bad ?....'.......... + 38390: feefccd2 ffa2d129 ff9ffeb6 003474ac ....)........t4. + 383a0: fede67c3 003b45cd 01291635 00c230da .g...E;.5.)..0.. + 383b0: 00f2d250 00cfbcd2 fea1a1bb 000111d8 P............... + 383c0: 0071e188 003fb8fa fe621edf 00a2a84d ..q...?...b.M... + 383d0: 00af353b ff0ac913 00c2e08b ff9ac193 ;5.............. + 383e0: fe0cbdd4 ffaec801 01718532 005ab35e ........2.q.^.Z. + 383f0: 0087b6ad 0071b15e ffd7592b ff6afc88 ....^.q.+Y....j. + 38400: fe53867b ff42f505 01273152 00e002dc {.S...B.R1'..... + 38410: 00b18161 00593b4d 019b1d3d ffdcabcb a...M;Y.=....... + 38420: 008b4e5c ffb52191 018d18a9 00b39637 \N...!......7... + 38430: ff503c8b 006127da ff6b9302 0048f83c .. + 38730: fe1278ec ff637b62 fec2c9a8 00d6ea2e .x..b{c......... + 38740: ff3185bf 0077a963 0123bbbe ff2d1573 ..1.c.w...#.s.-. + 38750: 004883f9 ff7b0670 feb531d6 0022e9a6 ..H.p.{..1....". + 38760: fe66c55c ffcde4fd 01c93b03 002e622a \.f......;..*b.. + 38770: ff2325db 0026c3a9 01c17c5e 00df2b9c .%#...&.^|...+.. + 38780: fe85485f 00bfce78 ffefc57a ff4fbbb1 _H..x...z.....O. + 38790: 01022efe 00bea7fa 00138154 ffa671cb ........T....q.. + 387a0: febd1ff9 ffca9d48 ff4947d0 004818cf ....H....GI...H. + 387b0: 0112100a ff4c51d2 ffc0d058 ff6bf37e .....QL.X...~.k. + 387c0: ff788dee ffea79c7 ff3b0c89 ff7bdc24 ..x..y....;.$.{. + 387d0: fe3cb394 001d0cf0 01610042 ff261e24 ..<.....B.a.$.&. + 387e0: ff5d0173 ffe76760 013b9ec5 00f0a4c0 s.].`g....;..... + 387f0: ff39caca 0030ae18 019b4d59 00d74c2a ..9...0.YM..*L.. + 38800: 00e997f4 00513017 fe347fef ff2582e3 .....0Q...4...%. + 38810: 015d74f8 0076847c 01c0fead ff53eb06 .t].|.v.......S. + 38820: 01e7af6e 00b61cfb fe5df981 0080b854 n.........].T... + 38830: 003eb54c 00ba80af fe883564 00e21d6d L.>.....d5..m... + 38840: 013ae9dd 004a6314 00a01600 00150d86 ..:..cJ......... + 38850: ff373409 008c5911 003b22af ff77a554 .47..Y...";.T.w. + 38860: ffeae2e0 ffa64807 01ff737b 00f6d612 .....H..{s...... + 38870: 014707fa 00b9dcd9 ff4c23d4 00af7d26 ..G......#L.&}.. + 38880: 00d261bd ff2cee72 fea9bc29 009aba2d .a..r.,.)...-... + 38890: 00165c51 00c1a084 ff62d079 ff2c510d Q\......y.b..Q,. + 388a0: 00529ccb ff153a47 febf72d0 00932632 ..R.G:...r..2&.. + 388b0: 00c3d89a 00121965 ffd7fa3c ffeb84e9 ....e...<....... + 388c0: 018eaf67 005c0e10 fe6e1f8d ff2df1ee g.....\...n...-. + 388d0: 01efd999 ff2fa861 011055f9 ff3eaf1c ....a./..U....>. + 388e0: 0036fe39 007ee7de fe752da6 ff60bd12 9.6...~..-u...`. + 388f0: 00324ce4 005ef4c8 017898c6 ff452244 .L2...^...x.D"E. + 38900: fea0410c 005a1365 ff78c5a7 ffb93644 .A..e.Z...x.D6.. + 38910: 00bcda29 0030a871 01bd6958 ff20521a )...q.0.Xi...R . + 38920: 01a45db9 ffedf0e4 0035b642 ff5cc5ab .]......B.5...\. + 38930: 01e9096b ff9078c7 ff0a314e ff69aa6d k....x..N1..m.i. + 38940: ff1f045a ff71f41c 000b3a4a fff6dc3e Z.....q.J:..>... + 38950: fec89a79 ffb2d290 0181397e ff0efa2b y.......~9..+... + 38960: 011c6f65 fff1562f ff96463d ff054935 eo../V..=F..5I.. + 38970: 009e1a1e 00561ad1 004aed8a 00bc5fa4 ......V...J.._.. + 38980: fe1d3c8e fff874a2 00a0afbb 00101297 .<...t.......... + 38990: fe416fd1 ff2786cb ff316c58 ff471a83 .oA...'.Xl1...G. + 389a0: fed71bdd ff5d6968 fe1fec1f ffd30087 ....hi]......... + 389b0: 016e7f8f 00e549d4 fea743e9 ffd001c3 ..n..I...C...... + 389c0: ffdd1184 005ad933 ff32eb43 008fd2df ....3.Z.C.2..... + 389d0: 018235b3 00c66ae9 ffdcadd9 ff18e570 .5...j......p... + 389e0: fe5d9aaf fff6cb47 ff854230 ffe68803 ..].G...0B...... + 389f0: fe71dd17 00d56feb fe5f78aa 0002ddfb ..q..o...x_..... + 38a00: fe9e822d ffd95e69 feb434f2 ff2d44d5 -...i^...4...D-. + 38a10: 001c2668 004c9ef4 ff60c8a1 ff0d35cf h&....L...`..5.. + 38a20: 009443bb 00f836aa ffb2a277 000b1453 .C...6..w...S... + 38a30: 01c02a2a ffa39f92 006fe8b7 ff15e54d **........o.M... + 38a40: 008f3547 00224c1b ff2f88f6 ffb627db G5...L".../..'.. + 38a50: 01c9e05c ff0e8e13 fff1b645 00f576a3 \.......E....v.. + 38a60: 016a6d09 fff7b5aa ffee2f4e ffb0d254 .mj.....N/..T... + 38a70: 008b6bd5 000b2627 00961548 00458248 .k..'&..H...H.E. + 38a80: fe9b4dcd 0015858e feac6f47 ff3b2ae2 .M......Go...*;. + 38a90: 01d700b3 00f18021 010dfcea 00084fb8 ....!........O.. + 38aa0: ff491e6e 00bd8df6 01dacfaa ff459a4a n.I.........J.E. + 38ab0: ff31f68a 0064209b ff694a7d ff3d555a ..1.. d.}Ji.ZU=. + 38ac0: ffb1e523 ffc17d3e 01bc5699 00d47849 #...>}...V..Ix.. + 38ad0: fef67bd1 ff26d187 012c3a97 ffd6455c .{....&..:,.\E.. + 38ae0: ff580c0e ffa699fc ff70cffd ff534e3c ..X.......p..{. ... + 38b80: 003ebfe1 0099465d 01682ab5 ffe0bf16 ..>.]F...*h..... + 38b90: ff8cc8c8 0025eaf9 008d3995 ffd038c3 ......%..9...8.. + 38ba0: ff4682fe fff0ad20 00c7dc1d ff73646e ..F. .......nds. + 38bb0: 00f9e584 ffdfe9e4 fed1d825 ffd1b1b2 ........%....... + 38bc0: fea52db7 007261e0 ffa86189 00acdee1 .-...ar..a...... + 38bd0: 01310da5 ffccebd2 fe1c04fc 0097a046 ..1.........F... + 38be0: fe34bee8 ff5df853 014dd73e ffb3afaf ..4.S.].>.M..... + 38bf0: 004232a0 00d03079 ffd1a93f 00c8d200 .2B.y0..?....... + 38c00: 012cbbe0 0052a249 ff8fb009 ffc14c13 ..,.I.R......L.. + 38c10: 01a73b1d 009a2b18 00bebe1c 0081bc8d .;...+.......... + 38c20: ffcbebe8 ff6d00ea 009f4136 ffe8583c ......m.6A..{...d...... + 38ff0: 0021c58f ff2c3b9b 01f05d96 ff57037f ..!..;,..]....W. + 39000: 01cf475f ff0155a7 ff7498bc 0017170a _G...U....t..... + 39010: 015dc389 00616236 ffa800f0 007fbc94 ..].6ba......... + 39020: 00976b86 00abfd4c 00c0845a 00361692 .k..L...Z.....6. + 39030: fe3642e0 ffe5bae6 00c4b627 ff82fb94 .B6.....'....... + 39040: fe6c8341 00a00180 fea731a9 ff94fec7 A.l......1...... + 39050: 008306fb ff81febb 003e5255 ff3a17b2 ........UR>...:. + 39060: 000584fe 0027d5a4 fe92fc86 ff513525 ......'.....%5Q. + 39070: 0052869b ffeea7cd ffb42d5e 00a12884 ..R.....^-...(.. + 39080: 01706ffe 00d94b36 01dde6b3 ffbf5eeb .op.6K.......^.. + 39090: 0130f317 ffcb91ca ff2a7627 00fd8d75 ..0.....'v*.u... + 390a0: 00de00fe 0032fb2b 01eaa936 00d04450 ....+.2.6...PD.. + 390b0: fef3cb94 00870791 0000fe06 007fb9fc ................ + 390c0: ff810862 ff482326 01dc24d3 00591a28 b...&#H..$..(.Y. + 390d0: fec540a8 ffefde03 fed75302 00699fb4 .@.......S....i. + 390e0: 00c2733a ff6a74ba ffdbf7e5 00c17681 :s...tj......v.. + 390f0: 01b7aeca 0048a1a6 fe936bc9 004a88ed ......H..k....J. + 39100: 016ae6e9 00a86f69 011ee040 0003e501 ..j.io..@....... + 39110: ffaf9766 ffe4eec2 00d4fafe 0079edbb f.............y. + 39120: 0160fb43 000b1ec5 00cc5fb7 008a59cd C.`......_...Y.. + 39130: 0125dd40 ff1edfff ffd330b2 ff5ac8f1 @.%......0....Z. + 39140: ff60d1a7 00dd8239 ffc8722e 0042b83d ..`.9....r..=.B. + 39150: fe18b637 0021b66e ffe8beab 001f5e72 7...n.!.....r^.. + 39160: 0008dd12 00fee72f 005370ff ffd70f76 ..../....pS.v... + 39170: fe2819ad ff1fc1c0 ff9215ee ff76c1ab ..(...........v. + 39180: fe35ea65 0070d483 016bc059 001bd008 e.5...p.Y.k..... + 39190: ff0fd9b5 00e895e7 007eec8c ffc70990 ..........~..... + 391a0: feb54f0c ffcab693 ffb66d13 00e1d431 .O.......m..1... + 391b0: 00cba34a 0094e9af 0033701a ff09c1c1 J........p3..... + 391c0: 00f9870f 0082e396 01db00cc 00cdf218 ................ + 391d0: ff75d0ee 0070f416 0022e51a ffbc5025 ..u...p...".%P.. + 391e0: fece2d26 ffe15af0 ff2f031d 004ce02a &-...Z..../.*.L. + 391f0: 00a7f3ba ff0f8420 007d3305 0018878b .... ....3}..... + 39200: 00dbf106 ff85e5ac 0032d6f6 ffcf0be7 ..........2..... + 39210: 01537ebf ffaaa3b4 011838f5 ffd3a4b2 .~S......8...... + 39220: 01ca1003 ff763962 fe59838d 00183321 ....b9v...Y.!3.. + 39230: ff5b95f3 000e34fd fe43a923 ff581e31 ..[..4..#.C.1.X. + 39240: ff241bb3 00b78ca5 0097bd3a 00001f58 ..$.....:...X... + 39250: 0042a94b ffc76542 01c7d818 ff1ac479 K.B.Be......y... + 39260: fecb4f0e ff51e2f0 ff0a1c5e fff0c153 .O....Q.^...S... + 39270: ff83c1cc 00560f5e 009d28da 00d1c133 ....^.V..(..3... + 39280: 00b1f200 00f7b966 00746d9e 005b8726 ....f....mt.&.[. + 39290: 0095afdf ff0142dc 00e83c56 ff256019 .....B..V<...`%. + 392a0: 01a27ae1 ffa8bbd7 002e9d9e 00a2ab38 .z..........8... + 392b0: 0165f0e8 0009167a ff150933 ffee1935 ..e.z...3...5... + 392c0: fee81ed9 0094a97d 0066e80d 00250994 ....}.....f...%. + 392d0: 018d61a5 002983e4 fff30fde 001112fe .a....)......... + 392e0: 01ed3c06 0071036a 00bd843b 001e705c .<..j.q.;...\p.. + 392f0: 00d5d069 ffb35430 fee779bb ff6dd81b i...0T...y....m. + 39300: fe6bdda2 ffc3ef49 ff391ffa ff598795 ..k.I.....9...Y. + 39310: 017317b9 ff9da303 00fa7012 ffbb3919 ..s......p...9.. + 39320: 00a460a1 00f3102f fefb8d0c ffb8ea43 .`../.......C... + 39330: 00a11229 ff6006af fe34aca0 ffb7b018 ).....`...4..... + 39340: 0155c1c6 ff89797c ff723297 ff3ccbdc ..U.|y...2r...<. + 39350: 0105efcf ff6b2600 fe5eee37 005e9846 .....&k.7.^.F.^. + 39360: 014ddcd5 ff451178 ffbea455 0051eacb ..M.x.E.U.....Q. + 39370: fe253126 007c903d fe314e89 0030f7a8 &1%.=.|..N1...0. + 39380: 00fca45f 0087a969 0086e4fd 004ba640 _...i.......@.K. + 39390: ff144951 000ad2cf ff966aea ff5a225e QI.......j..^"Z. + 393a0: fe399ffe 006385dc feb4938b 00b91718 ..9...c......... + 393b0: ff1e3929 004c61bd ffdfbb41 ff25ace0 )9...aL.A.....%. + 393c0: 015f3e22 00f090e7 fe7e6a4d 005b9840 ">_.....Mj~.@.[. + 393d0: 009b621d ff35fbe2 ff05d3ea ffdecb90 .b....5......... + 393e0: feddb0a4 0018e705 00cd7ab3 ff860124 .........z..$... + 393f0: fe97467d 00fce461 fe1781ac ffd15a30 }F..a.......0Z.. + 39400: 0152e096 001e8654 002ec4f1 ffea7167 ..R.T.......gq.. + 39410: fe79652e fffa7c28 fef22d87 ffa8f909 .ey.(|...-...... + 39420: ff836c8c 00aba38f ffc7ad32 ff8ede58 .l......2...X... + 39430: 009e5fc8 ffa3c08e 00877507 00167c6f ._.......u..o|.. + 39440: fe410cec ff412644 00feaee3 0026f5f4 ..A.D&A.......&. + 39450: ffd032f0 00fa3fa1 00efd13c 0013237a .2...?..<...z#.. + 39460: fee6210e 00719f02 ff7f146a 0060cde4 .!....q.j.....`. + 39470: feaed289 ff90d4b4 019a6259 008b5822 ........Yb.."X.. + 39480: 0170a2a7 00c56e41 00a925f1 ff833842 ..p.An...%..B8.. + 39490: fe53c90a ffbbfd85 fe2d70b1 0000fbc4 ..S......p-..... + 394a0: ff97fac4 ffd6e8ee 00cdd196 0076f01c ..............v. + 394b0: 01534c47 005b63ec 0183fa2a ff401260 GLS..c[.*...`.@. + 394c0: 0023de76 ffcbd671 ffb8777a 00241342 v.#.q...zw..B.$. + 394d0: 00f940cc 008b5992 01873e86 0065e968 .@...Y...>..h.e. + 394e0: 001a54bc 0081f931 ff4bd6d0 ff4d82cf .T..1.....K...M. + 394f0: 00ebaf73 ff8902ab 01ba91af ff87f537 s...........7... + 39500: 01b5569a fff63a64 ff3cc76d ff86cc52 .V..d:..m.<.R... + 39510: 01e631d7 ffc0e58c fffbc1de ff0f8851 .1..........Q... + 39520: ffa295b3 ff1d2717 fe4b5f07 00de51bf .....'..._K..Q.. + 39530: ff5a51f1 ffc9316b 009dd3f4 ff958cde .QZ.k1.......... + 39540: fe38db41 ff5af6bd 019d3bb2 0034db30 A.8...Z..;..0.4. + 39550: 00d72262 ffbb111c 0018a9af ffa14f5c b"..........\O.. + 39560: 01c2c8ec 00ea8f93 0107e1e5 000ea8c5 ................ + 39570: 013533eb 00ae78fd ffa806c5 00ab75ca .35..x.......u.. + 39580: 00ce15a3 ff5a5572 ff0a290f 006313c2 ....rUZ..)....c. + 39590: fed83741 007492a2 ffd4ce32 ff1d9240 A7....t.2...@... + 395a0: 01839e9e ff82a564 ff8117ac ff09357d ....d.......}5.. + 395b0: 0112c10f ff0b311a 01c9aeb5 ff0ec987 .....1.......... + 395c0: 00951364 004f62db fe8f632a ff300060 d....bO.*c..`.0. + 395d0: fe53f9c5 ff4f9568 fe886eeb ff2c8052 ..S.h.O..n..R.,. + 395e0: fe242941 000ad358 00bb79bb 00c78662 A)$.X....y..b... + 395f0: feb3bcab ffee0bd2 fe827b42 003dea34 ........B{..4.=. + 39600: fe177130 ff785606 00f5b277 00c98157 0q...Vx.w...W... + 39610: 00d18df2 005572ca 00a11694 0030c367 .....rU.....g.0. + 39620: ffab3119 0082438a fe7a49b6 00821894 .1...C...Iz..... + 39630: 009ae5d3 009e9b20 003d6954 ff09c2b1 .... ...Ti=..... + 39640: 015659a6 00bb5336 ff7528f9 ffd7036d .YV.6S...(u.m... + 39650: 012c9235 00b32f3f fe03d8c2 0088540e 5.,.?/.......T.. + 39660: ff0db188 ffbaf348 ff7d1175 ffd33ad3 ....H...u.}..:.. + 39670: 00df4f5d fff5585a ff6fd18b 002fde46 ]O..ZX....o.F./. + 39680: ff4ff60a 00b2d9c6 010be1e3 ffb37e4e ..O.........N~.. + 39690: 007e2b3e 00239467 fea50881 0094f0f5 >+~.g.#......... + 396a0: 008e333d 0086d051 ff73890f ffec77d3 =3..Q.....s..w.. + 396b0: fff8f59f ff888602 013a8be6 00fea4a0 ..........:..... + 396c0: ff8d5572 ffb6a631 01544690 0007b655 rU..1....FT.U... + 396d0: 005d352e ffa1a609 ffb2a237 00bcb82d .5].....7...-... + 396e0: fe2c1c92 00315aa9 01f1b278 ff7f7b0e ..,..Z1.x....{.. + 396f0: 01c7f107 ff3242bd fe658fc6 ff87f3bd .....B2...e..... + 39700: fe18188d 0057614b 019afb76 009c36ed ....KaW.v....6.. + 39710: ffcf92ab fff6c483 01714088 0039e897 .........@q...9. + 39720: 0073daf0 ff1b3d31 01498140 ff1ba9fc ..s.1=..@.I..... + 39730: 010a8428 ffc1c95a 01f079fc 0029ceba (...Z....y....). + 39740: 0061c62b 00b76491 fe50d8cc 004196ac +.a..d....P...A. + 39750: fec4e5f9 ff497b68 fe60684d 0008b482 ....h{I.Mh`..... + 39760: 00397b68 ffe5cadc 00d3f966 ffe80e56 h{9.....f...V... + 39770: 00d14eb6 00a4e1ef ff200d6a ff114978 .N......j. .xI.. + 39780: 00e94386 00b5fe53 0170ecb7 ff834030 .C..S.....p.0@.. + 39790: fff3d8f1 00e2c141 fe64f1ce ffa68664 ....A.....d.d... + 397a0: 00c5caed 00510d37 ff667c20 00b1e428 ....7.Q. |f.(... + 397b0: 011fb576 ff86a0e7 00cabb77 ff3c8e00 v.......w.....<. + 397c0: ffbd2680 0096c9a6 011a78cf 00acb836 .&.......x..6... + 397d0: feccf20c 00e64285 011f2622 005070b8 .....B.."&...pP. + 397e0: fea53320 0037f3bf fe92493a ffcda79b 3....7.:I...... + 397f0: ff986864 ffcffec5 00f713ad 00ca0aee dh.............. + 39800: 00f297ef ff273b5e ff661df0 ff9a5c0a ....^;'...f..\.. + 39810: ffdb54e5 005081a1 01cc5ad0 ffaedbf0 .T....P..Z...... + 39820: 0191669e ff4cb235 01a86c34 006bde53 .f..5.L.4l..S.k. + 39830: 006d24d3 00383a76 00161d08 00c7a0ed .$m.v:8......... + 39840: 009dd1aa 002f4789 0020568f 0002f2c6 .....G/..V ..... + 39850: 018830d4 00baac5c 016997e6 00e5bf60 .0..\.....i.`... + 39860: febf508a ff82d8f0 fe062b62 0031c4a8 .P......b+....1. + 39870: 015b12fd 00794990 0127923d ff18683f ..[..Iy.=.'.?h.. + 39880: fe70a5b8 0062eb7e ff62d550 ff573c7b ..p.~.b.P.b.{. + 39910: 0108589c ff62b8d2 ff7baf14 00e55366 .X....b...{.fS.. + 39920: 017441dc ff04fa96 ffdc8e5c ff42f722 .At.....\...".B. + 39930: feb3e1cc 00975197 ffec2847 003e3f8a .....Q..G(...?>. + 39940: fff04f06 00b5b9b7 001b3276 00c0e33f .O......v2..?... + 39950: 013a637b ff9be032 fedfe111 ff4de0dc {c:.2.........M. + 39960: 017b2c0e 00af808d 00c8d4f8 ffb73b96 .,{..........;.. + 39970: 001d6193 00b5cc96 004725fd 00775591 .a.......%G..Uw. + 39980: 00bac89a fff98002 007c1853 008f570e ........S.|..W.. + 39990: 01f533a8 ffe7977c 01c5f0d0 00b9be7c .3..|.......|... + 399a0: 00f63a30 00e8e914 ff62127d ff1ffe0d 0:......}.b..... + 399b0: ff82b1f5 00238e6c fef27dab ff220c8c ....l.#..}....". + 399c0: 00a2a1a5 0065cdce 012219f7 00399164 ......e...".d.9. + 399d0: 00394627 ffcbcc76 00a200f2 001ef4a5 'F9.v........... + 399e0: 00e274c6 ff996f80 01b6368c ff0f7a3c .t...o...6.... + 39a60: fe09404f 0071305e fe328a11 0016ffc1 O@..^0q...2..... + 39a70: 01c512f7 00683743 ff5fcd10 00422530 ....C7h..._.0%B. + 39a80: 013f9c37 ff4a5240 fe4735c8 007d43ef 7.?.@RJ..5G..C}. + 39a90: 00dee01a ff5d89df ffcae01e 0084dc09 ......]......... + 39aa0: 01eb26c6 00568d66 01512b3c 001a1c88 .&..f.V.<+Q..... + 39ab0: fe0824e9 0094f2cf 003fa2a4 ffe02e33 .$........?.3... + 39ac0: ff4f3072 00e2af09 ffc103de ffe8a02f r0O........./... + 39ad0: fe695dff 00e62a0e 01528a1a 00f42bd0 .]i..*....R..+.. + 39ae0: ff26271b ff7fd062 ffb69540 00d1fa05 .'&.b...@....... + 39af0: fe1c3cbb ffda1931 ffcd74a9 00781277 .<..1....t..w.x. + 39b00: ff93749c ff6d3584 00ca0a0d 00a7536e .t...5m.....nS.. + 39b10: ff89db9d ff820306 ff1ea732 ff2f9f3c ........2...<./. + 39b20: fe9d8081 00bd035e 0044a603 00d7df53 ....^.....D.S... + 39b30: 01c25a96 0041a80f ff3353e3 ff42abcd .Z....A..S3...B. + 39b40: 013cbb36 ff2d6698 00e19a77 0088f7f0 6.<..f-.w....... + 39b50: ffb2c564 ffdf478b 011052cc ff2ace29 d....G...R..).*. + 39b60: ffddc09c fff47bd8 ffb9dada ffefbabb .....{.......... + 39b70: ffa0acfc 001634c3 feb5ae90 ff7364bb .....4.......ds. + 39b80: ffb04ed3 00c1071b ff68d593 ff0ac95a .N........h.Z... + 39b90: 01427b50 00ba2116 fe630701 000ace1e P{B..!....c..... + 39ba0: 0005eae5 00d21e35 fedc088a 00a73747 ....5.......G7.. + 39bb0: 0156e148 00bcbe76 0165c1fe ffacf9ab H.V.v.....e..... + 39bc0: feb79e5e ff6c025d ff4c5db0 ff4f6349 ^...].l..]L.IcO. + 39bd0: fe81404a 00412ef6 fe7ff163 ff6697f6 J@....A.c.....f. + 39be0: fed0352c 00ea663b ffa4af9a 0020f258 ,5..;f......X. . + 39bf0: 0001266f ffbeb6ff fe0fb073 00813ca9 o&......s....<.. + 39c00: 00f1ed7a 003f4c5a ff784a3e 006ec37a z...ZL?.>Jx.z.n. + 39c10: 00b20477 00d2f2de fe2e2182 0029289c w........!...(). + 39c20: 017092a7 ff6fa331 00ebb079 ff0ecf4c ..p.1.o.y...L... + 39c30: 01c61903 00d5eb29 01d62455 ff6d5c31 ....)...U$..1\m. + 39c40: fe1e18c8 00c3eca8 017c2791 0095c3ec .........'|..... + 39c50: ffb8245a ffaa5543 fe1a2326 ff447c83 Z$..CU..&#...|D. + 39c60: ff239bef 00a4c936 ff7516c4 00cd0f31 ..#.6.....u.1... + 39c70: 011de018 0090717e 00b61575 008d9fcb ....~q..u....... + 39c80: 004d87df ffb0e6b0 ffd7e5be ffb52563 ..M.........c%.. + 39c90: ff8a1533 ff59bd19 fea53031 00f72d98 3.....Y.10...-.. + 39ca0: 00de6caa 0005ca50 fe67451b ff8116cc .l..P....Eg..... + 39cb0: fe3efcb4 ff5b01d2 fffe6e92 001ca2db ..>...[..n...... + 39cc0: 01d5fcdf 0021083b 00f410ce 0030d381 ....;.!.......0. + 39cd0: 00d0a06b 00d13b70 fed84d6d ffb91522 k...p;..mM.."... + 39ce0: ff3863f6 ff138bb3 ff321db9 00135954 .c8.......2.TY.. + 39cf0: ff62fa4a ffc82ae1 ffcdd9c0 00a710d2 J.b..*.......... + 39d00: 015f8463 0039e62b ffcb0bfe ff3fbc63 c._.+.9.....c.?. + 39d10: fefbc177 00366950 01bdb5e8 ff7045b7 w...Pi6......Ep. + 39d20: ffa5abd0 ffb46d2f 00a5537b ff34a292 ..../m..{S....4. + 39d30: ff040b9a ff5ae397 fe618992 ff29e93d ......Z...a.=.). + 39d40: ff372a5e 00eca46c 00fe4498 ff838c0a ^*7.l....D...... + 39d50: fe4f6a0a 00899ef3 fe42b243 ffc67bb1 .jO.....C.B..{.. + 39d60: 00223e0f ff2a58c5 ffb15f95 ffc60098 .>"..X*.._...... + 39d70: ff71fe95 ffa35ae1 00f7d97d 00e01112 ..q..Z..}....... + 39d80: fe784280 ff0919c0 00cddd32 0046d431 .Bx.....2...1.F. + 39d90: 00a4ffe9 0009d102 fedb34dd fff4e0ac .........4...... + 39da0: 01ce385e ff02b3f2 01a45b1f ff8a2ee6 ^8.......[...... + 39db0: 00dce6bd ff3d2f39 009d0b6f 00985bb1 ....9/=.o....[.. + 39dc0: 0062e61c 007e5761 ff9159c6 006b4fa7 ..b.aW~..Y...Ok. + 39dd0: 01a04df9 ffe6e91d fe561596 00c10b3c .M........V.<... + 39de0: fe242597 fff396b9 0153d4e4 00b497ac .%$.......S..... + 39df0: 009ba9c9 00ea3cf4 0104eb8e 003cda43 .....<......C.<. + 39e00: 014b71c0 ffcff374 009bac41 ff9c1e51 .qK.t...A...Q... + 39e10: fe214850 ff6de712 fe156b8e ff841a7d PH!...m..k..}... + 39e20: ff3b10b0 003ac996 00c9a9ce 00e279d0 ..;...:......y.. + 39e30: ff0eac28 ff5e3d96 ff9c3938 ff913c8d (....=^.89...<.. + 39e40: ff956c2d ff9b91ee fe1f55d1 00d20cc0 -l.......U...... + 39e50: fe5d6263 00971098 00dcb9e1 ff2ceb8d cb]...........,. + 39e60: fe15aca0 ff1f1a47 fe5d400d 00c6381c ....G....@]..8.. + 39e70: 01f83eb1 00f108b6 ff9465a6 ff85514e .>.......e..NQ.. + 39e80: 01d7de81 ff81a9bc 006107e8 ff3c7031 ..........a.1p<. + 39e90: 00fbe5d9 008a6c77 fe7b1327 00eb3183 ....wl..'.{..1.. + 39ea0: 00915484 ff94e682 00bb4a19 ff36f505 .T.......J....6. + 39eb0: 01f1dbb9 ffe4c212 0066caf1 00ca7169 ..........f.iq.. + 39ec0: 004feb9b ffb20915 00ef019c 003d94c8 ..O...........=. + 39ed0: ffd2f773 0087dd31 0108bd3a 00092e23 s...1...:...#... + 39ee0: ff054151 ffb99e34 ff2e747d ff0d8c4a QA..4...}t..J... + 39ef0: feac5cd2 00471793 fefde0d9 ffb46c73 .\....G.....sl.. + 39f00: fe303a91 ff18b1db 013cff9c 00f2939a .:0.......<..... + 39f10: 005786fd 00e54b35 ffdec330 ff32af1f ..W.5K..0.....2. + 39f20: ff78d29c ffde23d0 01b3f812 ff650a02 ..x..#........e. + 39f30: fff8c29d ff65cc9e ffc5fe68 00043e4f ......e.h...O>.. + 39f40: 0165acb2 fffb9260 009c0a41 ffa58902 ..e.`...A....... + 39f50: 00e70474 0001d7f2 ff1d2313 004fa12b t........#..+.O. + 39f60: 01f6953b 00b042fb ff0321c8 ff8e6e50 ;....B...!..Pn.. + 39f70: 0111a1c3 ff4238e4 fe912f7b 00a40484 .....8B.{/...... + 39f80: 00acae43 0072fd19 01576157 0054dcfa C.....r.WaW...T. + 39f90: ffc85b60 003b7d25 00764113 fff134a1 `[..%};..Av..4.. + 39fa0: ff06aced ffffbfb0 fe824101 00e6bedf .........A...... + 39fb0: ffe7fd65 006d2392 014d1dfa 00130031 e....#m...M.1... + 39fc0: 019b5a7b ff205616 0041d5da 007f5d6f {Z...V ...A.o].. + 39fd0: ffa95d3c 00b67f08 fe0eba11 fff689fd <].............. + 39fe0: fe3019d5 ff00ee4c ff465cf8 008be063 ..0.L....\F.c... + 39ff0: 01ff09b8 00d0a407 01c683cd 00c7d657 ............W... + 3a000: 005fd682 00de95dd feab2617 00d56ec5 .._......&...n.. + 3a010: fe8c732b 0076b1d7 01423460 00ed9e75 +s....v.`4B.u... + 3a020: ffb6400e ffae3f2e ffbe5f9e ffb1cde1 .@...?..._...... + 3a030: ff8e052b ffd463ac 0093bbf4 ff99331d +....c.......3.. + 3a040: fe1874e4 00cf651e ff96f613 0005e786 .t...e.......... + 3a050: 01e2867d 0062414d ff2182ec 003e6e05 }...MAb...!..n>. + 3a060: ff7f6c45 00167107 fe531491 ffe7a1c2 El...q....S..... + 3a070: 003cb583 ffb1d1d9 fed494e5 00b88303 ..<............. + 3a080: 01bbb175 ff1f0e1c 005066b0 ff975432 u........fP.2T.. + 3a090: ff361f7d ff859d15 018bb313 001ae8e0 }.6............. + 3a0a0: ffaa7522 ffabfca7 fece8d49 0023fa81 "u......I.....#. + 3a0b0: 01ec4f48 ff14e5dc ffadca29 ffee4c63 HO......)...cL.. + 3a0c0: ffe016c6 ffc3c66c 01608d24 ff3b9eec ....l...$.`...;. + 3a0d0: 0057646a 0002e26e 00deeae3 ff775d9a jdW.n........]w. + 3a0e0: ffa4704a ff025b43 ff219115 ff89d666 Jp..C[....!.f... + 3a0f0: fe67e6af 00a6f6a3 fe74f75d ff1ce0a7 ..g.....].t..... + 3a100: 013902dc 0054ceab ff11e47b 0077781b ..9...T.{....xw. + 3a110: 01930b77 ffe12fb4 feb9c868 007202a5 w..../..h.....r. + 3a120: 00d44e4d ffb19a2d fe79c418 00b69d52 MN..-.....y.R... + 3a130: 01be105a 00c5930c ff98ef5f 0047eb0b Z......._.....G. + 3a140: ff779256 00d686ac 00c4833c 0081e1a1 V.w.....<....... + 3a150: fe78821f 0033c85f ffd2e769 ff94093a ..x._.3.i...:... + 3a160: ffdda82b 008eed7c fe32d3c6 0067f52e +...|.....2...g. + 3a170: 0054f8a4 ffd04698 00b175b4 00b94f46 ..T..F...u..FO.. + 3a180: 00204af3 00cf9c95 01a1c4c5 00ef35f5 .J ..........5.. + 3a190: fef65d0f ff31f08b ff2458c4 007b26a2 .]....1..X$..&{. + 3a1a0: 019dc880 ff674cae fe22a9ad ffab01d8 .....Lg..."..... + 3a1b0: 00113372 00c2e488 fe38966e 009ff66a r3......n.8.j... + 3a1c0: ff4fb813 fff04d96 00a2509b ffa93500 ..O..M...P...5.. + 3a1d0: 0056971d 00105e44 fe6e075c ff957562 ..V.D^..\.n.bu.. + 3a1e0: ffe64df9 008c0afd fe5c7cd6 00eb7623 .M.......|\.#v.. + 3a1f0: 01393059 00a63516 ff3d90b8 00c2ffb3 Y09..5....=..... + 3a200: fe3df8d6 00f66e3b fe511579 00e403a6 ..=.;n..y.Q..... + 3a210: ff1a406a ff86e845 fe35dcf2 0055dc2e j@..E.....5...U. + 3a220: fff79571 ff67b361 000b7fbe 00b6d187 q...a.g......... + 3a230: 0181345f ffce90aa ffccc87a 009264a8 _4......z....d.. + 3a240: fe95903c 00283c46 ffb1347a ff65d3f6 <...F<(.z4....e. + 3a250: 0008edae 00783307 00ad1f13 ff9cef7e .....3x.....~... + 3a260: 00cbbd8f ff5880c4 ffe285e9 ffad7d1e ......X......}.. + 3a270: 00326cc9 ff3b647b 0103a3fe ffb594dd .l2.{d;......... + 3a280: fe3988d6 ff89b4de ff3658cf fffb211c ..9......X6..!.. + 3a290: 0134d643 0064d0d2 005eaa51 00352891 C.4...d.Q.^..(5. + 3a2a0: fee76fe0 fff41c23 fec3c7e2 00e611ee .o..#........... + 3a2b0: fea4d9d9 00dd9da9 01a22eda ffa3cfc7 ................ + 3a2c0: 01a2736c ffbb600e 004c3c76 00989fb8 ls...`..v...... + 3a400: fed4bd22 00f9bbf4 01500dbe 00015982 ".........P..Y.. + 3a410: 00ad85df ffc6de09 004a7f42 ff5dd8a7 ........B.J...]. + 3a420: 01c6a89b 00009142 012e6644 009a5aac ....B...Df...Z.. + 3a430: ff4b80d8 003328a0 011b119e 0031f07c ..K..(3.....|.1. + 3a440: ffb0caec ffc07c97 00bec126 003db65f .....|..&..._.=. + 3a450: ff7c93a3 ff33a5ff fe11281c 004e60d7 ..|...3..(...`N. + 3a460: feda9156 ffca241f 00050956 ffc8296f V....$..V...o).. + 3a470: 00616ced 002c3e39 010fb875 0074f12d .la.9>,.u...-.t. + 3a480: ffdc0198 00bca59d 01830ffa ff7d2c3c ............<,}. + 3a490: fffbdc41 00b8324b ff805a35 ffc250e7 A...K2..5Z...P.. + 3a4a0: 017f8188 ffbb1215 ffa13a2d 00229347 ........-:..G.". + 3a4b0: fe0bf9ae 001d8d23 ffb144ef 003a6e73 ....#....D..sn:. + 3a4c0: 01b1beee ffa6f557 fff731be ffb85392 ....W....1...S.. + 3a4d0: ff270ead 0068d792 0078df8e ff9bc895 ..'...h...x..... + 3a4e0: 0191cfd4 00d9b510 ff5720ad 00b523ff ......... W..#.. + 3a4f0: 01a1df77 ff5edfc8 ffba0646 ff5543c0 w.....^.F....CU. + 3a500: 0098a932 ff7b1a90 feb3f338 00884414 2.....{.8....D.. + 3a510: febc8c27 ff05d0fd 018773c8 ffe5ac2b '........s..+... + 3a520: 00bb689c 00a7fb97 00178734 00489997 .h......4.....H. + 3a530: fe6bc593 ff059e94 00ce8fee ff89997e ..k.........~... + 3a540: fec59858 00a74407 ffa59ffc ff364eef X....D.......N6. + 3a550: ff373f18 005ede26 ff0cb7ed 00d2ccce .?7.&.^......... + 3a560: fef62713 00e74a1e 011d6c87 000073b3 .'...J...l...s.. + 3a570: 01747675 fffc0684 01a18191 008d4369 uvt.........iC.. + 3a580: ffe22552 ffe4e2ee fe81d6cc ff647ba2 R%...........{d. + 3a590: 00ea79b9 00e76c2d ff380842 00808884 .y..-l..B.8..... + 3a5a0: fe42e0ac 00bc9daf fee2dfe6 0045dbf2 ..B...........E. + 3a5b0: 01770eb8 0038a252 00147b72 ff5567a2 ..w.R.8.r{...gU. + 3a5c0: fe63ef31 00d7879c fea7ff6f 00d6c427 1.c.....o...'... + 3a5d0: 014f2690 007da8f9 ff9c619b ffdb3417 .&O...}..a...4.. + 3a5e0: 00901696 ffa5952c 00b77f28 ffe94dc4 ....,...(....M.. + 3a5f0: ffd28176 ffe687aa 00c677d6 0023f0e9 v........w....#. + 3a600: ff0734fd ff306675 ff9acc15 ffb188b3 .4..uf0......... + 3a610: 01030217 ff598295 019f11fc 001a3c46 ......Y.....F<.. + 3a620: 00116b90 ff3cbeb4 ff3bb638 ff36476e .k....<.8.;.nG6. + 3a630: ff8112c6 ff57e095 ff9815df ffb6168a ......W......... + 3a640: 00cd9cfa ffd02dec 01f2944f 00d14665 .....-..O...eF.. + 3a650: 00ae4e67 ffac9065 01ed8898 0088c2bf gN..e........... + 3a660: 017d5071 008d0498 ff35969b 00f574c4 qP}.......5..t.. + 3a670: fe4972ef ff115213 ffea7d7c 00bf3428 .rI..R..|}..(4.. + 3a680: ff9ed22a 00a5849b 012a05b2 ff285c40 *.........*.@\(. + 3a690: ff4d5524 0076e4b2 fe604289 0042e273 $UM...v..B`.s.B. + 3a6a0: fe45f06e 00506f97 ffecaea7 ff6b6ce3 n.E..oP......lk. + 3a6b0: ff41f2bc 00ff51b7 ffb5ce39 ffb5222f ..A..Q..9.../".. + 3a6c0: 019ef0d5 005f4b47 ff18289c 0051d266 ....GK_..(..f.Q. + 3a6d0: ffe4c7ab 0029229a 004bafe3 00c3ef15 .....")...K..... + 3a6e0: 015fe58a 0031c04c 01577b75 0082e1e3 .._.L.1.u{W..... + 3a6f0: ff3f3e7d 00abc602 fe0d24fe 00ceba91 }>?......$...... + 3a700: fff4ff94 00a60023 01db961e 00d4e45c ....#.......\... + 3a710: fe3cc65c ffc8853e 003b29c9 ff6dee7d \.<.>....);.}.m. + 3a720: 01eea3b4 00527a8c ff581609 ff2f9dc5 .....zR...X.../. + 3a730: 00395e99 00b61e58 0055a154 007c92b2 .^9.X...T.U...|. + 3a740: ff07a6a6 00dfd015 00f2b69c 00b9799b .............y.. + 3a750: feae9c53 ff76109a 01e853ba ff793adf S.....v..S...:y. + 3a760: 0058171d ff7f7d23 fe9505aa ff820ca4 ..X.#}.......... + 3a770: 001dc49b 008860a1 011d2307 00fb25a2 .....`...#...%.. + 3a780: fff22e03 00bcd900 01e2ae39 0002e9ce ........9....... + 3a790: fe88bb39 ff09bd7b ff7f75c9 00cc24ba 9...{....u...$.. + 3a7a0: 00d819e7 00694e50 ff818613 0044cb94 ....PNi.......D. + 3a7b0: fe7d518d ffc8a5f8 008790d6 ffa63797 .Q}..........7.. + 3a7c0: 005beb26 009a2e15 ff96fedf ffb49923 &.[.........#... + 3a7d0: 011db07d ff1e622b ffe67ad8 000ca0e9 }...+b...z...... + 3a7e0: fe0cb939 ff0771f0 fe100905 006c5b1a 9....q.......[l. + 3a7f0: 00cbc66d 00289308 ffe48681 ff28ba7c m.....(.....|.(. + 3a800: fe846272 001784a6 002c4563 ffeef209 rb......cE,..... + 3a810: 003b35b8 ff668184 fef32034 ffc8df93 .5;...f.4 ...... + 3a820: feb3537b ffc99087 0138258d ffe33c97 {S.......%8..<.. + 3a830: 019c495a 00bbaccb ff2f9750 ffe7895e ZI......P./.^... + 3a840: ff3bbf24 ffb5d1e1 fed5d74a ffb37606 $.;.....J....v.. + 3a850: 01c13699 00e70032 01489d68 ff9ae38c .6..2...h.H..... + 3a860: fe10e2b6 ff5ce160 feaa1473 004efa06 ....`.\.s.....N. + 3a870: ffad4bf8 ff065935 0076b400 0001ad48 .K..5Y....v.H... + 3a880: 01ce0840 00df85ae ff853eb9 00620bd6 @........>....b. + 3a890: 00d01fc5 fff4a7ab 01b5e716 00b9da96 ................ + 3a8a0: 0161a9f7 fff78ba5 0195782f 0033f867 ..a...../x..g.3. + 3a8b0: fe1c453c 00c4b319 feda077c 00516b3a . + 3aa00: 017ba6b2 ffa10c84 002bae3d 009045c3 ..{.....=.+..E.. + 3aa10: 01bf2f7f 004e2c22 0134ea39 ff2816ff ./..",N.9.4...(. + 3aa20: 00925ef6 0080e453 ffe04e3c ffd26000 .^..S...?.....M... + 3aa70: 00a45677 ff92d0aa ff9a85d0 ff3a9b94 wV............:. + 3aa80: fee878a2 009bd5fc 002a0df1 0083325e .x........*.^2.. + 3aa90: 0070aab3 ff97538c 01547737 ffef238c ..p..S..7wT..#.. + 3aaa0: 01432d99 0027afec ff679736 ff412a9e .-C...'.6.g..*A. + 3aab0: fe87efc4 00cb3556 fe2f6195 ff1123d8 ....V5...a/..#.. + 3aac0: 01460346 ff5a2467 00ad1a28 000d30b8 F.F.g$Z.(....0.. + 3aad0: ffd9dba3 ff010651 fe6caadd 005dd0e9 ....Q.....l...]. + 3aae0: fef9c964 ff232456 011e9ad1 fffbc9e3 d...V$#......... + 3aaf0: fea7bd02 00033964 0029800d 004b64c5 ....d9....)..dK. + 3ab00: ffebcc96 003bae91 ff95f878 00e13755 ......;.x...U7.. + 3ab10: fe35d272 0077ccc7 014af70e 0081fb3f r.5...w...J.?... + 3ab20: 01976843 00508287 ff37594f ff9de675 Ch....P.OY7.u... + 3ab30: 008f6019 000591d5 0178f145 ff5ff395 .`......E.x..._. + 3ab40: 00142a72 00024883 ff14359a 006d3e49 r*...H...5..I>m. + 3ab50: 009866c4 ffcc0c29 010b267a 00910afa .f..)...z&...... + 3ab60: 00947dcf ffdef4f6 01552029 007ed570 .}......) U.p.~. + 3ab70: 0156f9a2 ff7fc647 01150951 ff042762 ..V.G...Q...b'.. + 3ab80: 012d47cc 00896f4b 00e73bea ff5f3020 .G-.Ko...;.. 0_. + 3ab90: 01721fcc ffb5c41d fea7f133 008e6d5d ..r.....3...]m.. + 3aba0: 002d9068 ffb50ceb 00a47034 ffcafe4c h.-.....4p..L... + 3abb0: 00a20eae ff93eb3d feb9402b 00d97de9 ....=...+@...}.. + 3abc0: fea758f3 0008314a 0042cc9c 007bd67c .X..J1....B.|.{. + 3abd0: 0176dd26 00ec7092 00b16272 00c75997 &.v..p..rb...Y.. + 3abe0: 0070c557 00a195b9 00a5602c ff14b3f8 W.p.....,`...... + 3abf0: fed8dbbc 000d3e28 008d8ef3 ffcee3e5 ....(>.......... + 3ac00: ff23caac ffe1b075 01266e52 ff0ef52a ..#.u...Rn&.*... + 3ac10: 00615314 000aab31 007877f2 003de819 .Sa.1....wx...=. + 3ac20: ff93f0d4 ff387304 feef1191 fffb11ca .....s8......... + 3ac30: fff512f9 00ef7563 ffb304b8 ff33edf6 ....cu........3. + 3ac40: ff89ef25 ffa670a6 ff21bc51 ff8efab9 %....p..Q.!..... + 3ac50: 00adbb36 00c970d0 01e42bf6 ff58b868 6....p...+..h.X. + 3ac60: ffc434d4 ff6c7533 009b75fe ff0f5b2e .4..3ul..u...[.. + 3ac70: ff900e57 00cce357 01531a53 00e34c9f W...W...S.S..L.. + 3ac80: 01d51b9f 006c9718 feb39075 0052d189 ......l.u.....R. + 3ac90: 000a9f26 00c98573 019cb6df ff5dc46e &...s.......n.]. + 3aca0: 00e93c39 ff69a705 00a4c59a ffba2260 9<....i.....`".. + 3acb0: 01258593 00be63dc ff54a701 00ab9114 ..%..c....T..... + 3acc0: fefbc5c2 ff854e5f fff3f8fc ff835de1 ...._N.......].. + 3acd0: ffc486bb 00aa99d8 fe9e7614 0076018c .........v....v. + 3ace0: 010f9e56 ff29d32d fe640193 ff4c7471 V...-.)...d.qtL. + 3acf0: 016c7fd3 00300f67 016610c1 ff5f3345 ..l.g.0...f.E3_. + 3ad00: 009d806b 00e9ab89 01907c5a 00b6a16a k.......Z|..j... + 3ad10: 01ec4caf ffac8dc8 00683aa3 ff34b4e9 .L.......:h...4. + 3ad20: ff0efdf0 fffe71a2 fe8aef26 00a62e34 .....q..&...4... + 3ad30: fe2165f1 009cba83 ff3ed06f ffa05e7c .e!.....o.>.|^.. + 3ad40: 00feac1f ff38ae70 ff1b63bc 00fb8a43 ....p.8..c..C... + 3ad50: 01803a7d ffae989c fff70cb2 009e54fc }:...........T.. + 3ad60: fe0ec552 ff53c8ac 012e2725 00a7cf6a R.....S.%'..j... + 3ad70: 0022bd18 0090b283 0004d5ce 00d2e2a1 .."............. + 3ad80: ff693348 ffbb2d61 ffdfb84e 00fb1db0 H3i.a-..N....... + 3ad90: ff56a04f 00b22574 01d54d52 ff8d5452 O.V.t%..RM..RT.. + 3ada0: 01d465e2 ffc758af 01f75ef5 ff6d76ac .e...X...^...vm. + 3adb0: 00beb9a6 0078b583 ff5dfe57 ff49f086 ......x.W.]...I. + 3adc0: ff8ff520 ff67a28b fe1262b3 0070ccd9 .....g..b....p. + 3add0: ff78df93 00f30a35 00968ca6 ffc8507d ..x.5.......}P.. + 3ade0: ffdb6d0e ff01da5b fe2ffcfc ff749c6d .m..[...../.m.t. + 3adf0: 017f3173 ffd357cc ffd9ca94 fff9551a s1...W.......U.. + 3ae00: 0186f50e ffa9594c 00e62df2 ffac623b ....LY...-..;b.. + 3ae10: fe844972 ff319b4e 00547e9e ff2baf31 rI..N.1..~T.1.+. + 3ae20: ff54b610 0023679d ff6dc168 009add43 ..T..g#.h.m.C... + 3ae30: fe01acc9 0058a208 ff1d01a5 ffe59b7d ......X.....}... + 3ae40: 01dc9a1e 005cef67 ff6d01dc 0001c6ca ....g.\...m..... + 3ae50: 018e025e 002c3624 ff9ee2eb ffd6fbaa ^...$6,......... + 3ae60: 00094db9 00f24a61 ff95a3db ff7623f0 .M..aJ.......#v. + 3ae70: fe5872df 0003c7c0 ff18256a ff76a1c9 .rX.....j%....v. + 3ae80: 01635961 ff673ae0 fe93c765 00633cde aYc..:g.e......... + 3b260: ffb28b4f 00caf278 00d5db1a ff237d3e O...x.......>}#. + 3b270: ff6c0290 ff5321e6 01d82d51 00113ee0 ..l..!S.Q-...>.. + 3b280: 007dd9d6 ff999962 fe6ab0b3 ff8a5d83 ..}.b.....j..].. + 3b290: ff243e6d ff2079b2 0046fc78 0025f8dc m>$..y .x.F...%. + 3b2a0: 016758cc fffbdc80 0107e3ec ffc6316a .Xg.........j1.. + 3b2b0: 006b383c 00ee7263 015eccdc 0001bb49 <8k.cr....^.I... + 3b2c0: 00229a59 ffa5d94e fff9c30e fffde609 Y.".N........... + 3b2d0: 00f587cd ff07fc1a 011bcd54 00700286 ........T.....p. + 3b2e0: 00209e25 ffed5be7 ffccaabf 00de0798 %. ..[.......... + 3b2f0: 0031c06d ff92a6c1 ffb513e8 ff348e69 m.1.........i.4. + 3b300: 011b1067 00a5c8fd ff04d9c3 ff90bd34 g...........4... + 3b310: fea09b7b ff368257 ff3d784e 0029380e {...W.6.Nx=..8). + 3b320: ff7d2919 00f5a857 0046a5d6 ff06a9d4 .)}.W.....F..... + 3b330: fec2d3db ffa45d48 ff6721c5 008d8e2b ....H]...!g.+... + 3b340: 00ace183 001c69f4 00e14444 ff0d5488 .....i..DD...T.. + 3b350: fe283982 00384d8b 00359654 009d5f36 .9(..M8.T.5.6_.. + 3b360: feb10d90 00ba735f ff761775 fff1a6f4 ...._s..u.v..... + 3b370: 0087ba0b ffcb6ab2 005dda61 002dfd2b .....j..a.].+.-. + 3b380: 000498a4 00ef768b fe180160 ffd399eb .....v..`....... + 3b390: ff146ea8 00b0ef32 00e82972 0035fac1 .n..2...r)....5. + 3b3a0: fe6fa0fe ff297a88 00436c61 ff1798d7 ..o..z).alC..... + 3b3b0: 00d4d18c 00a3bd2a ff322aca ffbd6a6a ....*....*2.jj.. + 3b3c0: ffd944be 00753ae9 01f3dce5 000403c5 .D...:u......... + 3b3d0: fe367825 ff869c04 feab3d24 ff6488a5 %x6.....$=....d. + 3b3e0: 000ee8d4 000aae5a ff41c6d8 0040030c ....Z.....A...@. + 3b3f0: ff737174 000867f8 ff127de7 00c51ca0 tqs..g...}...... + 3b400: 0123b81e fff949df fe2e147b ff253887 ..#..I..{....8%. + 3b410: 01e50dad ff22a177 00493df5 00707dcd ....w."..=I..}p. + 3b420: 00866889 ff1ef6d9 008f8eed ff669f41 .h..........A.f. + 3b430: 00bea46c ffad75db fe782522 005045c8 l....u.."%x..EP. + 3b440: feda7c1f ffa01b4a ffc79aba 00fcc747 .|..J.......G... + 3b450: 019f5168 0027c811 01c03dd3 005bee1a hQ....'..=....[. + 3b460: 000cd994 ffd55b3b ffb7510b ff7ae681 ....;[...Q....z. + 3b470: 0191cb72 ff42b477 00b48a48 006a95e0 r...w.B.H.....j. + 3b480: ff685277 002b8cd0 ffb60962 ff8665cd wRh...+.b....e.. + 3b490: 00266512 ffa6c55f 0093f1cb ff91d03e .e&._.......>... + 3b4a0: 00fbf685 000ea902 00b8f70d 00fe078e ................ + 3b4b0: ff17c824 00dfcd58 ff34815b 001eba15 $...X...[.4..... + 3b4c0: 01d2e48f fff8eaf7 fe1f45e6 ff87bab0 .........E...... + 3b4d0: 0134cdee 002b4f8b fed9b011 0043f320 ..4..O+..... .C. + 3b4e0: 00e96ff2 ff09232c 015172e3 ff0c4704 .o..,#...rQ..G.. + 3b4f0: 00bf6926 ff327507 00104f51 ff41443f &i...u2.QO..?DA. + 3b500: ff6e249d ff03f14d 01fb2de2 00ce198e .$n.M....-...... + 3b510: 01d17b78 ffeefe1c ff7e8005 ffd7de5b x{........~.[... + 3b520: 00bf0fa2 0049f056 fe51b987 00a3f12c ....V.I...Q.,... + 3b530: ffd2dbd4 009ba270 007665cf ff3848a8 ....p....ev..H8. + 3b540: 003405c4 fff2ac48 ff9d167e ff3b6092 ..4.H...~....`;. + 3b550: fe9879a2 005f108c fec8fec3 00a29652 .y...._.....R... + 3b560: fe912b77 ff4eaccc 009fe0a6 ffed1368 w+....N.....h... + 3b570: ffd07ef5 00d53be2 00c5d975 00ed4898 .~...;..u....H.. + 3b580: fe171fdc ffe75a0e 0140d4bc fff6653c .....Z....@...L@.......J%. + 3b720: fed31b8a 00c27d94 0051590a ff65cba8 .....}...YQ...e. + 3b730: 01d1d52b 0036f5eb ffe2231e 00467e09 +.....6..#...~F. + 3b740: fe5e7de2 ff14759c 0170f839 ff4030e6 .}^..u..9.p..0@. + 3b750: 01a65ca4 ffe6d6e0 008f7824 ff2b0837 .\......$x..7.+. + 3b760: 01f501fb 00a5626a fe6a6b4a ff360435 ....jb..Jkj.5.6. + 3b770: 0196b25a ff7b7803 015905f4 ff3dfa72 Z....x{...Y.r.=. + 3b780: 015299fe 00110f4d 015aee39 00e6df5f ..R.M...9.Z._... + 3b790: fe2f34ec ffa49467 0124cf79 ffb91012 .4/.g...y.$..... + 3b7a0: 004a144b 00650bbb ff81302e ffd2ef16 K.J...e..0...... + 3b7b0: ff81ec4d ffcc4d6f ff61483d fffbd9c7 M...oM..=Ha..... + 3b7c0: 00ccd72a ffc99185 0192e639 00c664eb *.......9....d.. + 3b7d0: fe234992 ff14c66c ffd24fb6 00886752 .I#.l....O..Rg.. + 3b7e0: 00b06cf6 ff3c1122 fe724a13 ff4eaaa8 .l..".<..Jr...N. + 3b7f0: ff14ef9d 00a82995 001c793a ff86b34f .....)..:y..O... + 3b800: ff8779e7 ff62d1ae 00be7af3 00cda6ab .y....b..z...... + 3b810: 003074d4 ff426c1d 01b6dea2 0015770e .t0..lB......w.. + 3b820: fff927d5 ffe4dffe 00c6a5b7 0030be85 .'............0. + 3b830: ff6dd07c ff55af77 0179d109 ffbdab30 |.m.w.U...y.0... + 3b840: 018647c3 ff33db88 fe8d5bb6 00489f31 .G....3..[..1.H. + 3b850: fff57623 ffe3ba70 001f893b 00a32c89 #v..p...;....,.. + 3b860: fe3c6772 0096d508 ff710aa2 004868c2 rg<.......q..hH. + 3b870: ff7483dc 005c4fb2 fed5facb ffbdc15d ..t..O\.....]... + 3b880: fe22ff82 0097bcd4 ff141188 ff536514 .."..........eS. + 3b890: 00a6ced4 ff49eee5 ff034a97 00d757a8 ......I..J...W.. + 3b8a0: ff85bc9b 004981a6 ff854ff0 ff51d3b2 ......I..O....Q. + 3b8b0: fea348cb 00a5a8c1 fec7a40e 00ccff1e .H.............. + 3b8c0: 015b4841 ff664aa6 ff002ac8 ffe371c2 AH[..Jf..*...q.. + 3b8d0: 00d01742 ff64d8e5 001aef18 ff3ee90a B.....d.......>. + 3b8e0: 01b20a7b ffae241a 01c7db77 00bea32d {....$..w...-... + 3b8f0: 002aa810 ffc639a6 001a1a1c 00e7a57e ..*..9......~... + 3b900: ff646cfb ff79e53d 008a763a 0011cf4c .ld.=.y.:v..L... + 3b910: fe70220d 00a81059 ff69d025 ffd7c923 ."p.Y...%.i.#... + 3b920: fe656a28 0072ef06 fee26728 ff6e7ff6 (je...r.(g....n. + 3b930: 003aa73f 008ef084 ff589e05 ff9e4981 ?.:.......X..I.. + 3b940: 0092595e 009236e6 00ad2d08 0001a94f ^Y...6...-..O... + 3b950: 00f7ba73 00834054 fffde043 0040bdcf s...T@..C.....@. + 3b960: 01511c9a ff36b82d ffe0d457 ff496000 ..Q.-.6.W....`I. + 3b970: 01eb2181 ff504234 ff9baefb 0025b304 .!..4BP.......%. + 3b980: fe5da4ea 00fdaf5d ff5745c6 002e6ae0 ..].]....EW..j.. + 3b990: 00d21d63 ff72bc3e 0008ea2c fff7afa9 c...>.r.,....... + 3b9a0: ff896d17 0027b6e5 fe5ea5c0 00d965f5 .m....'...^..e.. + 3b9b0: 006058bf ff635ec4 fe0bee6a 00f37e35 .X`..^c.j...5~.. + 3b9c0: ff65015e 0002932e ff7c7cc9 00da0c8d ^.e......||..... + 3b9d0: 019da60d ffedfb30 ff7cfa9b ff92946a ....0.....|.j... + 3b9e0: 00ca0db6 00a73d1c fe0898d9 ff2d82dc .....=........-. + 3b9f0: 01ffe6c8 ff574137 fe61bf5d 000efb72 ....7AW.].a.r... + 3ba00: 015c6920 008dcf1a fe0dcf18 ff303215 i\..........20. + 3ba10: ff7494ba 00e12bd3 fea22225 ff2ad2a4 ..t..+..%"....*. + 3ba20: ff601744 ff08d6b6 ff8975f5 0032c342 D.`......u..B.2. + 3ba30: fe530c4b 00a48c50 0124a509 00e36ee4 K.S.P.....$..n.. + 3ba40: 015a11f1 00d43419 ff0cdf06 0039f38b ..Z..4........9. + 3ba50: 014b710c ffbfb7f6 ff45bfd5 008e0fe6 .qK.......E..... + 3ba60: ffc4c301 ff2fab8a 016a3f40 ffd6a910 ....../.@?j..... + 3ba70: 0138aecf ff854958 008c85b6 ff190eb1 ..8.XI.......... + 3ba80: ff35b893 ffa1e30a fff4d878 00e94d49 ..5.....x...IM.. + 3ba90: 018bee9d 00e9413b 01d8fb46 ff99b829 ....;A..F...)... + 3baa0: 0070cb20 00fd9392 016d6557 ff85522c .p.....Wem.,R.. + 3bab0: ff3596f4 ffe8985e ff275d3b ffdc9358 ..5.^...;]'.X... + 3bac0: 010d514e fffc2f20 ff7213a0 ff276b5d NQ.. /....r.]k'. + 3bad0: 01d31076 ffd177b9 fe7fdbe3 ffec6958 v....w......Xi.. + 3bae0: ff176ea2 ff6ea624 ffddec5b 0074ea42 .n..$.n.[...B.t. + 3baf0: fef4136f 001ae90a fe06b720 00f2bf02 o....... ....... + 3bb00: fe359cda ff463c29 006feca8 ff7eb979 ..5.)...o... + 3bbd0: ff5b7376 003c5480 00cb90a7 00f30d57 vs[..T<.....W... + 3bbe0: 01e41e16 ff9271b1 fee6aa81 ff8199fc .....q.......... + 3bbf0: 002be191 ff05e746 fe7e697a ff94f656 ..+.F...zi~.V... + 3bc00: fe9a256e 005b03d1 003e9144 ffa510e4 n%....[.D.>..... + 3bc10: fef9dd37 005bd2b2 fee29253 00ba9245 7.....[.S...E... + 3bc20: fe68d25d 00ad1910 0026bae7 ff8c7abd ].h.......&..z.. + 3bc30: ff700dfb 005d6e69 00aa48fb ffdf17c0 ..p.in]..H...... + 3bc40: 01ca0318 00e45de1 fec79399 0016aa6d .....]......m... + 3bc50: fff665f8 ff0c7cb2 fe66feb2 00410437 .e...|....f.7.A. + 3bc60: 00b4d67d 009360b7 fe17752d 00f9bf84 }....`..-u...... + 3bc70: fecbb08f ff36b788 00b1ea92 ff566592 ......6......eV. + 3bc80: 018f7b2c 0098d121 fe295ac0 ff7d0f53 ,{..!....Z).S.}. + 3bc90: 0052acd5 0090a9d7 00220d10 ff64d120 ..R.......". .d. + 3bca0: 01f91254 ffec11c5 00e6bad9 ffb0a031 T...........1... + 3bcb0: ff61766f 00eb68ed fe5c3b4f ff0bf945 ova..h..O;\.E... + 3bcc0: 014aac23 00447613 ffa57cde ff2342b4 #.J..vD..|...B#. + 3bcd0: 00f6ae56 ff6f4a2b ff56907e 005beae4 V...+Jo.~.V...[. + 3bce0: fe18d5f2 ffeb2c45 0023b4dc ff07f808 ....E,....#..... + 3bcf0: ff5c2f66 ff66cdf0 01abe671 ffc9b91f f/\...f.q....... + 3bd00: ff46f6c2 00bb117a ffc74686 ff960395 ..F.z....F...... + 3bd10: 00673f75 ff7b6841 011336d4 00588d06 u?g.Ah{..6....X. + 3bd20: fff38653 00673588 00b41ba9 001831b1 S....5g......1.. + 3bd30: 00a7366f ffd73dc3 016c011f 00462a3c o6...=....l.<*F. + 3bd40: ffa203b9 ff2895c2 fe267ff6 ff2677be ......(...&..w&. + 3bd50: 0108773d ffdba160 01ddcb2a ffa4f2b1 =w..`...*....... + 3bd60: 000a9ff5 0000c474 fecd5d05 00b37f80 ....t....]...... + 3bd70: fff6ed7d ffd9a295 fe142557 00c0ee8c }.......W%...... + 3bd80: 00c10909 00e20161 000a261d ff3f8800 ....a....&....?. + 3bd90: fed248e5 ff5c8626 01d0da4e ff542468 .H..&.\.N...h$T. + 3bda0: ffc1050c ff3daff2 012ea9bf ff9393b3 ......=......... + 3bdb0: fe8bbe71 001fac7d fefc4b03 000f24d7 q...}....K...$.. + 3bdc0: 01181bc1 ff9545ff 0076816e 00f95dcb .....E..n.v..].. + 3bdd0: fe40898a 00064626 00de7499 007b4aa1 ..@.&F...t...J{. + 3bde0: ff4f63c1 ff5e3b76 012b0c3d 009db192 .cO.v;^.=.+..... + 3bdf0: 00bf932e 0026ff10 011f330b ff623a3c ......&..3..<:b. + 3be00: 014dc26f 00f45b9a 0190288c 00fb0aad o.M..[...(...... + 3be10: fe32d1cb 004e826c 005ab4e4 00fa07ae ..2.l.N...Z..... + 3be20: 003cae1f 001eab29 ff526374 ff8bc176 ..<.)...tcR.v... + 3be30: fec6adbb 00386fda 00d87bb9 00349ef9 .....o8..{....4. + 3be40: ff5db434 ff5b09c9 fea62d38 ffcb9b84 4.]...[.8-...... + 3be50: 006ee83a ff59d334 01a200fd 00b75709 :.n.4.Y......W.. + 3be60: 012c8891 00f57a5e 01abbc55 00c65c93 ..,.^z..U....\.. + 3be70: 00680800 00ae5f1e 0134e6dd ffebf7f7 ..h.._....4..... + 3be80: ff35ae89 ffcc1523 01d6e347 00c252e8 ..5.#...G....R.. + 3be90: ffe3300b ffb849aa fefcfbc6 0022702c .0...I......,p". + 3bea0: ff836583 00bba848 ff7d8784 ff61688a .e..H.....}..ha. + 3beb0: ffa8b8ee ff5468f3 ffe2d887 00ed908b .....hT......... + 3bec0: 019689bc ff8c3850 ffa7a956 ff194ec2 ....P8..V....N.. + 3bed0: ffb411dc 00c10d11 ffd48975 0097e08d ........u....... + 3bee0: 00aff431 ffaf63c1 019a6313 ff3e41ff 1....c...c...A>. + 3bef0: ff37d29c ff03f4f2 00950efa ffd9589e ..7..........X.. + 3bf00: fe86cf9d 001ce8fb fffb9c2e ffb838ab .............8.. + 3bf10: 00ea33ef ff838a8e 01f3fe19 00c2c90a .3.............. + 3bf20: 004b613f 00a2efd2 011fc8c0 00f3d675 ?aK.........u... + 3bf30: fede4718 ffe82836 fe6fb74c ff570e90 .G..6(..L.o...W. + 3bf40: ff884fd6 00d4c4d8 fe8c1b84 00fd0583 .O.............. + 3bf50: ff136c7c 004bd71c fe37de4c 003fb6e9 |l....K.L.7...?. + 3bf60: febfab44 ffde6f34 ff4d690a 00ebaa50 D...4o...iM.P... + 3bf70: ff58188f 0079e72d 01e08194 0054f63d ..X.-.y.....=.T. + 3bf80: ffdb2efd 00214cef fe129431 004525e6 .....L!.1....%E. + 3bf90: fe168643 005e9b8e fed39d1f ff1e2ad5 C.....^......*.. + 3bfa0: fef7e404 ff0db0fc fe1f0027 fffff4f1 ........'....... + 3bfb0: fe0a2daa 00f9defd 008472de ff062fff .-.......r.../.. + 3bfc0: 01b3a3b4 ff975e54 fe52d159 ffa934e5 ....T^..Y.R..4.. + 3bfd0: 0100ecd5 ffe438d6 ff977787 00c1c970 .....8...w..p... + 3bfe0: fe35a053 00429706 0011a212 005b61e9 S.5...B......a[. + 3bff0: 014e0583 ff3578b5 ff3f5f75 00b975ed ..N..x5.u_?..u.. + 3c000: ff887ebf 00e97790 016139b7 ffbbc92f .~...w...9a./... + 3c010: 0177a5a7 007e642d fe066215 ff5f9691 ..w.-d~..b...._. + 3c020: 00983678 006862d1 fe1e6f8f 00f994b8 x6...bh..o...... + 3c030: 002ed8eb ff94caf8 00165f39 00a3e1f2 ........9_...... + 3c040: ffe8f7e9 ff13ab47 ff31f467 ff5d6754 ....G...g.1.Tg]. + 3c050: 01f47944 000de052 ff2b4f29 ffa7cef9 Dy..R...)O+..... + 3c060: fe1534d7 ff1620c0 003c6ff7 ff264a65 .4... ...o<.eJ&. + 3c070: fe545b16 ff0d1c1d fed7e7c6 00c89af4 .[T............. + 3c080: 00ed89df 000e84d3 ffce405f fff73e11 ........_@...>.. + 3c090: 017983e9 004d175d fe34cccd 0088bd51 ..y.].M...4.Q... + 3c0a0: 018adbb4 005e128f fe8c2bcc 00dbafbc ......^..+...... + 3c0b0: ff8f626f ffa23f97 fe4732d3 00359213 ob...?...2G...5. + 3c0c0: fe532d92 ffee52b2 ff548510 ff5dc6e2 .-S..R....T...]. + 3c0d0: ff1461c9 ff237678 ffe73272 ff9ce5a2 .a..xv#.r2...... + 3c0e0: 000c1ad3 ff732772 0086d4ce ffa0d9c5 ....r's......... + 3c0f0: fe5e8174 ffdbd7c7 01f9df4b ffb574fd t.^.....K....t.. + 3c100: ff68d7e8 fff682e4 005675b9 0008050e ..h......uV..... + 3c110: 013d1def ff8557ed fe89927d 00dfa8cc ..=..W..}....... + 3c120: 00f5a82e 0016699a ffa1d4dc ff18456b .....i......kE.. + 3c130: ffb5da89 ffc654f1 ffd37a82 ff99088d .....T...z...... + 3c140: 0076b1be 00b25960 fe3010ff ff69607a ..v.`Y....0.z`i. + 3c150: ffe83675 ff697e22 00a643cc ff8a34e8 u6.."~i..C...4.. + 3c160: 000c93d3 00073619 fed70f2c 002dec33 .....6..,...3.-. + 3c170: 018144be 00e1936a fe2d5d1c ff0f8dec .D..j....]-..... + 3c180: 00a13d11 00c073dc fe1891ec 00a9a86f .=...s......o... + 3c190: ff3f3ae0 00bca47f 014bea52 00869ee0 .:?.....R.K..... + 3c1a0: 016e44d1 00d9a6d9 01a6e146 ff8fc1bb .Dn.....F....... + 3c1b0: ff580710 008ccd0a 019cc075 00263811 ..X.....u....8&. + 3c1c0: 016c7c1b ff37d7ab 00d4fd5f ffa8879b .|l...7._....... + 3c1d0: fe99b2f6 004a449a fe603de8 003b8469 .....DJ..=`.i.;. + 3c1e0: 01c74c21 ff82b0bd fe196809 ff66c64b !L.......h..K.f. + 3c1f0: 007001e9 ff14dc6c 0046e672 ff85c28c ..p.l...r.F..... + 3c200: fea49e39 ff500692 0161c4a9 0082b755 9.....P...a.U... + 3c210: 01de9e46 ffeaed3b ff1a1960 ff61afe8 F...;...`.....a. + 3c220: fef8790b 00c22358 fefcb4db 00e3084a .y..X#......J... + 3c230: 0149e3c3 ffa16eb8 01a4e931 002f3580 ..I..n..1....5/. + 3c240: ff790e52 003abec1 ff75ae30 00201784 R.y...:.0.u... . + 3c250: 01860a28 ff193316 ffb00bf0 0092396e (....3......n9.. + 3c260: 01ef8f75 ff76659d 004c5436 ff12b8cd u....ev.6TL..... + 3c270: ff48042f ff55704e 014232c1 ff34105d /.H.NpU..2B.].4. + 3c280: 00866908 ff486d0c 00fb9c3a 00cc2390 .i...mH.:....#.. + 3c290: fe75a02c 00c26b32 ffa54401 00a26e6f ,.u.2k...D..on.. + 3c2a0: fe28539e 00ead64c ffcdd83a ff9360ab .S(.L...:....`.. + 3c2b0: 0172e328 00f1e3b0 01b7f946 ff8b5488 (.r.....F....T.. + 3c2c0: fef77a3c ff75098f fe89aeb1 008ff749 ...-@8..... + 3c2e0: 01383922 0053ca69 00d09380 ff0a6706 "98.i.S......g.. + 3c2f0: ff418a4a ff645061 ff21aed6 ff4a8632 J.A.aPd...!.2.J. + 3c300: fe82976e 00ac546f fe4bc754 ff703bf8 n...oT..T.K..;p. + 3c310: 01b2d808 005fb709 fe081bee 00dccdaa ......_......... + 3c320: 0087e5c3 ffed4c62 011a5be2 ff27db52 ....bL...[..R.'. + 3c330: 01c7bee1 ff79c8d9 ff08b351 00ce418c ......y.Q....A.. + 3c340: fe57cfb2 ff2efcfa 016e5968 ff9ebdfd ..W.....hYn..... + 3c350: ff9ed690 ff36f5a0 015cb735 ffc2c815 ......6.5.\..... + 3c360: 01712192 00ff01d1 ff2b6aeb 00e834a7 .!q......j+..4.. + 3c370: 00dde59d 00191e33 011bddfa ff579341 ....3.......A.W. + 3c380: 00c47b4f ffdfc441 01112c4c 0044f155 O{..A...L,..U.D. + 3c390: fff9b7ca ffd4d441 019a2109 00503b47 ....A....!..G;P. + 3c3a0: ff3bc2af 0009488d 00f4a064 0038d0e6 ..;..H..d.....8. + 3c3b0: fe4b193b 00c2c250 fec80312 00739fa0 ;.K.P.........s. + 3c3c0: 01f78f84 ff395d6f 010bed3a ff87de86 ....o]9.:....... + 3c3d0: 016ca37a ffbe2b7b fecebdfb ff48b650 z.l.{+......P.H. + 3c3e0: 01e0f6d0 00093c11 0026cfa1 005b6d8d .....<....&..m[. + 3c3f0: ffd30fd8 006e4e88 ff68a362 ff795015 .....Nn.b.h..Py. + 3c400: 01b7b2ad 00048f7f fe523c68 ff0d10d6 ........h.3... + 3c420: feec8d3e ffe0379d 00f42772 fffabcc0 >....7..r'...... + 3c430: 00354ce4 ff515462 fe3dcbad ff373293 .L5.bTQ...=..27. + 3c440: 00bfebcc 00f4c534 fed32b58 0077bf1b ....4...X+....w. + 3c450: 009ae7bc 00a15142 01a0c15c 0078e3fa ....BQ..\.....x. + 3c460: 00e2377b 004811b8 fe0aa885 ff9c8716 {7....H......... + 3c470: ff671929 003aca30 ff5195ba 00ef86bc ).g.0.:...Q..... + 3c480: febdb5eb ffbc8bd9 0052304a 00e5da2e ........J0R..... + 3c490: 00fbfdbd ff0ce532 01bf8dd3 ff19f480 ....2........... + 3c4a0: fe7ae7a9 ffbd2f56 ff17b784 ff96b225 ..z.V/......%... + 3c4b0: 00fd8933 001f4ec8 00326916 00003c82 3....N...i2..<.. + 3c4c0: fe5ba384 00bbe717 00ef4fc0 ffa4669d ..[......O...f.. + 3c4d0: 011452c0 ff67b518 00ea09f0 ffa47b01 .R....g......{.. + 3c4e0: ff00e985 00f2f2ca 00f5ba3c ffc710f1 ........<....... + 3c4f0: fe9e74e0 ff5b7dbf 00cf56e0 ffe72579 .t...}[..V..y%.. + 3c500: ffc609e3 ffef990f fed9e879 0052704b ........y...KpR. + 3c510: fe390c5f ff69d633 0161dc94 002462c7 _.9.3.i...a..b$. + 3c520: fe0cd19c 0034d40a fe37b4d9 ffe8aad4 ......4...7..... + 3c530: ff5414d8 0087fa9d fe7f639d 0029ce01 ..T......c....). + 3c540: 01462495 ffc9c436 fe007457 0096abeb .$F.6...Wt...... + 3c550: 00eaa31b 00b487ca fe005fd0 005d9c7b ........._..{.]. + 3c560: 004b3eb7 00b6eb89 ffffe1cc ffd28bd6 .>K............. + 3c570: ff087302 006f0c1d 00019c34 fffb15fd .s....o.4....... + 3c580: fe1fa525 00d3820c fe35126a 009a632a %.......j.5.*c.. + 3c590: fe3dd90e ff5c0bd8 fe70c5c8 00c72693 ..=...\...p..&.. + 3c5a0: fe78fc24 004da96b ff9f7b01 00664bcf $.x.k.M..{...Kf. + 3c5b0: 00c4afa3 00f0012c feb0ba78 ff4c620d ....,...x....bL. + 3c5c0: fff17ced ffbc92e8 00e060c8 00291fcc .|.......`....). + 3c5d0: 000dc8d0 ff60e115 00c49caf 007ed0f7 ......`.......~. + 3c5e0: fef4b83e 0051ab02 009e7355 ff2d4036 >.....Q.Us..6@-. + 3c5f0: 00728a13 00cd4787 01932fe3 0042e7da ..r..G.../....B. + 3c600: 001cd1fd ffad0ff4 fe760f06 ffd09610 ..........v..... + 3c610: ff3216b9 ffcf7056 01d7714b ff2b923f ..2.Vp..Kq..?.+. + 3c620: fe13e104 ff3e17e3 fed6ff0e ffcd082d ......>.....-... + 3c630: fe97c557 ffd752d2 fff7f8f5 0046f880 W....R........F. + 3c640: 0057f7e1 0046785a 005cf5d5 00e2850d ..W.ZxF...\..... + 3c650: 0105b52f ff69a35c fe851e06 ff3db2e8 /...\.i.......=. + 3c660: ff1895e6 009e3112 fe3d64e4 fffbf374 .....1...d=.t... + 3c670: 015c4b4d ff93db51 fefea34c 00f6d58d MK\.Q...L....... + 3c680: fe9825e8 00642c61 013225c9 0039f4d4 .%..a,d..%2...9. + 3c690: ffb7abae 00704af9 001e9ca6 ff61ddde .....Jp.......a. + 3c6a0: fe495df3 ff6465fb ff5dd9d8 ffbb8afe .]I..ed...]..... + 3c6b0: ff34be8e ffb1cb3b 00345ec8 ff9e7273 ..4.;....^4.sr.. + 3c6c0: 016898a5 ffe2637e 01f49d76 0010c86b ..h.~c..v...k... + 3c6d0: 00e55ac1 00580679 fe5d209c ffd3f17d .Z..y.X.. ].}... + 3c6e0: ff9ded0e ff159aa5 ff16e0b8 ff9818fa ................ + 3c6f0: 001f4d71 ff17abf7 ffccb1ed ff918934 qM..........4... + 3c700: 0072b6c2 0095eae0 01676f0a 000481c9 ..r......og..... + 3c710: 004e8eee ff280634 fea5d56e 00fdcf3c ..N.4.(.n...<... + 3c720: 0045d73e ff006160 00ca2d31 ff167978 >.E.`a..1-..xy.. + 3c730: 01308beb ff222dc6 011b32b6 ff5bd283 ..0..-"..2....[. + 3c740: 0080362e ff697baf fe4e8dc6 ffeff443 .6...{i...N.C... + 3c750: fe6736f5 fff2264e fef95c02 ff57aefb .6g.N&...\....W. + 3c760: 00903f8b ff1b6c18 01126622 00981622 .?...l.."f.."... + 3c770: fe76e542 00638f32 0195a990 00981e76 B.v.2.c.....v... + 3c780: 017908b2 00129f08 ffe6655a 00771d81 ..y.....Ze....w. + 3c790: 010b2444 0037b7e8 ff60ff17 ffc129a1 D$....7...`..).. + 3c7a0: 00de8b3f 00f3b30f ff0f64ff 00873552 ?........d..R5.. + 3c7b0: 01953989 ffaaf063 fee4e616 ff52b431 .9..c.......1.R. + 3c7c0: 002b523d 00d9f56e 003d7dc7 0034fd2e =R+.n....}=...4. + 3c7d0: 00dbc58d 00c19fd3 fe697937 008114b7 ........7yi..... + 3c7e0: ffaa77a9 ff8bb2cb ffb62887 ffca0dac .w.......(...... + 3c7f0: 0094b241 002bcf08 017f357a 0030a14a A.....+.z5..J.0. + 3c800: fe80d6e3 fff30b56 01075664 ff8644f5 ....V...dV...D.. + 3c810: 01152b3d ff5e5498 fefa3cbe ffe876ef =+...T^..<...v.. + 3c820: 012588d6 ff6b4c71 0164685d ff17ce90 ..%.qLk.]hd..... + 3c830: 019a966e 00b967e4 fe3231da ff8b4d87 n....g...12..M.. + 3c840: 004e01b9 ff94a100 ffe91d61 ff9594cf ..N.....a....... + 3c850: 0000a8a0 ffab805b fe131c06 00f76f0b ....[........o.. + 3c860: ff96bb27 0095e88a ff443e75 ffbcd83f '.......u>D.?... + 3c870: fe20eaeb ffa0391d 01f10c19 00bf3ca9 .. ..9.......<.. + 3c880: ff8d8320 ff7b9fed fe5ec55e ff03fe74 .....{.^.^.t... + 3c890: fe61b35c ff5c6179 000e70aa 00f89515 \.a.ya\..p...... + 3c8a0: 0003e3f8 006d6050 014ac04b ffe25a0c ....P`m.K.J..Z.. + 3c8b0: 01446aa1 ff7f72d0 feff2a72 ff4a1a4a .jD..r..r*..J.J. + 3c8c0: fe96b3f7 003c8c79 ffc84693 ffa128d6 ....y.<..F...(.. + 3c8d0: ffc9bca1 ff87418d 00fc73f2 00ca2f3e .....A...s..>/.. + 3c8e0: feff95b4 00ed3782 ffba11a5 00c2a90a .....7.......... + 3c8f0: ffda6d9c ff7b8c70 fedf8068 ff6c8eb1 .m..p.{.h.....l. + 3c900: ffdb2579 ff124d80 01176c6f 004bc05b y%...M..ol..[.K. + 3c910: ff16f5ae ff3eec04 0199402b 00feade3 ......>.+@...... + 3c920: 01847aed ffba597f fe80528e 00ae54fc .z...Y...R...T.. + 3c930: 01b1b35a ff57d6f3 ffa23c67 ff0e82d0 Z.....W.g<...... + 3c940: 008b820b ffdb81ce ff9dd95e ffe6e6ef ........^....... + 3c950: fe9f7374 005f6ba4 0102da33 ffc67dd8 ts...k_.3....}.. + 3c960: fe80ca8c ff445f0b fe5d0937 ff0699ae ....._D.7.]..... + 3c970: 0060accc 006ea045 fe3126d5 00d5501b ..`.E.n..&1..P.. + 3c980: 00727d76 ff434646 ff498e0f ffb97a83 v}r.FFC...I..z.. + 3c990: fe3214f3 0028ed82 018c9fd2 ff4197c5 ..2...(.......A. + 3c9a0: 00429954 005a7ec3 01ecee10 ff66bb76 T.B..~Z.....v.f. + 3c9b0: ff851803 00e645bb 015cc538 ff5e45d5 .....E..8.\..E^. + 3c9c0: 01e58a50 00e607ce 01e66fde ff77e95b P........o..[.w. + 3c9d0: 01075909 00016202 ff854a94 ffb4f633 .Y...b...J..3... + 3c9e0: 0170b1e4 ff6cbd3a feedcbc2 00c3d115 ..p.:.l......... + 3c9f0: 01230a93 00e29d56 fe8ba31f ff4b0738 ..#.V.......8.K. + 3ca00: 00745a3e 00a93cb5 fed4a28a 001fa751 >Zt..<......Q... + 3ca10: ff705acd 00e37021 01759753 ff49e0b1 .Zp.!p..S.u...I. + 3ca20: ffd990ae ff4fcce6 ffe84d16 00ea4e72 ......O..M..rN.. + 3ca30: fe7e39e0 008d3109 01a593f2 ff8cb668 .9~..1......h... + 3ca40: 010c84a7 007f447b 012757e1 00086cfb ....{D...W'..l.. + 3ca50: 018fc1c6 ffcf8779 004616ac ff744432 ....y.....F.2Dt. + 3ca60: ff28af65 00e969f8 0007cba6 00dac56e e.(..i......n... + 3ca70: fe1afed7 00fde2a8 00608f1f 0029670b ..........`..g). + 3ca80: fecb81b7 ff4af764 00847ed5 002c93d2 ....d.J..~....,. + 3ca90: 011beac7 00b52f94 019e5b9b ffaf6936 ...../...[..6i.. + 3caa0: fe914e02 005f9a66 fe7fcf80 ffec7c34 .N..f._.....4|.. + 3cab0: 00475482 00d3f3dd 00cfaa98 00c76ade .TG..........j.. + 3cac0: fe5e54b7 ff38c85c 0173b68a 0092608e .T^.\.8...s..`.. + 3cad0: 00e48885 00961261 0042fb37 0004668c ....a...7.B..f.. + 3cae0: 009767ca fff8131e 00cfb833 0059c6ca .g......3.....Y. + 3caf0: fee1c537 fff95fa9 ff444142 007eeabc 7...._..BAD...~. + 3cb00: 0164dfa6 00f4ef70 00c21790 00b6273a ..d.p.......:'.. + 3cb10: fe182cf4 ffb344af 019a7698 0082a2b0 .,...D...v...... + 3cb20: fecc72d9 ff4e7ead ff1ede21 ff5b0224 .r...~N.!...$.[. + 3cb30: 00f38f02 00d7eb09 0197ab03 fff5d718 ................ + 3cb40: fea42fa8 00cf92f1 00b48145 0071f344 ./......E...D.q. + 3cb50: fe483590 000e2dfb 00a86e17 ff4f4444 .5H..-...n..DDO. + 3cb60: fe5f466e ff905bae ff5fce21 ff072989 nF_..[..!._..).. + 3cb70: fe99bb13 ff70ff23 feb99109 00259d32 ....#.p.....2.%. + 3cb80: 0131700b ffbe0866 01a9f3ea 0017553c .p1.f........ + 3cbb0: ff47e661 004c3d66 ffecd41a 001061a4 a.G.f=L......a.. + 3cbc0: 00923bc6 00c417a3 003d1838 00c162b5 .;......8.=..b.. + 3cbd0: ffe593fb ff18bd62 ffce362e 00f652ea ....b....6...R.. + 3cbe0: 012667b7 00cc3e6d 00e0f00a ff751692 .g&.m>........u. + 3cbf0: 00789a8e 0023d445 017663d0 ff03ff79 ..x.E.#..cv.y... + 3cc00: 00c20648 ffc51175 00170f7d 00994f9a H...u...}....O.. + 3cc10: ffc55ed6 ff9337b9 fe4efe3e 0099527f .^...7..>.N..R.. + 3cc20: ff3f666e ffa1526c 01d4bb69 00278a50 nf?.lR..i...P.'. + 3cc30: ff5dff3c 00ba0c48 011ffbd2 ff90a7be <.].H........... + 3cc40: fe132ce4 00e84380 fe6bf9d6 ff569188 .,...C....k...V. + 3cc50: 00b02e84 ffe3bbbd 008c16d0 0074d3d9 ..............t. + 3cc60: feba5132 001ffa8b 01c6401e 00649b87 2Q.......@....d. + 3cc70: fe17cea0 ffd3a2bb 003fbc10 0031d0fe ..........?...1. + 3cc80: 00bf5455 fff2c0f1 01917e99 ffa2a2ea UT.......~...... + 3cc90: 01d861e6 007e8740 01df94be ff2b0034 .a..@.~.....4.+. + 3cca0: 01bd271c 00ee8840 00b9c4af ffd5e262 .'..@.......b... + 3ccb0: 01f49f7f 003cafe2 018ee9a0 ffcff3b4 ......<......... + 3ccc0: 01599845 0015651f fea41990 00d1bf8b E.Y..e.......... + 3ccd0: 0079195b 00059320 ff7bba27 ffe6733f [.y. ...'.{.?s.. + 3cce0: ffc6a75d ffdcd58f ff139cb3 007a4219 ]............Bz. + 3ccf0: ffd9a0d6 ff3e2d02 fe924f6a ff638933 .....->.jO..3.c. + 3cd00: ffe76457 ffe891af ff01b865 007d09ae Wd......e.....}. + 3cd10: 01a12552 ff8d7224 ff8ede30 009abaf5 R%..$r..0....... + 3cd20: feddae05 ff9b723f 01a03787 00871f50 ....?r...7..P... + 3cd30: 01b3fa7e 002ddaec 01911c14 00499310 ~.....-.......I. + 3cd40: 0184bdf9 ffc0bd11 ffc68edf ff0f1448 ............H... + 3cd50: feed35fa 00120b0f fe71d31b ff386bd5 .5........q..k8. + 3cd60: ff9293ae 00307e60 016dc117 005ea225 ....`~0...m.%.^. + 3cd70: fef99dc7 ffbb8018 feb231cd ff2aa45d .........1..].*. + 3cd80: 01eb772b ffedb758 ff01d2da 002afe6b +w..X.......k.*. + 3cd90: ff630ae6 00e200a2 005beddb 00cbb281 ..c.......[..... + 3cda0: fe5f32d0 ff5fd0ce fe59bff7 ff4fea6e .2_..._...Y.n.O. + 3cdb0: 00f33da5 ff707a14 feb9f6f6 007b0467 .=...zp.....g.{. + 3cdc0: 01e663e9 fffc5bdb ff16dec7 ffe9f5b3 .c...[.......... + 3cdd0: 00eaf1d3 ffc0fa6f 00885455 ff323a65 ....o...UT..e:2. + 3cde0: fe9cad83 ff332d77 fe10e976 00d65af2 ....w-3.v....Z.. + 3cdf0: 01db9f5e ffea0303 fe5c4c62 00e63650 ^.......bL\.P6.. + 3ce00: fee7e405 ffdf1835 01763871 ff018414 ....5...q8v..... + 3ce10: 00ecd2ab ff9ef138 ff1373ba 00aee508 ....8....s...... + 3ce20: 01002c30 ffa67272 ffe24906 00f459cd 0,..rr...I...Y.. + 3ce30: 014be389 0038adf8 fef6784a ff0b0377 ..K...8.Jx..w... + 3ce40: ffc67851 ff627a88 01ddf192 ff4ec26d Qx...zb.....m.N. + 3ce50: 0146f1df ffa9c8d6 ff2fbe61 ffae672f ..F.....a././g.. + 3ce60: fe485c63 ffb4e976 fee923c1 ff20e51a c\H.v....#.... . + 3ce70: 00c6fcde ff472bcc 00ac54c7 00be6686 .....+G..T...f.. + 3ce80: fe61ee6f 00e628e6 fe40cde3 00e10cc8 o.a..(....@..... + 3ce90: 00de19a6 ff334571 00189f8f 004ab8a7 ....qE3.......J. + 3cea0: fe74e01d 00e9d09e ff7e74c1 ff850bd4 ..t......t~..... + 3ceb0: 018c3a16 ff3324cc 002b1ee8 ffb546eb .:...$3...+..F.. + 3cec0: fe923840 ff5412a9 ff0d01e2 ffb032c8 @8....T......2.. + 3ced0: fef5d534 0061d1a8 003747bf 009c4e22 4.....a..G7."N.. + 3cee0: 013a90e8 00bd4ab9 fe958eba ff7f4540 ..:..J......@E.. + 3cef0: ff93cba1 00bf97b0 fecbe788 0089b6a3 ................ + 3cf00: fefb7ea1 004220e9 0042cf44 00251c1e .~... B.D.B...%. + 3cf10: 0160725d fff75cfe 0045ab2c ff0b77ca ]r`..\..,.E..w.. + 3cf20: 013276bc ff8853ff 001a5247 0002e346 .v2..S..GR..F... + 3cf30: 0179eb20 009a29b5 fee58647 0024ffca .y..)..G.....$. + 3cf40: 00059829 ff493f9a 007cb622 ff96dd79 )....?I.".|.y... + 3cf50: 01d5cc1a 0057ac29 ff929d5a 0014826d ....).W.Z...m... + 3cf60: ffc86b47 00bd66f3 fe91c301 0075582e Gk...f.......Xu. + 3cf70: 00e3ce08 fffd6ebf fe14806d ff335586 .....n..m....U3. + 3cf80: 0170b189 ff1622d8 ffd01083 00aa9579 ..p.."......y... + 3cf90: 01171372 ff1f50a6 007af071 00fab3e8 r....P..q.z..... + 3cfa0: feb46e44 0077aad2 ffa46cdf ffe94fcf Dn....w..l...O.. + 3cfb0: fee2e51b ff5162d1 0007444f 0064b983 .....bQ.OD....d. + 3cfc0: ffa21daa ff6ba211 010b1539 ffb5c864 ......k.9...d... + 3cfd0: 01a6417f 00cc86a5 00a8a768 004fa401 .A......h.....O. + 3cfe0: 013b8792 ff803246 fe0d7766 008706e3 ..;.F2..fw...... + 3cff0: ffb38ea2 00de64a0 01dbe01b ffc35d9e .....d.......].. + 3d000: 00898dea ff7d1810 ff2fceee ff621161 ......}.../.a.b. + 3d010: ff0c6e74 004d7360 ffe8e35b ff4ffef8 tn..`sM.[.....O. + 3d020: fe06e55c 008bc658 00814bce ffce4dfa \...X....K...M.. + 3d030: 017bf48d 00dc458a 01069720 ff16a783 ..{..E.. ....... + 3d040: fea744ed 0096bdc7 ff8aaba3 ff06bc33 .D..........3... + 3d050: fe891d5f 00b3e294 ffd06bb5 ff521f86 _........k....R. + 3d060: ff2d6597 00e1ca81 009348e0 ff978a30 .e-......H..0... + 3d070: fece40c3 009edaed fe891d6a ffe9bdfd .@......j....... + 3d080: ff110f67 00ff61c2 fea92db2 009be1c6 g....a...-...... + 3d090: ff753027 00736a87 00b52661 ff412f96 '0u..js.a&.../A. + 3d0a0: fee58253 008126f6 fe9aef5c 007f635b S....&..\...[c.. + 3d0b0: ff216fa1 fff2d9ee ffc3b983 ff9ebfd5 .o!............. + 3d0c0: 00da9629 0083a984 01fc5459 ff8046ab ).......YT...F.. + 3d0d0: fecbf8a3 ffb43201 01554c7c 00506ffb .....2..|LU..oP. + 3d0e0: ffef4263 ffb6ed9a fe857edd ff63cc4a cB.......~..J.c. + 3d0f0: ff779341 ffa73863 ff95f84f ffe49b74 A.w.c8..O...t... + 3d100: fe0e2bed ff0b8945 01f1fa16 ff8f7a5b .+..E.......[z.. + 3d110: 00f3f9cd ff3c1ad4 01b0b630 ffbf1730 ......<.0...0... + 3d120: fe9879cb ffd54a2d fe125a3e ffe6a3f5 .y..-J..>Z...... + 3d130: ff746ab9 009f2353 ff02210c 003e2250 .jt.S#...!..P">. + 3d140: ffae5710 005565ad fe5124ca ffcc45a0 .W...eU..$Q..E.. + 3d150: 00bbe140 005ece3a 002f9056 00f556e5 @...:.^.V./..V.. + 3d160: 01be913f 00270525 001afb6d 00ea9389 ?...%.'.m....... + 3d170: ff9179a2 ffce7490 ffb9e8c5 ff8cbeb7 .y...t.......... + 3d180: fffe0c49 fff2148b ffef5aaa ffbb4261 I........Z..aB.. + 3d190: fe87b5f5 003488de fe3305f5 004e2fcb ......4...3../N. + 3d1a0: 00d86598 007d1749 012160fe ff49d2eb .e..I.}..`!...I. + 3d1b0: 0158d12b 006d8107 fee4687a 00cbf2aa +.X...m.zh...... + 3d1c0: ff87ccf2 ffe91cca 007f0641 0047909f ........A.....G. + 3d1d0: 005f8c64 000d964e 01766bfb ff7d3ab6 d._.N....kv..:}. + 3d1e0: ff6c2601 ffd1bd8d 017d9b08 ff5ba371 .&l.......}.q.[. + 3d1f0: ffbe4f79 ff6cef86 00f82f4c 00efe4a3 yO....l.L/...... + 3d200: 000a6f11 ff4b9558 00efebd7 ff189fa7 .o..X.K......... + 3d210: ff6c972f 00bcd16b fe63e7e9 ff94ca1c /.l.k.....c..... + 3d220: ff8a23ae ff44186e 00b54502 0052666b .#..n.D..E..kfR. + 3d230: 0007ed66 ffed245c 0153a2dd ff06ca37 f...\$....S.7... + 3d240: ff87ea87 00defa18 fea85e41 ffd2f8f5 ........A^...... + 3d250: fec96ca7 006fa1ff 00fe08cd 00740d88 .l....o.......t. + 3d260: ff84b064 ff7ed72b ff8285b1 00944f9e d...+.~......O.. + 3d270: 0125e043 ff15ce0c 016e223e ffaf68ed C.%.....>"n..h.. + 3d280: ff6f8450 0048ae8e feb4e554 008cb369 P.o...H.T...i... + 3d290: ff0ff840 00108ae9 fe7b43f5 ffd479da @........C{..y.. + 3d2a0: 01da5f3f ff8985d5 ff52b68f 000b1c30 ?_........R.0... + 3d2b0: 018d72f4 ff4cafd1 ff96b59d ff03e5ba .r....L......... + 3d2c0: 016f9da4 008bbde7 ffbeca77 ff406ada ..o.....w....j@. + 3d2d0: fe3feb44 ffac1a60 010b2fbb fffb12d7 D.?.`..../...... + 3d2e0: 00595451 00803a44 0105715e ffd0815c QTY.D:..^q..\... + 3d2f0: fe530f61 00bc1c09 00a409ef 0098cd3c a.S.........<... + 3d300: ff62a3c0 003c12b8 008bb6d9 ff783b6d ..b...<.....m;x. + 3d310: 00fbc004 fff0d2a9 fe5cac25 fff5d394 ........%.\..... + 3d320: 003441b3 00730dfd 01ceaeb9 ff95bc72 .A4...s.....r... + 3d330: 00ad5aed ffc0c72b 00716c58 004c2334 .Z..+...Xlq.4#L. + 3d340: ff941942 ff0704dd ff72f197 00e8d1be B.........r..... + 3d350: 00c73262 ffd59697 01244a12 00072835 b2.......J$.5(.. + 3d360: ff418713 0045ac1a 0055edae 00295f63 ..A...E...U.c_). + 3d370: 00103803 ffb1a027 feda6ac8 ff5444b9 .8..'....j...DT. + 3d380: fe3dba5b ff8d8f43 ffa6f40d 00c67263 [.=.C.......cr.. + 3d390: ffa36ec7 00ba12c1 01f6ef7c 0016446e .n......|...nD.. + 3d3a0: 012eeb02 006b3cd4 01692a69 0098e60e ......d...^..... + 3d460: ff70164c 004f6678 01e5c0ca 00d7b0c8 L.p.xfO......... + 3d470: fff44029 004eb8ce 013f2da7 ff0023a0 )@....N..-?..#.. + 3d480: ff8e0c3b ff9009cc 01e55edb 00701b7a ;........^..z.p. + 3d490: ff6d69bd ff4ad040 01377ffb 00c6e202 .im.@.J...7..... + 3d4a0: 00d14c2c ff4d9897 012e17d2 ff45abc9 ,L....M.......E. + 3d4b0: 00e7d32c ffe025be ff3ec4f5 ffdeb5a9 ,....%....>..... + 3d4c0: 0011d322 ffc5f177 019823e5 ff284515 "...w....#...E(. + 3d4d0: 00a1e2b2 00c1b394 01fec2db ff33ce28 ............(.3. + 3d4e0: 01fa5ce7 00aa9943 00f19415 ff5245aa .\..C........ER. + 3d4f0: ffe71279 0003725c 00e63eb8 ff57c9e1 y...\r...>....W. + 3d500: ffa26092 00dcf2b5 01ddbbad ffaa3ee2 .`...........>.. + 3d510: 01d97e38 ffe30d75 00ef2cb3 ff9b8d9d 8~..u....,...... + 3d520: 0053dd90 00d0d1eb 01a5112a 008551fb ..S.....*....Q.. + 3d530: fec9f57c ff18d361 00a6d653 ff09249a |...a...S....$.. + 3d540: 007f2ff8 ff8cdb5a fe26d9a1 ff3f93d4 ./..Z.....&...?. + 3d550: 01945442 000103cf 015986e6 ff7a4e7f BT........Y..Nz. + 3d560: ff019be0 004a8852 ffd09cb2 ff3119ba ....R.J.......1. + 3d570: 01d203de ffbe96e5 ff34a255 ff8d5429 ........U.4.)T.. + 3d580: fe547b49 0096115d 011c1377 ffd71620 I{T.]...w... ... + 3d590: ffcc171c ff34f18e 007d34e4 00cf4c1d ......4..4}..L.. + 3d5a0: fefaa7d7 00e6a4af 0169cf37 fff5bb6d ........7.i.m... + 3d5b0: 01dc2ca1 ff806529 005e10a7 ff6bd65d .,..)e....^.].k. + 3d5c0: fe004876 ffea3d50 007daf79 00fba98b vH..P=..y.}..... + 3d5d0: fe932761 ff31c4fa fe6eb3a5 ffbb46df a'....1...n..F.. + 3d5e0: 017d8e16 ff8ab39a 012ab076 0099ae0a ..}.....v.*..... + 3d5f0: 00665c9c ffa10da8 0020108f ffb4c5fa .\f....... ..... + 3d600: 012ca3cb 00242057 ff1499a1 000ffc7b ..,.W $.....{... + 3d610: 0050e319 008e583c 01c91611 ff4dcd9a ..P.......{... + 3d700: ff29551a 00b76fe2 0097e7d5 ff073b04 .U)..o.......;.. + 3d710: 00948aee ff219342 ff8df61f ff748dd1 ....B.!.......t. + 3d720: 001f7068 00aca158 fee6d753 00976f2f hp..X...S.../o.. + 3d730: 0134262d 00cc2d84 fe6d808a ff8675e9 -&4..-....m..u.. + 3d740: feadbef3 00f0ecf1 feec7f52 ffa1df28 ........R...(... + 3d750: ffe1b66e 00efae7b 0191f287 009ad133 n...{.......3... + 3d760: fe730396 fffca4d9 01459c37 ffff5e54 ..s.....7.E.T^.. + 3d770: 012d49e8 ffd41314 fe3bc560 0021fb60 .I-.....`.;.`.!. + 3d780: 0149c726 fff7ac40 ff387475 001211e4 &.I.@...ut8..... + 3d790: 01678a3e ffa4e5f6 fec976f4 ff9f2056 >.g......v..V .. + 3d7a0: 0189226d 00bad355 fec1c10a 00b1c27a m"..U.......z... + 3d7b0: ff66ee7a 00abdaa2 01a1d96c 0022aa9e z.f.....l.....". + 3d7c0: 019b2fb0 ff0be4b5 00009c08 005d4b10 ./...........K]. + 3d7d0: 01ff62ce 00239a3a feb8f30c ff427543 .b..:.#.....CuB. + 3d7e0: 007be5e6 006e2ac9 feb2e486 ff766cba ..{..*n......lv. + 3d7f0: ff9a133a ff3ea952 01738f72 ff32c4ef :...R.>.r.s...2. + 3d800: ffc130ad ff540293 fe938696 0049e85f .0....T....._.I. + 3d810: fe34e36d 000a89bf fe1ecc28 ff61344c m.4.....(...L4a. + 3d820: 007eeba4 00bc7cfe 0115b64a ff231d79 ..~..|..J...y.#. + 3d830: fe071ef1 ffd6da55 fe965407 ff751b51 ....U....T..Q.u. + 3d840: fe989fa0 ffdd1842 013c0ae3 0066878d ....B.....<...f. + 3d850: 0196bdd0 005cb375 ff881684 001cc778 ....u.\.....x... + 3d860: fe4f8115 004109b6 00a9a3da ffc693f6 ..O...A......... + 3d870: 0190266b ffcdaf4e fefa05d6 ff1d582f k&..N......./X.. + 3d880: ffcc2fa4 ff06372b fecf8683 00d66474 ./..+7......td.. + 3d890: 014b8c60 0090dc6a 011c20c3 ff0551ac `.K.j.... ...Q.. + 3d8a0: ff34b3c7 00cb5425 00ae70aa 005b040b ..4.%T...p....[. + 3d8b0: 011bf445 005c8375 ffaf9821 ff6b998c E...u.\.!.....k. + 3d8c0: fe2b87fb ff048a57 fe93eac6 ff549879 ..+.W.......y.T. + 3d8d0: 019b65cd 0019099d fe116a48 ff00996c .e......Hj..l... + 3d8e0: 00bae5bd ffb008c1 00d195ae 001d82ee ................ + 3d8f0: 017ed6e9 0066e23d 0104a339 ff336fc6 ..~.=.f.9....o3. + 3d900: 014e4f2d ff0ad273 ff1909da ffc68b9e -ON.s........... + 3d910: febb52d3 00538550 01e6819d ff8685f3 .R..P.S......... + 3d920: 00108828 ff4f6b4d 015c55b7 00caccb1 (...MkO..U\..... + 3d930: ff9347a3 00be4598 01bc33ac ffacd2fa .G...E...3...... + 3d940: 0171f2d3 ff1a5959 fe6f4240 002a9874 ..q.YY..@Bo.t.*. + 3d950: ff1b27a1 00fe5036 0173d16a 00617c67 .'..6P..j.s.g|a. + 3d960: ff62e6dd 0006e71f fe78c0b2 ffcbd90f ..b.......x..... + 3d970: 004f9e7c 00f79170 0130fa5c ffc1b5a3 |.O.p...\.0..... + 3d980: fe8e2f25 ffa5bd90 00f0922e 00804b06 %/...........K.. + 3d990: fec89d29 00d57957 00ec7101 00fa2d05 )...Wy...q...-.. + 3d9a0: 00520c90 00e76c1f ff77efe1 ffbd07a7 ..R..l....w..... + 3d9b0: ff84e4bb 0022bd6e 01cc2c5e 00c534a2 ....n.".^,...4.. + 3d9c0: fef1bc4e 008d1439 012f92f4 003364ce N...9...../..d3. + 3d9d0: fe946b7d 004dc31b 015afd98 ff908f07 }k....M...Z..... + 3d9e0: 001f2533 ff267722 0076c507 00d3bc99 3%.."w&...v..... + 3d9f0: fe741497 ff3441f5 016efdb4 00d1b12f ..t..A4...n./... + 3da00: ff1163a1 00cade76 01fcb37d ff7e367b .c..v...}...{6~. + 3da10: 00bf3991 0079ba37 008af30a ffe5d3cd .9..7.y......... + 3da20: fef19c7d ffb99c94 ffbc13e3 ff20297c }...........|) . + 3da30: fece221f 00533911 ff2516cc 0062602a ."...9S...%.*`b. + 3da40: 01b86677 001cbe03 ffda526e ffc0ccc8 wf......nR...... + 3da50: 007691c9 0092cc75 01622084 0079c2c0 ..v.u.... b...y. + 3da60: 01f8a16a 007c58ed 001ad417 ff5aabcd j....X|.......Z. + 3da70: 01d830f8 ffe6258d fe00cb7c ff1ea89e .0...%..|....... + 3da80: 0015f8d6 ff07bb70 ffef854b fff3e34a ....p...K...J... + 3da90: 004693fa 00a278d6 ffb309a7 00129e16 ..F..x.......... + 3daa0: 01d14dda ff516d61 ffb321f4 ff393439 .M..amQ..!..949. + 3dab0: ffd2ac41 ffd147f9 00eea98e ff99bd9e A....G.......... + 3dac0: fe67feae 000e2162 ffe64c8d ff348b71 ..g.b!...L..q.4. + 3dad0: 00d43a0f ffc9d7a8 01d7ccf8 ffa044df .:...........D.. + 3dae0: feb79a39 0079e72f 0089a66a 008a8851 9.../.y.j...Q... + 3daf0: 00332ba5 003d8be7 fe3b5f39 ff196276 .+3...=.9_;.vb.. + 3db00: 01ec3f97 fffabe5e 0172b9a9 ff3afa05 .?..^.....r...:. + 3db10: 0161694b 0086dfd7 01a36371 00703e80 Kia.....qc...>p. + 3db20: 00936a63 000ac3a3 00b6cd21 ffae0ed6 cj......!....... + 3db30: ffe72681 00dfb635 ff9f2a62 00280df7 .&..5...b*....(. + 3db40: 01b1d2bc ff001506 fe943dff ff812d89 .........=...-.. + 3db50: fe741a59 0072267e fef232fb ff808679 Y.t.~&r..2..y... + 3db60: fea7f9cc 00d7eba5 00f3b1ca 003e8d85 ..............>. + 3db70: 01be82f0 00ffaf6e 01921400 ff79d225 ....n.......%.y. + 3db80: 00822707 ff54fa8e 00cfc88d ff685f09 .'....T......_h. + 3db90: 00aef40b 007ee886 fe7b01a7 ff95c110 ......~...{..... + 3dba0: 01efe9e8 ff7046d5 fea074fc ffdcdef2 .....Fp..t...... + 3dbb0: 00e355cd 003ab907 013ff776 ffb14d74 .U....:.v.?.tM.. + 3dbc0: fec8f53e ff25123f fee8356b 00d3dd32 >...?.%.k5..2... + 3dbd0: fe07dba2 002b5e02 feb63eb6 ffc84ea0 .....^+..>...N.. + 3dbe0: 00aa8c87 00e4b8eb fe8a35af ff4d3a50 .........5..P:M. + 3dbf0: 0102c998 0022c43f 00b81e05 009ab0ab ....?."......... + 3dc00: 00ce3b79 00276326 fe4d50ac 00978600 y;..&c'..PM..... + 3dc10: fef121ba ffdffd5e 00fc722c ff397e6c .!..^...,r..l~9. + 3dc20: ff0d28c9 ff1be527 0117ef27 ff337997 .(..'...'....y3. + 3dc30: 00f89699 ffaeea0a fe04f676 0026f5c8 ........v.....&. + 3dc40: 01f2a145 0096b210 00823871 00691fab E.......q8....i. + 3dc50: ff6c581a 006a2a31 0042a9fb 00955d45 .Xl.1*j...B.E].. + 3dc60: 00fe3914 006f19a4 ff5abc5a 00c504cc .9....o.Z.Z..... + 3dc70: 0132d528 ff8460d4 feb48a58 ff7c92e4 (.2..`..X.....|. + 3dc80: 00f7f6b8 ff567541 fed266fd 002479fe ....AuV..f...y$. + 3dc90: ff037389 00d8183c 001d1286 0061e23b .s..<.......;.a. + 3dca0: 00478eb0 00a1d107 fe3354bd 0048fa9b ..G......T3...H. + 3dcb0: ffeb54d5 00e0de2d ff8f94ee ff352aaa .T..-........*5. + 3dcc0: 0075a74e ff2800ba ff67b17d 0042e145 N.u...(.}.g.E.B. + 3dcd0: 015807e3 0006ac4b 01e32da9 ff462410 ..X.K....-...$F. + 3dce0: ff090232 0016c18b fee7b78f 003245da 2............E2. + 3dcf0: 01a138ec 002a83d5 fe2c918a ff28e588 .8....*...,...(. + 3dd00: ff233f31 fff5913d fe02c065 0071a7e8 1?#.=...e.....q. + 3dd10: 01266898 00dab979 fed38b79 0023f077 .h&.y...y...w.#. + 3dd20: fed9bd41 ffa2b3bb 00e6bba0 ff0ef83e A...........>... + 3dd30: 00614e3c ffa3f7ff ff5b3be1 ff3a476b ....l..... + 3dd70: 015b508f ff655d83 01022790 00b2faff .P[..]e..'...... + 3dd80: feec1105 002e208b fe26bccc ff3473f5 ..... ....&..s4. + 3dd90: fe4971bf ff456cbf 01f54516 00b2cb17 .qI..lE..E...... + 3dda0: 00aa63aa 006ff841 ff996c25 00452540 .c..A.o.%l..@%E. + 3ddb0: fe3e5800 ff909459 01e044bf 003527f1 .X>.Y....D...'5. + 3ddc0: ffedcb29 ffc27e91 fffd2add 00976319 )....~...*...c.. + 3ddd0: 01dffd61 ff31734a ff48af06 00cbb03b a...Js1...H.;... + 3dde0: 01f9b77c 0063e4e4 fecf0c81 ffc3c0a8 |.....c......... + 3ddf0: fe10b0cc 00abea98 ff55254d ff877821 ........M%U.!x.. + 3de00: 01e3c28e 003ad61f ff7dbbd5 ff3c2ee8 ......:...}...<. + 3de10: fe2a74be ff13b297 feed3e33 00c1eccc .t*.....3>...... + 3de20: 003ce8c2 ff9d22ac feb810bd ff5f0367 ..<.."......g._. + 3de30: fe24e98d ff0b1929 00a6c315 002df576 ..$.).......v.-. + 3de40: ff95d543 ff120c9f 01e3a4bb 000519a0 C............... + 3de50: 01c34e0c 00e1c52b fe298e30 ff3c9bc4 .N..+...0.)...<. + 3de60: 0112c7df 009c8891 fea975fc 00eee291 .........u...... + 3de70: 006b17ef ffbcb56d fe3170e6 ffedaa49 ..k.m....p1.I... + 3de80: ffe3b7e7 0014dc50 017f6bc2 0065cd7f ....P....k....e. + 3de90: 01c5342e ff24abd2 ff5a0358 008d9738 .4....$.X.Z.8... + 3dea0: ffffbb60 00c84e2a 014646fe 00a87df4 `...*N...FF..}.. + 3deb0: 018a44cc 0046d77c fec84266 00e43411 .D..|.F.fB...4.. + 3dec0: fe8fdc75 007bf8cb ffae1238 ffa497ba u.....{.8....... + 3ded0: 01d0e833 ff2be4a0 01191df9 003fbe44 3.....+.....D.?. + +0003dee0 : + 3dee0: 018c3b85 ff24f1bd 01c325f8 0037dc60 .;....$..%..`.7. + 3def0: ff3e4cb7 003d42c3 01a44c32 ff4ca4e1 .L>..B=.2L....L. + 3df00: ffa33d4c 001f3e75 ff409151 000e4176 L=..u>..Q.@.vA.. + 3df10: ffd673a2 002e8a06 fff4e67c 008f8a0a .s......|....... + 3df20: 00c21a34 004cf4b8 01298f81 ff13f4be 4.....L...)..... + 3df30: ff7aaa7b 00448162 0093d579 ff1e6556 {.z.b.D.y...Ve.. + 3df40: 009b67a1 ff43598c 01bee5ef 00b50b43 .g...YC.....C... + 3df50: fe89f0c6 ffbc45ee 00ee9743 ff6c2a13 .....E..C....*l. + 3df60: 017155e5 ff874432 00096a11 ff016732 .Uq.2D...j..2g.. + 3df70: 01a80150 ff1e9823 01b9a810 ffe85938 P...#.......8Y.. + 3df80: 00fcd265 0047fa29 ff4faacc ffef2e0e e...).G...O..... + 3df90: 00ef4d50 ff4bd6bd 00f98d11 ff4c5026 PM....K.....&PL. + 3dfa0: 007555be 00aae456 01d0d89c ffa4cfc3 .Uu.V........... + 3dfb0: ff4c4296 ff10e1af 0162508d 00f2db4c .BL......Pb.L... + 3dfc0: 0072a2c6 0098da2e fef12b9b ff68a09b ..r......+....h. + 3dfd0: 00a5bb33 00af1102 01a05442 001e3af7 3.......BT...:.. + 3dfe0: fe354123 00bfec45 01f5862d 00dd7ba3 #A5.E...-....{.. + 3dff0: ff146e20 00a51734 0047d6ba 0060b0e9 n..4.....G...`. + 3e000: 0136eff2 008a5939 ff540053 0064a088 ..6.9Y..S.T...d. + 3e010: fe788e5c 00be7c68 ff3eb1b5 005529fa \.x.h|....>..)U. + 3e020: 012a8298 00f6fc60 fe3f9797 003e85ef ..*.`.....?...>. + 3e030: 009c3820 ffbda72d 01b3858e 00d35683 8..-........V.. + 3e040: fe96b3bb ff0eaafa 004ea3d2 00973425 ..........N.%4.. + 3e050: 001a4d63 ffd59cee 01d1c0d5 00542e49 cM..........I.T. + 3e060: 01294114 004fce36 fe9283c9 ff186faa .A).6.O......o.. + 3e070: fe3221b1 ffcb26ab 0074f74e 0099ddd1 .!2..&..N.t..... + 3e080: 01b28085 00192c3a 013b27c9 00fc13bd ....:,...';..... + 3e090: 01d2e531 0075bb75 01b8b3b5 00db7200 1...u.u......r.. + 3e0a0: 00935e30 003829f5 fecc0d7d 0077adf4 0^...)8.}.....w. + 3e0b0: fe20dd2c 0014ea54 01c6a0f9 ffea7eec ,. .T........~.. + 3e0c0: fea8632f ff99e2aa 00d8b366 ff7a8de2 /c......f.....z. + 3e0d0: fe99427a 0086f5b6 0119e4e3 ffeb39d6 zB...........9.. + 3e0e0: ff38add8 00d2e7b5 ff9d8077 ff885f81 ..8.....w...._.. + 3e0f0: 00337e6e ffb7a902 fe628207 ff5eb045 n~3.......b.E.^. + 3e100: 01e30474 ff91f2d9 011fadca ff270169 t...........i.'. + 3e110: 0045af2e ff3a2fe4 fe45e0d7 ff4538cf ..E../:...E..8E. + 3e120: ff8bfe10 ffd4cf17 ff7e14ca ff60d55f ..........~._.`. + 3e130: 0021b009 ffcf05c8 fe802af1 ffc02123 ..!......*..#!.. + 3e140: 01c4e5f8 00781181 ff9767fb ff703407 ......x..g...4p. + 3e150: ff42388c fff5e228 fe2546d9 ff09d6ac .8B.(....F%..... + 3e160: 01864348 ffd6c092 0070262c ff4bb844 HC......,&p.D.K. + 3e170: 00fb5ace 008deb95 003aaab5 00eff474 .Z........:.t... + 3e180: 00029d5c 0062ad66 016089e9 00cb317f \...f.b...`..1.. + 3e190: 00949b05 ff099417 000c7ad3 ff1a8622 .........z.."... + 3e1a0: 0088ccdb ff290886 fe2b53e0 00f71955 ......)..S+.U... + 3e1b0: fe007f6d 003088a9 ffdb77ee 00d5ade7 m.....0..w...... + 3e1c0: fefe12ce ff07ba08 0107097e 00482a6f ........~...o*H. + 3e1d0: feec346f 008d3f60 fe7fbf93 ffc04ecd o4..`?.......N.. + 3e1e0: 01ed6a0e 004cdbbb febbf3af 00ad5969 .j....L.....iY.. + 3e1f0: 01591955 0094f3a2 fed17602 00099e21 U.Y......v..!... + 3e200: ff2ea38b 0028465d fe8e2a6c ff8efc6f ....]F(.l*..o... + 3e210: 0090df9b ffa7e533 ff9bfc49 ff0c745e ....3...I...^t.. + 3e220: ffdaa098 ff25ee9c ffcfeab3 ffb300c5 ......%......... + 3e230: 008da49a 0068c4e1 fe19230a fff2d4d1 ......h..#...... + 3e240: fedefd61 00e565b8 017f12de ff8788a4 a....e.......... + 3e250: fe8ccf1e 00f36192 fe1ac081 ff2154c9 .....a.......T!. + 3e260: ff4e0a6f ffb25193 00180404 ffd7eea1 o.N..Q.......... + 3e270: 00218d06 ff0ed735 ffd0b529 009d8be7 ..!.5...)....... + 3e280: ffddcbb3 0071b9ff fface2bd ffd64271 ......q.....qB.. + 3e290: ff2d3eca ff084066 fe10ae4e ff447585 .>-.f@..N....uD. + +0003e2a0 : + 3e2a0: ff5978b6 00d37285 ff156ebd 006a0a0f .xY..r...n....j. + 3e2b0: 0001c029 ff79e898 ffa03cbc ffce7199 ).....y..<...q.. + 3e2c0: fee2b700 ff480db4 ......H. + +0003e2c8 : + 3e2c8: fe0ea0b0 ff86c9d3 008f189e 0035697f .............i5. + 3e2d8: 00bd0c60 fffbd7a7 fe804c9f ffe1656a `........L..je.. + 3e2e8: 0004fc1e 00ae0c92 ........ + +0003e2f0 : + 3e2f0: 3f7fec43 3f800000 3f7fec43 3f7fb10f C..?...?C..?...? + 3e300: 3f7f4e6d 3f7ec46d 3f7e1324 3f7d3aac mN.?m.~?$.~?.:}? + 3e310: 3f7c3b28 3f7b14be 3f79c79d 3f7853f8 (;|?..{?..y?.Sx? + 3e320: 3f76ba07 3f74fa0b 3f731447 3f710908 ..v?..t?G.s?..q? + 3e330: 3f6ed89e 3f6c835e 3f6a09a7 3f676bd8 ..n?^.l?..j?.kg? + 3e340: 3f64aa59 3f61c598 3f5ebe05 3f5b941a Y.d?..a?..^?..[? + 3e350: 3f584853 3f54db31 3f514d3d 3f4d9f02 SHX?1.T?=MQ?..M? + 3e360: 3f49d112 3f45e403 3f41d870 3f3daef9 ..I?..E?p.A?..=? + 3e370: 3f396842 3f3504f3 3f3085bb 3f2beb4a Bh9?..5?..0?J.+? + 3e380: 3f273656 3f226799 3f1d7fd1 3f187fc0 V6'?.g"?...?...? + 3e390: 3f13682a 3f0e39da 3f08f59b 3f039c3d *h.?.9.?...?=..? + 3e3a0: 3efc5d27 3ef15aea 3ee63375 3edae880 '].>.Z.>u3.>...> + 3e3b0: 3ecf7bca 3ec3ef15 3eb8442a 3eac7cd4 .{.>...>*D.>.|.> + 3e3c0: 3ea09ae5 3e94a031 3e888e93 3e78cfcc ...>1..>...>..x> + 3e3d0: 3e605c13 3e47c5c2 3e2f10a2 3e164083 .\`>..G>../>.@.> + 3e3e0: 3dfab273 3dc8bd36 3d96a905 3d48fb30 s..=6..=...=0.H= + 3e3f0: 3cc90ab0 248ca80b bcc90ab0 bd48fb30 ...<...$....0.H. + 3e400: bd96a905 bdc8bd36 bdfab273 be164083 ....6...s....@.. + 3e410: be2f10a2 be47c5c2 be605c13 be78cfcc ../...G..\`...x. + 3e420: be888e93 be94a031 bea09ae5 beac7cd4 ....1........|.. + 3e430: beb8442a bec3ef15 becf7bca bedae880 *D.......{...... + 3e440: bee63375 bef15aea befc5d27 bf039c3d u3...Z..']..=... + 3e450: bf08f59b bf0e39da bf13682a bf187fc0 .....9..*h...... + 3e460: bf1d7fd1 bf226799 bf273656 bf2beb4a .....g".V6'.J.+. + 3e470: bf3085bb bf3504f3 bf396842 bf3daef9 ..0...5.Bh9...=. + 3e480: bf41d870 bf45e403 bf49d112 bf4d9f02 p.A...E...I...M. + 3e490: bf514d3d bf54db31 bf584853 bf5b941a =MQ.1.T.SHX...[. + 3e4a0: bf5ebe05 bf61c598 bf64aa59 bf676bd8 ..^...a.Y.d..kg. + 3e4b0: bf6a09a7 bf6c835e bf6ed89e bf710908 ..j.^.l...n...q. + 3e4c0: bf731447 bf74fa0b bf76ba07 bf7853f8 G.s...t...v..Sx. + 3e4d0: bf79c79d bf7b14be bf7c3b28 bf7d3aac ..y...{.(;|..:}. + 3e4e0: bf7e1324 bf7ec46d bf7f4e6d bf7fb10f $.~.m.~.mN...... + 3e4f0: bf7fec43 bf800000 bf7fec43 bf7fb10f C.......C....... + 3e500: bf7f4e6d bf7ec46d bf7e1324 bf7d3aac mN..m.~.$.~..:}. + 3e510: bf7c3b28 bf7b14be bf79c79d bf7853f8 (;|...{...y..Sx. + 3e520: bf76ba07 bf74fa0b bf731447 bf710908 ..v...t.G.s...q. + 3e530: bf6ed89e bf6c835e bf6a09a7 bf676bd8 ..n.^.l...j..kg. + 3e540: bf64aa59 bf61c598 bf5ebe05 bf5b941a Y.d...a...^...[. + 3e550: bf584853 bf54db31 bf514d3d bf4d9f02 SHX.1.T.=MQ...M. + 3e560: bf49d112 bf45e403 bf41d870 bf3daef9 ..I...E.p.A...=. + 3e570: bf396842 bf3504f3 bf3085bb bf2beb4a Bh9...5...0.J.+. + 3e580: bf273656 bf226799 bf1d7fd1 bf187fc0 V6'..g"......... + 3e590: bf13682a bf0e39da bf08f59b bf039c3d *h...9......=... + 3e5a0: befc5d27 bef15aea bee63375 bedae880 ']...Z..u3...... + 3e5b0: becf7bca bec3ef15 beb8442a beac7cd4 .{......*D...|.. + 3e5c0: bea09ae5 be94a031 be888e93 be78cfcc ....1.........x. + 3e5d0: be605c13 be47c5c2 be2f10a2 be164083 .\`...G.../..@.. + 3e5e0: bdfab273 bdc8bd36 bd96a905 bd48fb30 s...6.......0.H. + 3e5f0: bcc90ab0 a5542337 3cc90ab0 3d48fb30 ....7#T....<0.H= + 3e600: 3d96a905 3dc8bd36 3dfab273 3e164083 ...=6..=s..=.@.> + 3e610: 3e2f10a2 3e47c5c2 3e605c13 3e78cfcc ../>..G>.\`>..x> + 3e620: 3e888e93 3e94a031 3ea09ae5 3eac7cd4 ...>1..>...>.|.> + 3e630: 3eb8442a 3ec3ef15 3ecf7bca 3edae880 *D.>...>.{.>...> + 3e640: 3ee63375 3ef15aea 3efc5d27 3f039c3d u3.>.Z.>'].>=..? + 3e650: 3f08f59b 3f0e39da 3f13682a 3f187fc0 ...?.9.?*h.?...? + 3e660: 3f1d7fd1 3f226799 3f273656 3f2beb4a ...?.g"?V6'?J.+? + 3e670: 3f3085bb 3f3504f3 3f396842 3f3daef9 ..0?..5?Bh9?..=? + 3e680: 3f41d870 3f45e403 3f49d112 3f4d9f02 p.A?..E?..I?..M? + 3e690: 3f514d3d 3f54db31 3f584853 3f5b941a =MQ?1.T?SHX?..[? + 3e6a0: 3f5ebe05 3f61c598 3f64aa59 3f676bd8 ..^?..a?Y.d?.kg? + 3e6b0: 3f6a09a7 3f6c835e 3f6ed89e 3f710908 ..j?^.l?..n?..q? + 3e6c0: 3f731447 3f74fa0b 3f76ba07 3f7853f8 G.s?..t?..v?.Sx? + 3e6d0: 3f79c79d 3f7b14be 3f7c3b28 3f7d3aac ..y?..{?(;|?.:}? + 3e6e0: 3f7e1324 3f7ec46d 3f7f4e6d 3f7fb10f $.~?m.~?mN.?...? + 3e6f0: 3f7fec43 3f800000 3f7fec43 C..?...?C..? + +0003e6fc : + 3e6fc: bcc90ab0 00000000 3cc90ab0 3d48fb30 ...........<0.H= + 3e70c: 3d96a905 3dc8bd36 3dfab273 3e164083 ...=6..=s..=.@.> + 3e71c: 3e2f10a2 3e47c5c2 3e605c13 3e78cfcc ../>..G>.\`>..x> + 3e72c: 3e888e93 3e94a031 3ea09ae5 3eac7cd4 ...>1..>...>.|.> + 3e73c: 3eb8442a 3ec3ef15 3ecf7bca 3edae880 *D.>...>.{.>...> + 3e74c: 3ee63375 3ef15aea 3efc5d27 3f039c3d u3.>.Z.>'].>=..? + 3e75c: 3f08f59b 3f0e39da 3f13682a 3f187fc0 ...?.9.?*h.?...? + 3e76c: 3f1d7fd1 3f226799 3f273656 3f2beb4a ...?.g"?V6'?J.+? + 3e77c: 3f3085bb 3f3504f3 3f396842 3f3daef9 ..0?..5?Bh9?..=? + 3e78c: 3f41d870 3f45e403 3f49d112 3f4d9f02 p.A?..E?..I?..M? + 3e79c: 3f514d3d 3f54db31 3f584853 3f5b941a =MQ?1.T?SHX?..[? + 3e7ac: 3f5ebe05 3f61c598 3f64aa59 3f676bd8 ..^?..a?Y.d?.kg? + 3e7bc: 3f6a09a7 3f6c835e 3f6ed89e 3f710908 ..j?^.l?..n?..q? + 3e7cc: 3f731447 3f74fa0b 3f76ba07 3f7853f8 G.s?..t?..v?.Sx? + 3e7dc: 3f79c79d 3f7b14be 3f7c3b28 3f7d3aac ..y?..{?(;|?.:}? + 3e7ec: 3f7e1324 3f7ec46d 3f7f4e6d 3f7fb10f $.~?m.~?mN.?...? + 3e7fc: 3f7fec43 3f800000 3f7fec43 3f7fb10f C..?...?C..?...? + 3e80c: 3f7f4e6d 3f7ec46d 3f7e1324 3f7d3aac mN.?m.~?$.~?.:}? + 3e81c: 3f7c3b28 3f7b14be 3f79c79d 3f7853f8 (;|?..{?..y?.Sx? + 3e82c: 3f76ba07 3f74fa0b 3f731447 3f710908 ..v?..t?G.s?..q? + 3e83c: 3f6ed89e 3f6c835e 3f6a09a7 3f676bd8 ..n?^.l?..j?.kg? + 3e84c: 3f64aa59 3f61c598 3f5ebe05 3f5b941a Y.d?..a?..^?..[? + 3e85c: 3f584853 3f54db31 3f514d3d 3f4d9f02 SHX?1.T?=MQ?..M? + 3e86c: 3f49d112 3f45e403 3f41d870 3f3daef9 ..I?..E?p.A?..=? + 3e87c: 3f396842 3f3504f3 3f3085bb 3f2beb4a Bh9?..5?..0?J.+? + 3e88c: 3f273656 3f226799 3f1d7fd1 3f187fc0 V6'?.g"?...?...? + 3e89c: 3f13682a 3f0e39da 3f08f59b 3f039c3d *h.?.9.?...?=..? + 3e8ac: 3efc5d27 3ef15aea 3ee63375 3edae880 '].>.Z.>u3.>...> + 3e8bc: 3ecf7bca 3ec3ef15 3eb8442a 3eac7cd4 .{.>...>*D.>.|.> + 3e8cc: 3ea09ae5 3e94a031 3e888e93 3e78cfcc ...>1..>...>..x> + 3e8dc: 3e605c13 3e47c5c2 3e2f10a2 3e164083 .\`>..G>../>.@.> + 3e8ec: 3dfab273 3dc8bd36 3d96a905 3d48fb30 s..=6..=...=0.H= + 3e8fc: 3cc90ab0 250ca80b bcc90ab0 bd48fb30 ...<...%....0.H. + 3e90c: bd96a905 bdc8bd36 bdfab273 be164083 ....6...s....@.. + 3e91c: be2f10a2 be47c5c2 be605c13 be78cfcc ../...G..\`...x. + 3e92c: be888e93 be94a031 bea09ae5 beac7cd4 ....1........|.. + 3e93c: beb8442a bec3ef15 becf7bca bedae880 *D.......{...... + 3e94c: bee63375 bef15aea befc5d27 bf039c3d u3...Z..']..=... + 3e95c: bf08f59b bf0e39da bf13682a bf187fc0 .....9..*h...... + 3e96c: bf1d7fd1 bf226799 bf273656 bf2beb4a .....g".V6'.J.+. + 3e97c: bf3085bb bf3504f3 bf396842 bf3daef9 ..0...5.Bh9...=. + 3e98c: bf41d870 bf45e403 bf49d112 bf4d9f02 p.A...E...I...M. + 3e99c: bf514d3d bf54db31 bf584853 bf5b941a =MQ.1.T.SHX...[. + 3e9ac: bf5ebe05 bf61c598 bf64aa59 bf676bd8 ..^...a.Y.d..kg. + 3e9bc: bf6a09a7 bf6c835e bf6ed89e bf710908 ..j.^.l...n...q. + 3e9cc: bf731447 bf74fa0b bf76ba07 bf7853f8 G.s...t...v..Sx. + 3e9dc: bf79c79d bf7b14be bf7c3b28 bf7d3aac ..y...{.(;|..:}. + 3e9ec: bf7e1324 bf7ec46d bf7f4e6d bf7fb10f $.~.m.~.mN...... + 3e9fc: bf7fec43 bf800000 bf7fec43 bf7fb10f C.......C....... + 3ea0c: bf7f4e6d bf7ec46d bf7e1324 bf7d3aac mN..m.~.$.~..:}. + 3ea1c: bf7c3b28 bf7b14be bf79c79d bf7853f8 (;|...{...y..Sx. + 3ea2c: bf76ba07 bf74fa0b bf731447 bf710908 ..v...t.G.s...q. + 3ea3c: bf6ed89e bf6c835e bf6a09a7 bf676bd8 ..n.^.l...j..kg. + 3ea4c: bf64aa59 bf61c598 bf5ebe05 bf5b941a Y.d...a...^...[. + 3ea5c: bf584853 bf54db31 bf514d3d bf4d9f02 SHX.1.T.=MQ...M. + 3ea6c: bf49d112 bf45e403 bf41d870 bf3daef9 ..I...E.p.A...=. + 3ea7c: bf396842 bf3504f3 bf3085bb bf2beb4a Bh9...5...0.J.+. + 3ea8c: bf273656 bf226799 bf1d7fd1 bf187fc0 V6'..g"......... + 3ea9c: bf13682a bf0e39da bf08f59b bf039c3d *h...9......=... + 3eaac: befc5d27 bef15aea bee63375 bedae880 ']...Z..u3...... + 3eabc: becf7bca bec3ef15 beb8442a beac7cd4 .{......*D...|.. + 3eacc: bea09ae5 be94a031 be888e93 be78cfcc ....1.........x. + 3eadc: be605c13 be47c5c2 be2f10a2 be164083 .\`...G.../..@.. + 3eaec: bdfab273 bdc8bd36 bd96a905 bd48fb30 s...6.......0.H. + 3eafc: bcc90ab0 a58d3b9e 3cc90ab0 .....;.....< + +0003eb08 : + 3eb08: 00000000 3ff00000 00000000 40240000 .......?......$@ + 3eb18: 00000000 40590000 00000000 408f4000 ......Y@.....@.@ + 3eb28: 00000000 40c38800 00000000 40f86a00 .......@.....j.@ + 3eb38: 00000000 412e8480 00000000 416312d0 .......A......cA + 3eb48: 00000000 4197d784 00000000 41cdcd65 .......A....e..A + 3eb58: 20000000 4202a05f e8000000 42374876 ... _..B....vH7B + 3eb68: a2000000 426d1a94 e5400000 42a2309c ......mB..@..0.B + 3eb78: 1e900000 42d6bcc4 26340000 430c6bf5 .......B..4&.k.C + 3eb88: 37e08000 4341c379 85d8a000 43763457 ...7y.AC....W4vC + 3eb98: 674ec800 43abc16d 60913d00 43e158e4 ..Ngm..C.=.`.X.C + 3eba8: 78b58c40 4415af1d d6e2ef50 444b1ae4 @..x...DP.....KD + 3ebb8: 064dd592 4480f0cf c7e14af6 44b52d02 ..M....D.J...-.D + 3ebc8: 79d99db4 44ea7843 ...yCx.D + +0003ebd0 : + 3ebd0: 37e08000 4341c379 b5056e17 4693b8b5 ...7y.AC.n.....F + 3ebe0: e93ff9f5 4d384f03 f9301d32 5a827748 ..?..O8M2.0.Hw.Z + 3ebf0: 7f73bf3c 75154fdd <.s..O.u + +0003ebf8 : + 3ebf8: 00000005 00000019 0000007d ........}... + +0003ec04 : + 3ec04: 20202020 20202020 20202020 20202020 + +0003ec14 : + 3ec14: 30303030 30303030 30303030 30303030 0000000000000000 + +0003ec24 <.LC0>: + 3ec24: 3d3d3d0d .word 0x3d3d3d0d + 3ec28: 3d3d3d3d .word 0x3d3d3d3d + 3ec2c: 3d3d3d3d .word 0x3d3d3d3d + 3ec30: 3d3d3d3d .word 0x3d3d3d3d + 3ec34: 3d3d3d3d .word 0x3d3d3d3d + 3ec38: 3d3d3d3d .word 0x3d3d3d3d + 3ec3c: 3d3d3d3d .word 0x3d3d3d3d + 3ec40: 3d3d3d3d .word 0x3d3d3d3d + 3ec44: 3d3d3d3d .word 0x3d3d3d3d + 3ec48: 3d3d3d3d .word 0x3d3d3d3d + 3ec4c: 3d3d3d3d .word 0x3d3d3d3d + 3ec50: 3d3d3d3d .word 0x3d3d3d3d + 3ec54: 3d3d3d3d .word 0x3d3d3d3d + 3ec58: 3d3d3d3d .word 0x3d3d3d3d + 3ec5c: 0a0a3d3d .word 0x0a0a3d3d + 3ec60: 00000000 .word 0x00000000 + +0003ec64 <.LC1>: + 3ec64: 4d4f520d .word 0x4d4f520d + 3ec68: 72655620 .word 0x72655620 + 3ec6c: 6e6f6973 .word 0x6e6f6973 + 3ec70: 6425203a .word 0x6425203a + 3ec74: 0a64252e .word 0x0a64252e + 3ec78: 0000000a .word 0x0000000a + +0003ec7c <.LC2>: + 3ec7c: 6975420d .word 0x6975420d + 3ec80: 5420646c .word 0x5420646c + 3ec84: 436c6f6f .word 0x436c6f6f + 3ec88: 6e696168 .word 0x6e696168 + 3ec8c: 72655620 .word 0x72655620 + 3ec90: 6e6f6973 .word 0x6e6f6973 + 3ec94: 6367203a .word 0x6367203a + 3ec98: 65762063 .word 0x65762063 + 3ec9c: 6f697372 .word 0x6f697372 + 3eca0: 2e34206e .word 0x2e34206e + 3eca4: 20332e38 .word 0x20332e38 + 3eca8: 61655228 .word 0x61655228 + 3ecac: 6b65746c .word 0x6b65746c + 3ecb0: 44534120 .word 0x44534120 + 3ecb4: 2e342d4b .word 0x2e342d4b + 3ecb8: 70332e38 .word 0x70332e38 + 3ecbc: 75422031 .word 0x75422031 + 3ecc0: 20646c69 .word 0x20646c69 + 3ecc4: 33303032 .word 0x33303032 + 3ecc8: 0a0a2029 .word 0x0a0a2029 + 3eccc: 00000000 .word 0x00000000 + +0003ecd0 <.LC3>: + 3ecd0: 3d3d3d0d .word 0x3d3d3d0d + 3ecd4: 3d3d3d3d .word 0x3d3d3d3d + 3ecd8: 3d3d3d3d .word 0x3d3d3d3d + 3ecdc: 3d3d3d3d .word 0x3d3d3d3d + 3ece0: 3d3d3d3d .word 0x3d3d3d3d + 3ece4: 3d3d3d3d .word 0x3d3d3d3d + 3ece8: 3d3d3d3d .word 0x3d3d3d3d + 3ecec: 3d3d3d3d .word 0x3d3d3d3d + 3ecf0: 3d3d3d3d .word 0x3d3d3d3d + 3ecf4: 3d3d3d3d .word 0x3d3d3d3d + 3ecf8: 3d3d3d3d .word 0x3d3d3d3d + 3ecfc: 3d3d3d3d .word 0x3d3d3d3d + 3ed00: 3d3d3d3d .word 0x3d3d3d3d + 3ed04: 3d3d3d3d .word 0x3d3d3d3d + 3ed08: 000a3d3d .word 0x000a3d3d + +0003ed0c <.LC4>: + 3ed0c: 4643490d .word 0x4643490d + 3ed10: 20322047 .word 0x20322047 + 3ed14: 0000000a .word 0x0000000a + +0003ed18 <.LC5>: + 3ed18: 6568430d .word 0x6568430d + 3ed1c: 62206b63 .word 0x62206b63 + 3ed20: 20746f6f .word 0x20746f6f + 3ed24: 65707974 .word 0x65707974 + 3ed28: 726f6620 .word 0x726f6620 + 3ed2c: 4665206d .word 0x4665206d + 3ed30: 0a657375 .word 0x0a657375 + 3ed34: 00000000 .word 0x00000000 + +0003ed38 <.LC6>: + 3ed38: 4950530d .word 0x4950530d + 3ed3c: 696e4920 .word 0x696e4920 + 3ed40: 6c616974 .word 0x6c616974 + 3ed44: 0000000a .word 0x0000000a + +0003ed48 <.LC7>: + 3ed48: 616d490d .word 0x616d490d + 3ed4c: 20316567 .word 0x20316567 + 3ed50: 676e656c .word 0x676e656c + 3ed54: 203a6874 .word 0x203a6874 + 3ed58: 78257830 .word 0x78257830 + 3ed5c: 6d49202c .word 0x6d49202c + 3ed60: 20656761 .word 0x20656761 + 3ed64: 72646441 .word 0x72646441 + 3ed68: 7830203a .word 0x7830203a + 3ed6c: 000a7825 .word 0x000a7825 + +0003ed70 <.LC8>: + 3ed70: 616d490d .word 0x616d490d + 3ed74: 20316567 .word 0x20316567 + 3ed78: 696c6156 .word 0x696c6156 + 3ed7c: 69746164 .word 0x69746164 + 3ed80: 49206e6f .word 0x49206e6f + 3ed84: 726f636e .word 0x726f636e + 3ed88: 74636572 .word 0x74636572 + 3ed8c: 21212120 .word 0x21212120 + 3ed90: 0000000a .word 0x0000000a + +0003ed94 <.LC9>: + 3ed94: 656c500d .word 0x656c500d + 3ed98: 20657361 .word 0x20657361 + 3ed9c: 622d6552 .word 0x622d6552 + 3eda0: 20746f6f .word 0x20746f6f + 3eda4: 20646e61 .word 0x20646e61 + 3eda8: 20797274 .word 0x20797274 + 3edac: 69616761 .word 0x69616761 + 3edb0: 6f202c6e .word 0x6f202c6e + 3edb4: 65722072 .word 0x65722072 + 3edb8: 7275622d .word 0x7275622d + 3edbc: 6874206e .word 0x6874206e + 3edc0: 6c662065 .word 0x6c662065 + 3edc4: 20687361 .word 0x20687361 + 3edc8: 67616d69 .word 0x67616d69 + 3edcc: 00000a65 .word 0x00000a65 + +0003edd0 <.LC10>: + 3edd0: 616d490d .word 0x616d490d + 3edd4: 20316567 .word 0x20316567 + 3edd8: 696c6156 .word 0x696c6156 + 3eddc: 65746164 .word 0x65746164 + 3ede0: 2c4b4f20 .word 0x2c4b4f20 + 3ede4: 696f4720 .word 0x696f4720 + 3ede8: 6a20676e .word 0x6a20676e + 3edec: 20706d75 .word 0x20706d75 + 3edf0: 49206f74 .word 0x49206f74 + 3edf4: 6567616d .word 0x6567616d + 3edf8: 00000a31 .word 0x00000a31 + +0003edfc <.LC11>: + 3edfc: 4944530d .word 0x4944530d + 3ee00: 6f62204f .word 0x6f62204f + 3ee04: 6e20726f .word 0x6e20726f + 3ee08: 7220746f .word 0x7220746f + 3ee0c: 79646165 .word 0x79646165 + 3ee10: 21212120 .word 0x21212120 + 3ee14: 21212121 .word 0x21212121 + 3ee18: 0000000a .word 0x0000000a + +0003ee1c <.LC12>: + 3ee1c: 4253550d .word 0x4253550d + 3ee20: 6f6f6220 .word 0x6f6f6220 + 3ee24: 6f6e2072 .word 0x6f6e2072 + 3ee28: 65722074 .word 0x65722074 + 3ee2c: 20796461 .word 0x20796461 + 3ee30: 21212121 .word 0x21212121 + 3ee34: 0a212121 .word 0x0a212121 + 3ee38: 00000000 .word 0x00000000 + +0003ee3c <.LC13>: + 3ee3c: 206f4e0d .word 0x206f4e0d + 3ee40: 70707573 .word 0x70707573 + 3ee44: 2074726f .word 0x2074726f + 3ee48: 746f6f62 .word 0x746f6f62 + 3ee4c: 65797420 .word 0x65797420 + 3ee50: 21212070 .word 0x21212070 + 3ee54: 21212121 .word 0x21212121 + 3ee58: 00000a21 .word 0x00000a21 + +0003ee5c <.LC14>: + 3ee5c: 4c54520d .word 0x4c54520d + 3ee60: 35393138 .word 0x35393138 + 3ee64: 41485b41 .word 0x41485b41 + 3ee68: 203a5d4c .word 0x203a5d4c + 3ee6c: 20494d4e .word 0x20494d4e + 3ee70: 6f727245 .word 0x6f727245 + 3ee74: 21212172 .word 0x21212172 + 3ee78: 00000a21 .word 0x00000a21 + +0003ee7c <.LC15>: + 3ee7c: 4c54520d .word 0x4c54520d + 3ee80: 35393138 .word 0x35393138 + 3ee84: 41485b41 .word 0x41485b41 + 3ee88: 203a5d4c .word 0x203a5d4c + 3ee8c: 64726148 .word 0x64726148 + 3ee90: 75614620 .word 0x75614620 + 3ee94: 4520746c .word 0x4520746c + 3ee98: 726f7272 .word 0x726f7272 + 3ee9c: 21212121 .word 0x21212121 + 3eea0: 0000000a .word 0x0000000a + +0003eea4 <.LC16>: + 3eea4: 4c54520d .word 0x4c54520d + 3eea8: 35393138 .word 0x35393138 + 3eeac: 41485b41 .word 0x41485b41 + 3eeb0: 203a5d4c .word 0x203a5d4c + 3eeb4: 3d203052 .word 0x3d203052 + 3eeb8: 25783020 .word 0x25783020 + 3eebc: 00000a78 .word 0x00000a78 + +0003eec0 <.LC17>: + 3eec0: 4c54520d .word 0x4c54520d + 3eec4: 35393138 .word 0x35393138 + 3eec8: 41485b41 .word 0x41485b41 + 3eecc: 203a5d4c .word 0x203a5d4c + 3eed0: 3d203152 .word 0x3d203152 + 3eed4: 25783020 .word 0x25783020 + 3eed8: 00000a78 .word 0x00000a78 + +0003eedc <.LC18>: + 3eedc: 4c54520d .word 0x4c54520d + 3eee0: 35393138 .word 0x35393138 + 3eee4: 41485b41 .word 0x41485b41 + 3eee8: 203a5d4c .word 0x203a5d4c + 3eeec: 3d203252 .word 0x3d203252 + 3eef0: 25783020 .word 0x25783020 + 3eef4: 00000a78 .word 0x00000a78 + +0003eef8 <.LC19>: + 3eef8: 4c54520d .word 0x4c54520d + 3eefc: 35393138 .word 0x35393138 + 3ef00: 41485b41 .word 0x41485b41 + 3ef04: 203a5d4c .word 0x203a5d4c + 3ef08: 3d203352 .word 0x3d203352 + 3ef0c: 25783020 .word 0x25783020 + 3ef10: 00000a78 .word 0x00000a78 + +0003ef14 <.LC20>: + 3ef14: 4c54520d .word 0x4c54520d + 3ef18: 35393138 .word 0x35393138 + 3ef1c: 41485b41 .word 0x41485b41 + 3ef20: 203a5d4c .word 0x203a5d4c + 3ef24: 20323152 .word 0x20323152 + 3ef28: 7830203d .word 0x7830203d + 3ef2c: 000a7825 .word 0x000a7825 + +0003ef30 <.LC21>: + 3ef30: 4c54520d .word 0x4c54520d + 3ef34: 35393138 .word 0x35393138 + 3ef38: 41485b41 .word 0x41485b41 + 3ef3c: 203a5d4c .word 0x203a5d4c + 3ef40: 3d20524c .word 0x3d20524c + 3ef44: 25783020 .word 0x25783020 + 3ef48: 00000a78 .word 0x00000a78 + +0003ef4c <.LC22>: + 3ef4c: 4c54520d .word 0x4c54520d + 3ef50: 35393138 .word 0x35393138 + 3ef54: 41485b41 .word 0x41485b41 + 3ef58: 203a5d4c .word 0x203a5d4c + 3ef5c: 3d204350 .word 0x3d204350 + 3ef60: 25783020 .word 0x25783020 + 3ef64: 00000a78 .word 0x00000a78 + +0003ef68 <.LC23>: + 3ef68: 4c54520d .word 0x4c54520d + 3ef6c: 35393138 .word 0x35393138 + 3ef70: 41485b41 .word 0x41485b41 + 3ef74: 203a5d4c .word 0x203a5d4c + 3ef78: 20525350 .word 0x20525350 + 3ef7c: 7830203d .word 0x7830203d + 3ef80: 000a7825 .word 0x000a7825 + +0003ef84 <.LC24>: + 3ef84: 4c54520d .word 0x4c54520d + 3ef88: 35393138 .word 0x35393138 + 3ef8c: 41485b41 .word 0x41485b41 + 3ef90: 203a5d4c .word 0x203a5d4c + 3ef94: 52414642 .word 0x52414642 + 3ef98: 30203d20 .word 0x30203d20 + 3ef9c: 0a782578 .word 0x0a782578 + 3efa0: 00000000 .word 0x00000000 + +0003efa4 <.LC25>: + 3efa4: 4c54520d .word 0x4c54520d + 3efa8: 35393138 .word 0x35393138 + 3efac: 41485b41 .word 0x41485b41 + 3efb0: 203a5d4c .word 0x203a5d4c + 3efb4: 52534643 .word 0x52534643 + 3efb8: 30203d20 .word 0x30203d20 + 3efbc: 0a782578 .word 0x0a782578 + 3efc0: 00000000 .word 0x00000000 + +0003efc4 <.LC26>: + 3efc4: 4c54520d .word 0x4c54520d + 3efc8: 35393138 .word 0x35393138 + 3efcc: 41485b41 .word 0x41485b41 + 3efd0: 203a5d4c .word 0x203a5d4c + 3efd4: 52534648 .word 0x52534648 + 3efd8: 30203d20 .word 0x30203d20 + 3efdc: 0a782578 .word 0x0a782578 + 3efe0: 00000000 .word 0x00000000 + +0003efe4 <.LC27>: + 3efe4: 4c54520d .word 0x4c54520d + 3efe8: 35393138 .word 0x35393138 + 3efec: 41485b41 .word 0x41485b41 + 3eff0: 203a5d4c .word 0x203a5d4c + 3eff4: 52534644 .word 0x52534644 + 3eff8: 30203d20 .word 0x30203d20 + 3effc: 0a782578 .word 0x0a782578 + 3f000: 00000000 .word 0x00000000 + +0003f004 <.LC28>: + 3f004: 4c54520d .word 0x4c54520d + 3f008: 35393138 .word 0x35393138 + 3f00c: 41485b41 .word 0x41485b41 + 3f010: 203a5d4c .word 0x203a5d4c + 3f014: 52534641 .word 0x52534641 + 3f018: 30203d20 .word 0x30203d20 + 3f01c: 0a782578 .word 0x0a782578 + 3f020: 00000000 .word 0x00000000 + +0003f024 <.LC29>: + 3f024: 4c54520d .word 0x4c54520d + 3f028: 35393138 .word 0x35393138 + 3f02c: 41485b41 .word 0x41485b41 + 3f030: 203a5d4c .word 0x203a5d4c + 3f034: 4d697250 .word 0x4d697250 + 3f038: 206b7361 .word 0x206b7361 + 3f03c: 78257830 .word 0x78257830 + 3f040: 0000000a .word 0x0000000a + +0003f044 <.LC30>: + 3f044: 4c54520d .word 0x4c54520d + 3f048: 35393138 .word 0x35393138 + 3f04c: 41485b41 .word 0x41485b41 + 3f050: 203a5d4c .word 0x203a5d4c + 3f054: 65736142 .word 0x65736142 + 3f058: 20697250 .word 0x20697250 + 3f05c: 78257830 .word 0x78257830 + 3f060: 0000000a .word 0x0000000a + +0003f064 <.LC31>: + 3f064: 4c54520d .word 0x4c54520d + 3f068: 35393138 .word 0x35393138 + 3f06c: 41485b41 .word 0x41485b41 + 3f070: 203a5d4c .word 0x203a5d4c + 3f074: 20435653 .word 0x20435653 + 3f078: 6f697270 .word 0x6f697270 + 3f07c: 79746972 .word 0x79746972 + 3f080: 7830203a .word 0x7830203a + 3f084: 78323025 .word 0x78323025 + 3f088: 0000000a .word 0x0000000a + +0003f08c <.LC32>: + 3f08c: 4c54520d .word 0x4c54520d + 3f090: 35393138 .word 0x35393138 + 3f094: 41485b41 .word 0x41485b41 + 3f098: 203a5d4c .word 0x203a5d4c + 3f09c: 646e6550 .word 0x646e6550 + 3f0a0: 20435653 .word 0x20435653 + 3f0a4: 6f697270 .word 0x6f697270 + 3f0a8: 79746972 .word 0x79746972 + 3f0ac: 7830203a .word 0x7830203a + 3f0b0: 78323025 .word 0x78323025 + 3f0b4: 0000000a .word 0x0000000a + +0003f0b8 <.LC33>: + 3f0b8: 4c54520d .word 0x4c54520d + 3f0bc: 35393138 .word 0x35393138 + 3f0c0: 41485b41 .word 0x41485b41 + 3f0c4: 203a5d4c .word 0x203a5d4c + 3f0c8: 74737953 .word 0x74737953 + 3f0cc: 206b6369 .word 0x206b6369 + 3f0d0: 6f697270 .word 0x6f697270 + 3f0d4: 79746972 .word 0x79746972 + 3f0d8: 7830203a .word 0x7830203a + 3f0dc: 78323025 .word 0x78323025 + 3f0e0: 0000000a .word 0x0000000a + +0003f0e4 <.LC34>: + 3f0e4: 4c54520d .word 0x4c54520d + 3f0e8: 35393138 .word 0x35393138 + 3f0ec: 41485b41 .word 0x41485b41 + 3f0f0: 203a5d4c .word 0x203a5d4c + 3f0f4: 6f6d654d .word 0x6f6d654d + 3f0f8: 4d207972 .word 0x4d207972 + 3f0fc: 67616e61 .word 0x67616e61 + 3f100: 72452065 .word 0x72452065 + 3f104: 21726f72 .word 0x21726f72 + 3f108: 0a212121 .word 0x0a212121 + 3f10c: 00000000 .word 0x00000000 + +0003f110 <.LC35>: + 3f110: 4c54520d .word 0x4c54520d + 3f114: 35393138 .word 0x35393138 + 3f118: 41485b41 .word 0x41485b41 + 3f11c: 203a5d4c .word 0x203a5d4c + 3f120: 20737542 .word 0x20737542 + 3f124: 6c756146 .word 0x6c756146 + 3f128: 72452074 .word 0x72452074 + 3f12c: 21726f72 .word 0x21726f72 + 3f130: 0a212121 .word 0x0a212121 + 3f134: 00000000 .word 0x00000000 + +0003f138 <.LC36>: + 3f138: 4c54520d .word 0x4c54520d + 3f13c: 35393138 .word 0x35393138 + 3f140: 41485b41 .word 0x41485b41 + 3f144: 203a5d4c .word 0x203a5d4c + 3f148: 67617355 .word 0x67617355 + 3f14c: 61462065 .word 0x61462065 + 3f150: 20746c75 .word 0x20746c75 + 3f154: 6f727245 .word 0x6f727245 + 3f158: 21212172 .word 0x21212172 + 3f15c: 00000a21 .word 0x00000a21 + +0003f160 <.LC0>: + 3f160: 696e490d .word 0x696e490d + 3f164: 61422074 .word 0x61422074 + 3f168: 52206475 .word 0x52206475 + 3f16c: 3a657461 .word 0x3a657461 + 3f170: 25783020 .word 0x25783020 + 3f174: 00000a78 .word 0x00000a78 + +0003f178 <.LC1>: + 3f178: 696e490d .word 0x696e490d + 3f17c: 44522074 .word 0x44522074 + 3f180: 6d754420 .word 0x6d754420 + 3f184: 203a796d .word 0x203a796d + 3f188: 78257830 .word 0x78257830 + 3f18c: 0000000a .word 0x0000000a + +0003f190 <.LC2>: + 3f190: 696e490d .word 0x696e490d + 3f194: 65442074 .word 0x65442074 + 3f198: 2079616c .word 0x2079616c + 3f19c: 656e694c .word 0x656e694c + 3f1a0: 7830203a .word 0x7830203a + 3f1a4: 000a7825 .word 0x000a7825 + +0003f1a8 <.LC3>: + 3f1a8: 6172450d .word 0x6172450d + 3f1ac: 43206573 .word 0x43206573 + 3f1b0: 5320646d .word 0x5320646d + 3f1b4: 000a7465 .word 0x000a7465 + +0003f1b8 <.LC4>: + 3f1b8: 696e490d .word 0x696e490d + 3f1bc: 6c616974 .word 0x6c616974 + 3f1c0: 69705320 .word 0x69705320 + 3f1c4: 616c4620 .word 0x616c4620 + 3f1c8: 43206873 .word 0x43206873 + 3f1cc: 72746e6f .word 0x72746e6f + 3f1d0: 656c6c6f .word 0x656c6c6f + 3f1d4: 00000a72 .word 0x00000a72 + +0003f1d8 <.LC5>: + 3f1d8: 696e490d .word 0x696e490d + 3f1dc: 6c616974 .word 0x6c616974 + 3f1e0: 69705320 .word 0x69705320 + 3f1e4: 6e4f2063 .word 0x6e4f2063 + 3f1e8: 69622065 .word 0x69622065 + 3f1ec: 6f6d2074 .word 0x6f6d2074 + 3f1f0: 000a6564 .word 0x000a6564 + +0003f1f4 <.LC6>: + 3f1f4: 696e490d .word 0x696e490d + 3f1f8: 6c616974 .word 0x6c616974 + 3f1fc: 69705320 .word 0x69705320 + 3f200: 77542063 .word 0x77542063 + 3f204: 6962206f .word 0x6962206f + 3f208: 6f6d2074 .word 0x6f6d2074 + 3f20c: 000a6564 .word 0x000a6564 + +0003f210 <.LC7>: + 3f210: 696e490d .word 0x696e490d + 3f214: 6c616974 .word 0x6c616974 + 3f218: 69705320 .word 0x69705320 + 3f21c: 6f462063 .word 0x6f462063 + 3f220: 62207275 .word 0x62207275 + 3f224: 6d207469 .word 0x6d207469 + 3f228: 0a65646f .word 0x0a65646f + 3f22c: 00000000 .word 0x00000000 + +0003f230 <.LC8>: + 3f230: 6172450d .word 0x6172450d + 3f234: 46206573 .word 0x46206573 + 3f238: 68736c61 .word 0x68736c61 + 3f23c: 61745320 .word 0x61745320 + 3f240: 000a7472 .word 0x000a7472 + +0003f244 <.LC9>: + 3f244: 6172450d .word 0x6172450d + 3f248: 46206573 .word 0x46206573 + 3f24c: 68736c61 .word 0x68736c61 + 3f250: 646e4520 .word 0x646e4520 + 3f254: 0000000a .word 0x0000000a + +0003f258 <.LC0>: + 3f258: 6573550d .word 0x6573550d + 3f25c: 72492072 .word 0x72492072 + 3f260: 64252071 .word 0x64252071 + 3f264: 6e754620 .word 0x6e754620 + 3f268: 746f4e20 .word 0x746f4e20 + 3f26c: 73734120 .word 0x73734120 + 3f270: 216e6769 .word 0x216e6769 + 3f274: 21212121 .word 0x21212121 + 3f278: 00000000 .word 0x00000000 + +0003f27c <.LC1>: + 3f27c: 4c54520d .word 0x4c54520d + 3f280: 35393138 .word 0x35393138 + 3f284: 41485b41 .word 0x41485b41 + 3f288: 203a5d4c .word 0x203a5d4c + 3f28c: 20525349 .word 0x20525349 + 3f290: 68206425 .word 0x68206425 + 3f294: 62206461 .word 0x62206461 + 3f298: 206e6565 .word 0x206e6565 + 3f29c: 6f6c6c61 .word 0x6f6c6c61 + 3f2a0: 65746163 .word 0x65746163 + 3f2a4: 21212164 .word 0x21212164 + 3f2a8: 0000000a .word 0x0000000a + +0003f2ac <.LC2>: + 3f2ac: 4c54520d .word 0x4c54520d + 3f2b0: 35393138 .word 0x35393138 + 3f2b4: 41485b41 .word 0x41485b41 + 3f2b8: 203a5d4c .word 0x203a5d4c + 3f2bc: 20525349 .word 0x20525349 + 3f2c0: 64206425 .word 0x64206425 + 3f2c4: 27626469 .word 0x27626469 + 3f2c8: 65622074 .word 0x65622074 + 3f2cc: 65722065 .word 0x65722065 + 3f2d0: 74736967 .word 0x74736967 + 3f2d4: 21217265 .word 0x21217265 + 3f2d8: 00000a21 .word 0x00000a21 + +0003f2dc <.LC0>: + 3f2dc: 41555b0d .word 0x41555b0d + 3f2e0: 49205452 .word 0x49205452 + 3f2e4: 1b5d666e .word 0x1b5d666e + 3f2e8: 6d31335b .word 0x6d31335b + 3f2ec: 53676244 .word 0x53676244 + 3f2f0: 3d206c65 .word 0x3d206c65 + 3f2f4: 0a642520 .word 0x0a642520 + 3f2f8: 6d305b1b .word 0x6d305b1b + 3f2fc: 00000000 .word 0x00000000 + +0003f300 <.LC1>: + 3f300: 41555b0d .word 0x41555b0d + 3f304: 49205452 .word 0x49205452 + 3f308: 5b5d666e .word 0x5b5d666e + 3f30c: 55205d52 .word 0x55205d52 + 3f310: 25545241 .word 0x25545241 + 3f314: 50532064 .word 0x50532064 + 3f318: 78302852 .word 0x78302852 + 3f31c: 20294331 .word 0x20294331 + 3f320: 5825203d .word 0x5825203d + 3f324: 0000000a .word 0x0000000a + +0003f328 <.LC2>: + 3f328: 41555b0d .word 0x41555b0d + 3f32c: 49205452 .word 0x49205452 + 3f330: 1b5d666e .word 0x1b5d666e + 3f334: 6d31335b .word 0x6d31335b + 3f338: 56676552 .word 0x56676552 + 3f33c: 65756c61 .word 0x65756c61 + 3f340: 25203d20 .word 0x25203d20 + 3f344: 5b1b0a58 .word 0x5b1b0a58 + 3f348: 00006d30 .word 0x00006d30 + +0003f34c <.LC3>: + 3f34c: 41555b0d .word 0x41555b0d + 3f350: 49205452 .word 0x49205452 + 3f354: 5b5d666e .word 0x5b5d666e + 3f358: 415b5d52 .word 0x415b5d52 + 3f35c: 72657466 .word 0x72657466 + 3f360: 4155205d .word 0x4155205d + 3f364: 64255452 .word 0x64255452 + 3f368: 52505320 .word 0x52505320 + 3f36c: 31783028 .word 0x31783028 + 3f370: 3d202943 .word 0x3d202943 + 3f374: 0a582520 .word 0x0a582520 + 3f378: 00000000 .word 0x00000000 + +0003f37c <.LC4>: + 3f37c: 41555b0d .word 0x41555b0d + 3f380: 49205452 .word 0x49205452 + 3f384: 1b5d666e .word 0x1b5d666e + 3f388: 6d33335b .word 0x6d33335b + 3f38c: 205d525b .word 0x205d525b + 3f390: 54524155 .word 0x54524155 + 3f394: 44206425 .word 0x44206425 + 3f398: 535f4742 .word 0x535f4742 + 3f39c: 25284c45 .word 0x25284c45 + 3f3a0: 3d202964 .word 0x3d202964 + 3f3a4: 0a582520 .word 0x0a582520 + 3f3a8: 6d305b1b .word 0x6d305b1b + 3f3ac: 00000000 .word 0x00000000 + +0003f3b0 <.LC5>: + 3f3b0: 41555b0d .word 0x41555b0d + 3f3b4: 49205452 .word 0x49205452 + 3f3b8: 555d666e .word 0x555d666e + 3f3bc: 25545241 .word 0x25545241 + 3f3c0: 4e492064 .word 0x4e492064 + 3f3c4: 4e455f54 .word 0x4e455f54 + 3f3c8: 30783028 .word 0x30783028 + 3f3cc: 203a2934 .word 0x203a2934 + 3f3d0: 000a5825 .word 0x000a5825 + +0003f3d4 <.LC6>: + 3f3d4: 41555b0d .word 0x41555b0d + 3f3d8: 49205452 .word 0x49205452 + 3f3dc: 5b5d666e .word 0x5b5d666e + 3f3e0: 55205d57 .word 0x55205d57 + 3f3e4: 25545241 .word 0x25545241 + 3f3e8: 4e492064 .word 0x4e492064 + 3f3ec: 4e455f54 .word 0x4e455f54 + 3f3f0: 30783028 .word 0x30783028 + 3f3f4: 3d202934 .word 0x3d202934 + 3f3f8: 0a782520 .word 0x0a782520 + 3f3fc: 00000000 .word 0x00000000 + +0003f400 <.LC7>: + 3f400: 41555b0d .word 0x41555b0d + 3f404: 45205452 .word 0x45205452 + 3f408: 1b5d7272 .word 0x1b5d7272 + 3f40c: 6d31335b .word 0x6d31335b + 3f410: 6e6b6e55 .word 0x6e6b6e55 + 3f414: 206e776f .word 0x206e776f + 3f418: 65746e49 .word 0x65746e49 + 3f41c: 70757272 .word 0x70757272 + 3f420: 79542074 .word 0x79542074 + 3f424: 1b0a6570 .word 0x1b0a6570 + 3f428: 006d305b .word 0x006d305b + +0003f42c <.LC8>: + 3f42c: 41555b0d .word 0x41555b0d + 3f430: 49205452 .word 0x49205452 + 3f434: 555d666e .word 0x555d666e + 3f438: 25545241 .word 0x25545241 + 3f43c: 55522064 .word 0x55522064 + 3f440: 5f545241 .word 0x5f545241 + 3f444: 4353494d .word 0x4353494d + 3f448: 4c54435f .word 0x4c54435f + 3f44c: 4745525f .word 0x4745525f + 3f450: 46464f5f .word 0x46464f5f + 3f454: 5825203a .word 0x5825203a + 3f458: 0000000a .word 0x0000000a + +0003f45c <.LC9>: + 3f45c: 41555b0d .word 0x41555b0d + 3f460: 49205452 .word 0x49205452 + 3f464: 465d666e .word 0x465d666e + 3f468: 204f4649 .word 0x204f4649 + 3f46c: 746e6f43 .word 0x746e6f43 + 3f470: 206c6f72 .word 0x206c6f72 + 3f474: 56676552 .word 0x56676552 + 3f478: 65756c61 .word 0x65756c61 + 3f47c: 5825203a .word 0x5825203a + 3f480: 0000000a .word 0x0000000a + +0003f484 <.LC10>: + 3f484: 41555b0d .word 0x41555b0d + 3f488: 45205452 .word 0x45205452 + 3f48c: 255d7272 .word 0x255d7272 + 3f490: 49203a73 .word 0x49203a73 + 3f494: 6c61766e .word 0x6c61766e + 3f498: 55206469 .word 0x55206469 + 3f49c: 20545241 .word 0x20545241 + 3f4a0: 28786449 .word 0x28786449 + 3f4a4: 0a296425 .word 0x0a296425 + 3f4a8: 00000000 .word 0x00000000 + +0003f4ac <.LC11>: + 3f4ac: 41555b0d .word 0x41555b0d + 3f4b0: 45205452 .word 0x45205452 + 3f4b4: 495d7272 .word 0x495d7272 + 3f4b8: 6c61766e .word 0x6c61766e + 3f4bc: 55206469 .word 0x55206469 + 3f4c0: 20545241 .word 0x20545241 + 3f4c4: 65646e49 .word 0x65646e49 + 3f4c8: 64252878 .word 0x64252878 + 3f4cc: 00000a29 .word 0x00000a29 + +0003f4d0 <.LC12>: + 3f4d0: 41555b0d .word 0x41555b0d + 3f4d4: 45205452 .word 0x45205452 + 3f4d8: 555d7272 .word 0x555d7272 + 3f4dc: 20545241 .word 0x20545241 + 3f4e0: 46717249 .word 0x46717249 + 3f4e4: 69206e75 .word 0x69206e75 + 3f4e8: 754e2073 .word 0x754e2073 + 3f4ec: 000a6c6c .word 0x000a6c6c + +0003f4f0 <.LC13>: + 3f4f0: 41555b0d .word 0x41555b0d + 3f4f4: 57205452 .word 0x57205452 + 3f4f8: 485d6e72 .word 0x485d6e72 + 3f4fc: 75526c61 .word 0x75526c61 + 3f500: 49747261 .word 0x49747261 + 3f504: 6553746e .word 0x6553746e + 3f508: 7452646e .word 0x7452646e + 3f50c: 3931386c .word 0x3931386c + 3f510: 203a6135 .word 0x203a6135 + 3f514: 42206e6f .word 0x42206e6f + 3f518: 2c797375 .word 0x2c797375 + 3f51c: 61745320 .word 0x61745320 + 3f520: 253d6574 .word 0x253d6574 + 3f524: 00000a64 .word 0x00000a64 + +0003f528 <.LC14>: + 3f528: 41555b0d .word 0x41555b0d + 3f52c: 45205452 .word 0x45205452 + 3f530: 485d7272 .word 0x485d7272 + 3f534: 75526c61 .word 0x75526c61 + 3f538: 49747261 .word 0x49747261 + 3f53c: 6553746e .word 0x6553746e + 3f540: 7452646e .word 0x7452646e + 3f544: 3931386c .word 0x3931386c + 3f548: 203a6135 .word 0x203a6135 + 3f54c: 3a727245 .word 0x3a727245 + 3f550: 78547020 .word 0x78547020 + 3f554: 61746144 .word 0x61746144 + 3f558: 2578303d .word 0x2578303d + 3f55c: 20202c78 .word 0x20202c78 + 3f560: 676e654c .word 0x676e654c + 3f564: 253d6874 .word 0x253d6874 + 3f568: 00000a64 .word 0x00000a64 + +0003f56c <.LC15>: + 3f56c: 41555b0d .word 0x41555b0d + 3f570: 57205452 .word 0x57205452 + 3f574: 485d6e72 .word 0x485d6e72 + 3f578: 75526c61 .word 0x75526c61 + 3f57c: 49747261 .word 0x49747261 + 3f580: 6553746e .word 0x6553746e + 3f584: 7452646e .word 0x7452646e + 3f588: 3931386c .word 0x3931386c + 3f58c: 553a6135 .word 0x553a6135 + 3f590: 6c62616e .word 0x6c62616e + 3f594: 6f742065 .word 0x6f742065 + 3f598: 636f4c20 .word 0x636f4c20 + 3f59c: 53202c6b .word 0x53202c6b + 3f5a0: 75746174 .word 0x75746174 + 3f5a4: 0a64253d .word 0x0a64253d + 3f5a8: 00000000 .word 0x00000000 + +0003f5ac <.LC16>: + 3f5ac: 41555b0d .word 0x41555b0d + 3f5b0: 57205452 .word 0x57205452 + 3f5b4: 485d6e72 .word 0x485d6e72 + 3f5b8: 75526c61 .word 0x75526c61 + 3f5bc: 44747261 .word 0x44747261 + 3f5c0: 6553616d .word 0x6553616d + 3f5c4: 7452646e .word 0x7452646e + 3f5c8: 3931386c .word 0x3931386c + 3f5cc: 203a6135 .word 0x203a6135 + 3f5d0: 42206e6f .word 0x42206e6f + 3f5d4: 2c797375 .word 0x2c797375 + 3f5d8: 61745320 .word 0x61745320 + 3f5dc: 253d6574 .word 0x253d6574 + 3f5e0: 00000a64 .word 0x00000a64 + +0003f5e4 <.LC17>: + 3f5e4: 41555b0d .word 0x41555b0d + 3f5e8: 45205452 .word 0x45205452 + 3f5ec: 485d7272 .word 0x485d7272 + 3f5f0: 75526c61 .word 0x75526c61 + 3f5f4: 44747261 .word 0x44747261 + 3f5f8: 6553616d .word 0x6553616d + 3f5fc: 7452646e .word 0x7452646e + 3f600: 3931386c .word 0x3931386c + 3f604: 203a6135 .word 0x203a6135 + 3f608: 3a727245 .word 0x3a727245 + 3f60c: 78547020 .word 0x78547020 + 3f610: 61746144 .word 0x61746144 + 3f614: 2578303d .word 0x2578303d + 3f618: 20202c78 .word 0x20202c78 + 3f61c: 676e654c .word 0x676e654c + 3f620: 253d6874 .word 0x253d6874 + 3f624: 00000a64 .word 0x00000a64 + +0003f628 <.LC18>: + 3f628: 41555b0d .word 0x41555b0d + 3f62c: 57205452 .word 0x57205452 + 3f630: 485d6e72 .word 0x485d6e72 + 3f634: 75526c61 .word 0x75526c61 + 3f638: 44747261 .word 0x44747261 + 3f63c: 6553616d .word 0x6553616d + 3f640: 7452646e .word 0x7452646e + 3f644: 3931386c .word 0x3931386c + 3f648: 553a6135 .word 0x553a6135 + 3f64c: 6c62616e .word 0x6c62616e + 3f650: 6f742065 .word 0x6f742065 + 3f654: 636f4c20 .word 0x636f4c20 + 3f658: 53202c6b .word 0x53202c6b + 3f65c: 75746174 .word 0x75746174 + 3f660: 0a64253d .word 0x0a64253d + 3f664: 00000000 .word 0x00000000 + +0003f668 <.LC19>: + 3f668: 41555b0d .word 0x41555b0d + 3f66c: 45205452 .word 0x45205452 + 3f670: 535d7272 .word 0x535d7272 + 3f674: 72546372 .word 0x72546372 + 3f678: 74646957 .word 0x74646957 + 3f67c: 64253d68 .word 0x64253d68 + 3f680: 6f6c4220 .word 0x6f6c4220 + 3f684: 69536b63 .word 0x69536b63 + 3f688: 253d657a .word 0x253d657a + 3f68c: 00000a64 .word 0x00000a64 + +0003f690 <.LC20>: + 3f690: 41555b0d .word 0x41555b0d + 3f694: 57205452 .word 0x57205452 + 3f698: 485d6e72 .word 0x485d6e72 + 3f69c: 75526c61 .word 0x75526c61 + 3f6a0: 44747261 .word 0x44747261 + 3f6a4: 6553616d .word 0x6553616d + 3f6a8: 7452646e .word 0x7452646e + 3f6ac: 3931386c .word 0x3931386c + 3f6b0: 203a6135 .word 0x203a6135 + 3f6b4: 20746f4e .word 0x20746f4e + 3f6b8: 54206e69 .word 0x54206e69 + 3f6bc: 74732058 .word 0x74732058 + 3f6c0: 2c657461 .word 0x2c657461 + 3f6c4: 61745320 .word 0x61745320 + 3f6c8: 253d6574 .word 0x253d6574 + 3f6cc: 00000a64 .word 0x00000a64 + +0003f6d0 <.LC21>: + 3f6d0: 41555b0d .word 0x41555b0d + 3f6d4: 57205452 .word 0x57205452 + 3f6d8: 485d6e72 .word 0x485d6e72 + 3f6dc: 75526c61 .word 0x75526c61 + 3f6e0: 49747261 .word 0x49747261 + 3f6e4: 6552746e .word 0x6552746e + 3f6e8: 74527663 .word 0x74527663 + 3f6ec: 3931386c .word 0x3931386c + 3f6f0: 203a6135 .word 0x203a6135 + 3f6f4: 42206e6f .word 0x42206e6f + 3f6f8: 2c797375 .word 0x2c797375 + 3f6fc: 61745320 .word 0x61745320 + 3f700: 253d6574 .word 0x253d6574 + 3f704: 00000a64 .word 0x00000a64 + +0003f708 <.LC22>: + 3f708: 41555b0d .word 0x41555b0d + 3f70c: 45205452 .word 0x45205452 + 3f710: 485d7272 .word 0x485d7272 + 3f714: 75526c61 .word 0x75526c61 + 3f718: 49747261 .word 0x49747261 + 3f71c: 6552746e .word 0x6552746e + 3f720: 74527663 .word 0x74527663 + 3f724: 3931386c .word 0x3931386c + 3f728: 203a6135 .word 0x203a6135 + 3f72c: 3a727245 .word 0x3a727245 + 3f730: 78547020 .word 0x78547020 + 3f734: 61746144 .word 0x61746144 + 3f738: 2578303d .word 0x2578303d + 3f73c: 20202c78 .word 0x20202c78 + 3f740: 676e654c .word 0x676e654c + 3f744: 253d6874 .word 0x253d6874 + 3f748: 00000a64 .word 0x00000a64 + +0003f74c <.LC23>: + 3f74c: 41555b0d .word 0x41555b0d + 3f750: 57205452 .word 0x57205452 + 3f754: 485d6e72 .word 0x485d6e72 + 3f758: 75526c61 .word 0x75526c61 + 3f75c: 49747261 .word 0x49747261 + 3f760: 6552746e .word 0x6552746e + 3f764: 74527663 .word 0x74527663 + 3f768: 3931386c .word 0x3931386c + 3f76c: 553a6135 .word 0x553a6135 + 3f770: 6c62616e .word 0x6c62616e + 3f774: 6f742065 .word 0x6f742065 + 3f778: 636f4c20 .word 0x636f4c20 + 3f77c: 53202c6b .word 0x53202c6b + 3f780: 75746174 .word 0x75746174 + 3f784: 0a64253d .word 0x0a64253d + 3f788: 00000000 .word 0x00000000 + +0003f78c <.LC24>: + 3f78c: 41555b0d .word 0x41555b0d + 3f790: 57205452 .word 0x57205452 + 3f794: 255d6e72 .word 0x255d6e72 + 3f798: 6f203a73 .word 0x6f203a73 + 3f79c: 7542206e .word 0x7542206e + 3f7a0: 202c7973 .word 0x202c7973 + 3f7a4: 74617453 .word 0x74617453 + 3f7a8: 64253d65 .word 0x64253d65 + 3f7ac: 0000000a .word 0x0000000a + +0003f7b0 <.LC25>: + 3f7b0: 41555b0d .word 0x41555b0d + 3f7b4: 45205452 .word 0x45205452 + 3f7b8: 485d7272 .word 0x485d7272 + 3f7bc: 75526c61 .word 0x75526c61 + 3f7c0: 44747261 .word 0x44747261 + 3f7c4: 6552616d .word 0x6552616d + 3f7c8: 74527663 .word 0x74527663 + 3f7cc: 3931386c .word 0x3931386c + 3f7d0: 203a6135 .word 0x203a6135 + 3f7d4: 3a727245 .word 0x3a727245 + 3f7d8: 78547020 .word 0x78547020 + 3f7dc: 61746144 .word 0x61746144 + 3f7e0: 2578303d .word 0x2578303d + 3f7e4: 20202c78 .word 0x20202c78 + 3f7e8: 676e654c .word 0x676e654c + 3f7ec: 253d6874 .word 0x253d6874 + 3f7f0: 00000a64 .word 0x00000a64 + +0003f7f4 <.LC26>: + 3f7f4: 41555b0d .word 0x41555b0d + 3f7f8: 57205452 .word 0x57205452 + 3f7fc: 485d6e72 .word 0x485d6e72 + 3f800: 75526c61 .word 0x75526c61 + 3f804: 44747261 .word 0x44747261 + 3f808: 6552616d .word 0x6552616d + 3f80c: 74527663 .word 0x74527663 + 3f810: 3931386c .word 0x3931386c + 3f814: 553a6135 .word 0x553a6135 + 3f818: 6c62616e .word 0x6c62616e + 3f81c: 6f742065 .word 0x6f742065 + 3f820: 636f4c20 .word 0x636f4c20 + 3f824: 53202c6b .word 0x53202c6b + 3f828: 75746174 .word 0x75746174 + 3f82c: 0a64253d .word 0x0a64253d + 3f830: 00000000 .word 0x00000000 + +0003f834 <.LC27>: + 3f834: 41555b0d .word 0x41555b0d + 3f838: 57205452 .word 0x57205452 + 3f83c: 485d6e72 .word 0x485d6e72 + 3f840: 75526c61 .word 0x75526c61 + 3f844: 53747261 .word 0x53747261 + 3f848: 52706f74 .word 0x52706f74 + 3f84c: 52766365 .word 0x52766365 + 3f850: 31386c74 .word 0x31386c74 + 3f854: 3a613539 .word 0x3a613539 + 3f858: 746f4e20 .word 0x746f4e20 + 3f85c: 206e6920 .word 0x206e6920 + 3f860: 73205854 .word 0x73205854 + 3f864: 65746174 .word 0x65746174 + 3f868: 7453202c .word 0x7453202c + 3f86c: 3d657461 .word 0x3d657461 + 3f870: 000a6425 .word 0x000a6425 + +0003f874 <.LC28>: + 3f874: 41555b0d .word 0x41555b0d + 3f878: 57205452 .word 0x57205452 + 3f87c: 485d6e72 .word 0x485d6e72 + 3f880: 75526c61 .word 0x75526c61 + 3f884: 53747261 .word 0x53747261 + 3f888: 52706f74 .word 0x52706f74 + 3f88c: 52766365 .word 0x52766365 + 3f890: 31386c74 .word 0x31386c74 + 3f894: 3a613539 .word 0x3a613539 + 3f898: 62616e55 .word 0x62616e55 + 3f89c: 7420656c .word 0x7420656c + 3f8a0: 6f4c206f .word 0x6f4c206f + 3f8a4: 202c6b63 .word 0x202c6b63 + 3f8a8: 74617453 .word 0x74617453 + 3f8ac: 64253d75 .word 0x64253d75 + 3f8b0: 0000000a .word 0x0000000a + +0003f8b4 <.LC29>: + 3f8b4: 41555b0d .word 0x41555b0d + 3f8b8: 57205452 .word 0x57205452 + 3f8bc: 485d6e72 .word 0x485d6e72 + 3f8c0: 75526c61 .word 0x75526c61 + 3f8c4: 53747261 .word 0x53747261 + 3f8c8: 52646e65 .word 0x52646e65 + 3f8cc: 31386c74 .word 0x31386c74 + 3f8d0: 3a613539 .word 0x3a613539 + 3f8d4: 206e6f20 .word 0x206e6f20 + 3f8d8: 79737542 .word 0x79737542 + 3f8dc: 7453202c .word 0x7453202c + 3f8e0: 3d657461 .word 0x3d657461 + 3f8e4: 000a6425 .word 0x000a6425 + +0003f8e8 <.LC30>: + 3f8e8: 41555b0d .word 0x41555b0d + 3f8ec: 45205452 .word 0x45205452 + 3f8f0: 485d7272 .word 0x485d7272 + 3f8f4: 75526c61 .word 0x75526c61 + 3f8f8: 53747261 .word 0x53747261 + 3f8fc: 52646e65 .word 0x52646e65 + 3f900: 31386c74 .word 0x31386c74 + 3f904: 3a613539 .word 0x3a613539 + 3f908: 72724520 .word 0x72724520 + 3f90c: 5470203a .word 0x5470203a + 3f910: 74614478 .word 0x74614478 + 3f914: 78303d61 .word 0x78303d61 + 3f918: 202c7825 .word 0x202c7825 + 3f91c: 6e654c20 .word 0x6e654c20 + 3f920: 3d687467 .word 0x3d687467 + 3f924: 000a6425 .word 0x000a6425 + +0003f928 <.LC31>: + 3f928: 41555b0d .word 0x41555b0d + 3f92c: 57205452 .word 0x57205452 + 3f930: 485d6e72 .word 0x485d6e72 + 3f934: 75526c61 .word 0x75526c61 + 3f938: 53747261 .word 0x53747261 + 3f93c: 52646e65 .word 0x52646e65 + 3f940: 31386c74 .word 0x31386c74 + 3f944: 3a613539 .word 0x3a613539 + 3f948: 62616e55 .word 0x62616e55 + 3f94c: 7420656c .word 0x7420656c + 3f950: 6f4c206f .word 0x6f4c206f + 3f954: 202c6b63 .word 0x202c6b63 + 3f958: 74617453 .word 0x74617453 + 3f95c: 64253d75 .word 0x64253d75 + 3f960: 0000000a .word 0x0000000a + +0003f964 <.LC32>: + 3f964: 41555b0d .word 0x41555b0d + 3f968: 49205452 .word 0x49205452 + 3f96c: 485d666e .word 0x485d666e + 3f970: 75526c61 .word 0x75526c61 + 3f974: 53747261 .word 0x53747261 + 3f978: 52646e65 .word 0x52646e65 + 3f97c: 31386c74 .word 0x31386c74 + 3f980: 3a613539 .word 0x3a613539 + 3f984: 676e654c .word 0x676e654c + 3f988: 253d6874 .word 0x253d6874 + 3f98c: 69542064 .word 0x69542064 + 3f990: 756f656d .word 0x756f656d + 3f994: 64253d74 .word 0x64253d74 + 3f998: 0000000a .word 0x0000000a + +0003f99c <.LC33>: + 3f99c: 41555b0d .word 0x41555b0d + 3f9a0: 57205452 .word 0x57205452 + 3f9a4: 485d6e72 .word 0x485d6e72 + 3f9a8: 75526c61 .word 0x75526c61 + 3f9ac: 53747261 .word 0x53747261 + 3f9b0: 52646e65 .word 0x52646e65 + 3f9b4: 31386c74 .word 0x31386c74 + 3f9b8: 3a613539 .word 0x3a613539 + 3f9bc: 20785420 .word 0x20785420 + 3f9c0: 656d6954 .word 0x656d6954 + 3f9c4: 2c74756f .word 0x2c74756f + 3f9c8: 43785420 .word 0x43785420 + 3f9cc: 746e756f .word 0x746e756f + 3f9d0: 0a64253d .word 0x0a64253d + 3f9d4: 00000000 .word 0x00000000 + +0003f9d8 <.LC34>: + 3f9d8: 41555b0d .word 0x41555b0d + 3f9dc: 57205452 .word 0x57205452 + 3f9e0: 485d6e72 .word 0x485d6e72 + 3f9e4: 75526c61 .word 0x75526c61 + 3f9e8: 52747261 .word 0x52747261 + 3f9ec: 52766365 .word 0x52766365 + 3f9f0: 31386c74 .word 0x31386c74 + 3f9f4: 3a613539 .word 0x3a613539 + 3f9f8: 206e6f20 .word 0x206e6f20 + 3f9fc: 79737542 .word 0x79737542 + 3fa00: 7453202c .word 0x7453202c + 3fa04: 3d657461 .word 0x3d657461 + 3fa08: 000a6425 .word 0x000a6425 + +0003fa0c <.LC35>: + 3fa0c: 41555b0d .word 0x41555b0d + 3fa10: 45205452 .word 0x45205452 + 3fa14: 485d7272 .word 0x485d7272 + 3fa18: 75526c61 .word 0x75526c61 + 3fa1c: 52747261 .word 0x52747261 + 3fa20: 52766365 .word 0x52766365 + 3fa24: 31386c74 .word 0x31386c74 + 3fa28: 3a613539 .word 0x3a613539 + 3fa2c: 72724520 .word 0x72724520 + 3fa30: 5470203a .word 0x5470203a + 3fa34: 74614478 .word 0x74614478 + 3fa38: 78303d61 .word 0x78303d61 + 3fa3c: 202c7825 .word 0x202c7825 + 3fa40: 6e654c20 .word 0x6e654c20 + 3fa44: 3d687467 .word 0x3d687467 + 3fa48: 000a6425 .word 0x000a6425 + +0003fa4c <.LC36>: + 3fa4c: 41555b0d .word 0x41555b0d + 3fa50: 57205452 .word 0x57205452 + 3fa54: 485d6e72 .word 0x485d6e72 + 3fa58: 75526c61 .word 0x75526c61 + 3fa5c: 52747261 .word 0x52747261 + 3fa60: 52766365 .word 0x52766365 + 3fa64: 31386c74 .word 0x31386c74 + 3fa68: 3a613539 .word 0x3a613539 + 3fa6c: 62616e55 .word 0x62616e55 + 3fa70: 7420656c .word 0x7420656c + 3fa74: 6f4c206f .word 0x6f4c206f + 3fa78: 202c6b63 .word 0x202c6b63 + 3fa7c: 74617453 .word 0x74617453 + 3fa80: 64253d75 .word 0x64253d75 + 3fa84: 0000000a .word 0x0000000a + +0003fa88 <.LC37>: + 3fa88: 41555b0d .word 0x41555b0d + 3fa8c: 57205452 .word 0x57205452 + 3fa90: 485d6e72 .word 0x485d6e72 + 3fa94: 75526c61 .word 0x75526c61 + 3fa98: 52747261 .word 0x52747261 + 3fa9c: 52766365 .word 0x52766365 + 3faa0: 31386c74 .word 0x31386c74 + 3faa4: 3a613539 .word 0x3a613539 + 3faa8: 20785220 .word 0x20785220 + 3faac: 656d6954 .word 0x656d6954 + 3fab0: 2c74756f .word 0x2c74756f + 3fab4: 43785220 .word 0x43785220 + 3fab8: 746e756f .word 0x746e756f + 3fabc: 0a64253d .word 0x0a64253d + 3fac0: 00000000 .word 0x00000000 + +0003fac4 <.LC38>: + 3fac4: 41555b0d .word 0x41555b0d + 3fac8: 49205452 .word 0x49205452 + 3facc: 1b5d666e .word 0x1b5d666e + 3fad0: 6d32335b .word 0x6d32335b + 3fad4: 20296425 .word 0x20296425 + 3fad8: 65736552 .word 0x65736552 + 3fadc: 41552074 .word 0x41552074 + 3fae0: 64255452 .word 0x64255452 + 3fae4: 46785220 .word 0x46785220 + 3fae8: 214f4649 .word 0x214f4649 + 3faec: 52534c20 .word 0x52534c20 + 3faf0: 31783028 .word 0x31783028 + 3faf4: 3d202934 .word 0x3d202934 + 3faf8: 25783020 .word 0x25783020 + 3fafc: 0a583230 .word 0x0a583230 + 3fb00: 6d305b1b .word 0x6d305b1b + 3fb04: 00000000 .word 0x00000000 + +0003fb08 <.LC39>: + 3fb08: 41555b0d .word 0x41555b0d + 3fb0c: 57205452 .word 0x57205452 + 3fb10: 1b5d6e72 .word 0x1b5d6e72 + 3fb14: 6d35335b .word 0x6d35335b + 3fb18: 20296425 .word 0x20296425 + 3fb1c: 65736552 .word 0x65736552 + 3fb20: 41552074 .word 0x41552074 + 3fb24: 64255452 .word 0x64255452 + 3fb28: 46785220 .word 0x46785220 + 3fb2c: 214f4649 .word 0x214f4649 + 3fb30: 52534c20 .word 0x52534c20 + 3fb34: 31783028 .word 0x31783028 + 3fb38: 3d202934 .word 0x3d202934 + 3fb3c: 25783020 .word 0x25783020 + 3fb40: 0a583230 .word 0x0a583230 + 3fb44: 6d305b1b .word 0x6d305b1b + 3fb48: 00000000 .word 0x00000000 + +0003fb4c <.LC40>: + 3fb4c: 41555b0d .word 0x41555b0d + 3fb50: 45205452 .word 0x45205452 + 3fb54: 1b5d7272 .word 0x1b5d7272 + 3fb58: 6d35335b .word 0x6d35335b + 3fb5c: 65736552 .word 0x65736552 + 3fb60: 41552074 .word 0x41552074 + 3fb64: 64255452 .word 0x64255452 + 3fb68: 46785220 .word 0x46785220 + 3fb6c: 204f4649 .word 0x204f4649 + 3fb70: 4c494146 .word 0x4c494146 + 3fb74: 0a214445 .word 0x0a214445 + 3fb78: 6d305b1b .word 0x6d305b1b + 3fb7c: 00000000 .word 0x00000000 + +0003fb80 <.LC41>: + 3fb80: 41555b0d .word 0x41555b0d + 3fb84: 45205452 .word 0x45205452 + 3fb88: 1b5d7272 .word 0x1b5d7272 + 3fb8c: 6d35335b .word 0x6d35335b + 3fb90: 526c6148 .word 0x526c6148 + 3fb94: 74726175 .word 0x74726175 + 3fb98: 74696e49 .word 0x74696e49 + 3fb9c: 386c7452 .word 0x386c7452 + 3fba0: 61353931 .word 0x61353931 + 3fba4: 6e49203a .word 0x6e49203a + 3fba8: 696c6176 .word 0x696c6176 + 3fbac: 41552064 .word 0x41552064 + 3fbb0: 49205452 .word 0x49205452 + 3fbb4: 7865646e .word 0x7865646e + 3fbb8: 305b1b0a .word 0x305b1b0a + 3fbbc: 0000006d .word 0x0000006d + +0003fbc0 <.LC42>: + 3fbc0: 41555b0d .word 0x41555b0d + 3fbc4: 49205452 .word 0x49205452 + 3fbc8: 485d666e .word 0x485d666e + 3fbcc: 75526c61 .word 0x75526c61 + 3fbd0: 49747261 .word 0x49747261 + 3fbd4: 5274696e .word 0x5274696e + 3fbd8: 31386c74 .word 0x31386c74 + 3fbdc: 3a613539 .word 0x3a613539 + 3fbe0: 41555b20 .word 0x41555b20 + 3fbe4: 25205452 .word 0x25205452 + 3fbe8: 50205d64 .word 0x50205d64 + 3fbec: 65536e69 .word 0x65536e69 + 3fbf0: 64253d6c .word 0x64253d6c + 3fbf4: 0000000a .word 0x0000000a + +0003fbf8 <.LC43>: + 3fbf8: 41555b0d .word 0x41555b0d + 3fbfc: 57205452 .word 0x57205452 + 3fc00: 1b5d6e72 .word 0x1b5d6e72 + 3fc04: 6d35335b .word 0x6d35335b + 3fc08: 61736944 .word 0x61736944 + 3fc0c: 20656c62 .word 0x20656c62 + 3fc10: 4741544a .word 0x4741544a + 3fc14: 6e756620 .word 0x6e756620 + 3fc18: 6f697463 .word 0x6f697463 + 3fc1c: 7564206e .word 0x7564206e + 3fc20: 6f742065 .word 0x6f742065 + 3fc24: 6e697020 .word 0x6e697020 + 3fc28: 6e6f6320 .word 0x6e6f6320 + 3fc2c: 63696c66 .word 0x63696c66 + 3fc30: 5b1b0a74 .word 0x5b1b0a74 + 3fc34: 00006d30 .word 0x00006d30 + +0003fc38 <.LC44>: + 3fc38: 41555b0d .word 0x41555b0d + 3fc3c: 57205452 .word 0x57205452 + 3fc40: 445d6e72 .word 0x445d6e72 + 3fc44: 62617369 .word 0x62617369 + 3fc48: 4520656c .word 0x4520656c + 3fc4c: 4f525045 .word 0x4f525045 + 3fc50: 6950204d .word 0x6950204d + 3fc54: 6f66206e .word 0x6f66206e + 3fc58: 41552072 .word 0x41552072 + 3fc5c: 30205452 .word 0x30205452 + 3fc60: 0000000a .word 0x0000000a + +0003fc64 <.LC45>: + 3fc64: 41555b0d .word 0x41555b0d + 3fc68: 49205452 .word 0x49205452 + 3fc6c: 1b5d666e .word 0x1b5d666e + 3fc70: 6d36335b .word 0x6d36335b + 3fc74: 204c4148 .word 0x204c4148 + 3fc78: 54524155 .word 0x54524155 + 3fc7c: 696e4920 .word 0x696e4920 + 3fc80: 41555b74 .word 0x41555b74 + 3fc84: 25205452 .word 0x25205452 + 3fc88: 1b0a5d64 .word 0x1b0a5d64 + 3fc8c: 006d305b .word 0x006d305b + +0003fc90 <.LC46>: + 3fc90: 41555b0d .word 0x41555b0d + 3fc94: 49205452 .word 0x49205452 + 3fc98: 5b5d666e .word 0x5b5d666e + 3fc9c: 52205d52 .word 0x52205d52 + 3fca0: 54524155 .word 0x54524155 + 3fca4: 4e494c5f .word 0x4e494c5f + 3fca8: 54435f45 .word 0x54435f45 + 3fcac: 45525f4c .word 0x45525f4c + 3fcb0: 464f5f47 .word 0x464f5f47 + 3fcb4: 78302846 .word 0x78302846 + 3fcb8: 20294330 .word 0x20294330 + 3fcbc: 7825203d .word 0x7825203d + 3fcc0: 0000000a .word 0x0000000a + +0003fcc4 <.LC47>: + 3fcc4: 41555b0d .word 0x41555b0d + 3fcc8: 45205452 .word 0x45205452 + 3fccc: 495d7272 .word 0x495d7272 + 3fcd0: 6c61766e .word 0x6c61766e + 3fcd4: 42206469 .word 0x42206469 + 3fcd8: 52647561 .word 0x52647561 + 3fcdc: 28657461 .word 0x28657461 + 3fce0: 2c296425 .word 0x2c296425 + 3fce4: 726f4620 .word 0x726f4620 + 3fce8: 69206563 .word 0x69206563 + 3fcec: 73612074 .word 0x73612074 + 3fcf0: 66656420 .word 0x66656420 + 3fcf4: 746c7561 .word 0x746c7561 + 3fcf8: 29642528 .word 0x29642528 + 3fcfc: 0000000a .word 0x0000000a + +0003fd00 <.LC48>: + 3fd00: 41555b0d .word 0x41555b0d + 3fd04: 49205452 .word 0x49205452 + 3fd08: 425d666e .word 0x425d666e + 3fd0c: 20647561 .word 0x20647561 + 3fd10: 202c6425 .word 0x202c6425 + 3fd14: 7273764f .word 0x7273764f + 3fd18: 2c642520 .word 0x2c642520 + 3fd1c: 76694420 .word 0x76694420 + 3fd20: 2c642520 .word 0x2c642520 + 3fd24: 73764f20 .word 0x73764f20 + 3fd28: 6a644172 .word 0x6a644172 + 3fd2c: 25783020 .word 0x25783020 + 3fd30: 00000a58 .word 0x00000a58 + +0003fd34 <.LC49>: + 3fd34: 41555b0d .word 0x41555b0d + 3fd38: 49205452 .word 0x49205452 + 3fd3c: 435d666e .word 0x435d666e + 3fd40: 75636c61 .word 0x75636c61 + 3fd44: 6574616c .word 0x6574616c + 3fd48: 6c442064 .word 0x6c442064 + 3fd4c: 44202c6c .word 0x44202c6c + 3fd50: 3d206d6c .word 0x3d206d6c + 3fd54: 32302520 .word 0x32302520 + 3fd58: 25202c78 .word 0x25202c78 + 3fd5c: 0a783230 .word 0x0a783230 + 3fd60: 00000000 .word 0x00000000 + +0003fd64 <.LC50>: + 3fd64: 41555b0d .word 0x41555b0d + 3fd68: 49205452 .word 0x49205452 + 3fd6c: 2d5d666e .word 0x2d5d666e + 3fd70: 202d2d2d .word 0x202d2d2d + 3fd74: 6f666542 .word 0x6f666542 + 3fd78: 73206572 .word 0x73206572 + 3fd7c: 69747465 .word 0x69747465 + 3fd80: 6220676e .word 0x6220676e + 3fd84: 20647561 .word 0x20647561 + 3fd88: 65746172 .word 0x65746172 + 3fd8c: 2d2d2d20 .word 0x2d2d2d20 + 3fd90: 00000a2d .word 0x00000a2d + +0003fd94 <.LC51>: + 3fd94: 41555b0d .word 0x41555b0d + 3fd98: 49205452 .word 0x49205452 + 3fd9c: 205d666e .word 0x205d666e + 3fda0: 5d525b20 .word 0x5d525b20 + 3fda4: 41555220 .word 0x41555220 + 3fda8: 445f5452 .word 0x445f5452 + 3fdac: 4f5f4c4c .word 0x4f5f4c4c + 3fdb0: 30284646 .word 0x30284646 + 3fdb4: 29303078 .word 0x29303078 + 3fdb8: 25203d20 .word 0x25203d20 + 3fdbc: 00000a78 .word 0x00000a78 + +0003fdc0 <.LC52>: + 3fdc0: 41555b0d .word 0x41555b0d + 3fdc4: 49205452 .word 0x49205452 + 3fdc8: 205d666e .word 0x205d666e + 3fdcc: 5d525b20 .word 0x5d525b20 + 3fdd0: 41555220 .word 0x41555220 + 3fdd4: 445f5452 .word 0x445f5452 + 3fdd8: 4f5f4d4c .word 0x4f5f4d4c + 3fddc: 30284646 .word 0x30284646 + 3fde0: 29343078 .word 0x29343078 + 3fde4: 25203d20 .word 0x25203d20 + 3fde8: 00000a78 .word 0x00000a78 + +0003fdec <.LC53>: + 3fdec: 41555b0d .word 0x41555b0d + 3fdf0: 49205452 .word 0x49205452 + 3fdf4: 2d5d666e .word 0x2d5d666e + 3fdf8: 202d2d2d .word 0x202d2d2d + 3fdfc: 65746641 .word 0x65746641 + 3fe00: 65732072 .word 0x65732072 + 3fe04: 6e697474 .word 0x6e697474 + 3fe08: 61622067 .word 0x61622067 + 3fe0c: 72206475 .word 0x72206475 + 3fe10: 20657461 .word 0x20657461 + 3fe14: 2d2d2d2d .word 0x2d2d2d2d + 3fe18: 0000000a .word 0x0000000a + +0003fe1c <.LC54>: + 3fe1c: 41555b0d .word 0x41555b0d + 3fe20: 49205452 .word 0x49205452 + 3fe24: 1b5d666e .word 0x1b5d666e + 3fe28: 6d36335b .word 0x6d36335b + 3fe2c: 2d2d2d2d .word 0x2d2d2d2d + 3fe30: 66654220 .word 0x66654220 + 3fe34: 4f20726f .word 0x4f20726f + 3fe38: 20525356 .word 0x20525356 + 3fe3c: 564f2026 .word 0x564f2026 + 3fe40: 415f5253 .word 0x415f5253 + 3fe44: 2d204a44 .word 0x2d204a44 + 3fe48: 0a2d2d2d .word 0x0a2d2d2d + 3fe4c: 6d305b1b .word 0x6d305b1b + 3fe50: 00000000 .word 0x00000000 + +0003fe54 <.LC55>: + 3fe54: 41555b0d .word 0x41555b0d + 3fe58: 49205452 .word 0x49205452 + 3fe5c: 555d666e .word 0x555d666e + 3fe60: 25545241 .word 0x25545241 + 3fe64: 50532064 .word 0x50532064 + 3fe68: 78302852 .word 0x78302852 + 3fe6c: 20294331 .word 0x20294331 + 3fe70: 5825203d .word 0x5825203d + 3fe74: 0000000a .word 0x0000000a + +0003fe78 <.LC56>: + 3fe78: 41555b0d .word 0x41555b0d + 3fe7c: 49205452 .word 0x49205452 + 3fe80: 555d666e .word 0x555d666e + 3fe84: 25545241 .word 0x25545241 + 3fe88: 49532064 .word 0x49532064 + 3fe8c: 78302853 .word 0x78302853 + 3fe90: 20293032 .word 0x20293032 + 3fe94: 5825203d .word 0x5825203d + 3fe98: 0000000a .word 0x0000000a + +0003fe9c <.LC57>: + 3fe9c: 41555b0d .word 0x41555b0d + 3fea0: 49205452 .word 0x49205452 + 3fea4: 1b5d666e .word 0x1b5d666e + 3fea8: 6d36335b .word 0x6d36335b + 3feac: 2d2d2d2d .word 0x2d2d2d2d + 3feb0: 74664120 .word 0x74664120 + 3feb4: 4f207265 .word 0x4f207265 + 3feb8: 20525356 .word 0x20525356 + 3febc: 564f2026 .word 0x564f2026 + 3fec0: 415f5253 .word 0x415f5253 + 3fec4: 2d204a44 .word 0x2d204a44 + 3fec8: 0a2d2d2d .word 0x0a2d2d2d + 3fecc: 6d305b1b .word 0x6d305b1b + 3fed0: 00000000 .word 0x00000000 + +0003fed4 <.LC58>: + 3fed4: 41555b0d .word 0x41555b0d + 3fed8: 49205452 .word 0x49205452 + 3fedc: 5b5d666e .word 0x5b5d666e + 3fee0: 55205d52 .word 0x55205d52 + 3fee4: 25545241 .word 0x25545241 + 3fee8: 4e492064 .word 0x4e492064 + 3feec: 4e455f54 .word 0x4e455f54 + 3fef0: 30783028 .word 0x30783028 + 3fef4: 3d202934 .word 0x3d202934 + 3fef8: 0a782520 .word 0x0a782520 + 3fefc: 00000000 .word 0x00000000 + +0003ff00 <.LC59>: + 3ff00: 41555b0d .word 0x41555b0d + 3ff04: 49205452 .word 0x49205452 + 3ff08: 5b5d666e .word 0x5b5d666e + 3ff0c: 55205d52 .word 0x55205d52 + 3ff10: 25545241 .word 0x25545241 + 3ff14: 434c2064 .word 0x434c2064 + 3ff18: 78302852 .word 0x78302852 + 3ff1c: 58323025 .word 0x58323025 + 3ff20: 25203a29 .word 0x25203a29 + 3ff24: 00000a58 .word 0x00000a58 + +0003ff28 <.LC60>: + 3ff28: 41555b0d .word 0x41555b0d + 3ff2c: 49205452 .word 0x49205452 + 3ff30: 5b5d666e .word 0x5b5d666e + 3ff34: 55205d57 .word 0x55205d57 + 3ff38: 25545241 .word 0x25545241 + 3ff3c: 434c2064 .word 0x434c2064 + 3ff40: 78302852 .word 0x78302852 + 3ff44: 58323025 .word 0x58323025 + 3ff48: 25203a29 .word 0x25203a29 + 3ff4c: 00000a58 .word 0x00000a58 + +0003ff50 <.LC0>: + 3ff50: 44475b0d .word 0x44475b0d + 3ff54: 5720414d .word 0x5720414d + 3ff58: 435d6e72 .word 0x435d6e72 + 3ff5c: 6e6e6168 .word 0x6e6e6168 + 3ff60: 68206c65 .word 0x68206c65 + 3ff64: 75206461 .word 0x75206461 + 3ff68: 3b646573 .word 0x3b646573 + 3ff6c: 73694420 .word 0x73694420 + 3ff70: 656c6261 .word 0x656c6261 + 3ff74: 61684320 .word 0x61684320 + 3ff78: 6c656e6e .word 0x6c656e6e + 3ff7c: 21212121 .word 0x21212121 + 3ff80: 0000000a .word 0x0000000a + +0003ff84 <.LC1>: + 3ff84: 44475b0d .word 0x44475b0d + 3ff88: 4920414d .word 0x4920414d + 3ff8c: 435d666e .word 0x435d666e + 3ff90: 4c204746 .word 0x4c204746 + 3ff94: 6420776f .word 0x6420776f + 3ff98: 3a617461 .word 0x3a617461 + 3ff9c: 78257830 .word 0x78257830 + 3ffa0: 0000000a .word 0x0000000a + +0003ffa4 <.LC2>: + 3ffa4: 44475b0d .word 0x44475b0d + 3ffa8: 5720414d .word 0x5720414d + 3ffac: 4c5d6e72 .word 0x4c5d6e72 + 3ffb0: 4120694c .word 0x4120694c + 3ffb4: 3a726464 .word 0x3a726464 + 3ffb8: 25783020 .word 0x25783020 + 3ffbc: 6f6e2078 .word 0x6f6e2078 + 3ffc0: 20342074 .word 0x20342074 + 3ffc4: 65747962 .word 0x65747962 + 3ffc8: 6c612073 .word 0x6c612073 + 3ffcc: 6d6e6769 .word 0x6d6e6769 + 3ffd0: 21746e65 .word 0x21746e65 + 3ffd4: 0a212121 .word 0x0a212121 + 3ffd8: 00000000 .word 0x00000000 + +0003ffdc <.LC3>: + 3ffdc: 44475b0d .word 0x44475b0d + 3ffe0: 4920414d .word 0x4920414d + 3ffe4: 425d666e .word 0x425d666e + 3ffe8: 6b636f6c .word 0x6b636f6c + 3ffec: 756f4320 .word 0x756f4320 + 3fff0: 2520746e .word 0x2520746e + 3fff4: 00000a64 .word 0x00000a64 + +0003fff8 <.LC4>: + 3fff8: 6c4c700d .word 0x6c4c700d + 3fffc: 656c4569 .word 0x656c4569 + 40000: 6c754e20 .word 0x6c754e20 + 40004: 6f50206c .word 0x6f50206c + 40008: 21746e69 .word 0x21746e69 + 4000c: 21212121 .word 0x21212121 + 40010: 0000000a .word 0x0000000a + +00040014 <.LC5>: + 40014: 44475b0d .word 0x44475b0d + 40018: 4920414d .word 0x4920414d + 4001c: 485d666e .word 0x485d666e + 40020: 64476c61 .word 0x64476c61 + 40024: 6843616d .word 0x6843616d + 40028: 43727349 .word 0x43727349 + 4002c: 6e61656c .word 0x6e61656c + 40030: 386c7452 .word 0x386c7452 + 40034: 61353931 .word 0x61353931 + 40038: 7349203a .word 0x7349203a + 4003c: 79542072 .word 0x79542072 + 40040: 25206570 .word 0x25206570 + 40044: 49203a64 .word 0x49203a64 + 40048: 53207273 .word 0x53207273 + 4004c: 75746174 .word 0x75746174 + 40050: 78302073 .word 0x78302073 + 40054: 000a7825 .word 0x000a7825 + +00040058 <.LC0>: + 40058: 00007325 .word 0x00007325 + +0004005c <.LC1>: + 4005c: 0000000a .word 0x0000000a + +00040060 <.LC2>: + 40060: 30255b0a .word 0x30255b0a + 40064: 205d7838 .word 0x205d7838 + 40068: 00000000 .word 0x00000000 + +0004006c <.LC3>: + 4006c: 00002020 .word 0x00002020 + +00040070 <.LC4>: + 40070: 78323025 .word 0x78323025 + 40074: 00000020 .word 0x00000020 + +00040078 <.LC5>: + 40078: 00202020 .word 0x00202020 + +0004007c <.LC6>: + 4007c: 52435b0d .word 0x52435b0d + 40080: 45205059 .word 0x45205059 + 40084: 255d7272 .word 0x255d7272 + 40088: 3a292873 .word 0x3a292873 + 4008c: 206f4e20 .word 0x206f4e20 + 40090: 73696874 .word 0x73696874 + 40094: 74756120 .word 0x74756120 + 40098: 79745f68 .word 0x79745f68 + 4009c: 25286570 .word 0x25286570 + 400a0: 66202964 .word 0x66202964 + 400a4: 5320726f .word 0x5320726f + 400a8: 0a324148 .word 0x0a324148 + 400ac: 0000000a .word 0x0000000a + +000400b0 <.LC7>: + 400b0: 5f6c7472 .word 0x5f6c7472 + 400b4: 70797263 .word 0x70797263 + 400b8: 6e456f74 .word 0x6e456f74 + 400bc: 656e6967 .word 0x656e6967 + 400c0: 7272655f .word 0x7272655f + 400c4: 00000000 .word 0x00000000 + +000400c8 <.LC8>: + 400c8: 29287325 .word 0x29287325 + 400cc: 656d203a .word 0x656d203a + 400d0: 6d75646d .word 0x6d75646d + 400d4: 203a2070 .word 0x203a2070 + 400d8: 72646461 .word 0x72646461 + 400dc: 3a737365 .word 0x3a737365 + 400e0: 38302520 .word 0x38302520 + 400e4: 73202c78 .word 0x73202c78 + 400e8: 3a657a69 .word 0x3a657a69 + 400ec: 0a642520 .word 0x0a642520 + 400f0: 00000000 .word 0x00000000 + +000400f4 <.LC9>: + 400f4: 5f6c7472 .word 0x5f6c7472 + 400f8: 70797263 .word 0x70797263 + 400fc: 6e456f74 .word 0x6e456f74 + 40100: 656e6967 .word 0x656e6967 + 40104: 6762645f .word 0x6762645f + 40108: 00000000 .word 0x00000000 + +0004010c <.LC10>: + 4010c: 3a59454b .word 0x3a59454b + 40110: 00000020 .word 0x00000020 + +00040114 <.LC11>: + 40114: 20637273 .word 0x20637273 + 40118: 63736544 .word 0x63736544 + 4011c: 0000003a .word 0x0000003a + +00040120 <.LC12>: + 40120: 203a5649 .word 0x203a5649 + 40124: 00000000 .word 0x00000000 + +00040128 <.LC13>: + 40128: 52435b0d .word 0x52435b0d + 4012c: 45205059 .word 0x45205059 + 40130: 255d7272 .word 0x255d7272 + 40134: 3a292873 .word 0x3a292873 + 40138: 6e656c20 .word 0x6e656c20 + 4013c: 28687467 .word 0x28687467 + 40140: 20296425 .word 0x20296425 + 40144: 20726f66 .word 0x20726f66 + 40148: 32414853 .word 0x32414853 + 4014c: 20736920 .word 0x20736920 + 40150: 20746f6e .word 0x20746f6e + 40154: 72726f63 .word 0x72726f63 + 40158: 0a746365 .word 0x0a746365 + 4015c: 00000000 .word 0x00000000 + +00040160 <.LC14>: + 40160: 3a444150 .word 0x3a444150 + 40164: 00000020 .word 0x00000020 + +00040168 <.LC15>: + 40168: 61746164 .word 0x61746164 + 4016c: 0000203a .word 0x0000203a + +00040170 <.LC16>: + 40170: 64646150 .word 0x64646150 + 40174: 3a676e69 .word 0x3a676e69 + 40178: 00000020 .word 0x00000020 + +0004017c <.LC17>: + 4017c: 74736420 .word 0x74736420 + 40180: 73656420 .word 0x73656420 + 40184: 203a2063 .word 0x203a2063 + 40188: 00000000 .word 0x00000000 + +0004018c <.LC18>: + 4018c: 52435b0d .word 0x52435b0d + 40190: 45205059 .word 0x45205059 + 40194: 255d7272 .word 0x255d7272 + 40198: 3a292873 .word 0x3a292873 + 4019c: 69615720 .word 0x69615720 + 401a0: 69542074 .word 0x69542074 + 401a4: 756f656d .word 0x756f656d + 401a8: 52202e74 .word 0x52202e74 + 401ac: 5f444145 .word 0x5f444145 + 401b0: 334d454d .word 0x334d454d + 401b4: 50492832 .word 0x50492832 + 401b8: 52534353 .word 0x52534353 + 401bc: 78303d29 .word 0x78303d29 + 401c0: 78383025 .word 0x78383025 + 401c4: 000a0a2e .word 0x000a0a2e + +000401c8 <.LC19>: + 401c8: 52435b0d .word 0x52435b0d + 401cc: 45205059 .word 0x45205059 + 401d0: 255d7272 .word 0x255d7272 + 401d4: 3a292873 .word 0x3a292873 + 401d8: 53504920 .word 0x53504920 + 401dc: 4c44535f .word 0x4c44535f + 401e0: 20504945 .word 0x20504945 + 401e4: 4920726f .word 0x4920726f + 401e8: 445f5350 .word 0x445f5350 + 401ec: 49464241 .word 0x49464241 + 401f0: 20736920 .word 0x20736920 + 401f4: 202e4e4f .word 0x202e4e4f + 401f8: 44414552 .word 0x44414552 + 401fc: 4d454d5f .word 0x4d454d5f + 40200: 49283233 .word 0x49283233 + 40204: 53435350 .word 0x53435350 + 40208: 303d2952 .word 0x303d2952 + 4020c: 38302578 .word 0x38302578 + 40210: 0a0a2e78 .word 0x0a0a2e78 + 40214: 00000000 .word 0x00000000 + +00040218 <.LC20>: + 40218: 52435b0d .word 0x52435b0d + 4021c: 45205059 .word 0x45205059 + 40220: 255d7272 .word 0x255d7272 + 40224: 3a292873 .word 0x3a292873 + 40228: 6e776f20 .word 0x6e776f20 + 4022c: 74696220 .word 0x74696220 + 40230: 72726520 .word 0x72726520 + 40234: 5220726f .word 0x5220726f + 40238: 5f444145 .word 0x5f444145 + 4023c: 334d454d .word 0x334d454d + 40240: 50492832 .word 0x50492832 + 40244: 52534353 .word 0x52534353 + 40248: 78303d29 .word 0x78303d29 + 4024c: 78383025 .word 0x78383025 + 40250: 000a0a2e .word 0x000a0a2e + +00040254 <.LC21>: + 40254: 52435b0d .word 0x52435b0d + 40258: 45205059 .word 0x45205059 + 4025c: 255d7272 .word 0x255d7272 + 40260: 3a292873 .word 0x3a292873 + 40264: 53504920 .word 0x53504920 + 40268: 45206365 .word 0x45206365 + 4026c: 6e69676e .word 0x6e69676e + 40270: 696b2065 .word 0x696b2065 + 40274: 6f206b63 .word 0x6f206b63 + 40278: 46206666 .word 0x46206666 + 4027c: 214c4941 .word 0x214c4941 + 40280: 000a0a20 .word 0x000a0a20 + +00040284 <.LC22>: + 40284: 73655270 .word 0x73655270 + 40288: 3a746c75 .word 0x3a746c75 + 4028c: 00000020 .word 0x00000020 + +00040290 <.LC0>: + 40290: 53535b0d .word 0x53535b0d + 40294: 49202049 .word 0x49202049 + 40298: 205d666e .word 0x205d666e + 4029c: 1b202020 .word 0x1b202020 + 402a0: 6d32335b .word 0x6d32335b + 402a4: 536c6148 .word 0x536c6148 + 402a8: 69506973 .word 0x69506973 + 402ac: 78756d6e .word 0x78756d6e + 402b0: 62616e45 .word 0x62616e45 + 402b4: 7452656c .word 0x7452656c + 402b8: 3931386c .word 0x3931386c + 402bc: 29286135 .word 0x29286135 + 402c0: 305b1b0a .word 0x305b1b0a + 402c4: 0000006d .word 0x0000006d + +000402c8 <.LC1>: + 402c8: 53535b0d .word 0x53535b0d + 402cc: 49202049 .word 0x49202049 + 402d0: 205d666e .word 0x205d666e + 402d4: 5b202020 .word 0x5b202020 + 402d8: 53205d31 .word 0x53205d31 + 402dc: 64254953 .word 0x64254953 + 402e0: 47455220 .word 0x47455220 + 402e4: 4953535f .word 0x4953535f + 402e8: 58554d5f .word 0x58554d5f + 402ec: 5254435f .word 0x5254435f + 402f0: 5825284c .word 0x5825284c + 402f4: 203d2029 .word 0x203d2029 + 402f8: 000a5825 .word 0x000a5825 + +000402fc <.LC2>: + 402fc: 53535b0d .word 0x53535b0d + 40300: 45202049 .word 0x45202049 + 40304: 495d7272 .word 0x495d7272 + 40308: 6c61766e .word 0x6c61766e + 4030c: 53206469 .word 0x53206469 + 40310: 49204953 .word 0x49204953 + 40314: 7865646e .word 0x7865646e + 40318: 000a2120 .word 0x000a2120 + +0004031c <.LC3>: + 4031c: 53535b0d .word 0x53535b0d + 40320: 49202049 .word 0x49202049 + 40324: 205d666e .word 0x205d666e + 40328: 5b202020 .word 0x5b202020 + 4032c: 53205d32 .word 0x53205d32 + 40330: 64254953 .word 0x64254953 + 40334: 47455220 .word 0x47455220 + 40338: 4953535f .word 0x4953535f + 4033c: 58554d5f .word 0x58554d5f + 40340: 5254435f .word 0x5254435f + 40344: 5825284c .word 0x5825284c + 40348: 203d2029 .word 0x203d2029 + 4034c: 000a5825 .word 0x000a5825 + +00040350 <.LC4>: + 40350: 53535b0d .word 0x53535b0d + 40354: 49202049 .word 0x49202049 + 40358: 205d666e .word 0x205d666e + 4035c: 1b202020 .word 0x1b202020 + 40360: 6d32335b .word 0x6d32335b + 40364: 536c6148 .word 0x536c6148 + 40368: 6e456973 .word 0x6e456973 + 4036c: 656c6261 .word 0x656c6261 + 40370: 386c7452 .word 0x386c7452 + 40374: 61353931 .word 0x61353931 + 40378: 1b0a2928 .word 0x1b0a2928 + 4037c: 006d305b .word 0x006d305b + +00040380 <.LC5>: + 40380: 53535b0d .word 0x53535b0d + 40384: 49202049 .word 0x49202049 + 40388: 205d666e .word 0x205d666e + 4038c: 5b202020 .word 0x5b202020 + 40390: 53205d31 .word 0x53205d31 + 40394: 64254953 .word 0x64254953 + 40398: 47455220 .word 0x47455220 + 4039c: 5f57445f .word 0x5f57445f + 403a0: 5f495353 .word 0x5f495353 + 403a4: 45495353 .word 0x45495353 + 403a8: 2528524e .word 0x2528524e + 403ac: 3d202958 .word 0x3d202958 + 403b0: 0a582520 .word 0x0a582520 + 403b4: 00000000 .word 0x00000000 + +000403b8 <.LC6>: + 403b8: 53535b0d .word 0x53535b0d + 403bc: 49202049 .word 0x49202049 + 403c0: 205d666e .word 0x205d666e + 403c4: 5b202020 .word 0x5b202020 + 403c8: 53205d32 .word 0x53205d32 + 403cc: 64254953 .word 0x64254953 + 403d0: 47455220 .word 0x47455220 + 403d4: 5f57445f .word 0x5f57445f + 403d8: 5f495353 .word 0x5f495353 + 403dc: 45495353 .word 0x45495353 + 403e0: 2528524e .word 0x2528524e + 403e4: 3d202958 .word 0x3d202958 + 403e8: 0a582520 .word 0x0a582520 + 403ec: 00000000 .word 0x00000000 + +000403f0 <.LC7>: + 403f0: 53535b0d .word 0x53535b0d + 403f4: 49202049 .word 0x49202049 + 403f8: 205d666e .word 0x205d666e + 403fc: 1b202020 .word 0x1b202020 + 40400: 6d32335b .word 0x6d32335b + 40404: 536c6148 .word 0x536c6148 + 40408: 69446973 .word 0x69446973 + 4040c: 6c626173 .word 0x6c626173 + 40410: 6c745265 .word 0x6c745265 + 40414: 35393138 .word 0x35393138 + 40418: 0a292861 .word 0x0a292861 + 4041c: 6d305b1b .word 0x6d305b1b + 40420: 00000000 .word 0x00000000 + +00040424 <.LC8>: + 40424: 53535b0d .word 0x53535b0d + 40428: 49202049 .word 0x49202049 + 4042c: 205d666e .word 0x205d666e + 40430: 1b202020 .word 0x1b202020 + 40434: 6d32335b .word 0x6d32335b + 40438: 536c6148 .word 0x536c6148 + 4043c: 6f4c6973 .word 0x6f4c6973 + 40440: 65536461 .word 0x65536461 + 40444: 6e697474 .word 0x6e697474 + 40448: 6c745267 .word 0x6c745267 + 4044c: 35393138 .word 0x35393138 + 40450: 0a292861 .word 0x0a292861 + 40454: 6d305b1b .word 0x6d305b1b + 40458: 00000000 .word 0x00000000 + +0004045c <.LC9>: + 4045c: 53535b0d .word 0x53535b0d + 40460: 49202049 .word 0x49202049 + 40464: 205d666e .word 0x205d666e + 40468: 4c202020 .word 0x4c202020 + 4046c: 2064616f .word 0x2064616f + 40470: 25495353 .word 0x25495353 + 40474: 65442064 .word 0x65442064 + 40478: 6c756166 .word 0x6c756166 + 4047c: 65532074 .word 0x65532074 + 40480: 6e697474 .word 0x6e697474 + 40484: 0a3a7367 .word 0x0a3a7367 + 40488: 00000000 .word 0x00000000 + +0004048c <.LC10>: + 4048c: 53535b0d .word 0x53535b0d + 40490: 49202049 .word 0x49202049 + 40494: 205d666e .word 0x205d666e + 40498: 20202020 .word 0x20202020 + 4049c: 6f437852 .word 0x6f437852 + 404a0: 6143706d .word 0x6143706d + 404a4: 61626c6c .word 0x61626c6c + 404a8: 20206b63 .word 0x20206b63 + 404ac: 203d2020 .word 0x203d2020 + 404b0: 000a5825 .word 0x000a5825 + +000404b4 <.LC11>: + 404b4: 53535b0d .word 0x53535b0d + 404b8: 49202049 .word 0x49202049 + 404bc: 205d666e .word 0x205d666e + 404c0: 20202020 .word 0x20202020 + 404c4: 6f437852 .word 0x6f437852 + 404c8: 6243706d .word 0x6243706d + 404cc: 61726150 .word 0x61726150 + 404d0: 20202020 .word 0x20202020 + 404d4: 203d2020 .word 0x203d2020 + 404d8: 000a5825 .word 0x000a5825 + +000404dc <.LC12>: + 404dc: 53535b0d .word 0x53535b0d + 404e0: 49202049 .word 0x49202049 + 404e4: 205d666e .word 0x205d666e + 404e8: 20202020 .word 0x20202020 + 404ec: 61447852 .word 0x61447852 + 404f0: 20206174 .word 0x20206174 + 404f4: 20202020 .word 0x20202020 + 404f8: 20202020 .word 0x20202020 + 404fc: 203d2020 .word 0x203d2020 + 40500: 000a5825 .word 0x000a5825 + +00040504 <.LC13>: + 40504: 53535b0d .word 0x53535b0d + 40508: 49202049 .word 0x49202049 + 4050c: 205d666e .word 0x205d666e + 40510: 20202020 .word 0x20202020 + 40514: 6f437854 .word 0x6f437854 + 40518: 6143706d .word 0x6143706d + 4051c: 61626c6c .word 0x61626c6c + 40520: 20206b63 .word 0x20206b63 + 40524: 203d2020 .word 0x203d2020 + 40528: 000a5825 .word 0x000a5825 + +0004052c <.LC14>: + 4052c: 53535b0d .word 0x53535b0d + 40530: 49202049 .word 0x49202049 + 40534: 205d666e .word 0x205d666e + 40538: 20202020 .word 0x20202020 + 4053c: 6f437854 .word 0x6f437854 + 40540: 6243706d .word 0x6243706d + 40544: 61726150 .word 0x61726150 + 40548: 20202020 .word 0x20202020 + 4054c: 203d2020 .word 0x203d2020 + 40550: 000a5825 .word 0x000a5825 + +00040554 <.LC15>: + 40554: 53535b0d .word 0x53535b0d + 40558: 49202049 .word 0x49202049 + 4055c: 205d666e .word 0x205d666e + 40560: 20202020 .word 0x20202020 + 40564: 61447854 .word 0x61447854 + 40568: 20206174 .word 0x20206174 + 4056c: 20202020 .word 0x20202020 + 40570: 20202020 .word 0x20202020 + 40574: 203d2020 .word 0x203d2020 + 40578: 000a5825 .word 0x000a5825 + +0004057c <.LC16>: + 4057c: 53535b0d .word 0x53535b0d + 40580: 49202049 .word 0x49202049 + 40584: 205d666e .word 0x205d666e + 40588: 20202020 .word 0x20202020 + 4058c: 52616d44 .word 0x52616d44 + 40590: 74614478 .word 0x74614478 + 40594: 76654c61 .word 0x76654c61 + 40598: 20206c65 .word 0x20206c65 + 4059c: 203d2020 .word 0x203d2020 + 405a0: 000a6425 .word 0x000a6425 + +000405a4 <.LC17>: + 405a4: 53535b0d .word 0x53535b0d + 405a8: 49202049 .word 0x49202049 + 405ac: 205d666e .word 0x205d666e + 405b0: 20202020 .word 0x20202020 + 405b4: 54616d44 .word 0x54616d44 + 405b8: 74614478 .word 0x74614478 + 405bc: 76654c61 .word 0x76654c61 + 405c0: 20206c65 .word 0x20206c65 + 405c4: 203d2020 .word 0x203d2020 + 405c8: 000a6425 .word 0x000a6425 + +000405cc <.LC18>: + 405cc: 53535b0d .word 0x53535b0d + 405d0: 49202049 .word 0x49202049 + 405d4: 205d666e .word 0x205d666e + 405d8: 20202020 .word 0x20202020 + 405dc: 65746e49 .word 0x65746e49 + 405e0: 70757272 .word 0x70757272 + 405e4: 69725074 .word 0x69725074 + 405e8: 7469726f .word 0x7469726f + 405ec: 203d2079 .word 0x203d2079 + 405f0: 000a6425 .word 0x000a6425 + +000405f4 <.LC19>: + 405f4: 53535b0d .word 0x53535b0d + 405f8: 49202049 .word 0x49202049 + 405fc: 205d666e .word 0x205d666e + 40600: 20202020 .word 0x20202020 + 40604: 654c7852 .word 0x654c7852 + 40608: 6874676e .word 0x6874676e + 4060c: 20202020 .word 0x20202020 + 40610: 20202020 .word 0x20202020 + 40614: 203d2020 .word 0x203d2020 + 40618: 000a6425 .word 0x000a6425 + +0004061c <.LC20>: + 4061c: 53535b0d .word 0x53535b0d + 40620: 49202049 .word 0x49202049 + 40624: 205d666e .word 0x205d666e + 40628: 20202020 .word 0x20202020 + 4062c: 654c7852 .word 0x654c7852 + 40630: 6874676e .word 0x6874676e + 40634: 616d6552 .word 0x616d6552 + 40638: 65646e69 .word 0x65646e69 + 4063c: 203d2072 .word 0x203d2072 + 40640: 000a6425 .word 0x000a6425 + +00040644 <.LC21>: + 40644: 53535b0d .word 0x53535b0d + 40648: 49202049 .word 0x49202049 + 4064c: 205d666e .word 0x205d666e + 40650: 20202020 .word 0x20202020 + 40654: 68547852 .word 0x68547852 + 40658: 68736572 .word 0x68736572 + 4065c: 4c646c6f .word 0x4c646c6f + 40660: 6c657665 .word 0x6c657665 + 40664: 203d2020 .word 0x203d2020 + 40668: 000a6425 .word 0x000a6425 + +0004066c <.LC22>: + 4066c: 53535b0d .word 0x53535b0d + 40670: 49202049 .word 0x49202049 + 40674: 205d666e .word 0x205d666e + 40678: 20202020 .word 0x20202020 + 4067c: 654c7854 .word 0x654c7854 + 40680: 6874676e .word 0x6874676e + 40684: 20202020 .word 0x20202020 + 40688: 20202020 .word 0x20202020 + 4068c: 203d2020 .word 0x203d2020 + 40690: 000a6425 .word 0x000a6425 + +00040694 <.LC23>: + 40694: 53535b0d .word 0x53535b0d + 40698: 49202049 .word 0x49202049 + 4069c: 205d666e .word 0x205d666e + 406a0: 20202020 .word 0x20202020 + 406a4: 68547854 .word 0x68547854 + 406a8: 68736572 .word 0x68736572 + 406ac: 4c646c6f .word 0x4c646c6f + 406b0: 6c657665 .word 0x6c657665 + 406b4: 203d2020 .word 0x203d2020 + 406b8: 000a6425 .word 0x000a6425 + +000406bc <.LC24>: + 406bc: 53535b0d .word 0x53535b0d + 406c0: 49202049 .word 0x49202049 + 406c4: 205d666e .word 0x205d666e + 406c8: 20202020 .word 0x20202020 + 406cc: 746e6f43 .word 0x746e6f43 + 406d0: 466c6f72 .word 0x466c6f72 + 406d4: 656d6172 .word 0x656d6172 + 406d8: 657a6953 .word 0x657a6953 + 406dc: 203d2020 .word 0x203d2020 + 406e0: 000a6425 .word 0x000a6425 + +000406e4 <.LC25>: + 406e4: 53535b0d .word 0x53535b0d + 406e8: 49202049 .word 0x49202049 + 406ec: 205d666e .word 0x205d666e + 406f0: 20202020 .word 0x20202020 + 406f4: 61746144 .word 0x61746144 + 406f8: 6d617246 .word 0x6d617246 + 406fc: 726f4665 .word 0x726f4665 + 40700: 2074616d .word 0x2074616d + 40704: 203d2020 .word 0x203d2020 + 40708: 000a6425 .word 0x000a6425 + +0004070c <.LC26>: + 4070c: 53535b0d .word 0x53535b0d + 40710: 49202049 .word 0x49202049 + 40714: 205d666e .word 0x205d666e + 40718: 20202020 .word 0x20202020 + 4071c: 61746144 .word 0x61746144 + 40720: 6d617246 .word 0x6d617246 + 40724: 7a695365 .word 0x7a695365 + 40728: 20202065 .word 0x20202065 + 4072c: 203d2020 .word 0x203d2020 + 40730: 000a6425 .word 0x000a6425 + +00040734 <.LC27>: + 40734: 53535b0d .word 0x53535b0d + 40738: 49202049 .word 0x49202049 + 4073c: 205d666e .word 0x205d666e + 40740: 20202020 .word 0x20202020 + 40744: 43616d44 .word 0x43616d44 + 40748: 72746e6f .word 0x72746e6f + 4074c: 20206c6f .word 0x20206c6f + 40750: 20202020 .word 0x20202020 + 40754: 203d2020 .word 0x203d2020 + 40758: 000a6425 .word 0x000a6425 + +0004075c <.LC28>: + 4075c: 53535b0d .word 0x53535b0d + 40760: 49202049 .word 0x49202049 + 40764: 205d666e .word 0x205d666e + 40768: 20202020 .word 0x20202020 + 4076c: 65746e49 .word 0x65746e49 + 40770: 70757272 .word 0x70757272 + 40774: 73614d74 .word 0x73614d74 + 40778: 2020206b .word 0x2020206b + 4077c: 203d2020 .word 0x203d2020 + 40780: 000a6425 .word 0x000a6425 + +00040784 <.LC29>: + 40784: 53535b0d .word 0x53535b0d + 40788: 49202049 .word 0x49202049 + 4078c: 205d666e .word 0x205d666e + 40790: 20202020 .word 0x20202020 + 40794: 6b6c6353 .word 0x6b6c6353 + 40798: 73616850 .word 0x73616850 + 4079c: 20202065 .word 0x20202065 + 407a0: 20202020 .word 0x20202020 + 407a4: 203d2020 .word 0x203d2020 + 407a8: 000a6425 .word 0x000a6425 + +000407ac <.LC30>: + 407ac: 53535b0d .word 0x53535b0d + 407b0: 49202049 .word 0x49202049 + 407b4: 205d666e .word 0x205d666e + 407b8: 20202020 .word 0x20202020 + 407bc: 6b6c6353 .word 0x6b6c6353 + 407c0: 616c6f50 .word 0x616c6f50 + 407c4: 79746972 .word 0x79746972 + 407c8: 20202020 .word 0x20202020 + 407cc: 203d2020 .word 0x203d2020 + 407d0: 000a6425 .word 0x000a6425 + +000407d4 <.LC31>: + 407d4: 53535b0d .word 0x53535b0d + 407d8: 49202049 .word 0x49202049 + 407dc: 205d666e .word 0x205d666e + 407e0: 20202020 .word 0x20202020 + 407e4: 6e617254 .word 0x6e617254 + 407e8: 72656673 .word 0x72656673 + 407ec: 65646f4d .word 0x65646f4d + 407f0: 20202020 .word 0x20202020 + 407f4: 203d2020 .word 0x203d2020 + 407f8: 000a6425 .word 0x000a6425 + +000407fc <.LC32>: + 407fc: 53535b0d .word 0x53535b0d + 40800: 49202049 .word 0x49202049 + 40804: 205d666e .word 0x205d666e + 40808: 20202020 .word 0x20202020 + 4080c: 6e617254 .word 0x6e617254 + 40810: 72656673 .word 0x72656673 + 40814: 6863654d .word 0x6863654d + 40818: 73696e61 .word 0x73696e61 + 4081c: 203d206d .word 0x203d206d + 40820: 000a6425 .word 0x000a6425 + +00040824 <.LC33>: + 40824: 53535b0d .word 0x53535b0d + 40828: 49202049 .word 0x49202049 + 4082c: 205d666e .word 0x205d666e + 40830: 20202020 .word 0x20202020 + 40834: 636f6c43 .word 0x636f6c43 + 40838: 7669446b .word 0x7669446b + 4083c: 72656469 .word 0x72656469 + 40840: 20202020 .word 0x20202020 + 40844: 203d2020 .word 0x203d2020 + 40848: 000a6425 .word 0x000a6425 + +0004084c <.LC34>: + 4084c: 53535b0d .word 0x53535b0d + 40850: 49202049 .word 0x49202049 + 40854: 205d666e .word 0x205d666e + 40858: 20202020 .word 0x20202020 + 4085c: 61746144 .word 0x61746144 + 40860: 6d617246 .word 0x6d617246 + 40864: 6d754e65 .word 0x6d754e65 + 40868: 20726562 .word 0x20726562 + 4086c: 203d2020 .word 0x203d2020 + 40870: 000a6425 .word 0x000a6425 + +00040874 <.LC35>: + 40874: 53535b0d .word 0x53535b0d + 40878: 49202049 .word 0x49202049 + 4087c: 205d666e .word 0x205d666e + 40880: 20202020 .word 0x20202020 + 40884: 76616c53 .word 0x76616c53 + 40888: 6c655365 .word 0x6c655365 + 4088c: 45746365 .word 0x45746365 + 40890: 6c62616e .word 0x6c62616e + 40894: 203d2065 .word 0x203d2065 + 40898: 000a6425 .word 0x000a6425 + +0004089c <.LC36>: + 4089c: 53535b0d .word 0x53535b0d + 408a0: 49202049 .word 0x49202049 + 408a4: 205d666e .word 0x205d666e + 408a8: 20202020 .word 0x20202020 + 408ac: 76616c53 .word 0x76616c53 + 408b0: 74754f65 .word 0x74754f65 + 408b4: 45747570 .word 0x45747570 + 408b8: 6c62616e .word 0x6c62616e + 408bc: 203d2065 .word 0x203d2065 + 408c0: 000a6425 .word 0x000a6425 + +000408c4 <.LC37>: + 408c4: 53535b0d .word 0x53535b0d + 408c8: 49202049 .word 0x49202049 + 408cc: 205d666e .word 0x205d666e + 408d0: 20202020 .word 0x20202020 + 408d4: 7263694d .word 0x7263694d + 408d8: 7269776f .word 0x7269776f + 408dc: 72694465 .word 0x72694465 + 408e0: 69746365 .word 0x69746365 + 408e4: 20206e6f .word 0x20206e6f + 408e8: 203d2020 .word 0x203d2020 + 408ec: 000a6425 .word 0x000a6425 + +000408f0 <.LC38>: + 408f0: 53535b0d .word 0x53535b0d + 408f4: 49202049 .word 0x49202049 + 408f8: 205d666e .word 0x205d666e + 408fc: 20202020 .word 0x20202020 + 40900: 7263694d .word 0x7263694d + 40904: 7269776f .word 0x7269776f + 40908: 61725465 .word 0x61725465 + 4090c: 6566736e .word 0x6566736e + 40910: 646f4d72 .word 0x646f4d72 + 40914: 203d2065 .word 0x203d2065 + 40918: 000a6425 .word 0x000a6425 + +0004091c <.LC39>: + 4091c: 53535b0d .word 0x53535b0d + 40920: 49202049 .word 0x49202049 + 40924: 205d666e .word 0x205d666e + 40928: 20202020 .word 0x20202020 + 4092c: 7263694d .word 0x7263694d + 40930: 7269776f .word 0x7269776f + 40934: 6e614865 .word 0x6e614865 + 40938: 61687364 .word 0x61687364 + 4093c: 676e696b .word 0x676e696b + 40940: 203d2020 .word 0x203d2020 + 40944: 000a6425 .word 0x000a6425 + +00040948 <.LC40>: + 40948: 53535b0d .word 0x53535b0d + 4094c: 49202049 .word 0x49202049 + 40950: 205d666e .word 0x205d666e + 40954: 1b202020 .word 0x1b202020 + 40958: 6d32335b .word 0x6d32335b + 4095c: 536c6148 .word 0x536c6148 + 40960: 65536973 .word 0x65536973 + 40964: 746e4974 .word 0x746e4974 + 40968: 75727265 .word 0x75727265 + 4096c: 614d7470 .word 0x614d7470 + 40970: 74526b73 .word 0x74526b73 + 40974: 3931386c .word 0x3931386c + 40978: 29286135 .word 0x29286135 + 4097c: 305b1b0a .word 0x305b1b0a + 40980: 0000006d .word 0x0000006d + +00040984 <.LC41>: + 40984: 53535b0d .word 0x53535b0d + 40988: 49202049 .word 0x49202049 + 4098c: 205d666e .word 0x205d666e + 40990: 5b202020 .word 0x5b202020 + 40994: 53205d31 .word 0x53205d31 + 40998: 53207465 .word 0x53207465 + 4099c: 64254953 .word 0x64254953 + 409a0: 524d4920 .word 0x524d4920 + 409a4: 6c617620 .word 0x6c617620 + 409a8: 203a6575 .word 0x203a6575 + 409ac: 000a5825 .word 0x000a5825 + +000409b0 <.LC42>: + 409b0: 53535b0d .word 0x53535b0d + 409b4: 49202049 .word 0x49202049 + 409b8: 205d666e .word 0x205d666e + 409bc: 5b202020 .word 0x5b202020 + 409c0: 53205d32 .word 0x53205d32 + 409c4: 64254953 .word 0x64254953 + 409c8: 47455220 .word 0x47455220 + 409cc: 5f57445f .word 0x5f57445f + 409d0: 5f495353 .word 0x5f495353 + 409d4: 28524d49 .word 0x28524d49 + 409d8: 20295825 .word 0x20295825 + 409dc: 5825203d .word 0x5825203d + 409e0: 0000000a .word 0x0000000a + +000409e4 <.LC43>: + 409e4: 53535b0d .word 0x53535b0d + 409e8: 49202049 .word 0x49202049 + 409ec: 205d666e .word 0x205d666e + 409f0: 1b202020 .word 0x1b202020 + 409f4: 6d32335b .word 0x6d32335b + 409f8: 536c6148 .word 0x536c6148 + 409fc: 65476973 .word 0x65476973 + 40a00: 746e4974 .word 0x746e4974 + 40a04: 75727265 .word 0x75727265 + 40a08: 614d7470 .word 0x614d7470 + 40a0c: 74526b73 .word 0x74526b73 + 40a10: 3931386c .word 0x3931386c + 40a14: 29286135 .word 0x29286135 + 40a18: 305b1b0a .word 0x305b1b0a + 40a1c: 0000006d .word 0x0000006d + +00040a20 <.LC44>: + 40a20: 53535b0d .word 0x53535b0d + 40a24: 49202049 .word 0x49202049 + 40a28: 205d666e .word 0x205d666e + 40a2c: 53202020 .word 0x53202020 + 40a30: 64254953 .word 0x64254953 + 40a34: 524d4920 .word 0x524d4920 + 40a38: 6c617620 .word 0x6c617620 + 40a3c: 203a6575 .word 0x203a6575 + 40a40: 000a5825 .word 0x000a5825 + +00040a44 <.LC45>: + 40a44: 53535b0d .word 0x53535b0d + 40a48: 49202049 .word 0x49202049 + 40a4c: 205d666e .word 0x205d666e + 40a50: 1b202020 .word 0x1b202020 + 40a54: 6d32335b .word 0x6d32335b + 40a58: 536c6148 .word 0x536c6148 + 40a5c: 65536973 .word 0x65536973 + 40a60: 6c635374 .word 0x6c635374 + 40a64: 6c6f506b .word 0x6c6f506b + 40a68: 74697261 .word 0x74697261 + 40a6c: 6c745279 .word 0x6c745279 + 40a70: 35393138 .word 0x35393138 + 40a74: 0a292861 .word 0x0a292861 + 40a78: 6d305b1b .word 0x6d305b1b + 40a7c: 00000000 .word 0x00000000 + +00040a80 <.LC46>: + 40a80: 53535b0d .word 0x53535b0d + 40a84: 49202049 .word 0x49202049 + 40a88: 205d666e .word 0x205d666e + 40a8c: 5b202020 .word 0x5b202020 + 40a90: 53205d31 .word 0x53205d31 + 40a94: 53207465 .word 0x53207465 + 40a98: 64254953 .word 0x64254953 + 40a9c: 6c635320 .word 0x6c635320 + 40aa0: 6c6f506b .word 0x6c6f506b + 40aa4: 74697261 .word 0x74697261 + 40aa8: 61562079 .word 0x61562079 + 40aac: 3a65756c .word 0x3a65756c + 40ab0: 0a582520 .word 0x0a582520 + 40ab4: 00000000 .word 0x00000000 + +00040ab8 <.LC47>: + 40ab8: 53535b0d .word 0x53535b0d + 40abc: 49202049 .word 0x49202049 + 40ac0: 205d666e .word 0x205d666e + 40ac4: 5b202020 .word 0x5b202020 + 40ac8: 53205d32 .word 0x53205d32 + 40acc: 64254953 .word 0x64254953 + 40ad0: 47455220 .word 0x47455220 + 40ad4: 5f57445f .word 0x5f57445f + 40ad8: 5f495353 .word 0x5f495353 + 40adc: 4c525443 .word 0x4c525443 + 40ae0: 25283052 .word 0x25283052 + 40ae4: 3d202958 .word 0x3d202958 + 40ae8: 0a582520 .word 0x0a582520 + 40aec: 00000000 .word 0x00000000 + +00040af0 <.LC48>: + 40af0: 53535b0d .word 0x53535b0d + 40af4: 49202049 .word 0x49202049 + 40af8: 205d666e .word 0x205d666e + 40afc: 1b202020 .word 0x1b202020 + 40b00: 6d32335b .word 0x6d32335b + 40b04: 536c6148 .word 0x536c6148 + 40b08: 65536973 .word 0x65536973 + 40b0c: 6c635374 .word 0x6c635374 + 40b10: 6168506b .word 0x6168506b + 40b14: 74526573 .word 0x74526573 + 40b18: 3931386c .word 0x3931386c + 40b1c: 29286135 .word 0x29286135 + 40b20: 305b1b0a .word 0x305b1b0a + 40b24: 0000006d .word 0x0000006d + +00040b28 <.LC49>: + 40b28: 53535b0d .word 0x53535b0d + 40b2c: 49202049 .word 0x49202049 + 40b30: 205d666e .word 0x205d666e + 40b34: 5b202020 .word 0x5b202020 + 40b38: 53205d31 .word 0x53205d31 + 40b3c: 53207465 .word 0x53207465 + 40b40: 64254953 .word 0x64254953 + 40b44: 6c635320 .word 0x6c635320 + 40b48: 6168506b .word 0x6168506b + 40b4c: 56206573 .word 0x56206573 + 40b50: 65756c61 .word 0x65756c61 + 40b54: 5825203a .word 0x5825203a + 40b58: 0000000a .word 0x0000000a + +00040b5c <.LC50>: + 40b5c: 53535b0d .word 0x53535b0d + 40b60: 49202049 .word 0x49202049 + 40b64: 205d666e .word 0x205d666e + 40b68: 1b202020 .word 0x1b202020 + 40b6c: 6d32335b .word 0x6d32335b + 40b70: 536c6148 .word 0x536c6148 + 40b74: 72576973 .word 0x72576973 + 40b78: 52657469 .word 0x52657469 + 40b7c: 31386c74 .word 0x31386c74 + 40b80: 28613539 .word 0x28613539 + 40b84: 5b1b0a29 .word 0x5b1b0a29 + 40b88: 00006d30 .word 0x00006d30 + +00040b8c <.LC51>: + 40b8c: 53535b0d .word 0x53535b0d + 40b90: 49202049 .word 0x49202049 + 40b94: 205d666e .word 0x205d666e + 40b98: 53202020 .word 0x53202020 + 40b9c: 64254953 .word 0x64254953 + 40ba0: 69725720 .word 0x69725720 + 40ba4: 203a6574 .word 0x203a6574 + 40ba8: 58343025 .word 0x58343025 + 40bac: 0000000a .word 0x0000000a + +00040bb0 <.LC52>: + 40bb0: 53535b0d .word 0x53535b0d + 40bb4: 49202049 .word 0x49202049 + 40bb8: 205d666e .word 0x205d666e + 40bbc: 1b202020 .word 0x1b202020 + 40bc0: 6d32335b .word 0x6d32335b + 40bc4: 536c6148 .word 0x536c6148 + 40bc8: 65536973 .word 0x65536973 + 40bcc: 76654474 .word 0x76654474 + 40bd0: 52656369 .word 0x52656369 + 40bd4: 52656c6f .word 0x52656c6f + 40bd8: 31386c74 .word 0x31386c74 + 40bdc: 28613539 .word 0x28613539 + 40be0: 5b1b0a29 .word 0x5b1b0a29 + 40be4: 00006d30 .word 0x00006d30 + +00040be8 <.LC53>: + 40be8: 53535b0d .word 0x53535b0d + 40bec: 49202049 .word 0x49202049 + 40bf0: 205d666e .word 0x205d666e + 40bf4: 1b202020 .word 0x1b202020 + 40bf8: 6d32335b .word 0x6d32335b + 40bfc: 536c6148 .word 0x536c6148 + 40c00: 65536973 .word 0x65536973 + 40c04: 46785274 .word 0x46785274 + 40c08: 546f6669 .word 0x546f6669 + 40c0c: 73657268 .word 0x73657268 + 40c10: 646c6f68 .word 0x646c6f68 + 40c14: 6576654c .word 0x6576654c + 40c18: 6c74526c .word 0x6c74526c + 40c1c: 35393138 .word 0x35393138 + 40c20: 0a292861 .word 0x0a292861 + 40c24: 6d305b1b .word 0x6d305b1b + 40c28: 00000000 .word 0x00000000 + +00040c2c <.LC54>: + 40c2c: 53535b0d .word 0x53535b0d + 40c30: 49202049 .word 0x49202049 + 40c34: 205d666e .word 0x205d666e + 40c38: 53202020 .word 0x53202020 + 40c3c: 53207465 .word 0x53207465 + 40c40: 64254953 .word 0x64254953 + 40c44: 20785220 .word 0x20785220 + 40c48: 4f464946 .word 0x4f464946 + 40c4c: 72685420 .word 0x72685420 + 40c50: 6f687365 .word 0x6f687365 + 40c54: 4c20646c .word 0x4c20646c + 40c58: 6c657665 .word 0x6c657665 + 40c5c: 6425203a .word 0x6425203a + 40c60: 0000000a .word 0x0000000a + +00040c64 <.LC55>: + 40c64: 53535b0d .word 0x53535b0d + 40c68: 49202049 .word 0x49202049 + 40c6c: 205d666e .word 0x205d666e + 40c70: 1b202020 .word 0x1b202020 + 40c74: 6d32335b .word 0x6d32335b + 40c78: 536c6148 .word 0x536c6148 + 40c7c: 65536973 .word 0x65536973 + 40c80: 46785474 .word 0x46785474 + 40c84: 546f6669 .word 0x546f6669 + 40c88: 73657268 .word 0x73657268 + 40c8c: 646c6f68 .word 0x646c6f68 + 40c90: 6576654c .word 0x6576654c + 40c94: 6c74526c .word 0x6c74526c + 40c98: 35393138 .word 0x35393138 + 40c9c: 0a292861 .word 0x0a292861 + 40ca0: 6d305b1b .word 0x6d305b1b + 40ca4: 00000000 .word 0x00000000 + +00040ca8 <.LC56>: + 40ca8: 53535b0d .word 0x53535b0d + 40cac: 49202049 .word 0x49202049 + 40cb0: 205d666e .word 0x205d666e + 40cb4: 53202020 .word 0x53202020 + 40cb8: 53207465 .word 0x53207465 + 40cbc: 64254953 .word 0x64254953 + 40cc0: 20785420 .word 0x20785420 + 40cc4: 4f464946 .word 0x4f464946 + 40cc8: 72685420 .word 0x72685420 + 40ccc: 6f687365 .word 0x6f687365 + 40cd0: 4c20646c .word 0x4c20646c + 40cd4: 6c657665 .word 0x6c657665 + 40cd8: 6425203a .word 0x6425203a + 40cdc: 0000000a .word 0x0000000a + +00040ce0 <.LC57>: + 40ce0: 53535b0d .word 0x53535b0d + 40ce4: 49202049 .word 0x49202049 + 40ce8: 205d666e .word 0x205d666e + 40cec: 1b202020 .word 0x1b202020 + 40cf0: 6d32335b .word 0x6d32335b + 40cf4: 536c6148 .word 0x536c6148 + 40cf8: 65526973 .word 0x65526973 + 40cfc: 74526461 .word 0x74526461 + 40d00: 3931386c .word 0x3931386c + 40d04: 29286135 .word 0x29286135 + 40d08: 305b1b0a .word 0x305b1b0a + 40d0c: 0000006d .word 0x0000006d + +00040d10 <.LC58>: + 40d10: 53535b0d .word 0x53535b0d + 40d14: 49202049 .word 0x49202049 + 40d18: 205d666e .word 0x205d666e + 40d1c: 53202020 .word 0x53202020 + 40d20: 64254953 .word 0x64254953 + 40d24: 61655220 .word 0x61655220 + 40d28: 25203a64 .word 0x25203a64 + 40d2c: 000a3430 .word 0x000a3430 + +00040d30 <.LC59>: + 40d30: 53535b0d .word 0x53535b0d + 40d34: 49202049 .word 0x49202049 + 40d38: 205d666e .word 0x205d666e + 40d3c: 1b202020 .word 0x1b202020 + 40d40: 6d32335b .word 0x6d32335b + 40d44: 536c6148 .word 0x536c6148 + 40d48: 65476973 .word 0x65476973 + 40d4c: 46785274 .word 0x46785274 + 40d50: 4c6f6669 .word 0x4c6f6669 + 40d54: 6c657665 .word 0x6c657665 + 40d58: 386c7452 .word 0x386c7452 + 40d5c: 61353931 .word 0x61353931 + 40d60: 1b0a2928 .word 0x1b0a2928 + 40d64: 006d305b .word 0x006d305b + +00040d68 <.LC60>: + 40d68: 53535b0d .word 0x53535b0d + 40d6c: 49202049 .word 0x49202049 + 40d70: 205d666e .word 0x205d666e + 40d74: 47202020 .word 0x47202020 + 40d78: 53207465 .word 0x53207465 + 40d7c: 64254953 .word 0x64254953 + 40d80: 20785220 .word 0x20785220 + 40d84: 4f464946 .word 0x4f464946 + 40d88: 76654c20 .word 0x76654c20 + 40d8c: 203a6c65 .word 0x203a6c65 + 40d90: 000a6425 .word 0x000a6425 + +00040d94 <.LC61>: + 40d94: 53535b0d .word 0x53535b0d + 40d98: 49202049 .word 0x49202049 + 40d9c: 205d666e .word 0x205d666e + 40da0: 1b202020 .word 0x1b202020 + 40da4: 6d32335b .word 0x6d32335b + 40da8: 536c6148 .word 0x536c6148 + 40dac: 65476973 .word 0x65476973 + 40db0: 46785474 .word 0x46785474 + 40db4: 4c6f6669 .word 0x4c6f6669 + 40db8: 6c657665 .word 0x6c657665 + 40dbc: 386c7452 .word 0x386c7452 + 40dc0: 61353931 .word 0x61353931 + 40dc4: 1b0a2928 .word 0x1b0a2928 + 40dc8: 006d305b .word 0x006d305b + +00040dcc <.LC62>: + 40dcc: 53535b0d .word 0x53535b0d + 40dd0: 49202049 .word 0x49202049 + 40dd4: 205d666e .word 0x205d666e + 40dd8: 47202020 .word 0x47202020 + 40ddc: 53207465 .word 0x53207465 + 40de0: 64254953 .word 0x64254953 + 40de4: 20785420 .word 0x20785420 + 40de8: 4f464946 .word 0x4f464946 + 40dec: 76654c20 .word 0x76654c20 + 40df0: 203a6c65 .word 0x203a6c65 + 40df4: 000a6425 .word 0x000a6425 + +00040df8 <.LC63>: + 40df8: 53535b0d .word 0x53535b0d + 40dfc: 49202049 .word 0x49202049 + 40e00: 205d666e .word 0x205d666e + 40e04: 1b202020 .word 0x1b202020 + 40e08: 6d32335b .word 0x6d32335b + 40e0c: 536c6148 .word 0x536c6148 + 40e10: 65476973 .word 0x65476973 + 40e14: 61745374 .word 0x61745374 + 40e18: 52737574 .word 0x52737574 + 40e1c: 31386c74 .word 0x31386c74 + 40e20: 28613539 .word 0x28613539 + 40e24: 5b1b0a29 .word 0x5b1b0a29 + 40e28: 00006d30 .word 0x00006d30 + +00040e2c <.LC64>: + 40e2c: 53535b0d .word 0x53535b0d + 40e30: 49202049 .word 0x49202049 + 40e34: 205d666e .word 0x205d666e + 40e38: 53202020 .word 0x53202020 + 40e3c: 64254953 .word 0x64254953 + 40e40: 61745320 .word 0x61745320 + 40e44: 3a737574 .word 0x3a737574 + 40e48: 0a582520 .word 0x0a582520 + 40e4c: 00000000 .word 0x00000000 + +00040e50 <.LC65>: + 40e50: 53535b0d .word 0x53535b0d + 40e54: 49202049 .word 0x49202049 + 40e58: 205d666e .word 0x205d666e + 40e5c: 1b202020 .word 0x1b202020 + 40e60: 6d32335b .word 0x6d32335b + 40e64: 536c6148 .word 0x536c6148 + 40e68: 72576973 .word 0x72576973 + 40e6c: 61657469 .word 0x61657469 + 40e70: 52656c62 .word 0x52656c62 + 40e74: 31386c74 .word 0x31386c74 + 40e78: 28613539 .word 0x28613539 + 40e7c: 5b1b0a29 .word 0x5b1b0a29 + 40e80: 00006d30 .word 0x00006d30 + +00040e84 <.LC66>: + 40e84: 53535b0d .word 0x53535b0d + 40e88: 49202049 .word 0x49202049 + 40e8c: 205d666e .word 0x205d666e + 40e90: 53202020 .word 0x53202020 + 40e94: 64254953 .word 0x64254953 + 40e98: 69725720 .word 0x69725720 + 40e9c: 62616574 .word 0x62616574 + 40ea0: 203a656c .word 0x203a656c + 40ea4: 000a6425 .word 0x000a6425 + +00040ea8 <.LC67>: + 40ea8: 53535b0d .word 0x53535b0d + 40eac: 49202049 .word 0x49202049 + 40eb0: 205d666e .word 0x205d666e + 40eb4: 1b202020 .word 0x1b202020 + 40eb8: 6d32335b .word 0x6d32335b + 40ebc: 536c6148 .word 0x536c6148 + 40ec0: 65526973 .word 0x65526973 + 40ec4: 62616461 .word 0x62616461 + 40ec8: 7452656c .word 0x7452656c + 40ecc: 3931386c .word 0x3931386c + 40ed0: 29286135 .word 0x29286135 + 40ed4: 305b1b0a .word 0x305b1b0a + 40ed8: 0000006d .word 0x0000006d + +00040edc <.LC68>: + 40edc: 53535b0d .word 0x53535b0d + 40ee0: 49202049 .word 0x49202049 + 40ee4: 205d666e .word 0x205d666e + 40ee8: 53202020 .word 0x53202020 + 40eec: 64254953 .word 0x64254953 + 40ef0: 61655220 .word 0x61655220 + 40ef4: 6c626164 .word 0x6c626164 + 40ef8: 25203a65 .word 0x25203a65 + 40efc: 00000a64 .word 0x00000a64 + +00040f00 <.LC69>: + 40f00: 53535b0d .word 0x53535b0d + 40f04: 49202049 .word 0x49202049 + 40f08: 205d666e .word 0x205d666e + 40f0c: 1b202020 .word 0x1b202020 + 40f10: 6d32335b .word 0x6d32335b + 40f14: 536c6148 .word 0x536c6148 + 40f18: 75426973 .word 0x75426973 + 40f1c: 74527973 .word 0x74527973 + 40f20: 3931386c .word 0x3931386c + 40f24: 29286135 .word 0x29286135 + 40f28: 305b1b0a .word 0x305b1b0a + 40f2c: 0000006d .word 0x0000006d + +00040f30 <.LC70>: + 40f30: 53535b0d .word 0x53535b0d + 40f34: 49202049 .word 0x49202049 + 40f38: 205d666e .word 0x205d666e + 40f3c: 53202020 .word 0x53202020 + 40f40: 64254953 .word 0x64254953 + 40f44: 73754220 .word 0x73754220 + 40f48: 25203a79 .word 0x25203a79 + 40f4c: 00000a64 .word 0x00000a64 + +00040f50 <.LC71>: + 40f50: 53535b0d .word 0x53535b0d + 40f54: 49202049 .word 0x49202049 + 40f58: 205d666e .word 0x205d666e + 40f5c: 1b202020 .word 0x1b202020 + 40f60: 6d32335b .word 0x6d32335b + 40f64: 536c6148 .word 0x536c6148 + 40f68: 65526973 .word 0x65526973 + 40f6c: 6e496461 .word 0x6e496461 + 40f70: 72726574 .word 0x72726574 + 40f74: 52747075 .word 0x52747075 + 40f78: 31386c74 .word 0x31386c74 + 40f7c: 28613539 .word 0x28613539 + 40f80: 5b1b0a29 .word 0x5b1b0a29 + 40f84: 00006d30 .word 0x00006d30 + +00040f88 <.LC72>: + 40f88: 53535b0d .word 0x53535b0d + 40f8c: 49202049 .word 0x49202049 + 40f90: 205d666e .word 0x205d666e + 40f94: 53202020 .word 0x53202020 + 40f98: 64254953 .word 0x64254953 + 40f9c: 20736920 .word 0x20736920 + 40fa0: 79737562 .word 0x79737562 + 40fa4: 0000000a .word 0x0000000a + +00040fa8 <.LC73>: + 40fa8: 53535b0d .word 0x53535b0d + 40fac: 49202049 .word 0x49202049 + 40fb0: 205d666e .word 0x205d666e + 40fb4: 53202020 .word 0x53202020 + 40fb8: 64254953 .word 0x64254953 + 40fbc: 44785220 .word 0x44785220 + 40fc0: 20617461 .word 0x20617461 + 40fc4: 72646461 .word 0x72646461 + 40fc8: 7830203a .word 0x7830203a + 40fcc: 202c5825 .word 0x202c5825 + 40fd0: 676e654c .word 0x676e654c + 40fd4: 203a6874 .word 0x203a6874 + 40fd8: 000a6425 .word 0x000a6425 + +00040fdc <.LC74>: + 40fdc: 53535b0d .word 0x53535b0d + 40fe0: 49202049 .word 0x49202049 + 40fe4: 205d666e .word 0x205d666e + 40fe8: 4c202020 .word 0x4c202020 + 40fec: 74676e65 .word 0x74676e65 + 40ff0: 3d3e2068 .word 0x3d3e2068 + 40ff4: 46785220 .word 0x46785220 + 40ff8: 546f6669 .word 0x546f6669 + 40ffc: 73657268 .word 0x73657268 + 41000: 646c6f68 .word 0x646c6f68 + 41004: 6576654c .word 0x6576654c + 41008: 52202c6c .word 0x52202c6c + 4100c: 6e654c78 .word 0x6e654c78 + 41010: 52687467 .word 0x52687467 + 41014: 69616d65 .word 0x69616d65 + 41018: 7265646e .word 0x7265646e + 4101c: 6425203a .word 0x6425203a + 41020: 0000000a .word 0x0000000a + +00041024 <.LC75>: + 41024: 53535b0d .word 0x53535b0d + 41028: 49202049 .word 0x49202049 + 4102c: 205d666e .word 0x205d666e + 41030: 4c202020 .word 0x4c202020 + 41034: 74676e65 .word 0x74676e65 + 41038: 203c2068 .word 0x203c2068 + 4103c: 69467852 .word 0x69467852 + 41040: 68546f66 .word 0x68546f66 + 41044: 68736572 .word 0x68736572 + 41048: 4c646c6f .word 0x4c646c6f + 4104c: 6c657665 .word 0x6c657665 + 41050: 7852202c .word 0x7852202c + 41054: 676e654c .word 0x676e654c + 41058: 65526874 .word 0x65526874 + 4105c: 6e69616d .word 0x6e69616d + 41060: 3a726564 .word 0x3a726564 + 41064: 000a3020 .word 0x000a3020 + +00041068 <.LC76>: + 41068: 53535b0d .word 0x53535b0d + 4106c: 49202049 .word 0x49202049 + 41070: 205d666e .word 0x205d666e + 41074: 53202020 .word 0x53202020 + 41078: 69747465 .word 0x69747465 + 4107c: 5220676e .word 0x5220676e + 41080: 49462078 .word 0x49462078 + 41084: 54204f46 .word 0x54204f46 + 41088: 73657268 .word 0x73657268 + 4108c: 646c6f68 .word 0x646c6f68 + 41090: 76654c20 .word 0x76654c20 + 41094: 74206c65 .word 0x74206c65 + 41098: 0a31206f .word 0x0a31206f + 4109c: 00000000 .word 0x00000000 + +000410a0 <.LC77>: + 410a0: 53535b0d .word 0x53535b0d + 410a4: 49202049 .word 0x49202049 + 410a8: 205d666e .word 0x205d666e + 410ac: 53202020 .word 0x53202020 + 410b0: 64254953 .word 0x64254953 + 410b4: 44785220 .word 0x44785220 + 410b8: 20617461 .word 0x20617461 + 410bc: 72646461 .word 0x72646461 + 410c0: 7830203a .word 0x7830203a + 410c4: 202c5825 .word 0x202c5825 + 410c8: 676e654c .word 0x676e654c + 410cc: 203a6874 .word 0x203a6874 + 410d0: 202c6425 .word 0x202c6425 + 410d4: 616d6552 .word 0x616d6552 + 410d8: 65646e69 .word 0x65646e69 + 410dc: 25203a72 .word 0x25203a72 + 410e0: 00000a64 .word 0x00000a64 + +000410e4 <.LC78>: + 410e4: 53535b0d .word 0x53535b0d + 410e8: 49202049 .word 0x49202049 + 410ec: 205d666e .word 0x205d666e + 410f0: 1b202020 .word 0x1b202020 + 410f4: 6d32335b .word 0x6d32335b + 410f8: 536c6148 .word 0x536c6148 + 410fc: 72576973 .word 0x72576973 + 41100: 49657469 .word 0x49657469 + 41104: 7265746e .word 0x7265746e + 41108: 74707572 .word 0x74707572 + 4110c: 386c7452 .word 0x386c7452 + 41110: 61353931 .word 0x61353931 + 41114: 1b0a2928 .word 0x1b0a2928 + 41118: 006d305b .word 0x006d305b + +0004111c <.LC79>: + 4111c: 53535b0d .word 0x53535b0d + 41120: 49202049 .word 0x49202049 + 41124: 205d666e .word 0x205d666e + 41128: 53202020 .word 0x53202020 + 4112c: 64254953 .word 0x64254953 + 41130: 44785420 .word 0x44785420 + 41134: 20617461 .word 0x20617461 + 41138: 72646461 .word 0x72646461 + 4113c: 7830203a .word 0x7830203a + 41140: 202c5825 .word 0x202c5825 + 41144: 676e654c .word 0x676e654c + 41148: 203a6874 .word 0x203a6874 + 4114c: 000a6425 .word 0x000a6425 + +00041150 <.LC80>: + 41150: 53535b0d .word 0x53535b0d + 41154: 49202049 .word 0x49202049 + 41158: 205d666e .word 0x205d666e + 4115c: 1b202020 .word 0x1b202020 + 41160: 6d32335b .word 0x6d32335b + 41164: 536c6148 .word 0x536c6148 + 41168: 65536973 .word 0x65536973 + 4116c: 616c5374 .word 0x616c5374 + 41170: 6e456576 .word 0x6e456576 + 41174: 656c6261 .word 0x656c6261 + 41178: 69676552 .word 0x69676552 + 4117c: 72657473 .word 0x72657473 + 41180: 386c7452 .word 0x386c7452 + 41184: 61353931 .word 0x61353931 + 41188: 1b0a2928 .word 0x1b0a2928 + 4118c: 006d305b .word 0x006d305b + +00041190 <.LC81>: + 41190: 53535b0d .word 0x53535b0d + 41194: 49202049 .word 0x49202049 + 41198: 205d666e .word 0x205d666e + 4119c: 53202020 .word 0x53202020 + 411a0: 53207465 .word 0x53207465 + 411a4: 64254953 .word 0x64254953 + 411a8: 52455320 .word 0x52455320 + 411ac: 3025203a .word 0x3025203a + 411b0: 000a5838 .word 0x000a5838 + +000411b4 <.LC82>: + 411b4: 53535b0d .word 0x53535b0d + 411b8: 49202049 .word 0x49202049 + 411bc: 205d666e .word 0x205d666e + 411c0: 1b202020 .word 0x1b202020 + 411c4: 6d32335b .word 0x6d32335b + 411c8: 536c6148 .word 0x536c6148 + 411cc: 65476973 .word 0x65476973 + 411d0: 746e4974 .word 0x746e4974 + 411d4: 75727265 .word 0x75727265 + 411d8: 74537470 .word 0x74537470 + 411dc: 73757461 .word 0x73757461 + 411e0: 386c7452 .word 0x386c7452 + 411e4: 61353931 .word 0x61353931 + 411e8: 1b0a2928 .word 0x1b0a2928 + 411ec: 006d305b .word 0x006d305b + +000411f0 <.LC83>: + 411f0: 53535b0d .word 0x53535b0d + 411f4: 49202049 .word 0x49202049 + 411f8: 205d666e .word 0x205d666e + 411fc: 53202020 .word 0x53202020 + 41200: 64254953 .word 0x64254953 + 41204: 746e4920 .word 0x746e4920 + 41208: 75727265 .word 0x75727265 + 4120c: 53207470 .word 0x53207470 + 41210: 75746174 .word 0x75746174 + 41214: 25203a73 .word 0x25203a73 + 41218: 00000a58 .word 0x00000a58 + +0004121c <.LC84>: + 4121c: 53535b0d .word 0x53535b0d + 41220: 49202049 .word 0x49202049 + 41224: 205d666e .word 0x205d666e + 41228: 1b202020 .word 0x1b202020 + 4122c: 6d32335b .word 0x6d32335b + 41230: 536c6148 .word 0x536c6148 + 41234: 6e496973 .word 0x6e496973 + 41238: 72726574 .word 0x72726574 + 4123c: 45747075 .word 0x45747075 + 41240: 6c62616e .word 0x6c62616e + 41244: 6c745265 .word 0x6c745265 + 41248: 35393138 .word 0x35393138 + 4124c: 0a292861 .word 0x0a292861 + 41250: 6d305b1b .word 0x6d305b1b + 41254: 00000000 .word 0x00000000 + +00041258 <.LC85>: + 41258: 53535b0d .word 0x53535b0d + 4125c: 49202049 .word 0x49202049 + 41260: 205d666e .word 0x205d666e + 41264: 53202020 .word 0x53202020 + 41268: 64254953 .word 0x64254953 + 4126c: 524d4920 .word 0x524d4920 + 41270: 5825203a .word 0x5825203a + 41274: 5349202c .word 0x5349202c + 41278: 25203a52 .word 0x25203a52 + 4127c: 00000a58 .word 0x00000a58 + +00041280 <.LC86>: + 41280: 53535b0d .word 0x53535b0d + 41284: 49202049 .word 0x49202049 + 41288: 205d666e .word 0x205d666e + 4128c: 53202020 .word 0x53202020 + 41290: 64254953 .word 0x64254953 + 41294: 71724920 .word 0x71724920 + 41298: 646e6148 .word 0x646e6148 + 4129c: 6920656c .word 0x6920656c + 412a0: 6174736e .word 0x6174736e + 412a4: 2065636e .word 0x2065636e + 412a8: 3a727470 .word 0x3a727470 + 412ac: 0a582520 .word 0x0a582520 + 412b0: 00000000 .word 0x00000000 + +000412b4 <.LC87>: + 412b4: 53535b0d .word 0x53535b0d + 412b8: 49202049 .word 0x49202049 + 412bc: 205d666e .word 0x205d666e + 412c0: 53202020 .word 0x53202020 + 412c4: 64254953 .word 0x64254953 + 412c8: 71724920 .word 0x71724920 + 412cc: 646e6148 .word 0x646e6148 + 412d0: 492e656c .word 0x492e656c + 412d4: 754e7172 .word 0x754e7172 + 412d8: 3a20206d .word 0x3a20206d + 412dc: 0a642520 .word 0x0a642520 + 412e0: 00000000 .word 0x00000000 + +000412e4 <.LC88>: + 412e4: 53535b0d .word 0x53535b0d + 412e8: 49202049 .word 0x49202049 + 412ec: 205d666e .word 0x205d666e + 412f0: 20202020 .word 0x20202020 + 412f4: 20202020 .word 0x20202020 + 412f8: 20202020 .word 0x20202020 + 412fc: 20202020 .word 0x20202020 + 41300: 72492e20 .word 0x72492e20 + 41304: 6e754671 .word 0x6e754671 + 41308: 203a2020 .word 0x203a2020 + 4130c: 000a5825 .word 0x000a5825 + +00041310 <.LC89>: + 41310: 53535b0d .word 0x53535b0d + 41314: 49202049 .word 0x49202049 + 41318: 205d666e .word 0x205d666e + 4131c: 20202020 .word 0x20202020 + 41320: 20202020 .word 0x20202020 + 41324: 20202020 .word 0x20202020 + 41328: 20202020 .word 0x20202020 + 4132c: 61442e20 .word 0x61442e20 + 41330: 20206174 .word 0x20206174 + 41334: 203a2020 .word 0x203a2020 + 41338: 000a5825 .word 0x000a5825 + +0004133c <.LC90>: + 4133c: 53535b0d .word 0x53535b0d + 41340: 49202049 .word 0x49202049 + 41344: 205d666e .word 0x205d666e + 41348: 20202020 .word 0x20202020 + 4134c: 20202020 .word 0x20202020 + 41350: 20202020 .word 0x20202020 + 41354: 20202020 .word 0x20202020 + 41358: 72502e20 .word 0x72502e20 + 4135c: 69726f69 .word 0x69726f69 + 41360: 203a7974 .word 0x203a7974 + 41364: 58257830 .word 0x58257830 + 41368: 0000000a .word 0x0000000a + +0004136c <.LC91>: + 4136c: 53535b0d .word 0x53535b0d + 41370: 49202049 .word 0x49202049 + 41374: 205d666e .word 0x205d666e + 41378: 1b202020 .word 0x1b202020 + 4137c: 6d32335b .word 0x6d32335b + 41380: 536c6148 .word 0x536c6148 + 41384: 6e496973 .word 0x6e496973 + 41388: 72726574 .word 0x72726574 + 4138c: 44747075 .word 0x44747075 + 41390: 62617369 .word 0x62617369 + 41394: 7452656c .word 0x7452656c + 41398: 3931386c .word 0x3931386c + 4139c: 29286135 .word 0x29286135 + 413a0: 305b1b0a .word 0x305b1b0a + 413a4: 0000006d .word 0x0000006d + +000413a8 <.LC92>: + 413a8: 53535b0d .word 0x53535b0d + 413ac: 49202049 .word 0x49202049 + 413b0: 205d666e .word 0x205d666e + 413b4: 1b202020 .word 0x1b202020 + 413b8: 6d32335b .word 0x6d32335b + 413bc: 536c6148 .word 0x536c6148 + 413c0: 65476973 .word 0x65476973 + 413c4: 77615274 .word 0x77615274 + 413c8: 65746e49 .word 0x65746e49 + 413cc: 70757272 .word 0x70757272 + 413d0: 61745374 .word 0x61745374 + 413d4: 52737574 .word 0x52737574 + 413d8: 31386c74 .word 0x31386c74 + 413dc: 28613539 .word 0x28613539 + 413e0: 5b1b0a29 .word 0x5b1b0a29 + 413e4: 00006d30 .word 0x00006d30 + +000413e8 <.LC93>: + 413e8: 53535b0d .word 0x53535b0d + 413ec: 49202049 .word 0x49202049 + 413f0: 205d666e .word 0x205d666e + 413f4: 53202020 .word 0x53202020 + 413f8: 64254953 .word 0x64254953 + 413fc: 77615220 .word 0x77615220 + 41400: 746e4920 .word 0x746e4920 + 41404: 75727265 .word 0x75727265 + 41408: 53207470 .word 0x53207470 + 4140c: 75746174 .word 0x75746174 + 41410: 25203a73 .word 0x25203a73 + 41414: 00000a58 .word 0x00000a58 + +00041418 <.LC94>: + 41418: 53535b0d .word 0x53535b0d + 4141c: 49202049 .word 0x49202049 + 41420: 205d666e .word 0x205d666e + 41424: 1b202020 .word 0x1b202020 + 41428: 6d32335b .word 0x6d32335b + 4142c: 536c6148 .word 0x536c6148 + 41430: 65476973 .word 0x65476973 + 41434: 616c5374 .word 0x616c5374 + 41438: 6e456576 .word 0x6e456576 + 4143c: 656c6261 .word 0x656c6261 + 41440: 69676552 .word 0x69676552 + 41444: 72657473 .word 0x72657473 + 41448: 386c7452 .word 0x386c7452 + 4144c: 61353931 .word 0x61353931 + 41450: 1b0a2928 .word 0x1b0a2928 + 41454: 006d305b .word 0x006d305b + +00041458 <.LC95>: + 41458: 53535b0d .word 0x53535b0d + 4145c: 49202049 .word 0x49202049 + 41460: 205d666e .word 0x205d666e + 41464: 53202020 .word 0x53202020 + 41468: 64254953 .word 0x64254953 + 4146c: 52455320 .word 0x52455320 + 41470: 6c617620 .word 0x6c617620 + 41474: 203a6575 .word 0x203a6575 + 41478: 000a5825 .word 0x000a5825 + +0004147c <.LC96>: + 4147c: 53535b0d .word 0x53535b0d + 41480: 49202049 .word 0x49202049 + 41484: 205d666e .word 0x205d666e + 41488: 1b202020 .word 0x1b202020 + 4148c: 6d32335b .word 0x6d32335b + 41490: 536c6148 .word 0x536c6148 + 41494: 6e496973 .word 0x6e496973 + 41498: 74527469 .word 0x74527469 + 4149c: 3931386c .word 0x3931386c + 414a0: 29286135 .word 0x29286135 + 414a4: 305b1b0a .word 0x305b1b0a + 414a8: 0000006d .word 0x0000006d + +000414ac <.LC97>: + 414ac: 53535b0d .word 0x53535b0d + 414b0: 49202049 .word 0x49202049 + 414b4: 205d666e .word 0x205d666e + 414b8: 5b202020 .word 0x5b202020 + 414bc: 53205d31 .word 0x53205d31 + 414c0: 53207465 .word 0x53207465 + 414c4: 64254953 .word 0x64254953 + 414c8: 47455220 .word 0x47455220 + 414cc: 5f57445f .word 0x5f57445f + 414d0: 5f495353 .word 0x5f495353 + 414d4: 4c525443 .word 0x4c525443 + 414d8: 56203052 .word 0x56203052 + 414dc: 65756c61 .word 0x65756c61 + 414e0: 5825203a .word 0x5825203a + 414e4: 0000000a .word 0x0000000a + +000414e8 <.LC98>: + 414e8: 53535b0d .word 0x53535b0d + 414ec: 49202049 .word 0x49202049 + 414f0: 205d666e .word 0x205d666e + 414f4: 5b202020 .word 0x5b202020 + 414f8: 53205d31 .word 0x53205d31 + 414fc: 53207465 .word 0x53207465 + 41500: 64254953 .word 0x64254953 + 41504: 47455220 .word 0x47455220 + 41508: 5f57445f .word 0x5f57445f + 4150c: 5f495353 .word 0x5f495353 + 41510: 54465854 .word 0x54465854 + 41514: 5620524c .word 0x5620524c + 41518: 65756c61 .word 0x65756c61 + 4151c: 5825203a .word 0x5825203a + 41520: 0000000a .word 0x0000000a + +00041524 <.LC99>: + 41524: 53535b0d .word 0x53535b0d + 41528: 49202049 .word 0x49202049 + 4152c: 205d666e .word 0x205d666e + 41530: 5b202020 .word 0x5b202020 + 41534: 53205d32 .word 0x53205d32 + 41538: 64254953 .word 0x64254953 + 4153c: 47455220 .word 0x47455220 + 41540: 5f57445f .word 0x5f57445f + 41544: 5f495353 .word 0x5f495353 + 41548: 54465854 .word 0x54465854 + 4154c: 2528524c .word 0x2528524c + 41550: 3d202958 .word 0x3d202958 + 41554: 0a582520 .word 0x0a582520 + 41558: 00000000 .word 0x00000000 + +0004155c <.LC100>: + 4155c: 53535b0d .word 0x53535b0d + 41560: 49202049 .word 0x49202049 + 41564: 205d666e .word 0x205d666e + 41568: 5b202020 .word 0x5b202020 + 4156c: 53205d31 .word 0x53205d31 + 41570: 53207465 .word 0x53207465 + 41574: 64254953 .word 0x64254953 + 41578: 47455220 .word 0x47455220 + 4157c: 5f57445f .word 0x5f57445f + 41580: 5f495353 .word 0x5f495353 + 41584: 54465852 .word 0x54465852 + 41588: 5620524c .word 0x5620524c + 4158c: 65756c61 .word 0x65756c61 + 41590: 5825203a .word 0x5825203a + 41594: 0000000a .word 0x0000000a + +00041598 <.LC101>: + 41598: 53535b0d .word 0x53535b0d + 4159c: 49202049 .word 0x49202049 + 415a0: 205d666e .word 0x205d666e + 415a4: 5b202020 .word 0x5b202020 + 415a8: 53205d32 .word 0x53205d32 + 415ac: 64254953 .word 0x64254953 + 415b0: 47455220 .word 0x47455220 + 415b4: 5f57445f .word 0x5f57445f + 415b8: 5f495353 .word 0x5f495353 + 415bc: 54465852 .word 0x54465852 + 415c0: 2528524c .word 0x2528524c + 415c4: 3d202958 .word 0x3d202958 + 415c8: 0a582520 .word 0x0a582520 + 415cc: 00000000 .word 0x00000000 + +000415d0 <.LC102>: + 415d0: 53535b0d .word 0x53535b0d + 415d4: 49202049 .word 0x49202049 + 415d8: 205d666e .word 0x205d666e + 415dc: 5b202020 .word 0x5b202020 + 415e0: 53205d31 .word 0x53205d31 + 415e4: 53207465 .word 0x53207465 + 415e8: 64254953 .word 0x64254953 + 415ec: 47455220 .word 0x47455220 + 415f0: 5f57445f .word 0x5f57445f + 415f4: 5f495353 .word 0x5f495353 + 415f8: 4c525443 .word 0x4c525443 + 415fc: 56203152 .word 0x56203152 + 41600: 65756c61 .word 0x65756c61 + 41604: 5825203a .word 0x5825203a + 41608: 0000000a .word 0x0000000a + +0004160c <.LC103>: + 4160c: 53535b0d .word 0x53535b0d + 41610: 49202049 .word 0x49202049 + 41614: 205d666e .word 0x205d666e + 41618: 5b202020 .word 0x5b202020 + 4161c: 53205d32 .word 0x53205d32 + 41620: 64254953 .word 0x64254953 + 41624: 47455220 .word 0x47455220 + 41628: 5f57445f .word 0x5f57445f + 4162c: 5f495353 .word 0x5f495353 + 41630: 4c525443 .word 0x4c525443 + 41634: 25283152 .word 0x25283152 + 41638: 3d202958 .word 0x3d202958 + 4163c: 0a582520 .word 0x0a582520 + 41640: 00000000 .word 0x00000000 + +00041644 <.LC104>: + 41644: 53535b0d .word 0x53535b0d + 41648: 49202049 .word 0x49202049 + 4164c: 205d666e .word 0x205d666e + 41650: 5b202020 .word 0x5b202020 + 41654: 53205d31 .word 0x53205d31 + 41658: 53207465 .word 0x53207465 + 4165c: 64254953 .word 0x64254953 + 41660: 47455220 .word 0x47455220 + 41664: 5f57445f .word 0x5f57445f + 41668: 5f495353 .word 0x5f495353 + 4166c: 20524553 .word 0x20524553 + 41670: 756c6156 .word 0x756c6156 + 41674: 25203a65 .word 0x25203a65 + 41678: 00000a58 .word 0x00000a58 + +0004167c <.LC105>: + 4167c: 53535b0d .word 0x53535b0d + 41680: 49202049 .word 0x49202049 + 41684: 205d666e .word 0x205d666e + 41688: 5b202020 .word 0x5b202020 + 4168c: 53205d32 .word 0x53205d32 + 41690: 64254953 .word 0x64254953 + 41694: 47455220 .word 0x47455220 + 41698: 5f57445f .word 0x5f57445f + 4169c: 5f495353 .word 0x5f495353 + 416a0: 28524553 .word 0x28524553 + 416a4: 20295825 .word 0x20295825 + 416a8: 5825203d .word 0x5825203d + 416ac: 0000000a .word 0x0000000a + +000416b0 <.LC106>: + 416b0: 53535b0d .word 0x53535b0d + 416b4: 49202049 .word 0x49202049 + 416b8: 205d666e .word 0x205d666e + 416bc: 5b202020 .word 0x5b202020 + 416c0: 53205d31 .word 0x53205d31 + 416c4: 53207465 .word 0x53207465 + 416c8: 64254953 .word 0x64254953 + 416cc: 47455220 .word 0x47455220 + 416d0: 5f57445f .word 0x5f57445f + 416d4: 5f495353 .word 0x5f495353 + 416d8: 44554142 .word 0x44554142 + 416dc: 61562052 .word 0x61562052 + 416e0: 3a65756c .word 0x3a65756c + 416e4: 0a582520 .word 0x0a582520 + 416e8: 00000000 .word 0x00000000 + +000416ec <.LC107>: + 416ec: 53535b0d .word 0x53535b0d + 416f0: 49202049 .word 0x49202049 + 416f4: 205d666e .word 0x205d666e + 416f8: 5b202020 .word 0x5b202020 + 416fc: 53205d32 .word 0x53205d32 + 41700: 64254953 .word 0x64254953 + 41704: 47455220 .word 0x47455220 + 41708: 5f57445f .word 0x5f57445f + 4170c: 5f495353 .word 0x5f495353 + 41710: 44554142 .word 0x44554142 + 41714: 58252852 .word 0x58252852 + 41718: 203d2029 .word 0x203d2029 + 4171c: 000a5825 .word 0x000a5825 + +00041720 <.LC108>: + 41720: 53535b0d .word 0x53535b0d + 41724: 49202049 .word 0x49202049 + 41728: 205d666e .word 0x205d666e + 4172c: 5b202020 .word 0x5b202020 + 41730: 53205d31 .word 0x53205d31 + 41734: 53207465 .word 0x53207465 + 41738: 64254953 .word 0x64254953 + 4173c: 47455220 .word 0x47455220 + 41740: 5f57445f .word 0x5f57445f + 41744: 5f495353 .word 0x5f495353 + 41748: 43414d44 .word 0x43414d44 + 4174c: 61562052 .word 0x61562052 + 41750: 3a65756c .word 0x3a65756c + 41754: 0a582520 .word 0x0a582520 + 41758: 00000000 .word 0x00000000 + +0004175c <.LC109>: + 4175c: 53535b0d .word 0x53535b0d + 41760: 49202049 .word 0x49202049 + 41764: 205d666e .word 0x205d666e + 41768: 5b202020 .word 0x5b202020 + 4176c: 53205d32 .word 0x53205d32 + 41770: 64254953 .word 0x64254953 + 41774: 47455220 .word 0x47455220 + 41778: 5f57445f .word 0x5f57445f + 4177c: 5f495353 .word 0x5f495353 + 41780: 43414d44 .word 0x43414d44 + 41784: 58252852 .word 0x58252852 + 41788: 203d2029 .word 0x203d2029 + 4178c: 000a5825 .word 0x000a5825 + +00041790 <.LC110>: + 41790: 53535b0d .word 0x53535b0d + 41794: 49202049 .word 0x49202049 + 41798: 205d666e .word 0x205d666e + 4179c: 5b202020 .word 0x5b202020 + 417a0: 53205d31 .word 0x53205d31 + 417a4: 53207465 .word 0x53207465 + 417a8: 64254953 .word 0x64254953 + 417ac: 47455220 .word 0x47455220 + 417b0: 5f57445f .word 0x5f57445f + 417b4: 5f495353 .word 0x5f495353 + 417b8: 54414d44 .word 0x54414d44 + 417bc: 20524c44 .word 0x20524c44 + 417c0: 756c6156 .word 0x756c6156 + 417c4: 25203a65 .word 0x25203a65 + 417c8: 00000a58 .word 0x00000a58 + +000417cc <.LC111>: + 417cc: 53535b0d .word 0x53535b0d + 417d0: 49202049 .word 0x49202049 + 417d4: 205d666e .word 0x205d666e + 417d8: 5b202020 .word 0x5b202020 + 417dc: 53205d32 .word 0x53205d32 + 417e0: 64254953 .word 0x64254953 + 417e4: 47455220 .word 0x47455220 + 417e8: 5f57445f .word 0x5f57445f + 417ec: 5f495353 .word 0x5f495353 + 417f0: 54414d44 .word 0x54414d44 + 417f4: 28524c44 .word 0x28524c44 + 417f8: 20295825 .word 0x20295825 + 417fc: 5825203d .word 0x5825203d + 41800: 0000000a .word 0x0000000a + +00041804 <.LC112>: + 41804: 53535b0d .word 0x53535b0d + 41808: 49202049 .word 0x49202049 + 4180c: 205d666e .word 0x205d666e + 41810: 5b202020 .word 0x5b202020 + 41814: 53205d31 .word 0x53205d31 + 41818: 53207465 .word 0x53207465 + 4181c: 64254953 .word 0x64254953 + 41820: 47455220 .word 0x47455220 + 41824: 5f57445f .word 0x5f57445f + 41828: 5f495353 .word 0x5f495353 + 4182c: 52414d44 .word 0x52414d44 + 41830: 20524c44 .word 0x20524c44 + 41834: 756c6156 .word 0x756c6156 + 41838: 25203a65 .word 0x25203a65 + 4183c: 00000a58 .word 0x00000a58 + +00041840 <.LC113>: + 41840: 53535b0d .word 0x53535b0d + 41844: 49202049 .word 0x49202049 + 41848: 205d666e .word 0x205d666e + 4184c: 5b202020 .word 0x5b202020 + 41850: 53205d32 .word 0x53205d32 + 41854: 64254953 .word 0x64254953 + 41858: 47455220 .word 0x47455220 + 4185c: 5f57445f .word 0x5f57445f + 41860: 5f495353 .word 0x5f495353 + 41864: 52414d44 .word 0x52414d44 + 41868: 28524c44 .word 0x28524c44 + 4186c: 20295825 .word 0x20295825 + 41870: 5825203d .word 0x5825203d + 41874: 0000000a .word 0x0000000a + +00041878 <.LC114>: + 41878: 53535b0d .word 0x53535b0d + 4187c: 49202049 .word 0x49202049 + 41880: 205d666e .word 0x205d666e + 41884: 5b202020 .word 0x5b202020 + 41888: 53205d31 .word 0x53205d31 + 4188c: 53207465 .word 0x53207465 + 41890: 64254953 .word 0x64254953 + 41894: 47455220 .word 0x47455220 + 41898: 5f57445f .word 0x5f57445f + 4189c: 5f495353 .word 0x5f495353 + 418a0: 5243574d .word 0x5243574d + 418a4: 6c615620 .word 0x6c615620 + 418a8: 203a6575 .word 0x203a6575 + 418ac: 000a5825 .word 0x000a5825 + +000418b0 <.LC115>: + 418b0: 53535b0d .word 0x53535b0d + 418b4: 49202049 .word 0x49202049 + 418b8: 205d666e .word 0x205d666e + 418bc: 5b202020 .word 0x5b202020 + 418c0: 53205d32 .word 0x53205d32 + 418c4: 64254953 .word 0x64254953 + 418c8: 47455220 .word 0x47455220 + 418cc: 5f57445f .word 0x5f57445f + 418d0: 5f495353 .word 0x5f495353 + 418d4: 5243574d .word 0x5243574d + 418d8: 29582528 .word 0x29582528 + 418dc: 25203d20 .word 0x25203d20 + 418e0: 00000a58 .word 0x00000a58 + +000418e4 <.LC116>: + 418e4: 53535b0d .word 0x53535b0d + 418e8: 49202049 .word 0x49202049 + 418ec: 205d666e .word 0x205d666e + 418f0: 53202020 .word 0x53202020 + 418f4: 64254953 .word 0x64254953 + 418f8: 61725420 .word 0x61725420 + 418fc: 6566736e .word 0x6566736e + 41900: 63654d72 .word 0x63654d72 + 41904: 696e6168 .word 0x696e6168 + 41908: 203a6d73 .word 0x203a6d73 + 4190c: 000a6425 .word 0x000a6425 + +00041910 <.LC117>: + 41910: 53535b0d .word 0x53535b0d + 41914: 49202049 .word 0x49202049 + 41918: 205d666e .word 0x205d666e + 4191c: 53202020 .word 0x53202020 + 41920: 64254953 .word 0x64254953 + 41924: 746e4920 .word 0x746e4920 + 41928: 75727265 .word 0x75727265 + 4192c: 69207470 .word 0x69207470 + 41930: 6974696e .word 0x6974696e + 41934: 7a696c61 .word 0x7a696c61 + 41938: 49202c65 .word 0x49202c65 + 4193c: 7265746e .word 0x7265746e + 41940: 74707572 .word 0x74707572 + 41944: 5825203a .word 0x5825203a + 41948: 0000000a .word 0x0000000a + +0004194c <.LC118>: + 4194c: 53535b0d .word 0x53535b0d + 41950: 49202049 .word 0x49202049 + 41954: 205d666e .word 0x205d666e + 41958: 55202020 .word 0x55202020 + 4195c: 6f6e6b6e .word 0x6f6e6b6e + 41960: 53206e77 .word 0x53206e77 + 41964: 49204953 .word 0x49204953 + 41968: 7865646e .word 0x7865646e + 4196c: 00000a2e .word 0x00000a2e + +00041970 <.LC119>: + 41970: 53535b0d .word 0x53535b0d + 41974: 49202049 .word 0x49202049 + 41978: 205d666e .word 0x205d666e + 4197c: 1b202020 .word 0x1b202020 + 41980: 6d32335b .word 0x6d32335b + 41984: 6973535f .word 0x6973535f + 41988: 64616552 .word 0x64616552 + 4198c: 65746e49 .word 0x65746e49 + 41990: 70757272 .word 0x70757272 + 41994: 0a292874 .word 0x0a292874 + 41998: 6d305b1b .word 0x6d305b1b + 4199c: 00000000 .word 0x00000000 + +000419a0 <.LC120>: + 419a0: 53535b0d .word 0x53535b0d + 419a4: 49202049 .word 0x49202049 + 419a8: 205d666e .word 0x205d666e + 419ac: 52202020 .word 0x52202020 + 419b0: 74614478 .word 0x74614478 + 419b4: 3a202061 .word 0x3a202061 + 419b8: 2c582520 .word 0x2c582520 + 419bc: 0a582520 .word 0x0a582520 + 419c0: 00000000 .word 0x00000000 + +000419c4 <.LC121>: + 419c4: 53535b0d .word 0x53535b0d + 419c8: 49202049 .word 0x49202049 + 419cc: 205d666e .word 0x205d666e + 419d0: 52202020 .word 0x52202020 + 419d4: 74614478 .word 0x74614478 + 419d8: 3a312b61 .word 0x3a312b61 + 419dc: 0a582520 .word 0x0a582520 + 419e0: 00000000 .word 0x00000000 + +000419e4 <.LC122>: + 419e4: 53535b0d .word 0x53535b0d + 419e8: 49202049 .word 0x49202049 + 419ec: 205d666e .word 0x205d666e + 419f0: 52202020 .word 0x52202020 + 419f4: 6e654c78 .word 0x6e654c78 + 419f8: 3a687467 .word 0x3a687467 + 419fc: 2c642520 .word 0x2c642520 + 41a00: 4c785220 .word 0x4c785220 + 41a04: 74676e65 .word 0x74676e65 + 41a08: 6d655268 .word 0x6d655268 + 41a0c: 646e6961 .word 0x646e6961 + 41a10: 203a7265 .word 0x203a7265 + 41a14: 000a6425 .word 0x000a6425 + +00041a18 <.LC123>: + 41a18: 53535b0d .word 0x53535b0d + 41a1c: 49202049 .word 0x49202049 + 41a20: 205d666e .word 0x205d666e + 41a24: 1b202020 .word 0x1b202020 + 41a28: 6d32335b .word 0x6d32335b + 41a2c: 6973535f .word 0x6973535f + 41a30: 74697257 .word 0x74697257 + 41a34: 746e4965 .word 0x746e4965 + 41a38: 75727265 .word 0x75727265 + 41a3c: 29287470 .word 0x29287470 + 41a40: 305b1b0a .word 0x305b1b0a + 41a44: 0000006d .word 0x0000006d + +00041a48 <.LC124>: + 41a48: 53535b0d .word 0x53535b0d + 41a4c: 49202049 .word 0x49202049 + 41a50: 205d666e .word 0x205d666e + 41a54: 54202020 .word 0x54202020 + 41a58: 74614478 .word 0x74614478 + 41a5c: 3a312b61 .word 0x3a312b61 + 41a60: 2c582520 .word 0x2c582520 + 41a64: 4c785420 .word 0x4c785420 + 41a68: 74676e65 .word 0x74676e65 + 41a6c: 25203a68 .word 0x25203a68 + 41a70: 00000a64 .word 0x00000a64 + +00041a74 <.LC125>: + 41a74: 53535b0d .word 0x53535b0d + 41a78: 49202049 .word 0x49202049 + 41a7c: 205d666e .word 0x205d666e + 41a80: 1b202020 .word 0x1b202020 + 41a84: 6d32335b .word 0x6d32335b + 41a88: 6973535f .word 0x6973535f + 41a8c: 48717249 .word 0x48717249 + 41a90: 6c646e61 .word 0x6c646e61 + 41a94: 0a292865 .word 0x0a292865 + 41a98: 6d305b1b .word 0x6d305b1b + 41a9c: 00000000 .word 0x00000000 + +00041aa0 <.LC126>: + 41aa0: 53535b0d .word 0x53535b0d + 41aa4: 49202049 .word 0x49202049 + 41aa8: 205d666e .word 0x205d666e + 41aac: 5b202020 .word 0x5b202020 + 41ab0: 5d544e49 .word 0x5d544e49 + 41ab4: 4953535b .word 0x4953535b + 41ab8: 205d6425 .word 0x205d6425 + 41abc: 6e617254 .word 0x6e617254 + 41ac0: 74696d73 .word 0x74696d73 + 41ac4: 46494620 .word 0x46494620 + 41ac8: 764f204f .word 0x764f204f + 41acc: 6c667265 .word 0x6c667265 + 41ad0: 4920776f .word 0x4920776f + 41ad4: 7265746e .word 0x7265746e + 41ad8: 74707572 .word 0x74707572 + 41adc: 0000000a .word 0x0000000a + +00041ae0 <.LC127>: + 41ae0: 53535b0d .word 0x53535b0d + 41ae4: 49202049 .word 0x49202049 + 41ae8: 205d666e .word 0x205d666e + 41aec: 5b202020 .word 0x5b202020 + 41af0: 5d544e49 .word 0x5d544e49 + 41af4: 4953535b .word 0x4953535b + 41af8: 205d6425 .word 0x205d6425 + 41afc: 65636552 .word 0x65636552 + 41b00: 20657669 .word 0x20657669 + 41b04: 4f464946 .word 0x4f464946 + 41b08: 646e5520 .word 0x646e5520 + 41b0c: 6c667265 .word 0x6c667265 + 41b10: 4920776f .word 0x4920776f + 41b14: 7265746e .word 0x7265746e + 41b18: 74707572 .word 0x74707572 + 41b1c: 0000000a .word 0x0000000a + +00041b20 <.LC128>: + 41b20: 53535b0d .word 0x53535b0d + 41b24: 49202049 .word 0x49202049 + 41b28: 205d666e .word 0x205d666e + 41b2c: 5b202020 .word 0x5b202020 + 41b30: 5d544e49 .word 0x5d544e49 + 41b34: 4953535b .word 0x4953535b + 41b38: 205d6425 .word 0x205d6425 + 41b3c: 65636552 .word 0x65636552 + 41b40: 20657669 .word 0x20657669 + 41b44: 4f464946 .word 0x4f464946 + 41b48: 65764f20 .word 0x65764f20 + 41b4c: 6f6c6672 .word 0x6f6c6672 + 41b50: 6e492077 .word 0x6e492077 + 41b54: 72726574 .word 0x72726574 + 41b58: 0a747075 .word 0x0a747075 + 41b5c: 00000000 .word 0x00000000 + +00041b60 <.LC129>: + 41b60: 53535b0d .word 0x53535b0d + 41b64: 49202049 .word 0x49202049 + 41b68: 205d666e .word 0x205d666e + 41b6c: 5b202020 .word 0x5b202020 + 41b70: 5d544e49 .word 0x5d544e49 + 41b74: 4953535b .word 0x4953535b + 41b78: 205d6425 .word 0x205d6425 + 41b7c: 746c754d .word 0x746c754d + 41b80: 614d2d69 .word 0x614d2d69 + 41b84: 72657473 .word 0x72657473 + 41b88: 6e6f4320 .word 0x6e6f4320 + 41b8c: 746e6574 .word 0x746e6574 + 41b90: 206e6f69 .word 0x206e6f69 + 41b94: 65746e49 .word 0x65746e49 + 41b98: 70757272 .word 0x70757272 + 41b9c: 00000a74 .word 0x00000a74 + +00041ba0 <.LC130>: + 41ba0: 53535b0d .word 0x53535b0d + 41ba4: 49202049 .word 0x49202049 + 41ba8: 205d666e .word 0x205d666e + 41bac: 5b202020 .word 0x5b202020 + 41bb0: 5d544e49 .word 0x5d544e49 + 41bb4: 4953535b .word 0x4953535b + 41bb8: 205d6425 .word 0x205d6425 + 41bbc: 65636552 .word 0x65636552 + 41bc0: 20657669 .word 0x20657669 + 41bc4: 4f464946 .word 0x4f464946 + 41bc8: 6c754620 .word 0x6c754620 + 41bcc: 6e49206c .word 0x6e49206c + 41bd0: 72726574 .word 0x72726574 + 41bd4: 0a747075 .word 0x0a747075 + 41bd8: 00000000 .word 0x00000000 + +00041bdc <.LC131>: + 41bdc: 53535b0d .word 0x53535b0d + 41be0: 49202049 .word 0x49202049 + 41be4: 205d666e .word 0x205d666e + 41be8: 5b202020 .word 0x5b202020 + 41bec: 5d544e49 .word 0x5d544e49 + 41bf0: 4953535b .word 0x4953535b + 41bf4: 205d6425 .word 0x205d6425 + 41bf8: 6e617254 .word 0x6e617254 + 41bfc: 74696d73 .word 0x74696d73 + 41c00: 46494620 .word 0x46494620 + 41c04: 6d45204f .word 0x6d45204f + 41c08: 20797470 .word 0x20797470 + 41c0c: 65746e49 .word 0x65746e49 + 41c10: 70757272 .word 0x70757272 + 41c14: 00000a74 .word 0x00000a74 + +00041c18 <.LC0>: + 41c18: 32495b0d .word 0x32495b0d + 41c1c: 49202043 .word 0x49202043 + 41c20: 495d666e .word 0x495d666e + 41c24: 495f4332 .word 0x495f4332 + 41c28: 4e455f43 .word 0x4e455f43 + 41c2c: 454c4241 .word 0x454c4241 + 41c30: 7832255f .word 0x7832255f + 41c34: 29782528 .word 0x29782528 + 41c38: 7825203a .word 0x7825203a + 41c3c: 0000000a .word 0x0000000a + +00041c40 <.LC1>: + 41c40: 32495b0d .word 0x32495b0d + 41c44: 49202043 .word 0x49202043 + 41c48: 485d666e .word 0x485d666e + 41c4c: 32496c61 .word 0x32496c61 + 41c50: 6e655343 .word 0x6e655343 + 41c54: 6c745264 .word 0x6c745264 + 41c58: 35393138 .word 0x35393138 + 41c5c: 00000a61 .word 0x00000a61 + +00041c60 <.LC2>: + 41c60: 32495b0d .word 0x32495b0d + 41c64: 49202043 .word 0x49202043 + 41c68: 495d666e .word 0x495d666e + 41c6c: 49204332 .word 0x49204332 + 41c70: 7865646e .word 0x7865646e + 41c74: 7825203a .word 0x7825203a + 41c78: 0000000a .word 0x0000000a + +00041c7c <.LC3>: + 41c7c: 32495b0d .word 0x32495b0d + 41c80: 49202043 .word 0x49202043 + 41c84: 495d666e .word 0x495d666e + 41c88: 53535f43 .word 0x53535f43 + 41c8c: 4c43535f .word 0x4c43535f + 41c90: 4e43485f .word 0x4e43485f + 41c94: 5b642554 .word 0x5b642554 + 41c98: 5d783225 .word 0x5d783225 + 41c9c: 7825203a .word 0x7825203a + 41ca0: 0000000a .word 0x0000000a + +00041ca4 <.LC4>: + 41ca4: 32495b0d .word 0x32495b0d + 41ca8: 49202043 .word 0x49202043 + 41cac: 495d666e .word 0x495d666e + 41cb0: 53535f43 .word 0x53535f43 + 41cb4: 4c43535f .word 0x4c43535f + 41cb8: 4e434c5f .word 0x4e434c5f + 41cbc: 5b642554 .word 0x5b642554 + 41cc0: 5d783225 .word 0x5d783225 + 41cc4: 7825203a .word 0x7825203a + 41cc8: 0000000a .word 0x0000000a + +00041ccc <.LC5>: + 41ccc: 32495b0d .word 0x32495b0d + 41cd0: 49202043 .word 0x49202043 + 41cd4: 495d666e .word 0x495d666e + 41cd8: 53465f43 .word 0x53465f43 + 41cdc: 4c43535f .word 0x4c43535f + 41ce0: 4e43485f .word 0x4e43485f + 41ce4: 5b642554 .word 0x5b642554 + 41ce8: 5d783225 .word 0x5d783225 + 41cec: 7825203a .word 0x7825203a + 41cf0: 0000000a .word 0x0000000a + +00041cf4 <.LC6>: + 41cf4: 32495b0d .word 0x32495b0d + 41cf8: 49202043 .word 0x49202043 + 41cfc: 495d666e .word 0x495d666e + 41d00: 53465f43 .word 0x53465f43 + 41d04: 4c43535f .word 0x4c43535f + 41d08: 4e434c5f .word 0x4e434c5f + 41d0c: 5b642554 .word 0x5b642554 + 41d10: 5d783225 .word 0x5d783225 + 41d14: 7825203a .word 0x7825203a + 41d18: 0000000a .word 0x0000000a + +00041d1c <.LC7>: + 41d1c: 32495b0d .word 0x32495b0d + 41d20: 49202043 .word 0x49202043 + 41d24: 495d666e .word 0x495d666e + 41d28: 69744843 .word 0x69744843 + 41d2c: 253a656d .word 0x253a656d + 41d30: 00000a78 .word 0x00000a78 + +00041d34 <.LC8>: + 41d34: 32495b0d .word 0x32495b0d + 41d38: 49202043 .word 0x49202043 + 41d3c: 495d666e .word 0x495d666e + 41d40: 69744c43 .word 0x69744c43 + 41d44: 253a656d .word 0x253a656d + 41d48: 00000a78 .word 0x00000a78 + +00041d4c <.LC9>: + 41d4c: 32495b0d .word 0x32495b0d + 41d50: 49202043 .word 0x49202043 + 41d54: 495d666e .word 0x495d666e + 41d58: 53485f43 .word 0x53485f43 + 41d5c: 4c43535f .word 0x4c43535f + 41d60: 4e43485f .word 0x4e43485f + 41d64: 5b642554 .word 0x5b642554 + 41d68: 5d783225 .word 0x5d783225 + 41d6c: 7825203a .word 0x7825203a + 41d70: 0000000a .word 0x0000000a + +00041d74 <.LC10>: + 41d74: 32495b0d .word 0x32495b0d + 41d78: 49202043 .word 0x49202043 + 41d7c: 495d666e .word 0x495d666e + 41d80: 53485f43 .word 0x53485f43 + 41d84: 4c43535f .word 0x4c43535f + 41d88: 4e434c5f .word 0x4e434c5f + 41d8c: 5b642554 .word 0x5b642554 + 41d90: 5d783225 .word 0x5d783225 + 41d94: 7825203a .word 0x7825203a + 41d98: 0000000a .word 0x0000000a + +00041d9c <.LC11>: + 41d9c: 32495b0d .word 0x32495b0d + 41da0: 49202043 .word 0x49202043 + 41da4: 495d666e .word 0x495d666e + 41da8: 2074696e .word 0x2074696e + 41dac: 7473616d .word 0x7473616d + 41db0: 202c7265 .word 0x202c7265 + 41db4: 435f4349 .word 0x435f4349 + 41db8: 64254e4f .word 0x64254e4f + 41dbc: 7832255b .word 0x7832255b + 41dc0: 25203a5d .word 0x25203a5d + 41dc4: 00000a78 .word 0x00000a78 + +00041dc8 <.LC12>: + 41dc8: 32495b0d .word 0x32495b0d + 41dcc: 49202043 .word 0x49202043 + 41dd0: 495d666e .word 0x495d666e + 41dd4: 2074696e .word 0x2074696e + 41dd8: 7473616d .word 0x7473616d + 41ddc: 202c7265 .word 0x202c7265 + 41de0: 545f4349 .word 0x545f4349 + 41de4: 64255241 .word 0x64255241 + 41de8: 7832255b .word 0x7832255b + 41dec: 25203a5d .word 0x25203a5d + 41df0: 00000a78 .word 0x00000a78 + +00041df4 <.LC13>: + 41df4: 32495b0d .word 0x32495b0d + 41df8: 49202043 .word 0x49202043 + 41dfc: 495d666e .word 0x495d666e + 41e00: 2074696e .word 0x2074696e + 41e04: 76616c73 .word 0x76616c73 + 41e08: 49202c65 .word 0x49202c65 + 41e0c: 4f435f43 .word 0x4f435f43 + 41e10: 5b64254e .word 0x5b64254e + 41e14: 5d783225 .word 0x5d783225 + 41e18: 7825203a .word 0x7825203a + 41e1c: 0000000a .word 0x0000000a + +00041e20 <.LC14>: + 41e20: 32495b0d .word 0x32495b0d + 41e24: 49202043 .word 0x49202043 + 41e28: 495d666e .word 0x495d666e + 41e2c: 2074696e .word 0x2074696e + 41e30: 76616c73 .word 0x76616c73 + 41e34: 49202c65 .word 0x49202c65 + 41e38: 41535f43 .word 0x41535f43 + 41e3c: 5b642552 .word 0x5b642552 + 41e40: 5d783225 .word 0x5d783225 + 41e44: 7825203a .word 0x7825203a + 41e48: 0000000a .word 0x0000000a + +00041e4c <.LC15>: + 41e4c: 32495b0d .word 0x32495b0d + 41e50: 49202043 .word 0x49202043 + 41e54: 495d666e .word 0x495d666e + 41e58: 2074696e .word 0x2074696e + 41e5c: 76616c73 .word 0x76616c73 + 41e60: 49202c65 .word 0x49202c65 + 41e64: 495f4332 .word 0x495f4332 + 41e68: 43415f43 .word 0x43415f43 + 41e6c: 43475f4b .word 0x43475f4b + 41e70: 255b6425 .word 0x255b6425 + 41e74: 3a5d7832 .word 0x3a5d7832 + 41e78: 0a782520 .word 0x0a782520 + 41e7c: 00000000 .word 0x00000000 + +00041e80 <.LC16>: + 41e80: 32495b0d .word 0x32495b0d + 41e84: 49202043 .word 0x49202043 + 41e88: 495d666e .word 0x495d666e + 41e8c: 2074696e .word 0x2074696e + 41e90: 20633269 .word 0x20633269 + 41e94: 2c766564 .word 0x2c766564 + 41e98: 43324920 .word 0x43324920 + 41e9c: 5f43495f .word 0x5f43495f + 41ea0: 5f414d44 .word 0x5f414d44 + 41ea4: 524c4454 .word 0x524c4454 + 41ea8: 255b6425 .word 0x255b6425 + 41eac: 3a5d7832 .word 0x3a5d7832 + 41eb0: 0a782520 .word 0x0a782520 + 41eb4: 00000000 .word 0x00000000 + +00041eb8 <.LC17>: + 41eb8: 32495b0d .word 0x32495b0d + 41ebc: 49202043 .word 0x49202043 + 41ec0: 495d666e .word 0x495d666e + 41ec4: 2074696e .word 0x2074696e + 41ec8: 20633269 .word 0x20633269 + 41ecc: 2c766564 .word 0x2c766564 + 41ed0: 43324920 .word 0x43324920 + 41ed4: 5f43495f .word 0x5f43495f + 41ed8: 5f414d44 .word 0x5f414d44 + 41edc: 524c4452 .word 0x524c4452 + 41ee0: 255b6425 .word 0x255b6425 + 41ee4: 3a5d7832 .word 0x3a5d7832 + 41ee8: 0a782520 .word 0x0a782520 + 41eec: 00000000 .word 0x00000000 + +00041ef0 <.LC0>: + 41ef0: 32495b0d .word 0x32495b0d + 41ef4: 49202043 .word 0x49202043 + 41ef8: 485d666e .word 0x485d666e + 41efc: 704f6c61 .word 0x704f6c61 + 41f00: 74696e49 .word 0x74696e49 + 41f04: 61483e2d .word 0x61483e2d + 41f08: 4332496c .word 0x4332496c + 41f0c: 74696e49 .word 0x74696e49 + 41f10: 0a78253a .word 0x0a78253a + 41f14: 00000000 .word 0x00000000 + +00041f18 <.LC1>: + 41f18: 32495b0d .word 0x32495b0d + 41f1c: 49202043 .word 0x49202043 + 41f20: 485d666e .word 0x485d666e + 41f24: 704f6c61 .word 0x704f6c61 + 41f28: 74696e49 .word 0x74696e49 + 41f2c: 61483e2d .word 0x61483e2d + 41f30: 4332496c .word 0x4332496c + 41f34: 6e496544 .word 0x6e496544 + 41f38: 253a7469 .word 0x253a7469 + 41f3c: 00000a78 .word 0x00000a78 + +00041f40 <.LC2>: + 41f40: 32495b0d .word 0x32495b0d + 41f44: 49202043 .word 0x49202043 + 41f48: 485d666e .word 0x485d666e + 41f4c: 704f6c61 .word 0x704f6c61 + 41f50: 74696e49 .word 0x74696e49 + 41f54: 61483e2d .word 0x61483e2d + 41f58: 4332496c .word 0x4332496c + 41f5c: 646e6553 .word 0x646e6553 + 41f60: 0a78253a .word 0x0a78253a + 41f64: 00000000 .word 0x00000000 + +00041f68 <.LC3>: + 41f68: 32495b0d .word 0x32495b0d + 41f6c: 49202043 .word 0x49202043 + 41f70: 485d666e .word 0x485d666e + 41f74: 704f6c61 .word 0x704f6c61 + 41f78: 74696e49 .word 0x74696e49 + 41f7c: 61483e2d .word 0x61483e2d + 41f80: 4332496c .word 0x4332496c + 41f84: 65636552 .word 0x65636552 + 41f88: 3a657669 .word 0x3a657669 + 41f8c: 000a7825 .word 0x000a7825 + +00041f90 <.LC4>: + 41f90: 32495b0d .word 0x32495b0d + 41f94: 49202043 .word 0x49202043 + 41f98: 485d666e .word 0x485d666e + 41f9c: 704f6c61 .word 0x704f6c61 + 41fa0: 74696e49 .word 0x74696e49 + 41fa4: 61483e2d .word 0x61483e2d + 41fa8: 4332496c .word 0x4332496c + 41fac: 62616e45 .word 0x62616e45 + 41fb0: 253a656c .word 0x253a656c + 41fb4: 00000a78 .word 0x00000a78 + +00041fb8 <.LC5>: + 41fb8: 32495b0d .word 0x32495b0d + 41fbc: 49202043 .word 0x49202043 + 41fc0: 485d666e .word 0x485d666e + 41fc4: 704f6c61 .word 0x704f6c61 + 41fc8: 74696e49 .word 0x74696e49 + 41fcc: 61483e2d .word 0x61483e2d + 41fd0: 4332496c .word 0x4332496c + 41fd4: 72746e49 .word 0x72746e49 + 41fd8: 6c727443 .word 0x6c727443 + 41fdc: 0a78253a .word 0x0a78253a + 41fe0: 00000000 .word 0x00000000 + +00041fe4 <.LC6>: + 41fe4: 32495b0d .word 0x32495b0d + 41fe8: 49202043 .word 0x49202043 + 41fec: 485d666e .word 0x485d666e + 41ff0: 704f6c61 .word 0x704f6c61 + 41ff4: 74696e49 .word 0x74696e49 + 41ff8: 61483e2d .word 0x61483e2d + 41ffc: 4332496c .word 0x4332496c + 42000: 64616552 .word 0x64616552 + 42004: 3a676552 .word 0x3a676552 + 42008: 000a7825 .word 0x000a7825 + +0004200c <.LC7>: + 4200c: 32495b0d .word 0x32495b0d + 42010: 49202043 .word 0x49202043 + 42014: 705d666e .word 0x705d666e + 42018: 496c6148 .word 0x496c6148 + 4201c: 704f4332 .word 0x704f4332 + 42020: 61483e2d .word 0x61483e2d + 42024: 4332496c .word 0x4332496c + 42028: 74697257 .word 0x74697257 + 4202c: 67655265 .word 0x67655265 + 42030: 0a78253a .word 0x0a78253a + 42034: 00000000 .word 0x00000000 + +00042038 <.LC8>: + 42038: 32495b0d .word 0x32495b0d + 4203c: 49202043 .word 0x49202043 + 42040: 485d666e .word 0x485d666e + 42044: 704f6c61 .word 0x704f6c61 + 42048: 74696e49 .word 0x74696e49 + 4204c: 61483e2d .word 0x61483e2d + 42050: 4332496c .word 0x4332496c + 42054: 43746553 .word 0x43746553 + 42058: 253a4b4c .word 0x253a4b4c + 4205c: 00000a78 .word 0x00000a78 + +00042060 <.LC9>: + 42060: 32495b0d .word 0x32495b0d + 42064: 49202043 .word 0x49202043 + 42068: 485d666e .word 0x485d666e + 4206c: 704f6c61 .word 0x704f6c61 + 42070: 74696e49 .word 0x74696e49 + 42074: 61483e2d .word 0x61483e2d + 42078: 4332496c .word 0x4332496c + 4207c: 7373614d .word 0x7373614d + 42080: 646e6553 .word 0x646e6553 + 42084: 0a78253a .word 0x0a78253a + 42088: 00000000 .word 0x00000000 + +0004208c <.LC10>: + 4208c: 32495b0d .word 0x32495b0d + 42090: 49202043 .word 0x49202043 + 42094: 485d666e .word 0x485d666e + 42098: 704f6c61 .word 0x704f6c61 + 4209c: 74696e49 .word 0x74696e49 + 420a0: 61483e2d .word 0x61483e2d + 420a4: 4332496c .word 0x4332496c + 420a8: 49726c43 .word 0x49726c43 + 420ac: 3a72746e .word 0x3a72746e + 420b0: 000a7825 .word 0x000a7825 + +000420b4 <.LC11>: + 420b4: 32495b0d .word 0x32495b0d + 420b8: 49202043 .word 0x49202043 + 420bc: 485d666e .word 0x485d666e + 420c0: 704f6c61 .word 0x704f6c61 + 420c4: 74696e49 .word 0x74696e49 + 420c8: 61483e2d .word 0x61483e2d + 420cc: 4332496c .word 0x4332496c + 420d0: 41726c43 .word 0x41726c43 + 420d4: 6e496c6c .word 0x6e496c6c + 420d8: 253a7274 .word 0x253a7274 + 420dc: 00000a78 .word 0x00000a78 + +000420e0 <.LC12>: + 420e0: 32495b0d .word 0x32495b0d + 420e4: 49202043 .word 0x49202043 + 420e8: 485d666e .word 0x485d666e + 420ec: 704f6c61 .word 0x704f6c61 + 420f0: 74696e49 .word 0x74696e49 + 420f4: 61483e2d .word 0x61483e2d + 420f8: 4332496c .word 0x4332496c + 420fc: 43414d44 .word 0x43414d44 + 42100: 3a6c7274 .word 0x3a6c7274 + 42104: 000a7825 .word 0x000a7825 + +00042108 <.LC13>: + 42108: 32495b0d .word 0x32495b0d + 4210c: 57202043 .word 0x57202043 + 42110: 495d6e72 .word 0x495d6e72 + 42114: 64254332 .word 0x64254332 + 42118: 544e4920 .word 0x544e4920 + 4211c: 45475f52 .word 0x45475f52 + 42120: 41435f4e .word 0x41435f4e + 42124: 000a4c4c .word 0x000a4c4c + +00042128 <.LC14>: + 42128: 32495b0d .word 0x32495b0d + 4212c: 57202043 .word 0x57202043 + 42130: 495d6e72 .word 0x495d6e72 + 42134: 64254332 .word 0x64254332 + 42138: 544e4920 .word 0x544e4920 + 4213c: 54535f52 .word 0x54535f52 + 42140: 5f545241 .word 0x5f545241 + 42144: 0a544544 .word 0x0a544544 + 42148: 00000000 .word 0x00000000 + +0004214c <.LC15>: + 4214c: 32495b0d .word 0x32495b0d + 42150: 57202043 .word 0x57202043 + 42154: 495d6e72 .word 0x495d6e72 + 42158: 64254332 .word 0x64254332 + 4215c: 544e4920 .word 0x544e4920 + 42160: 54535f52 .word 0x54535f52 + 42164: 445f504f .word 0x445f504f + 42168: 000a5445 .word 0x000a5445 + +0004216c <.LC16>: + 4216c: 32495b0d .word 0x32495b0d + 42170: 57202043 .word 0x57202043 + 42174: 495d6e72 .word 0x495d6e72 + 42178: 64254332 .word 0x64254332 + 4217c: 544e4920 .word 0x544e4920 + 42180: 43415f52 .word 0x43415f52 + 42184: 49564954 .word 0x49564954 + 42188: 000a5954 .word 0x000a5954 + +0004218c <.LC17>: + 4218c: 32495b0d .word 0x32495b0d + 42190: 45202043 .word 0x45202043 + 42194: 495d7272 .word 0x495d7272 + 42198: 64254332 .word 0x64254332 + 4219c: 544e4920 .word 0x544e4920 + 421a0: 58525f52 .word 0x58525f52 + 421a4: 4e4f445f .word 0x4e4f445f + 421a8: 00000a45 .word 0x00000a45 + +000421ac <.LC18>: + 421ac: 32495b0d .word 0x32495b0d + 421b0: 45202043 .word 0x45202043 + 421b4: 495d7272 .word 0x495d7272 + 421b8: 64254332 .word 0x64254332 + 421bc: 5f434920 .word 0x5f434920 + 421c0: 4c465854 .word 0x4c465854 + 421c4: 32253a52 .word 0x32253a52 + 421c8: 00000a78 .word 0x00000a78 + +000421cc <.LC19>: + 421cc: 32495b0d .word 0x32495b0d + 421d0: 45202043 .word 0x45202043 + 421d4: 215d7272 .word 0x215d7272 + 421d8: 32492121 .word 0x32492121 + 421dc: 20642543 .word 0x20642543 + 421e0: 52544e49 .word 0x52544e49 + 421e4: 5f58545f .word 0x5f58545f + 421e8: 54524241 .word 0x54524241 + 421ec: 0a212121 .word 0x0a212121 + 421f0: 00000000 .word 0x00000000 + +000421f4 <.LC20>: + 421f4: 32495b0d .word 0x32495b0d + 421f8: 45202043 .word 0x45202043 + 421fc: 495d7272 .word 0x495d7272 + 42200: 64254332 .word 0x64254332 + 42204: 5f434920 .word 0x5f434920 + 42208: 415f5854 .word 0x415f5854 + 4220c: 5f545242 .word 0x5f545242 + 42210: 52554f53 .word 0x52554f53 + 42214: 255b4543 .word 0x255b4543 + 42218: 3a5d7832 .word 0x3a5d7832 + 4221c: 0a782520 .word 0x0a782520 + 42220: 00000000 .word 0x00000000 + +00042224 <.LC21>: + 42224: 32495b0d .word 0x32495b0d + 42228: 45202043 .word 0x45202043 + 4222c: 495d7272 .word 0x495d7272 + 42230: 53494332 .word 0x53494332 + 42234: 6e614852 .word 0x6e614852 + 42238: 20656c64 .word 0x20656c64 + 4223c: 656d6954 .word 0x656d6954 + 42240: 2c74756f .word 0x2c74756f + 42244: 25433249 .word 0x25433249 + 42248: 312c7832 .word 0x312c7832 + 4224c: 0000000a .word 0x0000000a + +00042250 <.LC22>: + 42250: 32495b0d .word 0x32495b0d + 42254: 45202043 .word 0x45202043 + 42258: 445d7272 .word 0x445d7272 + 4225c: 74537665 .word 0x74537665 + 42260: 78253a73 .word 0x78253a73 + 42264: 7245202c .word 0x7245202c + 42268: 70795472 .word 0x70795472 + 4226c: 78253a65 .word 0x78253a65 + 42270: 0000000a .word 0x0000000a + +00042274 <.LC23>: + 42274: 32495b0d .word 0x32495b0d + 42278: 45202043 .word 0x45202043 + 4227c: 495d7272 .word 0x495d7272 + 42280: 53494332 .word 0x53494332 + 42284: 6e614852 .word 0x6e614852 + 42288: 20656c64 .word 0x20656c64 + 4228c: 656d6954 .word 0x656d6954 + 42290: 2c74756f .word 0x2c74756f + 42294: 25433249 .word 0x25433249 + 42298: 322c7832 .word 0x322c7832 + 4229c: 0000000a .word 0x0000000a + +000422a0 <.LC24>: + 422a0: 32495b0d .word 0x32495b0d + 422a4: 45202043 .word 0x45202043 + 422a8: 215d7272 .word 0x215d7272 + 422ac: 32492121 .word 0x32492121 + 422b0: 20642543 .word 0x20642543 + 422b4: 52544e49 .word 0x52544e49 + 422b8: 5f58545f .word 0x5f58545f + 422bc: 5245564f .word 0x5245564f + 422c0: 0a212121 .word 0x0a212121 + 422c4: 00000000 .word 0x00000000 + +000422c8 <.LC25>: + 422c8: 32495b0d .word 0x32495b0d + 422cc: 45202043 .word 0x45202043 + 422d0: 495d7272 .word 0x495d7272 + 422d4: 64254332 .word 0x64254332 + 422d8: 544e4920 .word 0x544e4920 + 422dc: 58525f52 .word 0x58525f52 + 422e0: 45564f5f .word 0x45564f5f + 422e4: 00000a52 .word 0x00000a52 + +000422e8 <.LC26>: + 422e8: 32495b0d .word 0x32495b0d + 422ec: 45202043 .word 0x45202043 + 422f0: 215d7272 .word 0x215d7272 + 422f4: 32492121 .word 0x32492121 + 422f8: 20642543 .word 0x20642543 + 422fc: 52544e49 .word 0x52544e49 + 42300: 5f58525f .word 0x5f58525f + 42304: 45444e55 .word 0x45444e55 + 42308: 21212152 .word 0x21212152 + 4230c: 0000000a .word 0x0000000a + +00042310 <.LC27>: + 42310: 32495b0d .word 0x32495b0d + 42314: 49202043 .word 0x49202043 + 42318: 525d666e .word 0x525d666e + 4231c: 32496b74 .word 0x32496b74 + 42320: 71724943 .word 0x71724943 + 42324: 74696e49 .word 0x74696e49 + 42328: 0a3e3e20 .word 0x0a3e3e20 + 4232c: 00000000 .word 0x00000000 + +00042330 <.LC28>: + 42330: 32495b0d .word 0x32495b0d + 42334: 49202043 .word 0x49202043 + 42338: 525d666e .word 0x525d666e + 4233c: 32496b74 .word 0x32496b74 + 42340: 71724943 .word 0x71724943 + 42344: 74696e49 .word 0x74696e49 + 42348: 0a3c3c20 .word 0x0a3c3c20 + 4234c: 00000000 .word 0x00000000 + +00042350 <.LC29>: + 42350: 32495b0d .word 0x32495b0d + 42354: 49202043 .word 0x49202043 + 42358: 525d666e .word 0x525d666e + 4235c: 32496b74 .word 0x32496b74 + 42360: 71724943 .word 0x71724943 + 42364: 6e496544 .word 0x6e496544 + 42368: 3c207469 .word 0x3c207469 + 4236c: 00000a3c .word 0x00000a3c + +00042370 <.LC30>: + 42370: 32495b0d .word 0x32495b0d + 42374: 49202043 .word 0x49202043 + 42378: 525d666e .word 0x525d666e + 4237c: 32496b74 .word 0x32496b74 + 42380: 6e695043 .word 0x6e695043 + 42384: 4978754d .word 0x4978754d + 42388: 2074696e .word 0x2074696e + 4238c: 000a3e3e .word 0x000a3e3e + +00042390 <.LC31>: + 42390: 32495b0d .word 0x32495b0d + 42394: 49202043 .word 0x49202043 + 42398: 525d666e .word 0x525d666e + 4239c: 32496b74 .word 0x32496b74 + 423a0: 6e695043 .word 0x6e695043 + 423a4: 4978754d .word 0x4978754d + 423a8: 2074696e .word 0x2074696e + 423ac: 000a3c3c .word 0x000a3c3c + +000423b0 <.LC32>: + 423b0: 32495b0d .word 0x32495b0d + 423b4: 49202043 .word 0x49202043 + 423b8: 525d666e .word 0x525d666e + 423bc: 32496b74 .word 0x32496b74 + 423c0: 6e695043 .word 0x6e695043 + 423c4: 4478754d .word 0x4478754d + 423c8: 696e4965 .word 0x696e4965 + 423cc: 3e3e2074 .word 0x3e3e2074 + 423d0: 0000000a .word 0x0000000a + +000423d4 <.LC33>: + 423d4: 32495b0d .word 0x32495b0d + 423d8: 49202043 .word 0x49202043 + 423dc: 525d666e .word 0x525d666e + 423e0: 32496b74 .word 0x32496b74 + 423e4: 6e695043 .word 0x6e695043 + 423e8: 4478754d .word 0x4478754d + 423ec: 696e4965 .word 0x696e4965 + 423f0: 3c3c2074 .word 0x3c3c2074 + 423f4: 0000000a .word 0x0000000a + +000423f8 <.LC34>: + 423f8: 32495b0d .word 0x32495b0d + 423fc: 49202043 .word 0x49202043 + 42400: 525d666e .word 0x525d666e + 42404: 32496b74 .word 0x32496b74 + 42408: 414d4443 .word 0x414d4443 + 4240c: 74696e49 .word 0x74696e49 + 42410: 0a3e3e20 .word 0x0a3e3e20 + 42414: 00000000 .word 0x00000000 + +00042418 <.LC35>: + 42418: 32495b0d .word 0x32495b0d + 4241c: 49202043 .word 0x49202043 + 42420: 495d666e .word 0x495d666e + 42424: 3249206e .word 0x3249206e + 42428: 64202c43 .word 0x64202c43 + 4242c: 75616665 .word 0x75616665 + 42430: 4720746c .word 0x4720746c + 42434: 20414d44 .word 0x20414d44 + 42438: 20462f49 .word 0x20462f49 + 4243c: 7070616d .word 0x7070616d + 42440: 5b676e69 .word 0x5b676e69 + 42444: 3a5d7825 .word 0x3a5d7825 + 42448: 0a782520 .word 0x0a782520 + 4244c: 00000000 .word 0x00000000 + +00042450 <.LC36>: + 42450: 32495b0d .word 0x32495b0d + 42454: 49202043 .word 0x49202043 + 42458: 495d666e .word 0x495d666e + 4245c: 3249206e .word 0x3249206e + 42460: 47202c43 .word 0x47202c43 + 42464: 20414d44 .word 0x20414d44 + 42468: 20462f49 .word 0x20462f49 + 4246c: 7070616d .word 0x7070616d + 42470: 5b676e69 .word 0x5b676e69 + 42474: 3a5d7825 .word 0x3a5d7825 + 42478: 0a782520 .word 0x0a782520 + 4247c: 00000000 .word 0x00000000 + +00042480 <.LC37>: + 42480: 32495b0d .word 0x32495b0d + 42484: 49202043 .word 0x49202043 + 42488: 525d666e .word 0x525d666e + 4248c: 32496b74 .word 0x32496b74 + 42490: 414d4443 .word 0x414d4443 + 42494: 74696e49 .word 0x74696e49 + 42498: 0a3c3c20 .word 0x0a3c3c20 + 4249c: 00000000 .word 0x00000000 + +000424a0 <.LC38>: + 424a0: 32495b0d .word 0x32495b0d + 424a4: 49202043 .word 0x49202043 + 424a8: 525d666e .word 0x525d666e + 424ac: 32496b74 .word 0x32496b74 + 424b0: 696e4943 .word 0x696e4943 + 424b4: 3e3e2074 .word 0x3e3e2074 + 424b8: 0000000a .word 0x0000000a + +000424bc <.LC39>: + 424bc: 32495b0d .word 0x32495b0d + 424c0: 49202043 .word 0x49202043 + 424c4: 525d666e .word 0x525d666e + 424c8: 32496b74 .word 0x32496b74 + 424cc: 696e4943 .word 0x696e4943 + 424d0: 3c3c2074 .word 0x3c3c2074 + 424d4: 0000000a .word 0x0000000a + +000424d8 <.LC40>: + 424d8: 32495b0d .word 0x32495b0d + 424dc: 49202043 .word 0x49202043 + 424e0: 525d666e .word 0x525d666e + 424e4: 32496b74 .word 0x32496b74 + 424e8: 414d4443 .word 0x414d4443 + 424ec: 6e496544 .word 0x6e496544 + 424f0: 3e207469 .word 0x3e207469 + 424f4: 00000a3e .word 0x00000a3e + +000424f8 <.LC41>: + 424f8: 32495b0d .word 0x32495b0d + 424fc: 49202043 .word 0x49202043 + 42500: 525d666e .word 0x525d666e + 42504: 32496b74 .word 0x32496b74 + 42508: 414d4443 .word 0x414d4443 + 4250c: 6e496544 .word 0x6e496544 + 42510: 3c207469 .word 0x3c207469 + 42514: 00000a3c .word 0x00000a3c + +00042518 <.LC42>: + 42518: 32495b0d .word 0x32495b0d + 4251c: 49202043 .word 0x49202043 + 42520: 525d666e .word 0x525d666e + 42524: 32496b74 .word 0x32496b74 + 42528: 49654443 .word 0x49654443 + 4252c: 2074696e .word 0x2074696e + 42530: 000a3e3e .word 0x000a3e3e + +00042534 <.LC43>: + 42534: 32495b0d .word 0x32495b0d + 42538: 49202043 .word 0x49202043 + 4253c: 525d666e .word 0x525d666e + 42540: 32496b74 .word 0x32496b74 + 42544: 49654443 .word 0x49654443 + 42548: 2074696e .word 0x2074696e + 4254c: 000a3c3c .word 0x000a3c3c + +00042550 <.LC44>: + 42550: 32495b0d .word 0x32495b0d + 42554: 45202043 .word 0x45202043 + 42558: 525d7272 .word 0x525d7272 + 4255c: 32496b74 .word 0x32496b74 + 42560: 6e655343 .word 0x6e655343 + 42564: 65735564 .word 0x65735564 + 42568: 64644172 .word 0x64644172 + 4256c: 69542072 .word 0x69542072 + 42570: 756f656d .word 0x756f656d + 42574: 32492c74 .word 0x32492c74 + 42578: 78322543 .word 0x78322543 + 4257c: 000a312c .word 0x000a312c + +00042580 <.LC45>: + 42580: 32495b0d .word 0x32495b0d + 42584: 45202043 .word 0x45202043 + 42588: 525d7272 .word 0x525d7272 + 4258c: 32496b74 .word 0x32496b74 + 42590: 6e655343 .word 0x6e655343 + 42594: 65735564 .word 0x65735564 + 42598: 64644172 .word 0x64644172 + 4259c: 69542072 .word 0x69542072 + 425a0: 756f656d .word 0x756f656d + 425a4: 49202c74 .word 0x49202c74 + 425a8: 32254332 .word 0x32254332 + 425ac: 0a322c78 .word 0x0a322c78 + 425b0: 00000000 .word 0x00000000 + +000425b4 <.LC46>: + 425b4: 32495b0d .word 0x32495b0d + 425b8: 45202043 .word 0x45202043 + 425bc: 525d7272 .word 0x525d7272 + 425c0: 32496b74 .word 0x32496b74 + 425c4: 6e655343 .word 0x6e655343 + 425c8: 69542064 .word 0x69542064 + 425cc: 756f656d .word 0x756f656d + 425d0: 49202c74 .word 0x49202c74 + 425d4: 32254332 .word 0x32254332 + 425d8: 0a312c78 .word 0x0a312c78 + 425dc: 00000000 .word 0x00000000 + +000425e0 <.LC47>: + 425e0: 32495b0d .word 0x32495b0d + 425e4: 45202043 .word 0x45202043 + 425e8: 525d7272 .word 0x525d7272 + 425ec: 32496b74 .word 0x32496b74 + 425f0: 6e655343 .word 0x6e655343 + 425f4: 69542064 .word 0x69542064 + 425f8: 756f656d .word 0x756f656d + 425fc: 49202c74 .word 0x49202c74 + 42600: 32254332 .word 0x32254332 + 42604: 0a322c78 .word 0x0a322c78 + 42608: 00000000 .word 0x00000000 + +0004260c <.LC48>: + 4260c: 32495b0d .word 0x32495b0d + 42610: 45202043 .word 0x45202043 + 42614: 525d7272 .word 0x525d7272 + 42618: 32496b74 .word 0x32496b74 + 4261c: 6e655343 .word 0x6e655343 + 42620: 69542064 .word 0x69542064 + 42624: 756f656d .word 0x756f656d + 42628: 49202c74 .word 0x49202c74 + 4262c: 32254332 .word 0x32254332 + 42630: 0a332c78 .word 0x0a332c78 + 42634: 00000000 .word 0x00000000 + +00042638 <.LC49>: + 42638: 32495b0d .word 0x32495b0d + 4263c: 45202043 .word 0x45202043 + 42640: 525d7272 .word 0x525d7272 + 42644: 32496b74 .word 0x32496b74 + 42648: 6e655343 .word 0x6e655343 + 4264c: 69542064 .word 0x69542064 + 42650: 756f656d .word 0x756f656d + 42654: 49202c74 .word 0x49202c74 + 42658: 32254332 .word 0x32254332 + 4265c: 0a342c78 .word 0x0a342c78 + 42660: 00000000 .word 0x00000000 + +00042664 <.LC50>: + 42664: 32495b0d .word 0x32495b0d + 42668: 45202043 .word 0x45202043 + 4266c: 525d7272 .word 0x525d7272 + 42670: 32496b74 .word 0x32496b74 + 42674: 6e655343 .word 0x6e655343 + 42678: 69542064 .word 0x69542064 + 4267c: 756f656d .word 0x756f656d + 42680: 49202c74 .word 0x49202c74 + 42684: 32254332 .word 0x32254332 + 42688: 0a352c78 .word 0x0a352c78 + 4268c: 00000000 .word 0x00000000 + +00042690 <.LC51>: + 42690: 32495b0d .word 0x32495b0d + 42694: 45202043 .word 0x45202043 + 42698: 525d7272 .word 0x525d7272 + 4269c: 32496b74 .word 0x32496b74 + 426a0: 6e655343 .word 0x6e655343 + 426a4: 69542064 .word 0x69542064 + 426a8: 756f656d .word 0x756f656d + 426ac: 49202c74 .word 0x49202c74 + 426b0: 32254332 .word 0x32254332 + 426b4: 0a362c78 .word 0x0a362c78 + 426b8: 00000000 .word 0x00000000 + +000426bc <.LC52>: + 426bc: 32495b0d .word 0x32495b0d + 426c0: 45202043 .word 0x45202043 + 426c4: 525d7272 .word 0x525d7272 + 426c8: 32496b74 .word 0x32496b74 + 426cc: 6e655343 .word 0x6e655343 + 426d0: 69542064 .word 0x69542064 + 426d4: 756f656d .word 0x756f656d + 426d8: 49202c74 .word 0x49202c74 + 426dc: 32254332 .word 0x32254332 + 426e0: 0a372c78 .word 0x0a372c78 + 426e4: 00000000 .word 0x00000000 + +000426e8 <.LC53>: + 426e8: 32495b0d .word 0x32495b0d + 426ec: 45202043 .word 0x45202043 + 426f0: 525d7272 .word 0x525d7272 + 426f4: 32496b74 .word 0x32496b74 + 426f8: 6e655343 .word 0x6e655343 + 426fc: 69542064 .word 0x69542064 + 42700: 756f656d .word 0x756f656d + 42704: 49202c74 .word 0x49202c74 + 42708: 32254332 .word 0x32254332 + 4270c: 0a382c78 .word 0x0a382c78 + 42710: 00000000 .word 0x00000000 + +00042714 <.LC54>: + 42714: 32495b0d .word 0x32495b0d + 42718: 45202043 .word 0x45202043 + 4271c: 525d7272 .word 0x525d7272 + 42720: 32496b74 .word 0x32496b74 + 42724: 6e655343 .word 0x6e655343 + 42728: 69542064 .word 0x69542064 + 4272c: 756f656d .word 0x756f656d + 42730: 49202c74 .word 0x49202c74 + 42734: 32254332 .word 0x32254332 + 42738: 0a392c78 .word 0x0a392c78 + 4273c: 00000000 .word 0x00000000 + +00042740 <.LC55>: + 42740: 32495b0d .word 0x32495b0d + 42744: 45202043 .word 0x45202043 + 42748: 525d7272 .word 0x525d7272 + 4274c: 32496b74 .word 0x32496b74 + 42750: 6e655343 .word 0x6e655343 + 42754: 69542064 .word 0x69542064 + 42758: 756f656d .word 0x756f656d + 4275c: 49202c74 .word 0x49202c74 + 42760: 32254332 .word 0x32254332 + 42764: 30312c78 .word 0x30312c78 + 42768: 0000000a .word 0x0000000a + +0004276c <.LC56>: + 4276c: 32495b0d .word 0x32495b0d + 42770: 45202043 .word 0x45202043 + 42774: 525d7272 .word 0x525d7272 + 42778: 32496b74 .word 0x32496b74 + 4277c: 63655243 .word 0x63655243 + 42780: 65766965 .word 0x65766965 + 42784: 6d695420 .word 0x6d695420 + 42788: 74756f65 .word 0x74756f65 + 4278c: 3249202c .word 0x3249202c + 42790: 78322543 .word 0x78322543 + 42794: 000a312c .word 0x000a312c + +00042798 <.LC57>: + 42798: 32495b0d .word 0x32495b0d + 4279c: 45202043 .word 0x45202043 + 427a0: 525d7272 .word 0x525d7272 + 427a4: 32496b74 .word 0x32496b74 + 427a8: 63655243 .word 0x63655243 + 427ac: 65766965 .word 0x65766965 + 427b0: 6d695420 .word 0x6d695420 + 427b4: 74756f65 .word 0x74756f65 + 427b8: 3249202c .word 0x3249202c + 427bc: 78322543 .word 0x78322543 + 427c0: 000a322c .word 0x000a322c + +000427c4 <.LC58>: + 427c4: 32495b0d .word 0x32495b0d + 427c8: 45202043 .word 0x45202043 + 427cc: 525d7272 .word 0x525d7272 + 427d0: 32496b74 .word 0x32496b74 + 427d4: 63655243 .word 0x63655243 + 427d8: 65766965 .word 0x65766965 + 427dc: 6d695420 .word 0x6d695420 + 427e0: 74756f65 .word 0x74756f65 + 427e4: 3249202c .word 0x3249202c + 427e8: 78322543 .word 0x78322543 + 427ec: 000a332c .word 0x000a332c + +000427f0 <.LC59>: + 427f0: 32495b0d .word 0x32495b0d + 427f4: 45202043 .word 0x45202043 + 427f8: 525d7272 .word 0x525d7272 + 427fc: 32496b74 .word 0x32496b74 + 42800: 63655243 .word 0x63655243 + 42804: 65766965 .word 0x65766965 + 42808: 6d695420 .word 0x6d695420 + 4280c: 74756f65 .word 0x74756f65 + 42810: 3249202c .word 0x3249202c + 42814: 78322543 .word 0x78322543 + 42818: 000a342c .word 0x000a342c + +0004281c <.LC60>: + 4281c: 32495b0d .word 0x32495b0d + 42820: 45202043 .word 0x45202043 + 42824: 525d7272 .word 0x525d7272 + 42828: 32496b74 .word 0x32496b74 + 4282c: 63655243 .word 0x63655243 + 42830: 65766965 .word 0x65766965 + 42834: 6d695420 .word 0x6d695420 + 42838: 74756f65 .word 0x74756f65 + 4283c: 3249202c .word 0x3249202c + 42840: 78322543 .word 0x78322543 + 42844: 000a352c .word 0x000a352c + +00042848 <.LC61>: + 42848: 32495b0d .word 0x32495b0d + 4284c: 45202043 .word 0x45202043 + 42850: 525d7272 .word 0x525d7272 + 42854: 32496b74 .word 0x32496b74 + 42858: 63655243 .word 0x63655243 + 4285c: 65766965 .word 0x65766965 + 42860: 6d695420 .word 0x6d695420 + 42864: 74756f65 .word 0x74756f65 + 42868: 3249202c .word 0x3249202c + 4286c: 78322543 .word 0x78322543 + 42870: 000a362c .word 0x000a362c + +00042874 <.LC62>: + 42874: 32495b0d .word 0x32495b0d + 42878: 45202043 .word 0x45202043 + 4287c: 525d7272 .word 0x525d7272 + 42880: 32496b74 .word 0x32496b74 + 42884: 63655243 .word 0x63655243 + 42888: 65766965 .word 0x65766965 + 4288c: 6d695420 .word 0x6d695420 + 42890: 74756f65 .word 0x74756f65 + 42894: 3249202c .word 0x3249202c + 42898: 78322543 .word 0x78322543 + 4289c: 000a372c .word 0x000a372c + +000428a0 <.LC63>: + 428a0: 32495b0d .word 0x32495b0d + 428a4: 45202043 .word 0x45202043 + 428a8: 525d7272 .word 0x525d7272 + 428ac: 32496b74 .word 0x32496b74 + 428b0: 63655243 .word 0x63655243 + 428b4: 65766965 .word 0x65766965 + 428b8: 6d695420 .word 0x6d695420 + 428bc: 74756f65 .word 0x74756f65 + 428c0: 3249202c .word 0x3249202c + 428c4: 78322543 .word 0x78322543 + 428c8: 000a382c .word 0x000a382c + +000428cc <.LC64>: + 428cc: 32495b0d .word 0x32495b0d + 428d0: 45202043 .word 0x45202043 + 428d4: 525d7272 .word 0x525d7272 + 428d8: 32496b74 .word 0x32496b74 + 428dc: 63655243 .word 0x63655243 + 428e0: 65766965 .word 0x65766965 + 428e4: 6d695420 .word 0x6d695420 + 428e8: 74756f65 .word 0x74756f65 + 428ec: 3249202c .word 0x3249202c + 428f0: 78322543 .word 0x78322543 + 428f4: 000a392c .word 0x000a392c + +000428f8 <.LC65>: + 428f8: 32495b0d .word 0x32495b0d + 428fc: 45202043 .word 0x45202043 + 42900: 525d7272 .word 0x525d7272 + 42904: 32496b74 .word 0x32496b74 + 42908: 63655243 .word 0x63655243 + 4290c: 65766965 .word 0x65766965 + 42910: 6d695420 .word 0x6d695420 + 42914: 74756f65 .word 0x74756f65 + 42918: 3249202c .word 0x3249202c + 4291c: 78322543 .word 0x78322543 + 42920: 0a30312c .word 0x0a30312c + 42924: 00000000 .word 0x00000000 + +00042928 <.LC0>: + 42928: 50475b0d .word 0x50475b0d + 4292c: 57204f49 .word 0x57204f49 + 42930: 475d6e72 .word 0x475d6e72 + 42934: 5f4f4950 .word 0x5f4f4950 + 42938: 49746547 .word 0x49746547 + 4293c: 6e695050 .word 0x6e695050 + 42940: 656d614e .word 0x656d614e + 42944: 3931385f .word 0x3931385f + 42948: 203a6135 .word 0x203a6135 + 4294c: 6e6e6143 .word 0x6e6e6143 + 42950: 6620746f .word 0x6620746f + 42954: 20646e69 .word 0x20646e69 + 42958: 206e6970 .word 0x206e6970 + 4295c: 20726f66 .word 0x20726f66 + 42960: 4f495047 .word 0x4f495047 + 42964: 0a642520 .word 0x0a642520 + 42968: 00000000 .word 0x00000000 + +0004296c <.LC1>: + 4296c: 50475b0d .word 0x50475b0d + 42970: 57204f49 .word 0x57204f49 + 42974: 475d6e72 .word 0x475d6e72 + 42978: 5f4f4950 .word 0x5f4f4950 + 4297c: 43746547 .word 0x43746547 + 42980: 50706968 .word 0x50706968 + 42984: 614e6e69 .word 0x614e6e69 + 42988: 385f656d .word 0x385f656d + 4298c: 61353931 .word 0x61353931 + 42990: 6143203a .word 0x6143203a + 42994: 746f6e6e .word 0x746f6e6e + 42998: 6e696620 .word 0x6e696620 + 4299c: 69702064 .word 0x69702064 + 429a0: 6f66206e .word 0x6f66206e + 429a4: 6f702072 .word 0x6f702072 + 429a8: 253a7472 .word 0x253a7472 + 429ac: 69702064 .word 0x69702064 + 429b0: 64253a6e .word 0x64253a6e + 429b4: 0000000a .word 0x0000000a + +000429b8 <.LC2>: + 429b8: 50475b0d .word 0x50475b0d + 429bc: 57204f49 .word 0x57204f49 + 429c0: 475d6e72 .word 0x475d6e72 + 429c4: 5f4f4950 .word 0x5f4f4950 + 429c8: 6c6c7550 .word 0x6c6c7550 + 429cc: 6c727443 .word 0x6c727443 + 429d0: 3931385f .word 0x3931385f + 429d4: 203a6135 .word 0x203a6135 + 429d8: 6e6e6143 .word 0x6e6e6143 + 429dc: 6620746f .word 0x6620746f + 429e0: 20646e69 .word 0x20646e69 + 429e4: 206e6970 .word 0x206e6970 + 429e8: 30257830 .word 0x30257830 + 429ec: 000a7832 .word 0x000a7832 + +000429f0 <.LC3>: + 429f0: 50475b0d .word 0x50475b0d + 429f4: 49204f49 .word 0x49204f49 + 429f8: 475d666e .word 0x475d666e + 429fc: 5f4f4950 .word 0x5f4f4950 + 42a00: 636e7546 .word 0x636e7546 + 42a04: 385f6e4f .word 0x385f6e4f + 42a08: 61353931 .word 0x61353931 + 42a0c: 000a2121 .word 0x000a2121 + +00042a10 <.LC4>: + 42a10: 50475b0d .word 0x50475b0d + 42a14: 49204f49 .word 0x49204f49 + 42a18: 475d666e .word 0x475d666e + 42a1c: 5f4f4950 .word 0x5f4f4950 + 42a20: 636e7546 .word 0x636e7546 + 42a24: 5f66664f .word 0x5f66664f + 42a28: 35393138 .word 0x35393138 + 42a2c: 0a212161 .word 0x0a212161 + 42a30: 00000000 .word 0x00000000 + +00042a34 <.LC5>: + 42a34: 50475b0d .word 0x50475b0d + 42a38: 45204f49 .word 0x45204f49 + 42a3c: 555d7272 .word 0x555d7272 + 42a40: 6f6e6b6e .word 0x6f6e6b6e + 42a44: 6e492077 .word 0x6e492077 + 42a48: 72726574 .word 0x72726574 + 42a4c: 20747075 .word 0x20747075 + 42a50: 67697254 .word 0x67697254 + 42a54: 20726567 .word 0x20726567 + 42a58: 65707954 .word 0x65707954 + 42a5c: 29642528 .word 0x29642528 + 42a60: 0000000a .word 0x0000000a + +00042a64 <.LC6>: + 42a64: 50475b0d .word 0x50475b0d + 42a68: 49204f49 .word 0x49204f49 + 42a6c: 475d666e .word 0x475d666e + 42a70: 5f4f4950 .word 0x5f4f4950 + 42a74: 5f746e49 .word 0x5f746e49 + 42a78: 54746553 .word 0x54746553 + 42a7c: 5f657079 .word 0x5f657079 + 42a80: 35393138 .word 0x35393138 + 42a84: 6c203a61 .word 0x6c203a61 + 42a88: 6c657665 .word 0x6c657665 + 42a8c: 6764655f .word 0x6764655f + 42a90: 64253d65 .word 0x64253d65 + 42a94: 6c6f7020 .word 0x6c6f7020 + 42a98: 74697261 .word 0x74697261 + 42a9c: 64253d79 .word 0x64253d79 + 42aa0: 0000000a .word 0x0000000a + +00042aa4 <.LC7>: + 42aa4: 50475b0d .word 0x50475b0d + 42aa8: 49204f49 .word 0x49204f49 + 42aac: 475d666e .word 0x475d666e + 42ab0: 204f4950 .word 0x204f4950 + 42ab4: 57676552 .word 0x57676552 + 42ab8: 65746972 .word 0x65746972 + 42abc: 6552203a .word 0x6552203a + 42ac0: 78305b67 .word 0x78305b67 + 42ac4: 205d7825 .word 0x205d7825 + 42ac8: 7830203d .word 0x7830203d + 42acc: 000a7825 .word 0x000a7825 + +00042ad0 <.LC8>: + 42ad0: 50475b0d .word 0x50475b0d + 42ad4: 45204f49 .word 0x45204f49 + 42ad8: 485d7272 .word 0x485d7272 + 42adc: 475f4c41 .word 0x475f4c41 + 42ae0: 5f4f4950 .word 0x5f4f4950 + 42ae4: 43746e49 .word 0x43746e49 + 42ae8: 5f6c7274 .word 0x5f6c7274 + 42aec: 35393138 .word 0x35393138 + 42af0: 54203a61 .word 0x54203a61 + 42af4: 20736968 .word 0x20736968 + 42af8: 286e6970 .word 0x286e6970 + 42afc: 253a7825 .word 0x253a7825 + 42b00: 69202978 .word 0x69202978 + 42b04: 746e2773 .word 0x746e2773 + 42b08: 206e6120 .word 0x206e6120 + 42b0c: 65746e69 .word 0x65746e69 + 42b10: 70757272 .word 0x70757272 + 42b14: 69702074 .word 0x69702074 + 42b18: 00000a6e .word 0x00000a6e + +00042b1c <.LC9>: + 42b1c: 50475b0d .word 0x50475b0d + 42b20: 49204f49 .word 0x49204f49 + 42b24: 485d666e .word 0x485d666e + 42b28: 475f4c41 .word 0x475f4c41 + 42b2c: 5f4f4950 .word 0x5f4f4950 + 42b30: 43746e49 .word 0x43746e49 + 42b34: 5f6c7274 .word 0x5f6c7274 + 42b38: 35393138 .word 0x35393138 + 42b3c: 70203a61 .word 0x70203a61 + 42b40: 5f74726f .word 0x5f74726f + 42b44: 3d6d756e .word 0x3d6d756e + 42b48: 70206425 .word 0x70206425 + 42b4c: 6e5f6e69 .word 0x6e5f6e69 + 42b50: 253d6d75 .word 0x253d6d75 + 42b54: 69702064 .word 0x69702064 + 42b58: 6f6d5f6e .word 0x6f6d5f6e + 42b5c: 253d6564 .word 0x253d6564 + 42b60: 00000a64 .word 0x00000a64 + +00042b64 <.LC10>: + 42b64: 50475b0d .word 0x50475b0d + 42b68: 45204f49 .word 0x45204f49 + 42b6c: 455d7272 .word 0x455d7272 + 42b70: 203a7272 .word 0x203a7272 + 42b74: 4f495047 .word 0x4f495047 + 42b78: 61644120 .word 0x61644120 + 42b7c: 72657470 .word 0x72657470 + 42b80: 746f4e20 .word 0x746f4e20 + 42b84: 696e4920 .word 0x696e4920 + 42b88: 6c616974 .word 0x6c616974 + 42b8c: 000a6465 .word 0x000a6465 + +00042b90 <.LC11>: + 42b90: 50475b0d .word 0x50475b0d + 42b94: 49204f49 .word 0x49204f49 + 42b98: 485d666e .word 0x485d666e + 42b9c: 475f4c41 .word 0x475f4c41 + 42ba0: 5f4f4950 .word 0x5f4f4950 + 42ba4: 74696e49 .word 0x74696e49 + 42ba8: 3931385f .word 0x3931385f + 42bac: 203a6135 .word 0x203a6135 + 42bb0: 4f495047 .word 0x4f495047 + 42bb4: 6d616e28 .word 0x6d616e28 + 42bb8: 78303d65 .word 0x78303d65 + 42bbc: 28297825 .word 0x28297825 + 42bc0: 65646f6d .word 0x65646f6d + 42bc4: 2964253d .word 0x2964253d + 42bc8: 0000200a .word 0x0000200a + +00042bcc <.LC12>: + 42bcc: 50475b0d .word 0x50475b0d + 42bd0: 45204f49 .word 0x45204f49 + 42bd4: 4f5d7272 .word 0x4f5d7272 + 42bd8: 20796c6e .word 0x20796c6e + 42bdc: 4f495047 .word 0x4f495047 + 42be0: 524f5020 .word 0x524f5020 + 42be4: 20415f54 .word 0x20415f54 + 42be8: 206e6163 .word 0x206e6163 + 42bec: 49206562 .word 0x49206562 + 42bf0: 7265746e .word 0x7265746e + 42bf4: 74707572 .word 0x74707572 + 42bf8: 756f5320 .word 0x756f5320 + 42bfc: 0a656372 .word 0x0a656372 + 42c00: 00000000 .word 0x00000000 + +00042c04 <.LC13>: + 42c04: 50475b0d .word 0x50475b0d + 42c08: 57204f49 .word 0x57204f49 + 42c0c: 485d6e72 .word 0x485d6e72 + 42c10: 475f4c41 .word 0x475f4c41 + 42c14: 5f4f4950 .word 0x5f4f4950 + 42c18: 74696e49 .word 0x74696e49 + 42c1c: 3931385f .word 0x3931385f + 42c20: 203a6135 .word 0x203a6135 + 42c24: 6b636f4c .word 0x6b636f4c + 42c28: 69614620 .word 0x69614620 + 42c2c: 0a64656c .word 0x0a64656c + 42c30: 00000000 .word 0x00000000 + +00042c34 <.LC14>: + 42c34: 50475b0d .word 0x50475b0d + 42c38: 45204f49 .word 0x45204f49 + 42c3c: 485d7272 .word 0x485d7272 + 42c40: 475f4c41 .word 0x475f4c41 + 42c44: 5f4f4950 .word 0x5f4f4950 + 42c48: 74696e49 .word 0x74696e49 + 42c4c: 3931385f .word 0x3931385f + 42c50: 203a6135 .word 0x203a6135 + 42c54: 6e6b6e55 .word 0x6e6b6e55 + 42c58: 206e776f .word 0x206e776f + 42c5c: 206e6950 .word 0x206e6950 + 42c60: 65646f6d .word 0x65646f6d + 42c64: 29642528 .word 0x29642528 + 42c68: 0000000a .word 0x0000000a + +00042c6c <.LC15>: + 42c6c: 50475b0d .word 0x50475b0d + 42c70: 49204f49 .word 0x49204f49 + 42c74: 485d666e .word 0x485d666e + 42c78: 475f4c41 .word 0x475f4c41 + 42c7c: 5f4f4950 .word 0x5f4f4950 + 42c80: 6e496544 .word 0x6e496544 + 42c84: 385f7469 .word 0x385f7469 + 42c88: 61353931 .word 0x61353931 + 42c8c: 5047203a .word 0x5047203a + 42c90: 6e284f49 .word 0x6e284f49 + 42c94: 3d656d61 .word 0x3d656d61 + 42c98: 78257830 .word 0x78257830 + 42c9c: 6f6d2829 .word 0x6f6d2829 + 42ca0: 253d6564 .word 0x253d6564 + 42ca4: 200a2964 .word 0x200a2964 + 42ca8: 00000000 .word 0x00000000 + +00042cac <.LC16>: + 42cac: 50475b0d .word 0x50475b0d + 42cb0: 57204f49 .word 0x57204f49 + 42cb4: 485d6e72 .word 0x485d6e72 + 42cb8: 475f4c41 .word 0x475f4c41 + 42cbc: 5f4f4950 .word 0x5f4f4950 + 42cc0: 64616552 .word 0x64616552 + 42cc4: 5f6e6950 .word 0x5f6e6950 + 42cc8: 35393138 .word 0x35393138 + 42ccc: 4c203a61 .word 0x4c203a61 + 42cd0: 206b636f .word 0x206b636f + 42cd4: 6c696146 .word 0x6c696146 + 42cd8: 000a6465 .word 0x000a6465 + +00042cdc <.LC17>: + 42cdc: 50475b0d .word 0x50475b0d + 42ce0: 57204f49 .word 0x57204f49 + 42ce4: 485d6e72 .word 0x485d6e72 + 42ce8: 475f4c41 .word 0x475f4c41 + 42cec: 5f4f4950 .word 0x5f4f4950 + 42cf0: 74697257 .word 0x74697257 + 42cf4: 6e695065 .word 0x6e695065 + 42cf8: 3931385f .word 0x3931385f + 42cfc: 203a6135 .word 0x203a6135 + 42d00: 6b636f4c .word 0x6b636f4c + 42d04: 69614620 .word 0x69614620 + 42d08: 0a64656c .word 0x0a64656c + 42d0c: 00000000 .word 0x00000000 + +00042d10 <.LC18>: + 42d10: 50475b0d .word 0x50475b0d + 42d14: 45204f49 .word 0x45204f49 + 42d18: 525d7272 .word 0x525d7272 + 42d1c: 73696765 .word 0x73696765 + 42d20: 20726574 .word 0x20726574 + 42d24: 46717249 .word 0x46717249 + 42d28: 69206e75 .word 0x69206e75 + 42d2c: 754e2073 .word 0x754e2073 + 42d30: 000a6c6c .word 0x000a6c6c + +00042d34 <.LC19>: + 42d34: 50475b0d .word 0x50475b0d + 42d38: 45204f49 .word 0x45204f49 + 42d3c: 485d7272 .word 0x485d7272 + 42d40: 475f4c41 .word 0x475f4c41 + 42d44: 5f4f4950 .word 0x5f4f4950 + 42d48: 72657355 .word 0x72657355 + 42d4c: 49676552 .word 0x49676552 + 42d50: 385f7172 .word 0x385f7172 + 42d54: 61353931 .word 0x61353931 + 42d58: 6854203a .word 0x6854203a + 42d5c: 70207369 .word 0x70207369 + 42d60: 25286e69 .word 0x25286e69 + 42d64: 78253a78 .word 0x78253a78 + 42d68: 73692029 .word 0x73692029 + 42d6c: 20746e27 .word 0x20746e27 + 42d70: 69206e61 .word 0x69206e61 + 42d74: 7265746e .word 0x7265746e + 42d78: 74707572 .word 0x74707572 + 42d7c: 6e697020 .word 0x6e697020 + 42d80: 0000000a .word 0x0000000a + +00042d84 <.LC20>: + 42d84: 50475b0d .word 0x50475b0d + 42d88: 57204f49 .word 0x57204f49 + 42d8c: 485d6e72 .word 0x485d6e72 + 42d90: 475f4c41 .word 0x475f4c41 + 42d94: 5f4f4950 .word 0x5f4f4950 + 42d98: 72657355 .word 0x72657355 + 42d9c: 49676552 .word 0x49676552 + 42da0: 385f7172 .word 0x385f7172 + 42da4: 61353931 .word 0x61353931 + 42da8: 6f4c203a .word 0x6f4c203a + 42dac: 46206b63 .word 0x46206b63 + 42db0: 656c6961 .word 0x656c6961 + 42db4: 00000a64 .word 0x00000a64 + +00042db8 <.LC21>: + 42db8: 50475b0d .word 0x50475b0d + 42dbc: 45204f49 .word 0x45204f49 + 42dc0: 485d7272 .word 0x485d7272 + 42dc4: 475f4c41 .word 0x475f4c41 + 42dc8: 5f4f4950 .word 0x5f4f4950 + 42dcc: 72657355 .word 0x72657355 + 42dd0: 65526e55 .word 0x65526e55 + 42dd4: 71724967 .word 0x71724967 + 42dd8: 3931385f .word 0x3931385f + 42ddc: 203a6135 .word 0x203a6135 + 42de0: 73696854 .word 0x73696854 + 42de4: 6e697020 .word 0x6e697020 + 42de8: 3a782528 .word 0x3a782528 + 42dec: 20297825 .word 0x20297825 + 42df0: 6e277369 .word 0x6e277369 + 42df4: 6e612074 .word 0x6e612074 + 42df8: 746e6920 .word 0x746e6920 + 42dfc: 75727265 .word 0x75727265 + 42e00: 70207470 .word 0x70207470 + 42e04: 000a6e69 .word 0x000a6e69 + +00042e08 <.LC22>: + 42e08: 50475b0d .word 0x50475b0d + 42e0c: 57204f49 .word 0x57204f49 + 42e10: 485d6e72 .word 0x485d6e72 + 42e14: 475f4c41 .word 0x475f4c41 + 42e18: 5f4f4950 .word 0x5f4f4950 + 42e1c: 72657355 .word 0x72657355 + 42e20: 65526e55 .word 0x65526e55 + 42e24: 71724967 .word 0x71724967 + 42e28: 3931385f .word 0x3931385f + 42e2c: 203a6135 .word 0x203a6135 + 42e30: 6b636f4c .word 0x6b636f4c + 42e34: 69614620 .word 0x69614620 + 42e38: 0a64656c .word 0x0a64656c + 42e3c: 00000000 .word 0x00000000 + +00042e40 <.LC23>: + 42e40: 50475b0d .word 0x50475b0d + 42e44: 45204f49 .word 0x45204f49 + 42e48: 485d7272 .word 0x485d7272 + 42e4c: 475f4c41 .word 0x475f4c41 + 42e50: 5f4f4950 .word 0x5f4f4950 + 42e54: 6b73614d .word 0x6b73614d + 42e58: 5f717249 .word 0x5f717249 + 42e5c: 35393138 .word 0x35393138 + 42e60: 54203a61 .word 0x54203a61 + 42e64: 20736968 .word 0x20736968 + 42e68: 286e6970 .word 0x286e6970 + 42e6c: 253a7825 .word 0x253a7825 + 42e70: 69202978 .word 0x69202978 + 42e74: 746e2773 .word 0x746e2773 + 42e78: 206e6120 .word 0x206e6120 + 42e7c: 65746e69 .word 0x65746e69 + 42e80: 70757272 .word 0x70757272 + 42e84: 69702074 .word 0x69702074 + 42e88: 00000a6e .word 0x00000a6e + +00042e8c <.LC24>: + 42e8c: 50475b0d .word 0x50475b0d + 42e90: 45204f49 .word 0x45204f49 + 42e94: 485d7272 .word 0x485d7272 + 42e98: 475f4c41 .word 0x475f4c41 + 42e9c: 5f4f4950 .word 0x5f4f4950 + 42ea0: 614d6e55 .word 0x614d6e55 + 42ea4: 72496b73 .word 0x72496b73 + 42ea8: 31385f71 .word 0x31385f71 + 42eac: 3a613539 .word 0x3a613539 + 42eb0: 69685420 .word 0x69685420 + 42eb4: 69702073 .word 0x69702073 + 42eb8: 7825286e .word 0x7825286e + 42ebc: 2978253a .word 0x2978253a + 42ec0: 27736920 .word 0x27736920 + 42ec4: 6120746e .word 0x6120746e + 42ec8: 6e69206e .word 0x6e69206e + 42ecc: 72726574 .word 0x72726574 + 42ed0: 20747075 .word 0x20747075 + 42ed4: 0a6e6970 .word 0x0a6e6970 + 42ed8: 00000000 .word 0x00000000 + +00042edc <.LC25>: + 42edc: 50475b0d .word 0x50475b0d + 42ee0: 45204f49 .word 0x45204f49 + 42ee4: 485d7272 .word 0x485d7272 + 42ee8: 475f4c41 .word 0x475f4c41 + 42eec: 5f4f4950 .word 0x5f4f4950 + 42ef0: 44746e49 .word 0x44746e49 + 42ef4: 756f6265 .word 0x756f6265 + 42ef8: 5f65636e .word 0x5f65636e + 42efc: 35393138 .word 0x35393138 + 42f00: 54203a61 .word 0x54203a61 + 42f04: 20736968 .word 0x20736968 + 42f08: 286e6970 .word 0x286e6970 + 42f0c: 253a7825 .word 0x253a7825 + 42f10: 69202978 .word 0x69202978 + 42f14: 746e2773 .word 0x746e2773 + 42f18: 206e6120 .word 0x206e6120 + 42f1c: 65746e69 .word 0x65746e69 + 42f20: 70757272 .word 0x70757272 + 42f24: 69702074 .word 0x69702074 + 42f28: 00000a6e .word 0x00000a6e + +00042f2c <.LC26>: + 42f2c: 50475b0d .word 0x50475b0d + 42f30: 57204f49 .word 0x57204f49 + 42f34: 485d6e72 .word 0x485d6e72 + 42f38: 475f4c41 .word 0x475f4c41 + 42f3c: 5f4f4950 .word 0x5f4f4950 + 42f40: 6c6c7550 .word 0x6c6c7550 + 42f44: 6c727443 .word 0x6c727443 + 42f48: 3931385f .word 0x3931385f + 42f4c: 203a6135 .word 0x203a6135 + 42f50: 6b636f4c .word 0x6b636f4c + 42f54: 69614620 .word 0x69614620 + 42f58: 0a64656c .word 0x0a64656c + 42f5c: 00000000 .word 0x00000000 + +00042f60 <.LC0>: + 42f60: 415b200d .word 0x415b200d + 42f64: 5d726464 .word 0x5d726464 + 42f68: 2e202020 .word 0x2e202020 + 42f6c: 312e2030 .word 0x312e2030 + 42f70: 20322e20 .word 0x20322e20 + 42f74: 2e20332e .word 0x2e20332e + 42f78: 352e2034 .word 0x352e2034 + 42f7c: 20362e20 .word 0x20362e20 + 42f80: 2e20372e .word 0x2e20372e + 42f84: 392e2038 .word 0x392e2038 + 42f88: 20412e20 .word 0x20412e20 + 42f8c: 2e20422e .word 0x2e20422e + 42f90: 442e2043 .word 0x442e2043 + 42f94: 20452e20 .word 0x20452e20 + 42f98: 0a0d462e .word 0x0a0d462e + 42f9c: 00000000 .word 0x00000000 + +00042fa0 <.LC1>: + 42fa0: 58383025 .word 0x58383025 + 42fa4: 0000203a .word 0x0000203a + +00042fa8 <.LC2>: + 42fa8: 78323025 .word 0x78323025 + 42fac: 00000020 .word 0x00000020 + +00042fb0 <.LC3>: + 42fb0: 00202020 .word 0x00202020 + +00042fb4 <.LC4>: + 42fb4: 20202020 .word 0x20202020 + 42fb8: 00000000 .word 0x00000000 + +00042fbc <.LC5>: + 42fbc: 00006325 .word 0x00006325 + +00042fc0 <.LC6>: + 42fc0: 0000002e .word 0x0000002e + +00042fc4 <.LC7>: + 42fc4: 00000d0a .word 0x00000d0a + +00042fc8 <.LC0>: + 42fc8: 6d69540d .word 0x6d69540d + 42fcc: 5f327265 .word 0x5f327265 + 42fd0: 53492037 .word 0x53492037 + 42fd4: 00000a52 .word 0x00000a52 + +00042fd8 <.LC1>: + 42fd8: 6d69540d .word 0x6d69540d + 42fdc: 72497265 .word 0x72497265 + 42fe0: 61745371 .word 0x61745371 + 42fe4: 3a737574 .word 0x3a737574 + 42fe8: 25783020 .word 0x25783020 + 42fec: 00000a78 .word 0x00000a78 + +00042ff0 <.LC2>: + 42ff0: 6578450d .word 0x6578450d + 42ff4: 65747563 .word 0x65747563 + 42ff8: 62755320 .word 0x62755320 + 42ffc: 756f7220 .word 0x756f7220 + 43000: 00000a74 .word 0x00000a74 + +00043004 <.LC3>: + 43004: 4c54520d .word 0x4c54520d + 43008: 35393138 .word 0x35393138 + 4300c: 72445b41 .word 0x72445b41 + 43010: 72657669 .word 0x72657669 + 43014: 57203a5d .word 0x57203a5d + 43018: 696e7261 .word 0x696e7261 + 4301c: 3a20676e .word 0x3a20676e + 43020: 6d695420 .word 0x6d695420 + 43024: 4c207265 .word 0x4c207265 + 43028: 2064616f .word 0x2064616f + 4302c: 6e756f43 .word 0x6e756f43 + 43030: 203d2074 .word 0x203d2074 + 43034: 21212131 .word 0x21212131 + 43038: 21212121 .word 0x21212121 + 4303c: 0000000a .word 0x0000000a + +00043040 <.LC4>: + 43040: 4c54520d .word 0x4c54520d + 43044: 35393138 .word 0x35393138 + 43048: 72445b41 .word 0x72445b41 + 4304c: 72657669 .word 0x72657669 + 43050: 45203a5d .word 0x45203a5d + 43054: 726f7272 .word 0x726f7272 + 43058: 6f4e203a .word 0x6f4e203a + 4305c: 70755320 .word 0x70755320 + 43060: 74726f70 .word 0x74726f70 + 43064: 6d695420 .word 0x6d695420 + 43068: 49207265 .word 0x49207265 + 4306c: 21212144 .word 0x21212144 + 43070: 21212121 .word 0x21212121 + 43074: 0000000a .word 0x0000000a + +00043078 <.LC5>: + 43078: 4c54520d .word 0x4c54520d + 4307c: 35393138 .word 0x35393138 + 43080: 72445b41 .word 0x72445b41 + 43084: 72657669 .word 0x72657669 + 43088: 43203a5d .word 0x43203a5d + 4308c: 72746e6f .word 0x72746e6f + 43090: 52206c6f .word 0x52206c6f + 43094: 203a6765 .word 0x203a6765 + 43098: 78257830 .word 0x78257830 + 4309c: 0000000a .word 0x0000000a + +000430a0 <.LC6>: + 430a0: 4c54520d .word 0x4c54520d + 430a4: 35393138 .word 0x35393138 + 430a8: 72445b41 .word 0x72445b41 + 430ac: 72657669 .word 0x72657669 + 430b0: 4c203a5d .word 0x4c203a5d + 430b4: 2064616f .word 0x2064616f + 430b8: 6e756f43 .word 0x6e756f43 + 430bc: 65522074 .word 0x65522074 + 430c0: 30203a67 .word 0x30203a67 + 430c4: 0a782578 .word 0x0a782578 + 430c8: 00000000 .word 0x00000000 + +000430cc <.LC0>: + 430cc: 33323130 .word 0x33323130 + 430d0: 37363534 .word 0x37363534 + 430d4: 42413938 .word 0x42413938 + 430d8: 46454443 .word 0x46454443 + 430dc: 00000000 .word 0x00000000 + +000430e0 <.LC0>: + 430e0: 2d2d2d0d .word 0x2d2d2d0d + 430e4: 2d2d2d2d .word 0x2d2d2d2d + 430e8: 2d2d2d2d .word 0x2d2d2d2d + 430ec: 2d2d2d2d .word 0x2d2d2d2d + 430f0: 43202d2d .word 0x43202d2d + 430f4: 414d4d4f .word 0x414d4d4f + 430f8: 4d20444e .word 0x4d20444e + 430fc: 2045444f .word 0x2045444f + 43100: 504c4548 .word 0x504c4548 + 43104: 2d2d2d20 .word 0x2d2d2d20 + 43108: 2d2d2d2d .word 0x2d2d2d2d + 4310c: 2d2d2d2d .word 0x2d2d2d2d + 43110: 2d2d2d2d .word 0x2d2d2d2d + 43114: 0a2d2d2d .word 0x0a2d2d2d + 43118: 00000000 .word 0x00000000 + +0004311c <.LC1>: + 4311c: 0a73250d .word 0x0a73250d + 43120: 00000000 .word 0x00000000 + +00043124 <.LC2>: + 43124: 2d2d2d0d .word 0x2d2d2d0d + 43128: 2d2d2d2d .word 0x2d2d2d2d + 4312c: 2d2d2d2d .word 0x2d2d2d2d + 43130: 2d2d2d2d .word 0x2d2d2d2d + 43134: 43202d2d .word 0x43202d2d + 43138: 414d4d4f .word 0x414d4d4f + 4313c: 4d20444e .word 0x4d20444e + 43140: 2045444f .word 0x2045444f + 43144: 20444e45 .word 0x20444e45 + 43148: 2d2d2d20 .word 0x2d2d2d20 + 4314c: 2d2d2d2d .word 0x2d2d2d2d + 43150: 2d2d2d2d .word 0x2d2d2d2d + 43154: 2d2d2d2d .word 0x2d2d2d2d + 43158: 0a2d2d2d .word 0x0a2d2d2d + 4315c: 00000000 .word 0x00000000 + +00043160 <.LC3>: + 43160: 6464610d .word 0x6464610d + 43164: 30203a72 .word 0x30203a72 + 43168: 3b782578 .word 0x3b782578 + 4316c: 6c617620 .word 0x6c617620 + 43170: 303a6575 .word 0x303a6575 + 43174: 0a782578 .word 0x0a782578 + 43178: 00000000 .word 0x00000000 + +0004317c <.LC4>: + 4317c: 6f72570d .word 0x6f72570d + 43180: 6120676e .word 0x6120676e + 43184: 6d756772 .word 0x6d756772 + 43188: 20746e65 .word 0x20746e65 + 4318c: 626d756e .word 0x626d756e + 43190: 0d217265 .word 0x0d217265 + 43194: 0000000a .word 0x0000000a + +00043198 <.LC5>: + 43198: 3830250d .word 0x3830250d + 4319c: 25093a58 .word 0x25093a58 + 431a0: 09583430 .word 0x09583430 + 431a4: 58343025 .word 0x58343025 + 431a8: 34302509 .word 0x34302509 + 431ac: 20202058 .word 0x20202058 + 431b0: 34302520 .word 0x34302520 + 431b4: 20202058 .word 0x20202058 + 431b8: 34302520 .word 0x34302520 + 431bc: 30250958 .word 0x30250958 + 431c0: 25095834 .word 0x25095834 + 431c4: 20583430 .word 0x20583430 + 431c8: 25202020 .word 0x25202020 + 431cc: 0a583430 .word 0x0a583430 + 431d0: 00000000 .word 0x00000000 + +000431d4 <.LC6>: + 431d4: 3830250d .word 0x3830250d + 431d8: 20203a58 .word 0x20203a58 + 431dc: 30252020 .word 0x30252020 + 431e0: 00005838 .word 0x00005838 + +000431e4 <.LC7>: + 431e4: 20202020 .word 0x20202020 + 431e8: 58383025 .word 0x58383025 + 431ec: 00000000 .word 0x00000000 + +000431f0 <.LC8>: + 431f0: 20202020 .word 0x20202020 + 431f4: 58383025 .word 0x58383025 + 431f8: 0000000a .word 0x0000000a + 431fc: 0000003f .word 0x0000003f + 43200: 4c454809 .word 0x4c454809 + 43204: 3f282050 .word 0x3f282050 + 43208: 20202029 .word 0x20202029 + 4320c: 7250203a .word 0x7250203a + 43210: 20746e69 .word 0x20746e69 + 43214: 73696874 .word 0x73696874 + 43218: 6c656820 .word 0x6c656820 + 4321c: 656d2070 .word 0x656d2070 + 43220: 67617373 .word 0x67617373 + 43224: 0000000a .word 0x0000000a + 43228: 00004244 .word 0x00004244 + 4322c: 20424409 .word 0x20424409 + 43230: 6464413c .word 0x6464413c + 43234: 73736572 .word 0x73736572 + 43238: 6548202c .word 0x6548202c + 4323c: 3c203e78 .word 0x3c203e78 + 43240: 2c6e654c .word 0x2c6e654c + 43244: 63654420 .word 0x63654420 + 43248: 0a203a3e .word 0x0a203a3e + 4324c: 09090909 .word 0x09090909 + 43250: 6d754420 .word 0x6d754420 + 43254: 656d2070 .word 0x656d2070 + 43258: 79726f6d .word 0x79726f6d + 4325c: 74796220 .word 0x74796220 + 43260: 726f2065 .word 0x726f2065 + 43264: 61655220 .word 0x61655220 + 43268: 77482064 .word 0x77482064 + 4326c: 74796220 .word 0x74796220 + 43270: 65722065 .word 0x65722065 + 43274: 74736967 .word 0x74736967 + 43278: 00007265 .word 0x00007265 + 4327c: 00574844 .word 0x00574844 + 43280: 57484409 .word 0x57484409 + 43284: 64413c20 .word 0x64413c20 + 43288: 73657264 .word 0x73657264 + 4328c: 48202c73 .word 0x48202c73 + 43290: 203e7865 .word 0x203e7865 + 43294: 6e654c3c .word 0x6e654c3c + 43298: 6544202c .word 0x6544202c + 4329c: 203a3e63 .word 0x203a3e63 + 432a0: 0909090a .word 0x0909090a + 432a4: 75442009 .word 0x75442009 + 432a8: 6d20706d .word 0x6d20706d + 432ac: 726f6d65 .word 0x726f6d65 + 432b0: 65682079 .word 0x65682079 + 432b4: 772d666c .word 0x772d666c + 432b8: 2064726f .word 0x2064726f + 432bc: 5220726f .word 0x5220726f + 432c0: 20646165 .word 0x20646165 + 432c4: 68207748 .word 0x68207748 + 432c8: 2d666c65 .word 0x2d666c65 + 432cc: 64726f77 .word 0x64726f77 + 432d0: 67657220 .word 0x67657220 + 432d4: 65747369 .word 0x65747369 + 432d8: 00000072 .word 0x00000072 + 432dc: 00005744 .word 0x00005744 + 432e0: 20574409 .word 0x20574409 + 432e4: 6464413c .word 0x6464413c + 432e8: 73736572 .word 0x73736572 + 432ec: 6548202c .word 0x6548202c + 432f0: 3c203e78 .word 0x3c203e78 + 432f4: 2c6e654c .word 0x2c6e654c + 432f8: 63654420 .word 0x63654420 + 432fc: 0a203a3e .word 0x0a203a3e + 43300: 09090909 .word 0x09090909 + 43304: 6d754420 .word 0x6d754420 + 43308: 656d2070 .word 0x656d2070 + 4330c: 79726f6d .word 0x79726f6d + 43310: 726f7720 .word 0x726f7720 + 43314: 726f2064 .word 0x726f2064 + 43318: 61655220 .word 0x61655220 + 4331c: 77482064 .word 0x77482064 + 43320: 726f7720 .word 0x726f7720 + 43324: 65722064 .word 0x65722064 + 43328: 74736967 .word 0x74736967 + 4332c: 00007265 .word 0x00007265 + 43330: 00005745 .word 0x00005745 + 43334: 20574509 .word 0x20574509 + 43338: 6464413c .word 0x6464413c + 4333c: 73736572 .word 0x73736572 + 43340: 6548202c .word 0x6548202c + 43344: 3c203e78 .word 0x3c203e78 + 43348: 756c6156 .word 0x756c6156 + 4334c: 48202c65 .word 0x48202c65 + 43350: 3a3e7865 .word 0x3a3e7865 + 43354: 09090a20 .word 0x09090a20 + 43358: 57200909 .word 0x57200909 + 4335c: 65746972 .word 0x65746972 + 43360: 6d656d20 .word 0x6d656d20 + 43364: 2079726f .word 0x2079726f + 43368: 64726f77 .word 0x64726f77 + 4336c: 20726f20 .word 0x20726f20 + 43370: 74697257 .word 0x74697257 + 43374: 77482065 .word 0x77482065 + 43378: 726f7720 .word 0x726f7720 + 4337c: 65722064 .word 0x65722064 + 43380: 74736967 .word 0x74736967 + 43384: 0a207265 .word 0x0a207265 + 43388: 09090909 .word 0x09090909 + 4338c: 6e614320 .word 0x6e614320 + 43390: 69727720 .word 0x69727720 + 43394: 6d206574 .word 0x6d206574 + 43398: 2065726f .word 0x2065726f + 4339c: 64726f77 .word 0x64726f77 + 433a0: 20746120 .word 0x20746120 + 433a4: 20656874 .word 0x20656874 + 433a8: 656d6173 .word 0x656d6173 + 433ac: 6d697420 .word 0x6d697420 + 433b0: 090a2065 .word 0x090a2065 + 433b4: 20090909 .word 0x20090909 + 433b8: 203a7845 .word 0x203a7845 + 433bc: 41205745 .word 0x41205745 + 433c0: 65726464 .word 0x65726464 + 433c4: 56207373 .word 0x56207373 + 433c8: 65756c61 .word 0x65756c61 + 433cc: 61562030 .word 0x61562030 + 433d0: 3165756c .word 0x3165756c + 433d4: 00000000 .word 0x00000000 + 433d8: 43495053 .word 0x43495053 + 433dc: 4c4f4f54 .word 0x4c4f4f54 + 433e0: 00000000 .word 0x00000000 + 433e4: 49505309 .word 0x49505309 + 433e8: 4f4f5443 .word 0x4f4f5443 + 433ec: 4d3c204c .word 0x4d3c204c + 433f0: 2c65646f .word 0x2c65646f + 433f4: 63654420 .word 0x63654420 + 433f8: 423c203e .word 0x423c203e + 433fc: 6f4d7469 .word 0x6f4d7469 + 43400: 202c6564 .word 0x202c6564 + 43404: 3e636544 .word 0x3e636544 + 43408: 090a203a .word 0x090a203a + 4340c: 20090909 .word 0x20090909 + 43410: 65646f4d .word 0x65646f4d + 43414: 31203d20 .word 0x31203d20 + 43418: 6e49203a .word 0x6e49203a + 4341c: 53207469 .word 0x53207469 + 43420: 3b434950 .word 0x3b434950 + 43424: 69422020 .word 0x69422020 + 43428: 646f4d74 .word 0x646f4d74 + 4342c: 30203a65 .word 0x30203a65 + 43430: 656e4f28 .word 0x656e4f28 + 43434: 28312f29 .word 0x28312f29 + 43438: 6c617544 .word 0x6c617544 + 4343c: 28322f29 .word 0x28322f29 + 43440: 64617551 .word 0x64617551 + 43444: 09090a29 .word 0x09090a29 + 43448: 4d200909 .word 0x4d200909 + 4344c: 2065646f .word 0x2065646f + 43450: 3a32203d .word 0x3a32203d + 43454: 61724520 .word 0x61724520 + 43458: 43206573 .word 0x43206573 + 4345c: 20706968 .word 0x20706968 + 43460: 0000000a .word 0x0000000a + +00043464 <.LC0>: + 43464: 00006325 .word 0x00006325 + +00043468 <.LC1>: + 43468: 00000020 .word 0x00000020 + +0004346c <.LC2>: + 4346c: 00000a0d .word 0x00000a0d + +00043470 <.LC3>: + 43470: 3c200d0a .word 0x3c200d0a + 43474: 6f543c3c .word 0x6f543c3c + 43478: 6f6c206f .word 0x6f6c206f + 4347c: 6320676e .word 0x6320676e + 43480: 7320646d .word 0x7320646d + 43484: 6e697274 .word 0x6e697274 + 43488: 3e3e2e67 .word 0x3e3e2e67 + 4348c: 000a203e .word 0x000a203e + +00043490 <.LC4>: + 43490: 54523c0d .word 0x54523c0d + 43494: 3931384c .word 0x3931384c + 43498: 003e4135 .word 0x003e4135 + +0004349c <.LC0>: + 4349c: 53767270 .word 0x53767270 + 434a0: 74537274 .word 0x74537274 + 434a4: 6e203a72 .word 0x6e203a72 + 434a8: 7320746f .word 0x7320746f + 434ac: 6f707075 .word 0x6f707075 + 434b0: 64657472 .word 0x64657472 + 434b4: 74657920 .word 0x74657920 + 434b8: 00000000 .word 0x00000000 + +000434bc <.LC0>: + 434bc: 5f6d6f72 .word 0x5f6d6f72 + 434c0: 5f6d646f .word 0x5f6d646f + 434c4: 3a67736d .word 0x3a67736d + 434c8: 746e4520 .word 0x746e4520 + 434cc: 52207265 .word 0x52207265 + 434d0: 6f204d4f .word 0x6f204d4f + 434d4: 465f6d64 .word 0x465f6d64 + 434d8: 65736c61 .word 0x65736c61 + 434dc: 72616c41 .word 0x72616c41 + 434e0: 756f436d .word 0x756f436d + 434e4: 7265746e .word 0x7265746e + 434e8: 74617453 .word 0x74617453 + 434ec: 69747369 .word 0x69747369 + 434f0: 000a7363 .word 0x000a7363 + +000434f4 <.LC1>: + 434f4: 5f6d6f72 .word 0x5f6d6f72 + 434f8: 5f6d646f .word 0x5f6d646f + 434fc: 3a67736d .word 0x3a67736d + 43500: 746e4320 .word 0x746e4320 + 43504: 7361465f .word 0x7361465f + 43508: 73465f74 .word 0x73465f74 + 4350c: 3d636e79 .word 0x3d636e79 + 43510: 202c6425 .word 0x202c6425 + 43514: 5f746e43 .word 0x5f746e43 + 43518: 535f4253 .word 0x535f4253 + 4351c: 63726165 .word 0x63726165 + 43520: 61665f68 .word 0x61665f68 + 43524: 253d6c69 .word 0x253d6c69 + 43528: 00000a64 .word 0x00000a64 + +0004352c <.LC2>: + 4352c: 5f6d6f72 .word 0x5f6d6f72 + 43530: 5f6d646f .word 0x5f6d646f + 43534: 3a67736d .word 0x3a67736d + 43538: 746e4320 .word 0x746e4320 + 4353c: 7261505f .word 0x7261505f + 43540: 5f797469 .word 0x5f797469 + 43544: 6c696146 .word 0x6c696146 + 43548: 2c64253d .word 0x2c64253d + 4354c: 746e4320 .word 0x746e4320 + 43550: 7461525f .word 0x7461525f + 43554: 6c495f65 .word 0x6c495f65 + 43558: 6167656c .word 0x6167656c + 4355c: 64253d6c .word 0x64253d6c + 43560: 0000000a .word 0x0000000a + +00043564 <.LC3>: + 43564: 5f6d6f72 .word 0x5f6d6f72 + 43568: 5f6d646f .word 0x5f6d646f + 4356c: 3a67736d .word 0x3a67736d + 43570: 746e4320 .word 0x746e4320 + 43574: 6372435f .word 0x6372435f + 43578: 61665f38 .word 0x61665f38 + 4357c: 253d6c69 .word 0x253d6c69 + 43580: 43202c64 .word 0x43202c64 + 43584: 4d5f746e .word 0x4d5f746e + 43588: 665f7363 .word 0x665f7363 + 4358c: 3d6c6961 .word 0x3d6c6961 + 43590: 000a6425 .word 0x000a6425 + +00043594 <.LC4>: + 43594: 5f6d6f72 .word 0x5f6d6f72 + 43598: 5f6d646f .word 0x5f6d646f + 4359c: 3a67736d .word 0x3a67736d + 435a0: 746e4320 .word 0x746e4320 + 435a4: 44464f5f .word 0x44464f5f + 435a8: 43435f4d .word 0x43435f4d + 435ac: 64253d41 .word 0x64253d41 + 435b0: 0000000a .word 0x0000000a + +000435b4 <.LC5>: + 435b4: 5f6d6f72 .word 0x5f6d6f72 + 435b8: 5f6d646f .word 0x5f6d646f + 435bc: 3a67736d .word 0x3a67736d + 435c0: 746e4320 .word 0x746e4320 + 435c4: 4b43435f .word 0x4b43435f + 435c8: 4143435f .word 0x4143435f + 435cc: 0a64253d .word 0x0a64253d + 435d0: 00000000 .word 0x00000000 + +000435d4 <.LC6>: + 435d4: 5f6d6f72 .word 0x5f6d6f72 + 435d8: 5f6d646f .word 0x5f6d646f + 435dc: 3a67736d .word 0x3a67736d + 435e0: 746e4320 .word 0x746e4320 + 435e4: 4143435f .word 0x4143435f + 435e8: 6c6c615f .word 0x6c6c615f + 435ec: 0a64253d .word 0x0a64253d + 435f0: 00000000 .word 0x00000000 + +000435f4 <.LC7>: + 435f4: 5f6d6f72 .word 0x5f6d6f72 + 435f8: 5f6d646f .word 0x5f6d646f + 435fc: 3a67736d .word 0x3a67736d + 43600: 746e4320 .word 0x746e4320 + 43604: 64664f5f .word 0x64664f5f + 43608: 61665f6d .word 0x61665f6d + 4360c: 253d6c69 .word 0x253d6c69 + 43610: 00000a64 .word 0x00000a64 + +00043614 <.LC8>: + 43614: 5f6d6f72 .word 0x5f6d6f72 + 43618: 5f6d646f .word 0x5f6d646f + 4361c: 3a67736d .word 0x3a67736d + 43620: 746e4320 .word 0x746e4320 + 43624: 6b63435f .word 0x6b63435f + 43628: 6961665f .word 0x6961665f + 4362c: 64253d6c .word 0x64253d6c + 43630: 0000000a .word 0x0000000a + +00043634 <.LC9>: + 43634: 5f6d6f72 .word 0x5f6d6f72 + 43638: 5f6d646f .word 0x5f6d646f + 4363c: 3a67736d .word 0x3a67736d + 43640: 746f5420 .word 0x746f5420 + 43644: 46206c61 .word 0x46206c61 + 43648: 65736c61 .word 0x65736c61 + 4364c: 616c4120 .word 0x616c4120 + 43650: 253d6d72 .word 0x253d6d72 + 43654: 00000a64 .word 0x00000a64 + +00043658 <.LC10>: + 43658: 5f6d6f72 .word 0x5f6d6f72 + 4365c: 5f6d646f .word 0x5f6d646f + 43660: 3a67736d .word 0x3a67736d + 43664: 6d646f20 .word 0x6d646f20 + 43668: 7465535f .word 0x7465535f + 4366c: 73797243 .word 0x73797243 + 43670: 436c6174 .word 0x436c6174 + 43674: 29287061 .word 0x29287061 + 43678: 7243203a .word 0x7243203a + 4367c: 61747379 .word 0x61747379 + 43680: 7061436c .word 0x7061436c + 43684: 30203d20 .word 0x30203d20 + 43688: 0a782578 .word 0x0a782578 + 4368c: 00000000 .word 0x00000000 + +00043690 <.LC11>: + 43690: 5f6d6f72 .word 0x5f6d6f72 + 43694: 5f6d646f .word 0x5f6d646f + 43698: 3a67736d .word 0x3a67736d + 4369c: 4d444f20 .word 0x4d444f20 + 436a0: 6f66435f .word 0x6f66435f + 436a4: 63617254 .word 0x63617254 + 436a8: 676e696b .word 0x676e696b + 436ac: 203a2928 .word 0x203a2928 + 436b0: 6b636170 .word 0x6b636170 + 436b4: 63207465 .word 0x63207465 + 436b8: 746e756f .word 0x746e756f + 436bc: 64207265 .word 0x64207265 + 436c0: 6e73656f .word 0x6e73656f + 436c4: 63207427 .word 0x63207427 + 436c8: 676e6168 .word 0x676e6168 + 436cc: 00000a65 .word 0x00000a65 + +000436d0 <.LC12>: + 436d0: 5f6d6f72 .word 0x5f6d6f72 + 436d4: 5f6d646f .word 0x5f6d646f + 436d8: 3a67736d .word 0x3a67736d + 436dc: 4d444f20 .word 0x4d444f20 + 436e0: 6f66435f .word 0x6f66435f + 436e4: 63617254 .word 0x63617254 + 436e8: 676e696b .word 0x676e696b + 436ec: 203a2928 .word 0x203a2928 + 436f0: 5f4f4643 .word 0x5f4f4643 + 436f4: 5f7a486b .word 0x5f7a486b + 436f8: 203d2041 .word 0x203d2041 + 436fc: 486b6425 .word 0x486b6425 + 43700: 00000a7a .word 0x00000a7a + +00043704 <.LC13>: + 43704: 5f6d6f72 .word 0x5f6d6f72 + 43708: 5f6d646f .word 0x5f6d646f + 4370c: 3a67736d .word 0x3a67736d + 43710: 4d444f20 .word 0x4d444f20 + 43714: 6f66435f .word 0x6f66435f + 43718: 63617254 .word 0x63617254 + 4371c: 676e696b .word 0x676e696b + 43720: 203a2928 .word 0x203a2928 + 43724: 73726966 .word 0x73726966 + 43728: 616c2074 .word 0x616c2074 + 4372c: 20656772 .word 0x20656772 + 43730: 204f4643 .word 0x204f4643 + 43734: 0a746968 .word 0x0a746968 + 43738: 00000000 .word 0x00000000 + +0004373c <.LC14>: + 4373c: 5f6d6f72 .word 0x5f6d6f72 + 43740: 5f6d646f .word 0x5f6d646f + 43744: 3a67736d .word 0x3a67736d + 43748: 4d444f20 .word 0x4d444f20 + 4374c: 6f66435f .word 0x6f66435f + 43750: 63617254 .word 0x63617254 + 43754: 676e696b .word 0x676e696b + 43758: 203a2928 .word 0x203a2928 + 4375c: 73797243 .word 0x73797243 + 43760: 206c6174 .word 0x206c6174 + 43764: 20706163 .word 0x20706163 + 43768: 7366666f .word 0x7366666f + 4376c: 3d207465 .word 0x3d207465 + 43770: 0a642520 .word 0x0a642520 + 43774: 00000000 .word 0x00000000 + +00043778 <.LC15>: + 43778: 5f6d6f72 .word 0x5f6d6f72 + 4377c: 5f6d646f .word 0x5f6d646f + 43780: 3a67736d .word 0x3a67736d + 43784: 4d444f20 .word 0x4d444f20 + 43788: 6f66435f .word 0x6f66435f + 4378c: 63617254 .word 0x63617254 + 43790: 676e696b .word 0x676e696b + 43794: 203a2928 .word 0x203a2928 + 43798: 73797243 .word 0x73797243 + 4379c: 206c6174 .word 0x206c6174 + 437a0: 20706163 .word 0x20706163 + 437a4: 7830203d .word 0x7830203d + 437a8: 202c7825 .word 0x202c7825 + 437ac: 61666544 .word 0x61666544 + 437b0: 20746c75 .word 0x20746c75 + 437b4: 73797243 .word 0x73797243 + 437b8: 206c6174 .word 0x206c6174 + 437bc: 20706163 .word 0x20706163 + 437c0: 7830203d .word 0x7830203d + 437c4: 000a7825 .word 0x000a7825 + +000437c8 <.LC0>: + 437c8: 69666e49 .word 0x69666e49 + 437cc: 7974696e .word 0x7974696e + 437d0: 00000000 .word 0x00000000 + +000437d4 <.LC1>: + 437d4: 004e614e .word 0x004e614e + +000437d8 <.LC2>: + 437d8: 00000030 .word 0x00000030 + 437dc: 00000043 .word 0x00000043 + +000437e0 <.LC0>: + 437e0: 00464e49 .word 0x00464e49 + +000437e4 <.LC1>: + 437e4: 00666e69 .word 0x00666e69 + +000437e8 <.LC2>: + 437e8: 004e414e .word 0x004e414e + +000437ec <.LC3>: + 437ec: 006e616e .word 0x006e616e + +000437f0 <.LC4>: + 437f0: 33323130 .word 0x33323130 + 437f4: 37363534 .word 0x37363534 + 437f8: 42413938 .word 0x42413938 + 437fc: 46454443 .word 0x46454443 + 43800: 00000000 .word 0x00000000 + +00043804 <.LC5>: + 43804: 33323130 .word 0x33323130 + 43808: 37363534 .word 0x37363534 + 4380c: 62613938 .word 0x62613938 + 43810: 66656463 .word 0x66656463 + 43814: 00000000 .word 0x00000000 + +00043818 <.LC6>: + 43818: 6c756e28 .word 0x6c756e28 + 4381c: 0000296c .word 0x0000296c + +00043820 <.LC7>: + 43820: 0000002e .word 0x0000002e + +00043824 <.LC8>: + 43824: 00000030 .word 0x00000030 + +Disassembly of section A3 rw: + +10004000 : +10004000: 1000406d .word 0x1000406d + +10004004 : +10004004: 574b5452 ff006e69 00010100 01018195 RTKWin.......... +10004014: 00000000 .... + +10004018 : +10004018: 74737543 72656d6f 67695320 7574616e Customer Signatu +10004028: 6d2d6572 6c65646f 00787878 00000000 re-modelxxx..... + +10004038 : +10004038: f8df f000 ldr.w pc, [pc] ; 1000403c +1000403c: 0000f511 .word 0x0000f511 + +10004040 : +10004040: f8df f000 ldr.w pc, [pc] ; 10004044 +10004044: 0000f39d .word 0x0000f39d + +10004048 : +10004048: f8df f000 ldr.w pc, [pc] ; 1000404c +1000404c: 00004019 .word 0x00004019 + +10004050 : +10004050: 482c ldr r0, [pc, #176] ; (10004104 <.infra.ram.start_84>) +10004052: 6801 ldr r1, [r0, #0] +10004054: f021 6170 bic.w r1, r1, #251658240 ; 0xf000000 +10004058: f041 61c0 orr.w r1, r1, #100663296 ; 0x6000000 +1000405c: 6001 str r1, [r0, #0] +1000405e: 6c41 ldr r1, [r0, #68] ; 0x44 +10004060: f021 0118 bic.w r1, r1, #24 +10004064: f041 0108 orr.w r1, r1, #8 +10004068: 6441 str r1, [r0, #68] ; 0x44 +1000406a: 4770 bx lr + +1000406c : +1000406c: b510 push {r4, lr} +1000406e: f03b fca5 bl 1003f9bc <__iar_data_init_app> +10004072: 4925 ldr r1, [pc, #148] ; (10004108 <.infra.ram.start_85>) +10004074: 4825 ldr r0, [pc, #148] ; (1000410c <.infra.ram.start_86>) +10004076: 4c26 ldr r4, [pc, #152] ; (10004110 <.infra.ram.start_87>) +10004078: 6088 str r0, [r1, #8] +1000407a: f03e f9ad bl 100423d8 +1000407e: b130 cbz r0, 1000408e +10004080: 6820 ldr r0, [r4, #0] +10004082: 0040 lsls r0, r0, #1 +10004084: d50a bpl.n 1000409c +10004086: f20f 00a8 addw r0, pc, #168 ; 0xa8 +1000408a: f7ff ffd9 bl 10004040 +1000408e: 6820 ldr r0, [r4, #0] +10004090: 0040 lsls r0, r0, #1 +10004092: bf44 itt mi +10004094: f20f 00b4 addwmi r0, pc, #180 ; 0xb4 +10004098: f7ff ffd2 blmi 10004040 +1000409c: f03e f9a4 bl 100423e8 +100040a0: 491c ldr r1, [pc, #112] ; (10004114 <.infra.ram.start_88>) +100040a2: 6808 ldr r0, [r1, #0] +100040a4: 6849 ldr r1, [r1, #4] +100040a6: 1a0a subs r2, r1, r0 +100040a8: 2100 movs r1, #0 +100040aa: f7ff ffc5 bl 10004038 +100040ae: f000 ff8e bl 10004fce +100040b2: f03b fc75 bl 1003f9a0 +100040b6: f7ff ffcb bl 10004050 +100040ba: f039 ff5f bl 1003df7c +100040be: f00f fca6 bl 10013a0e +100040c2: 4815 ldr r0, [pc, #84] ; (10004118 <.infra.ram.start_89>) +100040c4: 6ac1 ldr r1, [r0, #44] ; 0x2c +100040c6: 0849 lsrs r1, r1, #1 +100040c8: 0049 lsls r1, r1, #1 +100040ca: 62c1 str r1, [r0, #44] ; 0x2c +100040cc: 4913 ldr r1, [pc, #76] ; (1000411c <.infra.ram.start_90>) +100040ce: 680a ldr r2, [r1, #0] +100040d0: 6802 ldr r2, [r0, #0] +100040d2: 0852 lsrs r2, r2, #1 +100040d4: 0052 lsls r2, r2, #1 +100040d6: 6002 str r2, [r0, #0] +100040d8: 6809 ldr r1, [r1, #0] +100040da: 6801 ldr r1, [r0, #0] +100040dc: 4a10 ldr r2, [pc, #64] ; (10004120 <.infra.ram.start_91>) +100040de: f021 0102 bic.w r1, r1, #2 +100040e2: 6001 str r1, [r0, #0] +100040e4: 480f ldr r0, [pc, #60] ; (10004124 <.infra.ram.start_92>) +100040e6: 6801 ldr r1, [r0, #0] +100040e8: 0849 lsrs r1, r1, #1 +100040ea: 0049 lsls r1, r1, #1 +100040ec: 6001 str r1, [r0, #0] +100040ee: 480e ldr r0, [pc, #56] ; (10004128 <.infra.ram.start_93>) +100040f0: 490e ldr r1, [pc, #56] ; (1000412c <.infra.ram.start_94>) +100040f2: f7ff ffa9 bl 10004048 +100040f6: f000 ff1d bl 10004f34 +100040fa: e8bd 4010 ldmia.w sp!, {r4, lr} +100040fe: f03e b975 b.w 100423ec <_AppStart> + ... + +10004104 <.infra.ram.start_84>: +10004104: 40000020 .word 0x40000020 + +10004108 <.infra.ram.start_85>: +10004108: 10000000 .word 0x10000000 + +1000410c <.infra.ram.start_86>: +1000410c: 1003faa1 .word 0x1003faa1 + +10004110 <.infra.ram.start_87>: +10004110: 10000314 .word 0x10000314 + +10004114 <.infra.ram.start_88>: +10004114: 10048170 .word 0x10048170 + +10004118 <.infra.ram.start_89>: +10004118: 40000214 .word 0x40000214 + +1000411c <.infra.ram.start_90>: +1000411c: 40050000 .word 0x40050000 + +10004120 <.infra.ram.start_91>: +10004120: 1000b25b .word 0x1000b25b + +10004124 <.infra.ram.start_92>: +10004124: 400002a0 .word 0x400002a0 + +10004128 <.infra.ram.start_93>: +10004128: 10043bff .word 0x10043bff + +1000412c <.infra.ram.start_94>: +1000412c: 10043bad .word 0x10043bad + +10004130 : +10004130: 6c61480d 6d6f4320 206e6f6d 74696e49 .Hal Common Init +10004140: 69614620 2e64656c 0000000a Failed..... + +1000414c : +1000414c: 3d3d3d0d 45203d3d 7265746e 616d4920 .===== Enter Ima +1000415c: 32206567 3d3d3d20 00000a3d ge 2 ====... + +10004168 : +10004168: 44535441 00000000 ATSD.... + +10004170 : +10004170: 45535441 00000000 ATSE.... + +10004178 : +10004178: 41535441 00000000 ATSA.... + +10004180 : +10004180: 47535441 00000000 ATSG.... + +10004188 : +10004188: 43535441 00000000 ATSC.... + +10004190 : +10004190: 52535441 00000000 ATSR.... + +10004198 : +10004198: 50535441 00000000 ATSP.... + +100041a0 : +100041a0: 4c535441 00000000 ATSL.... + +100041a8 : +100041a8: 40535441 00000000 ATS@.... + +100041b0 : +100041b0: 21535441 00000000 ATS!.... + +100041b8 : +100041b8: 23535441 00000000 ATS#.... + +100041c0 : +100041c0: 3f535441 00000000 ATS?.... + +100041c8 : +100041c8: 52475441 00000000 ATGR.... + +100041d0 : +100041d0: 30575441 00000000 ATW0.... + +100041d8 : +100041d8: 31575441 00000000 ATW1.... + +100041e0 : +100041e0: 32575441 00000000 ATW2.... + +100041e8 : +100041e8: 33575441 00000000 ATW3.... + +100041f0 : +100041f0: 34575441 00000000 ATW4.... + +100041f8 : +100041f8: 35575441 00000000 ATW5.... + +10004200 : +10004200: 36575441 00000000 ATW6.... + +10004208 : +10004208: 41575441 00000000 ATWA.... + +10004210 : +10004210: 42575441 00000000 ATWB.... + +10004218 : +10004218: 43575441 00000000 ATWC.... + +10004220 : +10004220: 44575441 00000000 ATWD.... + +10004228 : +10004228: 50575441 00000000 ATWP.... + +10004230 : +10004230: 52575441 00000000 ATWR.... + +10004238 : +10004238: 53575441 00000000 ATWS.... + +10004240 : +10004240: 4d575441 00000000 ATWM.... + +10004248 : +10004248: 5a575441 00000000 ATWZ.... + +10004250 : +10004250: 4f575441 00000000 ATWO.... + +10004258 : +10004258: 45575441 00000000 ATWE.... + +10004260 : +10004260: 51575441 00000000 ATWQ.... + +10004268 : +10004268: 57575441 00000000 ATWW.... + +10004270 : +10004270: 77575441 00000000 ATWw.... + +10004278 : +10004278: 49575441 00000000 ATWI.... + +10004280 : +10004280: 3f575441 00000000 ATW?.... + +10004288 : +10004288: 2b575441 00434241 ATW+ABC. + +10004290 : +10004290: 00000000 .... + +10004294 : +10004294: ffffffff .... + +10004298 : +10004298: 2d2d5441 00000000 AT--.... + +100042a0 : +100042a0: 78785441 00000000 ATxx.... + +100042a8 : +100042a8: 10010cb5 10010cb9 10010cd1 10010cb5 ................ +100042b8: 10010cb9 10010cd1 10010cd5 10010cd9 ................ +100042c8: 10010ce9 10010ced 10010cfd 10010d01 ................ +100042d8: 10010d03 10010d27 10010d2b 10010d3d ....'...+...=... +100042e8: 10010d4d 10010d5b 10010d5f 00000000 M...[..._....... +100042f8: 00000000 10010d63 10010d99 10010d9b ....c........... +10004308: 10010da9 10010dad 10010de5 10010de7 ................ +10004318: 10010dfb 10010e11 10010e2d 10010e55 ........-...U... +10004328: 10010e83 10010e9d 10010ea1 10010ea3 ................ +10004338: 10010ead 10010eaf 10010eb7 10010ebb ................ +10004348: 10010ebd 10010ec1 10010ec5 10010ec9 ................ +10004358: 10010ed1 10010ed5 10010edf 10010ee3 ................ +10004368: 10010ee7 10010eeb 10010ef7 10010f0b ................ +10004378: 10010f0f 10010f13 10010f27 10010f3b ........'...;... +10004388: 10010f3f 10010f43 10010fe5 10011019 ?...C........... +10004398: 1001101d 10011095 100110db 100110df ................ +100043a8: 100110e1 100110e7 100110f5 10011101 ................ +100043b8: 10011105 10011115 ........ + +100043c0 : +100043c0: 73416e4f 52636f73 00007165 OnAssocReq.. + +100043cc : +100043cc: 73416e4f 52636f73 00007073 OnAssocRsp.. + +100043d8 : +100043d8: 65526e4f 6f737341 71655263 00000000 OnReAssocReq.... + +100043e8 : +100043e8: 65526e4f 6f737341 70735263 00000000 OnReAssocRsp.... + +100043f8 : +100043f8: 72506e4f 5265626f 00007165 OnProbeReq.. + +10004404 : +10004404: 72506e4f 5265626f 00007073 OnProbeRsp.. + +10004410 : +10004410: 65526f44 76726573 00006465 DoReserved.. + +1000441c : +1000441c: 65426e4f 6e6f6361 00000000 OnBeacon.... + +10004428 : +10004428: 54416e4f 00004d49 OnATIM.. + +10004430 : +10004430: 69446e4f 73736173 0000636f OnDisassoc.. + +1000443c : +1000443c: 75416e4f 00006874 OnAuth.. + +10004444 : +10004444: 65446e4f 68747541 00000000 OnDeAuth.... + +10004450 : +10004450: 63416e4f 6e6f6974 00000000 OnAction.... + +1000445c : +1000445c: 099a6f50 Po.. + +10004460 : +10004460: 02ac0f00 .... + +10004464 : +10004464: 10042445 10042473 100424a5 100424d1 E$..s$...$...$.. + +10004474 : +10004474: 024ce000 00002001 ..L.. .. + +1000447c : +1000447c: 00000002 .... + +10004480 : +10004480: ffffffff ffffffff a2da0fc9 34c26821 ............!h.4 +10004490: 8b62c6c4 d11cdc80 084e0229 74cc678a ..b.....).N..g.t +100044a0: a6be0b02 229b133b 79084a51 dd04348e ....;.."QJ.y.4.. +100044b0: b31995ef 1b433acd 6d0a2b30 37145ff2 .....:C.0+.m._.7 +100044c0: 6d35e14f 45c2516d 76b585e4 c67e5e62 O.5mmQ.E...vb^~. +100044d0: e9424cf4 6bed37a6 b65cff0b edb706f4 .LB..7.k..\..... +100044e0: fb6b38ee a59f895a 11249fae e61f4b7c .8k.Z.....$.|K.. +100044f0: 51662849 3d5be4ec b87c00c2 05bf63a1 I(fQ..[=..|..c.. +10004500: 3648da98 9ad3551c a83f1669 5fcf24fd ..H6.U..i.?..$._ +10004510: 235d6583 96ada3dc 56f3621c bb528520 .e]#.....b.V .R. +10004520: 0729d59e 6d969670 4e350c67 0498bc4a ..).p..mg.5NJ... +10004530: 086c74f1 277323ca ffffffff ffffffff .tl..#s'........ + +10004540 : +10004540: 1a202425 03080d14 22262701 080e151c %$ ......'&".... +10004550: 282a0203 0e161e24 2c020309 181f262a ..*($......,*&.. +10004560: 0203090f 21282d2f 040a1019 2b2f3102 ..../-(!.....1/+ +10004570: 0a111b23 32340204 121c252d 3702040b #.....42-%.....7 +10004580: 1e273035 02040c13 2a33383b 050c1420 50'.....;83* ... +10004590: 363c3e02 0d15212c 3f420205 17232f39 .><6,!....B?9/#. +100045a0: 4603050e 26323c43 03050f18 3540474a ...FC<2&....JG@5 +100045b0: 06101a28 444b4e03 111b2a38 50530306 (....NKD8*....SP +100045c0: 1d2d3b48 58030612 2f3e4c54 0307131e H;-....XTL>/.... +100045d0: 4250595d 07142032 555f6204 15223546 ]YPB2 ...b_UF5". +100045e0: 64680408 24384a5a 6e040816 3b4f606a ..hdZJ8$...nj`O; +100045f0: 04081726 53657075 0919283f 6b777c04 &...upeS?(...|wk +10004600: 1a2b4358 7e83050a 2d475d72 8b050a1c XC+....~r]G-.... +10004610: 4b637886 050b1d30 697f8e93 0b1f334f .xcK0......iO3.. +10004620: 87969c06 2136546f 9fa5060c 3959768f ....oT6!.....vY9 +10004630: af060d23 5e7d97a8 070d253d 84a0b2b9 #.....}^=%...... +10004640: 0e274064 aabdc407 2a446a8c c8d0080f d@'......jD*.... +10004650: 487094b4 dc08102c 779dbfd4 08112f4c ..pH,......wL/.. +10004660: a6cae0e9 1231517e 00000009 ....~Q1..... + +1000466c : +1000466c: 1a202425 00000000 22262700 0000001c %$ ......'&".... +1000467c: 282a0000 00001e24 2c000000 001f262a ..*($......,*&.. +1000468c: 00000000 21282d2f 00000000 2b2f3100 ..../-(!.....1/+ +1000469c: 00000023 32340000 0000252d 37000000 #.....42-%.....7 +100046ac: 00273035 00000000 2a33383b 00000000 50'.....;83*.... +100046bc: 363c3e00 0000002c 3f420000 00002f39 .><6,.....B?9/.. +100046cc: 46000000 00323c43 00000000 3540474a ...FC<2.....JG@5 +100046dc: 00000000 444b4e00 00000038 50530000 .....NKD8.....SP +100046ec: 00003b48 58000000 003e4c54 00000000 H;.....XTL>..... +100046fc: 4250595d 00000000 555f6200 00000046 ]YPB.....b_UF... +1000470c: 64680000 00004a5a 6e000000 004f606a ..hdZJ.....nj`O. +1000471c: 00000000 53657075 00000000 6b777c00 ....upeS.....|wk +1000472c: 00000058 7e830000 00005d72 8b000000 X......~r]...... +1000473c: 00637886 00000000 697f8e93 00000000 .xc........i.... +1000474c: 87969c00 0000006f 9fa50000 0000768f ....o........v.. +1000475c: af000000 007d97a8 00000000 84a0b2b9 ......}......... +1000476c: 00000000 aabdc400 0000008c c8d00000 ................ +1000477c: 000094b4 dc000000 009dbfd4 00000000 ................ +1000478c: a6cae0e9 00000000 00000000 ............ + +10004798 : +10004798: c8d00000 487094b4 0000102c 00080000 ......pH,....... + ... + +100047b0 : +100047b0: d1d80000 5a7da0b0 0000223b 05100000 ......}Z;"...... + ... + +100047c8 : +100047c8: 00434346 FCC. + +100047cc : +100047cc: 47342e32 00000000 2.4G.... + +100047d4 : +100047d4: 004d3032 20M. + +100047d8 : +100047d8: 004b4343 CCK. + +100047dc : +100047dc: 00005431 1T.. + +100047e0 : +100047e0: 00003130 01.. + +100047e4 : +100047e4: 00003233 32.. + +100047e8 : +100047e8: 49535445 00000000 ETSI.... + +100047f0 : +100047f0: 004b4b4d MKK. + +100047f4 : +100047f4: 00003230 02.. + +100047f8 : +100047f8: 00003330 03.. + +100047fc : +100047fc: 00003430 04.. + +10004800 : +10004800: 00003530 05.. + +10004804 : +10004804: 00003630 06.. + +10004808 : +10004808: 00003730 07.. + +1000480c : +1000480c: 00003830 08.. + +10004810 : +10004810: 00003930 09.. + +10004814 : +10004814: 00003031 10.. + +10004818 : +10004818: 00003131 11.. + +1000481c : +1000481c: 00003231 12.. + +10004820 : +10004820: 00003336 63.. + +10004824 : +10004824: 00003331 13.. + +10004828 : +10004828: 00003431 14.. + +1000482c : +1000482c: 4d44464f 00000000 OFDM.... + +10004834 : +10004834: 00003832 28.. + +10004838 : +10004838: 00003033 30.. + +1000483c : +1000483c: 00005448 HT.. + +10004840 : +10004840: 004d3034 40M. + +10004844 : +10004844: 00003632 26.. + +10004848 : +10004848: f8df f000 ldr.w pc, [pc] ; 1000484c +1000484c: 0000eadd .word 0x0000eadd + +10004850 : +10004850: f8df f000 ldr.w pc, [pc] ; 10004854 +10004854: 0000ea71 .word 0x0000ea71 + +10004858 : +10004858: f8df f000 ldr.w pc, [pc] ; 1000485c +1000485c: 00000329 .word 0x00000329 + +10004860 : +10004860: f8df f000 ldr.w pc, [pc] ; 10004864 +10004864: 00000335 .word 0x00000335 + +10004868 : +10004868: f8df f000 ldr.w pc, [pc] ; 1000486c +1000486c: 00000309 .word 0x00000309 + +10004870 : +10004870: f8df f000 ldr.w pc, [pc] ; 10004874 +10004874: 0000e8b1 .word 0x0000e8b1 + +10004878 : +10004878: b538 push {r3, r4, r5, lr} +1000487a: f7ff ffed bl 10004858 +1000487e: 4604 mov r4, r0 +10004880: 2000 movs r0, #0 +10004882: f7ff ffed bl 10004860 +10004886: 2000 movs r0, #0 +10004888: f7ff ffee bl 10004868 +1000488c: 4d25 ldr r5, [pc, #148] ; (10004924 ) +1000488e: 6829 ldr r1, [r5, #0] +10004890: 281b cmp r0, #27 +10004892: d113 bne.n 100048bc +10004894: 7948 ldrb r0, [r1, #5] +10004896: 2801 cmp r0, #1 +10004898: d004 beq.n 100048a4 +1000489a: 2001 movs r0, #1 +1000489c: 7148 strb r0, [r1, #5] +1000489e: 2000 movs r0, #0 +100048a0: 6829 ldr r1, [r5, #0] +100048a2: e012 b.n 100048ca + +100048a4 : +100048a4: 7988 ldrb r0, [r1, #6] +100048a6: 2801 cmp r0, #1 +100048a8: bf1c itt ne +100048aa: 6a08 ldrne r0, [r1, #32] +100048ac: 2801 cmpne r0, #1 +100048ae: d103 bne.n 100048b8 +100048b0: 78c8 ldrb r0, [r1, #3] +100048b2: bb88 cbnz r0, 10004918 +100048b4: 2001 movs r0, #1 +100048b6: e008 b.n 100048ca + +100048b8 : +100048b8: 2000 movs r0, #0 +100048ba: e006 b.n 100048ca + +100048bc : +100048bc: 78ca ldrb r2, [r1, #3] +100048be: 2a01 cmp r2, #1 +100048c0: d105 bne.n 100048ce +100048c2: 285b cmp r0, #91 ; 0x5b +100048c4: bf14 ite ne +100048c6: 2000 movne r0, #0 +100048c8: 2002 moveq r0, #2 + +100048ca : +100048ca: 70c8 strb r0, [r1, #3] +100048cc: e024 b.n 10004918 + +100048ce : +100048ce: 78ca ldrb r2, [r1, #3] +100048d0: 2a02 cmp r2, #2 +100048d2: d10a bne.n 100048ea +100048d4: 2200 movs r2, #0 +100048d6: 70ca strb r2, [r1, #3] +100048d8: 2841 cmp r0, #65 ; 0x41 +100048da: bf18 it ne +100048dc: 2842 cmpne r0, #66 ; 0x42 +100048de: d11b bne.n 10004918 +100048e0: 6829 ldr r1, [r5, #0] +100048e2: 2201 movs r2, #1 +100048e4: f7ff ffb4 bl 10004850 +100048e8: e016 b.n 10004918 + +100048ea : +100048ea: 2201 movs r2, #1 +100048ec: f7ff ffac bl 10004848 +100048f0: 2802 cmp r0, #2 +100048f2: d111 bne.n 10004918 +100048f4: 6828 ldr r0, [r5, #0] +100048f6: 6881 ldr r1, [r0, #8] +100048f8: b141 cbz r1, 1000490c +100048fa: 2101 movs r1, #1 +100048fc: 7101 strb r1, [r0, #4] +100048fe: 6828 ldr r0, [r5, #0] +10004900: 6a01 ldr r1, [r0, #32] +10004902: b149 cbz r1, 10004918 +10004904: 3024 adds r0, #36 ; 0x24 +10004906: f00f faa3 bl 10013e50 +1000490a: e005 b.n 10004918 + +1000490c : +1000490c: 6880 ldr r0, [r0, #8] +1000490e: 2200 movs r2, #0 +10004910: 217f movs r1, #127 ; 0x7f +10004912: 1c40 adds r0, r0, #1 +10004914: f7ff ffac bl 10004870 + +10004918 : +10004918: 4620 mov r0, r4 +1000491a: e8bd 4032 ldmia.w sp!, {r1, r4, r5, lr} +1000491e: f7ff bf9f b.w 10004860 + ... + +10004924 : +10004924: 06a8 1000 .... + +10004928 : +10004928: f8df f000 ldr.w pc, [pc] ; 1000492c +1000492c: 00003081 .word 0x00003081 + +10004930 : +10004930: f8df f000 ldr.w pc, [pc] ; 10004934 +10004934: 00002ea5 .word 0x00002ea5 + +10004938 : +10004938: f8df f000 ldr.w pc, [pc] ; 1000493c +1000493c: 00003049 .word 0x00003049 + +10004940 : +10004940: e92d 42fc stmdb sp!, {r2, r3, r4, r5, r6, r7, r9, lr} +10004944: 4681 mov r9, r0 +10004946: f000 fa00 bl 10004d4a <.hal.flash.text_23+0x2> +1000494a: 460c mov r4, r1 +1000494c: 4615 mov r5, r2 +1000494e: 461e mov r6, r3 +10004950: d509 bpl.n 10004966 +10004952: 9601 str r6, [sp, #4] +10004954: 9500 str r5, [sp, #0] +10004956: 4623 mov r3, r4 +10004958: 464a mov r2, r9 +1000495a: f20f 71cc addw r1, pc, #1996 ; 0x7cc +1000495e: f20f 70e4 addw r0, pc, #2020 ; 0x7e4 +10004962: f7ff fb6d bl 10004040 +10004966: f8df 777c ldr.w r7, [pc, #1916] ; 100050e4 <.hal.flash.text_35> +1000496a: 2000 movs r0, #0 +1000496c: 2c10 cmp r4, #16 +1000496e: 60b8 str r0, [r7, #8] +10004970: db0a blt.n 10004988 +10004972: f8df 0774 ldr.w r0, [pc, #1908] ; 100050e8 <.hal.flash.text_36> +10004976: 6800 ldr r0, [r0, #0] +10004978: 04c0 lsls r0, r0, #19 +1000497a: d504 bpl.n 10004986 +1000497c: 4621 mov r1, r4 +1000497e: f20f 70ec addw r0, pc, #2028 ; 0x7ec +10004982: f7ff fb5d bl 10004040 +10004986: 240f movs r4, #15 +10004988: f8df 0760 ldr.w r0, [pc, #1888] ; 100050ec <.hal.flash.text_37> +1000498c: f8df 1760 ldr.w r1, [pc, #1888] ; 100050f0 <.hal.flash.text_38> +10004990: 6004 str r4, [r0, #0] +10004992: 6838 ldr r0, [r7, #0] +10004994: 4008 ands r0, r1 +10004996: 6038 str r0, [r7, #0] +10004998: 2100 movs r1, #0 +1000499a: f8df 0758 ldr.w r0, [pc, #1880] ; 100050f4 <.hal.flash.text_39> +1000499e: f880 9000 strb.w r9, [r0] +100049a2: e002 b.n 100049aa +100049a4: 5d4a ldrb r2, [r1, r5] +100049a6: 7002 strb r2, [r0, #0] +100049a8: 1c49 adds r1, r1, #1 +100049aa: b2c9 uxtb r1, r1 +100049ac: 42a1 cmp r1, r4 +100049ae: d3f9 bcc.n 100049a4 +100049b0: 2001 movs r0, #1 +100049b2: 60b8 str r0, [r7, #8] +100049b4: f7ff ffbc bl 10004930 +100049b8: 4630 mov r0, r6 +100049ba: e8bd 42f6 ldmia.w sp!, {r1, r2, r4, r5, r6, r7, r9, lr} +100049be: e1b3 b.n 10004d28 + +100049c0 : +100049c0: b5e0 push {r5, r6, r7, lr} +100049c2: 4605 mov r5, r0 +100049c4: 460e mov r6, r1 +100049c6: 4617 mov r7, r2 +100049c8: 4620 mov r0, r4 +100049ca: f000 f9ad bl 10004d28 +100049ce: f000 f989 bl 10004ce4 <.hal.flash.text_20> +100049d2: d505 bpl.n 100049e0 +100049d4: a037 add r0, pc, #220 ; (adr r0, 10004ab4 <.hal.flash.text_14>) +100049d6: f7ff fb33 bl 10004040 +100049da: e001 b.n 100049e0 +100049dc: f000 f812 bl 10004a04 <.hal.flash.text_7+0x2> +100049e0: f000 f80d bl 100049fe <.hal.flash.text_6> +100049e4: 0780 lsls r0, r0, #30 +100049e6: 4623 mov r3, r4 +100049e8: d5f8 bpl.n 100049dc +100049ea: 463a mov r2, r7 +100049ec: 4631 mov r1, r6 +100049ee: 4628 mov r0, r5 +100049f0: f7ff ffa6 bl 10004940 +100049f4: f000 f803 bl 100049fe <.hal.flash.text_6> +100049f8: 0780 lsls r0, r0, #30 +100049fa: d4fb bmi.n 100049f4 +100049fc: bde0 pop {r5, r6, r7, pc} + +100049fe <.hal.flash.text_6>: +100049fe: 4620 mov r0, r4 +10004a00: e20c b.n 10004e1c + +10004a02 <.hal.flash.text_7>: +10004a02: 4623 mov r3, r4 +10004a04: 2200 movs r2, #0 +10004a06: 2100 movs r1, #0 +10004a08: 2006 movs r0, #6 +10004a0a: e799 b.n 10004940 + +10004a0c : +10004a0c: b580 push {r7, lr} +10004a0e: 0c01 lsrs r1, r0, #16 +10004a10: f88d 1000 strb.w r1, [sp] +10004a14: f88d 0002 strb.w r0, [sp, #2] +10004a18: 0a01 lsrs r1, r0, #8 +10004a1a: f88d 1001 strb.w r1, [sp, #1] +10004a1e: aa00 add r2, sp, #0 +10004a20: 2103 movs r1, #3 +10004a22: 2020 movs r0, #32 +10004a24: e7ff b.n 10004a26 <.hal.flash.text_11> + +10004a26 <.hal.flash.text_11>: +10004a26: f7ff ffcb bl 100049c0 +10004a2a: bd01 pop {r0, pc} + +10004a2c : +10004a2c: b570 push {r4, r5, r6, lr} +10004a2e: f8df 66cc ldr.w r6, [pc, #1740] ; 100050fc <.hal.flash.text_43> +10004a32: 4604 mov r4, r0 +10004a34: 6830 ldr r0, [r6, #0] +10004a36: b082 sub sp, #8 +10004a38: 2500 movs r5, #0 +10004a3a: b11c cbz r4, 10004a44 +10004a3c: 2c02 cmp r4, #2 +10004a3e: d00d beq.n 10004a5c +10004a40: d307 bcc.n 10004a52 +10004a42: e019 b.n 10004a78 +10004a44: 9800 ldr r0, [sp, #0] +10004a46: f000 f96f bl 10004d28 +10004a4a: 2000 movs r0, #0 +10004a4c: f000 f94f bl 10004cee +10004a50: e018 b.n 10004a84 +10004a52: 2001 movs r0, #1 +10004a54: f000 f94b bl 10004cee +10004a58: 2508 movs r5, #8 +10004a5a: e013 b.n 10004a84 +10004a5c: 0040 lsls r0, r0, #1 +10004a5e: bf44 itt mi +10004a60: f20f 7044 addwmi r0, pc, #1860 ; 0x744 +10004a64: f7ff faec blmi 10004040 +10004a68: 2002 movs r0, #2 +10004a6a: f000 f940 bl 10004cee +10004a6e: 9900 ldr r1, [sp, #0] +10004a70: 2040 movs r0, #64 ; 0x40 +10004a72: f000 fa2f bl 10004ed4 +10004a76: e005 b.n 10004a84 +10004a78: 0040 lsls r0, r0, #1 +10004a7a: bf44 itt mi +10004a7c: f20f 7048 addwmi r0, pc, #1864 ; 0x748 +10004a80: f7ff fade blmi 10004040 +10004a84: 4629 mov r1, r5 +10004a86: 4620 mov r0, r4 +10004a88: f000 f816 bl 10004ab8 +10004a8c: b980 cbnz r0, 10004ab0 +10004a8e: 6830 ldr r0, [r6, #0] +10004a90: 0040 lsls r0, r0, #1 +10004a92: bf44 itt mi +10004a94: f20f 7050 addwmi r0, pc, #1872 ; 0x750 +10004a98: f7ff fad2 blmi 10004040 +10004a9c: f89d 0000 ldrb.w r0, [sp] +10004aa0: 2100 movs r1, #0 +10004aa2: f000 f9d4 bl 10004e4e +10004aa6: 2000 movs r0, #0 +10004aa8: f000 f921 bl 10004cee +10004aac: 2000 movs r0, #0 +10004aae: bd76 pop {r1, r2, r4, r5, r6, pc} +10004ab0: 2001 movs r0, #1 +10004ab2: bd76 pop {r1, r2, r4, r5, r6, pc} + +10004ab4 <.hal.flash.text_14>: +10004ab4: 0000000d .word 0x0000000d + +10004ab8 : +10004ab8: e92d 4ff3 stmdb sp!, {r0, r1, r4, r5, r6, r7, r8, r9, sl, fp, lr} +10004abc: f8df 0640 ldr.w r0, [pc, #1600] ; 10005100 <.hal.flash.text_44> +10004ac0: b089 sub sp, #36 ; 0x24 +10004ac2: 6800 ldr r0, [r0, #0] +10004ac4: f89d 1024 ldrb.w r1, [sp, #36] ; 0x24 +10004ac8: f3c0 1002 ubfx r0, r0, #4, #3 +10004acc: 9004 str r0, [sp, #16] +10004ace: 2218 movs r2, #24 +10004ad0: f8df 0630 ldr.w r0, [pc, #1584] ; 10005104 <.hal.flash.text_45> +10004ad4: fb02 0001 mla r0, r2, r1, r0 +10004ad8: 9005 str r0, [sp, #20] +10004ada: 2400 movs r4, #0 +10004adc: 9904 ldr r1, [sp, #16] +10004ade: eb00 0081 add.w r0, r0, r1, lsl #2 +10004ae2: 9001 str r0, [sp, #4] +10004ae4: 78c0 ldrb r0, [r0, #3] +10004ae6: b928 cbnz r0, 10004af4 +10004ae8: 9904 ldr r1, [sp, #16] +10004aea: f89d 0024 ldrb.w r0, [sp, #36] ; 0x24 +10004aee: b2c9 uxtb r1, r1 +10004af0: f000 fa26 bl 10004f40 +10004af4: 9801 ldr r0, [sp, #4] +10004af6: 78c0 ldrb r0, [r0, #3] +10004af8: b308 cbz r0, 10004b3e +10004afa: f8df 160c ldr.w r1, [pc, #1548] ; 10005108 <.hal.flash.text_46> +10004afe: 600c str r4, [r1, #0] +10004b00: 9805 ldr r0, [sp, #20] +10004b02: 9904 ldr r1, [sp, #16] +10004b04: f810 0021 ldrb.w r0, [r0, r1, lsl #2] +10004b08: f8df 15fc ldr.w r1, [pc, #1532] ; 10005108 <.hal.flash.text_46> +10004b0c: 60c8 str r0, [r1, #12] +10004b0e: f8df 05fc ldr.w r0, [pc, #1532] ; 1000510c <.hal.flash.text_47> +10004b12: 6800 ldr r0, [r0, #0] +10004b14: 9901 ldr r1, [sp, #4] +10004b16: 7849 ldrb r1, [r1, #1] +10004b18: 0c00 lsrs r0, r0, #16 +10004b1a: f000 f8d3 bl 10004cc4 <.hal.flash.text_17> +10004b1e: f8df 05f0 ldr.w r0, [pc, #1520] ; 10005110 <.hal.flash.text_48> +10004b22: 6800 ldr r0, [r0, #0] +10004b24: 9901 ldr r1, [sp, #4] +10004b26: 7889 ldrb r1, [r1, #2] +10004b28: 0a00 lsrs r0, r0, #8 +10004b2a: f000 f8c5 bl 10004cb8 <.hal.flash.text_16> +10004b2e: 2001 movs r0, #1 +10004b30: f000 f8d3 bl 10004cda <.hal.flash.text_19> +10004b34: f7ff ff00 bl 10004938 +10004b38: 2800 cmp r0, #0 +10004b3a: f040 80b1 bne.w 10004ca0 +10004b3e: f8df 05bc ldr.w r0, [pc, #1468] ; 100050fc <.hal.flash.text_43> +10004b42: 6800 ldr r0, [r0, #0] +10004b44: 0040 lsls r0, r0, #1 +10004b46: bf44 itt mi +10004b48: f20f 60cc addwmi r0, pc, #1740 ; 0x6cc +10004b4c: f7ff fa78 blmi 10004040 +10004b50: 2001 movs r0, #1 +10004b52: 2500 movs r5, #0 +10004b54: 4626 mov r6, r4 +10004b56: 46a2 mov sl, r4 +10004b58: 9403 str r4, [sp, #12] +10004b5a: 9000 str r0, [sp, #0] +10004b5c: f000 f8b8 bl 10004cd0 <.hal.flash.text_18> +10004b60: 9800 ldr r0, [sp, #0] +10004b62: b280 uxth r0, r0 +10004b64: 60c8 str r0, [r1, #12] +10004b66: 2001 movs r0, #1 +10004b68: 6008 str r0, [r1, #0] +10004b6a: 9900 ldr r1, [sp, #0] +10004b6c: 980a ldr r0, [sp, #40] ; 0x28 +10004b6e: 4348 muls r0, r1 +10004b70: 0040 lsls r0, r0, #1 +10004b72: 9006 str r0, [sp, #24] +10004b74: e013 b.n 10004b9e +10004b76: b157 cbz r7, 10004b8e +10004b78: 2c01 cmp r4, #1 +10004b7a: d003 beq.n 10004b84 +10004b7c: eba8 0009 sub.w r0, r8, r9 +10004b80: 4583 cmp fp, r0 +10004b82: d204 bcs.n 10004b8e +10004b84: 9e00 ldr r6, [sp, #0] +10004b86: 9d02 ldr r5, [sp, #8] +10004b88: f8cd 900c str.w r9, [sp, #12] +10004b8c: 46c2 mov sl, r8 +10004b8e: 2700 movs r7, #0 +10004b90: f108 0801 add.w r8, r8, #1 +10004b94: f1b8 0f64 cmp.w r8, #100 ; 0x64 +10004b98: d319 bcc.n 10004bce +10004b9a: 9802 ldr r0, [sp, #8] +10004b9c: 1c40 adds r0, r0, #1 +10004b9e: 9002 str r0, [sp, #8] +10004ba0: 9906 ldr r1, [sp, #24] +10004ba2: 9802 ldr r0, [sp, #8] +10004ba4: 3114 adds r1, #20 +10004ba6: 4288 cmp r0, r1 +10004ba8: d234 bcs.n 10004c14 +10004baa: f000 f891 bl 10004cd0 <.hal.flash.text_18> +10004bae: 2700 movs r7, #0 +10004bb0: f8df 0558 ldr.w r0, [pc, #1368] ; 1000510c <.hal.flash.text_47> +10004bb4: 6800 ldr r0, [r0, #0] +10004bb6: 9902 ldr r1, [sp, #8] +10004bb8: 0c00 lsrs r0, r0, #16 +10004bba: b289 uxth r1, r1 +10004bbc: f000 f882 bl 10004cc4 <.hal.flash.text_17> +10004bc0: 2001 movs r0, #1 +10004bc2: f8df 1544 ldr.w r1, [pc, #1348] ; 10005108 <.hal.flash.text_46> +10004bc6: f04f 0963 mov.w r9, #99 ; 0x63 +10004bca: 6008 str r0, [r1, #0] +10004bcc: 46b8 mov r8, r7 +10004bce: f8df 0540 ldr.w r0, [pc, #1344] ; 10005110 <.hal.flash.text_48> +10004bd2: 6800 ldr r0, [r0, #0] +10004bd4: 0a00 lsrs r0, r0, #8 +10004bd6: fa5f f188 uxtb.w r1, r8 +10004bda: f000 f86d bl 10004cb8 <.hal.flash.text_16> +10004bde: 9803 ldr r0, [sp, #12] +10004be0: ebaa 0b00 sub.w fp, sl, r0 +10004be4: f7ff fea8 bl 10004938 +10004be8: 2800 cmp r0, #0 +10004bea: d0c4 beq.n 10004b76 +10004bec: b90f cbnz r7, 10004bf2 +10004bee: 46c1 mov r9, r8 +10004bf0: 1c64 adds r4, r4, #1 +10004bf2: f1b8 0f63 cmp.w r8, #99 ; 0x63 +10004bf6: d10b bne.n 10004c10 +10004bf8: 2c01 cmp r4, #1 +10004bfa: d003 beq.n 10004c04 +10004bfc: f1c9 0063 rsb r0, r9, #99 ; 0x63 +10004c00: 4583 cmp fp, r0 +10004c02: d205 bcs.n 10004c10 +10004c04: 9e00 ldr r6, [sp, #0] +10004c06: 9d02 ldr r5, [sp, #8] +10004c08: f8cd 900c str.w r9, [sp, #12] +10004c0c: f04f 0a63 mov.w sl, #99 ; 0x63 +10004c10: 2701 movs r7, #1 +10004c12: e7bd b.n 10004b90 +10004c14: 2c00 cmp r4, #0 +10004c16: d047 beq.n 10004ca8 +10004c18: b2b6 uxth r6, r6 +10004c1a: f000 f863 bl 10004ce4 <.hal.flash.text_20> +10004c1e: d510 bpl.n 10004c42 +10004c20: f20f 6008 addw r0, pc, #1544 ; 0x608 +10004c24: f7ff fa0c bl 10004040 +10004c28: f000 f85c bl 10004ce4 <.hal.flash.text_20> +10004c2c: d509 bpl.n 10004c42 +10004c2e: 9b03 ldr r3, [sp, #12] +10004c30: f20f 6014 addw r0, pc, #1556 ; 0x614 +10004c34: f8cd a000 str.w sl, [sp] +10004c38: b2ad uxth r5, r5 +10004c3a: 462a mov r2, r5 +10004c3c: 4631 mov r1, r6 +10004c3e: f7ff f9ff bl 10004040 +10004c42: f000 f845 bl 10004cd0 <.hal.flash.text_18> +10004c46: b2ad uxth r5, r5 +10004c48: 0530 lsls r0, r6, #20 +10004c4a: 0d00 lsrs r0, r0, #20 +10004c4c: 60c8 str r0, [r1, #12] +10004c4e: 9805 ldr r0, [sp, #20] +10004c50: 9904 ldr r1, [sp, #16] +10004c52: f800 6021 strb.w r6, [r0, r1, lsl #2] +10004c56: f8df 04b4 ldr.w r0, [pc, #1204] ; 1000510c <.hal.flash.text_47> +10004c5a: f8df 14b0 ldr.w r1, [pc, #1200] ; 1000510c <.hal.flash.text_47> +10004c5e: 6800 ldr r0, [r0, #0] +10004c60: 0c00 lsrs r0, r0, #16 +10004c62: ea45 4000 orr.w r0, r5, r0, lsl #16 +10004c66: 6008 str r0, [r1, #0] +10004c68: f8df 14a4 ldr.w r1, [pc, #1188] ; 10005110 <.hal.flash.text_48> +10004c6c: 9801 ldr r0, [sp, #4] +10004c6e: 7045 strb r5, [r0, #1] +10004c70: 9803 ldr r0, [sp, #12] +10004c72: 6809 ldr r1, [r1, #0] +10004c74: 4450 add r0, sl +10004c76: 0840 lsrs r0, r0, #1 +10004c78: 0a09 lsrs r1, r1, #8 +10004c7a: b2c2 uxtb r2, r0 +10004c7c: ea42 2101 orr.w r1, r2, r1, lsl #8 +10004c80: f8df 248c ldr.w r2, [pc, #1164] ; 10005110 <.hal.flash.text_48> +10004c84: 6011 str r1, [r2, #0] +10004c86: 9901 ldr r1, [sp, #4] +10004c88: 7088 strb r0, [r1, #2] +10004c8a: 2001 movs r0, #1 +10004c8c: 9901 ldr r1, [sp, #4] +10004c8e: 70c8 strb r0, [r1, #3] +10004c90: f000 f823 bl 10004cda <.hal.flash.text_19> +10004c94: 9904 ldr r1, [sp, #16] +10004c96: f89d 0024 ldrb.w r0, [sp, #36] ; 0x24 +10004c9a: b2c9 uxtb r1, r1 +10004c9c: f000 f9a5 bl 10004fea +10004ca0: 2001 movs r0, #1 +10004ca2: b00b add sp, #44 ; 0x2c +10004ca4: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} +10004ca8: 9800 ldr r0, [sp, #0] +10004caa: 1c40 adds r0, r0, #1 +10004cac: 2805 cmp r0, #5 +10004cae: 9000 str r0, [sp, #0] +10004cb0: f4ff af54 bcc.w 10004b5c +10004cb4: 2000 movs r0, #0 +10004cb6: e7f4 b.n 10004ca2 + +10004cb8 <.hal.flash.text_16>: +10004cb8: ea41 2000 orr.w r0, r1, r0, lsl #8 +10004cbc: f8df 1450 ldr.w r1, [pc, #1104] ; 10005110 <.hal.flash.text_48> +10004cc0: 6008 str r0, [r1, #0] +10004cc2: 4770 bx lr + +10004cc4 <.hal.flash.text_17>: +10004cc4: ea41 4000 orr.w r0, r1, r0, lsl #16 +10004cc8: f8df 1440 ldr.w r1, [pc, #1088] ; 1000510c <.hal.flash.text_47> +10004ccc: 6008 str r0, [r1, #0] +10004cce: 4770 bx lr + +10004cd0 <.hal.flash.text_18>: +10004cd0: f8df 1434 ldr.w r1, [pc, #1076] ; 10005108 <.hal.flash.text_46> +10004cd4: 2000 movs r0, #0 +10004cd6: 6008 str r0, [r1, #0] +10004cd8: 4770 bx lr + +10004cda <.hal.flash.text_19>: +10004cda: f8df 142c ldr.w r1, [pc, #1068] ; 10005108 <.hal.flash.text_46> +10004cde: 6008 str r0, [r1, #0] +10004ce0: 9807 ldr r0, [sp, #28] +10004ce2: e021 b.n 10004d28 + +10004ce4 <.hal.flash.text_20>: +10004ce4: f8df 0414 ldr.w r0, [pc, #1044] ; 100050fc <.hal.flash.text_43> +10004ce8: 6800 ldr r0, [r0, #0] +10004cea: 0040 lsls r0, r0, #1 +10004cec: 4770 bx lr + +10004cee : +10004cee: f8df 2418 ldr.w r2, [pc, #1048] ; 10005108 <.hal.flash.text_46> +10004cf2: 2100 movs r1, #0 +10004cf4: 6011 str r1, [r2, #0] +10004cf6: f8df 141c ldr.w r1, [pc, #1052] ; 10005114 <.hal.flash.text_49> +10004cfa: b938 cbnz r0, 10004d0c +10004cfc: 2238 movs r2, #56 ; 0x38 +10004cfe: 620a str r2, [r1, #32] +10004d00: 22eb movs r2, #235 ; 0xeb +10004d02: 60ca str r2, [r1, #12] +10004d04: 6bca ldr r2, [r1, #60] ; 0x3c +10004d06: f422 72ff bic.w r2, r2, #510 ; 0x1fe +10004d0a: 63ca str r2, [r1, #60] ; 0x3c +10004d0c: 2801 cmp r0, #1 +10004d0e: d106 bne.n 10004d1e +10004d10: 203b movs r0, #59 ; 0x3b +10004d12: 6008 str r0, [r1, #0] +10004d14: f240 2202 movw r2, #514 ; 0x202 +10004d18: 6bc8 ldr r0, [r1, #60] ; 0x3c +10004d1a: 4310 orrs r0, r2 +10004d1c: e002 b.n 10004d24 +10004d1e: 2802 cmp r0, #2 +10004d20: d101 bne.n 10004d26 +10004d22: 6bc8 ldr r0, [r1, #60] ; 0x3c +10004d24: 63c8 str r0, [r1, #60] ; 0x3c +10004d26: 4770 bx lr + +10004d28 : +10004d28: b510 push {r4, lr} +10004d2a: f000 f80d bl 10004d48 <.hal.flash.text_23> +10004d2e: d506 bpl.n 10004d3e +10004d30: 4622 mov r2, r4 +10004d32: f20f 514c addw r1, pc, #1356 ; 0x54c +10004d36: f20f 5068 addw r0, pc, #1384 ; 0x568 +10004d3a: f7ff f981 bl 10004040 +10004d3e: f7ff fe5e bl 100049fe <.hal.flash.text_6> +10004d42: 07c0 lsls r0, r0, #31 +10004d44: d4fb bmi.n 10004d3e +10004d46: bd10 pop {r4, pc} + +10004d48 <.hal.flash.text_23>: +10004d48: 4604 mov r4, r0 +10004d4a: f8df 03cc ldr.w r0, [pc, #972] ; 10005118 <.hal.flash.text_50> +10004d4e: 6800 ldr r0, [r0, #0] +10004d50: 04c0 lsls r0, r0, #19 +10004d52: 4770 bx lr + +10004d54 : +10004d54: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +10004d58: 4682 mov sl, r0 +10004d5a: f8df 03a4 ldr.w r0, [pc, #932] ; 10005100 <.hal.flash.text_44> +10004d5e: f8df 13a4 ldr.w r1, [pc, #932] ; 10005104 <.hal.flash.text_45> +10004d62: 6800 ldr r0, [r0, #0] +10004d64: f3c0 1002 ubfx r0, r0, #4, #3 +10004d68: eb01 0780 add.w r7, r1, r0, lsl #2 +10004d6c: 78f9 ldrb r1, [r7, #3] +10004d6e: b921 cbnz r1, 10004d7a +10004d70: af00 add r7, sp, #0 +10004d72: aa00 add r2, sp, #0 +10004d74: 2101 movs r1, #1 +10004d76: f7ff fdd7 bl 10004928 +10004d7a: f7ff ffe6 bl 10004d4a <.hal.flash.text_23+0x2> +10004d7e: d507 bpl.n 10004d90 +10004d80: 463b mov r3, r7 +10004d82: 4652 mov r2, sl +10004d84: f20f 5130 addw r1, pc, #1328 ; 0x530 +10004d88: f20f 5048 addw r0, pc, #1352 ; 0x548 +10004d8c: f7ff f958 bl 10004040 +10004d90: f8df 4378 ldr.w r4, [pc, #888] ; 1000510c <.hal.flash.text_47> +10004d94: f8df 634c ldr.w r6, [pc, #844] ; 100050e4 <.hal.flash.text_35> +10004d98: 6825 ldr r5, [r4, #0] +10004d9a: 7879 ldrb r1, [r7, #1] +10004d9c: f8df 8370 ldr.w r8, [pc, #880] ; 10005110 <.hal.flash.text_48> +10004da0: 0c28 lsrs r0, r5, #16 +10004da2: ea41 4000 orr.w r0, r1, r0, lsl #16 +10004da6: 6020 str r0, [r4, #0] +10004da8: f8d6 b014 ldr.w fp, [r6, #20] +10004dac: 7839 ldrb r1, [r7, #0] +10004dae: ea4f 401b mov.w r0, fp, lsr #16 +10004db2: ea41 4000 orr.w r0, r1, r0, lsl #16 +10004db6: 6170 str r0, [r6, #20] +10004db8: f8d8 9000 ldr.w r9, [r8] +10004dbc: 78b9 ldrb r1, [r7, #2] +10004dbe: ea4f 2019 mov.w r0, r9, lsr #8 +10004dc2: ea41 2000 orr.w r0, r1, r0, lsl #8 +10004dc6: f8c8 0000 str.w r0, [r8] +10004dca: 2000 movs r0, #0 +10004dcc: 60b0 str r0, [r6, #8] +10004dce: 6830 ldr r0, [r6, #0] +10004dd0: f420 2070 bic.w r0, r0, #983040 ; 0xf0000 +10004dd4: f440 7040 orr.w r0, r0, #768 ; 0x300 +10004dd8: 6030 str r0, [r6, #0] +10004dda: 48c6 ldr r0, [pc, #792] ; (100050f4 <.hal.flash.text_39>) +10004ddc: f880 a000 strb.w sl, [r0] +10004de0: 2001 movs r0, #1 +10004de2: 60b0 str r0, [r6, #8] +10004de4: f7ff fda4 bl 10004930 +10004de8: 2000 movs r0, #0 +10004dea: 60b0 str r0, [r6, #8] +10004dec: b2a9 uxth r1, r5 +10004dee: 6820 ldr r0, [r4, #0] +10004df0: 0c00 lsrs r0, r0, #16 +10004df2: ea41 4000 orr.w r0, r1, r0, lsl #16 +10004df6: 6020 str r0, [r4, #0] +10004df8: fa1f f18b uxth.w r1, fp +10004dfc: 6970 ldr r0, [r6, #20] +10004dfe: 0c00 lsrs r0, r0, #16 +10004e00: ea41 4000 orr.w r0, r1, r0, lsl #16 +10004e04: 6170 str r0, [r6, #20] +10004e06: fa5f f189 uxtb.w r1, r9 +10004e0a: f8d8 0000 ldr.w r0, [r8] +10004e0e: 0a00 lsrs r0, r0, #8 +10004e10: ea41 2000 orr.w r0, r1, r0, lsl #8 +10004e14: f8c8 0000 str.w r0, [r8] +10004e18: e8bd 8ff1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +10004e1c : +10004e1c: b538 push {r3, r4, r5, lr} +10004e1e: f7ff ff93 bl 10004d48 <.hal.flash.text_23> +10004e22: d506 bpl.n 10004e32 +10004e24: 4622 mov r2, r4 +10004e26: f20f 41c8 addw r1, pc, #1224 ; 0x4c8 +10004e2a: f20f 4074 addw r0, pc, #1140 ; 0x474 +10004e2e: f7ff f907 bl 10004040 +10004e32: 4dba ldr r5, [pc, #744] ; (1000511c <.hal.flash.text_51>) +10004e34: 2000 movs r0, #0 +10004e36: 6068 str r0, [r5, #4] +10004e38: 4621 mov r1, r4 +10004e3a: 2001 movs r0, #1 +10004e3c: 6028 str r0, [r5, #0] +10004e3e: 2005 movs r0, #5 +10004e40: f7ff ff88 bl 10004d54 +10004e44: 48ab ldr r0, [pc, #684] ; (100050f4 <.hal.flash.text_39>) +10004e46: 7800 ldrb r0, [r0, #0] +10004e48: 2100 movs r1, #0 +10004e4a: 6069 str r1, [r5, #4] +10004e4c: bd32 pop {r1, r4, r5, pc} + +10004e4e : +10004e4e: b570 push {r4, r5, r6, lr} +10004e50: 4606 mov r6, r0 +10004e52: 48ab ldr r0, [pc, #684] ; (10005100 <.hal.flash.text_44>) +10004e54: b082 sub sp, #8 +10004e56: 460c mov r4, r1 +10004e58: 6800 ldr r0, [r0, #0] +10004e5a: 49aa ldr r1, [pc, #680] ; (10005104 <.hal.flash.text_45>) +10004e5c: 2218 movs r2, #24 +10004e5e: f3c0 1002 ubfx r0, r0, #4, #3 +10004e62: fb02 1104 mla r1, r2, r4, r1 +10004e66: eb01 0180 add.w r1, r1, r0, lsl #2 +10004e6a: ad00 add r5, sp, #0 +10004e6c: 78ca ldrb r2, [r1, #3] +10004e6e: 2a00 cmp r2, #0 +10004e70: bf11 iteee ne +10004e72: 460d movne r5, r1 +10004e74: aa00 addeq r2, sp, #0 +10004e76: 2101 moveq r1, #1 +10004e78: f7ff fd56 bleq 10004928 +10004e7c: 4899 ldr r0, [pc, #612] ; (100050e4 <.hal.flash.text_35>) +10004e7e: 2100 movs r1, #0 +10004e80: 6081 str r1, [r0, #8] +10004e82: 6146 str r6, [r0, #20] +10004e84: 2101 movs r1, #1 +10004e86: 6101 str r1, [r0, #16] +10004e88: 49a0 ldr r1, [pc, #640] ; (1000510c <.hal.flash.text_47>) +10004e8a: 680a ldr r2, [r1, #0] +10004e8c: 786b ldrb r3, [r5, #1] +10004e8e: 0c12 lsrs r2, r2, #16 +10004e90: ea43 4202 orr.w r2, r3, r2, lsl #16 +10004e94: 600a str r2, [r1, #0] +10004e96: 499e ldr r1, [pc, #632] ; (10005110 <.hal.flash.text_48>) +10004e98: 680a ldr r2, [r1, #0] +10004e9a: 78ab ldrb r3, [r5, #2] +10004e9c: 0a12 lsrs r2, r2, #8 +10004e9e: ea43 2202 orr.w r2, r3, r2, lsl #8 +10004ea2: 600a str r2, [r1, #0] +10004ea4: 2104 movs r1, #4 +10004ea6: 6041 str r1, [r0, #4] +10004ea8: b11c cbz r4, 10004eb2 +10004eaa: 2c02 cmp r4, #2 +10004eac: d00b beq.n 10004ec6 +10004eae: d304 bcc.n 10004eba +10004eb0: bd73 pop {r0, r1, r4, r5, r6, pc} +10004eb2: 6801 ldr r1, [r0, #0] +10004eb4: f421 117c bic.w r1, r1, #4128768 ; 0x3f0000 +10004eb8: e00a b.n 10004ed0 +10004eba: 6801 ldr r1, [r0, #0] +10004ebc: f421 117c bic.w r1, r1, #4128768 ; 0x3f0000 +10004ec0: f441 21a0 orr.w r1, r1, #327680 ; 0x50000 +10004ec4: e004 b.n 10004ed0 +10004ec6: 6801 ldr r1, [r0, #0] +10004ec8: f421 117c bic.w r1, r1, #4128768 ; 0x3f0000 +10004ecc: f441 2120 orr.w r1, r1, #655360 ; 0xa0000 +10004ed0: 6001 str r1, [r0, #0] +10004ed2: bd73 pop {r0, r1, r4, r5, r6, pc} + +10004ed4 : +10004ed4: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +10004ed8: 4e84 ldr r6, [pc, #528] ; (100050ec <.hal.flash.text_37>) +10004eda: 4604 mov r4, r0 +10004edc: 4688 mov r8, r1 +10004ede: 6837 ldr r7, [r6, #0] +10004ee0: 4643 mov r3, r8 +10004ee2: f7ff fd8f bl 10004a04 <.hal.flash.text_7+0x2> +10004ee6: 4d7f ldr r5, [pc, #508] ; (100050e4 <.hal.flash.text_35>) +10004ee8: 2000 movs r0, #0 +10004eea: 60a8 str r0, [r5, #8] +10004eec: 2101 movs r1, #1 +10004eee: 6828 ldr r0, [r5, #0] +10004ef0: f420 7040 bic.w r0, r0, #768 ; 0x300 +10004ef4: 6028 str r0, [r5, #0] +10004ef6: 2001 movs r0, #1 +10004ef8: 6030 str r0, [r6, #0] +10004efa: 487e ldr r0, [pc, #504] ; (100050f4 <.hal.flash.text_39>) +10004efc: 7001 strb r1, [r0, #0] +10004efe: 7004 strb r4, [r0, #0] +10004f00: 60a9 str r1, [r5, #8] +10004f02: f7ff fd15 bl 10004930 +10004f06: 2000 movs r0, #0 +10004f08: 60a8 str r0, [r5, #8] +10004f0a: 6037 str r7, [r6, #0] +10004f0c: 4640 mov r0, r8 +10004f0e: e8bd 41f0 ldmia.w sp!, {r4, r5, r6, r7, r8, lr} +10004f12: e709 b.n 10004d28 + +10004f14 : +10004f14: b580 push {r7, lr} +10004f16: f7ff ff07 bl 10004d28 +10004f1a: 2001 movs r0, #1 +10004f1c: bd02 pop {r1, pc} + +10004f1e : +10004f1e: b580 push {r7, lr} +10004f20: 2000 movs r0, #0 +10004f22: f7ff fee4 bl 10004cee +10004f26: 2100 movs r1, #0 +10004f28: 2000 movs r0, #0 +10004f2a: f7ff fdc5 bl 10004ab8 +10004f2e: b100 cbz r0, 10004f32 +10004f30: 2001 movs r0, #1 +10004f32: bd02 pop {r1, pc} + +10004f34 : +10004f34: 4870 ldr r0, [pc, #448] ; (100050f8 <.hal.flash.text_42>) +10004f36: 6801 ldr r1, [r0, #0] +10004f38: 0849 lsrs r1, r1, #1 +10004f3a: 0049 lsls r1, r1, #1 +10004f3c: 6001 str r1, [r0, #0] +10004f3e: 4770 bx lr + +10004f40 : +10004f40: b530 push {r4, r5, lr} +10004f42: 460a mov r2, r1 +10004f44: 00d1 lsls r1, r2, #3 +10004f46: 2330 movs r3, #48 ; 0x30 +10004f48: fb03 1400 mla r4, r3, r0, r1 +10004f4c: 4974 ldr r1, [pc, #464] ; (10005120 <.hal.flash.text_52>) +10004f4e: b083 sub sp, #12 +10004f50: 5909 ldr r1, [r1, r4] +10004f52: 9100 str r1, [sp, #0] +10004f54: f111 0f01 cmn.w r1, #1 +10004f58: d038 beq.n 10004fcc +10004f5a: 4b72 ldr r3, [pc, #456] ; (10005124 <.hal.flash.text_53>) +10004f5c: 591b ldr r3, [r3, r4] +10004f5e: ea83 0501 eor.w r5, r3, r1 +10004f62: f115 0f01 cmn.w r5, #1 +10004f66: d122 bne.n 10004fae +10004f68: 4966 ldr r1, [pc, #408] ; (10005104 <.hal.flash.text_45>) +10004f6a: 2318 movs r3, #24 +10004f6c: fb03 1100 mla r1, r3, r0, r1 +10004f70: f89d 3000 ldrb.w r3, [sp] +10004f74: f801 3022 strb.w r3, [r1, r2, lsl #2] +10004f78: eb01 0382 add.w r3, r1, r2, lsl #2 +10004f7c: f89d 4001 ldrb.w r4, [sp, #1] +10004f80: 705c strb r4, [r3, #1] +10004f82: f89d 4002 ldrb.w r4, [sp, #2] +10004f86: 709c strb r4, [r3, #2] +10004f88: f89d 4003 ldrb.w r4, [sp, #3] +10004f8c: 70dc strb r4, [r3, #3] +10004f8e: 4c62 ldr r4, [pc, #392] ; (10005118 <.hal.flash.text_50>) +10004f90: 6824 ldr r4, [r4, #0] +10004f92: 04e4 lsls r4, r4, #19 +10004f94: d51a bpl.n 10004fcc +10004f96: 789c ldrb r4, [r3, #2] +10004f98: 9401 str r4, [sp, #4] +10004f9a: 785b ldrb r3, [r3, #1] +10004f9c: 9300 str r3, [sp, #0] +10004f9e: f811 3022 ldrb.w r3, [r1, r2, lsl #2] +10004fa2: 4601 mov r1, r0 +10004fa4: f20f 306c addw r0, pc, #876 ; 0x36c +10004fa8: f7ff f84a bl 10004040 +10004fac: bd37 pop {r0, r1, r2, r4, r5, pc} +10004fae: 484e ldr r0, [pc, #312] ; (100050e8 <.hal.flash.text_36>) +10004fb0: 6800 ldr r0, [r0, #0] +10004fb2: 04c0 lsls r0, r0, #19 +10004fb4: d50a bpl.n 10004fcc +10004fb6: 460a mov r2, r1 +10004fb8: f504 4110 add.w r1, r4, #36864 ; 0x9000 +10004fbc: b003 add sp, #12 +10004fbe: e8bd 4030 ldmia.w sp!, {r4, r5, lr} +10004fc2: 3180 adds r1, #128 ; 0x80 +10004fc4: f20f 30c4 addw r0, pc, #964 ; 0x3c4 +10004fc8: f7ff b83a b.w 10004040 +10004fcc: bd37 pop {r0, r1, r2, r4, r5, pc} + +10004fce : +10004fce: b538 push {r3, r4, r5, lr} +10004fd0: 2400 movs r4, #0 +10004fd2: 2500 movs r5, #0 +10004fd4: 4629 mov r1, r5 +10004fd6: 4620 mov r0, r4 +10004fd8: f7ff ffb2 bl 10004f40 +10004fdc: 1c6d adds r5, r5, #1 +10004fde: 2d06 cmp r5, #6 +10004fe0: dbf8 blt.n 10004fd4 +10004fe2: 1c64 adds r4, r4, #1 +10004fe4: 2c03 cmp r4, #3 +10004fe6: dbf4 blt.n 10004fd2 +10004fe8: bd31 pop {r0, r4, r5, pc} + +10004fea : +10004fea: e92d 4ffe stmdb sp!, {r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +10004fee: 4e4a ldr r6, [pc, #296] ; (10005118 <.hal.flash.text_50>) +10004ff0: 4682 mov sl, r0 +10004ff2: 6830 ldr r0, [r6, #0] +10004ff4: 04c0 lsls r0, r0, #19 +10004ff6: 4688 mov r8, r1 +10004ff8: d505 bpl.n 10005006 +10004ffa: 4642 mov r2, r8 +10004ffc: 4651 mov r1, sl +10004ffe: f20f 30d8 addw r0, pc, #984 ; 0x3d8 +10005002: f7ff f81d bl 10004040 +10005006: ea4f 00c8 mov.w r0, r8, lsl #3 +1000500a: 2130 movs r1, #48 ; 0x30 +1000500c: fb01 070a mla r7, r1, sl, r0 +10005010: 4843 ldr r0, [pc, #268] ; (10005120 <.hal.flash.text_52>) +10005012: 4c3a ldr r4, [pc, #232] ; (100050fc <.hal.flash.text_43>) +10005014: 59c2 ldr r2, [r0, r7] +10005016: 9202 str r2, [sp, #8] +10005018: f112 0f01 cmn.w r2, #1 +1000501c: d152 bne.n 100050c4 +1000501e: 4839 ldr r0, [pc, #228] ; (10005104 <.hal.flash.text_45>) +10005020: 2118 movs r1, #24 +10005022: fb01 090a mla r9, r1, sl, r0 +10005026: eb09 0588 add.w r5, r9, r8, lsl #2 +1000502a: f819 0028 ldrb.w r0, [r9, r8, lsl #2] +1000502e: 493c ldr r1, [pc, #240] ; (10005120 <.hal.flash.text_52>) +10005030: f88d 0008 strb.w r0, [sp, #8] +10005034: 7868 ldrb r0, [r5, #1] +10005036: f88d 0009 strb.w r0, [sp, #9] +1000503a: 78a8 ldrb r0, [r5, #2] +1000503c: f88d 000a strb.w r0, [sp, #10] +10005040: 78e8 ldrb r0, [r5, #3] +10005042: f88d 000b strb.w r0, [sp, #11] +10005046: 9802 ldr r0, [sp, #8] +10005048: 51c8 str r0, [r1, r7] +1000504a: 9800 ldr r0, [sp, #0] +1000504c: f7ff fe6c bl 10004d28 +10005050: 9802 ldr r0, [sp, #8] +10005052: ea6f 0b00 mvn.w fp, r0 +10005056: 4833 ldr r0, [pc, #204] ; (10005124 <.hal.flash.text_53>) +10005058: f840 b007 str.w fp, [r0, r7] +1000505c: 9800 ldr r0, [sp, #0] +1000505e: f7ff fe63 bl 10004d28 +10005062: 6830 ldr r0, [r6, #0] +10005064: 04c0 lsls r0, r0, #19 +10005066: d50b bpl.n 10005080 +10005068: 78a8 ldrb r0, [r5, #2] +1000506a: 9001 str r0, [sp, #4] +1000506c: 4642 mov r2, r8 +1000506e: 7868 ldrb r0, [r5, #1] +10005070: 9000 str r0, [sp, #0] +10005072: 4651 mov r1, sl +10005074: f819 3028 ldrb.w r3, [r9, r8, lsl #2] +10005078: f20f 3094 addw r0, pc, #916 ; 0x394 +1000507c: f7fe ffe0 bl 10004040 +10005080: 4827 ldr r0, [pc, #156] ; (10005120 <.hal.flash.text_52>) +10005082: f20f 4504 addw r5, pc, #1028 ; 0x404 +10005086: 59c0 ldr r0, [r0, r7] +10005088: 9902 ldr r1, [sp, #8] +1000508a: 4288 cmp r0, r1 +1000508c: d009 beq.n 100050a2 +1000508e: 6820 ldr r0, [r4, #0] +10005090: 04c0 lsls r0, r0, #19 +10005092: d506 bpl.n 100050a2 +10005094: 4822 ldr r0, [pc, #136] ; (10005120 <.hal.flash.text_52>) +10005096: 59c3 ldr r3, [r0, r7] +10005098: 460a mov r2, r1 +1000509a: 4639 mov r1, r7 +1000509c: 4628 mov r0, r5 +1000509e: f7fe ffcf bl 10004040 +100050a2: 4820 ldr r0, [pc, #128] ; (10005124 <.hal.flash.text_53>) +100050a4: 59c0 ldr r0, [r0, r7] +100050a6: 4558 cmp r0, fp +100050a8: d019 beq.n 100050de +100050aa: 6820 ldr r0, [r4, #0] +100050ac: 04c0 lsls r0, r0, #19 +100050ae: d516 bpl.n 100050de +100050b0: 481c ldr r0, [pc, #112] ; (10005124 <.hal.flash.text_53>) +100050b2: 59c3 ldr r3, [r0, r7] +100050b4: 465a mov r2, fp +100050b6: 1d39 adds r1, r7, #4 +100050b8: 4628 mov r0, r5 +100050ba: b003 add sp, #12 +100050bc: e8bd 4ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +100050c0: f7fe bfbe b.w 10004040 +100050c4: 6820 ldr r0, [r4, #0] +100050c6: 04c0 lsls r0, r0, #19 +100050c8: d509 bpl.n 100050de +100050ca: f507 4110 add.w r1, r7, #36864 ; 0x9000 +100050ce: b003 add sp, #12 +100050d0: e8bd 4ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +100050d4: 3180 adds r1, #128 ; 0x80 +100050d6: f20f 30f0 addw r0, pc, #1008 ; 0x3f0 +100050da: f7fe bfb1 b.w 10004040 +100050de: e8bd 8ff7 ldmia.w sp!, {r0, r1, r2, r4, r5, r6, r7, r8, r9, sl, fp, pc} + ... + +100050e4 <.hal.flash.text_35>: +100050e4: 40006000 .word 0x40006000 + +100050e8 <.hal.flash.text_36>: +100050e8: 1000030c .word 0x1000030c + +100050ec <.hal.flash.text_37>: +100050ec: 40006118 .word 0x40006118 + +100050f0 <.hal.flash.text_38>: +100050f0: fff0fcff .word 0xfff0fcff + +100050f4 <.hal.flash.text_39>: +100050f4: 40006060 .word 0x40006060 + +100050f8 <.hal.flash.text_42>: +100050f8: 400002c0 .word 0x400002c0 + +100050fc <.hal.flash.text_43>: +100050fc: 10000314 .word 0x10000314 + +10005100 <.hal.flash.text_44>: +10005100: 40000014 .word 0x40000014 + +10005104 <.hal.flash.text_45>: +10005104: 10048b18 .word 0x10048b18 + +10005108 <.hal.flash.text_46>: +10005108: 40006008 .word 0x40006008 + +1000510c <.hal.flash.text_47>: +1000510c: 4000611c .word 0x4000611c + +10005110 <.hal.flash.text_48>: +10005110: 40000300 .word 0x40000300 + +10005114 <.hal.flash.text_49>: +10005114: 400060e4 .word 0x400060e4 + +10005118 <.hal.flash.text_50>: +10005118: 10000310 .word 0x10000310 + +1000511c <.hal.flash.text_51>: +1000511c: 40006004 .word 0x40006004 + +10005120 <.hal.flash.text_52>: +10005120: 98009080 .word 0x98009080 + +10005124 <.hal.flash.text_53>: +10005124: 98009084 .word 0x98009084 + +10005128 : +10005128: 63697053 6d437854 74695764 74614468 SpicTxCmdWithDat +10005138: 6c745261 35393138 00000041 aRtl8195A... + +10005144 : +10005144: 50535b0d 49204649 255d666e 78302873 .[SPIF Inf]%s(0x +10005154: 202c7825 78257830 7830202c 202c7825 %x, 0x%x, 0x%x, +10005164: 78257830 00000a29 0x%x)... + +1000516c : +1000516c: 50535b0d 57204649 535d6e72 54636970 .[SPIF Wrn]SpicT +1000517c: 736e4978 6c745274 35393138 44203a41 xInstRtl8195A: D +1000518c: 20617461 73616850 654c2065 7420676e ata Phase Leng t +1000519c: 42206f6f 25286769 000a2964 oo Big(%d).. + +100051a8 : +100051a8: 696e490d 6c616974 69705320 6f462063 .Initial Spic Fo +100051b8: 62207275 6d207469 0a65646f 00000000 ur bit mode..... + +100051c8 : +100051c8: 206f4e0d 70707553 2074726f 20495053 .No Support SPI +100051d8: 65646f4d 21212121 21212121 0000000a Mode!!!!!!!!.... + +100051e8 : +100051e8: 4950530d 6c616320 61726269 6e6f6974 .SPI calibration +100051f8: 69616620 6e61206c 65722064 65766f63 fail and recove +10005208: 6e6f2072 69622065 6f6d2074 000a6564 r one bit mode.. + +10005218 : +10005218: 4950530d 6c616320 61726269 6e6f6974 .SPI calibration +10005228: 0000000a .... + +1000522c : +1000522c: 6e69460d 68742064 76612065 62616961 .Find the avaiab +1000523c: 7720656c 6f646e69 00000a77 le window... + +10005248 : +10005248: 7561420d 78253a64 7561203b 6c5f6f74 .Baud:%x; auto_l +10005258: 74676e65 78253a68 6544203b 2079616c ength:%x; Delay +10005268: 72617473 78253a74 6544203b 2079616c start:%x; Delay +10005278: 3a646e65 000a7825 end:%x.. + +10005280 : +10005280: 63697053 74696157 44706957 52656e6f SpicWaitWipDoneR +10005290: 6e696665 74526465 3931386c 00004135 efinedRtl8195A.. + +100052a0 : +100052a0: 50535b0d 49204649 255d666e 78302873 .[SPIF Inf]%s(0x +100052b0: 0a297825 00000000 %x)..... + +100052b8 : +100052b8: 63697053 6d437852 66655264 64656e69 SpicRxCmdRefined +100052c8: 386c7452 41353931 00000000 Rtl8195A.... + +100052d4 : +100052d4: 50535b0d 49204649 255d666e 78302873 .[SPIF Inf]%s(0x +100052e4: 202c7825 78257830 00000a29 %x, 0x%x)... + +100052f0 : +100052f0: 63697053 46746547 6873616c 74617453 SpicGetFlashStat +10005300: 65527375 656e6966 6c745264 35393138 usRefinedRtl8195 +10005310: 00000041 A... + +10005314 : +10005314: 50535b0d 49204649 535d666e 4e636970 .[SPIF Inf]SpicN +10005324: 61434d56 616f4c6c 43203a64 62696c61 VMCalLoad: Calib +10005334: 69746172 4c206e6f 6564616f 69422864 ration Loaded(Bi +10005344: 646f4d74 64252065 5043202c 6b6c4355 tMode %d, CPUClk +10005354: 29642520 6142203a 61526475 303d6574 %d): BaudRate=0 +10005364: 20782578 75446452 43796d6d 3d656c79 x%x RdDummyCyle= +10005374: 78257830 6c654420 694c7961 303d656e 0x%x DelayLine=0 +10005384: 0d782578 0000000a x%x..... + +1000538c : +1000538c: 50535b0d 57204649 535d6e72 4e636970 .[SPIF Wrn]SpicN +1000539c: 61434d56 616f4c6c 44203a64 20617461 VMCalLoad: Data +100053ac: 46206e69 6873616c 30204028 20782578 in Flash(@ 0x%x +100053bc: 7830203d 30207825 29782578 20736920 = 0x%x 0x%x) is +100053cc: 61766e49 0d64696c 0000000a Invalid..... + +100053d8 : +100053d8: 50535b0d 49204649 535d666e 4e636970 .[SPIF Inf]SpicN +100053e8: 61434d56 6f74536c 3d3d6572 6942203e VMCalStore==> Bi +100053f8: 646f4d74 64253d65 75704320 3d6b6c43 tMode=%d CpuClk= +10005408: 0a0d6425 00000000 %d...... + +10005410 : +10005410: 50535b0d 49204649 535d666e 4e636970 .[SPIF Inf]SpicN +10005420: 61434d56 6f74536c 42286572 6f4d7469 VMCalStore(BitMo +10005430: 25206564 43202c64 6c435550 6425206b de %d, CPUClk %d +10005440: 43203a29 62696c61 69746172 53206e6f ): Calibration S +10005450: 65726f74 42203a64 52647561 3d657461 tored: BaudRate= +10005460: 78257830 44645220 796d6d75 656c7943 0x%x RdDummyCyle +10005470: 2578303d 65442078 4c79616c 3d656e69 =0x%x DelayLine= +10005480: 78257830 00000a0d 0x%x.... + +10005488 : +10005488: 50535b0d 45204649 535d7272 4e636970 .[SPIF Err]SpicN +10005498: 61434d56 6f74536c 45206572 4f287272 VMCalStore Err(O +100054a8: 65736666 78303d74 2c297825 3d725720 ffset=0x%x), Wr= +100054b8: 78257830 3d645220 78257830 000a0d20 0x%x Rd=0x%x ... + +100054c8 : +100054c8: 50535b0d 45204649 535d7272 4e636970 .[SPIF Err]SpicN +100054d8: 61434d56 6f74536c 203a6572 20656854 VMCalStore: The +100054e8: 73616c66 656d2068 79726f6d 78304028 flash memory(@0x +100054f8: 3d207825 25783020 69202978 6f6e2073 %x = 0x%x) is no +10005508: 62612074 7420656c 6562206f 69727720 t able to be wri +10005518: 202c6574 73617245 74692065 72696620 te, Erase it fir +10005528: 21217473 00000a0d st!!.... + +10005530 : +10005530: f8df f000 ldr.w pc, [pc] ; 10005534 +10005534: 0000e1c1 .word 0x0000e1c1 + +10005538 : +10005538: f8df f000 ldr.w pc, [pc] ; 1000553c +1000553c: 0000d805 .word 0x0000d805 + +10005540 : +10005540: f7ff bff6 b.w 10005530 + +10005544 : +10005544: b510 push {r4, lr} +10005546: 4604 mov r4, r0 +10005548: 4809 ldr r0, [pc, #36] ; (10005570 ) +1000554a: 6801 ldr r1, [r0, #0] +1000554c: b959 cbnz r1, 10005566 +1000554e: 4909 ldr r1, [pc, #36] ; (10005574 ) +10005550: 6001 str r1, [r0, #0] +10005552: 4809 ldr r0, [pc, #36] ; (10005578 ) +10005554: 7800 ldrb r0, [r0, #0] +10005556: 0740 lsls r0, r0, #29 +10005558: d505 bpl.n 10005566 +1000555a: f20f 0120 addw r1, pc, #32 +1000555e: f20f 002c addw r0, pc, #44 ; 0x2c +10005562: f7fe fd6d bl 10004040 + +10005566 : +10005566: 4620 mov r0, r4 +10005568: e8bd 4010 ldmia.w sp!, {r4, lr} +1000556c: f7ff bfe4 b.w 10005538 + +10005570 : +10005570: 0354 1000 T... + +10005574 : +10005574: 8b60 1004 `... + +10005578 : +10005578: 0310 1000 .... + +1000557c : +1000557c: 4148 5f4c 5047 4f49 495f 696e 0074 0000 HAL_GPIO_Init... + +1000558c : +1000558c: 5b0d 5047 4f49 4920 666e 255d 3a73 4920 .[GPIO Inf]%s: I +1000559c: 696e 6974 6c61 4720 4950 204f 6441 7061 nitial GPIO Adap +100055ac: 6574 0a72 0020 0000 0000 0000 ter. ....... + +100055b8 : +100055b8: e92d 4dff stmdb sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, sl, fp, lr} +100055bc: b086 sub sp, #24 +100055be: e9dd 0108 ldrd r0, r1, [sp, #32] +100055c2: e9cd 0104 strd r0, r1, [sp, #16] +100055c6: 9807 ldr r0, [sp, #28] +100055c8: f3c0 500a ubfx r0, r0, #20, #11 +100055cc: f240 71ff movw r1, #2047 ; 0x7ff +100055d0: 4288 cmp r0, r1 +100055d2: d108 bne.n 100055e6 +100055d4: 9807 ldr r0, [sp, #28] +100055d6: 2700 movs r7, #0 +100055d8: 0300 lsls r0, r0, #12 +100055da: bf05 ittet eq +100055dc: 9806 ldreq r0, [sp, #24] +100055de: 2800 cmpeq r0, #0 +100055e0: 2402 movne r4, #2 +100055e2: 2401 moveq r4, #1 +100055e4: e012 b.n 1000560c +100055e6: 2801 cmp r0, #1 +100055e8: da07 bge.n 100055fa +100055ea: a806 add r0, sp, #24 +100055ec: f000 fc0c bl 10005e08 <__iar_Dnorm> +100055f0: 2801 cmp r0, #1 +100055f2: db02 blt.n 100055fa +100055f4: 2700 movs r7, #0 +100055f6: 2400 movs r4, #0 +100055f8: e008 b.n 1000560c +100055fa: 9a07 ldr r2, [sp, #28] +100055fc: f240 31fe movw r1, #1022 ; 0x3fe +10005600: f361 521e bfi r2, r1, #20, #11 +10005604: 9207 str r2, [sp, #28] +10005606: 1a47 subs r7, r0, r1 +10005608: f04f 34ff mov.w r4, #4294967295 +1000560c: 2100 movs r1, #0 +1000560e: a804 add r0, sp, #16 +10005610: f000 fc1b bl 10005e4a <__iar_Dint> +10005614: 4605 mov r5, r0 +10005616: 9812 ldr r0, [sp, #72] ; 0x48 +10005618: b110 cbz r0, 10005620 +1000561a: 9912 ldr r1, [sp, #72] ; 0x48 +1000561c: 2000 movs r0, #0 +1000561e: 8008 strh r0, [r1, #0] +10005620: b935 cbnz r5, 10005630 +10005622: e9dd 2308 ldrd r2, r3, [sp, #32] +10005626: 2000 movs r0, #0 +10005628: 2100 movs r1, #0 +1000562a: f000 fc4d bl 10005ec8 <__aeabi_cdcmpeq> +1000562e: d011 beq.n 10005654 +10005630: 2c00 cmp r4, #0 +10005632: d511 bpl.n 10005658 +10005634: b23f sxth r7, r7 +10005636: 2f01 cmp r7, #1 +10005638: d113 bne.n 10005662 +1000563a: e9dd 2306 ldrd r2, r3, [sp, #24] +1000563e: 2000 movs r0, #0 +10005640: 49ca ldr r1, [pc, #808] ; (1000596c ) +10005642: f000 fc41 bl 10005ec8 <__aeabi_cdcmpeq> +10005646: d005 beq.n 10005654 +10005648: 2d01 cmp r5, #1 +1000564a: d10a bne.n 10005662 +1000564c: 49c8 ldr r1, [pc, #800] ; (10005970 ) +1000564e: f000 fc3b bl 10005ec8 <__aeabi_cdcmpeq> +10005652: d12e bne.n 100056b2 +10005654: 49c7 ldr r1, [pc, #796] ; (10005974 ) +10005656: e1bb b.n 100059d0 <.text_3> +10005658: 2c02 cmp r4, #2 +1000565a: d104 bne.n 10005666 +1000565c: e9dd 0106 ldrd r0, r1, [sp, #24] +10005660: e1b6 b.n 100059d0 <.text_3> +10005662: 2d01 cmp r5, #1 +10005664: db59 blt.n 1000571a +10005666: 2d02 cmp r5, #2 +10005668: bf08 it eq +1000566a: e9dd 0108 ldrdeq r0, r1, [sp, #32] +1000566e: f000 81af beq.w 100059d0 <.text_3> +10005672: 2c01 cmp r4, #1 +10005674: d11b bne.n 100056ae +10005676: 9807 ldr r0, [sp, #28] +10005678: 2800 cmp r0, #0 +1000567a: 9809 ldr r0, [sp, #36] ; 0x24 +1000567c: d402 bmi.n 10005684 +1000567e: 2800 cmp r0, #0 +10005680: d548 bpl.n 10005714 +10005682: e032 b.n 100056ea +10005684: 2800 cmp r0, #0 +10005686: d409 bmi.n 1000569c +10005688: 2d00 cmp r5, #0 +1000568a: d143 bne.n 10005714 +1000568c: f04f 31ff mov.w r1, #4294967295 +10005690: a804 add r0, sp, #16 +10005692: f000 fbda bl 10005e4a <__iar_Dint> +10005696: 2800 cmp r0, #0 +10005698: d53c bpl.n 10005714 +1000569a: e038 b.n 1000570e +1000569c: bb2d cbnz r5, 100056ea +1000569e: f04f 31ff mov.w r1, #4294967295 +100056a2: a804 add r0, sp, #16 +100056a4: f000 fbd1 bl 10005e4a <__iar_Dint> +100056a8: 2800 cmp r0, #0 +100056aa: d51e bpl.n 100056ea +100056ac: e019 b.n 100056e2 +100056ae: 2d01 cmp r5, #1 +100056b0: d109 bne.n 100056c6 +100056b2: 9809 ldr r0, [sp, #36] ; 0x24 +100056b4: b239 sxth r1, r7 +100056b6: 2800 cmp r0, #0 +100056b8: d402 bmi.n 100056c0 +100056ba: 2901 cmp r1, #1 +100056bc: da2a bge.n 10005714 +100056be: e014 b.n 100056ea +100056c0: 2901 cmp r1, #1 +100056c2: da12 bge.n 100056ea +100056c4: e026 b.n 10005714 +100056c6: 9809 ldr r0, [sp, #36] ; 0x24 +100056c8: 2800 cmp r0, #0 +100056ca: d411 bmi.n 100056f0 +100056cc: b96d cbnz r5, 100056ea +100056ce: f04f 31ff mov.w r1, #4294967295 +100056d2: a804 add r0, sp, #16 +100056d4: f000 fbb9 bl 10005e4a <__iar_Dint> +100056d8: 2800 cmp r0, #0 +100056da: bf44 itt mi +100056dc: 9807 ldrmi r0, [sp, #28] +100056de: 2800 cmpmi r0, #0 +100056e0: d503 bpl.n 100056ea +100056e2: 2000 movs r0, #0 +100056e4: f04f 4100 mov.w r1, #2147483648 ; 0x80000000 +100056e8: e172 b.n 100059d0 <.text_3> +100056ea: 2000 movs r0, #0 +100056ec: 2100 movs r1, #0 +100056ee: e16f b.n 100059d0 <.text_3> +100056f0: f000 fbfa bl 10005ee8 <__aeabi_errno_addr> +100056f4: 2122 movs r1, #34 ; 0x22 +100056f6: 6001 str r1, [r0, #0] +100056f8: b965 cbnz r5, 10005714 +100056fa: f04f 31ff mov.w r1, #4294967295 +100056fe: a804 add r0, sp, #16 +10005700: f000 fba3 bl 10005e4a <__iar_Dint> +10005704: 2800 cmp r0, #0 +10005706: bf44 itt mi +10005708: 9807 ldrmi r0, [sp, #28] +1000570a: 2800 cmpmi r0, #0 +1000570c: d502 bpl.n 10005714 +1000570e: 2000 movs r0, #0 +10005710: 4999 ldr r1, [pc, #612] ; (10005978 ) +10005712: e15d b.n 100059d0 <.text_3> +10005714: 2000 movs r0, #0 +10005716: 4999 ldr r1, [pc, #612] ; (1000597c ) +10005718: e15a b.n 100059d0 <.text_3> +1000571a: 9807 ldr r0, [sp, #28] +1000571c: 2800 cmp r0, #0 +1000571e: bf48 it mi +10005720: 2d00 cmpmi r5, #0 +10005722: d508 bpl.n 10005736 +10005724: f000 fbe0 bl 10005ee8 <__aeabi_errno_addr> +10005728: 2121 movs r1, #33 ; 0x21 +1000572a: 6001 str r1, [r0, #0] +1000572c: f04f 30ff mov.w r0, #4294967295 +10005730: f06f 4100 mvn.w r1, #2147483648 ; 0x80000000 +10005734: e14c b.n 100059d0 <.text_3> +10005736: e9dd 0106 ldrd r0, r1, [sp, #24] +1000573a: 2200 movs r2, #0 +1000573c: 2300 movs r3, #0 +1000573e: f000 fbd9 bl 10005ef4 <__aeabi_cdrcmple> +10005742: bf38 it cc +10005744: f8ad 2004 strhcc.w r2, [sp, #4] +10005748: d30a bcc.n 10005760 +1000574a: f081 4100 eor.w r1, r1, #2147483648 ; 0x80000000 +1000574e: e9cd 0106 strd r0, r1, [sp, #24] +10005752: f04f 31ff mov.w r1, #4294967295 +10005756: a804 add r0, sp, #16 +10005758: f000 fb77 bl 10005e4a <__iar_Dint> +1000575c: f8ad 0004 strh.w r0, [sp, #4] +10005760: 2f01 cmp r7, #1 +10005762: d113 bne.n 1000578c +10005764: e9dd 0106 ldrd r0, r1, [sp, #24] +10005768: 4a85 ldr r2, [pc, #532] ; (10005980 ) +1000576a: 4b86 ldr r3, [pc, #536] ; (10005984 ) +1000576c: f000 fbdc bl 10005f28 <__aeabi_cdcmple> +10005770: d20c bcs.n 1000578c +10005772: e9dd 2306 ldrd r2, r3, [sp, #24] +10005776: 2400 movs r4, #0 +10005778: 2600 movs r6, #0 +1000577a: 4d7e ldr r5, [pc, #504] ; (10005974 ) +1000577c: 4620 mov r0, r4 +1000577e: f04f 4180 mov.w r1, #1073741824 ; 0x40000000 +10005782: f000 fbf7 bl 10005f74 <__aeabi_dmul> +10005786: e9cd 0106 strd r0, r1, [sp, #24] +1000578a: e01b b.n 100057c4 +1000578c: e9dd 2306 ldrd r2, r3, [sp, #24] +10005790: 4d76 ldr r5, [pc, #472] ; (1000596c ) +10005792: 497d ldr r1, [pc, #500] ; (10005988 ) +10005794: 2000 movs r0, #0 +10005796: f000 fbed bl 10005f74 <__aeabi_dmul> +1000579a: 2200 movs r2, #0 +1000579c: 462b mov r3, r5 +1000579e: f000 fccb bl 10006138 <__aeabi_dadd> +100057a2: f000 fd3d bl 10006220 <__aeabi_d2iz> +100057a6: f1a0 0620 sub.w r6, r0, #32 +100057aa: 4630 mov r0, r6 +100057ac: f000 fd5e bl 1000626c <__aeabi_i2d> +100057b0: 2200 movs r2, #0 +100057b2: 4b76 ldr r3, [pc, #472] ; (1000598c ) +100057b4: f000 fbde bl 10005f74 <__aeabi_dmul> +100057b8: 2200 movs r2, #0 +100057ba: 462b mov r3, r5 +100057bc: f000 fcbc bl 10006138 <__aeabi_dadd> +100057c0: 4604 mov r4, r0 +100057c2: 460d mov r5, r1 +100057c4: f20f 2020 addw r0, pc, #544 ; 0x220 +100057c8: eb00 1046 add.w r0, r0, r6, lsl #5 +100057cc: 9000 str r0, [sp, #0] +100057ce: 4622 mov r2, r4 +100057d0: e9dd 0106 ldrd r0, r1, [sp, #24] +100057d4: 462b mov r3, r5 +100057d6: f000 fd5f bl 10006298 <__aeabi_dsub> +100057da: 4682 mov sl, r0 +100057dc: 468b mov fp, r1 +100057de: e9dd 0106 ldrd r0, r1, [sp, #24] +100057e2: 4622 mov r2, r4 +100057e4: 462b mov r3, r5 +100057e6: f000 fca7 bl 10006138 <__aeabi_dadd> +100057ea: 4602 mov r2, r0 +100057ec: 460b mov r3, r1 +100057ee: 4650 mov r0, sl +100057f0: 4659 mov r1, fp +100057f2: f000 fe11 bl 10006418 <__aeabi_ddiv> +100057f6: e9cd 0104 strd r0, r1, [sp, #16] +100057fa: e9dd 2304 ldrd r2, r3, [sp, #16] +100057fe: f000 fbb9 bl 10005f74 <__aeabi_dmul> +10005802: e9cd ab06 strd sl, fp, [sp, #24] +10005806: 4606 mov r6, r0 +10005808: 4688 mov r8, r1 +1000580a: f000 ff29 bl 10006660 <__iar_Logpoly> +1000580e: 4632 mov r2, r6 +10005810: 4643 mov r3, r8 +10005812: f000 fbaf bl 10005f74 <__aeabi_dmul> +10005816: e9dd 2306 ldrd r2, r3, [sp, #24] +1000581a: f000 fd3d bl 10006298 <__aeabi_dsub> +1000581e: 4606 mov r6, r0 +10005820: 4688 mov r8, r1 +10005822: 2000 movs r0, #0 +10005824: 4953 ldr r1, [pc, #332] ; (10005974 ) +10005826: 4622 mov r2, r4 +10005828: 462b mov r3, r5 +1000582a: f000 fd35 bl 10006298 <__aeabi_dsub> +1000582e: 2200 movs r2, #0 +10005830: f04f 4380 mov.w r3, #1073741824 ; 0x40000000 +10005834: f000 fb9e bl 10005f74 <__aeabi_dmul> +10005838: 4632 mov r2, r6 +1000583a: 4643 mov r3, r8 +1000583c: f000 fc7c bl 10006138 <__aeabi_dadd> +10005840: e9dd 2304 ldrd r2, r3, [sp, #16] +10005844: f000 fb96 bl 10005f74 <__aeabi_dmul> +10005848: 4602 mov r2, r0 +1000584a: 460b mov r3, r1 +1000584c: e9dd 0106 ldrd r0, r1, [sp, #24] +10005850: f000 fc72 bl 10006138 <__aeabi_dadd> +10005854: 4604 mov r4, r0 +10005856: 460d mov r5, r1 +10005858: 4a4d ldr r2, [pc, #308] ; (10005990 ) +1000585a: 4b4e ldr r3, [pc, #312] ; (10005994 ) +1000585c: f000 fddc bl 10006418 <__aeabi_ddiv> +10005860: e9cd 0104 strd r0, r1, [sp, #16] +10005864: 4638 mov r0, r7 +10005866: f000 fd01 bl 1000626c <__aeabi_i2d> +1000586a: 9a00 ldr r2, [sp, #0] +1000586c: 4607 mov r7, r0 +1000586e: 468b mov fp, r1 +10005870: e9d2 0100 ldrd r0, r1, [r2] +10005874: 463a mov r2, r7 +10005876: 465b mov r3, fp +10005878: f000 fc5e bl 10006138 <__aeabi_dadd> +1000587c: e9dd 2304 ldrd r2, r3, [sp, #16] +10005880: f000 fc5a bl 10006138 <__aeabi_dadd> +10005884: e9cd 0104 strd r0, r1, [sp, #16] +10005888: e9dd 2308 ldrd r2, r3, [sp, #32] +1000588c: f000 fb72 bl 10005f74 <__aeabi_dmul> +10005890: e9cd 0102 strd r0, r1, [sp, #8] +10005894: 2200 movs r2, #0 +10005896: 4b40 ldr r3, [pc, #256] ; (10005998 ) +10005898: f000 fb46 bl 10005f28 <__aeabi_cdcmple> +1000589c: f0c0 8080 bcc.w 100059a0 +100058a0: 2201 movs r2, #1 +100058a2: 4b3e ldr r3, [pc, #248] ; (1000599c ) +100058a4: f000 fb26 bl 10005ef4 <__aeabi_cdrcmple> +100058a8: f240 807e bls.w 100059a8 +100058ac: 2200 movs r2, #0 +100058ae: 2300 movs r3, #0 +100058b0: f000 fb3a bl 10005f28 <__aeabi_cdcmple> +100058b4: e9dd 2302 ldrd r2, r3, [sp, #8] +100058b8: bf39 ittee cc +100058ba: 2000 movcc r0, #0 +100058bc: 492c ldrcc r1, [pc, #176] ; (10005970 ) +100058be: 2000 movcs r0, #0 +100058c0: 492a ldrcs r1, [pc, #168] ; (1000596c ) +100058c2: f000 fc39 bl 10006138 <__aeabi_dadd> +100058c6: f000 fcab bl 10006220 <__aeabi_d2iz> +100058ca: 4606 mov r6, r0 +100058cc: e9dd 0108 ldrd r0, r1, [sp, #32] +100058d0: 4622 mov r2, r4 +100058d2: 462b mov r3, r5 +100058d4: f000 fb4e bl 10005f74 <__aeabi_dmul> +100058d8: e9cd 0102 strd r0, r1, [sp, #8] +100058dc: 9a00 ldr r2, [sp, #0] +100058de: 4c2c ldr r4, [pc, #176] ; (10005990 ) +100058e0: 4d2c ldr r5, [pc, #176] ; (10005994 ) +100058e2: e9d2 0102 ldrd r0, r1, [r2, #8] +100058e6: 4690 mov r8, r2 +100058e8: e9d8 2304 ldrd r2, r3, [r8, #16] +100058ec: f000 fc24 bl 10006138 <__aeabi_dadd> +100058f0: e9dd 2308 ldrd r2, r3, [sp, #32] +100058f4: f000 fb3e bl 10005f74 <__aeabi_dmul> +100058f8: 4622 mov r2, r4 +100058fa: 462b mov r3, r5 +100058fc: f000 fb3a bl 10005f74 <__aeabi_dmul> +10005900: e9dd 2302 ldrd r2, r3, [sp, #8] +10005904: f000 fc18 bl 10006138 <__aeabi_dadd> +10005908: e9cd 0102 strd r0, r1, [sp, #8] +1000590c: f8dd 8000 ldr.w r8, [sp] +10005910: 463a mov r2, r7 +10005912: e9d8 0100 ldrd r0, r1, [r8] +10005916: 465b mov r3, fp +10005918: f000 fc0e bl 10006138 <__aeabi_dadd> +1000591c: e9dd 2308 ldrd r2, r3, [sp, #32] +10005920: f000 fb28 bl 10005f74 <__aeabi_dmul> +10005924: 4607 mov r7, r0 +10005926: 468b mov fp, r1 +10005928: 4630 mov r0, r6 +1000592a: f000 fc9f bl 1000626c <__aeabi_i2d> +1000592e: 4602 mov r2, r0 +10005930: 460b mov r3, r1 +10005932: 4638 mov r0, r7 +10005934: 4659 mov r1, fp +10005936: f000 fcaf bl 10006298 <__aeabi_dsub> +1000593a: 4622 mov r2, r4 +1000593c: 462b mov r3, r5 +1000593e: f000 fb19 bl 10005f74 <__aeabi_dmul> +10005942: e9dd 2302 ldrd r2, r3, [sp, #8] +10005946: f000 fbf7 bl 10006138 <__aeabi_dadd> +1000594a: e9cd 0102 strd r0, r1, [sp, #8] +1000594e: 9812 ldr r0, [sp, #72] ; 0x48 +10005950: b108 cbz r0, 10005956 +10005952: 8006 strh r6, [r0, #0] +10005954: 2600 movs r6, #0 +10005956: 9600 str r6, [sp, #0] +10005958: 2200 movs r2, #0 +1000595a: 4b06 ldr r3, [pc, #24] ; (10005974 ) +1000595c: a802 add r0, sp, #8 +1000595e: f000 fed5 bl 1000670c <__iar_Exp> +10005962: b1e8 cbz r0, 100059a0 +10005964: 2801 cmp r0, #1 +10005966: d01f beq.n 100059a8 +10005968: e02a b.n 100059c0 +1000596a: bf00 nop +1000596c: 3fe00000 .word 0x3fe00000 +10005970: bfe00000 .word 0xbfe00000 +10005974: 3ff00000 .word 0x3ff00000 +10005978: fff00000 .word 0xfff00000 +1000597c: 7ff00000 .word 0x7ff00000 +10005980: 667f3bcd .word 0x667f3bcd +10005984: 3fe6a09e .word 0x3fe6a09e +10005988: 40500000 .word 0x40500000 +1000598c: 3f900000 .word 0x3f900000 +10005990: fefa39ef .word 0xfefa39ef +10005994: 3fe62e42 .word 0x3fe62e42 +10005998: c0e00000 .word 0xc0e00000 +1000599c: 40e00000 .word 0x40e00000 +100059a0: 2000 movs r0, #0 +100059a2: e9cd 0002 strd r0, r0, [sp, #8] +100059a6: e007 b.n 100059b8 +100059a8: 2000 movs r0, #0 +100059aa: 4901 ldr r1, [pc, #4] ; (100059b0 ) +100059ac: e002 b.n 100059b4 +100059ae: bf00 nop +100059b0: 7ff00000 .word 0x7ff00000 +100059b4: e9cd 0102 strd r0, r1, [sp, #8] +100059b8: f000 fa96 bl 10005ee8 <__aeabi_errno_addr> +100059bc: 2122 movs r1, #34 ; 0x22 +100059be: 6001 str r1, [r0, #0] +100059c0: f9bd 0004 ldrsh.w r0, [sp, #4] +100059c4: 2800 cmp r0, #0 +100059c6: e9dd 0102 ldrd r0, r1, [sp, #8] +100059ca: bf18 it ne +100059cc: f081 4100 eorne.w r1, r1, #2147483648 ; 0x80000000 + +100059d0 <.text_3>: +100059d0: b00a add sp, #40 ; 0x28 +100059d2: e8bd 8df0 ldmia.w sp!, {r4, r5, r6, r7, r8, sl, fp, pc} + +100059d6 : +100059d6: b510 push {r4, lr} +100059d8: b082 sub sp, #8 +100059da: 2400 movs r4, #0 +100059dc: 9400 str r4, [sp, #0] +100059de: f7ff fdeb bl 100055b8 +100059e2: bd1c pop {r2, r3, r4, pc} +100059e4: 0000 movs r0, r0 + ... + +100059e8 : +100059e8: 0000 0000 0000 bff0 0000 0000 0000 8000 ................ +100059f8: 0000 0000 0000 8000 0000 0000 0000 0000 ................ +10005a08: 0000 c000 9452 bfee 0000 4800 4e20 be51 ....R......H NQ. +10005a18: 0000 f800 6764 bcbc 0000 0000 0000 0000 ....dg.......... +10005a28: 0000 2000 3381 bfed 0000 8000 dbb3 be14 ... .3.......... +10005a38: 0000 5000 0667 bca3 0000 0000 0000 0000 ...Pg........... +10005a48: 0000 d000 dce9 bfeb 0000 0800 92c3 be59 ..............Y. +10005a58: 0000 8000 d3b0 bcb8 0000 0000 0000 0000 ................ +10005a68: 0000 7000 8ff9 bfea 0000 c000 10a5 be28 ...p..........(. +10005a78: 0000 e800 c0bf bcb0 0000 0000 0000 0000 ................ +10005a88: 0000 7000 4c28 bfe9 0000 6000 4b13 be42 ...p(L.....`.KB. +10005a98: 0000 c000 203d bcb8 0000 0000 0000 0000 ....= .......... +10005aa8: 0000 5000 10fa bfe8 0000 c000 f65f be2b ...P........_.+. +10005ab8: 0000 9000 715c bca7 0000 0000 0000 0000 ....\q.......... +10005ac8: 0000 2000 ddfc bfe6 0000 c000 f1f8 be54 ... ..........T. +10005ad8: 0000 1800 f6e9 bcb9 0000 0000 0000 0000 ................ +10005ae8: 0000 d000 b2c3 bfe5 0000 7000 32e4 be54 ...........p.2T. +10005af8: 0000 5000 06db bcb4 0000 0000 0000 0000 ...P............ +10005b08: 0000 1000 8eef bfe4 0000 2000 62f3 be52 ........... .bR. +10005b18: 0000 c000 872a bc9a 0000 0000 0000 0000 ....*........... +10005b28: 0000 b000 7222 bfe3 0000 f000 e0e8 be56 ...."r........V. +10005b38: 0000 2800 2d35 bcbd 0000 0000 0000 0000 ...(5-.......... +10005b48: 0000 0000 5c0a bfe2 0000 b000 8efa be41 .....\........A. +10005b58: 0000 4000 6fae bcbd 0000 0000 0000 0000 ...@.o.......... +10005b68: 0000 0000 4c56 bfe1 0000 f000 cd15 be5f ....VL........_. +10005b78: 0000 0000 1c14 bc90 0000 0000 0000 0000 ................ +10005b88: 0000 4000 42bd bfe0 0000 3000 34f9 be57 ...@.B.....0.4W. +10005b98: 0000 e000 1e6c bc93 0000 0000 0000 0000 ....l........... +10005ba8: 0000 e000 7df5 bfde 0000 b000 538a be5e .....}.......S^. +10005bb8: 0000 8000 77da bcaa 0000 0000 0000 0000 .....w.......... +10005bc8: 0000 c000 819d bfdc 0000 0000 a2ff be26 ..............&. +10005bd8: 0000 6000 e257 bcb0 0000 0000 0000 0000 ...`W........... +10005be8: 0000 6000 8ff9 bfda 0000 5800 810a be51 ...`.......X..Q. +10005bf8: 0000 f000 605f bcb8 0000 0000 0000 0000 ...._`.......... +10005c08: 0000 0000 a898 bfd8 0000 6000 7f7a be45 ...........`z.E. +10005c18: 0000 d000 3354 bca3 0000 0000 0000 0000 ....T3.......... +10005c28: 0000 6000 cb0f bfd6 0000 d000 cb91 be40 ...`..........@. +10005c38: 0000 4000 1b6d bca0 0000 0000 0000 0000 ...@m........... +10005c48: 0000 a000 f6fb bfd4 0000 9800 cec5 be52 ..............R. +10005c58: 0000 0000 393a bc7e 0000 0000 0000 0000 ....:9~......... +10005c68: 0000 e000 2bfe bfd3 0000 4000 8773 be2b .....+.....@s.+. +10005c78: 0000 0000 6892 bc79 0000 0000 0000 0000 .....hy......... +10005c88: 0000 4000 69c0 bfd1 0000 5800 63f1 be53 ...@.i.....X.cS. +10005c98: 0000 8000 8d43 bc7c 0000 0000 0000 0000 ....C.|......... +10005ca8: 0000 8000 5fd8 bfcf 0000 1800 831f be54 ....._........T. +10005cb8: 0000 b000 423f bca2 0000 0000 0000 0000 ....?B.......... +10005cc8: 0000 8000 fc67 bfcb 0000 6000 fffa be53 ....g......`..S. +10005cd8: 0000 5000 0de0 bcb8 0000 0000 0000 0000 ...P............ +10005ce8: 0000 0000 a898 bfc8 0000 6000 7f7a be35 ...........`z.5. +10005cf8: 0000 c000 3354 bc93 0000 0000 0000 0000 ....T3.......... +10005d08: 0000 0000 63dc bfc5 0000 5800 ffd6 be54 .....c.....X..T. +10005d18: 0000 0000 6439 bc90 0000 0000 0000 0000 ....9d.......... +10005d28: 0000 c000 2dad bfc2 0000 8000 59a4 be15 .....-.......Y.. +10005d38: 0000 e000 4b48 bcab 0000 0000 0000 0000 ....HK.......... +10005d48: 0000 8000 0b1a bfbe 0000 5000 3cbf be5a ...........P.: +10005e08: b430 push {r4, r5} +10005e0a: 6843 ldr r3, [r0, #4] +10005e0c: f003 4200 and.w r2, r3, #2147483648 ; 0x80000000 +10005e10: 2101 movs r1, #1 +10005e12: 031b lsls r3, r3, #12 +10005e14: 0b1b lsrs r3, r3, #12 +10005e16: 6043 str r3, [r0, #4] +10005e18: bf04 itt eq +10005e1a: 6803 ldreq r3, [r0, #0] +10005e1c: 2b00 cmpeq r3, #0 +10005e1e: d108 bne.n 10005e32 <__iar_Dnorm+0x2a> +10005e20: e00d b.n 10005e3e <__iar_Dnorm+0x36> +10005e22: 6803 ldr r3, [r0, #0] +10005e24: 0fdd lsrs r5, r3, #31 +10005e26: ea45 0444 orr.w r4, r5, r4, lsl #1 +10005e2a: 6044 str r4, [r0, #4] +10005e2c: 005b lsls r3, r3, #1 +10005e2e: 6003 str r3, [r0, #0] +10005e30: 1e49 subs r1, r1, #1 +10005e32: 6844 ldr r4, [r0, #4] +10005e34: 02e3 lsls r3, r4, #11 +10005e36: d5f4 bpl.n 10005e22 <__iar_Dnorm+0x1a> +10005e38: 0323 lsls r3, r4, #12 +10005e3a: 0b1b lsrs r3, r3, #12 +10005e3c: 6043 str r3, [r0, #4] +10005e3e: 6843 ldr r3, [r0, #4] +10005e40: 431a orrs r2, r3 +10005e42: 6042 str r2, [r0, #4] +10005e44: 4608 mov r0, r1 +10005e46: bc30 pop {r4, r5} +10005e48: 4770 bx lr + +10005e4a <__iar_Dint>: +10005e4a: 6842 ldr r2, [r0, #4] +10005e4c: f3c2 520a ubfx r2, r2, #20, #11 +10005e50: f240 73ff movw r3, #2047 ; 0x7ff +10005e54: 429a cmp r2, r3 +10005e56: d109 bne.n 10005e6c <__iar_Dint+0x22> +10005e58: 6841 ldr r1, [r0, #4] +10005e5a: 0309 lsls r1, r1, #12 +10005e5c: bf04 itt eq +10005e5e: 6800 ldreq r0, [r0, #0] +10005e60: 2800 cmpeq r0, #0 +10005e62: d101 bne.n 10005e68 <__iar_Dint+0x1e> +10005e64: 2001 movs r0, #1 +10005e66: 4770 bx lr +10005e68: 2002 movs r0, #2 +10005e6a: 4770 bx lr +10005e6c: 6843 ldr r3, [r0, #4] +10005e6e: 005b lsls r3, r3, #1 +10005e70: bf04 itt eq +10005e72: 6803 ldreq r3, [r0, #0] +10005e74: 2b00 cmpeq r3, #0 +10005e76: d025 beq.n 10005ec4 <__iar_Dint+0x7a> +10005e78: f240 4333 movw r3, #1075 ; 0x433 +10005e7c: 1a9a subs r2, r3, r2 +10005e7e: 1a52 subs r2, r2, r1 +10005e80: 2a01 cmp r2, #1 +10005e82: db1f blt.n 10005ec4 <__iar_Dint+0x7a> +10005e84: 2a35 cmp r2, #53 ; 0x35 +10005e86: db06 blt.n 10005e96 <__iar_Dint+0x4c> +10005e88: 6841 ldr r1, [r0, #4] +10005e8a: f001 4100 and.w r1, r1, #2147483648 ; 0x80000000 +10005e8e: 6041 str r1, [r0, #4] +10005e90: 2100 movs r1, #0 +10005e92: 6001 str r1, [r0, #0] +10005e94: e013 b.n 10005ebe <__iar_Dint+0x74> +10005e96: 2101 movs r1, #1 +10005e98: f002 031f and.w r3, r2, #31 +10005e9c: 4099 lsls r1, r3 +10005e9e: 1e49 subs r1, r1, #1 +10005ea0: 0692 lsls r2, r2, #26 +10005ea2: d507 bpl.n 10005eb4 <__iar_Dint+0x6a> +10005ea4: 6842 ldr r2, [r0, #4] +10005ea6: 4011 ands r1, r2 +10005ea8: 404a eors r2, r1 +10005eaa: 6042 str r2, [r0, #4] +10005eac: 6802 ldr r2, [r0, #0] +10005eae: 4311 orrs r1, r2 +10005eb0: 2200 movs r2, #0 +10005eb2: e002 b.n 10005eba <__iar_Dint+0x70> +10005eb4: 6802 ldr r2, [r0, #0] +10005eb6: 4011 ands r1, r2 +10005eb8: 404a eors r2, r1 +10005eba: 6002 str r2, [r0, #0] +10005ebc: b111 cbz r1, 10005ec4 <__iar_Dint+0x7a> +10005ebe: f04f 30ff mov.w r0, #4294967295 +10005ec2: 4770 bx lr +10005ec4: 2000 movs r0, #0 +10005ec6: 4770 bx lr + +10005ec8 <__aeabi_cdcmpeq>: +10005ec8: 4290 cmp r0, r2 +10005eca: d10c bne.n 10005ee6 <__aeabi_cdcmpeq+0x1e> +10005ecc: ea41 0c03 orr.w ip, r1, r3 +10005ed0: ea50 0c4c orrs.w ip, r0, ip, lsl #1 +10005ed4: d007 beq.n 10005ee6 <__aeabi_cdcmpeq+0x1e> +10005ed6: 4299 cmp r1, r3 +10005ed8: d105 bne.n 10005ee6 <__aeabi_cdcmpeq+0x1e> +10005eda: f44f 1c00 mov.w ip, #2097152 ; 0x200000 +10005ede: eb1c 0f41 cmn.w ip, r1, lsl #1 +10005ee2: bf38 it cc +10005ee4: 4289 cmpcc r1, r1 +10005ee6: 4770 bx lr + +10005ee8 <__aeabi_errno_addr>: +10005ee8: 4801 ldr r0, [pc, #4] ; (10005ef0 <.text_4>) +10005eea: f000 bd6d b.w 100069c8 <__iar_dlib_perthread_access> + ... + +10005ef0 <.text_4>: +10005ef0: 10043ccc .word 0x10043ccc + +10005ef4 <__aeabi_cdrcmple>: +10005ef4: f44f 1c00 mov.w ip, #2097152 ; 0x200000 +10005ef8: eb1c 0f41 cmn.w ip, r1, lsl #1 +10005efc: bf94 ite ls +10005efe: eb1c 0f43 cmnls.w ip, r3, lsl #1 +10005f02: e009 bhi.n 10005f18 <__aeabi_cdrcmple+0x24> +10005f04: ea41 0c03 orr.w ip, r1, r3 +10005f08: ea50 0c4c orrs.w ip, r0, ip, lsl #1 +10005f0c: ea52 0c0c orrs.w ip, r2, ip +10005f10: d203 bcs.n 10005f1a <__aeabi_cdrcmple+0x26> +10005f12: 428b cmp r3, r1 +10005f14: bf08 it eq +10005f16: 4282 cmpeq r2, r0 +10005f18: 4770 bx lr +10005f1a: bf14 ite ne +10005f1c: 4299 cmpne r1, r3 +10005f1e: 4290 cmpeq r0, r2 +10005f20: 4770 bx lr + +10005f22 : +10005f22: 2001 movs r0, #1 +10005f24: 4770 bx lr + +10005f26 : +10005f26: 4770 bx lr + +10005f28 <__aeabi_cdcmple>: +10005f28: f44f 1c00 mov.w ip, #2097152 ; 0x200000 +10005f2c: eb1c 0f41 cmn.w ip, r1, lsl #1 +10005f30: bf94 ite ls +10005f32: eb1c 0f43 cmnls.w ip, r3, lsl #1 +10005f36: e009 bhi.n 10005f4c <__aeabi_cdcmple+0x24> +10005f38: ea41 0c03 orr.w ip, r1, r3 +10005f3c: ea50 0c4c orrs.w ip, r0, ip, lsl #1 +10005f40: ea52 0c0c orrs.w ip, r2, ip +10005f44: d203 bcs.n 10005f4e <__aeabi_cdcmple+0x26> +10005f46: 4299 cmp r1, r3 +10005f48: bf08 it eq +10005f4a: 4290 cmpeq r0, r2 +10005f4c: 4770 bx lr +10005f4e: bf14 ite ne +10005f50: 428b cmpne r3, r1 +10005f52: 4282 cmpeq r2, r0 +10005f54: 4770 bx lr + +10005f56 <_SScin>: +10005f56: 6803 ldr r3, [r0, #0] +10005f58: b91a cbnz r2, 10005f62 <_SScin+0xc> +10005f5a: 1e5a subs r2, r3, #1 +10005f5c: 6002 str r2, [r0, #0] +10005f5e: 4608 mov r0, r1 +10005f60: 4770 bx lr +10005f62: 7819 ldrb r1, [r3, #0] +10005f64: b911 cbnz r1, 10005f6c <_SScin+0x16> +10005f66: f04f 30ff mov.w r0, #4294967295 +10005f6a: 4770 bx lr +10005f6c: 1c59 adds r1, r3, #1 +10005f6e: 6001 str r1, [r0, #0] +10005f70: 7818 ldrb r0, [r3, #0] +10005f72: 4770 bx lr + +10005f74 <__aeabi_dmul>: +10005f74: b5b0 push {r4, r5, r7, lr} +10005f76: ea81 0c03 eor.w ip, r1, r3 +10005f7a: f00c 4c00 and.w ip, ip, #2147483648 ; 0x80000000 +10005f7e: f240 75ff movw r5, #2047 ; 0x7ff +10005f82: ea15 5411 ands.w r4, r5, r1, lsr #20 +10005f86: bf1d ittte ne +10005f88: ea15 5713 andsne.w r7, r5, r3, lsr #20 +10005f8c: 42ac cmpne r4, r5 +10005f8e: 42af cmpne r7, r5 +10005f90: e039 beq.n 10006006 <__aeabi_dmul+0x92> +10005f92: 19e4 adds r4, r4, r7 +10005f94: ea23 5345 bic.w r3, r3, r5, lsl #21 +10005f98: f443 1380 orr.w r3, r3, #1048576 ; 0x100000 +10005f9c: 02c9 lsls r1, r1, #11 +10005f9e: f041 4100 orr.w r1, r1, #2147483648 ; 0x80000000 +10005fa2: ea41 5e50 orr.w lr, r1, r0, lsr #21 +10005fa6: 02c7 lsls r7, r0, #11 +10005fa8: 0011 movs r1, r2 +10005faa: fba7 0202 umull r0, r2, r7, r2 +10005fae: 2800 cmp r0, #0 +10005fb0: f04f 0000 mov.w r0, #0 +10005fb4: fbee 2001 umlal r2, r0, lr, r1 +10005fb8: f04f 0100 mov.w r1, #0 +10005fbc: fbe3 2107 umlal r2, r1, r3, r7 +10005fc0: bf18 it ne +10005fc2: f042 0201 orrne.w r2, r2, #1 +10005fc6: 1840 adds r0, r0, r1 +10005fc8: 2100 movs r1, #0 +10005fca: 4149 adcs r1, r1 +10005fcc: fbe3 010e umlal r0, r1, r3, lr +10005fd0: f5a4 6480 sub.w r4, r4, #1024 ; 0x400 +10005fd4: 030f lsls r7, r1, #12 +10005fd6: d202 bcs.n 10005fde <__aeabi_dmul+0x6a> +10005fd8: 0052 lsls r2, r2, #1 +10005fda: 4140 adcs r0, r0 +10005fdc: 4149 adcs r1, r1 +10005fde: f154 0401 adcs.w r4, r4, #1 +10005fe2: dd6c ble.n 100060be <__aeabi_dmul+0x14a> +10005fe4: 0847 lsrs r7, r0, #1 +10005fe6: f172 4200 sbcs.w r2, r2, #2147483648 ; 0x80000000 +10005fea: f150 0000 adcs.w r0, r0, #0 +10005fee: eb51 5104 adcs.w r1, r1, r4, lsl #20 +10005ff2: f5a1 1180 sub.w r1, r1, #1048576 ; 0x100000 +10005ff6: bf5c itt pl +10005ff8: ea41 010c orrpl.w r1, r1, ip +10005ffc: bdb0 poppl {r4, r5, r7, pc} +10005ffe: ea4c 5105 orr.w r1, ip, r5, lsl #20 +10006002: 2000 movs r0, #0 +10006004: bdb0 pop {r4, r5, r7, pc} +10006006: ea05 5713 and.w r7, r5, r3, lsr #20 +1000600a: 42ac cmp r4, r5 +1000600c: bf14 ite ne +1000600e: 42af cmpne r7, r5 +10006010: e041 beq.n 10006096 <__aeabi_dmul+0x122> +10006012: ea50 0e41 orrs.w lr, r0, r1, lsl #1 +10006016: bf1c itt ne +10006018: ea52 0e43 orrsne.w lr, r2, r3, lsl #1 +1000601c: e002 bne.n 10006024 <__aeabi_dmul+0xb0> +1000601e: 4661 mov r1, ip +10006020: 2000 movs r0, #0 +10006022: bdb0 pop {r4, r5, r7, pc} +10006024: 4224 tst r4, r4 +10006026: 443c add r4, r7 +10006028: d11b bne.n 10006062 <__aeabi_dmul+0xee> +1000602a: ea5f 0e07 movs.w lr, r7 +1000602e: d0f6 beq.n 1000601e <__aeabi_dmul+0xaa> +10006030: 0309 lsls r1, r1, #12 +10006032: bf02 ittt eq +10006034: 4601 moveq r1, r0 +10006036: 2000 moveq r0, #0 +10006038: f1ae 0e14 subeq.w lr, lr, #20 +1000603c: fab1 f781 clz r7, r1 +10006040: ebae 0407 sub.w r4, lr, r7 +10006044: fa01 fe07 lsl.w lr, r1, r7 +10006048: 370c adds r7, #12 +1000604a: f1c7 0120 rsb r1, r7, #32 +1000604e: fa00 f707 lsl.w r7, r0, r7 +10006052: 40c8 lsrs r0, r1 +10006054: ea4e 0e00 orr.w lr, lr, r0 +10006058: ea23 5345 bic.w r3, r3, r5, lsl #21 +1000605c: f443 1380 orr.w r3, r3, #1048576 ; 0x100000 +10006060: e7a2 b.n 10005fa8 <__aeabi_dmul+0x34> +10006062: f033 4300 bics.w r3, r3, #2147483648 ; 0x80000000 +10006066: fab3 f783 clz r7, r3 +1000606a: bf04 itt eq +1000606c: fab2 fe82 clzeq lr, r2 +10006070: 4477 addeq r7, lr +10006072: 3f0b subs r7, #11 +10006074: 1be4 subs r4, r4, r7 +10006076: f1b7 0e20 subs.w lr, r7, #32 +1000607a: bf2f iteee cs +1000607c: fa02 f30e lslcs.w r3, r2, lr +10006080: 40bb lslcc r3, r7 +10006082: f1c7 0e20 rsbcc lr, r7, #32 +10006086: fa22 fe0e lsrcc.w lr, r2, lr +1000608a: bf38 it cc +1000608c: ea43 030e orrcc.w r3, r3, lr +10006090: 40ba lsls r2, r7 +10006092: 1c64 adds r4, r4, #1 +10006094: e782 b.n 10005f9c <__aeabi_dmul+0x28> +10006096: ea50 0e41 orrs.w lr, r0, r1, lsl #1 +1000609a: bf14 ite ne +1000609c: ea52 0e43 orrsne.w lr, r2, r3, lsl #1 +100060a0: f06f 0100 mvneq.w r1, #0 +100060a4: f44f 1700 mov.w r7, #2097152 ; 0x200000 +100060a8: eb17 0f43 cmn.w r7, r3, lsl #1 +100060ac: bf8a itet hi +100060ae: 4619 movhi r1, r3 +100060b0: eb17 0f41 cmnls.w r7, r1, lsl #1 +100060b4: e7b5 bhi.n 10006022 <__aeabi_dmul+0xae> +100060b6: ea4c 5105 orr.w r1, ip, r5, lsl #20 +100060ba: 2000 movs r0, #0 +100060bc: bdb0 pop {r4, r5, r7, pc} +100060be: f1d4 0401 rsbs r4, r4, #1 +100060c2: f1b4 0720 subs.w r7, r4, #32 +100060c6: da0f bge.n 100060e8 <__aeabi_dmul+0x174> +100060c8: f1c4 0720 rsb r7, r4, #32 +100060cc: 0852 lsrs r2, r2, #1 +100060ce: bf28 it cs +100060d0: f042 0201 orrcs.w r2, r2, #1 +100060d4: fa10 f507 lsls.w r5, r0, r7 +100060d8: fa01 f707 lsl.w r7, r1, r7 +100060dc: bfe1 itttt al +100060de: 432a orral r2, r5 +100060e0: 40e0 lsral r0, r4 +100060e2: 4338 orral r0, r7 +100060e4: 40e1 lsral r1, r4 +100060e6: e00f b.n 10006108 <__aeabi_dmul+0x194> +100060e8: 2c35 cmp r4, #53 ; 0x35 +100060ea: dc98 bgt.n 1000601e <__aeabi_dmul+0xaa> +100060ec: f1c7 0420 rsb r4, r7, #32 +100060f0: ea52 0240 orrs.w r2, r2, r0, lsl #1 +100060f4: fa20 f207 lsr.w r2, r0, r7 +100060f8: bf18 it ne +100060fa: f042 0201 orrne.w r2, r2, #1 +100060fe: fa31 f007 lsrs.w r0, r1, r7 +10006102: 40a1 lsls r1, r4 +10006104: 430a orrs r2, r1 +10006106: 2100 movs r1, #0 +10006108: f172 4200 sbcs.w r2, r2, #2147483648 ; 0x80000000 +1000610c: f150 0000 adcs.w r0, r0, #0 +10006110: eb51 010c adcs.w r1, r1, ip +10006114: bdb0 pop {r4, r5, r7, pc} + +10006116 <__iar_zero_init3>: +10006116: f850 1b04 ldr.w r1, [r0], #4 +1000611a: b161 cbz r1, 10006136 <__iar_zero_init3+0x20> +1000611c: f850 2b04 ldr.w r2, [r0], #4 +10006120: 07d3 lsls r3, r2, #31 +10006122: bf44 itt mi +10006124: f1a9 0301 submi.w r3, r9, #1 +10006128: 189a addmi r2, r3, r2 +1000612a: 2300 movs r3, #0 +1000612c: f842 3b04 str.w r3, [r2], #4 +10006130: 1f09 subs r1, r1, #4 +10006132: d1fa bne.n 1000612a <__iar_zero_init3+0x14> +10006134: e7ef b.n 10006116 <__iar_zero_init3> +10006136: 4770 bx lr + +10006138 <__aeabi_dadd>: +10006138: b470 push {r4, r5, r6} +1000613a: f04f 4500 mov.w r5, #2147483648 ; 0x80000000 +1000613e: ea91 0c03 eors.w ip, r1, r3 +10006142: bf44 itt mi +10006144: 406b eormi r3, r5 +10006146: f000 b8b1 bmi.w 100062ac <__iar_dsub> +1000614a: bf00 nop + +1000614c <__iar_dadd>: +1000614c: 1a84 subs r4, r0, r2 +1000614e: eb71 0603 sbcs.w r6, r1, r3 +10006152: d203 bcs.n 1000615c <__iar_dadd+0x10> +10006154: 1b00 subs r0, r0, r4 +10006156: 41b1 sbcs r1, r6 +10006158: 1912 adds r2, r2, r4 +1000615a: 4173 adcs r3, r6 +1000615c: f44f 1c00 mov.w ip, #2097152 ; 0x200000 +10006160: eb1c 0f41 cmn.w ip, r1, lsl #1 +10006164: bf34 ite cc +10006166: eb7c 0443 sbcscc.w r4, ip, r3, lsl #1 +1000616a: e043 bcs.n 100061f4 <__iar_dadd+0xa8> +1000616c: 0d0c lsrs r4, r1, #20 +1000616e: eba4 5613 sub.w r6, r4, r3, lsr #20 +10006172: 2e35 cmp r6, #53 ; 0x35 +10006174: dc50 bgt.n 10006218 <__iar_dadd+0xcc> +10006176: ea45 23c3 orr.w r3, r5, r3, lsl #11 +1000617a: 0adb lsrs r3, r3, #11 +1000617c: ea45 21c1 orr.w r1, r5, r1, lsl #11 +10006180: 12c9 asrs r1, r1, #11 +10006182: f1b6 0520 subs.w r5, r6, #32 +10006186: dd0d ble.n 100061a4 <__iar_dadd+0x58> +10006188: fa63 f605 ror.w r6, r3, r5 +1000618c: 40eb lsrs r3, r5 +1000618e: ea86 0503 eor.w r5, r6, r3 +10006192: 4212 tst r2, r2 +10006194: bf18 it ne +10006196: f045 0501 orrne.w r5, r5, #1 +1000619a: 18c0 adds r0, r0, r3 +1000619c: f151 0100 adcs.w r1, r1, #0 +100061a0: d20c bcs.n 100061bc <__iar_dadd+0x70> +100061a2: e013 b.n 100061cc <__iar_dadd+0x80> +100061a4: fa62 f506 ror.w r5, r2, r6 +100061a8: 40f2 lsrs r2, r6 +100061aa: 4055 eors r5, r2 +100061ac: 41f3 rors r3, r6 +100061ae: 405a eors r2, r3 +100061b0: 40b3 lsls r3, r6 +100061b2: 40f3 lsrs r3, r6 +100061b4: 405a eors r2, r3 +100061b6: 1880 adds r0, r0, r2 +100061b8: 4159 adcs r1, r3 +100061ba: d307 bcc.n 100061cc <__iar_dadd+0x80> +100061bc: 0849 lsrs r1, r1, #1 +100061be: ea5f 0030 movs.w r0, r0, rrx +100061c2: ea5f 0535 movs.w r5, r5, rrx +100061c6: bf28 it cs +100061c8: f045 0501 orrcs.w r5, r5, #1 +100061cc: f501 1180 add.w r1, r1, #1048576 ; 0x100000 +100061d0: 0842 lsrs r2, r0, #1 +100061d2: f175 4200 sbcs.w r2, r5, #2147483648 ; 0x80000000 +100061d6: f150 0000 adcs.w r0, r0, #0 +100061da: eb41 5104 adc.w r1, r1, r4, lsl #20 +100061de: bc70 pop {r4, r5, r6} +100061e0: f44f 1c00 mov.w ip, #2097152 ; 0x200000 +100061e4: eb1c 0f41 cmn.w ip, r1, lsl #1 +100061e8: bf38 it cc +100061ea: 4770 bxcc lr +100061ec: 2000 movs r0, #0 +100061ee: 0d09 lsrs r1, r1, #20 +100061f0: 0509 lsls r1, r1, #20 +100061f2: 4770 bx lr +100061f4: eb1c 0f41 cmn.w ip, r1, lsl #1 +100061f8: d210 bcs.n 1000621c <__iar_dadd+0xd0> +100061fa: ea52 0643 orrs.w r6, r2, r3, lsl #1 +100061fe: d00b beq.n 10006218 <__iar_dadd+0xcc> +10006200: ebbc 0f41 cmp.w ip, r1, lsl #1 +10006204: d805 bhi.n 10006212 <__iar_dadd+0xc6> +10006206: 0d0c lsrs r4, r1, #20 +10006208: 43ab bics r3, r5 +1000620a: 1e66 subs r6, r4, #1 +1000620c: 2e34 cmp r6, #52 ; 0x34 +1000620e: ddb5 ble.n 1000617c <__iar_dadd+0x30> +10006210: e002 b.n 10006218 <__iar_dadd+0xcc> +10006212: 43ab bics r3, r5 +10006214: 1880 adds r0, r0, r2 +10006216: 4159 adcs r1, r3 +10006218: bc70 pop {r4, r5, r6} +1000621a: 4770 bx lr +1000621c: bc70 pop {r4, r5, r6} +1000621e: 4770 bx lr + +10006220 <__aeabi_d2iz>: +10006220: 46f4 mov ip, lr +10006222: 0d40 lsrs r0, r0, #21 +10006224: ea40 20c1 orr.w r0, r0, r1, lsl #11 +10006228: 0049 lsls r1, r1, #1 +1000622a: d206 bcs.n 1000623a <__aeabi_d2iz+0x1a> +1000622c: f000 f80e bl 1000624c <__iar_d2uiz> +10006230: 4200 tst r0, r0 +10006232: bf48 it mi +10006234: f06f 4000 mvnmi.w r0, #2147483648 ; 0x80000000 +10006238: 4760 bx ip +1000623a: f000 f807 bl 1000624c <__iar_d2uiz> +1000623e: f04f 4100 mov.w r1, #2147483648 ; 0x80000000 +10006242: 4288 cmp r0, r1 +10006244: bf8c ite hi +10006246: 4608 movhi r0, r1 +10006248: 4240 negls r0, r0 +1000624a: 4760 bx ip + +1000624c <__iar_d2uiz>: +1000624c: f040 4000 orr.w r0, r0, #2147483648 ; 0x80000000 +10006250: 0d49 lsrs r1, r1, #21 +10006252: f5a1 6180 sub.w r1, r1, #1024 ; 0x400 +10006256: 1c49 adds r1, r1, #1 +10006258: d405 bmi.n 10006266 <__iar_d2uiz+0x1a> +1000625a: f1d1 011f rsbs r1, r1, #31 +1000625e: bf54 ite pl +10006260: 40c8 lsrpl r0, r1 +10006262: 17c0 asrmi r0, r0, #31 +10006264: 4770 bx lr +10006266: f04f 0000 mov.w r0, #0 +1000626a: 4770 bx lr + +1000626c <__aeabi_i2d>: +1000626c: 0001 movs r1, r0 +1000626e: f140 8007 bpl.w 10006280 <__iar_ui2d> +10006272: 46f4 mov ip, lr +10006274: 4240 negs r0, r0 +10006276: f000 f803 bl 10006280 <__iar_ui2d> +1000627a: f051 4100 orrs.w r1, r1, #2147483648 ; 0x80000000 +1000627e: 4760 bx ip + +10006280 <__iar_ui2d>: +10006280: d009 beq.n 10006296 <__iar_ui2d+0x16> +10006282: fab0 f180 clz r1, r0 +10006286: 4088 lsls r0, r1 +10006288: 1cc9 adds r1, r1, #3 +1000628a: f5c1 6184 rsb r1, r1, #1056 ; 0x420 +1000628e: 0509 lsls r1, r1, #20 +10006290: eb01 21d0 add.w r1, r1, r0, lsr #11 +10006294: 0540 lsls r0, r0, #21 +10006296: 4770 bx lr + +10006298 <__aeabi_dsub>: +10006298: b470 push {r4, r5, r6} +1000629a: f04f 4500 mov.w r5, #2147483648 ; 0x80000000 +1000629e: ea91 0f03 teq r1, r3 +100062a2: bf44 itt mi +100062a4: 406b eormi r3, r5 +100062a6: f7ff bf51 bmi.w 1000614c <__iar_dadd> +100062aa: bf00 nop + +100062ac <__iar_dsub>: +100062ac: 1a84 subs r4, r0, r2 +100062ae: eb71 0603 sbcs.w r6, r1, r3 +100062b2: d204 bcs.n 100062be <__iar_dsubStart> +100062b4: 406e eors r6, r5 +100062b6: 1b00 subs r0, r0, r4 +100062b8: 41b1 sbcs r1, r6 +100062ba: 1912 adds r2, r2, r4 +100062bc: 4173 adcs r3, r6 + +100062be <__iar_dsubStart>: +100062be: f44f 1c00 mov.w ip, #2097152 ; 0x200000 +100062c2: eb1c 0f41 cmn.w ip, r1, lsl #1 +100062c6: bf34 ite cc +100062c8: eb7c 0643 sbcscc.w r6, ip, r3, lsl #1 +100062cc: e084 bcs.n 100063d8 <__iar_dsubStart+0x11a> +100062ce: 0d0c lsrs r4, r1, #20 +100062d0: eba4 5613 sub.w r6, r4, r3, lsr #20 +100062d4: 2e36 cmp r6, #54 ; 0x36 +100062d6: dc7d bgt.n 100063d4 <__iar_dsubStart+0x116> +100062d8: 2e01 cmp r6, #1 +100062da: dc43 bgt.n 10006364 <__iar_dsubStart+0xa6> +100062dc: ea45 23c3 orr.w r3, r5, r3, lsl #11 +100062e0: ea43 5352 orr.w r3, r3, r2, lsr #21 +100062e4: bf12 itee ne +100062e6: 02d2 lslne r2, r2, #11 +100062e8: 0292 lsleq r2, r2, #10 +100062ea: 085b lsreq r3, r3, #1 +100062ec: 0524 lsls r4, r4, #20 +100062ee: ea45 21c1 orr.w r1, r5, r1, lsl #11 +100062f2: ea41 5150 orr.w r1, r1, r0, lsr #21 +100062f6: ebd2 20c0 rsbs r0, r2, r0, lsl #11 +100062fa: 4199 sbcs r1, r3 +100062fc: d425 bmi.n 1000634a <__iar_dsubStart+0x8c> +100062fe: d107 bne.n 10006310 <__iar_dsubStart+0x52> +10006300: fab0 f680 clz r6, r0 +10006304: fa10 f106 lsls.w r1, r0, r6 +10006308: d064 beq.n 100063d4 <__iar_dsubStart+0x116> +1000630a: 2000 movs r0, #0 +1000630c: 3620 adds r6, #32 +1000630e: e008 b.n 10006322 <__iar_dsubStart+0x64> +10006310: fab1 f681 clz r6, r1 +10006314: 40b1 lsls r1, r6 +10006316: f1c6 0220 rsb r2, r6, #32 +1000631a: fa20 f202 lsr.w r2, r0, r2 +1000631e: 4311 orrs r1, r2 +10006320: 40b0 lsls r0, r6 +10006322: ea4f 74f4 mov.w r4, r4, ror #31 +10006326: ebb4 5446 subs.w r4, r4, r6, lsl #21 +1000632a: f034 0601 bics.w r6, r4, #1 +1000632e: ea4f 0474 mov.w r4, r4, ror #1 +10006332: d80a bhi.n 1000634a <__iar_dsubStart+0x8c> +10006334: f5d6 1600 rsbs r6, r6, #2097152 ; 0x200000 +10006338: 0d76 lsrs r6, r6, #21 +1000633a: f004 4400 and.w r4, r4, #2147483648 ; 0x80000000 +1000633e: 40f0 lsrs r0, r6 +10006340: fa61 f206 ror.w r2, r1, r6 +10006344: 4050 eors r0, r2 +10006346: 40f1 lsrs r1, r6 +10006348: 4048 eors r0, r1 +1000634a: 0ac0 lsrs r0, r0, #11 +1000634c: ea40 5041 orr.w r0, r0, r1, lsl #21 +10006350: f021 4100 bic.w r1, r1, #2147483648 ; 0x80000000 +10006354: bf28 it cs +10006356: ea5f 0550 movscs.w r5, r0, lsr #1 +1000635a: f150 0000 adcs.w r0, r0, #0 +1000635e: eb44 21d1 adc.w r1, r4, r1, lsr #11 +10006362: e037 b.n 100063d4 <__iar_dsubStart+0x116> +10006364: ea45 23c3 orr.w r3, r5, r3, lsl #11 +10006368: 0adb lsrs r3, r3, #11 +1000636a: ea45 21c1 orr.w r1, r5, r1, lsl #11 +1000636e: 0ac9 lsrs r1, r1, #11 +10006370: f1b6 0520 subs.w r5, r6, #32 +10006374: dd0e ble.n 10006394 <__iar_dsubStart+0xd6> +10006376: ea42 4202 orr.w r2, r2, r2, lsl #16 +1000637a: 0c12 lsrs r2, r2, #16 +1000637c: f1c5 0620 rsb r6, r5, #32 +10006380: fa03 f606 lsl.w r6, r3, r6 +10006384: 40eb lsrs r3, r5 +10006386: ea42 0506 orr.w r5, r2, r6 +1000638a: 426d negs r5, r5 +1000638c: 4198 sbcs r0, r3 +1000638e: f161 0100 sbc.w r1, r1, #0 +10006392: e00d b.n 100063b0 <__iar_dsubStart+0xf2> +10006394: fa62 f506 ror.w r5, r2, r6 +10006398: 40f2 lsrs r2, r6 +1000639a: 4055 eors r5, r2 +1000639c: fa63 fc06 ror.w ip, r3, r6 +100063a0: ea82 020c eor.w r2, r2, ip +100063a4: 40f3 lsrs r3, r6 +100063a6: 405a eors r2, r3 +100063a8: 426d negs r5, r5 +100063aa: 4190 sbcs r0, r2 +100063ac: eb61 0103 sbc.w r1, r1, r3 +100063b0: f411 1f80 tst.w r1, #1048576 ; 0x100000 +100063b4: d105 bne.n 100063c2 <__iar_dsubStart+0x104> +100063b6: 1e64 subs r4, r4, #1 +100063b8: 0562 lsls r2, r4, #21 +100063ba: d002 beq.n 100063c2 <__iar_dsubStart+0x104> +100063bc: 006d lsls r5, r5, #1 +100063be: 4140 adcs r0, r0 +100063c0: 4149 adcs r1, r1 +100063c2: f421 1180 bic.w r1, r1, #1048576 ; 0x100000 +100063c6: 0843 lsrs r3, r0, #1 +100063c8: f175 4300 sbcs.w r3, r5, #2147483648 ; 0x80000000 +100063cc: f150 0000 adcs.w r0, r0, #0 +100063d0: eb41 5104 adc.w r1, r1, r4, lsl #20 +100063d4: bc70 pop {r4, r5, r6} +100063d6: 4770 bx lr +100063d8: eb1c 0f41 cmn.w ip, r1, lsl #1 +100063dc: d215 bcs.n 1000640a <__iar_dsubStart+0x14c> +100063de: f023 4300 bic.w r3, r3, #2147483648 ; 0x80000000 +100063e2: ea52 0643 orrs.w r6, r2, r3, lsl #1 +100063e6: d00b beq.n 10006400 <__iar_dsubStart+0x142> +100063e8: ea4f 0c4c mov.w ip, ip, lsl #1 +100063ec: ebbc 0f41 cmp.w ip, r1, lsl #1 +100063f0: d804 bhi.n 100063fc <__iar_dsubStart+0x13e> +100063f2: 0d0c lsrs r4, r1, #20 +100063f4: 1e66 subs r6, r4, #1 +100063f6: 2e34 cmp r6, #52 ; 0x34 +100063f8: ddb7 ble.n 1000636a <__iar_dsubStart+0xac> +100063fa: e7eb b.n 100063d4 <__iar_dsubStart+0x116> +100063fc: 1a80 subs r0, r0, r2 +100063fe: 4199 sbcs r1, r3 +10006400: ea50 0641 orrs.w r6, r0, r1, lsl #1 +10006404: bf08 it eq +10006406: 2100 moveq r1, #0 +10006408: e7e4 b.n 100063d4 <__iar_dsubStart+0x116> +1000640a: bf08 it eq +1000640c: eb1c 0f43 cmneq.w ip, r3, lsl #1 +10006410: bf28 it cs +10006412: f06f 0100 mvncs.w r1, #0 +10006416: e7dd b.n 100063d4 <__iar_dsubStart+0x116> + +10006418 <__aeabi_ddiv>: +10006418: b5f0 push {r4, r5, r6, r7, lr} +1000641a: f240 75ff movw r5, #2047 ; 0x7ff +1000641e: ea81 0c03 eor.w ip, r1, r3 +10006422: f00c 4c00 and.w ip, ip, #2147483648 ; 0x80000000 +10006426: ea15 5411 ands.w r4, r5, r1, lsr #20 +1000642a: bf1d ittte ne +1000642c: ea15 5713 andsne.w r7, r5, r3, lsr #20 +10006430: 42ac cmpne r4, r5 +10006432: 42af cmpne r7, r5 +10006434: e0e5 beq.n 10006602 <__aeabi_ddiv+0x1ea> +10006436: 41bc sbcs r4, r7 +10006438: f3c1 0113 ubfx r1, r1, #0, #20 +1000643c: f3c3 0313 ubfx r3, r3, #0, #20 +10006440: 1a80 subs r0, r0, r2 +10006442: 4199 sbcs r1, r3 +10006444: f443 1380 orr.w r3, r3, #1048576 ; 0x100000 +10006448: d204 bcs.n 10006454 <__aeabi_ddiv+0x3c> +1000644a: 1e64 subs r4, r4, #1 +1000644c: 0040 lsls r0, r0, #1 +1000644e: 4149 adcs r1, r1 +10006450: 1880 adds r0, r0, r2 +10006452: 4159 adcs r1, r3 +10006454: 02c9 lsls r1, r1, #11 +10006456: ea41 5150 orr.w r1, r1, r0, lsr #21 +1000645a: fbb1 f6f3 udiv r6, r1, r3 +1000645e: fb03 1116 mls r1, r3, r6, r1 +10006462: fba2 7506 umull r7, r5, r2, r6 +10006466: ebd7 20c0 rsbs r0, r7, r0, lsl #11 +1000646a: 41a9 sbcs r1, r5 +1000646c: d202 bcs.n 10006474 <__aeabi_ddiv+0x5c> +1000646e: 1e76 subs r6, r6, #1 +10006470: 1880 adds r0, r0, r2 +10006472: 4159 adcs r1, r3 +10006474: 02c9 lsls r1, r1, #11 +10006476: ea41 5150 orr.w r1, r1, r0, lsr #21 +1000647a: fbb1 fef3 udiv lr, r1, r3 +1000647e: fb03 111e mls r1, r3, lr, r1 +10006482: fba2 750e umull r7, r5, r2, lr +10006486: ebd7 20c0 rsbs r0, r7, r0, lsl #11 +1000648a: 41a9 sbcs r1, r5 +1000648c: d203 bcs.n 10006496 <__aeabi_ddiv+0x7e> +1000648e: f1ae 0e01 sub.w lr, lr, #1 +10006492: 1880 adds r0, r0, r2 +10006494: 4159 adcs r1, r3 +10006496: 0289 lsls r1, r1, #10 +10006498: ea41 5190 orr.w r1, r1, r0, lsr #22 +1000649c: 0576 lsls r6, r6, #21 +1000649e: ea46 2e8e orr.w lr, r6, lr, lsl #10 +100064a2: fbb1 f6f3 udiv r6, r1, r3 +100064a6: fb03 1116 mls r1, r3, r6, r1 +100064aa: fba2 7506 umull r7, r5, r2, r6 +100064ae: ebd7 2080 rsbs r0, r7, r0, lsl #10 +100064b2: 41a9 sbcs r1, r5 +100064b4: d202 bcs.n 100064bc <__aeabi_ddiv+0xa4> +100064b6: 1e76 subs r6, r6, #1 +100064b8: 1880 adds r0, r0, r2 +100064ba: 4159 adcs r1, r3 +100064bc: 02c9 lsls r1, r1, #11 +100064be: ea41 5150 orr.w r1, r1, r0, lsr #21 +100064c2: ea4e 0e06 orr.w lr, lr, r6 +100064c6: fbb1 f6f3 udiv r6, r1, r3 +100064ca: fb03 1116 mls r1, r3, r6, r1 +100064ce: fba2 7506 umull r7, r5, r2, r6 +100064d2: ebd7 20c0 rsbs r0, r7, r0, lsl #11 +100064d6: 41a9 sbcs r1, r5 +100064d8: d202 bcs.n 100064e0 <__aeabi_ddiv+0xc8> +100064da: 1e76 subs r6, r6, #1 +100064dc: 1880 adds r0, r0, r2 +100064de: 4159 adcs r1, r3 +100064e0: 02c9 lsls r1, r1, #11 +100064e2: ea41 5150 orr.w r1, r1, r0, lsr #21 +100064e6: fbb1 f7f3 udiv r7, r1, r3 +100064ea: fb03 1117 mls r1, r3, r7, r1 +100064ee: fba2 3507 umull r3, r5, r2, r7 +100064f2: ebd3 20c0 rsbs r0, r3, r0, lsl #11 +100064f6: 41a9 sbcs r1, r5 +100064f8: f167 0700 sbc.w r7, r7, #0 +100064fc: bf0c ite eq +100064fe: 4200 tsteq r0, r0 +10006500: f047 0701 orrne.w r7, r7, #1 +10006504: f366 27d5 bfi r7, r6, #11, #11 +10006508: ea4f 311e mov.w r1, lr, lsr #12 +1000650c: 08b8 lsrs r0, r7, #2 +1000650e: f514 6480 adds.w r4, r4, #1024 ; 0x400 +10006512: dd12 ble.n 1000653a <__aeabi_ddiv+0x122> +10006514: 07bd lsls r5, r7, #30 +10006516: f175 4200 sbcs.w r2, r5, #2147483648 ; 0x80000000 +1000651a: eb50 500e adcs.w r0, r0, lr, lsl #20 +1000651e: eb51 5104 adcs.w r1, r1, r4, lsl #20 +10006522: f511 1f80 cmn.w r1, #1048576 ; 0x100000 +10006526: bf5c itt pl +10006528: ea41 010c orrpl.w r1, r1, ip +1000652c: bdf0 poppl {r4, r5, r6, r7, pc} +1000652e: f04c 617f orr.w r1, ip, #267386880 ; 0xff00000 +10006532: f041 41e0 orr.w r1, r1, #1879048192 ; 0x70000000 +10006536: 2000 movs r0, #0 +10006538: bdf0 pop {r4, r5, r6, r7, pc} +1000653a: 07bd lsls r5, r7, #30 +1000653c: 086d lsrs r5, r5, #1 +1000653e: ea40 500e orr.w r0, r0, lr, lsl #20 +10006542: f441 1180 orr.w r1, r1, #1048576 ; 0x100000 +10006546: f1d4 0401 rsbs r4, r4, #1 +1000654a: f1b4 0620 subs.w r6, r4, #32 +1000654e: da0a bge.n 10006566 <__aeabi_ddiv+0x14e> +10006550: f1c4 0620 rsb r6, r4, #32 +10006554: 0002 movs r2, r0 +10006556: 40e0 lsrs r0, r4 +10006558: fa01 f306 lsl.w r3, r1, r6 +1000655c: 40e1 lsrs r1, r4 +1000655e: 4318 orrs r0, r3 +10006560: 40b2 lsls r2, r6 +10006562: 4315 orrs r5, r2 +10006564: e00e b.n 10006584 <__aeabi_ddiv+0x16c> +10006566: 2c34 cmp r4, #52 ; 0x34 +10006568: dc13 bgt.n 10006592 <__aeabi_ddiv+0x17a> +1000656a: f1c6 0420 rsb r4, r6, #32 +1000656e: ea45 0540 orr.w r5, r5, r0, lsl #1 +10006572: 086d lsrs r5, r5, #1 +10006574: fa20 f206 lsr.w r2, r0, r6 +10006578: 4315 orrs r5, r2 +1000657a: fa21 f006 lsr.w r0, r1, r6 +1000657e: 40a1 lsls r1, r4 +10006580: 430d orrs r5, r1 +10006582: 2100 movs r1, #0 +10006584: f175 4200 sbcs.w r2, r5, #2147483648 ; 0x80000000 +10006588: f150 0000 adcs.w r0, r0, #0 +1000658c: eb51 010c adcs.w r1, r1, ip +10006590: bdf0 pop {r4, r5, r6, r7, pc} +10006592: 2000 movs r0, #0 +10006594: ea5f 010c movs.w r1, ip +10006598: bdf0 pop {r4, r5, r6, r7, pc} +1000659a: b9cf cbnz r7, 100065d0 <__aeabi_ddiv+0x1b8> +1000659c: 1892 adds r2, r2, r2 +1000659e: 415b adcs r3, r3 +100065a0: fab3 f783 clz r7, r3 +100065a4: bf04 itt eq +100065a6: fab2 f682 clzeq r6, r2 +100065aa: 19bf addeq r7, r7, r6 +100065ac: 3f0b subs r7, #11 +100065ae: f1b7 0620 subs.w r6, r7, #32 +100065b2: bf2f iteee cs +100065b4: fa02 f306 lslcs.w r3, r2, r6 +100065b8: 40bb lslcc r3, r7 +100065ba: f1c7 0620 rsbcc r6, r7, #32 +100065be: fa22 f606 lsrcc.w r6, r2, r6 +100065c2: bf38 it cc +100065c4: 4333 orrcc r3, r6 +100065c6: 40ba lsls r2, r7 +100065c8: b11c cbz r4, 100065d2 <__aeabi_ddiv+0x1ba> +100065ca: 19e4 adds r4, r4, r7 +100065cc: 1e64 subs r4, r4, #1 +100065ce: e733 b.n 10006438 <__aeabi_ddiv+0x20> +100065d0: 427f negs r7, r7 +100065d2: f031 4100 bics.w r1, r1, #2147483648 ; 0x80000000 +100065d6: fab1 f481 clz r4, r1 +100065da: bf04 itt eq +100065dc: fab0 f680 clzeq r6, r0 +100065e0: 19a4 addeq r4, r4, r6 +100065e2: 3c0b subs r4, #11 +100065e4: f1b4 0620 subs.w r6, r4, #32 +100065e8: bf2f iteee cs +100065ea: fa00 f106 lslcs.w r1, r0, r6 +100065ee: 40a1 lslcc r1, r4 +100065f0: f1c4 0620 rsbcc r6, r4, #32 +100065f4: fa20 f606 lsrcc.w r6, r0, r6 +100065f8: bf38 it cc +100065fa: 4331 orrcc r1, r6 +100065fc: 40a0 lsls r0, r4 +100065fe: 1b3c subs r4, r7, r4 +10006600: e71a b.n 10006438 <__aeabi_ddiv+0x20> +10006602: 42ac cmp r4, r5 +10006604: bf1a itte ne +10006606: ea05 5713 andne.w r7, r5, r3, lsr #20 +1000660a: 42af cmpne r7, r5 +1000660c: e012 beq.n 10006634 <__aeabi_ddiv+0x21c> +1000660e: ea50 0641 orrs.w r6, r0, r1, lsl #1 +10006612: bf1c itt ne +10006614: ea52 0643 orrsne.w r6, r2, r3, lsl #1 +10006618: e7bf bne.n 1000659a <__aeabi_ddiv+0x182> +1000661a: ea50 0741 orrs.w r7, r0, r1, lsl #1 +1000661e: 4630 mov r0, r6 +10006620: 4661 mov r1, ip +10006622: bf1c itt ne +10006624: ea41 5105 orrne.w r1, r1, r5, lsl #20 +10006628: bdf0 popne {r4, r5, r6, r7, pc} +1000662a: ea52 0c43 orrs.w ip, r2, r3, lsl #1 +1000662e: bf08 it eq +10006630: 43c1 mvneq r1, r0 +10006632: bdf0 pop {r4, r5, r6, r7, pc} +10006634: 2000 movs r0, #0 +10006636: f44f 1600 mov.w r6, #2097152 ; 0x200000 +1000663a: eb16 0f41 cmn.w r6, r1, lsl #1 +1000663e: bf98 it ls +10006640: eb16 0f43 cmnls.w r6, r3, lsl #1 +10006644: bf08 it eq +10006646: eb16 0f41 cmneq.w r6, r1, lsl #1 +1000664a: bf24 itt cs +1000664c: 43c1 mvncs r1, r0 +1000664e: e005 bcs.n 1000665c <__aeabi_ddiv+0x244> +10006650: eb16 0f43 cmn.w r6, r3, lsl #1 +10006654: bf0c ite eq +10006656: 4661 moveq r1, ip +10006658: ea4c 5105 orrne.w r1, ip, r5, lsl #20 +1000665c: bdf0 pop {r4, r5, r6, r7, pc} + ... + +10006660 <__iar_Logpoly>: +10006660: b538 push {r3, r4, r5, lr} +10006662: 4604 mov r4, r0 +10006664: 460d mov r5, r1 +10006666: 481b ldr r0, [pc, #108] ; (100066d4 <.text_10>) +10006668: 491b ldr r1, [pc, #108] ; (100066d8 <.text_11>) +1000666a: 4622 mov r2, r4 +1000666c: 462b mov r3, r5 +1000666e: f7ff fc81 bl 10005f74 <__aeabi_dmul> +10006672: 4a1a ldr r2, [pc, #104] ; (100066dc <.text_12>) +10006674: 4b1a ldr r3, [pc, #104] ; (100066e0 <.text_13>) +10006676: f7ff fd5f bl 10006138 <__aeabi_dadd> +1000667a: 4622 mov r2, r4 +1000667c: 462b mov r3, r5 +1000667e: f7ff fc79 bl 10005f74 <__aeabi_dmul> +10006682: 4a18 ldr r2, [pc, #96] ; (100066e4 <.text_14>) +10006684: 4b18 ldr r3, [pc, #96] ; (100066e8 <.text_15>) +10006686: f7ff fd57 bl 10006138 <__aeabi_dadd> +1000668a: 4622 mov r2, r4 +1000668c: 462b mov r3, r5 +1000668e: f7ff fc71 bl 10005f74 <__aeabi_dmul> +10006692: 4a16 ldr r2, [pc, #88] ; (100066ec <.text_16>) +10006694: 4b16 ldr r3, [pc, #88] ; (100066f0 <.text_17>) +10006696: f7ff fd4f bl 10006138 <__aeabi_dadd> +1000669a: 4622 mov r2, r4 +1000669c: 462b mov r3, r5 +1000669e: f7ff fc69 bl 10005f74 <__aeabi_dmul> +100066a2: 4a14 ldr r2, [pc, #80] ; (100066f4 <.text_18>) +100066a4: 4b14 ldr r3, [pc, #80] ; (100066f8 <.text_19>) +100066a6: f7ff fd47 bl 10006138 <__aeabi_dadd> +100066aa: 4622 mov r2, r4 +100066ac: 462b mov r3, r5 +100066ae: f7ff fc61 bl 10005f74 <__aeabi_dmul> +100066b2: 4a12 ldr r2, [pc, #72] ; (100066fc <.text_20>) +100066b4: 4b12 ldr r3, [pc, #72] ; (10006700 <.text_21>) +100066b6: f7ff fd3f bl 10006138 <__aeabi_dadd> +100066ba: 4622 mov r2, r4 +100066bc: 462b mov r3, r5 +100066be: f7ff fc59 bl 10005f74 <__aeabi_dmul> +100066c2: b001 add sp, #4 +100066c4: e8bd 4030 ldmia.w sp!, {r4, r5, lr} +100066c8: 4a0e ldr r2, [pc, #56] ; (10006704 <.text_22>) +100066ca: 4b0f ldr r3, [pc, #60] ; (10006708 <.text_23>) +100066cc: f7ff bd34 b.w 10006138 <__aeabi_dadd> +100066d0: 0000 movs r0, r0 + ... + +100066d4 <.text_10>: +100066d4: bf29def7 .word 0xbf29def7 + +100066d8 <.text_11>: +100066d8: 3fc2f8d8 .word 0x3fc2f8d8 + +100066dc <.text_12>: +100066dc: ccfeb3f4 .word 0xccfeb3f4 + +100066e0 <.text_13>: +100066e0: 3fc3991a .word 0x3fc3991a + +100066e4 <.text_14>: +100066e4: d968cb62 .word 0xd968cb62 + +100066e8 <.text_15>: +100066e8: 3fc7466f .word 0x3fc7466f + +100066ec <.text_16>: +100066ec: da12c9c6 .word 0xda12c9c6 + +100066f0 <.text_17>: +100066f0: 3fcc71c4 .word 0x3fcc71c4 + +100066f4 <.text_18>: +100066f4: 948ae94a .word 0x948ae94a + +100066f8 <.text_19>: +100066f8: 3fd24924 .word 0x3fd24924 + +100066fc <.text_20>: +100066fc: 99975ff7 .word 0x99975ff7 + +10006700 <.text_21>: +10006700: 3fd99999 .word 0x3fd99999 + +10006704 <.text_22>: +10006704: 555555bc .word 0x555555bc + +10006708 <.text_23>: +10006708: 3fe55555 .word 0x3fe55555 + +1000670c <__iar_Exp>: +1000670c: e92d 4df0 stmdb sp!, {r4, r5, r6, r7, r8, sl, fp, lr} +10006710: 4680 mov r8, r0 +10006712: b086 sub sp, #24 +10006714: e9d8 6700 ldrd r6, r7, [r8] +10006718: 4614 mov r4, r2 +1000671a: 461d mov r5, r3 +1000671c: 4630 mov r0, r6 +1000671e: 4639 mov r1, r7 +10006720: f000 f953 bl 100069ca <__iar_Dtest> +10006724: 4682 mov sl, r0 +10006726: 4620 mov r0, r4 +10006728: 4629 mov r1, r5 +1000672a: f000 f94e bl 100069ca <__iar_Dtest> +1000672e: f1ba 0f00 cmp.w sl, #0 +10006732: d506 bpl.n 10006742 <__iar_Exp+0x36> +10006734: 2800 cmp r0, #0 +10006736: d44d bmi.n 100067d4 <__iar_Exp+0xc8> +10006738: 2802 cmp r0, #2 +1000673a: d106 bne.n 1000674a <__iar_Exp+0x3e> +1000673c: e9c8 4500 strd r4, r5, [r8] +10006740: e13f b.n 100069c2 <.text_3> +10006742: f1ba 0f02 cmp.w sl, #2 +10006746: d1f7 bne.n 10006738 <__iar_Exp+0x2c> +10006748: e021 b.n 1000678e <__iar_Exp+0x82> +1000674a: b950 cbnz r0, 10006762 <__iar_Exp+0x56> +1000674c: 2200 movs r2, #0 +1000674e: 4b52 ldr r3, [pc, #328] ; (10006898 <__iar_Exp+0x18c>) +10006750: 4630 mov r0, r6 +10006752: 4639 mov r1, r7 +10006754: f7ff fbb8 bl 10005ec8 <__aeabi_cdcmpeq> +10006758: d00f beq.n 1000677a <__iar_Exp+0x6e> +1000675a: e9c8 4500 strd r4, r5, [r8] +1000675e: 2000 movs r0, #0 +10006760: e12f b.n 100069c2 <.text_3> +10006762: 2801 cmp r0, #1 +10006764: d115 bne.n 10006792 <__iar_Exp+0x86> +10006766: 2200 movs r2, #0 +10006768: 4b4c ldr r3, [pc, #304] ; (1000689c <__iar_Exp+0x190>) +1000676a: 4630 mov r0, r6 +1000676c: 4639 mov r1, r7 +1000676e: f7ff fbab bl 10005ec8 <__aeabi_cdcmpeq> +10006772: bf18 it ne +10006774: e9c8 4500 strdne r4, r5, [r8] +10006778: d14f bne.n 1000681a <__iar_Exp+0x10e> +1000677a: f7ff fbb5 bl 10005ee8 <__aeabi_errno_addr> +1000677e: 2121 movs r1, #33 ; 0x21 +10006780: 6001 str r1, [r0, #0] +10006782: f04f 30ff mov.w r0, #4294967295 +10006786: f06f 4100 mvn.w r1, #2147483648 ; 0x80000000 +1000678a: e9c8 0100 strd r0, r1, [r8] +1000678e: 2002 movs r0, #2 +10006790: e117 b.n 100069c2 <.text_3> +10006792: f1ba 0f00 cmp.w sl, #0 +10006796: d10f bne.n 100067b8 <__iar_Exp+0xac> +10006798: e9c8 4500 strd r4, r5, [r8] +1000679c: 990e ldr r1, [sp, #56] ; 0x38 +1000679e: 4640 mov r0, r8 +100067a0: f000 f92c bl 100069fc <__iar_Dscale> +100067a4: 0004 movs r4, r0 +100067a6: bf18 it ne +100067a8: 2c01 cmpne r4, #1 +100067aa: f040 8109 bne.w 100069c0 <__iar_Exp+0x2b4> +100067ae: f7ff fb9b bl 10005ee8 <__aeabi_errno_addr> +100067b2: 2122 movs r1, #34 ; 0x22 +100067b4: 6001 str r1, [r0, #0] +100067b6: e103 b.n 100069c0 <__iar_Exp+0x2b4> +100067b8: 2200 movs r2, #0 +100067ba: 4b37 ldr r3, [pc, #220] ; (10006898 <__iar_Exp+0x18c>) +100067bc: 4630 mov r0, r6 +100067be: 4639 mov r1, r7 +100067c0: f7ff fb82 bl 10005ec8 <__aeabi_cdcmpeq> +100067c4: d10d bne.n 100067e2 <__iar_Exp+0xd6> +100067c6: 4620 mov r0, r4 +100067c8: 4629 mov r1, r5 +100067ca: f7ff fbd3 bl 10005f74 <__aeabi_dmul> +100067ce: e9c8 0100 strd r0, r1, [r8] +100067d2: e022 b.n 1000681a <__iar_Exp+0x10e> +100067d4: 4630 mov r0, r6 +100067d6: 4639 mov r1, r7 +100067d8: 2200 movs r2, #0 +100067da: 4b31 ldr r3, [pc, #196] ; (100068a0 <__iar_Exp+0x194>) +100067dc: f7ff fba4 bl 10005f28 <__aeabi_cdcmple> +100067e0: d20a bcs.n 100067f8 <__iar_Exp+0xec> +100067e2: 2300 movs r3, #0 +100067e4: 4620 mov r0, r4 +100067e6: 4629 mov r1, r5 +100067e8: f7ff fbc4 bl 10005f74 <__aeabi_dmul> +100067ec: e9c8 0100 strd r0, r1, [r8] +100067f0: b006 add sp, #24 +100067f2: 2000 movs r0, #0 +100067f4: e8bd 8df0 ldmia.w sp!, {r4, r5, r6, r7, r8, sl, fp, pc} +100067f8: 2201 movs r2, #1 +100067fa: 4b2a ldr r3, [pc, #168] ; (100068a4 <__iar_Exp+0x198>) +100067fc: f7ff fb7a bl 10005ef4 <__aeabi_cdrcmple> +10006800: d80d bhi.n 1000681e <__iar_Exp+0x112> +10006802: 2200 movs r2, #0 +10006804: 4b24 ldr r3, [pc, #144] ; (10006898 <__iar_Exp+0x18c>) +10006806: 4620 mov r0, r4 +10006808: 4629 mov r1, r5 +1000680a: f7ff fbb3 bl 10005f74 <__aeabi_dmul> +1000680e: e9c8 0100 strd r0, r1, [r8] +10006812: f7ff fb69 bl 10005ee8 <__aeabi_errno_addr> +10006816: 2122 movs r1, #34 ; 0x22 +10006818: 6001 str r1, [r0, #0] +1000681a: 2001 movs r0, #1 +1000681c: e0d1 b.n 100069c2 <.text_3> +1000681e: 4a22 ldr r2, [pc, #136] ; (100068a8 <__iar_Exp+0x19c>) +10006820: 4b22 ldr r3, [pc, #136] ; (100068ac <__iar_Exp+0x1a0>) +10006822: f7ff fba7 bl 10005f74 <__aeabi_dmul> +10006826: 2200 movs r2, #0 +10006828: 2300 movs r3, #0 +1000682a: f7ff fb7d bl 10005f28 <__aeabi_cdcmple> +1000682e: bf34 ite cc +10006830: 4b1f ldrcc r3, [pc, #124] ; (100068b0 <__iar_Exp+0x1a4>) +10006832: 4b40 ldrcs r3, [pc, #256] ; (10006934 <__iar_Exp+0x228>) +10006834: f7ff fc80 bl 10006138 <__aeabi_dadd> +10006838: f7ff fcf2 bl 10006220 <__aeabi_d2iz> +1000683c: 9002 str r0, [sp, #8] +1000683e: f7ff fd15 bl 1000626c <__aeabi_i2d> +10006842: 4682 mov sl, r0 +10006844: 468b mov fp, r1 +10006846: f04f 4278 mov.w r2, #4160749568 ; 0xf8000000 +1000684a: 4b1a ldr r3, [pc, #104] ; (100068b4 <__iar_Exp+0x1a8>) +1000684c: f7ff fb92 bl 10005f74 <__aeabi_dmul> +10006850: 4602 mov r2, r0 +10006852: 460b mov r3, r1 +10006854: 4630 mov r0, r6 +10006856: 4639 mov r1, r7 +10006858: f7ff fd1e bl 10006298 <__aeabi_dsub> +1000685c: 4606 mov r6, r0 +1000685e: 460f mov r7, r1 +10006860: 4a15 ldr r2, [pc, #84] ; (100068b8 <__iar_Exp+0x1ac>) +10006862: 4b16 ldr r3, [pc, #88] ; (100068bc <__iar_Exp+0x1b0>) +10006864: 4650 mov r0, sl +10006866: 4659 mov r1, fp +10006868: f7ff fb84 bl 10005f74 <__aeabi_dmul> +1000686c: 4602 mov r2, r0 +1000686e: 460b mov r3, r1 +10006870: 4630 mov r0, r6 +10006872: 4639 mov r1, r7 +10006874: f7ff fd10 bl 10006298 <__aeabi_dsub> +10006878: f06f 0201 mvn.w r2, #1 +1000687c: 4b10 ldr r3, [pc, #64] ; (100068c0 <__iar_Exp+0x1b4>) +1000687e: f7ff fb39 bl 10005ef4 <__aeabi_cdrcmple> +10006882: 4606 mov r6, r0 +10006884: 460f mov r7, r1 +10006886: d81f bhi.n 100068c8 <__iar_Exp+0x1bc> +10006888: 2200 movs r2, #0 +1000688a: 4b0e ldr r3, [pc, #56] ; (100068c4 <__iar_Exp+0x1b8>) +1000688c: f7ff fb4c bl 10005f28 <__aeabi_cdcmple> +10006890: d21a bcs.n 100068c8 <__iar_Exp+0x1bc> +10006892: 4620 mov r0, r4 +10006894: 4629 mov r1, r5 +10006896: e083 b.n 100069a0 <__iar_Exp+0x294> +10006898: 7ff00000 .word 0x7ff00000 +1000689c: fff00000 .word 0xfff00000 +100068a0: c09cc800 .word 0xc09cc800 +100068a4: 409cc800 .word 0x409cc800 +100068a8: 652b82fe .word 0x652b82fe +100068ac: 3ff71547 .word 0x3ff71547 +100068b0: bfe00000 .word 0xbfe00000 +100068b4: 3fe62e42 .word 0x3fe62e42 +100068b8: bcd5e4f2 .word 0xbcd5e4f2 +100068bc: 3e4be8e7 .word 0x3e4be8e7 +100068c0: bc8fffff .word 0xbc8fffff +100068c4: 3c900000 .word 0x3c900000 +100068c8: 4632 mov r2, r6 +100068ca: 463b mov r3, r7 +100068cc: f7ff fb52 bl 10005f74 <__aeabi_dmul> +100068d0: 4682 mov sl, r0 +100068d2: 468b mov fp, r1 +100068d4: 4a18 ldr r2, [pc, #96] ; (10006938 <__iar_Exp+0x22c>) +100068d6: 4b19 ldr r3, [pc, #100] ; (1000693c <__iar_Exp+0x230>) +100068d8: f7ff fb4c bl 10005f74 <__aeabi_dmul> +100068dc: 4a18 ldr r2, [pc, #96] ; (10006940 <__iar_Exp+0x234>) +100068de: 4b19 ldr r3, [pc, #100] ; (10006944 <__iar_Exp+0x238>) +100068e0: f7ff fc2a bl 10006138 <__aeabi_dadd> +100068e4: 4602 mov r2, r0 +100068e6: 460b mov r3, r1 +100068e8: 4650 mov r0, sl +100068ea: 4659 mov r1, fp +100068ec: f7ff fb42 bl 10005f74 <__aeabi_dmul> +100068f0: e9cd 0104 strd r0, r1, [sp, #16] +100068f4: 4a14 ldr r2, [pc, #80] ; (10006948 <__iar_Exp+0x23c>) +100068f6: 4b15 ldr r3, [pc, #84] ; (1000694c <__iar_Exp+0x240>) +100068f8: 4650 mov r0, sl +100068fa: 4659 mov r1, fp +100068fc: f7ff fb3a bl 10005f74 <__aeabi_dmul> +10006900: 4a13 ldr r2, [pc, #76] ; (10006950 <__iar_Exp+0x244>) +10006902: 4b14 ldr r3, [pc, #80] ; (10006954 <__iar_Exp+0x248>) +10006904: f7ff fc18 bl 10006138 <__aeabi_dadd> +10006908: 4602 mov r2, r0 +1000690a: 460b mov r3, r1 +1000690c: 4650 mov r0, sl +1000690e: 4659 mov r1, fp +10006910: f7ff fb30 bl 10005f74 <__aeabi_dmul> +10006914: 2200 movs r2, #0 +10006916: 4b07 ldr r3, [pc, #28] ; (10006934 <__iar_Exp+0x228>) +10006918: f7ff fc0e bl 10006138 <__aeabi_dadd> +1000691c: 4602 mov r2, r0 +1000691e: 460b mov r3, r1 +10006920: 4630 mov r0, r6 +10006922: 4639 mov r1, r7 +10006924: f7ff fb26 bl 10005f74 <__aeabi_dmul> +10006928: e9dd 2304 ldrd r2, r3, [sp, #16] +1000692c: 4606 mov r6, r0 +1000692e: 468b mov fp, r1 +10006930: 4f09 ldr r7, [pc, #36] ; (10006958 <__iar_Exp+0x24c>) +10006932: e013 b.n 1000695c <__iar_Exp+0x250> +10006934: 3fe00000 .word 0x3fe00000 +10006938: 81572e11 .word 0x81572e11 +1000693c: 3f503fa0 .word 0x3f503fa0 +10006940: 8c124358 .word 0x8c124358 +10006944: 3fbc718f .word 0x3fbc718f +10006948: 41a5e84b .word 0x41a5e84b +1000694c: 3f0152b7 .word 0x3f0152b7 +10006950: daf3bd0b .word 0xdaf3bd0b +10006954: 3f8c70e8 .word 0x3f8c70e8 +10006958: 3ff00000 .word 0x3ff00000 +1000695c: f7ff fbec bl 10006138 <__aeabi_dadd> +10006960: 4602 mov r2, r0 +10006962: 460b mov r3, r1 +10006964: 2000 movs r0, #0 +10006966: 4639 mov r1, r7 +10006968: f7ff fbe6 bl 10006138 <__aeabi_dadd> +1000696c: e9cd 0100 strd r0, r1, [sp] +10006970: 4632 mov r2, r6 +10006972: e9dd 0104 ldrd r0, r1, [sp, #16] +10006976: 465b mov r3, fp +10006978: f7ff fc8e bl 10006298 <__aeabi_dsub> +1000697c: 4602 mov r2, r0 +1000697e: 460b mov r3, r1 +10006980: 2000 movs r0, #0 +10006982: 4639 mov r1, r7 +10006984: f7ff fbd8 bl 10006138 <__aeabi_dadd> +10006988: 4602 mov r2, r0 +1000698a: 460b mov r3, r1 +1000698c: e9dd 0100 ldrd r0, r1, [sp] +10006990: f7ff fd42 bl 10006418 <__aeabi_ddiv> +10006994: 4602 mov r2, r0 +10006996: 460b mov r3, r1 +10006998: 4620 mov r0, r4 +1000699a: 4629 mov r1, r5 +1000699c: f7ff faea bl 10005f74 <__aeabi_dmul> +100069a0: e9c8 0100 strd r0, r1, [r8] +100069a4: 9802 ldr r0, [sp, #8] +100069a6: 990e ldr r1, [sp, #56] ; 0x38 +100069a8: 1809 adds r1, r1, r0 +100069aa: 4640 mov r0, r8 +100069ac: f000 f826 bl 100069fc <__iar_Dscale> +100069b0: 0004 movs r4, r0 +100069b2: bf18 it ne +100069b4: 2c01 cmpne r4, #1 +100069b6: d103 bne.n 100069c0 <__iar_Exp+0x2b4> +100069b8: f7ff fa96 bl 10005ee8 <__aeabi_errno_addr> +100069bc: 2122 movs r1, #34 ; 0x22 +100069be: 6001 str r1, [r0, #0] +100069c0: 4620 mov r0, r4 + +100069c2 <.text_3>: +100069c2: b006 add sp, #24 +100069c4: e8bd 8df0 ldmia.w sp!, {r4, r5, r6, r7, r8, sl, fp, pc} + +100069c8 <__iar_dlib_perthread_access>: +100069c8: 4770 bx lr + +100069ca <__iar_Dtest>: +100069ca: f3c1 520a ubfx r2, r1, #20, #11 +100069ce: f240 73ff movw r3, #2047 ; 0x7ff +100069d2: 429a cmp r2, r3 +100069d4: d00a beq.n 100069ec <__iar_Dtest+0x22> +100069d6: b112 cbz r2, 100069de <__iar_Dtest+0x14> +100069d8: f04f 30ff mov.w r0, #4294967295 +100069dc: 4770 bx lr +100069de: 0309 lsls r1, r1, #12 +100069e0: ea50 3011 orrs.w r0, r0, r1, lsr #12 +100069e4: d009 beq.n 100069fa <__iar_Dtest+0x30> +100069e6: f06f 0001 mvn.w r0, #1 +100069ea: 4770 bx lr +100069ec: 0309 lsls r1, r1, #12 +100069ee: ea50 3011 orrs.w r0, r0, r1, lsr #12 +100069f2: d001 beq.n 100069f8 <__iar_Dtest+0x2e> +100069f4: 2002 movs r0, #2 +100069f6: 4770 bx lr +100069f8: 2001 movs r0, #1 +100069fa: 4770 bx lr + +100069fc <__iar_Dscale>: +100069fc: b570 push {r4, r5, r6, lr} +100069fe: 4604 mov r4, r0 +10006a00: 460d mov r5, r1 +10006a02: 6860 ldr r0, [r4, #4] +10006a04: f3c0 500a ubfx r0, r0, #20, #11 +10006a08: f240 71ff movw r1, #2047 ; 0x7ff +10006a0c: 4288 cmp r0, r1 +10006a0e: d107 bne.n 10006a20 <__iar_Dscale+0x24> +10006a10: 6860 ldr r0, [r4, #4] +10006a12: 0300 lsls r0, r0, #12 +10006a14: bf04 itt eq +10006a16: 6820 ldreq r0, [r4, #0] +10006a18: 2800 cmpeq r0, #0 +10006a1a: d017 beq.n 10006a4c <__iar_Dscale+0x50> +10006a1c: 2002 movs r0, #2 +10006a1e: bd70 pop {r4, r5, r6, pc} +10006a20: b920 cbnz r0, 10006a2c <__iar_Dscale+0x30> +10006a22: 4620 mov r0, r4 +10006a24: f7ff f9f0 bl 10005e08 <__iar_Dnorm> +10006a28: 2801 cmp r0, #1 +10006a2a: da67 bge.n 10006afc <__iar_Dscale+0x100> +10006a2c: 2d01 cmp r5, #1 +10006a2e: db0f blt.n 10006a50 <__iar_Dscale+0x54> +10006a30: f240 71ff movw r1, #2047 ; 0x7ff +10006a34: 1a09 subs r1, r1, r0 +10006a36: 428d cmp r5, r1 +10006a38: d30a bcc.n 10006a50 <__iar_Dscale+0x54> +10006a3a: 6860 ldr r0, [r4, #4] +10006a3c: 2800 cmp r0, #0 +10006a3e: bf47 ittee mi +10006a40: 2000 movmi r0, #0 +10006a42: 492f ldrmi r1, [pc, #188] ; (10006b00 <__iar_Dscale+0x104>) +10006a44: 2000 movpl r0, #0 +10006a46: 492f ldrpl r1, [pc, #188] ; (10006b04 <__iar_Dscale+0x108>) +10006a48: e9c4 0100 strd r0, r1, [r4] +10006a4c: 2001 movs r0, #1 +10006a4e: bd70 pop {r4, r5, r6, pc} +10006a50: 4241 negs r1, r0 +10006a52: 42a9 cmp r1, r5 +10006a54: 6861 ldr r1, [r4, #4] +10006a56: da06 bge.n 10006a66 <__iar_Dscale+0x6a> +10006a58: f36f 511e bfc r1, #20, #11 +10006a5c: 1940 adds r0, r0, r5 +10006a5e: ea41 5000 orr.w r0, r1, r0, lsl #20 +10006a62: 6060 str r0, [r4, #4] +10006a64: e041 b.n 10006aea <__iar_Dscale+0xee> +10006a66: 1e40 subs r0, r0, #1 +10006a68: 6863 ldr r3, [r4, #4] +10006a6a: 2201 movs r2, #1 +10006a6c: 1945 adds r5, r0, r5 +10006a6e: f362 531f bfi r3, r2, #20, #12 +10006a72: f105 0035 add.w r0, r5, #53 ; 0x35 +10006a76: f001 4100 and.w r1, r1, #2147483648 ; 0x80000000 +10006a7a: 6063 str r3, [r4, #4] +10006a7c: 2835 cmp r0, #53 ; 0x35 +10006a7e: d303 bcc.n 10006a88 <__iar_Dscale+0x8c> +10006a80: 6061 str r1, [r4, #4] +10006a82: 2000 movs r0, #0 +10006a84: 6020 str r0, [r4, #0] +10006a86: bd70 pop {r4, r5, r6, pc} +10006a88: 2200 movs r2, #0 +10006a8a: f115 0f1f cmn.w r5, #31 +10006a8e: da04 bge.n 10006a9a <__iar_Dscale+0x9e> +10006a90: 6822 ldr r2, [r4, #0] +10006a92: 6023 str r3, [r4, #0] +10006a94: 2000 movs r0, #0 +10006a96: 3520 adds r5, #32 +10006a98: 6060 str r0, [r4, #4] +10006a9a: 4268 negs r0, r5 +10006a9c: d013 beq.n 10006ac6 <__iar_Dscale+0xca> +10006a9e: 1e52 subs r2, r2, #1 +10006aa0: 6825 ldr r5, [r4, #0] +10006aa2: 4192 sbcs r2, r2 +10006aa4: f1c0 0320 rsb r3, r0, #32 +10006aa8: 43d2 mvns r2, r2 +10006aaa: 409d lsls r5, r3 +10006aac: ea45 72d2 orr.w r2, r5, r2, lsr #31 +10006ab0: 6825 ldr r5, [r4, #0] +10006ab2: 6866 ldr r6, [r4, #4] +10006ab4: 40c5 lsrs r5, r0 +10006ab6: fa06 f303 lsl.w r3, r6, r3 +10006aba: 432b orrs r3, r5 +10006abc: 6023 str r3, [r4, #0] +10006abe: 6863 ldr r3, [r4, #4] +10006ac0: fa23 f000 lsr.w r0, r3, r0 +10006ac4: 6060 str r0, [r4, #4] +10006ac6: 6860 ldr r0, [r4, #4] +10006ac8: 4308 orrs r0, r1 +10006aca: 6060 str r0, [r4, #4] +10006acc: f1b2 4f00 cmp.w r2, #2147483648 ; 0x80000000 +10006ad0: d803 bhi.n 10006ada <__iar_Dscale+0xde> +10006ad2: d10d bne.n 10006af0 <__iar_Dscale+0xf4> +10006ad4: 7820 ldrb r0, [r4, #0] +10006ad6: 07c0 lsls r0, r0, #31 +10006ad8: d50a bpl.n 10006af0 <__iar_Dscale+0xf4> +10006ada: 6820 ldr r0, [r4, #0] +10006adc: 1c40 adds r0, r0, #1 +10006ade: 6020 str r0, [r4, #0] +10006ae0: 6820 ldr r0, [r4, #0] +10006ae2: b928 cbnz r0, 10006af0 <__iar_Dscale+0xf4> +10006ae4: 6860 ldr r0, [r4, #4] +10006ae6: 1c40 adds r0, r0, #1 +10006ae8: 6060 str r0, [r4, #4] +10006aea: f04f 30ff mov.w r0, #4294967295 +10006aee: bd70 pop {r4, r5, r6, pc} +10006af0: 6860 ldr r0, [r4, #4] +10006af2: 4288 cmp r0, r1 +10006af4: bf04 itt eq +10006af6: 6820 ldreq r0, [r4, #0] +10006af8: 2800 cmpeq r0, #0 +10006afa: d1f6 bne.n 10006aea <__iar_Dscale+0xee> +10006afc: 2000 movs r0, #0 +10006afe: bd70 pop {r4, r5, r6, pc} +10006b00: fff00000 .word 0xfff00000 +10006b04: 7ff00000 .word 0x7ff00000 + +10006b08 : +10006b08: b570 push {r4, r5, r6, lr} +10006b0a: 4b2f ldr r3, [pc, #188] ; (10006bc8 ) +10006b0c: 4a2f ldr r2, [pc, #188] ; (10006bcc ) +10006b0e: 681d ldr r5, [r3, #0] +10006b10: 4015 ands r5, r2 +10006b12: 601d str r5, [r3, #0] +10006b14: f500 76a2 add.w r6, r0, #324 ; 0x144 +10006b18: 4b2d ldr r3, [pc, #180] ; (10006bd0 ) +10006b1a: 681d ldr r5, [r3, #0] +10006b1c: 402a ands r2, r5 +10006b1e: 601a str r2, [r3, #0] +10006b20: f100 0334 add.w r3, r0, #52 ; 0x34 +10006b24: 6003 str r3, [r0, #0] +10006b26: 6018 str r0, [r3, #0] +10006b28: f500 72b6 add.w r2, r0, #364 ; 0x16c +10006b2c: 4d29 ldr r5, [pc, #164] ; (10006bd4 ) +10006b2e: 60c5 str r5, [r0, #12] +10006b30: 4d29 ldr r5, [pc, #164] ; (10006bd8 ) +10006b32: 6285 str r5, [r0, #40] ; 0x28 +10006b34: 4d29 ldr r5, [pc, #164] ; (10006bdc ) +10006b36: 6145 str r5, [r0, #20] +10006b38: 4d29 ldr r5, [pc, #164] ; (10006be0 ) +10006b3a: 6305 str r5, [r0, #48] ; 0x30 +10006b3c: f100 0554 add.w r5, r0, #84 ; 0x54 +10006b40: 6045 str r5, [r0, #4] +10006b42: f100 057c add.w r5, r0, #124 ; 0x7c +10006b46: 6085 str r5, [r0, #8] +10006b48: f100 0594 add.w r5, r0, #148 ; 0x94 +10006b4c: 6105 str r5, [r0, #16] +10006b4e: f100 05a4 add.w r5, r0, #164 ; 0xa4 +10006b52: 61c5 str r5, [r0, #28] +10006b54: f500 7586 add.w r5, r0, #268 ; 0x10c +10006b58: 6205 str r5, [r0, #32] +10006b5a: f500 759a add.w r5, r0, #308 ; 0x134 +10006b5e: 6245 str r5, [r0, #36] ; 0x24 +10006b60: 62c6 str r6, [r0, #44] ; 0x2c +10006b62: 1d1d adds r5, r3, #4 +10006b64: 6843 ldr r3, [r0, #4] +10006b66: 612b str r3, [r5, #16] +10006b68: 61ae str r6, [r5, #24] +10006b6a: f102 0308 add.w r3, r2, #8 +10006b6e: 6ac0 ldr r0, [r0, #44] ; 0x2c +10006b70: 6002 str r2, [r0, #0] +10006b72: 6043 str r3, [r0, #4] +10006b74: f102 0310 add.w r3, r2, #16 +10006b78: 6083 str r3, [r0, #8] +10006b7a: f102 0318 add.w r3, r2, #24 +10006b7e: 60c3 str r3, [r0, #12] +10006b80: f102 0320 add.w r3, r2, #32 +10006b84: 6103 str r3, [r0, #16] +10006b86: f102 0328 add.w r3, r2, #40 ; 0x28 +10006b8a: 6143 str r3, [r0, #20] +10006b8c: f102 0330 add.w r3, r2, #48 ; 0x30 +10006b90: 6183 str r3, [r0, #24] +10006b92: f102 0338 add.w r3, r2, #56 ; 0x38 +10006b96: 61c3 str r3, [r0, #28] +10006b98: f102 0340 add.w r3, r2, #64 ; 0x40 +10006b9c: 6203 str r3, [r0, #32] +10006b9e: 3248 adds r2, #72 ; 0x48 +10006ba0: 6242 str r2, [r0, #36] ; 0x24 +10006ba2: f001 000f and.w r0, r1, #15 +10006ba6: 7028 strb r0, [r5, #0] +10006ba8: 4628 mov r0, r5 +10006baa: f000 fa19 bl 10006fe0 +10006bae: 2000 movs r0, #0 +10006bb0: 7068 strb r0, [r5, #1] +10006bb2: 70a8 strb r0, [r5, #2] +10006bb4: 2008 movs r0, #8 +10006bb6: 6929 ldr r1, [r5, #16] +10006bb8: 70c8 strb r0, [r1, #3] +10006bba: 6929 ldr r1, [r5, #16] +10006bbc: 71c8 strb r0, [r1, #7] +10006bbe: 4628 mov r0, r5 +10006bc0: e8bd 4062 ldmia.w sp!, {r1, r5, r6, lr} +10006bc4: f000 b928 b.w 10006e18 + +10006bc8 : +10006bc8: 0314 1000 .... + +10006bcc : +10006bcc: fffd fffb .... + +10006bd0 : +10006bd0: 0310 1000 .... + +10006bd4 : +10006bd4: 6c49 1000 Il.. + +10006bd8 : +10006bd8: e00d 1003 .... + +10006bdc : +10006bdc: 6c71 1000 ql.. + +10006be0 : +10006be0: 6cad 1000 .l.. + +10006be4 : +10006be4: b51c push {r2, r3, r4, lr} +10006be6: f000 f811 bl 10006c0c + +10006bea : +10006bea: a900 add r1, sp, #0 +10006bec: eb04 72d4 add.w r2, r4, r4, lsr #31 +10006bf0: 0852 lsrs r2, r2, #1 +10006bf2: f851 1022 ldr.w r1, [r1, r2, lsl #2] +10006bf6: f004 0001 and.w r0, r4, #1 +10006bfa: 0100 lsls r0, r0, #4 +10006bfc: f64f 72ff movw r2, #65535 ; 0xffff +10006c00: 4082 lsls r2, r0 +10006c02: 4011 ands r1, r2 +10006c04: fa21 f000 lsr.w r0, r1, r0 +10006c08: b280 uxth r0, r0 +10006c0a: bd16 pop {r1, r2, r4, pc} + +10006c0c : +10006c0c: a900 add r1, sp, #0 +10006c0e: 2200 movs r2, #0 +10006c10: 2300 movs r3, #0 +10006c12: c10c stmia r1!, {r2, r3} +10006c14: 6800 ldr r0, [r0, #0] +10006c16: f810 4f04 ldrb.w r4, [r0, #4]! +10006c1a: a900 add r1, sp, #0 +10006c1c: f000 b985 b.w 10006f2a + +10006c20 : +10006c20: f8df f000 ldr.w pc, [pc] ; 10006c24 +10006c24: 00000899 .word 0x00000899 + +10006c28 : +10006c28: f8df f000 ldr.w pc, [pc] ; 10006c2c +10006c2c: 0000f465 .word 0x0000f465 + +10006c30 : +10006c30: f8df f000 ldr.w pc, [pc] ; 10006c34 +10006c34: 00004029 .word 0x00004029 + +10006c38 : +10006c38: f8df f000 ldr.w pc, [pc] ; 10006c3c +10006c3c: 000040f1 .word 0x000040f1 + +10006c40 : +10006c40: f8df f000 ldr.w pc, [pc] ; 10006c44 +10006c44: 0000f429 .word 0x0000f429 + +10006c48 : +10006c48: f8df 1354 ldr.w r1, [pc, #852] ; 10006fa0 +10006c4c: 6001 str r1, [r0, #0] +10006c4e: f8df 1354 ldr.w r1, [pc, #852] ; 10006fa4 +10006c52: 6041 str r1, [r0, #4] +10006c54: f8df 1350 ldr.w r1, [pc, #848] ; 10006fa8 +10006c58: 6081 str r1, [r0, #8] +10006c5a: f8df 1350 ldr.w r1, [pc, #848] ; 10006fac +10006c5e: 60c1 str r1, [r0, #12] +10006c60: f8df 134c ldr.w r1, [pc, #844] ; 10006fb0 +10006c64: 6101 str r1, [r0, #16] +10006c66: f8df 134c ldr.w r1, [pc, #844] ; 10006fb4 +10006c6a: 6141 str r1, [r0, #20] +10006c6c: 4770 bx lr + ... + +10006c70 : +10006c70: b510 push {r4, lr} +10006c72: f850 2c04 ldr.w r2, [r0, #-4] +10006c76: 7881 ldrb r1, [r0, #2] +10006c78: 6893 ldr r3, [r2, #8] +10006c7a: b989 cbnz r1, 10006ca0 +10006c7c: f8df 1338 ldr.w r1, [pc, #824] ; 10006fb8 +10006c80: 2201 movs r2, #1 +10006c82: 700a strb r2, [r1, #0] +10006c84: f8df 2334 ldr.w r2, [pc, #820] ; 10006fbc +10006c88: 6814 ldr r4, [r2, #0] +10006c8a: 604c str r4, [r1, #4] +10006c8c: 6812 ldr r2, [r2, #0] +10006c8e: 608a str r2, [r1, #8] +10006c90: 2100 movs r1, #0 +10006c92: 6902 ldr r2, [r0, #16] +10006c94: 61d1 str r1, [r2, #28] +10006c96: e8bd 4010 ldmia.w sp!, {r4, lr} +10006c9a: 6900 ldr r0, [r0, #16] +10006c9c: 6919 ldr r1, [r3, #16] + +10006c9e <__iar_annotation$$tailcall>: +10006c9e: 4708 bx r1 + +10006ca0 : +10006ca0: 6850 ldr r0, [r2, #4] +10006ca2: 695a ldr r2, [r3, #20] +10006ca4: e8bd 4010 ldmia.w sp!, {r4, lr} +10006ca8: 210c movs r1, #12 + +10006caa <__iar_annotation$$tailcall>: +10006caa: 4710 bx r2 + +10006cac : +10006cac: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +10006cb0: 4606 mov r6, r0 +10006cb2: f856 1c04 ldr.w r1, [r6, #-4] +10006cb6: f8d6 8018 ldr.w r8, [r6, #24] +10006cba: 69cc ldr r4, [r1, #28] +10006cbc: 688f ldr r7, [r1, #8] +10006cbe: 6a0d ldr r5, [r1, #32] +10006cc0: 6ca2 ldr r2, [r4, #72] ; 0x48 +10006cc2: 6ce1 ldr r1, [r4, #76] ; 0x4c +10006cc4: 1c52 adds r2, r2, #1 +10006cc6: 4291 cmp r1, r2 +10006cc8: d11d bne.n 10006d06 +10006cca: 6931 ldr r1, [r6, #16] +10006ccc: 2000 movs r0, #0 +10006cce: 61c8 str r0, [r1, #28] +10006cd0: 6939 ldr r1, [r7, #16] +10006cd2: 6930 ldr r0, [r6, #16] +10006cd4: 4788 blx r1 +10006cd6: f8df 02e8 ldr.w r0, [pc, #744] ; 10006fc0 +10006cda: 6800 ldr r0, [r0, #0] +10006cdc: 6931 ldr r1, [r6, #16] +10006cde: 2000 movs r0, #0 +10006ce0: 7048 strb r0, [r1, #1] +10006ce2: 68b9 ldr r1, [r7, #8] +10006ce4: 6930 ldr r0, [r6, #16] +10006ce6: 4788 blx r1 +10006ce8: 6a29 ldr r1, [r5, #32] +10006cea: 4620 mov r0, r4 +10006cec: 4788 blx r1 +10006cee: 6929 ldr r1, [r5, #16] +10006cf0: 4620 mov r0, r4 +10006cf2: 4788 blx r1 +10006cf4: 2002 movs r0, #2 +10006cf6: 70f0 strb r0, [r6, #3] +10006cf8: f8d8 0024 ldr.w r0, [r8, #36] ; 0x24 +10006cfc: 6801 ldr r1, [r0, #0] +10006cfe: 000a movs r2, r1 +10006d00: bf1c itt ne +10006d02: 6840 ldrne r0, [r0, #4] +10006d04: 4788 blxne r1 + +10006d06 : +10006d06: 69e9 ldr r1, [r5, #28] +10006d08: 4620 mov r0, r4 +10006d0a: 4788 blx r1 +10006d0c: 0780 lsls r0, r0, #30 +10006d0e: d502 bpl.n 10006d16 +10006d10: 6ca0 ldr r0, [r4, #72] ; 0x48 +10006d12: 1c40 adds r0, r0, #1 +10006d14: 64a0 str r0, [r4, #72] ; 0x48 + +10006d16 : +10006d16: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +10006d1a : +10006d1a: e92d 46f8 stmdb sp!, {r3, r4, r5, r6, r7, r9, sl, lr} +10006d1e: 4682 mov sl, r0 +10006d20: f85a 7c04 ldr.w r7, [sl, #-4] +10006d24: 6a3d ldr r5, [r7, #32] +10006d26: f8d7 901c ldr.w r9, [r7, #28] +10006d2a: 6a7c ldr r4, [r7, #36] ; 0x24 +10006d2c: 6ab9 ldr r1, [r7, #40] ; 0x28 +10006d2e: 4628 mov r0, r5 +10006d30: 4788 blx r1 +10006d32: 2268 movs r2, #104 ; 0x68 +10006d34: 2100 movs r1, #0 +10006d36: 4648 mov r0, r9 +10006d38: f7fd f97e bl 10004038 +10006d3c: f899 0028 ldrb.w r0, [r9, #40] ; 0x28 +10006d40: f040 0101 orr.w r1, r0, #1 +10006d44: f109 0008 add.w r0, r9, #8 +10006d48: f889 1028 strb.w r1, [r9, #40] ; 0x28 +10006d4c: 2202 movs r2, #2 +10006d4e: 60c2 str r2, [r0, #12] +10006d50: 6082 str r2, [r0, #8] +10006d52: 61c2 str r2, [r0, #28] +10006d54: 6182 str r2, [r0, #24] +10006d56: 6142 str r2, [r0, #20] +10006d58: f041 0120 orr.w r1, r1, #32 +10006d5c: 2200 movs r2, #0 +10006d5e: 6102 str r2, [r0, #16] +10006d60: f889 1028 strb.w r1, [r9, #40] ; 0x28 +10006d64: f109 0660 add.w r6, r9, #96 ; 0x60 +10006d68: 2102 movs r1, #2 +10006d6a: 6041 str r1, [r0, #4] +10006d6c: f109 0028 add.w r0, r9, #40 ; 0x28 +10006d70: 210c movs r1, #12 +10006d72: 7481 strb r1, [r0, #18] +10006d74: 8a81 ldrh r1, [r0, #20] +10006d76: f441 7180 orr.w r1, r1, #256 ; 0x100 +10006d7a: 8281 strh r1, [r0, #20] +10006d7c: 6202 str r2, [r0, #32] +10006d7e: 2101 movs r1, #1 +10006d80: 6241 str r1, [r0, #36] ; 0x24 +10006d82: 2013 movs r0, #19 +10006d84: 7130 strb r0, [r6, #4] +10006d86: 78f0 ldrb r0, [r6, #3] +10006d88: f040 0003 orr.w r0, r0, #3 +10006d8c: 70f0 strb r0, [r6, #3] +10006d8e: 2004 movs r0, #4 +10006d90: 7070 strb r0, [r6, #1] +10006d92: f241 0010 movw r0, #4112 ; 0x1010 +10006d96: f8c9 0008 str.w r0, [r9, #8] +10006d9a: 2003 movs r0, #3 +10006d9c: f889 0060 strb.w r0, [r9, #96] ; 0x60 +10006da0: 488a ldr r0, [pc, #552] ; (10006fcc ) +10006da2: 6800 ldr r0, [r0, #0] +10006da4: 0340 lsls r0, r0, #13 +10006da6: d505 bpl.n 10006db4 +10006da8: f89a 1000 ldrb.w r1, [sl] +10006dac: f20f 2094 addw r0, pc, #660 ; 0x294 +10006db0: f7fd f946 bl 10004040 + +10006db4 : +10006db4: 2001 movs r0, #1 +10006db6: 70b0 strb r0, [r6, #2] +10006db8: 201e movs r0, #30 +10006dba: 6060 str r0, [r4, #4] +10006dbc: f8c4 a008 str.w sl, [r4, #8] +10006dc0: 6b38 ldr r0, [r7, #48] ; 0x30 +10006dc2: 6020 str r0, [r4, #0] +10006dc4: 2002 movs r0, #2 +10006dc6: 60e0 str r0, [r4, #12] +10006dc8: 4620 mov r0, r4 +10006dca: f7ff ff31 bl 10006c30 +10006dce: 4620 mov r0, r4 +10006dd0: f7ff ff32 bl 10006c38 +10006dd4: 78b1 ldrb r1, [r6, #2] +10006dd6: 487e ldr r0, [pc, #504] ; (10006fd0 ) +10006dd8: 2900 cmp r1, #0 +10006dda: 6a01 ldr r1, [r0, #32] +10006ddc: d10a bne.n 10006df4 +10006dde: f441 3180 orr.w r1, r1, #65536 ; 0x10000 +10006de2: 6201 str r1, [r0, #32] +10006de4: 6a01 ldr r1, [r0, #32] +10006de6: f441 3100 orr.w r1, r1, #131072 ; 0x20000 +10006dea: 6201 str r1, [r0, #32] +10006dec: 6801 ldr r1, [r0, #0] +10006dee: f441 5100 orr.w r1, r1, #8192 ; 0x2000 +10006df2: e009 b.n 10006e08 + +10006df4 : +10006df4: f441 2180 orr.w r1, r1, #262144 ; 0x40000 +10006df8: 6201 str r1, [r0, #32] +10006dfa: 6a01 ldr r1, [r0, #32] +10006dfc: f441 2100 orr.w r1, r1, #524288 ; 0x80000 +10006e00: 6201 str r1, [r0, #32] +10006e02: 6801 ldr r1, [r0, #0] +10006e04: f441 4180 orr.w r1, r1, #16384 ; 0x4000 + +10006e08 : +10006e08: 6001 str r1, [r0, #0] +10006e0a: 4648 mov r0, r9 +10006e0c: 6829 ldr r1, [r5, #0] +10006e0e: 4788 blx r1 +10006e10: 69a9 ldr r1, [r5, #24] +10006e12: 4648 mov r0, r9 +10006e14: 4788 blx r1 +10006e16: e085 b.n 10006f24 + +10006e18 : +10006e18: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +10006e1c: 4a6b ldr r2, [pc, #428] ; (10006fcc ) +10006e1e: 6812 ldr r2, [r2, #0] +10006e20: 4604 mov r4, r0 +10006e22: 0352 lsls r2, r2, #13 +10006e24: d505 bpl.n 10006e32 +10006e26: f20f 2140 addw r1, pc, #576 ; 0x240 +10006e2a: f20f 2048 addw r0, pc, #584 ; 0x248 +10006e2e: f7fd f907 bl 10004040 + +10006e32 : +10006e32: f854 7c04 ldr.w r7, [r4, #-4] +10006e36: 4e67 ldr r6, [pc, #412] ; (10006fd4 ) +10006e38: f8d7 8004 ldr.w r8, [r7, #4] +10006e3c: f8d7 9008 ldr.w r9, [r7, #8] +10006e40: 7830 ldrb r0, [r6, #0] +10006e42: 1ca5 adds r5, r4, #2 +10006e44: b1a0 cbz r0, 10006e70 +10006e46: 2228 movs r2, #40 ; 0x28 +10006e48: 1d31 adds r1, r6, #4 +10006e4a: 4640 mov r0, r8 +10006e4c: f7ff fef8 bl 10006c40 +10006e50: 2800 cmp r0, #0 +10006e52: d062 beq.n 10006f1a +10006e54: 68f9 ldr r1, [r7, #12] +10006e56: 4648 mov r0, r9 +10006e58: 4788 blx r1 +10006e5a: 2002 movs r0, #2 +10006e5c: 7068 strb r0, [r5, #1] +10006e5e: 485e ldr r0, [pc, #376] ; (10006fd8 ) +10006e60: 6800 ldr r0, [r0, #0] +10006e62: 0040 lsls r0, r0, #1 +10006e64: d559 bpl.n 10006f1a +10006e66: f20f 201c addw r0, pc, #540 ; 0x21c +10006e6a: f7fd f8e9 bl 10004040 +10006e6e: e054 b.n 10006f1a + +10006e70 : +10006e70: 68f9 ldr r1, [r7, #12] +10006e72: 4648 mov r0, r9 +10006e74: 4788 blx r1 +10006e76: f854 0c04 ldr.w r0, [r4, #-4] +10006e7a: 6907 ldr r7, [r0, #16] +10006e7c: 60bc str r4, [r7, #8] +10006e7e: 2159 movs r1, #89 ; 0x59 +10006e80: 6079 str r1, [r7, #4] +10006e82: 6940 ldr r0, [r0, #20] +10006e84: 6038 str r0, [r7, #0] +10006e86: 2005 movs r0, #5 +10006e88: 60f8 str r0, [r7, #12] +10006e8a: 4638 mov r0, r7 +10006e8c: f7ff fed0 bl 10006c30 +10006e90: 4638 mov r0, r7 +10006e92: f7ff fed1 bl 10006c38 +10006e96: 4620 mov r0, r4 +10006e98: f7ff ff3f bl 10006d1a +10006e9c: 484a ldr r0, [pc, #296] ; (10006fc8 ) +10006e9e: 6801 ldr r1, [r0, #0] +10006ea0: f041 7100 orr.w r1, r1, #33554432 ; 0x2000000 +10006ea4: 6001 str r1, [r0, #0] +10006ea6: 4847 ldr r0, [pc, #284] ; (10006fc4 ) +10006ea8: 69c1 ldr r1, [r0, #28] +10006eaa: f041 7180 orr.w r1, r1, #16777216 ; 0x1000000 +10006eae: 61c1 str r1, [r0, #28] +10006eb0: 6801 ldr r1, [r0, #0] +10006eb2: f041 0101 orr.w r1, r1, #1 +10006eb6: 6001 str r1, [r0, #0] +10006eb8: 6920 ldr r0, [r4, #16] +10006eba: f8d9 1000 ldr.w r1, [r9] +10006ebe: 4788 blx r1 +10006ec0: 78a0 ldrb r0, [r4, #2] +10006ec2: 6921 ldr r1, [r4, #16] +10006ec4: 2801 cmp r0, #1 +10006ec6: bf08 it eq +10006ec8: 2060 moveq r0, #96 ; 0x60 +10006eca: d003 beq.n 10006ed4 +10006ecc: 2802 cmp r0, #2 +10006ece: bf0c ite eq +10006ed0: 2070 moveq r0, #112 ; 0x70 +10006ed2: 2000 movne r0, #0 + +10006ed4 : +10006ed4: 61c8 str r0, [r1, #28] +10006ed6: f898 0005 ldrb.w r0, [r8, #5] +10006eda: 2801 cmp r0, #1 +10006edc: d104 bne.n 10006ee8 +10006ede: 6920 ldr r0, [r4, #16] +10006ee0: 69c1 ldr r1, [r0, #28] +10006ee2: f041 0180 orr.w r1, r1, #128 ; 0x80 +10006ee6: 61c1 str r1, [r0, #28] + +10006ee8 : +10006ee8: 6920 ldr r0, [r4, #16] +10006eea: f8d9 1010 ldr.w r1, [r9, #16] +10006eee: 4788 blx r1 +10006ef0: f898 0005 ldrb.w r0, [r8, #5] +10006ef4: 2801 cmp r0, #1 +10006ef6: d104 bne.n 10006f02 +10006ef8: 4838 ldr r0, [pc, #224] ; (10006fdc ) +10006efa: 211e movs r1, #30 +10006efc: 6001 str r1, [r0, #0] +10006efe: 2103 movs r1, #3 +10006f00: 6081 str r1, [r0, #8] + +10006f02 : +10006f02: 2101 movs r1, #1 +10006f04: f994 2000 ldrsb.w r2, [r4] +10006f08: 7830 ldrb r0, [r6, #0] +10006f0a: 4091 lsls r1, r2 +10006f0c: 4308 orrs r0, r1 +10006f0e: 7030 strb r0, [r6, #0] +10006f10: 2228 movs r2, #40 ; 0x28 +10006f12: 6921 ldr r1, [r4, #16] +10006f14: 1d30 adds r0, r6, #4 +10006f16: f7ff fe87 bl 10006c28 + +10006f1a : +10006f1a: 2002 movs r0, #2 +10006f1c: 7068 strb r0, [r5, #1] +10006f1e: 2000 movs r0, #0 +10006f20: e8bd 83f2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, pc} + +10006f24 : +10006f24: 2000 movs r0, #0 +10006f26: e8bd 86f2 ldmia.w sp!, {r1, r4, r5, r6, r7, r9, sl, pc} + +10006f2a : +10006f2a: e92d 42f0 stmdb sp!, {r4, r5, r6, r7, r9, lr} +10006f2e: 4605 mov r5, r0 +10006f30: 4f23 ldr r7, [pc, #140] ; (10006fc0 ) +10006f32: f855 0c04 ldr.w r0, [r5, #-4] +10006f36: 4c20 ldr r4, [pc, #128] ; (10006fb8 ) +10006f38: 6886 ldr r6, [r0, #8] +10006f3a: 6838 ldr r0, [r7, #0] +10006f3c: 2000 movs r0, #0 +10006f3e: 7020 strb r0, [r4, #0] +10006f40: 4689 mov r9, r1 +10006f42: f44f 60fa mov.w r0, #2000 ; 0x7d0 +10006f46: f7ff fe6b bl 10006c20 +10006f4a: 6929 ldr r1, [r5, #16] +10006f4c: 2010 movs r0, #16 +10006f4e: 61c8 str r0, [r1, #28] +10006f50: 6931 ldr r1, [r6, #16] +10006f52: 6928 ldr r0, [r5, #16] +10006f54: 4788 blx r1 +10006f56: 2002 movs r0, #2 +10006f58: 70e8 strb r0, [r5, #3] +10006f5a: 2001 movs r0, #1 +10006f5c: 6929 ldr r1, [r5, #16] +10006f5e: 7048 strb r0, [r1, #1] +10006f60: 68b1 ldr r1, [r6, #8] +10006f62: 6928 ldr r0, [r5, #16] +10006f64: 4788 blx r1 + +10006f66 : +10006f66: 6938 ldr r0, [r7, #16] +10006f68: 0500 lsls r0, r0, #20 +10006f6a: d5fc bpl.n 10006f66 + +10006f6c : +10006f6c: 7820 ldrb r0, [r4, #0] +10006f6e: 2800 cmp r0, #0 +10006f70: d0fc beq.n 10006f6c +10006f72: 6929 ldr r1, [r5, #16] +10006f74: 2000 movs r0, #0 +10006f76: 7048 strb r0, [r1, #1] +10006f78: 68b1 ldr r1, [r6, #8] +10006f7a: 6928 ldr r0, [r5, #16] +10006f7c: 4788 blx r1 + +10006f7e : +10006f7e: 6938 ldr r0, [r7, #16] +10006f80: 0500 lsls r0, r0, #20 +10006f82: d4fc bmi.n 10006f7e +10006f84: 6838 ldr r0, [r7, #0] +10006f86: 2000 movs r0, #0 +10006f88: 7020 strb r0, [r4, #0] +10006f8a: 6860 ldr r0, [r4, #4] +10006f8c: f8c9 0000 str.w r0, [r9] +10006f90: 68a0 ldr r0, [r4, #8] +10006f92: f8c9 0004 str.w r0, [r9, #4] +10006f96: 2000 movs r0, #0 +10006f98: 6060 str r0, [r4, #4] +10006f9a: 60a0 str r0, [r4, #8] +10006f9c: e8bd 82f0 ldmia.w sp!, {r4, r5, r6, r7, r9, pc} + +10006fa0 : +10006fa0: f705 1003 .... + +10006fa4 : +10006fa4: f8cd 1003 .... + +10006fa8 : +10006fa8: f8db 1003 .... + +10006fac : +10006fac: f8f7 1003 .... + +10006fb0 : +10006fb0: f8ed 1003 .... + +10006fb4 : +10006fb4: f8fd 1003 .... + +10006fb8 : +10006fb8: 73a4 1004 .s.. + +10006fbc : +10006fbc: 0000 4001 ...@ + +10006fc0 : +10006fc0: 000c 4001 ...@ + +10006fc4 : +10006fc4: 021c 4000 ...@ + +10006fc8 : +10006fc8: 0078 4000 x..@ + +10006fcc : +10006fcc: 0310 1000 .... + +10006fd0 : +10006fd0: 0210 4000 ...@ + +10006fd4 : +10006fd4: 73b0 1004 .s.. + +10006fd8 : +10006fd8: 0314 1000 .... + +10006fdc : +10006fdc: 2014 4000 . .@ + +10006fe0 : +10006fe0: 2100 movs r1, #0 +10006fe2: 7041 strb r1, [r0, #1] +10006fe4: 7081 strb r1, [r0, #2] +10006fe6: 70c1 strb r1, [r0, #3] +10006fe8: 6041 str r1, [r0, #4] +10006fea: 6081 str r1, [r0, #8] +10006fec: 6902 ldr r2, [r0, #16] +10006fee: 7801 ldrb r1, [r0, #0] +10006ff0: 7011 strb r1, [r2, #0] +10006ff2: 2100 movs r1, #0 +10006ff4: 6902 ldr r2, [r0, #16] +10006ff6: 7051 strb r1, [r2, #1] +10006ff8: 6902 ldr r2, [r0, #16] +10006ffa: 7091 strb r1, [r2, #2] +10006ffc: 2108 movs r1, #8 +10006ffe: 6902 ldr r2, [r0, #16] +10007000: 70d1 strb r1, [r2, #3] +10007002: 2100 movs r1, #0 +10007004: 6902 ldr r2, [r0, #16] +10007006: 7111 strb r1, [r2, #4] +10007008: 6902 ldr r2, [r0, #16] +1000700a: 7151 strb r1, [r2, #5] +1000700c: 6902 ldr r2, [r0, #16] +1000700e: 7191 strb r1, [r2, #6] +10007010: 2108 movs r1, #8 +10007012: 6902 ldr r2, [r0, #16] +10007014: 71d1 strb r1, [r2, #7] +10007016: 2100 movs r1, #0 +10007018: 6902 ldr r2, [r0, #16] +1000701a: 8111 strh r1, [r2, #8] +1000701c: 2108 movs r1, #8 +1000701e: 6902 ldr r2, [r0, #16] +10007020: 8151 strh r1, [r2, #10] +10007022: 2100 movs r1, #0 +10007024: 6902 ldr r2, [r0, #16] +10007026: 7311 strb r1, [r2, #12] +10007028: 6902 ldr r2, [r0, #16] +1000702a: 7351 strb r1, [r2, #13] +1000702c: 6902 ldr r2, [r0, #16] +1000702e: 7391 strb r1, [r2, #14] +10007030: 6902 ldr r2, [r0, #16] +10007032: 73d1 strb r1, [r2, #15] +10007034: 6902 ldr r2, [r0, #16] +10007036: 6191 str r1, [r2, #24] +10007038: 6902 ldr r2, [r0, #16] +1000703a: 61d1 str r1, [r2, #28] +1000703c: 6900 ldr r0, [r0, #16] +1000703e: 6201 str r1, [r0, #32] +10007040: 2000 movs r0, #0 +10007042: 4770 bx lr + +10007044 : +10007044: 5b0d 4441 2043 4920 666e 705d 6153 416c .[ADC Inf]pSalA +10007054: 4344 4e48 2d44 443e 7665 754e 3a6d 7825 DCHND->DevNum:%x +10007064: 000a 0000 .... + +10007068 : +10007068: 7452 416b 4344 6e49 7469 0000 RtkADCInit.. + +10007074 : +10007074: 5b0d 4441 2043 4920 666e 255d 0a73 0000 .[ADC Inf]%s... + +10007084 : +10007084: 540d 6568 4420 4341 6920 696e 6974 6c61 .The DAC initial +10007094: 7620 6c61 6575 6920 2073 6964 6666 7265 value is differ +100070a4: 6e65 2074 7266 6d6f 7420 6568 7020 6572 ent from the pre +100070b4: 6976 756f 2073 6176 756c 2e65 000a 0000 vious value..... + +100070c4 : +100070c4: b530 push {r4, r5, lr} +100070c6: 460c mov r4, r1 +100070c8: b087 sub sp, #28 +100070ca: 4611 mov r1, r2 +100070cc: f000 fc2d bl 1000792a +100070d0: 0005 movs r5, r0 +100070d2: d022 beq.n 1000711a +100070d4: f8df 042c ldr.w r0, [pc, #1068] ; 10007504 +100070d8: 9000 str r0, [sp, #0] +100070da: f88d 400c strb.w r4, [sp, #12] +100070de: 9501 str r5, [sp, #4] +100070e0: f000 f9b5 bl 1000744e + +100070e4 : +100070e4: b1c8 cbz r0, 1000711a +100070e6: f105 0010 add.w r0, r5, #16 +100070ea: f001 f889 bl 10008200 +100070ee: f105 0014 add.w r0, r5, #20 +100070f2: f001 f841 bl 10008178 +100070f6: f105 0018 add.w r0, r5, #24 +100070fa: f001 f83d bl 10008178 +100070fe: f105 0010 add.w r0, r5, #16 +10007102: f001 f87a bl 100081fa +10007106: f105 0014 add.w r0, r5, #20 +1000710a: f000 ffdf bl 100080cc +1000710e: 4629 mov r1, r5 +10007110: 2008 movs r0, #8 +10007112: f001 f8f9 bl 10008308 +10007116: 2000 movs r0, #0 +10007118: e000 b.n 1000711c + +1000711a : +1000711a: 4628 mov r0, r5 + +1000711c : +1000711c: b007 add sp, #28 +1000711e: bd30 pop {r4, r5, pc} + +10007120 : +10007120: b510 push {r4, lr} +10007122: b086 sub sp, #24 +10007124: 0004 movs r4, r0 +10007126: d008 beq.n 1000713a +10007128: f8df 03dc ldr.w r0, [pc, #988] ; 10007508 +1000712c: 9000 str r0, [sp, #0] +1000712e: 9401 str r4, [sp, #4] +10007130: f000 f98d bl 1000744e + +10007134 : +10007134: 4620 mov r0, r4 +10007136: f000 fc3f bl 100079b8 + +1000713a : +1000713a: 2000 movs r0, #0 +1000713c: b006 add sp, #24 +1000713e: bd10 pop {r4, pc} + +10007140 : +10007140: b530 push {r4, r5, lr} +10007142: b087 sub sp, #28 +10007144: 0004 movs r4, r0 +10007146: bf18 it ne +10007148: 2900 cmpne r1, #0 +1000714a: d000 beq.n 1000714e +1000714c: b912 cbnz r2, 10007154 + +1000714e : +1000714e: f06f 000d mvn.w r0, #13 +10007152: e012 b.n 1000717a + +10007154 : +10007154: f8df 03b4 ldr.w r0, [pc, #948] ; 1000750c +10007158: 9000 str r0, [sp, #0] +1000715a: 9401 str r4, [sp, #4] +1000715c: 9103 str r1, [sp, #12] +1000715e: 9204 str r2, [sp, #16] +10007160: f88d 3014 strb.w r3, [sp, #20] +10007164: f000 f973 bl 1000744e + +10007168 : +10007168: f000 f835 bl 100071d6 + +1000716c : +1000716c: f000 f84d bl 1000720a + +10007170 : +10007170: bfa8 it ge +10007172: 7325 strbge r5, [r4, #12] +10007174: f001 f88d bl 10008292 +10007178: 4628 mov r0, r5 + +1000717a : +1000717a: b007 add sp, #28 +1000717c: bd30 pop {r4, r5, pc} + +1000717e : +1000717e: b530 push {r4, r5, lr} +10007180: b087 sub sp, #28 +10007182: 0004 movs r4, r0 +10007184: bf08 it eq +10007186: f06f 000d mvneq.w r0, #13 +1000718a: d00c beq.n 100071a6 +1000718c: f8df 0380 ldr.w r0, [pc, #896] ; 10007510 +10007190: f000 f958 bl 10007444 + +10007194 : +10007194: f000 f81f bl 100071d6 + +10007198 : +10007198: f000 f837 bl 1000720a + +1000719c : +1000719c: bfa8 it ge +1000719e: 7325 strbge r5, [r4, #12] +100071a0: f001 f877 bl 10008292 +100071a4: 4628 mov r0, r5 + +100071a6 : +100071a6: b007 add sp, #28 +100071a8: bd30 pop {r4, r5, pc} + +100071aa : +100071aa: b530 push {r4, r5, lr} +100071ac: b087 sub sp, #28 +100071ae: 0004 movs r4, r0 +100071b0: bf08 it eq +100071b2: f06f 000d mvneq.w r0, #13 +100071b6: d00c beq.n 100071d2 +100071b8: f8df 0358 ldr.w r0, [pc, #856] ; 10007514 +100071bc: f000 f942 bl 10007444 + +100071c0 : +100071c0: f000 f809 bl 100071d6 + +100071c4 : +100071c4: f000 f821 bl 1000720a + +100071c8 : +100071c8: bfa8 it ge +100071ca: 7325 strbge r5, [r4, #12] +100071cc: f001 f861 bl 10008292 +100071d0: 4628 mov r0, r5 + +100071d2 : +100071d2: b007 add sp, #28 +100071d4: bd30 pop {r4, r5, pc} + +100071d6 : +100071d6: 4605 mov r5, r0 +100071d8: f001 b856 b.w 10008288 + +100071dc : +100071dc: b530 push {r4, r5, lr} +100071de: b087 sub sp, #28 +100071e0: 0004 movs r4, r0 +100071e2: bf08 it eq +100071e4: f06f 000d mvneq.w r0, #13 +100071e8: d00d beq.n 10007206 +100071ea: 48cb ldr r0, [pc, #812] ; (10007518 ) +100071ec: 9000 str r0, [sp, #0] +100071ee: 9401 str r4, [sp, #4] +100071f0: f000 f92d bl 1000744e + +100071f4 : +100071f4: f7ff ffef bl 100071d6 + +100071f8 : +100071f8: f000 f807 bl 1000720a + +100071fc : +100071fc: bfa8 it ge +100071fe: 7325 strbge r5, [r4, #12] +10007200: f001 f847 bl 10008292 +10007204: 4628 mov r0, r5 + +10007206 : +10007206: b007 add sp, #28 +10007208: bd30 pop {r4, r5, pc} + +1000720a : +1000720a: f994 100c ldrsb.w r1, [r4, #12] +1000720e: f111 0f09 cmn.w r1, #9 +10007212: 4770 bx lr + +10007214 : +10007214: b570 push {r4, r5, r6, lr} +10007216: b082 sub sp, #8 +10007218: 4604 mov r4, r0 +1000721a: 000e movs r6, r1 +1000721c: bf1e ittt ne +1000721e: 2000 movne r0, #0 +10007220: 6030 strne r0, [r6, #0] +10007222: 2c00 cmpne r4, #0 +10007224: d004 beq.n 10007230 +10007226: f104 0018 add.w r0, r4, #24 +1000722a: f000 ffa5 bl 10008178 +1000722e: b900 cbnz r0, 10007232 + +10007230 : +10007230: e0d9 b.n 100073e6 + +10007232 : +10007232: f994 000c ldrsb.w r0, [r4, #12] +10007236: f06f 0508 mvn.w r5, #8 +1000723a: 42a8 cmp r0, r5 +1000723c: db23 blt.n 10007286 +1000723e: 6a22 ldr r2, [r4, #32] +10007240: a900 add r1, sp, #0 +10007242: f104 0018 add.w r0, r4, #24 +10007246: f000 ff61 bl 1000810c +1000724a: f110 0f01 cmn.w r0, #1 +1000724e: d104 bne.n 1000725a +10007250: f001 f81a bl 10008288 +10007254: f06f 0602 mvn.w r6, #2 +10007258: e00a b.n 10007270 + +1000725a : +1000725a: 6b23 ldr r3, [r4, #48] ; 0x30 +1000725c: 0018 movs r0, r3 +1000725e: d001 beq.n 10007264 +10007260: f000 f812 bl 10007288 + +10007264 : +10007264: 9800 ldr r0, [sp, #0] +10007266: b960 cbnz r0, 10007282 +10007268: f001 f80e bl 10008288 +1000726c: f06f 0609 mvn.w r6, #9 + +10007270 : +10007270: f994 100c ldrsb.w r1, [r4, #12] +10007274: 42a9 cmp r1, r5 +10007276: bfa8 it ge +10007278: 7326 strbge r6, [r4, #12] +1000727a: f001 f80a bl 10008292 +1000727e: 4630 mov r0, r6 +10007280: bd76 pop {r1, r2, r4, r5, r6, pc} + +10007282 : +10007282: 6030 str r0, [r6, #0] +10007284: 2000 movs r0, #0 + +10007286 : +10007286: bd76 pop {r1, r2, r4, r5, r6, pc} + +10007288 : +10007288: 2200 movs r2, #0 + +1000728a : +1000728a: 2101 movs r1, #1 +1000728c: 4620 mov r0, r4 + +1000728e <__iar_annotation$$tailcall>: +1000728e: 4718 bx r3 + +10007290 : +10007290: b570 push {r4, r5, r6, lr} +10007292: b088 sub sp, #32 +10007294: 4604 mov r4, r0 +10007296: 460e mov r6, r1 +10007298: 2000 movs r0, #0 +1000729a: 9000 str r0, [sp, #0] +1000729c: 2e00 cmp r6, #0 +1000729e: bf1a itte ne +100072a0: 6030 strne r0, [r6, #0] +100072a2: 2c00 cmpne r4, #0 +100072a4: f06f 000d mvneq.w r0, #13 +100072a8: d050 beq.n 1000734c +100072aa: f104 0014 add.w r0, r4, #20 +100072ae: f000 ff63 bl 10008178 +100072b2: b910 cbnz r0, 100072ba +100072b4: f06f 000c mvn.w r0, #12 +100072b8: e048 b.n 1000734c + +100072ba : +100072ba: f994 000c ldrsb.w r0, [r4, #12] +100072be: f06f 0508 mvn.w r5, #8 +100072c2: 42a8 cmp r0, r5 +100072c4: db42 blt.n 1000734c +100072c6: 6a22 ldr r2, [r4, #32] +100072c8: a900 add r1, sp, #0 +100072ca: f104 0014 add.w r0, r4, #20 +100072ce: f000 ff1d bl 1000810c +100072d2: f110 0f01 cmn.w r0, #1 +100072d6: d104 bne.n 100072e2 +100072d8: f000 ffd6 bl 10008288 +100072dc: f06f 0602 mvn.w r6, #2 +100072e0: e020 b.n 10007324 + +100072e2 : +100072e2: 6820 ldr r0, [r4, #0] +100072e4: 2810 cmp r0, #16 +100072e6: d126 bne.n 10007336 +100072e8: f894 0024 ldrb.w r0, [r4, #36] ; 0x24 +100072ec: 0700 lsls r0, r0, #28 +100072ee: d501 bpl.n 100072f4 +100072f0: 9800 ldr r0, [sp, #0] +100072f2: b960 cbnz r0, 1000730e + +100072f4 : +100072f4: 4889 ldr r0, [pc, #548] ; (1000751c ) +100072f6: 9001 str r0, [sp, #4] +100072f8: 9402 str r4, [sp, #8] +100072fa: 9800 ldr r0, [sp, #0] +100072fc: 2800 cmp r0, #0 +100072fe: bf1a itte ne +10007300: 9800 ldrne r0, [sp, #0] +10007302: 8900 ldrhne r0, [r0, #8] +10007304: 2001 moveq r0, #1 +10007306: 9004 str r0, [sp, #16] +10007308: a801 add r0, sp, #4 +1000730a: f001 f8eb bl 100084e4 + +1000730e : +1000730e: 9800 ldr r0, [sp, #0] +10007310: b998 cbnz r0, 1000733a +10007312: 6b23 ldr r3, [r4, #48] ; 0x30 +10007314: 0018 movs r0, r3 +10007316: d001 beq.n 1000731c +10007318: f7ff ffb6 bl 10007288 + +1000731c : +1000731c: f000 ffb4 bl 10008288 +10007320: f06f 060b mvn.w r6, #11 + +10007324 : +10007324: f994 100c ldrsb.w r1, [r4, #12] +10007328: 42a9 cmp r1, r5 +1000732a: bfa8 it ge +1000732c: 7326 strbge r6, [r4, #12] +1000732e: f000 ffb0 bl 10008292 +10007332: 4630 mov r0, r6 +10007334: e00a b.n 1000734c + +10007336 : +10007336: 9800 ldr r0, [sp, #0] +10007338: 6800 ldr r0, [r0, #0] + +1000733a : +1000733a: 6b23 ldr r3, [r4, #48] ; 0x30 +1000733c: 8902 ldrh r2, [r0, #8] +1000733e: 0018 movs r0, r3 +10007340: d001 beq.n 10007346 +10007342: f7ff ffa2 bl 1000728a + +10007346 : +10007346: 9800 ldr r0, [sp, #0] +10007348: 6030 str r0, [r6, #0] +1000734a: 2000 movs r0, #0 + +1000734c : +1000734c: b008 add sp, #32 +1000734e: bd70 pop {r4, r5, r6, pc} + +10007350 : +10007350: b110 cbz r0, 10007358 +10007352: 6802 ldr r2, [r0, #0] +10007354: 2a10 cmp r2, #16 +10007356: d002 beq.n 1000735e + +10007358 : +10007358: f06f 000d mvn.w r0, #13 +1000735c: 4770 bx lr + +1000735e : +1000735e: e797 b.n 10007290 + +10007360 : +10007360: b570 push {r4, r5, r6, lr} +10007362: b082 sub sp, #8 +10007364: 4604 mov r4, r0 +10007366: 000d movs r5, r1 +10007368: bf1e ittt ne +1000736a: 2000 movne r0, #0 +1000736c: 6028 strne r0, [r5, #0] +1000736e: 2c00 cmpne r4, #0 +10007370: d100 bne.n 10007374 +10007372: e038 b.n 100073e6 + +10007374 : +10007374: f104 0014 add.w r0, r4, #20 +10007378: f000 fefe bl 10008178 +1000737c: b910 cbnz r0, 10007384 +1000737e: f06f 000c mvn.w r0, #12 +10007382: bd76 pop {r1, r2, r4, r5, r6, pc} + +10007384 : +10007384: 6820 ldr r0, [r4, #0] +10007386: 2810 cmp r0, #16 +10007388: d128 bne.n 100073dc +1000738a: 2000 movs r0, #0 +1000738c: 9000 str r0, [sp, #0] +1000738e: 2007 movs r0, #7 +10007390: f000 ffa7 bl 100082e2 +10007394: 0006 movs r6, r0 +10007396: d10c bne.n 100073b2 +10007398: f000 ff76 bl 10008288 +1000739c: f7ff ff35 bl 1000720a + +100073a0 : +100073a0: bfa4 itt ge +100073a2: f04f 31ff movge.w r1, #4294967295 +100073a6: 7321 strbge r1, [r4, #12] +100073a8: f000 ff73 bl 10008292 +100073ac: f04f 30ff mov.w r0, #4294967295 +100073b0: bd76 pop {r1, r2, r4, r5, r6, pc} + +100073b2 : +100073b2: a900 add r1, sp, #0 +100073b4: 4620 mov r0, r4 +100073b6: f7ff ff6b bl 10007290 +100073ba: 0004 movs r4, r0 +100073bc: d005 beq.n 100073ca +100073be: 4631 mov r1, r6 +100073c0: 2007 movs r0, #7 +100073c2: f000 ffa1 bl 10008308 +100073c6: 4620 mov r0, r4 +100073c8: bd76 pop {r1, r2, r4, r5, r6, pc} + +100073ca : +100073ca: 9800 ldr r0, [sp, #0] +100073cc: 6030 str r0, [r6, #0] +100073ce: 9800 ldr r0, [sp, #0] +100073d0: 6070 str r0, [r6, #4] +100073d2: 2000 movs r0, #0 +100073d4: 81b0 strh r0, [r6, #12] +100073d6: 60b0 str r0, [r6, #8] +100073d8: 602e str r6, [r5, #0] +100073da: bd76 pop {r1, r2, r4, r5, r6, pc} + +100073dc : +100073dc: 4629 mov r1, r5 +100073de: 4620 mov r0, r4 +100073e0: f7ff ff56 bl 10007290 +100073e4: bd76 pop {r1, r2, r4, r5, r6, pc} + +100073e6 : +100073e6: f06f 000d mvn.w r0, #13 +100073ea: bd76 pop {r1, r2, r4, r5, r6, pc} + +100073ec : +100073ec: b900 cbnz r0, 100073f0 +100073ee: 4770 bx lr + +100073f0 : +100073f0: b500 push {lr} +100073f2: b087 sub sp, #28 +100073f4: 6802 ldr r2, [r0, #0] +100073f6: 2a10 cmp r2, #16 +100073f8: d10a bne.n 10007410 +100073fa: f890 2024 ldrb.w r2, [r0, #36] ; 0x24 +100073fe: 0712 lsls r2, r2, #28 +10007400: d506 bpl.n 10007410 +10007402: 9001 str r0, [sp, #4] +10007404: 9103 str r1, [sp, #12] +10007406: a800 add r0, sp, #0 +10007408: 4a44 ldr r2, [pc, #272] ; (1000751c ) +1000740a: 9200 str r2, [sp, #0] +1000740c: f001 f86a bl 100084e4 + +10007410 : +10007410: b007 add sp, #28 +10007412: bd00 pop {pc} + +10007414 : +10007414: b530 push {r4, r5, lr} +10007416: b087 sub sp, #28 +10007418: 0004 movs r4, r0 +1000741a: bf08 it eq +1000741c: f06f 000d mvneq.w r0, #13 +10007420: d00e beq.n 10007440 +10007422: 483f ldr r0, [pc, #252] ; (10007520 ) +10007424: 9000 str r0, [sp, #0] +10007426: 9401 str r4, [sp, #4] +10007428: 9103 str r1, [sp, #12] +1000742a: f000 f810 bl 1000744e + +1000742e : +1000742e: f7ff fed2 bl 100071d6 + +10007432 : +10007432: f7ff feea bl 1000720a + +10007436 : +10007436: bfa8 it ge +10007438: 7325 strbge r5, [r4, #12] +1000743a: f000 ff2a bl 10008292 +1000743e: 4628 mov r0, r5 + +10007440 : +10007440: b007 add sp, #28 +10007442: bd30 pop {r4, r5, pc} + +10007444 : +10007444: 9000 str r0, [sp, #0] +10007446: 9401 str r4, [sp, #4] +10007448: 9103 str r1, [sp, #12] +1000744a: f8ad 2010 strh.w r2, [sp, #16] + +1000744e : +1000744e: a800 add r0, sp, #0 +10007450: f001 b848 b.w 100084e4 + +10007454 : +10007454: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +10007458: b086 sub sp, #24 +1000745a: 0004 movs r4, r0 +1000745c: 4615 mov r5, r2 +1000745e: bf08 it eq +10007460: f06f 000d mvneq.w r0, #13 +10007464: d031 beq.n 100074ca +10007466: 6820 ldr r0, [r4, #0] +10007468: 2810 cmp r0, #16 +1000746a: d10f bne.n 1000748c +1000746c: b90d cbnz r5, 10007472 +1000746e: 2000 movs r0, #0 +10007470: e02b b.n 100074ca + +10007472 : +10007472: f894 0024 ldrb.w r0, [r4, #36] ; 0x24 +10007476: 0840 lsrs r0, r0, #1 +10007478: 089a lsrs r2, r3, #2 +1000747a: f000 0001 and.w r0, r0, #1 +1000747e: f002 0201 and.w r2, r2, #1 +10007482: 9e0c ldr r6, [sp, #48] ; 0x30 +10007484: ea52 0700 orrs.w r7, r2, r0 +10007488: d003 beq.n 10007492 +1000748a: b916 cbnz r6, 10007492 + +1000748c : +1000748c: f06f 0005 mvn.w r0, #5 +10007490: e01b b.n 100074ca + +10007492 : +10007492: 4824 ldr r0, [pc, #144] ; (10007524 ) +10007494: 9000 str r0, [sp, #0] +10007496: 9401 str r4, [sp, #4] +10007498: 9103 str r1, [sp, #12] +1000749a: f88d 3014 strb.w r3, [sp, #20] +1000749e: 9504 str r5, [sp, #16] +100074a0: f7ff ffd5 bl 1000744e + +100074a4 : +100074a4: ea5f 0800 movs.w r8, r0 +100074a8: d105 bne.n 100074b6 +100074aa: b126 cbz r6, 100074b6 +100074ac: 2f00 cmp r7, #0 +100074ae: bf1a itte ne +100074b0: 9804 ldrne r0, [sp, #16] +100074b2: 6030 strne r0, [r6, #0] +100074b4: 6035 streq r5, [r6, #0] + +100074b6 : +100074b6: f000 fee7 bl 10008288 +100074ba: f7ff fea6 bl 1000720a + +100074be : +100074be: bfa8 it ge +100074c0: f884 800c strbge.w r8, [r4, #12] +100074c4: f000 fee5 bl 10008292 +100074c8: 4640 mov r0, r8 + +100074ca : +100074ca: b006 add sp, #24 +100074cc: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +100074d0 : +100074d0: b530 push {r4, r5, lr} +100074d2: b087 sub sp, #28 +100074d4: 0004 movs r4, r0 +100074d6: bf08 it eq +100074d8: f06f 000d mvneq.w r0, #13 +100074dc: d00f beq.n 100074fe +100074de: 4812 ldr r0, [pc, #72] ; (10007528 ) +100074e0: 9000 str r0, [sp, #0] +100074e2: 9401 str r4, [sp, #4] +100074e4: f88d 100c strb.w r1, [sp, #12] +100074e8: f7ff ffb1 bl 1000744e + +100074ec : +100074ec: f7ff fe73 bl 100071d6 + +100074f0 : +100074f0: f7ff fe8b bl 1000720a + +100074f4 : +100074f4: bfa8 it ge +100074f6: 7325 strbge r5, [r4, #12] +100074f8: f000 fecb bl 10008292 +100074fc: 4628 mov r0, r5 + +100074fe : +100074fe: b007 add sp, #28 +10007500: bd30 pop {r4, r5, pc} + ... + +10007504 : +10007504: 78ad 1000 .x.. + +10007508 : +10007508: 7b61 1000 a{.. + +1000750c : +1000750c: 7ff7 1000 .... + +10007510 : +10007510: 7be9 1000 .{.. + +10007514 : +10007514: 7c9d 1000 .|.. + +10007518 : +10007518: 7d2d 1000 -}.. + +1000751c : +1000751c: 7e6b 1000 k~.. + +10007520 : +10007520: 7e03 1000 .~.. + +10007524 : +10007524: 7fb9 1000 .... + +10007528 : +10007528: 8061 1000 a... + +1000752c : +1000752c: 2103 movs r1, #3 +1000752e: e7cf b.n 100074d0 + +10007530 : +10007530: b510 push {r4, lr} +10007532: 4604 mov r4, r0 +10007534: 69a0 ldr r0, [r4, #24] +10007536: b150 cbz r0, 1000754e +10007538: 6b23 ldr r3, [r4, #48] ; 0x30 +1000753a: 0018 movs r0, r3 +1000753c: d003 beq.n 10007546 +1000753e: 2200 movs r2, #0 +10007540: 2100 movs r1, #0 +10007542: 4620 mov r0, r4 +10007544: 4798 blx r3 + +10007546 : +10007546: 69a0 ldr r0, [r4, #24] +10007548: 2100 movs r1, #0 +1000754a: f000 fdc9 bl 100080e0 + +1000754e : +1000754e: 2000 movs r0, #0 +10007550: bd10 pop {r4, pc} + ... + +10007554 : +10007554: b5f8 push {r3, r4, r5, r6, r7, lr} +10007556: 0004 movs r4, r0 +10007558: 460d mov r5, r1 +1000755a: 4616 mov r6, r2 +1000755c: d030 beq.n 100075c0 +1000755e: f000 f937 bl 100077d0 + +10007562 : +10007562: b368 cbz r0, 100075c0 +10007564: 8931 ldrh r1, [r6, #8] +10007566: 2200 movs r2, #0 +10007568: 2003 movs r0, #3 +1000756a: f001 f82d bl 100085c8 +1000756e: 0007 movs r7, r0 +10007570: d026 beq.n 100075c0 +10007572: 4631 mov r1, r6 +10007574: f001 f996 bl 100088a4 +10007578: b920 cbnz r0, 10007584 +1000757a: 2007 movs r0, #7 +1000757c: f000 feb1 bl 100082e2 +10007580: 0006 movs r6, r0 +10007582: d103 bne.n 1000758c + +10007584 : +10007584: 4638 mov r0, r7 +10007586: f001 f92f bl 100087e8 +1000758a: e019 b.n 100075c0 + +1000758c : +1000758c: 6037 str r7, [r6, #0] +1000758e: 6077 str r7, [r6, #4] +10007590: 4631 mov r1, r6 +10007592: f8df 083c ldr.w r0, [pc, #2108] ; 10007dd0 +10007596: 6800 ldr r0, [r0, #0] +10007598: 60b0 str r0, [r6, #8] +1000759a: 7c28 ldrb r0, [r5, #16] +1000759c: 81b0 strh r0, [r6, #12] +1000759e: f104 0014 add.w r0, r4, #20 +100075a2: 893d ldrh r5, [r7, #8] +100075a4: f000 fda6 bl 100080f4 +100075a8: b118 cbz r0, 100075b2 +100075aa: 4630 mov r0, r6 +100075ac: f001 fa08 bl 100089c0 +100075b0: e006 b.n 100075c0 + +100075b2 : +100075b2: 6b23 ldr r3, [r4, #48] ; 0x30 +100075b4: 0018 movs r0, r3 +100075b6: d003 beq.n 100075c0 +100075b8: 462a mov r2, r5 +100075ba: 2100 movs r1, #0 +100075bc: 4620 mov r0, r4 +100075be: 4798 blx r3 + +100075c0 : +100075c0: 2000 movs r0, #0 +100075c2: bdf2 pop {r1, r4, r5, r6, r7, pc} + +100075c4 : +100075c4: b5f8 push {r3, r4, r5, r6, r7, lr} +100075c6: 0004 movs r4, r0 +100075c8: 4615 mov r5, r2 +100075ca: 461e mov r6, r3 +100075cc: d007 beq.n 100075de +100075ce: f000 f8ff bl 100077d0 + +100075d2 : +100075d2: b120 cbz r0, 100075de +100075d4: 2007 movs r0, #7 +100075d6: f000 fe84 bl 100082e2 +100075da: 0007 movs r7, r0 +100075dc: d104 bne.n 100075e8 + +100075de : +100075de: 4628 mov r0, r5 +100075e0: e8bd 40f2 ldmia.w sp!, {r1, r4, r5, r6, r7, lr} +100075e4: f001 b900 b.w 100087e8 + +100075e8 : +100075e8: 603d str r5, [r7, #0] +100075ea: 607d str r5, [r7, #4] +100075ec: 2e00 cmp r6, #0 +100075ee: bf0c ite eq +100075f0: 2000 moveq r0, #0 +100075f2: 6830 ldrne r0, [r6, #0] +100075f4: 60b8 str r0, [r7, #8] +100075f6: 4639 mov r1, r7 +100075f8: 9806 ldr r0, [sp, #24] +100075fa: 81b8 strh r0, [r7, #12] +100075fc: f104 0014 add.w r0, r4, #20 +10007600: 892d ldrh r5, [r5, #8] +10007602: f000 fd77 bl 100080f4 +10007606: b120 cbz r0, 10007612 +10007608: 4638 mov r0, r7 +1000760a: e8bd 40f2 ldmia.w sp!, {r1, r4, r5, r6, r7, lr} +1000760e: f001 b9d7 b.w 100089c0 + +10007612 : +10007612: 6b23 ldr r3, [r4, #48] ; 0x30 +10007614: 0018 movs r0, r3 +10007616: d006 beq.n 10007626 +10007618: 462a mov r2, r5 +1000761a: 4620 mov r0, r4 +1000761c: b001 add sp, #4 +1000761e: e8bd 40f0 ldmia.w sp!, {r4, r5, r6, r7, lr} +10007622: 2100 movs r1, #0 + +10007624 <__iar_annotation$$tailcall>: +10007624: 4718 bx r3 + +10007626 : +10007626: bdf1 pop {r0, r4, r5, r6, r7, pc} + +10007628 : +10007628: b5f8 push {r3, r4, r5, r6, r7, lr} +1000762a: 0004 movs r4, r0 +1000762c: 460d mov r5, r1 +1000762e: 4616 mov r6, r2 +10007630: 461f mov r7, r3 +10007632: d100 bne.n 10007636 +10007634: e134 b.n 100078a0 + +10007636 : +10007636: f000 f8cb bl 100077d0 + +1000763a : +1000763a: b940 cbnz r0, 1000764e +1000763c: b31e cbz r6, 10007686 +1000763e: 8931 ldrh r1, [r6, #8] +10007640: 4628 mov r0, r5 +10007642: f001 fbac bl 10008d9e +10007646: 4630 mov r0, r6 +10007648: f001 f8ce bl 100087e8 +1000764c: e01b b.n 10007686 + +1000764e : +1000764e: f000 fe1b bl 10008288 +10007652: f994 100c ldrsb.w r1, [r4, #12] +10007656: f111 0f09 cmn.w r1, #9 +1000765a: bfa8 it ge +1000765c: 7327 strbge r7, [r4, #12] +1000765e: f000 fe18 bl 10008292 +10007662: 2e00 cmp r6, #0 +10007664: bf14 ite ne +10007666: 8935 ldrhne r5, [r6, #8] +10007668: 2500 moveq r5, #0 +1000766a: 4631 mov r1, r6 +1000766c: f104 0014 add.w r0, r4, #20 +10007670: f000 fd40 bl 100080f4 +10007674: b100 cbz r0, 10007678 +10007676: e116 b.n 100078a6 + +10007678 : +10007678: 6b23 ldr r3, [r4, #48] ; 0x30 +1000767a: 0018 movs r0, r3 +1000767c: d003 beq.n 10007686 +1000767e: 462a mov r2, r5 +10007680: 2100 movs r1, #0 +10007682: 4620 mov r0, r4 +10007684: 4798 blx r3 + +10007686 : +10007686: 2000 movs r0, #0 +10007688: bdf2 pop {r1, r4, r5, r6, r7, pc} + +1000768a : +1000768a: b510 push {r4, lr} +1000768c: 4604 mov r4, r0 +1000768e: 6860 ldr r0, [r4, #4] +10007690: 2801 cmp r0, #1 +10007692: d103 bne.n 1000769c +10007694: 4620 mov r0, r4 +10007696: f000 fc08 bl 10007eaa +1000769a: e004 b.n 100076a6 + +1000769c : +1000769c: 2804 cmp r0, #4 +1000769e: bf04 itt eq +100076a0: 4620 moveq r0, r4 +100076a2: f000 f9e9 bleq 10007a78 + +100076a6 : +100076a6: f894 0024 ldrb.w r0, [r4, #36] ; 0x24 +100076aa: 06c1 lsls r1, r0, #27 +100076ac: d517 bpl.n 100076de +100076ae: 1d21 adds r1, r4, #4 +100076b0: 6849 ldr r1, [r1, #4] +100076b2: b1a1 cbz r1, 100076de +100076b4: f8b1 206a ldrh.w r2, [r1, #106] ; 0x6a +100076b8: f640 6343 movw r3, #3651 ; 0xe43 +100076bc: 429a cmp r2, r3 +100076be: db0e blt.n 100076de +100076c0: f8b1 106c ldrh.w r1, [r1, #108] ; 0x6c +100076c4: 290a cmp r1, #10 +100076c6: da0a bge.n 100076de +100076c8: f000 00ef and.w r0, r0, #239 ; 0xef +100076cc: f884 0024 strb.w r0, [r4, #36] ; 0x24 +100076d0: f104 0024 add.w r0, r4, #36 ; 0x24 +100076d4: 68c3 ldr r3, [r0, #12] +100076d6: 0018 movs r0, r3 +100076d8: d001 beq.n 100076de +100076da: f000 fa37 bl 10007b4c + +100076de : +100076de: 2000 movs r0, #0 +100076e0: bd10 pop {r4, pc} + +100076e2 : +100076e2: b538 push {r3, r4, r5, lr} +100076e4: 4604 mov r4, r0 +100076e6: 4615 mov r5, r2 +100076e8: 6860 ldr r0, [r4, #4] +100076ea: 2801 cmp r0, #1 +100076ec: d103 bne.n 100076f6 +100076ee: 4620 mov r0, r4 +100076f0: f000 fbdb bl 10007eaa +100076f4: e004 b.n 10007700 + +100076f6 : +100076f6: 2804 cmp r0, #4 +100076f8: bf04 itt eq +100076fa: 4620 moveq r0, r4 +100076fc: f000 f9bc bleq 10007a78 + +10007700 : +10007700: 2c00 cmp r4, #0 +10007702: bf1e ittt ne +10007704: 1d20 addne r0, r4, #4 +10007706: 6840 ldrne r0, [r0, #4] +10007708: 2800 cmpne r0, #0 +1000770a: d018 beq.n 1000773e +1000770c: f8b0 106a ldrh.w r1, [r0, #106] ; 0x6a +10007710: f640 6243 movw r2, #3651 ; 0xe43 +10007714: 4291 cmp r1, r2 +10007716: db12 blt.n 1000773e +10007718: f8b0 006c ldrh.w r0, [r0, #108] ; 0x6c +1000771c: 280a cmp r0, #10 +1000771e: da0e bge.n 1000773e +10007720: f894 0024 ldrb.w r0, [r4, #36] ; 0x24 +10007724: f000 00ef and.w r0, r0, #239 ; 0xef +10007728: f884 0024 strb.w r0, [r4, #36] ; 0x24 +1000772c: f104 0024 add.w r0, r4, #36 ; 0x24 +10007730: 68c3 ldr r3, [r0, #12] +10007732: 0018 movs r0, r3 +10007734: d003 beq.n 1000773e +10007736: 462a mov r2, r5 +10007738: 2102 movs r1, #2 +1000773a: 4620 mov r0, r4 +1000773c: 4798 blx r3 + +1000773e : +1000773e: 2000 movs r0, #0 +10007740: bd32 pop {r1, r4, r5, pc} + +10007742 : +10007742: b5f8 push {r3, r4, r5, r6, r7, lr} +10007744: 4604 mov r4, r0 +10007746: 1d26 adds r6, r4, #4 +10007748: 2000 movs r0, #0 +1000774a: 460d mov r5, r1 +1000774c: 6070 str r0, [r6, #4] +1000774e: f000 fd9b bl 10008288 +10007752: 7235 strb r5, [r6, #8] +10007754: f000 fd9d bl 10008292 +10007758: 2000 movs r0, #0 +1000775a: 6867 ldr r7, [r4, #4] +1000775c: 6060 str r0, [r4, #4] +1000775e: f104 0624 add.w r6, r4, #36 ; 0x24 +10007762: 68f3 ldr r3, [r6, #12] +10007764: 0018 movs r0, r3 +10007766: d00d beq.n 10007784 +10007768: 2200 movs r2, #0 +1000776a: 2104 movs r1, #4 +1000776c: 4620 mov r0, r4 +1000776e: 4798 blx r3 +10007770: 68f3 ldr r3, [r6, #12] +10007772: 0018 movs r0, r3 +10007774: d006 beq.n 10007784 +10007776: f000 f88f bl 10007898 + +1000777a : +1000777a: 68f3 ldr r3, [r6, #12] +1000777c: 0018 movs r0, r3 +1000777e: d001 beq.n 10007784 +10007780: f000 f9e4 bl 10007b4c + +10007784 : +10007784: f000 f824 bl 100077d0 + +10007788 : +10007788: b120 cbz r0, 10007794 +1000778a: 2100 movs r1, #0 +1000778c: f104 0014 add.w r0, r4, #20 +10007790: f000 fcb0 bl 100080f4 + +10007794 : +10007794: f000 f923 bl 100079de + +10007798 : +10007798: b120 cbz r0, 100077a4 +1000779a: 2100 movs r1, #0 +1000779c: f104 0018 add.w r0, r4, #24 +100077a0: f000 fca8 bl 100080f4 + +100077a4 : +100077a4: 2f01 cmp r7, #1 +100077a6: bf1c itt ne +100077a8: 2f04 cmpne r7, #4 +100077aa: 2f03 cmpne r7, #3 +100077ac: d10e bne.n 100077cc +100077ae: f894 0024 ldrb.w r0, [r4, #36] ; 0x24 +100077b2: 0881 lsrs r1, r0, #2 +100077b4: f000 00fb and.w r0, r0, #251 ; 0xfb +100077b8: f011 0101 ands.w r1, r1, #1 +100077bc: f884 0024 strb.w r0, [r4, #36] ; 0x24 +100077c0: d104 bne.n 100077cc +100077c2: 68b0 ldr r0, [r6, #8] +100077c4: 7105 strb r5, [r0, #4] +100077c6: 2000 movs r0, #0 +100077c8: 60b0 str r0, [r6, #8] +100077ca: e1c3 b.n 10007b54 + +100077cc : +100077cc: bdf1 pop {r0, r4, r5, r6, r7, pc} + +100077ce : +100077ce: 4604 mov r4, r0 + +100077d0 : +100077d0: f104 0014 add.w r0, r4, #20 +100077d4: f000 bcd0 b.w 10008178 + +100077d8 : +100077d8: b510 push {r4, lr} +100077da: 6884 ldr r4, [r0, #8] +100077dc: 4601 mov r1, r0 +100077de: 4620 mov r0, r4 +100077e0: f001 fdf2 bl 100093c8 +100077e4: f8df 15ec ldr.w r1, [pc, #1516] ; 10007dd4 +100077e8: 4620 mov r0, r4 +100077ea: f001 fdef bl 100093cc +100077ee: f8df 15e8 ldr.w r1, [pc, #1512] ; 10007dd8 +100077f2: 4620 mov r0, r4 +100077f4: f001 fded bl 100093d2 +100077f8: 2204 movs r2, #4 +100077fa: f8df 15e0 ldr.w r1, [pc, #1504] ; 10007ddc +100077fe: 4620 mov r0, r4 +10007800: f001 fdef bl 100093e2 +10007804: 4620 mov r0, r4 +10007806: e8bd 4010 ldmia.w sp!, {r4, lr} +1000780a: f8df 15d4 ldr.w r1, [pc, #1492] ; 10007de0 +1000780e: f001 bde3 b.w 100093d8 + +10007812 : +10007812: b5f8 push {r3, r4, r5, r6, r7, lr} +10007814: 4604 mov r4, r0 +10007816: 460d mov r5, r1 +10007818: 4616 mov r6, r2 +1000781a: f000 f8e0 bl 100079de + +1000781e : +1000781e: b900 cbnz r0, 10007822 +10007820: e03e b.n 100078a0 + +10007822 : +10007822: 6b21 ldr r1, [r4, #48] ; 0x30 +10007824: 6820 ldr r0, [r4, #0] +10007826: f000 f880 bl 1000792a +1000782a: 0007 movs r7, r0 +1000782c: d02c beq.n 10007888 +1000782e: 60bd str r5, [r7, #8] +10007830: f7ff ffd2 bl 100077d8 +10007834: 733e strb r6, [r7, #12] +10007836: 4639 mov r1, r7 +10007838: f104 0018 add.w r0, r4, #24 +1000783c: f000 fc5a bl 100080f4 +10007840: b318 cbz r0, 1000788a +10007842: 68bc ldr r4, [r7, #8] +10007844: 2100 movs r1, #0 +10007846: 4620 mov r0, r4 +10007848: f001 fdbe bl 100093c8 +1000784c: 2100 movs r1, #0 +1000784e: 4620 mov r0, r4 +10007850: f001 fdbc bl 100093cc +10007854: 2100 movs r1, #0 +10007856: 4620 mov r0, r4 +10007858: f001 fdbb bl 100093d2 +1000785c: 2204 movs r2, #4 +1000785e: 2100 movs r1, #0 +10007860: 4620 mov r0, r4 +10007862: f001 fdbe bl 100093e2 +10007866: 2100 movs r1, #0 +10007868: 4620 mov r0, r4 +1000786a: f001 fdb5 bl 100093d8 +1000786e: 2000 movs r0, #0 +10007870: 60b8 str r0, [r7, #8] +10007872: f107 0014 add.w r0, r7, #20 +10007876: f000 fc29 bl 100080cc +1000787a: f107 0014 add.w r0, r7, #20 +1000787e: f000 fc7c bl 1000817a +10007882: 4638 mov r0, r7 +10007884: f000 f898 bl 100079b8 + +10007888 : +10007888: e00d b.n 100078a6 + +1000788a : +1000788a: 6b23 ldr r3, [r4, #48] ; 0x30 +1000788c: 0018 movs r0, r3 +1000788e: d001 beq.n 10007894 +10007890: f000 f802 bl 10007898 + +10007894 : +10007894: 2000 movs r0, #0 +10007896: bdf2 pop {r1, r4, r5, r6, r7, pc} + +10007898 : +10007898: 2200 movs r2, #0 +1000789a: 2100 movs r1, #0 +1000789c: 4620 mov r0, r4 + +1000789e <__iar_annotation$$tailcall>: +1000789e: 4718 bx r3 + +100078a0 : +100078a0: f06f 0005 mvn.w r0, #5 +100078a4: bdf2 pop {r1, r4, r5, r6, r7, pc} + +100078a6 : +100078a6: f04f 30ff mov.w r0, #4294967295 +100078aa: bdf2 pop {r1, r4, r5, r6, r7, pc} + +100078ac : +100078ac: b538 push {r3, r4, r5, lr} +100078ae: f000 faf6 bl 10007e9e + +100078b2 : +100078b2: 2900 cmp r1, #0 +100078b4: d135 bne.n 10007922 +100078b6: 7800 ldrb r0, [r0, #0] +100078b8: f000 00f0 and.w r0, r0, #240 ; 0xf0 +100078bc: f04f 35ff mov.w r5, #4294967295 +100078c0: 2810 cmp r0, #16 +100078c2: d004 beq.n 100078ce +100078c4: 2820 cmp r0, #32 +100078c6: d00b beq.n 100078e0 +100078c8: 2840 cmp r0, #64 ; 0x40 +100078ca: d01a beq.n 10007902 +100078cc: e026 b.n 1000791c + +100078ce : +100078ce: f001 fd79 bl 100093c4 +100078d2: 6821 ldr r1, [r4, #0] +100078d4: 6088 str r0, [r1, #8] +100078d6: b1d0 cbz r0, 1000790e +100078d8: 4608 mov r0, r1 +100078da: f7ff ff7d bl 100077d8 +100078de: e020 b.n 10007922 + +100078e0 : +100078e0: f001 ffe8 bl 100098b4 +100078e4: 6821 ldr r1, [r4, #0] +100078e6: 6088 str r0, [r1, #8] +100078e8: b188 cbz r0, 1000790e +100078ea: 6809 ldr r1, [r1, #0] +100078ec: 2922 cmp r1, #34 ; 0x22 +100078ee: bf04 itt eq +100078f0: 2101 moveq r1, #1 +100078f2: 7401 strbeq r1, [r0, #16] +100078f4: 6822 ldr r2, [r4, #0] +100078f6: f8df 14ec ldr.w r1, [pc, #1260] ; 10007de4 +100078fa: 6890 ldr r0, [r2, #8] +100078fc: f001 ffbd bl 1000987a +10007900: e00f b.n 10007922 + +10007902 : +10007902: 7a20 ldrb r0, [r4, #8] +10007904: f002 f883 bl 10009a0e +10007908: 6822 ldr r2, [r4, #0] +1000790a: 6090 str r0, [r2, #8] +1000790c: b908 cbnz r0, 10007912 + +1000790e : +1000790e: 7125 strb r5, [r4, #4] +10007910: e007 b.n 10007922 + +10007912 : +10007912: f8df 14d4 ldr.w r1, [pc, #1236] ; 10007de8 +10007916: f002 f81c bl 10009952 +1000791a: e002 b.n 10007922 + +1000791c : +1000791c: f06f 0005 mvn.w r0, #5 +10007920: 7120 strb r0, [r4, #4] + +10007922 : +10007922: 6820 ldr r0, [r4, #0] +10007924: e8bd 4032 ldmia.w sp!, {r1, r4, r5, lr} +10007928: e3bf b.n 100080aa + +1000792a : +1000792a: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1000792e: 4680 mov r8, r0 +10007930: 460c mov r4, r1 +10007932: 2700 movs r7, #0 +10007934: 2008 movs r0, #8 +10007936: f000 fcd4 bl 100082e2 +1000793a: 0005 movs r5, r0 +1000793c: bf08 it eq +1000793e: 2000 moveq r0, #0 +10007940: d024 beq.n 1000798c +10007942: 1d2e adds r6, r5, #4 +10007944: f008 00f0 and.w r0, r8, #240 ; 0xf0 +10007948: 7237 strb r7, [r6, #8] +1000794a: f8c5 8000 str.w r8, [r5] +1000794e: 6077 str r7, [r6, #4] +10007950: 2810 cmp r0, #16 +10007952: bf18 it ne +10007954: 2820 cmpne r0, #32 +10007956: d002 beq.n 1000795e +10007958: 2840 cmp r0, #64 ; 0x40 +1000795a: d002 beq.n 10007962 +1000795c: e011 b.n 10007982 + +1000795e : +1000795e: f44f 67fa mov.w r7, #2000 ; 0x7d0 + +10007962 : +10007962: 2100 movs r1, #0 +10007964: f105 0010 add.w r0, r5, #16 +10007968: f000 fc08 bl 1000817c +1000796c: b948 cbnz r0, 10007982 +1000796e: 4639 mov r1, r7 +10007970: f105 0014 add.w r0, r5, #20 +10007974: f000 fb9c bl 100080b0 +10007978: b150 cbz r0, 10007990 +1000797a: f105 0010 add.w r0, r5, #16 +1000797e: f000 fc3c bl 100081fa + +10007982 : +10007982: 4629 mov r1, r5 +10007984: 2008 movs r0, #8 +10007986: f000 fcbf bl 10008308 +1000798a: 2000 movs r0, #0 + +1000798c : +1000798c: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +10007990 : +10007990: f105 0018 add.w r0, r5, #24 +10007994: f000 fbf1 bl 1000817a +10007998: 2000 movs r0, #0 +1000799a: 6068 str r0, [r5, #4] +1000799c: 2100 movs r1, #0 +1000799e: f04f 30ff mov.w r0, #4294967295 +100079a2: 61b0 str r0, [r6, #24] +100079a4: f105 0024 add.w r0, r5, #36 ; 0x24 +100079a8: 60c4 str r4, [r0, #12] +100079aa: 6081 str r1, [r0, #8] +100079ac: 6041 str r1, [r0, #4] +100079ae: 61f1 str r1, [r6, #28] +100079b0: f885 1024 strb.w r1, [r5, #36] ; 0x24 +100079b4: 4628 mov r0, r5 +100079b6: e7e9 b.n 1000798c + +100079b8 : +100079b8: b510 push {r4, lr} +100079ba: f7ff ff08 bl 100077ce + +100079be : +100079be: f000 f80e bl 100079de + +100079c2 : +100079c2: f104 0010 add.w r0, r4, #16 +100079c6: f000 fc18 bl 100081fa +100079ca: f104 0010 add.w r0, r4, #16 +100079ce: f000 fc1c bl 1000820a +100079d2: 4621 mov r1, r4 +100079d4: e8bd 4010 ldmia.w sp!, {r4, lr} +100079d8: 2008 movs r0, #8 +100079da: f000 bc95 b.w 10008308 + +100079de : +100079de: f104 0018 add.w r0, r4, #24 +100079e2: f000 bbc9 b.w 10008178 + +100079e6 : +100079e6: b538 push {r3, r4, r5, lr} +100079e8: f7ff fef1 bl 100077ce + +100079ec : +100079ec: b910 cbnz r0, 100079f4 +100079ee: e021 b.n 10007a34 + +100079f0 : +100079f0: f000 ffe6 bl 100089c0 + +100079f4 : +100079f4: a900 add r1, sp, #0 +100079f6: f104 0014 add.w r0, r4, #20 +100079fa: f000 fbae bl 1000815a +100079fe: f110 0f01 cmn.w r0, #1 +10007a02: d00f beq.n 10007a24 +10007a04: 6820 ldr r0, [r4, #0] +10007a06: 2810 cmp r0, #16 +10007a08: 9800 ldr r0, [sp, #0] +10007a0a: d1f1 bne.n 100079f0 +10007a0c: 2800 cmp r0, #0 +10007a0e: d0f1 beq.n 100079f4 +10007a10: 4605 mov r5, r0 +10007a12: 68a0 ldr r0, [r4, #8] +10007a14: b110 cbz r0, 10007a1c +10007a16: 8929 ldrh r1, [r5, #8] +10007a18: f001 f9c1 bl 10008d9e + +10007a1c : +10007a1c: 4628 mov r0, r5 +10007a1e: f000 fee3 bl 100087e8 +10007a22: e7e7 b.n 100079f4 + +10007a24 : +10007a24: f104 0014 add.w r0, r4, #20 +10007a28: f000 fb50 bl 100080cc +10007a2c: f104 0014 add.w r0, r4, #20 +10007a30: f000 fba3 bl 1000817a + +10007a34 : +10007a34: f7ff ffd3 bl 100079de + +10007a38 : +10007a38: b968 cbnz r0, 10007a56 +10007a3a: bd31 pop {r0, r4, r5, pc} + +10007a3c : +10007a3c: 9d00 ldr r5, [sp, #0] +10007a3e: 4628 mov r0, r5 +10007a40: f7ff ffd1 bl 100079e6 +10007a44: 68a8 ldr r0, [r5, #8] +10007a46: b118 cbz r0, 10007a50 +10007a48: f001 f918 bl 10008c7c +10007a4c: 2000 movs r0, #0 +10007a4e: 60a8 str r0, [r5, #8] + +10007a50 : +10007a50: 4628 mov r0, r5 +10007a52: f7ff ffb1 bl 100079b8 + +10007a56 : +10007a56: a900 add r1, sp, #0 +10007a58: f104 0018 add.w r0, r4, #24 +10007a5c: f000 fb7d bl 1000815a +10007a60: f110 0f01 cmn.w r0, #1 +10007a64: d1ea bne.n 10007a3c +10007a66: f104 0018 add.w r0, r4, #24 +10007a6a: f000 fb2f bl 100080cc +10007a6e: f104 0018 add.w r0, r4, #24 +10007a72: f000 fb82 bl 1000817a +10007a76: bd31 pop {r0, r4, r5, pc} + +10007a78 : +10007a78: b5f8 push {r3, r4, r5, r6, r7, lr} +10007a7a: 4604 mov r4, r0 +10007a7c: 6ae0 ldr r0, [r4, #44] ; 0x2c +10007a7e: 7a00 ldrb r0, [r0, #8] +10007a80: f000 0601 and.w r6, r0, #1 +10007a84: f000 0502 and.w r5, r0, #2 +10007a88: 2803 cmp r0, #3 +10007a8a: d105 bne.n 10007a98 +10007a8c: 68a0 ldr r0, [r4, #8] +10007a8e: 2701 movs r7, #1 +10007a90: 2100 movs r1, #0 +10007a92: f001 fc99 bl 100093c8 +10007a96: e000 b.n 10007a9a + +10007a98 : +10007a98: 2700 movs r7, #0 + +10007a9a : +10007a9a: 68a0 ldr r0, [r4, #8] +10007a9c: 6981 ldr r1, [r0, #24] +10007a9e: 2901 cmp r1, #1 +10007aa0: d125 bne.n 10007aee +10007aa2: 2100 movs r1, #0 +10007aa4: f001 fc9b bl 100093de +10007aa8: 2f00 cmp r7, #0 +10007aaa: d138 bne.n 10007b1e + +10007aac : +10007aac: 68a0 ldr r0, [r4, #8] +10007aae: 462a mov r2, r5 +10007ab0: 4631 mov r1, r6 +10007ab2: f001 f874 bl 10008b9e + +10007ab6 : +10007ab6: 2800 cmp r0, #0 +10007ab8: d135 bne.n 10007b26 +10007aba: 6ae1 ldr r1, [r4, #44] ; 0x2c +10007abc: 7108 strb r0, [r1, #4] +10007abe: 62e0 str r0, [r4, #44] ; 0x2c +10007ac0: 6060 str r0, [r4, #4] +10007ac2: b13f cbz r7, 10007ad4 +10007ac4: 60a0 str r0, [r4, #8] +10007ac6: 6b23 ldr r3, [r4, #48] ; 0x30 +10007ac8: 0018 movs r0, r3 +10007aca: d00f beq.n 10007aec +10007acc: 2200 movs r2, #0 +10007ace: 2104 movs r1, #4 +10007ad0: 4620 mov r0, r4 +10007ad2: 4798 blx r3 + +10007ad4 : +10007ad4: b126 cbz r6, 10007ae0 +10007ad6: 6b23 ldr r3, [r4, #48] ; 0x30 +10007ad8: 0018 movs r0, r3 +10007ada: d007 beq.n 10007aec +10007adc: f7ff fedc bl 10007898 + +10007ae0 : +10007ae0: b125 cbz r5, 10007aec +10007ae2: 6b23 ldr r3, [r4, #48] ; 0x30 +10007ae4: 0018 movs r0, r3 +10007ae6: d001 beq.n 10007aec +10007ae8: f000 f830 bl 10007b4c + +10007aec : +10007aec: e032 b.n 10007b54 + +10007aee : +10007aee: b136 cbz r6, 10007afe +10007af0: 2100 movs r1, #0 +10007af2: f001 fc6b bl 100093cc +10007af6: 68a0 ldr r0, [r4, #8] +10007af8: 2100 movs r1, #0 +10007afa: f001 fc70 bl 100093de + +10007afe : +10007afe: b11d cbz r5, 10007b08 +10007b00: 68a0 ldr r0, [r4, #8] +10007b02: 2100 movs r1, #0 +10007b04: f001 fc65 bl 100093d2 + +10007b08 : +10007b08: 2f00 cmp r7, #0 +10007b0a: d0cf beq.n 10007aac +10007b0c: 68a0 ldr r0, [r4, #8] +10007b0e: 2204 movs r2, #4 +10007b10: 2100 movs r1, #0 +10007b12: f001 fc66 bl 100093e2 +10007b16: 68a0 ldr r0, [r4, #8] +10007b18: 2100 movs r1, #0 +10007b1a: f001 fc5d bl 100093d8 + +10007b1e : +10007b1e: 68a0 ldr r0, [r4, #8] +10007b20: f001 f832 bl 10008b88 +10007b24: e7c7 b.n 10007ab6 + +10007b26 : +10007b26: 68a0 ldr r0, [r4, #8] +10007b28: 49ab ldr r1, [pc, #684] ; (10007dd8 ) +10007b2a: f001 fc52 bl 100093d2 +10007b2e: 68a0 ldr r0, [r4, #8] +10007b30: 49aa ldr r1, [pc, #680] ; (10007ddc ) +10007b32: 2204 movs r2, #4 +10007b34: f001 fc55 bl 100093e2 +10007b38: 68a0 ldr r0, [r4, #8] +10007b3a: 49a9 ldr r1, [pc, #676] ; (10007de0 ) +10007b3c: f001 fc4c bl 100093d8 +10007b40: 68a0 ldr r0, [r4, #8] +10007b42: 4621 mov r1, r4 +10007b44: e8bd 40f4 ldmia.w sp!, {r2, r4, r5, r6, r7, lr} +10007b48: f001 bc3e b.w 100093c8 + +10007b4c : +10007b4c: 2200 movs r2, #0 +10007b4e: 2102 movs r1, #2 +10007b50: 4620 mov r0, r4 + +10007b52 <__iar_annotation$$tailcall>: +10007b52: 4718 bx r3 + +10007b54 : +10007b54: f104 0010 add.w r0, r4, #16 +10007b58: e8bd 40f2 ldmia.w sp!, {r1, r4, r5, r6, r7, lr} +10007b5c: f000 bb47 b.w 100081ee + +10007b60 : +10007b60: b510 push {r4, lr} +10007b62: 4604 mov r4, r0 +10007b64: 6820 ldr r0, [r4, #0] +10007b66: 6841 ldr r1, [r0, #4] +10007b68: 2900 cmp r1, #0 +10007b6a: bf1c itt ne +10007b6c: 2902 cmpne r1, #2 +10007b6e: 2903 cmpne r1, #3 +10007b70: d003 beq.n 10007b7a +10007b72: f06f 0004 mvn.w r0, #4 +10007b76: 7120 strb r0, [r4, #4] +10007b78: e020 b.n 10007bbc + +10007b7a : +10007b7a: f7ff ff34 bl 100079e6 +10007b7e: 6821 ldr r1, [r4, #0] +10007b80: 6888 ldr r0, [r1, #8] +10007b82: b168 cbz r0, 10007ba0 +10007b84: 780a ldrb r2, [r1, #0] +10007b86: f002 02f0 and.w r2, r2, #240 ; 0xf0 +10007b8a: 2a10 cmp r2, #16 +10007b8c: d023 beq.n 10007bd6 +10007b8e: 2a20 cmp r2, #32 +10007b90: d01b beq.n 10007bca +10007b92: 2a40 cmp r2, #64 ; 0x40 +10007b94: bf08 it eq +10007b96: f001 ff26 bleq 100099e6 + +10007b9a : +10007b9a: 6821 ldr r1, [r4, #0] +10007b9c: 2000 movs r0, #0 +10007b9e: 6088 str r0, [r1, #8] + +10007ba0 : +10007ba0: 6820 ldr r0, [r4, #0] +10007ba2: 6b03 ldr r3, [r0, #48] ; 0x30 +10007ba4: 0019 movs r1, r3 +10007ba6: d009 beq.n 10007bbc +10007ba8: 2200 movs r2, #0 +10007baa: 2100 movs r1, #0 +10007bac: 4798 blx r3 +10007bae: 6820 ldr r0, [r4, #0] +10007bb0: 6b03 ldr r3, [r0, #48] ; 0x30 +10007bb2: 0019 movs r1, r3 +10007bb4: d002 beq.n 10007bbc +10007bb6: 2200 movs r2, #0 +10007bb8: 2102 movs r1, #2 +10007bba: 4798 blx r3 + +10007bbc : +10007bbc: 6820 ldr r0, [r4, #0] +10007bbe: 3010 adds r0, #16 +10007bc0: f000 fb1e bl 10008200 +10007bc4: b100 cbz r0, 10007bc8 +10007bc6: e26d b.n 100080a4 + +10007bc8 : +10007bc8: bd10 pop {r4, pc} + +10007bca : +10007bca: 2200 movs r2, #0 +10007bcc: 61c2 str r2, [r0, #28] +10007bce: 6888 ldr r0, [r1, #8] +10007bd0: f001 fe56 bl 10009880 +10007bd4: e7e1 b.n 10007b9a + +10007bd6 : +10007bd6: 2004 movs r0, #4 +10007bd8: 6048 str r0, [r1, #4] +10007bda: 2003 movs r0, #3 +10007bdc: 7220 strb r0, [r4, #8] +10007bde: 6820 ldr r0, [r4, #0] + +10007be0 : +10007be0: 62c4 str r4, [r0, #44] ; 0x2c +10007be2: e8bd 4010 ldmia.w sp!, {r4, lr} +10007be6: e747 b.n 10007a78 + +10007be8 : +10007be8: b510 push {r4, lr} +10007bea: f000 f903 bl 10007df4 + +10007bee : +10007bee: db1a blt.n 10007c26 +10007bf0: f06f 0005 mvn.w r0, #5 +10007bf4: 7120 strb r0, [r4, #4] +10007bf6: 6888 ldr r0, [r1, #8] +10007bf8: b1b0 cbz r0, 10007c28 +10007bfa: 7809 ldrb r1, [r1, #0] +10007bfc: f001 01f0 and.w r1, r1, #240 ; 0xf0 +10007c00: 2910 cmp r1, #16 +10007c02: d00c beq.n 10007c1e +10007c04: 2920 cmp r1, #32 +10007c06: d005 beq.n 10007c14 +10007c08: 2940 cmp r1, #64 ; 0x40 +10007c0a: d10d bne.n 10007c28 +10007c0c: 68a1 ldr r1, [r4, #8] +10007c0e: f001 fe96 bl 1000993e +10007c12: e008 b.n 10007c26 + +10007c14 : +10007c14: 89a2 ldrh r2, [r4, #12] +10007c16: 68a1 ldr r1, [r4, #8] +10007c18: f001 fdc4 bl 100097a4 +10007c1c: e003 b.n 10007c26 + +10007c1e : +10007c1e: 89a2 ldrh r2, [r4, #12] +10007c20: 68a1 ldr r1, [r4, #8] +10007c22: f001 f82d bl 10008c80 + +10007c26 : +10007c26: 7120 strb r0, [r4, #4] + +10007c28 : +10007c28: e23c b.n 100080a4 + +10007c2a : +10007c2a: b570 push {r4, r5, r6, lr} +10007c2c: 0004 movs r4, r0 +10007c2e: d102 bne.n 10007c36 +10007c30: f06f 0005 mvn.w r0, #5 +10007c34: bd70 pop {r4, r5, r6, pc} + +10007c36 : +10007c36: f104 0524 add.w r5, r4, #36 ; 0x24 +10007c3a: 68a8 ldr r0, [r5, #8] +10007c3c: b100 cbz r0, 10007c40 +10007c3e: 7102 strb r2, [r0, #4] + +10007c40 : +10007c40: 6820 ldr r0, [r4, #0] +10007c42: 2810 cmp r0, #16 +10007c44: bf02 ittt eq +10007c46: 2a00 cmpeq r2, #0 +10007c48: 4620 moveq r0, r4 +10007c4a: f7ff fdc5 bleq 100077d8 +10007c4e: f894 0024 ldrb.w r0, [r4, #36] ; 0x24 +10007c52: 0881 lsrs r1, r0, #2 +10007c54: f000 00fb and.w r0, r0, #251 ; 0xfb +10007c58: f884 0024 strb.w r0, [r4, #36] ; 0x24 +10007c5c: f001 0101 and.w r1, r1, #1 +10007c60: 2000 movs r0, #0 +10007c62: 60a8 str r0, [r5, #8] +10007c64: f081 0601 eor.w r6, r1, #1 +10007c68: 6060 str r0, [r4, #4] +10007c6a: b95e cbnz r6, 10007c84 +10007c6c: f000 fb0c bl 10008288 +10007c70: 1d21 adds r1, r4, #4 +10007c72: f991 2008 ldrsb.w r2, [r1, #8] +10007c76: f112 0f09 cmn.w r2, #9 +10007c7a: bfa4 itt ge +10007c7c: 2200 movge r2, #0 +10007c7e: 720a strbge r2, [r1, #8] +10007c80: f000 fb07 bl 10008292 + +10007c84 : +10007c84: 68eb ldr r3, [r5, #12] +10007c86: 0018 movs r0, r3 +10007c88: d001 beq.n 10007c8e +10007c8a: f7ff ff5f bl 10007b4c + +10007c8e : +10007c8e: b11e cbz r6, 10007c98 +10007c90: f104 0010 add.w r0, r4, #16 +10007c94: f000 faab bl 100081ee + +10007c98 : +10007c98: 2000 movs r0, #0 +10007c9a: bd70 pop {r4, r5, r6, pc} + +10007c9c : +10007c9c: b510 push {r4, lr} +10007c9e: 4604 mov r4, r0 +10007ca0: 6821 ldr r1, [r4, #0] +10007ca2: 6888 ldr r0, [r1, #8] +10007ca4: b910 cbnz r0, 10007cac +10007ca6: f06f 000b mvn.w r0, #11 +10007caa: e03d b.n 10007d28 + +10007cac : +10007cac: 780a ldrb r2, [r1, #0] +10007cae: f002 02f0 and.w r2, r2, #240 ; 0xf0 +10007cb2: 2a10 cmp r2, #16 +10007cb4: d00c beq.n 10007cd0 +10007cb6: 2a20 cmp r2, #32 +10007cb8: d005 beq.n 10007cc6 +10007cba: 2a40 cmp r2, #64 ; 0x40 +10007cbc: d132 bne.n 10007d24 +10007cbe: 68a1 ldr r1, [r4, #8] +10007cc0: f001 fe42 bl 10009948 +10007cc4: e030 b.n 10007d28 + +10007cc6 : +10007cc6: 89a2 ldrh r2, [r4, #12] +10007cc8: 68a1 ldr r1, [r4, #8] +10007cca: f001 fdab bl 10009824 +10007cce: e02b b.n 10007d28 + +10007cd0 : +10007cd0: 6848 ldr r0, [r1, #4] +10007cd2: b110 cbz r0, 10007cda +10007cd4: f06f 0008 mvn.w r0, #8 +10007cd8: e026 b.n 10007d28 + +10007cda : +10007cda: 4608 mov r0, r1 +10007cdc: f7ff fd7c bl 100077d8 +10007ce0: 6820 ldr r0, [r4, #0] +10007ce2: 89a2 ldrh r2, [r4, #12] +10007ce4: 68a1 ldr r1, [r4, #8] +10007ce6: 6880 ldr r0, [r0, #8] +10007ce8: 4b40 ldr r3, [pc, #256] ; (10007dec ) +10007cea: f001 f89f bl 10008e2c +10007cee: 7120 strb r0, [r4, #4] +10007cf0: b9d8 cbnz r0, 10007d2a +10007cf2: 6820 ldr r0, [r4, #0] +10007cf4: f890 1024 ldrb.w r1, [r0, #36] ; 0x24 +10007cf8: 2203 movs r2, #3 +10007cfa: 6042 str r2, [r0, #4] +10007cfc: 0849 lsrs r1, r1, #1 +10007cfe: f890 2024 ldrb.w r2, [r0, #36] ; 0x24 +10007d02: f001 0101 and.w r1, r1, #1 +10007d06: b131 cbz r1, 10007d16 +10007d08: f042 0104 orr.w r1, r2, #4 +10007d0c: f880 1024 strb.w r1, [r0, #36] ; 0x24 +10007d10: f06f 0004 mvn.w r0, #4 +10007d14: e008 b.n 10007d28 + +10007d16 : +10007d16: f002 01fb and.w r1, r2, #251 ; 0xfb +10007d1a: f880 1024 strb.w r1, [r0, #36] ; 0x24 +10007d1e: 6820 ldr r0, [r4, #0] +10007d20: 62c4 str r4, [r0, #44] ; 0x2c +10007d22: bd10 pop {r4, pc} + +10007d24 : +10007d24: f06f 0005 mvn.w r0, #5 + +10007d28 : +10007d28: 7120 strb r0, [r4, #4] + +10007d2a : +10007d2a: e1bb b.n 100080a4 + +10007d2c : +10007d2c: b538 push {r3, r4, r5, lr} +10007d2e: f000 f861 bl 10007df4 + +10007d32 : +10007d32: db47 blt.n 10007dc4 +10007d34: f06f 000c mvn.w r0, #12 +10007d38: 7120 strb r0, [r4, #4] +10007d3a: 6888 ldr r0, [r1, #8] +10007d3c: 2800 cmp r0, #0 +10007d3e: d042 beq.n 10007dc6 +10007d40: 680a ldr r2, [r1, #0] +10007d42: 2a10 cmp r2, #16 +10007d44: d13c bne.n 10007dc0 +10007d46: 6849 ldr r1, [r1, #4] +10007d48: 2900 cmp r1, #0 +10007d4a: d13c bne.n 10007dc6 +10007d4c: 21ff movs r1, #255 ; 0xff +10007d4e: f000 ffcf bl 10008cf0 +10007d52: 0005 movs r5, r0 +10007d54: bf08 it eq +10007d56: f04f 30ff moveq.w r0, #4294967295 +10007d5a: d033 beq.n 10007dc4 +10007d5c: 6820 ldr r0, [r4, #0] +10007d5e: 3014 adds r0, #20 +10007d60: f000 fa0a bl 10008178 +10007d64: b138 cbz r0, 10007d76 +10007d66: 6820 ldr r0, [r4, #0] +10007d68: 3014 adds r0, #20 +10007d6a: f000 f9af bl 100080cc +10007d6e: 6820 ldr r0, [r4, #0] +10007d70: 3014 adds r0, #20 +10007d72: f000 fa02 bl 1000817a + +10007d76 : +10007d76: 2000 movs r0, #0 +10007d78: 7120 strb r0, [r4, #4] +10007d7a: 6820 ldr r0, [r4, #0] +10007d7c: 3018 adds r0, #24 +10007d7e: f000 f9fb bl 10008178 +10007d82: b930 cbnz r0, 10007d92 +10007d84: 6820 ldr r0, [r4, #0] +10007d86: f44f 61fa mov.w r1, #2000 ; 0x7d0 +10007d8a: 3018 adds r0, #24 +10007d8c: f000 f990 bl 100080b0 +10007d90: 7120 strb r0, [r4, #4] + +10007d92 : +10007d92: f994 0004 ldrsb.w r0, [r4, #4] +10007d96: b960 cbnz r0, 10007db2 +10007d98: 6821 ldr r1, [r4, #0] +10007d9a: 2002 movs r0, #2 +10007d9c: 6048 str r0, [r1, #4] +10007d9e: 608d str r5, [r1, #8] +10007da0: 4628 mov r0, r5 +10007da2: f001 fb11 bl 100093c8 +10007da6: 6820 ldr r0, [r4, #0] +10007da8: 4911 ldr r1, [pc, #68] ; (10007df0 ) +10007daa: 6880 ldr r0, [r0, #8] +10007dac: f001 fb17 bl 100093de +10007db0: e009 b.n 10007dc6 + +10007db2 : +10007db2: 4628 mov r0, r5 +10007db4: f000 fee8 bl 10008b88 +10007db8: 6821 ldr r1, [r4, #0] +10007dba: 2000 movs r0, #0 +10007dbc: 6088 str r0, [r1, #8] +10007dbe: e002 b.n 10007dc6 + +10007dc0 : +10007dc0: f06f 000d mvn.w r0, #13 + +10007dc4 : +10007dc4: 7120 strb r0, [r4, #4] + +10007dc6 : +10007dc6: 6820 ldr r0, [r4, #0] +10007dc8: e8bd 4032 ldmia.w sp!, {r1, r4, r5, lr} +10007dcc: e16d b.n 100080aa + ... + +10007dd0 : +10007dd0: 7704 1004 .w.. + +10007dd4 : +10007dd4: 7629 1000 )v.. + +10007dd8 : +10007dd8: 76e3 1000 .v.. + +10007ddc : +10007ddc: 768b 1000 .v.. + +10007de0 : +10007de0: 7743 1000 Cw.. + +10007de4 : +10007de4: 75c5 1000 .u.. + +10007de8 : +10007de8: 7555 1000 Uu.. + +10007dec : +10007dec: 7c2b 1000 +|.. + +10007df0 : +10007df0: 7813 1000 .x.. + +10007df4 : +10007df4: 4604 mov r4, r0 +10007df6: 6821 ldr r1, [r4, #0] +10007df8: f991 000c ldrsb.w r0, [r1, #12] +10007dfc: f110 0f09 cmn.w r0, #9 +10007e00: 4770 bx lr + +10007e02 : +10007e02: b510 push {r4, lr} +10007e04: f7ff fff6 bl 10007df4 + +10007e08 : +10007e08: db2d blt.n 10007e66 +10007e0a: f06f 000c mvn.w r0, #12 +10007e0e: 7120 strb r0, [r4, #4] +10007e10: 6888 ldr r0, [r1, #8] +10007e12: b348 cbz r0, 10007e68 +10007e14: 7809 ldrb r1, [r1, #0] +10007e16: f001 01f0 and.w r1, r1, #240 ; 0xf0 +10007e1a: 2920 cmp r1, #32 +10007e1c: d012 beq.n 10007e44 +10007e1e: 2940 cmp r1, #64 ; 0x40 +10007e20: d122 bne.n 10007e68 +10007e22: 68a1 ldr r1, [r4, #8] +10007e24: f111 0208 adds.w r2, r1, #8 +10007e28: bf1c itt ne +10007e2a: 688a ldrne r2, [r1, #8] +10007e2c: 2a00 cmpne r2, #0 +10007e2e: d103 bne.n 10007e38 +10007e30: 6809 ldr r1, [r1, #0] +10007e32: f001 fdd6 bl 100099e2 +10007e36: e016 b.n 10007e66 + +10007e38 : +10007e38: f101 0208 add.w r2, r1, #8 +10007e3c: 6809 ldr r1, [r1, #0] +10007e3e: f001 fd8b bl 10009958 +10007e42: e010 b.n 10007e66 + +10007e44 : +10007e44: 68a1 ldr r1, [r4, #8] +10007e46: f111 0208 adds.w r2, r1, #8 +10007e4a: bf1c itt ne +10007e4c: 688a ldrne r2, [r1, #8] +10007e4e: 2a00 cmpne r2, #0 +10007e50: d103 bne.n 10007e5a +10007e52: 6809 ldr r1, [r1, #0] +10007e54: f001 fc21 bl 1000969a +10007e58: e005 b.n 10007e66 + +10007e5a : +10007e5a: 898b ldrh r3, [r1, #12] +10007e5c: f101 0208 add.w r2, r1, #8 +10007e60: 6809 ldr r1, [r1, #0] +10007e62: f001 fc1c bl 1000969e + +10007e66 : +10007e66: 7120 strb r0, [r4, #4] + +10007e68 : +10007e68: e11c b.n 100080a4 + +10007e6a : +10007e6a: b570 push {r4, r5, r6, lr} +10007e6c: f000 f817 bl 10007e9e + +10007e70 : +10007e70: b189 cbz r1, 10007e96 +10007e72: 6800 ldr r0, [r0, #0] +10007e74: 2810 cmp r0, #16 +10007e76: d10e bne.n 10007e96 +10007e78: 68a5 ldr r5, [r4, #8] + +10007e7a : +10007e7a: f5b5 3f80 cmp.w r5, #65536 ; 0x10000 +10007e7e: bf2c ite cs +10007e80: f64f 76ff movwcs r6, #65535 ; 0xffff +10007e84: 462e movcc r6, r5 +10007e86: 6820 ldr r0, [r4, #0] +10007e88: 6880 ldr r0, [r0, #8] +10007e8a: b2b1 uxth r1, r6 +10007e8c: f000 ff87 bl 10008d9e +10007e90: b2b6 uxth r6, r6 +10007e92: 1bad subs r5, r5, r6 +10007e94: d1f1 bne.n 10007e7a + +10007e96 : +10007e96: 6820 ldr r0, [r4, #0] +10007e98: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +10007e9c: e105 b.n 100080aa + +10007e9e : +10007e9e: 4604 mov r4, r0 +10007ea0: 2000 movs r0, #0 +10007ea2: 7120 strb r0, [r4, #4] +10007ea4: 6820 ldr r0, [r4, #0] +10007ea6: 6881 ldr r1, [r0, #8] +10007ea8: 4770 bx lr + +10007eaa : +10007eaa: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +10007eae: 4680 mov r8, r0 +10007eb0: f108 0724 add.w r7, r8, #36 ; 0x24 +10007eb4: 68b8 ldr r0, [r7, #8] +10007eb6: f898 1024 ldrb.w r1, [r8, #36] ; 0x24 +10007eba: 7c03 ldrb r3, [r0, #16] +10007ebc: 2600 movs r6, #0 +10007ebe: 0789 lsls r1, r1, #30 +10007ec0: bf5a itte pl +10007ec2: 0899 lsrpl r1, r3, #2 +10007ec4: f001 0501 andpl.w r5, r1, #1 +10007ec8: 2501 movmi r5, #1 +10007eca: 6881 ldr r1, [r0, #8] +10007ecc: 687a ldr r2, [r7, #4] +10007ece: 68c0 ldr r0, [r0, #12] +10007ed0: 1851 adds r1, r2, r1 +10007ed2: 1a84 subs r4, r0, r2 +10007ed4: f5b4 3f80 cmp.w r4, #65536 ; 0x10000 +10007ed8: bf24 itt cs +10007eda: f64f 74ff movwcs r4, #65535 ; 0xffff +10007ede: f043 0302 orrcs.w r3, r3, #2 +10007ee2: f108 0904 add.w r9, r8, #4 +10007ee6: b2a4 uxth r4, r4 +10007ee8: f8d9 0004 ldr.w r0, [r9, #4] +10007eec: f8b0 206a ldrh.w r2, [r0, #106] ; 0x6a +10007ef0: 42a2 cmp r2, r4 +10007ef2: d207 bcs.n 10007f04 +10007ef4: 4614 mov r4, r2 +10007ef6: b11d cbz r5, 10007f00 +10007ef8: b924 cbnz r4, 10007f04 +10007efa: f06f 0a06 mvn.w sl, #6 +10007efe: e00b b.n 10007f18 + +10007f00 : +10007f00: f043 0302 orr.w r3, r3, #2 + +10007f04 : +10007f04: 4622 mov r2, r4 +10007f06: f001 fe75 bl 10009bf4 +10007f0a: ea5f 0a00 movs.w sl, r0 +10007f0e: bf18 it ne +10007f10: f11a 0f01 cmnne.w sl, #1 +10007f14: d135 bne.n 10007f82 +10007f16: b18d cbz r5, 10007f3c + +10007f18 : +10007f18: 68b8 ldr r0, [r7, #8] +10007f1a: 68c0 ldr r0, [r0, #12] +10007f1c: 4284 cmp r4, r0 +10007f1e: d20d bcs.n 10007f3c +10007f20: 68fb ldr r3, [r7, #12] +10007f22: 0018 movs r0, r3 +10007f24: d003 beq.n 10007f2e +10007f26: 4622 mov r2, r4 +10007f28: 2103 movs r1, #3 +10007f2a: 4640 mov r0, r8 +10007f2c: 4798 blx r3 + +10007f2e : +10007f2e: f898 0024 ldrb.w r0, [r8, #36] ; 0x24 +10007f32: f040 0010 orr.w r0, r0, #16 +10007f36: f888 0024 strb.w r0, [r8, #36] ; 0x24 +10007f3a: e012 b.n 10007f62 + +10007f3c : +10007f3c: f640 6243 movw r2, #3651 ; 0xe43 +10007f40: f8d9 0004 ldr.w r0, [r9, #4] +10007f44: f8b0 106a ldrh.w r1, [r0, #106] ; 0x6a +10007f48: 4291 cmp r1, r2 +10007f4a: db03 blt.n 10007f54 +10007f4c: f8b0 006c ldrh.w r0, [r0, #108] ; 0x6c +10007f50: 280a cmp r0, #10 +10007f52: db06 blt.n 10007f62 + +10007f54 : +10007f54: 68fb ldr r3, [r7, #12] +10007f56: 0018 movs r0, r3 +10007f58: d003 beq.n 10007f62 +10007f5a: 4622 mov r2, r4 +10007f5c: 2103 movs r1, #3 +10007f5e: 4640 mov r0, r8 +10007f60: 4798 blx r3 + +10007f62 : +10007f62: f1ba 0f00 cmp.w sl, #0 +10007f66: d10c bne.n 10007f82 +10007f68: 6878 ldr r0, [r7, #4] +10007f6a: 1820 adds r0, r4, r0 +10007f6c: 6078 str r0, [r7, #4] +10007f6e: 68b9 ldr r1, [r7, #8] +10007f70: 68ca ldr r2, [r1, #12] +10007f72: 4290 cmp r0, r2 +10007f74: d000 beq.n 10007f78 +10007f76: b14d cbz r5, 10007f8c + +10007f78 : +10007f78: 60c8 str r0, [r1, #12] +10007f7a: 2601 movs r6, #1 +10007f7c: 2000 movs r0, #0 +10007f7e: 6078 str r0, [r7, #4] +10007f80: e004 b.n 10007f8c + +10007f82 : +10007f82: f11a 0f01 cmn.w sl, #1 +10007f86: bf08 it eq +10007f88: 2d00 cmpeq r5, #0 +10007f8a: d105 bne.n 10007f98 + +10007f8c : +10007f8c: f8d9 0004 ldr.w r0, [r9, #4] +10007f90: f002 f83d bl 1000a00e +10007f94: b916 cbnz r6, 10007f9c +10007f96: e00c b.n 10007fb2 + +10007f98 : +10007f98: 68b9 ldr r1, [r7, #8] +10007f9a: 60ce str r6, [r1, #12] + +10007f9c : +10007f9c: 68b8 ldr r0, [r7, #8] +10007f9e: f880 a004 strb.w sl, [r0, #4] +10007fa2: 2000 movs r0, #0 +10007fa4: 60b8 str r0, [r7, #8] +10007fa6: f8c8 0004 str.w r0, [r8, #4] +10007faa: f108 0010 add.w r0, r8, #16 +10007fae: f000 f91e bl 100081ee + +10007fb2 : +10007fb2: 2000 movs r0, #0 +10007fb4: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + +10007fb8 : +10007fb8: 6801 ldr r1, [r0, #0] +10007fba: f991 200c ldrsb.w r2, [r1, #12] +10007fbe: f112 0f09 cmn.w r2, #9 +10007fc2: db15 blt.n 10007ff0 +10007fc4: 680a ldr r2, [r1, #0] +10007fc6: 2a10 cmp r2, #16 +10007fc8: d110 bne.n 10007fec +10007fca: 684a ldr r2, [r1, #4] +10007fcc: b112 cbz r2, 10007fd4 +10007fce: f06f 0204 mvn.w r2, #4 +10007fd2: e00d b.n 10007ff0 + +10007fd4 : +10007fd4: 688a ldr r2, [r1, #8] +10007fd6: b132 cbz r2, 10007fe6 +10007fd8: 2201 movs r2, #1 +10007fda: 604a str r2, [r1, #4] +10007fdc: 62c8 str r0, [r1, #44] ; 0x2c +10007fde: 2000 movs r0, #0 +10007fe0: 6288 str r0, [r1, #40] ; 0x28 +10007fe2: 4608 mov r0, r1 +10007fe4: e761 b.n 10007eaa + +10007fe6 : +10007fe6: f06f 020c mvn.w r2, #12 +10007fea: e001 b.n 10007ff0 + +10007fec : +10007fec: f06f 0205 mvn.w r2, #5 + +10007ff0 : +10007ff0: 7102 strb r2, [r0, #4] +10007ff2: 6800 ldr r0, [r0, #0] +10007ff4: e059 b.n 100080aa + +10007ff6 : +10007ff6: b510 push {r4, lr} +10007ff8: 6802 ldr r2, [r0, #0] +10007ffa: 6893 ldr r3, [r2, #8] +10007ffc: f06f 010c mvn.w r1, #12 +10008000: b35b cbz r3, 1000805a +10008002: 7c04 ldrb r4, [r0, #16] +10008004: 2c00 cmp r4, #0 +10008006: bf14 ite ne +10008008: 681a ldrne r2, [r3, #0] +1000800a: 685a ldreq r2, [r3, #4] +1000800c: 6883 ldr r3, [r0, #8] +1000800e: 601a str r2, [r3, #0] +10008010: 2200 movs r2, #0 +10008012: 7102 strb r2, [r0, #4] +10008014: 6802 ldr r2, [r0, #0] +10008016: 7813 ldrb r3, [r2, #0] +10008018: f003 03f0 and.w r3, r3, #240 ; 0xf0 +1000801c: 2b10 cmp r3, #16 +1000801e: d013 beq.n 10008048 +10008020: 2b20 cmp r3, #32 +10008022: d006 beq.n 10008032 +10008024: 2b40 cmp r3, #64 ; 0x40 +10008026: d119 bne.n 1000805c +10008028: 7c03 ldrb r3, [r0, #16] +1000802a: b1b3 cbz r3, 1000805a +1000802c: 6891 ldr r1, [r2, #8] +1000802e: 7c09 ldrb r1, [r1, #16] +10008030: e010 b.n 10008054 + +10008032 : +10008032: 7c03 ldrb r3, [r0, #16] +10008034: b113 cbz r3, 1000803c +10008036: 6891 ldr r1, [r2, #8] +10008038: 8a49 ldrh r1, [r1, #18] +1000803a: e00b b.n 10008054 + +1000803c : +1000803c: 6892 ldr r2, [r2, #8] +1000803e: 7c13 ldrb r3, [r2, #16] +10008040: 075b lsls r3, r3, #29 +10008042: d50a bpl.n 1000805a +10008044: 8a91 ldrh r1, [r2, #20] +10008046: e005 b.n 10008054 + +10008048 : +10008048: 7c01 ldrb r1, [r0, #16] +1000804a: 2900 cmp r1, #0 +1000804c: 6891 ldr r1, [r2, #8] +1000804e: bf14 ite ne +10008050: 8bc9 ldrhne r1, [r1, #30] +10008052: 8c09 ldrheq r1, [r1, #32] + +10008054 : +10008054: 68c2 ldr r2, [r0, #12] +10008056: 8011 strh r1, [r2, #0] +10008058: e000 b.n 1000805c + +1000805a : +1000805a: 7101 strb r1, [r0, #4] + +1000805c : +1000805c: 6800 ldr r0, [r0, #0] +1000805e: e022 b.n 100080a6 + +10008060 : +10008060: b510 push {r4, lr} +10008062: 4604 mov r4, r0 +10008064: 6820 ldr r0, [r4, #0] +10008066: 6841 ldr r1, [r0, #4] +10008068: 2900 cmp r1, #0 +1000806a: bf1c itt ne +1000806c: 2902 cmpne r1, #2 +1000806e: f06f 0004 mvnne.w r0, #4 +10008072: d116 bne.n 100080a2 +10008074: 6882 ldr r2, [r0, #8] +10008076: b192 cbz r2, 1000809e +10008078: 6802 ldr r2, [r0, #0] +1000807a: 2a10 cmp r2, #16 +1000807c: d10f bne.n 1000809e +1000807e: 7a22 ldrb r2, [r4, #8] +10008080: 2a03 cmp r2, #3 +10008082: d004 beq.n 1000808e +10008084: 2902 cmp r1, #2 +10008086: bf08 it eq +10008088: f06f 000c mvneq.w r0, #12 +1000808c: d009 beq.n 100080a2 + +1000808e : +1000808e: 07d1 lsls r1, r2, #31 +10008090: bf48 it mi +10008092: f7ff fca8 blmi 100079e6 +10008096: 6820 ldr r0, [r4, #0] +10008098: 2104 movs r1, #4 +1000809a: 6041 str r1, [r0, #4] +1000809c: e5a0 b.n 10007be0 + +1000809e : +1000809e: f06f 0005 mvn.w r0, #5 + +100080a2 : +100080a2: 7120 strb r0, [r4, #4] + +100080a4 : +100080a4: 6820 ldr r0, [r4, #0] + +100080a6 : +100080a6: e8bd 4010 ldmia.w sp!, {r4, lr} + +100080aa : +100080aa: 3010 adds r0, #16 +100080ac: f000 b89f b.w 100081ee + +100080b0 : +100080b0: b510 push {r4, lr} +100080b2: 4604 mov r4, r0 +100080b4: 2200 movs r2, #0 +100080b6: 2104 movs r1, #4 +100080b8: 2006 movs r0, #6 +100080ba: f002 fa13 bl 1000a4e4 +100080be: 6020 str r0, [r4, #0] +100080c0: b910 cbnz r0, 100080c8 +100080c2: f04f 30ff mov.w r0, #4294967295 +100080c6: bd10 pop {r4, pc} + +100080c8 : +100080c8: 2000 movs r0, #0 +100080ca: bd10 pop {r4, pc} + +100080cc : +100080cc: b510 push {r4, lr} +100080ce: 4604 mov r4, r0 +100080d0: 6820 ldr r0, [r4, #0] +100080d2: f002 fb72 bl 1000a7ba +100080d6: 6820 ldr r0, [r4, #0] +100080d8: e8bd 4010 ldmia.w sp!, {r4, lr} +100080dc: f002 bb76 b.w 1000a7cc + +100080e0 : +100080e0: b513 push {r0, r1, r4, lr} +100080e2: 4604 mov r4, r0 + +100080e4 : +100080e4: f000 f834 bl 10008150 + +100080e8 : +100080e8: a901 add r1, sp, #4 +100080ea: f002 fa47 bl 1000a57c +100080ee: 2801 cmp r0, #1 +100080f0: d1f8 bne.n 100080e4 +100080f2: bd13 pop {r0, r1, r4, pc} + +100080f4 : +100080f4: b502 push {r1, lr} +100080f6: 6800 ldr r0, [r0, #0] +100080f8: 2300 movs r3, #0 +100080fa: 2200 movs r2, #0 +100080fc: a900 add r1, sp, #0 +100080fe: f002 fa3d bl 1000a57c +10008102: 2801 cmp r0, #1 +10008104: d101 bne.n 1000810a +10008106: 2000 movs r0, #0 +10008108: bd02 pop {r1, pc} + +1000810a : +1000810a: e032 b.n 10008172 + +1000810c : +1000810c: b5f8 push {r3, r4, r5, r6, r7, lr} +1000810e: 4604 mov r4, r0 +10008110: 460d mov r5, r1 +10008112: 4616 mov r6, r2 +10008114: f002 fdf1 bl 1000acfa +10008118: 4607 mov r7, r0 +1000811a: b905 cbnz r5, 1000811e +1000811c: ad00 add r5, sp, #0 + +1000811e : +1000811e: b166 cbz r6, 1000813a +10008120: 6820 ldr r0, [r4, #0] +10008122: 2300 movs r3, #0 +10008124: 4632 mov r2, r6 +10008126: 4629 mov r1, r5 +10008128: f002 fac0 bl 1000a6ac +1000812c: 2801 cmp r0, #1 +1000812e: d00b beq.n 10008148 +10008130: 2000 movs r0, #0 +10008132: 6028 str r0, [r5, #0] +10008134: f04f 30ff mov.w r0, #4294967295 +10008138: bdf2 pop {r1, r4, r5, r6, r7, pc} + +1000813a : +1000813a: f000 f809 bl 10008150 + +1000813e : +1000813e: 4629 mov r1, r5 +10008140: f002 fab4 bl 1000a6ac +10008144: 2801 cmp r0, #1 +10008146: d1f8 bne.n 1000813a + +10008148 : +10008148: f002 fdd7 bl 1000acfa +1000814c: 1bc0 subs r0, r0, r7 +1000814e: bdf2 pop {r1, r4, r5, r6, r7, pc} + +10008150 : +10008150: 6820 ldr r0, [r4, #0] +10008152: 2300 movs r3, #0 +10008154: f04f 32ff mov.w r2, #4294967295 +10008158: 4770 bx lr + +1000815a : +1000815a: b580 push {r7, lr} +1000815c: b901 cbnz r1, 10008160 +1000815e: a900 add r1, sp, #0 + +10008160 : +10008160: 6800 ldr r0, [r0, #0] +10008162: 2300 movs r3, #0 +10008164: 2200 movs r2, #0 +10008166: f002 faa1 bl 1000a6ac +1000816a: 2801 cmp r0, #1 +1000816c: d101 bne.n 10008172 +1000816e: 2000 movs r0, #0 +10008170: bd02 pop {r1, pc} + +10008172 : +10008172: f04f 30ff mov.w r0, #4294967295 +10008176: bd02 pop {r1, pc} + +10008178 : +10008178: e043 b.n 10008202 + +1000817a : +1000817a: e047 b.n 1000820c + +1000817c : +1000817c: b538 push {r3, r4, r5, lr} +1000817e: 4604 mov r4, r0 +10008180: 460d mov r5, r1 +10008182: 2203 movs r2, #3 +10008184: 2100 movs r1, #0 +10008186: 2001 movs r0, #1 +10008188: f002 f9ac bl 1000a4e4 +1000818c: 6020 str r0, [r4, #0] +1000818e: b130 cbz r0, 1000819e +10008190: 2200 movs r2, #0 +10008192: 2300 movs r3, #0 +10008194: 4611 mov r1, r2 +10008196: f002 f9f1 bl 1000a57c +1000819a: 6820 ldr r0, [r4, #0] +1000819c: b910 cbnz r0, 100081a4 + +1000819e : +1000819e: f04f 30ff mov.w r0, #4294967295 +100081a2: bd32 pop {r1, r4, r5, pc} + +100081a4 : +100081a4: b925 cbnz r5, 100081b0 +100081a6: 2300 movs r3, #0 +100081a8: 2201 movs r2, #1 +100081aa: 2100 movs r1, #0 +100081ac: f002 fa7e bl 1000a6ac + +100081b0 : +100081b0: 2000 movs r0, #0 +100081b2: bd32 pop {r1, r4, r5, pc} + +100081b4 : +100081b4: b570 push {r4, r5, r6, lr} +100081b6: 4604 mov r4, r0 +100081b8: 460d mov r5, r1 +100081ba: f002 fd9e bl 1000acfa +100081be: 4606 mov r6, r0 +100081c0: b155 cbz r5, 100081d8 +100081c2: 6820 ldr r0, [r4, #0] +100081c4: 2300 movs r3, #0 +100081c6: 462a mov r2, r5 +100081c8: 2100 movs r1, #0 +100081ca: f002 fa6f bl 1000a6ac +100081ce: 2801 cmp r0, #1 +100081d0: d009 beq.n 100081e6 +100081d2: f04f 30ff mov.w r0, #4294967295 +100081d6: bd70 pop {r4, r5, r6, pc} + +100081d8 : +100081d8: f7ff ffba bl 10008150 + +100081dc : +100081dc: 2100 movs r1, #0 +100081de: f002 fa65 bl 1000a6ac +100081e2: 2801 cmp r0, #1 +100081e4: d1f8 bne.n 100081d8 + +100081e6 : +100081e6: f002 fd88 bl 1000acfa +100081ea: 1b80 subs r0, r0, r6 +100081ec: bd70 pop {r4, r5, r6, pc} + +100081ee : +100081ee: 2200 movs r2, #0 +100081f0: 6800 ldr r0, [r0, #0] +100081f2: 2300 movs r3, #0 +100081f4: 4611 mov r1, r2 +100081f6: f002 b9c1 b.w 1000a57c + +100081fa : +100081fa: 6800 ldr r0, [r0, #0] +100081fc: f002 bae6 b.w 1000a7cc + +10008200 : +10008200: bf00 nop + +10008202 : +10008202: 6800 ldr r0, [r0, #0] +10008204: b100 cbz r0, 10008208 +10008206: 2001 movs r0, #1 + +10008208 : +10008208: 4770 bx lr + +1000820a : +1000820a: bf00 nop + +1000820c : +1000820c: 2100 movs r1, #0 +1000820e: 6001 str r1, [r0, #0] +10008210: 4770 bx lr + +10008212 : +10008212: 2000 movs r0, #0 +10008214: 491b ldr r1, [pc, #108] ; (10008284 ) +10008216: 2300 movs r3, #0 + +10008218 : +10008218: eb01 02c0 add.w r2, r1, r0, lsl #3 +1000821c: 1c40 adds r0, r0, #1 +1000821e: 6093 str r3, [r2, #8] +10008220: 6053 str r3, [r2, #4] +10008222: 2806 cmp r0, #6 +10008224: dbf8 blt.n 10008218 +10008226: 800b strh r3, [r1, #0] +10008228: 4770 bx lr + +1000822a : +1000822a: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1000822e: 4c15 ldr r4, [pc, #84] ; (10008284 ) +10008230: 4605 mov r5, r0 +10008232: 8820 ldrh r0, [r4, #0] +10008234: b086 sub sp, #24 +10008236: 460e mov r6, r1 +10008238: 4690 mov r8, r2 +1000823a: 461f mov r7, r3 +1000823c: 2806 cmp r0, #6 +1000823e: da1c bge.n 1000827a +10008240: f002 fff6 bl 1000b230 +10008244: 2000 movs r0, #0 +10008246: 9003 str r0, [sp, #12] +10008248: 9002 str r0, [sp, #8] +1000824a: 4643 mov r3, r8 +1000824c: a804 add r0, sp, #16 +1000824e: 9001 str r0, [sp, #4] +10008250: b2ba uxth r2, r7 +10008252: 980c ldr r0, [sp, #48] ; 0x30 +10008254: 9000 str r0, [sp, #0] +10008256: 4629 mov r1, r5 +10008258: 4630 mov r0, r6 +1000825a: f002 fb65 bl 1000a928 +1000825e: 4605 mov r5, r0 +10008260: 8820 ldrh r0, [r4, #0] +10008262: 9904 ldr r1, [sp, #16] +10008264: eb04 02c0 add.w r2, r4, r0, lsl #3 +10008268: 1c40 adds r0, r0, #1 +1000826a: 6091 str r1, [r2, #8] +1000826c: 8020 strh r0, [r4, #0] +1000826e: f002 ffeb bl 1000b248 +10008272: 2d01 cmp r5, #1 +10008274: bf08 it eq +10008276: 9804 ldreq r0, [sp, #16] +10008278: d000 beq.n 1000827c + +1000827a : +1000827a: 2000 movs r0, #0 + +1000827c : +1000827c: b006 add sp, #24 +1000827e: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + ... + +10008284 : +10008284: 79c0 1004 .y.. + +10008288 : +10008288: b580 push {r7, lr} +1000828a: f002 ffd1 bl 1000b230 +1000828e: 2001 movs r0, #1 +10008290: bd02 pop {r1, pc} + +10008292 : +10008292: f002 bfd9 b.w 1000b248 + ... + +10008298 : +10008298: b570 push {r4, r5, r6, lr} +1000829a: 2000 movs r0, #0 + +1000829c : +1000829c: 1c40 adds r0, r0, #1 +1000829e: 280e cmp r0, #14 +100082a0: dbfc blt.n 1000829c +100082a2: 4822 ldr r0, [pc, #136] ; (1000832c ) +100082a4: f20f 0388 addw r3, pc, #136 ; 0x88 +100082a8: f20f 04a0 addw r4, pc, #160 ; 0xa0 +100082ac: f100 013b add.w r1, r0, #59 ; 0x3b +100082b0: 0889 lsrs r1, r1, #2 +100082b2: 0089 lsls r1, r1, #2 +100082b4: 2200 movs r2, #0 + +100082b6 : +100082b6: 2500 movs r5, #0 +100082b8: f840 5022 str.w r5, [r0, r2, lsl #2] +100082bc: e008 b.n 100082d0 + +100082be : +100082be: f850 6022 ldr.w r6, [r0, r2, lsl #2] +100082c2: 600e str r6, [r1, #0] +100082c4: f840 1022 str.w r1, [r0, r2, lsl #2] +100082c8: 1c6d adds r5, r5, #1 +100082ca: f833 6012 ldrh.w r6, [r3, r2, lsl #1] +100082ce: 1871 adds r1, r6, r1 + +100082d0 : +100082d0: f834 6012 ldrh.w r6, [r4, r2, lsl #1] +100082d4: b2ad uxth r5, r5 +100082d6: 42b5 cmp r5, r6 +100082d8: d3f1 bcc.n 100082be +100082da: 1c52 adds r2, r2, #1 +100082dc: 2a0e cmp r2, #14 +100082de: dbea blt.n 100082b6 +100082e0: bd70 pop {r4, r5, r6, pc} + +100082e2 : +100082e2: b538 push {r3, r4, r5, lr} +100082e4: 4604 mov r4, r0 +100082e6: 2c0e cmp r4, #14 +100082e8: db01 blt.n 100082ee +100082ea: 2000 movs r0, #0 +100082ec: bd32 pop {r1, r4, r5, pc} + +100082ee : +100082ee: f7ff ffcb bl 10008288 +100082f2: 490e ldr r1, [pc, #56] ; (1000832c ) +100082f4: f851 5024 ldr.w r5, [r1, r4, lsl #2] +100082f8: b115 cbz r5, 10008300 +100082fa: 682a ldr r2, [r5, #0] +100082fc: f841 2024 str.w r2, [r1, r4, lsl #2] + +10008300 : +10008300: f7ff ffc7 bl 10008292 +10008304: 4628 mov r0, r5 +10008306: bd32 pop {r1, r4, r5, pc} + +10008308 : +10008308: b538 push {r3, r4, r5, lr} +1000830a: 4604 mov r4, r0 +1000830c: 000d movs r5, r1 +1000830e: d00b beq.n 10008328 +10008310: f7ff ffba bl 10008288 +10008314: 4905 ldr r1, [pc, #20] ; (1000832c ) +10008316: f851 2024 ldr.w r2, [r1, r4, lsl #2] +1000831a: 602a str r2, [r5, #0] +1000831c: f841 5024 str.w r5, [r1, r4, lsl #2] +10008320: e8bd 4032 ldmia.w sp!, {r1, r4, r5, lr} +10008324: f7ff bfb5 b.w 10008292 + +10008328 : +10008328: bd31 pop {r0, r4, r5, pc} + ... + +1000832c : +1000832c: 1424 1fff $... + +10008330 : +10008330: 001c 0020 009c 0020 0014 0020 0018 0010 .. ... ... ..... +10008340: 0034 0014 0014 0010 0010 0204 4........... + +1000834c : +1000834c: 0004 0006 000a 0005 0014 0005 000f 0002 ................ +1000835c: 0008 0008 0008 000a 0064 0014 ........d... + +10008368 : +10008368: b510 push {r4, lr} +1000836a: 4c79 ldr r4, [pc, #484] ; (10008550 ) +1000836c: 6821 ldr r1, [r4, #0] +1000836e: b082 sub sp, #8 +10008370: 0008 movs r0, r1 +10008372: d009 beq.n 10008388 +10008374: 6860 ldr r0, [r4, #4] +10008376: 4788 blx r1 +10008378: e006 b.n 10008388 + +1000837a : +1000837a: 9900 ldr r1, [sp, #0] +1000837c: 9800 ldr r0, [sp, #0] +1000837e: 6889 ldr r1, [r1, #8] +10008380: 6880 ldr r0, [r0, #8] +10008382: 6809 ldr r1, [r1, #0] +10008384: 1d00 adds r0, r0, #4 +10008386: 4788 blx r1 + +10008388 : +10008388: a900 add r1, sp, #0 +1000838a: f104 0008 add.w r0, r4, #8 +1000838e: f003 f8e6 bl 1000b55e +10008392: 9800 ldr r0, [sp, #0] +10008394: 6800 ldr r0, [r0, #0] +10008396: 2805 cmp r0, #5 +10008398: d8f6 bhi.n 10008388 +1000839a: e8df f000 tbb [pc, r0] + +1000839e : +1000839e: 0503 2219 2b28 ..."(+ + +100083a4 : +100083a4: e7e9 b.n 1000837a + +100083a6 : +100083a6: e7ef b.n 10008388 + +100083a8 : +100083a8: 9800 ldr r0, [sp, #0] +100083aa: 68c0 ldr r0, [r0, #12] +100083ac: f890 0031 ldrb.w r0, [r0, #49] ; 0x31 +100083b0: 2160 movs r1, #96 ; 0x60 +100083b2: 4208 tst r0, r1 +100083b4: 9800 ldr r0, [sp, #0] +100083b6: 68c1 ldr r1, [r0, #12] +100083b8: 6880 ldr r0, [r0, #8] +100083ba: d002 beq.n 100083c2 +100083bc: f003 fc28 bl 1000bc10 +100083c0: e001 b.n 100083c6 + +100083c2 : +100083c2: f003 fc8d bl 1000bce0 + +100083c6 : +100083c6: 9900 ldr r1, [sp, #0] +100083c8: 200a movs r0, #10 + +100083ca : +100083ca: f7ff ff9d bl 10008308 +100083ce: e7db b.n 10008388 + +100083d0 : +100083d0: 9800 ldr r0, [sp, #0] +100083d2: 6902 ldr r2, [r0, #16] +100083d4: 68c1 ldr r1, [r0, #12] +100083d6: 6880 ldr r0, [r0, #8] +100083d8: f003 f876 bl 1000b4c8 + +100083dc : +100083dc: 9900 ldr r1, [sp, #0] +100083de: 2009 movs r0, #9 +100083e0: e7f3 b.n 100083ca + +100083e2 : +100083e2: 9800 ldr r0, [sp, #0] +100083e4: 6901 ldr r1, [r0, #16] +100083e6: 68c0 ldr r0, [r0, #12] +100083e8: f003 f897 bl 1000b51a +100083ec: e7f6 b.n 100083dc + +100083ee : +100083ee: f000 f804 bl 100083fa + +100083f2 : +100083f2: e7f3 b.n 100083dc + +100083f4 : +100083f4: f000 f801 bl 100083fa + +100083f8 : +100083f8: e7c6 b.n 10008388 + +100083fa : +100083fa: 9800 ldr r0, [sp, #0] +100083fc: 9900 ldr r1, [sp, #0] +100083fe: 68c0 ldr r0, [r0, #12] +10008400: 6889 ldr r1, [r1, #8] + +10008402 <__iar_annotation$$tailcall>: +10008402: 4708 bx r1 + +10008404 : +10008404: b5f8 push {r3, r4, r5, r6, r7, lr} +10008406: f000 f866 bl 100084d6 + +1000840a : +1000840a: b900 cbnz r0, 1000840e +1000840c: e05d b.n 100084ca + +1000840e : +1000840e: 200a movs r0, #10 +10008410: f7ff ff67 bl 100082e2 +10008414: 0007 movs r7, r0 +10008416: d00d beq.n 10008434 +10008418: 2001 movs r0, #1 +1000841a: 6038 str r0, [r7, #0] +1000841c: 60bc str r4, [r7, #8] +1000841e: 60fd str r5, [r7, #12] +10008420: 4639 mov r1, r7 +10008422: f106 0008 add.w r0, r6, #8 +10008426: f7ff fe65 bl 100080f4 +1000842a: b128 cbz r0, 10008438 +1000842c: 4639 mov r1, r7 +1000842e: 200a movs r0, #10 +10008430: f7ff ff6a bl 10008308 + +10008434 : +10008434: f04f 30ff mov.w r0, #4294967295 + +10008438 : +10008438: bdf2 pop {r1, r4, r5, r6, r7, pc} + +1000843a : +1000843a: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1000843e: 4604 mov r4, r0 +10008440: f8df 810c ldr.w r8, [pc, #268] ; 10008550 +10008444: 460d mov r5, r1 +10008446: 4616 mov r6, r2 +10008448: f108 0008 add.w r0, r8, #8 +1000844c: f7ff fe94 bl 10008178 +10008450: b1d8 cbz r0, 1000848a +10008452: f000 f83d bl 100084d0 + +10008456 : +10008456: 0007 movs r7, r0 +10008458: d014 beq.n 10008484 +1000845a: 2004 movs r0, #4 +1000845c: 6038 str r0, [r7, #0] +1000845e: 60bc str r4, [r7, #8] +10008460: 60fd str r5, [r7, #12] +10008462: 2e00 cmp r6, #0 +10008464: 4639 mov r1, r7 +10008466: f108 0008 add.w r0, r8, #8 +1000846a: d003 beq.n 10008474 +1000846c: f7ff fe38 bl 100080e0 + +10008470 : +10008470: 2000 movs r0, #0 +10008472: e00c b.n 1000848e + +10008474 : +10008474: f7ff fe3e bl 100080f4 +10008478: 2800 cmp r0, #0 +1000847a: d0f9 beq.n 10008470 +1000847c: 4639 mov r1, r7 +1000847e: 2009 movs r0, #9 +10008480: f7ff ff42 bl 10008308 + +10008484 : +10008484: f04f 30ff mov.w r0, #4294967295 +10008488: e001 b.n 1000848e + +1000848a : +1000848a: f06f 0005 mvn.w r0, #5 + +1000848e : +1000848e: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +10008492 : +10008492: b5f8 push {r3, r4, r5, r6, r7, lr} +10008494: 4604 mov r4, r0 +10008496: 4f2e ldr r7, [pc, #184] ; (10008550 ) +10008498: 460d mov r5, r1 +1000849a: 4616 mov r6, r2 +1000849c: f107 0008 add.w r0, r7, #8 +100084a0: f7ff fe6a bl 10008178 +100084a4: b188 cbz r0, 100084ca +100084a6: f000 f813 bl 100084d0 + +100084aa : +100084aa: b910 cbnz r0, 100084b2 +100084ac: f04f 30ff mov.w r0, #4294967295 +100084b0: bdf2 pop {r1, r4, r5, r6, r7, pc} + +100084b2 : +100084b2: 2102 movs r1, #2 +100084b4: 6001 str r1, [r0, #0] +100084b6: 6084 str r4, [r0, #8] +100084b8: 60c5 str r5, [r0, #12] +100084ba: 6106 str r6, [r0, #16] +100084bc: 4601 mov r1, r0 +100084be: f107 0008 add.w r0, r7, #8 +100084c2: f7ff fe0d bl 100080e0 +100084c6: 2000 movs r0, #0 +100084c8: bdf2 pop {r1, r4, r5, r6, r7, pc} + +100084ca : +100084ca: f06f 0005 mvn.w r0, #5 +100084ce: bdf2 pop {r1, r4, r5, r6, r7, pc} + +100084d0 : +100084d0: 2009 movs r0, #9 +100084d2: f7ff bf06 b.w 100082e2 + +100084d6 : +100084d6: 4604 mov r4, r0 +100084d8: 4e1d ldr r6, [pc, #116] ; (10008550 ) +100084da: 460d mov r5, r1 +100084dc: f106 0008 add.w r0, r6, #8 +100084e0: f7ff be4a b.w 10008178 + +100084e4 : +100084e4: b570 push {r4, r5, r6, lr} +100084e6: 4604 mov r4, r0 +100084e8: b086 sub sp, #24 +100084ea: f06f 0505 mvn.w r5, #5 +100084ee: 4e18 ldr r6, [pc, #96] ; (10008550 ) +100084f0: 7225 strb r5, [r4, #8] +100084f2: f106 0008 add.w r0, r6, #8 +100084f6: f7ff fe3f bl 10008178 +100084fa: b178 cbz r0, 1000851c +100084fc: 2000 movs r0, #0 +100084fe: 9000 str r0, [sp, #0] +10008500: 9402 str r4, [sp, #8] +10008502: a900 add r1, sp, #0 +10008504: f106 0008 add.w r0, r6, #8 +10008508: f7ff fdea bl 100080e0 +1000850c: 6860 ldr r0, [r4, #4] +1000850e: 2100 movs r1, #0 +10008510: 3010 adds r0, #16 +10008512: f7ff fe4f bl 100081b4 +10008516: f994 0008 ldrsb.w r0, [r4, #8] +1000851a: e000 b.n 1000851e + +1000851c : +1000851c: 4628 mov r0, r5 + +1000851e : +1000851e: b006 add sp, #24 +10008520: bd70 pop {r4, r5, r6, pc} + +10008522 : +10008522: b538 push {r3, r4, r5, lr} +10008524: 4604 mov r4, r0 +10008526: 460d mov r5, r1 +10008528: f003 fd0a bl 1000bf40 +1000852c: 4808 ldr r0, [pc, #32] ; (10008550 ) +1000852e: 6004 str r4, [r0, #0] +10008530: 6045 str r5, [r0, #4] +10008532: 2105 movs r1, #5 +10008534: 3008 adds r0, #8 +10008536: f7ff fdbb bl 100080b0 +1000853a: 2009 movs r0, #9 +1000853c: 9000 str r0, [sp, #0] +1000853e: f44f 737a mov.w r3, #1000 ; 0x3e8 +10008542: 2200 movs r2, #0 +10008544: 4903 ldr r1, [pc, #12] ; (10008554 ) +10008546: f20f 0010 addw r0, pc, #16 +1000854a: f7ff fe6e bl 1000822a +1000854e: bd31 pop {r0, r4, r5, pc} + +10008550 : +10008550: 7b00 1004 .{.. + +10008554 : +10008554: 8369 1000 i... + +10008558 : +10008558: 4354 5f50 5049 0000 TCP_IP.. + +10008560 : +10008560: b510 push {r4, lr} +10008562: f7ff fe91 bl 10008288 +10008566: 4a15 ldr r2, [pc, #84] ; (100085bc ) +10008568: 2100 movs r1, #0 +1000856a: 7011 strb r1, [r2, #0] +1000856c: f7ff fe91 bl 10008292 +10008570: 4813 ldr r0, [pc, #76] ; (100085c0 ) +10008572: 6804 ldr r4, [r0, #0] +10008574: e000 b.n 10008578 + +10008576 : +10008576: 68e4 ldr r4, [r4, #12] + +10008578 : +10008578: b134 cbz r4, 10008588 +1000857a: 6fa0 ldr r0, [r4, #120] ; 0x78 +1000857c: 2800 cmp r0, #0 +1000857e: d0fa beq.n 10008576 +10008580: f000 fe6a bl 10009258 +10008584: 2000 movs r0, #0 +10008586: 67a0 str r0, [r4, #120] ; 0x78 + +10008588 : +10008588: bd10 pop {r4, pc} + +1000858a : +1000858a: b538 push {r3, r4, r5, lr} +1000858c: f7ff fe7c bl 10008288 +10008590: 4c0a ldr r4, [pc, #40] ; (100085bc ) +10008592: 7825 ldrb r5, [r4, #0] +10008594: 2101 movs r1, #1 +10008596: 7021 strb r1, [r4, #0] +10008598: f7ff fe7b bl 10008292 +1000859c: b96d cbnz r5, 100085ba +1000859e: 2200 movs r2, #0 +100085a0: 2100 movs r1, #0 +100085a2: 4808 ldr r0, [pc, #32] ; (100085c4 ) +100085a4: f7ff ff49 bl 1000843a +100085a8: b138 cbz r0, 100085ba +100085aa: f7ff fe6d bl 10008288 +100085ae: 2100 movs r1, #0 +100085b0: 7021 strb r1, [r4, #0] +100085b2: e8bd 4032 ldmia.w sp!, {r1, r4, r5, lr} +100085b6: f7ff be6c b.w 10008292 + +100085ba : +100085ba: bd31 pop {r0, r4, r5, pc} + +100085bc : +100085bc: 8b0f 1004 .... + +100085c0 : +100085c0: 4088 1004 .@.. + +100085c4 : +100085c4: 8561 1000 a... + +100085c8 : +100085c8: b5f8 push {r3, r4, r5, r6, r7, lr} +100085ca: 460d mov r5, r1 +100085cc: 4617 mov r7, r2 +100085ce: b128 cbz r0, 100085dc +100085d0: 2802 cmp r0, #2 +100085d2: d007 beq.n 100085e4 +100085d4: d304 bcc.n 100085e0 +100085d6: 2803 cmp r0, #3 +100085d8: d006 beq.n 100085e8 +100085da: e014 b.n 10008606 + +100085dc : +100085dc: 2636 movs r6, #54 ; 0x36 +100085de: e004 b.n 100085ea + +100085e0 : +100085e0: 2622 movs r6, #34 ; 0x22 +100085e2: e002 b.n 100085ea + +100085e4 : +100085e4: 260e movs r6, #14 +100085e6: e000 b.n 100085ea + +100085e8 : +100085e8: 2600 movs r6, #0 + +100085ea : +100085ea: 2f00 cmp r7, #0 +100085ec: d051 beq.n 10008692 +100085ee: 2f02 cmp r7, #2 +100085f0: d06a beq.n 100086c8 +100085f2: d369 bcc.n 100086c8 +100085f4: 2f03 cmp r7, #3 +100085f6: d106 bne.n 10008606 +100085f8: 200d movs r0, #13 +100085fa: f7ff fe72 bl 100082e2 +100085fe: 0004 movs r4, r0 +10008600: d103 bne.n 1000860a +10008602: f7ff ffc2 bl 1000858a + +10008606 : +10008606: 2000 movs r0, #0 +10008608: bdf2 pop {r1, r4, r5, r6, r7, pc} + +1000860a : +1000860a: 2003 movs r0, #3 +1000860c: 7320 strb r0, [r4, #12] +1000860e: 1cf1 adds r1, r6, #3 +10008610: 2000 movs r0, #0 +10008612: 6020 str r0, [r4, #0] +10008614: f021 0103 bic.w r1, r1, #3 +10008618: 1930 adds r0, r6, r4 +1000861a: 3010 adds r0, #16 +1000861c: 1cc0 adds r0, r0, #3 +1000861e: 0880 lsrs r0, r0, #2 +10008620: 0080 lsls r0, r0, #2 +10008622: 6060 str r0, [r4, #4] +10008624: f5c1 71fa rsb r1, r1, #500 ; 0x1f4 +10008628: 4628 mov r0, r5 +1000862a: 8125 strh r5, [r4, #8] +1000862c: 4288 cmp r0, r1 +1000862e: db05 blt.n 1000863c +10008630: 1cf1 adds r1, r6, #3 +10008632: f64f 72fc movw r2, #65532 ; 0xfffc +10008636: 4011 ands r1, r2 +10008638: f5c1 75fa rsb r5, r1, #500 ; 0x1f4 + +1000863c : +1000863c: 8165 strh r5, [r4, #10] +1000863e: 2101 movs r1, #1 +10008640: 81e1 strh r1, [r4, #14] +10008642: 4626 mov r6, r4 +10008644: 8961 ldrh r1, [r4, #10] +10008646: 1a45 subs r5, r0, r1 +10008648: e008 b.n 1000865c + +1000864a : +1000864a: 8141 strh r1, [r0, #10] +1000864c: 4606 mov r6, r0 +1000864e: f100 0110 add.w r1, r0, #16 +10008652: 6041 str r1, [r0, #4] +10008654: 2101 movs r1, #1 +10008656: 81c1 strh r1, [r0, #14] +10008658: 8941 ldrh r1, [r0, #10] +1000865a: 1a6d subs r5, r5, r1 + +1000865c : +1000865c: 2d01 cmp r5, #1 +1000865e: db3e blt.n 100086de +10008660: 200d movs r0, #13 +10008662: f7ff fe3e bl 100082e2 +10008666: b928 cbnz r0, 10008674 +10008668: f7ff ff8f bl 1000858a +1000866c: 4620 mov r0, r4 +1000866e: f000 f8bb bl 100087e8 +10008672: e7c8 b.n 10008606 + +10008674 : +10008674: 2103 movs r1, #3 +10008676: 7301 strb r1, [r0, #12] +10008678: 2100 movs r1, #0 +1000867a: 7341 strb r1, [r0, #13] +1000867c: 6001 str r1, [r0, #0] +1000867e: 6030 str r0, [r6, #0] +10008680: b2a9 uxth r1, r5 +10008682: 8105 strh r5, [r0, #8] +10008684: f5b1 7ffa cmp.w r1, #500 ; 0x1f4 +10008688: bfb4 ite lt +1000868a: 4629 movlt r1, r5 +1000868c: f44f 71fa movge.w r1, #500 ; 0x1f4 +10008690: e7db b.n 1000864a + +10008692 : +10008692: f106 0013 add.w r0, r6, #19 +10008696: f64f 71fc movw r1, #65532 ; 0xfffc +1000869a: 4008 ands r0, r1 +1000869c: 1ce9 adds r1, r5, #3 +1000869e: f64f 72fc movw r2, #65532 ; 0xfffc +100086a2: 4011 ands r1, r2 +100086a4: 1808 adds r0, r1, r0 +100086a6: b280 uxth r0, r0 +100086a8: f003 fd29 bl 1000c0fe +100086ac: 0004 movs r4, r0 +100086ae: d0aa beq.n 10008606 +100086b0: 1930 adds r0, r6, r4 +100086b2: 3010 adds r0, #16 +100086b4: 1cc0 adds r0, r0, #3 +100086b6: 0880 lsrs r0, r0, #2 +100086b8: 0080 lsls r0, r0, #2 +100086ba: 6060 str r0, [r4, #4] +100086bc: 8125 strh r5, [r4, #8] +100086be: 8165 strh r5, [r4, #10] +100086c0: 2000 movs r0, #0 +100086c2: 6020 str r0, [r4, #0] +100086c4: 7320 strb r0, [r4, #12] +100086c6: e00a b.n 100086de + +100086c8 : +100086c8: 200c movs r0, #12 +100086ca: f7ff fe0a bl 100082e2 +100086ce: 0004 movs r4, r0 +100086d0: d099 beq.n 10008606 +100086d2: 2000 movs r0, #0 +100086d4: 6060 str r0, [r4, #4] +100086d6: 8125 strh r5, [r4, #8] +100086d8: 8165 strh r5, [r4, #10] +100086da: 6020 str r0, [r4, #0] +100086dc: 7327 strb r7, [r4, #12] + +100086de : +100086de: 2001 movs r0, #1 +100086e0: 81e0 strh r0, [r4, #14] +100086e2: 2000 movs r0, #0 +100086e4: 7360 strb r0, [r4, #13] +100086e6: 4620 mov r0, r4 +100086e8: bdf2 pop {r1, r4, r5, r6, r7, pc} + +100086ea : +100086ea: b530 push {r4, r5, lr} +100086ec: b128 cbz r0, 100086fa +100086ee: 2802 cmp r0, #2 +100086f0: d007 beq.n 10008702 +100086f2: d304 bcc.n 100086fe +100086f4: 2803 cmp r0, #3 +100086f6: d006 beq.n 10008706 +100086f8: e00d b.n 10008716 + +100086fa : +100086fa: 2036 movs r0, #54 ; 0x36 +100086fc: e004 b.n 10008708 + +100086fe : +100086fe: 2022 movs r0, #34 ; 0x22 +10008700: e002 b.n 10008708 + +10008702 : +10008702: 200e movs r0, #14 +10008704: e000 b.n 10008708 + +10008706 : +10008706: 2000 movs r0, #0 + +10008708 : +10008708: 1cc0 adds r0, r0, #3 +1000870a: f020 0403 bic.w r4, r0, #3 +1000870e: 9804 ldr r0, [sp, #16] +10008710: 190d adds r5, r1, r4 +10008712: 42a8 cmp r0, r5 +10008714: da01 bge.n 1000871a + +10008716 : +10008716: 2000 movs r0, #0 +10008718: bd30 pop {r4, r5, pc} + +1000871a : +1000871a: 2000 movs r0, #0 +1000871c: 6018 str r0, [r3, #0] +1000871e: 9803 ldr r0, [sp, #12] +10008720: b100 cbz r0, 10008724 +10008722: 1820 adds r0, r4, r0 + +10008724 : +10008724: 6058 str r0, [r3, #4] +10008726: 2002 movs r0, #2 +10008728: 7358 strb r0, [r3, #13] +1000872a: 8119 strh r1, [r3, #8] +1000872c: 8159 strh r1, [r3, #10] +1000872e: 731a strb r2, [r3, #12] +10008730: 2001 movs r0, #1 +10008732: 81d8 strh r0, [r3, #14] +10008734: 4618 mov r0, r3 +10008736: bd30 pop {r4, r5, pc} + +10008738 : +10008738: b538 push {r3, r4, r5, lr} +1000873a: 4604 mov r4, r0 +1000873c: 460d mov r5, r1 +1000873e: 8920 ldrh r0, [r4, #8] +10008740: 4285 cmp r5, r0 +10008742: d21f bcs.n 10008784 +10008744: 1a28 subs r0, r5, r0 +10008746: e005 b.n 10008754 + +10008748 : +10008748: 1a6d subs r5, r5, r1 +1000874a: 8921 ldrh r1, [r4, #8] +1000874c: 1841 adds r1, r0, r1 +1000874e: 8121 strh r1, [r4, #8] +10008750: b2ad uxth r5, r5 +10008752: 6824 ldr r4, [r4, #0] + +10008754 : +10008754: 8961 ldrh r1, [r4, #10] +10008756: 42a9 cmp r1, r5 +10008758: dbf6 blt.n 10008748 +1000875a: 7b20 ldrb r0, [r4, #12] +1000875c: b948 cbnz r0, 10008772 +1000875e: 428d cmp r5, r1 +10008760: d007 beq.n 10008772 +10008762: 6860 ldr r0, [r4, #4] +10008764: 1b00 subs r0, r0, r4 +10008766: 1829 adds r1, r5, r0 +10008768: b289 uxth r1, r1 +1000876a: 4620 mov r0, r4 +1000876c: f003 fc5f bl 1000c02e +10008770: 4604 mov r4, r0 + +10008772 : +10008772: 8165 strh r5, [r4, #10] +10008774: 8960 ldrh r0, [r4, #10] +10008776: 8120 strh r0, [r4, #8] +10008778: 6820 ldr r0, [r4, #0] +1000877a: b108 cbz r0, 10008780 +1000877c: f000 f834 bl 100087e8 + +10008780 : +10008780: 2000 movs r0, #0 +10008782: 6020 str r0, [r4, #0] + +10008784 : +10008784: bd31 pop {r0, r4, r5, pc} + +10008786 : +10008786: b570 push {r4, r5, r6, lr} +10008788: 2900 cmp r1, #0 +1000878a: bf18 it ne +1000878c: 2800 cmpne r0, #0 +1000878e: d029 beq.n 100087e4 +10008790: 424b negs r3, r1 +10008792: 2900 cmp r1, #0 +10008794: d505 bpl.n 100087a2 +10008796: 8945 ldrh r5, [r0, #10] +10008798: b29c uxth r4, r3 +1000879a: 42a5 cmp r5, r4 +1000879c: d202 bcs.n 100087a4 + +1000879e : +1000879e: 2001 movs r0, #1 +100087a0: bd70 pop {r4, r5, r6, pc} + +100087a2 : +100087a2: 460c mov r4, r1 + +100087a4 : +100087a4: 7b05 ldrb r5, [r0, #12] +100087a6: 6846 ldr r6, [r0, #4] +100087a8: 2d00 cmp r5, #0 +100087aa: bf18 it ne +100087ac: 2d03 cmpne r5, #3 +100087ae: d107 bne.n 100087c0 +100087b0: 199a adds r2, r3, r6 +100087b2: f100 0310 add.w r3, r0, #16 +100087b6: 6042 str r2, [r0, #4] +100087b8: 429a cmp r2, r3 +100087ba: d20d bcs.n 100087d8 +100087bc: 6046 str r6, [r0, #4] +100087be: e7ee b.n 1000879e + +100087c0 : +100087c0: 2d02 cmp r5, #2 +100087c2: bf18 it ne +100087c4: 2d01 cmpne r5, #1 +100087c6: d1ea bne.n 1000879e +100087c8: 2900 cmp r1, #0 +100087ca: d5e8 bpl.n 1000879e +100087cc: 8942 ldrh r2, [r0, #10] +100087ce: b2a4 uxth r4, r4 +100087d0: 42a2 cmp r2, r4 +100087d2: d3e4 bcc.n 1000879e +100087d4: 199a adds r2, r3, r6 +100087d6: 6042 str r2, [r0, #4] + +100087d8 : +100087d8: 8942 ldrh r2, [r0, #10] +100087da: 188a adds r2, r1, r2 +100087dc: 8142 strh r2, [r0, #10] +100087de: 8902 ldrh r2, [r0, #8] +100087e0: 1889 adds r1, r1, r2 +100087e2: 8101 strh r1, [r0, #8] + +100087e4 : +100087e4: 2000 movs r0, #0 +100087e6: bd70 pop {r4, r5, r6, pc} + +100087e8 : +100087e8: b570 push {r4, r5, r6, lr} +100087ea: 0005 movs r5, r0 +100087ec: d101 bne.n 100087f2 +100087ee: 2000 movs r0, #0 +100087f0: bd70 pop {r4, r5, r6, pc} + +100087f2 : +100087f2: 2400 movs r4, #0 + +100087f4 : +100087f4: f7ff fd48 bl 10008288 +100087f8: 89e9 ldrh r1, [r5, #14] +100087fa: 1e4e subs r6, r1, #1 +100087fc: 81ee strh r6, [r5, #14] +100087fe: f7ff fd48 bl 10008292 +10008802: b2b6 uxth r6, r6 +10008804: b9e6 cbnz r6, 10008840 +10008806: 7b69 ldrb r1, [r5, #13] +10008808: 682e ldr r6, [r5, #0] +1000880a: 7b28 ldrb r0, [r5, #12] +1000880c: 0789 lsls r1, r1, #30 +1000880e: d503 bpl.n 10008818 +10008810: 6929 ldr r1, [r5, #16] +10008812: 4628 mov r0, r5 +10008814: 4788 blx r1 +10008816: e010 b.n 1000883a + +10008818 : +10008818: 2803 cmp r0, #3 +1000881a: d102 bne.n 10008822 +1000881c: 4629 mov r1, r5 +1000881e: 200d movs r0, #13 +10008820: e005 b.n 1000882e + +10008822 : +10008822: 2801 cmp r0, #1 +10008824: bf18 it ne +10008826: 2802 cmpne r0, #2 +10008828: d104 bne.n 10008834 +1000882a: 4629 mov r1, r5 +1000882c: 200c movs r0, #12 + +1000882e : +1000882e: f7ff fd6b bl 10008308 +10008832: e002 b.n 1000883a + +10008834 : +10008834: 4628 mov r0, r5 +10008836: f003 fbb2 bl 1000bf9e + +1000883a : +1000883a: 1c64 adds r4, r4, #1 +1000883c: 0035 movs r5, r6 +1000883e: d1d9 bne.n 100087f4 + +10008840 : +10008840: b2e0 uxtb r0, r4 +10008842: bd70 pop {r4, r5, r6, pc} + +10008844 : +10008844: 2100 movs r1, #0 +10008846: e001 b.n 1000884c + +10008848 : +10008848: 6800 ldr r0, [r0, #0] +1000884a: 1c49 adds r1, r1, #1 + +1000884c : +1000884c: 2800 cmp r0, #0 +1000884e: d1fb bne.n 10008848 +10008850: b2c8 uxtb r0, r1 +10008852: 4770 bx lr + +10008854 : +10008854: b510 push {r4, lr} +10008856: 0004 movs r4, r0 +10008858: d008 beq.n 1000886c +1000885a: f7ff fd15 bl 10008288 +1000885e: 89e1 ldrh r1, [r4, #14] +10008860: 1c49 adds r1, r1, #1 +10008862: 81e1 strh r1, [r4, #14] +10008864: e8bd 4010 ldmia.w sp!, {r4, lr} +10008868: f7ff bd13 b.w 10008292 + +1000886c : +1000886c: bd10 pop {r4, pc} + +1000886e : +1000886e: b900 cbnz r0, 10008872 +10008870: 4770 bx lr + +10008872 : +10008872: b510 push {r4, lr} +10008874: b929 cbnz r1, 10008882 +10008876: bd10 pop {r4, pc} + +10008878 : +10008878: 8903 ldrh r3, [r0, #8] +1000887a: 890c ldrh r4, [r1, #8] +1000887c: 18e3 adds r3, r4, r3 +1000887e: 8103 strh r3, [r0, #8] +10008880: 4610 mov r0, r2 + +10008882 : +10008882: 6802 ldr r2, [r0, #0] +10008884: 2a00 cmp r2, #0 +10008886: d1f7 bne.n 10008878 +10008888: 8902 ldrh r2, [r0, #8] +1000888a: 890b ldrh r3, [r1, #8] +1000888c: 189a adds r2, r3, r2 +1000888e: 8102 strh r2, [r0, #8] +10008890: 6001 str r1, [r0, #0] +10008892: bd10 pop {r4, pc} + +10008894 : +10008894: b510 push {r4, lr} +10008896: 460c mov r4, r1 +10008898: f7ff ffe9 bl 1000886e +1000889c: 4620 mov r0, r4 +1000889e: e8bd 4010 ldmia.w sp!, {r4, lr} +100088a2: e7d7 b.n 10008854 + +100088a4 : +100088a4: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +100088a8: 4604 mov r4, r0 +100088aa: 2600 movs r6, #0 +100088ac: 2700 movs r7, #0 +100088ae: 460d mov r5, r1 +100088b0: 2c00 cmp r4, #0 +100088b2: bf18 it ne +100088b4: 2d00 cmpne r5, #0 +100088b6: d025 beq.n 10008904 +100088b8: 8920 ldrh r0, [r4, #8] +100088ba: 8929 ldrh r1, [r5, #8] +100088bc: 4288 cmp r0, r1 +100088be: d321 bcc.n 10008904 + +100088c0 : +100088c0: 8968 ldrh r0, [r5, #10] +100088c2: 8961 ldrh r1, [r4, #10] +100088c4: 1b8a subs r2, r1, r6 +100088c6: 1bc3 subs r3, r0, r7 +100088c8: 429a cmp r2, r3 +100088ca: bfac ite ge +100088cc: 1bc0 subge r0, r0, r7 +100088ce: 1b88 sublt r0, r1, r6 +100088d0: fa1f f880 uxth.w r8, r0 +100088d4: 6868 ldr r0, [r5, #4] +100088d6: 1839 adds r1, r7, r0 +100088d8: 6860 ldr r0, [r4, #4] +100088da: 4642 mov r2, r8 +100088dc: 1830 adds r0, r6, r0 +100088de: f003 fd33 bl 1000c348 +100088e2: 4447 add r7, r8 +100088e4: 8968 ldrh r0, [r5, #10] +100088e6: 4446 add r6, r8 +100088e8: b2bf uxth r7, r7 +100088ea: b2b6 uxth r6, r6 +100088ec: 4287 cmp r7, r0 +100088ee: bfa4 itt ge +100088f0: 2700 movge r7, #0 +100088f2: 682d ldrge r5, [r5, #0] +100088f4: 8960 ldrh r0, [r4, #10] +100088f6: 4286 cmp r6, r0 +100088f8: bf02 ittt eq +100088fa: 2600 moveq r6, #0 +100088fc: 6824 ldreq r4, [r4, #0] +100088fe: 2c00 cmpeq r4, #0 +10008900: d103 bne.n 1000890a +10008902: b1ad cbz r5, 10008930 + +10008904 : +10008904: f06f 000d mvn.w r0, #13 +10008908: e013 b.n 10008932 + +1000890a : +1000890a: b12d cbz r5, 10008918 +1000890c: 8968 ldrh r0, [r5, #10] +1000890e: 8929 ldrh r1, [r5, #8] +10008910: 4288 cmp r0, r1 +10008912: d101 bne.n 10008918 +10008914: 6828 ldr r0, [r5, #0] +10008916: b930 cbnz r0, 10008926 + +10008918 : +10008918: b144 cbz r4, 1000892c +1000891a: 8960 ldrh r0, [r4, #10] +1000891c: 8921 ldrh r1, [r4, #8] +1000891e: 4288 cmp r0, r1 +10008920: d104 bne.n 1000892c +10008922: 6820 ldr r0, [r4, #0] +10008924: b110 cbz r0, 1000892c + +10008926 : +10008926: f06f 0005 mvn.w r0, #5 +1000892a: e002 b.n 10008932 + +1000892c : +1000892c: 2d00 cmp r5, #0 +1000892e: d1c7 bne.n 100088c0 + +10008930 : +10008930: 2000 movs r0, #0 + +10008932 : +10008932: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +10008936 : +10008936: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +1000893a: 4604 mov r4, r0 +1000893c: 2600 movs r6, #0 +1000893e: 4688 mov r8, r1 +10008940: 4615 mov r5, r2 +10008942: 2c00 cmp r4, #0 +10008944: bf18 it ne +10008946: f1b8 0f00 cmpne.w r8, #0 +1000894a: d021 beq.n 10008990 +1000894c: 46b1 mov r9, r6 +1000894e: e018 b.n 10008982 + +10008950 : +10008950: 8960 ldrh r0, [r4, #10] +10008952: b29b uxth r3, r3 +10008954: b10b cbz r3, 1000895a +10008956: 4283 cmp r3, r0 +10008958: d216 bcs.n 10008988 + +1000895a : +1000895a: 1ac0 subs r0, r0, r3 +1000895c: b287 uxth r7, r0 +1000895e: 42bd cmp r5, r7 +10008960: bfb8 it lt +10008962: 462f movlt r7, r5 +10008964: 6860 ldr r0, [r4, #4] +10008966: 1819 adds r1, r3, r0 +10008968: 463a mov r2, r7 +1000896a: eb09 0008 add.w r0, r9, r8 +1000896e: f003 fceb bl 1000c348 +10008972: 19be adds r6, r7, r6 +10008974: 44b9 add r9, r7 +10008976: 6824 ldr r4, [r4, #0] +10008978: b2b6 uxth r6, r6 +1000897a: fa1f f989 uxth.w r9, r9 +1000897e: 1bed subs r5, r5, r7 +10008980: 2300 movs r3, #0 + +10008982 : +10008982: b2ad uxth r5, r5 +10008984: b125 cbz r5, 10008990 +10008986: e001 b.n 1000898c + +10008988 : +10008988: 6824 ldr r4, [r4, #0] +1000898a: 1a1b subs r3, r3, r0 + +1000898c : +1000898c: 2c00 cmp r4, #0 +1000898e: d1df bne.n 10008950 + +10008990 : +10008990: 4630 mov r0, r6 +10008992: e8bd 83f2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, pc} + +10008996 : +10008996: b538 push {r3, r4, r5, lr} +10008998: 4604 mov r4, r0 +1000899a: 4608 mov r0, r1 +1000899c: 6821 ldr r1, [r4, #0] +1000899e: b129 cbz r1, 100089ac +100089a0: 8921 ldrh r1, [r4, #8] +100089a2: 2200 movs r2, #0 +100089a4: f7ff fe10 bl 100085c8 +100089a8: 0005 movs r5, r0 +100089aa: d101 bne.n 100089b0 + +100089ac : +100089ac: 4620 mov r0, r4 +100089ae: bd32 pop {r1, r4, r5, pc} + +100089b0 : +100089b0: 4621 mov r1, r4 +100089b2: f7ff ff77 bl 100088a4 +100089b6: 4620 mov r0, r4 +100089b8: f7ff ff16 bl 100087e8 +100089bc: 4628 mov r0, r5 +100089be: bd32 pop {r1, r4, r5, pc} + +100089c0 : +100089c0: b510 push {r4, lr} +100089c2: 0004 movs r4, r0 +100089c4: d00a beq.n 100089dc +100089c6: 6820 ldr r0, [r4, #0] +100089c8: b120 cbz r0, 100089d4 +100089ca: f7ff ff0d bl 100087e8 +100089ce: 2000 movs r0, #0 +100089d0: 6060 str r0, [r4, #4] +100089d2: 6020 str r0, [r4, #0] + +100089d4 : +100089d4: 4621 mov r1, r4 +100089d6: e8bd 4010 ldmia.w sp!, {r4, lr} +100089da: e028 b.n 10008a2e + +100089dc : +100089dc: bd10 pop {r4, pc} + +100089de : +100089de: b510 push {r4, lr} +100089e0: 0004 movs r4, r0 +100089e2: d006 beq.n 100089f2 +100089e4: 6820 ldr r0, [r4, #0] +100089e6: b108 cbz r0, 100089ec +100089e8: f7ff fefe bl 100087e8 + +100089ec : +100089ec: 2000 movs r0, #0 +100089ee: 6060 str r0, [r4, #4] +100089f0: 6020 str r0, [r4, #0] + +100089f2 : +100089f2: bd10 pop {r4, pc} + +100089f4 : +100089f4: b570 push {r4, r5, r6, lr} +100089f6: 0004 movs r4, r0 +100089f8: 460d mov r5, r1 +100089fa: 4616 mov r6, r2 +100089fc: d102 bne.n 10008a04 +100089fe: f06f 000d mvn.w r0, #13 +10008a02: bd70 pop {r4, r5, r6, pc} + +10008a04 : +10008a04: 6820 ldr r0, [r4, #0] +10008a06: b108 cbz r0, 10008a0c +10008a08: f7ff feee bl 100087e8 + +10008a0c : +10008a0c: 2202 movs r2, #2 +10008a0e: 2100 movs r1, #0 +10008a10: 2000 movs r0, #0 +10008a12: f7ff fdd9 bl 100085c8 +10008a16: 6020 str r0, [r4, #0] +10008a18: b918 cbnz r0, 10008a22 +10008a1a: 6060 str r0, [r4, #4] +10008a1c: f04f 30ff mov.w r0, #4294967295 +10008a20: bd70 pop {r4, r5, r6, pc} + +10008a22 : +10008a22: 6045 str r5, [r0, #4] +10008a24: 8106 strh r6, [r0, #8] +10008a26: 8146 strh r6, [r0, #10] +10008a28: 6060 str r0, [r4, #4] +10008a2a: 2000 movs r0, #0 +10008a2c: bd70 pop {r4, r5, r6, pc} + +10008a2e : +10008a2e: 2007 movs r0, #7 +10008a30: f7ff bc6a b.w 10008308 + +10008a34 : +10008a34: 2800 cmp r0, #0 +10008a36: bf18 it ne +10008a38: 2900 cmpne r1, #0 +10008a3a: d000 beq.n 10008a3e +10008a3c: b912 cbnz r2, 10008a44 + +10008a3e : +10008a3e: f06f 000d mvn.w r0, #13 +10008a42: 4770 bx lr + +10008a44 : +10008a44: 6840 ldr r0, [r0, #4] +10008a46: b910 cbnz r0, 10008a4e +10008a48: f06f 0001 mvn.w r0, #1 +10008a4c: 4770 bx lr + +10008a4e : +10008a4e: 6843 ldr r3, [r0, #4] +10008a50: 600b str r3, [r1, #0] +10008a52: 8940 ldrh r0, [r0, #10] +10008a54: 8010 strh r0, [r2, #0] +10008a56: 2000 movs r0, #0 +10008a58: 4770 bx lr + ... + +10008a5c : +10008a5c: 4770 bx lr + +10008a5e : +10008a5e: b580 push {r7, lr} +10008a60: f000 fb97 bl 10009192 +10008a64: f8df 0a2c ldr.w r0, [pc, #2604] ; 10009494 +10008a68: 7801 ldrb r1, [r0, #0] +10008a6a: 1c49 adds r1, r1, #1 +10008a6c: 7001 strb r1, [r0, #0] +10008a6e: 07c8 lsls r0, r1, #31 +10008a70: bf44 itt mi +10008a72: e8bd 4001 ldmiami.w sp!, {r0, lr} +10008a76: f000 ba4a bmi.w 10008f0e +10008a7a: bd01 pop {r0, pc} + +10008a7c : +10008a7c: b57c push {r2, r3, r4, r5, r6, lr} +10008a7e: 4604 mov r4, r0 +10008a80: f8df 5a14 ldr.w r5, [pc, #2580] ; 10009498 +10008a84: 69a0 ldr r0, [r4, #24] +10008a86: 2900 cmp r1, #0 +10008a88: d033 beq.n 10008af2 +10008a8a: 2804 cmp r0, #4 +10008a8c: bf18 it ne +10008a8e: 2807 cmpne r0, #7 +10008a90: d12f bne.n 10008af2 +10008a92: 6fe1 ldr r1, [r4, #124] ; 0x7c +10008a94: 2900 cmp r1, #0 +10008a96: bf02 ittt eq +10008a98: 8e21 ldrheq r1, [r4, #48] ; 0x30 +10008a9a: f640 3268 movweq r2, #2920 ; 0xb68 +10008a9e: 4291 cmpeq r1, r2 +10008aa0: d027 beq.n 10008af2 +10008aa2: 8c20 ldrh r0, [r4, #32] +10008aa4: 9001 str r0, [sp, #4] +10008aa6: 1d23 adds r3, r4, #4 +10008aa8: 8be0 ldrh r0, [r4, #30] +10008aaa: 9000 str r0, [sp, #0] +10008aac: 4622 mov r2, r4 +10008aae: 6ae1 ldr r1, [r4, #44] ; 0x2c +10008ab0: 6d60 ldr r0, [r4, #84] ; 0x54 +10008ab2: f001 fbbf bl 1000a234 +10008ab6: 4620 mov r0, r4 +10008ab8: f000 fc98 bl 100093ec +10008abc: 6928 ldr r0, [r5, #16] +10008abe: 42a0 cmp r0, r4 +10008ac0: d102 bne.n 10008ac8 +10008ac2: 68c0 ldr r0, [r0, #12] +10008ac4: 6128 str r0, [r5, #16] +10008ac6: e001 b.n 10008acc + +10008ac8 : +10008ac8: f000 f855 bl 10008b76 + +10008acc : +10008acc: 2000 movs r0, #0 +10008ace: 60e0 str r0, [r4, #12] +10008ad0: 2001 movs r0, #1 +10008ad2: 7028 strb r0, [r5, #0] +10008ad4: 69a0 ldr r0, [r4, #24] +10008ad6: 2804 cmp r0, #4 +10008ad8: d107 bne.n 10008aea +10008ada: 200a movs r0, #10 +10008adc: 61a0 str r0, [r4, #24] +10008ade: 6968 ldr r0, [r5, #20] +10008ae0: 60e0 str r0, [r4, #12] +10008ae2: 616c str r4, [r5, #20] +10008ae4: f002 fc93 bl 1000b40e +10008ae8: e001 b.n 10008aee + +10008aea : +10008aea: f000 f8c3 bl 10008c74 + +10008aee : +10008aee: 2000 movs r0, #0 +10008af0: bd76 pop {r1, r2, r4, r5, r6, pc} + +10008af2 : +10008af2: 2807 cmp r0, #7 +10008af4: d83d bhi.n 10008b72 +10008af6: e8df f000 tbb [pc, r0] + +10008afa : +10008afa: 1104 271a 3c27 353c ...''<<5 + +10008b02 : +10008b02: 8be0 ldrh r0, [r4, #30] +10008b04: 2600 movs r6, #0 +10008b06: b1d0 cbz r0, 10008b3e +10008b08: 68a8 ldr r0, [r5, #8] +10008b0a: 42a0 cmp r0, r4 +10008b0c: d102 bne.n 10008b14 +10008b0e: 68c0 ldr r0, [r0, #12] +10008b10: 60a8 str r0, [r5, #8] +10008b12: e001 b.n 10008b18 + +10008b14 : +10008b14: f000 f82f bl 10008b76 + +10008b18 : +10008b18: 60e6 str r6, [r4, #12] +10008b1a: e010 b.n 10008b3e + +10008b1c : +10008b1c: 2600 movs r6, #0 +10008b1e: 4621 mov r1, r4 +10008b20: f105 000c add.w r0, r5, #12 +10008b24: f000 fc86 bl 10009434 +10008b28: 4621 mov r1, r4 +10008b2a: 2003 movs r0, #3 +10008b2c: e009 b.n 10008b42 + +10008b2e : +10008b2e: 2600 movs r6, #0 +10008b30: 4621 mov r1, r4 +10008b32: f105 0010 add.w r0, r5, #16 +10008b36: f000 fc7d bl 10009434 +10008b3a: 2001 movs r0, #1 +10008b3c: 7028 strb r0, [r5, #0] + +10008b3e : +10008b3e: 4621 mov r1, r4 +10008b40: 2002 movs r0, #2 + +10008b42 : +10008b42: f7ff fbe1 bl 10008308 +10008b46: e00b b.n 10008b60 + +10008b48 : +10008b48: 4620 mov r0, r4 +10008b4a: f000 ffb2 bl 10009ab2 +10008b4e: 0006 movs r6, r0 +10008b50: d101 bne.n 10008b56 +10008b52: 2005 movs r0, #5 + +10008b54 : +10008b54: 61a0 str r0, [r4, #24] + +10008b56 : +10008b56: b11c cbz r4, 10008b60 +10008b58: b916 cbnz r6, 10008b60 +10008b5a: 4620 mov r0, r4 +10008b5c: f001 fa57 bl 1000a00e + +10008b60 : +10008b60: 4630 mov r0, r6 +10008b62: bd76 pop {r1, r2, r4, r5, r6, pc} + +10008b64 : +10008b64: 4620 mov r0, r4 +10008b66: f000 ffa4 bl 10009ab2 +10008b6a: 0006 movs r6, r0 +10008b6c: d1f3 bne.n 10008b56 +10008b6e: 2009 movs r0, #9 +10008b70: e7f0 b.n 10008b54 + +10008b72 : +10008b72: 2600 movs r6, #0 +10008b74: e7f4 b.n 10008b60 + +10008b76 : +10008b76: 61a8 str r0, [r5, #24] +10008b78: 69a9 ldr r1, [r5, #24] +10008b7a: b121 cbz r1, 10008b86 +10008b7c: 68c8 ldr r0, [r1, #12] +10008b7e: 42a0 cmp r0, r4 +10008b80: d1f9 bne.n 10008b76 +10008b82: 68e0 ldr r0, [r4, #12] +10008b84: 60c8 str r0, [r1, #12] + +10008b86 : +10008b86: 4770 bx lr + +10008b88 : +10008b88: 6981 ldr r1, [r0, #24] +10008b8a: 2901 cmp r1, #1 +10008b8c: d005 beq.n 10008b9a +10008b8e: f100 0118 add.w r1, r0, #24 +10008b92: 7a8a ldrb r2, [r1, #10] +10008b94: f042 0210 orr.w r2, r2, #16 +10008b98: 728a strb r2, [r1, #10] + +10008b9a : +10008b9a: 2101 movs r1, #1 +10008b9c: e76e b.n 10008a7c + +10008b9e : +10008b9e: b510 push {r4, lr} +10008ba0: 6983 ldr r3, [r0, #24] +10008ba2: 2b01 cmp r3, #1 +10008ba4: d01a beq.n 10008bdc +10008ba6: b191 cbz r1, 10008bce +10008ba8: f100 0418 add.w r4, r0, #24 +10008bac: 7aa1 ldrb r1, [r4, #10] +10008bae: f041 0110 orr.w r1, r1, #16 +10008bb2: 72a1 strb r1, [r4, #10] +10008bb4: b11a cbz r2, 10008bbe +10008bb6: 2101 movs r1, #1 + +10008bb8 : +10008bb8: e8bd 4010 ldmia.w sp!, {r4, lr} +10008bbc: e75e b.n 10008a7c + +10008bbe : +10008bbe: 6e60 ldr r0, [r4, #100] ; 0x64 +10008bc0: b118 cbz r0, 10008bca +10008bc2: f7ff fe11 bl 100087e8 +10008bc6: 2000 movs r0, #0 +10008bc8: 6660 str r0, [r4, #100] ; 0x64 + +10008bca : +10008bca: 2000 movs r0, #0 +10008bcc: bd10 pop {r4, pc} + +10008bce : +10008bce: 2a00 cmp r2, #0 +10008bd0: d0fb beq.n 10008bca +10008bd2: 1edb subs r3, r3, #3 +10008bd4: 2b01 cmp r3, #1 +10008bd6: d9ef bls.n 10008bb8 +10008bd8: 1f1b subs r3, r3, #4 +10008bda: d0ed beq.n 10008bb8 + +10008bdc : +10008bdc: f06f 000c mvn.w r0, #12 +10008be0: bd10 pop {r4, pc} + +10008be2 : +10008be2: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +10008be6: 4604 mov r4, r0 +10008be8: f104 0610 add.w r6, r4, #16 +10008bec: b083 sub sp, #12 +10008bee: 68b0 ldr r0, [r6, #8] +10008bf0: f8df b8a4 ldr.w fp, [pc, #2212] ; 10009498 +10008bf4: 460d mov r5, r1 +10008bf6: 280a cmp r0, #10 +10008bf8: d10b bne.n 10008c12 +10008bfa: 4621 mov r1, r4 +10008bfc: f10b 0014 add.w r0, fp, #20 +10008c00: f000 fc18 bl 10009434 +10008c04: 4621 mov r1, r4 +10008c06: b003 add sp, #12 +10008c08: e8bd 4ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +10008c0c: 2002 movs r0, #2 +10008c0e: f7ff bb7b b.w 10008308 + +10008c12 : +10008c12: 6c77 ldr r7, [r6, #68] ; 0x44 +10008c14: f8d6 801c ldr.w r8, [r6, #28] +10008c18: f8d4 9090 ldr.w r9, [r4, #144] ; 0x90 +10008c1c: f8d4 a010 ldr.w sl, [r4, #16] +10008c20: 4621 mov r1, r4 +10008c22: f10b 0010 add.w r0, fp, #16 +10008c26: f000 fc05 bl 10009434 +10008c2a: 2001 movs r0, #1 +10008c2c: f88b 0000 strb.w r0, [fp] +10008c30: 6e70 ldr r0, [r6, #100] ; 0x64 +10008c32: b108 cbz r0, 10008c38 +10008c34: f000 fb10 bl 10009258 + +10008c38 : +10008c38: 6e30 ldr r0, [r6, #96] ; 0x60 +10008c3a: b108 cbz r0, 10008c40 +10008c3c: f000 fb0c bl 10009258 + +10008c40 : +10008c40: 6eb0 ldr r0, [r6, #104] ; 0x68 +10008c42: b108 cbz r0, 10008c48 +10008c44: f000 fb08 bl 10009258 + +10008c48 : +10008c48: b14d cbz r5, 10008c5e +10008c4a: 8a30 ldrh r0, [r6, #16] +10008c4c: 9001 str r0, [sp, #4] +10008c4e: 1d23 adds r3, r4, #4 +10008c50: 89f0 ldrh r0, [r6, #14] +10008c52: 9000 str r0, [sp, #0] +10008c54: 4622 mov r2, r4 +10008c56: 4641 mov r1, r8 +10008c58: 4638 mov r0, r7 +10008c5a: f001 faeb bl 1000a234 + +10008c5e : +10008c5e: f000 f809 bl 10008c74 + +10008c62 : +10008c62: f1b9 0f00 cmp.w r9, #0 +10008c66: d003 beq.n 10008c70 +10008c68: f06f 0109 mvn.w r1, #9 +10008c6c: 4650 mov r0, sl +10008c6e: 47c8 blx r9 + +10008c70 : +10008c70: e8bd 8ff7 ldmia.w sp!, {r0, r1, r2, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +10008c74 : +10008c74: 4621 mov r1, r4 +10008c76: 2002 movs r0, #2 +10008c78: f7ff bb46 b.w 10008308 + +10008c7c : +10008c7c: 2101 movs r1, #1 +10008c7e: e7b0 b.n 10008be2 + +10008c80 : +10008c80: b5f8 push {r3, r4, r5, r6, r7, lr} +10008c82: 4604 mov r4, r0 +10008c84: 460d mov r5, r1 +10008c86: 69a1 ldr r1, [r4, #24] +10008c88: 4610 mov r0, r2 +10008c8a: b101 cbz r1, 10008c8e +10008c8c: e139 b.n 10008f02 + +10008c8e : +10008c8e: b918 cbnz r0, 10008c98 +10008c90: f000 f8a6 bl 10008de0 +10008c94: b900 cbnz r0, 10008c98 +10008c96: e137 b.n 10008f08 + +10008c98 : +10008c98: 2100 movs r1, #0 +10008c9a: f60f 0254 addw r2, pc, #2132 ; 0x854 + +10008c9e : +10008c9e: f852 3021 ldr.w r3, [r2, r1, lsl #2] +10008ca2: 681b ldr r3, [r3, #0] +10008ca4: e000 b.n 10008ca8 + +10008ca6 : +10008ca6: 68db ldr r3, [r3, #12] + +10008ca8 : +10008ca8: b16b cbz r3, 10008cc6 +10008caa: 8bde ldrh r6, [r3, #30] +10008cac: 4286 cmp r6, r0 +10008cae: d1fa bne.n 10008ca6 +10008cb0: 681e ldr r6, [r3, #0] +10008cb2: b12e cbz r6, 10008cc0 +10008cb4: b125 cbz r5, 10008cc0 +10008cb6: 682f ldr r7, [r5, #0] +10008cb8: 2f00 cmp r7, #0 +10008cba: bf18 it ne +10008cbc: 42be cmpne r6, r7 +10008cbe: d1f2 bne.n 10008ca6 + +10008cc0 : +10008cc0: f06f 0007 mvn.w r0, #7 +10008cc4: bdf2 pop {r1, r4, r5, r6, r7, pc} + +10008cc6 : +10008cc6: 1c49 adds r1, r1, #1 +10008cc8: 2904 cmp r1, #4 +10008cca: dbe8 blt.n 10008c9e +10008ccc: 2d00 cmp r5, #0 +10008cce: bf1e ittt ne +10008cd0: 6829 ldrne r1, [r5, #0] +10008cd2: 2900 cmpne r1, #0 +10008cd4: 6021 strne r1, [r4, #0] +10008cd6: 83e0 strh r0, [r4, #30] +10008cd8: f8df 07bc ldr.w r0, [pc, #1980] ; 10009498 +10008cdc: 6881 ldr r1, [r0, #8] +10008cde: 60e1 str r1, [r4, #12] +10008ce0: 6084 str r4, [r0, #8] +10008ce2: f002 fb94 bl 1000b40e +10008ce6: 2000 movs r0, #0 +10008ce8: bdf2 pop {r1, r4, r5, r6, r7, pc} + +10008cea : +10008cea: f06f 0009 mvn.w r0, #9 +10008cee: 4770 bx lr + +10008cf0 : +10008cf0: b570 push {r4, r5, r6, lr} +10008cf2: 4604 mov r4, r0 +10008cf4: 69a0 ldr r0, [r4, #24] +10008cf6: b920 cbnz r0, 10008d02 +10008cf8: 2003 movs r0, #3 +10008cfa: f7ff faf2 bl 100082e2 +10008cfe: 0005 movs r5, r0 +10008d00: d101 bne.n 10008d06 + +10008d02 : +10008d02: 2000 movs r0, #0 +10008d04: bd70 pop {r4, r5, r6, pc} + +10008d06 : +10008d06: 6920 ldr r0, [r4, #16] +10008d08: f8df 678c ldr.w r6, [pc, #1932] ; 10009498 +10008d0c: 6128 str r0, [r5, #16] +10008d0e: 8be0 ldrh r0, [r4, #30] +10008d10: 83e8 strh r0, [r5, #30] +10008d12: 2001 movs r0, #1 +10008d14: 61a8 str r0, [r5, #24] +10008d16: 7f20 ldrb r0, [r4, #28] +10008d18: 7728 strb r0, [r5, #28] +10008d1a: 7a20 ldrb r0, [r4, #8] +10008d1c: f040 0002 orr.w r0, r0, #2 +10008d20: 7228 strb r0, [r5, #8] +10008d22: 7aa0 ldrb r0, [r4, #10] +10008d24: 72a8 strb r0, [r5, #10] +10008d26: 7a60 ldrb r0, [r4, #9] +10008d28: 7268 strb r0, [r5, #9] +10008d2a: 6820 ldr r0, [r4, #0] +10008d2c: 6028 str r0, [r5, #0] +10008d2e: 8be0 ldrh r0, [r4, #30] +10008d30: b178 cbz r0, 10008d52 +10008d32: 68b0 ldr r0, [r6, #8] +10008d34: 42a0 cmp r0, r4 +10008d36: d102 bne.n 10008d3e +10008d38: 68c0 ldr r0, [r0, #12] +10008d3a: 60b0 str r0, [r6, #8] +10008d3c: e007 b.n 10008d4e + +10008d3e : +10008d3e: 61b0 str r0, [r6, #24] +10008d40: 69b1 ldr r1, [r6, #24] +10008d42: b121 cbz r1, 10008d4e +10008d44: 68c8 ldr r0, [r1, #12] +10008d46: 42a0 cmp r0, r4 +10008d48: d1f9 bne.n 10008d3e +10008d4a: 68e0 ldr r0, [r4, #12] +10008d4c: 60c8 str r0, [r1, #12] + +10008d4e : +10008d4e: 2000 movs r0, #0 +10008d50: 60e0 str r0, [r4, #12] + +10008d52 : +10008d52: f7ff ff8f bl 10008c74 + +10008d56 : +10008d56: f8df 0744 ldr.w r0, [pc, #1860] ; 1000949c +10008d5a: 6168 str r0, [r5, #20] +10008d5c: 68f0 ldr r0, [r6, #12] +10008d5e: 60e8 str r0, [r5, #12] +10008d60: 60f5 str r5, [r6, #12] +10008d62: f002 fb54 bl 1000b40e +10008d66: 4628 mov r0, r5 +10008d68: bd70 pop {r4, r5, r6, pc} + +10008d6a : +10008d6a: b530 push {r4, r5, lr} +10008d6c: 8e02 ldrh r2, [r0, #48] ; 0x30 +10008d6e: 6ac3 ldr r3, [r0, #44] ; 0x2c +10008d70: 8f44 ldrh r4, [r0, #58] ; 0x3a +10008d72: 18d1 adds r1, r2, r3 +10008d74: f240 55b5 movw r5, #1461 ; 0x5b5 +10008d78: 42ac cmp r4, r5 +10008d7a: bfa8 it ge +10008d7c: f240 54b4 movwge r4, #1460 ; 0x5b4 +10008d80: 6b45 ldr r5, [r0, #52] ; 0x34 +10008d82: 1b49 subs r1, r1, r5 +10008d84: 1b0c subs r4, r1, r4 +10008d86: d402 bmi.n 10008d8e +10008d88: 8642 strh r2, [r0, #50] ; 0x32 +10008d8a: 4608 mov r0, r1 +10008d8c: bd30 pop {r4, r5, pc} + +10008d8e : +10008d8e: 1b59 subs r1, r3, r5 +10008d90: 2901 cmp r1, #1 +10008d92: bfac ite ge +10008d94: 2100 movge r1, #0 +10008d96: 1ae9 sublt r1, r5, r3 +10008d98: 8641 strh r1, [r0, #50] ; 0x32 +10008d9a: 2000 movs r0, #0 +10008d9c: bd30 pop {r4, r5, pc} + +10008d9e : +10008d9e: b510 push {r4, lr} +10008da0: 4604 mov r4, r0 +10008da2: f104 0022 add.w r0, r4, #34 ; 0x22 +10008da6: 89c2 ldrh r2, [r0, #14] +10008da8: 1889 adds r1, r1, r2 +10008daa: b289 uxth r1, r1 +10008dac: f640 3269 movw r2, #2921 ; 0xb69 +10008db0: 4291 cmp r1, r2 +10008db2: bfa8 it ge +10008db4: f640 3168 movwge r1, #2920 ; 0xb68 +10008db8: 81c1 strh r1, [r0, #14] +10008dba: 4620 mov r0, r4 +10008dbc: f7ff ffd5 bl 10008d6a +10008dc0: f240 21da movw r1, #730 ; 0x2da +10008dc4: 4288 cmp r0, r1 +10008dc6: db0a blt.n 10008dde +10008dc8: f894 0022 ldrb.w r0, [r4, #34] ; 0x22 +10008dcc: f040 0002 orr.w r0, r0, #2 +10008dd0: f884 0022 strb.w r0, [r4, #34] ; 0x22 +10008dd4: 4620 mov r0, r4 +10008dd6: e8bd 4010 ldmia.w sp!, {r4, lr} +10008dda: f001 b918 b.w 1000a00e + +10008dde : +10008dde: bd10 pop {r4, pc} + +10008de0 : +10008de0: b570 push {r4, r5, r6, lr} +10008de2: 2100 movs r1, #0 +10008de4: f20f 7208 addw r2, pc, #1800 ; 0x708 +10008de8: f8df 36b4 ldr.w r3, [pc, #1716] ; 100094a0 + +10008dec : +10008dec: 8818 ldrh r0, [r3, #0] +10008dee: 1c44 adds r4, r0, #1 +10008df0: f64f 75ff movw r5, #65535 ; 0xffff +10008df4: 42a8 cmp r0, r5 +10008df6: bf08 it eq +10008df8: f44f 4440 moveq.w r4, #49152 ; 0xc000 +10008dfc: 801c strh r4, [r3, #0] +10008dfe: 2400 movs r4, #0 +10008e00: 8818 ldrh r0, [r3, #0] + +10008e02 : +10008e02: f852 5024 ldr.w r5, [r2, r4, lsl #2] +10008e06: 682d ldr r5, [r5, #0] +10008e08: e000 b.n 10008e0c + +10008e0a : +10008e0a: 68ed ldr r5, [r5, #12] + +10008e0c : +10008e0c: b14d cbz r5, 10008e22 +10008e0e: 8bee ldrh r6, [r5, #30] +10008e10: 4286 cmp r6, r0 +10008e12: d1fa bne.n 10008e0a +10008e14: 1c49 adds r1, r1, #1 +10008e16: b289 uxth r1, r1 +10008e18: f5b1 4f80 cmp.w r1, #16384 ; 0x4000 +10008e1c: dbe6 blt.n 10008dec +10008e1e: 2000 movs r0, #0 +10008e20: bd70 pop {r4, r5, r6, pc} + +10008e22 : +10008e22: 1c64 adds r4, r4, #1 +10008e24: b2e4 uxtb r4, r4 +10008e26: 2c04 cmp r4, #4 +10008e28: dbeb blt.n 10008e02 +10008e2a: bd70 pop {r4, r5, r6, pc} + +10008e2c : +10008e2c: b5f8 push {r3, r4, r5, r6, r7, lr} +10008e2e: 4604 mov r4, r0 +10008e30: 460e mov r6, r1 +10008e32: 69a0 ldr r0, [r4, #24] +10008e34: 461f mov r7, r3 +10008e36: b110 cbz r0, 10008e3e +10008e38: f06f 0008 mvn.w r0, #8 +10008e3c: bdf2 pop {r1, r4, r5, r6, r7, pc} + +10008e3e : +10008e3e: b176 cbz r6, 10008e5e +10008e40: 6830 ldr r0, [r6, #0] +10008e42: 6060 str r0, [r4, #4] +10008e44: 8422 strh r2, [r4, #32] +10008e46: 2c00 cmp r4, #0 +10008e48: bf1c itt ne +10008e4a: 6820 ldrne r0, [r4, #0] +10008e4c: 2800 cmpne r0, #0 +10008e4e: d109 bne.n 10008e64 +10008e50: 1d20 adds r0, r4, #4 +10008e52: f002 ff2b bl 1000bcac +10008e56: b918 cbnz r0, 10008e60 +10008e58: f06f 0003 mvn.w r0, #3 +10008e5c: bdf2 pop {r1, r4, r5, r6, r7, pc} + +10008e5e : +10008e5e: e050 b.n 10008f02 + +10008e60 : +10008e60: 6840 ldr r0, [r0, #4] +10008e62: 6020 str r0, [r4, #0] + +10008e64 : +10008e64: 8be5 ldrh r5, [r4, #30] +10008e66: b925 cbnz r5, 10008e72 +10008e68: f7ff ffba bl 10008de0 +10008e6c: 83e0 strh r0, [r4, #30] +10008e6e: b900 cbnz r0, 10008e72 +10008e70: e04a b.n 10008f08 + +10008e72 : +10008e72: f000 fb08 bl 10009486 +10008e76: 2100 movs r1, #0 +10008e78: 62e1 str r1, [r4, #44] ; 0x2c +10008e7a: 6560 str r0, [r4, #84] ; 0x54 +10008e7c: 1e40 subs r0, r0, #1 +10008e7e: 64e0 str r0, [r4, #76] ; 0x4c +10008e80: 6620 str r0, [r4, #96] ; 0x60 +10008e82: f640 3068 movw r0, #2920 ; 0xb68 +10008e86: 8620 strh r0, [r4, #48] ; 0x30 +10008e88: 8660 strh r0, [r4, #50] ; 0x32 +10008e8a: 6ae1 ldr r1, [r4, #44] ; 0x2c +10008e8c: 6361 str r1, [r4, #52] ; 0x34 +10008e8e: f8a4 0064 strh.w r0, [r4, #100] ; 0x64 +10008e92: 4631 mov r1, r6 +10008e94: f44f 7006 mov.w r0, #536 ; 0x218 +10008e98: 8760 strh r0, [r4, #58] ; 0x3a +10008e9a: f000 fb0b bl 100094b4 +10008e9e: 8760 strh r0, [r4, #58] ; 0x3a +10008ea0: 210a movs r1, #10 +10008ea2: 2001 movs r0, #1 +10008ea4: f8a4 0050 strh.w r0, [r4, #80] ; 0x50 +10008ea8: 8f60 ldrh r0, [r4, #58] ; 0x3a +10008eaa: 4348 muls r0, r1 +10008eac: f8a4 0052 strh.w r0, [r4, #82] ; 0x52 +10008eb0: f8c4 7088 str.w r7, [r4, #136] ; 0x88 +10008eb4: 2102 movs r1, #2 +10008eb6: 4620 mov r0, r4 +10008eb8: f001 f832 bl 10009f20 +10008ebc: 0006 movs r6, r0 +10008ebe: d11e bne.n 10008efe +10008ec0: 2002 movs r0, #2 +10008ec2: 61a0 str r0, [r4, #24] +10008ec4: f8df 75d0 ldr.w r7, [pc, #1488] ; 10009498 +10008ec8: b17d cbz r5, 10008eea +10008eca: 68b8 ldr r0, [r7, #8] +10008ecc: 42a0 cmp r0, r4 +10008ece: d102 bne.n 10008ed6 +10008ed0: 68c0 ldr r0, [r0, #12] +10008ed2: 60b8 str r0, [r7, #8] +10008ed4: e007 b.n 10008ee6 + +10008ed6 : +10008ed6: 61b8 str r0, [r7, #24] +10008ed8: 69b9 ldr r1, [r7, #24] +10008eda: b121 cbz r1, 10008ee6 +10008edc: 68c8 ldr r0, [r1, #12] +10008ede: 42a0 cmp r0, r4 +10008ee0: d1f9 bne.n 10008ed6 +10008ee2: 68e0 ldr r0, [r4, #12] +10008ee4: 60c8 str r0, [r1, #12] + +10008ee6 : +10008ee6: 2000 movs r0, #0 +10008ee8: 60e0 str r0, [r4, #12] + +10008eea : +10008eea: 6938 ldr r0, [r7, #16] +10008eec: 60e0 str r0, [r4, #12] +10008eee: 613c str r4, [r7, #16] +10008ef0: f002 fa8d bl 1000b40e +10008ef4: 2001 movs r0, #1 +10008ef6: 7038 strb r0, [r7, #0] +10008ef8: 4620 mov r0, r4 +10008efa: f001 f888 bl 1000a00e + +10008efe : +10008efe: 4630 mov r0, r6 +10008f00: bdf2 pop {r1, r4, r5, r6, r7, pc} + +10008f02 : +10008f02: f06f 0005 mvn.w r0, #5 +10008f06: bdf2 pop {r1, r4, r5, r6, r7, pc} + +10008f08 : +10008f08: f06f 0001 mvn.w r0, #1 +10008f0c: bdf2 pop {r1, r4, r5, r6, r7, pc} + +10008f0e : +10008f0e: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +10008f12: f8df 4584 ldr.w r4, [pc, #1412] ; 10009498 +10008f16: 6860 ldr r0, [r4, #4] +10008f18: 1c40 adds r0, r0, #1 +10008f1a: 6060 str r0, [r4, #4] +10008f1c: b083 sub sp, #12 +10008f1e: 7860 ldrb r0, [r4, #1] +10008f20: 1c40 adds r0, r0, #1 +10008f22: 7060 strb r0, [r4, #1] + +10008f24 : +10008f24: 6926 ldr r6, [r4, #16] +10008f26: 2500 movs r5, #0 +10008f28: e000 b.n 10008f2c + +10008f2a : +10008f2a: 68f6 ldr r6, [r6, #12] + +10008f2c : +10008f2c: 2e00 cmp r6, #0 +10008f2e: f000 8112 beq.w 10009156 +10008f32: 7860 ldrb r0, [r4, #1] +10008f34: f106 0122 add.w r1, r6, #34 ; 0x22 +10008f38: 78ca ldrb r2, [r1, #3] +10008f3a: 4282 cmp r2, r0 +10008f3c: d0f5 beq.n 10008f2a +10008f3e: 70c8 strb r0, [r1, #3] +10008f40: 2700 movs r7, #0 +10008f42: 69b1 ldr r1, [r6, #24] +10008f44: 46bb mov fp, r7 +10008f46: f106 0854 add.w r8, r6, #84 ; 0x54 +10008f4a: f106 0928 add.w r9, r6, #40 ; 0x28 +10008f4e: f106 0a98 add.w sl, r6, #152 ; 0x98 +10008f52: 2902 cmp r1, #2 +10008f54: bf02 ittt eq +10008f56: f896 004a ldrbeq.w r0, [r6, #74] ; 0x4a +10008f5a: 2806 cmpeq r0, #6 +10008f5c: 2701 moveq r7, #1 +10008f5e: d063 beq.n 10009028 +10008f60: f896 204a ldrb.w r2, [r6, #74] ; 0x4a +10008f64: 2a0c cmp r2, #12 +10008f66: bf08 it eq +10008f68: 2701 moveq r7, #1 +10008f6a: d050 beq.n 1000900e +10008f6c: f89a 0001 ldrb.w r0, [sl, #1] +10008f70: b1b8 cbz r0, 10008fa2 +10008f72: f896 1098 ldrb.w r1, [r6, #152] ; 0x98 +10008f76: f20f 5270 addw r2, pc, #1392 ; 0x570 +10008f7a: 1c49 adds r1, r1, #1 +10008f7c: 1882 adds r2, r0, r2 +10008f7e: f886 1098 strb.w r1, [r6, #152] ; 0x98 +10008f82: b2c9 uxtb r1, r1 +10008f84: f812 2c01 ldrb.w r2, [r2, #-1] +10008f88: 4291 cmp r1, r2 +10008f8a: d340 bcc.n 1000900e +10008f8c: f886 b098 strb.w fp, [r6, #152] ; 0x98 +10008f90: 2807 cmp r0, #7 +10008f92: bf3c itt cc +10008f94: 1c40 addcc r0, r0, #1 +10008f96: f88a 0001 strbcc.w r0, [sl, #1] +10008f9a: 4630 mov r0, r6 +10008f9c: f001 fa1b bl 1000a3d6 +10008fa0: e035 b.n 1000900e + +10008fa2 : +10008fa2: f9b9 0010 ldrsh.w r0, [r9, #16] +10008fa6: 2800 cmp r0, #0 +10008fa8: bf5c itt pl +10008faa: 1c40 addpl r0, r0, #1 +10008fac: f8a9 0010 strhpl.w r0, [r9, #16] +10008fb0: f8d8 0020 ldr.w r0, [r8, #32] +10008fb4: b358 cbz r0, 1000900e +10008fb6: f9b9 0010 ldrsh.w r0, [r9, #16] +10008fba: f9b9 3020 ldrsh.w r3, [r9, #32] +10008fbe: 4298 cmp r0, r3 +10008fc0: db25 blt.n 1000900e +10008fc2: 2902 cmp r1, #2 +10008fc4: d00b beq.n 10008fde +10008fc6: f9b9 001c ldrsh.w r0, [r9, #28] +10008fca: f9b9 101e ldrsh.w r1, [r9, #30] +10008fce: eb01 00e0 add.w r0, r1, r0, asr #3 +10008fd2: f20f 5104 addw r1, pc, #1284 ; 0x504 +10008fd6: 5651 ldrsb r1, [r2, r1] +10008fd8: 4088 lsls r0, r1 +10008fda: f8a9 0020 strh.w r0, [r9, #32] + +10008fde : +10008fde: f106 004a add.w r0, r6, #74 ; 0x4a +10008fe2: f8a9 b010 strh.w fp, [r9, #16] +10008fe6: 88c1 ldrh r1, [r0, #6] +10008fe8: f8b8 2010 ldrh.w r2, [r8, #16] +10008fec: 4291 cmp r1, r2 +10008fee: bf88 it hi +10008ff0: 4611 movhi r1, r2 +10008ff2: f8b9 2012 ldrh.w r2, [r9, #18] +10008ff6: 0849 lsrs r1, r1, #1 +10008ff8: ebb1 0f42 cmp.w r1, r2, lsl #1 +10008ffc: bfb8 it lt +10008ffe: 0051 lsllt r1, r2, #1 +10009000: 8101 strh r1, [r0, #8] +10009002: f8b9 1012 ldrh.w r1, [r9, #18] +10009006: 80c1 strh r1, [r0, #6] +10009008: 4630 mov r0, r6 +1000900a: f001 f957 bl 1000a2bc + +1000900e : +1000900e: 69b0 ldr r0, [r6, #24] +10009010: 2806 cmp r0, #6 +10009012: d109 bne.n 10009028 +10009014: f896 0022 ldrb.w r0, [r6, #34] ; 0x22 +10009018: 06c0 lsls r0, r0, #27 +1000901a: d505 bpl.n 10009028 +1000901c: 6860 ldr r0, [r4, #4] +1000901e: 6ab1 ldr r1, [r6, #40] ; 0x28 +10009020: 1a40 subs r0, r0, r1 +10009022: 2829 cmp r0, #41 ; 0x29 +10009024: bf28 it cs +10009026: 1c7f addcs r7, r7, #1 + +10009028 : +10009028: 7a30 ldrb r0, [r6, #8] +1000902a: 0700 lsls r0, r0, #28 +1000902c: d52a bpl.n 10009084 +1000902e: 69b0 ldr r0, [r6, #24] +10009030: 2804 cmp r0, #4 +10009032: bf18 it ne +10009034: 2807 cmpne r0, #7 +10009036: d125 bne.n 10009084 +10009038: 6860 ldr r0, [r4, #4] +1000903a: 6ab1 ldr r1, [r6, #40] ; 0x28 +1000903c: f8df 2464 ldr.w r2, [pc, #1124] ; 100094a4 +10009040: 1a40 subs r0, r0, r1 +10009042: f8d8 1040 ldr.w r1, [r8, #64] ; 0x40 +10009046: 1852 adds r2, r2, r1 +10009048: f44f 73fa mov.w r3, #500 ; 0x1f4 +1000904c: fbb2 f2f3 udiv r2, r2, r3 +10009050: 4282 cmp r2, r0 +10009052: d203 bcs.n 1000905c +10009054: 1c7f adds r7, r7, #1 +10009056: f04f 0b01 mov.w fp, #1 +1000905a: e013 b.n 10009084 + +1000905c : +1000905c: f89a 2002 ldrb.w r2, [sl, #2] +10009060: f8df 3444 ldr.w r3, [pc, #1092] ; 100094a8 +10009064: fb03 1102 mla r1, r3, r2, r1 +10009068: f44f 72fa mov.w r2, #500 ; 0x1f4 +1000906c: fbb1 f1f2 udiv r1, r1, r2 +10009070: 4281 cmp r1, r0 +10009072: d207 bcs.n 10009084 +10009074: 4630 mov r0, r6 +10009076: f001 f986 bl 1000a386 +1000907a: f89a 0002 ldrb.w r0, [sl, #2] +1000907e: 1c40 adds r0, r0, #1 +10009080: f88a 0002 strb.w r0, [sl, #2] + +10009084 : +10009084: f8d8 0024 ldr.w r0, [r8, #36] ; 0x24 +10009088: b168 cbz r0, 100090a6 +1000908a: 6861 ldr r1, [r4, #4] +1000908c: 6ab2 ldr r2, [r6, #40] ; 0x28 +1000908e: 1a89 subs r1, r1, r2 +10009090: f9b9 2020 ldrsh.w r2, [r9, #32] +10009094: 2306 movs r3, #6 +10009096: 435a muls r2, r3 +10009098: 4291 cmp r1, r2 +1000909a: d304 bcc.n 100090a6 +1000909c: f000 f8dc bl 10009258 +100090a0: 2000 movs r0, #0 +100090a2: f8c8 0024 str.w r0, [r8, #36] ; 0x24 + +100090a6 : +100090a6: 1c78 adds r0, r7, #1 +100090a8: 69b1 ldr r1, [r6, #24] +100090aa: 2903 cmp r1, #3 +100090ac: d104 bne.n 100090b8 +100090ae: 6861 ldr r1, [r4, #4] +100090b0: 6ab2 ldr r2, [r6, #40] ; 0x28 +100090b2: 1a89 subs r1, r1, r2 +100090b4: 2929 cmp r1, #41 ; 0x29 +100090b6: e005 b.n 100090c4 + +100090b8 : +100090b8: 2909 cmp r1, #9 +100090ba: d105 bne.n 100090c8 +100090bc: 6861 ldr r1, [r4, #4] +100090be: 6ab2 ldr r2, [r6, #40] ; 0x28 +100090c0: 1a89 subs r1, r1, r2 +100090c2: 29f1 cmp r1, #241 ; 0xf1 + +100090c4 : +100090c4: bf28 it cs +100090c6: 4607 movcs r7, r0 + +100090c8 : +100090c8: b2f8 uxtb r0, r7 +100090ca: b338 cbz r0, 1000911c +100090cc: 4630 mov r0, r6 +100090ce: f000 f98d bl 100093ec +100090d2: 68f0 ldr r0, [r6, #12] +100090d4: 2d00 cmp r5, #0 +100090d6: bf14 ite ne +100090d8: 60e8 strne r0, [r5, #12] +100090da: 6120 streq r0, [r4, #16] +100090dc: f1bb 0f00 cmp.w fp, #0 +100090e0: d00a beq.n 100090f8 +100090e2: 8c30 ldrh r0, [r6, #32] +100090e4: 9001 str r0, [sp, #4] +100090e6: 1d33 adds r3, r6, #4 +100090e8: 8bf0 ldrh r0, [r6, #30] +100090ea: 9000 str r0, [sp, #0] +100090ec: 4632 mov r2, r6 +100090ee: f8d9 1004 ldr.w r1, [r9, #4] +100090f2: 6d70 ldr r0, [r6, #84] ; 0x54 +100090f4: f001 f89e bl 1000a234 + +100090f8 : +100090f8: 6937 ldr r7, [r6, #16] +100090fa: f8d8 b03c ldr.w fp, [r8, #60] ; 0x3c +100090fe: f000 f843 bl 10009188 + +10009102 : +10009102: 2000 movs r0, #0 +10009104: 7020 strb r0, [r4, #0] +10009106: ea5f 000b movs.w r0, fp +1000910a: d023 beq.n 10009154 +1000910c: f06f 0109 mvn.w r1, #9 +10009110: 4638 mov r0, r7 +10009112: 47d8 blx fp +10009114: 7820 ldrb r0, [r4, #0] +10009116: 2800 cmp r0, #0 +10009118: d01c beq.n 10009154 + +1000911a : +1000911a: e703 b.n 10008f24 + +1000911c : +1000911c: 4635 mov r5, r6 +1000911e: f105 0010 add.w r0, r5, #16 +10009122: 7cc1 ldrb r1, [r0, #19] +10009124: 68f6 ldr r6, [r6, #12] +10009126: 1c49 adds r1, r1, #1 +10009128: 74c1 strb r1, [r0, #19] +1000912a: b2c9 uxtb r1, r1 +1000912c: 7d02 ldrb r2, [r0, #20] +1000912e: 4291 cmp r1, r2 +10009130: d310 bcc.n 10009154 +10009132: 2100 movs r1, #0 +10009134: 74c1 strb r1, [r0, #19] +10009136: 7021 strb r1, [r4, #0] +10009138: 6fc2 ldr r2, [r0, #124] ; 0x7c +1000913a: 0010 movs r0, r2 +1000913c: d007 beq.n 1000914e +1000913e: 6928 ldr r0, [r5, #16] +10009140: 4629 mov r1, r5 +10009142: 4790 blx r2 +10009144: 7821 ldrb r1, [r4, #0] +10009146: 2900 cmp r1, #0 +10009148: d1e7 bne.n 1000911a +1000914a: 2800 cmp r0, #0 +1000914c: d102 bne.n 10009154 + +1000914e : +1000914e: 4628 mov r0, r5 +10009150: f000 ff5d bl 1000a00e + +10009154 : +10009154: e6ea b.n 10008f2c + +10009156 : +10009156: 2500 movs r5, #0 +10009158: 6966 ldr r6, [r4, #20] +1000915a: e001 b.n 10009160 + +1000915c : +1000915c: f000 f814 bl 10009188 + +10009160 : +10009160: b186 cbz r6, 10009184 +10009162: 6860 ldr r0, [r4, #4] +10009164: 6ab1 ldr r1, [r6, #40] ; 0x28 +10009166: 1a40 subs r0, r0, r1 +10009168: 28f1 cmp r0, #241 ; 0xf1 +1000916a: d308 bcc.n 1000917e +1000916c: 4630 mov r0, r6 +1000916e: f000 f93d bl 100093ec +10009172: 68f0 ldr r0, [r6, #12] +10009174: 2d00 cmp r5, #0 +10009176: bf14 ite ne +10009178: 60e8 strne r0, [r5, #12] +1000917a: 6160 streq r0, [r4, #20] +1000917c: e7ee b.n 1000915c + +1000917e : +1000917e: 4635 mov r5, r6 +10009180: 68f6 ldr r6, [r6, #12] +10009182: e7ed b.n 10009160 + +10009184 : +10009184: e8bd 8ff7 ldmia.w sp!, {r0, r1, r2, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +10009188 : +10009188: 4631 mov r1, r6 +1000918a: 68f6 ldr r6, [r6, #12] +1000918c: 2002 movs r0, #2 +1000918e: f7ff b8bb b.w 10008308 + +10009192 : +10009192: b5f8 push {r3, r4, r5, r6, r7, lr} +10009194: 4cc0 ldr r4, [pc, #768] ; (10009498 ) +10009196: 7860 ldrb r0, [r4, #1] +10009198: 1c40 adds r0, r0, #1 +1000919a: 7060 strb r0, [r4, #1] + +1000919c : +1000919c: 6925 ldr r5, [r4, #16] +1000919e: e01e b.n 100091de + +100091a0 : +100091a0: f105 060c add.w r6, r5, #12 +100091a4: 7e71 ldrb r1, [r6, #25] +100091a6: 4281 cmp r1, r0 +100091a8: d0fa beq.n 100091a0 +100091aa: 7670 strb r0, [r6, #25] +100091ac: 7db0 ldrb r0, [r6, #22] +100091ae: 07c1 lsls r1, r0, #31 +100091b0: d509 bpl.n 100091c6 +100091b2: f040 0002 orr.w r0, r0, #2 +100091b6: 75b0 strb r0, [r6, #22] +100091b8: 4628 mov r0, r5 +100091ba: f000 ff28 bl 1000a00e +100091be: 7db0 ldrb r0, [r6, #22] +100091c0: f000 00fc and.w r0, r0, #252 ; 0xfc +100091c4: 75b0 strb r0, [r6, #22] + +100091c6 : +100091c6: 68ef ldr r7, [r5, #12] +100091c8: 6f30 ldr r0, [r6, #112] ; 0x70 +100091ca: b138 cbz r0, 100091dc +100091cc: 2000 movs r0, #0 +100091ce: 7020 strb r0, [r4, #0] +100091d0: 4628 mov r0, r5 +100091d2: f000 f808 bl 100091e6 +100091d6: 7820 ldrb r0, [r4, #0] +100091d8: 2800 cmp r0, #0 +100091da: d1df bne.n 1000919c + +100091dc : +100091dc: 463d mov r5, r7 + +100091de : +100091de: 7860 ldrb r0, [r4, #1] +100091e0: 2d00 cmp r5, #0 +100091e2: d1dd bne.n 100091a0 +100091e4: bdf1 pop {r0, r4, r5, r6, r7, pc} + +100091e6 : +100091e6: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +100091ea: 4604 mov r4, r0 +100091ec: f104 0510 add.w r5, r4, #16 +100091f0: 2000 movs r0, #0 +100091f2: 6eef ldr r7, [r5, #108] ; 0x6c +100091f4: 7b7e ldrb r6, [r7, #13] +100091f6: 66e8 str r0, [r5, #108] ; 0x6c +100091f8: f8d5 8074 ldr.w r8, [r5, #116] ; 0x74 +100091fc: ea5f 0008 movs.w r0, r8 +10009200: d005 beq.n 1000920e +10009202: 6920 ldr r0, [r4, #16] +10009204: 2300 movs r3, #0 +10009206: 463a mov r2, r7 +10009208: 4621 mov r1, r4 +1000920a: 47c0 blx r8 +1000920c: e005 b.n 1000921a + +1000920e : +1000920e: 2300 movs r3, #0 +10009210: 463a mov r2, r7 +10009212: 4621 mov r1, r4 +10009214: 2000 movs r0, #0 +10009216: f000 f848 bl 100092aa + +1000921a : +1000921a: f06f 0809 mvn.w r8, #9 +1000921e: b998 cbnz r0, 10009248 +10009220: 06b0 lsls r0, r6, #26 +10009222: d516 bpl.n 10009252 +10009224: 8c28 ldrh r0, [r5, #32] +10009226: f640 3168 movw r1, #2920 ; 0xb68 +1000922a: 4288 cmp r0, r1 +1000922c: bf1c itt ne +1000922e: 1c40 addne r0, r0, #1 +10009230: 8428 strhne r0, [r5, #32] +10009232: 6f6d ldr r5, [r5, #116] ; 0x74 +10009234: 0028 movs r0, r5 +10009236: d00c beq.n 10009252 +10009238: 6920 ldr r0, [r4, #16] +1000923a: 2300 movs r3, #0 +1000923c: 2200 movs r2, #0 +1000923e: 4621 mov r1, r4 +10009240: 47a8 blx r5 +10009242: 4540 cmp r0, r8 +10009244: d105 bne.n 10009252 +10009246: e001 b.n 1000924c + +10009248 : +10009248: 4540 cmp r0, r8 +1000924a: d101 bne.n 10009250 + +1000924c : +1000924c: 4640 mov r0, r8 +1000924e: e001 b.n 10009254 + +10009250 : +10009250: 66ef str r7, [r5, #108] ; 0x6c + +10009252 : +10009252: 2000 movs r0, #0 + +10009254 : +10009254: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +10009258 : +10009258: b510 push {r4, lr} +1000925a: 2800 cmp r0, #0 +1000925c: e003 b.n 10009266 + +1000925e : +1000925e: 6804 ldr r4, [r0, #0] +10009260: f000 f803 bl 1000926a +10009264: 0020 movs r0, r4 + +10009266 : +10009266: d1fa bne.n 1000925e +10009268: bd10 pop {r4, pc} + +1000926a : +1000926a: b510 push {r4, lr} +1000926c: 0004 movs r4, r0 +1000926e: d009 beq.n 10009284 +10009270: 6860 ldr r0, [r4, #4] +10009272: b108 cbz r0, 10009278 +10009274: f7ff fab8 bl 100087e8 + +10009278 : +10009278: 4621 mov r1, r4 +1000927a: e8bd 4010 ldmia.w sp!, {r4, lr} +1000927e: 2004 movs r0, #4 +10009280: f7ff b842 b.w 10008308 + +10009284 : +10009284: bd10 pop {r4, pc} + +10009286 : +10009286: b538 push {r3, r4, r5, lr} +10009288: 4604 mov r4, r0 +1000928a: 2004 movs r0, #4 +1000928c: f7ff f829 bl 100082e2 +10009290: 0005 movs r5, r0 +10009292: d101 bne.n 10009298 +10009294: 2000 movs r0, #0 +10009296: bd32 pop {r1, r4, r5, pc} + +10009298 : +10009298: 2214 movs r2, #20 +1000929a: 4621 mov r1, r4 +1000929c: f003 f854 bl 1000c348 +100092a0: 6868 ldr r0, [r5, #4] +100092a2: f7ff fad7 bl 10008854 +100092a6: 4628 mov r0, r5 +100092a8: bd32 pop {r1, r4, r5, pc} + +100092aa : +100092aa: b510 push {r4, lr} +100092ac: 4608 mov r0, r1 +100092ae: 0014 movs r4, r2 +100092b0: d007 beq.n 100092c2 +100092b2: 8921 ldrh r1, [r4, #8] +100092b4: f7ff fd73 bl 10008d9e +100092b8: 4620 mov r0, r4 +100092ba: f7ff fa95 bl 100087e8 + +100092be : +100092be: 2000 movs r0, #0 +100092c0: bd10 pop {r4, pc} + +100092c2 : +100092c2: 2b00 cmp r3, #0 +100092c4: d1fb bne.n 100092be +100092c6: e8bd 4010 ldmia.w sp!, {r4, lr} +100092ca: e45d b.n 10008b88 + +100092cc : +100092cc: b5f8 push {r3, r4, r5, r6, r7, lr} +100092ce: 4605 mov r5, r0 +100092d0: 2002 movs r0, #2 +100092d2: f7ff f806 bl 100082e2 +100092d6: 0006 movs r6, r0 +100092d8: 4c6f ldr r4, [pc, #444] ; (10009498 ) +100092da: d133 bne.n 10009344 +100092dc: 6962 ldr r2, [r4, #20] +100092de: 2100 movs r1, #0 +100092e0: 2000 movs r0, #0 +100092e2: e007 b.n 100092f4 + +100092e4 : +100092e4: 6863 ldr r3, [r4, #4] +100092e6: 6a96 ldr r6, [r2, #40] ; 0x28 +100092e8: 1b9b subs r3, r3, r6 +100092ea: 428b cmp r3, r1 +100092ec: bf24 itt cs +100092ee: 4619 movcs r1, r3 +100092f0: 4610 movcs r0, r2 +100092f2: 68d2 ldr r2, [r2, #12] + +100092f4 : +100092f4: 2a00 cmp r2, #0 +100092f6: d1f5 bne.n 100092e4 +100092f8: b108 cbz r0, 100092fe +100092fa: f7ff fcbf bl 10008c7c + +100092fe : +100092fe: 2002 movs r0, #2 +10009300: f7fe ffef bl 100082e2 +10009304: 0006 movs r6, r0 +10009306: d11d bne.n 10009344 +10009308: 6923 ldr r3, [r4, #16] +1000930a: 217f movs r1, #127 ; 0x7f +1000930c: 2200 movs r2, #0 +1000930e: 2000 movs r0, #0 +10009310: e00f b.n 10009332 + +10009312 : +10009312: 7f1e ldrb r6, [r3, #28] +10009314: 42b5 cmp r5, r6 +10009316: bf28 it cs +10009318: 42b1 cmpcs r1, r6 +1000931a: bf21 itttt cs +1000931c: 6867 ldrcs r7, [r4, #4] +1000931e: f8d3 c028 ldrcs.w ip, [r3, #40] ; 0x28 +10009322: eba7 070c subcs.w r7, r7, ip +10009326: 4297 cmpcs r7, r2 +10009328: d302 bcc.n 10009330 +1000932a: 463a mov r2, r7 +1000932c: 4618 mov r0, r3 +1000932e: 4631 mov r1, r6 + +10009330 : +10009330: 68db ldr r3, [r3, #12] + +10009332 : +10009332: 2b00 cmp r3, #0 +10009334: d1ed bne.n 10009312 +10009336: b108 cbz r0, 1000933c +10009338: f7ff fca0 bl 10008c7c + +1000933c : +1000933c: 2002 movs r0, #2 +1000933e: f7fe ffd0 bl 100082e2 +10009342: 4606 mov r6, r0 + +10009344 : +10009344: 2e00 cmp r6, #0 +10009346: d03b beq.n 100093c0 +10009348: 229c movs r2, #156 ; 0x9c +1000934a: 2100 movs r1, #0 +1000934c: 4630 mov r0, r6 +1000934e: f002 fffd bl 1000c34c +10009352: f106 0709 add.w r7, r6, #9 +10009356: f641 4084 movw r0, #7300 ; 0x1c84 +1000935a: 74fd strb r5, [r7, #19] +1000935c: f8a6 006a strh.w r0, [r6, #106] ; 0x6a +10009360: f106 0528 add.w r5, r6, #40 ; 0x28 +10009364: 2000 movs r0, #0 +10009366: f8a6 006c strh.w r0, [r6, #108] ; 0x6c +1000936a: f640 3068 movw r0, #2920 ; 0xb68 +1000936e: 8128 strh r0, [r5, #8] +10009370: 8168 strh r0, [r5, #10] +10009372: 2000 movs r0, #0 +10009374: 7270 strb r0, [r6, #9] +10009376: 20ff movs r0, #255 ; 0xff +10009378: 7078 strb r0, [r7, #1] +1000937a: f44f 7006 mov.w r0, #536 ; 0x218 +1000937e: 8268 strh r0, [r5, #18] +10009380: 2006 movs r0, #6 +10009382: 8428 strh r0, [r5, #32] +10009384: 2000 movs r0, #0 +10009386: 83a8 strh r0, [r5, #28] +10009388: 2006 movs r0, #6 +1000938a: 83e8 strh r0, [r5, #30] +1000938c: f04f 30ff mov.w r0, #4294967295 +10009390: 8228 strh r0, [r5, #16] +10009392: 2001 movs r0, #1 +10009394: 8528 strh r0, [r5, #40] ; 0x28 +10009396: f000 f876 bl 10009486 +1000939a: 6368 str r0, [r5, #52] ; 0x34 +1000939c: 62e8 str r0, [r5, #44] ; 0x2c +1000939e: 6268 str r0, [r5, #36] ; 0x24 +100093a0: 63a8 str r0, [r5, #56] ; 0x38 +100093a2: 4942 ldr r1, [pc, #264] ; (100094ac ) +100093a4: 6860 ldr r0, [r4, #4] +100093a6: 62b0 str r0, [r6, #40] ; 0x28 +100093a8: 7860 ldrb r0, [r4, #1] +100093aa: 7738 strb r0, [r7, #28] +100093ac: 2000 movs r0, #0 +100093ae: 76b8 strb r0, [r7, #26] +100093b0: 483f ldr r0, [pc, #252] ; (100094b0 ) +100093b2: f8c6 0084 str.w r0, [r6, #132] ; 0x84 +100093b6: f106 0084 add.w r0, r6, #132 ; 0x84 +100093ba: 6101 str r1, [r0, #16] +100093bc: 2100 movs r1, #0 +100093be: 7581 strb r1, [r0, #22] + +100093c0 : +100093c0: 4630 mov r0, r6 +100093c2: bdf2 pop {r1, r4, r5, r6, r7, pc} + +100093c4 : +100093c4: 2040 movs r0, #64 ; 0x40 +100093c6: e781 b.n 100092cc + +100093c8 : +100093c8: 6101 str r1, [r0, #16] +100093ca: 4770 bx lr + +100093cc : +100093cc: f8c0 1084 str.w r1, [r0, #132] ; 0x84 +100093d0: 4770 bx lr + +100093d2 : +100093d2: f8c0 1080 str.w r1, [r0, #128] ; 0x80 +100093d6: 4770 bx lr + +100093d8 : +100093d8: f8c0 1090 str.w r1, [r0, #144] ; 0x90 +100093dc: 4770 bx lr + +100093de : +100093de: 6141 str r1, [r0, #20] +100093e0: 4770 bx lr + +100093e2 : +100093e2: f8c0 108c str.w r1, [r0, #140] ; 0x8c +100093e6: f880 2024 strb.w r2, [r0, #36] ; 0x24 +100093ea: 4770 bx lr + +100093ec : +100093ec: b538 push {r3, r4, r5, lr} +100093ee: 4604 mov r4, r0 +100093f0: 69a0 ldr r0, [r4, #24] +100093f2: 2800 cmp r0, #0 +100093f4: bf1c itt ne +100093f6: 280a cmpne r0, #10 +100093f8: 2801 cmpne r0, #1 +100093fa: d01a beq.n 10009432 +100093fc: f104 0570 add.w r5, r4, #112 ; 0x70 +10009400: 68e8 ldr r0, [r5, #12] +10009402: b118 cbz r0, 1000940c +10009404: f7ff f9f0 bl 100087e8 +10009408: 2000 movs r0, #0 +1000940a: 60e8 str r0, [r5, #12] + +1000940c : +1000940c: 68a8 ldr r0, [r5, #8] +1000940e: f7ff ff23 bl 10009258 +10009412: 2000 movs r0, #0 +10009414: 60a8 str r0, [r5, #8] +10009416: f04f 30ff mov.w r0, #4294967295 +1000941a: 8720 strh r0, [r4, #56] ; 0x38 +1000941c: 6f20 ldr r0, [r4, #112] ; 0x70 +1000941e: f7ff ff1b bl 10009258 +10009422: 6868 ldr r0, [r5, #4] +10009424: f7ff ff18 bl 10009258 +10009428: 2000 movs r0, #0 +1000942a: 6720 str r0, [r4, #112] ; 0x70 +1000942c: 6068 str r0, [r5, #4] +1000942e: f8a4 006e strh.w r0, [r4, #110] ; 0x6e + +10009432 : +10009432: bd31 pop {r0, r4, r5, pc} + +10009434 : +10009434: b538 push {r3, r4, r5, lr} +10009436: 460c mov r4, r1 +10009438: 6801 ldr r1, [r0, #0] +1000943a: 42a1 cmp r1, r4 +1000943c: d102 bne.n 10009444 +1000943e: 68c9 ldr r1, [r1, #12] +10009440: 6001 str r1, [r0, #0] +10009442: e008 b.n 10009456 + +10009444 : +10009444: 4814 ldr r0, [pc, #80] ; (10009498 ) + +10009446 : +10009446: 6181 str r1, [r0, #24] +10009448: 6982 ldr r2, [r0, #24] +1000944a: b122 cbz r2, 10009456 +1000944c: 68d1 ldr r1, [r2, #12] +1000944e: 42a1 cmp r1, r4 +10009450: d1f9 bne.n 10009446 +10009452: 68e0 ldr r0, [r4, #12] +10009454: 60d0 str r0, [r2, #12] + +10009456 : +10009456: 2000 movs r0, #0 +10009458: 60e0 str r0, [r4, #12] +1000945a: 4620 mov r0, r4 +1000945c: f7ff ffc6 bl 100093ec +10009460: f104 050c add.w r5, r4, #12 +10009464: 68e8 ldr r0, [r5, #12] +10009466: 280a cmp r0, #10 +10009468: bf18 it ne +1000946a: 2801 cmpne r0, #1 +1000946c: d008 beq.n 10009480 +1000946e: 7da8 ldrb r0, [r5, #22] +10009470: 07c1 lsls r1, r0, #31 +10009472: d505 bpl.n 10009480 +10009474: f040 0002 orr.w r0, r0, #2 +10009478: 75a8 strb r0, [r5, #22] +1000947a: 4620 mov r0, r4 +1000947c: f000 fdc7 bl 1000a00e + +10009480 : +10009480: 2000 movs r0, #0 +10009482: 60e8 str r0, [r5, #12] +10009484: bd31 pop {r0, r4, r5, pc} + +10009486 : +10009486: 4904 ldr r1, [pc, #16] ; (10009498 ) +10009488: 69c8 ldr r0, [r1, #28] +1000948a: 684a ldr r2, [r1, #4] +1000948c: 1810 adds r0, r2, r0 +1000948e: 61c8 str r0, [r1, #28] +10009490: 4770 bx lr + ... + +10009494 : +10009494: 8b10 1004 .... + +10009498 : +10009498: 4078 1004 x@.. + +1000949c : +1000949c: 8ceb 1000 .... + +100094a0 : +100094a0: 6e44 1004 Dn.. + +100094a4 : +100094a4: 4cb8 000a .L.. + +100094a8 : +100094a8: 24f8 0001 .$.. + +100094ac : +100094ac: dd00 006d ..m. + +100094b0 : +100094b0: 92ab 1000 .... + +100094b4 : +100094b4: b510 push {r4, lr} +100094b6: 4604 mov r4, r0 +100094b8: 4608 mov r0, r1 +100094ba: f002 fbf7 bl 1000bcac +100094be: 2800 cmp r0, #0 +100094c0: bf1c itt ne +100094c2: 8d00 ldrhne r0, [r0, #40] ; 0x28 +100094c4: 2800 cmpne r0, #0 +100094c6: d004 beq.n 100094d2 +100094c8: 3828 subs r0, #40 ; 0x28 +100094ca: b280 uxth r0, r0 +100094cc: 4284 cmp r4, r0 +100094ce: bf88 it hi +100094d0: 4604 movhi r4, r0 + +100094d2 : +100094d2: 4620 mov r0, r4 +100094d4: bd10 pop {r4, pc} + ... + +100094d8 : +100094d8: 0201 0403 0605 0707 0707 0707 0007 0000 ................ + +100094e8 : +100094e8: 0603 180c 6030 0078 ....0`x. + +100094f0 : +100094f0: 4084 1004 4080 1004 4088 1004 408c 1004 .@...@...@...@.. + +10009500 : +10009500: 4770 bx lr + +10009502 : +10009502: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +10009506: 4604 mov r4, r0 +10009508: b083 sub sp, #12 +1000950a: 6860 ldr r0, [r4, #4] +1000950c: 9001 str r0, [sp, #4] +1000950e: 460d mov r5, r1 +10009510: 7800 ldrb r0, [r0, #0] +10009512: 8921 ldrh r1, [r4, #8] +10009514: f000 020f and.w r2, r0, #15 +10009518: 0092 lsls r2, r2, #2 +1000951a: 3208 adds r2, #8 +1000951c: 4291 cmp r1, r2 +1000951e: f2c0 80b5 blt.w 1000968c +10009522: f000 000f and.w r0, r0, #15 +10009526: 0080 lsls r0, r0, #2 +10009528: 4241 negs r1, r0 +1000952a: b209 sxth r1, r1 +1000952c: 4620 mov r0, r4 +1000952e: f7ff f92a bl 10008786 +10009532: 2800 cmp r0, #0 +10009534: d175 bne.n 10009622 +10009536: 6860 ldr r0, [r4, #4] +10009538: f8df 636c ldr.w r6, [pc, #876] ; 100098a8 +1000953c: 9000 str r0, [sp, #0] +1000953e: 4629 mov r1, r5 +10009540: 6830 ldr r0, [r6, #0] +10009542: f002 ff13 bl 1000c36c +10009546: 4682 mov sl, r0 +10009548: 9800 ldr r0, [sp, #0] +1000954a: 8800 ldrh r0, [r0, #0] +1000954c: f003 f800 bl 1000c550 +10009550: 4680 mov r8, r0 +10009552: 9800 ldr r0, [sp, #0] +10009554: 8840 ldrh r0, [r0, #2] +10009556: f002 fffb bl 1000c550 +1000955a: f8df 9350 ldr.w r9, [pc, #848] ; 100098ac +1000955e: 2700 movs r7, #0 +10009560: 2844 cmp r0, #68 ; 0x44 +10009562: d112 bne.n 1000958a +10009564: f1b8 0f43 cmp.w r8, #67 ; 0x43 +10009568: d158 bne.n 1000961c +1000956a: 6a28 ldr r0, [r5, #32] +1000956c: 2800 cmp r0, #0 +1000956e: bf1c itt ne +10009570: 6840 ldrne r0, [r0, #4] +10009572: 2800 cmpne r0, #0 +10009574: d052 beq.n 1000961c +10009576: 1d01 adds r1, r0, #4 +10009578: bf1f itttt ne +1000957a: 6841 ldrne r1, [r0, #4] +1000957c: 2900 cmpne r1, #0 +1000957e: f8d9 2000 ldrne.w r2, [r9] +10009582: 4291 cmpne r1, r2 +10009584: d14a bne.n 1000961c +10009586: 4607 mov r7, r0 +10009588: e04c b.n 10009624 + +1000958a : +1000958a: 4ac9 ldr r2, [pc, #804] ; (100098b0 ) +1000958c: 6857 ldr r7, [r2, #4] +1000958e: 2300 movs r3, #0 +10009590: 4619 mov r1, r3 +10009592: e001 b.n 10009598 + +10009594 : +10009594: 463b mov r3, r7 +10009596: 68ff ldr r7, [r7, #12] + +10009598 : +10009598: 2f00 cmp r7, #0 +1000959a: d03d beq.n 10009618 +1000959c: f8b7 c012 ldrh.w ip, [r7, #18] +100095a0: 4584 cmp ip, r0 +100095a2: d1f7 bne.n 10009594 +100095a4: f1ba 0f00 cmp.w sl, #0 +100095a8: bf04 itt eq +100095aa: f8d7 c000 ldreq.w ip, [r7] +100095ae: f1bc 0f00 cmpeq.w ip, #0 +100095b2: bf1e ittt ne +100095b4: f8d6 e000 ldrne.w lr, [r6] +100095b8: f8d7 b000 ldrne.w fp, [r7] +100095bc: 45f3 cmpne fp, lr +100095be: d00d beq.n 100095dc +100095c0: f1ba 0f00 cmp.w sl, #0 +100095c4: d0e6 beq.n 10009594 +100095c6: f1bb 0f00 cmp.w fp, #0 +100095ca: bf1f itttt ne +100095cc: f8d5 c008 ldrne.w ip, [r5, #8] +100095d0: ea0c 0b0b andne.w fp, ip, fp +100095d4: ea0c 0c0e andne.w ip, ip, lr +100095d8: 45e3 cmpne fp, ip +100095da: d1db bne.n 10009594 + +100095dc : +100095dc: b929 cbnz r1, 100095ea +100095de: f897 c010 ldrb.w ip, [r7, #16] +100095e2: ea5f 7c4c movs.w ip, ip, lsl #29 +100095e6: bf58 it pl +100095e8: 4639 movpl r1, r7 + +100095ea : +100095ea: f8b7 c014 ldrh.w ip, [r7, #20] +100095ee: 45c4 cmp ip, r8 +100095f0: d1d0 bne.n 10009594 +100095f2: f117 0c04 adds.w ip, r7, #4 +100095f6: d008 beq.n 1000960a +100095f8: f8d7 c004 ldr.w ip, [r7, #4] +100095fc: f1bc 0f00 cmp.w ip, #0 +10009600: bf1c itt ne +10009602: f8d9 e000 ldrne.w lr, [r9] +10009606: 45f4 cmpne ip, lr +10009608: d1c4 bne.n 10009594 + +1000960a : +1000960a: b15b cbz r3, 10009624 +1000960c: 68f8 ldr r0, [r7, #12] +1000960e: 60d8 str r0, [r3, #12] +10009610: 6850 ldr r0, [r2, #4] +10009612: 60f8 str r0, [r7, #12] +10009614: 6057 str r7, [r2, #4] +10009616: e005 b.n 10009624 + +10009618 : +10009618: 000f movs r7, r1 +1000961a: d103 bne.n 10009624 + +1000961c : +1000961c: 6868 ldr r0, [r5, #4] +1000961e: 6831 ldr r1, [r6, #0] +10009620: 4288 cmp r0, r1 + +10009622 : +10009622: d133 bne.n 1000968c + +10009624 : +10009624: 9800 ldr r0, [sp, #0] +10009626: 88c0 ldrh r0, [r0, #6] +10009628: b140 cbz r0, 1000963c +1000962a: 8920 ldrh r0, [r4, #8] +1000962c: 9000 str r0, [sp, #0] +1000962e: 2311 movs r3, #17 +10009630: 4632 mov r2, r6 +10009632: 4649 mov r1, r9 +10009634: 4620 mov r0, r4 +10009636: f002 ffc5 bl 1000c5c4 +1000963a: bb38 cbnz r0, 1000968c + +1000963c : +1000963c: f06f 0107 mvn.w r1, #7 +10009640: 4620 mov r0, r4 +10009642: f7ff f8a0 bl 10008786 +10009646: bb08 cbnz r0, 1000968c +10009648: b157 cbz r7, 10009660 +1000964a: 69bd ldr r5, [r7, #24] +1000964c: 0028 movs r0, r5 +1000964e: d01d beq.n 1000968c +10009650: f8cd 8000 str.w r8, [sp] +10009654: 464b mov r3, r9 +10009656: 69f8 ldr r0, [r7, #28] +10009658: 4622 mov r2, r4 +1000965a: 4639 mov r1, r7 +1000965c: 47a8 blx r5 +1000965e: e01a b.n 10009696 + +10009660 : +10009660: f1ba 0f00 cmp.w sl, #0 +10009664: d112 bne.n 1000968c +10009666: 7830 ldrb r0, [r6, #0] +10009668: f000 00f0 and.w r0, r0, #240 ; 0xf0 +1000966c: 28e0 cmp r0, #224 ; 0xe0 +1000966e: d00d beq.n 1000968c +10009670: 9801 ldr r0, [sp, #4] +10009672: 7800 ldrb r0, [r0, #0] +10009674: f000 000f and.w r0, r0, #15 +10009678: 0080 lsls r0, r0, #2 +1000967a: f100 0108 add.w r1, r0, #8 +1000967e: 4620 mov r0, r4 +10009680: f7ff f881 bl 10008786 +10009684: 2103 movs r1, #3 +10009686: 4620 mov r0, r4 +10009688: f003 f894 bl 1000c7b4 + +1000968c : +1000968c: 4620 mov r0, r4 +1000968e: e8bd 4ffe ldmia.w sp!, {r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +10009692: f7ff b8a9 b.w 100087e8 + +10009696 : +10009696: e8bd 8ff7 ldmia.w sp!, {r0, r1, r2, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1000969a : +1000969a: 8a83 ldrh r3, [r0, #20] +1000969c: 1d02 adds r2, r0, #4 + +1000969e : +1000969e: b5f8 push {r3, r4, r5, r6, r7, lr} +100096a0: 4604 mov r4, r0 +100096a2: 4616 mov r6, r2 +100096a4: 460d mov r5, r1 +100096a6: 461f mov r7, r3 +100096a8: 4630 mov r0, r6 +100096aa: f002 faff bl 1000bcac +100096ae: b910 cbnz r0, 100096b6 +100096b0: f06f 0003 mvn.w r0, #3 +100096b4: bdf2 pop {r1, r4, r5, r6, r7, pc} + +100096b6 : +100096b6: 9000 str r0, [sp, #0] +100096b8: 463b mov r3, r7 +100096ba: 4632 mov r2, r6 +100096bc: 4629 mov r1, r5 +100096be: 4620 mov r0, r4 +100096c0: f000 f801 bl 100096c6 +100096c4: bdf2 pop {r1, r4, r5, r6, r7, pc} + +100096c6 : +100096c6: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +100096ca: 4604 mov r4, r0 +100096cc: b084 sub sp, #16 +100096ce: 8a60 ldrh r0, [r4, #18] +100096d0: 4688 mov r8, r1 +100096d2: 4691 mov r9, r2 +100096d4: 461e mov r6, r3 +100096d6: b930 cbnz r0, 100096e6 +100096d8: 2200 movs r2, #0 +100096da: 4621 mov r1, r4 +100096dc: 4620 mov r0, r4 +100096de: f000 f861 bl 100097a4 +100096e2: 0005 movs r5, r0 +100096e4: d15a bne.n 1000979c + +100096e6 : +100096e6: 2108 movs r1, #8 +100096e8: 4640 mov r0, r8 +100096ea: f7ff f84c bl 10008786 +100096ee: b188 cbz r0, 10009714 +100096f0: 2200 movs r2, #0 +100096f2: 2108 movs r1, #8 +100096f4: 2001 movs r0, #1 +100096f6: f7fe ff67 bl 100085c8 +100096fa: 0007 movs r7, r0 +100096fc: bf08 it eq +100096fe: f04f 30ff moveq.w r0, #4294967295 +10009702: d04c beq.n 1000979e +10009704: f8b8 0008 ldrh.w r0, [r8, #8] +10009708: b128 cbz r0, 10009716 +1000970a: 4641 mov r1, r8 +1000970c: 4638 mov r0, r7 +1000970e: f7ff f8c1 bl 10008894 +10009712: e000 b.n 10009716 + +10009714 : +10009714: 4647 mov r7, r8 + +10009716 : +10009716: 687d ldr r5, [r7, #4] +10009718: 8a60 ldrh r0, [r4, #18] +1000971a: f002 ff14 bl 1000c546 +1000971e: 8028 strh r0, [r5, #0] +10009720: 4630 mov r0, r6 +10009722: f002 ff10 bl 1000c546 +10009726: 8068 strh r0, [r5, #2] +10009728: 2000 movs r0, #0 +1000972a: 80e8 strh r0, [r5, #6] +1000972c: 2c00 cmp r4, #0 +1000972e: 9e0c ldr r6, [sp, #48] ; 0x30 +10009730: bf1a itte ne +10009732: 6820 ldrne r0, [r4, #0] +10009734: 2800 cmpne r0, #0 +10009736: f106 0a04 addeq.w sl, r6, #4 +1000973a: d00b beq.n 10009754 +1000973c: 6871 ldr r1, [r6, #4] +1000973e: 4288 cmp r0, r1 +10009740: d007 beq.n 10009752 +10009742: 4547 cmp r7, r8 +10009744: bf1c itt ne +10009746: 4638 movne r0, r7 +10009748: f7ff f84e blne 100087e8 +1000974c: f06f 0005 mvn.w r0, #5 +10009750: e025 b.n 1000979e + +10009752 : +10009752: 46a2 mov sl, r4 + +10009754 : +10009754: 8938 ldrh r0, [r7, #8] +10009756: f002 fef6 bl 1000c546 +1000975a: 80a8 strh r0, [r5, #4] +1000975c: 7c20 ldrb r0, [r4, #16] +1000975e: 07c0 lsls r0, r0, #31 +10009760: d40b bmi.n 1000977a +10009762: 8938 ldrh r0, [r7, #8] +10009764: 9000 str r0, [sp, #0] +10009766: 2311 movs r3, #17 +10009768: 464a mov r2, r9 +1000976a: 4651 mov r1, sl +1000976c: 4638 mov r0, r7 +1000976e: f002 ff29 bl 1000c5c4 +10009772: b908 cbnz r0, 10009778 +10009774: f64f 70ff movw r0, #65535 ; 0xffff + +10009778 : +10009778: 80e8 strh r0, [r5, #6] + +1000977a : +1000977a: 9602 str r6, [sp, #8] +1000977c: 2011 movs r0, #17 +1000977e: 9001 str r0, [sp, #4] +10009780: 464a mov r2, r9 +10009782: 7a60 ldrb r0, [r4, #9] +10009784: 9000 str r0, [sp, #0] +10009786: 4651 mov r1, sl +10009788: 7aa3 ldrb r3, [r4, #10] +1000978a: 4638 mov r0, r7 +1000978c: f002 fb55 bl 1000be3a +10009790: 4605 mov r5, r0 +10009792: 4547 cmp r7, r8 +10009794: bf1c itt ne +10009796: 4638 movne r0, r7 +10009798: f7ff f826 blne 100087e8 + +1000979c : +1000979c: 4628 mov r0, r5 + +1000979e : +1000979e: b004 add sp, #16 +100097a0: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + +100097a4 : +100097a4: b5f0 push {r4, r5, r6, r7, lr} +100097a6: 4c42 ldr r4, [pc, #264] ; (100098b0 ) +100097a8: 6865 ldr r5, [r4, #4] +100097aa: 2300 movs r3, #0 +100097ac: 462e mov r6, r5 +100097ae: e00d b.n 100097cc + +100097b0 : +100097b0: 8a77 ldrh r7, [r6, #18] +100097b2: 4297 cmp r7, r2 +100097b4: d109 bne.n 100097ca +100097b6: 6837 ldr r7, [r6, #0] +100097b8: b35f cbz r7, 10009812 +100097ba: b351 cbz r1, 10009812 +100097bc: f8d1 c000 ldr.w ip, [r1] +100097c0: f1bc 0f00 cmp.w ip, #0 +100097c4: bf18 it ne +100097c6: 4567 cmpne r7, ip +100097c8: d023 beq.n 10009812 + +100097ca : +100097ca: 68f6 ldr r6, [r6, #12] + +100097cc : +100097cc: b11e cbz r6, 100097d6 +100097ce: 42b0 cmp r0, r6 +100097d0: d1ee bne.n 100097b0 +100097d2: 2301 movs r3, #1 +100097d4: e7f9 b.n 100097ca + +100097d6 : +100097d6: b101 cbz r1, 100097da +100097d8: 6809 ldr r1, [r1, #0] + +100097da : +100097da: 6001 str r1, [r0, #0] +100097dc: b9e2 cbnz r2, 10009818 +100097de: 2100 movs r1, #0 + +100097e0 : +100097e0: 8822 ldrh r2, [r4, #0] +100097e2: 1c56 adds r6, r2, #1 +100097e4: f64f 77ff movw r7, #65535 ; 0xffff +100097e8: 42ba cmp r2, r7 +100097ea: bf08 it eq +100097ec: f44f 4640 moveq.w r6, #49152 ; 0xc000 +100097f0: 8026 strh r6, [r4, #0] +100097f2: 462a mov r2, r5 +100097f4: 8827 ldrh r7, [r4, #0] +100097f6: e000 b.n 100097fa + +100097f8 : +100097f8: 68d2 ldr r2, [r2, #12] + +100097fa : +100097fa: b142 cbz r2, 1000980e +100097fc: 8a56 ldrh r6, [r2, #18] +100097fe: 42be cmp r6, r7 +10009800: d1fa bne.n 100097f8 +10009802: 1c49 adds r1, r1, #1 +10009804: b289 uxth r1, r1 +10009806: f5b1 4f80 cmp.w r1, #16384 ; 0x4000 +1000980a: dbe9 blt.n 100097e0 +1000980c: e001 b.n 10009812 + +1000980e : +1000980e: 003a movs r2, r7 +10009810: d102 bne.n 10009818 + +10009812 : +10009812: f06f 0007 mvn.w r0, #7 +10009816: bdf0 pop {r4, r5, r6, r7, pc} + +10009818 : +10009818: 8242 strh r2, [r0, #18] +1000981a: b90b cbnz r3, 10009820 +1000981c: 60c5 str r5, [r0, #12] +1000981e: 6060 str r0, [r4, #4] + +10009820 : +10009820: 2000 movs r0, #0 +10009822: bdf0 pop {r4, r5, r6, r7, pc} + +10009824 : +10009824: b570 push {r4, r5, r6, lr} +10009826: 4604 mov r4, r0 +10009828: 460d mov r5, r1 +1000982a: 8a60 ldrh r0, [r4, #18] +1000982c: 4616 mov r6, r2 +1000982e: b928 cbnz r0, 1000983c +10009830: 2200 movs r2, #0 +10009832: 4621 mov r1, r4 +10009834: 4620 mov r0, r4 +10009836: f7ff ffb5 bl 100097a4 +1000983a: b9a8 cbnz r0, 10009868 + +1000983c : +1000983c: 2d00 cmp r5, #0 +1000983e: bf0c ite eq +10009840: 2000 moveq r0, #0 +10009842: 6828 ldrne r0, [r5, #0] +10009844: 6060 str r0, [r4, #4] +10009846: 82a6 strh r6, [r4, #20] +10009848: 7c20 ldrb r0, [r4, #16] +1000984a: f040 0004 orr.w r0, r0, #4 +1000984e: 7420 strb r0, [r4, #16] +10009850: 4817 ldr r0, [pc, #92] ; (100098b0 ) +10009852: 6841 ldr r1, [r0, #4] +10009854: 460a mov r2, r1 +10009856: e000 b.n 1000985a + +10009858 : +10009858: 68d2 ldr r2, [r2, #12] + +1000985a : +1000985a: b112 cbz r2, 10009862 +1000985c: 4294 cmp r4, r2 +1000985e: d1fb bne.n 10009858 +10009860: e001 b.n 10009866 + +10009862 : +10009862: 60e1 str r1, [r4, #12] +10009864: 6044 str r4, [r0, #4] + +10009866 : +10009866: 2000 movs r0, #0 + +10009868 : +10009868: bd70 pop {r4, r5, r6, pc} + +1000986a : +1000986a: 2100 movs r1, #0 +1000986c: 6041 str r1, [r0, #4] +1000986e: 8281 strh r1, [r0, #20] +10009870: 7c01 ldrb r1, [r0, #16] +10009872: f001 01fb and.w r1, r1, #251 ; 0xfb +10009876: 7401 strb r1, [r0, #16] +10009878: 4770 bx lr + +1000987a : +1000987a: 6181 str r1, [r0, #24] +1000987c: 61c2 str r2, [r0, #28] +1000987e: 4770 bx lr + +10009880 : +10009880: 490b ldr r1, [pc, #44] ; (100098b0 ) +10009882: 684a ldr r2, [r1, #4] +10009884: 4282 cmp r2, r0 +10009886: d109 bne.n 1000989c +10009888: 68d2 ldr r2, [r2, #12] +1000988a: 604a str r2, [r1, #4] +1000988c: e008 b.n 100098a0 + +1000988e : +1000988e: 68d1 ldr r1, [r2, #12] +10009890: b119 cbz r1, 1000989a +10009892: 4281 cmp r1, r0 +10009894: bf04 itt eq +10009896: 68c1 ldreq r1, [r0, #12] +10009898: 60d1 streq r1, [r2, #12] + +1000989a : +1000989a: 68d2 ldr r2, [r2, #12] + +1000989c : +1000989c: 2a00 cmp r2, #0 +1000989e: d1f6 bne.n 1000988e + +100098a0 : +100098a0: 4601 mov r1, r0 +100098a2: 2001 movs r0, #1 +100098a4: f7fe bd30 b.w 10008308 + +100098a8 : +100098a8: 7708 1004 .w.. + +100098ac : +100098ac: 7704 1004 .w.. + +100098b0 : +100098b0: 4098 1004 .@.. + +100098b4 : +100098b4: b510 push {r4, lr} +100098b6: 2001 movs r0, #1 +100098b8: f7fe fd13 bl 100082e2 +100098bc: 0004 movs r4, r0 +100098be: d005 beq.n 100098cc +100098c0: 2220 movs r2, #32 +100098c2: 2100 movs r1, #0 +100098c4: f002 fd42 bl 1000c34c +100098c8: 20ff movs r0, #255 ; 0xff +100098ca: 72a0 strb r0, [r4, #10] + +100098cc : +100098cc: 4620 mov r0, r4 +100098ce: bd10 pop {r4, pc} + +100098d0 : +100098d0: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +100098d4: 4604 mov r4, r0 +100098d6: 4e58 ldr r6, [pc, #352] ; (10009a38 ) +100098d8: 6860 ldr r0, [r4, #4] +100098da: 6837 ldr r7, [r6, #0] +100098dc: f890 8009 ldrb.w r8, [r0, #9] +100098e0: f8df a158 ldr.w sl, [pc, #344] ; 10009a3c +100098e4: f8df b158 ldr.w fp, [pc, #344] ; 10009a40 +100098e8: 2500 movs r5, #0 +100098ea: 46a9 mov r9, r5 + +100098ec : +100098ec: b327 cbz r7, 10009938 +100098ee: 7c38 ldrb r0, [r7, #16] +100098f0: 4540 cmp r0, r8 +100098f2: d11d bne.n 10009930 +100098f4: 6838 ldr r0, [r7, #0] +100098f6: 2800 cmp r0, #0 +100098f8: bf1c itt ne +100098fa: f8db 1000 ldrne.w r1, [fp] +100098fe: 4288 cmpne r0, r1 +10009900: d116 bne.n 10009930 +10009902: f8d7 c014 ldr.w ip, [r7, #20] +10009906: f1bc 0f00 cmp.w ip, #0 +1000990a: d011 beq.n 10009930 +1000990c: 69b8 ldr r0, [r7, #24] +1000990e: 4653 mov r3, sl +10009910: 4622 mov r2, r4 +10009912: 4639 mov r1, r7 +10009914: 47e0 blx ip +10009916: 2800 cmp r0, #0 +10009918: bf1e ittt ne +1000991a: 2400 movne r4, #0 +1000991c: 2501 movne r5, #1 +1000991e: f1b9 0f00 cmpne.w r9, #0 +10009922: d005 beq.n 10009930 +10009924: 68f8 ldr r0, [r7, #12] +10009926: f8c9 000c str.w r0, [r9, #12] +1000992a: 6830 ldr r0, [r6, #0] +1000992c: 60f8 str r0, [r7, #12] +1000992e: 6037 str r7, [r6, #0] + +10009930 : +10009930: 46b9 mov r9, r7 +10009932: 68ff ldr r7, [r7, #12] +10009934: 2d00 cmp r5, #0 +10009936: d0d9 beq.n 100098ec + +10009938 : +10009938: 4628 mov r0, r5 +1000993a: e8bd 8ff2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1000993e : +1000993e: b101 cbz r1, 10009942 +10009940: 6809 ldr r1, [r1, #0] + +10009942 : +10009942: 6001 str r1, [r0, #0] +10009944: 2000 movs r0, #0 +10009946: 4770 bx lr + +10009948 : +10009948: b101 cbz r1, 1000994c +1000994a: 6809 ldr r1, [r1, #0] + +1000994c : +1000994c: 6041 str r1, [r0, #4] +1000994e: 2000 movs r0, #0 +10009950: 4770 bx lr + +10009952 : +10009952: 6141 str r1, [r0, #20] +10009954: 6182 str r2, [r0, #24] +10009956: 4770 bx lr + +10009958 : +10009958: b5fe push {r1, r2, r3, r4, r5, r6, r7, lr} +1000995a: 4606 mov r6, r0 +1000995c: 460c mov r4, r1 +1000995e: 4617 mov r7, r2 +10009960: 2114 movs r1, #20 +10009962: 4620 mov r0, r4 +10009964: f7fe ff0f bl 10008786 +10009968: b1c0 cbz r0, 1000999c +1000996a: 2200 movs r2, #0 +1000996c: 2100 movs r1, #0 +1000996e: 2001 movs r0, #1 +10009970: f7fe fe2a bl 100085c8 +10009974: 0005 movs r5, r0 +10009976: d019 beq.n 100099ac +10009978: 8920 ldrh r0, [r4, #8] +1000997a: b118 cbz r0, 10009984 +1000997c: 4621 mov r1, r4 +1000997e: 4628 mov r0, r5 +10009980: f7fe ff88 bl 10008894 + +10009984 : +10009984: 4638 mov r0, r7 +10009986: f002 f991 bl 1000bcac +1000998a: b990 cbnz r0, 100099b2 +1000998c: 42a5 cmp r5, r4 +1000998e: bf1c itt ne +10009990: 4628 movne r0, r5 +10009992: f7fe ff29 blne 100087e8 +10009996: f06f 0003 mvn.w r0, #3 +1000999a: bdfe pop {r1, r2, r3, r4, r5, r6, r7, pc} + +1000999c : +1000999c: 4625 mov r5, r4 +1000999e: f06f 0113 mvn.w r1, #19 +100099a2: 4628 mov r0, r5 +100099a4: f7fe feef bl 10008786 +100099a8: 2800 cmp r0, #0 +100099aa: d0eb beq.n 10009984 + +100099ac : +100099ac: f04f 30ff mov.w r0, #4294967295 +100099b0: bdfe pop {r1, r2, r3, r4, r5, r6, r7, pc} + +100099b2 : +100099b2: 2e00 cmp r6, #0 +100099b4: bf1b ittet ne +100099b6: 6831 ldrne r1, [r6, #0] +100099b8: 2900 cmpne r1, #0 +100099ba: 1d01 addeq r1, r0, #4 +100099bc: 4631 movne r1, r6 +100099be: 9002 str r0, [sp, #8] +100099c0: 463a mov r2, r7 +100099c2: 7c30 ldrb r0, [r6, #16] +100099c4: 9001 str r0, [sp, #4] +100099c6: 7a70 ldrb r0, [r6, #9] +100099c8: 9000 str r0, [sp, #0] +100099ca: 4628 mov r0, r5 +100099cc: 7ab3 ldrb r3, [r6, #10] +100099ce: f002 fa34 bl 1000be3a +100099d2: 4606 mov r6, r0 +100099d4: 42a5 cmp r5, r4 +100099d6: bf1c itt ne +100099d8: 4628 movne r0, r5 +100099da: f7fe ff05 blne 100087e8 +100099de: 4630 mov r0, r6 +100099e0: bdfe pop {r1, r2, r3, r4, r5, r6, r7, pc} + +100099e2 : +100099e2: 1d02 adds r2, r0, #4 +100099e4: e7b8 b.n 10009958 + +100099e6 : +100099e6: 4914 ldr r1, [pc, #80] ; (10009a38 ) +100099e8: 680a ldr r2, [r1, #0] +100099ea: 4282 cmp r2, r0 +100099ec: d109 bne.n 10009a02 +100099ee: 68d2 ldr r2, [r2, #12] +100099f0: 600a str r2, [r1, #0] +100099f2: e008 b.n 10009a06 + +100099f4 : +100099f4: 68d1 ldr r1, [r2, #12] +100099f6: b119 cbz r1, 10009a00 +100099f8: 4281 cmp r1, r0 +100099fa: bf04 itt eq +100099fc: 68c1 ldreq r1, [r0, #12] +100099fe: 60d1 streq r1, [r2, #12] + +10009a00 : +10009a00: 68d2 ldr r2, [r2, #12] + +10009a02 : +10009a02: 2a00 cmp r2, #0 +10009a04: d1f6 bne.n 100099f4 + +10009a06 : +10009a06: 4601 mov r1, r0 +10009a08: 2000 movs r0, #0 +10009a0a: f7fe bc7d b.w 10008308 + +10009a0e : +10009a0e: b538 push {r3, r4, r5, lr} +10009a10: 4604 mov r4, r0 +10009a12: 2000 movs r0, #0 +10009a14: f7fe fc65 bl 100082e2 +10009a18: 0005 movs r5, r0 +10009a1a: d00a beq.n 10009a32 +10009a1c: 221c movs r2, #28 +10009a1e: 2100 movs r1, #0 +10009a20: f002 fc94 bl 1000c34c +10009a24: 742c strb r4, [r5, #16] +10009a26: 20ff movs r0, #255 ; 0xff +10009a28: 72a8 strb r0, [r5, #10] +10009a2a: 4803 ldr r0, [pc, #12] ; (10009a38 ) +10009a2c: 6801 ldr r1, [r0, #0] +10009a2e: 60e9 str r1, [r5, #12] +10009a30: 6005 str r5, [r0, #0] + +10009a32 : +10009a32: 4628 mov r0, r5 +10009a34: bd32 pop {r1, r4, r5, pc} + ... + +10009a38 : +10009a38: 78dc 1004 .x.. + +10009a3c : +10009a3c: 7704 1004 .w.. + +10009a40 : +10009a40: 7708 1004 .w.. + +10009a44 : +10009a44: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +10009a48: 4604 mov r4, r0 +10009a4a: 460f mov r7, r1 +10009a4c: 4610 mov r0, r2 +10009a4e: 19c0 adds r0, r0, r7 +10009a50: f100 0114 add.w r1, r0, #20 +10009a54: 4698 mov r8, r3 +10009a56: 2200 movs r2, #0 +10009a58: b289 uxth r1, r1 +10009a5a: 2001 movs r0, #1 +10009a5c: f7fe fdb4 bl 100085c8 +10009a60: 0005 movs r5, r0 +10009a62: d023 beq.n 10009aac +10009a64: 686e ldr r6, [r5, #4] +10009a66: 8be0 ldrh r0, [r4, #30] +10009a68: f002 fd6d bl 1000c546 +10009a6c: 8030 strh r0, [r6, #0] +10009a6e: 8c20 ldrh r0, [r4, #32] +10009a70: f002 fd69 bl 1000c546 +10009a74: 8070 strh r0, [r6, #2] +10009a76: f8c6 8004 str.w r8, [r6, #4] +10009a7a: 6ae0 ldr r0, [r4, #44] ; 0x2c +10009a7c: f002 fd69 bl 1000c552 +10009a80: 60b0 str r0, [r6, #8] +10009a82: 063f lsls r7, r7, #24 +10009a84: 0eb8 lsrs r0, r7, #26 +10009a86: 1d40 adds r0, r0, #5 +10009a88: 0300 lsls r0, r0, #12 +10009a8a: f040 0010 orr.w r0, r0, #16 +10009a8e: b280 uxth r0, r0 +10009a90: f002 fd59 bl 1000c546 +10009a94: 81b0 strh r0, [r6, #12] +10009a96: 8e60 ldrh r0, [r4, #50] ; 0x32 +10009a98: f002 fd55 bl 1000c546 +10009a9c: 81f0 strh r0, [r6, #14] +10009a9e: 2000 movs r0, #0 +10009aa0: 8230 strh r0, [r6, #16] +10009aa2: 8270 strh r0, [r6, #18] +10009aa4: 8e61 ldrh r1, [r4, #50] ; 0x32 +10009aa6: 6ae0 ldr r0, [r4, #44] ; 0x2c +10009aa8: 1808 adds r0, r1, r0 +10009aaa: 6360 str r0, [r4, #52] ; 0x34 + +10009aac : +10009aac: 4628 mov r0, r5 +10009aae: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +10009ab2 : +10009ab2: b538 push {r3, r4, r5, lr} +10009ab4: 4604 mov r4, r0 +10009ab6: 6f25 ldr r5, [r4, #112] ; 0x70 +10009ab8: b1cd cbz r5, 10009aee +10009aba: e000 b.n 10009abe + +10009abc : +10009abc: 4605 mov r5, r0 + +10009abe : +10009abe: 6828 ldr r0, [r5, #0] +10009ac0: 2800 cmp r0, #0 +10009ac2: d1fb bne.n 10009abc +10009ac4: 6928 ldr r0, [r5, #16] +10009ac6: f000 fcda bl 1000a47e + +10009aca : +10009aca: 2107 movs r1, #7 +10009acc: 4208 tst r0, r1 +10009ace: d10e bne.n 10009aee +10009ad0: 2001 movs r0, #1 +10009ad2: f002 fd38 bl 1000c546 +10009ad6: 6929 ldr r1, [r5, #16] +10009ad8: 898a ldrh r2, [r1, #12] +10009ada: 4310 orrs r0, r2 +10009adc: 8188 strh r0, [r1, #12] +10009ade: f894 0022 ldrb.w r0, [r4, #34] ; 0x22 +10009ae2: f040 0020 orr.w r0, r0, #32 +10009ae6: f884 0022 strb.w r0, [r4, #34] ; 0x22 +10009aea: 2000 movs r0, #0 +10009aec: bd32 pop {r1, r4, r5, pc} + +10009aee : +10009aee: 4620 mov r0, r4 +10009af0: e8bd 4034 ldmia.w sp!, {r2, r4, r5, lr} +10009af4: 2101 movs r1, #1 +10009af6: e213 b.n 10009f20 + +10009af8 : +10009af8: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +10009afc: 9c08 ldr r4, [sp, #32] +10009afe: 4606 mov r6, r0 +10009b00: 468a mov sl, r1 +10009b02: 4691 mov r9, r2 +10009b04: 4698 mov r8, r3 +10009b06: 07e0 lsls r0, r4, #31 +10009b08: bf4c ite mi +10009b0a: 2704 movmi r7, #4 +10009b0c: 2700 movpl r7, #0 +10009b0e: 07a0 lsls r0, r4, #30 +10009b10: bf48 it mi +10009b12: 370c addmi r7, #12 +10009b14: 2004 movs r0, #4 +10009b16: f7fe fbe4 bl 100082e2 +10009b1a: 0005 movs r5, r0 +10009b1c: d103 bne.n 10009b26 +10009b1e: 4650 mov r0, sl +10009b20: f7fe fe62 bl 100087e8 +10009b24: e012 b.n 10009b4c + +10009b26 : +10009b26: 732c strb r4, [r5, #12] +10009b28: 2000 movs r0, #0 +10009b2a: 6028 str r0, [r5, #0] +10009b2c: f8c5 a004 str.w sl, [r5, #4] +10009b30: 2114 movs r1, #20 +10009b32: f8ba 0008 ldrh.w r0, [sl, #8] +10009b36: 1bc0 subs r0, r0, r7 +10009b38: 8128 strh r0, [r5, #8] +10009b3a: 2000 movs r0, #0 +10009b3c: 8168 strh r0, [r5, #10] +10009b3e: 4650 mov r0, sl +10009b40: f7fe fe21 bl 10008786 +10009b44: b120 cbz r0, 10009b50 +10009b46: 4628 mov r0, r5 +10009b48: f7ff fb8f bl 1000926a + +10009b4c : +10009b4c: 2000 movs r0, #0 +10009b4e: e021 b.n 10009b94 + +10009b50 : +10009b50: 6868 ldr r0, [r5, #4] +10009b52: 6840 ldr r0, [r0, #4] +10009b54: 6128 str r0, [r5, #16] +10009b56: 8bf0 ldrh r0, [r6, #30] +10009b58: f002 fcf5 bl 1000c546 +10009b5c: 6929 ldr r1, [r5, #16] +10009b5e: 8008 strh r0, [r1, #0] +10009b60: 8c30 ldrh r0, [r6, #32] +10009b62: f002 fcf0 bl 1000c546 +10009b66: 6929 ldr r1, [r5, #16] +10009b68: 8048 strh r0, [r1, #2] +10009b6a: 4640 mov r0, r8 +10009b6c: f002 fcf1 bl 1000c552 +10009b70: 6929 ldr r1, [r5, #16] +10009b72: 6048 str r0, [r1, #4] +10009b74: 1078 asrs r0, r7, #1 +10009b76: eb07 7090 add.w r0, r7, r0, lsr #30 +10009b7a: 1080 asrs r0, r0, #2 +10009b7c: 1d40 adds r0, r0, #5 +10009b7e: ea49 3000 orr.w r0, r9, r0, lsl #12 +10009b82: b280 uxth r0, r0 +10009b84: f002 fcdf bl 1000c546 +10009b88: 6929 ldr r1, [r5, #16] +10009b8a: 8188 strh r0, [r1, #12] +10009b8c: 2000 movs r0, #0 +10009b8e: 6929 ldr r1, [r5, #16] +10009b90: 8248 strh r0, [r1, #18] +10009b92: 4628 mov r0, r5 + +10009b94 : +10009b94: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + +10009b98 : +10009b98: b570 push {r4, r5, r6, lr} +10009b9a: 460c mov r4, r1 +10009b9c: 461d mov r5, r3 +10009b9e: 4623 mov r3, r4 +10009ba0: 4294 cmp r4, r2 +10009ba2: d21c bcs.n 10009bde +10009ba4: 9905 ldr r1, [sp, #20] +10009ba6: 0789 lsls r1, r1, #30 +10009ba8: d40c bmi.n 10009bc4 +10009baa: 9e04 ldr r6, [sp, #16] +10009bac: f896 1022 ldrb.w r1, [r6, #34] ; 0x22 +10009bb0: 0649 lsls r1, r1, #25 +10009bb2: d414 bmi.n 10009bde +10009bb4: 9906 ldr r1, [sp, #24] +10009bb6: b129 cbz r1, 10009bc4 +10009bb8: 6f31 ldr r1, [r6, #112] ; 0x70 +10009bba: 2900 cmp r1, #0 +10009bbc: bf04 itt eq +10009bbe: 6f71 ldreq r1, [r6, #116] ; 0x74 +10009bc0: 2900 cmpeq r1, #0 +10009bc2: d00c beq.n 10009bde + +10009bc4 : +10009bc4: f204 51b7 addw r1, r4, #1463 ; 0x5b7 +10009bc8: f021 0103 bic.w r1, r1, #3 +10009bcc: 428a cmp r2, r1 +10009bce: bfb1 iteee lt +10009bd0: 4613 movlt r3, r2 +10009bd2: f204 51b7 addwge r1, r4, #1463 ; 0x5b7 +10009bd6: f64f 72fc movwge r2, #65532 ; 0xfffc +10009bda: ea02 0301 andge.w r3, r2, r1 + +10009bde : +10009bde: 2200 movs r2, #0 +10009be0: 4619 mov r1, r3 +10009be2: f7fe fcf1 bl 100085c8 +10009be6: b120 cbz r0, 10009bf2 +10009be8: 8941 ldrh r1, [r0, #10] +10009bea: 1b09 subs r1, r1, r4 +10009bec: 8029 strh r1, [r5, #0] +10009bee: 8104 strh r4, [r0, #8] +10009bf0: 8144 strh r4, [r0, #10] + +10009bf2 : +10009bf2: bd70 pop {r4, r5, r6, pc} + +10009bf4 : +10009bf4: e92d 4ff7 stmdb sp!, {r0, r1, r2, r4, r5, r6, r7, r8, r9, sl, fp, lr} +10009bf8: b08a sub sp, #40 ; 0x28 +10009bfa: 2000 movs r0, #0 +10009bfc: 9005 str r0, [sp, #20] +10009bfe: 9008 str r0, [sp, #32] +10009c00: f8ad 000c strh.w r0, [sp, #12] +10009c04: 4604 mov r4, r0 +10009c06: 4683 mov fp, r0 +10009c08: 4606 mov r6, r0 +10009c0a: 4681 mov r9, r0 +10009c0c: 980a ldr r0, [sp, #40] ; 0x28 +10009c0e: 990a ldr r1, [sp, #40] ; 0x28 +10009c10: f8b0 0066 ldrh.w r0, [r0, #102] ; 0x66 +10009c14: f101 0718 add.w r7, r1, #24 +10009c18: 2500 movs r5, #0 +10009c1a: 8c79 ldrh r1, [r7, #34] ; 0x22 +10009c1c: 0840 lsrs r0, r0, #1 +10009c1e: 4698 mov r8, r3 +10009c20: 4281 cmp r1, r0 +10009c22: bf34 ite cc +10009c24: f8ad 1010 strhcc.w r1, [sp, #16] +10009c28: f8ad 0010 strhcs.w r0, [sp, #16] +10009c2c: 980b ldr r0, [sp, #44] ; 0x2c +10009c2e: b910 cbnz r0, 10009c36 +10009c30: f06f 000d mvn.w r0, #13 + +10009c34 : +10009c34: e0ea b.n 10009e0c + +10009c36 : +10009c36: 980a ldr r0, [sp, #40] ; 0x28 +10009c38: 6980 ldr r0, [r0, #24] +10009c3a: 2804 cmp r0, #4 +10009c3c: bf18 it ne +10009c3e: 2807 cmpne r0, #7 +10009c40: d005 beq.n 10009c4e +10009c42: 2802 cmp r0, #2 +10009c44: bf1c itt ne +10009c46: 2803 cmpne r0, #3 +10009c48: f06f 000c mvnne.w r0, #12 +10009c4c: d1f2 bne.n 10009c34 + +10009c4e : +10009c4e: 980a ldr r0, [sp, #40] ; 0x28 +10009c50: 3066 adds r0, #102 ; 0x66 +10009c52: 9006 str r0, [sp, #24] +10009c54: f8bd 0030 ldrh.w r0, [sp, #48] ; 0x30 +10009c58: b190 cbz r0, 10009c80 +10009c5a: 9806 ldr r0, [sp, #24] +10009c5c: f8bd 1030 ldrh.w r1, [sp, #48] ; 0x30 +10009c60: 8880 ldrh r0, [r0, #4] +10009c62: 4288 cmp r0, r1 +10009c64: d307 bcc.n 10009c76 +10009c66: 9806 ldr r0, [sp, #24] +10009c68: 88c0 ldrh r0, [r0, #6] +10009c6a: 2814 cmp r0, #20 +10009c6c: da03 bge.n 10009c76 +10009c6e: f64f 71fd movw r1, #65533 ; 0xfffd +10009c72: 4288 cmp r0, r1 +10009c74: d304 bcc.n 10009c80 + +10009c76 : +10009c76: 7ab8 ldrb r0, [r7, #10] +10009c78: f040 0080 orr.w r0, r0, #128 ; 0x80 +10009c7c: 72b8 strb r0, [r7, #10] +10009c7e: e0c3 b.n 10009e08 + +10009c80 : +10009c80: 9806 ldr r0, [sp, #24] +10009c82: f8b0 a006 ldrh.w sl, [r0, #6] +10009c86: 980a ldr r0, [sp, #40] ; 0x28 +10009c88: 6f00 ldr r0, [r0, #112] ; 0x70 +10009c8a: 2800 cmp r0, #0 +10009c8c: d073 beq.n 10009d76 + +10009c8e : +10009c8e: 4605 mov r5, r0 +10009c90: 6828 ldr r0, [r5, #0] +10009c92: 2800 cmp r0, #0 +10009c94: d1fb bne.n 10009c8e +10009c96: 7b29 ldrb r1, [r5, #12] +10009c98: 07c8 lsls r0, r1, #31 +10009c9a: bf4c ite mi +10009c9c: 2004 movmi r0, #4 +10009c9e: 2000 movpl r0, #0 +10009ca0: 0789 lsls r1, r1, #30 +10009ca2: bf4c ite mi +10009ca4: 210c movmi r1, #12 +10009ca6: 2100 movpl r1, #0 +10009ca8: f8bd 2010 ldrh.w r2, [sp, #16] +10009cac: 892b ldrh r3, [r5, #8] +10009cae: 1ad2 subs r2, r2, r3 +10009cb0: 1a10 subs r0, r2, r0 +10009cb2: 1a42 subs r2, r0, r1 +10009cb4: 9806 ldr r0, [sp, #24] +10009cb6: 8900 ldrh r0, [r0, #8] +10009cb8: f8ad 000c strh.w r0, [sp, #12] +10009cbc: b168 cbz r0, 10009cda +10009cbe: 462c mov r4, r5 +10009cc0: f8bd 1030 ldrh.w r1, [sp, #48] ; 0x30 +10009cc4: 4288 cmp r0, r1 +10009cc6: bf34 ite cc +10009cc8: 4681 movcc r9, r0 +10009cca: 4689 movcs r9, r1 +10009ccc: eba0 0009 sub.w r0, r0, r9 +10009cd0: 464e mov r6, r9 +10009cd2: f8ad 000c strh.w r0, [sp, #12] +10009cd6: eba2 0209 sub.w r2, r2, r9 + +10009cda : +10009cda: f8bd 0030 ldrh.w r0, [sp, #48] ; 0x30 +10009cde: 4286 cmp r6, r0 +10009ce0: da49 bge.n 10009d76 +10009ce2: b292 uxth r2, r2 +10009ce4: 2a00 cmp r2, #0 +10009ce6: bf1c itt ne +10009ce8: 8928 ldrhne r0, [r5, #8] +10009cea: 2800 cmpne r0, #0 +10009cec: d043 beq.n 10009d76 +10009cee: f8bd 0030 ldrh.w r0, [sp, #48] ; 0x30 +10009cf2: 1b80 subs r0, r0, r6 +10009cf4: 4282 cmp r2, r0 +10009cf6: bfb1 iteee lt +10009cf8: f8ad 200e strhlt.w r2, [sp, #14] +10009cfc: f8bd 0030 ldrhge.w r0, [sp, #48] ; 0x30 +10009d00: 1b80 subge r0, r0, r6 +10009d02: f8ad 000e strhge.w r0, [sp, #14] +10009d06: 980b ldr r0, [sp, #44] ; 0x2c +10009d08: 1830 adds r0, r6, r0 +10009d0a: 9007 str r0, [sp, #28] +10009d0c: 462c mov r4, r5 +10009d0e: ea5f 70c8 movs.w r0, r8, lsl #31 +10009d12: d514 bpl.n 10009d3e +10009d14: 2001 movs r0, #1 +10009d16: f000 f8fd bl 10009f14 + +10009d1a : +10009d1a: f8bd 100e ldrh.w r1, [sp, #14] +10009d1e: 9000 str r0, [sp, #0] +10009d20: 2003 movs r0, #3 +10009d22: f7ff ff39 bl 10009b98 +10009d26: 9005 str r0, [sp, #20] +10009d28: 2800 cmp r0, #0 +10009d2a: d05f beq.n 10009dec +10009d2c: 8968 ldrh r0, [r5, #10] +10009d2e: f8bd 100c ldrh.w r1, [sp, #12] +10009d32: 1808 adds r0, r1, r0 +10009d34: 8168 strh r0, [r5, #10] +10009d36: 9805 ldr r0, [sp, #20] +10009d38: f000 f8e6 bl 10009f08 + +10009d3c : +10009d3c: e00b b.n 10009d56 + +10009d3e : +10009d3e: f8bd 100e ldrh.w r1, [sp, #14] +10009d42: 2201 movs r2, #1 +10009d44: 2003 movs r0, #3 +10009d46: f7fe fc3f bl 100085c8 +10009d4a: 9005 str r0, [sp, #20] +10009d4c: 2800 cmp r0, #0 +10009d4e: d04d beq.n 10009dec +10009d50: 9905 ldr r1, [sp, #20] +10009d52: 9807 ldr r0, [sp, #28] +10009d54: 6048 str r0, [r1, #4] + +10009d56 : +10009d56: f8bd 000e ldrh.w r0, [sp, #14] +10009d5a: 1980 adds r0, r0, r6 +10009d5c: b286 uxth r6, r0 +10009d5e: 9805 ldr r0, [sp, #20] +10009d60: f7fe fd70 bl 10008844 +10009d64: 4450 add r0, sl +10009d66: fa1f fa80 uxth.w sl, r0 +10009d6a: e004 b.n 10009d76 + +10009d6c : +10009d6c: 9408 str r4, [sp, #32] +10009d6e: f8bd 000e ldrh.w r0, [sp, #14] +10009d72: 1980 adds r0, r0, r6 +10009d74: b286 uxth r6, r0 + +10009d76 : +10009d76: f8bd 0030 ldrh.w r0, [sp, #48] ; 0x30 +10009d7a: 4286 cmp r6, r0 +10009d7c: da70 bge.n 10009e60 +10009d7e: 1b80 subs r0, r0, r6 +10009d80: f8bd 1010 ldrh.w r1, [sp, #16] +10009d84: b280 uxth r0, r0 +10009d86: 4281 cmp r1, r0 +10009d88: bf88 it hi +10009d8a: 4601 movhi r1, r0 +10009d8c: 980b ldr r0, [sp, #44] ; 0x2c +10009d8e: f8ad 100e strh.w r1, [sp, #14] +10009d92: 1830 adds r0, r6, r0 +10009d94: 9007 str r0, [sp, #28] +10009d96: ea5f 70c8 movs.w r0, r8, lsl #31 +10009d9a: d513 bpl.n 10009dc4 +10009d9c: f1bb 0f00 cmp.w fp, #0 +10009da0: bf0c ite eq +10009da2: 2001 moveq r0, #1 +10009da4: 2000 movne r0, #0 +10009da6: f000 f8b5 bl 10009f14 + +10009daa : +10009daa: f8bd 2010 ldrh.w r2, [sp, #16] +10009dae: f8bd 100e ldrh.w r1, [sp, #14] +10009db2: 9000 str r0, [sp, #0] +10009db4: 2000 movs r0, #0 +10009db6: f7ff feef bl 10009b98 +10009dba: 9001 str r0, [sp, #4] +10009dbc: b1b0 cbz r0, 10009dec +10009dbe: f000 f8a3 bl 10009f08 + +10009dc2 : +10009dc2: e029 b.n 10009e18 + +10009dc4 : +10009dc4: f8bd 100e ldrh.w r1, [sp, #14] +10009dc8: 2201 movs r2, #1 +10009dca: 2000 movs r0, #0 +10009dcc: f7fe fbfc bl 100085c8 +10009dd0: 0004 movs r4, r0 +10009dd2: d00b beq.n 10009dec +10009dd4: 9807 ldr r0, [sp, #28] +10009dd6: 6060 str r0, [r4, #4] +10009dd8: 2100 movs r1, #0 +10009dda: 2200 movs r2, #0 +10009ddc: 4608 mov r0, r1 +10009dde: f7fe fbf3 bl 100085c8 +10009de2: 9001 str r0, [sp, #4] +10009de4: b9a8 cbnz r0, 10009e12 +10009de6: 4620 mov r0, r4 + +10009de8 : +10009de8: f7fe fcfe bl 100087e8 + +10009dec : +10009dec: 7ab8 ldrb r0, [r7, #10] +10009dee: f040 0080 orr.w r0, r0, #128 ; 0x80 +10009df2: 72b8 strb r0, [r7, #10] +10009df4: 9805 ldr r0, [sp, #20] +10009df6: b108 cbz r0, 10009dfc +10009df8: f7fe fcf6 bl 100087e8 + +10009dfc : +10009dfc: f1bb 0f00 cmp.w fp, #0 +10009e00: bf1c itt ne +10009e02: 4658 movne r0, fp +10009e04: f7ff fa28 blne 10009258 + +10009e08 : +10009e08: f04f 30ff mov.w r0, #4294967295 + +10009e0c : +10009e0c: b00d add sp, #52 ; 0x34 +10009e0e: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +10009e12 : +10009e12: 4621 mov r1, r4 +10009e14: f7fe fd2b bl 1000886e + +10009e18 : +10009e18: 9801 ldr r0, [sp, #4] +10009e1a: f7fe fd13 bl 10008844 +10009e1e: 4450 add r0, sl +10009e20: fa1f fa80 uxth.w sl, r0 +10009e24: f1ba 0f15 cmp.w sl, #21 +10009e28: da03 bge.n 10009e32 +10009e2a: f64f 70fd movw r0, #65533 ; 0xfffd +10009e2e: 4582 cmp sl, r0 +10009e30: d301 bcc.n 10009e36 + +10009e32 : +10009e32: 9801 ldr r0, [sp, #4] +10009e34: e7d8 b.n 10009de8 + +10009e36 : +10009e36: 2000 movs r0, #0 +10009e38: 9000 str r0, [sp, #0] +10009e3a: 2200 movs r2, #0 +10009e3c: 6cb8 ldr r0, [r7, #72] ; 0x48 +10009e3e: 9901 ldr r1, [sp, #4] +10009e40: 1833 adds r3, r6, r0 +10009e42: 980a ldr r0, [sp, #40] ; 0x28 +10009e44: f7ff fe58 bl 10009af8 +10009e48: 0004 movs r4, r0 +10009e4a: d0cf beq.n 10009dec +10009e4c: f8bd 000c ldrh.w r0, [sp, #12] +10009e50: 8160 strh r0, [r4, #10] +10009e52: f1bb 0f00 cmp.w fp, #0 +10009e56: bf0e itee eq +10009e58: 46a3 moveq fp, r4 +10009e5a: 9808 ldrne r0, [sp, #32] +10009e5c: 6004 strne r4, [r0, #0] +10009e5e: e785 b.n 10009d6c + +10009e60 : +10009e60: f1b9 0f00 cmp.w r9, #0 +10009e64: d01a beq.n 10009e9c +10009e66: 686e ldr r6, [r5, #4] +10009e68: e00f b.n 10009e8a + +10009e6a : +10009e6a: 8930 ldrh r0, [r6, #8] +10009e6c: 4448 add r0, r9 +10009e6e: 8130 strh r0, [r6, #8] +10009e70: 6830 ldr r0, [r6, #0] +10009e72: b948 cbnz r0, 10009e88 +10009e74: 6870 ldr r0, [r6, #4] +10009e76: 8973 ldrh r3, [r6, #10] +10009e78: 990b ldr r1, [sp, #44] ; 0x2c +10009e7a: 464a mov r2, r9 +10009e7c: 1818 adds r0, r3, r0 +10009e7e: f002 fa63 bl 1000c348 +10009e82: 8970 ldrh r0, [r6, #10] +10009e84: 4448 add r0, r9 +10009e86: 8170 strh r0, [r6, #10] + +10009e88 : +10009e88: 6836 ldr r6, [r6, #0] + +10009e8a : +10009e8a: 2e00 cmp r6, #0 +10009e8c: d1ed bne.n 10009e6a +10009e8e: 8928 ldrh r0, [r5, #8] +10009e90: 4448 add r0, r9 +10009e92: 8128 strh r0, [r5, #8] +10009e94: 8968 ldrh r0, [r5, #10] +10009e96: eba0 0009 sub.w r0, r0, r9 +10009e9a: 8168 strh r0, [r5, #10] + +10009e9c : +10009e9c: 9906 ldr r1, [sp, #24] +10009e9e: f8bd 000c ldrh.w r0, [sp, #12] +10009ea2: 8108 strh r0, [r1, #8] +10009ea4: 9805 ldr r0, [sp, #20] +10009ea6: b140 cbz r0, 10009eba +10009ea8: 4601 mov r1, r0 +10009eaa: 6868 ldr r0, [r5, #4] +10009eac: f7fe fcdf bl 1000886e +10009eb0: 9905 ldr r1, [sp, #20] +10009eb2: 8928 ldrh r0, [r5, #8] +10009eb4: 8909 ldrh r1, [r1, #8] +10009eb6: 1808 adds r0, r1, r0 +10009eb8: 8128 strh r0, [r5, #8] + +10009eba : +10009eba: 2d00 cmp r5, #0 +10009ebc: bf06 itte eq +10009ebe: 980a ldreq r0, [sp, #40] ; 0x28 +10009ec0: f8c0 b070 streq.w fp, [r0, #112] ; 0x70 +10009ec4: f8c5 b000 strne.w fp, [r5] +10009ec8: 6cb8 ldr r0, [r7, #72] ; 0x48 +10009eca: f8bd 1030 ldrh.w r1, [sp, #48] ; 0x30 +10009ece: 1808 adds r0, r1, r0 +10009ed0: 64b8 str r0, [r7, #72] ; 0x48 +10009ed2: 9806 ldr r0, [sp, #24] +10009ed4: f8bd 1030 ldrh.w r1, [sp, #48] ; 0x30 +10009ed8: 8880 ldrh r0, [r0, #4] +10009eda: 1a40 subs r0, r0, r1 +10009edc: 9906 ldr r1, [sp, #24] +10009ede: 8088 strh r0, [r1, #4] +10009ee0: 2c00 cmp r4, #0 +10009ee2: 9806 ldr r0, [sp, #24] +10009ee4: f8a0 a006 strh.w sl, [r0, #6] +10009ee8: bf1c itt ne +10009eea: 6920 ldrne r0, [r4, #16] +10009eec: 2800 cmpne r0, #0 +10009eee: d009 beq.n 10009f04 +10009ef0: ea5f 7088 movs.w r0, r8, lsl #30 +10009ef4: d406 bmi.n 10009f04 +10009ef6: 2008 movs r0, #8 +10009ef8: f002 fb25 bl 1000c546 +10009efc: 6921 ldr r1, [r4, #16] +10009efe: 898a ldrh r2, [r1, #12] +10009f00: 4310 orrs r0, r2 +10009f02: 8188 strh r0, [r1, #12] + +10009f04 : +10009f04: 2000 movs r0, #0 +10009f06: e781 b.n 10009e0c + +10009f08 : +10009f08: f8bd 200e ldrh.w r2, [sp, #14] +10009f0c: 9907 ldr r1, [sp, #28] +10009f0e: 6840 ldr r0, [r0, #4] +10009f10: f002 ba1a b.w 1000c348 + +10009f14 : +10009f14: 9002 str r0, [sp, #8] +10009f16: f8cd 8004 str.w r8, [sp, #4] +10009f1a: ab03 add r3, sp, #12 +10009f1c: 980a ldr r0, [sp, #40] ; 0x28 +10009f1e: 4770 bx lr + +10009f20 : +10009f20: b5f8 push {r3, r4, r5, r6, r7, lr} +10009f22: 4605 mov r5, r0 +10009f24: f105 0460 add.w r4, r5, #96 ; 0x60 +10009f28: 2700 movs r7, #0 +10009f2a: 89a0 ldrh r0, [r4, #12] +10009f2c: 460e mov r6, r1 +10009f2e: 2814 cmp r0, #20 +10009f30: da17 bge.n 10009f62 +10009f32: f64f 71fd movw r1, #65533 ; 0xfffd +10009f36: 4288 cmp r0, r1 +10009f38: d213 bcs.n 10009f62 +10009f3a: 07b0 lsls r0, r6, #30 +10009f3c: bf46 itte mi +10009f3e: 2701 movmi r7, #1 +10009f40: 2104 movmi r1, #4 +10009f42: 2100 movpl r1, #0 +10009f44: 8960 ldrh r0, [r4, #10] +10009f46: b190 cbz r0, 10009f6e +10009f48: 2200 movs r2, #0 +10009f4a: 2000 movs r0, #0 +10009f4c: f7fe fb3c bl 100085c8 +10009f50: b138 cbz r0, 10009f62 +10009f52: 9700 str r7, [sp, #0] +10009f54: 4601 mov r1, r0 +10009f56: 6e2b ldr r3, [r5, #96] ; 0x60 +10009f58: 4632 mov r2, r6 +10009f5a: 4628 mov r0, r5 +10009f5c: f7ff fdcc bl 10009af8 +10009f60: b940 cbnz r0, 10009f74 + +10009f62 : +10009f62: f895 0022 ldrb.w r0, [r5, #34] ; 0x22 +10009f66: f040 0080 orr.w r0, r0, #128 ; 0x80 +10009f6a: f885 0022 strb.w r0, [r5, #34] ; 0x22 + +10009f6e : +10009f6e: f04f 30ff mov.w r0, #4294967295 +10009f72: bdf2 pop {r1, r4, r5, r6, r7, pc} + +10009f74 : +10009f74: 6921 ldr r1, [r4, #16] +10009f76: b911 cbnz r1, 10009f7e +10009f78: 6120 str r0, [r4, #16] +10009f7a: e004 b.n 10009f86 + +10009f7c : +10009f7c: 4611 mov r1, r2 + +10009f7e : +10009f7e: 680a ldr r2, [r1, #0] +10009f80: 2a00 cmp r2, #0 +10009f82: d1fb bne.n 10009f7c +10009f84: 6008 str r0, [r1, #0] + +10009f86 : +10009f86: 2100 movs r1, #0 +10009f88: 81e1 strh r1, [r4, #14] +10009f8a: 2103 movs r1, #3 +10009f8c: 420e tst r6, r1 +10009f8e: d005 beq.n 10009f9c +10009f90: 6e29 ldr r1, [r5, #96] ; 0x60 +10009f92: 1c49 adds r1, r1, #1 +10009f94: 6629 str r1, [r5, #96] ; 0x60 +10009f96: 8961 ldrh r1, [r4, #10] +10009f98: 1e49 subs r1, r1, #1 +10009f9a: 8161 strh r1, [r4, #10] + +10009f9c : +10009f9c: 07f1 lsls r1, r6, #31 +10009f9e: d505 bpl.n 10009fac +10009fa0: f895 1022 ldrb.w r1, [r5, #34] ; 0x22 +10009fa4: f041 0120 orr.w r1, r1, #32 +10009fa8: f885 1022 strb.w r1, [r5, #34] ; 0x22 + +10009fac : +10009fac: 6840 ldr r0, [r0, #4] +10009fae: f7fe fc49 bl 10008844 +10009fb2: 89a1 ldrh r1, [r4, #12] +10009fb4: 1840 adds r0, r0, r1 +10009fb6: 81a0 strh r0, [r4, #12] +10009fb8: 2000 movs r0, #0 +10009fba: bdf2 pop {r1, r4, r5, r6, r7, pc} + +10009fbc : +10009fbc: b5f0 push {r4, r5, r6, r7, lr} +10009fbe: 4604 mov r4, r0 +10009fc0: b083 sub sp, #12 +10009fc2: 6d60 ldr r0, [r4, #84] ; 0x54 +10009fc4: f002 fac5 bl 1000c552 +10009fc8: f000 f9ff bl 1000a3ca + +10009fcc : +10009fcc: 0005 movs r5, r0 +10009fce: d102 bne.n 10009fd6 +10009fd0: f06f 0001 mvn.w r0, #1 +10009fd4: bdfe pop {r1, r2, r3, r4, r5, r6, r7, pc} + +10009fd6 : +10009fd6: f104 0609 add.w r6, r4, #9 +10009fda: 7e70 ldrb r0, [r6, #25] +10009fdc: 686f ldr r7, [r5, #4] +10009fde: f000 00fc and.w r0, r0, #252 ; 0xfc +10009fe2: 7670 strb r0, [r6, #25] +10009fe4: 2306 movs r3, #6 +10009fe6: 8928 ldrh r0, [r5, #8] +10009fe8: 9000 str r0, [sp, #0] +10009fea: f000 f9e9 bl 1000a3c0 + +10009fee : +10009fee: 8238 strh r0, [r7, #16] +10009ff0: 1d22 adds r2, r4, #4 +10009ff2: 2006 movs r0, #6 +10009ff4: 9001 str r0, [sp, #4] +10009ff6: 4621 mov r1, r4 +10009ff8: 7a60 ldrb r0, [r4, #9] +10009ffa: 9000 str r0, [sp, #0] +10009ffc: 4628 mov r0, r5 +10009ffe: 7873 ldrb r3, [r6, #1] +1000a000: f001 ff86 bl 1000bf10 +1000a004: 4628 mov r0, r5 +1000a006: f7fe fbef bl 100087e8 +1000a00a: 2000 movs r0, #0 +1000a00c: bdfe pop {r1, r2, r3, r4, r5, r6, r7, pc} + +1000a00e : +1000a00e: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1000a012: 4681 mov r9, r0 +1000a014: 4885 ldr r0, [pc, #532] ; (1000a22c ) +1000a016: 6800 ldr r0, [r0, #0] +1000a018: 4548 cmp r0, r9 +1000a01a: f000 80a8 beq.w 1000a16e +1000a01e: f109 0618 add.w r6, r9, #24 +1000a022: f8b9 8064 ldrh.w r8, [r9, #100] ; 0x64 +1000a026: 8f30 ldrh r0, [r6, #56] ; 0x38 +1000a028: 4580 cmp r8, r0 +1000a02a: bf28 it cs +1000a02c: 4680 movcs r8, r0 +1000a02e: f109 0764 add.w r7, r9, #100 ; 0x64 +1000a032: 7ab0 ldrb r0, [r6, #10] +1000a034: 68fc ldr r4, [r7, #12] +1000a036: 0780 lsls r0, r0, #30 +1000a038: d50c bpl.n 1000a054 +1000a03a: b13c cbz r4, 1000a04c +1000a03c: f000 f979 bl 1000a332 + +1000a040 : +1000a040: 6b71 ldr r1, [r6, #52] ; 0x34 +1000a042: 1a40 subs r0, r0, r1 +1000a044: 8921 ldrh r1, [r4, #8] +1000a046: 1808 adds r0, r1, r0 +1000a048: 4580 cmp r8, r0 +1000a04a: d203 bcs.n 1000a054 + +1000a04c : +1000a04c: 4648 mov r0, r9 +1000a04e: e8bd 4ff2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1000a052: e7b3 b.n 10009fbc + +1000a054 : +1000a054: 693d ldr r5, [r7, #16] +1000a056: b125 cbz r5, 1000a062 +1000a058: e000 b.n 1000a05c + +1000a05a : +1000a05a: 4605 mov r5, r0 + +1000a05c : +1000a05c: 6828 ldr r0, [r5, #0] +1000a05e: 2800 cmp r0, #0 +1000a060: d1fb bne.n 1000a05a + +1000a062 : +1000a062: 2c00 cmp r4, #0 +1000a064: d07c beq.n 1000a160 +1000a066: f000 f964 bl 1000a332 + +1000a06a : +1000a06a: 6b71 ldr r1, [r6, #52] ; 0x34 +1000a06c: 1a40 subs r0, r0, r1 +1000a06e: 8921 ldrh r1, [r4, #8] +1000a070: 1808 adds r0, r1, r0 +1000a072: 4580 cmp r8, r0 +1000a074: d374 bcc.n 1000a160 +1000a076: f000 fa01 bl 1000a47c + +1000a07a : +1000a07a: 6938 ldr r0, [r7, #16] +1000a07c: b198 cbz r0, 1000a0a6 +1000a07e: 7ab1 ldrb r1, [r6, #10] +1000a080: 2244 movs r2, #68 ; 0x44 +1000a082: 4211 tst r1, r2 +1000a084: d10f bne.n 1000a0a6 +1000a086: 68f8 ldr r0, [r7, #12] +1000a088: b128 cbz r0, 1000a096 +1000a08a: 6802 ldr r2, [r0, #0] +1000a08c: b95a cbnz r2, 1000a0a6 +1000a08e: 8900 ldrh r0, [r0, #8] +1000a090: 8c72 ldrh r2, [r6, #34] ; 0x22 +1000a092: 4290 cmp r0, r2 +1000a094: d207 bcs.n 1000a0a6 + +1000a096 : +1000a096: 88f8 ldrh r0, [r7, #6] +1000a098: b128 cbz r0, 1000a0a6 +1000a09a: 8938 ldrh r0, [r7, #8] +1000a09c: 2814 cmp r0, #20 +1000a09e: da02 bge.n 1000a0a6 +1000a0a0: 20a0 movs r0, #160 ; 0xa0 +1000a0a2: 4201 tst r1, r0 +1000a0a4: d05c beq.n 1000a160 + +1000a0a6 : +1000a0a6: 6820 ldr r0, [r4, #0] +1000a0a8: 60f8 str r0, [r7, #12] +1000a0aa: f8d9 0018 ldr.w r0, [r9, #24] +1000a0ae: 2802 cmp r0, #2 +1000a0b0: d00a beq.n 1000a0c8 +1000a0b2: 2010 movs r0, #16 +1000a0b4: f002 fa47 bl 1000c546 +1000a0b8: 6921 ldr r1, [r4, #16] +1000a0ba: 898a ldrh r2, [r1, #12] +1000a0bc: 4310 orrs r0, r2 +1000a0be: 8188 strh r0, [r1, #12] +1000a0c0: 7ab0 ldrb r0, [r6, #10] +1000a0c2: f000 00fc and.w r0, r0, #252 ; 0xfc +1000a0c6: 72b0 strb r0, [r6, #10] + +1000a0c8 : +1000a0c8: 4649 mov r1, r9 +1000a0ca: 4620 mov r0, r4 +1000a0cc: f000 f852 bl 1000a174 +1000a0d0: f000 f92f bl 1000a332 + +1000a0d4 : +1000a0d4: 4682 mov sl, r0 +1000a0d6: f000 f9d1 bl 1000a47c + +1000a0da : +1000a0da: f010 0003 ands.w r0, r0, #3 +1000a0de: bf18 it ne +1000a0e0: 2001 movne r0, #1 +1000a0e2: 8921 ldrh r1, [r4, #8] +1000a0e4: 1840 adds r0, r0, r1 +1000a0e6: 6bf1 ldr r1, [r6, #60] ; 0x3c +1000a0e8: 4450 add r0, sl +1000a0ea: 1a09 subs r1, r1, r0 +1000a0ec: bf48 it mi +1000a0ee: 63f0 strmi r0, [r6, #60] ; 0x3c +1000a0f0: f000 f9c4 bl 1000a47c + +1000a0f4 : +1000a0f4: f010 0003 ands.w r0, r0, #3 +1000a0f8: bf18 it ne +1000a0fa: 2001 movne r0, #1 +1000a0fc: 8921 ldrh r1, [r4, #8] +1000a0fe: 1840 adds r0, r0, r1 +1000a100: 2801 cmp r0, #1 +1000a102: db28 blt.n 1000a156 +1000a104: 2000 movs r0, #0 +1000a106: 6020 str r0, [r4, #0] +1000a108: 6938 ldr r0, [r7, #16] +1000a10a: b908 cbnz r0, 1000a110 +1000a10c: 613c str r4, [r7, #16] +1000a10e: e020 b.n 1000a152 + +1000a110 : +1000a110: f000 f90f bl 1000a332 + +1000a114 : +1000a114: 4682 mov sl, r0 +1000a116: 6928 ldr r0, [r5, #16] +1000a118: f000 f90c bl 1000a334 + +1000a11c : +1000a11c: ebba 0000 subs.w r0, sl, r0 +1000a120: d516 bpl.n 1000a150 +1000a122: f109 0a74 add.w sl, r9, #116 ; 0x74 +1000a126: e001 b.n 1000a12c + +1000a128 : +1000a128: f8da a000 ldr.w sl, [sl] + +1000a12c : +1000a12c: f8da 0000 ldr.w r0, [sl] +1000a130: b140 cbz r0, 1000a144 +1000a132: 6900 ldr r0, [r0, #16] +1000a134: f000 f8fe bl 1000a334 + +1000a138 : +1000a138: 4683 mov fp, r0 +1000a13a: f000 f8fa bl 1000a332 + +1000a13e : +1000a13e: ebbb 0000 subs.w r0, fp, r0 +1000a142: d4f1 bmi.n 1000a128 + +1000a144 : +1000a144: f8da 0000 ldr.w r0, [sl] +1000a148: 6020 str r0, [r4, #0] +1000a14a: f8ca 4000 str.w r4, [sl] +1000a14e: e005 b.n 1000a15c + +1000a150 : +1000a150: 602c str r4, [r5, #0] + +1000a152 : +1000a152: 4625 mov r5, r4 +1000a154: e002 b.n 1000a15c + +1000a156 : +1000a156: 4620 mov r0, r4 +1000a158: f7ff f887 bl 1000926a + +1000a15c : +1000a15c: 68fc ldr r4, [r7, #12] +1000a15e: e780 b.n 1000a062 + +1000a160 : +1000a160: 68f8 ldr r0, [r7, #12] +1000a162: b900 cbnz r0, 1000a166 +1000a164: 8178 strh r0, [r7, #10] + +1000a166 : +1000a166: 7ab0 ldrb r0, [r6, #10] +1000a168: f000 007f and.w r0, r0, #127 ; 0x7f +1000a16c: 72b0 strb r0, [r6, #10] + +1000a16e : +1000a16e: 2000 movs r0, #0 +1000a170: e8bd 8ff2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1000a174 : +1000a174: b57c push {r2, r3, r4, r5, r6, lr} +1000a176: 460d mov r5, r1 +1000a178: 4604 mov r4, r0 +1000a17a: 6ae8 ldr r0, [r5, #44] ; 0x2c +1000a17c: f002 f9e9 bl 1000c552 +1000a180: 6921 ldr r1, [r4, #16] +1000a182: 6088 str r0, [r1, #8] +1000a184: 8e68 ldrh r0, [r5, #50] ; 0x32 +1000a186: f002 f9de bl 1000c546 +1000a18a: 6921 ldr r1, [r4, #16] +1000a18c: 81c8 strh r0, [r1, #14] +1000a18e: f101 0614 add.w r6, r1, #20 +1000a192: 6ae8 ldr r0, [r5, #44] ; 0x2c +1000a194: 8e6a ldrh r2, [r5, #50] ; 0x32 +1000a196: 1810 adds r0, r2, r0 +1000a198: 6368 str r0, [r5, #52] ; 0x34 +1000a19a: 7b20 ldrb r0, [r4, #12] +1000a19c: 07c0 lsls r0, r0, #31 +1000a19e: d509 bpl.n 1000a1b4 +1000a1a0: 1d29 adds r1, r5, #4 +1000a1a2: f240 50b4 movw r0, #1460 ; 0x5b4 +1000a1a6: f7ff f985 bl 100094b4 +1000a1aa: f040 7001 orr.w r0, r0, #33816576 ; 0x2040000 +1000a1ae: f002 f9d0 bl 1000c552 +1000a1b2: 6030 str r0, [r6, #0] + +1000a1b4 : +1000a1b4: f9b5 0038 ldrsh.w r0, [r5, #56] ; 0x38 +1000a1b8: f110 0f01 cmn.w r0, #1 +1000a1bc: bf04 itt eq +1000a1be: 2000 moveq r0, #0 +1000a1c0: 8728 strheq r0, [r5, #56] ; 0x38 +1000a1c2: 2d00 cmp r5, #0 +1000a1c4: bf1c itt ne +1000a1c6: 6828 ldrne r0, [r5, #0] +1000a1c8: 2800 cmpne r0, #0 +1000a1ca: d105 bne.n 1000a1d8 +1000a1cc: 1d28 adds r0, r5, #4 +1000a1ce: f001 fd6d bl 1000bcac +1000a1d2: b350 cbz r0, 1000a22a +1000a1d4: 6840 ldr r0, [r0, #4] +1000a1d6: 6028 str r0, [r5, #0] + +1000a1d8 : +1000a1d8: 6be8 ldr r0, [r5, #60] ; 0x3c +1000a1da: b928 cbnz r0, 1000a1e8 +1000a1dc: 4814 ldr r0, [pc, #80] ; (1000a230 ) +1000a1de: 6800 ldr r0, [r0, #0] +1000a1e0: 63e8 str r0, [r5, #60] ; 0x3c +1000a1e2: f000 f8a6 bl 1000a332 + +1000a1e6 : +1000a1e6: 6428 str r0, [r5, #64] ; 0x40 + +1000a1e8 : +1000a1e8: 6860 ldr r0, [r4, #4] +1000a1ea: 6921 ldr r1, [r4, #16] +1000a1ec: 6842 ldr r2, [r0, #4] +1000a1ee: 8943 ldrh r3, [r0, #10] +1000a1f0: 1a8a subs r2, r1, r2 +1000a1f2: b292 uxth r2, r2 +1000a1f4: 1a9b subs r3, r3, r2 +1000a1f6: 8143 strh r3, [r0, #10] +1000a1f8: 8903 ldrh r3, [r0, #8] +1000a1fa: 1a9a subs r2, r3, r2 +1000a1fc: 8102 strh r2, [r0, #8] +1000a1fe: 6041 str r1, [r0, #4] +1000a200: 2200 movs r2, #0 +1000a202: 820a strh r2, [r1, #16] +1000a204: 2306 movs r3, #6 +1000a206: 8901 ldrh r1, [r0, #8] +1000a208: 9100 str r1, [sp, #0] +1000a20a: 1d2a adds r2, r5, #4 +1000a20c: 4629 mov r1, r5 +1000a20e: f002 f9d9 bl 1000c5c4 +1000a212: 6921 ldr r1, [r4, #16] +1000a214: 8208 strh r0, [r1, #16] +1000a216: 1d2a adds r2, r5, #4 +1000a218: 2006 movs r0, #6 +1000a21a: 9001 str r0, [sp, #4] +1000a21c: 4629 mov r1, r5 +1000a21e: 7a68 ldrb r0, [r5, #9] +1000a220: 9000 str r0, [sp, #0] +1000a222: 7aab ldrb r3, [r5, #10] +1000a224: 6860 ldr r0, [r4, #4] +1000a226: f001 fe73 bl 1000bf10 + +1000a22a : +1000a22a: bd73 pop {r0, r1, r4, r5, r6, pc} + +1000a22c : +1000a22c: 7afc 1004 .z.. + +1000a230 : +1000a230: 407c 1004 |@.. + +1000a234 : +1000a234: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} +1000a238: 4680 mov r8, r0 +1000a23a: 4689 mov r9, r1 +1000a23c: 4614 mov r4, r2 +1000a23e: b083 sub sp, #12 +1000a240: 461d mov r5, r3 +1000a242: 2200 movs r2, #0 +1000a244: 2114 movs r1, #20 +1000a246: 2001 movs r0, #1 +1000a248: f7fe f9be bl 100085c8 +1000a24c: 0006 movs r6, r0 +1000a24e: d033 beq.n 1000a2b8 +1000a250: 6877 ldr r7, [r6, #4] +1000a252: 980a ldr r0, [sp, #40] ; 0x28 +1000a254: f002 f977 bl 1000c546 +1000a258: 8038 strh r0, [r7, #0] +1000a25a: 980b ldr r0, [sp, #44] ; 0x2c +1000a25c: f002 f973 bl 1000c546 +1000a260: 8078 strh r0, [r7, #2] +1000a262: 4640 mov r0, r8 +1000a264: f002 f975 bl 1000c552 +1000a268: 6078 str r0, [r7, #4] +1000a26a: 4648 mov r0, r9 +1000a26c: f002 f971 bl 1000c552 +1000a270: 60b8 str r0, [r7, #8] +1000a272: f245 0014 movw r0, #20500 ; 0x5014 +1000a276: f002 f966 bl 1000c546 +1000a27a: 81b8 strh r0, [r7, #12] +1000a27c: 2306 movs r3, #6 +1000a27e: f646 000b movw r0, #26635 ; 0x680b +1000a282: 81f8 strh r0, [r7, #14] +1000a284: 462a mov r2, r5 +1000a286: 2000 movs r0, #0 +1000a288: 8238 strh r0, [r7, #16] +1000a28a: 8278 strh r0, [r7, #18] +1000a28c: 4621 mov r1, r4 +1000a28e: 8930 ldrh r0, [r6, #8] +1000a290: 9000 str r0, [sp, #0] +1000a292: 4630 mov r0, r6 +1000a294: f002 f996 bl 1000c5c4 +1000a298: 8238 strh r0, [r7, #16] +1000a29a: 23ff movs r3, #255 ; 0xff +1000a29c: 2006 movs r0, #6 +1000a29e: 9001 str r0, [sp, #4] +1000a2a0: 462a mov r2, r5 +1000a2a2: 2000 movs r0, #0 +1000a2a4: 9000 str r0, [sp, #0] +1000a2a6: 4621 mov r1, r4 +1000a2a8: 4630 mov r0, r6 +1000a2aa: f001 fe31 bl 1000bf10 +1000a2ae: 4630 mov r0, r6 +1000a2b0: e8bd 43fe ldmia.w sp!, {r1, r2, r3, r4, r5, r6, r7, r8, r9, lr} +1000a2b4: f7fe ba98 b.w 100087e8 + +1000a2b8 : +1000a2b8: e8bd 83f7 ldmia.w sp!, {r0, r1, r2, r4, r5, r6, r7, r8, r9, pc} + +1000a2bc : +1000a2bc: f100 013c add.w r1, r0, #60 ; 0x3c +1000a2c0: 6b8a ldr r2, [r1, #56] ; 0x38 +1000a2c2: b90a cbnz r2, 1000a2c8 +1000a2c4: 4770 bx lr + +1000a2c6 : +1000a2c6: 461a mov r2, r3 + +1000a2c8 : +1000a2c8: 6813 ldr r3, [r2, #0] +1000a2ca: 2b00 cmp r3, #0 +1000a2cc: d1fb bne.n 1000a2c6 +1000a2ce: 6b4b ldr r3, [r1, #52] ; 0x34 +1000a2d0: 6013 str r3, [r2, #0] +1000a2d2: 6b8a ldr r2, [r1, #56] ; 0x38 +1000a2d4: 634a str r2, [r1, #52] ; 0x34 +1000a2d6: 2200 movs r2, #0 +1000a2d8: 638a str r2, [r1, #56] ; 0x38 +1000a2da: 7b8a ldrb r2, [r1, #14] +1000a2dc: 1c52 adds r2, r2, #1 +1000a2de: 738a strb r2, [r1, #14] +1000a2e0: 2100 movs r1, #0 +1000a2e2: 63c1 str r1, [r0, #60] ; 0x3c +1000a2e4: e693 b.n 1000a00e + +1000a2e6 : +1000a2e6: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1000a2ea: 4604 mov r4, r0 +1000a2ec: f104 053c add.w r5, r4, #60 ; 0x3c +1000a2f0: 6bae ldr r6, [r5, #56] ; 0x38 +1000a2f2: b1e6 cbz r6, 1000a32e +1000a2f4: 6830 ldr r0, [r6, #0] +1000a2f6: 63a8 str r0, [r5, #56] ; 0x38 +1000a2f8: f104 0770 add.w r7, r4, #112 ; 0x70 +1000a2fc: e000 b.n 1000a300 + +1000a2fe : +1000a2fe: 683f ldr r7, [r7, #0] + +1000a300 : +1000a300: 6838 ldr r0, [r7, #0] +1000a302: b148 cbz r0, 1000a318 +1000a304: 6900 ldr r0, [r0, #16] +1000a306: f000 f815 bl 1000a334 + +1000a30a : +1000a30a: 4680 mov r8, r0 +1000a30c: 6930 ldr r0, [r6, #16] +1000a30e: f000 f811 bl 1000a334 + +1000a312 : +1000a312: ebb8 0000 subs.w r0, r8, r0 +1000a316: d4f2 bmi.n 1000a2fe + +1000a318 : +1000a318: 6838 ldr r0, [r7, #0] +1000a31a: 6030 str r0, [r6, #0] +1000a31c: 603e str r6, [r7, #0] +1000a31e: 6830 ldr r0, [r6, #0] +1000a320: b900 cbnz r0, 1000a324 +1000a322: 8668 strh r0, [r5, #50] ; 0x32 + +1000a324 : +1000a324: 7ba8 ldrb r0, [r5, #14] +1000a326: 1c40 adds r0, r0, #1 +1000a328: 73a8 strb r0, [r5, #14] +1000a32a: 2000 movs r0, #0 +1000a32c: 63e0 str r0, [r4, #60] ; 0x3c + +1000a32e : +1000a32e: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +1000a332 : +1000a332: 6920 ldr r0, [r4, #16] + +1000a334 : +1000a334: 6840 ldr r0, [r0, #4] +1000a336: f002 b918 b.w 1000c56a + +1000a33a : +1000a33a: b510 push {r4, lr} +1000a33c: 4604 mov r4, r0 +1000a33e: 6f60 ldr r0, [r4, #116] ; 0x74 +1000a340: b300 cbz r0, 1000a384 +1000a342: f894 0022 ldrb.w r0, [r4, #34] ; 0x22 +1000a346: 0740 lsls r0, r0, #29 +1000a348: d41c bmi.n 1000a384 +1000a34a: 4620 mov r0, r4 +1000a34c: f7ff ffcb bl 1000a2e6 +1000a350: f104 0022 add.w r0, r4, #34 ; 0x22 +1000a354: f8b4 2064 ldrh.w r2, [r4, #100] ; 0x64 +1000a358: 8dc1 ldrh r1, [r0, #46] ; 0x2e +1000a35a: 428a cmp r2, r1 +1000a35c: bf34 ite cc +1000a35e: 0851 lsrcc r1, r2, #1 +1000a360: 0849 lsrcs r1, r1, #1 +1000a362: 8b02 ldrh r2, [r0, #24] +1000a364: ebb1 0f42 cmp.w r1, r2, lsl #1 +1000a368: bfb8 it lt +1000a36a: 0051 lsllt r1, r2, #1 +1000a36c: 8601 strh r1, [r0, #48] ; 0x30 +1000a36e: eb02 0242 add.w r2, r2, r2, lsl #1 +1000a372: 8e01 ldrh r1, [r0, #48] ; 0x30 +1000a374: 1851 adds r1, r2, r1 +1000a376: 85c1 strh r1, [r0, #46] ; 0x2e +1000a378: f894 0022 ldrb.w r0, [r4, #34] ; 0x22 +1000a37c: f040 0004 orr.w r0, r0, #4 +1000a380: f884 0022 strb.w r0, [r4, #34] ; 0x22 + +1000a384 : +1000a384: bd10 pop {r4, pc} + +1000a386 : +1000a386: b57c push {r2, r3, r4, r5, r6, lr} +1000a388: 4604 mov r4, r0 +1000a38a: 6d60 ldr r0, [r4, #84] ; 0x54 +1000a38c: 1e40 subs r0, r0, #1 +1000a38e: f002 f8e0 bl 1000c552 +1000a392: f000 f81a bl 1000a3ca + +1000a396 : +1000a396: 0005 movs r5, r0 +1000a398: d011 beq.n 1000a3be +1000a39a: 686e ldr r6, [r5, #4] +1000a39c: 8928 ldrh r0, [r5, #8] +1000a39e: 9000 str r0, [sp, #0] +1000a3a0: 2306 movs r3, #6 +1000a3a2: f000 f80d bl 1000a3c0 + +1000a3a6 : +1000a3a6: 8230 strh r0, [r6, #16] +1000a3a8: f000 f861 bl 1000a46e + +1000a3ac : +1000a3ac: 4628 mov r0, r5 +1000a3ae: 7aa3 ldrb r3, [r4, #10] +1000a3b0: f001 fdae bl 1000bf10 +1000a3b4: 4628 mov r0, r5 +1000a3b6: e8bd 4076 ldmia.w sp!, {r1, r2, r4, r5, r6, lr} +1000a3ba: f7fe ba15 b.w 100087e8 + +1000a3be : +1000a3be: bd73 pop {r0, r1, r4, r5, r6, pc} + +1000a3c0 : +1000a3c0: 1d22 adds r2, r4, #4 +1000a3c2: 4621 mov r1, r4 +1000a3c4: 4628 mov r0, r5 +1000a3c6: f002 b8fd b.w 1000c5c4 + +1000a3ca : +1000a3ca: 4603 mov r3, r0 +1000a3cc: 2200 movs r2, #0 +1000a3ce: 2100 movs r1, #0 +1000a3d0: 4620 mov r0, r4 +1000a3d2: f7ff bb37 b.w 10009a44 + +1000a3d6 : +1000a3d6: e92d 41fc stmdb sp!, {r2, r3, r4, r5, r6, r7, r8, lr} +1000a3da: 4604 mov r4, r0 +1000a3dc: 6f65 ldr r5, [r4, #116] ; 0x74 +1000a3de: b905 cbnz r5, 1000a3e2 +1000a3e0: 6f25 ldr r5, [r4, #112] ; 0x70 + +1000a3e2 : +1000a3e2: 2d00 cmp r5, #0 +1000a3e4: d041 beq.n 1000a46a +1000a3e6: 6928 ldr r0, [r5, #16] +1000a3e8: f000 f849 bl 1000a47e + +1000a3ec : +1000a3ec: 07c0 lsls r0, r0, #31 +1000a3ee: d504 bpl.n 1000a3fa +1000a3f0: 8928 ldrh r0, [r5, #8] +1000a3f2: 1e46 subs r6, r0, #1 +1000a3f4: 41b6 sbcs r6, r6 +1000a3f6: 0ff6 lsrs r6, r6, #31 +1000a3f8: e000 b.n 1000a3fc + +1000a3fa : +1000a3fa: 2600 movs r6, #0 + +1000a3fc : +1000a3fc: 6928 ldr r0, [r5, #16] +1000a3fe: 6843 ldr r3, [r0, #4] +1000a400: f086 0201 eor.w r2, r6, #1 +1000a404: 2100 movs r1, #0 +1000a406: 4620 mov r0, r4 +1000a408: f7ff fb1c bl 10009a44 +1000a40c: ea5f 0800 movs.w r8, r0 +1000a410: d02b beq.n 1000a46a +1000a412: f8d8 1004 ldr.w r1, [r8, #4] +1000a416: 460f mov r7, r1 +1000a418: b14e cbz r6, 1000a42e +1000a41a: 2011 movs r0, #17 +1000a41c: f002 f893 bl 1000c546 +1000a420: 89b9 ldrh r1, [r7, #12] +1000a422: f24c 02ff movw r2, #49407 ; 0xc0ff +1000a426: 4011 ands r1, r2 +1000a428: 4308 orrs r0, r1 +1000a42a: 81b8 strh r0, [r7, #12] +1000a42c: e008 b.n 1000a440 + +1000a42e : +1000a42e: 3114 adds r1, #20 +1000a430: 6868 ldr r0, [r5, #4] +1000a432: 892b ldrh r3, [r5, #8] +1000a434: 8902 ldrh r2, [r0, #8] +1000a436: 1ad3 subs r3, r2, r3 +1000a438: b29b uxth r3, r3 +1000a43a: 2201 movs r2, #1 +1000a43c: f7fe fa7b bl 10008936 + +1000a440 : +1000a440: f8b8 0008 ldrh.w r0, [r8, #8] +1000a444: 9000 str r0, [sp, #0] +1000a446: 2306 movs r3, #6 +1000a448: 1d22 adds r2, r4, #4 +1000a44a: 4621 mov r1, r4 +1000a44c: 4640 mov r0, r8 +1000a44e: f002 f8b9 bl 1000c5c4 +1000a452: 8238 strh r0, [r7, #16] +1000a454: f000 f80b bl 1000a46e + +1000a458 : +1000a458: 4640 mov r0, r8 +1000a45a: 7aa3 ldrb r3, [r4, #10] +1000a45c: f001 fd58 bl 1000bf10 +1000a460: 4640 mov r0, r8 +1000a462: e8bd 41f6 ldmia.w sp!, {r1, r2, r4, r5, r6, r7, r8, lr} +1000a466: f7fe b9bf b.w 100087e8 + +1000a46a : +1000a46a: e8bd 81f3 ldmia.w sp!, {r0, r1, r4, r5, r6, r7, r8, pc} + +1000a46e : +1000a46e: 1d22 adds r2, r4, #4 +1000a470: 2006 movs r0, #6 +1000a472: 9001 str r0, [sp, #4] +1000a474: 4621 mov r1, r4 +1000a476: 2000 movs r0, #0 +1000a478: 9000 str r0, [sp, #0] +1000a47a: 4770 bx lr + +1000a47c : +1000a47c: 6920 ldr r0, [r4, #16] + +1000a47e : +1000a47e: 8980 ldrh r0, [r0, #12] +1000a480: f002 b866 b.w 1000c550 + +1000a484 : +1000a484: b538 push {r3, r4, r5, lr} +1000a486: 4604 mov r4, r0 +1000a488: 460d mov r5, r1 +1000a48a: f000 fed1 bl 1000b230 +1000a48e: 6820 ldr r0, [r4, #0] +1000a490: 6be1 ldr r1, [r4, #60] ; 0x3c +1000a492: 6c22 ldr r2, [r4, #64] ; 0x40 +1000a494: fb02 0001 mla r0, r2, r1, r0 +1000a498: 6060 str r0, [r4, #4] +1000a49a: 2000 movs r0, #0 +1000a49c: 63a0 str r0, [r4, #56] ; 0x38 +1000a49e: 6820 ldr r0, [r4, #0] +1000a4a0: 60a0 str r0, [r4, #8] +1000a4a2: 6be1 ldr r1, [r4, #60] ; 0x3c +1000a4a4: 6820 ldr r0, [r4, #0] +1000a4a6: 6c22 ldr r2, [r4, #64] ; 0x40 +1000a4a8: 1e49 subs r1, r1, #1 +1000a4aa: fb02 0001 mla r0, r2, r1, r0 +1000a4ae: 60e0 str r0, [r4, #12] +1000a4b0: f04f 30ff mov.w r0, #4294967295 +1000a4b4: 6460 str r0, [r4, #68] ; 0x44 +1000a4b6: 64a0 str r0, [r4, #72] ; 0x48 +1000a4b8: b945 cbnz r5, 1000a4cc +1000a4ba: 6920 ldr r0, [r4, #16] +1000a4bc: b170 cbz r0, 1000a4dc +1000a4be: f000 f978 bl 1000a7b2 + +1000a4c2 : +1000a4c2: 2801 cmp r0, #1 +1000a4c4: d10a bne.n 1000a4dc +1000a4c6: f000 feaa bl 1000b21e +1000a4ca: e007 b.n 1000a4dc + +1000a4cc : +1000a4cc: f104 0010 add.w r0, r4, #16 +1000a4d0: f002 f9a8 bl 1000c824 +1000a4d4: f104 0024 add.w r0, r4, #36 ; 0x24 +1000a4d8: f002 f9a4 bl 1000c824 + +1000a4dc : +1000a4dc: f000 feb4 bl 1000b248 +1000a4e0: 2001 movs r0, #1 +1000a4e2: bd32 pop {r1, r4, r5, pc} + +1000a4e4 : +1000a4e4: b5f8 push {r3, r4, r5, r6, r7, lr} +1000a4e6: 4604 mov r4, r0 +1000a4e8: 460d mov r5, r1 +1000a4ea: 2600 movs r6, #0 +1000a4ec: b1b4 cbz r4, 1000a51c +1000a4ee: 204c movs r0, #76 ; 0x4c +1000a4f0: f002 f9e0 bl 1000c8b4 +1000a4f4: 0007 movs r7, r0 +1000a4f6: d011 beq.n 1000a51c +1000a4f8: fb05 f004 mul.w r0, r5, r4 +1000a4fc: 1c40 adds r0, r0, #1 +1000a4fe: f002 f9d9 bl 1000c8b4 +1000a502: 6038 str r0, [r7, #0] +1000a504: b138 cbz r0, 1000a516 +1000a506: 63fc str r4, [r7, #60] ; 0x3c +1000a508: 643d str r5, [r7, #64] ; 0x40 +1000a50a: 2101 movs r1, #1 +1000a50c: 4638 mov r0, r7 +1000a50e: f7ff ffb9 bl 1000a484 +1000a512: 463e mov r6, r7 +1000a514: e002 b.n 1000a51c + +1000a516 : +1000a516: 4638 mov r0, r7 +1000a518: f002 fa53 bl 1000c9c2 + +1000a51c : +1000a51c: 4630 mov r0, r6 +1000a51e: bdf2 pop {r1, r4, r5, r6, r7, pc} + +1000a520 : +1000a520: b510 push {r4, lr} +1000a522: 204c movs r0, #76 ; 0x4c +1000a524: f002 f9c6 bl 1000c8b4 +1000a528: 0004 movs r4, r0 +1000a52a: d017 beq.n 1000a55c +1000a52c: 2000 movs r0, #0 +1000a52e: 6060 str r0, [r4, #4] +1000a530: 6020 str r0, [r4, #0] +1000a532: 60a0 str r0, [r4, #8] +1000a534: 60e0 str r0, [r4, #12] +1000a536: 63a0 str r0, [r4, #56] ; 0x38 +1000a538: 2001 movs r0, #1 +1000a53a: 63e0 str r0, [r4, #60] ; 0x3c +1000a53c: 2000 movs r0, #0 +1000a53e: 6420 str r0, [r4, #64] ; 0x40 +1000a540: f04f 30ff mov.w r0, #4294967295 +1000a544: 6460 str r0, [r4, #68] ; 0x44 +1000a546: 64a0 str r0, [r4, #72] ; 0x48 +1000a548: f104 0010 add.w r0, r4, #16 +1000a54c: f002 f96a bl 1000c824 +1000a550: f104 0024 add.w r0, r4, #36 ; 0x24 +1000a554: f002 f966 bl 1000c824 +1000a558: f000 f802 bl 1000a560 + +1000a55c : +1000a55c: 4620 mov r0, r4 +1000a55e: bd10 pop {r4, pc} + +1000a560 : +1000a560: 2200 movs r2, #0 +1000a562: 2300 movs r3, #0 +1000a564: 4611 mov r1, r2 +1000a566: 4620 mov r0, r4 +1000a568: e008 b.n 1000a57c + +1000a56a : +1000a56a: b510 push {r4, lr} +1000a56c: 460c mov r4, r1 +1000a56e: 2202 movs r2, #2 +1000a570: 2100 movs r1, #0 +1000a572: f7ff ffb7 bl 1000a4e4 +1000a576: b100 cbz r0, 1000a57a +1000a578: 6384 str r4, [r0, #56] ; 0x38 + +1000a57a : +1000a57a: bd10 pop {r4, pc} + +1000a57c : +1000a57c: b5f7 push {r0, r1, r2, r4, r5, r6, r7, lr} +1000a57e: 4604 mov r4, r0 +1000a580: 460d mov r5, r1 +1000a582: 461e mov r6, r3 +1000a584: 2700 movs r7, #0 +1000a586: e003 b.n 1000a590 + +1000a588 : +1000a588: f000 f90d bl 1000a7a6 + +1000a58c : +1000a58c: f000 fb6f bl 1000ac6e + +1000a590 : +1000a590: f000 fe4e bl 1000b230 +1000a594: 6ba0 ldr r0, [r4, #56] ; 0x38 +1000a596: 6be1 ldr r1, [r4, #60] ; 0x3c +1000a598: 4288 cmp r0, r1 +1000a59a: d301 bcc.n 1000a5a0 +1000a59c: 2e02 cmp r6, #2 +1000a59e: d112 bne.n 1000a5c6 + +1000a5a0 : +1000a5a0: 4632 mov r2, r6 +1000a5a2: 4629 mov r1, r5 +1000a5a4: 4620 mov r0, r4 +1000a5a6: f000 f91c bl 1000a7e2 +1000a5aa: 6a61 ldr r1, [r4, #36] ; 0x24 +1000a5ac: b121 cbz r1, 1000a5b8 +1000a5ae: f000 f8fc bl 1000a7aa + +1000a5b2 : +1000a5b2: 2801 cmp r0, #1 +1000a5b4: d103 bne.n 1000a5be +1000a5b6: e000 b.n 1000a5ba + +1000a5b8 : +1000a5b8: b108 cbz r0, 1000a5be + +1000a5ba : +1000a5ba: f000 fe30 bl 1000b21e + +1000a5be : +1000a5be: f000 fe43 bl 1000b248 +1000a5c2: 2001 movs r0, #1 +1000a5c4: bdfe pop {r1, r2, r3, r4, r5, r6, r7, pc} + +1000a5c6 : +1000a5c6: 9802 ldr r0, [sp, #8] +1000a5c8: b910 cbnz r0, 1000a5d0 +1000a5ca: f000 fe3d bl 1000b248 +1000a5ce: e035 b.n 1000a63c + +1000a5d0 : +1000a5d0: b91f cbnz r7, 1000a5da +1000a5d2: a800 add r0, sp, #0 +1000a5d4: f000 fca8 bl 1000af28 +1000a5d8: 2701 movs r7, #1 + +1000a5da : +1000a5da: f000 fe35 bl 1000b248 +1000a5de: f000 fb30 bl 1000ac42 +1000a5e2: f000 fe25 bl 1000b230 +1000a5e6: 6c60 ldr r0, [r4, #68] ; 0x44 +1000a5e8: f110 0f01 cmn.w r0, #1 +1000a5ec: bf04 itt eq +1000a5ee: 2000 moveq r0, #0 +1000a5f0: 6460 streq r0, [r4, #68] ; 0x44 +1000a5f2: 6ca0 ldr r0, [r4, #72] ; 0x48 +1000a5f4: f110 0f01 cmn.w r0, #1 +1000a5f8: bf04 itt eq +1000a5fa: 2000 moveq r0, #0 +1000a5fc: 64a0 streq r0, [r4, #72] ; 0x48 +1000a5fe: f000 fe23 bl 1000b248 +1000a602: a902 add r1, sp, #8 +1000a604: a800 add r0, sp, #0 +1000a606: f000 fc95 bl 1000af34 +1000a60a: 2800 cmp r0, #0 +1000a60c: 4620 mov r0, r4 +1000a60e: d111 bne.n 1000a634 +1000a610: f000 f961 bl 1000a8d6 +1000a614: 2800 cmp r0, #0 +1000a616: d0b7 beq.n 1000a588 +1000a618: 9902 ldr r1, [sp, #8] +1000a61a: f104 0010 add.w r0, r4, #16 +1000a61e: f000 fc13 bl 1000ae48 +1000a622: f000 f8c0 bl 1000a7a6 + +1000a626 : +1000a626: f000 fb22 bl 1000ac6e +1000a62a: 2800 cmp r0, #0 +1000a62c: d1b0 bne.n 1000a590 +1000a62e: f000 fdf6 bl 1000b21e +1000a632: e7ad b.n 1000a590 + +1000a634 : +1000a634: f000 f91f bl 1000a876 +1000a638: f000 fb19 bl 1000ac6e + +1000a63c : +1000a63c: 2000 movs r0, #0 +1000a63e: bdfe pop {r1, r2, r3, r4, r5, r6, r7, pc} + +1000a640 : +1000a640: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1000a644: 4605 mov r5, r0 +1000a646: 4688 mov r8, r1 +1000a648: 4616 mov r6, r2 +1000a64a: 461f mov r7, r3 +1000a64c: f039 facd bl 10043bea +1000a650: 4604 mov r4, r0 +1000a652: 6ba8 ldr r0, [r5, #56] ; 0x38 +1000a654: 6be9 ldr r1, [r5, #60] ; 0x3c +1000a656: 4288 cmp r0, r1 +1000a658: d301 bcc.n 1000a65e +1000a65a: 2f02 cmp r7, #2 +1000a65c: d11f bne.n 1000a69e + +1000a65e : +1000a65e: 463a mov r2, r7 +1000a660: 4641 mov r1, r8 +1000a662: 4628 mov r0, r5 +1000a664: f000 f8bd bl 1000a7e2 +1000a668: 2800 cmp r0, #0 +1000a66a: bf1e ittt ne +1000a66c: 2e00 cmpne r6, #0 +1000a66e: 2001 movne r0, #1 +1000a670: 6030 strne r0, [r6, #0] +1000a672: 6ca8 ldr r0, [r5, #72] ; 0x48 +1000a674: f110 0f01 cmn.w r0, #1 +1000a678: d10c bne.n 1000a694 +1000a67a: 6a68 ldr r0, [r5, #36] ; 0x24 +1000a67c: b168 cbz r0, 1000a69a +1000a67e: f105 0024 add.w r0, r5, #36 ; 0x24 +1000a682: f000 fc22 bl 1000aeca +1000a686: 2800 cmp r0, #0 +1000a688: bf18 it ne +1000a68a: 2e00 cmpne r6, #0 +1000a68c: d005 beq.n 1000a69a +1000a68e: 2001 movs r0, #1 +1000a690: 6030 str r0, [r6, #0] +1000a692: e002 b.n 1000a69a + +1000a694 : +1000a694: 6ca8 ldr r0, [r5, #72] ; 0x48 +1000a696: 1c40 adds r0, r0, #1 +1000a698: 64a8 str r0, [r5, #72] ; 0x48 + +1000a69a : +1000a69a: 2501 movs r5, #1 +1000a69c: e000 b.n 1000a6a0 + +1000a69e : +1000a69e: 2500 movs r5, #0 + +1000a6a0 : +1000a6a0: 4620 mov r0, r4 +1000a6a2: f039 faa9 bl 10043bf8 +1000a6a6: 4628 mov r0, r5 +1000a6a8: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +1000a6ac : +1000a6ac: e92d 41f4 stmdb sp!, {r2, r4, r5, r6, r7, r8, lr} +1000a6b0: b083 sub sp, #12 +1000a6b2: 4604 mov r4, r0 +1000a6b4: 4688 mov r8, r1 +1000a6b6: 461e mov r6, r3 +1000a6b8: 2700 movs r7, #0 +1000a6ba: e003 b.n 1000a6c4 + +1000a6bc : +1000a6bc: f000 f873 bl 1000a7a6 + +1000a6c0 : +1000a6c0: f000 fad5 bl 1000ac6e + +1000a6c4 : +1000a6c4: f000 fdb4 bl 1000b230 +1000a6c8: 6ba0 ldr r0, [r4, #56] ; 0x38 +1000a6ca: b300 cbz r0, 1000a70e +1000a6cc: 68e7 ldr r7, [r4, #12] +1000a6ce: 4641 mov r1, r8 +1000a6d0: 4620 mov r0, r4 +1000a6d2: f000 f8bd bl 1000a850 +1000a6d6: b976 cbnz r6, 1000a6f6 +1000a6d8: 6ba0 ldr r0, [r4, #56] ; 0x38 +1000a6da: 1e40 subs r0, r0, #1 +1000a6dc: 63a0 str r0, [r4, #56] ; 0x38 +1000a6de: 6820 ldr r0, [r4, #0] +1000a6e0: b910 cbnz r0, 1000a6e8 +1000a6e2: f000 fd5c bl 1000b19e +1000a6e6: 6060 str r0, [r4, #4] + +1000a6e8 : +1000a6e8: 6920 ldr r0, [r4, #16] +1000a6ea: b160 cbz r0, 1000a706 +1000a6ec: f000 f861 bl 1000a7b2 + +1000a6f0 : +1000a6f0: 2801 cmp r0, #1 +1000a6f2: d108 bne.n 1000a706 +1000a6f4: e005 b.n 1000a702 + +1000a6f6 : +1000a6f6: 60e7 str r7, [r4, #12] +1000a6f8: 6a60 ldr r0, [r4, #36] ; 0x24 +1000a6fa: b120 cbz r0, 1000a706 +1000a6fc: f000 f855 bl 1000a7aa + +1000a700 : +1000a700: b108 cbz r0, 1000a706 + +1000a702 : +1000a702: f000 fd8c bl 1000b21e + +1000a706 : +1000a706: f000 fd9f bl 1000b248 +1000a70a: 2001 movs r0, #1 +1000a70c: e048 b.n 1000a7a0 + +1000a70e : +1000a70e: 9803 ldr r0, [sp, #12] +1000a710: b910 cbnz r0, 1000a718 +1000a712: f000 fd99 bl 1000b248 +1000a716: e042 b.n 1000a79e + +1000a718 : +1000a718: b91f cbnz r7, 1000a722 +1000a71a: a800 add r0, sp, #0 +1000a71c: f000 fc04 bl 1000af28 +1000a720: 2701 movs r7, #1 + +1000a722 : +1000a722: f000 fd91 bl 1000b248 +1000a726: f000 fa8c bl 1000ac42 +1000a72a: f000 fd81 bl 1000b230 +1000a72e: 6c60 ldr r0, [r4, #68] ; 0x44 +1000a730: f110 0f01 cmn.w r0, #1 +1000a734: bf04 itt eq +1000a736: 2000 moveq r0, #0 +1000a738: 6460 streq r0, [r4, #68] ; 0x44 +1000a73a: 6ca0 ldr r0, [r4, #72] ; 0x48 +1000a73c: f110 0f01 cmn.w r0, #1 +1000a740: bf04 itt eq +1000a742: 2000 moveq r0, #0 +1000a744: 64a0 streq r0, [r4, #72] ; 0x48 +1000a746: f000 fd7f bl 1000b248 +1000a74a: a903 add r1, sp, #12 +1000a74c: a800 add r0, sp, #0 +1000a74e: f000 fbf1 bl 1000af34 +1000a752: bb00 cbnz r0, 1000a796 +1000a754: f000 fd6c bl 1000b230 +1000a758: 6ba0 ldr r0, [r4, #56] ; 0x38 +1000a75a: 1e45 subs r5, r0, #1 +1000a75c: 41ad sbcs r5, r5 +1000a75e: 0fed lsrs r5, r5, #31 +1000a760: f000 fd72 bl 1000b248 +1000a764: 2d00 cmp r5, #0 +1000a766: d0a9 beq.n 1000a6bc +1000a768: 6820 ldr r0, [r4, #0] +1000a76a: b930 cbnz r0, 1000a77a +1000a76c: f000 fd60 bl 1000b230 +1000a770: 6860 ldr r0, [r4, #4] +1000a772: f000 fc9f bl 1000b0b4 +1000a776: f000 fd67 bl 1000b248 + +1000a77a : +1000a77a: 9903 ldr r1, [sp, #12] +1000a77c: f104 0024 add.w r0, r4, #36 ; 0x24 +1000a780: f000 fb62 bl 1000ae48 +1000a784: f000 f80f bl 1000a7a6 + +1000a788 : +1000a788: f000 fa71 bl 1000ac6e +1000a78c: 2800 cmp r0, #0 +1000a78e: d199 bne.n 1000a6c4 +1000a790: f000 fd45 bl 1000b21e +1000a794: e796 b.n 1000a6c4 + +1000a796 : +1000a796: f000 f806 bl 1000a7a6 + +1000a79a : +1000a79a: f000 fa68 bl 1000ac6e + +1000a79e : +1000a79e: 2000 movs r0, #0 + +1000a7a0 : +1000a7a0: b004 add sp, #16 +1000a7a2: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +1000a7a6 : +1000a7a6: 4620 mov r0, r4 +1000a7a8: e065 b.n 1000a876 + +1000a7aa : +1000a7aa: f104 0024 add.w r0, r4, #36 ; 0x24 +1000a7ae: f000 bb8c b.w 1000aeca + +1000a7b2 : +1000a7b2: f104 0010 add.w r0, r4, #16 +1000a7b6: f000 bb88 b.w 1000aeca + +1000a7ba : +1000a7ba: b510 push {r4, lr} +1000a7bc: f000 f888 bl 1000a8d0 + +1000a7c0 : +1000a7c0: 6ba4 ldr r4, [r4, #56] ; 0x38 +1000a7c2: e7ff b.n 1000a7c4 + +1000a7c4 : +1000a7c4: f000 fd40 bl 1000b248 +1000a7c8: 4620 mov r0, r4 +1000a7ca: bd10 pop {r4, pc} + +1000a7cc : +1000a7cc: b510 push {r4, lr} +1000a7ce: 4604 mov r4, r0 +1000a7d0: 6820 ldr r0, [r4, #0] +1000a7d2: b108 cbz r0, 1000a7d8 +1000a7d4: f002 f8f5 bl 1000c9c2 + +1000a7d8 : +1000a7d8: 4620 mov r0, r4 +1000a7da: e8bd 4010 ldmia.w sp!, {r4, lr} +1000a7de: f002 b8f0 b.w 1000c9c2 + +1000a7e2 : +1000a7e2: b570 push {r4, r5, r6, lr} +1000a7e4: 4604 mov r4, r0 +1000a7e6: 4616 mov r6, r2 +1000a7e8: 6c22 ldr r2, [r4, #64] ; 0x40 +1000a7ea: 2500 movs r5, #0 +1000a7ec: b942 cbnz r2, 1000a800 +1000a7ee: 6820 ldr r0, [r4, #0] +1000a7f0: bb48 cbnz r0, 1000a846 +1000a7f2: 6860 ldr r0, [r4, #4] +1000a7f4: f000 fc9e bl 1000b134 +1000a7f8: 4605 mov r5, r0 +1000a7fa: 2000 movs r0, #0 +1000a7fc: 6060 str r0, [r4, #4] +1000a7fe: e022 b.n 1000a846 + +1000a800 : +1000a800: b966 cbnz r6, 1000a81c +1000a802: 68a0 ldr r0, [r4, #8] +1000a804: f001 fda0 bl 1000c348 +1000a808: 68a0 ldr r0, [r4, #8] +1000a80a: 6c21 ldr r1, [r4, #64] ; 0x40 +1000a80c: 1808 adds r0, r1, r0 +1000a80e: 60a0 str r0, [r4, #8] +1000a810: 6861 ldr r1, [r4, #4] +1000a812: 4288 cmp r0, r1 +1000a814: d317 bcc.n 1000a846 +1000a816: 6820 ldr r0, [r4, #0] +1000a818: 60a0 str r0, [r4, #8] +1000a81a: e014 b.n 1000a846 + +1000a81c : +1000a81c: 68e0 ldr r0, [r4, #12] +1000a81e: f001 fd93 bl 1000c348 +1000a822: 6c20 ldr r0, [r4, #64] ; 0x40 +1000a824: 68e1 ldr r1, [r4, #12] +1000a826: 4240 negs r0, r0 +1000a828: 1841 adds r1, r0, r1 +1000a82a: 60e1 str r1, [r4, #12] +1000a82c: 6822 ldr r2, [r4, #0] +1000a82e: 4291 cmp r1, r2 +1000a830: d202 bcs.n 1000a838 +1000a832: 6861 ldr r1, [r4, #4] +1000a834: 1840 adds r0, r0, r1 +1000a836: 60e0 str r0, [r4, #12] + +1000a838 : +1000a838: 2e02 cmp r6, #2 +1000a83a: d104 bne.n 1000a846 +1000a83c: 6ba0 ldr r0, [r4, #56] ; 0x38 +1000a83e: b110 cbz r0, 1000a846 +1000a840: 6ba0 ldr r0, [r4, #56] ; 0x38 +1000a842: 1e40 subs r0, r0, #1 +1000a844: 63a0 str r0, [r4, #56] ; 0x38 + +1000a846 : +1000a846: 6ba0 ldr r0, [r4, #56] ; 0x38 +1000a848: 1c40 adds r0, r0, #1 +1000a84a: 63a0 str r0, [r4, #56] ; 0x38 +1000a84c: 4628 mov r0, r5 +1000a84e: bd70 pop {r4, r5, r6, pc} + +1000a850 : +1000a850: b510 push {r4, lr} +1000a852: 6c02 ldr r2, [r0, #64] ; 0x40 +1000a854: 460b mov r3, r1 +1000a856: b16a cbz r2, 1000a874 +1000a858: 68c1 ldr r1, [r0, #12] +1000a85a: 1851 adds r1, r2, r1 +1000a85c: 60c1 str r1, [r0, #12] +1000a85e: 6844 ldr r4, [r0, #4] +1000a860: 42a1 cmp r1, r4 +1000a862: bf24 itt cs +1000a864: 6801 ldrcs r1, [r0, #0] +1000a866: 60c1 strcs r1, [r0, #12] +1000a868: 68c1 ldr r1, [r0, #12] +1000a86a: e8bd 4010 ldmia.w sp!, {r4, lr} +1000a86e: 4618 mov r0, r3 +1000a870: f001 bd6a b.w 1000c348 + +1000a874 : +1000a874: bd10 pop {r4, pc} + +1000a876 : +1000a876: b538 push {r3, r4, r5, lr} +1000a878: f000 f82a bl 1000a8d0 + +1000a87c : +1000a87c: e007 b.n 1000a88e + +1000a87e : +1000a87e: f7ff ff94 bl 1000a7aa + +1000a882 : +1000a882: b108 cbz r0, 1000a888 +1000a884: f000 fb78 bl 1000af78 + +1000a888 : +1000a888: 6ca0 ldr r0, [r4, #72] ; 0x48 +1000a88a: 1e40 subs r0, r0, #1 +1000a88c: 64a0 str r0, [r4, #72] ; 0x48 + +1000a88e : +1000a88e: 6ca0 ldr r0, [r4, #72] ; 0x48 +1000a890: 2801 cmp r0, #1 +1000a892: db02 blt.n 1000a89a +1000a894: 6a60 ldr r0, [r4, #36] ; 0x24 +1000a896: 2800 cmp r0, #0 +1000a898: d1f1 bne.n 1000a87e + +1000a89a : +1000a89a: f04f 35ff mov.w r5, #4294967295 +1000a89e: 64a5 str r5, [r4, #72] ; 0x48 +1000a8a0: f000 fcd2 bl 1000b248 +1000a8a4: f000 fcc4 bl 1000b230 +1000a8a8: e007 b.n 1000a8ba + +1000a8aa : +1000a8aa: f7ff ff82 bl 1000a7b2 + +1000a8ae : +1000a8ae: b108 cbz r0, 1000a8b4 +1000a8b0: f000 fb62 bl 1000af78 + +1000a8b4 : +1000a8b4: 6c60 ldr r0, [r4, #68] ; 0x44 +1000a8b6: 1e40 subs r0, r0, #1 +1000a8b8: 6460 str r0, [r4, #68] ; 0x44 + +1000a8ba : +1000a8ba: 6c60 ldr r0, [r4, #68] ; 0x44 +1000a8bc: 2801 cmp r0, #1 +1000a8be: db02 blt.n 1000a8c6 +1000a8c0: 6920 ldr r0, [r4, #16] +1000a8c2: 2800 cmp r0, #0 +1000a8c4: d1f1 bne.n 1000a8aa + +1000a8c6 : +1000a8c6: 6465 str r5, [r4, #68] ; 0x44 +1000a8c8: e8bd 4031 ldmia.w sp!, {r0, r4, r5, lr} +1000a8cc: f000 bcbc b.w 1000b248 + +1000a8d0 : +1000a8d0: 4604 mov r4, r0 +1000a8d2: f000 bcad b.w 1000b230 + +1000a8d6 : +1000a8d6: b510 push {r4, lr} +1000a8d8: f7ff fffa bl 1000a8d0 + +1000a8dc : +1000a8dc: 6ba0 ldr r0, [r4, #56] ; 0x38 +1000a8de: 6be1 ldr r1, [r4, #60] ; 0x3c +1000a8e0: 4288 cmp r0, r1 +1000a8e2: bf0c ite eq +1000a8e4: 2401 moveq r4, #1 +1000a8e6: 2400 movne r4, #0 +1000a8e8: e76c b.n 1000a7c4 + +1000a8ea : +1000a8ea: b538 push {r3, r4, r5, lr} +1000a8ec: 4604 mov r4, r0 +1000a8ee: 460d mov r5, r1 +1000a8f0: f000 fc9e bl 1000b230 +1000a8f4: 6c60 ldr r0, [r4, #68] ; 0x44 +1000a8f6: f110 0f01 cmn.w r0, #1 +1000a8fa: bf04 itt eq +1000a8fc: 2000 moveq r0, #0 +1000a8fe: 6460 streq r0, [r4, #68] ; 0x44 +1000a900: 6ca0 ldr r0, [r4, #72] ; 0x48 +1000a902: f110 0f01 cmn.w r0, #1 +1000a906: bf04 itt eq +1000a908: 2000 moveq r0, #0 +1000a90a: 64a0 streq r0, [r4, #72] ; 0x48 +1000a90c: f000 fc9c bl 1000b248 +1000a910: 6ba0 ldr r0, [r4, #56] ; 0x38 +1000a912: b920 cbnz r0, 1000a91e +1000a914: 4629 mov r1, r5 +1000a916: f104 0024 add.w r0, r4, #36 ; 0x24 +1000a91a: f000 fabf bl 1000ae9c + +1000a91e : +1000a91e: 4620 mov r0, r4 +1000a920: e8bd 4032 ldmia.w sp!, {r1, r4, r5, lr} +1000a924: e7a7 b.n 1000a876 + ... + +1000a928 : +1000a928: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +1000a92c: 4606 mov r6, r0 +1000a92e: b082 sub sp, #8 +1000a930: 4689 mov r9, r1 +1000a932: 4615 mov r5, r2 +1000a934: 461f mov r7, r3 +1000a936: 2048 movs r0, #72 ; 0x48 +1000a938: f001 ffbc bl 1000c8b4 +1000a93c: 0004 movs r4, r0 +1000a93e: d009 beq.n 1000a954 +1000a940: 980c ldr r0, [sp, #48] ; 0x30 +1000a942: b910 cbnz r0, 1000a94a +1000a944: 00a8 lsls r0, r5, #2 +1000a946: f001 ffb5 bl 1000c8b4 + +1000a94a : +1000a94a: 6320 str r0, [r4, #48] ; 0x30 +1000a94c: b928 cbnz r0, 1000a95a +1000a94e: 4620 mov r0, r4 +1000a950: f002 f837 bl 1000c9c2 + +1000a954 : +1000a954: f04f 34ff mov.w r4, #4294967295 +1000a958: e06f b.n 1000aa3a + +1000a95a : +1000a95a: 00aa lsls r2, r5, #2 +1000a95c: 21a5 movs r1, #165 ; 0xa5 +1000a95e: f001 fcf5 bl 1000c34c +1000a962: 6b20 ldr r0, [r4, #48] ; 0x30 +1000a964: f8dd 8028 ldr.w r8, [sp, #40] ; 0x28 +1000a968: 9500 str r5, [sp, #0] +1000a96a: eb00 0085 add.w r0, r0, r5, lsl #2 +1000a96e: f1a0 0a04 sub.w sl, r0, #4 +1000a972: 9b0d ldr r3, [sp, #52] ; 0x34 +1000a974: 4642 mov r2, r8 +1000a976: 4649 mov r1, r9 +1000a978: 4620 mov r0, r4 +1000a97a: f000 fb46 bl 1000b00a +1000a97e: ea4f 00da mov.w r0, sl, lsr #3 +1000a982: 463a mov r2, r7 +1000a984: 4631 mov r1, r6 +1000a986: 00c0 lsls r0, r0, #3 +1000a988: f000 fc24 bl 1000b1d4 +1000a98c: 6020 str r0, [r4, #0] +1000a98e: 980b ldr r0, [sp, #44] ; 0x2c +1000a990: b100 cbz r0, 1000a994 +1000a992: 6004 str r4, [r0, #0] + +1000a994 : +1000a994: f000 fc4c bl 1000b230 +1000a998: f8df 6814 ldr.w r6, [pc, #2068] ; 1000b1b0 +1000a99c: f8df 5814 ldr.w r5, [pc, #2068] ; 1000b1b4 +1000a9a0: 6cf0 ldr r0, [r6, #76] ; 0x4c +1000a9a2: 1c40 adds r0, r0, #1 +1000a9a4: 64f0 str r0, [r6, #76] ; 0x4c +1000a9a6: f04f 0914 mov.w r9, #20 +1000a9aa: 6ab0 ldr r0, [r6, #40] ; 0x28 +1000a9ac: bb20 cbnz r0, 1000a9f8 +1000a9ae: 62b4 str r4, [r6, #40] ; 0x28 +1000a9b0: 6cf0 ldr r0, [r6, #76] ; 0x4c +1000a9b2: 2801 cmp r0, #1 +1000a9b4: d127 bne.n 1000aa06 +1000a9b6: 2700 movs r7, #0 + +1000a9b8 : +1000a9b8: fb09 5007 mla r0, r9, r7, r5 +1000a9bc: f001 ff32 bl 1000c824 +1000a9c0: 1c7f adds r7, r7, #1 +1000a9c2: 2f0b cmp r7, #11 +1000a9c4: d3f8 bcc.n 1000a9b8 +1000a9c6: f106 0074 add.w r0, r6, #116 ; 0x74 +1000a9ca: f001 ff2b bl 1000c824 +1000a9ce: f106 0788 add.w r7, r6, #136 ; 0x88 +1000a9d2: 4638 mov r0, r7 +1000a9d4: f001 ff26 bl 1000c824 +1000a9d8: 4630 mov r0, r6 +1000a9da: f001 ff23 bl 1000c824 +1000a9de: f106 0014 add.w r0, r6, #20 +1000a9e2: f001 ff1f bl 1000c824 +1000a9e6: f106 0038 add.w r0, r6, #56 ; 0x38 +1000a9ea: f001 ff1b bl 1000c824 +1000a9ee: f106 0074 add.w r0, r6, #116 ; 0x74 +1000a9f2: 62f0 str r0, [r6, #44] ; 0x2c +1000a9f4: 6337 str r7, [r6, #48] ; 0x30 +1000a9f6: e006 b.n 1000aa06 + +1000a9f8 : +1000a9f8: 6db0 ldr r0, [r6, #88] ; 0x58 +1000a9fa: b920 cbnz r0, 1000aa06 +1000a9fc: 6ab0 ldr r0, [r6, #40] ; 0x28 +1000a9fe: 6ac0 ldr r0, [r0, #44] ; 0x2c +1000aa00: 4580 cmp r8, r0 +1000aa02: bf28 it cs +1000aa04: 62b4 strcs r4, [r6, #40] ; 0x28 + +1000aa06 : +1000aa06: 6eb0 ldr r0, [r6, #104] ; 0x68 +1000aa08: 1c40 adds r0, r0, #1 +1000aa0a: 66b0 str r0, [r6, #104] ; 0x68 +1000aa0c: 2101 movs r1, #1 +1000aa0e: 6d70 ldr r0, [r6, #84] ; 0x54 +1000aa10: 6ae2 ldr r2, [r4, #44] ; 0x2c +1000aa12: 4091 lsls r1, r2 +1000aa14: 4308 orrs r0, r1 +1000aa16: 6570 str r0, [r6, #84] ; 0x54 +1000aa18: 1d21 adds r1, r4, #4 +1000aa1a: 6ae0 ldr r0, [r4, #44] ; 0x2c +1000aa1c: fb09 5000 mla r0, r9, r0, r5 +1000aa20: f001 ff10 bl 1000c844 +1000aa24: 2401 movs r4, #1 +1000aa26: f000 fc0f bl 1000b248 +1000aa2a: 6db0 ldr r0, [r6, #88] ; 0x58 +1000aa2c: b128 cbz r0, 1000aa3a +1000aa2e: 6ab0 ldr r0, [r6, #40] ; 0x28 +1000aa30: 6ac0 ldr r0, [r0, #44] ; 0x2c +1000aa32: 4540 cmp r0, r8 +1000aa34: bf38 it cc +1000aa36: f000 fbf2 blcc 1000b21e + +1000aa3a : +1000aa3a: 4620 mov r0, r4 +1000aa3c: e8bd 87f6 ldmia.w sp!, {r1, r2, r4, r5, r6, r7, r8, r9, sl, pc} + +1000aa40 : +1000aa40: b538 push {r3, r4, r5, lr} +1000aa42: 4605 mov r5, r0 +1000aa44: f000 fbf4 bl 1000b230 +1000aa48: f000 f8b6 bl 1000abb8 + +1000aa4c : +1000aa4c: f000 f8bb bl 1000abc6 + +1000aa50 : +1000aa50: b118 cbz r0, 1000aa5a +1000aa52: f105 0018 add.w r0, r5, #24 +1000aa56: f001 ff1a bl 1000c88e + +1000aa5a : +1000aa5a: 1d29 adds r1, r5, #4 +1000aa5c: f104 0014 add.w r0, r4, #20 +1000aa60: f001 fef0 bl 1000c844 +1000aa64: 6b60 ldr r0, [r4, #52] ; 0x34 +1000aa66: 1c40 adds r0, r0, #1 +1000aa68: 6360 str r0, [r4, #52] ; 0x34 +1000aa6a: 6ea0 ldr r0, [r4, #104] ; 0x68 +1000aa6c: 1c40 adds r0, r0, #1 +1000aa6e: 66a0 str r0, [r4, #104] ; 0x68 +1000aa70: f000 fbea bl 1000b248 +1000aa74: 6da0 ldr r0, [r4, #88] ; 0x58 +1000aa76: b138 cbz r0, 1000aa88 +1000aa78: 6aa0 ldr r0, [r4, #40] ; 0x28 +1000aa7a: 4285 cmp r5, r0 +1000aa7c: bf04 itt eq +1000aa7e: e8bd 4031 ldmiaeq.w sp!, {r0, r4, r5, lr} +1000aa82: f000 bbcc beq.w 1000b21e +1000aa86: e0b0 b.n 1000abea + +1000aa88 : +1000aa88: bd31 pop {r0, r4, r5, pc} + +1000aa8a : +1000aa8a: b570 push {r4, r5, r6, lr} +1000aa8c: 4606 mov r6, r0 +1000aa8e: 460d mov r5, r1 +1000aa90: f000 f8d7 bl 1000ac42 +1000aa94: f8df 4718 ldr.w r4, [pc, #1816] ; 1000b1b0 +1000aa98: 6d20 ldr r0, [r4, #80] ; 0x50 +1000aa9a: 6831 ldr r1, [r6, #0] +1000aa9c: 186d adds r5, r5, r1 +1000aa9e: 4288 cmp r0, r1 +1000aaa0: d203 bcs.n 1000aaaa +1000aaa2: 428d cmp r5, r1 +1000aaa4: d303 bcc.n 1000aaae + +1000aaa6 : +1000aaa6: 6035 str r5, [r6, #0] +1000aaa8: e00a b.n 1000aac0 + +1000aaaa : +1000aaaa: 428d cmp r5, r1 +1000aaac: d301 bcc.n 1000aab2 + +1000aaae : +1000aaae: 42a8 cmp r0, r5 +1000aab0: d2f9 bcs.n 1000aaa6 + +1000aab2 : +1000aab2: 6035 str r5, [r6, #0] +1000aab4: 6aa0 ldr r0, [r4, #40] ; 0x28 +1000aab6: 1d00 adds r0, r0, #4 +1000aab8: f001 fee9 bl 1000c88e +1000aabc: f000 f820 bl 1000ab00 + +1000aac0 : +1000aac0: f000 f8d5 bl 1000ac6e +1000aac4: 2800 cmp r0, #0 +1000aac6: bf04 itt eq +1000aac8: e8bd 4070 ldmiaeq.w sp!, {r4, r5, r6, lr} +1000aacc: f000 bba7 beq.w 1000b21e +1000aad0: bd70 pop {r4, r5, r6, pc} + +1000aad2 : +1000aad2: b538 push {r3, r4, r5, lr} +1000aad4: 0005 movs r5, r0 +1000aad6: d00e beq.n 1000aaf6 +1000aad8: f000 f8b3 bl 1000ac42 +1000aadc: f8df 46d0 ldr.w r4, [pc, #1744] ; 1000b1b0 +1000aae0: 6d20 ldr r0, [r4, #80] ; 0x50 +1000aae2: 182d adds r5, r5, r0 +1000aae4: 6aa0 ldr r0, [r4, #40] ; 0x28 +1000aae6: 1d00 adds r0, r0, #4 +1000aae8: f001 fed1 bl 1000c88e +1000aaec: f000 f808 bl 1000ab00 + +1000aaf0 : +1000aaf0: f000 f8bd bl 1000ac6e +1000aaf4: b918 cbnz r0, 1000aafe + +1000aaf6 : +1000aaf6: e8bd 4031 ldmia.w sp!, {r0, r4, r5, lr} +1000aafa: f000 bb90 b.w 1000b21e + +1000aafe : +1000aafe: bd31 pop {r0, r4, r5, pc} + +1000ab00 : +1000ab00: b940 cbnz r0, 1000ab14 +1000ab02: 6aa0 ldr r0, [r4, #40] ; 0x28 +1000ab04: 6d61 ldr r1, [r4, #84] ; 0x54 +1000ab06: 6ac0 ldr r0, [r0, #44] ; 0x2c +1000ab08: 2201 movs r2, #1 +1000ab0a: fa02 f000 lsl.w r0, r2, r0 +1000ab0e: ea21 0000 bic.w r0, r1, r0 +1000ab12: 6560 str r0, [r4, #84] ; 0x54 + +1000ab14 : +1000ab14: 4628 mov r0, r5 +1000ab16: e29d b.n 1000b054 + +1000ab18 : +1000ab18: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +1000ab1c: 460e mov r6, r1 +1000ab1e: 2400 movs r4, #0 +1000ab20: 4607 mov r7, r0 +1000ab22: 2e0b cmp r6, #11 +1000ab24: bf28 it cs +1000ab26: 260a movcs r6, #10 +1000ab28: f000 fb82 bl 1000b230 +1000ab2c: f8df 5680 ldr.w r5, [pc, #1664] ; 1000b1b0 +1000ab30: b907 cbnz r7, 1000ab34 +1000ab32: 6aaf ldr r7, [r5, #40] ; 0x28 + +1000ab34 : +1000ab34: 6c38 ldr r0, [r7, #64] ; 0x40 +1000ab36: 42b0 cmp r0, r6 +1000ab38: d03a beq.n 1000abb0 +1000ab3a: 6aa9 ldr r1, [r5, #40] ; 0x28 +1000ab3c: d206 bcs.n 1000ab4c +1000ab3e: 428f cmp r7, r1 +1000ab40: d007 beq.n 1000ab52 +1000ab42: 6aa9 ldr r1, [r5, #40] ; 0x28 +1000ab44: 6ac9 ldr r1, [r1, #44] ; 0x2c +1000ab46: 428e cmp r6, r1 +1000ab48: d303 bcc.n 1000ab52 +1000ab4a: e001 b.n 1000ab50 + +1000ab4c : +1000ab4c: 428f cmp r7, r1 +1000ab4e: d100 bne.n 1000ab52 + +1000ab50 : +1000ab50: 2401 movs r4, #1 + +1000ab52 : +1000ab52: f8d7 802c ldr.w r8, [r7, #44] ; 0x2c +1000ab56: 4540 cmp r0, r8 +1000ab58: bf08 it eq +1000ab5a: 62fe streq r6, [r7, #44] ; 0x2c +1000ab5c: 643e str r6, [r7, #64] ; 0x40 +1000ab5e: 69b8 ldr r0, [r7, #24] +1000ab60: 2800 cmp r0, #0 +1000ab62: bf5c itt pl +1000ab64: f1c6 000b rsbpl r0, r6, #11 +1000ab68: 61b8 strpl r0, [r7, #24] +1000ab6a: f8df 6648 ldr.w r6, [pc, #1608] ; 1000b1b4 +1000ab6e: 6978 ldr r0, [r7, #20] +1000ab70: f04f 0914 mov.w r9, #20 +1000ab74: fb09 6108 mla r1, r9, r8, r6 +1000ab78: 4288 cmp r0, r1 +1000ab7a: d116 bne.n 1000abaa +1000ab7c: f04f 0a01 mov.w sl, #1 +1000ab80: 1d38 adds r0, r7, #4 +1000ab82: f001 fe84 bl 1000c88e +1000ab86: b920 cbnz r0, 1000ab92 +1000ab88: 6d68 ldr r0, [r5, #84] ; 0x54 +1000ab8a: fa0a f108 lsl.w r1, sl, r8 +1000ab8e: 4388 bics r0, r1 +1000ab90: 6568 str r0, [r5, #84] ; 0x54 + +1000ab92 : +1000ab92: 6d68 ldr r0, [r5, #84] ; 0x54 +1000ab94: 6af9 ldr r1, [r7, #44] ; 0x2c +1000ab96: fa0a f101 lsl.w r1, sl, r1 +1000ab9a: 4308 orrs r0, r1 +1000ab9c: 6568 str r0, [r5, #84] ; 0x54 +1000ab9e: 1d39 adds r1, r7, #4 +1000aba0: 6af8 ldr r0, [r7, #44] ; 0x2c +1000aba2: fb09 6000 mla r0, r9, r0, r6 +1000aba6: f001 fe4d bl 1000c844 + +1000abaa : +1000abaa: b10c cbz r4, 1000abb0 +1000abac: f000 fb37 bl 1000b21e + +1000abb0 : +1000abb0: e8bd 47f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +1000abb4: f000 bb48 b.w 1000b248 + +1000abb8 : +1000abb8: f8df 45f4 ldr.w r4, [pc, #1524] ; 1000b1b0 +1000abbc: b905 cbnz r5, 1000abc0 +1000abbe: 6aa5 ldr r5, [r4, #40] ; 0x28 + +1000abc0 : +1000abc0: 1d28 adds r0, r5, #4 +1000abc2: f001 be64 b.w 1000c88e + +1000abc6 : +1000abc6: b970 cbnz r0, 1000abe6 +1000abc8: 6ae8 ldr r0, [r5, #44] ; 0x2c +1000abca: f8df 15e8 ldr.w r1, [pc, #1512] ; 1000b1b4 +1000abce: 2214 movs r2, #20 +1000abd0: fb02 1100 mla r1, r2, r0, r1 +1000abd4: 6809 ldr r1, [r1, #0] +1000abd6: b931 cbnz r1, 1000abe6 +1000abd8: 6d61 ldr r1, [r4, #84] ; 0x54 +1000abda: 2201 movs r2, #1 +1000abdc: fa02 f000 lsl.w r0, r2, r0 +1000abe0: ea21 0000 bic.w r0, r1, r0 +1000abe4: 6560 str r0, [r4, #84] ; 0x54 + +1000abe6 : +1000abe6: 6aa8 ldr r0, [r5, #40] ; 0x28 +1000abe8: 4770 bx lr + +1000abea : +1000abea: f000 fb21 bl 1000b230 +1000abee: f000 fa49 bl 1000b084 + +1000abf2 : +1000abf2: e8bd 4031 ldmia.w sp!, {r0, r4, r5, lr} +1000abf6: f000 bb27 b.w 1000b248 + +1000abfa : +1000abfa: b500 push {lr} +1000abfc: b085 sub sp, #20 +1000abfe: 2000 movs r0, #0 +1000ac00: 9003 str r0, [sp, #12] +1000ac02: 9002 str r0, [sp, #8] +1000ac04: 9001 str r0, [sp, #4] +1000ac06: 9000 str r0, [sp, #0] +1000ac08: 2300 movs r3, #0 +1000ac0a: 2246 movs r2, #70 ; 0x46 +1000ac0c: f20f 51a8 addw r1, pc, #1448 ; 0x5a8 +1000ac10: f20f 3071 addw r0, pc, #881 ; 0x371 +1000ac14: f7ff fe88 bl 1000a928 +1000ac18: 2801 cmp r0, #1 +1000ac1a: bf08 it eq +1000ac1c: f001 ff0a bleq 1000ca34 +1000ac20: 2801 cmp r0, #1 +1000ac22: d10c bne.n 1000ac3e +1000ac24: f038 ffe1 bl 10043bea +1000ac28: f8df 0584 ldr.w r0, [pc, #1412] ; 1000b1b0 +1000ac2c: 2101 movs r1, #1 +1000ac2e: 6581 str r1, [r0, #88] ; 0x58 +1000ac30: 2100 movs r1, #0 +1000ac32: 6501 str r1, [r0, #80] ; 0x50 +1000ac34: b005 add sp, #20 +1000ac36: f85d eb04 ldr.w lr, [sp], #4 +1000ac3a: f000 badd b.w 1000b1f8 + +1000ac3e : +1000ac3e: b005 add sp, #20 +1000ac40: bd00 pop {pc} + +1000ac42 : +1000ac42: f8df 056c ldr.w r0, [pc, #1388] ; 1000b1b0 +1000ac46: 6f01 ldr r1, [r0, #112] ; 0x70 +1000ac48: 1c49 adds r1, r1, #1 +1000ac4a: 6701 str r1, [r0, #112] ; 0x70 +1000ac4c: 4770 bx lr + +1000ac4e : +1000ac4e: f8df 0560 ldr.w r0, [pc, #1376] ; 1000b1b0 +1000ac52: 6a81 ldr r1, [r0, #40] ; 0x28 +1000ac54: 6ac9 ldr r1, [r1, #44] ; 0x2c +1000ac56: b921 cbnz r1, 1000ac62 +1000ac58: f8df 1558 ldr.w r1, [pc, #1368] ; 1000b1b4 +1000ac5c: 6809 ldr r1, [r1, #0] +1000ac5e: 2902 cmp r1, #2 +1000ac60: d301 bcc.n 1000ac66 + +1000ac62 : +1000ac62: 2000 movs r0, #0 +1000ac64: 4770 bx lr + +1000ac66 : +1000ac66: 6ec1 ldr r1, [r0, #108] ; 0x6c +1000ac68: 6d00 ldr r0, [r0, #80] ; 0x50 +1000ac6a: 1a08 subs r0, r1, r0 +1000ac6c: 4770 bx lr + +1000ac6e : +1000ac6e: b570 push {r4, r5, r6, lr} +1000ac70: 2400 movs r4, #0 +1000ac72: f000 fadd bl 1000b230 +1000ac76: f8df 5538 ldr.w r5, [pc, #1336] ; 1000b1b0 +1000ac7a: 6f28 ldr r0, [r5, #112] ; 0x70 +1000ac7c: 1e40 subs r0, r0, #1 +1000ac7e: 6728 str r0, [r5, #112] ; 0x70 +1000ac80: 6f28 ldr r0, [r5, #112] ; 0x70 +1000ac82: 2800 cmp r0, #0 +1000ac84: d138 bne.n 1000acf8 +1000ac86: 6ce8 ldr r0, [r5, #76] ; 0x4c +1000ac88: b9f8 cbnz r0, 1000acca +1000ac8a: e035 b.n 1000acf8 + +1000ac8c : +1000ac8c: 68e8 ldr r0, [r5, #12] +1000ac8e: 68c6 ldr r6, [r0, #12] +1000ac90: f106 0018 add.w r0, r6, #24 +1000ac94: f001 fdfb bl 1000c88e +1000ac98: 1d30 adds r0, r6, #4 +1000ac9a: f001 fdf8 bl 1000c88e +1000ac9e: 6d68 ldr r0, [r5, #84] ; 0x54 +1000aca0: 6af2 ldr r2, [r6, #44] ; 0x2c +1000aca2: 2101 movs r1, #1 +1000aca4: 4091 lsls r1, r2 +1000aca6: 4308 orrs r0, r1 +1000aca8: 6568 str r0, [r5, #84] ; 0x54 +1000acaa: 1d31 adds r1, r6, #4 +1000acac: 6af2 ldr r2, [r6, #44] ; 0x2c +1000acae: f8df 0504 ldr.w r0, [pc, #1284] ; 1000b1b4 +1000acb2: 2314 movs r3, #20 +1000acb4: fb03 0002 mla r0, r3, r2, r0 +1000acb8: f001 fdc4 bl 1000c844 +1000acbc: 6af0 ldr r0, [r6, #44] ; 0x2c +1000acbe: 6aa9 ldr r1, [r5, #40] ; 0x28 +1000acc0: 6ac9 ldr r1, [r1, #44] ; 0x2c +1000acc2: 4288 cmp r0, r1 +1000acc4: bf24 itt cs +1000acc6: 2001 movcs r0, #1 +1000acc8: 6628 strcs r0, [r5, #96] ; 0x60 + +1000acca : +1000acca: 6828 ldr r0, [r5, #0] +1000accc: 2800 cmp r0, #0 +1000acce: d1dd bne.n 1000ac8c +1000acd0: 6de8 ldr r0, [r5, #92] ; 0x5c +1000acd2: b940 cbnz r0, 1000ace6 +1000acd4: e00a b.n 1000acec + +1000acd6 : +1000acd6: f000 f826 bl 1000ad26 +1000acda: b108 cbz r0, 1000ace0 +1000acdc: 2001 movs r0, #1 +1000acde: 6628 str r0, [r5, #96] ; 0x60 + +1000ace0 : +1000ace0: 6de8 ldr r0, [r5, #92] ; 0x5c +1000ace2: 1e40 subs r0, r0, #1 +1000ace4: 65e8 str r0, [r5, #92] ; 0x5c + +1000ace6 : +1000ace6: 6de8 ldr r0, [r5, #92] ; 0x5c +1000ace8: 2800 cmp r0, #0 +1000acea: d1f4 bne.n 1000acd6 + +1000acec : +1000acec: 6e28 ldr r0, [r5, #96] ; 0x60 +1000acee: 2801 cmp r0, #1 +1000acf0: bf04 itt eq +1000acf2: 2401 moveq r4, #1 +1000acf4: f000 fa93 bleq 1000b21e + +1000acf8 : +1000acf8: e13a b.n 1000af70 + +1000acfa : +1000acfa: b510 push {r4, lr} +1000acfc: f000 fa98 bl 1000b230 +1000ad00: f8df 04ac ldr.w r0, [pc, #1196] ; 1000b1b0 +1000ad04: 6d04 ldr r4, [r0, #80] ; 0x50 + +1000ad06 : +1000ad06: f000 fa9f bl 1000b248 +1000ad0a: 4620 mov r0, r4 +1000ad0c: bd10 pop {r4, pc} + +1000ad0e : +1000ad0e: b910 cbnz r0, 1000ad16 +1000ad10: f8df 049c ldr.w r0, [pc, #1180] ; 1000b1b0 +1000ad14: 6a80 ldr r0, [r0, #40] ; 0x28 + +1000ad16 : +1000ad16: 3034 adds r0, #52 ; 0x34 +1000ad18: 4770 bx lr + +1000ad1a : +1000ad1a: f8df 1494 ldr.w r1, [pc, #1172] ; 1000b1b0 +1000ad1e: 6d0a ldr r2, [r1, #80] ; 0x50 +1000ad20: 1880 adds r0, r0, r2 +1000ad22: 6508 str r0, [r1, #80] ; 0x50 +1000ad24: 4770 bx lr + +1000ad26 : +1000ad26: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +1000ad2a: f8df 5484 ldr.w r5, [pc, #1156] ; 1000b1b0 +1000ad2e: 6f28 ldr r0, [r5, #112] ; 0x70 +1000ad30: 2400 movs r4, #0 +1000ad32: 2800 cmp r0, #0 +1000ad34: d146 bne.n 1000adc4 +1000ad36: 6d28 ldr r0, [r5, #80] ; 0x50 +1000ad38: 1c40 adds r0, r0, #1 +1000ad3a: 6528 str r0, [r5, #80] ; 0x50 +1000ad3c: 6d2e ldr r6, [r5, #80] ; 0x50 +1000ad3e: b946 cbnz r6, 1000ad52 +1000ad40: 6ae8 ldr r0, [r5, #44] ; 0x2c +1000ad42: 6b29 ldr r1, [r5, #48] ; 0x30 +1000ad44: 62e9 str r1, [r5, #44] ; 0x2c +1000ad46: 6328 str r0, [r5, #48] ; 0x30 +1000ad48: 6e68 ldr r0, [r5, #100] ; 0x64 +1000ad4a: 1c40 adds r0, r0, #1 +1000ad4c: 6668 str r0, [r5, #100] ; 0x64 +1000ad4e: f000 f999 bl 1000b084 + +1000ad52 : +1000ad52: f04f 0914 mov.w r9, #20 +1000ad56: 6ee8 ldr r0, [r5, #108] ; 0x6c +1000ad58: f8df 8458 ldr.w r8, [pc, #1112] ; 1000b1b4 +1000ad5c: 4286 cmp r6, r0 +1000ad5e: d328 bcc.n 1000adb2 +1000ad60: e01a b.n 1000ad98 + +1000ad62 : +1000ad62: 1d38 adds r0, r7, #4 +1000ad64: f001 fd93 bl 1000c88e +1000ad68: 6ab8 ldr r0, [r7, #40] ; 0x28 +1000ad6a: b118 cbz r0, 1000ad74 +1000ad6c: f107 0018 add.w r0, r7, #24 +1000ad70: f001 fd8d bl 1000c88e + +1000ad74 : +1000ad74: 6d68 ldr r0, [r5, #84] ; 0x54 +1000ad76: 6afa ldr r2, [r7, #44] ; 0x2c +1000ad78: 2101 movs r1, #1 +1000ad7a: 4091 lsls r1, r2 +1000ad7c: 4308 orrs r0, r1 +1000ad7e: 6568 str r0, [r5, #84] ; 0x54 +1000ad80: 1d39 adds r1, r7, #4 +1000ad82: 6af8 ldr r0, [r7, #44] ; 0x2c +1000ad84: fb09 8000 mla r0, r9, r0, r8 +1000ad88: f001 fd5c bl 1000c844 +1000ad8c: 6af8 ldr r0, [r7, #44] ; 0x2c +1000ad8e: 6aa9 ldr r1, [r5, #40] ; 0x28 +1000ad90: 6ac9 ldr r1, [r1, #44] ; 0x2c +1000ad92: 4288 cmp r0, r1 +1000ad94: bf28 it cs +1000ad96: 2401 movcs r4, #1 + +1000ad98 : +1000ad98: 6ae8 ldr r0, [r5, #44] ; 0x2c +1000ad9a: 6800 ldr r0, [r0, #0] +1000ad9c: b910 cbnz r0, 1000ada4 +1000ad9e: f04f 30ff mov.w r0, #4294967295 +1000ada2: e005 b.n 1000adb0 + +1000ada4 : +1000ada4: 6ae8 ldr r0, [r5, #44] ; 0x2c +1000ada6: 68c0 ldr r0, [r0, #12] +1000ada8: 68c7 ldr r7, [r0, #12] +1000adaa: 6878 ldr r0, [r7, #4] +1000adac: 4286 cmp r6, r0 +1000adae: d2d8 bcs.n 1000ad62 + +1000adb0 : +1000adb0: 66e8 str r0, [r5, #108] ; 0x6c + +1000adb2 : +1000adb2: 6aa8 ldr r0, [r5, #40] ; 0x28 +1000adb4: 6ac0 ldr r0, [r0, #44] ; 0x2c +1000adb6: fb09 8000 mla r0, r9, r0, r8 +1000adba: 6800 ldr r0, [r0, #0] +1000adbc: 2802 cmp r0, #2 +1000adbe: d304 bcc.n 1000adca +1000adc0: 2401 movs r4, #1 +1000adc2: e002 b.n 1000adca + +1000adc4 : +1000adc4: 6de8 ldr r0, [r5, #92] ; 0x5c +1000adc6: 1c40 adds r0, r0, #1 +1000adc8: 65e8 str r0, [r5, #92] ; 0x5c + +1000adca : +1000adca: 6e28 ldr r0, [r5, #96] ; 0x60 +1000adcc: b100 cbz r0, 1000add0 +1000adce: 2401 movs r4, #1 + +1000add0 : +1000add0: 4620 mov r0, r4 +1000add2: e8bd 83f2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, pc} + +1000add6 : +1000add6: b510 push {r4, lr} +1000add8: f8df 43d4 ldr.w r4, [pc, #980] ; 1000b1b0 +1000addc: 6f20 ldr r0, [r4, #112] ; 0x70 +1000adde: b110 cbz r0, 1000ade6 +1000ade0: 2001 movs r0, #1 +1000ade2: 6620 str r0, [r4, #96] ; 0x60 +1000ade4: bd10 pop {r4, pc} + +1000ade6 : +1000ade6: 6620 str r0, [r4, #96] ; 0x60 +1000ade8: 6aa0 ldr r0, [r4, #40] ; 0x28 +1000adea: 6b00 ldr r0, [r0, #48] ; 0x30 +1000adec: 6aa1 ldr r1, [r4, #40] ; 0x28 +1000adee: 6809 ldr r1, [r1, #0] +1000adf0: 4288 cmp r0, r1 +1000adf2: d301 bcc.n 1000adf8 +1000adf4: f000 f822 bl 1000ae3c + +1000adf8 : +1000adf8: 6aa0 ldr r0, [r4, #40] ; 0x28 +1000adfa: f20f 31c4 addw r1, pc, #964 ; 0x3c4 +1000adfe: 6b00 ldr r0, [r0, #48] ; 0x30 +1000ae00: 2214 movs r2, #20 +1000ae02: f001 fa9f bl 1000c344 +1000ae06: b108 cbz r0, 1000ae0c +1000ae08: f000 f818 bl 1000ae3c + +1000ae0c : +1000ae0c: 6d61 ldr r1, [r4, #84] ; 0x54 +1000ae0e: f8df 03a4 ldr.w r0, [pc, #932] ; 1000b1b4 +1000ae12: fab1 f181 clz r1, r1 +1000ae16: f06f 0213 mvn.w r2, #19 +1000ae1a: fb02 0001 mla r0, r2, r1, r0 +1000ae1e: f500 701b add.w r0, r0, #620 ; 0x26c +1000ae22: f100 0208 add.w r2, r0, #8 +1000ae26: 6841 ldr r1, [r0, #4] +1000ae28: 6849 ldr r1, [r1, #4] +1000ae2a: 6041 str r1, [r0, #4] +1000ae2c: 4291 cmp r1, r2 +1000ae2e: bf04 itt eq +1000ae30: 6849 ldreq r1, [r1, #4] +1000ae32: 6041 streq r1, [r0, #4] +1000ae34: 6840 ldr r0, [r0, #4] +1000ae36: 68c0 ldr r0, [r0, #12] +1000ae38: 62a0 str r0, [r4, #40] ; 0x28 +1000ae3a: bd10 pop {r4, pc} + +1000ae3c : +1000ae3c: 6aa0 ldr r0, [r4, #40] ; 0x28 +1000ae3e: f100 0134 add.w r1, r0, #52 ; 0x34 +1000ae42: 6aa0 ldr r0, [r4, #40] ; 0x28 +1000ae44: f000 baa5 b.w 1000b392 + +1000ae48 : +1000ae48: b538 push {r3, r4, r5, lr} +1000ae4a: f000 f839 bl 1000aec0 + +1000ae4e : +1000ae4e: f001 fd05 bl 1000c85c +1000ae52: f000 f805 bl 1000ae60 + +1000ae56 : +1000ae56: f000 f807 bl 1000ae68 + +1000ae5a : +1000ae5a: d100 bne.n 1000ae5e +1000ae5c: e011 b.n 1000ae82 + +1000ae5e : +1000ae5e: e018 b.n 1000ae92 + +1000ae60 : +1000ae60: 6aa8 ldr r0, [r5, #40] ; 0x28 +1000ae62: 1d00 adds r0, r0, #4 +1000ae64: f001 bd13 b.w 1000c88e + +1000ae68 : +1000ae68: b940 cbnz r0, 1000ae7c +1000ae6a: 6aa8 ldr r0, [r5, #40] ; 0x28 +1000ae6c: 6d69 ldr r1, [r5, #84] ; 0x54 +1000ae6e: 6ac0 ldr r0, [r0, #44] ; 0x2c +1000ae70: 2201 movs r2, #1 +1000ae72: fa02 f000 lsl.w r0, r2, r0 +1000ae76: ea21 0000 bic.w r0, r1, r0 +1000ae7a: 6568 str r0, [r5, #84] ; 0x54 + +1000ae7c : +1000ae7c: f114 0f01 cmn.w r4, #1 +1000ae80: 4770 bx lr + +1000ae82 : +1000ae82: 6aa8 ldr r0, [r5, #40] ; 0x28 +1000ae84: 1d01 adds r1, r0, #4 +1000ae86: f105 0038 add.w r0, r5, #56 ; 0x38 +1000ae8a: e8bd 4034 ldmia.w sp!, {r2, r4, r5, lr} +1000ae8e: f001 bcd9 b.w 1000c844 + +1000ae92 : +1000ae92: 6d28 ldr r0, [r5, #80] ; 0x50 +1000ae94: 1820 adds r0, r4, r0 +1000ae96: e8bd 4032 ldmia.w sp!, {r1, r4, r5, lr} +1000ae9a: e0db b.n 1000b054 + +1000ae9c : +1000ae9c: b538 push {r3, r4, r5, lr} +1000ae9e: f000 f80f bl 1000aec0 + +1000aea2 : +1000aea2: f001 fccf bl 1000c844 +1000aea6: f7ff ffdb bl 1000ae60 + +1000aeaa : +1000aeaa: b940 cbnz r0, 1000aebe +1000aeac: 6aa8 ldr r0, [r5, #40] ; 0x28 +1000aeae: 6d69 ldr r1, [r5, #84] ; 0x54 +1000aeb0: 6ac0 ldr r0, [r0, #44] ; 0x2c +1000aeb2: 2201 movs r2, #1 +1000aeb4: fa02 f000 lsl.w r0, r2, r0 +1000aeb8: ea21 0000 bic.w r0, r1, r0 +1000aebc: 6568 str r0, [r5, #84] ; 0x54 + +1000aebe : +1000aebe: e7e8 b.n 1000ae92 + +1000aec0 : +1000aec0: 4dbb ldr r5, [pc, #748] ; (1000b1b0 ) +1000aec2: 460c mov r4, r1 +1000aec4: 6aa9 ldr r1, [r5, #40] ; 0x28 +1000aec6: 3118 adds r1, #24 +1000aec8: 4770 bx lr + +1000aeca : +1000aeca: b538 push {r3, r4, r5, lr} +1000aecc: 68c0 ldr r0, [r0, #12] +1000aece: 68c4 ldr r4, [r0, #12] +1000aed0: f104 0018 add.w r0, r4, #24 +1000aed4: f001 fcdb bl 1000c88e +1000aed8: 4db5 ldr r5, [pc, #724] ; (1000b1b0 ) +1000aeda: 6f28 ldr r0, [r5, #112] ; 0x70 +1000aedc: b920 cbnz r0, 1000aee8 +1000aede: f000 f810 bl 1000af02 + +1000aee2 : +1000aee2: f000 f811 bl 1000af08 + +1000aee6 : +1000aee6: e002 b.n 1000aeee + +1000aee8 : +1000aee8: f104 0118 add.w r1, r4, #24 +1000aeec: 4628 mov r0, r5 + +1000aeee : +1000aeee: f001 fca9 bl 1000c844 +1000aef2: 6aa8 ldr r0, [r5, #40] ; 0x28 +1000aef4: 6ae1 ldr r1, [r4, #44] ; 0x2c +1000aef6: 6ac0 ldr r0, [r0, #44] ; 0x2c +1000aef8: 4288 cmp r0, r1 +1000aefa: d200 bcs.n 1000aefe +1000aefc: e011 b.n 1000af22 + +1000aefe : +1000aefe: 2000 movs r0, #0 +1000af00: bd32 pop {r1, r4, r5, pc} + +1000af02 : +1000af02: 1d20 adds r0, r4, #4 +1000af04: f001 bcc3 b.w 1000c88e + +1000af08 : +1000af08: 6d68 ldr r0, [r5, #84] ; 0x54 +1000af0a: 6ae2 ldr r2, [r4, #44] ; 0x2c +1000af0c: 2101 movs r1, #1 +1000af0e: 4091 lsls r1, r2 +1000af10: 4308 orrs r0, r1 +1000af12: 6568 str r0, [r5, #84] ; 0x54 +1000af14: 1d21 adds r1, r4, #4 +1000af16: 6ae2 ldr r2, [r4, #44] ; 0x2c +1000af18: 48a6 ldr r0, [pc, #664] ; (1000b1b4 ) +1000af1a: 2314 movs r3, #20 +1000af1c: fb03 0002 mla r0, r3, r2, r0 +1000af20: 4770 bx lr + +1000af22 : +1000af22: 2001 movs r0, #1 +1000af24: 6628 str r0, [r5, #96] ; 0x60 +1000af26: bd32 pop {r1, r4, r5, pc} + +1000af28 : +1000af28: 49a1 ldr r1, [pc, #644] ; (1000b1b0 ) +1000af2a: 6e4a ldr r2, [r1, #100] ; 0x64 +1000af2c: 6002 str r2, [r0, #0] +1000af2e: 6d09 ldr r1, [r1, #80] ; 0x50 +1000af30: 6041 str r1, [r0, #4] +1000af32: 4770 bx lr + +1000af34 : +1000af34: b570 push {r4, r5, r6, lr} +1000af36: 4604 mov r4, r0 +1000af38: 460d mov r5, r1 +1000af3a: f000 f979 bl 1000b230 +1000af3e: 489c ldr r0, [pc, #624] ; (1000b1b0 ) +1000af40: 6d01 ldr r1, [r0, #80] ; 0x50 +1000af42: 682a ldr r2, [r5, #0] +1000af44: f112 0f01 cmn.w r2, #1 +1000af48: d00f beq.n 1000af6a +1000af4a: 6863 ldr r3, [r4, #4] +1000af4c: 6e40 ldr r0, [r0, #100] ; 0x64 +1000af4e: 6826 ldr r6, [r4, #0] +1000af50: 42b0 cmp r0, r6 +1000af52: d001 beq.n 1000af58 +1000af54: 4299 cmp r1, r3 +1000af56: d20a bcs.n 1000af6e + +1000af58 : +1000af58: 1ac8 subs r0, r1, r3 +1000af5a: 4290 cmp r0, r2 +1000af5c: d207 bcs.n 1000af6e +1000af5e: 1a50 subs r0, r2, r1 +1000af60: 1818 adds r0, r3, r0 +1000af62: 6028 str r0, [r5, #0] +1000af64: 4620 mov r0, r4 +1000af66: f7ff ffdf bl 1000af28 + +1000af6a : +1000af6a: 2400 movs r4, #0 +1000af6c: e000 b.n 1000af70 + +1000af6e : +1000af6e: 2401 movs r4, #1 + +1000af70 : +1000af70: f000 f96a bl 1000b248 +1000af74: 4620 mov r0, r4 +1000af76: bd70 pop {r4, r5, r6, pc} + +1000af78 : +1000af78: 498d ldr r1, [pc, #564] ; (1000b1b0 ) +1000af7a: 2001 movs r0, #1 +1000af7c: 6608 str r0, [r1, #96] ; 0x60 +1000af7e: 4770 bx lr +1000af80: 0000 movs r0, r0 + ... + +1000af84 : +1000af84: b538 push {r3, r4, r5, lr} +1000af86: e01d b.n 1000afc4 + +1000af88 : +1000af88: f7ff fe5b bl 1000ac42 +1000af8c: 6960 ldr r0, [r4, #20] +1000af8e: 1e45 subs r5, r0, #1 +1000af90: 41ad sbcs r5, r5 +1000af92: 0fed lsrs r5, r5, #31 +1000af94: f7ff fe6b bl 1000ac6e +1000af98: b9a5 cbnz r5, 1000afc4 +1000af9a: f000 f949 bl 1000b230 +1000af9e: 6a20 ldr r0, [r4, #32] +1000afa0: 68c5 ldr r5, [r0, #12] +1000afa2: 1d28 adds r0, r5, #4 +1000afa4: f001 fc73 bl 1000c88e +1000afa8: 6ce0 ldr r0, [r4, #76] ; 0x4c +1000afaa: 1e40 subs r0, r0, #1 +1000afac: 64e0 str r0, [r4, #76] ; 0x4c +1000afae: 6b60 ldr r0, [r4, #52] ; 0x34 +1000afb0: 1e40 subs r0, r0, #1 +1000afb2: 6360 str r0, [r4, #52] ; 0x34 +1000afb4: f000 f948 bl 1000b248 +1000afb8: 6b28 ldr r0, [r5, #48] ; 0x30 +1000afba: f001 fd02 bl 1000c9c2 +1000afbe: 4628 mov r0, r5 +1000afc0: f001 fcff bl 1000c9c2 + +1000afc4 : +1000afc4: 4c7a ldr r4, [pc, #488] ; (1000b1b0 ) +1000afc6: 6b60 ldr r0, [r4, #52] ; 0x34 +1000afc8: 2800 cmp r0, #0 +1000afca: d1dd bne.n 1000af88 +1000afcc: f000 f9e0 bl 1000b390 +1000afd0: f7ff fe3d bl 1000ac4e +1000afd4: 2864 cmp r0, #100 ; 0x64 +1000afd6: d3f5 bcc.n 1000afc4 +1000afd8: f7ff fe33 bl 1000ac42 +1000afdc: f7ff fe37 bl 1000ac4e +1000afe0: 4604 mov r4, r0 +1000afe2: 2c64 cmp r4, #100 ; 0x64 +1000afe4: d305 bcc.n 1000aff2 +1000afe6: f001 fe9f bl 1000cd28 +1000afea: b110 cbz r0, 1000aff2 +1000afec: 4620 mov r0, r4 +1000afee: f000 f943 bl 1000b278 + +1000aff2 : +1000aff2: f7ff fe3c bl 1000ac6e +1000aff6: e7e5 b.n 1000afc4 + +1000aff8 : +1000aff8: 496d ldr r1, [pc, #436] ; (1000b1b0 ) +1000affa: 680a ldr r2, [r1, #0] +1000affc: 2001 movs r0, #1 +1000affe: 2a00 cmp r2, #0 +1000b000: bf06 itte eq +1000b002: 6e09 ldreq r1, [r1, #96] ; 0x60 +1000b004: 2900 cmpeq r1, #0 +1000b006: 2000 movne r0, #0 +1000b008: 4770 bx lr + +1000b00a : +1000b00a: b570 push {r4, r5, r6, lr} +1000b00c: 4604 mov r4, r0 +1000b00e: 4615 mov r5, r2 +1000b010: 2000 movs r0, #0 + +1000b012 : +1000b012: 5c42 ldrb r2, [r0, r1] +1000b014: 1903 adds r3, r0, r4 +1000b016: f883 2034 strb.w r2, [r3, #52] ; 0x34 +1000b01a: 5642 ldrsb r2, [r0, r1] +1000b01c: b112 cbz r2, 1000b024 +1000b01e: 1c40 adds r0, r0, #1 +1000b020: 280a cmp r0, #10 +1000b022: d3f6 bcc.n 1000b012 + +1000b024 : +1000b024: 2000 movs r0, #0 +1000b026: f884 003d strb.w r0, [r4, #61] ; 0x3d +1000b02a: 2d0b cmp r5, #11 +1000b02c: bf28 it cs +1000b02e: 250a movcs r5, #10 +1000b030: f104 0610 add.w r6, r4, #16 +1000b034: 61f5 str r5, [r6, #28] +1000b036: 6425 str r5, [r4, #64] ; 0x40 +1000b038: 6460 str r0, [r4, #68] ; 0x44 +1000b03a: 1d20 adds r0, r4, #4 +1000b03c: f001 fbff bl 1000c83e +1000b040: f104 0018 add.w r0, r4, #24 +1000b044: f001 fbfb bl 1000c83e +1000b048: 6124 str r4, [r4, #16] +1000b04a: f1c5 000b rsb r0, r5, #11 +1000b04e: 60b0 str r0, [r6, #8] +1000b050: 6174 str r4, [r6, #20] +1000b052: bd70 pop {r4, r5, r6, pc} + +1000b054 : +1000b054: b538 push {r3, r4, r5, lr} +1000b056: 4d56 ldr r5, [pc, #344] ; (1000b1b0 ) +1000b058: 4604 mov r4, r0 +1000b05a: 6aa8 ldr r0, [r5, #40] ; 0x28 +1000b05c: 6044 str r4, [r0, #4] +1000b05e: 6d28 ldr r0, [r5, #80] ; 0x50 +1000b060: 4284 cmp r4, r0 +1000b062: 6aa8 ldr r0, [r5, #40] ; 0x28 +1000b064: d205 bcs.n 1000b072 +1000b066: 1d01 adds r1, r0, #4 +1000b068: 6b28 ldr r0, [r5, #48] ; 0x30 +1000b06a: e8bd 4034 ldmia.w sp!, {r2, r4, r5, lr} +1000b06e: f001 bbf5 b.w 1000c85c + +1000b072 : +1000b072: 1d01 adds r1, r0, #4 +1000b074: 6ae8 ldr r0, [r5, #44] ; 0x2c +1000b076: f001 fbf1 bl 1000c85c +1000b07a: 6ee8 ldr r0, [r5, #108] ; 0x6c +1000b07c: 4284 cmp r4, r0 +1000b07e: bf38 it cc +1000b080: 66ec strcc r4, [r5, #108] ; 0x6c +1000b082: bd31 pop {r0, r4, r5, pc} + +1000b084 : +1000b084: 484a ldr r0, [pc, #296] ; (1000b1b0 ) +1000b086: 6ac1 ldr r1, [r0, #44] ; 0x2c +1000b088: 6809 ldr r1, [r1, #0] +1000b08a: b911 cbnz r1, 1000b092 +1000b08c: f04f 31ff mov.w r1, #4294967295 +1000b090: e003 b.n 1000b09a + +1000b092 : +1000b092: 6ac1 ldr r1, [r0, #44] ; 0x2c +1000b094: 68c9 ldr r1, [r1, #12] +1000b096: 68c9 ldr r1, [r1, #12] +1000b098: 6849 ldr r1, [r1, #4] + +1000b09a : +1000b09a: 66c1 str r1, [r0, #108] ; 0x6c +1000b09c: 4770 bx lr + +1000b09e : +1000b09e: 4844 ldr r0, [pc, #272] ; (1000b1b0 ) +1000b0a0: 6d81 ldr r1, [r0, #88] ; 0x58 +1000b0a2: b909 cbnz r1, 1000b0a8 +1000b0a4: 2001 movs r0, #1 +1000b0a6: 4770 bx lr + +1000b0a8 : +1000b0a8: 6f00 ldr r0, [r0, #112] ; 0x70 +1000b0aa: b908 cbnz r0, 1000b0b0 +1000b0ac: 2002 movs r0, #2 +1000b0ae: 4770 bx lr + +1000b0b0 : +1000b0b0: 2000 movs r0, #0 +1000b0b2: 4770 bx lr + +1000b0b4 : +1000b0b4: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1000b0b8: 0004 movs r4, r0 +1000b0ba: d039 beq.n 1000b130 +1000b0bc: 4d3c ldr r5, [pc, #240] ; (1000b1b0 ) +1000b0be: 6ae0 ldr r0, [r4, #44] ; 0x2c +1000b0c0: 6aa9 ldr r1, [r5, #40] ; 0x28 +1000b0c2: 6ac9 ldr r1, [r1, #44] ; 0x2c +1000b0c4: 4288 cmp r0, r1 +1000b0c6: d233 bcs.n 1000b130 +1000b0c8: 69a0 ldr r0, [r4, #24] +1000b0ca: 2800 cmp r0, #0 +1000b0cc: d404 bmi.n 1000b0d8 +1000b0ce: 6aa8 ldr r0, [r5, #40] ; 0x28 +1000b0d0: 6ac0 ldr r0, [r0, #44] ; 0x2c +1000b0d2: f1c0 000b rsb r0, r0, #11 +1000b0d6: 61a0 str r0, [r4, #24] + +1000b0d8 : +1000b0d8: 2714 movs r7, #20 +1000b0da: 6ae1 ldr r1, [r4, #44] ; 0x2c +1000b0dc: f8df 80d4 ldr.w r8, [pc, #212] ; 1000b1b4 +1000b0e0: 6960 ldr r0, [r4, #20] +1000b0e2: fb07 8101 mla r1, r7, r1, r8 +1000b0e6: 4288 cmp r0, r1 +1000b0e8: d11f bne.n 1000b12a +1000b0ea: 2601 movs r6, #1 +1000b0ec: f7ff ff09 bl 1000af02 + +1000b0f0 : +1000b0f0: 2800 cmp r0, #0 +1000b0f2: bf01 itttt eq +1000b0f4: 6ae0 ldreq r0, [r4, #44] ; 0x2c +1000b0f6: fb07 8000 mlaeq r0, r7, r0, r8 +1000b0fa: 6800 ldreq r0, [r0, #0] +1000b0fc: 2800 cmpeq r0, #0 +1000b0fe: d105 bne.n 1000b10c +1000b100: 6d68 ldr r0, [r5, #84] ; 0x54 +1000b102: 6ae1 ldr r1, [r4, #44] ; 0x2c +1000b104: fa06 f101 lsl.w r1, r6, r1 +1000b108: 4388 bics r0, r1 +1000b10a: 6568 str r0, [r5, #84] ; 0x54 + +1000b10c : +1000b10c: 6aa8 ldr r0, [r5, #40] ; 0x28 +1000b10e: 6ac0 ldr r0, [r0, #44] ; 0x2c +1000b110: 62e0 str r0, [r4, #44] ; 0x2c +1000b112: fa06 f200 lsl.w r2, r6, r0 +1000b116: 6d69 ldr r1, [r5, #84] ; 0x54 +1000b118: 4311 orrs r1, r2 +1000b11a: 6569 str r1, [r5, #84] ; 0x54 +1000b11c: fb07 8000 mla r0, r7, r0, r8 +1000b120: 1d21 adds r1, r4, #4 +1000b122: e8bd 41f0 ldmia.w sp!, {r4, r5, r6, r7, r8, lr} +1000b126: f001 bb8d b.w 1000c844 + +1000b12a : +1000b12a: 6aa8 ldr r0, [r5, #40] ; 0x28 +1000b12c: 6ac0 ldr r0, [r0, #44] ; 0x2c +1000b12e: 62e0 str r0, [r4, #44] ; 0x2c + +1000b130 : +1000b130: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +1000b134 : +1000b134: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1000b138: 4604 mov r4, r0 +1000b13a: 2000 movs r0, #0 +1000b13c: b36c cbz r4, 1000b19a +1000b13e: 6c61 ldr r1, [r4, #68] ; 0x44 +1000b140: 1e49 subs r1, r1, #1 +1000b142: 6461 str r1, [r4, #68] ; 0x44 +1000b144: 6ae2 ldr r2, [r4, #44] ; 0x2c +1000b146: 6c23 ldr r3, [r4, #64] ; 0x40 +1000b148: 429a cmp r2, r3 +1000b14a: d026 beq.n 1000b19a +1000b14c: bb29 cbnz r1, 1000b19a +1000b14e: 2501 movs r5, #1 +1000b150: 4e17 ldr r6, [pc, #92] ; (1000b1b0 ) +1000b152: f8df 8060 ldr.w r8, [pc, #96] ; 1000b1b4 +1000b156: 2714 movs r7, #20 +1000b158: f7ff fed3 bl 1000af02 + +1000b15c : +1000b15c: 2800 cmp r0, #0 +1000b15e: bf01 itttt eq +1000b160: 6ae0 ldreq r0, [r4, #44] ; 0x2c +1000b162: fb07 8000 mlaeq r0, r7, r0, r8 +1000b166: 6800 ldreq r0, [r0, #0] +1000b168: 2800 cmpeq r0, #0 +1000b16a: d105 bne.n 1000b178 +1000b16c: 6d70 ldr r0, [r6, #84] ; 0x54 +1000b16e: 6ae1 ldr r1, [r4, #44] ; 0x2c +1000b170: fa05 f101 lsl.w r1, r5, r1 +1000b174: 4388 bics r0, r1 +1000b176: 6570 str r0, [r6, #84] ; 0x54 + +1000b178 : +1000b178: 6c20 ldr r0, [r4, #64] ; 0x40 +1000b17a: 62e0 str r0, [r4, #44] ; 0x2c +1000b17c: f1c0 000b rsb r0, r0, #11 +1000b180: 61a0 str r0, [r4, #24] +1000b182: 6ae0 ldr r0, [r4, #44] ; 0x2c +1000b184: 6d71 ldr r1, [r6, #84] ; 0x54 +1000b186: fa05 f200 lsl.w r2, r5, r0 +1000b18a: 4311 orrs r1, r2 +1000b18c: 6571 str r1, [r6, #84] ; 0x54 +1000b18e: fb07 8000 mla r0, r7, r0, r8 +1000b192: 1d21 adds r1, r4, #4 +1000b194: f001 fb56 bl 1000c844 +1000b198: 2001 movs r0, #1 + +1000b19a : +1000b19a: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +1000b19e : +1000b19e: 4804 ldr r0, [pc, #16] ; (1000b1b0 ) +1000b1a0: 6a81 ldr r1, [r0, #40] ; 0x28 +1000b1a2: b119 cbz r1, 1000b1ac +1000b1a4: 6a81 ldr r1, [r0, #40] ; 0x28 +1000b1a6: 6c4a ldr r2, [r1, #68] ; 0x44 +1000b1a8: 1c52 adds r2, r2, #1 +1000b1aa: 644a str r2, [r1, #68] ; 0x44 + +1000b1ac : +1000b1ac: 6a80 ldr r0, [r0, #40] ; 0x28 +1000b1ae: 4770 bx lr + +1000b1b0 : +1000b1b0: 3fdc 1004 .?.. + +1000b1b4 : +1000b1b4: 79f4 1004 .y.. + +1000b1b8 : +1000b1b8: 4449 454c 0000 0000 IDLE.... + +1000b1c0 : +1000b1c0: a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 ................ +1000b1d0: a5a5 a5a5 .... + +1000b1d4 : +1000b1d4: f04f 7380 mov.w r3, #16777216 ; 0x1000000 +1000b1d8: f840 3d04 str.w r3, [r0, #-4]! +1000b1dc: f840 1d04 str.w r1, [r0, #-4]! +1000b1e0: f20f 010d addw r1, pc, #13 +1000b1e4: f840 1d04 str.w r1, [r0, #-4]! +1000b1e8: f840 2d14 str.w r2, [r0, #-20]! +1000b1ec: 3820 subs r0, #32 +1000b1ee: 4770 bx lr + +1000b1f0 : +1000b1f0: b580 push {r7, lr} +1000b1f2: f038 fcfa bl 10043bea + +1000b1f6 : +1000b1f6: e7fe b.n 1000b1f6 + +1000b1f8 : +1000b1f8: b580 push {r7, lr} +1000b1fa: 485f ldr r0, [pc, #380] ; (1000b378 ) +1000b1fc: 6801 ldr r1, [r0, #0] +1000b1fe: f441 0170 orr.w r1, r1, #15728640 ; 0xf00000 +1000b202: 6001 str r1, [r0, #0] +1000b204: 6801 ldr r1, [r0, #0] +1000b206: f041 4170 orr.w r1, r1, #4026531840 ; 0xf0000000 +1000b20a: 6001 str r1, [r0, #0] +1000b20c: f000 f89d bl 1000b34a +1000b210: 2000 movs r0, #0 +1000b212: 495a ldr r1, [pc, #360] ; (1000b37c ) +1000b214: 6008 str r0, [r1, #0] +1000b216: f038 fd02 bl 10043c1e +1000b21a: 2000 movs r0, #0 +1000b21c: bd02 pop {r1, pc} + +1000b21e : +1000b21e: 4958 ldr r1, [pc, #352] ; (1000b380 ) +1000b220: f04f 5080 mov.w r0, #268435456 ; 0x10000000 +1000b224: 6008 str r0, [r1, #0] +1000b226: f3bf 8f4f dsb sy +1000b22a: f3bf 8f6f isb sy +1000b22e: 4770 bx lr + +1000b230 : +1000b230: b580 push {r7, lr} +1000b232: f038 fcda bl 10043bea +1000b236: 4851 ldr r0, [pc, #324] ; (1000b37c ) +1000b238: 6801 ldr r1, [r0, #0] +1000b23a: 1c49 adds r1, r1, #1 +1000b23c: 6001 str r1, [r0, #0] +1000b23e: f3bf 8f4f dsb sy +1000b242: f3bf 8f6f isb sy +1000b246: bd01 pop {r0, pc} + +1000b248 : +1000b248: 484c ldr r0, [pc, #304] ; (1000b37c ) +1000b24a: 6801 ldr r1, [r0, #0] +1000b24c: 1e49 subs r1, r1, #1 +1000b24e: 6001 str r1, [r0, #0] +1000b250: bf04 itt eq +1000b252: 2000 moveq r0, #0 +1000b254: f038 bcd0 beq.w 10043bf8 +1000b258: 4770 bx lr + +1000b25a : +1000b25a: b580 push {r7, lr} +1000b25c: f038 fcc5 bl 10043bea +1000b260: f7ff fd61 bl 1000ad26 +1000b264: b118 cbz r0, 1000b26e +1000b266: 4946 ldr r1, [pc, #280] ; (1000b380 ) +1000b268: f04f 5080 mov.w r0, #268435456 ; 0x10000000 +1000b26c: 6008 str r0, [r1, #0] + +1000b26e : +1000b26e: 2000 movs r0, #0 +1000b270: e8bd 4002 ldmia.w sp!, {r1, lr} +1000b274: f038 bcc0 b.w 10043bf8 + +1000b278 : +1000b278: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1000b27c: 4c41 ldr r4, [pc, #260] ; (1000b384 ) +1000b27e: 4605 mov r5, r0 +1000b280: 6860 ldr r0, [r4, #4] +1000b282: b082 sub sp, #8 +1000b284: 42a8 cmp r0, r5 +1000b286: bf38 it cc +1000b288: 4605 movcc r5, r0 +1000b28a: 4e3f ldr r6, [pc, #252] ; (1000b388 ) +1000b28c: 6830 ldr r0, [r6, #0] +1000b28e: 0840 lsrs r0, r0, #1 +1000b290: 0040 lsls r0, r0, #1 +1000b292: 6030 str r0, [r6, #0] +1000b294: f1a5 0801 sub.w r8, r5, #1 +1000b298: 68b0 ldr r0, [r6, #8] +1000b29a: 6821 ldr r1, [r4, #0] +1000b29c: fb08 0701 mla r7, r8, r1, r0 +1000b2a0: 68a0 ldr r0, [r4, #8] +1000b2a2: 42b8 cmp r0, r7 +1000b2a4: bf38 it cc +1000b2a6: 1a3f subcc r7, r7, r0 +1000b2a8: b672 cpsid i +1000b2aa: f7ff fea5 bl 1000aff8 +1000b2ae: b950 cbnz r0, 1000b2c6 +1000b2b0: 68b0 ldr r0, [r6, #8] +1000b2b2: 6070 str r0, [r6, #4] +1000b2b4: 6830 ldr r0, [r6, #0] +1000b2b6: f040 0001 orr.w r0, r0, #1 +1000b2ba: 6030 str r0, [r6, #0] +1000b2bc: 6820 ldr r0, [r4, #0] +1000b2be: 1e40 subs r0, r0, #1 +1000b2c0: 6070 str r0, [r6, #4] +1000b2c2: b662 cpsie i +1000b2c4: e03f b.n 1000b346 + +1000b2c6 : +1000b2c6: 6077 str r7, [r6, #4] +1000b2c8: 2000 movs r0, #0 +1000b2ca: 60b0 str r0, [r6, #8] +1000b2cc: 6830 ldr r0, [r6, #0] +1000b2ce: f040 0001 orr.w r0, r0, #1 +1000b2d2: 6030 str r0, [r6, #0] +1000b2d4: 9500 str r5, [sp, #0] +1000b2d6: a800 add r0, sp, #0 +1000b2d8: f001 fd2c bl 1000cd34 +1000b2dc: 9800 ldr r0, [sp, #0] +1000b2de: b120 cbz r0, 1000b2ea +1000b2e0: f3bf 8f4f dsb sy +1000b2e4: bf30 wfi +1000b2e6: f3bf 8f6f isb sy + +1000b2ea : +1000b2ea: 6831 ldr r1, [r6, #0] +1000b2ec: 0848 lsrs r0, r1, #1 +1000b2ee: 0040 lsls r0, r0, #1 +1000b2f0: 6030 str r0, [r6, #0] +1000b2f2: b662 cpsie i +1000b2f4: 03c9 lsls r1, r1, #15 +1000b2f6: 6820 ldr r0, [r4, #0] +1000b2f8: d50a bpl.n 1000b310 +1000b2fa: 68b3 ldr r3, [r6, #8] +1000b2fc: 1e41 subs r1, r0, #1 +1000b2fe: 1bca subs r2, r1, r7 +1000b300: 189a adds r2, r3, r2 +1000b302: 68a3 ldr r3, [r4, #8] +1000b304: 429a cmp r2, r3 +1000b306: bf2c ite cs +1000b308: 4290 cmpcs r0, r2 +1000b30a: 460a movcc r2, r1 +1000b30c: 6072 str r2, [r6, #4] +1000b30e: e00a b.n 1000b326 + +1000b310 : +1000b310: 68b2 ldr r2, [r6, #8] +1000b312: fb00 f105 mul.w r1, r0, r5 +1000b316: 1a89 subs r1, r1, r2 +1000b318: fbb1 f8f0 udiv r8, r1, r0 +1000b31c: f108 0201 add.w r2, r8, #1 +1000b320: 4350 muls r0, r2 +1000b322: 1a40 subs r0, r0, r1 +1000b324: 6070 str r0, [r6, #4] + +1000b326 : +1000b326: 2000 movs r0, #0 +1000b328: 60b0 str r0, [r6, #8] +1000b32a: f7ff ff81 bl 1000b230 +1000b32e: 6830 ldr r0, [r6, #0] +1000b330: f040 0001 orr.w r0, r0, #1 +1000b334: 6030 str r0, [r6, #0] +1000b336: 4640 mov r0, r8 +1000b338: f7ff fcef bl 1000ad1a +1000b33c: 6820 ldr r0, [r4, #0] +1000b33e: 1e40 subs r0, r0, #1 +1000b340: 6070 str r0, [r6, #4] +1000b342: f7ff ff81 bl 1000b248 + +1000b346 : +1000b346: e8bd 81f3 ldmia.w sp!, {r0, r1, r4, r5, r6, r7, r8, pc} + +1000b34a : +1000b34a: 4810 ldr r0, [pc, #64] ; (1000b38c ) +1000b34c: 6800 ldr r0, [r0, #0] +1000b34e: f44f 717a mov.w r1, #1000 ; 0x3e8 +1000b352: fbb0 f0f1 udiv r0, r0, r1 +1000b356: 490b ldr r1, [pc, #44] ; (1000b384 ) +1000b358: 6008 str r0, [r1, #0] +1000b35a: f06f 427f mvn.w r2, #4278190080 ; 0xff000000 +1000b35e: fbb2 f2f0 udiv r2, r2, r0 +1000b362: 604a str r2, [r1, #4] +1000b364: 1e40 subs r0, r0, #1 +1000b366: 222d movs r2, #45 ; 0x2d +1000b368: 608a str r2, [r1, #8] +1000b36a: 4907 ldr r1, [pc, #28] ; (1000b388 ) +1000b36c: 6048 str r0, [r1, #4] +1000b36e: 2007 movs r0, #7 +1000b370: 6008 str r0, [r1, #0] +1000b372: 4770 bx lr +1000b374: 0000 movs r0, r0 + ... + +1000b378 : +1000b378: ed20 e000 ... + +1000b37c : +1000b37c: 3fd4 1004 .?.. + +1000b380 : +1000b380: ed04 e000 .... + +1000b384 : +1000b384: 78d0 1004 .x.. + +1000b388 : +1000b388: e010 e000 .... + +1000b38c : +1000b38c: 3fd8 1004 .?.. + +1000b390 : +1000b390: 4770 bx lr + +1000b392 : +1000b392: b580 push {r7, lr} +1000b394: 460a mov r2, r1 +1000b396: f20f 010c addw r1, pc, #12 +1000b39a: f20f 0028 addw r0, pc, #40 ; 0x28 +1000b39e: f7f8 fe4f bl 10004040 + +1000b3a2 : +1000b3a2: e7fe b.n 1000b3a2 + +1000b3a4 : +1000b3a4: 4176 7070 696c 6163 6974 6e6f 7453 6361 vApplicationStac +1000b3b4: 4f6b 6576 6672 6f6c 4877 6f6f 006b 0000 kOverflowHook... + +1000b3c4 : +1000b3c4: 0d0a 255b 5d73 5320 4154 4b43 4f20 4556 ..[%s] STACK OVE +1000b3d4: 4652 4f4c 2057 202d 6154 6b73 614e 656d RFLOW - TaskName +1000b3e4: 2528 2973 0d0a 0000 (%s).... + +1000b3ec : +1000b3ec: b580 push {r7, lr} +1000b3ee: f7fd fb36 bl 10008a5e +1000b3f2: 4872 ldr r0, [pc, #456] ; (1000b5bc ) +1000b3f4: 6800 ldr r0, [r0, #0] +1000b3f6: 2800 cmp r0, #0 +1000b3f8: bf02 ittt eq +1000b3fa: 4871 ldreq r0, [pc, #452] ; (1000b5c0 ) +1000b3fc: 6800 ldreq r0, [r0, #0] +1000b3fe: 2800 cmpeq r0, #0 +1000b400: d002 beq.n 1000b408 +1000b402: e8bd 4008 ldmia.w sp!, {r3, lr} +1000b406: e011 b.n 1000b42c + +1000b408 : +1000b408: 496e ldr r1, [pc, #440] ; (1000b5c4 ) +1000b40a: 6008 str r0, [r1, #0] +1000b40c: bd01 pop {r0, pc} + +1000b40e : +1000b40e: 486d ldr r0, [pc, #436] ; (1000b5c4 ) +1000b410: 6801 ldr r1, [r0, #0] +1000b412: b951 cbnz r1, 1000b42a +1000b414: 4969 ldr r1, [pc, #420] ; (1000b5bc ) +1000b416: 6809 ldr r1, [r1, #0] +1000b418: 2900 cmp r1, #0 +1000b41a: bf02 ittt eq +1000b41c: 4968 ldreq r1, [pc, #416] ; (1000b5c0 ) +1000b41e: 6809 ldreq r1, [r1, #0] +1000b420: 2900 cmpeq r1, #0 +1000b422: d002 beq.n 1000b42a +1000b424: 2101 movs r1, #1 +1000b426: 6001 str r1, [r0, #0] +1000b428: e000 b.n 1000b42c + +1000b42a : +1000b42a: 4770 bx lr + +1000b42c : +1000b42c: 2200 movs r2, #0 +1000b42e: 4966 ldr r1, [pc, #408] ; (1000b5c8 ) +1000b430: 20fa movs r0, #250 ; 0xfa +1000b432: e049 b.n 1000b4c8 + +1000b434 : +1000b434: b580 push {r7, lr} +1000b436: f001 fca5 bl 1000cd84 +1000b43a: e8bd 4008 ldmia.w sp!, {r3, lr} +1000b43e: 2200 movs r2, #0 +1000b440: 4962 ldr r1, [pc, #392] ; (1000b5cc ) +1000b442: f44f 707a mov.w r0, #1000 ; 0x3e8 +1000b446: e03f b.n 1000b4c8 + +1000b448 : +1000b448: b580 push {r7, lr} +1000b44a: f000 f8e3 bl 1000b614 +1000b44e: e8bd 4008 ldmia.w sp!, {r3, lr} +1000b452: 2200 movs r2, #0 +1000b454: 495e ldr r1, [pc, #376] ; (1000b5d0 ) +1000b456: f241 3088 movw r0, #5000 ; 0x1388 +1000b45a: e035 b.n 1000b4c8 + +1000b45c : +1000b45c: b580 push {r7, lr} +1000b45e: f001 ff57 bl 1000d310 +1000b462: e8bd 4008 ldmia.w sp!, {r3, lr} +1000b466: 2200 movs r2, #0 +1000b468: 495a ldr r1, [pc, #360] ; (1000b5d4 ) +1000b46a: f64e 2060 movw r0, #60000 ; 0xea60 +1000b46e: e02b b.n 1000b4c8 + +1000b470 : +1000b470: b580 push {r7, lr} +1000b472: f001 ff73 bl 1000d35c +1000b476: e8bd 4008 ldmia.w sp!, {r3, lr} +1000b47a: 2200 movs r2, #0 +1000b47c: 4956 ldr r1, [pc, #344] ; (1000b5d8 ) +1000b47e: f44f 70fa mov.w r0, #500 ; 0x1f4 +1000b482: e021 b.n 1000b4c8 + +1000b484 : +1000b484: b580 push {r7, lr} +1000b486: f002 fd75 bl 1000df74 +1000b48a: e018 b.n 1000b4be + +1000b48c : +1000b48c: b580 push {r7, lr} +1000b48e: 2200 movs r2, #0 +1000b490: 494e ldr r1, [pc, #312] ; (1000b5cc ) +1000b492: f44f 707a mov.w r0, #1000 ; 0x3e8 +1000b496: f000 f817 bl 1000b4c8 +1000b49a: 2200 movs r2, #0 +1000b49c: 494c ldr r1, [pc, #304] ; (1000b5d0 ) +1000b49e: f241 3088 movw r0, #5000 ; 0x1388 +1000b4a2: f000 f811 bl 1000b4c8 +1000b4a6: 2200 movs r2, #0 +1000b4a8: 494a ldr r1, [pc, #296] ; (1000b5d4 ) +1000b4aa: f64e 2060 movw r0, #60000 ; 0xea60 +1000b4ae: f000 f80b bl 1000b4c8 +1000b4b2: 2200 movs r2, #0 +1000b4b4: 4948 ldr r1, [pc, #288] ; (1000b5d8 ) +1000b4b6: f44f 70fa mov.w r0, #500 ; 0x1f4 +1000b4ba: f000 f805 bl 1000b4c8 + +1000b4be : +1000b4be: e8bd 4008 ldmia.w sp!, {r3, lr} +1000b4c2: 2200 movs r2, #0 +1000b4c4: 4945 ldr r1, [pc, #276] ; (1000b5dc ) +1000b4c6: 2064 movs r0, #100 ; 0x64 + +1000b4c8 : +1000b4c8: b570 push {r4, r5, r6, lr} +1000b4ca: 4604 mov r4, r0 +1000b4cc: 460d mov r5, r1 +1000b4ce: 4616 mov r6, r2 +1000b4d0: 200b movs r0, #11 +1000b4d2: f7fc ff06 bl 100082e2 +1000b4d6: b1f8 cbz r0, 1000b518 +1000b4d8: 2100 movs r1, #0 +1000b4da: 6001 str r1, [r0, #0] +1000b4dc: 6085 str r5, [r0, #8] +1000b4de: 60c6 str r6, [r0, #12] +1000b4e0: 6044 str r4, [r0, #4] +1000b4e2: 493f ldr r1, [pc, #252] ; (1000b5e0 ) +1000b4e4: 680a ldr r2, [r1, #0] +1000b4e6: b12a cbz r2, 1000b4f4 +1000b4e8: 6853 ldr r3, [r2, #4] +1000b4ea: 429c cmp r4, r3 +1000b4ec: d205 bcs.n 1000b4fa +1000b4ee: 1b1b subs r3, r3, r4 +1000b4f0: 6053 str r3, [r2, #4] +1000b4f2: 6002 str r2, [r0, #0] + +1000b4f4 : +1000b4f4: 6008 str r0, [r1, #0] +1000b4f6: bd70 pop {r4, r5, r6, pc} + +1000b4f8 : +1000b4f8: 460a mov r2, r1 + +1000b4fa : +1000b4fa: 6841 ldr r1, [r0, #4] +1000b4fc: 6853 ldr r3, [r2, #4] +1000b4fe: 1acb subs r3, r1, r3 +1000b500: 6043 str r3, [r0, #4] +1000b502: 6811 ldr r1, [r2, #0] +1000b504: b111 cbz r1, 1000b50c +1000b506: 684c ldr r4, [r1, #4] +1000b508: 42a3 cmp r3, r4 +1000b50a: d2f5 bcs.n 1000b4f8 + +1000b50c : +1000b50c: b111 cbz r1, 1000b514 +1000b50e: 684c ldr r4, [r1, #4] +1000b510: 1ae3 subs r3, r4, r3 +1000b512: 604b str r3, [r1, #4] + +1000b514 : +1000b514: 6001 str r1, [r0, #0] +1000b516: 6010 str r0, [r2, #0] + +1000b518 : +1000b518: bd70 pop {r4, r5, r6, pc} + +1000b51a : +1000b51a: 4b31 ldr r3, [pc, #196] ; (1000b5e0 ) +1000b51c: 681a ldr r2, [r3, #0] +1000b51e: b902 cbnz r2, 1000b522 +1000b520: 4770 bx lr + +1000b522 : +1000b522: b570 push {r4, r5, r6, lr} +1000b524: 2400 movs r4, #0 + +1000b526 : +1000b526: 6895 ldr r5, [r2, #8] +1000b528: 4285 cmp r5, r0 +1000b52a: bf04 itt eq +1000b52c: 68d5 ldreq r5, [r2, #12] +1000b52e: 428d cmpeq r5, r1 +1000b530: d110 bne.n 1000b554 +1000b532: 6810 ldr r0, [r2, #0] +1000b534: 2c00 cmp r4, #0 +1000b536: bf0c ite eq +1000b538: 6018 streq r0, [r3, #0] +1000b53a: 6020 strne r0, [r4, #0] +1000b53c: 6810 ldr r0, [r2, #0] +1000b53e: b118 cbz r0, 1000b548 +1000b540: 6841 ldr r1, [r0, #4] +1000b542: 6853 ldr r3, [r2, #4] +1000b544: 1859 adds r1, r3, r1 +1000b546: 6041 str r1, [r0, #4] + +1000b548 : +1000b548: 4611 mov r1, r2 +1000b54a: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +1000b54e: 200b movs r0, #11 +1000b550: f7fc beda b.w 10008308 + +1000b554 : +1000b554: 4614 mov r4, r2 +1000b556: 6812 ldr r2, [r2, #0] +1000b558: 2a00 cmp r2, #0 +1000b55a: d1e4 bne.n 1000b526 +1000b55c: bd70 pop {r4, r5, r6, pc} + +1000b55e : +1000b55e: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1000b562: 4604 mov r4, r0 +1000b564: 4688 mov r8, r1 +1000b566: 4e1e ldr r6, [pc, #120] ; (1000b5e0 ) +1000b568: e00b b.n 1000b582 + +1000b56a : +1000b56a: 6831 ldr r1, [r6, #0] +1000b56c: 6808 ldr r0, [r1, #0] +1000b56e: 6030 str r0, [r6, #0] +1000b570: 688f ldr r7, [r1, #8] +1000b572: 68cd ldr r5, [r1, #12] +1000b574: 200b movs r0, #11 +1000b576: f7fc fec7 bl 10008308 +1000b57a: 0038 movs r0, r7 +1000b57c: bf1c itt ne +1000b57e: 4628 movne r0, r5 +1000b580: 47b8 blxne r7 + +1000b582 : +1000b582: 6830 ldr r0, [r6, #0] +1000b584: b930 cbnz r0, 1000b594 +1000b586: 4641 mov r1, r8 +1000b588: 4620 mov r0, r4 +1000b58a: e8bd 41f0 ldmia.w sp!, {r4, r5, r6, r7, r8, lr} +1000b58e: 2200 movs r2, #0 +1000b590: f7fc bdbc b.w 1000810c + +1000b594 : +1000b594: 6842 ldr r2, [r0, #4] +1000b596: 2a00 cmp r2, #0 +1000b598: d0e7 beq.n 1000b56a +1000b59a: 4641 mov r1, r8 +1000b59c: 4620 mov r0, r4 +1000b59e: f7fc fdb5 bl 1000810c +1000b5a2: f110 0f01 cmn.w r0, #1 +1000b5a6: d0e0 beq.n 1000b56a +1000b5a8: 6831 ldr r1, [r6, #0] +1000b5aa: 684a ldr r2, [r1, #4] +1000b5ac: 4290 cmp r0, r2 +1000b5ae: bf34 ite cc +1000b5b0: 1a10 subcc r0, r2, r0 +1000b5b2: 2000 movcs r0, #0 +1000b5b4: 6048 str r0, [r1, #4] +1000b5b6: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + ... + +1000b5bc : +1000b5bc: 4088 1004 .@.. + +1000b5c0 : +1000b5c0: 408c 1004 .@.. + +1000b5c4 : +1000b5c4: 7898 1004 .x.. + +1000b5c8 : +1000b5c8: b3ed 1000 .... + +1000b5cc : +1000b5cc: b435 1000 5... + +1000b5d0 : +1000b5d0: b449 1000 I... + +1000b5d4 : +1000b5d4: b45d 1000 ]... + +1000b5d8 : +1000b5d8: b471 1000 q... + +1000b5dc : +1000b5dc: b485 1000 .... + +1000b5e0 : +1000b5e0: 7894 1004 .x.. + +1000b5e4 : +1000b5e4: b538 push {r3, r4, r5, lr} +1000b5e6: 2114 movs r1, #20 +1000b5e8: fb01 f400 mul.w r4, r1, r0 +1000b5ec: f8df 553c ldr.w r5, [pc, #1340] ; 1000bb2c +1000b5f0: 5960 ldr r0, [r4, r5] +1000b5f2: b118 cbz r0, 1000b5fc +1000b5f4: f7fd f8f8 bl 100087e8 +1000b5f8: 2000 movs r0, #0 +1000b5fa: 5160 str r0, [r4, r5] + +1000b5fc : +1000b5fc: 1960 adds r0, r4, r5 +1000b5fe: 2100 movs r1, #0 +1000b600: 7481 strb r1, [r0, #18] +1000b602: 74c1 strb r1, [r0, #19] +1000b604: 6081 str r1, [r0, #8] +1000b606: 6041 str r1, [r0, #4] +1000b608: 300c adds r0, #12 +1000b60a: e8bd 4034 ldmia.w sp!, {r2, r4, r5, lr} +1000b60e: 2106 movs r1, #6 +1000b610: f002 bd90 b.w 1000e134 <__aeabi_memclr> + +1000b614 : +1000b614: b510 push {r4, lr} +1000b616: 2400 movs r4, #0 + +1000b618 : +1000b618: f8df 0510 ldr.w r0, [pc, #1296] ; 1000bb2c +1000b61c: 2114 movs r1, #20 +1000b61e: fb01 0004 mla r0, r1, r4, r0 +1000b622: 7c81 ldrb r1, [r0, #18] +1000b624: b1a1 cbz r1, 1000b650 +1000b626: 7cc1 ldrb r1, [r0, #19] +1000b628: 1c49 adds r1, r1, #1 +1000b62a: 74c1 strb r1, [r0, #19] +1000b62c: b2c9 uxtb r1, r1 +1000b62e: 29f0 cmp r1, #240 ; 0xf0 +1000b630: da05 bge.n 1000b63e +1000b632: 7c81 ldrb r1, [r0, #18] +1000b634: 2901 cmp r1, #1 +1000b636: d106 bne.n 1000b646 +1000b638: 7cc1 ldrb r1, [r0, #19] +1000b63a: 2902 cmp r1, #2 +1000b63c: db03 blt.n 1000b646 + +1000b63e : +1000b63e: 4620 mov r0, r4 +1000b640: f7ff ffd0 bl 1000b5e4 +1000b644: e004 b.n 1000b650 + +1000b646 : +1000b646: 7c81 ldrb r1, [r0, #18] +1000b648: 2903 cmp r1, #3 +1000b64a: bf04 itt eq +1000b64c: 2102 moveq r1, #2 +1000b64e: 7481 strbeq r1, [r0, #18] + +1000b650 : +1000b650: 1c64 adds r4, r4, #1 +1000b652: 2c0a cmp r4, #10 +1000b654: dbe0 blt.n 1000b618 +1000b656: bd10 pop {r4, pc} + +1000b658 : +1000b658: e92d 4ff1 stmdb sp!, {r0, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1000b65c: 200a movs r0, #10 +1000b65e: f04f 0800 mov.w r8, #0 +1000b662: b082 sub sp, #8 +1000b664: 220a movs r2, #10 +1000b666: 4603 mov r3, r0 +1000b668: 46c1 mov r9, r8 +1000b66a: 4682 mov sl, r0 +1000b66c: 46c6 mov lr, r8 +1000b66e: 4644 mov r4, r8 + +1000b670 : +1000b670: 2614 movs r6, #20 +1000b672: fb06 f504 mul.w r5, r6, r4 +1000b676: 9500 str r5, [sp, #0] +1000b678: fa4f fc84 sxtb.w ip, r4 +1000b67c: f8df 64ac ldr.w r6, [pc, #1196] ; 1000bb2c +1000b680: 4435 add r5, r6 +1000b682: 2b0a cmp r3, #10 +1000b684: 7cae ldrb r6, [r5, #18] +1000b686: bf04 itt eq +1000b688: 2e00 cmpeq r6, #0 +1000b68a: 4663 moveq r3, ip +1000b68c: d021 beq.n 1000b6d2 +1000b68e: b306 cbz r6, 1000b6d2 +1000b690: 9f02 ldr r7, [sp, #8] +1000b692: b127 cbz r7, 1000b69e +1000b694: 683f ldr r7, [r7, #0] +1000b696: f8d5 b004 ldr.w fp, [r5, #4] +1000b69a: 455f cmp r7, fp +1000b69c: d045 beq.n 1000b72a + +1000b69e : +1000b69e: 2e01 cmp r6, #1 +1000b6a0: d110 bne.n 1000b6c4 +1000b6a2: 9f00 ldr r7, [sp, #0] +1000b6a4: f8df 6484 ldr.w r6, [pc, #1156] ; 1000bb2c +1000b6a8: 59be ldr r6, [r7, r6] +1000b6aa: 7ced ldrb r5, [r5, #19] +1000b6ac: 2e00 cmp r6, #0 +1000b6ae: d004 beq.n 1000b6ba +1000b6b0: 4575 cmp r5, lr +1000b6b2: d30e bcc.n 1000b6d2 +1000b6b4: 46e2 mov sl, ip +1000b6b6: 46ae mov lr, r5 +1000b6b8: e00b b.n 1000b6d2 + +1000b6ba : +1000b6ba: 4545 cmp r5, r8 +1000b6bc: d309 bcc.n 1000b6d2 +1000b6be: 4660 mov r0, ip +1000b6c0: 46a8 mov r8, r5 +1000b6c2: e006 b.n 1000b6d2 + +1000b6c4 : +1000b6c4: 2e02 cmp r6, #2 +1000b6c6: db04 blt.n 1000b6d2 +1000b6c8: 7ced ldrb r5, [r5, #19] +1000b6ca: 454d cmp r5, r9 +1000b6cc: bf24 itt cs +1000b6ce: 4662 movcs r2, ip +1000b6d0: 46a9 movcs r9, r5 + +1000b6d2 : +1000b6d2: 1c64 adds r4, r4, #1 +1000b6d4: b2e4 uxtb r4, r4 +1000b6d6: 2c0a cmp r4, #10 +1000b6d8: dbca blt.n 1000b670 +1000b6da: 078c lsls r4, r1, #30 +1000b6dc: d403 bmi.n 1000b6e6 +1000b6de: 2b0a cmp r3, #10 +1000b6e0: d104 bne.n 1000b6ec +1000b6e2: 07c9 lsls r1, r1, #31 +1000b6e4: d406 bmi.n 1000b6f4 + +1000b6e6 : +1000b6e6: f04f 30ff mov.w r0, #4294967295 +1000b6ea: e01f b.n 1000b72c + +1000b6ec : +1000b6ec: 2b0a cmp r3, #10 +1000b6ee: bfb8 it lt +1000b6f0: b2dc uxtblt r4, r3 +1000b6f2: db0f blt.n 1000b714 + +1000b6f4 : +1000b6f4: 2a0a cmp r2, #10 +1000b6f6: bfb8 it lt +1000b6f8: b2d4 uxtblt r4, r2 +1000b6fa: db08 blt.n 1000b70e +1000b6fc: 280a cmp r0, #10 +1000b6fe: bfb8 it lt +1000b700: b2c4 uxtblt r4, r0 +1000b702: db04 blt.n 1000b70e +1000b704: f1ba 0f0a cmp.w sl, #10 +1000b708: daed bge.n 1000b6e6 +1000b70a: fa5f f48a uxtb.w r4, sl + +1000b70e : +1000b70e: 4620 mov r0, r4 +1000b710: f7ff ff68 bl 1000b5e4 + +1000b714 : +1000b714: f8df 0414 ldr.w r0, [pc, #1044] ; 1000bb2c +1000b718: 2114 movs r1, #20 +1000b71a: fb01 0004 mla r0, r1, r4, r0 +1000b71e: 9902 ldr r1, [sp, #8] +1000b720: b109 cbz r1, 1000b726 +1000b722: 6809 ldr r1, [r1, #0] +1000b724: 6041 str r1, [r0, #4] + +1000b726 : +1000b726: 2100 movs r1, #0 +1000b728: 74c1 strb r1, [r0, #19] + +1000b72a : +1000b72a: b260 sxtb r0, r4 + +1000b72c : +1000b72c: e8bd 8ffe ldmia.w sp!, {r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1000b730 : +1000b730: b5f8 push {r3, r4, r5, r6, r7, lr} +1000b732: 460d mov r5, r1 +1000b734: 4604 mov r4, r0 +1000b736: 686f ldr r7, [r5, #4] +1000b738: 4616 mov r6, r2 +1000b73a: 4619 mov r1, r3 +1000b73c: 2206 movs r2, #6 +1000b73e: 4638 mov r0, r7 +1000b740: f000 fe02 bl 1000c348 +1000b744: 2206 movs r2, #6 +1000b746: 4631 mov r1, r6 +1000b748: 1db8 adds r0, r7, #6 +1000b74a: f000 fdfd bl 1000c348 +1000b74e: 2008 movs r0, #8 +1000b750: 81b8 strh r0, [r7, #12] +1000b752: 4629 mov r1, r5 +1000b754: 69a2 ldr r2, [r4, #24] +1000b756: 4620 mov r0, r4 +1000b758: e8bd 40f8 ldmia.w sp!, {r3, r4, r5, r6, r7, lr} + +1000b75c <__iar_annotation$$tailcall>: +1000b75c: 4710 bx r2 + +1000b75e : +1000b75e: b538 push {r3, r4, r5, lr} +1000b760: 4604 mov r4, r0 +1000b762: 2500 movs r5, #0 + +1000b764 : +1000b764: f8df 03c4 ldr.w r0, [pc, #964] ; 1000bb2c +1000b768: 2114 movs r1, #20 +1000b76a: fb01 0005 mla r0, r1, r5, r0 +1000b76e: 7c81 ldrb r1, [r0, #18] +1000b770: b129 cbz r1, 1000b77e +1000b772: 6880 ldr r0, [r0, #8] +1000b774: 42a0 cmp r0, r4 +1000b776: bf04 itt eq +1000b778: 4628 moveq r0, r5 +1000b77a: f7ff ff33 bleq 1000b5e4 + +1000b77e : +1000b77e: 1c6d adds r5, r5, #1 +1000b780: 2d0a cmp r5, #10 +1000b782: dbef blt.n 1000b764 +1000b784: bd31 pop {r0, r4, r5, pc} + +1000b786 : +1000b786: e92d 4ff2 stmdb sp!, {r1, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1000b78a: b084 sub sp, #16 +1000b78c: 0004 movs r4, r0 +1000b78e: 4690 mov r8, r2 +1000b790: f000 80b4 beq.w 1000b8fc +1000b794: f8b8 000a ldrh.w r0, [r8, #10] +1000b798: 282a cmp r0, #42 ; 0x2a +1000b79a: db72 blt.n 1000b882 +1000b79c: f8d8 b004 ldr.w fp, [r8, #4] +1000b7a0: f10b 070e add.w r7, fp, #14 +1000b7a4: 8838 ldrh r0, [r7, #0] +1000b7a6: f5b0 7f80 cmp.w r0, #256 ; 0x100 +1000b7aa: bf04 itt eq +1000b7ac: 7938 ldrbeq r0, [r7, #4] +1000b7ae: 2806 cmpeq r0, #6 +1000b7b0: d167 bne.n 1000b882 +1000b7b2: 7978 ldrb r0, [r7, #5] +1000b7b4: 2804 cmp r0, #4 +1000b7b6: bf04 itt eq +1000b7b8: 8878 ldrheq r0, [r7, #2] +1000b7ba: 2808 cmpeq r0, #8 +1000b7bc: d161 bne.n 1000b882 +1000b7be: 4639 mov r1, r7 +1000b7c0: 4620 mov r0, r4 +1000b7c2: f002 fc69 bl 1000e098 +1000b7c6: 2204 movs r2, #4 +1000b7c8: f107 010e add.w r1, r7, #14 +1000b7cc: a800 add r0, sp, #0 +1000b7ce: f000 fdbb bl 1000c348 +1000b7d2: 2204 movs r2, #4 +1000b7d4: f107 0118 add.w r1, r7, #24 +1000b7d8: a802 add r0, sp, #8 +1000b7da: f000 fdb5 bl 1000c348 +1000b7de: 1d20 adds r0, r4, #4 +1000b7e0: bf1c itt ne +1000b7e2: 6860 ldrne r0, [r4, #4] +1000b7e4: 2800 cmpne r0, #0 +1000b7e6: d005 beq.n 1000b7f4 +1000b7e8: 9902 ldr r1, [sp, #8] +1000b7ea: 4281 cmp r1, r0 +1000b7ec: d102 bne.n 1000b7f4 +1000b7ee: 2501 movs r5, #1 +1000b7f0: 46a9 mov r9, r5 +1000b7f2: e002 b.n 1000b7fa + +1000b7f4 : +1000b7f4: 2500 movs r5, #0 +1000b7f6: f04f 0902 mov.w r9, #2 + +1000b7fa : +1000b7fa: f107 0008 add.w r0, r7, #8 +1000b7fe: 9001 str r0, [sp, #4] +1000b800: 9800 ldr r0, [sp, #0] +1000b802: b398 cbz r0, 1000b86c +1000b804: 9800 ldr r0, [sp, #0] +1000b806: 4621 mov r1, r4 +1000b808: f000 fdb0 bl 1000c36c +1000b80c: bb70 cbnz r0, 1000b86c +1000b80e: 9800 ldr r0, [sp, #0] +1000b810: f000 00f0 and.w r0, r0, #240 ; 0xf0 +1000b814: 28e0 cmp r0, #224 ; 0xe0 +1000b816: d029 beq.n 1000b86c +1000b818: 4649 mov r1, r9 +1000b81a: a800 add r0, sp, #0 +1000b81c: f7ff ff1c bl 1000b658 +1000b820: 4681 mov r9, r0 +1000b822: f1b9 0f00 cmp.w r9, #0 +1000b826: d421 bmi.n 1000b86c +1000b828: f8df a300 ldr.w sl, [pc, #768] ; 1000bb2c +1000b82c: 2014 movs r0, #20 +1000b82e: fb00 a609 mla r6, r0, r9, sl +1000b832: 2002 movs r0, #2 +1000b834: 74b0 strb r0, [r6, #18] +1000b836: 60b4 str r4, [r6, #8] +1000b838: 2206 movs r2, #6 +1000b83a: 9901 ldr r1, [sp, #4] +1000b83c: f106 000c add.w r0, r6, #12 +1000b840: f000 fd82 bl 1000c348 +1000b844: 2000 movs r0, #0 +1000b846: 74f0 strb r0, [r6, #19] +1000b848: 2014 movs r0, #20 +1000b84a: fb00 a009 mla r0, r0, r9, sl +1000b84e: 6806 ldr r6, [r0, #0] +1000b850: b166 cbz r6, 1000b86c +1000b852: 2114 movs r1, #20 +1000b854: fb01 a109 mla r1, r1, r9, sl +1000b858: 2000 movs r0, #0 +1000b85a: 6008 str r0, [r1, #0] +1000b85c: f104 022b add.w r2, r4, #43 ; 0x2b +1000b860: 9b01 ldr r3, [sp, #4] +1000b862: f000 f84e bl 1000b902 + +1000b866 : +1000b866: 4630 mov r0, r6 +1000b868: f7fc ffbe bl 100087e8 + +1000b86c : +1000b86c: 88f8 ldrh r0, [r7, #6] +1000b86e: f5b0 7f80 cmp.w r0, #256 ; 0x100 +1000b872: d007 beq.n 1000b884 +1000b874: f5b0 7f00 cmp.w r0, #512 ; 0x200 +1000b878: bf02 ittt eq +1000b87a: a900 addeq r1, sp, #0 +1000b87c: 4620 moveq r0, r4 +1000b87e: f001 fe14 bleq 1000d4aa + +1000b882 : +1000b882: e038 b.n 1000b8f6 + +1000b884 : +1000b884: 2d00 cmp r5, #0 +1000b886: d036 beq.n 1000b8f6 +1000b888: 2002 movs r0, #2 +1000b88a: f000 fe5c bl 1000c546 +1000b88e: 80f8 strh r0, [r7, #6] +1000b890: 2204 movs r2, #4 +1000b892: f107 010e add.w r1, r7, #14 +1000b896: f107 0018 add.w r0, r7, #24 +1000b89a: f000 fd55 bl 1000c348 +1000b89e: 2204 movs r2, #4 +1000b8a0: 1d21 adds r1, r4, #4 +1000b8a2: f107 000e add.w r0, r7, #14 +1000b8a6: f000 fd4f bl 1000c348 +1000b8aa: 6860 ldr r0, [r4, #4] +1000b8ac: b280 uxth r0, r0 +1000b8ae: f64f 61a9 movw r1, #65193 ; 0xfea9 +1000b8b2: 4288 cmp r0, r1 +1000b8b4: bf0c ite eq +1000b8b6: f20f 35e4 addweq r5, pc, #996 ; 0x3e4 +1000b8ba: f107 0508 addne.w r5, r7, #8 +1000b8be: 2206 movs r2, #6 +1000b8c0: f107 0108 add.w r1, r7, #8 +1000b8c4: f107 0012 add.w r0, r7, #18 +1000b8c8: f000 fd3e bl 1000c348 +1000b8cc: 2206 movs r2, #6 +1000b8ce: 4629 mov r1, r5 +1000b8d0: 4658 mov r0, fp +1000b8d2: f000 fd39 bl 1000c348 +1000b8d6: 9904 ldr r1, [sp, #16] +1000b8d8: 2206 movs r2, #6 +1000b8da: f107 0008 add.w r0, r7, #8 +1000b8de: f000 fd33 bl 1000c348 +1000b8e2: 9904 ldr r1, [sp, #16] +1000b8e4: 2206 movs r2, #6 +1000b8e6: f10b 0006 add.w r0, fp, #6 +1000b8ea: f000 fd2d bl 1000c348 +1000b8ee: 69a2 ldr r2, [r4, #24] +1000b8f0: 4641 mov r1, r8 +1000b8f2: 4620 mov r0, r4 +1000b8f4: 4790 blx r2 + +1000b8f6 : +1000b8f6: 4640 mov r0, r8 +1000b8f8: f7fc ff76 bl 100087e8 + +1000b8fc : +1000b8fc: b005 add sp, #20 +1000b8fe: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1000b902 : +1000b902: 4631 mov r1, r6 + +1000b904 : +1000b904: 4620 mov r0, r4 +1000b906: e713 b.n 1000b730 + +1000b908 : +1000b908: b570 push {r4, r5, r6, lr} +1000b90a: 4604 mov r4, r0 +1000b90c: 460d mov r5, r1 +1000b90e: 4887 ldr r0, [pc, #540] ; (1000bb2c ) +1000b910: 2114 movs r1, #20 +1000b912: fb01 0602 mla r6, r1, r2, r0 +1000b916: 7cb0 ldrb r0, [r6, #18] +1000b918: 2802 cmp r0, #2 +1000b91a: d109 bne.n 1000b930 +1000b91c: 7cf0 ldrb r0, [r6, #19] +1000b91e: 28e4 cmp r0, #228 ; 0xe4 +1000b920: db06 blt.n 1000b930 +1000b922: 1d31 adds r1, r6, #4 +1000b924: 4620 mov r0, r4 +1000b926: f000 f95f bl 1000bbe8 +1000b92a: b908 cbnz r0, 1000b930 +1000b92c: 2003 movs r0, #3 +1000b92e: 74b0 strb r0, [r6, #18] + +1000b930 : +1000b930: f106 030c add.w r3, r6, #12 +1000b934: f104 022b add.w r2, r4, #43 ; 0x2b +1000b938: 4629 mov r1, r5 +1000b93a: 4620 mov r0, r4 +1000b93c: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +1000b940: e6f6 b.n 1000b730 + +1000b942 : +1000b942: b5f0 push {r4, r5, r6, r7, lr} +1000b944: 4604 mov r4, r0 +1000b946: 460d mov r5, r1 +1000b948: 4616 mov r6, r2 +1000b94a: b083 sub sp, #12 +1000b94c: 4637 mov r7, r6 +1000b94e: 210e movs r1, #14 +1000b950: 4628 mov r0, r5 +1000b952: f7fc ff18 bl 10008786 +1000b956: b110 cbz r0, 1000b95e +1000b958: f06f 0001 mvn.w r0, #1 +1000b95c: bdfe pop {r1, r2, r3, r4, r5, r6, r7, pc} + +1000b95e : +1000b95e: 6830 ldr r0, [r6, #0] +1000b960: 4621 mov r1, r4 +1000b962: f000 fd03 bl 1000c36c +1000b966: b138 cbz r0, 1000b978 +1000b968: f20f 3330 addw r3, pc, #816 ; 0x330 + +1000b96c : +1000b96c: f104 022b add.w r2, r4, #43 ; 0x2b +1000b970: 4629 mov r1, r5 +1000b972: f7ff ffc7 bl 1000b904 + +1000b976 : +1000b976: bdfe pop {r1, r2, r3, r4, r5, r6, r7, pc} + +1000b978 : +1000b978: 6830 ldr r0, [r6, #0] +1000b97a: f000 01f0 and.w r1, r0, #240 ; 0xf0 +1000b97e: 29e0 cmp r1, #224 ; 0xe0 +1000b980: d115 bne.n 1000b9ae +1000b982: 2001 movs r0, #1 +1000b984: f88d 0000 strb.w r0, [sp] +1000b988: ab00 add r3, sp, #0 +1000b98a: 2000 movs r0, #0 +1000b98c: f88d 0001 strb.w r0, [sp, #1] +1000b990: 205e movs r0, #94 ; 0x5e +1000b992: f88d 0002 strb.w r0, [sp, #2] +1000b996: 7870 ldrb r0, [r6, #1] +1000b998: f000 007f and.w r0, r0, #127 ; 0x7f +1000b99c: f88d 0003 strb.w r0, [sp, #3] +1000b9a0: 78b0 ldrb r0, [r6, #2] +1000b9a2: f88d 0004 strb.w r0, [sp, #4] +1000b9a6: 78f0 ldrb r0, [r6, #3] +1000b9a8: f88d 0005 strb.w r0, [sp, #5] +1000b9ac: e7de b.n 1000b96c + +1000b9ae : +1000b9ae: 68a1 ldr r1, [r4, #8] +1000b9b0: 6863 ldr r3, [r4, #4] +1000b9b2: ea01 0200 and.w r2, r1, r0 +1000b9b6: 4019 ands r1, r3 +1000b9b8: 428a cmp r2, r1 +1000b9ba: bf1e ittt ne +1000b9bc: f64f 61a9 movwne r1, #65193 ; 0xfea9 +1000b9c0: b280 uxthne r0, r0 +1000b9c2: 4288 cmpne r0, r1 +1000b9c4: bf1f itttt ne +1000b9c6: 6868 ldrne r0, [r5, #4] +1000b9c8: f8d0 001a ldrne.w r0, [r0, #26] +1000b9cc: b280 uxthne r0, r0 +1000b9ce: 4288 cmpne r0, r1 +1000b9d0: d007 beq.n 1000b9e2 +1000b9d2: f114 000c adds.w r0, r4, #12 +1000b9d6: bf1c itt ne +1000b9d8: 68e0 ldrne r0, [r4, #12] +1000b9da: 2800 cmpne r0, #0 +1000b9dc: d012 beq.n 1000ba04 +1000b9de: f104 070c add.w r7, r4, #12 + +1000b9e2 : +1000b9e2: 4853 ldr r0, [pc, #332] ; (1000bb30 ) +1000b9e4: 4b51 ldr r3, [pc, #324] ; (1000bb2c ) +1000b9e6: 7802 ldrb r2, [r0, #0] +1000b9e8: 2114 movs r1, #20 +1000b9ea: f000 f824 bl 1000ba36 + +1000b9ee : +1000b9ee: db0c blt.n 1000ba0a +1000b9f0: f8d7 c000 ldr.w ip, [r7] +1000b9f4: 6876 ldr r6, [r6, #4] +1000b9f6: 45b4 cmp ip, r6 +1000b9f8: d107 bne.n 1000ba0a + +1000b9fa : +1000b9fa: 4629 mov r1, r5 +1000b9fc: 4620 mov r0, r4 +1000b9fe: f7ff ff83 bl 1000b908 +1000ba02: bdfe pop {r1, r2, r3, r4, r5, r6, r7, pc} + +1000ba04 : +1000ba04: f06f 0003 mvn.w r0, #3 +1000ba08: bdfe pop {r1, r2, r3, r4, r5, r6, r7, pc} + +1000ba0a : +1000ba0a: 2200 movs r2, #0 + +1000ba0c : +1000ba0c: f000 f813 bl 1000ba36 + +1000ba10 : +1000ba10: db07 blt.n 1000ba22 +1000ba12: f8d7 c000 ldr.w ip, [r7] +1000ba16: 6876 ldr r6, [r6, #4] +1000ba18: 45b4 cmp ip, r6 +1000ba1a: d102 bne.n 1000ba22 +1000ba1c: 7002 strb r2, [r0, #0] +1000ba1e: b2d2 uxtb r2, r2 +1000ba20: e7eb b.n 1000b9fa + +1000ba22 : +1000ba22: 1c52 adds r2, r2, #1 +1000ba24: b252 sxtb r2, r2 +1000ba26: 2a0a cmp r2, #10 +1000ba28: dbf0 blt.n 1000ba0c +1000ba2a: 462a mov r2, r5 +1000ba2c: 4639 mov r1, r7 +1000ba2e: 4620 mov r0, r4 +1000ba30: f000 f808 bl 1000ba44 +1000ba34: bdfe pop {r1, r2, r3, r4, r5, r6, r7, pc} + +1000ba36 : +1000ba36: fb01 3602 mla r6, r1, r2, r3 +1000ba3a: f896 c012 ldrb.w ip, [r6, #18] +1000ba3e: f1bc 0f02 cmp.w ip, #2 +1000ba42: 4770 bx lr + +1000ba44 : +1000ba44: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1000ba48: 4604 mov r4, r0 +1000ba4a: f104 002b add.w r0, r4, #43 ; 0x2b +1000ba4e: 460d mov r5, r1 +1000ba50: 9000 str r0, [sp, #0] +1000ba52: f04f 3bff mov.w fp, #4294967295 +1000ba56: 6828 ldr r0, [r5, #0] +1000ba58: 4616 mov r6, r2 +1000ba5a: 46da mov sl, fp +1000ba5c: 4621 mov r1, r4 +1000ba5e: f000 fc85 bl 1000c36c +1000ba62: b938 cbnz r0, 1000ba74 +1000ba64: 6828 ldr r0, [r5, #0] +1000ba66: f000 01f0 and.w r1, r0, #240 ; 0xf0 +1000ba6a: 29e0 cmp r1, #224 ; 0xe0 +1000ba6c: bf18 it ne +1000ba6e: 2d00 cmpne r5, #0 +1000ba70: d000 beq.n 1000ba74 +1000ba72: b910 cbnz r0, 1000ba7a + +1000ba74 : +1000ba74: f06f 000d mvn.w r0, #13 +1000ba78: e041 b.n 1000bafe + +1000ba7a : +1000ba7a: 2101 movs r1, #1 +1000ba7c: 4628 mov r0, r5 +1000ba7e: f7ff fdeb bl 1000b658 +1000ba82: 4680 mov r8, r0 +1000ba84: f1b8 0f00 cmp.w r8, #0 +1000ba88: d439 bmi.n 1000bafe +1000ba8a: f8df 90a0 ldr.w r9, [pc, #160] ; 1000bb2c +1000ba8e: 2014 movs r0, #20 +1000ba90: fb00 9708 mla r7, r0, r8, r9 +1000ba94: 7cb8 ldrb r0, [r7, #18] +1000ba96: b908 cbnz r0, 1000ba9c +1000ba98: 2001 movs r0, #1 +1000ba9a: 74b8 strb r0, [r7, #18] + +1000ba9c : +1000ba9c: 7cb8 ldrb r0, [r7, #18] +1000ba9e: 2801 cmp r0, #1 +1000baa0: bf18 it ne +1000baa2: 2e00 cmpne r6, #0 +1000baa4: d105 bne.n 1000bab2 +1000baa6: 4629 mov r1, r5 +1000baa8: 4620 mov r0, r4 +1000baaa: f000 f89d bl 1000bbe8 +1000baae: 4682 mov sl, r0 +1000bab0: b326 cbz r6, 1000bafc + +1000bab2 : +1000bab2: 7cb8 ldrb r0, [r7, #18] +1000bab4: 2802 cmp r0, #2 +1000bab6: db09 blt.n 1000bacc +1000bab8: 481d ldr r0, [pc, #116] ; (1000bb30 ) +1000baba: 9a00 ldr r2, [sp, #0] +1000babc: f880 8000 strb.w r8, [r0] +1000bac0: f107 030c add.w r3, r7, #12 +1000bac4: f7ff ff1d bl 1000b902 + +1000bac8 : +1000bac8: 4682 mov sl, r0 +1000baca: e017 b.n 1000bafc + +1000bacc : +1000bacc: 2801 cmp r0, #1 +1000bace: d115 bne.n 1000bafc +1000bad0: 4630 mov r0, r6 +1000bad2: e000 b.n 1000bad6 + +1000bad4 : +1000bad4: 6800 ldr r0, [r0, #0] + +1000bad6 : +1000bad6: b1a0 cbz r0, 1000bb02 +1000bad8: 7b01 ldrb r1, [r0, #12] +1000bada: 2901 cmp r1, #1 +1000badc: d0fa beq.n 1000bad4 +1000bade: 8901 ldrh r1, [r0, #8] +1000bae0: 2200 movs r2, #0 +1000bae2: 2003 movs r0, #3 +1000bae4: f7fc fd70 bl 100085c8 +1000bae8: 0004 movs r4, r0 +1000baea: d006 beq.n 1000bafa +1000baec: 4631 mov r1, r6 +1000baee: f7fc fed9 bl 100088a4 +1000baf2: b160 cbz r0, 1000bb0e +1000baf4: 4620 mov r0, r4 +1000baf6: f7fc fe77 bl 100087e8 + +1000bafa : +1000bafa: 46da mov sl, fp + +1000bafc : +1000bafc: 4650 mov r0, sl + +1000bafe : +1000bafe: e8bd 8ff2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1000bb02 : +1000bb02: 4634 mov r4, r6 +1000bb04: 4620 mov r0, r4 +1000bb06: f7fc fea5 bl 10008854 +1000bb0a: 2c00 cmp r4, #0 +1000bb0c: d0f5 beq.n 1000bafa + +1000bb0e : +1000bb0e: 2014 movs r0, #20 +1000bb10: fb00 9008 mla r0, r0, r8, r9 +1000bb14: 6800 ldr r0, [r0, #0] +1000bb16: b108 cbz r0, 1000bb1c +1000bb18: f7fc fe66 bl 100087e8 + +1000bb1c : +1000bb1c: 2014 movs r0, #20 +1000bb1e: fb00 9008 mla r0, r0, r8, r9 +1000bb22: f04f 0a00 mov.w sl, #0 +1000bb26: 6004 str r4, [r0, #0] +1000bb28: e7e8 b.n 1000bafc + ... + +1000bb2c : +1000bb2c: 72d4 1004 .r.. + +1000bb30 : +1000bb30: 8b0e 1004 .... + +1000bb34 : +1000bb34: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1000bb38: 4681 mov r9, r0 +1000bb3a: 468a mov sl, r1 +1000bb3c: 4693 mov fp, r2 +1000bb3e: 4698 mov r8, r3 +1000bb40: 2200 movs r2, #0 +1000bb42: 212a movs r1, #42 ; 0x2a +1000bb44: 2003 movs r0, #3 +1000bb46: f7fc fd3f bl 100085c8 +1000bb4a: 0004 movs r4, r0 +1000bb4c: bf08 it eq +1000bb4e: f04f 30ff moveq.w r0, #4294967295 +1000bb52: d047 beq.n 1000bbe4 +1000bb54: 6865 ldr r5, [r4, #4] +1000bb56: 980d ldr r0, [sp, #52] ; 0x34 +1000bb58: f105 060e add.w r6, r5, #14 +1000bb5c: f000 fcf3 bl 1000c546 +1000bb60: 80f0 strh r0, [r6, #6] +1000bb62: f64f 61a9 movw r1, #65193 ; 0xfea9 +1000bb66: 9f0a ldr r7, [sp, #40] ; 0x28 +1000bb68: 6838 ldr r0, [r7, #0] +1000bb6a: b280 uxth r0, r0 +1000bb6c: 4288 cmp r0, r1 +1000bb6e: bf08 it eq +1000bb70: f20f 1b28 addweq fp, pc, #296 ; 0x128 +1000bb74: 2206 movs r2, #6 +1000bb76: 4641 mov r1, r8 +1000bb78: f106 0008 add.w r0, r6, #8 +1000bb7c: f000 fbe4 bl 1000c348 +1000bb80: 990b ldr r1, [sp, #44] ; 0x2c +1000bb82: 2206 movs r2, #6 +1000bb84: f106 0012 add.w r0, r6, #18 +1000bb88: f000 fbde bl 1000c348 +1000bb8c: 2206 movs r2, #6 +1000bb8e: 4659 mov r1, fp +1000bb90: 4628 mov r0, r5 +1000bb92: f000 fbd9 bl 1000c348 +1000bb96: 2206 movs r2, #6 +1000bb98: 4651 mov r1, sl +1000bb9a: 1da8 adds r0, r5, #6 +1000bb9c: f000 fbd4 bl 1000c348 +1000bba0: 2204 movs r2, #4 +1000bba2: 4639 mov r1, r7 +1000bba4: f106 000e add.w r0, r6, #14 +1000bba8: f000 fbce bl 1000c348 +1000bbac: 990c ldr r1, [sp, #48] ; 0x30 +1000bbae: 2204 movs r2, #4 +1000bbb0: f106 0018 add.w r0, r6, #24 +1000bbb4: f000 fbc8 bl 1000c348 +1000bbb8: f44f 7080 mov.w r0, #256 ; 0x100 +1000bbbc: 8030 strh r0, [r6, #0] +1000bbbe: 4621 mov r1, r4 +1000bbc0: 2008 movs r0, #8 +1000bbc2: 8070 strh r0, [r6, #2] +1000bbc4: 2006 movs r0, #6 +1000bbc6: 7130 strb r0, [r6, #4] +1000bbc8: 2004 movs r0, #4 +1000bbca: 7170 strb r0, [r6, #5] +1000bbcc: f44f 60c1 mov.w r0, #1544 ; 0x608 +1000bbd0: 81a8 strh r0, [r5, #12] +1000bbd2: 4648 mov r0, r9 +1000bbd4: f8d9 2018 ldr.w r2, [r9, #24] +1000bbd8: 4790 blx r2 +1000bbda: 4605 mov r5, r0 +1000bbdc: 4620 mov r0, r4 +1000bbde: f7fc fe03 bl 100087e8 +1000bbe2: 4628 mov r0, r5 + +1000bbe4 : +1000bbe4: e8bd 8ff2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1000bbe8 : +1000bbe8: b500 push {lr} +1000bbea: b085 sub sp, #20 +1000bbec: 2201 movs r2, #1 +1000bbee: 9102 str r1, [sp, #8] +1000bbf0: 9203 str r2, [sp, #12] +1000bbf2: f100 032b add.w r3, r0, #43 ; 0x2b +1000bbf6: f20f 01ac addw r1, pc, #172 ; 0xac +1000bbfa: f20f 02a0 addw r2, pc, #160 ; 0xa0 +1000bbfe: 9101 str r1, [sp, #4] +1000bc00: 1d01 adds r1, r0, #4 +1000bc02: 9100 str r1, [sp, #0] +1000bc04: f100 012b add.w r1, r0, #43 ; 0x2b +1000bc08: f7ff ff94 bl 1000bb34 +1000bc0c: b005 add sp, #20 +1000bc0e: bd00 pop {pc} + +1000bc10 : +1000bc10: b570 push {r4, r5, r6, lr} +1000bc12: 4604 mov r4, r0 +1000bc14: 460d mov r5, r1 +1000bc16: 8960 ldrh r0, [r4, #10] +1000bc18: 280f cmp r0, #15 +1000bc1a: db3a blt.n 1000bc92 +1000bc1c: 6860 ldr r0, [r4, #4] +1000bc1e: 7801 ldrb r1, [r0, #0] +1000bc20: 8986 ldrh r6, [r0, #12] +1000bc22: 07ca lsls r2, r1, #31 +1000bc24: d515 bpl.n 1000bc52 +1000bc26: 2901 cmp r1, #1 +1000bc28: d109 bne.n 1000bc3e +1000bc2a: 7841 ldrb r1, [r0, #1] +1000bc2c: 2900 cmp r1, #0 +1000bc2e: bf04 itt eq +1000bc30: 7880 ldrbeq r0, [r0, #2] +1000bc32: 285e cmpeq r0, #94 ; 0x5e +1000bc34: d10d bne.n 1000bc52 +1000bc36: 7b60 ldrb r0, [r4, #13] +1000bc38: f040 0010 orr.w r0, r0, #16 +1000bc3c: e008 b.n 1000bc50 + +1000bc3e : +1000bc3e: 2206 movs r2, #6 +1000bc40: f20f 0158 addw r1, pc, #88 ; 0x58 +1000bc44: f000 fb7e bl 1000c344 +1000bc48: b918 cbnz r0, 1000bc52 +1000bc4a: 7b60 ldrb r0, [r4, #13] +1000bc4c: f040 0008 orr.w r0, r0, #8 + +1000bc50 : +1000bc50: 7360 strb r0, [r4, #13] + +1000bc52 : +1000bc52: 2e08 cmp r6, #8 +1000bc54: d003 beq.n 1000bc5e +1000bc56: f5b6 6fc1 cmp.w r6, #1544 ; 0x608 +1000bc5a: d00f beq.n 1000bc7c +1000bc5c: e019 b.n 1000bc92 + +1000bc5e : +1000bc5e: f895 0031 ldrb.w r0, [r5, #49] ; 0x31 +1000bc62: 0680 lsls r0, r0, #26 +1000bc64: d515 bpl.n 1000bc92 +1000bc66: f06f 010d mvn.w r1, #13 +1000bc6a: 4620 mov r0, r4 +1000bc6c: f7fc fd8b bl 10008786 +1000bc70: b978 cbnz r0, 1000bc92 +1000bc72: 4629 mov r1, r5 +1000bc74: 4620 mov r0, r4 +1000bc76: f000 f833 bl 1000bce0 +1000bc7a: e00d b.n 1000bc98 + +1000bc7c : +1000bc7c: f895 0031 ldrb.w r0, [r5, #49] ; 0x31 +1000bc80: 0680 lsls r0, r0, #26 +1000bc82: d506 bpl.n 1000bc92 +1000bc84: 4622 mov r2, r4 +1000bc86: f105 012b add.w r1, r5, #43 ; 0x2b +1000bc8a: 4628 mov r0, r5 +1000bc8c: f7ff fd7b bl 1000b786 +1000bc90: e002 b.n 1000bc98 + +1000bc92 : +1000bc92: 4620 mov r0, r4 +1000bc94: f7fc fda8 bl 100087e8 + +1000bc98 : +1000bc98: 2000 movs r0, #0 +1000bc9a: bd70 pop {r4, r5, r6, pc} + +1000bc9c : +1000bc9c: ffff ffff ffff 0000 ........ + +1000bca4 : + ... + +1000bcac : +1000bcac: b510 push {r4, lr} +1000bcae: 4994 ldr r1, [pc, #592] ; (1000bf00 ) + +1000bcb0 : +1000bcb0: 6809 ldr r1, [r1, #0] +1000bcb2: b161 cbz r1, 1000bcce +1000bcb4: f891 2031 ldrb.w r2, [r1, #49] ; 0x31 +1000bcb8: 07d2 lsls r2, r2, #31 +1000bcba: d5f9 bpl.n 1000bcb0 +1000bcbc: 688a ldr r2, [r1, #8] +1000bcbe: 6803 ldr r3, [r0, #0] +1000bcc0: 684c ldr r4, [r1, #4] +1000bcc2: 4013 ands r3, r2 +1000bcc4: 4022 ands r2, r4 +1000bcc6: 4293 cmp r3, r2 +1000bcc8: d1f2 bne.n 1000bcb0 +1000bcca: 4608 mov r0, r1 +1000bccc: bd10 pop {r4, pc} + +1000bcce : +1000bcce: 488d ldr r0, [pc, #564] ; (1000bf04 ) +1000bcd0: 6800 ldr r0, [r0, #0] +1000bcd2: b118 cbz r0, 1000bcdc +1000bcd4: f890 1031 ldrb.w r1, [r0, #49] ; 0x31 +1000bcd8: 07c9 lsls r1, r1, #31 +1000bcda: d400 bmi.n 1000bcde + +1000bcdc : +1000bcdc: 2000 movs r0, #0 + +1000bcde : +1000bcde: bd10 pop {r4, pc} + +1000bce0 : +1000bce0: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1000bce4: 4604 mov r4, r0 +1000bce6: 4688 mov r8, r1 +1000bce8: 6866 ldr r6, [r4, #4] +1000bcea: 7830 ldrb r0, [r6, #0] +1000bcec: 0901 lsrs r1, r0, #4 +1000bcee: 2904 cmp r1, #4 +1000bcf0: d15c bne.n 1000bdac +1000bcf2: f000 000f and.w r0, r0, #15 +1000bcf6: ea4f 0980 mov.w r9, r0, lsl #2 +1000bcfa: 8870 ldrh r0, [r6, #2] +1000bcfc: f000 fc28 bl 1000c550 +1000bd00: 4607 mov r7, r0 +1000bd02: 8960 ldrh r0, [r4, #10] +1000bd04: 4548 cmp r0, r9 +1000bd06: bf24 itt cs +1000bd08: 8920 ldrhcs r0, [r4, #8] +1000bd0a: 42b8 cmpcs r0, r7 +1000bd0c: d34e bcc.n 1000bdac +1000bd0e: 4649 mov r1, r9 +1000bd10: 4630 mov r0, r6 +1000bd12: f000 fc98 bl 1000c646 +1000bd16: 2800 cmp r0, #0 +1000bd18: d148 bne.n 1000bdac +1000bd1a: 4639 mov r1, r7 +1000bd1c: 4620 mov r0, r4 +1000bd1e: f7fc fd0b bl 10008738 +1000bd22: 4f79 ldr r7, [pc, #484] ; (1000bf08 ) +1000bd24: 6930 ldr r0, [r6, #16] +1000bd26: f8df b1d8 ldr.w fp, [pc, #472] ; 1000bf00 +1000bd2a: 60f8 str r0, [r7, #12] +1000bd2c: f04f 0a01 mov.w sl, #1 +1000bd30: 68f0 ldr r0, [r6, #12] +1000bd32: 60b8 str r0, [r7, #8] +1000bd34: 4645 mov r5, r8 + +1000bd36 : +1000bd36: f895 0031 ldrb.w r0, [r5, #49] ; 0x31 +1000bd3a: 07c0 lsls r0, r0, #31 +1000bd3c: d511 bpl.n 1000bd62 +1000bd3e: 1d28 adds r0, r5, #4 +1000bd40: bf1c itt ne +1000bd42: 6869 ldrne r1, [r5, #4] +1000bd44: 2900 cmpne r1, #0 +1000bd46: d00c beq.n 1000bd62 +1000bd48: 68f8 ldr r0, [r7, #12] +1000bd4a: 4288 cmp r0, r1 +1000bd4c: d017 beq.n 1000bd7e +1000bd4e: 4629 mov r1, r5 +1000bd50: f000 fb0c bl 1000c36c +1000bd54: b998 cbnz r0, 1000bd7e +1000bd56: 6a68 ldr r0, [r5, #36] ; 0x24 +1000bd58: b118 cbz r0, 1000bd62 +1000bd5a: 68f9 ldr r1, [r7, #12] +1000bd5c: 6800 ldr r0, [r0, #0] +1000bd5e: 4281 cmp r1, r0 +1000bd60: d00d beq.n 1000bd7e + +1000bd62 : +1000bd62: f1ba 0f00 cmp.w sl, #0 +1000bd66: bf1a itte ne +1000bd68: f04f 0a00 movne.w sl, #0 +1000bd6c: f8db 5000 ldrne.w r5, [fp] +1000bd70: 682d ldreq r5, [r5, #0] +1000bd72: 4545 cmp r5, r8 +1000bd74: bf08 it eq +1000bd76: 682d ldreq r5, [r5, #0] +1000bd78: 2d00 cmp r5, #0 +1000bd7a: d1dc bne.n 1000bd36 +1000bd7c: e000 b.n 1000bd80 + +1000bd7e : +1000bd7e: b94d cbnz r5, 1000bd94 + +1000bd80 : +1000bd80: 7a70 ldrb r0, [r6, #9] +1000bd82: 2811 cmp r0, #17 +1000bd84: bf01 itttt eq +1000bd86: eb09 0006 addeq.w r0, r9, r6 +1000bd8a: 8840 ldrheq r0, [r0, #2] +1000bd8c: f5b0 4f88 cmpeq.w r0, #17408 ; 0x4400 +1000bd90: 4645 moveq r5, r8 +1000bd92: d00a beq.n 1000bdaa + +1000bd94 : +1000bd94: 68b8 ldr r0, [r7, #8] +1000bd96: b140 cbz r0, 1000bdaa +1000bd98: 4641 mov r1, r8 +1000bd9a: f000 fae7 bl 1000c36c +1000bd9e: b928 cbnz r0, 1000bdac +1000bda0: 7a38 ldrb r0, [r7, #8] +1000bda2: f000 00f0 and.w r0, r0, #240 ; 0xf0 +1000bda6: 28e0 cmp r0, #224 ; 0xe0 +1000bda8: d000 beq.n 1000bdac + +1000bdaa : +1000bdaa: b91d cbnz r5, 1000bdb4 + +1000bdac : +1000bdac: 4620 mov r0, r4 +1000bdae: f7fc fd1b bl 100087e8 +1000bdb2: e009 b.n 1000bdc8 + +1000bdb4 : +1000bdb4: 88f0 ldrh r0, [r6, #6] +1000bdb6: f64f 713f movw r1, #65343 ; 0xff3f +1000bdba: 4208 tst r0, r1 +1000bdbc: d007 beq.n 1000bdce +1000bdbe: 4620 mov r0, r4 +1000bdc0: f001 f8d9 bl 1000cf76 +1000bdc4: 0004 movs r4, r0 +1000bdc6: d101 bne.n 1000bdcc + +1000bdc8 : +1000bdc8: 2000 movs r0, #0 +1000bdca: e034 b.n 1000be36 + +1000bdcc : +1000bdcc: 6866 ldr r6, [r4, #4] + +1000bdce : +1000bdce: f8c7 8000 str.w r8, [r7] +1000bdd2: 607e str r6, [r7, #4] +1000bdd4: 4641 mov r1, r8 +1000bdd6: 4620 mov r0, r4 +1000bdd8: f7fd fd7a bl 100098d0 +1000bddc: bb30 cbnz r0, 1000be2c +1000bdde: 7a70 ldrb r0, [r6, #9] +1000bde0: 2801 cmp r0, #1 +1000bde2: d00d beq.n 1000be00 +1000bde4: 2806 cmp r0, #6 +1000bde6: d006 beq.n 1000bdf6 +1000bde8: 2811 cmp r0, #17 +1000bdea: 4641 mov r1, r8 +1000bdec: d10d bne.n 1000be0a +1000bdee: 4620 mov r0, r4 +1000bdf0: f7fd fb87 bl 10009502 +1000bdf4: e01a b.n 1000be2c + +1000bdf6 : +1000bdf6: 4641 mov r1, r8 +1000bdf8: 4620 mov r0, r4 +1000bdfa: f002 f99f bl 1000e13c +1000bdfe: e015 b.n 1000be2c + +1000be00 : +1000be00: 4641 mov r1, r8 +1000be02: 4620 mov r0, r4 +1000be04: f000 fc4a bl 1000c69c +1000be08: e010 b.n 1000be2c + +1000be0a : +1000be0a: 68f8 ldr r0, [r7, #12] +1000be0c: f000 faae bl 1000c36c +1000be10: b948 cbnz r0, 1000be26 +1000be12: 7b38 ldrb r0, [r7, #12] +1000be14: f000 00f0 and.w r0, r0, #240 ; 0xf0 +1000be18: 28e0 cmp r0, #224 ; 0xe0 +1000be1a: d004 beq.n 1000be26 +1000be1c: 6066 str r6, [r4, #4] +1000be1e: 2102 movs r1, #2 +1000be20: 4620 mov r0, r4 +1000be22: f000 fcc7 bl 1000c7b4 + +1000be26 : +1000be26: 4620 mov r0, r4 +1000be28: f7fc fcde bl 100087e8 + +1000be2c : +1000be2c: 2000 movs r0, #0 +1000be2e: 6038 str r0, [r7, #0] +1000be30: 6078 str r0, [r7, #4] +1000be32: 60b8 str r0, [r7, #8] +1000be34: 60f8 str r0, [r7, #12] + +1000be36 : +1000be36: e8bd 8ff2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1000be3a : +1000be3a: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +1000be3e: b082 sub sp, #8 +1000be40: 4604 mov r4, r0 +1000be42: 9d0c ldr r5, [sp, #48] ; 0x30 +1000be44: 4688 mov r8, r1 +1000be46: ea5f 0902 movs.w r9, r2 +1000be4a: 461f mov r7, r3 +1000be4c: d041 beq.n 1000bed2 +1000be4e: 2114 movs r1, #20 +1000be50: f7fc fc99 bl 10008786 +1000be54: b110 cbz r0, 1000be5c +1000be56: f06f 0001 mvn.w r0, #1 +1000be5a: e04f b.n 1000befc + +1000be5c : +1000be5c: 6866 ldr r6, [r4, #4] +1000be5e: 7237 strb r7, [r6, #8] +1000be60: 980b ldr r0, [sp, #44] ; 0x2c +1000be62: 7270 strb r0, [r6, #9] +1000be64: ea47 2000 orr.w r0, r7, r0, lsl #8 +1000be68: f8d9 1000 ldr.w r1, [r9] +1000be6c: 6131 str r1, [r6, #16] +1000be6e: b28a uxth r2, r1 +1000be70: 1810 adds r0, r2, r0 +1000be72: eb00 4111 add.w r1, r0, r1, lsr #16 +1000be76: 2045 movs r0, #69 ; 0x45 +1000be78: 7030 strb r0, [r6, #0] +1000be7a: 980a ldr r0, [sp, #40] ; 0x28 +1000be7c: 7070 strb r0, [r6, #1] +1000be7e: 7832 ldrb r2, [r6, #0] +1000be80: ea42 2000 orr.w r0, r2, r0, lsl #8 +1000be84: 1847 adds r7, r0, r1 +1000be86: 8920 ldrh r0, [r4, #8] +1000be88: f000 fb5d bl 1000c546 +1000be8c: 8070 strh r0, [r6, #2] +1000be8e: eb00 0a07 add.w sl, r0, r7 +1000be92: 2000 movs r0, #0 +1000be94: 80f0 strh r0, [r6, #6] +1000be96: 4f1d ldr r7, [pc, #116] ; (1000bf0c ) +1000be98: 8838 ldrh r0, [r7, #0] +1000be9a: f000 fb54 bl 1000c546 +1000be9e: 80b0 strh r0, [r6, #4] +1000bea0: 4450 add r0, sl +1000bea2: 8839 ldrh r1, [r7, #0] +1000bea4: 1c49 adds r1, r1, #1 +1000bea6: 8039 strh r1, [r7, #0] +1000bea8: f1b8 0f00 cmp.w r8, #0 +1000beac: bf1a itte ne +1000beae: f8d8 1000 ldrne.w r1, [r8] +1000beb2: 2900 cmpne r1, #0 +1000beb4: 6869 ldreq r1, [r5, #4] +1000beb6: 60f1 str r1, [r6, #12] +1000beb8: 68f1 ldr r1, [r6, #12] +1000beba: b28a uxth r2, r1 +1000bebc: 1810 adds r0, r2, r0 +1000bebe: eb00 4011 add.w r0, r0, r1, lsr #16 +1000bec2: b281 uxth r1, r0 +1000bec4: eb01 4010 add.w r0, r1, r0, lsr #16 +1000bec8: eb00 4010 add.w r0, r0, r0, lsr #16 +1000becc: 43c0 mvns r0, r0 +1000bece: 8170 strh r0, [r6, #10] +1000bed0: e004 b.n 1000bedc + +1000bed2 : +1000bed2: f10d 0900 add.w r9, sp, #0 +1000bed6: 6860 ldr r0, [r4, #4] +1000bed8: 6900 ldr r0, [r0, #16] +1000beda: 9000 str r0, [sp, #0] + +1000bedc : +1000bedc: 8d28 ldrh r0, [r5, #40] ; 0x28 +1000bede: b140 cbz r0, 1000bef2 +1000bee0: 8921 ldrh r1, [r4, #8] +1000bee2: 4288 cmp r0, r1 +1000bee4: d205 bcs.n 1000bef2 +1000bee6: 464a mov r2, r9 +1000bee8: 4629 mov r1, r5 +1000beea: 4620 mov r0, r4 +1000beec: f001 f911 bl 1000d112 +1000bef0: e004 b.n 1000befc + +1000bef2 : +1000bef2: 696b ldr r3, [r5, #20] +1000bef4: 464a mov r2, r9 +1000bef6: 4621 mov r1, r4 +1000bef8: 4628 mov r0, r5 +1000befa: 4798 blx r3 + +1000befc : +1000befc: e8bd 87f6 ldmia.w sp!, {r1, r2, r4, r5, r6, r7, r8, r9, sl, pc} + +1000bf00 : +1000bf00: 78a0 1004 .x.. + +1000bf04 : +1000bf04: 78a4 1004 .x.. + +1000bf08 : +1000bf08: 76fc 1004 .v.. + +1000bf0c : +1000bf0c: 8b0c 1004 .... + +1000bf10 : +1000bf10: b5fe push {r1, r2, r3, r4, r5, r6, r7, lr} +1000bf12: 4604 mov r4, r0 +1000bf14: 4616 mov r6, r2 +1000bf16: 460d mov r5, r1 +1000bf18: 461f mov r7, r3 +1000bf1a: 4630 mov r0, r6 +1000bf1c: f7ff fec6 bl 1000bcac +1000bf20: b910 cbnz r0, 1000bf28 +1000bf22: f06f 0003 mvn.w r0, #3 +1000bf26: bdfe pop {r1, r2, r3, r4, r5, r6, r7, pc} + +1000bf28 : +1000bf28: 9002 str r0, [sp, #8] +1000bf2a: 463b mov r3, r7 +1000bf2c: 9809 ldr r0, [sp, #36] ; 0x24 +1000bf2e: 9001 str r0, [sp, #4] +1000bf30: 4632 mov r2, r6 +1000bf32: 9808 ldr r0, [sp, #32] +1000bf34: 9000 str r0, [sp, #0] +1000bf36: 4629 mov r1, r5 +1000bf38: 4620 mov r0, r4 +1000bf3a: f7ff ff7e bl 1000be3a +1000bf3e: bdfe pop {r1, r2, r3, r4, r5, r6, r7, pc} + +1000bf40 : +1000bf40: b580 push {r7, lr} +1000bf42: f7fc f966 bl 10008212 +1000bf46: f000 f80f bl 1000bf68 +1000bf4a: f7fc f9a5 bl 10008298 +1000bf4e: f003 f847 bl 1000efe0 +1000bf52: f003 f8d3 bl 1000f0fc +1000bf56: f7fd fad3 bl 10009500 +1000bf5a: f7fc fd7f bl 10008a5c +1000bf5e: e8bd 4001 ldmia.w sp!, {r0, lr} +1000bf62: f7ff ba93 b.w 1000b48c + ... + +1000bf68 : +1000bf68: 4896 ldr r0, [pc, #600] ; (1000c1c4 ) +1000bf6a: b510 push {r4, lr} +1000bf6c: f100 010f add.w r1, r0, #15 +1000bf70: 0889 lsrs r1, r1, #2 +1000bf72: 0089 lsls r1, r1, #2 +1000bf74: 6001 str r1, [r0, #0] +1000bf76: f44f 52a0 mov.w r2, #5120 ; 0x1400 +1000bf7a: 800a strh r2, [r1, #0] +1000bf7c: 2300 movs r3, #0 +1000bf7e: 804b strh r3, [r1, #2] +1000bf80: 710b strb r3, [r1, #4] +1000bf82: 2401 movs r4, #1 +1000bf84: 1853 adds r3, r2, r1 +1000bf86: 6043 str r3, [r0, #4] +1000bf88: 711c strb r4, [r3, #4] +1000bf8a: 801a strh r2, [r3, #0] +1000bf8c: 805a strh r2, [r3, #2] +1000bf8e: 6081 str r1, [r0, #8] +1000bf90: 2101 movs r1, #1 +1000bf92: e8bd 4010 ldmia.w sp!, {r4, lr} +1000bf96: f500 50a1 add.w r0, r0, #5152 ; 0x1420 +1000bf9a: f7fc b8ef b.w 1000817c + +1000bf9e : +1000bf9e: b570 push {r4, r5, r6, lr} +1000bfa0: 0006 movs r6, r0 +1000bfa2: d043 beq.n 1000c02c +1000bfa4: 4c87 ldr r4, [pc, #540] ; (1000c1c4 ) +1000bfa6: 6821 ldr r1, [r4, #0] +1000bfa8: 4288 cmp r0, r1 +1000bfaa: d302 bcc.n 1000bfb2 +1000bfac: 6861 ldr r1, [r4, #4] +1000bfae: 4288 cmp r0, r1 +1000bfb0: d305 bcc.n 1000bfbe + +1000bfb2 : +1000bfb2: f7fc f969 bl 10008288 +1000bfb6: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +1000bfba: f7fc b96a b.w 10008292 + +1000bfbe : +1000bfbe: f504 55a1 add.w r5, r4, #5152 ; 0x1420 +1000bfc2: 2100 movs r1, #0 +1000bfc4: 4628 mov r0, r5 +1000bfc6: f7fc f8f5 bl 100081b4 +1000bfca: f1a6 0008 sub.w r0, r6, #8 +1000bfce: 2100 movs r1, #0 +1000bfd0: 7101 strb r1, [r0, #4] +1000bfd2: 68a1 ldr r1, [r4, #8] +1000bfd4: 4288 cmp r0, r1 +1000bfd6: bf38 it cc +1000bfd8: 60a0 strcc r0, [r4, #8] +1000bfda: 6821 ldr r1, [r4, #0] +1000bfdc: 8802 ldrh r2, [r0, #0] +1000bfde: 1852 adds r2, r2, r1 +1000bfe0: 4290 cmp r0, r2 +1000bfe2: d00e beq.n 1000c002 +1000bfe4: 7913 ldrb r3, [r2, #4] +1000bfe6: b963 cbnz r3, 1000c002 +1000bfe8: 6863 ldr r3, [r4, #4] +1000bfea: 429a cmp r2, r3 +1000bfec: d009 beq.n 1000c002 +1000bfee: 68a3 ldr r3, [r4, #8] +1000bff0: 4293 cmp r3, r2 +1000bff2: bf08 it eq +1000bff4: 60a0 streq r0, [r4, #8] +1000bff6: 8813 ldrh r3, [r2, #0] +1000bff8: 8003 strh r3, [r0, #0] +1000bffa: 1a43 subs r3, r0, r1 +1000bffc: 8812 ldrh r2, [r2, #0] +1000bffe: 1852 adds r2, r2, r1 +1000c000: 8053 strh r3, [r2, #2] + +1000c002 : +1000c002: 8842 ldrh r2, [r0, #2] +1000c004: 1852 adds r2, r2, r1 +1000c006: 4282 cmp r2, r0 +1000c008: d00b beq.n 1000c022 +1000c00a: 7913 ldrb r3, [r2, #4] +1000c00c: b94b cbnz r3, 1000c022 +1000c00e: 68a3 ldr r3, [r4, #8] +1000c010: 4283 cmp r3, r0 +1000c012: bf08 it eq +1000c014: 60a2 streq r2, [r4, #8] +1000c016: 8803 ldrh r3, [r0, #0] +1000c018: 8013 strh r3, [r2, #0] +1000c01a: 1a52 subs r2, r2, r1 +1000c01c: 8800 ldrh r0, [r0, #0] +1000c01e: 1840 adds r0, r0, r1 +1000c020: 8042 strh r2, [r0, #2] + +1000c022 : +1000c022: 4628 mov r0, r5 +1000c024: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +1000c028: f7fc b8e1 b.w 100081ee + +1000c02c : +1000c02c: bd70 pop {r4, r5, r6, pc} + +1000c02e : +1000c02e: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +1000c032: 4680 mov r8, r0 +1000c034: 1cc8 adds r0, r1, #3 +1000c036: f64f 71fc movw r1, #65532 ; 0xfffc +1000c03a: ea01 0500 and.w r5, r1, r0 +1000c03e: 2d0c cmp r5, #12 +1000c040: bfb8 it lt +1000c042: 250c movlt r5, #12 +1000c044: db02 blt.n 1000c04c +1000c046: f5b5 5fa0 cmp.w r5, #5120 ; 0x1400 +1000c04a: dc15 bgt.n 1000c078 + +1000c04c : +1000c04c: 4e5d ldr r6, [pc, #372] ; (1000c1c4 ) +1000c04e: 6830 ldr r0, [r6, #0] +1000c050: 4580 cmp r8, r0 +1000c052: d302 bcc.n 1000c05a +1000c054: 6872 ldr r2, [r6, #4] +1000c056: 4590 cmp r8, r2 +1000c058: d304 bcc.n 1000c064 + +1000c05a : +1000c05a: f7fc f915 bl 10008288 +1000c05e: f7fc f918 bl 10008292 +1000c062: e049 b.n 1000c0f8 + +1000c064 : +1000c064: f1a8 0708 sub.w r7, r8, #8 +1000c068: 1a3c subs r4, r7, r0 +1000c06a: 8838 ldrh r0, [r7, #0] +1000c06c: 1b00 subs r0, r0, r4 +1000c06e: 3808 subs r0, #8 +1000c070: fa1f f980 uxth.w r9, r0 +1000c074: 45a9 cmp r9, r5 +1000c076: da01 bge.n 1000c07c + +1000c078 : +1000c078: 2000 movs r0, #0 +1000c07a: e03e b.n 1000c0fa + +1000c07c : +1000c07c: 454d cmp r5, r9 +1000c07e: d03b beq.n 1000c0f8 +1000c080: f506 5aa1 add.w sl, r6, #5152 ; 0x1420 +1000c084: 2100 movs r1, #0 +1000c086: 4650 mov r0, sl +1000c088: f7fc f894 bl 100081b4 +1000c08c: 6830 ldr r0, [r6, #0] +1000c08e: 8839 ldrh r1, [r7, #0] +1000c090: 68b3 ldr r3, [r6, #8] +1000c092: 180a adds r2, r1, r0 +1000c094: 1929 adds r1, r5, r4 +1000c096: f892 c004 ldrb.w ip, [r2, #4] +1000c09a: 3108 adds r1, #8 +1000c09c: f1bc 0f00 cmp.w ip, #0 +1000c0a0: d112 bne.n 1000c0c8 +1000c0a2: 8815 ldrh r5, [r2, #0] +1000c0a4: b289 uxth r1, r1 +1000c0a6: eb01 0c00 add.w ip, r1, r0 +1000c0aa: 4293 cmp r3, r2 +1000c0ac: bf08 it eq +1000c0ae: f8c6 c008 streq.w ip, [r6, #8] +1000c0b2: 2300 movs r3, #0 +1000c0b4: f88c 3004 strb.w r3, [ip, #4] +1000c0b8: f8ac 5000 strh.w r5, [ip] +1000c0bc: f8ac 4002 strh.w r4, [ip, #2] +1000c0c0: 8039 strh r1, [r7, #0] +1000c0c2: f8bc 2000 ldrh.w r2, [ip] +1000c0c6: e00f b.n 1000c0e8 + +1000c0c8 : +1000c0c8: f105 0214 add.w r2, r5, #20 +1000c0cc: 4591 cmp r9, r2 +1000c0ce: d310 bcc.n 1000c0f2 +1000c0d0: b289 uxth r1, r1 +1000c0d2: 180a adds r2, r1, r0 +1000c0d4: 429a cmp r2, r3 +1000c0d6: bf38 it cc +1000c0d8: 60b2 strcc r2, [r6, #8] +1000c0da: 2300 movs r3, #0 +1000c0dc: 7113 strb r3, [r2, #4] +1000c0de: 883b ldrh r3, [r7, #0] +1000c0e0: 8013 strh r3, [r2, #0] +1000c0e2: 8054 strh r4, [r2, #2] +1000c0e4: 8039 strh r1, [r7, #0] +1000c0e6: 8812 ldrh r2, [r2, #0] + +1000c0e8 : +1000c0e8: f5b2 5fa0 cmp.w r2, #5120 ; 0x1400 +1000c0ec: bf1c itt ne +1000c0ee: 1810 addne r0, r2, r0 +1000c0f0: 8041 strhne r1, [r0, #2] + +1000c0f2 : +1000c0f2: 4650 mov r0, sl +1000c0f4: f7fc f87b bl 100081ee + +1000c0f8 : +1000c0f8: 4640 mov r0, r8 + +1000c0fa : +1000c0fa: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + +1000c0fe : +1000c0fe: b5f8 push {r3, r4, r5, r6, r7, lr} +1000c100: 0004 movs r4, r0 +1000c102: d016 beq.n 1000c132 +1000c104: 1cc0 adds r0, r0, #3 +1000c106: f64f 71fc movw r1, #65532 ; 0xfffc +1000c10a: ea01 0400 and.w r4, r1, r0 +1000c10e: 2c0c cmp r4, #12 +1000c110: da0c bge.n 1000c12c +1000c112: 240c movs r4, #12 + +1000c114 : +1000c114: 4d2b ldr r5, [pc, #172] ; (1000c1c4 ) +1000c116: f505 56a1 add.w r6, r5, #5152 ; 0x1420 +1000c11a: 2100 movs r1, #0 +1000c11c: 4630 mov r0, r6 +1000c11e: f7fc f849 bl 100081b4 +1000c122: 68a8 ldr r0, [r5, #8] +1000c124: 6829 ldr r1, [r5, #0] +1000c126: 1a42 subs r2, r0, r1 +1000c128: b292 uxth r2, r2 +1000c12a: e005 b.n 1000c138 + +1000c12c : +1000c12c: f5b4 5fa0 cmp.w r4, #5120 ; 0x1400 +1000c130: ddf0 ble.n 1000c114 + +1000c132 : +1000c132: 2000 movs r0, #0 +1000c134: bdf2 pop {r1, r4, r5, r6, r7, pc} + +1000c136 : +1000c136: 5a52 ldrh r2, [r2, r1] + +1000c138 : +1000c138: f5c4 57a0 rsb r7, r4, #5120 ; 0x1400 +1000c13c: 42ba cmp r2, r7 +1000c13e: da3c bge.n 1000c1ba +1000c140: 1857 adds r7, r2, r1 +1000c142: f897 c004 ldrb.w ip, [r7, #4] +1000c146: f1bc 0f00 cmp.w ip, #0 +1000c14a: d1f4 bne.n 1000c136 +1000c14c: f8b7 c000 ldrh.w ip, [r7] +1000c150: ebac 0c02 sub.w ip, ip, r2 +1000c154: f1ac 0c08 sub.w ip, ip, #8 +1000c158: 45a4 cmp ip, r4 +1000c15a: d3ec bcc.n 1000c136 +1000c15c: f104 0314 add.w r3, r4, #20 +1000c160: 459c cmp ip, r3 +1000c162: d316 bcc.n 1000c192 +1000c164: 18a3 adds r3, r4, r2 +1000c166: 3308 adds r3, #8 +1000c168: b29b uxth r3, r3 +1000c16a: 185c adds r4, r3, r1 +1000c16c: f04f 0c00 mov.w ip, #0 +1000c170: f884 c004 strb.w ip, [r4, #4] +1000c174: f8b7 c000 ldrh.w ip, [r7] +1000c178: f8a4 c000 strh.w ip, [r4] +1000c17c: 8062 strh r2, [r4, #2] +1000c17e: 803b strh r3, [r7, #0] +1000c180: 2201 movs r2, #1 +1000c182: 713a strb r2, [r7, #4] +1000c184: 8822 ldrh r2, [r4, #0] +1000c186: f5b2 5fa0 cmp.w r2, #5120 ; 0x1400 +1000c18a: d004 beq.n 1000c196 +1000c18c: 1852 adds r2, r2, r1 +1000c18e: 8053 strh r3, [r2, #2] +1000c190: e001 b.n 1000c196 + +1000c192 : +1000c192: 2201 movs r2, #1 +1000c194: 713a strb r2, [r7, #4] + +1000c196 : +1000c196: 4287 cmp r7, r0 +1000c198: d109 bne.n 1000c1ae +1000c19a: e001 b.n 1000c1a0 + +1000c19c : +1000c19c: 8800 ldrh r0, [r0, #0] +1000c19e: 1840 adds r0, r0, r1 + +1000c1a0 : +1000c1a0: 7902 ldrb r2, [r0, #4] +1000c1a2: 2a00 cmp r2, #0 +1000c1a4: bf1c itt ne +1000c1a6: 686a ldrne r2, [r5, #4] +1000c1a8: 4290 cmpne r0, r2 +1000c1aa: d1f7 bne.n 1000c19c +1000c1ac: 60a8 str r0, [r5, #8] + +1000c1ae : +1000c1ae: 4630 mov r0, r6 +1000c1b0: f7fc f81d bl 100081ee +1000c1b4: f107 0008 add.w r0, r7, #8 +1000c1b8: bdf2 pop {r1, r4, r5, r6, r7, pc} + +1000c1ba : +1000c1ba: 4630 mov r0, r6 +1000c1bc: f7fc f817 bl 100081ee +1000c1c0: e7b7 b.n 1000c132 + ... + +1000c1c4 : +1000c1c4: 0000 1fff .... + +1000c1c8 : +1000c1c8: f8df f000 ldr.w pc, [pc] ; 1000c1cc +1000c1cc: 0002d7d1 .word 0x0002d7d1 + +1000c1d0 : +1000c1d0: f8df f000 ldr.w pc, [pc] ; 1000c1d4 +1000c1d4: 0002f661 .word 0x0002f661 + +1000c1d8 : +1000c1d8: f8df f000 ldr.w pc, [pc] ; 1000c1dc +1000c1dc: 0002ef8d .word 0x0002ef8d + +1000c1e0 : +1000c1e0: f8df f000 ldr.w pc, [pc] ; 1000c1e4 +1000c1e4: 00028ae1 .word 0x00028ae1 + +1000c1e8 : +1000c1e8: f8df f000 ldr.w pc, [pc] ; 1000c1ec +1000c1ec: 00028b49 .word 0x00028b49 + +1000c1f0 : +1000c1f0: f8df f000 ldr.w pc, [pc] ; 1000c1f4 +1000c1f4: 00028cb5 .word 0x00028cb5 + +1000c1f8 : +1000c1f8: f8df f000 ldr.w pc, [pc] ; 1000c1fc +1000c1fc: 00028e55 .word 0x00028e55 + +1000c200 : +1000c200: f8df f000 ldr.w pc, [pc] ; 1000c204 +1000c204: 00028ec9 .word 0x00028ec9 + +1000c208 : +1000c208: f8df f000 ldr.w pc, [pc] ; 1000c20c +1000c20c: 00028f15 .word 0x00028f15 + +1000c210 : +1000c210: f8df f000 ldr.w pc, [pc] ; 1000c214 +1000c214: 00028fc5 .word 0x00028fc5 + +1000c218 : +1000c218: f8df f000 ldr.w pc, [pc] ; 1000c21c +1000c21c: 0002907d .word 0x0002907d + +1000c220 : +1000c220: f8df f000 ldr.w pc, [pc] ; 1000c224 +1000c224: 000293cd .word 0x000293cd + +1000c228 : +1000c228: f8df f000 ldr.w pc, [pc] ; 1000c22c +1000c22c: 0002960d .word 0x0002960d + +1000c230 : +1000c230: b408 push {r3} +1000c232: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1000c236: 4607 mov r7, r0 +1000c238: 4840 ldr r0, [pc, #256] ; (1000c33c <.text_8>) +1000c23a: 4d41 ldr r5, [pc, #260] ; (1000c340 <.text_9>) +1000c23c: 6806 ldr r6, [r0, #0] +1000c23e: b09b sub sp, #108 ; 0x6c +1000c240: 6828 ldr r0, [r5, #0] +1000c242: 460c mov r4, r1 +1000c244: 4690 mov r8, r2 +1000c246: b928 cbnz r0, 1000c254 +1000c248: f7ff ffbe bl 1000c1c8 +1000c24c: f003 fb4a bl 1000f8e4 +1000c250: 2001 movs r0, #1 +1000c252: 6028 str r0, [r5, #0] +1000c254: f1b4 4f00 cmp.w r4, #2147483648 ; 0x80000000 +1000c258: d304 bcc.n 1000c264 +1000c25a: 208b movs r0, #139 ; 0x8b +1000c25c: 6030 str r0, [r6, #0] +1000c25e: f04f 30ff mov.w r0, #4294967295 +1000c262: e01e b.n 1000c2a2 +1000c264: f44f 7002 mov.w r0, #520 ; 0x208 +1000c268: f8ad 000c strh.w r0, [sp, #12] +1000c26c: 2c00 cmp r4, #0 +1000c26e: bf14 ite ne +1000c270: 1e60 subne r0, r4, #1 +1000c272: 2000 moveq r0, #0 +1000c274: 9002 str r0, [sp, #8] +1000c276: 9005 str r0, [sp, #20] +1000c278: 9700 str r7, [sp, #0] +1000c27a: f04f 30ff mov.w r0, #4294967295 +1000c27e: f8ad 000e strh.w r0, [sp, #14] +1000c282: 9704 str r7, [sp, #16] +1000c284: ab21 add r3, sp, #132 ; 0x84 +1000c286: 4642 mov r2, r8 +1000c288: a900 add r1, sp, #0 +1000c28a: 4630 mov r0, r6 +1000c28c: f7ff ffa0 bl 1000c1d0 +1000c290: f110 0f01 cmn.w r0, #1 +1000c294: bfbc itt lt +1000c296: 218b movlt r1, #139 ; 0x8b +1000c298: 6031 strlt r1, [r6, #0] +1000c29a: b114 cbz r4, 1000c2a2 +1000c29c: 9a00 ldr r2, [sp, #0] +1000c29e: 2100 movs r1, #0 +1000c2a0: 7011 strb r1, [r2, #0] +1000c2a2: b01b add sp, #108 ; 0x6c +1000c2a4: e8bd 01f0 ldmia.w sp!, {r4, r5, r6, r7, r8} +1000c2a8: f85d fb08 ldr.w pc, [sp], #8 + +1000c2ac : +1000c2ac: b40c push {r2, r3} +1000c2ae: b5f0 push {r4, r5, r6, r7, lr} +1000c2b0: 4606 mov r6, r0 +1000c2b2: 4822 ldr r0, [pc, #136] ; (1000c33c <.text_8>) +1000c2b4: 4f22 ldr r7, [pc, #136] ; (1000c340 <.text_9>) +1000c2b6: 6805 ldr r5, [r0, #0] +1000c2b8: 6838 ldr r0, [r7, #0] +1000c2ba: b09b sub sp, #108 ; 0x6c +1000c2bc: 460c mov r4, r1 +1000c2be: b928 cbnz r0, 1000c2cc +1000c2c0: f7ff ff82 bl 1000c1c8 +1000c2c4: f003 fb0e bl 1000f8e4 +1000c2c8: 2001 movs r0, #1 +1000c2ca: 6038 str r0, [r7, #0] +1000c2cc: f44f 7002 mov.w r0, #520 ; 0x208 +1000c2d0: f8ad 000c strh.w r0, [sp, #12] +1000c2d4: 9600 str r6, [sp, #0] +1000c2d6: f06f 4000 mvn.w r0, #2147483648 ; 0x80000000 +1000c2da: 9002 str r0, [sp, #8] +1000c2dc: 9005 str r0, [sp, #20] +1000c2de: 9604 str r6, [sp, #16] +1000c2e0: f04f 30ff mov.w r0, #4294967295 +1000c2e4: f8ad 000e strh.w r0, [sp, #14] +1000c2e8: ab20 add r3, sp, #128 ; 0x80 +1000c2ea: 4622 mov r2, r4 +1000c2ec: a900 add r1, sp, #0 +1000c2ee: 4628 mov r0, r5 +1000c2f0: f7ff ff6e bl 1000c1d0 +1000c2f4: 9a00 ldr r2, [sp, #0] +1000c2f6: 2100 movs r1, #0 +1000c2f8: 7011 strb r1, [r2, #0] +1000c2fa: b01b add sp, #108 ; 0x6c +1000c2fc: bcf0 pop {r4, r5, r6, r7} +1000c2fe: f85d fb0c ldr.w pc, [sp], #12 + +1000c302 : +1000c302: b40e push {r1, r2, r3} +1000c304: b578 push {r3, r4, r5, r6, lr} +1000c306: 4604 mov r4, r0 +1000c308: 480c ldr r0, [pc, #48] ; (1000c33c <.text_8>) +1000c30a: 4e0d ldr r6, [pc, #52] ; (1000c340 <.text_9>) +1000c30c: 6805 ldr r5, [r0, #0] +1000c30e: 6830 ldr r0, [r6, #0] +1000c310: b928 cbnz r0, 1000c31e +1000c312: f7ff ff59 bl 1000c1c8 +1000c316: f003 fae5 bl 1000f8e4 +1000c31a: 2001 movs r0, #1 +1000c31c: 6030 str r0, [r6, #0] +1000c31e: ab05 add r3, sp, #20 +1000c320: 68a9 ldr r1, [r5, #8] +1000c322: 4622 mov r2, r4 +1000c324: 4628 mov r0, r5 +1000c326: f7ff ff53 bl 1000c1d0 +1000c32a: 4604 mov r4, r0 +1000c32c: 68a9 ldr r1, [r5, #8] +1000c32e: 4628 mov r0, r5 +1000c330: f7ff ff52 bl 1000c1d8 +1000c334: 4620 mov r0, r4 +1000c336: bc72 pop {r1, r4, r5, r6} +1000c338: f85d fb10 ldr.w pc, [sp], #16 + +1000c33c <.text_8>: +1000c33c: 10001c60 .word 0x10001c60 + +1000c340 <.text_9>: +1000c340: 10048178 .word 0x10048178 + +1000c344 : +1000c344: f7ff bf4c b.w 1000c1e0 + +1000c348 : +1000c348: f7ff bf4e b.w 1000c1e8 + +1000c34c : +1000c34c: f7ff bf50 b.w 1000c1f0 + +1000c350 : +1000c350: f7ff bf52 b.w 1000c1f8 + +1000c354 : +1000c354: f7ff bf54 b.w 1000c200 + +1000c358 : +1000c358: f7ff bf56 b.w 1000c208 + +1000c35c : +1000c35c: f7ff bf58 b.w 1000c210 + +1000c360 : +1000c360: f7ff bf5a b.w 1000c218 + +1000c364 : +1000c364: f7ff bf5c b.w 1000c220 + +1000c368 : +1000c368: f7ff bf5e b.w 1000c228 + +1000c36c : +1000c36c: 43c2 mvns r2, r0 +1000c36e: bf18 it ne +1000c370: 2800 cmpne r0, #0 +1000c372: d011 beq.n 1000c398 +1000c374: f891 2031 ldrb.w r2, [r1, #49] ; 0x31 +1000c378: 0792 lsls r2, r2, #30 +1000c37a: d50f bpl.n 1000c39c +1000c37c: 684a ldr r2, [r1, #4] +1000c37e: 4290 cmp r0, r2 +1000c380: d00c beq.n 1000c39c +1000c382: 1d09 adds r1, r1, #4 +1000c384: 6849 ldr r1, [r1, #4] +1000c386: ea01 0300 and.w r3, r1, r0 +1000c38a: 400a ands r2, r1 +1000c38c: 4293 cmp r3, r2 +1000c38e: bf02 ittt eq +1000c390: 43c9 mvneq r1, r1 +1000c392: 4008 andeq r0, r1 +1000c394: 4288 cmpeq r0, r1 +1000c396: d101 bne.n 1000c39c + +1000c398 : +1000c398: 2001 movs r0, #1 +1000c39a: 4770 bx lr + +1000c39c : +1000c39c: 2000 movs r0, #0 +1000c39e: 4770 bx lr + +1000c3a0 : +1000c3a0: b580 push {r7, lr} +1000c3a2: a900 add r1, sp, #0 +1000c3a4: f000 f806 bl 1000c3b4 +1000c3a8: b108 cbz r0, 1000c3ae +1000c3aa: 9800 ldr r0, [sp, #0] +1000c3ac: bd02 pop {r1, pc} + +1000c3ae : +1000c3ae: f04f 30ff mov.w r0, #4294967295 +1000c3b2: bd02 pop {r1, pc} + +1000c3b4 : +1000c3b4: b5f0 push {r4, r5, r6, r7, lr} +1000c3b6: b085 sub sp, #20 +1000c3b8: f990 3000 ldrsb.w r3, [r0] +1000c3bc: 460c mov r4, r1 +1000c3be: aa00 add r2, sp, #0 +1000c3c0: e006 b.n 1000c3d0 + +1000c3c2 : +1000c3c2: ab03 add r3, sp, #12 +1000c3c4: 429d cmp r5, r3 +1000c3c6: d260 bcs.n 1000c48a +1000c3c8: f842 1b04 str.w r1, [r2], #4 +1000c3cc: f910 3f01 ldrsb.w r3, [r0, #1]! + +1000c3d0 : +1000c3d0: b2d9 uxtb r1, r3 +1000c3d2: 3930 subs r1, #48 ; 0x30 +1000c3d4: 290a cmp r1, #10 +1000c3d6: d258 bcs.n 1000c48a +1000c3d8: 2100 movs r1, #0 +1000c3da: 250a movs r5, #10 +1000c3dc: 2b30 cmp r3, #48 ; 0x30 +1000c3de: d10d bne.n 1000c3fc +1000c3e0: f910 3f01 ldrsb.w r3, [r0, #1]! +1000c3e4: 2b78 cmp r3, #120 ; 0x78 +1000c3e6: bf14 ite ne +1000c3e8: 2b58 cmpne r3, #88 ; 0x58 +1000c3ea: 2510 moveq r5, #16 +1000c3ec: d004 beq.n 1000c3f8 +1000c3ee: 2508 movs r5, #8 +1000c3f0: e004 b.n 1000c3fc + +1000c3f2 : +1000c3f2: 3b30 subs r3, #48 ; 0x30 +1000c3f4: fb05 3101 mla r1, r5, r1, r3 + +1000c3f8 : +1000c3f8: f910 3f01 ldrsb.w r3, [r0, #1]! + +1000c3fc : +1000c3fc: b2de uxtb r6, r3 +1000c3fe: f1a6 0730 sub.w r7, r6, #48 ; 0x30 +1000c402: 2f0a cmp r7, #10 +1000c404: d3f5 bcc.n 1000c3f2 +1000c406: 2d10 cmp r5, #16 +1000c408: d10f bne.n 1000c42a +1000c40a: f1a6 0761 sub.w r7, r6, #97 ; 0x61 +1000c40e: 2f06 cmp r7, #6 +1000c410: bf24 itt cs +1000c412: 3e41 subcs r6, #65 ; 0x41 +1000c414: 2e06 cmpcs r6, #6 +1000c416: d208 bcs.n 1000c42a +1000c418: 2f1a cmp r7, #26 +1000c41a: bf34 ite cc +1000c41c: 2661 movcc r6, #97 ; 0x61 +1000c41e: 2641 movcs r6, #65 ; 0x41 +1000c420: 330a adds r3, #10 +1000c422: 1b9b subs r3, r3, r6 +1000c424: ea43 1101 orr.w r1, r3, r1, lsl #4 +1000c428: e7e6 b.n 1000c3f8 + +1000c42a : +1000c42a: 4615 mov r5, r2 +1000c42c: 2b2e cmp r3, #46 ; 0x2e +1000c42e: d0c8 beq.n 1000c3c2 +1000c430: 2b00 cmp r3, #0 +1000c432: bf18 it ne +1000c434: 2b20 cmpne r3, #32 +1000c436: d00b beq.n 1000c450 +1000c438: 2b0c cmp r3, #12 +1000c43a: bf18 it ne +1000c43c: 2b0a cmpne r3, #10 +1000c43e: d007 beq.n 1000c450 +1000c440: 2b0d cmp r3, #13 +1000c442: bf18 it ne +1000c444: 2b09 cmpne r3, #9 +1000c446: d003 beq.n 1000c450 +1000c448: 2b0b cmp r3, #11 +1000c44a: bf18 it ne +1000c44c: 2b2c cmpne r3, #44 ; 0x2c +1000c44e: d11c bne.n 1000c48a + +1000c450 : +1000c450: a800 add r0, sp, #0 +1000c452: 9b00 ldr r3, [sp, #0] +1000c454: 6842 ldr r2, [r0, #4] +1000c456: ae00 add r6, sp, #0 +1000c458: 1bad subs r5, r5, r6 +1000c45a: 061b lsls r3, r3, #24 +1000c45c: 10ad asrs r5, r5, #2 +1000c45e: 1c6d adds r5, r5, #1 +1000c460: d013 beq.n 1000c48a +1000c462: 2d02 cmp r5, #2 +1000c464: d004 beq.n 1000c470 +1000c466: 2d03 cmp r5, #3 +1000c468: d007 beq.n 1000c47a +1000c46a: 2d04 cmp r5, #4 +1000c46c: d00b beq.n 1000c486 +1000c46e: e014 b.n 1000c49a + +1000c470 : +1000c470: f1b1 7f80 cmp.w r1, #16777216 ; 0x1000000 +1000c474: d209 bcs.n 1000c48a +1000c476: 4319 orrs r1, r3 +1000c478: e00f b.n 1000c49a + +1000c47a : +1000c47a: f5b1 3f80 cmp.w r1, #65536 ; 0x10000 +1000c47e: d204 bcs.n 1000c48a +1000c480: ea43 4002 orr.w r0, r3, r2, lsl #16 +1000c484: e008 b.n 1000c498 + +1000c486 : +1000c486: 29ff cmp r1, #255 ; 0xff +1000c488: d901 bls.n 1000c48e + +1000c48a : +1000c48a: 2000 movs r0, #0 +1000c48c: e00b b.n 1000c4a6 + +1000c48e : +1000c48e: 6880 ldr r0, [r0, #8] +1000c490: ea43 4202 orr.w r2, r3, r2, lsl #16 +1000c494: ea42 2000 orr.w r0, r2, r0, lsl #8 + +1000c498 : +1000c498: 4301 orrs r1, r0 + +1000c49a : +1000c49a: b11c cbz r4, 1000c4a4 +1000c49c: 4608 mov r0, r1 +1000c49e: f000 f858 bl 1000c552 +1000c4a2: 6020 str r0, [r4, #0] + +1000c4a4 : +1000c4a4: 2001 movs r0, #1 + +1000c4a6 : +1000c4a6: b005 add sp, #20 +1000c4a8: bdf0 pop {r4, r5, r6, r7, pc} + ... + +1000c4ac : +1000c4ac: 2210 movs r2, #16 +1000c4ae: 4901 ldr r1, [pc, #4] ; (1000c4b4 ) +1000c4b0: e002 b.n 1000c4b8 +1000c4b2: bf00 nop + +1000c4b4 : +1000c4b4: 770c 1004 .w.. + +1000c4b8 : +1000c4b8: e92d 41fc stmdb sp!, {r2, r3, r4, r5, r6, r7, r8, lr} +1000c4bc: 4603 mov r3, r0 +1000c4be: 4608 mov r0, r1 +1000c4c0: 681b ldr r3, [r3, #0] +1000c4c2: 9300 str r3, [sp, #0] +1000c4c4: 2100 movs r1, #0 +1000c4c6: 4603 mov r3, r0 +1000c4c8: ac00 add r4, sp, #0 +1000c4ca: 2504 movs r5, #4 +1000c4cc: f10d 0804 add.w r8, sp, #4 +1000c4d0: 260a movs r6, #10 + +1000c4d2 : +1000c4d2: 2700 movs r7, #0 + +1000c4d4 : +1000c4d4: f894 c000 ldrb.w ip, [r4] +1000c4d8: 46b6 mov lr, r6 +1000c4da: fb9c fefe sdiv lr, ip, lr +1000c4de: fb06 cc1e mls ip, r6, lr, ip +1000c4e2: b2ff uxtb r7, r7 +1000c4e4: f884 e000 strb.w lr, [r4] +1000c4e8: f10c 0c30 add.w ip, ip, #48 ; 0x30 +1000c4ec: f807 c008 strb.w ip, [r7, r8] +1000c4f0: 1c7f adds r7, r7, #1 +1000c4f2: fa5f fe8e uxtb.w lr, lr +1000c4f6: f1be 0f00 cmp.w lr, #0 +1000c4fa: d1eb bne.n 1000c4d4 + +1000c4fc : +1000c4fc: 46bc mov ip, r7 +1000c4fe: f1ac 0701 sub.w r7, ip, #1 +1000c502: fa5f fc8c uxtb.w ip, ip +1000c506: f1bc 0f00 cmp.w ip, #0 +1000c50a: d00b beq.n 1000c524 +1000c50c: 468c mov ip, r1 +1000c50e: f10c 0101 add.w r1, ip, #1 +1000c512: 4594 cmp ip, r2 +1000c514: bfbe ittt lt +1000c516: b2ff uxtblt r7, r7 +1000c518: f817 c008 ldrblt.w ip, [r7, r8] +1000c51c: f803 cb01 strblt.w ip, [r3], #1 +1000c520: dbec blt.n 1000c4fc +1000c522: e003 b.n 1000c52c + +1000c524 : +1000c524: 460f mov r7, r1 +1000c526: 1c79 adds r1, r7, #1 +1000c528: 4297 cmp r7, r2 +1000c52a: db01 blt.n 1000c530 + +1000c52c : +1000c52c: 2000 movs r0, #0 +1000c52e: e008 b.n 1000c542 + +1000c530 : +1000c530: 272e movs r7, #46 ; 0x2e +1000c532: 1c64 adds r4, r4, #1 +1000c534: f803 7b01 strb.w r7, [r3], #1 +1000c538: 1e6d subs r5, r5, #1 +1000c53a: d1ca bne.n 1000c4d2 +1000c53c: 2100 movs r1, #0 +1000c53e: f803 1c01 strb.w r1, [r3, #-1] + +1000c542 : +1000c542: e8bd 81f6 ldmia.w sp!, {r1, r2, r4, r5, r6, r7, r8, pc} + +1000c546 : +1000c546: 0a01 lsrs r1, r0, #8 +1000c548: ea41 2000 orr.w r0, r1, r0, lsl #8 +1000c54c: b280 uxth r0, r0 +1000c54e: 4770 bx lr + +1000c550 : +1000c550: e7f9 b.n 1000c546 + +1000c552 : +1000c552: f400 417f and.w r1, r0, #65280 ; 0xff00 +1000c556: 0209 lsls r1, r1, #8 +1000c558: 0a02 lsrs r2, r0, #8 +1000c55a: ea41 6100 orr.w r1, r1, r0, lsl #24 +1000c55e: f402 427f and.w r2, r2, #65280 ; 0xff00 +1000c562: 4311 orrs r1, r2 +1000c564: ea41 6010 orr.w r0, r1, r0, lsr #24 +1000c568: 4770 bx lr + +1000c56a : +1000c56a: e7f2 b.n 1000c552 + +1000c56c : +1000c56c: b518 push {r3, r4, lr} +1000c56e: 2200 movs r2, #0 +1000c570: f8ad 2000 strh.w r2, [sp] +1000c574: 2300 movs r3, #0 +1000c576: f010 0201 ands.w r2, r0, #1 +1000c57a: d00b beq.n 1000c594 +1000c57c: 2901 cmp r1, #1 +1000c57e: db09 blt.n 1000c594 +1000c580: f810 4b01 ldrb.w r4, [r0], #1 +1000c584: f88d 4001 strb.w r4, [sp, #1] +1000c588: 1e49 subs r1, r1, #1 +1000c58a: e003 b.n 1000c594 + +1000c58c : +1000c58c: f830 4b02 ldrh.w r4, [r0], #2 +1000c590: 18e3 adds r3, r4, r3 +1000c592: 1e89 subs r1, r1, #2 + +1000c594 : +1000c594: 2902 cmp r1, #2 +1000c596: daf9 bge.n 1000c58c +1000c598: 2901 cmp r1, #1 +1000c59a: bfa4 itt ge +1000c59c: 7800 ldrbge r0, [r0, #0] +1000c59e: f88d 0000 strbge.w r0, [sp] +1000c5a2: f8bd 0000 ldrh.w r0, [sp] +1000c5a6: 18c0 adds r0, r0, r3 +1000c5a8: b281 uxth r1, r0 +1000c5aa: eb01 4010 add.w r0, r1, r0, lsr #16 +1000c5ae: b281 uxth r1, r0 +1000c5b0: eb01 4010 add.w r0, r1, r0, lsr #16 +1000c5b4: b122 cbz r2, 1000c5c0 +1000c5b6: b2c1 uxtb r1, r0 +1000c5b8: f3c0 2007 ubfx r0, r0, #8, #8 +1000c5bc: ea40 2001 orr.w r0, r0, r1, lsl #8 + +1000c5c0 : +1000c5c0: b280 uxth r0, r0 +1000c5c2: bd12 pop {r1, r4, pc} + +1000c5c4 : +1000c5c4: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +1000c5c8: 4605 mov r5, r0 +1000c5ca: 4689 mov r9, r1 +1000c5cc: 4614 mov r4, r2 +1000c5ce: 4698 mov r8, r3 +1000c5d0: 2600 movs r6, #0 +1000c5d2: 2700 movs r7, #0 +1000c5d4: e012 b.n 1000c5fc + +1000c5d6 : +1000c5d6: 8969 ldrh r1, [r5, #10] +1000c5d8: 6868 ldr r0, [r5, #4] +1000c5da: f7ff ffc7 bl 1000c56c +1000c5de: 1980 adds r0, r0, r6 +1000c5e0: b281 uxth r1, r0 +1000c5e2: eb01 4610 add.w r6, r1, r0, lsr #16 +1000c5e6: 7aa8 ldrb r0, [r5, #10] +1000c5e8: 07c0 lsls r0, r0, #31 +1000c5ea: d506 bpl.n 1000c5fa +1000c5ec: b2f0 uxtb r0, r6 +1000c5ee: f3c6 2107 ubfx r1, r6, #8, #8 +1000c5f2: f1c7 0701 rsb r7, r7, #1 +1000c5f6: ea41 2600 orr.w r6, r1, r0, lsl #8 + +1000c5fa : +1000c5fa: 682d ldr r5, [r5, #0] + +1000c5fc : +1000c5fc: 2d00 cmp r5, #0 +1000c5fe: d1ea bne.n 1000c5d6 +1000c600: b2ff uxtb r7, r7 +1000c602: b127 cbz r7, 1000c60e +1000c604: b2f0 uxtb r0, r6 +1000c606: f3c6 2107 ubfx r1, r6, #8, #8 +1000c60a: ea41 2600 orr.w r6, r1, r0, lsl #8 + +1000c60e : +1000c60e: f8d9 0000 ldr.w r0, [r9] +1000c612: b281 uxth r1, r0 +1000c614: 1989 adds r1, r1, r6 +1000c616: eb01 4010 add.w r0, r1, r0, lsr #16 +1000c61a: 6821 ldr r1, [r4, #0] +1000c61c: b28a uxth r2, r1 +1000c61e: 1810 adds r0, r2, r0 +1000c620: eb00 4411 add.w r4, r0, r1, lsr #16 +1000c624: 4640 mov r0, r8 +1000c626: f7ff ff8e bl 1000c546 +1000c62a: 1904 adds r4, r0, r4 +1000c62c: 9808 ldr r0, [sp, #32] +1000c62e: f7ff ff8a bl 1000c546 +1000c632: 1900 adds r0, r0, r4 +1000c634: b281 uxth r1, r0 +1000c636: eb01 4010 add.w r0, r1, r0, lsr #16 +1000c63a: eb00 4010 add.w r0, r0, r0, lsr #16 +1000c63e: 43c0 mvns r0, r0 +1000c640: b280 uxth r0, r0 +1000c642: e8bd 83f2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, pc} + +1000c646 : +1000c646: b580 push {r7, lr} +1000c648: f7ff ff90 bl 1000c56c +1000c64c: 43c0 mvns r0, r0 +1000c64e: b280 uxth r0, r0 +1000c650: bd02 pop {r1, pc} + +1000c652 : +1000c652: b570 push {r4, r5, r6, lr} +1000c654: 4605 mov r5, r0 +1000c656: 2600 movs r6, #0 +1000c658: 2400 movs r4, #0 +1000c65a: e012 b.n 1000c682 + +1000c65c : +1000c65c: 8969 ldrh r1, [r5, #10] +1000c65e: 6868 ldr r0, [r5, #4] +1000c660: f7ff ff84 bl 1000c56c +1000c664: 1980 adds r0, r0, r6 +1000c666: b281 uxth r1, r0 +1000c668: eb01 4610 add.w r6, r1, r0, lsr #16 +1000c66c: 7aa8 ldrb r0, [r5, #10] +1000c66e: 07c0 lsls r0, r0, #31 +1000c670: d506 bpl.n 1000c680 +1000c672: b2f0 uxtb r0, r6 +1000c674: f3c6 2107 ubfx r1, r6, #8, #8 +1000c678: f1c4 0401 rsb r4, r4, #1 +1000c67c: ea41 2600 orr.w r6, r1, r0, lsl #8 + +1000c680 : +1000c680: 682d ldr r5, [r5, #0] + +1000c682 : +1000c682: 2d00 cmp r5, #0 +1000c684: d1ea bne.n 1000c65c +1000c686: b2e4 uxtb r4, r4 +1000c688: b124 cbz r4, 1000c694 +1000c68a: b2f0 uxtb r0, r6 +1000c68c: f3c6 2107 ubfx r1, r6, #8, #8 +1000c690: ea41 2600 orr.w r6, r1, r0, lsl #8 + +1000c694 : +1000c694: 43f0 mvns r0, r6 +1000c696: b280 uxth r0, r0 +1000c698: bd70 pop {r4, r5, r6, pc} + ... + +1000c69c : +1000c69c: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +1000c6a0: 4604 mov r4, r0 +1000c6a2: b084 sub sp, #16 +1000c6a4: 6867 ldr r7, [r4, #4] +1000c6a6: 7838 ldrb r0, [r7, #0] +1000c6a8: f000 000f and.w r0, r0, #15 +1000c6ac: ea4f 0a80 mov.w sl, r0, lsl #2 +1000c6b0: 4688 mov r8, r1 +1000c6b2: f1ca 0900 rsb r9, sl, #0 +1000c6b6: fa0f f189 sxth.w r1, r9 +1000c6ba: f000 f878 bl 1000c7ae + +1000c6be : +1000c6be: 2800 cmp r0, #0 +1000c6c0: d16a bne.n 1000c798 +1000c6c2: 8920 ldrh r0, [r4, #8] +1000c6c4: 2804 cmp r0, #4 +1000c6c6: d367 bcc.n 1000c798 +1000c6c8: 6860 ldr r0, [r4, #4] +1000c6ca: 7800 ldrb r0, [r0, #0] +1000c6cc: 2808 cmp r0, #8 +1000c6ce: d163 bne.n 1000c798 +1000c6d0: 4e34 ldr r6, [pc, #208] ; (1000c7a4 ) +1000c6d2: 6830 ldr r0, [r6, #0] +1000c6d4: 2501 movs r5, #1 +1000c6d6: f000 01f0 and.w r1, r0, #240 ; 0xf0 +1000c6da: 29e0 cmp r1, #224 ; 0xe0 +1000c6dc: bf08 it eq +1000c6de: 2500 moveq r5, #0 +1000c6e0: 4641 mov r1, r8 +1000c6e2: f7ff fe43 bl 1000c36c +1000c6e6: 2800 cmp r0, #0 +1000c6e8: d156 bne.n 1000c798 +1000c6ea: 2d00 cmp r5, #0 +1000c6ec: d054 beq.n 1000c798 +1000c6ee: 8920 ldrh r0, [r4, #8] +1000c6f0: 2808 cmp r0, #8 +1000c6f2: d351 bcc.n 1000c798 +1000c6f4: 4620 mov r0, r4 +1000c6f6: f7ff ffac bl 1000c652 +1000c6fa: 2800 cmp r0, #0 +1000c6fc: d14c bne.n 1000c798 +1000c6fe: 2122 movs r1, #34 ; 0x22 +1000c700: f000 f855 bl 1000c7ae + +1000c704 : +1000c704: b1d8 cbz r0, 1000c73e +1000c706: f000 f851 bl 1000c7ac + +1000c70a : +1000c70a: 2800 cmp r0, #0 +1000c70c: d144 bne.n 1000c798 +1000c70e: 8921 ldrh r1, [r4, #8] +1000c710: 2200 movs r2, #0 +1000c712: 2002 movs r0, #2 +1000c714: f7fb ff58 bl 100085c8 +1000c718: 0005 movs r5, r0 +1000c71a: d03d beq.n 1000c798 +1000c71c: 4621 mov r1, r4 +1000c71e: f7fc f8c1 bl 100088a4 +1000c722: 2800 cmp r0, #0 +1000c724: d138 bne.n 1000c798 +1000c726: 686f ldr r7, [r5, #4] +1000c728: fa0f f189 sxth.w r1, r9 +1000c72c: 4628 mov r0, r5 +1000c72e: f7fc f82a bl 10008786 +1000c732: bb88 cbnz r0, 1000c798 +1000c734: 4620 mov r0, r4 +1000c736: f7fc f857 bl 100087e8 +1000c73a: 462c mov r4, r5 +1000c73c: e004 b.n 1000c748 + +1000c73e : +1000c73e: f06f 0121 mvn.w r1, #33 ; 0x21 +1000c742: f000 f834 bl 1000c7ae + +1000c746 : +1000c746: bb38 cbnz r0, 1000c798 + +1000c748 : +1000c748: 6860 ldr r0, [r4, #4] +1000c74a: 6831 ldr r1, [r6, #0] +1000c74c: 60f9 str r1, [r7, #12] +1000c74e: f64f 73f7 movw r3, #65527 ; 0xfff7 +1000c752: 4915 ldr r1, [pc, #84] ; (1000c7a8 ) +1000c754: 6809 ldr r1, [r1, #0] +1000c756: 6139 str r1, [r7, #16] +1000c758: 2100 movs r1, #0 +1000c75a: 7001 strb r1, [r0, #0] +1000c75c: 8841 ldrh r1, [r0, #2] +1000c75e: 4299 cmp r1, r3 +1000c760: bf2c ite cs +1000c762: 3109 addcs r1, #9 +1000c764: 3108 addcc r1, #8 +1000c766: 8041 strh r1, [r0, #2] +1000c768: 20ff movs r0, #255 ; 0xff +1000c76a: 7238 strb r0, [r7, #8] +1000c76c: 2114 movs r1, #20 +1000c76e: 2000 movs r0, #0 +1000c770: 8178 strh r0, [r7, #10] +1000c772: 4638 mov r0, r7 +1000c774: f7ff ff67 bl 1000c646 +1000c778: 8178 strh r0, [r7, #10] +1000c77a: f000 f817 bl 1000c7ac + +1000c77e : +1000c77e: b958 cbnz r0, 1000c798 +1000c780: 2001 movs r0, #1 +1000c782: 9001 str r0, [sp, #4] +1000c784: f8cd 8008 str.w r8, [sp, #8] +1000c788: 2000 movs r0, #0 +1000c78a: 9000 str r0, [sp, #0] +1000c78c: 23ff movs r3, #255 ; 0xff +1000c78e: 2200 movs r2, #0 +1000c790: 4631 mov r1, r6 +1000c792: 4620 mov r0, r4 +1000c794: f7ff fb51 bl 1000be3a + +1000c798 : +1000c798: 4620 mov r0, r4 +1000c79a: b004 add sp, #16 +1000c79c: e8bd 47f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +1000c7a0: f7fc b822 b.w 100087e8 + +1000c7a4 : +1000c7a4: 7708 1004 .w.. + +1000c7a8 : +1000c7a8: 7704 1004 .w.. + +1000c7ac : +1000c7ac: 4651 mov r1, sl + +1000c7ae : +1000c7ae: 4620 mov r0, r4 +1000c7b0: f7fb bfe9 b.w 10008786 + +1000c7b4 : +1000c7b4: b2ca uxtb r2, r1 +1000c7b6: 2103 movs r1, #3 +1000c7b8: e001 b.n 1000c7be + +1000c7ba : +1000c7ba: b2ca uxtb r2, r1 +1000c7bc: 210b movs r1, #11 + +1000c7be : +1000c7be: e92d 43fe stmdb sp!, {r1, r2, r3, r4, r5, r6, r7, r8, r9, lr} +1000c7c2: 4607 mov r7, r0 +1000c7c4: 4688 mov r8, r1 +1000c7c6: 4691 mov r9, r2 +1000c7c8: 2200 movs r2, #0 +1000c7ca: 2124 movs r1, #36 ; 0x24 +1000c7cc: 2001 movs r0, #1 +1000c7ce: f7fb fefb bl 100085c8 +1000c7d2: 0004 movs r4, r0 +1000c7d4: d024 beq.n 1000c820 +1000c7d6: 6866 ldr r6, [r4, #4] +1000c7d8: 687d ldr r5, [r7, #4] +1000c7da: f886 8000 strb.w r8, [r6] +1000c7de: f886 9001 strb.w r9, [r6, #1] +1000c7e2: 2000 movs r0, #0 +1000c7e4: 80b0 strh r0, [r6, #4] +1000c7e6: 80f0 strh r0, [r6, #6] +1000c7e8: 221c movs r2, #28 +1000c7ea: 6860 ldr r0, [r4, #4] +1000c7ec: 6879 ldr r1, [r7, #4] +1000c7ee: 3008 adds r0, #8 +1000c7f0: f7ff fdaa bl 1000c348 +1000c7f4: 2000 movs r0, #0 +1000c7f6: 8070 strh r0, [r6, #2] +1000c7f8: 4630 mov r0, r6 +1000c7fa: 8961 ldrh r1, [r4, #10] +1000c7fc: f7ff ff23 bl 1000c646 +1000c800: 8070 strh r0, [r6, #2] +1000c802: 23ff movs r3, #255 ; 0xff +1000c804: 68e8 ldr r0, [r5, #12] +1000c806: 9002 str r0, [sp, #8] +1000c808: aa02 add r2, sp, #8 +1000c80a: 2001 movs r0, #1 +1000c80c: 9001 str r0, [sp, #4] +1000c80e: 2100 movs r1, #0 +1000c810: 2000 movs r0, #0 +1000c812: 9000 str r0, [sp, #0] +1000c814: 4620 mov r0, r4 +1000c816: f7ff fb7b bl 1000bf10 +1000c81a: 4620 mov r0, r4 +1000c81c: f7fb ffe4 bl 100087e8 + +1000c820 : +1000c820: e8bd 83f7 ldmia.w sp!, {r0, r1, r2, r4, r5, r6, r7, r8, r9, pc} + +1000c824 : +1000c824: f100 0108 add.w r1, r0, #8 +1000c828: 6041 str r1, [r0, #4] +1000c82a: f04f 31ff mov.w r1, #4294967295 +1000c82e: 6081 str r1, [r0, #8] +1000c830: f100 0108 add.w r1, r0, #8 +1000c834: 60c1 str r1, [r0, #12] +1000c836: 6101 str r1, [r0, #16] +1000c838: 2100 movs r1, #0 +1000c83a: 6001 str r1, [r0, #0] +1000c83c: 4770 bx lr + +1000c83e : +1000c83e: 2100 movs r1, #0 +1000c840: 6101 str r1, [r0, #16] +1000c842: 4770 bx lr + +1000c844 : +1000c844: 6842 ldr r2, [r0, #4] +1000c846: 604a str r2, [r1, #4] +1000c848: 6893 ldr r3, [r2, #8] +1000c84a: 608b str r3, [r1, #8] +1000c84c: 6893 ldr r3, [r2, #8] +1000c84e: 6059 str r1, [r3, #4] +1000c850: 6091 str r1, [r2, #8] +1000c852: 6108 str r0, [r1, #16] +1000c854: 6801 ldr r1, [r0, #0] +1000c856: 1c49 adds r1, r1, #1 +1000c858: 6001 str r1, [r0, #0] +1000c85a: 4770 bx lr + +1000c85c : +1000c85c: b530 push {r4, r5, lr} +1000c85e: 680a ldr r2, [r1, #0] +1000c860: f112 0f01 cmn.w r2, #1 +1000c864: bf08 it eq +1000c866: 6903 ldreq r3, [r0, #16] +1000c868: d007 beq.n 1000c87a +1000c86a: f100 0308 add.w r3, r0, #8 +1000c86e: e000 b.n 1000c872 + +1000c870 : +1000c870: 4623 mov r3, r4 + +1000c872 : +1000c872: 685c ldr r4, [r3, #4] +1000c874: 6825 ldr r5, [r4, #0] +1000c876: 42aa cmp r2, r5 +1000c878: d2fa bcs.n 1000c870 + +1000c87a : +1000c87a: 685a ldr r2, [r3, #4] +1000c87c: 604a str r2, [r1, #4] +1000c87e: 6091 str r1, [r2, #8] +1000c880: 608b str r3, [r1, #8] +1000c882: 6059 str r1, [r3, #4] +1000c884: 6108 str r0, [r1, #16] +1000c886: 6801 ldr r1, [r0, #0] +1000c888: 1c49 adds r1, r1, #1 +1000c88a: 6001 str r1, [r0, #0] +1000c88c: bd30 pop {r4, r5, pc} + +1000c88e : +1000c88e: 6843 ldr r3, [r0, #4] +1000c890: 6901 ldr r1, [r0, #16] +1000c892: 6882 ldr r2, [r0, #8] +1000c894: 609a str r2, [r3, #8] +1000c896: 6883 ldr r3, [r0, #8] +1000c898: 6842 ldr r2, [r0, #4] +1000c89a: 605a str r2, [r3, #4] +1000c89c: 684a ldr r2, [r1, #4] +1000c89e: 4282 cmp r2, r0 +1000c8a0: bf04 itt eq +1000c8a2: 6882 ldreq r2, [r0, #8] +1000c8a4: 604a streq r2, [r1, #4] +1000c8a6: 2200 movs r2, #0 +1000c8a8: 6102 str r2, [r0, #16] +1000c8aa: 6808 ldr r0, [r1, #0] +1000c8ac: 1e40 subs r0, r0, #1 +1000c8ae: 6008 str r0, [r1, #0] +1000c8b0: 4770 bx lr + ... + +1000c8b4 : +1000c8b4: b5f8 push {r3, r4, r5, r6, r7, lr} +1000c8b6: 4604 mov r4, r0 +1000c8b8: 2500 movs r5, #0 +1000c8ba: f7fe f9c2 bl 1000ac42 +1000c8be: 4e5a ldr r6, [pc, #360] ; (1000ca28 ) +1000c8c0: 68b0 ldr r0, [r6, #8] +1000c8c2: b9f0 cbnz r0, 1000c902 +1000c8c4: 4a59 ldr r2, [pc, #356] ; (1000ca2c ) +1000c8c6: f44f 3196 mov.w r1, #76800 ; 0x12c00 +1000c8ca: 4610 mov r0, r2 +1000c8cc: f012 0307 ands.w r3, r2, #7 +1000c8d0: d005 beq.n 1000c8de +1000c8d2: 1dd0 adds r0, r2, #7 +1000c8d4: 08c0 lsrs r0, r0, #3 +1000c8d6: 00c0 lsls r0, r0, #3 +1000c8d8: f5c0 3196 rsb r1, r0, #76800 ; 0x12c00 +1000c8dc: 1851 adds r1, r2, r1 + +1000c8de : +1000c8de: 1809 adds r1, r1, r0 +1000c8e0: 3908 subs r1, #8 +1000c8e2: 08c9 lsrs r1, r1, #3 +1000c8e4: 00c9 lsls r1, r1, #3 +1000c8e6: 6030 str r0, [r6, #0] +1000c8e8: 6075 str r5, [r6, #4] +1000c8ea: 60b1 str r1, [r6, #8] +1000c8ec: 604d str r5, [r1, #4] +1000c8ee: 600d str r5, [r1, #0] +1000c8f0: 1a0a subs r2, r1, r0 +1000c8f2: 6042 str r2, [r0, #4] +1000c8f4: 6001 str r1, [r0, #0] +1000c8f6: 6840 ldr r0, [r0, #4] +1000c8f8: 6130 str r0, [r6, #16] +1000c8fa: 60f0 str r0, [r6, #12] +1000c8fc: f04f 4000 mov.w r0, #2147483648 ; 0x80000000 +1000c900: 6170 str r0, [r6, #20] + +1000c902 : +1000c902: 6970 ldr r0, [r6, #20] +1000c904: 4204 tst r4, r0 +1000c906: d137 bne.n 1000c978 +1000c908: b3b4 cbz r4, 1000c978 +1000c90a: 3408 adds r4, #8 +1000c90c: f014 0f07 tst.w r4, #7 +1000c910: d004 beq.n 1000c91c +1000c912: f104 0008 add.w r0, r4, #8 +1000c916: f004 0107 and.w r1, r4, #7 +1000c91a: 1a44 subs r4, r0, r1 + +1000c91c : +1000c91c: b364 cbz r4, 1000c978 +1000c91e: 68f0 ldr r0, [r6, #12] +1000c920: 42a0 cmp r0, r4 +1000c922: d329 bcc.n 1000c978 +1000c924: 6837 ldr r7, [r6, #0] +1000c926: 4630 mov r0, r6 +1000c928: e001 b.n 1000c92e + +1000c92a : +1000c92a: 4638 mov r0, r7 +1000c92c: 460f mov r7, r1 + +1000c92e : +1000c92e: 6879 ldr r1, [r7, #4] +1000c930: 42a1 cmp r1, r4 +1000c932: d202 bcs.n 1000c93a +1000c934: 6839 ldr r1, [r7, #0] +1000c936: 2900 cmp r1, #0 +1000c938: d1f7 bne.n 1000c92a + +1000c93a : +1000c93a: 68b1 ldr r1, [r6, #8] +1000c93c: 428f cmp r7, r1 +1000c93e: d01b beq.n 1000c978 +1000c940: 6801 ldr r1, [r0, #0] +1000c942: f101 0508 add.w r5, r1, #8 +1000c946: 6839 ldr r1, [r7, #0] +1000c948: 6001 str r1, [r0, #0] +1000c94a: 6878 ldr r0, [r7, #4] +1000c94c: 1b01 subs r1, r0, r4 +1000c94e: 2911 cmp r1, #17 +1000c950: d304 bcc.n 1000c95c +1000c952: 19e0 adds r0, r4, r7 +1000c954: 6041 str r1, [r0, #4] +1000c956: 607c str r4, [r7, #4] +1000c958: f000 f843 bl 1000c9e2 + +1000c95c : +1000c95c: 68f0 ldr r0, [r6, #12] +1000c95e: 6879 ldr r1, [r7, #4] +1000c960: 1a40 subs r0, r0, r1 +1000c962: 6931 ldr r1, [r6, #16] +1000c964: 60f0 str r0, [r6, #12] +1000c966: 4288 cmp r0, r1 +1000c968: bf38 it cc +1000c96a: 6130 strcc r0, [r6, #16] +1000c96c: 6878 ldr r0, [r7, #4] +1000c96e: 6971 ldr r1, [r6, #20] +1000c970: 4308 orrs r0, r1 +1000c972: 6078 str r0, [r7, #4] +1000c974: 2000 movs r0, #0 +1000c976: 6038 str r0, [r7, #0] + +1000c978 : +1000c978: f7fe f979 bl 1000ac6e +1000c97c: 4628 mov r0, r5 +1000c97e: bdf2 pop {r1, r4, r5, r6, r7, pc} + +1000c980 <__vPortFree>: +1000c980: b900 cbnz r0, 1000c984 +1000c982: 4770 bx lr + +1000c984 : +1000c984: b538 push {r3, r4, r5, lr} +1000c986: f1a0 0408 sub.w r4, r0, #8 +1000c98a: 4d27 ldr r5, [pc, #156] ; (1000ca28 ) +1000c98c: 6860 ldr r0, [r4, #4] +1000c98e: 6969 ldr r1, [r5, #20] +1000c990: 4208 tst r0, r1 +1000c992: d010 beq.n 1000c9b6 +1000c994: 6822 ldr r2, [r4, #0] +1000c996: b972 cbnz r2, 1000c9b6 +1000c998: 4388 bics r0, r1 +1000c99a: 6060 str r0, [r4, #4] +1000c99c: f7fe f951 bl 1000ac42 +1000c9a0: 68e8 ldr r0, [r5, #12] +1000c9a2: 6861 ldr r1, [r4, #4] +1000c9a4: 1808 adds r0, r1, r0 +1000c9a6: 60e8 str r0, [r5, #12] +1000c9a8: 4620 mov r0, r4 +1000c9aa: f000 f81a bl 1000c9e2 +1000c9ae: e8bd 4031 ldmia.w sp!, {r0, r4, r5, lr} +1000c9b2: f7fe b95c b.w 1000ac6e + +1000c9b6 : +1000c9b6: bd31 pop {r0, r4, r5, pc} + +1000c9b8 : +1000c9b8: 4b1d ldr r3, [pc, #116] ; (1000ca30 ) +1000c9ba: 6018 str r0, [r3, #0] +1000c9bc: 6059 str r1, [r3, #4] +1000c9be: 609a str r2, [r3, #8] +1000c9c0: 4770 bx lr + +1000c9c2 : +1000c9c2: 4a1b ldr r2, [pc, #108] ; (1000ca30 ) +1000c9c4: 6893 ldr r3, [r2, #8] +1000c9c6: 4298 cmp r0, r3 +1000c9c8: d306 bcc.n 1000c9d8 +1000c9ca: 6853 ldr r3, [r2, #4] +1000c9cc: 4298 cmp r0, r3 +1000c9ce: d203 bcs.n 1000c9d8 +1000c9d0: 6811 ldr r1, [r2, #0] +1000c9d2: 000a movs r2, r1 +1000c9d4: d001 beq.n 1000c9da + +1000c9d6 <__iar_annotation$$tailcall>: +1000c9d6: 4708 bx r1 + +1000c9d8 : +1000c9d8: e7d2 b.n 1000c980 <__vPortFree> + +1000c9da : +1000c9da: 4770 bx lr + +1000c9dc : +1000c9dc: 4812 ldr r0, [pc, #72] ; (1000ca28 ) +1000c9de: 68c0 ldr r0, [r0, #12] +1000c9e0: 4770 bx lr + +1000c9e2 : +1000c9e2: b530 push {r4, r5, lr} +1000c9e4: 4910 ldr r1, [pc, #64] ; (1000ca28 ) +1000c9e6: 460a mov r2, r1 +1000c9e8: e000 b.n 1000c9ec + +1000c9ea : +1000c9ea: 461a mov r2, r3 + +1000c9ec : +1000c9ec: 6813 ldr r3, [r2, #0] +1000c9ee: 4283 cmp r3, r0 +1000c9f0: d3fb bcc.n 1000c9ea +1000c9f2: 6853 ldr r3, [r2, #4] +1000c9f4: 189c adds r4, r3, r2 +1000c9f6: 4284 cmp r4, r0 +1000c9f8: d103 bne.n 1000ca02 +1000c9fa: 6840 ldr r0, [r0, #4] +1000c9fc: 18c0 adds r0, r0, r3 +1000c9fe: 6050 str r0, [r2, #4] +1000ca00: 4610 mov r0, r2 + +1000ca02 : +1000ca02: 6843 ldr r3, [r0, #4] +1000ca04: 6814 ldr r4, [r2, #0] +1000ca06: 181d adds r5, r3, r0 +1000ca08: 42a5 cmp r5, r4 +1000ca0a: d108 bne.n 1000ca1e +1000ca0c: 6889 ldr r1, [r1, #8] +1000ca0e: 428c cmp r4, r1 +1000ca10: d004 beq.n 1000ca1c +1000ca12: 6861 ldr r1, [r4, #4] +1000ca14: 18c9 adds r1, r1, r3 +1000ca16: 6041 str r1, [r0, #4] +1000ca18: 6824 ldr r4, [r4, #0] +1000ca1a: e000 b.n 1000ca1e + +1000ca1c : +1000ca1c: 460c mov r4, r1 + +1000ca1e : +1000ca1e: 6004 str r4, [r0, #0] +1000ca20: 4282 cmp r2, r0 +1000ca22: bf18 it ne +1000ca24: 6010 strne r0, [r2, #0] +1000ca26: bd30 pop {r4, r5, pc} + +1000ca28 : +1000ca28: da94 1004 .... + +1000ca2c : +1000ca2c: d400 1005 .... + +1000ca30 : +1000ca30: daac 1004 .... + +1000ca34 : +1000ca34: b51f push {r0, r1, r2, r3, r4, lr} +1000ca36: 2400 movs r4, #0 +1000ca38: f000 f945 bl 1000ccc6 +1000ca3c: 48b7 ldr r0, [pc, #732] ; (1000cd1c ) +1000ca3e: 6880 ldr r0, [r0, #8] +1000ca40: b170 cbz r0, 1000ca60 +1000ca42: f20f 21dc addw r1, pc, #732 ; 0x2dc +1000ca46: 9403 str r4, [sp, #12] +1000ca48: 2005 movs r0, #5 +1000ca4a: 9000 str r0, [sp, #0] +1000ca4c: 9402 str r4, [sp, #8] +1000ca4e: 9401 str r4, [sp, #4] +1000ca50: 2300 movs r3, #0 +1000ca52: f44f 7200 mov.w r2, #512 ; 0x200 +1000ca56: f20f 0091 addw r0, pc, #145 ; 0x91 +1000ca5a: f7fd ff65 bl 1000a928 +1000ca5e: 4604 mov r4, r0 + +1000ca60 : +1000ca60: 4620 mov r0, r4 +1000ca62: b004 add sp, #16 +1000ca64: bd10 pop {r4, pc} + +1000ca66 : +1000ca66: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1000ca6a: 4604 mov r4, r0 +1000ca6c: 000d movs r5, r1 +1000ca6e: 4616 mov r6, r2 +1000ca70: 4698 mov r8, r3 +1000ca72: bf08 it eq +1000ca74: 2700 moveq r7, #0 +1000ca76: d010 beq.n 1000ca9a +1000ca78: 2028 movs r0, #40 ; 0x28 +1000ca7a: f7ff ff1b bl 1000c8b4 +1000ca7e: 0007 movs r7, r0 +1000ca80: d00b beq.n 1000ca9a +1000ca82: f000 f920 bl 1000ccc6 +1000ca86: 603c str r4, [r7, #0] +1000ca88: 61bd str r5, [r7, #24] +1000ca8a: 61fe str r6, [r7, #28] +1000ca8c: f8c7 8020 str.w r8, [r7, #32] +1000ca90: 9806 ldr r0, [sp, #24] +1000ca92: 6278 str r0, [r7, #36] ; 0x24 +1000ca94: 1d38 adds r0, r7, #4 +1000ca96: f7ff fed2 bl 1000c83e + +1000ca9a : +1000ca9a: 4638 mov r0, r7 +1000ca9c: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +1000caa0 : +1000caa0: b57f push {r0, r1, r2, r3, r4, r5, r6, lr} +1000caa2: 4e9e ldr r6, [pc, #632] ; (1000cd1c ) +1000caa4: 4604 mov r4, r0 +1000caa6: 461d mov r5, r3 +1000caa8: 68b0 ldr r0, [r6, #8] +1000caaa: 2300 movs r3, #0 +1000caac: b1c0 cbz r0, 1000cae0 +1000caae: 9100 str r1, [sp, #0] +1000cab0: 9201 str r2, [sp, #4] +1000cab2: 9402 str r4, [sp, #8] +1000cab4: 2906 cmp r1, #6 +1000cab6: da0e bge.n 1000cad6 +1000cab8: f7fe faf1 bl 1000b09e +1000cabc: 2802 cmp r0, #2 +1000cabe: d103 bne.n 1000cac8 +1000cac0: 9a08 ldr r2, [sp, #32] +1000cac2: 68b0 ldr r0, [r6, #8] +1000cac4: 2300 movs r3, #0 +1000cac6: e002 b.n 1000cace + +1000cac8 : +1000cac8: 68b0 ldr r0, [r6, #8] +1000caca: 2300 movs r3, #0 +1000cacc: 2200 movs r2, #0 + +1000cace : +1000cace: a900 add r1, sp, #0 +1000cad0: f7fd fd54 bl 1000a57c +1000cad4: e003 b.n 1000cade + +1000cad6 : +1000cad6: 462a mov r2, r5 +1000cad8: a900 add r1, sp, #0 +1000cada: f7fd fdb1 bl 1000a640 + +1000cade : +1000cade: 4603 mov r3, r0 + +1000cae0 : +1000cae0: 4618 mov r0, r3 +1000cae2: b004 add sp, #16 +1000cae4: bd70 pop {r4, r5, r6, pc} + ... + +1000cae8 : +1000cae8: b5f0 push {r4, r5, r6, r7, lr} +1000caea: b083 sub sp, #12 +1000caec: 4c8b ldr r4, [pc, #556] ; (1000cd1c ) +1000caee: e003 b.n 1000caf8 + +1000caf0 : +1000caf0: f7fe f8bd bl 1000ac6e + +1000caf4 : +1000caf4: f000 f894 bl 1000cc20 + +1000caf8 : +1000caf8: 6820 ldr r0, [r4, #0] +1000cafa: 6801 ldr r1, [r0, #0] +1000cafc: b911 cbnz r1, 1000cb04 +1000cafe: 2701 movs r7, #1 +1000cb00: 2500 movs r5, #0 +1000cb02: e002 b.n 1000cb0a + +1000cb04 : +1000cb04: 68c0 ldr r0, [r0, #12] +1000cb06: 6805 ldr r5, [r0, #0] +1000cb08: 2700 movs r7, #0 + +1000cb0a : +1000cb0a: f7fe f89a bl 1000ac42 +1000cb0e: a801 add r0, sp, #4 +1000cb10: f000 f832 bl 1000cb78 +1000cb14: 4606 mov r6, r0 +1000cb16: 9801 ldr r0, [sp, #4] +1000cb18: 2800 cmp r0, #0 +1000cb1a: d1e9 bne.n 1000caf0 +1000cb1c: bb0f cbnz r7, 1000cb62 +1000cb1e: 42ae cmp r6, r5 +1000cb20: d31f bcc.n 1000cb62 +1000cb22: f7fe f8a4 bl 1000ac6e +1000cb26: 6820 ldr r0, [r4, #0] +1000cb28: 68c0 ldr r0, [r0, #12] +1000cb2a: 68c7 ldr r7, [r0, #12] +1000cb2c: 1d38 adds r0, r7, #4 +1000cb2e: f7ff feae bl 1000c88e +1000cb32: 69f8 ldr r0, [r7, #28] +1000cb34: 2801 cmp r0, #1 +1000cb36: d110 bne.n 1000cb5a +1000cb38: 69b8 ldr r0, [r7, #24] +1000cb3a: 1941 adds r1, r0, r5 +1000cb3c: 462b mov r3, r5 +1000cb3e: 4632 mov r2, r6 +1000cb40: 4638 mov r0, r7 +1000cb42: f000 f852 bl 1000cbea +1000cb46: 2801 cmp r0, #1 +1000cb48: d107 bne.n 1000cb5a +1000cb4a: 2000 movs r0, #0 +1000cb4c: 9000 str r0, [sp, #0] +1000cb4e: 4601 mov r1, r0 +1000cb50: 2300 movs r3, #0 +1000cb52: 462a mov r2, r5 +1000cb54: 4638 mov r0, r7 +1000cb56: f7ff ffa3 bl 1000caa0 + +1000cb5a : +1000cb5a: 6a79 ldr r1, [r7, #36] ; 0x24 +1000cb5c: 4638 mov r0, r7 +1000cb5e: 4788 blx r1 +1000cb60: e7c8 b.n 1000caf4 + +1000cb62 : +1000cb62: 68a0 ldr r0, [r4, #8] +1000cb64: 1ba9 subs r1, r5, r6 +1000cb66: f7fd fec0 bl 1000a8ea +1000cb6a: f7fe f880 bl 1000ac6e +1000cb6e: 2800 cmp r0, #0 +1000cb70: d1c0 bne.n 1000caf4 +1000cb72: f7fe fb54 bl 1000b21e +1000cb76: e7bd b.n 1000caf4 + +1000cb78 : +1000cb78: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1000cb7c: b082 sub sp, #8 +1000cb7e: 4604 mov r4, r0 +1000cb80: f7fe f8bb bl 1000acfa +1000cb84: 4e65 ldr r6, [pc, #404] ; (1000cd1c ) +1000cb86: 4605 mov r5, r0 +1000cb88: 68f0 ldr r0, [r6, #12] +1000cb8a: 4285 cmp r5, r0 +1000cb8c: d30b bcc.n 1000cba6 +1000cb8e: 2000 movs r0, #0 + +1000cb90 : +1000cb90: 6020 str r0, [r4, #0] +1000cb92: 60f5 str r5, [r6, #12] +1000cb94: 4628 mov r0, r5 +1000cb96: e8bd 81f6 ldmia.w sp!, {r1, r2, r4, r5, r6, r7, r8, pc} + +1000cb9a : +1000cb9a: 6078 str r0, [r7, #4] +1000cb9c: 613f str r7, [r7, #16] +1000cb9e: 1d39 adds r1, r7, #4 +1000cba0: 6830 ldr r0, [r6, #0] +1000cba2: f7ff fe5b bl 1000c85c + +1000cba6 : +1000cba6: 6830 ldr r0, [r6, #0] +1000cba8: 6801 ldr r1, [r0, #0] +1000cbaa: b1c9 cbz r1, 1000cbe0 +1000cbac: 68c0 ldr r0, [r0, #12] +1000cbae: f8d0 8000 ldr.w r8, [r0] +1000cbb2: 68c7 ldr r7, [r0, #12] +1000cbb4: 1d38 adds r0, r7, #4 +1000cbb6: f7ff fe6a bl 1000c88e +1000cbba: 6a79 ldr r1, [r7, #36] ; 0x24 +1000cbbc: 4638 mov r0, r7 +1000cbbe: 4788 blx r1 +1000cbc0: 69f8 ldr r0, [r7, #28] +1000cbc2: 2801 cmp r0, #1 +1000cbc4: d1ef bne.n 1000cba6 +1000cbc6: 69b8 ldr r0, [r7, #24] +1000cbc8: 4440 add r0, r8 +1000cbca: 4580 cmp r8, r0 +1000cbcc: d3e5 bcc.n 1000cb9a +1000cbce: 2000 movs r0, #0 +1000cbd0: 9000 str r0, [sp, #0] +1000cbd2: 4601 mov r1, r0 +1000cbd4: 2300 movs r3, #0 +1000cbd6: 4642 mov r2, r8 +1000cbd8: 4638 mov r0, r7 +1000cbda: f7ff ff61 bl 1000caa0 +1000cbde: e7e2 b.n 1000cba6 + +1000cbe0 : +1000cbe0: 6871 ldr r1, [r6, #4] +1000cbe2: 6070 str r0, [r6, #4] +1000cbe4: 6031 str r1, [r6, #0] +1000cbe6: 2001 movs r0, #1 +1000cbe8: e7d2 b.n 1000cb90 + +1000cbea : +1000cbea: b538 push {r3, r4, r5, lr} +1000cbec: 2400 movs r4, #0 +1000cbee: 6041 str r1, [r0, #4] +1000cbf0: 6100 str r0, [r0, #16] +1000cbf2: 428a cmp r2, r1 +1000cbf4: 4d49 ldr r5, [pc, #292] ; (1000cd1c ) +1000cbf6: d306 bcc.n 1000cc06 +1000cbf8: 1ad1 subs r1, r2, r3 +1000cbfa: 6982 ldr r2, [r0, #24] +1000cbfc: 4291 cmp r1, r2 +1000cbfe: d206 bcs.n 1000cc0e +1000cc00: 1d01 adds r1, r0, #4 +1000cc02: 6868 ldr r0, [r5, #4] +1000cc04: e007 b.n 1000cc16 + +1000cc06 : +1000cc06: 429a cmp r2, r3 +1000cc08: d203 bcs.n 1000cc12 +1000cc0a: 4299 cmp r1, r3 +1000cc0c: d301 bcc.n 1000cc12 + +1000cc0e : +1000cc0e: 2401 movs r4, #1 +1000cc10: e003 b.n 1000cc1a + +1000cc12 : +1000cc12: 1d01 adds r1, r0, #4 +1000cc14: 6828 ldr r0, [r5, #0] + +1000cc16 : +1000cc16: f7ff fe21 bl 1000c85c + +1000cc1a : +1000cc1a: 4620 mov r0, r4 +1000cc1c: bd32 pop {r1, r4, r5, pc} + ... + +1000cc20 : +1000cc20: b510 push {r4, lr} +1000cc22: b086 sub sp, #24 +1000cc24: e006 b.n 1000cc34 + +1000cc26 : +1000cc26: 9802 ldr r0, [sp, #8] +1000cc28: 61a0 str r0, [r4, #24] +1000cc2a: 1881 adds r1, r0, r2 +1000cc2c: 4613 mov r3, r2 +1000cc2e: 4620 mov r0, r4 +1000cc30: f7ff ffdb bl 1000cbea + +1000cc34 : +1000cc34: 4839 ldr r0, [pc, #228] ; (1000cd1c ) +1000cc36: 6880 ldr r0, [r0, #8] +1000cc38: 2300 movs r3, #0 +1000cc3a: 2200 movs r2, #0 +1000cc3c: a901 add r1, sp, #4 +1000cc3e: f7fd fd35 bl 1000a6ac +1000cc42: 2800 cmp r0, #0 +1000cc44: d03d beq.n 1000ccc2 +1000cc46: 9801 ldr r0, [sp, #4] +1000cc48: 2800 cmp r0, #0 +1000cc4a: d503 bpl.n 1000cc54 +1000cc4c: 9904 ldr r1, [sp, #16] +1000cc4e: 9803 ldr r0, [sp, #12] +1000cc50: 9a02 ldr r2, [sp, #8] +1000cc52: 4790 blx r2 + +1000cc54 : +1000cc54: 9801 ldr r0, [sp, #4] +1000cc56: 2800 cmp r0, #0 +1000cc58: d4ec bmi.n 1000cc34 +1000cc5a: 9c03 ldr r4, [sp, #12] +1000cc5c: 6960 ldr r0, [r4, #20] +1000cc5e: b110 cbz r0, 1000cc66 +1000cc60: 1d20 adds r0, r4, #4 +1000cc62: f7ff fe14 bl 1000c88e + +1000cc66 : +1000cc66: a805 add r0, sp, #20 +1000cc68: f7ff ff86 bl 1000cb78 +1000cc6c: 4602 mov r2, r0 +1000cc6e: 9801 ldr r0, [sp, #4] +1000cc70: 2809 cmp r0, #9 +1000cc72: d8df bhi.n 1000cc34 +1000cc74: e8df f000 tbb [pc, r0] + +1000cc78 : +1000cc78: 0707 0607 2105 0707 0506 .....!.... + +1000cc82 : +1000cc82: e7d0 b.n 1000cc26 + +1000cc84 : +1000cc84: e7d6 b.n 1000cc34 + +1000cc86 : +1000cc86: 9802 ldr r0, [sp, #8] +1000cc88: 69a1 ldr r1, [r4, #24] +1000cc8a: 4603 mov r3, r0 +1000cc8c: 1809 adds r1, r1, r0 +1000cc8e: 4620 mov r0, r4 +1000cc90: f7ff ffab bl 1000cbea +1000cc94: 2801 cmp r0, #1 +1000cc96: d1cd bne.n 1000cc34 +1000cc98: 6a61 ldr r1, [r4, #36] ; 0x24 +1000cc9a: 4620 mov r0, r4 +1000cc9c: 4788 blx r1 +1000cc9e: 69e0 ldr r0, [r4, #28] +1000cca0: 2801 cmp r0, #1 +1000cca2: d1c7 bne.n 1000cc34 +1000cca4: 2000 movs r0, #0 +1000cca6: 9000 str r0, [sp, #0] +1000cca8: 2300 movs r3, #0 +1000ccaa: 9802 ldr r0, [sp, #8] +1000ccac: 69a1 ldr r1, [r4, #24] +1000ccae: 180a adds r2, r1, r0 +1000ccb0: 4619 mov r1, r3 +1000ccb2: 4620 mov r0, r4 +1000ccb4: f7ff fef4 bl 1000caa0 +1000ccb8: e7bc b.n 1000cc34 + +1000ccba : +1000ccba: 4620 mov r0, r4 +1000ccbc: f7ff fe81 bl 1000c9c2 +1000ccc0: e7b8 b.n 1000cc34 + +1000ccc2 : +1000ccc2: b006 add sp, #24 +1000ccc4: bd10 pop {r4, pc} + +1000ccc6 : +1000ccc6: b510 push {r4, lr} +1000ccc8: f7fe fab2 bl 1000b230 +1000cccc: 4c13 ldr r4, [pc, #76] ; (1000cd1c ) +1000ccce: 68a0 ldr r0, [r4, #8] +1000ccd0: b998 cbnz r0, 1000ccfa +1000ccd2: f104 0010 add.w r0, r4, #16 +1000ccd6: f7ff fda5 bl 1000c824 +1000ccda: f104 0024 add.w r0, r4, #36 ; 0x24 +1000ccde: f7ff fda1 bl 1000c824 +1000cce2: f104 0010 add.w r0, r4, #16 +1000cce6: 6020 str r0, [r4, #0] +1000cce8: 2200 movs r2, #0 +1000ccea: f104 0024 add.w r0, r4, #36 ; 0x24 +1000ccee: 6060 str r0, [r4, #4] +1000ccf0: 2110 movs r1, #16 +1000ccf2: 200a movs r0, #10 +1000ccf4: f7fd fbf6 bl 1000a4e4 +1000ccf8: 60a0 str r0, [r4, #8] + +1000ccfa : +1000ccfa: e8bd 4010 ldmia.w sp!, {r4, lr} +1000ccfe: f7fe baa3 b.w 1000b248 + +1000cd02 : +1000cd02: b510 push {r4, lr} +1000cd04: 4604 mov r4, r0 +1000cd06: f7fe fa93 bl 1000b230 +1000cd0a: 6960 ldr r0, [r4, #20] +1000cd0c: 2800 cmp r0, #0 +1000cd0e: bf14 ite ne +1000cd10: 2401 movne r4, #1 +1000cd12: 2400 moveq r4, #0 +1000cd14: f7fe fa98 bl 1000b248 +1000cd18: 4620 mov r0, r4 +1000cd1a: bd10 pop {r4, pc} + +1000cd1c : +1000cd1c: 7b0c 1004 .{.. + +1000cd20 : +1000cd20: 6d54 2072 7653 0063 Tmr Svc. + +1000cd28 : +1000cd28: 4814 ldr r0, [pc, #80] ; (1000cd7c ) +1000cd2a: 6800 ldr r0, [r0, #0] +1000cd2c: 1e40 subs r0, r0, #1 +1000cd2e: 4180 sbcs r0, r0 +1000cd30: 0fc0 lsrs r0, r0, #31 +1000cd32: 4770 bx lr + +1000cd34 : +1000cd34: b570 push {r4, r5, r6, lr} +1000cd36: 6804 ldr r4, [r0, #0] +1000cd38: 4d11 ldr r5, [pc, #68] ; (1000cd80 ) +1000cd3a: 2100 movs r1, #0 +1000cd3c: 6001 str r1, [r0, #0] +1000cd3e: 682e ldr r6, [r5, #0] +1000cd40: 0730 lsls r0, r6, #28 +1000cd42: bf48 it mi +1000cd44: f003 f9c5 blmi 100100d2 +1000cd48: 4621 mov r1, r4 +1000cd4a: 4630 mov r0, r6 +1000cd4c: f003 fc3a bl 100105c4 +1000cd50: 7828 ldrb r0, [r5, #0] +1000cd52: 0700 lsls r0, r0, #28 +1000cd54: bf48 it mi +1000cd56: f003 f9c5 blmi 100100e4 +1000cd5a: bd70 pop {r4, r5, r6, pc} + +1000cd5c : +1000cd5c: 4907 ldr r1, [pc, #28] ; (1000cd7c ) +1000cd5e: e008 b.n 1000cd72 + +1000cd60 : +1000cd60: 4906 ldr r1, [pc, #24] ; (1000cd7c ) +1000cd62: 680a ldr r2, [r1, #0] +1000cd64: ea22 0000 bic.w r0, r2, r0 +1000cd68: 6008 str r0, [r1, #0] +1000cd6a: 4770 bx lr + +1000cd6c : +1000cd6c: 4803 ldr r0, [pc, #12] ; (1000cd7c ) +1000cd6e: 6800 ldr r0, [r0, #0] +1000cd70: 4770 bx lr + +1000cd72 : +1000cd72: 680a ldr r2, [r1, #0] +1000cd74: 4310 orrs r0, r2 +1000cd76: 6008 str r0, [r1, #0] +1000cd78: 4770 bx lr + ... + +1000cd7c : +1000cd7c: 3fac 1004 .?.. + +1000cd80 : +1000cd80: 3fb0 1004 .?.. + +1000cd84 : +1000cd84: b538 push {r3, r4, r5, lr} +1000cd86: f8df 04e8 ldr.w r0, [pc, #1256] ; 1000d270 +1000cd8a: 6845 ldr r5, [r0, #4] +1000cd8c: 2400 movs r4, #0 +1000cd8e: e003 b.n 1000cd98 + +1000cd90 : +1000cd90: 1e40 subs r0, r0, #1 +1000cd92: 77e8 strb r0, [r5, #31] +1000cd94: 462c mov r4, r5 +1000cd96: 460d mov r5, r1 + +1000cd98 : +1000cd98: b14d cbz r5, 1000cdae +1000cd9a: 7fe8 ldrb r0, [r5, #31] +1000cd9c: 6829 ldr r1, [r5, #0] +1000cd9e: 2800 cmp r0, #0 +1000cda0: d1f6 bne.n 1000cd90 +1000cda2: 4628 mov r0, r5 +1000cda4: 460d mov r5, r1 +1000cda6: 4621 mov r1, r4 +1000cda8: f000 f802 bl 1000cdb0 +1000cdac: e7f4 b.n 1000cd98 + +1000cdae : +1000cdae: bd31 pop {r0, r4, r5, pc} + +1000cdb0 : +1000cdb0: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1000cdb4: 4605 mov r5, r0 +1000cdb6: 460e mov r6, r1 +1000cdb8: 686f ldr r7, [r5, #4] +1000cdba: 6878 ldr r0, [r7, #4] +1000cdbc: 8881 ldrh r1, [r0, #4] +1000cdbe: 2400 movs r4, #0 +1000cdc0: b991 cbnz r1, 1000cde8 +1000cdc2: 6800 ldr r0, [r0, #0] +1000cdc4: 6068 str r0, [r5, #4] +1000cdc6: 2214 movs r2, #20 +1000cdc8: 6878 ldr r0, [r7, #4] +1000cdca: f105 0108 add.w r1, r5, #8 +1000cdce: f7ff fabb bl 1000c348 +1000cdd2: 2101 movs r1, #1 +1000cdd4: 4638 mov r0, r7 +1000cdd6: f7ff fcf0 bl 1000c7ba +1000cdda: 4638 mov r0, r7 +1000cddc: f7fb fd32 bl 10008844 +1000cde0: 4604 mov r4, r0 +1000cde2: 4638 mov r0, r7 +1000cde4: f7fb fd00 bl 100087e8 + +1000cde8 : +1000cde8: 686f ldr r7, [r5, #4] +1000cdea: e00a b.n 1000ce02 + +1000cdec : +1000cdec: 6878 ldr r0, [r7, #4] +1000cdee: 46b8 mov r8, r7 +1000cdf0: 6807 ldr r7, [r0, #0] +1000cdf2: 4640 mov r0, r8 +1000cdf4: f7fb fd26 bl 10008844 +1000cdf8: 1904 adds r4, r0, r4 +1000cdfa: b2a4 uxth r4, r4 +1000cdfc: 4640 mov r0, r8 +1000cdfe: f7fb fcf3 bl 100087e8 + +1000ce02 : +1000ce02: 2f00 cmp r7, #0 +1000ce04: d1f2 bne.n 1000cdec +1000ce06: 4631 mov r1, r6 +1000ce08: 4628 mov r0, r5 +1000ce0a: f000 f83c bl 1000ce86 +1000ce0e: f8df 0460 ldr.w r0, [pc, #1120] ; 1000d270 +1000ce12: 8801 ldrh r1, [r0, #0] +1000ce14: 1b09 subs r1, r1, r4 +1000ce16: 8001 strh r1, [r0, #0] +1000ce18: 4620 mov r0, r4 +1000ce1a: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +1000ce1e : +1000ce1e: b5f8 push {r3, r4, r5, r6, r7, lr} +1000ce20: 4604 mov r4, r0 +1000ce22: 460d mov r5, r1 +1000ce24: 2600 movs r6, #0 + +1000ce26 : +1000ce26: f8df 2448 ldr.w r2, [pc, #1096] ; 1000d270 +1000ce2a: 6852 ldr r2, [r2, #4] +1000ce2c: 2000 movs r0, #0 +1000ce2e: 2100 movs r1, #0 +1000ce30: 4607 mov r7, r0 +1000ce32: 2a00 cmp r2, #0 +1000ce34: e009 b.n 1000ce4a + +1000ce36 : +1000ce36: 7fc3 ldrb r3, [r0, #31] +1000ce38: f892 c01f ldrb.w ip, [r2, #31] +1000ce3c: 4563 cmp r3, ip +1000ce3e: d300 bcc.n 1000ce42 + +1000ce40 : +1000ce40: 4610 mov r0, r2 + +1000ce42 : +1000ce42: 6813 ldr r3, [r2, #0] +1000ce44: b103 cbz r3, 1000ce48 +1000ce46: 4611 mov r1, r2 + +1000ce48 : +1000ce48: 001a movs r2, r3 + +1000ce4a : +1000ce4a: d012 beq.n 1000ce72 +1000ce4c: 6953 ldr r3, [r2, #20] +1000ce4e: f8d4 c00c ldr.w ip, [r4, #12] +1000ce52: 4563 cmp r3, ip +1000ce54: bf02 ittt eq +1000ce56: 6993 ldreq r3, [r2, #24] +1000ce58: f8d4 c010 ldreq.w ip, [r4, #16] +1000ce5c: 4563 cmpeq r3, ip +1000ce5e: bf02 ittt eq +1000ce60: 8993 ldrheq r3, [r2, #12] +1000ce62: f8b4 c004 ldrheq.w ip, [r4, #4] +1000ce66: 4563 cmpeq r3, ip +1000ce68: d0eb beq.n 1000ce42 +1000ce6a: 1c7f adds r7, r7, #1 +1000ce6c: 2800 cmp r0, #0 +1000ce6e: d1e2 bne.n 1000ce36 +1000ce70: e7e6 b.n 1000ce40 + +1000ce72 : +1000ce72: b110 cbz r0, 1000ce7a +1000ce74: f7ff ff9c bl 1000cdb0 +1000ce78: 1986 adds r6, r0, r6 + +1000ce7a : +1000ce7a: 42ae cmp r6, r5 +1000ce7c: da01 bge.n 1000ce82 +1000ce7e: 2f02 cmp r7, #2 +1000ce80: dad1 bge.n 1000ce26 + +1000ce82 : +1000ce82: 4630 mov r0, r6 +1000ce84: bdf2 pop {r1, r4, r5, r6, r7, pc} + +1000ce86 : +1000ce86: b510 push {r4, lr} +1000ce88: f8df 33e4 ldr.w r3, [pc, #996] ; 1000d270 +1000ce8c: 6802 ldr r2, [r0, #0] +1000ce8e: 685c ldr r4, [r3, #4] +1000ce90: 4284 cmp r4, r0 +1000ce92: bf0c ite eq +1000ce94: 605a streq r2, [r3, #4] +1000ce96: 600a strne r2, [r1, #0] +1000ce98: e8bd 4010 ldmia.w sp!, {r4, lr} +1000ce9c: 4601 mov r1, r0 +1000ce9e: 2005 movs r0, #5 +1000cea0: f7fb ba32 b.w 10008308 + +1000cea4 : +1000cea4: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +1000cea8: 460c mov r4, r1 +1000ceaa: 4605 mov r5, r0 +1000ceac: f8d4 9004 ldr.w r9, [r4, #4] +1000ceb0: f8b9 0002 ldrh.w r0, [r9, #2] +1000ceb4: 2600 movs r6, #0 +1000ceb6: 2701 movs r7, #1 +1000ceb8: f7ff fb4a bl 1000c550 +1000cebc: f899 1000 ldrb.w r1, [r9] +1000cec0: f001 010f and.w r1, r1, #15 +1000cec4: eba0 0081 sub.w r0, r0, r1, lsl #2 +1000cec8: fa1f f880 uxth.w r8, r0 +1000cecc: f8b9 0006 ldrh.w r0, [r9, #6] +1000ced0: f7ff fb3e bl 1000c550 +1000ced4: 00c1 lsls r1, r0, #3 +1000ced6: 6860 ldr r0, [r4, #4] +1000ced8: 6006 str r6, [r0, #0] +1000ceda: 8081 strh r1, [r0, #4] +1000cedc: 4441 add r1, r8 +1000cede: 80c1 strh r1, [r0, #6] +1000cee0: 686a ldr r2, [r5, #4] +1000cee2: e00c b.n 1000cefe + +1000cee4 : +1000cee4: d03a beq.n 1000cf5c +1000cee6: f8be 2006 ldrh.w r2, [lr, #6] +1000ceea: 4293 cmp r3, r2 +1000ceec: d336 bcc.n 1000cf5c +1000ceee: 2e00 cmp r6, #0 +1000cef0: bf1e ittt ne +1000cef2: 88f2 ldrhne r2, [r6, #6] +1000cef4: 4562 cmpne r2, ip +1000cef6: 2700 movne r7, #0 +1000cef8: f8de 2000 ldr.w r2, [lr] +1000cefc: 4676 mov r6, lr + +1000cefe : +1000cefe: b192 cbz r2, 1000cf26 +1000cf00: f8d2 e004 ldr.w lr, [r2, #4] +1000cf04: 8883 ldrh r3, [r0, #4] +1000cf06: f8be c004 ldrh.w ip, [lr, #4] +1000cf0a: 4563 cmp r3, ip +1000cf0c: d2ea bcs.n 1000cee4 +1000cf0e: 6002 str r2, [r0, #0] +1000cf10: b90e cbnz r6, 1000cf16 + +1000cf12 : +1000cf12: 606c str r4, [r5, #4] +1000cf14: e00f b.n 1000cf36 + +1000cf16 : +1000cf16: 88f2 ldrh r2, [r6, #6] +1000cf18: 4293 cmp r3, r2 +1000cf1a: bf24 itt cs +1000cf1c: b289 uxthcs r1, r1 +1000cf1e: 458c cmpcs ip, r1 +1000cf20: d31c bcc.n 1000cf5c +1000cf22: 6034 str r4, [r6, #0] +1000cf24: e007 b.n 1000cf36 + +1000cf26 : +1000cf26: 2e00 cmp r6, #0 +1000cf28: d0f3 beq.n 1000cf12 +1000cf2a: 6034 str r4, [r6, #0] +1000cf2c: 88f1 ldrh r1, [r6, #6] +1000cf2e: 8882 ldrh r2, [r0, #4] +1000cf30: 4291 cmp r1, r2 +1000cf32: bf18 it ne +1000cf34: 2700 movne r7, #0 + +1000cf36 : +1000cf36: 7fa9 ldrb r1, [r5, #30] +1000cf38: 07c9 lsls r1, r1, #31 +1000cf3a: d519 bpl.n 1000cf70 +1000cf3c: b167 cbz r7, 1000cf58 +1000cf3e: 6869 ldr r1, [r5, #4] +1000cf40: 6849 ldr r1, [r1, #4] +1000cf42: 8889 ldrh r1, [r1, #4] +1000cf44: b939 cbnz r1, 1000cf56 + +1000cf46 : +1000cf46: 6802 ldr r2, [r0, #0] +1000cf48: 4606 mov r6, r0 +1000cf4a: b12a cbz r2, 1000cf58 +1000cf4c: 6850 ldr r0, [r2, #4] +1000cf4e: 88f1 ldrh r1, [r6, #6] +1000cf50: 8882 ldrh r2, [r0, #4] +1000cf52: 4291 cmp r1, r2 +1000cf54: d0f7 beq.n 1000cf46 + +1000cf56 : +1000cf56: 2700 movs r7, #0 + +1000cf58 : +1000cf58: 4638 mov r0, r7 +1000cf5a: e00a b.n 1000cf72 + +1000cf5c : +1000cf5c: 4620 mov r0, r4 +1000cf5e: f7fb fc71 bl 10008844 +1000cf62: 49c3 ldr r1, [pc, #780] ; (1000d270 ) +1000cf64: 880a ldrh r2, [r1, #0] +1000cf66: 1a10 subs r0, r2, r0 +1000cf68: 8008 strh r0, [r1, #0] +1000cf6a: 4620 mov r0, r4 +1000cf6c: f7fb fc3c bl 100087e8 + +1000cf70 : +1000cf70: 2000 movs r0, #0 + +1000cf72 : +1000cf72: e8bd 83f2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, pc} + +1000cf76 : +1000cf76: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +1000cf7a: 4680 mov r8, r0 +1000cf7c: b082 sub sp, #8 +1000cf7e: f8d8 5004 ldr.w r5, [r8, #4] +1000cf82: 7828 ldrb r0, [r5, #0] +1000cf84: f000 000f and.w r0, r0, #15 +1000cf88: 0080 lsls r0, r0, #2 +1000cf8a: f04f 0900 mov.w r9, #0 +1000cf8e: 2814 cmp r0, #20 +1000cf90: d152 bne.n 1000d038 +1000cf92: 88e8 ldrh r0, [r5, #6] +1000cf94: f7ff fadc bl 1000c550 +1000cf98: 04c0 lsls r0, r0, #19 +1000cf9a: 0c07 lsrs r7, r0, #16 +1000cf9c: 8868 ldrh r0, [r5, #2] +1000cf9e: f7ff fad7 bl 1000c550 +1000cfa2: 7829 ldrb r1, [r5, #0] +1000cfa4: f001 010f and.w r1, r1, #15 +1000cfa8: eba0 0081 sub.w r0, r0, r1, lsl #2 +1000cfac: b280 uxth r0, r0 +1000cfae: 9000 str r0, [sp, #0] +1000cfb0: 4640 mov r0, r8 +1000cfb2: f7fb fc47 bl 10008844 +1000cfb6: 4eae ldr r6, [pc, #696] ; (1000d270 ) +1000cfb8: 4682 mov sl, r0 +1000cfba: 8830 ldrh r0, [r6, #0] +1000cfbc: 4450 add r0, sl +1000cfbe: 280b cmp r0, #11 +1000cfc0: db08 blt.n 1000cfd4 +1000cfc2: 4651 mov r1, sl +1000cfc4: 4628 mov r0, r5 +1000cfc6: f7ff ff2a bl 1000ce1e +1000cfca: b3a8 cbz r0, 1000d038 +1000cfcc: 8830 ldrh r0, [r6, #0] +1000cfce: 4450 add r0, sl +1000cfd0: 280b cmp r0, #11 +1000cfd2: da31 bge.n 1000d038 + +1000cfd4 : +1000cfd4: 6874 ldr r4, [r6, #4] +1000cfd6: e00d b.n 1000cff4 + +1000cfd8 : +1000cfd8: 6960 ldr r0, [r4, #20] +1000cfda: 68e9 ldr r1, [r5, #12] +1000cfdc: 4288 cmp r0, r1 +1000cfde: bf02 ittt eq +1000cfe0: 69a0 ldreq r0, [r4, #24] +1000cfe2: 6929 ldreq r1, [r5, #16] +1000cfe4: 4288 cmpeq r0, r1 +1000cfe6: bf02 ittt eq +1000cfe8: 89a0 ldrheq r0, [r4, #12] +1000cfea: 88a9 ldrheq r1, [r5, #4] +1000cfec: 4288 cmpeq r0, r1 +1000cfee: d029 beq.n 1000d044 +1000cff0: 46a1 mov r9, r4 +1000cff2: 6824 ldr r4, [r4, #0] + +1000cff4 : +1000cff4: 2c00 cmp r4, #0 +1000cff6: d1ef bne.n 1000cfd8 +1000cff8: 2005 movs r0, #5 +1000cffa: f7fb f972 bl 100082e2 +1000cffe: 0004 movs r4, r0 +1000d000: d10c bne.n 1000d01c +1000d002: 4651 mov r1, sl +1000d004: 4628 mov r0, r5 +1000d006: f7ff ff0a bl 1000ce1e +1000d00a: 4550 cmp r0, sl +1000d00c: db04 blt.n 1000d018 +1000d00e: 2005 movs r0, #5 +1000d010: f7fb f967 bl 100082e2 +1000d014: 0004 movs r4, r0 +1000d016: d101 bne.n 1000d01c + +1000d018 : +1000d018: 2400 movs r4, #0 +1000d01a: e00c b.n 1000d036 + +1000d01c : +1000d01c: 2220 movs r2, #32 +1000d01e: 2100 movs r1, #0 +1000d020: 4620 mov r0, r4 +1000d022: f7ff f993 bl 1000c34c +1000d026: 2003 movs r0, #3 +1000d028: 77e0 strb r0, [r4, #31] +1000d02a: 2214 movs r2, #20 +1000d02c: 6870 ldr r0, [r6, #4] +1000d02e: 6020 str r0, [r4, #0] +1000d030: 6074 str r4, [r6, #4] +1000d032: f000 f85b bl 1000d0ec + +1000d036 : +1000d036: b994 cbnz r4, 1000d05e + +1000d038 : +1000d038: 4640 mov r0, r8 +1000d03a: f7fb fbd5 bl 100087e8 +1000d03e: 2000 movs r0, #0 + +1000d040 : +1000d040: e8bd 87f6 ldmia.w sp!, {r1, r2, r4, r5, r6, r7, r8, r9, sl, pc} + +1000d044 : +1000d044: 88e8 ldrh r0, [r5, #6] +1000d046: f7ff fa83 bl 1000c550 +1000d04a: 04c0 lsls r0, r0, #19 +1000d04c: d107 bne.n 1000d05e +1000d04e: 89e0 ldrh r0, [r4, #14] +1000d050: f7ff fa7e bl 1000c550 +1000d054: 04c0 lsls r0, r0, #19 +1000d056: d002 beq.n 1000d05e +1000d058: 2214 movs r2, #20 +1000d05a: f000 f847 bl 1000d0ec + +1000d05e : +1000d05e: 8830 ldrh r0, [r6, #0] +1000d060: 4450 add r0, sl +1000d062: 8030 strh r0, [r6, #0] +1000d064: 79a8 ldrb r0, [r5, #6] +1000d066: 0680 lsls r0, r0, #26 +1000d068: d406 bmi.n 1000d078 +1000d06a: 7fa0 ldrb r0, [r4, #30] +1000d06c: f040 0001 orr.w r0, r0, #1 +1000d070: 77a0 strb r0, [r4, #30] +1000d072: 9800 ldr r0, [sp, #0] +1000d074: 19c0 adds r0, r0, r7 +1000d076: 83a0 strh r0, [r4, #28] + +1000d078 : +1000d078: 4641 mov r1, r8 +1000d07a: 4620 mov r0, r4 +1000d07c: f7ff ff12 bl 1000cea4 +1000d080: 2800 cmp r0, #0 +1000d082: d0dd beq.n 1000d040 +1000d084: 8ba0 ldrh r0, [r4, #28] +1000d086: 3014 adds r0, #20 +1000d088: 83a0 strh r0, [r4, #28] +1000d08a: 2214 movs r2, #20 +1000d08c: 6860 ldr r0, [r4, #4] +1000d08e: 6845 ldr r5, [r0, #4] +1000d090: 682f ldr r7, [r5, #0] +1000d092: f104 0108 add.w r1, r4, #8 +1000d096: 4628 mov r0, r5 +1000d098: f7ff f956 bl 1000c348 +1000d09c: 8ba0 ldrh r0, [r4, #28] +1000d09e: f7ff fa52 bl 1000c546 +1000d0a2: 8068 strh r0, [r5, #2] +1000d0a4: 2114 movs r1, #20 +1000d0a6: 2000 movs r0, #0 +1000d0a8: 80e8 strh r0, [r5, #6] +1000d0aa: 8168 strh r0, [r5, #10] +1000d0ac: 4628 mov r0, r5 +1000d0ae: f7ff faca bl 1000c646 +1000d0b2: 8168 strh r0, [r5, #10] +1000d0b4: f8d4 8004 ldr.w r8, [r4, #4] +1000d0b8: e00a b.n 1000d0d0 + +1000d0ba : +1000d0ba: 687d ldr r5, [r7, #4] +1000d0bc: f06f 0113 mvn.w r1, #19 +1000d0c0: 4638 mov r0, r7 +1000d0c2: f7fb fb60 bl 10008786 +1000d0c6: 4639 mov r1, r7 +1000d0c8: 4640 mov r0, r8 +1000d0ca: f7fb fbd0 bl 1000886e +1000d0ce: 682f ldr r7, [r5, #0] + +1000d0d0 : +1000d0d0: 2f00 cmp r7, #0 +1000d0d2: d1f2 bne.n 1000d0ba +1000d0d4: 4649 mov r1, r9 +1000d0d6: 4620 mov r0, r4 +1000d0d8: f7ff fed5 bl 1000ce86 +1000d0dc: 4640 mov r0, r8 +1000d0de: f7fb fbb1 bl 10008844 +1000d0e2: 8831 ldrh r1, [r6, #0] +1000d0e4: 1a08 subs r0, r1, r0 +1000d0e6: 8030 strh r0, [r6, #0] +1000d0e8: 4640 mov r0, r8 +1000d0ea: e7a9 b.n 1000d040 + +1000d0ec : +1000d0ec: 4629 mov r1, r5 +1000d0ee: f104 0008 add.w r0, r4, #8 +1000d0f2: f7ff b929 b.w 1000c348 + +1000d0f6 : +1000d0f6: 4601 mov r1, r0 +1000d0f8: 2006 movs r0, #6 +1000d0fa: f7fb b905 b.w 10008308 + +1000d0fe : +1000d0fe: b510 push {r4, lr} +1000d100: 4604 mov r4, r0 +1000d102: 6960 ldr r0, [r4, #20] +1000d104: b108 cbz r0, 1000d10a +1000d106: f7fb fb6f bl 100087e8 + +1000d10a : +1000d10a: 4620 mov r0, r4 +1000d10c: e8bd 4010 ldmia.w sp!, {r4, lr} +1000d110: e7f1 b.n 1000d0f6 + +1000d112 : +1000d112: e92d 4ff6 stmdb sp!, {r1, r2, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1000d116: 4605 mov r5, r0 +1000d118: b089 sub sp, #36 ; 0x24 +1000d11a: 8d0f ldrh r7, [r1, #40] ; 0x28 +1000d11c: 6868 ldr r0, [r5, #4] +1000d11e: 9007 str r0, [sp, #28] +1000d120: 2614 movs r6, #20 +1000d122: 88c0 ldrh r0, [r0, #6] +1000d124: 2400 movs r4, #0 +1000d126: f7ff fa13 bl 1000c550 +1000d12a: 4601 mov r1, r0 +1000d12c: 04c8 lsls r0, r1, #19 +1000d12e: 0cc0 lsrs r0, r0, #19 +1000d130: 9004 str r0, [sp, #16] +1000d132: f401 5000 and.w r0, r1, #8192 ; 0x2000 +1000d136: 9008 str r0, [sp, #32] +1000d138: 8928 ldrh r0, [r5, #8] +1000d13a: 3814 subs r0, #20 +1000d13c: b280 uxth r0, r0 +1000d13e: 9003 str r0, [sp, #12] +1000d140: f1a7 0014 sub.w r0, r7, #20 +1000d144: 9006 str r0, [sp, #24] +1000d146: 1081 asrs r1, r0, #2 +1000d148: eb00 7051 add.w r0, r0, r1, lsr #29 +1000d14c: 0340 lsls r0, r0, #13 +1000d14e: 0c00 lsrs r0, r0, #16 +1000d150: 9005 str r0, [sp, #20] +1000d152: e037 b.n 1000d1c4 + +1000d154 : +1000d154: 4628 mov r0, r5 +1000d156: f7fb fb7d bl 10008854 +1000d15a: f8ca 5014 str.w r5, [sl, #20] +1000d15e: 4659 mov r1, fp +1000d160: 4844 ldr r0, [pc, #272] ; (1000d274 ) +1000d162: f8ca 0010 str.w r0, [sl, #16] +1000d166: 4648 mov r0, r9 +1000d168: f7fb fb81 bl 1000886e +1000d16c: 1b36 subs r6, r6, r4 +1000d16e: b2b6 uxth r6, r6 +1000d170: 2e00 cmp r6, #0 +1000d172: d157 bne.n 1000d224 + +1000d174 : +1000d174: 4626 mov r6, r4 +1000d176: fa1f f088 uxth.w r0, r8 +1000d17a: f7ff f9e4 bl 1000c546 +1000d17e: 9902 ldr r1, [sp, #8] +1000d180: 80c8 strh r0, [r1, #6] +1000d182: f107 0014 add.w r0, r7, #20 +1000d186: b280 uxth r0, r0 +1000d188: f7ff f9dd bl 1000c546 +1000d18c: 9902 ldr r1, [sp, #8] +1000d18e: 8048 strh r0, [r1, #2] +1000d190: 2000 movs r0, #0 +1000d192: 9902 ldr r1, [sp, #8] +1000d194: 8148 strh r0, [r1, #10] +1000d196: 2114 movs r1, #20 +1000d198: 9802 ldr r0, [sp, #8] +1000d19a: f7ff fa54 bl 1000c646 +1000d19e: 9902 ldr r1, [sp, #8] +1000d1a0: 8148 strh r0, [r1, #10] +1000d1a2: 4649 mov r1, r9 +1000d1a4: 9809 ldr r0, [sp, #36] ; 0x24 +1000d1a6: 9a0a ldr r2, [sp, #40] ; 0x28 +1000d1a8: 6943 ldr r3, [r0, #20] +1000d1aa: 4798 blx r3 +1000d1ac: 4648 mov r0, r9 +1000d1ae: f7fb fb1b bl 100087e8 +1000d1b2: 9803 ldr r0, [sp, #12] +1000d1b4: 9905 ldr r1, [sp, #20] +1000d1b6: 1bc0 subs r0, r0, r7 +1000d1b8: b280 uxth r0, r0 +1000d1ba: 9003 str r0, [sp, #12] +1000d1bc: 9804 ldr r0, [sp, #16] +1000d1be: 1808 adds r0, r1, r0 +1000d1c0: b280 uxth r0, r0 +1000d1c2: 9004 str r0, [sp, #16] + +1000d1c4 : +1000d1c4: 9803 ldr r0, [sp, #12] +1000d1c6: 2800 cmp r0, #0 +1000d1c8: d04e beq.n 1000d268 +1000d1ca: 9806 ldr r0, [sp, #24] +1000d1cc: 9903 ldr r1, [sp, #12] +1000d1ce: 4288 cmp r0, r1 +1000d1d0: bfac ite ge +1000d1d2: 2001 movge r0, #1 +1000d1d4: 2000 movlt r0, #0 +1000d1d6: 9a04 ldr r2, [sp, #16] +1000d1d8: 9908 ldr r1, [sp, #32] +1000d1da: 04d2 lsls r2, r2, #19 +1000d1dc: ea41 48d2 orr.w r8, r1, r2, lsr #19 +1000d1e0: 2800 cmp r0, #0 +1000d1e2: bf03 ittte eq +1000d1e4: f448 5800 orreq.w r8, r8, #8192 ; 0x2000 +1000d1e8: 9805 ldreq r0, [sp, #20] +1000d1ea: 00c7 lsleq r7, r0, #3 +1000d1ec: 9f03 ldrne r7, [sp, #12] +1000d1ee: 2200 movs r2, #0 +1000d1f0: 2114 movs r1, #20 +1000d1f2: 2002 movs r0, #2 +1000d1f4: f7fb f9e8 bl 100085c8 +1000d1f8: ea5f 0900 movs.w r9, r0 +1000d1fc: d032 beq.n 1000d264 +1000d1fe: 9907 ldr r1, [sp, #28] +1000d200: f8d9 0004 ldr.w r0, [r9, #4] +1000d204: 2214 movs r2, #20 +1000d206: f7ff f89f bl 1000c348 +1000d20a: f8d9 0004 ldr.w r0, [r9, #4] +1000d20e: 9002 str r0, [sp, #8] +1000d210: b2bf uxth r7, r7 +1000d212: 6868 ldr r0, [r5, #4] +1000d214: 1830 adds r0, r6, r0 +1000d216: 6068 str r0, [r5, #4] +1000d218: 8968 ldrh r0, [r5, #10] +1000d21a: 1b80 subs r0, r0, r6 +1000d21c: 8168 strh r0, [r5, #10] +1000d21e: 003e movs r6, r7 +1000d220: d101 bne.n 1000d226 +1000d222: e7a7 b.n 1000d174 + +1000d224 : +1000d224: 682d ldr r5, [r5, #0] + +1000d226 : +1000d226: 896c ldrh r4, [r5, #10] +1000d228: 42a6 cmp r6, r4 +1000d22a: bfb8 it lt +1000d22c: 4634 movlt r4, r6 +1000d22e: 2c00 cmp r4, #0 +1000d230: d0f8 beq.n 1000d224 +1000d232: 2006 movs r0, #6 +1000d234: f7fb f855 bl 100082e2 +1000d238: ea5f 0a00 movs.w sl, r0 +1000d23c: d00f beq.n 1000d25e +1000d23e: 9401 str r4, [sp, #4] +1000d240: 4653 mov r3, sl +1000d242: 6868 ldr r0, [r5, #4] +1000d244: 9000 str r0, [sp, #0] +1000d246: 2202 movs r2, #2 +1000d248: b2a1 uxth r1, r4 +1000d24a: 2003 movs r0, #3 +1000d24c: f7fb fa4d bl 100086ea +1000d250: ea5f 0b00 movs.w fp, r0 +1000d254: f47f af7e bne.w 1000d154 +1000d258: 4650 mov r0, sl +1000d25a: f7ff ff4c bl 1000d0f6 + +1000d25e : +1000d25e: 4648 mov r0, r9 +1000d260: f7fb fac2 bl 100087e8 + +1000d264 : +1000d264: f04f 30ff mov.w r0, #4294967295 + +1000d268 : +1000d268: b00b add sp, #44 ; 0x2c +1000d26a: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + ... + +1000d270 : +1000d270: 771c 1004 .w.. + +1000d274 : +1000d274: d0ff 1000 .... + +1000d278 : +1000d278: b538 push {r3, r4, r5, lr} +1000d27a: 4604 mov r4, r0 +1000d27c: 2108 movs r1, #8 +1000d27e: 6a25 ldr r5, [r4, #32] +1000d280: 4628 mov r0, r5 +1000d282: f000 fb57 bl 1000d934 +1000d286: 2200 movs r2, #0 +1000d288: f105 0124 add.w r1, r5, #36 ; 0x24 +1000d28c: 4620 mov r0, r4 +1000d28e: f7fe fbd9 bl 1000ba44 +1000d292: 7b68 ldrb r0, [r5, #13] +1000d294: 1c40 adds r0, r0, #1 +1000d296: 7368 strb r0, [r5, #13] +1000d298: 2001 movs r0, #1 +1000d29a: 8368 strh r0, [r5, #26] +1000d29c: bd31 pop {r0, r4, r5, pc} + +1000d29e : +1000d29e: b570 push {r4, r5, r6, lr} +1000d2a0: 4606 mov r6, r0 +1000d2a2: b082 sub sp, #8 +1000d2a4: 6a34 ldr r4, [r6, #32] +1000d2a6: 2101 movs r1, #1 +1000d2a8: f000 fa1a bl 1000d6e0 + +1000d2ac : +1000d2ac: f000 fa44 bl 1000d738 + +1000d2b0 : +1000d2b0: 0005 movs r5, r0 +1000d2b2: d12c bne.n 1000d30e +1000d2b4: f000 fa79 bl 1000d7aa + +1000d2b8 : +1000d2b8: f000 f974 bl 1000d5a4 + +1000d2bc : +1000d2bc: 2204 movs r2, #4 +1000d2be: 2132 movs r1, #50 ; 0x32 +1000d2c0: f000 fa75 bl 1000d7ae + +1000d2c4 : +1000d2c4: 6a60 ldr r0, [r4, #36] ; 0x24 +1000d2c6: f7ff f950 bl 1000c56a +1000d2ca: f000 f91c bl 1000d506 + +1000d2ce : +1000d2ce: 2204 movs r2, #4 +1000d2d0: 2136 movs r1, #54 ; 0x36 +1000d2d2: f000 fa6c bl 1000d7ae + +1000d2d6 : +1000d2d6: 6a20 ldr r0, [r4, #32] +1000d2d8: f7ff f947 bl 1000c56a +1000d2dc: f000 f913 bl 1000d506 + +1000d2e0 : +1000d2e0: 2204 movs r2, #4 +1000d2e2: 2137 movs r1, #55 ; 0x37 +1000d2e4: f000 fa63 bl 1000d7ae + +1000d2e8 : +1000d2e8: f000 f95f bl 1000d5aa + +1000d2ec : +1000d2ec: 2103 movs r1, #3 +1000d2ee: f000 f95d bl 1000d5ac + +1000d2f2 : +1000d2f2: 211c movs r1, #28 +1000d2f4: f000 f95a bl 1000d5ac + +1000d2f8 : +1000d2f8: 2106 movs r1, #6 +1000d2fa: f000 f957 bl 1000d5ac + +1000d2fe : +1000d2fe: f000 f9ed bl 1000d6dc + +1000d302 : +1000d302: f000 f9e2 bl 1000d6ca + +1000d306 : +1000d306: f000 f945 bl 1000d594 + +1000d30a : +1000d30a: f000 f9e5 bl 1000d6d8 + +1000d30e : +1000d30e: e128 b.n 1000d562 + +1000d310 : +1000d310: b510 push {r4, lr} +1000d312: f8df 0aec ldr.w r0, [pc, #2796] ; 1000de00 +1000d316: 6804 ldr r4, [r0, #0] +1000d318: e00d b.n 1000d336 + +1000d31a : +1000d31a: 8b88 ldrh r0, [r1, #28] +1000d31c: 1e42 subs r2, r0, #1 +1000d31e: 838a strh r2, [r1, #28] +1000d320: d108 bne.n 1000d334 +1000d322: 7b08 ldrb r0, [r1, #12] +1000d324: 2801 cmp r0, #1 +1000d326: bf1c itt ne +1000d328: 280a cmpne r0, #10 +1000d32a: 2805 cmpne r0, #5 +1000d32c: d102 bne.n 1000d334 +1000d32e: 4620 mov r0, r4 +1000d330: f000 f99b bl 1000d66a + +1000d334 : +1000d334: 6824 ldr r4, [r4, #0] + +1000d336 : +1000d336: b184 cbz r4, 1000d35a +1000d338: 6a21 ldr r1, [r4, #32] +1000d33a: 2900 cmp r1, #0 +1000d33c: d0fa beq.n 1000d334 +1000d33e: 8bc8 ldrh r0, [r1, #30] +1000d340: 1e42 subs r2, r0, #1 +1000d342: 83ca strh r2, [r1, #30] +1000d344: d1e9 bne.n 1000d31a +1000d346: 7b08 ldrb r0, [r1, #12] +1000d348: 2801 cmp r0, #1 +1000d34a: bf1c itt ne +1000d34c: 280a cmpne r0, #10 +1000d34e: 2805 cmpne r0, #5 +1000d350: d1f0 bne.n 1000d334 +1000d352: 4620 mov r0, r4 +1000d354: f000 f9c6 bl 1000d6e4 +1000d358: e7ec b.n 1000d334 + +1000d35a : +1000d35a: bd10 pop {r4, pc} + +1000d35c : +1000d35c: b510 push {r4, lr} +1000d35e: f8df 0aa0 ldr.w r0, [pc, #2720] ; 1000de00 +1000d362: 6804 ldr r4, [r0, #0] +1000d364: e007 b.n 1000d376 + +1000d366 : +1000d366: 2901 cmp r1, #1 +1000d368: d104 bne.n 1000d374 +1000d36a: 2000 movs r0, #0 +1000d36c: 8350 strh r0, [r2, #26] +1000d36e: 4620 mov r0, r4 +1000d370: f000 f80c bl 1000d38c + +1000d374 : +1000d374: 6824 ldr r4, [r4, #0] + +1000d376 : +1000d376: b144 cbz r4, 1000d38a +1000d378: 6a22 ldr r2, [r4, #32] +1000d37a: 2a00 cmp r2, #0 +1000d37c: d0fa beq.n 1000d374 +1000d37e: 8b51 ldrh r1, [r2, #26] +1000d380: 2902 cmp r1, #2 +1000d382: dbf0 blt.n 1000d366 +1000d384: 1e48 subs r0, r1, #1 +1000d386: 8350 strh r0, [r2, #26] +1000d388: e7f4 b.n 1000d374 + +1000d38a : +1000d38a: bd10 pop {r4, pc} + +1000d38c : +1000d38c: b510 push {r4, lr} +1000d38e: 4604 mov r4, r0 +1000d390: 6a20 ldr r0, [r4, #32] +1000d392: 7b01 ldrb r1, [r0, #12] +1000d394: 290c cmp r1, #12 +1000d396: bf14 ite ne +1000d398: 2906 cmpne r1, #6 +1000d39a: 4620 moveq r0, r4 +1000d39c: d033 beq.n 1000d406 +1000d39e: 2901 cmp r1, #1 +1000d3a0: d106 bne.n 1000d3b0 +1000d3a2: 7b40 ldrb r0, [r0, #13] +1000d3a4: 2806 cmp r0, #6 +1000d3a6: da1f bge.n 1000d3e8 +1000d3a8: 4620 mov r0, r4 +1000d3aa: e8bd 4010 ldmia.w sp!, {r4, lr} +1000d3ae: e776 b.n 1000d29e + +1000d3b0 : +1000d3b0: 2908 cmp r1, #8 +1000d3b2: d10a bne.n 1000d3ca +1000d3b4: 7b40 ldrb r0, [r0, #13] +1000d3b6: 2802 cmp r0, #2 +1000d3b8: 4620 mov r0, r4 +1000d3ba: bfbc itt lt +1000d3bc: e8bd 4010 ldmialt.w sp!, {r4, lr} +1000d3c0: f7ff bf5a blt.w 1000d278 +1000d3c4: e8bd 4010 ldmia.w sp!, {r4, lr} +1000d3c8: e0f2 b.n 1000d5b0 + +1000d3ca : +1000d3ca: 2905 cmp r1, #5 +1000d3cc: d103 bne.n 1000d3d6 +1000d3ce: 4620 mov r0, r4 +1000d3d0: e8bd 4010 ldmia.w sp!, {r4, lr} +1000d3d4: e149 b.n 1000d66a + +1000d3d6 : +1000d3d6: 2904 cmp r1, #4 +1000d3d8: d10b bne.n 1000d3f2 +1000d3da: 7b40 ldrb r0, [r0, #13] +1000d3dc: 2809 cmp r0, #9 +1000d3de: da03 bge.n 1000d3e8 +1000d3e0: 4620 mov r0, r4 +1000d3e2: e8bd 4010 ldmia.w sp!, {r4, lr} +1000d3e6: e17d b.n 1000d6e4 + +1000d3e8 : +1000d3e8: 4620 mov r0, r4 +1000d3ea: f000 f9e2 bl 1000d7b2 +1000d3ee: 4620 mov r0, r4 +1000d3f0: e009 b.n 1000d406 + +1000d3f2 : +1000d3f2: 2903 cmp r1, #3 +1000d3f4: d10a bne.n 1000d40c +1000d3f6: 7b40 ldrb r0, [r0, #13] +1000d3f8: 2802 cmp r0, #2 +1000d3fa: 4620 mov r0, r4 +1000d3fc: bfbc itt lt +1000d3fe: e8bd 4010 ldmialt.w sp!, {r4, lr} +1000d402: f000 b99d blt.w 1000d740 + +1000d406 : +1000d406: e8bd 4010 ldmia.w sp!, {r4, lr} +1000d40a: e07f b.n 1000d50c + +1000d40c : +1000d40c: bd10 pop {r4, pc} + +1000d40e : +1000d40e: b5f8 push {r3, r4, r5, r6, r7, lr} +1000d410: 0004 movs r4, r0 +1000d412: d008 beq.n 1000d426 +1000d414: f104 0620 add.w r6, r4, #32 +1000d418: 7c70 ldrb r0, [r6, #17] +1000d41a: 6a25 ldr r5, [r4, #32] +1000d41c: f000 00f7 and.w r0, r0, #247 ; 0xf7 +1000d420: 7470 strb r0, [r6, #17] +1000d422: 0680 lsls r0, r0, #26 +1000d424: d401 bmi.n 1000d42a + +1000d426 : +1000d426: f000 bcf7 b.w 1000de18 + +1000d42a : +1000d42a: 8930 ldrh r0, [r6, #8] +1000d42c: f5b0 7f10 cmp.w r0, #576 ; 0x240 +1000d430: db2e blt.n 1000d490 +1000d432: b935 cbnz r5, 1000d442 +1000d434: 2040 movs r0, #64 ; 0x40 +1000d436: f7fe fe62 bl 1000c0fe +1000d43a: 0005 movs r5, r0 +1000d43c: d028 beq.n 1000d490 +1000d43e: 6225 str r5, [r4, #32] +1000d440: e003 b.n 1000d44a + +1000d442 : +1000d442: 6868 ldr r0, [r5, #4] +1000d444: b108 cbz r0, 1000d44a +1000d446: f7fc fa1b bl 10009880 + +1000d44a : +1000d44a: f000 f829 bl 1000d4a0 + +1000d44e : +1000d44e: f7fc fa31 bl 100098b4 +1000d452: 6068 str r0, [r5, #4] +1000d454: b1e0 cbz r0, 1000d490 +1000d456: 7a01 ldrb r1, [r0, #8] +1000d458: f8df 79a8 ldr.w r7, [pc, #2472] ; 1000de04 +1000d45c: f041 0120 orr.w r1, r1, #32 +1000d460: 7201 strb r1, [r0, #8] +1000d462: 2244 movs r2, #68 ; 0x44 +1000d464: 6868 ldr r0, [r5, #4] +1000d466: 4639 mov r1, r7 +1000d468: f7fc f99c bl 100097a4 +1000d46c: 6868 ldr r0, [r5, #4] +1000d46e: 2243 movs r2, #67 ; 0x43 +1000d470: 4639 mov r1, r7 +1000d472: f7fc f9d7 bl 10009824 +1000d476: 6868 ldr r0, [r5, #4] +1000d478: f20f 7151 addw r1, pc, #1873 ; 0x751 +1000d47c: 4622 mov r2, r4 +1000d47e: f7fc f9fc bl 1000987a +1000d482: 4620 mov r0, r4 +1000d484: f000 f842 bl 1000d50c +1000d488: b120 cbz r0, 1000d494 +1000d48a: 4620 mov r0, r4 +1000d48c: f000 fa3c bl 1000d908 + +1000d490 : +1000d490: f000 bcc5 b.w 1000de1e + +1000d494 : +1000d494: 7c70 ldrb r0, [r6, #17] +1000d496: f040 0008 orr.w r0, r0, #8 +1000d49a: 7470 strb r0, [r6, #17] +1000d49c: 2000 movs r0, #0 +1000d49e: bdf2 pop {r1, r4, r5, r6, r7, pc} + +1000d4a0 : +1000d4a0: 2240 movs r2, #64 ; 0x40 +1000d4a2: 2100 movs r1, #0 +1000d4a4: 4628 mov r0, r5 +1000d4a6: f7fe bf51 b.w 1000c34c + +1000d4aa : +1000d4aa: b538 push {r3, r4, r5, lr} +1000d4ac: 0005 movs r5, r0 +1000d4ae: bf1c itt ne +1000d4b0: 6a2c ldrne r4, [r5, #32] +1000d4b2: 2c00 cmpne r4, #0 +1000d4b4: d026 beq.n 1000d504 +1000d4b6: 7b20 ldrb r0, [r4, #12] +1000d4b8: 2808 cmp r0, #8 +1000d4ba: bf02 ittt eq +1000d4bc: 6808 ldreq r0, [r1, #0] +1000d4be: 6a61 ldreq r1, [r4, #36] ; 0x24 +1000d4c0: 4288 cmpeq r0, r1 +1000d4c2: d11f bne.n 1000d504 +1000d4c4: 210c movs r1, #12 +1000d4c6: f000 f90b bl 1000d6e0 + +1000d4ca : +1000d4ca: 2204 movs r2, #4 +1000d4cc: 4621 mov r1, r4 +1000d4ce: 4628 mov r0, r5 +1000d4d0: f000 fc19 bl 1000dd06 +1000d4d4: b988 cbnz r0, 1000d4fa +1000d4d6: 2204 movs r2, #4 +1000d4d8: 2132 movs r1, #50 ; 0x32 +1000d4da: f000 f968 bl 1000d7ae + +1000d4de : +1000d4de: 6a60 ldr r0, [r4, #36] ; 0x24 +1000d4e0: f7ff f843 bl 1000c56a +1000d4e4: f000 f80f bl 1000d506 + +1000d4e8 : +1000d4e8: f000 f8f8 bl 1000d6dc + +1000d4ec : +1000d4ec: f000 f8ed bl 1000d6ca + +1000d4f0 : +1000d4f0: 9500 str r5, [sp, #0] +1000d4f2: f000 f850 bl 1000d596 + +1000d4f6 : +1000d4f6: f000 f8ef bl 1000d6d8 + +1000d4fa : +1000d4fa: 7b60 ldrb r0, [r4, #13] +1000d4fc: 1c40 adds r0, r0, #1 +1000d4fe: 7360 strb r0, [r4, #13] +1000d500: 2014 movs r0, #20 +1000d502: 8360 strh r0, [r4, #26] + +1000d504 : +1000d504: bd31 pop {r0, r4, r5, pc} + +1000d506 : +1000d506: 4601 mov r1, r0 +1000d508: 4620 mov r0, r4 +1000d50a: e23a b.n 1000d982 + +1000d50c : +1000d50c: b570 push {r4, r5, r6, lr} +1000d50e: 4606 mov r6, r0 +1000d510: b082 sub sp, #8 +1000d512: 6a34 ldr r4, [r6, #32] +1000d514: 2000 movs r0, #0 +1000d516: 6260 str r0, [r4, #36] ; 0x24 +1000d518: 2106 movs r1, #6 +1000d51a: f000 f8e1 bl 1000d6e0 + +1000d51e : +1000d51e: 2201 movs r2, #1 +1000d520: 4621 mov r1, r4 +1000d522: 4630 mov r0, r6 +1000d524: f000 fbef bl 1000dd06 +1000d528: 0005 movs r5, r0 +1000d52a: d11a bne.n 1000d562 +1000d52c: f000 f93d bl 1000d7aa + +1000d530 : +1000d530: f000 f838 bl 1000d5a4 + +1000d534 : +1000d534: 2204 movs r2, #4 +1000d536: 2137 movs r1, #55 ; 0x37 +1000d538: f000 f939 bl 1000d7ae + +1000d53c : +1000d53c: f000 f835 bl 1000d5aa + +1000d540 : +1000d540: 2103 movs r1, #3 +1000d542: f000 f833 bl 1000d5ac + +1000d546 : +1000d546: 211c movs r1, #28 +1000d548: f000 f830 bl 1000d5ac + +1000d54c : +1000d54c: 2106 movs r1, #6 +1000d54e: f000 f82d bl 1000d5ac + +1000d552 : +1000d552: f000 f8c3 bl 1000d6dc + +1000d556 : +1000d556: f000 f8b8 bl 1000d6ca + +1000d55a : +1000d55a: f000 f81b bl 1000d594 + +1000d55e : +1000d55e: f000 f8bb bl 1000d6d8 + +1000d562 : +1000d562: 7b60 ldrb r0, [r4, #13] +1000d564: 1c40 adds r0, r0, #1 +1000d566: 7360 strb r0, [r4, #13] +1000d568: b2c0 uxtb r0, r0 +1000d56a: 2806 cmp r0, #6 +1000d56c: da09 bge.n 1000d582 +1000d56e: 2101 movs r1, #1 +1000d570: fa01 f000 lsl.w r0, r1, r0 +1000d574: f44f 717a mov.w r1, #1000 ; 0x3e8 +1000d578: 4348 muls r0, r1 +1000d57a: b280 uxth r0, r0 +1000d57c: f200 10f3 addw r0, r0, #499 ; 0x1f3 +1000d580: e001 b.n 1000d586 + +1000d582 : +1000d582: f64e 4053 movw r0, #60499 ; 0xec53 + +1000d586 : +1000d586: f44f 71fa mov.w r1, #500 ; 0x1f4 +1000d58a: fb90 f0f1 sdiv r0, r0, r1 + +1000d58e : +1000d58e: 8360 strh r0, [r4, #26] +1000d590: 4628 mov r0, r5 +1000d592: bd76 pop {r1, r2, r4, r5, r6, pc} + +1000d594 : +1000d594: 9600 str r6, [sp, #0] + +1000d596 : +1000d596: 6921 ldr r1, [r4, #16] +1000d598: 6860 ldr r0, [r4, #4] +1000d59a: f8df 286c ldr.w r2, [pc, #2156] ; 1000de08 +1000d59e: 2343 movs r3, #67 ; 0x43 +1000d5a0: f7fc b891 b.w 100096c6 + +1000d5a4 : +1000d5a4: 8d31 ldrh r1, [r6, #40] ; 0x28 + +1000d5a6 : +1000d5a6: 4620 mov r0, r4 +1000d5a8: e1e3 b.n 1000d972 + +1000d5aa : +1000d5aa: 2101 movs r1, #1 + +1000d5ac : +1000d5ac: 4620 mov r0, r4 +1000d5ae: e1d8 b.n 1000d962 + +1000d5b0 : +1000d5b0: b57c push {r2, r3, r4, r5, r6, lr} +1000d5b2: 0004 movs r4, r0 +1000d5b4: bf1c itt ne +1000d5b6: 6a25 ldrne r5, [r4, #32] +1000d5b8: 2d00 cmpne r5, #0 +1000d5ba: d04e beq.n 1000d65a +1000d5bc: f105 0124 add.w r1, r5, #36 ; 0x24 +1000d5c0: f105 020e add.w r2, r5, #14 +1000d5c4: 694b ldr r3, [r1, #20] +1000d5c6: f64f 70ff movw r0, #65535 ; 0xffff +1000d5ca: f113 0f01 cmn.w r3, #1 +1000d5ce: d008 beq.n 1000d5e2 +1000d5d0: f000 f844 bl 1000d65c + +1000d5d4 : +1000d5d4: bf28 it cs +1000d5d6: 4603 movcs r3, r0 +1000d5d8: 81d3 strh r3, [r2, #14] +1000d5da: 89d3 ldrh r3, [r2, #14] +1000d5dc: b90b cbnz r3, 1000d5e2 +1000d5de: 2301 movs r3, #1 +1000d5e0: 81d3 strh r3, [r2, #14] + +1000d5e2 : +1000d5e2: 698b ldr r3, [r1, #24] +1000d5e4: f113 0f01 cmn.w r3, #1 +1000d5e8: d008 beq.n 1000d5fc +1000d5ea: f000 f837 bl 1000d65c + +1000d5ee : +1000d5ee: bf28 it cs +1000d5f0: 4603 movcs r3, r0 +1000d5f2: 8213 strh r3, [r2, #16] +1000d5f4: 8a13 ldrh r3, [r2, #16] +1000d5f6: b90b cbnz r3, 1000d5fc +1000d5f8: 2301 movs r3, #1 +1000d5fa: 8213 strh r3, [r2, #16] + +1000d5fc : +1000d5fc: 8a13 ldrh r3, [r2, #16] +1000d5fe: 89d6 ldrh r6, [r2, #14] +1000d600: 429e cmp r6, r3 +1000d602: d302 bcc.n 1000d60a +1000d604: b10b cbz r3, 1000d60a +1000d606: 2300 movs r3, #0 +1000d608: 81d3 strh r3, [r2, #14] + +1000d60a : +1000d60a: 7bab ldrb r3, [r5, #14] +1000d60c: b10b cbz r3, 1000d612 +1000d60e: 6848 ldr r0, [r1, #4] +1000d610: e008 b.n 1000d624 + +1000d612 : +1000d612: 7d92 ldrb r2, [r2, #22] +1000d614: 2a80 cmp r2, #128 ; 0x80 +1000d616: bfb8 it lt +1000d618: 20ff movlt r0, #255 ; 0xff +1000d61a: db03 blt.n 1000d624 +1000d61c: 2ac0 cmp r2, #192 ; 0xc0 +1000d61e: bfa8 it ge +1000d620: f06f 407f mvnge.w r0, #4278190080 ; 0xff000000 + +1000d624 : +1000d624: 9000 str r0, [sp, #0] +1000d626: 6ae8 ldr r0, [r5, #44] ; 0x2c +1000d628: 9001 str r0, [sp, #4] +1000d62a: b928 cbnz r0, 1000d638 +1000d62c: 6a68 ldr r0, [r5, #36] ; 0x24 +1000d62e: 9a00 ldr r2, [sp, #0] +1000d630: 4010 ands r0, r2 +1000d632: f040 7080 orr.w r0, r0, #16777216 ; 0x1000000 +1000d636: 9001 str r0, [sp, #4] + +1000d638 : +1000d638: f000 f902 bl 1000d840 + +1000d63c : +1000d63c: a900 add r1, sp, #0 +1000d63e: 4620 mov r0, r4 +1000d640: f001 fd30 bl 1000f0a4 +1000d644: a901 add r1, sp, #4 +1000d646: 4620 mov r0, r4 +1000d648: f001 fd28 bl 1000f09c +1000d64c: 4620 mov r0, r4 +1000d64e: f001 fd37 bl 1000f0c0 +1000d652: 210a movs r1, #10 +1000d654: 4628 mov r0, r5 +1000d656: f000 f96d bl 1000d934 + +1000d65a : +1000d65a: bd73 pop {r0, r1, r4, r5, r6, pc} + +1000d65c : +1000d65c: 331e adds r3, #30 +1000d65e: 263c movs r6, #60 ; 0x3c +1000d660: fbb3 f3f6 udiv r3, r3, r6 +1000d664: f5b3 3f80 cmp.w r3, #65536 ; 0x10000 +1000d668: 4770 bx lr + +1000d66a : +1000d66a: b570 push {r4, r5, r6, lr} +1000d66c: 4606 mov r6, r0 +1000d66e: b082 sub sp, #8 +1000d670: 6a34 ldr r4, [r6, #32] +1000d672: 2105 movs r1, #5 +1000d674: f000 f834 bl 1000d6e0 + +1000d678 : +1000d678: f000 f85e bl 1000d738 + +1000d67c : +1000d67c: 0005 movs r5, r0 +1000d67e: d111 bne.n 1000d6a4 +1000d680: f000 f893 bl 1000d7aa + +1000d684 : +1000d684: f7ff ff8e bl 1000d5a4 + +1000d688 : +1000d688: f000 f828 bl 1000d6dc + +1000d68c : +1000d68c: f000 f81d bl 1000d6ca + +1000d690 : +1000d690: 9600 str r6, [sp, #0] +1000d692: 6921 ldr r1, [r4, #16] +1000d694: 6860 ldr r0, [r4, #4] +1000d696: 2343 movs r3, #67 ; 0x43 +1000d698: f104 0220 add.w r2, r4, #32 +1000d69c: f7fc f813 bl 100096c6 +1000d6a0: f000 f81a bl 1000d6d8 + +1000d6a4 : +1000d6a4: 7b60 ldrb r0, [r4, #13] +1000d6a6: 1c40 adds r0, r0, #1 +1000d6a8: 7360 strb r0, [r4, #13] +1000d6aa: b2c0 uxtb r0, r0 +1000d6ac: 280a cmp r0, #10 +1000d6ae: da0a bge.n 1000d6c6 +1000d6b0: f44f 61fa mov.w r1, #2000 ; 0x7d0 +1000d6b4: 4348 muls r0, r1 +1000d6b6: b280 uxth r0, r0 +1000d6b8: f200 10f3 addw r0, r0, #499 ; 0x1f3 +1000d6bc: f44f 71fa mov.w r1, #500 ; 0x1f4 +1000d6c0: fb90 f0f1 sdiv r0, r0, r1 +1000d6c4: e000 b.n 1000d6c8 + +1000d6c6 : +1000d6c6: 2028 movs r0, #40 ; 0x28 + +1000d6c8 : +1000d6c8: e761 b.n 1000d58e + +1000d6ca : +1000d6ca: 8b20 ldrh r0, [r4, #24] +1000d6cc: f100 01f0 add.w r1, r0, #240 ; 0xf0 +1000d6d0: 6920 ldr r0, [r4, #16] +1000d6d2: b289 uxth r1, r1 +1000d6d4: f7fb b830 b.w 10008738 + +1000d6d8 : +1000d6d8: 4620 mov r0, r4 +1000d6da: e3a3 b.n 1000de24 + +1000d6dc : +1000d6dc: 4620 mov r0, r4 +1000d6de: e3ac b.n 1000de3a + +1000d6e0 : +1000d6e0: 4620 mov r0, r4 +1000d6e2: e127 b.n 1000d934 + +1000d6e4 : +1000d6e4: b570 push {r4, r5, r6, lr} +1000d6e6: 4606 mov r6, r0 +1000d6e8: b082 sub sp, #8 +1000d6ea: 6a34 ldr r4, [r6, #32] +1000d6ec: 2104 movs r1, #4 +1000d6ee: f7ff fff7 bl 1000d6e0 + +1000d6f2 : +1000d6f2: f000 f821 bl 1000d738 + +1000d6f6 : +1000d6f6: 0005 movs r5, r0 +1000d6f8: d10b bne.n 1000d712 +1000d6fa: f000 f856 bl 1000d7aa + +1000d6fe : +1000d6fe: f7ff ff51 bl 1000d5a4 + +1000d702 : +1000d702: f7ff ffeb bl 1000d6dc + +1000d706 : +1000d706: f7ff ffe0 bl 1000d6ca + +1000d70a : +1000d70a: f7ff ff43 bl 1000d594 + +1000d70e : +1000d70e: f7ff ffe3 bl 1000d6d8 + +1000d712 : +1000d712: 7b60 ldrb r0, [r4, #13] +1000d714: 1c40 adds r0, r0, #1 +1000d716: 7360 strb r0, [r4, #13] +1000d718: b2c0 uxtb r0, r0 +1000d71a: 280a cmp r0, #10 +1000d71c: da0a bge.n 1000d734 +1000d71e: f44f 717a mov.w r1, #1000 ; 0x3e8 +1000d722: 4348 muls r0, r1 +1000d724: b280 uxth r0, r0 +1000d726: f200 10f3 addw r0, r0, #499 ; 0x1f3 +1000d72a: f44f 71fa mov.w r1, #500 ; 0x1f4 +1000d72e: fb90 f0f1 sdiv r0, r0, r1 +1000d732: e000 b.n 1000d736 + +1000d734 : +1000d734: 2014 movs r0, #20 + +1000d736 : +1000d736: e72a b.n 1000d58e + +1000d738 : +1000d738: 2203 movs r2, #3 +1000d73a: 4621 mov r1, r4 +1000d73c: 4630 mov r0, r6 +1000d73e: e2e2 b.n 1000dd06 + +1000d740 : +1000d740: b570 push {r4, r5, r6, lr} +1000d742: 4606 mov r6, r0 +1000d744: b082 sub sp, #8 +1000d746: 6a34 ldr r4, [r6, #32] +1000d748: 2103 movs r1, #3 +1000d74a: f7ff ffc9 bl 1000d6e0 + +1000d74e : +1000d74e: f7ff fff3 bl 1000d738 + +1000d752 : +1000d752: 0005 movs r5, r0 +1000d754: d116 bne.n 1000d784 +1000d756: f000 f828 bl 1000d7aa + +1000d75a : +1000d75a: f44f 7110 mov.w r1, #576 ; 0x240 +1000d75e: f7ff ff22 bl 1000d5a6 + +1000d762 : +1000d762: 2204 movs r2, #4 +1000d764: 2132 movs r1, #50 ; 0x32 +1000d766: f000 f822 bl 1000d7ae + +1000d76a : +1000d76a: 6a60 ldr r0, [r4, #36] ; 0x24 +1000d76c: f7fe fefd bl 1000c56a +1000d770: f7ff fec9 bl 1000d506 + +1000d774 : +1000d774: f7ff ffb2 bl 1000d6dc + +1000d778 : +1000d778: f7ff ffa7 bl 1000d6ca + +1000d77c : +1000d77c: f7ff ff0a bl 1000d594 + +1000d780 : +1000d780: f7ff ffaa bl 1000d6d8 + +1000d784 : +1000d784: 7b60 ldrb r0, [r4, #13] +1000d786: 1c40 adds r0, r0, #1 +1000d788: 7360 strb r0, [r4, #13] +1000d78a: b2c0 uxtb r0, r0 +1000d78c: 280a cmp r0, #10 +1000d78e: da0a bge.n 1000d7a6 +1000d790: f44f 717a mov.w r1, #1000 ; 0x3e8 +1000d794: 4348 muls r0, r1 +1000d796: b280 uxth r0, r0 +1000d798: f200 10f3 addw r0, r0, #499 ; 0x1f3 +1000d79c: f44f 71fa mov.w r1, #500 ; 0x1f4 +1000d7a0: fb90 f0f1 sdiv r0, r0, r1 +1000d7a4: e000 b.n 1000d7a8 + +1000d7a6 : +1000d7a6: 2014 movs r0, #20 + +1000d7a8 : +1000d7a8: e6f1 b.n 1000d58e + +1000d7aa : +1000d7aa: 2202 movs r2, #2 +1000d7ac: 2139 movs r1, #57 ; 0x39 + +1000d7ae : +1000d7ae: 4620 mov r0, r4 +1000d7b0: e0c8 b.n 1000d944 + +1000d7b2 : +1000d7b2: b570 push {r4, r5, r6, lr} +1000d7b4: 4604 mov r4, r0 +1000d7b6: b082 sub sp, #8 +1000d7b8: 6a25 ldr r5, [r4, #32] +1000d7ba: 2100 movs r1, #0 +1000d7bc: 4628 mov r0, r5 +1000d7be: f000 f8b9 bl 1000d934 +1000d7c2: 2000 movs r0, #0 +1000d7c4: 6228 str r0, [r5, #32] +1000d7c6: 6268 str r0, [r5, #36] ; 0x24 +1000d7c8: 62a8 str r0, [r5, #40] ; 0x28 +1000d7ca: 62e8 str r0, [r5, #44] ; 0x2c +1000d7cc: 63e8 str r0, [r5, #60] ; 0x3c +1000d7ce: 63a8 str r0, [r5, #56] ; 0x38 +1000d7d0: 6368 str r0, [r5, #52] ; 0x34 +1000d7d2: 2207 movs r2, #7 +1000d7d4: 4629 mov r1, r5 +1000d7d6: 4620 mov r0, r4 +1000d7d8: f000 fa95 bl 1000dd06 +1000d7dc: 0006 movs r6, r0 +1000d7de: d114 bne.n 1000d80a +1000d7e0: 4628 mov r0, r5 +1000d7e2: f000 fb2a bl 1000de3a +1000d7e6: 8b28 ldrh r0, [r5, #24] +1000d7e8: f100 01f0 add.w r1, r0, #240 ; 0xf0 +1000d7ec: 6928 ldr r0, [r5, #16] +1000d7ee: b289 uxth r1, r1 +1000d7f0: f7fa ffa2 bl 10008738 +1000d7f4: 9400 str r4, [sp, #0] +1000d7f6: 6929 ldr r1, [r5, #16] +1000d7f8: 6868 ldr r0, [r5, #4] +1000d7fa: 2343 movs r3, #67 ; 0x43 +1000d7fc: f105 0220 add.w r2, r5, #32 +1000d800: f7fb ff61 bl 100096c6 +1000d804: 4628 mov r0, r5 +1000d806: f000 fb0d bl 1000de24 + +1000d80a : +1000d80a: 7b68 ldrb r0, [r5, #13] +1000d80c: 1c40 adds r0, r0, #1 +1000d80e: 7368 strb r0, [r5, #13] +1000d810: f000 f867 bl 1000d8e2 + +1000d814 : +1000d814: 8368 strh r0, [r5, #26] +1000d816: f000 f874 bl 1000d902 + +1000d81a : +1000d81a: f000 f80e bl 1000d83a + +1000d81e : +1000d81e: f000 f808 bl 1000d832 + +1000d822 : +1000d822: f000 f802 bl 1000d82a + +1000d826 : +1000d826: 4630 mov r0, r6 +1000d828: bd76 pop {r1, r2, r4, r5, r6, pc} + +1000d82a : +1000d82a: 4629 mov r1, r5 + +1000d82c : +1000d82c: 4620 mov r0, r4 +1000d82e: f001 bc39 b.w 1000f0a4 + +1000d832 : +1000d832: 4629 mov r1, r5 + +1000d834 : +1000d834: 4620 mov r0, r4 +1000d836: f001 bc31 b.w 1000f09c + +1000d83a : +1000d83a: f8df 55c8 ldr.w r5, [pc, #1480] ; 1000de04 +1000d83e: 4629 mov r1, r5 + +1000d840 : +1000d840: 4620 mov r0, r4 +1000d842: f001 bbff b.w 1000f044 + +1000d846 : +1000d846: b570 push {r4, r5, r6, lr} +1000d848: 4604 mov r4, r0 +1000d84a: b082 sub sp, #8 +1000d84c: 6a26 ldr r6, [r4, #32] +1000d84e: 210b movs r1, #11 +1000d850: 4630 mov r0, r6 +1000d852: f000 f86f bl 1000d934 +1000d856: 6a21 ldr r1, [r4, #32] +1000d858: 2203 movs r2, #3 +1000d85a: 4620 mov r0, r4 +1000d85c: f000 fa53 bl 1000dd06 +1000d860: 0005 movs r5, r0 +1000d862: d129 bne.n 1000d8b8 +1000d864: 2201 movs r2, #1 +1000d866: 2135 movs r1, #53 ; 0x35 +1000d868: 4630 mov r0, r6 +1000d86a: f000 f86b bl 1000d944 +1000d86e: 2107 movs r1, #7 +1000d870: 4630 mov r0, r6 +1000d872: f000 f876 bl 1000d962 +1000d876: 2204 movs r2, #4 +1000d878: 2136 movs r1, #54 ; 0x36 +1000d87a: 4630 mov r0, r6 +1000d87c: f000 f862 bl 1000d944 +1000d880: 6a30 ldr r0, [r6, #32] +1000d882: f7fe fe72 bl 1000c56a +1000d886: 4601 mov r1, r0 +1000d888: 4630 mov r0, r6 +1000d88a: f000 f87a bl 1000d982 +1000d88e: 4630 mov r0, r6 +1000d890: f000 fad3 bl 1000de3a +1000d894: 8b30 ldrh r0, [r6, #24] +1000d896: f100 01f0 add.w r1, r0, #240 ; 0xf0 +1000d89a: 6930 ldr r0, [r6, #16] +1000d89c: b289 uxth r1, r1 +1000d89e: f7fa ff4b bl 10008738 +1000d8a2: 9400 str r4, [sp, #0] +1000d8a4: 6931 ldr r1, [r6, #16] +1000d8a6: 6870 ldr r0, [r6, #4] +1000d8a8: 2343 movs r3, #67 ; 0x43 +1000d8aa: f106 0220 add.w r2, r6, #32 +1000d8ae: f7fb ff0a bl 100096c6 +1000d8b2: 6a20 ldr r0, [r4, #32] +1000d8b4: f000 fab6 bl 1000de24 + +1000d8b8 : +1000d8b8: 7b70 ldrb r0, [r6, #13] +1000d8ba: 1c40 adds r0, r0, #1 +1000d8bc: 7370 strb r0, [r6, #13] +1000d8be: f000 f810 bl 1000d8e2 + +1000d8c2 : +1000d8c2: 8370 strh r0, [r6, #26] +1000d8c4: f000 f81d bl 1000d902 + +1000d8c8 : +1000d8c8: f8df 6538 ldr.w r6, [pc, #1336] ; 1000de04 +1000d8cc: 4631 mov r1, r6 +1000d8ce: f7ff ffb7 bl 1000d840 + +1000d8d2 : +1000d8d2: 4631 mov r1, r6 +1000d8d4: f7ff ffae bl 1000d834 + +1000d8d8 : +1000d8d8: 4631 mov r1, r6 +1000d8da: f7ff ffa7 bl 1000d82c + +1000d8de : +1000d8de: 4628 mov r0, r5 +1000d8e0: bd76 pop {r1, r2, r4, r5, r6, pc} + +1000d8e2 : +1000d8e2: b2c0 uxtb r0, r0 +1000d8e4: 280a cmp r0, #10 +1000d8e6: da0a bge.n 1000d8fe +1000d8e8: f44f 717a mov.w r1, #1000 ; 0x3e8 +1000d8ec: 4348 muls r0, r1 +1000d8ee: b280 uxth r0, r0 +1000d8f0: f200 10f3 addw r0, r0, #499 ; 0x1f3 +1000d8f4: f44f 71fa mov.w r1, #500 ; 0x1f4 +1000d8f8: fb90 f0f1 sdiv r0, r0, r1 +1000d8fc: 4770 bx lr + +1000d8fe : +1000d8fe: 2014 movs r0, #20 + +1000d900 : +1000d900: 4770 bx lr + +1000d902 : +1000d902: 4620 mov r0, r4 +1000d904: f001 bbec b.w 1000f0e0 + +1000d908 : +1000d908: b900 cbnz r0, 1000d90c +1000d90a: 4770 bx lr + +1000d90c : +1000d90c: b510 push {r4, lr} +1000d90e: 6a04 ldr r4, [r0, #32] +1000d910: 3020 adds r0, #32 +1000d912: 7c41 ldrb r1, [r0, #17] +1000d914: f001 01f7 and.w r1, r1, #247 ; 0xf7 +1000d918: 7441 strb r1, [r0, #17] +1000d91a: b154 cbz r4, 1000d932 +1000d91c: 6860 ldr r0, [r4, #4] +1000d91e: b118 cbz r0, 1000d928 +1000d920: f7fb ffae bl 10009880 +1000d924: 2000 movs r0, #0 +1000d926: 6060 str r0, [r4, #4] + +1000d928 : +1000d928: 4620 mov r0, r4 +1000d92a: e8bd 4010 ldmia.w sp!, {r4, lr} +1000d92e: 2100 movs r1, #0 +1000d930: e000 b.n 1000d934 + +1000d932 : +1000d932: bd10 pop {r4, pc} + +1000d934 : +1000d934: 7b02 ldrb r2, [r0, #12] +1000d936: 4291 cmp r1, r2 +1000d938: d003 beq.n 1000d942 +1000d93a: 7301 strb r1, [r0, #12] +1000d93c: 2100 movs r1, #0 +1000d93e: 7341 strb r1, [r0, #13] +1000d940: 8341 strh r1, [r0, #26] + +1000d942 : +1000d942: 4770 bx lr + +1000d944 : +1000d944: b530 push {r4, r5, lr} +1000d946: 8b03 ldrh r3, [r0, #24] +1000d948: 1c5c adds r4, r3, #1 +1000d94a: 8304 strh r4, [r0, #24] +1000d94c: 6945 ldr r5, [r0, #20] +1000d94e: 195b adds r3, r3, r5 +1000d950: f883 10f0 strb.w r1, [r3, #240] ; 0xf0 +1000d954: 1c61 adds r1, r4, #1 +1000d956: 8301 strh r1, [r0, #24] +1000d958: b2a4 uxth r4, r4 +1000d95a: 1960 adds r0, r4, r5 +1000d95c: f880 20f0 strb.w r2, [r0, #240] ; 0xf0 +1000d960: bd30 pop {r4, r5, pc} + +1000d962 : +1000d962: 8b02 ldrh r2, [r0, #24] +1000d964: 1c53 adds r3, r2, #1 +1000d966: 8303 strh r3, [r0, #24] +1000d968: 6940 ldr r0, [r0, #20] +1000d96a: 1810 adds r0, r2, r0 +1000d96c: f880 10f0 strb.w r1, [r0, #240] ; 0xf0 +1000d970: 4770 bx lr + +1000d972 : +1000d972: b530 push {r4, r5, lr} +1000d974: 8b02 ldrh r2, [r0, #24] +1000d976: 1c53 adds r3, r2, #1 +1000d978: 8303 strh r3, [r0, #24] +1000d97a: 0a0d lsrs r5, r1, #8 +1000d97c: 6944 ldr r4, [r0, #20] +1000d97e: 1912 adds r2, r2, r4 +1000d980: e014 b.n 1000d9ac + +1000d982 : +1000d982: b530 push {r4, r5, lr} +1000d984: 8b02 ldrh r2, [r0, #24] +1000d986: 1c53 adds r3, r2, #1 +1000d988: 8303 strh r3, [r0, #24] +1000d98a: 0e0d lsrs r5, r1, #24 +1000d98c: 6944 ldr r4, [r0, #20] +1000d98e: 1912 adds r2, r2, r4 +1000d990: f882 50f0 strb.w r5, [r2, #240] ; 0xf0 +1000d994: 1c5a adds r2, r3, #1 +1000d996: b29b uxth r3, r3 +1000d998: 191b adds r3, r3, r4 +1000d99a: 8302 strh r2, [r0, #24] +1000d99c: 0c0d lsrs r5, r1, #16 +1000d99e: f883 50f0 strb.w r5, [r3, #240] ; 0xf0 +1000d9a2: 1c53 adds r3, r2, #1 +1000d9a4: b292 uxth r2, r2 +1000d9a6: 1912 adds r2, r2, r4 +1000d9a8: 8303 strh r3, [r0, #24] +1000d9aa: 0a0d lsrs r5, r1, #8 + +1000d9ac : +1000d9ac: f882 50f0 strb.w r5, [r2, #240] ; 0xf0 +1000d9b0: 1c5a adds r2, r3, #1 +1000d9b2: 8302 strh r2, [r0, #24] +1000d9b4: b29b uxth r3, r3 +1000d9b6: 1918 adds r0, r3, r4 +1000d9b8: f880 10f0 strb.w r1, [r0, #240] ; 0xf0 +1000d9bc: bd30 pop {r4, r5, pc} + +1000d9be : +1000d9be: e92d 4ff2 stmdb sp!, {r1, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1000d9c2: 4605 mov r5, r0 +1000d9c4: b082 sub sp, #8 +1000d9c6: f04f 0800 mov.w r8, #0 +1000d9ca: 220a movs r2, #10 +1000d9cc: 2100 movs r1, #0 +1000d9ce: f8df 043c ldr.w r0, [pc, #1084] ; 1000de0c +1000d9d2: f7fe fcbb bl 1000c34c +1000d9d6: 9802 ldr r0, [sp, #8] +1000d9d8: 8940 ldrh r0, [r0, #10] +1000d9da: 282c cmp r0, #44 ; 0x2c +1000d9dc: db18 blt.n 1000da10 +1000d9de: 9802 ldr r0, [sp, #8] +1000d9e0: 6840 ldr r0, [r0, #4] +1000d9e2: 60a8 str r0, [r5, #8] +1000d9e4: 26f0 movs r6, #240 ; 0xf0 +1000d9e6: 9802 ldr r0, [sp, #8] +1000d9e8: f8b0 9008 ldrh.w r9, [r0, #8] +1000d9ec: e004 b.n 1000d9f8 + +1000d9ee : +1000d9ee: f04f 0801 mov.w r8, #1 + +1000d9f2 : +1000d9f2: 266c movs r6, #108 ; 0x6c +1000d9f4: f04f 09ec mov.w r9, #236 ; 0xec + +1000d9f8 : +1000d9f8: 9d02 ldr r5, [sp, #8] +1000d9fa: e007 b.n 1000da0c + +1000d9fc : +1000d9fc: 8968 ldrh r0, [r5, #10] +1000d9fe: 4286 cmp r6, r0 +1000da00: db09 blt.n 1000da16 +1000da02: 1a31 subs r1, r6, r0 +1000da04: 682d ldr r5, [r5, #0] +1000da06: b28e uxth r6, r1 +1000da08: eba9 0900 sub.w r9, r9, r0 + +1000da0c : +1000da0c: 2d00 cmp r5, #0 +1000da0e: d1f5 bne.n 1000d9fc + +1000da10 : +1000da10: f06f 0001 mvn.w r0, #1 +1000da14: e0d6 b.n 1000dbc4 + +1000da16 : +1000da16: 6868 ldr r0, [r5, #4] +1000da18: 9001 str r0, [sp, #4] +1000da1a: fa1f f989 uxth.w r9, r9 + +1000da1e : +1000da1e: 9801 ldr r0, [sp, #4] +1000da20: 5c30 ldrb r0, [r6, r0] +1000da22: 28ff cmp r0, #255 ; 0xff +1000da24: f000 80b4 beq.w 1000db90 +1000da28: 454e cmp r6, r9 +1000da2a: f280 80b1 bge.w 1000db90 +1000da2e: 896a ldrh r2, [r5, #10] +1000da30: 1c71 adds r1, r6, #1 +1000da32: f04f 34ff mov.w r4, #4294967295 +1000da36: f106 0b02 add.w fp, r6, #2 +1000da3a: 4291 cmp r1, r2 +1000da3c: da03 bge.n 1000da46 +1000da3e: 9901 ldr r1, [sp, #4] +1000da40: 1871 adds r1, r6, r1 +1000da42: 7849 ldrb r1, [r1, #1] +1000da44: e003 b.n 1000da4e + +1000da46 : +1000da46: 6829 ldr r1, [r5, #0] +1000da48: b109 cbz r1, 1000da4e +1000da4a: 6849 ldr r1, [r1, #4] +1000da4c: 7809 ldrb r1, [r1, #0] + +1000da4e : +1000da4e: 460f mov r7, r1 +1000da50: b190 cbz r0, 1000da78 +1000da52: 2801 cmp r0, #1 +1000da54: d015 beq.n 1000da82 +1000da56: 2803 cmp r0, #3 +1000da58: d017 beq.n 1000da8a +1000da5a: 2806 cmp r0, #6 +1000da5c: d01a beq.n 1000da94 +1000da5e: 2833 cmp r0, #51 ; 0x33 +1000da60: d026 beq.n 1000dab0 +1000da62: 2834 cmp r0, #52 ; 0x34 +1000da64: d028 beq.n 1000dab8 +1000da66: 2835 cmp r0, #53 ; 0x35 +1000da68: d02a beq.n 1000dac0 +1000da6a: 2836 cmp r0, #54 ; 0x36 +1000da6c: d02c beq.n 1000dac8 +1000da6e: 283a cmp r0, #58 ; 0x3a +1000da70: d02e beq.n 1000dad0 +1000da72: 283b cmp r0, #59 ; 0x3b +1000da74: d030 beq.n 1000dad8 +1000da76: e033 b.n 1000dae0 + +1000da78 : +1000da78: 1e70 subs r0, r6, #1 +1000da7a: 2100 movs r1, #0 +1000da7c: 2700 movs r7, #0 +1000da7e: b286 uxth r6, r0 +1000da80: e02f b.n 1000dae2 + +1000da82 : +1000da82: 2904 cmp r1, #4 +1000da84: d163 bne.n 1000db4e +1000da86: 2406 movs r4, #6 +1000da88: e02b b.n 1000dae2 + +1000da8a : +1000da8a: 2704 movs r7, #4 +1000da8c: 2904 cmp r1, #4 +1000da8e: db5e blt.n 1000db4e +1000da90: 2407 movs r4, #7 +1000da92: e026 b.n 1000dae2 + +1000da94 : +1000da94: 1048 asrs r0, r1, #1 +1000da96: eb01 7090 add.w r0, r1, r0, lsr #30 +1000da9a: 1080 asrs r0, r0, #2 +1000da9c: ebb1 0080 subs.w r0, r1, r0, lsl #2 +1000daa0: d155 bne.n 1000db4e +1000daa2: 2908 cmp r1, #8 +1000daa4: bfa8 it ge +1000daa6: 2708 movge r7, #8 +1000daa8: 42b9 cmp r1, r7 +1000daaa: db50 blt.n 1000db4e +1000daac: 2408 movs r4, #8 +1000daae: e018 b.n 1000dae2 + +1000dab0 : +1000dab0: 2904 cmp r1, #4 +1000dab2: d14c bne.n 1000db4e +1000dab4: 2403 movs r4, #3 +1000dab6: e014 b.n 1000dae2 + +1000dab8 : +1000dab8: 2901 cmp r1, #1 +1000daba: d148 bne.n 1000db4e +1000dabc: 2400 movs r4, #0 +1000dabe: e010 b.n 1000dae2 + +1000dac0 : +1000dac0: 2901 cmp r1, #1 +1000dac2: d144 bne.n 1000db4e +1000dac4: 2401 movs r4, #1 +1000dac6: e00c b.n 1000dae2 + +1000dac8 : +1000dac8: 2904 cmp r1, #4 +1000daca: d140 bne.n 1000db4e +1000dacc: 2402 movs r4, #2 +1000dace: e008 b.n 1000dae2 + +1000dad0 : +1000dad0: 2904 cmp r1, #4 +1000dad2: d13c bne.n 1000db4e +1000dad4: 2404 movs r4, #4 +1000dad6: e004 b.n 1000dae2 + +1000dad8 : +1000dad8: 2904 cmp r1, #4 +1000dada: d138 bne.n 1000db4e +1000dadc: 2405 movs r4, #5 +1000dade: e000 b.n 1000dae2 + +1000dae0 : +1000dae0: 2700 movs r7, #0 + +1000dae2 : +1000dae2: 1988 adds r0, r1, r6 +1000dae4: 1c80 adds r0, r0, #2 +1000dae6: b286 uxth r6, r0 +1000dae8: 2f00 cmp r7, #0 +1000daea: d03c beq.n 1000db66 +1000daec: 2000 movs r0, #0 +1000daee: 9000 str r0, [sp, #0] +1000daf0: e013 b.n 1000db1a + +1000daf2 : +1000daf2: 1078 asrs r0, r7, #1 +1000daf4: eb07 7090 add.w r0, r7, r0, lsr #30 +1000daf8: 1080 asrs r0, r0, #2 +1000dafa: ebb7 0080 subs.w r0, r7, r0, lsl #2 +1000dafe: d126 bne.n 1000db4e +1000db00: 49c2 ldr r1, [pc, #776] ; (1000de0c ) +1000db02: 2001 movs r0, #1 +1000db04: 5460 strb r0, [r4, r1] +1000db06: 9800 ldr r0, [sp, #0] +1000db08: f7fe fd23 bl 1000c552 +1000db0c: f8ca 000c str.w r0, [sl, #12] +1000db10: f10b 0b04 add.w fp, fp, #4 +1000db14: 1f38 subs r0, r7, #4 +1000db16: b2c7 uxtb r7, r0 +1000db18: 1c64 adds r4, r4, #1 + +1000db1a : +1000db1a: 48bc ldr r0, [pc, #752] ; (1000de0c ) +1000db1c: 5c20 ldrb r0, [r4, r0] +1000db1e: bb10 cbnz r0, 1000db66 +1000db20: 2f04 cmp r7, #4 +1000db22: bfb4 ite lt +1000db24: 463a movlt r2, r7 +1000db26: 2204 movge r2, #4 +1000db28: fa1f f38b uxth.w r3, fp +1000db2c: a900 add r1, sp, #0 +1000db2e: 4628 mov r0, r5 +1000db30: f7fa ff01 bl 10008936 +1000db34: 48b5 ldr r0, [pc, #724] ; (1000de0c ) +1000db36: eb00 0a84 add.w sl, r0, r4, lsl #2 +1000db3a: 2f05 cmp r7, #5 +1000db3c: dad9 bge.n 1000daf2 +1000db3e: 2f04 cmp r7, #4 +1000db40: d103 bne.n 1000db4a +1000db42: 9800 ldr r0, [sp, #0] +1000db44: f7fe fd11 bl 1000c56a +1000db48: e006 b.n 1000db58 + +1000db4a : +1000db4a: 2f01 cmp r7, #1 +1000db4c: d002 beq.n 1000db54 + +1000db4e : +1000db4e: f06f 0005 mvn.w r0, #5 +1000db52: e037 b.n 1000dbc4 + +1000db54 : +1000db54: f89d 0000 ldrb.w r0, [sp] + +1000db58 : +1000db58: 9000 str r0, [sp, #0] +1000db5a: 2001 movs r0, #1 +1000db5c: 49ab ldr r1, [pc, #684] ; (1000de0c ) +1000db5e: 5460 strb r0, [r4, r1] +1000db60: 9800 ldr r0, [sp, #0] +1000db62: f8ca 000c str.w r0, [sl, #12] + +1000db66 : +1000db66: 8968 ldrh r0, [r5, #10] +1000db68: 4286 cmp r6, r0 +1000db6a: f6ff af58 blt.w 1000da1e +1000db6e: 1a31 subs r1, r6, r0 +1000db70: eba9 0000 sub.w r0, r9, r0 +1000db74: b28e uxth r6, r1 +1000db76: fa1f f980 uxth.w r9, r0 +1000db7a: 454e cmp r6, r9 +1000db7c: da08 bge.n 1000db90 +1000db7e: f1b9 0f00 cmp.w r9, #0 +1000db82: bf1f itttt ne +1000db84: 682d ldrne r5, [r5, #0] +1000db86: 6868 ldrne r0, [r5, #4] +1000db88: 9001 strne r0, [sp, #4] +1000db8a: 2d00 cmpne r5, #0 +1000db8c: f47f af47 bne.w 1000da1e + +1000db90 : +1000db90: 489e ldr r0, [pc, #632] ; (1000de0c ) +1000db92: 7800 ldrb r0, [r0, #0] +1000db94: b160 cbz r0, 1000dbb0 +1000db96: 489d ldr r0, [pc, #628] ; (1000de0c ) +1000db98: 4a9c ldr r2, [pc, #624] ; (1000de0c ) +1000db9a: 68c0 ldr r0, [r0, #12] +1000db9c: 2100 movs r1, #0 +1000db9e: 7011 strb r1, [r2, #0] +1000dba0: 2801 cmp r0, #1 +1000dba2: f43f af26 beq.w 1000d9f2 +1000dba6: 2802 cmp r0, #2 +1000dba8: d005 beq.n 1000dbb6 +1000dbaa: 2803 cmp r0, #3 +1000dbac: f43f af1f beq.w 1000d9ee + +1000dbb0 : +1000dbb0: f1b8 0f00 cmp.w r8, #0 +1000dbb4: d005 beq.n 1000dbc2 + +1000dbb6 : +1000dbb6: f04f 0800 mov.w r8, #0 +1000dbba: 262c movs r6, #44 ; 0x2c +1000dbbc: f04f 096c mov.w r9, #108 ; 0x6c +1000dbc0: e71a b.n 1000d9f8 + +1000dbc2 : +1000dbc2: 2000 movs r0, #0 + +1000dbc4 : +1000dbc4: e8bd 8ffe ldmia.w sp!, {r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, pc} +1000dbc8: 0000 movs r0, r0 + ... + +1000dbcc : +1000dbcc: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1000dbd0: 4690 mov r8, r2 +1000dbd2: 4604 mov r4, r0 +1000dbd4: f8b8 100a ldrh.w r1, [r8, #10] +1000dbd8: 6a26 ldr r6, [r4, #32] +1000dbda: f8d8 0004 ldr.w r0, [r8, #4] +1000dbde: 292c cmp r1, #44 ; 0x2c +1000dbe0: db50 blt.n 1000dc84 +1000dbe2: 7801 ldrb r1, [r0, #0] +1000dbe4: 2902 cmp r1, #2 +1000dbe6: d113 bne.n 1000dc10 +1000dbe8: 2100 movs r1, #0 +1000dbea: e008 b.n 1000dbfe + +1000dbec : +1000dbec: 190a adds r2, r1, r4 +1000dbee: 180b adds r3, r1, r0 +1000dbf0: f892 202b ldrb.w r2, [r2, #43] ; 0x2b +1000dbf4: 7f1b ldrb r3, [r3, #28] +1000dbf6: 429a cmp r2, r3 +1000dbf8: d10a bne.n 1000dc10 +1000dbfa: 1c49 adds r1, r1, #1 +1000dbfc: b2c9 uxtb r1, r1 + +1000dbfe : +1000dbfe: f894 202a ldrb.w r2, [r4, #42] ; 0x2a +1000dc02: 4291 cmp r1, r2 +1000dc04: dbf2 blt.n 1000dbec +1000dc06: 6840 ldr r0, [r0, #4] +1000dc08: f7fe fcaf bl 1000c56a +1000dc0c: 6831 ldr r1, [r6, #0] +1000dc0e: 4288 cmp r0, r1 + +1000dc10 : +1000dc10: d172 bne.n 1000dcf8 +1000dc12: 4641 mov r1, r8 +1000dc14: 4630 mov r0, r6 +1000dc16: f7ff fed2 bl 1000d9be +1000dc1a: 2800 cmp r0, #0 +1000dc1c: d16c bne.n 1000dcf8 +1000dc1e: 4f7b ldr r7, [pc, #492] ; (1000de0c ) +1000dc20: 7878 ldrb r0, [r7, #1] +1000dc22: 2800 cmp r0, #0 +1000dc24: d068 beq.n 1000dcf8 +1000dc26: 7c38 ldrb r0, [r7, #16] +1000dc28: 2805 cmp r0, #5 +1000dc2a: d135 bne.n 1000dc98 +1000dc2c: 7b30 ldrb r0, [r6, #12] +1000dc2e: 2801 cmp r0, #1 +1000dc30: d129 bne.n 1000dc86 +1000dc32: 6a25 ldr r5, [r4, #32] +1000dc34: 2000 movs r0, #0 +1000dc36: 62a8 str r0, [r5, #40] ; 0x28 +1000dc38: 62e8 str r0, [r5, #44] ; 0x2c +1000dc3a: 78f8 ldrb r0, [r7, #3] +1000dc3c: b108 cbz r0, 1000dc42 +1000dc3e: 69b8 ldr r0, [r7, #24] +1000dc40: 6368 str r0, [r5, #52] ; 0x34 + +1000dc42 : +1000dc42: 7938 ldrb r0, [r7, #4] +1000dc44: 2800 cmp r0, #0 +1000dc46: bf12 itee ne +1000dc48: 69f8 ldrne r0, [r7, #28] +1000dc4a: 6b68 ldreq r0, [r5, #52] ; 0x34 +1000dc4c: 0840 lsreq r0, r0, #1 +1000dc4e: 63a8 str r0, [r5, #56] ; 0x38 +1000dc50: 7978 ldrb r0, [r7, #5] +1000dc52: 2800 cmp r0, #0 +1000dc54: bf14 ite ne +1000dc56: 6a38 ldrne r0, [r7, #32] +1000dc58: 6b68 ldreq r0, [r5, #52] ; 0x34 +1000dc5a: 63e8 str r0, [r5, #60] ; 0x3c +1000dc5c: 68a8 ldr r0, [r5, #8] +1000dc5e: 6900 ldr r0, [r0, #16] +1000dc60: 6268 str r0, [r5, #36] ; 0x24 +1000dc62: 79b8 ldrb r0, [r7, #6] +1000dc64: b120 cbz r0, 1000dc70 +1000dc66: 6a78 ldr r0, [r7, #36] ; 0x24 +1000dc68: f7fe fc73 bl 1000c552 +1000dc6c: 62a8 str r0, [r5, #40] ; 0x28 +1000dc6e: 2001 movs r0, #1 + +1000dc70 : +1000dc70: 73a8 strb r0, [r5, #14] +1000dc72: 79f8 ldrb r0, [r7, #7] +1000dc74: b118 cbz r0, 1000dc7e +1000dc76: 6ab8 ldr r0, [r7, #40] ; 0x28 +1000dc78: f7fe fc6b bl 1000c552 +1000dc7c: 62e8 str r0, [r5, #44] ; 0x2c + +1000dc7e : +1000dc7e: 4620 mov r0, r4 +1000dc80: f7ff fafa bl 1000d278 + +1000dc84 : +1000dc84: e038 b.n 1000dcf8 + +1000dc86 : +1000dc86: 2803 cmp r0, #3 +1000dc88: bf1c itt ne +1000dc8a: 2804 cmpne r0, #4 +1000dc8c: 2805 cmpne r0, #5 +1000dc8e: d133 bne.n 1000dcf8 +1000dc90: 4620 mov r0, r4 +1000dc92: f7ff fc8d bl 1000d5b0 +1000dc96: e02f b.n 1000dcf8 + +1000dc98 : +1000dc98: 2806 cmp r0, #6 +1000dc9a: d119 bne.n 1000dcd0 +1000dc9c: 7b30 ldrb r0, [r6, #12] +1000dc9e: 2803 cmp r0, #3 +1000dca0: bf18 it ne +1000dca2: 2801 cmpne r0, #1 +1000dca4: d003 beq.n 1000dcae +1000dca6: 2804 cmp r0, #4 +1000dca8: bf18 it ne +1000dcaa: 2805 cmpne r0, #5 +1000dcac: d124 bne.n 1000dcf8 + +1000dcae : +1000dcae: 6a27 ldr r7, [r4, #32] +1000dcb0: f7ff fe27 bl 1000d902 + +1000dcb4 : +1000dcb4: f7ff fdc1 bl 1000d83a + +1000dcb8 : +1000dcb8: f7ff fdbb bl 1000d832 + +1000dcbc : +1000dcbc: f7ff fdb5 bl 1000d82a + +1000dcc0 : +1000dcc0: 210c movs r1, #12 +1000dcc2: 4638 mov r0, r7 +1000dcc4: f7ff fe36 bl 1000d934 +1000dcc8: 4620 mov r0, r4 +1000dcca: f7ff fc1f bl 1000d50c +1000dcce: e013 b.n 1000dcf8 + +1000dcd0 : +1000dcd0: 2802 cmp r0, #2 +1000dcd2: bf04 itt eq +1000dcd4: 7b30 ldrbeq r0, [r6, #12] +1000dcd6: 2806 cmpeq r0, #6 +1000dcd8: d10e bne.n 1000dcf8 +1000dcda: 2000 movs r0, #0 +1000dcdc: 8370 strh r0, [r6, #26] +1000dcde: 6a25 ldr r5, [r4, #32] +1000dce0: 78b8 ldrb r0, [r7, #2] +1000dce2: b148 cbz r0, 1000dcf8 +1000dce4: 6978 ldr r0, [r7, #20] +1000dce6: f7fe fc34 bl 1000c552 +1000dcea: 6228 str r0, [r5, #32] +1000dcec: 68a8 ldr r0, [r5, #8] +1000dcee: 6900 ldr r0, [r0, #16] +1000dcf0: 6268 str r0, [r5, #36] ; 0x24 +1000dcf2: 4620 mov r0, r4 +1000dcf4: f7ff fad3 bl 1000d29e + +1000dcf8 : +1000dcf8: 2000 movs r0, #0 +1000dcfa: 60b0 str r0, [r6, #8] +1000dcfc: 4640 mov r0, r8 +1000dcfe: e8bd 41f0 ldmia.w sp!, {r4, r5, r6, r7, r8, lr} +1000dd02: f7fa bd71 b.w 100087e8 + +1000dd06 : +1000dd06: b5f8 push {r3, r4, r5, r6, r7, lr} +1000dd08: 0004 movs r4, r0 +1000dd0a: 460d mov r5, r1 +1000dd0c: 4616 mov r6, r2 +1000dd0e: d100 bne.n 1000dd12 +1000dd10: e082 b.n 1000de18 + +1000dd12 : +1000dd12: b915 cbnz r5, 1000dd1a +1000dd14: f06f 0005 mvn.w r0, #5 +1000dd18: bdf2 pop {r1, r4, r5, r6, r7, pc} + +1000dd1a : +1000dd1a: 2200 movs r2, #0 +1000dd1c: f44f 719a mov.w r1, #308 ; 0x134 +1000dd20: 2000 movs r0, #0 +1000dd22: f7fa fc51 bl 100085c8 +1000dd26: 6128 str r0, [r5, #16] +1000dd28: b900 cbnz r0, 1000dd2c +1000dd2a: e078 b.n 1000de1e + +1000dd2c : +1000dd2c: 7b68 ldrb r0, [r5, #13] +1000dd2e: 4f38 ldr r7, [pc, #224] ; (1000de10 ) +1000dd30: b910 cbnz r0, 1000dd38 +1000dd32: f002 fc51 bl 100105d8 +1000dd36: 6038 str r0, [r7, #0] + +1000dd38 : +1000dd38: 6838 ldr r0, [r7, #0] +1000dd3a: 6028 str r0, [r5, #0] +1000dd3c: 2101 movs r1, #1 +1000dd3e: 6928 ldr r0, [r5, #16] +1000dd40: 6840 ldr r0, [r0, #4] +1000dd42: 6168 str r0, [r5, #20] +1000dd44: 7001 strb r1, [r0, #0] +1000dd46: 2001 movs r0, #1 +1000dd48: 6969 ldr r1, [r5, #20] +1000dd4a: 7048 strb r0, [r1, #1] +1000dd4c: 6969 ldr r1, [r5, #20] +1000dd4e: f894 002a ldrb.w r0, [r4, #42] ; 0x2a +1000dd52: 7088 strb r0, [r1, #2] +1000dd54: 2000 movs r0, #0 +1000dd56: 6969 ldr r1, [r5, #20] +1000dd58: 70c8 strb r0, [r1, #3] +1000dd5a: 6828 ldr r0, [r5, #0] +1000dd5c: f7fe fbf9 bl 1000c552 +1000dd60: 6969 ldr r1, [r5, #20] +1000dd62: 6048 str r0, [r1, #4] +1000dd64: 2000 movs r0, #0 +1000dd66: 8108 strh r0, [r1, #8] +1000dd68: 8148 strh r0, [r1, #10] +1000dd6a: 60c8 str r0, [r1, #12] +1000dd6c: 2e08 cmp r6, #8 +1000dd6e: bf18 it ne +1000dd70: 2e04 cmpne r6, #4 +1000dd72: d006 beq.n 1000dd82 +1000dd74: 2e03 cmp r6, #3 +1000dd76: d106 bne.n 1000dd86 +1000dd78: 7b28 ldrb r0, [r5, #12] +1000dd7a: 2805 cmp r0, #5 +1000dd7c: bf18 it ne +1000dd7e: 2804 cmpne r0, #4 +1000dd80: d101 bne.n 1000dd86 + +1000dd82 : +1000dd82: 6860 ldr r0, [r4, #4] +1000dd84: 60c8 str r0, [r1, #12] + +1000dd86 : +1000dd86: 2000 movs r0, #0 +1000dd88: 6108 str r0, [r1, #16] +1000dd8a: 6148 str r0, [r1, #20] +1000dd8c: 6188 str r0, [r1, #24] + +1000dd8e : +1000dd8e: f894 102a ldrb.w r1, [r4, #42] ; 0x2a +1000dd92: 4288 cmp r0, r1 +1000dd94: bfba itte lt +1000dd96: 1901 addlt r1, r0, r4 +1000dd98: f891 102b ldrblt.w r1, [r1, #43] ; 0x2b +1000dd9c: 2100 movge r1, #0 +1000dd9e: 696a ldr r2, [r5, #20] +1000dda0: 1882 adds r2, r0, r2 +1000dda2: 1c40 adds r0, r0, #1 +1000dda4: b280 uxth r0, r0 +1000dda6: 7711 strb r1, [r2, #28] +1000dda8: 2810 cmp r0, #16 +1000ddaa: d3f0 bcc.n 1000dd8e +1000ddac: 2000 movs r0, #0 +1000ddae: 2100 movs r1, #0 + +1000ddb0 : +1000ddb0: 696a ldr r2, [r5, #20] +1000ddb2: 1882 adds r2, r0, r2 +1000ddb4: 1c40 adds r0, r0, #1 +1000ddb6: f882 102c strb.w r1, [r2, #44] ; 0x2c +1000ddba: 2840 cmp r0, #64 ; 0x40 +1000ddbc: d3f8 bcc.n 1000ddb0 +1000ddbe: 2000 movs r0, #0 + +1000ddc0 : +1000ddc0: 696a ldr r2, [r5, #20] +1000ddc2: 1882 adds r2, r0, r2 +1000ddc4: 1c40 adds r0, r0, #1 +1000ddc6: f882 106c strb.w r1, [r2, #108] ; 0x6c +1000ddca: 2880 cmp r0, #128 ; 0x80 +1000ddcc: d3f8 bcc.n 1000ddc0 +1000ddce: 6969 ldr r1, [r5, #20] +1000ddd0: 4810 ldr r0, [pc, #64] ; (1000de14 ) +1000ddd2: f8c1 00ec str.w r0, [r1, #236] ; 0xec +1000ddd6: 2000 movs r0, #0 +1000ddd8: 8328 strh r0, [r5, #24] + +1000ddda : +1000ddda: 6969 ldr r1, [r5, #20] +1000dddc: 1841 adds r1, r0, r1 +1000ddde: f881 00f0 strb.w r0, [r1, #240] ; 0xf0 +1000dde2: 1c40 adds r0, r0, #1 +1000dde4: 2844 cmp r0, #68 ; 0x44 +1000dde6: d3f8 bcc.n 1000ddda +1000dde8: 2201 movs r2, #1 +1000ddea: 2135 movs r1, #53 ; 0x35 +1000ddec: 4628 mov r0, r5 +1000ddee: f7ff fda9 bl 1000d944 +1000ddf2: 4631 mov r1, r6 +1000ddf4: 4628 mov r0, r5 +1000ddf6: f7ff fdb4 bl 1000d962 +1000ddfa: 2000 movs r0, #0 +1000ddfc: bdf2 pop {r1, r4, r5, r6, r7, pc} + ... + +1000de00 : +1000de00: 78a0 1004 .x.. + +1000de04 : +1000de04: 4290 1000 .B.. + +1000de08 : +1000de08: 4294 1000 .B.. + +1000de0c : +1000de0c: 729c 1004 .r.. + +1000de10 : +1000de10: 72d0 1004 .r.. + +1000de14 : +1000de14: 8263 6353 c.Sc + +1000de18 : +1000de18: f06f 000d mvn.w r0, #13 +1000de1c: bdf2 pop {r1, r4, r5, r6, r7, pc} + +1000de1e : +1000de1e: f04f 30ff mov.w r0, #4294967295 +1000de22: bdf2 pop {r1, r4, r5, r6, r7, pc} + +1000de24 : +1000de24: b510 push {r4, lr} +1000de26: 0004 movs r4, r0 +1000de28: d006 beq.n 1000de38 +1000de2a: 6920 ldr r0, [r4, #16] +1000de2c: b108 cbz r0, 1000de32 +1000de2e: f7fa fcdb bl 100087e8 + +1000de32 : +1000de32: 2000 movs r0, #0 +1000de34: 6120 str r0, [r4, #16] +1000de36: 6160 str r0, [r4, #20] + +1000de38 : +1000de38: bd10 pop {r4, pc} + +1000de3a : +1000de3a: b900 cbnz r0, 1000de3e +1000de3c: 4770 bx lr + +1000de3e : +1000de3e: b510 push {r4, lr} +1000de40: 8b01 ldrh r1, [r0, #24] +1000de42: 6943 ldr r3, [r0, #20] +1000de44: 1c4a adds r2, r1, #1 +1000de46: 18c9 adds r1, r1, r3 +1000de48: 24ff movs r4, #255 ; 0xff +1000de4a: f881 40f0 strb.w r4, [r1, #240] ; 0xf0 +1000de4e: e004 b.n 1000de5a + +1000de50 : +1000de50: 18d4 adds r4, r2, r3 +1000de52: 2100 movs r1, #0 +1000de54: f884 10f0 strb.w r1, [r4, #240] ; 0xf0 +1000de58: 1c52 adds r2, r2, #1 + +1000de5a : +1000de5a: b292 uxth r2, r2 +1000de5c: 2a44 cmp r2, #68 ; 0x44 +1000de5e: d302 bcc.n 1000de66 +1000de60: 2403 movs r4, #3 +1000de62: 4222 tst r2, r4 +1000de64: d001 beq.n 1000de6a + +1000de66 : +1000de66: 2a44 cmp r2, #68 ; 0x44 +1000de68: d3f2 bcc.n 1000de50 + +1000de6a : +1000de6a: 8302 strh r2, [r0, #24] +1000de6c: bd10 pop {r4, pc} + ... + +1000de70 : +1000de70: 6a41 ldr r1, [r0, #36] ; 0x24 +1000de72: 7a4a ldrb r2, [r1, #9] +1000de74: 1c52 adds r2, r2, #1 +1000de76: 724a strb r2, [r1, #9] +1000de78: e011 b.n 1000de9e + +1000de7a : +1000de7a: b500 push {lr} +1000de7c: b085 sub sp, #20 +1000de7e: 6a41 ldr r1, [r0, #36] ; 0x24 +1000de80: 9102 str r1, [sp, #8] +1000de82: 2201 movs r2, #1 +1000de84: 9203 str r2, [sp, #12] +1000de86: 9100 str r1, [sp, #0] +1000de88: f100 032b add.w r3, r0, #43 ; 0x2b +1000de8c: 4a7c ldr r2, [pc, #496] ; (1000e080 ) +1000de8e: 9201 str r2, [sp, #4] +1000de90: f100 012b add.w r1, r0, #43 ; 0x2b +1000de94: 4a7b ldr r2, [pc, #492] ; (1000e084 ) +1000de96: f7fd fe4d bl 1000bb34 +1000de9a: b005 add sp, #20 +1000de9c: bd00 pop {pc} + +1000de9e : +1000de9e: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1000dea2: 4604 mov r4, r0 +1000dea4: f104 072f add.w r7, r4, #47 ; 0x2f +1000dea8: 1d26 adds r6, r4, #4 +1000deaa: 78b8 ldrb r0, [r7, #2] +1000deac: 6a35 ldr r5, [r6, #32] +1000deae: 07c0 lsls r0, r0, #31 +1000deb0: bf44 itt mi +1000deb2: 4620 movmi r0, r4 +1000deb4: f001 f914 blmi 1000f0e0 +1000deb8: 2000 movs r0, #0 +1000deba: 6060 str r0, [r4, #4] +1000debc: 6070 str r0, [r6, #4] +1000debe: 60b0 str r0, [r6, #8] +1000dec0: b96d cbnz r5, 1000dede +1000dec2: 200c movs r0, #12 +1000dec4: f7fe f91b bl 1000c0fe +1000dec8: 0005 movs r5, r0 +1000deca: bf08 it eq +1000decc: f04f 30ff moveq.w r0, #4294967295 +1000ded0: d02b beq.n 1000df2a +1000ded2: 220c movs r2, #12 +1000ded4: 2100 movs r1, #0 +1000ded6: f7fe fa39 bl 1000c34c +1000deda: 6235 str r5, [r6, #32] +1000dedc: e004 b.n 1000dee8 + +1000dede : +1000dede: 7128 strb r0, [r5, #4] +1000dee0: 80e8 strh r0, [r5, #6] +1000dee2: 7168 strb r0, [r5, #5] +1000dee4: 6028 str r0, [r5, #0] +1000dee6: 7228 strb r0, [r5, #8] + +1000dee8 : +1000dee8: f894 002f ldrb.w r0, [r4, #47] ; 0x2f +1000deec: 7879 ldrb r1, [r7, #1] +1000deee: f8df 8198 ldr.w r8, [pc, #408] ; 1000e088 +1000def2: ea40 2001 orr.w r0, r0, r1, lsl #8 +1000def6: 4440 add r0, r8 +1000def8: f7fe fb2b bl 1000c552 +1000defc: f7fe fb35 bl 1000c56a +1000df00: 6a31 ldr r1, [r6, #32] +1000df02: 7a49 ldrb r1, [r1, #9] +1000df04: 1808 adds r0, r1, r0 +1000df06: f6ca 10fe movt r0, #43518 ; 0xa9fe +1000df0a: 4540 cmp r0, r8 +1000df0c: bf38 it cc +1000df0e: f500 407e addcc.w r0, r0, #65024 ; 0xfe00 +1000df12: 495e ldr r1, [pc, #376] ; (1000e08c ) +1000df14: 4288 cmp r0, r1 +1000df16: bf28 it cs +1000df18: f5a0 407e subcs.w r0, r0, #65024 ; 0xfe00 +1000df1c: f7fe fb19 bl 1000c552 +1000df20: 6028 str r0, [r5, #0] +1000df22: 4620 mov r0, r4 +1000df24: f000 f803 bl 1000df2e +1000df28: 2000 movs r0, #0 + +1000df2a : +1000df2a: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +1000df2e : +1000df2e: b510 push {r4, lr} +1000df30: 6a41 ldr r1, [r0, #36] ; 0x24 +1000df32: 2201 movs r2, #1 +1000df34: 710a strb r2, [r1, #4] +1000df36: 2200 movs r2, #0 +1000df38: 714a strb r2, [r1, #5] +1000df3a: 6a42 ldr r2, [r0, #36] ; 0x24 +1000df3c: b102 cbz r2, 1000df40 +1000df3e: 7a52 ldrb r2, [r2, #9] + +1000df40 : +1000df40: 3024 adds r0, #36 ; 0x24 +1000df42: 7a84 ldrb r4, [r0, #10] +1000df44: 7b03 ldrb r3, [r0, #12] +1000df46: 0424 lsls r4, r4, #16 +1000df48: ea44 6303 orr.w r3, r4, r3, lsl #24 +1000df4c: 7a44 ldrb r4, [r0, #9] +1000df4e: 7ac0 ldrb r0, [r0, #11] +1000df50: ea43 2304 orr.w r3, r3, r4, lsl #8 +1000df54: 4318 orrs r0, r3 +1000df56: 1810 adds r0, r2, r0 +1000df58: 220a movs r2, #10 +1000df5a: fbb0 f2f2 udiv r2, r0, r2 +1000df5e: 230a movs r3, #10 +1000df60: fb03 0012 mls r0, r3, r2, r0 +1000df64: 80c8 strh r0, [r1, #6] +1000df66: 7a48 ldrb r0, [r1, #9] +1000df68: 280b cmp r0, #11 +1000df6a: bfa4 itt ge +1000df6c: f44f 7016 movge.w r0, #600 ; 0x258 +1000df70: 80c8 strhge r0, [r1, #6] +1000df72: bd10 pop {r4, pc} + +1000df74 : +1000df74: e92d 41ff stmdb sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, lr} +1000df78: 4845 ldr r0, [pc, #276] ; (1000e090 ) +1000df7a: f8df 8108 ldr.w r8, [pc, #264] ; 1000e084 +1000df7e: 6804 ldr r4, [r0, #0] +1000df80: 4d44 ldr r5, [pc, #272] ; (1000e094 ) +1000df82: 4e3f ldr r6, [pc, #252] ; (1000e080 ) +1000df84: f64f 77ff movw r7, #65535 ; 0xffff +1000df88: e014 b.n 1000dfb4 + +1000df8a : +1000df8a: 4620 mov r0, r4 +1000df8c: f7ff ff75 bl 1000de7a + +1000df90 : +1000df90: 6a60 ldr r0, [r4, #36] ; 0x24 +1000df92: 2114 movs r1, #20 +1000df94: 80c1 strh r1, [r0, #6] +1000df96: 7941 ldrb r1, [r0, #5] +1000df98: 1c49 adds r1, r1, #1 +1000df9a: 7141 strb r1, [r0, #5] +1000df9c: 6a60 ldr r0, [r4, #36] ; 0x24 +1000df9e: 7941 ldrb r1, [r0, #5] +1000dfa0: 2902 cmp r1, #2 +1000dfa2: db06 blt.n 1000dfb2 +1000dfa4: 2103 movs r1, #3 +1000dfa6: 7101 strb r1, [r0, #4] +1000dfa8: 2000 movs r0, #0 +1000dfaa: 6a61 ldr r1, [r4, #36] ; 0x24 +1000dfac: 7148 strb r0, [r1, #5] + +1000dfae : +1000dfae: 6a61 ldr r1, [r4, #36] ; 0x24 + +1000dfb0 : +1000dfb0: 80c8 strh r0, [r1, #6] + +1000dfb2 : +1000dfb2: 6824 ldr r4, [r4, #0] + +1000dfb4 : +1000dfb4: 2c00 cmp r4, #0 +1000dfb6: d060 beq.n 1000e07a +1000dfb8: 6a60 ldr r0, [r4, #36] ; 0x24 +1000dfba: 2800 cmp r0, #0 +1000dfbc: d0f9 beq.n 1000dfb2 +1000dfbe: 7a01 ldrb r1, [r0, #8] +1000dfc0: b109 cbz r1, 1000dfc6 +1000dfc2: 1e49 subs r1, r1, #1 +1000dfc4: 7201 strb r1, [r0, #8] + +1000dfc6 : +1000dfc6: 6a61 ldr r1, [r4, #36] ; 0x24 +1000dfc8: 7908 ldrb r0, [r1, #4] +1000dfca: 2801 cmp r0, #1 +1000dfcc: d002 beq.n 1000dfd4 +1000dfce: 2802 cmp r0, #2 +1000dfd0: d03b beq.n 1000e04a +1000dfd2: e7ee b.n 1000dfb2 + +1000dfd4 : +1000dfd4: 88c8 ldrh r0, [r1, #6] +1000dfd6: 2800 cmp r0, #0 +1000dfd8: d139 bne.n 1000e04e +1000dfda: 7948 ldrb r0, [r1, #5] +1000dfdc: 2803 cmp r0, #3 +1000dfde: db06 blt.n 1000dfee +1000dfe0: 2002 movs r0, #2 +1000dfe2: 7108 strb r0, [r1, #4] +1000dfe4: 2000 movs r0, #0 +1000dfe6: 6a61 ldr r1, [r4, #36] ; 0x24 +1000dfe8: 7148 strb r0, [r1, #5] +1000dfea: 2014 movs r0, #20 +1000dfec: e7df b.n 1000dfae + +1000dfee : +1000dfee: 2001 movs r0, #1 +1000dff0: 9003 str r0, [sp, #12] +1000dff2: 9102 str r1, [sp, #8] +1000dff4: 9601 str r6, [sp, #4] +1000dff6: 9500 str r5, [sp, #0] +1000dff8: f104 032b add.w r3, r4, #43 ; 0x2b +1000dffc: 4642 mov r2, r8 +1000dffe: f104 012b add.w r1, r4, #43 ; 0x2b +1000e002: 4620 mov r0, r4 +1000e004: f7fd fd96 bl 1000bb34 +1000e008: 6a60 ldr r0, [r4, #36] ; 0x24 +1000e00a: 7941 ldrb r1, [r0, #5] +1000e00c: 1c49 adds r1, r1, #1 +1000e00e: 7141 strb r1, [r0, #5] +1000e010: 6a60 ldr r0, [r4, #36] ; 0x24 +1000e012: 2800 cmp r0, #0 +1000e014: bf14 ite ne +1000e016: 7a41 ldrbne r1, [r0, #9] +1000e018: 2100 moveq r1, #0 +1000e01a: f894 302e ldrb.w r3, [r4, #46] ; 0x2e +1000e01e: f894 2030 ldrb.w r2, [r4, #48] ; 0x30 +1000e022: 041b lsls r3, r3, #16 +1000e024: ea43 6202 orr.w r2, r3, r2, lsl #24 +1000e028: f894 302d ldrb.w r3, [r4, #45] ; 0x2d +1000e02c: ea42 2203 orr.w r2, r2, r3, lsl #8 +1000e030: f894 302f ldrb.w r3, [r4, #47] ; 0x2f +1000e034: 431a orrs r2, r3 +1000e036: 1889 adds r1, r1, r2 +1000e038: 220a movs r2, #10 +1000e03a: fbb1 f2f2 udiv r2, r1, r2 +1000e03e: 230a movs r3, #10 +1000e040: fb03 1112 mls r1, r3, r2, r1 +1000e044: 310a adds r1, #10 +1000e046: 80c1 strh r1, [r0, #6] +1000e048: e7b3 b.n 1000dfb2 + +1000e04a : +1000e04a: 88c8 ldrh r0, [r1, #6] +1000e04c: b108 cbz r0, 1000e052 + +1000e04e : +1000e04e: 1838 adds r0, r7, r0 +1000e050: e7ae b.n 1000dfb0 + +1000e052 : +1000e052: 7948 ldrb r0, [r1, #5] +1000e054: 2800 cmp r0, #0 +1000e056: d198 bne.n 1000df8a +1000e058: 9000 str r0, [sp, #0] +1000e05a: 9701 str r7, [sp, #4] +1000e05c: 4620 mov r0, r4 +1000e05e: f000 fff1 bl 1000f044 +1000e062: a901 add r1, sp, #4 +1000e064: 4620 mov r0, r4 +1000e066: f001 f81d bl 1000f0a4 +1000e06a: a900 add r1, sp, #0 +1000e06c: 4620 mov r0, r4 +1000e06e: f001 f815 bl 1000f09c +1000e072: 4620 mov r0, r4 +1000e074: f001 f824 bl 1000f0c0 +1000e078: e78a b.n 1000df90 + +1000e07a : +1000e07a: e8bd 81ff ldmia.w sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, pc} + ... + +1000e080 : +1000e080: bca4 1000 .... + +1000e084 : +1000e084: bc9c 1000 .... + +1000e088 : +1000e088: 0100 a9fe .... + +1000e08c : +1000e08c: ff00 a9fe .... + +1000e090 : +1000e090: 78a0 1004 .x.. + +1000e094 : +1000e094: 4290 1000 .B.. + +1000e098 : +1000e098: b530 push {r4, r5, lr} +1000e09a: 4604 mov r4, r0 +1000e09c: b085 sub sp, #20 +1000e09e: 6a60 ldr r0, [r4, #36] ; 0x24 +1000e0a0: 460d mov r5, r1 +1000e0a2: 2800 cmp r0, #0 +1000e0a4: bf1c itt ne +1000e0a6: 7900 ldrbne r0, [r0, #4] +1000e0a8: 2800 cmpne r0, #0 +1000e0aa: d03a beq.n 1000e122 +1000e0ac: 2206 movs r2, #6 +1000e0ae: f104 012b add.w r1, r4, #43 ; 0x2b +1000e0b2: a802 add r0, sp, #8 +1000e0b4: f7fe f948 bl 1000c348 +1000e0b8: 2204 movs r2, #4 +1000e0ba: f105 010e add.w r1, r5, #14 +1000e0be: a800 add r0, sp, #0 +1000e0c0: f7fe f942 bl 1000c348 +1000e0c4: 2204 movs r2, #4 +1000e0c6: f105 0118 add.w r1, r5, #24 +1000e0ca: a801 add r0, sp, #4 +1000e0cc: f7fe f93c bl 1000c348 +1000e0d0: 6a60 ldr r0, [r4, #36] ; 0x24 +1000e0d2: 7901 ldrb r1, [r0, #4] +1000e0d4: 2901 cmp r1, #1 +1000e0d6: d004 beq.n 1000e0e2 +1000e0d8: 2902 cmp r1, #2 +1000e0da: bf04 itt eq +1000e0dc: 7941 ldrbeq r1, [r0, #5] +1000e0de: 2900 cmpeq r1, #0 +1000e0e0: d10b bne.n 1000e0fa + +1000e0e2 : +1000e0e2: 6800 ldr r0, [r0, #0] +1000e0e4: 9900 ldr r1, [sp, #0] +1000e0e6: 4281 cmp r1, r0 +1000e0e8: d005 beq.n 1000e0f6 +1000e0ea: 9901 ldr r1, [sp, #4] +1000e0ec: 4281 cmp r1, r0 +1000e0ee: d118 bne.n 1000e122 +1000e0f0: f000 f819 bl 1000e126 + +1000e0f4 : +1000e0f4: b1a8 cbz r0, 1000e122 + +1000e0f6 : +1000e0f6: 4620 mov r0, r4 +1000e0f8: e00b b.n 1000e112 + +1000e0fa : +1000e0fa: 9900 ldr r1, [sp, #0] +1000e0fc: 6800 ldr r0, [r0, #0] +1000e0fe: 4281 cmp r1, r0 +1000e100: d10f bne.n 1000e122 +1000e102: f000 f810 bl 1000e126 + +1000e106 : +1000e106: b160 cbz r0, 1000e122 +1000e108: 6a60 ldr r0, [r4, #36] ; 0x24 +1000e10a: 7a00 ldrb r0, [r0, #8] +1000e10c: 2800 cmp r0, #0 +1000e10e: 4620 mov r0, r4 +1000e110: d002 beq.n 1000e118 + +1000e112 : +1000e112: f7ff fead bl 1000de70 +1000e116: e004 b.n 1000e122 + +1000e118 : +1000e118: f7ff feaf bl 1000de7a +1000e11c: 6a61 ldr r1, [r4, #36] ; 0x24 +1000e11e: 2064 movs r0, #100 ; 0x64 +1000e120: 7208 strb r0, [r1, #8] + +1000e122 : +1000e122: b005 add sp, #20 +1000e124: bd30 pop {r4, r5, pc} + +1000e126 : +1000e126: 2206 movs r2, #6 +1000e128: f105 0108 add.w r1, r5, #8 +1000e12c: a802 add r0, sp, #8 +1000e12e: f7fe b909 b.w 1000c344 + ... + +1000e134 <__aeabi_memclr>: +1000e134: 2200 movs r2, #0 +1000e136: f002 bac3 b.w 100106c0 <__iar_Memset_word> + ... + +1000e13c : +1000e13c: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} +1000e140: 4605 mov r5, r0 +1000e142: b083 sub sp, #12 +1000e144: 6868 ldr r0, [r5, #4] +1000e146: f8df 479c ldr.w r4, [pc, #1948] ; 1000e8e4 +1000e14a: 460e mov r6, r1 +1000e14c: 7801 ldrb r1, [r0, #0] +1000e14e: f001 010f and.w r1, r1, #15 +1000e152: eb00 0181 add.w r1, r0, r1, lsl #2 +1000e156: 61e1 str r1, [r4, #28] +1000e158: 7800 ldrb r0, [r0, #0] +1000e15a: f000 000f and.w r0, r0, #15 +1000e15e: f000 f998 bl 1000e492 + +1000e162 : +1000e162: 2800 cmp r0, #0 +1000e164: d126 bne.n 1000e1b4 +1000e166: 8928 ldrh r0, [r5, #8] +1000e168: 2814 cmp r0, #20 +1000e16a: f0c0 818b bcc.w 1000e484 +1000e16e: f8df 8778 ldr.w r8, [pc, #1912] ; 1000e8e8 +1000e172: f8d8 0000 ldr.w r0, [r8] +1000e176: 4631 mov r1, r6 +1000e178: f7fe f8f8 bl 1000c36c +1000e17c: 2800 cmp r0, #0 +1000e17e: d119 bne.n 1000e1b4 +1000e180: f898 0000 ldrb.w r0, [r8] +1000e184: f000 00f0 and.w r0, r0, #240 ; 0xf0 +1000e188: 28e0 cmp r0, #224 ; 0xe0 +1000e18a: f000 817b beq.w 1000e484 +1000e18e: 8928 ldrh r0, [r5, #8] +1000e190: f8df 9d44 ldr.w r9, [pc, #3396] ; 1000eed8 +1000e194: 9000 str r0, [sp, #0] +1000e196: 2306 movs r3, #6 +1000e198: 4642 mov r2, r8 +1000e19a: 4649 mov r1, r9 +1000e19c: 4628 mov r0, r5 +1000e19e: f7fe fa11 bl 1000c5c4 +1000e1a2: 2800 cmp r0, #0 +1000e1a4: d106 bne.n 1000e1b4 +1000e1a6: 69e0 ldr r0, [r4, #28] +1000e1a8: f000 fed0 bl 1000ef4c + +1000e1ac : +1000e1ac: 0b00 lsrs r0, r0, #12 +1000e1ae: f000 f970 bl 1000e492 + +1000e1b2 : +1000e1b2: 2800 cmp r0, #0 + +1000e1b4 : +1000e1b4: f040 8166 bne.w 1000e484 +1000e1b8: 69e0 ldr r0, [r4, #28] +1000e1ba: 8800 ldrh r0, [r0, #0] +1000e1bc: f7fe f9c8 bl 1000c550 +1000e1c0: 69e1 ldr r1, [r4, #28] +1000e1c2: 8008 strh r0, [r1, #0] +1000e1c4: 8848 ldrh r0, [r1, #2] +1000e1c6: f7fe f9c3 bl 1000c550 +1000e1ca: 69e1 ldr r1, [r4, #28] +1000e1cc: 8048 strh r0, [r1, #2] +1000e1ce: 6848 ldr r0, [r1, #4] +1000e1d0: f7fe f9cb bl 1000c56a +1000e1d4: 69e1 ldr r1, [r4, #28] +1000e1d6: 6048 str r0, [r1, #4] +1000e1d8: 6220 str r0, [r4, #32] +1000e1da: 6888 ldr r0, [r1, #8] +1000e1dc: f7fe f9c5 bl 1000c56a +1000e1e0: 69e1 ldr r1, [r4, #28] +1000e1e2: 6088 str r0, [r1, #8] +1000e1e4: 6260 str r0, [r4, #36] ; 0x24 +1000e1e6: 89c8 ldrh r0, [r1, #14] +1000e1e8: f7fe f9b2 bl 1000c550 +1000e1ec: 69e1 ldr r1, [r4, #28] +1000e1ee: 81c8 strh r0, [r1, #14] +1000e1f0: 8988 ldrh r0, [r1, #12] +1000e1f2: f7fe f9ad bl 1000c550 +1000e1f6: f000 003f and.w r0, r0, #63 ; 0x3f +1000e1fa: 7020 strb r0, [r4, #0] +1000e1fc: 4601 mov r1, r0 +1000e1fe: f011 0003 ands.w r0, r1, #3 +1000e202: bf18 it ne +1000e204: 2001 movne r0, #1 +1000e206: 892a ldrh r2, [r5, #8] +1000e208: f8df 7cd0 ldr.w r7, [pc, #3280] ; 1000eedc +1000e20c: 69e3 ldr r3, [r4, #28] +1000e20e: 1880 adds r0, r0, r2 +1000e210: 8320 strh r0, [r4, #24] +1000e212: 2200 movs r2, #0 +1000e214: 683e ldr r6, [r7, #0] +1000e216: e001 b.n 1000e21c + +1000e218 : +1000e218: 4632 mov r2, r6 +1000e21a: 68f6 ldr r6, [r6, #12] + +1000e21c : +1000e21c: 2e00 cmp r6, #0 +1000e21e: d04d beq.n 1000e2bc +1000e220: f8b3 e000 ldrh.w lr, [r3] +1000e224: f8b6 c020 ldrh.w ip, [r6, #32] +1000e228: 45f4 cmp ip, lr +1000e22a: bf02 ittt eq +1000e22c: f8b6 c01e ldrheq.w ip, [r6, #30] +1000e230: f8b3 e002 ldrheq.w lr, [r3, #2] +1000e234: 45f4 cmpeq ip, lr +1000e236: d1ef bne.n 1000e218 +1000e238: f8d6 c004 ldr.w ip, [r6, #4] +1000e23c: f8d9 e000 ldr.w lr, [r9] +1000e240: 45f4 cmp ip, lr +1000e242: bf02 ittt eq +1000e244: f8d6 c000 ldreq.w ip, [r6] +1000e248: f8d8 e000 ldreq.w lr, [r8] +1000e24c: 45f4 cmpeq ip, lr +1000e24e: d1e3 bne.n 1000e218 +1000e250: b122 cbz r2, 1000e25c +1000e252: 68f0 ldr r0, [r6, #12] +1000e254: 60d0 str r0, [r2, #12] +1000e256: 6838 ldr r0, [r7, #0] +1000e258: 60f0 str r0, [r6, #12] +1000e25a: 603e str r6, [r7, #0] + +1000e25c : +1000e25c: 2000 movs r0, #0 +1000e25e: 6060 str r0, [r4, #4] +1000e260: 8928 ldrh r0, [r5, #8] +1000e262: 81a0 strh r0, [r4, #12] +1000e264: 60a5 str r5, [r4, #8] +1000e266: 2000 movs r0, #0 +1000e268: 62a0 str r0, [r4, #40] ; 0x28 +1000e26a: 7060 strb r0, [r4, #1] +1000e26c: 6163 str r3, [r4, #20] +1000e26e: 0708 lsls r0, r1, #28 +1000e270: d503 bpl.n 1000e27a +1000e272: 7b68 ldrb r0, [r5, #13] +1000e274: f040 0001 orr.w r0, r0, #1 +1000e278: 7368 strb r0, [r5, #13] + +1000e27a : +1000e27a: f06f 0509 mvn.w r5, #9 +1000e27e: 6ff0 ldr r0, [r6, #124] ; 0x7c +1000e280: b158 cbz r0, 1000e29a +1000e282: 4630 mov r0, r6 +1000e284: f7fa ffaf bl 100091e6 +1000e288: 42a8 cmp r0, r5 +1000e28a: d00b beq.n 1000e2a4 +1000e28c: 6ff0 ldr r0, [r6, #124] ; 0x7c +1000e28e: 2800 cmp r0, #0 +1000e290: bf1c itt ne +1000e292: 8b20 ldrhne r0, [r4, #24] +1000e294: 2800 cmpne r0, #0 +1000e296: f040 80d9 bne.w 1000e44c + +1000e29a : +1000e29a: 62e6 str r6, [r4, #44] ; 0x2c +1000e29c: 4630 mov r0, r6 +1000e29e: f000 f96b bl 1000e578 +1000e2a2: 42a8 cmp r0, r5 + +1000e2a4 : +1000e2a4: f000 80d2 beq.w 1000e44c +1000e2a8: 7860 ldrb r0, [r4, #1] +1000e2aa: 0701 lsls r1, r0, #28 +1000e2ac: d568 bpl.n 1000e380 +1000e2ae: f8d6 2090 ldr.w r2, [r6, #144] ; 0x90 +1000e2b2: 0010 movs r0, r2 +1000e2b4: d072 beq.n 1000e39c +1000e2b6: f06f 010a mvn.w r1, #10 +1000e2ba: e06d b.n 1000e398 + +1000e2bc : +1000e2bc: f8df 2d08 ldr.w r2, [pc, #3336] ; 1000efc8 +1000e2c0: 6816 ldr r6, [r2, #0] +1000e2c2: e000 b.n 1000e2c6 + +1000e2c4 : +1000e2c4: 68f6 ldr r6, [r6, #12] + +1000e2c6 : +1000e2c6: 2e00 cmp r6, #0 +1000e2c8: d03b beq.n 1000e342 +1000e2ca: 69e3 ldr r3, [r4, #28] +1000e2cc: 8c37 ldrh r7, [r6, #32] +1000e2ce: 881a ldrh r2, [r3, #0] +1000e2d0: 4297 cmp r7, r2 +1000e2d2: bf02 ittt eq +1000e2d4: 885b ldrheq r3, [r3, #2] +1000e2d6: 8bf7 ldrheq r7, [r6, #30] +1000e2d8: 429f cmpeq r7, r3 +1000e2da: d1f3 bne.n 1000e2c4 +1000e2dc: 6877 ldr r7, [r6, #4] +1000e2de: f8d9 e000 ldr.w lr, [r9] +1000e2e2: 4577 cmp r7, lr +1000e2e4: bf02 ittt eq +1000e2e6: 6837 ldreq r7, [r6, #0] +1000e2e8: f8d8 e000 ldreq.w lr, [r8] +1000e2ec: 4577 cmpeq r7, lr +1000e2ee: d1e9 bne.n 1000e2c4 +1000e2f0: 074f lsls r7, r1, #29 +1000e2f2: d425 bmi.n 1000e340 +1000e2f4: 078f lsls r7, r1, #30 +1000e2f6: d511 bpl.n 1000e31c +1000e2f8: 6a21 ldr r1, [r4, #32] +1000e2fa: 6af7 ldr r7, [r6, #44] ; 0x2c +1000e2fc: 1bcf subs r7, r1, r7 +1000e2fe: d413 bmi.n 1000e328 +1000e300: f8b6 e030 ldrh.w lr, [r6, #48] ; 0x30 +1000e304: eba7 070e sub.w r7, r7, lr +1000e308: 2f01 cmp r7, #1 +1000e30a: da0d bge.n 1000e328 +1000e30c: b280 uxth r0, r0 +1000e30e: 9201 str r2, [sp, #4] +1000e310: 9300 str r3, [sp, #0] +1000e312: 1841 adds r1, r0, r1 +1000e314: 6a60 ldr r0, [r4, #36] ; 0x24 +1000e316: 464b mov r3, r9 +1000e318: 4642 mov r2, r8 +1000e31a: e0b1 b.n 1000e480 + +1000e31c : +1000e31c: 07c9 lsls r1, r1, #31 +1000e31e: d503 bpl.n 1000e328 +1000e320: f8df 1ca8 ldr.w r1, [pc, #3240] ; 1000efcc +1000e324: 6809 ldr r1, [r1, #0] +1000e326: 62b1 str r1, [r6, #40] ; 0x28 + +1000e328 : +1000e328: b280 uxth r0, r0 +1000e32a: 2800 cmp r0, #0 +1000e32c: d008 beq.n 1000e340 +1000e32e: f896 0022 ldrb.w r0, [r6, #34] ; 0x22 +1000e332: f040 0002 orr.w r0, r0, #2 +1000e336: f886 0022 strb.w r0, [r6, #34] ; 0x22 +1000e33a: 4630 mov r0, r6 +1000e33c: f7fb fe67 bl 1000a00e + +1000e340 : +1000e340: e0a0 b.n 1000e484 + +1000e342 : +1000e342: f8df 1c8c ldr.w r1, [pc, #3212] ; 1000efd0 +1000e346: 6808 ldr r0, [r1, #0] +1000e348: 2200 movs r2, #0 +1000e34a: e001 b.n 1000e350 + +1000e34c : +1000e34c: 4602 mov r2, r0 +1000e34e: 68c0 ldr r0, [r0, #12] + +1000e350 : +1000e350: 2800 cmp r0, #0 +1000e352: f000 8085 beq.w 1000e460 +1000e356: 69e6 ldr r6, [r4, #28] +1000e358: 8bc3 ldrh r3, [r0, #30] +1000e35a: 8876 ldrh r6, [r6, #2] +1000e35c: 42b3 cmp r3, r6 +1000e35e: d1f5 bne.n 1000e34c +1000e360: 6803 ldr r3, [r0, #0] +1000e362: f8d8 6000 ldr.w r6, [r8] +1000e366: 42b3 cmp r3, r6 +1000e368: bf18 it ne +1000e36a: 2b00 cmpne r3, #0 +1000e36c: d1ee bne.n 1000e34c +1000e36e: b122 cbz r2, 1000e37a +1000e370: 68c3 ldr r3, [r0, #12] +1000e372: 60d3 str r3, [r2, #12] +1000e374: 680a ldr r2, [r1, #0] +1000e376: 60c2 str r2, [r0, #12] +1000e378: 6008 str r0, [r1, #0] + +1000e37a : +1000e37a: f000 f890 bl 1000e49e +1000e37e: e081 b.n 1000e484 + +1000e380 : +1000e380: 06c0 lsls r0, r0, #27 +1000e382: d514 bpl.n 1000e3ae +1000e384: f896 0022 ldrb.w r0, [r6, #34] ; 0x22 +1000e388: 06c0 lsls r0, r0, #27 +1000e38a: d407 bmi.n 1000e39c +1000e38c: f8d6 2090 ldr.w r2, [r6, #144] ; 0x90 +1000e390: 0010 movs r0, r2 +1000e392: d003 beq.n 1000e39c +1000e394: f06f 010b mvn.w r1, #11 + +1000e398 : +1000e398: 6930 ldr r0, [r6, #16] +1000e39a: 4790 blx r2 + +1000e39c : +1000e39c: 4631 mov r1, r6 +1000e39e: 4638 mov r0, r7 +1000e3a0: f7fb f848 bl 10009434 +1000e3a4: 4631 mov r1, r6 +1000e3a6: 2002 movs r0, #2 +1000e3a8: f7f9 ffae bl 10008308 +1000e3ac: e04e b.n 1000e44c + +1000e3ae : +1000e3ae: f8b6 2068 ldrh.w r2, [r6, #104] ; 0x68 +1000e3b2: b142 cbz r2, 1000e3c6 +1000e3b4: f8d6 3080 ldr.w r3, [r6, #128] ; 0x80 +1000e3b8: 0018 movs r0, r3 +1000e3ba: d004 beq.n 1000e3c6 +1000e3bc: 6930 ldr r0, [r6, #16] +1000e3be: 4631 mov r1, r6 +1000e3c0: 4798 blx r3 +1000e3c2: 42a8 cmp r0, r5 +1000e3c4: d042 beq.n 1000e44c + +1000e3c6 : +1000e3c6: 6aa2 ldr r2, [r4, #40] ; 0x28 +1000e3c8: b1f2 cbz r2, 1000e408 +1000e3ca: f896 0022 ldrb.w r0, [r6, #34] ; 0x22 +1000e3ce: 06c0 lsls r0, r0, #27 +1000e3d0: d506 bpl.n 1000e3e0 +1000e3d2: 4610 mov r0, r2 +1000e3d4: f7fa fa08 bl 100087e8 +1000e3d8: 4630 mov r0, r6 +1000e3da: f7fa fc4f bl 10008c7c +1000e3de: e035 b.n 1000e44c + +1000e3e0 : +1000e3e0: f8d6 8084 ldr.w r8, [r6, #132] ; 0x84 +1000e3e4: ea5f 0008 movs.w r0, r8 +1000e3e8: d004 beq.n 1000e3f4 +1000e3ea: 6930 ldr r0, [r6, #16] +1000e3ec: 2300 movs r3, #0 +1000e3ee: 4631 mov r1, r6 +1000e3f0: 47c0 blx r8 +1000e3f2: e004 b.n 1000e3fe + +1000e3f4 : +1000e3f4: 2300 movs r3, #0 +1000e3f6: 4631 mov r1, r6 +1000e3f8: 2000 movs r0, #0 +1000e3fa: f7fa ff56 bl 100092aa + +1000e3fe : +1000e3fe: 42a8 cmp r0, r5 +1000e400: d024 beq.n 1000e44c +1000e402: b108 cbz r0, 1000e408 +1000e404: 6aa0 ldr r0, [r4, #40] ; 0x28 +1000e406: 67f0 str r0, [r6, #124] ; 0x7c + +1000e408 : +1000e408: 7860 ldrb r0, [r4, #1] +1000e40a: 0680 lsls r0, r0, #26 +1000e40c: d519 bpl.n 1000e442 +1000e40e: 6ff0 ldr r0, [r6, #124] ; 0x7c +1000e410: b120 cbz r0, 1000e41c +1000e412: 7b41 ldrb r1, [r0, #13] +1000e414: f041 0120 orr.w r1, r1, #32 +1000e418: 7341 strb r1, [r0, #13] +1000e41a: e012 b.n 1000e442 + +1000e41c : +1000e41c: f640 3168 movw r1, #2920 ; 0xb68 +1000e420: 8e30 ldrh r0, [r6, #48] ; 0x30 +1000e422: 4288 cmp r0, r1 +1000e424: bf1c itt ne +1000e426: 1c40 addne r0, r0, #1 +1000e428: 8630 strhne r0, [r6, #48] ; 0x30 +1000e42a: f8d6 8084 ldr.w r8, [r6, #132] ; 0x84 +1000e42e: ea5f 0008 movs.w r0, r8 +1000e432: d006 beq.n 1000e442 +1000e434: 6930 ldr r0, [r6, #16] +1000e436: 2300 movs r3, #0 +1000e438: 2200 movs r2, #0 +1000e43a: 4631 mov r1, r6 +1000e43c: 47c0 blx r8 +1000e43e: 42a8 cmp r0, r5 +1000e440: d004 beq.n 1000e44c + +1000e442 : +1000e442: 2000 movs r0, #0 +1000e444: 62e0 str r0, [r4, #44] ; 0x2c +1000e446: 4630 mov r0, r6 +1000e448: f7fb fde1 bl 1000a00e + +1000e44c : +1000e44c: 2000 movs r0, #0 +1000e44e: 62e0 str r0, [r4, #44] ; 0x2c +1000e450: 62a0 str r0, [r4, #40] ; 0x28 +1000e452: 68a0 ldr r0, [r4, #8] +1000e454: b1d8 cbz r0, 1000e48e +1000e456: f7fa f9c7 bl 100087e8 +1000e45a: 2000 movs r0, #0 +1000e45c: 60a0 str r0, [r4, #8] +1000e45e: e016 b.n 1000e48e + +1000e460 : +1000e460: 69e0 ldr r0, [r4, #28] +1000e462: f000 fd73 bl 1000ef4c + +1000e466 : +1000e466: 0740 lsls r0, r0, #29 +1000e468: d40c bmi.n 1000e484 +1000e46a: 69e0 ldr r0, [r4, #28] +1000e46c: 8801 ldrh r1, [r0, #0] +1000e46e: 9101 str r1, [sp, #4] +1000e470: 464b mov r3, r9 +1000e472: 8840 ldrh r0, [r0, #2] +1000e474: 8b21 ldrh r1, [r4, #24] +1000e476: 9000 str r0, [sp, #0] +1000e478: 4642 mov r2, r8 +1000e47a: 6a20 ldr r0, [r4, #32] +1000e47c: 1809 adds r1, r1, r0 +1000e47e: 6a60 ldr r0, [r4, #36] ; 0x24 + +1000e480 : +1000e480: f7fb fed8 bl 1000a234 + +1000e484 : +1000e484: 4628 mov r0, r5 +1000e486: e8bd 43fe ldmia.w sp!, {r1, r2, r3, r4, r5, r6, r7, r8, r9, lr} +1000e48a: f7fa b9ad b.w 100087e8 + +1000e48e : +1000e48e: e8bd 83f7 ldmia.w sp!, {r0, r1, r2, r4, r5, r6, r7, r8, r9, pc} + +1000e492 : +1000e492: 0080 lsls r0, r0, #2 +1000e494: 4241 negs r1, r0 +1000e496: b209 sxth r1, r1 +1000e498: 4628 mov r0, r5 +1000e49a: f7fa b974 b.w 10008786 + +1000e49e : +1000e49e: e92d 41fc stmdb sp!, {r2, r3, r4, r5, r6, r7, r8, lr} +1000e4a2: f8df 6440 ldr.w r6, [pc, #1088] ; 1000e8e4 +1000e4a6: 4604 mov r4, r0 +1000e4a8: 7830 ldrb r0, [r6, #0] +1000e4aa: 0741 lsls r1, r0, #29 +1000e4ac: d40f bmi.n 1000e4ce +1000e4ae: f8df 7438 ldr.w r7, [pc, #1080] ; 1000e8e8 +1000e4b2: f8df 8a24 ldr.w r8, [pc, #2596] ; 1000eed8 +1000e4b6: 06c1 lsls r1, r0, #27 +1000e4b8: d50c bpl.n 1000e4d4 +1000e4ba: 69f0 ldr r0, [r6, #28] +1000e4bc: 8801 ldrh r1, [r0, #0] +1000e4be: 9101 str r1, [sp, #4] +1000e4c0: 4643 mov r3, r8 +1000e4c2: 8840 ldrh r0, [r0, #2] +1000e4c4: 8b31 ldrh r1, [r6, #24] +1000e4c6: 9000 str r0, [sp, #0] +1000e4c8: 463a mov r2, r7 +1000e4ca: f000 f9cd bl 1000e868 + +1000e4ce : +1000e4ce: 2000 movs r0, #0 + +1000e4d0 : +1000e4d0: e8bd 81f6 ldmia.w sp!, {r1, r2, r4, r5, r6, r7, r8, pc} + +1000e4d4 : +1000e4d4: 0780 lsls r0, r0, #30 +1000e4d6: d5fa bpl.n 1000e4ce +1000e4d8: 7f20 ldrb r0, [r4, #28] +1000e4da: f7fa fef7 bl 100092cc +1000e4de: 0005 movs r5, r0 +1000e4e0: bf08 it eq +1000e4e2: f04f 30ff moveq.w r0, #4294967295 +1000e4e6: d0f3 beq.n 1000e4d0 +1000e4e8: 6838 ldr r0, [r7, #0] +1000e4ea: 6028 str r0, [r5, #0] +1000e4ec: 8be0 ldrh r0, [r4, #30] +1000e4ee: 83e8 strh r0, [r5, #30] +1000e4f0: f8d8 0000 ldr.w r0, [r8] +1000e4f4: 6068 str r0, [r5, #4] +1000e4f6: 69f0 ldr r0, [r6, #28] +1000e4f8: 8801 ldrh r1, [r0, #0] +1000e4fa: 8429 strh r1, [r5, #32] +1000e4fc: 2103 movs r1, #3 +1000e4fe: 61a9 str r1, [r5, #24] +1000e500: 6a31 ldr r1, [r6, #32] +1000e502: 1c4a adds r2, r1, #1 +1000e504: 62ea str r2, [r5, #44] ; 0x2c +1000e506: 636a str r2, [r5, #52] ; 0x34 +1000e508: 89c2 ldrh r2, [r0, #14] +1000e50a: f8a5 2064 strh.w r2, [r5, #100] ; 0x64 +1000e50e: 89c0 ldrh r0, [r0, #14] +1000e510: f8a5 0066 strh.w r0, [r5, #102] ; 0x66 +1000e514: f8b5 0064 ldrh.w r0, [r5, #100] ; 0x64 +1000e518: f8a5 0052 strh.w r0, [r5, #82] ; 0x52 +1000e51c: 1e48 subs r0, r1, #1 +1000e51e: 65a8 str r0, [r5, #88] ; 0x58 +1000e520: 6920 ldr r0, [r4, #16] +1000e522: 6128 str r0, [r5, #16] +1000e524: 6960 ldr r0, [r4, #20] +1000e526: 6168 str r0, [r5, #20] +1000e528: 7a20 ldrb r0, [r4, #8] +1000e52a: f000 008c and.w r0, r0, #140 ; 0x8c +1000e52e: 7228 strb r0, [r5, #8] +1000e530: f8df 09a8 ldr.w r0, [pc, #2472] ; 1000eedc +1000e534: 6801 ldr r1, [r0, #0] +1000e536: 60e9 str r1, [r5, #12] +1000e538: 6005 str r5, [r0, #0] +1000e53a: f7fc ff68 bl 1000b40e +1000e53e: 2001 movs r0, #1 +1000e540: f8df 1a90 ldr.w r1, [pc, #2704] ; 1000efd4 +1000e544: 7008 strb r0, [r1, #0] +1000e546: 4628 mov r0, r5 +1000e548: f000 fd03 bl 1000ef52 +1000e54c: 8f68 ldrh r0, [r5, #58] ; 0x3a +1000e54e: 1d29 adds r1, r5, #4 +1000e550: f7fa ffb0 bl 100094b4 +1000e554: 8768 strh r0, [r5, #58] ; 0x3a +1000e556: 2112 movs r1, #18 +1000e558: 4628 mov r0, r5 +1000e55a: f7fb fce1 bl 10009f20 +1000e55e: 0004 movs r4, r0 +1000e560: d005 beq.n 1000e56e +1000e562: 2100 movs r1, #0 +1000e564: 4628 mov r0, r5 +1000e566: f7fa fb3c bl 10008be2 +1000e56a: 4620 mov r0, r4 +1000e56c: e7b0 b.n 1000e4d0 + +1000e56e : +1000e56e: 4628 mov r0, r5 +1000e570: e8bd 41f6 ldmia.w sp!, {r1, r2, r4, r5, r6, r7, r8, lr} +1000e574: f7fb bd4b b.w 1000a00e + +1000e578 : +1000e578: e92d 41fc stmdb sp!, {r2, r3, r4, r5, r6, r7, r8, lr} +1000e57c: f8df 6364 ldr.w r6, [pc, #868] ; 1000e8e4 +1000e580: 4604 mov r4, r0 +1000e582: 7830 ldrb r0, [r6, #0] +1000e584: 0741 lsls r1, r0, #29 +1000e586: d51f bpl.n 1000e5c8 +1000e588: 69a0 ldr r0, [r4, #24] +1000e58a: 2802 cmp r0, #2 +1000e58c: d105 bne.n 1000e59a +1000e58e: 6a70 ldr r0, [r6, #36] ; 0x24 +1000e590: 6d61 ldr r1, [r4, #84] ; 0x54 +1000e592: 4288 cmp r0, r1 +1000e594: f040 8163 bne.w 1000e85e +1000e598: e009 b.n 1000e5ae + +1000e59a : +1000e59a: 6a30 ldr r0, [r6, #32] +1000e59c: 6ae1 ldr r1, [r4, #44] ; 0x2c +1000e59e: 1a40 subs r0, r0, r1 +1000e5a0: f100 815d bmi.w 1000e85e +1000e5a4: 8e21 ldrh r1, [r4, #48] ; 0x30 +1000e5a6: 1a40 subs r0, r0, r1 +1000e5a8: 2801 cmp r0, #1 +1000e5aa: f280 8158 bge.w 1000e85e + +1000e5ae : +1000e5ae: 7870 ldrb r0, [r6, #1] +1000e5b0: f040 0008 orr.w r0, r0, #8 +1000e5b4: 7070 strb r0, [r6, #1] +1000e5b6: f894 0022 ldrb.w r0, [r4, #34] ; 0x22 +1000e5ba: f000 00fe and.w r0, r0, #254 ; 0xfe +1000e5be: f884 0022 strb.w r0, [r4, #34] ; 0x22 +1000e5c2: f06f 000a mvn.w r0, #10 +1000e5c6: e14b b.n 1000e860 + +1000e5c8 : +1000e5c8: 0780 lsls r0, r0, #30 +1000e5ca: d504 bpl.n 1000e5d6 +1000e5cc: 69a0 ldr r0, [r4, #24] +1000e5ce: 2802 cmp r0, #2 +1000e5d0: bf18 it ne +1000e5d2: 2803 cmpne r0, #3 +1000e5d4: d171 bne.n 1000e6ba + +1000e5d6 : +1000e5d6: f894 0022 ldrb.w r0, [r4, #34] ; 0x22 +1000e5da: 06c0 lsls r0, r0, #27 +1000e5dc: d403 bmi.n 1000e5e6 +1000e5de: f8df 09ec ldr.w r0, [pc, #2540] ; 1000efcc +1000e5e2: 6800 ldr r0, [r0, #0] +1000e5e4: 62a0 str r0, [r4, #40] ; 0x28 + +1000e5e6 : +1000e5e6: 2000 movs r0, #0 +1000e5e8: f884 009a strb.w r0, [r4, #154] ; 0x9a +1000e5ec: 4620 mov r0, r4 +1000e5ee: f000 fcb0 bl 1000ef52 +1000e5f2: 69a1 ldr r1, [r4, #24] +1000e5f4: 7830 ldrb r0, [r6, #0] +1000e5f6: f8df 79e0 ldr.w r7, [pc, #2528] ; 1000efd8 +1000e5fa: f8df 58e0 ldr.w r5, [pc, #2272] ; 1000eedc +1000e5fe: 1e89 subs r1, r1, #2 +1000e600: f06f 0809 mvn.w r8, #9 +1000e604: 2907 cmp r1, #7 +1000e606: d85e bhi.n 1000e6c6 +1000e608: e8df f011 tbh [pc, r1, lsl #1] + +1000e60c : +1000e60c: 0008 006d 00a8 00b5 00df 00a8 00f0 011c ..m............. + +1000e61c : +1000e61c: f000 0012 and.w r0, r0, #18 +1000e620: 2812 cmp r0, #18 +1000e622: d151 bne.n 1000e6c8 +1000e624: 6f60 ldr r0, [r4, #116] ; 0x74 +1000e626: f000 fc8b bl 1000ef40 + +1000e62a : +1000e62a: 6a71 ldr r1, [r6, #36] ; 0x24 +1000e62c: 1c40 adds r0, r0, #1 +1000e62e: 4281 cmp r1, r0 +1000e630: d14a bne.n 1000e6c8 +1000e632: f8b4 006a ldrh.w r0, [r4, #106] ; 0x6a +1000e636: 1c40 adds r0, r0, #1 +1000e638: f8a4 006a strh.w r0, [r4, #106] ; 0x6a +1000e63c: 6a30 ldr r0, [r6, #32] +1000e63e: 1c42 adds r2, r0, #1 +1000e640: 62e2 str r2, [r4, #44] ; 0x2c +1000e642: 6362 str r2, [r4, #52] ; 0x34 +1000e644: 64e1 str r1, [r4, #76] ; 0x4c +1000e646: 1e40 subs r0, r0, #1 +1000e648: 69f1 ldr r1, [r6, #28] +1000e64a: 89ca ldrh r2, [r1, #14] +1000e64c: f8a4 2064 strh.w r2, [r4, #100] ; 0x64 +1000e650: 89c9 ldrh r1, [r1, #14] +1000e652: f8a4 1066 strh.w r1, [r4, #102] ; 0x66 +1000e656: 65a0 str r0, [r4, #88] ; 0x58 +1000e658: 1d21 adds r1, r4, #4 +1000e65a: 2004 movs r0, #4 +1000e65c: 61a0 str r0, [r4, #24] +1000e65e: 8f60 ldrh r0, [r4, #58] ; 0x3a +1000e660: f7fa ff28 bl 100094b4 +1000e664: 8760 strh r0, [r4, #58] ; 0x3a +1000e666: 210a movs r1, #10 +1000e668: 4348 muls r0, r1 +1000e66a: f8a4 0052 strh.w r0, [r4, #82] ; 0x52 +1000e66e: f8b4 1050 ldrh.w r1, [r4, #80] ; 0x50 +1000e672: 8f60 ldrh r0, [r4, #58] ; 0x3a +1000e674: 2901 cmp r1, #1 +1000e676: bf08 it eq +1000e678: 0040 lsleq r0, r0, #1 +1000e67a: f8a4 0050 strh.w r0, [r4, #80] ; 0x50 +1000e67e: f8b4 006c ldrh.w r0, [r4, #108] ; 0x6c +1000e682: 1e40 subs r0, r0, #1 +1000e684: f8a4 006c strh.w r0, [r4, #108] ; 0x6c +1000e688: 6f60 ldr r0, [r4, #116] ; 0x74 +1000e68a: 6801 ldr r1, [r0, #0] +1000e68c: 6761 str r1, [r4, #116] ; 0x74 +1000e68e: f7fa fdec bl 1000926a +1000e692: 6f60 ldr r0, [r4, #116] ; 0x74 +1000e694: b918 cbnz r0, 1000e69e +1000e696: f04f 30ff mov.w r0, #4294967295 +1000e69a: 8720 strh r0, [r4, #56] ; 0x38 +1000e69c: e003 b.n 1000e6a6 + +1000e69e : +1000e69e: 2000 movs r0, #0 +1000e6a0: 8720 strh r0, [r4, #56] ; 0x38 +1000e6a2: f884 004a strb.w r0, [r4, #74] ; 0x4a + +1000e6a6 : +1000e6a6: f8d4 3088 ldr.w r3, [r4, #136] ; 0x88 +1000e6aa: 0018 movs r0, r3 +1000e6ac: d005 beq.n 1000e6ba +1000e6ae: 6920 ldr r0, [r4, #16] +1000e6b0: 2200 movs r2, #0 +1000e6b2: 4621 mov r1, r4 +1000e6b4: 4798 blx r3 +1000e6b6: 4540 cmp r0, r8 +1000e6b8: d02f beq.n 1000e71a + +1000e6ba : +1000e6ba: f894 0022 ldrb.w r0, [r4, #34] ; 0x22 +1000e6be: f040 0002 orr.w r0, r0, #2 +1000e6c2: f884 0022 strb.w r0, [r4, #34] ; 0x22 + +1000e6c6 : +1000e6c6: e0ca b.n 1000e85e + +1000e6c8 : +1000e6c8: 7830 ldrb r0, [r6, #0] +1000e6ca: 06c0 lsls r0, r0, #27 +1000e6cc: d5fb bpl.n 1000e6c6 + +1000e6ce : +1000e6ce: 69f0 ldr r0, [r6, #28] +1000e6d0: f8df 3804 ldr.w r3, [pc, #2052] ; 1000eed8 +1000e6d4: 8801 ldrh r1, [r0, #0] +1000e6d6: 4a84 ldr r2, [pc, #528] ; (1000e8e8 ) +1000e6d8: 9101 str r1, [sp, #4] +1000e6da: 8840 ldrh r0, [r0, #2] +1000e6dc: 8b31 ldrh r1, [r6, #24] +1000e6de: 9000 str r0, [sp, #0] +1000e6e0: f000 f8c2 bl 1000e868 + +1000e6e4 : +1000e6e4: e0bb b.n 1000e85e + +1000e6e6 : +1000e6e6: 06c1 lsls r1, r0, #27 +1000e6e8: d52d bpl.n 1000e746 +1000e6ea: 6a70 ldr r0, [r6, #36] ; 0x24 +1000e6ec: 6ce1 ldr r1, [r4, #76] ; 0x4c +1000e6ee: 1a41 subs r1, r0, r1 +1000e6f0: 1e49 subs r1, r1, #1 +1000e6f2: d4ec bmi.n 1000e6ce +1000e6f4: 6d61 ldr r1, [r4, #84] ; 0x54 +1000e6f6: 1a40 subs r0, r0, r1 +1000e6f8: 2801 cmp r0, #1 +1000e6fa: dae8 bge.n 1000e6ce +1000e6fc: 2004 movs r0, #4 +1000e6fe: 61a0 str r0, [r4, #24] +1000e700: 6963 ldr r3, [r4, #20] +1000e702: 0018 movs r0, r3 +1000e704: d006 beq.n 1000e714 +1000e706: 6920 ldr r0, [r4, #16] +1000e708: 2200 movs r2, #0 +1000e70a: 4621 mov r1, r4 +1000e70c: 4798 blx r3 +1000e70e: b130 cbz r0, 1000e71e +1000e710: 4540 cmp r0, r8 +1000e712: d002 beq.n 1000e71a + +1000e714 : +1000e714: 4620 mov r0, r4 +1000e716: f7fa fab1 bl 10008c7c + +1000e71a : +1000e71a: 4640 mov r0, r8 +1000e71c: e0a0 b.n 1000e860 + +1000e71e : +1000e71e: f8b4 5050 ldrh.w r5, [r4, #80] ; 0x50 +1000e722: f000 f89f bl 1000e864 + +1000e726 : +1000e726: f8b4 0068 ldrh.w r0, [r4, #104] ; 0x68 +1000e72a: b110 cbz r0, 1000e732 +1000e72c: 1e40 subs r0, r0, #1 +1000e72e: f8a4 0068 strh.w r0, [r4, #104] ; 0x68 + +1000e732 : +1000e732: 2d01 cmp r5, #1 +1000e734: 8f60 ldrh r0, [r4, #58] ; 0x3a +1000e736: bf08 it eq +1000e738: 0040 lsleq r0, r0, #1 +1000e73a: f8a4 0050 strh.w r0, [r4, #80] ; 0x50 +1000e73e: 7870 ldrb r0, [r6, #1] +1000e740: 0680 lsls r0, r0, #26 +1000e742: d410 bmi.n 1000e766 + +1000e744 : +1000e744: e08b b.n 1000e85e + +1000e746 : +1000e746: 0780 lsls r0, r0, #30 +1000e748: d5fc bpl.n 1000e744 +1000e74a: 6ae1 ldr r1, [r4, #44] ; 0x2c +1000e74c: 6a30 ldr r0, [r6, #32] +1000e74e: 1e49 subs r1, r1, #1 +1000e750: 4288 cmp r0, r1 +1000e752: d102 bne.n 1000e75a +1000e754: 4620 mov r0, r4 +1000e756: f7fb fdc6 bl 1000a2e6 + +1000e75a : +1000e75a: e080 b.n 1000e85e + +1000e75c : +1000e75c: f000 f882 bl 1000e864 + +1000e760 : +1000e760: 7870 ldrb r0, [r6, #1] +1000e762: 0680 lsls r0, r0, #26 +1000e764: d57b bpl.n 1000e85e + +1000e766 : +1000e766: f894 0022 ldrb.w r0, [r4, #34] ; 0x22 +1000e76a: f040 0002 orr.w r0, r0, #2 +1000e76e: f884 0022 strb.w r0, [r4, #34] ; 0x22 +1000e772: 2007 movs r0, #7 +1000e774: e027 b.n 1000e7c6 + +1000e776 : +1000e776: f000 f875 bl 1000e864 + +1000e77a : +1000e77a: 7831 ldrb r1, [r6, #0] +1000e77c: 7872 ldrb r2, [r6, #1] +1000e77e: 6a70 ldr r0, [r6, #36] ; 0x24 +1000e780: f001 0110 and.w r1, r1, #16 +1000e784: 0692 lsls r2, r2, #26 +1000e786: d518 bpl.n 1000e7ba +1000e788: b179 cbz r1, 1000e7aa +1000e78a: 6d61 ldr r1, [r4, #84] ; 0x54 +1000e78c: 4288 cmp r0, r1 +1000e78e: d10c bne.n 1000e7aa +1000e790: f000 f86f bl 1000e872 + +1000e794 : +1000e794: 6828 ldr r0, [r5, #0] +1000e796: 42a0 cmp r0, r4 +1000e798: d037 beq.n 1000e80a + +1000e79a : +1000e79a: 6038 str r0, [r7, #0] +1000e79c: 6838 ldr r0, [r7, #0] +1000e79e: 2800 cmp r0, #0 +1000e7a0: d040 beq.n 1000e824 +1000e7a2: 68c0 ldr r0, [r0, #12] +1000e7a4: 42a0 cmp r0, r4 +1000e7a6: d1f8 bne.n 1000e79a +1000e7a8: e039 b.n 1000e81e + +1000e7aa : +1000e7aa: f894 0022 ldrb.w r0, [r4, #34] ; 0x22 +1000e7ae: f040 0002 orr.w r0, r0, #2 +1000e7b2: f884 0022 strb.w r0, [r4, #34] ; 0x22 +1000e7b6: 2008 movs r0, #8 +1000e7b8: e005 b.n 1000e7c6 + +1000e7ba : +1000e7ba: 2900 cmp r1, #0 +1000e7bc: d04f beq.n 1000e85e +1000e7be: 6d61 ldr r1, [r4, #84] ; 0x54 +1000e7c0: 4288 cmp r0, r1 +1000e7c2: d14c bne.n 1000e85e +1000e7c4: 2006 movs r0, #6 + +1000e7c6 : +1000e7c6: 61a0 str r0, [r4, #24] +1000e7c8: e049 b.n 1000e85e + +1000e7ca : +1000e7ca: f000 f84b bl 1000e864 + +1000e7ce : +1000e7ce: 7870 ldrb r0, [r6, #1] +1000e7d0: 0680 lsls r0, r0, #26 +1000e7d2: d544 bpl.n 1000e85e +1000e7d4: f000 f84d bl 1000e872 + +1000e7d8 : +1000e7d8: 6828 ldr r0, [r5, #0] +1000e7da: 42a0 cmp r0, r4 +1000e7dc: d015 beq.n 1000e80a + +1000e7de : +1000e7de: 6038 str r0, [r7, #0] +1000e7e0: 6838 ldr r0, [r7, #0] +1000e7e2: b1f8 cbz r0, 1000e824 +1000e7e4: 68c0 ldr r0, [r0, #12] +1000e7e6: 42a0 cmp r0, r4 +1000e7e8: d1f9 bne.n 1000e7de +1000e7ea: e018 b.n 1000e81e + +1000e7ec : +1000e7ec: f000 f83a bl 1000e864 + +1000e7f0 : +1000e7f0: 7830 ldrb r0, [r6, #0] +1000e7f2: 06c0 lsls r0, r0, #27 +1000e7f4: d533 bpl.n 1000e85e +1000e7f6: 6a70 ldr r0, [r6, #36] ; 0x24 +1000e7f8: 6d61 ldr r1, [r4, #84] ; 0x54 +1000e7fa: 4288 cmp r0, r1 +1000e7fc: d12f bne.n 1000e85e +1000e7fe: 4620 mov r0, r4 +1000e800: f7fa fdf4 bl 100093ec +1000e804: 6828 ldr r0, [r5, #0] +1000e806: 42a0 cmp r0, r4 +1000e808: d103 bne.n 1000e812 + +1000e80a : +1000e80a: 6828 ldr r0, [r5, #0] +1000e80c: 68c0 ldr r0, [r0, #12] +1000e80e: 6028 str r0, [r5, #0] +1000e810: e008 b.n 1000e824 + +1000e812 : +1000e812: 6038 str r0, [r7, #0] +1000e814: 6838 ldr r0, [r7, #0] +1000e816: b128 cbz r0, 1000e824 +1000e818: 68c0 ldr r0, [r0, #12] +1000e81a: 42a0 cmp r0, r4 +1000e81c: d1f9 bne.n 1000e812 + +1000e81e : +1000e81e: 6839 ldr r1, [r7, #0] +1000e820: 68e0 ldr r0, [r4, #12] +1000e822: 60c8 str r0, [r1, #12] + +1000e824 : +1000e824: 2000 movs r0, #0 +1000e826: 60e0 str r0, [r4, #12] +1000e828: 2001 movs r0, #1 +1000e82a: f8df 17a8 ldr.w r1, [pc, #1960] ; 1000efd4 +1000e82e: 7008 strb r0, [r1, #0] +1000e830: 200a movs r0, #10 +1000e832: 61a0 str r0, [r4, #24] +1000e834: f8df 0790 ldr.w r0, [pc, #1936] ; 1000efc8 +1000e838: 6801 ldr r1, [r0, #0] +1000e83a: 60e1 str r1, [r4, #12] +1000e83c: 6004 str r4, [r0, #0] +1000e83e: f7fc fde6 bl 1000b40e +1000e842: e00c b.n 1000e85e + +1000e844 : +1000e844: f000 f80e bl 1000e864 + +1000e848 : +1000e848: 7830 ldrb r0, [r6, #0] +1000e84a: 06c0 lsls r0, r0, #27 +1000e84c: d507 bpl.n 1000e85e +1000e84e: 6a70 ldr r0, [r6, #36] ; 0x24 +1000e850: 6d61 ldr r1, [r4, #84] ; 0x54 +1000e852: 4288 cmp r0, r1 +1000e854: d103 bne.n 1000e85e +1000e856: 7870 ldrb r0, [r6, #1] +1000e858: f040 0010 orr.w r0, r0, #16 +1000e85c: 7070 strb r0, [r6, #1] + +1000e85e : +1000e85e: 2000 movs r0, #0 + +1000e860 : +1000e860: e8bd 81f6 ldmia.w sp!, {r1, r2, r4, r5, r6, r7, r8, pc} + +1000e864 : +1000e864: 4620 mov r0, r4 +1000e866: e041 b.n 1000e8ec + +1000e868 : +1000e868: 6a30 ldr r0, [r6, #32] +1000e86a: 1809 adds r1, r1, r0 +1000e86c: 6a70 ldr r0, [r6, #36] ; 0x24 +1000e86e: f7fb bce1 b.w 1000a234 + +1000e872 : +1000e872: f894 0022 ldrb.w r0, [r4, #34] ; 0x22 +1000e876: f040 0002 orr.w r0, r0, #2 +1000e87a: f884 0022 strb.w r0, [r4, #34] ; 0x22 +1000e87e: 4620 mov r0, r4 +1000e880: f7fa bdb4 b.w 100093ec + +1000e884 : +1000e884: b570 push {r4, r5, r6, lr} +1000e886: 4604 mov r4, r0 +1000e888: 460d mov r5, r1 +1000e88a: 6920 ldr r0, [r4, #16] +1000e88c: f000 fb5e bl 1000ef4c + +1000e890 : +1000e890: 07c0 lsls r0, r0, #31 +1000e892: d513 bpl.n 1000e8bc +1000e894: 4628 mov r0, r5 +1000e896: f7fa fcdf bl 10009258 +1000e89a: 2500 movs r5, #0 +1000e89c: e020 b.n 1000e8e0 + +1000e89e : +1000e89e: f000 fb55 bl 1000ef4c + +1000e8a2 : +1000e8a2: 07c0 lsls r0, r0, #31 +1000e8a4: d506 bpl.n 1000e8b4 +1000e8a6: 2001 movs r0, #1 +1000e8a8: f7fd fe4d bl 1000c546 +1000e8ac: 6921 ldr r1, [r4, #16] +1000e8ae: 898a ldrh r2, [r1, #12] +1000e8b0: 4310 orrs r0, r2 +1000e8b2: 8188 strh r0, [r1, #12] + +1000e8b4 : +1000e8b4: 4628 mov r0, r5 +1000e8b6: 682d ldr r5, [r5, #0] +1000e8b8: f7fa fcd7 bl 1000926a + +1000e8bc : +1000e8bc: b185 cbz r5, 1000e8e0 +1000e8be: 4809 ldr r0, [pc, #36] ; (1000e8e4 ) +1000e8c0: 6a01 ldr r1, [r0, #32] +1000e8c2: 8920 ldrh r0, [r4, #8] +1000e8c4: 892e ldrh r6, [r5, #8] +1000e8c6: 1842 adds r2, r0, r1 +1000e8c8: 6928 ldr r0, [r5, #16] +1000e8ca: 6843 ldr r3, [r0, #4] +1000e8cc: 1ad3 subs r3, r2, r3 +1000e8ce: 1b9b subs r3, r3, r6 +1000e8d0: d5e5 bpl.n 1000e89e +1000e8d2: 6840 ldr r0, [r0, #4] +1000e8d4: 1a12 subs r2, r2, r0 +1000e8d6: 2a01 cmp r2, #1 +1000e8d8: db02 blt.n 1000e8e0 +1000e8da: 1a41 subs r1, r0, r1 +1000e8dc: f000 fb15 bl 1000ef0a + +1000e8e0 : +1000e8e0: 6025 str r5, [r4, #0] +1000e8e2: bd70 pop {r4, r5, r6, pc} + +1000e8e4 : +1000e8e4: 7ad0 1004 .z.. + +1000e8e8 : +1000e8e8: 7708 1004 .w.. + +1000e8ec : +1000e8ec: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +1000e8f0: f8df 76e8 ldr.w r7, [pc, #1768] ; 1000efdc +1000e8f4: 4680 mov r8, r0 +1000e8f6: 7838 ldrb r0, [r7, #0] +1000e8f8: f108 0518 add.w r5, r8, #24 +1000e8fc: f108 064c add.w r6, r8, #76 ; 0x4c +1000e900: 06c0 lsls r0, r0, #27 +1000e902: f140 8115 bpl.w 1000eb30 +1000e906: 6933 ldr r3, [r6, #16] +1000e908: 8b32 ldrh r2, [r6, #24] +1000e90a: 68f4 ldr r4, [r6, #12] +1000e90c: 6a39 ldr r1, [r7, #32] +1000e90e: 1898 adds r0, r3, r2 +1000e910: ebb4 0e01 subs.w lr, r4, r1 +1000e914: d40a bmi.n 1000e92c +1000e916: d102 bne.n 1000e91e +1000e918: 6a7c ldr r4, [r7, #36] ; 0x24 +1000e91a: 1b1c subs r4, r3, r4 +1000e91c: d406 bmi.n 1000e92c + +1000e91e : +1000e91e: 6a7c ldr r4, [r7, #36] ; 0x24 +1000e920: 42a3 cmp r3, r4 +1000e922: d11a bne.n 1000e95a +1000e924: 69fb ldr r3, [r7, #28] +1000e926: 89db ldrh r3, [r3, #14] +1000e928: 429a cmp r2, r3 +1000e92a: d216 bcs.n 1000e95a + +1000e92c : +1000e92c: 69fa ldr r2, [r7, #28] +1000e92e: 89d3 ldrh r3, [r2, #14] +1000e930: 8333 strh r3, [r6, #24] +1000e932: 89d2 ldrh r2, [r2, #14] +1000e934: 8b74 ldrh r4, [r6, #26] +1000e936: 4294 cmp r4, r2 +1000e938: bf38 it cc +1000e93a: 8372 strhcc r2, [r6, #26] +1000e93c: 60f1 str r1, [r6, #12] +1000e93e: 6a79 ldr r1, [r7, #36] ; 0x24 +1000e940: 6131 str r1, [r6, #16] +1000e942: f108 0198 add.w r1, r8, #152 ; 0x98 +1000e946: 784a ldrb r2, [r1, #1] +1000e948: b923 cbnz r3, 1000e954 +1000e94a: b932 cbnz r2, 1000e95a +1000e94c: f888 2098 strb.w r2, [r8, #152] ; 0x98 +1000e950: 2201 movs r2, #1 +1000e952: e001 b.n 1000e958 + +1000e954 : +1000e954: b10a cbz r2, 1000e95a +1000e956: 2200 movs r2, #0 + +1000e958 : +1000e958: 704a strb r2, [r1, #1] + +1000e95a : +1000e95a: f8d8 304c ldr.w r3, [r8, #76] ; 0x4c +1000e95e: 6a7a ldr r2, [r7, #36] ; 0x24 +1000e960: 1ad4 subs r4, r2, r3 +1000e962: f108 014a add.w r1, r8, #74 ; 0x4a +1000e966: 2c01 cmp r4, #1 +1000e968: da2b bge.n 1000e9c2 +1000e96a: 2400 movs r4, #0 +1000e96c: 83b4 strh r4, [r6, #28] +1000e96e: 8b3c ldrh r4, [r7, #24] +1000e970: 2c00 cmp r4, #0 +1000e972: bf01 itttt eq +1000e974: f8d6 c010 ldreq.w ip, [r6, #16] +1000e978: f8b6 e018 ldrheq.w lr, [r6, #24] +1000e97c: 44f4 addeq ip, lr +1000e97e: 4584 cmpeq ip, r0 +1000e980: d11c bne.n 1000e9bc +1000e982: f9b5 0020 ldrsh.w r0, [r5, #32] +1000e986: 2800 cmp r0, #0 +1000e988: d418 bmi.n 1000e9bc +1000e98a: 4293 cmp r3, r2 +1000e98c: d116 bne.n 1000e9bc +1000e98e: 7848 ldrb r0, [r1, #1] +1000e990: 1c42 adds r2, r0, #1 +1000e992: b2d2 uxtb r2, r2 +1000e994: 4290 cmp r0, r2 +1000e996: bf38 it cc +1000e998: 704a strbcc r2, [r1, #1] +1000e99a: 7848 ldrb r0, [r1, #1] +1000e99c: 2804 cmp r0, #4 +1000e99e: db07 blt.n 1000e9b0 +1000e9a0: 88b0 ldrh r0, [r6, #4] +1000e9a2: 8c69 ldrh r1, [r5, #34] ; 0x22 +1000e9a4: 1809 adds r1, r1, r0 +1000e9a6: b289 uxth r1, r1 +1000e9a8: 4288 cmp r0, r1 +1000e9aa: d200 bcs.n 1000e9ae +1000e9ac: 80b1 strh r1, [r6, #4] + +1000e9ae : +1000e9ae: e084 b.n 1000eaba + +1000e9b0 : +1000e9b0: 2803 cmp r0, #3 +1000e9b2: d1fc bne.n 1000e9ae +1000e9b4: 4640 mov r0, r8 +1000e9b6: f7fb fcc0 bl 1000a33a +1000e9ba: e07e b.n 1000eaba + +1000e9bc : +1000e9bc: 2000 movs r0, #0 +1000e9be: 7048 strb r0, [r1, #1] +1000e9c0: e07b b.n 1000eaba + +1000e9c2 : +1000e9c2: d466 bmi.n 1000ea92 +1000e9c4: 68b0 ldr r0, [r6, #8] +1000e9c6: 1a10 subs r0, r2, r0 +1000e9c8: 2801 cmp r0, #1 +1000e9ca: da62 bge.n 1000ea92 +1000e9cc: 7aa8 ldrb r0, [r5, #10] +1000e9ce: 0743 lsls r3, r0, #29 +1000e9d0: d504 bpl.n 1000e9dc +1000e9d2: f000 00fb and.w r0, r0, #251 ; 0xfb +1000e9d6: 72a8 strb r0, [r5, #10] +1000e9d8: 88f0 ldrh r0, [r6, #6] +1000e9da: 80b0 strh r0, [r6, #4] + +1000e9dc : +1000e9dc: 2000 movs r0, #0 +1000e9de: f888 004a strb.w r0, [r8, #74] ; 0x4a +1000e9e2: f9b5 302e ldrsh.w r3, [r5, #46] ; 0x2e +1000e9e6: f9b5 002c ldrsh.w r0, [r5, #44] ; 0x2c +1000e9ea: eb03 00e0 add.w r0, r3, r0, asr #3 +1000e9ee: 8628 strh r0, [r5, #48] ; 0x30 +1000e9f0: f8d8 004c ldr.w r0, [r8, #76] ; 0x4c +1000e9f4: 1a10 subs r0, r2, r0 +1000e9f6: 83b0 strh r0, [r6, #28] +1000e9f8: 8bf3 ldrh r3, [r6, #30] +1000e9fa: 18c0 adds r0, r0, r3 +1000e9fc: 83f0 strh r0, [r6, #30] +1000e9fe: 2000 movs r0, #0 +1000ea00: 7048 strb r0, [r1, #1] +1000ea02: f8c8 204c str.w r2, [r8, #76] ; 0x4c +1000ea06: f8d8 0018 ldr.w r0, [r8, #24] +1000ea0a: 2804 cmp r0, #4 +1000ea0c: db23 blt.n 1000ea56 +1000ea0e: 88b0 ldrh r0, [r6, #4] +1000ea10: 88f1 ldrh r1, [r6, #6] +1000ea12: 4288 cmp r0, r1 +1000ea14: 8c69 ldrh r1, [r5, #34] ; 0x22 +1000ea16: d205 bcs.n 1000ea24 +1000ea18: 1809 adds r1, r1, r0 +1000ea1a: b289 uxth r1, r1 +1000ea1c: 4288 cmp r0, r1 +1000ea1e: d21a bcs.n 1000ea56 +1000ea20: 80b1 strh r1, [r6, #4] +1000ea22: e018 b.n 1000ea56 + +1000ea24 : +1000ea24: 4349 muls r1, r1 +1000ea26: fb91 f1f0 sdiv r1, r1, r0 +1000ea2a: 1809 adds r1, r1, r0 +1000ea2c: b289 uxth r1, r1 +1000ea2e: 4288 cmp r0, r1 +1000ea30: bf38 it cc +1000ea32: 4608 movcc r0, r1 +1000ea34: 80b0 strh r0, [r6, #4] +1000ea36: e00e b.n 1000ea56 + +1000ea38 : +1000ea38: 6820 ldr r0, [r4, #0] +1000ea3a: 62b0 str r0, [r6, #40] ; 0x28 +1000ea3c: f000 fa62 bl 1000ef04 + +1000ea40 : +1000ea40: 8bb0 ldrh r0, [r6, #28] +1000ea42: b120 cbz r0, 1000ea4e +1000ea44: 6920 ldr r0, [r4, #16] +1000ea46: f000 fa81 bl 1000ef4c + +1000ea4a : +1000ea4a: f000 fa50 bl 1000eeee + +1000ea4e : +1000ea4e: f000 fa59 bl 1000ef04 + +1000ea52 : +1000ea52: f000 fa66 bl 1000ef22 + +1000ea56 : +1000ea56: 6ab0 ldr r0, [r6, #40] ; 0x28 +1000ea58: b198 cbz r0, 1000ea82 +1000ea5a: f000 fa71 bl 1000ef40 + +1000ea5e : +1000ea5e: 4681 mov r9, r0 +1000ea60: 6ab0 ldr r0, [r6, #40] ; 0x28 +1000ea62: 6900 ldr r0, [r0, #16] +1000ea64: f000 fa72 bl 1000ef4c + +1000ea68 : +1000ea68: f010 0003 ands.w r0, r0, #3 +1000ea6c: bf18 it ne +1000ea6e: 2001 movne r0, #1 +1000ea70: 6ab4 ldr r4, [r6, #40] ; 0x28 +1000ea72: 8921 ldrh r1, [r4, #8] +1000ea74: 1840 adds r0, r0, r1 +1000ea76: 6a79 ldr r1, [r7, #36] ; 0x24 +1000ea78: 4448 add r0, r9 +1000ea7a: 1a40 subs r0, r0, r1 +1000ea7c: 2801 cmp r0, #1 +1000ea7e: dbdb blt.n 1000ea38 +1000ea80: b914 cbnz r4, 1000ea88 + +1000ea82 : +1000ea82: f04f 30ff mov.w r0, #4294967295 +1000ea86: e000 b.n 1000ea8a + +1000ea88 : +1000ea88: 2000 movs r0, #0 + +1000ea8a : +1000ea8a: 8428 strh r0, [r5, #32] +1000ea8c: 2000 movs r0, #0 +1000ea8e: 72e8 strb r0, [r5, #11] +1000ea90: e013 b.n 1000eaba + +1000ea92 : +1000ea92: 2000 movs r0, #0 +1000ea94: 83b0 strh r0, [r6, #28] +1000ea96: e010 b.n 1000eaba + +1000ea98 : +1000ea98: 6820 ldr r0, [r4, #0] +1000ea9a: 6270 str r0, [r6, #36] ; 0x24 +1000ea9c: b900 cbnz r0, 1000eaa0 +1000ea9e: 8470 strh r0, [r6, #34] ; 0x22 + +1000eaa0 : +1000eaa0: f000 fa30 bl 1000ef04 + +1000eaa4 : +1000eaa4: 8bb0 ldrh r0, [r6, #28] +1000eaa6: b120 cbz r0, 1000eab2 +1000eaa8: 6920 ldr r0, [r4, #16] +1000eaaa: f000 fa4f bl 1000ef4c + +1000eaae : +1000eaae: f000 fa1e bl 1000eeee + +1000eab2 : +1000eab2: f000 fa27 bl 1000ef04 + +1000eab6 : +1000eab6: f000 fa34 bl 1000ef22 + +1000eaba : +1000eaba: 6a70 ldr r0, [r6, #36] ; 0x24 +1000eabc: b1b0 cbz r0, 1000eaec +1000eabe: f000 fa3f bl 1000ef40 + +1000eac2 : +1000eac2: 4681 mov r9, r0 +1000eac4: 6a70 ldr r0, [r6, #36] ; 0x24 +1000eac6: 6900 ldr r0, [r0, #16] +1000eac8: f000 fa40 bl 1000ef4c + +1000eacc : +1000eacc: f010 0003 ands.w r0, r0, #3 +1000ead0: bf18 it ne +1000ead2: 2001 movne r0, #1 +1000ead4: 6a74 ldr r4, [r6, #36] ; 0x24 +1000ead6: 6a79 ldr r1, [r7, #36] ; 0x24 +1000ead8: 8923 ldrh r3, [r4, #8] +1000eada: eba1 0209 sub.w r2, r1, r9 +1000eade: 1ad2 subs r2, r2, r3 +1000eae0: 1a10 subs r0, r2, r0 +1000eae2: d403 bmi.n 1000eaec +1000eae4: 68b0 ldr r0, [r6, #8] +1000eae6: 1a08 subs r0, r1, r0 +1000eae8: 2801 cmp r0, #1 +1000eaea: dbd5 blt.n 1000ea98 + +1000eaec : +1000eaec: 6a68 ldr r0, [r5, #36] ; 0x24 +1000eaee: b1f8 cbz r0, 1000eb30 +1000eaf0: 6aa9 ldr r1, [r5, #40] ; 0x28 +1000eaf2: 6a7a ldr r2, [r7, #36] ; 0x24 +1000eaf4: 1a89 subs r1, r1, r2 +1000eaf6: d51b bpl.n 1000eb30 +1000eaf8: f8df 24d0 ldr.w r2, [pc, #1232] ; 1000efcc +1000eafc: f9b5 102c ldrsh.w r1, [r5, #44] ; 0x2c +1000eb00: 6812 ldr r2, [r2, #0] +1000eb02: 1a10 subs r0, r2, r0 +1000eb04: b200 sxth r0, r0 +1000eb06: eba0 00e1 sub.w r0, r0, r1, asr #3 +1000eb0a: 1841 adds r1, r0, r1 +1000eb0c: b202 sxth r2, r0 +1000eb0e: 85a9 strh r1, [r5, #44] ; 0x2c +1000eb10: 2a00 cmp r2, #0 +1000eb12: bf48 it mi +1000eb14: 4240 negmi r0, r0 +1000eb16: f9b5 202e ldrsh.w r2, [r5, #46] ; 0x2e +1000eb1a: 1880 adds r0, r0, r2 +1000eb1c: eba0 00a2 sub.w r0, r0, r2, asr #2 +1000eb20: 85e8 strh r0, [r5, #46] ; 0x2e +1000eb22: b209 sxth r1, r1 +1000eb24: b200 sxth r0, r0 +1000eb26: eb00 00e1 add.w r0, r0, r1, asr #3 +1000eb2a: 8628 strh r0, [r5, #48] ; 0x30 +1000eb2c: 2000 movs r0, #0 +1000eb2e: 6268 str r0, [r5, #36] ; 0x24 + +1000eb30 : +1000eb30: 8b38 ldrh r0, [r7, #24] +1000eb32: 2800 cmp r0, #0 +1000eb34: f000 81c0 beq.w 1000eeb8 +1000eb38: f8d8 1018 ldr.w r1, [r8, #24] +1000eb3c: 2907 cmp r1, #7 +1000eb3e: f280 81bb bge.w 1000eeb8 +1000eb42: 696a ldr r2, [r5, #20] +1000eb44: 6a3b ldr r3, [r7, #32] +1000eb46: 1ad1 subs r1, r2, r3 +1000eb48: 1e4c subs r4, r1, #1 +1000eb4a: d421 bmi.n 1000eb90 +1000eb4c: 1a08 subs r0, r1, r0 +1000eb4e: 1c40 adds r0, r0, #1 +1000eb50: 2801 cmp r0, #1 +1000eb52: da1d bge.n 1000eb90 +1000eb54: 68ba ldr r2, [r7, #8] +1000eb56: 8953 ldrh r3, [r2, #10] +1000eb58: 4610 mov r0, r2 +1000eb5a: 428b cmp r3, r1 +1000eb5c: da0a bge.n 1000eb74 +1000eb5e: 8912 ldrh r2, [r2, #8] +1000eb60: 1a52 subs r2, r2, r1 +1000eb62: e004 b.n 1000eb6e + +1000eb64 : +1000eb64: 1ac9 subs r1, r1, r3 +1000eb66: 8102 strh r2, [r0, #8] +1000eb68: 2300 movs r3, #0 +1000eb6a: 8143 strh r3, [r0, #10] +1000eb6c: 6800 ldr r0, [r0, #0] + +1000eb6e : +1000eb6e: 8943 ldrh r3, [r0, #10] +1000eb70: 428b cmp r3, r1 +1000eb72: dbf7 blt.n 1000eb64 + +1000eb74 : +1000eb74: 4249 negs r1, r1 +1000eb76: b209 sxth r1, r1 +1000eb78: f7f9 fe05 bl 10008786 +1000eb7c: 6968 ldr r0, [r5, #20] +1000eb7e: 89b9 ldrh r1, [r7, #12] +1000eb80: 6a3a ldr r2, [r7, #32] +1000eb82: 6238 str r0, [r7, #32] +1000eb84: 1a09 subs r1, r1, r0 +1000eb86: 1851 adds r1, r2, r1 +1000eb88: 81b9 strh r1, [r7, #12] +1000eb8a: 6979 ldr r1, [r7, #20] +1000eb8c: 6048 str r0, [r1, #4] +1000eb8e: e005 b.n 1000eb9c + +1000eb90 : +1000eb90: 1a98 subs r0, r3, r2 +1000eb92: d503 bpl.n 1000eb9c +1000eb94: 7aa8 ldrb r0, [r5, #10] +1000eb96: f040 0002 orr.w r0, r0, #2 +1000eb9a: 72a8 strb r0, [r5, #10] + +1000eb9c : +1000eb9c: 6968 ldr r0, [r5, #20] +1000eb9e: 6a39 ldr r1, [r7, #32] +1000eba0: 1a0a subs r2, r1, r0 +1000eba2: f100 8184 bmi.w 1000eeae +1000eba6: 8b2b ldrh r3, [r5, #24] +1000eba8: 1ad2 subs r2, r2, r3 +1000ebaa: 1c52 adds r2, r2, #1 +1000ebac: 2a01 cmp r2, #1 +1000ebae: f280 817e bge.w 1000eeae +1000ebb2: 4288 cmp r0, r1 +1000ebb4: f040 80d6 bne.w 1000ed64 +1000ebb8: f000 f9c7 bl 1000ef4a + +1000ebbc : +1000ebbc: f010 0003 ands.w r0, r0, #3 +1000ebc0: bf18 it ne +1000ebc2: 2001 movne r0, #1 +1000ebc4: f000 f98c bl 1000eee0 + +1000ebc8 : +1000ebc8: b280 uxth r0, r0 +1000ebca: 8b29 ldrh r1, [r5, #24] +1000ebcc: 4281 cmp r1, r0 +1000ebce: d219 bcs.n 1000ec04 +1000ebd0: f000 f9bb bl 1000ef4a + +1000ebd4 : +1000ebd4: 07c0 lsls r0, r0, #31 +1000ebd6: d508 bpl.n 1000ebea +1000ebd8: f000 f9b7 bl 1000ef4a + +1000ebdc : +1000ebdc: f000 003e and.w r0, r0, #62 ; 0x3e +1000ebe0: f7fd fcb1 bl 1000c546 +1000ebe4: 6979 ldr r1, [r7, #20] +1000ebe6: f000 f995 bl 1000ef14 + +1000ebea : +1000ebea: 8b28 ldrh r0, [r5, #24] +1000ebec: f000 f9ac bl 1000ef48 + +1000ebf0 : +1000ebf0: f000 f99d bl 1000ef2e + +1000ebf4 : +1000ebf4: f000 f9a9 bl 1000ef4a + +1000ebf8 : +1000ebf8: f010 0003 ands.w r0, r0, #3 +1000ebfc: bf18 it ne +1000ebfe: 2001 movne r0, #1 +1000ec00: f000 f96e bl 1000eee0 + +1000ec04 : +1000ec04: 6af0 ldr r0, [r6, #44] ; 0x2c +1000ec06: 2800 cmp r0, #0 +1000ec08: d047 beq.n 1000ec9a +1000ec0a: f000 f99e bl 1000ef4a + +1000ec0e : +1000ec0e: 07c0 lsls r0, r0, #31 +1000ec10: d507 bpl.n 1000ec22 + +1000ec12 : +1000ec12: 6af0 ldr r0, [r6, #44] ; 0x2c +1000ec14: 2800 cmp r0, #0 +1000ec16: d040 beq.n 1000ec9a +1000ec18: 6801 ldr r1, [r0, #0] +1000ec1a: 62f1 str r1, [r6, #44] ; 0x2c +1000ec1c: f7fa fb25 bl 1000926a +1000ec20: e7f7 b.n 1000ec12 + +1000ec22 : +1000ec22: 6af4 ldr r4, [r6, #44] ; 0x2c +1000ec24: e01b b.n 1000ec5e + +1000ec26 : +1000ec26: 8988 ldrh r0, [r1, #12] +1000ec28: f7fd fc92 bl 1000c550 +1000ec2c: 07c0 lsls r0, r0, #31 +1000ec2e: d512 bpl.n 1000ec56 +1000ec30: f000 f98b bl 1000ef4a + +1000ec34 : +1000ec34: 0780 lsls r0, r0, #30 +1000ec36: d40e bmi.n 1000ec56 +1000ec38: 2001 movs r0, #1 +1000ec3a: f7fd fc84 bl 1000c546 +1000ec3e: 6979 ldr r1, [r7, #20] +1000ec40: 898a ldrh r2, [r1, #12] +1000ec42: 4310 orrs r0, r2 +1000ec44: 8188 strh r0, [r1, #12] +1000ec46: f7fd fc83 bl 1000c550 +1000ec4a: f010 0003 ands.w r0, r0, #3 +1000ec4e: bf18 it ne +1000ec50: 2001 movne r0, #1 +1000ec52: f000 f945 bl 1000eee0 + +1000ec56 : +1000ec56: 4620 mov r0, r4 +1000ec58: 6824 ldr r4, [r4, #0] +1000ec5a: f7fa fb06 bl 1000926a + +1000ec5e : +1000ec5e: b1dc cbz r4, 1000ec98 +1000ec60: 6a38 ldr r0, [r7, #32] +1000ec62: 8b39 ldrh r1, [r7, #24] +1000ec64: f8b4 c008 ldrh.w ip, [r4, #8] +1000ec68: 180a adds r2, r1, r0 +1000ec6a: 6921 ldr r1, [r4, #16] +1000ec6c: 684b ldr r3, [r1, #4] +1000ec6e: 1ad3 subs r3, r2, r3 +1000ec70: ebb3 030c subs.w r3, r3, ip +1000ec74: d5d7 bpl.n 1000ec26 +1000ec76: 6849 ldr r1, [r1, #4] +1000ec78: 1a52 subs r2, r2, r1 +1000ec7a: 2a01 cmp r2, #1 +1000ec7c: db0c blt.n 1000ec98 +1000ec7e: 1a08 subs r0, r1, r0 +1000ec80: f000 f962 bl 1000ef48 + +1000ec84 : +1000ec84: f000 f953 bl 1000ef2e + +1000ec88 : +1000ec88: f000 f95f bl 1000ef4a + +1000ec8c : +1000ec8c: f010 0003 ands.w r0, r0, #3 +1000ec90: bf18 it ne +1000ec92: 2001 movne r0, #1 +1000ec94: f000 f924 bl 1000eee0 + +1000ec98 : +1000ec98: 62f4 str r4, [r6, #44] ; 0x2c + +1000ec9a : +1000ec9a: 8b38 ldrh r0, [r7, #24] +1000ec9c: 6a39 ldr r1, [r7, #32] +1000ec9e: 1841 adds r1, r0, r1 +1000eca0: 6169 str r1, [r5, #20] +1000eca2: 8b29 ldrh r1, [r5, #24] +1000eca4: f000 f929 bl 1000eefa + +1000eca8 : +1000eca8: 68b8 ldr r0, [r7, #8] +1000ecaa: 8901 ldrh r1, [r0, #8] +1000ecac: b111 cbz r1, 1000ecb4 +1000ecae: 62b8 str r0, [r7, #40] ; 0x28 +1000ecb0: 2000 movs r0, #0 +1000ecb2: 60b8 str r0, [r7, #8] + +1000ecb4 : +1000ecb4: f000 f949 bl 1000ef4a + +1000ecb8 : +1000ecb8: 07c0 lsls r0, r0, #31 +1000ecba: d51b bpl.n 1000ecf4 +1000ecbc: 7878 ldrb r0, [r7, #1] +1000ecbe: f040 0020 orr.w r0, r0, #32 +1000ecc2: 7078 strb r0, [r7, #1] +1000ecc4: e016 b.n 1000ecf4 + +1000ecc6 : +1000ecc6: 62b9 str r1, [r7, #40] ; 0x28 + +1000ecc8 : +1000ecc8: 2000 movs r0, #0 +1000ecca: 6060 str r0, [r4, #4] + +1000eccc : +1000eccc: 6920 ldr r0, [r4, #16] +1000ecce: f000 f93d bl 1000ef4c + +1000ecd2 : +1000ecd2: 07c0 lsls r0, r0, #31 +1000ecd4: d50a bpl.n 1000ecec +1000ecd6: 7878 ldrb r0, [r7, #1] +1000ecd8: f040 0020 orr.w r0, r0, #32 +1000ecdc: 7078 strb r0, [r7, #1] +1000ecde: f8d8 0018 ldr.w r0, [r8, #24] +1000ece2: 2804 cmp r0, #4 +1000ece4: bf04 itt eq +1000ece6: 2007 moveq r0, #7 +1000ece8: f8c8 0018 streq.w r0, [r8, #24] + +1000ecec : +1000ecec: 6820 ldr r0, [r4, #0] +1000ecee: 62f0 str r0, [r6, #44] ; 0x2c +1000ecf0: f000 f91a bl 1000ef28 + +1000ecf4 : +1000ecf4: 6af4 ldr r4, [r6, #44] ; 0x2c +1000ecf6: 2c00 cmp r4, #0 +1000ecf8: d02a beq.n 1000ed50 +1000ecfa: 6920 ldr r0, [r4, #16] +1000ecfc: 6969 ldr r1, [r5, #20] +1000ecfe: 6840 ldr r0, [r0, #4] +1000ed00: 4288 cmp r0, r1 +1000ed02: d125 bne.n 1000ed50 +1000ed04: 6238 str r0, [r7, #32] +1000ed06: 6920 ldr r0, [r4, #16] +1000ed08: f000 f920 bl 1000ef4c + +1000ed0c : +1000ed0c: f010 0003 ands.w r0, r0, #3 +1000ed10: bf18 it ne +1000ed12: 2001 movne r0, #1 +1000ed14: 8922 ldrh r2, [r4, #8] +1000ed16: 6969 ldr r1, [r5, #20] +1000ed18: 1880 adds r0, r0, r2 +1000ed1a: 1840 adds r0, r0, r1 +1000ed1c: 6168 str r0, [r5, #20] +1000ed1e: 6920 ldr r0, [r4, #16] +1000ed20: f000 f914 bl 1000ef4c + +1000ed24 : +1000ed24: 6920 ldr r0, [r4, #16] +1000ed26: f000 f911 bl 1000ef4c + +1000ed2a : +1000ed2a: f010 0003 ands.w r0, r0, #3 +1000ed2e: bf18 it ne +1000ed30: 2001 movne r0, #1 +1000ed32: 8b29 ldrh r1, [r5, #24] +1000ed34: 8922 ldrh r2, [r4, #8] +1000ed36: 1a89 subs r1, r1, r2 +1000ed38: f000 f8df bl 1000eefa + +1000ed3c : +1000ed3c: 6861 ldr r1, [r4, #4] +1000ed3e: 8908 ldrh r0, [r1, #8] +1000ed40: 2800 cmp r0, #0 +1000ed42: d0c3 beq.n 1000eccc +1000ed44: 6ab8 ldr r0, [r7, #40] ; 0x28 +1000ed46: 2800 cmp r0, #0 +1000ed48: d0bd beq.n 1000ecc6 +1000ed4a: f7f9 fd90 bl 1000886e +1000ed4e: e7bb b.n 1000ecc8 + +1000ed50 : +1000ed50: 7aa8 ldrb r0, [r5, #10] +1000ed52: 07c1 lsls r1, r0, #31 +1000ed54: bf48 it mi +1000ed56: f000 00fe andmi.w r0, r0, #254 ; 0xfe +1000ed5a: f100 80b7 bmi.w 1000eecc +1000ed5e: f040 0001 orr.w r0, r0, #1 +1000ed62: e0b5 b.n 1000eed0 + +1000ed64 : +1000ed64: 4640 mov r0, r8 +1000ed66: f7fb f929 bl 10009fbc +1000ed6a: 6af4 ldr r4, [r6, #44] ; 0x2c +1000ed6c: b91c cbnz r4, 1000ed76 +1000ed6e: f000 f8bb bl 1000eee8 + +1000ed72 : +1000ed72: 62f0 str r0, [r6, #44] ; 0x2c + +1000ed74 : +1000ed74: e0ad b.n 1000eed2 + +1000ed76 : +1000ed76: f04f 0900 mov.w r9, #0 + +1000ed7a : +1000ed7a: 6920 ldr r0, [r4, #16] +1000ed7c: 6a39 ldr r1, [r7, #32] +1000ed7e: 6842 ldr r2, [r0, #4] +1000ed80: 4291 cmp r1, r2 +1000ed82: d10e bne.n 1000eda2 +1000ed84: 8920 ldrh r0, [r4, #8] +1000ed86: 89b9 ldrh r1, [r7, #12] +1000ed88: 4288 cmp r0, r1 +1000ed8a: d2f3 bcs.n 1000ed74 +1000ed8c: f000 f8ac bl 1000eee8 + +1000ed90 : +1000ed90: 2800 cmp r0, #0 +1000ed92: d0ef beq.n 1000ed74 +1000ed94: f1b9 0f00 cmp.w r9, #0 +1000ed98: bf14 ite ne +1000ed9a: f8c9 0000 strne.w r0, [r9] +1000ed9e: 62f0 streq r0, [r6, #44] ; 0x2c +1000eda0: e009 b.n 1000edb6 + +1000eda2 : +1000eda2: f1b9 0f00 cmp.w r9, #0 +1000eda6: d108 bne.n 1000edba +1000eda8: 1a8a subs r2, r1, r2 +1000edaa: d52d bpl.n 1000ee08 +1000edac: f000 f89c bl 1000eee8 + +1000edb0 : +1000edb0: 2800 cmp r0, #0 +1000edb2: d00f beq.n 1000edd4 +1000edb4: 62f0 str r0, [r6, #44] ; 0x2c + +1000edb6 : +1000edb6: 4621 mov r1, r4 +1000edb8: e023 b.n 1000ee02 + +1000edba : +1000edba: f8d9 3010 ldr.w r3, [r9, #16] +1000edbe: 685b ldr r3, [r3, #4] +1000edc0: 1acb subs r3, r1, r3 +1000edc2: 1e5b subs r3, r3, #1 +1000edc4: d420 bmi.n 1000ee08 +1000edc6: 1a8a subs r2, r1, r2 +1000edc8: 1c52 adds r2, r2, #1 +1000edca: 2a01 cmp r2, #1 +1000edcc: da1c bge.n 1000ee08 +1000edce: f000 f88b bl 1000eee8 + +1000edd2 : +1000edd2: 0005 movs r5, r0 + +1000edd4 : +1000edd4: d07d beq.n 1000eed2 +1000edd6: f8d9 0010 ldr.w r0, [r9, #16] +1000edda: f8b9 2008 ldrh.w r2, [r9, #8] +1000edde: 6840 ldr r0, [r0, #4] +1000ede0: 6a39 ldr r1, [r7, #32] +1000ede2: 1812 adds r2, r2, r0 +1000ede4: 1a52 subs r2, r2, r1 +1000ede6: 2a01 cmp r2, #1 +1000ede8: db07 blt.n 1000edfa +1000edea: 1a09 subs r1, r1, r0 +1000edec: f8a9 1008 strh.w r1, [r9, #8] +1000edf0: b289 uxth r1, r1 +1000edf2: f8d9 0004 ldr.w r0, [r9, #4] +1000edf6: f7f9 fc9f bl 10008738 + +1000edfa : +1000edfa: f8c9 5000 str.w r5, [r9] +1000edfe: 4621 mov r1, r4 +1000ee00: 4628 mov r0, r5 + +1000ee02 : +1000ee02: e8bd 43f4 ldmia.w sp!, {r2, r4, r5, r6, r7, r8, r9, lr} +1000ee06: e53d b.n 1000e884 + +1000ee08 : +1000ee08: 6822 ldr r2, [r4, #0] +1000ee0a: 2a00 cmp r2, #0 +1000ee0c: d14a bne.n 1000eea4 +1000ee0e: 6840 ldr r0, [r0, #4] +1000ee10: 1a08 subs r0, r1, r0 +1000ee12: 2801 cmp r0, #1 +1000ee14: db46 blt.n 1000eea4 +1000ee16: 6920 ldr r0, [r4, #16] +1000ee18: f000 f898 bl 1000ef4c + +1000ee1c : +1000ee1c: 07c0 lsls r0, r0, #31 +1000ee1e: d458 bmi.n 1000eed2 +1000ee20: f000 f862 bl 1000eee8 + +1000ee24 : +1000ee24: 6020 str r0, [r4, #0] +1000ee26: 2800 cmp r0, #0 +1000ee28: d053 beq.n 1000eed2 +1000ee2a: 6920 ldr r0, [r4, #16] +1000ee2c: 8922 ldrh r2, [r4, #8] +1000ee2e: 6840 ldr r0, [r0, #4] +1000ee30: 6a39 ldr r1, [r7, #32] +1000ee32: 1812 adds r2, r2, r0 +1000ee34: 1a52 subs r2, r2, r1 +1000ee36: 2a01 cmp r2, #1 +1000ee38: db02 blt.n 1000ee40 +1000ee3a: 1a09 subs r1, r1, r0 +1000ee3c: f000 f865 bl 1000ef0a + +1000ee40 : +1000ee40: 6968 ldr r0, [r5, #20] +1000ee42: 8b29 ldrh r1, [r5, #24] +1000ee44: 6a3a ldr r2, [r7, #32] +1000ee46: 1808 adds r0, r1, r0 +1000ee48: 8b39 ldrh r1, [r7, #24] +1000ee4a: 1851 adds r1, r2, r1 +1000ee4c: 4288 cmp r0, r1 +1000ee4e: d240 bcs.n 1000eed2 +1000ee50: 6820 ldr r0, [r4, #0] +1000ee52: 6900 ldr r0, [r0, #16] +1000ee54: f000 f87a bl 1000ef4c + +1000ee58 : +1000ee58: 07c0 lsls r0, r0, #31 +1000ee5a: d50b bpl.n 1000ee74 +1000ee5c: 6820 ldr r0, [r4, #0] +1000ee5e: 6900 ldr r0, [r0, #16] +1000ee60: f000 f874 bl 1000ef4c + +1000ee64 : +1000ee64: f000 003e and.w r0, r0, #62 ; 0x3e +1000ee68: f7fd fb6d bl 1000c546 +1000ee6c: 6821 ldr r1, [r4, #0] +1000ee6e: 6909 ldr r1, [r1, #16] +1000ee70: f000 f850 bl 1000ef14 + +1000ee74 : +1000ee74: 6968 ldr r0, [r5, #20] +1000ee76: 8b29 ldrh r1, [r5, #24] +1000ee78: 1808 adds r0, r1, r0 +1000ee7a: 6a39 ldr r1, [r7, #32] +1000ee7c: 1a41 subs r1, r0, r1 +1000ee7e: 6820 ldr r0, [r4, #0] +1000ee80: 8101 strh r1, [r0, #8] +1000ee82: b289 uxth r1, r1 +1000ee84: 6840 ldr r0, [r0, #4] +1000ee86: f7f9 fc57 bl 10008738 +1000ee8a: 6820 ldr r0, [r4, #0] +1000ee8c: 6900 ldr r0, [r0, #16] +1000ee8e: f000 f85d bl 1000ef4c + +1000ee92 : +1000ee92: f010 0003 ands.w r0, r0, #3 +1000ee96: bf18 it ne +1000ee98: 2001 movne r0, #1 +1000ee9a: 6821 ldr r1, [r4, #0] +1000ee9c: 8909 ldrh r1, [r1, #8] +1000ee9e: 1840 adds r0, r0, r1 +1000eea0: 8338 strh r0, [r7, #24] +1000eea2: e016 b.n 1000eed2 + +1000eea4 : +1000eea4: 46a1 mov r9, r4 +1000eea6: 0014 movs r4, r2 +1000eea8: f47f af67 bne.w 1000ed7a +1000eeac: e011 b.n 1000eed2 + +1000eeae : +1000eeae: 4640 mov r0, r8 +1000eeb0: e8bd 43f2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, lr} +1000eeb4: f7fb b882 b.w 10009fbc + +1000eeb8 : +1000eeb8: 696a ldr r2, [r5, #20] +1000eeba: 6a3b ldr r3, [r7, #32] +1000eebc: 1a98 subs r0, r3, r2 +1000eebe: d404 bmi.n 1000eeca +1000eec0: 8b29 ldrh r1, [r5, #24] +1000eec2: 1a40 subs r0, r0, r1 +1000eec4: 1c40 adds r0, r0, #1 +1000eec6: 2801 cmp r0, #1 +1000eec8: db03 blt.n 1000eed2 + +1000eeca : +1000eeca: 7aa8 ldrb r0, [r5, #10] + +1000eecc : +1000eecc: f040 0002 orr.w r0, r0, #2 + +1000eed0 : +1000eed0: 72a8 strb r0, [r5, #10] + +1000eed2 : +1000eed2: e8bd 83f1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, pc} + ... + +1000eed8 : +1000eed8: 7704 1004 .w.. + +1000eedc : +1000eedc: 4088 1004 .@.. + +1000eee0 : +1000eee0: 89b9 ldrh r1, [r7, #12] +1000eee2: 1840 adds r0, r0, r1 +1000eee4: 8338 strh r0, [r7, #24] +1000eee6: 4770 bx lr + +1000eee8 : +1000eee8: 1d38 adds r0, r7, #4 +1000eeea: f7fa b9cc b.w 10009286 + +1000eeee : +1000eeee: 07c0 lsls r0, r0, #31 +1000eef0: d502 bpl.n 1000eef8 +1000eef2: 8bb0 ldrh r0, [r6, #28] +1000eef4: 1e40 subs r0, r0, #1 +1000eef6: 83b0 strh r0, [r6, #28] + +1000eef8 : +1000eef8: 4770 bx lr + +1000eefa : +1000eefa: 1a08 subs r0, r1, r0 +1000eefc: 8328 strh r0, [r5, #24] +1000eefe: 4640 mov r0, r8 +1000ef00: f7f9 bf33 b.w 10008d6a + +1000ef04 : +1000ef04: 6860 ldr r0, [r4, #4] +1000ef06: f7f9 bc9d b.w 10008844 + +1000ef0a : +1000ef0a: 8121 strh r1, [r4, #8] +1000ef0c: b289 uxth r1, r1 +1000ef0e: 6860 ldr r0, [r4, #4] +1000ef10: f7f9 bc12 b.w 10008738 + +1000ef14 : +1000ef14: 898a ldrh r2, [r1, #12] +1000ef16: f24c 03ff movw r3, #49407 ; 0xc0ff +1000ef1a: 401a ands r2, r3 +1000ef1c: 4310 orrs r0, r2 +1000ef1e: 8188 strh r0, [r1, #12] +1000ef20: 4770 bx lr + +1000ef22 : +1000ef22: 8c31 ldrh r1, [r6, #32] +1000ef24: 1a08 subs r0, r1, r0 +1000ef26: 8430 strh r0, [r6, #32] + +1000ef28 : +1000ef28: 4620 mov r0, r4 +1000ef2a: f7fa b99e b.w 1000926a + +1000ef2e : +1000ef2e: 0780 lsls r0, r0, #30 +1000ef30: d502 bpl.n 1000ef38 +1000ef32: 89b8 ldrh r0, [r7, #12] +1000ef34: 1e40 subs r0, r0, #1 +1000ef36: 81b8 strh r0, [r7, #12] + +1000ef38 : +1000ef38: 89b9 ldrh r1, [r7, #12] +1000ef3a: 68b8 ldr r0, [r7, #8] +1000ef3c: f7f9 bbfc b.w 10008738 + +1000ef40 : +1000ef40: 6900 ldr r0, [r0, #16] +1000ef42: 6840 ldr r0, [r0, #4] +1000ef44: f7fd bb11 b.w 1000c56a + +1000ef48 : +1000ef48: 81b8 strh r0, [r7, #12] + +1000ef4a : +1000ef4a: 6978 ldr r0, [r7, #20] + +1000ef4c : +1000ef4c: 8980 ldrh r0, [r0, #12] +1000ef4e: f7fd baff b.w 1000c550 + +1000ef52 : +1000ef52: b570 push {r4, r5, r6, lr} +1000ef54: 4e21 ldr r6, [pc, #132] ; (1000efdc ) +1000ef56: 4604 mov r4, r0 +1000ef58: 69f0 ldr r0, [r6, #28] +1000ef5a: f100 0514 add.w r5, r0, #20 +1000ef5e: f7ff fff5 bl 1000ef4c + +1000ef62 : +1000ef62: 0b00 lsrs r0, r0, #12 +1000ef64: 2806 cmp r0, #6 +1000ef66: db2d blt.n 1000efc4 +1000ef68: 69f0 ldr r0, [r6, #28] +1000ef6a: f7ff ffef bl 1000ef4c + +1000ef6e : +1000ef6e: 0b00 lsrs r0, r0, #12 +1000ef70: 1f40 subs r0, r0, #5 +1000ef72: 0480 lsls r0, r0, #18 +1000ef74: 0c00 lsrs r0, r0, #16 +1000ef76: 2100 movs r1, #0 +1000ef78: e002 b.n 1000ef80 + +1000ef7a : +1000ef7a: 8762 strh r2, [r4, #58] ; 0x3a +1000ef7c: 1d09 adds r1, r1, #4 + +1000ef7e : +1000ef7e: b289 uxth r1, r1 + +1000ef80 : +1000ef80: 4281 cmp r1, r0 +1000ef82: da1f bge.n 1000efc4 +1000ef84: 5d4b ldrb r3, [r1, r5] +1000ef86: 194a adds r2, r1, r5 +1000ef88: b1e3 cbz r3, 1000efc4 +1000ef8a: 2b02 cmp r3, #2 +1000ef8c: d002 beq.n 1000ef94 +1000ef8e: d214 bcs.n 1000efba +1000ef90: 1c49 adds r1, r1, #1 +1000ef92: e7f4 b.n 1000ef7e + +1000ef94 : +1000ef94: 7853 ldrb r3, [r2, #1] +1000ef96: 2b04 cmp r3, #4 +1000ef98: d114 bne.n 1000efc4 +1000ef9a: 1d0b adds r3, r1, #4 +1000ef9c: 4298 cmp r0, r3 +1000ef9e: db11 blt.n 1000efc4 +1000efa0: 7893 ldrb r3, [r2, #2] +1000efa2: 78d2 ldrb r2, [r2, #3] +1000efa4: ea42 2203 orr.w r2, r2, r3, lsl #8 +1000efa8: f240 53b5 movw r3, #1461 ; 0x5b5 +1000efac: 429a cmp r2, r3 +1000efae: da01 bge.n 1000efb4 +1000efb0: 2a00 cmp r2, #0 +1000efb2: d1e2 bne.n 1000ef7a + +1000efb4 : +1000efb4: f240 52b4 movw r2, #1460 ; 0x5b4 +1000efb8: e7df b.n 1000ef7a + +1000efba : +1000efba: 7852 ldrb r2, [r2, #1] +1000efbc: 2a00 cmp r2, #0 +1000efbe: bf18 it ne +1000efc0: 1851 addne r1, r2, r1 +1000efc2: d1dc bne.n 1000ef7e + +1000efc4 : +1000efc4: bd70 pop {r4, r5, r6, pc} + ... + +1000efc8 : +1000efc8: 408c 1004 .@.. + +1000efcc : +1000efcc: 407c 1004 |@.. + +1000efd0 : +1000efd0: 4084 1004 .@.. + +1000efd4 : +1000efd4: 4078 1004 x@.. + +1000efd8 : +1000efd8: 4090 1004 .@.. + +1000efdc : +1000efdc: 7ad0 1004 .z.. + +1000efe0 : +1000efe0: 4770 bx lr + +1000efe2 : +1000efe2: b538 push {r3, r4, r5, lr} +1000efe4: 4604 mov r4, r0 +1000efe6: 2000 movs r0, #0 +1000efe8: 6060 str r0, [r4, #4] +1000efea: 60a0 str r0, [r4, #8] +1000efec: 60e0 str r0, [r4, #12] +1000efee: f884 0031 strb.w r0, [r4, #49] ; 0x31 +1000eff2: 6220 str r0, [r4, #32] +1000eff4: 6260 str r0, [r4, #36] ; 0x24 +1000eff6: 4d2f ldr r5, [pc, #188] ; (1000f0b4 ) +1000eff8: 9804 ldr r0, [sp, #16] +1000effa: 61e0 str r0, [r4, #28] +1000effc: 7828 ldrb r0, [r5, #0] +1000effe: f884 0034 strb.w r0, [r4, #52] ; 0x34 +1000f002: 1c40 adds r0, r0, #1 +1000f004: 7028 strb r0, [r5, #0] +1000f006: 9806 ldr r0, [sp, #24] +1000f008: 6120 str r0, [r4, #16] +1000f00a: 4620 mov r0, r4 +1000f00c: f000 f80b bl 1000f026 +1000f010: 9905 ldr r1, [sp, #20] +1000f012: 4620 mov r0, r4 +1000f014: 4788 blx r1 +1000f016: b108 cbz r0, 1000f01c +1000f018: 2000 movs r0, #0 +1000f01a: bd32 pop {r1, r4, r5, pc} + +1000f01c : +1000f01c: 6868 ldr r0, [r5, #4] +1000f01e: 6020 str r0, [r4, #0] +1000f020: 606c str r4, [r5, #4] +1000f022: 4620 mov r0, r4 +1000f024: bd32 pop {r1, r4, r5, pc} + +1000f026 : +1000f026: b570 push {r4, r5, r6, lr} +1000f028: 4604 mov r4, r0 +1000f02a: 4615 mov r5, r2 +1000f02c: 461e mov r6, r3 +1000f02e: f000 f809 bl 1000f044 +1000f032: 4629 mov r1, r5 +1000f034: 4620 mov r0, r4 +1000f036: f000 f835 bl 1000f0a4 +1000f03a: 4631 mov r1, r6 +1000f03c: 4620 mov r0, r4 +1000f03e: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +1000f042: e02b b.n 1000f09c + +1000f044 : +1000f044: b570 push {r4, r5, r6, lr} +1000f046: 4604 mov r4, r0 +1000f048: 000d movs r5, r1 +1000f04a: d022 beq.n 1000f092 +1000f04c: 6828 ldr r0, [r5, #0] +1000f04e: 6861 ldr r1, [r4, #4] +1000f050: 4288 cmp r0, r1 +1000f052: d020 beq.n 1000f096 +1000f054: 4818 ldr r0, [pc, #96] ; (1000f0b8 ) +1000f056: 6800 ldr r0, [r0, #0] +1000f058: e003 b.n 1000f062 + +1000f05a : +1000f05a: 68c6 ldr r6, [r0, #12] +1000f05c: f7f9 fe0e bl 10008c7c +1000f060: 4630 mov r0, r6 + +1000f062 : +1000f062: b150 cbz r0, 1000f07a +1000f064: 6801 ldr r1, [r0, #0] +1000f066: 6862 ldr r2, [r4, #4] +1000f068: 4291 cmp r1, r2 +1000f06a: d104 bne.n 1000f076 +1000f06c: b289 uxth r1, r1 +1000f06e: f64f 62a9 movw r2, #65193 ; 0xfea9 +1000f072: 4291 cmp r1, r2 +1000f074: d1f1 bne.n 1000f05a + +1000f076 : +1000f076: 68c0 ldr r0, [r0, #12] +1000f078: e7f3 b.n 1000f062 + +1000f07a : +1000f07a: 4810 ldr r0, [pc, #64] ; (1000f0bc ) +1000f07c: 6800 ldr r0, [r0, #0] + +1000f07e : +1000f07e: b150 cbz r0, 1000f096 +1000f080: 6801 ldr r1, [r0, #0] +1000f082: b121 cbz r1, 1000f08e +1000f084: 6862 ldr r2, [r4, #4] +1000f086: 4291 cmp r1, r2 +1000f088: bf04 itt eq +1000f08a: 6829 ldreq r1, [r5, #0] +1000f08c: 6001 streq r1, [r0, #0] + +1000f08e : +1000f08e: 68c0 ldr r0, [r0, #12] +1000f090: e7f5 b.n 1000f07e + +1000f092 : +1000f092: 2000 movs r0, #0 +1000f094: e000 b.n 1000f098 + +1000f096 : +1000f096: 6828 ldr r0, [r5, #0] + +1000f098 : +1000f098: 6060 str r0, [r4, #4] +1000f09a: bd70 pop {r4, r5, r6, pc} + +1000f09c : +1000f09c: b101 cbz r1, 1000f0a0 +1000f09e: 6809 ldr r1, [r1, #0] + +1000f0a0 : +1000f0a0: 60c1 str r1, [r0, #12] +1000f0a2: 4770 bx lr + +1000f0a4 : +1000f0a4: b101 cbz r1, 1000f0a8 +1000f0a6: 6809 ldr r1, [r1, #0] + +1000f0a8 : +1000f0a8: 6081 str r1, [r0, #8] +1000f0aa: 4770 bx lr + +1000f0ac : +1000f0ac: 4901 ldr r1, [pc, #4] ; (1000f0b4 ) +1000f0ae: 6088 str r0, [r1, #8] +1000f0b0: 4770 bx lr + ... + +1000f0b4 : +1000f0b4: 789c 1004 .x.. + +1000f0b8 : +1000f0b8: 4088 1004 .@.. + +1000f0bc : +1000f0bc: 4084 1004 .@.. + +1000f0c0 : +1000f0c0: f890 1031 ldrb.w r1, [r0, #49] ; 0x31 +1000f0c4: 07ca lsls r2, r1, #31 +1000f0c6: d40a bmi.n 1000f0de +1000f0c8: f041 0101 orr.w r1, r1, #1 +1000f0cc: f880 1031 strb.w r1, [r0, #49] ; 0x31 +1000f0d0: f001 0130 and.w r1, r1, #48 ; 0x30 +1000f0d4: 2930 cmp r1, #48 ; 0x30 +1000f0d6: bf04 itt eq +1000f0d8: 1d01 addeq r1, r0, #4 +1000f0da: f7fc bd85 beq.w 1000bbe8 + +1000f0de : +1000f0de: 4770 bx lr + +1000f0e0 : +1000f0e0: f890 1031 ldrb.w r1, [r0, #49] ; 0x31 +1000f0e4: 07ca lsls r2, r1, #31 +1000f0e6: d507 bpl.n 1000f0f8 +1000f0e8: f001 01fe and.w r1, r1, #254 ; 0xfe +1000f0ec: f880 1031 strb.w r1, [r0, #49] ; 0x31 +1000f0f0: 0689 lsls r1, r1, #26 +1000f0f2: bf48 it mi +1000f0f4: f7fc bb33 bmi.w 1000b75e + +1000f0f8 : +1000f0f8: 4770 bx lr + ... + +1000f0fc : +1000f0fc: 4770 bx lr + +1000f0fe : +1000f0fe: 2808 cmp r0, #8 +1000f100: d206 bcs.n 1000f110 +1000f102: f8df 1554 ldr.w r1, [pc, #1364] ; 1000f658 +1000f106: 2218 movs r2, #24 +1000f108: fb02 1000 mla r0, r2, r0, r1 +1000f10c: 6801 ldr r1, [r0, #0] +1000f10e: b901 cbnz r1, 1000f112 + +1000f110 : +1000f110: 2000 movs r0, #0 + +1000f112 : +1000f112: 4770 bx lr + +1000f114 : +1000f114: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1000f118: 4605 mov r5, r0 +1000f11a: 4688 mov r8, r1 +1000f11c: 2400 movs r4, #0 +1000f11e: f8df 7538 ldr.w r7, [pc, #1336] ; 1000f658 + +1000f122 : +1000f122: f7f9 f8b1 bl 10008288 +1000f126: 2118 movs r1, #24 +1000f128: fb01 f604 mul.w r6, r1, r4 +1000f12c: 59f1 ldr r1, [r6, r7] +1000f12e: b9a1 cbnz r1, 1000f15a +1000f130: 51f5 str r5, [r6, r7] +1000f132: f7f9 f8ae bl 10008292 +1000f136: 19f0 adds r0, r6, r7 +1000f138: 2100 movs r1, #0 +1000f13a: 6041 str r1, [r0, #4] +1000f13c: 8101 strh r1, [r0, #8] +1000f13e: 8141 strh r1, [r0, #10] +1000f140: 6829 ldr r1, [r5, #0] +1000f142: 2910 cmp r1, #16 +1000f144: bf0c ite eq +1000f146: ea5f 0108 movseq.w r1, r8 +1000f14a: 2101 movne r1, #1 +1000f14c: 8181 strh r1, [r0, #12] +1000f14e: 2100 movs r1, #0 +1000f150: 81c1 strh r1, [r0, #14] +1000f152: 6101 str r1, [r0, #16] +1000f154: 6141 str r1, [r0, #20] +1000f156: 4620 mov r0, r4 +1000f158: e006 b.n 1000f168 + +1000f15a : +1000f15a: f7f9 f89a bl 10008292 +1000f15e: 1c64 adds r4, r4, #1 +1000f160: 2c08 cmp r4, #8 +1000f162: dbde blt.n 1000f122 +1000f164: f04f 30ff mov.w r0, #4294967295 + +1000f168 : +1000f168: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +1000f16c : +1000f16c: 460d mov r5, r1 +1000f16e: 4616 mov r6, r2 +1000f170: e7c5 b.n 1000f0fe + +1000f172 : +1000f172: b570 push {r4, r5, r6, lr} +1000f174: 2500 movs r5, #0 +1000f176: f7ff ffc2 bl 1000f0fe +1000f17a: 0004 movs r4, r0 +1000f17c: d102 bne.n 1000f184 +1000f17e: f04f 30ff mov.w r0, #4294967295 +1000f182: bd70 pop {r4, r5, r6, pc} + +1000f184 : +1000f184: 6820 ldr r0, [r4, #0] +1000f186: b118 cbz r0, 1000f190 +1000f188: 6801 ldr r1, [r0, #0] +1000f18a: 2910 cmp r1, #16 +1000f18c: bf08 it eq +1000f18e: 2501 moveq r5, #1 + +1000f190 : +1000f190: f7f7 ffc6 bl 10007120 +1000f194: 6866 ldr r6, [r4, #4] +1000f196: 2000 movs r0, #0 +1000f198: 6060 str r0, [r4, #4] +1000f19a: 8120 strh r0, [r4, #8] +1000f19c: 6120 str r0, [r4, #16] +1000f19e: f7f9 f873 bl 10008288 +1000f1a2: 2100 movs r1, #0 +1000f1a4: 6021 str r1, [r4, #0] +1000f1a6: f7f9 f874 bl 10008292 +1000f1aa: b13e cbz r6, 1000f1bc +1000f1ac: 2d00 cmp r5, #0 +1000f1ae: 4630 mov r0, r6 +1000f1b0: d002 beq.n 1000f1b8 +1000f1b2: f7f9 fb19 bl 100087e8 +1000f1b6: e001 b.n 1000f1bc + +1000f1b8 : +1000f1b8: f7f9 fc02 bl 100089c0 + +1000f1bc : +1000f1bc: 2000 movs r0, #0 +1000f1be: bd70 pop {r4, r5, r6, pc} + +1000f1c0 : +1000f1c0: b570 push {r4, r5, r6, lr} +1000f1c2: b082 sub sp, #8 +1000f1c4: f7ff ffd2 bl 1000f16c + +1000f1c8 : +1000f1c8: 0004 movs r4, r0 +1000f1ca: d019 beq.n 1000f200 +1000f1cc: 2e10 cmp r6, #16 +1000f1ce: bf02 ittt eq +1000f1d0: 7868 ldrbeq r0, [r5, #1] +1000f1d2: 2802 cmpeq r0, #2 +1000f1d4: f015 0003 andseq.w r0, r5, #3 +1000f1d8: d001 beq.n 1000f1de +1000f1da: 2005 movs r0, #5 +1000f1dc: e00f b.n 1000f1fe + +1000f1de : +1000f1de: f000 f812 bl 1000f206 + +1000f1e2 : +1000f1e2: 4602 mov r2, r0 +1000f1e4: 6820 ldr r0, [r4, #0] +1000f1e6: a900 add r1, sp, #0 +1000f1e8: f7f7 ffdf bl 100071aa +1000f1ec: b148 cbz r0, 1000f202 +1000f1ee: 4240 negs r0, r0 +1000f1f0: 2810 cmp r0, #16 +1000f1f2: bf3a itte cc +1000f1f4: f20f 4164 addwcc r1, pc, #1124 ; 0x464 +1000f1f8: f851 0020 ldrcc.w r0, [r1, r0, lsl #2] +1000f1fc: 2005 movcs r0, #5 + +1000f1fe : +1000f1fe: 6120 str r0, [r4, #16] + +1000f200 : +1000f200: e006 b.n 1000f210 + +1000f202 : +1000f202: 6120 str r0, [r4, #16] +1000f204: bd76 pop {r1, r2, r4, r5, r6, pc} + +1000f206 : +1000f206: 6868 ldr r0, [r5, #4] +1000f208: 9000 str r0, [sp, #0] +1000f20a: 8868 ldrh r0, [r5, #2] +1000f20c: f7fd b9a0 b.w 1000c550 + +1000f210 : +1000f210: f04f 30ff mov.w r0, #4294967295 +1000f214: bd76 pop {r1, r2, r4, r5, r6, pc} + +1000f216 : +1000f216: e92d 4ffa stmdb sp!, {r1, r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1000f21a: b087 sub sp, #28 +1000f21c: 2100 movs r1, #0 +1000f21e: 4690 mov r8, r2 +1000f220: 9100 str r1, [sp, #0] +1000f222: 2500 movs r5, #0 +1000f224: 468b mov fp, r1 +1000f226: f7ff ff6a bl 1000f0fe +1000f22a: 0004 movs r4, r0 +1000f22c: f040 80b6 bne.w 1000f39c +1000f230: e02e b.n 1000f290 + +1000f232 : +1000f232: 9808 ldr r0, [sp, #32] +1000f234: 0700 lsls r0, r0, #28 +1000f236: d404 bmi.n 1000f242 +1000f238: 6820 ldr r0, [r4, #0] +1000f23a: f890 0024 ldrb.w r0, [r0, #36] ; 0x24 +1000f23e: 0780 lsls r0, r0, #30 +1000f240: d508 bpl.n 1000f254 + +1000f242 : +1000f242: f9b4 000a ldrsh.w r0, [r4, #10] +1000f246: 2801 cmp r0, #1 +1000f248: da04 bge.n 1000f254 +1000f24a: 2d01 cmp r5, #1 +1000f24c: da0f bge.n 1000f26e +1000f24e: 200b movs r0, #11 +1000f250: 6120 str r0, [r4, #16] +1000f252: e01d b.n 1000f290 + +1000f254 : +1000f254: 6820 ldr r0, [r4, #0] +1000f256: 6801 ldr r1, [r0, #0] +1000f258: 2910 cmp r1, #16 +1000f25a: a900 add r1, sp, #0 +1000f25c: d102 bne.n 1000f264 +1000f25e: f7f8 f877 bl 10007350 +1000f262: e001 b.n 1000f268 + +1000f264 : +1000f264: f7f8 f87c bl 10007360 + +1000f268 : +1000f268: b1a8 cbz r0, 1000f296 +1000f26a: 2d01 cmp r5, #1 +1000f26c: db02 blt.n 1000f274 + +1000f26e : +1000f26e: 4629 mov r1, r5 +1000f270: 6820 ldr r0, [r4, #0] +1000f272: e08b b.n 1000f38c + +1000f274 : +1000f274: 4241 negs r1, r0 +1000f276: 2910 cmp r1, #16 +1000f278: bf3a itte cc +1000f27a: f20f 32e0 addwcc r2, pc, #992 ; 0x3e0 +1000f27e: f852 1021 ldrcc.w r1, [r2, r1, lsl #2] +1000f282: 2105 movcs r1, #5 +1000f284: 6121 str r1, [r4, #16] +1000f286: f110 0f0c cmn.w r0, #12 +1000f28a: bf08 it eq +1000f28c: 2000 moveq r0, #0 +1000f28e: d001 beq.n 1000f294 + +1000f290 : +1000f290: f04f 30ff mov.w r0, #4294967295 + +1000f294 : +1000f294: e07f b.n 1000f396 + +1000f296 : +1000f296: 9800 ldr r0, [sp, #0] +1000f298: 6060 str r0, [r4, #4] + +1000f29a : +1000f29a: 6820 ldr r0, [r4, #0] +1000f29c: 6800 ldr r0, [r0, #0] +1000f29e: 2810 cmp r0, #16 +1000f2a0: bf0e itee eq +1000f2a2: 9e00 ldreq r6, [sp, #0] +1000f2a4: 9800 ldrne r0, [sp, #0] +1000f2a6: 6806 ldrne r6, [r0, #0] +1000f2a8: 8923 ldrh r3, [r4, #8] +1000f2aa: 8930 ldrh r0, [r6, #8] +1000f2ac: 1ac0 subs r0, r0, r3 +1000f2ae: fa1f f980 uxth.w r9, r0 +1000f2b2: 46ca mov sl, r9 +1000f2b4: 45c1 cmp r9, r8 +1000f2b6: bf88 it hi +1000f2b8: 46c2 movhi sl, r8 +1000f2ba: 9807 ldr r0, [sp, #28] +1000f2bc: 1829 adds r1, r5, r0 +1000f2be: fa1f f28a uxth.w r2, sl +1000f2c2: 4630 mov r0, r6 +1000f2c4: f7f9 fb37 bl 10008936 +1000f2c8: 6820 ldr r0, [r4, #0] +1000f2ca: 6801 ldr r1, [r0, #0] +1000f2cc: 4455 add r5, sl +1000f2ce: 2910 cmp r1, #16 +1000f2d0: d10c bne.n 1000f2ec +1000f2d2: ebb8 080a subs.w r8, r8, sl +1000f2d6: d009 beq.n 1000f2ec +1000f2d8: 7b72 ldrb r2, [r6, #13] +1000f2da: 07d2 lsls r2, r2, #31 +1000f2dc: d406 bmi.n 1000f2ec +1000f2de: f9b4 200a ldrsh.w r2, [r4, #10] +1000f2e2: 2a01 cmp r2, #1 +1000f2e4: db02 blt.n 1000f2ec +1000f2e6: 9a08 ldr r2, [sp, #32] +1000f2e8: 07d2 lsls r2, r2, #31 +1000f2ea: d502 bpl.n 1000f2f2 + +1000f2ec : +1000f2ec: f04f 0b01 mov.w fp, #1 +1000f2f0: e002 b.n 1000f2f8 + +1000f2f2 : +1000f2f2: f1bb 0f00 cmp.w fp, #0 +1000f2f6: d028 beq.n 1000f34a + +1000f2f8 : +1000f2f8: 9a12 ldr r2, [sp, #72] ; 0x48 +1000f2fa: 2a00 cmp r2, #0 +1000f2fc: bf18 it ne +1000f2fe: 2f00 cmpne r7, #0 +1000f300: d020 beq.n 1000f344 +1000f302: 2910 cmp r1, #16 +1000f304: d106 bne.n 1000f314 +1000f306: ae02 add r6, sp, #8 +1000f308: 2300 movs r3, #0 +1000f30a: aa01 add r2, sp, #4 +1000f30c: a902 add r1, sp, #8 +1000f30e: f7f7 ff17 bl 10007140 +1000f312: e005 b.n 1000f320 + +1000f314 : +1000f314: 9800 ldr r0, [sp, #0] +1000f316: f100 0608 add.w r6, r0, #8 +1000f31a: 8980 ldrh r0, [r0, #12] +1000f31c: f8ad 0004 strh.w r0, [sp, #4] + +1000f320 : +1000f320: f000 f843 bl 1000f3aa + +1000f324 : +1000f324: f000 f846 bl 1000f3b4 + +1000f328 : +1000f328: f8ad 000e strh.w r0, [sp, #14] +1000f32c: 6830 ldr r0, [r6, #0] +1000f32e: 9004 str r0, [sp, #16] +1000f330: 6838 ldr r0, [r7, #0] +1000f332: 2811 cmp r0, #17 +1000f334: bf24 itt cs +1000f336: 2010 movcs r0, #16 +1000f338: 6038 strcs r0, [r7, #0] +1000f33a: 683a ldr r2, [r7, #0] +1000f33c: 9812 ldr r0, [sp, #72] ; 0x48 +1000f33e: a903 add r1, sp, #12 +1000f340: f7fd f802 bl 1000c348 + +1000f344 : +1000f344: 9808 ldr r0, [sp, #32] +1000f346: 07c0 lsls r0, r0, #31 +1000f348: d419 bmi.n 1000f37e + +1000f34a : +1000f34a: 6820 ldr r0, [r4, #0] +1000f34c: 6801 ldr r1, [r0, #0] +1000f34e: 2910 cmp r1, #16 +1000f350: d109 bne.n 1000f366 +1000f352: eba9 010a sub.w r1, r9, sl +1000f356: 2901 cmp r1, #1 +1000f358: db05 blt.n 1000f366 +1000f35a: 9800 ldr r0, [sp, #0] +1000f35c: 6060 str r0, [r4, #4] +1000f35e: 8920 ldrh r0, [r4, #8] +1000f360: 4450 add r0, sl +1000f362: 8120 strh r0, [r4, #8] +1000f364: e00b b.n 1000f37e + +1000f366 : +1000f366: 2100 movs r1, #0 +1000f368: 6061 str r1, [r4, #4] +1000f36a: 8121 strh r1, [r4, #8] +1000f36c: 6800 ldr r0, [r0, #0] +1000f36e: 2810 cmp r0, #16 +1000f370: 9800 ldr r0, [sp, #0] +1000f372: d102 bne.n 1000f37a +1000f374: f7f9 fa38 bl 100087e8 +1000f378: e001 b.n 1000f37e + +1000f37a : +1000f37a: f7f9 fb21 bl 100089c0 + +1000f37e : +1000f37e: f1bb 0f00 cmp.w fp, #0 +1000f382: d00c beq.n 1000f39e +1000f384: 2d01 cmp r5, #1 +1000f386: db03 blt.n 1000f390 +1000f388: 6820 ldr r0, [r4, #0] +1000f38a: 4629 mov r1, r5 + +1000f38c : +1000f38c: f7f8 f82e bl 100073ec + +1000f390 : +1000f390: 2000 movs r0, #0 +1000f392: 6120 str r0, [r4, #16] +1000f394: 4628 mov r0, r5 + +1000f396 : +1000f396: b009 add sp, #36 ; 0x24 +1000f398: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1000f39c : +1000f39c: 9f13 ldr r7, [sp, #76] ; 0x4c + +1000f39e : +1000f39e: 6860 ldr r0, [r4, #4] +1000f3a0: 2800 cmp r0, #0 +1000f3a2: f43f af46 beq.w 1000f232 +1000f3a6: 9000 str r0, [sp, #0] +1000f3a8: e777 b.n 1000f29a + +1000f3aa : +1000f3aa: 2210 movs r2, #16 +1000f3ac: 2100 movs r1, #0 +1000f3ae: a803 add r0, sp, #12 +1000f3b0: f7fc bfcc b.w 1000c34c + +1000f3b4 : +1000f3b4: 2010 movs r0, #16 +1000f3b6: f88d 000c strb.w r0, [sp, #12] +1000f3ba: 2002 movs r0, #2 +1000f3bc: f88d 000d strb.w r0, [sp, #13] +1000f3c0: f8bd 0004 ldrh.w r0, [sp, #4] +1000f3c4: f7fd b8bf b.w 1000c546 + +1000f3c8 : +1000f3c8: b500 push {lr} +1000f3ca: b083 sub sp, #12 +1000f3cc: 2300 movs r3, #0 +1000f3ce: 9301 str r3, [sp, #4] +1000f3d0: 9300 str r3, [sp, #0] +1000f3d2: f7ff ff20 bl 1000f216 +1000f3d6: bd0e pop {r1, r2, r3, pc} + +1000f3d8 : +1000f3d8: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1000f3dc: b084 sub sp, #16 +1000f3de: 4680 mov r8, r0 +1000f3e0: 460d mov r5, r1 +1000f3e2: 4616 mov r6, r2 +1000f3e4: 461f mov r7, r3 +1000f3e6: f7ff fe8a bl 1000f0fe +1000f3ea: 0004 movs r4, r0 +1000f3ec: d02c beq.n 1000f448 +1000f3ee: 6820 ldr r0, [r4, #0] +1000f3f0: 6801 ldr r1, [r0, #0] +1000f3f2: 2910 cmp r1, #16 +1000f3f4: d009 beq.n 1000f40a +1000f3f6: 2000 movs r0, #0 +1000f3f8: 9001 str r0, [sp, #4] +1000f3fa: 9000 str r0, [sp, #0] +1000f3fc: 463b mov r3, r7 +1000f3fe: 4632 mov r2, r6 +1000f400: 4629 mov r1, r5 +1000f402: 4640 mov r0, r8 +1000f404: f000 f823 bl 1000f44e +1000f408: e020 b.n 1000f44c + +1000f40a : +1000f40a: 06f9 lsls r1, r7, #27 +1000f40c: bf4c ite mi +1000f40e: 2102 movmi r1, #2 +1000f410: 2100 movpl r1, #0 +1000f412: 073a lsls r2, r7, #28 +1000f414: bf4c ite mi +1000f416: 2204 movmi r2, #4 +1000f418: 2200 movpl r2, #0 +1000f41a: 2300 movs r3, #0 +1000f41c: 9302 str r3, [sp, #8] +1000f41e: 4311 orrs r1, r2 +1000f420: ab02 add r3, sp, #8 +1000f422: 9300 str r3, [sp, #0] +1000f424: 4632 mov r2, r6 +1000f426: f041 0301 orr.w r3, r1, #1 +1000f42a: 4629 mov r1, r5 +1000f42c: f7f8 f812 bl 10007454 +1000f430: 4241 negs r1, r0 +1000f432: 2910 cmp r1, #16 +1000f434: bf3a itte cc +1000f436: f20f 2224 addwcc r2, pc, #548 ; 0x224 +1000f43a: f852 1021 ldrcc.w r1, [r2, r1, lsl #2] +1000f43e: 2105 movcs r1, #5 +1000f440: 6121 str r1, [r4, #16] +1000f442: b908 cbnz r0, 1000f448 +1000f444: 9802 ldr r0, [sp, #8] +1000f446: e001 b.n 1000f44c + +1000f448 : +1000f448: f04f 30ff mov.w r0, #4294967295 + +1000f44c : +1000f44c: e051 b.n 1000f4f2 + +1000f44e : +1000f44e: e92d 41ff stmdb sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, lr} +1000f452: 4607 mov r7, r0 +1000f454: 460c mov r4, r1 +1000f456: 4616 mov r6, r2 +1000f458: 4698 mov r8, r3 +1000f45a: f7ff fe50 bl 1000f0fe +1000f45e: 0005 movs r5, r0 +1000f460: d019 beq.n 1000f496 +1000f462: 6828 ldr r0, [r5, #0] +1000f464: 6800 ldr r0, [r0, #0] +1000f466: 2810 cmp r0, #16 +1000f468: d106 bne.n 1000f478 +1000f46a: 4643 mov r3, r8 +1000f46c: 4632 mov r2, r6 +1000f46e: 4621 mov r1, r4 +1000f470: 4638 mov r0, r7 +1000f472: f7ff ffb1 bl 1000f3d8 +1000f476: e03c b.n 1000f4f2 + +1000f478 : +1000f478: 980a ldr r0, [sp, #40] ; 0x28 +1000f47a: 990b ldr r1, [sp, #44] ; 0x2c +1000f47c: 2800 cmp r0, #0 +1000f47e: bf08 it eq +1000f480: 2900 cmpeq r1, #0 +1000f482: d00b beq.n 1000f49c +1000f484: 2910 cmp r1, #16 +1000f486: bf02 ittt eq +1000f488: 7841 ldrbeq r1, [r0, #1] +1000f48a: 2902 cmpeq r1, #2 +1000f48c: f010 0103 andseq.w r1, r0, #3 +1000f490: d004 beq.n 1000f49c +1000f492: 2005 movs r0, #5 +1000f494: 6128 str r0, [r5, #16] + +1000f496 : +1000f496: f04f 30ff mov.w r0, #4294967295 +1000f49a: e02a b.n 1000f4f2 + +1000f49c : +1000f49c: 2100 movs r1, #0 +1000f49e: 9101 str r1, [sp, #4] +1000f4a0: 9100 str r1, [sp, #0] +1000f4a2: b128 cbz r0, 1000f4b0 +1000f4a4: 6841 ldr r1, [r0, #4] +1000f4a6: 9102 str r1, [sp, #8] +1000f4a8: 8840 ldrh r0, [r0, #2] +1000f4aa: f7fd f851 bl 1000c550 +1000f4ae: e000 b.n 1000f4b2 + +1000f4b0 : +1000f4b0: 9002 str r0, [sp, #8] + +1000f4b2 : +1000f4b2: f8ad 000c strh.w r0, [sp, #12] +1000f4b6: b2b2 uxth r2, r6 +1000f4b8: 4621 mov r1, r4 +1000f4ba: a800 add r0, sp, #0 +1000f4bc: f7f9 fa9a bl 100089f4 +1000f4c0: 0004 movs r4, r0 +1000f4c2: d104 bne.n 1000f4ce +1000f4c4: 6828 ldr r0, [r5, #0] +1000f4c6: a900 add r1, sp, #0 +1000f4c8: f7f7 ffa4 bl 10007414 +1000f4cc: 4604 mov r4, r0 + +1000f4ce : +1000f4ce: a800 add r0, sp, #0 +1000f4d0: f7f9 fa85 bl 100089de +1000f4d4: 4260 negs r0, r4 +1000f4d6: 2810 cmp r0, #16 +1000f4d8: bf3a itte cc +1000f4da: f20f 1180 addwcc r1, pc, #384 ; 0x180 +1000f4de: f851 0020 ldrcc.w r0, [r1, r0, lsl #2] +1000f4e2: 2005 movcs r0, #5 +1000f4e4: 6128 str r0, [r5, #16] +1000f4e6: 2c00 cmp r4, #0 +1000f4e8: bf0c ite eq +1000f4ea: b2b6 uxtheq r6, r6 +1000f4ec: f04f 36ff movne.w r6, #4294967295 +1000f4f0: 4630 mov r0, r6 + +1000f4f2 : +1000f4f2: b004 add sp, #16 +1000f4f4: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +1000f4f8 : +1000f4f8: b510 push {r4, lr} +1000f4fa: 4610 mov r0, r2 +1000f4fc: f20f 025d addw r2, pc, #93 ; 0x5d +1000f500: 2901 cmp r1, #1 +1000f502: d011 beq.n 1000f528 +1000f504: d326 bcc.n 1000f554 +1000f506: 2903 cmp r1, #3 +1000f508: d001 beq.n 1000f50e +1000f50a: d307 bcc.n 1000f51c +1000f50c: e022 b.n 1000f554 + +1000f50e : +1000f50e: b2c1 uxtb r1, r0 +1000f510: 2040 movs r0, #64 ; 0x40 + +1000f512 : +1000f512: f7f7 fdd7 bl 100070c4 +1000f516: 0004 movs r4, r0 +1000f518: d112 bne.n 1000f540 +1000f51a: e01b b.n 1000f554 + +1000f51c : +1000f51c: 2888 cmp r0, #136 ; 0x88 +1000f51e: bf0c ite eq +1000f520: 2021 moveq r0, #33 ; 0x21 +1000f522: 2020 movne r0, #32 +1000f524: 2100 movs r1, #0 +1000f526: e7f4 b.n 1000f512 + +1000f528 : +1000f528: 2100 movs r1, #0 +1000f52a: 2010 movs r0, #16 +1000f52c: f7f7 fdca bl 100070c4 +1000f530: 0004 movs r4, r0 +1000f532: d00f beq.n 1000f554 +1000f534: f894 0024 ldrb.w r0, [r4, #36] ; 0x24 +1000f538: f040 0008 orr.w r0, r0, #8 +1000f53c: f884 0024 strb.w r0, [r4, #36] ; 0x24 + +1000f540 : +1000f540: 2100 movs r1, #0 +1000f542: 4620 mov r0, r4 +1000f544: f7ff fde6 bl 1000f114 +1000f548: f110 0f01 cmn.w r0, #1 +1000f54c: d104 bne.n 1000f558 +1000f54e: 4620 mov r0, r4 +1000f550: f7f7 fde6 bl 10007120 + +1000f554 : +1000f554: f000 b970 b.w 1000f838 + +1000f558 : +1000f558: 61e0 str r0, [r4, #28] +1000f55a: bd10 pop {r4, pc} + +1000f55c : +1000f55c: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +1000f560: 0006 movs r6, r0 +1000f562: 460f mov r7, r1 +1000f564: d076 beq.n 1000f654 +1000f566: 69f4 ldr r4, [r6, #28] +1000f568: 2c00 cmp r4, #0 +1000f56a: d50c bpl.n 1000f586 +1000f56c: f7f8 fe8c bl 10008288 +1000f570: 69f4 ldr r4, [r6, #28] +1000f572: 4680 mov r8, r0 +1000f574: 2c00 cmp r4, #0 +1000f576: d504 bpl.n 1000f582 +1000f578: 2f00 cmp r7, #0 +1000f57a: d166 bne.n 1000f64a +1000f57c: 1e60 subs r0, r4, #1 +1000f57e: 61f0 str r0, [r6, #28] +1000f580: e063 b.n 1000f64a + +1000f582 : +1000f582: f7f8 fe86 bl 10008292 + +1000f586 : +1000f586: 4620 mov r0, r4 +1000f588: f7ff fdb9 bl 1000f0fe +1000f58c: 0006 movs r6, r0 +1000f58e: d061 beq.n 1000f654 +1000f590: f7f8 fe7a bl 10008288 +1000f594: 4680 mov r8, r0 +1000f596: b137 cbz r7, 1000f5a6 +1000f598: 2f02 cmp r7, #2 +1000f59a: d00b beq.n 1000f5b4 +1000f59c: d306 bcc.n 1000f5ac +1000f59e: 2f04 cmp r7, #4 +1000f5a0: d00d beq.n 1000f5be +1000f5a2: d309 bcc.n 1000f5b8 +1000f5a4: e00d b.n 1000f5c2 + +1000f5a6 : +1000f5a6: 8970 ldrh r0, [r6, #10] +1000f5a8: 1c40 adds r0, r0, #1 +1000f5aa: e001 b.n 1000f5b0 + +1000f5ac : +1000f5ac: 8970 ldrh r0, [r6, #10] +1000f5ae: 1e40 subs r0, r0, #1 + +1000f5b0 : +1000f5b0: 8170 strh r0, [r6, #10] +1000f5b2: e006 b.n 1000f5c2 + +1000f5b4 : +1000f5b4: 2001 movs r0, #1 +1000f5b6: e000 b.n 1000f5ba + +1000f5b8 : +1000f5b8: 2000 movs r0, #0 + +1000f5ba : +1000f5ba: 81b0 strh r0, [r6, #12] +1000f5bc: e001 b.n 1000f5c2 + +1000f5be : +1000f5be: 2001 movs r0, #1 +1000f5c0: 81f0 strh r0, [r6, #14] + +1000f5c2 : +1000f5c2: 6970 ldr r0, [r6, #20] +1000f5c4: f8df 7278 ldr.w r7, [pc, #632] ; 1000f840 +1000f5c8: 2800 cmp r0, #0 +1000f5ca: d03e beq.n 1000f64a + +1000f5cc : +1000f5cc: 683d ldr r5, [r7, #0] +1000f5ce: f004 0907 and.w r9, r4, #7 +1000f5d2: e038 b.n 1000f646 + +1000f5d4 : +1000f5d4: 6968 ldr r0, [r5, #20] +1000f5d6: bb50 cbnz r0, 1000f62e +1000f5d8: 10a0 asrs r0, r4, #2 +1000f5da: eb04 7050 add.w r0, r4, r0, lsr #29 +1000f5de: f9b6 100a ldrsh.w r1, [r6, #10] +1000f5e2: 10c0 asrs r0, r0, #3 +1000f5e4: 2901 cmp r1, #1 +1000f5e6: db06 blt.n 1000f5f6 +1000f5e8: 68a9 ldr r1, [r5, #8] +1000f5ea: b121 cbz r1, 1000f5f6 +1000f5ec: 5c41 ldrb r1, [r0, r1] +1000f5ee: fa21 f109 lsr.w r1, r1, r9 +1000f5f2: 07c9 lsls r1, r1, #31 +1000f5f4: d415 bmi.n 1000f622 + +1000f5f6 : +1000f5f6: 89b1 ldrh r1, [r6, #12] +1000f5f8: 2900 cmp r1, #0 +1000f5fa: bf1c itt ne +1000f5fc: 68e9 ldrne r1, [r5, #12] +1000f5fe: 2900 cmpne r1, #0 +1000f600: d004 beq.n 1000f60c +1000f602: 5c41 ldrb r1, [r0, r1] +1000f604: fa21 f109 lsr.w r1, r1, r9 +1000f608: 07c9 lsls r1, r1, #31 +1000f60a: d40a bmi.n 1000f622 + +1000f60c : +1000f60c: 89f1 ldrh r1, [r6, #14] +1000f60e: 2900 cmp r1, #0 +1000f610: bf1c itt ne +1000f612: 6929 ldrne r1, [r5, #16] +1000f614: 2900 cmpne r1, #0 +1000f616: d00a beq.n 1000f62e +1000f618: 5c40 ldrb r0, [r0, r1] +1000f61a: fa20 f009 lsr.w r0, r0, r9 +1000f61e: 07c0 lsls r0, r0, #31 +1000f620: d505 bpl.n 1000f62e + +1000f622 : +1000f622: 2001 movs r0, #1 +1000f624: 6168 str r0, [r5, #20] +1000f626: f105 0018 add.w r0, r5, #24 +1000f62a: f7f8 fde0 bl 100081ee + +1000f62e : +1000f62e: f8d7 a004 ldr.w sl, [r7, #4] +1000f632: 4640 mov r0, r8 +1000f634: f7f8 fe2d bl 10008292 +1000f638: f7f8 fe26 bl 10008288 +1000f63c: 4680 mov r8, r0 +1000f63e: 6878 ldr r0, [r7, #4] +1000f640: 4582 cmp sl, r0 +1000f642: d1c3 bne.n 1000f5cc +1000f644: 682d ldr r5, [r5, #0] + +1000f646 : +1000f646: 2d00 cmp r5, #0 +1000f648: d1c4 bne.n 1000f5d4 + +1000f64a : +1000f64a: 4640 mov r0, r8 +1000f64c: e8bd 47f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +1000f650: f7f8 be1f b.w 10008292 + +1000f654 : +1000f654: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + +1000f658 : +1000f658: 78f8 1004 .x.. + +1000f65c : +1000f65c: 0000 0000 000c 0000 0069 0000 000b 0000 ........i....... +1000f66c: 0071 0000 0073 0000 0016 0000 000b 0000 q...s........... +1000f67c: 0062 0000 0072 0000 0067 0000 0068 0000 b...r...g...h... +1000f68c: 006b 0000 006b 0000 0005 0000 ffff ffff k...k........... + +1000f69c : +1000f69c: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1000f6a0: b088 sub sp, #32 +1000f6a2: 4680 mov r8, r0 +1000f6a4: 460f mov r7, r1 +1000f6a6: 4616 mov r6, r2 +1000f6a8: 461d mov r5, r3 +1000f6aa: f7ff fd28 bl 1000f0fe +1000f6ae: 4604 mov r4, r0 +1000f6b0: 2000 movs r0, #0 +1000f6b2: 2c00 cmp r4, #0 +1000f6b4: d04d beq.n 1000f752 +1000f6b6: b90d cbnz r5, 1000f6bc +1000f6b8: 200e movs r0, #14 +1000f6ba: e049 b.n 1000f750 + +1000f6bc : +1000f6bc: 0039 movs r1, r7 +1000f6be: d01e beq.n 1000f6fe +1000f6c0: 2f06 cmp r7, #6 +1000f6c2: d035 beq.n 1000f730 +1000f6c4: f640 72ff movw r2, #4095 ; 0xfff +1000f6c8: 4297 cmp r7, r2 +1000f6ca: d13d bne.n 1000f748 +1000f6cc: f1b6 0108 subs.w r1, r6, #8 +1000f6d0: d018 beq.n 1000f704 +1000f6d2: 3918 subs r1, #24 +1000f6d4: d016 beq.n 1000f704 +1000f6d6: f640 72e6 movw r2, #4070 ; 0xfe6 +1000f6da: 1a89 subs r1, r1, r2 +1000f6dc: d012 beq.n 1000f704 +1000f6de: 1f09 subs r1, r1, #4 +1000f6e0: d132 bne.n 1000f748 +1000f6e2: 990e ldr r1, [sp, #56] ; 0x38 +1000f6e4: 2904 cmp r1, #4 +1000f6e6: bf38 it cc +1000f6e8: 2016 movcc r0, #22 +1000f6ea: 6821 ldr r1, [r4, #0] +1000f6ec: 680a ldr r2, [r1, #0] +1000f6ee: 2a20 cmp r2, #32 +1000f6f0: d103 bne.n 1000f6fa +1000f6f2: 6889 ldr r1, [r1, #8] +1000f6f4: 7c09 ldrb r1, [r1, #16] +1000f6f6: 0789 lsls r1, r1, #30 +1000f6f8: d528 bpl.n 1000f74c + +1000f6fa : +1000f6fa: 2061 movs r0, #97 ; 0x61 +1000f6fc: e028 b.n 1000f750 + +1000f6fe : +1000f6fe: 1e70 subs r0, r6, #1 +1000f700: 2801 cmp r0, #1 +1000f702: d821 bhi.n 1000f748 + +1000f704 : +1000f704: 980e ldr r0, [sp, #56] ; 0x38 +1000f706: 2804 cmp r0, #4 +1000f708: d315 bcc.n 1000f736 + +1000f70a : +1000f70a: a80e add r0, sp, #56 ; 0x38 +1000f70c: f000 f826 bl 1000f75c + +1000f710 : +1000f710: 9702 str r7, [sp, #8] +1000f712: 9603 str r6, [sp, #12] +1000f714: 9504 str r5, [sp, #16] +1000f716: 2201 movs r2, #1 +1000f718: a900 add r1, sp, #0 +1000f71a: f20f 005d addw r0, pc, #93 ; 0x5d +1000f71e: f7f8 fe8c bl 1000843a +1000f722: f000 f823 bl 1000f76c + +1000f726 : +1000f726: f99d 0018 ldrsb.w r0, [sp, #24] +1000f72a: 6120 str r0, [r4, #16] +1000f72c: b198 cbz r0, 1000f756 +1000f72e: e010 b.n 1000f752 + +1000f730 : +1000f730: 990e ldr r1, [sp, #56] ; 0x38 +1000f732: 2904 cmp r1, #4 +1000f734: d201 bcs.n 1000f73a + +1000f736 : +1000f736: 2016 movs r0, #22 +1000f738: e00a b.n 1000f750 + +1000f73a : +1000f73a: 6821 ldr r1, [r4, #0] +1000f73c: 6809 ldr r1, [r1, #0] +1000f73e: 2910 cmp r1, #16 +1000f740: d109 bne.n 1000f756 +1000f742: 1e71 subs r1, r6, #1 +1000f744: 2901 cmp r1, #1 +1000f746: d901 bls.n 1000f74c + +1000f748 : +1000f748: 205c movs r0, #92 ; 0x5c +1000f74a: e001 b.n 1000f750 + +1000f74c : +1000f74c: 2800 cmp r0, #0 +1000f74e: d0dc beq.n 1000f70a + +1000f750 : +1000f750: 6120 str r0, [r4, #16] + +1000f752 : +1000f752: f04f 30ff mov.w r0, #4294967295 + +1000f756 : +1000f756: b008 add sp, #32 +1000f758: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +1000f75c : +1000f75c: 9005 str r0, [sp, #20] +1000f75e: 9400 str r4, [sp, #0] +1000f760: 2000 movs r0, #0 +1000f762: f88d 0018 strb.w r0, [sp, #24] +1000f766: f8cd 8004 str.w r8, [sp, #4] +1000f76a: 4770 bx lr + +1000f76c : +1000f76c: 6820 ldr r0, [r4, #0] +1000f76e: 2100 movs r1, #0 +1000f770: 3010 adds r0, #16 +1000f772: f7f8 bd1f b.w 100081b4 + ... + +1000f778 : +1000f778: b510 push {r4, lr} +1000f77a: 6801 ldr r1, [r0, #0] +1000f77c: 68c2 ldr r2, [r0, #12] +1000f77e: 6903 ldr r3, [r0, #16] +1000f780: 6880 ldr r0, [r0, #8] +1000f782: b360 cbz r0, 1000f7de +1000f784: 2806 cmp r0, #6 +1000f786: d03a beq.n 1000f7fe +1000f788: f640 74ff movw r4, #4095 ; 0xfff +1000f78c: 42a0 cmp r0, r4 +1000f78e: d14d bne.n 1000f82c +1000f790: f1b2 0008 subs.w r0, r2, #8 +1000f794: d008 beq.n 1000f7a8 +1000f796: 3818 subs r0, #24 +1000f798: d006 beq.n 1000f7a8 +1000f79a: f640 74e6 movw r4, #4070 ; 0xfe6 +1000f79e: 1b00 subs r0, r0, r4 +1000f7a0: d00d beq.n 1000f7be +1000f7a2: 1f00 subs r0, r0, #4 +1000f7a4: d00f beq.n 1000f7c6 +1000f7a6: e041 b.n 1000f82c + +1000f7a8 : +1000f7a8: 6808 ldr r0, [r1, #0] +1000f7aa: 6880 ldr r0, [r0, #8] +1000f7ac: 681b ldr r3, [r3, #0] +1000f7ae: 7a04 ldrb r4, [r0, #8] +1000f7b0: 2b00 cmp r3, #0 +1000f7b2: bf14 ite ne +1000f7b4: 4322 orrne r2, r4 +1000f7b6: ea24 0202 biceq.w r2, r4, r2 +1000f7ba: 7202 strb r2, [r0, #8] +1000f7bc: e036 b.n 1000f82c + +1000f7be : +1000f7be: 680a ldr r2, [r1, #0] +1000f7c0: 6818 ldr r0, [r3, #0] +1000f7c2: 6210 str r0, [r2, #32] +1000f7c4: e032 b.n 1000f82c + +1000f7c6 : +1000f7c6: 6808 ldr r0, [r1, #0] +1000f7c8: 6880 ldr r0, [r0, #8] +1000f7ca: 681b ldr r3, [r3, #0] +1000f7cc: 7c02 ldrb r2, [r0, #16] +1000f7ce: 2b00 cmp r3, #0 +1000f7d0: bf14 ite ne +1000f7d2: f042 0201 orrne.w r2, r2, #1 +1000f7d6: f002 02fe andeq.w r2, r2, #254 ; 0xfe +1000f7da: 7402 strb r2, [r0, #16] +1000f7dc: e026 b.n 1000f82c + +1000f7de : +1000f7de: 2a01 cmp r2, #1 +1000f7e0: d007 beq.n 1000f7f2 +1000f7e2: 2a02 cmp r2, #2 +1000f7e4: d122 bne.n 1000f82c +1000f7e6: 680a ldr r2, [r1, #0] +1000f7e8: 6818 ldr r0, [r3, #0] +1000f7ea: 6892 ldr r2, [r2, #8] +1000f7ec: 3208 adds r2, #8 +1000f7ee: 7090 strb r0, [r2, #2] +1000f7f0: e01c b.n 1000f82c + +1000f7f2 : +1000f7f2: 680a ldr r2, [r1, #0] +1000f7f4: 6818 ldr r0, [r3, #0] +1000f7f6: 6892 ldr r2, [r2, #8] +1000f7f8: 3208 adds r2, #8 +1000f7fa: 7050 strb r0, [r2, #1] +1000f7fc: e016 b.n 1000f82c + +1000f7fe : +1000f7fe: 2a01 cmp r2, #1 +1000f800: d007 beq.n 1000f812 +1000f802: 2a02 cmp r2, #2 +1000f804: bf01 itttt eq +1000f806: 6818 ldreq r0, [r3, #0] +1000f808: 680a ldreq r2, [r1, #0] +1000f80a: 6892 ldreq r2, [r2, #8] +1000f80c: f8c2 0094 streq.w r0, [r2, #148] ; 0x94 +1000f810: e00c b.n 1000f82c + +1000f812 : +1000f812: 6808 ldr r0, [r1, #0] +1000f814: 6880 ldr r0, [r0, #8] +1000f816: 681b ldr r3, [r3, #0] +1000f818: f890 2022 ldrb.w r2, [r0, #34] ; 0x22 +1000f81c: 2b00 cmp r3, #0 +1000f81e: bf14 ite ne +1000f820: f042 0240 orrne.w r2, r2, #64 ; 0x40 +1000f824: f002 02bf andeq.w r2, r2, #191 ; 0xbf +1000f828: f880 2022 strb.w r2, [r0, #34] ; 0x22 + +1000f82c : +1000f82c: 6808 ldr r0, [r1, #0] +1000f82e: e8bd 4010 ldmia.w sp!, {r4, lr} +1000f832: 3010 adds r0, #16 +1000f834: f7f8 bcdb b.w 100081ee + +1000f838 : +1000f838: f04f 30ff mov.w r0, #4294967295 +1000f83c: bd10 pop {r4, pc} + ... + +1000f840 : +1000f840: 79b8 1004 .y.. + +1000f844 : +1000f844: f8df f000 ldr.w pc, [pc] ; 1000f848 +1000f848: 000002d9 .word 0x000002d9 + +1000f84c : +1000f84c: e012 b.n 1000f874 <.text_8> + +1000f84e : +1000f84e: 2801 cmp r0, #1 +1000f850: bf18 it ne +1000f852: 2802 cmpne r0, #2 +1000f854: d000 beq.n 1000f858 +1000f856: b920 cbnz r0, 1000f862 +1000f858: f44f 5000 mov.w r0, #8192 ; 0x2000 +1000f85c: 6048 str r0, [r1, #4] +1000f85e: 2000 movs r0, #0 +1000f860: 4770 bx lr +1000f862: 4929 ldr r1, [pc, #164] ; (1000f908 <.text_15>) +1000f864: 2009 movs r0, #9 +1000f866: e007 b.n 1000f878 <.text_8+0x4> + +1000f868 : +1000f868: 2803 cmp r0, #3 +1000f86a: da01 bge.n 1000f870 +1000f86c: 2001 movs r0, #1 +1000f86e: 4770 bx lr +1000f870: e003 b.n 1000f87a <.text_9> + +1000f872 : +1000f872: bf00 nop + +1000f874 <.text_8>: +1000f874: 4924 ldr r1, [pc, #144] ; (1000f908 <.text_15>) +1000f876: 2058 movs r0, #88 ; 0x58 +1000f878: 6008 str r0, [r1, #0] + +1000f87a <.text_9>: +1000f87a: f04f 30ff mov.w r0, #4294967295 +1000f87e: 4770 bx lr + +1000f880 : +1000f880: b510 push {r4, lr} +1000f882: 4604 mov r4, r0 +1000f884: f20f 01b0 addw r1, pc, #176 ; 0xb0 +1000f888: f7fc fd62 bl 1000c350 +1000f88c: b188 cbz r0, 1000f8b2 +1000f88e: f20f 01b0 addw r1, pc, #176 ; 0xb0 +1000f892: 4620 mov r0, r4 +1000f894: f7fc fd5c bl 1000c350 +1000f898: b908 cbnz r0, 1000f89e +1000f89a: 2001 movs r0, #1 +1000f89c: bd10 pop {r4, pc} +1000f89e: f20f 01a8 addw r1, pc, #168 ; 0xa8 +1000f8a2: 4620 mov r0, r4 +1000f8a4: f7fc fd54 bl 1000c350 +1000f8a8: b908 cbnz r0, 1000f8ae +1000f8aa: 2002 movs r0, #2 +1000f8ac: bd10 pop {r4, pc} +1000f8ae: f04f 30ff mov.w r0, #4294967295 +1000f8b2: bd10 pop {r4, pc} + +1000f8b4 : +1000f8b4: e7de b.n 1000f874 <.text_8> + +1000f8b6 : +1000f8b6: b570 push {r4, r5, r6, lr} +1000f8b8: 460c mov r4, r1 +1000f8ba: 4615 mov r5, r2 +1000f8bc: 2600 movs r6, #0 +1000f8be: e003 b.n 1000f8c8 +1000f8c0: 5d30 ldrb r0, [r6, r4] +1000f8c2: f7ff ffbf bl 1000f844 +1000f8c6: 1c76 adds r6, r6, #1 +1000f8c8: 42ae cmp r6, r5 +1000f8ca: dbf9 blt.n 1000f8c0 +1000f8cc: 4628 mov r0, r5 +1000f8ce: bd70 pop {r4, r5, r6, pc} + +1000f8d0 : +1000f8d0: 4a0e ldr r2, [pc, #56] ; (1000f90c <.text_16>) +1000f8d2: 6811 ldr r1, [r2, #0] +1000f8d4: b909 cbnz r1, 1000f8da +1000f8d6: 490e ldr r1, [pc, #56] ; (1000f910 <.text_17>) +1000f8d8: 6011 str r1, [r2, #0] +1000f8da: 6811 ldr r1, [r2, #0] +1000f8dc: 1840 adds r0, r0, r1 +1000f8de: 6010 str r0, [r2, #0] +1000f8e0: 4608 mov r0, r1 +1000f8e2: 4770 bx lr + +1000f8e4 : +1000f8e4: 480b ldr r0, [pc, #44] ; (1000f914 <.text_18>) +1000f8e6: 490c ldr r1, [pc, #48] ; (1000f918 <.text_19>) +1000f8e8: 6001 str r1, [r0, #0] +1000f8ea: 490c ldr r1, [pc, #48] ; (1000f91c <.text_20>) +1000f8ec: 6041 str r1, [r0, #4] +1000f8ee: 490c ldr r1, [pc, #48] ; (1000f920 <.text_21>) +1000f8f0: 6081 str r1, [r0, #8] +1000f8f2: 490c ldr r1, [pc, #48] ; (1000f924 <.text_22>) +1000f8f4: 60c1 str r1, [r0, #12] +1000f8f6: 490c ldr r1, [pc, #48] ; (1000f928 <.text_23>) +1000f8f8: 6101 str r1, [r0, #16] +1000f8fa: 490c ldr r1, [pc, #48] ; (1000f92c <.text_24>) +1000f8fc: 6141 str r1, [r0, #20] +1000f8fe: 490c ldr r1, [pc, #48] ; (1000f930 <.text_25>) +1000f900: 6181 str r1, [r0, #24] +1000f902: 490c ldr r1, [pc, #48] ; (1000f934 <.text_26>) +1000f904: 61c1 str r1, [r0, #28] +1000f906: 4770 bx lr + +1000f908 <.text_15>: +1000f908: 10000bc4 .word 0x10000bc4 + +1000f90c <.text_16>: +1000f90c: 10048848 .word 0x10048848 + +1000f910 <.text_17>: +1000f910: 1ffff210 .word 0x1ffff210 + +1000f914 <.text_18>: +1000f914: 10000760 .word 0x10000760 + +1000f918 <.text_19>: +1000f918: 1000f84d .word 0x1000f84d + +1000f91c <.text_20>: +1000f91c: 1000f84f .word 0x1000f84f + +1000f920 <.text_21>: +1000f920: 1000f869 .word 0x1000f869 + +1000f924 <.text_22>: +1000f924: 1000f873 .word 0x1000f873 + +1000f928 <.text_23>: +1000f928: 1000f881 .word 0x1000f881 + +1000f92c <.text_24>: +1000f92c: 1000f8b5 .word 0x1000f8b5 + +1000f930 <.text_25>: +1000f930: 1000f8b7 .word 0x1000f8b7 + +1000f934 <.text_26>: +1000f934: 1000f8d1 .word 0x1000f8d1 + +1000f938 <__stdin_name>: +1000f938: 6474732f 00006e69 /stdin.. + +1000f940 <__stdout_name>: +1000f940: 6474732f 0074756f /stdout. + +1000f948 <__stderr_name>: +1000f948: 6474732f 00727265 /stderr. + +1000f950 : +1000f950: b570 push {r4, r5, r6, lr} +1000f952: 4604 mov r4, r0 +1000f954: 2034 movs r0, #52 ; 0x34 +1000f956: f000 ff4f bl 100107f8 +1000f95a: 0005 movs r5, r0 +1000f95c: f20f 76b8 addw r6, pc, #1976 ; 0x7b8 +1000f960: d105 bne.n 1000f96e +1000f962: 4631 mov r1, r6 +1000f964: f20f 70c0 addw r0, pc, #1984 ; 0x7c0 +1000f968: f7fc fccb bl 1000c302 +1000f96c: e013 b.n 1000f996 +1000f96e: 2234 movs r2, #52 ; 0x34 +1000f970: 2100 movs r1, #0 +1000f972: f7fc fceb bl 1000c34c +1000f976: 2c01 cmp r4, #1 +1000f978: db13 blt.n 1000f9a2 +1000f97a: 4620 mov r0, r4 +1000f97c: f000 ff3c bl 100107f8 +1000f980: 6128 str r0, [r5, #16] +1000f982: b950 cbnz r0, 1000f99a +1000f984: 4631 mov r1, r6 +1000f986: f20f 70c4 addw r0, pc, #1988 ; 0x7c4 +1000f98a: f7fc fcba bl 1000c302 +1000f98e: 2134 movs r1, #52 ; 0x34 +1000f990: 4628 mov r0, r5 +1000f992: f000 ff3b bl 1001080c +1000f996: 2000 movs r0, #0 +1000f998: bd70 pop {r4, r5, r6, pc} +1000f99a: 4622 mov r2, r4 +1000f99c: 2100 movs r1, #0 +1000f99e: f7fc fcd5 bl 1000c34c +1000f9a2: 4628 mov r0, r5 +1000f9a4: bd70 pop {r4, r5, r6, pc} + +1000f9a6 : +1000f9a6: b510 push {r4, lr} +1000f9a8: 4604 mov r4, r0 +1000f9aa: 6920 ldr r0, [r4, #16] +1000f9ac: b110 cbz r0, 1000f9b4 +1000f9ae: 2100 movs r1, #0 +1000f9b0: f000 ff2c bl 1001080c +1000f9b4: b12c cbz r4, 1000f9c2 +1000f9b6: 4620 mov r0, r4 +1000f9b8: e8bd 4010 ldmia.w sp!, {r4, lr} +1000f9bc: 2100 movs r1, #0 +1000f9be: f000 bf25 b.w 1001080c +1000f9c2: bd10 pop {r4, pc} + +1000f9c4 : +1000f9c4: b580 push {r7, lr} +1000f9c6: f7fc fcc5 bl 1000c354 +1000f9ca: 2000 movs r0, #0 +1000f9cc: bd02 pop {r1, pc} + +1000f9ce : +1000f9ce: b510 push {r4, lr} +1000f9d0: f8df 4724 ldr.w r4, [pc, #1828] ; 100100f8 <.text_51> +1000f9d4: f104 0030 add.w r0, r4, #48 ; 0x30 +1000f9d8: f000 ff38 bl 1001084c +1000f9dc: 2000 movs r0, #0 +1000f9de: 63a0 str r0, [r4, #56] ; 0x38 +1000f9e0: 63e0 str r0, [r4, #60] ; 0x3c +1000f9e2: bd10 pop {r4, pc} + +1000f9e4 : +1000f9e4: b538 push {r3, r4, r5, lr} +1000f9e6: f8df 4710 ldr.w r4, [pc, #1808] ; 100100f8 <.text_51> +1000f9ea: 6ba2 ldr r2, [r4, #56] ; 0x38 +1000f9ec: 2a01 cmp r2, #1 +1000f9ee: db05 blt.n 1000f9fc +1000f9f0: f20f 717c addw r1, pc, #1916 ; 0x77c +1000f9f4: f20f 7090 addw r0, pc, #1936 ; 0x790 +1000f9f8: f7fc fc83 bl 1000c302 +1000f9fc: f001 f956 bl 10010cac +1000fa00: e007 b.n 1000fa12 +1000fa02: 6b25 ldr r5, [r4, #48] ; 0x30 +1000fa04: 4628 mov r0, r5 +1000fa06: f000 ff2d bl 10010864 +1000fa0a: 210c movs r1, #12 +1000fa0c: 4628 mov r0, r5 +1000fa0e: f000 fefd bl 1001080c +1000fa12: 6b21 ldr r1, [r4, #48] ; 0x30 +1000fa14: f104 0030 add.w r0, r4, #48 ; 0x30 +1000fa18: f000 ff97 bl 1001094a +1000fa1c: 2800 cmp r0, #0 +1000fa1e: d0f0 beq.n 1000fa02 +1000fa20: e8bd 4031 ldmia.w sp!, {r0, r4, r5, lr} +1000fa24: f001 b944 b.w 10010cb0 + +1000fa28 : +1000fa28: b5f8 push {r3, r4, r5, r6, r7, lr} +1000fa2a: 4604 mov r4, r0 +1000fa2c: 2500 movs r5, #0 +1000fa2e: f001 f93d bl 10010cac +1000fa32: f8df 66c4 ldr.w r6, [pc, #1732] ; 100100f8 <.text_51> +1000fa36: 6b37 ldr r7, [r6, #48] ; 0x30 +1000fa38: e000 b.n 1000fa3c +1000fa3a: 683f ldr r7, [r7, #0] +1000fa3c: 4639 mov r1, r7 +1000fa3e: f106 0030 add.w r0, r6, #48 ; 0x30 +1000fa42: f000 ff82 bl 1001094a +1000fa46: b920 cbnz r0, 1000fa52 +1000fa48: 463d mov r5, r7 +1000fa4a: 68a8 ldr r0, [r5, #8] +1000fa4c: 6800 ldr r0, [r0, #0] +1000fa4e: 42a0 cmp r0, r4 +1000fa50: d1f3 bne.n 1000fa3a +1000fa52: f001 f92d bl 10010cb0 +1000fa56: f106 0030 add.w r0, r6, #48 ; 0x30 +1000fa5a: 4287 cmp r7, r0 +1000fa5c: d107 bne.n 1000fa6e +1000fa5e: e8bd 40f4 ldmia.w sp!, {r2, r4, r5, r6, r7, lr} +1000fa62: f20f 714c addw r1, pc, #1868 ; 0x74c +1000fa66: f20f 7058 addw r0, pc, #1880 ; 0x758 +1000fa6a: f7fc bc4a b.w 1000c302 +1000fa6e: 68a9 ldr r1, [r5, #8] +1000fa70: 6848 ldr r0, [r1, #4] +1000fa72: 6889 ldr r1, [r1, #8] +1000fa74: e8bd 40f4 ldmia.w sp!, {r2, r4, r5, r6, r7, lr} + +1000fa78 <__iar_annotation$$tailcall>: +1000fa78: 4708 bx r1 + +1000fa7a : +1000fa7a: b570 push {r4, r5, r6, lr} +1000fa7c: 4604 mov r4, r0 +1000fa7e: b082 sub sp, #8 +1000fa80: 68a0 ldr r0, [r4, #8] +1000fa82: 2800 cmp r0, #0 +1000fa84: d03a beq.n 1000fafc +1000fa86: 6820 ldr r0, [r4, #0] +1000fa88: 2800 cmp r0, #0 +1000fa8a: d12f bne.n 1000faec +1000fa8c: f000 f893 bl 1000fbb6 <.text_12> +1000fa90: f20f 7560 addw r5, pc, #1888 ; 0x760 +1000fa94: 6020 str r0, [r4, #0] +1000fa96: b930 cbnz r0, 1000faa6 +1000fa98: 4629 mov r1, r5 +1000fa9a: e8bd 407c ldmia.w sp!, {r2, r3, r4, r5, r6, lr} +1000fa9e: f20f 7068 addw r0, pc, #1896 ; 0x768 +1000faa2: f7fc bc2e b.w 1000c302 +1000faa6: 200c movs r0, #12 +1000faa8: f000 feab bl 10010802 +1000faac: 0006 movs r6, r0 +1000faae: d109 bne.n 1000fac4 +1000fab0: 4629 mov r1, r5 +1000fab2: f20f 7070 addw r0, pc, #1904 ; 0x770 +1000fab6: f7fc fc24 bl 1000c302 +1000faba: f000 f877 bl 1000fbac <.text_11> +1000fabe: 2000 movs r0, #0 +1000fac0: 6020 str r0, [r4, #0] +1000fac2: bd73 pop {r0, r1, r4, r5, r6, pc} +1000fac4: 60b4 str r4, [r6, #8] +1000fac6: f001 f8f1 bl 10010cac +1000faca: f8df 462c ldr.w r4, [pc, #1580] ; 100100f8 <.text_51> +1000face: f104 0130 add.w r1, r4, #48 ; 0x30 +1000fad2: 4630 mov r0, r6 +1000fad4: f000 fec2 bl 1001085c +1000fad8: f001 f8ea bl 10010cb0 +1000fadc: 6ba0 ldr r0, [r4, #56] ; 0x38 +1000fade: 6be1 ldr r1, [r4, #60] ; 0x3c +1000fae0: 1c40 adds r0, r0, #1 +1000fae2: 4281 cmp r1, r0 +1000fae4: 63a0 str r0, [r4, #56] ; 0x38 +1000fae6: da09 bge.n 1000fafc +1000fae8: 63e0 str r0, [r4, #60] ; 0x3c +1000faea: bd73 pop {r0, r1, r4, r5, r6, pc} +1000faec: f001 f835 bl 10010b5a +1000faf0: 2801 cmp r0, #1 +1000faf2: d103 bne.n 1000fafc +1000faf4: 6820 ldr r0, [r4, #0] +1000faf6: e8bd 407c ldmia.w sp!, {r2, r3, r4, r5, r6, lr} +1000fafa: e085 b.n 1000fc08 <.text_15> +1000fafc: bd73 pop {r0, r1, r4, r5, r6, pc} + +1000fafe : +1000fafe: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1000fb02: f8df 65f4 ldr.w r6, [pc, #1524] ; 100100f8 <.text_51> +1000fb06: 4604 mov r4, r0 +1000fb08: 7c30 ldrb r0, [r6, #16] +1000fb0a: 2800 cmp r0, #0 +1000fb0c: b082 sub sp, #8 +1000fb0e: 460d mov r5, r1 +1000fb10: d04a beq.n 1000fba8 +1000fb12: 6820 ldr r0, [r4, #0] +1000fb14: f20f 7830 addw r8, pc, #1840 ; 0x730 +1000fb18: bb50 cbnz r0, 1000fb70 +1000fb1a: f000 f84c bl 1000fbb6 <.text_12> +1000fb1e: 6020 str r0, [r4, #0] +1000fb20: b928 cbnz r0, 1000fb2e +1000fb22: 4641 mov r1, r8 +1000fb24: f20f 60e0 addw r0, pc, #1760 ; 0x6e0 +1000fb28: f7fc fbeb bl 1000c302 +1000fb2c: e029 b.n 1000fb82 +1000fb2e: 200c movs r0, #12 +1000fb30: f000 fe67 bl 10010802 +1000fb34: 0007 movs r7, r0 +1000fb36: d109 bne.n 1000fb4c +1000fb38: 4641 mov r1, r8 +1000fb3a: f20f 60e8 addw r0, pc, #1768 ; 0x6e8 +1000fb3e: f7fc fbe0 bl 1000c302 +1000fb42: f000 f833 bl 1000fbac <.text_11> +1000fb46: 2000 movs r0, #0 +1000fb48: 6020 str r0, [r4, #0] +1000fb4a: e02d b.n 1000fba8 +1000fb4c: 60bc str r4, [r7, #8] +1000fb4e: f001 f8ad bl 10010cac +1000fb52: f106 0130 add.w r1, r6, #48 ; 0x30 +1000fb56: 4638 mov r0, r7 +1000fb58: f000 fe80 bl 1001085c +1000fb5c: f001 f8a8 bl 10010cb0 +1000fb60: 6bb0 ldr r0, [r6, #56] ; 0x38 +1000fb62: 6bf1 ldr r1, [r6, #60] ; 0x3c +1000fb64: 1c40 adds r0, r0, #1 +1000fb66: 4281 cmp r1, r0 +1000fb68: 63b0 str r0, [r6, #56] ; 0x38 +1000fb6a: da0a bge.n 1000fb82 +1000fb6c: 63f0 str r0, [r6, #60] ; 0x3c +1000fb6e: e008 b.n 1000fb82 +1000fb70: f000 fff3 bl 10010b5a +1000fb74: 2801 cmp r0, #1 +1000fb76: d104 bne.n 1000fb82 +1000fb78: 6820 ldr r0, [r4, #0] +1000fb7a: f04f 31ff mov.w r1, #4294967295 +1000fb7e: f000 fff4 bl 10010b6a +1000fb82: 6820 ldr r0, [r4, #0] +1000fb84: b180 cbz r0, 1000fba8 +1000fb86: 4628 mov r0, r5 +1000fb88: f000 ff19 bl 100109be +1000fb8c: 4601 mov r1, r0 +1000fb8e: 6820 ldr r0, [r4, #0] +1000fb90: f04f 32ff mov.w r2, #4294967295 +1000fb94: f000 fff1 bl 10010b7a +1000fb98: b930 cbnz r0, 1000fba8 +1000fb9a: 4641 mov r1, r8 +1000fb9c: e8bd 41fc ldmia.w sp!, {r2, r3, r4, r5, r6, r7, r8, lr} +1000fba0: f20f 60b0 addw r0, pc, #1712 ; 0x6b0 +1000fba4: f7fc bbad b.w 1000c302 +1000fba8: e8bd 81f3 ldmia.w sp!, {r0, r1, r4, r5, r6, r7, r8, pc} + +1000fbac <.text_11>: +1000fbac: 6820 ldr r0, [r4, #0] +1000fbae: f04f 31ff mov.w r1, #4294967295 +1000fbb2: f000 bfca b.w 10010b4a + +1000fbb6 <.text_12>: +1000fbb6: f8df 0544 ldr.w r0, [pc, #1348] ; 100100fc <.text_52> +1000fbba: 9000 str r0, [sp, #0] +1000fbbc: 2300 movs r3, #0 +1000fbbe: 2200 movs r2, #0 +1000fbc0: f04f 31ff mov.w r1, #4294967295 +1000fbc4: f20f 6038 addw r0, pc, #1592 ; 0x638 +1000fbc8: f000 bfb3 b.w 10010b32 + +1000fbcc : +1000fbcc: b570 push {r4, r5, r6, lr} +1000fbce: 4604 mov r4, r0 +1000fbd0: 6820 ldr r0, [r4, #0] +1000fbd2: b1c0 cbz r0, 1000fc06 +1000fbd4: f001 f86a bl 10010cac +1000fbd8: f8df 551c ldr.w r5, [pc, #1308] ; 100100f8 <.text_51> +1000fbdc: 6b2e ldr r6, [r5, #48] ; 0x30 +1000fbde: e000 b.n 1000fbe2 +1000fbe0: 6836 ldr r6, [r6, #0] +1000fbe2: f000 f83d bl 1000fc60 <.text_17> +1000fbe6: b920 cbnz r0, 1000fbf2 +1000fbe8: 68b0 ldr r0, [r6, #8] +1000fbea: 6821 ldr r1, [r4, #0] +1000fbec: 6800 ldr r0, [r0, #0] +1000fbee: 4288 cmp r0, r1 +1000fbf0: d1f6 bne.n 1000fbe0 +1000fbf2: f001 f85d bl 10010cb0 +1000fbf6: f105 0030 add.w r0, r5, #48 ; 0x30 +1000fbfa: 4286 cmp r6, r0 +1000fbfc: d003 beq.n 1000fc06 +1000fbfe: 6820 ldr r0, [r4, #0] +1000fc00: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +1000fc04: e000 b.n 1000fc08 <.text_15> +1000fc06: bd70 pop {r4, r5, r6, pc} + +1000fc08 <.text_15>: +1000fc08: f04f 31ff mov.w r1, #4294967295 +1000fc0c: f000 bfad b.w 10010b6a + +1000fc10 : +1000fc10: b570 push {r4, r5, r6, lr} +1000fc12: 4604 mov r4, r0 +1000fc14: 6820 ldr r0, [r4, #0] +1000fc16: b310 cbz r0, 1000fc5e +1000fc18: f001 f848 bl 10010cac +1000fc1c: f8df 54d8 ldr.w r5, [pc, #1240] ; 100100f8 <.text_51> +1000fc20: 6b2e ldr r6, [r5, #48] ; 0x30 +1000fc22: e000 b.n 1000fc26 +1000fc24: 6836 ldr r6, [r6, #0] +1000fc26: f000 f81b bl 1000fc60 <.text_17> +1000fc2a: b958 cbnz r0, 1000fc44 +1000fc2c: 68b0 ldr r0, [r6, #8] +1000fc2e: 6821 ldr r1, [r4, #0] +1000fc30: 6800 ldr r0, [r0, #0] +1000fc32: 4288 cmp r0, r1 +1000fc34: d1f6 bne.n 1000fc24 +1000fc36: 4630 mov r0, r6 +1000fc38: f000 fe14 bl 10010864 +1000fc3c: 210c movs r1, #12 +1000fc3e: 4630 mov r0, r6 +1000fc40: f000 fde4 bl 1001080c +1000fc44: f001 f834 bl 10010cb0 +1000fc48: f105 0030 add.w r0, r5, #48 ; 0x30 +1000fc4c: 4286 cmp r6, r0 +1000fc4e: d006 beq.n 1000fc5e +1000fc50: f7ff ffac bl 1000fbac <.text_11> +1000fc54: 2000 movs r0, #0 +1000fc56: 6020 str r0, [r4, #0] +1000fc58: 6ba8 ldr r0, [r5, #56] ; 0x38 +1000fc5a: 1e40 subs r0, r0, #1 +1000fc5c: 63a8 str r0, [r5, #56] ; 0x38 +1000fc5e: bd70 pop {r4, r5, r6, pc} + +1000fc60 <.text_17>: +1000fc60: 4631 mov r1, r6 +1000fc62: f105 0030 add.w r0, r5, #48 ; 0x30 +1000fc66: f000 be70 b.w 1001094a + +1000fc6a : +1000fc6a: 2100 movs r1, #0 +1000fc6c: f8df 2488 ldr.w r2, [pc, #1160] ; 100100f8 <.text_51> +1000fc70: 2318 movs r3, #24 +1000fc72: fb03 2301 mla r3, r3, r1, r2 +1000fc76: 681b ldr r3, [r3, #0] +1000fc78: 4298 cmp r0, r3 +1000fc7a: d101 bne.n 1000fc80 +1000fc7c: 4608 mov r0, r1 +1000fc7e: 4770 bx lr +1000fc80: 1c49 adds r1, r1, #1 +1000fc82: 2903 cmp r1, #3 +1000fc84: dbf4 blt.n 1000fc70 +1000fc86: f04f 30ff mov.w r0, #4294967295 +1000fc8a: 4770 bx lr + +1000fc8c : +1000fc8c: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1000fc90: 0004 movs r4, r0 +1000fc92: 460f mov r7, r1 +1000fc94: f20f 58dc addw r8, pc, #1500 ; 0x5dc +1000fc98: f8df 545c ldr.w r5, [pc, #1116] ; 100100f8 <.text_51> +1000fc9c: d117 bne.n 1000fcce +1000fc9e: 2100 movs r1, #0 +1000fca0: f000 fd79 bl 10010796 +1000fca4: f001 faf5 bl 10011292 +1000fca8: f001 fb07 bl 100112ba +1000fcac: f7ff fe8f bl 1000f9ce +1000fcb0: 2600 movs r6, #0 +1000fcb2: f002 f944 bl 10011f3e +1000fcb6: 4639 mov r1, r7 +1000fcb8: 4630 mov r0, r6 +1000fcba: f002 f8f6 bl 10011eaa +1000fcbe: 0006 movs r6, r0 +1000fcc0: d113 bne.n 1000fcea +1000fcc2: f002 f950 bl 10011f66 +1000fcc6: 4641 mov r1, r8 +1000fcc8: f20f 50d4 addw r0, pc, #1492 ; 0x5d4 +1000fccc: e008 b.n 1000fce0 +1000fcce: 2c01 cmp r4, #1 +1000fcd0: d103 bne.n 1000fcda +1000fcd2: 682e ldr r6, [r5, #0] +1000fcd4: 2e00 cmp r6, #0 +1000fcd6: d1ee bne.n 1000fcb6 +1000fcd8: e004 b.n 1000fce4 +1000fcda: 4641 mov r1, r8 +1000fcdc: f20f 50a4 addw r0, pc, #1444 ; 0x5a4 +1000fce0: f7fc fb0f bl 1000c302 +1000fce4: f04f 30ff mov.w r0, #4294967295 +1000fce8: e012 b.n 1000fd10 +1000fcea: 2018 movs r0, #24 +1000fcec: 4360 muls r0, r4 +1000fcee: 2100 movs r1, #0 +1000fcf0: 5141 str r1, [r0, r5] +1000fcf2: 1947 adds r7, r0, r5 +1000fcf4: f106 0214 add.w r2, r6, #20 +1000fcf8: 6079 str r1, [r7, #4] +1000fcfa: 60b9 str r1, [r7, #8] +1000fcfc: 60f9 str r1, [r7, #12] +1000fcfe: 7439 strb r1, [r7, #16] +1000fd00: 5146 str r6, [r0, r5] +1000fd02: 4631 mov r1, r6 +1000fd04: 4620 mov r0, r4 +1000fd06: f002 f95f bl 10011fc8 +1000fd0a: 2001 movs r0, #1 +1000fd0c: 7438 strb r0, [r7, #16] +1000fd0e: 2000 movs r0, #0 +1000fd10: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +1000fd14 : +1000fd14: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1000fd18: f8df 43dc ldr.w r4, [pc, #988] ; 100100f8 <.text_51> +1000fd1c: 6825 ldr r5, [r4, #0] +1000fd1e: 7c20 ldrb r0, [r4, #16] +1000fd20: 2700 movs r7, #0 +1000fd22: 2800 cmp r0, #0 +1000fd24: d05a beq.n 1000fddc +1000fd26: 6928 ldr r0, [r5, #16] +1000fd28: 6806 ldr r6, [r0, #0] +1000fd2a: f641 4ba8 movw fp, #7336 ; 0x1ca8 +1000fd2e: 2001 movs r0, #1 +1000fd30: f80b 0006 strb.w r0, [fp, r6] +1000fd34: f506 50e0 add.w r0, r6, #7168 ; 0x1c00 +1000fd38: 30bc adds r0, #188 ; 0xbc +1000fd3a: f000 fef3 bl 10010b24 +1000fd3e: f20f 5898 addw r8, pc, #1432 ; 0x598 +1000fd42: f20f 5980 addw r9, pc, #1408 ; 0x580 +1000fd46: f04f 0a18 mov.w sl, #24 +1000fd4a: e009 b.n 1000fd60 +1000fd4c: 463a mov r2, r7 +1000fd4e: 4649 mov r1, r9 +1000fd50: 4640 mov r0, r8 +1000fd52: f7fc fad6 bl 1000c302 +1000fd56: f44f 707a mov.w r0, #1000 ; 0x3e8 +1000fd5a: f000 fe56 bl 10010a0a +1000fd5e: 2700 movs r7, #0 +1000fd60: f000 ffa4 bl 10010cac +1000fd64: 2000 movs r0, #0 +1000fd66: fb0a 4100 mla r1, sl, r0, r4 +1000fd6a: 2200 movs r2, #0 +1000fd6c: 740a strb r2, [r1, #16] +1000fd6e: 1c40 adds r0, r0, #1 +1000fd70: 688a ldr r2, [r1, #8] +1000fd72: 68c9 ldr r1, [r1, #12] +1000fd74: 19d2 adds r2, r2, r7 +1000fd76: 188f adds r7, r1, r2 +1000fd78: 2802 cmp r0, #2 +1000fd7a: dbf4 blt.n 1000fd66 +1000fd7c: f000 ff98 bl 10010cb0 +1000fd80: 2f00 cmp r7, #0 +1000fd82: d1e3 bne.n 1000fd4c +1000fd84: 2064 movs r0, #100 ; 0x64 +1000fd86: f000 fe40 bl 10010a0a +1000fd8a: f20f 576c addw r7, pc, #1388 ; 0x56c +1000fd8e: e007 b.n 1000fda0 +1000fd90: 4649 mov r1, r9 +1000fd92: 4638 mov r0, r7 +1000fd94: f7fc fab5 bl 1000c302 +1000fd98: f44f 707a mov.w r0, #1000 ; 0x3e8 +1000fd9c: f000 fe35 bl 10010a0a +1000fda0: f81b 0006 ldrb.w r0, [fp, r6] +1000fda4: 2802 cmp r0, #2 +1000fda6: d1f3 bne.n 1000fd90 +1000fda8: 4628 mov r0, r5 +1000fdaa: f002 f8a7 bl 10011efc +1000fdae: f002 f8da bl 10011f66 +1000fdb2: f7ff fe17 bl 1000f9e4 +1000fdb6: 2000 movs r0, #0 +1000fdb8: 2200 movs r2, #0 +1000fdba: fb0a f100 mul.w r1, sl, r0 +1000fdbe: 1c40 adds r0, r0, #1 +1000fdc0: 510a str r2, [r1, r4] +1000fdc2: 1909 adds r1, r1, r4 +1000fdc4: 2802 cmp r0, #2 +1000fdc6: 604a str r2, [r1, #4] +1000fdc8: 608a str r2, [r1, #8] +1000fdca: 60ca str r2, [r1, #12] +1000fdcc: 740a strb r2, [r1, #16] +1000fdce: dbf4 blt.n 1000fdba +1000fdd0: e8bd 4ff4 ldmia.w sp!, {r2, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1000fdd4: 2100 movs r1, #0 +1000fdd6: 4608 mov r0, r1 +1000fdd8: f000 bce4 b.w 100107a4 +1000fddc: e8bd 8ff1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1000fde0 : +1000fde0: 2118 movs r1, #24 +1000fde2: 4341 muls r1, r0 +1000fde4: f8df 2310 ldr.w r2, [pc, #784] ; 100100f8 <.text_51> +1000fde8: 5888 ldr r0, [r1, r2] +1000fdea: 1889 adds r1, r1, r2 +1000fdec: 7c09 ldrb r1, [r1, #16] +1000fdee: b149 cbz r1, 1000fe04 <__iar_annotation$$tailcall+0xe> +1000fdf0: 2800 cmp r0, #0 +1000fdf2: bf1c itt ne +1000fdf4: 6a01 ldrne r1, [r0, #32] + +1000fdf6 <__iar_annotation$$tailcall>: +1000fdf6: 4708 bxne r1 +1000fdf8: f20f 5114 addw r1, pc, #1300 ; 0x514 +1000fdfc: f20f 5020 addw r0, pc, #1312 ; 0x520 +1000fe00: f7fc ba7f b.w 1000c302 +1000fe04: 4770 bx lr + +1000fe06 : +1000fe06: bf00 nop + +1000fe08 <.text_23>: +1000fe08: f8df 12ec ldr.w r1, [pc, #748] ; 100100f8 <.text_51> +1000fe0c: 2218 movs r2, #24 +1000fe0e: fb02 1000 mla r0, r2, r0, r1 +1000fe12: 7c00 ldrb r0, [r0, #16] +1000fe14: 4770 bx lr + +1000fe16 : +1000fe16: f8df 12e0 ldr.w r1, [pc, #736] ; 100100f8 <.text_51> +1000fe1a: 2218 movs r2, #24 +1000fe1c: fb02 1000 mla r0, r2, r0, r1 +1000fe20: 6881 ldr r1, [r0, #8] +1000fe22: 1c49 adds r1, r1, #1 +1000fe24: 6081 str r1, [r0, #8] +1000fe26: 4770 bx lr + +1000fe28 : +1000fe28: f8df 12cc ldr.w r1, [pc, #716] ; 100100f8 <.text_51> +1000fe2c: 2218 movs r2, #24 +1000fe2e: fb02 1000 mla r0, r2, r0, r1 +1000fe32: 6881 ldr r1, [r0, #8] +1000fe34: 1e49 subs r1, r1, #1 +1000fe36: 6081 str r1, [r0, #8] +1000fe38: 4770 bx lr + +1000fe3a : +1000fe3a: f8df 12bc ldr.w r1, [pc, #700] ; 100100f8 <.text_51> +1000fe3e: 2218 movs r2, #24 +1000fe40: fb02 1000 mla r0, r2, r0, r1 +1000fe44: 6840 ldr r0, [r0, #4] +1000fe46: 4770 bx lr + +1000fe48 : +1000fe48: b580 push {r7, lr} +1000fe4a: f8df 12b4 ldr.w r1, [pc, #692] ; 10010100 <.text_53> +1000fe4e: 680a ldr r2, [r1, #0] +1000fe50: 2a1a cmp r2, #26 +1000fe52: bfbe ittt lt +1000fe54: f8df 12ac ldrlt.w r1, [pc, #684] ; 10010104 <.text_54> +1000fe58: 6809 ldrlt r1, [r1, #0] +1000fe5a: 290a cmplt r1, #10 +1000fe5c: db08 blt.n 1000fe70 +1000fe5e: 231c movs r3, #28 +1000fe60: f20f 41e8 addw r1, pc, #1256 ; 0x4e8 +1000fe64: f20f 40f8 addw r0, pc, #1272 ; 0x4f8 +1000fe68: f7fc fa4b bl 1000c302 +1000fe6c: 2000 movs r0, #0 +1000fe6e: bd02 pop {r1, pc} +1000fe70: e8bd 4004 ldmia.w sp!, {r2, lr} +1000fe74: 214a movs r1, #74 ; 0x4a +1000fe76: f001 ba91 b.w 1001139c + +1000fe7a : +1000fe7a: f110 0f01 cmn.w r0, #1 +1000fe7e: 460a mov r2, r1 +1000fe80: d105 bne.n 1000fe8e +1000fe82: f20f 5120 addw r1, pc, #1312 ; 0x520 +1000fe86: f20f 5030 addw r0, pc, #1328 ; 0x530 +1000fe8a: f7fc ba3a b.w 1000c302 +1000fe8e: f8df 1268 ldr.w r1, [pc, #616] ; 100100f8 <.text_51> +1000fe92: 2318 movs r3, #24 +1000fe94: fb03 1000 mla r0, r3, r0, r1 +1000fe98: 6801 ldr r1, [r0, #0] +1000fe9a: 61d1 str r1, [r2, #28] +1000fe9c: 4610 mov r0, r2 +1000fe9e: 6a8a ldr r2, [r1, #40] ; 0x28 + +1000fea0 <__iar_annotation$$tailcall>: +1000fea0: 4710 bx r2 + +1000fea2 : +1000fea2: b5f8 push {r3, r4, r5, r6, r7, lr} +1000fea4: 0004 movs r4, r0 +1000fea6: f20f 5728 addw r7, pc, #1320 ; 0x528 +1000feaa: d006 beq.n 1000feba +1000feac: 69e0 ldr r0, [r4, #28] +1000feae: f7ff fedc bl 1000fc6a +1000feb2: 4605 mov r5, r0 +1000feb4: f115 0f01 cmn.w r5, #1 +1000feb8: d106 bne.n 1000fec8 +1000feba: 4639 mov r1, r7 +1000febc: e8bd 40f4 ldmia.w sp!, {r2, r4, r5, r6, r7, lr} +1000fec0: f20f 501c addw r0, pc, #1308 ; 0x51c +1000fec4: f7fc ba1d b.w 1000c302 +1000fec8: f000 fef0 bl 10010cac +1000fecc: f8df 0228 ldr.w r0, [pc, #552] ; 100100f8 <.text_51> +1000fed0: 2118 movs r1, #24 +1000fed2: fb01 0605 mla r6, r1, r5, r0 +1000fed6: 7c30 ldrb r0, [r6, #16] +1000fed8: b328 cbz r0, 1000ff26 +1000feda: 68f0 ldr r0, [r6, #12] +1000fedc: 1c40 adds r0, r0, #1 +1000fede: 60f0 str r0, [r6, #12] +1000fee0: f000 fee6 bl 10010cb0 +1000fee4: 6920 ldr r0, [r4, #16] +1000fee6: 7b01 ldrb r1, [r0, #12] +1000fee8: 2908 cmp r1, #8 +1000feea: bf04 itt eq +1000feec: 7b41 ldrbeq r1, [r0, #13] +1000feee: 2900 cmpeq r1, #0 +1000fef0: d105 bne.n 1000fefe +1000fef2: f100 011e add.w r1, r0, #30 +1000fef6: 4628 mov r0, r5 +1000fef8: f002 f8f2 bl 100120e0 +1000fefc: b120 cbz r0, 1000ff08 +1000fefe: 6074 str r4, [r6, #4] +1000ff00: 4628 mov r0, r5 +1000ff02: 6a21 ldr r1, [r4, #32] +1000ff04: f002 f916 bl 10012134 +1000ff08: 69e1 ldr r1, [r4, #28] +1000ff0a: 4620 mov r0, r4 +1000ff0c: f001 fa71 bl 100113f2 +1000ff10: 2000 movs r0, #0 +1000ff12: 6070 str r0, [r6, #4] +1000ff14: f000 feca bl 10010cac +1000ff18: 68f0 ldr r0, [r6, #12] +1000ff1a: 1e40 subs r0, r0, #1 +1000ff1c: 60f0 str r0, [r6, #12] +1000ff1e: e8bd 40f1 ldmia.w sp!, {r0, r4, r5, r6, r7, lr} +1000ff22: f000 bec5 b.w 10010cb0 +1000ff26: 69e1 ldr r1, [r4, #28] +1000ff28: 4620 mov r0, r4 +1000ff2a: f001 fa62 bl 100113f2 +1000ff2e: 4639 mov r1, r7 +1000ff30: f000 f8ae bl 10010090 <.text_38+0x2> +1000ff34: e7f3 b.n 1000ff1e + +1000ff36 : +1000ff36: b570 push {r4, r5, r6, lr} +1000ff38: 4604 mov r4, r0 +1000ff3a: 460d mov r5, r1 +1000ff3c: 2205 movs r2, #5 +1000ff3e: f20f 41c8 addw r1, pc, #1224 ; 0x4c8 +1000ff42: 4628 mov r0, r5 +1000ff44: f7fc f9fe bl 1000c344 +1000ff48: b100 cbz r0, 1000ff4c +1000ff4a: 2018 movs r0, #24 +1000ff4c: f8df 11a8 ldr.w r1, [pc, #424] ; 100100f8 <.text_51> +1000ff50: 5840 ldr r0, [r0, r1] +1000ff52: b368 cbz r0, 1000ffb0 <__iar_annotation$$tailcall+0x2> +1000ff54: 6901 ldr r1, [r0, #16] +1000ff56: 6809 ldr r1, [r1, #0] +1000ff58: f641 5348 movw r3, #7496 ; 0x1d48 +1000ff5c: 185e adds r6, r3, r1 +1000ff5e: f641 120c movw r2, #6412 ; 0x190c +1000ff62: 7a36 ldrb r6, [r6, #8] +1000ff64: b906 cbnz r6, 1000ff68 +1000ff66: 5859 ldr r1, [r3, r1] +1000ff68: 1851 adds r1, r2, r1 +1000ff6a: 6949 ldr r1, [r1, #20] +1000ff6c: f1b1 4f00 cmp.w r1, #2147483648 ; 0x80000000 +1000ff70: d10f bne.n 1000ff92 +1000ff72: f648 3106 movw r1, #35590 ; 0x8b06 +1000ff76: 428c cmp r4, r1 +1000ff78: bf1c itt ne +1000ff7a: f648 3114 movwne r1, #35604 ; 0x8b14 +1000ff7e: 428c cmpne r4, r1 +1000ff80: d01a beq.n 1000ffb8 <__iar_annotation$$tailcall+0xa> +1000ff82: f648 3118 movw r1, #35608 ; 0x8b18 +1000ff86: 428c cmp r4, r1 +1000ff88: bf1c itt ne +1000ff8a: f648 311a movwne r1, #35610 ; 0x8b1a +1000ff8e: 428c cmpne r4, r1 +1000ff90: d012 beq.n 1000ffb8 <__iar_annotation$$tailcall+0xa> +1000ff92: f8df 1174 ldr.w r1, [pc, #372] ; 10010108 <.text_55> +1000ff96: 1909 adds r1, r1, r4 +1000ff98: 2910 cmp r1, #16 +1000ff9a: d303 bcc.n 1000ffa4 +1000ff9c: f5a4 410b sub.w r1, r4, #35584 ; 0x8b00 +1000ffa0: 29ff cmp r1, #255 ; 0xff +1000ffa2: d809 bhi.n 1000ffb8 <__iar_annotation$$tailcall+0xa> +1000ffa4: 4622 mov r2, r4 +1000ffa6: 4629 mov r1, r5 +1000ffa8: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +1000ffac: 6ac3 ldr r3, [r0, #44] ; 0x2c + +1000ffae <__iar_annotation$$tailcall>: +1000ffae: 4718 bx r3 +1000ffb0: f20f 4140 addw r1, pc, #1088 ; 0x440 +1000ffb4: f000 f86c bl 10010090 <.text_38+0x2> +1000ffb8: f04f 30ff mov.w r0, #4294967295 +1000ffbc: bd70 pop {r4, r5, r6, pc} + +1000ffbe : +1000ffbe: 2802 cmp r0, #2 +1000ffc0: da00 bge.n 1000ffc4 +1000ffc2: e721 b.n 1000fe08 <.text_23> +1000ffc4: 2000 movs r0, #0 +1000ffc6: 4770 bx lr + +1000ffc8 : +1000ffc8: b5f8 push {r3, r4, r5, r6, r7, lr} +1000ffca: 4604 mov r4, r0 +1000ffcc: f000 fe6e bl 10010cac +1000ffd0: 2018 movs r0, #24 +1000ffd2: 4360 muls r0, r4 +1000ffd4: f8df 6120 ldr.w r6, [pc, #288] ; 100100f8 <.text_51> +1000ffd8: f20f 4534 addw r5, pc, #1076 ; 0x434 +1000ffdc: 1981 adds r1, r0, r6 +1000ffde: 7c09 ldrb r1, [r1, #16] +1000ffe0: b1a9 cbz r1, 1001000e +1000ffe2: 5980 ldr r0, [r0, r6] +1000ffe4: 6b01 ldr r1, [r0, #48] ; 0x30 +1000ffe6: 4788 blx r1 +1000ffe8: 4607 mov r7, r0 +1000ffea: 4629 mov r1, r5 +1000ffec: 6978 ldr r0, [r7, #20] +1000ffee: 9000 str r0, [sp, #0] +1000fff0: 68fb ldr r3, [r7, #12] +1000fff2: 687a ldr r2, [r7, #4] +1000fff4: f20f 402c addw r0, pc, #1068 ; 0x42c +1000fff8: f7fc f983 bl 1000c302 +1000fffc: 6938 ldr r0, [r7, #16] +1000fffe: 9000 str r0, [sp, #0] +10010000: 68bb ldr r3, [r7, #8] +10010002: 683a ldr r2, [r7, #0] +10010004: f20f 4058 addw r0, pc, #1112 ; 0x458 +10010008: 4629 mov r1, r5 +1001000a: f7fc f97a bl 1000c302 +1001000e: f000 fe4f bl 10010cb0 +10010012: bb44 cbnz r4, 10010066 +10010014: f000 fd62 bl 10010adc +10010018: 4603 mov r3, r0 +1001001a: f8df 00f0 ldr.w r0, [pc, #240] ; 1001010c <.text_56> +1001001e: 6802 ldr r2, [r0, #0] +10010020: f20f 4078 addw r0, pc, #1144 ; 0x478 +10010024: 4629 mov r1, r5 +10010026: f7fc f96c bl 1000c302 +1001002a: f8df 00d4 ldr.w r0, [pc, #212] ; 10010100 <.text_53> +1001002e: 6803 ldr r3, [r0, #0] +10010030: f8df 00dc ldr.w r0, [pc, #220] ; 10010110 <.text_57> +10010034: 6802 ldr r2, [r0, #0] +10010036: f20f 409c addw r0, pc, #1180 ; 0x49c +1001003a: 4629 mov r1, r5 +1001003c: f7fc f961 bl 1000c302 +10010040: f8df 00c0 ldr.w r0, [pc, #192] ; 10010104 <.text_54> +10010044: 6803 ldr r3, [r0, #0] +10010046: f8df 00cc ldr.w r0, [pc, #204] ; 10010114 <.text_58> +1001004a: 6802 ldr r2, [r0, #0] +1001004c: f20f 40b8 addw r0, pc, #1208 ; 0x4b8 +10010050: 4629 mov r1, r5 +10010052: f7fc f956 bl 1000c302 +10010056: 6bf2 ldr r2, [r6, #60] ; 0x3c +10010058: f20f 40e0 addw r0, pc, #1248 ; 0x4e0 +1001005c: 4629 mov r1, r5 +1001005e: e8bd 40f8 ldmia.w sp!, {r3, r4, r5, r6, r7, lr} +10010062: f7fc b94e b.w 1000c302 +10010066: bdf1 pop {r0, r4, r5, r6, r7, pc} + +10010068 : +10010068: b580 push {r7, lr} +1001006a: f000 f815 bl 10010098 <.text_40> +1001006e: b141 cbz r1, 10010082 +10010070: 6800 ldr r0, [r0, #0] +10010072: 6900 ldr r0, [r0, #16] +10010074: 6800 ldr r0, [r0, #0] +10010076: f500 50c1 add.w r0, r0, #6176 ; 0x1820 +1001007a: 6800 ldr r0, [r0, #0] +1001007c: f8d0 0308 ldr.w r0, [r0, #776] ; 0x308 +10010080: bd02 pop {r1, pc} +10010082: f20f 41d8 addw r1, pc, #1240 ; 0x4d8 +10010086: f000 f803 bl 10010090 <.text_38+0x2> +1001008a: 2000 movs r0, #0 +1001008c: bd02 pop {r1, pc} + +1001008e <.text_38>: +1001008e: 4621 mov r1, r4 +10010090: f20f 3024 addw r0, pc, #804 ; 0x324 +10010094: f7fc b935 b.w 1000c302 + +10010098 <.text_40>: +10010098: 4817 ldr r0, [pc, #92] ; (100100f8 <.text_51>) +1001009a: 7c01 ldrb r1, [r0, #16] +1001009c: 4770 bx lr + +1001009e : +1001009e: b580 push {r7, lr} +100100a0: 4915 ldr r1, [pc, #84] ; (100100f8 <.text_51>) +100100a2: 7c0a ldrb r2, [r1, #16] +100100a4: b192 cbz r2, 100100cc <.text_42> +100100a6: 6809 ldr r1, [r1, #0] +100100a8: 6909 ldr r1, [r1, #16] +100100aa: 6809 ldr r1, [r1, #0] +100100ac: 2801 cmp r0, #1 +100100ae: f641 0279 movw r2, #6265 ; 0x1879 +100100b2: d102 bne.n 100100ba +100100b4: 5450 strb r0, [r2, r1] +100100b6: 2000 movs r0, #0 +100100b8: bd02 pop {r1, pc} +100100ba: b908 cbnz r0, 100100c0 +100100bc: 5450 strb r0, [r2, r1] +100100be: bd02 pop {r1, pc} +100100c0: f20f 41b4 addw r1, pc, #1204 ; 0x4b4 +100100c4: f20f 40c8 addw r0, pc, #1224 ; 0x4c8 +100100c8: f7fc f91b bl 1000c302 + +100100cc <.text_42>: +100100cc: f04f 30ff mov.w r0, #4294967295 +100100d0: bd02 pop {r1, pc} + +100100d2 : +100100d2: 4809 ldr r0, [pc, #36] ; (100100f8 <.text_51>) +100100d4: 7c01 ldrb r1, [r0, #16] +100100d6: b121 cbz r1, 100100e2 +100100d8: 6800 ldr r0, [r0, #0] +100100da: 6900 ldr r0, [r0, #16] +100100dc: 6800 ldr r0, [r0, #0] +100100de: f003 b9e9 b.w 100134b4 +100100e2: 4770 bx lr + +100100e4 : +100100e4: 4804 ldr r0, [pc, #16] ; (100100f8 <.text_51>) +100100e6: 7c01 ldrb r1, [r0, #16] +100100e8: b121 cbz r1, 100100f4 +100100ea: 6800 ldr r0, [r0, #0] +100100ec: 6900 ldr r0, [r0, #16] +100100ee: 6800 ldr r0, [r0, #0] +100100f0: f003 ba05 b.w 100134fe +100100f4: 4770 bx lr + ... + +100100f8 <.text_51>: +100100f8: 100482dc .word 0x100482dc + +100100fc <.text_52>: +100100fc: 1000fa29 .word 0x1000fa29 + +10010100 <.text_53>: +10010100: 10048818 .word 0x10048818 + +10010104 <.text_54>: +10010104: 10048820 .word 0x10048820 + +10010108 <.text_55>: +10010108: ffff7610 .word 0xffff7610 + +1001010c <.text_56>: +1001010c: 1004833c .word 0x1004833c + +10010110 <.text_57>: +10010110: 1004881c .word 0x1004881c + +10010114 <.text_58>: +10010114: 10048824 .word 0x10048824 + +10010118 : +10010118: 6f6c6c61 74655f63 64726568 00007665 alloc_etherdev.. + +10010128 : +10010128: 255b0d0a 61205d73 636f6c6c 20657461 ..[%s] allocate +10010138: 5f74656e 69766564 66206563 656c6961 net_device faile +10010148: 00002164 d!.. + +1001014c : +1001014c: 255b0d0a 61205d73 636f6c6c 20657461 ..[%s] allocate +1001015c: 657a6973 705f666f 20766972 6c696166 sizeof_priv fail +1001016c: 00216465 ed!. + +10010170 : +10010170: 6e696564 745f7469 72656d69 6172775f deinit_timer_wra +10010180: 72657070 00000000 pper.... + +10010188 : +10010188: 255b0d0a 4e205d73 20646565 64206f74 ..[%s] Need to d +10010198: 74656c65 64252065 6d697420 655f7265 elete %d timer_e +100101a8: 7972746e 00000000 ntry.... + +100101b0 : +100101b0: 656d6974 72775f72 65707061 00000072 timer_wrapper... + +100101c0 : +100101c0: 255b0d0a 46205d73 206c6961 66206f74 ..[%s] Fail to f +100101d0: 20646e69 20656874 656d6974 6e655f72 ind the timer_en +100101e0: 20797274 74206e69 72656d69 62617420 try in timer tab +100101f0: 0000656c le.. + +100101f4 : +100101f4: 74696e69 6d69745f 00007265 init_timer.. + +10010200 : +10010200: 656d6954 00000072 Timer... + +10010208 : +10010208: 255b0d0a 46205d73 206c6961 69206f74 ..[%s] Fail to i +10010218: 2074696e 656d6974 00000072 nit timer... + +10010224 : +10010224: 255b0d0a 46205d73 206c6961 61206f74 ..[%s] Fail to a +10010234: 636f6c6c 6d697420 655f7265 7972746e lloc timer_entry +10010244: 00000000 .... + +10010248 : +10010248: 5f646f6d 656d6974 00000072 mod_timer... + +10010254 : +10010254: 255b0d0a 46205d73 206c6961 73206f74 ..[%s] Fail to s +10010264: 74207465 72656d69 72657020 00646f69 et timer period. + +10010274 : +10010274: 6b746c72 616c775f 6e695f6e 00007469 rltk_wlan_init.. + +10010284 : +10010284: 255b0d0a 75205d73 776f6b6e 6c77206e ..[%s] unkown wl +10010294: 64206e61 63697665 00002165 an device!.. + +100102a0 : +100102a0: 255b0d0a 77205d73 206e616c 74696e69 ..[%s] wlan init +100102b0: 696c6169 6974617a 66206e6f 0a6c6961 ialization fail. +100102c0: 00000000 .... + +100102c4 : +100102c4: 6b746c72 616c775f 65645f6e 74696e69 rltk_wlan_deinit +100102d4: 00000000 .... + +100102d8 : +100102d8: 255b0d0a 57205d73 20746961 20726f66 ..[%s] Wait for +100102e8: 522f5854 75422058 28207973 00296425 TX/RX Busy (%d). + +100102f8 : +100102f8: 255b0d0a 57205d73 20746961 20726f66 ..[%s] Wait for +10010308: 74537852 0000706f RxStop.. + +10010310 : +10010310: 6b746c72 616c775f 74735f6e 00747261 rltk_wlan_start. + +10010320 : +10010320: 255b0d0a 77205d73 206e616c 756f6873 ..[%s] wlan shou +10010330: 6220646c 61632065 64656c6c 206e6920 ld be called in +10010340: 61766461 6465636e 00000021 advanced!... + +1001034c : +1001034c: 6b746c72 616c775f 6c615f6e 5f636f6c rltk_wlan_alloc_ +1001035c: 00626b73 skb. + +10010360 : +10010360: 255b0d0a 73205d73 7562626b 73755f66 ..[%s] skbbuf_us +10010370: 6e5f6465 28206d75 20296425 6f207369 ed_num (%d) is o +10010380: 6f207475 61722066 2165676e 5f58414d ut of range!MAX_ +10010390: 41434f4c 4b535f4c 554e5f42 64253d4d LOCAL_SKB_NUM=%d +100103a0: 0000000a .... + +100103a4 : +100103a4: 6b746c72 616c775f 65735f6e 735f646e rltk_wlan_send_s +100103b4: 0000626b kb.. + +100103b8 : +100103b8: 255b0d0a 6e205d73 66697465 20736920 ..[%s] netif is +100103c8: 4e574f44 00000000 DOWN.... + +100103d0 : +100103d0: 6b746c72 74656e5f 725f6669 00000078 rltk_netif_rx... + +100103e0 : +100103e0: 255b0d0a 73205d73 6920626b 554e2073 ..[%s] skb is NU +100103f0: 00004c4c LL.. + +100103f4 : +100103f4: 6b746c72 616c775f 6f635f6e 6f72746e rltk_wlan_contro +10010404: 0000006c l... + +10010408 : +10010408: 6e616c77 00000030 wlan0... + +10010410 : +10010410: 6b746c72 616c775f 74735f6e 73697461 rltk_wlan_statis +10010420: 00636974 tic. + +10010424 : +10010424: 255b0d0a 74205d73 74732078 203a7461 ..[%s] tx stat: +10010434: 705f7874 656b6361 253d7374 74202c64 tx_packets=%d, t +10010444: 72645f78 6570706f 64253d64 7874202c x_dropped=%d, tx +10010454: 7479625f 253d7365 00000064 _bytes=%d... + +10010460 : +10010460: 255b0d0a 72205d73 74732078 203a7461 ..[%s] rx stat: +10010470: 705f7872 656b6361 253d7374 72202c64 rx_packets=%d, r +10010480: 72645f78 6570706f 64253d64 7872202c x_dropped=%d, rx +10010490: 7479625f 253d7365 00000064 _bytes=%d... + +1001049c : +1001049c: 255b0d0a 6d205d73 665f6e69 5f656572 ..[%s] min_free_ +100104ac: 70616568 7a69735f 64253d65 7563202c heap_size=%d, cu +100104bc: 6e657272 65682074 66207061 20656572 rrent heap free +100104cc: 657a6973 0064253d size=%d. + +100104d4 : +100104d4: 255b0d0a 6d205d73 735f7861 7562626b ..[%s] max_skbbu +100104e4: 73755f66 6e5f6465 253d6d75 73202c64 f_used_num=%d, s +100104f4: 7562626b 73755f66 6e5f6465 253d6d75 kbbuf_used_num=% +10010504: 00000064 d... + +10010508 : +10010508: 255b0d0a 6d205d73 735f7861 6164626b ..[%s] max_skbda +10010518: 755f6174 5f646573 3d6d756e 202c6425 ta_used_num=%d, +10010528: 64626b73 5f617461 64657375 6d756e5f skbdata_used_num +10010538: 0064253d =%d. + +1001053c : +1001053c: 255b0d0a 6d205d73 745f7861 72656d69 ..[%s] max_timer +1001054c: 6573755f 756e5f64 64253d6d 00000000 _used_num=%d.... + +1001055c : +1001055c: 6b746c72 616c775f 61685f6e 6873646e rltk_wlan_handsh +1001056c: 5f656b61 656e6f64 00000000 ake_done.... + +10010578 : +10010578: 6b746c72 616c775f 65735f6e 70775f74 rltk_wlan_set_wp +10010588: 68705f73 00657361 s_phase. + +10010590 : +10010590: 255b0d0a 69205d73 72745f73 65676769 ..[%s] is_trigge +100105a0: 70775f72 61762073 2065756c 756f6873 r_wps value shou +100105b0: 6f20646c 20796c6e 30206562 20726f20 ld only be 0 or +100105c0: 00000031 1... + +100105c4 : +100105c4: b909 cbnz r1, 100105ca +100105c6: f000 00fe and.w r0, r0, #254 ; 0xfe + +100105ca : +100105ca: b2c0 uxtb r0, r0 +100105cc: 2800 cmp r0, #0 +100105ce: bf18 it ne +100105d0: f003 baff bne.w 10013bd2 +100105d4: 4770 bx lr + ... + +100105d8 : +100105d8: b5f8 push {r3, r4, r5, r6, r7, lr} +100105da: 4f34 ldr r7, [pc, #208] ; (100106ac ) +100105dc: 4638 mov r0, r7 +100105de: f7f6 f9f3 bl 100069c8 <__iar_dlib_perthread_access> +100105e2: 4604 mov r4, r0 +100105e4: 1d38 adds r0, r7, #4 +100105e6: f7f6 f9ef bl 100069c8 <__iar_dlib_perthread_access> +100105ea: 4605 mov r5, r0 +100105ec: f107 0008 add.w r0, r7, #8 +100105f0: f7f6 f9ea bl 100069c8 <__iar_dlib_perthread_access> +100105f4: 4606 mov r6, r0 +100105f6: f107 000c add.w r0, r7, #12 +100105fa: f7f6 f9e5 bl 100069c8 <__iar_dlib_perthread_access> +100105fe: 7823 ldrb r3, [r4, #0] +10010600: 492b ldr r1, [pc, #172] ; (100106b0 ) +10010602: 4a2c ldr r2, [pc, #176] ; (100106b4 ) +10010604: 2b00 cmp r3, #0 +10010606: d140 bne.n 1001068a +10010608: 682b ldr r3, [r5, #0] +1001060a: fb02 1303 mla r3, r2, r3, r1 +1001060e: 602b str r3, [r5, #0] +10010610: 2708 movs r7, #8 +10010612: fb02 1303 mla r3, r2, r3, r1 +10010616: 602b str r3, [r5, #0] +10010618: fb02 1303 mla r3, r2, r3, r1 +1001061c: 602b str r3, [r5, #0] +1001061e: fb02 1303 mla r3, r2, r3, r1 +10010622: 602b str r3, [r5, #0] +10010624: fb02 1303 mla r3, r2, r3, r1 +10010628: 602b str r3, [r5, #0] +1001062a: fb02 1303 mla r3, r2, r3, r1 +1001062e: 602b str r3, [r5, #0] +10010630: fb02 1303 mla r3, r2, r3, r1 +10010634: 602b str r3, [r5, #0] +10010636: fb02 1303 mla r3, r2, r3, r1 +1001063a: 602b str r3, [r5, #0] +1001063c: 4603 mov r3, r0 +1001063e: f8d5 c000 ldr.w ip, [r5] +10010642: fb02 1c0c mla ip, r2, ip, r1 +10010646: f8c5 c000 str.w ip, [r5] +1001064a: f843 cb04 str.w ip, [r3], #4 +1001064e: 1e7f subs r7, r7, #1 +10010650: f8d5 c000 ldr.w ip, [r5] +10010654: fb02 1c0c mla ip, r2, ip, r1 +10010658: f8c5 c000 str.w ip, [r5] +1001065c: f843 cb04 str.w ip, [r3], #4 +10010660: f8d5 c000 ldr.w ip, [r5] +10010664: fb02 1c0c mla ip, r2, ip, r1 +10010668: f8c5 c000 str.w ip, [r5] +1001066c: f843 cb04 str.w ip, [r3], #4 +10010670: f8d5 c000 ldr.w ip, [r5] +10010674: fb02 1c0c mla ip, r2, ip, r1 +10010678: f8c5 c000 str.w ip, [r5] +1001067c: f843 cb04 str.w ip, [r3], #4 +10010680: d1dd bne.n 1001063e +10010682: 6fc3 ldr r3, [r0, #124] ; 0x7c +10010684: 6033 str r3, [r6, #0] +10010686: 2301 movs r3, #1 +10010688: 7023 strb r3, [r4, #0] +1001068a: 682b ldr r3, [r5, #0] +1001068c: fb02 1103 mla r1, r2, r3, r1 +10010690: 6029 str r1, [r5, #0] +10010692: 7831 ldrb r1, [r6, #0] +10010694: f001 011f and.w r1, r1, #31 +10010698: f850 2021 ldr.w r2, [r0, r1, lsl #2] +1001069c: 6032 str r2, [r6, #0] +1001069e: 682a ldr r2, [r5, #0] +100106a0: f840 2021 str.w r2, [r0, r1, lsl #2] +100106a4: 6830 ldr r0, [r6, #0] +100106a6: 0080 lsls r0, r0, #2 +100106a8: 0880 lsrs r0, r0, #2 +100106aa: bdf2 pop {r1, r4, r5, r6, r7, pc} +100106ac: 10043c40 .word 0x10043c40 +100106b0: 3c6ef35f .word 0x3c6ef35f +100106b4: 0019660d .word 0x0019660d + +100106b8 <__aeabi_memset>: +100106b8: f362 220f bfi r2, r2, #8, #8 +100106bc: f362 421f bfi r2, r2, #16, #16 + +100106c0 <__iar_Memset_word>: +100106c0: 1840 adds r0, r0, r1 +100106c2: f010 0303 ands.w r3, r0, #3 +100106c6: d008 beq.n 100106da <__iar_Memset_word+0x1a> +100106c8: 1ac9 subs r1, r1, r3 +100106ca: d31f bcc.n 1001070c <__iar_Memset_word+0x4c> +100106cc: 07db lsls r3, r3, #31 +100106ce: bf48 it mi +100106d0: f800 2d01 strbmi.w r2, [r0, #-1]! +100106d4: bf28 it cs +100106d6: f820 2d02 strhcs.w r2, [r0, #-2]! +100106da: 0013 movs r3, r2 +100106dc: b430 push {r4, r5} +100106de: 4614 mov r4, r2 +100106e0: 4615 mov r5, r2 +100106e2: 3910 subs r1, #16 +100106e4: bf28 it cs +100106e6: e920 003c stmdbcs r0!, {r2, r3, r4, r5} +100106ea: d8fa bhi.n 100106e2 <__iar_Memset_word+0x22> +100106ec: 0749 lsls r1, r1, #29 +100106ee: bf28 it cs +100106f0: e920 000c stmdbcs r0!, {r2, r3} +100106f4: bf48 it mi +100106f6: f840 2d04 strmi.w r2, [r0, #-4]! +100106fa: 0089 lsls r1, r1, #2 +100106fc: bf28 it cs +100106fe: f820 2d02 strhcs.w r2, [r0, #-2]! +10010702: bf48 it mi +10010704: f800 2d01 strbmi.w r2, [r0, #-1]! +10010708: bc30 pop {r4, r5} +1001070a: 4770 bx lr +1001070c: 18c9 adds r1, r1, r3 +1001070e: bf18 it ne +10010710: f800 2d01 strbne.w r2, [r0, #-1]! +10010714: 07cb lsls r3, r1, #31 +10010716: bf28 it cs +10010718: f800 2d01 strbcs.w r2, [r0, #-1]! +1001071c: 4770 bx lr + ... + +10010720 <_htons>: +10010720: 0a01 lsrs r1, r0, #8 +10010722: ea41 2000 orr.w r0, r1, r0, lsl #8 +10010726: b280 uxth r0, r0 +10010728: 4770 bx lr + +1001072a <_rtw_zvmalloc>: +1001072a: b510 push {r4, lr} +1001072c: 4604 mov r4, r0 +1001072e: f003 fb6c bl 10013e0a +10010732: b940 cbnz r0, 10010746 <__iar_annotation$$tailcall+0x2> +10010734: f8df 1474 ldr.w r1, [pc, #1140] ; 10010bac <.text_115> +10010738: 6849 ldr r1, [r1, #4] +1001073a: 000a movs r2, r1 +1001073c: d003 beq.n 10010746 <__iar_annotation$$tailcall+0x2> +1001073e: 4620 mov r0, r4 +10010740: e8bd 4010 ldmia.w sp!, {r4, lr} + +10010744 <__iar_annotation$$tailcall>: +10010744: 4708 bx r1 +10010746: bd10 pop {r4, pc} + +10010748 <_rtw_vmfree>: +10010748: f8df 2464 ldr.w r2, [pc, #1124] ; 10010bb0 <.text_116> +1001074c: 1812 adds r2, r2, r0 +1001074e: f64f 73ff movw r3, #65535 ; 0xffff +10010752: 429a cmp r2, r3 +10010754: bf38 it cc +10010756: f003 bb65 bcc.w 10013e24 +1001075a: f8df 2450 ldr.w r2, [pc, #1104] ; 10010bac <.text_115> +1001075e: 6892 ldr r2, [r2, #8] +10010760: 0013 movs r3, r2 +10010762: bf18 it ne + +10010764 <__iar_annotation$$tailcall>: +10010764: 4710 bxne r2 +10010766: 4770 bx lr + +10010768 <_rtw_malloc>: +10010768: f8df 1440 ldr.w r1, [pc, #1088] ; 10010bac <.text_115> +1001076c: 68c9 ldr r1, [r1, #12] +1001076e: 000a movs r2, r1 +10010770: bf18 it ne + +10010772 <__iar_annotation$$tailcall>: +10010772: 4708 bxne r1 +10010774: 2000 movs r0, #0 +10010776: 4770 bx lr + +10010778 <_rtw_zmalloc>: +10010778: f8df 1430 ldr.w r1, [pc, #1072] ; 10010bac <.text_115> +1001077c: 6909 ldr r1, [r1, #16] +1001077e: 000a movs r2, r1 +10010780: bf18 it ne + +10010782 <__iar_annotation$$tailcall>: +10010782: 4708 bxne r1 +10010784: 2000 movs r0, #0 +10010786: 4770 bx lr + +10010788 <_rtw_mfree>: +10010788: f8df 2420 ldr.w r2, [pc, #1056] ; 10010bac <.text_115> +1001078c: 6952 ldr r2, [r2, #20] +1001078e: 0013 movs r3, r2 +10010790: bf18 it ne + +10010792 <__iar_annotation$$tailcall>: +10010792: 4710 bxne r2 +10010794: 4770 bx lr + +10010796 : +10010796: b580 push {r7, lr} +10010798: f000 f9a0 bl 10010adc +1001079c: f8df 1414 ldr.w r1, [pc, #1044] ; 10010bb4 <.text_117> +100107a0: 6008 str r0, [r1, #0] +100107a2: bd01 pop {r0, pc} + +100107a4 : +100107a4: 4770 bx lr + +100107a6 : +100107a6: b538 push {r3, r4, r5, lr} +100107a8: 460c mov r4, r1 +100107aa: 4615 mov r5, r2 +100107ac: f000 f996 bl 10010adc +100107b0: b954 cbnz r4, 100107c8 +100107b2: 462a mov r2, r5 +100107b4: b001 add sp, #4 +100107b6: e8bd 4030 ldmia.w sp!, {r4, r5, lr} +100107ba: 4603 mov r3, r0 +100107bc: f20f 4158 addw r1, pc, #1112 ; 0x458 +100107c0: f20f 4064 addw r0, pc, #1124 ; 0x464 +100107c4: f7fb bd9d b.w 1000c302 +100107c8: f8df 13e8 ldr.w r1, [pc, #1000] ; 10010bb4 <.text_117> +100107cc: 680a ldr r2, [r1, #0] +100107ce: 4290 cmp r0, r2 +100107d0: bfc8 it gt +100107d2: 4610 movgt r0, r2 +100107d4: 6008 str r0, [r1, #0] +100107d6: bd31 pop {r0, r4, r5, pc} + +100107d8 : +100107d8: b538 push {r3, r4, r5, lr} +100107da: 4604 mov r4, r0 +100107dc: f7ff ffa5 bl 1001072a <_rtw_zvmalloc> + +100107e0 <.text_21>: +100107e0: 4605 mov r5, r0 +100107e2: 2001 movs r0, #1 +100107e4: 9000 str r0, [sp, #0] +100107e6: 2300 movs r3, #0 +100107e8: 4622 mov r2, r4 +100107ea: 4629 mov r1, r5 +100107ec: 2000 movs r0, #0 +100107ee: f7ff ffda bl 100107a6 +100107f2: 4628 mov r0, r5 +100107f4: bd32 pop {r1, r4, r5, pc} + +100107f6 : +100107f6: e7a7 b.n 10010748 <_rtw_vmfree> + +100107f8 : +100107f8: b538 push {r3, r4, r5, lr} +100107fa: 4604 mov r4, r0 +100107fc: f7ff ffb4 bl 10010768 <_rtw_malloc> +10010800: e7ee b.n 100107e0 <.text_21> + +10010802 : +10010802: b538 push {r3, r4, r5, lr} +10010804: 4604 mov r4, r0 +10010806: f7ff ffb7 bl 10010778 <_rtw_zmalloc> +1001080a: e7e9 b.n 100107e0 <.text_21> + +1001080c : +1001080c: e7bc b.n 10010788 <_rtw_mfree> + +1001080e : +1001080e: b510 push {r4, lr} +10010810: f8df 3398 ldr.w r3, [pc, #920] ; 10010bac <.text_115> +10010814: 699b ldr r3, [r3, #24] +10010816: 001c movs r4, r3 +10010818: bf1c itt ne +1001081a: e8bd 4010 ldmiane.w sp!, {r4, lr} + +1001081e <__iar_annotation$$tailcall>: +1001081e: 4718 bxne r3 +10010820: bd10 pop {r4, pc} + +10010822 : +10010822: b510 push {r4, lr} +10010824: f8df 3384 ldr.w r3, [pc, #900] ; 10010bac <.text_115> +10010828: 69db ldr r3, [r3, #28] +1001082a: 001c movs r4, r3 +1001082c: bf1c itt ne +1001082e: e8bd 4010 ldmiane.w sp!, {r4, lr} + +10010832 <__iar_annotation$$tailcall>: +10010832: 4718 bxne r3 +10010834: 2000 movs r0, #0 +10010836: bd10 pop {r4, pc} + +10010838 : +10010838: b510 push {r4, lr} +1001083a: f8df 3370 ldr.w r3, [pc, #880] ; 10010bac <.text_115> +1001083e: 6a1b ldr r3, [r3, #32] +10010840: 001c movs r4, r3 +10010842: bf1c itt ne +10010844: e8bd 4010 ldmiane.w sp!, {r4, lr} + +10010848 <__iar_annotation$$tailcall>: +10010848: 4718 bxne r3 +1001084a: bd10 pop {r4, pc} + +1001084c : +1001084c: e00e b.n 1001086c <.text_36> + +1001084e : +1001084e: 6801 ldr r1, [r0, #0] +10010850: 4281 cmp r1, r0 +10010852: d101 bne.n 10010858 +10010854: 2001 movs r0, #1 +10010856: 4770 bx lr +10010858: 2000 movs r0, #0 +1001085a: 4770 bx lr + +1001085c : +1001085c: f000 be0e b.w 1001147c + +10010860 : +10010860: f000 be0e b.w 10011480 + +10010864 : +10010864: 6801 ldr r1, [r0, #0] +10010866: 6842 ldr r2, [r0, #4] +10010868: 604a str r2, [r1, #4] +1001086a: 6011 str r1, [r2, #0] + +1001086c <.text_36>: +1001086c: 6000 str r0, [r0, #0] +1001086e: 6040 str r0, [r0, #4] +10010870: 4770 bx lr + +10010872 : +10010872: f8df 2338 ldr.w r2, [pc, #824] ; 10010bac <.text_115> +10010876: 6a52 ldr r2, [r2, #36] ; 0x24 +10010878: 0013 movs r3, r2 +1001087a: bf18 it ne + +1001087c <__iar_annotation$$tailcall>: +1001087c: 4710 bxne r2 +1001087e: 4770 bx lr + +10010880 : +10010880: f8df 1328 ldr.w r1, [pc, #808] ; 10010bac <.text_115> +10010884: 6a89 ldr r1, [r1, #40] ; 0x28 +10010886: 000a movs r2, r1 +10010888: bf18 it ne + +1001088a <__iar_annotation$$tailcall>: +1001088a: 4708 bxne r1 +1001088c: 4770 bx lr + +1001088e : +1001088e: f8df 131c ldr.w r1, [pc, #796] ; 10010bac <.text_115> +10010892: 6ac9 ldr r1, [r1, #44] ; 0x2c +10010894: 000a movs r2, r1 +10010896: bf18 it ne + +10010898 <__iar_annotation$$tailcall>: +10010898: 4708 bxne r1 +1001089a: 4770 bx lr + +1001089c : +1001089c: f8df 230c ldr.w r2, [pc, #780] ; 10010bac <.text_115> +100108a0: 6b12 ldr r2, [r2, #48] ; 0x30 +100108a2: 0013 movs r3, r2 +100108a4: bf18 it ne + +100108a6 <__iar_annotation$$tailcall>: +100108a6: 4710 bxne r2 +100108a8: 2000 movs r0, #0 +100108aa: 4770 bx lr + +100108ac : +100108ac: b5f8 push {r3, r4, r5, r6, r7, lr} +100108ae: 4604 mov r4, r0 +100108b0: f20f 35d0 addw r5, pc, #976 ; 0x3d0 +100108b4: f20f 36bc addw r6, pc, #956 ; 0x3bc +100108b8: a772 add r7, pc, #456 ; (adr r7, 10010a84 <.text_87>) +100108ba: e007 b.n 100108cc +100108bc: 4638 mov r0, r7 +100108be: f7fb fd20 bl 1000c302 +100108c2: 4622 mov r2, r4 +100108c4: 4631 mov r1, r6 +100108c6: 4628 mov r0, r5 +100108c8: f7fb fd1b bl 1000c302 +100108cc: f04f 31ff mov.w r1, #4294967295 +100108d0: 4620 mov r0, r4 +100108d2: f7ff ffe3 bl 1001089c +100108d6: 2801 cmp r0, #1 +100108d8: d1f0 bne.n 100108bc +100108da: bdf2 pop {r1, r4, r5, r6, r7, pc} + +100108dc : +100108dc: f8df 12cc ldr.w r1, [pc, #716] ; 10010bac <.text_115> +100108e0: 6b49 ldr r1, [r1, #52] ; 0x34 +100108e2: 000a movs r2, r1 +100108e4: bf18 it ne + +100108e6 <__iar_annotation$$tailcall>: +100108e6: 4708 bxne r1 +100108e8: 4770 bx lr + +100108ea : +100108ea: f8df 12c0 ldr.w r1, [pc, #704] ; 10010bac <.text_115> +100108ee: 6b89 ldr r1, [r1, #56] ; 0x38 +100108f0: 000a movs r2, r1 +100108f2: bf18 it ne + +100108f4 <__iar_annotation$$tailcall>: +100108f4: 4708 bxne r1 +100108f6: 4770 bx lr + +100108f8 : +100108f8: f8df 22b0 ldr.w r2, [pc, #688] ; 10010bac <.text_115> +100108fc: 6c52 ldr r2, [r2, #68] ; 0x44 +100108fe: 0013 movs r3, r2 +10010900: bf18 it ne + +10010902 <__iar_annotation$$tailcall>: +10010902: 4710 bxne r2 +10010904: 4770 bx lr + +10010906 : +10010906: f8df 22a4 ldr.w r2, [pc, #676] ; 10010bac <.text_115> +1001090a: 6c92 ldr r2, [r2, #72] ; 0x48 +1001090c: 0013 movs r3, r2 +1001090e: bf18 it ne + +10010910 <__iar_annotation$$tailcall>: +10010910: 4710 bxne r2 +10010912: 4770 bx lr + +10010914 : +10010914: e02d b.n 10010972 + +10010916 : +10010916: e033 b.n 10010980 + +10010918 : +10010918: f8df 2290 ldr.w r2, [pc, #656] ; 10010bac <.text_115> +1001091c: 6d52 ldr r2, [r2, #84] ; 0x54 +1001091e: 0013 movs r3, r2 +10010920: bf18 it ne + +10010922 <__iar_annotation$$tailcall>: +10010922: 4710 bxne r2 +10010924: 2000 movs r0, #0 +10010926: 4770 bx lr + +10010928 : +10010928: f8df 2280 ldr.w r2, [pc, #640] ; 10010bac <.text_115> +1001092c: 6d92 ldr r2, [r2, #88] ; 0x58 +1001092e: 0013 movs r3, r2 +10010930: bf18 it ne + +10010932 <__iar_annotation$$tailcall>: +10010932: 4710 bxne r2 +10010934: 4770 bx lr + +10010936 : +10010936: b510 push {r4, lr} +10010938: 4604 mov r4, r0 +1001093a: f7ff ff87 bl 1001084c +1001093e: f104 0008 add.w r0, r4, #8 +10010942: e8bd 4010 ldmia.w sp!, {r4, lr} +10010946: e006 b.n 10010956 + +10010948 : +10010948: e781 b.n 1001084e + +1001094a : +1001094a: 4288 cmp r0, r1 +1001094c: d101 bne.n 10010952 +1001094e: 2001 movs r0, #1 +10010950: 4770 bx lr +10010952: 2000 movs r0, #0 +10010954: 4770 bx lr + +10010956 : +10010956: f8df 1254 ldr.w r1, [pc, #596] ; 10010bac <.text_115> +1001095a: 6dc9 ldr r1, [r1, #92] ; 0x5c +1001095c: 000a movs r2, r1 +1001095e: bf18 it ne + +10010960 <__iar_annotation$$tailcall>: +10010960: 4708 bxne r1 +10010962: 4770 bx lr + +10010964 : +10010964: f8df 1244 ldr.w r1, [pc, #580] ; 10010bac <.text_115> +10010968: 6e09 ldr r1, [r1, #96] ; 0x60 +1001096a: 000a movs r2, r1 +1001096c: bf18 it ne + +1001096e <__iar_annotation$$tailcall>: +1001096e: 4708 bxne r1 +10010970: 4770 bx lr + +10010972 : +10010972: f8df 1238 ldr.w r1, [pc, #568] ; 10010bac <.text_115> +10010976: 6e49 ldr r1, [r1, #100] ; 0x64 +10010978: 000a movs r2, r1 +1001097a: bf18 it ne + +1001097c <__iar_annotation$$tailcall>: +1001097c: 4708 bxne r1 +1001097e: 4770 bx lr + +10010980 : +10010980: f8df 1228 ldr.w r1, [pc, #552] ; 10010bac <.text_115> +10010984: 6e89 ldr r1, [r1, #104] ; 0x68 +10010986: 000a movs r2, r1 +10010988: bf18 it ne + +1001098a <__iar_annotation$$tailcall>: +1001098a: 4708 bxne r1 +1001098c: 4770 bx lr + +1001098e : +1001098e: 4887 ldr r0, [pc, #540] ; (10010bac <.text_115>) +10010990: f8d0 0084 ldr.w r0, [r0, #132] ; 0x84 +10010994: 0001 movs r1, r0 +10010996: bf18 it ne + +10010998 <__iar_annotation$$tailcall>: +10010998: 4700 bxne r0 +1001099a: 2000 movs r0, #0 +1001099c: 4770 bx lr + +1001099e : +1001099e: 4983 ldr r1, [pc, #524] ; (10010bac <.text_115>) +100109a0: f8d1 1088 ldr.w r1, [r1, #136] ; 0x88 +100109a4: 000a movs r2, r1 +100109a6: bf18 it ne + +100109a8 <__iar_annotation$$tailcall>: +100109a8: 4708 bxne r1 +100109aa: 2000 movs r0, #0 +100109ac: 4770 bx lr + +100109ae : +100109ae: 497f ldr r1, [pc, #508] ; (10010bac <.text_115>) +100109b0: f8d1 108c ldr.w r1, [r1, #140] ; 0x8c +100109b4: 000a movs r2, r1 +100109b6: bf18 it ne + +100109b8 <__iar_annotation$$tailcall>: +100109b8: 4708 bxne r1 +100109ba: 2000 movs r0, #0 +100109bc: 4770 bx lr + +100109be : +100109be: 497b ldr r1, [pc, #492] ; (10010bac <.text_115>) +100109c0: f8d1 1090 ldr.w r1, [r1, #144] ; 0x90 +100109c4: 000a movs r2, r1 +100109c6: bf18 it ne + +100109c8 <__iar_annotation$$tailcall>: +100109c8: 4708 bxne r1 +100109ca: 2000 movs r0, #0 +100109cc: 4770 bx lr + +100109ce : +100109ce: 4977 ldr r1, [pc, #476] ; (10010bac <.text_115>) +100109d0: f8d1 1094 ldr.w r1, [r1, #148] ; 0x94 +100109d4: 000a movs r2, r1 +100109d6: bf18 it ne + +100109d8 <__iar_annotation$$tailcall>: +100109d8: 4708 bxne r1 +100109da: 2000 movs r0, #0 +100109dc: 4770 bx lr + +100109de : +100109de: b510 push {r4, lr} +100109e0: 4604 mov r4, r0 +100109e2: f7ff ffd4 bl 1001098e +100109e6: 1b00 subs r0, r0, r4 +100109e8: e8bd 4010 ldmia.w sp!, {r4, lr} +100109ec: e7d7 b.n 1001099e + +100109ee : +100109ee: 496f ldr r1, [pc, #444] ; (10010bac <.text_115>) +100109f0: f8d1 1098 ldr.w r1, [r1, #152] ; 0x98 +100109f4: 000a movs r2, r1 +100109f6: bf18 it ne + +100109f8 <__iar_annotation$$tailcall>: +100109f8: 4708 bxne r1 +100109fa: 4770 bx lr + +100109fc : +100109fc: 496b ldr r1, [pc, #428] ; (10010bac <.text_115>) +100109fe: f8d1 109c ldr.w r1, [r1, #156] ; 0x9c +10010a02: 000a movs r2, r1 +10010a04: bf18 it ne + +10010a06 <__iar_annotation$$tailcall>: +10010a06: 4708 bxne r1 +10010a08: 4770 bx lr + +10010a0a : +10010a0a: 4968 ldr r1, [pc, #416] ; (10010bac <.text_115>) +10010a0c: f8d1 10a0 ldr.w r1, [r1, #160] ; 0xa0 +10010a10: 000a movs r2, r1 +10010a12: bf18 it ne + +10010a14 <__iar_annotation$$tailcall>: +10010a14: 4708 bxne r1 +10010a16: 4770 bx lr + +10010a18 : +10010a18: 4964 ldr r1, [pc, #400] ; (10010bac <.text_115>) +10010a1a: f8d1 10a4 ldr.w r1, [r1, #164] ; 0xa4 +10010a1e: 000a movs r2, r1 +10010a20: bf18 it ne + +10010a22 <__iar_annotation$$tailcall>: +10010a22: 4708 bxne r1 +10010a24: 4770 bx lr + +10010a26 : +10010a26: b538 push {r3, r4, r5, lr} +10010a28: 4c60 ldr r4, [pc, #384] ; (10010bac <.text_115>) +10010a2a: f8d4 40ac ldr.w r4, [r4, #172] ; 0xac +10010a2e: 0025 movs r5, r4 +10010a30: d002 beq.n 10010a38 +10010a32: 9d04 ldr r5, [sp, #16] +10010a34: 9500 str r5, [sp, #0] +10010a36: 47a0 blx r4 +10010a38: bd31 pop {r0, r4, r5, pc} + +10010a3a : +10010a3a: 4a5c ldr r2, [pc, #368] ; (10010bac <.text_115>) +10010a3c: f8d2 20b0 ldr.w r2, [r2, #176] ; 0xb0 +10010a40: 0013 movs r3, r2 +10010a42: bf18 it ne + +10010a44 <__iar_annotation$$tailcall>: +10010a44: 4710 bxne r2 +10010a46: 4770 bx lr + +10010a48 : +10010a48: b580 push {r7, lr} +10010a4a: 4958 ldr r1, [pc, #352] ; (10010bac <.text_115>) +10010a4c: f8d1 10b4 ldr.w r1, [r1, #180] ; 0xb4 +10010a50: 000a movs r2, r1 +10010a52: bf18 it ne +10010a54: 4788 blxne r1 +10010a56: 2000 movs r0, #0 +10010a58: bd02 pop {r1, pc} + +10010a5a : +10010a5a: 4954 ldr r1, [pc, #336] ; (10010bac <.text_115>) +10010a5c: f8d1 10b8 ldr.w r1, [r1, #184] ; 0xb8 +10010a60: 000a movs r2, r1 +10010a62: bf18 it ne + +10010a64 <__iar_annotation$$tailcall>: +10010a64: 4708 bxne r1 +10010a66: 4770 bx lr + +10010a68 : +10010a68: 4a50 ldr r2, [pc, #320] ; (10010bac <.text_115>) +10010a6a: f8d2 20bc ldr.w r2, [r2, #188] ; 0xbc +10010a6e: 0013 movs r3, r2 +10010a70: bf18 it ne + +10010a72 <__iar_annotation$$tailcall>: +10010a72: 4710 bxne r2 +10010a74: 4770 bx lr + +10010a76 : +10010a76: 494d ldr r1, [pc, #308] ; (10010bac <.text_115>) +10010a78: f8d1 10cc ldr.w r1, [r1, #204] ; 0xcc +10010a7c: 000a movs r2, r1 +10010a7e: bf18 it ne + +10010a80 <__iar_annotation$$tailcall>: +10010a80: 4708 bxne r1 +10010a82: 4770 bx lr + +10010a84 <.text_87>: +10010a84: 00000d0a .word 0x00000d0a + +10010a88 : +10010a88: 4948 ldr r1, [pc, #288] ; (10010bac <.text_115>) +10010a8a: f8d1 10dc ldr.w r1, [r1, #220] ; 0xdc +10010a8e: 000a movs r2, r1 +10010a90: bf18 it ne + +10010a92 <__iar_annotation$$tailcall>: +10010a92: 4708 bxne r1 +10010a94: 2000 movs r0, #0 +10010a96: 4770 bx lr + +10010a98 : +10010a98: 4944 ldr r1, [pc, #272] ; (10010bac <.text_115>) +10010a9a: f8d1 10e0 ldr.w r1, [r1, #224] ; 0xe0 +10010a9e: 000a movs r2, r1 +10010aa0: bf18 it ne + +10010aa2 <__iar_annotation$$tailcall>: +10010aa2: 4708 bxne r1 +10010aa4: 2000 movs r0, #0 +10010aa6: 4770 bx lr + +10010aa8 : +10010aa8: b580 push {r7, lr} +10010aaa: f7ff fff5 bl 10010a98 +10010aae: 1e40 subs r0, r0, #1 +10010ab0: 4180 sbcs r0, r0 +10010ab2: 0fc0 lsrs r0, r0, #31 +10010ab4: bd02 pop {r1, pc} + +10010ab6 : +10010ab6: b538 push {r3, r4, r5, lr} +10010ab8: 4c3c ldr r4, [pc, #240] ; (10010bac <.text_115>) +10010aba: f8d4 40e4 ldr.w r4, [r4, #228] ; 0xe4 +10010abe: 0025 movs r5, r4 +10010ac0: d001 beq.n 10010ac6 +10010ac2: 47a0 blx r4 +10010ac4: bd34 pop {r2, r4, r5, pc} +10010ac6: 2000 movs r0, #0 +10010ac8: 2100 movs r1, #0 +10010aca: bd34 pop {r2, r4, r5, pc} + +10010acc : +10010acc: 4a37 ldr r2, [pc, #220] ; (10010bac <.text_115>) +10010ace: f8d2 20e8 ldr.w r2, [r2, #232] ; 0xe8 +10010ad2: 0013 movs r3, r2 +10010ad4: bf18 it ne + +10010ad6 <__iar_annotation$$tailcall>: +10010ad6: 4710 bxne r2 +10010ad8: 2000 movs r0, #0 +10010ada: 4770 bx lr + +10010adc : +10010adc: 4833 ldr r0, [pc, #204] ; (10010bac <.text_115>) +10010ade: f8d0 00ec ldr.w r0, [r0, #236] ; 0xec +10010ae2: 0001 movs r1, r0 +10010ae4: bf18 it ne + +10010ae6 <__iar_annotation$$tailcall>: +10010ae6: 4700 bxne r0 +10010ae8: 2000 movs r0, #0 +10010aea: 4770 bx lr + +10010aec : +10010aec: 2000 movs r0, #0 +10010aee: 4770 bx lr + +10010af0 : +10010af0: 4770 bx lr + +10010af2 : +10010af2: 4770 bx lr + +10010af4 : +10010af4: 4770 bx lr + +10010af6 : +10010af6: 4770 bx lr + +10010af8 : +10010af8: b530 push {r4, r5, lr} +10010afa: 4c2c ldr r4, [pc, #176] ; (10010bac <.text_115>) +10010afc: f8d4 40f0 ldr.w r4, [r4, #240] ; 0xf0 +10010b00: 0025 movs r5, r4 +10010b02: b083 sub sp, #12 +10010b04: d005 beq.n 10010b12 +10010b06: 9d07 ldr r5, [sp, #28] +10010b08: 9501 str r5, [sp, #4] +10010b0a: 9d06 ldr r5, [sp, #24] +10010b0c: 9500 str r5, [sp, #0] +10010b0e: 47a0 blx r4 +10010b10: bd3e pop {r1, r2, r3, r4, r5, pc} +10010b12: 2001 movs r0, #1 +10010b14: bd3e pop {r1, r2, r3, r4, r5, pc} + +10010b16 : +10010b16: 4925 ldr r1, [pc, #148] ; (10010bac <.text_115>) +10010b18: f8d1 10f4 ldr.w r1, [r1, #244] ; 0xf4 +10010b1c: 000a movs r2, r1 +10010b1e: bf18 it ne + +10010b20 <__iar_annotation$$tailcall>: +10010b20: 4708 bxne r1 +10010b22: 4770 bx lr + +10010b24 : +10010b24: 4921 ldr r1, [pc, #132] ; (10010bac <.text_115>) +10010b26: f8d1 10f8 ldr.w r1, [r1, #248] ; 0xf8 +10010b2a: 000a movs r2, r1 +10010b2c: bf18 it ne + +10010b2e <__iar_annotation$$tailcall>: +10010b2e: 4708 bxne r1 +10010b30: 4770 bx lr + +10010b32 : +10010b32: b538 push {r3, r4, r5, lr} +10010b34: 4c1d ldr r4, [pc, #116] ; (10010bac <.text_115>) +10010b36: f8d4 4104 ldr.w r4, [r4, #260] ; 0x104 +10010b3a: 0025 movs r5, r4 +10010b3c: d003 beq.n 10010b46 +10010b3e: 9d04 ldr r5, [sp, #16] +10010b40: 9500 str r5, [sp, #0] +10010b42: 47a0 blx r4 +10010b44: bd32 pop {r1, r4, r5, pc} +10010b46: 2000 movs r0, #0 +10010b48: bd32 pop {r1, r4, r5, pc} + +10010b4a : +10010b4a: 4a18 ldr r2, [pc, #96] ; (10010bac <.text_115>) +10010b4c: f8d2 2108 ldr.w r2, [r2, #264] ; 0x108 +10010b50: 0013 movs r3, r2 +10010b52: bf18 it ne + +10010b54 <__iar_annotation$$tailcall>: +10010b54: 4710 bxne r2 +10010b56: 2000 movs r0, #0 +10010b58: 4770 bx lr + +10010b5a : +10010b5a: 4914 ldr r1, [pc, #80] ; (10010bac <.text_115>) +10010b5c: f8d1 110c ldr.w r1, [r1, #268] ; 0x10c +10010b60: 000a movs r2, r1 +10010b62: bf18 it ne + +10010b64 <__iar_annotation$$tailcall>: +10010b64: 4708 bxne r1 +10010b66: 2000 movs r0, #0 +10010b68: 4770 bx lr + +10010b6a : +10010b6a: 4a10 ldr r2, [pc, #64] ; (10010bac <.text_115>) +10010b6c: f8d2 2110 ldr.w r2, [r2, #272] ; 0x110 +10010b70: 0013 movs r3, r2 +10010b72: bf18 it ne + +10010b74 <__iar_annotation$$tailcall>: +10010b74: 4710 bxne r2 +10010b76: 2000 movs r0, #0 +10010b78: 4770 bx lr + +10010b7a : +10010b7a: b510 push {r4, lr} +10010b7c: 4b0b ldr r3, [pc, #44] ; (10010bac <.text_115>) +10010b7e: f8d3 3114 ldr.w r3, [r3, #276] ; 0x114 +10010b82: 001c movs r4, r3 +10010b84: bf1c itt ne +10010b86: e8bd 4010 ldmiane.w sp!, {r4, lr} + +10010b8a <__iar_annotation$$tailcall>: +10010b8a: 4718 bxne r3 +10010b8c: 2000 movs r0, #0 +10010b8e: bd10 pop {r4, pc} + +10010b90 : +10010b90: 4906 ldr r1, [pc, #24] ; (10010bac <.text_115>) +10010b92: f8d1 10fc ldr.w r1, [r1, #252] ; 0xfc +10010b96: 000a movs r2, r1 +10010b98: bf18 it ne + +10010b9a <__iar_annotation$$tailcall>: +10010b9a: 4708 bxne r1 +10010b9c: 4770 bx lr + +10010b9e : +10010b9e: 4803 ldr r0, [pc, #12] ; (10010bac <.text_115>) +10010ba0: f8d0 0100 ldr.w r0, [r0, #256] ; 0x100 +10010ba4: 0001 movs r1, r0 +10010ba6: bf18 it ne + +10010ba8 <__iar_annotation$$tailcall>: +10010ba8: 4700 bxne r0 +10010baa: 4770 bx lr + +10010bac <.text_115>: +10010bac: 100042a8 .word 0x100042a8 + +10010bb0 <.text_116>: +10010bb0: e000ffff .word 0xe000ffff + +10010bb4 <.text_117>: +10010bb4: 1004833c .word 0x1004833c + +10010bb8 : +10010bb8: b538 push {r3, r4, r5, lr} +10010bba: 4604 mov r4, r0 +10010bbc: 460d mov r5, r1 +10010bbe: 2008 movs r0, #8 +10010bc0: f7fe fec6 bl 1000f950 +10010bc4: b110 cbz r0, 10010bcc +10010bc6: 6901 ldr r1, [r0, #16] +10010bc8: 600d str r5, [r1, #0] +10010bca: 604c str r4, [r1, #4] +10010bcc: bd32 pop {r1, r4, r5, pc} + +10010bce : +10010bce: b570 push {r4, r5, r6, lr} +10010bd0: 4604 mov r4, r0 +10010bd2: 2008 movs r0, #8 +10010bd4: f7fe febc bl 1000f950 +10010bd8: 0005 movs r5, r0 +10010bda: d00b beq.n 10010bf4 +10010bdc: 692e ldr r6, [r5, #16] +10010bde: 4620 mov r0, r4 +10010be0: f7ff fdfa bl 100107d8 +10010be4: 6030 str r0, [r6, #0] +10010be6: b920 cbnz r0, 10010bf2 +10010be8: 4628 mov r0, r5 +10010bea: f7fe fedc bl 1000f9a6 +10010bee: 2500 movs r5, #0 +10010bf0: e000 b.n 10010bf4 +10010bf2: 6074 str r4, [r6, #4] +10010bf4: 4628 mov r0, r5 +10010bf6: bd70 pop {r4, r5, r6, pc} + +10010bf8 : +10010bf8: b510 push {r4, lr} +10010bfa: 0004 movs r4, r0 +10010bfc: bf1e ittt ne +10010bfe: 6921 ldrne r1, [r4, #16] +10010c00: 6808 ldrne r0, [r1, #0] +10010c02: 2800 cmpne r0, #0 +10010c04: d007 beq.n 10010c16 +10010c06: 6849 ldr r1, [r1, #4] +10010c08: f7ff fdf5 bl 100107f6 +10010c0c: 4620 mov r0, r4 +10010c0e: e8bd 4010 ldmia.w sp!, {r4, lr} +10010c12: f7fe bec8 b.w 1000f9a6 +10010c16: bd10 pop {r4, pc} + +10010c18 : +10010c18: 6461 5f64 656d 5f6d 7375 6761 0065 0000 add_mem_usage... + +10010c28 : +10010c28: 0d0a 255b 5d73 4320 7461 6863 6120 6d20 ..[%s] Catch a m +10010c38: 6d65 6120 6c6c 636f 6620 6961 206c 6977 em alloc fail wi +10010c48: 6874 7320 7a69 2065 666f 2520 2c64 6320 th size of %d, c +10010c58: 7275 6572 746e 6820 6165 2070 7266 6565 urrent heap free +10010c68: 7320 7a69 2065 203d 6425 0000 size = %d.. + +10010c74 : +10010c74: 7472 5f77 6f64 6e77 735f 6d65 0061 0000 rtw_down_sema... + +10010c84 : +10010c84: 5452 384c 3931 4135 445b 6972 6576 5d72 RTL8195A[Driver] +10010c94: 203a 7325 2528 2970 6620 6961 656c 2c64 : %s(%p) failed, +10010ca4: 7220 7465 7972 000a retry.. + +10010cac : +10010cac: f7fa bac0 b.w 1000b230 + +10010cb0 : +10010cb0: f7fa baca b.w 1000b248 + +10010cb4 <_freertos_malloc>: +10010cb4: f7fb bdfe b.w 1000c8b4 + +10010cb8 <_freertos_zmalloc>: +10010cb8: b538 push {r3, r4, r5, lr} +10010cba: 4604 mov r4, r0 +10010cbc: f7fb fdfa bl 1000c8b4 +10010cc0: 0005 movs r5, r0 +10010cc2: d003 beq.n 10010ccc <_freertos_zmalloc+0x14> +10010cc4: 4622 mov r2, r4 +10010cc6: 2100 movs r1, #0 +10010cc8: f7fb fb40 bl 1000c34c +10010ccc: 4628 mov r0, r5 +10010cce: bd32 pop {r1, r4, r5, pc} + +10010cd0 <_freertos_mfree>: +10010cd0: f7fb be77 b.w 1000c9c2 + +10010cd4 <_freertos_memcpy>: +10010cd4: f7fb bb38 b.w 1000c348 + +10010cd8 <_freertos_memcmp>: +10010cd8: b580 push {r7, lr} +10010cda: f7fb fb33 bl 1000c344 +10010cde: b908 cbnz r0, 10010ce4 <_freertos_memcmp+0xc> +10010ce0: 2001 movs r0, #1 +10010ce2: bd02 pop {r1, pc} +10010ce4: 2000 movs r0, #0 +10010ce6: bd02 pop {r1, pc} + +10010ce8 <_freertos_memset>: +10010ce8: f7fb bb30 b.w 1000c34c + +10010cec <_freertos_init_sema>: +10010cec: b510 push {r4, lr} +10010cee: 4604 mov r4, r0 +10010cf0: f04f 30ff mov.w r0, #4294967295 +10010cf4: f7f9 fc39 bl 1000a56a +10010cf8: 6020 str r0, [r4, #0] +10010cfa: bd10 pop {r4, pc} + +10010cfc <_freertos_free_sema>: +10010cfc: b510 push {r4, lr} +10010cfe: e015 b.n 10010d2c <.text_18> + +10010d00 <_freertos_up_sema>: +10010d00: e025 b.n 10010d4e <.text_21> + +10010d02 <_freertos_down_sema>: +10010d02: b510 push {r4, lr} +10010d04: 4604 mov r4, r0 +10010d06: 4608 mov r0, r1 +10010d08: f110 0f01 cmn.w r0, #1 +10010d0c: bf18 it ne +10010d0e: f7ff fe56 blne 100109be +10010d12: 4602 mov r2, r0 +10010d14: 6820 ldr r0, [r4, #0] +10010d16: 2300 movs r3, #0 +10010d18: 2100 movs r1, #0 +10010d1a: f7f9 fcc7 bl 1000a6ac +10010d1e: 2801 cmp r0, #1 +10010d20: bf18 it ne +10010d22: 2000 movne r0, #0 +10010d24: bd10 pop {r4, pc} + +10010d26 <_freertos_mutex_init>: +10010d26: b510 push {r4, lr} +10010d28: e038 b.n 10010d9c <.text_27> + +10010d2a <_freertos_mutex_free>: +10010d2a: b510 push {r4, lr} + +10010d2c <.text_18>: +10010d2c: 4604 mov r4, r0 +10010d2e: 6820 ldr r0, [r4, #0] +10010d30: b108 cbz r0, 10010d36 <.text_18+0xa> +10010d32: f7f9 fd4b bl 1000a7cc +10010d36: 2000 movs r0, #0 +10010d38: 6020 str r0, [r4, #0] +10010d3a: bd10 pop {r4, pc} + +10010d3c <_freertos_mutex_get>: +10010d3c: b570 push {r4, r5, r6, lr} +10010d3e: b082 sub sp, #8 +10010d40: 4604 mov r4, r0 +10010d42: f20f 35f4 addw r5, pc, #1012 ; 0x3f4 +10010d46: f20f 36dc addw r6, pc, #988 ; 0x3dc +10010d4a: e036 b.n 10010dba <.text_30> + +10010d4c <_freertos_mutex_put>: +10010d4c: bf00 nop + +10010d4e <.text_21>: +10010d4e: 2200 movs r2, #0 +10010d50: 6800 ldr r0, [r0, #0] +10010d52: 2300 movs r3, #0 +10010d54: 4611 mov r1, r2 +10010d56: f7f9 bc11 b.w 1000a57c + +10010d5a <_freertos_enter_critical>: +10010d5a: f7fa ba69 b.w 1000b230 + +10010d5e <_freertos_exit_critical>: +10010d5e: f7fa ba73 b.w 1000b248 + +10010d62 <_freertos_enter_critical_mutex>: +10010d62: b570 push {r4, r5, r6, lr} +10010d64: 4604 mov r4, r0 +10010d66: f20f 4514 addw r5, pc, #1044 ; 0x414 +10010d6a: f20f 36f0 addw r6, pc, #1008 ; 0x3f0 +10010d6e: e008 b.n 10010d82 <_freertos_enter_critical_mutex+0x20> +10010d70: 2000 movs r0, #0 +10010d72: f7f9 ffcc bl 1000ad0e +10010d76: 4601 mov r1, r0 +10010d78: 4623 mov r3, r4 +10010d7a: 4632 mov r2, r6 +10010d7c: 4628 mov r0, r5 +10010d7e: f7fb fac0 bl 1000c302 +10010d82: 6820 ldr r0, [r4, #0] +10010d84: 2300 movs r3, #0 +10010d86: f64e 2260 movw r2, #60000 ; 0xea60 +10010d8a: 2100 movs r1, #0 +10010d8c: f7f9 fc8e bl 1000a6ac +10010d90: 2801 cmp r0, #1 +10010d92: d1ed bne.n 10010d70 <_freertos_enter_critical_mutex+0xe> +10010d94: 2000 movs r0, #0 +10010d96: bd70 pop {r4, r5, r6, pc} + +10010d98 <_freertos_exit_critical_mutex>: +10010d98: e7d9 b.n 10010d4e <.text_21> + +10010d9a <_freertos_spinlock_init>: +10010d9a: b510 push {r4, lr} + +10010d9c <.text_27>: +10010d9c: 4604 mov r4, r0 +10010d9e: 2001 movs r0, #1 +10010da0: f7f9 fbbe bl 1000a520 +10010da4: 6020 str r0, [r4, #0] +10010da6: bd10 pop {r4, pc} + +10010da8 <_freertos_spinlock_free>: +10010da8: b510 push {r4, lr} +10010daa: e7bf b.n 10010d2c <.text_18> + +10010dac <_freertos_spinlock>: +10010dac: b570 push {r4, r5, r6, lr} +10010dae: b082 sub sp, #8 +10010db0: 4604 mov r4, r0 +10010db2: f20f 3584 addw r5, pc, #900 ; 0x384 +10010db6: f20f 36e4 addw r6, pc, #996 ; 0x3e4 + +10010dba <.text_30>: +10010dba: e009 b.n 10010dd0 <.text_30+0x16> +10010dbc: 2000 movs r0, #0 +10010dbe: f7f9 ffa6 bl 1000ad0e +10010dc2: 4602 mov r2, r0 +10010dc4: 9400 str r4, [sp, #0] +10010dc6: 4633 mov r3, r6 +10010dc8: 4631 mov r1, r6 +10010dca: 4628 mov r0, r5 +10010dcc: f7fb fa99 bl 1000c302 +10010dd0: 6820 ldr r0, [r4, #0] +10010dd2: 2300 movs r3, #0 +10010dd4: f64e 2260 movw r2, #60000 ; 0xea60 +10010dd8: 2100 movs r1, #0 +10010dda: f7f9 fc67 bl 1000a6ac +10010dde: 2801 cmp r0, #1 +10010de0: d1ec bne.n 10010dbc <.text_30+0x2> +10010de2: bd73 pop {r0, r1, r4, r5, r6, pc} + +10010de4 <_freertos_spinunlock>: +10010de4: e7b3 b.n 10010d4e <.text_21> + +10010de6 <_freertos_spinlock_irqsave>: +10010de6: b570 push {r4, r5, r6, lr} +10010de8: b082 sub sp, #8 +10010dea: 4604 mov r4, r0 +10010dec: f7fa fa20 bl 1000b230 +10010df0: f20f 3544 addw r5, pc, #836 ; 0x344 +10010df4: f20f 36b8 addw r6, pc, #952 ; 0x3b8 +10010df8: e7df b.n 10010dba <.text_30> + +10010dfa <_freertos_spinunlock_irqsave>: +10010dfa: b580 push {r7, lr} +10010dfc: 2200 movs r2, #0 +10010dfe: 6800 ldr r0, [r0, #0] +10010e00: 2300 movs r3, #0 +10010e02: 4611 mov r1, r2 +10010e04: f7f9 fbba bl 1000a57c +10010e08: e8bd 4001 ldmia.w sp!, {r0, lr} +10010e0c: f7fa ba1c b.w 1000b248 + +10010e10 <_freertos_init_xqueue>: +10010e10: b510 push {r4, lr} +10010e12: 4604 mov r4, r0 +10010e14: 4611 mov r1, r2 +10010e16: 4618 mov r0, r3 +10010e18: 2200 movs r2, #0 +10010e1a: f7f9 fb63 bl 1000a4e4 +10010e1e: 6020 str r0, [r4, #0] +10010e20: b910 cbnz r0, 10010e28 <_freertos_init_xqueue+0x18> +10010e22: f04f 30ff mov.w r0, #4294967295 +10010e26: bd10 pop {r4, pc} +10010e28: 2000 movs r0, #0 +10010e2a: bd10 pop {r4, pc} + +10010e2c <_freertos_push_to_xqueue>: +10010e2c: b538 push {r3, r4, r5, lr} +10010e2e: 4604 mov r4, r0 +10010e30: 4610 mov r0, r2 +10010e32: 460d mov r5, r1 +10010e34: f110 0f01 cmn.w r0, #1 +10010e38: bf18 it ne +10010e3a: f7ff fdc0 blne 100109be +10010e3e: 4602 mov r2, r0 +10010e40: 6820 ldr r0, [r4, #0] +10010e42: 2300 movs r3, #0 +10010e44: 4629 mov r1, r5 +10010e46: f7f9 fb99 bl 1000a57c +10010e4a: 2801 cmp r0, #1 +10010e4c: d000 beq.n 10010e50 <_freertos_push_to_xqueue+0x24> +10010e4e: e015 b.n 10010e7c <.text_37> +10010e50: 2000 movs r0, #0 +10010e52: bd32 pop {r1, r4, r5, pc} + +10010e54 <_freertos_pop_from_xqueue>: +10010e54: b538 push {r3, r4, r5, lr} +10010e56: 4604 mov r4, r0 +10010e58: 4610 mov r0, r2 +10010e5a: 460d mov r5, r1 +10010e5c: f110 0f01 cmn.w r0, #1 +10010e60: bf18 it ne +10010e62: f7ff fdac blne 100109be +10010e66: 4602 mov r2, r0 +10010e68: 6820 ldr r0, [r4, #0] +10010e6a: 2300 movs r3, #0 +10010e6c: 4629 mov r1, r5 +10010e6e: f7f9 fc1d bl 1000a6ac +10010e72: 2801 cmp r0, #1 +10010e74: d000 beq.n 10010e78 <_freertos_pop_from_xqueue+0x24> +10010e76: e001 b.n 10010e7c <.text_37> +10010e78: 2000 movs r0, #0 +10010e7a: bd32 pop {r1, r4, r5, pc} + +10010e7c <.text_37>: +10010e7c: f04f 30ff mov.w r0, #4294967295 +10010e80: bd32 pop {r1, r4, r5, pc} + +10010e82 <_freertos_deinit_xqueue>: +10010e82: b538 push {r3, r4, r5, lr} +10010e84: 4604 mov r4, r0 +10010e86: 2500 movs r5, #0 +10010e88: f7f9 fc97 bl 1000a7ba +10010e8c: b108 cbz r0, 10010e92 <_freertos_deinit_xqueue+0x10> +10010e8e: f04f 35ff mov.w r5, #4294967295 +10010e92: 6820 ldr r0, [r4, #0] +10010e94: f7f9 fc9a bl 1000a7cc +10010e98: 4628 mov r0, r5 +10010e9a: bd32 pop {r1, r4, r5, pc} + +10010e9c <_freertos_get_current_time>: +10010e9c: f7f9 bf2d b.w 1000acfa + +10010ea0 <_freertos_systime_to_ms>: +10010ea0: 4770 bx lr + +10010ea2 <_freertos_systime_to_sec>: +10010ea2: f44f 717a mov.w r1, #1000 ; 0x3e8 +10010ea6: fbb0 f0f1 udiv r0, r0, r1 +10010eaa: 4770 bx lr + +10010eac <_freertos_ms_to_systime>: +10010eac: 4770 bx lr + +10010eae <_freertos_sec_to_systime>: +10010eae: f44f 717a mov.w r1, #1000 ; 0x3e8 +10010eb2: 4348 muls r0, r1 +10010eb4: 4770 bx lr + +10010eb6 <_freertos_msleep_os>: +10010eb6: f7f9 be0c b.w 1000aad2 + +10010eba <_freertos_usleep_os>: +10010eba: 4770 bx lr + +10010ebc <_freertos_mdelay_os>: +10010ebc: f7f9 be09 b.w 1000aad2 + +10010ec0 <_freertos_udelay_os>: +10010ec0: f002 bfd3 b.w 10013e6a + +10010ec4 <_freertos_yield_os>: +10010ec4: f7fa b9ab b.w 1000b21e + +10010ec8 <_freertos_init_timer>: +10010ec8: 6082 str r2, [r0, #8] +10010eca: 6043 str r3, [r0, #4] +10010ecc: f7fe bdd5 b.w 1000fa7a + +10010ed0 <_freertos_set_timer>: +10010ed0: f7fe be15 b.w 1000fafe + +10010ed4 <_freertos_cancel_timer_ex>: +10010ed4: b580 push {r7, lr} +10010ed6: f7fe fe79 bl 1000fbcc +10010eda: 2000 movs r0, #0 +10010edc: bd02 pop {r1, pc} + +10010ede <_freertos_del_timer>: +10010ede: f7fe be97 b.w 1000fc10 + +10010ee2 <_freertos_ATOMIC_SET>: +10010ee2: 6001 str r1, [r0, #0] +10010ee4: 4770 bx lr + +10010ee6 <_freertos_ATOMIC_READ>: +10010ee6: 6800 ldr r0, [r0, #0] +10010ee8: 4770 bx lr + +10010eea <_freertos_ATOMIC_ADD>: +10010eea: b538 push {r3, r4, r5, lr} +10010eec: f000 f817 bl 10010f1e <.text_61> +10010ef0: 6820 ldr r0, [r4, #0] +10010ef2: 1828 adds r0, r5, r0 +10010ef4: e004 b.n 10010f00 <.text_57> + +10010ef6 <_freertos_ATOMIC_SUB>: +10010ef6: b538 push {r3, r4, r5, lr} +10010ef8: f000 f811 bl 10010f1e <.text_61> +10010efc: 6820 ldr r0, [r4, #0] +10010efe: 1b40 subs r0, r0, r5 + +10010f00 <.text_57>: +10010f00: 6020 str r0, [r4, #0] +10010f02: e8bd 4031 ldmia.w sp!, {r0, r4, r5, lr} +10010f06: f7fa b99f b.w 1000b248 + +10010f0a <_freertos_ATOMIC_INC>: +10010f0a: 2101 movs r1, #1 +10010f0c: e7ed b.n 10010eea <_freertos_ATOMIC_ADD> + +10010f0e <_freertos_ATOMIC_DEC>: +10010f0e: 2101 movs r1, #1 +10010f10: e7f1 b.n 10010ef6 <_freertos_ATOMIC_SUB> + +10010f12 <_freertos_ATOMIC_ADD_RETURN>: +10010f12: b538 push {r3, r4, r5, lr} +10010f14: f000 f803 bl 10010f1e <.text_61> +10010f18: 6820 ldr r0, [r4, #0] +10010f1a: 182d adds r5, r5, r0 +10010f1c: e008 b.n 10010f30 <.text_63> + +10010f1e <.text_61>: +10010f1e: 4604 mov r4, r0 +10010f20: 460d mov r5, r1 +10010f22: f7fa b985 b.w 1000b230 + +10010f26 <_freertos_ATOMIC_SUB_RETURN>: +10010f26: b538 push {r3, r4, r5, lr} +10010f28: f7ff fff9 bl 10010f1e <.text_61> +10010f2c: 6820 ldr r0, [r4, #0] +10010f2e: 1b45 subs r5, r0, r5 + +10010f30 <.text_63>: +10010f30: 6025 str r5, [r4, #0] +10010f32: f7fa f989 bl 1000b248 +10010f36: 4628 mov r0, r5 +10010f38: bd32 pop {r1, r4, r5, pc} + +10010f3a <_freertos_ATOMIC_INC_RETURN>: +10010f3a: 2101 movs r1, #1 +10010f3c: e7e9 b.n 10010f12 <_freertos_ATOMIC_ADD_RETURN> + +10010f3e <_freertos_ATOMIC_DEC_RETURN>: +10010f3e: 2101 movs r1, #1 +10010f40: e7f1 b.n 10010f26 <_freertos_ATOMIC_SUB_RETURN> + +10010f42 <_freertos_modular64>: +10010f42: b5f0 push {r4, r5, r6, r7, lr} +10010f44: b921 cbnz r1, 10010f50 <_freertos_modular64+0xe> +10010f46: fbb0 f1f2 udiv r1, r0, r2 +10010f4a: fb02 0011 mls r0, r2, r1, r0 +10010f4e: e02e b.n 10010fae <_freertos_modular64+0x6c> +10010f50: 2700 movs r7, #0 +10010f52: 2401 movs r4, #1 +10010f54: 2500 movs r5, #0 +10010f56: 4291 cmp r1, r2 +10010f58: 4616 mov r6, r2 +10010f5a: d30d bcc.n 10010f78 <_freertos_modular64+0x36> +10010f5c: fbb1 f3f2 udiv r3, r1, r2 +10010f60: 4353 muls r3, r2 +10010f62: 1bc0 subs r0, r0, r7 +10010f64: 4199 sbcs r1, r3 +10010f66: e007 b.n 10010f78 <_freertos_modular64+0x36> +10010f68: 007f lsls r7, r7, #1 +10010f6a: 006a lsls r2, r5, #1 +10010f6c: ea47 77d6 orr.w r7, r7, r6, lsr #31 +10010f70: ea42 75d4 orr.w r5, r2, r4, lsr #31 +10010f74: 0076 lsls r6, r6, #1 +10010f76: 0064 lsls r4, r4, #1 +10010f78: 2f00 cmp r7, #0 +10010f7a: bf08 it eq +10010f7c: 2e00 cmpeq r6, #0 +10010f7e: d004 beq.n 10010f8a <_freertos_modular64+0x48> +10010f80: 428f cmp r7, r1 +10010f82: d3f1 bcc.n 10010f68 <_freertos_modular64+0x26> +10010f84: d801 bhi.n 10010f8a <_freertos_modular64+0x48> +10010f86: 4286 cmp r6, r0 +10010f88: d3ee bcc.n 10010f68 <_freertos_modular64+0x26> +10010f8a: 42b9 cmp r1, r7 +10010f8c: d304 bcc.n 10010f98 <_freertos_modular64+0x56> +10010f8e: d801 bhi.n 10010f94 <_freertos_modular64+0x52> +10010f90: 42b0 cmp r0, r6 +10010f92: d301 bcc.n 10010f98 <_freertos_modular64+0x56> +10010f94: 1b80 subs r0, r0, r6 +10010f96: 41b9 sbcs r1, r7 +10010f98: 0876 lsrs r6, r6, #1 +10010f9a: ea46 76c7 orr.w r6, r6, r7, lsl #31 +10010f9e: 0862 lsrs r2, r4, #1 +10010fa0: 087f lsrs r7, r7, #1 +10010fa2: ea42 74c5 orr.w r4, r2, r5, lsl #31 +10010fa6: 086d lsrs r5, r5, #1 +10010fa8: bf08 it eq +10010faa: 2c00 cmpeq r4, #0 +10010fac: d1ed bne.n 10010f8a <_freertos_modular64+0x48> +10010fae: 2100 movs r1, #0 +10010fb0: bdf0 pop {r4, r5, r6, r7, pc} + +10010fb2 <_freertos_arc4random>: +10010fb2: b510 push {r4, lr} +10010fb4: f7f9 fea1 bl 1000acfa +10010fb8: 4907 ldr r1, [pc, #28] ; (10010fd8 <.text_68>) +10010fba: 4b08 ldr r3, [pc, #32] ; (10010fdc <.text_69>) +10010fbc: 680a ldr r2, [r1, #0] +10010fbe: 4c08 ldr r4, [pc, #32] ; (10010fe0 <.text_70>) +10010fc0: 4013 ands r3, r2 +10010fc2: ea04 2212 and.w r2, r4, r2, lsr #8 +10010fc6: ea82 12c3 eor.w r2, r2, r3, lsl #7 +10010fca: ea82 3240 eor.w r2, r2, r0, lsl #13 +10010fce: ea82 2050 eor.w r0, r2, r0, lsr #9 +10010fd2: 6008 str r0, [r1, #0] +10010fd4: bd10 pop {r4, pc} + ... + +10010fd8 <.text_68>: +10010fd8: 1004416c .word 0x1004416c + +10010fdc <.text_69>: +10010fdc: 007f00ff .word 0x007f00ff + +10010fe0 <.text_70>: +10010fe0: 000f80ff .word 0x000f80ff + +10010fe4 <_freertos_get_random_bytes>: +10010fe4: b5f8 push {r3, r4, r5, r6, r7, lr} +10010fe6: 460d mov r5, r1 +10010fe8: 4604 mov r4, r0 +10010fea: 08ae lsrs r6, r5, #2 +10010fec: 2700 movs r7, #0 +10010fee: e005 b.n 10010ffc <_freertos_get_random_bytes+0x18> +10010ff0: f7ff ffdf bl 10010fb2 <_freertos_arc4random> +10010ff4: f844 0027 str.w r0, [r4, r7, lsl #2] +10010ff8: 1f2d subs r5, r5, #4 +10010ffa: 1c7f adds r7, r7, #1 +10010ffc: 42b7 cmp r7, r6 +10010ffe: dbf7 blt.n 10010ff0 <_freertos_get_random_bytes+0xc> +10011000: b145 cbz r5, 10011014 <_freertos_get_random_bytes+0x30> +10011002: f7ff ffd6 bl 10010fb2 <_freertos_arc4random> +10011006: 9000 str r0, [sp, #0] +10011008: 462a mov r2, r5 +1001100a: a900 add r1, sp, #0 +1001100c: eb04 0087 add.w r0, r4, r7, lsl #2 +10011010: f7ff fe60 bl 10010cd4 <_freertos_memcpy> +10011014: 2000 movs r0, #0 +10011016: bdf2 pop {r1, r4, r5, r6, r7, pc} + +10011018 <_freertos_GetFreeHeapSize>: +10011018: f7fb bce0 b.w 1000c9dc + +1001101c <_freertos_create_task>: +1001101c: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} +10011020: 4604 mov r4, r0 +10011022: b085 sub sp, #20 +10011024: 460d mov r5, r1 +10011026: 2700 movs r7, #0 +10011028: 6025 str r5, [r4, #0] +1001102a: 6127 str r7, [r4, #16] +1001102c: 4616 mov r6, r2 +1001102e: 4698 mov r8, r3 +10011030: 46b9 mov r9, r7 +10011032: 6167 str r7, [r4, #20] +10011034: 2100 movs r1, #0 +10011036: f104 0008 add.w r0, r4, #8 +1001103a: f7ff fe57 bl 10010cec <_freertos_init_sema> +1001103e: 4639 mov r1, r7 +10011040: f104 000c add.w r0, r4, #12 +10011044: f7ff fe52 bl 10010cec <_freertos_init_sema> +10011048: 980c ldr r0, [sp, #48] ; 0x30 +1001104a: 0001 movs r1, r0 +1001104c: bf1c itt ne +1001104e: 4607 movne r7, r0 +10011050: f8dd 9034 ldrne.w r9, [sp, #52] ; 0x34 +10011054: 00b0 lsls r0, r6, #2 +10011056: f002 fecf bl 10013df8 +1001105a: 9002 str r0, [sp, #8] +1001105c: 2100 movs r1, #0 +1001105e: 1d20 adds r0, r4, #4 +10011060: 9001 str r0, [sp, #4] +10011062: 9103 str r1, [sp, #12] +10011064: f108 0004 add.w r0, r8, #4 +10011068: 9000 str r0, [sp, #0] +1001106a: 464b mov r3, r9 +1001106c: b2b2 uxth r2, r6 +1001106e: 4629 mov r1, r5 +10011070: 4638 mov r0, r7 +10011072: f7f9 fc59 bl 1000a928 +10011076: 4605 mov r5, r0 +10011078: 2d01 cmp r5, #1 +1001107a: d007 beq.n 1001108c <_freertos_create_task+0x70> +1001107c: 6822 ldr r2, [r4, #0] +1001107e: f20f 114c addw r1, pc, #332 ; 0x14c +10011082: f20f 1060 addw r0, pc, #352 ; 0x160 +10011086: 462b mov r3, r5 +10011088: f7fb f93b bl 1000c302 +1001108c: 4628 mov r0, r5 +1001108e: b005 add sp, #20 +10011090: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + +10011094 <_freertos_delete_task>: +10011094: b510 push {r4, lr} +10011096: 4604 mov r4, r0 +10011098: 6860 ldr r0, [r4, #4] +1001109a: b938 cbnz r0, 100110ac <_freertos_delete_task+0x18> +1001109c: e8bd 4010 ldmia.w sp!, {r4, lr} +100110a0: f20f 1168 addw r1, pc, #360 ; 0x168 +100110a4: f20f 107c addw r0, pc, #380 ; 0x17c +100110a8: f7fb b92b b.w 1000c302 +100110ac: 2001 movs r0, #1 +100110ae: 6120 str r0, [r4, #16] +100110b0: f104 0008 add.w r0, r4, #8 +100110b4: f7ff fe24 bl 10010d00 <_freertos_up_sema> +100110b8: f04f 31ff mov.w r1, #4294967295 +100110bc: f104 000c add.w r0, r4, #12 +100110c0: f7ff fe1f bl 10010d02 <_freertos_down_sema> +100110c4: f104 0008 add.w r0, r4, #8 +100110c8: f7ff fe18 bl 10010cfc <_freertos_free_sema> +100110cc: f104 000c add.w r0, r4, #12 +100110d0: f7ff fe14 bl 10010cfc <_freertos_free_sema> +100110d4: 2000 movs r0, #0 +100110d6: 6060 str r0, [r4, #4] +100110d8: bd10 pop {r4, pc} + +100110da <_freertos_wakeup_task>: +100110da: 3008 adds r0, #8 +100110dc: e610 b.n 10010d00 <_freertos_up_sema> + +100110de <_freertos_thread_enter>: +100110de: 4770 bx lr + +100110e0 <_freertos_thread_exit>: +100110e0: 2000 movs r0, #0 +100110e2: f7f9 bcad b.w 1000aa40 + +100110e6 <_freertos_timerCreate>: +100110e6: b510 push {r4, lr} +100110e8: b082 sub sp, #8 +100110ea: 9c04 ldr r4, [sp, #16] +100110ec: 9400 str r4, [sp, #0] +100110ee: f7fb fcba bl 1000ca66 +100110f2: bd16 pop {r1, r2, r4, pc} + +100110f4 <_freertos_timerDelete>: +100110f4: b580 push {r7, lr} +100110f6: 9100 str r1, [sp, #0] +100110f8: 2300 movs r3, #0 +100110fa: 2200 movs r2, #0 +100110fc: 2105 movs r1, #5 +100110fe: e006 b.n 1001110e <.text_82> + +10011100 <_freertos_timerIsTimerActive>: +10011100: f7fb bdff b.w 1000cd02 + +10011104 <_freertos_timerStop>: +10011104: b580 push {r7, lr} +10011106: 9100 str r1, [sp, #0] +10011108: 2300 movs r3, #0 +1001110a: 2200 movs r2, #0 +1001110c: 2103 movs r1, #3 + +1001110e <.text_82>: +1001110e: f7fb fcc7 bl 1000caa0 +10011112: bd02 pop {r1, pc} + +10011114 <_freertos_timerChangePeriod>: +10011114: b580 push {r7, lr} +10011116: b901 cbnz r1, 1001111a <_freertos_timerChangePeriod+0x6> +10011118: 2101 movs r1, #1 +1001111a: 9200 str r2, [sp, #0] +1001111c: 2300 movs r3, #0 +1001111e: 460a mov r2, r1 +10011120: 2104 movs r1, #4 +10011122: e7f4 b.n 1001110e <.text_82> + +10011124 : +10011124: 665f 6572 7265 6f74 5f73 756d 6574 5f78 _freertos_mutex_ +10011134: 6567 0074 get. + +10011138 : +10011138: 0d0a 255b 5d73 5b20 7325 205d 7325 2528 ..[%s] [%s] %s(% +10011148: 2970 6620 6961 656c 2c64 7220 7465 7972 p) failed, retry +10011158: 000a 0000 .... + +1001115c : +1001115c: 665f 6572 7265 6f74 5f73 6e65 6574 5f72 _freertos_enter_ +1001116c: 7263 7469 6369 6c61 6d5f 7475 7865 0000 critical_mutex.. + +1001117c : +1001117c: 0d0a 255b 5d73 2520 2873 7025 2029 6166 ..[%s] %s(%p) fa +1001118c: 6c69 6465 202c 6572 7274 0a79 0000 0000 iled, retry..... + +1001119c : +1001119c: 665f 6572 7265 6f74 5f73 7073 6e69 6f6c _freertos_spinlo +100111ac: 6b63 0000 ck.. + +100111b0 : +100111b0: 665f 6572 7265 6f74 5f73 7073 6e69 6f6c _freertos_spinlo +100111c0: 6b63 695f 7172 6173 6576 0000 ck_irqsave.. + +100111cc : +100111cc: 665f 6572 7265 6f74 5f73 7263 6165 6574 _freertos_create +100111dc: 745f 7361 006b 0000 _task... + +100111e4 : +100111e4: 0d0a 255b 5d73 4320 6572 7461 2065 6154 ..[%s] Create Ta +100111f4: 6b73 2220 7325 2022 6146 6c69 6465 2021 sk "%s" Failed! +10011204: 6572 3d74 6425 000a ret=%d.. + +1001120c : +1001120c: 665f 6572 7265 6f74 5f73 6564 656c 6574 _freertos_delete +1001121c: 745f 7361 006b 0000 _task... + +10011224 : +10011224: 0d0a 255b 5d73 5f20 7266 6565 7472 736f ..[%s] _freertos +10011234: 645f 6c65 7465 5f65 6174 6b73 2928 203a _delete_task(): +10011244: 7470 7361 206b 7369 4e20 4c55 214c 000a ptask is NULL!.. + +10011254 <__list_add>: +10011254: 6050 str r0, [r2, #4] +10011256: 6002 str r2, [r0, #0] +10011258: 6041 str r1, [r0, #4] +1001125a: 6008 str r0, [r1, #0] +1001125c: 4770 bx lr + +1001125e : +1001125e: 6802 ldr r2, [r0, #0] +10011260: 4282 cmp r2, r0 +10011262: d101 bne.n 10011268 +10011264: 2000 movs r0, #0 +10011266: 4770 bx lr +10011268: 6810 ldr r0, [r2, #0] +1001126a: 6853 ldr r3, [r2, #4] +1001126c: 6043 str r3, [r0, #4] +1001126e: 6018 str r0, [r3, #0] +10011270: 6012 str r2, [r2, #0] +10011272: 6052 str r2, [r2, #4] +10011274: 6808 ldr r0, [r1, #0] +10011276: 1c40 adds r0, r0, #1 +10011278: 6008 str r0, [r1, #0] +1001127a: f102 0008 add.w r0, r2, #8 +1001127e: 4770 bx lr + +10011280 : +10011280: b510 push {r4, lr} +10011282: 4614 mov r4, r2 +10011284: 3808 subs r0, #8 +10011286: f000 f8fb bl 10011480 +1001128a: 6820 ldr r0, [r4, #0] +1001128c: 1e40 subs r0, r0, #1 +1001128e: 6020 str r0, [r4, #0] +10011290: bd10 pop {r4, pc} + +10011292 : +10011292: b570 push {r4, r5, r6, lr} +10011294: 4c75 ldr r4, [pc, #468] ; (1001146c <.text_27>) +10011296: f44f 629a mov.w r2, #1232 ; 0x4d0 +1001129a: f000 f824 bl 100112e6 <.text_11> +1001129e: 4d74 ldr r5, [pc, #464] ; (10011470 <.text_28>) +100112a0: 602d str r5, [r5, #0] +100112a2: 606d str r5, [r5, #4] +100112a4: 2600 movs r6, #0 +100112a6: 202c movs r0, #44 ; 0x2c +100112a8: f000 f821 bl 100112ee <.text_12> +100112ac: 1c76 adds r6, r6, #1 +100112ae: 2e1c cmp r6, #28 +100112b0: dbf9 blt.n 100112a6 +100112b2: 2000 movs r0, #0 +100112b4: 60a8 str r0, [r5, #8] +100112b6: 60e8 str r0, [r5, #12] +100112b8: bd70 pop {r4, r5, r6, pc} + +100112ba : +100112ba: b570 push {r4, r5, r6, lr} +100112bc: 4c6d ldr r4, [pc, #436] ; (10011474 <.text_29>) +100112be: f44f 429c mov.w r2, #19968 ; 0x4e00 +100112c2: f000 f810 bl 100112e6 <.text_11> +100112c6: 4d6c ldr r5, [pc, #432] ; (10011478 <.text_30>) +100112c8: 602d str r5, [r5, #0] +100112ca: 606d str r5, [r5, #4] +100112cc: 2600 movs r6, #0 +100112ce: f44f 60d0 mov.w r0, #1664 ; 0x680 +100112d2: f000 f80c bl 100112ee <.text_12> +100112d6: 1c76 adds r6, r6, #1 +100112d8: 2e0c cmp r6, #12 +100112da: dbf8 blt.n 100112ce +100112dc: 4864 ldr r0, [pc, #400] ; (10011470 <.text_28>) +100112de: 2100 movs r1, #0 +100112e0: 6101 str r1, [r0, #16] +100112e2: 6141 str r1, [r0, #20] +100112e4: bd70 pop {r4, r5, r6, pc} + +100112e6 <.text_11>: +100112e6: 2100 movs r1, #0 +100112e8: 4620 mov r0, r4 +100112ea: f7fb b82f b.w 1000c34c + +100112ee <.text_12>: +100112ee: 4370 muls r0, r6 +100112f0: 1901 adds r1, r0, r4 +100112f2: 5101 str r1, [r0, r4] +100112f4: 1900 adds r0, r0, r4 +100112f6: 4629 mov r1, r5 +100112f8: 6040 str r0, [r0, #4] +100112fa: e0c1 b.n 10011480 + +100112fc : +100112fc: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +10011300: 4605 mov r5, r0 +10011302: f7ff fcd3 bl 10010cac +10011306: 4e5a ldr r6, [pc, #360] ; (10011470 <.text_28>) +10011308: f106 0108 add.w r1, r6, #8 +1001130c: 4630 mov r0, r6 +1001130e: f7ff ffa6 bl 1001125e +10011312: 4604 mov r4, r0 +10011314: f7ff fccc bl 10010cb0 +10011318: f20f 186c addw r8, pc, #364 ; 0x16c +1001131c: b92c cbnz r4, 1001132a +1001131e: 4641 mov r1, r8 +10011320: f20f 1070 addw r0, pc, #368 ; 0x170 +10011324: f7fa ffed bl 1000c302 +10011328: e01c b.n 10011364 +1001132a: 2224 movs r2, #36 ; 0x24 +1001132c: f7ff ffdb bl 100112e6 <.text_11> +10011330: f7ff fcbc bl 10010cac +10011334: f106 0110 add.w r1, r6, #16 +10011338: 484f ldr r0, [pc, #316] ; (10011478 <.text_30>) +1001133a: f7ff ff90 bl 1001125e +1001133e: 4607 mov r7, r0 +10011340: f7ff fcb6 bl 10010cb0 +10011344: b987 cbnz r7, 10011368 +10011346: f20f 1064 addw r0, pc, #356 ; 0x164 +1001134a: 4641 mov r1, r8 +1001134c: f7fa ffd9 bl 1000c302 +10011350: f7ff fcac bl 10010cac +10011354: f106 0208 add.w r2, r6, #8 +10011358: 4631 mov r1, r6 +1001135a: 4620 mov r0, r4 +1001135c: f7ff ff90 bl 10011280 +10011360: f7ff fca6 bl 10010cb0 +10011364: 2000 movs r0, #0 +10011366: e017 b.n 10011398 +10011368: 68b0 ldr r0, [r6, #8] +1001136a: 68f1 ldr r1, [r6, #12] +1001136c: 4281 cmp r1, r0 +1001136e: bfb8 it lt +10011370: 60f0 strlt r0, [r6, #12] +10011372: 6930 ldr r0, [r6, #16] +10011374: 6971 ldr r1, [r6, #20] +10011376: 4281 cmp r1, r0 +10011378: bfb8 it lt +1001137a: 6170 strlt r0, [r6, #20] +1001137c: 1ce8 adds r0, r5, #3 +1001137e: f020 0203 bic.w r2, r0, #3 +10011382: 4639 mov r1, r7 +10011384: 4620 mov r0, r4 +10011386: f000 f842 bl 1001140e +1001138a: 68e0 ldr r0, [r4, #12] +1001138c: 2108 movs r1, #8 +1001138e: 1a40 subs r0, r0, r1 +10011390: 2101 movs r1, #1 +10011392: f8c0 167c str.w r1, [r0, #1660] ; 0x67c +10011396: 4620 mov r0, r4 +10011398: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +1001139c : +1001139c: b538 push {r3, r4, r5, lr} +1001139e: 1cc9 adds r1, r1, #3 +100113a0: 088c lsrs r4, r1, #2 +100113a2: eb00 0084 add.w r0, r0, r4, lsl #2 +100113a6: f7ff ffa9 bl 100112fc +100113aa: 0005 movs r5, r0 +100113ac: bf1c itt ne +100113ae: 00a1 lslne r1, r4, #2 +100113b0: f000 f828 blne 10011404 +100113b4: 4628 mov r0, r5 +100113b6: bd32 pop {r1, r4, r5, pc} + +100113b8 : +100113b8: b538 push {r3, r4, r5, lr} +100113ba: 4604 mov r4, r0 +100113bc: f7ff fc76 bl 10010cac +100113c0: 68e0 ldr r0, [r4, #12] +100113c2: 4d2b ldr r5, [pc, #172] ; (10011470 <.text_28>) +100113c4: 2108 movs r1, #8 +100113c6: 1a40 subs r0, r0, r1 +100113c8: f200 607c addw r0, r0, #1660 ; 0x67c +100113cc: f7ff fb6c bl 10010aa8 +100113d0: b128 cbz r0, 100113de +100113d2: 68e0 ldr r0, [r4, #12] +100113d4: 4928 ldr r1, [pc, #160] ; (10011478 <.text_30>) +100113d6: f105 0210 add.w r2, r5, #16 +100113da: f7ff ff51 bl 10011280 +100113de: f105 0208 add.w r2, r5, #8 +100113e2: 4629 mov r1, r5 +100113e4: 4620 mov r0, r4 +100113e6: f7ff ff4b bl 10011280 +100113ea: e8bd 4031 ldmia.w sp!, {r0, r4, r5, lr} +100113ee: f7ff bc5f b.w 10010cb0 + +100113f2 : +100113f2: e7e1 b.n 100113b8 + +100113f4 : +100113f4: 6942 ldr r2, [r0, #20] +100113f6: 188b adds r3, r1, r2 +100113f8: 6143 str r3, [r0, #20] +100113fa: 6a03 ldr r3, [r0, #32] +100113fc: 18c9 adds r1, r1, r3 +100113fe: 6201 str r1, [r0, #32] +10011400: 4610 mov r0, r2 +10011402: 4770 bx lr + +10011404 : +10011404: 6902 ldr r2, [r0, #16] +10011406: 188a adds r2, r1, r2 +10011408: 6102 str r2, [r0, #16] +1001140a: 6942 ldr r2, [r0, #20] +1001140c: e008 b.n 10011420 <.text_23> + +1001140e : +1001140e: 60c1 str r1, [r0, #12] +10011410: 6101 str r1, [r0, #16] +10011412: 6141 str r1, [r0, #20] +10011414: 1851 adds r1, r2, r1 +10011416: 6181 str r1, [r0, #24] +10011418: 4770 bx lr + +1001141a : +1001141a: 6980 ldr r0, [r0, #24] +1001141c: 4770 bx lr + +1001141e : +1001141e: 6902 ldr r2, [r0, #16] + +10011420 <.text_23>: +10011420: 1889 adds r1, r1, r2 +10011422: 6141 str r1, [r0, #20] +10011424: 4770 bx lr + +10011426 : +10011426: 6a02 ldr r2, [r0, #32] +10011428: 428a cmp r2, r1 +1001142a: d201 bcs.n 10011430 +1001142c: 2000 movs r0, #0 +1001142e: 4770 bx lr +10011430: 1a52 subs r2, r2, r1 +10011432: 6202 str r2, [r0, #32] +10011434: 6902 ldr r2, [r0, #16] +10011436: 1889 adds r1, r1, r2 +10011438: 6101 str r1, [r0, #16] +1001143a: 4608 mov r0, r1 +1001143c: 4770 bx lr + +1001143e : +1001143e: b538 push {r3, r4, r5, lr} +10011440: 4604 mov r4, r0 +10011442: 4611 mov r1, r2 +10011444: 6a20 ldr r0, [r4, #32] +10011446: f7ff ffa9 bl 1001139c +1001144a: 0005 movs r5, r0 +1001144c: d101 bne.n 10011452 +1001144e: 2000 movs r0, #0 +10011450: bd32 pop {r1, r4, r5, pc} +10011452: 6a21 ldr r1, [r4, #32] +10011454: f7ff ffce bl 100113f4 +10011458: 6a22 ldr r2, [r4, #32] +1001145a: 6921 ldr r1, [r4, #16] +1001145c: 6928 ldr r0, [r5, #16] +1001145e: f7fa ff73 bl 1000c348 +10011462: 69e0 ldr r0, [r4, #28] +10011464: 61e8 str r0, [r5, #28] +10011466: 4628 mov r0, r5 +10011468: bd32 pop {r1, r4, r5, pc} + ... + +1001146c <.text_27>: +1001146c: 10048340 .word 0x10048340 + +10011470 <.text_28>: +10011470: 10048810 .word 0x10048810 + +10011474 <.text_29>: +10011474: 10048c8c .word 0x10048c8c + +10011478 <.text_30>: +10011478: 1004da8c .word 0x1004da8c + +1001147c : +1001147c: 680a ldr r2, [r1, #0] +1001147e: e6e9 b.n 10011254 <__list_add> + +10011480 : +10011480: 460a mov r2, r1 +10011482: 6849 ldr r1, [r1, #4] +10011484: e6e6 b.n 10011254 <__list_add> + ... + +10011488 : +10011488: 6c61 6f6c 5f63 6b73 0062 0000 alloc_skb... + +10011494 : +10011494: 0d0a 255b 5d73 5720 6961 2074 6f66 2072 ..[%s] Wait for +100114a4: 6b73 6262 6675 0000 skbbuf.. + +100114ac : +100114ac: 0d0a 255b 5d73 5720 6961 2074 6f66 2072 ..[%s] Wait for +100114bc: 6b73 6462 7461 0a61 0000 0000 skbdata..... + +100114c8 : +100114c8: 6840 ldr r0, [r0, #4] +100114ca: 4208 tst r0, r1 +100114cc: d001 beq.n 100114d2 +100114ce: 2001 movs r0, #1 +100114d0: 4770 bx lr +100114d2: 2000 movs r0, #0 +100114d4: 4770 bx lr + +100114d6 : +100114d6: f002 bd37 b.w 10013f48 + +100114da : +100114da: f002 bd1e b.w 10013f1a + +100114de : +100114de: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +100114e2: 4604 mov r4, r0 +100114e4: f241 10f0 movw r0, #4592 ; 0x11f0 +100114e8: b083 sub sp, #12 +100114ea: 1905 adds r5, r0, r4 +100114ec: 5900 ldr r0, [r0, r4] +100114ee: 2802 cmp r0, #2 +100114f0: d15d bne.n 100115ae +100114f2: f241 697c movw r9, #5756 ; 0x167c +100114f6: eb09 0b04 add.w fp, r9, r4 +100114fa: f819 0004 ldrb.w r0, [r9, r4] +100114fe: f88d 0004 strb.w r0, [sp, #4] +10011502: f641 0618 movw r6, #6168 ; 0x1818 +10011506: f8db 8004 ldr.w r8, [fp, #4] +1001150a: f44f 5ac1 mov.w sl, #6176 ; 0x1820 +1001150e: 2110 movs r1, #16 +10011510: f000 fcc7 bl 10011ea2 <.text_31> +10011514: 2801 cmp r0, #1 +10011516: d10c bne.n 10011532 +10011518: 2700 movs r7, #0 +1001151a: eb04 0087 add.w r0, r4, r7, lsl #2 +1001151e: f85a 0000 ldr.w r0, [sl, r0] +10011522: f500 703d add.w r0, r0, #756 ; 0x2f4 +10011526: f7ff fa8f bl 10010a48 +1001152a: 1c7f adds r7, r7, #1 +1001152c: 2f03 cmp r7, #3 +1001152e: dbf4 blt.n 1001151a +10011530: e00a b.n 10011548 +10011532: 2108 movs r1, #8 +10011534: f000 fcb5 bl 10011ea2 <.text_31> +10011538: 2801 cmp r0, #1 +1001153a: d105 bne.n 10011548 +1001153c: 1930 adds r0, r6, r4 +1001153e: 6880 ldr r0, [r0, #8] +10011540: f500 703d add.w r0, r0, #756 ; 0x2f4 +10011544: f7ff fa80 bl 10010a48 +10011548: 1930 adds r0, r6, r4 +1001154a: 5937 ldr r7, [r6, r4] +1001154c: 6840 ldr r0, [r0, #4] +1001154e: 9000 str r0, [sp, #0] +10011550: f44f 62d2 mov.w r2, #1680 ; 0x690 +10011554: 2100 movs r1, #0 +10011556: 4628 mov r0, r5 +10011558: f7ff f96e bl 10010838 +1001155c: 5137 str r7, [r6, r4] +1001155e: 1931 adds r1, r6, r4 +10011560: 9800 ldr r0, [sp, #0] +10011562: 6048 str r0, [r1, #4] +10011564: f007 0003 and.w r0, r7, #3 +10011568: 1a38 subs r0, r7, r0 +1001156a: 1d00 adds r0, r0, #4 +1001156c: 6088 str r0, [r1, #8] +1001156e: 2001 movs r0, #1 +10011570: e008 b.n 10011584 +10011572: 1931 adds r1, r6, r4 +10011574: 6889 ldr r1, [r1, #8] +10011576: fb02 1100 mla r1, r2, r0, r1 +1001157a: eb04 0280 add.w r2, r4, r0, lsl #2 +1001157e: 1c40 adds r0, r0, #1 +10011580: f84a 1002 str.w r1, [sl, r2] +10011584: f44f 7246 mov.w r2, #792 ; 0x318 +10011588: 9900 ldr r1, [sp, #0] +1001158a: fbb1 f1f2 udiv r1, r1, r2 +1001158e: 4288 cmp r0, r1 +10011590: d3ef bcc.n 10011572 +10011592: f89d 0004 ldrb.w r0, [sp, #4] +10011596: f809 0004 strb.w r0, [r9, r4] +1001159a: f8cb 8004 str.w r8, [fp, #4] +1001159e: f241 5054 movw r0, #5460 ; 0x1554 +100115a2: 2100 movs r1, #0 +100115a4: 5101 str r1, [r0, r4] +100115a6: 1900 adds r0, r0, r4 +100115a8: 2101 movs r1, #1 +100115aa: 6041 str r1, [r0, #4] +100115ac: e00c b.n 100115c8 +100115ae: 2000 movs r0, #0 +100115b0: 6028 str r0, [r5, #0] +100115b2: 6068 str r0, [r5, #4] +100115b4: 60a8 str r0, [r5, #8] +100115b6: 65e8 str r0, [r5, #92] ; 0x5c +100115b8: 2001 movs r0, #1 +100115ba: 6628 str r0, [r5, #96] ; 0x60 +100115bc: 2000 movs r0, #0 +100115be: f8c5 0364 str.w r0, [r5, #868] ; 0x364 +100115c2: 2001 movs r0, #1 +100115c4: f8c5 0368 str.w r0, [r5, #872] ; 0x368 +100115c8: e8bd 8ff7 ldmia.w sp!, {r0, r1, r2, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +100115cc : +100115cc: b538 push {r3, r4, r5, lr} +100115ce: 4604 mov r4, r0 +100115d0: f002 fcce bl 10013f70 +100115d4: f241 15f8 movw r5, #4600 ; 0x11f8 +100115d8: 592a ldr r2, [r5, r4] +100115da: 2a04 cmp r2, #4 +100115dc: d216 bcs.n 1001160c +100115de: 2300 movs r3, #0 +100115e0: b2d2 uxtb r2, r2 +100115e2: 2100 movs r1, #0 +100115e4: 4620 mov r0, r4 +100115e6: f005 f99d bl 10016924 +100115ea: 5928 ldr r0, [r5, r4] +100115ec: eb04 1000 add.w r0, r4, r0, lsl #4 +100115f0: f500 5088 add.w r0, r0, #4352 ; 0x1100 +100115f4: 2210 movs r2, #16 +100115f6: 2100 movs r1, #0 +100115f8: 30fc adds r0, #252 ; 0xfc +100115fa: f7ff f91d bl 10010838 +100115fe: 5928 ldr r0, [r5, r4] +10011600: eb04 0080 add.w r0, r4, r0, lsl #2 +10011604: f241 213c movw r1, #4668 ; 0x123c +10011608: 2200 movs r2, #0 +1001160a: 500a str r2, [r1, r0] +1001160c: 4620 mov r0, r4 +1001160e: e8bd 4032 ldmia.w sp!, {r1, r4, r5, lr} +10011612: e764 b.n 100114de + +10011614 : +10011614: b510 push {r4, lr} +10011616: f500 54c4 add.w r4, r0, #6272 ; 0x1880 +1001161a: 2000 movs r0, #0 +1001161c: 7020 strb r0, [r4, #0] +1001161e: 2203 movs r2, #3 +10011620: 2002 movs r0, #2 +10011622: 7060 strb r0, [r4, #1] +10011624: a175 add r1, pc, #468 ; (adr r1, 100117fc <.text_16>) +10011626: 2000 movs r0, #0 +10011628: 70a0 strb r0, [r4, #2] +1001162a: f884 002c strb.w r0, [r4, #44] ; 0x2c +1001162e: f104 0008 add.w r0, r4, #8 +10011632: f7ff f8ec bl 1001080e +10011636: 2003 movs r0, #3 +10011638: 6060 str r0, [r4, #4] +1001163a: 2001 movs r0, #1 +1001163c: f884 002d strb.w r0, [r4, #45] ; 0x2d +10011640: 200b movs r0, #11 +10011642: f884 002e strb.w r0, [r4, #46] ; 0x2e +10011646: 2002 movs r0, #2 +10011648: f884 0032 strb.w r0, [r4, #50] ; 0x32 +1001164c: 2001 movs r0, #1 +1001164e: f884 0033 strb.w r0, [r4, #51] ; 0x33 +10011652: f640 102b movw r0, #2347 ; 0x92b +10011656: 86a0 strh r0, [r4, #52] ; 0x34 +10011658: 2001 movs r0, #1 +1001165a: f884 0031 strb.w r0, [r4, #49] ; 0x31 +1001165e: f884 002f strb.w r0, [r4, #47] ; 0x2f +10011662: f884 0036 strb.w r0, [r4, #54] ; 0x36 +10011666: 2000 movs r0, #0 +10011668: f884 0037 strb.w r0, [r4, #55] ; 0x37 +1001166c: 2002 movs r0, #2 +1001166e: f884 003b strb.w r0, [r4, #59] ; 0x3b +10011672: 2001 movs r0, #1 +10011674: f884 0038 strb.w r0, [r4, #56] ; 0x38 +10011678: f884 003a strb.w r0, [r4, #58] ; 0x3a +1001167c: f884 0039 strb.w r0, [r4, #57] ; 0x39 +10011680: f884 0030 strb.w r0, [r4, #48] ; 0x30 +10011684: 2007 movs r0, #7 +10011686: f884 003c strb.w r0, [r4, #60] ; 0x3c +1001168a: f884 003d strb.w r0, [r4, #61] ; 0x3d +1001168e: 2028 movs r0, #40 ; 0x28 +10011690: 87e0 strh r0, [r4, #62] ; 0x3e +10011692: 2000 movs r0, #0 +10011694: f884 0040 strb.w r0, [r4, #64] ; 0x40 +10011698: f884 0041 strb.w r0, [r4, #65] ; 0x41 +1001169c: f884 0042 strb.w r0, [r4, #66] ; 0x42 +100116a0: f884 0043 strb.w r0, [r4, #67] ; 0x43 +100116a4: f884 0044 strb.w r0, [r4, #68] ; 0x44 +100116a8: 2001 movs r0, #1 +100116aa: f884 0045 strb.w r0, [r4, #69] ; 0x45 +100116ae: 2000 movs r0, #0 +100116b0: f884 0046 strb.w r0, [r4, #70] ; 0x46 +100116b4: f884 0047 strb.w r0, [r4, #71] ; 0x47 +100116b8: f884 0048 strb.w r0, [r4, #72] ; 0x48 +100116bc: f884 0049 strb.w r0, [r4, #73] ; 0x49 +100116c0: f884 004a strb.w r0, [r4, #74] ; 0x4a +100116c4: f884 004b strb.w r0, [r4, #75] ; 0x4b +100116c8: 2064 movs r0, #100 ; 0x64 +100116ca: 64e0 str r0, [r4, #76] ; 0x4c +100116cc: 2001 movs r0, #1 +100116ce: f884 0050 strb.w r0, [r4, #80] ; 0x50 +100116d2: 2000 movs r0, #0 +100116d4: f884 0051 strb.w r0, [r4, #81] ; 0x51 +100116d8: 2001 movs r0, #1 +100116da: f884 0052 strb.w r0, [r4, #82] ; 0x52 +100116de: f884 0053 strb.w r0, [r4, #83] ; 0x53 +100116e2: 2000 movs r0, #0 +100116e4: f884 0054 strb.w r0, [r4, #84] ; 0x54 +100116e8: 2001 movs r0, #1 +100116ea: f884 0055 strb.w r0, [r4, #85] ; 0x55 +100116ee: 2005 movs r0, #5 +100116f0: f884 0056 strb.w r0, [r4, #86] ; 0x56 +100116f4: 2000 movs r0, #0 +100116f6: f884 0057 strb.w r0, [r4, #87] ; 0x57 +100116fa: f884 0058 strb.w r0, [r4, #88] ; 0x58 +100116fe: 2059 movs r0, #89 ; 0x59 +10011700: f884 0059 strb.w r0, [r4, #89] ; 0x59 +10011704: 2002 movs r0, #2 +10011706: f884 005a strb.w r0, [r4, #90] ; 0x5a +1001170a: 2000 movs r0, #0 +1001170c: f884 005b strb.w r0, [r4, #91] ; 0x5b +10011710: f884 005f strb.w r0, [r4, #95] ; 0x5f +10011714: 2110 movs r1, #16 +10011716: f60f 02a0 addw r2, pc, #2208 ; 0x8a0 +1001171a: f104 0060 add.w r0, r4, #96 ; 0x60 +1001171e: f7fa fd87 bl 1000c230 +10011722: f60f 029c addw r2, pc, #2204 ; 0x89c +10011726: 2110 movs r1, #16 +10011728: f104 0070 add.w r0, r4, #112 ; 0x70 +1001172c: f7fa fd80 bl 1000c230 +10011730: 2000 movs r0, #0 +10011732: f884 0080 strb.w r0, [r4, #128] ; 0x80 +10011736: 2002 movs r0, #2 +10011738: f884 0081 strb.w r0, [r4, #129] ; 0x81 +1001173c: f884 0082 strb.w r0, [r4, #130] ; 0x82 +10011740: 200e movs r0, #14 +10011742: f884 0083 strb.w r0, [r4, #131] ; 0x83 +10011746: 2000 movs r0, #0 +10011748: f884 0085 strb.w r0, [r4, #133] ; 0x85 +1001174c: f884 0086 strb.w r0, [r4, #134] ; 0x86 +10011750: f884 0087 strb.w r0, [r4, #135] ; 0x87 +10011754: 2004 movs r0, #4 +10011756: f884 0088 strb.w r0, [r4, #136] ; 0x88 +1001175a: 2000 movs r0, #0 +1001175c: f884 0089 strb.w r0, [r4, #137] ; 0x89 +10011760: 2001 movs r0, #1 +10011762: bd10 pop {r4, pc} + +10011764 : +10011764: b570 push {r4, r5, r6, lr} +10011766: 6900 ldr r0, [r0, #16] +10011768: 6805 ldr r5, [r0, #0] +1001176a: f605 1128 addw r1, r5, #2344 ; 0x928 +1001176e: f641 562c movw r6, #7468 ; 0x1d2c +10011772: e9d1 231a ldrd r2, r3, [r1, #104] ; 0x68 +10011776: 1970 adds r0, r6, r5 +10011778: f505 6432 add.w r4, r5, #2848 ; 0xb20 +1001177c: 6042 str r2, [r0, #4] +1001177e: e9d4 2312 ldrd r2, r3, [r4, #72] ; 0x48 +10011782: 5172 str r2, [r6, r5] +10011784: e9d1 231c ldrd r2, r3, [r1, #112] ; 0x70 +10011788: 60c2 str r2, [r0, #12] +1001178a: e9d4 2314 ldrd r2, r3, [r4, #80] ; 0x50 +1001178e: 6082 str r2, [r0, #8] +10011790: e9d1 2318 ldrd r2, r3, [r1, #96] ; 0x60 +10011794: 6142 str r2, [r0, #20] +10011796: e9d4 2310 ldrd r2, r3, [r4, #64] ; 0x40 +1001179a: 6102 str r2, [r0, #16] +1001179c: bd70 pop {r4, r5, r6, pc} + +1001179e : +1001179e: b580 push {r7, lr} +100117a0: f7fe f910 bl 1000f9c4 +100117a4: 2000 movs r0, #0 +100117a6: bd02 pop {r1, pc} + +100117a8 : +100117a8: b510 push {r4, lr} +100117aa: f641 5268 movw r2, #7528 ; 0x1d68 +100117ae: b120 cbz r0, 100117ba +100117b0: 4601 mov r1, r0 +100117b2: 4610 mov r0, r2 +100117b4: f7ff fa00 bl 10010bb8 +100117b8: e002 b.n 100117c0 +100117ba: 4610 mov r0, r2 +100117bc: f7ff fa07 bl 10010bce +100117c0: 0004 movs r4, r0 +100117c2: d101 bne.n 100117c8 +100117c4: 2000 movs r0, #0 +100117c6: bd10 pop {r4, pc} +100117c8: 6920 ldr r0, [r4, #16] +100117ca: 6800 ldr r0, [r0, #0] +100117cc: f641 5124 movw r1, #7460 ; 0x1d24 +100117d0: 500c str r4, [r1, r0] +100117d2: f20f 41b1 addw r1, pc, #1201 ; 0x4b1 +100117d6: 6221 str r1, [r4, #32] +100117d8: f20f 41d5 addw r1, pc, #1237 ; 0x4d5 +100117dc: 6261 str r1, [r4, #36] ; 0x24 +100117de: f8df 17b0 ldr.w r1, [pc, #1968] ; 10011f90 <.text_36> +100117e2: 62a1 str r1, [r4, #40] ; 0x28 +100117e4: f8df 17ac ldr.w r1, [pc, #1964] ; 10011f94 <.text_37> +100117e8: 6321 str r1, [r4, #48] ; 0x30 +100117ea: f8df 17ac ldr.w r1, [pc, #1964] ; 10011f98 <.text_38> +100117ee: 62e1 str r1, [r4, #44] ; 0x2c +100117f0: 4621 mov r1, r4 +100117f2: f7ff ff0f bl 10011614 +100117f6: 4620 mov r0, r4 +100117f8: bd10 pop {r4, pc} + ... + +100117fc <.text_16>: +100117fc: 00594e41 .word 0x00594e41 + +10011800 : +10011800: b580 push {r7, lr} +10011802: 000a movs r2, r1 +10011804: d101 bne.n 1001180a +10011806: 2000 movs r0, #0 +10011808: bd02 pop {r1, pc} +1001180a: f600 00fc addw r0, r0, #2300 ; 0x8fc +1001180e: 4788 blx r1 +10011810: 2001 movs r0, #1 +10011812: bd02 pop {r1, pc} + +10011814 <_netdev_if2_open>: +10011814: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +10011818: 4682 mov sl, r0 +1001181a: f641 581c movw r8, #7452 ; 0x1d1c +1001181e: f8da 0010 ldr.w r0, [sl, #16] +10011822: 6805 ldr r5, [r0, #0] +10011824: f505 56e8 add.w r6, r5, #7424 ; 0x1d00 +10011828: 3644 adds r6, #68 ; 0x44 +1001182a: f641 5024 movw r0, #7460 ; 0x1d24 +1001182e: 6877 ldr r7, [r6, #4] +10011830: 19c4 adds r4, r0, r7 +10011832: f641 4bb5 movw fp, #7349 ; 0x1cb5 +10011836: 6861 ldr r1, [r4, #4] +10011838: 2900 cmp r1, #0 +1001183a: eb08 0905 add.w r9, r8, r5 +1001183e: bf19 ittee ne +10011840: f81b 1007 ldrbne.w r1, [fp, r7] +10011844: 2900 cmpne r1, #0 +10011846: 59c0 ldreq r0, [r0, r7] +10011848: f000 f99f bleq 10011b8a <_netdev_open> +1001184c: f8d9 000c ldr.w r0, [r9, #12] +10011850: 2800 cmp r0, #0 +10011852: bf01 itttt eq +10011854: 6860 ldreq r0, [r4, #4] +10011856: 2801 cmpeq r0, #1 +10011858: f81b 0007 ldrbeq.w r0, [fp, r7] +1001185c: 2801 cmpeq r0, #1 +1001185e: d126 bne.n 100118ae <_netdev_if2_open+0x9a> +10011860: f641 409c movw r0, #7324 ; 0x1c9c +10011864: 2100 movs r1, #0 +10011866: 5141 str r1, [r0, r5] +10011868: 1944 adds r4, r0, r5 +1001186a: 2206 movs r2, #6 +1001186c: 6061 str r1, [r4, #4] +1001186e: 60a1 str r1, [r4, #8] +10011870: f10a 0014 add.w r0, sl, #20 +10011874: f505 51c8 add.w r1, r5, #6400 ; 0x1900 +10011878: 3195 adds r1, #149 ; 0x95 +1001187a: f7fe ffc8 bl 1001080e +1001187e: 4639 mov r1, r7 +10011880: 4628 mov r0, r5 +10011882: f005 fe03 bl 1001748c +10011886: f641 5045 movw r0, #7493 ; 0x1d45 +1001188a: f10a 0214 add.w r2, sl, #20 +1001188e: 5dc0 ldrb r0, [r0, r7] +10011890: 7070 strb r0, [r6, #1] +10011892: 2103 movs r1, #3 +10011894: 4628 mov r0, r5 +10011896: f005 fd3b bl 10017310 +1001189a: f858 1005 ldr.w r1, [r8, r5] +1001189e: 0008 movs r0, r1 +100118a0: bf1c itt ne +100118a2: 4628 movne r0, r5 +100118a4: 4788 blxne r1 +100118a6: 2001 movs r0, #1 +100118a8: 7660 strb r0, [r4, #25] +100118aa: f8c9 000c str.w r0, [r9, #12] +100118ae: f641 5144 movw r1, #7492 ; 0x1d44 +100118b2: 2000 movs r0, #0 +100118b4: 5548 strb r0, [r1, r5] +100118b6: 4650 mov r0, sl +100118b8: f7ff f918 bl 10010aec +100118bc: 2800 cmp r0, #0 +100118be: 4650 mov r0, sl +100118c0: d102 bne.n 100118c8 <_netdev_if2_open+0xb4> +100118c2: f7ff f916 bl 10010af2 +100118c6: e001 b.n 100118cc <_netdev_if2_open+0xb8> +100118c8: f7ff f912 bl 10010af0 +100118cc: 2000 movs r0, #0 +100118ce: e8bd 8ff2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +100118d2 : +100118d2: b570 push {r4, r5, r6, lr} +100118d4: f000 f9e3 bl 10011c9e <.text_27> +100118d8: 4620 mov r0, r4 +100118da: f7ff ff9b bl 10011814 <_netdev_if2_open> +100118de: e1d7 b.n 10011c90 <.text_26> + +100118e0 : +100118e0: b510 push {r4, lr} +100118e2: 4604 mov r4, r0 +100118e4: f641 5244 movw r2, #7492 ; 0x1d44 +100118e8: 6921 ldr r1, [r4, #16] +100118ea: 6809 ldr r1, [r1, #0] +100118ec: 2001 movs r0, #1 +100118ee: 5450 strb r0, [r2, r1] +100118f0: b134 cbz r4, 10011900 +100118f2: 4620 mov r0, r4 +100118f4: f7ff f8fa bl 10010aec +100118f8: b910 cbnz r0, 10011900 +100118fa: 4620 mov r0, r4 +100118fc: f7ff f8fa bl 10010af4 +10011900: 2000 movs r0, #0 +10011902: bd10 pop {r4, pc} + +10011904 : +10011904: e92d 41fc stmdb sp!, {r2, r3, r4, r5, r6, r7, r8, lr} +10011908: 4604 mov r4, r0 +1001190a: 460f mov r7, r1 +1001190c: 2600 movs r6, #0 +1001190e: 2000 movs r0, #0 +10011910: f7ff ff4a bl 100117a8 +10011914: 0005 movs r5, r0 +10011916: f000 80e2 beq.w 10011ade +1001191a: f8df 0680 ldr.w r0, [pc, #1664] ; 10011f9c <.text_39> +1001191e: 6228 str r0, [r5, #32] +10011920: f641 5268 movw r2, #7528 ; 0x1d68 +10011924: f8df 0678 ldr.w r0, [pc, #1656] ; 10011fa0 <.text_40> +10011928: 6268 str r0, [r5, #36] ; 0x24 +1001192a: 4621 mov r1, r4 +1001192c: 6928 ldr r0, [r5, #16] +1001192e: 6806 ldr r6, [r0, #0] +10011930: 4630 mov r0, r6 +10011932: f7fe ff6c bl 1001080e +10011936: f240 42dc movw r2, #1244 ; 0x4dc +1001193a: 2100 movs r1, #0 +1001193c: f106 000c add.w r0, r6, #12 +10011940: f7fe ff7a bl 10010838 +10011944: f894 049e ldrb.w r0, [r4, #1182] ; 0x49e +10011948: f886 049e strb.w r0, [r6, #1182] ; 0x49e +1001194c: f44f 727c mov.w r2, #1008 ; 0x3f0 +10011950: 2100 movs r1, #0 +10011952: f506 609d add.w r0, r6, #1256 ; 0x4e8 +10011956: f7fe ff6f bl 10010838 +1001195a: f506 5088 add.w r0, r6, #4352 ; 0x1100 +1001195e: 22c8 movs r2, #200 ; 0xc8 +10011960: 2100 movs r1, #0 +10011962: 3028 adds r0, #40 ; 0x28 +10011964: f7fe ff68 bl 10010838 +10011968: f641 5054 movw r0, #7508 ; 0x1d54 +1001196c: f641 5848 movw r8, #7496 ; 0x1d48 +10011970: 5901 ldr r1, [r0, r4] +10011972: 5181 str r1, [r0, r6] +10011974: f641 5058 movw r0, #7512 ; 0x1d58 +10011978: 5901 ldr r1, [r0, r4] +1001197a: 5181 str r1, [r0, r6] +1001197c: f641 505c movw r0, #7516 ; 0x1d5c +10011980: 5901 ldr r1, [r0, r4] +10011982: 5181 str r1, [r0, r6] +10011984: f641 504c movw r0, #7500 ; 0x1d4c +10011988: 5901 ldr r1, [r0, r4] +1001198a: 5181 str r1, [r0, r6] +1001198c: 2000 movs r0, #0 +1001198e: f641 5128 movw r1, #7464 ; 0x1d28 +10011992: 5188 str r0, [r1, r6] +10011994: f641 5144 movw r1, #7492 ; 0x1d44 +10011998: 2001 movs r0, #1 +1001199a: 5588 strb r0, [r1, r6] +1001199c: f641 41b5 movw r1, #7349 ; 0x1cb5 +100119a0: 2000 movs r0, #0 +100119a2: 5588 strb r0, [r1, r6] +100119a4: f641 5150 movw r1, #7504 ; 0x1d50 +100119a8: 5588 strb r0, [r1, r6] +100119aa: f641 5151 movw r1, #7505 ; 0x1d51 +100119ae: 2001 movs r0, #1 +100119b0: 5588 strb r0, [r1, r6] +100119b2: f848 4006 str.w r4, [r8, r6] +100119b6: f641 5152 movw r1, #7506 ; 0x1d52 +100119ba: 5588 strb r0, [r1, r6] +100119bc: f641 5024 movw r0, #7460 ; 0x1d24 +100119c0: 5185 str r5, [r0, r6] +100119c2: 68b0 ldr r0, [r6, #8] +100119c4: 6046 str r6, [r0, #4] +100119c6: 7c01 ldrb r1, [r0, #16] +100119c8: 1c4a adds r2, r1, #1 +100119ca: 7402 strb r2, [r0, #16] +100119cc: eb00 0081 add.w r0, r0, r1, lsl #2 +100119d0: 6086 str r6, [r0, #8] +100119d2: 8860 ldrh r0, [r4, #2] +100119d4: 8070 strh r0, [r6, #2] +100119d6: 8820 ldrh r0, [r4, #0] +100119d8: 8030 strh r0, [r6, #0] +100119da: 4630 mov r0, r6 +100119dc: f006 fa7c bl 10017ed8 +100119e0: f641 31bc movw r1, #7100 ; 0x1bbc +100119e4: 2000 movs r0, #0 +100119e6: 5188 str r0, [r1, r6] +100119e8: f506 51de add.w r1, r6, #7104 ; 0x1bc0 +100119ec: 6008 str r0, [r1, #0] +100119ee: f641 501c movw r0, #7452 ; 0x1d1c +100119f2: 5901 ldr r1, [r0, r4] +100119f4: 5181 str r1, [r0, r6] +100119f6: f44f 50e9 mov.w r0, #7456 ; 0x1d20 +100119fa: 5901 ldr r1, [r0, r4] +100119fc: 5181 str r1, [r0, r6] +100119fe: 4630 mov r0, r6 +10011a00: f005 fc14 bl 1001722c +10011a04: 4630 mov r0, r6 +10011a06: f005 fbfb bl 10017200 +10011a0a: 4630 mov r0, r6 +10011a0c: f006 fbdb bl 100181c6 +10011a10: 2801 cmp r0, #1 +10011a12: d164 bne.n 10011ade +10011a14: b91f cbnz r7, 10011a1e +10011a16: f506 50c0 add.w r0, r6, #6144 ; 0x1800 +10011a1a: f100 07f0 add.w r7, r0, #240 ; 0xf0 +10011a1e: 4639 mov r1, r7 +10011a20: 4628 mov r0, r5 +10011a22: f7ff febc bl 1001179e +10011a26: f641 1795 movw r7, #6549 ; 0x1995 +10011a2a: 2206 movs r2, #6 +10011a2c: 1939 adds r1, r7, r4 +10011a2e: a800 add r0, sp, #0 +10011a30: f7fe feed bl 1001080e +10011a34: f89d 1000 ldrb.w r1, [sp] +10011a38: 29ff cmp r1, #255 ; 0xff +10011a3a: a800 add r0, sp, #0 +10011a3c: d130 bne.n 10011aa0 +10011a3e: 7841 ldrb r1, [r0, #1] +10011a40: 29ff cmp r1, #255 ; 0xff +10011a42: bf04 itt eq +10011a44: 7881 ldrbeq r1, [r0, #2] +10011a46: 29ff cmpeq r1, #255 ; 0xff +10011a48: d107 bne.n 10011a5a +10011a4a: 78c1 ldrb r1, [r0, #3] +10011a4c: 29ff cmp r1, #255 ; 0xff +10011a4e: bf01 itttt eq +10011a50: 7901 ldrbeq r1, [r0, #4] +10011a52: 29ff cmpeq r1, #255 ; 0xff +10011a54: 7941 ldrbeq r1, [r0, #5] +10011a56: 29ff cmpeq r1, #255 ; 0xff +10011a58: d033 beq.n 10011ac2 +10011a5a: f89d 0000 ldrb.w r0, [sp] +10011a5e: f040 0002 orr.w r0, r0, #2 +10011a62: f88d 0000 strb.w r0, [sp] +10011a66: 2206 movs r2, #6 +10011a68: a900 add r1, sp, #0 +10011a6a: 19b8 adds r0, r7, r6 +10011a6c: f7fe fecf bl 1001080e +10011a70: 2206 movs r2, #6 +10011a72: a900 add r1, sp, #0 +10011a74: f105 0014 add.w r0, r5, #20 +10011a78: f7fe fec9 bl 1001080e +10011a7c: f848 6004 str.w r6, [r8, r4] +10011a80: f44f 55eb mov.w r5, #7520 ; 0x1d60 +10011a84: 5928 ldr r0, [r5, r4] +10011a86: b948 cbnz r0, 10011a9c +10011a88: 2004 movs r0, #4 +10011a8a: f7fe fea5 bl 100107d8 +10011a8e: 5128 str r0, [r5, r4] +10011a90: 51a8 str r0, [r5, r6] +10011a92: 2101 movs r1, #1 +10011a94: 7001 strb r1, [r0, #0] +10011a96: 2100 movs r1, #0 +10011a98: 7041 strb r1, [r0, #1] +10011a9a: 7081 strb r1, [r0, #2] +10011a9c: 4630 mov r0, r6 +10011a9e: e026 b.n 10011aee +10011aa0: 2900 cmp r1, #0 +10011aa2: bf04 itt eq +10011aa4: 7841 ldrbeq r1, [r0, #1] +10011aa6: 2900 cmpeq r1, #0 +10011aa8: d1d7 bne.n 10011a5a +10011aaa: 7881 ldrb r1, [r0, #2] +10011aac: 2900 cmp r1, #0 +10011aae: bf04 itt eq +10011ab0: 78c1 ldrbeq r1, [r0, #3] +10011ab2: 2900 cmpeq r1, #0 +10011ab4: d1d1 bne.n 10011a5a +10011ab6: 7901 ldrb r1, [r0, #4] +10011ab8: 2900 cmp r1, #0 +10011aba: bf04 itt eq +10011abc: 7941 ldrbeq r1, [r0, #5] +10011abe: 2900 cmpeq r1, #0 +10011ac0: d1cb bne.n 10011a5a +10011ac2: 2100 movs r1, #0 +10011ac4: f88d 1000 strb.w r1, [sp] +10011ac8: 21e0 movs r1, #224 ; 0xe0 +10011aca: 7041 strb r1, [r0, #1] +10011acc: 214c movs r1, #76 ; 0x4c +10011ace: 7081 strb r1, [r0, #2] +10011ad0: 2187 movs r1, #135 ; 0x87 +10011ad2: 70c1 strb r1, [r0, #3] +10011ad4: 2111 movs r1, #17 +10011ad6: 7101 strb r1, [r0, #4] +10011ad8: 2122 movs r1, #34 ; 0x22 +10011ada: 7141 strb r1, [r0, #5] +10011adc: e7c3 b.n 10011a66 +10011ade: 4630 mov r0, r6 +10011ae0: f006 fb0b bl 100180fa +10011ae4: b115 cbz r5, 10011aec +10011ae6: 4628 mov r0, r5 +10011ae8: f7ff f886 bl 10010bf8 +10011aec: 2000 movs r0, #0 +10011aee: e8bd 81f6 ldmia.w sp!, {r1, r2, r4, r5, r6, r7, r8, pc} + +10011af2 : +10011af2: b570 push {r4, r5, r6, lr} +10011af4: 0004 movs r4, r0 +10011af6: d021 beq.n 10011b3c +10011af8: f006 fac8 bl 1001808c +10011afc: f504 55e9 add.w r5, r4, #7456 ; 0x1d20 +10011b00: 68a8 ldr r0, [r5, #8] +10011b02: 2801 cmp r0, #1 +10011b04: d11a bne.n 10011b3c +10011b06: f641 469c movw r6, #7324 ; 0x1c9c +10011b0a: 5130 str r0, [r6, r4] +10011b0c: e002 b.n 10011b14 +10011b0e: 2001 movs r0, #1 +10011b10: f7fe ff7b bl 10010a0a +10011b14: 1930 adds r0, r6, r4 +10011b16: 6cc0 ldr r0, [r0, #76] ; 0x4c +10011b18: 2801 cmp r0, #1 +10011b1a: d0f8 beq.n 10011b0e +10011b1c: 6aa8 ldr r0, [r5, #40] ; 0x28 +10011b1e: f600 00d8 addw r0, r0, #2264 ; 0x8d8 +10011b22: f7fe fe94 bl 1001084e +10011b26: 2800 cmp r0, #0 +10011b28: d0f1 beq.n 10011b0e +10011b2a: f504 50e9 add.w r0, r4, #7456 ; 0x1d20 +10011b2e: 6801 ldr r1, [r0, #0] +10011b30: 0008 movs r0, r1 +10011b32: bf1c itt ne +10011b34: 4620 movne r0, r4 +10011b36: 4788 blxne r1 +10011b38: 2000 movs r0, #0 +10011b3a: 60a8 str r0, [r5, #8] +10011b3c: bd70 pop {r4, r5, r6, pc} + +10011b3e : +10011b3e: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +10011b42: 0007 movs r7, r0 +10011b44: d01f beq.n 10011b86 +10011b46: f641 5648 movw r6, #7496 ; 0x1d48 +10011b4a: 19f4 adds r4, r6, r7 +10011b4c: 7a60 ldrb r0, [r4, #9] +10011b4e: b9d0 cbnz r0, 10011b86 +10011b50: 59f5 ldr r5, [r6, r7] +10011b52: b1c5 cbz r5, 10011b86 +10011b54: f641 5924 movw r9, #7460 ; 0x1d24 +10011b58: 4628 mov r0, r5 +10011b5a: f859 8005 ldr.w r8, [r9, r5] +10011b5e: f006 fc39 bl 100183d4 +10011b62: 2000 movs r0, #0 +10011b64: 51f0 str r0, [r6, r7] +10011b66: eb09 0105 add.w r1, r9, r5 +10011b6a: 63c8 str r0, [r1, #60] ; 0x3c +10011b6c: 4628 mov r0, r5 +10011b6e: f006 fac4 bl 100180fa +10011b72: 4640 mov r0, r8 +10011b74: f7ff f840 bl 10010bf8 +10011b78: 69a0 ldr r0, [r4, #24] +10011b7a: b120 cbz r0, 10011b86 +10011b7c: 2104 movs r1, #4 +10011b7e: f7fe fe3a bl 100107f6 +10011b82: 2000 movs r0, #0 +10011b84: 61a0 str r0, [r4, #24] +10011b86: e8bd 83f1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, pc} + +10011b8a <_netdev_open>: +10011b8a: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +10011b8e: 4680 mov r8, r0 +10011b90: f641 1a3c movw sl, #6460 ; 0x193c +10011b94: f8d8 0010 ldr.w r0, [r8, #16] +10011b98: 6804 ldr r4, [r0, #0] +10011b9a: eb0a 0604 add.w r6, sl, r4 +10011b9e: f641 5544 movw r5, #7492 ; 0x1d44 +10011ba2: 6b70 ldr r0, [r6, #52] ; 0x34 +10011ba4: 2801 cmp r0, #1 +10011ba6: d102 bne.n 10011bae <_netdev_open+0x24> +10011ba8: 2000 movs r0, #0 +10011baa: 5528 strb r0, [r5, r4] +10011bac: e03f b.n 10011c2e <_netdev_open+0xa4> +10011bae: f641 591c movw r9, #7452 ; 0x1d1c +10011bb2: eb09 0704 add.w r7, r9, r4 +10011bb6: 68f8 ldr r0, [r7, #12] +10011bb8: b9e8 cbnz r0, 10011bf6 <_netdev_open+0x6c> +10011bba: f641 409c movw r0, #7324 ; 0x1c9c +10011bbe: 2100 movs r1, #0 +10011bc0: 5101 str r1, [r0, r4] +10011bc2: 1900 adds r0, r0, r4 +10011bc4: 6041 str r1, [r0, #4] +10011bc6: 6081 str r1, [r0, #8] +10011bc8: 4620 mov r0, r4 +10011bca: f005 fb71 bl 100172b0 +10011bce: 2800 cmp r0, #0 +10011bd0: d04f beq.n 10011c72 <_netdev_open+0xe8> +10011bd2: 4620 mov r0, r4 +10011bd4: f006 fb3c bl 10018250 +10011bd8: 2800 cmp r0, #0 +10011bda: d04a beq.n 10011c72 <_netdev_open+0xe8> +10011bdc: 4620 mov r0, r4 +10011bde: f007 ff15 bl 10019a0c +10011be2: 2800 cmp r0, #0 +10011be4: d045 beq.n 10011c72 <_netdev_open+0xe8> +10011be6: f859 1004 ldr.w r1, [r9, r4] +10011bea: 0008 movs r0, r1 +10011bec: bf1c itt ne +10011bee: 4620 movne r0, r4 +10011bf0: 4788 blxne r1 +10011bf2: 2001 movs r0, #1 +10011bf4: 60f8 str r0, [r7, #12] +10011bf6: 2000 movs r0, #0 +10011bf8: 5528 strb r0, [r5, r4] +10011bfa: f44f 61fa mov.w r1, #2000 ; 0x7d0 +10011bfe: f504 6092 add.w r0, r4, #1168 ; 0x490 +10011c02: f7fe ff1a bl 10010a3a +10011c06: 2000 movs r0, #0 +10011c08: f84a 0004 str.w r0, [sl, r4] +10011c0c: f504 50c8 add.w r0, r4, #6400 ; 0x1900 +10011c10: 6af1 ldr r1, [r6, #44] ; 0x2c +10011c12: 305c adds r0, #92 ; 0x5c +10011c14: f7fe ff11 bl 10010a3a +10011c18: 4640 mov r0, r8 +10011c1a: f7fe ff67 bl 10010aec +10011c1e: 2800 cmp r0, #0 +10011c20: 4640 mov r0, r8 +10011c22: d102 bne.n 10011c2a <_netdev_open+0xa0> +10011c24: f7fe ff65 bl 10010af2 +10011c28: e001 b.n 10011c2e <_netdev_open+0xa4> +10011c2a: f7fe ff61 bl 10010af0 +10011c2e: 1928 adds r0, r5, r4 +10011c30: 6840 ldr r0, [r0, #4] +10011c32: b168 cbz r0, 10011c50 <_netdev_open+0xc6> +10011c34: f641 5124 movw r1, #7460 ; 0x1d24 +10011c38: 180a adds r2, r1, r0 +10011c3a: 6852 ldr r2, [r2, #4] +10011c3c: 2a00 cmp r2, #0 +10011c3e: bf1e ittt ne +10011c40: f641 42b5 movwne r2, #7349 ; 0x1cb5 +10011c44: 5c12 ldrbne r2, [r2, r0] +10011c46: 2a00 cmpne r2, #0 +10011c48: bf04 itt eq +10011c4a: 5808 ldreq r0, [r1, r0] +10011c4c: f7ff fde2 bleq 10011814 <_netdev_if2_open> +10011c50: 4dd4 ldr r5, [pc, #848] ; (10011fa4 <.text_41>) +10011c52: 6828 ldr r0, [r5, #0] +10011c54: 0001 movs r1, r0 +10011c56: d003 beq.n 10011c60 <_netdev_open+0xd6> +10011c58: 6861 ldr r1, [r4, #4] +10011c5a: 2901 cmp r1, #1 +10011c5c: bf08 it eq +10011c5e: 4780 blxeq r0 +10011c60: 6868 ldr r0, [r5, #4] +10011c62: 0001 movs r1, r0 +10011c64: d003 beq.n 10011c6e <_netdev_open+0xe4> +10011c66: 6861 ldr r1, [r4, #4] +10011c68: 2901 cmp r1, #1 +10011c6a: bf08 it eq +10011c6c: 4780 blxeq r0 +10011c6e: 2000 movs r0, #0 +10011c70: e006 b.n 10011c80 <_netdev_open+0xf6> +10011c72: 2000 movs r0, #0 +10011c74: 60f8 str r0, [r7, #12] +10011c76: 4640 mov r0, r8 +10011c78: f7fe ff3c bl 10010af4 +10011c7c: f04f 30ff mov.w r0, #4294967295 +10011c80: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + +10011c84 : +10011c84: b570 push {r4, r5, r6, lr} +10011c86: f000 f80a bl 10011c9e <.text_27> +10011c8a: 4620 mov r0, r4 +10011c8c: f7ff ff7d bl 10011b8a <_netdev_open> + +10011c90 <.text_26>: +10011c90: 4604 mov r4, r0 +10011c92: 5970 ldr r0, [r6, r5] +10011c94: 2100 movs r1, #0 +10011c96: f7fe fe47 bl 10010928 +10011c9a: 4620 mov r0, r4 +10011c9c: bd70 pop {r4, r5, r6, pc} + +10011c9e <.text_27>: +10011c9e: 4604 mov r4, r0 +10011ca0: f641 564c movw r6, #7500 ; 0x1d4c +10011ca4: 6920 ldr r0, [r4, #16] +10011ca6: 6805 ldr r5, [r0, #0] +10011ca8: 5970 ldr r0, [r6, r5] +10011caa: 2100 movs r1, #0 +10011cac: f7fe be34 b.w 10010918 + +10011cb0 : +10011cb0: b538 push {r3, r4, r5, lr} +10011cb2: 4604 mov r4, r0 +10011cb4: f641 1259 movw r2, #6489 ; 0x1959 +10011cb8: 6920 ldr r0, [r4, #16] +10011cba: 6805 ldr r5, [r0, #0] +10011cbc: 5d52 ldrb r2, [r2, r5] +10011cbe: f641 1070 movw r0, #6512 ; 0x1970 +10011cc2: 1941 adds r1, r0, r5 +10011cc4: 2a01 cmp r2, #1 +10011cc6: bf01 itttt eq +10011cc8: 684a ldreq r2, [r1, #4] +10011cca: 2a02 cmpeq r2, #2 +10011ccc: 2201 moveq r2, #1 +10011cce: 5142 streq r2, [r0, r5] +10011cd0: f641 5244 movw r2, #7492 ; 0x1d44 +10011cd4: 2001 movs r0, #1 +10011cd6: 5550 strb r0, [r2, r5] +10011cd8: 6848 ldr r0, [r1, #4] +10011cda: b9a8 cbnz r0, 10011d08 +10011cdc: b134 cbz r4, 10011cec +10011cde: 4620 mov r0, r4 +10011ce0: f7fe ff04 bl 10010aec +10011ce4: b910 cbnz r0, 10011cec +10011ce6: 4620 mov r0, r4 +10011ce8: f7fe ff04 bl 10010af4 +10011cec: 4628 mov r0, r5 +10011cee: f004 fd8f bl 10016810 +10011cf2: 4628 mov r0, r5 +10011cf4: f00d f892 bl 1001ee1c +10011cf8: 2101 movs r1, #1 +10011cfa: 4628 mov r0, r5 +10011cfc: f00d f80f bl 1001ed1e +10011d00: 2101 movs r1, #1 +10011d02: 4628 mov r0, r5 +10011d04: f00c fe03 bl 1001e90e +10011d08: 2000 movs r0, #0 +10011d0a: bd32 pop {r1, r4, r5, pc} + +10011d0c : +10011d0c: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +10011d10: 4607 mov r7, r0 +10011d12: f641 5868 movw r8, #7528 ; 0x1d68 +10011d16: 468a mov sl, r1 +10011d18: 4640 mov r0, r8 +10011d1a: f7fe fd5d bl 100107d8 +10011d1e: 0005 movs r5, r0 +10011d20: d07a beq.n 10011e18 +10011d22: 60af str r7, [r5, #8] +10011d24: f641 469c movw r6, #7324 ; 0x1c9c +10011d28: 603d str r5, [r7, #0] +10011d2a: 2001 movs r0, #1 +10011d2c: 5170 str r0, [r6, r5] +10011d2e: f641 591c movw r9, #7452 ; 0x1d1c +10011d32: eb09 0405 add.w r4, r9, r5 +10011d36: 499c ldr r1, [pc, #624] ; (10011fa8 <.text_42>) +10011d38: 1d08 adds r0, r1, #4 +10011d3a: 6320 str r0, [r4, #48] ; 0x30 +10011d3c: f641 5250 movw r2, #7504 ; 0x1d50 +10011d40: 1950 adds r0, r2, r5 +10011d42: f101 0308 add.w r3, r1, #8 +10011d46: 6043 str r3, [r0, #4] +10011d48: f101 030c add.w r3, r1, #12 +10011d4c: 6083 str r3, [r0, #8] +10011d4e: 3110 adds r1, #16 +10011d50: 60c1 str r1, [r0, #12] +10011d52: 2101 movs r1, #1 +10011d54: 5551 strb r1, [r2, r5] +10011d56: 2100 movs r1, #0 +10011d58: 7041 strb r1, [r0, #1] +10011d5a: 7c39 ldrb r1, [r7, #16] +10011d5c: 1c4a adds r2, r1, #1 +10011d5e: eb07 0181 add.w r1, r7, r1, lsl #2 +10011d62: 743a strb r2, [r7, #16] +10011d64: 608d str r5, [r1, #8] +10011d66: 2100 movs r1, #0 +10011d68: 7081 strb r1, [r0, #2] +10011d6a: f8c5 a004 str.w sl, [r5, #4] +10011d6e: 2010 movs r0, #16 +10011d70: 8068 strh r0, [r5, #2] +10011d72: 4628 mov r0, r5 +10011d74: f005 fbff bl 10017576 +10011d78: 4628 mov r0, r5 +10011d7a: f7ff fd15 bl 100117a8 +10011d7e: 0007 movs r7, r0 +10011d80: d045 beq.n 10011e0e +10011d82: 498a ldr r1, [pc, #552] ; (10011fac <.text_43>) +10011d84: 4628 mov r0, r5 +10011d86: f7ff fd3b bl 10011800 +10011d8a: 2800 cmp r0, #0 +10011d8c: d03b beq.n 10011e06 +10011d8e: 4628 mov r0, r5 +10011d90: f006 f8a2 bl 10017ed8 +10011d94: b380 cbz r0, 10011df8 +10011d96: 4628 mov r0, r5 +10011d98: f005 fa32 bl 10017200 +10011d9c: 4628 mov r0, r5 +10011d9e: f005 fa45 bl 1001722c +10011da2: 4628 mov r0, r5 +10011da4: f005 fa37 bl 10017216 +10011da8: 4881 ldr r0, [pc, #516] ; (10011fb0 <.text_44>) +10011daa: f849 0005 str.w r0, [r9, r5] +10011dae: 4881 ldr r0, [pc, #516] ; (10011fb4 <.text_45>) +10011db0: 6060 str r0, [r4, #4] +10011db2: 4628 mov r0, r5 +10011db4: f005 fafe bl 100173b4 +10011db8: b1f0 cbz r0, 10011df8 +10011dba: 4628 mov r0, r5 +10011dbc: f005 faea bl 10017394 +10011dc0: 4628 mov r0, r5 +10011dc2: f006 fa00 bl 100181c6 +10011dc6: b190 cbz r0, 10011dee +10011dc8: f505 51c7 add.w r1, r5, #6368 ; 0x18e0 +10011dcc: 4638 mov r0, r7 +10011dce: f7ff fce6 bl 1001179e +10011dd2: f505 50c8 add.w r0, r5, #6400 ; 0x1900 +10011dd6: f100 0495 add.w r4, r0, #149 ; 0x95 +10011dda: 4620 mov r0, r4 +10011ddc: f00d fd6c bl 1001f8b8 +10011de0: 2206 movs r2, #6 +10011de2: 4621 mov r1, r4 +10011de4: f107 0014 add.w r0, r7, #20 +10011de8: f7fe fd11 bl 1001080e +10011dec: e014 b.n 10011e18 +10011dee: 2001 movs r0, #1 +10011df0: 5170 str r0, [r6, r5] +10011df2: 4628 mov r0, r5 +10011df4: f006 fa25 bl 10018242 +10011df8: f641 30a4 movw r0, #7076 ; 0x1ba4 +10011dfc: 5940 ldr r0, [r0, r5] +10011dfe: b110 cbz r0, 10011e06 +10011e00: 2104 movs r1, #4 +10011e02: f7fe fd03 bl 1001080c +10011e06: 4638 mov r0, r7 +10011e08: f7fe fef6 bl 10010bf8 +10011e0c: e003 b.n 10011e16 +10011e0e: 4641 mov r1, r8 +10011e10: 4628 mov r0, r5 +10011e12: f7fe fcf0 bl 100107f6 +10011e16: 2500 movs r5, #0 +10011e18: 4628 mov r0, r5 +10011e1a: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + +10011e1e : +10011e1e: b5f8 push {r3, r4, r5, r6, r7, lr} +10011e20: 4604 mov r4, r0 +10011e22: f504 55e9 add.w r5, r4, #7456 ; 0x1d20 +10011e26: 2101 movs r1, #1 +10011e28: 686e ldr r6, [r5, #4] +10011e2a: f000 f83a bl 10011ea2 <.text_31> +10011e2e: b118 cbz r0, 10011e38 +10011e30: 2100 movs r1, #0 +10011e32: 4620 mov r0, r4 +10011e34: f00b fe19 bl 1001da6a +10011e38: 4620 mov r0, r4 +10011e3a: f006 facb bl 100183d4 +10011e3e: 6a71 ldr r1, [r6, #36] ; 0x24 +10011e40: 4630 mov r0, r6 +10011e42: 4788 blx r1 +10011e44: 4620 mov r0, r4 +10011e46: f006 f921 bl 1001808c +10011e4a: f641 479c movw r7, #7324 ; 0x1c9c +10011e4e: 2001 movs r0, #1 +10011e50: 5138 str r0, [r7, r4] +10011e52: 68a8 ldr r0, [r5, #8] +10011e54: 2801 cmp r0, #1 +10011e56: d117 bne.n 10011e88 +10011e58: f504 50e9 add.w r0, r4, #7456 ; 0x1d20 +10011e5c: 6801 ldr r1, [r0, #0] +10011e5e: 0008 movs r0, r1 +10011e60: bf1c itt ne +10011e62: 4620 movne r0, r4 +10011e64: 4788 blxne r1 +10011e66: f641 1059 movw r0, #6489 ; 0x1959 +10011e6a: 5d00 ldrb r0, [r0, r4] +10011e6c: b910 cbnz r0, 10011e74 +10011e6e: 4620 mov r0, r4 +10011e70: f006 fa44 bl 100182fc +10011e74: 193f adds r7, r7, r4 +10011e76: 6878 ldr r0, [r7, #4] +10011e78: b920 cbnz r0, 10011e84 +10011e7a: 4620 mov r0, r4 +10011e7c: f005 fa3b bl 100172f6 +10011e80: 2001 movs r0, #1 +10011e82: 6078 str r0, [r7, #4] +10011e84: 2000 movs r0, #0 +10011e86: 60a8 str r0, [r5, #8] +10011e88: 4620 mov r0, r4 +10011e8a: f005 fa9d bl 100173c8 +10011e8e: 4620 mov r0, r4 +10011e90: f006 f933 bl 100180fa +10011e94: b126 cbz r6, 10011ea0 +10011e96: 4630 mov r0, r6 +10011e98: e8bd 40f2 ldmia.w sp!, {r1, r4, r5, r6, r7, lr} +10011e9c: f7fe beac b.w 10010bf8 +10011ea0: bdf1 pop {r0, r4, r5, r6, r7, pc} + +10011ea2 <.text_31>: +10011ea2: f104 000c add.w r0, r4, #12 +10011ea6: f7ff bb0f b.w 100114c8 + +10011eaa : +10011eaa: b570 push {r4, r5, r6, lr} +10011eac: 460c mov r4, r1 +10011eae: f641 5524 movw r5, #7460 ; 0x1d24 +10011eb2: b198 cbz r0, 10011edc +10011eb4: 6900 ldr r0, [r0, #16] +10011eb6: 6804 ldr r4, [r0, #0] +10011eb8: 68a6 ldr r6, [r4, #8] +10011eba: f504 51c0 add.w r1, r4, #6144 ; 0x1800 +10011ebe: 2200 movs r2, #0 +10011ec0: 31f0 adds r1, #240 ; 0xf0 +10011ec2: 4620 mov r0, r4 +10011ec4: f7ff fd1e bl 10011904 +10011ec8: b9b0 cbnz r0, 10011ef8 +10011eca: b114 cbz r4, 10011ed2 +10011ecc: 4620 mov r0, r4 +10011ece: f7ff ffa6 bl 10011e1e +10011ed2: 4630 mov r0, r6 +10011ed4: f00d fdf3 bl 1001fabe +10011ed8: 2000 movs r0, #0 +10011eda: bd70 pop {r4, r5, r6, pc} +10011edc: f00d fde8 bl 1001fab0 +10011ee0: 0006 movs r6, r0 +10011ee2: d0f9 beq.n 10011ed8 +10011ee4: 4621 mov r1, r4 +10011ee6: f7ff ff11 bl 10011d0c +10011eea: 0004 movs r4, r0 +10011eec: d0f1 beq.n 10011ed2 +10011eee: 4630 mov r0, r6 +10011ef0: f00d fdeb bl 1001faca +10011ef4: 5928 ldr r0, [r5, r4] +10011ef6: bd70 pop {r4, r5, r6, pc} +10011ef8: 5828 ldr r0, [r5, r0] +10011efa: bd70 pop {r4, r5, r6, pc} + +10011efc : +10011efc: b510 push {r4, lr} +10011efe: 6900 ldr r0, [r0, #16] +10011f00: 6804 ldr r4, [r0, #0] +10011f02: 68a0 ldr r0, [r4, #8] +10011f04: f00d fde7 bl 1001fad6 +10011f08: 2100 movs r1, #0 +10011f0a: 4620 mov r0, r4 +10011f0c: f00e f904 bl 10020118 +10011f10: 2100 movs r1, #0 +10011f12: 4620 mov r0, r4 +10011f14: f00e f8dd bl 100200d2 +10011f18: 4620 mov r0, r4 +10011f1a: f00e f802 bl 1001ff22 +10011f1e: f641 5048 movw r0, #7496 ; 0x1d48 +10011f22: 5900 ldr r0, [r0, r4] +10011f24: f7ff fde5 bl 10011af2 +10011f28: 4620 mov r0, r4 +10011f2a: f7ff fe08 bl 10011b3e +10011f2e: 4620 mov r0, r4 +10011f30: f7ff ff75 bl 10011e1e +10011f34: 68a0 ldr r0, [r4, #8] +10011f36: f00d fdc2 bl 1001fabe +10011f3a: 2000 movs r0, #0 +10011f3c: bd10 pop {r4, pc} + +10011f3e : +10011f3e: b510 push {r4, lr} +10011f40: 4c19 ldr r4, [pc, #100] ; (10011fa8 <.text_42>) +10011f42: 1d20 adds r0, r4, #4 +10011f44: f7fe fcca bl 100108dc +10011f48: f104 0008 add.w r0, r4, #8 +10011f4c: f7fe fcc6 bl 100108dc +10011f50: f104 000c add.w r0, r4, #12 +10011f54: f7fe fcc2 bl 100108dc +10011f58: f104 0010 add.w r0, r4, #16 +10011f5c: f7fe fcbe bl 100108dc +10011f60: 2001 movs r0, #1 +10011f62: 6020 str r0, [r4, #0] +10011f64: bd10 pop {r4, pc} + +10011f66 : +10011f66: b510 push {r4, lr} +10011f68: 4c0f ldr r4, [pc, #60] ; (10011fa8 <.text_42>) +10011f6a: 2000 movs r0, #0 +10011f6c: 6020 str r0, [r4, #0] +10011f6e: 1d20 adds r0, r4, #4 +10011f70: f7fe fcbb bl 100108ea +10011f74: f104 0008 add.w r0, r4, #8 +10011f78: f7fe fcb7 bl 100108ea +10011f7c: f104 000c add.w r0, r4, #12 +10011f80: f7fe fcb3 bl 100108ea +10011f84: f104 0010 add.w r0, r4, #16 +10011f88: e8bd 4010 ldmia.w sp!, {r4, lr} +10011f8c: f7fe bcad b.w 100108ea + +10011f90 <.text_36>: +10011f90: 1002ff69 .word 0x1002ff69 + +10011f94 <.text_37>: +10011f94: 10011765 .word 0x10011765 + +10011f98 <.text_38>: +10011f98: 10015b81 .word 0x10015b81 + +10011f9c <.text_39>: +10011f9c: 100118d3 .word 0x100118d3 + +10011fa0 <.text_40>: +10011fa0: 100118e1 .word 0x100118e1 + +10011fa4 <.text_41>: +10011fa4: 10048320 .word 0x10048320 + +10011fa8 <.text_42>: +10011fa8: 10048328 .word 0x10048328 + +10011fac <.text_43>: +10011fac: 10021ae1 .word 0x10021ae1 + +10011fb0 <.text_44>: +10011fb0: 10017375 .word 0x10017375 + +10011fb4 <.text_45>: +10011fb4: 1004240d .word 0x1004240d + +10011fb8 : +10011fb8: 6e616c77 00000031 wlan1... + +10011fc0 : +10011fc0: 6e616c77 00000032 wlan2... + +10011fc8 : +10011fc8: b538 push {r3, r4, r5, lr} +10011fca: 460c mov r4, r1 +10011fcc: 4611 mov r1, r2 +10011fce: 4a5c ldr r2, [pc, #368] ; (10012140 ) +10011fd0: 2338 movs r3, #56 ; 0x38 +10011fd2: fb03 2500 mla r5, r3, r0, r2 +10011fd6: 2206 movs r2, #6 +10011fd8: f105 002b add.w r0, r5, #43 ; 0x2b +10011fdc: f7fe fc17 bl 1001080e +10011fe0: 61ec str r4, [r5, #28] +10011fe2: bd31 pop {r0, r4, r5, pc} + +10011fe4 : +10011fe4: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +10011fe8: 4604 mov r4, r0 +10011fea: 2600 movs r6, #0 +10011fec: 460d mov r5, r1 +10011fee: 4691 mov r9, r2 +10011ff0: 4698 mov r8, r3 +10011ff2: f20f 1764 addw r7, pc, #356 ; 0x164 +10011ff6: f20f 1a50 addw sl, pc, #336 ; 0x150 +10011ffa: f114 0f01 cmn.w r4, #1 +10011ffe: d104 bne.n 1001200a +10012000: 4651 mov r1, sl +10012002: 4638 mov r0, r7 +10012004: f7fa f97d bl 1000c302 +10012008: e01e b.n 10012048 + +1001200a : +1001200a: f7fe fe4f bl 10010cac +1001200e: 4620 mov r0, r4 +10012010: f7fd fef9 bl 1000fe06 +10012014: b190 cbz r0, 1001203c +10012016: 4620 mov r0, r4 +10012018: f7fd fefd bl 1000fe16 +1001201c: f7fe fe48 bl 10010cb0 +10012020: 4640 mov r0, r8 +10012022: f7fd ff11 bl 1000fe48 +10012026: 0007 movs r7, r0 +10012028: d111 bne.n 1001204e +1001202a: 4642 mov r2, r8 +1001202c: 4651 mov r1, sl +1001202e: f20f 1040 addw r0, pc, #320 ; 0x140 +10012032: f7fa f966 bl 1000c302 +10012036: f04f 36ff mov.w r6, #4294967295 +1001203a: e01b b.n 10012074 + +1001203c : +1001203c: 4651 mov r1, sl +1001203e: 4638 mov r0, r7 +10012040: f7fa f95f bl 1000c302 +10012044: f7fe fe34 bl 10010cb0 + +10012048 : +10012048: f04f 30ff mov.w r0, #4294967295 +1001204c: e01a b.n 10012084 + +1001204e : +1001204e: eb05 09c9 add.w r9, r5, r9, lsl #3 +10012052: e009 b.n 10012068 + +10012054 : +10012054: 686a ldr r2, [r5, #4] +10012056: 6829 ldr r1, [r5, #0] +10012058: 6978 ldr r0, [r7, #20] +1001205a: f7fe fbd8 bl 1001080e +1001205e: 6869 ldr r1, [r5, #4] +10012060: 4638 mov r0, r7 +10012062: f7ff f9c7 bl 100113f4 +10012066: 3508 adds r5, #8 + +10012068 : +10012068: 454d cmp r5, r9 +1001206a: d3f3 bcc.n 10012054 +1001206c: 4639 mov r1, r7 +1001206e: 4620 mov r0, r4 +10012070: f7fd ff03 bl 1000fe7a + +10012074 : +10012074: f7fe fe1a bl 10010cac +10012078: 4620 mov r0, r4 +1001207a: f7fd fed5 bl 1000fe28 +1001207e: f7fe fe17 bl 10010cb0 +10012082: 4630 mov r0, r6 + +10012084 : +10012084: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + +10012088 : +10012088: b570 push {r4, r5, r6, lr} +1001208a: 460c mov r4, r1 +1001208c: 4615 mov r5, r2 +1001208e: f110 0f01 cmn.w r0, #1 +10012092: d107 bne.n 100120a4 +10012094: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +10012098: f20f 110c addw r1, pc, #268 ; 0x10c +1001209c: f20f 1018 addw r0, pc, #280 ; 0x118 +100120a0: f7fa b92f b.w 1000c302 + +100120a4 : +100120a4: f7fd fec9 bl 1000fe3a +100120a8: 0006 movs r6, r0 +100120aa: d108 bne.n 100120be +100120ac: f20f 1360 addw r3, pc, #352 ; 0x160 +100120b0: f20f 1148 addw r1, pc, #328 ; 0x148 +100120b4: f20f 1014 addw r0, pc, #276 ; 0x114 +100120b8: 227d movs r2, #125 ; 0x7d +100120ba: f7fa f922 bl 1000c302 + +100120be : +100120be: eb04 05c5 add.w r5, r4, r5, lsl #3 +100120c2: e00a b.n 100120da + +100120c4 : +100120c4: 6820 ldr r0, [r4, #0] +100120c6: b138 cbz r0, 100120d8 +100120c8: 6862 ldr r2, [r4, #4] +100120ca: 6931 ldr r1, [r6, #16] +100120cc: f7fe fb9f bl 1001080e +100120d0: 6861 ldr r1, [r4, #4] +100120d2: 4630 mov r0, r6 +100120d4: f7ff f9a7 bl 10011426 + +100120d8 : +100120d8: 3408 adds r4, #8 + +100120da : +100120da: 42ac cmp r4, r5 +100120dc: d3f2 bcc.n 100120c4 +100120de: bd70 pop {r4, r5, r6, pc} + +100120e0 : +100120e0: b538 push {r3, r4, r5, lr} +100120e2: 4a17 ldr r2, [pc, #92] ; (10012140 ) +100120e4: 680d ldr r5, [r1, #0] +100120e6: 2338 movs r3, #56 ; 0x38 +100120e8: fb03 2400 mla r4, r3, r0, r2 +100120ec: 6860 ldr r0, [r4, #4] +100120ee: 2800 cmp r0, #0 +100120f0: bf1c itt ne +100120f2: f005 00f0 andne.w r0, r5, #240 ; 0xf0 +100120f6: 28e0 cmpne r0, #224 ; 0xe0 +100120f8: d007 beq.n 1001210a +100120fa: 4621 mov r1, r4 +100120fc: 4628 mov r0, r5 +100120fe: f7fa f935 bl 1000c36c +10012102: b910 cbnz r0, 1001210a +10012104: 6860 ldr r0, [r4, #4] +10012106: 42a8 cmp r0, r5 +10012108: d101 bne.n 1001210e + +1001210a : +1001210a: 2001 movs r0, #1 +1001210c: bd32 pop {r1, r4, r5, pc} + +1001210e : +1001210e: 2000 movs r0, #0 +10012110: bd32 pop {r1, r4, r5, pc} + +10012112 : +10012112: 490b ldr r1, [pc, #44] ; (10012140 ) +10012114: 1a40 subs r0, r0, r1 +10012116: 2138 movs r1, #56 ; 0x38 +10012118: fb90 f0f1 sdiv r0, r0, r1 +1001211c: 2800 cmp r0, #0 +1001211e: bf1c itt ne +10012120: 2801 cmpne r0, #1 +10012122: f04f 30ff movne.w r0, #4294967295 +10012126: 4770 bx lr + +10012128 : +10012128: 4905 ldr r1, [pc, #20] ; (10012140 ) +1001212a: 2238 movs r2, #56 ; 0x38 +1001212c: fb02 1000 mla r0, r2, r0, r1 +10012130: 302b adds r0, #43 ; 0x2b +10012132: 4770 bx lr + +10012134 : +10012134: 4a02 ldr r2, [pc, #8] ; (10012140 ) +10012136: 2338 movs r3, #56 ; 0x38 +10012138: fb03 2000 mla r0, r3, r0, r2 +1001213c: f00e b84b b.w 100201d6 + +10012140 : +10012140: 7824 1004 $x.. + +10012144 : +10012144: f00e b89b b.w 1002027e + +10012148 : +10012148: 6c72 6b74 775f 616c 5f6e 6573 646e 0000 rltk_wlan_send.. + +10012158 : +10012158: 0d0a 255b 5d73 6e20 7465 6669 6920 2073 ..[%s] netif is +10012168: 4f44 4e57 0000 0000 DOWN.... + +10012170 : +10012170: 0d0a 255b 5d73 7220 746c 5f6b 6c77 6e61 ..[%s] rltk_wlan +10012180: 615f 6c6c 636f 735f 626b 2928 6620 726f _alloc_skb() for +10012190: 6420 7461 2061 656c 3d6e 6425 6620 6961 data len=%d fai +100121a0: 656c 2164 0000 0000 led!.... + +100121a8 : +100121a8: 6c72 6b74 775f 616c 5f6e 6572 7663 0000 rltk_wlan_recv.. + +100121b8 : +100121b8: 0d0a 255b 5d73 7320 626b 6920 2073 554e ..[%s] skb is NU +100121c8: 4c4c 0000 LL.. + +100121cc : +100121cc: 0d0a 7325 202c 7341 6573 7472 7328 626b ..%s, Assert(skb +100121dc: 2029 6166 6c69 6465 6f20 206e 696c 656e ) failed on line +100121ec: 2520 2064 6e69 6620 6c69 2065 7325 0000 %d in file %s.. + +100121fc : +100121fc: 6f4e 7020 6e65 6964 676e 7220 2078 6b73 No pending rx sk +1001220c: 0062 0000 b... + +10012210 : +10012210: 3a44 615c 656d 6162 775f 3273 3138 6232 D:\ameba_ws2812b +10012220: 635c 6d6f 6f70 656e 746e 635c 6d6f 6f6d \component\commo +10012230: 5c6e 7264 7669 7265 5c73 6c77 6e61 725c n\drivers\wlan\r +10012240: 6165 746c 6b65 735c 6372 6f5c 6473 7065 ealtek\src\osdep +10012250: 6c5c 6977 5f70 6e69 6674 632e 0000 0000 \lwip_intf.c.... + +10012260 : +10012260: b510 push {r4, lr} +10012262: 4604 mov r4, r0 +10012264: f00e f98c bl 10020580 +10012268: 4620 mov r0, r4 +1001226a: e8bd 4010 ldmia.w sp!, {r4, lr} +1001226e: f00e b990 b.w 10020592 + +10012272 : +10012272: f00e b953 b.w 1002051c + +10012276 : +10012276: b538 push {r3, r4, r5, lr} +10012278: f641 31a4 movw r1, #7076 ; 0x1ba4 +1001227c: 580c ldr r4, [r1, r0] +1001227e: f504 5524 add.w r5, r4, #10496 ; 0x2900 +10012282: 35a4 adds r5, #164 ; 0xa4 +10012284: 7929 ldrb r1, [r5, #4] +10012286: 2900 cmp r1, #0 +10012288: bf1f itttt ne +1001228a: 79a9 ldrbne r1, [r5, #6] +1001228c: 79ea ldrbne r2, [r5, #7] +1001228e: 4291 cmpne r1, r2 +10012290: f000 fdc8 blne 10012e24 +10012294: 7828 ldrb r0, [r5, #0] +10012296: 07c0 lsls r0, r0, #31 +10012298: d506 bpl.n 100122a8 +1001229a: f504 5024 add.w r0, r4, #10496 ; 0x2900 +1001229e: e8bd 4032 ldmia.w sp!, {r1, r4, r5, lr} +100122a2: 3094 adds r0, #148 ; 0x94 +100122a4: f7fe baf3 b.w 1001088e +100122a8: bd31 pop {r0, r4, r5, pc} + +100122aa : +100122aa: f641 31a4 movw r1, #7076 ; 0x1ba4 +100122ae: 5809 ldr r1, [r1, r0] +100122b0: f501 5124 add.w r1, r1, #10496 ; 0x2900 +100122b4: 31a4 adds r1, #164 ; 0xa4 +100122b6: 790a ldrb r2, [r1, #4] +100122b8: b12a cbz r2, 100122c6 +100122ba: 798a ldrb r2, [r1, #6] +100122bc: 79c9 ldrb r1, [r1, #7] +100122be: 428a cmp r2, r1 +100122c0: bf18 it ne +100122c2: f000 bdaf bne.w 10012e24 +100122c6: 4770 bx lr + +100122c8 : +100122c8: b538 push {r3, r4, r5, lr} +100122ca: f8df 5a24 ldr.w r5, [pc, #2596] ; 10012cf0 <.text_87> +100122ce: 68e9 ldr r1, [r5, #12] +100122d0: 4604 mov r4, r0 +100122d2: 2006 movs r0, #6 +100122d4: 4788 blx r1 +100122d6: 6929 ldr r1, [r5, #16] +100122d8: 2006 movs r0, #6 +100122da: 4788 blx r1 +100122dc: f641 30a4 movw r0, #7076 ; 0x1ba4 +100122e0: f642 11a8 movw r1, #10664 ; 0x29a8 +100122e4: 5900 ldr r0, [r0, r4] +100122e6: 5c08 ldrb r0, [r1, r0] +100122e8: b120 cbz r0, 100122f4 +100122ea: 4620 mov r0, r4 +100122ec: e8bd 4032 ldmia.w sp!, {r1, r4, r5, lr} +100122f0: f000 bf5d b.w 100131ae +100122f4: bd31 pop {r0, r4, r5, pc} + +100122f6 : +100122f6: b538 push {r3, r4, r5, lr} +100122f8: f8df 59f4 ldr.w r5, [pc, #2548] ; 10012cf0 <.text_87> +100122fc: 68e9 ldr r1, [r5, #12] +100122fe: 4604 mov r4, r0 +10012300: 2007 movs r0, #7 +10012302: 4788 blx r1 +10012304: 6929 ldr r1, [r5, #16] +10012306: 2007 movs r0, #7 +10012308: 4788 blx r1 +1001230a: f641 30a4 movw r0, #7076 ; 0x1ba4 +1001230e: f000 ff45 bl 1001319c <.text_131> +10012312: b191 cbz r1, 1001233a +10012314: f8df 19dc ldr.w r1, [pc, #2524] ; 10012cf4 <.text_88> +10012318: 7809 ldrb r1, [r1, #0] +1001231a: 0789 lsls r1, r1, #30 +1001231c: d504 bpl.n 10012328 +1001231e: 4620 mov r0, r4 +10012320: e8bd 4032 ldmia.w sp!, {r1, r4, r5, lr} +10012324: f000 bd86 b.w 10012e34 +10012328: 7801 ldrb r1, [r0, #0] +1001232a: f001 01f7 and.w r1, r1, #247 ; 0xf7 +1001232e: 7001 strb r1, [r0, #0] +10012330: 4620 mov r0, r4 +10012332: e8bd 4032 ldmia.w sp!, {r1, r4, r5, lr} +10012336: f000 bd75 b.w 10012e24 +1001233a: bd31 pop {r0, r4, r5, pc} + +1001233c : +1001233c: b510 push {r4, lr} +1001233e: b088 sub sp, #32 +10012340: 2a06 cmp r2, #6 +10012342: f88d 101d strb.w r1, [sp, #29] +10012346: bf08 it eq +10012348: f8df 19ac ldreq.w r1, [pc, #2476] ; 10012cf8 <.text_89> +1001234c: d003 beq.n 10012356 +1001234e: 2a07 cmp r2, #7 +10012350: d102 bne.n 10012358 +10012352: f8df 19a8 ldr.w r1, [pc, #2472] ; 10012cfc <.text_90> +10012356: 9103 str r1, [sp, #12] +10012358: 9005 str r0, [sp, #20] +1001235a: 2105 movs r1, #5 +1001235c: 0298 lsls r0, r3, #10 +1001235e: 9000 str r0, [sp, #0] +10012360: 9104 str r1, [sp, #16] +10012362: 2001 movs r0, #1 +10012364: 9002 str r0, [sp, #8] +10012366: 2100 movs r1, #0 +10012368: f8df 4984 ldr.w r4, [pc, #2436] ; 10012cf0 <.text_87> +1001236c: 9106 str r1, [sp, #24] +1001236e: f88d 201c strb.w r2, [sp, #28] +10012372: 9101 str r1, [sp, #4] +10012374: 4620 mov r0, r4 +10012376: f00e fa57 bl 10020828 +1001237a: 6861 ldr r1, [r4, #4] +1001237c: a800 add r0, sp, #0 +1001237e: 4788 blx r1 +10012380: b008 add sp, #32 +10012382: bd10 pop {r4, pc} + +10012384 : +10012384: b500 push {lr} +10012386: b089 sub sp, #36 ; 0x24 +10012388: 2201 movs r2, #1 +1001238a: f88d 201d strb.w r2, [sp, #29] +1001238e: 2906 cmp r1, #6 +10012390: bf08 it eq +10012392: f8df 2964 ldreq.w r2, [pc, #2404] ; 10012cf8 <.text_89> +10012396: d003 beq.n 100123a0 +10012398: 2907 cmp r1, #7 +1001239a: d102 bne.n 100123a2 +1001239c: f8df 295c ldr.w r2, [pc, #2396] ; 10012cfc <.text_90> +100123a0: 9203 str r2, [sp, #12] +100123a2: 9005 str r0, [sp, #20] +100123a4: 2205 movs r2, #5 +100123a6: 9204 str r2, [sp, #16] +100123a8: 2001 movs r0, #1 +100123aa: 9002 str r0, [sp, #8] +100123ac: 2200 movs r2, #0 +100123ae: 9206 str r2, [sp, #24] +100123b0: f88d 101c strb.w r1, [sp, #28] +100123b4: 9201 str r2, [sp, #4] +100123b6: 9200 str r2, [sp, #0] +100123b8: a800 add r0, sp, #0 +100123ba: f00e f89a bl 100204f2 +100123be: b009 add sp, #36 ; 0x24 +100123c0: bd00 pop {pc} + +100123c2 : +100123c2: b510 push {r4, lr} +100123c4: 4604 mov r4, r0 +100123c6: 2100 movs r1, #0 +100123c8: 2000 movs r0, #0 +100123ca: f00e fa9e bl 1002090a +100123ce: f8df 1930 ldr.w r1, [pc, #2352] ; 10012d00 <.text_91> +100123d2: 1909 adds r1, r1, r4 +100123d4: f000 000f and.w r0, r0, #15 +100123d8: 780a ldrb r2, [r1, #0] +100123da: f002 02fb and.w r2, r2, #251 ; 0xfb +100123de: f042 0201 orr.w r2, r2, #1 +100123e2: 700a strb r2, [r1, #0] +100123e4: f8df 191c ldr.w r1, [pc, #2332] ; 10012d04 <.text_92> +100123e8: 1909 adds r1, r1, r4 +100123ea: 780a ldrb r2, [r1, #0] +100123ec: f042 02fa orr.w r2, r2, #250 ; 0xfa +100123f0: 700a strb r2, [r1, #0] +100123f2: f8df 1914 ldr.w r1, [pc, #2324] ; 10012d08 <.text_93> +100123f6: 1909 adds r1, r1, r4 +100123f8: 780a ldrb r2, [r1, #0] +100123fa: f042 021f orr.w r2, r2, #31 +100123fe: 700a strb r2, [r1, #0] +10012400: f8df 1908 ldr.w r1, [pc, #2312] ; 10012d0c <.text_94> +10012404: 1909 adds r1, r1, r4 +10012406: 780a ldrb r2, [r1, #0] +10012408: f042 020e orr.w r2, r2, #14 +1001240c: 700a strb r2, [r1, #0] +1001240e: f64f 71fd movw r1, #65533 ; 0xfffd +10012412: f8df 28fc ldr.w r2, [pc, #2300] ; 10012d10 <.text_95> +10012416: 6011 str r1, [r2, #0] +10012418: f8df 1b20 ldr.w r1, [pc, #2848] ; 10012f3c <.text_108> +1001241c: 1909 adds r1, r1, r4 +1001241e: 780a ldrb r2, [r1, #0] +10012420: f002 02c0 and.w r2, r2, #192 ; 0xc0 +10012424: 4310 orrs r0, r2 +10012426: 7008 strb r0, [r1, #0] +10012428: bd10 pop {r4, pc} + +1001242a : +1001242a: f8df 28e8 ldr.w r2, [pc, #2280] ; 10012d14 <.text_96> +1001242e: 1852 adds r2, r2, r1 +10012430: 7813 ldrb r3, [r2, #0] +10012432: f003 033f and.w r3, r3, #63 ; 0x3f +10012436: 7013 strb r3, [r2, #0] +10012438: f8df 3b04 ldr.w r3, [pc, #2820] ; 10012f40 <.text_109> +1001243c: 1859 adds r1, r3, r1 +1001243e: 2800 cmp r0, #0 +10012440: 7808 ldrb r0, [r1, #0] +10012442: d006 beq.n 10012452 +10012444: f040 0010 orr.w r0, r0, #16 +10012448: 7008 strb r0, [r1, #0] +1001244a: 7810 ldrb r0, [r2, #0] +1001244c: f040 0080 orr.w r0, r0, #128 ; 0x80 +10012450: e005 b.n 1001245e +10012452: f000 00ef and.w r0, r0, #239 ; 0xef +10012456: 7008 strb r0, [r1, #0] +10012458: 7810 ldrb r0, [r2, #0] +1001245a: f040 0040 orr.w r0, r0, #64 ; 0x40 +1001245e: 7010 strb r0, [r2, #0] +10012460: 4770 bx lr + +10012462 : +10012462: f8df 2a18 ldr.w r2, [pc, #2584] ; 10012e7c <.text_102> +10012466: 7a13 ldrb r3, [r2, #8] +10012468: 7812 ldrb r2, [r2, #0] +1001246a: 1cdb adds r3, r3, #3 +1001246c: b29b uxth r3, r3 +1001246e: 429a cmp r2, r3 +10012470: d000 beq.n 10012474 +10012472: 4770 bx lr +10012474: b510 push {r4, lr} +10012476: 79c3 ldrb r3, [r0, #7] +10012478: f8df 4a04 ldr.w r4, [pc, #2564] ; 10012e80 <.text_103> +1001247c: f8df 2ac4 ldr.w r2, [pc, #2756] ; 10012f44 <.text_110> +10012480: 2b0e cmp r3, #14 +10012482: d10d bne.n 100124a0 +10012484: b9f9 cbnz r1, 100124c6 +10012486: 7801 ldrb r1, [r0, #0] +10012488: f001 017f and.w r1, r1, #127 ; 0x7f +1001248c: 7001 strb r1, [r0, #0] +1001248e: 7811 ldrb r1, [r2, #0] +10012490: f001 017f and.w r1, r1, #127 ; 0x7f +10012494: 7011 strb r1, [r2, #0] +10012496: 220c movs r2, #12 +10012498: 2101 movs r1, #1 +1001249a: f000 f914 bl 100126c6 +1001249e: e010 b.n 100124c2 +100124a0: 2b06 cmp r3, #6 +100124a2: d110 bne.n 100124c6 +100124a4: b179 cbz r1, 100124c6 +100124a6: 7801 ldrb r1, [r0, #0] +100124a8: f001 01bf and.w r1, r1, #191 ; 0xbf +100124ac: 7001 strb r1, [r0, #0] +100124ae: 7811 ldrb r1, [r2, #0] +100124b0: f041 0140 orr.w r1, r1, #64 ; 0x40 +100124b4: 7011 strb r1, [r2, #0] +100124b6: 7811 ldrb r1, [r2, #0] +100124b8: f041 0180 orr.w r1, r1, #128 ; 0x80 +100124bc: 7011 strb r1, [r2, #0] +100124be: 2104 movs r1, #4 +100124c0: 71c1 strb r1, [r0, #7] +100124c2: 2000 movs r0, #0 +100124c4: 7020 strb r0, [r4, #0] +100124c6: bd10 pop {r4, pc} + +100124c8 : +100124c8: b510 push {r4, lr} +100124ca: f8df 39b8 ldr.w r3, [pc, #2488] ; 10012e84 <.text_104> +100124ce: f8df 49b8 ldr.w r4, [pc, #2488] ; 10012e88 <.text_105> +100124d2: 7018 strb r0, [r3, #0] +100124d4: 01c0 lsls r0, r0, #7 +100124d6: f500 00f0 add.w r0, r0, #7864320 ; 0x780000 +100124da: 0b03 lsrs r3, r0, #12 +100124dc: 0500 lsls r0, r0, #20 +100124de: 0d00 lsrs r0, r0, #20 +100124e0: f5a0 4000 sub.w r0, r0, #32768 ; 0x8000 +100124e4: 8023 strh r3, [r4, #0] +100124e6: b280 uxth r0, r0 +100124e8: b131 cbz r1, 100124f8 +100124ea: f8df 1a5c ldr.w r1, [pc, #2652] ; 10012f48 <.text_111> +100124ee: 1809 adds r1, r1, r0 +100124f0: 780b ldrb r3, [r1, #0] +100124f2: f043 0380 orr.w r3, r3, #128 ; 0x80 +100124f6: 700b strb r3, [r1, #0] +100124f8: f24c 04c0 movw r4, #49344 ; 0xc0c0 +100124fc: f8df 1a4c ldr.w r1, [pc, #2636] ; 10012f4c <.text_112> +10012500: 1809 adds r1, r1, r0 +10012502: 880b ldrh r3, [r1, #0] +10012504: 4023 ands r3, r4 +10012506: 800b strh r3, [r1, #0] +10012508: f8df 17f8 ldr.w r1, [pc, #2040] ; 10012d04 <.text_92> +1001250c: 1809 adds r1, r1, r0 +1001250e: 780b ldrb r3, [r1, #0] +10012510: f003 0301 and.w r3, r3, #1 +10012514: ea43 0282 orr.w r2, r3, r2, lsl #2 +10012518: f042 0202 orr.w r2, r2, #2 +1001251c: 700a strb r2, [r1, #0] +1001251e: 21ff movs r1, #255 ; 0xff +10012520: f8df 27e4 ldr.w r2, [pc, #2020] ; 10012d08 <.text_93> +10012524: 5411 strb r1, [r2, r0] +10012526: f8df 1a18 ldr.w r1, [pc, #2584] ; 10012f40 <.text_109> +1001252a: 1809 adds r1, r1, r0 +1001252c: 780a ldrb r2, [r1, #0] +1001252e: f002 02f7 and.w r2, r2, #247 ; 0xf7 +10012532: 700a strb r2, [r1, #0] +10012534: bd10 pop {r4, pc} + +10012536 : +10012536: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +1001253a: f8df 6c0c ldr.w r6, [pc, #3084] ; 10013148 <.text_125> +1001253e: 4680 mov r8, r0 +10012540: 79f0 ldrb r0, [r6, #7] +10012542: 1cc4 adds r4, r0, #3 +10012544: 7830 ldrb r0, [r6, #0] +10012546: 4689 mov r9, r1 +10012548: 4692 mov sl, r2 +1001254a: b1a8 cbz r0, 10012578 +1001254c: f8df 5930 ldr.w r5, [pc, #2352] ; 10012e80 <.text_103> +10012550: 782f ldrb r7, [r5, #0] +10012552: 20ff movs r0, #255 ; 0xff +10012554: 7028 strb r0, [r5, #0] +10012556: f000 f834 bl 100125c2 +1001255a: 2801 cmp r0, #1 +1001255c: d106 bne.n 1001256c +1001255e: f000 f81a bl 10012596 <.text_41> +10012562: f000 f81c bl 1001259e <.text_42> +10012566: 4620 mov r0, r4 +10012568: f7ff ff2b bl 100123c2 +1001256c: 702f strb r7, [r5, #0] +1001256e: 4649 mov r1, r9 +10012570: 4640 mov r0, r8 +10012572: f7ff ff76 bl 10012462 +10012576: e009 b.n 1001258c +10012578: 4640 mov r0, r8 +1001257a: f7ff ff72 bl 10012462 +1001257e: f000 f80a bl 10012596 <.text_41> +10012582: f000 f80c bl 1001259e <.text_42> +10012586: 4620 mov r0, r4 +10012588: f7ff ff1b bl 100123c2 +1001258c: 2020 movs r0, #32 +1001258e: 70b0 strb r0, [r6, #2] +10012590: 2001 movs r0, #1 +10012592: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + +10012596 <.text_41>: +10012596: 4652 mov r2, sl +10012598: 2101 movs r1, #1 +1001259a: b2e0 uxtb r0, r4 +1001259c: e794 b.n 100124c8 + +1001259e <.text_42>: +1001259e: 4604 mov r4, r0 +100125a0: 4621 mov r1, r4 +100125a2: 4648 mov r0, r9 +100125a4: e741 b.n 1001242a + +100125a6 : +100125a6: b510 push {r4, lr} +100125a8: f8df 4b9c ldr.w r4, [pc, #2972] ; 10013148 <.text_125> +100125ac: 79e0 ldrb r0, [r4, #7] +100125ae: 7821 ldrb r1, [r4, #0] +100125b0: b931 cbnz r1, 100125c0 +100125b2: 1c80 adds r0, r0, #2 +100125b4: 2218 movs r2, #24 +100125b6: b2c0 uxtb r0, r0 +100125b8: f7ff ff86 bl 100124c8 +100125bc: 2020 movs r0, #32 +100125be: 70a0 strb r0, [r4, #2] +100125c0: bd10 pop {r4, pc} + +100125c2 : +100125c2: b510 push {r4, lr} +100125c4: f240 34e9 movw r4, #1001 ; 0x3e9 +100125c8: e003 b.n 100125d2 +100125ca: 2032 movs r0, #50 ; 0x32 +100125cc: f001 fc4d bl 10013e6a +100125d0: 1e64 subs r4, r4, #1 +100125d2: f8df 0b78 ldr.w r0, [pc, #2936] ; 1001314c <.text_126> +100125d6: 6800 ldr r0, [r0, #0] +100125d8: b908 cbnz r0, 100125de +100125da: 2001 movs r0, #1 +100125dc: bd10 pop {r4, pc} +100125de: 2c00 cmp r4, #0 +100125e0: d1f3 bne.n 100125ca +100125e2: f8df 0b6c ldr.w r0, [pc, #2924] ; 10013150 <.text_127> +100125e6: 7801 ldrb r1, [r0, #0] +100125e8: f041 0120 orr.w r1, r1, #32 +100125ec: 7001 strb r1, [r0, #0] +100125ee: f8df 0618 ldr.w r0, [pc, #1560] ; 10012c08 <.text_79> +100125f2: 6800 ldr r0, [r0, #0] +100125f4: 0040 lsls r0, r0, #1 +100125f6: bf44 itt mi +100125f8: f20f 000c addwmi r0, pc, #12 +100125fc: f7f1 fd20 blmi 10004040 +10012600: 2000 movs r0, #0 +10012602: bd10 pop {r4, pc} +10012604: 0000 movs r0, r0 + ... + +10012608 : +10012608: 3c0d 5746 455f 5252 573e 6961 5474 5378 .WaitTxS +10012618: 6174 6574 614d 6863 6e69 4f65 206b 6f70 tateMachineOk po +10012628: 6c6c 6620 6961 216c 000a 0000 ll fail!.... + +10012634 : +10012634: b580 push {r7, lr} +10012636: f7ff ffc4 bl 100125c2 +1001263a: f8df 0c78 ldr.w r0, [pc, #3192] ; 100132b4 <.text_140> +1001263e: f8df 2c78 ldr.w r2, [pc, #3192] ; 100132b8 <.text_141> +10012642: f000 f817 bl 10012674 <.text_48> +10012646: f000 f815 bl 10012674 <.text_48> +1001264a: 6801 ldr r1, [r0, #0] +1001264c: f421 3100 bic.w r1, r1, #131072 ; 0x20000 +10012650: 6001 str r1, [r0, #0] +10012652: 213f movs r1, #63 ; 0x3f +10012654: f8df 0c64 ldr.w r0, [pc, #3172] ; 100132bc <.text_142> +10012658: 7001 strb r1, [r0, #0] +1001265a: 2108 movs r1, #8 +1001265c: 7011 strb r1, [r2, #0] +1001265e: 7841 ldrb r1, [r0, #1] +10012660: f001 01fd and.w r1, r1, #253 ; 0xfd +10012664: 7041 strb r1, [r0, #1] +10012666: f8df 0cb4 ldr.w r0, [pc, #3252] ; 1001331c <.text_147> +1001266a: 7801 ldrb r1, [r0, #0] +1001266c: f041 0120 orr.w r1, r1, #32 +10012670: 7001 strb r1, [r0, #0] +10012672: bd01 pop {r0, pc} + +10012674 <.text_48>: +10012674: 6801 ldr r1, [r0, #0] +10012676: f421 3100 bic.w r1, r1, #131072 ; 0x20000 +1001267a: 6001 str r1, [r0, #0] +1001267c: 6801 ldr r1, [r0, #0] +1001267e: f441 3100 orr.w r1, r1, #131072 ; 0x20000 +10012682: 6001 str r1, [r0, #0] +10012684: 4770 bx lr + +10012686 : +10012686: f8df 0c34 ldr.w r0, [pc, #3124] ; 100132bc <.text_142> +1001268a: 7841 ldrb r1, [r0, #1] +1001268c: f041 0102 orr.w r1, r1, #2 +10012690: 7041 strb r1, [r0, #1] +10012692: 21ff movs r1, #255 ; 0xff +10012694: 7001 strb r1, [r0, #0] +10012696: 2109 movs r1, #9 +10012698: f8df 0c84 ldr.w r0, [pc, #3204] ; 10013320 <.text_148> +1001269c: 70c1 strb r1, [r0, #3] +1001269e: 2186 movs r1, #134 ; 0x86 +100126a0: 7001 strb r1, [r0, #0] +100126a2: f8df 0c10 ldr.w r0, [pc, #3088] ; 100132b4 <.text_140> +100126a6: 6801 ldr r1, [r0, #0] +100126a8: f441 3100 orr.w r1, r1, #131072 ; 0x20000 +100126ac: 6001 str r1, [r0, #0] +100126ae: 4770 bx lr + +100126b0 : +100126b0: b918 cbnz r0, 100126ba +100126b2: b139 cbz r1, 100126c4 +100126b4: 2002 movs r0, #2 +100126b6: f7fa bb51 b.w 1000cd5c +100126ba: 2900 cmp r1, #0 +100126bc: bf04 itt eq +100126be: 2006 moveq r0, #6 +100126c0: f7fa bb4e beq.w 1000cd60 +100126c4: 4770 bx lr + +100126c6 : +100126c6: b538 push {r3, r4, r5, lr} +100126c8: 4604 mov r4, r0 +100126ca: 4615 mov r5, r2 +100126cc: b119 cbz r1, 100126d6 +100126ce: 2902 cmp r1, #2 +100126d0: d00c beq.n 100126ec +100126d2: d305 bcc.n 100126e0 +100126d4: bd31 pop {r0, r4, r5, pc} +100126d6: 7820 ldrb r0, [r4, #0] +100126d8: f365 0000 bfi r0, r5, #0, #1 +100126dc: 7020 strb r0, [r4, #0] +100126de: bd31 pop {r0, r4, r5, pc} +100126e0: 79e0 ldrb r0, [r4, #7] +100126e2: 4629 mov r1, r5 +100126e4: f7ff ffe4 bl 100126b0 +100126e8: 71e5 strb r5, [r4, #7] +100126ea: bd31 pop {r0, r4, r5, pc} +100126ec: 71a5 strb r5, [r4, #6] +100126ee: bd31 pop {r0, r4, r5, pc} + +100126f0 : +100126f0: f8df 0c30 ldr.w r0, [pc, #3120] ; 10013324 <.text_149> +100126f4: 8800 ldrh r0, [r0, #0] +100126f6: 0540 lsls r0, r0, #21 +100126f8: 0d40 lsrs r0, r0, #21 +100126fa: f240 71ff movw r1, #2047 ; 0x7ff +100126fe: 4288 cmp r0, r1 +10012700: d001 beq.n 10012706 +10012702: 2000 movs r0, #0 +10012704: 4770 bx lr +10012706: 2001 movs r0, #1 +10012708: 4770 bx lr + +1001270a : +1001270a: b538 push {r3, r4, r5, lr} +1001270c: f641 31a4 movw r1, #7076 ; 0x1ba4 +10012710: 2218 movs r2, #24 +10012712: 580c ldr r4, [r1, r0] +10012714: f504 5524 add.w r5, r4, #10496 ; 0x2900 +10012718: 35a4 adds r5, #164 ; 0xa4 +1001271a: 2100 movs r1, #0 +1001271c: 4628 mov r0, r5 +1001271e: f7f9 fe15 bl 1000c34c +10012722: 2002 movs r0, #2 +10012724: 70e8 strb r0, [r5, #3] +10012726: 2200 movs r2, #0 +10012728: 2001 movs r0, #1 +1001272a: 72a8 strb r0, [r5, #10] +1001272c: 72e8 strb r0, [r5, #11] +1001272e: 2100 movs r1, #0 +10012730: 2007 movs r0, #7 +10012732: 7328 strb r0, [r5, #12] +10012734: 2001 movs r0, #1 +10012736: 8228 strh r0, [r5, #16] +10012738: f000 fede bl 100134f8 <.text_165+0x2> +1001273c: 220c movs r2, #12 +1001273e: 2102 movs r1, #2 +10012740: f000 feda bl 100134f8 <.text_165+0x2> +10012744: 220c movs r2, #12 +10012746: 2101 movs r1, #1 +10012748: f000 fed6 bl 100134f8 <.text_165+0x2> +1001274c: f8df 07f4 ldr.w r0, [pc, #2036] ; 10012f44 <.text_110> +10012750: 7801 ldrb r1, [r0, #0] +10012752: f001 017f and.w r1, r1, #127 ; 0x7f +10012756: 7001 strb r1, [r0, #0] +10012758: 6841 ldr r1, [r0, #4] +1001275a: f421 21e0 bic.w r1, r1, #458752 ; 0x70000 +1001275e: 6041 str r1, [r0, #4] +10012760: 2000 movs r0, #0 +10012762: f8df 171c ldr.w r1, [pc, #1820] ; 10012e80 <.text_103> +10012766: 7008 strb r0, [r1, #0] +10012768: f642 11bc movw r1, #10684 ; 0x29bc +1001276c: 5508 strb r0, [r1, r4] +1001276e: bd31 pop {r0, r4, r5, pc} + +10012770 : +10012770: b500 push {lr} +10012772: f641 31a4 movw r1, #7076 ; 0x1ba4 +10012776: b087 sub sp, #28 +10012778: 5809 ldr r1, [r1, r0] +1001277a: f501 5124 add.w r1, r1, #10496 ; 0x2900 +1001277e: f811 2fa4 ldrb.w r2, [r1, #164]! +10012782: f002 02fb and.w r2, r2, #251 ; 0xfb +10012786: 700a strb r2, [r1, #0] +10012788: 2200 movs r2, #0 +1001278a: 734a strb r2, [r1, #13] +1001278c: 738a strb r2, [r1, #14] +1001278e: 720a strb r2, [r1, #8] +10012790: 784a ldrb r2, [r1, #1] +10012792: f002 02b7 and.w r2, r2, #183 ; 0xb7 +10012796: 704a strb r2, [r1, #1] +10012798: 2101 movs r1, #1 +1001279a: f8df 2b8c ldr.w r2, [pc, #2956] ; 10013328 <.text_150> +1001279e: 6011 str r1, [r2, #0] +100127a0: f44f 3100 mov.w r1, #131072 ; 0x20000 +100127a4: f8df 2b10 ldr.w r2, [pc, #2832] ; 100132b8 <.text_141> +100127a8: 6011 str r1, [r2, #0] +100127aa: 2200 movs r2, #0 +100127ac: 2100 movs r1, #0 +100127ae: 9103 str r1, [sp, #12] +100127b0: a903 add r1, sp, #12 +100127b2: 604a str r2, [r1, #4] +100127b4: 2201 movs r2, #1 +100127b6: 608a str r2, [r1, #8] +100127b8: 2100 movs r1, #0 +100127ba: 9100 str r1, [sp, #0] +100127bc: 2200 movs r2, #0 +100127be: a900 add r1, sp, #0 +100127c0: 604a str r2, [r1, #4] +100127c2: 2202 movs r2, #2 +100127c4: 608a str r2, [r1, #8] +100127c6: a903 add r1, sp, #12 +100127c8: aa00 add r2, sp, #0 +100127ca: f00e fe2b bl 10021424 +100127ce: b007 add sp, #28 +100127d0: bd00 pop {pc} + +100127d2 : +100127d2: b530 push {r4, r5, lr} +100127d4: f000 fc24 bl 10013020 <.text_122> +100127d8: b087 sub sp, #28 +100127da: 5900 ldr r0, [r0, r4] +100127dc: f8df 1ad8 ldr.w r1, [pc, #2776] ; 100132b8 <.text_141> +100127e0: f500 5524 add.w r5, r0, #10496 ; 0x2900 +100127e4: f04f 701e mov.w r0, #41418752 ; 0x2780000 +100127e8: 6008 str r0, [r1, #0] +100127ea: f000 fd2d bl 10013248 <.text_134> +100127ee: a800 add r0, sp, #0 +100127f0: 9100 str r1, [sp, #0] +100127f2: 6041 str r1, [r0, #4] +100127f4: 6081 str r1, [r0, #8] +100127f6: 35a4 adds r5, #164 ; 0xa4 +100127f8: f000 fec6 bl 10013588 <.text_172+0x4> +100127fc: f8df 0c80 ldr.w r0, [pc, #3200] ; 10013480 <.text_158> +10012800: 6801 ldr r1, [r0, #0] +10012802: f441 21e0 orr.w r1, r1, #458752 ; 0x70000 +10012806: 6001 str r1, [r0, #0] +10012808: 8a28 ldrh r0, [r5, #16] +1001280a: f8df 1c78 ldr.w r1, [pc, #3192] ; 10013484 <.text_159> +1001280e: 7008 strb r0, [r1, #0] +10012810: f000 fc0a bl 10013028 <.text_123> +10012814: 2801 cmp r0, #1 +10012816: 7868 ldrb r0, [r5, #1] +10012818: d10b bne.n 10012832 +1001281a: f000 00fb and.w r0, r0, #251 ; 0xfb +1001281e: 7068 strb r0, [r5, #1] +10012820: 79e8 ldrb r0, [r5, #7] +10012822: 0740 lsls r0, r0, #29 +10012824: d408 bmi.n 10012838 +10012826: 2201 movs r2, #1 +10012828: 2104 movs r1, #4 +1001282a: 4620 mov r0, r4 +1001282c: f000 fa84 bl 10012d38 +10012830: e002 b.n 10012838 +10012832: f040 0004 orr.w r0, r0, #4 +10012836: 7068 strb r0, [r5, #1] +10012838: b007 add sp, #28 +1001283a: bd30 pop {r4, r5, pc} + +1001283c : +1001283c: b570 push {r4, r5, r6, lr} +1001283e: f000 fbef bl 10013020 <.text_122> +10012842: b086 sub sp, #24 +10012844: 5900 ldr r0, [r0, r4] +10012846: f500 5524 add.w r5, r0, #10496 ; 0x2900 +1001284a: 35a4 adds r5, #164 ; 0xa4 +1001284c: bb61 cbnz r1, 100128a8 +1001284e: 2000 movs r0, #0 +10012850: 9003 str r0, [sp, #12] +10012852: aa00 add r2, sp, #0 +10012854: a803 add r0, sp, #12 +10012856: 6041 str r1, [r0, #4] +10012858: 6081 str r1, [r0, #8] +1001285a: f04f 701e mov.w r0, #41418752 ; 0x2780000 +1001285e: 9000 str r0, [sp, #0] +10012860: f000 f827 bl 100128b2 <.text_57> +10012864: f000 fd54 bl 10013310 <.text_146> +10012868: 68f1 ldr r1, [r6, #12] +1001286a: 2006 movs r0, #6 +1001286c: 4788 blx r1 +1001286e: f000 fbdb bl 10013028 <.text_123> +10012872: b948 cbnz r0, 10012888 +10012874: f7ff ff07 bl 10012686 +10012878: 4628 mov r0, r5 +1001287a: f000 f8ff bl 10012a7c +1001287e: 7828 ldrb r0, [r5, #0] +10012880: f000 003f and.w r0, r0, #63 ; 0x3f +10012884: 7028 strb r0, [r5, #0] +10012886: e004 b.n 10012892 +10012888: 2201 movs r2, #1 +1001288a: 210c movs r1, #12 +1001288c: 4620 mov r0, r4 +1001288e: f000 fa53 bl 10012d38 +10012892: 7828 ldrb r0, [r5, #0] +10012894: f000 00f7 and.w r0, r0, #247 ; 0xf7 +10012898: 7028 strb r0, [r5, #0] +1001289a: f8df 0be4 ldr.w r0, [pc, #3044] ; 10013480 <.text_158> +1001289e: 6801 ldr r1, [r0, #0] +100128a0: f421 21e0 bic.w r1, r1, #458752 ; 0x70000 +100128a4: 6001 str r1, [r0, #0] +100128a6: e002 b.n 100128ae +100128a8: 4620 mov r0, r4 +100128aa: f7ff ff92 bl 100127d2 +100128ae: b006 add sp, #24 +100128b0: bd70 pop {r4, r5, r6, pc} + +100128b2 <.text_57>: +100128b2: a800 add r0, sp, #0 +100128b4: 6041 str r1, [r0, #4] +100128b6: 6081 str r1, [r0, #8] +100128b8: 4620 mov r0, r4 +100128ba: a903 add r1, sp, #12 +100128bc: f00e bdb2 b.w 10021424 + +100128c0 : +100128c0: 2901 cmp r1, #1 +100128c2: d008 beq.n 100128d6 +100128c4: 2902 cmp r1, #2 +100128c6: d10a bne.n 100128de +100128c8: 2a00 cmp r2, #0 +100128ca: bf0c ite eq +100128cc: 2107 moveq r1, #7 +100128ce: 1e51 subne r1, r2, #1 +100128d0: 7281 strb r1, [r0, #10] +100128d2: 7a81 ldrb r1, [r0, #10] +100128d4: 72c1 strb r1, [r0, #11] +100128d6: 7841 ldrb r1, [r0, #1] +100128d8: f041 0108 orr.w r1, r1, #8 +100128dc: 7041 strb r1, [r0, #1] +100128de: 4770 bx lr + +100128e0 : +100128e0: b570 push {r4, r5, r6, lr} +100128e2: 4605 mov r5, r0 +100128e4: f641 30a4 movw r0, #7076 ; 0x1ba4 +100128e8: 460c mov r4, r1 +100128ea: 5940 ldr r0, [r0, r5] +100128ec: f500 5624 add.w r6, r0, #10496 ; 0x2900 +100128f0: 36a4 adds r6, #164 ; 0xa4 +100128f2: 4628 mov r0, r5 +100128f4: f7ff ff3c bl 10012770 +100128f8: 7820 ldrb r0, [r4, #0] +100128fa: f000 017f and.w r1, r0, #127 ; 0x7f +100128fe: 4628 mov r0, r5 +10012900: f7ff ff9c bl 1001283c +10012904: 7820 ldrb r0, [r4, #0] +10012906: 217f movs r1, #127 ; 0x7f +10012908: 4208 tst r0, r1 +1001290a: d007 beq.n 1001291c +1001290c: 7860 ldrb r0, [r4, #1] +1001290e: 78a2 ldrb r2, [r4, #2] +10012910: f000 010f and.w r1, r0, #15 +10012914: 4630 mov r0, r6 +10012916: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +1001291a: e7d1 b.n 100128c0 +1001291c: bd70 pop {r4, r5, r6, pc} + +1001291e : +1001291e: b510 push {r4, lr} +10012920: 4604 mov r4, r0 +10012922: f7ff fee5 bl 100126f0 +10012926: 2801 cmp r0, #1 +10012928: bf02 ittt eq +1001292a: 7820 ldrbeq r0, [r4, #0] +1001292c: f3c0 00c0 ubfxeq r0, r0, #3, #1 +10012930: 2800 cmpeq r0, #0 +10012932: d104 bne.n 1001293e +10012934: 79a0 ldrb r0, [r4, #6] +10012936: 2805 cmp r0, #5 +10012938: da01 bge.n 1001293e +1001293a: 2001 movs r0, #1 +1001293c: bd10 pop {r4, pc} +1001293e: 2000 movs r0, #0 +10012940: bd10 pop {r4, pc} + +10012942 : +10012942: b538 push {r3, r4, r5, lr} +10012944: f641 31a4 movw r1, #7076 ; 0x1ba4 +10012948: 580c ldr r4, [r1, r0] +1001294a: f504 5524 add.w r5, r4, #10496 ; 0x2900 +1001294e: 35a4 adds r5, #164 ; 0xa4 +10012950: f7ff fece bl 100126f0 +10012954: 2801 cmp r0, #1 +10012956: bf02 ittt eq +10012958: 7a28 ldrbeq r0, [r5, #8] +1001295a: 2103 moveq r1, #3 +1001295c: 4208 tsteq r0, r1 +1001295e: d11c bne.n 1001299a +10012960: 79a9 ldrb r1, [r5, #6] +10012962: 2900 cmp r1, #0 +10012964: bf04 itt eq +10012966: 2114 moveq r1, #20 +10012968: 4208 tsteq r0, r1 +1001296a: d116 bne.n 1001299a +1001296c: 7868 ldrb r0, [r5, #1] +1001296e: f3c0 0080 ubfx r0, r0, #2, #1 +10012972: b190 cbz r0, 1001299a +10012974: f642 10bc movw r0, #10684 ; 0x29bc +10012978: 5d00 ldrb r0, [r0, r4] +1001297a: b970 cbnz r0, 1001299a +1001297c: f8df 0bec ldr.w r0, [pc, #3052] ; 1001356c <.text_169> +10012980: 7801 ldrb r1, [r0, #0] +10012982: 0789 lsls r1, r1, #30 +10012984: d409 bmi.n 1001299a +10012986: 7801 ldrb r1, [r0, #0] +10012988: 07c9 lsls r1, r1, #31 +1001298a: d504 bpl.n 10012996 +1001298c: 7800 ldrb r0, [r0, #0] +1001298e: f000 00fc and.w r0, r0, #252 ; 0xfc +10012992: 2880 cmp r0, #128 ; 0x80 +10012994: d001 beq.n 1001299a +10012996: 2001 movs r0, #1 +10012998: bd32 pop {r1, r4, r5, pc} +1001299a: 2000 movs r0, #0 +1001299c: bd32 pop {r1, r4, r5, pc} + +1001299e : +1001299e: f8df 0bd0 ldr.w r0, [pc, #3024] ; 10013570 <.text_170> +100129a2: 7841 ldrb r1, [r0, #1] +100129a4: 2900 cmp r1, #0 +100129a6: bf02 ittt eq +100129a8: f8df 1910 ldreq.w r1, [pc, #2320] ; 100132bc <.text_142> +100129ac: 7809 ldrbeq r1, [r1, #0] +100129ae: 293f cmpeq r1, #63 ; 0x3f +100129b0: d107 bne.n 100129c2 +100129b2: 7801 ldrb r1, [r0, #0] +100129b4: 0789 lsls r1, r1, #30 +100129b6: d504 bpl.n 100129c2 +100129b8: 7800 ldrb r0, [r0, #0] +100129ba: 0700 lsls r0, r0, #28 +100129bc: d401 bmi.n 100129c2 +100129be: 2001 movs r0, #1 +100129c0: 4770 bx lr +100129c2: 2000 movs r0, #0 +100129c4: 4770 bx lr + +100129c6 : +100129c6: b510 push {r4, lr} +100129c8: f641 32a4 movw r2, #7076 ; 0x1ba4 +100129cc: 5812 ldr r2, [r2, r0] +100129ce: f502 5424 add.w r4, r2, #10496 ; 0x2900 +100129d2: 34a4 adds r4, #164 ; 0xa4 +100129d4: b331 cbz r1, 10012a24 +100129d6: 2100 movs r1, #0 +100129d8: f00d ffdb bl 10020992 +100129dc: 2801 cmp r0, #1 +100129de: d121 bne.n 10012a24 +100129e0: 7860 ldrb r0, [r4, #1] +100129e2: f8df 149c ldr.w r1, [pc, #1180] ; 10012e80 <.text_103> +100129e6: f000 00fe and.w r0, r0, #254 ; 0xfe +100129ea: 7060 strb r0, [r4, #1] +100129ec: 2208 movs r2, #8 +100129ee: 200f movs r0, #15 +100129f0: 7008 strb r0, [r1, #0] +100129f2: f8df 0938 ldr.w r0, [pc, #2360] ; 1001332c <.text_151> +100129f6: 7801 ldrb r1, [r0, #0] +100129f8: f001 01bf and.w r1, r1, #191 ; 0xbf +100129fc: 7001 strb r1, [r0, #0] +100129fe: 4620 mov r0, r4 +10012a00: 2100 movs r1, #0 +10012a02: f7ff fd98 bl 10012536 +10012a06: 2801 cmp r0, #1 +10012a08: d103 bne.n 10012a12 +10012a0a: 4620 mov r0, r4 +10012a0c: e8bd 4010 ldmia.w sp!, {r4, lr} +10012a10: e040 b.n 10012a94 +10012a12: f000 f895 bl 10012b40 <.text_69> +10012a16: d505 bpl.n 10012a24 +10012a18: e8bd 4010 ldmia.w sp!, {r4, lr} +10012a1c: f20f 0008 addw r0, pc, #8 +10012a20: f7f1 bb0e b.w 10004040 +10012a24: bd10 pop {r4, pc} + ... + +10012a28 : +10012a28: 5b0d 3253 7420 206f 3053 4520 7272 726f .[S2 to S0 Error +10012a38: 3a5d 6320 6e61 6e20 746f 5420 2078 6e61 ]: can not Tx an +10012a48: 2064 6562 7520 6c6e 636f 656b 2064 7962 d be unlocked by +10012a58: 6420 6972 6576 2c72 2020 7473 7961 6920 driver, stay i +10012a68: 206e 7563 7272 6e65 2074 7473 7461 0a65 n current state. +10012a78: 0000 0000 .... + +10012a7c : +10012a7c: f8df 14c4 ldr.w r1, [pc, #1220] ; 10012f44 <.text_110> +10012a80: 780a ldrb r2, [r1, #0] +10012a82: f002 027f and.w r2, r2, #127 ; 0x7f +10012a86: 700a strb r2, [r1, #0] +10012a88: 2100 movs r1, #0 +10012a8a: f8df 23f4 ldr.w r2, [pc, #1012] ; 10012e80 <.text_103> +10012a8e: 7011 strb r1, [r2, #0] +10012a90: 220c movs r2, #12 +10012a92: e0a0 b.n 10012bd6 <.text_77+0x2> + +10012a94 : +10012a94: b580 push {r7, lr} +10012a96: f8df 1894 ldr.w r1, [pc, #2196] ; 1001332c <.text_151> +10012a9a: 780a ldrb r2, [r1, #0] +10012a9c: f002 027f and.w r2, r2, #127 ; 0x7f +10012aa0: 700a strb r2, [r1, #0] +10012aa2: 2101 movs r1, #1 +10012aa4: 220c movs r2, #12 +10012aa6: e05d b.n 10012b64 <.text_71> + +10012aa8 : +10012aa8: b510 push {r4, lr} +10012aaa: f000 fc09 bl 100132c0 <.text_143> +10012aae: 2801 cmp r0, #1 +10012ab0: d11b bne.n 10012aea +10012ab2: 7860 ldrb r0, [r4, #1] +10012ab4: f8df 13c8 ldr.w r1, [pc, #968] ; 10012e80 <.text_103> +10012ab8: f000 00fd and.w r0, r0, #253 ; 0xfd +10012abc: 7060 strb r0, [r4, #1] +10012abe: 2208 movs r2, #8 +10012ac0: 206f movs r0, #111 ; 0x6f +10012ac2: 7008 strb r0, [r1, #0] +10012ac4: 2101 movs r1, #1 +10012ac6: 4620 mov r0, r4 +10012ac8: f7ff fd35 bl 10012536 +10012acc: 2801 cmp r0, #1 +10012ace: d103 bne.n 10012ad8 +10012ad0: 4620 mov r0, r4 +10012ad2: e8bd 4010 ldmia.w sp!, {r4, lr} +10012ad6: e038 b.n 10012b4a +10012ad8: f000 f832 bl 10012b40 <.text_69> +10012adc: d505 bpl.n 10012aea +10012ade: e8bd 4010 ldmia.w sp!, {r4, lr} +10012ae2: f20f 0008 addw r0, pc, #8 +10012ae6: f7f1 baab b.w 10004040 +10012aea: bd10 pop {r4, pc} + +10012aec : +10012aec: 5b0d 3053 7420 206f 3253 4520 7272 726f .[S0 to S2 Error +10012afc: 3a5d 6320 6e61 6e20 746f 5420 2078 6e61 ]: can not Tx an +10012b0c: 2064 6562 7520 6c6e 636f 656b 2064 7962 d be unlocked by +10012b1c: 6420 6972 6576 2c72 2020 7473 7961 6920 driver, stay i +10012b2c: 206e 7563 7272 6e65 2074 7473 7461 0a65 n current state. +10012b3c: 0000 0000 .... + +10012b40 <.text_69>: +10012b40: f8df 0cc4 ldr.w r0, [pc, #3268] ; 10013808 <.text_177> +10012b44: 6800 ldr r0, [r0, #0] +10012b46: 0040 lsls r0, r0, #1 +10012b48: 4770 bx lr + +10012b4a : +10012b4a: b580 push {r7, lr} +10012b4c: f8df 13f4 ldr.w r1, [pc, #1012] ; 10012f44 <.text_110> +10012b50: 780a ldrb r2, [r1, #0] +10012b52: f042 0240 orr.w r2, r2, #64 ; 0x40 +10012b56: 700a strb r2, [r1, #0] +10012b58: 780a ldrb r2, [r1, #0] +10012b5a: f042 0280 orr.w r2, r2, #128 ; 0x80 +10012b5e: 700a strb r2, [r1, #0] +10012b60: 2101 movs r1, #1 +10012b62: 2204 movs r2, #4 + +10012b64 <.text_71>: +10012b64: f7ff fdaf bl 100126c6 +10012b68: f000 f801 bl 10012b6e <.text_72> +10012b6c: bd01 pop {r0, pc} + +10012b6e <.text_72>: +10012b6e: 49c4 ldr r1, [pc, #784] ; (10012e80 <.text_103>) +10012b70: 2000 movs r0, #0 +10012b72: 7008 strb r0, [r1, #0] +10012b74: 4770 bx lr + +10012b76 : +10012b76: b530 push {r4, r5, lr} +10012b78: f000 fa52 bl 10013020 <.text_122> +10012b7c: b087 sub sp, #28 +10012b7e: 5905 ldr r5, [r0, r4] +10012b80: 49bf ldr r1, [pc, #764] ; (10012e80 <.text_103>) +10012b82: 20ff movs r0, #255 ; 0xff +10012b84: 7008 strb r0, [r1, #0] +10012b86: f7ff fd1c bl 100125c2 +10012b8a: f04f 7000 mov.w r0, #33554432 ; 0x2000000 +10012b8e: f8df 1728 ldr.w r1, [pc, #1832] ; 100132b8 <.text_141> +10012b92: f000 fcef bl 10013574 <.text_171> +10012b96: f7ff fd4d bl 10012634 +10012b9a: f505 5024 add.w r0, r5, #10496 ; 0x2900 +10012b9e: 2200 movs r2, #0 +10012ba0: 2101 movs r1, #1 +10012ba2: 30a4 adds r0, #164 ; 0xa4 +10012ba4: f7ff fd8f bl 100126c6 +10012ba8: 4620 mov r0, r4 +10012baa: f7ff fb64 bl 10012276 +10012bae: b007 add sp, #28 +10012bb0: bd30 pop {r4, r5, pc} + +10012bb2 : +10012bb2: 4ab3 ldr r2, [pc, #716] ; (10012e80 <.text_103>) +10012bb4: 216f movs r1, #111 ; 0x6f +10012bb6: 7011 strb r1, [r2, #0] +10012bb8: 2202 movs r2, #2 +10012bba: e00c b.n 10012bd6 <.text_77+0x2> + +10012bbc : +10012bbc: b538 push {r3, r4, r5, lr} +10012bbe: 4604 mov r4, r0 +10012bc0: 460d mov r5, r1 +10012bc2: f7ff fd60 bl 10012686 +10012bc6: b10d cbz r5, 10012bcc +10012bc8: f7ff ffd1 bl 10012b6e <.text_72> +10012bcc: 4620 mov r0, r4 +10012bce: e8bd 4038 ldmia.w sp!, {r3, r4, r5, lr} +10012bd2: e7ff b.n 10012bd4 <.text_77> + +10012bd4 <.text_77>: +10012bd4: 2204 movs r2, #4 +10012bd6: 2101 movs r1, #1 +10012bd8: e575 b.n 100126c6 + +10012bda : +10012bda: b538 push {r3, r4, r5, lr} +10012bdc: f000 fa20 bl 10013020 <.text_122> +10012be0: 49a7 ldr r1, [pc, #668] ; (10012e80 <.text_103>) +10012be2: 5905 ldr r5, [r0, r4] +10012be4: 20ff movs r0, #255 ; 0xff +10012be6: 7008 strb r0, [r1, #0] +10012be8: f7ff fd24 bl 10012634 +10012bec: f505 5024 add.w r0, r5, #10496 ; 0x2900 +10012bf0: 2208 movs r2, #8 +10012bf2: 2101 movs r1, #1 +10012bf4: 30a4 adds r0, #164 ; 0xa4 +10012bf6: f7ff fd66 bl 100126c6 +10012bfa: 4620 mov r0, r4 +10012bfc: e8bd 4032 ldmia.w sp!, {r1, r4, r5, lr} +10012c00: f7ff bb39 b.w 10012276 +10012c04: 0000 movs r0, r0 + ... + +10012c08 <.text_79>: +10012c08: 10000314 .word 0x10000314 + +10012c0c : +10012c0c: b510 push {r4, lr} +10012c0e: 4604 mov r4, r0 +10012c10: f7ff fd39 bl 10012686 +10012c14: f7ff ffab bl 10012b6e <.text_72> +10012c18: 220c movs r2, #12 +10012c1a: 4620 mov r0, r4 +10012c1c: e8bd 4010 ldmia.w sp!, {r4, lr} +10012c20: e7d9 b.n 10012bd6 <.text_77+0x2> + +10012c22 : +10012c22: b570 push {r4, r5, r6, lr} +10012c24: 4604 mov r4, r0 +10012c26: 2500 movs r5, #0 +10012c28: f8df 6be0 ldr.w r6, [pc, #3040] ; 1001380c <.text_178> +10012c2c: 8830 ldrh r0, [r6, #0] +10012c2e: 05c0 lsls r0, r0, #23 +10012c30: bf43 ittte mi +10012c32: 8830 ldrhmi r0, [r6, #0] +10012c34: 0a40 lsrmi r0, r0, #9 +10012c36: f000 0001 andmi.w r0, r0, #1 +10012c3a: 2000 movpl r0, #0 +10012c3c: 4284 cmp r4, r0 +10012c3e: d019 beq.n 10012c74 +10012c40: f241 3088 movw r0, #5000 ; 0x1388 +10012c44: 4285 cmp r5, r0 +10012c46: db05 blt.n 10012c54 +10012c48: f7ff ff7a bl 10012b40 <.text_69> +10012c4c: d512 bpl.n 10012c74 +10012c4e: f60f 30f8 addw r0, pc, #3064 ; 0xbf8 +10012c52: e00b b.n 10012c6c +10012c54: 1c6d adds r5, r5, #1 +10012c56: 2014 movs r0, #20 +10012c58: f001 f907 bl 10013e6a +10012c5c: b2ad uxth r5, r5 +10012c5e: 2d33 cmp r5, #51 ; 0x33 +10012c60: dbe4 blt.n 10012c2c +10012c62: f7ff ff6d bl 10012b40 <.text_69> +10012c66: d505 bpl.n 10012c74 +10012c68: f60f 400c addw r0, pc, #3084 ; 0xc0c +10012c6c: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +10012c70: f7f1 b9e6 b.w 10004040 +10012c74: bd70 pop {r4, r5, r6, pc} + +10012c76 : +10012c76: b510 push {r4, lr} +10012c78: 7841 ldrb r1, [r0, #1] +10012c7a: f8df 4b94 ldr.w r4, [pc, #2964] ; 10013810 <.text_179> +10012c7e: f041 0110 orr.w r1, r1, #16 +10012c82: 7041 strb r1, [r0, #1] +10012c84: f8d4 101e ldr.w r1, [r4, #30] +10012c88: f441 3140 orr.w r1, r1, #196608 ; 0x30000 +10012c8c: f8c4 101e str.w r1, [r4, #30] +10012c90: 7940 ldrb r0, [r0, #5] +10012c92: b138 cbz r0, 10012ca4 +10012c94: f8df 0b7c ldr.w r0, [pc, #2940] ; 10013814 <.text_180> +10012c98: 7801 ldrb r1, [r0, #0] +10012c9a: 0609 lsls r1, r1, #24 +10012c9c: bf4c ite mi +10012c9e: 2110 movmi r1, #16 +10012ca0: 2190 movpl r1, #144 ; 0x90 +10012ca2: 7001 strb r1, [r0, #0] +10012ca4: 8820 ldrh r0, [r4, #0] +10012ca6: f440 7040 orr.w r0, r0, #768 ; 0x300 +10012caa: 8020 strh r0, [r4, #0] +10012cac: 2001 movs r0, #1 +10012cae: f7ff ffb8 bl 10012c22 +10012cb2: 7fa0 ldrb r0, [r4, #30] +10012cb4: f040 0004 orr.w r0, r0, #4 +10012cb8: 77a0 strb r0, [r4, #30] +10012cba: bd10 pop {r4, pc} + +10012cbc : +10012cbc: b510 push {r4, lr} +10012cbe: 4604 mov r4, r0 +10012cc0: f8df 0b4c ldr.w r0, [pc, #2892] ; 10013810 <.text_179> +10012cc4: 7f81 ldrb r1, [r0, #30] +10012cc6: f041 0101 orr.w r1, r1, #1 +10012cca: 7781 strb r1, [r0, #30] +10012ccc: 7f81 ldrb r1, [r0, #30] +10012cce: 07c9 lsls r1, r1, #31 +10012cd0: d4fc bmi.n 10012ccc +10012cd2: f64f 42ff movw r2, #64767 ; 0xfcff +10012cd6: 8801 ldrh r1, [r0, #0] +10012cd8: 4011 ands r1, r2 +10012cda: 8001 strh r1, [r0, #0] +10012cdc: 2000 movs r0, #0 +10012cde: f7ff ffa0 bl 10012c22 +10012ce2: 7860 ldrb r0, [r4, #1] +10012ce4: f000 00ef and.w r0, r0, #239 ; 0xef +10012ce8: 7060 strb r0, [r4, #1] +10012cea: bd10 pop {r4, pc} +10012cec: 0000 movs r0, r0 + ... + +10012cf0 <.text_87>: +10012cf0: 10000318 .word 0x10000318 + +10012cf4 <.text_88>: +10012cf4: 40080692 .word 0x40080692 + +10012cf8 <.text_89>: +10012cf8: 100122c9 .word 0x100122c9 + +10012cfc <.text_90>: +10012cfc: 100122f7 .word 0x100122f7 + +10012d00 <.text_91>: +10012d00: 4008000d .word 0x4008000d + +10012d04 <.text_92>: +10012d04: 40080012 .word 0x40080012 + +10012d08 <.text_93>: +10012d08: 40080011 .word 0x40080011 + +10012d0c <.text_94>: +10012d0c: 40080006 .word 0x40080006 + +10012d10 <.text_95>: +10012d10: 400804a4 .word 0x400804a4 + +10012d14 <.text_96>: +10012d14: 40080009 .word 0x40080009 + +10012d18 : +10012d18: b510 push {r4, lr} +10012d1a: 4604 mov r4, r0 +10012d1c: 79e0 ldrb r0, [r4, #7] +10012d1e: 2800 cmp r0, #0 +10012d20: bf18 it ne +10012d22: 2808 cmpne r0, #8 +10012d24: d107 bne.n 10012d36 +10012d26: f7ff fe3a bl 1001299e +10012d2a: 2801 cmp r0, #1 +10012d2c: d103 bne.n 10012d36 +10012d2e: 4620 mov r0, r4 +10012d30: e8bd 4010 ldmia.w sp!, {r4, lr} +10012d34: e79f b.n 10012c76 +10012d36: bd10 pop {r4, pc} + +10012d38 : +10012d38: b570 push {r4, r5, r6, lr} +10012d3a: f000 f971 bl 10013020 <.text_122> +10012d3e: 4615 mov r5, r2 +10012d40: 5900 ldr r0, [r0, r4] +10012d42: f500 5624 add.w r6, r0, #10496 ; 0x2900 +10012d46: 22c0 movs r2, #192 ; 0xc0 +10012d48: f816 0fa4 ldrb.w r0, [r6, #164]! +10012d4c: 4210 tst r0, r2 +10012d4e: d165 bne.n 10012e1c +10012d50: 79f0 ldrb r0, [r6, #7] +10012d52: 4288 cmp r0, r1 +10012d54: d062 beq.n 10012e1c +10012d56: b361 cbz r1, 10012db2 +10012d58: 2902 cmp r1, #2 +10012d5a: d040 beq.n 10012dde +10012d5c: 2904 cmp r1, #4 +10012d5e: d019 beq.n 10012d94 +10012d60: 2908 cmp r1, #8 +10012d62: d051 beq.n 10012e08 +10012d64: 290c cmp r1, #12 +10012d66: d159 bne.n 10012e1c +10012d68: b908 cbnz r0, 10012d6e +10012d6a: f000 f858 bl 10012e1e <.text_99> +10012d6e: 79f0 ldrb r0, [r6, #7] +10012d70: 2804 cmp r0, #4 +10012d72: d108 bne.n 10012d86 +10012d74: b125 cbz r5, 10012d80 +10012d76: 4629 mov r1, r5 +10012d78: 4620 mov r0, r4 +10012d7a: f7ff fe24 bl 100129c6 +10012d7e: e002 b.n 10012d86 +10012d80: 4630 mov r0, r6 +10012d82: f7ff fe7b bl 10012a7c +10012d86: 79f0 ldrb r0, [r6, #7] +10012d88: 2808 cmp r0, #8 +10012d8a: d147 bne.n 10012e1c +10012d8c: 4630 mov r0, r6 +10012d8e: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +10012d92: e73b b.n 10012c0c +10012d94: b908 cbnz r0, 10012d9a +10012d96: f000 f842 bl 10012e1e <.text_99> +10012d9a: 79f0 ldrb r0, [r6, #7] +10012d9c: 280c cmp r0, #12 +10012d9e: d13d bne.n 10012e1c +10012da0: 4630 mov r0, r6 +10012da2: f7ff fdbc bl 1001291e +10012da6: 2801 cmp r0, #1 +10012da8: d138 bne.n 10012e1c +10012daa: 4620 mov r0, r4 +10012dac: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +10012db0: e67a b.n 10012aa8 +10012db2: 280c cmp r0, #12 +10012db4: d107 bne.n 10012dc6 +10012db6: 4630 mov r0, r6 +10012db8: f7ff fdb1 bl 1001291e +10012dbc: 2801 cmp r0, #1 +10012dbe: bf04 itt eq +10012dc0: 4620 moveq r0, r4 +10012dc2: f7ff fe71 bleq 10012aa8 +10012dc6: 79f0 ldrb r0, [r6, #7] +10012dc8: 2804 cmp r0, #4 +10012dca: d127 bne.n 10012e1c +10012dcc: 4620 mov r0, r4 +10012dce: f7ff fdb8 bl 10012942 +10012dd2: 2801 cmp r0, #1 +10012dd4: d122 bne.n 10012e1c +10012dd6: 4620 mov r0, r4 +10012dd8: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +10012ddc: e6cb b.n 10012b76 +10012dde: 280c cmp r0, #12 +10012de0: d107 bne.n 10012df2 +10012de2: 4630 mov r0, r6 +10012de4: f7ff fd9b bl 1001291e +10012de8: 2801 cmp r0, #1 +10012dea: bf04 itt eq +10012dec: 4620 moveq r0, r4 +10012dee: f7ff fe5b bleq 10012aa8 +10012df2: 79f0 ldrb r0, [r6, #7] +10012df4: b908 cbnz r0, 10012dfa +10012df6: f000 f812 bl 10012e1e <.text_99> +10012dfa: 79f0 ldrb r0, [r6, #7] +10012dfc: 2804 cmp r0, #4 +10012dfe: d10d bne.n 10012e1c +10012e00: 4630 mov r0, r6 +10012e02: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +10012e06: e6d4 b.n 10012bb2 +10012e08: 280c cmp r0, #12 +10012e0a: d107 bne.n 10012e1c +10012e0c: 7870 ldrb r0, [r6, #1] +10012e0e: f3c0 0080 ubfx r0, r0, #2, #1 +10012e12: b118 cbz r0, 10012e1c +10012e14: 4620 mov r0, r4 +10012e16: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +10012e1a: e6de b.n 10012bda +10012e1c: bd70 pop {r4, r5, r6, pc} + +10012e1e <.text_99>: +10012e1e: 2101 movs r1, #1 +10012e20: 4630 mov r0, r6 +10012e22: e6cb b.n 10012bbc + +10012e24 : +10012e24: f641 31a4 movw r1, #7076 ; 0x1ba4 +10012e28: f642 13aa movw r3, #10666 ; 0x29aa +10012e2c: 5809 ldr r1, [r1, r0] +10012e2e: 5c59 ldrb r1, [r3, r1] +10012e30: 2201 movs r2, #1 +10012e32: e781 b.n 10012d38 + +10012e34 : +10012e34: b538 push {r3, r4, r5, lr} +10012e36: f641 31a4 movw r1, #7076 ; 0x1ba4 +10012e3a: f8df 59dc ldr.w r5, [pc, #2524] ; 10013818 <.text_181> +10012e3e: 5808 ldr r0, [r1, r0] +10012e40: f500 5424 add.w r4, r0, #10496 ; 0x2900 +10012e44: f814 0fa4 ldrb.w r0, [r4, #164]! +10012e48: f3c0 00c0 ubfx r0, r0, #3, #1 +10012e4c: b110 cbz r0, 10012e54 +10012e4e: 6929 ldr r1, [r5, #16] +10012e50: 2007 movs r0, #7 +10012e52: 4788 blx r1 +10012e54: f8df 19c4 ldr.w r1, [pc, #2500] ; 1001381c <.text_182> +10012e58: 2002 movs r0, #2 +10012e5a: 7008 strb r0, [r1, #0] +10012e5c: 2007 movs r0, #7 +10012e5e: 68e9 ldr r1, [r5, #12] +10012e60: 4788 blx r1 +10012e62: f44f 5170 mov.w r1, #15360 ; 0x3c00 +10012e66: 2007 movs r0, #7 +10012e68: f7ff fa03 bl 10012272 +10012e6c: 2007 movs r0, #7 +10012e6e: f7ff f9f7 bl 10012260 +10012e72: 7820 ldrb r0, [r4, #0] +10012e74: f040 0008 orr.w r0, r0, #8 +10012e78: 7020 strb r0, [r4, #0] +10012e7a: bd31 pop {r0, r4, r5, pc} + +10012e7c <.text_102>: +10012e7c: 4008041c .word 0x4008041c + +10012e80 <.text_103>: +10012e80: 40080522 .word 0x40080522 + +10012e84 <.text_104>: +10012e84: 40080425 .word 0x40080425 + +10012e88 <.text_105>: +10012e88: 40080140 .word 0x40080140 + +10012e8c : +10012e8c: b538 push {r3, r4, r5, lr} +10012e8e: f000 f893 bl 10012fb8 <.text_116> +10012e92: 4620 mov r0, r4 +10012e94: f7ff ffce bl 10012e34 +10012e98: 79e8 ldrb r0, [r5, #7] +10012e9a: 280c cmp r0, #12 +10012e9c: d00a beq.n 10012eb4 +10012e9e: f000 f979 bl 10013194 <.text_130> +10012ea2: f7ff fe64 bl 10012b6e <.text_72> +10012ea6: 2208 movs r2, #8 +10012ea8: 4628 mov r0, r5 +10012eaa: e8bd 4038 ldmia.w sp!, {r3, r4, r5, lr} +10012eae: 2100 movs r1, #0 +10012eb0: f7ff bb41 b.w 10012536 +10012eb4: bd31 pop {r0, r4, r5, pc} + +10012eb6 : +10012eb6: b538 push {r3, r4, r5, lr} +10012eb8: f641 31a4 movw r1, #7076 ; 0x1ba4 +10012ebc: 5809 ldr r1, [r1, r0] +10012ebe: f501 5424 add.w r4, r1, #10496 ; 0x2900 +10012ec2: f8df 195c ldr.w r1, [pc, #2396] ; 10013820 <.text_183> +10012ec6: 880d ldrh r5, [r1, #0] +10012ec8: 34a4 adds r4, #164 ; 0xa4 +10012eca: f44f 4140 mov.w r1, #49152 ; 0xc000 +10012ece: 420d tst r5, r1 +10012ed0: d104 bne.n 10012edc +10012ed2: 7a21 ldrb r1, [r4, #8] +10012ed4: f001 01fc and.w r1, r1, #252 ; 0xfc +10012ed8: 7221 strb r1, [r4, #8] +10012eda: e25a b.n 10013392 <.text_155> +10012edc: 0469 lsls r1, r5, #17 +10012ede: d511 bpl.n 10012f04 +10012ee0: 7921 ldrb r1, [r4, #4] +10012ee2: 2901 cmp r1, #1 +10012ee4: d112 bne.n 10012f0c +10012ee6: 7a21 ldrb r1, [r4, #8] +10012ee8: f041 0101 orr.w r1, r1, #1 +10012eec: 7221 strb r1, [r4, #8] +10012eee: 78a1 ldrb r1, [r4, #2] +10012ef0: f001 010f and.w r1, r1, #15 +10012ef4: 2902 cmp r1, #2 +10012ef6: d002 beq.n 10012efe +10012ef8: f7ff fb55 bl 100125a6 +10012efc: e006 b.n 10012f0c +10012efe: f7ff ffc5 bl 10012e8c +10012f02: e003 b.n 10012f0c +10012f04: 7a20 ldrb r0, [r4, #8] +10012f06: f000 00fe and.w r0, r0, #254 ; 0xfe +10012f0a: 7220 strb r0, [r4, #8] +10012f0c: 0429 lsls r1, r5, #16 +10012f0e: 7a20 ldrb r0, [r4, #8] +10012f10: d50f bpl.n 10012f32 +10012f12: f040 0002 orr.w r0, r0, #2 +10012f16: 7220 strb r0, [r4, #8] +10012f18: f44f 5170 mov.w r1, #15360 ; 0x3c00 +10012f1c: 2006 movs r0, #6 +10012f1e: f7ff f9a8 bl 10012272 +10012f22: 2006 movs r0, #6 +10012f24: f7ff f99c bl 10012260 +10012f28: 7820 ldrb r0, [r4, #0] +10012f2a: f040 0004 orr.w r0, r0, #4 +10012f2e: 7020 strb r0, [r4, #0] +10012f30: bd31 pop {r0, r4, r5, pc} +10012f32: f000 00fd and.w r0, r0, #253 ; 0xfd +10012f36: 7220 strb r0, [r4, #8] +10012f38: bd31 pop {r0, r4, r5, pc} + ... + +10012f3c <.text_108>: +10012f3c: 40080014 .word 0x40080014 + +10012f40 <.text_109>: +10012f40: 40080029 .word 0x40080029 + +10012f44 <.text_110>: +10012f44: 40080604 .word 0x40080604 + +10012f48 <.text_111>: +10012f48: 40080021 .word 0x40080021 + +10012f4c <.text_112>: +10012f4c: 40080020 .word 0x40080020 + +10012f50 : +10012f50: b538 push {r3, r4, r5, lr} +10012f52: f000 f831 bl 10012fb8 <.text_116> +10012f56: 7928 ldrb r0, [r5, #4] +10012f58: b368 cbz r0, 10012fb6 +10012f5a: f000 f865 bl 10013028 <.text_123> +10012f5e: 2801 cmp r0, #1 +10012f60: d129 bne.n 10012fb6 +10012f62: 78a8 ldrb r0, [r5, #2] +10012f64: 0900 lsrs r0, r0, #4 +10012f66: d00c beq.n 10012f82 +10012f68: 2802 cmp r0, #2 +10012f6a: d000 beq.n 10012f6e +10012f6c: d223 bcs.n 10012fb6 +10012f6e: 7ae8 ldrb r0, [r5, #11] +10012f70: 1e40 subs r0, r0, #1 +10012f72: 72e8 strb r0, [r5, #11] +10012f74: b2c0 uxtb r0, r0 +10012f76: b110 cbz r0, 10012f7e +10012f78: 7b68 ldrb r0, [r5, #13] +10012f7a: b910 cbnz r0, 10012f82 +10012f7c: bd31 pop {r0, r4, r5, pc} +10012f7e: 7aa8 ldrb r0, [r5, #10] +10012f80: 72e8 strb r0, [r5, #11] +10012f82: 7a28 ldrb r0, [r5, #8] +10012f84: f040 0010 orr.w r0, r0, #16 +10012f88: 7228 strb r0, [r5, #8] +10012f8a: 7b68 ldrb r0, [r5, #13] +10012f8c: 0001 movs r1, r0 +10012f8e: bf17 itett ne +10012f90: 2801 cmpne r0, #1 +10012f92: 1dc0 addeq r0, r0, #7 +10012f94: eb00 0040 addne.w r0, r0, r0, lsl #1 +10012f98: 1d40 addne r0, r0, #5 +10012f9a: 0281 lsls r1, r0, #10 +10012f9c: 2006 movs r0, #6 +10012f9e: f7ff f968 bl 10012272 +10012fa2: 2006 movs r0, #6 +10012fa4: f7ff f95c bl 10012260 +10012fa8: 79e8 ldrb r0, [r5, #7] +10012faa: 0740 lsls r0, r0, #29 +10012fac: d403 bmi.n 10012fb6 +10012fae: 4620 mov r0, r4 +10012fb0: e8bd 4038 ldmia.w sp!, {r3, r4, r5, lr} +10012fb4: e0f8 b.n 100131a8 <.text_132> +10012fb6: bd31 pop {r0, r4, r5, pc} + +10012fb8 <.text_116>: +10012fb8: 4604 mov r4, r0 +10012fba: f641 30a4 movw r0, #7076 ; 0x1ba4 +10012fbe: 5900 ldr r0, [r0, r4] +10012fc0: f500 5524 add.w r5, r0, #10496 ; 0x2900 +10012fc4: 35a4 adds r5, #164 ; 0xa4 +10012fc6: 4770 bx lr + +10012fc8 : +10012fc8: b530 push {r4, r5, lr} +10012fca: f000 f829 bl 10013020 <.text_122> +10012fce: b087 sub sp, #28 +10012fd0: f000 f8c0 bl 10013154 <.text_128> +10012fd4: b1e8 cbz r0, 10013012 +10012fd6: f000 f827 bl 10013028 <.text_123> +10012fda: 2801 cmp r0, #1 +10012fdc: d119 bne.n 10013012 +10012fde: 7aa8 ldrb r0, [r5, #10] +10012fe0: f8df 1840 ldr.w r1, [pc, #2112] ; 10013824 <.text_184> +10012fe4: 7008 strb r0, [r1, #0] +10012fe6: f44f 51e0 mov.w r1, #7168 ; 0x1c00 +10012fea: 2000 movs r0, #0 +10012fec: 72e8 strb r0, [r5, #11] +10012fee: 7a28 ldrb r0, [r5, #8] +10012ff0: f040 0010 orr.w r0, r0, #16 +10012ff4: 7228 strb r0, [r5, #8] +10012ff6: 2006 movs r0, #6 +10012ff8: f7ff f93b bl 10012272 +10012ffc: 2006 movs r0, #6 +10012ffe: f7ff f92f bl 10012260 +10013002: 79e8 ldrb r0, [r5, #7] +10013004: 0740 lsls r0, r0, #29 +10013006: d404 bmi.n 10013012 +10013008: 2201 movs r2, #1 +1001300a: 2104 movs r1, #4 +1001300c: 4620 mov r0, r4 +1001300e: f7ff fe93 bl 10012d38 +10013012: 49a9 ldr r1, [pc, #676] ; (100132b8 <.text_141>) +10013014: f44f 3000 mov.w r0, #131072 ; 0x20000 +10013018: f000 faac bl 10013574 <.text_171> +1001301c: b007 add sp, #28 +1001301e: bd30 pop {r4, r5, pc} + +10013020 <.text_122>: +10013020: 4604 mov r4, r0 +10013022: f641 30a4 movw r0, #7076 ; 0x1ba4 +10013026: 4770 bx lr + +10013028 <.text_123>: +10013028: 2100 movs r1, #0 +1001302a: 4620 mov r0, r4 +1001302c: f00d bcb1 b.w 10020992 + +10013030 : +10013030: b5f0 push {r4, r5, r6, r7, lr} +10013032: f7ff fff5 bl 10013020 <.text_122> +10013036: b087 sub sp, #28 +10013038: f000 f88c bl 10013154 <.text_128> +1001303c: 2800 cmp r0, #0 +1001303e: f000 8080 beq.w 10013142 +10013042: f7ff fff1 bl 10013028 <.text_123> +10013046: 2801 cmp r0, #1 +10013048: d17b bne.n 10013142 +1001304a: 78a8 ldrb r0, [r5, #2] +1001304c: 0900 lsrs r0, r0, #4 +1001304e: 2801 cmp r0, #1 +10013050: d10a bne.n 10013068 +10013052: f8df 07cc ldr.w r0, [pc, #1996] ; 10013820 <.text_183> +10013056: 6800 ldr r0, [r0, #0] +10013058: 0e01 lsrs r1, r0, #24 +1001305a: 72e9 strb r1, [r5, #11] +1001305c: 0c00 lsrs r0, r0, #16 +1001305e: 72a8 strb r0, [r5, #10] +10013060: 7ae8 ldrb r0, [r5, #11] +10013062: b900 cbnz r0, 10013066 +10013064: 7aa8 ldrb r0, [r5, #10] +10013066: 72e8 strb r0, [r5, #11] +10013068: 2000 movs r0, #0 +1001306a: 7368 strb r0, [r5, #13] +1001306c: 73a8 strb r0, [r5, #14] +1001306e: f8df 6414 ldr.w r6, [pc, #1044] ; 10013484 <.text_159> +10013072: 8a28 ldrh r0, [r5, #16] +10013074: f8df 77a0 ldr.w r7, [pc, #1952] ; 10013818 <.text_181> +10013078: 7030 strb r0, [r6, #0] +1001307a: 2006 movs r0, #6 +1001307c: 6939 ldr r1, [r7, #16] +1001307e: 4788 blx r1 +10013080: 68f9 ldr r1, [r7, #12] +10013082: 2006 movs r0, #6 +10013084: 4788 blx r1 +10013086: 7a28 ldrb r0, [r5, #8] +10013088: f000 00ed and.w r0, r0, #237 ; 0xed +1001308c: 7228 strb r0, [r5, #8] +1001308e: 78a8 ldrb r0, [r5, #2] +10013090: 0900 lsrs r0, r0, #4 +10013092: 2802 cmp r0, #2 +10013094: bf9c itt ls +10013096: 4620 movls r0, r4 +10013098: f7ff ff0d blls 10012eb6 +1001309c: 786f ldrb r7, [r5, #1] +1001309e: f3c7 00c0 ubfx r0, r7, #3, #1 +100130a2: 2800 cmp r0, #0 +100130a4: d049 beq.n 1001313a +100130a6: f3c7 1c80 ubfx ip, r7, #6, #1 +100130aa: f1bc 0f00 cmp.w ip, #0 +100130ae: f44f 3100 mov.w r1, #131072 ; 0x20000 +100130b2: 4b9d ldr r3, [pc, #628] ; (10013328 <.text_150>) +100130b4: a800 add r0, sp, #0 +100130b6: aa03 add r2, sp, #12 +100130b8: d11b bne.n 100130f2 +100130ba: f895 c00b ldrb.w ip, [r5, #11] +100130be: f895 e00a ldrb.w lr, [r5, #10] +100130c2: 45f4 cmp ip, lr +100130c4: d139 bne.n 1001313a +100130c6: f047 0740 orr.w r7, r7, #64 ; 0x40 +100130ca: 706f strb r7, [r5, #1] +100130cc: 7aaf ldrb r7, [r5, #10] +100130ce: 76f7 strb r7, [r6, #27] +100130d0: 2602 movs r6, #2 +100130d2: 601e str r6, [r3, #0] +100130d4: 9100 str r1, [sp, #0] +100130d6: 2300 movs r3, #0 +100130d8: 2100 movs r1, #0 +100130da: 6041 str r1, [r0, #4] +100130dc: 6053 str r3, [r2, #4] +100130de: 2101 movs r1, #1 +100130e0: 6081 str r1, [r0, #8] +100130e2: 6096 str r6, [r2, #8] +100130e4: 9303 str r3, [sp, #12] +100130e6: f000 fa4f bl 10013588 <.text_172+0x4> +100130ea: 7ae8 ldrb r0, [r5, #11] +100130ec: 1e40 subs r0, r0, #1 +100130ee: 72e8 strb r0, [r5, #11] +100130f0: e023 b.n 1001313a +100130f2: f895 c002 ldrb.w ip, [r5, #2] +100130f6: ea4f 1c1c mov.w ip, ip, lsr #4 +100130fa: f1bc 0f01 cmp.w ip, #1 +100130fe: d11c bne.n 1001313a +10013100: f895 c00b ldrb.w ip, [r5, #11] +10013104: f895 e00a ldrb.w lr, [r5, #10] +10013108: 45f4 cmp ip, lr +1001310a: bf1c itt ne +1001310c: 7ef6 ldrbne r6, [r6, #27] +1001310e: 45b4 cmpne ip, r6 +10013110: d013 beq.n 1001313a +10013112: f3c7 0680 ubfx r6, r7, #2, #1 +10013116: b186 cbz r6, 1001313a +10013118: f007 06bf and.w r6, r7, #191 ; 0xbf +1001311c: 706e strb r6, [r5, #1] +1001311e: 2601 movs r6, #1 +10013120: 601e str r6, [r3, #0] +10013122: 4b65 ldr r3, [pc, #404] ; (100132b8 <.text_141>) +10013124: 6019 str r1, [r3, #0] +10013126: 9103 str r1, [sp, #12] +10013128: 6096 str r6, [r2, #8] +1001312a: 2100 movs r1, #0 +1001312c: 6051 str r1, [r2, #4] +1001312e: 9100 str r1, [sp, #0] +10013130: 6041 str r1, [r0, #4] +10013132: aa00 add r2, sp, #0 +10013134: 2102 movs r1, #2 +10013136: f7ff fbbe bl 100128b6 <.text_57+0x4> +1001313a: 7868 ldrb r0, [r5, #1] +1001313c: f040 0004 orr.w r0, r0, #4 +10013140: 7068 strb r0, [r5, #1] +10013142: b007 add sp, #28 +10013144: bdf0 pop {r4, r5, r6, r7, pc} + ... + +10013148 <.text_125>: +10013148: 4008041d .word 0x4008041d + +1001314c <.text_126>: +1001314c: 400805f8 .word 0x400805f8 + +10013150 <.text_127>: +10013150: 400801c0 .word 0x400801c0 + +10013154 <.text_128>: +10013154: 5900 ldr r0, [r0, r4] +10013156: f500 5524 add.w r5, r0, #10496 ; 0x2900 +1001315a: 35a4 adds r5, #164 ; 0xa4 +1001315c: 7928 ldrb r0, [r5, #4] +1001315e: 4770 bx lr + +10013160 : +10013160: b510 push {r4, lr} +10013162: f7ff ff5d bl 10013020 <.text_122> +10013166: f000 f819 bl 1001319c <.text_131> +1001316a: 2901 cmp r1, #1 +1001316c: d111 bne.n 10013192 +1001316e: 7881 ldrb r1, [r0, #2] +10013170: 220f movs r2, #15 +10013172: 4211 tst r1, r2 +10013174: d007 beq.n 10013186 +10013176: f000 f80d bl 10013194 <.text_130> +1001317a: f7ff fcf8 bl 10012b6e <.text_72> +1001317e: 4620 mov r0, r4 +10013180: e8bd 4010 ldmia.w sp!, {r4, lr} +10013184: e656 b.n 10012e34 +10013186: 79c0 ldrb r0, [r0, #7] +10013188: b918 cbnz r0, 10013192 +1001318a: 4620 mov r0, r4 +1001318c: e8bd 4010 ldmia.w sp!, {r4, lr} +10013190: e00a b.n 100131a8 <.text_132> +10013192: bd10 pop {r4, pc} + +10013194 <.text_130>: +10013194: 2200 movs r2, #0 +10013196: 210c movs r1, #12 +10013198: 4620 mov r0, r4 +1001319a: e5cd b.n 10012d38 + +1001319c <.text_131>: +1001319c: 5900 ldr r0, [r0, r4] +1001319e: f500 5024 add.w r0, r0, #10496 ; 0x2900 +100131a2: 30a4 adds r0, #164 ; 0xa4 +100131a4: 7901 ldrb r1, [r0, #4] +100131a6: 4770 bx lr + +100131a8 <.text_132>: +100131a8: 2201 movs r2, #1 +100131aa: 2104 movs r1, #4 +100131ac: e5c4 b.n 10012d38 + +100131ae : +100131ae: b530 push {r4, r5, lr} +100131b0: f7ff ff36 bl 10013020 <.text_122> +100131b4: b087 sub sp, #28 +100131b6: 5900 ldr r0, [r0, r4] +100131b8: f500 5524 add.w r5, r0, #10496 ; 0x2900 +100131bc: 35a4 adds r5, #164 ; 0xa4 +100131be: 7868 ldrb r0, [r5, #1] +100131c0: f000 0048 and.w r0, r0, #72 ; 0x48 +100131c4: 2848 cmp r0, #72 ; 0x48 +100131c6: d108 bne.n 100131da +100131c8: 2000 movs r0, #0 +100131ca: f000 f83d bl 10013248 <.text_134> +100131ce: f44f 3000 mov.w r0, #131072 ; 0x20000 +100131d2: 9000 str r0, [sp, #0] +100131d4: aa00 add r2, sp, #0 +100131d6: f7ff fb6c bl 100128b2 <.text_57> +100131da: 7828 ldrb r0, [r5, #0] +100131dc: f3c0 0180 ubfx r1, r0, #2, #1 +100131e0: b119 cbz r1, 100131ea +100131e2: f000 f88b bl 100132fc <.text_145> +100131e6: d12d bne.n 10013244 +100131e8: e029 b.n 1001323e +100131ea: 7b68 ldrb r0, [r5, #13] +100131ec: 1c40 adds r0, r0, #1 +100131ee: 7368 strb r0, [r5, #13] +100131f0: b2c0 uxtb r0, r0 +100131f2: 7a29 ldrb r1, [r5, #8] +100131f4: f001 01ef and.w r1, r1, #239 ; 0xef +100131f8: 2803 cmp r0, #3 +100131fa: 7229 strb r1, [r5, #8] +100131fc: db1f blt.n 1001323e +100131fe: f7ff ff13 bl 10013028 <.text_123> +10013202: 2801 cmp r0, #1 +10013204: d118 bne.n 10013238 +10013206: 78a8 ldrb r0, [r5, #2] +10013208: 210f movs r1, #15 +1001320a: 4208 tst r0, r1 +1001320c: d104 bne.n 10013218 +1001320e: 7868 ldrb r0, [r5, #1] +10013210: f000 00fb and.w r0, r0, #251 ; 0xfb +10013214: 7068 strb r0, [r5, #1] +10013216: e00f b.n 10013238 +10013218: 7ba8 ldrb r0, [r5, #14] +1001321a: 1c40 adds r0, r0, #1 +1001321c: 73a8 strb r0, [r5, #14] +1001321e: b2c0 uxtb r0, r0 +10013220: 2803 cmp r0, #3 +10013222: db06 blt.n 10013232 +10013224: 7868 ldrb r0, [r5, #1] +10013226: f000 00fb and.w r0, r0, #251 ; 0xfb +1001322a: 7068 strb r0, [r5, #1] +1001322c: 2000 movs r0, #0 +1001322e: 73a8 strb r0, [r5, #14] +10013230: e002 b.n 10013238 +10013232: 4620 mov r0, r4 +10013234: f7ff fe2a bl 10012e8c +10013238: 2000 movs r0, #0 +1001323a: 7368 strb r0, [r5, #13] +1001323c: e002 b.n 10013244 +1001323e: 4620 mov r0, r4 +10013240: f7ff fdf0 bl 10012e24 +10013244: b007 add sp, #28 +10013246: bd30 pop {r4, r5, pc} + +10013248 <.text_134>: +10013248: 9003 str r0, [sp, #12] +1001324a: 2100 movs r1, #0 +1001324c: a803 add r0, sp, #12 +1001324e: 6041 str r1, [r0, #4] +10013250: 6081 str r1, [r0, #8] +10013252: 4770 bx lr + +10013254 : +10013254: b510 push {r4, lr} +10013256: 4604 mov r4, r0 +10013258: f641 30a4 movw r0, #7076 ; 0x1ba4 +1001325c: 5900 ldr r0, [r0, r4] +1001325e: f500 5024 add.w r0, r0, #10496 ; 0x2900 +10013262: f810 1fa4 ldrb.w r1, [r0, #164]! +10013266: 07c9 lsls r1, r1, #31 +10013268: bf48 it mi +1001326a: f7ff fd27 blmi 10012cbc +1001326e: 4620 mov r0, r4 +10013270: e8bd 4010 ldmia.w sp!, {r4, lr} +10013274: e66c b.n 10012f50 + +10013276 : +10013276: 4770 bx lr + +10013278 : +10013278: f641 31a4 movw r1, #7076 ; 0x1ba4 +1001327c: f642 12ab movw r2, #10667 ; 0x29ab +10013280: 5809 ldr r1, [r1, r0] +10013282: 5c51 ldrb r1, [r2, r1] +10013284: 2902 cmp r1, #2 +10013286: bf18 it ne +10013288: f7ff bed2 bne.w 10013030 +1001328c: 4770 bx lr + +1001328e : +1001328e: b510 push {r4, lr} +10013290: f000 f816 bl 100132c0 <.text_143> +10013294: 2801 cmp r0, #1 +10013296: d10b bne.n 100132b0 <__iar_annotation$$tailcall+0x2> +10013298: 7920 ldrb r0, [r4, #4] +1001329a: b148 cbz r0, 100132b0 <__iar_annotation$$tailcall+0x2> +1001329c: f8df 4578 ldr.w r4, [pc, #1400] ; 10013818 <.text_181> +100132a0: 6921 ldr r1, [r4, #16] +100132a2: 2006 movs r0, #6 +100132a4: 4788 blx r1 +100132a6: 68e1 ldr r1, [r4, #12] +100132a8: e8bd 4010 ldmia.w sp!, {r4, lr} +100132ac: 2006 movs r0, #6 + +100132ae <__iar_annotation$$tailcall>: +100132ae: 4708 bx r1 +100132b0: bd10 pop {r4, pc} + ... + +100132b4 <.text_140>: +100132b4: 40080004 .word 0x40080004 + +100132b8 <.text_141>: +100132b8: 40080134 .word 0x40080134 + +100132bc <.text_142>: +100132bc: 40080100 .word 0x40080100 + +100132c0 <.text_143>: +100132c0: f641 31a4 movw r1, #7076 ; 0x1ba4 +100132c4: 5809 ldr r1, [r1, r0] +100132c6: f501 5424 add.w r4, r1, #10496 ; 0x2900 +100132ca: 34a4 adds r4, #164 ; 0xa4 +100132cc: 2100 movs r1, #0 +100132ce: f00d bb60 b.w 10020992 + +100132d2 : +100132d2: b570 push {r4, r5, r6, lr} +100132d4: f000 f841 bl 1001335a <.text_153> +100132d8: 2801 cmp r0, #1 +100132da: d10e bne.n 100132fa +100132dc: 7928 ldrb r0, [r5, #4] +100132de: b160 cbz r0, 100132fa +100132e0: f000 f816 bl 10013310 <.text_146> +100132e4: 68f1 ldr r1, [r6, #12] +100132e6: 2006 movs r0, #6 +100132e8: 4788 blx r1 +100132ea: 7828 ldrb r0, [r5, #0] +100132ec: f000 f806 bl 100132fc <.text_145> +100132f0: d103 bne.n 100132fa +100132f2: 4620 mov r0, r4 +100132f4: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +100132f8: e594 b.n 10012e24 +100132fa: bd70 pop {r4, r5, r6, pc} + +100132fc <.text_145>: +100132fc: f000 00fb and.w r0, r0, #251 ; 0xfb +10013300: 7028 strb r0, [r5, #0] +10013302: 2107 movs r1, #7 +10013304: 7a28 ldrb r0, [r5, #8] +10013306: f000 00fd and.w r0, r0, #253 ; 0xfd +1001330a: 4208 tst r0, r1 +1001330c: 7228 strb r0, [r5, #8] +1001330e: 4770 bx lr + +10013310 <.text_146>: +10013310: f8df 6504 ldr.w r6, [pc, #1284] ; 10013818 <.text_181> +10013314: 6931 ldr r1, [r6, #16] +10013316: 2006 movs r0, #6 + +10013318 <__iar_annotation$$tailcall>: +10013318: 4708 bx r1 + ... + +1001331c <.text_147>: +1001331c: 40080553 .word 0x40080553 + +10013320 <.text_148>: +10013320: 400806b4 .word 0x400806b4 + +10013324 <.text_149>: +10013324: 4008041a .word 0x4008041a + +10013328 <.text_150>: +10013328: 40080084 .word 0x40080084 + +1001332c <.text_151>: +1001332c: 40080604 .word 0x40080604 + +10013330 : +10013330: b538 push {r3, r4, r5, lr} +10013332: f000 f812 bl 1001335a <.text_153> +10013336: 2801 cmp r0, #1 +10013338: d10e bne.n 10013358 +1001333a: 7928 ldrb r0, [r5, #4] +1001333c: b160 cbz r0, 10013358 +1001333e: 78a8 ldrb r0, [r5, #2] +10013340: f000 000f and.w r0, r0, #15 +10013344: 2802 cmp r0, #2 +10013346: bf1c itt ne +10013348: e8bd 4031 ldmiane.w sp!, {r0, r4, r5, lr} +1001334c: f7ff b92b bne.w 100125a6 +10013350: 4620 mov r0, r4 +10013352: e8bd 4032 ldmia.w sp!, {r1, r4, r5, lr} +10013356: e599 b.n 10012e8c +10013358: bd31 pop {r0, r4, r5, pc} + +1001335a <.text_153>: +1001335a: 4604 mov r4, r0 +1001335c: f641 30a4 movw r0, #7076 ; 0x1ba4 +10013360: 2100 movs r1, #0 +10013362: 5900 ldr r0, [r0, r4] +10013364: f500 5524 add.w r5, r0, #10496 ; 0x2900 +10013368: 35a4 adds r5, #164 ; 0xa4 +1001336a: 4620 mov r0, r4 +1001336c: f00d bb11 b.w 10020992 + +10013370 : +10013370: b538 push {r3, r4, r5, lr} +10013372: f7ff fff2 bl 1001335a <.text_153> +10013376: 2801 cmp r0, #1 +10013378: d10a bne.n 10013390 +1001337a: 7928 ldrb r0, [r5, #4] +1001337c: b140 cbz r0, 10013390 +1001337e: 7a28 ldrb r0, [r5, #8] +10013380: f000 00fe and.w r0, r0, #254 ; 0xfe +10013384: 2107 movs r1, #7 +10013386: 4208 tst r0, r1 +10013388: 7228 strb r0, [r5, #8] +1001338a: d101 bne.n 10013390 +1001338c: 4620 mov r0, r4 +1001338e: e000 b.n 10013392 <.text_155> +10013390: bd31 pop {r0, r4, r5, pc} + +10013392 <.text_155>: +10013392: e8bd 4032 ldmia.w sp!, {r1, r4, r5, lr} +10013396: e545 b.n 10012e24 + +10013398 : +10013398: f641 31a4 movw r1, #7076 ; 0x1ba4 +1001339c: f642 12a8 movw r2, #10664 ; 0x29a8 +100133a0: 5809 ldr r1, [r1, r0] +100133a2: 5c51 ldrb r1, [r2, r1] +100133a4: 2900 cmp r1, #0 +100133a6: bf18 it ne +100133a8: f7ff beda bne.w 10013160 +100133ac: 4770 bx lr + +100133ae : +100133ae: b5f8 push {r3, r4, r5, r6, r7, lr} +100133b0: f7ff fe36 bl 10013020 <.text_122> +100133b4: 460d mov r5, r1 +100133b6: 5900 ldr r0, [r0, r4] +100133b8: f500 5624 add.w r6, r0, #10496 ; 0x2900 +100133bc: 7828 ldrb r0, [r5, #0] +100133be: 36a4 adds r6, #164 ; 0xa4 +100133c0: f000 007f and.w r0, r0, #127 ; 0x7f +100133c4: 7130 strb r0, [r6, #4] +100133c6: 7828 ldrb r0, [r5, #0] +100133c8: 09c0 lsrs r0, r0, #7 +100133ca: 7170 strb r0, [r6, #5] +100133cc: 78b0 ldrb r0, [r6, #2] +100133ce: 7869 ldrb r1, [r5, #1] +100133d0: f000 00f0 and.w r0, r0, #240 ; 0xf0 +100133d4: ea40 1011 orr.w r0, r0, r1, lsr #4 +100133d8: 70b0 strb r0, [r6, #2] +100133da: 7831 ldrb r1, [r6, #0] +100133dc: 78ea ldrb r2, [r5, #3] +100133de: f001 01fd and.w r1, r1, #253 ; 0xfd +100133e2: f002 0201 and.w r2, r2, #1 +100133e6: ea41 0142 orr.w r1, r1, r2, lsl #1 +100133ea: 7031 strb r1, [r6, #0] +100133ec: f000 000f and.w r0, r0, #15 +100133f0: 7869 ldrb r1, [r5, #1] +100133f2: ea40 1001 orr.w r0, r0, r1, lsl #4 +100133f6: 70b0 strb r0, [r6, #2] +100133f8: 2102 movs r1, #2 +100133fa: 78a8 ldrb r0, [r5, #2] +100133fc: 70f0 strb r0, [r6, #3] +100133fe: 4630 mov r0, r6 +10013400: 792a ldrb r2, [r5, #4] +10013402: f7ff f960 bl 100126c6 +10013406: 4629 mov r1, r5 +10013408: 4620 mov r0, r4 +1001340a: f7ff fa69 bl 100128e0 +1001340e: f8df 53f8 ldr.w r5, [pc, #1016] ; 10013808 <.text_177> +10013412: 682f ldr r7, [r5, #0] +10013414: 2000 movs r0, #0 +10013416: 6028 str r0, [r5, #0] +10013418: 7930 ldrb r0, [r6, #4] +1001341a: 2801 cmp r0, #1 +1001341c: bf18 it ne +1001341e: 2802 cmpne r0, #2 +10013420: d10c bne.n 1001343c +10013422: 2307 movs r3, #7 +10013424: 2206 movs r2, #6 +10013426: 2100 movs r1, #0 +10013428: 4620 mov r0, r4 +1001342a: f7fe ff87 bl 1001233c +1001342e: 230f movs r3, #15 +10013430: 2207 movs r2, #7 +10013432: 2100 movs r1, #0 +10013434: 4620 mov r0, r4 +10013436: f7fe ff81 bl 1001233c +1001343a: e007 b.n 1001344c +1001343c: 2106 movs r1, #6 +1001343e: 4620 mov r0, r4 +10013440: f7fe ffa0 bl 10012384 +10013444: 2107 movs r1, #7 +10013446: 4620 mov r0, r4 +10013448: f7fe ff9c bl 10012384 +1001344c: 602f str r7, [r5, #0] +1001344e: 4620 mov r0, r4 +10013450: f7fe ff2b bl 100122aa +10013454: f8df 13d0 ldr.w r1, [pc, #976] ; 10013828 <.text_185> +10013458: 20ff movs r0, #255 ; 0xff +1001345a: 7008 strb r0, [r1, #0] +1001345c: 6828 ldr r0, [r5, #0] +1001345e: f020 0008 bic.w r0, r0, #8 +10013462: 6028 str r0, [r5, #0] +10013464: f8df 03c4 ldr.w r0, [pc, #964] ; 1001382c <.text_186> +10013468: 6801 ldr r1, [r0, #0] +1001346a: f021 0108 bic.w r1, r1, #8 +1001346e: 6001 str r1, [r0, #0] +10013470: f8df 03bc ldr.w r0, [pc, #956] ; 10013830 <.text_187> +10013474: 6801 ldr r1, [r0, #0] +10013476: f021 0108 bic.w r1, r1, #8 +1001347a: 6001 str r1, [r0, #0] +1001347c: bdf1 pop {r0, r4, r5, r6, r7, pc} + ... + +10013480 <.text_158>: +10013480: 40080608 .word 0x40080608 + +10013484 <.text_159>: +10013484: 40080558 .word 0x40080558 + +10013488 : +10013488: b538 push {r3, r4, r5, lr} +1001348a: 2100 movs r1, #0 +1001348c: 9100 str r1, [sp, #0] +1001348e: f641 31a4 movw r1, #7076 ; 0x1ba4 +10013492: 6884 ldr r4, [r0, #8] +10013494: 580d ldr r5, [r1, r0] +10013496: f000 f829 bl 100134ec <.text_164> +1001349a: f505 5024 add.w r0, r5, #10496 ; 0x2900 +1001349e: 30a4 adds r0, #164 ; 0xa4 +100134a0: f7ff fc3a bl 10012d18 +100134a4: f000 f801 bl 100134aa <.text_161> +100134a8: bd31 pop {r0, r4, r5, pc} + +100134aa <.text_161>: +100134aa: a900 add r1, sp, #0 +100134ac: f104 0020 add.w r0, r4, #32 +100134b0: f7fd ba29 b.w 10010906 + +100134b4 : +100134b4: b570 push {r4, r5, r6, lr} +100134b6: b082 sub sp, #8 +100134b8: f000 f832 bl 10013520 <.text_167> +100134bc: b9a8 cbnz r0, 100134ea +100134be: 2201 movs r2, #1 +100134c0: f000 f819 bl 100134f6 <.text_165> +100134c4: f000 f812 bl 100134ec <.text_164> +100134c8: f7ff f8b4 bl 10012634 +100134cc: 260a movs r6, #10 +100134ce: f7ff fa66 bl 1001299e +100134d2: b118 cbz r0, 100134dc +100134d4: 4628 mov r0, r5 +100134d6: f7ff fbce bl 10012c76 +100134da: e004 b.n 100134e6 +100134dc: 2032 movs r0, #50 ; 0x32 +100134de: f7f3 fb9f bl 10006c20 +100134e2: 1e76 subs r6, r6, #1 +100134e4: d1f3 bne.n 100134ce +100134e6: f7ff ffe0 bl 100134aa <.text_161> +100134ea: bd73 pop {r0, r1, r4, r5, r6, pc} + +100134ec <.text_164>: +100134ec: a900 add r1, sp, #0 +100134ee: f104 0020 add.w r0, r4, #32 +100134f2: f7fd ba01 b.w 100108f8 + +100134f6 <.text_165>: +100134f6: 2100 movs r1, #0 +100134f8: 4628 mov r0, r5 +100134fa: f7ff b8e4 b.w 100126c6 + +100134fe : +100134fe: b538 push {r3, r4, r5, lr} +10013500: f000 f80e bl 10013520 <.text_167> +10013504: b958 cbnz r0, 1001351e +10013506: f7ff fff1 bl 100134ec <.text_164> +1001350a: 4628 mov r0, r5 +1001350c: f7ff fbd6 bl 10012cbc +10013510: 2200 movs r2, #0 +10013512: f7ff fff0 bl 100134f6 <.text_165> +10013516: f7ff f8b6 bl 10012686 +1001351a: f7ff ffc6 bl 100134aa <.text_161> +1001351e: bd31 pop {r0, r4, r5, pc} + +10013520 <.text_167>: +10013520: 2100 movs r1, #0 +10013522: 9100 str r1, [sp, #0] +10013524: f641 31a4 movw r1, #7076 ; 0x1ba4 +10013528: 6884 ldr r4, [r0, #8] +1001352a: 5808 ldr r0, [r1, r0] +1001352c: f500 5524 add.w r5, r0, #10496 ; 0x2900 +10013530: 35a4 adds r5, #164 ; 0xa4 +10013532: 79e8 ldrb r0, [r5, #7] +10013534: 4770 bx lr + +10013536 : +10013536: b510 push {r4, lr} +10013538: 4604 mov r4, r0 +1001353a: 48be ldr r0, [pc, #760] ; (10013834 <.text_188>) +1001353c: b086 sub sp, #24 +1001353e: 6801 ldr r1, [r0, #0] +10013540: f441 6100 orr.w r1, r1, #2048 ; 0x800 +10013544: 6001 str r1, [r0, #0] +10013546: 2100 movs r1, #0 +10013548: 48bb ldr r0, [pc, #748] ; (10013838 <.text_189>) +1001354a: 9003 str r0, [sp, #12] +1001354c: 9100 str r1, [sp, #0] +1001354e: a803 add r0, sp, #12 +10013550: 6041 str r1, [r0, #4] +10013552: 6081 str r1, [r0, #8] +10013554: a800 add r0, sp, #0 +10013556: f000 f815 bl 10013584 <.text_172> +1001355a: 4620 mov r0, r4 +1001355c: f7ff f8d5 bl 1001270a +10013560: 49b6 ldr r1, [pc, #728] ; (1001383c <.text_190>) +10013562: 2028 movs r0, #40 ; 0x28 +10013564: 7008 strb r0, [r1, #0] +10013566: b006 add sp, #24 +10013568: bd10 pop {r4, pc} + ... + +1001356c <.text_169>: +1001356c: 40080662 .word 0x40080662 + +10013570 <.text_170>: +10013570: 40080286 .word 0x40080286 + +10013574 <.text_171>: +10013574: 6008 str r0, [r1, #0] +10013576: 9003 str r0, [sp, #12] +10013578: 2100 movs r1, #0 +1001357a: a803 add r0, sp, #12 +1001357c: 6041 str r1, [r0, #4] +1001357e: 6081 str r1, [r0, #8] +10013580: a800 add r0, sp, #0 +10013582: 9100 str r1, [sp, #0] + +10013584 <.text_172>: +10013584: 6041 str r1, [r0, #4] +10013586: 6081 str r1, [r0, #8] +10013588: aa00 add r2, sp, #0 +1001358a: a903 add r1, sp, #12 +1001358c: 4620 mov r0, r4 +1001358e: f00d bf49 b.w 10021424 + +10013592 : +10013592: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +10013596: 4682 mov sl, r0 +10013598: f641 30a4 movw r0, #7076 ; 0x1ba4 +1001359c: b083 sub sp, #12 +1001359e: f850 500a ldr.w r5, [r0, sl] +100135a2: 4fa7 ldr r7, [pc, #668] ; (10013840 <.text_191>) +100135a4: f505 50c8 add.w r0, r5, #6400 ; 0x1900 +100135a8: f100 0ba8 add.w fp, r0, #168 ; 0xa8 +100135ac: 2000 movs r0, #0 +100135ae: 9001 str r0, [sp, #4] +100135b0: f642 1874 movw r8, #10612 ; 0x2974 +100135b4: 6838 ldr r0, [r7, #0] +100135b6: f858 1005 ldr.w r1, [r8, r5] +100135ba: f8da 4008 ldr.w r4, [sl, #8] +100135be: 4308 orrs r0, r1 +100135c0: 6038 str r0, [r7, #0] +100135c2: f505 5624 add.w r6, r5, #10496 ; 0x2900 +100135c6: 36a4 adds r6, #164 ; 0xa4 +100135c8: a901 add r1, sp, #4 +100135ca: f104 0020 add.w r0, r4, #32 +100135ce: f7fd f993 bl 100108f8 +100135d2: 2000 movs r0, #0 +100135d4: f848 0005 str.w r0, [r8, r5] +100135d8: a901 add r1, sp, #4 +100135da: f104 0020 add.w r0, r4, #32 +100135de: f7fd f992 bl 10010906 +100135e2: e002 b.n 100135ea +100135e4: 4650 mov r0, sl +100135e6: f7ff fc25 bl 10012e34 +100135ea: 6838 ldr r0, [r7, #0] +100135ec: 2800 cmp r0, #0 +100135ee: f000 80fc beq.w 100137ea +100135f2: 4650 mov r0, sl +100135f4: f00d f9af bl 10020956 +100135f8: fa5f f980 uxtb.w r9, r0 +100135fc: f1b9 0f00 cmp.w r9, #0 +10013600: d103 bne.n 1001360a +10013602: 6838 ldr r0, [r7, #0] +10013604: 498f ldr r1, [pc, #572] ; (10013844 <.text_192>) +10013606: 4008 ands r0, r1 +10013608: 6038 str r0, [r7, #0] +1001360a: 2400 movs r4, #0 +1001360c: e008 b.n 10013620 +1001360e: f898 0036 ldrb.w r0, [r8, #54] ; 0x36 +10013612: 9000 str r0, [sp, #0] +10013614: 2300 movs r3, #0 +10013616: 4641 mov r1, r8 +10013618: 4658 mov r0, fp +1001361a: f00e facc bl 10021bb6 +1001361e: 1c64 adds r4, r4, #1 +10013620: b2e4 uxtb r4, r4 +10013622: 4620 mov r0, r4 +10013624: 4548 cmp r0, r9 +10013626: da37 bge.n 10013698 +10013628: 2158 movs r1, #88 ; 0x58 +1001362a: fb01 b000 mla r0, r1, r0, fp +1001362e: f500 78b8 add.w r8, r0, #368 ; 0x170 +10013632: 4621 mov r1, r4 +10013634: 4650 mov r0, sl +10013636: f00d f9ac bl 10020992 +1001363a: 2800 cmp r0, #0 +1001363c: bf1e ittt ne +1001363e: f108 0536 addne.w r5, r8, #54 ; 0x36 +10013642: 78a8 ldrbne r0, [r5, #2] +10013644: 2801 cmpne r0, #1 +10013646: d0ea beq.n 1001361e +10013648: 716c strb r4, [r5, #5] +1001364a: 6838 ldr r0, [r7, #0] +1001364c: 0701 lsls r1, r0, #28 +1001364e: d506 bpl.n 1001365e +10013650: f020 0008 bic.w r0, r0, #8 +10013654: 6038 str r0, [r7, #0] +10013656: 4641 mov r1, r8 +10013658: 4658 mov r0, fp +1001365a: f00e fb58 bl 10021d0e +1001365e: 6838 ldr r0, [r7, #0] +10013660: 07c1 lsls r1, r0, #31 +10013662: d5dc bpl.n 1001361e +10013664: 0840 lsrs r0, r0, #1 +10013666: 0040 lsls r0, r0, #1 +10013668: 6038 str r0, [r7, #0] +1001366a: 2103 movs r1, #3 +1001366c: 7968 ldrb r0, [r5, #5] +1001366e: f00d f94c bl 1002090a +10013672: 0600 lsls r0, r0, #24 +10013674: f100 80b9 bmi.w 100137ea +10013678: 2200 movs r2, #0 +1001367a: 4641 mov r1, r8 +1001367c: 4658 mov r0, fp +1001367e: f00d f99a bl 100209b6 +10013682: f641 5064 movw r0, #7524 ; 0x1d64 +10013686: f810 200a ldrb.w r2, [r0, sl] +1001368a: 2aff cmp r2, #255 ; 0xff +1001368c: d1bf bne.n 1001360e +1001368e: 4641 mov r1, r8 +10013690: 4658 mov r0, fp +10013692: f00e fc27 bl 10021ee4 +10013696: e7c2 b.n 1001361e +10013698: 6838 ldr r0, [r7, #0] +1001369a: 0501 lsls r1, r0, #20 +1001369c: d505 bpl.n 100136aa +1001369e: f420 6000 bic.w r0, r0, #2048 ; 0x800 +100136a2: 6038 str r0, [r7, #0] +100136a4: 4650 mov r0, sl +100136a6: f7ff fc53 bl 10012f50 +100136aa: 6838 ldr r0, [r7, #0] +100136ac: 04c1 lsls r1, r0, #19 +100136ae: d505 bpl.n 100136bc +100136b0: f420 5080 bic.w r0, r0, #4096 ; 0x1000 +100136b4: 6038 str r0, [r7, #0] +100136b6: 4650 mov r0, sl +100136b8: f7ff fc86 bl 10012fc8 +100136bc: 6838 ldr r0, [r7, #0] +100136be: 0481 lsls r1, r0, #18 +100136c0: d508 bpl.n 100136d4 +100136c2: f420 5000 bic.w r0, r0, #8192 ; 0x2000 +100136c6: 6038 str r0, [r7, #0] +100136c8: 79f0 ldrb r0, [r6, #7] +100136ca: 2802 cmp r0, #2 +100136cc: bf1c itt ne +100136ce: 4650 movne r0, sl +100136d0: f7ff fcae blne 10013030 +100136d4: 6838 ldr r0, [r7, #0] +100136d6: 0441 lsls r1, r0, #17 +100136d8: d50b bpl.n 100136f2 +100136da: f420 4080 bic.w r0, r0, #16384 ; 0x4000 +100136de: f000 f886 bl 100137ee <.text_174> +100136e2: 2801 cmp r0, #1 +100136e4: d105 bne.n 100136f2 +100136e6: 7930 ldrb r0, [r6, #4] +100136e8: b118 cbz r0, 100136f2 +100136ea: f000 f885 bl 100137f8 <.text_175> +100136ee: f000 f887 bl 10013800 <.text_176> +100136f2: 6838 ldr r0, [r7, #0] +100136f4: 0401 lsls r1, r0, #16 +100136f6: d519 bpl.n 1001372c +100136f8: f420 4000 bic.w r0, r0, #32768 ; 0x8000 +100136fc: f000 f877 bl 100137ee <.text_174> +10013700: 2801 cmp r0, #1 +10013702: d113 bne.n 1001372c +10013704: 7930 ldrb r0, [r6, #4] +10013706: b188 cbz r0, 1001372c +10013708: f000 f876 bl 100137f8 <.text_175> +1001370c: f000 f878 bl 10013800 <.text_176> +10013710: 7830 ldrb r0, [r6, #0] +10013712: f000 00fb and.w r0, r0, #251 ; 0xfb +10013716: 7030 strb r0, [r6, #0] +10013718: 2107 movs r1, #7 +1001371a: 7a30 ldrb r0, [r6, #8] +1001371c: f000 00fd and.w r0, r0, #253 ; 0xfd +10013720: 7230 strb r0, [r6, #8] +10013722: 4208 tst r0, r1 +10013724: bf04 itt eq +10013726: 4650 moveq r0, sl +10013728: f7ff fb7c bleq 10012e24 +1001372c: 6838 ldr r0, [r7, #0] +1001372e: 03c1 lsls r1, r0, #15 +10013730: d512 bpl.n 10013758 +10013732: f420 3080 bic.w r0, r0, #65536 ; 0x10000 +10013736: f000 f85a bl 100137ee <.text_174> +1001373a: 2801 cmp r0, #1 +1001373c: d10c bne.n 10013758 +1001373e: 7930 ldrb r0, [r6, #4] +10013740: b150 cbz r0, 10013758 +10013742: 78b0 ldrb r0, [r6, #2] +10013744: f000 000f and.w r0, r0, #15 +10013748: 2802 cmp r0, #2 +1001374a: d002 beq.n 10013752 +1001374c: f7fe ff2b bl 100125a6 +10013750: e002 b.n 10013758 +10013752: 4650 mov r0, sl +10013754: f7ff fb9a bl 10012e8c +10013758: 6838 ldr r0, [r7, #0] +1001375a: 0381 lsls r1, r0, #14 +1001375c: d511 bpl.n 10013782 +1001375e: f420 3000 bic.w r0, r0, #131072 ; 0x20000 +10013762: f000 f844 bl 100137ee <.text_174> +10013766: 2801 cmp r0, #1 +10013768: d10b bne.n 10013782 +1001376a: 7930 ldrb r0, [r6, #4] +1001376c: b148 cbz r0, 10013782 +1001376e: 7a30 ldrb r0, [r6, #8] +10013770: f000 00fe and.w r0, r0, #254 ; 0xfe +10013774: 7230 strb r0, [r6, #8] +10013776: 2107 movs r1, #7 +10013778: 4208 tst r0, r1 +1001377a: bf04 itt eq +1001377c: 4650 moveq r0, sl +1001377e: f7ff fb51 bleq 10012e24 +10013782: 6838 ldr r0, [r7, #0] +10013784: 0341 lsls r1, r0, #13 +10013786: d507 bpl.n 10013798 +10013788: f420 2080 bic.w r0, r0, #262144 ; 0x40000 +1001378c: 6038 str r0, [r7, #0] +1001378e: 7930 ldrb r0, [r6, #4] +10013790: b110 cbz r0, 10013798 +10013792: 4650 mov r0, sl +10013794: f7ff fce4 bl 10013160 +10013798: 6838 ldr r0, [r7, #0] +1001379a: 0301 lsls r1, r0, #12 +1001379c: d507 bpl.n 100137ae +1001379e: f420 2000 bic.w r0, r0, #524288 ; 0x80000 +100137a2: 6038 str r0, [r7, #0] +100137a4: 7930 ldrb r0, [r6, #4] +100137a6: b110 cbz r0, 100137ae +100137a8: 4650 mov r0, sl +100137aa: f7ff fd00 bl 100131ae +100137ae: 6838 ldr r0, [r7, #0] +100137b0: 02c1 lsls r1, r0, #11 +100137b2: d519 bpl.n 100137e8 +100137b4: f420 1080 bic.w r0, r0, #1048576 ; 0x100000 +100137b8: 6038 str r0, [r7, #0] +100137ba: 4813 ldr r0, [pc, #76] ; (10013808 <.text_177>) +100137bc: 6800 ldr r0, [r0, #0] +100137be: 0040 lsls r0, r0, #1 +100137c0: bf44 itt mi +100137c2: f20f 00e8 addwmi r0, pc, #232 ; 0xe8 +100137c6: f7f0 fc3b blmi 10004040 +100137ca: 7930 ldrb r0, [r6, #4] +100137cc: 2800 cmp r0, #0 +100137ce: d00b beq.n 100137e8 +100137d0: 4812 ldr r0, [pc, #72] ; (1001381c <.text_182>) +100137d2: 7800 ldrb r0, [r0, #0] +100137d4: 0780 lsls r0, r0, #30 +100137d6: f53f af05 bmi.w 100135e4 +100137da: 7830 ldrb r0, [r6, #0] +100137dc: f000 00f7 and.w r0, r0, #247 ; 0xf7 +100137e0: 7030 strb r0, [r6, #0] +100137e2: 4650 mov r0, sl +100137e4: f7ff fb1e bl 10012e24 +100137e8: e6ff b.n 100135ea +100137ea: e8bd 8ff7 ldmia.w sp!, {r0, r1, r2, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +100137ee <.text_174>: +100137ee: 6038 str r0, [r7, #0] +100137f0: 2100 movs r1, #0 +100137f2: 4650 mov r0, sl +100137f4: f00d b8cd b.w 10020992 + +100137f8 <.text_175>: +100137f8: 4907 ldr r1, [pc, #28] ; (10013818 <.text_181>) +100137fa: 6909 ldr r1, [r1, #16] +100137fc: 2006 movs r0, #6 + +100137fe <__iar_annotation$$tailcall>: +100137fe: 4708 bx r1 + +10013800 <.text_176>: +10013800: 4905 ldr r1, [pc, #20] ; (10013818 <.text_181>) +10013802: 68c9 ldr r1, [r1, #12] +10013804: 2006 movs r0, #6 + +10013806 <__iar_annotation$$tailcall>: +10013806: 4708 bx r1 + +10013808 <.text_177>: +10013808: 10000314 .word 0x10000314 + +1001380c <.text_178>: +1001380c: 400800f0 .word 0x400800f0 + +10013810 <.text_179>: +10013810: 40080002 .word 0x40080002 + +10013814 <.text_180>: +10013814: 4008012f .word 0x4008012f + +10013818 <.text_181>: +10013818: 10000318 .word 0x10000318 + +1001381c <.text_182>: +1001381c: 40080692 .word 0x40080692 + +10013820 <.text_183>: +10013820: 400806a8 .word 0x400806a8 + +10013824 <.text_184>: +10013824: 40080573 .word 0x40080573 + +10013828 <.text_185>: +10013828: 400804c8 .word 0x400804c8 + +1001382c <.text_186>: +1001382c: 10000310 .word 0x10000310 + +10013830 <.text_187>: +10013830: 1000030c .word 0x1000030c + +10013834 <.text_188>: +10013834: 40080100 .word 0x40080100 + +10013838 <.text_189>: +10013838: 20060000 .word 0x20060000 + +1001383c <.text_190>: +1001383c: 4008055c .word 0x4008055c + +10013840 <.text_191>: +10013840: 1004884c .word 0x1004884c + +10013844 <.text_192>: +10013844: fff807f0 .word 0xfff807f0 + +10013848 : +10013848: 57463c0d 5252455f 6568433e 53546b63 .CheckTS +10013858: 53734946 6c626174 6f702065 66206c6c FIsStable poll f +10013868: 206c6961 6d695428 74756f65 000a2129 ail (Timeout)!.. + +10013878 : +10013878: 57463c0d 5252455f 6568433e 53546b63 .CheckTS +10013888: 53734946 6c626174 6f702065 66206c6c FIsStable poll f +10013898: 206c6961 63614228 6f6f446b 0a212972 ail (BackDoor)!. +100138a8: 00000000 .... + +100138ac : +100138ac: 6d69540d 37207265 204f5420 0a525349 .Timer 7 TO ISR. +100138bc: 00000000 .... + +100138c0 : +100138c0: f8df f000 ldr.w pc, [pc] ; 100138c4 +100138c4: 00000355 .word 0x00000355 + +100138c8 : +100138c8: f8df f000 ldr.w pc, [pc] ; 100138cc +100138cc: 00002b39 .word 0x00002b39 + +100138d0 : +100138d0: f8df f000 ldr.w pc, [pc] ; 100138d4 +100138d4: 00003de5 .word 0x00003de5 + +100138d8 : +100138d8: b51f push {r0, r1, r2, r3, r4, lr} +100138da: f8df 43a4 ldr.w r4, [pc, #932] ; 10013c80 +100138de: 2000 movs r0, #0 +100138e0: 6060 str r0, [r4, #4] +100138e2: 2080 movs r0, #128 ; 0x80 +100138e4: 60e0 str r0, [r4, #12] +100138e6: f7ff ffeb bl 100138c0 +100138ea: 0880 lsrs r0, r0, #2 +100138ec: 9900 ldr r1, [sp, #0] +100138ee: 0109 lsls r1, r1, #4 +100138f0: fbb0 f2f1 udiv r2, r0, r1 +100138f4: 230a movs r3, #10 +100138f6: 4358 muls r0, r3 +100138f8: fbb0 f0f1 udiv r0, r0, r1 +100138fc: fb03 0012 mls r0, r3, r2, r0 +10013900: 2805 cmp r0, #5 +10013902: bf28 it cs +10013904: 1c52 addcs r2, r2, #1 +10013906: b2d0 uxtb r0, r2 +10013908: 6020 str r0, [r4, #0] +1001390a: f3c2 2007 ubfx r0, r2, #8, #8 +1001390e: 6060 str r0, [r4, #4] +10013910: 2000 movs r0, #0 +10013912: 60e0 str r0, [r4, #12] +10013914: f89d 100d ldrb.w r1, [sp, #13] +10013918: f89d 000c ldrb.w r0, [sp, #12] +1001391c: 4308 orrs r0, r1 +1001391e: f89d 100e ldrb.w r1, [sp, #14] +10013922: 4308 orrs r0, r1 +10013924: 60e0 str r0, [r4, #12] +10013926: 9801 ldr r0, [sp, #4] +10013928: 60a0 str r0, [r4, #8] +1001392a: 9802 ldr r0, [sp, #8] +1001392c: 6060 str r0, [r4, #4] +1001392e: b1b8 cbz r0, 10013960 +10013930: f04f 7080 mov.w r0, #16777216 ; 0x1000000 +10013934: f8df 134c ldr.w r1, [pc, #844] ; 10013c84 +10013938: 6008 str r0, [r1, #0] +1001393a: f64f 02ff movw r2, #63743 ; 0xf8ff +1001393e: f8df 0348 ldr.w r0, [pc, #840] ; 10013c88 +10013942: 6801 ldr r1, [r0, #0] +10013944: 4011 ands r1, r2 +10013946: f8df 2344 ldr.w r2, [pc, #836] ; 10013c8c +1001394a: 4311 orrs r1, r2 +1001394c: 6001 str r1, [r0, #0] +1001394e: 20e0 movs r0, #224 ; 0xe0 +10013950: f8df 133c ldr.w r1, [pc, #828] ; 10013c90 +10013954: 7008 strb r0, [r1, #0] +10013956: f44f 2000 mov.w r0, #524288 ; 0x80000 +1001395a: f8df 1338 ldr.w r1, [pc, #824] ; 10013c94 +1001395e: 6008 str r0, [r1, #0] + +10013960 : +10013960: 2000 movs r0, #0 +10013962: b004 add sp, #16 +10013964: bd10 pop {r4, pc} + +10013966 : +10013966: b500 push {lr} +10013968: f8df 0314 ldr.w r0, [pc, #788] ; 10013c80 +1001396c: b089 sub sp, #36 ; 0x24 +1001396e: 6800 ldr r0, [r0, #0] +10013970: f8df 0324 ldr.w r0, [pc, #804] ; 10013c98 +10013974: 6801 ldr r1, [r0, #0] +10013976: f421 5180 bic.w r1, r1, #4096 ; 0x1000 +1001397a: 6001 str r1, [r0, #0] +1001397c: 2201 movs r2, #1 +1001397e: 6801 ldr r1, [r0, #0] +10013980: f441 5180 orr.w r1, r1, #4096 ; 0x1000 +10013984: 6001 str r1, [r0, #0] +10013986: 6a01 ldr r1, [r0, #32] +10013988: f441 5180 orr.w r1, r1, #4096 ; 0x1000 +1001398c: 6201 str r1, [r0, #32] +1001398e: 20dc movs r0, #220 ; 0xdc +10013990: 2100 movs r1, #0 +10013992: f7ff ff99 bl 100138c8 +10013996: 2000 movs r0, #0 +10013998: 9006 str r0, [sp, #24] +1001399a: 2058 movs r0, #88 ; 0x58 +1001399c: 9005 str r0, [sp, #20] +1001399e: f8df 02fc ldr.w r0, [pc, #764] ; 10013c9c +100139a2: 9004 str r0, [sp, #16] +100139a4: 2000 movs r0, #0 +100139a6: 9007 str r0, [sp, #28] +100139a8: f44f 4016 mov.w r0, #38400 ; 0x9600 +100139ac: 9000 str r0, [sp, #0] +100139ae: 2003 movs r0, #3 +100139b0: f88d 000e strb.w r0, [sp, #14] +100139b4: 20c1 movs r0, #193 ; 0xc1 +100139b6: 9001 str r0, [sp, #4] +100139b8: 2000 movs r0, #0 +100139ba: 9002 str r0, [sp, #8] +100139bc: f8ad 000c strh.w r0, [sp, #12] +100139c0: a800 add r0, sp, #0 +100139c2: c80f ldmia r0, {r0, r1, r2, r3} +100139c4: f7ff ff88 bl 100138d8 +100139c8: a804 add r0, sp, #16 +100139ca: f7f3 f931 bl 10006c30 +100139ce: 2005 movs r0, #5 +100139d0: 9002 str r0, [sp, #8] +100139d2: a800 add r0, sp, #0 +100139d4: c80f ldmia r0, {r0, r1, r2, r3} +100139d6: f7ff ff7f bl 100138d8 +100139da: b009 add sp, #36 ; 0x24 +100139dc: bd00 pop {pc} + +100139de : +100139de: b580 push {r7, lr} +100139e0: f000 f8cd bl 10013b7e +100139e4: f000 f93f bl 10013c66 + +100139e8 : +100139e8: f8df 02b4 ldr.w r0, [pc, #692] ; 10013ca0 +100139ec: 6801 ldr r1, [r0, #0] +100139ee: f041 4180 orr.w r1, r1, #1073741824 ; 0x40000000 +100139f2: 6001 str r1, [r0, #0] +100139f4: 2100 movs r1, #0 +100139f6: f8df 02ac ldr.w r0, [pc, #684] ; 10013ca4 +100139fa: 6001 str r1, [r0, #0] +100139fc: 6701 str r1, [r0, #112] ; 0x70 +100139fe: 6f81 ldr r1, [r0, #120] ; 0x78 +10013a00: 6781 str r1, [r0, #120] ; 0x78 +10013a02: 2001 movs r0, #1 +10013a04: f8df 12a0 ldr.w r1, [pc, #672] ; 10013ca8 +10013a08: f8c1 0314 str.w r0, [r1, #788] ; 0x314 +10013a0c: bd01 pop {r0, pc} + +10013a0e : +10013a0e: b51f push {r0, r1, r2, r3, r4, lr} +10013a10: f8df 4294 ldr.w r4, [pc, #660] ; 10013ca8 +10013a14: f504 7047 add.w r0, r4, #796 ; 0x31c +10013a18: f000 f928 bl 10013c6c + +10013a1c : +10013a1c: a800 add r0, sp, #0 +10013a1e: f7f3 f90b bl 10006c38 +10013a22: 2000 movs r0, #0 +10013a24: f8c4 0314 str.w r0, [r4, #788] ; 0x314 +10013a28: bd1f pop {r0, r1, r2, r3, r4, pc} + +10013a2a : +10013a2a: 4770 bx lr + +10013a2c : +10013a2c: b580 push {r7, lr} +10013a2e: f8df 027c ldr.w r0, [pc, #636] ; 10013cac +10013a32: f240 71ff movw r1, #2047 ; 0x7ff +10013a36: 6001 str r1, [r0, #0] +10013a38: f8df 1274 ldr.w r1, [pc, #628] ; 10013cb0 +10013a3c: 6181 str r1, [r0, #24] +10013a3e: f000 f89e bl 10013b7e +10013a42: f8df 0270 ldr.w r0, [pc, #624] ; 10013cb4 +10013a46: f7ff ff43 bl 100138d0 +10013a4a: f8df 126c ldr.w r1, [pc, #620] ; 10013cb8 +10013a4e: f8df 026c ldr.w r0, [pc, #620] ; 10013cbc +10013a52: 6008 str r0, [r1, #0] +10013a54: f7ff ff87 bl 10013966 +10013a58: f8df 2264 ldr.w r2, [pc, #612] ; 10013cc0 +10013a5c: f8df 1264 ldr.w r1, [pc, #612] ; 10013cc4 +10013a60: f8df 0264 ldr.w r0, [pc, #612] ; 10013cc8 +10013a64: f7f0 faf0 bl 10004048 +10013a68: f8df 123c ldr.w r1, [pc, #572] ; 10013ca8 +10013a6c: f501 702b add.w r0, r1, #684 ; 0x2ac +10013a70: 6c02 ldr r2, [r0, #64] ; 0x40 +10013a72: 6b43 ldr r3, [r0, #52] ; 0x34 +10013a74: f042 7280 orr.w r2, r2, #16777216 ; 0x1000000 +10013a78: 6402 str r2, [r0, #64] ; 0x40 +10013a7a: f843 2c04 str.w r2, [r3, #-4] +10013a7e: 6b43 ldr r3, [r0, #52] ; 0x34 +10013a80: 6bc2 ldr r2, [r0, #60] ; 0x3c +10013a82: f843 2c08 str.w r2, [r3, #-8] +10013a86: 6b43 ldr r3, [r0, #52] ; 0x34 +10013a88: 6b82 ldr r2, [r0, #56] ; 0x38 +10013a8a: f843 2c0c str.w r2, [r3, #-12] +10013a8e: 6b43 ldr r3, [r0, #52] ; 0x34 +10013a90: 6b02 ldr r2, [r0, #48] ; 0x30 +10013a92: f843 2c10 str.w r2, [r3, #-16] +10013a96: 6b43 ldr r3, [r0, #52] ; 0x34 +10013a98: 68c2 ldr r2, [r0, #12] +10013a9a: f843 2c14 str.w r2, [r3, #-20] +10013a9e: 6b43 ldr r3, [r0, #52] ; 0x34 +10013aa0: 6882 ldr r2, [r0, #8] +10013aa2: f843 2c18 str.w r2, [r3, #-24] +10013aa6: 6b43 ldr r3, [r0, #52] ; 0x34 +10013aa8: 6842 ldr r2, [r0, #4] +10013aaa: f843 2c1c str.w r2, [r3, #-28] +10013aae: 6b42 ldr r2, [r0, #52] ; 0x34 +10013ab0: f8d1 12ac ldr.w r1, [r1, #684] ; 0x2ac +10013ab4: f842 1c20 str.w r1, [r2, #-32] +10013ab8: 6b42 ldr r2, [r0, #52] ; 0x34 +10013aba: 6ac1 ldr r1, [r0, #44] ; 0x2c +10013abc: f842 1c24 str.w r1, [r2, #-36] +10013ac0: 6b42 ldr r2, [r0, #52] ; 0x34 +10013ac2: 6a81 ldr r1, [r0, #40] ; 0x28 +10013ac4: f842 1c28 str.w r1, [r2, #-40] +10013ac8: 6b42 ldr r2, [r0, #52] ; 0x34 +10013aca: 6a41 ldr r1, [r0, #36] ; 0x24 +10013acc: f842 1c2c str.w r1, [r2, #-44] +10013ad0: 6b42 ldr r2, [r0, #52] ; 0x34 +10013ad2: 6a01 ldr r1, [r0, #32] +10013ad4: f842 1c30 str.w r1, [r2, #-48] +10013ad8: 6b42 ldr r2, [r0, #52] ; 0x34 +10013ada: 69c1 ldr r1, [r0, #28] +10013adc: f842 1c34 str.w r1, [r2, #-52] +10013ae0: 6b42 ldr r2, [r0, #52] ; 0x34 +10013ae2: 6981 ldr r1, [r0, #24] +10013ae4: f842 1c38 str.w r1, [r2, #-56] +10013ae8: 6b42 ldr r2, [r0, #52] ; 0x34 +10013aea: 6941 ldr r1, [r0, #20] +10013aec: f842 1c3c str.w r1, [r2, #-60] +10013af0: 6b42 ldr r2, [r0, #52] ; 0x34 +10013af2: 6901 ldr r1, [r0, #16] +10013af4: f842 1c40 str.w r1, [r2, #-64] +10013af8: 6b41 ldr r1, [r0, #52] ; 0x34 +10013afa: 3940 subs r1, #64 ; 0x40 +10013afc: 6341 str r1, [r0, #52] ; 0x34 +10013afe: 6641 str r1, [r0, #100] ; 0x64 +10013b00: b662 cpsie i +10013b02: df00 svc 0 +10013b04: bf00 nop +10013b06: bd01 pop {r0, pc} + +10013b08 : +10013b08: b530 push {r4, r5, lr} +10013b0a: f242 03a4 movw r3, #8356 ; 0x20a4 +10013b0e: 4298 cmp r0, r3 +10013b10: bf28 it cs +10013b12: f242 00a3 movwcs r0, #8355 ; 0x20a3 +10013b16: 237d movs r3, #125 ; 0x7d +10013b18: 4358 muls r0, r3 +10013b1a: 680b ldr r3, [r1, #0] +10013b1c: 0900 lsrs r0, r0, #4 +10013b1e: 2418 movs r4, #24 + +10013b20 : +10013b20: 0a05 lsrs r5, r0, #8 +10013b22: 022d lsls r5, r5, #8 +10013b24: d003 beq.n 10013b2e +10013b26: 1c5b adds r3, r3, #1 +10013b28: 0840 lsrs r0, r0, #1 +10013b2a: 1e64 subs r4, r4, #1 +10013b2c: d1f8 bne.n 10013b20 + +10013b2e : +10013b2e: 021b lsls r3, r3, #8 +10013b30: 600b str r3, [r1, #0] +10013b32: 6010 str r0, [r2, #0] +10013b34: bd30 pop {r4, r5, pc} + +10013b36 : +10013b36: f44f 0100 mov.w r1, #8388608 ; 0x800000 +10013b3a: b108 cbz r0, 10013b40 +10013b3c: f44f 0101 mov.w r1, #8454144 ; 0x810000 + +10013b40 : +10013b40: f8df 2188 ldr.w r2, [pc, #392] ; 10013ccc +10013b44: 6011 str r1, [r2, #0] + +10013b46 : +10013b46: 6811 ldr r1, [r2, #0] +10013b48: 0209 lsls r1, r1, #8 +10013b4a: d4fc bmi.n 10013b46 +10013b4c: 6811 ldr r1, [r2, #0] +10013b4e: 0489 lsls r1, r1, #18 +10013b50: 0c89 lsrs r1, r1, #18 +10013b52: 1c49 adds r1, r1, #1 +10013b54: b920 cbnz r0, 10013b60 +10013b56: f640 0055 movw r0, #2133 ; 0x855 +10013b5a: fbb0 f0f1 udiv r0, r0, r1 +10013b5e: 1e41 subs r1, r0, #1 + +10013b60 : +10013b60: 4608 mov r0, r1 +10013b62: 4770 bx lr + +10013b64 : +10013b64: f8df 0168 ldr.w r0, [pc, #360] ; 10013cd0 +10013b68: f8df 2168 ldr.w r2, [pc, #360] ; 10013cd4 +10013b6c: 6801 ldr r1, [r0, #0] +10013b6e: 6812 ldr r2, [r2, #0] +10013b70: 0909 lsrs r1, r1, #4 +10013b72: f3c2 1202 ubfx r2, r2, #4, #3 +10013b76: ea42 1101 orr.w r1, r2, r1, lsl #4 +10013b7a: 6001 str r1, [r0, #0] +10013b7c: 4770 bx lr + +10013b7e : +10013b7e: f8df 0150 ldr.w r0, [pc, #336] ; 10013cd0 +10013b82: f8df 1150 ldr.w r1, [pc, #336] ; 10013cd4 +10013b86: 6800 ldr r0, [r0, #0] +10013b88: 680a ldr r2, [r1, #0] +10013b8a: f022 0270 bic.w r2, r2, #112 ; 0x70 +10013b8e: f000 000f and.w r0, r0, #15 +10013b92: ea42 1000 orr.w r0, r2, r0, lsl #4 +10013b96: 6008 str r0, [r1, #0] +10013b98: 4770 bx lr + +10013b9a : +10013b9a: 6828 ldr r0, [r5, #0] +10013b9c: f440 4000 orr.w r0, r0, #32768 ; 0x8000 +10013ba0: 6028 str r0, [r5, #0] +10013ba2: 4770 bx lr + +10013ba4 : +10013ba4: b57c push {r2, r3, r4, r5, r6, lr} +10013ba6: 4604 mov r4, r0 +10013ba8: 2000 movs r0, #0 +10013baa: f8df 50f8 ldr.w r5, [pc, #248] ; 10013ca4 +10013bae: 9001 str r0, [sp, #4] +10013bb0: 9000 str r0, [sp, #0] +10013bb2: 6028 str r0, [r5, #0] +10013bb4: f7ff ffbf bl 10013b36 +10013bb8: 4606 mov r6, r0 +10013bba: aa00 add r2, sp, #0 +10013bbc: a901 add r1, sp, #4 +10013bbe: 4620 mov r0, r4 +10013bc0: f7ff ffa2 bl 10013b08 +10013bc4: 9801 ldr r0, [sp, #4] +10013bc6: 9900 ldr r1, [sp, #0] +10013bc8: ea40 4006 orr.w r0, r0, r6, lsl #16 +10013bcc: 4308 orrs r0, r1 +10013bce: 6028 str r0, [r5, #0] +10013bd0: bd73 pop {r0, r1, r4, r5, r6, pc} + +10013bd2 : +10013bd2: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +10013bd6: f8df 50cc ldr.w r5, [pc, #204] ; 10013ca4 +10013bda: 6f2e ldr r6, [r5, #112] ; 0x70 +10013bdc: 4604 mov r4, r0 +10013bde: 4688 mov r8, r1 +10013be0: f7ff ffc0 bl 10013b64 +10013be4: f8df 90c0 ldr.w r9, [pc, #192] ; 10013ca8 +10013be8: f8df 70ec ldr.w r7, [pc, #236] ; 10013cd8 +10013bec: 2000 movs r0, #0 +10013bee: f8c9 0314 str.w r0, [r9, #788] ; 0x314 +10013bf2: 6fa8 ldr r0, [r5, #120] ; 0x78 +10013bf4: 67a8 str r0, [r5, #120] ; 0x78 +10013bf6: f8df 00e8 ldr.w r0, [pc, #232] ; 10013ce0 +10013bfa: 60b8 str r0, [r7, #8] +10013bfc: 68f8 ldr r0, [r7, #12] +10013bfe: 0a00 lsrs r0, r0, #8 +10013c00: 0200 lsls r0, r0, #8 +10013c02: f040 0002 orr.w r0, r0, #2 +10013c06: 60f8 str r0, [r7, #12] +10013c08: 07e0 lsls r0, r4, #31 +10013c0a: d506 bpl.n 10013c1a +10013c0c: 4640 mov r0, r8 +10013c0e: f7ff ffc9 bl 10013ba4 +10013c12: f7ff ffc2 bl 10013b9a + +10013c16 : +10013c16: f046 0601 orr.w r6, r6, #1 + +10013c1a : +10013c1a: 07a0 lsls r0, r4, #30 +10013c1c: bf48 it mi +10013c1e: f046 0602 orrmi.w r6, r6, #2 +10013c22: 0760 lsls r0, r4, #29 +10013c24: bf48 it mi +10013c26: f046 0610 orrmi.w r6, r6, #16 +10013c2a: 0720 lsls r0, r4, #28 +10013c2c: bf48 it mi +10013c2e: f446 7680 orrmi.w r6, r6, #256 ; 0x100 +10013c32: 06e0 lsls r0, r4, #27 +10013c34: bf48 it mi +10013c36: f046 5680 orrmi.w r6, r6, #268435456 ; 0x10000000 +10013c3a: 0620 lsls r0, r4, #24 +10013c3c: bf48 it mi +10013c3e: f046 5680 orrmi.w r6, r6, #268435456 ; 0x10000000 + +10013c42 : +10013c42: f000 f810 bl 10013c66 + +10013c46 : +10013c46: f8df 0094 ldr.w r0, [pc, #148] ; 10013cdc +10013c4a: 7800 ldrb r0, [r0, #0] +10013c4c: 0640 lsls r0, r0, #25 +10013c4e: d5f8 bpl.n 10013c42 +10013c50: 672e str r6, [r5, #112] ; 0x70 +10013c52: f8d9 0314 ldr.w r0, [r9, #788] ; 0x314 +10013c56: 2801 cmp r0, #1 +10013c58: d003 beq.n 10013c62 +10013c5a: 2004 movs r0, #4 +10013c5c: 6038 str r0, [r7, #0] +10013c5e: 6838 ldr r0, [r7, #0] +10013c60: bf30 wfi + +10013c62 : +10013c62: e8bd 83f1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, pc} + +10013c66 : +10013c66: 2064 movs r0, #100 ; 0x64 +10013c68: f7f2 bfda b.w 10006c20 + +10013c6c : +10013c6c: 9002 str r0, [sp, #8] +10013c6e: 2000 movs r0, #0 +10013c70: 9001 str r0, [sp, #4] +10013c72: 481c ldr r0, [pc, #112] ; (10013ce4 ) +10013c74: 9000 str r0, [sp, #0] +10013c76: 2000 movs r0, #0 +10013c78: 9003 str r0, [sp, #12] +10013c7a: a800 add r0, sp, #0 +10013c7c: f7f2 bfd8 b.w 10006c30 + +10013c80 : +10013c80: 3000 4000 .0.@ + +10013c84 : +10013c84: 280c 4000 .(.@ + +10013c88 : +10013c88: ed0c e000 .... + +10013c8c : +10013c8c: 0300 05fa .... + +10013c90 : +10013c90: e413 e000 .... + +10013c94 : +10013c94: e100 e000 .... + +10013c98 : +10013c98: 0210 4000 ...@ + +10013c9c : +10013c9c: 4879 1000 yH.. + +10013ca0 : +10013ca0: 0008 4000 ...@ + +10013ca4 : +10013ca4: 0090 4000 ...@ + +10013ca8 : +10013ca8: 73dc 1004 .s.. + +10013cac : +10013cac: 0320 4000 ..@ + +10013cb0 : +10013cb0: 5556 0555 VUU. + +10013cb4 : +10013cb4: fffc 1fff .... + +10013cb8 : +10013cb8: ed20 e000 ... + +10013cbc : +10013cbc: 0000 f0f0 .... + +10013cc0 : +10013cc0: b25b 1000 [... + +10013cc4 : +10013cc4: 3bad 1004 .;.. + +10013cc8 : +10013cc8: 3a2b 1001 +:.. + +10013ccc : +10013ccc: 28a0 4000 .(.@ + +10013cd0 : +10013cd0: 00f0 4000 ...@ + +10013cd4 : +10013cd4: 0014 4000 ...@ + +10013cd8 : +10013cd8: 0118 4000 ...@ + +10013cdc : +10013cdc: 3014 4000 .0.@ + +10013ce0 : +10013ce0: 0900 7400 ...t + +10013ce4 : +10013ce4: 39df 1001 .9.. + +10013ce8 : +10013ce8: b580 push {r7, lr} +10013cea: 4940 ldr r1, [pc, #256] ; (10013dec <.text_11>) +10013cec: 4840 ldr r0, [pc, #256] ; (10013df0 <.text_12>) +10013cee: 6001 str r1, [r0, #0] +10013cf0: 2200 movs r2, #0 +10013cf2: 600a str r2, [r1, #0] +10013cf4: f44f 4220 mov.w r2, #40960 ; 0xa000 +10013cf8: 604a str r2, [r1, #4] +10013cfa: 2101 movs r1, #1 +10013cfc: 6041 str r1, [r0, #4] +10013cfe: 3008 adds r0, #8 +10013d00: f7fc fe29 bl 10010956 +10013d04: e8bd 4008 ldmia.w sp!, {r3, lr} +10013d08: 4a3a ldr r2, [pc, #232] ; (10013df4 <.text_13>) +10013d0a: f20f 1019 addw r0, pc, #281 ; 0x119 +10013d0e: f04f 5100 mov.w r1, #536870912 ; 0x20000000 +10013d12: f7f8 be51 b.w 1000c9b8 + +10013d16 : +10013d16: b538 push {r3, r4, r5, lr} +10013d18: 4605 mov r5, r0 +10013d1a: f000 f85b bl 10013dd4 <.text_8> +10013d1e: 6860 ldr r0, [r4, #4] +10013d20: b908 cbnz r0, 10013d26 +10013d22: f7ff ffe1 bl 10013ce8 +10013d26: 1de8 adds r0, r5, #7 +10013d28: 08c0 lsrs r0, r0, #3 +10013d2a: 00c0 lsls r0, r0, #3 +10013d2c: 6825 ldr r5, [r4, #0] +10013d2e: bf08 it eq +10013d30: 2008 moveq r0, #8 +10013d32: 4621 mov r1, r4 +10013d34: e001 b.n 10013d3a +10013d36: 4629 mov r1, r5 +10013d38: 682d ldr r5, [r5, #0] +10013d3a: b185 cbz r5, 10013d5e +10013d3c: 686a ldr r2, [r5, #4] +10013d3e: 4282 cmp r2, r0 +10013d40: dbf9 blt.n 10013d36 +10013d42: d105 bne.n 10013d50 +10013d44: 6828 ldr r0, [r5, #0] +10013d46: 6008 str r0, [r1, #0] +10013d48: f000 f84a bl 10013de0 <.text_9> +10013d4c: 4628 mov r0, r5 +10013d4e: bd32 pop {r1, r4, r5, pc} +10013d50: 1a10 subs r0, r2, r0 +10013d52: 6068 str r0, [r5, #4] +10013d54: f000 f844 bl 10013de0 <.text_9> +10013d58: 6868 ldr r0, [r5, #4] +10013d5a: 1940 adds r0, r0, r5 +10013d5c: bd32 pop {r1, r4, r5, pc} +10013d5e: f000 f83f bl 10013de0 <.text_9> +10013d62: 2000 movs r0, #0 +10013d64: bd32 pop {r1, r4, r5, pc} + +10013d66 : +10013d66: b570 push {r4, r5, r6, lr} +10013d68: b082 sub sp, #8 +10013d6a: 4605 mov r5, r0 +10013d6c: 460e mov r6, r1 +10013d6e: f000 f831 bl 10013dd4 <.text_8> +10013d72: 6860 ldr r0, [r4, #4] +10013d74: b908 cbnz r0, 10013d7a +10013d76: f7ff ffb7 bl 10013ce8 +10013d7a: 1df0 adds r0, r6, #7 +10013d7c: 08c1 lsrs r1, r0, #3 +10013d7e: 00c9 lsls r1, r1, #3 +10013d80: 6822 ldr r2, [r4, #0] +10013d82: bf08 it eq +10013d84: 2108 moveq r1, #8 +10013d86: 4295 cmp r5, r2 +10013d88: d300 bcc.n 10013d8c +10013d8a: b922 cbnz r2, 10013d96 +10013d8c: 4628 mov r0, r5 +10013d8e: 6002 str r2, [r0, #0] +10013d90: 6041 str r1, [r0, #4] +10013d92: 6020 str r0, [r4, #0] +10013d94: e011 b.n 10013dba +10013d96: 4610 mov r0, r2 +10013d98: 6802 ldr r2, [r0, #0] +10013d9a: 42aa cmp r2, r5 +10013d9c: d201 bcs.n 10013da2 +10013d9e: 2a00 cmp r2, #0 +10013da0: d1f9 bne.n 10013d96 +10013da2: 6842 ldr r2, [r0, #4] +10013da4: 1813 adds r3, r2, r0 +10013da6: 42ab cmp r3, r5 +10013da8: d102 bne.n 10013db0 +10013daa: 1889 adds r1, r1, r2 +10013dac: 6041 str r1, [r0, #4] +10013dae: e004 b.n 10013dba +10013db0: 6802 ldr r2, [r0, #0] +10013db2: 602a str r2, [r5, #0] +10013db4: 6069 str r1, [r5, #4] +10013db6: 6005 str r5, [r0, #0] +10013db8: 4628 mov r0, r5 +10013dba: 6841 ldr r1, [r0, #4] +10013dbc: 6802 ldr r2, [r0, #0] +10013dbe: 180b adds r3, r1, r0 +10013dc0: 4293 cmp r3, r2 +10013dc2: d104 bne.n 10013dce +10013dc4: 6853 ldr r3, [r2, #4] +10013dc6: 1859 adds r1, r3, r1 +10013dc8: 6041 str r1, [r0, #4] +10013dca: 6811 ldr r1, [r2, #0] +10013dcc: 6001 str r1, [r0, #0] +10013dce: f000 f807 bl 10013de0 <.text_9> +10013dd2: bd73 pop {r0, r1, r4, r5, r6, pc} + +10013dd4 <.text_8>: +10013dd4: 4c06 ldr r4, [pc, #24] ; (10013df0 <.text_12>) +10013dd6: a900 add r1, sp, #0 +10013dd8: f104 0008 add.w r0, r4, #8 +10013ddc: f7fc bd8c b.w 100108f8 + +10013de0 <.text_9>: +10013de0: a900 add r1, sp, #0 +10013de2: f104 0008 add.w r0, r4, #8 +10013de6: f7fc bd8e b.w 10010906 + ... + +10013dec <.text_11>: +10013dec: 1fff5210 .word 0x1fff5210 + +10013df0 <.text_12>: +10013df0: 10048850 .word 0x10048850 + +10013df4 <.text_13>: +10013df4: 1fff0000 .word 0x1fff0000 + +10013df8 : +10013df8: b510 push {r4, lr} +10013dfa: 1d04 adds r4, r0, #4 +10013dfc: 4620 mov r0, r4 +10013dfe: f7ff ff8a bl 10013d16 +10013e02: b108 cbz r0, 10013e08 +10013e04: f840 4b04 str.w r4, [r0], #4 +10013e08: bd10 pop {r4, pc} + +10013e0a : +10013e0a: b538 push {r3, r4, r5, lr} +10013e0c: 4604 mov r4, r0 +10013e0e: f7ff fff3 bl 10013df8 +10013e12: 0005 movs r5, r0 +10013e14: d003 beq.n 10013e1e +10013e16: 4622 mov r2, r4 +10013e18: 2100 movs r1, #0 +10013e1a: f7f8 fa97 bl 1000c34c +10013e1e: 4628 mov r0, r5 +10013e20: bd32 pop {r1, r4, r5, pc} + ... + +10013e24 : +10013e24: 2800 cmp r0, #0 +10013e26: bf1c itt ne +10013e28: f850 1d04 ldrne.w r1, [r0, #-4]! +10013e2c: f7ff bf9b bne.w 10013d66 +10013e30: 4770 bx lr + ... + +10013e34 : +10013e34: b510 push {r4, lr} +10013e36: 4604 mov r4, r0 +10013e38: f7f7 f9fa bl 1000b230 +10013e3c: 4620 mov r0, r4 +10013e3e: f7f8 fd39 bl 1000c8b4 +10013e42: 4604 mov r4, r0 +10013e44: f7f7 fa00 bl 1000b248 +10013e48: 4620 mov r0, r4 +10013e4a: bd10 pop {r4, pc} + +10013e4c : +10013e4c: f7f8 bdb9 b.w 1000c9c2 + +10013e50 : +10013e50: b580 push {r7, lr} +10013e52: 2100 movs r1, #0 +10013e54: 9100 str r1, [sp, #0] +10013e56: 2300 movs r3, #0 +10013e58: 6800 ldr r0, [r0, #0] +10013e5a: aa00 add r2, sp, #0 +10013e5c: f7f6 fbf0 bl 1000a640 +10013e60: 9800 ldr r0, [sp, #0] +10013e62: b108 cbz r0, 10013e68 +10013e64: f7f7 f9db bl 1000b21e + +10013e68 : +10013e68: bd01 pop {r0, pc} + +10013e6a : +10013e6a: f7f2 bed9 b.w 10006c20 + ... + +10013e70 : +10013e70: f8df f000 ldr.w pc, [pc] ; 10013e74 +10013e74: 000138ad .word 0x000138ad + +10013e78 : +10013e78: f8df f000 ldr.w pc, [pc] ; 10013e7c +10013e7c: 000137d1 .word 0x000137d1 + +10013e80 : +10013e80: f8df f000 ldr.w pc, [pc] ; 10013e84 +10013e84: 0001355d .word 0x0001355d + +10013e88 : +10013e88: f8df f000 ldr.w pc, [pc] ; 10013e8c +10013e8c: 00013db9 .word 0x00013db9 + +10013e90 : +10013e90: 6840 ldr r0, [r0, #4] +10013e92: 4208 tst r0, r1 +10013e94: d001 beq.n 10013e9a +10013e96: 2001 movs r0, #1 +10013e98: 4770 bx lr +10013e9a: 2000 movs r0, #0 +10013e9c: 4770 bx lr + +10013e9e : +10013e9e: 4608 mov r0, r1 +10013ea0: 4611 mov r1, r2 +10013ea2: 461a mov r2, r3 +10013ea4: f00e bc90 b.w 100227c8 + +10013ea8 : +10013ea8: b5f0 push {r4, r5, r6, r7, lr} +10013eaa: 4604 mov r4, r0 +10013eac: 460d mov r5, r1 +10013eae: b085 sub sp, #20 +10013eb0: f240 1601 movw r6, #257 ; 0x101 +10013eb4: f001 fc44 bl 10015740 <.text_98> +10013eb8: 42b0 cmp r0, r6 +10013eba: d21f bcs.n 10013efc +10013ebc: 4630 mov r0, r6 +10013ebe: f7fc fca0 bl 10010802 +10013ec2: 0007 movs r7, r0 +10013ec4: d01a beq.n 10013efc +10013ec6: f001 fc3b bl 10015740 <.text_98> +10013eca: 4602 mov r2, r0 +10013ecc: 4629 mov r1, r5 +10013ece: 4638 mov r0, r7 +10013ed0: f7fc fc9d bl 1001080e +10013ed4: 2210 movs r2, #16 +10013ed6: 2100 movs r1, #0 +10013ed8: a800 add r0, sp, #0 +10013eda: f7fc fcad bl 10010838 +10013ede: f001 fc2f bl 10015740 <.text_98> +10013ee2: f8ad 0004 strh.w r0, [sp, #4] +10013ee6: 463b mov r3, r7 +10013ee8: f641 5024 movw r0, #7460 ; 0x1d24 +10013eec: aa00 add r2, sp, #0 +10013eee: 5900 ldr r0, [r0, r4] +10013ef0: f648 4102 movw r1, #35842 ; 0x8c02 +10013ef4: f7ff ffd3 bl 10013e9e +10013ef8: f000 f802 bl 10013f00 <.text_6> +10013efc: b005 add sp, #20 +10013efe: bdf0 pop {r4, r5, r6, r7, pc} + +10013f00 <.text_6>: +10013f00: 4631 mov r1, r6 +10013f02: 4638 mov r0, r7 +10013f04: f7fc bc82 b.w 1001080c + +10013f08 : +10013f08: b51f push {r0, r1, r2, r3, r4, lr} +10013f0a: f000 f82b bl 10013f64 <.text_11> +10013f0e: 6c20 ldr r0, [r4, #64] ; 0x40 +10013f10: 9000 str r0, [sp, #0] +10013f12: 2300 movs r3, #0 +10013f14: f000 f811 bl 10013f3a <.text_9> +10013f18: e03d b.n 10013f96 <.text_14> + +10013f1a : +10013f1a: b51f push {r0, r1, r2, r3, r4, lr} +10013f1c: f000 f822 bl 10013f64 <.text_11> +10013f20: 2000 movs r0, #0 +10013f22: 6420 str r0, [r4, #64] ; 0x40 +10013f24: 2100 movs r1, #0 +10013f26: f104 0040 add.w r0, r4, #64 ; 0x40 +10013f2a: 2300 movs r3, #0 +10013f2c: 6041 str r1, [r0, #4] +10013f2e: f8ad 1006 strh.w r1, [sp, #6] +10013f32: 8141 strh r1, [r0, #10] +10013f34: f000 f801 bl 10013f3a <.text_9> +10013f38: e02d b.n 10013f96 <.text_14> + +10013f3a <.text_9>: +10013f3a: f641 5024 movw r0, #7460 ; 0x1d24 +10013f3e: aa00 add r2, sp, #0 +10013f40: 5900 ldr r0, [r0, r4] +10013f42: f648 3119 movw r1, #35609 ; 0x8b19 +10013f46: 4770 bx lr + +10013f48 : +10013f48: b51f push {r0, r1, r2, r3, r4, lr} +10013f4a: f000 f80b bl 10013f64 <.text_11> +10013f4e: 2001 movs r0, #1 +10013f50: f88d 0001 strb.w r0, [sp, #1] +10013f54: 2206 movs r2, #6 +10013f56: f104 019c add.w r1, r4, #156 ; 0x9c +10013f5a: f10d 0002 add.w r0, sp, #2 +10013f5e: f7fc fc56 bl 1001080e +10013f62: e011 b.n 10013f88 <.text_13> + +10013f64 <.text_11>: +10013f64: 4604 mov r4, r0 +10013f66: 2210 movs r2, #16 +10013f68: 2100 movs r1, #0 +10013f6a: a800 add r0, sp, #0 +10013f6c: f7fc bc64 b.w 10010838 + +10013f70 : +10013f70: b51f push {r0, r1, r2, r3, r4, lr} +10013f72: f7ff fff7 bl 10013f64 <.text_11> +10013f76: 2001 movs r0, #1 +10013f78: f88d 0001 strb.w r0, [sp, #1] +10013f7c: 2206 movs r2, #6 +10013f7e: 2100 movs r1, #0 +10013f80: f10d 0002 add.w r0, sp, #2 +10013f84: f7fc fc58 bl 10010838 + +10013f88 <.text_13>: +10013f88: f641 5024 movw r0, #7460 ; 0x1d24 +10013f8c: 2300 movs r3, #0 +10013f8e: 5900 ldr r0, [r0, r4] +10013f90: aa00 add r2, sp, #0 +10013f92: f648 3115 movw r1, #35605 ; 0x8b15 + +10013f96 <.text_14>: +10013f96: f7ff ff82 bl 10013e9e +10013f9a: bd1f pop {r0, r1, r2, r3, r4, pc} + +10013f9c : +10013f9c: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +10013fa0: b083 sub sp, #12 +10013fa2: 6900 ldr r0, [r0, #16] +10013fa4: 6807 ldr r7, [r0, #0] +10013fa6: 468b mov fp, r1 +10013fa8: f10b 0404 add.w r4, fp, #4 +10013fac: f04f 0900 mov.w r9, #0 +10013fb0: f8c4 901c str.w r9, [r4, #28] +10013fb4: f10b 0524 add.w r5, fp, #36 ; 0x24 +10013fb8: f507 5088 add.w r0, r7, #4352 ; 0x1100 +10013fbc: f884 9017 strb.w r9, [r4, #23] +10013fc0: f100 08f0 add.w r8, r0, #240 ; 0xf0 +10013fc4: 8969 ldrh r1, [r5, #10] +10013fc6: 2030 movs r0, #48 ; 0x30 +10013fc8: 1808 adds r0, r1, r0 +10013fca: 4282 cmp r2, r0 +10013fcc: f06f 0615 mvn.w r6, #21 +10013fd0: d201 bcs.n 10013fd6 +10013fd2: 46b1 mov r9, r6 +10013fd4: e064 b.n 100140a0 +10013fd6: f89b 0004 ldrb.w r0, [fp, #4] +10013fda: 28ff cmp r0, #255 ; 0xff +10013fdc: bf04 itt eq +10013fde: 7860 ldrbeq r0, [r4, #1] +10013fe0: 28ff cmpeq r0, #255 ; 0xff +10013fe2: d1f6 bne.n 10013fd2 +10013fe4: 78a0 ldrb r0, [r4, #2] +10013fe6: 28ff cmp r0, #255 ; 0xff +10013fe8: bf04 itt eq +10013fea: 78e0 ldrbeq r0, [r4, #3] +10013fec: 28ff cmpeq r0, #255 ; 0xff +10013fee: d1f0 bne.n 10013fd2 +10013ff0: 7920 ldrb r0, [r4, #4] +10013ff2: 28ff cmp r0, #255 ; 0xff +10013ff4: bf04 itt eq +10013ff6: 7960 ldrbeq r0, [r4, #5] +10013ff8: 28ff cmpeq r0, #255 ; 0xff +10013ffa: d1ea bne.n 10013fd2 +10013ffc: f89b 0024 ldrb.w r0, [fp, #36] ; 0x24 +10014000: 2804 cmp r0, #4 +10014002: dae6 bge.n 10013fd2 +10014004: f507 5088 add.w r0, r7, #4352 ; 0x1100 +10014008: f100 0af4 add.w sl, r0, #244 ; 0xf4 +1001400c: a146 add r1, pc, #280 ; (adr r1, 10014128 <.text_16>) +1001400e: f10b 000c add.w r0, fp, #12 +10014012: f7f8 f99d bl 1000c350 +10014016: 2800 cmp r0, #0 +10014018: d165 bne.n 100140e6 +1001401a: f241 5158 movw r1, #5464 ; 0x1558 +1001401e: 51c8 str r0, [r1, r7] +10014020: f241 11f4 movw r1, #4596 ; 0x11f4 +10014024: 2001 movs r0, #1 +10014026: 51c8 str r0, [r1, r7] +10014028: f8ca 0058 str.w r0, [sl, #88] ; 0x58 +1001402c: f89b 0024 ldrb.w r0, [fp, #36] ; 0x24 +10014030: 9000 str r0, [sp, #0] +10014032: 2805 cmp r0, #5 +10014034: 8969 ldrh r1, [r5, #10] +10014036: bf28 it cs +10014038: 4630 movcs r0, r6 +1001403a: d232 bcs.n 100140a2 +1001403c: 2900 cmp r1, #0 +1001403e: d0c8 beq.n 10013fd2 +10014040: 2906 cmp r1, #6 +10014042: bf34 ite cc +10014044: 2505 movcc r5, #5 +10014046: 250d movcs r5, #13 +10014048: f105 000c add.w r0, r5, #12 +1001404c: 9001 str r0, [sp, #4] +1001404e: f7fc fbd3 bl 100107f8 +10014052: 0006 movs r6, r0 +10014054: d024 beq.n 100140a0 +10014056: 9a01 ldr r2, [sp, #4] +10014058: f000 fc94 bl 10014984 <.text_43> +1001405c: 60b5 str r5, [r6, #8] +1001405e: 2d0d cmp r5, #13 +10014060: 9801 ldr r0, [sp, #4] +10014062: 6030 str r0, [r6, #0] +10014064: d105 bne.n 10014072 +10014066: f241 11f4 movw r1, #4596 ; 0x11f4 +1001406a: 2005 movs r0, #5 +1001406c: 51c8 str r0, [r1, r7] +1001406e: f8ca 0058 str.w r0, [sl, #88] ; 0x58 +10014072: f10b 0130 add.w r1, fp, #48 ; 0x30 +10014076: 9800 ldr r0, [sp, #0] +10014078: f040 4000 orr.w r0, r0, #2147483648 ; 0x80000000 +1001407c: 6070 str r0, [r6, #4] +1001407e: f106 000c add.w r0, r6, #12 +10014082: 68b2 ldr r2, [r6, #8] +10014084: f7fc fbc3 bl 1001080e +10014088: f20f 02a0 addw r2, pc, #160 ; 0xa0 +1001408c: f06f 055e mvn.w r5, #94 ; 0x5e +10014090: f000 faf8 bl 10014684 <.text_34> +10014094: b938 cbnz r0, 100140a6 +10014096: 46a9 mov r9, r5 +10014098: 9901 ldr r1, [sp, #4] +1001409a: 4630 mov r0, r6 +1001409c: f7fc fbb6 bl 1001080c +100140a0: 4648 mov r0, r9 +100140a2: e8bd 8ffe ldmia.w sp!, {r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, pc} +100140a6: 7e20 ldrb r0, [r4, #24] +100140a8: b130 cbz r0, 100140b8 +100140aa: 4631 mov r1, r6 +100140ac: 4638 mov r0, r7 +100140ae: f00e fff9 bl 100230a4 +100140b2: 2800 cmp r0, #0 +100140b4: d1f0 bne.n 10014098 +100140b6: e7ee b.n 10014096 +100140b8: 9800 ldr r0, [sp, #0] +100140ba: 2804 cmp r0, #4 +100140bc: d2eb bcs.n 10014096 +100140be: 68b2 ldr r2, [r6, #8] +100140c0: eb08 1000 add.w r0, r8, r0, lsl #4 +100140c4: f106 010c add.w r1, r6, #12 +100140c8: 300c adds r0, #12 +100140ca: f7fc fba0 bl 1001080e +100140ce: 9900 ldr r1, [sp, #0] +100140d0: 68b0 ldr r0, [r6, #8] +100140d2: eb08 0181 add.w r1, r8, r1, lsl #2 +100140d6: 2300 movs r3, #0 +100140d8: 64c8 str r0, [r1, #76] ; 0x4c +100140da: 4641 mov r1, r8 +100140dc: 9a00 ldr r2, [sp, #0] +100140de: 4638 mov r0, r7 +100140e0: f00b f9cd bl 1001f47e +100140e4: e7d8 b.n 10014098 +100140e6: f60f 018c addw r1, pc, #2188 ; 0x88c +100140ea: f10b 000c add.w r0, fp, #12 +100140ee: f7f8 f92f bl 1000c350 +100140f2: b938 cbnz r0, 10014104 +100140f4: 2004 movs r0, #4 +100140f6: f8c8 0364 str.w r0, [r8, #868] ; 0x364 +100140fa: 2002 movs r0, #2 +100140fc: f8c8 0004 str.w r0, [r8, #4] +10014100: f8ca 0058 str.w r0, [sl, #88] ; 0x58 +10014104: f10b 000c add.w r0, fp, #12 +10014108: f60f 0170 addw r1, pc, #2160 ; 0x870 +1001410c: f7f8 f920 bl 1000c350 +10014110: 2800 cmp r0, #0 +10014112: d1c5 bne.n 100140a0 +10014114: 2007 movs r0, #7 +10014116: f8c8 0364 str.w r0, [r8, #868] ; 0x364 +1001411a: 2004 movs r0, #4 +1001411c: f8c8 0004 str.w r0, [r8, #4] +10014120: f8ca 0058 str.w r0, [sl, #88] ; 0x58 +10014124: e7bc b.n 100140a0 + ... + +10014128 <.text_16>: +10014128: 00504557 .word 0x00504557 + +1001412c : +1001412c: 5f617077 5f746573 72636e65 69747079 wpa_set_encrypti +1001413c: 00006e6f on.. + +10014140 : +10014140: e92d 46fe stmdb sp!, {r1, r2, r3, r4, r5, r6, r7, r9, sl, lr} +10014144: 4604 mov r4, r0 +10014146: 4692 mov sl, r2 +10014148: 2000 movs r0, #0 +1001414a: f5ba 7f80 cmp.w sl, #256 ; 0x100 +1001414e: 460d mov r5, r1 +10014150: 9002 str r0, [sp, #8] +10014152: 9001 str r0, [sp, #4] +10014154: dc03 bgt.n 1001415e +10014156: b115 cbz r5, 1001415e +10014158: f1ba 0f04 cmp.w sl, #4 +1001415c: da0a bge.n 10014174 +1001415e: f104 000c add.w r0, r4, #12 +10014162: 2d00 cmp r5, #0 +10014164: 6841 ldr r1, [r0, #4] +10014166: f421 7180 bic.w r1, r1, #256 ; 0x100 +1001416a: 6041 str r1, [r0, #4] +1001416c: d067 beq.n 1001423e +1001416e: f06f 0015 mvn.w r0, #21 +10014172: e065 b.n 10014240 +10014174: f504 51a8 add.w r1, r4, #5376 ; 0x1500 +10014178: 9000 str r0, [sp, #0] +1001417a: f101 0978 add.w r9, r1, #120 ; 0x78 +1001417e: f241 5654 movw r6, #5460 ; 0x1554 +10014182: f241 17f0 movw r7, #4592 ; 0x11f0 +10014186: ab01 add r3, sp, #4 +10014188: aa02 add r2, sp, #8 +1001418a: 4651 mov r1, sl +1001418c: 4628 mov r0, r5 +1001418e: f7ff fe73 bl 10013e78 +10014192: 2801 cmp r0, #1 +10014194: d105 bne.n 100141a2 +10014196: 2002 movs r0, #2 +10014198: 5138 str r0, [r7, r4] +1001419a: 4652 mov r2, sl +1001419c: 2004 movs r0, #4 +1001419e: f000 f851 bl 10014244 <.text_19> +100141a2: 2000 movs r0, #0 +100141a4: 9000 str r0, [sp, #0] +100141a6: ab01 add r3, sp, #4 +100141a8: aa02 add r2, sp, #8 +100141aa: 4651 mov r1, sl +100141ac: 4628 mov r0, r5 +100141ae: f7ff fe5f bl 10013e70 +100141b2: 2801 cmp r0, #1 +100141b4: d105 bne.n 100141c2 +100141b6: 2002 movs r0, #2 +100141b8: 5138 str r0, [r7, r4] +100141ba: 4652 mov r2, sl +100141bc: 2007 movs r0, #7 +100141be: f000 f841 bl 10014244 <.text_19> +100141c2: 9a02 ldr r2, [sp, #8] +100141c4: 1930 adds r0, r6, r4 +100141c6: 1939 adds r1, r7, r4 +100141c8: 2a01 cmp r2, #1 +100141ca: d008 beq.n 100141de +100141cc: 2a02 cmp r2, #2 +100141ce: d00a beq.n 100141e6 +100141d0: 2a04 cmp r2, #4 +100141d2: d012 beq.n 100141fa +100141d4: 2a08 cmp r2, #8 +100141d6: d008 beq.n 100141ea +100141d8: 2a10 cmp r2, #16 +100141da: d00a beq.n 100141f2 +100141dc: e011 b.n 10014202 +100141de: 2200 movs r2, #0 +100141e0: 65ca str r2, [r1, #92] ; 0x5c +100141e2: 2201 movs r2, #1 +100141e4: e00c b.n 10014200 +100141e6: 2201 movs r2, #1 +100141e8: e008 b.n 100141fc +100141ea: 2202 movs r2, #2 +100141ec: 65ca str r2, [r1, #92] ; 0x5c +100141ee: 2204 movs r2, #4 +100141f0: e006 b.n 10014200 +100141f2: 2204 movs r2, #4 +100141f4: 65ca str r2, [r1, #92] ; 0x5c +100141f6: 2206 movs r2, #6 +100141f8: e002 b.n 10014200 +100141fa: 2205 movs r2, #5 +100141fc: 65ca str r2, [r1, #92] ; 0x5c +100141fe: 2200 movs r2, #0 +10014200: 6042 str r2, [r0, #4] +10014202: 9a01 ldr r2, [sp, #4] +10014204: 2a01 cmp r2, #1 +10014206: d008 beq.n 1001421a +10014208: 2a02 cmp r2, #2 +1001420a: d00a beq.n 10014222 +1001420c: 2a04 cmp r2, #4 +1001420e: d012 beq.n 10014236 +10014210: 2a08 cmp r2, #8 +10014212: d008 beq.n 10014226 +10014214: 2a10 cmp r2, #16 +10014216: d00a beq.n 1001422e +10014218: e011 b.n 1001423e +1001421a: 2200 movs r2, #0 +1001421c: 604a str r2, [r1, #4] +1001421e: 2101 movs r1, #1 +10014220: e00c b.n 1001423c +10014222: 2201 movs r2, #1 +10014224: e008 b.n 10014238 +10014226: 2202 movs r2, #2 +10014228: 604a str r2, [r1, #4] +1001422a: 2104 movs r1, #4 +1001422c: e006 b.n 1001423c +1001422e: 2204 movs r2, #4 +10014230: 604a str r2, [r1, #4] +10014232: 2106 movs r1, #6 +10014234: e002 b.n 1001423c +10014236: 2205 movs r2, #5 +10014238: 604a str r2, [r1, #4] +1001423a: 2100 movs r1, #0 +1001423c: 6041 str r1, [r0, #4] +1001423e: 2000 movs r0, #0 +10014240: e8bd 86fe ldmia.w sp!, {r1, r2, r3, r4, r5, r6, r7, r9, sl, pc} + +10014244 <.text_19>: +10014244: 5130 str r0, [r6, r4] +10014246: 4629 mov r1, r5 +10014248: 4648 mov r0, r9 +1001424a: f7fc bae0 b.w 1001080e + +1001424e : +1001424e: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +10014252: 4614 mov r4, r2 +10014254: b082 sub sp, #8 +10014256: 6821 ldr r1, [r4, #0] +10014258: 6900 ldr r0, [r0, #16] +1001425a: 780e ldrb r6, [r1, #0] +1001425c: 6800 ldr r0, [r0, #0] +1001425e: 2700 movs r7, #0 +10014260: 2e01 cmp r6, #1 +10014262: f500 659d add.w r5, r0, #1256 ; 0x4e8 +10014266: 46b8 mov r8, r7 +10014268: d11f bne.n 100142aa +1001426a: f105 0214 add.w r2, r5, #20 +1001426e: 2141 movs r1, #65 ; 0x41 +10014270: f005 fc48 bl 10019b04 +10014274: 74a8 strb r0, [r5, #18] +10014276: 6820 ldr r0, [r4, #0] +10014278: 7840 ldrb r0, [r0, #1] +1001427a: 7528 strb r0, [r5, #20] +1001427c: e015 b.n 100142aa +1001427e: 6820 ldr r0, [r4, #0] +10014280: 4440 add r0, r8 +10014282: aa00 add r2, sp, #0 +10014284: 7841 ldrb r1, [r0, #1] +10014286: f105 0014 add.w r0, r5, #20 +1001428a: f005 fbad bl 100199e8 +1001428e: 2801 cmp r0, #1 +10014290: d109 bne.n 100142a6 +10014292: 6820 ldr r0, [r4, #0] +10014294: 9900 ldr r1, [sp, #0] +10014296: 1830 adds r0, r6, r0 +10014298: 4440 add r0, r8 +1001429a: 220c movs r2, #12 +1001429c: 7840 ldrb r0, [r0, #1] +1001429e: fb02 5101 mla r1, r2, r1, r5 +100142a2: 2701 movs r7, #1 +100142a4: 7708 strb r0, [r1, #28] +100142a6: f108 0801 add.w r8, r8, #1 +100142aa: 45b0 cmp r8, r6 +100142ac: dbe7 blt.n 1001427e +100142ae: 2f00 cmp r7, #0 +100142b0: bf1d ittte ne +100142b2: 2001 movne r0, #1 +100142b4: f885 03e5 strbne.w r0, [r5, #997] ; 0x3e5 +100142b8: 2000 movne r0, #0 +100142ba: f06f 0015 mvneq.w r0, #21 +100142be: e8bd 81f6 ldmia.w sp!, {r1, r2, r4, r5, r6, r7, r8, pc} + +100142c2 : +100142c2: 6900 ldr r0, [r0, #16] +100142c4: 6811 ldr r1, [r2, #0] +100142c6: 6800 ldr r0, [r0, #0] +100142c8: 7809 ldrb r1, [r1, #0] +100142ca: f500 609d add.w r0, r0, #1256 ; 0x4e8 +100142ce: b101 cbz r1, 100142d2 +100142d0: 2101 movs r1, #1 +100142d2: f880 13e4 strb.w r1, [r0, #996] ; 0x3e4 +100142d6: 2000 movs r0, #0 +100142d8: 4770 bx lr + +100142da : +100142da: 6900 ldr r0, [r0, #16] +100142dc: 6800 ldr r0, [r0, #0] +100142de: f990 08cc ldrsb.w r0, [r0, #2252] ; 0x8cc +100142e2: 7018 strb r0, [r3, #0] +100142e4: 2000 movs r0, #0 +100142e6: 4770 bx lr + +100142e8 : +100142e8: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +100142ec: 6900 ldr r0, [r0, #16] +100142ee: f8d0 8000 ldr.w r8, [r0] +100142f2: f508 699d add.w r9, r8, #1256 ; 0x4e8 +100142f6: f8d9 03e8 ldr.w r0, [r9, #1000] ; 0x3e8 +100142fa: 2800 cmp r0, #0 +100142fc: bf03 ittte eq +100142fe: f509 767a addeq.w r6, r9, #1000 ; 0x3e8 +10014302: 7930 ldrbeq r0, [r6, #4] +10014304: 2800 cmpeq r0, #0 +10014306: f04f 30ff movne.w r0, #4294967295 +1001430a: d13f bne.n 1001438c +1001430c: 6810 ldr r0, [r2, #0] +1001430e: 6807 ldr r7, [r0, #0] +10014310: 2f00 cmp r7, #0 +10014312: d03a beq.n 1001438a +10014314: 6840 ldr r0, [r0, #4] +10014316: 7130 strb r0, [r6, #4] +10014318: 2400 movs r4, #0 +1001431a: 7930 ldrb r0, [r6, #4] +1001431c: 2500 movs r5, #0 +1001431e: 00c0 lsls r0, r0, #3 +10014320: f7fc fa6a bl 100107f8 +10014324: f8c9 03e8 str.w r0, [r9, #1000] ; 0x3e8 +10014328: 7931 ldrb r1, [r6, #4] +1001432a: 00ca lsls r2, r1, #3 +1001432c: 4621 mov r1, r4 +1001432e: f7f8 f80d bl 1000c34c +10014332: e020 b.n 10014376 +10014334: f857 0034 ldr.w r0, [r7, r4, lsl #3] +10014338: 7840 ldrb r0, [r0, #1] +1001433a: 1c80 adds r0, r0, #2 +1001433c: f7fc fa5c bl 100107f8 +10014340: f8d9 13e8 ldr.w r1, [r9, #1000] ; 0x3e8 +10014344: f841 0034 str.w r0, [r1, r4, lsl #3] +10014348: f857 1034 ldr.w r1, [r7, r4, lsl #3] +1001434c: 784a ldrb r2, [r1, #1] +1001434e: 1c92 adds r2, r2, #2 +10014350: f7f7 fffa bl 1000c348 +10014354: f8d9 03e8 ldr.w r0, [r9, #1000] ; 0x3e8 +10014358: eb07 01c4 add.w r1, r7, r4, lsl #3 +1001435c: eb00 00c4 add.w r0, r0, r4, lsl #3 +10014360: 7909 ldrb r1, [r1, #4] +10014362: 7101 strb r1, [r0, #4] +10014364: f8d9 03e8 ldr.w r0, [r9, #1000] ; 0x3e8 +10014368: eb00 00c4 add.w r0, r0, r4, lsl #3 +1001436c: 7900 ldrb r0, [r0, #4] +1001436e: 0740 lsls r0, r0, #29 +10014370: bf48 it mi +10014372: 2501 movmi r5, #1 +10014374: 1c64 adds r4, r4, #1 +10014376: 7930 ldrb r0, [r6, #4] +10014378: 4284 cmp r4, r0 +1001437a: dbdb blt.n 10014334 +1001437c: b12d cbz r5, 1001438a +1001437e: 2301 movs r3, #1 +10014380: 2200 movs r2, #0 +10014382: 2100 movs r1, #0 +10014384: 4640 mov r0, r8 +10014386: f004 febb bl 10019100 +1001438a: 2000 movs r0, #0 +1001438c: e8bd 83f2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, pc} + +10014390 : +10014390: b570 push {r4, r5, r6, lr} +10014392: 6900 ldr r0, [r0, #16] +10014394: 6800 ldr r0, [r0, #0] +10014396: f500 649d add.w r4, r0, #1256 ; 0x4e8 +1001439a: 6810 ldr r0, [r2, #0] +1001439c: 6805 ldr r5, [r0, #0] +1001439e: 7906 ldrb r6, [r0, #4] +100143a0: f894 03ec ldrb.w r0, [r4, #1004] ; 0x3ec +100143a4: 42b0 cmp r0, r6 +100143a6: da00 bge.n 100143aa +100143a8: e04c b.n 10014444 <.text_26> +100143aa: f8d4 03e8 ldr.w r0, [r4, #1000] ; 0x3e8 +100143ae: 6829 ldr r1, [r5, #0] +100143b0: 784b ldrb r3, [r1, #1] +100143b2: eb00 00c6 add.w r0, r0, r6, lsl #3 +100143b6: f850 0c08 ldr.w r0, [r0, #-8] +100143ba: 7842 ldrb r2, [r0, #1] +100143bc: 4293 cmp r3, r2 +100143be: bf08 it eq +100143c0: 1c9a addeq r2, r3, #2 +100143c2: d010 beq.n 100143e6 +100143c4: 1c91 adds r1, r2, #2 +100143c6: f7fc fa21 bl 1001080c +100143ca: 6828 ldr r0, [r5, #0] +100143cc: 7840 ldrb r0, [r0, #1] +100143ce: 1c80 adds r0, r0, #2 +100143d0: f7fc fa12 bl 100107f8 +100143d4: f8d4 13e8 ldr.w r1, [r4, #1000] ; 0x3e8 +100143d8: eb01 01c6 add.w r1, r1, r6, lsl #3 +100143dc: f841 0c08 str.w r0, [r1, #-8] +100143e0: 6829 ldr r1, [r5, #0] +100143e2: 784a ldrb r2, [r1, #1] +100143e4: 1c92 adds r2, r2, #2 +100143e6: f7f7 ffaf bl 1000c348 +100143ea: f8d4 03e8 ldr.w r0, [r4, #1000] ; 0x3e8 +100143ee: 7929 ldrb r1, [r5, #4] +100143f0: eb00 00c6 add.w r0, r0, r6, lsl #3 +100143f4: f800 1c04 strb.w r1, [r0, #-4] +100143f8: 2000 movs r0, #0 +100143fa: bd70 pop {r4, r5, r6, pc} + +100143fc : +100143fc: b570 push {r4, r5, r6, lr} +100143fe: 6900 ldr r0, [r0, #16] +10014400: 6800 ldr r0, [r0, #0] +10014402: f500 649d add.w r4, r0, #1256 ; 0x4e8 +10014406: 2500 movs r5, #0 +10014408: f8d4 03e8 ldr.w r0, [r4, #1000] ; 0x3e8 +1001440c: 2800 cmp r0, #0 +1001440e: bf1e ittt ne +10014410: f504 767a addne.w r6, r4, #1000 ; 0x3e8 +10014414: 7930 ldrbne r0, [r6, #4] +10014416: 2800 cmpne r0, #0 +10014418: d107 bne.n 1001442a +1001441a: e013 b.n 10014444 <.text_26> +1001441c: f850 0035 ldr.w r0, [r0, r5, lsl #3] +10014420: 7841 ldrb r1, [r0, #1] +10014422: 1c89 adds r1, r1, #2 +10014424: f7fc f9f2 bl 1001080c +10014428: 1c6d adds r5, r5, #1 +1001442a: 7931 ldrb r1, [r6, #4] +1001442c: f8d4 03e8 ldr.w r0, [r4, #1000] ; 0x3e8 +10014430: 428d cmp r5, r1 +10014432: dbf3 blt.n 1001441c +10014434: 00c9 lsls r1, r1, #3 +10014436: f7fc f9e9 bl 1001080c +1001443a: 2000 movs r0, #0 +1001443c: f8c4 03e8 str.w r0, [r4, #1000] ; 0x3e8 +10014440: 7130 strb r0, [r6, #4] +10014442: bd70 pop {r4, r5, r6, pc} + +10014444 <.text_26>: +10014444: f04f 30ff mov.w r0, #4294967295 +10014448: bd70 pop {r4, r5, r6, pc} + +1001444a : +1001444a: 6811 ldr r1, [r2, #0] +1001444c: 6900 ldr r0, [r0, #16] +1001444e: f991 1000 ldrsb.w r1, [r1] +10014452: 6800 ldr r0, [r0, #0] +10014454: 2931 cmp r1, #49 ; 0x31 +10014456: f641 42b9 movw r2, #7353 ; 0x1cb9 +1001445a: bf08 it eq +1001445c: 2100 moveq r1, #0 +1001445e: d002 beq.n 10014466 +10014460: 2930 cmp r1, #48 ; 0x30 +10014462: d101 bne.n 10014468 +10014464: 2101 movs r1, #1 +10014466: 5411 strb r1, [r2, r0] +10014468: 2000 movs r0, #0 +1001446a: 4770 bx lr + +1001446c : +1001446c: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +10014470: 6900 ldr r0, [r0, #16] +10014472: 6806 ldr r6, [r0, #0] +10014474: f106 070c add.w r7, r6, #12 +10014478: 4614 mov r4, r2 +1001447a: f04f 0b00 mov.w fp, #0 +1001447e: f107 0820 add.w r8, r7, #32 +10014482: f44f 6108 mov.w r1, #2176 ; 0x880 +10014486: 4630 mov r0, r6 +10014488: f00b f9e1 bl 1001f84e +1001448c: 2801 cmp r0, #1 +1001448e: d012 beq.n 100144b6 +10014490: f04f 39ff mov.w r9, #4294967295 +10014494: f20f 02dc addw r2, pc, #220 ; 0xdc +10014498: f44f 61fa mov.w r1, #2000 ; 0x7d0 +1001449c: 4630 mov r0, r6 +1001449e: f00b fdb3 bl 10020008 <_rtw_pwr_wakeup> +100144a2: 2800 cmp r0, #0 +100144a4: bf1e ittt ne +100144a6: f641 5028 movwne r0, #7464 ; 0x1d28 +100144aa: 5980 ldrne r0, [r0, r6] +100144ac: 2800 cmpne r0, #0 +100144ae: d05c beq.n 1001456a +100144b0: 7860 ldrb r0, [r4, #1] +100144b2: 2801 cmp r0, #1 +100144b4: d002 beq.n 100144bc +100144b6: f06f 0b15 mvn.w fp, #21 +100144ba: e057 b.n 1001456c +100144bc: f000 f862 bl 10014584 <.text_30> +100144c0: 2801 cmp r0, #1 +100144c2: bf04 itt eq +100144c4: f994 0002 ldrsbeq.w r0, [r4, #2] +100144c8: 2800 cmpeq r0, #0 +100144ca: d11d bne.n 10014508 +100144cc: f994 0003 ldrsb.w r0, [r4, #3] +100144d0: 2800 cmp r0, #0 +100144d2: bf04 itt eq +100144d4: f994 0004 ldrsbeq.w r0, [r4, #4] +100144d8: 2800 cmpeq r0, #0 +100144da: d115 bne.n 10014508 +100144dc: f994 0005 ldrsb.w r0, [r4, #5] +100144e0: 2800 cmp r0, #0 +100144e2: bf01 itttt eq +100144e4: f994 0006 ldrsbeq.w r0, [r4, #6] +100144e8: 2800 cmpeq r0, #0 +100144ea: f994 0007 ldrsbeq.w r0, [r4, #7] +100144ee: 2801 cmpeq r0, #1 +100144f0: d10a bne.n 10014508 +100144f2: 4630 mov r0, r6 +100144f4: f002 f98c bl 10016810 +100144f8: 4630 mov r0, r6 +100144fa: f00a fc8f bl 1001ee1c +100144fe: 2101 movs r1, #1 +10014500: 4630 mov r0, r6 +10014502: f00a fc0c bl 1001ed1e +10014506: e031 b.n 1001456c +10014508: f241 5054 movw r0, #5460 ; 0x1554 +1001450c: a900 add r1, sp, #0 +1001450e: f850 a006 ldr.w sl, [r0, r6] +10014512: f108 0008 add.w r0, r8, #8 +10014516: f7fc f9fd bl 10010914 +1001451a: f8d8 0000 ldr.w r0, [r8] +1001451e: 6138 str r0, [r7, #16] +10014520: 6939 ldr r1, [r7, #16] +10014522: 4640 mov r0, r8 +10014524: f7fc fa11 bl 1001094a +10014528: 2801 cmp r0, #1 +1001452a: d013 beq.n 10014554 +1001452c: 693d ldr r5, [r7, #16] +1001452e: 6828 ldr r0, [r5, #0] +10014530: 6138 str r0, [r7, #16] +10014532: 2206 movs r2, #6 +10014534: 1ca1 adds r1, r4, #2 +10014536: f105 0020 add.w r0, r5, #32 +1001453a: f7fc f972 bl 10010822 +1001453e: 2801 cmp r0, #1 +10014540: d1ee bne.n 10014520 +10014542: 4630 mov r0, r6 +10014544: 6fe9 ldr r1, [r5, #124] ; 0x7c +10014546: f00e fd0b bl 10022f60 +1001454a: b918 cbnz r0, 10014554 +1001454c: 46cb mov fp, r9 +1001454e: f000 f81c bl 1001458a <.text_31> +10014552: e00b b.n 1001456c +10014554: f000 f819 bl 1001458a <.text_31> +10014558: 4651 mov r1, sl +1001455a: 4630 mov r0, r6 +1001455c: f00e fd91 bl 10023082 +10014560: 1ca1 adds r1, r4, #2 +10014562: 4630 mov r0, r6 +10014564: f00e fba0 bl 10022ca8 +10014568: b900 cbnz r0, 1001456c +1001456a: 46cb mov fp, r9 +1001456c: 4658 mov r0, fp +1001456e: e8bd 8ff2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, sl, fp, pc} + ... + +10014574 : +10014574: 7472 5f77 7877 735f 7465 775f 7061 0000 rtw_wx_set_wap.. + +10014584 <.text_30>: +10014584: 2101 movs r1, #1 +10014586: 4638 mov r0, r7 +10014588: e482 b.n 10013e90 + +1001458a <.text_31>: +1001458a: a900 add r1, sp, #0 +1001458c: f108 0008 add.w r0, r8, #8 +10014590: f7fc b9c1 b.w 10010916 + +10014594 : +10014594: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +10014598: b08c sub sp, #48 ; 0x30 +1001459a: 2500 movs r5, #0 +1001459c: 9500 str r5, [sp, #0] +1001459e: 4616 mov r6, r2 +100145a0: 6900 ldr r0, [r0, #16] +100145a2: f20f 02d0 addw r2, pc, #208 ; 0xd0 +100145a6: 6807 ldr r7, [r0, #0] +100145a8: 461c mov r4, r3 +100145aa: f107 0a0c add.w sl, r7, #12 +100145ae: 46a8 mov r8, r5 +100145b0: f04f 39ff mov.w r9, #4294967295 +100145b4: f000 f866 bl 10014684 <.text_34> +100145b8: 2800 cmp r0, #0 +100145ba: d056 beq.n 1001466a +100145bc: f641 409c movw r0, #7324 ; 0x1c9c +100145c0: 59c1 ldr r1, [r0, r7] +100145c2: 2900 cmp r1, #0 +100145c4: d151 bne.n 1001466a +100145c6: f641 5128 movw r1, #7464 ; 0x1d28 +100145ca: 59c9 ldr r1, [r1, r7] +100145cc: 2900 cmp r1, #0 +100145ce: bf1e ittt ne +100145d0: 19c0 addne r0, r0, r7 +100145d2: 7e40 ldrbne r0, [r0, #25] +100145d4: 2800 cmpne r0, #0 +100145d6: d048 beq.n 1001466a +100145d8: f89a 047c ldrb.w r0, [sl, #1148] ; 0x47c +100145dc: 2801 cmp r0, #1 +100145de: d016 beq.n 1001460e +100145e0: f44f 6108 mov.w r1, #2176 ; 0x880 +100145e4: 4650 mov r0, sl +100145e6: f7ff fc53 bl 10013e90 +100145ea: 2801 cmp r0, #1 +100145ec: d00f beq.n 1001460e +100145ee: f44f 6118 mov.w r1, #2432 ; 0x980 +100145f2: 4638 mov r0, r7 +100145f4: f00b f92b bl 1001f84e +100145f8: 2801 cmp r0, #1 +100145fa: d10d bne.n 10014618 +100145fc: f44f 6100 mov.w r1, #2048 ; 0x800 +10014600: 4638 mov r0, r7 +10014602: f00b f924 bl 1001f84e +10014606: b110 cbz r0, 1001460e +10014608: 2001 movs r0, #1 +1001460a: f88a 04d5 strb.w r0, [sl, #1237] ; 0x4d5 +1001460e: 2101 movs r1, #1 +10014610: 4638 mov r0, r7 +10014612: f00a fc15 bl 1001ee40 +10014616: e029 b.n 1001466c +10014618: f8ca 4034 str.w r4, [sl, #52] ; 0x34 +1001461c: f10a 0034 add.w r0, sl, #52 ; 0x34 +10014620: 88f1 ldrh r1, [r6, #6] +10014622: 0509 lsls r1, r1, #20 +10014624: 0d09 lsrs r1, r1, #20 +10014626: 8141 strh r1, [r0, #10] +10014628: 88b1 ldrh r1, [r6, #4] +1001462a: 6041 str r1, [r0, #4] +1001462c: 8105 strh r5, [r0, #8] +1001462e: b1b4 cbz r4, 1001465e +10014630: 2204 movs r2, #4 +10014632: 4621 mov r1, r4 +10014634: a800 add r0, sp, #0 +10014636: f7f7 fe87 bl 1000c348 +1001463a: 9800 ldr r0, [sp, #0] +1001463c: b148 cbz r0, 10014652 +1001463e: 2821 cmp r0, #33 ; 0x21 +10014640: da07 bge.n 10014652 +10014642: 9001 str r0, [sp, #4] +10014644: f10d 0804 add.w r8, sp, #4 +10014648: 9a00 ldr r2, [sp, #0] +1001464a: 1d21 adds r1, r4, #4 +1001464c: a802 add r0, sp, #8 +1001464e: f7f7 fe7b bl 1000c348 +10014652: 9800 ldr r0, [sp, #0] +10014654: 1d02 adds r2, r0, #4 +10014656: 2100 movs r1, #0 +10014658: 4620 mov r0, r4 +1001465a: f7f7 fe77 bl 1000c34c +1001465e: 2201 movs r2, #1 +10014660: 4641 mov r1, r8 +10014662: 4638 mov r0, r7 +10014664: f00e fcd9 bl 1002301a +10014668: b900 cbnz r0, 1001466c +1001466a: 464d mov r5, r9 +1001466c: 4628 mov r0, r5 +1001466e: b00c add sp, #48 ; 0x30 +10014670: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + +10014674 : +10014674: 7472 5f77 7877 735f 7465 735f 6163 006e rtw_wx_set_scan. + +10014684 <.text_34>: +10014684: f44f 61fa mov.w r1, #2000 ; 0x7d0 +10014688: 4638 mov r0, r7 +1001468a: f00b bcbd b.w 10020008 <_rtw_pwr_wakeup> + +1001468e : +1001468e: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +10014692: b08d sub sp, #52 ; 0x34 +10014694: 6900 ldr r0, [r0, #16] +10014696: 6805 ldr r5, [r0, #0] +10014698: f105 060c add.w r6, r5, #12 +1001469c: 4693 mov fp, r2 +1001469e: 461c mov r4, r3 +100146a0: f106 0a20 add.w sl, r6, #32 +100146a4: f04f 0800 mov.w r8, #0 +100146a8: f44f 6108 mov.w r1, #2176 ; 0x880 +100146ac: 4628 mov r0, r5 +100146ae: f00b f8ce bl 1001f84e +100146b2: 2801 cmp r0, #1 +100146b4: bf08 it eq +100146b6: f06f 0815 mvneq.w r8, #21 +100146ba: d078 beq.n 100147ae +100146bc: f04f 39ff mov.w r9, #4294967295 +100146c0: f20f 02f4 addw r2, pc, #244 ; 0xf4 +100146c4: f44f 61fa mov.w r1, #2000 ; 0x7d0 +100146c8: 4628 mov r0, r5 +100146ca: f00b fc9d bl 10020008 <_rtw_pwr_wakeup> +100146ce: 2800 cmp r0, #0 +100146d0: bf1e ittt ne +100146d2: f641 5028 movwne r0, #7464 ; 0x1d28 +100146d6: 5940 ldrne r0, [r0, r5] +100146d8: 2800 cmpne r0, #0 +100146da: d067 beq.n 100147ac +100146dc: f8bb 0004 ldrh.w r0, [fp, #4] +100146e0: 2821 cmp r0, #33 ; 0x21 +100146e2: bfa8 it ge +100146e4: f06f 0806 mvnge.w r8, #6 +100146e8: da61 bge.n 100147ae +100146ea: f001 fc66 bl 10015fba <.text_120> +100146ee: 2800 cmp r0, #0 +100146f0: d15c bne.n 100147ac +100146f2: f605 0034 addw r0, r5, #2100 ; 0x834 +100146f6: f7fc f9a7 bl 10010a48 +100146fa: f885 8844 strb.w r8, [r5, #2116] ; 0x844 +100146fe: f241 5054 movw r0, #5460 ; 0x1554 +10014702: f885 8845 strb.w r8, [r5, #2117] ; 0x845 +10014706: 5940 ldr r0, [r0, r5] +10014708: 9001 str r0, [sp, #4] +1001470a: f8bb 0006 ldrh.w r0, [fp, #6] +1001470e: 2800 cmp r0, #0 +10014710: bf1c itt ne +10014712: f8bb 7004 ldrhne.w r7, [fp, #4] +10014716: 2f00 cmpne r7, #0 +10014718: d049 beq.n 100147ae +1001471a: 2f20 cmp r7, #32 +1001471c: bfc8 it gt +1001471e: 2720 movgt r7, #32 +10014720: 2228 movs r2, #40 ; 0x28 +10014722: 2100 movs r1, #0 +10014724: a802 add r0, sp, #8 +10014726: f7fc f887 bl 10010838 +1001472a: 9702 str r7, [sp, #8] +1001472c: 463a mov r2, r7 +1001472e: 4621 mov r1, r4 +10014730: a803 add r0, sp, #12 +10014732: f7fc f86c bl 1001080e +10014736: a900 add r1, sp, #0 +10014738: f10a 0008 add.w r0, sl, #8 +1001473c: f7fc f8ea bl 10010914 +10014740: f8da 0000 ldr.w r0, [sl] +10014744: 6130 str r0, [r6, #16] +10014746: 6931 ldr r1, [r6, #16] +10014748: 4650 mov r0, sl +1001474a: f7fc f8fe bl 1001094a +1001474e: 2801 cmp r0, #1 +10014750: d021 beq.n 10014796 +10014752: 6934 ldr r4, [r6, #16] +10014754: 6820 ldr r0, [r4, #0] +10014756: 6130 str r0, [r6, #16] +10014758: a903 add r1, sp, #12 +1001475a: 9a02 ldr r2, [sp, #8] +1001475c: f104 002c add.w r0, r4, #44 ; 0x2c +10014760: f7fc f85f bl 10010822 +10014764: 2801 cmp r0, #1 +10014766: bf02 ittt eq +10014768: 6aa0 ldreq r0, [r4, #40] ; 0x28 +1001476a: 9902 ldreq r1, [sp, #8] +1001476c: 4288 cmpeq r0, r1 +1001476e: d1ea bne.n 10014746 +10014770: 2120 movs r1, #32 +10014772: f001 fc23 bl 10015fbc <.text_120+0x2> +10014776: 2801 cmp r0, #1 +10014778: d104 bne.n 10014784 +1001477a: 6fe0 ldr r0, [r4, #124] ; 0x7c +1001477c: f8d6 10ec ldr.w r1, [r6, #236] ; 0xec +10014780: 4288 cmp r0, r1 +10014782: d1e0 bne.n 10014746 +10014784: 4628 mov r0, r5 +10014786: 6fe1 ldr r1, [r4, #124] ; 0x7c +10014788: f00e fbea bl 10022f60 +1001478c: b918 cbnz r0, 10014796 +1001478e: 46c8 mov r8, r9 +10014790: f000 f81c bl 100147cc <.text_37> +10014794: e00b b.n 100147ae +10014796: f000 f819 bl 100147cc <.text_37> +1001479a: 9901 ldr r1, [sp, #4] +1001479c: 4628 mov r0, r5 +1001479e: f00e fc70 bl 10023082 +100147a2: a902 add r1, sp, #8 +100147a4: 4628 mov r0, r5 +100147a6: f00e fb45 bl 10022e34 +100147aa: b900 cbnz r0, 100147ae +100147ac: 46c8 mov r8, r9 +100147ae: 4640 mov r0, r8 +100147b0: b00d add sp, #52 ; 0x34 +100147b2: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + ... + +100147b8 : +100147b8: 7472 5f77 7877 735f 7465 655f 7373 6469 rtw_wx_set_essid +100147c8: 0000 0000 .... + +100147cc <.text_37>: +100147cc: a900 add r1, sp, #0 +100147ce: f10a 0008 add.w r0, sl, #8 +100147d2: f7fc b8a0 b.w 10010916 + ... + +100147d8 : +100147d8: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +100147dc: 4680 mov r8, r0 +100147de: 4617 mov r7, r2 +100147e0: f8d8 0010 ldr.w r0, [r8, #16] +100147e4: 88f9 ldrh r1, [r7, #6] +100147e6: 6806 ldr r6, [r0, #0] +100147e8: 0509 lsls r1, r1, #20 +100147ea: 2000 movs r0, #0 +100147ec: 0d09 lsrs r1, r1, #20 +100147ee: 290a cmp r1, #10 +100147f0: f241 14f0 movw r4, #4592 ; 0x11f0 +100147f4: f241 5554 movw r5, #5460 ; 0x1554 +100147f8: d851 bhi.n 1001489e +100147fa: e8df f001 tbb [pc, r1] +100147fe: 0c0c .short 0x0c0c +10014800: 0e060c0c .word 0x0e060c0c +10014804: 500c0c1d .word 0x500c0c1d +10014808: 000c .short 0x000c +1001480a: 6839 ldr r1, [r7, #0] +1001480c: b101 cbz r1, 10014810 +1001480e: 2101 movs r1, #1 +10014810: f241 627c movw r2, #5756 ; 0x167c +10014814: 5591 strb r1, [r2, r6] +10014816: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} +1001481a: 19a9 adds r1, r5, r6 +1001481c: 684a ldr r2, [r1, #4] +1001481e: 2a00 cmp r2, #0 +10014820: bf1c itt ne +10014822: 683a ldrne r2, [r7, #0] +10014824: 2a00 cmpne r2, #0 +10014826: d0f6 beq.n 10014816 +10014828: 2201 movs r2, #1 +1001482a: 604a str r2, [r1, #4] +1001482c: 19a1 adds r1, r4, r6 +1001482e: 6048 str r0, [r1, #4] +10014830: 65c8 str r0, [r1, #92] ; 0x5c +10014832: 51a0 str r0, [r4, r6] +10014834: 51a8 str r0, [r5, r6] +10014836: e7ee b.n 10014816 +10014838: 2101 movs r1, #1 +1001483a: f106 000c add.w r0, r6, #12 +1001483e: f7ff fb27 bl 10013e90 +10014842: b148 cbz r0, 10014858 +10014844: 4630 mov r0, r6 +10014846: f001 ffe3 bl 10016810 +1001484a: 4630 mov r0, r6 +1001484c: f00a fae6 bl 1001ee1c +10014850: 2101 movs r1, #1 +10014852: 4630 mov r0, r6 +10014854: f00a fa63 bl 1001ed1e +10014858: f8d8 0010 ldr.w r0, [r8, #16] +1001485c: 683a ldr r2, [r7, #0] +1001485e: 6801 ldr r1, [r0, #0] +10014860: 2000 movs r0, #0 +10014862: 186b adds r3, r5, r1 +10014864: f002 0603 and.w r6, r2, #3 +10014868: 2e03 cmp r6, #3 +1001486a: d105 bne.n 10014878 +1001486c: 6058 str r0, [r3, #4] +1001486e: 2202 movs r2, #2 +10014870: 506a str r2, [r5, r1] +10014872: 2203 movs r2, #3 +10014874: 5062 str r2, [r4, r1] +10014876: e7ce b.n 10014816 +10014878: 0796 lsls r6, r2, #30 +1001487a: d503 bpl.n 10014884 +1001487c: 6058 str r0, [r3, #4] +1001487e: 2201 movs r2, #1 +10014880: 506a str r2, [r5, r1] +10014882: e7f7 b.n 10014874 +10014884: 07d3 lsls r3, r2, #31 +10014886: d505 bpl.n 10014894 +10014888: 586a ldr r2, [r5, r1] +1001488a: 2a04 cmp r2, #4 +1001488c: d2c3 bcs.n 10014816 +1001488e: 5068 str r0, [r5, r1] +10014890: 5060 str r0, [r4, r1] +10014892: e7c0 b.n 10014816 +10014894: 0751 lsls r1, r2, #29 +10014896: d4be bmi.n 10014816 +10014898: f06f 0015 mvn.w r0, #21 +1001489c: e7bb b.n 10014816 +1001489e: f06f 005e mvn.w r0, #94 ; 0x5e +100148a2: e7b8 b.n 10014816 + +100148a4 : +100148a4: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +100148a8: 461d mov r5, r3 +100148aa: 4680 mov r8, r0 +100148ac: 8ce8 ldrh r0, [r5, #38] ; 0x26 +100148ae: f100 0940 add.w r9, r0, #64 ; 0x40 +100148b2: 4614 mov r4, r2 +100148b4: 4648 mov r0, r9 +100148b6: f7fb ff9f bl 100107f8 +100148ba: 0007 movs r7, r0 +100148bc: d052 beq.n 10014964 +100148be: 464a mov r2, r9 +100148c0: f000 f860 bl 10014984 <.text_43> +100148c4: 2003 movs r0, #3 +100148c6: 6038 str r0, [r7, #0] +100148c8: 2206 movs r2, #6 +100148ca: 21ff movs r1, #255 ; 0xff +100148cc: 1d38 adds r0, r7, #4 +100148ce: f7fb ffb3 bl 10010838 +100148d2: 8ca8 ldrh r0, [r5, #36] ; 0x24 +100148d4: b128 cbz r0, 100148e2 +100148d6: 2802 cmp r0, #2 +100148d8: d03e beq.n 10014958 +100148da: d33b bcc.n 10014954 +100148dc: 2803 cmp r0, #3 +100148de: d03e beq.n 1001495e +100148e0: e040 b.n 10014964 +100148e2: f20f 0188 addw r1, pc, #136 ; 0x88 +100148e6: 2210 movs r2, #16 +100148e8: f107 000c add.w r0, r7, #12 +100148ec: f7f7 fd38 bl 1000c360 +100148f0: 7828 ldrb r0, [r5, #0] +100148f2: 0700 lsls r0, r0, #28 +100148f4: bf44 itt mi +100148f6: 2001 movmi r0, #1 +100148f8: 7738 strbmi r0, [r7, #28] +100148fa: 8ca8 ldrh r0, [r5, #36] ; 0x24 +100148fc: 2801 cmp r0, #1 +100148fe: d004 beq.n 1001490a +10014900: 7828 ldrb r0, [r5, #0] +10014902: 0740 lsls r0, r0, #29 +10014904: bf44 itt mi +10014906: 2000 movmi r0, #0 +10014908: 7738 strbmi r0, [r7, #28] +1001490a: 88e0 ldrh r0, [r4, #6] +1001490c: f107 061c add.w r6, r7, #28 +10014910: 1e40 subs r0, r0, #1 +10014912: 7230 strb r0, [r6, #8] +10014914: 7828 ldrb r0, [r5, #0] +10014916: 0780 lsls r0, r0, #30 +10014918: d506 bpl.n 10014928 +1001491a: 2208 movs r2, #8 +1001491c: f105 010c add.w r1, r5, #12 +10014920: f107 0025 add.w r0, r7, #37 ; 0x25 +10014924: f7fb ff73 bl 1001080e +10014928: 8ce8 ldrh r0, [r5, #38] ; 0x26 +1001492a: b138 cbz r0, 1001493c +1001492c: 8270 strh r0, [r6, #18] +1001492e: f105 0128 add.w r1, r5, #40 ; 0x28 +10014932: 8cea ldrh r2, [r5, #38] ; 0x26 +10014934: f107 0030 add.w r0, r7, #48 ; 0x30 +10014938: f7fb ff69 bl 1001080e +1001493c: 464a mov r2, r9 +1001493e: 4639 mov r1, r7 +10014940: 4640 mov r0, r8 +10014942: f7ff fb2b bl 10013f9c +10014946: 4604 mov r4, r0 +10014948: 4649 mov r1, r9 +1001494a: f7ff fada bl 10013f02 <.text_6+0x2> +1001494e: 4620 mov r0, r4 +10014950: e8bd 83f2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, pc} +10014954: a1db add r1, pc, #876 ; (adr r1, 10014cc4 <.text_55>) +10014956: e7c6 b.n 100148e6 +10014958: f20f 0118 addw r1, pc, #24 +1001495c: e7c3 b.n 100148e6 +1001495e: f20f 011c addw r1, pc, #28 +10014962: e7c0 b.n 100148e6 +10014964: f04f 30ff mov.w r0, #4294967295 +10014968: e7f2 b.n 10014950 + ... + +1001496c : +1001496c: 6f6e 656e 0000 0000 none.... + +10014974 : +10014974: 4b54 5049 0000 0000 TKIP.... + +1001497c : +1001497c: 4343 504d 0000 0000 CCMP.... + +10014984 <.text_43>: +10014984: 2100 movs r1, #0 +10014986: f7fb bf57 b.w 10010838 + +1001498a : +1001498a: b900 cbnz r0, 1001498e +1001498c: 4770 bx lr +1001498e: b5f0 push {r4, r5, r6, r7, lr} +10014990: b371 cbz r1, 100149f0 +10014992: 2300 movs r3, #0 +10014994: e007 b.n 100149a6 +10014996: 1bf6 subs r6, r6, r7 +10014998: 4466 add r6, ip +1001499a: eb0e 1606 add.w r6, lr, r6, lsl #4 +1001499e: 1b34 subs r4, r6, r4 +100149a0: 192c adds r4, r5, r4 +100149a2: 541c strb r4, [r3, r0] +100149a4: 1c5b adds r3, r3, #1 +100149a6: 4293 cmp r3, r2 +100149a8: da22 bge.n 100149f0 +100149aa: 005c lsls r4, r3, #1 +100149ac: 5c66 ldrb r6, [r4, r1] +100149ae: 2e61 cmp r6, #97 ; 0x61 +100149b0: bfa8 it ge +100149b2: 2761 movge r7, #97 ; 0x61 +100149b4: da03 bge.n 100149be +100149b6: 2e41 cmp r6, #65 ; 0x41 +100149b8: bfac ite ge +100149ba: 2741 movge r7, #65 ; 0x41 +100149bc: 2730 movlt r7, #48 ; 0x30 +100149be: 1864 adds r4, r4, r1 +100149c0: f894 e001 ldrb.w lr, [r4, #1] +100149c4: f1be 0f61 cmp.w lr, #97 ; 0x61 +100149c8: bfa8 it ge +100149ca: 2461 movge r4, #97 ; 0x61 +100149cc: da04 bge.n 100149d8 +100149ce: f1be 0f41 cmp.w lr, #65 ; 0x41 +100149d2: bfac ite ge +100149d4: 2441 movge r4, #65 ; 0x41 +100149d6: 2430 movlt r4, #48 ; 0x30 +100149d8: 2e41 cmp r6, #65 ; 0x41 +100149da: bfac ite ge +100149dc: f04f 0c0a movge.w ip, #10 +100149e0: f04f 0c00 movlt.w ip, #0 +100149e4: f1be 0f41 cmp.w lr, #65 ; 0x41 +100149e8: bfac ite ge +100149ea: 250a movge r5, #10 +100149ec: 2500 movlt r5, #0 +100149ee: e7d2 b.n 10014996 +100149f0: bdf0 pop {r4, r5, r6, r7, pc} + +100149f2 : +100149f2: b570 push {r4, r5, r6, lr} +100149f4: 6900 ldr r0, [r0, #16] +100149f6: 6800 ldr r0, [r0, #0] +100149f8: f500 5088 add.w r0, r0, #4352 ; 0x1100 +100149fc: 30f0 adds r0, #240 ; 0xf0 +100149fe: f500 66c9 add.w r6, r0, #1608 ; 0x648 +10014a02: 4614 mov r4, r2 +10014a04: 461d mov r5, r3 +10014a06: 4630 mov r0, r6 +10014a08: f7f7 fca6 bl 1000c358 +10014a0c: 80a0 strh r0, [r4, #4] +10014a0e: 88a2 ldrh r2, [r4, #4] +10014a10: b12a cbz r2, 10014a1e +10014a12: 2a40 cmp r2, #64 ; 0x40 +10014a14: da03 bge.n 10014a1e +10014a16: 4631 mov r1, r6 +10014a18: 4628 mov r0, r5 +10014a1a: f7fb fef8 bl 1001080e +10014a1e: 2000 movs r0, #0 +10014a20: bd70 pop {r4, r5, r6, pc} + +10014a22 : +10014a22: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +10014a26: 4604 mov r4, r0 +10014a28: b083 sub sp, #12 +10014a2a: 6920 ldr r0, [r4, #16] +10014a2c: 6800 ldr r0, [r0, #0] +10014a2e: 9000 str r0, [sp, #0] +10014a30: f500 5788 add.w r7, r0, #4352 ; 0x1100 +10014a34: 2600 movs r6, #0 +10014a36: 4615 mov r5, r2 +10014a38: 4698 mov r8, r3 +10014a3a: 37f0 adds r7, #240 ; 0xf0 +10014a3c: 46b1 mov r9, r6 +10014a3e: 46b2 mov sl, r6 +10014a40: f44f 7040 mov.w r0, #768 ; 0x300 +10014a44: f7fb fed8 bl 100107f8 +10014a48: 4683 mov fp, r0 +10014a4a: f44f 7240 mov.w r2, #768 ; 0x300 +10014a4e: f7ff ff99 bl 10014984 <.text_43> +10014a52: 88aa ldrh r2, [r5, #4] +10014a54: 9800 ldr r0, [sp, #0] +10014a56: 465b mov r3, fp +10014a58: 4641 mov r1, r8 +10014a5a: f004 fe3f bl 100196dc +10014a5e: 4605 mov r5, r0 +10014a60: f5b5 7f40 cmp.w r5, #768 ; 0x300 +10014a64: bfc8 it gt +10014a66: f04f 36ff movgt.w r6, #4294967295 +10014a6a: dc48 bgt.n 10014afe +10014a6c: f8d7 0364 ldr.w r0, [r7, #868] ; 0x364 +10014a70: 2804 cmp r0, #4 +10014a72: bf18 it ne +10014a74: 2807 cmpne r0, #7 +10014a76: d111 bne.n 10014a9c +10014a78: 462b mov r3, r5 +10014a7a: aa01 add r2, sp, #4 +10014a7c: 2130 movs r1, #48 ; 0x30 +10014a7e: 4658 mov r0, fp +10014a80: f7ff f9fe bl 10013e80 +10014a84: 9a01 ldr r2, [sp, #4] +10014a86: 4601 mov r1, r0 +10014a88: 9800 ldr r0, [sp, #0] +10014a8a: b292 uxth r2, r2 +10014a8c: f00f ffb6 bl 100249fc +10014a90: 9800 ldr r0, [sp, #0] +10014a92: 4642 mov r2, r8 +10014a94: f507 61c9 add.w r1, r7, #1608 ; 0x648 +10014a98: f00f ff65 bl 10024966 +10014a9c: f105 0a0e add.w sl, r5, #14 +10014aa0: 4650 mov r0, sl +10014aa2: f7fb fea9 bl 100107f8 +10014aa6: 4681 mov r9, r0 +10014aa8: 4652 mov r2, sl +10014aaa: f7ff ff6b bl 10014984 <.text_43> +10014aae: 462a mov r2, r5 +10014ab0: 4659 mov r1, fp +10014ab2: f109 000e add.w r0, r9, #14 +10014ab6: f7fb feaa bl 1001080e +10014aba: 6920 ldr r0, [r4, #16] +10014abc: 6804 ldr r4, [r0, #0] +10014abe: f504 5588 add.w r5, r4, #4352 ; 0x1100 +10014ac2: 3528 adds r5, #40 ; 0x28 +10014ac4: 2110 movs r1, #16 +10014ac6: f104 000c add.w r0, r4, #12 +10014aca: f7ff f9e1 bl 10013e90 +10014ace: 2801 cmp r0, #1 +10014ad0: d115 bne.n 10014afe +10014ad2: 2202 movs r2, #2 +10014ad4: f109 010c add.w r1, r9, #12 +10014ad8: f105 00c4 add.w r0, r5, #196 ; 0xc4 +10014adc: f7fb fe97 bl 1001080e +10014ae0: f8b5 00c4 ldrh.w r0, [r5, #196] ; 0xc4 +10014ae4: 2809 cmp r0, #9 +10014ae6: da00 bge.n 10014aea +10014ae8: b910 cbnz r0, 10014af0 +10014aea: 2008 movs r0, #8 +10014aec: f8a5 00c4 strh.w r0, [r5, #196] ; 0xc4 +10014af0: f1aa 020e sub.w r2, sl, #14 +10014af4: f109 010e add.w r1, r9, #14 +10014af8: 4620 mov r0, r4 +10014afa: f004 f8b4 bl 10018c66 +10014afe: f1bb 0f00 cmp.w fp, #0 +10014b02: d004 beq.n 10014b0e +10014b04: f44f 7140 mov.w r1, #768 ; 0x300 +10014b08: 4658 mov r0, fp +10014b0a: f7fb fe7f bl 1001080c +10014b0e: f1b9 0f00 cmp.w r9, #0 +10014b12: d003 beq.n 10014b1c +10014b14: 4651 mov r1, sl +10014b16: 4648 mov r0, r9 +10014b18: f7fb fe78 bl 1001080c +10014b1c: 4630 mov r0, r6 +10014b1e: e8bd 8ffe ldmia.w sp!, {r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +10014b22 : +10014b22: e92d 41fc stmdb sp!, {r2, r3, r4, r5, r6, r7, r8, lr} +10014b26: 6900 ldr r0, [r0, #16] +10014b28: 6807 ldr r7, [r0, #0] +10014b2a: 4616 mov r6, r2 +10014b2c: 461c mov r4, r3 +10014b2e: 88b5 ldrh r5, [r6, #4] +10014b30: 4628 mov r0, r5 +10014b32: f7fb fe61 bl 100107f8 +10014b36: ea5f 0800 movs.w r8, r0 +10014b3a: bf08 it eq +10014b3c: f06f 000b mvneq.w r0, #11 +10014b40: d024 beq.n 10014b8c +10014b42: 6831 ldr r1, [r6, #0] +10014b44: 462a mov r2, r5 +10014b46: f7fb fe62 bl 1001080e +10014b4a: 2000 movs r0, #0 +10014b4c: 9001 str r0, [sp, #4] +10014b4e: 9000 str r0, [sp, #0] +10014b50: ab00 add r3, sp, #0 +10014b52: aa01 add r2, sp, #4 +10014b54: f20f 0160 addw r1, pc, #96 ; 0x60 +10014b58: 4640 mov r0, r8 +10014b5a: f010 f855 bl 10024c08 +10014b5e: 9801 ldr r0, [sp, #4] +10014b60: 2801 cmp r0, #1 +10014b62: d004 beq.n 10014b6e +10014b64: 2802 cmp r0, #2 +10014b66: d013 beq.n 10014b90 +10014b68: 2804 cmp r0, #4 +10014b6a: d019 beq.n 10014ba0 +10014b6c: e020 b.n 10014bb0 +10014b6e: 9900 ldr r1, [sp, #0] +10014b70: 4638 mov r0, r7 +10014b72: f010 f85b bl 10024c2c +10014b76: 4602 mov r2, r0 +10014b78: f20f 0144 addw r1, pc, #68 ; 0x44 +10014b7c: 4620 mov r0, r4 +10014b7e: f7f7 fb95 bl 1000c2ac +10014b82: 4629 mov r1, r5 +10014b84: 4640 mov r0, r8 +10014b86: f7fb fe41 bl 1001080c +10014b8a: 2000 movs r0, #0 +10014b8c: e8bd 81f6 ldmia.w sp!, {r1, r2, r4, r5, r6, r7, r8, pc} +10014b90: 9900 ldr r1, [sp, #0] +10014b92: 4638 mov r0, r7 +10014b94: f010 f850 bl 10024c38 +10014b98: 4602 mov r2, r0 +10014b9a: f20f 012c addw r1, pc, #44 ; 0x2c +10014b9e: e7ed b.n 10014b7c +10014ba0: 9900 ldr r1, [sp, #0] +10014ba2: 4638 mov r0, r7 +10014ba4: f010 f84e bl 10024c44 +10014ba8: 4602 mov r2, r0 +10014baa: f20f 0124 addw r1, pc, #36 ; 0x24 +10014bae: e7e5 b.n 10014b7c +10014bb0: f06f 0015 mvn.w r0, #21 +10014bb4: e7ea b.n 10014b8c + ... + +10014bb8 : +10014bb8: 6425 252c 0078 0000 %d,%x... + +10014bc0 : +10014bc0: 7830 3025 5832 0000 0x%02X.. + +10014bc8 : +10014bc8: 7830 3025 5834 0000 0x%04X.. + +10014bd0 : +10014bd0: 7830 3025 5838 0000 0x%08X.. + +10014bd8 : +10014bd8: b51f push {r0, r1, r2, r3, r4, lr} +10014bda: 4601 mov r1, r0 +10014bdc: 4618 mov r0, r3 +10014bde: 6909 ldr r1, [r1, #16] +10014be0: 680c ldr r4, [r1, #0] +10014be2: 2100 movs r1, #0 +10014be4: 9103 str r1, [sp, #12] +10014be6: 9102 str r1, [sp, #8] +10014be8: 9101 str r1, [sp, #4] +10014bea: ab02 add r3, sp, #8 +10014bec: a901 add r1, sp, #4 +10014bee: 9100 str r1, [sp, #0] +10014bf0: aa03 add r2, sp, #12 +10014bf2: f20f 0148 addw r1, pc, #72 ; 0x48 +10014bf6: f010 f807 bl 10024c08 +10014bfa: 9803 ldr r0, [sp, #12] +10014bfc: 2801 cmp r0, #1 +10014bfe: d004 beq.n 10014c0a +10014c00: 2802 cmp r0, #2 +10014c02: d00b beq.n 10014c1c +10014c04: 2804 cmp r0, #4 +10014c06: d010 beq.n 10014c2a +10014c08: e015 b.n 10014c36 +10014c0a: 9a01 ldr r2, [sp, #4] +10014c0c: 9902 ldr r1, [sp, #8] +10014c0e: b2d2 uxtb r2, r2 +10014c10: 4620 mov r0, r4 +10014c12: f010 f81d bl 10024c50 +10014c16: 2000 movs r0, #0 +10014c18: b004 add sp, #16 +10014c1a: bd10 pop {r4, pc} +10014c1c: 9a01 ldr r2, [sp, #4] +10014c1e: 9902 ldr r1, [sp, #8] +10014c20: b292 uxth r2, r2 +10014c22: 4620 mov r0, r4 +10014c24: f010 f81c bl 10024c60 +10014c28: e7f5 b.n 10014c16 +10014c2a: 9a01 ldr r2, [sp, #4] +10014c2c: 9902 ldr r1, [sp, #8] +10014c2e: 4620 mov r0, r4 +10014c30: f010 f81e bl 10024c70 +10014c34: e7ef b.n 10014c16 +10014c36: f06f 0015 mvn.w r0, #21 +10014c3a: e7ed b.n 10014c18 + +10014c3c : +10014c3c: 6425 252c 2c78 7825 0000 0000 %d,%x,%x.... + +10014c48 : +10014c48: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +10014c4c: 4681 mov r9, r0 +10014c4e: 2401 movs r4, #1 +10014c50: f20f 0074 addw r0, pc, #116 ; 0x74 +10014c54: f7f7 fb55 bl 1000c302 +10014c58: f20f 1ad8 addw sl, pc, #472 ; 0x1d8 +10014c5c: f20f 180c addw r8, pc, #268 ; 0x10c +10014c60: 2500 movs r5, #0 +10014c62: a666 add r6, pc, #408 ; (adr r6, 10014dfc <.text_62>) +10014c64: f000 f83e bl 10014ce4 <.text_57> +10014c68: d101 bne.n 10014c6e +10014c6a: f000 f8e9 bl 10014e40 <.text_67> +10014c6e: 4629 mov r1, r5 +10014c70: 4648 mov r0, r9 +10014c72: f00f ffe7 bl 10024c44 +10014c76: 4601 mov r1, r0 +10014c78: 4650 mov r0, sl +10014c7a: f7f7 fb42 bl 1000c302 +10014c7e: 1c64 adds r4, r4, #1 +10014c80: b917 cbnz r7, 10014c88 +10014c82: 4630 mov r0, r6 +10014c84: f7f7 fb3d bl 1000c302 +10014c88: 1d2d adds r5, r5, #4 +10014c8a: f5b5 7f40 cmp.w r5, #768 ; 0x300 +10014c8e: dbe9 blt.n 10014c64 +10014c90: f44f 6580 mov.w r5, #1024 ; 0x400 +10014c94: f000 f826 bl 10014ce4 <.text_57> +10014c98: d101 bne.n 10014c9e +10014c9a: f000 f8d1 bl 10014e40 <.text_67> +10014c9e: 4629 mov r1, r5 +10014ca0: 4648 mov r0, r9 +10014ca2: f00f ffcf bl 10024c44 +10014ca6: 4601 mov r1, r0 +10014ca8: 4650 mov r0, sl +10014caa: f7f7 fb2a bl 1000c302 +10014cae: 1c64 adds r4, r4, #1 +10014cb0: b917 cbnz r7, 10014cb8 +10014cb2: 4630 mov r0, r6 +10014cb4: f7f7 fb25 bl 1000c302 +10014cb8: 1d2d adds r5, r5, #4 +10014cba: f5b5 6f00 cmp.w r5, #2048 ; 0x800 +10014cbe: dbe9 blt.n 10014c94 +10014cc0: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + +10014cc4 <.text_55>: +10014cc4: 00504557 .word 0x00504557 + +10014cc8 : +10014cc8: 3d3d3d0a 3d3d3d3d 43414d20 47455220 .======= MAC REG +10014cd8: 3d3d3d20 3d3d3d3d 0000000a =======.... + +10014ce4 <.text_57>: +10014ce4: 1060 asrs r0, r4, #1 +10014ce6: eb04 7090 add.w r0, r4, r0, lsr #30 +10014cea: 1080 asrs r0, r0, #2 +10014cec: eba4 0780 sub.w r7, r4, r0, lsl #2 +10014cf0: 2f01 cmp r7, #1 +10014cf2: 4770 bx lr + +10014cf4 : +10014cf4: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +10014cf8: 4682 mov sl, r0 +10014cfa: 2501 movs r5, #1 +10014cfc: f20f 0050 addw r0, pc, #80 ; 0x50 +10014d00: f7f7 faff bl 1000c302 +10014d04: f20f 182c addw r8, pc, #300 ; 0x12c +10014d08: f20f 0960 addw r9, pc, #96 ; 0x60 +10014d0c: f44f 6600 mov.w r6, #2048 ; 0x800 +10014d10: a73a add r7, pc, #232 ; (adr r7, 10014dfc <.text_62>) +10014d12: 1068 asrs r0, r5, #1 +10014d14: eb05 7090 add.w r0, r5, r0, lsr #30 +10014d18: 1080 asrs r0, r0, #2 +10014d1a: eba5 0480 sub.w r4, r5, r0, lsl #2 +10014d1e: 2c01 cmp r4, #1 +10014d20: d103 bne.n 10014d2a +10014d22: 4631 mov r1, r6 +10014d24: 4648 mov r0, r9 +10014d26: f7f7 faec bl 1000c302 +10014d2a: 4631 mov r1, r6 +10014d2c: 4650 mov r0, sl +10014d2e: f00f ff89 bl 10024c44 +10014d32: 4601 mov r1, r0 +10014d34: f000 f885 bl 10014e42 <.text_67+0x2> +10014d38: 1c6d adds r5, r5, #1 +10014d3a: b914 cbnz r4, 10014d42 +10014d3c: 4638 mov r0, r7 +10014d3e: f7f7 fae0 bl 1000c302 +10014d42: 1d36 adds r6, r6, #4 +10014d44: f5b6 5f80 cmp.w r6, #4096 ; 0x1000 +10014d48: dbe3 blt.n 10014d12 +10014d4a: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + ... + +10014d50 : +10014d50: 3d0a 3d3d 3d3d 3d3d 4220 2042 4552 2047 .======= BB REG +10014d60: 3d3d 3d3d 3d3d 0a3d 0000 0000 =======..... + +10014d6c : +10014d6c: 7830 3025 7832 0000 0x%02x.. + +10014d74 : +10014d74: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +10014d78: 4681 mov r9, r0 +10014d7a: 2501 movs r5, #1 +10014d7c: aa00 add r2, sp, #0 +10014d7e: 2116 movs r1, #22 +10014d80: f002 fad0 bl 10017324 +10014d84: f89d 0000 ldrb.w r0, [sp] +10014d88: 2800 cmp r0, #0 +10014d8a: bf16 itet ne +10014d8c: 2803 cmpne r0, #3 +10014d8e: 46ab moveq fp, r5 +10014d90: f04f 0b02 movne.w fp, #2 +10014d94: f20f 0068 addw r0, pc, #104 ; 0x68 +10014d98: f7f7 fab3 bl 1000c302 +10014d9c: f20f 087c addw r8, pc, #124 ; 0x7c +10014da0: 2700 movs r7, #0 +10014da2: e026 b.n 10014df2 +10014da4: 4639 mov r1, r7 +10014da6: f20f 007c addw r0, pc, #124 ; 0x7c +10014daa: f7f7 faaa bl 1000c302 +10014dae: 2400 movs r4, #0 +10014db0: f04f 33ff mov.w r3, #4294967295 +10014db4: 4622 mov r2, r4 +10014db6: 4639 mov r1, r7 +10014db8: 4648 mov r0, r9 +10014dba: f002 fb8f bl 100174dc +10014dbe: 4682 mov sl, r0 +10014dc0: 1068 asrs r0, r5, #1 +10014dc2: eb05 7090 add.w r0, r5, r0, lsr #30 +10014dc6: 1080 asrs r0, r0, #2 +10014dc8: eba5 0680 sub.w r6, r5, r0, lsl #2 +10014dcc: 2e01 cmp r6, #1 +10014dce: d102 bne.n 10014dd6 +10014dd0: 4621 mov r1, r4 +10014dd2: f000 f836 bl 10014e42 <.text_67+0x2> +10014dd6: 4651 mov r1, sl +10014dd8: f20f 0058 addw r0, pc, #88 ; 0x58 +10014ddc: f7f7 fa91 bl 1000c302 +10014de0: 1c6d adds r5, r5, #1 +10014de2: b916 cbnz r6, 10014dea +10014de4: a005 add r0, pc, #20 ; (adr r0, 10014dfc <.text_62>) +10014de6: f7f7 fa8c bl 1000c302 +10014dea: 1c64 adds r4, r4, #1 +10014dec: 2cff cmp r4, #255 ; 0xff +10014dee: dddf ble.n 10014db0 +10014df0: 1c7f adds r7, r7, #1 +10014df2: 455f cmp r7, fp +10014df4: dbd6 blt.n 10014da4 +10014df6: e8bd 8ff1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, sl, fp, pc} + ... + +10014dfc <.text_62>: +10014dfc: 0000000a .word 0x0000000a + +10014e00 : +10014e00: 3d3d3d0a 3d3d3d3d 20465220 20474552 .======= RF REG +10014e10: 3d3d3d3d 0a3d3d3d 00000000 =======..... + +10014e1c : +10014e1c: 30257830 00207832 0x%02x . + +10014e24 : +10014e24: 5f46520a 68746150 29782528 0000000a .RF_Path(%x).... + +10014e34 : +10014e34: 25783020 20783830 00000000 0x%08x .... + +10014e40 <.text_67>: +10014e40: 4629 mov r1, r5 +10014e42: 4640 mov r0, r8 +10014e44: f7f7 ba5d b.w 1000c302 + +10014e48 : +10014e48: b538 push {r3, r4, r5, lr} +10014e4a: 6900 ldr r0, [r0, #16] +10014e4c: 6804 ldr r4, [r0, #0] +10014e4e: 6810 ldr r0, [r2, #0] +10014e50: 7845 ldrb r5, [r0, #1] +10014e52: 7801 ldrb r1, [r0, #0] +10014e54: 4620 mov r0, r4 +10014e56: f00b f95f bl 10020118 +10014e5a: 4629 mov r1, r5 +10014e5c: 4620 mov r0, r4 +10014e5e: f00b f938 bl 100200d2 +10014e62: 2000 movs r0, #0 +10014e64: bd32 pop {r1, r4, r5, pc} + +10014e66 : +10014e66: b5fe push {r1, r2, r3, r4, r5, r6, r7, lr} +10014e68: 6900 ldr r0, [r0, #16] +10014e6a: 6811 ldr r1, [r2, #0] +10014e6c: 6805 ldr r5, [r0, #0] +10014e6e: f505 5788 add.w r7, r5, #4352 ; 0x1100 +10014e72: b28c uxth r4, r1 +10014e74: 020e lsls r6, r1, #8 +10014e76: 3728 adds r7, #40 ; 0x28 +10014e78: 0e36 lsrs r6, r6, #24 +10014e7a: 6852 ldr r2, [r2, #4] +10014e7c: 9201 str r2, [sp, #4] +10014e7e: 0e09 lsrs r1, r1, #24 +10014e80: 2970 cmp r1, #112 ; 0x70 +10014e82: f105 007c add.w r0, r5, #124 ; 0x7c +10014e86: d013 beq.n 10014eb0 +10014e88: 2971 cmp r1, #113 ; 0x71 +10014e8a: d033 beq.n 10014ef4 +10014e8c: 2972 cmp r1, #114 ; 0x72 +10014e8e: d061 beq.n 10014f54 +10014e90: 2973 cmp r1, #115 ; 0x73 +10014e92: d066 beq.n 10014f62 +10014e94: 2974 cmp r1, #116 ; 0x74 +10014e96: d074 beq.n 10014f82 +10014e98: 2975 cmp r1, #117 ; 0x75 +10014e9a: d07a beq.n 10014f92 +10014e9c: 2976 cmp r1, #118 ; 0x76 +10014e9e: f000 808a beq.w 10014fb6 +10014ea2: 2979 cmp r1, #121 ; 0x79 +10014ea4: f000 809b beq.w 10014fde +10014ea8: 297f cmp r1, #127 ; 0x7f +10014eaa: f000 80a5 beq.w 10014ff8 +10014eae: e14f b.n 10015150 +10014eb0: 2e01 cmp r6, #1 +10014eb2: d004 beq.n 10014ebe +10014eb4: 2e02 cmp r6, #2 +10014eb6: d00b beq.n 10014ed0 +10014eb8: 2e04 cmp r6, #4 +10014eba: d012 beq.n 10014ee2 +10014ebc: e148 b.n 10015150 +10014ebe: 4621 mov r1, r4 +10014ec0: 4628 mov r0, r5 +10014ec2: f00f feb3 bl 10024c2c +10014ec6: 4602 mov r2, r0 +10014ec8: 4621 mov r1, r4 +10014eca: f20f 2088 addw r0, pc, #648 ; 0x288 +10014ece: e055 b.n 10014f7c +10014ed0: 4621 mov r1, r4 +10014ed2: 4628 mov r0, r5 +10014ed4: f00f feb0 bl 10024c38 +10014ed8: 4602 mov r2, r0 +10014eda: 4621 mov r1, r4 +10014edc: f20f 208c addw r0, pc, #652 ; 0x28c +10014ee0: e04c b.n 10014f7c +10014ee2: 4621 mov r1, r4 +10014ee4: 4628 mov r0, r5 +10014ee6: f00f fead bl 10024c44 +10014eea: 4602 mov r2, r0 +10014eec: 4621 mov r1, r4 +10014eee: f20f 2098 addw r0, pc, #664 ; 0x298 +10014ef2: e043 b.n 10014f7c +10014ef4: 2e01 cmp r6, #1 +10014ef6: d004 beq.n 10014f02 +10014ef8: 2e02 cmp r6, #2 +10014efa: d010 beq.n 10014f1e +10014efc: 2e04 cmp r6, #4 +10014efe: d01c beq.n 10014f3a +10014f00: e126 b.n 10015150 +10014f02: b2d2 uxtb r2, r2 +10014f04: 4621 mov r1, r4 +10014f06: 4628 mov r0, r5 +10014f08: f00f fea2 bl 10024c50 +10014f0c: 4621 mov r1, r4 +10014f0e: 4628 mov r0, r5 +10014f10: f00f fe8c bl 10024c2c +10014f14: 4602 mov r2, r0 +10014f16: 4621 mov r1, r4 +10014f18: f20f 2088 addw r0, pc, #648 ; 0x288 +10014f1c: e02e b.n 10014f7c +10014f1e: b292 uxth r2, r2 +10014f20: 4621 mov r1, r4 +10014f22: 4628 mov r0, r5 +10014f24: f00f fe9c bl 10024c60 +10014f28: 4621 mov r1, r4 +10014f2a: 4628 mov r0, r5 +10014f2c: f00f fe84 bl 10024c38 +10014f30: 4602 mov r2, r0 +10014f32: 4621 mov r1, r4 +10014f34: f20f 2088 addw r0, pc, #648 ; 0x288 +10014f38: e020 b.n 10014f7c +10014f3a: 4621 mov r1, r4 +10014f3c: 4628 mov r0, r5 +10014f3e: f00f fe97 bl 10024c70 +10014f42: 4621 mov r1, r4 +10014f44: 4628 mov r0, r5 +10014f46: f00f fe7d bl 10024c44 +10014f4a: 4602 mov r2, r0 +10014f4c: 4621 mov r1, r4 +10014f4e: f20f 208c addw r0, pc, #652 ; 0x28c +10014f52: e013 b.n 10014f7c +10014f54: f000 fa58 bl 10015408 <.text_88> +10014f58: 4602 mov r2, r0 +10014f5a: 4621 mov r1, r4 +10014f5c: f20f 2098 addw r0, pc, #664 ; 0x298 +10014f60: e00c b.n 10014f7c +10014f62: 4613 mov r3, r2 +10014f64: f04f 32ff mov.w r2, #4294967295 +10014f68: 4621 mov r1, r4 +10014f6a: 4628 mov r0, r5 +10014f6c: f002 faae bl 100174cc +10014f70: f000 fa4a bl 10015408 <.text_88> +10014f74: 4602 mov r2, r0 +10014f76: 4621 mov r1, r4 +10014f78: f20f 2094 addw r0, pc, #660 ; 0x294 +10014f7c: f7f7 f9c1 bl 1000c302 +10014f80: e0e6 b.n 10015150 +10014f82: f000 fa47 bl 10015414 <.text_89> +10014f86: 4603 mov r3, r0 +10014f88: 4622 mov r2, r4 +10014f8a: 4631 mov r1, r6 +10014f8c: f20f 2098 addw r0, pc, #664 ; 0x298 +10014f90: e00e b.n 10014fb0 +10014f92: 9200 str r2, [sp, #0] +10014f94: f04f 33ff mov.w r3, #4294967295 +10014f98: 4622 mov r2, r4 +10014f9a: 4631 mov r1, r6 +10014f9c: 4628 mov r0, r5 +10014f9e: f002 faa8 bl 100174f2 +10014fa2: f000 fa37 bl 10015414 <.text_89> +10014fa6: 4603 mov r3, r0 +10014fa8: 4622 mov r2, r4 +10014faa: 4631 mov r1, r6 +10014fac: f20f 20b0 addw r0, pc, #688 ; 0x2b0 +10014fb0: f7f7 f9a7 bl 1000c302 +10014fb4: e0cc b.n 10015150 +10014fb6: b116 cbz r6, 10014fbe +10014fb8: 2e01 cmp r6, #1 +10014fba: d004 beq.n 10014fc6 +10014fbc: e0c8 b.n 10015150 +10014fbe: 2000 movs r0, #0 +10014fc0: f885 0dba strb.w r0, [r5, #3514] ; 0xdba +10014fc4: e0c4 b.n 10015150 +10014fc6: 2001 movs r0, #1 +10014fc8: f885 0dba strb.w r0, [r5, #3514] ; 0xdba +10014fcc: 9801 ldr r0, [sp, #4] +10014fce: 2865 cmp r0, #101 ; 0x65 +10014fd0: bf24 itt cs +10014fd2: 2064 movcs r0, #100 ; 0x64 +10014fd4: 9001 strcs r0, [sp, #4] +10014fd6: 9801 ldr r0, [sp, #4] +10014fd8: f885 0dbb strb.w r0, [r5, #3515] ; 0xdbb +10014fdc: e0b8 b.n 10015150 +10014fde: f002 000f and.w r0, r2, #15 +10014fe2: b10e cbz r6, 10014fe8 +10014fe4: f040 0010 orr.w r0, r0, #16 +10014fe8: ea40 1240 orr.w r2, r0, r0, lsl #5 +10014fec: f240 61d9 movw r1, #1753 ; 0x6d9 +10014ff0: 4628 mov r0, r5 +10014ff2: f00f fe35 bl 10024c60 +10014ff6: e0ab b.n 10015150 +10014ff8: 2e05 cmp r6, #5 +10014ffa: f641 5146 movw r1, #7494 ; 0x1d46 +10014ffe: d011 beq.n 10015024 +10015000: 2e06 cmp r6, #6 +10015002: d015 beq.n 10015030 +10015004: 2e09 cmp r6, #9 +10015006: d021 beq.n 1001504c +10015008: 2e0c cmp r6, #12 +1001500a: d03b beq.n 10015084 +1001500c: 2e11 cmp r6, #17 +1001500e: d045 beq.n 1001509c +10015010: 2eaa cmp r6, #170 ; 0xaa +10015012: d045 beq.n 100150a0 +10015014: 2edd cmp r6, #221 ; 0xdd +10015016: d04b beq.n 100150b0 +10015018: 2eee cmp r6, #238 ; 0xee +1001501a: d05a beq.n 100150d2 +1001501c: 2efd cmp r6, #253 ; 0xfd +1001501e: f000 808b beq.w 10015138 +10015022: e095 b.n 10015150 +10015024: f100 0120 add.w r1, r0, #32 +10015028: 4638 mov r0, r7 +1001502a: f010 f8bf bl 100251ac +1001502e: e08f b.n 10015150 +10015030: aa00 add r2, sp, #0 +10015032: 2117 movs r1, #23 +10015034: 4628 mov r0, r5 +10015036: f002 f975 bl 10017324 +1001503a: f004 000f and.w r0, r4, #15 +1001503e: 9000 str r0, [sp, #0] +10015040: aa00 add r2, sp, #0 +10015042: 2117 movs r1, #23 +10015044: 4628 mov r0, r5 +10015046: f002 f963 bl 10017310 +1001504a: e081 b.n 10015150 +1001504c: a902 add r1, sp, #8 +1001504e: f107 0018 add.w r0, r7, #24 +10015052: f7fb fc5f bl 10010914 +10015056: 2400 movs r4, #0 +10015058: eb07 00c4 add.w r0, r7, r4, lsl #3 +1001505c: f100 051c add.w r5, r0, #28 +10015060: 682e ldr r6, [r5, #0] +10015062: e000 b.n 10015066 +10015064: 6836 ldr r6, [r6, #0] +10015066: 4631 mov r1, r6 +10015068: 4628 mov r0, r5 +1001506a: f7fb fc6e bl 1001094a +1001506e: 2800 cmp r0, #0 +10015070: d0f8 beq.n 10015064 +10015072: 1c64 adds r4, r4, #1 +10015074: 2c08 cmp r4, #8 +10015076: dbef blt.n 10015058 +10015078: a902 add r1, sp, #8 +1001507a: f107 0018 add.w r0, r7, #24 +1001507e: f7fb fc4a bl 10010916 +10015082: e065 b.n 10015150 +10015084: b914 cbnz r4, 1001508c +10015086: aa01 add r2, sp, #4 +10015088: 2106 movs r1, #6 +1001508a: e003 b.n 10015094 +1001508c: 2c01 cmp r4, #1 +1001508e: d15f bne.n 10015150 +10015090: aa01 add r2, sp, #4 +10015092: 210d movs r1, #13 +10015094: 4628 mov r0, r5 +10015096: f002 f94f bl 10017338 +1001509a: e059 b.n 10015150 +1001509c: 554a strb r2, [r1, r5] +1001509e: e057 b.n 10015150 +100150a0: 2a14 cmp r2, #20 +100150a2: bf24 itt cs +100150a4: 20ff movcs r0, #255 ; 0xff +100150a6: 9001 strcs r0, [sp, #4] +100150a8: 9801 ldr r0, [sp, #4] +100150aa: 1949 adds r1, r1, r5 +100150ac: 7788 strb r0, [r1, #30] +100150ae: e04f b.n 10015150 +100150b0: b91a cbnz r2, 100150ba +100150b2: 4628 mov r0, r5 +100150b4: f7ff fdc8 bl 10014c48 +100150b8: e04a b.n 10015150 +100150ba: 2a01 cmp r2, #1 +100150bc: d103 bne.n 100150c6 +100150be: 4628 mov r0, r5 +100150c0: f7ff fe18 bl 10014cf4 +100150c4: e044 b.n 10015150 +100150c6: 2a02 cmp r2, #2 +100150c8: d142 bne.n 10015150 +100150ca: 4628 mov r0, r5 +100150cc: f7ff fe52 bl 10014d74 +100150d0: e03e b.n 10015150 +100150d2: 2a0f cmp r2, #15 +100150d4: f20f 14c0 addw r4, pc, #448 ; 0x1c0 +100150d8: d122 bne.n 10015120 +100150da: f000 f9a2 bl 10015422 <.text_90> +100150de: 9900 ldr r1, [sp, #0] +100150e0: 4620 mov r0, r4 +100150e2: f7f7 f90e bl 1000c302 +100150e6: f20f 10cc addw r0, pc, #460 ; 0x1cc +100150ea: f7f7 f90a bl 1000c302 +100150ee: f20f 10f0 addw r0, pc, #496 ; 0x1f0 +100150f2: f7f7 f906 bl 1000c302 +100150f6: f20f 2010 addw r0, pc, #528 ; 0x210 +100150fa: f7f7 f902 bl 1000c302 +100150fe: f20f 2038 addw r0, pc, #568 ; 0x238 +10015102: f7f7 f8fe bl 1000c302 +10015106: f20f 2068 addw r0, pc, #616 ; 0x268 +1001510a: f7f7 f8fa bl 1000c302 +1001510e: f20f 2094 addw r0, pc, #660 ; 0x294 +10015112: f7f7 f8f6 bl 1000c302 +10015116: f20f 20c4 addw r0, pc, #708 ; 0x2c4 +1001511a: f7f7 f8f2 bl 1000c302 +1001511e: e017 b.n 10015150 +10015120: aa01 add r2, sp, #4 +10015122: 2107 movs r1, #7 +10015124: 4628 mov r0, r5 +10015126: f002 f907 bl 10017338 +1001512a: f000 f97a bl 10015422 <.text_90> +1001512e: 9900 ldr r1, [sp, #0] +10015130: 4620 mov r0, r4 +10015132: f7f7 f8e6 bl 1000c302 +10015136: e00b b.n 10015150 +10015138: b2e2 uxtb r2, r4 +1001513a: f44f 6145 mov.w r1, #3152 ; 0xc50 +1001513e: 4628 mov r0, r5 +10015140: f00f fd86 bl 10024c50 +10015144: b2e2 uxtb r2, r4 +10015146: f640 4158 movw r1, #3160 ; 0xc58 +1001514a: 4628 mov r0, r5 +1001514c: f00f fd80 bl 10024c50 +10015150: 2000 movs r0, #0 +10015152: bdfe pop {r1, r2, r3, r4, r5, r6, r7, pc} + +10015154 : +10015154: 7472 5f77 6572 6461 2838 7830 7825 3d29 rtw_read8(0x%x)= +10015164: 7830 3025 7832 000a 0x%02x.. + +1001516c : +1001516c: 7472 5f77 6572 6461 3631 3028 2578 2978 rtw_read16(0x%x) +1001517c: 303d 2578 3430 0a78 0000 0000 =0x%04x..... + +10015188 : +10015188: 7472 5f77 6572 6461 3233 3028 2578 2978 rtw_read32(0x%x) +10015198: 303d 2578 3830 0a78 0000 0000 =0x%08x..... + +100151a4 : +100151a4: 7472 5f77 7277 7469 3865 3028 2578 2978 rtw_write8(0x%x) +100151b4: 303d 2578 3230 0a78 0000 0000 =0x%02x..... + +100151c0 : +100151c0: 7472 5f77 7277 7469 3165 2836 7830 7825 rtw_write16(0x%x +100151d0: 3d29 7830 3025 7834 000a 0000 )=0x%04x.... + +100151dc : +100151dc: 7472 5f77 7277 7469 3365 2832 7830 7825 rtw_write32(0x%x +100151ec: 3d29 7830 3025 7838 000a 0000 )=0x%08x.... + +100151f8 : +100151f8: 6572 6461 625f 7262 6765 3028 2578 2978 read_bbreg(0x%x) +10015208: 303d 2578 0a78 0000 =0x%x... + +10015210 : +10015210: 7277 7469 5f65 6262 6572 2867 7830 7825 write_bbreg(0x%x +10015220: 3d29 7830 7825 000a )=0x%x.. + +10015228 : +10015228: 6572 6461 5220 5f46 6572 2067 6170 6874 read RF_reg path +10015238: 3028 2578 3230 2978 6f2c 6666 6573 2874 (0x%02x),offset( +10015248: 7830 7825 2c29 6176 756c 2865 7830 3025 0x%x),value(0x%0 +10015258: 7838 0a29 0000 0000 8x)..... + +10015260 : +10015260: 7277 7469 2065 4652 725f 6765 7020 7461 write RF_reg pat +10015270: 2868 7830 3025 7832 2c29 666f 7366 7465 h(0x%02x),offset +10015280: 3028 2578 2978 762c 6c61 6575 3028 2578 (0x%x),value(0x% +10015290: 3830 2978 000a 0000 08x).... + +10015298 : +10015298: 3d20 3d3d 4420 464d 616c 2867 7830 3025 === DMFlag(0x%0 +100152a8: 7838 2029 3d3d 203d 000a 0000 8x) === .... + +100152b4 : +100152b4: 7865 7274 5f61 7261 2067 203d 2030 2d20 extra_arg = 0 - +100152c4: 6420 7369 6261 656c 6120 6c6c 6420 6e79 disable all dyn +100152d4: 6d61 6369 6620 6e75 2063 000a amic func .. + +100152e0 : +100152e0: 7865 7274 5f61 7261 2067 203d 2031 2d20 extra_arg = 1 - +100152f0: 6420 7369 6261 656c 4420 4749 202d 4942 disable DIG- BI +10015300: 2854 2930 000a 0000 T(0).... + +10015308 : +10015308: 7865 7274 5f61 7261 2067 203d 2032 2d20 extra_arg = 2 - +10015318: 6420 7369 6261 656c 4820 6769 2068 6f70 disable High po +10015328: 6577 2072 202d 4942 2854 2931 000a 0000 wer - BIT(1).... + +10015338 : +10015338: 7865 7274 5f61 7261 2067 203d 2033 2d20 extra_arg = 3 - +10015348: 6420 7369 6261 656c 7420 2078 6f70 6577 disable tx powe +10015358: 2072 7274 6361 696b 676e 2d20 4220 5449 r tracking - BIT +10015368: 3228 0a29 0000 0000 (2)..... + +10015370 : +10015370: 7865 7274 5f61 7261 2067 203d 2034 2d20 extra_arg = 4 - +10015380: 6420 7369 6261 656c 4220 2054 6f63 7865 disable BT coex +10015390: 7369 6574 636e 2065 202d 4942 2854 2933 istence - BIT(3) +100153a0: 000a 0000 .... + +100153a4 : +100153a4: 7865 7274 5f61 7261 2067 203d 2035 2d20 extra_arg = 5 - +100153b4: 6420 7369 6261 656c 6120 746e 6e65 616e disable antenna +100153c4: 6420 7669 7265 6973 7974 2d20 4220 5449 diversity - BIT +100153d4: 3428 0a29 0000 0000 (4)..... + +100153dc : +100153dc: 7865 7274 5f61 7261 2067 203d 2036 2d20 extra_arg = 6 - +100153ec: 6520 616e 6c62 2065 6c61 206c 7964 616e enable all dyna +100153fc: 696d 2063 7566 636e 0a20 0000 mic func ... + +10015408 <.text_88>: +10015408: f04f 32ff mov.w r2, #4294967295 +1001540c: 4621 mov r1, r4 +1001540e: 4628 mov r0, r5 +10015410: f002 b851 b.w 100174b6 + +10015414 <.text_89>: +10015414: f04f 33ff mov.w r3, #4294967295 +10015418: 4622 mov r2, r4 +1001541a: 4631 mov r1, r6 +1001541c: 4628 mov r0, r5 +1001541e: f002 b85d b.w 100174dc + +10015422 <.text_90>: +10015422: aa00 add r2, sp, #0 +10015424: 2107 movs r1, #7 +10015426: 4628 mov r0, r5 +10015428: f001 bf91 b.w 1001734e + +1001542c : +1001542c: b5f0 push {r4, r5, r6, r7, lr} +1001542e: b083 sub sp, #12 +10015430: 6900 ldr r0, [r0, #16] +10015432: 6805 ldr r5, [r0, #0] +10015434: 461c mov r4, r3 +10015436: f000 fba0 bl 10015b7a <.text_107+0x2> +1001543a: 280c cmp r0, #12 +1001543c: bf18 it ne +1001543e: f60f 30d4 addwne r0, pc, #3028 ; 0xbd4 +10015442: d116 bne.n 10015472 +10015444: 2600 movs r6, #0 +10015446: 2700 movs r7, #0 +10015448: 1938 adds r0, r7, r4 +1001544a: 7841 ldrb r1, [r0, #1] +1001544c: 5d38 ldrb r0, [r7, r4] +1001544e: f7fe fd1b bl 10013e88 +10015452: a900 add r1, sp, #0 +10015454: 1cbf adds r7, r7, #2 +10015456: 5470 strb r0, [r6, r1] +10015458: 1c76 adds r6, r6, #1 +1001545a: 2e06 cmp r6, #6 +1001545c: d3f4 bcc.n 10015448 +1001545e: ab00 add r3, sp, #0 +10015460: 2206 movs r2, #6 +10015462: f44f 718d mov.w r1, #282 ; 0x11a +10015466: 4628 mov r0, r5 +10015468: f010 f979 bl 1002575e +1001546c: b930 cbnz r0, 1001547c +1001546e: f60f 30c0 addw r0, pc, #3008 ; 0xbc0 +10015472: f7f6 ff46 bl 1000c302 +10015476: f04f 30ff mov.w r0, #4294967295 +1001547a: bdfe pop {r1, r2, r3, r4, r5, r6, r7, pc} +1001547c: f505 50c8 add.w r0, r5, #6400 ; 0x1900 +10015480: 2206 movs r2, #6 +10015482: a900 add r1, sp, #0 +10015484: 3095 adds r0, #149 ; 0x95 +10015486: f7f6 ff5f bl 1000c348 +1001548a: f60f 30c8 addw r0, pc, #3016 ; 0xbc8 +1001548e: f7f6 ff38 bl 1000c302 +10015492: 2000 movs r0, #0 +10015494: bdfe pop {r1, r2, r3, r4, r5, r6, r7, pc} + +10015496 : +10015496: e92d 41fc stmdb sp!, {r2, r3, r4, r5, r6, r7, r8, lr} +1001549a: 6900 ldr r0, [r0, #16] +1001549c: 6800 ldr r0, [r0, #0] +1001549e: 4615 mov r5, r2 +100154a0: f500 5788 add.w r7, r0, #4352 ; 0x1100 +100154a4: 682e ldr r6, [r5, #0] +100154a6: 2400 movs r4, #0 +100154a8: 3728 adds r7, #40 ; 0x28 +100154aa: 2110 movs r1, #16 +100154ac: 300c adds r0, #12 +100154ae: f7fe fcef bl 10013e90 +100154b2: 2801 cmp r0, #1 +100154b4: d106 bne.n 100154c4 +100154b6: aa00 add r2, sp, #0 +100154b8: a19f add r1, pc, #636 ; (adr r1, 10015738 <.text_96>) +100154ba: 4630 mov r0, r6 +100154bc: f00f fba4 bl 10024c08 +100154c0: 9800 ldr r0, [sp, #0] +100154c2: b910 cbnz r0, 100154ca +100154c4: f04f 30ff mov.w r0, #4294967295 +100154c8: e02d b.n 10015526 +100154ca: f107 088c add.w r8, r7, #140 ; 0x8c +100154ce: a901 add r1, sp, #4 +100154d0: 4640 mov r0, r8 +100154d2: f7fb fa1f bl 10010914 +100154d6: f857 6f7c ldr.w r6, [r7, #124]! +100154da: e000 b.n 100154de +100154dc: 6836 ldr r6, [r6, #0] +100154de: 4631 mov r1, r6 +100154e0: 4638 mov r0, r7 +100154e2: f7fb fa32 bl 1001094a +100154e6: b988 cbnz r0, 1001550c +100154e8: f506 7007 add.w r0, r6, #540 ; 0x21c +100154ec: 1b80 subs r0, r0, r6 +100154ee: 1a30 subs r0, r6, r0 +100154f0: f500 7184 add.w r1, r0, #264 ; 0x108 +100154f4: 9800 ldr r0, [sp, #0] +100154f6: 2206 movs r2, #6 +100154f8: fb02 0004 mla r0, r2, r4, r0 +100154fc: 1d00 adds r0, r0, #4 +100154fe: f7fb f986 bl 1001080e +10015502: 9800 ldr r0, [sp, #0] +10015504: 6800 ldr r0, [r0, #0] +10015506: 1c64 adds r4, r4, #1 +10015508: 4284 cmp r4, r0 +1001550a: d3e7 bcc.n 100154dc +1001550c: a901 add r1, sp, #4 +1001550e: 4640 mov r0, r8 +10015510: f7fb fa01 bl 10010916 +10015514: 9800 ldr r0, [sp, #0] +10015516: 6800 ldr r0, [r0, #0] +10015518: 9900 ldr r1, [sp, #0] +1001551a: 4284 cmp r4, r0 +1001551c: bf38 it cc +1001551e: 4620 movcc r0, r4 +10015520: 6008 str r0, [r1, #0] +10015522: 2000 movs r0, #0 +10015524: 80a8 strh r0, [r5, #4] +10015526: e8bd 81f6 ldmia.w sp!, {r1, r2, r4, r5, r6, r7, r8, pc} + +1001552a : +1001552a: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +1001552e: 6900 ldr r0, [r0, #16] +10015530: 6807 ldr r7, [r0, #0] +10015532: 4614 mov r4, r2 +10015534: f107 090c add.w r9, r7, #12 +10015538: f109 068c add.w r6, r9, #140 ; 0x8c +1001553c: 6825 ldr r5, [r4, #0] +1001553e: f106 087c add.w r8, r6, #124 ; 0x7c +10015542: 2110 movs r1, #16 +10015544: 4648 mov r0, r9 +10015546: f7fe fca3 bl 10013e90 +1001554a: 2801 cmp r0, #1 +1001554c: bf04 itt eq +1001554e: 6e30 ldreq r0, [r6, #96] ; 0x60 +10015550: 2804 cmpeq r0, #4 +10015552: d106 bne.n 10015562 +10015554: aa00 add r2, sp, #0 +10015556: a178 add r1, pc, #480 ; (adr r1, 10015738 <.text_96>) +10015558: 4628 mov r0, r5 +1001555a: f00f fb55 bl 10024c08 +1001555e: 9800 ldr r0, [sp, #0] +10015560: b910 cbnz r0, 10015568 +10015562: f04f 30ff mov.w r0, #4294967295 +10015566: e049 b.n 100155fc +10015568: 9900 ldr r1, [sp, #0] +1001556a: 2064 movs r0, #100 ; 0x64 +1001556c: 6008 str r0, [r1, #0] +1001556e: 2000 movs r0, #0 +10015570: 9900 ldr r1, [sp, #0] +10015572: 6048 str r0, [r1, #4] +10015574: f507 51c8 add.w r1, r7, #6400 ; 0x1900 +10015578: 9800 ldr r0, [sp, #0] +1001557a: 2206 movs r2, #6 +1001557c: 3195 adds r1, #149 ; 0x95 +1001557e: 3008 adds r0, #8 +10015580: f7fb f945 bl 1001080e +10015584: 9900 ldr r1, [sp, #0] +10015586: 6c70 ldr r0, [r6, #68] ; 0x44 +10015588: 81c8 strh r0, [r1, #14] +1001558a: 4640 mov r0, r8 +1001558c: f009 f9a2 bl 1001e8d4 +10015590: 9900 ldr r1, [sp, #0] +10015592: 8800 ldrh r0, [r0, #0] +10015594: 8208 strh r0, [r1, #16] +10015596: 9900 ldr r1, [sp, #0] +10015598: 6cb0 ldr r0, [r6, #72] ; 0x48 +1001559a: 8688 strh r0, [r1, #52] ; 0x34 +1001559c: f106 0110 add.w r1, r6, #16 +100155a0: 9800 ldr r0, [sp, #0] +100155a2: 68f2 ldr r2, [r6, #12] +100155a4: 3013 adds r0, #19 +100155a6: f7fb f932 bl 1001080e +100155aa: 9900 ldr r1, [sp, #0] +100155ac: 68f0 ldr r0, [r6, #12] +100155ae: 7488 strb r0, [r1, #18] +100155b0: 9900 ldr r1, [sp, #0] +100155b2: 6cf0 ldr r0, [r6, #76] ; 0x4c +100155b4: f881 0033 strb.w r0, [r1, #51] ; 0x33 +100155b8: 9900 ldr r1, [sp, #0] +100155ba: 6bb0 ldr r0, [r6, #56] ; 0x38 +100155bc: 8708 strh r0, [r1, #56] ; 0x38 +100155be: 9800 ldr r0, [sp, #0] +100155c0: f8b9 1456 ldrh.w r1, [r9, #1110] ; 0x456 +100155c4: 3038 adds r0, #56 ; 0x38 +100155c6: b169 cbz r1, 100155e4 +100155c8: 2101 movs r1, #1 +100155ca: 7081 strb r1, [r0, #2] +100155cc: 2210 movs r2, #16 +100155ce: 9900 ldr r1, [sp, #0] +100155d0: f8b9 0456 ldrh.w r0, [r9, #1110] ; 0x456 +100155d4: 63c8 str r0, [r1, #60] ; 0x3c +100155d6: f209 4159 addw r1, r9, #1113 ; 0x459 +100155da: 9800 ldr r0, [sp, #0] +100155dc: 3040 adds r0, #64 ; 0x40 +100155de: f7fb f916 bl 1001080e +100155e2: e009 b.n 100155f8 +100155e4: 7081 strb r1, [r0, #2] +100155e6: 2000 movs r0, #0 +100155e8: 9900 ldr r1, [sp, #0] +100155ea: 63c8 str r0, [r1, #60] ; 0x3c +100155ec: 2210 movs r2, #16 +100155ee: 9800 ldr r0, [sp, #0] +100155f0: 2100 movs r1, #0 +100155f2: 3040 adds r0, #64 ; 0x40 +100155f4: f7fb f920 bl 10010838 +100155f8: 2000 movs r0, #0 +100155fa: 80a0 strh r0, [r4, #4] +100155fc: e8bd 83f2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, pc} + +10015600 : +10015600: b538 push {r3, r4, r5, lr} +10015602: 6905 ldr r5, [r0, #16] +10015604: 88d4 ldrh r4, [r2, #6] +10015606: 682d ldr r5, [r5, #0] +10015608: b915 cbnz r5, 10015610 +1001560a: f06f 0063 mvn.w r0, #99 ; 0x63 +1001560e: bd32 pop {r1, r4, r5, pc} +10015610: b923 cbnz r3, 1001561c +10015612: 2000 movs r0, #0 +10015614: 8090 strh r0, [r2, #4] +10015616: f06f 0004 mvn.w r0, #4 +1001561a: bd32 pop {r1, r4, r5, pc} +1001561c: b90c cbnz r4, 10015622 +1001561e: f7ff ff05 bl 1001542c +10015622: 2000 movs r0, #0 +10015624: bd32 pop {r1, r4, r5, pc} + +10015626 : +10015626: e92d 41ff stmdb sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, lr} +1001562a: 461d mov r5, r3 +1001562c: 6903 ldr r3, [r0, #16] +1001562e: 681e ldr r6, [r3, #0] +10015630: 4614 mov r4, r2 +10015632: 88e2 ldrh r2, [r4, #6] +10015634: b916 cbnz r6, 1001563c +10015636: f06f 0063 mvn.w r0, #99 ; 0x63 +1001563a: e079 b.n 10015730 +1001563c: b925 cbnz r5, 10015648 +1001563e: 2000 movs r0, #0 +10015640: 80a0 strh r0, [r4, #4] +10015642: f06f 0004 mvn.w r0, #4 +10015646: e073 b.n 10015730 +10015648: 2a01 cmp r2, #1 +1001564a: d031 beq.n 100156b0 +1001564c: d36c bcc.n 10015728 +1001564e: 2a03 cmp r2, #3 +10015650: d042 beq.n 100156d8 +10015652: d303 bcc.n 1001565c +10015654: 2a05 cmp r2, #5 +10015656: d049 beq.n 100156ec +10015658: d343 bcc.n 100156e2 +1001565a: e065 b.n 10015728 +1001565c: 2000 movs r0, #0 +1001565e: 9001 str r0, [sp, #4] +10015660: 9000 str r0, [sp, #0] +10015662: 88a6 ldrh r6, [r4, #4] +10015664: 4630 mov r0, r6 +10015666: f7fb f8c7 bl 100107f8 +1001566a: 0007 movs r7, r0 +1001566c: d05c beq.n 10015728 +1001566e: 88a2 ldrh r2, [r4, #4] +10015670: 6821 ldr r1, [r4, #0] +10015672: f7fb f8cc bl 1001080e +10015676: f60f 115c addw r1, pc, #2396 ; 0x95c +1001567a: ab00 add r3, sp, #0 +1001567c: aa01 add r2, sp, #4 +1001567e: 4638 mov r0, r7 +10015680: f00f fac2 bl 10024c08 +10015684: f110 0f01 cmn.w r0, #1 +10015688: d104 bne.n 10015694 +1001568a: 2322 movs r3, #34 ; 0x22 +1001568c: 220c movs r2, #12 +1001568e: f60f 1158 addw r1, pc, #2392 ; 0x958 +10015692: e003 b.n 1001569c +10015694: 9b00 ldr r3, [sp, #0] +10015696: 9a01 ldr r2, [sp, #4] +10015698: f60f 1154 addw r1, pc, #2388 ; 0x954 +1001569c: 4628 mov r0, r5 +1001569e: f7f6 fe05 bl 1000c2ac +100156a2: f000 f84d bl 10015740 <.text_98> +100156a6: 1c40 adds r0, r0, #1 +100156a8: 80a0 strh r0, [r4, #4] +100156aa: f7fe fc29 bl 10013f00 <.text_6> +100156ae: e03b b.n 10015728 +100156b0: f641 1095 movw r0, #6549 ; 0x1995 +100156b4: 1981 adds r1, r0, r6 +100156b6: 794a ldrb r2, [r1, #5] +100156b8: 9203 str r2, [sp, #12] +100156ba: 790a ldrb r2, [r1, #4] +100156bc: 9202 str r2, [sp, #8] +100156be: 78ca ldrb r2, [r1, #3] +100156c0: 9201 str r2, [sp, #4] +100156c2: 788a ldrb r2, [r1, #2] +100156c4: 9200 str r2, [sp, #0] +100156c6: 784b ldrb r3, [r1, #1] +100156c8: 5d82 ldrb r2, [r0, r6] +100156ca: f60f 11c4 addw r1, pc, #2500 ; 0x9c4 +100156ce: 4628 mov r0, r5 +100156d0: f7f6 fdec bl 1000c2ac +100156d4: 2012 movs r0, #18 +100156d6: e026 b.n 10015726 +100156d8: 462b mov r3, r5 +100156da: 4622 mov r2, r4 +100156dc: f7ff fedb bl 10015496 +100156e0: e022 b.n 10015728 +100156e2: 462b mov r3, r5 +100156e4: 4622 mov r2, r4 +100156e6: f7ff ff20 bl 1001552a +100156ea: e01d b.n 10015728 +100156ec: f106 080c add.w r8, r6, #12 +100156f0: f506 5688 add.w r6, r6, #4352 ; 0x1100 +100156f4: 36f0 adds r6, #240 ; 0xf0 +100156f6: 2700 movs r7, #0 +100156f8: 2110 movs r1, #16 +100156fa: 4640 mov r0, r8 +100156fc: f7fe fbc8 bl 10013e90 +10015700: 2801 cmp r0, #1 +10015702: bf04 itt eq +10015704: f8d8 00ec ldreq.w r0, [r8, #236] ; 0xec +10015708: 2804 cmpeq r0, #4 +1001570a: d10d bne.n 10015728 +1001570c: f8d6 0364 ldr.w r0, [r6, #868] ; 0x364 +10015710: 2807 cmp r0, #7 +10015712: bf08 it eq +10015714: f8df 786c ldreq.w r7, [pc, #2156] ; 10015f84 <.text_113> +10015718: 463a mov r2, r7 +1001571a: a108 add r1, pc, #32 ; (adr r1, 1001573c <.text_97>) +1001571c: 4628 mov r0, r5 +1001571e: f7f6 fdc5 bl 1000c2ac +10015722: f000 f80d bl 10015740 <.text_98> +10015726: 80a0 strh r0, [r4, #4] +10015728: 200a movs r0, #10 +1001572a: f7fb f960 bl 100109ee +1001572e: 2000 movs r0, #0 +10015730: b004 add sp, #16 +10015732: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + ... + +10015738 <.text_96>: +10015738: 00007825 .word 0x00007825 + +1001573c <.text_97>: +1001573c: 00006425 .word 0x00006425 + +10015740 <.text_98>: +10015740: 4628 mov r0, r5 +10015742: f7f6 be09 b.w 1000c358 + +10015746 : +10015746: 0541 lsls r1, r0, #21 +10015748: f60f 3240 addw r2, pc, #2880 ; 0xb40 +1001574c: f3c0 3002 ubfx r0, r0, #12, #3 +10015750: 0d49 lsrs r1, r1, #21 +10015752: 5680 ldrsb r0, [r0, r2] +10015754: 4348 muls r0, r1 +10015756: 4770 bx lr + +10015758 : +10015758: e92d 4ff3 stmdb sp!, {r0, r1, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1001575c: f60f 1050 addw r0, pc, #2384 ; 0x950 +10015760: 8800 ldrh r0, [r0, #0] +10015762: b099 sub sp, #100 ; 0x64 +10015764: 2400 movs r4, #0 +10015766: f8ad 0016 strh.w r0, [sp, #22] +1001576a: 940e str r4, [sp, #56] ; 0x38 +1001576c: 2500 movs r5, #0 +1001576e: 46a0 mov r8, r4 +10015770: 940a str r4, [sp, #40] ; 0x28 +10015772: 940d str r4, [sp, #52] ; 0x34 +10015774: 9402 str r4, [sp, #8] +10015776: a814 add r0, sp, #80 ; 0x50 +10015778: 2114 movs r1, #20 +1001577a: f010 f84f bl 1002581c <__aeabi_memclr4> +1001577e: 991a ldr r1, [sp, #104] ; 0x68 +10015780: 9404 str r4, [sp, #16] +10015782: 4626 mov r6, r4 +10015784: 2210 movs r2, #16 +10015786: a806 add r0, sp, #24 +10015788: f7fb f841 bl 1001080e +1001578c: f8bd 001c ldrh.w r0, [sp, #28] +10015790: 9001 str r0, [sp, #4] +10015792: 1c40 adds r0, r0, #1 +10015794: f7fb f835 bl 10010802 +10015798: 9003 str r0, [sp, #12] +1001579a: f06f 0b0b mvn.w fp, #11 +1001579e: b908 cbnz r0, 100157a4 +100157a0: 4658 mov r0, fp +100157a2: e06b b.n 1001587c +100157a4: 9a01 ldr r2, [sp, #4] +100157a6: 9906 ldr r1, [sp, #24] +100157a8: f7fb f831 bl 1001080e +100157ac: 9803 ldr r0, [sp, #12] +100157ae: f60f 1104 addw r1, pc, #2308 ; 0x904 +100157b2: 9002 str r0, [sp, #8] +100157b4: aa14 add r2, sp, #80 ; 0x50 +100157b6: 9f01 ldr r7, [sp, #4] +100157b8: f00f fa26 bl 10024c08 +100157bc: a814 add r0, sp, #80 ; 0x50 +100157be: f7f6 fdcb bl 1000c358 +100157c2: b100 cbz r0, 100157c6 +100157c4: 1c40 adds r0, r0, #1 +100157c6: 9902 ldr r1, [sp, #8] +100157c8: 1841 adds r1, r0, r1 +100157ca: 9102 str r1, [sp, #8] +100157cc: eba7 0900 sub.w r9, r7, r0 +100157d0: f04f 3aff mov.w sl, #4294967295 +100157d4: f10a 0a01 add.w sl, sl, #1 +100157d8: f000 f9c3 bl 10015b62 <.text_105> +100157dc: f1ba 0f13 cmp.w sl, #19 +100157e0: 9000 str r0, [sp, #0] +100157e2: d237 bcs.n 10015854 +100157e4: a914 add r1, sp, #80 ; 0x50 +100157e6: 3008 adds r0, #8 +100157e8: f7f6 fdb2 bl 1000c350 +100157ec: 2800 cmp r0, #0 +100157ee: d1f1 bne.n 100157d4 +100157f0: f000 f9b7 bl 10015b62 <.text_105> +100157f4: f648 11f0 movw r1, #35312 ; 0x89f0 +100157f8: 6800 ldr r0, [r0, #0] +100157fa: 4288 cmp r0, r1 +100157fc: d220 bcs.n 10015840 +100157fe: f04f 30ff mov.w r0, #4294967295 +10015802: 1c40 adds r0, r0, #1 +10015804: 2813 cmp r0, #19 +10015806: d23c bcs.n 10015882 +10015808: f60f 01b8 addw r1, pc, #2232 ; 0x8b8 +1001580c: 2218 movs r2, #24 +1001580e: fb02 1100 mla r1, r2, r0, r1 +10015812: f991 2008 ldrsb.w r2, [r1, #8] +10015816: 2a00 cmp r2, #0 +10015818: bf01 itttt eq +1001581a: 888a ldrheq r2, [r1, #4] +1001581c: 9b00 ldreq r3, [sp, #0] +1001581e: 889b ldrheq r3, [r3, #4] +10015820: 429a cmpeq r2, r3 +10015822: d1ee bne.n 10015802 +10015824: 9a00 ldr r2, [sp, #0] +10015826: 88c9 ldrh r1, [r1, #6] +10015828: 88d2 ldrh r2, [r2, #6] +1001582a: 4291 cmp r1, r2 +1001582c: d1e9 bne.n 10015802 +1001582e: f60f 0194 addw r1, pc, #2196 ; 0x894 +10015832: 2218 movs r2, #24 +10015834: fb02 110a mla r1, r2, sl, r1 +10015838: 4682 mov sl, r0 +1001583a: 680e ldr r6, [r1, #0] +1001583c: 2104 movs r1, #4 +1001583e: 9104 str r1, [sp, #16] +10015840: f44f 6000 mov.w r0, #2048 ; 0x800 +10015844: 900d str r0, [sp, #52] ; 0x34 +10015846: f7fa ffdc bl 10010802 +1001584a: ea5f 0800 movs.w r8, r0 +1001584e: d11c bne.n 1001588a +10015850: 465d mov r5, fp +10015852: e002 b.n 1001585a +10015854: d1cc bne.n 100157f0 +10015856: f06f 055e mvn.w r5, #94 ; 0x5e +1001585a: 9901 ldr r1, [sp, #4] +1001585c: 9803 ldr r0, [sp, #12] +1001585e: f7fa ffd5 bl 1001080c +10015862: f1b8 0f00 cmp.w r8, #0 +10015866: d003 beq.n 10015870 +10015868: 990d ldr r1, [sp, #52] ; 0x34 +1001586a: 4640 mov r0, r8 +1001586c: f7fa ffce bl 1001080c +10015870: b11c cbz r4, 1001587a +10015872: 990e ldr r1, [sp, #56] ; 0x38 +10015874: 4620 mov r0, r4 +10015876: f7fa ffc9 bl 1001080c +1001587a: 4628 mov r0, r5 +1001587c: b01b add sp, #108 ; 0x6c +1001587e: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} +10015882: d1d4 bne.n 1001582e +10015884: f06f 0515 mvn.w r5, #21 +10015888: e7e7 b.n 1001585a +1001588a: f000 f96a bl 10015b62 <.text_105> +1001588e: 9000 str r0, [sp, #0] +10015890: f44f 41e0 mov.w r1, #28672 ; 0x7000 +10015894: 8887 ldrh r7, [r0, #4] +10015896: 9801 ldr r0, [sp, #4] +10015898: 1e40 subs r0, r0, #1 +1001589a: 420f tst r7, r1 +1001589c: 900c str r0, [sp, #48] ; 0x30 +1001589e: d068 beq.n 10015972 +100158a0: 0578 lsls r0, r7, #21 +100158a2: 0d40 lsrs r0, r0, #21 +100158a4: f8ad 0014 strh.w r0, [sp, #20] +100158a8: d063 beq.n 10015972 +100158aa: f407 40e0 and.w r0, r7, #28672 ; 0x7000 +100158ae: f5b0 5f80 cmp.w r0, #4096 ; 0x1000 +100158b2: d016 beq.n 100158e2 +100158b4: f5b0 5f00 cmp.w r0, #8192 ; 0x2000 +100158b8: d039 beq.n 1001592e +100158ba: f5b0 4f80 cmp.w r0, #16384 ; 0x4000 +100158be: d026 beq.n 1001590e +100158c0: f5b0 4fc0 cmp.w r0, #24576 ; 0x6000 +100158c4: d04c beq.n 10015960 +100158c6: 9803 ldr r0, [sp, #12] +100158c8: 2800 cmp r0, #0 +100158ca: f04f 35ff mov.w r5, #4294967295 +100158ce: d0c8 beq.n 10015862 +100158d0: e7c3 b.n 1001585a +100158d2: aa0b add r2, sp, #44 ; 0x2c +100158d4: a199 add r1, pc, #612 ; (adr r1, 10015b3c <.text_101>) +100158d6: f00f f997 bl 10024c08 +100158da: 980b ldr r0, [sp, #44] ; 0x2c +100158dc: f805 0008 strb.w r0, [r5, r8] +100158e0: 1c6d adds r5, r5, #1 +100158e2: f000 f933 bl 10015b4c <.text_103> +100158e6: 2800 cmp r0, #0 +100158e8: d1f3 bne.n 100158d2 +100158ea: f8ad 501c strh.w r5, [sp, #28] +100158ee: 0578 lsls r0, r7, #21 +100158f0: f8bd 101c ldrh.w r1, [sp, #28] +100158f4: 950a str r5, [sp, #40] ; 0x28 +100158f6: 0d40 lsrs r0, r0, #21 +100158f8: 4288 cmp r0, r1 +100158fa: da31 bge.n 10015960 +100158fc: e012 b.n 10015924 +100158fe: aa0b add r2, sp, #44 ; 0x2c +10015900: a18e add r1, pc, #568 ; (adr r1, 10015b3c <.text_101>) +10015902: f00f f981 bl 10024c08 +10015906: 980b ldr r0, [sp, #44] ; 0x2c +10015908: f848 0025 str.w r0, [r8, r5, lsl #2] +1001590c: 1c6d adds r5, r5, #1 +1001590e: f000 f91d bl 10015b4c <.text_103> +10015912: 2800 cmp r0, #0 +10015914: d1f3 bne.n 100158fe +10015916: 00a8 lsls r0, r5, #2 +10015918: 900a str r0, [sp, #40] ; 0x28 +1001591a: f8ad 501c strh.w r5, [sp, #28] +1001591e: f000 f91a bl 10015b56 <.text_104> +10015922: da1d bge.n 10015960 +10015924: f8bd 0014 ldrh.w r0, [sp, #20] +10015928: f8ad 001c strh.w r0, [sp, #28] +1001592c: e018 b.n 10015960 +1001592e: f1b9 0f01 cmp.w r9, #1 +10015932: db0d blt.n 10015950 +10015934: f8ad 901c strh.w r9, [sp, #28] +10015938: f000 f90d bl 10015b56 <.text_104> +1001593c: bfb8 it lt +1001593e: f8ad 001c strhlt.w r0, [sp, #28] +10015942: f8bd 201c ldrh.w r2, [sp, #28] +10015946: 9902 ldr r1, [sp, #8] +10015948: 4640 mov r0, r8 +1001594a: f7fa ff60 bl 1001080e +1001594e: e004 b.n 1001595a +10015950: 2001 movs r0, #1 +10015952: f8ad 001c strh.w r0, [sp, #28] +10015956: f888 4000 strb.w r4, [r8] +1001595a: f8bd 001c ldrh.w r0, [sp, #28] +1001595e: 900a str r0, [sp, #40] ; 0x28 +10015960: 0538 lsls r0, r7, #20 +10015962: d51c bpl.n 1001599e +10015964: f8bd 001c ldrh.w r0, [sp, #28] +10015968: 0579 lsls r1, r7, #21 +1001596a: ebb0 5f51 cmp.w r0, r1, lsr #21 +1001596e: d002 beq.n 10015976 +10015970: e788 b.n 10015884 +10015972: f8ad 401c strh.w r4, [sp, #28] +10015976: 0538 lsls r0, r7, #20 +10015978: d511 bpl.n 1001599e +1001597a: 4638 mov r0, r7 +1001597c: f7ff fee3 bl 10015746 +10015980: 9904 ldr r1, [sp, #16] +10015982: 1808 adds r0, r1, r0 +10015984: 2811 cmp r0, #17 +10015986: da0a bge.n 1001599e +10015988: b101 cbz r1, 1001598c +1001598a: 9606 str r6, [sp, #24] +1001598c: 9b04 ldr r3, [sp, #16] +1001598e: f1c1 0210 rsb r2, r1, #16 +10015992: a806 add r0, sp, #24 +10015994: 4641 mov r1, r8 +10015996: 1818 adds r0, r3, r0 +10015998: f7fa ff39 bl 1001080e +1001599c: e023 b.n 100159e6 +1001599e: f407 40c0 and.w r0, r7, #24576 ; 0x6000 +100159a2: f5b0 4fc0 cmp.w r0, #24576 ; 0x6000 +100159a6: d105 bne.n 100159b4 +100159a8: 9902 ldr r1, [sp, #8] +100159aa: 9806 ldr r0, [sp, #24] +100159ac: 464a mov r2, r9 +100159ae: f7fa ff2e bl 1001080e +100159b2: e018 b.n 100159e6 +100159b4: b95f cbnz r7, 100159ce +100159b6: 9800 ldr r0, [sp, #0] +100159b8: 88c0 ldrh r0, [r0, #6] +100159ba: 0501 lsls r1, r0, #20 +100159bc: d507 bpl.n 100159ce +100159be: f7ff fec2 bl 10015746 +100159c2: 2811 cmp r0, #17 +100159c4: da03 bge.n 100159ce +100159c6: 9804 ldr r0, [sp, #16] +100159c8: b168 cbz r0, 100159e6 +100159ca: 9606 str r6, [sp, #24] +100159cc: e00b b.n 100159e6 +100159ce: 9801 ldr r0, [sp, #4] +100159d0: 990a ldr r1, [sp, #40] ; 0x28 +100159d2: 4288 cmp r0, r1 +100159d4: bf34 ite cc +100159d6: 9a0c ldrcc r2, [sp, #48] ; 0x30 +100159d8: 460a movcs r2, r1 +100159da: 9806 ldr r0, [sp, #24] +100159dc: 4641 mov r1, r8 +100159de: f7fa ff16 bl 1001080e +100159e2: f8ad 601e strh.w r6, [sp, #30] +100159e6: 9901 ldr r1, [sp, #4] +100159e8: 9803 ldr r0, [sp, #12] +100159ea: f7fa ff0f bl 1001080c +100159ee: f20f 60d4 addw r0, pc, #1748 ; 0x6d4 +100159f2: 9403 str r4, [sp, #12] +100159f4: 2118 movs r1, #24 +100159f6: fb01 000a mla r0, r1, sl, r0 +100159fa: 7800 ldrb r0, [r0, #0] +100159fc: 07c0 lsls r0, r0, #31 +100159fe: 9800 ldr r0, [sp, #0] +10015a00: d40a bmi.n 10015a18 +10015a02: 8885 ldrh r5, [r0, #4] +10015a04: 4628 mov r0, r5 +10015a06: f7ff fe9e bl 10015746 +10015a0a: 0529 lsls r1, r5, #20 +10015a0c: d50c bpl.n 10015a28 +10015a0e: 9904 ldr r1, [sp, #16] +10015a10: 1809 adds r1, r1, r0 +10015a12: 2911 cmp r1, #17 +10015a14: d208 bcs.n 10015a28 +10015a16: e008 b.n 10015a2a +10015a18: 88c5 ldrh r5, [r0, #6] +10015a1a: 4628 mov r0, r5 +10015a1c: f7ff fe93 bl 10015746 +10015a20: 0529 lsls r1, r5, #20 +10015a22: d501 bpl.n 10015a28 +10015a24: 2811 cmp r0, #17 +10015a26: d300 bcc.n 10015a2a +10015a28: b938 cbnz r0, 10015a3a +10015a2a: af06 add r7, sp, #24 +10015a2c: f44f 6100 mov.w r1, #2048 ; 0x800 +10015a30: 4640 mov r0, r8 +10015a32: f7fa feeb bl 1001080c +10015a36: 46a0 mov r8, r4 +10015a38: e000 b.n 10015a3c +10015a3a: 4647 mov r7, r8 +10015a3c: f8df 5548 ldr.w r5, [pc, #1352] ; 10015f88 <.text_114> +10015a40: 9819 ldr r0, [sp, #100] ; 0x64 +10015a42: f855 502a ldr.w r5, [r5, sl, lsl #2] +10015a46: 463b mov r3, r7 +10015a48: aa06 add r2, sp, #24 +10015a4a: 2100 movs r1, #0 +10015a4c: 47a8 blx r5 +10015a4e: 4605 mov r5, r0 +10015a50: 9800 ldr r0, [sp, #0] +10015a52: 88c6 ldrh r6, [r0, #6] +10015a54: f44f 40e0 mov.w r0, #28672 ; 0x7000 +10015a58: 4206 tst r6, r0 +10015a5a: d102 bne.n 10015a62 +10015a5c: 991a ldr r1, [sp, #104] ; 0x68 +10015a5e: 808c strh r4, [r1, #4] +10015a60: e6ff b.n 10015862 +10015a62: 0570 lsls r0, r6, #21 +10015a64: d0fa beq.n 10015a5c +10015a66: a80f add r0, sp, #60 ; 0x3c +10015a68: 2114 movs r1, #20 +10015a6a: f00f fed7 bl 1002581c <__aeabi_memclr4> +10015a6e: 0530 lsls r0, r6, #20 +10015a70: d509 bpl.n 10015a86 +10015a72: 4630 mov r0, r6 +10015a74: f7ff fe67 bl 10015746 +10015a78: 2811 cmp r0, #17 +10015a7a: da04 bge.n 10015a86 +10015a7c: ea4f 5a46 mov.w sl, r6, lsl #21 +10015a80: ea4f 5a5a mov.w sl, sl, lsr #21 +10015a84: e001 b.n 10015a8a +10015a86: f8bd a01c ldrh.w sl, [sp, #28] +10015a8a: f44f 6000 mov.w r0, #2048 ; 0x800 +10015a8e: 900e str r0, [sp, #56] ; 0x38 +10015a90: f7fa feb7 bl 10010802 +10015a94: 0004 movs r4, r0 +10015a96: bf08 it eq +10015a98: 465d moveq r5, fp +10015a9a: d0e1 beq.n 10015a60 +10015a9c: f406 40e0 and.w r0, r6, #28672 ; 0x7000 +10015aa0: f5b0 5f80 cmp.w r0, #4096 ; 0x1000 +10015aa4: f20f 6b14 addw fp, pc, #1556 ; 0x614 +10015aa8: d006 beq.n 10015ab8 +10015aaa: f5b0 5f00 cmp.w r0, #8192 ; 0x2000 +10015aae: d02f beq.n 10015b10 +10015ab0: f5b0 4f80 cmp.w r0, #16384 ; 0x4000 +10015ab4: d014 beq.n 10015ae0 +10015ab6: e706 b.n 100158c6 +10015ab8: 2600 movs r6, #0 +10015aba: 4556 cmp r6, sl +10015abc: da2d bge.n 10015b1a +10015abe: 5df2 ldrb r2, [r6, r7] +10015ac0: 4659 mov r1, fp +10015ac2: a80f add r0, sp, #60 ; 0x3c +10015ac4: f7f6 fbf2 bl 1000c2ac +10015ac8: a80f add r0, sp, #60 ; 0x3c +10015aca: f7f6 fc45 bl 1000c358 +10015ace: f000 f853 bl 10015b78 <.text_107> +10015ad2: f000 f835 bl 10015b40 <.text_102> +10015ad6: d818 bhi.n 10015b0a +10015ad8: f000 f849 bl 10015b6e <.text_106> +10015adc: 1c76 adds r6, r6, #1 +10015ade: e7ec b.n 10015aba +10015ae0: 2600 movs r6, #0 +10015ae2: e002 b.n 10015aea +10015ae4: f000 f843 bl 10015b6e <.text_106> +10015ae8: 1c76 adds r6, r6, #1 +10015aea: 4556 cmp r6, sl +10015aec: da15 bge.n 10015b1a +10015aee: f857 2026 ldr.w r2, [r7, r6, lsl #2] +10015af2: 4659 mov r1, fp +10015af4: a80f add r0, sp, #60 ; 0x3c +10015af6: f7f6 fbd9 bl 1000c2ac +10015afa: a80f add r0, sp, #60 ; 0x3c +10015afc: f7f6 fc2c bl 1000c358 +10015b00: f000 f83a bl 10015b78 <.text_107> +10015b04: f000 f81c bl 10015b40 <.text_102> +10015b08: d9ec bls.n 10015ae4 +10015b0a: f06f 0506 mvn.w r5, #6 +10015b0e: e6a8 b.n 10015862 +10015b10: 4652 mov r2, sl +10015b12: 4639 mov r1, r7 +10015b14: 4620 mov r0, r4 +10015b16: f7fa fe7a bl 1001080e +10015b1a: f000 f82e bl 10015b7a <.text_107+0x2> +10015b1e: 991a ldr r1, [sp, #104] ; 0x68 +10015b20: 1c40 adds r0, r0, #1 +10015b22: 8088 strh r0, [r1, #4] +10015b24: 991a ldr r1, [sp, #104] ; 0x68 +10015b26: 680b ldr r3, [r1, #0] +10015b28: 9901 ldr r1, [sp, #4] +10015b2a: 4281 cmp r1, r0 +10015b2c: bf2c ite cs +10015b2e: 4602 movcs r2, r0 +10015b30: 9a0c ldrcc r2, [sp, #48] ; 0x30 +10015b32: 4621 mov r1, r4 +10015b34: 4618 mov r0, r3 +10015b36: f7fa fe6a bl 1001080e +10015b3a: e692 b.n 10015862 + +10015b3c <.text_101>: +10015b3c: 00006925 .word 0x00006925 + +10015b40 <.text_102>: +10015b40: eb09 0100 add.w r1, r9, r0 +10015b44: 1c49 adds r1, r1, #1 +10015b46: f5b1 6f00 cmp.w r1, #2048 ; 0x800 +10015b4a: 4770 bx lr + +10015b4c <.text_103>: +10015b4c: f10d 0116 add.w r1, sp, #22 +10015b50: a802 add r0, sp, #8 +10015b52: f7f6 bc09 b.w 1000c368 + +10015b56 <.text_104>: +10015b56: 0578 lsls r0, r7, #21 +10015b58: f8bd 101c ldrh.w r1, [sp, #28] +10015b5c: 0d40 lsrs r0, r0, #21 +10015b5e: 4288 cmp r0, r1 +10015b60: 4770 bx lr + +10015b62 <.text_105>: +10015b62: f20f 5060 addw r0, pc, #1376 ; 0x560 +10015b66: 2118 movs r1, #24 +10015b68: fb01 000a mla r0, r1, sl, r0 +10015b6c: 4770 bx lr + +10015b6e <.text_106>: +10015b6e: 464a mov r2, r9 +10015b70: a90f add r1, sp, #60 ; 0x3c +10015b72: 1900 adds r0, r0, r4 +10015b74: f7fa be4b b.w 1001080e + +10015b78 <.text_107>: +10015b78: 4681 mov r9, r0 +10015b7a: 4620 mov r0, r4 +10015b7c: f7f6 bbec b.w 1000c358 + +10015b80 : +10015b80: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +10015b84: 4607 mov r7, r0 +10015b86: 460d mov r5, r1 +10015b88: 6938 ldr r0, [r7, #16] +10015b8a: 2400 movs r4, #0 +10015b8c: 6800 ldr r0, [r0, #0] +10015b8e: f648 11f0 movw r1, #35312 ; 0x89f0 +10015b92: 1a52 subs r2, r2, r1 +10015b94: f500 699d add.w r9, r0, #1256 ; 0x4e8 +10015b98: f241 1af0 movw sl, #4592 ; 0x11f0 +10015b9c: f04f 38ff mov.w r8, #4294967295 +10015ba0: f06f 0615 mvn.w r6, #21 +10015ba4: f000 81da beq.w 10015f5c +10015ba8: f44f 718a mov.w r1, #276 ; 0x114 +10015bac: 1a52 subs r2, r2, r1 +10015bae: f000 8164 beq.w 10015e7a +10015bb2: 1e52 subs r2, r2, #1 +10015bb4: f000 819d beq.w 10015ef2 +10015bb8: 1e52 subs r2, r2, #1 +10015bba: f000 80db beq.w 10015d74 +10015bbe: 1e52 subs r2, r2, #1 +10015bc0: f000 8101 beq.w 10015dc6 +10015bc4: 1e92 subs r2, r2, #2 +10015bc6: f000 8122 beq.w 10015e0e +10015bca: 3a0b subs r2, #11 +10015bcc: d01c beq.n 10015c08 +10015bce: 1f12 subs r2, r2, #4 +10015bd0: f000 819e beq.w 10015f10 +10015bd4: 1e52 subs r2, r2, #1 +10015bd6: f000 81a0 beq.w 10015f1a +10015bda: 1e52 subs r2, r2, #1 +10015bdc: d019 beq.n 10015c12 +10015bde: 1e52 subs r2, r2, #1 +10015be0: d029 beq.n 10015c36 +10015be2: 3a17 subs r2, #23 +10015be4: d046 beq.n 10015c74 +10015be6: 1e92 subs r2, r2, #2 +10015be8: d049 beq.n 10015c7e +10015bea: 1e52 subs r2, r2, #1 +10015bec: d062 beq.n 10015cb4 +10015bee: 3ac7 subs r2, #199 ; 0xc7 +10015bf0: f000 80bb beq.w 10015d6a +10015bf4: 1e52 subs r2, r2, #1 +10015bf6: f000 811f beq.w 10015e38 +10015bfa: 1e52 subs r2, r2, #1 +10015bfc: f000 8102 beq.w 10015e04 +10015c00: 1e52 subs r2, r2, #1 +10015c02: f000 807c beq.w 10015cfe +10015c06: e1b0 b.n 10015f6a +10015c08: f000 f9ce bl 10015fa8 <.text_118> +10015c0c: f7fe fc2e bl 1001446c +10015c10: e1a9 b.n 10015f66 +10015c12: f899 03e4 ldrb.w r0, [r9, #996] ; 0x3e4 +10015c16: b148 cbz r0, 10015c2c +10015c18: 8aaa ldrh r2, [r5, #20] +10015c1a: 6929 ldr r1, [r5, #16] +10015c1c: f209 305f addw r0, r9, #863 ; 0x35f +10015c20: f7fa fdf5 bl 1001080e +10015c24: 8aa9 ldrh r1, [r5, #20] +10015c26: 4449 add r1, r9 +10015c28: f881 435f strb.w r4, [r1, #863] ; 0x35f +10015c2c: f000 f9b0 bl 10015f90 <.text_116> +10015c30: f7fe fd2d bl 1001468e +10015c34: e197 b.n 10015f66 +10015c36: 692e ldr r6, [r5, #16] +10015c38: f105 0710 add.w r7, r5, #16 +10015c3c: f100 050c add.w r5, r0, #12 +10015c40: f105 098c add.w r9, r5, #140 ; 0x8c +10015c44: 2101 movs r1, #1 +10015c46: 4628 mov r0, r5 +10015c48: f7fe f922 bl 10013e90 +10015c4c: 2801 cmp r0, #1 +10015c4e: d006 beq.n 10015c5e +10015c50: 2140 movs r1, #64 ; 0x40 +10015c52: 4628 mov r0, r5 +10015c54: f7fe f91c bl 10013e90 +10015c58: 2801 cmp r0, #1 +10015c5a: f040 810c bne.w 10015e76 +10015c5e: f8d9 200c ldr.w r2, [r9, #12] +10015c62: 80ba strh r2, [r7, #4] +10015c64: f109 0110 add.w r1, r9, #16 +10015c68: 4630 mov r0, r6 +10015c6a: f7fa fdd0 bl 1001080e +10015c6e: 2001 movs r0, #1 +10015c70: 80f8 strh r0, [r7, #6] +10015c72: e17c b.n 10015f6e +10015c74: f000 f998 bl 10015fa8 <.text_118> +10015c78: f7fe fdae bl 100147d8 +10015c7c: e173 b.n 10015f66 +10015c7e: f899 03e4 ldrb.w r0, [r9, #996] ; 0x3e4 +10015c82: b190 cbz r0, 10015caa +10015c84: 6928 ldr r0, [r5, #16] +10015c86: 8c80 ldrh r0, [r0, #36] ; 0x24 +10015c88: f889 035e strb.w r0, [r9, #862] ; 0x35e +10015c8c: 6928 ldr r0, [r5, #16] +10015c8e: 8cc2 ldrh r2, [r0, #38] ; 0x26 +10015c90: f8a9 23a0 strh.w r2, [r9, #928] ; 0x3a0 +10015c94: 6928 ldr r0, [r5, #16] +10015c96: f100 0128 add.w r1, r0, #40 ; 0x28 +10015c9a: f209 307f addw r0, r9, #895 ; 0x37f +10015c9e: f7fa fdb6 bl 1001080e +10015ca2: 8ae8 ldrh r0, [r5, #22] +10015ca4: 1e40 subs r0, r0, #1 +10015ca6: f889 03a2 strb.w r0, [r9, #930] ; 0x3a2 +10015caa: f000 f971 bl 10015f90 <.text_116> +10015cae: f7fe fdf9 bl 100148a4 +10015cb2: e158 b.n 10015f66 +10015cb4: 692e ldr r6, [r5, #16] +10015cb6: f105 0110 add.w r1, r5, #16 +10015cba: 4450 add r0, sl +10015cbc: 80ca strh r2, [r1, #6] +10015cbe: 6842 ldr r2, [r0, #4] +10015cc0: 2a05 cmp r2, #5 +10015cc2: d8ca bhi.n 10015c5a +10015cc4: e8df f002 tbb [pc, r2] +10015cc8: d7050819 .word 0xd7050819 +10015ccc: 0803 .short 0x0803 +10015cce: 2003 movs r0, #3 +10015cd0: e000 b.n 10015cd4 +10015cd2: 2002 movs r0, #2 +10015cd4: 84b0 strh r0, [r6, #36] ; 0x24 +10015cd6: e14a b.n 10015f6e +10015cd8: 2201 movs r2, #1 +10015cda: 84b2 strh r2, [r6, #36] ; 0x24 +10015cdc: 6882 ldr r2, [r0, #8] +10015cde: 80ca strh r2, [r1, #6] +10015ce0: 2210 movs r2, #16 +10015ce2: 88c9 ldrh r1, [r1, #6] +10015ce4: eb00 1001 add.w r0, r0, r1, lsl #4 +10015ce8: f100 010c add.w r1, r0, #12 +10015cec: f106 0028 add.w r0, r6, #40 ; 0x28 +10015cf0: f7fa fd8d bl 1001080e +10015cf4: 2010 movs r0, #16 +10015cf6: 84f0 strh r0, [r6, #38] ; 0x26 +10015cf8: e139 b.n 10015f6e +10015cfa: 84b4 strh r4, [r6, #36] ; 0x24 +10015cfc: e137 b.n 10015f6e +10015cfe: f899 03e4 ldrb.w r0, [r9, #996] ; 0x3e4 +10015d02: b148 cbz r0, 10015d18 +10015d04: 8aaa ldrh r2, [r5, #20] +10015d06: 6929 ldr r1, [r5, #16] +10015d08: f209 30a3 addw r0, r9, #931 ; 0x3a3 +10015d0c: f7fa fd7f bl 1001080e +10015d10: 8aa9 ldrh r1, [r5, #20] +10015d12: 4449 add r1, r9 +10015d14: f881 43a3 strb.w r4, [r1, #931] ; 0x3a3 +10015d18: f105 0010 add.w r0, r5, #16 +10015d1c: 693a ldr r2, [r7, #16] +10015d1e: 6929 ldr r1, [r5, #16] +10015d20: 6812 ldr r2, [r2, #0] +10015d22: f641 5651 movw r6, #7505 ; 0x1d51 +10015d26: eb0a 0302 add.w r3, sl, r2 +10015d2a: 5cb2 ldrb r2, [r6, r2] +10015d2c: 2a00 cmp r2, #0 +10015d2e: bf0c ite eq +10015d30: 2600 moveq r6, #0 +10015d32: 2628 movne r6, #40 ; 0x28 +10015d34: 8882 ldrh r2, [r0, #4] +10015d36: 2700 movs r7, #0 +10015d38: f503 65c9 add.w r5, r3, #1608 ; 0x648 +10015d3c: b12a cbz r2, 10015d4a +10015d3e: 2a40 cmp r2, #64 ; 0x40 +10015d40: da03 bge.n 10015d4a +10015d42: 4628 mov r0, r5 +10015d44: f7fa fd63 bl 1001080e +10015d48: e00d b.n 10015d66 +10015d4a: 2a40 cmp r2, #64 ; 0x40 +10015d4c: d10a bne.n 10015d64 +10015d4e: 488f ldr r0, [pc, #572] ; (10015f8c <.text_115>) +10015d50: 2220 movs r2, #32 +10015d52: 1830 adds r0, r6, r0 +10015d54: f7fe fe19 bl 1001498a +10015d58: 2241 movs r2, #65 ; 0x41 +10015d5a: 2100 movs r1, #0 +10015d5c: 4628 mov r0, r5 +10015d5e: f7fa fd6b bl 10010838 +10015d62: e104 b.n 10015f6e +10015d64: 4647 mov r7, r8 +10015d66: 463c mov r4, r7 +10015d68: e101 b.n 10015f6e +10015d6a: f000 f917 bl 10015f9c <.text_117> +10015d6e: f7fe fe40 bl 100149f2 +10015d72: e0f8 b.n 10015f66 +10015d74: 3510 adds r5, #16 +10015d76: 4607 mov r7, r0 +10015d78: f20f 2248 addw r2, pc, #584 ; 0x248 +10015d7c: f44f 61fa mov.w r1, #2000 ; 0x7d0 +10015d80: f00a f942 bl 10020008 <_rtw_pwr_wakeup> +10015d84: 2800 cmp r0, #0 +10015d86: bf1e ittt ne +10015d88: f641 40b5 movwne r0, #7349 ; 0x1cb5 +10015d8c: 5dc0 ldrbne r0, [r0, r7] +10015d8e: 2800 cmpne r0, #0 +10015d90: d071 beq.n 10015e76 +10015d92: 6828 ldr r0, [r5, #0] +10015d94: b158 cbz r0, 10015dae +10015d96: 2802 cmp r0, #2 +10015d98: d003 beq.n 10015da2 +10015d9a: d306 bcc.n 10015daa +10015d9c: 2803 cmp r0, #3 +10015d9e: d002 beq.n 10015da6 +10015da0: e0c8 b.n 10015f34 +10015da2: 2601 movs r6, #1 +10015da4: e004 b.n 10015db0 +10015da6: 2604 movs r6, #4 +10015da8: e002 b.n 10015db0 +10015daa: 2600 movs r6, #0 +10015dac: e000 b.n 10015db0 +10015dae: 2602 movs r6, #2 +10015db0: 4631 mov r1, r6 +10015db2: 4638 mov r0, r7 +10015db4: f00d f8d4 bl 10022f60 +10015db8: 2800 cmp r0, #0 +10015dba: d05c beq.n 10015e76 +10015dbc: 4631 mov r1, r6 +10015dbe: 4638 mov r0, r7 +10015dc0: f00f fe9f bl 10025b02 +10015dc4: e0d3 b.n 10015f6e +10015dc6: f100 060c add.w r6, r0, #12 +10015dca: 3510 adds r5, #16 +10015dcc: 2108 movs r1, #8 +10015dce: f000 f8f5 bl 10015fbc <.text_120+0x2> +10015dd2: 2801 cmp r0, #1 +10015dd4: bf08 it eq +10015dd6: 2002 moveq r0, #2 +10015dd8: d012 beq.n 10015e00 +10015dda: 2140 movs r1, #64 ; 0x40 +10015ddc: f000 f8ee bl 10015fbc <.text_120+0x2> +10015de0: 2801 cmp r0, #1 +10015de2: d00c beq.n 10015dfe +10015de4: 2120 movs r1, #32 +10015de6: f000 f8e9 bl 10015fbc <.text_120+0x2> +10015dea: 2801 cmp r0, #1 +10015dec: d007 beq.n 10015dfe +10015dee: f000 f8e4 bl 10015fba <.text_120> +10015df2: 2801 cmp r0, #1 +10015df4: bf08 it eq +10015df6: 2003 moveq r0, #3 +10015df8: d002 beq.n 10015e00 +10015dfa: 602c str r4, [r5, #0] +10015dfc: e0b7 b.n 10015f6e +10015dfe: 2001 movs r0, #1 +10015e00: 6028 str r0, [r5, #0] +10015e02: e0b4 b.n 10015f6e +10015e04: f000 f8ca bl 10015f9c <.text_117> +10015e08: f7fe fe0b bl 10014a22 +10015e0c: e0ab b.n 10015f66 +10015e0e: f105 0610 add.w r6, r5, #16 +10015e12: 4605 mov r5, r0 +10015e14: 2101 movs r1, #1 +10015e16: f105 000c add.w r0, r5, #12 +10015e1a: f7fe f839 bl 10013e90 +10015e1e: 2801 cmp r0, #1 +10015e20: d105 bne.n 10015e2e +10015e22: f995 0dbc ldrsb.w r0, [r5, #3516] ; 0xdbc +10015e26: 4240 negs r0, r0 +10015e28: 6030 str r0, [r6, #0] +10015e2a: 7134 strb r4, [r6, #4] +10015e2c: e09f b.n 10015f6e +10015e2e: 6034 str r4, [r6, #0] +10015e30: 7134 strb r4, [r6, #4] +10015e32: 2001 movs r0, #1 +10015e34: 7170 strb r0, [r6, #5] +10015e36: e09a b.n 10015f6e +10015e38: 692f ldr r7, [r5, #16] +10015e3a: 4606 mov r6, r0 +10015e3c: 2500 movs r5, #0 +10015e3e: a14d add r1, pc, #308 ; (adr r1, 10015f74 <.text_109>) +10015e40: f000 f8b8 bl 10015fb4 <.text_119> +10015e44: b180 cbz r0, 10015e68 +10015e46: a14c add r1, pc, #304 ; (adr r1, 10015f78 <.text_110>) +10015e48: f000 f8b4 bl 10015fb4 <.text_119> +10015e4c: b908 cbnz r0, 10015e52 +10015e4e: 2502 movs r5, #2 +10015e50: e00a b.n 10015e68 +10015e52: a14a add r1, pc, #296 ; (adr r1, 10015f7c <.text_111>) +10015e54: f000 f8ae bl 10015fb4 <.text_119> +10015e58: b908 cbnz r0, 10015e5e +10015e5a: 2506 movs r5, #6 +10015e5c: e004 b.n 10015e68 +10015e5e: a148 add r1, pc, #288 ; (adr r1, 10015f80 <.text_112>) +10015e60: f000 f8a8 bl 10015fb4 <.text_119> +10015e64: b900 cbnz r0, 10015e68 +10015e66: 250c movs r5, #12 +10015e68: 2201 movs r2, #1 +10015e6a: 4629 mov r1, r5 +10015e6c: 4630 mov r0, r6 +10015e6e: f000 fdcf bl 10016a10 +10015e72: 2801 cmp r0, #1 +10015e74: d07b beq.n 10015f6e +10015e76: 4644 mov r4, r8 +10015e78: e079 b.n 10015f6e +10015e7a: 4680 mov r8, r0 +10015e7c: f641 5a48 movw sl, #7496 ; 0x1d48 +10015e80: eb0a 0b08 add.w fp, sl, r8 +10015e84: 7dad ldrb r5, [r5, #22] +10015e86: f89b 0009 ldrb.w r0, [fp, #9] +10015e8a: f109 070e add.w r7, r9, #14 +10015e8e: b1f8 cbz r0, 10015ed0 +10015e90: f44f 6100 mov.w r1, #2048 ; 0x800 +10015e94: 4640 mov r0, r8 +10015e96: f009 fcda bl 1001f84e +10015e9a: 2801 cmp r0, #1 +10015e9c: bf04 itt eq +10015e9e: f44f 707a moveq.w r0, #1000 ; 0x3e8 +10015ea2: f7fa fda4 bleq 100109ee +10015ea6: f89b 0009 ldrb.w r0, [fp, #9] +10015eaa: b188 cbz r0, 10015ed0 +10015eac: 2181 movs r1, #129 ; 0x81 +10015eae: 4640 mov r0, r8 +10015eb0: f009 fccd bl 1001f84e +10015eb4: 2801 cmp r0, #1 +10015eb6: d10b bne.n 10015ed0 +10015eb8: f85a 0008 ldr.w r0, [sl, r8] +10015ebc: f500 609d add.w r0, r0, #1256 ; 0x4e8 +10015ec0: 7b81 ldrb r1, [r0, #14] +10015ec2: f889 100e strb.w r1, [r9, #14] +10015ec6: 7c01 ldrb r1, [r0, #16] +10015ec8: 70b9 strb r1, [r7, #2] +10015eca: 7bc0 ldrb r0, [r0, #15] +10015ecc: 7078 strb r0, [r7, #1] +10015ece: e04e b.n 10015f6e +10015ed0: 2200 movs r2, #0 +10015ed2: 4629 mov r1, r5 +10015ed4: f109 0014 add.w r0, r9, #20 +10015ed8: f003 fd86 bl 100199e8 +10015edc: 2801 cmp r0, #1 +10015ede: d129 bne.n 10015f34 +10015ee0: f889 500e strb.w r5, [r9, #14] +10015ee4: 787b ldrb r3, [r7, #1] +10015ee6: 78ba ldrb r2, [r7, #2] +10015ee8: 4629 mov r1, r5 +10015eea: 4640 mov r0, r8 +10015eec: f00f fe54 bl 10025b98 +10015ef0: e03d b.n 10015f6e +10015ef2: f105 0610 add.w r6, r5, #16 +10015ef6: 4605 mov r5, r0 +10015ef8: f105 070c add.w r7, r5, #12 +10015efc: f7fe fb42 bl 10014584 <.text_30> +10015f00: 2801 cmp r0, #1 +10015f02: bf0c ite eq +10015f04: f8d7 00d8 ldreq.w r0, [r7, #216] ; 0xd8 +10015f08: f895 04f6 ldrbne.w r0, [r5, #1270] ; 0x4f6 +10015f0c: 71b0 strb r0, [r6, #6] +10015f0e: e02e b.n 10015f6e +10015f10: f000 f844 bl 10015f9c <.text_117> +10015f14: f7fe fb3e bl 10014594 +10015f18: e025 b.n 10015f66 +10015f1a: f500 51cc add.w r1, r0, #6528 ; 0x1980 +10015f1e: f105 0810 add.w r8, r5, #16 +10015f22: 7809 ldrb r1, [r1, #0] +10015f24: f100 070c add.w r7, r0, #12 +10015f28: 2500 movs r5, #0 +10015f2a: b129 cbz r1, 10015f38 +10015f2c: f641 419c movw r1, #7324 ; 0x1c9c +10015f30: 5808 ldr r0, [r1, r0] +10015f32: b108 cbz r0, 10015f38 +10015f34: 4634 mov r4, r6 +10015f36: e01a b.n 10015f6e +10015f38: f44f 6108 mov.w r1, #2176 ; 0x880 +10015f3c: f7fe fb23 bl 10014586 <.text_30+0x2> +10015f40: 2801 cmp r0, #1 +10015f42: d105 bne.n 10015f50 +10015f44: 201e movs r0, #30 +10015f46: f7fa fd52 bl 100109ee +10015f4a: 1c6d adds r5, r5, #1 +10015f4c: 2dc9 cmp r5, #201 ; 0xc9 +10015f4e: d3f3 bcc.n 10015f38 +10015f50: 8fb8 ldrh r0, [r7, #60] ; 0x3c +10015f52: f8a8 0006 strh.w r0, [r8, #6] +10015f56: 637c str r4, [r7, #52] ; 0x34 +10015f58: 87bc strh r4, [r7, #60] ; 0x3c +10015f5a: e008 b.n 10015f6e +10015f5c: f105 0110 add.w r1, r5, #16 +10015f60: 4638 mov r0, r7 +10015f62: f7ff fbf9 bl 10015758 +10015f66: 4604 mov r4, r0 +10015f68: e001 b.n 10015f6e +10015f6a: f06f 045e mvn.w r4, #94 ; 0x5e +10015f6e: 4620 mov r0, r4 +10015f70: e8bd 8ff2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +10015f74 <.text_109>: +10015f74: 00005355 .word 0x00005355 + +10015f78 <.text_110>: +10015f78: 00005545 .word 0x00005545 + +10015f7c <.text_111>: +10015f7c: 0000504a .word 0x0000504a + +10015f80 <.text_112>: +10015f80: 00004e43 .word 0x00004e43 + +10015f84 <.text_113>: +10015f84: 00400004 .word 0x00400004 + +10015f88 <.text_114>: +10015f88: 10044224 .word 0x10044224 + +10015f8c <.text_115>: +10015f8c: 10048248 .word 0x10048248 + +10015f90 <.text_116>: +10015f90: f105 0210 add.w r2, r5, #16 +10015f94: 692b ldr r3, [r5, #16] +10015f96: 2100 movs r1, #0 +10015f98: 4638 mov r0, r7 +10015f9a: 4770 bx lr + +10015f9c <.text_117>: +10015f9c: 692b ldr r3, [r5, #16] +10015f9e: f105 0210 add.w r2, r5, #16 +10015fa2: 2100 movs r1, #0 +10015fa4: 4638 mov r0, r7 +10015fa6: 4770 bx lr + +10015fa8 <.text_118>: +10015fa8: 2300 movs r3, #0 +10015faa: f105 0210 add.w r2, r5, #16 +10015fae: 4619 mov r1, r3 +10015fb0: 4638 mov r0, r7 +10015fb2: 4770 bx lr + +10015fb4 <.text_119>: +10015fb4: 4638 mov r0, r7 +10015fb6: f7f6 b9cb b.w 1000c350 + +10015fba <.text_120>: +10015fba: 2110 movs r1, #16 +10015fbc: 4630 mov r0, r6 +10015fbe: f7fd bf67 b.w 10013e90 + ... + +10015fc4 : +10015fc4: 7472 5f77 7877 735f 7465 6d5f 646f 0065 rtw_wx_set_mode. + +10015fd4 : +10015fd4: 6170 6874 3d61 6425 702c 7461 6268 253d patha=%d,pathb=% +10015fe4: 0064 0000 d... + +10015fe8 : +10015fe8: 6425 2520 0064 0000 %d %d... + +10015ff0 : +10015ff0: 6553 2074 6f70 6577 2072 656c 6576 206c Set power level +10016000: 6170 6874 415f 253a 2064 6170 6874 425f path_A:%d path_B +10016010: 253a 0064 :%d. + +10016014 : +10016014: 616d 2063 6461 7264 7365 2073 6f66 6d72 mac address form +10016024: 7461 6520 7272 726f 0d21 000a at error!... + +10016030 : +10016030: 7277 7469 2065 616d 2063 6461 7264 7365 write mac addres +10016040: 2073 6f74 6620 616c 6873 6520 7272 726f s to flash error +10016050: 0d21 000a !... + +10016054 : +10016054: 0a0d 7720 6972 6574 6d20 6361 6120 6464 .. write mac add +10016064: 6572 7373 7320 6375 6563 7373 202c 6c70 ress success, pl +10016074: 6165 6573 7220 7365 7465 7720 6669 2069 ease reset wifi +10016084: 7264 7669 7265 0d21 000a 0000 driver!..... + +10016090 : +10016090: 3025 7832 253a 3230 3a78 3025 7832 253a %02x:%02x:%02x:% +100160a0: 3230 3a78 3025 7832 253a 3230 0078 0000 02x:%02x:%02x... + +100160b0 : +100160b0: 0020 0000 ... + +100160b4 : +100160b4: 3125 7336 0000 0000 %16s.... + +100160bc : +100160bc: 6425 2020 0000 0000 %d .... + +100160c4 : +100160c4: 8be0 0000 27ff 0000 7277 7469 0065 0000 .....'..write... + ... +100160dc: 8be1 0000 27ff 2810 6572 6461 0000 0000 .....'.(read.... + ... +100160f4: 8beb 0000 4802 0000 6264 0067 0000 0000 .....H..dbg..... + ... +1001610c: 8bf6 0000 2040 0000 6d70 735f 7465 0000 ....@ ..pm_set.. + ... +10016124: 8c00 0000 27ff 0000 6150 7472 6169 536c .....'..PartialS +10016134: 6163 006e 0000 0000 8c01 0000 27ff 0000 can..........'.. +10016144: 6553 4174 7475 526f 6365 746e 0000 0000 SetAutoRecnt.... +10016154: 8c02 0000 27ff 27ff 6547 4174 7475 526f .....'.'GetAutoR +10016164: 6365 746e 0000 0000 8c03 0000 67ff 0000 ecnt.........g.. +10016174: 6553 4374 7375 4549 0000 0000 0000 0000 SetCusIE........ +10016184: 8c04 0000 67ff 0000 7055 6164 6574 4549 .....g..UpdateIE + ... +1001619c: 8c05 0000 0000 0000 6544 496c 0045 0000 ........DelIE... + ... +100161b4: 8c06 0000 2001 0000 6f66 7772 7261 6964 ..... ..forwardi +100161c4: 676e 735f 7465 0000 8bee 0000 2400 0000 ng_set.......$.. + ... +100161e4: 8bef 0000 2400 27ff 0000 0000 0000 0000 .....$.'........ + ... +10016200: 2400 0000 7277 7469 5f65 616d 0063 0000 .$..write_mac... +10016210: 0000 0000 0001 0000 2400 27ff 6572 6461 .........$.'read +10016220: 6d5f 6361 0000 0000 0000 0000 0002 0000 _mac............ +10016230: 2400 27ff 7874 6f70 6577 0072 0000 0000 .$.'txpower..... +10016240: 0000 0000 0003 0000 2400 27ff 6567 5f74 .........$.'get_ +10016250: 6c63 6569 746e 6c5f 7369 0074 0004 0000 client_list..... +10016260: 2400 27ff 6567 5f74 7061 695f 666e 006f .$.'get_ap_info. +10016270: 0000 0000 0005 0000 2400 27ff 6567 5f74 .........$.'get_ +10016280: 6573 7563 6972 7974 0000 0000 security.... + +1001628c : +1001628c: 0100 0001 0804 0010 ........ + +10016294 : +10016294: f8df f000 ldr.w pc, [pc] ; 10016298 +10016298: 00013965 .word 0x00013965 + +1001629c : +1001629c: 6f80 ldr r0, [r0, #120] ; 0x78 +1001629e: 307c adds r0, #124 ; 0x7c +100162a0: 4770 bx lr + +100162a2 : +100162a2: 6840 ldr r0, [r0, #4] +100162a4: 4208 tst r0, r1 +100162a6: d001 beq.n 100162ac +100162a8: 2001 movs r0, #1 +100162aa: 4770 bx lr +100162ac: 2000 movs r0, #0 +100162ae: 4770 bx lr + +100162b0 : +100162b0: 6842 ldr r2, [r0, #4] +100162b2: 430a orrs r2, r1 +100162b4: 6042 str r2, [r0, #4] +100162b6: f5b1 6f00 cmp.w r1, #2048 ; 0x800 +100162ba: bf04 itt eq +100162bc: 2101 moveq r1, #1 +100162be: 7201 strbeq r1, [r0, #8] +100162c0: 4770 bx lr + +100162c2 <_rtw_init_evt_priv>: +100162c2: b510 push {r4, lr} +100162c4: 4604 mov r4, r0 +100162c6: 2100 movs r1, #0 +100162c8: f7fa fbce bl 10010a68 +100162cc: 2000 movs r0, #0 +100162ce: 60e0 str r0, [r4, #12] +100162d0: 2001 movs r0, #1 +100162d2: bd10 pop {r4, pc} + +100162d4 <_rtw_free_cmd_priv>: +100162d4: 2800 cmp r0, #0 +100162d6: bf1c itt ne +100162d8: 3008 addne r0, #8 +100162da: f7fa bb43 bne.w 10010964 +100162de: 4770 bx lr + +100162e0 <_rtw_enqueue_cmd>: +100162e0: b538 push {r3, r4, r5, lr} +100162e2: 000d movs r5, r1 +100162e4: 4604 mov r4, r0 +100162e6: d008 beq.n 100162fa <_rtw_enqueue_cmd+0x1a> +100162e8: f000 f821 bl 1001632e <.text_12> +100162ec: 4621 mov r1, r4 +100162ee: f105 0018 add.w r0, r5, #24 +100162f2: f7fa fab5 bl 10010860 +100162f6: f000 f815 bl 10016324 <.text_11> +100162fa: 2001 movs r0, #1 +100162fc: bd32 pop {r1, r4, r5, pc} + +100162fe <_rtw_dequeue_cmd>: +100162fe: b538 push {r3, r4, r5, lr} +10016300: 4604 mov r4, r0 +10016302: f000 f814 bl 1001632e <.text_12> +10016306: 4620 mov r0, r4 +10016308: f7fa faa1 bl 1001084e +1001630c: b108 cbz r0, 10016312 <_rtw_dequeue_cmd+0x14> +1001630e: 2500 movs r5, #0 +10016310: e004 b.n 1001631c <_rtw_dequeue_cmd+0x1e> +10016312: 6820 ldr r0, [r4, #0] +10016314: 2118 movs r1, #24 +10016316: 1a45 subs r5, r0, r1 +10016318: f7fa faa4 bl 10010864 +1001631c: f000 f802 bl 10016324 <.text_11> +10016320: 4628 mov r0, r5 +10016322: bd32 pop {r1, r4, r5, pc} + +10016324 <.text_11>: +10016324: a900 add r1, sp, #0 +10016326: f104 0008 add.w r0, r4, #8 +1001632a: f7fa baec b.w 10010906 + +1001632e <.text_12>: +1001632e: a900 add r1, sp, #0 +10016330: f104 0008 add.w r0, r4, #8 +10016334: f7fa bae0 b.w 100108f8 + +10016338 <_rtw_observequeue_cmd>: +10016338: b510 push {r4, lr} +1001633a: 4604 mov r4, r0 +1001633c: f7fa fa87 bl 1001084e +10016340: b108 cbz r0, 10016346 <_rtw_observequeue_cmd+0xe> +10016342: 2000 movs r0, #0 +10016344: bd10 pop {r4, pc} +10016346: 6820 ldr r0, [r4, #0] +10016348: 2118 movs r1, #24 +1001634a: 1a40 subs r0, r0, r1 +1001634c: bd10 pop {r4, pc} + +1001634e : +1001634e: b580 push {r7, lr} + +10016350 <.text_15>: +10016350: f7fa faf1 bl 10010936 +10016354: 2001 movs r0, #1 +10016356: bd02 pop {r1, pc} + +10016358 : +10016358: e7b3 b.n 100162c2 <_rtw_init_evt_priv> + +1001635a : +1001635a: 4770 bx lr + +1001635c : +1001635c: e7ba b.n 100162d4 <_rtw_free_cmd_priv> + +1001635e : +1001635e: 8889 ldrh r1, [r1, #4] +10016360: 2200 movs r2, #0 +10016362: 293b cmp r1, #59 ; 0x3b +10016364: 6901 ldr r1, [r0, #16] +10016366: f641 43b5 movw r3, #7349 ; 0x1cb5 +1001636a: bf08 it eq +1001636c: 2201 moveq r2, #1 +1001636e: 5c59 ldrb r1, [r3, r1] +10016370: 4311 orrs r1, r2 +10016372: bf1c itt ne +10016374: 7b00 ldrbne r0, [r0, #12] +10016376: 2800 cmpne r0, #0 +10016378: d101 bne.n 1001637e +1001637a: 2000 movs r0, #0 +1001637c: 4770 bx lr +1001637e: 2001 movs r0, #1 +10016380: 4770 bx lr + +10016382 : +10016382: b5f8 push {r3, r4, r5, r6, r7, lr} +10016384: 4604 mov r4, r0 +10016386: 460d mov r5, r1 +10016388: 6927 ldr r7, [r4, #16] +1001638a: 2600 movs r6, #0 +1001638c: b315 cbz r5, 100163d4 +1001638e: f641 5051 movw r0, #7505 ; 0x1d51 +10016392: 602f str r7, [r5, #0] +10016394: 5dc0 ldrb r0, [r0, r7] +10016396: 2800 cmp r0, #0 +10016398: bf1e ittt ne +1001639a: f641 5048 movwne r0, #7496 ; 0x1d48 +1001639e: 59c0 ldrne r0, [r0, r7] +100163a0: 2800 cmpne r0, #0 +100163a2: bf1c itt ne +100163a4: f600 04d8 addwne r4, r0, #2264 ; 0x8d8 +100163a8: 4607 movne r7, r0 +100163aa: 4620 mov r0, r4 +100163ac: f7ff ffd7 bl 1001635e +100163b0: 0006 movs r6, r0 +100163b2: d103 bne.n 100163bc +100163b4: 4628 mov r0, r5 +100163b6: f000 f811 bl 100163dc +100163ba: e00b b.n 100163d4 +100163bc: 4629 mov r1, r5 +100163be: 4620 mov r0, r4 +100163c0: f7ff ff8e bl 100162e0 <_rtw_enqueue_cmd> +100163c4: 4606 mov r6, r0 +100163c6: 2e01 cmp r6, #1 +100163c8: d104 bne.n 100163d4 +100163ca: f507 50e0 add.w r0, r7, #7168 ; 0x1c00 +100163ce: 30d4 adds r0, #212 ; 0xd4 +100163d0: f7fa fba8 bl 10010b24 +100163d4: 4630 mov r0, r6 +100163d6: bdf2 pop {r1, r4, r5, r6, r7, pc} + +100163d8 : +100163d8: e791 b.n 100162fe <_rtw_dequeue_cmd> + +100163da : +100163da: e7ad b.n 10016338 <_rtw_observequeue_cmd> + +100163dc : +100163dc: b510 push {r4, lr} +100163de: 4604 mov r4, r0 +100163e0: 88a0 ldrh r0, [r4, #4] +100163e2: 2810 cmp r0, #16 +100163e4: d003 beq.n 100163ee +100163e6: 68e1 ldr r1, [r4, #12] +100163e8: 68a0 ldr r0, [r4, #8] +100163ea: f7fa fa0f bl 1001080c +100163ee: 6920 ldr r0, [r4, #16] +100163f0: 2800 cmp r0, #0 +100163f2: bf1e ittt ne +100163f4: 6961 ldrne r1, [r4, #20] +100163f6: 2900 cmpne r1, #0 +100163f8: f7fa fa08 blne 1001080c +100163fc: 4620 mov r0, r4 +100163fe: e8bd 4010 ldmia.w sp!, {r4, lr} +10016402: 2120 movs r1, #32 +10016404: f7fa ba02 b.w 1001080c + +10016408 : +10016408: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1001640c: 4682 mov sl, r0 +1001640e: f50a 56e0 add.w r6, sl, #7168 ; 0x1c00 +10016412: f60a 05d8 addw r5, sl, #2264 ; 0x8d8 +10016416: 36d4 adds r6, #212 ; 0xd4 +10016418: f60f 10e4 addw r0, pc, #2532 ; 0x9e4 +1001641c: f7fa fbb8 bl 10010b90 +10016420: 2001 movs r0, #1 +10016422: 7328 strb r0, [r5, #12] +10016424: f106 000c add.w r0, r6, #12 +10016428: f7fa fa31 bl 1001088e +1001642c: f641 4b9c movw fp, #7324 ; 0x1c9c +10016430: f60f 38d4 addw r8, pc, #3028 ; 0xbd4 +10016434: f641 5948 movw r9, #7496 ; 0x1d48 +10016438: f641 44e8 movw r4, #7400 ; 0x1ce8 +1001643c: f000 f876 bl 1001652c <.text_25> +10016440: f106 0008 add.w r0, r6, #8 +10016444: f7fa fa32 bl 100108ac +10016448: 2800 cmp r0, #0 +1001644a: d05b beq.n 10016504 +1001644c: 6930 ldr r0, [r6, #16] +1001644e: 2800 cmp r0, #0 +10016450: d158 bne.n 10016504 +10016452: f85b 000a ldr.w r0, [fp, sl] +10016456: 2801 cmp r0, #1 +10016458: bf1e ittt ne +1001645a: eb0b 000a addne.w r0, fp, sl +1001645e: 6840 ldrne r0, [r0, #4] +10016460: 2801 cmpne r0, #1 +10016462: d04f beq.n 10016504 +10016464: f85b 000a ldr.w r0, [fp, sl] +10016468: 2801 cmp r0, #1 +1001646a: bf1e ittt ne +1001646c: eb0b 000a addne.w r0, fp, sl +10016470: 6840 ldrne r0, [r0, #4] +10016472: 2801 cmpne r0, #1 +10016474: d046 beq.n 10016504 +10016476: 4628 mov r0, r5 +10016478: f7ff ffaf bl 100163da +1001647c: b110 cbz r0, 10016484 +1001647e: 6800 ldr r0, [r0, #0] +10016480: 2101 movs r1, #1 +10016482: 5021 str r1, [r4, r0] +10016484: 4628 mov r0, r5 +10016486: f7ff ffa7 bl 100163d8 +1001648a: 0007 movs r7, r0 +1001648c: d0d6 beq.n 1001643c +1001648e: 6928 ldr r0, [r5, #16] +10016490: 6839 ldr r1, [r7, #0] +10016492: 4281 cmp r1, r0 +10016494: d002 beq.n 1001649c +10016496: f859 0000 ldr.w r0, [r9, r0] +1001649a: b358 cbz r0, 100164f4 +1001649c: 4639 mov r1, r7 +1001649e: 4628 mov r0, r5 +100164a0: f7ff ff5d bl 1001635e +100164a4: b908 cbnz r0, 100164aa +100164a6: 2003 movs r0, #3 +100164a8: e015 b.n 100164d6 +100164aa: 68f8 ldr r0, [r7, #12] +100164ac: f010 0103 ands.w r1, r0, #3 +100164b0: bf18 it ne +100164b2: 2101 movne r1, #1 +100164b4: eb01 0090 add.w r0, r1, r0, lsr #2 +100164b8: 0080 lsls r0, r0, #2 +100164ba: 60f8 str r0, [r7, #12] +100164bc: 88b8 ldrh r0, [r7, #4] +100164be: 2840 cmp r0, #64 ; 0x40 +100164c0: d208 bcs.n 100164d4 +100164c2: eb08 00c0 add.w r0, r8, r0, lsl #3 +100164c6: 6842 ldr r2, [r0, #4] +100164c8: 0010 movs r0, r2 +100164ca: d005 beq.n 100164d8 +100164cc: 68b9 ldr r1, [r7, #8] +100164ce: 6838 ldr r0, [r7, #0] +100164d0: 4790 blx r2 +100164d2: e000 b.n 100164d6 +100164d4: 2004 movs r0, #4 +100164d6: 71b8 strb r0, [r7, #6] +100164d8: 88b8 ldrh r0, [r7, #4] +100164da: 2840 cmp r0, #64 ; 0x40 +100164dc: d20a bcs.n 100164f4 +100164de: f60f 1130 addw r1, pc, #2352 ; 0x930 +100164e2: eb01 00c0 add.w r0, r1, r0, lsl #3 +100164e6: 6842 ldr r2, [r0, #4] +100164e8: 0010 movs r0, r2 +100164ea: d003 beq.n 100164f4 +100164ec: 6838 ldr r0, [r7, #0] +100164ee: 4639 mov r1, r7 +100164f0: 4790 blx r2 +100164f2: e002 b.n 100164fa +100164f4: 4638 mov r0, r7 +100164f6: f7ff ff71 bl 100163dc +100164fa: f7fa fafc bl 10010af6 +100164fe: 6930 ldr r0, [r6, #16] +10016500: 2800 cmp r0, #0 +10016502: d0af beq.n 10016464 +10016504: 2000 movs r0, #0 +10016506: 7328 strb r0, [r5, #12] +10016508: e001 b.n 1001650e +1001650a: f7ff ff67 bl 100163dc +1001650e: 4628 mov r0, r5 +10016510: f7ff ff62 bl 100163d8 +10016514: 2800 cmp r0, #0 +10016516: d1f8 bne.n 1001650a +10016518: f000 f808 bl 1001652c <.text_25> +1001651c: f106 000c add.w r0, r6, #12 +10016520: f7fa f9b5 bl 1001088e +10016524: e8bd 4ff1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, sl, fp, lr} +10016528: f7fa bb39 b.w 10010b9e + +1001652c <.text_25>: +1001652c: f859 000a ldr.w r0, [r9, sl] +10016530: b108 cbz r0, 10016536 <.text_25+0xa> +10016532: 2100 movs r1, #0 +10016534: 5021 str r1, [r4, r0] +10016536: 2000 movs r0, #0 +10016538: 6170 str r0, [r6, #20] +1001653a: 4770 bx lr + +1001653c : +1001653c: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +10016540: 4606 mov r6, r0 +10016542: 460c mov r4, r1 +10016544: 4690 mov r8, r2 +10016546: f606 0bd8 addw fp, r6, #2264 ; 0x8d8 +1001654a: f106 070c add.w r7, r6, #12 +1001654e: 2201 movs r2, #1 +10016550: 2100 movs r1, #0 +10016552: f000 fb34 bl 10016bbe +10016556: f000 fa98 bl 10016a8a <.text_42+0x4> +1001655a: 0005 movs r5, r0 +1001655c: d05a beq.n 10016614 +1001655e: 2030 movs r0, #48 ; 0x30 +10016560: f7fa f94f bl 10010802 +10016564: ea5f 0900 movs.w r9, r0 +10016568: d103 bne.n 10016572 +1001656a: f000 fb45 bl 10016bf8 <.text_48> +1001656e: 2000 movs r0, #0 +10016570: e050 b.n 10016614 +10016572: 2100 movs r1, #0 +10016574: 4630 mov r0, r6 +10016576: f008 f9ca bl 1001e90e +1001657a: f000 fa1f bl 100169bc <.text_37> +1001657e: 2012 movs r0, #18 +10016580: 80a8 strh r0, [r5, #4] +10016582: f8c5 9008 str.w r9, [r5, #8] +10016586: 2030 movs r0, #48 ; 0x30 +10016588: 60e8 str r0, [r5, #12] +1001658a: f207 4a1c addw sl, r7, #1052 ; 0x41c +1001658e: 2000 movs r0, #0 +10016590: 6128 str r0, [r5, #16] +10016592: 6168 str r0, [r5, #20] +10016594: 2228 movs r2, #40 ; 0x28 +10016596: 2030 movs r0, #48 ; 0x30 +10016598: f8c9 0004 str.w r0, [r9, #4] +1001659c: 2100 movs r1, #0 +1001659e: f8da 0078 ldr.w r0, [sl, #120] ; 0x78 +100165a2: f8c9 0000 str.w r0, [r9] +100165a6: f109 0008 add.w r0, r9, #8 +100165aa: f7fa f945 bl 10010838 +100165ae: b184 cbz r4, 100165d2 +100165b0: 2600 movs r6, #0 +100165b2: e00a b.n 100165ca +100165b4: 2028 movs r0, #40 ; 0x28 +100165b6: 4370 muls r0, r6 +100165b8: 5901 ldr r1, [r0, r4] +100165ba: b129 cbz r1, 100165c8 +100165bc: 1901 adds r1, r0, r4 +100165be: 4448 add r0, r9 +100165c0: 2228 movs r2, #40 ; 0x28 +100165c2: 3008 adds r0, #8 +100165c4: f7fa f923 bl 1001080e +100165c8: 1c76 adds r6, r6, #1 +100165ca: 4546 cmp r6, r8 +100165cc: bfb8 it lt +100165ce: 2e01 cmplt r6, #1 +100165d0: dbf0 blt.n 100165b4 +100165d2: f44f 6100 mov.w r1, #2048 ; 0x800 +100165d6: 4638 mov r0, r7 +100165d8: f7ff fe6a bl 100162b0 +100165dc: 4629 mov r1, r5 +100165de: 4658 mov r0, fp +100165e0: f7ff fecf bl 10016382 +100165e4: b2c4 uxtb r4, r0 +100165e6: 2c01 cmp r4, #1 +100165e8: d10d bne.n 10016606 +100165ea: f7fa f9d0 bl 1001098e +100165ee: f8ca 0020 str.w r0, [sl, #32] +100165f2: f44f 51fa mov.w r1, #8000 ; 0x1f40 +100165f6: f507 6086 add.w r0, r7, #1072 ; 0x430 +100165fa: f7fa fa1e bl 10010a3a +100165fe: 201e movs r0, #30 +10016600: f8c7 041c str.w r0, [r7, #1052] ; 0x41c +10016604: e005 b.n 10016612 +10016606: 6878 ldr r0, [r7, #4] +10016608: f420 6000 bic.w r0, r0, #2048 ; 0x800 +1001660c: 6078 str r0, [r7, #4] +1001660e: 2000 movs r0, #0 +10016610: 7238 strb r0, [r7, #8] +10016612: 4620 mov r0, r4 +10016614: e8bd 8ff2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +10016618 : +10016618: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +1001661c: b089 sub sp, #36 ; 0x24 +1001661e: 4604 mov r4, r0 +10016620: f604 00d8 addw r0, r4, #2264 ; 0x8d8 +10016624: 9007 str r0, [sp, #28] +10016626: f104 0b0c add.w fp, r4, #12 +1001662a: f50b 6088 add.w r0, fp, #1088 ; 0x440 +1001662e: 9003 str r0, [sp, #12] +10016630: 468a mov sl, r1 +10016632: f50b 6089 add.w r0, fp, #1096 ; 0x448 +10016636: 9006 str r0, [sp, #24] +10016638: f504 5788 add.w r7, r4, #4352 ; 0x1100 +1001663c: f8da 007c ldr.w r0, [sl, #124] ; 0x7c +10016640: 9005 str r0, [sp, #20] +10016642: 37f0 adds r7, #240 ; 0xf0 +10016644: f504 60bf add.w r0, r4, #1528 ; 0x5f8 +10016648: 9004 str r0, [sp, #16] +1001664a: f504 58c4 add.w r8, r4, #6272 ; 0x1880 +1001664e: f8d7 0364 ldr.w r0, [r7, #868] ; 0x364 +10016652: 2804 cmp r0, #4 +10016654: bf18 it ne +10016656: 2807 cmpne r0, #7 +10016658: f10a 0998 add.w r9, sl, #152 ; 0x98 +1001665c: f10a 057c add.w r5, sl, #124 ; 0x7c +10016660: d142 bne.n 100166e8 +10016662: 2000 movs r0, #0 +10016664: 9002 str r0, [sp, #8] +10016666: ab02 add r3, sp, #8 +10016668: f504 50a8 add.w r0, r4, #5376 ; 0x1500 +1001666c: f100 0678 add.w r6, r0, #120 ; 0x78 +10016670: f10d 000a add.w r0, sp, #10 +10016674: 9001 str r0, [sp, #4] +10016676: 4632 mov r2, r6 +10016678: 2000 movs r0, #0 +1001667a: 9000 str r0, [sp, #0] +1001667c: 4648 mov r0, r9 +1001667e: 69a9 ldr r1, [r5, #24] +10016680: f7ff fe08 bl 10016294 +10016684: b380 cbz r0, 100166e8 +10016686: f8bd 0008 ldrh.w r0, [sp, #8] +1001668a: b150 cbz r0, 100166a2 +1001668c: 4601 mov r1, r0 +1001668e: 4630 mov r0, r6 +10016690: f00e f9fd bl 10024a8e +10016694: f8ad 0008 strh.w r0, [sp, #8] +10016698: f000 f8ae bl 100167f8 <.text_29> +1001669c: f8bd 2008 ldrh.w r2, [sp, #8] +100166a0: e017 b.n 100166d2 +100166a2: f8bd 000a ldrh.w r0, [sp, #10] +100166a6: b1c0 cbz r0, 100166da +100166a8: f10d 000a add.w r0, sp, #10 +100166ac: 9001 str r0, [sp, #4] +100166ae: 9600 str r6, [sp, #0] +100166b0: ab02 add r3, sp, #8 +100166b2: 69a9 ldr r1, [r5, #24] +100166b4: 2200 movs r2, #0 +100166b6: 4648 mov r0, r9 +100166b8: f7ff fdec bl 10016294 +100166bc: f8bd 100a ldrh.w r1, [sp, #10] +100166c0: 4630 mov r0, r6 +100166c2: f00e fa1b bl 10024afc +100166c6: f8ad 000a strh.w r0, [sp, #10] +100166ca: f000 f895 bl 100167f8 <.text_29> +100166ce: f8bd 200a ldrh.w r2, [sp, #10] +100166d2: 4631 mov r1, r6 +100166d4: 4620 mov r0, r4 +100166d6: f00e f991 bl 100249fc +100166da: f10a 022c add.w r2, sl, #44 ; 0x2c +100166de: f507 61c9 add.w r1, r7, #1608 ; 0x648 +100166e2: 4620 mov r0, r4 +100166e4: f00e f93f bl 10024966 +100166e8: f000 f9cf bl 10016a8a <.text_42+0x4> +100166ec: 0007 movs r7, r0 +100166ee: d01a beq.n 10016726 +100166f0: 2128 movs r1, #40 ; 0x28 +100166f2: 4658 mov r0, fp +100166f4: f7ff fdd5 bl 100162a2 +100166f8: 2801 cmp r0, #1 +100166fa: d00a beq.n 10016712 +100166fc: 9805 ldr r0, [sp, #20] +100166fe: b110 cbz r0, 10016706 +10016700: 2801 cmp r0, #1 +10016702: d002 beq.n 1001670a +10016704: e005 b.n 10016712 +10016706: 2120 movs r1, #32 +10016708: e000 b.n 1001670c +1001670a: 2108 movs r1, #8 +1001670c: 4658 mov r0, fp +1001670e: f7ff fdcf bl 100162b0 +10016712: f44f 705f mov.w r0, #892 ; 0x37c +10016716: f7fa f874 bl 10010802 +1001671a: 0006 movs r6, r0 +1001671c: d105 bne.n 1001672a +1001671e: 2120 movs r1, #32 +10016720: 4638 mov r0, r7 +10016722: f7fa f873 bl 1001080c +10016726: 2000 movs r0, #0 +10016728: e062 b.n 100167f0 +1001672a: f44f 725f mov.w r2, #892 ; 0x37c +1001672e: 2100 movs r1, #0 +10016730: f7fa f882 bl 10010838 +10016734: f10a 001c add.w r0, sl, #28 +10016738: f7ff fdb0 bl 1001629c +1001673c: 4602 mov r2, r0 +1001673e: f10a 011c add.w r1, sl, #28 +10016742: 4630 mov r0, r6 +10016744: f7fa f863 bl 1001080e +10016748: 2000 movs r0, #0 +1001674a: 67b0 str r0, [r6, #120] ; 0x78 +1001674c: f89b 042c ldrb.w r0, [fp, #1068] ; 0x42c +10016750: b930 cbnz r0, 10016760 +10016752: 2206 movs r2, #6 +10016754: f10a 0120 add.w r1, sl, #32 +10016758: f10b 0068 add.w r0, fp, #104 ; 0x68 +1001675c: f7fa f857 bl 1001080e +10016760: 69ab ldr r3, [r5, #24] +10016762: f106 027c add.w r2, r6, #124 ; 0x7c +10016766: 4649 mov r1, r9 +10016768: 4620 mov r0, r4 +1001676a: f008 ff14 bl 1001f596 +1001676e: 67b0 str r0, [r6, #120] ; 0x78 +10016770: 2000 movs r0, #0 +10016772: 9903 ldr r1, [sp, #12] +10016774: 6008 str r0, [r1, #0] +10016776: f898 0045 ldrb.w r0, [r8, #69] ; 0x45 +1001677a: b160 cbz r0, 10016796 +1001677c: 6fb0 ldr r0, [r6, #120] ; 0x78 +1001677e: f000 f840 bl 10016802 <.text_30> +10016782: f008 feda bl 1001f53a +10016786: 6fb1 ldr r1, [r6, #120] ; 0x78 +10016788: 4281 cmp r1, r0 +1001678a: bf1a itte ne +1001678c: 67b0 strne r0, [r6, #120] ; 0x78 +1001678e: 2001 movne r0, #1 +10016790: 2000 moveq r0, #0 +10016792: 9903 ldr r1, [sp, #12] +10016794: 6008 str r0, [r1, #0] +10016796: 2000 movs r0, #0 +10016798: 9906 ldr r1, [sp, #24] +1001679a: 6008 str r0, [r1, #0] +1001679c: f898 0050 ldrb.w r0, [r8, #80] ; 0x50 +100167a0: 2800 cmp r0, #0 +100167a2: bf1e ittt ne +100167a4: f241 10f4 movwne r0, #4596 ; 0x11f4 +100167a8: 5900 ldrne r0, [r0, r4] +100167aa: 2801 cmpne r0, #1 +100167ac: d009 beq.n 100167c2 +100167ae: 2805 cmp r0, #5 +100167b0: bf18 it ne +100167b2: 2802 cmpne r0, #2 +100167b4: d005 beq.n 100167c2 +100167b6: f106 0078 add.w r0, r6, #120 ; 0x78 +100167ba: f000 f822 bl 10016802 <.text_30> +100167be: f008 ff36 bl 1001f62e +100167c2: 69a9 ldr r1, [r5, #24] +100167c4: 4648 mov r0, r9 +100167c6: f00f fe92 bl 100264ee +100167ca: 9904 ldr r1, [sp, #16] +100167cc: f881 00ae strb.w r0, [r1, #174] ; 0xae +100167d0: 4630 mov r0, r6 +100167d2: f7ff fd63 bl 1001629c +100167d6: 60f8 str r0, [r7, #12] +100167d8: f000 f8ec bl 100169b4 <.text_35> +100167dc: 200e movs r0, #14 +100167de: 80b8 strh r0, [r7, #4] +100167e0: 60be str r6, [r7, #8] +100167e2: 2000 movs r0, #0 +100167e4: 6138 str r0, [r7, #16] +100167e6: 6178 str r0, [r7, #20] +100167e8: 4639 mov r1, r7 +100167ea: 9807 ldr r0, [sp, #28] +100167ec: f7ff fdc9 bl 10016382 +100167f0: b2c0 uxtb r0, r0 +100167f2: b009 add sp, #36 ; 0x24 +100167f4: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +100167f8 <.text_29>: +100167f8: 4602 mov r2, r0 +100167fa: 4631 mov r1, r6 +100167fc: 4620 mov r0, r4 +100167fe: f7fd bc9f b.w 10014140 + +10016802 <.text_30>: +10016802: 9000 str r0, [sp, #0] +10016804: f106 027c add.w r2, r6, #124 ; 0x7c +10016808: 69ab ldr r3, [r5, #24] +1001680a: 4649 mov r1, r9 +1001680c: 4620 mov r0, r4 +1001680e: 4770 bx lr + +10016810 : +10016810: b570 push {r4, r5, r6, lr} +10016812: f000 f938 bl 10016a86 <.text_42> +10016816: 0005 movs r5, r0 +10016818: d006 beq.n 10016828 +1001681a: 2004 movs r0, #4 +1001681c: f7f9 fff1 bl 10010802 +10016820: 0006 movs r6, r0 +10016822: d103 bne.n 1001682c +10016824: f000 f9e8 bl 10016bf8 <.text_48> +10016828: 2000 movs r0, #0 +1001682a: e007 b.n 1001683c +1001682c: f000 f8c6 bl 100169bc <.text_37> +10016830: 200f movs r0, #15 +10016832: 80a8 strh r0, [r5, #4] +10016834: 60ae str r6, [r5, #8] +10016836: 2004 movs r0, #4 +10016838: f000 f8c8 bl 100169cc <.text_39> +1001683c: b2c0 uxtb r0, r0 +1001683e: bd70 pop {r4, r5, r6, pc} + +10016840 : +10016840: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +10016844: b083 sub sp, #12 +10016846: 4604 mov r4, r0 +10016848: f604 00d8 addw r0, r4, #2264 ; 0x8d8 +1001684c: 9001 str r0, [sp, #4] +1001684e: f504 5788 add.w r7, r4, #4352 ; 0x1100 +10016852: f104 000c add.w r0, r4, #12 +10016856: 9000 str r0, [sp, #0] +10016858: 4688 mov r8, r1 +1001685a: 4691 mov r9, r2 +1001685c: 37f0 adds r7, #240 ; 0xf0 +1001685e: f000 f914 bl 10016a8a <.text_42+0x4> +10016862: 0005 movs r5, r0 +10016864: d05b beq.n 1001691e +10016866: 2018 movs r0, #24 +10016868: f7f9 ffcb bl 10010802 +1001686c: 0006 movs r6, r0 +1001686e: d102 bne.n 10016876 +10016870: 2120 movs r1, #32 +10016872: 4628 mov r0, r5 +10016874: e009 b.n 1001688a +10016876: 2008 movs r0, #8 +10016878: f7f9 ffc3 bl 10010802 +1001687c: ea5f 0a00 movs.w sl, r0 +10016880: d107 bne.n 10016892 +10016882: f000 f9b9 bl 10016bf8 <.text_48> +10016886: 2118 movs r1, #24 +10016888: 4630 mov r0, r6 +1001688a: f7f9 ffbf bl 1001080c +1001688e: 2000 movs r0, #0 +10016890: e045 b.n 1001691e +10016892: f000 f893 bl 100169bc <.text_37> +10016896: 2015 movs r0, #21 +10016898: 80a8 strh r0, [r5, #4] +1001689a: 60ae str r6, [r5, #8] +1001689c: 2018 movs r0, #24 +1001689e: 60e8 str r0, [r5, #12] +100168a0: f508 7b84 add.w fp, r8, #264 ; 0x108 +100168a4: 2000 movs r0, #0 +100168a6: 6128 str r0, [r5, #16] +100168a8: 6168 str r0, [r5, #20] +100168aa: f8c5 a010 str.w sl, [r5, #16] +100168ae: 2008 movs r0, #8 +100168b0: 6168 str r0, [r5, #20] +100168b2: 2206 movs r2, #6 +100168b4: 4659 mov r1, fp +100168b6: 4650 mov r0, sl +100168b8: f7f9 ffa9 bl 1001080e +100168bc: 2206 movs r2, #6 +100168be: 4659 mov r1, fp +100168c0: 4630 mov r0, r6 +100168c2: f7f9 ffa4 bl 1001080e +100168c6: 9800 ldr r0, [sp, #0] +100168c8: 2108 movs r1, #8 +100168ca: f7ff fcea bl 100162a2 +100168ce: b958 cbnz r0, 100168e8 +100168d0: 6838 ldr r0, [r7, #0] +100168d2: b148 cbz r0, 100168e8 +100168d4: 2802 cmp r0, #2 +100168d6: d004 beq.n 100168e2 +100168d8: d306 bcc.n 100168e8 +100168da: 2804 cmp r0, #4 +100168dc: d004 beq.n 100168e8 +100168de: d303 bcc.n 100168e8 +100168e0: e004 b.n 100168ec +100168e2: f8d8 0114 ldr.w r0, [r8, #276] ; 0x114 +100168e6: e000 b.n 100168ea +100168e8: 6878 ldr r0, [r7, #4] +100168ea: 71b0 strb r0, [r6, #6] +100168ec: f1b9 0f01 cmp.w r9, #1 +100168f0: d103 bne.n 100168fa +100168f2: 2210 movs r2, #16 +100168f4: f508 719c add.w r1, r8, #312 ; 0x138 +100168f8: e005 b.n 10016906 +100168fa: 6e38 ldr r0, [r7, #96] ; 0x60 +100168fc: eb07 1000 add.w r0, r7, r0, lsl #4 +10016900: 2210 movs r2, #16 +10016902: f100 0164 add.w r1, r0, #100 ; 0x64 +10016906: f106 0008 add.w r0, r6, #8 +1001690a: f7f9 ff80 bl 1001080e +1001690e: f241 5145 movw r1, #5445 ; 0x1545 +10016912: 2001 movs r0, #1 +10016914: 5508 strb r0, [r1, r4] +10016916: 4629 mov r1, r5 +10016918: 9801 ldr r0, [sp, #4] +1001691a: f7ff fd32 bl 10016382 +1001691e: b2c0 uxtb r0, r0 +10016920: e8bd 8ffe ldmia.w sp!, {r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +10016924 : +10016924: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +10016928: 460c mov r4, r1 +1001692a: 4615 mov r5, r2 +1001692c: f600 08d8 addw r8, r0, #2264 ; 0x8d8 +10016930: 2701 movs r7, #1 +10016932: b91b cbnz r3, 1001693c +10016934: 4629 mov r1, r5 +10016936: f00f f9d6 bl 10025ce6 +1001693a: e038 b.n 100169ae +1001693c: f000 f8a5 bl 10016a8a <.text_42+0x4> +10016940: 0007 movs r7, r0 +10016942: d015 beq.n 10016970 +10016944: 2018 movs r0, #24 +10016946: f7f9 ff5c bl 10010802 +1001694a: 0006 movs r6, r0 +1001694c: d102 bne.n 10016954 +1001694e: 2120 movs r1, #32 +10016950: 4638 mov r0, r7 +10016952: e00b b.n 1001696c +10016954: 2008 movs r0, #8 +10016956: f7f9 ff54 bl 10010802 +1001695a: ea5f 0900 movs.w r9, r0 +1001695e: d109 bne.n 10016974 +10016960: 2120 movs r1, #32 +10016962: 4638 mov r0, r7 +10016964: f7f9 ff52 bl 1001080c +10016968: 2118 movs r1, #24 +1001696a: 4630 mov r0, r6 +1001696c: f7f9 ff4e bl 1001080c +10016970: 2700 movs r7, #0 +10016972: e01c b.n 100169ae +10016974: f000 f81e bl 100169b4 <.text_35> +10016978: 2015 movs r0, #21 +1001697a: 80b8 strh r0, [r7, #4] +1001697c: 60be str r6, [r7, #8] +1001697e: 2018 movs r0, #24 +10016980: 60f8 str r0, [r7, #12] +10016982: 2000 movs r0, #0 +10016984: 6138 str r0, [r7, #16] +10016986: 6178 str r0, [r7, #20] +10016988: f8c7 9010 str.w r9, [r7, #16] +1001698c: 2008 movs r0, #8 +1001698e: 6178 str r0, [r7, #20] +10016990: b12c cbz r4, 1001699e +10016992: 2206 movs r2, #6 +10016994: f504 7184 add.w r1, r4, #264 ; 0x108 +10016998: 4630 mov r0, r6 +1001699a: f7f9 ff38 bl 1001080e +1001699e: 2000 movs r0, #0 +100169a0: 71b0 strb r0, [r6, #6] +100169a2: 71f5 strb r5, [r6, #7] +100169a4: 4639 mov r1, r7 +100169a6: 4640 mov r0, r8 +100169a8: f7ff fceb bl 10016382 +100169ac: 4607 mov r7, r0 +100169ae: b2f8 uxtb r0, r7 +100169b0: e8bd 83f2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, pc} + +100169b4 <.text_35>: +100169b4: f107 0018 add.w r0, r7, #24 +100169b8: f7f9 bf48 b.w 1001084c + +100169bc <.text_37>: +100169bc: f105 0018 add.w r0, r5, #24 +100169c0: f7f9 bf44 b.w 1001084c + +100169c4 <.text_38>: +100169c4: 2039 movs r0, #57 ; 0x39 +100169c6: 80a8 strh r0, [r5, #4] +100169c8: 60af str r7, [r5, #8] +100169ca: 200c movs r0, #12 + +100169cc <.text_39>: +100169cc: 60e8 str r0, [r5, #12] +100169ce: 4629 mov r1, r5 +100169d0: 2000 movs r0, #0 +100169d2: 6128 str r0, [r5, #16] +100169d4: 6168 str r0, [r5, #20] +100169d6: 4620 mov r0, r4 +100169d8: e4d3 b.n 10016382 + +100169da : +100169da: b5f8 push {r3, r4, r5, r6, r7, lr} +100169dc: 4606 mov r6, r0 +100169de: f606 04d8 addw r4, r6, #2264 ; 0x8d8 +100169e2: f000 f852 bl 10016a8a <.text_42+0x4> +100169e6: 0005 movs r5, r0 +100169e8: d005 beq.n 100169f6 +100169ea: f000 f90f bl 10016c0c <.text_51> +100169ee: 0007 movs r7, r0 +100169f0: d103 bne.n 100169fa +100169f2: f000 f901 bl 10016bf8 <.text_48> +100169f6: 2000 movs r0, #0 +100169f8: e008 b.n 10016a0c +100169fa: 2001 movs r0, #1 +100169fc: 6038 str r0, [r7, #0] +100169fe: 2000 movs r0, #0 +10016a00: 6078 str r0, [r7, #4] +10016a02: 60be str r6, [r7, #8] +10016a04: f7ff ffda bl 100169bc <.text_37> +10016a08: f7ff ffdc bl 100169c4 <.text_38> +10016a0c: b2c0 uxtb r0, r0 +10016a0e: bdf2 pop {r1, r4, r5, r6, r7, pc} + +10016a10 : +10016a10: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +10016a14: 460d mov r5, r1 +10016a16: 2401 movs r4, #1 +10016a18: 4680 mov r8, r0 +10016a1a: 2d59 cmp r5, #89 ; 0x59 +10016a1c: 4617 mov r7, r2 +10016a1e: f608 09d8 addw r9, r8, #2264 ; 0x8d8 +10016a22: db01 blt.n 10016a28 +10016a24: 2d7f cmp r5, #127 ; 0x7f +10016a26: d104 bne.n 10016a32 +10016a28: 2001 movs r0, #1 +10016a2a: f7f9 feea bl 10010802 +10016a2e: 0006 movs r6, r0 +10016a30: d101 bne.n 10016a36 +10016a32: 2400 movs r4, #0 +10016a34: e024 b.n 10016a80 +10016a36: 7035 strb r5, [r6, #0] +10016a38: b1af cbz r7, 10016a66 +10016a3a: f000 f826 bl 10016a8a <.text_42+0x4> +10016a3e: 0007 movs r7, r0 +10016a40: d102 bne.n 10016a48 +10016a42: f000 f825 bl 10016a90 <.text_43> +10016a46: e7f4 b.n 10016a32 +10016a48: f7ff ffb4 bl 100169b4 <.text_35> +10016a4c: 203b movs r0, #59 ; 0x3b +10016a4e: 80b8 strh r0, [r7, #4] +10016a50: 60be str r6, [r7, #8] +10016a52: 60fc str r4, [r7, #12] +10016a54: 2000 movs r0, #0 +10016a56: 6138 str r0, [r7, #16] +10016a58: 6178 str r0, [r7, #20] +10016a5a: 4639 mov r1, r7 +10016a5c: 4648 mov r0, r9 +10016a5e: f7ff fc90 bl 10016382 +10016a62: 4604 mov r4, r0 +10016a64: e007 b.n 10016a76 +10016a66: 4631 mov r1, r6 +10016a68: 4640 mov r0, r8 +10016a6a: f007 fb59 bl 1001e120 +10016a6e: b100 cbz r0, 10016a72 +10016a70: 2400 movs r4, #0 +10016a72: f000 f80d bl 10016a90 <.text_43> +10016a76: b2e4 uxtb r4, r4 +10016a78: 2c01 cmp r4, #1 +10016a7a: bf08 it eq +10016a7c: f888 549e strbeq.w r5, [r8, #1182] ; 0x49e +10016a80: 4620 mov r0, r4 +10016a82: e8bd 83f2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, pc} + +10016a86 <.text_42>: +10016a86: f600 04d8 addw r4, r0, #2264 ; 0x8d8 +10016a8a: 2020 movs r0, #32 +10016a8c: f7f9 beb9 b.w 10010802 + +10016a90 <.text_43>: +10016a90: 2101 movs r1, #1 +10016a92: 4630 mov r0, r6 +10016a94: f7f9 beba b.w 1001080c + +10016a98 : +10016a98: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +10016a9c: 4680 mov r8, r0 +10016a9e: 2500 movs r5, #0 +10016aa0: f108 000c add.w r0, r8, #12 +10016aa4: 2600 movs r6, #0 +10016aa6: 46ab mov fp, r5 +10016aa8: 462c mov r4, r5 +10016aaa: 46a9 mov r9, r5 +10016aac: 46aa mov sl, r5 +10016aae: 9000 str r0, [sp, #0] +10016ab0: f500 678e add.w r7, r0, #1136 ; 0x470 +10016ab4: 2101 movs r1, #1 +10016ab6: f7ff fbf4 bl 100162a2 +10016aba: 2801 cmp r0, #1 +10016abc: d121 bne.n 10016b02 +10016abe: 9900 ldr r1, [sp, #0] +10016ac0: 6878 ldr r0, [r7, #4] +10016ac2: f8d1 1470 ldr.w r1, [r1, #1136] ; 0x470 +10016ac6: 2865 cmp r0, #101 ; 0x65 +10016ac8: bf38 it cc +10016aca: 2965 cmpcc r1, #101 ; 0x65 +10016acc: f640 72a1 movw r2, #4001 ; 0xfa1 +10016ad0: d306 bcc.n 10016ae0 +10016ad2: 2501 movs r5, #1 +10016ad4: 4281 cmp r1, r0 +10016ad6: bf34 ite cc +10016ad8: 46ab movcc fp, r5 +10016ada: 2601 movcs r6, #1 +10016adc: 4290 cmp r0, r2 +10016ade: d201 bcs.n 10016ae4 +10016ae0: 4291 cmp r1, r2 +10016ae2: d304 bcc.n 10016aee +10016ae4: 2401 movs r4, #1 +10016ae6: 4281 cmp r1, r0 +10016ae8: bf34 ite cc +10016aea: 46a1 movcc r9, r4 +10016aec: 46a2 movcs sl, r4 +10016aee: 68b8 ldr r0, [r7, #8] +10016af0: 1809 adds r1, r1, r0 +10016af2: 2909 cmp r1, #9 +10016af4: bf38 it cc +10016af6: 2803 cmpcc r0, #3 +10016af8: d203 bcs.n 10016b02 +10016afa: 4640 mov r0, r8 +10016afc: f009 f9cc bl 1001fe98 +10016b00: e002 b.n 10016b08 +10016b02: 4640 mov r0, r8 +10016b04: f009 f9f5 bl 1001fef2 +10016b08: 2000 movs r0, #0 +10016b0a: 6078 str r0, [r7, #4] +10016b0c: 9900 ldr r1, [sp, #0] +10016b0e: f8c1 0470 str.w r0, [r1, #1136] ; 0x470 +10016b12: 60b8 str r0, [r7, #8] +10016b14: 733d strb r5, [r7, #12] +10016b16: 737e strb r6, [r7, #13] +10016b18: f887 b00e strb.w fp, [r7, #14] +10016b1c: 73fc strb r4, [r7, #15] +10016b1e: f887 9010 strb.w r9, [r7, #16] +10016b22: f887 a011 strb.w sl, [r7, #17] +10016b26: e8bd 8ff1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +10016b2a : +10016b2a: b510 push {r4, lr} +10016b2c: 460c mov r4, r1 +10016b2e: 4620 mov r0, r4 +10016b30: f006 fd33 bl 1001d59a +10016b34: 4620 mov r0, r4 +10016b36: f7ff ffaf bl 10016a98 +10016b3a: 4620 mov r0, r4 +10016b3c: e8bd 4010 ldmia.w sp!, {r4, lr} +10016b40: f000 bd04 b.w 1001754c + +10016b44 : +10016b44: b5f8 push {r3, r4, r5, r6, r7, lr} +10016b46: 4604 mov r4, r0 +10016b48: 460d mov r5, r1 +10016b4a: f504 56c8 add.w r6, r4, #6400 ; 0x1900 +10016b4e: f104 070c add.w r7, r4, #12 +10016b52: 360c adds r6, #12 +10016b54: 2140 movs r1, #64 ; 0x40 +10016b56: 4638 mov r0, r7 +10016b58: f7ff fba3 bl 100162a2 +10016b5c: 2801 cmp r0, #1 +10016b5e: d02d beq.n 10016bbc +10016b60: 2120 movs r1, #32 +10016b62: 4638 mov r0, r7 +10016b64: f7ff fb9d bl 100162a2 +10016b68: 2801 cmp r0, #1 +10016b6a: d027 beq.n 10016bbc +10016b6c: 2d05 cmp r5, #5 +10016b6e: d825 bhi.n 10016bbc +10016b70: e8df f005 tbb [pc, r5] +10016b74: 120a2103 .word 0x120a2103 +10016b78: 211e .short 0x211e +10016b7a: 2101 movs r1, #1 +10016b7c: 4638 mov r0, r7 +10016b7e: f7ff fb90 bl 100162a2 +10016b82: 2801 cmp r0, #1 +10016b84: d11a bne.n 10016bbc +10016b86: e016 b.n 10016bb6 +10016b88: 2001 movs r0, #1 +10016b8a: f88d 0000 strb.w r0, [sp] +10016b8e: f641 1146 movw r1, #6470 ; 0x1946 +10016b92: 2000 movs r0, #0 +10016b94: 5508 strb r0, [r1, r4] +10016b96: e005 b.n 10016ba4 +10016b98: 2000 movs r0, #0 +10016b9a: f88d 0000 strb.w r0, [sp] +10016b9e: 4620 mov r0, r4 +10016ba0: f009 f9a7 bl 1001fef2 +10016ba4: aa00 add r2, sp, #0 +10016ba6: 212b movs r1, #43 ; 0x2b +10016ba8: 4620 mov r0, r4 +10016baa: f000 fbb1 bl 10017310 +10016bae: bdf1 pop {r0, r4, r5, r6, r7, pc} +10016bb0: f7f9 feed bl 1001098e +10016bb4: 6430 str r0, [r6, #64] ; 0x40 +10016bb6: 4620 mov r0, r4 +10016bb8: f009 f99b bl 1001fef2 +10016bbc: bdf1 pop {r0, r4, r5, r6, r7, pc} + +10016bbe : +10016bbe: b5f8 push {r3, r4, r5, r6, r7, lr} +10016bc0: 460e mov r6, r1 +10016bc2: f600 04d8 addw r4, r0, #2264 ; 0x8d8 +10016bc6: 2501 movs r5, #1 +10016bc8: b192 cbz r2, 10016bf0 +10016bca: f7ff ff5e bl 10016a8a <.text_42+0x4> +10016bce: 0005 movs r5, r0 +10016bd0: d005 beq.n 10016bde +10016bd2: f000 f81b bl 10016c0c <.text_51> +10016bd6: 0007 movs r7, r0 +10016bd8: d103 bne.n 10016be2 +10016bda: f000 f80d bl 10016bf8 <.text_48> +10016bde: 2500 movs r5, #0 +10016be0: e008 b.n 10016bf4 +10016be2: 2005 movs r0, #5 +10016be4: f000 f815 bl 10016c12 <.text_52> +10016be8: f7ff feec bl 100169c4 <.text_38> +10016bec: 4605 mov r5, r0 +10016bee: e001 b.n 10016bf4 +10016bf0: f7ff ffa8 bl 10016b44 +10016bf4: b2e8 uxtb r0, r5 +10016bf6: bdf2 pop {r1, r4, r5, r6, r7, pc} + +10016bf8 <.text_48>: +10016bf8: 2120 movs r1, #32 +10016bfa: 4628 mov r0, r5 +10016bfc: f7f9 be06 b.w 1001080c + +10016c00 : +10016c00: b502 push {r1, lr} +10016c02: aa00 add r2, sp, #0 +10016c04: 2143 movs r1, #67 ; 0x43 +10016c06: f000 fb83 bl 10017310 +10016c0a: bd01 pop {r0, pc} + +10016c0c <.text_51>: +10016c0c: 200c movs r0, #12 +10016c0e: f7f9 bdf8 b.w 10010802 + +10016c12 <.text_52>: +10016c12: 6038 str r0, [r7, #0] +10016c14: 607e str r6, [r7, #4] +10016c16: 2000 movs r0, #0 +10016c18: 60b8 str r0, [r7, #8] +10016c1a: f105 0018 add.w r0, r5, #24 +10016c1e: f7f9 be15 b.w 1001084c + +10016c22 : +10016c22: b570 push {r4, r5, r6, lr} +10016c24: 4601 mov r1, r0 +10016c26: f641 5251 movw r2, #7505 ; 0x1d51 +10016c2a: f601 04d8 addw r4, r1, #2264 ; 0x8d8 +10016c2e: 5c51 ldrb r1, [r2, r1] +10016c30: 2001 movs r0, #1 +10016c32: b9b1 cbnz r1, 10016c62 +10016c34: f7ff ff29 bl 10016a8a <.text_42+0x4> +10016c38: 0005 movs r5, r0 +10016c3a: d005 beq.n 10016c48 +10016c3c: f7ff ffe6 bl 10016c0c <.text_51> +10016c40: 0006 movs r6, r0 +10016c42: d103 bne.n 10016c4c +10016c44: f7ff ffd8 bl 10016bf8 <.text_48> +10016c48: 2000 movs r0, #0 +10016c4a: e00a b.n 10016c62 +10016c4c: 2004 movs r0, #4 +10016c4e: 6030 str r0, [r6, #0] +10016c50: 2000 movs r0, #0 +10016c52: 60b0 str r0, [r6, #8] +10016c54: f7ff feb2 bl 100169bc <.text_37> +10016c58: 2039 movs r0, #57 ; 0x39 +10016c5a: 80a8 strh r0, [r5, #4] +10016c5c: 60ae str r6, [r5, #8] +10016c5e: f7ff feb4 bl 100169ca <.text_38+0x6> +10016c62: b2c0 uxtb r0, r0 +10016c64: bd70 pop {r4, r5, r6, pc} + +10016c66 : +10016c66: b570 push {r4, r5, r6, lr} +10016c68: f7ff ff0d bl 10016a86 <.text_42> +10016c6c: 0005 movs r5, r0 +10016c6e: d005 beq.n 10016c7c +10016c70: f7ff ffcc bl 10016c0c <.text_51> +10016c74: 0006 movs r6, r0 +10016c76: d103 bne.n 10016c80 +10016c78: f7ff ffbe bl 10016bf8 <.text_48> +10016c7c: 2000 movs r0, #0 +10016c7e: e007 b.n 10016c90 +10016c80: 2008 movs r0, #8 +10016c82: f000 f807 bl 10016c94 <.text_57> +10016c86: 2039 movs r0, #57 ; 0x39 +10016c88: 80a8 strh r0, [r5, #4] +10016c8a: 60ae str r6, [r5, #8] +10016c8c: f7ff fe9d bl 100169ca <.text_38+0x6> +10016c90: b2c0 uxtb r0, r0 +10016c92: bd70 pop {r4, r5, r6, pc} + +10016c94 <.text_57>: +10016c94: 6030 str r0, [r6, #0] +10016c96: 2000 movs r0, #0 +10016c98: 6070 str r0, [r6, #4] +10016c9a: 60b0 str r0, [r6, #8] +10016c9c: f105 0018 add.w r0, r5, #24 +10016ca0: f7f9 bdd4 b.w 1001084c + +10016ca4 : +10016ca4: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +10016ca8: 4605 mov r5, r0 +10016caa: 000c movs r4, r1 +10016cac: b082 sub sp, #8 +10016cae: bf08 it eq +10016cb0: 2004 moveq r0, #4 +10016cb2: d069 beq.n 10016d88 +10016cb4: 6820 ldr r0, [r4, #0] +10016cb6: 2801 cmp r0, #1 +10016cb8: d00a beq.n 10016cd0 +10016cba: 2804 cmp r0, #4 +10016cbc: d00e beq.n 10016cdc +10016cbe: 2805 cmp r0, #5 +10016cc0: d010 beq.n 10016ce4 +10016cc2: 2808 cmp r0, #8 +10016cc4: d01a beq.n 10016cfc +10016cc6: 280a cmp r0, #10 +10016cc8: d051 beq.n 10016d6e +10016cca: 280b cmp r0, #11 +10016ccc: d010 beq.n 10016cf0 +10016cce: e053 b.n 10016d78 +10016cd0: 6862 ldr r2, [r4, #4] +10016cd2: 68a1 ldr r1, [r4, #8] +10016cd4: 4628 mov r0, r5 +10016cd6: f7ff ff28 bl 10016b2a +10016cda: e04d b.n 10016d78 +10016cdc: 4628 mov r0, r5 +10016cde: f009 f80f bl 1001fd00 +10016ce2: e049 b.n 10016d78 +10016ce4: 6861 ldr r1, [r4, #4] +10016ce6: b2c9 uxtb r1, r1 +10016ce8: 4628 mov r0, r5 +10016cea: f7ff ff2b bl 10016b44 +10016cee: e043 b.n 10016d78 +10016cf0: 6861 ldr r1, [r4, #4] +10016cf2: b289 uxth r1, r1 +10016cf4: 4628 mov r0, r5 +10016cf6: f7ff ff83 bl 10016c00 +10016cfa: e03d b.n 10016d78 +10016cfc: f505 5688 add.w r6, r5, #4352 ; 0x1100 +10016d00: 2700 movs r7, #0 +10016d02: 3628 adds r6, #40 ; 0x28 +10016d04: 4628 mov r0, r5 +10016d06: f00e fa97 bl 10025238 +10016d0a: ea5f 0800 movs.w r8, r0 +10016d0e: d033 beq.n 10016d78 +10016d10: f8d8 00f4 ldr.w r0, [r8, #244] ; 0xf4 +10016d14: bb80 cbnz r0, 10016d78 +10016d16: f88d 0000 strb.w r0, [sp] +10016d1a: aa00 add r2, sp, #0 +10016d1c: 2146 movs r1, #70 ; 0x46 +10016d1e: 4628 mov r0, r5 +10016d20: f000 fb00 bl 10017324 +10016d24: f89d 0000 ldrb.w r0, [sp] +10016d28: b928 cbnz r0, 10016d36 +10016d2a: 2064 movs r0, #100 ; 0x64 +10016d2c: f7f9 fe5f bl 100109ee +10016d30: 1c7f adds r7, r7, #1 +10016d32: 2f0b cmp r7, #11 +10016d34: dbf1 blt.n 10016d1a +10016d36: 2f0b cmp r7, #11 +10016d38: da15 bge.n 10016d66 +10016d3a: f8d8 00f4 ldr.w r0, [r8, #244] ; 0xf4 +10016d3e: b958 cbnz r0, 10016d58 +10016d40: f106 00c0 add.w r0, r6, #192 ; 0xc0 +10016d44: f64f 72fe movw r2, #65534 ; 0xfffe +10016d48: 8841 ldrh r1, [r0, #2] +10016d4a: 4011 ands r1, r2 +10016d4c: 8041 strh r1, [r0, #2] +10016d4e: f8b6 00c0 ldrh.w r0, [r6, #192] ; 0xc0 +10016d52: 4010 ands r0, r2 +10016d54: f8a6 00c0 strh.w r0, [r6, #192] ; 0xc0 +10016d58: 2300 movs r3, #0 +10016d5a: 2200 movs r2, #0 +10016d5c: 2105 movs r1, #5 +10016d5e: 4628 mov r0, r5 +10016d60: f002 f9ce bl 10019100 +10016d64: e008 b.n 10016d78 +10016d66: 4628 mov r0, r5 +10016d68: f7ff ff7d bl 10016c66 +10016d6c: e004 b.n 10016d78 +10016d6e: 2200 movs r2, #0 +10016d70: 2142 movs r1, #66 ; 0x42 +10016d72: 4628 mov r0, r5 +10016d74: f000 facc bl 10017310 +10016d78: 68a0 ldr r0, [r4, #8] +10016d7a: b120 cbz r0, 10016d86 +10016d7c: 6861 ldr r1, [r4, #4] +10016d7e: 2901 cmp r1, #1 +10016d80: bfa8 it ge +10016d82: f7f9 fd43 blge 1001080c +10016d86: 2000 movs r0, #0 +10016d88: e8bd 81f6 ldmia.w sp!, {r1, r2, r4, r5, r6, r7, r8, pc} + +10016d8c : +10016d8c: b510 push {r4, lr} +10016d8e: 460c mov r4, r1 +10016d90: 300c adds r0, #12 +10016d92: 79a1 ldrb r1, [r4, #6] +10016d94: 2903 cmp r1, #3 +10016d96: f500 6086 add.w r0, r0, #1072 ; 0x430 +10016d9a: e01d b.n 10016dd8 <.text_62> + +10016d9c : +10016d9c: b510 push {r4, lr} +10016d9e: b082 sub sp, #8 +10016da0: f100 040c add.w r4, r0, #12 +10016da4: 7988 ldrb r0, [r1, #6] +10016da6: b160 cbz r0, 10016dc2 +10016da8: a900 add r1, sp, #0 +10016daa: 4620 mov r0, r4 +10016dac: f7f9 fdb2 bl 10010914 +10016db0: 2101 movs r1, #1 +10016db2: 4620 mov r0, r4 +10016db4: f7ff fa7c bl 100162b0 +10016db8: a900 add r1, sp, #0 +10016dba: 4620 mov r0, r4 +10016dbc: f7f9 fdab bl 10010916 +10016dc0: bd13 pop {r0, r1, r4, pc} +10016dc2: 4608 mov r0, r1 +10016dc4: f7ff fb0a bl 100163dc +10016dc8: bd13 pop {r0, r1, r4, pc} + +10016dca : +10016dca: b510 push {r4, lr} +10016dcc: 460c mov r4, r1 +10016dce: 300c adds r0, #12 +10016dd0: 79a1 ldrb r1, [r4, #6] +10016dd2: 2903 cmp r1, #3 +10016dd4: f500 6084 add.w r0, r0, #1056 ; 0x420 + +10016dd8 <.text_62>: +10016dd8: d000 beq.n 10016ddc <.text_62+0x4> +10016dda: b111 cbz r1, 10016de2 <.text_62+0xa> +10016ddc: 2101 movs r1, #1 +10016dde: f7f9 fe2c bl 10010a3a +10016de2: 4620 mov r0, r4 +10016de4: e8bd 4010 ldmia.w sp!, {r4, lr} +10016de8: f7ff baf8 b.w 100163dc + +10016dec : +10016dec: b510 push {r4, lr} +10016dee: 460c mov r4, r1 +10016df0: f500 5088 add.w r0, r0, #4352 ; 0x1100 +10016df4: 6921 ldr r1, [r4, #16] +10016df6: 3028 adds r0, #40 ; 0x28 +10016df8: f00e f9d8 bl 100251ac +10016dfc: e7f1 b.n 10016de2 <.text_62+0xa> + ... + +10016e00 : +10016e00: 5452 5f57 4d43 5f44 4854 4552 4441 0000 RTW_CMD_THREAD.. + +10016e10 : + ... +10016e18: 0001 0000 0000 0000 0002 0000 0000 0000 ................ +10016e28: 0003 0000 0000 0000 0004 0000 0000 0000 ................ +10016e38: 0005 0000 0000 0000 0006 0000 0000 0000 ................ +10016e48: 0007 0000 0000 0000 0008 0000 0000 0000 ................ +10016e58: 0009 0000 0000 0000 000a 0000 0000 0000 ................ +10016e68: 000b 0000 0000 0000 000c 0000 0000 0000 ................ +10016e78: 000d 0000 0000 0000 000e 0000 6dcb 1001 .............m.. +10016e88: 000f 0000 6d9d 1001 0010 0000 0000 0000 .....m.......... +10016e98: 0011 0000 0000 0000 0012 0000 6d8d 1001 .............m.. +10016ea8: 0013 0000 0000 0000 0014 0000 0000 0000 ................ +10016eb8: 0015 0000 6ded 1001 0016 0000 0000 0000 .....m.......... +10016ec8: 0017 0000 0000 0000 0018 0000 0000 0000 ................ +10016ed8: 0019 0000 0000 0000 001a 0000 0000 0000 ................ +10016ee8: 001b 0000 0000 0000 001c 0000 0000 0000 ................ +10016ef8: 001d 0000 0000 0000 001e 0000 0000 0000 ................ +10016f08: 001f 0000 0000 0000 0020 0000 0000 0000 ........ ....... +10016f18: 0021 0000 0000 0000 0022 0000 0000 0000 !......."....... +10016f28: 0023 0000 0000 0000 0024 0000 0000 0000 #.......$....... +10016f38: 0025 0000 0000 0000 0026 0000 0000 0000 %.......&....... +10016f48: 0027 0000 0000 0000 0028 0000 0000 0000 '.......(....... +10016f58: 0029 0000 0000 0000 002a 0000 0000 0000 ).......*....... +10016f68: 002b 0000 0000 0000 002c 0000 0000 0000 +.......,....... +10016f78: 002d 0000 0000 0000 002e 0000 0000 0000 -............... +10016f88: 002f 0000 0000 0000 0030 0000 0000 0000 /.......0....... +10016f98: 0031 0000 0000 0000 0032 0000 0000 0000 1.......2....... +10016fa8: 0033 0000 0000 0000 0034 0000 0000 0000 3.......4....... +10016fb8: 0035 0000 0000 0000 0036 0000 0000 0000 5.......6....... +10016fc8: 0037 0000 0000 0000 0038 0000 0000 0000 7.......8....... +10016fd8: 0039 0000 0000 0000 003a 0000 0000 0000 9.......:....... +10016fe8: 003b 0000 0000 0000 003c 0000 0000 0000 ;.......<....... +10016ff8: 003d 0000 0000 0000 003e 0000 0000 0000 =.......>....... + +10017008 : +10017008: 0000 0000 d8d7 1001 0000 0000 d8d7 1001 ................ +10017018: 0000 0000 d8d7 1001 0000 0000 d8d7 1001 ................ +10017028: 0000 0000 d8d7 1001 0000 0000 d8d7 1001 ................ + ... +10017078: 037c 0000 d917 1001 0004 0000 da6b 1001 |...........k... +10017088: 037c 0000 0000 0000 0004 0000 d8db 1001 |............... +10017098: 0030 0000 db13 1001 0004 0000 dbfb 1001 0............... +100170a8: 0014 0000 dc09 1001 0018 0000 dc55 1001 ............U... +100170b8: 0006 0000 0000 0000 0006 0000 0000 0000 ................ +100170c8: 0008 0000 0000 0000 000d 0000 0000 0000 ................ +100170d8: 0004 0000 0000 0000 000e 0000 0000 0000 ................ +100170e8: 0004 0000 0000 0000 0038 0000 0000 0000 ........8....... +100170f8: 0004 0000 0000 0000 0002 0000 0000 0000 ................ +10017108: 0004 0000 0000 0000 0000 0000 0000 0000 ................ + ... +10017170: 000c 0000 0000 0000 0000 0000 0000 0000 ................ + ... +100171c0: 037c 0000 de01 1001 0000 0000 ddb1 1001 |............... +100171d0: 0000 0000 6ca5 1001 0000 0000 0000 0000 .....l.......... +100171e0: 0001 0000 0000 0000 0000 0000 0000 0000 ................ +100171f0: 0001 0000 0000 0000 0007 0000 0000 0000 ................ + +10017200 : +10017200: f641 5151 movw r1, #7505 ; 0x1d51 +10017204: 5c09 ldrb r1, [r1, r0] +10017206: b929 cbnz r1, 10017214 <__iar_annotation$$tailcall+0x2> +10017208: f641 31f4 movw r1, #7156 ; 0x1bf4 +1001720c: 5809 ldr r1, [r1, r0] +1001720e: 000a movs r2, r1 +10017210: bf18 it ne + +10017212 <__iar_annotation$$tailcall>: +10017212: 4708 bxne r1 +10017214: 4770 bx lr + +10017216 : +10017216: f641 5151 movw r1, #7505 ; 0x1d51 +1001721a: 5c09 ldrb r1, [r1, r0] +1001721c: b929 cbnz r1, 1001722a <__iar_annotation$$tailcall+0x2> +1001721e: f641 31f8 movw r1, #7160 ; 0x1bf8 +10017222: 5809 ldr r1, [r1, r0] +10017224: 000a movs r2, r1 +10017226: bf18 it ne + +10017228 <__iar_annotation$$tailcall>: +10017228: 4708 bxne r1 +1001722a: 4770 bx lr + +1001722c : +1001722c: f641 5151 movw r1, #7505 ; 0x1d51 +10017230: 5c09 ldrb r1, [r1, r0] +10017232: b929 cbnz r1, 10017240 <__iar_annotation$$tailcall+0x2> +10017234: f641 31ec movw r1, #7148 ; 0x1bec +10017238: 5809 ldr r1, [r1, r0] +1001723a: 000a movs r2, r1 +1001723c: bf18 it ne + +1001723e <__iar_annotation$$tailcall>: +1001723e: 4708 bxne r1 +10017240: 4770 bx lr + +10017242 : +10017242: f641 5151 movw r1, #7505 ; 0x1d51 +10017246: 5c09 ldrb r1, [r1, r0] +10017248: b929 cbnz r1, 10017256 <__iar_annotation$$tailcall+0x2> +1001724a: f641 31f0 movw r1, #7152 ; 0x1bf0 +1001724e: 5809 ldr r1, [r1, r0] +10017250: 000a movs r2, r1 +10017252: bf18 it ne + +10017254 <__iar_annotation$$tailcall>: +10017254: 4708 bxne r1 +10017256: 4770 bx lr + +10017258 : +10017258: f641 5151 movw r1, #7505 ; 0x1d51 +1001725c: 5c09 ldrb r1, [r1, r0] +1001725e: b929 cbnz r1, 1001726c <__iar_annotation$$tailcall+0x2> +10017260: f641 31b8 movw r1, #7096 ; 0x1bb8 +10017264: 5809 ldr r1, [r1, r0] +10017266: 000a movs r2, r1 +10017268: bf18 it ne + +1001726a <__iar_annotation$$tailcall>: +1001726a: 4708 bxne r1 +1001726c: 4770 bx lr + +1001726e : +1001726e: f641 5151 movw r1, #7505 ; 0x1d51 +10017272: 5c09 ldrb r1, [r1, r0] +10017274: b929 cbnz r1, 10017282 <__iar_annotation$$tailcall+0x2> +10017276: f641 31e4 movw r1, #7140 ; 0x1be4 +1001727a: 5809 ldr r1, [r1, r0] +1001727c: 000a movs r2, r1 +1001727e: bf18 it ne + +10017280 <__iar_annotation$$tailcall>: +10017280: 4708 bxne r1 +10017282: 4770 bx lr + +10017284 : +10017284: f641 5151 movw r1, #7505 ; 0x1d51 +10017288: 5c09 ldrb r1, [r1, r0] +1001728a: b929 cbnz r1, 10017298 <__iar_annotation$$tailcall+0x2> +1001728c: f641 31e8 movw r1, #7144 ; 0x1be8 +10017290: 5809 ldr r1, [r1, r0] +10017292: 000a movs r2, r1 +10017294: bf18 it ne + +10017296 <__iar_annotation$$tailcall>: +10017296: 4708 bxne r1 +10017298: 4770 bx lr + +1001729a : +1001729a: f641 5151 movw r1, #7505 ; 0x1d51 +1001729e: 5c09 ldrb r1, [r1, r0] +100172a0: b929 cbnz r1, 100172ae <__iar_annotation$$tailcall+0x2> +100172a2: f500 51df add.w r1, r0, #7136 ; 0x1be0 +100172a6: 6809 ldr r1, [r1, #0] +100172a8: 000a movs r2, r1 +100172aa: bf18 it ne + +100172ac <__iar_annotation$$tailcall>: +100172ac: 4708 bxne r1 +100172ae: 4770 bx lr + +100172b0 : +100172b0: b570 push {r4, r5, r6, lr} +100172b2: 4604 mov r4, r0 +100172b4: f641 45b5 movw r5, #7349 ; 0x1cb5 +100172b8: 2000 movs r0, #0 +100172ba: 5528 strb r0, [r5, r4] +100172bc: f641 31b0 movw r1, #7088 ; 0x1bb0 +100172c0: 4620 mov r0, r4 +100172c2: 5909 ldr r1, [r1, r4] +100172c4: 4788 blx r1 +100172c6: 4606 mov r6, r0 +100172c8: 2e01 cmp r6, #1 +100172ca: d110 bne.n 100172ee +100172cc: 5528 strb r0, [r5, r4] +100172ce: f504 50c8 add.w r0, r4, #6400 ; 0x1900 +100172d2: 7800 ldrb r0, [r0, #0] +100172d4: 2801 cmp r0, #1 +100172d6: d103 bne.n 100172e0 +100172d8: 2101 movs r1, #1 +100172da: 4620 mov r0, r4 +100172dc: f000 f93d bl 1001755a +100172e0: 4620 mov r0, r4 +100172e2: f000 f941 bl 10017568 +100172e6: 4620 mov r0, r4 +100172e8: f00f febe bl 10027068 +100172ec: e001 b.n 100172f2 +100172ee: 2000 movs r0, #0 +100172f0: 5528 strb r0, [r5, r4] +100172f2: 4630 mov r0, r6 +100172f4: bd70 pop {r4, r5, r6, pc} + +100172f6 : +100172f6: b510 push {r4, lr} +100172f8: 4604 mov r4, r0 +100172fa: f641 31b4 movw r1, #7092 ; 0x1bb4 +100172fe: 5909 ldr r1, [r1, r4] +10017300: 4788 blx r1 +10017302: 2801 cmp r0, #1 +10017304: d103 bne.n 1001730e +10017306: f641 42b5 movw r2, #7349 ; 0x1cb5 +1001730a: 2100 movs r1, #0 +1001730c: 5511 strb r1, [r2, r4] +1001730e: bd10 pop {r4, pc} + +10017310 : +10017310: b510 push {r4, lr} +10017312: f641 431c movw r3, #7196 ; 0x1c1c +10017316: 581b ldr r3, [r3, r0] +10017318: 001c movs r4, r3 +1001731a: bf1c itt ne +1001731c: e8bd 4010 ldmiane.w sp!, {r4, lr} + +10017320 <__iar_annotation$$tailcall>: +10017320: 4718 bxne r3 +10017322: bd10 pop {r4, pc} + +10017324 : +10017324: b510 push {r4, lr} +10017326: f500 53e1 add.w r3, r0, #7200 ; 0x1c20 +1001732a: 681b ldr r3, [r3, #0] +1001732c: 001c movs r4, r3 +1001732e: bf1c itt ne +10017330: e8bd 4010 ldmiane.w sp!, {r4, lr} + +10017334 <__iar_annotation$$tailcall>: +10017334: 4718 bxne r3 +10017336: bd10 pop {r4, pc} + +10017338 : +10017338: b510 push {r4, lr} +1001733a: f641 4328 movw r3, #7208 ; 0x1c28 +1001733e: 581b ldr r3, [r3, r0] +10017340: 001c movs r4, r3 +10017342: bf1c itt ne +10017344: e8bd 4010 ldmiane.w sp!, {r4, lr} + +10017348 <__iar_annotation$$tailcall>: +10017348: 4718 bxne r3 +1001734a: 2000 movs r0, #0 +1001734c: bd10 pop {r4, pc} + +1001734e : +1001734e: b510 push {r4, lr} +10017350: f641 4324 movw r3, #7204 ; 0x1c24 +10017354: 581b ldr r3, [r3, r0] +10017356: 001c movs r4, r3 +10017358: bf1c itt ne +1001735a: e8bd 4010 ldmiane.w sp!, {r4, lr} + +1001735e <__iar_annotation$$tailcall>: +1001735e: 4718 bxne r3 +10017360: 2000 movs r0, #0 +10017362: bd10 pop {r4, pc} + +10017364 : +10017364: b538 push {r3, r4, r5, lr} +10017366: f641 4430 movw r4, #7216 ; 0x1c30 +1001736a: 5824 ldr r4, [r4, r0] +1001736c: 0025 movs r5, r4 +1001736e: bf18 it ne +10017370: 47a0 blxne r4 +10017372: bd31 pop {r0, r4, r5, pc} + +10017374 : +10017374: f641 5148 movw r1, #7496 ; 0x1d48 +10017378: 180a adds r2, r1, r0 +1001737a: 7a52 ldrb r2, [r2, #9] +1001737c: 2a00 cmp r2, #0 +1001737e: bf1e ittt ne +10017380: 5809 ldrne r1, [r1, r0] +10017382: 2900 cmpne r1, #0 +10017384: 4608 movne r0, r1 +10017386: f641 31fc movw r1, #7164 ; 0x1bfc +1001738a: 5809 ldr r1, [r1, r0] +1001738c: 000a movs r2, r1 +1001738e: bf18 it ne + +10017390 <__iar_annotation$$tailcall>: +10017390: 4708 bxne r1 +10017392: 4770 bx lr + +10017394 : +10017394: f641 5148 movw r1, #7496 ; 0x1d48 +10017398: 180a adds r2, r1, r0 +1001739a: 7a52 ldrb r2, [r2, #9] +1001739c: 2a00 cmp r2, #0 +1001739e: bf1e ittt ne +100173a0: 5809 ldrne r1, [r1, r0] +100173a2: 2900 cmpne r1, #0 +100173a4: 4608 movne r0, r1 +100173a6: f500 51e0 add.w r1, r0, #7168 ; 0x1c00 +100173aa: 6809 ldr r1, [r1, #0] +100173ac: 000a movs r2, r1 +100173ae: bf18 it ne + +100173b0 <__iar_annotation$$tailcall>: +100173b0: 4708 bxne r1 +100173b2: 4770 bx lr + +100173b4 : +100173b4: 4601 mov r1, r0 +100173b6: f641 32bc movw r2, #7100 ; 0x1bbc +100173ba: 2000 movs r0, #0 +100173bc: 5852 ldr r2, [r2, r1] +100173be: 0013 movs r3, r2 +100173c0: bf1c itt ne +100173c2: 4608 movne r0, r1 + +100173c4 <__iar_annotation$$tailcall>: +100173c4: 4710 bxne r2 +100173c6: 4770 bx lr + +100173c8 : +100173c8: f500 51de add.w r1, r0, #7104 ; 0x1bc0 +100173cc: 6809 ldr r1, [r1, #0] +100173ce: 000a movs r2, r1 +100173d0: bf18 it ne + +100173d2 <__iar_annotation$$tailcall>: +100173d2: 4708 bxne r1 +100173d4: 2000 movs r0, #0 +100173d6: 4770 bx lr + +100173d8 : +100173d8: f641 31c4 movw r1, #7108 ; 0x1bc4 +100173dc: 5809 ldr r1, [r1, r0] +100173de: 000a movs r2, r1 +100173e0: bf18 it ne + +100173e2 <__iar_annotation$$tailcall>: +100173e2: 4708 bxne r1 +100173e4: 4770 bx lr + +100173e6 : +100173e6: f641 4250 movw r2, #7248 ; 0x1c50 +100173ea: 5812 ldr r2, [r2, r0] +100173ec: 0013 movs r3, r2 +100173ee: bf18 it ne + +100173f0 <__iar_annotation$$tailcall>: +100173f0: 4710 bxne r2 +100173f2: 2000 movs r0, #0 +100173f4: 4770 bx lr + +100173f6 : +100173f6: b510 push {r4, lr} +100173f8: 4602 mov r2, r0 +100173fa: f641 4354 movw r3, #7252 ; 0x1c54 +100173fe: 2000 movs r0, #0 +10017400: 589b ldr r3, [r3, r2] +10017402: 001c movs r4, r3 +10017404: d003 beq.n 1001740e <__iar_annotation$$tailcall+0x2> +10017406: e8bd 4010 ldmia.w sp!, {r4, lr} +1001740a: 4610 mov r0, r2 + +1001740c <__iar_annotation$$tailcall>: +1001740c: 4718 bx r3 +1001740e: bd10 pop {r4, pc} + +10017410 : +10017410: f641 31c8 movw r1, #7112 ; 0x1bc8 +10017414: 5809 ldr r1, [r1, r0] +10017416: 000a movs r2, r1 +10017418: bf18 it ne + +1001741a <__iar_annotation$$tailcall>: +1001741a: 4708 bxne r1 +1001741c: 2000 movs r0, #0 +1001741e: 4770 bx lr + +10017420 : +10017420: f641 31cc movw r1, #7116 ; 0x1bcc +10017424: 5809 ldr r1, [r1, r0] +10017426: 000a movs r2, r1 +10017428: bf18 it ne + +1001742a <__iar_annotation$$tailcall>: +1001742a: 4708 bxne r1 +1001742c: 4770 bx lr + +1001742e : +1001742e: f641 31d0 movw r1, #7120 ; 0x1bd0 +10017432: 5809 ldr r1, [r1, r0] +10017434: 000a movs r2, r1 +10017436: bf18 it ne + +10017438 <__iar_annotation$$tailcall>: +10017438: 4708 bxne r1 +1001743a: 2000 movs r0, #0 +1001743c: 4770 bx lr + +1001743e : +1001743e: f641 31d4 movw r1, #7124 ; 0x1bd4 +10017442: 5809 ldr r1, [r1, r0] +10017444: 000a movs r2, r1 +10017446: bf18 it ne + +10017448 <__iar_annotation$$tailcall>: +10017448: 4708 bxne r1 +1001744a: 4770 bx lr + +1001744c : +1001744c: 0003 movs r3, r0 +1001744e: d100 bne.n 10017452 +10017450: 4770 bx lr +10017452: b510 push {r4, lr} +10017454: 6958 ldr r0, [r3, #20] +10017456: 7c02 ldrb r2, [r0, #16] +10017458: 06d2 lsls r2, r2, #27 +1001745a: d505 bpl.n 10017468 +1001745c: e8bd 4010 ldmia.w sp!, {r4, lr} +10017460: 460a mov r2, r1 +10017462: 4619 mov r1, r3 +10017464: f001 b93e b.w 100186e4 +10017468: f641 4234 movw r2, #7220 ; 0x1c34 +1001746c: 5814 ldr r4, [r2, r0] +1001746e: 0022 movs r2, r4 +10017470: d003 beq.n 1001747a +10017472: 460a mov r2, r1 +10017474: f8d3 1100 ldr.w r1, [r3, #256] ; 0x100 +10017478: 47a0 blx r4 +1001747a: bd10 pop {r4, pc} + +1001747c : +1001747c: b538 push {r3, r4, r5, lr} +1001747e: f641 443c movw r4, #7228 ; 0x1c3c +10017482: 5824 ldr r4, [r4, r0] +10017484: 0025 movs r5, r4 +10017486: bf18 it ne +10017488: 47a0 blxne r4 +1001748a: bd31 pop {r0, r4, r5, pc} + +1001748c : +1001748c: f500 52e2 add.w r2, r0, #7232 ; 0x1c40 +10017490: 6812 ldr r2, [r2, #0] +10017492: 0013 movs r3, r2 +10017494: bf18 it ne + +10017496 <__iar_annotation$$tailcall>: +10017496: 4710 bxne r2 +10017498: 4770 bx lr + +1001749a : +1001749a: f641 4144 movw r1, #7236 ; 0x1c44 +1001749e: 5809 ldr r1, [r1, r0] +100174a0: 000a movs r2, r1 +100174a2: bf18 it ne + +100174a4 <__iar_annotation$$tailcall>: +100174a4: 4708 bxne r1 +100174a6: 4770 bx lr + +100174a8 : +100174a8: f641 4148 movw r1, #7240 ; 0x1c48 +100174ac: 5809 ldr r1, [r1, r0] +100174ae: 000a movs r2, r1 +100174b0: bf18 it ne + +100174b2 <__iar_annotation$$tailcall>: +100174b2: 4708 bxne r1 +100174b4: 4770 bx lr + +100174b6 : +100174b6: b538 push {r3, r4, r5, lr} +100174b8: 4603 mov r3, r0 +100174ba: f641 4458 movw r4, #7256 ; 0x1c58 +100174be: 2000 movs r0, #0 +100174c0: 58e4 ldr r4, [r4, r3] +100174c2: 0025 movs r5, r4 +100174c4: bf1c itt ne +100174c6: 4618 movne r0, r3 +100174c8: 47a0 blxne r4 +100174ca: bd32 pop {r1, r4, r5, pc} + +100174cc : +100174cc: b538 push {r3, r4, r5, lr} +100174ce: f641 445c movw r4, #7260 ; 0x1c5c +100174d2: 5824 ldr r4, [r4, r0] +100174d4: 0025 movs r5, r4 +100174d6: bf18 it ne +100174d8: 47a0 blxne r4 +100174da: bd31 pop {r0, r4, r5, pc} + +100174dc : +100174dc: b570 push {r4, r5, r6, lr} +100174de: f500 55e3 add.w r5, r0, #7264 ; 0x1c60 +100174e2: 2400 movs r4, #0 +100174e4: 682d ldr r5, [r5, #0] +100174e6: 002e movs r6, r5 +100174e8: d001 beq.n 100174ee +100174ea: 47a8 blx r5 +100174ec: 4604 mov r4, r0 +100174ee: 4620 mov r0, r4 +100174f0: bd70 pop {r4, r5, r6, pc} + +100174f2 : +100174f2: b538 push {r3, r4, r5, lr} +100174f4: f641 4464 movw r4, #7268 ; 0x1c64 +100174f8: 5824 ldr r4, [r4, r0] +100174fa: 0025 movs r5, r4 +100174fc: d002 beq.n 10017504 +100174fe: 9d04 ldr r5, [sp, #16] +10017500: 9500 str r5, [sp, #0] +10017502: 47a0 blx r4 +10017504: bd31 pop {r0, r4, r5, pc} + +10017506 : +10017506: f641 4104 movw r1, #7172 ; 0x1c04 +1001750a: 5809 ldr r1, [r1, r0] +1001750c: 000a movs r2, r1 +1001750e: bf18 it ne + +10017510 <__iar_annotation$$tailcall>: +10017510: 4708 bxne r1 +10017512: 2000 movs r0, #0 +10017514: 4770 bx lr + +10017516 : +10017516: b510 push {r4, lr} +10017518: f641 4308 movw r3, #7176 ; 0x1c08 +1001751c: 581b ldr r3, [r3, r0] +1001751e: 001c movs r4, r3 +10017520: bf1c itt ne +10017522: e8bd 4010 ldmiane.w sp!, {r4, lr} + +10017526 <__iar_annotation$$tailcall>: +10017526: 4718 bxne r3 +10017528: bd10 pop {r4, pc} + +1001752a : +1001752a: f641 420c movw r2, #7180 ; 0x1c0c +1001752e: 5812 ldr r2, [r2, r0] +10017530: 0013 movs r3, r2 +10017532: bf18 it ne + +10017534 <__iar_annotation$$tailcall>: +10017534: 4710 bxne r2 +10017536: 4770 bx lr + +10017538 : +10017538: b538 push {r3, r4, r5, lr} +1001753a: f641 4410 movw r4, #7184 ; 0x1c10 +1001753e: 5825 ldr r5, [r4, r0] +10017540: 002c movs r4, r5 +10017542: d002 beq.n 1001754a +10017544: 9c04 ldr r4, [sp, #16] +10017546: 9400 str r4, [sp, #0] +10017548: 47a8 blx r5 +1001754a: bd31 pop {r0, r4, r5, pc} + +1001754c : +1001754c: f641 4114 movw r1, #7188 ; 0x1c14 +10017550: 5809 ldr r1, [r1, r0] +10017552: 000a movs r2, r1 +10017554: bf18 it ne + +10017556 <__iar_annotation$$tailcall>: +10017556: 4708 bxne r1 +10017558: 4770 bx lr + +1001755a : +1001755a: f641 428c movw r2, #7308 ; 0x1c8c +1001755e: 5812 ldr r2, [r2, r0] +10017560: 0013 movs r3, r2 +10017562: bf18 it ne + +10017564 <__iar_annotation$$tailcall>: +10017564: 4710 bxne r2 +10017566: 4770 bx lr + +10017568 : +10017568: f641 4190 movw r1, #7312 ; 0x1c90 +1001756c: 5809 ldr r1, [r1, r0] +1001756e: 000a movs r2, r1 +10017570: bf18 it ne + +10017572 <__iar_annotation$$tailcall>: +10017572: 4708 bxne r1 +10017574: 4770 bx lr + +10017576 : +10017576: 211f movs r1, #31 +10017578: 8001 strh r1, [r0, #0] +1001757a: 4770 bx lr + +1001757c : +1001757c: f8df f000 ldr.w pc, [pc] ; 10017580 +10017580: 00018239 .word 0x00018239 + +10017584 <_InitPowerOn>: +10017584: b51c push {r2, r3, r4, lr} +10017586: 4604 mov r4, r0 +10017588: aa01 add r2, sp, #4 +1001758a: 2140 movs r1, #64 ; 0x40 +1001758c: f7ff feca bl 10017324 +10017590: f89d 0004 ldrb.w r0, [sp, #4] +10017594: b970 cbnz r0, 100175b4 <_InitPowerOn+0x30> +10017596: 2200 movs r2, #0 +10017598: 211c movs r1, #28 +1001759a: f000 f9a3 bl 100178e4 <.text_22> +1001759e: f8df 09d4 ldr.w r0, [pc, #2516] ; 10017f74 <.text_41> +100175a2: f000 fb2d bl 10017c00 <.text_28> +100175a6: 2801 cmp r0, #1 +100175a8: d11a bne.n 100175e0 <_InitPowerOn+0x5c> +100175aa: f88d 0000 strb.w r0, [sp] +100175ae: aa00 add r2, sp, #0 +100175b0: f000 f819 bl 100175e6 <.text_9> +100175b4: f44f 7180 mov.w r1, #256 ; 0x100 +100175b8: f000 fc0a bl 10017dd0 <.text_35+0x4> +100175bc: f240 613f movw r1, #1599 ; 0x63f +100175c0: ea41 0200 orr.w r2, r1, r0 +100175c4: f44f 7180 mov.w r1, #256 ; 0x100 +100175c8: f000 f929 bl 1001781e <.text_17> +100175cc: 2104 movs r1, #4 +100175ce: f000 fc05 bl 10017ddc <.text_36+0x6> +100175d2: f440 7280 orr.w r2, r0, #256 ; 0x100 +100175d6: 2104 movs r1, #4 +100175d8: f000 f942 bl 10017860 <.text_19+0x4> +100175dc: 2001 movs r0, #1 +100175de: bd16 pop {r1, r2, r4, pc} +100175e0: 2800 cmp r0, #0 +100175e2: d1e7 bne.n 100175b4 <_InitPowerOn+0x30> +100175e4: bd16 pop {r1, r2, r4, pc} + +100175e6 <.text_9>: +100175e6: 2140 movs r1, #64 ; 0x40 +100175e8: 4620 mov r0, r4 +100175ea: f7ff be91 b.w 10017310 + +100175ee <_InitNormalChipRegPriority>: +100175ee: b5f8 push {r3, r4, r5, r6, r7, lr} +100175f0: 460e mov r6, r1 +100175f2: 4604 mov r4, r0 +100175f4: 4617 mov r7, r2 +100175f6: 461d mov r5, r3 +100175f8: f44f 7186 mov.w r1, #268 ; 0x10c +100175fc: f00d fb1c bl 10024c38 +10017600: f000 0007 and.w r0, r0, #7 +10017604: f006 0103 and.w r1, r6, #3 +10017608: ea40 2001 orr.w r0, r0, r1, lsl #8 +1001760c: f007 0103 and.w r1, r7, #3 +10017610: ea40 2081 orr.w r0, r0, r1, lsl #10 +10017614: f005 0103 and.w r1, r5, #3 +10017618: ea40 1181 orr.w r1, r0, r1, lsl #6 +1001761c: 9806 ldr r0, [sp, #24] +1001761e: f000 0003 and.w r0, r0, #3 +10017622: ea41 1100 orr.w r1, r1, r0, lsl #4 +10017626: 9807 ldr r0, [sp, #28] +10017628: f000 0003 and.w r0, r0, #3 +1001762c: ea41 3100 orr.w r1, r1, r0, lsl #12 +10017630: 9808 ldr r0, [sp, #32] +10017632: ea41 3280 orr.w r2, r1, r0, lsl #14 +10017636: 4620 mov r0, r4 +10017638: e8bd 40f8 ldmia.w sp!, {r3, r4, r5, r6, r7, lr} +1001763c: b292 uxth r2, r2 +1001763e: f44f 7186 mov.w r1, #268 ; 0x10c +10017642: f00d bb0d b.w 10024c60 + +10017646 <_InitNormalChipQueuePriority>: +10017646: b53e push {r1, r2, r3, r4, r5, lr} +10017648: f641 31a4 movw r1, #7076 ; 0x1ba4 +1001764c: f642 1414 movw r4, #10516 ; 0x2914 +10017650: 580a ldr r2, [r1, r0] +10017652: 18a1 adds r1, r4, r2 +10017654: 7849 ldrb r1, [r1, #1] +10017656: 2901 cmp r1, #1 +10017658: d004 beq.n 10017664 <_InitNormalChipQueuePriority+0x1e> +1001765a: d346 bcc.n 100176ea <_InitNormalChipQueuePriority+0xa4> +1001765c: 2903 cmp r1, #3 +1001765e: d035 beq.n 100176cc <_InitNormalChipQueuePriority+0x86> +10017660: d313 bcc.n 1001768a <_InitNormalChipQueuePriority+0x44> +10017662: bd37 pop {r0, r1, r2, r4, r5, pc} +10017664: 5ca1 ldrb r1, [r4, r2] +10017666: 2300 movs r3, #0 +10017668: 2901 cmp r1, #1 +1001766a: d007 beq.n 1001767c <_InitNormalChipQueuePriority+0x36> +1001766c: 2902 cmp r1, #2 +1001766e: d003 beq.n 10017678 <_InitNormalChipQueuePriority+0x32> +10017670: 2904 cmp r1, #4 +10017672: d104 bne.n 1001767e <_InitNormalChipQueuePriority+0x38> +10017674: 2302 movs r3, #2 +10017676: e002 b.n 1001767e <_InitNormalChipQueuePriority+0x38> +10017678: 2301 movs r3, #1 +1001767a: e000 b.n 1001767e <_InitNormalChipQueuePriority+0x38> +1001767c: 2303 movs r3, #3 +1001767e: 9302 str r3, [sp, #8] +10017680: 9301 str r3, [sp, #4] +10017682: 9300 str r3, [sp, #0] +10017684: 461a mov r2, r3 +10017686: 4619 mov r1, r3 +10017688: e02d b.n 100176e6 <_InitNormalChipQueuePriority+0xa0> +1001768a: 5ca2 ldrb r2, [r4, r2] +1001768c: 2500 movs r5, #0 +1001768e: 2100 movs r1, #0 +10017690: 2a03 cmp r2, #3 +10017692: f500 53c4 add.w r3, r0, #6272 ; 0x1880 +10017696: d009 beq.n 100176ac <_InitNormalChipQueuePriority+0x66> +10017698: 2a05 cmp r2, #5 +1001769a: d002 beq.n 100176a2 <_InitNormalChipQueuePriority+0x5c> +1001769c: 2a06 cmp r2, #6 +1001769e: d003 beq.n 100176a8 <_InitNormalChipQueuePriority+0x62> +100176a0: e006 b.n 100176b0 <_InitNormalChipQueuePriority+0x6a> +100176a2: 2503 movs r5, #3 +100176a4: 2102 movs r1, #2 +100176a6: e003 b.n 100176b0 <_InitNormalChipQueuePriority+0x6a> +100176a8: 2502 movs r5, #2 +100176aa: e000 b.n 100176ae <_InitNormalChipQueuePriority+0x68> +100176ac: 2503 movs r5, #3 +100176ae: 2101 movs r1, #1 +100176b0: f893 2058 ldrb.w r2, [r3, #88] ; 0x58 +100176b4: b91a cbnz r2, 100176be <_InitNormalChipQueuePriority+0x78> +100176b6: 460a mov r2, r1 +100176b8: 462b mov r3, r5 +100176ba: 462c mov r4, r5 +100176bc: e002 b.n 100176c4 <_InitNormalChipQueuePriority+0x7e> +100176be: 462a mov r2, r5 +100176c0: 462b mov r3, r5 +100176c2: 460c mov r4, r1 +100176c4: 9502 str r5, [sp, #8] +100176c6: 9501 str r5, [sp, #4] +100176c8: 9400 str r4, [sp, #0] +100176ca: e00c b.n 100176e6 <_InitNormalChipQueuePriority+0xa0> +100176cc: f641 01d8 movw r1, #6360 ; 0x18d8 +100176d0: 5c09 ldrb r1, [r1, r0] +100176d2: 2900 cmp r1, #0 +100176d4: bf0c ite eq +100176d6: 2201 moveq r2, #1 +100176d8: 2202 movne r2, #2 +100176da: 2103 movs r1, #3 +100176dc: 9102 str r1, [sp, #8] +100176de: 9101 str r1, [sp, #4] +100176e0: 9100 str r1, [sp, #0] +100176e2: 2302 movs r3, #2 +100176e4: 2101 movs r1, #1 +100176e6: f7ff ff82 bl 100175ee <_InitNormalChipRegPriority> +100176ea: bd37 pop {r0, r1, r2, r4, r5, pc} + +100176ec <_InitDriverInfoSize>: +100176ec: 460a mov r2, r1 +100176ee: f240 610f movw r1, #1551 ; 0x60f +100176f2: f00d baad b.w 10024c50 + +100176f6 <_InitNetworkType>: +100176f6: b510 push {r4, lr} +100176f8: 4604 mov r4, r0 +100176fa: f44f 7180 mov.w r1, #256 ; 0x100 +100176fe: f00d faa1 bl 10024c44 +10017702: f420 3040 bic.w r0, r0, #196608 ; 0x30000 +10017706: f440 3200 orr.w r2, r0, #131072 ; 0x20000 +1001770a: 4620 mov r0, r4 +1001770c: e8bd 4010 ldmia.w sp!, {r4, lr} +10017710: f44f 7180 mov.w r1, #256 ; 0x100 +10017714: f00d baac b.w 10024c70 + +10017718 <_InitWMACSetting>: +10017718: b570 push {r4, r5, r6, lr} +1001771a: 4604 mov r4, r0 +1001771c: f641 30a4 movw r0, #7076 ; 0x1ba4 +10017720: f8df 2854 ldr.w r2, [pc, #2132] ; 10017f78 <.text_42> +10017724: 5905 ldr r5, [r0, r4] +10017726: f44f 61c1 mov.w r1, #1544 ; 0x608 +1001772a: 636a str r2, [r5, #52] ; 0x34 +1001772c: f000 f898 bl 10017860 <.text_19+0x4> +10017730: f04f 32ff mov.w r2, #4294967295 +10017734: f44f 61c4 mov.w r1, #1568 ; 0x620 +10017738: f000 f892 bl 10017860 <.text_19+0x4> +1001773c: f04f 32ff mov.w r2, #4294967295 +10017740: f240 6124 movw r1, #1572 ; 0x624 +10017744: f000 f88c bl 10017860 <.text_19+0x4> +10017748: f64f 76ff movw r6, #65535 ; 0xffff +1001774c: 4632 mov r2, r6 +1001774e: f240 61a4 movw r1, #1700 ; 0x6a4 +10017752: f000 f864 bl 1001781e <.text_17> +10017756: f44f 6280 mov.w r2, #1024 ; 0x400 +1001775a: f240 61a2 movw r1, #1698 ; 0x6a2 +1001775e: f000 f85e bl 1001781e <.text_17> +10017762: 4632 mov r2, r6 +10017764: f44f 61d4 mov.w r1, #1696 ; 0x6a0 +10017768: f000 f859 bl 1001781e <.text_17> +1001776c: 4620 mov r0, r4 +1001776e: f009 fc9a bl 100210a6 +10017772: f642 114a movw r1, #10570 ; 0x294a +10017776: 2000 movs r0, #0 +10017778: 5348 strh r0, [r1, r5] +1001777a: bd70 pop {r4, r5, r6, pc} + +1001777c <_InitAdaptiveCtrl>: +1001777c: b510 push {r4, lr} +1001777e: 4604 mov r4, r0 +10017780: f44f 6188 mov.w r1, #1088 ; 0x440 +10017784: f00d fa5e bl 10024c44 +10017788: 0d00 lsrs r0, r0, #20 +1001778a: f8df 17f0 ldr.w r1, [pc, #2032] ; 10017f7c <.text_43> +1001778e: ea41 5200 orr.w r2, r1, r0, lsl #20 +10017792: f44f 6188 mov.w r1, #1088 ; 0x440 +10017796: f000 f863 bl 10017860 <.text_19+0x4> +1001779a: f241 0210 movw r2, #4112 ; 0x1010 +1001779e: f44f 6185 mov.w r1, #1064 ; 0x428 +100177a2: f000 f83c bl 1001781e <.text_17> +100177a6: 4620 mov r0, r4 +100177a8: e8bd 4010 ldmia.w sp!, {r4, lr} +100177ac: f243 0230 movw r2, #12336 ; 0x3030 +100177b0: f240 412a movw r1, #1066 ; 0x42a +100177b4: f00d ba54 b.w 10024c60 + +100177b8 <_InitEDCA>: +100177b8: b538 push {r3, r4, r5, lr} +100177ba: f241 050a movw r5, #4106 ; 0x100a +100177be: 4604 mov r4, r0 +100177c0: 462a mov r2, r5 +100177c2: f44f 6185 mov.w r1, #1064 ; 0x428 +100177c6: f00d fa4b bl 10024c60 +100177ca: 462a mov r2, r5 +100177cc: f240 613a movw r1, #1594 ; 0x63a +100177d0: f000 f825 bl 1001781e <.text_17> +100177d4: 462a mov r2, r5 +100177d6: f240 5114 movw r1, #1300 ; 0x514 +100177da: f000 f820 bl 1001781e <.text_17> +100177de: 462a mov r2, r5 +100177e0: f240 5116 movw r1, #1302 ; 0x516 +100177e4: f000 f81b bl 1001781e <.text_17> +100177e8: f8df 2794 ldr.w r2, [pc, #1940] ; 10017f80 <.text_44> +100177ec: f44f 61a1 mov.w r1, #1288 ; 0x508 +100177f0: f000 f836 bl 10017860 <.text_19+0x4> +100177f4: f24a 424f movw r2, #42063 ; 0xa44f +100177f8: f240 510c movw r1, #1292 ; 0x50c +100177fc: f000 f830 bl 10017860 <.text_19+0x4> +10017800: f8df 2780 ldr.w r2, [pc, #1920] ; 10017f84 <.text_45> +10017804: f240 5104 movw r1, #1284 ; 0x504 +10017808: f000 f82a bl 10017860 <.text_19+0x4> +1001780c: 4620 mov r0, r4 +1001780e: e8bd 4038 ldmia.w sp!, {r3, r4, r5, lr} +10017812: f8df 2774 ldr.w r2, [pc, #1908] ; 10017f88 <.text_46> +10017816: f44f 61a0 mov.w r1, #1280 ; 0x500 +1001781a: f00d ba29 b.w 10024c70 + +1001781e <.text_17>: +1001781e: 4620 mov r0, r4 +10017820: f00d ba1e b.w 10024c60 + +10017824 <_InitRateFallback>: +10017824: b510 push {r4, lr} +10017826: 4604 mov r4, r0 +10017828: 2200 movs r2, #0 +1001782a: f44f 6186 mov.w r1, #1072 ; 0x430 +1001782e: f00d fa1f bl 10024c70 +10017832: f8df 2758 ldr.w r2, [pc, #1880] ; 10017f8c <.text_47> +10017836: f240 4134 movw r1, #1076 ; 0x434 +1001783a: f000 f811 bl 10017860 <.text_19+0x4> +1001783e: f8df 2750 ldr.w r2, [pc, #1872] ; 10017f90 <.text_48> +10017842: f44f 6187 mov.w r1, #1080 ; 0x438 +10017846: f000 f80b bl 10017860 <.text_19+0x4> +1001784a: 4620 mov r0, r4 +1001784c: e8bd 4010 ldmia.w sp!, {r4, lr} +10017850: f8df 2740 ldr.w r2, [pc, #1856] ; 10017f94 <.text_49> +10017854: f240 413c movw r1, #1084 ; 0x43c +10017858: f00d ba0a b.w 10024c70 + +1001785c <.text_19>: +1001785c: f44f 61c1 mov.w r1, #1544 ; 0x608 +10017860: 4620 mov r0, r4 +10017862: f00d ba05 b.w 10024c70 + +10017866 <_InitRetryFunction>: +10017866: b510 push {r4, lr} +10017868: 4604 mov r4, r0 +1001786a: f44f 6184 mov.w r1, #1056 ; 0x420 +1001786e: f00d f9dd bl 10024c2c +10017872: f040 0280 orr.w r2, r0, #128 ; 0x80 +10017876: f44f 6184 mov.w r1, #1056 ; 0x420 +1001787a: f000 f833 bl 100178e4 <.text_22> +1001787e: 4620 mov r0, r4 +10017880: e8bd 4010 ldmia.w sp!, {r4, lr} +10017884: 2240 movs r2, #64 ; 0x40 +10017886: f44f 61c8 mov.w r1, #1600 ; 0x640 +1001788a: f00d b9e1 b.w 10024c50 + +1001788e <_InitOperationMode>: +1001788e: b570 push {r4, r5, r6, lr} +10017890: 4604 mov r4, r0 +10017892: f641 30a4 movw r0, #7076 ; 0x1ba4 +10017896: 2200 movs r2, #0 +10017898: 5906 ldr r6, [r0, r4] +1001789a: f894 04f9 ldrb.w r0, [r4, #1273] ; 0x4f9 +1001789e: 2500 movs r5, #0 +100178a0: 2802 cmp r0, #2 +100178a2: bf18 it ne +100178a4: 2804 cmpne r0, #4 +100178a6: d003 beq.n 100178b0 <_InitOperationMode+0x22> +100178a8: 2808 cmp r0, #8 +100178aa: bf18 it ne +100178ac: 2810 cmpne r0, #16 +100178ae: d100 bne.n 100178b2 <_InitOperationMode+0x24> +100178b0: 2204 movs r2, #4 +100178b2: f240 6103 movw r1, #1539 ; 0x603 +100178b6: f000 f815 bl 100178e4 <.text_22> +100178ba: f896 004b ldrb.w r0, [r6, #75] ; 0x4b +100178be: b130 cbz r0, 100178ce <_InitOperationMode+0x40> +100178c0: 2802 cmp r0, #2 +100178c2: d006 beq.n 100178d2 <_InitOperationMode+0x44> +100178c4: 2803 cmp r0, #3 +100178c6: d002 beq.n 100178ce <_InitOperationMode+0x40> +100178c8: 2804 cmp r0, #4 +100178ca: d002 beq.n 100178d2 <_InitOperationMode+0x44> +100178cc: e002 b.n 100178d4 <_InitOperationMode+0x46> +100178ce: 2550 movs r5, #80 ; 0x50 +100178d0: e000 b.n 100178d4 <_InitOperationMode+0x46> +100178d2: 2598 movs r5, #152 ; 0x98 +100178d4: 462a mov r2, r5 +100178d6: 4620 mov r0, r4 +100178d8: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +100178dc: f240 415c movw r1, #1116 ; 0x45c +100178e0: f00d b9b6 b.w 10024c50 + +100178e4 <.text_22>: +100178e4: 4620 mov r0, r4 +100178e6: f00d b9b3 b.w 10024c50 + +100178ea <_InitInterrupt>: +100178ea: b510 push {r4, lr} +100178ec: 4604 mov r4, r0 +100178ee: 2200 movs r2, #0 +100178f0: 2180 movs r1, #128 ; 0x80 +100178f2: f00d f9bd bl 10024c70 +100178f6: 2200 movs r2, #0 +100178f8: f44f 7198 mov.w r1, #304 ; 0x130 +100178fc: f7ff ffb0 bl 10017860 <.text_19+0x4> +10017900: 2200 movs r2, #0 +10017902: f44f 719c mov.w r1, #312 ; 0x138 +10017906: f7ff ffab bl 10017860 <.text_19+0x4> +1001790a: 2200 movs r2, #0 +1001790c: f44f 717b mov.w r1, #1004 ; 0x3ec +10017910: f7ff ffa6 bl 10017860 <.text_19+0x4> +10017914: 4620 mov r0, r4 +10017916: f009 fdba bl 1002148e +1001791a: 4620 mov r0, r4 +1001791c: e8bd 4010 ldmia.w sp!, {r4, lr} +10017920: f7fb be09 b.w 10013536 + +10017924 : +10017924: e92d 47fc stmdb sp!, {r2, r3, r4, r5, r6, r7, r8, r9, sl, lr} +10017928: 4604 mov r4, r0 +1001792a: f247 5030 movw r0, #30000 ; 0x7530 +1001792e: f641 37a4 movw r7, #7076 ; 0x1ba4 +10017932: 9001 str r0, [sp, #4] +10017934: f504 56c8 add.w r6, r4, #6400 ; 0x1900 +10017938: f857 9004 ldr.w r9, [r7, r4] +1001793c: 360c adds r6, #12 +1001793e: 4620 mov r0, r4 +10017940: f7ff fe20 bl 10017584 <_InitPowerOn> +10017944: 2800 cmp r0, #0 +10017946: d013 beq.n 10017970 +10017948: 2200 movs r2, #0 +1001794a: f44f 619a mov.w r1, #1232 ; 0x4d0 +1001794e: f7ff ffc9 bl 100178e4 <.text_22> +10017952: 2100 movs r1, #0 +10017954: 4620 mov r0, r4 +10017956: f00f fcae bl 100272b6 +1001795a: f641 1834 movw r8, #6452 ; 0x1934 +1001795e: 2801 cmp r0, #1 +10017960: eb08 0509 add.w r5, r8, r9 +10017964: f641 5145 movw r1, #7493 ; 0x1d45 +10017968: d003 beq.n 10017972 +1001796a: 2200 movs r2, #0 +1001796c: 550a strb r2, [r1, r4] +1001796e: 72aa strb r2, [r5, #10] +10017970: e12c b.n 10017bcc +10017972: 5508 strb r0, [r1, r4] +10017974: 72a8 strb r0, [r5, #10] +10017976: 4620 mov r0, r4 +10017978: f00f fc9f bl 100272ba +1001797c: 7cb0 ldrb r0, [r6, #18] +1001797e: 2801 cmp r0, #1 +10017980: bf04 itt eq +10017982: 2002 moveq r0, #2 +10017984: 66b0 streq r0, [r6, #104] ; 0x68 +10017986: 5938 ldr r0, [r7, r4] +10017988: 6801 ldr r1, [r0, #0] +1001798a: 2902 cmp r1, #2 +1001798c: bf12 itee ne +1001798e: 2901 cmpne r1, #1 +10017990: 6901 ldreq r1, [r0, #16] +10017992: 2902 cmpeq r1, #2 +10017994: d103 bne.n 1001799e +10017996: 2104 movs r1, #4 +10017998: f880 104a strb.w r1, [r0, #74] ; 0x4a +1001799c: e005 b.n 100179aa +1001799e: 2104 movs r1, #4 +100179a0: f880 104a strb.w r1, [r0, #74] ; 0x4a +100179a4: 2103 movs r1, #3 +100179a6: f880 104b strb.w r1, [r0, #75] ; 0x4b +100179aa: 2006 movs r0, #6 +100179ac: f889 0044 strb.w r0, [r9, #68] ; 0x44 +100179b0: 4620 mov r0, r4 +100179b2: f011 ff07 bl 100297c4 +100179b6: 2801 cmp r0, #1 +100179b8: d1da bne.n 10017970 +100179ba: 4620 mov r0, r4 +100179bc: f011 ff64 bl 10029888 +100179c0: 2801 cmp r0, #1 +100179c2: d1d5 bne.n 10017970 +100179c4: 4620 mov r0, r4 +100179c6: f011 ffac bl 10029922 +100179ca: 2801 cmp r0, #1 +100179cc: d1d0 bne.n 10017970 +100179ce: 2301 movs r3, #1 +100179d0: f04f 7280 mov.w r2, #16777216 ; 0x1000000 +100179d4: f000 f8fc bl 10017bd0 <.text_26> +100179d8: 2301 movs r3, #1 +100179da: f04f 7200 mov.w r2, #33554432 ; 0x2000000 +100179de: f000 f8f7 bl 10017bd0 <.text_26> +100179e2: f8df a5b4 ldr.w sl, [pc, #1460] ; 10017f98 <.text_50> +100179e6: 4653 mov r3, sl +100179e8: 2218 movs r2, #24 +100179ea: 2100 movs r1, #0 +100179ec: 4620 mov r0, r4 +100179ee: f011 feaf bl 10029750 +100179f2: f848 0009 str.w r0, [r8, r9] +100179f6: 4653 mov r3, sl +100179f8: 2218 movs r2, #24 +100179fa: 2101 movs r1, #1 +100179fc: 4620 mov r0, r4 +100179fe: f011 fea7 bl 10029750 +10017a02: 6068 str r0, [r5, #4] +10017a04: f642 1214 movw r2, #10516 ; 0x2914 +10017a08: 5938 ldr r0, [r7, r4] +10017a0a: 5c10 ldrb r0, [r2, r0] +10017a0c: f641 01d8 movw r1, #6360 ; 0x18d8 +10017a10: 2700 movs r7, #0 +10017a12: 2500 movs r5, #0 +10017a14: 5d09 ldrb r1, [r1, r4] +10017a16: 07c2 lsls r2, r0, #31 +10017a18: 46b8 mov r8, r7 +10017a1a: d503 bpl.n 10017a24 +10017a1c: 2900 cmp r1, #0 +10017a1e: bf14 ite ne +10017a20: 2730 movne r7, #48 ; 0x30 +10017a22: 270c moveq r7, #12 +10017a24: 0782 lsls r2, r0, #30 +10017a26: d505 bpl.n 10017a34 +10017a28: 2900 cmp r1, #0 +10017a2a: bf14 ite ne +10017a2c: f04f 0820 movne.w r8, #32 +10017a30: f04f 0802 moveq.w r8, #2 +10017a34: 0740 lsls r0, r0, #29 +10017a36: d503 bpl.n 10017a40 +10017a38: 2900 cmp r1, #0 +10017a3a: bf14 ite ne +10017a3c: 2520 movne r5, #32 +10017a3e: 2502 moveq r5, #2 +10017a40: 462a mov r2, r5 +10017a42: f44f 7105 mov.w r1, #532 ; 0x214 +10017a46: f7ff ff4d bl 100178e4 <.text_22> +10017a4a: f1c7 01f3 rsb r1, r7, #243 ; 0xf3 +10017a4e: eba1 0108 sub.w r1, r1, r8 +10017a52: 1b49 subs r1, r1, r5 +10017a54: ea47 2008 orr.w r0, r7, r8, lsl #8 +10017a58: b2c9 uxtb r1, r1 +10017a5a: ea40 4001 orr.w r0, r0, r1, lsl #16 +10017a5e: f040 4200 orr.w r2, r0, #2147483648 ; 0x80000000 +10017a62: f44f 7100 mov.w r1, #512 ; 0x200 +10017a66: f7ff fefb bl 10017860 <.text_19+0x4> +10017a6a: 22f4 movs r2, #244 ; 0xf4 +10017a6c: f240 4124 movw r1, #1060 ; 0x424 +10017a70: f7ff ff38 bl 100178e4 <.text_22> +10017a74: 22f4 movs r2, #244 ; 0xf4 +10017a76: f240 4125 movw r1, #1061 ; 0x425 +10017a7a: f7ff ff33 bl 100178e4 <.text_22> +10017a7e: 22f4 movs r2, #244 ; 0xf4 +10017a80: f240 415d movw r1, #1117 ; 0x45d +10017a84: f7ff ff2e bl 100178e4 <.text_22> +10017a88: 22f4 movs r2, #244 ; 0xf4 +10017a8a: f44f 718a mov.w r1, #276 ; 0x114 +10017a8e: f7ff ff29 bl 100178e4 <.text_22> +10017a92: 22f4 movs r2, #244 ; 0xf4 +10017a94: f240 2109 movw r1, #521 ; 0x209 +10017a98: f7ff ff24 bl 100178e4 <.text_22> +10017a9c: 22fc movs r2, #252 ; 0xfc +10017a9e: f240 4157 movw r1, #1111 ; 0x457 +10017aa2: f7ff ff1f bl 100178e4 <.text_22> +10017aa6: 22fc movs r2, #252 ; 0xfc +10017aa8: f240 2129 movw r1, #553 ; 0x229 +10017aac: f7ff ff1a bl 100178e4 <.text_22> +10017ab0: f240 272a movw r7, #554 ; 0x22a +10017ab4: 4639 mov r1, r7 +10017ab6: 4620 mov r0, r4 +10017ab8: f00d f8b8 bl 10024c2c +10017abc: f040 0202 orr.w r2, r0, #2 +10017ac0: 4639 mov r1, r7 +10017ac2: f7ff ff0f bl 100178e4 <.text_22> +10017ac6: 4620 mov r0, r4 +10017ac8: f010 faba bl 10028040 +10017acc: 2801 cmp r0, #1 +10017ace: bf18 it ne +10017ad0: 2000 movne r0, #0 +10017ad2: d17b bne.n 10017bcc +10017ad4: 4620 mov r0, r4 +10017ad6: f7ff fdb6 bl 10017646 <_InitNormalChipQueuePriority> +10017ada: f643 727f movw r2, #16255 ; 0x3f7f +10017ade: f44f 718b mov.w r1, #278 ; 0x116 +10017ae2: f7ff fe9c bl 1001781e <.text_17> +10017ae6: 2211 movs r2, #17 +10017ae8: f44f 7182 mov.w r1, #260 ; 0x104 +10017aec: f7ff fefa bl 100178e4 <.text_22> +10017af0: 2104 movs r1, #4 +10017af2: 4620 mov r0, r4 +10017af4: f7ff fdfa bl 100176ec <_InitDriverInfoSize> +10017af8: 4620 mov r0, r4 +10017afa: f00f f956 bl 10026daa +10017afe: 4620 mov r0, r4 +10017b00: f7ff fdf9 bl 100176f6 <_InitNetworkType> +10017b04: 4620 mov r0, r4 +10017b06: f7ff fe07 bl 10017718 <_InitWMACSetting> +10017b0a: 4620 mov r0, r4 +10017b0c: f7ff fe36 bl 1001777c <_InitAdaptiveCtrl> +10017b10: 4620 mov r0, r4 +10017b12: f7ff fe51 bl 100177b8 <_InitEDCA> +10017b16: 4620 mov r0, r4 +10017b18: f7ff fe84 bl 10017824 <_InitRateFallback> +10017b1c: 4620 mov r0, r4 +10017b1e: f7ff fea2 bl 10017866 <_InitRetryFunction> +10017b22: 4620 mov r0, r4 +10017b24: f7ff feb3 bl 1001788e <_InitOperationMode> +10017b28: 4620 mov r0, r4 +10017b2a: f00f ffdc bl 10027ae6 +10017b2e: 2101 movs r1, #1 +10017b30: 4620 mov r0, r4 +10017b32: f010 f81a bl 10027b6a +10017b36: 4620 mov r0, r4 +10017b38: f7ff fed7 bl 100178ea <_InitInterrupt> +10017b3c: 4620 mov r0, r4 +10017b3e: f010 f815 bl 10027b6c <_InitBurstPktLen_8195AB> +10017b42: f44f 5240 mov.w r2, #12288 ; 0x3000 +10017b46: f44f 6198 mov.w r1, #1216 ; 0x4c0 +10017b4a: f7ff fe68 bl 1001781e <.text_17> +10017b4e: f44f 5240 mov.w r2, #12288 ; 0x3000 +10017b52: f240 41c2 movw r1, #1218 ; 0x4c2 +10017b56: f7ff fe62 bl 1001781e <.text_17> +10017b5a: 4620 mov r0, r4 +10017b5c: f00e f88c bl 10025c78 +10017b60: 2000 movs r0, #0 +10017b62: 9000 str r0, [sp, #0] +10017b64: 4602 mov r2, r0 +10017b66: f641 00ad movw r0, #6317 ; 0x18ad +10017b6a: 2300 movs r3, #0 +10017b6c: 5d01 ldrb r1, [r0, r4] +10017b6e: 4620 mov r0, r4 +10017b70: f7ff fce2 bl 10017538 +10017b74: 4620 mov r0, r4 +10017b76: f010 fa61 bl 1002803c +10017b7a: f8df 2420 ldr.w r2, [pc, #1056] ; 10017f9c <.text_51> +10017b7e: f240 41cc movw r1, #1228 ; 0x4cc +10017b82: f7ff fe6d bl 10017860 <.text_19+0x4> +10017b86: 22ff movs r2, #255 ; 0xff +10017b88: f240 4123 movw r1, #1059 ; 0x423 +10017b8c: f7ff feaa bl 100178e4 <.text_22> +10017b90: 4620 mov r0, r4 +10017b92: f009 f846 bl 10020c22 +10017b96: f44f 7180 mov.w r1, #256 ; 0x100 +10017b9a: 4620 mov r0, r4 +10017b9c: f00d f846 bl 10024c2c +10017ba0: f040 02c0 orr.w r2, r0, #192 ; 0xc0 +10017ba4: f44f 7180 mov.w r1, #256 ; 0x100 +10017ba8: f7ff fe9c bl 100178e4 <.text_22> +10017bac: aa01 add r2, sp, #4 +10017bae: 2141 movs r1, #65 ; 0x41 +10017bb0: f7ff fd1a bl 100175e8 <.text_9+0x2> +10017bb4: 2000 movs r0, #0 +10017bb6: 66b0 str r0, [r6, #104] ; 0x68 +10017bb8: 4602 mov r2, r0 +10017bba: 4601 mov r1, r0 +10017bbc: 4620 mov r0, r4 +10017bbe: f013 fbd9 bl 1002b374 +10017bc2: f242 716c movw r1, #10092 ; 0x276c +10017bc6: 2001 movs r0, #1 +10017bc8: f801 0009 strb.w r0, [r1, r9] +10017bcc: e8bd 87f6 ldmia.w sp!, {r1, r2, r4, r5, r6, r7, r8, r9, sl, pc} + +10017bd0 <.text_26>: +10017bd0: f44f 6100 mov.w r1, #2048 ; 0x800 +10017bd4: 4620 mov r0, r4 +10017bd6: f7ff bcd1 b.w 1001757c + +10017bda : +10017bda: b51c push {r2, r3, r4, lr} +10017bdc: 4604 mov r4, r0 +10017bde: f641 40b5 movw r0, #7349 ; 0x1cb5 +10017be2: 5d00 ldrb r0, [r0, r4] +10017be4: 2801 cmp r0, #1 +10017be6: d109 bne.n 10017bfc +10017be8: 2000 movs r0, #0 +10017bea: f88d 0004 strb.w r0, [sp, #4] +10017bee: aa01 add r2, sp, #4 +10017bf0: f7ff fcf9 bl 100175e6 <.text_9> +10017bf4: f8df 03a8 ldr.w r0, [pc, #936] ; 10017fa0 <.text_52> +10017bf8: f000 f802 bl 10017c00 <.text_28> +10017bfc: 2001 movs r0, #1 +10017bfe: bd16 pop {r1, r2, r4, pc} + +10017c00 <.text_28>: +10017c00: 9000 str r0, [sp, #0] +10017c02: 2301 movs r3, #1 +10017c04: 220f movs r2, #15 +10017c06: 21ff movs r1, #255 ; 0xff +10017c08: 4620 mov r0, r4 +10017c0a: f013 bd81 b.w 1002b710 + +10017c0e : +10017c0e: f010 ba16 b.w 1002803e + +10017c12 : +10017c12: b5f8 push {r3, r4, r5, r6, r7, lr} +10017c14: 4604 mov r4, r0 +10017c16: f641 30a4 movw r0, #7076 ; 0x1ba4 +10017c1a: 5905 ldr r5, [r0, r4] +10017c1c: 68a6 ldr r6, [r4, #8] +10017c1e: f641 00d8 movw r0, #6360 ; 0x18d8 +10017c22: 5d07 ldrb r7, [r0, r4] +10017c24: f013 fde2 bl 1002b7ec +10017c28: 2004 movs r0, #4 +10017c2a: 7470 strb r0, [r6, #17] +10017c2c: f642 1214 movw r2, #10516 ; 0x2914 +10017c30: 2005 movs r0, #5 +10017c32: 74b0 strb r0, [r6, #18] +10017c34: 2006 movs r0, #6 +10017c36: 74f0 strb r0, [r6, #19] +10017c38: 2f00 cmp r7, #0 +10017c3a: bf14 ite ne +10017c3c: 2002 movne r0, #2 +10017c3e: 2003 moveq r0, #3 +10017c40: 1951 adds r1, r2, r5 +10017c42: 7048 strb r0, [r1, #1] +10017c44: 7849 ldrb r1, [r1, #1] +10017c46: 2902 cmp r1, #2 +10017c48: d003 beq.n 10017c52 +10017c4a: 2903 cmp r1, #3 +10017c4c: d103 bne.n 10017c56 +10017c4e: 2007 movs r0, #7 +10017c50: e000 b.n 10017c54 +10017c52: 2005 movs r0, #5 +10017c54: 5550 strb r0, [r2, r5] +10017c56: 4620 mov r0, r4 +10017c58: e8bd 40f4 ldmia.w sp!, {r2, r4, r5, r6, r7, lr} +10017c5c: f00f b87f b.w 10026d5e + +10017c60 <_ReadEfuseInfo8195a>: +10017c60: b530 push {r4, r5, lr} +10017c62: f5ad 7d03 sub.w sp, sp, #524 ; 0x20c +10017c66: 4604 mov r4, r0 +10017c68: f504 55c8 add.w r5, r4, #6400 ; 0x1900 +10017c6c: a902 add r1, sp, #8 +10017c6e: f010 fa7a bl 10028166 +10017c72: a902 add r1, sp, #8 +10017c74: 4620 mov r0, r4 +10017c76: f010 fa90 bl 1002819a +10017c7a: f815 2f94 ldrb.w r2, [r5, #148]! +10017c7e: a902 add r1, sp, #8 +10017c80: 4620 mov r0, r4 +10017c82: f010 fbc9 bl 10028418 +10017c86: f20f 317c addw r1, pc, #892 ; 0x37c +10017c8a: c90c ldmia r1!, {r2, r3} +10017c8c: a800 add r0, sp, #0 +10017c8e: c00c stmia r0!, {r2, r3} +10017c90: 7829 ldrb r1, [r5, #0] +10017c92: b141 cbz r1, 10017ca6 <_ReadEfuseInfo8195a+0x46> +10017c94: 2100 movs r1, #0 +10017c96: aa00 add r2, sp, #0 +10017c98: 194b adds r3, r1, r5 +10017c9a: 5c8a ldrb r2, [r1, r2] +10017c9c: 705a strb r2, [r3, #1] +10017c9e: 1c49 adds r1, r1, #1 +10017ca0: 2906 cmp r1, #6 +10017ca2: dbf8 blt.n 10017c96 <_ReadEfuseInfo8195a+0x36> +10017ca4: e005 b.n 10017cb2 <_ReadEfuseInfo8195a+0x52> +10017ca6: 2206 movs r2, #6 +10017ca8: f50d 7191 add.w r1, sp, #290 ; 0x122 +10017cac: 1c68 adds r0, r5, #1 +10017cae: f7f8 fdae bl 1001080e +10017cb2: f000 f82c bl 10017d0e <.text_32> +10017cb6: f010 fb54 bl 10028362 +10017cba: f641 30a4 movw r0, #7076 ; 0x1ba4 +10017cbe: 7829 ldrb r1, [r5, #0] +10017cc0: 5900 ldr r0, [r0, r4] +10017cc2: 2900 cmp r1, #0 +10017cc4: bf06 itte eq +10017cc6: f89d 1139 ldrbeq.w r1, [sp, #313] ; 0x139 +10017cca: 0949 lsreq r1, r1, #5 +10017ccc: 2100 movne r1, #0 +10017cce: f880 104e strb.w r1, [r0, #78] ; 0x4e +10017cd2: a902 add r1, sp, #8 +10017cd4: 782a ldrb r2, [r5, #0] +10017cd6: 4620 mov r0, r4 +10017cd8: f010 fbcd bl 10028476 +10017cdc: f000 f817 bl 10017d0e <.text_32> +10017ce0: f010 fbf0 bl 100284c4 +10017ce4: 782a ldrb r2, [r5, #0] +10017ce6: f105 010d add.w r1, r5, #13 +10017cea: 4620 mov r0, r4 +10017cec: f010 fb9f bl 1002842e +10017cf0: f000 f80d bl 10017d0e <.text_32> +10017cf4: f010 fbf3 bl 100284de +10017cf8: f000 f809 bl 10017d0e <.text_32> +10017cfc: f010 fbd7 bl 100284ae +10017d00: f000 f805 bl 10017d0e <.text_32> +10017d04: f010 fc02 bl 1002850c +10017d08: f50d 7d03 add.w sp, sp, #524 ; 0x20c +10017d0c: bd30 pop {r4, r5, pc} + +10017d0e <.text_32>: +10017d0e: 782a ldrb r2, [r5, #0] +10017d10: a902 add r1, sp, #8 +10017d12: 4620 mov r0, r4 +10017d14: 4770 bx lr + +10017d16 : +10017d16: b510 push {r4, lr} +10017d18: 4604 mov r4, r0 +10017d1a: f7ff fc33 bl 10017584 <_InitPowerOn> +10017d1e: 49a1 ldr r1, [pc, #644] ; (10017fa4 <.text_53>) +10017d20: 6809 ldr r1, [r1, #0] +10017d22: f504 50c8 add.w r0, r4, #6400 ; 0x1900 +10017d26: 090a lsrs r2, r1, #4 +10017d28: 3094 adds r0, #148 ; 0x94 +10017d2a: 0949 lsrs r1, r1, #5 +10017d2c: f002 0201 and.w r2, r2, #1 +10017d30: f001 0101 and.w r1, r1, #1 +10017d34: 7302 strb r2, [r0, #12] +10017d36: f081 0101 eor.w r1, r1, #1 +10017d3a: 7001 strb r1, [r0, #0] +10017d3c: 4620 mov r0, r4 +10017d3e: e8bd 4010 ldmia.w sp!, {r4, lr} +10017d42: e78d b.n 10017c60 <_ReadEfuseInfo8195a> + +10017d44 : +10017d44: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +10017d48: 2926 cmp r1, #38 ; 0x26 +10017d4a: bf18 it ne +10017d4c: 2927 cmpne r1, #39 ; 0x27 +10017d4e: 4604 mov r4, r0 +10017d50: d03a beq.n 10017dc8 +10017d52: 294a cmp r1, #74 ; 0x4a +10017d54: d002 beq.n 10017d5c +10017d56: 294b cmp r1, #75 ; 0x4b +10017d58: d004 beq.n 10017d64 +10017d5a: e031 b.n 10017dc0 +10017d5c: e8bd 41f0 ldmia.w sp!, {r4, r5, r6, r7, r8, lr} +10017d60: f008 bfe7 b.w 10020d32 +10017d64: f241 151c movw r5, #4380 ; 0x111c +10017d68: 7810 ldrb r0, [r2, #0] +10017d6a: 192e adds r6, r5, r4 +10017d6c: f64f 77ff movw r7, #65535 ; 0xffff +10017d70: f240 68a4 movw r8, #1700 ; 0x6a4 +10017d74: b118 cbz r0, 10017d7e +10017d76: 2802 cmp r0, #2 +10017d78: d011 beq.n 10017d9e +10017d7a: d305 bcc.n 10017d88 +10017d7c: e024 b.n 10017dc8 +10017d7e: 592a ldr r2, [r5, r4] +10017d80: f7ff fd6c bl 1001785c <.text_19> +10017d84: 88b2 ldrh r2, [r6, #4] +10017d86: e015 b.n 10017db4 +10017d88: f000 f826 bl 10017dd8 <.text_36+0x2> +10017d8c: f000 f81e bl 10017dcc <.text_35> +10017d90: f000 f821 bl 10017dd6 <.text_36> +10017d94: f020 00c0 bic.w r0, r0, #192 ; 0xc0 +10017d98: f040 0201 orr.w r2, r0, #1 +10017d9c: e007 b.n 10017dae +10017d9e: f000 f81b bl 10017dd8 <.text_36+0x2> +10017da2: f000 f813 bl 10017dcc <.text_35> +10017da6: f000 f816 bl 10017dd6 <.text_36> +10017daa: f020 02c0 bic.w r2, r0, #192 ; 0xc0 +10017dae: f7ff fd55 bl 1001785c <.text_19> +10017db2: 463a mov r2, r7 +10017db4: 4641 mov r1, r8 +10017db6: 4620 mov r0, r4 +10017db8: e8bd 41f0 ldmia.w sp!, {r4, r5, r6, r7, r8, lr} +10017dbc: f00c bf50 b.w 10024c60 +10017dc0: e8bd 41f0 ldmia.w sp!, {r4, r5, r6, r7, r8, lr} +10017dc4: f011 b8fa b.w 10028fbc +10017dc8: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +10017dcc <.text_35>: +10017dcc: 5128 str r0, [r5, r4] +10017dce: 4641 mov r1, r8 +10017dd0: 4620 mov r0, r4 +10017dd2: f00c bf31 b.w 10024c38 + +10017dd6 <.text_36>: +10017dd6: 80b0 strh r0, [r6, #4] +10017dd8: f44f 61c1 mov.w r1, #1544 ; 0x608 +10017ddc: 4620 mov r0, r4 +10017dde: f00c bf31 b.w 10024c44 + +10017de2 : +10017de2: f011 bb7f b.w 100294e4 + +10017de6 : +10017de6: b570 push {r4, r5, r6, lr} +10017de8: 4603 mov r3, r0 +10017dea: f641 30a4 movw r0, #7076 ; 0x1ba4 +10017dee: f641 1554 movw r5, #6484 ; 0x1954 +10017df2: 58c4 ldr r4, [r0, r3] +10017df4: 2001 movs r0, #1 +10017df6: 000e movs r6, r1 +10017df8: d00a beq.n 10017e10 +10017dfa: 2901 cmp r1, #1 +10017dfc: bf18 it ne +10017dfe: 2902 cmpne r1, #2 +10017e00: d018 beq.n 10017e34 +10017e02: 2906 cmp r1, #6 +10017e04: d006 beq.n 10017e14 +10017e06: 2907 cmp r1, #7 +10017e08: d009 beq.n 10017e1e +10017e0a: 290b cmp r1, #11 +10017e0c: d00b beq.n 10017e26 +10017e0e: e00c b.n 10017e2a +10017e10: 5929 ldr r1, [r5, r4] +10017e12: e006 b.n 10017e22 +10017e14: f642 110b movw r1, #10507 ; 0x290b +10017e18: 5d09 ldrb r1, [r1, r4] +10017e1a: 7011 strb r1, [r2, #0] +10017e1c: bd70 pop {r4, r5, r6, pc} +10017e1e: 1929 adds r1, r5, r4 +10017e20: 6fc9 ldr r1, [r1, #124] ; 0x7c +10017e22: 6011 str r1, [r2, #0] +10017e24: bd70 pop {r4, r5, r6, pc} +10017e26: 6010 str r0, [r2, #0] +10017e28: bd70 pop {r4, r5, r6, pc} +10017e2a: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +10017e2e: 4618 mov r0, r3 +10017e30: f011 bbc4 b.w 100295bc +10017e34: bd70 pop {r4, r5, r6, pc} + +10017e36 : +10017e36: b570 push {r4, r5, r6, lr} +10017e38: f641 33a4 movw r3, #7076 ; 0x1ba4 +10017e3c: 2401 movs r4, #1 +10017e3e: 581b ldr r3, [r3, r0] +10017e40: 2906 cmp r1, #6 +10017e42: d002 beq.n 10017e4a +10017e44: 2907 cmp r1, #7 +10017e46: d005 beq.n 10017e54 +10017e48: e041 b.n 10017ece +10017e4a: 7810 ldrb r0, [r2, #0] +10017e4c: f642 110b movw r1, #10507 ; 0x290b +10017e50: 54c8 strb r0, [r1, r3] +10017e52: e03f b.n 10017ed4 +10017e54: 7811 ldrb r1, [r2, #0] +10017e56: f503 56c8 add.w r6, r3, #6400 ; 0x1900 +10017e5a: f503 55c8 add.w r5, r3, #6400 ; 0x1900 +10017e5e: 364c adds r6, #76 ; 0x4c +10017e60: 35a8 adds r5, #168 ; 0xa8 +10017e62: b909 cbnz r1, 10017e68 +10017e64: 2000 movs r0, #0 +10017e66: e030 b.n 10017eca +10017e68: 2901 cmp r1, #1 +10017e6a: d103 bne.n 10017e74 +10017e6c: 6aa8 ldr r0, [r5, #40] ; 0x28 +10017e6e: 0840 lsrs r0, r0, #1 +10017e70: 0040 lsls r0, r0, #1 +10017e72: e02a b.n 10017eca +10017e74: 2902 cmp r1, #2 +10017e76: d103 bne.n 10017e80 +10017e78: 6aa8 ldr r0, [r5, #40] ; 0x28 +10017e7a: f020 0004 bic.w r0, r0, #4 +10017e7e: e024 b.n 10017eca +10017e80: 2903 cmp r1, #3 +10017e82: d103 bne.n 10017e8c +10017e84: 6aa8 ldr r0, [r5, #40] ; 0x28 +10017e86: f020 6080 bic.w r0, r0, #67108864 ; 0x4000000 +10017e8a: e01e b.n 10017eca +10017e8c: 2904 cmp r1, #4 +10017e8e: d104 bne.n 10017e9a +10017e90: 7870 ldrb r0, [r6, #1] +10017e92: f000 00fe and.w r0, r0, #254 ; 0xfe +10017e96: 7070 strb r0, [r6, #1] +10017e98: e01c b.n 10017ed4 +10017e9a: 2905 cmp r1, #5 +10017e9c: d103 bne.n 10017ea6 +10017e9e: 6aa8 ldr r0, [r5, #40] ; 0x28 +10017ea0: f020 0040 bic.w r0, r0, #64 ; 0x40 +10017ea4: e011 b.n 10017eca +10017ea6: 2906 cmp r1, #6 +10017ea8: d114 bne.n 10017ed4 +10017eaa: f895 1028 ldrb.w r1, [r5, #40] ; 0x28 +10017eae: 07c9 lsls r1, r1, #31 +10017eb0: d405 bmi.n 10017ebe +10017eb2: f44f 6145 mov.w r1, #3152 ; 0xc50 +10017eb6: f00c feb9 bl 10024c2c +10017eba: f885 0670 strb.w r0, [r5, #1648] ; 0x670 +10017ebe: 7870 ldrb r0, [r6, #1] +10017ec0: f040 0001 orr.w r0, r0, #1 +10017ec4: 7070 strb r0, [r6, #1] +10017ec6: f06f 4070 mvn.w r0, #4026531840 ; 0xf0000000 +10017eca: 62a8 str r0, [r5, #40] ; 0x28 +10017ecc: e002 b.n 10017ed4 +10017ece: f011 fb73 bl 100295b8 +10017ed2: 4604 mov r4, r0 +10017ed4: 4620 mov r0, r4 +10017ed6: bd70 pop {r4, r5, r6, pc} + +10017ed8 : +10017ed8: b5f8 push {r3, r4, r5, r6, r7, lr} +10017eda: 4606 mov r6, r0 +10017edc: f641 5051 movw r0, #7505 ; 0x1d51 +10017ee0: f506 54d8 add.w r4, r6, #6912 ; 0x1b00 +10017ee4: 5d80 ldrb r0, [r0, r6] +10017ee6: 34ac adds r4, #172 ; 0xac +10017ee8: 2501 movs r5, #1 +10017eea: f641 37a4 movw r7, #7076 ; 0x1ba4 +10017eee: b930 cbnz r0, 10017efe +10017ef0: f44f 5027 mov.w r0, #10688 ; 0x29c0 +10017ef4: f7f8 fc85 bl 10010802 +10017ef8: 51b8 str r0, [r7, r6] +10017efa: b900 cbnz r0, 10017efe +10017efc: 2500 movs r5, #0 +10017efe: 19b9 adds r1, r7, r6 +10017f00: f44f 5027 mov.w r0, #10688 ; 0x29c0 +10017f04: 6048 str r0, [r1, #4] +10017f06: 4620 mov r0, r4 +10017f08: f010 f812 bl 10027f30 +10017f0c: 4826 ldr r0, [pc, #152] ; (10017fa8 <.text_54>) +10017f0e: 4927 ldr r1, [pc, #156] ; (10017fac <.text_55>) +10017f10: 6060 str r0, [r4, #4] +10017f12: 1d20 adds r0, r4, #4 +10017f14: 6041 str r1, [r0, #4] +10017f16: 4926 ldr r1, [pc, #152] ; (10017fb0 <.text_56>) +10017f18: 60c1 str r1, [r0, #12] +10017f1a: 4926 ldr r1, [pc, #152] ; (10017fb4 <.text_57>) +10017f1c: 6101 str r1, [r0, #16] +10017f1e: 4926 ldr r1, [pc, #152] ; (10017fb8 <.text_58>) +10017f20: 6141 str r1, [r0, #20] +10017f22: 4926 ldr r1, [pc, #152] ; (10017fbc <.text_59>) +10017f24: 6181 str r1, [r0, #24] +10017f26: 4926 ldr r1, [pc, #152] ; (10017fc0 <.text_60>) +10017f28: 61c1 str r1, [r0, #28] +10017f2a: 4926 ldr r1, [pc, #152] ; (10017fc4 <.text_61>) +10017f2c: 6201 str r1, [r0, #32] +10017f2e: 4926 ldr r1, [pc, #152] ; (10017fc8 <.text_62>) +10017f30: 6241 str r1, [r0, #36] ; 0x24 +10017f32: 4926 ldr r1, [pc, #152] ; (10017fcc <.text_63>) +10017f34: 62c1 str r1, [r0, #44] ; 0x2c +10017f36: 4926 ldr r1, [pc, #152] ; (10017fd0 <.text_64>) +10017f38: 6301 str r1, [r0, #48] ; 0x30 +10017f3a: 4926 ldr r1, [pc, #152] ; (10017fd4 <.text_65>) +10017f3c: 6401 str r1, [r0, #64] ; 0x40 +10017f3e: 4926 ldr r1, [pc, #152] ; (10017fd8 <.text_66>) +10017f40: 6441 str r1, [r0, #68] ; 0x44 +10017f42: 4926 ldr r1, [pc, #152] ; (10017fdc <.text_67>) +10017f44: 6481 str r1, [r0, #72] ; 0x48 +10017f46: 4926 ldr r1, [pc, #152] ; (10017fe0 <.text_68>) +10017f48: 64c1 str r1, [r0, #76] ; 0x4c +10017f4a: 4926 ldr r1, [pc, #152] ; (10017fe4 <.text_69>) +10017f4c: 6501 str r1, [r0, #80] ; 0x50 +10017f4e: 4926 ldr r1, [pc, #152] ; (10017fe8 <.text_70>) +10017f50: 6541 str r1, [r0, #84] ; 0x54 +10017f52: 4926 ldr r1, [pc, #152] ; (10017fec <.text_71>) +10017f54: 66c1 str r1, [r0, #108] ; 0x6c +10017f56: 4926 ldr r1, [pc, #152] ; (10017ff0 <.text_72>) +10017f58: 6701 str r1, [r0, #112] ; 0x70 +10017f5a: 4926 ldr r1, [pc, #152] ; (10017ff4 <.text_73>) +10017f5c: 6741 str r1, [r0, #116] ; 0x74 +10017f5e: 4926 ldr r1, [pc, #152] ; (10017ff8 <.text_74>) +10017f60: 6781 str r1, [r0, #120] ; 0x78 +10017f62: 4826 ldr r0, [pc, #152] ; (10017ffc <.text_75>) +10017f64: f8c4 00a4 str.w r0, [r4, #164] ; 0xa4 +10017f68: 4825 ldr r0, [pc, #148] ; (10018000 <.text_76>) +10017f6a: f8c4 00a8 str.w r0, [r4, #168] ; 0xa8 +10017f6e: 4628 mov r0, r5 +10017f70: bdf2 pop {r1, r4, r5, r6, r7, pc} + ... + +10017f74 <.text_41>: +10017f74: 1004443c .word 0x1004443c + +10017f78 <.text_42>: +10017f78: 700060ce .word 0x700060ce + +10017f7c <.text_43>: +10017f7c: 000ffff1 .word 0x000ffff1 + +10017f80 <.text_44>: +10017f80: 005ea42b .word 0x005ea42b + +10017f84 <.text_45>: +10017f84: 005ea324 .word 0x005ea324 + +10017f88 <.text_46>: +10017f88: 002fa226 .word 0x002fa226 + +10017f8c <.text_47>: +10017f8c: 10080404 .word 0x10080404 + +10017f90 <.text_48>: +10017f90: 04030201 .word 0x04030201 + +10017f94 <.text_49>: +10017f94: 08070605 .word 0x08070605 + +10017f98 <.text_50>: +10017f98: 000fffff .word 0x000fffff + +10017f9c <.text_51>: +10017f9c: 0201ffff .word 0x0201ffff + +10017fa0 <.text_52>: +10017fa0: 1004439c .word 0x1004439c + +10017fa4 <.text_53>: +10017fa4: 400000e0 .word 0x400000e0 + +10017fa8 <.text_54>: +10017fa8: 10017925 .word 0x10017925 + +10017fac <.text_55>: +10017fac: 10017bdb .word 0x10017bdb + +10017fb0 <.text_56>: +10017fb0: 10020f65 .word 0x10020f65 + +10017fb4 <.text_57>: +10017fb4: 10020fe9 .word 0x10020fe9 + +10017fb8 <.text_58>: +10017fb8: 10021005 .word 0x10021005 + +10017fbc <.text_59>: +10017fbc: 10030395 .word 0x10030395 + +10017fc0 <.text_60>: +10017fc0: 100303a3 .word 0x100303a3 + +10017fc4 <.text_61>: +10017fc4: 10005f23 .word 0x10005f23 + +10017fc8 <.text_62>: +10017fc8: 10005f27 .word 0x10005f27 + +10017fcc <.text_63>: +10017fcc: 10043b69 .word 0x10043b69 + +10017fd0 <.text_64>: +10017fd0: 10043b6b .word 0x10043b6b + +10017fd4 <.text_65>: +10017fd4: 10017c0f .word 0x10017c0f + +10017fd8 <.text_66>: +10017fd8: 10017c13 .word 0x10017c13 + +10017fdc <.text_67>: +10017fdc: 10017d17 .word 0x10017d17 + +10017fe0 <.text_68>: +10017fe0: 100214cb .word 0x100214cb + +10017fe4 <.text_69>: +10017fe4: 10021511 .word 0x10021511 + +10017fe8 <.text_70>: +10017fe8: 10021553 .word 0x10021553 + +10017fec <.text_71>: +10017fec: 10017d45 .word 0x10017d45 + +10017ff0 <.text_72>: +10017ff0: 10017de3 .word 0x10017de3 + +10017ff4 <.text_73>: +10017ff4: 10017de7 .word 0x10017de7 + +10017ff8 <.text_74>: +10017ff8: 10017e37 .word 0x10017e37 + +10017ffc <.text_75>: +10017ffc: 10030c4d .word 0x10030c4d + +10018000 <.text_76>: +10018000: 10030c11 .word 0x10030c11 + +10018004 : +10018004: b74ce000 00000023 ..L.#... + +1001800c : +1001800c: 6840 ldr r0, [r0, #4] +1001800e: 4208 tst r0, r1 +10018010: d001 beq.n 10018016 +10018012: 2001 movs r0, #1 +10018014: 4770 bx lr +10018016: 2000 movs r0, #0 +10018018: 4770 bx lr + +1001801a : +1001801a: b538 push {r3, r4, r5, lr} +1001801c: 4604 mov r4, r0 +1001801e: f504 51c4 add.w r1, r4, #6272 ; 0x1880 +10018022: f604 1228 addw r2, r4, #2344 ; 0x928 +10018026: f891 5032 ldrb.w r5, [r1, #50] ; 0x32 +1001802a: f882 505c strb.w r5, [r2, #92] ; 0x5c +1001802e: 3132 adds r1, #50 ; 0x32 +10018030: 325c adds r2, #92 ; 0x5c +10018032: 784d ldrb r5, [r1, #1] +10018034: 7055 strb r5, [r2, #1] +10018036: f104 030c add.w r3, r4, #12 +1001803a: 784d ldrb r5, [r1, #1] +1001803c: 7095 strb r5, [r2, #2] +1001803e: 221e movs r2, #30 +10018040: f8c3 241c str.w r2, [r3, #1052] ; 0x41c +10018044: f504 5088 add.w r0, r4, #4352 ; 0x1100 +10018048: f203 421c addw r2, r3, #1052 ; 0x41c +1001804c: 2301 movs r3, #1 +1001804e: 6793 str r3, [r2, #120] ; 0x78 +10018050: 30f0 adds r0, #240 ; 0xf0 +10018052: 2300 movs r3, #0 +10018054: 6313 str r3, [r2, #48] ; 0x30 +10018056: f880 3354 strb.w r3, [r0, #852] ; 0x354 +1001805a: 7c0a ldrb r2, [r1, #16] +1001805c: f8c0 2358 str.w r2, [r0, #856] ; 0x358 +10018060: 7c49 ldrb r1, [r1, #17] +10018062: f8c0 135c str.w r1, [r0, #860] ; 0x35c +10018066: 6003 str r3, [r0, #0] +10018068: 6043 str r3, [r0, #4] +1001806a: 6083 str r3, [r0, #8] +1001806c: 65c3 str r3, [r0, #92] ; 0x5c +1001806e: 2101 movs r1, #1 +10018070: 6601 str r1, [r0, #96] ; 0x60 +10018072: f8c0 3364 str.w r3, [r0, #868] ; 0x364 +10018076: f8c0 1368 str.w r1, [r0, #872] ; 0x368 +1001807a: 4620 mov r0, r4 +1001807c: f7ff f8e1 bl 10017242 +10018080: f641 5146 movw r1, #7494 ; 0x1d46 +10018084: 2000 movs r0, #0 +10018086: 5508 strb r0, [r1, r4] +10018088: 2001 movs r0, #1 +1001808a: bd32 pop {r1, r4, r5, pc} + +1001808c : +1001808c: b570 push {r4, r5, r6, lr} +1001808e: 4604 mov r4, r0 +10018090: f7ff f903 bl 1001729a +10018094: f641 5051 movw r0, #7505 ; 0x1d51 +10018098: 5d00 ldrb r0, [r0, r4] +1001809a: b920 cbnz r0, 100180a6 +1001809c: f504 50c8 add.w r0, r4, #6400 ; 0x1900 +100180a0: 305c adds r0, #92 ; 0x5c +100180a2: f7f8 fcda bl 10010a5a +100180a6: f604 0034 addw r0, r4, #2100 ; 0x834 +100180aa: f7f8 fcd6 bl 10010a5a +100180ae: f44f 55c1 mov.w r5, #6176 ; 0x1820 +100180b2: 2110 movs r1, #16 +100180b4: f104 000c add.w r0, r4, #12 +100180b8: f7ff ffa8 bl 1001800c +100180bc: 2801 cmp r0, #1 +100180be: d10b bne.n 100180d8 +100180c0: 2600 movs r6, #0 +100180c2: eb04 0086 add.w r0, r4, r6, lsl #2 +100180c6: 5828 ldr r0, [r5, r0] +100180c8: f500 703d add.w r0, r0, #756 ; 0x2f4 +100180cc: f7f8 fcc5 bl 10010a5a +100180d0: 1c76 adds r6, r6, #1 +100180d2: 2e03 cmp r6, #3 +100180d4: dbf5 blt.n 100180c2 +100180d6: e00b b.n 100180f0 +100180d8: 2108 movs r1, #8 +100180da: f104 000c add.w r0, r4, #12 +100180de: f7ff ff95 bl 1001800c +100180e2: 2801 cmp r0, #1 +100180e4: d104 bne.n 100180f0 +100180e6: 5928 ldr r0, [r5, r4] +100180e8: f500 703d add.w r0, r0, #756 ; 0x2f4 +100180ec: f7f8 fcb5 bl 10010a5a +100180f0: 4620 mov r0, r4 +100180f2: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +100180f6: f7ff b8c5 b.w 10017284 + +100180fa : +100180fa: b538 push {r3, r4, r5, lr} +100180fc: 4604 mov r4, r0 +100180fe: f504 609d add.w r0, r4, #1256 ; 0x4e8 +10018102: f001 fdfa bl 10019cfa +10018106: f604 00d8 addw r0, r4, #2264 ; 0x8d8 +1001810a: f7fe f927 bl 1001635c +1001810e: f604 00ec addw r0, r4, #2284 ; 0x8ec +10018112: f7fe f922 bl 1001635a +10018116: f104 000c add.w r0, r4, #12 +1001811a: f006 fbf5 bl 1001e908 +1001811e: f241 1528 movw r5, #4392 ; 0x1128 +10018122: 5928 ldr r0, [r5, r4] +10018124: b138 cbz r0, 10018136 +10018126: 4620 mov r0, r4 +10018128: f00d f886 bl 10025238 +1001812c: b118 cbz r0, 10018136 +1001812e: 4601 mov r1, r0 +10018130: 4620 mov r0, r4 +10018132: f00c ff35 bl 10024fa0 +10018136: f604 1028 addw r0, r4, #2344 ; 0x928 +1001813a: f013 fc8e bl 1002ba5a <_rtw_free_xmit_priv> +1001813e: 1928 adds r0, r5, r4 +10018140: f00c feae bl 10024ea0 <_rtw_free_sta_priv> +10018144: f504 6032 add.w r0, r4, #2848 ; 0xb20 +10018148: f014 ff50 bl 1002cfec <_rtw_free_recv_priv> +1001814c: 4620 mov r0, r4 +1001814e: f007 ff51 bl 1001fff4 +10018152: f504 5088 add.w r0, r4, #4352 ; 0x1100 +10018156: 30f0 adds r0, #240 ; 0xf0 +10018158: f016 f985 bl 1002e466 +1001815c: 4620 mov r0, r4 +1001815e: f7ff f87b bl 10017258 +10018162: f641 5048 movw r0, #7496 ; 0x1d48 +10018166: 5901 ldr r1, [r0, r4] +10018168: b109 cbz r1, 1001816e +1001816a: 2200 movs r2, #0 +1001816c: 5042 str r2, [r0, r1] +1001816e: 2001 movs r0, #1 +10018170: bd32 pop {r1, r4, r5, pc} + +10018172 : +10018172: b570 push {r4, r5, r6, lr} +10018174: 4604 mov r4, r0 +10018176: f504 56c8 add.w r6, r4, #6400 ; 0x1900 +1001817a: f104 050c add.w r5, r4, #12 +1001817e: 360c adds r6, #12 +10018180: f7ff f85f bl 10017242 +10018184: f641 5146 movw r1, #7494 ; 0x1d46 +10018188: 2000 movs r0, #0 +1001818a: 5508 strb r0, [r1, r4] +1001818c: f504 6219 add.w r2, r4, #2448 ; 0x990 +10018190: 201e movs r0, #30 +10018192: f8c5 041c str.w r0, [r5, #1052] ; 0x41c +10018196: 2100 movs r1, #0 +10018198: 2000 movs r0, #0 +1001819a: 6330 str r0, [r6, #48] ; 0x30 +1001819c: 66b0 str r0, [r6, #104] ; 0x68 +1001819e: f886 004e strb.w r0, [r6, #78] ; 0x4e +100181a2: e9c2 0100 strd r0, r1, [r2] +100181a6: f604 3268 addw r2, r4, #2920 ; 0xb68 +100181aa: e9c2 0100 strd r0, r1, [r2] +100181ae: f885 047c strb.w r0, [r5, #1148] ; 0x47c +100181b2: 6868 ldr r0, [r5, #4] +100181b4: f420 6008 bic.w r0, r0, #2176 ; 0x880 +100181b8: 6068 str r0, [r5, #4] +100181ba: f886 1060 strb.w r1, [r6, #96] ; 0x60 +100181be: f8c4 15c0 str.w r1, [r4, #1472] ; 0x5c0 +100181c2: 2001 movs r0, #1 +100181c4: bd70 pop {r4, r5, r6, pc} + +100181c6 : +100181c6: b538 push {r3, r4, r5, lr} +100181c8: 4604 mov r4, r0 +100181ca: f604 00d8 addw r0, r4, #2264 ; 0x8d8 +100181ce: f7fe f8be bl 1001634e +100181d2: b310 cbz r0, 1001821a +100181d4: f8c4 48e8 str.w r4, [r4, #2280] ; 0x8e8 +100181d8: f604 00ec addw r0, r4, #2284 ; 0x8ec +100181dc: f7fe f8bc bl 10016358 +100181e0: b1d8 cbz r0, 1001821a +100181e2: 4620 mov r0, r4 +100181e4: f016 f90b bl 1002e3fe +100181e8: b1b8 cbz r0, 1001821a +100181ea: 4620 mov r0, r4 +100181ec: f006 fb80 bl 1001e8f0 +100181f0: b198 cbz r0, 1001821a +100181f2: 4620 mov r0, r4 +100181f4: f001 fd68 bl 10019cc8 +100181f8: b178 cbz r0, 1001821a +100181fa: 4621 mov r1, r4 +100181fc: f604 1028 addw r0, r4, #2344 ; 0x928 +10018200: f013 fb48 bl 1002b894 <_rtw_init_xmit_priv> +10018204: b148 cbz r0, 1001821a +10018206: 4621 mov r1, r4 +10018208: f504 6032 add.w r0, r4, #2848 ; 0xb20 +1001820c: f014 fe97 bl 1002cf3e <_rtw_init_recv_priv> +10018210: b118 cbz r0, 1001821a +10018212: 4620 mov r0, r4 +10018214: f00c fd8f bl 10024d36 <_rtw_init_sta_priv> +10018218: b908 cbnz r0, 1001821e +1001821a: 2500 movs r5, #0 +1001821c: e00f b.n 1001823e +1001821e: f504 508d add.w r0, r4, #4512 ; 0x11a0 +10018222: 6004 str r4, [r0, #0] +10018224: 4620 mov r0, r4 +10018226: f00c fffa bl 1002521e +1001822a: 4620 mov r0, r4 +1001822c: f007 fe8a bl 1001ff44 +10018230: 4620 mov r0, r4 +10018232: f7ff fef2 bl 1001801a +10018236: 4605 mov r5, r0 +10018238: 4620 mov r0, r4 +1001823a: f7ff f818 bl 1001726e +1001823e: 4628 mov r0, r5 +10018240: bd32 pop {r1, r4, r5, pc} + +10018242 : +10018242: b120 cbz r0, 1001824e +10018244: f500 52e5 add.w r2, r0, #7328 ; 0x1ca0 +10018248: 2101 movs r1, #1 +1001824a: 6011 str r1, [r2, #0] +1001824c: e755 b.n 100180fa +1001824e: 4770 bx lr + +10018250 : +10018250: b530 push {r4, r5, lr} +10018252: b083 sub sp, #12 +10018254: 4604 mov r4, r0 +10018256: 4825 ldr r0, [pc, #148] ; (100182ec <.text_10>) +10018258: f20f 01d8 addw r1, pc, #216 ; 0xd8 +1001825c: 9000 str r0, [sp, #0] +1001825e: 2501 movs r5, #1 +10018260: f504 50e0 add.w r0, r4, #7168 ; 0x1c00 +10018264: 9401 str r4, [sp, #4] +10018266: 2301 movs r3, #1 +10018268: f44f 62b8 mov.w r2, #1472 ; 0x5c0 +1001826c: 30ec adds r0, #236 ; 0xec +1001826e: f7f8 fc43 bl 10010af8 +10018272: 2801 cmp r0, #1 +10018274: 481e ldr r0, [pc, #120] ; (100182f0 <.text_11>) +10018276: f20f 01d0 addw r1, pc, #208 ; 0xd0 +1001827a: 9000 str r0, [sp, #0] +1001827c: bf18 it ne +1001827e: 2500 movne r5, #0 +10018280: f504 50e8 add.w r0, r4, #7424 ; 0x1d00 +10018284: 9401 str r4, [sp, #4] +10018286: 2301 movs r3, #1 +10018288: f44f 7280 mov.w r2, #256 ; 0x100 +1001828c: 1d00 adds r0, r0, #4 +1001828e: f7f8 fc33 bl 10010af8 +10018292: 2801 cmp r0, #1 +10018294: 4817 ldr r0, [pc, #92] ; (100182f4 <.text_12>) +10018296: f20f 01c4 addw r1, pc, #196 ; 0xc4 +1001829a: 9000 str r0, [sp, #0] +1001829c: bf18 it ne +1001829e: 2500 movne r5, #0 +100182a0: f504 50e0 add.w r0, r4, #7168 ; 0x1c00 +100182a4: 9401 str r4, [sp, #4] +100182a6: 2302 movs r3, #2 +100182a8: f44f 7280 mov.w r2, #256 ; 0x100 +100182ac: 30bc adds r0, #188 ; 0xbc +100182ae: f7f8 fc23 bl 10010af8 +100182b2: 2801 cmp r0, #1 +100182b4: 4810 ldr r0, [pc, #64] ; (100182f8 <.text_13>) +100182b6: f20f 01bc addw r1, pc, #188 ; 0xbc +100182ba: 9000 str r0, [sp, #0] +100182bc: bf18 it ne +100182be: 2500 movne r5, #0 +100182c0: f504 50e0 add.w r0, r4, #7168 ; 0x1c00 +100182c4: 9401 str r4, [sp, #4] +100182c6: 2302 movs r3, #2 +100182c8: f44f 7200 mov.w r2, #512 ; 0x200 +100182cc: 30d4 adds r0, #212 ; 0xd4 +100182ce: f7f8 fc13 bl 10010af8 +100182d2: 2801 cmp r0, #1 +100182d4: bf12 itee ne +100182d6: 2500 movne r5, #0 +100182d8: f504 50e7 addeq.w r0, r4, #7392 ; 0x1ce0 +100182dc: f7f8 fae6 bleq 100108ac +100182e0: 4620 mov r0, r4 +100182e2: f7ff f8da bl 1001749a +100182e6: 4628 mov r0, r5 +100182e8: bd3e pop {r1, r2, r3, r4, r5, pc} + ... + +100182ec <.text_10>: +100182ec: 1002e0bd .word 0x1002e0bd + +100182f0 <.text_11>: +100182f0: 1002cdc7 .word 0x1002cdc7 + +100182f4 <.text_12>: +100182f4: 1003fb45 .word 0x1003fb45 + +100182f8 <.text_13>: +100182f8: 10016409 .word 0x10016409 + +100182fc : +100182fc: b510 push {r4, lr} +100182fe: 4604 mov r4, r0 +10018300: f504 50e0 add.w r0, r4, #7168 ; 0x1c00 +10018304: 30d4 adds r0, #212 ; 0xd4 +10018306: f7f8 fc06 bl 10010b16 +1001830a: f504 50e0 add.w r0, r4, #7168 ; 0x1c00 +1001830e: 30bc adds r0, #188 ; 0xbc +10018310: f7f8 fc01 bl 10010b16 +10018314: f504 50e0 add.w r0, r4, #7168 ; 0x1c00 +10018318: 30ec adds r0, #236 ; 0xec +1001831a: f7f8 fbfc bl 10010b16 +1001831e: f504 50e8 add.w r0, r4, #7424 ; 0x1d00 +10018322: 1d00 adds r0, r0, #4 +10018324: f7f8 fbf7 bl 10010b16 +10018328: 4620 mov r0, r4 +1001832a: e8bd 4010 ldmia.w sp!, {r4, lr} +1001832e: f7ff b8bb b.w 100174a8 + ... + +10018334 : +10018334: 7472 5f77 6572 7663 745f 7361 6c6b 7465 rtw_recv_tasklet +10018344: 0000 0000 .... + +10018348 : +10018348: 7472 5f77 6d78 7469 745f 7361 6c6b 7465 rtw_xmit_tasklet +10018358: 0000 0000 .... + +1001835c : +1001835c: 7472 5f77 6e69 6574 7272 7075 5f74 6874 rtw_interrupt_th +1001836c: 6572 6461 0000 0000 read.... + +10018374 : +10018374: 6d63 5f64 6874 6572 6461 0000 cmd_thread.. + +10018380 : +10018380: f8df f000 ldr.w pc, [pc] ; 10018384 +10018384: 0001352d .word 0x0001352d + +10018388 : +10018388: f8df f000 ldr.w pc, [pc] ; 1001838c +1001838c: 00013449 .word 0x00013449 + +10018390 : +10018390: f8df f000 ldr.w pc, [pc] ; 10018394 +10018394: 00013611 .word 0x00013611 + +10018398 : +10018398: f8df f000 ldr.w pc, [pc] ; 1001839c +1001839c: 000134dd .word 0x000134dd + +100183a0 : +100183a0: f8df f000 ldr.w pc, [pc] ; 100183a4 +100183a4: 00013591 .word 0x00013591 + +100183a8 : +100183a8: f8df f000 ldr.w pc, [pc] ; 100183ac +100183ac: 00013a15 .word 0x00013a15 + +100183b0 : +100183b0: 6840 ldr r0, [r0, #4] +100183b2: 4208 tst r0, r1 +100183b4: d001 beq.n 100183ba +100183b6: 2001 movs r0, #1 +100183b8: 4770 bx lr +100183ba: 2000 movs r0, #0 +100183bc: 4770 bx lr + +100183be : +100183be: b510 push {r4, lr} +100183c0: 4604 mov r4, r0 +100183c2: f204 40dc addw r0, r4, #1244 ; 0x4dc +100183c6: f7f8 fac6 bl 10010956 +100183ca: 4620 mov r0, r4 +100183cc: e8bd 4010 ldmia.w sp!, {r4, lr} +100183d0: f001 b937 b.w 10019642 + +100183d4 : +100183d4: b5f8 push {r3, r4, r5, r6, r7, lr} +100183d6: 4604 mov r4, r0 +100183d8: f104 060c add.w r6, r4, #12 +100183dc: f504 679d add.w r7, r4, #1256 ; 0x4e8 +100183e0: 2000 movs r0, #0 +100183e2: f886 04d4 strb.w r0, [r6, #1236] ; 0x4d4 +100183e6: f887 0348 strb.w r0, [r7, #840] ; 0x348 +100183ea: f504 5588 add.w r5, r4, #4352 ; 0x1100 +100183ee: 3528 adds r5, #40 ; 0x28 +100183f0: 4620 mov r0, r4 +100183f2: f001 f8b6 bl 10019562 +100183f6: 2000 movs r0, #0 +100183f8: f8c7 0110 str.w r0, [r7, #272] ; 0x110 +100183fc: 4620 mov r0, r4 +100183fe: f00c fea5 bl 1002514c +10018402: 4620 mov r0, r4 +10018404: f00c ff18 bl 10025238 +10018408: f001 f962 bl 100196d0 <.text_44> +1001840c: f000 f807 bl 1001841e <.text_5> +10018410: f001 f959 bl 100196c6 <.text_43> +10018414: f506 609a add.w r0, r6, #1232 ; 0x4d0 +10018418: f7f8 faa4 bl 10010964 +1001841c: bdf1 pop {r0, r4, r5, r6, r7, pc} + +1001841e <.text_5>: +1001841e: 4639 mov r1, r7 +10018420: 4620 mov r0, r4 +10018422: f00c bdbd b.w 10024fa0 + +10018426 : +10018426: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +1001842a: f500 5188 add.w r1, r0, #4352 ; 0x1100 +1001842e: f101 0928 add.w r9, r1, #40 ; 0x28 +10018432: b084 sub sp, #16 +10018434: f100 0698 add.w r6, r0, #152 ; 0x98 +10018438: f8b9 00c2 ldrh.w r0, [r9, #194] ; 0xc2 +1001843c: f8ad 0004 strh.w r0, [sp, #4] +10018440: f106 087c add.w r8, r6, #124 ; 0x7c +10018444: 6fb0 ldr r0, [r6, #120] ; 0x78 +10018446: f1a0 030c sub.w r3, r0, #12 +1001844a: 2500 movs r5, #0 +1001844c: aa00 add r2, sp, #0 +1001844e: 2105 movs r1, #5 +10018450: f108 000c add.w r0, r8, #12 +10018454: f7fb fd14 bl 10013e80 +10018458: 2800 cmp r0, #0 +1001845a: bf1c itt ne +1001845c: 9900 ldrne r1, [sp, #0] +1001845e: 2900 cmpne r1, #0 +10018460: 46c2 mov sl, r8 +10018462: d009 beq.n 10018478 +10018464: 1c89 adds r1, r1, #2 +10018466: 9100 str r1, [sp, #0] +10018468: 180f adds r7, r1, r0 +1001846a: 6fb1 ldr r1, [r6, #120] ; 0x78 +1001846c: 9a00 ldr r2, [sp, #0] +1001846e: 1a09 subs r1, r1, r0 +10018470: 4451 add r1, sl +10018472: 1a8c subs r4, r1, r2 +10018474: 4680 mov r8, r0 +10018476: e018 b.n 100184aa +10018478: 9500 str r5, [sp, #0] +1001847a: aa02 add r2, sp, #8 +1001847c: 68f0 ldr r0, [r6, #12] +1001847e: f100 040e add.w r4, r0, #14 +10018482: 6fb0 ldr r0, [r6, #120] ; 0x78 +10018484: f1a0 030c sub.w r3, r0, #12 +10018488: 2101 movs r1, #1 +1001848a: f108 000c add.w r0, r8, #12 +1001848e: f7fb fcf7 bl 10013e80 +10018492: b110 cbz r0, 1001849a +10018494: 9802 ldr r0, [sp, #8] +10018496: 1c80 adds r0, r0, #2 +10018498: 1904 adds r4, r0, r4 +1001849a: 1ce0 adds r0, r4, #3 +1001849c: 6fb1 ldr r1, [r6, #120] ; 0x78 +1001849e: eb00 0708 add.w r7, r0, r8 +100184a2: 1a08 subs r0, r1, r0 +100184a4: 9900 ldr r1, [sp, #0] +100184a6: 1a44 subs r4, r0, r1 +100184a8: 46b8 mov r8, r7 +100184aa: b154 cbz r4, 100184c2 +100184ac: 4620 mov r0, r4 +100184ae: f7f8 f9a3 bl 100107f8 +100184b2: 0005 movs r5, r0 +100184b4: bf18 it ne +100184b6: 2f00 cmpne r7, #0 +100184b8: d003 beq.n 100184c2 +100184ba: 4622 mov r2, r4 +100184bc: 4639 mov r1, r7 +100184be: f7f8 f9a6 bl 1001080e +100184c2: 2005 movs r0, #5 +100184c4: f808 0b01 strb.w r0, [r8], #1 +100184c8: f44f 427f mov.w r2, #65280 ; 0xff00 +100184cc: f8b9 10c2 ldrh.w r1, [r9, #194] ; 0xc2 +100184d0: 4211 tst r1, r2 +100184d2: bf1d ittte ne +100184d4: 20fc movne r0, #252 ; 0xfc +100184d6: 4201 tstne r1, r0 +100184d8: 2005 movne r0, #5 +100184da: 2004 moveq r0, #4 +100184dc: 9000 str r0, [sp, #0] +100184de: 9800 ldr r0, [sp, #0] +100184e0: f808 0b01 strb.w r0, [r8], #1 +100184e4: 2000 movs r0, #0 +100184e6: f808 0b01 strb.w r0, [r8], #1 +100184ea: 2001 movs r0, #1 +100184ec: f808 0b01 strb.w r0, [r8], #1 +100184f0: f899 00c2 ldrb.w r0, [r9, #194] ; 0xc2 +100184f4: 07c0 lsls r0, r0, #31 +100184f6: bf4c ite mi +100184f8: 2001 movmi r0, #1 +100184fa: 2000 movpl r0, #0 +100184fc: f808 0b01 strb.w r0, [r8], #1 +10018500: 9800 ldr r0, [sp, #0] +10018502: 2804 cmp r0, #4 +10018504: d104 bne.n 10018510 +10018506: f89d 0004 ldrb.w r0, [sp, #4] +1001850a: f808 0b01 strb.w r0, [r8], #1 +1001850e: e008 b.n 10018522 +10018510: 2805 cmp r0, #5 +10018512: d106 bne.n 10018522 +10018514: 2202 movs r2, #2 +10018516: a901 add r1, sp, #4 +10018518: 4640 mov r0, r8 +1001851a: f7f8 f978 bl 1001080e +1001851e: f108 0802 add.w r8, r8, #2 +10018522: b145 cbz r5, 10018536 +10018524: 4622 mov r2, r4 +10018526: 4629 mov r1, r5 +10018528: 4640 mov r0, r8 +1001852a: f7f8 f970 bl 1001080e +1001852e: 4621 mov r1, r4 +10018530: 4628 mov r0, r5 +10018532: f7f8 f96b bl 1001080c +10018536: eba8 000a sub.w r0, r8, sl +1001853a: 1820 adds r0, r4, r0 +1001853c: 67b0 str r0, [r6, #120] ; 0x78 +1001853e: e8bd 87ff ldmia.w sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, pc} + +10018542 : +10018542: b5f0 push {r4, r5, r6, r7, lr} +10018544: f500 72c0 add.w r2, r0, #384 ; 0x180 +10018548: e9d2 450a ldrd r4, r5, [r2, #40] ; 0x28 +1001854c: e9d2 6704 ldrd r6, r7, [r2, #16] +10018550: 2100 movs r1, #0 +10018552: 42bd cmp r5, r7 +10018554: bf0c ite eq +10018556: 42b4 cmpeq r4, r6 +10018558: 2101 movne r1, #1 +1001855a: e9d0 4560 ldrd r4, r5, [r0, #384] ; 0x180 +1001855e: e9c2 4506 strd r4, r5, [r2, #24] +10018562: 4608 mov r0, r1 +10018564: e9d2 4502 ldrd r4, r5, [r2, #8] +10018568: e9c2 4508 strd r4, r5, [r2, #32] +1001856c: e9d2 4504 ldrd r4, r5, [r2, #16] +10018570: e9c2 450a strd r4, r5, [r2, #40] ; 0x28 +10018574: bdf0 pop {r4, r5, r6, r7, pc} + +10018576 : +10018576: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +1001857a: 4680 mov r8, r0 +1001857c: f508 5688 add.w r6, r8, #4352 ; 0x1100 +10018580: 3628 adds r6, #40 ; 0x28 +10018582: b085 sub sp, #20 +10018584: f106 0a90 add.w sl, r6, #144 ; 0x90 +10018588: 2500 movs r5, #0 +1001858a: f000 f8a7 bl 100186dc <.text_11> +1001858e: f106 0484 add.w r4, r6, #132 ; 0x84 +10018592: 6827 ldr r7, [r4, #0] +10018594: e022 b.n 100185dc +10018596: f507 7009 add.w r0, r7, #548 ; 0x224 +1001859a: 1bc0 subs r0, r0, r7 +1001859c: eba7 0900 sub.w r9, r7, r0 +100185a0: 683f ldr r7, [r7, #0] +100185a2: f8d9 022c ldr.w r0, [r9, #556] ; 0x22c +100185a6: b1c8 cbz r0, 100185dc +100185a8: 1e40 subs r0, r0, #1 +100185aa: f8c9 022c str.w r0, [r9, #556] ; 0x22c +100185ae: d115 bne.n 100185dc +100185b0: f509 7009 add.w r0, r9, #548 ; 0x224 +100185b4: f7f8 f956 bl 10010864 +100185b8: f000 f88c bl 100186d4 <.text_10> +100185bc: a903 add r1, sp, #12 +100185be: f106 0018 add.w r0, r6, #24 +100185c2: f7f8 f9a7 bl 10010914 +100185c6: 4649 mov r1, r9 +100185c8: 4640 mov r0, r8 +100185ca: f00c fce9 bl 10024fa0 +100185ce: a903 add r1, sp, #12 +100185d0: f106 0018 add.w r0, r6, #24 +100185d4: f7f8 f99f bl 10010916 +100185d8: f000 f880 bl 100186dc <.text_11> +100185dc: 4639 mov r1, r7 +100185de: 4620 mov r0, r4 +100185e0: f7f8 f9b3 bl 1001094a +100185e4: 2800 cmp r0, #0 +100185e6: d0d6 beq.n 10018596 +100185e8: f000 f874 bl 100186d4 <.text_10> +100185ec: f106 0a8c add.w sl, r6, #140 ; 0x8c +100185f0: f000 f874 bl 100186dc <.text_11> +100185f4: f106 007c add.w r0, r6, #124 ; 0x7c +100185f8: 9004 str r0, [sp, #16] +100185fa: a77f add r7, pc, #508 ; (adr r7, 100187f8 <.text_13>) +100185fc: 6804 ldr r4, [r0, #0] +100185fe: f20f 0994 addw r9, pc, #148 ; 0x94 +10018602: e01a b.n 1001863a +10018604: f50b 7007 add.w r0, fp, #540 ; 0x21c +10018608: f7f8 f92c bl 10010864 +1001860c: 4638 mov r0, r7 +1001860e: f7f3 fe78 bl 1000c302 +10018612: f10b 00f4 add.w r0, fp, #244 ; 0xf4 +10018616: 7e41 ldrb r1, [r0, #25] +10018618: 9102 str r1, [sp, #8] +1001861a: 7e01 ldrb r1, [r0, #24] +1001861c: 9101 str r1, [sp, #4] +1001861e: 7dc1 ldrb r1, [r0, #23] +10018620: 9100 str r1, [sp, #0] +10018622: 7d83 ldrb r3, [r0, #22] +10018624: 7d42 ldrb r2, [r0, #21] +10018626: 7d01 ldrb r1, [r0, #20] +10018628: 4648 mov r0, r9 +1001862a: f7f3 fe6a bl 1000c302 +1001862e: 2203 movs r2, #3 +10018630: 4659 mov r1, fp +10018632: 4640 mov r0, r8 +10018634: f000 ff4b bl 100194ce +10018638: 4605 mov r5, r0 +1001863a: 9804 ldr r0, [sp, #16] +1001863c: 4621 mov r1, r4 +1001863e: f7f8 f984 bl 1001094a +10018642: b9f0 cbnz r0, 10018682 +10018644: f504 7007 add.w r0, r4, #540 ; 0x21c +10018648: 1b00 subs r0, r0, r4 +1001864a: eba4 0b00 sub.w fp, r4, r0 +1001864e: 6824 ldr r4, [r4, #0] +10018650: 4658 mov r0, fp +10018652: f7ff ff76 bl 10018542 +10018656: b118 cbz r0, 10018660 +10018658: f8d6 009c ldr.w r0, [r6, #156] ; 0x9c +1001865c: f8cb 022c str.w r0, [fp, #556] ; 0x22c +10018660: f8db 022c ldr.w r0, [fp, #556] ; 0x22c +10018664: 2800 cmp r0, #0 +10018666: d0e8 beq.n 1001863a +10018668: 1e40 subs r0, r0, #1 +1001866a: f8cb 022c str.w r0, [fp, #556] ; 0x22c +1001866e: d0c9 beq.n 10018604 +10018670: f8db 00f4 ldr.w r0, [fp, #244] ; 0xf4 +10018674: 2809 cmp r0, #9 +10018676: d3e0 bcc.n 1001863a +10018678: 4659 mov r1, fp +1001867a: 4640 mov r0, r8 +1001867c: f014 fa2f bl 1002cade +10018680: e7db b.n 1001863a +10018682: f000 f827 bl 100186d4 <.text_10> +10018686: 4629 mov r1, r5 +10018688: 4640 mov r0, r8 +1001868a: f000 fddf bl 1001924c +1001868e: b005 add sp, #20 +10018690: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +10018694 : +10018694: 5452 384c 3931 4135 445b 6972 6576 5d72 RTL8195A[Driver] +100186a4: 203a 7341 636f 6520 7078 7269 2065 3025 : Asoc expire %0 +100186b4: 7832 253a 3230 3a78 3025 7832 253a 3230 2x:%02x:%02x:%02 +100186c4: 3a78 3025 7832 253a 3230 0a78 0000 0000 x:%02x:%02x..... + +100186d4 <.text_10>: +100186d4: a903 add r1, sp, #12 +100186d6: 4650 mov r0, sl +100186d8: f7f8 b91d b.w 10010916 + +100186dc <.text_11>: +100186dc: a903 add r1, sp, #12 +100186de: 4650 mov r0, sl +100186e0: f7f8 b918 b.w 10010914 + +100186e4 : +100186e4: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +100186e8: 468a mov sl, r1 +100186ea: 2600 movs r6, #0 +100186ec: 2700 movs r7, #0 +100186ee: 4680 mov r8, r0 +100186f0: f1ba 0f00 cmp.w sl, #0 +100186f4: 4693 mov fp, r2 +100186f6: f108 0498 add.w r4, r8, #152 ; 0x98 +100186fa: d07b beq.n 100187f4 +100186fc: f89a 00f8 ldrb.w r0, [sl, #248] ; 0xf8 +10018700: 07c0 lsls r0, r0, #31 +10018702: f50a 79fa add.w r9, sl, #500 ; 0x1f4 +10018706: d575 bpl.n 100187f4 +10018708: 2500 movs r5, #0 +1001870a: eb05 000a add.w r0, r5, sl +1001870e: f890 0158 ldrb.w r0, [r0, #344] ; 0x158 +10018712: b120 cbz r0, 1001871e +10018714: f000 007f and.w r0, r0, #127 ; 0x7f +10018718: f7ff fe36 bl 10018388 +1001871c: 4307 orrs r7, r0 +1001871e: 1c6d adds r5, r5, #1 +10018720: 2d10 cmp r5, #16 +10018722: d3f2 bcc.n 1001870a +10018724: f8d9 0000 ldr.w r0, [r9] +10018728: b328 cbz r0, 10018776 +1001872a: f10d 0201 add.w r2, sp, #1 +1001872e: 2116 movs r1, #22 +10018730: 4640 mov r0, r8 +10018732: f7fe fdf7 bl 10017324 +10018736: f89d 0001 ldrb.w r0, [sp, #1] +1001873a: 2802 cmp r0, #2 +1001873c: bf0c ite eq +1001873e: 2110 moveq r1, #16 +10018740: 2108 movne r1, #8 +10018742: 2500 movs r5, #0 +10018744: 2201 movs r2, #1 +10018746: e012 b.n 1001876e +10018748: 10a8 asrs r0, r5, #2 +1001874a: eb05 7050 add.w r0, r5, r0, lsr #29 +1001874e: 10c0 asrs r0, r0, #3 +10018750: eb00 0309 add.w r3, r0, r9 +10018754: eba5 00c0 sub.w r0, r5, r0, lsl #3 +10018758: 7c5b ldrb r3, [r3, #17] +1001875a: fa02 f000 lsl.w r0, r2, r0 +1001875e: 4203 tst r3, r0 +10018760: d004 beq.n 1001876c +10018762: f105 000c add.w r0, r5, #12 +10018766: fa02 f000 lsl.w r0, r2, r0 +1001876a: 4307 orrs r7, r0 +1001876c: 1c6d adds r5, r5, #1 +1001876e: 428d cmp r5, r1 +10018770: dbea blt.n 10018748 +10018772: f899 600a ldrb.w r6, [r9, #10] +10018776: 6ce1 ldr r1, [r4, #76] ; 0x4c +10018778: f8df 0978 ldr.w r0, [pc, #2424] ; 100190f4 <.text_27> +1001877c: 290f cmp r1, #15 +1001877e: d304 bcc.n 1001878a +10018780: 4207 tst r7, r0 +10018782: bf0c ite eq +10018784: 2004 moveq r0, #4 +10018786: 2014 movne r0, #20 +10018788: e008 b.n 1001879c +1001878a: 4207 tst r7, r0 +1001878c: bf18 it ne +1001878e: 200b movne r0, #11 +10018790: d104 bne.n 1001879c +10018792: f417 6f7f tst.w r7, #4080 ; 0xff0 +10018796: bf14 ite ne +10018798: 2003 movne r0, #3 +1001879a: 2001 moveq r0, #1 +1001879c: f50a 74bb add.w r4, sl, #374 ; 0x176 +100187a0: 71a0 strb r0, [r4, #6] +100187a2: f00d f874 bl 1002588e +100187a6: 4681 mov r9, r0 +100187a8: 0138 lsls r0, r7, #4 +100187aa: 0900 lsrs r0, r0, #4 +100187ac: f00d fe62 bl 10026474 +100187b0: f000 053f and.w r5, r0, #63 ; 0x3f +100187b4: f10a 00f8 add.w r0, sl, #248 ; 0xf8 +100187b8: 6841 ldr r1, [r0, #4] +100187ba: 2908 cmp r1, #8 +100187bc: d21a bcs.n 100187f4 +100187be: 7a00 ldrb r0, [r0, #8] +100187c0: f000 001f and.w r0, r0, #31 +100187c4: f040 0080 orr.w r0, r0, #128 ; 0x80 +100187c8: f88d 0000 strb.w r0, [sp] +100187cc: 2e01 cmp r6, #1 +100187ce: bf04 itt eq +100187d0: f040 0020 orreq.w r0, r0, #32 +100187d4: f88d 0000 strbeq.w r0, [sp] +100187d8: 465b mov r3, fp +100187da: aa00 add r2, sp, #0 +100187dc: ea47 7109 orr.w r1, r7, r9, lsl #28 +100187e0: 4640 mov r0, r8 +100187e2: f7fe fe4b bl 1001747c +100187e6: 2e01 cmp r6, #1 +100187e8: bf08 it eq +100187ea: f045 0540 orreq.w r5, r5, #64 ; 0x40 +100187ee: f88a 9176 strb.w r9, [sl, #374] ; 0x176 +100187f2: 7065 strb r5, [r4, #1] +100187f4: e8bd 8ff1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +100187f8 <.text_13>: +100187f8: 00000d0a .word 0x00000d0a + +100187fc : +100187fc: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} +10018800: 4681 mov r9, r0 +10018802: b083 sub sp, #12 +10018804: f109 0798 add.w r7, r9, #152 ; 0x98 +10018808: f00c fd16 bl 10025238 +1001880c: 0005 movs r5, r0 +1001880e: d05f beq.n 100188d0 +10018810: f105 06f8 add.w r6, r5, #248 ; 0xf8 +10018814: 2000 movs r0, #0 +10018816: 6070 str r0, [r6, #4] +10018818: 2248 movs r2, #72 ; 0x48 +1001881a: 2001 movs r0, #1 +1001881c: 60b0 str r0, [r6, #8] +1001881e: 2100 movs r1, #0 +10018820: 2000 movs r0, #0 +10018822: 60f0 str r0, [r6, #12] +10018824: f8c5 01f4 str.w r0, [r5, #500] ; 0x1f4 +10018828: 61b0 str r0, [r6, #24] +1001882a: f505 70c0 add.w r0, r5, #384 ; 0x180 +1001882e: f7f8 f803 bl 10010838 +10018832: f107 0064 add.w r0, r7, #100 ; 0x64 +10018836: f7ff fdab bl 10018390 +1001883a: 4680 mov r8, r0 +1001883c: 2201 movs r2, #1 +1001883e: 4641 mov r1, r8 +10018840: f107 0064 add.w r0, r7, #100 ; 0x64 +10018844: f7ff fda8 bl 10018398 +10018848: 4642 mov r2, r8 +1001884a: f107 0164 add.w r1, r7, #100 ; 0x64 +1001884e: f505 70ac add.w r0, r5, #344 ; 0x158 +10018852: f7f7 ffdc bl 1001080e +10018856: f8c6 8070 str.w r8, [r6, #112] ; 0x70 +1001885a: 2400 movs r4, #0 +1001885c: e008 b.n 10018870 +1001885e: 1960 adds r0, r4, r5 +10018860: f890 0158 ldrb.w r0, [r0, #344] ; 0x158 +10018864: b118 cbz r0, 1001886e +10018866: f000 007f and.w r0, r0, #127 ; 0x7f +1001886a: f7ff fd8d bl 10018388 +1001886e: 1c64 adds r4, r4, #1 +10018870: 4544 cmp r4, r8 +10018872: dbf4 blt.n 1001885e +10018874: 6cf8 ldr r0, [r7, #76] ; 0x4c +10018876: 280f cmp r0, #15 +10018878: bf27 ittee cs +1001887a: 2004 movcs r0, #4 +1001887c: f44f 77a8 movcs.w r7, #336 ; 0x150 +10018880: 2001 movcc r0, #1 +10018882: 270f movcc r7, #15 +10018884: f00d f803 bl 1002588e +10018888: 4680 mov r8, r0 +1001888a: 4638 mov r0, r7 +1001888c: f00d fdf2 bl 10026474 +10018890: 4604 mov r4, r0 +10018892: 2301 movs r3, #1 +10018894: 462a mov r2, r5 +10018896: 2100 movs r1, #0 +10018898: 4648 mov r0, r9 +1001889a: f7fe fd63 bl 10017364 +1001889e: 7a30 ldrb r0, [r6, #8] +100188a0: f000 001f and.w r0, r0, #31 +100188a4: f040 0080 orr.w r0, r0, #128 ; 0x80 +100188a8: f88d 0004 strb.w r0, [sp, #4] +100188ac: 2300 movs r3, #0 +100188ae: aa01 add r2, sp, #4 +100188b0: ea47 7108 orr.w r1, r7, r8, lsl #28 +100188b4: 4648 mov r0, r9 +100188b6: f7fe fde1 bl 1001747c +100188ba: f885 8176 strb.w r8, [r5, #374] ; 0x176 +100188be: f004 003f and.w r0, r4, #63 ; 0x3f +100188c2: f885 0177 strb.w r0, [r5, #375] ; 0x177 +100188c6: f000 f805 bl 100188d4 <.text_15> +100188ca: 2001 movs r0, #1 +100188cc: f000 f806 bl 100188dc <.text_16> +100188d0: e8bd 83f7 ldmia.w sp!, {r0, r1, r2, r4, r5, r6, r7, r8, r9, pc} + +100188d4 <.text_15>: +100188d4: a900 add r1, sp, #0 +100188d6: 4628 mov r0, r5 +100188d8: f7f8 b81c b.w 10010914 + +100188dc <.text_16>: +100188dc: f8c5 00f8 str.w r0, [r5, #248] ; 0xf8 +100188e0: a900 add r1, sp, #0 +100188e2: 4628 mov r0, r5 +100188e4: f7f8 b817 b.w 10010916 + +100188e8 : +100188e8: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +100188ec: 4688 mov r8, r1 +100188ee: f108 04f8 add.w r4, r8, #248 ; 0xf8 +100188f2: 4681 mov r9, r0 +100188f4: 6860 ldr r0, [r4, #4] +100188f6: 1c40 adds r0, r0, #1 +100188f8: 60a0 str r0, [r4, #8] +100188fa: f509 659d add.w r5, r9, #1256 ; 0x4e8 +100188fe: f209 4654 addw r6, r9, #1108 ; 0x454 +10018902: f508 77fa add.w r7, r8, #500 ; 0x1f4 +10018906: 2301 movs r3, #1 +10018908: 4642 mov r2, r8 +1001890a: 2100 movs r1, #0 +1001890c: 4648 mov r0, r9 +1001890e: f7fe fd29 bl 10017364 +10018912: f241 10f0 movw r0, #4592 ; 0x11f0 +10018916: 4641 mov r1, r8 +10018918: f850 0009 ldr.w r0, [r0, r9] +1001891c: 2802 cmp r0, #2 +1001891e: bf0c ite eq +10018920: 2001 moveq r0, #1 +10018922: 2000 movne r0, #0 +10018924: 61a0 str r0, [r4, #24] +10018926: 4648 mov r0, r9 +10018928: f00d fba6 bl 10026078 +1001892c: 6838 ldr r0, [r7, #0] +1001892e: b1a0 cbz r0, 1001895a +10018930: 6870 ldr r0, [r6, #4] +10018932: 6078 str r0, [r7, #4] +10018934: 89f1 ldrh r1, [r6, #14] +10018936: 89f8 ldrh r0, [r7, #14] +10018938: 4001 ands r1, r0 +1001893a: f011 0f60 tst.w r1, #96 ; 0x60 +1001893e: bf1c itt ne +10018940: 2101 movne r1, #1 +10018942: 72b9 strbne r1, [r7, #10] +10018944: 89f1 ldrh r1, [r6, #14] +10018946: 4008 ands r0, r1 +10018948: 0780 lsls r0, r0, #30 +1001894a: d503 bpl.n 10018954 +1001894c: 7be8 ldrb r0, [r5, #15] +1001894e: 7238 strb r0, [r7, #8] +10018950: 7c28 ldrb r0, [r5, #16] +10018952: 7278 strb r0, [r7, #9] +10018954: 2001 movs r0, #1 +10018956: 60e0 str r0, [r4, #12] +10018958: e003 b.n 10018962 +1001895a: 6078 str r0, [r7, #4] +1001895c: 72b8 strb r0, [r7, #10] +1001895e: 7238 strb r0, [r7, #8] +10018960: 7278 strb r0, [r7, #9] +10018962: 2000 movs r0, #0 +10018964: 72f8 strb r0, [r7, #11] +10018966: 7338 strb r0, [r7, #12] +10018968: 2248 movs r2, #72 ; 0x48 +1001896a: 2100 movs r1, #0 +1001896c: f508 70c0 add.w r0, r8, #384 ; 0x180 +10018970: f7f7 ff62 bl 10010838 +10018974: a900 add r1, sp, #0 +10018976: 4640 mov r0, r8 +10018978: f7f7 ffcc bl 10010914 +1001897c: f8d8 00f8 ldr.w r0, [r8, #248] ; 0xf8 +10018980: f040 0001 orr.w r0, r0, #1 +10018984: f8c8 00f8 str.w r0, [r8, #248] ; 0xf8 +10018988: a900 add r1, sp, #0 +1001898a: 4640 mov r0, r8 +1001898c: f7f7 ffc3 bl 10010916 +10018990: e8bd 83f1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, pc} + +10018994 : +10018994: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +10018998: b089 sub sp, #36 ; 0x24 +1001899a: 4680 mov r8, r0 +1001899c: f508 50c4 add.w r0, r8, #6272 ; 0x1880 +100189a0: 9008 str r0, [sp, #32] +100189a2: 2600 movs r6, #0 +100189a4: f108 000c add.w r0, r8, #12 +100189a8: 9003 str r0, [sp, #12] +100189aa: 2400 movs r4, #0 +100189ac: f508 5088 add.w r0, r8, #4352 ; 0x1100 +100189b0: 30f0 adds r0, #240 ; 0xf0 +100189b2: 9007 str r0, [sp, #28] +100189b4: f04f 0a01 mov.w sl, #1 +100189b8: 9803 ldr r0, [sp, #12] +100189ba: f100 058c add.w r5, r0, #140 ; 0x8c +100189be: f508 609d add.w r0, r8, #1256 ; 0x4e8 +100189c2: 9002 str r0, [sp, #8] +100189c4: f500 7b88 add.w fp, r0, #272 ; 0x110 +100189c8: 6c69 ldr r1, [r5, #68] ; 0x44 +100189ca: f8ad 1018 strh.w r1, [sp, #24] +100189ce: 46b1 mov r9, r6 +100189d0: 9902 ldr r1, [sp, #8] +100189d2: 6cef ldr r7, [r5, #76] ; 0x4c +100189d4: f891 1348 ldrb.w r1, [r1, #840] ; 0x348 +100189d8: 2901 cmp r1, #1 +100189da: bf0e itee eq +100189dc: 46b2 moveq sl, r6 +100189de: 9a02 ldrne r2, [sp, #8] +100189e0: f882 a348 strbne.w sl, [r2, #840] ; 0x348 +100189e4: 9903 ldr r1, [sp, #12] +100189e6: f8d1 1440 ldr.w r1, [r1, #1088] ; 0x440 +100189ea: b111 cbz r1, 100189f2 +100189ec: 2101 movs r1, #1 +100189ee: f88b 10b1 strb.w r1, [fp, #177] ; 0xb1 +100189f2: 9903 ldr r1, [sp, #12] +100189f4: f8d1 1448 ldr.w r1, [r1, #1096] ; 0x448 +100189f8: b301 cbz r1, 10018a3c +100189fa: 2101 movs r1, #1 +100189fc: f88b 10b1 strb.w r1, [fp, #177] ; 0xb1 +10018a00: f88b 10b4 strb.w r1, [fp, #180] ; 0xb4 +10018a04: f10d 0201 add.w r2, sp, #1 +10018a08: f89b 00dc ldrb.w r0, [fp, #220] ; 0xdc +10018a0c: f000 0003 and.w r0, r0, #3 +10018a10: f88d 0002 strb.w r0, [sp, #2] +10018a14: 2124 movs r1, #36 ; 0x24 +10018a16: f89b 00dc ldrb.w r0, [fp, #220] ; 0xdc +10018a1a: f3c0 0082 ubfx r0, r0, #2, #3 +10018a1e: f88d 0001 strb.w r0, [sp, #1] +10018a22: f000 f91d bl 10018c60 <.text_19> +10018a26: f10d 0202 add.w r2, sp, #2 +10018a2a: 2125 movs r1, #37 ; 0x25 +10018a2c: f000 f918 bl 10018c60 <.text_19> +10018a30: f8bb 00da ldrh.w r0, [fp, #218] ; 0xda +10018a34: f3c0 0081 ubfx r0, r0, #2, #2 +10018a38: f88b 00ba strb.w r0, [fp, #186] ; 0xba +10018a3c: 9803 ldr r0, [sp, #12] +10018a3e: 3078 adds r0, #120 ; 0x78 +10018a40: 9005 str r0, [sp, #20] +10018a42: 6900 ldr r0, [r0, #16] +10018a44: 2801 cmp r0, #1 +10018a46: bf1c itt ne +10018a48: 4640 movne r0, r8 +10018a4a: f00d f961 blne 10025d10 +10018a4e: 2103 movs r1, #3 +10018a50: 4640 mov r0, r8 +10018a52: f00d f84a bl 10025aea +10018a56: 1d2a adds r2, r5, #4 +10018a58: 2104 movs r1, #4 +10018a5a: 4640 mov r0, r8 +10018a5c: f7fe fc58 bl 10017310 +10018a60: f8df b694 ldr.w fp, [pc, #1684] ; 100190f8 <.text_28> +10018a64: f8cd b004 str.w fp, [sp, #4] +10018a68: aa01 add r2, sp, #4 +10018a6a: 211f movs r1, #31 +10018a6c: f000 f8f8 bl 10018c60 <.text_19> +10018a70: f8df 0688 ldr.w r0, [pc, #1672] ; 100190fc <.text_29> +10018a74: 9001 str r0, [sp, #4] +10018a76: aa01 add r2, sp, #4 +10018a78: 2120 movs r1, #32 +10018a7a: f000 f8f1 bl 10018c60 <.text_19> +10018a7e: f8cd b004 str.w fp, [sp, #4] +10018a82: aa01 add r2, sp, #4 +10018a84: 2121 movs r1, #33 ; 0x21 +10018a86: f000 f8eb bl 10018c60 <.text_19> +10018a8a: f24a 4044 movw r0, #42052 ; 0xa444 +10018a8e: 9001 str r0, [sp, #4] +10018a90: aa01 add r2, sp, #4 +10018a92: 2122 movs r1, #34 ; 0x22 +10018a94: f000 f8e4 bl 10018c60 <.text_19> +10018a98: 9807 ldr r0, [sp, #28] +10018a9a: 6800 ldr r0, [r0, #0] +10018a9c: 2802 cmp r0, #2 +10018a9e: bf0c ite eq +10018aa0: 20cc moveq r0, #204 ; 0xcc +10018aa2: 20cf movne r0, #207 ; 0xcf +10018aa4: f88d 0000 strb.w r0, [sp] +10018aa8: aa00 add r2, sp, #0 +10018aaa: f8d8 0004 ldr.w r0, [r8, #4] +10018aae: 2803 cmp r0, #3 +10018ab0: bf04 itt eq +10018ab2: 202c moveq r0, #44 ; 0x2c +10018ab4: f88d 0000 strbeq.w r0, [sp] +10018ab8: 2114 movs r1, #20 +10018aba: f000 f8d1 bl 10018c60 <.text_19> +10018abe: aa06 add r2, sp, #24 +10018ac0: 2110 movs r1, #16 +10018ac2: f000 f8cd bl 10018c60 <.text_19> +10018ac6: f105 0164 add.w r1, r5, #100 ; 0x64 +10018aca: 4640 mov r0, r8 +10018acc: f00c ffce bl 10025a6c +10018ad0: f105 0264 add.w r2, r5, #100 ; 0x64 +10018ad4: 2106 movs r1, #6 +10018ad6: 4640 mov r0, r8 +10018ad8: f7fe fc1a bl 10017310 +10018adc: 9805 ldr r0, [sp, #20] +10018ade: 6900 ldr r0, [r0, #16] +10018ae0: 2801 cmp r0, #1 +10018ae2: d005 beq.n 10018af0 +10018ae4: 2201 movs r2, #1 +10018ae6: f06f 4170 mvn.w r1, #4026531840 ; 0xf0000000 +10018aea: 4640 mov r0, r8 +10018aec: f00c fff6 bl 10025adc +10018af0: 6fa8 ldr r0, [r5, #120] ; 0x78 +10018af2: f1a0 030c sub.w r3, r0, #12 +10018af6: aa04 add r2, sp, #16 +10018af8: 213d movs r1, #61 ; 0x3d +10018afa: f105 0088 add.w r0, r5, #136 ; 0x88 +10018afe: f7fb f9bf bl 10013e80 +10018b02: 2800 cmp r0, #0 +10018b04: bf1c itt ne +10018b06: 9904 ldrne r1, [sp, #16] +10018b08: 2900 cmpne r1, #0 +10018b0a: d012 beq.n 10018b32 +10018b0c: 1c86 adds r6, r0, #2 +10018b0e: 9808 ldr r0, [sp, #32] +10018b10: f890 0051 ldrb.w r0, [r0, #81] ; 0x51 +10018b14: b168 cbz r0, 10018b32 +10018b16: 7870 ldrb r0, [r6, #1] +10018b18: 0741 lsls r1, r0, #29 +10018b1a: d50a bpl.n 10018b32 +10018b1c: 2401 movs r4, #1 +10018b1e: f000 0003 and.w r0, r0, #3 +10018b22: 2801 cmp r0, #1 +10018b24: d004 beq.n 10018b30 +10018b26: 2803 cmp r0, #3 +10018b28: bf08 it eq +10018b2a: f04f 0902 moveq.w r9, #2 +10018b2e: e000 b.n 10018b32 +10018b30: 46a1 mov r9, r4 +10018b32: f640 0181 movw r1, #2177 ; 0x881 +10018b36: 4640 mov r0, r8 +10018b38: f006 fe89 bl 1001f84e +10018b3c: b930 cbnz r0, 10018b4c +10018b3e: 4623 mov r3, r4 +10018b40: 464a mov r2, r9 +10018b42: b2f9 uxtb r1, r7 +10018b44: 4640 mov r0, r8 +10018b46: f00d f827 bl 10025b98 +10018b4a: e059 b.n 10018c00 +10018b4c: 2101 movs r1, #1 +10018b4e: 4640 mov r0, r8 +10018b50: f006 fe7d bl 1001f84e +10018b54: 2801 cmp r0, #1 +10018b56: d153 bne.n 10018c00 +10018b58: f641 5048 movw r0, #7496 ; 0x1d48 +10018b5c: 2c00 cmp r4, #0 +10018b5e: f850 0008 ldr.w r0, [r0, r8] +10018b62: f500 609d add.w r0, r0, #1256 ; 0x4e8 +10018b66: 7b87 ldrb r7, [r0, #14] +10018b68: d039 beq.n 10018bde +10018b6a: b11e cbz r6, 10018b74 +10018b6c: 7871 ldrb r1, [r6, #1] +10018b6e: f001 01fc and.w r1, r1, #252 ; 0xfc +10018b72: 7071 strb r1, [r6, #1] +10018b74: 7bc1 ldrb r1, [r0, #15] +10018b76: 2901 cmp r1, #1 +10018b78: d112 bne.n 10018ba0 +10018b7a: f890 9010 ldrb.w r9, [r0, #16] +10018b7e: b376 cbz r6, 10018bde +10018b80: f1b9 0f01 cmp.w r9, #1 +10018b84: d003 beq.n 10018b8e +10018b86: f1b9 0f02 cmp.w r9, #2 +10018b8a: d004 beq.n 10018b96 +10018b8c: e027 b.n 10018bde +10018b8e: 7870 ldrb r0, [r6, #1] +10018b90: f040 0001 orr.w r0, r0, #1 +10018b94: e002 b.n 10018b9c +10018b96: 7870 ldrb r0, [r6, #1] +10018b98: f040 0003 orr.w r0, r0, #3 +10018b9c: 7070 strb r0, [r6, #1] +10018b9e: e01e b.n 10018bde +10018ba0: b9e9 cbnz r1, 10018bde +10018ba2: 2400 movs r4, #0 +10018ba4: 46a1 mov r9, r4 +10018ba6: b147 cbz r7, 10018bba +10018ba8: 2f05 cmp r7, #5 +10018baa: da06 bge.n 10018bba +10018bac: b11e cbz r6, 10018bb6 +10018bae: 7870 ldrb r0, [r6, #1] +10018bb0: f040 0001 orr.w r0, r0, #1 +10018bb4: 7070 strb r0, [r6, #1] +10018bb6: 2401 movs r4, #1 +10018bb8: 46a1 mov r9, r4 +10018bba: f1a7 0008 sub.w r0, r7, #8 +10018bbe: 2807 cmp r0, #7 +10018bc0: d207 bcs.n 10018bd2 +10018bc2: b11e cbz r6, 10018bcc +10018bc4: 7870 ldrb r0, [r6, #1] +10018bc6: f040 0003 orr.w r0, r0, #3 +10018bca: 7070 strb r0, [r6, #1] +10018bcc: 2401 movs r4, #1 +10018bce: f04f 0902 mov.w r9, #2 +10018bd2: 4623 mov r3, r4 +10018bd4: 464a mov r2, r9 +10018bd6: 4639 mov r1, r7 +10018bd8: 4640 mov r0, r8 +10018bda: f00c ffdd bl 10025b98 +10018bde: 64ef str r7, [r5, #76] ; 0x4c +10018be0: aa04 add r2, sp, #16 +10018be2: 6fa8 ldr r0, [r5, #120] ; 0x78 +10018be4: f1a0 030c sub.w r3, r0, #12 +10018be8: 2103 movs r1, #3 +10018bea: f105 0088 add.w r0, r5, #136 ; 0x88 +10018bee: f7fb f947 bl 10013e80 +10018bf2: 2800 cmp r0, #0 +10018bf4: bf1e ittt ne +10018bf6: 9904 ldrne r1, [sp, #16] +10018bf8: 2900 cmpne r1, #0 +10018bfa: 7087 strbne r7, [r0, #2] +10018bfc: b106 cbz r6, 10018c00 +10018bfe: 7037 strb r7, [r6, #0] +10018c00: 9802 ldr r0, [sp, #8] +10018c02: 7387 strb r7, [r0, #14] +10018c04: 9802 ldr r0, [sp, #8] +10018c06: 300e adds r0, #14 +10018c08: 7044 strb r4, [r0, #1] +10018c0a: f880 9002 strb.w r9, [r0, #2] +10018c0e: 9903 ldr r1, [sp, #12] +10018c10: 6f89 ldr r1, [r1, #120] ; 0x78 +10018c12: 70c1 strb r1, [r0, #3] +10018c14: 4640 mov r0, r8 +10018c16: f00d fd2f bl 10026678 +10018c1a: 4628 mov r0, r5 +10018c1c: f005 fe5c bl 1001e8d8 +10018c20: 4601 mov r1, r0 +10018c22: 4640 mov r0, r8 +10018c24: f00d fce5 bl 100265f2 +10018c28: f1ba 0f00 cmp.w sl, #0 +10018c2c: d005 beq.n 10018c3a +10018c2e: 2300 movs r3, #0 +10018c30: 2200 movs r2, #0 +10018c32: 2105 movs r1, #5 +10018c34: 4640 mov r0, r8 +10018c36: f000 fa63 bl 10019100 +10018c3a: 4640 mov r0, r8 +10018c3c: f7ff fdde bl 100187fc +10018c40: f8d8 0004 ldr.w r0, [r8, #4] +10018c44: 2803 cmp r0, #3 +10018c46: d108 bne.n 10018c5a +10018c48: 4640 mov r0, r8 +10018c4a: f004 fb39 bl 1001d2c0 +10018c4e: b120 cbz r0, 10018c5a +10018c50: 2200 movs r2, #0 +10018c52: 2148 movs r1, #72 ; 0x48 +10018c54: 4640 mov r0, r8 +10018c56: f7fe fb5b bl 10017310 +10018c5a: b009 add sp, #36 ; 0x24 +10018c5c: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +10018c60 <.text_19>: +10018c60: 4640 mov r0, r8 +10018c62: f7fe bb55 b.w 10017310 + +10018c66 : +10018c66: e92d 4ff2 stmdb sp!, {r1, r4, r5, r6, r7, r8, r9, sl, fp, lr} +10018c6a: b08e sub sp, #56 ; 0x38 +10018c6c: 4680 mov r8, r0 +10018c6e: 2000 movs r0, #0 +10018c70: 9007 str r0, [sp, #28] +10018c72: 9006 str r0, [sp, #24] +10018c74: 9001 str r0, [sp, #4] +10018c76: 4616 mov r6, r2 +10018c78: f60f 41f8 addw r1, pc, #3320 ; 0xcf8 +10018c7c: 680a ldr r2, [r1, #0] +10018c7e: 4607 mov r7, r0 +10018c80: a808 add r0, sp, #32 +10018c82: f108 0b0c add.w fp, r8, #12 +10018c86: 6002 str r2, [r0, #0] +10018c88: f508 50c4 add.w r0, r8, #6272 ; 0x1880 +10018c8c: 9005 str r0, [sp, #20] +10018c8e: f10b 048c add.w r4, fp, #140 ; 0x8c +10018c92: f508 5088 add.w r0, r8, #4352 ; 0x1100 +10018c96: f100 0af0 add.w sl, r0, #240 ; 0xf0 +10018c9a: 2500 movs r5, #0 +10018c9c: f104 097c add.w r9, r4, #124 ; 0x7c +10018ca0: 2110 movs r1, #16 +10018ca2: 4658 mov r0, fp +10018ca4: f7ff fb84 bl 100183b0 +10018ca8: 2801 cmp r0, #1 +10018caa: d110 bne.n 10018cce +10018cac: f5b6 7f40 cmp.w r6, #768 ; 0x300 +10018cb0: dc0d bgt.n 10018cce +10018cb2: 67a6 str r6, [r4, #120] ; 0x78 +10018cb4: f44f 7240 mov.w r2, #768 ; 0x300 +10018cb8: 2100 movs r1, #0 +10018cba: 4648 mov r0, r9 +10018cbc: f7f7 fdbc bl 10010838 +10018cc0: 6fa2 ldr r2, [r4, #120] ; 0x78 +10018cc2: 990e ldr r1, [sp, #56] ; 0x38 +10018cc4: 4648 mov r0, r9 +10018cc6: f7f7 fda2 bl 1001080e +10018cca: 6e20 ldr r0, [r4, #96] ; 0x60 +10018ccc: 2804 cmp r0, #4 +10018cce: f040 8171 bne.w 10018fb4 +10018cd2: f508 51c8 add.w r1, r8, #6400 ; 0x1900 +10018cd6: 63a5 str r5, [r4, #56] ; 0x38 +10018cd8: 2206 movs r2, #6 +10018cda: 3195 adds r1, #149 ; 0x95 +10018cdc: 1d20 adds r0, r4, #4 +10018cde: f7f7 fd96 bl 1001080e +10018ce2: 4648 mov r0, r9 +10018ce4: f005 fe02 bl 1001e8ec +10018ce8: 7841 ldrb r1, [r0, #1] +10018cea: 7800 ldrb r0, [r0, #0] +10018cec: ea40 2001 orr.w r0, r0, r1, lsl #8 +10018cf0: 6460 str r0, [r4, #68] ; 0x44 +10018cf2: 4648 mov r0, r9 +10018cf4: f005 fdee bl 1001e8d4 +10018cf8: 7841 ldrb r1, [r0, #1] +10018cfa: 7800 ldrb r0, [r0, #0] +10018cfc: ea40 2001 orr.w r0, r0, r1, lsl #8 +10018d00: f8ad 0000 strh.w r0, [sp] +10018d04: aa01 add r2, sp, #4 +10018d06: 6fa0 ldr r0, [r4, #120] ; 0x78 +10018d08: f1a0 030c sub.w r3, r0, #12 +10018d0c: 2100 movs r1, #0 +10018d0e: f000 f974 bl 10018ffa <.text_23> +10018d12: 0006 movs r6, r0 +10018d14: bf1c itt ne +10018d16: 9801 ldrne r0, [sp, #4] +10018d18: 2800 cmpne r0, #0 +10018d1a: d00d beq.n 10018d38 +10018d1c: 2228 movs r2, #40 ; 0x28 +10018d1e: 2100 movs r1, #0 +10018d20: f104 000c add.w r0, r4, #12 +10018d24: f7f7 fd88 bl 10010838 +10018d28: 9a01 ldr r2, [sp, #4] +10018d2a: 1cb1 adds r1, r6, #2 +10018d2c: f104 0010 add.w r0, r4, #16 +10018d30: f7f7 fd6d bl 1001080e +10018d34: 9801 ldr r0, [sp, #4] +10018d36: 60e0 str r0, [r4, #12] +10018d38: 6425 str r5, [r4, #64] ; 0x40 +10018d3a: 2600 movs r6, #0 +10018d3c: f000 f961 bl 10019002 <.text_24> +10018d40: 2103 movs r1, #3 +10018d42: f000 f95a bl 10018ffa <.text_23> +10018d46: 2800 cmp r0, #0 +10018d48: bf1e ittt ne +10018d4a: 9901 ldrne r1, [sp, #4] +10018d4c: 2900 cmpne r1, #0 +10018d4e: 7886 ldrbne r6, [r0, #2] +10018d50: 64e6 str r6, [r4, #76] ; 0x4c +10018d52: 2210 movs r2, #16 +10018d54: 2100 movs r1, #0 +10018d56: a809 add r0, sp, #36 ; 0x24 +10018d58: f7f7 fd6e bl 10010838 +10018d5c: f000 f951 bl 10019002 <.text_24> +10018d60: 2101 movs r1, #1 +10018d62: f000 f94a bl 10018ffa <.text_23> +10018d66: b128 cbz r0, 10018d74 +10018d68: 9a01 ldr r2, [sp, #4] +10018d6a: 1c81 adds r1, r0, #2 +10018d6c: a809 add r0, sp, #36 ; 0x24 +10018d6e: f7f7 fd4e bl 1001080e +10018d72: 9f01 ldr r7, [sp, #4] +10018d74: f000 f945 bl 10019002 <.text_24> +10018d78: 2132 movs r1, #50 ; 0x32 +10018d7a: f000 f93e bl 10018ffa <.text_23> +10018d7e: b138 cbz r0, 10018d90 +10018d80: 1c81 adds r1, r0, #2 +10018d82: 9a01 ldr r2, [sp, #4] +10018d84: a809 add r0, sp, #36 ; 0x24 +10018d86: 1838 adds r0, r7, r0 +10018d88: f7f7 fd41 bl 1001080e +10018d8c: 9801 ldr r0, [sp, #4] +10018d8e: 19c7 adds r7, r0, r7 +10018d90: 4632 mov r2, r6 +10018d92: 4639 mov r1, r7 +10018d94: a809 add r0, sp, #36 ; 0x24 +10018d96: f7ff faff bl 10018398 +10018d9a: b2c6 uxtb r6, r0 +10018d9c: 4631 mov r1, r6 +10018d9e: f104 0064 add.w r0, r4, #100 ; 0x64 +10018da2: f7ff fafd bl 100183a0 +10018da6: f000 f92c bl 10019002 <.text_24> +10018daa: 212a movs r1, #42 ; 0x2a +10018dac: f000 f925 bl 10018ffa <.text_23> +10018db0: 0001 movs r1, r0 +10018db2: bf1f itttt ne +10018db4: 9801 ldrne r0, [sp, #4] +10018db6: 2800 cmpne r0, #0 +10018db8: 4640 movne r0, r8 +10018dba: f00d f94e blne 1002605a +10018dbe: f8bd 0000 ldrh.w r0, [sp] +10018dc2: f010 0010 ands.w r0, r0, #16 +10018dc6: bf18 it ne +10018dc8: 2001 movne r0, #1 +10018dca: 6360 str r0, [r4, #52] ; 0x34 +10018dcc: f8ca 513c str.w r5, [sl, #316] ; 0x13c +10018dd0: 9503 str r5, [sp, #12] +10018dd2: 9502 str r5, [sp, #8] +10018dd4: f8ca 5144 str.w r5, [sl, #324] ; 0x144 +10018dd8: f8ca 514c str.w r5, [sl, #332] ; 0x14c +10018ddc: aa01 add r2, sp, #4 +10018dde: 6fa0 ldr r0, [r4, #120] ; 0x78 +10018de0: f1a0 030c sub.w r3, r0, #12 +10018de4: 2130 movs r1, #48 ; 0x30 +10018de6: f000 f908 bl 10018ffa <.text_23> +10018dea: 2800 cmp r0, #0 +10018dec: bf1c itt ne +10018dee: 9901 ldrne r1, [sp, #4] +10018df0: 2900 cmpne r1, #0 +10018df2: d014 beq.n 10018e1e +10018df4: 9901 ldr r1, [sp, #4] +10018df6: 9500 str r5, [sp, #0] +10018df8: ab02 add r3, sp, #8 +10018dfa: aa03 add r2, sp, #12 +10018dfc: 1c89 adds r1, r1, #2 +10018dfe: f7fb f837 bl 10013e70 +10018e02: 2801 cmp r0, #1 +10018e04: d10b bne.n 10018e1e +10018e06: f000 f8e6 bl 10018fd6 <.text_21> +10018e0a: f040 0002 orr.w r0, r0, #2 +10018e0e: f8ca 013c str.w r0, [sl, #316] ; 0x13c +10018e12: 9803 ldr r0, [sp, #12] +10018e14: f8ca 0144 str.w r0, [sl, #324] ; 0x144 +10018e18: 9802 ldr r0, [sp, #8] +10018e1a: f8ca 014c str.w r0, [sl, #332] ; 0x14c +10018e1e: 9501 str r5, [sp, #4] +10018e20: 9503 str r5, [sp, #12] +10018e22: 9502 str r5, [sp, #8] +10018e24: f8ca 5140 str.w r5, [sl, #320] ; 0x140 +10018e28: f8ca 5148 str.w r5, [sl, #328] ; 0x148 +10018e2c: f109 000c add.w r0, r9, #12 +10018e30: e001 b.n 10018e36 +10018e32: 19c0 adds r0, r0, r7 +10018e34: 1c80 adds r0, r0, #2 +10018e36: f000 f8d7 bl 10018fe8 <.text_22> +10018e3a: 0007 movs r7, r0 +10018e3c: d01f beq.n 10018e7e +10018e3e: 2204 movs r2, #4 +10018e40: a908 add r1, sp, #32 +10018e42: 1cb8 adds r0, r7, #2 +10018e44: f7f7 fced bl 10010822 +10018e48: b1b0 cbz r0, 10018e78 +10018e4a: 9801 ldr r0, [sp, #4] +10018e4c: 9500 str r5, [sp, #0] +10018e4e: 1c81 adds r1, r0, #2 +10018e50: ab02 add r3, sp, #8 +10018e52: aa03 add r2, sp, #12 +10018e54: 4638 mov r0, r7 +10018e56: f7fb f80f bl 10013e78 +10018e5a: 2801 cmp r0, #1 +10018e5c: d10f bne.n 10018e7e +10018e5e: f000 f8ba bl 10018fd6 <.text_21> +10018e62: f040 0001 orr.w r0, r0, #1 +10018e66: f8ca 013c str.w r0, [sl, #316] ; 0x13c +10018e6a: 9803 ldr r0, [sp, #12] +10018e6c: f8ca 0140 str.w r0, [sl, #320] ; 0x140 +10018e70: 9802 ldr r0, [sp, #8] +10018e72: f8ca 0148 str.w r0, [sl, #328] ; 0x148 +10018e76: e002 b.n 10018e7e +10018e78: 9801 ldr r0, [sp, #4] +10018e7a: 2800 cmp r0, #0 +10018e7c: d1d9 bne.n 10018e32 +10018e7e: 9501 str r5, [sp, #4] +10018e80: f8cb 5440 str.w r5, [fp, #1088] ; 0x440 +10018e84: 9805 ldr r0, [sp, #20] +10018e86: f890 0045 ldrb.w r0, [r0, #69] ; 0x45 +10018e8a: b1d0 cbz r0, 10018ec2 +10018e8c: f109 000c add.w r0, r9, #12 +10018e90: e001 b.n 10018e96 +10018e92: 19c0 adds r0, r0, r7 +10018e94: 1c80 adds r0, r0, #2 +10018e96: f000 f8a7 bl 10018fe8 <.text_22> +10018e9a: 0007 movs r7, r0 +10018e9c: d011 beq.n 10018ec2 +10018e9e: 2206 movs r2, #6 +10018ea0: f8df 1ab4 ldr.w r1, [pc, #2740] ; 10019958 <.text_49> +10018ea4: 1cb8 adds r0, r7, #2 +10018ea6: f7f7 fcbc bl 10010822 +10018eaa: b138 cbz r0, 10018ebc +10018eac: 2001 movs r0, #1 +10018eae: f8cb 0440 str.w r0, [fp, #1088] ; 0x440 +10018eb2: 7a38 ldrb r0, [r7, #8] +10018eb4: f040 0080 orr.w r0, r0, #128 ; 0x80 +10018eb8: 7238 strb r0, [r7, #8] +10018eba: e002 b.n 10018ec2 +10018ebc: 9801 ldr r0, [sp, #4] +10018ebe: 2800 cmp r0, #0 +10018ec0: d1e7 bne.n 10018e92 +10018ec2: f000 f89e bl 10019002 <.text_24> +10018ec6: 212d movs r1, #45 ; 0x2d +10018ec8: f000 f897 bl 10018ffa <.text_23> +10018ecc: 0007 movs r7, r0 +10018ece: bf1c itt ne +10018ed0: 9801 ldrne r0, [sp, #4] +10018ed2: 2800 cmpne r0, #0 +10018ed4: d028 beq.n 10018f28 +10018ed6: 1cb8 adds r0, r7, #2 +10018ed8: 9004 str r0, [sp, #16] +10018eda: 9707 str r7, [sp, #28] +10018edc: 2501 movs r5, #1 +10018ede: f046 0608 orr.w r6, r6, #8 +10018ee2: aa00 add r2, sp, #0 +10018ee4: 2116 movs r1, #22 +10018ee6: 4640 mov r0, r8 +10018ee8: f7fe fa1c bl 10017324 +10018eec: f89a 0148 ldrb.w r0, [sl, #328] ; 0x148 +10018ef0: 06c0 lsls r0, r0, #27 +10018ef2: d403 bmi.n 10018efc +10018ef4: f89a 014c ldrb.w r0, [sl, #332] ; 0x14c +10018ef8: 06c0 lsls r0, r0, #27 +10018efa: d505 bpl.n 10018f08 +10018efc: 9804 ldr r0, [sp, #16] +10018efe: 9904 ldr r1, [sp, #16] +10018f00: 7880 ldrb r0, [r0, #2] +10018f02: f040 001c orr.w r0, r0, #28 +10018f06: 7088 strb r0, [r1, #2] +10018f08: f89d 0000 ldrb.w r0, [sp] +10018f0c: 2803 cmp r0, #3 +10018f0e: d105 bne.n 10018f1c +10018f10: 9904 ldr r1, [sp, #16] +10018f12: 20ff movs r0, #255 ; 0xff +10018f14: 70c8 strb r0, [r1, #3] +10018f16: 2000 movs r0, #0 +10018f18: 9904 ldr r1, [sp, #16] +10018f1a: 7108 strb r0, [r1, #4] +10018f1c: 1cb9 adds r1, r7, #2 +10018f1e: 9a01 ldr r2, [sp, #4] +10018f20: f20b 4056 addw r0, fp, #1110 ; 0x456 +10018f24: f7f7 fc73 bl 1001080e +10018f28: f000 f86b bl 10019002 <.text_24> +10018f2c: 213d movs r1, #61 ; 0x3d +10018f2e: f000 f864 bl 10018ffa <.text_23> +10018f32: 2800 cmp r0, #0 +10018f34: bf1e ittt ne +10018f36: 9901 ldrne r1, [sp, #4] +10018f38: 2900 cmpne r1, #0 +10018f3a: 9006 strne r0, [sp, #24] +10018f3c: 2e01 cmp r6, #1 +10018f3e: d002 beq.n 10018f46 +10018f40: 2e04 cmp r6, #4 +10018f42: d002 beq.n 10018f4a +10018f44: e003 b.n 10018f4e +10018f46: 2001 movs r0, #1 +10018f48: e002 b.n 10018f50 +10018f4a: 2002 movs r0, #2 +10018f4c: e000 b.n 10018f50 +10018f4e: 2003 movs r0, #3 +10018f50: 63e0 str r0, [r4, #60] ; 0x3c +10018f52: f8cb 6078 str.w r6, [fp, #120] ; 0x78 +10018f56: f50b 6088 add.w r0, fp, #1088 ; 0x440 +10018f5a: 2100 movs r1, #0 +10018f5c: 6081 str r1, [r0, #8] +10018f5e: 9905 ldr r1, [sp, #20] +10018f60: 3145 adds r1, #69 ; 0x45 +10018f62: 7aca ldrb r2, [r1, #11] +10018f64: 2a00 cmp r2, #0 +10018f66: bf18 it ne +10018f68: 2d00 cmpne r5, #0 +10018f6a: d00f beq.n 10018f8c +10018f6c: 2201 movs r2, #1 +10018f6e: 6082 str r2, [r0, #8] +10018f70: f8cb 2440 str.w r2, [fp, #1088] ; 0x440 +10018f74: 7b49 ldrb r1, [r1, #13] +10018f76: 2901 cmp r1, #1 +10018f78: bf08 it eq +10018f7a: 60c1 streq r1, [r0, #12] +10018f7c: 9907 ldr r1, [sp, #28] +10018f7e: 4640 mov r0, r8 +10018f80: f00c ffd1 bl 10025f26 +10018f84: 9906 ldr r1, [sp, #24] +10018f86: 4640 mov r0, r8 +10018f88: f00d f82b bl 10025fe2 +10018f8c: 6fa0 ldr r0, [r4, #120] ; 0x78 +10018f8e: 307c adds r0, #124 ; 0x7c +10018f90: 6020 str r0, [r4, #0] +10018f92: 4621 mov r1, r4 +10018f94: 4640 mov r0, r8 +10018f96: f7ff fcfd bl 10018994 +10018f9a: f508 5588 add.w r5, r8, #4352 ; 0x1100 +10018f9e: 3528 adds r5, #40 ; 0x28 +10018fa0: 1d21 adds r1, r4, #4 +10018fa2: 4628 mov r0, r5 +10018fa4: f00c f902 bl 100251ac +10018fa8: b930 cbnz r0, 10018fb8 +10018faa: 1d21 adds r1, r4, #4 +10018fac: 4628 mov r0, r5 +10018fae: f00b ff9b bl 10024ee8 +10018fb2: b908 cbnz r0, 10018fb8 +10018fb4: 2000 movs r0, #0 +10018fb6: e00b b.n 10018fd0 +10018fb8: f8d0 10f8 ldr.w r1, [r0, #248] ; 0xf8 +10018fbc: f041 0110 orr.w r1, r1, #16 +10018fc0: f8c0 10f8 str.w r1, [r0, #248] ; 0xf8 +10018fc4: 4640 mov r0, r8 +10018fc6: f005 ff1b bl 1001ee00 +10018fca: 2001 movs r0, #1 +10018fcc: f8cb 0088 str.w r0, [fp, #136] ; 0x88 +10018fd0: b00f add sp, #60 ; 0x3c +10018fd2: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +10018fd6 <.text_21>: +10018fd6: 2002 movs r0, #2 +10018fd8: f8ca 0000 str.w r0, [sl] +10018fdc: 2001 movs r0, #1 +10018fde: f8ca 0138 str.w r0, [sl, #312] ; 0x138 +10018fe2: f8da 013c ldr.w r0, [sl, #316] ; 0x13c +10018fe6: 4770 bx lr + +10018fe8 <.text_22>: +10018fe8: 6fa1 ldr r1, [r4, #120] ; 0x78 +10018fea: 9a01 ldr r2, [sp, #4] +10018fec: 390c subs r1, #12 +10018fee: 1a89 subs r1, r1, r2 +10018ff0: 1e8b subs r3, r1, #2 +10018ff2: aa01 add r2, sp, #4 +10018ff4: 21dd movs r1, #221 ; 0xdd +10018ff6: f7fa bf43 b.w 10013e80 + +10018ffa <.text_23>: +10018ffa: f109 000c add.w r0, r9, #12 +10018ffe: f7fa bf3f b.w 10013e80 + +10019002 <.text_24>: +10019002: 6fa0 ldr r0, [r4, #120] ; 0x78 +10019004: f1a0 030c sub.w r3, r0, #12 +10019008: aa01 add r2, sp, #4 +1001900a: 4770 bx lr + +1001900c : +1001900c: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +10019010: b082 sub sp, #8 +10019012: f100 080c add.w r8, r0, #12 +10019016: 2400 movs r4, #0 +10019018: f108 058c add.w r5, r8, #140 ; 0x8c +1001901c: 9400 str r4, [sp, #0] +1001901e: f105 077c add.w r7, r5, #124 ; 0x7c +10019022: 6fae ldr r6, [r5, #120] ; 0x78 +10019024: ab00 add r3, sp, #0 +10019026: 2200 movs r2, #0 +10019028: f1a6 010c sub.w r1, r6, #12 +1001902c: f107 000c add.w r0, r7, #12 +10019030: f7ff f9ba bl 100183a8 +10019034: ea5f 0900 movs.w r9, r0 +10019038: bf1c itt ne +1001903a: 9800 ldrne r0, [sp, #0] +1001903c: 2800 cmpne r0, #0 +1001903e: d032 beq.n 100190a6 +10019040: eba9 0707 sub.w r7, r9, r7 +10019044: eb00 0a09 add.w sl, r0, r9 +10019048: 9900 ldr r1, [sp, #0] +1001904a: 1bf0 subs r0, r6, r7 +1001904c: 1a46 subs r6, r0, r1 +1001904e: d008 beq.n 10019062 +10019050: 4630 mov r0, r6 +10019052: f7f7 fbd1 bl 100107f8 +10019056: 0004 movs r4, r0 +10019058: d003 beq.n 10019062 +1001905a: 4632 mov r2, r6 +1001905c: 4651 mov r1, sl +1001905e: f7f7 fbd6 bl 1001080e +10019062: f8d8 14b8 ldr.w r1, [r8, #1208] ; 0x4b8 +10019066: b1f1 cbz r1, 100190a6 +10019068: 7848 ldrb r0, [r1, #1] +1001906a: 9000 str r0, [sp, #0] +1001906c: 19c0 adds r0, r0, r7 +1001906e: 1830 adds r0, r6, r0 +10019070: 1c80 adds r0, r0, #2 +10019072: f5b0 7f40 cmp.w r0, #768 ; 0x300 +10019076: d811 bhi.n 1001909c +10019078: 9800 ldr r0, [sp, #0] +1001907a: 1c82 adds r2, r0, #2 +1001907c: 4648 mov r0, r9 +1001907e: f7f7 fbc6 bl 1001080e +10019082: b134 cbz r4, 10019092 +10019084: 9800 ldr r0, [sp, #0] +10019086: 4448 add r0, r9 +10019088: 4632 mov r2, r6 +1001908a: 4621 mov r1, r4 +1001908c: 1c80 adds r0, r0, #2 +1001908e: f7f7 fbbe bl 1001080e +10019092: 9800 ldr r0, [sp, #0] +10019094: 19c0 adds r0, r0, r7 +10019096: 1830 adds r0, r6, r0 +10019098: 1c80 adds r0, r0, #2 +1001909a: 67a8 str r0, [r5, #120] ; 0x78 +1001909c: b11c cbz r4, 100190a6 +1001909e: 4631 mov r1, r6 +100190a0: 4620 mov r0, r4 +100190a2: f7f7 fbb3 bl 1001080c +100190a6: e8bd 87f3 ldmia.w sp!, {r0, r1, r4, r5, r6, r7, r8, r9, sl, pc} + +100190aa : +100190aa: b538 push {r3, r4, r5, lr} +100190ac: 4604 mov r4, r0 +100190ae: 460d mov r5, r1 +100190b0: 2204 movs r2, #4 +100190b2: f8df 08a8 ldr.w r0, [pc, #2216] ; 1001995c <.text_50> +100190b6: f7f7 fbb4 bl 10010822 +100190ba: b9c8 cbnz r0, 100190f0 +100190bc: f8df 08a0 ldr.w r0, [pc, #2208] ; 10019960 <.text_51> +100190c0: 2204 movs r2, #4 +100190c2: 4629 mov r1, r5 +100190c4: f7f7 fbad bl 10010822 +100190c8: b990 cbnz r0, 100190f0 +100190ca: 2204 movs r2, #4 +100190cc: 4629 mov r1, r5 +100190ce: f8df 0894 ldr.w r0, [pc, #2196] ; 10019964 <.text_52> +100190d2: f7f7 fba6 bl 10010822 +100190d6: b118 cbz r0, 100190e0 +100190d8: 4620 mov r0, r4 +100190da: e8bd 4032 ldmia.w sp!, {r1, r4, r5, lr} +100190de: e795 b.n 1001900c +100190e0: 4629 mov r1, r5 +100190e2: e8bd 4038 ldmia.w sp!, {r3, r4, r5, lr} +100190e6: 2204 movs r2, #4 +100190e8: f8df 087c ldr.w r0, [pc, #2172] ; 10019968 <.text_53> +100190ec: f7f7 bb99 b.w 10010822 +100190f0: bd31 pop {r0, r4, r5, pc} + ... + +100190f4 <.text_27>: +100190f4: 0ffff000 .word 0x0ffff000 + +100190f8 <.text_28>: +100190f8: 005ea42b .word 0x005ea42b + +100190fc <.text_29>: +100190fc: 005e4317 .word 0x005e4317 + +10019100 : +10019100: e92d 41fc stmdb sp!, {r2, r3, r4, r5, r6, r7, r8, lr} +10019104: 0006 movs r6, r0 +10019106: bf1e ittt ne +10019108: f106 040c addne.w r4, r6, #12 +1001910c: f896 0830 ldrbne.w r0, [r6, #2096] ; 0x830 +10019110: 2800 cmpne r0, #0 +10019112: 460f mov r7, r1 +10019114: 4690 mov r8, r2 +10019116: d047 beq.n 100191a8 +10019118: f504 659a add.w r5, r4, #1232 ; 0x4d0 +1001911c: a901 add r1, sp, #4 +1001911e: f7ff fbda bl 100188d6 <.text_15+0x2> +10019122: 2f05 cmp r7, #5 +10019124: d008 beq.n 10019138 +10019126: 2f2a cmp r7, #42 ; 0x2a +10019128: d00a beq.n 10019140 +1001912a: 2fdd cmp r7, #221 ; 0xdd +1001912c: bf02 ittt eq +1001912e: 4641 moveq r1, r8 +10019130: 4630 moveq r0, r6 +10019132: f7ff ffba bleq 100190aa +10019136: e031 b.n 1001919c +10019138: 4630 mov r0, r6 +1001913a: f7ff f974 bl 10018426 +1001913e: e02d b.n 1001919c +10019140: 2100 movs r1, #0 +10019142: 9100 str r1, [sp, #0] +10019144: f106 070c add.w r7, r6, #12 +10019148: f896 16aa ldrb.w r1, [r6, #1706] ; 0x6aa +1001914c: f107 008c add.w r0, r7, #140 ; 0x8c +10019150: b321 cbz r1, 1001919c +10019152: 6f81 ldr r1, [r0, #120] ; 0x78 +10019154: f1a1 030c sub.w r3, r1, #12 +10019158: aa00 add r2, sp, #0 +1001915a: 212a movs r1, #42 ; 0x2a +1001915c: 3088 adds r0, #136 ; 0x88 +1001915e: f7fa fe8f bl 10013e80 +10019162: 2800 cmp r0, #0 +10019164: bf1c itt ne +10019166: 9900 ldrne r1, [sp, #0] +10019168: 2900 cmpne r1, #0 +1001916a: d017 beq.n 1001919c +1001916c: f8b7 24a8 ldrh.w r2, [r7, #1192] ; 0x4a8 +10019170: 7881 ldrb r1, [r0, #2] +10019172: 2a01 cmp r2, #1 +10019174: bf0c ite eq +10019176: f041 0103 orreq.w r1, r1, #3 +1001917a: f001 01fc andne.w r1, r1, #252 ; 0xfc +1001917e: 7081 strb r1, [r0, #2] +10019180: f8b7 24ac ldrh.w r2, [r7, #1196] ; 0x4ac +10019184: 7881 ldrb r1, [r0, #2] +10019186: 2a00 cmp r2, #0 +10019188: bf14 ite ne +1001918a: f041 0104 orrne.w r1, r1, #4 +1001918e: f001 01fb andeq.w r1, r1, #251 ; 0xfb +10019192: 7081 strb r1, [r0, #2] +10019194: 4601 mov r1, r0 +10019196: 4630 mov r0, r6 +10019198: f00c ff5f bl 1002605a +1001919c: 2001 movs r0, #1 +1001919e: f884 04d4 strb.w r0, [r4, #1236] ; 0x4d4 +100191a2: a901 add r1, sp, #4 +100191a4: f7ff fb9d bl 100188e2 <.text_16+0x6> +100191a8: e8bd 81f3 ldmia.w sp!, {r0, r1, r4, r5, r6, r7, r8, pc} + +100191ac : +100191ac: 4601 mov r1, r0 +100191ae: f101 030c add.w r3, r1, #12 +100191b2: 2000 movs r0, #0 +100191b4: f8d3 2448 ldr.w r2, [r3, #1096] ; 0x448 +100191b8: 2a01 cmp r2, #1 +100191ba: f503 6189 add.w r1, r3, #1096 ; 0x448 +100191be: d100 bne.n 100191c2 +100191c0: 4770 bx lr +100191c2: b570 push {r4, r5, r6, lr} +100191c4: f203 42ae addw r2, r3, #1198 ; 0x4ae +100191c8: 88d4 ldrh r4, [r2, #6] +100191ca: f8b3 54ae ldrh.w r5, [r3, #1198] ; 0x4ae +100191ce: 0766 lsls r6, r4, #29 +100191d0: d403 bmi.n 100191da +100191d2: b13d cbz r5, 100191e4 +100191d4: f044 0404 orr.w r4, r4, #4 +100191d8: e003 b.n 100191e2 +100191da: b91d cbnz r5, 100191e4 +100191dc: f64f 70fb movw r0, #65531 ; 0xfffb +100191e0: 4004 ands r4, r0 +100191e2: 2001 movs r0, #1 +100191e4: f8b3 5444 ldrh.w r5, [r3, #1092] ; 0x444 +100191e8: 1c43 adds r3, r0, #1 +100191ea: 06e6 lsls r6, r4, #27 +100191ec: d407 bmi.n 100191fe +100191ee: 2d00 cmp r5, #0 +100191f0: bf04 itt eq +100191f2: 7916 ldrbeq r6, [r2, #4] +100191f4: 2e00 cmpeq r6, #0 +100191f6: d00b beq.n 10019210 +100191f8: f044 0410 orr.w r4, r4, #16 +100191fc: e007 b.n 1001920e +100191fe: 2d00 cmp r5, #0 +10019200: bf04 itt eq +10019202: 7916 ldrbeq r6, [r2, #4] +10019204: 2e00 cmpeq r6, #0 +10019206: d103 bne.n 10019210 +10019208: f64f 70ef movw r0, #65519 ; 0xffef +1001920c: 4004 ands r4, r0 +1001920e: 4618 mov r0, r3 +10019210: 80d4 strh r4, [r2, #6] +10019212: 2300 movs r3, #0 +10019214: b915 cbnz r5, 1001921c +10019216: 7994 ldrb r4, [r2, #6] +10019218: 0764 lsls r4, r4, #29 +1001921a: d501 bpl.n 10019220 +1001921c: 2303 movs r3, #3 +1001921e: e009 b.n 10019234 +10019220: 7b89 ldrb r1, [r1, #14] +10019222: 0789 lsls r1, r1, #30 +10019224: d503 bpl.n 1001922e +10019226: 8851 ldrh r1, [r2, #2] +10019228: b109 cbz r1, 1001922e +1001922a: 2302 movs r3, #2 +1001922c: e002 b.n 10019234 +1001922e: 7911 ldrb r1, [r2, #4] +10019230: b101 cbz r1, 10019234 +10019232: 2301 movs r3, #1 +10019234: 88d1 ldrh r1, [r2, #6] +10019236: f001 0403 and.w r4, r1, #3 +1001923a: 429c cmp r4, r3 +1001923c: d005 beq.n 1001924a +1001923e: f64f 74fc movw r4, #65532 ; 0xfffc +10019242: 4021 ands r1, r4 +10019244: 4319 orrs r1, r3 +10019246: 80d1 strh r1, [r2, #6] +10019248: 1c40 adds r0, r0, #1 +1001924a: bd70 pop {r4, r5, r6, pc} + +1001924c : +1001924c: b5f8 push {r3, r4, r5, r6, r7, lr} +1001924e: 2901 cmp r1, #1 +10019250: 4604 mov r4, r0 +10019252: d11d bne.n 10019290 +10019254: f504 5588 add.w r5, r4, #4352 ; 0x1100 +10019258: 3528 adds r5, #40 ; 0x28 +1001925a: f105 068c add.w r6, r5, #140 ; 0x8c +1001925e: a900 add r1, sp, #0 +10019260: 4630 mov r0, r6 +10019262: f7f7 fb57 bl 10010914 +10019266: f855 7f7c ldr.w r7, [r5, #124]! +1001926a: e007 b.n 1001927c +1001926c: f507 7007 add.w r0, r7, #540 ; 0x21c +10019270: 1bc0 subs r0, r0, r7 +10019272: 1a39 subs r1, r7, r0 +10019274: 683f ldr r7, [r7, #0] +10019276: 4620 mov r0, r4 +10019278: f00c fefe bl 10026078 +1001927c: 4639 mov r1, r7 +1001927e: 4628 mov r0, r5 +10019280: f7f7 fb63 bl 1001094a +10019284: 2800 cmp r0, #0 +10019286: d0f1 beq.n 1001926c +10019288: a900 add r1, sp, #0 +1001928a: 4630 mov r0, r6 +1001928c: f7f7 fb43 bl 10010916 +10019290: bdf1 pop {r0, r4, r5, r6, r7, pc} + +10019292 : +10019292: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +10019296: 4689 mov r9, r1 +10019298: f509 7b2e add.w fp, r9, #696 ; 0x2b8 +1001929c: 4680 mov r8, r0 +1001929e: f89b 0004 ldrb.w r0, [fp, #4] +100192a2: 2400 movs r4, #0 +100192a4: f209 27f9 addw r7, r9, #761 ; 0x2f9 +100192a8: 0600 lsls r0, r0, #24 +100192aa: f108 0a0c add.w sl, r8, #12 +100192ae: 78b8 ldrb r0, [r7, #2] +100192b0: f508 659d add.w r5, r8, #1256 ; 0x4e8 +100192b4: f50a 6695 add.w r6, sl, #1192 ; 0x4a8 +100192b8: d40c bmi.n 100192d4 +100192ba: b9b8 cbnz r0, 100192ec +100192bc: 2001 movs r0, #1 +100192be: 70b8 strb r0, [r7, #2] +100192c0: 88b0 ldrh r0, [r6, #4] +100192c2: 1c40 adds r0, r0, #1 +100192c4: 80b0 strh r0, [r6, #4] +100192c6: 7c69 ldrb r1, [r5, #17] +100192c8: 2902 cmp r1, #2 +100192ca: db0f blt.n 100192ec +100192cc: b280 uxth r0, r0 +100192ce: 2801 cmp r0, #1 +100192d0: d10c bne.n 100192ec +100192d2: e009 b.n 100192e8 +100192d4: b150 cbz r0, 100192ec +100192d6: 70bc strb r4, [r7, #2] +100192d8: 88b0 ldrh r0, [r6, #4] +100192da: 1e40 subs r0, r0, #1 +100192dc: 80b0 strh r0, [r6, #4] +100192de: 7c69 ldrb r1, [r5, #17] +100192e0: 2902 cmp r1, #2 +100192e2: db03 blt.n 100192ec +100192e4: b280 uxth r0, r0 +100192e6: b908 cbnz r0, 100192ec +100192e8: f000 f8eb bl 100194c2 <.text_35> +100192ec: f8db 0004 ldr.w r0, [fp, #4] +100192f0: 2800 cmp r0, #0 +100192f2: f899 02f9 ldrb.w r0, [r9, #761] ; 0x2f9 +100192f6: d50c bpl.n 10019312 +100192f8: b9e0 cbnz r0, 10019334 +100192fa: 2001 movs r0, #1 +100192fc: f889 02f9 strb.w r0, [r9, #761] ; 0x2f9 +10019300: f8ba 04a8 ldrh.w r0, [sl, #1192] ; 0x4a8 +10019304: 1c40 adds r0, r0, #1 +10019306: f8aa 04a8 strh.w r0, [sl, #1192] ; 0x4a8 +1001930a: b280 uxth r0, r0 +1001930c: 2801 cmp r0, #1 +1001930e: d111 bne.n 10019334 +10019310: e00a b.n 10019328 +10019312: b178 cbz r0, 10019334 +10019314: 2000 movs r0, #0 +10019316: f889 02f9 strb.w r0, [r9, #761] ; 0x2f9 +1001931a: f8ba 04a8 ldrh.w r0, [sl, #1192] ; 0x4a8 +1001931e: 1e40 subs r0, r0, #1 +10019320: f8aa 04a8 strh.w r0, [sl, #1192] ; 0x4a8 +10019324: b280 uxth r0, r0 +10019326: b928 cbnz r0, 10019334 +10019328: 2401 movs r4, #1 +1001932a: 2301 movs r3, #1 +1001932c: 2200 movs r2, #0 +1001932e: 212a movs r1, #42 ; 0x2a +10019330: f000 f8cb bl 100194ca <.text_36> +10019334: f8b9 02b8 ldrh.w r0, [r9, #696] ; 0x2b8 +10019338: 0540 lsls r0, r0, #21 +1001933a: 7878 ldrb r0, [r7, #1] +1001933c: d40c bmi.n 10019358 +1001933e: b9c0 cbnz r0, 10019372 +10019340: 2001 movs r0, #1 +10019342: 7078 strb r0, [r7, #1] +10019344: 8870 ldrh r0, [r6, #2] +10019346: 1c40 adds r0, r0, #1 +10019348: 8070 strh r0, [r6, #2] +1001934a: 7c69 ldrb r1, [r5, #17] +1001934c: 2902 cmp r1, #2 +1001934e: db10 blt.n 10019372 +10019350: b280 uxth r0, r0 +10019352: 2801 cmp r0, #1 +10019354: d10d bne.n 10019372 +10019356: e00a b.n 1001936e +10019358: b158 cbz r0, 10019372 +1001935a: 2000 movs r0, #0 +1001935c: 7078 strb r0, [r7, #1] +1001935e: 8870 ldrh r0, [r6, #2] +10019360: 1e40 subs r0, r0, #1 +10019362: 8070 strh r0, [r6, #2] +10019364: 7c69 ldrb r1, [r5, #17] +10019366: 2902 cmp r1, #2 +10019368: db03 blt.n 10019372 +1001936a: b280 uxth r0, r0 +1001936c: b908 cbnz r0, 10019372 +1001936e: f000 f8a8 bl 100194c2 <.text_35> +10019372: f8db 0004 ldr.w r0, [fp, #4] +10019376: 0500 lsls r0, r0, #20 +10019378: d51d bpl.n 100193b6 +1001937a: f8b9 0202 ldrh.w r0, [r9, #514] ; 0x202 +1001937e: 7939 ldrb r1, [r7, #4] +10019380: b131 cbz r1, 10019390 +10019382: 2100 movs r1, #0 +10019384: 7139 strb r1, [r7, #4] +10019386: f8ba 1444 ldrh.w r1, [sl, #1092] ; 0x444 +1001938a: 1e49 subs r1, r1, #1 +1001938c: f8aa 1444 strh.w r1, [sl, #1092] ; 0x444 +10019390: 06c1 lsls r1, r0, #27 +10019392: d406 bmi.n 100193a2 +10019394: 78f9 ldrb r1, [r7, #3] +10019396: b921 cbnz r1, 100193a2 +10019398: 2101 movs r1, #1 +1001939a: 70f9 strb r1, [r7, #3] +1001939c: 88f1 ldrh r1, [r6, #6] +1001939e: 1c49 adds r1, r1, #1 +100193a0: 80f1 strh r1, [r6, #6] +100193a2: 0780 lsls r0, r0, #30 +100193a4: d410 bmi.n 100193c8 +100193a6: 7978 ldrb r0, [r7, #5] +100193a8: b970 cbnz r0, 100193c8 +100193aa: 2001 movs r0, #1 +100193ac: 7178 strb r0, [r7, #5] +100193ae: 8930 ldrh r0, [r6, #8] +100193b0: 1c40 adds r0, r0, #1 +100193b2: 8130 strh r0, [r6, #8] +100193b4: e008 b.n 100193c8 +100193b6: 7938 ldrb r0, [r7, #4] +100193b8: b930 cbnz r0, 100193c8 +100193ba: 2001 movs r0, #1 +100193bc: 7138 strb r0, [r7, #4] +100193be: f8ba 0444 ldrh.w r0, [sl, #1092] ; 0x444 +100193c2: 1c40 adds r0, r0, #1 +100193c4: f8aa 0444 strh.w r0, [sl, #1092] ; 0x444 +100193c8: 4640 mov r0, r8 +100193ca: f7ff feef bl 100191ac +100193ce: 2801 cmp r0, #1 +100193d0: db09 blt.n 100193e6 +100193d2: 2300 movs r3, #0 +100193d4: 2200 movs r2, #0 +100193d6: 212d movs r1, #45 ; 0x2d +100193d8: f000 f877 bl 100194ca <.text_36> +100193dc: 2301 movs r3, #1 +100193de: 2200 movs r2, #0 +100193e0: 213d movs r1, #61 ; 0x3d +100193e2: f000 f872 bl 100194ca <.text_36> +100193e6: 4621 mov r1, r4 +100193e8: 4640 mov r0, r8 +100193ea: e8bd 4ff4 ldmia.w sp!, {r2, r4, r5, r6, r7, r8, r9, sl, fp, lr} +100193ee: e72d b.n 1001924c + +100193f0 : +100193f0: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +100193f4: 468a mov sl, r1 +100193f6: 2500 movs r5, #0 +100193f8: 4680 mov r8, r0 +100193fa: f1ba 0f00 cmp.w sl, #0 +100193fe: f108 090c add.w r9, r8, #12 +10019402: f508 669d add.w r6, r8, #1256 ; 0x4e8 +10019406: d059 beq.n 100194bc +10019408: f20a 24f9 addw r4, sl, #761 ; 0x2f9 +1001940c: f509 6795 add.w r7, r9, #1192 ; 0x4a8 +10019410: 78a0 ldrb r0, [r4, #2] +10019412: b158 cbz r0, 1001942c +10019414: 70a5 strb r5, [r4, #2] +10019416: 88b8 ldrh r0, [r7, #4] +10019418: 1e40 subs r0, r0, #1 +1001941a: 80b8 strh r0, [r7, #4] +1001941c: 7c71 ldrb r1, [r6, #17] +1001941e: 2902 cmp r1, #2 +10019420: db04 blt.n 1001942c +10019422: b280 uxth r0, r0 +10019424: b910 cbnz r0, 1001942c +10019426: 2501 movs r5, #1 +10019428: f000 f84c bl 100194c4 <.text_35+0x2> +1001942c: f89a 02f9 ldrb.w r0, [sl, #761] ; 0x2f9 +10019430: b178 cbz r0, 10019452 +10019432: 2000 movs r0, #0 +10019434: f88a 02f9 strb.w r0, [sl, #761] ; 0x2f9 +10019438: f8b9 04a8 ldrh.w r0, [r9, #1192] ; 0x4a8 +1001943c: 1e40 subs r0, r0, #1 +1001943e: f8a9 04a8 strh.w r0, [r9, #1192] ; 0x4a8 +10019442: b280 uxth r0, r0 +10019444: b928 cbnz r0, 10019452 +10019446: 2501 movs r5, #1 +10019448: 2301 movs r3, #1 +1001944a: 2200 movs r2, #0 +1001944c: 212a movs r1, #42 ; 0x2a +1001944e: f000 f83c bl 100194ca <.text_36> +10019452: 7860 ldrb r0, [r4, #1] +10019454: b160 cbz r0, 10019470 +10019456: 2000 movs r0, #0 +10019458: 7060 strb r0, [r4, #1] +1001945a: 8878 ldrh r0, [r7, #2] +1001945c: 1e40 subs r0, r0, #1 +1001945e: 8078 strh r0, [r7, #2] +10019460: 7c71 ldrb r1, [r6, #17] +10019462: 2902 cmp r1, #2 +10019464: db04 blt.n 10019470 +10019466: b280 uxth r0, r0 +10019468: b910 cbnz r0, 10019470 +1001946a: 2501 movs r5, #1 +1001946c: f000 f82a bl 100194c4 <.text_35+0x2> +10019470: 78e0 ldrb r0, [r4, #3] +10019472: b120 cbz r0, 1001947e +10019474: 2000 movs r0, #0 +10019476: 70e0 strb r0, [r4, #3] +10019478: 88f8 ldrh r0, [r7, #6] +1001947a: 1e40 subs r0, r0, #1 +1001947c: 80f8 strh r0, [r7, #6] +1001947e: 7920 ldrb r0, [r4, #4] +10019480: b130 cbz r0, 10019490 +10019482: 2000 movs r0, #0 +10019484: 7120 strb r0, [r4, #4] +10019486: f8b9 0444 ldrh.w r0, [r9, #1092] ; 0x444 +1001948a: 1e40 subs r0, r0, #1 +1001948c: f8a9 0444 strh.w r0, [r9, #1092] ; 0x444 +10019490: 7960 ldrb r0, [r4, #5] +10019492: b120 cbz r0, 1001949e +10019494: 2000 movs r0, #0 +10019496: 7160 strb r0, [r4, #5] +10019498: 8938 ldrh r0, [r7, #8] +1001949a: 1e40 subs r0, r0, #1 +1001949c: 8138 strh r0, [r7, #8] +1001949e: 4640 mov r0, r8 +100194a0: f7ff fe84 bl 100191ac +100194a4: 2801 cmp r0, #1 +100194a6: db09 blt.n 100194bc +100194a8: 2300 movs r3, #0 +100194aa: 2200 movs r2, #0 +100194ac: 212d movs r1, #45 ; 0x2d +100194ae: f000 f80c bl 100194ca <.text_36> +100194b2: 2301 movs r3, #1 +100194b4: 2200 movs r2, #0 +100194b6: 213d movs r1, #61 ; 0x3d +100194b8: f000 f807 bl 100194ca <.text_36> +100194bc: 4628 mov r0, r5 +100194be: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + +100194c2 <.text_35>: +100194c2: 2401 movs r4, #1 +100194c4: 2301 movs r3, #1 +100194c6: 2200 movs r2, #0 +100194c8: 21ff movs r1, #255 ; 0xff + +100194ca <.text_36>: +100194ca: 4640 mov r0, r8 +100194cc: e618 b.n 10019100 + +100194ce : +100194ce: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +100194d2: 4604 mov r4, r0 +100194d4: f504 5688 add.w r6, r4, #4352 ; 0x1100 +100194d8: b082 sub sp, #8 +100194da: 460d mov r5, r1 +100194dc: 4617 mov r7, r2 +100194de: 3628 adds r6, #40 ; 0x28 +100194e0: b90d cbnz r5, 100194e6 +100194e2: 2000 movs r0, #0 +100194e4: e03b b.n 1001955e +100194e6: 2000 movs r0, #0 +100194e8: f885 01ff strb.w r0, [r5, #511] ; 0x1ff +100194ec: f885 0200 strb.w r0, [r5, #512] ; 0x200 +100194f0: f505 7884 add.w r8, r5, #264 ; 0x108 +100194f4: f44f 7180 mov.w r1, #256 ; 0x100 +100194f8: f104 000c add.w r0, r4, #12 +100194fc: f7fe ff58 bl 100183b0 +10019500: b920 cbnz r0, 1001950c +10019502: 463a mov r2, r7 +10019504: 4641 mov r1, r8 +10019506: 4620 mov r0, r4 +10019508: f002 fe06 bl 1001c118 +1001950c: f8d5 0100 ldr.w r0, [r5, #256] ; 0x100 +10019510: 1cc2 adds r2, r0, #3 +10019512: 2301 movs r3, #1 +10019514: b2d2 uxtb r2, r2 +10019516: 4629 mov r1, r5 +10019518: 4620 mov r0, r4 +1001951a: f7fd fa03 bl 10016924 +1001951e: f7ff f9d9 bl 100188d4 <.text_15> +10019522: f8d5 00f8 ldr.w r0, [r5, #248] ; 0xf8 +10019526: 0840 lsrs r0, r0, #1 +10019528: 0040 lsls r0, r0, #1 +1001952a: f7ff f9d7 bl 100188dc <.text_16> +1001952e: 463a mov r2, r7 +10019530: 4641 mov r1, r8 +10019532: 4620 mov r0, r4 +10019534: f003 fe31 bl 1001d19a +10019538: 4629 mov r1, r5 +1001953a: 4620 mov r0, r4 +1001953c: f7ff ff58 bl 100193f0 +10019540: 4607 mov r7, r0 +10019542: a900 add r1, sp, #0 +10019544: f106 0018 add.w r0, r6, #24 +10019548: f7f7 f9e4 bl 10010914 +1001954c: 4629 mov r1, r5 +1001954e: f7fe ff67 bl 10018420 <.text_5+0x2> +10019552: a900 add r1, sp, #0 +10019554: f106 0018 add.w r0, r6, #24 +10019558: f7f7 f9dd bl 10010916 +1001955c: 4638 mov r0, r7 +1001955e: e8bd 81f6 ldmia.w sp!, {r1, r2, r4, r5, r6, r7, r8, pc} + +10019562 : +10019562: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +10019566: b084 sub sp, #16 +10019568: f20f 410c addw r1, pc, #1036 ; 0x40c +1001956c: 4604 mov r4, r0 +1001956e: c90c ldmia r1!, {r2, r3} +10019570: a801 add r0, sp, #4 +10019572: f504 5588 add.w r5, r4, #4352 ; 0x1100 +10019576: c00c stmia r0!, {r2, r3} +10019578: 3528 adds r5, #40 ; 0x28 +1001957a: 2110 movs r1, #16 +1001957c: f104 000c add.w r0, r4, #12 +10019580: f7fe ff16 bl 100183b0 +10019584: 2801 cmp r0, #1 +10019586: d129 bne.n 100195dc +10019588: f105 088c add.w r8, r5, #140 ; 0x8c +1001958c: a900 add r1, sp, #0 +1001958e: 4640 mov r0, r8 +10019590: f7f7 f9c0 bl 10010914 +10019594: f855 7f7c ldr.w r7, [r5, #124]! +10019598: e00d b.n 100195b6 +1001959a: f507 7007 add.w r0, r7, #540 ; 0x21c +1001959e: 1bc0 subs r0, r0, r7 +100195a0: 1a3e subs r6, r7, r0 +100195a2: 683f ldr r7, [r7, #0] +100195a4: f506 7007 add.w r0, r6, #540 ; 0x21c +100195a8: f7f7 f95c bl 10010864 +100195ac: 2203 movs r2, #3 +100195ae: 4631 mov r1, r6 +100195b0: 4620 mov r0, r4 +100195b2: f7ff ff8c bl 100194ce +100195b6: 4639 mov r1, r7 +100195b8: 4628 mov r0, r5 +100195ba: f7f7 f9c6 bl 1001094a +100195be: 2800 cmp r0, #0 +100195c0: d0eb beq.n 1001959a +100195c2: a900 add r1, sp, #0 +100195c4: 4640 mov r0, r8 +100195c6: f7f7 f9a6 bl 10010916 +100195ca: 2203 movs r2, #3 +100195cc: a901 add r1, sp, #4 +100195ce: 4620 mov r0, r4 +100195d0: f002 fda2 bl 1001c118 +100195d4: 2101 movs r1, #1 +100195d6: 4620 mov r0, r4 +100195d8: f7ff fe38 bl 1001924c +100195dc: 2000 movs r0, #0 +100195de: b004 add sp, #16 +100195e0: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +100195e4 : +100195e4: b510 push {r4, lr} +100195e6: f8d1 22bc ldr.w r2, [r1, #700] ; 0x2bc +100195ea: f412 7400 ands.w r4, r2, #512 ; 0x200 +100195ee: bf18 it ne +100195f0: 2401 movne r4, #1 +100195f2: f100 030c add.w r3, r0, #12 +100195f6: f8c1 4104 str.w r4, [r1, #260] ; 0x104 +100195fa: f8d3 4440 ldr.w r4, [r3, #1088] ; 0x440 +100195fe: b90c cbnz r4, 10019604 +10019600: f8c1 4104 str.w r4, [r1, #260] ; 0x104 +10019604: 0512 lsls r2, r2, #20 +10019606: bf46 itte mi +10019608: 2201 movmi r2, #1 +1001960a: f8c1 2104 strmi.w r2, [r1, #260] ; 0x104 +1001960e: 2200 movpl r2, #0 +10019610: f8c1 21f4 str.w r2, [r1, #500] ; 0x1f4 +10019614: f8d3 2448 ldr.w r2, [r3, #1096] ; 0x448 +10019618: b90a cbnz r2, 1001961e +1001961a: f8c1 21f4 str.w r2, [r1, #500] ; 0x1f4 +1001961e: e8bd 4010 ldmia.w sp!, {r4, lr} +10019622: f7ff b961 b.w 100188e8 + +10019626 : +10019626: f891 20f8 ldrb.w r2, [r1, #248] ; 0xf8 +1001962a: 07d2 lsls r2, r2, #31 +1001962c: d508 bpl.n 10019640 +1001962e: f8d1 2100 ldr.w r2, [r1, #256] ; 0x100 +10019632: eb00 1242 add.w r2, r0, r2, lsl #5 +10019636: f8c2 1704 str.w r1, [r2, #1796] ; 0x704 +1001963a: 2200 movs r2, #0 +1001963c: f7ff b852 b.w 100186e4 +10019640: 4770 bx lr + +10019642 : +10019642: f100 020c add.w r2, r0, #12 +10019646: 2300 movs r3, #0 +10019648: f882 34d4 strb.w r3, [r2, #1236] ; 0x4d4 +1001964c: f500 5188 add.w r1, r0, #4352 ; 0x1100 +10019650: f880 3830 strb.w r3, [r0, #2096] ; 0x830 +10019654: f502 6095 add.w r0, r2, #1192 ; 0x4a8 +10019658: f8a2 34a8 strh.w r3, [r2, #1192] ; 0x4a8 +1001965c: 8043 strh r3, [r0, #2] +1001965e: 8083 strh r3, [r0, #4] +10019660: 80c3 strh r3, [r0, #6] +10019662: f8a2 3444 strh.w r3, [r2, #1092] ; 0x444 +10019666: 2200 movs r2, #0 +10019668: 8102 strh r2, [r0, #8] +1001966a: 7282 strb r2, [r0, #10] +1001966c: 8182 strh r2, [r0, #12] +1001966e: 3128 adds r1, #40 ; 0x28 +10019670: 4610 mov r0, r2 +10019672: eb01 0380 add.w r3, r1, r0, lsl #2 +10019676: 1c40 adds r0, r0, #1 +10019678: 2808 cmp r0, #8 +1001967a: f8c3 20a0 str.w r2, [r3, #160] ; 0xa0 +1001967e: dbf8 blt.n 10019672 +10019680: 4770 bx lr + +10019682 : +10019682: b5f8 push {r3, r4, r5, r6, r7, lr} +10019684: 4604 mov r4, r0 +10019686: f104 060c add.w r6, r4, #12 +1001968a: 2000 movs r0, #0 +1001968c: f886 04d4 strb.w r0, [r6, #1236] ; 0x4d4 +10019690: f884 0830 strb.w r0, [r4, #2096] ; 0x830 +10019694: f504 5588 add.w r5, r4, #4352 ; 0x1100 +10019698: 3528 adds r5, #40 ; 0x28 +1001969a: 4620 mov r0, r4 +1001969c: f7ff ff61 bl 10019562 +100196a0: 4620 mov r0, r4 +100196a2: f00b fd53 bl 1002514c +100196a6: 4620 mov r0, r4 +100196a8: f00b fdc6 bl 10025238 +100196ac: f000 f810 bl 100196d0 <.text_44> +100196b0: f7fe feb5 bl 1001841e <.text_5> +100196b4: f000 f807 bl 100196c6 <.text_43> +100196b8: 4620 mov r0, r4 +100196ba: f00b fdb0 bl 1002521e +100196be: 4630 mov r0, r6 +100196c0: f005 f810 bl 1001e6e4 +100196c4: bdf1 pop {r0, r4, r5, r6, r7, pc} + +100196c6 <.text_43>: +100196c6: a900 add r1, sp, #0 +100196c8: f105 0018 add.w r0, r5, #24 +100196cc: f7f7 b923 b.w 10010916 + +100196d0 <.text_44>: +100196d0: 4607 mov r7, r0 +100196d2: a900 add r1, sp, #0 +100196d4: f105 0018 add.w r0, r5, #24 +100196d8: f7f7 b91c b.w 10010914 + +100196dc : +100196dc: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +100196e0: 4681 mov r9, r0 +100196e2: b098 sub sp, #96 ; 0x60 +100196e4: 4618 mov r0, r3 +100196e6: 2308 movs r3, #8 +100196e8: f509 5ac4 add.w sl, r9, #6272 ; 0x1880 +100196ec: 9301 str r3, [sp, #4] +100196ee: f509 5688 add.w r6, r9, #4352 ; 0x1100 +100196f2: f8da 304c ldr.w r3, [sl, #76] ; 0x4c +100196f6: f820 3f08 strh.w r3, [r0, #8]! +100196fa: 36f0 adds r6, #240 ; 0xf0 +100196fc: 230a movs r3, #10 +100196fe: 9301 str r3, [sp, #4] +10019700: f509 679d add.w r7, r9, #1256 ; 0x4e8 +10019704: 2321 movs r3, #33 ; 0x21 +10019706: f820 3f02 strh.w r3, [r0, #2]! +1001970a: 6873 ldr r3, [r6, #4] +1001970c: b10b cbz r3, 10019712 +1001970e: 2331 movs r3, #49 ; 0x31 +10019710: 8003 strh r3, [r0, #0] +10019712: 230c movs r3, #12 +10019714: 9301 str r3, [sp, #4] +10019716: 1c80 adds r0, r0, #2 +10019718: ab01 add r3, sp, #4 +1001971a: 9300 str r3, [sp, #0] +1001971c: 460b mov r3, r1 +1001971e: 2100 movs r1, #0 +10019720: f7fe fe2e bl 10018380 +10019724: f89a 102e ldrb.w r1, [sl, #46] ; 0x2e +10019728: 291f cmp r1, #31 +1001972a: 4604 mov r4, r0 +1001972c: d104 bne.n 10019738 +1001972e: 7bb8 ldrb r0, [r7, #14] +10019730: 280f cmp r0, #15 +10019732: bfac ite ge +10019734: 2114 movge r1, #20 +10019736: 210b movlt r1, #11 +10019738: a807 add r0, sp, #28 +1001973a: f7fe fe31 bl 100183a0 +1001973e: a807 add r0, sp, #28 +10019740: f7fe fe26 bl 10018390 +10019744: 4680 mov r8, r0 +10019746: a801 add r0, sp, #4 +10019748: f1b8 0f09 cmp.w r8, #9 +1001974c: 9000 str r0, [sp, #0] +1001974e: bf2c ite cs +10019750: 2208 movcs r2, #8 +10019752: 4642 movcc r2, r8 +10019754: ab07 add r3, sp, #28 +10019756: 2101 movs r1, #1 +10019758: f000 f8fb bl 10019952 <.text_47> +1001975c: a901 add r1, sp, #4 +1001975e: 9100 str r1, [sp, #0] +10019760: f107 030e add.w r3, r7, #14 +10019764: 2201 movs r2, #1 +10019766: 2103 movs r1, #3 +10019768: f7fe fe0a bl 10018380 +1001976c: 2100 movs r1, #0 +1001976e: f88d 1008 strb.w r1, [sp, #8] +10019772: ab02 add r3, sp, #8 +10019774: a901 add r1, sp, #4 +10019776: 9100 str r1, [sp, #0] +10019778: 2201 movs r2, #1 +1001977a: 212a movs r1, #42 ; 0x2a +1001977c: f7fe fe00 bl 10018380 +10019780: 4604 mov r4, r0 +10019782: f8d6 0364 ldr.w r0, [r6, #868] ; 0x364 +10019786: 2807 cmp r0, #7 +10019788: d127 bne.n 100197da +1001978a: 2030 movs r0, #48 ; 0x30 +1001978c: 7020 strb r0, [r4, #0] +1001978e: 2114 movs r1, #20 +10019790: 1c60 adds r0, r4, #1 +10019792: 4c76 ldr r4, [pc, #472] ; (1001996c <.text_54>) +10019794: f800 1b01 strb.w r1, [r0], #1 +10019798: 1c85 adds r5, r0, #2 +1001979a: 2101 movs r1, #1 +1001979c: 7001 strb r1, [r0, #0] +1001979e: 6df0 ldr r0, [r6, #92] ; 0x5c +100197a0: 2804 cmp r0, #4 +100197a2: d101 bne.n 100197a8 +100197a4: f000 f8d0 bl 10019948 <.text_46> +100197a8: 1d2d adds r5, r5, #4 +100197aa: 2001 movs r0, #1 +100197ac: f805 0b02 strb.w r0, [r5], #2 +100197b0: 6870 ldr r0, [r6, #4] +100197b2: 2804 cmp r0, #4 +100197b4: d101 bne.n 100197ba +100197b6: f000 f8c7 bl 10019948 <.text_46> +100197ba: 1d2e adds r6, r5, #4 +100197bc: 2001 movs r0, #1 +100197be: f806 0b02 strb.w r0, [r6], #2 +100197c2: 2204 movs r2, #4 +100197c4: 496a ldr r1, [pc, #424] ; (10019970 <.text_55>) +100197c6: 4630 mov r0, r6 +100197c8: f7f7 f821 bl 1001080e +100197cc: 1d34 adds r4, r6, #4 +100197ce: 2000 movs r0, #0 +100197d0: f804 0b02 strb.w r0, [r4], #2 +100197d4: 9801 ldr r0, [sp, #4] +100197d6: 3016 adds r0, #22 +100197d8: 9001 str r0, [sp, #4] +100197da: f1b8 0f09 cmp.w r8, #9 +100197de: d308 bcc.n 100197f2 +100197e0: a801 add r0, sp, #4 +100197e2: 9000 str r0, [sp, #0] +100197e4: ab09 add r3, sp, #36 ; 0x24 +100197e6: f1a8 0208 sub.w r2, r8, #8 +100197ea: 2132 movs r1, #50 ; 0x32 +100197ec: f000 f8b1 bl 10019952 <.text_47> +100197f0: 4604 mov r4, r0 +100197f2: f89a 0050 ldrb.w r0, [sl, #80] ; 0x50 +100197f6: b398 cbz r0, 10019860 +100197f8: 221a movs r2, #26 +100197fa: 2100 movs r1, #0 +100197fc: a811 add r0, sp, #68 ; 0x44 +100197fe: f7f7 f81b bl 10010838 +10019802: 2020 movs r0, #32 +10019804: f8ad 0044 strh.w r0, [sp, #68] ; 0x44 +10019808: aa02 add r2, sp, #8 +1001980a: 210b movs r1, #11 +1001980c: 4648 mov r0, r9 +1001980e: f7fd fd9e bl 1001734e +10019812: 9802 ldr r0, [sp, #8] +10019814: f000 0003 and.w r0, r0, #3 +10019818: f241 11f4 movw r1, #4596 ; 0x11f4 +1001981c: f88d 0046 strb.w r0, [sp, #70] ; 0x46 +10019820: ab11 add r3, sp, #68 ; 0x44 +10019822: f851 1009 ldr.w r1, [r1, r9] +10019826: 2904 cmp r1, #4 +10019828: bf04 itt eq +1001982a: f040 001c orreq.w r0, r0, #28 +1001982e: f88d 0046 strbeq.w r0, [sp, #70] ; 0x46 +10019832: a801 add r0, sp, #4 +10019834: 9000 str r0, [sp, #0] +10019836: 221a movs r2, #26 +10019838: 212d movs r1, #45 ; 0x2d +1001983a: f000 f88a bl 10019952 <.text_47> +1001983e: 4604 mov r4, r0 +10019840: 2216 movs r2, #22 +10019842: 2100 movs r1, #0 +10019844: a80b add r0, sp, #44 ; 0x2c +10019846: f7f6 fff7 bl 10010838 +1001984a: 7bb8 ldrb r0, [r7, #14] +1001984c: f88d 002c strb.w r0, [sp, #44] ; 0x2c +10019850: ab0b add r3, sp, #44 ; 0x2c +10019852: a801 add r0, sp, #4 +10019854: 9000 str r0, [sp, #0] +10019856: 2216 movs r2, #22 +10019858: 213d movs r1, #61 ; 0x3d +1001985a: f000 f87a bl 10019952 <.text_47> +1001985e: 4604 mov r4, r0 +10019860: f89a 0045 ldrb.w r0, [sl, #69] ; 0x45 +10019864: 2800 cmp r0, #0 +10019866: d03c beq.n 100198e2 +10019868: 20dd movs r0, #221 ; 0xdd +1001986a: 7020 strb r0, [r4, #0] +1001986c: 2206 movs r2, #6 +1001986e: 2018 movs r0, #24 +10019870: 7060 strb r0, [r4, #1] +10019872: 1ca0 adds r0, r4, #2 +10019874: 4938 ldr r1, [pc, #224] ; (10019958 <.text_49>) +10019876: f7f6 ffca bl 1001080e +1001987a: 2003 movs r0, #3 +1001987c: f88d 0008 strb.w r0, [sp, #8] +10019880: 2212 movs r2, #18 +10019882: 2000 movs r0, #0 +10019884: f88d 0009 strb.w r0, [sp, #9] +10019888: a902 add r1, sp, #8 +1001988a: 2003 movs r0, #3 +1001988c: f88d 000a strb.w r0, [sp, #10] +10019890: 20a4 movs r0, #164 ; 0xa4 +10019892: f88d 000b strb.w r0, [sp, #11] +10019896: 2000 movs r0, #0 +10019898: f8ad 000c strh.w r0, [sp, #12] +1001989c: 2027 movs r0, #39 ; 0x27 +1001989e: f88d 000e strb.w r0, [sp, #14] +100198a2: 20a4 movs r0, #164 ; 0xa4 +100198a4: f88d 000f strb.w r0, [sp, #15] +100198a8: 2000 movs r0, #0 +100198aa: f8ad 0010 strh.w r0, [sp, #16] +100198ae: 2042 movs r0, #66 ; 0x42 +100198b0: f88d 0012 strb.w r0, [sp, #18] +100198b4: 2043 movs r0, #67 ; 0x43 +100198b6: f88d 0013 strb.w r0, [sp, #19] +100198ba: 205e movs r0, #94 ; 0x5e +100198bc: f8ad 0014 strh.w r0, [sp, #20] +100198c0: 2062 movs r0, #98 ; 0x62 +100198c2: f88d 0016 strb.w r0, [sp, #22] +100198c6: 2032 movs r0, #50 ; 0x32 +100198c8: f88d 0017 strb.w r0, [sp, #23] +100198cc: 202f movs r0, #47 ; 0x2f +100198ce: f8ad 0018 strh.w r0, [sp, #24] +100198d2: f104 0008 add.w r0, r4, #8 +100198d6: f7f6 ff9a bl 1001080e +100198da: 9801 ldr r0, [sp, #4] +100198dc: 301a adds r0, #26 +100198de: 9001 str r0, [sp, #4] +100198e0: 341a adds r4, #26 +100198e2: f20f 019c addw r1, pc, #156 ; 0x9c +100198e6: c90c ldmia r1!, {r2, r3} +100198e8: a80b add r0, sp, #44 ; 0x2c +100198ea: f20f 019c addw r1, pc, #156 ; 0x9c +100198ee: c00c stmia r0!, {r2, r3} +100198f0: c90c ldmia r1!, {r2, r3} +100198f2: a804 add r0, sp, #16 +100198f4: 491b ldr r1, [pc, #108] ; (10019964 <.text_52>) +100198f6: c00c stmia r0!, {r2, r3} +100198f8: 20dd movs r0, #221 ; 0xdd +100198fa: 7020 strb r0, [r4, #0] +100198fc: 2204 movs r2, #4 +100198fe: 200e movs r0, #14 +10019900: 7060 strb r0, [r4, #1] +10019902: 1ca0 adds r0, r4, #2 +10019904: f7f6 ff83 bl 1001080e +10019908: 2205 movs r2, #5 +1001990a: a90b add r1, sp, #44 ; 0x2c +1001990c: 1da0 adds r0, r4, #6 +1001990e: f7f6 ff7e bl 1001080e +10019912: 2205 movs r2, #5 +10019914: a904 add r1, sp, #16 +10019916: f104 000b add.w r0, r4, #11 +1001991a: f7f6 ff78 bl 1001080e +1001991e: 9801 ldr r0, [sp, #4] +10019920: f20f 016c addw r1, pc, #108 ; 0x6c +10019924: 3010 adds r0, #16 +10019926: 9001 str r0, [sp, #4] +10019928: a802 add r0, sp, #8 +1001992a: c90c ldmia r1!, {r2, r3} +1001992c: c00c stmia r0!, {r2, r3} +1001992e: a801 add r0, sp, #4 +10019930: 9000 str r0, [sp, #0] +10019932: ab02 add r3, sp, #8 +10019934: 2206 movs r2, #6 +10019936: 21dd movs r1, #221 ; 0xdd +10019938: f104 0010 add.w r0, r4, #16 +1001993c: f7fe fd20 bl 10018380 +10019940: 9801 ldr r0, [sp, #4] +10019942: b018 add sp, #96 ; 0x60 +10019944: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + +10019948 <.text_46>: +10019948: 2204 movs r2, #4 +1001994a: 4621 mov r1, r4 +1001994c: 4628 mov r0, r5 +1001994e: f7f6 bf5e b.w 1001080e + +10019952 <.text_47>: +10019952: 4620 mov r0, r4 +10019954: f7fe bd14 b.w 10018380 + +10019958 <.text_49>: +10019958: 1001bb34 .word 0x1001bb34 + +1001995c <.text_50>: +1001995c: 1001beb8 .word 0x1001beb8 + +10019960 <.text_51>: +10019960: 1001e460 .word 0x1001e460 + +10019964 <.text_52>: +10019964: 1001beb4 .word 0x1001beb4 + +10019968 <.text_53>: +10019968: 1000445c .word 0x1000445c + +1001996c <.text_54>: +1001996c: 00035430 .word 0x00035430 + +10019970 <.text_55>: +10019970: 00035444 .word 0x00035444 + +10019974 : +10019974: 01f25000 .P.. + +10019978 : +10019978: ffffffff 0000ffff ........ + +10019980 : +10019980: 01004a10 00000020 .J.. ... + +10019988 : +10019988: 01004410 00000002 .D...... + +10019990 : +10019990: 024ce000 00001001 ..L..... + +10019998 : +10019998: f8df f000 ldr.w pc, [pc] ; 1001999c +1001999c: 0001362d .word 0x0001362d + +100199a0 : +100199a0: f8df f000 ldr.w pc, [pc] ; 100199a4 +100199a4: 000136c9 .word 0x000136c9 + +100199a8 : +100199a8: f8df f000 ldr.w pc, [pc] ; 100199ac +100199ac: 00013b91 .word 0x00013b91 + +100199b0 : +100199b0: f8df f000 ldr.w pc, [pc] ; 100199b4 +100199b4: 00013b49 .word 0x00013b49 + +100199b8 : +100199b8: f8df f000 ldr.w pc, [pc] ; 100199bc +100199bc: 0001350d .word 0x0001350d + +100199c0 : +100199c0: 8801 ldrh r1, [r0, #0] +100199c2: 0a0a lsrs r2, r1, #8 +100199c4: f002 0201 and.w r2, r2, #1 +100199c8: 0a89 lsrs r1, r1, #10 +100199ca: 4152 adcs r2, r2 +100199cc: b2d2 uxtb r2, r2 +100199ce: 2a01 cmp r2, #1 +100199d0: d801 bhi.n 100199d6 +100199d2: 1d00 adds r0, r0, #4 +100199d4: 4770 bx lr +100199d6: 3010 adds r0, #16 +100199d8: 4770 bx lr + +100199da : +100199da: 6840 ldr r0, [r0, #4] +100199dc: 4208 tst r0, r1 +100199de: d001 beq.n 100199e4 +100199e0: 2001 movs r0, #1 +100199e2: 4770 bx lr +100199e4: 2000 movs r0, #0 +100199e6: 4770 bx lr + +100199e8 : +100199e8: b530 push {r4, r5, lr} +100199ea: 2300 movs r3, #0 +100199ec: e000 b.n 100199f0 +100199ee: 1c5b adds r3, r3, #1 +100199f0: 240c movs r4, #12 +100199f2: 435c muls r4, r3 +100199f4: 5c25 ldrb r5, [r4, r0] +100199f6: 2d00 cmp r5, #0 +100199f8: d004 beq.n 10019a04 +100199fa: 42a9 cmp r1, r5 +100199fc: d1f7 bne.n 100199ee +100199fe: b11a cbz r2, 10019a08 +10019a00: 6013 str r3, [r2, #0] +10019a02: e001 b.n 10019a08 +10019a04: 4628 mov r0, r5 +10019a06: d000 beq.n 10019a0a +10019a08: 2001 movs r0, #1 +10019a0a: bd30 pop {r4, r5, pc} + +10019a0c : +10019a0c: b580 push {r7, lr} +10019a0e: f500 619d add.w r1, r0, #1256 ; 0x4e8 +10019a12: 7bcb ldrb r3, [r1, #15] +10019a14: 7c0a ldrb r2, [r1, #16] +10019a16: 7b89 ldrb r1, [r1, #14] +10019a18: f00c f8be bl 10025b98 +10019a1c: 2001 movs r0, #1 +10019a1e: bd02 pop {r1, pc} + +10019a20 : +10019a20: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +10019a24: 4680 mov r8, r0 +10019a26: b088 sub sp, #32 +10019a28: f508 649d add.w r4, r8, #1256 ; 0x4e8 +10019a2c: f504 7588 add.w r5, r4, #272 ; 0x110 +10019a30: a804 add r0, sp, #16 +10019a32: f20f 01b0 addw r1, pc, #176 ; 0xb0 +10019a36: 2210 movs r2, #16 +10019a38: f014 fd38 bl 1002e4ac <__iar_unaligned___aeabi_memcpy4> +10019a3c: a800 add r0, sp, #0 +10019a3e: f20f 01b4 addw r1, pc, #180 ; 0xb4 +10019a42: 2210 movs r2, #16 +10019a44: f014 fd32 bl 1002e4ac <__iar_unaligned___aeabi_memcpy4> +10019a48: 2100 movs r1, #0 +10019a4a: f104 0008 add.w r0, r4, #8 +10019a4e: f7f7 f80b bl 10010a68 +10019a52: 2000 movs r0, #0 +10019a54: 81a0 strh r0, [r4, #12] +10019a56: f104 070c add.w r7, r4, #12 +10019a5a: f641 00ad movw r0, #6317 ; 0x18ad +10019a5e: f204 3636 addw r6, r4, #822 ; 0x336 +10019a62: f810 1008 ldrb.w r1, [r0, r8] +10019a66: 70b9 strb r1, [r7, #2] +10019a68: 4440 add r0, r8 +10019a6a: 2100 movs r1, #0 +10019a6c: 70f9 strb r1, [r7, #3] +10019a6e: 7139 strb r1, [r7, #4] +10019a70: 70b1 strb r1, [r6, #2] +10019a72: 220d movs r2, #13 +10019a74: 7840 ldrb r0, [r0, #1] +10019a76: 7178 strb r0, [r7, #5] +10019a78: a904 add r1, sp, #16 +10019a7a: f104 00c9 add.w r0, r4, #201 ; 0xc9 +10019a7e: f7f6 fec6 bl 1001080e +10019a82: 220d movs r2, #13 +10019a84: a900 add r1, sp, #0 +10019a86: f104 00bc add.w r0, r4, #188 ; 0xbc +10019a8a: f7f6 fec0 bl 1001080e +10019a8e: 78b8 ldrb r0, [r7, #2] +10019a90: 280f cmp r0, #15 +10019a92: bfac ite ge +10019a94: 200c movge r0, #12 +10019a96: 2002 movlt r0, #2 +10019a98: 7070 strb r0, [r6, #1] +10019a9a: 2100 movs r1, #0 +10019a9c: 2000 movs r0, #0 +10019a9e: f8c4 00d8 str.w r0, [r4, #216] ; 0xd8 +10019aa2: 2280 movs r2, #128 ; 0x80 +10019aa4: f104 00d8 add.w r0, r4, #216 ; 0xd8 +10019aa8: 6081 str r1, [r0, #8] +10019aaa: 6041 str r1, [r0, #4] +10019aac: f884 1336 strb.w r1, [r4, #822] ; 0x336 +10019ab0: 6029 str r1, [r5, #0] +10019ab2: 6069 str r1, [r5, #4] +10019ab4: 60a9 str r1, [r5, #8] +10019ab6: 60e9 str r1, [r5, #12] +10019ab8: 6129 str r1, [r5, #16] +10019aba: 6169 str r1, [r5, #20] +10019abc: 6229 str r1, [r5, #32] +10019abe: 6269 str r1, [r5, #36] ; 0x24 +10019ac0: 61e9 str r1, [r5, #28] +10019ac2: 61a9 str r1, [r5, #24] +10019ac4: f105 0028 add.w r0, r5, #40 ; 0x28 +10019ac8: f7f6 feb6 bl 10010838 +10019acc: 2009 movs r0, #9 +10019ace: f885 00af strb.w r0, [r5, #175] ; 0xaf +10019ad2: 2002 movs r0, #2 +10019ad4: f885 00b0 strb.w r0, [r5, #176] ; 0xb0 +10019ad8: 2000 movs r0, #0 +10019ada: f885 00be strb.w r0, [r5, #190] ; 0xbe +10019ade: b008 add sp, #32 +10019ae0: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +10019ae4 : +10019ae4: 0100 0302 0504 0706 0908 0b0a 00ff 0000 ................ + +10019af4 : +10019af4: 0100 0302 0604 ff08 0000 0000 0000 0000 ................ + +10019b04 : +10019b04: b5f8 push {r3, r4, r5, r6, r7, lr} +10019b06: 4604 mov r4, r0 +10019b08: 460d mov r5, r1 +10019b0a: 4616 mov r6, r2 +10019b0c: 2700 movs r7, #0 +10019b0e: 22a8 movs r2, #168 ; 0xa8 +10019b10: 2100 movs r1, #0 +10019b12: 4630 mov r0, r6 +10019b14: f7f6 fe90 bl 10010838 +10019b18: 4628 mov r0, r5 +10019b1a: 2859 cmp r0, #89 ; 0x59 +10019b1c: db03 blt.n 10019b26 +10019b1e: 287f cmp r0, #127 ; 0x7f +10019b20: d001 beq.n 10019b26 +10019b22: 2000 movs r0, #0 +10019b24: bdf2 pop {r1, r4, r5, r6, r7, pc} +10019b26: f641 01ae movw r1, #6318 ; 0x18ae +10019b2a: 220b movs r2, #11 +10019b2c: 5d09 ldrb r1, [r1, r4] +10019b2e: 4211 tst r1, r2 +10019b30: d03b beq.n 10019baa +10019b32: 287f cmp r0, #127 ; 0x7f +10019b34: bf0e itee eq +10019b36: 2103 moveq r1, #3 +10019b38: f20f 017c addwne r1, pc, #124 ; 0x7c +10019b3c: f811 1010 ldrbne.w r1, [r1, r0, lsl #1] +10019b40: f20f 1328 addw r3, pc, #296 ; 0x128 +10019b44: ebc1 1c01 rsb ip, r1, r1, lsl #4 +10019b48: 2200 movs r2, #0 +10019b4a: 4463 add r3, ip +10019b4c: e006 b.n 10019b5c +10019b4e: f04f 0e01 mov.w lr, #1 +10019b52: f8cc e004 str.w lr, [ip, #4] +10019b56: 1c7f adds r7, r7, #1 +10019b58: b2ff uxtb r7, r7 +10019b5a: 1c52 adds r2, r2, #1 +10019b5c: f893 c00e ldrb.w ip, [r3, #14] +10019b60: b2d2 uxtb r2, r2 +10019b62: 4562 cmp r2, ip +10019b64: d221 bcs.n 10019baa +10019b66: f04f 0c0c mov.w ip, #12 +10019b6a: f812 e003 ldrb.w lr, [r2, r3] +10019b6e: fb0c fc07 mul.w ip, ip, r7 +10019b72: 2809 cmp r0, #9 +10019b74: f80c e006 strb.w lr, [ip, r6] +10019b78: 44b4 add ip, r6 +10019b7a: d10b bne.n 10019b94 +10019b7c: f1be 0f00 cmp.w lr, #0 +10019b80: d002 beq.n 10019b88 +10019b82: f1be 0f0c cmp.w lr, #12 +10019b86: dbe2 blt.n 10019b4e +10019b88: f1ae 0e0c sub.w lr, lr, #12 +10019b8c: f1be 0f03 cmp.w lr, #3 +10019b90: d308 bcc.n 10019ba4 +10019b92: e7e0 b.n 10019b56 +10019b94: 280a cmp r0, #10 +10019b96: bf1c itt ne +10019b98: 2813 cmpne r0, #19 +10019b9a: 2900 cmpne r1, #0 +10019b9c: d1d7 bne.n 10019b4e +10019b9e: f1be 0f0c cmp.w lr, #12 +10019ba2: dbd4 blt.n 10019b4e +10019ba4: f04f 0e00 mov.w lr, #0 +10019ba8: e7d3 b.n 10019b52 +10019baa: 4629 mov r1, r5 +10019bac: 4620 mov r0, r4 +10019bae: f016 f8b1 bl 1002fd14 +10019bb2: 4638 mov r0, r7 +10019bb4: bdf2 pop {r1, r4, r5, r6, r7, pc} + ... + +10019bb8 : +10019bb8: 1102 0a02 0101 0001 0001 0003 0003 0901 ................ +10019bc8: 0903 0003 0000 0f02 0801 0602 0b02 0902 ................ +10019bd8: 0101 0502 1201 0400 1002 0000 0000 0000 ................ + ... +10019bf8: 0000 0001 0002 0003 0004 0402 0100 0c03 ................ +10019c08: 0b00 0500 0000 0000 0000 0000 0000 0000 ................ +10019c18: 0600 0700 0800 0900 0a02 0200 0300 0d03 ................ +10019c28: 0e03 0f02 0000 0000 0000 0000 0000 0000 ................ +10019c38: 1002 0005 0000 0000 0000 0000 0000 0000 ................ + ... + +10019c6c : +10019c6c: 0201 0403 0605 0807 0a09 0c0b 000d 010d ................ +10019c7c: 0302 0504 0706 0908 0b0a 0d0c 0d00 0201 ................ +10019c8c: 0403 0605 0807 0a09 000b 0000 010b 0302 ................ +10019c9c: 0504 0706 0908 0b0a 0d0c 0e0e 0b0a 0d0c ................ + ... +10019cb4: 0000 0104 0000 0000 0000 0000 0000 0000 ................ +10019cc4: 0100 0000 .... + +10019cc8 : +10019cc8: b538 push {r3, r4, r5, lr} +10019cca: f003 ff1e bl 1001db0a <.text_214> +10019cce: 602c str r4, [r5, #0] +10019cd0: f7ff fea6 bl 10019a20 +10019cd4: 4620 mov r0, r4 +10019cd6: f004 fa35 bl 1001e144 +10019cda: 4620 mov r0, r4 +10019cdc: f7fe fb6f bl 100183be +10019ce0: f105 0214 add.w r2, r5, #20 +10019ce4: f894 149e ldrb.w r1, [r4, #1182] ; 0x49e +10019ce8: 4620 mov r0, r4 +10019cea: f7ff ff0b bl 10019b04 +10019cee: 74a8 strb r0, [r5, #18] +10019cf0: 2064 movs r0, #100 ; 0x64 +10019cf2: f8a5 0334 strh.w r0, [r5, #820] ; 0x334 +10019cf6: 2001 movs r0, #1 +10019cf8: bd32 pop {r1, r4, r5, pc} + +10019cfa : +10019cfa: b510 push {r4, lr} +10019cfc: 4604 mov r4, r0 +10019cfe: 6820 ldr r0, [r4, #0] +10019d00: b170 cbz r0, 10019d20 +10019d02: f641 419c movw r1, #7324 ; 0x1c9c +10019d06: 5808 ldr r0, [r1, r0] +10019d08: 2801 cmp r0, #1 +10019d0a: d109 bne.n 10019d20 +10019d0c: f504 7047 add.w r0, r4, #796 ; 0x31c +10019d10: f7f6 fea3 bl 10010a5a +10019d14: f504 704a add.w r0, r4, #808 ; 0x328 +10019d18: e8bd 4010 ldmia.w sp!, {r4, lr} +10019d1c: f7f6 be9d b.w 10010a5a +10019d20: bd10 pop {r4, pc} + +10019d22 <_mgt_dispatcher>: +10019d22: b5f0 push {r4, r5, r6, r7, lr} +10019d24: 460d mov r5, r1 +10019d26: b083 sub sp, #12 +10019d28: 4616 mov r6, r2 +10019d2a: f20f 0138 addw r1, pc, #56 ; 0x38 +10019d2e: 4604 mov r4, r0 +10019d30: c90c ldmia r1!, {r2, r3} +10019d32: a800 add r0, sp, #0 +10019d34: c00c stmia r0!, {r2, r3} +10019d36: f8d6 0084 ldr.w r0, [r6, #132] ; 0x84 +10019d3a: 68a9 ldr r1, [r5, #8] +10019d3c: b189 cbz r1, 10019d62 <_mgt_dispatcher+0x40> +10019d3e: 1d07 adds r7, r0, #4 +10019d40: f504 51c8 add.w r1, r4, #6400 ; 0x1900 +10019d44: 2206 movs r2, #6 +10019d46: 3195 adds r1, #149 ; 0x95 +10019d48: f000 ffaf bl 1001acaa <.text_51> +10019d4c: b928 cbnz r0, 10019d5a <_mgt_dispatcher+0x38> +10019d4e: 2206 movs r2, #6 +10019d50: a900 add r1, sp, #0 +10019d52: 4638 mov r0, r7 +10019d54: f7f6 fd65 bl 10010822 +10019d58: b118 cbz r0, 10019d62 <_mgt_dispatcher+0x40> +10019d5a: 68aa ldr r2, [r5, #8] +10019d5c: 4631 mov r1, r6 +10019d5e: 4620 mov r0, r4 +10019d60: 4790 blx r2 +10019d62: bdf7 pop {r0, r1, r2, r4, r5, r6, r7, pc} + +10019d64 : +10019d64: ffff ffff ffff 0000 ........ + +10019d6c : +10019d6c: e92d 41fc stmdb sp!, {r2, r3, r4, r5, r6, r7, r8, lr} +10019d70: 460d mov r5, r1 +10019d72: f20f 0180 addw r1, pc, #128 ; 0x80 +10019d76: 4604 mov r4, r0 +10019d78: c90c ldmia r1!, {r2, r3} +10019d7a: a800 add r0, sp, #0 +10019d7c: 210c movs r1, #12 +10019d7e: c00c stmia r0!, {r2, r3} +10019d80: f8d5 7084 ldr.w r7, [r5, #132] ; 0x84 +10019d84: 7838 ldrb r0, [r7, #0] +10019d86: 4208 tst r0, r1 +10019d88: f104 080c add.w r8, r4, #12 +10019d8c: d12f bne.n 10019dee +10019d8e: 1d3e adds r6, r7, #4 +10019d90: f504 51c8 add.w r1, r4, #6400 ; 0x1900 +10019d94: 2206 movs r2, #6 +10019d96: 3195 adds r1, #149 ; 0x95 +10019d98: 4630 mov r0, r6 +10019d9a: f7f6 fd42 bl 10010822 +10019d9e: b928 cbnz r0, 10019dac +10019da0: 2206 movs r2, #6 +10019da2: a900 add r1, sp, #0 +10019da4: 4630 mov r0, r6 +10019da6: f7f6 fd3c bl 10010822 +10019daa: b300 cbz r0, 10019dee +10019dac: 8838 ldrh r0, [r7, #0] +10019dae: f3c0 1103 ubfx r1, r0, #4, #4 +10019db2: 290e cmp r1, #14 +10019db4: da1b bge.n 10019dee +10019db6: 230c movs r3, #12 +10019db8: f000 00fc and.w r0, r0, #252 ; 0xfc +10019dbc: f8df 2d38 ldr.w r2, [pc, #3384] ; 1001aaf8 <.text_43> +10019dc0: 2840 cmp r0, #64 ; 0x40 +10019dc2: fb03 2701 mla r7, r3, r1, r2 +10019dc6: d00b beq.n 10019de0 +10019dc8: 28b0 cmp r0, #176 ; 0xb0 +10019dca: d10b bne.n 10019de4 +10019dcc: f000 f816 bl 10019dfc <.text_22> +10019dd0: 2801 cmp r0, #1 +10019dd2: bf0c ite eq +10019dd4: f20f 2031 addweq r0, pc, #561 ; 0x231 +10019dd8: f20f 40f1 addwne r0, pc, #1265 ; 0x4f1 +10019ddc: 60b8 str r0, [r7, #8] +10019dde: e001 b.n 10019de4 +10019de0: f000 f80c bl 10019dfc <.text_22> +10019de4: 462a mov r2, r5 +10019de6: 4639 mov r1, r7 +10019de8: 4620 mov r0, r4 +10019dea: f7ff ff9a bl 10019d22 <_mgt_dispatcher> +10019dee: e8bd 81f3 ldmia.w sp!, {r0, r1, r4, r5, r6, r7, r8, pc} + ... + +10019df4 : +10019df4: ffff ffff ffff 0000 ........ + +10019dfc <.text_22>: +10019dfc: 2110 movs r1, #16 +10019dfe: 4640 mov r0, r8 +10019e00: e5eb b.n 100199da + +10019e02 : +10019e02: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +10019e06: 4680 mov r8, r0 +10019e08: f8d1 5084 ldr.w r5, [r1, #132] ; 0x84 +10019e0c: 6fce ldr r6, [r1, #124] ; 0x7c +10019e0e: f108 090c add.w r9, r8, #12 +10019e12: f508 67bf add.w r7, r8, #1528 ; 0x5f8 +10019e16: f109 048c add.w r4, r9, #140 ; 0x8c +10019e1a: 2108 movs r1, #8 +10019e1c: f000 f84f bl 10019ebe <.text_24+0x2> +10019e20: 2800 cmp r0, #0 +10019e22: d148 bne.n 10019eb6 +10019e24: f000 f84a bl 10019ebc <.text_24> +10019e28: b920 cbnz r0, 10019e34 +10019e2a: 2150 movs r1, #80 ; 0x50 +10019e2c: f000 f847 bl 10019ebe <.text_24+0x2> +10019e30: 2800 cmp r0, #0 +10019e32: d040 beq.n 10019eb6 +10019e34: f000 fdd0 bl 1001a9d8 <.text_39> +10019e38: 2803 cmp r0, #3 +10019e3a: d106 bne.n 10019e4a +10019e3c: f44f 6108 mov.w r1, #2176 ; 0x880 +10019e40: 4640 mov r0, r8 +10019e42: f005 fd04 bl 1001f84e +10019e46: 2800 cmp r0, #0 +10019e48: d135 bne.n 10019eb6 +10019e4a: f1a6 0318 sub.w r3, r6, #24 +10019e4e: aa00 add r2, sp, #0 +10019e50: 2100 movs r1, #0 +10019e52: f105 0018 add.w r0, r5, #24 +10019e56: f7fa f813 bl 10013e80 +10019e5a: b360 cbz r0, 10019eb6 +10019e5c: 9900 ldr r1, [sp, #0] +10019e5e: b141 cbz r1, 10019e72 +10019e60: 68e2 ldr r2, [r4, #12] +10019e62: f104 0110 add.w r1, r4, #16 +10019e66: 1c80 adds r0, r0, #2 +10019e68: f7f6 fcdb bl 10010822 +10019e6c: b318 cbz r0, 10019eb6 +10019e6e: 9800 ldr r0, [sp, #0] +10019e70: b910 cbnz r0, 10019e78 +10019e72: f897 00c0 ldrb.w r0, [r7, #192] ; 0xc0 +10019e76: b9f0 cbnz r0, 10019eb6 +10019e78: f000 f820 bl 10019ebc <.text_24> +10019e7c: 2801 cmp r0, #1 +10019e7e: bf04 itt eq +10019e80: f8d9 0088 ldreq.w r0, [r9, #136] ; 0x88 +10019e84: 2801 cmpeq r0, #1 +10019e86: d116 bne.n 10019eb6 +10019e88: 8828 ldrh r0, [r5, #0] +10019e8a: 0a01 lsrs r1, r0, #8 +10019e8c: f001 0101 and.w r1, r1, #1 +10019e90: 0a80 lsrs r0, r0, #10 +10019e92: 4149 adcs r1, r1 +10019e94: b2c9 uxtb r1, r1 +10019e96: 2900 cmp r1, #0 +10019e98: bf18 it ne +10019e9a: 2902 cmpne r1, #2 +10019e9c: d005 beq.n 10019eaa +10019e9e: bf34 ite cc +10019ea0: f105 0110 addcc.w r1, r5, #16 +10019ea4: f105 0118 addcs.w r1, r5, #24 +10019ea8: e001 b.n 10019eae +10019eaa: f105 010a add.w r1, r5, #10 +10019eae: 2200 movs r2, #0 +10019eb0: 4640 mov r0, r8 +10019eb2: f001 fa0d bl 1001b2d0 +10019eb6: 2001 movs r0, #1 +10019eb8: e8bd 83f2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, pc} + +10019ebc <.text_24>: +10019ebc: 2101 movs r1, #1 +10019ebe: 4648 mov r0, r9 +10019ec0: e58b b.n 100199da + +10019ec2 : +10019ec2: b580 push {r7, lr} +10019ec4: f8d0 25c0 ldr.w r2, [r0, #1472] ; 0x5c0 +10019ec8: 2a03 cmp r2, #3 +10019eca: bf08 it eq +10019ecc: f003 f847 bleq 1001cf5e +10019ed0: 2001 movs r0, #1 +10019ed2: bd02 pop {r1, pc} + +10019ed4 : +10019ed4: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +10019ed8: 4604 mov r4, r0 +10019eda: f504 689d add.w r8, r4, #1256 ; 0x4e8 +10019ede: f504 5088 add.w r0, r4, #4352 ; 0x1100 +10019ee2: f100 0a28 add.w sl, r0, #40 ; 0x28 +10019ee6: f8d8 00d8 ldr.w r0, [r8, #216] ; 0xd8 +10019eea: f8d1 9084 ldr.w r9, [r1, #132] ; 0x84 +10019eee: 6fcd ldr r5, [r1, #124] ; 0x7c +10019ef0: 2803 cmp r0, #3 +10019ef2: f508 7788 add.w r7, r8, #272 ; 0x110 +10019ef6: f104 0698 add.w r6, r4, #152 ; 0x98 +10019efa: d103 bne.n 10019f04 +10019efc: 4620 mov r0, r4 +10019efe: f003 f82e bl 1001cf5e +10019f02: e063 b.n 10019fcc +10019f04: 4630 mov r0, r6 +10019f06: f00b fe70 bl 10025bea +10019f0a: 4601 mov r1, r0 +10019f0c: 2206 movs r2, #6 +10019f0e: f109 0010 add.w r0, r9, #16 +10019f12: f7f6 fc86 bl 10010822 +10019f16: 2800 cmp r0, #0 +10019f18: d058 beq.n 10019fcc +10019f1a: 6838 ldr r0, [r7, #0] +10019f1c: 05c1 lsls r1, r0, #23 +10019f1e: d510 bpl.n 10019f42 +10019f20: f1a5 0118 sub.w r1, r5, #24 +10019f24: f109 0018 add.w r0, r9, #24 +10019f28: f00c fae1 bl 100264ee +10019f2c: f887 00ae strb.w r0, [r7, #174] ; 0xae +10019f30: 462a mov r2, r5 +10019f32: 4649 mov r1, r9 +10019f34: 4640 mov r0, r8 +10019f36: f00c fc10 bl 1002675a +10019f3a: 4620 mov r0, r4 +10019f3c: f002 fdef bl 1001cb1e +10019f40: e044 b.n 10019fcc +10019f42: f244 0103 movw r1, #16387 ; 0x4003 +10019f46: 4008 ands r0, r1 +10019f48: f244 0102 movw r1, #16386 ; 0x4002 +10019f4c: 4288 cmp r0, r1 +10019f4e: d13d bne.n 10019fcc +10019f50: f109 010a add.w r1, r9, #10 +10019f54: 4650 mov r0, sl +10019f56: f00b f929 bl 100251ac +10019f5a: 0007 movs r7, r0 +10019f5c: d036 beq.n 10019fcc +10019f5e: 462a mov r2, r5 +10019f60: 4649 mov r1, r9 +10019f62: 4620 mov r0, r4 +10019f64: f00c f8a7 bl 100260b6 +10019f68: b958 cbnz r0, 10019f82 +10019f6a: f001 ffbf bl 1001beec <.text_124> +10019f6e: f20f 0064 addw r0, pc, #100 ; 0x64 +10019f72: f7f2 f9c6 bl 1000c302 +10019f76: f64f 72ff movw r2, #65535 ; 0xffff +10019f7a: 1d31 adds r1, r6, #4 +10019f7c: f000 fe8d bl 1001ac9a <.text_49+0x4> +10019f80: e024 b.n 10019fcc +10019f82: f504 5088 add.w r0, r4, #4352 ; 0x1100 +10019f86: 30f0 adds r0, #240 ; 0xf0 +10019f88: f8d0 0364 ldr.w r0, [r0, #868] ; 0x364 +10019f8c: 2804 cmp r0, #4 +10019f8e: bf18 it ne +10019f90: 2807 cmpne r0, #7 +10019f92: d102 bne.n 10019f9a +10019f94: f7f6 f868 bl 10010068 +10019f98: b128 cbz r0, 10019fa6 +10019f9a: 2200 movs r2, #0 +10019f9c: 2300 movs r3, #0 +10019f9e: 4611 mov r1, r2 +10019fa0: 200d movs r0, #13 +10019fa2: f015 ff33 bl 1002fe0c +10019fa6: f507 76c0 add.w r6, r7, #384 ; 0x180 +10019faa: e9d7 0160 ldrd r0, r1, [r7, #384] ; 0x180 +10019fae: e9d6 2302 ldrd r2, r3, [r6, #8] +10019fb2: 1882 adds r2, r0, r2 +10019fb4: e9d6 0104 ldrd r0, r1, [r6, #16] +10019fb8: 1810 adds r0, r2, r0 +10019fba: f010 000f ands.w r0, r0, #15 +10019fbe: d105 bne.n 10019fcc +10019fc0: 463b mov r3, r7 +10019fc2: 462a mov r2, r5 +10019fc4: 4649 mov r1, r9 +10019fc6: 4620 mov r0, r4 +10019fc8: f00c f976 bl 100262b8 +10019fcc: 2001 movs r0, #1 +10019fce: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + ... + +10019fd4 : +10019fd4: 5452 384c 3931 4135 445b 6972 6576 5d72 RTL8195A[Driver] +10019fe4: 203a 7061 6820 7361 6320 6168 676e 6465 : ap has changed +10019ff4: 202c 6964 6373 6e6f 656e 7463 6e20 776f , disconnect now +1001a004: 200a 0000 . .. + +1001a008 : +1001a008: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +1001a00c: 4681 mov r9, r0 +1001a00e: f509 5088 add.w r0, r9, #4352 ; 0x1100 +1001a012: b087 sub sp, #28 +1001a014: f100 08f0 add.w r8, r0, #240 ; 0xf0 +1001a018: f8d1 0084 ldr.w r0, [r1, #132] ; 0x84 +1001a01c: 9004 str r0, [sp, #16] +1001a01e: f509 66bf add.w r6, r9, #1528 ; 0x5f8 +1001a022: 6fc8 ldr r0, [r1, #124] ; 0x7c +1001a024: 9006 str r0, [sp, #24] +1001a026: f509 5788 add.w r7, r9, #4352 ; 0x1100 +1001a02a: 7830 ldrb r0, [r6, #0] +1001a02c: 3728 adds r7, #40 ; 0x28 +1001a02e: f001 f943 bl 1001b2b8 <.text_85> +1001a032: d104 bne.n 1001a03e +1001a034: f000 f944 bl 1001a2c0 <.text_32> +1001a038: 2800 cmp r0, #0 +1001a03a: f040 80a9 bne.w 1001a190 +1001a03e: 7830 ldrb r0, [r6, #0] +1001a040: f001 f93a bl 1001b2b8 <.text_85> +1001a044: f040 80f5 bne.w 1001a232 +1001a048: f8dd b010 ldr.w fp, [sp, #16] +1001a04c: a47a add r4, pc, #488 ; (adr r4, 1001a238 <.text_29>) +1001a04e: f10b 060a add.w r6, fp, #10 +1001a052: 4620 mov r0, r4 +1001a054: f7f2 f955 bl 1000c302 +1001a058: 7970 ldrb r0, [r6, #5] +1001a05a: 9002 str r0, [sp, #8] +1001a05c: 7930 ldrb r0, [r6, #4] +1001a05e: 9001 str r0, [sp, #4] +1001a060: 78f0 ldrb r0, [r6, #3] +1001a062: 9000 str r0, [sp, #0] +1001a064: 78b3 ldrb r3, [r6, #2] +1001a066: 7872 ldrb r2, [r6, #1] +1001a068: 7831 ldrb r1, [r6, #0] +1001a06a: f20f 10d0 addw r0, pc, #464 ; 0x1d0 +1001a06e: f7f2 f948 bl 1000c302 +1001a072: f8d8 5000 ldr.w r5, [r8] +1001a076: f8bb a01a ldrh.w sl, [fp, #26] +1001a07a: f8bb b018 ldrh.w fp, [fp, #24] +1001a07e: 2d02 cmp r5, #2 +1001a080: d106 bne.n 1001a090 +1001a082: f8d8 0004 ldr.w r0, [r8, #4] +1001a086: 2801 cmp r0, #1 +1001a088: bf18 it ne +1001a08a: 2805 cmpne r0, #5 +1001a08c: d008 beq.n 1001a0a0 +1001a08e: 2500 movs r5, #0 +1001a090: f1bb 0f00 cmp.w fp, #0 +1001a094: d002 beq.n 1001a09c +1001a096: b91d cbnz r5, 1001a0a0 +1001a098: 270d movs r7, #13 +1001a09a: e0b6 b.n 1001a20a +1001a09c: 2d01 cmp r5, #1 +1001a09e: d0fb beq.n 1001a098 +1001a0a0: 4631 mov r1, r6 +1001a0a2: f000 fe06 bl 1001acb2 <.text_52+0x2> +1001a0a6: ea5f 0800 movs.w r8, r0 +1001a0aa: d118 bne.n 1001a0de +1001a0ac: 4631 mov r1, r6 +1001a0ae: 4638 mov r0, r7 +1001a0b0: f00a ff1a bl 10024ee8 +1001a0b4: ea5f 0800 movs.w r8, r0 +1001a0b8: d109 bne.n 1001a0ce +1001a0ba: 4620 mov r0, r4 +1001a0bc: f7f2 f921 bl 1000c302 +1001a0c0: 2103 movs r1, #3 +1001a0c2: f20f 10b4 addw r0, pc, #436 ; 0x1b4 +1001a0c6: f7f2 f91c bl 1000c302 +1001a0ca: 2711 movs r7, #17 +1001a0cc: e09d b.n 1001a20a +1001a0ce: f44f 7080 mov.w r0, #256 ; 0x100 +1001a0d2: f8c8 00f8 str.w r0, [r8, #248] ; 0xf8 +1001a0d6: 2000 movs r0, #0 +1001a0d8: f8c8 0230 str.w r0, [r8, #560] ; 0x230 +1001a0dc: e012 b.n 1001a104 +1001a0de: a903 add r1, sp, #12 +1001a0e0: f107 008c add.w r0, r7, #140 ; 0x8c +1001a0e4: f7f6 fc16 bl 10010914 +1001a0e8: f508 7407 add.w r4, r8, #540 ; 0x21c +1001a0ec: 4620 mov r0, r4 +1001a0ee: f7f6 fbae bl 1001084e +1001a0f2: b910 cbnz r0, 1001a0fa +1001a0f4: 4620 mov r0, r4 +1001a0f6: f7f6 fbb5 bl 10010864 +1001a0fa: a903 add r1, sp, #12 +1001a0fc: f107 008c add.w r0, r7, #140 ; 0x8c +1001a100: f7f6 fc09 bl 10010916 +1001a104: a903 add r1, sp, #12 +1001a106: f107 0090 add.w r0, r7, #144 ; 0x90 +1001a10a: f7f6 fc03 bl 10010914 +1001a10e: f508 7409 add.w r4, r8, #548 ; 0x224 +1001a112: 4620 mov r0, r4 +1001a114: f7f6 fb9b bl 1001084e +1001a118: b120 cbz r0, 1001a124 +1001a11a: f107 0184 add.w r1, r7, #132 ; 0x84 +1001a11e: 4620 mov r0, r4 +1001a120: f7f6 fb9e bl 10010860 +1001a124: a903 add r1, sp, #12 +1001a126: f107 0090 add.w r0, r7, #144 ; 0x90 +1001a12a: f7f6 fbf4 bl 10010916 +1001a12e: f508 740b add.w r4, r8, #556 ; 0x22c +1001a132: 6860 ldr r0, [r4, #4] +1001a134: b918 cbnz r0, 1001a13e +1001a136: f8d7 1094 ldr.w r1, [r7, #148] ; 0x94 +1001a13a: f8c8 122c str.w r1, [r8, #556] ; 0x22c +1001a13e: 1c40 adds r0, r0, #1 +1001a140: 4550 cmp r0, sl +1001a142: d15a bne.n 1001a1fa +1001a144: 3794 adds r7, #148 ; 0x94 +1001a146: f1bb 0f00 cmp.w fp, #0 +1001a14a: d123 bne.n 1001a194 +1001a14c: 2d00 cmp r5, #0 +1001a14e: bf18 it ne +1001a150: 2d02 cmpne r5, #2 +1001a152: d11f bne.n 1001a194 +1001a154: f1ba 0f01 cmp.w sl, #1 +1001a158: d14f bne.n 1001a1fa +1001a15a: f8d8 00f8 ldr.w r0, [r8, #248] ; 0xf8 +1001a15e: f420 7080 bic.w r0, r0, #256 ; 0x100 +1001a162: f440 6080 orr.w r0, r0, #1024 ; 0x400 +1001a166: f8c8 00f8 str.w r0, [r8, #248] ; 0xf8 +1001a16a: 6878 ldr r0, [r7, #4] +1001a16c: f8c8 022c str.w r0, [r8, #556] ; 0x22c +1001a170: 2000 movs r0, #0 +1001a172: 60a0 str r0, [r4, #8] +1001a174: f10a 0001 add.w r0, sl, #1 +1001a178: 6060 str r0, [r4, #4] +1001a17a: 2200 movs r2, #0 +1001a17c: 4641 mov r1, r8 +1001a17e: 4648 mov r0, r9 +1001a180: f001 fab8 bl 1001b6f4 +1001a184: f8d8 00f8 ldr.w r0, [r8, #248] ; 0xf8 +1001a188: 0540 lsls r0, r0, #21 +1001a18a: bf44 itt mi +1001a18c: 2000 movmi r0, #0 +1001a18e: 6060 strmi r0, [r4, #4] +1001a190: 2001 movs r0, #1 +1001a192: e04f b.n 1001a234 +1001a194: f1ba 0f01 cmp.w sl, #1 +1001a198: d10a bne.n 1001a1b0 +1001a19a: f8d8 10f8 ldr.w r1, [r8, #248] ; 0xf8 +1001a19e: 2002 movs r0, #2 +1001a1a0: f360 2109 bfi r1, r0, #8, #2 +1001a1a4: f8c8 10f8 str.w r1, [r8, #248] ; 0xf8 +1001a1a8: f8c4 b008 str.w fp, [r4, #8] +1001a1ac: 6060 str r0, [r4, #4] +1001a1ae: e7e1 b.n 1001a174 +1001a1b0: f1ba 0f03 cmp.w sl, #3 +1001a1b4: d121 bne.n 1001a1fa +1001a1b6: 9806 ldr r0, [sp, #24] +1001a1b8: f1a0 0322 sub.w r3, r0, #34 ; 0x22 +1001a1bc: 9804 ldr r0, [sp, #16] +1001a1be: aa05 add r2, sp, #20 +1001a1c0: 2110 movs r1, #16 +1001a1c2: 3022 adds r0, #34 ; 0x22 +1001a1c4: f7f9 fe5c bl 10013e80 +1001a1c8: 2800 cmp r0, #0 +1001a1ca: bf1c itt ne +1001a1cc: 9905 ldrne r1, [sp, #20] +1001a1ce: 2900 cmpne r1, #0 +1001a1d0: d011 beq.n 1001a1f6 +1001a1d2: 2280 movs r2, #128 ; 0x80 +1001a1d4: f508 710e add.w r1, r8, #568 ; 0x238 +1001a1d8: 1c80 adds r0, r0, #2 +1001a1da: f7f6 fb22 bl 10010822 +1001a1de: b150 cbz r0, 1001a1f6 +1001a1e0: f8d8 10f8 ldr.w r1, [r8, #248] ; 0xf8 +1001a1e4: 2002 movs r0, #2 +1001a1e6: f360 214a bfi r1, r0, #9, #2 +1001a1ea: f8c8 10f8 str.w r1, [r8, #248] ; 0xf8 +1001a1ee: 6878 ldr r0, [r7, #4] +1001a1f0: f8c8 022c str.w r0, [r8, #556] ; 0x22c +1001a1f4: e7be b.n 1001a174 +1001a1f6: 270f movs r7, #15 +1001a1f8: e000 b.n 1001a1fc +1001a1fa: 270e movs r7, #14 +1001a1fc: f1b8 0f00 cmp.w r8, #0 +1001a200: d003 beq.n 1001a20a +1001a202: 4641 mov r1, r8 +1001a204: 4648 mov r0, r9 +1001a206: f00a fecb bl 10024fa0 +1001a20a: f8df 4c60 ldr.w r4, [pc, #3168] ; 1001ae6c <.text_64> +1001a20e: f44f 7250 mov.w r2, #832 ; 0x340 +1001a212: f000 fbeb bl 1001a9ec <.text_41> +1001a216: 2002 movs r0, #2 +1001a218: f8c4 0230 str.w r0, [r4, #560] ; 0x230 +1001a21c: 2206 movs r2, #6 +1001a21e: 4631 mov r1, r6 +1001a220: f504 7084 add.w r0, r4, #264 ; 0x108 +1001a224: f7f6 faf3 bl 1001080e +1001a228: 463a mov r2, r7 +1001a22a: 4621 mov r1, r4 +1001a22c: 4648 mov r0, r9 +1001a22e: f001 fa61 bl 1001b6f4 +1001a232: 2000 movs r0, #0 +1001a234: f001 b838 b.w 1001b2a8 <.text_83> + +1001a238 <.text_29>: +1001a238: 00000d0a .word 0x00000d0a + +1001a23c : +1001a23c: 384c5452 41353931 6972445b 5d726576 RTL8195A[Driver] +1001a24c: 4f2b203a 7475416e 25203a68 3a783230 : +OnAuth: %02x: +1001a25c: 78323025 3230253a 30253a78 253a7832 %02x:%02x:%02x:% +1001a26c: 3a783230 78323025 0000000a 02x:%02x.... + +1001a278 : +1001a278: 384c5452 41353931 6972445b 5d726576 RTL8195A[Driver] +1001a288: 4520203a 65656378 68742064 70752065 : Exceed the up +1001a298: 20726570 696d696c 64252874 666f2029 per limit(%d) of +1001a2a8: 70757320 74726f70 63206465 6e65696c supported clien +1001a2b8: 2e2e7374 00000a2e ts...... + +1001a2c0 <.text_32>: +1001a2c0: f44f 6108 mov.w r1, #2176 ; 0x880 +1001a2c4: 4648 mov r0, r9 +1001a2c6: f005 bac2 b.w 1001f84e + ... + +1001a2cc : +1001a2cc: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1001a2d0: b082 sub sp, #8 +1001a2d2: 4604 mov r4, r0 +1001a2d4: f8d1 6084 ldr.w r6, [r1, #132] ; 0x84 +1001a2d8: 6fcf ldr r7, [r1, #124] ; 0x7c +1001a2da: f504 689d add.w r8, r4, #1256 ; 0x4e8 +1001a2de: f508 7588 add.w r5, r8, #272 ; 0x110 +1001a2e2: 4630 mov r0, r6 +1001a2e4: f7ff fb6c bl 100199c0 +1001a2e8: 4601 mov r1, r0 +1001a2ea: f504 50c8 add.w r0, r4, #6400 ; 0x1900 +1001a2ee: f000 f869 bl 1001a3c4 <.text_35> +1001a2f2: b110 cbz r0, 1001a2fa +1001a2f4: 6828 ldr r0, [r5, #0] +1001a2f6: 0580 lsls r0, r0, #22 +1001a2f8: d401 bmi.n 1001a2fe +1001a2fa: 2001 movs r0, #1 +1001a2fc: e017 b.n 1001a32e +1001a2fe: 8830 ldrh r0, [r6, #0] +1001a300: 0440 lsls r0, r0, #17 +1001a302: bf4c ite mi +1001a304: 2004 movmi r0, #4 +1001a306: 2000 movpl r0, #0 +1001a308: 1980 adds r0, r0, r6 +1001a30a: f508 784a add.w r8, r8, #808 ; 0x328 +1001a30e: 8b41 ldrh r1, [r0, #26] +1001a310: 8b80 ldrh r0, [r0, #28] +1001a312: b170 cbz r0, 1001a332 +1001a314: 280d cmp r0, #13 +1001a316: d105 bne.n 1001a324 +1001a318: 6968 ldr r0, [r5, #20] +1001a31a: 2801 cmp r0, #1 +1001a31c: bf0c ite eq +1001a31e: 2000 moveq r0, #0 +1001a320: 2001 movne r0, #1 +1001a322: 6168 str r0, [r5, #20] +1001a324: 2101 movs r1, #1 +1001a326: 4640 mov r0, r8 +1001a328: f7f6 fb87 bl 10010a3a +1001a32c: 2000 movs r0, #0 +1001a32e: e8bd 81f6 ldmia.w sp!, {r1, r2, r4, r5, r6, r7, r8, pc} +1001a332: 2902 cmp r1, #2 +1001a334: d11f bne.n 1001a376 +1001a336: 6968 ldr r0, [r5, #20] +1001a338: 2801 cmp r0, #1 +1001a33a: d121 bne.n 1001a380 +1001a33c: f1a7 031e sub.w r3, r7, #30 +1001a340: aa00 add r2, sp, #0 +1001a342: 2110 movs r1, #16 +1001a344: f106 001e add.w r0, r6, #30 +1001a348: f7f9 fd9a bl 10013e80 +1001a34c: 2800 cmp r0, #0 +1001a34e: d0ed beq.n 1001a32c +1001a350: 9a00 ldr r2, [sp, #0] +1001a352: 1c81 adds r1, r0, #2 +1001a354: f105 0028 add.w r0, r5, #40 ; 0x28 +1001a358: f7f6 fa59 bl 1001080e +1001a35c: 2003 movs r0, #3 +1001a35e: 6128 str r0, [r5, #16] +1001a360: 2200 movs r2, #0 +1001a362: 2100 movs r1, #0 +1001a364: 4620 mov r0, r4 +1001a366: f001 f9c5 bl 1001b6f4 +1001a36a: f44f 7196 mov.w r1, #300 ; 0x12c +1001a36e: 4640 mov r0, r8 +1001a370: f7f6 fb63 bl 10010a3a +1001a374: e7c1 b.n 1001a2fa +1001a376: 2904 cmp r1, #4 +1001a378: bf04 itt eq +1001a37a: 6968 ldreq r0, [r5, #20] +1001a37c: 2801 cmpeq r0, #1 +1001a37e: d1d5 bne.n 1001a32c +1001a380: f001 fdb4 bl 1001beec <.text_124> +1001a384: f20f 000c addw r0, pc, #12 +1001a388: f7f1 ffbb bl 1000c302 +1001a38c: 4620 mov r0, r4 +1001a38e: f002 fc1b bl 1001cbc8 +1001a392: e7b2 b.n 1001a2fa + +1001a394 : +1001a394: 5452 384c 3931 4135 445b 6972 6576 5d72 RTL8195A[Driver] +1001a3a4: 203a 7561 6874 7320 6375 6563 7373 202c : auth success, +1001a3b4: 7473 7261 2074 7361 6f73 0a63 0000 0000 start assoc..... + +1001a3c4 <.text_35>: +1001a3c4: 2206 movs r2, #6 +1001a3c6: 3095 adds r0, #149 ; 0x95 +1001a3c8: f7f6 ba2b b.w 10010822 + +1001a3cc : +1001a3cc: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +1001a3d0: b0bd sub sp, #244 ; 0xf4 +1001a3d2: 4681 mov r9, r0 +1001a3d4: f109 000c add.w r0, r9, #12 +1001a3d8: 9006 str r0, [sp, #24] +1001a3da: f509 67bf add.w r7, r9, #1528 ; 0x5f8 +1001a3de: f509 5088 add.w r0, r9, #4352 ; 0x1100 +1001a3e2: 30f0 adds r0, #240 ; 0xf0 +1001a3e4: 9005 str r0, [sp, #20] +1001a3e6: 2600 movs r6, #0 +1001a3e8: 9806 ldr r0, [sp, #24] +1001a3ea: 308c adds r0, #140 ; 0x8c +1001a3ec: 9000 str r0, [sp, #0] +1001a3ee: f509 5088 add.w r0, r9, #4352 ; 0x1100 +1001a3f2: 3028 adds r0, #40 ; 0x28 +1001a3f4: 9003 str r0, [sp, #12] +1001a3f6: 7838 ldrb r0, [r7, #0] +1001a3f8: f8d1 4084 ldr.w r4, [r1, #132] ; 0x84 +1001a3fc: 6fcd ldr r5, [r1, #124] ; 0x7c +1001a3fe: f000 ff5b bl 1001b2b8 <.text_85> +1001a402: d104 bne.n 1001a40e +1001a404: f7ff ff5c bl 1001a2c0 <.text_32> +1001a408: 2800 cmp r0, #0 +1001a40a: f040 82c6 bne.w 1001a99a +1001a40e: f000 fae3 bl 1001a9d8 <.text_39> +1001a412: 2803 cmp r0, #3 +1001a414: d12f bne.n 1001a476 +1001a416: 7820 ldrb r0, [r4, #0] +1001a418: f010 0afc ands.w sl, r0, #252 ; 0xfc +1001a41c: bf0c ite eq +1001a41e: 2704 moveq r7, #4 +1001a420: 270a movne r7, #10 +1001a422: f107 0018 add.w r0, r7, #24 +1001a426: 4285 cmp r5, r0 +1001a428: d325 bcc.n 1001a476 +1001a42a: f104 000a add.w r0, r4, #10 +1001a42e: 9002 str r0, [sp, #8] +1001a430: 4601 mov r1, r0 +1001a432: 9803 ldr r0, [sp, #12] +1001a434: f00a feba bl 100251ac +1001a438: ea5f 0800 movs.w r8, r0 +1001a43c: d016 beq.n 1001a46c +1001a43e: 7e60 ldrb r0, [r4, #25] +1001a440: 7e21 ldrb r1, [r4, #24] +1001a442: ea41 2b00 orr.w fp, r1, r0, lsl #8 +1001a446: 1be8 subs r0, r5, r7 +1001a448: 3818 subs r0, #24 +1001a44a: 9007 str r0, [sp, #28] +1001a44c: 1938 adds r0, r7, r4 +1001a44e: 9004 str r0, [sp, #16] +1001a450: f100 0418 add.w r4, r0, #24 +1001a454: f001 fd4a bl 1001beec <.text_124> +1001a458: f20f 5054 addw r0, pc, #1364 ; 0x554 +1001a45c: f7f1 ff51 bl 1000c302 +1001a460: f8d8 00f8 ldr.w r0, [r8, #248] ; 0xf8 +1001a464: 0541 lsls r1, r0, #21 +1001a466: d40a bmi.n 1001a47e +1001a468: 0441 lsls r1, r0, #17 +1001a46a: d405 bmi.n 1001a478 +1001a46c: 9902 ldr r1, [sp, #8] +1001a46e: 2206 movs r2, #6 +1001a470: 4648 mov r0, r9 +1001a472: f001 fe51 bl 1001c118 +1001a476: e297 b.n 1001a9a8 +1001a478: f420 4080 bic.w r0, r0, #16384 ; 0x4000 +1001a47c: e001 b.n 1001a482 +1001a47e: f420 6080 bic.w r0, r0, #1024 ; 0x400 +1001a482: f8c8 00f8 str.w r0, [r8, #248] ; 0xf8 +1001a486: 2301 movs r3, #1 +1001a488: f440 5000 orr.w r0, r0, #8192 ; 0x2000 +1001a48c: f8c8 00f8 str.w r0, [r8, #248] ; 0xf8 +1001a490: f8a8 b2b8 strh.w fp, [r8, #696] ; 0x2b8 +1001a494: aa0e add r2, sp, #56 ; 0x38 +1001a496: 9907 ldr r1, [sp, #28] +1001a498: 4620 mov r0, r4 +1001a49a: f7ff fa85 bl 100199a8 +1001a49e: f110 0f01 cmn.w r0, #1 +1001a4a2: bf1c itt ne +1001a4a4: 980e ldrne r0, [sp, #56] ; 0x38 +1001a4a6: 2800 cmpne r0, #0 +1001a4a8: d029 beq.n 1001a4fe +1001a4aa: f1a5 0018 sub.w r0, r5, #24 +1001a4ae: 1bc0 subs r0, r0, r7 +1001a4b0: 9007 str r0, [sp, #28] +1001a4b2: 4603 mov r3, r0 +1001a4b4: 9804 ldr r0, [sp, #16] +1001a4b6: aa01 add r2, sp, #4 +1001a4b8: 2100 movs r1, #0 +1001a4ba: 3018 adds r0, #24 +1001a4bc: f7f9 fce0 bl 10013e80 +1001a4c0: 0004 movs r4, r0 +1001a4c2: 9801 ldr r0, [sp, #4] +1001a4c4: bf08 it eq +1001a4c6: 2601 moveq r6, #1 +1001a4c8: 2800 cmp r0, #0 +1001a4ca: d018 beq.n 1001a4fe +1001a4cc: 9800 ldr r0, [sp, #0] +1001a4ce: 68c2 ldr r2, [r0, #12] +1001a4d0: f100 0110 add.w r1, r0, #16 +1001a4d4: 1ca0 adds r0, r4, #2 +1001a4d6: f7f6 f9a4 bl 10010822 +1001a4da: b900 cbnz r0, 1001a4de +1001a4dc: 2601 movs r6, #1 +1001a4de: 9900 ldr r1, [sp, #0] +1001a4e0: 9801 ldr r0, [sp, #4] +1001a4e2: 68c9 ldr r1, [r1, #12] +1001a4e4: 4288 cmp r0, r1 +1001a4e6: f040 8190 bne.w 1001a80a +1001a4ea: 2e00 cmp r6, #0 +1001a4ec: d174 bne.n 1001a5d8 +1001a4ee: 9804 ldr r0, [sp, #16] +1001a4f0: 9b07 ldr r3, [sp, #28] +1001a4f2: aa01 add r2, sp, #4 +1001a4f4: 2101 movs r1, #1 +1001a4f6: 3018 adds r0, #24 +1001a4f8: f7f9 fcc2 bl 10013e80 +1001a4fc: 0004 movs r4, r0 +1001a4fe: f000 8184 beq.w 1001a80a +1001a502: 9a01 ldr r2, [sp, #4] +1001a504: 1c81 adds r1, r0, #2 +1001a506: a80a add r0, sp, #40 ; 0x28 +1001a508: f7f6 f981 bl 1001080e +1001a50c: 9804 ldr r0, [sp, #16] +1001a50e: 9d01 ldr r5, [sp, #4] +1001a510: 9b07 ldr r3, [sp, #28] +1001a512: aa01 add r2, sp, #4 +1001a514: 2132 movs r1, #50 ; 0x32 +1001a516: 3018 adds r0, #24 +1001a518: f7f9 fcb2 bl 10013e80 +1001a51c: 0004 movs r4, r0 +1001a51e: d009 beq.n 1001a534 +1001a520: 2d11 cmp r5, #17 +1001a522: d207 bcs.n 1001a534 +1001a524: 1c81 adds r1, r0, #2 +1001a526: 9a01 ldr r2, [sp, #4] +1001a528: a80a add r0, sp, #40 ; 0x28 +1001a52a: 1828 adds r0, r5, r0 +1001a52c: f7f6 f96f bl 1001080e +1001a530: 9801 ldr r0, [sp, #4] +1001a532: 1945 adds r5, r0, r5 +1001a534: f508 74ac add.w r4, r8, #344 ; 0x158 +1001a538: f8c8 5168 str.w r5, [r8, #360] ; 0x168 +1001a53c: 462a mov r2, r5 +1001a53e: a90a add r1, sp, #40 ; 0x28 +1001a540: 4620 mov r0, r4 +1001a542: f7f6 f964 bl 1001080e +1001a546: f8d8 1168 ldr.w r1, [r8, #360] ; 0x168 +1001a54a: 4620 mov r0, r4 +1001a54c: f00b faa6 bl 10025a9c +1001a550: 2000 movs r0, #0 +1001a552: f8c8 02c0 str.w r0, [r8, #704] ; 0x2c0 +1001a556: f8c8 02c4 str.w r0, [r8, #708] ; 0x2c4 +1001a55a: f8c8 02c8 str.w r0, [r8, #712] ; 0x2c8 +1001a55e: f8c8 02cc str.w r0, [r8, #716] ; 0x2cc +1001a562: f8c8 02d0 str.w r0, [r8, #720] ; 0x2d0 +1001a566: f8c8 02d4 str.w r0, [r8, #724] ; 0x2d4 +1001a56a: 2220 movs r2, #32 +1001a56c: 2100 movs r1, #0 +1001a56e: f208 20d9 addw r0, r8, #729 ; 0x2d9 +1001a572: f7f6 f961 bl 10010838 +1001a576: 9805 ldr r0, [sp, #20] +1001a578: 9905 ldr r1, [sp, #20] +1001a57a: f8d0 013c ldr.w r0, [r0, #316] ; 0x13c +1001a57e: f501 779e add.w r7, r1, #316 ; 0x13c +1001a582: 0781 lsls r1, r0, #30 +1001a584: ad22 add r5, sp, #136 ; 0x88 +1001a586: d53b bpl.n 1001a600 +1001a588: 68ac ldr r4, [r5, #8] +1001a58a: 2c00 cmp r4, #0 +1001a58c: d038 beq.n 1001a600 +1001a58e: f000 fa27 bl 1001a9e0 <.text_40> +1001a592: f895 b00c ldrb.w fp, [r5, #12] +1001a596: aa09 add r2, sp, #36 ; 0x24 +1001a598: f10b 0102 add.w r1, fp, #2 +1001a59c: 1ea0 subs r0, r4, #2 +1001a59e: f7f9 fc67 bl 10013e70 +1001a5a2: 2801 cmp r0, #1 +1001a5a4: d13b bne.n 1001a61e +1001a5a6: f8c8 02c0 str.w r0, [r8, #704] ; 0x2c0 +1001a5aa: f8d8 02c4 ldr.w r0, [r8, #708] ; 0x2c4 +1001a5ae: f040 0002 orr.w r0, r0, #2 +1001a5b2: f8c8 02c4 str.w r0, [r8, #708] ; 0x2c4 +1001a5b6: 68b9 ldr r1, [r7, #8] +1001a5b8: 9809 ldr r0, [sp, #36] ; 0x24 +1001a5ba: 4008 ands r0, r1 +1001a5bc: f8c8 02cc str.w r0, [r8, #716] ; 0x2cc +1001a5c0: 6939 ldr r1, [r7, #16] +1001a5c2: 9802 ldr r0, [sp, #8] +1001a5c4: 4008 ands r0, r1 +1001a5c6: f8c8 02d4 str.w r0, [r8, #724] ; 0x2d4 +1001a5ca: f8d8 12cc ldr.w r1, [r8, #716] ; 0x2cc +1001a5ce: b901 cbnz r1, 1001a5d2 +1001a5d0: 2629 movs r6, #41 ; 0x29 +1001a5d2: 2800 cmp r0, #0 +1001a5d4: d03c beq.n 1001a650 +1001a5d6: 2e00 cmp r6, #0 +1001a5d8: d13b bne.n 1001a652 +1001a5da: f8d8 02bc ldr.w r0, [r8, #700] ; 0x2bc +1001a5de: f420 5040 bic.w r0, r0, #12288 ; 0x3000 +1001a5e2: f8c8 02bc str.w r0, [r8, #700] ; 0x2bc +1001a5e6: 2c00 cmp r4, #0 +1001a5e8: 9906 ldr r1, [sp, #24] +1001a5ea: f501 6688 add.w r6, r1, #1088 ; 0x440 +1001a5ee: d15c bne.n 1001a6aa +1001a5f0: 6a29 ldr r1, [r5, #32] +1001a5f2: 2900 cmp r1, #0 +1001a5f4: bf14 ite ne +1001a5f6: f440 5080 orrne.w r0, r0, #4096 ; 0x1000 +1001a5fa: f440 5000 orreq.w r0, r0, #8192 ; 0x2000 +1001a5fe: e034 b.n 1001a66a +1001a600: 07c0 lsls r0, r0, #31 +1001a602: d52f bpl.n 1001a664 +1001a604: 9c22 ldr r4, [sp, #136] ; 0x88 +1001a606: b36c cbz r4, 1001a664 +1001a608: f000 f9ea bl 1001a9e0 <.text_40> +1001a60c: f895 b004 ldrb.w fp, [r5, #4] +1001a610: aa09 add r2, sp, #36 ; 0x24 +1001a612: f10b 0102 add.w r1, fp, #2 +1001a616: 1ea0 subs r0, r4, #2 +1001a618: f7f9 fc2e bl 10013e78 +1001a61c: 2801 cmp r0, #1 +1001a61e: d148 bne.n 1001a6b2 +1001a620: f8c8 02c0 str.w r0, [r8, #704] ; 0x2c0 +1001a624: f8d8 02c4 ldr.w r0, [r8, #708] ; 0x2c4 +1001a628: f040 0001 orr.w r0, r0, #1 +1001a62c: f8c8 02c4 str.w r0, [r8, #708] ; 0x2c4 +1001a630: 6879 ldr r1, [r7, #4] +1001a632: 9809 ldr r0, [sp, #36] ; 0x24 +1001a634: 4008 ands r0, r1 +1001a636: f8c8 02c8 str.w r0, [r8, #712] ; 0x2c8 +1001a63a: 68f9 ldr r1, [r7, #12] +1001a63c: 9802 ldr r0, [sp, #8] +1001a63e: 4008 ands r0, r1 +1001a640: f8c8 02d0 str.w r0, [r8, #720] ; 0x2d0 +1001a644: f8d8 12c8 ldr.w r1, [r8, #712] ; 0x2c8 +1001a648: b901 cbnz r1, 1001a64c +1001a64a: 2629 movs r6, #41 ; 0x29 +1001a64c: 2800 cmp r0, #0 +1001a64e: d1c2 bne.n 1001a5d6 +1001a650: 262a movs r6, #42 ; 0x2a +1001a652: 2000 movs r0, #0 +1001a654: f1ba 0f00 cmp.w sl, #0 +1001a658: f8c8 00fc str.w r0, [r8, #252] ; 0xfc +1001a65c: bf0c ite eq +1001a65e: 2310 moveq r3, #16 +1001a660: 2330 movne r3, #48 ; 0x30 +1001a662: e19c b.n 1001a99e +1001a664: 2400 movs r4, #0 +1001a666: 46a3 mov fp, r4 +1001a668: e7b7 b.n 1001a5da +1001a66a: f8c8 02bc str.w r0, [r8, #700] ; 0x2bc +1001a66e: 9805 ldr r0, [sp, #20] +1001a670: f8d0 013c ldr.w r0, [r0, #316] ; 0x13c +1001a674: 2800 cmp r0, #0 +1001a676: bf1c itt ne +1001a678: f8d8 02bc ldrne.w r0, [r8, #700] ; 0x2bc +1001a67c: f410 5f40 tstne.w r0, #12288 ; 0x3000 +1001a680: d02d beq.n 1001a6de +1001a682: 6fb0 ldr r0, [r6, #120] ; 0x78 +1001a684: b358 cbz r0, 1001a6de +1001a686: 2000 movs r0, #0 +1001a688: f88d 0008 strb.w r0, [sp, #8] +1001a68c: 9000 str r0, [sp, #0] +1001a68e: ab02 add r3, sp, #8 +1001a690: 9806 ldr r0, [sp, #24] +1001a692: f8d0 14c4 ldr.w r1, [r0, #1220] ; 0x4c4 +1001a696: 6fb0 ldr r0, [r6, #120] ; 0x78 +1001a698: f241 0241 movw r2, #4161 ; 0x1041 +1001a69c: f7ff f988 bl 100199b0 +1001a6a0: f89d 0008 ldrb.w r0, [sp, #8] +1001a6a4: b9d8 cbnz r0, 1001a6de +1001a6a6: 2611 movs r6, #17 +1001a6a8: e7d3 b.n 1001a652 +1001a6aa: 9905 ldr r1, [sp, #20] +1001a6ac: f8d1 113c ldr.w r1, [r1, #316] ; 0x13c +1001a6b0: b909 cbnz r1, 1001a6b6 +1001a6b2: 2628 movs r6, #40 ; 0x28 +1001a6b4: e7cd b.n 1001a652 +1001a6b6: 6a29 ldr r1, [r5, #32] +1001a6b8: b121 cbz r1, 1001a6c4 +1001a6ba: f440 5080 orr.w r0, r0, #4096 ; 0x1000 +1001a6be: f8c8 02bc str.w r0, [r8, #700] ; 0x2bc +1001a6c2: e00c b.n 1001a6de +1001a6c4: f10b 0202 add.w r2, fp, #2 +1001a6c8: 2a21 cmp r2, #33 ; 0x21 +1001a6ca: bf28 it cs +1001a6cc: 2220 movcs r2, #32 +1001a6ce: d201 bcs.n 1001a6d4 +1001a6d0: 2a01 cmp r2, #1 +1001a6d2: db04 blt.n 1001a6de +1001a6d4: 1ea1 subs r1, r4, #2 +1001a6d6: f208 20d9 addw r0, r8, #729 ; 0x2d9 +1001a6da: f7f6 f898 bl 1001080e +1001a6de: f8d8 02bc ldr.w r0, [r8, #700] ; 0x2bc +1001a6e2: f420 7000 bic.w r0, r0, #512 ; 0x200 +1001a6e6: f8c8 02bc str.w r0, [r8, #700] ; 0x2bc +1001a6ea: 2000 movs r0, #0 +1001a6ec: f8c8 0104 str.w r0, [r8, #260] ; 0x104 +1001a6f0: f888 0304 strb.w r0, [r8, #772] ; 0x304 +1001a6f4: 2001 movs r0, #1 +1001a6f6: f888 030a strb.w r0, [r8, #778] ; 0x30a +1001a6fa: 2000 movs r0, #0 +1001a6fc: f888 0309 strb.w r0, [r8, #777] ; 0x309 +1001a700: f888 0308 strb.w r0, [r8, #776] ; 0x308 +1001a704: f888 0307 strb.w r0, [r8, #775] ; 0x307 +1001a708: f888 0306 strb.w r0, [r8, #774] ; 0x306 +1001a70c: 9806 ldr r0, [sp, #24] +1001a70e: f8d0 0440 ldr.w r0, [r0, #1088] ; 0x440 +1001a712: 2800 cmp r0, #0 +1001a714: d054 beq.n 1001a7c0 +1001a716: 9804 ldr r0, [sp, #16] +1001a718: f20f 27b4 addw r7, pc, #692 ; 0x2b4 +1001a71c: 2100 movs r1, #0 +1001a71e: 3018 adds r0, #24 +1001a720: 9101 str r1, [sp, #4] +1001a722: e002 b.n 1001a72a +1001a724: 9801 ldr r0, [sp, #4] +1001a726: 1900 adds r0, r0, r4 +1001a728: 1c80 adds r0, r0, #2 +1001a72a: 9b07 ldr r3, [sp, #28] +1001a72c: aa01 add r2, sp, #4 +1001a72e: 21dd movs r1, #221 ; 0xdd +1001a730: f7f9 fba6 bl 10013e80 +1001a734: 0004 movs r4, r0 +1001a736: d043 beq.n 1001a7c0 +1001a738: 2206 movs r2, #6 +1001a73a: 4639 mov r1, r7 +1001a73c: 1ca0 adds r0, r4, #2 +1001a73e: f7f6 f870 bl 10010822 +1001a742: 2800 cmp r0, #0 +1001a744: d0ee beq.n 1001a724 +1001a746: f8d8 02bc ldr.w r0, [r8, #700] ; 0x2bc +1001a74a: f440 7000 orr.w r0, r0, #512 ; 0x200 +1001a74e: f8c8 02bc str.w r0, [r8, #700] ; 0x2bc +1001a752: 2001 movs r0, #1 +1001a754: f8c8 0104 str.w r0, [r8, #260] ; 0x104 +1001a758: 7a20 ldrb r0, [r4, #8] +1001a75a: f888 0304 strb.w r0, [r8, #772] ; 0x304 +1001a75e: f3c0 1041 ubfx r0, r0, #5, #2 +1001a762: f888 0305 strb.w r0, [r8, #773] ; 0x305 +1001a766: f898 0304 ldrb.w r0, [r8, #772] ; 0x304 +1001a76a: f000 000f and.w r0, r0, #15 +1001a76e: 280f cmp r0, #15 +1001a770: bf14 ite ne +1001a772: 2001 movne r0, #1 +1001a774: 2000 moveq r0, #0 +1001a776: f888 030a strb.w r0, [r8, #778] ; 0x30a +1001a77a: 210f movs r1, #15 +1001a77c: f898 0304 ldrb.w r0, [r8, #772] ; 0x304 +1001a780: 4208 tst r0, r1 +1001a782: d01d beq.n 1001a7c0 +1001a784: 07c0 lsls r0, r0, #31 +1001a786: bf4c ite mi +1001a788: 2003 movmi r0, #3 +1001a78a: 2000 movpl r0, #0 +1001a78c: f888 0309 strb.w r0, [r8, #777] ; 0x309 +1001a790: f898 0304 ldrb.w r0, [r8, #772] ; 0x304 +1001a794: 0780 lsls r0, r0, #30 +1001a796: bf4c ite mi +1001a798: 2003 movmi r0, #3 +1001a79a: 2000 movpl r0, #0 +1001a79c: f888 0308 strb.w r0, [r8, #776] ; 0x308 +1001a7a0: f898 0304 ldrb.w r0, [r8, #772] ; 0x304 +1001a7a4: 0740 lsls r0, r0, #29 +1001a7a6: bf4c ite mi +1001a7a8: 2003 movmi r0, #3 +1001a7aa: 2000 movpl r0, #0 +1001a7ac: f888 0306 strb.w r0, [r8, #774] ; 0x306 +1001a7b0: f898 0304 ldrb.w r0, [r8, #772] ; 0x304 +1001a7b4: 0700 lsls r0, r0, #28 +1001a7b6: bf4c ite mi +1001a7b8: 2003 movmi r0, #3 +1001a7ba: 2000 movpl r0, #0 +1001a7bc: f888 0307 strb.w r0, [r8, #775] ; 0x307 +1001a7c0: f208 2402 addw r4, r8, #514 ; 0x202 +1001a7c4: 221a movs r2, #26 +1001a7c6: f000 f911 bl 1001a9ec <.text_41> +1001a7ca: 6d29 ldr r1, [r5, #80] ; 0x50 +1001a7cc: b189 cbz r1, 1001a7f2 +1001a7ce: f89d 00dc ldrb.w r0, [sp, #220] ; 0xdc +1001a7d2: 281a cmp r0, #26 +1001a7d4: d30d bcc.n 1001a7f2 +1001a7d6: f8d8 02bc ldr.w r0, [r8, #700] ; 0x2bc +1001a7da: f440 6000 orr.w r0, r0, #2048 ; 0x800 +1001a7de: f8c8 02bc str.w r0, [r8, #700] ; 0x2bc +1001a7e2: 221a movs r2, #26 +1001a7e4: f440 7000 orr.w r0, r0, #512 ; 0x200 +1001a7e8: f8c8 02bc str.w r0, [r8, #700] ; 0x2bc +1001a7ec: f001 f9c1 bl 1001bb72 <.text_114> +1001a7f0: e005 b.n 1001a7fe +1001a7f2: f8d8 02bc ldr.w r0, [r8, #700] ; 0x2bc +1001a7f6: f420 6000 bic.w r0, r0, #2048 ; 0x800 +1001a7fa: f8c8 02bc str.w r0, [r8, #700] ; 0x2bc +1001a7fe: 68b0 ldr r0, [r6, #8] +1001a800: b928 cbnz r0, 1001a80e +1001a802: f8d8 02bc ldr.w r0, [r8, #700] ; 0x2bc +1001a806: 0500 lsls r0, r0, #20 +1001a808: d501 bpl.n 1001a80e +1001a80a: 2601 movs r6, #1 +1001a80c: e721 b.n 1001a652 +1001a80e: f8d8 02bc ldr.w r0, [r8, #700] ; 0x2bc +1001a812: f040 4000 orr.w r0, r0, #2147483648 ; 0x80000000 +1001a816: f8c8 02bc str.w r0, [r8, #700] ; 0x2bc +1001a81a: 2000 movs r0, #0 +1001a81c: e000 b.n 1001a820 +1001a81e: 1c40 adds r0, r0, #1 +1001a820: f8d8 1168 ldr.w r1, [r8, #360] ; 0x168 +1001a824: 4288 cmp r0, r1 +1001a826: d20d bcs.n 1001a844 +1001a828: eb00 0108 add.w r1, r0, r8 +1001a82c: f891 1158 ldrb.w r1, [r1, #344] ; 0x158 +1001a830: f001 017f and.w r1, r1, #127 ; 0x7f +1001a834: 2917 cmp r1, #23 +1001a836: dbf2 blt.n 1001a81e +1001a838: f8d8 02bc ldr.w r0, [r8, #700] ; 0x2bc +1001a83c: 0040 lsls r0, r0, #1 +1001a83e: 0840 lsrs r0, r0, #1 +1001a840: f8c8 02bc str.w r0, [r8, #700] ; 0x2bc +1001a844: f898 12b8 ldrb.w r1, [r8, #696] ; 0x2b8 +1001a848: f8d8 02bc ldr.w r0, [r8, #700] ; 0x2bc +1001a84c: 0689 lsls r1, r1, #26 +1001a84e: bf4c ite mi +1001a850: f040 0080 orrmi.w r0, r0, #128 ; 0x80 +1001a854: f020 0080 bicpl.w r0, r0, #128 ; 0x80 +1001a858: f8c8 02bc str.w r0, [r8, #700] ; 0x2bc +1001a85c: f8d8 00fc ldr.w r0, [r8, #252] ; 0xfc +1001a860: b9e8 cbnz r0, 1001a89e +1001a862: 2001 movs r0, #1 +1001a864: e000 b.n 1001a868 +1001a866: 1c40 adds r0, r0, #1 +1001a868: f8c8 00fc str.w r0, [r8, #252] ; 0xfc +1001a86c: f8d8 00fc ldr.w r0, [r8, #252] ; 0xfc +1001a870: 2809 cmp r0, #9 +1001a872: d206 bcs.n 1001a882 +1001a874: 9903 ldr r1, [sp, #12] +1001a876: eb01 0180 add.w r1, r1, r0, lsl #2 +1001a87a: f8d1 109c ldr.w r1, [r1, #156] ; 0x9c +1001a87e: 2900 cmp r1, #0 +1001a880: d1f1 bne.n 1001a866 +1001a882: 9903 ldr r1, [sp, #12] +1001a884: f8b1 10c4 ldrh.w r1, [r1, #196] ; 0xc4 +1001a888: 4281 cmp r1, r0 +1001a88a: d203 bcs.n 1001a894 +1001a88c: 2000 movs r0, #0 +1001a88e: f8c8 00fc str.w r0, [r8, #252] ; 0xfc +1001a892: e708 b.n 1001a6a6 +1001a894: 9903 ldr r1, [sp, #12] +1001a896: eb01 0080 add.w r0, r1, r0, lsl #2 +1001a89a: f8c0 809c str.w r8, [r0, #156] ; 0x9c +1001a89e: a908 add r1, sp, #32 +1001a8a0: f8d8 00f8 ldr.w r0, [r8, #248] ; 0xf8 +1001a8a4: f420 5000 bic.w r0, r0, #8192 ; 0x2000 +1001a8a8: f8c8 00f8 str.w r0, [r8, #248] ; 0xf8 +1001a8ac: f440 4080 orr.w r0, r0, #16384 ; 0x4000 +1001a8b0: f8c8 00f8 str.w r0, [r8, #248] ; 0xf8 +1001a8b4: 9803 ldr r0, [sp, #12] +1001a8b6: f100 0490 add.w r4, r0, #144 ; 0x90 +1001a8ba: 4620 mov r0, r4 +1001a8bc: f7f6 f82a bl 10010914 +1001a8c0: f508 7609 add.w r6, r8, #548 ; 0x224 +1001a8c4: 4630 mov r0, r6 +1001a8c6: f7f5 ffc2 bl 1001084e +1001a8ca: b910 cbnz r0, 1001a8d2 +1001a8cc: 4630 mov r0, r6 +1001a8ce: f7f5 ffc9 bl 10010864 +1001a8d2: a908 add r1, sp, #32 +1001a8d4: 4620 mov r0, r4 +1001a8d6: f7f6 f81e bl 10010916 +1001a8da: 9803 ldr r0, [sp, #12] +1001a8dc: f100 048c add.w r4, r0, #140 ; 0x8c +1001a8e0: a908 add r1, sp, #32 +1001a8e2: 4620 mov r0, r4 +1001a8e4: f7f6 f816 bl 10010914 +1001a8e8: f508 7607 add.w r6, r8, #540 ; 0x21c +1001a8ec: 4630 mov r0, r6 +1001a8ee: f7f5 ffae bl 1001084e +1001a8f2: b150 cbz r0, 1001a90a +1001a8f4: 9803 ldr r0, [sp, #12] +1001a8f6: f8d0 009c ldr.w r0, [r0, #156] ; 0x9c +1001a8fa: f8c8 022c str.w r0, [r8, #556] ; 0x22c +1001a8fe: 9803 ldr r0, [sp, #12] +1001a900: f100 017c add.w r1, r0, #124 ; 0x7c +1001a904: 4630 mov r0, r6 +1001a906: f7f5 ffab bl 10010860 +1001a90a: a908 add r1, sp, #32 +1001a90c: 4620 mov r0, r4 +1001a90e: f7f6 f802 bl 10010916 +1001a912: f8d8 00f8 ldr.w r0, [r8, #248] ; 0xf8 +1001a916: 0440 lsls r0, r0, #17 +1001a918: d53f bpl.n 1001a99a +1001a91a: 4641 mov r1, r8 +1001a91c: 4648 mov r0, r9 +1001a91e: f7fe fcb8 bl 10019292 +1001a922: 4641 mov r1, r8 +1001a924: 4648 mov r0, r9 +1001a926: f7fe fe5d bl 100195e4 +1001a92a: f8d8 20fc ldr.w r2, [r8, #252] ; 0xfc +1001a92e: f508 7184 add.w r1, r8, #264 ; 0x108 +1001a932: 4648 mov r0, r9 +1001a934: f002 fc83 bl 1001d23e +1001a938: f1ba 0f00 cmp.w sl, #0 +1001a93c: bf0c ite eq +1001a93e: 2310 moveq r3, #16 +1001a940: 2330 movne r3, #48 ; 0x30 +1001a942: 4642 mov r2, r8 +1001a944: 2100 movs r1, #0 +1001a946: 4648 mov r0, r9 +1001a948: f000 ffe0 bl 1001b90c +1001a94c: 9806 ldr r0, [sp, #24] +1001a94e: f44f 7180 mov.w r1, #256 ; 0x100 +1001a952: f7ff f842 bl 100199da +1001a956: bb00 cbnz r0, 1001a99a +1001a958: f8d8 02c4 ldr.w r0, [r8, #708] ; 0x2c4 +1001a95c: b1e8 cbz r0, 1001a99a +1001a95e: 9805 ldr r0, [sp, #20] +1001a960: f8d8 10fc ldr.w r1, [r8, #252] ; 0xfc +1001a964: eb00 0081 add.w r0, r0, r1, lsl #2 +1001a968: 4641 mov r1, r8 +1001a96a: f8d0 462c ldr.w r4, [r0, #1580] ; 0x62c +1001a96e: 4648 mov r0, r9 +1001a970: f008 ffbd bl 100238ee +1001a974: f8d8 02c4 ldr.w r0, [r8, #708] ; 0x2c4 +1001a978: 0781 lsls r1, r0, #30 +1001a97a: d503 bpl.n 1001a984 +1001a97c: 2004 movs r0, #4 +1001a97e: 7420 strb r0, [r4, #16] +1001a980: 2002 movs r0, #2 +1001a982: e004 b.n 1001a98e +1001a984: 07c0 lsls r0, r0, #31 +1001a986: d503 bpl.n 1001a990 +1001a988: 2002 movs r0, #2 +1001a98a: 7420 strb r0, [r4, #16] +1001a98c: 2001 movs r0, #1 +1001a98e: 60a0 str r0, [r4, #8] +1001a990: 2200 movs r2, #0 +1001a992: 4641 mov r1, r8 +1001a994: 4648 mov r0, r9 +1001a996: f009 f875 bl 10023a84 +1001a99a: 2001 movs r0, #1 +1001a99c: e005 b.n 1001a9aa +1001a99e: 4642 mov r2, r8 +1001a9a0: 4631 mov r1, r6 +1001a9a2: 4648 mov r0, r9 +1001a9a4: f000 ffb2 bl 1001b90c +1001a9a8: 2000 movs r0, #0 +1001a9aa: b03d add sp, #244 ; 0xf4 +1001a9ac: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1001a9b0 : +1001a9b0: 5452 384c 3931 4135 445b 6972 6576 5d72 RTL8195A[Driver] +1001a9c0: 203a 4f2b 416e 7373 636f 6552 0a71 0000 : +OnAssocReq... + +1001a9d0 : +1001a9d0: 5000 02f2 0100 0000 .P...... + +1001a9d8 <.text_39>: +1001a9d8: 7838 ldrb r0, [r7, #0] +1001a9da: f000 0003 and.w r0, r0, #3 +1001a9de: 4770 bx lr + +1001a9e0 <.text_40>: +1001a9e0: 2000 movs r0, #0 +1001a9e2: 9009 str r0, [sp, #36] ; 0x24 +1001a9e4: 9002 str r0, [sp, #8] +1001a9e6: 9000 str r0, [sp, #0] +1001a9e8: ab02 add r3, sp, #8 +1001a9ea: 4770 bx lr + +1001a9ec <.text_41>: +1001a9ec: 2100 movs r1, #0 +1001a9ee: 4620 mov r0, r4 +1001a9f0: f7f5 bf22 b.w 10010838 + +1001a9f4 : +1001a9f4: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1001a9f8: 468b mov fp, r1 +1001a9fa: 4682 mov sl, r0 +1001a9fc: f8db 7084 ldr.w r7, [fp, #132] ; 0x84 +1001aa00: f8db 007c ldr.w r0, [fp, #124] ; 0x7c +1001aa04: 9000 str r0, [sp, #0] +1001aa06: f50a 649d add.w r4, sl, #1256 ; 0x4e8 +1001aa0a: f504 7688 add.w r6, r4, #272 ; 0x110 +1001aa0e: 4638 mov r0, r7 +1001aa10: f7fe ffd6 bl 100199c0 +1001aa14: 4601 mov r1, r0 +1001aa16: f50a 50c8 add.w r0, sl, #6400 ; 0x1900 +1001aa1a: f7ff fcd3 bl 1001a3c4 <.text_35> +1001aa1e: 2800 cmp r0, #0 +1001aa20: bf1c itt ne +1001aa22: 6830 ldrne r0, [r6, #0] +1001aa24: f410 5f10 tstne.w r0, #9216 ; 0x2400 +1001aa28: d063 beq.n 1001aaf2 +1001aa2a: 0440 lsls r0, r0, #17 +1001aa2c: d461 bmi.n 1001aaf2 +1001aa2e: f504 704a add.w r0, r4, #808 ; 0x328 +1001aa32: f7f6 f809 bl 10010a48 +1001aa36: 8b78 ldrh r0, [r7, #26] +1001aa38: b120 cbz r0, 1001aa44 +1001aa3a: 2000 movs r0, #0 +1001aa3c: 6030 str r0, [r6, #0] +1001aa3e: f06f 0803 mvn.w r8, #3 +1001aa42: e049 b.n 1001aad8 +1001aa44: 8b38 ldrh r0, [r7, #24] +1001aa46: f8df 942c ldr.w r9, [pc, #1068] ; 1001ae74 <.text_66> +1001aa4a: f8a6 00ac strh.w r0, [r6, #172] ; 0xac +1001aa4e: 0540 lsls r0, r0, #21 +1001aa50: bf4c ite mi +1001aa52: 2009 movmi r0, #9 +1001aa54: 2014 movpl r0, #20 +1001aa56: f886 00af strb.w r0, [r6, #175] ; 0xaf +1001aa5a: 241e movs r4, #30 +1001aa5c: 8bb8 ldrh r0, [r7, #28] +1001aa5e: ea4f 4880 mov.w r8, r0, lsl #18 +1001aa62: ea4f 4898 mov.w r8, r8, lsr #18 +1001aa66: f8a6 80a8 strh.w r8, [r6, #168] ; 0xa8 +1001aa6a: e006 b.n 1001aa7a +1001aa6c: 4629 mov r1, r5 +1001aa6e: 4650 mov r0, sl +1001aa70: f00b faf3 bl 1002605a +1001aa74: 7868 ldrb r0, [r5, #1] +1001aa76: 1c80 adds r0, r0, #2 +1001aa78: 1904 adds r4, r0, r4 +1001aa7a: 9800 ldr r0, [sp, #0] +1001aa7c: 4284 cmp r4, r0 +1001aa7e: d21f bcs.n 1001aac0 +1001aa80: 19e5 adds r5, r4, r7 +1001aa82: 7828 ldrb r0, [r5, #0] +1001aa84: 282a cmp r0, #42 ; 0x2a +1001aa86: d0f1 beq.n 1001aa6c +1001aa88: 282d cmp r0, #45 ; 0x2d +1001aa8a: d00f beq.n 1001aaac +1001aa8c: 283d cmp r0, #61 ; 0x3d +1001aa8e: d012 beq.n 1001aab6 +1001aa90: 28dd cmp r0, #221 ; 0xdd +1001aa92: d1ef bne.n 1001aa74 +1001aa94: 2206 movs r2, #6 +1001aa96: 4649 mov r1, r9 +1001aa98: 1ca8 adds r0, r5, #2 +1001aa9a: f7f5 fec2 bl 10010822 +1001aa9e: 2800 cmp r0, #0 +1001aaa0: d0e8 beq.n 1001aa74 +1001aaa2: 4629 mov r1, r5 +1001aaa4: 4650 mov r0, sl +1001aaa6: f00b f96f bl 10025d88 +1001aaaa: e7e3 b.n 1001aa74 +1001aaac: 4629 mov r1, r5 +1001aaae: 4650 mov r0, sl +1001aab0: f00b fa39 bl 10025f26 +1001aab4: e7de b.n 1001aa74 +1001aab6: 4629 mov r1, r5 +1001aab8: 4650 mov r0, sl +1001aaba: f00b fa92 bl 10025fe2 +1001aabe: e7d9 b.n 1001aa74 +1001aac0: 6831 ldr r1, [r6, #0] +1001aac2: 2002 movs r0, #2 +1001aac4: f360 314e bfi r1, r0, #13, #2 +1001aac8: 6031 str r1, [r6, #0] +1001aaca: f001 fa0f bl 1001beec <.text_124> +1001aace: 4641 mov r1, r8 +1001aad0: f20f 0028 addw r0, pc, #40 ; 0x28 +1001aad4: f7f1 fc15 bl 1000c302 +1001aad8: 4641 mov r1, r8 +1001aada: 4650 mov r0, sl +1001aadc: f002 fb16 bl 1001d10c +1001aae0: f641 0079 movw r0, #6265 ; 0x1879 +1001aae4: f810 000a ldrb.w r0, [r0, sl] +1001aae8: b118 cbz r0, 1001aaf2 +1001aaea: 4659 mov r1, fp +1001aaec: 4650 mov r0, sl +1001aaee: f003 fb57 bl 1001e1a0 +1001aaf2: 2001 movs r0, #1 +1001aaf4: e8bd 8ff2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1001aaf8 <.text_43>: +1001aaf8: 10044258 .word 0x10044258 + +1001aafc : +1001aafc: 384c5452 41353931 6972445b 5d726576 RTL8195A[Driver] +1001ab0c: 7361203a 69636f73 6f697461 7573206e : association su +1001ab1c: 73656363 65722873 64253d73 00000a29 ccess(res=%d)... + +1001ab2c : +1001ab2c: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +1001ab30: b085 sub sp, #20 +1001ab32: f000 f9a8 bl 1001ae86 <.text_69> +1001ab36: f000 f8b3 bl 1001aca0 <.text_50> +1001ab3a: 2800 cmp r0, #0 +1001ab3c: d046 beq.n 1001abcc +1001ab3e: f000 f989 bl 1001ae54 <.text_62> +1001ab42: 2801 cmp r0, #1 +1001ab44: d11f bne.n 1001ab86 +1001ab46: f000 f997 bl 1001ae78 <.text_67> +1001ab4a: f000 f897 bl 1001ac7c <.text_48> +1001ab4e: f20f 0080 addw r0, pc, #128 ; 0x80 +1001ab52: f7f1 fbd6 bl 1000c302 +1001ab56: f000 f8ab bl 1001acb0 <.text_52> +1001ab5a: 0005 movs r5, r0 +1001ab5c: d036 beq.n 1001abcc +1001ab5e: f000 f967 bl 1001ae30 <.text_60> +1001ab62: f000 f960 bl 1001ae26 <.text_59> +1001ab66: b928 cbnz r0, 1001ab74 +1001ab68: 4640 mov r0, r8 +1001ab6a: f7f5 fe7b bl 10010864 +1001ab6e: f000 f94f bl 1001ae10 <.text_57> +1001ab72: 4606 mov r6, r0 +1001ab74: a904 add r1, sp, #16 +1001ab76: 4638 mov r0, r7 +1001ab78: f7f5 fecd bl 10010916 +1001ab7c: 4631 mov r1, r6 +1001ab7e: 4620 mov r0, r4 +1001ab80: f7fe fb64 bl 1001924c +1001ab84: e022 b.n 1001abcc +1001ab86: f000 f97b bl 1001ae80 <.text_68> +1001ab8a: f000 f957 bl 1001ae3c <.text_61> +1001ab8e: f20f 0094 addw r0, pc, #148 ; 0x94 +1001ab92: f7f1 fbb6 bl 1000c302 +1001ab96: f000 f87e bl 1001ac96 <.text_49> +1001ab9a: f000 f97f bl 1001ae9c <.text_70> +1001ab9e: b188 cbz r0, 1001abc4 +1001aba0: f899 035c ldrb.w r0, [r9, #860] ; 0x35c +1001aba4: 1c40 adds r0, r0, #1 +1001aba6: f889 035c strb.w r0, [r9, #860] ; 0x35c +1001abaa: b2c0 uxtb r0, r0 +1001abac: 2803 cmp r0, #3 +1001abae: da04 bge.n 1001abba +1001abb0: 5d28 ldrb r0, [r5, r4] +1001abb2: b910 cbnz r0, 1001abba +1001abb4: f000 f931 bl 1001ae1a <.text_58> +1001abb8: e004 b.n 1001abc4 +1001abba: 2000 movs r0, #0 +1001abbc: f889 035c strb.w r0, [r9, #860] ; 0x35c +1001abc0: f000 f94f bl 1001ae62 <.text_63> +1001abc4: 5d28 ldrb r0, [r5, r4] +1001abc6: b108 cbz r0, 1001abcc +1001abc8: f000 f970 bl 1001aeac <.text_71> +1001abcc: e0c4 b.n 1001ad58 <.text_54> + ... + +1001abd0 : +1001abd0: 5452 384c 3931 4135 445b 6972 6576 5d72 RTL8195A[Driver] +1001abe0: 203a 7061 7220 6365 2076 6564 7561 6874 : ap recv deauth +1001abf0: 7220 6165 6f73 206e 6f63 6564 2528 2964 reason code(%d) +1001ac00: 7320 6174 253a 3230 3a78 3025 7832 253a sta:%02x:%02x:% +1001ac10: 3230 3a78 3025 7832 253a 3230 3a78 3025 02x:%02x:%02x:%0 +1001ac20: 7832 000a 2x.. + +1001ac24 : +1001ac24: 5452 384c 3931 4135 445b 6972 6576 5d72 RTL8195A[Driver] +1001ac34: 203a 7473 2061 6572 7663 6420 6165 7475 : sta recv deaut +1001ac44: 2068 6572 7361 6e6f 6320 646f 2865 6425 h reason code(%d +1001ac54: 2029 7473 3a61 3025 7832 253a 3230 3a78 ) sta:%02x:%02x: +1001ac64: 3025 7832 253a 3230 3a78 3025 7832 253a %02x:%02x:%02x:% +1001ac74: 3230 0a78 0000 0000 02x..... + +1001ac7c <.text_48>: +1001ac7c: 350a adds r5, #10 +1001ac7e: 4659 mov r1, fp +1001ac80: 7968 ldrb r0, [r5, #5] +1001ac82: 9003 str r0, [sp, #12] +1001ac84: 7928 ldrb r0, [r5, #4] +1001ac86: 9002 str r0, [sp, #8] +1001ac88: 78e8 ldrb r0, [r5, #3] +1001ac8a: 9001 str r0, [sp, #4] +1001ac8c: 78a8 ldrb r0, [r5, #2] +1001ac8e: 9000 str r0, [sp, #0] +1001ac90: 786b ldrb r3, [r5, #1] +1001ac92: 782a ldrb r2, [r5, #0] +1001ac94: 4770 bx lr + +1001ac96 <.text_49>: +1001ac96: 465a mov r2, fp +1001ac98: 4639 mov r1, r7 +1001ac9a: 4620 mov r0, r4 +1001ac9c: f001 bfb2 b.w 1001cc04 + +1001aca0 <.text_50>: +1001aca0: 4635 mov r5, r6 +1001aca2: f105 0710 add.w r7, r5, #16 +1001aca6: 4601 mov r1, r0 +1001aca8: 2206 movs r2, #6 + +1001acaa <.text_51>: +1001acaa: 4638 mov r0, r7 +1001acac: f7f5 bdb9 b.w 10010822 + +1001acb0 <.text_52>: +1001acb0: 4629 mov r1, r5 +1001acb2: 4638 mov r0, r7 +1001acb4: f00a ba7a b.w 100251ac + +1001acb8 : +1001acb8: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +1001acbc: b085 sub sp, #20 +1001acbe: f000 f8e2 bl 1001ae86 <.text_69> +1001acc2: f7ff ffed bl 1001aca0 <.text_50> +1001acc6: 2800 cmp r0, #0 +1001acc8: d046 beq.n 1001ad58 <.text_54> +1001acca: f000 f8c3 bl 1001ae54 <.text_62> +1001acce: 2801 cmp r0, #1 +1001acd0: d11f bne.n 1001ad12 +1001acd2: f000 f8d1 bl 1001ae78 <.text_67> +1001acd6: f7ff ffd1 bl 1001ac7c <.text_48> +1001acda: f20f 0084 addw r0, pc, #132 ; 0x84 +1001acde: f7f1 fb10 bl 1000c302 +1001ace2: f7ff ffe5 bl 1001acb0 <.text_52> +1001ace6: 0005 movs r5, r0 +1001ace8: d036 beq.n 1001ad58 <.text_54> +1001acea: f000 f8a1 bl 1001ae30 <.text_60> +1001acee: f000 f89a bl 1001ae26 <.text_59> +1001acf2: b928 cbnz r0, 1001ad00 +1001acf4: 4640 mov r0, r8 +1001acf6: f7f5 fdb5 bl 10010864 +1001acfa: f000 f889 bl 1001ae10 <.text_57> +1001acfe: 4606 mov r6, r0 +1001ad00: a904 add r1, sp, #16 +1001ad02: 4638 mov r0, r7 +1001ad04: f7f5 fe07 bl 10010916 +1001ad08: 4631 mov r1, r6 +1001ad0a: 4620 mov r0, r4 +1001ad0c: f7fe fa9e bl 1001924c +1001ad10: e022 b.n 1001ad58 <.text_54> +1001ad12: f000 f8b5 bl 1001ae80 <.text_68> +1001ad16: f000 f891 bl 1001ae3c <.text_61> +1001ad1a: f20f 009c addw r0, pc, #156 ; 0x9c +1001ad1e: f7f1 faf0 bl 1000c302 +1001ad22: f7ff ffb8 bl 1001ac96 <.text_49> +1001ad26: f000 f8b9 bl 1001ae9c <.text_70> +1001ad2a: b188 cbz r0, 1001ad50 +1001ad2c: f899 035d ldrb.w r0, [r9, #861] ; 0x35d +1001ad30: 1c40 adds r0, r0, #1 +1001ad32: f889 035d strb.w r0, [r9, #861] ; 0x35d +1001ad36: b2c0 uxtb r0, r0 +1001ad38: 2803 cmp r0, #3 +1001ad3a: da04 bge.n 1001ad46 +1001ad3c: 5d28 ldrb r0, [r5, r4] +1001ad3e: b910 cbnz r0, 1001ad46 +1001ad40: f000 f86b bl 1001ae1a <.text_58> +1001ad44: e004 b.n 1001ad50 +1001ad46: 2000 movs r0, #0 +1001ad48: f889 035d strb.w r0, [r9, #861] ; 0x35d +1001ad4c: f000 f889 bl 1001ae62 <.text_63> +1001ad50: 5d28 ldrb r0, [r5, r4] +1001ad52: b108 cbz r0, 1001ad58 <.text_54> +1001ad54: f000 f8aa bl 1001aeac <.text_71> + +1001ad58 <.text_54>: +1001ad58: 2001 movs r0, #1 +1001ad5a: b005 add sp, #20 +1001ad5c: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1001ad60 : +1001ad60: 5452 384c 3931 4135 445b 6972 6576 5d72 RTL8195A[Driver] +1001ad70: 203a 7061 7220 6365 2076 6964 6173 7373 : ap recv disass +1001ad80: 636f 7220 6165 6f73 206e 6f63 6564 2528 oc reason code(% +1001ad90: 2964 7320 6174 253a 3230 3a78 3025 7832 d) sta:%02x:%02x +1001ada0: 253a 3230 3a78 3025 7832 253a 3230 3a78 :%02x:%02x:%02x: +1001adb0: 3025 7832 000a 0000 %02x.... + +1001adb8 : +1001adb8: 5452 384c 3931 4135 445b 6972 6576 5d72 RTL8195A[Driver] +1001adc8: 203a 7473 2061 6572 7663 6420 7369 7361 : sta recv disas +1001add8: 6f73 2063 6572 7361 6e6f 6320 646f 2865 soc reason code( +1001ade8: 6425 2029 7473 3a61 3025 7832 253a 3230 %d) sta:%02x:%02 +1001adf8: 3a78 3025 7832 253a 3230 3a78 3025 7832 x:%02x:%02x:%02x +1001ae08: 253a 3230 0a78 0000 :%02x... + +1001ae10 <.text_57>: +1001ae10: 2203 movs r2, #3 +1001ae12: 4629 mov r1, r5 +1001ae14: 4620 mov r0, r4 +1001ae16: f7fe bb5a b.w 100194ce + +1001ae1a <.text_58>: +1001ae1a: f241 3188 movw r1, #5000 ; 0x1388 +1001ae1e: f509 7053 add.w r0, r9, #844 ; 0x34c +1001ae22: f7f5 be0a b.w 10010a3a + +1001ae26 <.text_59>: +1001ae26: f505 7807 add.w r8, r5, #540 ; 0x21c +1001ae2a: 4640 mov r0, r8 +1001ae2c: f7f5 bd0f b.w 1001084e + +1001ae30 <.text_60>: +1001ae30: 378c adds r7, #140 ; 0x8c +1001ae32: 2600 movs r6, #0 +1001ae34: a904 add r1, sp, #16 +1001ae36: 4638 mov r0, r7 +1001ae38: f7f5 bd6c b.w 10010914 + +1001ae3c <.text_61>: +1001ae3c: 7978 ldrb r0, [r7, #5] +1001ae3e: 9003 str r0, [sp, #12] +1001ae40: 4659 mov r1, fp +1001ae42: 7938 ldrb r0, [r7, #4] +1001ae44: 9002 str r0, [sp, #8] +1001ae46: 78f8 ldrb r0, [r7, #3] +1001ae48: 9001 str r0, [sp, #4] +1001ae4a: 78b8 ldrb r0, [r7, #2] +1001ae4c: 9000 str r0, [sp, #0] +1001ae4e: 787b ldrb r3, [r7, #1] +1001ae50: 783a ldrb r2, [r7, #0] +1001ae52: 4770 bx lr + +1001ae54 <.text_62>: +1001ae54: f8b6 b018 ldrh.w fp, [r6, #24] +1001ae58: a605 add r6, pc, #20 ; (adr r6, 1001ae70 <.text_65>) +1001ae5a: 2110 movs r1, #16 +1001ae5c: 4650 mov r0, sl +1001ae5e: f7fe bdbc b.w 100199da + +1001ae62 <.text_63>: +1001ae62: 4620 mov r0, r4 +1001ae64: f8df 1cc8 ldr.w r1, [pc, #3272] ; 1001bb30 <.text_108> +1001ae68: f7f9 b81e b.w 10013ea8 + +1001ae6c <.text_64>: +1001ae6c: 10046ea8 .word 0x10046ea8 + +1001ae70 <.text_65>: +1001ae70: 00000d0a .word 0x00000d0a + +1001ae74 <.text_66>: +1001ae74: 1001bb34 .word 0x1001bb34 + +1001ae78 <.text_67>: +1001ae78: f504 5088 add.w r0, r4, #4352 ; 0x1100 +1001ae7c: f100 0728 add.w r7, r0, #40 ; 0x28 + +1001ae80 <.text_68>: +1001ae80: 4630 mov r0, r6 +1001ae82: f7f1 ba3e b.w 1000c302 + +1001ae86 <.text_69>: +1001ae86: 4604 mov r4, r0 +1001ae88: f104 0a0c add.w sl, r4, #12 +1001ae8c: f8d1 6084 ldr.w r6, [r1, #132] ; 0x84 +1001ae90: f504 699d add.w r9, r4, #1256 ; 0x4e8 +1001ae94: f10a 008c add.w r0, sl, #140 ; 0x8c +1001ae98: f00a bea7 b.w 10025bea + +1001ae9c <.text_70>: +1001ae9c: 2000 movs r0, #0 +1001ae9e: f88a 047c strb.w r0, [sl, #1148] ; 0x47c +1001aea2: f641 0579 movw r5, #6265 ; 0x1879 +1001aea6: f899 03e4 ldrb.w r0, [r9, #996] ; 0x3e4 +1001aeaa: 4770 bx lr + +1001aeac <.text_71>: +1001aeac: 2200 movs r2, #0 +1001aeae: 2300 movs r3, #0 +1001aeb0: 4611 mov r1, r2 +1001aeb2: 200a movs r0, #10 +1001aeb4: f014 bfaa b.w 1002fe0c + +1001aeb8 : +1001aeb8: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1001aebc: 4604 mov r4, r0 +1001aebe: f504 5088 add.w r0, r4, #4352 ; 0x1100 +1001aec2: f8d1 7084 ldr.w r7, [r1, #132] ; 0x84 +1001aec6: f100 0828 add.w r8, r0, #40 ; 0x28 +1001aeca: f504 50c8 add.w r0, r4, #6400 ; 0x1900 +1001aece: f504 65bf add.w r5, r4, #1528 ; 0x5f8 +1001aed2: 2206 movs r2, #6 +1001aed4: 1d39 adds r1, r7, #4 +1001aed6: f7ff fa76 bl 1001a3c6 <.text_35+0x2> +1001aeda: 2800 cmp r0, #0 +1001aedc: d058 beq.n 1001af90 +1001aede: 6828 ldr r0, [r5, #0] +1001aee0: f000 0103 and.w r1, r0, #3 +1001aee4: 2903 cmp r1, #3 +1001aee6: d001 beq.n 1001aeec +1001aee8: 0440 lsls r0, r0, #17 +1001aeea: d551 bpl.n 1001af90 +1001aeec: f107 060a add.w r6, r7, #10 +1001aef0: 4631 mov r1, r6 +1001aef2: 4640 mov r0, r8 +1001aef4: f00a f95a bl 100251ac +1001aef8: 2800 cmp r0, #0 +1001aefa: d049 beq.n 1001af90 +1001aefc: f107 0118 add.w r1, r7, #24 +1001af00: 780a ldrb r2, [r1, #0] +1001af02: 2a03 cmp r2, #3 +1001af04: d144 bne.n 1001af90 +1001af06: f895 20b4 ldrb.w r2, [r5, #180] ; 0xb4 +1001af0a: 2a00 cmp r2, #0 +1001af0c: d040 beq.n 1001af90 +1001af0e: 784f ldrb r7, [r1, #1] +1001af10: f200 12ff addw r2, r0, #511 ; 0x1ff +1001af14: 2301 movs r3, #1 +1001af16: b11f cbz r7, 1001af20 +1001af18: 2f02 cmp r7, #2 +1001af1a: d026 beq.n 1001af6a +1001af1c: d30d bcc.n 1001af3a +1001af1e: e037 b.n 1001af90 +1001af20: 2207 movs r2, #7 +1001af22: 1c89 adds r1, r1, #2 +1001af24: f105 00c1 add.w r0, r5, #193 ; 0xc1 +1001af28: f7f5 fc71 bl 1001080e +1001af2c: 2325 movs r3, #37 ; 0x25 +1001af2e: 2201 movs r2, #1 +1001af30: 4631 mov r1, r6 +1001af32: 4620 mov r0, r4 +1001af34: f001 f94f bl 1001c1d6 +1001af38: e02a b.n 1001af90 +1001af3a: 794c ldrb r4, [r1, #5] +1001af3c: 790e ldrb r6, [r1, #4] +1001af3e: f890 51ff ldrb.w r5, [r0, #511] ; 0x1ff +1001af42: 78c9 ldrb r1, [r1, #3] +1001af44: f3c4 0482 ubfx r4, r4, #2, #3 +1001af48: 40a3 lsls r3, r4 +1001af4a: 43dc mvns r4, r3 +1001af4c: ea51 2106 orrs.w r1, r1, r6, lsl #8 +1001af50: d106 bne.n 1001af60 +1001af52: ea43 0105 orr.w r1, r3, r5 +1001af56: f880 11ff strb.w r1, [r0, #511] ; 0x1ff +1001af5a: 7850 ldrb r0, [r2, #1] +1001af5c: 4020 ands r0, r4 +1001af5e: e016 b.n 1001af8e +1001af60: ea04 0105 and.w r1, r4, r5 +1001af64: f880 11ff strb.w r1, [r0, #511] ; 0x1ff +1001af68: e012 b.n 1001af90 +1001af6a: 78cc ldrb r4, [r1, #3] +1001af6c: 0725 lsls r5, r4, #28 +1001af6e: d40f bmi.n 1001af90 +1001af70: f890 51ff ldrb.w r5, [r0, #511] ; 0x1ff +1001af74: 0924 lsrs r4, r4, #4 +1001af76: fa03 f404 lsl.w r4, r3, r4 +1001af7a: ea25 0404 bic.w r4, r5, r4 +1001af7e: f880 41ff strb.w r4, [r0, #511] ; 0x1ff +1001af82: 78c9 ldrb r1, [r1, #3] +1001af84: 7850 ldrb r0, [r2, #1] +1001af86: 0909 lsrs r1, r1, #4 +1001af88: fa03 f101 lsl.w r1, r3, r1 +1001af8c: 4388 bics r0, r1 +1001af8e: 7050 strb r0, [r2, #1] +1001af90: 2001 movs r0, #1 +1001af92: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +1001af96 : +1001af96: b580 push {r7, lr} +1001af98: f8d1 2084 ldr.w r2, [r1, #132] ; 0x84 +1001af9c: 7e12 ldrb r2, [r2, #24] +1001af9e: 2a03 cmp r2, #3 +1001afa0: bf08 it eq +1001afa2: f7ff ff89 bleq 1001aeb8 +1001afa6: 2001 movs r0, #1 +1001afa8: bd02 pop {r1, pc} + +1001afaa : +1001afaa: 2001 movs r0, #1 +1001afac: 4770 bx lr + +1001afae : +1001afae: b538 push {r3, r4, r5, lr} +1001afb0: 4604 mov r4, r0 +1001afb2: f011 fb04 bl 1002c5be +1001afb6: 0005 movs r5, r0 +1001afb8: d007 beq.n 1001afca +1001afba: 4620 mov r0, r4 +1001afbc: f011 fa4b bl 1002c456 +1001afc0: b928 cbnz r0, 1001afce +1001afc2: 4629 mov r1, r5 +1001afc4: 4620 mov r0, r4 +1001afc6: f011 fb27 bl 1002c618 +1001afca: 2000 movs r0, #0 +1001afcc: bd32 pop {r1, r4, r5, pc} +1001afce: 2103 movs r1, #3 +1001afd0: 67a9 str r1, [r5, #120] ; 0x78 +1001afd2: f8c5 0084 str.w r0, [r5, #132] ; 0x84 +1001afd6: 6901 ldr r1, [r0, #16] +1001afd8: f8c5 1080 str.w r1, [r5, #128] ; 0x80 +1001afdc: 6145 str r5, [r0, #20] +1001afde: 4628 mov r0, r5 +1001afe0: bd32 pop {r1, r4, r5, pc} + +1001afe2 : +1001afe2: f880 181f strb.w r1, [r0, #2079] ; 0x81f +1001afe6: 4770 bx lr + +1001afe8 : +1001afe8: b538 push {r3, r4, r5, lr} +1001afea: 460c mov r4, r1 +1001afec: f500 659d add.w r5, r0, #1256 ; 0x4e8 +1001aff0: 226c movs r2, #108 ; 0x6c +1001aff2: f7ff fcfb bl 1001a9ec <.text_41> +1001aff6: 1ca0 adds r0, r4, #2 +1001aff8: 2118 movs r1, #24 +1001affa: 8101 strh r1, [r0, #8] +1001affc: 2200 movs r2, #0 +1001affe: 2107 movs r1, #7 +1001b000: f884 1039 strb.w r1, [r4, #57] ; 0x39 +1001b004: 2312 movs r3, #18 +1001b006: f104 0139 add.w r1, r4, #57 ; 0x39 +1001b00a: 708a strb r2, [r1, #2] +1001b00c: f104 0259 add.w r2, r4, #89 ; 0x59 +1001b010: 71d3 strb r3, [r2, #7] +1001b012: 2300 movs r3, #0 +1001b014: 60e3 str r3, [r4, #12] +1001b016: 7c6b ldrb r3, [r5, #17] +1001b018: 07db lsls r3, r3, #31 +1001b01a: bf4c ite mi +1001b01c: 2306 movmi r3, #6 +1001b01e: 2305 movpl r3, #5 +1001b020: 77cb strb r3, [r1, #31] +1001b022: 2300 movs r3, #0 +1001b024: 7523 strb r3, [r4, #20] +1001b026: 70a3 strb r3, [r4, #2] +1001b028: 774b strb r3, [r1, #29] +1001b02a: 778b strb r3, [r1, #30] +1001b02c: f884 3059 strb.w r3, [r4, #89] ; 0x59 +1001b030: 7053 strb r3, [r2, #1] +1001b032: 7093 strb r3, [r2, #2] +1001b034: 89a9 ldrh r1, [r5, #12] +1001b036: 8081 strh r1, [r0, #4] +1001b038: 2001 movs r0, #1 +1001b03a: 72d0 strb r0, [r2, #11] +1001b03c: bd31 pop {r0, r4, r5, pc} + +1001b03e : +1001b03e: f641 429c movw r2, #7324 ; 0x1c9c +1001b042: 1813 adds r3, r2, r0 +1001b044: 685b ldr r3, [r3, #4] +1001b046: 2b01 cmp r3, #1 +1001b048: d004 beq.n 1001b054 +1001b04a: 5812 ldr r2, [r2, r0] +1001b04c: 2a01 cmp r2, #1 +1001b04e: bf18 it ne +1001b050: f011 bedd bne.w 1002ce0e +1001b054: 4770 bx lr + +1001b056 : +1001b056: b5f8 push {r3, r4, r5, r6, r7, lr} +1001b058: 460d mov r5, r1 +1001b05a: 4616 mov r6, r2 +1001b05c: 4604 mov r4, r0 +1001b05e: 2700 movs r7, #0 +1001b060: 462b mov r3, r5 +1001b062: aa00 add r2, sp, #0 +1001b064: 2100 movs r1, #0 +1001b066: f7f8 ff0b bl 10013e80 +1001b06a: 2800 cmp r0, #0 +1001b06c: bf1c itt ne +1001b06e: 9900 ldrne r1, [sp, #0] +1001b070: 2900 cmpne r1, #0 +1001b072: d013 beq.n 1001b09c +1001b074: 2e01 cmp r6, #1 +1001b076: d007 beq.n 1001b088 +1001b078: 2e02 cmp r6, #2 +1001b07a: bf01 itttt eq +1001b07c: 460a moveq r2, r1 +1001b07e: 2100 moveq r1, #0 +1001b080: 1c80 addeq r0, r0, #2 +1001b082: f7f5 fbd9 bleq 10010838 +1001b086: e009 b.n 1001b09c +1001b088: 1809 adds r1, r1, r0 +1001b08a: 1c89 adds r1, r1, #2 +1001b08c: 7047 strb r7, [r0, #1] +1001b08e: 1a6a subs r2, r5, r1 +1001b090: 18a2 adds r2, r4, r2 +1001b092: 1c80 adds r0, r0, #2 +1001b094: f7f5 fbbb bl 1001080e +1001b098: 9800 ldr r0, [sp, #0] +1001b09a: 4247 negs r7, r0 +1001b09c: 4638 mov r0, r7 +1001b09e: bdf2 pop {r1, r4, r5, r6, r7, pc} + +1001b0a0 : +1001b0a0: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +1001b0a4: b087 sub sp, #28 +1001b0a6: 4680 mov r8, r0 +1001b0a8: f508 609d add.w r0, r8, #1256 ; 0x4e8 +1001b0ac: 9003 str r0, [sp, #12] +1001b0ae: f108 090c add.w r9, r8, #12 +1001b0b2: f20f 11fc addw r1, pc, #508 ; 0x1fc +1001b0b6: f500 7b88 add.w fp, r0, #272 ; 0x110 +1001b0ba: c90c ldmia r1!, {r2, r3} +1001b0bc: a805 add r0, sp, #20 +1001b0be: f109 058c add.w r5, r9, #140 ; 0x8c +1001b0c2: f000 fb13 bl 1001b6ec <.text_97> +1001b0c6: ea5f 0a00 movs.w sl, r0 +1001b0ca: f000 80ed beq.w 1001b2a8 <.text_83> +1001b0ce: a904 add r1, sp, #16 +1001b0d0: f509 609a add.w r0, r9, #1232 ; 0x4d0 +1001b0d4: f7f5 fc1e bl 10010914 +1001b0d8: f10a 0708 add.w r7, sl, #8 +1001b0dc: 4639 mov r1, r7 +1001b0de: f000 fc0c bl 1001b8fa <.text_105+0x6> +1001b0e2: 2010 movs r0, #16 +1001b0e4: f887 0060 strb.w r0, [r7, #96] ; 0x60 +1001b0e8: 2268 movs r2, #104 ; 0x68 +1001b0ea: f8da 0080 ldr.w r0, [sl, #128] ; 0x80 +1001b0ee: f000 ff12 bl 1001bf16 <.text_130+0x6> +1001b0f2: f8da 0080 ldr.w r0, [sl, #128] ; 0x80 +1001b0f6: f000 fd27 bl 1001bb48 <.text_111> +1001b0fa: a905 add r1, sp, #20 +1001b0fc: 1d20 adds r0, r4, #4 +1001b0fe: f7f5 fb86 bl 1001080e +1001b102: f000 f8dd bl 1001b2c0 <.text_86> +1001b106: 4628 mov r0, r5 +1001b108: f00a fd6f bl 10025bea +1001b10c: f000 fbf8 bl 1001b900 <.text_106> +1001b110: f104 0016 add.w r0, r4, #22 +1001b114: f104 0618 add.w r6, r4, #24 +1001b118: 7801 ldrb r1, [r0, #0] +1001b11a: f001 010f and.w r1, r1, #15 +1001b11e: 8001 strh r1, [r0, #0] +1001b120: f64f 7103 movw r1, #65283 ; 0xff03 +1001b124: 8820 ldrh r0, [r4, #0] +1001b126: 4008 ands r0, r1 +1001b128: 8020 strh r0, [r4, #0] +1001b12a: f040 0080 orr.w r0, r0, #128 ; 0x80 +1001b12e: 8020 strh r0, [r4, #0] +1001b130: f107 040c add.w r4, r7, #12 +1001b134: 2018 movs r0, #24 +1001b136: 60f8 str r0, [r7, #12] +1001b138: f89b 0000 ldrb.w r0, [fp] +1001b13c: f000 f8bc bl 1001b2b8 <.text_85> +1001b140: d159 bne.n 1001b1f6 +1001b142: 6faa ldr r2, [r5, #120] ; 0x78 +1001b144: f105 017c add.w r1, r5, #124 ; 0x7c +1001b148: f002 f876 bl 1001d238 <.text_182+0x4> +1001b14c: 6fa8 ldr r0, [r5, #120] ; 0x78 +1001b14e: f89b 20c0 ldrb.w r2, [fp, #192] ; 0xc0 +1001b152: f1a0 010c sub.w r1, r0, #12 +1001b156: f106 000c add.w r0, r6, #12 +1001b15a: f7ff ff7c bl 1001b056 +1001b15e: 6fa9 ldr r1, [r5, #120] ; 0x78 +1001b160: 1842 adds r2, r0, r1 +1001b162: eb02 0b06 add.w fp, r2, r6 +1001b166: 68fa ldr r2, [r7, #12] +1001b168: 1840 adds r0, r0, r1 +1001b16a: 1880 adds r0, r0, r2 +1001b16c: 60f8 str r0, [r7, #12] +1001b16e: ab02 add r3, sp, #8 +1001b170: 2000 movs r0, #0 +1001b172: f88d 0004 strb.w r0, [sp, #4] +1001b176: 2200 movs r2, #0 +1001b178: 68f8 ldr r0, [r7, #12] +1001b17a: f1a0 0124 sub.w r1, r0, #36 ; 0x24 +1001b17e: f8da 0080 ldr.w r0, [sl, #128] ; 0x80 +1001b182: 304c adds r0, #76 ; 0x4c +1001b184: f7fd f910 bl 100183a8 +1001b188: 2800 cmp r0, #0 +1001b18a: bf1c itt ne +1001b18c: 9902 ldrne r1, [sp, #8] +1001b18e: 2900 cmpne r1, #0 +1001b190: d007 beq.n 1001b1a2 +1001b192: 2100 movs r1, #0 +1001b194: 9100 str r1, [sp, #0] +1001b196: ab01 add r3, sp, #4 +1001b198: 9902 ldr r1, [sp, #8] +1001b19a: f241 0241 movw r2, #4161 ; 0x1041 +1001b19e: f7fe fc07 bl 100199b0 +1001b1a2: f89d 1004 ldrb.w r1, [sp, #4] +1001b1a6: f8d9 0004 ldr.w r0, [r9, #4] +1001b1aa: 2900 cmp r1, #0 +1001b1ac: bf14 ite ne +1001b1ae: f440 7080 orrne.w r0, r0, #256 ; 0x100 +1001b1b2: f420 7080 biceq.w r0, r0, #256 ; 0x100 +1001b1b6: f8c9 0004 str.w r0, [r9, #4] +1001b1ba: 9803 ldr r0, [sp, #12] +1001b1bc: f500 757a add.w r5, r0, #1000 ; 0x3e8 +1001b1c0: 7928 ldrb r0, [r5, #4] +1001b1c2: 2800 cmp r0, #0 +1001b1c4: d058 beq.n 1001b278 +1001b1c6: 2600 movs r6, #0 +1001b1c8: 7928 ldrb r0, [r5, #4] +1001b1ca: 42b0 cmp r0, r6 +1001b1cc: db54 blt.n 1001b278 +1001b1ce: 9803 ldr r0, [sp, #12] +1001b1d0: f8d0 03e8 ldr.w r0, [r0, #1000] ; 0x3e8 +1001b1d4: eb00 01c6 add.w r1, r0, r6, lsl #3 +1001b1d8: 7909 ldrb r1, [r1, #4] +1001b1da: 0749 lsls r1, r1, #29 +1001b1dc: d509 bpl.n 1001b1f2 +1001b1de: f850 0036 ldr.w r0, [r0, r6, lsl #3] +1001b1e2: 9400 str r4, [sp, #0] +1001b1e4: 7842 ldrb r2, [r0, #1] +1001b1e6: 7801 ldrb r1, [r0, #0] +1001b1e8: 1c83 adds r3, r0, #2 +1001b1ea: 4658 mov r0, fp +1001b1ec: f7fd f8c8 bl 10018380 +1001b1f0: 4683 mov fp, r0 +1001b1f2: 1c76 adds r6, r6, #1 +1001b1f4: e7e8 b.n 1001b1c8 +1001b1f6: 2020 movs r0, #32 +1001b1f8: 60f8 str r0, [r7, #12] +1001b1fa: 3608 adds r6, #8 +1001b1fc: f000 f99a bl 1001b534 <.text_90> +1001b200: f002 f818 bl 1001d234 <.text_182> +1001b204: f000 f99f bl 1001b546 <.text_92> +1001b208: f002 f814 bl 1001d234 <.text_182> +1001b20c: 68f8 ldr r0, [r7, #12] +1001b20e: 1c80 adds r0, r0, #2 +1001b210: 60f8 str r0, [r7, #12] +1001b212: 9400 str r4, [sp, #0] +1001b214: f105 0310 add.w r3, r5, #16 +1001b218: 68ea ldr r2, [r5, #12] +1001b21a: 2100 movs r1, #0 +1001b21c: 1cb0 adds r0, r6, #2 +1001b21e: f7fd f8af bl 10018380 +1001b222: 4683 mov fp, r0 +1001b224: f105 0064 add.w r0, r5, #100 ; 0x64 +1001b228: f7fd f8b2 bl 10018390 +1001b22c: 4606 mov r6, r0 +1001b22e: 2e09 cmp r6, #9 +1001b230: bf2c ite cs +1001b232: 2208 movcs r2, #8 +1001b234: 4632 movcc r2, r6 +1001b236: 9400 str r4, [sp, #0] +1001b238: f105 0364 add.w r3, r5, #100 ; 0x64 +1001b23c: 2101 movs r1, #1 +1001b23e: 4658 mov r0, fp +1001b240: f7fd f89e bl 10018380 +1001b244: 9400 str r4, [sp, #0] +1001b246: f000 f96f bl 1001b528 <.text_89> +1001b24a: 2100 movs r1, #0 +1001b24c: f88d 1004 strb.w r1, [sp, #4] +1001b250: 9102 str r1, [sp, #8] +1001b252: 9400 str r4, [sp, #0] +1001b254: ab02 add r3, sp, #8 +1001b256: 2202 movs r2, #2 +1001b258: 2106 movs r1, #6 +1001b25a: f7fd f891 bl 10018380 +1001b25e: 9400 str r4, [sp, #0] +1001b260: ab01 add r3, sp, #4 +1001b262: 2201 movs r2, #1 +1001b264: 212a movs r1, #42 ; 0x2a +1001b266: f7fd f88b bl 10018380 +1001b26a: 2e09 cmp r6, #9 +1001b26c: d304 bcc.n 1001b278 +1001b26e: 9400 str r4, [sp, #0] +1001b270: f000 f954 bl 1001b51c <.text_88> +1001b274: f7fd f884 bl 10018380 +1001b278: 2000 movs r0, #0 +1001b27a: f889 04d4 strb.w r0, [r9, #1236] ; 0x4d4 +1001b27e: a904 add r1, sp, #16 +1001b280: f509 609a add.w r0, r9, #1232 ; 0x4d0 +1001b284: f7f5 fb47 bl 10010916 +1001b288: 68f8 ldr r0, [r7, #12] +1001b28a: f100 0128 add.w r1, r0, #40 ; 0x28 +1001b28e: f240 6253 movw r2, #1619 ; 0x653 +1001b292: 4291 cmp r1, r2 +1001b294: d304 bcc.n 1001b2a0 +1001b296: f000 fe29 bl 1001beec <.text_124> +1001b29a: f000 fe18 bl 1001bece <.text_122> +1001b29e: e003 b.n 1001b2a8 <.text_83> +1001b2a0: 6060 str r0, [r4, #4] +1001b2a2: 4651 mov r1, sl +1001b2a4: f000 fb23 bl 1001b8ee <.text_104+0x2> + +1001b2a8 <.text_83>: +1001b2a8: b007 add sp, #28 +1001b2aa: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + ... + +1001b2b0 : +1001b2b0: ffff ffff ffff 0000 ........ + +1001b2b8 <.text_85>: +1001b2b8: f000 0003 and.w r0, r0, #3 +1001b2bc: 2803 cmp r0, #3 +1001b2be: 4770 bx lr + +1001b2c0 <.text_86>: +1001b2c0: f508 51c8 add.w r1, r8, #6400 ; 0x1900 +1001b2c4: 2206 movs r2, #6 +1001b2c6: 3195 adds r1, #149 ; 0x95 +1001b2c8: f104 000a add.w r0, r4, #10 +1001b2cc: f7f5 ba9f b.w 1001080e + +1001b2d0 : +1001b2d0: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +1001b2d4: b085 sub sp, #20 +1001b2d6: 4680 mov r8, r0 +1001b2d8: f508 609d add.w r0, r8, #1256 ; 0x4e8 +1001b2dc: 9002 str r0, [sp, #8] +1001b2de: f108 060c add.w r6, r8, #12 +1001b2e2: f500 7488 add.w r4, r0, #272 ; 0x110 +1001b2e6: 468a mov sl, r1 +1001b2e8: f106 058c add.w r5, r6, #140 ; 0x8c +1001b2ec: f608 1028 addw r0, r8, #2344 ; 0x928 +1001b2f0: f7ff fe5d bl 1001afae +1001b2f4: ea5f 0900 movs.w r9, r0 +1001b2f8: f000 810f beq.w 1001b51a +1001b2fc: f109 0708 add.w r7, r9, #8 +1001b300: 4639 mov r1, r7 +1001b302: f000 fafa bl 1001b8fa <.text_105+0x6> +1001b306: f000 fe03 bl 1001bf10 <.text_130> +1001b30a: f8d9 0080 ldr.w r0, [r9, #128] ; 0x80 +1001b30e: f100 0b28 add.w fp, r0, #40 ; 0x28 +1001b312: 2000 movs r0, #0 +1001b314: f8ab 0000 strh.w r0, [fp] +1001b318: 2206 movs r2, #6 +1001b31a: 4651 mov r1, sl +1001b31c: f10b 0004 add.w r0, fp, #4 +1001b320: f7f5 fa75 bl 1001080e +1001b324: f000 face bl 1001b8c4 <.text_100> +1001b328: f10b 000a add.w r0, fp, #10 +1001b32c: f7f5 fa6f bl 1001080e +1001b330: 2206 movs r2, #6 +1001b332: 1d29 adds r1, r5, #4 +1001b334: f10b 0010 add.w r0, fp, #16 +1001b338: f7f5 fa69 bl 1001080e +1001b33c: f10b 0016 add.w r0, fp, #22 +1001b340: 9a02 ldr r2, [sp, #8] +1001b342: 7801 ldrb r1, [r0, #0] +1001b344: 8992 ldrh r2, [r2, #12] +1001b346: f000 fbf9 bl 1001bb3c <.text_110> +1001b34a: f10b 0a18 add.w sl, fp, #24 +1001b34e: 9802 ldr r0, [sp, #8] +1001b350: 9902 ldr r1, [sp, #8] +1001b352: 8980 ldrh r0, [r0, #12] +1001b354: 1c40 adds r0, r0, #1 +1001b356: 8188 strh r0, [r1, #12] +1001b358: f64f 7103 movw r1, #65283 ; 0xff03 +1001b35c: f8bb 0000 ldrh.w r0, [fp] +1001b360: 4008 ands r0, r1 +1001b362: f040 0050 orr.w r0, r0, #80 ; 0x50 +1001b366: f8ab 0000 strh.w r0, [fp] +1001b36a: f240 3b01 movw fp, #769 ; 0x301 +1001b36e: 2018 movs r0, #24 +1001b370: 8178 strh r0, [r7, #10] +1001b372: 60f8 str r0, [r7, #12] +1001b374: 6fa8 ldr r0, [r5, #120] ; 0x78 +1001b376: 4558 cmp r0, fp +1001b378: f080 80cf bcs.w 1001b51a +1001b37c: 7821 ldrb r1, [r4, #0] +1001b37e: f002 fdf3 bl 1001df68 <.text_227> +1001b382: d16e bne.n 1001b462 +1001b384: f1a0 010c sub.w r1, r0, #12 +1001b388: ab01 add r3, sp, #4 +1001b38a: 2200 movs r2, #0 +1001b38c: f105 0088 add.w r0, r5, #136 ; 0x88 +1001b390: f7fd f80a bl 100183a8 +1001b394: f8d6 14bc ldr.w r1, [r6, #1212] ; 0x4bc +1001b398: 2900 cmp r1, #0 +1001b39a: bf1e ittt ne +1001b39c: 2800 cmpne r0, #0 +1001b39e: 9901 ldrne r1, [sp, #4] +1001b3a0: 2900 cmpne r1, #0 +1001b3a2: d037 beq.n 1001b414 +1001b3a4: f105 017c add.w r1, r5, #124 ; 0x7c +1001b3a8: 1a44 subs r4, r0, r1 +1001b3aa: 9901 ldr r1, [sp, #4] +1001b3ac: 1808 adds r0, r1, r0 +1001b3ae: 9003 str r0, [sp, #12] +1001b3b0: 4622 mov r2, r4 +1001b3b2: 6fa8 ldr r0, [r5, #120] ; 0x78 +1001b3b4: 9901 ldr r1, [sp, #4] +1001b3b6: 1b00 subs r0, r0, r4 +1001b3b8: 1a40 subs r0, r0, r1 +1001b3ba: 9000 str r0, [sp, #0] +1001b3bc: f000 f8be bl 1001b53c <.text_91> +1001b3c0: 68f8 ldr r0, [r7, #12] +1001b3c2: 1820 adds r0, r4, r0 +1001b3c4: 60f8 str r0, [r7, #12] +1001b3c6: 44a2 add sl, r4 +1001b3c8: f8d6 14bc ldr.w r1, [r6, #1212] ; 0x4bc +1001b3cc: 7848 ldrb r0, [r1, #1] +1001b3ce: 9001 str r0, [sp, #4] +1001b3d0: 1900 adds r0, r0, r4 +1001b3d2: 1c80 adds r0, r0, #2 +1001b3d4: 4558 cmp r0, fp +1001b3d6: d20c bcs.n 1001b3f2 +1001b3d8: 9801 ldr r0, [sp, #4] +1001b3da: 1c82 adds r2, r0, #2 +1001b3dc: f000 f8b0 bl 1001b540 <.text_91+0x4> +1001b3e0: 9801 ldr r0, [sp, #4] +1001b3e2: 9901 ldr r1, [sp, #4] +1001b3e4: 4450 add r0, sl +1001b3e6: f100 0a02 add.w sl, r0, #2 +1001b3ea: 68f8 ldr r0, [r7, #12] +1001b3ec: 1c89 adds r1, r1, #2 +1001b3ee: 1808 adds r0, r1, r0 +1001b3f0: 60f8 str r0, [r7, #12] +1001b3f2: 9801 ldr r0, [sp, #4] +1001b3f4: 9900 ldr r1, [sp, #0] +1001b3f6: 1900 adds r0, r0, r4 +1001b3f8: 1808 adds r0, r1, r0 +1001b3fa: 1c80 adds r0, r0, #2 +1001b3fc: 4558 cmp r0, fp +1001b3fe: d211 bcs.n 1001b424 +1001b400: 460a mov r2, r1 +1001b402: 9903 ldr r1, [sp, #12] +1001b404: f000 f89c bl 1001b540 <.text_91+0x4> +1001b408: 9800 ldr r0, [sp, #0] +1001b40a: 9900 ldr r1, [sp, #0] +1001b40c: 4482 add sl, r0 +1001b40e: 68f8 ldr r0, [r7, #12] +1001b410: 1808 adds r0, r1, r0 +1001b412: e006 b.n 1001b422 +1001b414: 6faa ldr r2, [r5, #120] ; 0x78 +1001b416: f000 f891 bl 1001b53c <.text_91> +1001b41a: 6fa8 ldr r0, [r5, #120] ; 0x78 +1001b41c: 68f9 ldr r1, [r7, #12] +1001b41e: 4482 add sl, r0 +1001b420: 1840 adds r0, r0, r1 +1001b422: 60f8 str r0, [r7, #12] +1001b424: 9802 ldr r0, [sp, #8] +1001b426: f500 757a add.w r5, r0, #1000 ; 0x3e8 +1001b42a: 7928 ldrb r0, [r5, #4] +1001b42c: 2800 cmp r0, #0 +1001b42e: d06a beq.n 1001b506 +1001b430: 2400 movs r4, #0 +1001b432: 7928 ldrb r0, [r5, #4] +1001b434: 42a0 cmp r0, r4 +1001b436: db66 blt.n 1001b506 +1001b438: 9802 ldr r0, [sp, #8] +1001b43a: f8d0 03e8 ldr.w r0, [r0, #1000] ; 0x3e8 +1001b43e: eb00 01c4 add.w r1, r0, r4, lsl #3 +1001b442: 7909 ldrb r1, [r1, #4] +1001b444: 0789 lsls r1, r1, #30 +1001b446: d50a bpl.n 1001b45e +1001b448: f850 0034 ldr.w r0, [r0, r4, lsl #3] +1001b44c: f000 fa36 bl 1001b8bc <.text_99> +1001b450: 1c83 adds r3, r0, #2 +1001b452: 7842 ldrb r2, [r0, #1] +1001b454: 7801 ldrb r1, [r0, #0] +1001b456: 4650 mov r0, sl +1001b458: f7fc ff92 bl 10018380 +1001b45c: 4682 mov sl, r0 +1001b45e: 1c64 adds r4, r4, #1 +1001b460: e7e7 b.n 1001b432 +1001b462: 2020 movs r0, #32 +1001b464: 60f8 str r0, [r7, #12] +1001b466: f10a 0608 add.w r6, sl, #8 +1001b46a: f000 f863 bl 1001b534 <.text_90> +1001b46e: f001 fee1 bl 1001d234 <.text_182> +1001b472: f000 f868 bl 1001b546 <.text_92> +1001b476: f001 fedd bl 1001d234 <.text_182> +1001b47a: 68f8 ldr r0, [r7, #12] +1001b47c: 1c80 adds r0, r0, #2 +1001b47e: 60f8 str r0, [r7, #12] +1001b480: f105 0310 add.w r3, r5, #16 +1001b484: f001 f8c4 bl 1001c610 <.text_152> +1001b488: 2100 movs r1, #0 +1001b48a: 68ea ldr r2, [r5, #12] +1001b48c: 1cb0 adds r0, r6, #2 +1001b48e: f7fc ff77 bl 10018380 +1001b492: 4682 mov sl, r0 +1001b494: f105 0064 add.w r0, r5, #100 ; 0x64 +1001b498: f7fc ff7a bl 10018390 +1001b49c: 4606 mov r6, r0 +1001b49e: f107 000c add.w r0, r7, #12 +1001b4a2: 2e09 cmp r6, #9 +1001b4a4: 9000 str r0, [sp, #0] +1001b4a6: bf2c ite cs +1001b4a8: 2208 movcs r2, #8 +1001b4aa: 4632 movcc r2, r6 +1001b4ac: f105 0364 add.w r3, r5, #100 ; 0x64 +1001b4b0: 2101 movs r1, #1 +1001b4b2: 4650 mov r0, sl +1001b4b4: f7fc ff64 bl 10018380 +1001b4b8: f000 fa00 bl 1001b8bc <.text_99> +1001b4bc: f000 f834 bl 1001b528 <.text_89> +1001b4c0: 4682 mov sl, r0 +1001b4c2: 7820 ldrb r0, [r4, #0] +1001b4c4: f000 0003 and.w r0, r0, #3 +1001b4c8: 2801 cmp r0, #1 +1001b4ca: d113 bne.n 1001b4f4 +1001b4cc: 2000 movs r0, #0 +1001b4ce: f88d 0008 strb.w r0, [sp, #8] +1001b4d2: 9003 str r0, [sp, #12] +1001b4d4: ab03 add r3, sp, #12 +1001b4d6: f001 f89b bl 1001c610 <.text_152> +1001b4da: 2202 movs r2, #2 +1001b4dc: 2106 movs r1, #6 +1001b4de: 4650 mov r0, sl +1001b4e0: f7fc ff4e bl 10018380 +1001b4e4: f000 f9ea bl 1001b8bc <.text_99> +1001b4e8: ab02 add r3, sp, #8 +1001b4ea: 2201 movs r2, #1 +1001b4ec: 212a movs r1, #42 ; 0x2a +1001b4ee: f7fc ff47 bl 10018380 +1001b4f2: 4682 mov sl, r0 +1001b4f4: 2e09 cmp r6, #9 +1001b4f6: d306 bcc.n 1001b506 +1001b4f8: f001 f88a bl 1001c610 <.text_152> +1001b4fc: f000 f80e bl 1001b51c <.text_88> +1001b500: 4650 mov r0, sl +1001b502: f7fc ff3d bl 10018380 +1001b506: f001 f887 bl 1001c618 <.text_153> +1001b50a: d303 bcc.n 1001b514 +1001b50c: f000 fcee bl 1001beec <.text_124> +1001b510: f000 fcdd bl 1001bece <.text_122> +1001b514: 4649 mov r1, r9 +1001b516: f000 f9ea bl 1001b8ee <.text_104+0x2> +1001b51a: e41e b.n 1001ad5a <.text_54+0x2> + +1001b51c <.text_88>: +1001b51c: f105 036c add.w r3, r5, #108 ; 0x6c +1001b520: f1a6 0208 sub.w r2, r6, #8 +1001b524: 2132 movs r1, #50 ; 0x32 +1001b526: 4770 bx lr + +1001b528 <.text_89>: +1001b528: f105 034c add.w r3, r5, #76 ; 0x4c +1001b52c: 2201 movs r2, #1 +1001b52e: 2103 movs r1, #3 +1001b530: f7fc bf26 b.w 10018380 + +1001b534 <.text_90>: +1001b534: f105 007c add.w r0, r5, #124 ; 0x7c +1001b538: f003 b9d8 b.w 1001e8ec + +1001b53c <.text_91>: +1001b53c: f105 017c add.w r1, r5, #124 ; 0x7c +1001b540: 4650 mov r0, sl +1001b542: f7f5 b964 b.w 1001080e + +1001b546 <.text_92>: +1001b546: 68f8 ldr r0, [r7, #12] +1001b548: 1c80 adds r0, r0, #2 +1001b54a: 60f8 str r0, [r7, #12] +1001b54c: 1cb6 adds r6, r6, #2 +1001b54e: f105 007c add.w r0, r5, #124 ; 0x7c +1001b552: f003 b9bf b.w 1001e8d4 + +1001b556 : +1001b556: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +1001b55a: b089 sub sp, #36 ; 0x24 +1001b55c: 4680 mov r8, r0 +1001b55e: 460d mov r5, r1 +1001b560: 2000 movs r0, #0 +1001b562: 4692 mov sl, r2 +1001b564: 9001 str r0, [sp, #4] +1001b566: f108 090c add.w r9, r8, #12 +1001b56a: f20f 1154 addw r1, pc, #340 ; 0x154 +1001b56e: c90c ldmia r1!, {r2, r3} +1001b570: a802 add r0, sp, #8 +1001b572: f508 669d add.w r6, r8, #1256 ; 0x4e8 +1001b576: f000 f8b9 bl 1001b6ec <.text_97> +1001b57a: ea5f 0b00 movs.w fp, r0 +1001b57e: f000 809c beq.w 1001b6ba +1001b582: f000 f9b7 bl 1001b8f4 <.text_105> +1001b586: f8db 0080 ldr.w r0, [fp, #128] ; 0x80 +1001b58a: f000 fcc3 bl 1001bf14 <.text_130+0x4> +1001b58e: f8db 0080 ldr.w r0, [fp, #128] ; 0x80 +1001b592: f100 0728 add.w r7, r0, #40 ; 0x28 +1001b596: f508 50c8 add.w r0, r8, #6400 ; 0x1900 +1001b59a: 3095 adds r0, #149 ; 0x95 +1001b59c: 9000 str r0, [sp, #0] +1001b59e: 2000 movs r0, #0 +1001b5a0: f1ba 0f00 cmp.w sl, #0 +1001b5a4: 8038 strh r0, [r7, #0] +1001b5a6: d10a bne.n 1001b5be +1001b5a8: f109 0a8c add.w sl, r9, #140 ; 0x8c +1001b5ac: f000 fca8 bl 1001bf00 <.text_128> +1001b5b0: f000 fd12 bl 1001bfd8 <.text_133> +1001b5b4: f000 fca4 bl 1001bf00 <.text_128> +1001b5b8: f000 fdff bl 1001c1ba <.text_141> +1001b5bc: e00a b.n 1001b5d4 +1001b5be: 2206 movs r2, #6 +1001b5c0: a902 add r1, sp, #8 +1001b5c2: 1d38 adds r0, r7, #4 +1001b5c4: f7f5 f923 bl 1001080e +1001b5c8: 2206 movs r2, #6 +1001b5ca: a902 add r1, sp, #8 +1001b5cc: f107 0010 add.w r0, r7, #16 +1001b5d0: f7f5 f91d bl 1001080e +1001b5d4: 9900 ldr r1, [sp, #0] +1001b5d6: 2206 movs r2, #6 +1001b5d8: f107 000a add.w r0, r7, #10 +1001b5dc: f7f5 f917 bl 1001080e +1001b5e0: f000 f872 bl 1001b6c8 <.text_95> +1001b5e4: 2118 movs r1, #24 +1001b5e6: f040 0040 orr.w r0, r0, #64 ; 0x40 +1001b5ea: 8038 strh r0, [r7, #0] +1001b5ec: 60e1 str r1, [r4, #12] +1001b5ee: 2d00 cmp r5, #0 +1001b5f0: f104 010c add.w r1, r4, #12 +1001b5f4: f107 0018 add.w r0, r7, #24 +1001b5f8: 9100 str r1, [sp, #0] +1001b5fa: d003 beq.n 1001b604 +1001b5fc: 682a ldr r2, [r5, #0] +1001b5fe: 1d2b adds r3, r5, #4 +1001b600: 2100 movs r1, #0 +1001b602: e002 b.n 1001b60a +1001b604: 2200 movs r2, #0 +1001b606: 2300 movs r3, #0 +1001b608: 4611 mov r1, r2 +1001b60a: f7fc feb9 bl 10018380 +1001b60e: 4605 mov r5, r0 +1001b610: aa01 add r2, sp, #4 +1001b612: a904 add r1, sp, #16 +1001b614: 4640 mov r0, r8 +1001b616: f00a fa15 bl 10025a44 +1001b61a: 9801 ldr r0, [sp, #4] +1001b61c: 2809 cmp r0, #9 +1001b61e: f000 fc4d bl 1001bebc <.text_120> +1001b622: ab04 add r3, sp, #16 +1001b624: db0a blt.n 1001b63c +1001b626: f000 fc4d bl 1001bec4 <.text_121> +1001b62a: f104 010c add.w r1, r4, #12 +1001b62e: 9100 str r1, [sp, #0] +1001b630: ab06 add r3, sp, #24 +1001b632: 9901 ldr r1, [sp, #4] +1001b634: f1a1 0208 sub.w r2, r1, #8 +1001b638: 2132 movs r1, #50 ; 0x32 +1001b63a: e002 b.n 1001b642 +1001b63c: 9a01 ldr r2, [sp, #4] +1001b63e: 2101 movs r1, #1 +1001b640: 4628 mov r0, r5 +1001b642: f7fc fe9d bl 10018380 +1001b646: f506 757a add.w r5, r6, #1000 ; 0x3e8 +1001b64a: 7929 ldrb r1, [r5, #4] +1001b64c: b1c1 cbz r1, 1001b680 +1001b64e: f04f 0a00 mov.w sl, #0 +1001b652: e012 b.n 1001b67a +1001b654: f8d6 13e8 ldr.w r1, [r6, #1000] ; 0x3e8 +1001b658: eb01 02ca add.w r2, r1, sl, lsl #3 +1001b65c: 7912 ldrb r2, [r2, #4] +1001b65e: 07d2 lsls r2, r2, #31 +1001b660: d509 bpl.n 1001b676 +1001b662: f851 103a ldr.w r1, [r1, sl, lsl #3] +1001b666: f104 020c add.w r2, r4, #12 +1001b66a: 9200 str r2, [sp, #0] +1001b66c: 1c8b adds r3, r1, #2 +1001b66e: 784a ldrb r2, [r1, #1] +1001b670: 7809 ldrb r1, [r1, #0] +1001b672: f7fc fe85 bl 10018380 +1001b676: f10a 0a01 add.w sl, sl, #1 +1001b67a: 7929 ldrb r1, [r5, #4] +1001b67c: 4551 cmp r1, sl +1001b67e: dae9 bge.n 1001b654 +1001b680: f509 6693 add.w r6, r9, #1176 ; 0x498 +1001b684: 6872 ldr r2, [r6, #4] +1001b686: 2a00 cmp r2, #0 +1001b688: bf1c itt ne +1001b68a: f8d9 1498 ldrne.w r1, [r9, #1176] ; 0x498 +1001b68e: 2900 cmpne r1, #0 +1001b690: d005 beq.n 1001b69e +1001b692: f7f5 f8bc bl 1001080e +1001b696: 68e0 ldr r0, [r4, #12] +1001b698: 6871 ldr r1, [r6, #4] +1001b69a: 1808 adds r0, r1, r0 +1001b69c: 60e0 str r0, [r4, #12] +1001b69e: f240 6153 movw r1, #1619 ; 0x653 +1001b6a2: 68e0 ldr r0, [r4, #12] +1001b6a4: 6120 str r0, [r4, #16] +1001b6a6: 68e0 ldr r0, [r4, #12] +1001b6a8: 3028 adds r0, #40 ; 0x28 +1001b6aa: 4288 cmp r0, r1 +1001b6ac: d303 bcc.n 1001b6b6 +1001b6ae: f000 fc1d bl 1001beec <.text_124> +1001b6b2: f000 fc0c bl 1001bece <.text_122> +1001b6b6: f000 f919 bl 1001b8ec <.text_104> +1001b6ba: b009 add sp, #36 ; 0x24 +1001b6bc: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1001b6c0 : +1001b6c0: ffff ffff ffff 0000 ........ + +1001b6c8 <.text_95>: +1001b6c8: f107 0016 add.w r0, r7, #22 +1001b6cc: 7801 ldrb r1, [r0, #0] +1001b6ce: 89b2 ldrh r2, [r6, #12] +1001b6d0: f001 010f and.w r1, r1, #15 +1001b6d4: ea41 1102 orr.w r1, r1, r2, lsl #4 +1001b6d8: 8001 strh r1, [r0, #0] +1001b6da: f64f 7103 movw r1, #65283 ; 0xff03 +1001b6de: 89b0 ldrh r0, [r6, #12] +1001b6e0: 1c40 adds r0, r0, #1 +1001b6e2: 81b0 strh r0, [r6, #12] + +1001b6e4 <.text_96>: +1001b6e4: 8838 ldrh r0, [r7, #0] +1001b6e6: 4008 ands r0, r1 +1001b6e8: 8038 strh r0, [r7, #0] +1001b6ea: 4770 bx lr + +1001b6ec <.text_97>: +1001b6ec: c00c stmia r0!, {r2, r3} +1001b6ee: f608 1028 addw r0, r8, #2344 ; 0x928 +1001b6f2: e45c b.n 1001afae + +1001b6f4 : +1001b6f4: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +1001b6f8: b085 sub sp, #20 +1001b6fa: 4680 mov r8, r0 +1001b6fc: f108 000c add.w r0, r8, #12 +1001b700: 9000 str r0, [sp, #0] +1001b702: f508 6b9d add.w fp, r8, #1256 ; 0x4e8 +1001b706: 468a mov sl, r1 +1001b708: 4691 mov r9, r2 +1001b70a: 2500 movs r5, #0 +1001b70c: f50b 7688 add.w r6, fp, #272 ; 0x110 +1001b710: f608 1028 addw r0, r8, #2344 ; 0x928 +1001b714: f7ff fc4b bl 1001afae +1001b718: 2800 cmp r0, #0 +1001b71a: 9002 str r0, [sp, #8] +1001b71c: f000 80cc beq.w 1001b8b8 +1001b720: f100 0708 add.w r7, r0, #8 +1001b724: 4639 mov r1, r7 +1001b726: f000 f8e8 bl 1001b8fa <.text_105+0x6> +1001b72a: 9802 ldr r0, [sp, #8] +1001b72c: f8d0 0080 ldr.w r0, [r0, #128] ; 0x80 +1001b730: f000 fbf0 bl 1001bf14 <.text_130+0x4> +1001b734: 9802 ldr r0, [sp, #8] +1001b736: f8d0 0080 ldr.w r0, [r0, #128] ; 0x80 +1001b73a: f100 0428 add.w r4, r0, #40 ; 0x28 +1001b73e: f104 0016 add.w r0, r4, #22 +1001b742: 8025 strh r5, [r4, #0] +1001b744: 7801 ldrb r1, [r0, #0] +1001b746: f8bb 200c ldrh.w r2, [fp, #12] +1001b74a: f000 fcd4 bl 1001c0f6 <.text_135> +1001b74e: f8bb 000c ldrh.w r0, [fp, #12] +1001b752: 1c40 adds r0, r0, #1 +1001b754: f8ab 000c strh.w r0, [fp, #12] +1001b758: f104 0b18 add.w fp, r4, #24 +1001b75c: 8820 ldrh r0, [r4, #0] +1001b75e: 4008 ands r0, r1 +1001b760: 8020 strh r0, [r4, #0] +1001b762: f040 00b0 orr.w r0, r0, #176 ; 0xb0 +1001b766: 8020 strh r0, [r4, #0] +1001b768: 2018 movs r0, #24 +1001b76a: f1ba 0f00 cmp.w sl, #0 +1001b76e: 60f8 str r0, [r7, #12] +1001b770: d038 beq.n 1001b7e4 +1001b772: 2206 movs r2, #6 +1001b774: f50a 7184 add.w r1, sl, #264 ; 0x108 +1001b778: 1d20 adds r0, r4, #4 +1001b77a: f7f5 f848 bl 1001080e +1001b77e: f7ff fd9f bl 1001b2c0 <.text_86> +1001b782: f000 f89f bl 1001b8c4 <.text_100> +1001b786: f104 0010 add.w r0, r4, #16 +1001b78a: f7f5 f840 bl 1001080e +1001b78e: f8da 0234 ldr.w r0, [sl, #564] ; 0x234 +1001b792: f8ad 0004 strh.w r0, [sp, #4] +1001b796: f1b9 0f00 cmp.w r9, #0 +1001b79a: bf18 it ne +1001b79c: f8ad 5004 strhne.w r5, [sp, #4] +1001b7a0: d103 bne.n 1001b7aa +1001b7a2: f8bd 0004 ldrh.w r0, [sp, #4] +1001b7a6: b100 cbz r0, 1001b7aa +1001b7a8: 2501 movs r5, #1 +1001b7aa: f000 f890 bl 1001b8ce <.text_101> +1001b7ae: f8da 1230 ldr.w r1, [sl, #560] ; 0x230 +1001b7b2: f000 f893 bl 1001b8dc <.text_102> +1001b7b6: f8ad 9004 strh.w r9, [sp, #4] +1001b7ba: f000 f891 bl 1001b8e0 <.text_102+0x4> +1001b7be: f8da 1230 ldr.w r1, [sl, #560] ; 0x230 +1001b7c2: 2902 cmp r1, #2 +1001b7c4: d165 bne.n 1001b892 +1001b7c6: f8da 10f8 ldr.w r1, [sl, #248] ; 0xf8 +1001b7ca: 0589 lsls r1, r1, #22 +1001b7cc: d561 bpl.n 1001b892 +1001b7ce: 2d00 cmp r5, #0 +1001b7d0: d05f beq.n 1001b892 +1001b7d2: f000 f873 bl 1001b8bc <.text_99> +1001b7d6: f50a 730e add.w r3, sl, #568 ; 0x238 +1001b7da: 2280 movs r2, #128 ; 0x80 +1001b7dc: 2110 movs r1, #16 +1001b7de: f7fc fdcf bl 10018380 +1001b7e2: e056 b.n 1001b892 +1001b7e4: 9800 ldr r0, [sp, #0] +1001b7e6: f100 0a8c add.w sl, r0, #140 ; 0x8c +1001b7ea: f000 fb89 bl 1001bf00 <.text_128> +1001b7ee: 4601 mov r1, r0 +1001b7f0: 2206 movs r2, #6 +1001b7f2: 1d20 adds r0, r4, #4 +1001b7f4: f7f5 f80b bl 1001080e +1001b7f8: f7ff fd62 bl 1001b2c0 <.text_86> +1001b7fc: f000 fb80 bl 1001bf00 <.text_128> +1001b800: f000 f87e bl 1001b900 <.text_106> +1001b804: 6970 ldr r0, [r6, #20] +1001b806: 2801 cmp r0, #1 +1001b808: bf18 it ne +1001b80a: 2000 movne r0, #0 +1001b80c: f8ad 0004 strh.w r0, [sp, #4] +1001b810: f8bd 0004 ldrh.w r0, [sp, #4] +1001b814: b100 cbz r0, 1001b818 +1001b816: 2501 movs r5, #1 +1001b818: 6930 ldr r0, [r6, #16] +1001b81a: 2803 cmp r0, #3 +1001b81c: d114 bne.n 1001b848 +1001b81e: 6830 ldr r0, [r6, #0] +1001b820: 0580 lsls r0, r0, #22 +1001b822: d511 bpl.n 1001b848 +1001b824: b185 cbz r5, 1001b848 +1001b826: 6a70 ldr r0, [r6, #36] ; 0x24 +1001b828: 1c41 adds r1, r0, #1 +1001b82a: 6271 str r1, [r6, #36] ; 0x24 +1001b82c: f107 030c add.w r3, r7, #12 +1001b830: 6a31 ldr r1, [r6, #32] +1001b832: ea40 7081 orr.w r0, r0, r1, lsl #30 +1001b836: 9003 str r0, [sp, #12] +1001b838: aa03 add r2, sp, #12 +1001b83a: 2104 movs r1, #4 +1001b83c: 4658 mov r0, fp +1001b83e: f7fe f8bb bl 100199b8 +1001b842: 4683 mov fp, r0 +1001b844: 2004 movs r0, #4 +1001b846: 7578 strb r0, [r7, #21] +1001b848: f000 f841 bl 1001b8ce <.text_101> +1001b84c: 6931 ldr r1, [r6, #16] +1001b84e: f000 f845 bl 1001b8dc <.text_102> +1001b852: f8ad 9004 strh.w r9, [sp, #4] +1001b856: f000 f843 bl 1001b8e0 <.text_102+0x4> +1001b85a: 6931 ldr r1, [r6, #16] +1001b85c: 2903 cmp r1, #3 +1001b85e: d118 bne.n 1001b892 +1001b860: 6831 ldr r1, [r6, #0] +1001b862: 0589 lsls r1, r1, #22 +1001b864: d515 bpl.n 1001b892 +1001b866: b1a5 cbz r5, 1001b892 +1001b868: f000 f828 bl 1001b8bc <.text_99> +1001b86c: f106 0328 add.w r3, r6, #40 ; 0x28 +1001b870: 2280 movs r2, #128 ; 0x80 +1001b872: 2110 movs r1, #16 +1001b874: f7fc fd84 bl 10018380 +1001b878: 8820 ldrh r0, [r4, #0] +1001b87a: f440 4080 orr.w r0, r0, #16384 ; 0x4000 +1001b87e: 8020 strh r0, [r4, #0] +1001b880: 2018 movs r0, #24 +1001b882: 8178 strh r0, [r7, #10] +1001b884: 2001 movs r0, #1 +1001b886: 7538 strb r0, [r7, #20] +1001b888: 2004 movs r0, #4 +1001b88a: 75b8 strb r0, [r7, #22] +1001b88c: 68f8 ldr r0, [r7, #12] +1001b88e: 1d00 adds r0, r0, #4 +1001b890: 60f8 str r0, [r7, #12] +1001b892: f240 6153 movw r1, #1619 ; 0x653 +1001b896: 68f8 ldr r0, [r7, #12] +1001b898: 6138 str r0, [r7, #16] +1001b89a: 68f8 ldr r0, [r7, #12] +1001b89c: 3028 adds r0, #40 ; 0x28 +1001b89e: 4288 cmp r0, r1 +1001b8a0: d303 bcc.n 1001b8aa +1001b8a2: f000 fb23 bl 1001beec <.text_124> +1001b8a6: f000 fb12 bl 1001bece <.text_122> +1001b8aa: 9902 ldr r1, [sp, #8] +1001b8ac: 4640 mov r0, r8 +1001b8ae: f012 fc60 bl 1002e172 +1001b8b2: 9902 ldr r1, [sp, #8] +1001b8b4: f000 f81b bl 1001b8ee <.text_104+0x2> +1001b8b8: f7ff ba4f b.w 1001ad5a <.text_54+0x2> + +1001b8bc <.text_99>: +1001b8bc: f107 010c add.w r1, r7, #12 +1001b8c0: 9100 str r1, [sp, #0] +1001b8c2: 4770 bx lr + +1001b8c4 <.text_100>: +1001b8c4: f508 51c8 add.w r1, r8, #6400 ; 0x1900 +1001b8c8: 2206 movs r2, #6 +1001b8ca: 3195 adds r1, #149 ; 0x95 +1001b8cc: 4770 bx lr + +1001b8ce <.text_101>: +1001b8ce: f107 030c add.w r3, r7, #12 +1001b8d2: aa01 add r2, sp, #4 +1001b8d4: 2102 movs r1, #2 +1001b8d6: 4658 mov r0, fp +1001b8d8: f7fe b86e b.w 100199b8 + +1001b8dc <.text_102>: +1001b8dc: f8ad 1004 strh.w r1, [sp, #4] +1001b8e0: f107 030c add.w r3, r7, #12 + +1001b8e4 <.text_103>: +1001b8e4: aa01 add r2, sp, #4 +1001b8e6: 2102 movs r1, #2 +1001b8e8: f7fe b866 b.w 100199b8 + +1001b8ec <.text_104>: +1001b8ec: 4659 mov r1, fp +1001b8ee: 4640 mov r0, r8 +1001b8f0: f7ff bba5 b.w 1001b03e + +1001b8f4 <.text_105>: +1001b8f4: f10b 0408 add.w r4, fp, #8 +1001b8f8: 4621 mov r1, r4 +1001b8fa: 4640 mov r0, r8 +1001b8fc: f7ff bb74 b.w 1001afe8 + +1001b900 <.text_106>: +1001b900: 4601 mov r1, r0 +1001b902: 2206 movs r2, #6 +1001b904: f104 0010 add.w r0, r4, #16 +1001b908: f7f4 bf81 b.w 1001080e + +1001b90c : +1001b90c: e92d 4ffa stmdb sp!, {r1, r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1001b910: 4682 mov sl, r0 +1001b912: b085 sub sp, #20 +1001b914: f50a 679d add.w r7, sl, #1256 ; 0x4e8 +1001b918: f507 7088 add.w r0, r7, #272 ; 0x110 +1001b91c: 9003 str r0, [sp, #12] +1001b91e: f10a 0b0c add.w fp, sl, #12 +1001b922: f10b 008c add.w r0, fp, #140 ; 0x8c +1001b926: 9002 str r0, [sp, #8] +1001b928: f100 087c add.w r8, r0, #124 ; 0x7c +1001b92c: 4615 mov r5, r2 +1001b92e: f60a 1028 addw r0, sl, #2344 ; 0x928 +1001b932: f7ff fb3c bl 1001afae +1001b936: ea5f 0900 movs.w r9, r0 +1001b93a: f000 80f7 beq.w 1001bb2c +1001b93e: f109 0608 add.w r6, r9, #8 +1001b942: 4631 mov r1, r6 +1001b944: 4650 mov r0, sl +1001b946: f7ff fb4f bl 1001afe8 +1001b94a: f000 fae1 bl 1001bf10 <.text_130> +1001b94e: f8d9 0080 ldr.w r0, [r9, #128] ; 0x80 +1001b952: f000 f8f9 bl 1001bb48 <.text_111> +1001b956: f505 7184 add.w r1, r5, #264 ; 0x108 +1001b95a: 1d20 adds r0, r4, #4 +1001b95c: f7f4 ff57 bl 1001080e +1001b960: f50a 51c8 add.w r1, sl, #6400 ; 0x1900 +1001b964: f7ff fcae bl 1001b2c4 <.text_86+0x4> +1001b968: 9802 ldr r0, [sp, #8] +1001b96a: f00a f93e bl 10025bea +1001b96e: f7ff ffc7 bl 1001b900 <.text_106> +1001b972: f104 0016 add.w r0, r4, #22 +1001b976: 7801 ldrb r1, [r0, #0] +1001b978: 89ba ldrh r2, [r7, #12] +1001b97a: f000 f8df bl 1001bb3c <.text_110> +1001b97e: 89b8 ldrh r0, [r7, #12] +1001b980: 1c40 adds r0, r0, #1 +1001b982: 81b8 strh r0, [r7, #12] +1001b984: 9806 ldr r0, [sp, #24] +1001b986: 2810 cmp r0, #16 +1001b988: bf18 it ne +1001b98a: 2830 cmpne r0, #48 ; 0x30 +1001b98c: f040 80ce bne.w 1001bb2c +1001b990: 8820 ldrh r0, [r4, #0] +1001b992: f64f 7103 movw r1, #65283 ; 0xff03 +1001b996: 4008 ands r0, r1 +1001b998: 9906 ldr r1, [sp, #24] +1001b99a: 4308 orrs r0, r1 +1001b99c: 8020 strh r0, [r4, #0] +1001b99e: 2018 movs r0, #24 +1001b9a0: 8170 strh r0, [r6, #10] +1001b9a2: 68f0 ldr r0, [r6, #12] +1001b9a4: 3018 adds r0, #24 +1001b9a6: 60f0 str r0, [r6, #12] +1001b9a8: 4640 mov r0, r8 +1001b9aa: f002 ff93 bl 1001e8d4 +1001b9ae: 8800 ldrh r0, [r0, #0] +1001b9b0: f8ad 0004 strh.w r0, [sp, #4] +1001b9b4: f106 030c add.w r3, r6, #12 +1001b9b8: aa01 add r2, sp, #4 +1001b9ba: 2102 movs r1, #2 +1001b9bc: f104 0018 add.w r0, r4, #24 +1001b9c0: f7fd fffa bl 100199b8 +1001b9c4: f106 030c add.w r3, r6, #12 +1001b9c8: aa05 add r2, sp, #20 +1001b9ca: f000 fd0b bl 1001c3e4 <.text_144> +1001b9ce: f8d5 10fc ldr.w r1, [r5, #252] ; 0xfc +1001b9d2: f441 4140 orr.w r1, r1, #49152 ; 0xc000 +1001b9d6: f8ad 1004 strh.w r1, [sp, #4] +1001b9da: f106 030c add.w r3, r6, #12 +1001b9de: f7ff ff81 bl 1001b8e4 <.text_103> +1001b9e2: f105 04fc add.w r4, r5, #252 ; 0xfc +1001b9e6: f106 010c add.w r1, r6, #12 +1001b9ea: 6ee2 ldr r2, [r4, #108] ; 0x6c +1001b9ec: 9100 str r1, [sp, #0] +1001b9ee: 2a09 cmp r2, #9 +1001b9f0: f505 73ac add.w r3, r5, #344 ; 0x158 +1001b9f4: bf38 it cc +1001b9f6: 2101 movcc r1, #1 +1001b9f8: d30c bcc.n 1001ba14 +1001b9fa: 2208 movs r2, #8 +1001b9fc: 2101 movs r1, #1 +1001b9fe: f7fc fcbf bl 10018380 +1001ba02: f106 010c add.w r1, r6, #12 +1001ba06: 9100 str r1, [sp, #0] +1001ba08: f505 73b0 add.w r3, r5, #352 ; 0x160 +1001ba0c: 6ee1 ldr r1, [r4, #108] ; 0x6c +1001ba0e: f1a1 0208 sub.w r2, r1, #8 +1001ba12: 2132 movs r1, #50 ; 0x32 +1001ba14: f7fc fcb4 bl 10018380 +1001ba18: 4604 mov r4, r0 +1001ba1a: f8d5 02bc ldr.w r0, [r5, #700] ; 0x2bc +1001ba1e: 0500 lsls r0, r0, #20 +1001ba20: d528 bpl.n 1001ba74 +1001ba22: f8db 0448 ldr.w r0, [fp, #1096] ; 0x448 +1001ba26: b328 cbz r0, 1001ba74 +1001ba28: 2000 movs r0, #0 +1001ba2a: 9000 str r0, [sp, #0] +1001ba2c: f000 f89b bl 1001bb66 <.text_113> +1001ba30: 212d movs r1, #45 ; 0x2d +1001ba32: f108 000c add.w r0, r8, #12 +1001ba36: f7f8 fa23 bl 10013e80 +1001ba3a: 2800 cmp r0, #0 +1001ba3c: bf1c itt ne +1001ba3e: 9900 ldrne r1, [sp, #0] +1001ba40: 2900 cmpne r1, #0 +1001ba42: d005 beq.n 1001ba50 +1001ba44: 1c8a adds r2, r1, #2 +1001ba46: 4601 mov r1, r0 +1001ba48: f000 f893 bl 1001bb72 <.text_114> +1001ba4c: f000 f882 bl 1001bb54 <.text_112> +1001ba50: f000 f889 bl 1001bb66 <.text_113> +1001ba54: 213d movs r1, #61 ; 0x3d +1001ba56: f108 000c add.w r0, r8, #12 +1001ba5a: f7f8 fa11 bl 10013e80 +1001ba5e: 0003 movs r3, r0 +1001ba60: bf1c itt ne +1001ba62: 9800 ldrne r0, [sp, #0] +1001ba64: 2800 cmpne r0, #0 +1001ba66: d005 beq.n 1001ba74 +1001ba68: 1c82 adds r2, r0, #2 +1001ba6a: 4619 mov r1, r3 +1001ba6c: f000 f881 bl 1001bb72 <.text_114> +1001ba70: f000 f870 bl 1001bb54 <.text_112> +1001ba74: f8d5 02bc ldr.w r0, [r5, #700] ; 0x2bc +1001ba78: 0580 lsls r0, r0, #22 +1001ba7a: d528 bpl.n 1001bace +1001ba7c: f8db 0440 ldr.w r0, [fp, #1088] ; 0x440 +1001ba80: b328 cbz r0, 1001bace +1001ba82: 2000 movs r0, #0 +1001ba84: 9000 str r0, [sp, #0] +1001ba86: f108 000c add.w r0, r8, #12 +1001ba8a: f20f 05a8 addw r5, pc, #168 ; 0xa8 +1001ba8e: e001 b.n 1001ba94 +1001ba90: 19c0 adds r0, r0, r7 +1001ba92: 1c80 adds r0, r0, #2 +1001ba94: 9902 ldr r1, [sp, #8] +1001ba96: 6f89 ldr r1, [r1, #120] ; 0x78 +1001ba98: 9a00 ldr r2, [sp, #0] +1001ba9a: 390c subs r1, #12 +1001ba9c: 1a89 subs r1, r1, r2 +1001ba9e: 1e8b subs r3, r1, #2 +1001baa0: aa00 add r2, sp, #0 +1001baa2: 21dd movs r1, #221 ; 0xdd +1001baa4: f7f8 f9ec bl 10013e80 +1001baa8: 0007 movs r7, r0 +1001baaa: d010 beq.n 1001bace +1001baac: 2206 movs r2, #6 +1001baae: 4629 mov r1, r5 +1001bab0: 1cb8 adds r0, r7, #2 +1001bab2: f7f4 feb6 bl 10010822 +1001bab6: 2800 cmp r0, #0 +1001bab8: 9800 ldr r0, [sp, #0] +1001baba: d006 beq.n 1001baca +1001babc: 1c82 adds r2, r0, #2 +1001babe: 4639 mov r1, r7 +1001bac0: f000 f857 bl 1001bb72 <.text_114> +1001bac4: f000 f846 bl 1001bb54 <.text_112> +1001bac8: e001 b.n 1001bace +1001baca: 2800 cmp r0, #0 +1001bacc: d1e0 bne.n 1001ba90 +1001bace: 9803 ldr r0, [sp, #12] +1001bad0: f890 00ae ldrb.w r0, [r0, #174] ; 0xae +1001bad4: 2801 cmp r0, #1 +1001bad6: d10a bne.n 1001baee +1001bad8: f106 000c add.w r0, r6, #12 +1001badc: 9000 str r0, [sp, #0] +1001bade: 2206 movs r2, #6 +1001bae0: f8df 3414 ldr.w r3, [pc, #1044] ; 1001bef8 <.text_126> +1001bae4: 21dd movs r1, #221 ; 0xdd +1001bae6: 4620 mov r0, r4 +1001bae8: f7fc fc4a bl 10018380 +1001baec: 4604 mov r4, r0 +1001baee: f8db 14c0 ldr.w r1, [fp, #1216] ; 0x4c0 +1001baf2: 2900 cmp r1, #0 +1001baf4: bf1e ittt ne +1001baf6: f50b 6598 addne.w r5, fp, #1216 ; 0x4c0 +1001bafa: 68ea ldrne r2, [r5, #12] +1001bafc: 2a00 cmpne r2, #0 +1001bafe: d005 beq.n 1001bb0c +1001bb00: f000 f837 bl 1001bb72 <.text_114> +1001bb04: 68f0 ldr r0, [r6, #12] +1001bb06: 68e9 ldr r1, [r5, #12] +1001bb08: 1808 adds r0, r1, r0 +1001bb0a: 60f0 str r0, [r6, #12] +1001bb0c: f240 6153 movw r1, #1619 ; 0x653 +1001bb10: 68f0 ldr r0, [r6, #12] +1001bb12: 6130 str r0, [r6, #16] +1001bb14: 68f0 ldr r0, [r6, #12] +1001bb16: 3028 adds r0, #40 ; 0x28 +1001bb18: 4288 cmp r0, r1 +1001bb1a: d303 bcc.n 1001bb24 +1001bb1c: f000 f9e6 bl 1001beec <.text_124> +1001bb20: f000 f9d5 bl 1001bece <.text_122> +1001bb24: 4649 mov r1, r9 +1001bb26: 4650 mov r0, sl +1001bb28: f7ff fa89 bl 1001b03e +1001bb2c: f7ff bbbc b.w 1001b2a8 <.text_83> + +1001bb30 <.text_108>: +1001bb30: 1001e204 .word 0x1001e204 + +1001bb34 : +1001bb34: 02f25000 00000101 .P...... + +1001bb3c <.text_110>: +1001bb3c: f001 010f and.w r1, r1, #15 +1001bb40: ea41 1102 orr.w r1, r1, r2, lsl #4 +1001bb44: 8001 strh r1, [r0, #0] +1001bb46: 4770 bx lr + +1001bb48 <.text_111>: +1001bb48: f100 0428 add.w r4, r0, #40 ; 0x28 +1001bb4c: 2000 movs r0, #0 +1001bb4e: 8020 strh r0, [r4, #0] +1001bb50: 2206 movs r2, #6 +1001bb52: 4770 bx lr + +1001bb54 <.text_112>: +1001bb54: 9800 ldr r0, [sp, #0] +1001bb56: 9900 ldr r1, [sp, #0] +1001bb58: 1900 adds r0, r0, r4 +1001bb5a: 1c84 adds r4, r0, #2 +1001bb5c: 68f0 ldr r0, [r6, #12] +1001bb5e: 1c89 adds r1, r1, #2 +1001bb60: 1808 adds r0, r1, r0 +1001bb62: 60f0 str r0, [r6, #12] +1001bb64: 4770 bx lr + +1001bb66 <.text_113>: +1001bb66: aa00 add r2, sp, #0 +1001bb68: 9802 ldr r0, [sp, #8] +1001bb6a: 6f80 ldr r0, [r0, #120] ; 0x78 +1001bb6c: f1a0 030c sub.w r3, r0, #12 +1001bb70: 4770 bx lr + +1001bb72 <.text_114>: +1001bb72: 4620 mov r0, r4 +1001bb74: f7f4 be4b b.w 1001080e + +1001bb78 : +1001bb78: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +1001bb7c: b08f sub sp, #60 ; 0x3c +1001bb7e: 4680 mov r8, r0 +1001bb80: f508 50c4 add.w r0, r8, #6272 ; 0x1880 +1001bb84: 9006 str r0, [sp, #24] +1001bb86: f508 699d add.w r9, r8, #1256 ; 0x4e8 +1001bb8a: f608 1028 addw r0, r8, #2344 ; 0x928 +1001bb8e: 9005 str r0, [sp, #20] +1001bb90: 2600 movs r6, #0 +1001bb92: f509 7088 add.w r0, r9, #272 ; 0x110 +1001bb96: 9003 str r0, [sp, #12] +1001bb98: 9602 str r6, [sp, #8] +1001bb9a: f108 0a98 add.w sl, r8, #152 ; 0x98 +1001bb9e: 9805 ldr r0, [sp, #20] +1001bba0: f7ff fa05 bl 1001afae +1001bba4: ea5f 0b00 movs.w fp, r0 +1001bba8: f000 8171 beq.w 1001be8e +1001bbac: f7ff fea2 bl 1001b8f4 <.text_105> +1001bbb0: f8db 0080 ldr.w r0, [fp, #128] ; 0x80 +1001bbb4: f000 f9ae bl 1001bf14 <.text_130+0x4> +1001bbb8: f8db 0080 ldr.w r0, [fp, #128] ; 0x80 +1001bbbc: f100 0528 add.w r5, r0, #40 ; 0x28 +1001bbc0: 4650 mov r0, sl +1001bbc2: 802e strh r6, [r5, #0] +1001bbc4: f00a f811 bl 10025bea +1001bbc8: 4601 mov r1, r0 +1001bbca: 2206 movs r2, #6 +1001bbcc: 1d28 adds r0, r5, #4 +1001bbce: f7f4 fe1e bl 1001080e +1001bbd2: f7ff fe77 bl 1001b8c4 <.text_100> +1001bbd6: f105 000a add.w r0, r5, #10 +1001bbda: f7f4 fe18 bl 1001080e +1001bbde: f000 f98f bl 1001bf00 <.text_128> +1001bbe2: 4601 mov r1, r0 +1001bbe4: 2206 movs r2, #6 +1001bbe6: f105 0010 add.w r0, r5, #16 +1001bbea: f7f4 fe10 bl 1001080e +1001bbee: f105 0016 add.w r0, r5, #22 +1001bbf2: 7801 ldrb r1, [r0, #0] +1001bbf4: f8b9 200c ldrh.w r2, [r9, #12] +1001bbf8: f000 fa7d bl 1001c0f6 <.text_135> +1001bbfc: f8b9 000c ldrh.w r0, [r9, #12] +1001bc00: 1c40 adds r0, r0, #1 +1001bc02: f8a9 000c strh.w r0, [r9, #12] +1001bc06: 8828 ldrh r0, [r5, #0] +1001bc08: 4008 ands r0, r1 +1001bc0a: 8028 strh r0, [r5, #0] +1001bc0c: f825 0b18 strh.w r0, [r5], #24 +1001bc10: 2018 movs r0, #24 +1001bc12: 60e0 str r0, [r4, #12] +1001bc14: f10a 007c add.w r0, sl, #124 ; 0x7c +1001bc18: f002 fe5c bl 1001e8d4 +1001bc1c: 4601 mov r1, r0 +1001bc1e: 2202 movs r2, #2 +1001bc20: 4628 mov r0, r5 +1001bc22: f7f4 fdf4 bl 1001080e +1001bc26: 68e0 ldr r0, [r4, #12] +1001bc28: 1c80 adds r0, r0, #2 +1001bc2a: 60e0 str r0, [r4, #12] +1001bc2c: 1cad adds r5, r5, #2 +1001bc2e: 2003 movs r0, #3 +1001bc30: f8ad 0006 strh.w r0, [sp, #6] +1001bc34: 2202 movs r2, #2 +1001bc36: f10d 0106 add.w r1, sp, #6 +1001bc3a: 4628 mov r0, r5 +1001bc3c: f7f4 fde7 bl 1001080e +1001bc40: 68e0 ldr r0, [r4, #12] +1001bc42: 1c80 adds r0, r0, #2 +1001bc44: 60e0 str r0, [r4, #12] +1001bc46: f10a 0310 add.w r3, sl, #16 +1001bc4a: f000 f937 bl 1001bebc <.text_120> +1001bc4e: 4631 mov r1, r6 +1001bc50: f8da 200c ldr.w r2, [sl, #12] +1001bc54: 1ca8 adds r0, r5, #2 +1001bc56: f7fc fb93 bl 10018380 +1001bc5a: 4605 mov r5, r0 +1001bc5c: aa02 add r2, sp, #8 +1001bc5e: a90b add r1, sp, #44 ; 0x2c +1001bc60: 4640 mov r0, r8 +1001bc62: f009 feef bl 10025a44 +1001bc66: f899 000e ldrb.w r0, [r9, #14] +1001bc6a: 280e cmp r0, #14 +1001bc6c: bf04 itt eq +1001bc6e: 2004 moveq r0, #4 +1001bc70: 9002 streq r0, [sp, #8] +1001bc72: 2000 movs r0, #0 +1001bc74: eb00 010a add.w r1, r0, sl +1001bc78: f891 1064 ldrb.w r1, [r1, #100] ; 0x64 +1001bc7c: b111 cbz r1, 1001bc84 +1001bc7e: 1c40 adds r0, r0, #1 +1001bc80: 2810 cmp r0, #16 +1001bc82: d3f7 bcc.n 1001bc74 +1001bc84: 2700 movs r7, #0 +1001bc86: eb07 000a add.w r0, r7, sl +1001bc8a: f890 0064 ldrb.w r0, [r0, #100] ; 0x64 +1001bc8e: b1b0 cbz r0, 1001bcbe +1001bc90: 2100 movs r1, #0 +1001bc92: e000 b.n 1001bc96 +1001bc94: 1c49 adds r1, r1, #1 +1001bc96: 9a02 ldr r2, [sp, #8] +1001bc98: 4291 cmp r1, r2 +1001bc9a: d207 bcs.n 1001bcac +1001bc9c: ab0b add r3, sp, #44 ; 0x2c +1001bc9e: f040 0280 orr.w r2, r0, #128 ; 0x80 +1001bca2: 5ccb ldrb r3, [r1, r3] +1001bca4: f043 0380 orr.w r3, r3, #128 ; 0x80 +1001bca8: 429a cmp r2, r3 +1001bcaa: d1f3 bne.n 1001bc94 +1001bcac: 9a02 ldr r2, [sp, #8] +1001bcae: 4291 cmp r1, r2 +1001bcb0: d002 beq.n 1001bcb8 +1001bcb2: a907 add r1, sp, #28 +1001bcb4: 5470 strb r0, [r6, r1] +1001bcb6: 1c76 adds r6, r6, #1 +1001bcb8: 1c7f adds r7, r7, #1 +1001bcba: 2f10 cmp r7, #16 +1001bcbc: d3e3 bcc.n 1001bc86 +1001bcbe: b94e cbnz r6, 1001bcd4 +1001bcc0: f8db 1084 ldr.w r1, [fp, #132] ; 0x84 +1001bcc4: 9805 ldr r0, [sp, #20] +1001bcc6: f010 fc4b bl 1002c560 +1001bcca: 9805 ldr r0, [sp, #20] +1001bccc: 4659 mov r1, fp +1001bcce: f010 fca3 bl 1002c618 +1001bcd2: e0dc b.n 1001be8e +1001bcd4: 2e09 cmp r6, #9 +1001bcd6: f000 f8f1 bl 1001bebc <.text_120> +1001bcda: ab07 add r3, sp, #28 +1001bcdc: db09 blt.n 1001bcf2 +1001bcde: f000 f8f1 bl 1001bec4 <.text_121> +1001bce2: f104 010c add.w r1, r4, #12 +1001bce6: 9100 str r1, [sp, #0] +1001bce8: ab09 add r3, sp, #36 ; 0x24 +1001bcea: f1a6 0208 sub.w r2, r6, #8 +1001bcee: 2132 movs r1, #50 ; 0x32 +1001bcf0: e002 b.n 1001bcf8 +1001bcf2: 4632 mov r2, r6 +1001bcf4: 2101 movs r1, #1 +1001bcf6: 4628 mov r0, r5 +1001bcf8: f7fc fb42 bl 10018380 +1001bcfc: 4605 mov r5, r0 +1001bcfe: f8da 0078 ldr.w r0, [sl, #120] ; 0x78 +1001bd02: f10a 0688 add.w r6, sl, #136 ; 0x88 +1001bd06: f1a0 030c sub.w r3, r0, #12 +1001bd0a: aa04 add r2, sp, #16 +1001bd0c: 2130 movs r1, #48 ; 0x30 +1001bd0e: 4630 mov r0, r6 +1001bd10: f7f8 f8b6 bl 10013e80 +1001bd14: 0001 movs r1, r0 +1001bd16: d007 beq.n 1001bd28 +1001bd18: f000 f8d0 bl 1001bebc <.text_120> +1001bd1c: 1c8b adds r3, r1, #2 +1001bd1e: 9a04 ldr r2, [sp, #16] +1001bd20: 2130 movs r1, #48 ; 0x30 +1001bd22: f000 f8fc bl 1001bf1e <.text_131+0x2> +1001bd26: 4605 mov r5, r0 +1001bd28: f8d8 0454 ldr.w r0, [r8, #1108] ; 0x454 +1001bd2c: 2801 cmp r0, #1 +1001bd2e: d162 bne.n 1001bdf6 +1001bd30: f8da 0078 ldr.w r0, [sl, #120] ; 0x78 +1001bd34: f1a0 030c sub.w r3, r0, #12 +1001bd38: aa04 add r2, sp, #16 +1001bd3a: 212d movs r1, #45 ; 0x2d +1001bd3c: 4630 mov r0, r6 +1001bd3e: f7f8 f89f bl 10013e80 +1001bd42: 0007 movs r7, r0 +1001bd44: d057 beq.n 1001bdf6 +1001bd46: 4640 mov r0, r8 +1001bd48: f00a fadb bl 10026302 +1001bd4c: 2800 cmp r0, #0 +1001bd4e: d152 bne.n 1001bdf6 +1001bd50: 9803 ldr r0, [sp, #12] +1001bd52: f100 06da add.w r6, r0, #218 ; 0xda +1001bd56: 221a movs r2, #26 +1001bd58: 1cb9 adds r1, r7, #2 +1001bd5a: f001 fa6d bl 1001d238 <.text_182+0x4> +1001bd5e: 9803 ldr r0, [sp, #12] +1001bd60: f100 07ae add.w r7, r0, #174 ; 0xae +1001bd64: 9806 ldr r0, [sp, #24] +1001bd66: f890 0051 ldrb.w r0, [r0, #81] ; 0x51 +1001bd6a: 2800 cmp r0, #0 +1001bd6c: 8db8 ldrh r0, [r7, #44] ; 0x2c +1001bd6e: bf06 itte eq +1001bd70: f64f 71bd movweq r1, #65469 ; 0xffbd +1001bd74: 4008 andeq r0, r1 +1001bd76: f040 0002 orrne.w r0, r0, #2 +1001bd7a: 85b8 strh r0, [r7, #44] ; 0x2c +1001bd7c: aa01 add r2, sp, #4 +1001bd7e: 8db8 ldrh r0, [r7, #44] ; 0x2c +1001bd80: f040 000c orr.w r0, r0, #12 +1001bd84: 85b8 strh r0, [r7, #44] ; 0x2c +1001bd86: 2116 movs r1, #22 +1001bd88: 4640 mov r0, r8 +1001bd8a: f7fb facb bl 10017324 +1001bd8e: 9803 ldr r0, [sp, #12] +1001bd90: 9906 ldr r1, [sp, #24] +1001bd92: f89d 2004 ldrb.w r2, [sp, #4] +1001bd96: 30dd adds r0, #221 ; 0xdd +1001bd98: 3151 adds r1, #81 ; 0x51 +1001bd9a: 2a03 cmp r2, #3 +1001bd9c: d109 bne.n 1001bdb2 +1001bd9e: 7889 ldrb r1, [r1, #2] +1001bda0: b119 cbz r1, 1001bdaa +1001bda2: 8db9 ldrh r1, [r7, #44] ; 0x2c +1001bda4: f441 7180 orr.w r1, r1, #256 ; 0x100 +1001bda8: 85b9 strh r1, [r7, #44] ; 0x2c +1001bdaa: 2210 movs r2, #16 +1001bdac: f20f 01e4 addw r1, pc, #228 ; 0xe4 +1001bdb0: e017 b.n 1001bde2 +1001bdb2: 788a ldrb r2, [r1, #2] +1001bdb4: 2a03 cmp r2, #3 +1001bdb6: d00d beq.n 1001bdd4 +1001bdb8: f899 3011 ldrb.w r3, [r9, #17] +1001bdbc: ea5f 7903 movs.w r9, r3, lsl #28 +1001bdc0: d501 bpl.n 1001bdc6 +1001bdc2: 2a01 cmp r2, #1 +1001bdc4: d006 beq.n 1001bdd4 +1001bdc6: 06db lsls r3, r3, #27 +1001bdc8: d501 bpl.n 1001bdce +1001bdca: 2a02 cmp r2, #2 +1001bdcc: d002 beq.n 1001bdd4 +1001bdce: 79c9 ldrb r1, [r1, #7] +1001bdd0: 2901 cmp r1, #1 +1001bdd2: d103 bne.n 1001bddc +1001bdd4: 8db9 ldrh r1, [r7, #44] ; 0x2c +1001bdd6: f441 7100 orr.w r1, r1, #512 ; 0x200 +1001bdda: 85b9 strh r1, [r7, #44] ; 0x2c +1001bddc: 2210 movs r2, #16 +1001bdde: f20f 01c4 addw r1, pc, #196 ; 0xc4 +1001bde2: f7f4 fd14 bl 1001080e +1001bde6: 9a04 ldr r2, [sp, #16] +1001bde8: f000 f868 bl 1001bebc <.text_120> +1001bdec: 4633 mov r3, r6 +1001bdee: 212d movs r1, #45 ; 0x2d +1001bdf0: f000 f895 bl 1001bf1e <.text_131+0x2> +1001bdf4: 4605 mov r5, r0 +1001bdf6: 270c movs r7, #12 +1001bdf8: f20f 09b8 addw r9, pc, #184 ; 0xb8 +1001bdfc: e02a b.n 1001be54 +1001bdfe: eb07 000a add.w r0, r7, sl +1001be02: f100 067c add.w r6, r0, #124 ; 0x7c +1001be06: 7830 ldrb r0, [r6, #0] +1001be08: 28dd cmp r0, #221 ; 0xdd +1001be0a: d120 bne.n 1001be4e +1001be0c: 2204 movs r2, #4 +1001be0e: f20f 01a8 addw r1, pc, #168 ; 0xa8 +1001be12: f000 f87a bl 1001bf0a <.text_129+0x4> +1001be16: b970 cbnz r0, 1001be36 +1001be18: 2204 movs r2, #4 +1001be1a: 4938 ldr r1, [pc, #224] ; (1001befc <.text_127>) +1001be1c: f000 f875 bl 1001bf0a <.text_129+0x4> +1001be20: b948 cbnz r0, 1001be36 +1001be22: f000 f870 bl 1001bf06 <.text_129> +1001be26: 2800 cmp r0, #0 +1001be28: bf1e ittt ne +1001be2a: f641 0079 movwne r0, #6265 ; 0x1879 +1001be2e: f810 0008 ldrbne.w r0, [r0, r8] +1001be32: 2800 cmpne r0, #0 +1001be34: d00b beq.n 1001be4e +1001be36: f000 f866 bl 1001bf06 <.text_129> +1001be3a: b108 cbz r0, 1001be40 +1001be3c: 200e movs r0, #14 +1001be3e: 7070 strb r0, [r6, #1] +1001be40: f000 f83c bl 1001bebc <.text_120> +1001be44: 1cb3 adds r3, r6, #2 +1001be46: 7872 ldrb r2, [r6, #1] +1001be48: f000 f868 bl 1001bf1c <.text_131> +1001be4c: 4605 mov r5, r0 +1001be4e: 7870 ldrb r0, [r6, #1] +1001be50: 1c80 adds r0, r0, #2 +1001be52: 19c7 adds r7, r0, r7 +1001be54: f8da 0078 ldr.w r0, [sl, #120] ; 0x78 +1001be58: 4287 cmp r7, r0 +1001be5a: d3d0 bcc.n 1001bdfe +1001be5c: 9803 ldr r0, [sp, #12] +1001be5e: f890 00ae ldrb.w r0, [r0, #174] ; 0xae +1001be62: 2801 cmp r0, #1 +1001be64: d105 bne.n 1001be72 +1001be66: f000 f829 bl 1001bebc <.text_120> +1001be6a: 2206 movs r2, #6 +1001be6c: 4b22 ldr r3, [pc, #136] ; (1001bef8 <.text_126>) +1001be6e: f000 f855 bl 1001bf1c <.text_131> +1001be72: 68e0 ldr r0, [r4, #12] +1001be74: 6120 str r0, [r4, #16] +1001be76: f240 6153 movw r1, #1619 ; 0x653 +1001be7a: 68e0 ldr r0, [r4, #12] +1001be7c: 3028 adds r0, #40 ; 0x28 +1001be7e: 4288 cmp r0, r1 +1001be80: d303 bcc.n 1001be8a +1001be82: f000 f833 bl 1001beec <.text_124> +1001be86: f000 f822 bl 1001bece <.text_122> +1001be8a: f7ff fd2f bl 1001b8ec <.text_104> +1001be8e: b00f add sp, #60 ; 0x3c +1001be90: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1001be94 : +1001be94: 00ff 0000 0001 0000 0000 0000 0000 0000 ................ + +1001bea4 : +1001bea4: ffff 0000 0001 0000 0000 0000 0000 0000 ................ + +1001beb4 : +1001beb4: 5000 04f2 .P.. + +1001beb8 : +1001beb8: 5000 01f2 .P.. + +1001bebc <.text_120>: +1001bebc: f104 000c add.w r0, r4, #12 +1001bec0: 9000 str r0, [sp, #0] +1001bec2: 4770 bx lr + +1001bec4 <.text_121>: +1001bec4: 2208 movs r2, #8 +1001bec6: 2101 movs r1, #1 +1001bec8: 4628 mov r0, r5 +1001beca: f7fc ba59 b.w 10018380 + +1001bece <.text_122>: +1001bece: f20f 0008 addw r0, pc, #8 +1001bed2: f7f0 ba16 b.w 1000c302 + ... + +1001bed8 : +1001bed8: 5452 384c 3931 4135 445b 6972 6576 5d72 RTL8195A[Driver] +1001bee8: 203a 0000 : .. + +1001beec <.text_124>: +1001beec: a001 add r0, pc, #4 ; (adr r0, 1001bef4 <.text_125>) +1001beee: f7f0 ba08 b.w 1000c302 + ... + +1001bef4 <.text_125>: +1001bef4: 00000d0a .word 0x00000d0a + +1001bef8 <.text_126>: +1001bef8: 10004474 .word 0x10004474 + +1001befc <.text_127>: +1001befc: 1001e460 .word 0x1001e460 + +1001bf00 <.text_128>: +1001bf00: 4650 mov r0, sl +1001bf02: f009 be72 b.w 10025bea + +1001bf06 <.text_129>: +1001bf06: 2204 movs r2, #4 +1001bf08: 4649 mov r1, r9 +1001bf0a: 1cb0 adds r0, r6, #2 +1001bf0c: f7f4 bc89 b.w 10010822 + +1001bf10 <.text_130>: +1001bf10: f8d9 0080 ldr.w r0, [r9, #128] ; 0x80 +1001bf14: 2268 movs r2, #104 ; 0x68 +1001bf16: 2100 movs r1, #0 +1001bf18: f7f4 bc8e b.w 10010838 + +1001bf1c <.text_131>: +1001bf1c: 21dd movs r1, #221 ; 0xdd +1001bf1e: 4628 mov r0, r5 +1001bf20: f7fc ba2e b.w 10018380 + +1001bf24 : +1001bf24: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1001bf28: 0004 movs r4, r0 +1001bf2a: 4689 mov r9, r1 +1001bf2c: d052 beq.n 1001bfd4 +1001bf2e: f504 669d add.w r6, r4, #1256 ; 0x4e8 +1001bf32: f506 7b88 add.w fp, r6, #272 ; 0x110 +1001bf36: f104 0a98 add.w sl, r4, #152 ; 0x98 +1001bf3a: f000 f93a bl 1001c1b2 <.text_140> +1001bf3e: ea5f 0800 movs.w r8, r0 +1001bf42: d047 beq.n 1001bfd4 +1001bf44: f108 0508 add.w r5, r8, #8 +1001bf48: 4629 mov r1, r5 +1001bf4a: f000 f92f bl 1001c1ac <.text_139+0x2> +1001bf4e: 2000 movs r0, #0 +1001bf50: f885 0064 strb.w r0, [r5, #100] ; 0x64 +1001bf54: 2268 movs r2, #104 ; 0x68 +1001bf56: f8d8 0080 ldr.w r0, [r8, #128] ; 0x80 +1001bf5a: f7ff ffdc bl 1001bf16 <.text_130+0x6> +1001bf5e: f8d8 0080 ldr.w r0, [r8, #128] ; 0x80 +1001bf62: f100 0728 add.w r7, r0, #40 ; 0x28 +1001bf66: 2000 movs r0, #0 +1001bf68: 8038 strh r0, [r7, #0] +1001bf6a: f8db 0000 ldr.w r0, [fp] +1001bf6e: f000 0103 and.w r1, r0, #3 +1001bf72: 2903 cmp r1, #3 +1001bf74: bf08 it eq +1001bf76: f44f 7000 moveq.w r0, #512 ; 0x200 +1001bf7a: d004 beq.n 1001bf86 +1001bf7c: f000 f8c4 bl 1001c108 <.text_136+0x2> +1001bf80: d102 bne.n 1001bf88 +1001bf82: f44f 7080 mov.w r0, #256 ; 0x100 +1001bf86: 8038 strh r0, [r7, #0] +1001bf88: f1b9 0f00 cmp.w r9, #0 +1001bf8c: d003 beq.n 1001bf96 +1001bf8e: 8838 ldrh r0, [r7, #0] +1001bf90: f440 5080 orr.w r0, r0, #4096 ; 0x1000 +1001bf94: 8038 strh r0, [r7, #0] +1001bf96: f7ff ffb3 bl 1001bf00 <.text_128> +1001bf9a: f000 f81d bl 1001bfd8 <.text_133> +1001bf9e: f000 f912 bl 1001c1c6 <.text_142> +1001bfa2: f7ff ffad bl 1001bf00 <.text_128> +1001bfa6: f000 f908 bl 1001c1ba <.text_141> +1001bfaa: f7ff fb8d bl 1001b6c8 <.text_95> +1001bfae: f240 6153 movw r1, #1619 ; 0x653 +1001bfb2: f040 0048 orr.w r0, r0, #72 ; 0x48 +1001bfb6: 8038 strh r0, [r7, #0] +1001bfb8: 2018 movs r0, #24 +1001bfba: 60e8 str r0, [r5, #12] +1001bfbc: 6128 str r0, [r5, #16] +1001bfbe: 68e8 ldr r0, [r5, #12] +1001bfc0: 3028 adds r0, #40 ; 0x28 +1001bfc2: 4288 cmp r0, r1 +1001bfc4: d303 bcc.n 1001bfce +1001bfc6: f7ff ff91 bl 1001beec <.text_124> +1001bfca: f7ff ff80 bl 1001bece <.text_122> +1001bfce: 4641 mov r1, r8 +1001bfd0: 4620 mov r0, r4 +1001bfd2: e09d b.n 1001c110 <.text_137> +1001bfd4: e8bd 8ff1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1001bfd8 <.text_133>: +1001bfd8: 4601 mov r1, r0 +1001bfda: 2206 movs r2, #6 +1001bfdc: 1d38 adds r0, r7, #4 +1001bfde: f7f4 bc16 b.w 1001080e + +1001bfe2 : +1001bfe2: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1001bfe6: 4681 mov r9, r0 +1001bfe8: f509 679d add.w r7, r9, #1256 ; 0x4e8 +1001bfec: f507 7088 add.w r0, r7, #272 ; 0x110 +1001bff0: 9000 str r0, [sp, #0] +1001bff2: 468a mov sl, r1 +1001bff4: 4693 mov fp, r2 +1001bff6: f609 1028 addw r0, r9, #2344 ; 0x928 +1001bffa: f7fe ffd8 bl 1001afae +1001bffe: ea5f 0800 movs.w r8, r0 +1001c002: d076 beq.n 1001c0f2 +1001c004: f108 0408 add.w r4, r8, #8 +1001c008: 4621 mov r1, r4 +1001c00a: 4648 mov r0, r9 +1001c00c: f7fe ffec bl 1001afe8 +1001c010: 8960 ldrh r0, [r4, #10] +1001c012: 1c80 adds r0, r0, #2 +1001c014: 8160 strh r0, [r4, #10] +1001c016: f104 055d add.w r5, r4, #93 ; 0x5d +1001c01a: 2001 movs r0, #1 +1001c01c: f884 0056 strb.w r0, [r4, #86] ; 0x56 +1001c020: 7128 strb r0, [r5, #4] +1001c022: 2268 movs r2, #104 ; 0x68 +1001c024: 2000 movs r0, #0 +1001c026: f884 003a strb.w r0, [r4, #58] ; 0x3a +1001c02a: f884 005d strb.w r0, [r4, #93] ; 0x5d +1001c02e: 2100 movs r1, #0 +1001c030: f8d8 0080 ldr.w r0, [r8, #128] ; 0x80 +1001c034: f7f4 fc00 bl 10010838 +1001c038: f8d8 0080 ldr.w r0, [r8, #128] ; 0x80 +1001c03c: f100 0628 add.w r6, r0, #40 ; 0x28 +1001c040: 2000 movs r0, #0 +1001c042: 8030 strh r0, [r6, #0] +1001c044: 9800 ldr r0, [sp, #0] +1001c046: 6800 ldr r0, [r0, #0] +1001c048: f000 0103 and.w r1, r0, #3 +1001c04c: 2903 cmp r1, #3 +1001c04e: bf08 it eq +1001c050: f44f 7000 moveq.w r0, #512 ; 0x200 +1001c054: d004 beq.n 1001c060 +1001c056: f000 f857 bl 1001c108 <.text_136+0x2> +1001c05a: d102 bne.n 1001c062 +1001c05c: f44f 7080 mov.w r0, #256 ; 0x100 +1001c060: 8030 strh r0, [r6, #0] +1001c062: f894 005d ldrb.w r0, [r4, #93] ; 0x5d +1001c066: b118 cbz r0, 1001c070 +1001c068: 8830 ldrh r0, [r6, #0] +1001c06a: f440 5000 orr.w r0, r0, #8192 ; 0x2000 +1001c06e: 8030 strh r0, [r6, #0] +1001c070: f00b 020f and.w r2, fp, #15 +1001c074: 8960 ldrh r0, [r4, #10] +1001c076: 1980 adds r0, r0, r6 +1001c078: f830 1d02 ldrh.w r1, [r0, #-2]! +1001c07c: 4311 orrs r1, r2 +1001c07e: 8001 strh r1, [r0, #0] +1001c080: 792a ldrb r2, [r5, #4] +1001c082: f002 0201 and.w r2, r2, #1 +1001c086: ea41 1102 orr.w r1, r1, r2, lsl #4 +1001c08a: 8001 strh r1, [r0, #0] +1001c08c: f894 203a ldrb.w r2, [r4, #58] ; 0x3a +1001c090: f002 0203 and.w r2, r2, #3 +1001c094: ea41 1142 orr.w r1, r1, r2, lsl #5 +1001c098: 8001 strh r1, [r0, #0] +1001c09a: 2206 movs r2, #6 +1001c09c: 4651 mov r1, sl +1001c09e: 1d30 adds r0, r6, #4 +1001c0a0: f7f4 fbb5 bl 1001080e +1001c0a4: f000 fac6 bl 1001c634 <.text_155> +1001c0a8: f109 0098 add.w r0, r9, #152 ; 0x98 +1001c0ac: f009 fd9d bl 10025bea +1001c0b0: f000 faba bl 1001c628 <.text_154> +1001c0b4: f106 0016 add.w r0, r6, #22 +1001c0b8: 7801 ldrb r1, [r0, #0] +1001c0ba: 89ba ldrh r2, [r7, #12] +1001c0bc: f000 f81b bl 1001c0f6 <.text_135> +1001c0c0: 89b8 ldrh r0, [r7, #12] +1001c0c2: 1c40 adds r0, r0, #1 +1001c0c4: 81b8 strh r0, [r7, #12] +1001c0c6: 8830 ldrh r0, [r6, #0] +1001c0c8: 4008 ands r0, r1 +1001c0ca: 8030 strh r0, [r6, #0] +1001c0cc: f240 6153 movw r1, #1619 ; 0x653 +1001c0d0: f040 00c8 orr.w r0, r0, #200 ; 0xc8 +1001c0d4: 8030 strh r0, [r6, #0] +1001c0d6: 201a movs r0, #26 +1001c0d8: 60e0 str r0, [r4, #12] +1001c0da: 6120 str r0, [r4, #16] +1001c0dc: 68e0 ldr r0, [r4, #12] +1001c0de: 3028 adds r0, #40 ; 0x28 +1001c0e0: 4288 cmp r0, r1 +1001c0e2: d303 bcc.n 1001c0ec +1001c0e4: f7ff ff02 bl 1001beec <.text_124> +1001c0e8: f7ff fef1 bl 1001bece <.text_122> +1001c0ec: 4641 mov r1, r8 +1001c0ee: 4648 mov r0, r9 +1001c0f0: e00e b.n 1001c110 <.text_137> +1001c0f2: e8bd 8ff1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1001c0f6 <.text_135>: +1001c0f6: f001 010f and.w r1, r1, #15 +1001c0fa: ea41 1102 orr.w r1, r1, r2, lsl #4 +1001c0fe: 8001 strh r1, [r0, #0] +1001c100: f64f 7103 movw r1, #65283 ; 0xff03 +1001c104: 4770 bx lr + +1001c106 <.text_136>: +1001c106: 7820 ldrb r0, [r4, #0] +1001c108: f000 0003 and.w r0, r0, #3 +1001c10c: 2802 cmp r0, #2 +1001c10e: 4770 bx lr + +1001c110 <.text_137>: +1001c110: e8bd 4ff4 ldmia.w sp!, {r2, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1001c114: f7fe bf93 b.w 1001b03e + +1001c118 : +1001c118: e92d 43f4 stmdb sp!, {r2, r4, r5, r6, r7, r8, r9, lr} +1001c11c: 4604 mov r4, r0 +1001c11e: 4689 mov r9, r1 +1001c120: f504 659d add.w r5, r4, #1256 ; 0x4e8 +1001c124: f000 f845 bl 1001c1b2 <.text_140> +1001c128: ea5f 0800 movs.w r8, r0 +1001c12c: d03b beq.n 1001c1a6 +1001c12e: f108 0608 add.w r6, r8, #8 +1001c132: f000 f83a bl 1001c1aa <.text_139> +1001c136: 2000 movs r0, #0 +1001c138: f886 0064 strb.w r0, [r6, #100] ; 0x64 +1001c13c: 2268 movs r2, #104 ; 0x68 +1001c13e: f8d8 0080 ldr.w r0, [r8, #128] ; 0x80 +1001c142: f7ff fee8 bl 1001bf16 <.text_130+0x6> +1001c146: f8d8 0080 ldr.w r0, [r8, #128] ; 0x80 +1001c14a: f000 f967 bl 1001c41c <.text_148> +1001c14e: 4649 mov r1, r9 +1001c150: 1d38 adds r0, r7, #4 +1001c152: f7f4 fb5c bl 1001080e +1001c156: f000 f836 bl 1001c1c6 <.text_142> +1001c15a: f000 f965 bl 1001c428 <.text_149> +1001c15e: f000 f82c bl 1001c1ba <.text_141> +1001c162: f000 f948 bl 1001c3f6 <.text_146> +1001c166: f106 050c add.w r5, r6, #12 +1001c16a: f7ff fabb bl 1001b6e4 <.text_96> +1001c16e: 462b mov r3, r5 +1001c170: f040 00c0 orr.w r0, r0, #192 ; 0xc0 +1001c174: 8038 strh r0, [r7, #0] +1001c176: aa00 add r2, sp, #0 +1001c178: 2018 movs r0, #24 +1001c17a: 60f0 str r0, [r6, #12] +1001c17c: 2102 movs r1, #2 +1001c17e: a800 add r0, sp, #0 +1001c180: 8800 ldrh r0, [r0, #0] +1001c182: 9000 str r0, [sp, #0] +1001c184: f107 0018 add.w r0, r7, #24 +1001c188: f7fd fc16 bl 100199b8 +1001c18c: 68f0 ldr r0, [r6, #12] +1001c18e: 6068 str r0, [r5, #4] +1001c190: f000 f92b bl 1001c3ea <.text_145> +1001c194: d303 bcc.n 1001c19e +1001c196: f7ff fea9 bl 1001beec <.text_124> +1001c19a: f7ff fe98 bl 1001bece <.text_122> +1001c19e: 4641 mov r1, r8 +1001c1a0: 4620 mov r0, r4 +1001c1a2: f7fe ff4c bl 1001b03e +1001c1a6: e8bd 83f1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, pc} + +1001c1aa <.text_139>: +1001c1aa: 4631 mov r1, r6 +1001c1ac: 4620 mov r0, r4 +1001c1ae: f7fe bf1b b.w 1001afe8 + +1001c1b2 <.text_140>: +1001c1b2: f604 1028 addw r0, r4, #2344 ; 0x928 +1001c1b6: f7fe befa b.w 1001afae + +1001c1ba <.text_141>: +1001c1ba: 4601 mov r1, r0 +1001c1bc: 2206 movs r2, #6 +1001c1be: f107 0010 add.w r0, r7, #16 +1001c1c2: f7f4 bb24 b.w 1001080e + +1001c1c6 <.text_142>: +1001c1c6: f504 51c8 add.w r1, r4, #6400 ; 0x1900 +1001c1ca: 2206 movs r2, #6 +1001c1cc: 3195 adds r1, #149 ; 0x95 +1001c1ce: f107 000a add.w r0, r7, #10 +1001c1d2: f7f4 bb1c b.w 1001080e + +1001c1d6 : +1001c1d6: e92d 4ffc stmdb sp!, {r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1001c1da: b085 sub sp, #20 +1001c1dc: 4604 mov r4, r0 +1001c1de: 2003 movs r0, #3 +1001c1e0: f88d 000e strb.w r0, [sp, #14] +1001c1e4: f504 659d add.w r5, r4, #1256 ; 0x4e8 +1001c1e8: f504 5088 add.w r0, r4, #4352 ; 0x1100 +1001c1ec: 3028 adds r0, #40 ; 0x28 +1001c1ee: 9004 str r0, [sp, #16] +1001c1f0: 468b mov fp, r1 +1001c1f2: f505 7a88 add.w sl, r5, #272 ; 0x110 +1001c1f6: f504 58c4 add.w r8, r4, #6272 ; 0x1880 +1001c1fa: f7ff ffda bl 1001c1b2 <.text_140> +1001c1fe: ea5f 0900 movs.w r9, r0 +1001c202: f000 80ed beq.w 1001c3e0 +1001c206: f109 0608 add.w r6, r9, #8 +1001c20a: f7ff ffce bl 1001c1aa <.text_139> +1001c20e: f7ff fe7f bl 1001bf10 <.text_130> +1001c212: f8d9 0080 ldr.w r0, [r9, #128] ; 0x80 +1001c216: f000 f901 bl 1001c41c <.text_148> +1001c21a: 4659 mov r1, fp +1001c21c: 1d38 adds r0, r7, #4 +1001c21e: f7f4 faf6 bl 1001080e +1001c222: f7ff ffd0 bl 1001c1c6 <.text_142> +1001c226: f000 f8ff bl 1001c428 <.text_149> +1001c22a: f7ff ffc6 bl 1001c1ba <.text_141> +1001c22e: f000 f8e2 bl 1001c3f6 <.text_146> +1001c232: f106 030c add.w r3, r6, #12 +1001c236: f7ff fa55 bl 1001b6e4 <.text_96> +1001c23a: f10d 020e add.w r2, sp, #14 +1001c23e: f040 00d0 orr.w r0, r0, #208 ; 0xd0 +1001c242: 8038 strh r0, [r7, #0] +1001c244: 2101 movs r1, #1 +1001c246: 2018 movs r0, #24 +1001c248: 60f0 str r0, [r6, #12] +1001c24a: f107 0018 add.w r0, r7, #24 +1001c24e: f7fd fbb3 bl 100199b8 +1001c252: f106 030c add.w r3, r6, #12 +1001c256: aa05 add r2, sp, #20 +1001c258: 2101 movs r1, #1 +1001c25a: f7fd fbad bl 100199b8 +1001c25e: 4607 mov r7, r0 +1001c260: f89d 000e ldrb.w r0, [sp, #14] +1001c264: 2803 cmp r0, #3 +1001c266: d108 bne.n 1001c27a +1001c268: f89d 0014 ldrb.w r0, [sp, #20] +1001c26c: f10a 05be add.w r5, sl, #190 ; 0xbe +1001c270: b120 cbz r0, 1001c27c +1001c272: 2802 cmp r0, #2 +1001c274: f000 8093 beq.w 1001c39e +1001c278: d344 bcc.n 1001c304 +1001c27a: e0a4 b.n 1001c3c6 +1001c27c: f89a 00be ldrb.w r0, [sl, #190] ; 0xbe +1001c280: 1c40 adds r0, r0, #1 +1001c282: f88a 00be strb.w r0, [sl, #190] ; 0xbe +1001c286: b2c0 uxtb r0, r0 +1001c288: 2800 cmp r0, #0 +1001c28a: d0f7 beq.n 1001c27c +1001c28c: f106 030c add.w r3, r6, #12 +1001c290: 462a mov r2, r5 +1001c292: 2101 movs r1, #1 +1001c294: 4638 mov r0, r7 +1001c296: f7fd fb8f bl 100199b8 +1001c29a: f8bd 1018 ldrh.w r1, [sp, #24] +1001c29e: f001 010f and.w r1, r1, #15 +1001c2a2: 0089 lsls r1, r1, #2 +1001c2a4: f441 5180 orr.w r1, r1, #4096 ; 0x1000 +1001c2a8: f041 0102 orr.w r1, r1, #2 +1001c2ac: f8ad 1000 strh.w r1, [sp] +1001c2b0: f106 030c add.w r3, r6, #12 +1001c2b4: aa00 add r2, sp, #0 +1001c2b6: f000 f895 bl 1001c3e4 <.text_144> +1001c2ba: f241 3188 movw r1, #5000 ; 0x1388 +1001c2be: f8ad 100a strh.w r1, [sp, #10] +1001c2c2: f106 030c add.w r3, r6, #12 +1001c2c6: f10d 020a add.w r2, sp, #10 +1001c2ca: f000 f88b bl 1001c3e4 <.text_144> +1001c2ce: 4607 mov r7, r0 +1001c2d0: 9804 ldr r0, [sp, #16] +1001c2d2: 4659 mov r1, fp +1001c2d4: f008 ff6a bl 100251ac +1001c2d8: b178 cbz r0, 1001c2fa +1001c2da: f8bd 1018 ldrh.w r1, [sp, #24] +1001c2de: f001 0107 and.w r1, r1, #7 +1001c2e2: eb00 0041 add.w r0, r0, r1, lsl #1 +1001c2e6: f8b0 1094 ldrh.w r1, [r0, #148] ; 0x94 +1001c2ea: 0509 lsls r1, r1, #20 +1001c2ec: 0d09 lsrs r1, r1, #20 +1001c2ee: 1c49 adds r1, r1, #1 +1001c2f0: f8a0 11d4 strh.w r1, [r0, #468] ; 0x1d4 +1001c2f4: 0108 lsls r0, r1, #4 +1001c2f6: f8ad 0002 strh.w r0, [sp, #2] +1001c2fa: f106 030c add.w r3, r6, #12 +1001c2fe: f10d 0202 add.w r2, sp, #2 +1001c302: e049 b.n 1001c398 +1001c304: f106 030c add.w r3, r6, #12 +1001c308: f10a 02c1 add.w r2, sl, #193 ; 0xc1 +1001c30c: 2101 movs r1, #1 +1001c30e: 4638 mov r0, r7 +1001c310: f7fd fb52 bl 100199b8 +1001c314: f106 030c add.w r3, r6, #12 +1001c318: aa06 add r2, sp, #24 +1001c31a: f000 f863 bl 1001c3e4 <.text_144> +1001c31e: 4607 mov r7, r0 +1001c320: aa01 add r2, sp, #4 +1001c322: 210b movs r1, #11 +1001c324: 4620 mov r0, r4 +1001c326: f7fb f812 bl 1001734e +1001c32a: 9801 ldr r0, [sp, #4] +1001c32c: 2803 cmp r0, #3 +1001c32e: d013 beq.n 1001c358 +1001c330: 2802 cmp r0, #2 +1001c332: d104 bne.n 1001c33e +1001c334: f000 f86e bl 1001c414 <.text_147> +1001c338: f440 6000 orr.w r0, r0, #2048 ; 0x800 +1001c33c: e010 b.n 1001c360 +1001c33e: 2801 cmp r0, #1 +1001c340: d104 bne.n 1001c34c +1001c342: f000 f867 bl 1001c414 <.text_147> +1001c346: f440 6080 orr.w r0, r0, #1024 ; 0x400 +1001c34a: e009 b.n 1001c360 +1001c34c: b920 cbnz r0, 1001c358 +1001c34e: f000 f861 bl 1001c414 <.text_147> +1001c352: f440 7000 orr.w r0, r0, #512 ; 0x200 +1001c356: e003 b.n 1001c360 +1001c358: f000 f85c bl 1001c414 <.text_147> +1001c35c: f440 5080 orr.w r0, r0, #4096 ; 0x1000 +1001c360: f8ad 0000 strh.w r0, [sp] +1001c364: f898 0054 ldrb.w r0, [r8, #84] ; 0x54 +1001c368: b928 cbnz r0, 1001c376 +1001c36a: f8bd 0000 ldrh.w r0, [sp] +1001c36e: f64f 71fe movw r1, #65534 ; 0xfffe +1001c372: 4008 ands r0, r1 +1001c374: e005 b.n 1001c382 +1001c376: 2801 cmp r0, #1 +1001c378: d105 bne.n 1001c386 +1001c37a: f8bd 0000 ldrh.w r0, [sp] +1001c37e: f040 0001 orr.w r0, r0, #1 +1001c382: f8ad 0000 strh.w r0, [sp] +1001c386: f000 f853 bl 1001c430 <.text_150> +1001c38a: 4607 mov r7, r0 +1001c38c: 88e8 ldrh r0, [r5, #6] +1001c38e: f8ad 0008 strh.w r0, [sp, #8] +1001c392: f106 030c add.w r3, r6, #12 +1001c396: aa02 add r2, sp, #8 +1001c398: 2102 movs r1, #2 +1001c39a: 4638 mov r0, r7 +1001c39c: e011 b.n 1001c3c2 +1001c39e: f8bd 0018 ldrh.w r0, [sp, #24] +1001c3a2: f000 001f and.w r0, r0, #31 +1001c3a6: 00c0 lsls r0, r0, #3 +1001c3a8: f8ad 0000 strh.w r0, [sp] +1001c3ac: f000 f840 bl 1001c430 <.text_150> +1001c3b0: 4605 mov r5, r0 +1001c3b2: 2025 movs r0, #37 ; 0x25 +1001c3b4: f8ad 000c strh.w r0, [sp, #12] +1001c3b8: f106 030c add.w r3, r6, #12 +1001c3bc: aa03 add r2, sp, #12 +1001c3be: 2102 movs r1, #2 +1001c3c0: 4628 mov r0, r5 +1001c3c2: f7fd faf9 bl 100199b8 +1001c3c6: 68f0 ldr r0, [r6, #12] +1001c3c8: 6130 str r0, [r6, #16] +1001c3ca: f000 f80e bl 1001c3ea <.text_145> +1001c3ce: d303 bcc.n 1001c3d8 +1001c3d0: f7ff fd8c bl 1001beec <.text_124> +1001c3d4: f7ff fd7b bl 1001bece <.text_122> +1001c3d8: 4649 mov r1, r9 +1001c3da: 4620 mov r0, r4 +1001c3dc: f7fe fe2f bl 1001b03e +1001c3e0: f7fe bf62 b.w 1001b2a8 <.text_83> + +1001c3e4 <.text_144>: +1001c3e4: 2102 movs r1, #2 +1001c3e6: f7fd bae7 b.w 100199b8 + +1001c3ea <.text_145>: +1001c3ea: f240 6153 movw r1, #1619 ; 0x653 +1001c3ee: 68f0 ldr r0, [r6, #12] +1001c3f0: 3028 adds r0, #40 ; 0x28 +1001c3f2: 4288 cmp r0, r1 +1001c3f4: 4770 bx lr + +1001c3f6 <.text_146>: +1001c3f6: f107 0016 add.w r0, r7, #22 +1001c3fa: 7801 ldrb r1, [r0, #0] +1001c3fc: 89aa ldrh r2, [r5, #12] +1001c3fe: f001 010f and.w r1, r1, #15 +1001c402: ea41 1102 orr.w r1, r1, r2, lsl #4 +1001c406: 8001 strh r1, [r0, #0] +1001c408: f64f 7103 movw r1, #65283 ; 0xff03 +1001c40c: 89a8 ldrh r0, [r5, #12] +1001c40e: 1c40 adds r0, r0, #1 +1001c410: 81a8 strh r0, [r5, #12] +1001c412: 4770 bx lr + +1001c414 <.text_147>: +1001c414: 7928 ldrb r0, [r5, #4] +1001c416: f000 003f and.w r0, r0, #63 ; 0x3f +1001c41a: 4770 bx lr + +1001c41c <.text_148>: +1001c41c: f100 0728 add.w r7, r0, #40 ; 0x28 +1001c420: 2000 movs r0, #0 +1001c422: 8038 strh r0, [r7, #0] +1001c424: 2206 movs r2, #6 +1001c426: 4770 bx lr + +1001c428 <.text_149>: +1001c428: f104 0098 add.w r0, r4, #152 ; 0x98 +1001c42c: f009 bbdd b.w 10025bea + +1001c430 <.text_150>: +1001c430: f106 030c add.w r3, r6, #12 +1001c434: aa00 add r2, sp, #0 +1001c436: 2102 movs r1, #2 +1001c438: 4638 mov r0, r7 +1001c43a: f7fd babd b.w 100199b8 + +1001c43e : +1001c43e: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +1001c442: 4681 mov r9, r0 +1001c444: b0a7 sub sp, #156 ; 0x9c +1001c446: f109 050c add.w r5, r9, #12 +1001c44a: f105 0020 add.w r0, r5, #32 +1001c44e: 9002 str r0, [sp, #8] +1001c450: f509 689d add.w r8, r9, #1256 ; 0x4e8 +1001c454: f609 1b28 addw fp, r9, #2344 ; 0x928 +1001c458: f508 7788 add.w r7, r8, #272 ; 0x110 +1001c45c: a804 add r0, sp, #16 +1001c45e: 2110 movs r1, #16 +1001c460: f009 f9dc bl 1002581c <__aeabi_memclr4> +1001c464: f205 4444 addw r4, r5, #1092 ; 0x444 +1001c468: f109 0a98 add.w sl, r9, #152 ; 0x98 +1001c46c: 8860 ldrh r0, [r4, #2] +1001c46e: 2800 cmp r0, #0 +1001c470: bf1f itttt ne +1001c472: f8b5 0444 ldrhne.w r0, [r5, #1092] ; 0x444 +1001c476: 2800 cmpne r0, #0 +1001c478: f897 00bf ldrbne.w r0, [r7, #191] ; 0xbf +1001c47c: 2801 cmpne r0, #1 +1001c47e: d00a beq.n 1001c496 +1001c480: 2004 movs r0, #4 +1001c482: f88d 0005 strb.w r0, [sp, #5] +1001c486: 2000 movs r0, #0 +1001c488: f88d 0004 strb.w r0, [sp, #4] +1001c48c: 4658 mov r0, fp +1001c48e: f7fe fd8e bl 1001afae +1001c492: ea5f 0b00 movs.w fp, r0 +1001c496: f000 80b8 beq.w 1001c60a +1001c49a: f10b 0708 add.w r7, fp, #8 +1001c49e: 4639 mov r1, r7 +1001c4a0: 4648 mov r0, r9 +1001c4a2: f7fe fda1 bl 1001afe8 +1001c4a6: f8db 0080 ldr.w r0, [fp, #128] ; 0x80 +1001c4aa: f7ff fd33 bl 1001bf14 <.text_130+0x4> +1001c4ae: f8db 0080 ldr.w r0, [fp, #128] ; 0x80 +1001c4b2: f100 0628 add.w r6, r0, #40 ; 0x28 +1001c4b6: 2000 movs r0, #0 +1001c4b8: 8030 strh r0, [r6, #0] +1001c4ba: f7ff fd21 bl 1001bf00 <.text_128> +1001c4be: 4601 mov r1, r0 +1001c4c0: 2206 movs r2, #6 +1001c4c2: 1d30 adds r0, r6, #4 +1001c4c4: f7f4 f9a3 bl 1001080e +1001c4c8: f000 f8b4 bl 1001c634 <.text_155> +1001c4cc: f7ff fd18 bl 1001bf00 <.text_128> +1001c4d0: f000 f8aa bl 1001c628 <.text_154> +1001c4d4: f106 0016 add.w r0, r6, #22 +1001c4d8: 7801 ldrb r1, [r0, #0] +1001c4da: f8b8 200c ldrh.w r2, [r8, #12] +1001c4de: f7ff fe0a bl 1001c0f6 <.text_135> +1001c4e2: f8b8 000c ldrh.w r0, [r8, #12] +1001c4e6: 1c40 adds r0, r0, #1 +1001c4e8: f8a8 000c strh.w r0, [r8, #12] +1001c4ec: f107 030c add.w r3, r7, #12 +1001c4f0: 8830 ldrh r0, [r6, #0] +1001c4f2: 4008 ands r0, r1 +1001c4f4: 8030 strh r0, [r6, #0] +1001c4f6: f10d 0205 add.w r2, sp, #5 +1001c4fa: f040 00d0 orr.w r0, r0, #208 ; 0xd0 +1001c4fe: 8030 strh r0, [r6, #0] +1001c500: 2101 movs r1, #1 +1001c502: 2018 movs r0, #24 +1001c504: 60f8 str r0, [r7, #12] +1001c506: f106 0018 add.w r0, r6, #24 +1001c50a: f7fd fa55 bl 100199b8 +1001c50e: f107 030c add.w r3, r7, #12 +1001c512: aa01 add r2, sp, #4 +1001c514: 2101 movs r1, #1 +1001c516: f7fd fa4f bl 100199b8 +1001c51a: 4680 mov r8, r0 +1001c51c: 8860 ldrh r0, [r4, #2] +1001c51e: b160 cbz r0, 1001c53a +1001c520: 2004 movs r0, #4 +1001c522: f88d 0006 strb.w r0, [sp, #6] +1001c526: f10d 0306 add.w r3, sp, #6 +1001c52a: f000 f871 bl 1001c610 <.text_152> +1001c52e: 2201 movs r2, #1 +1001c530: 2148 movs r1, #72 ; 0x48 +1001c532: 4640 mov r0, r8 +1001c534: f7fb ff24 bl 10018380 +1001c538: 4680 mov r8, r0 +1001c53a: 2278 movs r2, #120 ; 0x78 +1001c53c: 2100 movs r1, #0 +1001c53e: a808 add r0, sp, #32 +1001c540: f7f4 f97a bl 10010838 +1001c544: f8b5 0444 ldrh.w r0, [r5, #1092] ; 0x444 +1001c548: 2800 cmp r0, #0 +1001c54a: d053 beq.n 1001c5f4 +1001c54c: a903 add r1, sp, #12 +1001c54e: f105 0028 add.w r0, r5, #40 ; 0x28 +1001c552: f7f4 f9df bl 10010914 +1001c556: 9802 ldr r0, [sp, #8] +1001c558: f8d0 a000 ldr.w sl, [r0] +1001c55c: ac08 add r4, sp, #32 +1001c55e: e01d b.n 1001c59c +1001c560: 4650 mov r0, sl +1001c562: f100 061c add.w r6, r0, #28 +1001c566: 6fb0 ldr r0, [r6, #120] ; 0x78 +1001c568: f8da a000 ldr.w sl, [sl] +1001c56c: f1a0 030c sub.w r3, r0, #12 +1001c570: aa00 add r2, sp, #0 +1001c572: 212d movs r1, #45 ; 0x2d +1001c574: f106 0088 add.w r0, r6, #136 ; 0x88 +1001c578: f7f7 fc82 bl 10013e80 +1001c57c: 2800 cmp r0, #0 +1001c57e: bf1c itt ne +1001c580: 9800 ldrne r0, [sp, #0] +1001c582: 2800 cmpne r0, #0 +1001c584: d10a bne.n 1001c59c +1001c586: 6cf0 ldr r0, [r6, #76] ; 0x4c +1001c588: b140 cbz r0, 1001c59c +1001c58a: 280f cmp r0, #15 +1001c58c: d206 bcs.n 1001c59c +1001c58e: 2101 movs r1, #1 +1001c590: 5501 strb r1, [r0, r4] +1001c592: f89d 0020 ldrb.w r0, [sp, #32] +1001c596: b908 cbnz r0, 1001c59c +1001c598: f88d 1020 strb.w r1, [sp, #32] +1001c59c: 9802 ldr r0, [sp, #8] +1001c59e: 4651 mov r1, sl +1001c5a0: f7f4 f9d3 bl 1001094a +1001c5a4: 2801 cmp r0, #1 +1001c5a6: d1db bne.n 1001c560 +1001c5a8: a903 add r1, sp, #12 +1001c5aa: f105 0028 add.w r0, r5, #40 ; 0x28 +1001c5ae: f7f4 f9b2 bl 10010916 +1001c5b2: 2500 movs r5, #0 +1001c5b4: ebc5 1005 rsb r0, r5, r5, lsl #4 +1001c5b8: 5d01 ldrb r1, [r0, r4] +1001c5ba: 2901 cmp r1, #1 +1001c5bc: d117 bne.n 1001c5ee +1001c5be: f88d 5010 strb.w r5, [sp, #16] +1001c5c2: 2201 movs r2, #1 +1001c5c4: ab08 add r3, sp, #32 +1001c5c6: 18c3 adds r3, r0, r3 +1001c5c8: 5ccb ldrb r3, [r1, r3] +1001c5ca: 2b01 cmp r3, #1 +1001c5cc: d104 bne.n 1001c5d8 +1001c5ce: 2a10 cmp r2, #16 +1001c5d0: da02 bge.n 1001c5d8 +1001c5d2: ab04 add r3, sp, #16 +1001c5d4: 54d1 strb r1, [r2, r3] +1001c5d6: 1c52 adds r2, r2, #1 +1001c5d8: 1c49 adds r1, r1, #1 +1001c5da: 290f cmp r1, #15 +1001c5dc: dbf2 blt.n 1001c5c4 +1001c5de: f000 f817 bl 1001c610 <.text_152> +1001c5e2: ab04 add r3, sp, #16 +1001c5e4: 2149 movs r1, #73 ; 0x49 +1001c5e6: 4640 mov r0, r8 +1001c5e8: f7fb feca bl 10018380 +1001c5ec: 4680 mov r8, r0 +1001c5ee: 1c6d adds r5, r5, #1 +1001c5f0: 2d08 cmp r5, #8 +1001c5f2: dbdf blt.n 1001c5b4 +1001c5f4: f000 f810 bl 1001c618 <.text_153> +1001c5f8: d303 bcc.n 1001c602 +1001c5fa: f7ff fc77 bl 1001beec <.text_124> +1001c5fe: f7ff fc66 bl 1001bece <.text_122> +1001c602: 4659 mov r1, fp +1001c604: 4648 mov r0, r9 +1001c606: f7fe fd1a bl 1001b03e +1001c60a: b027 add sp, #156 ; 0x9c +1001c60c: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1001c610 <.text_152>: +1001c610: f107 000c add.w r0, r7, #12 +1001c614: 9000 str r0, [sp, #0] +1001c616: 4770 bx lr + +1001c618 <.text_153>: +1001c618: 68f8 ldr r0, [r7, #12] +1001c61a: 6138 str r0, [r7, #16] +1001c61c: f240 6153 movw r1, #1619 ; 0x653 +1001c620: 68f8 ldr r0, [r7, #12] +1001c622: 3028 adds r0, #40 ; 0x28 +1001c624: 4288 cmp r0, r1 +1001c626: 4770 bx lr + +1001c628 <.text_154>: +1001c628: 4601 mov r1, r0 +1001c62a: 2206 movs r2, #6 +1001c62c: f106 0010 add.w r0, r6, #16 +1001c630: f7f4 b8ed b.w 1001080e + +1001c634 <.text_155>: +1001c634: f509 51c8 add.w r1, r9, #6400 ; 0x1900 +1001c638: 2206 movs r2, #6 +1001c63a: 3195 adds r1, #149 ; 0x95 +1001c63c: f106 000a add.w r0, r6, #10 +1001c640: f7f4 b8e5 b.w 1001080e + +1001c644 : +1001c644: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +1001c648: 4681 mov r9, r0 +1001c64a: b085 sub sp, #20 +1001c64c: f509 6a9d add.w sl, r9, #1256 ; 0x4e8 +1001c650: f50a 7088 add.w r0, sl, #272 ; 0x110 +1001c654: 9004 str r0, [sp, #16] +1001c656: 2600 movs r6, #0 +1001c658: 9601 str r6, [sp, #4] +1001c65a: f109 000c add.w r0, r9, #12 +1001c65e: 9000 str r0, [sp, #0] +1001c660: f641 5b48 movw fp, #7496 ; 0x1d48 +1001c664: f10a 04d8 add.w r4, sl, #216 ; 0xd8 +1001c668: f85b 0009 ldr.w r0, [fp, r9] +1001c66c: f8ba 8334 ldrh.w r8, [sl, #820] ; 0x334 +1001c670: 68a1 ldr r1, [r4, #8] +1001c672: f89a 23e5 ldrb.w r2, [sl, #997] ; 0x3e5 +1001c676: 2800 cmp r0, #0 +1001c678: bf14 ite ne +1001c67a: f500 679d addne.w r7, r0, #1256 ; 0x4e8 +1001c67e: 2700 moveq r7, #0 +1001c680: 200c movs r0, #12 +1001c682: fb00 a001 mla r0, r0, r1, sl +1001c686: f10a 050e add.w r5, sl, #14 +1001c68a: bb12 cbnz r2, 1001c6d2 +1001c68c: 7d06 ldrb r6, [r0, #20] +1001c68e: b95e cbnz r6, 1001c6a8 +1001c690: 7928 ldrb r0, [r5, #4] +1001c692: 2801 cmp r0, #1 +1001c694: d108 bne.n 1001c6a8 +1001c696: 9800 ldr r0, [sp, #0] +1001c698: f890 1492 ldrb.w r1, [r0, #1170] ; 0x492 +1001c69c: f10a 0214 add.w r2, sl, #20 +1001c6a0: 4648 mov r0, r9 +1001c6a2: f7fd fa2f bl 10019b04 +1001c6a6: 7128 strb r0, [r5, #4] +1001c6a8: 68a0 ldr r0, [r4, #8] +1001c6aa: 210c movs r1, #12 +1001c6ac: fb01 a100 mla r1, r1, r0, sl +1001c6b0: 2e00 cmp r6, #0 +1001c6b2: 6989 ldr r1, [r1, #24] +1001c6b4: 9103 str r1, [sp, #12] +1001c6b6: d057 beq.n 1001c768 +1001c6b8: 2800 cmp r0, #0 +1001c6ba: bf1c itt ne +1001c6bc: f89a 03e5 ldrbne.w r0, [sl, #997] ; 0x3e5 +1001c6c0: 2801 cmpne r0, #1 +1001c6c2: d122 bne.n 1001c70a +1001c6c4: 2300 movs r3, #0 +1001c6c6: 2200 movs r2, #0 +1001c6c8: 4631 mov r1, r6 +1001c6ca: 4648 mov r0, r9 +1001c6cc: f009 fa64 bl 10025b98 +1001c6d0: e01f b.n 1001c712 +1001c6d2: 7f02 ldrb r2, [r0, #28] +1001c6d4: 07d3 lsls r3, r2, #31 +1001c6d6: d510 bpl.n 1001c6fa +1001c6d8: 7d06 ldrb r6, [r0, #20] +1001c6da: 0791 lsls r1, r2, #30 +1001c6dc: f002 01fe and.w r1, r2, #254 ; 0xfe +1001c6e0: 7701 strb r1, [r0, #28] +1001c6e2: bf48 it mi +1001c6e4: f04f 0819 movmi.w r8, #25 +1001c6e8: 68a0 ldr r0, [r4, #8] +1001c6ea: 7929 ldrb r1, [r5, #4] +1001c6ec: 1c40 adds r0, r0, #1 +1001c6ee: 4288 cmp r0, r1 +1001c6f0: d1cd bne.n 1001c68e +1001c6f2: 2000 movs r0, #0 +1001c6f4: f88a 03e5 strb.w r0, [sl, #997] ; 0x3e5 +1001c6f8: e7c9 b.n 1001c68e +1001c6fa: 7928 ldrb r0, [r5, #4] +1001c6fc: 4281 cmp r1, r0 +1001c6fe: bfb8 it lt +1001c700: 2101 movlt r1, #1 +1001c702: db2c blt.n 1001c75e +1001c704: f88a 63e5 strb.w r6, [sl, #997] ; 0x3e5 +1001c708: e7c2 b.n 1001c690 +1001c70a: 4631 mov r1, r6 +1001c70c: 4648 mov r0, r9 +1001c70e: f009 fa13 bl 10025b38 +1001c712: 9803 ldr r0, [sp, #12] +1001c714: 2801 cmp r0, #1 +1001c716: d121 bne.n 1001c75c +1001c718: f04f 0b00 mov.w fp, #0 +1001c71c: 2700 movs r7, #0 +1001c71e: 2028 movs r0, #40 ; 0x28 +1001c720: fb00 a007 mla r0, r0, r7, sl +1001c724: f8d0 10e8 ldr.w r1, [r0, #232] ; 0xe8 +1001c728: b159 cbz r1, 1001c742 +1001c72a: f100 05e8 add.w r5, r0, #232 ; 0xe8 +1001c72e: f04f 0b01 mov.w fp, #1 +1001c732: 2201 movs r2, #1 +1001c734: 4629 mov r1, r5 +1001c736: f000 f888 bl 1001c84a <.text_158+0x4> +1001c73a: 465a mov r2, fp +1001c73c: 4629 mov r1, r5 +1001c73e: f000 f884 bl 1001c84a <.text_158+0x4> +1001c742: 1c7f adds r7, r7, #1 +1001c744: 2f01 cmp r7, #1 +1001c746: dbea blt.n 1001c71e +1001c748: f1bb 0f00 cmp.w fp, #0 +1001c74c: bf04 itt eq +1001c74e: 68e0 ldreq r0, [r4, #12] +1001c750: 2801 cmpeq r0, #1 +1001c752: d103 bne.n 1001c75c +1001c754: f000 f877 bl 1001c846 <.text_158> +1001c758: f000 f875 bl 1001c846 <.text_158> +1001c75c: 4641 mov r1, r8 +1001c75e: f50a 7047 add.w r0, sl, #796 ; 0x31c +1001c762: f7f4 f96a bl 10010a3a +1001c766: e06c b.n 1001c842 +1001c768: 9800 ldr r0, [sp, #0] +1001c76a: 2101 movs r1, #1 +1001c76c: f7fd f935 bl 100199da +1001c770: b938 cbnz r0, 1001c782 +1001c772: 2101 movs r1, #1 +1001c774: f7fd fda6 bl 1001a2c4 <.text_32+0x4> +1001c778: b118 cbz r0, 1001c782 +1001c77a: 7bb9 ldrb r1, [r7, #14] +1001c77c: 7bfb ldrb r3, [r7, #15] +1001c77e: 7c3a ldrb r2, [r7, #16] +1001c780: e003 b.n 1001c78a +1001c782: f89a 100e ldrb.w r1, [sl, #14] +1001c786: 786b ldrb r3, [r5, #1] +1001c788: 78aa ldrb r2, [r5, #2] +1001c78a: 2004 movs r0, #4 +1001c78c: f8ca 00d8 str.w r0, [sl, #216] ; 0xd8 +1001c790: 4648 mov r0, r9 +1001c792: f009 fa01 bl 10025b98 +1001c796: 9804 ldr r0, [sp, #16] +1001c798: 7800 ldrb r0, [r0, #0] +1001c79a: f000 0103 and.w r1, r0, #3 +1001c79e: 4648 mov r0, r9 +1001c7a0: f009 f9a3 bl 10025aea +1001c7a4: 20ff movs r0, #255 ; 0xff +1001c7a6: 9001 str r0, [sp, #4] +1001c7a8: aa01 add r2, sp, #4 +1001c7aa: 2132 movs r1, #50 ; 0x32 +1001c7ac: 4648 mov r0, r9 +1001c7ae: f7fa fdaf bl 10017310 +1001c7b2: 4648 mov r0, r9 +1001c7b4: f009 f989 bl 10025aca +1001c7b8: 4648 mov r0, r9 +1001c7ba: f009 fa24 bl 10025c06 +1001c7be: 2801 cmp r0, #1 +1001c7c0: d10a bne.n 1001c7d8 +1001c7c2: 2100 movs r1, #0 +1001c7c4: 4648 mov r0, r9 +1001c7c6: f7ff fbad bl 1001bf24 +1001c7ca: f85b 0009 ldr.w r0, [fp, r9] +1001c7ce: f009 fa1a bl 10025c06 +1001c7d2: 2801 cmp r0, #1 +1001c7d4: d10b bne.n 1001c7ee +1001c7d6: e005 b.n 1001c7e4 +1001c7d8: f85b 0009 ldr.w r0, [fp, r9] +1001c7dc: f009 fa13 bl 10025c06 +1001c7e0: 2801 cmp r0, #1 +1001c7e2: d104 bne.n 1001c7ee +1001c7e4: f85b 0009 ldr.w r0, [fp, r9] +1001c7e8: 2100 movs r1, #0 +1001c7ea: f7ff fb9b bl 1001bf24 +1001c7ee: 2000 movs r0, #0 +1001c7f0: f88d 0008 strb.w r0, [sp, #8] +1001c7f4: aa02 add r2, sp, #8 +1001c7f6: 210c movs r1, #12 +1001c7f8: 4648 mov r0, r9 +1001c7fa: f7fa fd89 bl 10017310 +1001c7fe: 4648 mov r0, r9 +1001c800: f000 fc5a bl 1001d0b8 +1001c804: 2064 movs r0, #100 ; 0x64 +1001c806: f8aa 0334 strh.w r0, [sl, #820] ; 0x334 +1001c80a: 2000 movs r0, #0 +1001c80c: f8ca 00d8 str.w r0, [sl, #216] ; 0xd8 +1001c810: 4648 mov r0, r9 +1001c812: f7ff fe14 bl 1001c43e +1001c816: 4648 mov r0, r9 +1001c818: f7ff fe11 bl 1001c43e +1001c81c: 4648 mov r0, r9 +1001c81e: f7ff fe0e bl 1001c43e +1001c822: 2103 movs r1, #3 +1001c824: 4648 mov r0, r9 +1001c826: f001 fb46 bl 1001deb6 +1001c82a: b150 cbz r0, 1001c842 +1001c82c: 2101 movs r1, #1 +1001c82e: f7fd fd49 bl 1001a2c4 <.text_32+0x4> +1001c832: b130 cbz r0, 1001c842 +1001c834: f85b 0009 ldr.w r0, [fp, r9] +1001c838: 2301 movs r3, #1 +1001c83a: 2200 movs r2, #0 +1001c83c: 2100 movs r1, #0 +1001c83e: f7fc fc5f bl 10019100 +1001c842: f7fe ba8a b.w 1001ad5a <.text_54+0x2> + +1001c846 <.text_158>: +1001c846: 2201 movs r2, #1 +1001c848: 2100 movs r1, #0 +1001c84a: 4648 mov r0, r9 +1001c84c: f7fe be83 b.w 1001b556 + +1001c850 : +1001c850: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +1001c854: 460f mov r7, r1 +1001c856: b083 sub sp, #12 +1001c858: 4680 mov r8, r0 +1001c85a: f8d7 b084 ldr.w fp, [r7, #132] ; 0x84 +1001c85e: f508 50c4 add.w r0, r8, #6272 ; 0x1880 +1001c862: 9001 str r0, [sp, #4] +1001c864: 4615 mov r5, r2 +1001c866: 6ff8 ldr r0, [r7, #124] ; 0x7c +1001c868: 3818 subs r0, #24 +1001c86a: f5b0 7f40 cmp.w r0, #768 ; 0x300 +1001c86e: f508 69bf add.w r9, r8, #1528 ; 0x5f8 +1001c872: 9000 str r0, [sp, #0] +1001c874: d862 bhi.n 1001c93c +1001c876: f44f 725f mov.w r2, #892 ; 0x37c +1001c87a: 2100 movs r1, #0 +1001c87c: 4628 mov r0, r5 +1001c87e: f7f3 ffdb bl 10010838 +1001c882: f89b 0000 ldrb.w r0, [fp] +1001c886: f000 00fc and.w r0, r0, #252 ; 0xfc +1001c88a: 2880 cmp r0, #128 ; 0x80 +1001c88c: bf0c ite eq +1001c88e: 2001 moveq r0, #1 +1001c890: 2000 movne r0, #0 +1001c892: 72a8 strb r0, [r5, #10] +1001c894: f10b 0118 add.w r1, fp, #24 +1001c898: 9800 ldr r0, [sp, #0] +1001c89a: 307c adds r0, #124 ; 0x7c +1001c89c: 6028 str r0, [r5, #0] +1001c89e: 9800 ldr r0, [sp, #0] +1001c8a0: 67a8 str r0, [r5, #120] ; 0x78 +1001c8a2: 4602 mov r2, r0 +1001c8a4: f105 007c add.w r0, r5, #124 ; 0x7c +1001c8a8: f7f3 ffb1 bl 1001080e +1001c8ac: f107 006b add.w r0, r7, #107 ; 0x6b +1001c8b0: aa00 add r2, sp, #0 +1001c8b2: f990 100a ldrsb.w r1, [r0, #10] +1001c8b6: 63a9 str r1, [r5, #56] ; 0x38 +1001c8b8: f897 106b ldrb.w r1, [r7, #107] ; 0x6b +1001c8bc: f885 1075 strb.w r1, [r5, #117] ; 0x75 +1001c8c0: f105 0788 add.w r7, r5, #136 ; 0x88 +1001c8c4: 7b00 ldrb r0, [r0, #12] +1001c8c6: f885 0074 strb.w r0, [r5, #116] ; 0x74 +1001c8ca: 2100 movs r1, #0 +1001c8cc: f000 f8b7 bl 1001ca3e <.text_160> +1001c8d0: f000 f8b9 bl 1001ca46 <.text_161> +1001c8d4: 0004 movs r4, r0 +1001c8d6: d031 beq.n 1001c93c +1001c8d8: 7862 ldrb r2, [r4, #1] +1001c8da: b14a cbz r2, 1001c8f0 +1001c8dc: 9800 ldr r0, [sp, #0] +1001c8de: 2821 cmp r0, #33 ; 0x21 +1001c8e0: d22c bcs.n 1001c93c +1001c8e2: 1ca1 adds r1, r4, #2 +1001c8e4: f105 0010 add.w r0, r5, #16 +1001c8e8: f7f3 ff91 bl 1001080e +1001c8ec: 7860 ldrb r0, [r4, #1] +1001c8ee: e000 b.n 1001c8f2 +1001c8f0: 2000 movs r0, #0 +1001c8f2: 60e8 str r0, [r5, #12] +1001c8f4: 2210 movs r2, #16 +1001c8f6: 2100 movs r1, #0 +1001c8f8: f105 0064 add.w r0, r5, #100 ; 0x64 +1001c8fc: f7f3 ff9c bl 10010838 +1001c900: f000 f89d bl 1001ca3e <.text_160> +1001c904: 2400 movs r4, #0 +1001c906: aa00 add r2, sp, #0 +1001c908: 2101 movs r1, #1 +1001c90a: f000 f89c bl 1001ca46 <.text_161> +1001c90e: b148 cbz r0, 1001c924 +1001c910: 9900 ldr r1, [sp, #0] +1001c912: 2909 cmp r1, #9 +1001c914: d212 bcs.n 1001c93c +1001c916: 460a mov r2, r1 +1001c918: 1c81 adds r1, r0, #2 +1001c91a: f105 0064 add.w r0, r5, #100 ; 0x64 +1001c91e: f7f3 ff76 bl 1001080e +1001c922: 9c00 ldr r4, [sp, #0] +1001c924: f000 f88b bl 1001ca3e <.text_160> +1001c928: aa00 add r2, sp, #0 +1001c92a: 2132 movs r1, #50 ; 0x32 +1001c92c: f000 f88b bl 1001ca46 <.text_161> +1001c930: b158 cbz r0, 1001c94a +1001c932: 9a00 ldr r2, [sp, #0] +1001c934: f1c4 0110 rsb r1, r4, #16 +1001c938: 4291 cmp r1, r2 +1001c93a: d201 bcs.n 1001c940 +1001c93c: 2000 movs r0, #0 +1001c93e: e07c b.n 1001ca3a +1001c940: 1c81 adds r1, r0, #2 +1001c942: 1960 adds r0, r4, r5 +1001c944: 3064 adds r0, #100 ; 0x64 +1001c946: f7f3 ff62 bl 1001080e +1001c94a: 2003 movs r0, #3 +1001c94c: 63e8 str r0, [r5, #60] ; 0x3c +1001c94e: aa00 add r2, sp, #0 +1001c950: f000 f875 bl 1001ca3e <.text_160> +1001c954: 2103 movs r1, #3 +1001c956: f000 f876 bl 1001ca46 <.text_161> +1001c95a: 2100 movs r1, #0 +1001c95c: 64e9 str r1, [r5, #76] ; 0x4c +1001c95e: 6429 str r1, [r5, #64] ; 0x40 +1001c960: f508 64b8 add.w r4, r8, #1472 ; 0x5c0 +1001c964: 260c movs r6, #12 +1001c966: b930 cbnz r0, 1001c976 +1001c968: f000 f869 bl 1001ca3e <.text_160> +1001c96c: aa00 add r2, sp, #0 +1001c96e: 213d movs r1, #61 ; 0x3d +1001c970: f000 f869 bl 1001ca46 <.text_161> +1001c974: b108 cbz r0, 1001c97a +1001c976: 7880 ldrb r0, [r0, #2] +1001c978: e00a b.n 1001c990 +1001c97a: f8d8 05c0 ldr.w r0, [r8, #1472] ; 0x5c0 +1001c97e: 2803 cmp r0, #3 +1001c980: bf03 ittte eq +1001c982: 68a0 ldreq r0, [r4, #8] +1001c984: fb06 8000 mlaeq r0, r6, r0, r8 +1001c988: f890 04fc ldrbeq.w r0, [r0, #1276] ; 0x4fc +1001c98c: f898 04f6 ldrbne.w r0, [r8, #1270] ; 0x4f6 +1001c990: 64e8 str r0, [r5, #76] ; 0x4c +1001c992: f7fe fdcf bl 1001b534 <.text_90> +1001c996: 4601 mov r1, r0 +1001c998: 2202 movs r2, #2 +1001c99a: f105 0044 add.w r0, r5, #68 ; 0x44 +1001c99e: f7f3 ff36 bl 1001080e +1001c9a2: 4628 mov r0, r5 +1001c9a4: f001 ff98 bl 1001e8d8 +1001c9a8: 4682 mov sl, r0 +1001c9aa: ea5f 70ca movs.w r0, sl, lsl #31 +1001c9ae: d505 bpl.n 1001c9bc +1001c9b0: 2001 movs r0, #1 +1001c9b2: 6628 str r0, [r5, #96] ; 0x60 +1001c9b4: 2206 movs r2, #6 +1001c9b6: f10b 010a add.w r1, fp, #10 +1001c9ba: e004 b.n 1001c9c6 +1001c9bc: 2000 movs r0, #0 +1001c9be: 6628 str r0, [r5, #96] ; 0x60 +1001c9c0: 2206 movs r2, #6 +1001c9c2: f10b 0110 add.w r1, fp, #16 +1001c9c6: 1d28 adds r0, r5, #4 +1001c9c8: f7f3 ff21 bl 1001080e +1001c9cc: f01a 0010 ands.w r0, sl, #16 +1001c9d0: bf18 it ne +1001c9d2: 2001 movne r0, #1 +1001c9d4: 6368 str r0, [r5, #52] ; 0x34 +1001c9d6: 2000 movs r0, #0 +1001c9d8: 64a8 str r0, [r5, #72] ; 0x48 +1001c9da: 9801 ldr r0, [sp, #4] +1001c9dc: f890 0058 ldrb.w r0, [r0, #88] ; 0x58 +1001c9e0: 2801 cmp r0, #1 +1001c9e2: bf04 itt eq +1001c9e4: f899 00bf ldrbeq.w r0, [r9, #191] ; 0xbf +1001c9e8: 2800 cmpeq r0, #0 +1001c9ea: d11a bne.n 1001ca22 +1001c9ec: f000 f827 bl 1001ca3e <.text_160> +1001c9f0: f108 090c add.w r9, r8, #12 +1001c9f4: aa00 add r2, sp, #0 +1001c9f6: 212d movs r1, #45 ; 0x2d +1001c9f8: f000 f825 bl 1001ca46 <.text_161> +1001c9fc: 2800 cmp r0, #0 +1001c9fe: bf1c itt ne +1001ca00: 9900 ldrne r1, [sp, #0] +1001ca02: 2900 cmpne r1, #0 +1001ca04: d008 beq.n 1001ca18 +1001ca06: 8840 ldrh r0, [r0, #2] +1001ca08: 0440 lsls r0, r0, #17 +1001ca0a: d50a bpl.n 1001ca22 +1001ca0c: f209 4044 addw r0, r9, #1092 ; 0x444 +1001ca10: 8841 ldrh r1, [r0, #2] +1001ca12: 1c49 adds r1, r1, #1 +1001ca14: 8041 strh r1, [r0, #2] +1001ca16: e004 b.n 1001ca22 +1001ca18: f8b9 0444 ldrh.w r0, [r9, #1092] ; 0x444 +1001ca1c: 1c40 adds r0, r0, #1 +1001ca1e: f8a9 0444 strh.w r0, [r9, #1092] ; 0x444 +1001ca22: 68a1 ldr r1, [r4, #8] +1001ca24: 6ce8 ldr r0, [r5, #76] ; 0x4c +1001ca26: fb06 8101 mla r1, r6, r1, r8 +1001ca2a: f891 14fc ldrb.w r1, [r1, #1276] ; 0x4fc +1001ca2e: 4288 cmp r0, r1 +1001ca30: bf1c itt ne +1001ca32: 2065 movne r0, #101 ; 0x65 +1001ca34: f885 0075 strbne.w r0, [r5, #117] ; 0x75 +1001ca38: 2001 movs r0, #1 +1001ca3a: e8bd 8ffe ldmia.w sp!, {r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1001ca3e <.text_160>: +1001ca3e: 6fa8 ldr r0, [r5, #120] ; 0x78 +1001ca40: f1a0 030c sub.w r3, r0, #12 +1001ca44: 4770 bx lr + +1001ca46 <.text_161>: +1001ca46: 4638 mov r0, r7 +1001ca48: f7f7 ba1a b.w 10013e80 + +1001ca4c : +1001ca4c: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1001ca50: 4604 mov r4, r0 +1001ca52: f104 0798 add.w r7, r4, #152 ; 0x98 +1001ca56: b082 sub sp, #8 +1001ca58: f504 659d add.w r5, r4, #1256 ; 0x4e8 +1001ca5c: 6cf8 ldr r0, [r7, #76] ; 0x4c +1001ca5e: 73a8 strb r0, [r5, #14] +1001ca60: f505 7688 add.w r6, r5, #272 ; 0x110 +1001ca64: f104 080c add.w r8, r4, #12 +1001ca68: 4638 mov r0, r7 +1001ca6a: f009 f8c0 bl 10025bee +1001ca6e: f8a6 00aa strh.w r0, [r6, #170] ; 0xaa +1001ca72: 4620 mov r0, r4 +1001ca74: f009 fe00 bl 10026678 +1001ca78: 4638 mov r0, r7 +1001ca7a: f001 ff2d bl 1001e8d8 +1001ca7e: 4607 mov r7, r0 +1001ca80: 4639 mov r1, r7 +1001ca82: 4620 mov r0, r4 +1001ca84: f009 fdb5 bl 100265f2 +1001ca88: 07f8 lsls r0, r7, #31 +1001ca8a: d546 bpl.n 1001cb1a +1001ca8c: 4620 mov r0, r4 +1001ca8e: f001 fa23 bl 1001ded8 +1001ca92: 2800 cmp r0, #0 +1001ca94: d041 beq.n 1001cb1a +1001ca96: f000 fd4c bl 1001d532 <.text_189> +1001ca9a: 6970 ldr r0, [r6, #20] +1001ca9c: 2802 cmp r0, #2 +1001ca9e: bf0c ite eq +1001caa0: 20cc moveq r0, #204 ; 0xcc +1001caa2: 20cf movne r0, #207 ; 0xcf +1001caa4: f88d 0000 strb.w r0, [sp] +1001caa8: aa00 add r2, sp, #0 +1001caaa: 6860 ldr r0, [r4, #4] +1001caac: 2803 cmp r0, #3 +1001caae: bf04 itt eq +1001cab0: 202c moveq r0, #44 ; 0x2c +1001cab2: f88d 0000 strbeq.w r0, [sp] +1001cab6: 2114 movs r1, #20 +1001cab8: f001 f81f bl 1001dafa <.text_212> +1001cabc: 7beb ldrb r3, [r5, #15] +1001cabe: 7c2a ldrb r2, [r5, #16] +1001cac0: 7ba9 ldrb r1, [r5, #14] +1001cac2: f000 fd4b bl 1001d55c <.text_193> +1001cac6: f8b6 00aa ldrh.w r0, [r6, #170] ; 0xaa +1001caca: f009 f8c7 bl 10025c5c +1001cace: 4601 mov r1, r0 +1001cad0: f505 704a add.w r0, r5, #808 ; 0x328 +1001cad4: f7f3 ffb1 bl 10010a3a +1001cad8: f44f 7081 mov.w r0, #258 ; 0x102 +1001cadc: 6030 str r0, [r6, #0] +1001cade: f8d8 14d8 ldr.w r1, [r8, #1240] ; 0x4d8 +1001cae2: 2900 cmp r1, #0 +1001cae4: bf1c itt ne +1001cae6: f8d1 0084 ldrne.w r0, [r1, #132] ; 0x84 +1001caea: 2800 cmpne r0, #0 +1001caec: d015 beq.n 1001cb1a +1001caee: 4620 mov r0, r4 +1001caf0: f7fd f9f0 bl 10019ed4 +1001caf4: f8d8 04d8 ldr.w r0, [r8, #1240] ; 0x4d8 +1001caf8: f8d0 0084 ldr.w r0, [r0, #132] ; 0x84 +1001cafc: 2100 movs r1, #0 +1001cafe: f7f3 fe85 bl 1001080c +1001cb02: f8d8 04d8 ldr.w r0, [r8, #1240] ; 0x4d8 +1001cb06: 2100 movs r1, #0 +1001cb08: f7f3 fe80 bl 1001080c +1001cb0c: f8d8 14d8 ldr.w r1, [r8, #1240] ; 0x4d8 +1001cb10: 2000 movs r0, #0 +1001cb12: f8c1 0084 str.w r0, [r1, #132] ; 0x84 +1001cb16: f8c8 04d8 str.w r0, [r8, #1240] ; 0x4d8 +1001cb1a: e8bd 81f3 ldmia.w sp!, {r0, r1, r4, r5, r6, r7, r8, pc} + +1001cb1e : +1001cb1e: b5fe push {r1, r2, r3, r4, r5, r6, r7, lr} +1001cb20: f000 f86a bl 1001cbf8 <.text_167> +1001cb24: f500 774a add.w r7, r0, #808 ; 0x328 +1001cb28: f104 0698 add.w r6, r4, #152 ; 0x98 +1001cb2c: 4638 mov r0, r7 +1001cb2e: f7f3 ff8b bl 10010a48 +1001cb32: 6829 ldr r1, [r5, #0] +1001cb34: 2002 movs r0, #2 +1001cb36: f360 2109 bfi r1, r0, #8, #2 +1001cb3a: 6029 str r1, [r5, #0] +1001cb3c: 2001 movs r0, #1 +1001cb3e: 6128 str r0, [r5, #16] +1001cb40: 2203 movs r2, #3 +1001cb42: 2000 movs r0, #0 +1001cb44: 6068 str r0, [r5, #4] +1001cb46: 60a8 str r0, [r5, #8] +1001cb48: 60e8 str r0, [r5, #12] +1001cb4a: 1d31 adds r1, r6, #4 +1001cb4c: 4620 mov r0, r4 +1001cb4e: f7ff fae3 bl 1001c118 +1001cb52: f7ff f9cb bl 1001beec <.text_124> +1001cb56: 7a70 ldrb r0, [r6, #9] +1001cb58: 9002 str r0, [sp, #8] +1001cb5a: 7a30 ldrb r0, [r6, #8] +1001cb5c: 9001 str r0, [sp, #4] +1001cb5e: 79f0 ldrb r0, [r6, #7] +1001cb60: 9000 str r0, [sp, #0] +1001cb62: 79b3 ldrb r3, [r6, #6] +1001cb64: 7972 ldrb r2, [r6, #5] +1001cb66: 7931 ldrb r1, [r6, #4] +1001cb68: f20f 001c addw r0, pc, #28 +1001cb6c: f7ef fbc9 bl 1000c302 +1001cb70: 2200 movs r2, #0 +1001cb72: 2100 movs r1, #0 +1001cb74: 4620 mov r0, r4 +1001cb76: f7fe fdbd bl 1001b6f4 +1001cb7a: 4638 mov r0, r7 +1001cb7c: b003 add sp, #12 +1001cb7e: e8bd 40f0 ldmia.w sp!, {r4, r5, r6, r7, lr} +1001cb82: e035 b.n 1001cbf0 <.text_166> +1001cb84: 0000 movs r0, r0 + ... + +1001cb88 : +1001cb88: 5452 384c 3931 4135 445b 6972 6576 5d72 RTL8195A[Driver] +1001cb98: 203a 7473 7261 2074 7561 6874 7420 206f : start auth to +1001cba8: 3025 7832 253a 3230 3a78 3025 7832 253a %02x:%02x:%02x:% +1001cbb8: 3230 3a78 3025 7832 253a 3230 0a78 0000 02x:%02x:%02x... + +1001cbc8 : +1001cbc8: b570 push {r4, r5, r6, lr} +1001cbca: f000 f815 bl 1001cbf8 <.text_167> +1001cbce: f500 764a add.w r6, r0, #808 ; 0x328 +1001cbd2: 4630 mov r0, r6 +1001cbd4: f7f3 ff38 bl 10010a48 +1001cbd8: 6828 ldr r0, [r5, #0] +1001cbda: f420 7040 bic.w r0, r0, #768 ; 0x300 +1001cbde: f440 5010 orr.w r0, r0, #9216 ; 0x2400 +1001cbe2: 6028 str r0, [r5, #0] +1001cbe4: 4620 mov r0, r4 +1001cbe6: f7fe ffc7 bl 1001bb78 +1001cbea: 4630 mov r0, r6 +1001cbec: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} + +1001cbf0 <.text_166>: +1001cbf0: f44f 7196 mov.w r1, #300 ; 0x12c +1001cbf4: f7f3 bf21 b.w 10010a3a + +1001cbf8 <.text_167>: +1001cbf8: 4604 mov r4, r0 +1001cbfa: f504 609d add.w r0, r4, #1256 ; 0x4e8 +1001cbfe: f500 7588 add.w r5, r0, #272 ; 0x110 +1001cc02: 4770 bx lr + +1001cc04 : +1001cc04: b5f8 push {r3, r4, r5, r6, r7, lr} +1001cc06: 4604 mov r4, r0 +1001cc08: 460e mov r6, r1 +1001cc0a: 4617 mov r7, r2 +1001cc0c: f504 65bf add.w r5, r4, #1528 ; 0x5f8 +1001cc10: f7ff fc0a bl 1001c428 <.text_149> +1001cc14: 4601 mov r1, r0 +1001cc16: 2206 movs r2, #6 +1001cc18: 4630 mov r0, r6 +1001cc1a: f7f3 fe02 bl 10010822 +1001cc1e: b1c0 cbz r0, 1001cc52 +1001cc20: 6828 ldr r0, [r5, #0] +1001cc22: f000 0103 and.w r1, r0, #3 +1001cc26: 2902 cmp r1, #2 +1001cc28: d113 bne.n 1001cc52 +1001cc2a: 0441 lsls r1, r0, #17 +1001cc2c: d507 bpl.n 1001cc3e +1001cc2e: 2000 movs r0, #0 +1001cc30: 6028 str r0, [r5, #0] +1001cc32: 463a mov r2, r7 +1001cc34: 4631 mov r1, r6 +1001cc36: 4620 mov r0, r4 +1001cc38: f000 faaf bl 1001d19a +1001cc3c: e009 b.n 1001cc52 +1001cc3e: f410 5f1c tst.w r0, #9984 ; 0x2700 +1001cc42: d006 beq.n 1001cc52 +1001cc44: 2000 movs r0, #0 +1001cc46: 6028 str r0, [r5, #0] +1001cc48: f06f 0101 mvn.w r1, #1 +1001cc4c: 4620 mov r0, r4 +1001cc4e: f000 fa5d bl 1001d10c +1001cc52: 2001 movs r0, #1 +1001cc54: bdf2 pop {r1, r4, r5, r6, r7, pc} + +1001cc56 : +1001cc56: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +1001cc5a: f5ad 7d17 sub.w sp, sp, #604 ; 0x25c +1001cc5e: 460d mov r5, r1 +1001cc60: a986 add r1, sp, #536 ; 0x218 +1001cc62: 9105 str r1, [sp, #20] +1001cc64: 4680 mov r8, r0 +1001cc66: 2100 movs r1, #0 +1001cc68: 9102 str r1, [sp, #8] +1001cc6a: f108 000c add.w r0, r8, #12 +1001cc6e: 6b6c ldr r4, [r5, #52] ; 0x34 +1001cc70: a905 add r1, sp, #20 +1001cc72: 6341 str r1, [r0, #52] ; 0x34 +1001cc74: 2206 movs r2, #6 +1001cc76: 8f81 ldrh r1, [r0, #60] ; 0x3c +1001cc78: 1c49 adds r1, r1, #1 +1001cc7a: 8781 strh r1, [r0, #60] ; 0x3c +1001cc7c: a88e add r0, sp, #568 ; 0x238 +1001cc7e: 1d29 adds r1, r5, #4 +1001cc80: 1c80 adds r0, r0, #2 +1001cc82: f7f3 fdc4 bl 1001080e +1001cc86: 6ba8 ldr r0, [r5, #56] ; 0x38 +1001cc88: f8ad 0240 strh.w r0, [sp, #576] ; 0x240 +1001cc8c: f105 0788 add.w r7, r5, #136 ; 0x88 +1001cc90: ae90 add r6, sp, #576 ; 0x240 +1001cc92: b2e0 uxtb r0, r4 +1001cc94: b908 cbnz r0, 1001cc9a +1001cc96: 2000 movs r0, #0 +1001cc98: e049 b.n 1001cd2e +1001cc9a: f10d 000a add.w r0, sp, #10 +1001cc9e: 9001 str r0, [sp, #4] +1001cca0: ab02 add r3, sp, #8 +1001cca2: 2000 movs r0, #0 +1001cca4: 9000 str r0, [sp, #0] +1001cca6: 2200 movs r2, #0 +1001cca8: 6fa9 ldr r1, [r5, #120] ; 0x78 +1001ccaa: f105 007c add.w r0, r5, #124 ; 0x7c +1001ccae: f7f9 faf1 bl 10016294 +1001ccb2: 2801 cmp r0, #1 +1001ccb4: db3a blt.n 1001cd2c +1001ccb6: 2000 movs r0, #0 +1001ccb8: 9001 str r0, [sp, #4] +1001ccba: 9004 str r0, [sp, #16] +1001ccbc: f8bd 000a ldrh.w r0, [sp, #10] +1001ccc0: b1c0 cbz r0, 1001ccf4 +1001ccc2: f000 f884 bl 1001cdce <.text_170> +1001ccc6: f7fc fe67 bl 10019998 +1001ccca: 2800 cmp r0, #0 +1001cccc: bf1c itt ne +1001ccce: 9903 ldrne r1, [sp, #12] +1001ccd0: 2900 cmpne r1, #0 +1001ccd2: d007 beq.n 1001cce4 +1001ccd4: 2100 movs r1, #0 +1001ccd6: 9100 str r1, [sp, #0] +1001ccd8: ab04 add r3, sp, #16 +1001ccda: f8bd 100a ldrh.w r1, [sp, #10] +1001ccde: aa01 add r2, sp, #4 +1001cce0: f7f7 f8ca bl 10013e78 +1001cce4: 9801 ldr r0, [sp, #4] +1001cce6: 2808 cmp r0, #8 +1001cce8: bf14 ite ne +1001ccea: f8df 0b34 ldrne.w r0, [pc, #2868] ; 1001d820 <.text_198> +1001ccee: f8df 0b34 ldreq.w r0, [pc, #2868] ; 1001d824 <.text_199> +1001ccf2: e01c b.n 1001cd2e +1001ccf4: f8bd 0008 ldrh.w r0, [sp, #8] +1001ccf8: b1d0 cbz r0, 1001cd30 +1001ccfa: f000 f868 bl 1001cdce <.text_170> +1001ccfe: f7fc fe4f bl 100199a0 +1001cd02: 2800 cmp r0, #0 +1001cd04: bf1c itt ne +1001cd06: 9903 ldrne r1, [sp, #12] +1001cd08: 2900 cmpne r1, #0 +1001cd0a: d007 beq.n 1001cd1c +1001cd0c: 2100 movs r1, #0 +1001cd0e: 9100 str r1, [sp, #0] +1001cd10: ab04 add r3, sp, #16 +1001cd12: f8bd 1008 ldrh.w r1, [sp, #8] +1001cd16: aa01 add r2, sp, #4 +1001cd18: f7f7 f8aa bl 10013e70 +1001cd1c: 9801 ldr r0, [sp, #4] +1001cd1e: 2808 cmp r0, #8 +1001cd20: bf14 ite ne +1001cd22: f8df 0b04 ldrne.w r0, [pc, #2820] ; 1001d828 <.text_200> +1001cd26: f8df 0b04 ldreq.w r0, [pc, #2820] ; 1001d82c <.text_201> +1001cd2a: e000 b.n 1001cd2e +1001cd2c: 2001 movs r0, #1 +1001cd2e: 60b0 str r0, [r6, #8] +1001cd30: 2400 movs r4, #0 +1001cd32: f64f 79ff movw r9, #65535 ; 0xffff +1001cd36: f44f 7200 mov.w r2, #512 ; 0x200 +1001cd3a: 2100 movs r1, #0 +1001cd3c: a806 add r0, sp, #24 +1001cd3e: f7f3 fd7b bl 10010838 +1001cd42: 6fa9 ldr r1, [r5, #120] ; 0x78 +1001cd44: ab01 add r3, sp, #4 +1001cd46: aa06 add r2, sp, #24 +1001cd48: 4638 mov r0, r7 +1001cd4a: f7fb fb2d bl 100183a8 +1001cd4e: b340 cbz r0, 1001cda2 +1001cd50: f89d 1019 ldrb.w r1, [sp, #25] +1001cd54: a806 add r0, sp, #24 +1001cd56: 1808 adds r0, r1, r0 +1001cd58: 9000 str r0, [sp, #0] +1001cd5a: f10d 071e add.w r7, sp, #30 +1001cd5e: e008 b.n 1001cd72 +1001cd60: f241 0012 movw r0, #4114 ; 0x1012 +1001cd64: 4583 cmp fp, r0 +1001cd66: d103 bne.n 1001cd70 +1001cd68: 8838 ldrh r0, [r7, #0] +1001cd6a: f7f3 fcd9 bl 10010720 <_htons> +1001cd6e: 4681 mov r9, r0 +1001cd70: 4457 add r7, sl +1001cd72: 9900 ldr r1, [sp, #0] +1001cd74: 428f cmp r7, r1 +1001cd76: d20f bcs.n 1001cd98 +1001cd78: 1bc8 subs r0, r1, r7 +1001cd7a: 2804 cmp r0, #4 +1001cd7c: db0c blt.n 1001cd98 +1001cd7e: f837 0b02 ldrh.w r0, [r7], #2 +1001cd82: f7f3 fccd bl 10010720 <_htons> +1001cd86: f000 f8e5 bl 1001cf54 <.text_172> +1001cd8a: 4682 mov sl, r0 +1001cd8c: f241 0041 movw r0, #4161 ; 0x1041 +1001cd90: 4583 cmp fp, r0 +1001cd92: d1e5 bne.n 1001cd60 +1001cd94: 783c ldrb r4, [r7, #0] +1001cd96: e7eb b.n 1001cd70 +1001cd98: 2c01 cmp r4, #1 +1001cd9a: bf08 it eq +1001cd9c: fa5f f089 uxtbeq.w r0, r9 +1001cda0: d000 beq.n 1001cda4 +1001cda2: 2006 movs r0, #6 +1001cda4: 60f0 str r0, [r6, #12] +1001cda6: f105 0110 add.w r1, r5, #16 +1001cdaa: 68e8 ldr r0, [r5, #12] +1001cdac: f88d 0218 strb.w r0, [sp, #536] ; 0x218 +1001cdb0: a886 add r0, sp, #536 ; 0x218 +1001cdb2: 68ea ldr r2, [r5, #12] +1001cdb4: 1c40 adds r0, r0, #1 +1001cdb6: f7f3 fd2a bl 1001080e +1001cdba: 6ce8 ldr r0, [r5, #76] ; 0x4c +1001cdbc: 7430 strb r0, [r6, #16] +1001cdbe: 4640 mov r0, r8 +1001cdc0: f7f7 f8a2 bl 10013f08 +1001cdc4: 2000 movs r0, #0 +1001cdc6: f50d 7d17 add.w sp, sp, #604 ; 0x25c +1001cdca: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1001cdce <.text_170>: +1001cdce: 6fa8 ldr r0, [r5, #120] ; 0x78 +1001cdd0: f1a0 020c sub.w r2, r0, #12 +1001cdd4: a903 add r1, sp, #12 +1001cdd6: 4638 mov r0, r7 +1001cdd8: 4770 bx lr + +1001cdda : +1001cdda: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +1001cdde: f5ad 7d07 sub.w sp, sp, #540 ; 0x21c +1001cde2: 300c adds r0, #12 +1001cde4: 9001 str r0, [sp, #4] +1001cde6: 460c mov r4, r1 +1001cde8: 6b46 ldr r6, [r0, #52] ; 0x34 +1001cdea: 6b80 ldr r0, [r0, #56] ; 0x38 +1001cdec: 9005 str r0, [sp, #20] +1001cdee: 2500 movs r5, #0 +1001cdf0: f8ad 500c strh.w r5, [sp, #12] +1001cdf4: f8ad 500a strh.w r5, [sp, #10] +1001cdf8: 46aa mov sl, r5 +1001cdfa: 6b60 ldr r0, [r4, #52] ; 0x34 +1001cdfc: f88d 0000 strb.w r0, [sp] +1001ce00: f64f 79ff movw r9, #65535 ; 0xffff +1001ce04: f88d 5008 strb.w r5, [sp, #8] +1001ce08: f44f 7200 mov.w r2, #512 ; 0x200 +1001ce0c: 2100 movs r1, #0 +1001ce0e: a807 add r0, sp, #28 +1001ce10: f7f3 fd12 bl 10010838 +1001ce14: 6fa0 ldr r0, [r4, #120] ; 0x78 +1001ce16: f1a0 010c sub.w r1, r0, #12 +1001ce1a: f04f 08ff mov.w r8, #255 ; 0xff +1001ce1e: ab06 add r3, sp, #24 +1001ce20: aa07 add r2, sp, #28 +1001ce22: f104 0088 add.w r0, r4, #136 ; 0x88 +1001ce26: f7fb fabf bl 100183a8 +1001ce2a: b910 cbnz r0, 1001ce32 +1001ce2c: f886 800c strb.w r8, [r6, #12] +1001ce30: e02b b.n 1001ce8a +1001ce32: 2001 movs r0, #1 +1001ce34: f88d 0008 strb.w r0, [sp, #8] +1001ce38: a807 add r0, sp, #28 +1001ce3a: f89d 101d ldrb.w r1, [sp, #29] +1001ce3e: 1808 adds r0, r1, r0 +1001ce40: 9004 str r0, [sp, #16] +1001ce42: f10d 0722 add.w r7, sp, #34 ; 0x22 +1001ce46: e00a b.n 1001ce5e +1001ce48: f241 0012 movw r0, #4114 ; 0x1012 +1001ce4c: 4583 cmp fp, r0 +1001ce4e: d103 bne.n 1001ce58 +1001ce50: 8838 ldrh r0, [r7, #0] +1001ce52: f7f3 fc65 bl 10010720 <_htons> +1001ce56: 4681 mov r9, r0 +1001ce58: f8bd 0002 ldrh.w r0, [sp, #2] +1001ce5c: 19c7 adds r7, r0, r7 +1001ce5e: 9904 ldr r1, [sp, #16] +1001ce60: 428f cmp r7, r1 +1001ce62: d212 bcs.n 1001ce8a +1001ce64: 1bc8 subs r0, r1, r7 +1001ce66: 2804 cmp r0, #4 +1001ce68: db0f blt.n 1001ce8a +1001ce6a: f837 0b02 ldrh.w r0, [r7], #2 +1001ce6e: f7f3 fc57 bl 10010720 <_htons> +1001ce72: f000 f86f bl 1001cf54 <.text_172> +1001ce76: f8ad 0002 strh.w r0, [sp, #2] +1001ce7a: f241 0041 movw r0, #4161 ; 0x1041 +1001ce7e: 4583 cmp fp, r0 +1001ce80: d1e2 bne.n 1001ce48 +1001ce82: f897 a000 ldrb.w sl, [r7] +1001ce86: e7e7 b.n 1001ce58 +1001ce88: 197d adds r5, r7, r5 +1001ce8a: 9805 ldr r0, [sp, #20] +1001ce8c: 4285 cmp r5, r0 +1001ce8e: d20d bcs.n 1001ceac +1001ce90: 5daf ldrb r7, [r5, r6] +1001ce92: b987 cbnz r7, 1001ceb6 +1001ce94: 9801 ldr r0, [sp, #4] +1001ce96: 9901 ldr r1, [sp, #4] +1001ce98: 8f80 ldrh r0, [r0, #60] ; 0x3c +1001ce9a: 1c40 adds r0, r0, #1 +1001ce9c: 8788 strh r0, [r1, #60] ; 0x3c +1001ce9e: 68e0 ldr r0, [r4, #12] +1001cea0: 9905 ldr r1, [sp, #20] +1001cea2: 300e adds r0, #14 +1001cea4: b2c0 uxtb r0, r0 +1001cea6: 1942 adds r2, r0, r5 +1001cea8: 4291 cmp r1, r2 +1001ceaa: d21b bcs.n 1001cee4 +1001ceac: 2000 movs r0, #0 +1001ceae: f50d 7d07 add.w sp, sp, #540 ; 0x21c +1001ceb2: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} +1001ceb6: 19a8 adds r0, r5, r6 +1001ceb8: 2206 movs r2, #6 +1001ceba: 1d21 adds r1, r4, #4 +1001cebc: 1c40 adds r0, r0, #1 +1001cebe: f7f3 fcb0 bl 10010822 +1001cec2: 2800 cmp r0, #0 +1001cec4: d0e0 beq.n 1001ce88 +1001cec6: 2f0e cmp r7, #14 +1001cec8: d102 bne.n 1001ced0 +1001ceca: 68e0 ldr r0, [r4, #12] +1001cecc: 2800 cmp r0, #0 +1001cece: d1db bne.n 1001ce88 +1001ced0: 19a9 adds r1, r5, r6 +1001ced2: 6ba0 ldr r0, [r4, #56] ; 0x38 +1001ced4: f8d1 1007 ldr.w r1, [r1, #7] +1001ced8: 4281 cmp r1, r0 +1001ceda: d2e7 bcs.n 1001ceac +1001cedc: 19a9 adds r1, r5, r6 +1001cede: f8c1 0007 str.w r0, [r1, #7] +1001cee2: e7e3 b.n 1001ceac +1001cee4: 55a8 strb r0, [r5, r6] +1001cee6: 2206 movs r2, #6 +1001cee8: 19a8 adds r0, r5, r6 +1001ceea: 1d21 adds r1, r4, #4 +1001ceec: 1c40 adds r0, r0, #1 +1001ceee: f7f3 fc8e bl 1001080e +1001cef2: 6ba0 ldr r0, [r4, #56] ; 0x38 +1001cef4: 19a9 adds r1, r5, r6 +1001cef6: f8c1 0007 str.w r0, [r1, #7] +1001cefa: f89d 0000 ldrb.w r0, [sp] +1001cefe: b178 cbz r0, 1001cf20 +1001cf00: a803 add r0, sp, #12 +1001cf02: 9001 str r0, [sp, #4] +1001cf04: f10d 030a add.w r3, sp, #10 +1001cf08: 2000 movs r0, #0 +1001cf0a: 9000 str r0, [sp, #0] +1001cf0c: 2200 movs r2, #0 +1001cf0e: 6fa1 ldr r1, [r4, #120] ; 0x78 +1001cf10: f104 007c add.w r0, r4, #124 ; 0x7c +1001cf14: f7f9 f9be bl 10016294 +1001cf18: 2801 cmp r0, #1 +1001cf1a: bfac ite ge +1001cf1c: 2003 movge r0, #3 +1001cf1e: 2001 movlt r0, #1 +1001cf20: 19a9 adds r1, r5, r6 +1001cf22: 72c8 strb r0, [r1, #11] +1001cf24: f89d 0008 ldrb.w r0, [sp, #8] +1001cf28: b130 cbz r0, 1001cf38 +1001cf2a: f1ba 0f01 cmp.w sl, #1 +1001cf2e: d103 bne.n 1001cf38 +1001cf30: 19a8 adds r0, r5, r6 +1001cf32: f880 900c strb.w r9, [r0, #12] +1001cf36: e002 b.n 1001cf3e +1001cf38: 19a8 adds r0, r5, r6 +1001cf3a: f880 800c strb.w r8, [r0, #12] +1001cf3e: 6ce0 ldr r0, [r4, #76] ; 0x4c +1001cf40: 7348 strb r0, [r1, #13] +1001cf42: f104 0110 add.w r1, r4, #16 +1001cf46: 68e2 ldr r2, [r4, #12] +1001cf48: 19a8 adds r0, r5, r6 +1001cf4a: 300e adds r0, #14 +1001cf4c: f7f3 fc5f bl 1001080e +1001cf50: 2001 movs r0, #1 +1001cf52: e7ac b.n 1001ceae + +1001cf54 <.text_172>: +1001cf54: 4683 mov fp, r0 +1001cf56: f837 0b02 ldrh.w r0, [r7], #2 +1001cf5a: f7f3 bbe1 b.w 10010720 <_htons> + +1001cf5e : +1001cf5e: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1001cf62: 0004 movs r4, r0 +1001cf64: 460d mov r5, r1 +1001cf66: f104 090c add.w r9, r4, #12 +1001cf6a: d006 beq.n 1001cf7a +1001cf6c: f504 6a9d add.w sl, r4, #1256 ; 0x4e8 +1001cf70: f604 08d8 addw r8, r4, #2264 ; 0x8d8 +1001cf74: f000 f95b bl 1001d22e <.text_181> +1001cf78: 0006 movs r6, r0 +1001cf7a: f000 8087 beq.w 1001d08c +1001cf7e: f44f 7061 mov.w r0, #900 ; 0x384 +1001cf82: f7f3 fc3e bl 10010802 +1001cf86: 0007 movs r7, r0 +1001cf88: d102 bne.n 1001cf90 +1001cf8a: 2120 movs r1, #32 +1001cf8c: 4630 mov r0, r6 +1001cf8e: e026 b.n 1001cfde +1001cf90: f000 f8b8 bl 1001d104 <.text_176> +1001cf94: 2038 movs r0, #56 ; 0x38 +1001cf96: 80b0 strh r0, [r6, #4] +1001cf98: f44f 7061 mov.w r0, #900 ; 0x384 +1001cf9c: 60f0 str r0, [r6, #12] +1001cf9e: 60b7 str r7, [r6, #8] +1001cfa0: 2000 movs r0, #0 +1001cfa2: 6130 str r0, [r6, #16] +1001cfa4: 6170 str r0, [r6, #20] +1001cfa6: f8df 1d84 ldr.w r1, [pc, #3460] ; 1001dd2c <.text_219> +1001cfaa: 6838 ldr r0, [r7, #0] +1001cfac: f000 407f and.w r0, r0, #4278190080 ; 0xff000000 +1001cfb0: 4308 orrs r0, r1 +1001cfb2: 6038 str r0, [r7, #0] +1001cfb4: f10a 0008 add.w r0, sl, #8 +1001cfb8: f7f3 fd66 bl 10010a88 +1001cfbc: f000 f8da bl 1001d174 <.text_178> +1001cfc0: f107 0b08 add.w fp, r7, #8 +1001cfc4: 465a mov r2, fp +1001cfc6: 4629 mov r1, r5 +1001cfc8: 4620 mov r0, r4 +1001cfca: f7ff fc41 bl 1001c850 +1001cfce: b950 cbnz r0, 1001cfe6 +1001cfd0: 2120 movs r1, #32 +1001cfd2: 4630 mov r0, r6 +1001cfd4: f7f3 fc1a bl 1001080c +1001cfd8: f44f 7161 mov.w r1, #900 ; 0x384 +1001cfdc: 4638 mov r0, r7 +1001cfde: e8bd 4ff4 ldmia.w sp!, {r2, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1001cfe2: f7f3 bc13 b.w 1001080c +1001cfe6: f8d9 04d8 ldr.w r0, [r9, #1240] ; 0x4d8 +1001cfea: bb18 cbnz r0, 1001d034 +1001cfec: f109 0144 add.w r1, r9, #68 ; 0x44 +1001cff0: f000 f85e bl 1001d0b0 <.text_174+0x4> +1001cff4: b9f0 cbnz r0, 1001d034 +1001cff6: f10a 00dc add.w r0, sl, #220 ; 0xdc +1001cffa: 210c movs r1, #12 +1001cffc: 6840 ldr r0, [r0, #4] +1001cffe: fb01 a000 mla r0, r1, r0, sl +1001d002: 7f01 ldrb r1, [r0, #28] +1001d004: f041 0180 orr.w r1, r1, #128 ; 0x80 +1001d008: 7701 strb r1, [r0, #28] +1001d00a: 2098 movs r0, #152 ; 0x98 +1001d00c: f7f3 fbf4 bl 100107f8 +1001d010: f8c9 04d8 str.w r0, [r9, #1240] ; 0x4d8 +1001d014: 6fe8 ldr r0, [r5, #124] ; 0x7c +1001d016: f7f3 fbef bl 100107f8 +1001d01a: f8d9 14d8 ldr.w r1, [r9, #1240] ; 0x4d8 +1001d01e: f8c1 0084 str.w r0, [r1, #132] ; 0x84 +1001d022: 6fea ldr r2, [r5, #124] ; 0x7c +1001d024: f8d5 1084 ldr.w r1, [r5, #132] ; 0x84 +1001d028: f7f3 fbf1 bl 1001080e +1001d02c: f8d9 14d8 ldr.w r1, [r9, #1240] ; 0x4d8 +1001d030: 6fe8 ldr r0, [r5, #124] ; 0x7c +1001d032: 67c8 str r0, [r1, #124] ; 0x7c +1001d034: f104 0540 add.w r5, r4, #64 ; 0x40 +1001d038: 8968 ldrh r0, [r5, #10] +1001d03a: f5b0 7f04 cmp.w r0, #528 ; 0x210 +1001d03e: d104 bne.n 1001d04a +1001d040: 4659 mov r1, fp +1001d042: 4620 mov r0, r4 +1001d044: f7ff fe07 bl 1001cc56 +1001d048: e026 b.n 1001d098 +1001d04a: 6c20 ldr r0, [r4, #64] ; 0x40 +1001d04c: b120 cbz r0, 1001d058 +1001d04e: 4659 mov r1, fp +1001d050: 4620 mov r0, r4 +1001d052: f7ff fec2 bl 1001cdda +1001d056: e01f b.n 1001d098 +1001d058: f899 042c ldrb.w r0, [r9, #1068] ; 0x42c +1001d05c: 2801 cmp r0, #1 +1001d05e: d117 bne.n 1001d090 +1001d060: 2206 movs r2, #6 +1001d062: f104 0174 add.w r1, r4, #116 ; 0x74 +1001d066: f10b 0004 add.w r0, fp, #4 +1001d06a: f7f3 fbda bl 10010822 +1001d06e: b198 cbz r0, 1001d098 +1001d070: 68e8 ldr r0, [r5, #12] +1001d072: b110 cbz r0, 1001d07a +1001d074: f000 f81a bl 1001d0ac <.text_174> +1001d078: b970 cbnz r0, 1001d098 +1001d07a: 4631 mov r1, r6 +1001d07c: 4640 mov r0, r8 +1001d07e: f7f9 f980 bl 10016382 +1001d082: f8da 00dc ldr.w r0, [sl, #220] ; 0xdc +1001d086: 1c40 adds r0, r0, #1 +1001d088: f8ca 00dc str.w r0, [sl, #220] ; 0xdc +1001d08c: e8bd 8ff1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, sl, fp, pc} +1001d090: f000 f80c bl 1001d0ac <.text_174> +1001d094: 2800 cmp r0, #0 +1001d096: d0f0 beq.n 1001d07a +1001d098: 2120 movs r1, #32 +1001d09a: 4630 mov r0, r6 +1001d09c: f7f3 fbb6 bl 1001080c +1001d0a0: f44f 7161 mov.w r1, #900 ; 0x384 +1001d0a4: 4638 mov r0, r7 +1001d0a6: f7f3 fbb1 bl 1001080c +1001d0aa: e7ea b.n 1001d082 + +1001d0ac <.text_174>: +1001d0ac: f104 0150 add.w r1, r4, #80 ; 0x50 +1001d0b0: f10b 0010 add.w r0, fp, #16 +1001d0b4: f7ef b94c b.w 1000c350 + +1001d0b8 : +1001d0b8: b5f8 push {r3, r4, r5, r6, r7, lr} +1001d0ba: f500 649d add.w r4, r0, #1256 ; 0x4e8 +1001d0be: f600 05d8 addw r5, r0, #2264 ; 0x8d8 +1001d0c2: f000 f8b4 bl 1001d22e <.text_181> +1001d0c6: 0006 movs r6, r0 +1001d0c8: d01b beq.n 1001d102 +1001d0ca: 200c movs r0, #12 +1001d0cc: f7f3 fb99 bl 10010802 +1001d0d0: 0007 movs r7, r0 +1001d0d2: d101 bne.n 1001d0d8 +1001d0d4: 4630 mov r0, r6 +1001d0d6: e3b3 b.n 1001d840 <.text_204> +1001d0d8: f000 f814 bl 1001d104 <.text_176> +1001d0dc: f000 f851 bl 1001d182 <.text_179> +1001d0e0: f440 2010 orr.w r0, r0, #589824 ; 0x90000 +1001d0e4: f040 0004 orr.w r0, r0, #4 +1001d0e8: 6038 str r0, [r7, #0] +1001d0ea: f104 0008 add.w r0, r4, #8 +1001d0ee: f7f3 fccb bl 10010a88 +1001d0f2: f000 f83f bl 1001d174 <.text_178> +1001d0f6: 4631 mov r1, r6 +1001d0f8: f8d4 00dc ldr.w r0, [r4, #220] ; 0xdc +1001d0fc: 60b8 str r0, [r7, #8] +1001d0fe: 4628 mov r0, r5 +1001d100: e39a b.n 1001d838 <.text_203> +1001d102: bdf1 pop {r0, r4, r5, r6, r7, pc} + +1001d104 <.text_176>: +1001d104: f106 0018 add.w r0, r6, #24 +1001d108: f7f3 bba0 b.w 1001084c + +1001d10c : +1001d10c: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +1001d110: 4680 mov r8, r0 +1001d112: 460d mov r5, r1 +1001d114: f508 699d add.w r9, r8, #1256 ; 0x4e8 +1001d118: f608 0ad8 addw sl, r8, #2264 ; 0x8d8 +1001d11c: f108 047c add.w r4, r8, #124 ; 0x7c +1001d120: f000 f885 bl 1001d22e <.text_181> +1001d124: 0006 movs r6, r0 +1001d126: d023 beq.n 1001d170 +1001d128: 200c movs r0, #12 +1001d12a: f7f3 fb6a bl 10010802 +1001d12e: 0007 movs r7, r0 +1001d130: d103 bne.n 1001d13a +1001d132: 4630 mov r0, r6 +1001d134: e8bd 47f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +1001d138: e384 b.n 1001d844 <.text_204+0x4> +1001d13a: f7ff ffe3 bl 1001d104 <.text_176> +1001d13e: f000 f820 bl 1001d182 <.text_179> +1001d142: f440 2020 orr.w r0, r0, #655360 ; 0xa0000 +1001d146: f040 0004 orr.w r0, r0, #4 +1001d14a: 6038 str r0, [r7, #0] +1001d14c: f109 0008 add.w r0, r9, #8 +1001d150: f7f3 fc9a bl 10010a88 +1001d154: f000 f80e bl 1001d174 <.text_178> +1001d158: 61a5 str r5, [r4, #24] +1001d15a: 60bd str r5, [r7, #8] +1001d15c: 4621 mov r1, r4 +1001d15e: 4640 mov r0, r8 +1001d160: f001 fed2 bl 1001ef08 +1001d164: 4631 mov r1, r6 +1001d166: 4650 mov r0, sl +1001d168: e8bd 47f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +1001d16c: f7f9 b909 b.w 10016382 +1001d170: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + +1001d174 <.text_178>: +1001d174: 6839 ldr r1, [r7, #0] +1001d176: 0209 lsls r1, r1, #8 +1001d178: 0a09 lsrs r1, r1, #8 +1001d17a: ea41 6000 orr.w r0, r1, r0, lsl #24 +1001d17e: 6038 str r0, [r7, #0] +1001d180: 4770 bx lr + +1001d182 <.text_179>: +1001d182: 2038 movs r0, #56 ; 0x38 +1001d184: 80b0 strh r0, [r6, #4] +1001d186: 200c movs r0, #12 +1001d188: 60f0 str r0, [r6, #12] +1001d18a: 60b7 str r7, [r6, #8] +1001d18c: 2000 movs r0, #0 +1001d18e: 6130 str r0, [r6, #16] +1001d190: 6170 str r0, [r6, #20] +1001d192: 6838 ldr r0, [r7, #0] +1001d194: f000 407f and.w r0, r0, #4278190080 ; 0xff000000 +1001d198: 4770 bx lr + +1001d19a : +1001d19a: e92d 43f4 stmdb sp!, {r2, r4, r5, r6, r7, r8, r9, lr} +1001d19e: 4680 mov r8, r0 +1001d1a0: 4689 mov r9, r1 +1001d1a2: f508 669d add.w r6, r8, #1256 ; 0x4e8 +1001d1a6: f608 04d8 addw r4, r8, #2264 ; 0x8d8 +1001d1aa: f000 f840 bl 1001d22e <.text_181> +1001d1ae: 0005 movs r5, r0 +1001d1b0: d03b beq.n 1001d22a +1001d1b2: 2014 movs r0, #20 +1001d1b4: f7f3 fb25 bl 10010802 +1001d1b8: 0007 movs r7, r0 +1001d1ba: d104 bne.n 1001d1c6 +1001d1bc: 2120 movs r1, #32 +1001d1be: 4628 mov r0, r5 +1001d1c0: f7f3 fb24 bl 1001080c +1001d1c4: e031 b.n 1001d22a +1001d1c6: f000 fb33 bl 1001d830 <.text_202> +1001d1ca: 2038 movs r0, #56 ; 0x38 +1001d1cc: 80a8 strh r0, [r5, #4] +1001d1ce: 2014 movs r0, #20 +1001d1d0: 60e8 str r0, [r5, #12] +1001d1d2: 60af str r7, [r5, #8] +1001d1d4: 2000 movs r0, #0 +1001d1d6: 6128 str r0, [r5, #16] +1001d1d8: 6168 str r0, [r5, #20] +1001d1da: 6838 ldr r0, [r7, #0] +1001d1dc: f000 407f and.w r0, r0, #4278190080 ; 0xff000000 +1001d1e0: f040 100c orr.w r0, r0, #786444 ; 0xc000c +1001d1e4: 6038 str r0, [r7, #0] +1001d1e6: f106 0008 add.w r0, r6, #8 +1001d1ea: f7f3 fc4d bl 10010a88 +1001d1ee: f7ff ffc1 bl 1001d174 <.text_178> +1001d1f2: f107 0608 add.w r6, r7, #8 +1001d1f6: 2206 movs r2, #6 +1001d1f8: 4649 mov r1, r9 +1001d1fa: f000 f81d bl 1001d238 <.text_182+0x4> +1001d1fe: 2202 movs r2, #2 +1001d200: a900 add r1, sp, #0 +1001d202: 1db0 adds r0, r6, #6 +1001d204: f7f3 fb03 bl 1001080e +1001d208: f508 5088 add.w r0, r8, #4352 ; 0x1100 +1001d20c: 4649 mov r1, r9 +1001d20e: 3028 adds r0, #40 ; 0x28 +1001d210: f007 ffcc bl 100251ac +1001d214: 2800 cmp r0, #0 +1001d216: bf14 ite ne +1001d218: f8d0 0100 ldrne.w r0, [r0, #256] ; 0x100 +1001d21c: f04f 30ff moveq.w r0, #4294967295 +1001d220: 60b0 str r0, [r6, #8] +1001d222: 4629 mov r1, r5 +1001d224: 4620 mov r0, r4 +1001d226: f7f9 f8ac bl 10016382 +1001d22a: e8bd 83f1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, pc} + +1001d22e <.text_181>: +1001d22e: 2020 movs r0, #32 +1001d230: f7f3 bae7 b.w 10010802 + +1001d234 <.text_182>: +1001d234: 4601 mov r1, r0 +1001d236: 2202 movs r2, #2 +1001d238: 4630 mov r0, r6 +1001d23a: f7f3 bae8 b.w 1001080e + +1001d23e : +1001d23e: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +1001d242: f500 699d add.w r9, r0, #1256 ; 0x4e8 +1001d246: f600 08d8 addw r8, r0, #2264 ; 0x8d8 +1001d24a: 460c mov r4, r1 +1001d24c: 4615 mov r5, r2 +1001d24e: f7ff ffee bl 1001d22e <.text_181> +1001d252: 0007 movs r7, r0 +1001d254: d032 beq.n 1001d2bc +1001d256: 2014 movs r0, #20 +1001d258: f7f3 fad3 bl 10010802 +1001d25c: 0006 movs r6, r0 +1001d25e: d103 bne.n 1001d268 +1001d260: 4638 mov r0, r7 +1001d262: e8bd 43f4 ldmia.w sp!, {r2, r4, r5, r6, r7, r8, r9, lr} +1001d266: e2ed b.n 1001d844 <.text_204+0x4> +1001d268: f107 0018 add.w r0, r7, #24 +1001d26c: f7f3 faee bl 1001084c +1001d270: 2038 movs r0, #56 ; 0x38 +1001d272: 80b8 strh r0, [r7, #4] +1001d274: 2014 movs r0, #20 +1001d276: 60f8 str r0, [r7, #12] +1001d278: 60be str r6, [r7, #8] +1001d27a: 2000 movs r0, #0 +1001d27c: 6138 str r0, [r7, #16] +1001d27e: 6178 str r0, [r7, #20] +1001d280: 6830 ldr r0, [r6, #0] +1001d282: f000 407f and.w r0, r0, #4278190080 ; 0xff000000 +1001d286: f440 2030 orr.w r0, r0, #720896 ; 0xb0000 +1001d28a: f040 000c orr.w r0, r0, #12 +1001d28e: 6030 str r0, [r6, #0] +1001d290: f109 0008 add.w r0, r9, #8 +1001d294: f7f3 fbf8 bl 10010a88 +1001d298: 6831 ldr r1, [r6, #0] +1001d29a: 0209 lsls r1, r1, #8 +1001d29c: 0a09 lsrs r1, r1, #8 +1001d29e: ea41 6000 orr.w r0, r1, r0, lsl #24 +1001d2a2: f846 0b08 str.w r0, [r6], #8 +1001d2a6: 2206 movs r2, #6 +1001d2a8: 4621 mov r1, r4 +1001d2aa: f7ff ffc5 bl 1001d238 <.text_182+0x4> +1001d2ae: 60b5 str r5, [r6, #8] +1001d2b0: 4639 mov r1, r7 +1001d2b2: 4640 mov r0, r8 +1001d2b4: e8bd 43f4 ldmia.w sp!, {r2, r4, r5, r6, r7, r8, r9, lr} +1001d2b8: f7f9 b863 b.w 10016382 +1001d2bc: e8bd 83f1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, pc} + +1001d2c0 : +1001d2c0: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1001d2c4: 6881 ldr r1, [r0, #8] +1001d2c6: 2200 movs r2, #0 +1001d2c8: 4610 mov r0, r2 +1001d2ca: 2400 movs r4, #0 +1001d2cc: 4605 mov r5, r0 +1001d2ce: 4606 mov r6, r0 +1001d2d0: 4607 mov r7, r0 +1001d2d2: f641 5852 movw r8, #7506 ; 0x1d52 +1001d2d6: e005 b.n 1001d2e4 +1001d2d8: 2b01 cmp r3, #1 +1001d2da: bf04 itt eq +1001d2dc: 4660 moveq r0, ip +1001d2de: f500 66bf addeq.w r6, r0, #1528 ; 0x5f8 +1001d2e2: 1c7f adds r7, r7, #1 +1001d2e4: 7c0b ldrb r3, [r1, #16] +1001d2e6: 429f cmp r7, r3 +1001d2e8: da0e bge.n 1001d308 +1001d2ea: eb01 0387 add.w r3, r1, r7, lsl #2 +1001d2ee: f8d3 c008 ldr.w ip, [r3, #8] +1001d2f2: f1bc 0f00 cmp.w ip, #0 +1001d2f6: d0f4 beq.n 1001d2e2 +1001d2f8: f818 300c ldrb.w r3, [r8, ip] +1001d2fc: 2b00 cmp r3, #0 +1001d2fe: d1eb bne.n 1001d2d8 +1001d300: 4662 mov r2, ip +1001d302: f502 65bf add.w r5, r2, #1528 ; 0x5f8 +1001d306: e7ec b.n 1001d2e2 +1001d308: 2a00 cmp r2, #0 +1001d30a: bf18 it ne +1001d30c: 2800 cmpne r0, #0 +1001d30e: d01b beq.n 1001d348 +1001d310: 6831 ldr r1, [r6, #0] +1001d312: f001 0203 and.w r2, r1, #3 +1001d316: 2a03 cmp r2, #3 +1001d318: d015 beq.n 1001d346 +1001d31a: f244 0203 movw r2, #16387 ; 0x4003 +1001d31e: 4011 ands r1, r2 +1001d320: f244 0202 movw r2, #16386 ; 0x4002 +1001d324: 4291 cmp r1, r2 +1001d326: d105 bne.n 1001d334 +1001d328: f44f 7180 mov.w r1, #256 ; 0x100 +1001d32c: 300c adds r0, #12 +1001d32e: f7fc fb54 bl 100199da +1001d332: b140 cbz r0, 1001d346 +1001d334: 6830 ldr r0, [r6, #0] +1001d336: 0440 lsls r0, r0, #17 +1001d338: d506 bpl.n 1001d348 +1001d33a: 6828 ldr r0, [r5, #0] +1001d33c: 0441 lsls r1, r0, #17 +1001d33e: d403 bmi.n 1001d348 +1001d340: f7fd ffba bl 1001b2b8 <.text_85> +1001d344: d000 beq.n 1001d348 +1001d346: 2401 movs r4, #1 +1001d348: 4620 mov r0, r4 +1001d34a: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +1001d34e : +1001d34e: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1001d352: 4680 mov r8, r0 +1001d354: 460c mov r4, r1 +1001d356: f108 050c add.w r5, r8, #12 +1001d35a: f508 669d add.w r6, r8, #1256 ; 0x4e8 +1001d35e: f008 fe8b bl 10026078 +1001d362: f505 6088 add.w r0, r5, #1088 ; 0x440 +1001d366: f504 77fa add.w r7, r4, #500 ; 0x1f4 +1001d36a: 6881 ldr r1, [r0, #8] +1001d36c: b171 cbz r1, 1001d38c +1001d36e: 2101 movs r1, #1 +1001d370: f8c4 11f4 str.w r1, [r4, #500] ; 0x1f4 +1001d374: f506 71f5 add.w r1, r6, #490 ; 0x1ea +1001d378: 68c0 ldr r0, [r0, #12] +1001d37a: 6078 str r0, [r7, #4] +1001d37c: 4640 mov r0, r8 +1001d37e: f009 f85f bl 10026440 +1001d382: b108 cbz r0, 1001d388 +1001d384: 2001 movs r0, #1 +1001d386: 72b8 strb r0, [r7, #10] +1001d388: 2001 movs r0, #1 +1001d38a: e004 b.n 1001d396 +1001d38c: 2000 movs r0, #0 +1001d38e: f8c4 01f4 str.w r0, [r4, #500] ; 0x1f4 +1001d392: 6078 str r0, [r7, #4] +1001d394: 72b8 strb r0, [r7, #10] +1001d396: f104 01f8 add.w r1, r4, #248 ; 0xf8 +1001d39a: 60c8 str r0, [r1, #12] +1001d39c: 7bf0 ldrb r0, [r6, #15] +1001d39e: 7238 strb r0, [r7, #8] +1001d3a0: 7c30 ldrb r0, [r6, #16] +1001d3a2: 7278 strb r0, [r7, #9] +1001d3a4: 2000 movs r0, #0 +1001d3a6: 72f8 strb r0, [r7, #11] +1001d3a8: 7338 strb r0, [r7, #12] +1001d3aa: f8d5 0440 ldr.w r0, [r5, #1088] ; 0x440 +1001d3ae: b108 cbz r0, 1001d3b4 +1001d3b0: 2001 movs r0, #1 +1001d3b2: 60c8 str r0, [r1, #12] +1001d3b4: 2001 movs r0, #1 +1001d3b6: f8c4 00f8 str.w r0, [r4, #248] ; 0xf8 +1001d3ba: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +1001d3be : +1001d3be: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +1001d3c2: 4604 mov r4, r0 +1001d3c4: 460d mov r5, r1 +1001d3c6: f504 669d add.w r6, r4, #1256 ; 0x4e8 +1001d3ca: 2d00 cmp r5, #0 +1001d3cc: f506 7788 add.w r7, r6, #272 ; 0x110 +1001d3d0: f104 0898 add.w r8, r4, #152 ; 0x98 +1001d3d4: d507 bpl.n 1001d3e6 +1001d3d6: 2001 movs r0, #1 +1001d3d8: f000 fb8b bl 1001daf2 <.text_211> +1001d3dc: f000 f8ad bl 1001d53a <.text_190> +1001d3e0: f000 f8a1 bl 1001d526 <.text_188> +1001d3e4: e071 b.n 1001d4ca +1001d3e6: f7fd faf7 bl 1001a9d8 <.text_39> +1001d3ea: 2801 cmp r0, #1 +1001d3ec: d112 bne.n 1001d414 +1001d3ee: 4620 mov r0, r4 +1001d3f0: f007 ff22 bl 10025238 +1001d3f4: ea5f 0900 movs.w r9, r0 +1001d3f8: d00c beq.n 1001d414 +1001d3fa: f8d9 1100 ldr.w r1, [r9, #256] ; 0x100 +1001d3fe: eb07 1041 add.w r0, r7, r1, lsl #5 +1001d402: f8c0 910c str.w r9, [r0, #268] ; 0x10c +1001d406: 4620 mov r0, r4 +1001d408: f009 f994 bl 10026734 +1001d40c: 4649 mov r1, r9 +1001d40e: 4620 mov r0, r4 +1001d410: f009 f83c bl 1002648c +1001d414: 2201 movs r2, #1 +1001d416: f06f 4170 mvn.w r1, #4026531840 ; 0xf0000000 +1001d41a: 4620 mov r0, r4 +1001d41c: f008 fb5e bl 10025adc +1001d420: 4620 mov r0, r4 +1001d422: f009 f8c8 bl 100265b6 +1001d426: f108 0264 add.w r2, r8, #100 ; 0x64 +1001d42a: 2106 movs r1, #6 +1001d42c: f000 f888 bl 1001d540 <.text_190+0x6> +1001d430: f107 02aa add.w r2, r7, #170 ; 0xaa +1001d434: 2110 movs r1, #16 +1001d436: f000 f883 bl 1001d540 <.text_190+0x6> +1001d43a: f8b7 10ac ldrh.w r1, [r7, #172] ; 0xac +1001d43e: 4620 mov r0, r4 +1001d440: f009 f8d7 bl 100265f2 +1001d444: 4620 mov r0, r4 +1001d446: f008 fcb3 bl 10025db0 +1001d44a: 4620 mov r0, r4 +1001d44c: f008 fddb bl 10026006 +1001d450: 7bf3 ldrb r3, [r6, #15] +1001d452: 7c32 ldrb r2, [r6, #16] +1001d454: 7bb1 ldrb r1, [r6, #14] +1001d456: f000 f881 bl 1001d55c <.text_193> +1001d45a: f504 5088 add.w r0, r4, #4352 ; 0x1100 +1001d45e: f108 0104 add.w r1, r8, #4 +1001d462: 3028 adds r0, #40 ; 0x28 +1001d464: f007 fea2 bl 100251ac +1001d468: ea5f 0800 movs.w r8, r0 +1001d46c: d01d beq.n 1001d4aa +1001d46e: f8d8 0100 ldr.w r0, [r8, #256] ; 0x100 +1001d472: eb07 1040 add.w r0, r7, r0, lsl #5 +1001d476: 4641 mov r1, r8 +1001d478: f8c0 810c str.w r8, [r0, #268] ; 0x10c +1001d47c: 7c70 ldrb r0, [r6, #17] +1001d47e: f888 017c strb.w r0, [r8, #380] ; 0x17c +1001d482: 4620 mov r0, r4 +1001d484: f009 f807 bl 10026496 +1001d488: f508 7280 add.w r2, r8, #256 ; 0x100 +1001d48c: 2144 movs r1, #68 ; 0x44 +1001d48e: f000 f857 bl 1001d540 <.text_190+0x6> +1001d492: f8d8 0100 ldr.w r0, [r8, #256] ; 0x100 +1001d496: 0200 lsls r0, r0, #8 +1001d498: f040 0001 orr.w r0, r0, #1 +1001d49c: f8ad 0002 strh.w r0, [sp, #2] +1001d4a0: f10d 0202 add.w r2, sp, #2 +1001d4a4: 2145 movs r1, #69 ; 0x45 +1001d4a6: f000 fb28 bl 1001dafa <.text_212> +1001d4aa: 2002 movs r0, #2 +1001d4ac: f000 fb21 bl 1001daf2 <.text_211> +1001d4b0: f7fd fa92 bl 1001a9d8 <.text_39> +1001d4b4: 2802 cmp r0, #2 +1001d4b6: d103 bne.n 1001d4c0 +1001d4b8: 4631 mov r1, r6 +1001d4ba: 4620 mov r0, r4 +1001d4bc: f009 f953 bl 10026766 +1001d4c0: 2200 movs r2, #0 +1001d4c2: 2102 movs r1, #2 +1001d4c4: 4620 mov r0, r4 +1001d4c6: f7f9 fb7a bl 10016bbe +1001d4ca: 4629 mov r1, r5 +1001d4cc: 4620 mov r0, r4 +1001d4ce: f000 fd54 bl 1001df7a +1001d4d2: e8bd 83f1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, pc} + +1001d4d6 : +1001d4d6: b570 push {r4, r5, r6, lr} +1001d4d8: f000 fb17 bl 1001db0a <.text_214> +1001d4dc: f505 7688 add.w r6, r5, #272 ; 0x110 +1001d4e0: f008 fb91 bl 10025c06 +1001d4e4: b918 cbnz r0, 1001d4ee +1001d4e6: 4620 mov r0, r4 +1001d4e8: f008 fba8 bl 10025c3c +1001d4ec: b1d0 cbz r0, 1001d524 +1001d4ee: f000 fb07 bl 1001db00 <.text_213> +1001d4f2: f000 f822 bl 1001d53a <.text_190> +1001d4f6: f000 f816 bl 1001d526 <.text_188> +1001d4fa: 2101 movs r1, #1 +1001d4fc: 4620 mov r0, r4 +1001d4fe: f002 f9a6 bl 1001f84e +1001d502: 2801 cmp r0, #1 +1001d504: d001 beq.n 1001d50a +1001d506: f000 f823 bl 1001d550 <.text_192> +1001d50a: 4620 mov r0, r4 +1001d50c: f008 fc00 bl 10025d10 +1001d510: 2000 movs r0, #0 +1001d512: 6030 str r0, [r6, #0] +1001d514: f000 f80d bl 1001d532 <.text_189> +1001d518: f505 704a add.w r0, r5, #808 ; 0x328 +1001d51c: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +1001d520: f7f3 ba92 b.w 10010a48 +1001d524: bd70 pop {r4, r5, r6, pc} + +1001d526 <.text_188>: +1001d526: f641 00ae movw r0, #6318 ; 0x18ae +1001d52a: 5d01 ldrb r1, [r0, r4] +1001d52c: 4620 mov r0, r4 +1001d52e: f008 bfb3 b.w 10026498 + +1001d532 <.text_189>: +1001d532: 2102 movs r1, #2 +1001d534: 4620 mov r0, r4 +1001d536: f008 bad8 b.w 10025aea + +1001d53a <.text_190>: +1001d53a: f20f 020c addw r2, pc, #12 +1001d53e: 2104 movs r1, #4 +1001d540: 4620 mov r0, r4 +1001d542: f7f9 bee5 b.w 10017310 + ... + +1001d548 : + ... + +1001d550 <.text_192>: +1001d550: 2000 movs r0, #0 +1001d552: 73e8 strb r0, [r5, #15] +1001d554: 7428 strb r0, [r5, #16] +1001d556: 4602 mov r2, r0 +1001d558: 7ba9 ldrb r1, [r5, #14] +1001d55a: 2300 movs r3, #0 + +1001d55c <.text_193>: +1001d55c: 4620 mov r0, r4 +1001d55e: f008 bb1b b.w 10025b98 + +1001d562 <_linked_rx_signal_strehgth_display>: +1001d562: b51c push {r2, r3, r4, lr} +1001d564: 4604 mov r4, r0 +1001d566: f504 60bf add.w r0, r4, #1528 ; 0x5f8 +1001d56a: 6800 ldr r0, [r0, #0] +1001d56c: f000 0103 and.w r1, r0, #3 +1001d570: 2902 cmp r1, #2 +1001d572: bf08 it eq +1001d574: 2000 moveq r0, #0 +1001d576: d003 beq.n 1001d580 <_linked_rx_signal_strehgth_display+0x1e> +1001d578: f7fd fe9e bl 1001b2b8 <.text_85> +1001d57c: d102 bne.n 1001d584 <_linked_rx_signal_strehgth_display+0x22> +1001d57e: 2002 movs r0, #2 +1001d580: f88d 0000 strb.w r0, [sp] +1001d584: aa00 add r2, sp, #0 +1001d586: 210c movs r1, #12 +1001d588: 4620 mov r0, r4 +1001d58a: f7f9 fee0 bl 1001734e +1001d58e: aa01 add r2, sp, #4 +1001d590: 2100 movs r1, #0 +1001d592: 4620 mov r0, r4 +1001d594: f7f9 fedb bl 1001734e +1001d598: bd13 pop {r0, r1, r4, pc} + +1001d59a : +1001d59a: e92d 47fc stmdb sp!, {r2, r3, r4, r5, r6, r7, r8, r9, sl, lr} +1001d59e: 4682 mov sl, r0 +1001d5a0: f50a 5088 add.w r0, sl, #4352 ; 0x1100 +1001d5a4: f100 0728 add.w r7, r0, #40 ; 0x28 +1001d5a8: f641 5046 movw r0, #7494 ; 0x1d46 +1001d5ac: f50a 659d add.w r5, sl, #1256 ; 0x4e8 +1001d5b0: f810 000a ldrb.w r0, [r0, sl] +1001d5b4: f60a 1828 addw r8, sl, #2344 ; 0x928 +1001d5b8: f505 7488 add.w r4, r5, #272 ; 0x110 +1001d5bc: f10a 0698 add.w r6, sl, #152 ; 0x98 +1001d5c0: b110 cbz r0, 1001d5c8 +1001d5c2: 4650 mov r0, sl +1001d5c4: f7ff ffcd bl 1001d562 <_linked_rx_signal_strehgth_display> +1001d5c8: 4650 mov r0, sl +1001d5ca: f008 fb1c bl 10025c06 +1001d5ce: 2800 cmp r0, #0 +1001d5d0: f000 8090 beq.w 1001d6f4 +1001d5d4: 1d31 adds r1, r6, #4 +1001d5d6: f7fd fb6c bl 1001acb2 <.text_52+0x2> +1001d5da: 2800 cmp r0, #0 +1001d5dc: f000 80cf beq.w 1001d77e +1001d5e0: e9d0 7966 ldrd r7, r9, [r0, #408] ; 0x198 +1001d5e4: e9d0 2368 ldrd r2, r3, [r0, #416] ; 0x1a0 +1001d5e8: 18b9 adds r1, r7, r2 +1001d5ea: eb49 0903 adc.w r9, r9, r3 +1001d5ee: e9d0 236a ldrd r2, r3, [r0, #424] ; 0x1a8 +1001d5f2: 188a adds r2, r1, r2 +1001d5f4: eb49 0303 adc.w r3, r9, r3 +1001d5f8: e9cd 2300 strd r2, r3, [sp] +1001d5fc: e9d0 7960 ldrd r7, r9, [r0, #384] ; 0x180 +1001d600: e9d0 2362 ldrd r2, r3, [r0, #392] ; 0x188 +1001d604: 18b9 adds r1, r7, r2 +1001d606: eb49 0903 adc.w r9, r9, r3 +1001d60a: e9d0 2364 ldrd r2, r3, [r0, #400] ; 0x190 +1001d60e: 188a adds r2, r1, r2 +1001d610: e9dd 7100 ldrd r7, r1, [sp] +1001d614: eb49 0303 adc.w r3, r9, r3 +1001d618: 4299 cmp r1, r3 +1001d61a: bf08 it eq +1001d61c: 4297 cmpeq r7, r2 +1001d61e: d13f bne.n 1001d6a0 +1001d620: f895 0338 ldrb.w r0, [r5, #824] ; 0x338 +1001d624: 2808 cmp r0, #8 +1001d626: da0c bge.n 1001d642 +1001d628: b928 cbnz r0, 1001d636 +1001d62a: f000 f8aa bl 1001d782 <.text_196> +1001d62e: f000 f8a8 bl 1001d782 <.text_196> +1001d632: f000 f8a6 bl 1001d782 <.text_196> +1001d636: f895 0338 ldrb.w r0, [r5, #824] ; 0x338 +1001d63a: 1c40 adds r0, r0, #1 +1001d63c: f885 0338 strb.w r0, [r5, #824] ; 0x338 +1001d640: e03f b.n 1001d6c2 +1001d642: 2000 movs r0, #0 +1001d644: f885 0338 strb.w r0, [r5, #824] ; 0x338 +1001d648: f7fe fc50 bl 1001beec <.text_124> +1001d64c: f60f 30cc addw r0, pc, #3020 ; 0xbcc +1001d650: f7ee fe57 bl 1000c302 +1001d654: f64f 72ff movw r2, #65535 ; 0xffff +1001d658: 1d31 adds r1, r6, #4 +1001d65a: 4650 mov r0, sl +1001d65c: f7ff fad2 bl 1001cc04 +1001d660: 2000 movs r0, #0 +1001d662: 60e0 str r0, [r4, #12] +1001d664: f895 03e4 ldrb.w r0, [r5, #996] ; 0x3e4 +1001d668: 2800 cmp r0, #0 +1001d66a: d042 beq.n 1001d6f2 +1001d66c: f895 035b ldrb.w r0, [r5, #859] ; 0x35b +1001d670: 1c40 adds r0, r0, #1 +1001d672: f885 035b strb.w r0, [r5, #859] ; 0x35b +1001d676: b2c0 uxtb r0, r0 +1001d678: 2803 cmp r0, #3 +1001d67a: da07 bge.n 1001d68c +1001d67c: f505 7053 add.w r0, r5, #844 ; 0x34c +1001d680: e8bd 47fc ldmia.w sp!, {r2, r3, r4, r5, r6, r7, r8, r9, sl, lr} +1001d684: f241 3188 movw r1, #5000 ; 0x1388 +1001d688: f7f3 b9d7 b.w 10010a3a +1001d68c: 2000 movs r0, #0 +1001d68e: f885 035b strb.w r0, [r5, #859] ; 0x35b +1001d692: 4650 mov r0, sl +1001d694: e8bd 47fc ldmia.w sp!, {r2, r3, r4, r5, r6, r7, r8, r9, sl, lr} +1001d698: f60f 3168 addw r1, pc, #2920 ; 0xb68 +1001d69c: f7f6 bc04 b.w 10013ea8 +1001d6a0: 2100 movs r1, #0 +1001d6a2: f885 135b strb.w r1, [r5, #859] ; 0x35b +1001d6a6: f885 1338 strb.w r1, [r5, #824] ; 0x338 +1001d6aa: e9d0 2360 ldrd r2, r3, [r0, #384] ; 0x180 +1001d6ae: e9c0 2366 strd r2, r3, [r0, #408] ; 0x198 +1001d6b2: e9d0 2362 ldrd r2, r3, [r0, #392] ; 0x188 +1001d6b6: e9c0 2368 strd r2, r3, [r0, #416] ; 0x1a0 +1001d6ba: e9d0 2364 ldrd r2, r3, [r0, #400] ; 0x190 +1001d6be: e9c0 236a strd r2, r3, [r0, #424] ; 0x1a8 +1001d6c2: f108 0268 add.w r2, r8, #104 ; 0x68 +1001d6c6: e9d8 011a ldrd r0, r1, [r8, #104] ; 0x68 +1001d6ca: e9d2 6306 ldrd r6, r3, [r2, #24] +1001d6ce: 428b cmp r3, r1 +1001d6d0: bf08 it eq +1001d6d2: 4286 cmpeq r6, r0 +1001d6d4: d109 bne.n 1001d6ea +1001d6d6: 68e0 ldr r0, [r4, #12] +1001d6d8: 1c41 adds r1, r0, #1 +1001d6da: 280f cmp r0, #15 +1001d6dc: 60e1 str r1, [r4, #12] +1001d6de: d14e bne.n 1001d77e +1001d6e0: 2100 movs r1, #0 +1001d6e2: 4650 mov r0, sl +1001d6e4: f7fe fc1e bl 1001bf24 +1001d6e8: e001 b.n 1001d6ee +1001d6ea: e9c2 0106 strd r0, r1, [r2, #24] +1001d6ee: 2000 movs r0, #0 +1001d6f0: 60e0 str r0, [r4, #12] +1001d6f2: e044 b.n 1001d77e +1001d6f4: 4650 mov r0, sl +1001d6f6: f008 fa94 bl 10025c22 +1001d6fa: 2800 cmp r0, #0 +1001d6fc: d03f beq.n 1001d77e +1001d6fe: 2502 movs r5, #2 +1001d700: eb04 1045 add.w r0, r4, r5, lsl #5 +1001d704: f500 7186 add.w r1, r0, #268 ; 0x10c +1001d708: 684a ldr r2, [r1, #4] +1001d70a: 2a01 cmp r2, #1 +1001d70c: d134 bne.n 1001d778 +1001d70e: f8d0 010c ldr.w r0, [r0, #268] ; 0x10c +1001d712: b388 cbz r0, 1001d778 +1001d714: e9d0 7960 ldrd r7, r9, [r0, #384] ; 0x180 +1001d718: 688a ldr r2, [r1, #8] +1001d71a: 2300 movs r3, #0 +1001d71c: e9cd 2300 strd r2, r3, [sp] +1001d720: f500 7cc0 add.w ip, r0, #384 ; 0x180 +1001d724: e9dc 2302 ldrd r2, r3, [ip, #8] +1001d728: 18be adds r6, r7, r2 +1001d72a: eb49 0803 adc.w r8, r9, r3 +1001d72e: e9dc 2304 ldrd r2, r3, [ip, #16] +1001d732: 18b2 adds r2, r6, r2 +1001d734: eb48 0303 adc.w r3, r8, r3 +1001d738: e9dd 6800 ldrd r6, r8, [sp] +1001d73c: 4598 cmp r8, r3 +1001d73e: bf08 it eq +1001d740: 4296 cmpeq r6, r2 +1001d742: d110 bne.n 1001d766 +1001d744: 68ca ldr r2, [r1, #12] +1001d746: 2a03 cmp r2, #3 +1001d748: d202 bcs.n 1001d750 +1001d74a: 1c50 adds r0, r2, #1 +1001d74c: 60c8 str r0, [r1, #12] +1001d74e: e013 b.n 1001d778 +1001d750: 2200 movs r2, #0 +1001d752: 60ca str r2, [r1, #12] +1001d754: 604a str r2, [r1, #4] +1001d756: f500 7184 add.w r1, r0, #264 ; 0x108 +1001d75a: f64f 72ff movw r2, #65535 ; 0xffff +1001d75e: 4650 mov r0, sl +1001d760: f7ff fd1b bl 1001d19a +1001d764: e008 b.n 1001d778 +1001d766: 2000 movs r0, #0 +1001d768: 60c8 str r0, [r1, #12] +1001d76a: e9dc 2302 ldrd r2, r3, [ip, #8] +1001d76e: 19d0 adds r0, r2, r7 +1001d770: e9dc 2304 ldrd r2, r3, [ip, #16] +1001d774: 1810 adds r0, r2, r0 +1001d776: 6088 str r0, [r1, #8] +1001d778: 1c6d adds r5, r5, #1 +1001d77a: 2d08 cmp r5, #8 +1001d77c: d3c0 bcc.n 1001d700 +1001d77e: e8bd 87f3 ldmia.w sp!, {r0, r1, r4, r5, r6, r7, r8, r9, sl, pc} + +1001d782 <.text_196>: +1001d782: 2200 movs r2, #0 +1001d784: f106 010c add.w r1, r6, #12 +1001d788: 4650 mov r0, sl +1001d78a: f7fd bee4 b.w 1001b556 + +1001d78e : +1001d78e: b5f8 push {r3, r4, r5, r6, r7, lr} +1001d790: f600 04d8 addw r4, r0, #2264 ; 0x8d8 +1001d794: f500 609d add.w r0, r0, #1256 ; 0x4e8 +1001d798: f8d0 50d8 ldr.w r5, [r0, #216] ; 0xd8 +1001d79c: 2d02 cmp r5, #2 +1001d79e: db3e blt.n 1001d81e +1001d7a0: f8df 19ec ldr.w r1, [pc, #2540] ; 1001e190 <.text_236> +1001d7a4: 780b ldrb r3, [r1, #0] +1001d7a6: 2d03 cmp r5, #3 +1001d7a8: f100 02d8 add.w r2, r0, #216 ; 0xd8 +1001d7ac: d119 bne.n 1001d7e2 +1001d7ae: 6895 ldr r5, [r2, #8] +1001d7b0: 260c movs r6, #12 +1001d7b2: fb06 0705 mla r7, r6, r5, r0 +1001d7b6: 7f3f ldrb r7, [r7, #28] +1001d7b8: ea5f 7c87 movs.w ip, r7, lsl #30 +1001d7bc: d50f bpl.n 1001d7de +1001d7be: 2b03 cmp r3, #3 +1001d7c0: da01 bge.n 1001d7c6 +1001d7c2: 063f lsls r7, r7, #24 +1001d7c4: d509 bpl.n 1001d7da +1001d7c6: 1c6d adds r5, r5, #1 +1001d7c8: 6095 str r5, [r2, #8] +1001d7ca: 2300 movs r3, #0 +1001d7cc: fb06 0505 mla r5, r6, r5, r0 +1001d7d0: 7f2e ldrb r6, [r5, #28] +1001d7d2: f006 067f and.w r6, r6, #127 ; 0x7f +1001d7d6: 772e strb r6, [r5, #28] +1001d7d8: e003 b.n 1001d7e2 +1001d7da: 1c5b adds r3, r3, #1 +1001d7dc: e001 b.n 1001d7e2 +1001d7de: 1c6d adds r5, r5, #1 +1001d7e0: 6095 str r5, [r2, #8] +1001d7e2: 700b strb r3, [r1, #0] +1001d7e4: f890 1336 ldrb.w r1, [r0, #822] ; 0x336 +1001d7e8: 2901 cmp r1, #1 +1001d7ea: d104 bne.n 1001d7f6 +1001d7ec: 7c81 ldrb r1, [r0, #18] +1001d7ee: 6091 str r1, [r2, #8] +1001d7f0: 2100 movs r1, #0 +1001d7f2: f880 1336 strb.w r1, [r0, #822] ; 0x336 +1001d7f6: f7ff fd1a bl 1001d22e <.text_181> +1001d7fa: 0005 movs r5, r0 +1001d7fc: d00f beq.n 1001d81e +1001d7fe: 2030 movs r0, #48 ; 0x30 +1001d800: f7f2 ffff bl 10010802 +1001d804: 0006 movs r6, r0 +1001d806: d101 bne.n 1001d80c +1001d808: 4628 mov r0, r5 +1001d80a: e019 b.n 1001d840 <.text_204> +1001d80c: f000 f810 bl 1001d830 <.text_202> +1001d810: 2012 movs r0, #18 +1001d812: 80a8 strh r0, [r5, #4] +1001d814: 60ae str r6, [r5, #8] +1001d816: 2030 movs r0, #48 ; 0x30 +1001d818: f000 fac3 bl 1001dda2 <.text_222> +1001d81c: e00c b.n 1001d838 <.text_203> +1001d81e: bdf1 pop {r0, r4, r5, r6, r7, pc} + +1001d820 <.text_198>: +1001d820: 00200004 .word 0x00200004 + +1001d824 <.text_199>: +1001d824: 00200002 .word 0x00200002 + +1001d828 <.text_200>: +1001d828: 00400004 .word 0x00400004 + +1001d82c <.text_201>: +1001d82c: 00400002 .word 0x00400002 + +1001d830 <.text_202>: +1001d830: f105 0018 add.w r0, r5, #24 +1001d834: f7f3 b80a b.w 1001084c + +1001d838 <.text_203>: +1001d838: e8bd 40f4 ldmia.w sp!, {r2, r4, r5, r6, r7, lr} +1001d83c: f7f8 bda1 b.w 10016382 + +1001d840 <.text_204>: +1001d840: e8bd 40f4 ldmia.w sp!, {r2, r4, r5, r6, r7, lr} +1001d844: 2120 movs r1, #32 +1001d846: f7f2 bfe1 b.w 1001080c + +1001d84a : +1001d84a: b510 push {r4, lr} +1001d84c: f500 629d add.w r2, r0, #1256 ; 0x4e8 +1001d850: f502 7188 add.w r1, r2, #272 ; 0x110 +1001d854: 680b ldr r3, [r1, #0] +1001d856: 05dc lsls r4, r3, #23 +1001d858: d504 bpl.n 1001d864 +1001d85a: 2200 movs r2, #0 +1001d85c: 600a str r2, [r1, #0] +1001d85e: f06f 0102 mvn.w r1, #2 +1001d862: e01f b.n 1001d8a4 +1001d864: f502 744a add.w r4, r2, #808 ; 0x328 +1001d868: 059a lsls r2, r3, #22 +1001d86a: d510 bpl.n 1001d88e +1001d86c: 684a ldr r2, [r1, #4] +1001d86e: 1c52 adds r2, r2, #1 +1001d870: 2a05 cmp r2, #5 +1001d872: 604a str r2, [r1, #4] +1001d874: d304 bcc.n 1001d880 +1001d876: 2200 movs r2, #0 +1001d878: 600a str r2, [r1, #0] +1001d87a: f04f 31ff mov.w r1, #4294967295 +1001d87e: e011 b.n 1001d8a4 +1001d880: 2201 movs r2, #1 +1001d882: 610a str r2, [r1, #16] +1001d884: 2100 movs r1, #0 +1001d886: 2200 movs r2, #0 +1001d888: f7fd ff34 bl 1001b6f4 +1001d88c: e00f b.n 1001d8ae +1001d88e: 049a lsls r2, r3, #18 +1001d890: d512 bpl.n 1001d8b8 +1001d892: 688a ldr r2, [r1, #8] +1001d894: 1c52 adds r2, r2, #1 +1001d896: 2a05 cmp r2, #5 +1001d898: 608a str r2, [r1, #8] +1001d89a: d306 bcc.n 1001d8aa +1001d89c: 2200 movs r2, #0 +1001d89e: 600a str r2, [r1, #0] +1001d8a0: f06f 0101 mvn.w r1, #1 +1001d8a4: e8bd 4010 ldmia.w sp!, {r4, lr} +1001d8a8: e430 b.n 1001d10c +1001d8aa: f7fe f965 bl 1001bb78 +1001d8ae: 4620 mov r0, r4 +1001d8b0: e8bd 4010 ldmia.w sp!, {r4, lr} +1001d8b4: f7ff b99c b.w 1001cbf0 <.text_166> +1001d8b8: bd10 pop {r4, pc} + +1001d8ba : +1001d8ba: b158 cbz r0, 1001d8d4 +1001d8bc: f500 70fa add.w r0, r0, #500 ; 0x1f4 +1001d8c0: 6801 ldr r1, [r0, #0] +1001d8c2: 2901 cmp r1, #1 +1001d8c4: bf04 itt eq +1001d8c6: 6841 ldreq r1, [r0, #4] +1001d8c8: 2901 cmpeq r1, #1 +1001d8ca: d103 bne.n 1001d8d4 +1001d8cc: 7b01 ldrb r1, [r0, #12] +1001d8ce: b109 cbz r1, 1001d8d4 +1001d8d0: 2100 movs r1, #0 +1001d8d2: 7301 strb r1, [r0, #12] +1001d8d4: 4770 bx lr + +1001d8d6 : +1001d8d6: 2000 movs r0, #0 +1001d8d8: 4770 bx lr + +1001d8da : +1001d8da: b580 push {r7, lr} +1001d8dc: 7809 ldrb r1, [r1, #0] +1001d8de: 2904 cmp r1, #4 +1001d8e0: f500 62bf add.w r2, r0, #1528 ; 0x5f8 +1001d8e4: d102 bne.n 1001d8ec +1001d8e6: 2103 movs r1, #3 +1001d8e8: 6011 str r1, [r2, #0] +1001d8ea: e006 b.n 1001d8fa +1001d8ec: 2901 cmp r1, #1 +1001d8ee: d107 bne.n 1001d900 +1001d8f0: 6813 ldr r3, [r2, #0] +1001d8f2: 2102 movs r1, #2 +1001d8f4: f361 0301 bfi r3, r1, #0, #2 +1001d8f8: 6013 str r3, [r2, #0] +1001d8fa: f88d 1000 strb.w r1, [sp] +1001d8fe: e004 b.n 1001d90a +1001d900: 1e4a subs r2, r1, #1 +1001d902: 4192 sbcs r2, r2 +1001d904: 0fd2 lsrs r2, r2, #31 +1001d906: f88d 2000 strb.w r2, [sp] +1001d90a: aa00 add r2, sp, #0 +1001d90c: 2102 movs r1, #2 +1001d90e: f7f9 fcff bl 10017310 +1001d912: 2000 movs r0, #0 +1001d914: bd02 pop {r1, pc} + +1001d916 : +1001d916: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +1001d91a: b083 sub sp, #12 +1001d91c: 4680 mov r8, r0 +1001d91e: f508 50c4 add.w r0, r8, #6272 ; 0x1880 +1001d922: f508 669d add.w r6, r8, #1256 ; 0x4e8 +1001d926: 9001 str r0, [sp, #4] +1001d928: f506 7788 add.w r7, r6, #272 ; 0x110 +1001d92c: 460d mov r5, r1 +1001d92e: 6838 ldr r0, [r7, #0] +1001d930: 0441 lsls r1, r0, #17 +1001d932: f108 0498 add.w r4, r8, #152 ; 0x98 +1001d936: f506 7b4a add.w fp, r6, #808 ; 0x328 +1001d93a: d517 bpl.n 1001d96c +1001d93c: 0780 lsls r0, r0, #30 +1001d93e: d504 bpl.n 1001d94a +1001d940: 2203 movs r2, #3 +1001d942: 1d21 adds r1, r4, #4 +1001d944: 4640 mov r0, r8 +1001d946: f7fe fbe7 bl 1001c118 +1001d94a: 2000 movs r0, #0 +1001d94c: 6038 str r0, [r7, #0] +1001d94e: 4640 mov r0, r8 +1001d950: f008 f9de bl 10025d10 +1001d954: 4658 mov r0, fp +1001d956: f7f3 f877 bl 10010a48 +1001d95a: 2102 movs r1, #2 +1001d95c: 4640 mov r0, r8 +1001d95e: f008 f8c4 bl 10025aea +1001d962: 2200 movs r2, #0 +1001d964: 210b movs r1, #11 +1001d966: 4640 mov r0, r8 +1001d968: f7f9 fcd2 bl 10017310 +1001d96c: 4640 mov r0, r8 +1001d96e: f001 fe55 bl 1001f61c +1001d972: 2000 movs r0, #0 +1001d974: 73f0 strb r0, [r6, #15] +1001d976: 7430 strb r0, [r6, #16] +1001d978: f887 00b2 strb.w r0, [r7, #178] ; 0xb2 +1001d97c: f887 00b1 strb.w r0, [r7, #177] ; 0xb1 +1001d980: f887 00b4 strb.w r0, [r7, #180] ; 0xb4 +1001d984: f887 00b5 strb.w r0, [r7, #181] ; 0xb5 +1001d988: f887 00b6 strb.w r0, [r7, #182] ; 0xb6 +1001d98c: f887 00bb strb.w r0, [r7, #187] ; 0xbb +1001d990: f887 00bd strb.w r0, [r7, #189] ; 0xbd +1001d994: f887 00bf strb.w r0, [r7, #191] ; 0xbf +1001d998: 2278 movs r2, #120 ; 0x78 +1001d99a: 4629 mov r1, r5 +1001d99c: f7fe f8e9 bl 1001bb72 <.text_114> +1001d9a0: 6faa ldr r2, [r5, #120] ; 0x78 +1001d9a2: 67a2 str r2, [r4, #120] ; 0x78 +1001d9a4: f5b2 7f40 cmp.w r2, #768 ; 0x300 +1001d9a8: bf88 it hi +1001d9aa: 2004 movhi r0, #4 +1001d9ac: d85b bhi.n 1001da66 +1001d9ae: f105 017c add.w r1, r5, #124 ; 0x7c +1001d9b2: f104 007c add.w r0, r4, #124 ; 0x7c +1001d9b6: f7f2 ff2a bl 1001080e +1001d9ba: f04f 0a0c mov.w sl, #12 +1001d9be: f60f 29a0 addw r9, pc, #2720 ; 0xaa0 +1001d9c2: e003 b.n 1001d9cc +1001d9c4: 7430 strb r0, [r6, #16] +1001d9c6: 7868 ldrb r0, [r5, #1] +1001d9c8: 1c80 adds r0, r0, #2 +1001d9ca: 4482 add sl, r0 +1001d9cc: 6fa0 ldr r0, [r4, #120] ; 0x78 +1001d9ce: 4582 cmp sl, r0 +1001d9d0: d231 bcs.n 1001da36 +1001d9d2: eb0a 0004 add.w r0, sl, r4 +1001d9d6: f100 057c add.w r5, r0, #124 ; 0x7c +1001d9da: 7828 ldrb r0, [r5, #0] +1001d9dc: 282d cmp r0, #45 ; 0x2d +1001d9de: d00e beq.n 1001d9fe +1001d9e0: 283d cmp r0, #61 ; 0x3d +1001d9e2: d010 beq.n 1001da06 +1001d9e4: 28dd cmp r0, #221 ; 0xdd +1001d9e6: d1ee bne.n 1001d9c6 +1001d9e8: 2204 movs r2, #4 +1001d9ea: 4649 mov r1, r9 +1001d9ec: 1ca8 adds r0, r5, #2 +1001d9ee: f7f2 ff18 bl 10010822 +1001d9f2: 2800 cmp r0, #0 +1001d9f4: d0e7 beq.n 1001d9c6 +1001d9f6: 2001 movs r0, #1 +1001d9f8: f887 00b1 strb.w r0, [r7, #177] ; 0xb1 +1001d9fc: e7e3 b.n 1001d9c6 +1001d9fe: 2001 movs r0, #1 +1001da00: f887 00b5 strb.w r0, [r7, #181] ; 0xb5 +1001da04: e7df b.n 1001d9c6 +1001da06: 2001 movs r0, #1 +1001da08: f887 00b6 strb.w r0, [r7, #182] ; 0xb6 +1001da0c: 1ca8 adds r0, r5, #2 +1001da0e: 9901 ldr r1, [sp, #4] +1001da10: f891 1051 ldrb.w r1, [r1, #81] ; 0x51 +1001da14: 2900 cmp r1, #0 +1001da16: d0d6 beq.n 1001d9c6 +1001da18: 7841 ldrb r1, [r0, #1] +1001da1a: 0749 lsls r1, r1, #29 +1001da1c: d5d3 bpl.n 1001d9c6 +1001da1e: 2101 movs r1, #1 +1001da20: 73f1 strb r1, [r6, #15] +1001da22: 7840 ldrb r0, [r0, #1] +1001da24: f000 0003 and.w r0, r0, #3 +1001da28: 2801 cmp r0, #1 +1001da2a: d0cb beq.n 1001d9c4 +1001da2c: 2803 cmp r0, #3 +1001da2e: bf0c ite eq +1001da30: 2002 moveq r0, #2 +1001da32: 2000 movne r0, #0 +1001da34: e7c6 b.n 1001d9c4 +1001da36: f108 007c add.w r0, r8, #124 ; 0x7c +1001da3a: f001 ffd4 bl 1001f9e6 +1001da3e: 1d22 adds r2, r4, #4 +1001da40: 2104 movs r1, #4 +1001da42: 4640 mov r0, r8 +1001da44: f7f9 fc64 bl 10017310 +1001da48: 2000 movs r0, #0 +1001da4a: f88d 0000 strb.w r0, [sp] +1001da4e: aa00 add r2, sp, #0 +1001da50: 210d movs r1, #13 +1001da52: 4640 mov r0, r8 +1001da54: f7f9 fc5c bl 10017310 +1001da58: 4658 mov r0, fp +1001da5a: f7f2 fff5 bl 10010a48 +1001da5e: 4640 mov r0, r8 +1001da60: f7fe fff4 bl 1001ca4c +1001da64: 2000 movs r0, #0 +1001da66: e8bd 8ffe ldmia.w sp!, {r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1001da6a : +1001da6a: b570 push {r4, r5, r6, lr} +1001da6c: f000 f84d bl 1001db0a <.text_214> +1001da70: b082 sub sp, #8 +1001da72: f505 7688 add.w r6, r5, #272 ; 0x110 +1001da76: f008 f8c6 bl 10025c06 +1001da7a: b128 cbz r0, 1001da88 +1001da7c: 2203 movs r2, #3 +1001da7e: f104 019c add.w r1, r4, #156 ; 0x9c +1001da82: 4620 mov r0, r4 +1001da84: f7fe fb48 bl 1001c118 +1001da88: f000 f83a bl 1001db00 <.text_213> +1001da8c: f7ff fd55 bl 1001d53a <.text_190> +1001da90: f7ff fd49 bl 1001d526 <.text_188> +1001da94: 6830 ldr r0, [r6, #0] +1001da96: f000 0103 and.w r1, r0, #3 +1001da9a: 2901 cmp r1, #1 +1001da9c: bf1c itt ne +1001da9e: f000 0003 andne.w r0, r0, #3 +1001daa2: 2803 cmpne r0, #3 +1001daa4: d106 bne.n 1001dab4 +1001daa6: 2000 movs r0, #0 +1001daa8: f88d 0000 strb.w r0, [sp] +1001daac: aa00 add r2, sp, #0 +1001daae: 2108 movs r1, #8 +1001dab0: f000 f823 bl 1001dafa <.text_212> +1001dab4: f7ff fd3d bl 1001d532 <.text_189> +1001dab8: 2000 movs r0, #0 +1001daba: 6030 str r0, [r6, #0] +1001dabc: 2101 movs r1, #1 +1001dabe: 4620 mov r0, r4 +1001dac0: f001 fec5 bl 1001f84e +1001dac4: 2801 cmp r0, #1 +1001dac6: d001 beq.n 1001dacc +1001dac8: f7ff fd42 bl 1001d550 <.text_192> +1001dacc: 4620 mov r0, r4 +1001dace: f008 f91f bl 10025d10 +1001dad2: f505 704a add.w r0, r5, #808 ; 0x328 +1001dad6: f7f2 ffb7 bl 10010a48 +1001dada: f204 402c addw r0, r4, #1068 ; 0x42c +1001dade: f7f2 ffb3 bl 10010a48 +1001dae2: 4620 mov r0, r4 +1001dae4: f00f fb4e bl 1002d184 +1001dae8: 4620 mov r0, r4 +1001daea: f00f fb64 bl 1002d1b6 +1001daee: 2000 movs r0, #0 +1001daf0: bd76 pop {r1, r2, r4, r5, r6, pc} + +1001daf2 <.text_211>: +1001daf2: f88d 0000 strb.w r0, [sp] +1001daf6: aa00 add r2, sp, #0 +1001daf8: 210d movs r1, #13 + +1001dafa <.text_212>: +1001dafa: 4620 mov r0, r4 +1001dafc: f7f9 bc08 b.w 10017310 + +1001db00 <.text_213>: +1001db00: 2200 movs r2, #0 +1001db02: 210b movs r1, #11 +1001db04: 4620 mov r0, r4 +1001db06: f7f9 bc03 b.w 10017310 + +1001db0a <.text_214>: +1001db0a: 4604 mov r4, r0 +1001db0c: f504 659d add.w r5, r4, #1256 ; 0x4e8 +1001db10: 4770 bx lr + +1001db12 : +1001db12: b5f0 push {r4, r5, r6, r7, lr} +1001db14: f7ff fff9 bl 1001db0a <.text_214> +1001db18: b083 sub sp, #12 +1001db1a: f8d5 00d8 ldr.w r0, [r5, #216] ; 0xd8 +1001db1e: 2800 cmp r0, #0 +1001db20: 460e mov r6, r1 +1001db22: d144 bne.n 1001dbae +1001db24: f000 fa24 bl 1001df70 <.text_228> +1001db28: 2001 movs r0, #1 +1001db2a: f8c5 00d8 str.w r0, [r5, #216] ; 0xd8 +1001db2e: f105 07d8 add.w r7, r5, #216 ; 0xd8 +1001db32: 2000 movs r0, #0 +1001db34: 6078 str r0, [r7, #4] +1001db36: 60b8 str r0, [r7, #8] +1001db38: 68b0 ldr r0, [r6, #8] +1001db3a: b138 cbz r0, 1001db4c +1001db3c: 2220 movs r2, #32 +1001db3e: f106 010c add.w r1, r6, #12 +1001db42: f105 00ec add.w r0, r5, #236 ; 0xec +1001db46: f7f2 fe62 bl 1001080e +1001db4a: 68b0 ldr r0, [r6, #8] +1001db4c: 6138 str r0, [r7, #16] +1001db4e: 6830 ldr r0, [r6, #0] +1001db50: 60f8 str r0, [r7, #12] +1001db52: f641 5648 movw r6, #7496 ; 0x1d48 +1001db56: 4620 mov r0, r4 +1001db58: f008 f855 bl 10025c06 +1001db5c: 2801 cmp r0, #1 +1001db5e: d110 bne.n 1001db82 +1001db60: 2002 movs r0, #2 +1001db62: f8c5 00d8 str.w r0, [r5, #216] ; 0xd8 +1001db66: 2101 movs r1, #1 +1001db68: 4620 mov r0, r4 +1001db6a: f7fe f9db bl 1001bf24 +1001db6e: 2101 movs r1, #1 +1001db70: 4620 mov r0, r4 +1001db72: f7fe f9d7 bl 1001bf24 +1001db76: 5930 ldr r0, [r6, r4] +1001db78: f008 f845 bl 10025c06 +1001db7c: 2801 cmp r0, #1 +1001db7e: d110 bne.n 1001dba2 +1001db80: e007 b.n 1001db92 +1001db82: 5930 ldr r0, [r6, r4] +1001db84: f008 f83f bl 10025c06 +1001db88: 2801 cmp r0, #1 +1001db8a: d110 bne.n 1001dbae +1001db8c: 2002 movs r0, #2 +1001db8e: f8c5 00d8 str.w r0, [r5, #216] ; 0xd8 +1001db92: 2101 movs r1, #1 +1001db94: 5930 ldr r0, [r6, r4] +1001db96: f7fe f9c5 bl 1001bf24 +1001db9a: 5930 ldr r0, [r6, r4] +1001db9c: 2101 movs r1, #1 +1001db9e: f7fe f9c1 bl 1001bf24 +1001dba2: 2132 movs r1, #50 ; 0x32 +1001dba4: f505 7047 add.w r0, r5, #796 ; 0x31c +1001dba8: f7f2 ff47 bl 10010a3a +1001dbac: e023 b.n 1001dbf6 +1001dbae: f8d5 00d8 ldr.w r0, [r5, #216] ; 0xd8 +1001dbb2: 2801 cmp r0, #1 +1001dbb4: bf18 it ne +1001dbb6: 2802 cmpne r0, #2 +1001dbb8: d11a bne.n 1001dbf0 +1001dbba: 4620 mov r0, r4 +1001dbbc: f007 ff82 bl 10025ac4 +1001dbc0: 2200 movs r2, #0 +1001dbc2: 2100 movs r1, #0 +1001dbc4: 4620 mov r0, r4 +1001dbc6: f007 ff89 bl 10025adc +1001dbca: 201e movs r0, #30 +1001dbcc: 9000 str r0, [sp, #0] +1001dbce: aa00 add r2, sp, #0 +1001dbd0: 2132 movs r1, #50 ; 0x32 +1001dbd2: f7ff ff92 bl 1001dafa <.text_212> +1001dbd6: 2100 movs r1, #0 +1001dbd8: f7ff fcac bl 1001d534 <.text_189+0x2> +1001dbdc: 2001 movs r0, #1 +1001dbde: f88d 0004 strb.w r0, [sp, #4] +1001dbe2: aa01 add r2, sp, #4 +1001dbe4: 210c movs r1, #12 +1001dbe6: f7ff ff88 bl 1001dafa <.text_212> +1001dbea: 2003 movs r0, #3 +1001dbec: f8c5 00d8 str.w r0, [r5, #216] ; 0xd8 +1001dbf0: 4620 mov r0, r4 +1001dbf2: f7fe fd27 bl 1001c644 +1001dbf6: 2000 movs r0, #0 +1001dbf8: bdfe pop {r1, r2, r3, r4, r5, r6, r7, pc} + +1001dbfa : +1001dbfa: 7809 ldrb r1, [r1, #0] +1001dbfc: 2904 cmp r1, #4 +1001dbfe: bfb8 it lt +1001dc00: f8c0 160c strlt.w r1, [r0, #1548] ; 0x60c +1001dc04: 2000 movs r0, #0 +1001dc06: 4770 bx lr + +1001dc08 : +1001dc08: b570 push {r4, r5, r6, lr} +1001dc0a: b084 sub sp, #16 +1001dc0c: 4604 mov r4, r0 +1001dc0e: 460d mov r5, r1 +1001dc10: a801 add r0, sp, #4 +1001dc12: 2100 movs r1, #0 +1001dc14: 2200 movs r2, #0 +1001dc16: c006 stmia r0!, {r1, r2} +1001dc18: 78e8 ldrb r0, [r5, #3] +1001dc1a: b110 cbz r0, 1001dc22 +1001dc1c: 7868 ldrb r0, [r5, #1] +1001dc1e: f8c4 0618 str.w r0, [r4, #1560] ; 0x618 +1001dc22: 7828 ldrb r0, [r5, #0] +1001dc24: 7869 ldrb r1, [r5, #1] +1001dc26: ea41 0080 orr.w r0, r1, r0, lsl #2 +1001dc2a: f440 4600 orr.w r6, r0, #32768 ; 0x8000 +1001dc2e: f7fe f95d bl 1001beec <.text_124> +1001dc32: 786a ldrb r2, [r5, #1] +1001dc34: 7829 ldrb r1, [r5, #0] +1001dc36: f20f 6028 addw r0, pc, #1576 ; 0x628 +1001dc3a: f7ee fb62 bl 1000c302 +1001dc3e: 1d28 adds r0, r5, #4 +1001dc40: 9000 str r0, [sp, #0] +1001dc42: ab01 add r3, sp, #4 +1001dc44: 7869 ldrb r1, [r5, #1] +1001dc46: 4632 mov r2, r6 +1001dc48: 4620 mov r0, r4 +1001dc4a: f008 f819 bl 10025c80 +1001dc4e: 2000 movs r0, #0 +1001dc50: b004 add sp, #16 +1001dc52: bd70 pop {r4, r5, r6, pc} + +1001dc54 : +1001dc54: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} +1001dc58: 4680 mov r8, r0 +1001dc5a: f508 64bf add.w r4, r8, #1528 ; 0x5f8 +1001dc5e: f508 5088 add.w r0, r8, #4352 ; 0x1100 +1001dc62: b085 sub sp, #20 +1001dc64: f100 0928 add.w r9, r0, #40 ; 0x28 +1001dc68: f7fe fa4d bl 1001c106 <.text_136> +1001dc6c: 460d mov r5, r1 +1001dc6e: d10c bne.n 1001dc8a +1001dc70: f108 019c add.w r1, r8, #156 ; 0x9c +1001dc74: 4648 mov r0, r9 +1001dc76: f007 fa99 bl 100251ac +1001dc7a: b128 cbz r0, 1001dc88 +1001dc7c: f8d0 0100 ldr.w r0, [r0, #256] ; 0x100 +1001dc80: 2802 cmp r0, #2 +1001dc82: bf08 it eq +1001dc84: 2705 moveq r7, #5 +1001dc86: d000 beq.n 1001dc8a +1001dc88: 2704 movs r7, #4 +1001dc8a: f7fe fa3c bl 1001c106 <.text_136> +1001dc8e: a628 add r6, pc, #160 ; (adr r6, 1001dd30 <.text_220>) +1001dc90: d106 bne.n 1001dca0 +1001dc92: f7fd f8f5 bl 1001ae80 <.text_68> +1001dc96: 79a9 ldrb r1, [r5, #6] +1001dc98: f20f 601c addw r0, pc, #1564 ; 0x61c +1001dc9c: f7ee fb31 bl 1000c302 +1001dca0: 7821 ldrb r1, [r4, #0] +1001dca2: 79a8 ldrb r0, [r5, #6] +1001dca4: f000 f960 bl 1001df68 <.text_227> +1001dca8: d128 bne.n 1001dcfc +1001dcaa: b920 cbnz r0, 1001dcb6 +1001dcac: 79e9 ldrb r1, [r5, #7] +1001dcae: 4640 mov r0, r8 +1001dcb0: f008 f819 bl 10025ce6 +1001dcb4: e01e b.n 1001dcf4 +1001dcb6: 4629 mov r1, r5 +1001dcb8: 4648 mov r0, r9 +1001dcba: f007 fa77 bl 100251ac +1001dcbe: b1d8 cbz r0, 1001dcf8 +1001dcc0: 79a9 ldrb r1, [r5, #6] +1001dcc2: f8d0 0100 ldr.w r0, [r0, #256] ; 0x100 +1001dcc6: 008a lsls r2, r1, #2 +1001dcc8: f442 4400 orr.w r4, r2, #32768 ; 0x8000 +1001dccc: 1cc7 adds r7, r0, #3 +1001dcce: b141 cbz r1, 1001dce2 +1001dcd0: f7fd f8d6 bl 1001ae80 <.text_68> +1001dcd4: f7fc ffd4 bl 1001ac80 <.text_48+0x4> +1001dcd8: 79a9 ldrb r1, [r5, #6] +1001dcda: f20f 6030 addw r0, pc, #1584 ; 0x630 +1001dcde: f7ee fb10 bl 1000c302 +1001dce2: f105 0008 add.w r0, r5, #8 +1001dce6: 9000 str r0, [sp, #0] +1001dce8: 462b mov r3, r5 +1001dcea: 4622 mov r2, r4 +1001dcec: b2f9 uxtb r1, r7 +1001dcee: 4640 mov r0, r8 +1001dcf0: f007 ffc6 bl 10025c80 +1001dcf4: 2001 movs r0, #1 +1001dcf6: e015 b.n 1001dd24 +1001dcf8: 2005 movs r0, #5 +1001dcfa: e013 b.n 1001dd24 +1001dcfc: b920 cbnz r0, 1001dd08 +1001dcfe: 79e9 ldrb r1, [r5, #7] +1001dd00: 4640 mov r0, r8 +1001dd02: f007 fff0 bl 10025ce6 +1001dd06: e00c b.n 1001dd22 +1001dd08: f105 0108 add.w r1, r5, #8 +1001dd0c: 9100 str r1, [sp, #0] +1001dd0e: 0080 lsls r0, r0, #2 +1001dd10: f440 4200 orr.w r2, r0, #32768 ; 0x8000 +1001dd14: 462b mov r3, r5 +1001dd16: b2f9 uxtb r1, r7 +1001dd18: 4640 mov r0, r8 +1001dd1a: f007 ffb1 bl 10025c80 +1001dd1e: 79a8 ldrb r0, [r5, #6] +1001dd20: 61e0 str r0, [r4, #28] +1001dd22: 2000 movs r0, #0 +1001dd24: b005 add sp, #20 +1001dd26: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + ... + +1001dd2c <.text_219>: +1001dd2c: 0008037c .word 0x0008037c + +1001dd30 <.text_220>: +1001dd30: 00000d0a .word 0x00000d0a + +1001dd34 : +1001dd34: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1001dd38: f600 04d8 addw r4, r0, #2264 ; 0x8d8 +1001dd3c: f500 67bf add.w r7, r0, #1528 ; 0x5f8 +1001dd40: f100 0898 add.w r8, r0, #152 ; 0x98 +1001dd44: f7ff fa73 bl 1001d22e <.text_181> +1001dd48: 0005 movs r5, r0 +1001dd4a: d009 beq.n 1001dd60 +1001dd4c: f44f 705f mov.w r0, #892 ; 0x37c +1001dd50: f7f2 fd57 bl 10010802 +1001dd54: 0006 movs r6, r0 +1001dd56: d105 bne.n 1001dd64 +1001dd58: 2120 movs r1, #32 +1001dd5a: 4628 mov r0, r5 +1001dd5c: f7f2 fd56 bl 1001080c +1001dd60: 2000 movs r0, #0 +1001dd62: e01b b.n 1001dd9c +1001dd64: f44f 725f mov.w r2, #892 ; 0x37c +1001dd68: 4641 mov r1, r8 +1001dd6a: f7f2 fd50 bl 1001080e +1001dd6e: 6fb0 ldr r0, [r6, #120] ; 0x78 +1001dd70: f897 20c0 ldrb.w r2, [r7, #192] ; 0xc0 +1001dd74: f1a0 010c sub.w r1, r0, #12 +1001dd78: f106 0088 add.w r0, r6, #136 ; 0x88 +1001dd7c: f7fd f96b bl 1001b056 +1001dd80: 6fb1 ldr r1, [r6, #120] ; 0x78 +1001dd82: 1840 adds r0, r0, r1 +1001dd84: 67b0 str r0, [r6, #120] ; 0x78 +1001dd86: f7ff fd53 bl 1001d830 <.text_202> +1001dd8a: 2037 movs r0, #55 ; 0x37 +1001dd8c: 80a8 strh r0, [r5, #4] +1001dd8e: 60ae str r6, [r5, #8] +1001dd90: f44f 705f mov.w r0, #892 ; 0x37c +1001dd94: f000 f805 bl 1001dda2 <.text_222> +1001dd98: f7f8 faf3 bl 10016382 +1001dd9c: b2c0 uxtb r0, r0 +1001dd9e: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +1001dda2 <.text_222>: +1001dda2: 60e8 str r0, [r5, #12] +1001dda4: 4629 mov r1, r5 +1001dda6: 2000 movs r0, #0 +1001dda8: 6128 str r0, [r5, #16] +1001ddaa: 6168 str r0, [r5, #20] +1001ddac: 4620 mov r0, r4 +1001ddae: 4770 bx lr + +1001ddb0 : +1001ddb0: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1001ddb4: 460e mov r6, r1 +1001ddb6: 4604 mov r4, r0 +1001ddb8: 6830 ldr r0, [r6, #0] +1001ddba: 0207 lsls r7, r0, #8 +1001ddbc: 0e3f lsrs r7, r7, #24 +1001ddbe: 2f19 cmp r7, #25 +1001ddc0: f604 05ec addw r5, r4, #2284 ; 0x8ec +1001ddc4: 4601 mov r1, r0 +1001ddc6: da18 bge.n 1001ddfa +1001ddc8: f20f 58d4 addw r8, pc, #1492 ; 0x5d4 +1001ddcc: f858 0037 ldr.w r0, [r8, r7, lsl #3] +1001ddd0: 2800 cmp r0, #0 +1001ddd2: bf1c itt ne +1001ddd4: b289 uxthne r1, r1 +1001ddd6: 4288 cmpne r0, r1 +1001ddd8: d10f bne.n 1001ddfa +1001ddda: 4628 mov r0, r5 +1001dddc: f7f2 fe4b bl 10010a76 +1001dde0: f116 0108 adds.w r1, r6, #8 +1001dde4: d009 beq.n 1001ddfa +1001dde6: eb08 00c7 add.w r0, r8, r7, lsl #3 +1001ddea: 6842 ldr r2, [r0, #4] +1001ddec: 0010 movs r0, r2 +1001ddee: bf1c itt ne +1001ddf0: 4620 movne r0, r4 +1001ddf2: 4790 blxne r2 +1001ddf4: 68e8 ldr r0, [r5, #12] +1001ddf6: 1c40 adds r0, r0, #1 +1001ddf8: 60e8 str r0, [r5, #12] +1001ddfa: 2000 movs r0, #0 +1001ddfc: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +1001de00 : +1001de00: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +1001de04: 4604 mov r4, r0 +1001de06: f7fd f94b bl 1001b0a0 +1001de0a: 4620 mov r0, r4 +1001de0c: f007 fa14 bl 10025238 +1001de10: 0005 movs r5, r0 +1001de12: d04d beq.n 1001deb0 +1001de14: f241 10ea movw r0, #4586 ; 0x11ea +1001de18: 5d00 ldrb r0, [r0, r4] +1001de1a: 07c0 lsls r0, r0, #31 +1001de1c: d548 bpl.n 1001deb0 +1001de1e: f8d5 00f4 ldr.w r0, [r5, #244] ; 0xf4 +1001de22: 2800 cmp r0, #0 +1001de24: d044 beq.n 1001deb0 +1001de26: 200a movs r0, #10 +1001de28: f7f2 fde1 bl 100109ee +1001de2c: f105 08f0 add.w r8, r5, #240 ; 0xf0 +1001de30: a900 add r1, sp, #0 +1001de32: 4640 mov r0, r8 +1001de34: f7f2 fd6e bl 10010914 +1001de38: f105 07e8 add.w r7, r5, #232 ; 0xe8 +1001de3c: f604 1928 addw r9, r4, #2344 ; 0x928 +1001de40: e02b b.n 1001de9a +1001de42: 4630 mov r0, r6 +1001de44: f7f2 fd0e bl 10010864 +1001de48: f8d5 00f4 ldr.w r0, [r5, #244] ; 0xf4 +1001de4c: 1e40 subs r0, r0, #1 +1001de4e: f8c5 00f4 str.w r0, [r5, #244] ; 0xf4 +1001de52: bf18 it ne +1001de54: 2001 movne r0, #1 +1001de56: f886 0065 strb.w r0, [r6, #101] ; 0x65 +1001de5a: 2101 movs r1, #1 +1001de5c: f106 0065 add.w r0, r6, #101 ; 0x65 +1001de60: 7081 strb r1, [r0, #2] +1001de62: 2111 movs r1, #17 +1001de64: 70c1 strb r1, [r0, #3] +1001de66: 4640 mov r0, r8 +1001de68: a900 add r1, sp, #0 +1001de6a: f7f2 fd54 bl 10010916 +1001de6e: a900 add r1, sp, #0 +1001de70: 4648 mov r0, r9 +1001de72: f7f2 fd4f bl 10010914 +1001de76: 4631 mov r1, r6 +1001de78: 4620 mov r0, r4 +1001de7a: f00e fc14 bl 1002c6a6 +1001de7e: 2801 cmp r0, #1 +1001de80: d003 beq.n 1001de8a +1001de82: 4631 mov r1, r6 +1001de84: 4648 mov r0, r9 +1001de86: f00e fbc7 bl 1002c618 +1001de8a: a900 add r1, sp, #0 +1001de8c: 4648 mov r0, r9 +1001de8e: f7f2 fd42 bl 10010916 +1001de92: a900 add r1, sp, #0 +1001de94: 4640 mov r0, r8 +1001de96: f7f2 fd3d bl 10010914 +1001de9a: 683e ldr r6, [r7, #0] +1001de9c: 4631 mov r1, r6 +1001de9e: 4638 mov r0, r7 +1001dea0: f7f2 fd53 bl 1001094a +1001dea4: 2800 cmp r0, #0 +1001dea6: d0cc beq.n 1001de42 +1001dea8: a900 add r1, sp, #0 +1001deaa: 4640 mov r0, r8 +1001deac: f7f2 fd33 bl 10010916 +1001deb0: 2000 movs r0, #0 +1001deb2: e8bd 83f2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, pc} + +1001deb6 : +1001deb6: 2800 cmp r0, #0 +1001deb8: bf1e ittt ne +1001deba: f641 5248 movwne r2, #7496 ; 0x1d48 +1001debe: 5810 ldrne r0, [r2, r0] +1001dec0: 2800 cmpne r0, #0 +1001dec2: d008 beq.n 1001ded6 +1001dec4: f890 05f8 ldrb.w r0, [r0, #1528] ; 0x5f8 +1001dec8: f000 0003 and.w r0, r0, #3 +1001decc: 4288 cmp r0, r1 +1001dece: d101 bne.n 1001ded4 +1001ded0: 2001 movs r0, #1 +1001ded2: 4770 bx lr +1001ded4: 2000 movs r0, #0 +1001ded6: 4770 bx lr + +1001ded8 : +1001ded8: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1001dedc: 4604 mov r4, r0 +1001dede: f001 fc9e bl 1001f81e +1001dee2: b1f8 cbz r0, 1001df24 +1001dee4: f641 5048 movw r0, #7496 ; 0x1d48 +1001dee8: f504 659d add.w r5, r4, #1256 ; 0x4e8 +1001deec: 5900 ldr r0, [r0, r4] +1001deee: f500 669d add.w r6, r0, #1256 ; 0x4e8 +1001def2: f100 080c add.w r8, r0, #12 +1001def6: f896 1110 ldrb.w r1, [r6, #272] ; 0x110 +1001defa: f000 f835 bl 1001df68 <.text_227> +1001defe: f106 070e add.w r7, r6, #14 +1001df02: d112 bne.n 1001df2a +1001df04: 7ba9 ldrb r1, [r5, #14] +1001df06: 7bb2 ldrb r2, [r6, #14] +1001df08: 4291 cmp r1, r2 +1001df0a: bf02 ittt eq +1001df0c: 7be9 ldrbeq r1, [r5, #15] +1001df0e: 787a ldrbeq r2, [r7, #1] +1001df10: 4291 cmpeq r1, r2 +1001df12: bf02 ittt eq +1001df14: 7c29 ldrbeq r1, [r5, #16] +1001df16: 78ba ldrbeq r2, [r7, #2] +1001df18: 4291 cmpeq r1, r2 +1001df1a: d006 beq.n 1001df2a +1001df1c: f7fb fb21 bl 10019562 +1001df20: f000 f826 bl 1001df70 <.text_228> +1001df24: 2001 movs r0, #1 +1001df26: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} +1001df2a: 2101 movs r1, #1 +1001df2c: f7fb ff67 bl 10019dfe <.text_22+0x2> +1001df30: 2801 cmp r0, #1 +1001df32: d1f7 bne.n 1001df24 +1001df34: 2108 movs r1, #8 +1001df36: f7fb ff62 bl 10019dfe <.text_22+0x2> +1001df3a: 2801 cmp r0, #1 +1001df3c: d1f2 bne.n 1001df24 +1001df3e: 7ba8 ldrb r0, [r5, #14] +1001df40: 7bb1 ldrb r1, [r6, #14] +1001df42: 4288 cmp r0, r1 +1001df44: d109 bne.n 1001df5a +1001df46: 7be8 ldrb r0, [r5, #15] +1001df48: 2801 cmp r0, #1 +1001df4a: bf04 itt eq +1001df4c: 7878 ldrbeq r0, [r7, #1] +1001df4e: 2801 cmpeq r0, #1 +1001df50: d1e8 bne.n 1001df24 +1001df52: 7c28 ldrb r0, [r5, #16] +1001df54: 78b9 ldrb r1, [r7, #2] +1001df56: 4288 cmp r0, r1 +1001df58: d0e4 beq.n 1001df24 +1001df5a: f06f 0103 mvn.w r1, #3 +1001df5e: 4620 mov r0, r4 +1001df60: f7ff f8d4 bl 1001d10c +1001df64: 2000 movs r0, #0 +1001df66: e7de b.n 1001df26 + +1001df68 <.text_227>: +1001df68: f001 0103 and.w r1, r1, #3 +1001df6c: 2903 cmp r1, #3 +1001df6e: 4770 bx lr + +1001df70 <.text_228>: +1001df70: 2200 movs r2, #0 +1001df72: 213f movs r1, #63 ; 0x3f +1001df74: 4620 mov r0, r4 +1001df76: f7f9 b9cb b.w 10017310 + +1001df7a : +1001df7a: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1001df7e: 4680 mov r8, r0 +1001df80: 460f mov r7, r1 +1001df82: f001 fc4c bl 1001f81e +1001df86: 2800 cmp r0, #0 +1001df88: d015 beq.n 1001dfb6 +1001df8a: f641 5048 movw r0, #7496 ; 0x1d48 +1001df8e: f508 659d add.w r5, r8, #1256 ; 0x4e8 +1001df92: f850 9008 ldr.w r9, [r0, r8] +1001df96: f509 6a9d add.w sl, r9, #1256 ; 0x4e8 +1001df9a: f109 000c add.w r0, r9, #12 +1001df9e: f89a 1110 ldrb.w r1, [sl, #272] ; 0x110 +1001dfa2: f7ff ffe1 bl 1001df68 <.text_227> +1001dfa6: f100 048c add.w r4, r0, #140 ; 0x8c +1001dfaa: f040 80a9 bne.w 1001e100 +1001dfae: 2101 movs r1, #1 +1001dfb0: f7fb fd13 bl 100199da +1001dfb4: 2800 cmp r0, #0 +1001dfb6: f000 80a3 beq.w 1001e100 +1001dfba: f10a 060e add.w r6, sl, #14 +1001dfbe: 2f00 cmp r7, #0 +1001dfc0: 7873 ldrb r3, [r6, #1] +1001dfc2: f100 8095 bmi.w 1001e0f0 +1001dfc6: 2700 movs r7, #0 +1001dfc8: 7ba8 ldrb r0, [r5, #14] +1001dfca: f88a 000e strb.w r0, [sl, #14] +1001dfce: 2b01 cmp r3, #1 +1001dfd0: f104 0b88 add.w fp, r4, #136 ; 0x88 +1001dfd4: d172 bne.n 1001e0bc +1001dfd6: f000 f895 bl 1001e104 <.text_230> +1001dfda: 2800 cmp r0, #0 +1001dfdc: bf1c itt ne +1001dfde: 9900 ldrne r1, [sp, #0] +1001dfe0: 2900 cmpne r1, #0 +1001dfe2: d004 beq.n 1001dfee +1001dfe4: 1c87 adds r7, r0, #2 +1001dfe6: 7878 ldrb r0, [r7, #1] +1001dfe8: f000 00fc and.w r0, r0, #252 ; 0xfc +1001dfec: 7078 strb r0, [r7, #1] +1001dfee: 7be8 ldrb r0, [r5, #15] +1001dff0: 2801 cmp r0, #1 +1001dff2: d112 bne.n 1001e01a +1001dff4: 7c28 ldrb r0, [r5, #16] +1001dff6: 70b0 strb r0, [r6, #2] +1001dff8: 2f00 cmp r7, #0 +1001dffa: d05c beq.n 1001e0b6 +1001dffc: 7c28 ldrb r0, [r5, #16] +1001dffe: 2801 cmp r0, #1 +1001e000: d002 beq.n 1001e008 +1001e002: 2802 cmp r0, #2 +1001e004: d004 beq.n 1001e010 +1001e006: e056 b.n 1001e0b6 +1001e008: 7878 ldrb r0, [r7, #1] +1001e00a: f040 0001 orr.w r0, r0, #1 +1001e00e: e002 b.n 1001e016 +1001e010: 7878 ldrb r0, [r7, #1] +1001e012: f040 0003 orr.w r0, r0, #3 +1001e016: 7078 strb r0, [r7, #1] +1001e018: e04d b.n 1001e0b6 +1001e01a: 2800 cmp r0, #0 +1001e01c: d14b bne.n 1001e0b6 +1001e01e: 7ba8 ldrb r0, [r5, #14] +1001e020: b108 cbz r0, 1001e026 +1001e022: 2805 cmp r0, #5 +1001e024: db2f blt.n 1001e086 +1001e026: 1f41 subs r1, r0, #5 +1001e028: 290a cmp r1, #10 +1001e02a: d333 bcc.n 1001e094 +1001e02c: 2824 cmp r0, #36 ; 0x24 +1001e02e: d02a beq.n 1001e086 +1001e030: 2828 cmp r0, #40 ; 0x28 +1001e032: d02f beq.n 1001e094 +1001e034: 282c cmp r0, #44 ; 0x2c +1001e036: d026 beq.n 1001e086 +1001e038: 2830 cmp r0, #48 ; 0x30 +1001e03a: d02b beq.n 1001e094 +1001e03c: 2834 cmp r0, #52 ; 0x34 +1001e03e: d022 beq.n 1001e086 +1001e040: 2838 cmp r0, #56 ; 0x38 +1001e042: d027 beq.n 1001e094 +1001e044: 283c cmp r0, #60 ; 0x3c +1001e046: d01e beq.n 1001e086 +1001e048: 2840 cmp r0, #64 ; 0x40 +1001e04a: d023 beq.n 1001e094 +1001e04c: 2864 cmp r0, #100 ; 0x64 +1001e04e: d01a beq.n 1001e086 +1001e050: 2868 cmp r0, #104 ; 0x68 +1001e052: d01f beq.n 1001e094 +1001e054: 286c cmp r0, #108 ; 0x6c +1001e056: d016 beq.n 1001e086 +1001e058: 2870 cmp r0, #112 ; 0x70 +1001e05a: d01b beq.n 1001e094 +1001e05c: 2874 cmp r0, #116 ; 0x74 +1001e05e: d012 beq.n 1001e086 +1001e060: 2878 cmp r0, #120 ; 0x78 +1001e062: d017 beq.n 1001e094 +1001e064: 287c cmp r0, #124 ; 0x7c +1001e066: d00e beq.n 1001e086 +1001e068: 2880 cmp r0, #128 ; 0x80 +1001e06a: d013 beq.n 1001e094 +1001e06c: 2884 cmp r0, #132 ; 0x84 +1001e06e: d00a beq.n 1001e086 +1001e070: 2888 cmp r0, #136 ; 0x88 +1001e072: d00f beq.n 1001e094 +1001e074: 2895 cmp r0, #149 ; 0x95 +1001e076: d006 beq.n 1001e086 +1001e078: 2899 cmp r0, #153 ; 0x99 +1001e07a: d00b beq.n 1001e094 +1001e07c: 289d cmp r0, #157 ; 0x9d +1001e07e: d002 beq.n 1001e086 +1001e080: 28a1 cmp r0, #161 ; 0xa1 +1001e082: d007 beq.n 1001e094 +1001e084: e00f b.n 1001e0a6 +1001e086: b11f cbz r7, 1001e090 +1001e088: 7878 ldrb r0, [r7, #1] +1001e08a: f040 0001 orr.w r0, r0, #1 +1001e08e: 7078 strb r0, [r7, #1] +1001e090: 2001 movs r0, #1 +1001e092: e00e b.n 1001e0b2 +1001e094: b11f cbz r7, 1001e09e +1001e096: 7878 ldrb r0, [r7, #1] +1001e098: f040 0003 orr.w r0, r0, #3 +1001e09c: 7078 strb r0, [r7, #1] +1001e09e: 2001 movs r0, #1 +1001e0a0: 7070 strb r0, [r6, #1] +1001e0a2: 2002 movs r0, #2 +1001e0a4: e006 b.n 1001e0b4 +1001e0a6: b11f cbz r7, 1001e0b0 +1001e0a8: 7878 ldrb r0, [r7, #1] +1001e0aa: f000 00fc and.w r0, r0, #252 ; 0xfc +1001e0ae: 7078 strb r0, [r7, #1] +1001e0b0: 2000 movs r0, #0 +1001e0b2: 7070 strb r0, [r6, #1] +1001e0b4: 70b0 strb r0, [r6, #2] +1001e0b6: 7873 ldrb r3, [r6, #1] +1001e0b8: f000 f82c bl 1001e114 <.text_231> +1001e0bc: 7ba8 ldrb r0, [r5, #14] +1001e0be: 64e0 str r0, [r4, #76] ; 0x4c +1001e0c0: aa00 add r2, sp, #0 +1001e0c2: 6fa0 ldr r0, [r4, #120] ; 0x78 +1001e0c4: f1a0 030c sub.w r3, r0, #12 +1001e0c8: 2103 movs r1, #3 +1001e0ca: 4658 mov r0, fp +1001e0cc: f7f5 fed8 bl 10013e80 +1001e0d0: b120 cbz r0, 1001e0dc +1001e0d2: 9900 ldr r1, [sp, #0] +1001e0d4: 2901 cmp r1, #1 +1001e0d6: bfa4 itt ge +1001e0d8: 7ba9 ldrbge r1, [r5, #14] +1001e0da: 7081 strbge r1, [r0, #2] +1001e0dc: f000 f812 bl 1001e104 <.text_230> +1001e0e0: 2800 cmp r0, #0 +1001e0e2: bf1c itt ne +1001e0e4: 9900 ldrne r1, [sp, #0] +1001e0e6: 2900 cmpne r1, #0 +1001e0e8: d004 beq.n 1001e0f4 +1001e0ea: 7ba9 ldrb r1, [r5, #14] +1001e0ec: 7081 strb r1, [r0, #2] +1001e0ee: e001 b.n 1001e0f4 +1001e0f0: f000 f810 bl 1001e114 <.text_231> +1001e0f4: 2301 movs r3, #1 +1001e0f6: 2200 movs r2, #0 +1001e0f8: 2100 movs r1, #0 +1001e0fa: 4648 mov r0, r9 +1001e0fc: f7fb f800 bl 10019100 +1001e100: e8bd 8ff1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1001e104 <.text_230>: +1001e104: 6fa0 ldr r0, [r4, #120] ; 0x78 +1001e106: f1a0 030c sub.w r3, r0, #12 +1001e10a: aa00 add r2, sp, #0 +1001e10c: 213d movs r1, #61 ; 0x3d +1001e10e: 4658 mov r0, fp +1001e110: f7f5 beb6 b.w 10013e80 + +1001e114 <.text_231>: +1001e114: 78b2 ldrb r2, [r6, #2] +1001e116: f89a 100e ldrb.w r1, [sl, #14] +1001e11a: 4640 mov r0, r8 +1001e11c: f007 bd3c b.w 10025b98 + +1001e120 : +1001e120: b510 push {r4, lr} +1001e122: f500 649d add.w r4, r0, #1256 ; 0x4e8 +1001e126: b909 cbnz r1, 1001e12c +1001e128: 2004 movs r0, #4 +1001e12a: bd10 pop {r4, pc} +1001e12c: 7809 ldrb r1, [r1, #0] +1001e12e: f104 0214 add.w r2, r4, #20 +1001e132: f7fb fce7 bl 10019b04 +1001e136: 74a0 strb r0, [r4, #18] +1001e138: 2000 movs r0, #0 +1001e13a: bd10 pop {r4, pc} + +1001e13c <_survey_timer_hdl>: +1001e13c: f7ff bb27 b.w 1001d78e + +1001e140 <_link_timer_hdl>: +1001e140: f7ff bb83 b.w 1001d84a + +1001e144 : +1001e144: b570 push {r4, r5, r6, lr} +1001e146: b082 sub sp, #8 +1001e148: 4604 mov r4, r0 +1001e14a: f641 5624 movw r6, #7460 ; 0x1d24 +1001e14e: f20f 2024 addw r0, pc, #548 ; 0x224 +1001e152: 4a10 ldr r2, [pc, #64] ; (1001e194 <.text_237>) +1001e154: 9000 str r0, [sp, #0] +1001e156: f504 659d add.w r5, r4, #1256 ; 0x4e8 +1001e15a: 5931 ldr r1, [r6, r4] +1001e15c: 4623 mov r3, r4 +1001e15e: f505 7047 add.w r0, r5, #796 ; 0x31c +1001e162: f7f2 fc60 bl 10010a26 +1001e166: f20f 201c addw r0, pc, #540 ; 0x21c +1001e16a: 4a0b ldr r2, [pc, #44] ; (1001e198 <.text_238>) +1001e16c: 9000 str r0, [sp, #0] +1001e16e: 4623 mov r3, r4 +1001e170: 5931 ldr r1, [r6, r4] +1001e172: f505 704a add.w r0, r5, #808 ; 0x328 +1001e176: f7f2 fc56 bl 10010a26 +1001e17a: f20f 2014 addw r0, pc, #532 ; 0x214 +1001e17e: 4a07 ldr r2, [pc, #28] ; (1001e19c <.text_239>) +1001e180: 9000 str r0, [sp, #0] +1001e182: 4623 mov r3, r4 +1001e184: 5931 ldr r1, [r6, r4] +1001e186: f505 7053 add.w r0, r5, #844 ; 0x34c +1001e18a: f7f2 fc4c bl 10010a26 +1001e18e: bd73 pop {r0, r1, r4, r5, r6, pc} + +1001e190 <.text_236>: +1001e190: 10048b15 .word 0x10048b15 + +1001e194 <.text_237>: +1001e194: 1001e13d .word 0x1001e13d + +1001e198 <.text_238>: +1001e198: 1001e141 .word 0x1001e141 + +1001e19c <.text_239>: +1001e19c: 1001e599 .word 0x1001e599 + +1001e1a0 : +1001e1a0: b5f8 push {r3, r4, r5, r6, r7, lr} +1001e1a2: f8d1 6084 ldr.w r6, [r1, #132] ; 0x84 +1001e1a6: 4605 mov r5, r0 +1001e1a8: 214a movs r1, #74 ; 0x4a +1001e1aa: f44f 7000 mov.w r0, #512 ; 0x200 +1001e1ae: f7f3 f8f5 bl 1001139c +1001e1b2: 0004 movs r4, r0 +1001e1b4: d025 beq.n 1001e202 <__iar_annotation$$tailcall+0x2> +1001e1b6: 6927 ldr r7, [r4, #16] +1001e1b8: 2206 movs r2, #6 +1001e1ba: f106 010a add.w r1, r6, #10 +1001e1be: 4638 mov r0, r7 +1001e1c0: f7f2 fb25 bl 1001080e +1001e1c4: f505 51c8 add.w r1, r5, #6400 ; 0x1900 +1001e1c8: 2206 movs r2, #6 +1001e1ca: 3195 adds r1, #149 ; 0x95 +1001e1cc: 1db8 adds r0, r7, #6 +1001e1ce: f7f2 fb1e bl 1001080e +1001e1d2: f648 008e movw r0, #34958 ; 0x888e +1001e1d6: f7f2 faa3 bl 10010720 <_htons> +1001e1da: 81b8 strh r0, [r7, #12] +1001e1dc: 2101 movs r1, #1 +1001e1de: f107 000e add.w r0, r7, #14 +1001e1e2: 7001 strb r1, [r0, #0] +1001e1e4: 7041 strb r1, [r0, #1] +1001e1e6: 2100 movs r1, #0 +1001e1e8: 8041 strh r1, [r0, #2] +1001e1ea: 4620 mov r0, r4 +1001e1ec: 2112 movs r1, #18 +1001e1ee: f7f3 f901 bl 100113f4 +1001e1f2: f641 5024 movw r0, #7460 ; 0x1d24 +1001e1f6: 5941 ldr r1, [r0, r5] +1001e1f8: 6a8a ldr r2, [r1, #40] ; 0x28 +1001e1fa: 4620 mov r0, r4 +1001e1fc: e8bd 40f8 ldmia.w sp!, {r3, r4, r5, r6, r7, lr} + +1001e200 <__iar_annotation$$tailcall>: +1001e200: 4710 bx r2 +1001e202: bdf1 pop {r0, r4, r5, r6, r7, pc} + +1001e204 : +1001e204: 4552 4f43 4e4e 4345 4954 4e4f 4620 4941 RECONNECTION FAI +1001e214: 554c 4552 0000 0000 LURE.... + +1001e21c : +1001e21c: 5452 384c 3931 4135 445b 6972 6576 5d72 RTL8195A[Driver] +1001e22c: 203a 6f6e 6220 6165 6f63 206e 6f66 2072 : no beacon for +1001e23c: 2061 6f6c 676e 7420 6d69 2c65 6420 7369 a long time, dis +1001e24c: 6f63 6e6e 6365 2074 726f 7220 616f 696d connect or roami +1001e25c: 676e 000a ng.. + +1001e260 : +1001e260: 5452 384c 3931 4135 445b 6972 6576 5d72 RTL8195A[Driver] +1001e270: 203a 6573 2074 7267 756f 2070 656b 2079 : set group key +1001e280: 6f74 6820 3a77 6120 676c 253a 2864 4557 to hw: alg:%d(WE +1001e290: 3450 2d30 2031 4557 3150 3430 352d 5420 P40-1 WEP104-5 T +1001e2a0: 494b 2d50 2032 4541 2d53 2934 6b20 7965 KIP-2 AES-4) key +1001e2b0: 6469 253a 0a64 0000 id:%d... + +1001e2b8 : +1001e2b8: 5452 384c 3931 4135 445b 6972 6576 5d72 RTL8195A[Driver] +1001e2c8: 203a 6573 2074 6170 7269 6977 6573 6b20 : set pairwise k +1001e2d8: 7965 7420 206f 7768 203a 6c61 3a67 6425 ey to hw: alg:%d +1001e2e8: 5728 5045 3034 312d 5720 5045 3031 2d34 (WEP40-1 WEP104- +1001e2f8: 2035 4b54 5049 322d 4120 5345 342d 0a29 5 TKIP-2 AES-4). +1001e308: 0000 0000 .... + +1001e30c : +1001e30c: 5452 384c 3931 4135 445b 6972 6576 5d72 RTL8195A[Driver] +1001e31c: 203a 6573 2074 6170 7269 6977 6573 6b20 : set pairwise k +1001e32c: 7965 7420 206f 7768 203a 6c61 3a67 6425 ey to hw: alg:%d +1001e33c: 5728 5045 3034 312d 5720 5045 3031 2d34 (WEP40-1 WEP104- +1001e34c: 2035 4b54 5049 322d 4120 5345 342d 2029 5 TKIP-2 AES-4) +1001e35c: 6f66 2072 7825 253a 3a78 7825 253a 3a78 for %x:%x:%x:%x: +1001e36c: 7825 253a 0a78 0000 %x:%x... + +1001e374 : +1001e374: 7573 7672 7965 745f 6d69 7265 0000 0000 survey_timer.... + +1001e384 : +1001e384: 696c 6b6e 745f 6d69 7265 0000 link_timer.. + +1001e390 : +1001e390: 6572 6f63 6e6e 6365 5f74 6974 656d 0072 reconnect_timer. + +1001e3a0 : +1001e3a0: 0000 0000 ed1d 1001 0000 0000 0000 0000 ................ + ... +1001e3e4: eb9d 1001 0004 0000 ec21 1001 0000 0000 ........!....... +1001e3f4: f071 1001 000c 0000 f10b 1001 000c 0000 q............... +1001e404: f145 1001 0000 0000 0000 0000 0000 0000 E............... +1001e414: ed1d 1001 0000 0000 0000 0000 0000 0000 ................ + ... + +1001e460 : +1001e460: 5000 02f2 .P.. + +1001e464 : +1001e464: 6f80 ldr r0, [r0, #120] ; 0x78 +1001e466: 307c adds r0, #124 ; 0x7c +1001e468: 4770 bx lr + +1001e46a : +1001e46a: 6840 ldr r0, [r0, #4] +1001e46c: 4208 tst r0, r1 +1001e46e: d001 beq.n 1001e474 +1001e470: 2001 movs r0, #1 +1001e472: 4770 bx lr +1001e474: 2000 movs r0, #0 +1001e476: 4770 bx lr + +1001e478 : +1001e478: 6842 ldr r2, [r0, #4] +1001e47a: 430a orrs r2, r1 +1001e47c: 6042 str r2, [r0, #4] +1001e47e: f5b1 6f00 cmp.w r1, #2048 ; 0x800 +1001e482: bf04 itt eq +1001e484: 2101 moveq r1, #1 +1001e486: 7201 strbeq r1, [r0, #8] +1001e488: 4770 bx lr + +1001e48a <_clr_fwstate_>: +1001e48a: 6842 ldr r2, [r0, #4] +1001e48c: 438a bics r2, r1 +1001e48e: 6042 str r2, [r0, #4] +1001e490: f5b1 6f00 cmp.w r1, #2048 ; 0x800 +1001e494: bf04 itt eq +1001e496: 2100 moveq r1, #0 +1001e498: 7201 strbeq r1, [r0, #8] +1001e49a: 4770 bx lr + +1001e49c : +1001e49c: b510 push {r4, lr} +1001e49e: 4604 mov r4, r0 +1001e4a0: f000 fea1 bl 1001f1e6 <_rtw_join_timeout_handler> +1001e4a4: f894 08cc ldrb.w r0, [r4, #2252] ; 0x8cc +1001e4a8: b190 cbz r0, 1001e4d0 +1001e4aa: f894 0841 ldrb.w r0, [r4, #2113] ; 0x841 +1001e4ae: 1c40 adds r0, r0, #1 +1001e4b0: f884 0841 strb.w r0, [r4, #2113] ; 0x841 +1001e4b4: b2c0 uxtb r0, r0 +1001e4b6: 2803 cmp r0, #3 +1001e4b8: da07 bge.n 1001e4ca +1001e4ba: f604 0034 addw r0, r4, #2100 ; 0x834 +1001e4be: e8bd 4010 ldmia.w sp!, {r4, lr} +1001e4c2: f241 3188 movw r1, #5000 ; 0x1388 +1001e4c6: f7f2 bab8 b.w 10010a3a +1001e4ca: 2000 movs r0, #0 +1001e4cc: f884 0841 strb.w r0, [r4, #2113] ; 0x841 +1001e4d0: bd10 pop {r4, pc} + +1001e4d2 <_rtw_scan_timeout_handler>: +1001e4d2: f000 becc b.w 1001f26e + +1001e4d6 <_dynamic_check_timer_handlder>: +1001e4d6: b510 push {r4, lr} +1001e4d8: 4604 mov r4, r0 +1001e4da: f641 5048 movw r0, #7496 ; 0x1d48 +1001e4de: 5900 ldr r0, [r0, r4] +1001e4e0: b108 cbz r0, 1001e4e6 <_dynamic_check_timer_handlder+0x10> +1001e4e2: f000 fedc bl 1001f29e +1001e4e6: 4620 mov r0, r4 +1001e4e8: f000 fed9 bl 1001f29e +1001e4ec: f504 6092 add.w r0, r4, #1168 ; 0x490 +1001e4f0: e8bd 4010 ldmia.w sp!, {r4, lr} +1001e4f4: f44f 61fa mov.w r1, #2000 ; 0x7d0 +1001e4f8: f7f2 ba9f b.w 10010a3a + +1001e4fc : +1001e4fc: b570 push {r4, r5, r6, lr} +1001e4fe: b082 sub sp, #8 +1001e500: 4604 mov r4, r0 +1001e502: f641 5624 movw r6, #7460 ; 0x1d24 +1001e506: f20f 0040 addw r0, pc, #64 ; 0x40 +1001e50a: 4a3e ldr r2, [pc, #248] ; (1001e604 <.text_16>) +1001e50c: 9000 str r0, [sp, #0] +1001e50e: f104 050c add.w r5, r4, #12 +1001e512: 5931 ldr r1, [r6, r4] +1001e514: 4623 mov r3, r4 +1001e516: f505 6084 add.w r0, r5, #1056 ; 0x420 +1001e51a: f7f2 fa84 bl 10010a26 +1001e51e: f20f 0034 addw r0, pc, #52 ; 0x34 +1001e522: 4a39 ldr r2, [pc, #228] ; (1001e608 <.text_17>) +1001e524: 9000 str r0, [sp, #0] +1001e526: 4623 mov r3, r4 +1001e528: 5931 ldr r1, [r6, r4] +1001e52a: f505 6086 add.w r0, r5, #1072 ; 0x430 +1001e52e: f7f2 fa7a bl 10010a26 +1001e532: f20f 0030 addw r0, pc, #48 ; 0x30 +1001e536: 4a35 ldr r2, [pc, #212] ; (1001e60c <.text_18>) +1001e538: 9000 str r0, [sp, #0] +1001e53a: 4623 mov r3, r4 +1001e53c: 5931 ldr r1, [r6, r4] +1001e53e: f205 4084 addw r0, r5, #1156 ; 0x484 +1001e542: f7f2 fa70 bl 10010a26 +1001e546: bd73 pop {r0, r1, r4, r5, r6, pc} + +1001e548 : +1001e548: 7361 6f73 5f63 6974 656d 0072 assoc_timer. + +1001e554 : +1001e554: 6373 6e61 745f 5f6f 6974 656d 0072 0000 scan_to_timer... + +1001e564 : +1001e564: 7964 616e 696d 5f63 6863 5f6b 6974 656d dynamic_chk_time +1001e574: 0072 0000 r... + +1001e578 : +1001e578: b510 push {r4, lr} +1001e57a: 4604 mov r4, r0 +1001e57c: f504 6084 add.w r0, r4, #1056 ; 0x420 +1001e580: f7f2 fa6b bl 10010a5a +1001e584: f504 6086 add.w r0, r4, #1072 ; 0x430 +1001e588: f7f2 fa67 bl 10010a5a +1001e58c: f204 4084 addw r0, r4, #1156 ; 0x484 +1001e590: e8bd 4010 ldmia.w sp!, {r4, lr} +1001e594: f7f2 ba61 b.w 10010a5a + +1001e598 : +1001e598: e92d 47fc stmdb sp!, {r2, r3, r4, r5, r6, r7, r8, r9, sl, lr} +1001e59c: f500 699d add.w r9, r0, #1256 ; 0x4e8 +1001e5a0: 2101 movs r1, #1 +1001e5a2: f899 635e ldrb.w r6, [r9, #862] ; 0x35e +1001e5a6: 300c adds r0, #12 +1001e5a8: f7ff ff5f bl 1001e46a +1001e5ac: bb38 cbnz r0, 1001e5fe +1001e5ae: 4c18 ldr r4, [pc, #96] ; (1001e610 <.text_19>) +1001e5b0: 6820 ldr r0, [r4, #0] +1001e5b2: b320 cbz r0, 1001e5fe +1001e5b4: 2700 movs r7, #0 +1001e5b6: 2500 movs r5, #0 +1001e5b8: 2e01 cmp r6, #1 +1001e5ba: 46b8 mov r8, r7 +1001e5bc: 46ba mov sl, r7 +1001e5be: d107 bne.n 1001e5d0 +1001e5c0: f8b9 53a0 ldrh.w r5, [r9, #928] ; 0x3a0 +1001e5c4: f899 a3a2 ldrb.w sl, [r9, #930] ; 0x3a2 +1001e5c8: 2701 movs r7, #1 +1001e5ca: f209 387f addw r8, r9, #895 ; 0x37f +1001e5ce: e008 b.n 1001e5e2 +1001e5d0: 2e03 cmp r6, #3 +1001e5d2: d106 bne.n 1001e5e2 +1001e5d4: f209 38a3 addw r8, r9, #931 ; 0x3a3 +1001e5d8: 4f0e ldr r7, [pc, #56] ; (1001e614 <.text_20>) +1001e5da: 4640 mov r0, r8 +1001e5dc: f7ed febc bl 1000c358 +1001e5e0: 4605 mov r5, r0 +1001e5e2: f209 395f addw r9, r9, #863 ; 0x35f +1001e5e6: 4648 mov r0, r9 +1001e5e8: f7ed feb6 bl 1000c358 +1001e5ec: f8cd a004 str.w sl, [sp, #4] +1001e5f0: 9500 str r5, [sp, #0] +1001e5f2: 4602 mov r2, r0 +1001e5f4: 6824 ldr r4, [r4, #0] +1001e5f6: 4643 mov r3, r8 +1001e5f8: 4649 mov r1, r9 +1001e5fa: 4638 mov r0, r7 +1001e5fc: 47a0 blx r4 +1001e5fe: e8bd 87f3 ldmia.w sp!, {r0, r1, r4, r5, r6, r7, r8, r9, sl, pc} + ... + +1001e604 <.text_16>: +1001e604: 1001e49d .word 0x1001e49d + +1001e608 <.text_17>: +1001e608: 1001e4d3 .word 0x1001e4d3 + +1001e60c <.text_18>: +1001e60c: 1001e4d7 .word 0x1001e4d7 + +1001e610 <.text_19>: +1001e610: 10048834 .word 0x10048834 + +1001e614 <.text_20>: +1001e614: 00400004 .word 0x00400004 + +1001e618 <_rtw_init_mlme_priv>: +1001e618: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1001e61c: 4604 mov r4, r0 +1001e61e: f104 050c add.w r5, r4, #12 +1001e622: 1d2f adds r7, r5, #4 +1001e624: b082 sub sp, #8 +1001e626: 60bc str r4, [r7, #8] +1001e628: 2000 movs r0, #0 +1001e62a: 60f8 str r0, [r7, #12] +1001e62c: 6068 str r0, [r5, #4] +1001e62e: 2601 movs r6, #1 +1001e630: 2002 movs r0, #2 +1001e632: f8c5 00ec str.w r0, [r5, #236] ; 0xec +1001e636: f8c5 6494 str.w r6, [r5, #1172] ; 0x494 +1001e63a: 4628 mov r0, r5 +1001e63c: f7f2 f98b bl 10010956 +1001e640: f105 0014 add.w r0, r5, #20 +1001e644: f7f2 f977 bl 10010936 +1001e648: f105 0020 add.w r0, r5, #32 +1001e64c: f7f2 f973 bl 10010936 +1001e650: a900 add r1, sp, #0 +1001e652: 4628 mov r0, r5 +1001e654: f7f2 f95e bl 10010914 +1001e658: 2000 movs r0, #0 +1001e65a: 85b8 strh r0, [r7, #44] ; 0x2c +1001e65c: f000 fb5a bl 1001ed14 <.text_55> +1001e660: 2228 movs r2, #40 ; 0x28 +1001e662: 2100 movs r1, #0 +1001e664: f105 0040 add.w r0, r5, #64 ; 0x40 +1001e668: f7f2 f8e6 bl 10010838 +1001e66c: f641 5051 movw r0, #7505 ; 0x1d51 +1001e670: 5d00 ldrb r0, [r0, r4] +1001e672: b9b8 cbnz r0, 1001e6a4 <_rtw_init_mlme_priv+0x8c> +1001e674: f44f 706b mov.w r0, #940 ; 0x3ac +1001e678: f7f2 f8ae bl 100107d8 +1001e67c: ea5f 0800 movs.w r8, r0 +1001e680: bf08 it eq +1001e682: 2600 moveq r6, #0 +1001e684: d011 beq.n 1001e6aa <_rtw_init_mlme_priv+0x92> +1001e686: f8c7 8028 str.w r8, [r7, #40] ; 0x28 +1001e68a: 2701 movs r7, #1 +1001e68c: 4640 mov r0, r8 +1001e68e: f7f2 f8dd bl 1001084c +1001e692: f105 0114 add.w r1, r5, #20 +1001e696: 4640 mov r0, r8 +1001e698: f7f2 f8e2 bl 10010860 +1001e69c: 1e7f subs r7, r7, #1 +1001e69e: f508 786b add.w r8, r8, #940 ; 0x3ac +1001e6a2: d1f3 bne.n 1001e68c <_rtw_init_mlme_priv+0x74> +1001e6a4: 4620 mov r0, r4 +1001e6a6: f7ff ff29 bl 1001e4fc +1001e6aa: 4630 mov r0, r6 +1001e6ac: e8bd 81f6 ldmia.w sp!, {r1, r2, r4, r5, r6, r7, r8, pc} + +1001e6b0 : +1001e6b0: b510 push {r4, lr} +1001e6b2: 4604 mov r4, r0 +1001e6b4: f7f2 f956 bl 10010964 +1001e6b8: f104 001c add.w r0, r4, #28 +1001e6bc: f7f2 f952 bl 10010964 +1001e6c0: f104 0028 add.w r0, r4, #40 ; 0x28 +1001e6c4: e8bd 4010 ldmia.w sp!, {r4, lr} +1001e6c8: f7f2 b94c b.w 10010964 + +1001e6cc : +1001e6cc: b538 push {r3, r4, r5, lr} +1001e6ce: 4604 mov r4, r0 +1001e6d0: 460d mov r5, r1 +1001e6d2: 6820 ldr r0, [r4, #0] +1001e6d4: b128 cbz r0, 1001e6e2 +1001e6d6: 6829 ldr r1, [r5, #0] +1001e6d8: f7f2 f898 bl 1001080c +1001e6dc: 2000 movs r0, #0 +1001e6de: 6028 str r0, [r5, #0] +1001e6e0: 6020 str r0, [r4, #0] +1001e6e2: bd31 pop {r0, r4, r5, pc} + +1001e6e4 : +1001e6e4: b510 push {r4, lr} +1001e6e6: 4604 mov r4, r0 +1001e6e8: f204 41c4 addw r1, r4, #1220 ; 0x4c4 +1001e6ec: f504 6097 add.w r0, r4, #1208 ; 0x4b8 +1001e6f0: f7ff ffec bl 1001e6cc +1001e6f4: f204 419c addw r1, r4, #1180 ; 0x49c +1001e6f8: f504 6093 add.w r0, r4, #1176 ; 0x498 +1001e6fc: f7ff ffe6 bl 1001e6cc +1001e700: f504 6199 add.w r1, r4, #1224 ; 0x4c8 +1001e704: f204 40bc addw r0, r4, #1212 ; 0x4bc +1001e708: f7ff ffe0 bl 1001e6cc +1001e70c: f204 41cc addw r1, r4, #1228 ; 0x4cc +1001e710: f504 6098 add.w r0, r4, #1216 ; 0x4c0 +1001e714: e8bd 4010 ldmia.w sp!, {r4, lr} +1001e718: e7d8 b.n 1001e6cc + +1001e71a <_rtw_free_mlme_priv>: +1001e71a: b510 push {r4, lr} +1001e71c: 4604 mov r4, r0 +1001e71e: f7ff ffe1 bl 1001e6e4 +1001e722: b164 cbz r4, 1001e73e <_rtw_free_mlme_priv+0x24> +1001e724: 4620 mov r0, r4 +1001e726: f7ff ffc3 bl 1001e6b0 +1001e72a: 6ae0 ldr r0, [r4, #44] ; 0x2c +1001e72c: b118 cbz r0, 1001e736 <_rtw_free_mlme_priv+0x1c> +1001e72e: f44f 716b mov.w r1, #940 ; 0x3ac +1001e732: f7f2 f860 bl 100107f6 +1001e736: 4620 mov r0, r4 +1001e738: e8bd 4010 ldmia.w sp!, {r4, lr} +1001e73c: e71c b.n 1001e578 +1001e73e: bd10 pop {r4, pc} + +1001e740 <_rtw_alloc_network>: +1001e740: b570 push {r4, r5, r6, lr} +1001e742: 4605 mov r5, r0 +1001e744: b082 sub sp, #8 +1001e746: f105 0414 add.w r4, r5, #20 +1001e74a: f000 f820 bl 1001e78e <.text_29> +1001e74e: 4620 mov r0, r4 +1001e750: f7f2 f8fa bl 10010948 +1001e754: 2801 cmp r0, #1 +1001e756: bf08 it eq +1001e758: 2600 moveq r6, #0 +1001e75a: d00f beq.n 1001e77c <_rtw_alloc_network+0x3c> +1001e75c: 6826 ldr r6, [r4, #0] +1001e75e: 4630 mov r0, r6 +1001e760: f7f2 f880 bl 10010864 +1001e764: 2000 movs r0, #0 +1001e766: 60b0 str r0, [r6, #8] +1001e768: 60f0 str r0, [r6, #12] +1001e76a: f7f2 f910 bl 1001098e +1001e76e: 6130 str r0, [r6, #16] +1001e770: 2000 movs r0, #0 +1001e772: 6170 str r0, [r6, #20] +1001e774: 61b0 str r0, [r6, #24] +1001e776: 8e28 ldrh r0, [r5, #48] ; 0x30 +1001e778: 1c40 adds r0, r0, #1 +1001e77a: 8628 strh r0, [r5, #48] ; 0x30 +1001e77c: f000 f802 bl 1001e784 <.text_28> +1001e780: 4630 mov r0, r6 +1001e782: bd76 pop {r1, r2, r4, r5, r6, pc} + +1001e784 <.text_28>: +1001e784: a900 add r1, sp, #0 +1001e786: f104 0008 add.w r0, r4, #8 +1001e78a: f7f2 b8c4 b.w 10010916 + +1001e78e <.text_29>: +1001e78e: a900 add r1, sp, #0 +1001e790: f104 0008 add.w r0, r4, #8 +1001e794: f7f2 b8be b.w 10010914 + +1001e798 <_rtw_free_network>: +1001e798: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +1001e79c: 460e mov r6, r1 +1001e79e: 2514 movs r5, #20 +1001e7a0: 4604 mov r4, r0 +1001e7a2: 2e00 cmp r6, #0 +1001e7a4: bf1c itt ne +1001e7a6: 68f0 ldrne r0, [r6, #12] +1001e7a8: 2801 cmpne r0, #1 +1001e7aa: 4617 mov r7, r2 +1001e7ac: f104 0814 add.w r8, r4, #20 +1001e7b0: d02b beq.n 1001e80a <_rtw_free_network+0x72> +1001e7b2: f7f2 f8ec bl 1001098e +1001e7b6: 4681 mov r9, r0 +1001e7b8: 2140 movs r1, #64 ; 0x40 +1001e7ba: 4620 mov r0, r4 +1001e7bc: f7ff fe55 bl 1001e46a +1001e7c0: 2801 cmp r0, #1 +1001e7c2: d005 beq.n 1001e7d0 <_rtw_free_network+0x38> +1001e7c4: 2120 movs r1, #32 +1001e7c6: 4620 mov r0, r4 +1001e7c8: f7ff fe4f bl 1001e46a +1001e7cc: 2801 cmp r0, #1 +1001e7ce: d100 bne.n 1001e7d2 <_rtw_free_network+0x3a> +1001e7d0: 2501 movs r5, #1 +1001e7d2: b937 cbnz r7, 1001e7e2 <_rtw_free_network+0x4a> +1001e7d4: 6930 ldr r0, [r6, #16] +1001e7d6: eba9 0000 sub.w r0, r9, r0 +1001e7da: f7f2 f8e8 bl 100109ae +1001e7de: 42a8 cmp r0, r5 +1001e7e0: d313 bcc.n 1001e80a <_rtw_free_network+0x72> +1001e7e2: a900 add r1, sp, #0 +1001e7e4: f108 0008 add.w r0, r8, #8 +1001e7e8: f7f2 f894 bl 10010914 +1001e7ec: 4630 mov r0, r6 +1001e7ee: f7f2 f839 bl 10010864 +1001e7f2: 4641 mov r1, r8 +1001e7f4: 4630 mov r0, r6 +1001e7f6: f7f2 f833 bl 10010860 +1001e7fa: 8e20 ldrh r0, [r4, #48] ; 0x30 +1001e7fc: 1e40 subs r0, r0, #1 +1001e7fe: 8620 strh r0, [r4, #48] ; 0x30 +1001e800: a900 add r1, sp, #0 +1001e802: f108 0008 add.w r0, r8, #8 +1001e806: f7f2 f886 bl 10010916 +1001e80a: e8bd 83f1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, pc} + +1001e80e <_rtw_free_network_nolock>: +1001e80e: b570 push {r4, r5, r6, lr} +1001e810: 4604 mov r4, r0 +1001e812: 000d movs r5, r1 +1001e814: bf1c itt ne +1001e816: 68e8 ldrne r0, [r5, #12] +1001e818: 2801 cmpne r0, #1 +1001e81a: f104 0614 add.w r6, r4, #20 +1001e81e: d009 beq.n 1001e834 <_rtw_free_network_nolock+0x26> +1001e820: 4628 mov r0, r5 +1001e822: f7f2 f81f bl 10010864 +1001e826: 4631 mov r1, r6 +1001e828: 4628 mov r0, r5 +1001e82a: f7f2 f819 bl 10010860 +1001e82e: 8e20 ldrh r0, [r4, #48] ; 0x30 +1001e830: 1e40 subs r0, r0, #1 +1001e832: 8620 strh r0, [r4, #48] ; 0x30 +1001e834: bd70 pop {r4, r5, r6, pc} + +1001e836 <_rtw_find_network>: +1001e836: b57c push {r2, r3, r4, r5, r6, lr} +1001e838: 4604 mov r4, r0 +1001e83a: 460d mov r5, r1 +1001e83c: a800 add r0, sp, #0 +1001e83e: 2100 movs r1, #0 +1001e840: 460a mov r2, r1 +1001e842: c006 stmia r0!, {r1, r2} +1001e844: 2600 movs r6, #0 +1001e846: 2206 movs r2, #6 +1001e848: 4629 mov r1, r5 +1001e84a: a800 add r0, sp, #0 +1001e84c: f7f1 ffe9 bl 10010822 +1001e850: b968 cbnz r0, 1001e86e <_rtw_find_network+0x38> +1001e852: 6826 ldr r6, [r4, #0] +1001e854: e008 b.n 1001e868 <_rtw_find_network+0x32> +1001e856: 2206 movs r2, #6 +1001e858: f106 0120 add.w r1, r6, #32 +1001e85c: 4628 mov r0, r5 +1001e85e: f7f1 ffe0 bl 10010822 +1001e862: 2801 cmp r0, #1 +1001e864: d003 beq.n 1001e86e <_rtw_find_network+0x38> +1001e866: 6836 ldr r6, [r6, #0] +1001e868: 42a6 cmp r6, r4 +1001e86a: d1f4 bne.n 1001e856 <_rtw_find_network+0x20> +1001e86c: 2600 movs r6, #0 +1001e86e: 4630 mov r0, r6 +1001e870: bd76 pop {r1, r2, r4, r5, r6, pc} + +1001e872 <_rtw_free_network_queue>: +1001e872: b5f8 push {r3, r4, r5, r6, r7, lr} +1001e874: f100 050c add.w r5, r0, #12 +1001e878: 460c mov r4, r1 +1001e87a: f105 0620 add.w r6, r5, #32 +1001e87e: f000 fcf1 bl 1001f264 <.text_78> +1001e882: 6837 ldr r7, [r6, #0] +1001e884: e005 b.n 1001e892 <_rtw_free_network_queue+0x20> +1001e886: 4639 mov r1, r7 +1001e888: 683f ldr r7, [r7, #0] +1001e88a: 4622 mov r2, r4 +1001e88c: 4628 mov r0, r5 +1001e88e: f7ff ff83 bl 1001e798 <_rtw_free_network> +1001e892: 4639 mov r1, r7 +1001e894: 4630 mov r0, r6 +1001e896: f7f2 f858 bl 1001094a +1001e89a: 2800 cmp r0, #0 +1001e89c: d0f3 beq.n 1001e886 <_rtw_free_network_queue+0x14> +1001e89e: f000 f801 bl 1001e8a4 <.text_34> +1001e8a2: bdf1 pop {r0, r4, r5, r6, r7, pc} + +1001e8a4 <.text_34>: +1001e8a4: a900 add r1, sp, #0 +1001e8a6: f106 0008 add.w r0, r6, #8 +1001e8aa: f7f2 b834 b.w 10010916 + +1001e8ae : +1001e8ae: b580 push {r7, lr} +1001e8b0: f641 419c movw r1, #7324 ; 0x1c9c +1001e8b4: 580a ldr r2, [r1, r0] +1001e8b6: 2a00 cmp r2, #0 +1001e8b8: bf02 ittt eq +1001e8ba: 1809 addeq r1, r1, r0 +1001e8bc: 6849 ldreq r1, [r1, #4] +1001e8be: 2900 cmpeq r1, #0 +1001e8c0: d106 bne.n 1001e8d0 +1001e8c2: 2101 movs r1, #1 +1001e8c4: 300c adds r0, #12 +1001e8c6: f7ff fdd0 bl 1001e46a +1001e8ca: b110 cbz r0, 1001e8d2 +1001e8cc: 2001 movs r0, #1 +1001e8ce: bd02 pop {r1, pc} +1001e8d0: 2000 movs r0, #0 +1001e8d2: bd02 pop {r1, pc} + +1001e8d4 : +1001e8d4: 300a adds r0, #10 +1001e8d6: 4770 bx lr + +1001e8d8 : +1001e8d8: b580 push {r7, lr} +1001e8da: f100 0186 add.w r1, r0, #134 ; 0x86 +1001e8de: 2202 movs r2, #2 +1001e8e0: a800 add r0, sp, #0 +1001e8e2: f7f1 ff94 bl 1001080e +1001e8e6: f8bd 0000 ldrh.w r0, [sp] +1001e8ea: bd02 pop {r1, pc} + +1001e8ec : +1001e8ec: 3008 adds r0, #8 +1001e8ee: 4770 bx lr + +1001e8f0 : +1001e8f0: b538 push {r3, r4, r5, lr} +1001e8f2: 4604 mov r4, r0 +1001e8f4: f7ff fe90 bl 1001e618 <_rtw_init_mlme_priv> +1001e8f8: 0005 movs r5, r0 +1001e8fa: bf04 itt eq +1001e8fc: f104 000c addeq.w r0, r4, #12 +1001e900: f7ff ff0b bleq 1001e71a <_rtw_free_mlme_priv> +1001e904: 4628 mov r0, r5 +1001e906: bd32 pop {r1, r4, r5, pc} + +1001e908 : +1001e908: e707 b.n 1001e71a <_rtw_free_mlme_priv> + +1001e90a : +1001e90a: e719 b.n 1001e740 <_rtw_alloc_network> + +1001e90c : +1001e90c: e77f b.n 1001e80e <_rtw_free_network_nolock> + +1001e90e : +1001e90e: e7b0 b.n 1001e872 <_rtw_free_network_queue> + +1001e910 : +1001e910: e791 b.n 1001e836 <_rtw_find_network> + +1001e912 : +1001e912: f241 13f4 movw r3, #4596 ; 0x11f4 +1001e916: 2201 movs r2, #1 +1001e918: 5818 ldr r0, [r3, r0] +1001e91a: 2800 cmp r0, #0 +1001e91c: 6d08 ldr r0, [r1, #80] ; 0x50 +1001e91e: d001 beq.n 1001e924 +1001e920: b918 cbnz r0, 1001e92a +1001e922: e001 b.n 1001e928 +1001e924: 2801 cmp r0, #1 +1001e926: d100 bne.n 1001e92a +1001e928: 2200 movs r2, #0 +1001e92a: 4610 mov r0, r2 +1001e92c: 4770 bx lr + +1001e92e : +1001e92e: b538 push {r3, r4, r5, lr} +1001e930: 4604 mov r4, r0 +1001e932: 460d mov r5, r1 +1001e934: 2202 movs r2, #2 +1001e936: f104 0186 add.w r1, r4, #134 ; 0x86 +1001e93a: f10d 0002 add.w r0, sp, #2 +1001e93e: f7f1 ff66 bl 1001080e +1001e942: 2202 movs r2, #2 +1001e944: f105 0186 add.w r1, r5, #134 ; 0x86 +1001e948: a800 add r0, sp, #0 +1001e94a: f7f1 ff60 bl 1001080e +1001e94e: 68e0 ldr r0, [r4, #12] +1001e950: 68e9 ldr r1, [r5, #12] +1001e952: 4288 cmp r0, r1 +1001e954: d121 bne.n 1001e99a +1001e956: 2206 movs r2, #6 +1001e958: 1d29 adds r1, r5, #4 +1001e95a: 1d20 adds r0, r4, #4 +1001e95c: f7f1 ff61 bl 10010822 +1001e960: 2801 cmp r0, #1 +1001e962: d11a bne.n 1001e99a +1001e964: 68e2 ldr r2, [r4, #12] +1001e966: f105 0110 add.w r1, r5, #16 +1001e96a: f104 0010 add.w r0, r4, #16 +1001e96e: f7f1 ff58 bl 10010822 +1001e972: 2801 cmp r0, #1 +1001e974: d111 bne.n 1001e99a +1001e976: f8bd 0000 ldrh.w r0, [sp] +1001e97a: f8bd 1002 ldrh.w r1, [sp, #2] +1001e97e: f001 0202 and.w r2, r1, #2 +1001e982: f000 0302 and.w r3, r0, #2 +1001e986: 429a cmp r2, r3 +1001e988: bf02 ittt eq +1001e98a: f001 0101 andeq.w r1, r1, #1 +1001e98e: f000 0001 andeq.w r0, r0, #1 +1001e992: 4281 cmpeq r1, r0 +1001e994: d101 bne.n 1001e99a +1001e996: 2001 movs r0, #1 +1001e998: bd32 pop {r1, r4, r5, pc} +1001e99a: 2000 movs r0, #0 +1001e99c: bd32 pop {r1, r4, r5, pc} + +1001e99e : +1001e99e: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1001e9a2: 4605 mov r5, r0 +1001e9a4: 460e mov r6, r1 +1001e9a6: 6ba8 ldr r0, [r5, #56] ; 0x38 +1001e9a8: 9000 str r0, [sp, #0] +1001e9aa: f106 0a74 add.w sl, r6, #116 ; 0x74 +1001e9ae: 4614 mov r4, r2 +1001e9b0: f89a 7001 ldrb.w r7, [sl, #1] +1001e9b4: 469b mov fp, r3 +1001e9b6: f105 0874 add.w r8, r5, #116 ; 0x74 +1001e9ba: f000 ff2b bl 1001f814 <.text_99> +1001e9be: b1a8 cbz r0, 1001e9ec +1001e9c0: 4631 mov r1, r6 +1001e9c2: f104 0098 add.w r0, r4, #152 ; 0x98 +1001e9c6: f7ff ffb2 bl 1001e92e +1001e9ca: b178 cbz r0, 1001e9ec +1001e9cc: f894 9dbe ldrb.w r9, [r4, #3518] ; 0xdbe +1001e9d0: f894 adbf ldrb.w sl, [r4, #3519] ; 0xdbf +1001e9d4: 2f65 cmp r7, #101 ; 0x65 +1001e9d6: d007 beq.n 1001e9e8 +1001e9d8: 6bb0 ldr r0, [r6, #56] ; 0x38 +1001e9da: 6ba9 ldr r1, [r5, #56] ; 0x38 +1001e9dc: eb00 0081 add.w r0, r0, r1, lsl #2 +1001e9e0: 2105 movs r1, #5 +1001e9e2: fb90 f4f1 sdiv r4, r0, r1 +1001e9e6: e01c b.n 1001ea22 +1001e9e8: 9c00 ldr r4, [sp, #0] +1001e9ea: e01a b.n 1001ea22 +1001e9ec: f898 0001 ldrb.w r0, [r8, #1] +1001e9f0: 6bac ldr r4, [r5, #56] ; 0x38 +1001e9f2: f895 9074 ldrb.w r9, [r5, #116] ; 0x74 +1001e9f6: 2f65 cmp r7, #101 ; 0x65 +1001e9f8: d012 beq.n 1001ea20 +1001e9fa: f896 1074 ldrb.w r1, [r6, #116] ; 0x74 +1001e9fe: eb01 0189 add.w r1, r1, r9, lsl #2 +1001ea02: 2205 movs r2, #5 +1001ea04: fbb1 f9f2 udiv r9, r1, r2 +1001ea08: f89a 1001 ldrb.w r1, [sl, #1] +1001ea0c: eb01 0080 add.w r0, r1, r0, lsl #2 +1001ea10: fbb0 faf2 udiv sl, r0, r2 +1001ea14: 6bb0 ldr r0, [r6, #56] ; 0x38 +1001ea16: eb00 0084 add.w r0, r0, r4, lsl #2 +1001ea1a: fb90 f4f2 sdiv r4, r0, r2 +1001ea1e: e000 b.n 1001ea22 +1001ea20: 4682 mov sl, r0 +1001ea22: f1bb 0f00 cmp.w fp, #0 +1001ea26: d007 beq.n 1001ea38 +1001ea28: 4630 mov r0, r6 +1001ea2a: f7ff fd1b bl 1001e464 +1001ea2e: 4602 mov r2, r0 +1001ea30: 4631 mov r1, r6 +1001ea32: 4628 mov r0, r5 +1001ea34: f7f1 feeb bl 1001080e +1001ea38: f885 9074 strb.w r9, [r5, #116] ; 0x74 +1001ea3c: f888 a001 strb.w sl, [r8, #1] +1001ea40: 63ac str r4, [r5, #56] ; 0x38 +1001ea42: e8bd 8ff1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1001ea46 : +1001ea46: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +1001ea4a: 4680 mov r8, r0 +1001ea4c: f108 040c add.w r4, r8, #12 +1001ea50: b082 sub sp, #8 +1001ea52: 460d mov r5, r1 +1001ea54: f104 0920 add.w r9, r4, #32 +1001ea58: 2700 movs r7, #0 +1001ea5a: 2600 movs r6, #0 +1001ea5c: a900 add r1, sp, #0 +1001ea5e: f109 0008 add.w r0, r9, #8 +1001ea62: f7f1 ff57 bl 10010914 +1001ea66: f8d9 a000 ldr.w sl, [r9] +1001ea6a: e007 b.n 1001ea7c +1001ea6c: b11e cbz r6, 1001ea76 +1001ea6e: 6938 ldr r0, [r7, #16] +1001ea70: 6931 ldr r1, [r6, #16] +1001ea72: 1a40 subs r0, r0, r1 +1001ea74: d500 bpl.n 1001ea78 +1001ea76: 463e mov r6, r7 +1001ea78: f8da a000 ldr.w sl, [sl] +1001ea7c: 4651 mov r1, sl +1001ea7e: 4648 mov r0, r9 +1001ea80: f7f1 ff63 bl 1001094a +1001ea84: 2801 cmp r0, #1 +1001ea86: d007 beq.n 1001ea98 +1001ea88: 4657 mov r7, sl +1001ea8a: 4629 mov r1, r5 +1001ea8c: f107 001c add.w r0, r7, #28 +1001ea90: f7ff ff4d bl 1001e92e +1001ea94: 2800 cmp r0, #0 +1001ea96: d0e9 beq.n 1001ea6c +1001ea98: 4651 mov r1, sl +1001ea9a: 4648 mov r0, r9 +1001ea9c: f7f1 ff55 bl 1001094a +1001eaa0: 2801 cmp r0, #1 +1001eaa2: d13d bne.n 1001eb20 +1001eaa4: f104 0014 add.w r0, r4, #20 +1001eaa8: f7f1 ff4e bl 10010948 +1001eaac: 2801 cmp r0, #1 +1001eaae: d119 bne.n 1001eae4 +1001eab0: 4628 mov r0, r5 +1001eab2: f7ff fcd7 bl 1001e464 +1001eab6: 4602 mov r2, r0 +1001eab8: 4629 mov r1, r5 +1001eaba: f106 001c add.w r0, r6, #28 +1001eabe: f7f1 fea6 bl 1001080e +1001eac2: 2000 movs r0, #0 +1001eac4: 60f0 str r0, [r6, #12] +1001eac6: f7f1 ff62 bl 1001098e +1001eaca: 6130 str r0, [r6, #16] +1001eacc: 2000 movs r0, #0 +1001eace: 60b0 str r0, [r6, #8] +1001ead0: 6170 str r0, [r6, #20] +1001ead2: 61b0 str r0, [r6, #24] +1001ead4: f896 0091 ldrb.w r0, [r6, #145] ; 0x91 +1001ead8: 2865 cmp r0, #101 ; 0x65 +1001eada: d135 bne.n 1001eb48 +1001eadc: 2000 movs r0, #0 +1001eade: f886 0091 strb.w r0, [r6, #145] ; 0x91 +1001eae2: e031 b.n 1001eb48 +1001eae4: 4620 mov r0, r4 +1001eae6: f7ff ff10 bl 1001e90a +1001eaea: 0007 movs r7, r0 +1001eaec: d02c beq.n 1001eb48 +1001eaee: 4628 mov r0, r5 +1001eaf0: f7ff fcb8 bl 1001e464 +1001eaf4: 4602 mov r2, r0 +1001eaf6: 602a str r2, [r5, #0] +1001eaf8: 4629 mov r1, r5 +1001eafa: f107 001c add.w r0, r7, #28 +1001eafe: f7f1 fe86 bl 1001080e +1001eb02: f7f1 ff44 bl 1001098e +1001eb06: 6138 str r0, [r7, #16] +1001eb08: 4649 mov r1, r9 +1001eb0a: f897 0091 ldrb.w r0, [r7, #145] ; 0x91 +1001eb0e: 2865 cmp r0, #101 ; 0x65 +1001eb10: bf04 itt eq +1001eb12: 2000 moveq r0, #0 +1001eb14: f887 0091 strbeq.w r0, [r7, #145] ; 0x91 +1001eb18: 4638 mov r0, r7 +1001eb1a: f7f1 fea1 bl 10010860 +1001eb1e: e013 b.n 1001eb48 +1001eb20: 2401 movs r4, #1 +1001eb22: f7f1 ff34 bl 1001098e +1001eb26: 6138 str r0, [r7, #16] +1001eb28: f8d7 1094 ldr.w r1, [r7, #148] ; 0x94 +1001eb2c: 6fa8 ldr r0, [r5, #120] ; 0x78 +1001eb2e: 4288 cmp r0, r1 +1001eb30: d203 bcs.n 1001eb3a +1001eb32: 7aa8 ldrb r0, [r5, #10] +1001eb34: 2801 cmp r0, #1 +1001eb36: bf08 it eq +1001eb38: 2400 moveq r4, #0 +1001eb3a: 4623 mov r3, r4 +1001eb3c: 4642 mov r2, r8 +1001eb3e: 4629 mov r1, r5 +1001eb40: f107 001c add.w r0, r7, #28 +1001eb44: f7ff ff2b bl 1001e99e +1001eb48: a900 add r1, sp, #0 +1001eb4a: f109 0008 add.w r0, r9, #8 +1001eb4e: f7f1 fee2 bl 10010916 +1001eb52: e8bd 87f3 ldmia.w sp!, {r0, r1, r4, r5, r6, r7, r8, r9, sl, pc} + +1001eb56 : +1001eb56: b5f8 push {r3, r4, r5, r6, r7, lr} +1001eb58: 4604 mov r4, r0 +1001eb5a: 460d mov r5, r1 +1001eb5c: f104 060c add.w r6, r4, #12 +1001eb60: 2101 movs r1, #1 +1001eb62: f000 f94a bl 1001edfa <.text_64+0x2> +1001eb66: 2801 cmp r0, #1 +1001eb68: d113 bne.n 1001eb92 +1001eb6a: f106 078c add.w r7, r6, #140 ; 0x8c +1001eb6e: 4629 mov r1, r5 +1001eb70: 4638 mov r0, r7 +1001eb72: f7ff fedc bl 1001e92e +1001eb76: b160 cbz r0, 1001eb92 +1001eb78: 2301 movs r3, #1 +1001eb7a: 4622 mov r2, r4 +1001eb7c: 4629 mov r1, r5 +1001eb7e: 4638 mov r0, r7 +1001eb80: f7ff ff0d bl 1001e99e +1001eb84: f8d6 2104 ldr.w r2, [r6, #260] ; 0x104 +1001eb88: f506 718a add.w r1, r6, #276 ; 0x114 +1001eb8c: 4620 mov r0, r4 +1001eb8e: f00d fc19 bl 1002c3c4 +1001eb92: 4629 mov r1, r5 +1001eb94: 4620 mov r0, r4 +1001eb96: e8bd 40f4 ldmia.w sp!, {r2, r4, r5, r6, r7, lr} +1001eb9a: e754 b.n 1001ea46 + +1001eb9c : +1001eb9c: b57c push {r2, r3, r4, r5, r6, lr} +1001eb9e: 4604 mov r4, r0 +1001eba0: 460d mov r5, r1 +1001eba2: f104 060c add.w r6, r4, #12 +1001eba6: 4628 mov r0, r5 +1001eba8: f7ff fc5c bl 1001e464 +1001ebac: f5b0 7f5f cmp.w r0, #892 ; 0x37c +1001ebb0: d835 bhi.n 1001ec1e +1001ebb2: a901 add r1, sp, #4 +1001ebb4: 4630 mov r0, r6 +1001ebb6: f7f1 fead bl 10010914 +1001ebba: f000 f91d bl 1001edf8 <.text_64> +1001ebbe: 2801 cmp r0, #1 +1001ebc0: d11e bne.n 1001ec00 +1001ebc2: 2206 movs r2, #6 +1001ebc4: 1d29 adds r1, r5, #4 +1001ebc6: f106 0090 add.w r0, r6, #144 ; 0x90 +1001ebca: f7f1 fe2a bl 10010822 +1001ebce: b1b8 cbz r0, 1001ec00 +1001ebd0: 2208 movs r2, #8 +1001ebd2: f105 017c add.w r1, r5, #124 ; 0x7c +1001ebd6: f506 7084 add.w r0, r6, #264 ; 0x108 +1001ebda: f7f1 fe18 bl 1001080e +1001ebde: f000 f901 bl 1001ede4 <.text_62> +1001ebe2: 1d29 adds r1, r5, #4 +1001ebe4: f000 f8f0 bl 1001edc8 <.text_59> +1001ebe8: b140 cbz r0, 1001ebfc +1001ebea: 2208 movs r2, #8 +1001ebec: f105 017c add.w r1, r5, #124 ; 0x7c +1001ebf0: 3098 adds r0, #152 ; 0x98 +1001ebf2: f7f1 fe0c bl 1001080e +1001ebf6: f000 f8fa bl 1001edee <.text_63> +1001ebfa: e00c b.n 1001ec16 +1001ebfc: f000 f8f7 bl 1001edee <.text_63> +1001ec00: 2180 movs r1, #128 ; 0x80 +1001ec02: f000 f8fa bl 1001edfa <.text_64+0x2> +1001ec06: b930 cbnz r0, 1001ec16 +1001ec08: 7c28 ldrb r0, [r5, #16] +1001ec0a: b900 cbnz r0, 1001ec0e +1001ec0c: 60e8 str r0, [r5, #12] +1001ec0e: 4629 mov r1, r5 +1001ec10: 4620 mov r0, r4 +1001ec12: f7ff ffa0 bl 1001eb56 +1001ec16: a901 add r1, sp, #4 +1001ec18: 4630 mov r0, r6 +1001ec1a: f7f1 fe7c bl 10010916 +1001ec1e: bd73 pop {r0, r1, r4, r5, r6, pc} + +1001ec20 : +1001ec20: b538 push {r3, r4, r5, lr} +1001ec22: f000 fb35 bl 1001f290 <.text_81> +1001ec26: f8d5 0498 ldr.w r0, [r5, #1176] ; 0x498 +1001ec2a: b148 cbz r0, 1001ec40 +1001ec2c: f505 6293 add.w r2, r5, #1176 ; 0x498 +1001ec30: 2300 movs r3, #0 +1001ec32: 6851 ldr r1, [r2, #4] +1001ec34: 6053 str r3, [r2, #4] +1001ec36: f7f1 fde9 bl 1001080c +1001ec3a: 2000 movs r0, #0 +1001ec3c: f8c5 0498 str.w r0, [r5, #1176] ; 0x498 +1001ec40: f44f 6100 mov.w r1, #2048 ; 0x800 +1001ec44: 4628 mov r0, r5 +1001ec46: f7ff fc10 bl 1001e46a +1001ec4a: b128 cbz r0, 1001ec58 +1001ec4c: f505 6086 add.w r0, r5, #1072 ; 0x430 +1001ec50: f7f1 fefa bl 10010a48 +1001ec54: f000 fb17 bl 1001f286 <.text_80> +1001ec58: 7a68 ldrb r0, [r5, #9] +1001ec5a: 2801 cmp r0, #1 +1001ec5c: d14b bne.n 1001ecf6 +1001ec5e: 2120 movs r1, #32 +1001ec60: 4628 mov r0, r5 +1001ec62: f7ff fc02 bl 1001e46a +1001ec66: 2801 cmp r0, #1 +1001ec68: d045 beq.n 1001ecf6 +1001ec6a: 2180 movs r1, #128 ; 0x80 +1001ec6c: 4628 mov r0, r5 +1001ec6e: f7ff fc03 bl 1001e478 +1001ec72: 2000 movs r0, #0 +1001ec74: 7268 strb r0, [r5, #9] +1001ec76: 4628 mov r0, r5 +1001ec78: f000 fb70 bl 1001f35c +1001ec7c: 2801 cmp r0, #1 +1001ec7e: d10c bne.n 1001ec9a +1001ec80: f894 08cc ldrb.w r0, [r4, #2252] ; 0x8cc +1001ec84: b110 cbz r0, 1001ec8c +1001ec86: 2000 movs r0, #0 +1001ec88: f884 0840 strb.w r0, [r4, #2112] ; 0x840 +1001ec8c: f641 1164 movw r1, #6500 ; 0x1964 +1001ec90: f505 6084 add.w r0, r5, #1056 ; 0x420 +1001ec94: f7f1 fed1 bl 10010a3a +1001ec98: e02d b.n 1001ecf6 +1001ec9a: 2802 cmp r0, #2 +1001ec9c: d106 bne.n 1001ecac +1001ec9e: 2180 movs r1, #128 ; 0x80 +1001eca0: f000 faf3 bl 1001f28a <.text_80+0x4> +1001eca4: 4620 mov r0, r4 +1001eca6: f000 f8ab bl 1001ee00 +1001ecaa: e024 b.n 1001ecf6 +1001ecac: f60f 31c4 addw r1, pc, #3012 ; 0xbc4 +1001ecb0: 4620 mov r0, r4 +1001ecb2: f7f5 f8f9 bl 10013ea8 +1001ecb6: 4620 mov r0, r4 +1001ecb8: f7f2 fc88 bl 100115cc +1001ecbc: f894 08cc ldrb.w r0, [r4, #2252] ; 0x8cc +1001ecc0: b1b0 cbz r0, 1001ecf0 +1001ecc2: f894 0840 ldrb.w r0, [r4, #2112] ; 0x840 +1001ecc6: 1c40 adds r0, r0, #1 +1001ecc8: f884 0840 strb.w r0, [r4, #2112] ; 0x840 +1001eccc: b2c0 uxtb r0, r0 +1001ecce: 2803 cmp r0, #3 +1001ecd0: da06 bge.n 1001ece0 +1001ecd2: f241 3188 movw r1, #5000 ; 0x1388 +1001ecd6: f604 0034 addw r0, r4, #2100 ; 0x834 +1001ecda: f7f1 feae bl 10010a3a +1001ecde: e007 b.n 1001ecf0 +1001ece0: 2000 movs r0, #0 +1001ece2: f884 0840 strb.w r0, [r4, #2112] ; 0x840 +1001ece6: 4620 mov r0, r4 +1001ece8: f60f 31ac addw r1, pc, #2988 ; 0xbac +1001ecec: f7f5 f8dc bl 10013ea8 +1001ecf0: 2180 movs r1, #128 ; 0x80 +1001ecf2: f000 faca bl 1001f28a <.text_80+0x4> +1001ecf6: 2100 movs r1, #0 +1001ecf8: 4620 mov r0, r4 +1001ecfa: f000 f8a1 bl 1001ee40 +1001ecfe: f000 f809 bl 1001ed14 <.text_55> +1001ed02: 4620 mov r0, r4 +1001ed04: f011 f912 bl 1002ff2c +1001ed08: f641 5048 movw r0, #7496 ; 0x1d48 +1001ed0c: 5900 ldr r0, [r0, r4] +1001ed0e: f011 f90d bl 1002ff2c +1001ed12: bd31 pop {r0, r4, r5, pc} + +1001ed14 <.text_55>: +1001ed14: a900 add r1, sp, #0 +1001ed16: 4628 mov r0, r5 +1001ed18: f7f1 bdfd b.w 10010916 + +1001ed1c : +1001ed1c: 4770 bx lr + +1001ed1e : +1001ed1e: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +1001ed22: 4604 mov r4, r0 +1001ed24: f504 5788 add.w r7, r4, #4352 ; 0x1100 +1001ed28: 460d mov r5, r1 +1001ed2a: f104 060c add.w r6, r4, #12 +1001ed2e: 3728 adds r7, #40 ; 0x28 +1001ed30: 46b8 mov r8, r7 +1001ed32: f106 0970 add.w r9, r6, #112 ; 0x70 +1001ed36: 2118 movs r1, #24 +1001ed38: f000 f85f bl 1001edfa <.text_64+0x2> +1001ed3c: b160 cbz r0, 1001ed58 +1001ed3e: f109 0120 add.w r1, r9, #32 +1001ed42: 4638 mov r0, r7 +1001ed44: f006 fa32 bl 100251ac +1001ed48: f000 f846 bl 1001edd8 <.text_61> +1001ed4c: 4639 mov r1, r7 +1001ed4e: 4620 mov r0, r4 +1001ed50: f006 f926 bl 10024fa0 +1001ed54: f000 f83b bl 1001edce <.text_60> +1001ed58: 2170 movs r1, #112 ; 0x70 +1001ed5a: f000 f84e bl 1001edfa <.text_64+0x2> +1001ed5e: b180 cbz r0, 1001ed82 +1001ed60: 4620 mov r0, r4 +1001ed62: f006 f9f3 bl 1002514c +1001ed66: 4620 mov r0, r4 +1001ed68: f006 fa66 bl 10025238 +1001ed6c: f000 f834 bl 1001edd8 <.text_61> +1001ed70: 4639 mov r1, r7 +1001ed72: 4620 mov r0, r4 +1001ed74: f006 f914 bl 10024fa0 +1001ed78: f000 f829 bl 1001edce <.text_60> +1001ed7c: 4620 mov r0, r4 +1001ed7e: f006 fa4e bl 1002521e +1001ed82: b10d cbz r5, 1001ed88 +1001ed84: f000 f82e bl 1001ede4 <.text_62> +1001ed88: f109 0120 add.w r1, r9, #32 +1001ed8c: f000 f81c bl 1001edc8 <.text_59> +1001ed90: 0007 movs r7, r0 +1001ed92: bf1c itt ne +1001ed94: 2000 movne r0, #0 +1001ed96: 60f8 strne r0, [r7, #12] +1001ed98: f000 f82e bl 1001edf8 <.text_64> +1001ed9c: b120 cbz r0, 1001eda8 +1001ed9e: f241 1084 movw r0, #4484 ; 0x1184 +1001eda2: 5900 ldr r0, [r0, r4] +1001eda4: 2801 cmp r0, #1 +1001eda6: d003 beq.n 1001edb0 +1001eda8: 2108 movs r1, #8 +1001edaa: f000 f826 bl 1001edfa <.text_64+0x2> +1001edae: b118 cbz r0, 1001edb8 +1001edb0: 4639 mov r1, r7 +1001edb2: 4630 mov r0, r6 +1001edb4: f7ff fdaa bl 1001e90c +1001edb8: b10d cbz r5, 1001edbe +1001edba: f000 f818 bl 1001edee <.text_63> +1001edbe: 2000 movs r0, #0 +1001edc0: f886 0490 strb.w r0, [r6, #1168] ; 0x490 +1001edc4: e8bd 83f1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, pc} + +1001edc8 <.text_59>: +1001edc8: f106 0020 add.w r0, r6, #32 +1001edcc: e5a0 b.n 1001e910 + +1001edce <.text_60>: +1001edce: a900 add r1, sp, #0 +1001edd0: f108 0018 add.w r0, r8, #24 +1001edd4: f7f1 bd9f b.w 10010916 + +1001edd8 <.text_61>: +1001edd8: 4607 mov r7, r0 +1001edda: a900 add r1, sp, #0 +1001eddc: f108 0018 add.w r0, r8, #24 +1001ede0: f7f1 bd98 b.w 10010914 + +1001ede4 <.text_62>: +1001ede4: a900 add r1, sp, #0 +1001ede6: f106 0028 add.w r0, r6, #40 ; 0x28 +1001edea: f7f1 bd93 b.w 10010914 + +1001edee <.text_63>: +1001edee: a900 add r1, sp, #0 +1001edf0: f106 0028 add.w r0, r6, #40 ; 0x28 +1001edf4: f7f1 bd8f b.w 10010916 + +1001edf8 <.text_64>: +1001edf8: 2140 movs r1, #64 ; 0x40 +1001edfa: 4630 mov r0, r6 +1001edfc: f7ff bb35 b.w 1001e46a + +1001ee00 : +1001ee00: b510 push {r4, lr} +1001ee02: 4604 mov r4, r0 +1001ee04: f104 000c add.w r0, r4, #12 +1001ee08: 2100 movs r1, #0 +1001ee0a: 7241 strb r1, [r0, #9] +1001ee0c: 2101 movs r1, #1 +1001ee0e: f7ff fb33 bl 1001e478 +1001ee12: 4620 mov r0, r4 +1001ee14: e8bd 4010 ldmia.w sp!, {r4, lr} +1001ee18: f7f2 bb5d b.w 100114d6 + +1001ee1c : +1001ee1c: b510 push {r4, lr} +1001ee1e: 4604 mov r4, r0 +1001ee20: f240 1181 movw r1, #385 ; 0x181 +1001ee24: f104 000c add.w r0, r4, #12 +1001ee28: f7ff fb2f bl 1001e48a <_clr_fwstate_> +1001ee2c: 4620 mov r0, r4 +1001ee2e: f7f2 fbcd bl 100115cc +1001ee32: 4620 mov r0, r4 +1001ee34: e8bd 4010 ldmia.w sp!, {r4, lr} +1001ee38: 2201 movs r2, #1 +1001ee3a: 2103 movs r1, #3 +1001ee3c: f7f7 bebf b.w 10016bbe + +1001ee40 : +1001ee40: f7f2 bb4b b.w 100114da + +1001ee44 : +1001ee44: b5f8 push {r3, r4, r5, r6, r7, lr} +1001ee46: 4604 mov r4, r0 +1001ee48: f504 5788 add.w r7, r4, #4352 ; 0x1100 +1001ee4c: 460e mov r6, r1 +1001ee4e: 3728 adds r7, #40 ; 0x28 +1001ee50: f106 0120 add.w r1, r6, #32 +1001ee54: 4638 mov r0, r7 +1001ee56: f006 f9a9 bl 100251ac +1001ee5a: 0005 movs r5, r0 +1001ee5c: d105 bne.n 1001ee6a +1001ee5e: f106 0120 add.w r1, r6, #32 +1001ee62: 4638 mov r0, r7 +1001ee64: f006 f840 bl 10024ee8 +1001ee68: 4605 mov r5, r0 +1001ee6a: 2d00 cmp r5, #0 +1001ee6c: d04a beq.n 1001ef04 +1001ee6e: 69b0 ldr r0, [r6, #24] +1001ee70: f8c5 00fc str.w r0, [r5, #252] ; 0xfc +1001ee74: f641 5051 movw r0, #7505 ; 0x1d51 +1001ee78: 5d00 ldrb r0, [r0, r4] +1001ee7a: b100 cbz r0, 1001ee7e +1001ee7c: 2002 movs r0, #2 +1001ee7e: f105 06fc add.w r6, r5, #252 ; 0xfc +1001ee82: 2301 movs r3, #1 +1001ee84: 6070 str r0, [r6, #4] +1001ee86: 462a mov r2, r5 +1001ee88: 2100 movs r1, #0 +1001ee8a: 4620 mov r0, r4 +1001ee8c: f7f8 fa6a bl 10017364 +1001ee90: f241 10f0 movw r0, #4592 ; 0x11f0 +1001ee94: 5901 ldr r1, [r0, r4] +1001ee96: 2902 cmp r1, #2 +1001ee98: d128 bne.n 1001eeec +1001ee9a: f504 51aa add.w r1, r4, #5440 ; 0x1540 +1001ee9e: 2200 movs r2, #0 +1001eea0: 710a strb r2, [r1, #4] +1001eea2: 714a strb r2, [r1, #5] +1001eea4: 71ca strb r2, [r1, #7] +1001eea6: 2101 movs r1, #1 +1001eea8: 1900 adds r0, r0, r4 +1001eeaa: 6171 str r1, [r6, #20] +1001eeac: 2210 movs r2, #16 +1001eeae: 6840 ldr r0, [r0, #4] +1001eeb0: 61b0 str r0, [r6, #24] +1001eeb2: 2100 movs r1, #0 +1001eeb4: f505 709c add.w r0, r5, #312 ; 0x138 +1001eeb8: f7f1 fcbe bl 10010838 +1001eebc: 2210 movs r2, #16 +1001eebe: 2100 movs r1, #0 +1001eec0: f505 7094 add.w r0, r5, #296 ; 0x128 +1001eec4: f7f1 fcb8 bl 10010838 +1001eec8: 2210 movs r2, #16 +1001eeca: 2100 movs r1, #0 +1001eecc: f505 708c add.w r0, r5, #280 ; 0x118 +1001eed0: f7f1 fcb2 bl 10010838 +1001eed4: 2208 movs r2, #8 +1001eed6: 2100 movs r1, #0 +1001eed8: f505 70a4 add.w r0, r5, #328 ; 0x148 +1001eedc: f7f1 fcac bl 10010838 +1001eee0: 2208 movs r2, #8 +1001eee2: 2100 movs r1, #0 +1001eee4: f505 70a8 add.w r0, r5, #336 ; 0x150 +1001eee8: f7f1 fca6 bl 10010838 +1001eeec: f44f 50aa mov.w r0, #5440 ; 0x1540 +1001eef0: 5901 ldr r1, [r0, r4] +1001eef2: b119 cbz r1, 1001eefc +1001eef4: 2101 movs r1, #1 +1001eef6: 6171 str r1, [r6, #20] +1001eef8: 2100 movs r1, #0 +1001eefa: 5101 str r1, [r0, r4] +1001eefc: 4629 mov r1, r5 +1001eefe: 4620 mov r0, r4 +1001ef00: f7fe fa25 bl 1001d34e +1001ef04: 4628 mov r0, r5 +1001ef06: bdf2 pop {r1, r4, r5, r6, r7, pc} + +1001ef08 : +1001ef08: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1001ef0c: 4680 mov r8, r0 +1001ef0e: 460d mov r5, r1 +1001ef10: f108 090c add.w r9, r8, #12 +1001ef14: f105 001c add.w r0, r5, #28 +1001ef18: f7ff faa4 bl 1001e464 +1001ef1c: f5b0 7f5f cmp.w r0, #892 ; 0x37c +1001ef20: 61e8 str r0, [r5, #28] +1001ef22: f200 809f bhi.w 1001f064 +1001ef26: a900 add r1, sp, #0 +1001ef28: 4648 mov r0, r9 +1001ef2a: f7f1 fcf3 bl 10010914 +1001ef2e: 69a8 ldr r0, [r5, #24] +1001ef30: 2801 cmp r0, #1 +1001ef32: f509 6b84 add.w fp, r9, #1056 ; 0x420 +1001ef36: db7d blt.n 1001f034 +1001ef38: f000 fa71 bl 1001f41e <.text_85> +1001ef3c: 2180 movs r1, #128 ; 0x80 +1001ef3e: f000 fa74 bl 1001f42a <.text_86+0x2> +1001ef42: 2800 cmp r0, #0 +1001ef44: d073 beq.n 1001f02e +1001ef46: f105 0120 add.w r1, r5, #32 +1001ef4a: f109 0020 add.w r0, r9, #32 +1001ef4e: f7ff fcdf bl 1001e910 +1001ef52: 4604 mov r4, r0 +1001ef54: f000 fa68 bl 1001f428 <.text_86> +1001ef58: 2801 cmp r0, #1 +1001ef5a: d103 bne.n 1001ef64 +1001ef5c: 2c00 cmp r4, #0 +1001ef5e: d066 beq.n 1001f02e +1001ef60: 60e0 str r0, [r4, #12] +1001ef62: e001 b.n 1001ef68 +1001ef64: 2c00 cmp r4, #0 +1001ef66: d062 beq.n 1001f02e +1001ef68: f108 060c add.w r6, r8, #12 +1001ef6c: f106 0a70 add.w sl, r6, #112 ; 0x70 +1001ef70: 69e2 ldr r2, [r4, #28] +1001ef72: f104 011c add.w r1, r4, #28 +1001ef76: f10a 001c add.w r0, sl, #28 +1001ef7a: f7f1 fc48 bl 1001080e +1001ef7e: f104 0790 add.w r7, r4, #144 ; 0x90 +1001ef82: f44f 7240 mov.w r2, #768 ; 0x300 +1001ef86: 6878 ldr r0, [r7, #4] +1001ef88: f8ca 0094 str.w r0, [sl, #148] ; 0x94 +1001ef8c: f104 0198 add.w r1, r4, #152 ; 0x98 +1001ef90: f10a 0098 add.w r0, sl, #152 ; 0x98 +1001ef94: f7f1 fc3b bl 1001080e +1001ef98: 69a8 ldr r0, [r5, #24] +1001ef9a: f8ca 0014 str.w r0, [sl, #20] +1001ef9e: f608 50bc addw r0, r8, #3516 ; 0xdbc +1001efa2: f894 1090 ldrb.w r1, [r4, #144] ; 0x90 +1001efa6: 7081 strb r1, [r0, #2] +1001efa8: 7879 ldrb r1, [r7, #1] +1001efaa: 70c1 strb r1, [r0, #3] +1001efac: 2112 movs r1, #18 +1001efae: f894 0090 ldrb.w r0, [r4, #144] ; 0x90 +1001efb2: 4348 muls r0, r1 +1001efb4: 2114 movs r1, #20 +1001efb6: fbb0 f0f1 udiv r0, r0, r1 +1001efba: 385f subs r0, #95 ; 0x5f +1001efbc: f888 0dbc strb.w r0, [r8, #3516] ; 0xdbc +1001efc0: 6fe8 ldr r0, [r5, #124] ; 0x7c +1001efc2: b110 cbz r0, 1001efca +1001efc4: 2801 cmp r0, #1 +1001efc6: d002 beq.n 1001efce +1001efc8: e003 b.n 1001efd2 +1001efca: 2020 movs r0, #32 +1001efcc: e002 b.n 1001efd4 +1001efce: 2008 movs r0, #8 +1001efd0: e000 b.n 1001efd4 +1001efd2: 2000 movs r0, #0 +1001efd4: 6070 str r0, [r6, #4] +1001efd6: f10a 01a4 add.w r1, sl, #164 ; 0xa4 +1001efda: f8da 2094 ldr.w r2, [sl, #148] ; 0x94 +1001efde: 4640 mov r0, r8 +1001efe0: f00d f9f0 bl 1002c3c4 +1001efe4: f8da 2094 ldr.w r2, [sl, #148] ; 0x94 +1001efe8: f10a 0198 add.w r1, sl, #152 ; 0x98 +1001efec: 4640 mov r0, r8 +1001efee: f000 fb8a bl 1001f706 +1001eff2: f109 01f0 add.w r1, r9, #240 ; 0xf0 +1001eff6: 4640 mov r0, r8 +1001eff8: f006 fd38 bl 10025a6c +1001effc: f000 fa14 bl 1001f428 <.text_86> +1001f000: 2801 cmp r0, #1 +1001f002: d104 bne.n 1001f00e +1001f004: 4629 mov r1, r5 +1001f006: 4640 mov r0, r8 +1001f008: f7ff ff1c bl 1001ee44 +1001f00c: b178 cbz r0, 1001f02e +1001f00e: f000 fa0b bl 1001f428 <.text_86> +1001f012: 2801 cmp r0, #1 +1001f014: bf04 itt eq +1001f016: 4640 moveq r0, r8 +1001f018: f7ff fef2 bleq 1001ee00 +1001f01c: 4658 mov r0, fp +1001f01e: f7f1 fd13 bl 10010a48 +1001f022: f898 08cc ldrb.w r0, [r8, #2252] ; 0x8cc +1001f026: b110 cbz r0, 1001f02e +1001f028: 2000 movs r0, #0 +1001f02a: f888 0841 strb.w r0, [r8, #2113] ; 0x841 +1001f02e: f000 f9f1 bl 1001f414 <.text_84> +1001f032: e017 b.n 1001f064 +1001f034: f110 0f04 cmn.w r0, #4 +1001f038: d10c bne.n 1001f054 +1001f03a: 4640 mov r0, r8 +1001f03c: f7f2 fa4f bl 100114de +1001f040: 2101 movs r1, #1 +1001f042: 4658 mov r0, fp +1001f044: f7f1 fcf9 bl 10010a3a +1001f048: 2180 movs r1, #128 ; 0x80 +1001f04a: f000 f9ee bl 1001f42a <.text_86+0x2> +1001f04e: 2801 cmp r0, #1 +1001f050: d108 bne.n 1001f064 +1001f052: e003 b.n 1001f05c +1001f054: 2101 movs r1, #1 +1001f056: 4658 mov r0, fp +1001f058: f7f1 fcef bl 10010a3a +1001f05c: 2180 movs r1, #128 ; 0x80 +1001f05e: 4648 mov r0, r9 +1001f060: f7ff fa13 bl 1001e48a <_clr_fwstate_> +1001f064: a900 add r1, sp, #0 +1001f066: 4648 mov r0, r9 +1001f068: f7f1 fc55 bl 10010916 +1001f06c: e8bd 8ff1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1001f070 : +1001f070: b510 push {r4, lr} +1001f072: 6809 ldr r1, [r1, #0] +1001f074: 4604 mov r4, r0 +1001f076: f7fe f9a2 bl 1001d3be +1001f07a: 4620 mov r0, r4 +1001f07c: f010 ff56 bl 1002ff2c +1001f080: f641 5048 movw r0, #7496 ; 0x1d48 +1001f084: 5900 ldr r0, [r0, r4] +1001f086: e8bd 4010 ldmia.w sp!, {r4, lr} +1001f08a: f010 bf4f b.w 1002ff2c + +1001f08e : +1001f08e: b538 push {r3, r4, r5, lr} +1001f090: f500 64bf add.w r4, r0, #1528 ; 0x5f8 +1001f094: f500 5588 add.w r5, r0, #4352 ; 0x1100 +1001f098: 3528 adds r5, #40 ; 0x28 +1001f09a: 2110 movs r1, #16 +1001f09c: 300c adds r0, #12 +1001f09e: f7ff f9e4 bl 1001e46a +1001f0a2: b168 cbz r0, 1001f0c0 +1001f0a4: f8b5 00c4 ldrh.w r0, [r5, #196] ; 0xc4 +1001f0a8: e000 b.n 1001f0ac +1001f0aa: 1e40 subs r0, r0, #1 +1001f0ac: b2c0 uxtb r0, r0 +1001f0ae: b128 cbz r0, 1001f0bc +1001f0b0: eb05 0180 add.w r1, r5, r0, lsl #2 +1001f0b4: f8d1 109c ldr.w r1, [r1, #156] ; 0x9c +1001f0b8: 2900 cmp r1, #0 +1001f0ba: d0f6 beq.n 1001f0aa +1001f0bc: 1c40 adds r0, r0, #1 +1001f0be: e00a b.n 1001f0d6 +1001f0c0: 2007 movs r0, #7 +1001f0c2: eb04 1140 add.w r1, r4, r0, lsl #5 +1001f0c6: f8d1 1110 ldr.w r1, [r1, #272] ; 0x110 +1001f0ca: 2901 cmp r1, #1 +1001f0cc: d003 beq.n 1001f0d6 +1001f0ce: 1e40 subs r0, r0, #1 +1001f0d0: b2c0 uxtb r0, r0 +1001f0d2: 2802 cmp r0, #2 +1001f0d4: daf5 bge.n 1001f0c2 +1001f0d6: b2c0 uxtb r0, r0 +1001f0d8: bd32 pop {r1, r4, r5, pc} + +1001f0da : +1001f0da: b538 push {r3, r4, r5, lr} +1001f0dc: 000d movs r5, r1 +1001f0de: 4604 mov r4, r0 +1001f0e0: d012 beq.n 1001f108 +1001f0e2: f7ff ffd4 bl 1001f08e +1001f0e6: f88d 0000 strb.w r0, [sp] +1001f0ea: aa00 add r2, sp, #0 +1001f0ec: 2144 movs r1, #68 ; 0x44 +1001f0ee: f000 f877 bl 1001f1e0 <.text_76+0x2> +1001f0f2: f8d5 0100 ldr.w r0, [r5, #256] ; 0x100 +1001f0f6: 0200 lsls r0, r0, #8 +1001f0f8: f040 0001 orr.w r0, r0, #1 +1001f0fc: f8ad 0002 strh.w r0, [sp, #2] +1001f100: f10d 0202 add.w r2, sp, #2 +1001f104: f000 f86b bl 1001f1de <.text_76> +1001f108: bd31 pop {r0, r4, r5, pc} + +1001f10a : +1001f10a: b538 push {r3, r4, r5, lr} +1001f10c: 4604 mov r4, r0 +1001f10e: 460d mov r5, r1 +1001f110: f000 f813 bl 1001f13a <.text_74> +1001f114: b180 cbz r0, 1001f138 +1001f116: f504 5088 add.w r0, r4, #4352 ; 0x1100 +1001f11a: 4629 mov r1, r5 +1001f11c: 3028 adds r0, #40 ; 0x28 +1001f11e: f006 f845 bl 100251ac +1001f122: 0005 movs r5, r0 +1001f124: d008 beq.n 1001f138 +1001f126: 4629 mov r1, r5 +1001f128: 4620 mov r0, r4 +1001f12a: f7fa fa7c bl 10019626 +1001f12e: 4629 mov r1, r5 +1001f130: 4620 mov r0, r4 +1001f132: e8bd 4034 ldmia.w sp!, {r2, r4, r5, lr} +1001f136: e7d0 b.n 1001f0da +1001f138: bd31 pop {r0, r4, r5, pc} + +1001f13a <.text_74>: +1001f13a: 2110 movs r1, #16 +1001f13c: f104 000c add.w r0, r4, #12 +1001f140: f7ff b993 b.w 1001e46a + +1001f144 : +1001f144: b5fe push {r1, r2, r3, r4, r5, r6, r7, lr} +1001f146: 4604 mov r4, r0 +1001f148: f104 060c add.w r6, r4, #12 +1001f14c: f504 5088 add.w r0, r4, #4352 ; 0x1100 +1001f150: 460d mov r5, r1 +1001f152: f106 0770 add.w r7, r6, #112 ; 0x70 +1001f156: 3028 adds r0, #40 ; 0x28 +1001f158: f006 f828 bl 100251ac +1001f15c: 2800 cmp r0, #0 +1001f15e: bf14 ite ne +1001f160: f8d0 0100 ldrne.w r0, [r0, #256] ; 0x100 +1001f164: 68a8 ldreq r0, [r5, #8] +1001f166: 0200 lsls r0, r0, #8 +1001f168: f8ad 0008 strh.w r0, [sp, #8] +1001f16c: aa02 add r2, sp, #8 +1001f16e: f000 f836 bl 1001f1de <.text_76> +1001f172: 2110 movs r1, #16 +1001f174: f7ff fe41 bl 1001edfa <.text_64+0x2> +1001f178: bb80 cbnz r0, 1001f1dc +1001f17a: 4620 mov r0, r4 +1001f17c: f7fe f9ab bl 1001d4d6 +1001f180: a900 add r1, sp, #0 +1001f182: 4630 mov r0, r6 +1001f184: f7f1 fbc6 bl 10010914 +1001f188: 2108 movs r1, #8 +1001f18a: f7ff fe36 bl 1001edfa <.text_64+0x2> +1001f18e: b308 cbz r0, 1001f1d4 +1001f190: 4620 mov r0, r4 +1001f192: f00d fff7 bl 1002d184 +1001f196: 4620 mov r0, r4 +1001f198: f00e f80d bl 1002d1b6 +1001f19c: 2101 movs r1, #1 +1001f19e: 4620 mov r0, r4 +1001f1a0: f7ff fdbd bl 1001ed1e +1001f1a4: 4620 mov r0, r4 +1001f1a6: f7ff fe39 bl 1001ee1c +1001f1aa: a901 add r1, sp, #4 +1001f1ac: f106 0028 add.w r0, r6, #40 ; 0x28 +1001f1b0: f7f1 fbb0 bl 10010914 +1001f1b4: f107 0120 add.w r1, r7, #32 +1001f1b8: f7ff fe06 bl 1001edc8 <.text_59> +1001f1bc: 0001 movs r1, r0 +1001f1be: d004 beq.n 1001f1ca +1001f1c0: 2000 movs r0, #0 +1001f1c2: 60c8 str r0, [r1, #12] +1001f1c4: 4630 mov r0, r6 +1001f1c6: f7ff fba1 bl 1001e90c +1001f1ca: a901 add r1, sp, #4 +1001f1cc: f106 0028 add.w r0, r6, #40 ; 0x28 +1001f1d0: f7f1 fba1 bl 10010916 +1001f1d4: a900 add r1, sp, #0 +1001f1d6: 4630 mov r0, r6 +1001f1d8: f7f1 fb9d bl 10010916 +1001f1dc: bdf7 pop {r0, r1, r2, r4, r5, r6, r7, pc} + +1001f1de <.text_76>: +1001f1de: 2145 movs r1, #69 ; 0x45 +1001f1e0: 4620 mov r0, r4 +1001f1e2: f7f8 b895 b.w 10017310 + +1001f1e6 <_rtw_join_timeout_handler>: +1001f1e6: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1001f1ea: 4605 mov r5, r0 +1001f1ec: f641 409c movw r0, #7324 ; 0x1c9c +1001f1f0: b084 sub sp, #16 +1001f1f2: 5941 ldr r1, [r0, r5] +1001f1f4: 2900 cmp r1, #0 +1001f1f6: bf02 ittt eq +1001f1f8: 1940 addeq r0, r0, r5 +1001f1fa: 6840 ldreq r0, [r0, #4] +1001f1fc: 2800 cmpeq r0, #0 +1001f1fe: f105 040c add.w r4, r5, #12 +1001f202: d12d bne.n 1001f260 <_rtw_join_timeout_handler+0x7a> +1001f204: a902 add r1, sp, #8 +1001f206: 4620 mov r0, r4 +1001f208: f7f1 fb84 bl 10010914 +1001f20c: 4628 mov r0, r5 +1001f20e: f7ff fe05 bl 1001ee1c +1001f212: f104 0620 add.w r6, r4, #32 +1001f216: f104 0514 add.w r5, r4, #20 +1001f21a: f000 f823 bl 1001f264 <.text_78> +1001f21e: a901 add r1, sp, #4 +1001f220: f105 0008 add.w r0, r5, #8 +1001f224: f7f1 fb76 bl 10010914 +1001f228: 6837 ldr r7, [r6, #0] +1001f22a: e00c b.n 1001f246 <_rtw_join_timeout_handler+0x60> +1001f22c: f8d7 8000 ldr.w r8, [r7] +1001f230: 4638 mov r0, r7 +1001f232: f7f1 fb17 bl 10010864 +1001f236: 4629 mov r1, r5 +1001f238: 4638 mov r0, r7 +1001f23a: f7f1 fb11 bl 10010860 +1001f23e: 8e20 ldrh r0, [r4, #48] ; 0x30 +1001f240: 1e40 subs r0, r0, #1 +1001f242: 4647 mov r7, r8 +1001f244: 8620 strh r0, [r4, #48] ; 0x30 +1001f246: 42b7 cmp r7, r6 +1001f248: d1f0 bne.n 1001f22c <_rtw_join_timeout_handler+0x46> +1001f24a: a901 add r1, sp, #4 +1001f24c: f105 0008 add.w r0, r5, #8 +1001f250: f7f1 fb61 bl 10010916 +1001f254: f7ff fb26 bl 1001e8a4 <.text_34> +1001f258: a902 add r1, sp, #8 +1001f25a: 4620 mov r0, r4 +1001f25c: f7f1 fb5b bl 10010916 +1001f260: e8bd 81ff ldmia.w sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, pc} + +1001f264 <.text_78>: +1001f264: a900 add r1, sp, #0 +1001f266: f106 0008 add.w r0, r6, #8 +1001f26a: f7f1 bb53 b.w 10010914 + +1001f26e : +1001f26e: b538 push {r3, r4, r5, lr} +1001f270: f000 f80e bl 1001f290 <.text_81> +1001f274: f000 f807 bl 1001f286 <.text_80> +1001f278: f7ff fd4c bl 1001ed14 <.text_55> +1001f27c: 2101 movs r1, #1 +1001f27e: 4620 mov r0, r4 +1001f280: f7ff fdde bl 1001ee40 +1001f284: bd31 pop {r0, r4, r5, pc} + +1001f286 <.text_80>: +1001f286: f44f 6100 mov.w r1, #2048 ; 0x800 +1001f28a: 4628 mov r0, r5 +1001f28c: f7ff b8fd b.w 1001e48a <_clr_fwstate_> + +1001f290 <.text_81>: +1001f290: 4604 mov r4, r0 +1001f292: f104 050c add.w r5, r4, #12 +1001f296: a900 add r1, sp, #0 +1001f298: 4628 mov r0, r5 +1001f29a: f7f1 bb3b b.w 10010914 + +1001f29e : +1001f29e: b5f8 push {r3, r4, r5, r6, r7, lr} +1001f2a0: 4604 mov r4, r0 +1001f2a2: f641 5044 movw r0, #7492 ; 0x1d44 +1001f2a6: 1906 adds r6, r0, r4 +1001f2a8: 2c00 cmp r4, #0 +1001f2aa: 6871 ldr r1, [r6, #4] +1001f2ac: bf1f itttt ne +1001f2ae: f641 429c movwne r2, #7324 ; 0x1c9c +1001f2b2: 1913 addne r3, r2, r4 +1001f2b4: f893 c019 ldrbne.w ip, [r3, #25] +1001f2b8: f1bc 0f00 cmpne.w ip, #0 +1001f2bc: f104 050c add.w r5, r4, #12 +1001f2c0: f504 57c4 add.w r7, r4, #6272 ; 0x1880 +1001f2c4: d049 beq.n 1001f35a +1001f2c6: 5912 ldr r2, [r2, r4] +1001f2c8: 2a01 cmp r2, #1 +1001f2ca: bf1c itt ne +1001f2cc: 685a ldrne r2, [r3, #4] +1001f2ce: 2a01 cmpne r2, #1 +1001f2d0: d043 beq.n 1001f35a +1001f2d2: 5d02 ldrb r2, [r0, r4] +1001f2d4: b129 cbz r1, 1001f2e2 +1001f2d6: 2a01 cmp r2, #1 +1001f2d8: bf04 itt eq +1001f2da: 5c40 ldrbeq r0, [r0, r1] +1001f2dc: 2801 cmpeq r0, #1 +1001f2de: d102 bne.n 1001f2e6 +1001f2e0: bdf1 pop {r0, r4, r5, r6, r7, pc} +1001f2e2: 2a01 cmp r2, #1 +1001f2e4: d039 beq.n 1001f35a +1001f2e6: 4620 mov r0, r4 +1001f2e8: f7f7 fb77 bl 100169da +1001f2ec: f897 0058 ldrb.w r0, [r7, #88] ; 0x58 +1001f2f0: 2801 cmp r0, #1 +1001f2f2: d127 bne.n 1001f344 +1001f2f4: f104 070c add.w r7, r4, #12 +1001f2f8: f504 50c8 add.w r0, r4, #6400 ; 0x1900 +1001f2fc: f8d7 141c ldr.w r1, [r7, #1052] ; 0x41c +1001f300: 300c adds r0, #12 +1001f302: b1f9 cbz r1, 1001f344 +1001f304: 1e49 subs r1, r1, #1 +1001f306: f8c7 141c str.w r1, [r7, #1052] ; 0x41c +1001f30a: bf04 itt eq +1001f30c: f890 003b ldrbeq.w r0, [r0, #59] ; 0x3b +1001f310: 2800 cmpeq r0, #0 +1001f312: d117 bne.n 1001f344 +1001f314: 4620 mov r0, r4 +1001f316: f000 fa82 bl 1001f81e +1001f31a: b158 cbz r0, 1001f334 +1001f31c: f44f 6108 mov.w r1, #2176 ; 0x880 +1001f320: 4620 mov r0, r4 +1001f322: f000 fa94 bl 1001f84e +1001f326: 2801 cmp r0, #1 +1001f328: bf1e ittt ne +1001f32a: 6870 ldrne r0, [r6, #4] +1001f32c: f890 0488 ldrbne.w r0, [r0, #1160] ; 0x488 +1001f330: 2801 cmpne r0, #1 +1001f332: d007 beq.n 1001f344 +1001f334: 2200 movs r2, #0 +1001f336: 2100 movs r1, #0 +1001f338: 4620 mov r0, r4 +1001f33a: f003 fe6e bl 1002301a +1001f33e: 201e movs r0, #30 +1001f340: f8c7 041c str.w r0, [r7, #1052] ; 0x41c +1001f344: 2110 movs r1, #16 +1001f346: 4628 mov r0, r5 +1001f348: f7ff f88f bl 1001e46a +1001f34c: 2801 cmp r0, #1 +1001f34e: d104 bne.n 1001f35a +1001f350: 4620 mov r0, r4 +1001f352: e8bd 40f2 ldmia.w sp!, {r1, r4, r5, r6, r7, lr} +1001f356: f7f9 b90e b.w 10018576 +1001f35a: bdf1 pop {r0, r4, r5, r6, r7, pc} + +1001f35c : +1001f35c: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +1001f360: 4681 mov r9, r0 +1001f362: 2600 movs r6, #0 +1001f364: f000 f85b bl 1001f41e <.text_85> +1001f368: f109 0720 add.w r7, r9, #32 +1001f36c: f8d9 800c ldr.w r8, [r9, #12] +1001f370: 6838 ldr r0, [r7, #0] +1001f372: f109 050c add.w r5, r9, #12 +1001f376: 6068 str r0, [r5, #4] +1001f378: e026 b.n 1001f3c8 +1001f37a: 6868 ldr r0, [r5, #4] +1001f37c: 0004 movs r4, r0 +1001f37e: d02a beq.n 1001f3d6 +1001f380: 6800 ldr r0, [r0, #0] +1001f382: 6068 str r0, [r5, #4] +1001f384: f899 042c ldrb.w r0, [r9, #1068] ; 0x42c +1001f388: 2801 cmp r0, #1 +1001f38a: d107 bne.n 1001f39c +1001f38c: 2206 movs r2, #6 +1001f38e: f109 0168 add.w r1, r9, #104 ; 0x68 +1001f392: f104 0020 add.w r0, r4, #32 +1001f396: f7f1 fa44 bl 10010822 +1001f39a: b1a8 cbz r0, 1001f3c8 +1001f39c: f119 0044 adds.w r0, r9, #68 ; 0x44 +1001f3a0: bf1c itt ne +1001f3a2: 6b6a ldrne r2, [r5, #52] ; 0x34 +1001f3a4: 2a00 cmpne r2, #0 +1001f3a6: d009 beq.n 1001f3bc +1001f3a8: 6aa0 ldr r0, [r4, #40] ; 0x28 +1001f3aa: 4290 cmp r0, r2 +1001f3ac: d10c bne.n 1001f3c8 +1001f3ae: f109 0144 add.w r1, r9, #68 ; 0x44 +1001f3b2: f104 002c add.w r0, r4, #44 ; 0x2c +1001f3b6: f7f1 fa34 bl 10010822 +1001f3ba: b128 cbz r0, 1001f3c8 +1001f3bc: b11e cbz r6, 1001f3c6 +1001f3be: 6d70 ldr r0, [r6, #84] ; 0x54 +1001f3c0: 6d61 ldr r1, [r4, #84] ; 0x54 +1001f3c2: 4288 cmp r0, r1 +1001f3c4: da00 bge.n 1001f3c8 +1001f3c6: 4626 mov r6, r4 +1001f3c8: 6869 ldr r1, [r5, #4] +1001f3ca: 4638 mov r0, r7 +1001f3cc: f7f1 fabd bl 1001094a +1001f3d0: 2800 cmp r0, #0 +1001f3d2: d0d2 beq.n 1001f37a +1001f3d4: b90e cbnz r6, 1001f3da +1001f3d6: 2400 movs r4, #0 +1001f3d8: e017 b.n 1001f40a +1001f3da: 2101 movs r1, #1 +1001f3dc: f000 f825 bl 1001f42a <.text_86+0x2> +1001f3e0: 2801 cmp r0, #1 +1001f3e2: d10d bne.n 1001f400 +1001f3e4: 4640 mov r0, r8 +1001f3e6: f7f7 fa13 bl 10016810 +1001f3ea: 4640 mov r0, r8 +1001f3ec: f7ff fd16 bl 1001ee1c +1001f3f0: 2100 movs r1, #0 +1001f3f2: 4640 mov r0, r8 +1001f3f4: f7ff fc93 bl 1001ed1e +1001f3f8: 2180 movs r1, #128 ; 0x80 +1001f3fa: 4648 mov r0, r9 +1001f3fc: f7ff f83c bl 1001e478 +1001f400: 4631 mov r1, r6 +1001f402: 4640 mov r0, r8 +1001f404: f7f7 f908 bl 10016618 +1001f408: 4604 mov r4, r0 +1001f40a: f000 f803 bl 1001f414 <.text_84> +1001f40e: 4620 mov r0, r4 +1001f410: e8bd 83f2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, pc} + +1001f414 <.text_84>: +1001f414: a900 add r1, sp, #0 +1001f416: f109 0028 add.w r0, r9, #40 ; 0x28 +1001f41a: f7f1 ba7c b.w 10010916 + +1001f41e <.text_85>: +1001f41e: a900 add r1, sp, #0 +1001f420: f109 0028 add.w r0, r9, #40 ; 0x28 +1001f424: f7f1 ba76 b.w 10010914 + +1001f428 <.text_86>: +1001f428: 2108 movs r1, #8 +1001f42a: 4648 mov r0, r9 +1001f42c: f7ff b81d b.w 1001e46a + +1001f430 : +1001f430: b570 push {r4, r5, r6, lr} +1001f432: f600 04d8 addw r4, r0, #2264 ; 0x8d8 +1001f436: 460e mov r6, r1 +1001f438: 2020 movs r0, #32 +1001f43a: f7f1 f9e2 bl 10010802 +1001f43e: 0005 movs r5, r0 +1001f440: d007 beq.n 1001f452 +1001f442: 2004 movs r0, #4 +1001f444: f7f1 f9dd bl 10010802 +1001f448: b928 cbnz r0, 1001f456 +1001f44a: 2120 movs r1, #32 +1001f44c: 4628 mov r0, r5 +1001f44e: f7f1 f9dd bl 1001080c +1001f452: 2000 movs r0, #0 +1001f454: bd70 pop {r4, r5, r6, pc} +1001f456: 6831 ldr r1, [r6, #0] +1001f458: 7001 strb r1, [r0, #0] +1001f45a: 2113 movs r1, #19 +1001f45c: 80a9 strh r1, [r5, #4] +1001f45e: 60a8 str r0, [r5, #8] +1001f460: 2004 movs r0, #4 +1001f462: 60e8 str r0, [r5, #12] +1001f464: 2000 movs r0, #0 +1001f466: 6128 str r0, [r5, #16] +1001f468: 6168 str r0, [r5, #20] +1001f46a: f105 0018 add.w r0, r5, #24 +1001f46e: f7f1 f9ed bl 1001084c +1001f472: 4629 mov r1, r5 +1001f474: 4620 mov r0, r4 +1001f476: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +1001f47a: f7f6 bf82 b.w 10016382 + +1001f47e : +1001f47e: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +1001f482: f600 09d8 addw r9, r0, #2264 ; 0x8d8 +1001f486: f100 0a0c add.w sl, r0, #12 +1001f48a: 460c mov r4, r1 +1001f48c: 4615 mov r5, r2 +1001f48e: 4698 mov r8, r3 +1001f490: 2020 movs r0, #32 +1001f492: f7f1 f9b6 bl 10010802 +1001f496: 0006 movs r6, r0 +1001f498: d008 beq.n 1001f4ac +1001f49a: 2014 movs r0, #20 +1001f49c: f7f1 f9b1 bl 10010802 +1001f4a0: 0007 movs r7, r0 +1001f4a2: d105 bne.n 1001f4b0 +1001f4a4: 2120 movs r1, #32 +1001f4a6: 4630 mov r0, r6 +1001f4a8: f7f1 f9b0 bl 1001080c +1001f4ac: 2000 movs r0, #0 +1001f4ae: e042 b.n 1001f536 +1001f4b0: 2214 movs r2, #20 +1001f4b2: 2100 movs r1, #0 +1001f4b4: f7f1 f9c0 bl 10010838 +1001f4b8: 6820 ldr r0, [r4, #0] +1001f4ba: 2802 cmp r0, #2 +1001f4bc: bf0c ite eq +1001f4be: 6de0 ldreq r0, [r4, #92] ; 0x5c +1001f4c0: 6860 ldrne r0, [r4, #4] +1001f4c2: 7038 strb r0, [r7, #0] +1001f4c4: 707d strb r5, [r7, #1] +1001f4c6: f887 8003 strb.w r8, [r7, #3] +1001f4ca: 2101 movs r1, #1 +1001f4cc: 787a ldrb r2, [r7, #1] +1001f4ce: f89a 0490 ldrb.w r0, [sl, #1168] ; 0x490 +1001f4d2: 4091 lsls r1, r2 +1001f4d4: 4308 orrs r0, r1 +1001f4d6: f88a 0490 strb.w r0, [sl, #1168] ; 0x490 +1001f4da: eb04 1005 add.w r0, r4, r5, lsl #4 +1001f4de: 7839 ldrb r1, [r7, #0] +1001f4e0: 2901 cmp r1, #1 +1001f4e2: d006 beq.n 1001f4f2 +1001f4e4: 2902 cmp r1, #2 +1001f4e6: bf18 it ne +1001f4e8: 2904 cmpne r1, #4 +1001f4ea: d00b beq.n 1001f504 +1001f4ec: 2905 cmp r1, #5 +1001f4ee: d002 beq.n 1001f4f6 +1001f4f0: e7dc b.n 1001f4ac +1001f4f2: 2205 movs r2, #5 +1001f4f4: e000 b.n 1001f4f8 +1001f4f6: 220d movs r2, #13 +1001f4f8: f100 010c add.w r1, r0, #12 +1001f4fc: 1d38 adds r0, r7, #4 +1001f4fe: f7f1 f986 bl 1001080e +1001f502: e007 b.n 1001f514 +1001f504: f100 0164 add.w r1, r0, #100 ; 0x64 +1001f508: 2210 movs r2, #16 +1001f50a: 1d38 adds r0, r7, #4 +1001f50c: f7f1 f97f bl 1001080e +1001f510: 2001 movs r0, #1 +1001f512: 70b8 strb r0, [r7, #2] +1001f514: 2014 movs r0, #20 +1001f516: 80b0 strh r0, [r6, #4] +1001f518: 60b7 str r7, [r6, #8] +1001f51a: 60f0 str r0, [r6, #12] +1001f51c: 2000 movs r0, #0 +1001f51e: 6130 str r0, [r6, #16] +1001f520: 6170 str r0, [r6, #20] +1001f522: f106 0018 add.w r0, r6, #24 +1001f526: f7f1 f991 bl 1001084c +1001f52a: 4631 mov r1, r6 +1001f52c: 4648 mov r0, r9 +1001f52e: e8bd 47f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +1001f532: f7f6 bf26 b.w 10016382 +1001f536: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + +1001f53a : +1001f53a: b5f0 push {r4, r5, r6, r7, lr} +1001f53c: 9c05 ldr r4, [sp, #20] +1001f53e: 2000 movs r0, #0 +1001f540: 250c movs r5, #12 +1001f542: e002 b.n 1001f54a +1001f544: 7876 ldrb r6, [r6, #1] +1001f546: 1cb6 adds r6, r6, #2 +1001f548: 1975 adds r5, r6, r5 +1001f54a: 429d cmp r5, r3 +1001f54c: d222 bcs.n 1001f594 +1001f54e: 5c6f ldrb r7, [r5, r1] +1001f550: 186e adds r6, r5, r1 +1001f552: 2fdd cmp r7, #221 ; 0xdd +1001f554: bf04 itt eq +1001f556: 78b7 ldrbeq r7, [r6, #2] +1001f558: 2f00 cmpeq r7, #0 +1001f55a: 4620 mov r0, r4 +1001f55c: d1f2 bne.n 1001f544 +1001f55e: 78f7 ldrb r7, [r6, #3] +1001f560: 2f50 cmp r7, #80 ; 0x50 +1001f562: bf01 itttt eq +1001f564: 7937 ldrbeq r7, [r6, #4] +1001f566: 2ff2 cmpeq r7, #242 ; 0xf2 +1001f568: 7977 ldrbeq r7, [r6, #5] +1001f56a: 2f02 cmpeq r7, #2 +1001f56c: d1ea bne.n 1001f544 +1001f56e: 1d6f adds r7, r5, #5 +1001f570: 429f cmp r7, r3 +1001f572: d2e7 bcs.n 1001f544 +1001f574: 462b mov r3, r5 +1001f576: e003 b.n 1001f580 +1001f578: 5c5e ldrb r6, [r3, r1] +1001f57a: 5486 strb r6, [r0, r2] +1001f57c: 1c40 adds r0, r0, #1 +1001f57e: 1c5b adds r3, r3, #1 +1001f580: f105 0609 add.w r6, r5, #9 +1001f584: 42b3 cmp r3, r6 +1001f586: d3f7 bcc.n 1001f578 +1001f588: 18a1 adds r1, r4, r2 +1001f58a: 2207 movs r2, #7 +1001f58c: 704a strb r2, [r1, #1] +1001f58e: 2200 movs r2, #0 +1001f590: 718a strb r2, [r1, #6] +1001f592: 720a strb r2, [r1, #8] +1001f594: bdf0 pop {r4, r5, r6, r7, pc} + +1001f596 : +1001f596: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +1001f59a: f500 5788 add.w r7, r0, #4352 ; 0x1100 +1001f59e: 37f0 adds r7, #240 ; 0xf0 +1001f5a0: 4614 mov r4, r2 +1001f5a2: f100 080c add.w r8, r0, #12 +1001f5a6: f8d7 6364 ldr.w r6, [r7, #868] ; 0x364 +1001f5aa: 2500 movs r5, #0 +1001f5ac: 220c movs r2, #12 +1001f5ae: 4620 mov r0, r4 +1001f5b0: f7f1 f92d bl 1001080e +1001f5b4: 2e03 cmp r6, #3 +1001f5b6: f04f 090c mov.w r9, #12 +1001f5ba: d101 bne.n 1001f5c0 +1001f5bc: 25dd movs r5, #221 ; 0xdd +1001f5be: e005 b.n 1001f5cc +1001f5c0: 2e04 cmp r6, #4 +1001f5c2: d0fb beq.n 1001f5bc +1001f5c4: 2e06 cmp r6, #6 +1001f5c6: bf14 ite ne +1001f5c8: 2e07 cmpne r6, #7 +1001f5ca: 2530 moveq r5, #48 ; 0x30 +1001f5cc: f44f 7180 mov.w r1, #256 ; 0x100 +1001f5d0: 4640 mov r0, r8 +1001f5d2: f7fe ff4a bl 1001e46a +1001f5d6: b160 cbz r0, 1001f5f2 +1001f5d8: f8d7 2350 ldr.w r2, [r7, #848] ; 0x350 +1001f5dc: f507 71a8 add.w r1, r7, #336 ; 0x150 +1001f5e0: f104 000c add.w r0, r4, #12 +1001f5e4: f7f1 f913 bl 1001080e +1001f5e8: f8d7 0350 ldr.w r0, [r7, #848] ; 0x350 +1001f5ec: f100 090c add.w r9, r0, #12 +1001f5f0: e011 b.n 1001f616 +1001f5f2: 2ddd cmp r5, #221 ; 0xdd +1001f5f4: bf18 it ne +1001f5f6: 2d30 cmpne r5, #48 ; 0x30 +1001f5f8: d10d bne.n 1001f616 +1001f5fa: f897 0389 ldrb.w r0, [r7, #905] ; 0x389 +1001f5fe: 1c82 adds r2, r0, #2 +1001f600: f507 7162 add.w r1, r7, #904 ; 0x388 +1001f604: f104 000c add.w r0, r4, #12 +1001f608: f7f1 f901 bl 1001080e +1001f60c: 7325 strb r5, [r4, #12] +1001f60e: f897 0389 ldrb.w r0, [r7, #905] ; 0x389 +1001f612: f100 090e add.w r9, r0, #14 +1001f616: 4648 mov r0, r9 +1001f618: e8bd 83f2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, pc} + +1001f61c : +1001f61c: 300c adds r0, #12 +1001f61e: f200 4144 addw r1, r0, #1092 ; 0x444 +1001f622: 2200 movs r2, #0 +1001f624: 804a strh r2, [r1, #2] +1001f626: f8a0 2444 strh.w r2, [r0, #1092] ; 0x444 +1001f62a: 608a str r2, [r1, #8] +1001f62c: 4770 bx lr + +1001f62e : +1001f62e: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +1001f632: 4689 mov r9, r1 +1001f634: b08c sub sp, #48 ; 0x30 +1001f636: 4692 mov sl, r2 +1001f638: f20f 2174 addw r1, pc, #628 ; 0x274 +1001f63c: 4604 mov r4, r0 +1001f63e: c984 ldmia r1!, {r2, r7} +1001f640: a803 add r0, sp, #12 +1001f642: f1a3 080c sub.w r8, r3, #12 +1001f646: c084 stmia r0!, {r2, r7} +1001f648: f104 000c add.w r0, r4, #12 +1001f64c: f500 6688 add.w r6, r0, #1088 ; 0x440 +1001f650: f500 6789 add.w r7, r0, #1096 ; 0x448 +1001f654: 2000 movs r0, #0 +1001f656: 6038 str r0, [r7, #0] +1001f658: 4643 mov r3, r8 +1001f65a: aa01 add r2, sp, #4 +1001f65c: 212d movs r1, #45 ; 0x2d +1001f65e: f109 000c add.w r0, r9, #12 +1001f662: f7f4 fc0d bl 10013e80 +1001f666: 2800 cmp r0, #0 +1001f668: bf1c itt ne +1001f66a: 9801 ldrne r0, [sp, #4] +1001f66c: 2800 cmpne r0, #0 +1001f66e: d046 beq.n 1001f6fe +1001f670: 9d14 ldr r5, [sp, #80] ; 0x50 +1001f672: 6830 ldr r0, [r6, #0] +1001f674: b948 cbnz r0, 1001f68a +1001f676: 9500 str r5, [sp, #0] +1001f678: ab03 add r3, sp, #12 +1001f67a: 6828 ldr r0, [r5, #0] +1001f67c: 2207 movs r2, #7 +1001f67e: 21dd movs r1, #221 ; 0xdd +1001f680: 4450 add r0, sl +1001f682: f7f8 fe7d bl 10018380 +1001f686: 2001 movs r0, #1 +1001f688: 6030 str r0, [r6, #0] +1001f68a: 221a movs r2, #26 +1001f68c: 682e ldr r6, [r5, #0] +1001f68e: 2100 movs r1, #0 +1001f690: a805 add r0, sp, #20 +1001f692: f7f1 f8d1 bl 10010838 +1001f696: f241 00e2 movw r0, #4322 ; 0x10e2 +1001f69a: f8ad 0014 strh.w r0, [sp, #20] +1001f69e: aa02 add r2, sp, #8 +1001f6a0: 210b movs r1, #11 +1001f6a2: 4620 mov r0, r4 +1001f6a4: f7f7 fe53 bl 1001734e +1001f6a8: 9802 ldr r0, [sp, #8] +1001f6aa: f000 0003 and.w r0, r0, #3 +1001f6ae: f241 11f4 movw r1, #4596 ; 0x11f4 +1001f6b2: f88d 0016 strb.w r0, [sp, #22] +1001f6b6: ab05 add r3, sp, #20 +1001f6b8: 5909 ldr r1, [r1, r4] +1001f6ba: 2904 cmp r1, #4 +1001f6bc: bf04 itt eq +1001f6be: f040 001c orreq.w r0, r0, #28 +1001f6c2: f88d 0016 strbeq.w r0, [sp, #22] +1001f6c6: 9500 str r5, [sp, #0] +1001f6c8: 221a movs r2, #26 +1001f6ca: 212d movs r1, #45 ; 0x2d +1001f6cc: eb06 000a add.w r0, r6, sl +1001f6d0: f7f8 fe56 bl 10018380 +1001f6d4: 2001 movs r0, #1 +1001f6d6: 6038 str r0, [r7, #0] +1001f6d8: 4643 mov r3, r8 +1001f6da: aa01 add r2, sp, #4 +1001f6dc: 213d movs r1, #61 ; 0x3d +1001f6de: f109 000c add.w r0, r9, #12 +1001f6e2: f7f4 fbcd bl 10013e80 +1001f6e6: b150 cbz r0, 1001f6fe +1001f6e8: 9901 ldr r1, [sp, #4] +1001f6ea: 2916 cmp r1, #22 +1001f6ec: d107 bne.n 1001f6fe +1001f6ee: 9500 str r5, [sp, #0] +1001f6f0: 1c83 adds r3, r0, #2 +1001f6f2: 6828 ldr r0, [r5, #0] +1001f6f4: 2216 movs r2, #22 +1001f6f6: 213d movs r1, #61 ; 0x3d +1001f6f8: 4450 add r0, sl +1001f6fa: f7f8 fe41 bl 10018380 +1001f6fe: 6838 ldr r0, [r7, #0] +1001f700: b00c add sp, #48 ; 0x30 +1001f702: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + +1001f706 : +1001f706: e92d 47fc stmdb sp!, {r2, r3, r4, r5, r6, r7, r8, r9, sl, lr} +1001f70a: 4604 mov r4, r0 +1001f70c: f204 4054 addw r0, r4, #1108 ; 0x454 +1001f710: 460d mov r5, r1 +1001f712: 6801 ldr r1, [r0, #0] +1001f714: f504 679d add.w r7, r4, #1256 ; 0x4e8 +1001f718: f507 7688 add.w r6, r7, #272 ; 0x110 +1001f71c: 2900 cmp r1, #0 +1001f71e: bf1e ittt ne +1001f720: f106 09b5 addne.w r9, r6, #181 ; 0xb5 +1001f724: f899 1001 ldrbne.w r1, [r9, #1] +1001f728: 2900 cmpne r1, #0 +1001f72a: bf1c itt ne +1001f72c: f896 10b5 ldrbne.w r1, [r6, #181] ; 0xb5 +1001f730: 2900 cmpne r1, #0 +1001f732: f504 58c4 add.w r8, r4, #6272 ; 0x1880 +1001f736: d066 beq.n 1001f806 +1001f738: 6843 ldr r3, [r0, #4] +1001f73a: f108 0151 add.w r1, r8, #81 ; 0x51 +1001f73e: 2b00 cmp r3, #0 +1001f740: bf04 itt eq +1001f742: 784b ldrbeq r3, [r1, #1] +1001f744: 2b01 cmpeq r3, #1 +1001f746: d103 bne.n 1001f750 +1001f748: 79c9 ldrb r1, [r1, #7] +1001f74a: 2901 cmp r1, #1 +1001f74c: d005 beq.n 1001f75a +1001f74e: e002 b.n 1001f756 +1001f750: 7849 ldrb r1, [r1, #1] +1001f752: 2902 cmp r1, #2 +1001f754: d101 bne.n 1001f75a +1001f756: 2101 movs r1, #1 +1001f758: 6041 str r1, [r0, #4] +1001f75a: 2000 movs r0, #0 +1001f75c: 9000 str r0, [sp, #0] +1001f75e: f1a2 0a0c sub.w sl, r2, #12 +1001f762: 4653 mov r3, sl +1001f764: aa00 add r2, sp, #0 +1001f766: 212d movs r1, #45 ; 0x2d +1001f768: f105 000c add.w r0, r5, #12 +1001f76c: f7f4 fb88 bl 10013e80 +1001f770: 2000 movs r0, #0 +1001f772: 9000 str r0, [sp, #0] +1001f774: 4653 mov r3, sl +1001f776: aa00 add r2, sp, #0 +1001f778: 213d movs r1, #61 ; 0x3d +1001f77a: f105 000c add.w r0, r5, #12 +1001f77e: f7f4 fb7f bl 10013e80 +1001f782: f898 0051 ldrb.w r0, [r8, #81] ; 0x51 +1001f786: 2800 cmp r0, #0 +1001f788: f106 05da add.w r5, r6, #218 ; 0xda +1001f78c: d030 beq.n 1001f7f0 +1001f78e: f896 00da ldrb.w r0, [r6, #218] ; 0xda +1001f792: 0780 lsls r0, r0, #30 +1001f794: d52c bpl.n 1001f7f0 +1001f796: 7ee8 ldrb r0, [r5, #27] +1001f798: 0740 lsls r0, r0, #29 +1001f79a: d529 bpl.n 1001f7f0 +1001f79c: f504 53e1 add.w r3, r4, #7200 ; 0x1c20 +1001f7a0: aa01 add r2, sp, #4 +1001f7a2: 681b ldr r3, [r3, #0] +1001f7a4: 2116 movs r1, #22 +1001f7a6: 4620 mov r0, r4 +1001f7a8: 4798 blx r3 +1001f7aa: 2000 movs r0, #0 +1001f7ac: 4917 ldr r1, [pc, #92] ; (1001f80c <.text_95>) +1001f7ae: 4a18 ldr r2, [pc, #96] ; (1001f810 <.text_96>) +1001f7b0: f89d 3004 ldrb.w r3, [sp, #4] +1001f7b4: 2b03 cmp r3, #3 +1001f7b6: bf18 it ne +1001f7b8: 2b00 cmpne r3, #0 +1001f7ba: d102 bne.n 1001f7c2 +1001f7bc: 1983 adds r3, r0, r6 +1001f7be: 5c44 ldrb r4, [r0, r1] +1001f7c0: e001 b.n 1001f7c6 +1001f7c2: 1983 adds r3, r0, r6 +1001f7c4: 5c84 ldrb r4, [r0, r2] +1001f7c6: f893 30dd ldrb.w r3, [r3, #221] ; 0xdd +1001f7ca: 4023 ands r3, r4 +1001f7cc: 1984 adds r4, r0, r6 +1001f7ce: 1c40 adds r0, r0, #1 +1001f7d0: 2810 cmp r0, #16 +1001f7d2: f884 30dd strb.w r3, [r4, #221] ; 0xdd +1001f7d6: dbeb blt.n 1001f7b0 +1001f7d8: 2001 movs r0, #1 +1001f7da: 73f8 strb r0, [r7, #15] +1001f7dc: 7ee8 ldrb r0, [r5, #27] +1001f7de: f000 0003 and.w r0, r0, #3 +1001f7e2: 2801 cmp r0, #1 +1001f7e4: d003 beq.n 1001f7ee +1001f7e6: 2803 cmp r0, #3 +1001f7e8: bf0c ite eq +1001f7ea: 2002 moveq r0, #2 +1001f7ec: 2000 movne r0, #0 +1001f7ee: 7438 strb r0, [r7, #16] +1001f7f0: f8b6 00da ldrh.w r0, [r6, #218] ; 0xda +1001f7f4: f3c0 0081 ubfx r0, r0, #2, #2 +1001f7f8: f889 0005 strb.w r0, [r9, #5] +1001f7fc: 7f28 ldrb r0, [r5, #28] +1001f7fe: f000 0003 and.w r0, r0, #3 +1001f802: f889 0002 strb.w r0, [r9, #2] +1001f806: e8bd 87f3 ldmia.w sp!, {r0, r1, r4, r5, r6, r7, r8, r9, sl, pc} + ... + +1001f80c <.text_95>: +1001f80c: 1001be94 .word 0x1001be94 + +1001f810 <.text_96>: +1001f810: 1001bea4 .word 0x1001bea4 + +1001f814 <.text_99>: +1001f814: 2101 movs r1, #1 +1001f816: f104 000c add.w r0, r4, #12 +1001f81a: f7fe be26 b.w 1001e46a + +1001f81e : +1001f81e: b1a8 cbz r0, 1001f84c +1001f820: f641 5148 movw r1, #7496 ; 0x1d48 +1001f824: 5808 ldr r0, [r1, r0] +1001f826: b180 cbz r0, 1001f84a +1001f828: f641 419c movw r1, #7324 ; 0x1c9c +1001f82c: 580a ldr r2, [r1, r0] +1001f82e: 2a00 cmp r2, #0 +1001f830: bf02 ittt eq +1001f832: 1809 addeq r1, r1, r0 +1001f834: 684a ldreq r2, [r1, #4] +1001f836: 2a00 cmpeq r2, #0 +1001f838: d107 bne.n 1001f84a +1001f83a: f641 5228 movw r2, #7464 ; 0x1d28 +1001f83e: 5810 ldr r0, [r2, r0] +1001f840: b118 cbz r0, 1001f84a +1001f842: 7e48 ldrb r0, [r1, #25] +1001f844: b110 cbz r0, 1001f84c +1001f846: 2001 movs r0, #1 +1001f848: 4770 bx lr +1001f84a: 2000 movs r0, #0 +1001f84c: 4770 bx lr + +1001f84e : +1001f84e: 2800 cmp r0, #0 +1001f850: bf1e ittt ne +1001f852: f641 5248 movwne r2, #7496 ; 0x1d48 +1001f856: 5810 ldrne r0, [r2, r0] +1001f858: 2800 cmpne r0, #0 +1001f85a: d009 beq.n 1001f870 +1001f85c: 6900 ldr r0, [r0, #16] +1001f85e: 2900 cmp r1, #0 +1001f860: bf08 it eq +1001f862: 2800 cmpeq r0, #0 +1001f864: d001 beq.n 1001f86a +1001f866: 4208 tst r0, r1 +1001f868: d001 beq.n 1001f86e +1001f86a: 2001 movs r0, #1 +1001f86c: 4770 bx lr +1001f86e: 2000 movs r0, #0 +1001f870: 4770 bx lr + ... + +1001f874 : +1001f874: 6f4e 4120 7373 636f 4e20 7465 6f77 6b72 No Assoc Network +1001f884: 4120 7466 7265 5320 6163 206e 6f44 656e After Scan Done +1001f894: 0000 0000 .... + +1001f898 : +1001f898: 4552 4f43 4e4e 4345 4954 4e4f 4620 4941 RECONNECTION FAI +1001f8a8: 554c 4552 0000 0000 LURE.... + +1001f8b0 : +1001f8b0: 5000 02f2 0100 0000 .P...... + +1001f8b8 : +1001f8b8: e92d 41fc stmdb sp!, {r2, r3, r4, r5, r6, r7, r8, lr} +1001f8bc: ea5f 0800 movs.w r8, r0 +1001f8c0: d048 beq.n 1001f954 +1001f8c2: 4e25 ldr r6, [pc, #148] ; (1001f958 <.text_3>) +1001f8c4: 6830 ldr r0, [r6, #0] +1001f8c6: ad00 add r5, sp, #0 +1001f8c8: b180 cbz r0, 1001f8ec +1001f8ca: 2700 movs r7, #0 +1001f8cc: 2400 movs r4, #0 +1001f8ce: 6830 ldr r0, [r6, #0] +1001f8d0: 1821 adds r1, r4, r0 +1001f8d2: 5c20 ldrb r0, [r4, r0] +1001f8d4: 7849 ldrb r1, [r1, #1] +1001f8d6: f7f4 fad7 bl 10013e88 +1001f8da: 5578 strb r0, [r7, r5] +1001f8dc: 1c7f adds r7, r7, #1 +1001f8de: 1ce4 adds r4, r4, #3 +1001f8e0: 2f06 cmp r7, #6 +1001f8e2: dbf4 blt.n 1001f8ce +1001f8e4: 2206 movs r2, #6 +1001f8e6: a900 add r1, sp, #0 +1001f8e8: 4640 mov r0, r8 +1001f8ea: e002 b.n 1001f8f2 +1001f8ec: 2206 movs r2, #6 +1001f8ee: 4641 mov r1, r8 +1001f8f0: a800 add r0, sp, #0 +1001f8f2: f7f0 ff8c bl 1001080e +1001f8f6: f89d 7000 ldrb.w r7, [sp] +1001f8fa: 7968 ldrb r0, [r5, #5] +1001f8fc: 7929 ldrb r1, [r5, #4] +1001f8fe: 78ea ldrb r2, [r5, #3] +1001f900: 78ab ldrb r3, [r5, #2] +1001f902: 786e ldrb r6, [r5, #1] +1001f904: 2fff cmp r7, #255 ; 0xff +1001f906: d109 bne.n 1001f91c +1001f908: 2eff cmp r6, #255 ; 0xff +1001f90a: bf08 it eq +1001f90c: 2bff cmpeq r3, #255 ; 0xff +1001f90e: d121 bne.n 1001f954 +1001f910: 2aff cmp r2, #255 ; 0xff +1001f912: bf04 itt eq +1001f914: 29ff cmpeq r1, #255 ; 0xff +1001f916: 28ff cmpeq r0, #255 ; 0xff +1001f918: d11c bne.n 1001f954 +1001f91a: e00b b.n 1001f934 +1001f91c: 2f00 cmp r7, #0 +1001f91e: bf08 it eq +1001f920: 2e00 cmpeq r6, #0 +1001f922: d117 bne.n 1001f954 +1001f924: 2b00 cmp r3, #0 +1001f926: bf08 it eq +1001f928: 2a00 cmpeq r2, #0 +1001f92a: d113 bne.n 1001f954 +1001f92c: 2900 cmp r1, #0 +1001f92e: bf08 it eq +1001f930: 2800 cmpeq r0, #0 +1001f932: d10f bne.n 1001f954 +1001f934: 2000 movs r0, #0 +1001f936: f88d 0000 strb.w r0, [sp] +1001f93a: 2206 movs r2, #6 +1001f93c: 20e0 movs r0, #224 ; 0xe0 +1001f93e: 7068 strb r0, [r5, #1] +1001f940: a900 add r1, sp, #0 +1001f942: 204c movs r0, #76 ; 0x4c +1001f944: 70a8 strb r0, [r5, #2] +1001f946: 2087 movs r0, #135 ; 0x87 +1001f948: 70e8 strb r0, [r5, #3] +1001f94a: 2000 movs r0, #0 +1001f94c: 80a8 strh r0, [r5, #4] +1001f94e: 4640 mov r0, r8 +1001f950: f7f0 ff5d bl 1001080e +1001f954: e8bd 81f3 ldmia.w sp!, {r0, r1, r4, r5, r6, r7, r8, pc} + +1001f958 <.text_3>: +1001f958: 1004831c .word 0x1004831c + +1001f95c : +1001f95c: b570 push {r4, r5, r6, lr} +1001f95e: b086 sub sp, #24 +1001f960: 4604 mov r4, r0 +1001f962: 2000 movs r0, #0 +1001f964: 9004 str r0, [sp, #16] +1001f966: 9003 str r0, [sp, #12] +1001f968: 9002 str r0, [sp, #8] +1001f96a: f104 06a4 add.w r6, r4, #164 ; 0xa4 +1001f96e: f8d4 0094 ldr.w r0, [r4, #148] ; 0x94 +1001f972: f1a0 020c sub.w r2, r0, #12 +1001f976: 2500 movs r5, #0 +1001f978: a901 add r1, sp, #4 +1001f97a: 4630 mov r0, r6 +1001f97c: f7fa f80c bl 10019998 +1001f980: 2800 cmp r0, #0 +1001f982: bf1c itt ne +1001f984: 9901 ldrne r1, [sp, #4] +1001f986: 2900 cmpne r1, #0 +1001f988: d006 beq.n 1001f998 +1001f98a: f000 f825 bl 1001f9d8 <.text_5> +1001f98e: f7f4 fa73 bl 10013e78 +1001f992: 2801 cmp r0, #1 +1001f994: d11d bne.n 1001f9d2 +1001f996: e012 b.n 1001f9be +1001f998: f8d4 0094 ldr.w r0, [r4, #148] ; 0x94 +1001f99c: f1a0 020c sub.w r2, r0, #12 +1001f9a0: a901 add r1, sp, #4 +1001f9a2: 4630 mov r0, r6 +1001f9a4: f7f9 fffc bl 100199a0 +1001f9a8: 2800 cmp r0, #0 +1001f9aa: bf1c itt ne +1001f9ac: 9901 ldrne r1, [sp, #4] +1001f9ae: 2900 cmpne r1, #0 +1001f9b0: d00f beq.n 1001f9d2 +1001f9b2: f000 f811 bl 1001f9d8 <.text_5> +1001f9b6: f7f4 fa5b bl 10013e70 +1001f9ba: 2801 cmp r0, #1 +1001f9bc: d109 bne.n 1001f9d2 +1001f9be: f504 7067 add.w r0, r4, #924 ; 0x39c +1001f9c2: 9903 ldr r1, [sp, #12] +1001f9c4: 6041 str r1, [r0, #4] +1001f9c6: 2501 movs r5, #1 +1001f9c8: 9904 ldr r1, [sp, #16] +1001f9ca: f8c4 139c str.w r1, [r4, #924] ; 0x39c +1001f9ce: 9902 ldr r1, [sp, #8] +1001f9d0: 6081 str r1, [r0, #8] +1001f9d2: 4628 mov r0, r5 +1001f9d4: b006 add sp, #24 +1001f9d6: bd70 pop {r4, r5, r6, pc} + +1001f9d8 <.text_5>: +1001f9d8: a902 add r1, sp, #8 +1001f9da: 9100 str r1, [sp, #0] +1001f9dc: ab03 add r3, sp, #12 +1001f9de: 9901 ldr r1, [sp, #4] +1001f9e0: aa04 add r2, sp, #16 +1001f9e2: 1c89 adds r1, r1, #2 +1001f9e4: 4770 bx lr + +1001f9e6 : +1001f9e6: b5f0 push {r4, r5, r6, r7, lr} +1001f9e8: b087 sub sp, #28 +1001f9ea: 4604 mov r4, r0 +1001f9ec: 2000 movs r0, #0 +1001f9ee: f8ad 0008 strh.w r0, [sp, #8] +1001f9f2: 9005 str r0, [sp, #20] +1001f9f4: 9004 str r0, [sp, #16] +1001f9f6: f104 0798 add.w r7, r4, #152 ; 0x98 +1001f9fa: 2600 movs r6, #0 +1001f9fc: 4638 mov r0, r7 +1001f9fe: f7fe ff69 bl 1001e8d4 +1001fa02: 4601 mov r1, r0 +1001fa04: 2202 movs r2, #2 +1001fa06: a802 add r0, sp, #8 +1001fa08: f7f0 ff01 bl 1001080e +1001fa0c: f8bd 0008 ldrh.w r0, [sp, #8] +1001fa10: 06c0 lsls r0, r0, #27 +1001fa12: bf46 itte mi +1001fa14: 2601 movmi r6, #1 +1001fa16: 6526 strmi r6, [r4, #80] ; 0x50 +1001fa18: f884 6398 strbpl.w r6, [r4, #920] ; 0x398 +1001fa1c: a805 add r0, sp, #20 +1001fa1e: 9001 str r0, [sp, #4] +1001fa20: f104 0550 add.w r5, r4, #80 ; 0x50 +1001fa24: 2000 movs r0, #0 +1001fa26: 9000 str r0, [sp, #0] +1001fa28: ab04 add r3, sp, #16 +1001fa2a: 6c69 ldr r1, [r5, #68] ; 0x44 +1001fa2c: 2200 movs r2, #0 +1001fa2e: 4638 mov r0, r7 +1001fa30: f7f6 fc30 bl 10016294 +1001fa34: 6c68 ldr r0, [r5, #68] ; 0x44 +1001fa36: f104 07a4 add.w r7, r4, #164 ; 0xa4 +1001fa3a: f1a0 030c sub.w r3, r0, #12 +1001fa3e: aa04 add r2, sp, #16 +1001fa40: 2130 movs r1, #48 ; 0x30 +1001fa42: 4638 mov r0, r7 +1001fa44: f7f4 fa1c bl 10013e80 +1001fa48: 9904 ldr r1, [sp, #16] +1001fa4a: 2900 cmp r1, #0 +1001fa4c: bf0c ite eq +1001fa4e: 2800 cmpeq r0, #0 +1001fa50: 2003 movne r0, #3 +1001fa52: d105 bne.n 1001fa60 +1001fa54: 9805 ldr r0, [sp, #20] +1001fa56: b108 cbz r0, 1001fa5c +1001fa58: 2002 movs r0, #2 +1001fa5a: e001 b.n 1001fa60 +1001fa5c: b116 cbz r6, 1001fa64 +1001fa5e: 2001 movs r0, #1 +1001fa60: f884 0398 strb.w r0, [r4, #920] ; 0x398 +1001fa64: 4620 mov r0, r4 +1001fa66: f7ff ff79 bl 1001f95c +1001fa6a: 6c68 ldr r0, [r5, #68] ; 0x44 +1001fa6c: f1a0 030c sub.w r3, r0, #12 +1001fa70: aa03 add r2, sp, #12 +1001fa72: 212d movs r1, #45 ; 0x2d +1001fa74: 4638 mov r0, r7 +1001fa76: f7f4 fa03 bl 10013e80 +1001fa7a: 2800 cmp r0, #0 +1001fa7c: f504 7466 add.w r4, r4, #920 ; 0x398 +1001fa80: bf1d ittte ne +1001fa82: 9903 ldrne r1, [sp, #12] +1001fa84: 2900 cmpne r1, #0 +1001fa86: 8840 ldrhne r0, [r0, #2] +1001fa88: 2000 moveq r0, #0 +1001fa8a: 8220 strh r0, [r4, #16] +1001fa8c: aa03 add r2, sp, #12 +1001fa8e: 6c68 ldr r0, [r5, #68] ; 0x44 +1001fa90: f1a0 030c sub.w r3, r0, #12 +1001fa94: 213d movs r1, #61 ; 0x3d +1001fa96: 4638 mov r0, r7 +1001fa98: f7f4 f9f2 bl 10013e80 +1001fa9c: 2800 cmp r0, #0 +1001fa9e: bf1d ittte ne +1001faa0: 9903 ldrne r1, [sp, #12] +1001faa2: 2900 cmpne r1, #0 +1001faa4: 78c0 ldrbne r0, [r0, #3] +1001faa6: 2000 moveq r0, #0 +1001faa8: 74a0 strb r0, [r4, #18] +1001faaa: b007 add sp, #28 +1001faac: bdf0 pop {r4, r5, r6, r7, pc} + ... + +1001fab0 : +1001fab0: 480c ldr r0, [pc, #48] ; (1001fae4 <.text_6>) +1001fab2: 6800 ldr r0, [r0, #0] +1001fab4: 0001 movs r1, r0 +1001fab6: bf18 it ne + +1001fab8 <__iar_annotation$$tailcall>: +1001fab8: 4700 bxne r0 +1001faba: 2000 movs r0, #0 +1001fabc: 4770 bx lr + +1001fabe : +1001fabe: 4909 ldr r1, [pc, #36] ; (1001fae4 <.text_6>) +1001fac0: 6849 ldr r1, [r1, #4] +1001fac2: 000a movs r2, r1 +1001fac4: bf18 it ne + +1001fac6 <__iar_annotation$$tailcall>: +1001fac6: 4708 bxne r1 +1001fac8: 4770 bx lr + +1001faca : +1001faca: 4906 ldr r1, [pc, #24] ; (1001fae4 <.text_6>) +1001facc: 6889 ldr r1, [r1, #8] +1001face: 000a movs r2, r1 +1001fad0: bf18 it ne + +1001fad2 <__iar_annotation$$tailcall>: +1001fad2: 4708 bxne r1 +1001fad4: 4770 bx lr + +1001fad6 : +1001fad6: 4903 ldr r1, [pc, #12] ; (1001fae4 <.text_6>) +1001fad8: 68c9 ldr r1, [r1, #12] +1001fada: 000a movs r2, r1 +1001fadc: bf18 it ne + +1001fade <__iar_annotation$$tailcall>: +1001fade: 4708 bxne r1 +1001fae0: 4770 bx lr + ... + +1001fae4 <.text_6>: +1001fae4: 10004464 .word 0x10004464 + +1001fae8 <_enter_pwrlock>: +1001fae8: f7f0 bee0 b.w 100108ac + +1001faec <_exit_pwrlock>: +1001faec: f7f0 becf b.w 1001088e + +1001faf0 : +1001faf0: 6840 ldr r0, [r0, #4] +1001faf2: 4208 tst r0, r1 +1001faf4: d001 beq.n 1001fafa +1001faf6: 2001 movs r0, #1 +1001faf8: 4770 bx lr +1001fafa: 2000 movs r0, #0 +1001fafc: 4770 bx lr + +1001fafe : +1001fafe: b5f8 push {r3, r4, r5, r6, r7, lr} +1001fb00: 4604 mov r4, r0 +1001fb02: f504 55c8 add.w r5, r4, #6400 ; 0x1900 +1001fb06: 350c adds r5, #12 +1001fb08: 4628 mov r0, r5 +1001fb0a: f7ff ffed bl 1001fae8 <_enter_pwrlock> +1001fb0e: f105 0610 add.w r6, r5, #16 +1001fb12: 2001 movs r0, #1 +1001fb14: 6230 str r0, [r6, #32] +1001fb16: 7fb0 ldrb r0, [r6, #30] +1001fb18: 7770 strb r0, [r6, #29] +1001fb1a: 6970 ldr r0, [r6, #20] +1001fb1c: 1c40 adds r0, r0, #1 +1001fb1e: 6170 str r0, [r6, #20] +1001fb20: 6df0 ldr r0, [r6, #92] ; 0x5c +1001fb22: 2802 cmp r0, #2 +1001fb24: d12a bne.n 1001fb7c +1001fb26: 2001 movs r0, #1 +1001fb28: 7428 strb r0, [r5, #16] +1001fb2a: 7f70 ldrb r0, [r6, #29] +1001fb2c: 2802 cmp r0, #2 +1001fb2e: bf04 itt eq +1001fb30: 2001 moveq r0, #1 +1001fb32: f885 0073 strbeq.w r0, [r5, #115] ; 0x73 +1001fb36: f7f0 ff2a bl 1001098e +1001fb3a: f504 57e5 add.w r7, r4, #7328 ; 0x1ca0 +1001fb3e: 2001 movs r0, #1 +1001fb40: f641 5144 movw r1, #7492 ; 0x1d44 +1001fb44: 6078 str r0, [r7, #4] +1001fb46: 5508 strb r0, [r1, r4] +1001fb48: 2200 movs r2, #0 +1001fb4a: 213e movs r1, #62 ; 0x3e +1001fb4c: 4620 mov r0, r4 +1001fb4e: f7f7 fbdf bl 10017310 +1001fb52: f504 50e9 add.w r0, r4, #7456 ; 0x1d20 +1001fb56: 6801 ldr r1, [r0, #0] +1001fb58: 0008 movs r0, r1 +1001fb5a: bf1c itt ne +1001fb5c: 4620 movne r0, r4 +1001fb5e: 4788 blxne r1 +1001fb60: f504 50e5 add.w r0, r4, #7328 ; 0x1ca0 +1001fb64: 6800 ldr r0, [r0, #0] +1001fb66: b910 cbnz r0, 1001fb6e +1001fb68: 4620 mov r0, r4 +1001fb6a: f7f7 fbc4 bl 100172f6 +1001fb6e: 2000 movs r0, #0 +1001fb70: 6078 str r0, [r7, #4] +1001fb72: 2002 movs r0, #2 +1001fb74: 65b0 str r0, [r6, #88] ; 0x58 +1001fb76: 2006 movs r0, #6 +1001fb78: f7ed f8f2 bl 1000cd60 +1001fb7c: 2000 movs r0, #0 +1001fb7e: 6230 str r0, [r6, #32] +1001fb80: 4628 mov r0, r5 +1001fb82: e8bd 40f2 ldmia.w sp!, {r1, r4, r5, r6, r7, lr} +1001fb86: e7b1 b.n 1001faec <_exit_pwrlock> + +1001fb88 : +1001fb88: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1001fb8c: 4604 mov r4, r0 +1001fb8e: f504 50c8 add.w r0, r4, #6400 ; 0x1900 +1001fb92: f100 080c add.w r8, r0, #12 +1001fb96: f504 5688 add.w r6, r4, #4352 ; 0x1100 +1001fb9a: 36f0 adds r6, #240 ; 0xf0 +1001fb9c: f104 0a0c add.w sl, r4, #12 +1001fba0: f04f 0901 mov.w r9, #1 +1001fba4: 4640 mov r0, r8 +1001fba6: f7ff ff9f bl 1001fae8 <_enter_pwrlock> +1001fbaa: f108 0510 add.w r5, r8, #16 +1001fbae: 6da8 ldr r0, [r5, #88] ; 0x58 +1001fbb0: 2802 cmp r0, #2 +1001fbb2: bf04 itt eq +1001fbb4: 6a28 ldreq r0, [r5, #32] +1001fbb6: 2800 cmpeq r0, #0 +1001fbb8: d166 bne.n 1001fc88 +1001fbba: 2004 movs r0, #4 +1001fbbc: f7ed f8ce bl 1000cd5c +1001fbc0: f8c5 9020 str.w r9, [r5, #32] +1001fbc4: 2000 movs r0, #0 +1001fbc6: 65e8 str r0, [r5, #92] ; 0x5c +1001fbc8: 69a8 ldr r0, [r5, #24] +1001fbca: 1c40 adds r0, r0, #1 +1001fbcc: 61a8 str r0, [r5, #24] +1001fbce: f7f0 fede bl 1001098e +1001fbd2: 4620 mov r0, r4 +1001fbd4: f7f8 facd bl 10018172 +1001fbd8: f641 5144 movw r1, #7492 ; 0x1d44 +1001fbdc: 2000 movs r0, #0 +1001fbde: 5508 strb r0, [r1, r4] +1001fbe0: 2100 movs r1, #0 +1001fbe2: f641 409c movw r0, #7324 ; 0x1c9c +1001fbe6: f641 571c movw r7, #7452 ; 0x1d1c +1001fbea: 5101 str r1, [r0, r4] +1001fbec: 1900 adds r0, r0, r4 +1001fbee: eb07 0b04 add.w fp, r7, r4 +1001fbf2: 6041 str r1, [r0, #4] +1001fbf4: 6081 str r1, [r0, #8] +1001fbf6: f8cb 900c str.w r9, [fp, #12] +1001fbfa: 4620 mov r0, r4 +1001fbfc: f7f7 fb58 bl 100172b0 +1001fc00: b920 cbnz r0, 1001fc0c +1001fc02: f8cb 000c str.w r0, [fp, #12] +1001fc06: f04f 0900 mov.w r9, #0 +1001fc0a: e010 b.n 1001fc2e +1001fc0c: 5939 ldr r1, [r7, r4] +1001fc0e: 0008 movs r0, r1 +1001fc10: bf1c itt ne +1001fc12: 4620 movne r0, r4 +1001fc14: 4788 blxne r1 +1001fc16: f000 f897 bl 1001fd48 <.text_9> +1001fc1a: f241 3188 movw r1, #5000 ; 0x1388 +1001fc1e: f504 6092 add.w r0, r4, #1168 ; 0x490 +1001fc22: f7f0 ff0a bl 10010a3a +1001fc26: f7f2 fa8d bl 10012144 +1001fc2a: 2000 movs r0, #0 +1001fc2c: 65a8 str r0, [r5, #88] ; 0x58 +1001fc2e: 6870 ldr r0, [r6, #4] +1001fc30: 2801 cmp r0, #1 +1001fc32: bf18 it ne +1001fc34: 2805 cmpne r0, #5 +1001fc36: d11b bne.n 1001fc70 +1001fc38: f894 14f6 ldrb.w r1, [r4, #1270] ; 0x4f6 +1001fc3c: 2300 movs r3, #0 +1001fc3e: 2200 movs r2, #0 +1001fc40: 4620 mov r0, r4 +1001fc42: f005 ffa9 bl 10025b98 +1001fc46: 2700 movs r7, #0 +1001fc48: f89a 0490 ldrb.w r0, [sl, #1168] ; 0x490 +1001fc4c: 2101 movs r1, #1 +1001fc4e: 40b9 lsls r1, r7 +1001fc50: 4208 tst r0, r1 +1001fc52: d00a beq.n 1001fc6a +1001fc54: 68b0 ldr r0, [r6, #8] +1001fc56: 4287 cmp r7, r0 +1001fc58: bf0c ite eq +1001fc5a: 2301 moveq r3, #1 +1001fc5c: 2300 movne r3, #0 +1001fc5e: 463a mov r2, r7 +1001fc60: 4631 mov r1, r6 +1001fc62: 4620 mov r0, r4 +1001fc64: f7ff fc0b bl 1001f47e +1001fc68: 4681 mov r9, r0 +1001fc6a: 1c7f adds r7, r7, #1 +1001fc6c: 2f04 cmp r7, #4 +1001fc6e: dbeb blt.n 1001fc48 +1001fc70: 2200 movs r2, #0 +1001fc72: f240 5122 movw r1, #1314 ; 0x522 +1001fc76: 4620 mov r0, r4 +1001fc78: f004 ffea bl 10024c50 +1001fc7c: 2000 movs r0, #0 +1001fc7e: 6228 str r0, [r5, #32] +1001fc80: f888 0073 strb.w r0, [r8, #115] ; 0x73 +1001fc84: f888 0010 strb.w r0, [r8, #16] +1001fc88: 4640 mov r0, r8 +1001fc8a: f7ff ff2f bl 1001faec <_exit_pwrlock> +1001fc8e: 4648 mov r0, r9 +1001fc90: e8bd 8ff2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1001fc94 : +1001fc94: b5f8 push {r3, r4, r5, r6, r7, lr} +1001fc96: 4604 mov r4, r0 +1001fc98: f641 5048 movw r0, #7496 ; 0x1d48 +1001fc9c: f104 060c add.w r6, r4, #12 +1001fca0: 5905 ldr r5, [r0, r4] +1001fca2: 2700 movs r7, #0 +1001fca4: f7f0 fe73 bl 1001098e +1001fca8: f504 51ca add.w r1, r4, #6464 ; 0x1940 +1001fcac: 6809 ldr r1, [r1, #0] +1001fcae: 4281 cmp r1, r0 +1001fcb0: d224 bcs.n 1001fcfc +1001fcb2: f640 0481 movw r4, #2177 ; 0x881 +1001fcb6: 4621 mov r1, r4 +1001fcb8: f000 f88f bl 1001fdda <.text_13+0x2> +1001fcbc: 2801 cmp r0, #1 +1001fcbe: d01d beq.n 1001fcfc +1001fcc0: f000 f88a bl 1001fdd8 <.text_13> +1001fcc4: 2801 cmp r0, #1 +1001fcc6: d019 beq.n 1001fcfc +1001fcc8: 2160 movs r1, #96 ; 0x60 +1001fcca: f000 f886 bl 1001fdda <.text_13+0x2> +1001fcce: 2801 cmp r0, #1 +1001fcd0: d014 beq.n 1001fcfc +1001fcd2: b195 cbz r5, 1001fcfa +1001fcd4: 350c adds r5, #12 +1001fcd6: 4621 mov r1, r4 +1001fcd8: 4628 mov r0, r5 +1001fcda: f7ff ff09 bl 1001faf0 +1001fcde: 2801 cmp r0, #1 +1001fce0: d00c beq.n 1001fcfc +1001fce2: 2110 movs r1, #16 +1001fce4: 4628 mov r0, r5 +1001fce6: f7ff ff03 bl 1001faf0 +1001fcea: 2801 cmp r0, #1 +1001fcec: d006 beq.n 1001fcfc +1001fcee: 2160 movs r1, #96 ; 0x60 +1001fcf0: 4628 mov r0, r5 +1001fcf2: f7ff fefd bl 1001faf0 +1001fcf6: 2801 cmp r0, #1 +1001fcf8: d000 beq.n 1001fcfc +1001fcfa: 2701 movs r7, #1 +1001fcfc: 4638 mov r0, r7 +1001fcfe: bdf2 pop {r1, r4, r5, r6, r7, pc} + +1001fd00 : +1001fd00: b570 push {r4, r5, r6, lr} +1001fd02: 4604 mov r4, r0 +1001fd04: f504 56c8 add.w r6, r4, #6400 ; 0x1900 +1001fd08: 360c adds r6, #12 +1001fd0a: f106 052e add.w r5, r6, #46 ; 0x2e +1001fd0e: 2001 movs r0, #1 +1001fd10: 72a8 strb r0, [r5, #10] +1001fd12: f896 002e ldrb.w r0, [r6, #46] ; 0x2e +1001fd16: b190 cbz r0, 1001fd3e +1001fd18: 4620 mov r0, r4 +1001fd1a: f7ff ffbb bl 1001fc94 +1001fd1e: b170 cbz r0, 1001fd3e +1001fd20: f106 0060 add.w r0, r6, #96 ; 0x60 +1001fd24: 6881 ldr r1, [r0, #8] +1001fd26: 2900 cmp r1, #0 +1001fd28: bf02 ittt eq +1001fd2a: f896 1060 ldrbeq.w r1, [r6, #96] ; 0x60 +1001fd2e: 2203 moveq r2, #3 +1001fd30: 4211 tsteq r1, r2 +1001fd32: d104 bne.n 1001fd3e +1001fd34: 2102 movs r1, #2 +1001fd36: 60c1 str r1, [r0, #12] +1001fd38: 4620 mov r0, r4 +1001fd3a: f7ff fee0 bl 1001fafe +1001fd3e: f000 f803 bl 1001fd48 <.text_9> +1001fd42: 2000 movs r0, #0 +1001fd44: 72a8 strb r0, [r5, #10] +1001fd46: bd70 pop {r4, r5, r6, pc} + +1001fd48 <.text_9>: +1001fd48: f641 1068 movw r0, #6504 ; 0x1968 +1001fd4c: 5901 ldr r1, [r0, r4] +1001fd4e: f504 50c8 add.w r0, r4, #6400 ; 0x1900 +1001fd52: 305c adds r0, #92 ; 0x5c +1001fd54: f7f0 be71 b.w 10010a3a + +1001fd58 : +1001fd58: f7f6 bf63 b.w 10016c22 + +1001fd5c : +1001fd5c: b570 push {r4, r5, r6, lr} +1001fd5e: 4605 mov r5, r0 +1001fd60: f505 54c8 add.w r4, r5, #6400 ; 0x1900 +1001fd64: f105 060c add.w r6, r5, #12 +1001fd68: 340c adds r4, #12 +1001fd6a: 2101 movs r1, #1 +1001fd6c: f000 f835 bl 1001fdda <.text_13+0x2> +1001fd70: b370 cbz r0, 1001fdd0 +1001fd72: f44f 6100 mov.w r1, #2048 ; 0x800 +1001fd76: f000 f830 bl 1001fdda <.text_13+0x2> +1001fd7a: 2801 cmp r0, #1 +1001fd7c: d028 beq.n 1001fdd0 +1001fd7e: f000 f82b bl 1001fdd8 <.text_13> +1001fd82: 2801 cmp r0, #1 +1001fd84: d024 beq.n 1001fdd0 +1001fd86: 2140 movs r1, #64 ; 0x40 +1001fd88: f000 f827 bl 1001fdda <.text_13+0x2> +1001fd8c: 2801 cmp r0, #1 +1001fd8e: d01f beq.n 1001fdd0 +1001fd90: 2120 movs r1, #32 +1001fd92: f000 f822 bl 1001fdda <.text_13+0x2> +1001fd96: 2801 cmp r0, #1 +1001fd98: d01a beq.n 1001fdd0 +1001fd9a: f241 10f0 movw r0, #4592 ; 0x11f0 +1001fd9e: 5940 ldr r0, [r0, r5] +1001fda0: 2802 cmp r0, #2 +1001fda2: bf02 ittt eq +1001fda4: f241 5044 movweq r0, #5444 ; 0x1544 +1001fda8: 5d40 ldrbeq r0, [r0, r5] +1001fdaa: 2800 cmpeq r0, #0 +1001fdac: d013 beq.n 1001fdd6 +1001fdae: f641 5051 movw r0, #7505 ; 0x1d51 +1001fdb2: 5d40 ldrb r0, [r0, r5] +1001fdb4: b970 cbnz r0, 1001fdd4 +1001fdb6: f7f0 fdea bl 1001098e +1001fdba: 6c21 ldr r1, [r4, #64] ; 0x40 +1001fdbc: 1a45 subs r5, r0, r1 +1001fdbe: 2001 movs r0, #1 +1001fdc0: f7f0 fe05 bl 100109ce +1001fdc4: 4285 cmp r5, r0 +1001fdc6: d303 bcc.n 1001fdd0 +1001fdc8: f894 004e ldrb.w r0, [r4, #78] ; 0x4e +1001fdcc: 2801 cmp r0, #1 +1001fdce: d101 bne.n 1001fdd4 +1001fdd0: 2000 movs r0, #0 +1001fdd2: bd70 pop {r4, r5, r6, pc} +1001fdd4: 2001 movs r0, #1 +1001fdd6: bd70 pop {r4, r5, r6, pc} + +1001fdd8 <.text_13>: +1001fdd8: 2110 movs r1, #16 +1001fdda: 4630 mov r0, r6 +1001fddc: e688 b.n 1001faf0 + +1001fdde : +1001fdde: e92d 41f3 stmdb sp!, {r0, r1, r4, r5, r6, r7, r8, lr} +1001fde2: 4680 mov r8, r0 +1001fde4: f508 57c8 add.w r7, r8, #6400 ; 0x1900 +1001fde8: 370c adds r7, #12 +1001fdea: 290b cmp r1, #11 +1001fdec: 4615 mov r5, r2 +1001fdee: 461e mov r6, r3 +1001fdf0: da28 bge.n 1001fe44 +1001fdf2: 7a38 ldrb r0, [r7, #8] +1001fdf4: 4288 cmp r0, r1 +1001fdf6: f107 0408 add.w r4, r7, #8 +1001fdfa: d107 bne.n 1001fe0c +1001fdfc: b311 cbz r1, 1001fe44 +1001fdfe: 7860 ldrb r0, [r4, #1] +1001fe00: 42a8 cmp r0, r5 +1001fe02: bf04 itt eq +1001fe04: 78a0 ldrbeq r0, [r4, #2] +1001fe06: 42b0 cmpeq r0, r6 +1001fe08: d10b bne.n 1001fe22 +1001fe0a: e01b b.n 1001fe44 +1001fe0c: b949 cbnz r1, 1001fe22 +1001fe0e: 7239 strb r1, [r7, #8] +1001fe10: aa01 add r2, sp, #4 +1001fe12: 2129 movs r1, #41 ; 0x29 +1001fe14: 4640 mov r0, r8 +1001fe16: f7f7 fa7b bl 10017310 +1001fe1a: 2000 movs r0, #0 +1001fe1c: f887 003c strb.w r0, [r7, #60] ; 0x3c +1001fe20: e010 b.n 1001fe44 +1001fe22: 4640 mov r0, r8 +1001fe24: f7ff ff9a bl 1001fd5c +1001fe28: b160 cbz r0, 1001fe44 +1001fe2a: 2001 movs r0, #1 +1001fe2c: f887 003c strb.w r0, [r7, #60] ; 0x3c +1001fe30: aa01 add r2, sp, #4 +1001fe32: f89d 0004 ldrb.w r0, [sp, #4] +1001fe36: 7238 strb r0, [r7, #8] +1001fe38: 7065 strb r5, [r4, #1] +1001fe3a: 70a6 strb r6, [r4, #2] +1001fe3c: 2129 movs r1, #41 ; 0x29 +1001fe3e: 4640 mov r0, r8 +1001fe40: f7f7 fa66 bl 10017310 +1001fe44: e8bd 81f3 ldmia.w sp!, {r0, r1, r4, r5, r6, r7, r8, pc} + +1001fe48 : +1001fe48: b5f8 push {r3, r4, r5, r6, r7, lr} +1001fe4a: 4604 mov r4, r0 +1001fe4c: 2000 movs r0, #0 +1001fe4e: 460d mov r5, r1 +1001fe50: f88d 0000 strb.w r0, [sp] +1001fe54: 2600 movs r6, #0 +1001fe56: f7f0 fd9a bl 1001098e +1001fe5a: 4607 mov r7, r0 +1001fe5c: e002 b.n 1001fe64 +1001fe5e: 2064 movs r0, #100 ; 0x64 +1001fe60: f7f0 fdcc bl 100109fc +1001fe64: aa00 add r2, sp, #0 +1001fe66: 212c movs r1, #44 ; 0x2c +1001fe68: 4620 mov r0, r4 +1001fe6a: f7f7 fa5b bl 10017324 +1001fe6e: f89d 0000 ldrb.w r0, [sp] +1001fe72: 2801 cmp r0, #1 +1001fe74: d00e beq.n 1001fe94 +1001fe76: f504 50e5 add.w r0, r4, #7328 ; 0x1ca0 +1001fe7a: 6800 ldr r0, [r0, #0] +1001fe7c: 2801 cmp r0, #1 +1001fe7e: d102 bne.n 1001fe86 +1001fe80: f06f 0601 mvn.w r6, #1 +1001fe84: e006 b.n 1001fe94 +1001fe86: 4638 mov r0, r7 +1001fe88: f7f0 fda9 bl 100109de +1001fe8c: 4285 cmp r5, r0 +1001fe8e: d2e6 bcs.n 1001fe5e +1001fe90: f04f 36ff mov.w r6, #4294967295 +1001fe94: 4630 mov r0, r6 +1001fe96: bdf2 pop {r1, r4, r5, r6, r7, pc} + +1001fe98 : +1001fe98: b570 push {r4, r5, r6, lr} +1001fe9a: 4604 mov r4, r0 +1001fe9c: f504 55c8 add.w r5, r4, #6400 ; 0x1900 +1001fea0: 350c adds r5, #12 +1001fea2: f895 002c ldrb.w r0, [r5, #44] ; 0x2c +1001fea6: b318 cbz r0, 1001fef0 +1001fea8: f641 5648 movw r6, #7496 ; 0x1d48 +1001feac: 1930 adds r0, r6, r4 +1001feae: 7a40 ldrb r0, [r0, #9] +1001feb0: b9f0 cbnz r0, 1001fef0 +1001feb2: 4620 mov r0, r4 +1001feb4: f7ff ff52 bl 1001fd5c +1001feb8: b1d0 cbz r0, 1001fef0 +1001feba: 5930 ldr r0, [r6, r4] +1001febc: b110 cbz r0, 1001fec4 +1001febe: f7ff ff4d bl 1001fd5c +1001fec2: b1a8 cbz r0, 1001fef0 +1001fec4: f105 002c add.w r0, r5, #44 ; 0x2c +1001fec8: 7b41 ldrb r1, [r0, #13] +1001feca: b189 cbz r1, 1001fef0 +1001fecc: 7b81 ldrb r1, [r0, #14] +1001fece: 2902 cmp r1, #2 +1001fed0: db0c blt.n 1001feec +1001fed2: 7a29 ldrb r1, [r5, #8] +1001fed4: b961 cbnz r1, 1001fef0 +1001fed6: 2101 movs r1, #1 +1001fed8: 7429 strb r1, [r5, #16] +1001feda: 2300 movs r3, #0 +1001fedc: f641 01bb movw r1, #6331 ; 0x18bb +1001fee0: 5d0a ldrb r2, [r1, r4] +1001fee2: 7bc1 ldrb r1, [r0, #15] +1001fee4: 4620 mov r0, r4 +1001fee6: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +1001feea: e778 b.n 1001fdde +1001feec: 1c49 adds r1, r1, #1 +1001feee: 7381 strb r1, [r0, #14] +1001fef0: bd70 pop {r4, r5, r6, pc} + +1001fef2 : +1001fef2: b538 push {r3, r4, r5, lr} +1001fef4: f000 f876 bl 1001ffe4 <.text_21> +1001fef8: b990 cbnz r0, 1001ff20 +1001fefa: f895 0039 ldrb.w r0, [r5, #57] ; 0x39 +1001fefe: 2800 cmp r0, #0 +1001ff00: bf1c itt ne +1001ff02: 7a28 ldrbne r0, [r5, #8] +1001ff04: 2800 cmpne r0, #0 +1001ff06: d009 beq.n 1001ff1c +1001ff08: 2200 movs r2, #0 +1001ff0a: 2300 movs r3, #0 +1001ff0c: 4611 mov r1, r2 +1001ff0e: 4620 mov r0, r4 +1001ff10: f7ff ff65 bl 1001fdde +1001ff14: 2164 movs r1, #100 ; 0x64 +1001ff16: 4620 mov r0, r4 +1001ff18: f7ff ff96 bl 1001fe48 +1001ff1c: 2000 movs r0, #0 +1001ff1e: 7428 strb r0, [r5, #16] +1001ff20: bd31 pop {r0, r4, r5, pc} + +1001ff22 : +1001ff22: b510 push {r4, lr} +1001ff24: 4604 mov r4, r0 +1001ff26: 2101 movs r1, #1 +1001ff28: f104 000c add.w r0, r4, #12 +1001ff2c: f7ff fde0 bl 1001faf0 +1001ff30: 2801 cmp r0, #1 +1001ff32: d106 bne.n 1001ff42 +1001ff34: 4620 mov r0, r4 +1001ff36: e8bd 4010 ldmia.w sp!, {r4, lr} +1001ff3a: 2200 movs r2, #0 +1001ff3c: 2105 movs r1, #5 +1001ff3e: f7f6 be3e b.w 10016bbe +1001ff42: bd10 pop {r4, pc} + +1001ff44 : +1001ff44: b5f8 push {r3, r4, r5, r6, r7, lr} +1001ff46: f000 f84d bl 1001ffe4 <.text_21> +1001ff4a: 2800 cmp r0, #0 +1001ff4c: d146 bne.n 1001ffdc +1001ff4e: 2101 movs r1, #1 +1001ff50: 4628 mov r0, r5 +1001ff52: f7f0 fc8e bl 10010872 +1001ff56: f105 015c add.w r1, r5, #92 ; 0x5c +1001ff5a: 2000 movs r0, #0 +1001ff5c: 60c8 str r0, [r1, #12] +1001ff5e: 2200 movs r2, #0 +1001ff60: 1d28 adds r0, r5, #4 +1001ff62: 2300 movs r3, #0 +1001ff64: 6202 str r2, [r0, #32] +1001ff66: 6242 str r2, [r0, #36] ; 0x24 +1001ff68: f641 06b8 movw r6, #6328 ; 0x18b8 +1001ff6c: f105 022c add.w r2, r5, #44 ; 0x2c +1001ff70: 6053 str r3, [r2, #4] +1001ff72: 1933 adds r3, r6, r4 +1001ff74: 789f ldrb r7, [r3, #2] +1001ff76: 7057 strb r7, [r2, #1] +1001ff78: 789f ldrb r7, [r3, #2] +1001ff7a: 7097 strb r7, [r2, #2] +1001ff7c: 785f ldrb r7, [r3, #1] +1001ff7e: f885 702c strb.w r7, [r5, #44] ; 0x2c +1001ff82: f44f 67fa mov.w r7, #2000 ; 0x7d0 +1001ff86: 65ef str r7, [r5, #92] ; 0x5c +1001ff88: 2700 movs r7, #0 +1001ff8a: 710f strb r7, [r1, #4] +1001ff8c: f885 704d strb.w r7, [r5, #77] ; 0x4d +1001ff90: f885 704e strb.w r7, [r5, #78] ; 0x4e +1001ff94: 75cf strb r7, [r1, #23] +1001ff96: 7397 strb r7, [r2, #14] +1001ff98: 7a59 ldrb r1, [r3, #9] +1001ff9a: 2901 cmp r1, #1 +1001ff9c: d102 bne.n 1001ffa4 +1001ff9e: 2100 movs r1, #0 +1001ffa0: 73d1 strb r1, [r2, #15] +1001ffa2: e004 b.n 1001ffae +1001ffa4: 5d36 ldrb r6, [r6, r4] +1001ffa6: 73d6 strb r6, [r2, #15] +1001ffa8: 0031 movs r1, r6 +1001ffaa: bf18 it ne +1001ffac: 2101 movne r1, #1 +1001ffae: 7351 strb r1, [r2, #13] +1001ffb0: 7417 strb r7, [r2, #16] +1001ffb2: 712f strb r7, [r5, #4] +1001ffb4: 210c movs r1, #12 +1001ffb6: 7041 strb r1, [r0, #1] +1001ffb8: 7107 strb r7, [r0, #4] +1001ffba: 78d9 ldrb r1, [r3, #3] +1001ffbc: 4a08 ldr r2, [pc, #32] ; (1001ffe0 <.text_20>) +1001ffbe: 7141 strb r1, [r0, #5] +1001ffc0: 7187 strb r7, [r0, #6] +1001ffc2: 2180 movs r1, #128 ; 0x80 +1001ffc4: 7081 strb r1, [r0, #2] +1001ffc6: 4623 mov r3, r4 +1001ffc8: f20f 108c addw r0, pc, #396 ; 0x18c +1001ffcc: 9000 str r0, [sp, #0] +1001ffce: f641 5024 movw r0, #7460 ; 0x1d24 +1001ffd2: 5901 ldr r1, [r0, r4] +1001ffd4: f105 0050 add.w r0, r5, #80 ; 0x50 +1001ffd8: f7f0 fd25 bl 10010a26 +1001ffdc: bdf1 pop {r0, r4, r5, r6, r7, pc} + ... + +1001ffe0 <.text_20>: +1001ffe0: 1001fd59 .word 0x1001fd59 + +1001ffe4 <.text_21>: +1001ffe4: 4604 mov r4, r0 +1001ffe6: f641 5051 movw r0, #7505 ; 0x1d51 +1001ffea: f504 55c8 add.w r5, r4, #6400 ; 0x1900 +1001ffee: 5d00 ldrb r0, [r0, r4] +1001fff0: 350c adds r5, #12 +1001fff2: 4770 bx lr + +1001fff4 : +1001fff4: f641 5151 movw r1, #7505 ; 0x1d51 +1001fff8: 5c09 ldrb r1, [r1, r0] +1001fffa: b921 cbnz r1, 10020006 +1001fffc: f500 50c8 add.w r0, r0, #6400 ; 0x1900 +10020000: 300c adds r0, #12 +10020002: f7f0 bc3d b.w 10010880 +10020006: 4770 bx lr + +10020008 <_rtw_pwr_wakeup>: +10020008: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +1002000c: 4688 mov r8, r1 +1002000e: 4604 mov r4, r0 +10020010: f641 5148 movw r1, #7496 ; 0x1d48 +10020014: 190a adds r2, r1, r4 +10020016: f641 100c movw r0, #6412 ; 0x190c +1002001a: 7a12 ldrb r2, [r2, #8] +1002001c: 1906 adds r6, r0, r4 +1002001e: f104 090c add.w r9, r4, #12 +10020022: 2501 movs r5, #1 +10020024: b92a cbnz r2, 10020032 <_rtw_pwr_wakeup+0x2a> +10020026: 5909 ldr r1, [r1, r4] +10020028: b119 cbz r1, 10020032 <_rtw_pwr_wakeup+0x2a> +1002002a: 460c mov r4, r1 +1002002c: 1906 adds r6, r0, r4 +1002002e: f104 090c add.w r9, r4, #12 +10020032: f7f0 fcac bl 1001098e +10020036: 4607 mov r7, r0 +10020038: 4640 mov r0, r8 +1002003a: f7f0 fcc0 bl 100109be +1002003e: 19c0 adds r0, r0, r7 +10020040: 6370 str r0, [r6, #52] ; 0x34 +10020042: f7f0 fca4 bl 1001098e +10020046: f106 0734 add.w r7, r6, #52 ; 0x34 +1002004a: 4682 mov sl, r0 +1002004c: 7938 ldrb r0, [r7, #4] +1002004e: b918 cbnz r0, 10020058 <_rtw_pwr_wakeup+0x50> +10020050: e00b b.n 1002006a <_rtw_pwr_wakeup+0x62> +10020052: 200a movs r0, #10 +10020054: f7f0 fccb bl 100109ee +10020058: 7938 ldrb r0, [r7, #4] +1002005a: b130 cbz r0, 1002006a <_rtw_pwr_wakeup+0x62> +1002005c: 4650 mov r0, sl +1002005e: f7f0 fcbe bl 100109de +10020062: f640 31b9 movw r1, #3001 ; 0xbb9 +10020066: 4288 cmp r0, r1 +10020068: dbf3 blt.n 10020052 <_rtw_pwr_wakeup+0x4a> +1002006a: 7e78 ldrb r0, [r7, #25] +1002006c: f641 5a28 movw sl, #7464 ; 0x1d28 +10020070: b918 cbnz r0, 1002007a <_rtw_pwr_wakeup+0x72> +10020072: 7eb8 ldrb r0, [r7, #26] +10020074: 2801 cmp r0, #1 +10020076: d107 bne.n 10020088 <_rtw_pwr_wakeup+0x80> +10020078: e01f b.n 100200ba <_rtw_pwr_wakeup+0xb2> +1002007a: 2801 cmp r0, #1 +1002007c: bf02 ittt eq +1002007e: eb0a 0004 addeq.w r0, sl, r4 +10020082: 7f00 ldrbeq r0, [r0, #28] +10020084: 2801 cmpeq r0, #1 +10020086: d018 beq.n 100200ba <_rtw_pwr_wakeup+0xb2> +10020088: 2101 movs r1, #1 +1002008a: 4648 mov r0, r9 +1002008c: f7ff fd30 bl 1001faf0 +10020090: 2801 cmp r0, #1 +10020092: d013 beq.n 100200bc <_rtw_pwr_wakeup+0xb4> +10020094: 6b78 ldr r0, [r7, #52] ; 0x34 +10020096: 2802 cmp r0, #2 +10020098: d103 bne.n 100200a2 <_rtw_pwr_wakeup+0x9a> +1002009a: 4620 mov r0, r4 +1002009c: f7ff fd74 bl 1001fb88 +100200a0: b158 cbz r0, 100200ba <_rtw_pwr_wakeup+0xb2> +100200a2: f641 409c movw r0, #7324 ; 0x1c9c +100200a6: 5901 ldr r1, [r0, r4] +100200a8: b939 cbnz r1, 100200ba <_rtw_pwr_wakeup+0xb2> +100200aa: f85a 1004 ldr.w r1, [sl, r4] +100200ae: 2900 cmp r1, #0 +100200b0: bf1e ittt ne +100200b2: 1900 addne r0, r0, r4 +100200b4: 7e40 ldrbne r0, [r0, #25] +100200b6: 2800 cmpne r0, #0 +100200b8: d100 bne.n 100200bc <_rtw_pwr_wakeup+0xb4> +100200ba: 2500 movs r5, #0 +100200bc: f7f0 fc67 bl 1001098e +100200c0: 4604 mov r4, r0 +100200c2: 4640 mov r0, r8 +100200c4: f7f0 fc7b bl 100109be +100200c8: 1900 adds r0, r0, r4 +100200ca: 6370 str r0, [r6, #52] ; 0x34 +100200cc: 4628 mov r0, r5 +100200ce: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + +100200d2 : +100200d2: b570 push {r4, r5, r6, lr} +100200d4: 460d mov r5, r1 +100200d6: f500 51c8 add.w r1, r0, #6400 ; 0x1900 +100200da: 310c adds r1, #12 +100200dc: 2400 movs r4, #0 +100200de: f891 202c ldrb.w r2, [r1, #44] ; 0x2c +100200e2: b912 cbnz r2, 100200ea +100200e4: b10d cbz r5, 100200ea +100200e6: 2000 movs r0, #0 +100200e8: bd70 pop {r4, r5, r6, pc} +100200ea: 2d0b cmp r5, #11 +100200ec: da10 bge.n 10020110 +100200ee: f101 062c add.w r6, r1, #44 ; 0x2c +100200f2: 7bf1 ldrb r1, [r6, #15] +100200f4: 42a9 cmp r1, r5 +100200f6: d00d beq.n 10020114 +100200f8: b915 cbnz r5, 10020100 +100200fa: f7ff ff12 bl 1001ff22 +100200fe: e001 b.n 10020104 +10020100: 2002 movs r0, #2 +10020102: 73b0 strb r0, [r6, #14] +10020104: 0028 movs r0, r5 +10020106: 73f5 strb r5, [r6, #15] +10020108: bf18 it ne +1002010a: 2001 movne r0, #1 +1002010c: 7370 strb r0, [r6, #13] +1002010e: e001 b.n 10020114 +10020110: f06f 0415 mvn.w r4, #21 +10020114: 4620 mov r0, r4 +10020116: bd70 pop {r4, r5, r6, pc} + +10020118 : +10020118: b580 push {r7, lr} +1002011a: f500 52c8 add.w r2, r0, #6400 ; 0x1900 +1002011e: 320c adds r2, #12 +10020120: f892 302c ldrb.w r3, [r2, #44] ; 0x2c +10020124: b903 cbnz r3, 10020128 +10020126: b989 cbnz r1, 1002014c +10020128: 322c adds r2, #44 ; 0x2c +1002012a: 2901 cmp r1, #1 +1002012c: bf14 ite ne +1002012e: 2902 cmpne r1, #2 +10020130: 7091 strbeq r1, [r2, #2] +10020132: d00b beq.n 1002014c +10020134: b961 cbnz r1, 10020150 +10020136: 7091 strb r1, [r2, #2] +10020138: f44f 61fa mov.w r1, #2000 ; 0x7d0 +1002013c: f20f 022c addw r2, pc, #44 ; 0x2c +10020140: f7ff ff62 bl 10020008 <_rtw_pwr_wakeup> +10020144: b910 cbnz r0, 1002014c +10020146: f06f 000d mvn.w r0, #13 +1002014a: bd02 pop {r1, pc} +1002014c: 2000 movs r0, #0 +1002014e: bd02 pop {r1, pc} +10020150: f06f 0015 mvn.w r0, #21 +10020154: bd02 pop {r1, pc} + ... + +10020158 : +10020158: 7750 5372 6174 6574 6843 6365 546b 6d69 PwrStateCheckTim +10020168: 7265 0000 er.. + +1002016c : +1002016c: 7472 5f77 6d70 735f 7465 695f 7370 0000 rtw_pm_set_ips.. + +1002017c : +1002017c: b570 push {r4, r5, r6, lr} +1002017e: b0c0 sub sp, #256 ; 0x100 +10020180: 4606 mov r6, r0 +10020182: 460c mov r4, r1 +10020184: 2500 movs r5, #0 +10020186: f7f1 ffc4 bl 10012112 +1002018a: b2c0 uxtb r0, r0 +1002018c: f7ef ff17 bl 1000ffbe +10020190: b910 cbnz r0, 10020198 +10020192: f06f 000e mvn.w r0, #14 +10020196: e01c b.n 100201d2 + +10020198 : +10020198: 4620 mov r0, r4 +1002019a: e009 b.n 100201b0 + +1002019c : +1002019c: 6841 ldr r1, [r0, #4] +1002019e: aa00 add r2, sp, #0 +100201a0: f842 1035 str.w r1, [r2, r5, lsl #3] +100201a4: eb02 02c5 add.w r2, r2, r5, lsl #3 +100201a8: 8941 ldrh r1, [r0, #10] +100201aa: 6051 str r1, [r2, #4] +100201ac: 1c6d adds r5, r5, #1 +100201ae: 6800 ldr r0, [r0, #0] + +100201b0 : +100201b0: b108 cbz r0, 100201b6 +100201b2: 2d20 cmp r5, #32 +100201b4: dbf2 blt.n 1002019c + +100201b6 : +100201b6: b15d cbz r5, 100201d0 +100201b8: 4630 mov r0, r6 +100201ba: f7f1 ffaa bl 10012112 +100201be: 8923 ldrh r3, [r4, #8] +100201c0: 462a mov r2, r5 +100201c2: a900 add r1, sp, #0 +100201c4: f7f1 ff0e bl 10011fe4 +100201c8: b118 cbz r0, 100201d2 +100201ca: f06f 0001 mvn.w r0, #1 +100201ce: e000 b.n 100201d2 + +100201d0 : +100201d0: 2000 movs r0, #0 + +100201d2 : +100201d2: b040 add sp, #256 ; 0x100 +100201d4: bd70 pop {r4, r5, r6, pc} + +100201d6 : +100201d6: b570 push {r4, r5, r6, lr} +100201d8: b0c0 sub sp, #256 ; 0x100 +100201da: 4604 mov r4, r0 +100201dc: 460e mov r6, r1 +100201de: 2500 movs r5, #0 +100201e0: f7f1 ff97 bl 10012112 +100201e4: b2c0 uxtb r0, r0 +100201e6: f7ef feea bl 1000ffbe +100201ea: b368 cbz r0, 10020248 +100201ec: f240 6005 movw r0, #1541 ; 0x605 +100201f0: 4286 cmp r6, r0 +100201f2: bf28 it cs +100201f4: f240 6604 movwcs r6, #1540 ; 0x604 +100201f8: 2203 movs r2, #3 +100201fa: b2b1 uxth r1, r6 +100201fc: 2003 movs r0, #3 +100201fe: f7e8 f9e3 bl 100085c8 +10020202: 0006 movs r6, r0 +10020204: d104 bne.n 10020210 +10020206: f20f 009c addw r0, pc, #156 ; 0x9c +1002020a: f7ec f87a bl 1000c302 +1002020e: e01b b.n 10020248 + +10020210 : +10020210: 6841 ldr r1, [r0, #4] +10020212: aa00 add r2, sp, #0 +10020214: f842 1035 str.w r1, [r2, r5, lsl #3] +10020218: eb02 02c5 add.w r2, r2, r5, lsl #3 +1002021c: 8941 ldrh r1, [r0, #10] +1002021e: 6051 str r1, [r2, #4] +10020220: 1c6d adds r5, r5, #1 +10020222: 6800 ldr r0, [r0, #0] +10020224: b108 cbz r0, 1002022a +10020226: 2d20 cmp r5, #32 +10020228: dbf2 blt.n 10020210 + +1002022a : +1002022a: 4620 mov r0, r4 +1002022c: f7f1 ff71 bl 10012112 +10020230: 462a mov r2, r5 +10020232: a900 add r1, sp, #0 +10020234: f7f1 ff28 bl 10012088 +10020238: 6922 ldr r2, [r4, #16] +1002023a: 4621 mov r1, r4 +1002023c: 4630 mov r0, r6 +1002023e: 4790 blx r2 +10020240: b110 cbz r0, 10020248 +10020242: 4630 mov r0, r6 +10020244: f7e8 fad0 bl 100087e8 + +10020248 : +10020248: b040 add sp, #256 ; 0x100 +1002024a: bd70 pop {r4, r5, r6, pc} + +1002024c : +1002024c: 4911 ldr r1, [pc, #68] ; (10020294 ) +1002024e: 6141 str r1, [r0, #20] +10020250: 3014 adds r0, #20 +10020252: 4911 ldr r1, [pc, #68] ; (10020298 ) +10020254: 6041 str r1, [r0, #4] +10020256: 2106 movs r1, #6 +10020258: 7581 strb r1, [r0, #22] +1002025a: f240 51dc movw r1, #1500 ; 0x5dc +1002025e: 8281 strh r1, [r0, #20] +10020260: 2122 movs r1, #34 ; 0x22 +10020262: 7741 strb r1, [r0, #29] +10020264: 2000 movs r0, #0 +10020266: 4770 bx lr + +10020268 : +10020268: b580 push {r7, lr} +1002026a: f7eb f9d3 bl 1000b614 +1002026e: e8bd 4008 ldmia.w sp!, {r3, lr} +10020272: 2200 movs r2, #0 +10020274: 4909 ldr r1, [pc, #36] ; (1002029c ) +10020276: f241 3088 movw r0, #5000 ; 0x1388 +1002027a: f7eb b925 b.w 1000b4c8 + +1002027e : +1002027e: 4808 ldr r0, [pc, #32] ; (100202a0 ) +10020280: 6800 ldr r0, [r0, #0] +10020282: b128 cbz r0, 10020290 +10020284: 4905 ldr r1, [pc, #20] ; (1002029c ) +10020286: 2200 movs r2, #0 +10020288: f241 3088 movw r0, #5000 ; 0x1388 +1002028c: f7e8 b901 b.w 10008492 + +10020290 : +10020290: 4770 bx lr + ... + +10020294 : +10020294: b943 1000 C... + +10020298 : +10020298: 017d 1002 }... + +1002029c : +1002029c: 0269 1002 i... + +100202a0 : +100202a0: 739c 1004 .s.. + +100202a4 : +100202a4: 0d0a 6143 6e6e 746f 6120 6c6c 636f 7461 ..Cannot allocat +100202b4: 2065 6270 6675 7420 206f 6572 6563 7669 e pbuf to receiv +100202c4: 2065 6170 6b63 7465 0000 0000 e packet.... + +100202d0 : +100202d0: f8df f000 ldr.w pc, [pc] ; 100202d4 +100202d4: 0000418d .word 0x0000418d + +100202d8 : +100202d8: f8df f000 ldr.w pc, [pc] ; 100202dc +100202dc: 00004091 .word 0x00004091 + +100202e0 : +100202e0: f8df f000 ldr.w pc, [pc] ; 100202e4 +100202e4: 0000f069 .word 0x0000f069 + +100202e8 : +100202e8: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +100202ec: 48b2 ldr r0, [pc, #712] ; (100205b8 ) +100202ee: 6804 ldr r4, [r0, #0] +100202f0: 48b2 ldr r0, [pc, #712] ; (100205bc ) +100202f2: 7800 ldrb r0, [r0, #0] +100202f4: 0700 lsls r0, r0, #28 +100202f6: d506 bpl.n 10020306 +100202f8: 4622 mov r2, r4 +100202fa: f20f 21ec addw r1, pc, #748 ; 0x2ec +100202fe: f20f 3004 addw r0, pc, #772 ; 0x304 +10020302: f7e3 fe9d bl 10004040 + +10020306 : +10020306: 4eae ldr r6, [pc, #696] ; (100205c0 ) +10020308: f8df 82b8 ldr.w r8, [pc, #696] ; 100205c4 +1002030c: 2502 movs r5, #2 + +1002030e : +1002030e: fa24 f005 lsr.w r0, r4, r5 +10020312: 07c0 lsls r0, r0, #31 +10020314: d513 bpl.n 1002033e +10020316: 2014 movs r0, #20 +10020318: fb00 f705 mul.w r7, r0, r5 +1002031c: 48aa ldr r0, [pc, #680] ; (100205c8 ) +1002031e: 59c0 ldr r0, [r0, r7] +10020320: 07c0 lsls r0, r0, #31 +10020322: d50c bpl.n 1002033e +10020324: eb08 0085 add.w r0, r8, r5, lsl #2 +10020328: f850 1c08 ldr.w r1, [r0, #-8] +1002032c: 0008 movs r0, r1 +1002032e: d004 beq.n 1002033a +10020330: eb06 0085 add.w r0, r6, r5, lsl #2 +10020334: f850 0c08 ldr.w r0, [r0, #-8] +10020338: 4788 blx r1 + +1002033a : +1002033a: 48a4 ldr r0, [pc, #656] ; (100205cc ) +1002033c: 59c0 ldr r0, [r0, r7] + +1002033e : +1002033e: 1c6d adds r5, r5, #1 +10020340: 2d08 cmp r5, #8 +10020342: d3e4 bcc.n 1002030e +10020344: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +10020348 : +10020348: b500 push {lr} +1002034a: b085 sub sp, #20 +1002034c: 7f01 ldrb r1, [r0, #28] +1002034e: 460a mov r2, r1 +10020350: 2a08 cmp r2, #8 +10020352: db0b blt.n 1002036c +10020354: 489e ldr r0, [pc, #632] ; (100205d0 ) +10020356: 7800 ldrb r0, [r0, #0] +10020358: 0700 lsls r0, r0, #28 +1002035a: d505 bpl.n 10020368 +1002035c: f20f 21c8 addw r1, pc, #712 ; 0x2c8 +10020360: f20f 20e8 addw r0, pc, #744 ; 0x2e8 +10020364: f7e3 fe6c bl 10004040 + +10020368 : +10020368: 2003 movs r0, #3 +1002036a: e020 b.n 100203ae + +1002036c : +1002036c: 2a02 cmp r2, #2 +1002036e: db12 blt.n 10020396 +10020370: 2105 movs r1, #5 +10020372: 9101 str r1, [sp, #4] +10020374: 4997 ldr r1, [pc, #604] ; (100205d4 ) +10020376: 9100 str r1, [sp, #0] +10020378: 7f02 ldrb r2, [r0, #28] +1002037a: 4992 ldr r1, [pc, #584] ; (100205c4 ) +1002037c: eb01 0182 add.w r1, r1, r2, lsl #2 +10020380: 68c2 ldr r2, [r0, #12] +10020382: f841 2c08 str.w r2, [r1, #-8] +10020386: 498e ldr r1, [pc, #568] ; (100205c0 ) +10020388: 7f02 ldrb r2, [r0, #28] +1002038a: eb01 0182 add.w r1, r1, r2, lsl #2 +1002038e: 6942 ldr r2, [r0, #20] +10020390: f841 2c08 str.w r2, [r1, #-8] +10020394: e006 b.n 100203a4 + +10020396 : +10020396: 2900 cmp r1, #0 +10020398: bf14 ite ne +1002039a: 2103 movne r1, #3 +1002039c: 2102 moveq r1, #2 +1002039e: 9101 str r1, [sp, #4] +100203a0: 68c1 ldr r1, [r0, #12] +100203a2: 9100 str r1, [sp, #0] + +100203a4 : +100203a4: 9002 str r0, [sp, #8] +100203a6: a800 add r0, sp, #0 +100203a8: f7e6 fc42 bl 10006c30 +100203ac: 2000 movs r0, #0 + +100203ae : +100203ae: b005 add sp, #20 +100203b0: bd00 pop {pc} + +100203b2 : +100203b2: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +100203b6: 4604 mov r4, r0 +100203b8: 4e87 ldr r6, [pc, #540] ; (100205d8 ) +100203ba: 7f22 ldrb r2, [r4, #28] +100203bc: 6830 ldr r0, [r6, #0] +100203be: 2500 movs r5, #0 +100203c0: 40d0 lsrs r0, r2 +100203c2: f20f 28b4 addw r8, pc, #692 ; 0x2b4 +100203c6: 4f82 ldr r7, [pc, #520] ; (100205d0 ) +100203c8: 07c0 lsls r0, r0, #31 +100203ca: d509 bpl.n 100203e0 +100203cc: 7838 ldrb r0, [r7, #0] +100203ce: 0700 lsls r0, r0, #28 +100203d0: d504 bpl.n 100203dc +100203d2: 4641 mov r1, r8 +100203d4: f20f 20bc addw r0, pc, #700 ; 0x2bc +100203d8: f7e3 fe32 bl 10004040 + +100203dc : +100203dc: 2001 movs r0, #1 +100203de: e047 b.n 10020470 + +100203e0 : +100203e0: 7f61 ldrb r1, [r4, #29] +100203e2: 68a0 ldr r0, [r4, #8] +100203e4: 0089 lsls r1, r1, #2 +100203e6: ea41 0940 orr.w r9, r1, r0, lsl #1 +100203ea: b1a0 cbz r0, 10020416 +100203ec: 6820 ldr r0, [r4, #0] +100203ee: 0080 lsls r0, r0, #2 +100203f0: 287d cmp r0, #125 ; 0x7d +100203f2: d209 bcs.n 10020408 +100203f4: 4879 ldr r0, [pc, #484] ; (100205dc ) +100203f6: 7800 ldrb r0, [r0, #0] +100203f8: 0700 lsls r0, r0, #28 +100203fa: d50a bpl.n 10020412 +100203fc: 4641 mov r1, r8 +100203fe: f20f 20c4 addw r0, pc, #708 ; 0x2c4 +10020402: f7e3 fe1d bl 10004040 +10020406: e004 b.n 10020412 + +10020408 : +10020408: 383e subs r0, #62 ; 0x3e +1002040a: 217d movs r1, #125 ; 0x7d +1002040c: fbb0 f0f1 udiv r0, r0, r1 +10020410: b918 cbnz r0, 1002041a + +10020412 : +10020412: 2001 movs r0, #1 +10020414: e001 b.n 1002041a + +10020416 : +10020416: f04f 30ff mov.w r0, #4294967295 + +1002041a : +1002041a: 7f22 ldrb r2, [r4, #28] +1002041c: 4b6a ldr r3, [pc, #424] ; (100205c8 ) +1002041e: 2114 movs r1, #20 +10020420: fb01 3202 mla r2, r1, r2, r3 +10020424: 4b6e ldr r3, [pc, #440] ; (100205e0 ) +10020426: f8c2 9000 str.w r9, [r2] +1002042a: 7f22 ldrb r2, [r4, #28] +1002042c: fb01 3102 mla r1, r1, r2, r3 +10020430: 6008 str r0, [r1, #0] +10020432: 7f60 ldrb r0, [r4, #29] +10020434: b9a0 cbnz r0, 10020460 +10020436: 68e0 ldr r0, [r4, #12] +10020438: b1e0 cbz r0, 10020474 +1002043a: 4620 mov r0, r4 +1002043c: f7ff ff84 bl 10020348 +10020440: 0005 movs r5, r0 +10020442: d009 beq.n 10020458 +10020444: 7838 ldrb r0, [r7, #0] +10020446: 0700 lsls r0, r0, #28 +10020448: d511 bpl.n 1002046e +1002044a: 7f22 ldrb r2, [r4, #28] +1002044c: f20f 209c addw r0, pc, #668 ; 0x29c +10020450: 4641 mov r1, r8 +10020452: f7e3 fdf5 bl 10004040 +10020456: e00a b.n 1002046e + +10020458 : +10020458: f104 000c add.w r0, r4, #12 +1002045c: f7e6 fbec bl 10006c38 + +10020460 : +10020460: f994 201c ldrsb.w r2, [r4, #28] +10020464: 6830 ldr r0, [r6, #0] +10020466: 2101 movs r1, #1 +10020468: 4091 lsls r1, r2 +1002046a: 4308 orrs r0, r1 +1002046c: 6030 str r0, [r6, #0] + +1002046e : +1002046e: 4628 mov r0, r5 + +10020470 : +10020470: e8bd 83f2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, pc} + +10020474 : +10020474: 7838 ldrb r0, [r7, #0] +10020476: 0700 lsls r0, r0, #28 +10020478: d505 bpl.n 10020486 +1002047a: 7f22 ldrb r2, [r4, #28] +1002047c: f20f 2098 addw r0, pc, #664 ; 0x298 +10020480: 4641 mov r1, r8 +10020482: f7e3 fddd bl 10004040 + +10020486 : +10020486: 2003 movs r0, #3 +10020488: e7f2 b.n 10020470 + +1002048a : +1002048a: b510 push {r4, lr} +1002048c: 7f01 ldrb r1, [r0, #28] +1002048e: f100 040c add.w r4, r0, #12 +10020492: 2908 cmp r1, #8 +10020494: db0b blt.n 100204ae +10020496: 484e ldr r0, [pc, #312] ; (100205d0 ) +10020498: 7800 ldrb r0, [r0, #0] +1002049a: 0700 lsls r0, r0, #28 +1002049c: d505 bpl.n 100204aa +1002049e: f20f 21a8 addw r1, pc, #680 ; 0x2a8 +100204a2: f20f 20c8 addw r0, pc, #712 ; 0x2c8 +100204a6: f7e3 fdcb bl 10004040 + +100204aa : +100204aa: 2003 movs r0, #3 +100204ac: bd10 pop {r4, pc} + +100204ae : +100204ae: 2902 cmp r1, #2 +100204b0: db15 blt.n 100204de +100204b2: 2105 movs r1, #5 +100204b4: 6061 str r1, [r4, #4] +100204b6: 2300 movs r3, #0 +100204b8: 7f02 ldrb r2, [r0, #28] +100204ba: 4942 ldr r1, [pc, #264] ; (100205c4 ) +100204bc: eb01 0282 add.w r2, r1, r2, lsl #2 +100204c0: f842 3c08 str.w r3, [r2, #-8] +100204c4: 2200 movs r2, #0 + +100204c6 : +100204c6: f851 3022 ldr.w r3, [r1, r2, lsl #2] +100204ca: b913 cbnz r3, 100204d2 +100204cc: 1c52 adds r2, r2, #1 +100204ce: 2a06 cmp r2, #6 +100204d0: d3f9 bcc.n 100204c6 + +100204d2 : +100204d2: 2a06 cmp r2, #6 +100204d4: d10b bne.n 100204ee +100204d6: 300c adds r0, #12 +100204d8: f7ff fefa bl 100202d0 +100204dc: e004 b.n 100204e8 + +100204de : +100204de: 2900 cmp r1, #0 +100204e0: bf14 ite ne +100204e2: 2003 movne r0, #3 +100204e4: 2002 moveq r0, #2 +100204e6: 6060 str r0, [r4, #4] + +100204e8 : +100204e8: 4620 mov r0, r4 +100204ea: f7ff fef5 bl 100202d8 + +100204ee : +100204ee: 2000 movs r0, #0 +100204f0: bd10 pop {r4, pc} + +100204f2 : +100204f2: b510 push {r4, lr} +100204f4: 4604 mov r4, r0 +100204f6: 7f20 ldrb r0, [r4, #28] +100204f8: f7ff fef2 bl 100202e0 +100204fc: 7f60 ldrb r0, [r4, #29] +100204fe: b920 cbnz r0, 1002050a +10020500: 68e0 ldr r0, [r4, #12] +10020502: b110 cbz r0, 1002050a +10020504: 4620 mov r0, r4 +10020506: f7ff ffc0 bl 1002048a + +1002050a : +1002050a: 4833 ldr r0, [pc, #204] ; (100205d8 ) +1002050c: f994 301c ldrsb.w r3, [r4, #28] +10020510: 6801 ldr r1, [r0, #0] +10020512: 2201 movs r2, #1 +10020514: 409a lsls r2, r3 +10020516: 4391 bics r1, r2 +10020518: 6001 str r1, [r0, #0] +1002051a: bd10 pop {r4, pc} + +1002051c : +1002051c: b538 push {r3, r4, r5, lr} +1002051e: 4604 mov r4, r0 +10020520: 0088 lsls r0, r1, #2 +10020522: 287d cmp r0, #125 ; 0x7d +10020524: d208 bcs.n 10020538 +10020526: 482d ldr r0, [pc, #180] ; (100205dc ) +10020528: 7800 ldrb r0, [r0, #0] +1002052a: 0700 lsls r0, r0, #28 +1002052c: d509 bpl.n 10020542 +1002052e: f20f 2088 addw r0, pc, #648 ; 0x288 +10020532: f7e3 fd85 bl 10004040 +10020536: e004 b.n 10020542 + +10020538 : +10020538: 383e subs r0, #62 ; 0x3e +1002053a: 217d movs r1, #125 ; 0x7d +1002053c: fbb0 f5f1 udiv r5, r0, r1 +10020540: b905 cbnz r5, 10020544 + +10020542 : +10020542: 2501 movs r5, #1 + +10020544 : +10020544: 481d ldr r0, [pc, #116] ; (100205bc ) +10020546: 7800 ldrb r0, [r0, #0] +10020548: 0700 lsls r0, r0, #28 +1002054a: d506 bpl.n 1002055a +1002054c: 462a mov r2, r5 +1002054e: f20f 2148 addw r1, pc, #584 ; 0x248 +10020552: f20f 20b0 addw r0, pc, #688 ; 0x2b0 +10020556: f7e3 fd73 bl 10004040 + +1002055a : +1002055a: 4921 ldr r1, [pc, #132] ; (100205e0 ) +1002055c: 2014 movs r0, #20 +1002055e: fb00 1004 mla r0, r0, r4, r1 +10020562: 6005 str r5, [r0, #0] +10020564: bd31 pop {r0, r4, r5, pc} + +10020566 : +10020566: 2114 movs r1, #20 +10020568: 4a1e ldr r2, [pc, #120] ; (100205e4 ) +1002056a: fb01 2100 mla r1, r1, r0, r2 +1002056e: 2202 movs r2, #2 +10020570: 6808 ldr r0, [r1, #0] + +10020572 : +10020572: 680b ldr r3, [r1, #0] +10020574: 4298 cmp r0, r3 +10020576: d002 beq.n 1002057e +10020578: 4618 mov r0, r3 +1002057a: 1e52 subs r2, r2, #1 +1002057c: d1f9 bne.n 10020572 + +1002057e : +1002057e: 4770 bx lr + +10020580 : +10020580: 2114 movs r1, #20 +10020582: 4a11 ldr r2, [pc, #68] ; (100205c8 ) +10020584: fb01 2000 mla r0, r1, r0, r2 +10020588: 6801 ldr r1, [r0, #0] +1002058a: f021 0104 bic.w r1, r1, #4 +1002058e: 6001 str r1, [r0, #0] +10020590: 4770 bx lr + +10020592 : +10020592: 2114 movs r1, #20 +10020594: 4a0c ldr r2, [pc, #48] ; (100205c8 ) +10020596: fb01 2000 mla r0, r1, r0, r2 +1002059a: 6801 ldr r1, [r0, #0] +1002059c: f041 0101 orr.w r1, r1, #1 +100205a0: 6001 str r1, [r0, #0] +100205a2: 4770 bx lr + +100205a4 : +100205a4: 2114 movs r1, #20 +100205a6: 4a08 ldr r2, [pc, #32] ; (100205c8 ) +100205a8: fb01 2000 mla r0, r1, r0, r2 +100205ac: 6801 ldr r1, [r0, #0] +100205ae: 0849 lsrs r1, r1, #1 +100205b0: 0049 lsls r1, r1, #1 +100205b2: 6001 str r1, [r0, #0] +100205b4: 4770 bx lr + ... + +100205b8 : +100205b8: 20a0 4000 . .@ + +100205bc : +100205bc: 0310 1000 .... + +100205c0 : +100205c0: 78e0 1004 .x.. + +100205c4 : +100205c4: 0358 1000 X... + +100205c8 : +100205c8: 2008 4000 . .@ + +100205cc : +100205cc: 200c 4000 . .@ + +100205d0 : +100205d0: 0314 1000 .... + +100205d4 : +100205d4: 02e9 1002 .... + +100205d8 : +100205d8: 034c 1000 L... + +100205dc : +100205dc: 030c 1000 .... + +100205e0 : +100205e0: 2000 4000 . .@ + +100205e4 : +100205e4: 2004 4000 . .@ + +100205e8 : +100205e8: 6148 546c 6d69 7265 7249 3271 6f54 4837 HalTimerIrq2To7H +100205f8: 6e61 6c64 5f65 6150 6374 0068 andle_Patch. + +10020604 : +10020604: 5b0d 4954 524d 4920 666e 255d 3a73 6954 .[TIMR Inf]%s:Ti +10020614: 656d 4972 7172 7453 7461 7375 203a 7830 merIrqStatus: 0x +10020624: 7825 000a %x.. + +10020628 : +10020628: 6148 546c 6d69 7265 7249 5271 6765 7369 HalTimerIrqRegis +10020638: 6574 5272 6c74 3138 3539 5f61 6150 6374 terRtl8195a_Patc +10020648: 0068 0000 h... + +1002064c : +1002064c: 5b0d 4954 524d 4520 7272 255d 3a73 4e20 .[TIMR Err]%s: N +1002065c: 206f 7553 7070 726f 2074 6954 656d 2072 o Support Timer +1002066c: 4449 2520 2164 0a0d 0000 0000 ID %d!...... + +10020678 : +10020678: 6148 546c 6d69 7265 6e49 7469 7452 386c HalTimerInitRtl8 +10020688: 3931 6135 505f 7461 6863 0000 195a_Patch.. + +10020694 : +10020694: 5b0d 4954 524d 4520 7272 255d 3a73 7245 .[TIMR Err]%s:Er +100206a4: 6f72 2172 5420 6d69 7265 2520 2064 7369 ror! Timer %d is +100206b4: 6f20 6363 7075 6569 2164 0a0d 0000 0000 occupied!...... + +100206c4 : +100206c4: 5b0d 4954 524d 5720 6e72 255d 2073 203a .[TIMR Wrn]%s : +100206d4: 6954 656d 2072 6f4c 6461 4320 756f 746e Timer Load Count +100206e4: 3d20 3120 0d21 000a = 1!... + +100206ec : +100206ec: 5b0d 4954 524d 4520 7272 255d 3a73 5420 .[TIMR Err]%s: T +100206fc: 6d69 7265 2520 2064 6552 6967 7473 7265 imer %d Register +1002070c: 4920 5152 4520 7272 0d21 000a IRQ Err!... + +10020718 : +10020718: 5b0d 4954 524d 4520 7272 255d 3a73 5420 .[TIMR Err]%s: T +10020728: 6d69 7265 2520 2064 5349 2052 6148 646e imer %d ISR Hand +10020738: 656c 2072 7369 4e20 4c55 214c 0a0d 0000 ler is NULL!.... + +10020748 : +10020748: 6148 546c 6d69 7265 7249 5571 526e 6765 HalTimerIrqUnReg +10020758: 7369 6574 5272 6c74 3138 3539 5f61 6150 isterRtl8195a_Pa +10020768: 6374 0068 tch. + +1002076c : +1002076c: 5b0d 4954 524d 4520 7272 255d 3a73 7245 .[TIMR Err]%s:Er +1002077c: 6f72 3a72 4e20 206f 7553 7070 726f 2074 ror: No Support +1002078c: 6954 656d 2072 4449 0a21 0000 Timer ID!... + +10020798 : +10020798: 6148 546c 6d69 7265 6552 6f4c 6461 7452 HalTimerReLoadRt +100207a8: 386c 3931 6135 505f 7461 6863 0000 0000 l8195a_Patch.... + +100207b8 : +100207b8: 5b0d 4954 524d 5720 6e72 485d 6c61 6954 .[TIMR Wrn]HalTi +100207c8: 656d 5272 4c65 616f 5264 6c74 3138 3539 merReLoadRtl8195 +100207d8: 2061 6157 6e72 6e69 2067 203a 6954 656d a Warning : Time +100207e8: 2072 6f4c 6461 4320 756f 746e 3d20 3120 r Load Count = 1 +100207f8: 2121 2121 2121 0a21 0000 0000 !!!!!!!..... + +10020804 : +10020804: 5b0d 4954 524d 4920 666e 255d 3a73 4c20 .[TIMR Inf]%s: L +10020814: 616f 2064 6f43 6e75 3d74 7830 7825 0a0d oad Count=0x%x.. +10020824: 0000 0000 .... + +10020828 : +10020828: 4907 ldr r1, [pc, #28] ; (10020848 ) +1002082a: 6001 str r1, [r0, #0] +1002082c: 4907 ldr r1, [pc, #28] ; (1002084c ) +1002082e: 6041 str r1, [r0, #4] +10020830: 4907 ldr r1, [pc, #28] ; (10020850 ) +10020832: 6081 str r1, [r0, #8] +10020834: 4907 ldr r1, [pc, #28] ; (10020854 ) +10020836: 60c1 str r1, [r0, #12] +10020838: 4907 ldr r1, [pc, #28] ; (10020858 ) +1002083a: 6101 str r1, [r0, #16] +1002083c: 4907 ldr r1, [pc, #28] ; (1002085c ) +1002083e: 6141 str r1, [r0, #20] +10020840: 4907 ldr r1, [pc, #28] ; (10020860 ) +10020842: 6181 str r1, [r0, #24] +10020844: 4770 bx lr +10020846: bf00 nop + +10020848 : +10020848: ef09 0000 03b3 1002 0567 1002 f0bd 0000 ........g....... +10020858: 05a5 1002 0593 1002 f0d1 0000 ............ + +10020864 : +10020864: 6840 ldr r0, [r0, #4] +10020866: 4208 tst r0, r1 +10020868: d001 beq.n 1002086e +1002086a: 2001 movs r0, #1 +1002086c: 4770 bx lr +1002086e: 2000 movs r0, #0 +10020870: 4770 bx lr + +10020872 : +10020872: b910 cbnz r0, 1002087a +10020874: f44f 61ca mov.w r1, #1616 ; 0x650 +10020878: e00d b.n 10020896 +1002087a: 2801 cmp r0, #1 +1002087c: bf08 it eq +1002087e: f44f 61cc moveq.w r1, #1632 ; 0x660 +10020882: d008 beq.n 10020896 +10020884: 2802 cmp r0, #2 +10020886: bf08 it eq +10020888: f44f 61ce moveq.w r1, #1648 ; 0x670 +1002088c: d003 beq.n 10020896 +1002088e: 2803 cmp r0, #3 +10020890: bf08 it eq +10020892: f44f 61d0 moveq.w r1, #1664 ; 0x680 +10020896: f8df 0370 ldr.w r0, [pc, #880] ; 10020c08 <.text_37> +1002089a: 6802 ldr r2, [r0, #0] +1002089c: 0b12 lsrs r2, r2, #12 +1002089e: ea41 3102 orr.w r1, r1, r2, lsl #12 +100208a2: 6001 str r1, [r0, #0] +100208a4: 2000 movs r0, #0 +100208a6: 4770 bx lr + +100208a8 : +100208a8: b538 push {r3, r4, r5, lr} +100208aa: f000 f806 bl 100208ba <.text_8> +100208ae: eb05 1004 add.w r0, r5, r4, lsl #4 +100208b2: f8df 1358 ldr.w r1, [pc, #856] ; 10020c0c <.text_38> +100208b6: 5c08 ldrb r0, [r1, r0] +100208b8: bd32 pop {r1, r4, r5, pc} + +100208ba <.text_8>: +100208ba: 4604 mov r4, r0 +100208bc: 460d mov r5, r1 +100208be: 2001 movs r0, #1 +100208c0: e7d7 b.n 10020872 + +100208c2 : +100208c2: b570 push {r4, r5, r6, lr} +100208c4: f000 f805 bl 100208d2 <.text_13> +100208c8: eb05 1004 add.w r0, r5, r4, lsl #4 +100208cc: f8df 133c ldr.w r1, [pc, #828] ; 10020c0c <.text_38> +100208d0: e012 b.n 100208f8 <.text_20> + +100208d2 <.text_13>: +100208d2: 4604 mov r4, r0 +100208d4: 460d mov r5, r1 +100208d6: 4616 mov r6, r2 +100208d8: 2001 movs r0, #1 +100208da: e7ca b.n 10020872 + +100208dc : +100208dc: b538 push {r3, r4, r5, lr} +100208de: f7ff ffec bl 100208ba <.text_8> +100208e2: eb05 00c4 add.w r0, r5, r4, lsl #3 +100208e6: 49ca ldr r1, [pc, #808] ; (10020c10 <.text_39>) +100208e8: 5c08 ldrb r0, [r1, r0] +100208ea: bd32 pop {r1, r4, r5, pc} + +100208ec : +100208ec: b570 push {r4, r5, r6, lr} +100208ee: f7ff fff0 bl 100208d2 <.text_13> +100208f2: eb05 00c4 add.w r0, r5, r4, lsl #3 +100208f6: 49c6 ldr r1, [pc, #792] ; (10020c10 <.text_39>) + +100208f8 <.text_20>: +100208f8: 540e strb r6, [r1, r0] +100208fa: 2000 movs r0, #0 +100208fc: bd70 pop {r4, r5, r6, pc} + +100208fe : +100208fe: b580 push {r7, lr} +10020900: f7ff ffec bl 100208dc +10020904: b2c0 uxtb r0, r0 +10020906: bd02 pop {r1, pc} + +10020908 : +10020908: e7f0 b.n 100208ec + +1002090a : +1002090a: b580 push {r7, lr} +1002090c: f7ff ffcc bl 100208a8 +10020910: b2c0 uxtb r0, r0 +10020912: bd02 pop {r1, pc} + +10020914 : +10020914: e7d5 b.n 100208c2 + +10020916 : +10020916: b510 push {r4, lr} +10020918: 460c mov r4, r1 +1002091a: b13a cbz r2, 1002092c +1002091c: 2100 movs r1, #0 +1002091e: 8381 strh r1, [r0, #28] +10020920: 83c1 strh r1, [r0, #30] +10020922: 8401 strh r1, [r0, #32] +10020924: 8441 strh r1, [r0, #34] ; 0x22 +10020926: 8481 strh r1, [r0, #36] ; 0x24 +10020928: 6281 str r1, [r0, #40] ; 0x28 +1002092a: 8581 strh r1, [r0, #44] ; 0x2c +1002092c: 2103 movs r1, #3 +1002092e: 4620 mov r0, r4 +10020930: f7ff ffeb bl 1002090a +10020934: f000 00bf and.w r0, r0, #191 ; 0xbf +10020938: f040 0280 orr.w r2, r0, #128 ; 0x80 +1002093c: e006 b.n 1002094c <.text_29> + +1002093e : +1002093e: b510 push {r4, lr} +10020940: 4604 mov r4, r0 +10020942: 2103 movs r1, #3 +10020944: f7ff ffe1 bl 1002090a +10020948: f040 0240 orr.w r2, r0, #64 ; 0x40 + +1002094c <.text_29>: +1002094c: 4620 mov r0, r4 +1002094e: e8bd 4010 ldmia.w sp!, {r4, lr} +10020952: 2103 movs r1, #3 +10020954: e7de b.n 10020914 + +10020956 : +10020956: b530 push {r4, r5, lr} +10020958: f641 31a4 movw r1, #7076 ; 0x1ba4 +1002095c: 5808 ldr r0, [r1, r0] +1002095e: 2110 movs r1, #16 +10020960: 1e49 subs r1, r1, #1 +10020962: b2c9 uxtb r1, r1 +10020964: 180b adds r3, r1, r0 +10020966: f642 1478 movw r4, #10616 ; 0x2978 +1002096a: 5ce3 ldrb r3, [r4, r3] +1002096c: b16b cbz r3, 1002098a +1002096e: 2408 movs r4, #8 +10020970: 1e64 subs r4, r4, #1 +10020972: b2e4 uxtb r4, r4 +10020974: 2501 movs r5, #1 +10020976: 40a5 lsls r5, r4 +10020978: 422b tst r3, r5 +1002097a: d004 beq.n 10020986 +1002097c: eb04 00c1 add.w r0, r4, r1, lsl #3 +10020980: 1c40 adds r0, r0, #1 +10020982: b2c0 uxtb r0, r0 +10020984: bd30 pop {r4, r5, pc} +10020986: 2c00 cmp r4, #0 +10020988: d1f2 bne.n 10020970 +1002098a: 2900 cmp r1, #0 +1002098c: d1e8 bne.n 10020960 +1002098e: 2000 movs r0, #0 +10020990: bd30 pop {r4, r5, pc} + +10020992 : +10020992: f641 32a4 movw r2, #7076 ; 0x1ba4 +10020996: 5810 ldr r0, [r2, r0] +10020998: eb00 00e1 add.w r0, r0, r1, asr #3 +1002099c: f642 1278 movw r2, #10616 ; 0x2978 +100209a0: f001 0107 and.w r1, r1, #7 +100209a4: 5c10 ldrb r0, [r2, r0] +100209a6: fa20 f201 lsr.w r2, r0, r1 +100209aa: 07d0 lsls r0, r2, #31 +100209ac: d501 bpl.n 100209b2 +100209ae: 2001 movs r0, #1 +100209b0: 4770 bx lr +100209b2: 2000 movs r0, #0 +100209b4: 4770 bx lr + +100209b6 : +100209b6: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +100209ba: 460c mov r4, r1 +100209bc: f104 061c add.w r6, r4, #28 +100209c0: 4690 mov r8, r2 +100209c2: 7ff0 ldrb r0, [r6, #31] +100209c4: f7ff ffbb bl 1002093e +100209c8: 2014 movs r0, #20 +100209ca: f7f0 f825 bl 10010a18 +100209ce: 7ff0 ldrb r0, [r6, #31] +100209d0: 2106 movs r1, #6 +100209d2: f7ff ff9a bl 1002090a +100209d6: 4607 mov r7, r0 +100209d8: 7ff0 ldrb r0, [r6, #31] +100209da: 2107 movs r1, #7 +100209dc: f7ff ff95 bl 1002090a +100209e0: ea47 2000 orr.w r0, r7, r0, lsl #8 +100209e4: 60f0 str r0, [r6, #12] +100209e6: 210a movs r1, #10 +100209e8: 7ff0 ldrb r0, [r6, #31] +100209ea: f7ff ff8e bl 1002090a +100209ee: 4607 mov r7, r0 +100209f0: 7ff0 ldrb r0, [r6, #31] +100209f2: 210b movs r1, #11 +100209f4: f7ff ff89 bl 1002090a +100209f8: ea47 2000 orr.w r0, r7, r0, lsl #8 +100209fc: 83a0 strh r0, [r4, #28] +100209fe: 2701 movs r7, #1 +10020a00: 2000 movs r0, #0 +10020a02: 62b0 str r0, [r6, #40] ; 0x28 +10020a04: f107 010b add.w r1, r7, #11 +10020a08: 7ff0 ldrb r0, [r6, #31] +10020a0a: eb04 0547 add.w r5, r4, r7, lsl #1 +10020a0e: b2c9 uxtb r1, r1 +10020a10: f7ff ff7b bl 1002090a +10020a14: 83a8 strh r0, [r5, #28] +10020a16: 8ba9 ldrh r1, [r5, #28] +10020a18: 6ab0 ldr r0, [r6, #40] ; 0x28 +10020a1a: fb01 0007 mla r0, r1, r7, r0 +10020a1e: 1c7f adds r7, r7, #1 +10020a20: 2f05 cmp r7, #5 +10020a22: 62b0 str r0, [r6, #40] ; 0x28 +10020a24: dbee blt.n 10020a04 +10020a26: 68f1 ldr r1, [r6, #12] +10020a28: 1808 adds r0, r1, r0 +10020a2a: 62b0 str r0, [r6, #40] ; 0x28 +10020a2c: 2109 movs r1, #9 +10020a2e: 7ff0 ldrb r0, [r6, #31] +10020a30: f7ff ff6b bl 1002090a +10020a34: 8230 strh r0, [r6, #16] +10020a36: 4642 mov r2, r8 +10020a38: 7ff1 ldrb r1, [r6, #31] +10020a3a: 4620 mov r0, r4 +10020a3c: e8bd 41f0 ldmia.w sp!, {r4, r5, r6, r7, r8, lr} +10020a40: e769 b.n 10020916 + +10020a42 : +10020a42: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +10020a46: 4606 mov r6, r0 +10020a48: f641 30a4 movw r0, #7076 ; 0x1ba4 +10020a4c: 2204 movs r2, #4 +10020a4e: 5987 ldr r7, [r0, r6] +10020a50: f507 54c8 add.w r4, r7, #6400 ; 0x1900 +10020a54: 34a8 adds r4, #168 ; 0xa8 +10020a56: f507 55c8 add.w r5, r7, #6400 ; 0x1900 +10020a5a: 354c adds r5, #76 ; 0x4c +10020a5c: 2100 movs r1, #0 +10020a5e: 4620 mov r0, r4 +10020a60: f7ef feea bl 10010838 +10020a64: 6026 str r6, [r4, #0] +10020a66: 2204 movs r2, #4 +10020a68: 2100 movs r1, #0 +10020a6a: f000 f84c bl 10020b06 <.text_34> +10020a6e: 8872 ldrh r2, [r6, #2] +10020a70: 2102 movs r1, #2 +10020a72: f000 f848 bl 10020b06 <.text_34> +10020a76: f897 204c ldrb.w r2, [r7, #76] ; 0x4c +10020a7a: 210a movs r1, #10 +10020a7c: f000 f843 bl 10020b06 <.text_34> +10020a80: f44f 5200 mov.w r2, #8192 ; 0x2000 +10020a84: 2104 movs r1, #4 +10020a86: f000 f83e bl 10020b06 <.text_34> +10020a8a: 4862 ldr r0, [pc, #392] ; (10020c14 <.text_40>) +10020a8c: f8d0 8000 ldr.w r8, [r0] +10020a90: 2200 movs r2, #0 +10020a92: 2106 movs r1, #6 +10020a94: f000 f837 bl 10020b06 <.text_34> +10020a98: f3c8 1203 ubfx r2, r8, #4, #4 +10020a9c: 2105 movs r1, #5 +10020a9e: f000 f832 bl 10020b06 <.text_34> +10020aa2: 6878 ldr r0, [r7, #4] +10020aa4: 2801 cmp r0, #1 +10020aa6: bf0c ite eq +10020aa8: 2201 moveq r2, #1 +10020aaa: 2200 movne r2, #0 +10020aac: 2103 movs r1, #3 +10020aae: f000 f82a bl 10020b06 <.text_34> +10020ab2: 2220 movs r2, #32 +10020ab4: 211b movs r1, #27 +10020ab6: f000 f826 bl 10020b06 <.text_34> +10020aba: 8cba ldrh r2, [r7, #36] ; 0x24 +10020abc: 2114 movs r1, #20 +10020abe: f000 f822 bl 10020b06 <.text_34> +10020ac2: f641 00d8 movw r0, #6360 ; 0x18d8 +10020ac6: 2116 movs r1, #22 +10020ac8: 5d82 ldrb r2, [r0, r6] +10020aca: f000 f81c bl 10020b06 <.text_34> +10020ace: f897 004b ldrb.w r0, [r7, #75] ; 0x4b +10020ad2: 2803 cmp r0, #3 +10020ad4: d101 bne.n 10020ada +10020ad6: 2200 movs r2, #0 +10020ad8: e005 b.n 10020ae6 +10020ada: 2802 cmp r0, #2 +10020adc: bf08 it eq +10020ade: 2202 moveq r2, #2 +10020ae0: d001 beq.n 10020ae6 +10020ae2: b928 cbnz r0, 10020af0 +10020ae4: 2201 movs r2, #1 +10020ae6: 2300 movs r3, #0 +10020ae8: 2107 movs r1, #7 +10020aea: 4620 mov r0, r4 +10020aec: f00f fb92 bl 10030214 +10020af0: f04f 60a0 mov.w r0, #83886080 ; 0x5000000 +10020af4: 6068 str r0, [r5, #4] +10020af6: 4602 mov r2, r0 +10020af8: 4620 mov r0, r4 +10020afa: e8bd 41f0 ldmia.w sp!, {r4, r5, r6, r7, r8, lr} +10020afe: 2300 movs r3, #0 +10020b00: 2101 movs r1, #1 +10020b02: f00f bb87 b.w 10030214 + +10020b06 <.text_34>: +10020b06: 4620 mov r0, r4 +10020b08: f00f bab3 b.w 10030072 + +10020b0c : +10020b0c: f641 1205 movw r2, #6405 ; 0x1905 +10020b10: 2100 movs r1, #0 +10020b12: 5c10 ldrb r0, [r2, r0] +10020b14: 2801 cmp r0, #1 +10020b16: bf08 it eq +10020b18: 2101 moveq r1, #1 +10020b1a: 4608 mov r0, r1 +10020b1c: 4770 bx lr + +10020b1e : +10020b1e: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +10020b22: 4604 mov r4, r0 +10020b24: f641 30a4 movw r0, #7076 ; 0x1ba4 +10020b28: f504 57c8 add.w r7, r4, #6400 ; 0x1900 +10020b2c: 5905 ldr r5, [r0, r4] +10020b2e: f505 50c8 add.w r0, r5, #6400 ; 0x1900 +10020b32: f100 09a8 add.w r9, r0, #168 ; 0xa8 +10020b36: f100 064c add.w r6, r0, #76 ; 0x4c +10020b3a: 4837 ldr r0, [pc, #220] ; (10020c18 <.text_41>) +10020b3c: 6070 str r0, [r6, #4] +10020b3e: f504 689d add.w r8, r4, #1256 ; 0x4e8 +10020b42: f104 0a0c add.w sl, r4, #12 +10020b46: 370c adds r7, #12 +10020b48: 4620 mov r0, r4 +10020b4a: f7ff ffdf bl 10020b0c +10020b4e: 2801 cmp r0, #1 +10020b50: d103 bne.n 10020b5a +10020b52: 6870 ldr r0, [r6, #4] +10020b54: f440 5000 orr.w r0, r0, #8192 ; 0x2000 +10020b58: 6070 str r0, [r6, #4] +10020b5a: 2300 movs r3, #0 +10020b5c: 6872 ldr r2, [r6, #4] +10020b5e: 2101 movs r1, #1 +10020b60: 4648 mov r0, r9 +10020b62: f00f fb57 bl 10030214 +10020b66: f604 1288 addw r2, r4, #2440 ; 0x988 +10020b6a: 211d movs r1, #29 +10020b6c: f000 f856 bl 10020c1c <.text_42> +10020b70: f504 6236 add.w r2, r4, #2912 ; 0xb60 +10020b74: 211e movs r1, #30 +10020b76: f000 f851 bl 10020c1c <.text_42> +10020b7a: f108 0211 add.w r2, r8, #17 +10020b7e: 211f movs r1, #31 +10020b80: f000 f84c bl 10020c1c <.text_42> +10020b84: f105 0245 add.w r2, r5, #69 ; 0x45 +10020b88: 2121 movs r1, #33 ; 0x21 +10020b8a: f000 f847 bl 10020c1c <.text_42> +10020b8e: f504 5288 add.w r2, r4, #4352 ; 0x1100 +10020b92: 32f4 adds r2, #244 ; 0xf4 +10020b94: 2122 movs r1, #34 ; 0x22 +10020b96: f000 f841 bl 10020c1c <.text_42> +10020b9a: f105 023c add.w r2, r5, #60 ; 0x3c +10020b9e: 2123 movs r1, #35 ; 0x23 +10020ba0: f000 f83c bl 10020c1c <.text_42> +10020ba4: f105 0244 add.w r2, r5, #68 ; 0x44 +10020ba8: 2124 movs r1, #36 ; 0x24 +10020baa: f000 f837 bl 10020c1c <.text_42> +10020bae: f504 52e8 add.w r2, r4, #7424 ; 0x1d00 +10020bb2: 3244 adds r2, #68 ; 0x44 +10020bb4: 2130 movs r1, #48 ; 0x30 +10020bb6: f000 f831 bl 10020c1c <.text_42> +10020bba: f504 52c0 add.w r2, r4, #6144 ; 0x1800 +10020bbe: 32c1 adds r2, #193 ; 0xc1 +10020bc0: 2131 movs r1, #49 ; 0x31 +10020bc2: f000 f82b bl 10020c1c <.text_42> +10020bc6: f105 0240 add.w r2, r5, #64 ; 0x40 +10020bca: 2120 movs r1, #32 +10020bcc: f000 f826 bl 10020c1c <.text_42> +10020bd0: f105 0226 add.w r2, r5, #38 ; 0x26 +10020bd4: 2125 movs r1, #37 ; 0x25 +10020bd6: f000 f821 bl 10020c1c <.text_42> +10020bda: f10a 0208 add.w r2, sl, #8 +10020bde: 2129 movs r1, #41 ; 0x29 +10020be0: f000 f81c bl 10020c1c <.text_42> +10020be4: f107 0210 add.w r2, r7, #16 +10020be8: 212a movs r1, #42 ; 0x2a +10020bea: f000 f817 bl 10020c1c <.text_42> +10020bee: 2400 movs r4, #0 +10020bf0: 2300 movs r3, #0 +10020bf2: b2a2 uxth r2, r4 +10020bf4: 2146 movs r1, #70 ; 0x46 +10020bf6: 4648 mov r0, r9 +10020bf8: f00f fb05 bl 10030206 +10020bfc: 1c64 adds r4, r4, #1 +10020bfe: 2c08 cmp r4, #8 +10020c00: dbf6 blt.n 10020bf0 +10020c02: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + ... + +10020c08 <.text_37>: +10020c08: 40080140 .word 0x40080140 + +10020c0c <.text_38>: +10020c0c: 40088100 .word 0x40088100 + +10020c10 <.text_39>: +10020c10: 40088900 .word 0x40088900 + +10020c14 <.text_40>: +10020c14: 400001f0 .word 0x400001f0 + +10020c18 <.text_41>: +10020c18: 051040bf .word 0x051040bf + +10020c1c <.text_42>: +10020c1c: 4648 mov r0, r9 +10020c1e: f00f baa7 b.w 10030170 + +10020c22 : +10020c22: b538 push {r3, r4, r5, lr} +10020c24: 4604 mov r4, r0 +10020c26: f641 30a4 movw r0, #7076 ; 0x1ba4 +10020c2a: 2101 movs r1, #1 +10020c2c: 5905 ldr r5, [r0, r4] +10020c2e: f505 50c8 add.w r0, r5, #6400 ; 0x1900 +10020c32: f800 1f4c strb.w r1, [r0, #76]! +10020c36: 2100 movs r1, #0 +10020c38: 7041 strb r1, [r0, #1] +10020c3a: 7081 strb r1, [r0, #2] +10020c3c: 4620 mov r0, r4 +10020c3e: f7ff ff6e bl 10020b1e +10020c42: f641 00c1 movw r0, #6337 ; 0x18c1 +10020c46: 5d00 ldrb r0, [r0, r4] +10020c48: b920 cbnz r0, 10020c54 +10020c4a: f505 50c8 add.w r0, r5, #6400 ; 0x1900 +10020c4e: 30a8 adds r0, #168 ; 0xa8 +10020c50: f00f f9ae bl 1002ffb0 +10020c54: f641 5164 movw r1, #7524 ; 0x1d64 +10020c58: 20ff movs r0, #255 ; 0xff +10020c5a: 5508 strb r0, [r1, r4] +10020c5c: bd31 pop {r0, r4, r5, pc} + +10020c5e : +10020c5e: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +10020c62: b083 sub sp, #12 +10020c64: 4604 mov r4, r0 +10020c66: 2001 movs r0, #1 +10020c68: f641 35a4 movw r5, #7076 ; 0x1ba4 +10020c6c: f88d 0004 strb.w r0, [sp, #4] +10020c70: f641 164c movw r6, #6476 ; 0x194c +10020c74: f855 9004 ldr.w r9, [r5, r4] +10020c78: f104 000c add.w r0, r4, #12 +10020c7c: 9000 str r0, [sp, #0] +10020c7e: f641 5848 movw r8, #7496 ; 0x1d48 +10020c82: f641 40b5 movw r0, #7349 ; 0x1cb5 +10020c86: 5d07 ldrb r7, [r0, r4] +10020c88: f858 b004 ldr.w fp, [r8, r4] +10020c8c: 2f00 cmp r7, #0 +10020c8e: eb06 0a09 add.w sl, r6, r9 +10020c92: d04c beq.n 10020d2e +10020c94: aa01 add r2, sp, #4 +10020c96: 212c movs r1, #44 ; 0x2c +10020c98: 4620 mov r0, r4 +10020c9a: f7f6 fb43 bl 10017324 +10020c9e: 2f01 cmp r7, #1 +10020ca0: d145 bne.n 10020d2e +10020ca2: 9800 ldr r0, [sp, #0] +10020ca4: 2700 movs r7, #0 +10020ca6: 2101 movs r1, #1 +10020ca8: f7ff fddc bl 10020864 +10020cac: 2801 cmp r0, #1 +10020cae: bf08 it eq +10020cb0: 2701 moveq r7, #1 +10020cb2: f1bb 0f00 cmp.w fp, #0 +10020cb6: d006 beq.n 10020cc6 +10020cb8: 2101 movs r1, #1 +10020cba: 4620 mov r0, r4 +10020cbc: f7fe fdc7 bl 1001f84e +10020cc0: 2801 cmp r0, #1 +10020cc2: bf08 it eq +10020cc4: 2701 moveq r7, #1 +10020cc6: f509 50c8 add.w r0, r9, #6400 ; 0x1900 +10020cca: f100 09a8 add.w r9, r0, #168 ; 0xa8 +10020cce: 463a mov r2, r7 +10020cd0: 2300 movs r3, #0 +10020cd2: 2138 movs r1, #56 ; 0x38 +10020cd4: 4648 mov r0, r9 +10020cd6: f00f fa9d bl 10030214 +10020cda: 5928 ldr r0, [r5, r4] +10020cdc: 1837 adds r7, r6, r0 +10020cde: f858 0004 ldr.w r0, [r8, r4] +10020ce2: f104 0b0c add.w fp, r4, #12 +10020ce6: b148 cbz r0, 10020cfc +10020ce8: 5828 ldr r0, [r5, r0] +10020cea: 693a ldr r2, [r7, #16] +10020cec: 1830 adds r0, r6, r0 +10020cee: 6901 ldr r1, [r0, #16] +10020cf0: b11a cbz r2, 10020cfa +10020cf2: b119 cbz r1, 10020cfc +10020cf4: 4291 cmp r1, r2 +10020cf6: bfc8 it gt +10020cf8: 4611 movgt r1, r2 +10020cfa: 6139 str r1, [r7, #16] +10020cfc: 2101 movs r1, #1 +10020cfe: 4658 mov r0, fp +10020d00: f7ff fdb0 bl 10020864 +10020d04: 2800 cmp r0, #0 +10020d06: bf02 ittt eq +10020d08: 6938 ldreq r0, [r7, #16] +10020d0a: 2800 cmpeq r0, #0 +10020d0c: 61b8 streq r0, [r7, #24] +10020d0e: 2101 movs r1, #1 +10020d10: 4658 mov r0, fp +10020d12: f7ff fda7 bl 10020864 +10020d16: 6938 ldr r0, [r7, #16] +10020d18: 61b8 str r0, [r7, #24] +10020d1a: 213a movs r1, #58 ; 0x3a +10020d1c: f8da 2018 ldr.w r2, [sl, #24] +10020d20: 17d3 asrs r3, r2, #31 +10020d22: 4648 mov r0, r9 +10020d24: f00f fa76 bl 10030214 +10020d28: 4648 mov r0, r9 +10020d2a: f00f f968 bl 1002fffe +10020d2e: e8bd 8ff7 ldmia.w sp!, {r0, r1, r2, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +10020d32 : +10020d32: 4770 bx lr + +10020d34 : +10020d34: 4770 bx lr + +10020d36 : +10020d36: b510 push {r4, lr} +10020d38: 4604 mov r4, r0 +10020d3a: f641 30a4 movw r0, #7076 ; 0x1ba4 +10020d3e: 2258 movs r2, #88 ; 0x58 +10020d40: 5900 ldr r0, [r0, r4] +10020d42: f500 50c8 add.w r0, r0, #6400 ; 0x1900 +10020d46: 2100 movs r1, #0 +10020d48: 304c adds r0, #76 ; 0x4c +10020d4a: f7ef fd75 bl 10010838 +10020d4e: 4620 mov r0, r4 +10020d50: e8bd 4010 ldmia.w sp!, {r4, lr} +10020d54: e675 b.n 10020a42 + +10020d56 : +10020d56: 4770 bx lr + +10020d58 <_RND4>: +10020d58: f010 0103 ands.w r1, r0, #3 +10020d5c: bf18 it ne +10020d5e: 2101 movne r1, #1 +10020d60: eb01 0090 add.w r0, r1, r0, lsr #2 +10020d64: 0080 lsls r0, r0, #2 +10020d66: 4770 bx lr + +10020d68 : +10020d68: b900 cbnz r0, 10020d6c +10020d6a: 4770 bx lr +10020d6c: b510 push {r4, lr} +10020d6e: f100 037c add.w r3, r0, #124 ; 0x7c +10020d72: 68da ldr r2, [r3, #12] +10020d74: 188a adds r2, r1, r2 +10020d76: 60da str r2, [r3, #12] +10020d78: 691c ldr r4, [r3, #16] +10020d7a: 4294 cmp r4, r2 +10020d7c: d203 bcs.n 10020d86 +10020d7e: 1a50 subs r0, r2, r1 +10020d80: 60d8 str r0, [r3, #12] +10020d82: 2000 movs r0, #0 +10020d84: bd10 pop {r4, pc} +10020d86: 6fc3 ldr r3, [r0, #124] ; 0x7c +10020d88: 18c9 adds r1, r1, r3 +10020d8a: 67c1 str r1, [r0, #124] ; 0x7c +10020d8c: 4610 mov r0, r2 +10020d8e: bd10 pop {r4, pc} + +10020d90 : +10020d90: 6840 ldr r0, [r0, #4] +10020d92: 4208 tst r0, r1 +10020d94: d001 beq.n 10020d9a +10020d96: 2001 movs r0, #1 +10020d98: 4770 bx lr +10020d9a: 2000 movs r0, #0 +10020d9c: 4770 bx lr + +10020d9e : +10020d9e: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +10020da2: f500 6932 add.w r9, r0, #2848 ; 0xb20 +10020da6: 2600 movs r6, #0 +10020da8: f509 7725 add.w r7, r9, #660 ; 0x294 +10020dac: f8d9 0294 ldr.w r0, [r9, #660] ; 0x294 +10020db0: 00c0 lsls r0, r0, #3 +10020db2: f7ef fd26 bl 10010802 +10020db6: f44f 7103 mov.w r1, #524 ; 0x20c +10020dba: fb01 9806 mla r8, r1, r6, r9 +10020dbe: 0004 movs r4, r0 +10020dc0: f8c8 0088 str.w r0, [r8, #136] ; 0x88 +10020dc4: d028 beq.n 10020e18 +10020dc6: 2000 movs r0, #0 +10020dc8: f8c8 0090 str.w r0, [r8, #144] ; 0x90 +10020dcc: 2500 movs r5, #0 +10020dce: e018 b.n 10020e02 +10020dd0: 88b9 ldrh r1, [r7, #4] +10020dd2: f7f0 fb0f bl 100113f4 +10020dd6: eb08 0185 add.w r1, r8, r5, lsl #2 +10020dda: f8c1 a094 str.w sl, [r1, #148] ; 0x94 +10020dde: eb04 01c5 add.w r1, r4, r5, lsl #3 +10020de2: 1c6d adds r5, r5, #1 +10020de4: 680a ldr r2, [r1, #0] +10020de6: f422 4280 bic.w r2, r2, #16384 ; 0x4000 +10020dea: 600a str r2, [r1, #0] +10020dec: f422 4200 bic.w r2, r2, #32768 ; 0x8000 +10020df0: 600a str r2, [r1, #0] +10020df2: 0b92 lsrs r2, r2, #14 +10020df4: 88bb ldrh r3, [r7, #4] +10020df6: 049b lsls r3, r3, #18 +10020df8: 0c9b lsrs r3, r3, #18 +10020dfa: ea43 3282 orr.w r2, r3, r2, lsl #14 +10020dfe: 600a str r2, [r1, #0] +10020e00: 6048 str r0, [r1, #4] +10020e02: f8d9 0294 ldr.w r0, [r9, #660] ; 0x294 +10020e06: 4285 cmp r5, r0 +10020e08: da08 bge.n 10020e1c +10020e0a: 88b8 ldrh r0, [r7, #4] +10020e0c: 2100 movs r1, #0 +10020e0e: f7f0 fac5 bl 1001139c +10020e12: ea5f 0a00 movs.w sl, r0 +10020e16: d1db bne.n 10020dd0 +10020e18: 2000 movs r0, #0 +10020e1a: e003 b.n 10020e24 +10020e1c: 1c76 adds r6, r6, #1 +10020e1e: 2e01 cmp r6, #1 +10020e20: dbc4 blt.n 10020dac +10020e22: 2001 movs r0, #1 +10020e24: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + +10020e28 : +10020e28: b538 push {r3, r4, r5, lr} +10020e2a: f500 6432 add.w r4, r0, #2848 ; 0xb20 +10020e2e: 2500 movs r5, #0 +10020e30: e007 b.n 10020e42 +10020e32: eb04 0085 add.w r0, r4, r5, lsl #2 +10020e36: f8d0 0094 ldr.w r0, [r0, #148] ; 0x94 +10020e3a: b108 cbz r0, 10020e40 +10020e3c: f7f0 fabc bl 100113b8 +10020e40: 1c6d adds r5, r5, #1 +10020e42: f8d4 0294 ldr.w r0, [r4, #660] ; 0x294 +10020e46: 4285 cmp r5, r0 +10020e48: dbf3 blt.n 10020e32 +10020e4a: 00c1 lsls r1, r0, #3 +10020e4c: f8d4 0088 ldr.w r0, [r4, #136] ; 0x88 +10020e50: e8bd 4034 ldmia.w sp!, {r2, r4, r5, lr} +10020e54: f7ef bcda b.w 1001080c + +10020e58 : +10020e58: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +10020e5c: 0014 movs r4, r2 +10020e5e: 460e mov r6, r1 +10020e60: f600 1828 addw r8, r0, #2344 ; 0x928 +10020e64: d034 beq.n 10020ed0 +10020e66: 0160 lsls r0, r4, #5 +10020e68: f7ef fccb bl 10010802 +10020e6c: ea5f 0900 movs.w r9, r0 +10020e70: d01d beq.n 10020eae +10020e72: 00a0 lsls r0, r4, #2 +10020e74: f7ef fcc5 bl 10010802 +10020e78: 4605 mov r5, r0 +10020e7a: 2700 movs r7, #0 +10020e7c: e00b b.n 10020e96 +10020e7e: eb09 1047 add.w r0, r9, r7, lsl #5 +10020e82: f855 1027 ldr.w r1, [r5, r7, lsl #2] +10020e86: 6041 str r1, [r0, #4] +10020e88: 1c7f adds r7, r7, #1 +10020e8a: 6801 ldr r1, [r0, #0] +10020e8c: 0c09 lsrs r1, r1, #16 +10020e8e: 0409 lsls r1, r1, #16 +10020e90: f041 0166 orr.w r1, r1, #102 ; 0x66 +10020e94: 6001 str r1, [r0, #0] +10020e96: 42a7 cmp r7, r4 +10020e98: d20b bcs.n 10020eb2 +10020e9a: 2046 movs r0, #70 ; 0x46 +10020e9c: f7ff ff5c bl 10020d58 <_RND4> +10020ea0: 3020 adds r0, #32 +10020ea2: f7ef fcae bl 10010802 +10020ea6: f845 0027 str.w r0, [r5, r7, lsl #2] +10020eaa: 2800 cmp r0, #0 +10020eac: d1e7 bne.n 10020e7e +10020eae: 2000 movs r0, #0 +10020eb0: e00f b.n 10020ed2 +10020eb2: eb08 1046 add.w r0, r8, r6, lsl #5 +10020eb6: f100 0690 add.w r6, r0, #144 ; 0x90 +10020eba: f8c0 9090 str.w r9, [r0, #144] ; 0x90 +10020ebe: 6075 str r5, [r6, #4] +10020ec0: 2100 movs r1, #0 +10020ec2: 60b1 str r1, [r6, #8] +10020ec4: 60f4 str r4, [r6, #12] +10020ec6: 30a0 adds r0, #160 ; 0xa0 +10020ec8: f7ef fd35 bl 10010936 +10020ecc: 2000 movs r0, #0 +10020ece: 61f0 str r0, [r6, #28] +10020ed0: 2001 movs r0, #1 +10020ed2: e8bd 83f2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, pc} + +10020ed6 : +10020ed6: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +10020eda: 460f mov r7, r1 +10020edc: f600 1828 addw r8, r0, #2344 ; 0x928 +10020ee0: eb08 1447 add.w r4, r8, r7, lsl #5 +10020ee4: f104 0590 add.w r5, r4, #144 ; 0x90 +10020ee8: f8d4 6094 ldr.w r6, [r4, #148] ; 0x94 +10020eec: e002 b.n 10020ef4 +10020eee: 4640 mov r0, r8 +10020ef0: f00b fb36 bl 1002c560 +10020ef4: 69e8 ldr r0, [r5, #28] +10020ef6: b180 cbz r0, 10020f1a +10020ef8: 6828 ldr r0, [r5, #0] +10020efa: 68a9 ldr r1, [r5, #8] +10020efc: f000 f8c7 bl 1002108e <.text_13> +10020f00: 2f04 cmp r7, #4 +10020f02: 6001 str r1, [r0, #0] +10020f04: d004 beq.n 10020f10 +10020f06: 68a8 ldr r0, [r5, #8] +10020f08: 68e9 ldr r1, [r5, #12] +10020f0a: f000 f8c6 bl 1002109a <.text_14> +10020f0e: 60a8 str r0, [r5, #8] +10020f10: 4628 mov r0, r5 +10020f12: f00f fa6e bl 100303f2 +10020f16: 0001 movs r1, r0 +10020f18: d1e9 bne.n 10020eee +10020f1a: 2700 movs r7, #0 +10020f1c: e009 b.n 10020f32 +10020f1e: 2046 movs r0, #70 ; 0x46 +10020f20: f7ff ff1a bl 10020d58 <_RND4> +10020f24: f100 0120 add.w r1, r0, #32 +10020f28: f856 0027 ldr.w r0, [r6, r7, lsl #2] +10020f2c: f7ef fc6e bl 1001080c +10020f30: 1c7f adds r7, r7, #1 +10020f32: 68e8 ldr r0, [r5, #12] +10020f34: 4287 cmp r7, r0 +10020f36: d204 bcs.n 10020f42 +10020f38: f856 0027 ldr.w r0, [r6, r7, lsl #2] +10020f3c: 2800 cmp r0, #0 +10020f3e: d1ee bne.n 10020f1e +10020f40: e00e b.n 10020f60 +10020f42: 0081 lsls r1, r0, #2 +10020f44: 6868 ldr r0, [r5, #4] +10020f46: f7ef fc61 bl 1001080c +10020f4a: 68e8 ldr r0, [r5, #12] +10020f4c: 0141 lsls r1, r0, #5 +10020f4e: 6828 ldr r0, [r5, #0] +10020f50: f7ef fc5c bl 1001080c +10020f54: f104 00a8 add.w r0, r4, #168 ; 0xa8 +10020f58: e8bd 41f0 ldmia.w sp!, {r4, r5, r6, r7, r8, lr} +10020f5c: f7ef bd02 b.w 10010964 +10020f60: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +10020f64 : +10020f64: b5f8 push {r3, r4, r5, r6, r7, lr} +10020f66: 4604 mov r4, r0 +10020f68: f604 1528 addw r5, r4, #2344 ; 0x928 +10020f6c: 2104 movs r1, #4 +10020f6e: f8c5 1190 str.w r1, [r5, #400] ; 0x190 +10020f72: 2204 movs r2, #4 +10020f74: f505 71c8 add.w r1, r5, #400 ; 0x190 +10020f78: f504 6032 add.w r0, r4, #2848 ; 0xb20 +10020f7c: 604a str r2, [r1, #4] +10020f7e: 608a str r2, [r1, #8] +10020f80: 60ca str r2, [r1, #12] +10020f82: 2202 movs r2, #2 +10020f84: 610a str r2, [r1, #16] +10020f86: 2204 movs r2, #4 +10020f88: 614a str r2, [r1, #20] +10020f8a: 2202 movs r2, #2 +10020f8c: 618a str r2, [r1, #24] +10020f8e: f240 6172 movw r1, #1650 ; 0x672 +10020f92: f8a0 1298 strh.w r1, [r0, #664] ; 0x298 +10020f96: 2104 movs r1, #4 +10020f98: f8c0 1294 str.w r1, [r0, #660] ; 0x294 +10020f9c: 4620 mov r0, r4 +10020f9e: f7ff fefe bl 10020d9e +10020fa2: 0006 movs r6, r0 +10020fa4: d01a beq.n 10020fdc +10020fa6: 2700 movs r7, #0 +10020fa8: eb05 0087 add.w r0, r5, r7, lsl #2 +10020fac: 4639 mov r1, r7 +10020fae: f8d0 2190 ldr.w r2, [r0, #400] ; 0x190 +10020fb2: 4620 mov r0, r4 +10020fb4: f7ff ff50 bl 10020e58 +10020fb8: 0006 movs r6, r0 +10020fba: d111 bne.n 10020fe0 +10020fbc: 4620 mov r0, r4 +10020fbe: f7ff ff33 bl 10020e28 +10020fc2: 2700 movs r7, #0 +10020fc4: eb05 1047 add.w r0, r5, r7, lsl #5 +10020fc8: f8d0 0090 ldr.w r0, [r0, #144] ; 0x90 +10020fcc: b118 cbz r0, 10020fd6 +10020fce: 4639 mov r1, r7 +10020fd0: 4620 mov r0, r4 +10020fd2: f7ff ff80 bl 10020ed6 +10020fd6: 1c7f adds r7, r7, #1 +10020fd8: 2f08 cmp r7, #8 +10020fda: dbf3 blt.n 10020fc4 +10020fdc: 4630 mov r0, r6 +10020fde: bdf2 pop {r1, r4, r5, r6, r7, pc} +10020fe0: 1c7f adds r7, r7, #1 +10020fe2: 2f08 cmp r7, #8 +10020fe4: dbe0 blt.n 10020fa8 +10020fe6: e7f9 b.n 10020fdc + +10020fe8 : +10020fe8: b538 push {r3, r4, r5, lr} +10020fea: 4604 mov r4, r0 +10020fec: f7ff ff1c bl 10020e28 +10020ff0: 2500 movs r5, #0 +10020ff2: 4629 mov r1, r5 +10020ff4: 4620 mov r0, r4 +10020ff6: f7ff ff6e bl 10020ed6 +10020ffa: 1c6d adds r5, r5, #1 +10020ffc: 2d08 cmp r5, #8 +10020ffe: d3f8 bcc.n 10020ff2 +10021000: 2001 movs r0, #1 +10021002: bd32 pop {r1, r4, r5, pc} + +10021004 : +10021004: b5f8 push {r3, r4, r5, r6, r7, lr} +10021006: 2100 movs r1, #0 +10021008: 9100 str r1, [sp, #0] +1002100a: f600 1428 addw r4, r0, #2344 ; 0x928 +1002100e: 6885 ldr r5, [r0, #8] +10021010: f500 6132 add.w r1, r0, #2848 ; 0xb20 +10021014: 2000 movs r0, #0 +10021016: f44f 7203 mov.w r2, #524 ; 0x20c +1002101a: fb02 1200 mla r2, r2, r0, r1 +1002101e: f8d2 3088 ldr.w r3, [r2, #136] ; 0x88 +10021022: b113 cbz r3, 1002102a +10021024: 2300 movs r3, #0 +10021026: f8c2 3090 str.w r3, [r2, #144] ; 0x90 +1002102a: 1c40 adds r0, r0, #1 +1002102c: 2801 cmp r0, #1 +1002102e: dbf2 blt.n 10021016 +10021030: a900 add r1, sp, #0 +10021032: f105 0020 add.w r0, r5, #32 +10021036: f7ef fc5f bl 100108f8 +1002103a: 2600 movs r6, #0 +1002103c: eb04 1046 add.w r0, r4, r6, lsl #5 +10021040: f8d0 1090 ldr.w r1, [r0, #144] ; 0x90 +10021044: b1d9 cbz r1, 1002107e +10021046: f100 0790 add.w r7, r0, #144 ; 0x90 +1002104a: e003 b.n 10021054 +1002104c: 4601 mov r1, r0 +1002104e: 4620 mov r0, r4 +10021050: f00b fa86 bl 1002c560 +10021054: 69f8 ldr r0, [r7, #28] +10021056: b180 cbz r0, 1002107a +10021058: 6838 ldr r0, [r7, #0] +1002105a: 68b9 ldr r1, [r7, #8] +1002105c: f000 f817 bl 1002108e <.text_13> +10021060: 2e04 cmp r6, #4 +10021062: 6001 str r1, [r0, #0] +10021064: d004 beq.n 10021070 +10021066: 68b8 ldr r0, [r7, #8] +10021068: 68f9 ldr r1, [r7, #12] +1002106a: f000 f816 bl 1002109a <.text_14> +1002106e: 60b8 str r0, [r7, #8] +10021070: 4638 mov r0, r7 +10021072: f00f f9be bl 100303f2 +10021076: 2800 cmp r0, #0 +10021078: d1e8 bne.n 1002104c +1002107a: 2000 movs r0, #0 +1002107c: 60b8 str r0, [r7, #8] +1002107e: 1c76 adds r6, r6, #1 +10021080: 2e08 cmp r6, #8 +10021082: dbdb blt.n 1002103c +10021084: a900 add r1, sp, #0 +10021086: f105 0020 add.w r0, r5, #32 +1002108a: f000 bcec b.w 10021a66 <.text_40> + +1002108e <.text_13>: +1002108e: eb00 1041 add.w r0, r0, r1, lsl #5 +10021092: 6801 ldr r1, [r0, #0] +10021094: 0049 lsls r1, r1, #1 +10021096: 0849 lsrs r1, r1, #1 +10021098: 4770 bx lr + +1002109a <.text_14>: +1002109a: 1c40 adds r0, r0, #1 +1002109c: fbb0 f2f1 udiv r2, r0, r1 +100210a0: fb01 0012 mls r0, r1, r2, r0 +100210a4: 4770 bx lr + +100210a6 : +100210a6: b570 push {r4, r5, r6, lr} +100210a8: 4604 mov r4, r0 +100210aa: f604 1528 addw r5, r4, #2344 ; 0x928 +100210ae: f44f 7140 mov.w r1, #768 ; 0x300 +100210b2: f003 fdc7 bl 10024c44 +100210b6: f420 7280 bic.w r2, r0, #256 ; 0x100 +100210ba: f44f 7140 mov.w r1, #768 ; 0x300 +100210be: f000 fa3b bl 10021538 <.text_31+0x4> +100210c2: f06f 427f mvn.w r2, #4278190080 ; 0xff000000 +100210c6: f44f 717a mov.w r1, #1000 ; 0x3e8 +100210ca: f000 fa35 bl 10021538 <.text_31+0x4> +100210ce: f241 0604 movw r6, #4100 ; 0x1004 +100210d2: 4632 mov r2, r6 +100210d4: f44f 7160 mov.w r1, #896 ; 0x380 +100210d8: f000 f876 bl 100211c8 <.text_16> +100210dc: f242 0204 movw r2, #8196 ; 0x2004 +100210e0: f240 3182 movw r1, #898 ; 0x382 +100210e4: f000 f870 bl 100211c8 <.text_16> +100210e8: 4632 mov r2, r6 +100210ea: f44f 7161 mov.w r1, #900 ; 0x384 +100210ee: f000 f86b bl 100211c8 <.text_16> +100210f2: 4632 mov r2, r6 +100210f4: f240 3186 movw r1, #902 ; 0x386 +100210f8: f000 f866 bl 100211c8 <.text_16> +100210fc: 4632 mov r2, r6 +100210fe: f44f 7162 mov.w r1, #904 ; 0x388 +10021102: f000 f861 bl 100211c8 <.text_16> +10021106: 4632 mov r2, r6 +10021108: f240 318a movw r1, #906 ; 0x38a +1002110c: f000 f85c bl 100211c8 <.text_16> +10021110: f241 0602 movw r6, #4098 ; 0x1002 +10021114: 4632 mov r2, r6 +10021116: f44f 7163 mov.w r1, #908 ; 0x38c +1002111a: f000 f855 bl 100211c8 <.text_16> +1002111e: 4632 mov r2, r6 +10021120: f240 318e movw r1, #910 ; 0x38e +10021124: f000 f850 bl 100211c8 <.text_16> +10021128: 4632 mov r2, r6 +1002112a: f44f 7164 mov.w r1, #912 ; 0x390 +1002112e: f000 f84b bl 100211c8 <.text_16> +10021132: 4632 mov r2, r6 +10021134: f240 3192 movw r1, #914 ; 0x392 +10021138: f000 f846 bl 100211c8 <.text_16> +1002113c: 4632 mov r2, r6 +1002113e: f44f 7165 mov.w r1, #916 ; 0x394 +10021142: f000 f841 bl 100211c8 <.text_16> +10021146: 4632 mov r2, r6 +10021148: f240 3196 movw r1, #918 ; 0x396 +1002114c: f000 f83c bl 100211c8 <.text_16> +10021150: 4632 mov r2, r6 +10021152: f44f 7166 mov.w r1, #920 ; 0x398 +10021156: f000 f837 bl 100211c8 <.text_16> +1002115a: 4632 mov r2, r6 +1002115c: f240 319a movw r1, #922 ; 0x39a +10021160: f000 f832 bl 100211c8 <.text_16> +10021164: f8d5 2090 ldr.w r2, [r5, #144] ; 0x90 +10021168: f44f 7146 mov.w r1, #792 ; 0x318 +1002116c: f000 f9e4 bl 10021538 <.text_31+0x4> +10021170: f105 0690 add.w r6, r5, #144 ; 0x90 +10021174: f44f 7148 mov.w r1, #800 ; 0x320 +10021178: 6a32 ldr r2, [r6, #32] +1002117a: f000 f9dd bl 10021538 <.text_31+0x4> +1002117e: 6c32 ldr r2, [r6, #64] ; 0x40 +10021180: f44f 714a mov.w r1, #808 ; 0x328 +10021184: f000 f9d8 bl 10021538 <.text_31+0x4> +10021188: 6e32 ldr r2, [r6, #96] ; 0x60 +1002118a: f44f 714c mov.w r1, #816 ; 0x330 +1002118e: f000 f9d3 bl 10021538 <.text_31+0x4> +10021192: f8d5 2110 ldr.w r2, [r5, #272] ; 0x110 +10021196: f44f 7142 mov.w r1, #776 ; 0x308 +1002119a: f000 f9cd bl 10021538 <.text_31+0x4> +1002119e: f505 7588 add.w r5, r5, #272 ; 0x110 +100211a2: f44f 7144 mov.w r1, #784 ; 0x310 +100211a6: 6a2a ldr r2, [r5, #32] +100211a8: f000 f9c6 bl 10021538 <.text_31+0x4> +100211ac: 6c2a ldr r2, [r5, #64] ; 0x40 +100211ae: f44f 7150 mov.w r1, #832 ; 0x340 +100211b2: f000 f9c1 bl 10021538 <.text_31+0x4> +100211b6: f8d4 2ba8 ldr.w r2, [r4, #2984] ; 0xba8 +100211ba: 4620 mov r0, r4 +100211bc: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +100211c0: f44f 714e mov.w r1, #824 ; 0x338 +100211c4: f003 bd54 b.w 10024c70 + +100211c8 <.text_16>: +100211c8: 4620 mov r0, r4 +100211ca: f003 bd49 b.w 10024c60 + +100211ce : +100211ce: b170 cbz r0, 100211ee +100211d0: 2801 cmp r0, #1 +100211d2: d009 beq.n 100211e8 +100211d4: 2803 cmp r0, #3 +100211d6: d004 beq.n 100211e2 +100211d8: 2805 cmp r0, #5 +100211da: d00b beq.n 100211f4 +100211dc: 2806 cmp r0, #6 +100211de: d00c beq.n 100211fa +100211e0: e00e b.n 10021200 +100211e2: f44f 706b mov.w r0, #940 ; 0x3ac +100211e6: 4770 bx lr +100211e8: f44f 7069 mov.w r0, #932 ; 0x3a4 +100211ec: 4770 bx lr +100211ee: f44f 7068 mov.w r0, #928 ; 0x3a0 +100211f2: 4770 bx lr +100211f4: f44f 706c mov.w r0, #944 ; 0x3b0 +100211f8: 4770 bx lr +100211fa: f44f 706e mov.w r0, #952 ; 0x3b8 +100211fe: 4770 bx lr +10021200: f44f 706a mov.w r0, #936 ; 0x3a8 +10021204: 4770 bx lr + +10021206 : +10021206: b5f8 push {r3, r4, r5, r6, r7, lr} +10021208: 460d mov r5, r1 +1002120a: 2600 movs r6, #0 +1002120c: 2d04 cmp r5, #4 +1002120e: 4604 mov r4, r0 +10021210: 4617 mov r7, r2 +10021212: d008 beq.n 10021226 +10021214: f641 409c movw r0, #7324 ; 0x1c9c +10021218: 5901 ldr r1, [r0, r4] +1002121a: 2900 cmp r1, #0 +1002121c: bf02 ittt eq +1002121e: 1900 addeq r0, r0, r4 +10021220: 6840 ldreq r0, [r0, #4] +10021222: 2800 cmpeq r0, #0 +10021224: d001 beq.n 1002122a +10021226: 2001 movs r0, #1 +10021228: bdf2 pop {r1, r4, r5, r6, r7, pc} +1002122a: b2a8 uxth r0, r5 +1002122c: f7ff ffcf bl 100211ce +10021230: 4601 mov r1, r0 +10021232: 4620 mov r0, r4 +10021234: f003 fd06 bl 10024c44 +10021238: 0141 lsls r1, r0, #5 +1002123a: 0540 lsls r0, r0, #21 +1002123c: 0d49 lsrs r1, r1, #21 +1002123e: 0d40 lsrs r0, r0, #21 +10021240: 4281 cmp r1, r0 +10021242: d202 bcs.n 1002124a +10021244: 4287 cmp r7, r0 +10021246: d209 bcs.n 1002125c +10021248: e003 b.n 10021252 +1002124a: 4288 cmp r0, r1 +1002124c: d204 bcs.n 10021258 +1002124e: 4287 cmp r7, r0 +10021250: d305 bcc.n 1002125e +10021252: 428f cmp r7, r1 +10021254: d203 bcs.n 1002125e +10021256: e001 b.n 1002125c +10021258: 428f cmp r7, r1 +1002125a: d000 beq.n 1002125e +1002125c: 2601 movs r6, #1 +1002125e: f8df 08a8 ldr.w r0, [pc, #2216] ; 10021b08 <.text_50> +10021262: 7802 ldrb r2, [r0, #0] +10021264: 2d04 cmp r5, #4 +10021266: f641 33a4 movw r3, #7076 ; 0x1ba4 +1002126a: d20b bcs.n 10021284 +1002126c: b916 cbnz r6, 10021274 +1002126e: 1c51 adds r1, r2, #1 +10021270: 7001 strb r1, [r0, #0] +10021272: e00e b.n 10021292 +10021274: 2200 movs r2, #0 +10021276: 2d02 cmp r5, #2 +10021278: 7002 strb r2, [r0, #0] +1002127a: d10a bne.n 10021292 +1002127c: 5918 ldr r0, [r3, r4] +1002127e: f642 1258 movw r2, #10584 ; 0x2958 +10021282: e005 b.n 10021290 +10021284: b12e cbz r6, 10021292 +10021286: 2d05 cmp r5, #5 +10021288: d103 bne.n 10021292 +1002128a: 5918 ldr r0, [r3, r4] +1002128c: f642 125a movw r2, #10586 ; 0x295a +10021290: 5211 strh r1, [r2, r0] +10021292: 4630 mov r0, r6 +10021294: bdf2 pop {r1, r4, r5, r6, r7, pc} + +10021296 : +10021296: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +1002129a: 4604 mov r4, r0 +1002129c: 460d mov r5, r1 +1002129e: eb04 1045 add.w r0, r4, r5, lsl #5 +100212a2: f600 16b8 addw r6, r0, #2488 ; 0x9b8 +100212a6: f641 5048 movw r0, #7496 ; 0x1d48 +100212aa: f641 5851 movw r8, #7505 ; 0x1d51 +100212ae: 5907 ldr r7, [r0, r4] +100212b0: 4620 mov r0, r4 +100212b2: f7fe fab4 bl 1001f81e +100212b6: b1e8 cbz r0, 100212f4 +100212b8: f818 0004 ldrb.w r0, [r8, r4] +100212bc: 2800 cmp r0, #0 +100212be: d019 beq.n 100212f4 +100212c0: eb07 1045 add.w r0, r7, r5, lsl #5 +100212c4: f600 16b8 addw r6, r0, #2488 ; 0x9b8 +100212c8: e014 b.n 100212f4 +100212ca: 6801 ldr r1, [r0, #0] +100212cc: 0049 lsls r1, r1, #1 +100212ce: 0849 lsrs r1, r1, #1 +100212d0: 6001 str r1, [r0, #0] +100212d2: 4630 mov r0, r6 +100212d4: f00f f88d bl 100303f2 +100212d8: ea5f 0900 movs.w r9, r0 +100212dc: d00a beq.n 100212f4 +100212de: f109 0024 add.w r0, r9, #36 ; 0x24 +100212e2: f00b fdd6 bl 1002ce92 +100212e6: f8d9 0008 ldr.w r0, [r9, #8] +100212ea: 4649 mov r1, r9 +100212ec: f600 1028 addw r0, r0, #2344 ; 0x928 +100212f0: f00b f936 bl 1002c560 +100212f4: 69f0 ldr r0, [r6, #28] +100212f6: b180 cbz r0, 1002131a +100212f8: 68b2 ldr r2, [r6, #8] +100212fa: 6830 ldr r0, [r6, #0] +100212fc: 2d04 cmp r5, #4 +100212fe: eb00 1042 add.w r0, r0, r2, lsl #5 +10021302: d0e2 beq.n 100212ca +10021304: 4629 mov r1, r5 +10021306: 4620 mov r0, r4 +10021308: f7ff ff7d bl 10021206 +1002130c: b390 cbz r0, 10021374 +1002130e: 68b0 ldr r0, [r6, #8] +10021310: 68f1 ldr r1, [r6, #12] +10021312: f7ff fec2 bl 1002109a <.text_14> +10021316: 60b0 str r0, [r6, #8] +10021318: e7db b.n 100212d2 +1002131a: 2d04 cmp r5, #4 +1002131c: d02a beq.n 10021374 +1002131e: 4629 mov r1, r5 +10021320: 4620 mov r0, r4 +10021322: f00f f9c5 bl 100306b0 +10021326: b328 cbz r0, 10021374 +10021328: f641 550c movw r5, #7436 ; 0x1d0c +1002132c: f44f 6100 mov.w r1, #2048 ; 0x800 +10021330: f104 000c add.w r0, r4, #12 +10021334: f7ff fd2c bl 10020d90 +10021338: 2801 cmp r0, #1 +1002133a: d006 beq.n 1002134a +1002133c: 4620 mov r0, r4 +1002133e: f00a ff9b bl 1002c278 +10021342: b110 cbz r0, 1002134a +10021344: 1928 adds r0, r5, r4 +10021346: f7ef faa2 bl 1001088e +1002134a: b19f cbz r7, 10021374 +1002134c: f44f 6100 mov.w r1, #2048 ; 0x800 +10021350: 4620 mov r0, r4 +10021352: f7fe fa7c bl 1001f84e +10021356: 2801 cmp r0, #1 +10021358: d00c beq.n 10021374 +1002135a: 4638 mov r0, r7 +1002135c: f00a ff8c bl 1002c278 +10021360: b140 cbz r0, 10021374 +10021362: f818 0007 ldrb.w r0, [r8, r7] +10021366: b100 cbz r0, 1002136a +10021368: 4627 mov r7, r4 +1002136a: 19e8 adds r0, r5, r7 +1002136c: e8bd 43f2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, lr} +10021370: f7ef ba8d b.w 1001088e +10021374: e8bd 83f1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, pc} + +10021378 : +10021378: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1002137c: 4605 mov r5, r0 +1002137e: f641 5148 movw r1, #7496 ; 0x1d48 +10021382: f641 30a4 movw r0, #7076 ; 0x1ba4 +10021386: 194a adds r2, r1, r5 +10021388: 5946 ldr r6, [r0, r5] +1002138a: 7a12 ldrb r2, [r2, #8] +1002138c: f04f 0800 mov.w r8, #0 +10021390: b91a cbnz r2, 1002139a +10021392: 5949 ldr r1, [r1, r5] +10021394: b109 cbz r1, 1002139a +10021396: 460d mov r5, r1 +10021398: 5946 ldr r6, [r0, r5] +1002139a: f44f 719a mov.w r1, #308 ; 0x134 +1002139e: 4628 mov r0, r5 +100213a0: f003 fc50 bl 10024c44 +100213a4: f642 172c movw r7, #10540 ; 0x292c +100213a8: 19bc adds r4, r7, r6 +100213aa: 59b9 ldr r1, [r7, r6] +100213ac: 4308 orrs r0, r1 +100213ae: 51b8 str r0, [r7, r6] +100213b0: 68e1 ldr r1, [r4, #12] +100213b2: ea01 0200 and.w r2, r1, r0 +100213b6: 51ba str r2, [r7, r6] +100213b8: f44f 719a mov.w r1, #308 ; 0x134 +100213bc: 4628 mov r0, r5 +100213be: f003 fc57 bl 10024c70 +100213c2: f44f 717a mov.w r1, #1000 ; 0x3e8 +100213c6: 4628 mov r0, r5 +100213c8: f003 fc3c bl 10024c44 +100213cc: 6861 ldr r1, [r4, #4] +100213ce: 4308 orrs r0, r1 +100213d0: 6060 str r0, [r4, #4] +100213d2: 6921 ldr r1, [r4, #16] +100213d4: ea01 0200 and.w r2, r1, r0 +100213d8: 6062 str r2, [r4, #4] +100213da: f44f 717a mov.w r1, #1000 ; 0x3e8 +100213de: 4628 mov r0, r5 +100213e0: f003 fc46 bl 10024c70 +100213e4: 2184 movs r1, #132 ; 0x84 +100213e6: 4628 mov r0, r5 +100213e8: f003 fc2c bl 10024c44 +100213ec: 68a1 ldr r1, [r4, #8] +100213ee: 4308 orrs r0, r1 +100213f0: 60a0 str r0, [r4, #8] +100213f2: 6961 ldr r1, [r4, #20] +100213f4: ea01 0200 and.w r2, r1, r0 +100213f8: 60a2 str r2, [r4, #8] +100213fa: 2184 movs r1, #132 ; 0x84 +100213fc: 4628 mov r0, r5 +100213fe: f003 fc37 bl 10024c70 +10021402: 59b8 ldr r0, [r7, r6] +10021404: 68e1 ldr r1, [r4, #12] +10021406: 4208 tst r0, r1 +10021408: bf02 ittt eq +1002140a: 6860 ldreq r0, [r4, #4] +1002140c: 6921 ldreq r1, [r4, #16] +1002140e: 4208 tsteq r0, r1 +10021410: bf02 ittt eq +10021412: 68a0 ldreq r0, [r4, #8] +10021414: 6961 ldreq r1, [r4, #20] +10021416: 4208 tsteq r0, r1 +10021418: d001 beq.n 1002141e +1002141a: f04f 0801 mov.w r8, #1 +1002141e: 4640 mov r0, r8 +10021420: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +10021424 : +10021424: b5f8 push {r3, r4, r5, r6, r7, lr} +10021426: 4604 mov r4, r0 +10021428: f641 30a4 movw r0, #7076 ; 0x1ba4 +1002142c: 460d mov r5, r1 +1002142e: 5907 ldr r7, [r0, r4] +10021430: 2100 movs r1, #0 +10021432: f88d 1000 strb.w r1, [sp] +10021436: 4616 mov r6, r2 +10021438: f641 5148 movw r1, #7496 ; 0x1d48 +1002143c: 190a adds r2, r1, r4 +1002143e: 7a12 ldrb r2, [r2, #8] +10021440: b91a cbnz r2, 1002144a +10021442: 5909 ldr r1, [r1, r4] +10021444: b109 cbz r1, 1002144a +10021446: 460c mov r4, r1 +10021448: 5907 ldr r7, [r0, r4] +1002144a: 4620 mov r0, r4 +1002144c: f000 f860 bl 10021510 +10021450: 2000 movs r0, #0 +10021452: 9000 str r0, [sp, #0] +10021454: f642 1038 movw r0, #10552 ; 0x2938 +10021458: 9900 ldr r1, [sp, #0] +1002145a: 9a00 ldr r2, [sp, #0] +1002145c: f855 1021 ldr.w r1, [r5, r1, lsl #2] +10021460: eb07 0282 add.w r2, r7, r2, lsl #2 +10021464: b111 cbz r1, 1002146c +10021466: 5883 ldr r3, [r0, r2] +10021468: 4319 orrs r1, r3 +1002146a: 5081 str r1, [r0, r2] +1002146c: 9900 ldr r1, [sp, #0] +1002146e: f856 1021 ldr.w r1, [r6, r1, lsl #2] +10021472: b119 cbz r1, 1002147c +10021474: 5883 ldr r3, [r0, r2] +10021476: ea23 0101 bic.w r1, r3, r1 +1002147a: 5081 str r1, [r0, r2] +1002147c: 9900 ldr r1, [sp, #0] +1002147e: 1c49 adds r1, r1, #1 +10021480: 2903 cmp r1, #3 +10021482: 9100 str r1, [sp, #0] +10021484: dbe8 blt.n 10021458 +10021486: 4620 mov r0, r4 +10021488: e8bd 40f2 ldmia.w sp!, {r1, r4, r5, r6, r7, lr} +1002148c: e01d b.n 100214ca + +1002148e : +1002148e: f641 31a4 movw r1, #7076 ; 0x1ba4 +10021492: 2230 movs r2, #48 ; 0x30 +10021494: 5808 ldr r0, [r1, r0] +10021496: f642 1138 movw r1, #10552 ; 0x2938 +1002149a: 500a str r2, [r1, r0] +1002149c: 1808 adds r0, r1, r0 +1002149e: f240 117d movw r1, #381 ; 0x17d +100214a2: 6041 str r1, [r0, #4] +100214a4: f8df 1664 ldr.w r1, [pc, #1636] ; 10021b0c <.text_51> +100214a8: 6081 str r1, [r0, #8] +100214aa: 4770 bx lr + +100214ac : +100214ac: f641 5148 movw r1, #7496 ; 0x1d48 +100214b0: 180a adds r2, r1, r0 +100214b2: 7a12 ldrb r2, [r2, #8] +100214b4: b912 cbnz r2, 100214bc +100214b6: 5809 ldr r1, [r1, r0] +100214b8: b101 cbz r1, 100214bc +100214ba: 4608 mov r0, r1 +100214bc: f641 31a4 movw r1, #7076 ; 0x1ba4 +100214c0: f642 123c movw r2, #10556 ; 0x293c +100214c4: 5809 ldr r1, [r1, r0] +100214c6: 5852 ldr r2, [r2, r1] +100214c8: e01e b.n 10021508 <.text_28> + +100214ca : +100214ca: b5f8 push {r3, r4, r5, r6, r7, lr} +100214cc: f000 f837 bl 1002153e <.text_32> +100214d0: f641 30a4 movw r0, #7076 ; 0x1ba4 +100214d4: f642 1638 movw r6, #10552 ; 0x2938 +100214d8: 5905 ldr r5, [r0, r4] +100214da: 1977 adds r7, r6, r5 +100214dc: f44f 717b mov.w r1, #1004 ; 0x3ec +100214e0: 687a ldr r2, [r7, #4] +100214e2: f000 f829 bl 10021538 <.text_31+0x4> +100214e6: 5972 ldr r2, [r6, r5] +100214e8: f000 f824 bl 10021534 <.text_31> +100214ec: 68ba ldr r2, [r7, #8] +100214ee: 4620 mov r0, r4 +100214f0: e8bd 40f8 ldmia.w sp!, {r3, r4, r5, r6, r7, lr} +100214f4: e01b b.n 1002152e <.text_30> + +100214f6 : +100214f6: f641 5148 movw r1, #7496 ; 0x1d48 +100214fa: 180a adds r2, r1, r0 +100214fc: 7a12 ldrb r2, [r2, #8] +100214fe: b912 cbnz r2, 10021506 +10021500: 5809 ldr r1, [r1, r0] +10021502: b101 cbz r1, 10021506 +10021504: 4608 mov r0, r1 +10021506: 2200 movs r2, #0 + +10021508 <.text_28>: +10021508: f44f 717b mov.w r1, #1004 ; 0x3ec +1002150c: f003 bbb0 b.w 10024c70 + +10021510 : +10021510: b510 push {r4, lr} +10021512: f000 f814 bl 1002153e <.text_32> +10021516: 2200 movs r2, #0 +10021518: f44f 717b mov.w r1, #1004 ; 0x3ec +1002151c: f000 f80c bl 10021538 <.text_31+0x4> +10021520: 2200 movs r2, #0 +10021522: f000 f807 bl 10021534 <.text_31> +10021526: 4620 mov r0, r4 +10021528: e8bd 4010 ldmia.w sp!, {r4, lr} +1002152c: 2200 movs r2, #0 + +1002152e <.text_30>: +1002152e: 2180 movs r1, #128 ; 0x80 +10021530: f003 bb9e b.w 10024c70 + +10021534 <.text_31>: +10021534: f44f 7198 mov.w r1, #304 ; 0x130 +10021538: 4620 mov r0, r4 +1002153a: f003 bb99 b.w 10024c70 + +1002153e <.text_32>: +1002153e: 4604 mov r4, r0 +10021540: f641 5048 movw r0, #7496 ; 0x1d48 +10021544: 1901 adds r1, r0, r4 +10021546: 7a09 ldrb r1, [r1, #8] +10021548: b911 cbnz r1, 10021550 <.text_32+0x12> +1002154a: 5900 ldr r0, [r0, r4] +1002154c: b100 cbz r0, 10021550 <.text_32+0x12> +1002154e: 4604 mov r4, r0 +10021550: 4770 bx lr + +10021552 : +10021552: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +10021556: b082 sub sp, #8 +10021558: 4680 mov r8, r0 +1002155a: 2000 movs r0, #0 +1002155c: 9000 str r0, [sp, #0] +1002155e: f641 30a4 movw r0, #7076 ; 0x1ba4 +10021562: f8d8 a008 ldr.w sl, [r8, #8] +10021566: f850 5008 ldr.w r5, [r0, r8] +1002156a: f108 040c add.w r4, r8, #12 +1002156e: a900 add r1, sp, #0 +10021570: f10a 0020 add.w r0, sl, #32 +10021574: f7ef f9c0 bl 100108f8 +10021578: f642 172c movw r7, #10540 ; 0x292c +1002157c: 5978 ldr r0, [r7, r5] +1002157e: f010 7fc0 tst.w r0, #25165824 ; 0x1800000 +10021582: d02f beq.n 100215e4 +10021584: f641 5948 movw r9, #7496 ; 0x1d48 +10021588: 4646 mov r6, r8 +1002158a: f859 0008 ldr.w r0, [r9, r8] +1002158e: b130 cbz r0, 1002159e +10021590: 2110 movs r1, #16 +10021592: 300c adds r0, #12 +10021594: f7ff fbfc bl 10020d90 +10021598: b108 cbz r0, 1002159e +1002159a: f859 6008 ldr.w r6, [r9, r8] +1002159e: f896 0ad8 ldrb.w r0, [r6, #2776] ; 0xad8 +100215a2: b130 cbz r0, 100215b2 +100215a4: 2000 movs r0, #0 +100215a6: f886 0ad8 strb.w r0, [r6, #2776] ; 0xad8 +100215aa: 2104 movs r1, #4 +100215ac: 4630 mov r0, r6 +100215ae: f7ff fe72 bl 10021296 +100215b2: 2110 movs r1, #16 +100215b4: 4620 mov r0, r4 +100215b6: f7ff fbeb bl 10020d90 +100215ba: b130 cbz r0, 100215ca +100215bc: f894 04d4 ldrb.w r0, [r4, #1236] ; 0x4d4 +100215c0: 2801 cmp r0, #1 +100215c2: bf04 itt eq +100215c4: 4640 moveq r0, r8 +100215c6: f7fc fbb5 bleq 1001dd34 +100215ca: 2110 movs r1, #16 +100215cc: 4640 mov r0, r8 +100215ce: f7fe f93e bl 1001f84e +100215d2: b138 cbz r0, 100215e4 +100215d4: f859 0008 ldr.w r0, [r9, r8] +100215d8: f890 14e0 ldrb.w r1, [r0, #1248] ; 0x4e0 +100215dc: 2901 cmp r1, #1 +100215de: bf08 it eq +100215e0: f7fc fba8 bleq 1001dd34 +100215e4: 197c adds r4, r7, r5 +100215e6: 7920 ldrb r0, [r4, #4] +100215e8: 0640 lsls r0, r0, #25 +100215ea: d503 bpl.n 100215f4 +100215ec: 2105 movs r1, #5 +100215ee: 4640 mov r0, r8 +100215f0: f7ff fe51 bl 10021296 +100215f4: 6860 ldr r0, [r4, #4] +100215f6: 05c0 lsls r0, r0, #23 +100215f8: d503 bpl.n 10021602 +100215fa: 2106 movs r1, #6 +100215fc: 4640 mov r0, r8 +100215fe: f7ff fe4a bl 10021296 +10021602: 7920 ldrb r0, [r4, #4] +10021604: 0740 lsls r0, r0, #29 +10021606: d503 bpl.n 10021610 +10021608: 2100 movs r1, #0 +1002160a: 4640 mov r0, r8 +1002160c: f7ff fe43 bl 10021296 +10021610: 7920 ldrb r0, [r4, #4] +10021612: f010 0f03 tst.w r0, #3 +10021616: d102 bne.n 1002161e +10021618: 5d78 ldrb r0, [r7, r5] +1002161a: 06c0 lsls r0, r0, #27 +1002161c: d517 bpl.n 1002164e +1002161e: 6920 ldr r0, [r4, #16] +10021620: 0882 lsrs r2, r0, #2 +10021622: 0092 lsls r2, r2, #2 +10021624: 6122 str r2, [r4, #16] +10021626: f44f 717b mov.w r1, #1004 ; 0x3ec +1002162a: 68e0 ldr r0, [r4, #12] +1002162c: f020 0010 bic.w r0, r0, #16 +10021630: 60e0 str r0, [r4, #12] +10021632: 4640 mov r0, r8 +10021634: f003 fb1c bl 10024c70 +10021638: 68e2 ldr r2, [r4, #12] +1002163a: f44f 7198 mov.w r1, #304 ; 0x130 +1002163e: 4640 mov r0, r8 +10021640: f003 fb16 bl 10024c70 +10021644: f508 50e0 add.w r0, r8, #7168 ; 0x1c00 +10021648: 30f4 adds r0, #244 ; 0xf4 +1002164a: f7ef f920 bl 1001088e +1002164e: 4640 mov r0, r8 +10021650: f000 fa0c bl 10021a6c +10021654: f505 5024 add.w r0, r5, #10496 ; 0x2900 +10021658: f100 0964 add.w r9, r0, #100 ; 0x64 +1002165c: 5978 ldr r0, [r7, r5] +1002165e: 0380 lsls r0, r0, #14 +10021660: f642 1688 movw r6, #10632 ; 0x2988 +10021664: d509 bpl.n 1002167a +10021666: 4640 mov r0, r8 +10021668: f7f1 fe05 bl 10013276 +1002166c: 5d70 ldrb r0, [r6, r5] +1002166e: b170 cbz r0, 1002168e +10021670: 6ca0 ldr r0, [r4, #72] ; 0x48 +10021672: f040 0001 orr.w r0, r0, #1 +10021676: f000 f848 bl 1002170a <.text_34> +1002167a: 5978 ldr r0, [r7, r5] +1002167c: 0080 lsls r0, r0, #2 +1002167e: d506 bpl.n 1002168e +10021680: 5d70 ldrb r0, [r6, r5] +10021682: b120 cbz r0, 1002168e +10021684: 6ca0 ldr r0, [r4, #72] ; 0x48 +10021686: f040 0008 orr.w r0, r0, #8 +1002168a: f000 f83e bl 1002170a <.text_34> +1002168e: 7a20 ldrb r0, [r4, #8] +10021690: 07c0 lsls r0, r0, #31 +10021692: bf44 itt mi +10021694: 4640 movmi r0, r8 +10021696: f7f1 fddd blmi 10013254 +1002169a: 7a20 ldrb r0, [r4, #8] +1002169c: 0780 lsls r0, r0, #30 +1002169e: d504 bpl.n 100216aa +100216a0: 6ca0 ldr r0, [r4, #72] ; 0x48 +100216a2: f440 5080 orr.w r0, r0, #4096 ; 0x1000 +100216a6: f000 f830 bl 1002170a <.text_34> +100216aa: 5978 ldr r0, [r7, r5] +100216ac: 0340 lsls r0, r0, #13 +100216ae: bf44 itt mi +100216b0: 4640 movmi r0, r8 +100216b2: f7f1 fde1 blmi 10013278 +100216b6: 5978 ldr r0, [r7, r5] +100216b8: 0300 lsls r0, r0, #12 +100216ba: bf44 itt mi +100216bc: 4640 movmi r0, r8 +100216be: f7f1 fde6 blmi 1001328e +100216c2: 5978 ldr r0, [r7, r5] +100216c4: 02c0 lsls r0, r0, #11 +100216c6: bf44 itt mi +100216c8: 4640 movmi r0, r8 +100216ca: f7f1 fe02 blmi 100132d2 +100216ce: 5978 ldr r0, [r7, r5] +100216d0: 0280 lsls r0, r0, #10 +100216d2: bf44 itt mi +100216d4: 4640 movmi r0, r8 +100216d6: f7f1 fe2b blmi 10013330 +100216da: 5978 ldr r0, [r7, r5] +100216dc: 0240 lsls r0, r0, #9 +100216de: bf44 itt mi +100216e0: 4640 movmi r0, r8 +100216e2: f7f1 fe45 blmi 10013370 +100216e6: 5978 ldr r0, [r7, r5] +100216e8: 0180 lsls r0, r0, #6 +100216ea: bf44 itt mi +100216ec: 4640 movmi r0, r8 +100216ee: f7f1 fe53 blmi 10013398 +100216f2: 2000 movs r0, #0 +100216f4: 5178 str r0, [r7, r5] +100216f6: 6060 str r0, [r4, #4] +100216f8: 60a0 str r0, [r4, #8] +100216fa: a900 add r1, sp, #0 +100216fc: f10a 0020 add.w r0, sl, #32 +10021700: f7ef f901 bl 10010906 +10021704: 2001 movs r0, #1 +10021706: e8bd 87f6 ldmia.w sp!, {r1, r2, r4, r5, r6, r7, r8, r9, sl, pc} + +1002170a <.text_34>: +1002170a: 64a0 str r0, [r4, #72] ; 0x48 +1002170c: 4648 mov r0, r9 +1002170e: f7ef b8be b.w 1001088e + +10021712 : +10021712: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +10021716: 4690 mov r8, r2 +10021718: f108 0608 add.w r6, r8, #8 +1002171c: 4604 mov r4, r0 +1002171e: 4689 mov r9, r1 +10021720: 461d mov r5, r3 +10021722: 60b4 str r4, [r6, #8] +10021724: 4640 mov r0, r8 +10021726: f7ef f891 bl 1001084c +1002172a: f108 0788 add.w r7, r8, #136 ; 0x88 +1002172e: 2000 movs r0, #0 +10021730: 60b8 str r0, [r7, #8] +10021732: 6770 str r0, [r6, #116] ; 0x74 +10021734: 2260 movs r2, #96 ; 0x60 +10021736: f109 011c add.w r1, r9, #28 +1002173a: f108 001c add.w r0, r8, #28 +1002173e: f7ef f866 bl 1001080e +10021742: f108 091c add.w r9, r8, #28 +10021746: b305 cbz r5, 1002178a +10021748: f641 5024 movw r0, #7460 ; 0x1d24 +1002174c: 5900 ldr r0, [r0, r4] +1002174e: 61e8 str r0, [r5, #28] +10021750: f8c8 5008 str.w r5, [r8, #8] +10021754: 68e8 ldr r0, [r5, #12] +10021756: 67b0 str r0, [r6, #120] ; 0x78 +10021758: 6928 ldr r0, [r5, #16] +1002175a: f8c8 0088 str.w r0, [r8, #136] ; 0x88 +1002175e: 67f0 str r0, [r6, #124] ; 0x7c +10021760: 4628 mov r0, r5 +10021762: f7ef fe5a bl 1001141a +10021766: 6078 str r0, [r7, #4] +10021768: 4640 mov r0, r8 +1002176a: 6a29 ldr r1, [r5, #32] +1002176c: f7ff fafc bl 10020d68 +10021770: f899 0002 ldrb.w r0, [r9, #2] +10021774: b130 cbz r0, 10021784 +10021776: f899 0040 ldrb.w r0, [r9, #64] ; 0x40 +1002177a: b918 cbnz r0, 10021784 +1002177c: 9908 ldr r1, [sp, #32] +1002177e: 4640 mov r0, r8 +10021780: f00f fb09 bl 10030d96 +10021784: 2001 movs r0, #1 +10021786: e8bd 83f2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, pc} +1002178a: 2000 movs r0, #0 +1002178c: e7fb b.n 10021786 + +1002178e : +1002178e: b5f0 push {r4, r5, r6, r7, lr} +10021790: f641 32a4 movw r2, #7076 ; 0x1ba4 +10021794: 2300 movs r3, #0 +10021796: 5812 ldr r2, [r2, r0] +10021798: 2001 movs r0, #1 +1002179a: 2400 movs r4, #0 +1002179c: b911 cbnz r1, 100217a4 +1002179e: 2000 movs r0, #0 +100217a0: bdf0 pop {r4, r5, r6, r7, pc} +100217a2: b994 cbnz r4, 100217ca +100217a4: f642 154a movw r5, #10570 ; 0x294a +100217a8: 680f ldr r7, [r1, #0] +100217aa: 5aae ldrh r6, [r5, r2] +100217ac: 00ff lsls r7, r7, #3 +100217ae: 1c5b adds r3, r3, #1 +100217b0: 0cff lsrs r7, r7, #19 +100217b2: 42b7 cmp r7, r6 +100217b4: d104 bne.n 100217c0 +100217b6: 1c74 adds r4, r6, #1 +100217b8: 04e4 lsls r4, r4, #19 +100217ba: 0ce4 lsrs r4, r4, #19 +100217bc: 52ac strh r4, [r5, r2] +100217be: 2401 movs r4, #1 +100217c0: f242 7511 movw r5, #10001 ; 0x2711 +100217c4: 42ab cmp r3, r5 +100217c6: d3ec bcc.n 100217a2 +100217c8: 2000 movs r0, #0 +100217ca: bdf0 pop {r4, r5, r6, r7, pc} + +100217cc : +100217cc: b510 push {r4, lr} +100217ce: f500 6432 add.w r4, r0, #2848 ; 0xb20 +100217d2: f44f 716d mov.w r1, #948 ; 0x3b4 +100217d6: f003 fa35 bl 10024c44 +100217da: 0141 lsls r1, r0, #5 +100217dc: 0540 lsls r0, r0, #21 +100217de: 0d49 lsrs r1, r1, #21 +100217e0: 0d40 lsrs r0, r0, #21 +100217e2: 4288 cmp r0, r1 +100217e4: d101 bne.n 100217ea +100217e6: 2000 movs r0, #0 +100217e8: bd10 pop {r4, pc} +100217ea: bf31 iteee cc +100217ec: 1a08 subcc r0, r1, r0 +100217ee: f8d4 2294 ldrcs.w r2, [r4, #660] ; 0x294 +100217f2: 1a10 subcs r0, r2, r0 +100217f4: 1808 addcs r0, r1, r0 +100217f6: b280 uxth r0, r0 +100217f8: bd10 pop {r4, pc} + +100217fa : +100217fa: e92d 4ff1 stmdb sp!, {r0, r4, r5, r6, r7, r8, r9, sl, fp, lr} +100217fe: b088 sub sp, #32 +10021800: f500 6032 add.w r0, r0, #2848 ; 0xb20 +10021804: 9001 str r0, [sp, #4] +10021806: 2100 movs r1, #0 +10021808: 1d00 adds r0, r0, #4 +1002180a: 9002 str r0, [sp, #8] +1002180c: 2000 movs r0, #0 +1002180e: 9006 str r0, [sp, #24] +10021810: 9808 ldr r0, [sp, #32] +10021812: f500 50e8 add.w r0, r0, #7424 ; 0x1d00 +10021816: 3024 adds r0, #36 ; 0x24 +10021818: 6a40 ldr r0, [r0, #36] ; 0x24 +1002181a: 9003 str r0, [sp, #12] +1002181c: 9808 ldr r0, [sp, #32] +1002181e: f7ff ffd5 bl 100217cc +10021822: 4604 mov r4, r0 +10021824: 9801 ldr r0, [sp, #4] +10021826: 3088 adds r0, #136 ; 0x88 +10021828: 9005 str r0, [sp, #20] +1002182a: e023 b.n 10021874 +1002182c: 9902 ldr r1, [sp, #8] +1002182e: 4658 mov r0, fp +10021830: f00b fc16 bl 1002d060 +10021834: 9901 ldr r1, [sp, #4] +10021836: 9804 ldr r0, [sp, #16] +10021838: 6800 ldr r0, [r0, #0] +1002183a: f501 7125 add.w r1, r1, #660 ; 0x294 +1002183e: 0b80 lsrs r0, r0, #14 +10021840: 8889 ldrh r1, [r1, #4] +10021842: 0489 lsls r1, r1, #18 +10021844: 0c89 lsrs r1, r1, #18 +10021846: ea41 3080 orr.w r0, r1, r0, lsl #14 +1002184a: 9904 ldr r1, [sp, #16] +1002184c: 6008 str r0, [r1, #0] +1002184e: 9805 ldr r0, [sp, #20] +10021850: 9901 ldr r1, [sp, #4] +10021852: 6880 ldr r0, [r0, #8] +10021854: f8d1 1294 ldr.w r1, [r1, #660] ; 0x294 +10021858: 1c40 adds r0, r0, #1 +1002185a: fbb0 f2f1 udiv r2, r0, r1 +1002185e: fb01 0212 mls r2, r1, r2, r0 +10021862: 9805 ldr r0, [sp, #20] +10021864: 6082 str r2, [r0, #8] +10021866: b292 uxth r2, r2 +10021868: 9808 ldr r0, [sp, #32] +1002186a: f44f 716d mov.w r1, #948 ; 0x3b4 +1002186e: f003 f9f7 bl 10024c60 +10021872: 1e64 subs r4, r4, #1 +10021874: b2a4 uxth r4, r4 +10021876: 2c00 cmp r4, #0 +10021878: f000 80cd beq.w 10021a16 +1002187c: 9805 ldr r0, [sp, #20] +1002187e: 9901 ldr r1, [sp, #4] +10021880: 6880 ldr r0, [r0, #8] +10021882: f8d1 1088 ldr.w r1, [r1, #136] ; 0x88 +10021886: eb01 01c0 add.w r1, r1, r0, lsl #3 +1002188a: 9104 str r1, [sp, #16] +1002188c: 2200 movs r2, #0 +1002188e: 9901 ldr r1, [sp, #4] +10021890: eb01 0080 add.w r0, r1, r0, lsl #2 +10021894: f8d0 8094 ldr.w r8, [r0, #148] ; 0x94 +10021898: 9904 ldr r1, [sp, #16] +1002189a: 9808 ldr r0, [sp, #32] +1002189c: f7ff ff77 bl 1002178e +100218a0: 2801 cmp r0, #1 +100218a2: f040 80b8 bne.w 10021a16 +100218a6: 9802 ldr r0, [sp, #8] +100218a8: f00b fbd2 bl 1002d050 +100218ac: ea5f 0b00 movs.w fp, r0 +100218b0: d0c0 beq.n 10021834 +100218b2: f7ee ffcb bl 1001084c +100218b6: f10b 0708 add.w r7, fp, #8 +100218ba: 2000 movs r0, #0 +100218bc: 6778 str r0, [r7, #116] ; 0x74 +100218be: 4658 mov r0, fp +100218c0: f8d8 1010 ldr.w r1, [r8, #16] +100218c4: f00f fa0a bl 10030cdc +100218c8: 9808 ldr r0, [sp, #32] +100218ca: f641 31a4 movw r1, #7076 ; 0x1ba4 +100218ce: f10b 051c add.w r5, fp, #28 +100218d2: 5808 ldr r0, [r1, r0] +100218d4: 7de9 ldrb r1, [r5, #23] +100218d6: b121 cbz r1, 100218e2 +100218d8: f642 1150 movw r1, #10576 ; 0x2950 +100218dc: 580a ldr r2, [r1, r0] +100218de: 1c52 adds r2, r2, #1 +100218e0: 500a str r2, [r1, r0] +100218e2: 7da8 ldrb r0, [r5, #22] +100218e4: 2800 cmp r0, #0 +100218e6: d1a1 bne.n 1002182c +100218e8: 78a8 ldrb r0, [r5, #2] +100218ea: b118 cbz r0, 100218f4 +100218ec: f8d8 0010 ldr.w r0, [r8, #16] +100218f0: 3018 adds r0, #24 +100218f2: 9006 str r0, [sp, #24] +100218f4: 7a28 ldrb r0, [r5, #8] +100218f6: 7be9 ldrb r1, [r5, #15] +100218f8: f8b5 9000 ldrh.w r9, [r5] +100218fc: 2800 cmp r0, #0 +100218fe: bf14 ite ne +10021900: f04f 0a06 movne.w sl, #6 +10021904: f04f 0a00 moveq.w sl, #0 +10021908: 2901 cmp r1, #1 +1002190a: bf04 itt eq +1002190c: 7ba9 ldrbeq r1, [r5, #14] +1002190e: 2900 cmpeq r1, #0 +10021910: f109 000e add.w r0, r9, #14 +10021914: d105 bne.n 10021922 +10021916: f240 6173 movw r1, #1651 ; 0x673 +1002191a: 4589 cmp r9, r1 +1002191c: bf38 it cc +1002191e: f44f 60d0 movcc.w r0, #1664 ; 0x680 +10021922: 2100 movs r1, #0 +10021924: f7ef fd3a bl 1001139c +10021928: 0006 movs r6, r0 +1002192a: f43f af7f beq.w 1002182c +1002192e: f8c6 9020 str.w r9, [r6, #32] +10021932: f641 5124 movw r1, #7460 ; 0x1d24 +10021936: 9808 ldr r0, [sp, #32] +10021938: 5808 ldr r0, [r1, r0] +1002193a: 61f0 str r0, [r6, #28] +1002193c: f8cb 6008 str.w r6, [fp, #8] +10021940: 4651 mov r1, sl +10021942: 4630 mov r0, r6 +10021944: f7ef fd5e bl 10011404 +10021948: f8d8 0010 ldr.w r0, [r8, #16] +1002194c: 78e9 ldrb r1, [r5, #3] +1002194e: 1808 adds r0, r1, r0 +10021950: 7929 ldrb r1, [r5, #4] +10021952: 1808 adds r0, r1, r0 +10021954: f100 0118 add.w r1, r0, #24 +10021958: 6930 ldr r0, [r6, #16] +1002195a: 464a mov r2, r9 +1002195c: f7ee ff57 bl 1001080e +10021960: 68f0 ldr r0, [r6, #12] +10021962: 67b8 str r0, [r7, #120] ; 0x78 +10021964: 6930 ldr r0, [r6, #16] +10021966: f8cb 0088 str.w r0, [fp, #136] ; 0x88 +1002196a: 67f8 str r0, [r7, #124] ; 0x7c +1002196c: 4630 mov r0, r6 +1002196e: f7ef fd54 bl 1001141a +10021972: f8cb 008c str.w r0, [fp, #140] ; 0x8c +10021976: 4649 mov r1, r9 +10021978: 4658 mov r0, fp +1002197a: f7ff f9f5 bl 10020d68 +1002197e: 9808 ldr r0, [sp, #32] +10021980: f7fd ff4d bl 1001f81e +10021984: 2800 cmp r0, #0 +10021986: d037 beq.n 100219f8 +10021988: f895 0040 ldrb.w r0, [r5, #64] ; 0x40 +1002198c: bba0 cbnz r0, 100219f8 +1002198e: 6ff8 ldr r0, [r7, #124] ; 0x7c +10021990: f810 1f04 ldrb.w r1, [r0, #4]! +10021994: 07c9 lsls r1, r1, #31 +10021996: d40f bmi.n 100219b8 +10021998: 9903 ldr r1, [sp, #12] +1002199a: f501 51c8 add.w r1, r1, #6400 ; 0x1900 +1002199e: 2206 movs r2, #6 +100219a0: 3195 adds r1, #149 ; 0x95 +100219a2: f7ee ff3e bl 10010822 +100219a6: b338 cbz r0, 100219f8 +100219a8: 9803 ldr r0, [sp, #12] +100219aa: f641 5124 movw r1, #7460 ; 0x1d24 +100219ae: 5808 ldr r0, [r1, r0] +100219b0: 61f0 str r0, [r6, #28] +100219b2: 9803 ldr r0, [sp, #12] +100219b4: 60b8 str r0, [r7, #8] +100219b6: e01f b.n 100219f8 +100219b8: 9802 ldr r0, [sp, #8] +100219ba: f00b fb49 bl 1002d050 +100219be: 0006 movs r6, r0 +100219c0: d028 beq.n 10021a14 +100219c2: f8db 0008 ldr.w r0, [fp, #8] +100219c6: 2200 movs r2, #0 +100219c8: 2101 movs r1, #1 +100219ca: f7ef fd38 bl 1001143e +100219ce: b910 cbnz r0, 100219d6 +100219d0: 9902 ldr r1, [sp, #8] +100219d2: 4630 mov r0, r6 +100219d4: e72c b.n 10021830 +100219d6: 9906 ldr r1, [sp, #24] +100219d8: 9100 str r1, [sp, #0] +100219da: 4603 mov r3, r0 +100219dc: 9803 ldr r0, [sp, #12] +100219de: 4632 mov r2, r6 +100219e0: 4659 mov r1, fp +100219e2: f7ff fe96 bl 10021712 +100219e6: 2801 cmp r0, #1 +100219e8: d003 beq.n 100219f2 +100219ea: 9902 ldr r1, [sp, #8] +100219ec: 4630 mov r0, r6 +100219ee: f00b fb37 bl 1002d060 +100219f2: 4630 mov r0, r6 +100219f4: f00c fb4b bl 1002e08e +100219f8: f895 0040 ldrb.w r0, [r5, #64] ; 0x40 +100219fc: 2800 cmp r0, #0 +100219fe: f47f af15 bne.w 1002182c +10021a02: 78a8 ldrb r0, [r5, #2] +10021a04: b118 cbz r0, 10021a0e +10021a06: 9906 ldr r1, [sp, #24] +10021a08: 4658 mov r0, fp +10021a0a: f00f f9c4 bl 10030d96 +10021a0e: 4658 mov r0, fp +10021a10: f00c fb3d bl 1002e08e +10021a14: e70e b.n 10021834 +10021a16: b009 add sp, #36 ; 0x24 +10021a18: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +10021a1c : +10021a1c: b5f8 push {r3, r4, r5, r6, r7, lr} +10021a1e: 4604 mov r4, r0 +10021a20: 2000 movs r0, #0 +10021a22: 9000 str r0, [sp, #0] +10021a24: f641 30a4 movw r0, #7076 ; 0x1ba4 +10021a28: 5905 ldr r5, [r0, r4] +10021a2a: 68a6 ldr r6, [r4, #8] +10021a2c: 4620 mov r0, r4 +10021a2e: f7ff fee4 bl 100217fa +10021a32: a900 add r1, sp, #0 +10021a34: f106 0020 add.w r0, r6, #32 +10021a38: f7ee ff5e bl 100108f8 +10021a3c: f642 1038 movw r0, #10552 ; 0x2938 +10021a40: 1947 adds r7, r0, r5 +10021a42: 6879 ldr r1, [r7, #4] +10021a44: f041 0101 orr.w r1, r1, #1 +10021a48: 6079 str r1, [r7, #4] +10021a4a: 5941 ldr r1, [r0, r5] +10021a4c: f041 0210 orr.w r2, r1, #16 +10021a50: 5142 str r2, [r0, r5] +10021a52: f7ff fd6f bl 10021534 <.text_31> +10021a56: 687a ldr r2, [r7, #4] +10021a58: f44f 717b mov.w r1, #1004 ; 0x3ec +10021a5c: f7ff fd6c bl 10021538 <.text_31+0x4> +10021a60: a900 add r1, sp, #0 +10021a62: f106 0020 add.w r0, r6, #32 + +10021a66 <.text_40>: +10021a66: f7ee ff4e bl 10010906 +10021a6a: bdf1 pop {r0, r4, r5, r6, r7, pc} + +10021a6c : +10021a6c: b530 push {r4, r5, lr} +10021a6e: b083 sub sp, #12 +10021a70: f20f 01b8 addw r1, pc, #184 ; 0xb8 +10021a74: 4604 mov r4, r0 +10021a76: c90c ldmia r1!, {r2, r3} +10021a78: a800 add r0, sp, #0 +10021a7a: 2500 movs r5, #0 +10021a7c: c00c stmia r0!, {r2, r3} +10021a7e: a800 add r0, sp, #0 +10021a80: 5c29 ldrb r1, [r5, r0] +10021a82: 4620 mov r0, r4 +10021a84: f7ff fc07 bl 10021296 +10021a88: 1c6d adds r5, r5, #1 +10021a8a: 2d06 cmp r5, #6 +10021a8c: d3f7 bcc.n 10021a7e +10021a8e: bd37 pop {r0, r1, r2, r4, r5, pc} + +10021a90 : +10021a90: 481f ldr r0, [pc, #124] ; (10021b10 <.text_52>) +10021a92: 5c40 ldrb r0, [r0, r1] +10021a94: 4770 bx lr + +10021a96 : +10021a96: 481e ldr r0, [pc, #120] ; (10021b10 <.text_52>) +10021a98: 5a40 ldrh r0, [r0, r1] +10021a9a: 4770 bx lr + +10021a9c : +10021a9c: 481c ldr r0, [pc, #112] ; (10021b10 <.text_52>) +10021a9e: 5840 ldr r0, [r0, r1] +10021aa0: 4770 bx lr + +10021aa2 : +10021aa2: 481b ldr r0, [pc, #108] ; (10021b10 <.text_52>) +10021aa4: 5442 strb r2, [r0, r1] +10021aa6: 2001 movs r0, #1 +10021aa8: 4770 bx lr + +10021aaa : +10021aaa: 4819 ldr r0, [pc, #100] ; (10021b10 <.text_52>) +10021aac: 5242 strh r2, [r0, r1] +10021aae: 2002 movs r0, #2 +10021ab0: 4770 bx lr + +10021ab2 : +10021ab2: 4817 ldr r0, [pc, #92] ; (10021b10 <.text_52>) +10021ab4: 5042 str r2, [r0, r1] +10021ab6: 2004 movs r0, #4 +10021ab8: 4770 bx lr + +10021aba : +10021aba: b538 push {r3, r4, r5, lr} +10021abc: 4604 mov r4, r0 +10021abe: f00e febb bl 10030838 +10021ac2: f641 5548 movw r5, #7496 ; 0x1d48 +10021ac6: 1928 adds r0, r5, r4 +10021ac8: 7a40 ldrb r0, [r0, #9] +10021aca: b940 cbnz r0, 10021ade +10021acc: 4620 mov r0, r4 +10021ace: f7fd fea6 bl 1001f81e +10021ad2: b120 cbz r0, 10021ade +10021ad4: 5928 ldr r0, [r5, r4] +10021ad6: e8bd 4032 ldmia.w sp!, {r1, r4, r5, lr} +10021ada: f00e bead b.w 10030838 +10021ade: bd31 pop {r0, r4, r5, pc} + +10021ae0 : +10021ae0: b510 push {r4, lr} +10021ae2: 4604 mov r4, r0 +10021ae4: 2228 movs r2, #40 ; 0x28 +10021ae6: 2100 movs r1, #0 +10021ae8: f7ee fea6 bl 10010838 +10021aec: 4809 ldr r0, [pc, #36] ; (10021b14 <.text_53>) +10021aee: 60a0 str r0, [r4, #8] +10021af0: 4809 ldr r0, [pc, #36] ; (10021b18 <.text_54>) +10021af2: 60e0 str r0, [r4, #12] +10021af4: 4809 ldr r0, [pc, #36] ; (10021b1c <.text_55>) +10021af6: 6120 str r0, [r4, #16] +10021af8: 4809 ldr r0, [pc, #36] ; (10021b20 <.text_56>) +10021afa: 6160 str r0, [r4, #20] +10021afc: 4809 ldr r0, [pc, #36] ; (10021b24 <.text_57>) +10021afe: 61a0 str r0, [r4, #24] +10021b00: 4809 ldr r0, [pc, #36] ; (10021b28 <.text_58>) +10021b02: 61e0 str r0, [r4, #28] +10021b04: bd10 pop {r4, pc} + ... + +10021b08 <.text_50>: +10021b08: 10048b16 .word 0x10048b16 + +10021b0c <.text_51>: +10021b0c: 80000040 .word 0x80000040 + +10021b10 <.text_52>: +10021b10: 40080000 .word 0x40080000 + +10021b14 <.text_53>: +10021b14: 10021a91 .word 0x10021a91 + +10021b18 <.text_54>: +10021b18: 10021a97 .word 0x10021a97 + +10021b1c <.text_55>: +10021b1c: 10021a9d .word 0x10021a9d + +10021b20 <.text_56>: +10021b20: 10021aa3 .word 0x10021aa3 + +10021b24 <.text_57>: +10021b24: 10021aab .word 0x10021aab + +10021b28 <.text_58>: +10021b28: 10021ab3 .word 0x10021ab3 + +10021b2c : +10021b2c: 01000506 00000302 ........ + +10021b34 : +10021b34: b570 push {r4, r5, r6, lr} +10021b36: f500 74b8 add.w r4, r0, #368 ; 0x170 +10021b3a: 2500 movs r5, #0 +10021b3c: 2600 movs r6, #0 +10021b3e: e001 b.n 10021b44 +10021b40: 2e03 cmp r6, #3 +10021b42: d002 beq.n 10021b4a +10021b44: 2200 movs r2, #0 +10021b46: 4631 mov r1, r6 +10021b48: e001 b.n 10021b4e +10021b4a: 2280 movs r2, #128 ; 0x80 +10021b4c: 2103 movs r1, #3 +10021b4e: 4628 mov r0, r5 +10021b50: f7fe fee0 bl 10020914 +10021b54: 2200 movs r2, #0 +10021b56: 4631 mov r1, r6 +10021b58: 4628 mov r0, r5 +10021b5a: f7fe fed5 bl 10020908 +10021b5e: 1c76 adds r6, r6, #1 +10021b60: b2f6 uxtb r6, r6 +10021b62: 2e10 cmp r6, #16 +10021b64: dbec blt.n 10021b40 +10021b66: 1c6d adds r5, r5, #1 +10021b68: 2d80 cmp r5, #128 ; 0x80 +10021b6a: dbe7 blt.n 10021b3c +10021b6c: 2500 movs r5, #0 +10021b6e: 210a movs r1, #10 +10021b70: f104 001c add.w r0, r4, #28 +10021b74: f003 fe52 bl 1002581c <__aeabi_memclr4> +10021b78: 2000 movs r0, #0 +10021b7a: 62a0 str r0, [r4, #40] ; 0x28 +10021b7c: 6460 str r0, [r4, #68] ; 0x44 +10021b7e: 85a0 strh r0, [r4, #44] ; 0x2c +10021b80: 2200 movs r2, #0 +10021b82: 2013 movs r0, #19 +10021b84: 74a0 strb r0, [r4, #18] +10021b86: 2000 movs r0, #0 +10021b88: 74e0 strb r0, [r4, #19] +10021b8a: 7020 strb r0, [r4, #0] +10021b8c: f884 0036 strb.w r0, [r4, #54] ; 0x36 +10021b90: f884 0035 strb.w r0, [r4, #53] ; 0x35 +10021b94: 2001 movs r0, #1 +10021b96: 73e0 strb r0, [r4, #15] +10021b98: f884 0037 strb.w r0, [r4, #55] ; 0x37 +10021b9c: 2000 movs r0, #0 +10021b9e: f884 0038 strb.w r0, [r4, #56] ; 0x38 +10021ba2: 4601 mov r1, r0 +10021ba4: 4628 mov r0, r5 +10021ba6: f7fe feb5 bl 10020914 +10021baa: 1c6d adds r5, r5, #1 +10021bac: 2d80 cmp r5, #128 ; 0x80 +10021bae: dbde blt.n 10021b6e +10021bb0: 20ff movs r0, #255 ; 0xff +10021bb2: 7460 strb r0, [r4, #17] +10021bb4: bd70 pop {r4, r5, r6, pc} + +10021bb6 : +10021bb6: b5f8 push {r3, r4, r5, r6, r7, lr} +10021bb8: 460c mov r4, r1 +10021bba: 4606 mov r6, r0 +10021bbc: f894 003b ldrb.w r0, [r4, #59] ; 0x3b +10021bc0: 4615 mov r5, r2 +10021bc2: 461f mov r7, r3 +10021bc4: 2101 movs r1, #1 +10021bc6: f7fe fea0 bl 1002090a +10021bca: 7ca2 ldrb r2, [r4, #18] +10021bcc: f005 017f and.w r1, r5, #127 ; 0x7f +10021bd0: 428a cmp r2, r1 +10021bd2: d204 bcs.n 10021bde +10021bd4: f005 0180 and.w r1, r5, #128 ; 0x80 +10021bd8: ea42 0501 orr.w r5, r2, r1 +10021bdc: e005 b.n 10021bea +10021bde: f104 0212 add.w r2, r4, #18 +10021be2: 7852 ldrb r2, [r2, #1] +10021be4: 4291 cmp r1, r2 +10021be6: bf38 it cc +10021be8: 4615 movcc r5, r2 +10021bea: b917 cbnz r7, 10021bf2 +10021bec: f000 077f and.w r7, r0, #127 ; 0x7f +10021bf0: e016 b.n 10021c20 +10021bf2: f894 003b ldrb.w r0, [r4, #59] ; 0x3b +10021bf6: 2101 movs r1, #1 +10021bf8: f7fe fe87 bl 1002090a +10021bfc: f8df 1530 ldr.w r1, [pc, #1328] ; 10022130 <.text_33> +10021c00: f005 027f and.w r2, r5, #127 ; 0x7f +10021c04: f000 0007 and.w r0, r0, #7 +10021c08: 5c51 ldrb r1, [r2, r1] +10021c0a: ea40 00c1 orr.w r0, r0, r1, lsl #3 +10021c0e: f040 0780 orr.w r7, r0, #128 ; 0x80 +10021c12: f04f 3201 mov.w r2, #16843009 ; 0x1010101 +10021c16: f44f 6186 mov.w r1, #1072 ; 0x430 +10021c1a: 4630 mov r0, r6 +10021c1c: f00f f994 bl 10030f48 +10021c20: f894 003b ldrb.w r0, [r4, #59] ; 0x3b +10021c24: 462a mov r2, r5 +10021c26: 2100 movs r1, #0 +10021c28: f7fe fe74 bl 10020914 +10021c2c: f894 003b ldrb.w r0, [r4, #59] ; 0x3b +10021c30: b2fa uxtb r2, r7 +10021c32: 2101 movs r1, #1 +10021c34: f7fe fe6e bl 10020914 +10021c38: f894 003b ldrb.w r0, [r4, #59] ; 0x3b +10021c3c: 2105 movs r1, #5 +10021c3e: f7fe fe64 bl 1002090a +10021c42: f000 01fc and.w r1, r0, #252 ; 0xfc +10021c46: 9806 ldr r0, [sp, #24] +10021c48: f000 0003 and.w r0, r0, #3 +10021c4c: ea40 0201 orr.w r2, r0, r1 +10021c50: f894 003b ldrb.w r0, [r4, #59] ; 0x3b +10021c54: 2105 movs r1, #5 +10021c56: f7fe fe5d bl 10020914 +10021c5a: f894 103b ldrb.w r1, [r4, #59] ; 0x3b +10021c5e: 4620 mov r0, r4 +10021c60: e8bd 40f8 ldmia.w sp!, {r3, r4, r5, r6, r7, lr} +10021c64: 2201 movs r2, #1 +10021c66: f7fe be56 b.w 10020916 + +10021c6a : +10021c6a: b570 push {r4, r5, r6, lr} +10021c6c: 460c mov r4, r1 +10021c6e: 2500 movs r5, #0 +10021c70: 1c56 adds r6, r2, #1 +10021c72: e000 b.n 10021c76 +10021c74: 1c76 adds r6, r6, #1 +10021c76: 7ca0 ldrb r0, [r4, #18] +10021c78: b2f6 uxtb r6, r6 +10021c7a: 42b0 cmp r0, r6 +10021c7c: db0b blt.n 10021c96 +10021c7e: f894 003b ldrb.w r0, [r4, #59] ; 0x3b +10021c82: 10f1 asrs r1, r6, #3 +10021c84: f7fe fe3b bl 100208fe +10021c88: f006 0107 and.w r1, r6, #7 +10021c8c: fa20 f201 lsr.w r2, r0, r1 +10021c90: 07d0 lsls r0, r2, #31 +10021c92: d5ef bpl.n 10021c74 +10021c94: 4635 mov r5, r6 +10021c96: 4628 mov r0, r5 +10021c98: bd70 pop {r4, r5, r6, pc} + +10021c9a : +10021c9a: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +10021c9e: 2600 movs r6, #0 +10021ca0: 460c mov r4, r1 +10021ca2: 461d mov r5, r3 +10021ca4: 46b0 mov r8, r6 +10021ca6: 1e57 subs r7, r2, #1 +10021ca8: e000 b.n 10021cac +10021caa: 1e7f subs r7, r7, #1 +10021cac: 7ce0 ldrb r0, [r4, #19] +10021cae: b2ff uxtb r7, r7 +10021cb0: 4287 cmp r7, r0 +10021cb2: d312 bcc.n 10021cda +10021cb4: f894 003b ldrb.w r0, [r4, #59] ; 0x3b +10021cb8: 08f9 lsrs r1, r7, #3 +10021cba: f7fe fe20 bl 100208fe +10021cbe: f007 0107 and.w r1, r7, #7 +10021cc2: fa20 f201 lsr.w r2, r0, r1 +10021cc6: 07d0 lsls r0, r2, #31 +10021cc8: d5ef bpl.n 10021caa +10021cca: 1c76 adds r6, r6, #1 +10021ccc: b2f6 uxtb r6, r6 +10021cce: 42ae cmp r6, r5 +10021cd0: 46b8 mov r8, r7 +10021cd2: d002 beq.n 10021cda +10021cd4: 7ce0 ldrb r0, [r4, #19] +10021cd6: 4540 cmp r0, r8 +10021cd8: d3e7 bcc.n 10021caa +10021cda: 4640 mov r0, r8 +10021cdc: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +10021ce0 : +10021ce0: b510 push {r4, lr} +10021ce2: b082 sub sp, #8 +10021ce4: 7b4a ldrb r2, [r1, #13] +10021ce6: f891 3036 ldrb.w r3, [r1, #54] ; 0x36 +10021cea: 2a2e cmp r2, #46 ; 0x2e +10021cec: f101 0436 add.w r4, r1, #54 ; 0x36 +10021cf0: db03 blt.n 10021cfa +10021cf2: 9300 str r3, [sp, #0] +10021cf4: 2300 movs r3, #0 +10021cf6: 7aa2 ldrb r2, [r4, #10] +10021cf8: e006 b.n 10021d08 +10021cfa: 9300 str r3, [sp, #0] +10021cfc: 2a1a cmp r2, #26 +10021cfe: bfa7 ittee ge +10021d00: 2300 movge r3, #0 +10021d02: 7ae2 ldrbge r2, [r4, #11] +10021d04: 2300 movlt r3, #0 +10021d06: 7b22 ldrblt r2, [r4, #12] +10021d08: f7ff ff55 bl 10021bb6 +10021d0c: bd13 pop {r0, r1, r4, pc} + +10021d0e : +10021d0e: b5f8 push {r3, r4, r5, r6, r7, lr} +10021d10: 460d mov r5, r1 +10021d12: 4604 mov r4, r0 +10021d14: f895 603b ldrb.w r6, [r5, #59] ; 0x3b +10021d18: 2101 movs r1, #1 +10021d1a: f000 f829 bl 10021d70 <.text_20> +10021d1e: 0600 lsls r0, r0, #24 +10021d20: d525 bpl.n 10021d6e +10021d22: 2102 movs r1, #2 +10021d24: f000 f824 bl 10021d70 <.text_20> +10021d28: 0601 lsls r1, r0, #24 +10021d2a: d520 bpl.n 10021d6e +10021d2c: 0640 lsls r0, r0, #25 +10021d2e: f8df 7404 ldr.w r7, [pc, #1028] ; 10022134 <.text_34> +10021d32: d50f bpl.n 10021d54 +10021d34: f000 f81f bl 10021d76 <.text_21> +10021d38: 2105 movs r1, #5 +10021d3a: f000 f819 bl 10021d70 <.text_20> +10021d3e: 4607 mov r7, r0 +10021d40: 2100 movs r1, #0 +10021d42: f000 f815 bl 10021d70 <.text_20> +10021d46: 4602 mov r2, r0 +10021d48: f007 0003 and.w r0, r7, #3 +10021d4c: 9000 str r0, [sp, #0] +10021d4e: f000 f87d bl 10021e4c <.text_26> +10021d52: bdf1 pop {r0, r4, r5, r6, r7, pc} +10021d54: f105 063b add.w r6, r5, #59 ; 0x3b +10021d58: 4629 mov r1, r5 +10021d5a: 78b0 ldrb r0, [r6, #2] +10021d5c: 1c40 adds r0, r0, #1 +10021d5e: 70b0 strb r0, [r6, #2] +10021d60: 4620 mov r0, r4 +10021d62: f000 f85a bl 10021e1a +10021d66: f000 f806 bl 10021d76 <.text_21> +10021d6a: 2000 movs r0, #0 +10021d6c: 70b0 strb r0, [r6, #2] +10021d6e: bdf1 pop {r0, r4, r5, r6, r7, pc} + +10021d70 <.text_20>: +10021d70: 4630 mov r0, r6 +10021d72: f7fe bdca b.w 1002090a + +10021d76 <.text_21>: +10021d76: 463a mov r2, r7 +10021d78: f44f 6186 mov.w r1, #1072 ; 0x430 +10021d7c: 4620 mov r0, r4 +10021d7e: f00f b8e3 b.w 10030f48 + +10021d82 : +10021d82: 2901 cmp r1, #1 +10021d84: d104 bne.n 10021d90 +10021d86: 3811 subs r0, #17 +10021d88: 2802 cmp r0, #2 +10021d8a: d906 bls.n 10021d9a +10021d8c: 2000 movs r0, #0 +10021d8e: 4770 bx lr +10021d90: 2902 cmp r1, #2 +10021d92: d1fb bne.n 10021d8c +10021d94: 3812 subs r0, #18 +10021d96: 2801 cmp r0, #1 +10021d98: d8f8 bhi.n 10021d8c +10021d9a: 2001 movs r0, #1 +10021d9c: 4770 bx lr + +10021d9e : +10021d9e: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +10021da2: 460d mov r5, r1 +10021da4: f105 063a add.w r6, r5, #58 ; 0x3a +10021da8: 4680 mov r8, r0 +10021daa: 7870 ldrb r0, [r6, #1] +10021dac: f000 f8fe bl 10021fac <.text_31> +10021db0: f105 040f add.w r4, r5, #15 +10021db4: f000 097f and.w r9, r0, #127 ; 0x7f +10021db8: 70a0 strb r0, [r4, #2] +10021dba: f000 0780 and.w r7, r0, #128 ; 0x80 +10021dbe: 7870 ldrb r0, [r6, #1] +10021dc0: 2105 movs r1, #5 +10021dc2: f7fe fda2 bl 1002090a +10021dc6: f000 0603 and.w r6, r0, #3 +10021dca: f885 603a strb.w r6, [r5, #58] ; 0x3a +10021dce: 78e0 ldrb r0, [r4, #3] +10021dd0: 4581 cmp r9, r0 +10021dd2: d104 bne.n 10021dde +10021dd4: 7be8 ldrb r0, [r5, #15] +10021dd6: 2801 cmp r0, #1 +10021dd8: d11d bne.n 10021e16 +10021dda: b14f cbz r7, 10021df0 +10021ddc: e01b b.n 10021e16 +10021dde: 2101 movs r1, #1 +10021de0: 4648 mov r0, r9 +10021de2: f7ff ffce bl 10021d82 +10021de6: b130 cbz r0, 10021df6 +10021de8: 7be8 ldrb r0, [r5, #15] +10021dea: 2801 cmp r0, #1 +10021dec: d103 bne.n 10021df6 +10021dee: b92f cbnz r7, 10021dfc +10021df0: f049 0080 orr.w r0, r9, #128 ; 0x80 +10021df4: e009 b.n 10021e0a +10021df6: 78e0 ldrb r0, [r4, #3] +10021df8: 4581 cmp r9, r0 +10021dfa: d205 bcs.n 10021e08 +10021dfc: 464a mov r2, r9 +10021dfe: 4629 mov r1, r5 +10021e00: 4640 mov r0, r8 +10021e02: f7ff ff32 bl 10021c6a +10021e06: e000 b.n 10021e0a +10021e08: 70a0 strb r0, [r4, #2] +10021e0a: 4602 mov r2, r0 +10021e0c: 9600 str r6, [sp, #0] +10021e0e: 2301 movs r3, #1 +10021e10: 4629 mov r1, r5 +10021e12: f000 f861 bl 10021ed8 <.text_28+0x2> +10021e16: e8bd 83f1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, pc} + +10021e1a : +10021e1a: b538 push {r3, r4, r5, lr} +10021e1c: 460d mov r5, r1 +10021e1e: 4604 mov r4, r0 +10021e20: f895 003b ldrb.w r0, [r5, #59] ; 0x3b +10021e24: 2105 movs r1, #5 +10021e26: f7fe fd70 bl 1002090a +10021e2a: 7ca9 ldrb r1, [r5, #18] +10021e2c: 7c6a ldrb r2, [r5, #17] +10021e2e: f000 0003 and.w r0, r0, #3 +10021e32: f002 037f and.w r3, r2, #127 ; 0x7f +10021e36: 9000 str r0, [sp, #0] +10021e38: 4299 cmp r1, r3 +10021e3a: bf88 it hi +10021e3c: 4619 movhi r1, r3 +10021e3e: f002 0080 and.w r0, r2, #128 ; 0x80 +10021e42: ea40 0201 orr.w r2, r0, r1 +10021e46: f000 f801 bl 10021e4c <.text_26> +10021e4a: bd31 pop {r0, r4, r5, pc} + +10021e4c <.text_26>: +10021e4c: 2300 movs r3, #0 +10021e4e: 4629 mov r1, r5 +10021e50: 4620 mov r0, r4 +10021e52: e6b0 b.n 10021bb6 + +10021e54 : +10021e54: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +10021e58: 4689 mov r9, r1 +10021e5a: f109 0536 add.w r5, r9, #54 ; 0x36 +10021e5e: 4680 mov r8, r0 +10021e60: 7968 ldrb r0, [r5, #5] +10021e62: 4616 mov r6, r2 +10021e64: f000 f8a2 bl 10021fac <.text_31> +10021e68: 4602 mov r2, r0 +10021e6a: f899 4036 ldrb.w r4, [r9, #54] ; 0x36 +10021e6e: f002 0b7f and.w fp, r2, #127 ; 0x7f +10021e72: f889 b011 strb.w fp, [r9, #17] +10021e76: 712c strb r4, [r5, #4] +10021e78: f109 0511 add.w r5, r9, #17 +10021e7c: 46b2 mov sl, r6 +10021e7e: 7868 ldrb r0, [r5, #1] +10021e80: 4558 cmp r0, fp +10021e82: bf3c itt cc +10021e84: 4683 movcc fp, r0 +10021e86: 4602 movcc r2, r0 +10021e88: 2700 movs r7, #0 +10021e8a: e008 b.n 10021e9e +10021e8c: 2301 movs r3, #1 +10021e8e: f000 f825 bl 10021edc <.text_29> +10021e92: 1e76 subs r6, r6, #1 +10021e94: f040 0280 orr.w r2, r0, #128 ; 0x80 +10021e98: b2f6 uxtb r6, r6 +10021e9a: b1b6 cbz r6, 10021eca +10021e9c: 1c7f adds r7, r7, #1 +10021e9e: b2ff uxtb r7, r7 +10021ea0: 4557 cmp r7, sl +10021ea2: da12 bge.n 10021eca +10021ea4: 0610 lsls r0, r2, #24 +10021ea6: d503 bpl.n 10021eb0 +10021ea8: 1e76 subs r6, r6, #1 +10021eaa: 465a mov r2, fp +10021eac: b2f6 uxtb r6, r6 +10021eae: b166 cbz r6, 10021eca +10021eb0: 2102 movs r1, #2 +10021eb2: 4658 mov r0, fp +10021eb4: f7ff ff65 bl 10021d82 +10021eb8: 2800 cmp r0, #0 +10021eba: d1e7 bne.n 10021e8c +10021ebc: 78aa ldrb r2, [r5, #2] +10021ebe: 455a cmp r2, fp +10021ec0: d203 bcs.n 10021eca +10021ec2: 4633 mov r3, r6 +10021ec4: f000 f80a bl 10021edc <.text_29> +10021ec8: 4602 mov r2, r0 +10021eca: 9400 str r4, [sp, #0] +10021ecc: 2300 movs r3, #0 +10021ece: f000 f802 bl 10021ed6 <.text_28> +10021ed2: e8bd 8ff1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +10021ed6 <.text_28>: +10021ed6: 4649 mov r1, r9 +10021ed8: 4640 mov r0, r8 +10021eda: e66c b.n 10021bb6 + +10021edc <.text_29>: +10021edc: 465a mov r2, fp +10021ede: 4649 mov r1, r9 +10021ee0: 4640 mov r0, r8 +10021ee2: e6da b.n 10021c9a + +10021ee4 : +10021ee4: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +10021ee8: 4680 mov r8, r0 +10021eea: 460e mov r6, r1 +10021eec: f898 00b3 ldrb.w r0, [r8, #179] ; 0xb3 +10021ef0: 2800 cmp r0, #0 +10021ef2: bf1c itt ne +10021ef4: 6ab4 ldrne r4, [r6, #40] ; 0x28 +10021ef6: 2c00 cmpne r4, #0 +10021ef8: d056 beq.n 10021fa8 +10021efa: f106 0728 add.w r7, r6, #40 ; 0x28 +10021efe: f106 051c add.w r5, r6, #28 +10021f02: 8af8 ldrh r0, [r7, #22] +10021f04: 1c40 adds r0, r0, #1 +10021f06: 82f8 strh r0, [r7, #22] +10021f08: f8b7 9004 ldrh.w r9, [r7, #4] +10021f0c: f896 a012 ldrb.w sl, [r6, #18] +10021f10: 7cf8 ldrb r0, [r7, #19] +10021f12: b2a4 uxth r4, r4 +10021f14: f000 f84a bl 10021fac <.text_31> +10021f18: 6ab2 ldr r2, [r6, #40] ; 0x28 +10021f1a: 2364 movs r3, #100 ; 0x64 +10021f1c: 435a muls r2, r3 +10021f1e: 69fb ldr r3, [r7, #28] +10021f20: fbb2 f2f3 udiv r2, r2, r3 +10021f24: 7c7b ldrb r3, [r7, #17] +10021f26: f1c2 0264 rsb r2, r2, #100 ; 0x64 +10021f2a: 2b05 cmp r3, #5 +10021f2c: f000 017f and.w r1, r0, #127 ; 0x7f +10021f30: b2d2 uxtb r2, r2 +10021f32: da39 bge.n 10021fa8 +10021f34: 458a cmp sl, r1 +10021f36: d204 bcs.n 10021f42 +10021f38: f000 0080 and.w r0, r0, #128 ; 0x80 +10021f3c: 4651 mov r1, sl +10021f3e: ea4a 0000 orr.w r0, sl, r0 +10021f42: 4b7d ldr r3, [pc, #500] ; (10022138 <.text_35>) +10021f44: 18c0 adds r0, r0, r3 +10021f46: f890 002c ldrb.w r0, [r0, #44] ; 0x2c +10021f4a: 4548 cmp r0, r9 +10021f4c: d326 bcc.n 10021f9c +10021f4e: 0860 lsrs r0, r4, #1 +10021f50: 2c0f cmp r4, #15 +10021f52: da0a bge.n 10021f6a +10021f54: 8929 ldrh r1, [r5, #8] +10021f56: 88ea ldrh r2, [r5, #6] +10021f58: 1851 adds r1, r2, r1 +10021f5a: 4288 cmp r0, r1 +10021f5c: db1e blt.n 10021f9c +10021f5e: 8829 ldrh r1, [r5, #0] +10021f60: eb00 00a4 add.w r0, r0, r4, asr #2 +10021f64: 4288 cmp r0, r1 +10021f66: da1f bge.n 10021fa8 +10021f68: e010 b.n 10021f8c +10021f6a: 7cff ldrb r7, [r7, #19] +10021f6c: b957 cbnz r7, 10021f84 +10021f6e: 892f ldrh r7, [r5, #8] +10021f70: 4287 cmp r7, r0 +10021f72: bfb8 it lt +10021f74: 2001 movlt r0, #1 +10021f76: db04 blt.n 10021f82 +10021f78: eb00 00e4 add.w r0, r0, r4, asr #3 +10021f7c: 42b8 cmp r0, r7 +10021f7e: da01 bge.n 10021f84 +10021f80: 2000 movs r0, #0 +10021f82: 7018 strb r0, [r3, #0] +10021f84: 18c8 adds r0, r1, r3 +10021f86: 7e01 ldrb r1, [r0, #24] +10021f88: 428a cmp r2, r1 +10021f8a: da04 bge.n 10021f96 +10021f8c: 4631 mov r1, r6 +10021f8e: 4640 mov r0, r8 +10021f90: e8bd 47f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +10021f94: e703 b.n 10021d9e +10021f96: 7900 ldrb r0, [r0, #4] +10021f98: 4290 cmp r0, r2 +10021f9a: da05 bge.n 10021fa8 +10021f9c: 4631 mov r1, r6 +10021f9e: 4640 mov r0, r8 +10021fa0: e8bd 47f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +10021fa4: 2201 movs r2, #1 +10021fa6: e755 b.n 10021e54 +10021fa8: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + +10021fac <.text_31>: +10021fac: 2100 movs r1, #0 +10021fae: f7fe bcac b.w 1002090a + ... + +10021fb4 : +10021fb4: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +10021fb8: 4689 mov r9, r1 +10021fba: 4680 mov r8, r0 +10021fbc: f899 7000 ldrb.w r7, [r9] +10021fc0: 2600 movs r6, #0 +10021fc2: f899 003b ldrb.w r0, [r9, #59] ; 0x3b +10021fc6: 4631 mov r1, r6 +10021fc8: f7fe fc99 bl 100208fe +10021fcc: 495b ldr r1, [pc, #364] ; (1002213c <.text_36>) +10021fce: ebc7 02c7 rsb r2, r7, r7, lsl #3 +10021fd2: 1851 adds r1, r2, r1 +10021fd4: 5c71 ldrb r1, [r6, r1] +10021fd6: ea01 0200 and.w r2, r1, r0 +10021fda: f899 0035 ldrb.w r0, [r9, #53] ; 0x35 +10021fde: 2802 cmp r0, #2 +10021fe0: f899 003b ldrb.w r0, [r9, #59] ; 0x3b +10021fe4: bf04 itt eq +10021fe6: 2e00 cmpeq r6, #0 +10021fe8: f002 02f0 andeq.w r2, r2, #240 ; 0xf0 +10021fec: 4631 mov r1, r6 +10021fee: f7fe fc8b bl 10020908 +10021ff2: 1c76 adds r6, r6, #1 +10021ff4: 2e07 cmp r6, #7 +10021ff6: dbe4 blt.n 10021fc2 +10021ff8: 2f08 cmp r7, #8 +10021ffa: d827 bhi.n 1002204c +10021ffc: e8df f007 tbb [pc, r7] +10022000: 0d050d05 .word 0x0d050d05 +10022004: 15150d05 .word 0x15150d05 +10022008: 001d .short 0x001d +1002200a: 201b movs r0, #27 +1002200c: f889 0040 strb.w r0, [r9, #64] ; 0x40 +10022010: 2017 movs r0, #23 +10022012: f889 0041 strb.w r0, [r9, #65] ; 0x41 +10022016: 2014 movs r0, #20 +10022018: e016 b.n 10022048 +1002201a: 2013 movs r0, #19 +1002201c: f889 0040 strb.w r0, [r9, #64] ; 0x40 +10022020: 200f movs r0, #15 +10022022: f889 0041 strb.w r0, [r9, #65] ; 0x41 +10022026: 200c movs r0, #12 +10022028: e00e b.n 10022048 +1002202a: 200b movs r0, #11 +1002202c: f889 0040 strb.w r0, [r9, #64] ; 0x40 +10022030: 2007 movs r0, #7 +10022032: f889 0041 strb.w r0, [r9, #65] ; 0x41 +10022036: 2004 movs r0, #4 +10022038: e006 b.n 10022048 +1002203a: 2003 movs r0, #3 +1002203c: f889 0040 strb.w r0, [r9, #64] ; 0x40 +10022040: 2002 movs r0, #2 +10022042: f889 0041 strb.w r0, [r9, #65] ; 0x41 +10022046: 2000 movs r0, #0 +10022048: f889 0042 strb.w r0, [r9, #66] ; 0x42 +1002204c: 2700 movs r7, #0 +1002204e: 2406 movs r4, #6 +10022050: f899 003b ldrb.w r0, [r9, #59] ; 0x3b +10022054: 4621 mov r1, r4 +10022056: f7fe fc52 bl 100208fe +1002205a: f000 000f and.w r0, r0, #15 +1002205e: e016 b.n 1002208e +10022060: 1e76 subs r6, r6, #1 +10022062: b2f6 uxtb r6, r6 +10022064: fa20 f106 lsr.w r1, r0, r6 +10022068: 07c9 lsls r1, r1, #31 +1002206a: d5f9 bpl.n 10022060 +1002206c: eb06 07c4 add.w r7, r6, r4, lsl #3 +10022070: 2400 movs r4, #0 +10022072: 2500 movs r5, #0 +10022074: e011 b.n 1002209a +10022076: 2c00 cmp r4, #0 +10022078: d0fa beq.n 10022070 +1002207a: 1e60 subs r0, r4, #1 +1002207c: b2c4 uxtb r4, r0 +1002207e: 2c06 cmp r4, #6 +10022080: d0e6 beq.n 10022050 +10022082: f899 003b ldrb.w r0, [r9, #59] ; 0x3b +10022086: 4621 mov r1, r4 +10022088: f7fe fc39 bl 100208fe +1002208c: b2c0 uxtb r0, r0 +1002208e: 2800 cmp r0, #0 +10022090: d0f1 beq.n 10022076 +10022092: 2607 movs r6, #7 +10022094: e7e6 b.n 10022064 +10022096: 2d06 cmp r5, #6 +10022098: d006 beq.n 100220a8 +1002209a: f899 003b ldrb.w r0, [r9, #59] ; 0x3b +1002209e: 4629 mov r1, r5 +100220a0: f7fe fc2d bl 100208fe +100220a4: b2c0 uxtb r0, r0 +100220a6: e006 b.n 100220b6 +100220a8: f899 003b ldrb.w r0, [r9, #59] ; 0x3b +100220ac: 2106 movs r1, #6 +100220ae: f7fe fc26 bl 100208fe +100220b2: f000 000f and.w r0, r0, #15 +100220b6: b158 cbz r0, 100220d0 +100220b8: 2600 movs r6, #0 +100220ba: fa20 f106 lsr.w r1, r0, r6 +100220be: 07c9 lsls r1, r1, #31 +100220c0: d502 bpl.n 100220c8 +100220c2: eb06 04c5 add.w r4, r6, r5, lsl #3 +100220c6: e007 b.n 100220d8 +100220c8: 1c76 adds r6, r6, #1 +100220ca: b2f6 uxtb r6, r6 +100220cc: 2e08 cmp r6, #8 +100220ce: dbf4 blt.n 100220ba +100220d0: 1c68 adds r0, r5, #1 +100220d2: b2c5 uxtb r5, r0 +100220d4: 2d07 cmp r5, #7 +100220d6: dbde blt.n 10022096 +100220d8: f889 7012 strb.w r7, [r9, #18] +100220dc: f889 4013 strb.w r4, [r9, #19] +100220e0: 2100 movs r1, #0 +100220e2: f899 003b ldrb.w r0, [r9, #59] ; 0x3b +100220e6: f7fe fc10 bl 1002090a +100220ea: f000 067f and.w r6, r0, #127 ; 0x7f +100220ee: f899 003b ldrb.w r0, [r9, #59] ; 0x3b +100220f2: f7ff ff5b bl 10021fac <.text_31> +100220f6: b2ff uxtb r7, r7 +100220f8: f000 0080 and.w r0, r0, #128 ; 0x80 +100220fc: 42b7 cmp r7, r6 +100220fe: bf38 it cc +10022100: ea40 0607 orrcc.w r6, r0, r7 +10022104: d304 bcc.n 10022110 +10022106: b2e1 uxtb r1, r4 +10022108: 428e cmp r6, r1 +1002210a: bf38 it cc +1002210c: ea40 0601 orrcc.w r6, r0, r1 +10022110: f899 0036 ldrb.w r0, [r9, #54] ; 0x36 +10022114: 9000 str r0, [sp, #0] +10022116: 2300 movs r3, #0 +10022118: 4632 mov r2, r6 +1002211a: f7ff fedc bl 10021ed6 <.text_28> +1002211e: f899 003b ldrb.w r0, [r9, #59] ; 0x3b +10022122: e8bd 43f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +10022126: 2200 movs r2, #0 +10022128: 2103 movs r1, #3 +1002212a: f7fe bbf3 b.w 10020914 + ... + +10022130 <.text_33>: +10022130: 10044388 .word 0x10044388 + +10022134 <.text_34>: +10022134: 01010000 .word 0x01010000 + +10022138 <.text_35>: +10022138: 10044348 .word 0x10044348 + +1002213c <.text_36>: +1002213c: 10044308 .word 0x10044308 + +10022140 : +10022140: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +10022144: 460d mov r5, r1 +10022146: 4604 mov r4, r0 +10022148: 7828 ldrb r0, [r5, #0] +1002214a: 7869 ldrb r1, [r5, #1] +1002214c: 78aa ldrb r2, [r5, #2] +1002214e: f000 087f and.w r8, r0, #127 ; 0x7f +10022152: f001 001f and.w r0, r1, #31 +10022156: f002 0303 and.w r3, r2, #3 +1002215a: f3c2 1680 ubfx r6, r2, #6, #1 +1002215e: ea4f 1ed2 mov.w lr, r2, lsr #7 +10022162: 09c9 lsrs r1, r1, #7 +10022164: 08d2 lsrs r2, r2, #3 +10022166: b324 cbz r4, 100221b2 +10022168: f1b8 0f0a cmp.w r8, #10 +1002216c: da21 bge.n 100221b2 +1002216e: 2758 movs r7, #88 ; 0x58 +10022170: fb07 4708 mla r7, r7, r8, r4 +10022174: f507 77b8 add.w r7, r7, #368 ; 0x170 +10022178: 07d2 lsls r2, r2, #31 +1002217a: f887 803b strb.w r8, [r7, #59] ; 0x3b +1002217e: f887 e038 strb.w lr, [r7, #56] ; 0x38 +10022182: f887 6037 strb.w r6, [r7, #55] ; 0x37 +10022186: d414 bmi.n 100221b2 +10022188: 7038 strb r0, [r7, #0] +1002218a: f887 3035 strb.w r3, [r7, #53] ; 0x35 +1002218e: f887 3036 strb.w r3, [r7, #54] ; 0x36 +10022192: 73f9 strb r1, [r7, #15] +10022194: 2600 movs r6, #0 +10022196: 1970 adds r0, r6, r5 +10022198: 4631 mov r1, r6 +1002219a: 78c2 ldrb r2, [r0, #3] +1002219c: 4640 mov r0, r8 +1002219e: f7fe fbb3 bl 10020908 +100221a2: 1c76 adds r6, r6, #1 +100221a4: 2e04 cmp r6, #4 +100221a6: dbf6 blt.n 10022196 +100221a8: 4639 mov r1, r7 +100221aa: 4620 mov r0, r4 +100221ac: e8bd 41f0 ldmia.w sp!, {r4, r5, r6, r7, r8, lr} +100221b0: e700 b.n 10021fb4 +100221b2: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +100221b6 : +100221b6: b510 push {r4, lr} +100221b8: 0004 movs r4, r0 +100221ba: d014 beq.n 100221e6 +100221bc: 4608 mov r0, r1 +100221be: 280a cmp r0, #10 +100221c0: da11 bge.n 100221e6 +100221c2: 2358 movs r3, #88 ; 0x58 +100221c4: fb03 4000 mla r0, r3, r0, r4 +100221c8: f500 70b8 add.w r0, r0, #368 ; 0x170 +100221cc: 7342 strb r2, [r0, #13] +100221ce: f880 103b strb.w r1, [r0, #59] ; 0x3b +100221d2: f894 1123 ldrb.w r1, [r4, #291] ; 0x123 +100221d6: b131 cbz r1, 100221e6 +100221d8: 4601 mov r1, r0 +100221da: 4620 mov r0, r4 +100221dc: f7ff fd80 bl 10021ce0 +100221e0: 2000 movs r0, #0 +100221e2: f884 0123 strb.w r0, [r4, #291] ; 0x123 +100221e6: bd10 pop {r4, pc} + +100221e8 : +100221e8: b538 push {r3, r4, r5, lr} +100221ea: 460c mov r4, r1 +100221ec: 4615 mov r5, r2 +100221ee: 4601 mov r1, r0 +100221f0: 2205 movs r2, #5 +100221f2: 4628 mov r0, r5 +100221f4: f7ea f8a8 bl 1000c348 +100221f8: 4629 mov r1, r5 +100221fa: 4620 mov r0, r4 +100221fc: e8bd 4034 ldmia.w sp!, {r2, r4, r5, lr} +10022200: f7ed be99 b.w 1000ff36 + +10022204 : +10022204: b530 push {r4, r5, lr} +10022206: b089 sub sp, #36 ; 0x24 +10022208: f000 f982 bl 10022510 + +1002220c : +1002220c: 2020 movs r0, #32 +1002220e: f8ad 0014 strh.w r0, [sp, #20] +10022212: 9504 str r5, [sp, #16] +10022214: aa00 add r2, sp, #0 +10022216: f648 311b movw r1, #35611 ; 0x8b1b +1002221a: f000 f9db bl 100225d4 + +1002221e : +1002221e: 2800 cmp r0, #0 +10022220: d506 bpl.n 10022230 +10022222: f20f 6098 addw r0, pc, #1688 ; 0x698 +10022226: f7ea f86c bl 1000c302 +1002222a: f04f 30ff mov.w r0, #4294967295 +1002222e: e00d b.n 1002224c + +10022230 : +10022230: f8bd 0014 ldrh.w r0, [sp, #20] +10022234: 2821 cmp r0, #33 ; 0x21 +10022236: bfac ite ge +10022238: 2020 movge r0, #32 +1002223a: 2801 cmplt r0, #1 +1002223c: db04 blt.n 10022248 +1002223e: 1941 adds r1, r0, r5 +10022240: f811 1c01 ldrb.w r1, [r1, #-1] +10022244: b901 cbnz r1, 10022248 +10022246: 1e40 subs r0, r0, #1 + +10022248 : +10022248: 2100 movs r1, #0 +1002224a: 5541 strb r1, [r0, r5] + +1002224c : +1002224c: b009 add sp, #36 ; 0x24 +1002224e: bd30 pop {r4, r5, pc} + +10022250 : +10022250: b5f0 push {r4, r5, r6, r7, lr} +10022252: b089 sub sp, #36 ; 0x24 +10022254: f000 f93a bl 100224cc + +10022258 : +10022258: f000 f933 bl 100224c2 + +1002225c : +1002225c: bf18 it ne +1002225e: 2001 movne r0, #1 +10022260: f8ad 0016 strh.w r0, [sp, #22] +10022264: aa00 add r2, sp, #0 +10022266: f648 311a movw r1, #35610 ; 0x8b1a +1002226a: f000 f9b3 bl 100225d4 + +1002226e : +1002226e: 2800 cmp r0, #0 +10022270: d505 bpl.n 1002227e +10022272: f20f 607c addw r0, pc, #1660 ; 0x67c +10022276: f7ea f844 bl 1000c302 +1002227a: f04f 37ff mov.w r7, #4294967295 + +1002227e : +1002227e: e11d b.n 100224bc + +10022280 : +10022280: b570 push {r4, r5, r6, lr} +10022282: b088 sub sp, #32 +10022284: f000 f9a8 bl 100225d8 + +10022288 : +10022288: 2001 movs r0, #1 +1002228a: f88d 0011 strb.w r0, [sp, #17] +1002228e: 2206 movs r2, #6 +10022290: 4629 mov r1, r5 +10022292: f10d 0012 add.w r0, sp, #18 +10022296: f7ea f857 bl 1000c348 +1002229a: 79a8 ldrb r0, [r5, #6] +1002229c: 2823 cmp r0, #35 ; 0x23 +1002229e: bf04 itt eq +100222a0: 79e8 ldrbeq r0, [r5, #7] +100222a2: 2840 cmpeq r0, #64 ; 0x40 +100222a4: d104 bne.n 100222b0 +100222a6: 2206 movs r2, #6 +100222a8: 1da9 adds r1, r5, #6 +100222aa: a806 add r0, sp, #24 +100222ac: f7ea f84c bl 1000c348 + +100222b0 : +100222b0: aa00 add r2, sp, #0 +100222b2: f648 3114 movw r1, #35604 ; 0x8b14 +100222b6: f000 f98d bl 100225d4 + +100222ba : +100222ba: 2800 cmp r0, #0 +100222bc: d505 bpl.n 100222ca +100222be: f20f 604c addw r0, pc, #1612 ; 0x64c +100222c2: f7ea f81e bl 1000c302 +100222c6: f04f 36ff mov.w r6, #4294967295 + +100222ca : +100222ca: e13a b.n 10022542 + +100222cc : +100222cc: 7801 ldrb r1, [r0, #0] +100222ce: 7842 ldrb r2, [r0, #1] +100222d0: 4011 ands r1, r2 +100222d2: 7882 ldrb r2, [r0, #2] +100222d4: 4011 ands r1, r2 +100222d6: 78c2 ldrb r2, [r0, #3] +100222d8: 4011 ands r1, r2 +100222da: 7902 ldrb r2, [r0, #4] +100222dc: 7940 ldrb r0, [r0, #5] +100222de: 4011 ands r1, r2 +100222e0: 4008 ands r0, r1 +100222e2: 28ff cmp r0, #255 ; 0xff +100222e4: d101 bne.n 100222ea +100222e6: 2001 movs r0, #1 +100222e8: 4770 bx lr + +100222ea : +100222ea: 2000 movs r0, #0 +100222ec: 4770 bx lr + +100222ee : +100222ee: b570 push {r4, r5, r6, lr} +100222f0: b088 sub sp, #32 +100222f2: 4604 mov r4, r0 +100222f4: 460d mov r5, r1 +100222f6: 4616 mov r6, r2 +100222f8: f000 fada bl 100228b0 + +100222fc : +100222fc: 0528 lsls r0, r5, #20 +100222fe: 0d00 lsrs r0, r0, #20 +10022300: f8ad 0016 strh.w r0, [sp, #22] +10022304: 9604 str r6, [sp, #16] +10022306: aa00 add r2, sp, #0 +10022308: f648 3132 movw r1, #35634 ; 0x8b32 +1002230c: f000 f962 bl 100225d4 + +10022310 : +10022310: 2800 cmp r0, #0 +10022312: d505 bpl.n 10022320 +10022314: 4632 mov r2, r6 +10022316: 4629 mov r1, r5 +10022318: f20f 600c addw r0, pc, #1548 ; 0x60c +1002231c: f7e9 fff1 bl 1000c302 + +10022320 : +10022320: 2000 movs r0, #0 +10022322: b008 add sp, #32 +10022324: bd70 pop {r4, r5, r6, pc} + +10022326 : +10022326: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +1002232a: b089 sub sp, #36 ; 0x24 +1002232c: 4681 mov r9, r0 +1002232e: 9c16 ldr r4, [sp, #88] ; 0x58 +10022330: f104 0b28 add.w fp, r4, #40 ; 0x28 +10022334: 460e mov r6, r1 +10022336: 4617 mov r7, r2 +10022338: 469a mov sl, r3 +1002233a: f04f 0800 mov.w r8, #0 +1002233e: 4658 mov r0, fp +10022340: f7ea fab8 bl 1000c8b4 +10022344: 0005 movs r5, r0 +10022346: bf08 it eq +10022348: f04f 30ff moveq.w r0, #4294967295 +1002234c: d066 beq.n 1002241c +1002234e: 465a mov r2, fp +10022350: f000 f9ea bl 10022728 + +10022354 : +10022354: 2220 movs r2, #32 +10022356: 4641 mov r1, r8 +10022358: a800 add r0, sp, #0 +1002235a: f7e9 fff7 bl 1000c34c +1002235e: f10a 0001 add.w r0, sl, #1 +10022362: f440 6080 orr.w r0, r0, #1024 ; 0x400 +10022366: f8ad 0016 strh.w r0, [sp, #22] +1002236a: 9504 str r5, [sp, #16] +1002236c: f104 0028 add.w r0, r4, #40 ; 0x28 +10022370: f8ad 0014 strh.w r0, [sp, #20] +10022374: f5b6 4f00 cmp.w r6, #32768 ; 0x8000 +10022378: d105 bne.n 10022386 +1002237a: f8bd 0016 ldrh.w r0, [sp, #22] +1002237e: f440 4000 orr.w r0, r0, #32768 ; 0x8000 +10022382: f8ad 0016 strh.w r0, [sp, #22] + +10022386 : +10022386: b11f cbz r7, 10022390 +10022388: 4638 mov r0, r7 +1002238a: f7ff ff9f bl 100222cc +1002238e: b118 cbz r0, 10022398 + +10022390 : +10022390: 6828 ldr r0, [r5, #0] +10022392: f040 0004 orr.w r0, r0, #4 +10022396: 6028 str r0, [r5, #0] + +10022398 : +10022398: 9812 ldr r0, [sp, #72] ; 0x48 +1002239a: b118 cbz r0, 100223a4 +1002239c: 6828 ldr r0, [r5, #0] +1002239e: f040 0008 orr.w r0, r0, #8 +100223a2: 6028 str r0, [r5, #0] + +100223a4 : +100223a4: 2001 movs r0, #1 +100223a6: 7568 strb r0, [r5, #21] +100223a8: b137 cbz r7, 100223b8 +100223aa: 2206 movs r2, #6 +100223ac: 4639 mov r1, r7 +100223ae: f105 0016 add.w r0, r5, #22 +100223b2: f7e9 ffc9 bl 1000c348 +100223b6: e005 b.n 100223c4 + +100223b8 : +100223b8: 2206 movs r2, #6 +100223ba: 21ff movs r1, #255 ; 0xff +100223bc: f105 0016 add.w r0, r5, #22 +100223c0: f7e9 ffc4 bl 1000c34c + +100223c4 : +100223c4: 9915 ldr r1, [sp, #84] ; 0x54 +100223c6: 2900 cmp r1, #0 +100223c8: bf18 it ne +100223ca: 2c00 cmpne r4, #0 +100223cc: d005 beq.n 100223da +100223ce: 4622 mov r2, r4 +100223d0: f105 0028 add.w r0, r5, #40 ; 0x28 +100223d4: f7e9 ffb8 bl 1000c348 +100223d8: 84ec strh r4, [r5, #38] ; 0x26 + +100223da : +100223da: 84ae strh r6, [r5, #36] ; 0x24 +100223dc: 9913 ldr r1, [sp, #76] ; 0x4c +100223de: 2900 cmp r1, #0 +100223e0: bf1c itt ne +100223e2: 9a14 ldrne r2, [sp, #80] ; 0x50 +100223e4: 2a00 cmpne r2, #0 +100223e6: d007 beq.n 100223f8 +100223e8: 6828 ldr r0, [r5, #0] +100223ea: f040 0002 orr.w r0, r0, #2 +100223ee: 6028 str r0, [r5, #0] +100223f0: f105 000c add.w r0, r5, #12 +100223f4: f7e9 ffa8 bl 1000c348 + +100223f8 : +100223f8: aa00 add r2, sp, #0 +100223fa: f648 3134 movw r1, #35636 ; 0x8b34 +100223fe: 4648 mov r0, r9 +10022400: f7ff fef2 bl 100221e8 +10022404: 2800 cmp r0, #0 +10022406: d505 bpl.n 10022414 +10022408: f06f 0801 mvn.w r8, #1 +1002240c: f20f 504c addw r0, pc, #1356 ; 0x54c +10022410: f7e9 ff77 bl 1000c302 + +10022414 : +10022414: 4628 mov r0, r5 +10022416: f7ea fad4 bl 1000c9c2 +1002241a: 4640 mov r0, r8 + +1002241c : +1002241c: b009 add sp, #36 ; 0x24 +1002241e: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +10022422 : +10022422: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} +10022426: 4680 mov r8, r0 +10022428: b089 sub sp, #36 ; 0x24 +1002242a: 4689 mov r9, r1 +1002242c: 4616 mov r6, r2 +1002242e: 461f mov r7, r3 +10022430: 2500 movs r5, #0 +10022432: 2038 movs r0, #56 ; 0x38 +10022434: f7ea fa3e bl 1000c8b4 +10022438: 0004 movs r4, r0 +1002243a: bf08 it eq +1002243c: f04f 30ff moveq.w r0, #4294967295 +10022440: d024 beq.n 1002248c +10022442: 2238 movs r2, #56 ; 0x38 +10022444: f000 f970 bl 10022728 + +10022448 : +10022448: 9404 str r4, [sp, #16] +1002244a: aa00 add r2, sp, #0 +1002244c: f648 3135 movw r1, #35637 ; 0x8b35 +10022450: 4640 mov r0, r8 +10022452: f7ff fec9 bl 100221e8 +10022456: 2800 cmp r0, #0 +10022458: d506 bpl.n 10022468 +1002245a: f20f 5028 addw r0, pc, #1320 ; 0x528 +1002245e: f7e9 ff50 bl 1000c302 +10022462: f04f 35ff mov.w r5, #4294967295 +10022466: e00d b.n 10022484 + +10022468 : +10022468: 8ca0 ldrh r0, [r4, #36] ; 0x24 +1002246a: f8a9 0000 strh.w r0, [r9] +1002246e: b116 cbz r6, 10022476 +10022470: f8bd 0016 ldrh.w r0, [sp, #22] +10022474: 7030 strb r0, [r6, #0] + +10022476 : +10022476: b12f cbz r7, 10022484 +10022478: f104 0128 add.w r1, r4, #40 ; 0x28 +1002247c: 8ce2 ldrh r2, [r4, #38] ; 0x26 +1002247e: 4638 mov r0, r7 +10022480: f7e9 ff62 bl 1000c348 + +10022484 : +10022484: 4620 mov r0, r4 +10022486: f7ea fa9c bl 1000c9c2 +1002248a: 4628 mov r0, r5 + +1002248c : +1002248c: e149 b.n 10022722 + +1002248e : +1002248e: b5f0 push {r4, r5, r6, r7, lr} +10022490: b089 sub sp, #36 ; 0x24 +10022492: f000 f81b bl 100224cc + +10022496 : +10022496: f000 f814 bl 100224c2 + +1002249a : +1002249a: bf18 it ne +1002249c: 2001 movne r0, #1 +1002249e: f8ad 0016 strh.w r0, [sp, #22] +100224a2: aa00 add r2, sp, #0 +100224a4: f648 31ff movw r1, #35839 ; 0x8bff +100224a8: f000 f894 bl 100225d4 + +100224ac : +100224ac: 2800 cmp r0, #0 +100224ae: d505 bpl.n 100224bc +100224b0: f20f 40f0 addw r0, pc, #1264 ; 0x4f0 +100224b4: f7e9 ff25 bl 1000c302 +100224b8: f04f 37ff mov.w r7, #4294967295 + +100224bc : +100224bc: 4638 mov r0, r7 +100224be: b009 add sp, #36 ; 0x24 +100224c0: bdf0 pop {r4, r5, r6, r7, pc} + +100224c2 : +100224c2: 9504 str r5, [sp, #16] +100224c4: f8ad 6014 strh.w r6, [sp, #20] +100224c8: 0030 movs r0, r6 +100224ca: 4770 bx lr + +100224cc : +100224cc: 4604 mov r4, r0 +100224ce: 460d mov r5, r1 +100224d0: 4616 mov r6, r2 +100224d2: 2700 movs r7, #0 +100224d4: 2220 movs r2, #32 +100224d6: 2100 movs r1, #0 +100224d8: a800 add r0, sp, #0 +100224da: f7e9 bf37 b.w 1000c34c + +100224de : +100224de: b530 push {r4, r5, lr} +100224e0: b089 sub sp, #36 ; 0x24 +100224e2: f000 f815 bl 10022510 + +100224e6 : +100224e6: 9504 str r5, [sp, #16] +100224e8: aa00 add r2, sp, #0 +100224ea: f648 31fc movw r1, #35836 ; 0x8bfc +100224ee: f000 f871 bl 100225d4 + +100224f2 : +100224f2: 2800 cmp r0, #0 +100224f4: d506 bpl.n 10022504 +100224f6: f20f 40d0 addw r0, pc, #1232 ; 0x4d0 +100224fa: f7e9 ff02 bl 1000c302 +100224fe: f04f 30ff mov.w r0, #4294967295 +10022502: e003 b.n 1002250c + +10022504 : +10022504: f8bd 0014 ldrh.w r0, [sp, #20] +10022508: 2100 movs r1, #0 +1002250a: 5541 strb r1, [r0, r5] + +1002250c : +1002250c: b009 add sp, #36 ; 0x24 +1002250e: bd30 pop {r4, r5, pc} + +10022510 : +10022510: 4604 mov r4, r0 +10022512: 460d mov r5, r1 +10022514: 2220 movs r2, #32 +10022516: 2100 movs r1, #0 +10022518: a800 add r0, sp, #0 +1002251a: f7e9 bf17 b.w 1000c34c + +1002251e : +1002251e: b570 push {r4, r5, r6, lr} +10022520: b088 sub sp, #32 +10022522: f000 f859 bl 100225d8 + +10022526 : +10022526: 9504 str r5, [sp, #16] +10022528: aa00 add r2, sp, #0 +1002252a: f648 3106 movw r1, #35590 ; 0x8b06 +1002252e: f000 f851 bl 100225d4 + +10022532 : +10022532: 2800 cmp r0, #0 +10022534: d505 bpl.n 10022542 +10022536: f20f 40dc addw r0, pc, #1244 ; 0x4dc +1002253a: f7e9 fee2 bl 1000c302 +1002253e: f04f 36ff mov.w r6, #4294967295 + +10022542 : +10022542: 4630 mov r0, r6 +10022544: b008 add sp, #32 +10022546: bd70 pop {r4, r5, r6, pc} + +10022548 : +10022548: b570 push {r4, r5, r6, lr} +1002254a: b088 sub sp, #32 +1002254c: f000 f844 bl 100225d8 + +10022550 : +10022550: aa00 add r2, sp, #0 +10022552: f648 3107 movw r1, #35591 ; 0x8b07 +10022556: f000 f83d bl 100225d4 + +1002255a : +1002255a: 2800 cmp r0, #0 +1002255c: d506 bpl.n 1002256c +1002255e: f20f 40d0 addw r0, pc, #1232 ; 0x4d0 +10022562: f7e9 fece bl 1000c302 +10022566: f04f 36ff mov.w r6, #4294967295 +1002256a: e001 b.n 10022570 + +1002256c : +1002256c: 9804 ldr r0, [sp, #16] +1002256e: 6028 str r0, [r5, #0] + +10022570 : +10022570: e7e7 b.n 10022542 + +10022572 : +10022572: b5f0 push {r4, r5, r6, r7, lr} +10022574: b089 sub sp, #36 ; 0x24 +10022576: f7ff ffa9 bl 100224cc + +1002257a : +1002257a: f7ff ffa2 bl 100224c2 + +1002257e : +1002257e: bf18 it ne +10022580: 2001 movne r0, #1 +10022582: f8ad 0016 strh.w r0, [sp, #22] +10022586: aa00 add r2, sp, #0 +10022588: f648 31fe movw r1, #35838 ; 0x8bfe +1002258c: f000 f822 bl 100225d4 + +10022590 : +10022590: 2800 cmp r0, #0 +10022592: d505 bpl.n 100225a0 +10022594: f20f 4058 addw r0, pc, #1112 ; 0x458 +10022598: f7e9 feb3 bl 1000c302 +1002259c: f04f 37ff mov.w r7, #4294967295 + +100225a0 : +100225a0: e78c b.n 100224bc + +100225a2 : +100225a2: b570 push {r4, r5, r6, lr} +100225a4: b088 sub sp, #32 +100225a6: f000 f817 bl 100225d8 + +100225aa : +100225aa: aa00 add r2, sp, #0 +100225ac: f648 3109 movw r1, #35593 ; 0x8b09 +100225b0: f000 f810 bl 100225d4 + +100225b4 : +100225b4: 2800 cmp r0, #0 +100225b6: d506 bpl.n 100225c6 +100225b8: f20f 4090 addw r0, pc, #1168 ; 0x490 +100225bc: f7e9 fea1 bl 1000c302 +100225c0: f04f 36ff mov.w r6, #4294967295 +100225c4: e002 b.n 100225cc + +100225c6 : +100225c6: 9804 ldr r0, [sp, #16] +100225c8: 4240 negs r0, r0 +100225ca: 6028 str r0, [r5, #0] + +100225cc : +100225cc: e7b9 b.n 10022542 + +100225ce : +100225ce: aa00 add r2, sp, #0 +100225d0: f648 11f0 movw r1, #35312 ; 0x89f0 + +100225d4 : +100225d4: 4620 mov r0, r4 +100225d6: e607 b.n 100221e8 + +100225d8 : +100225d8: 4604 mov r4, r0 +100225da: 460d mov r5, r1 +100225dc: 2600 movs r6, #0 +100225de: 2220 movs r2, #32 +100225e0: 2100 movs r1, #0 +100225e2: a800 add r0, sp, #0 +100225e4: f7e9 beb2 b.w 1000c34c + +100225e8 : +100225e8: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +100225ec: b088 sub sp, #32 +100225ee: 4682 mov sl, r0 +100225f0: 4688 mov r8, r1 +100225f2: 4691 mov r9, r2 +100225f4: 2500 movs r5, #0 +100225f6: 461f mov r7, r3 +100225f8: 2400 movs r4, #0 +100225fa: 2220 movs r2, #32 +100225fc: 4629 mov r1, r5 +100225fe: a800 add r0, sp, #0 +10022600: f7e9 fea4 bl 1000c34c +10022604: 0078 lsls r0, r7, #1 +10022606: 300d adds r0, #13 +10022608: f7ea f954 bl 1000c8b4 +1002260c: 4606 mov r6, r0 +1002260e: f20f 4258 addw r2, pc, #1112 ; 0x458 +10022612: 210c movs r1, #12 +10022614: f7e9 fe0c bl 1000c230 +10022618: 7337 strb r7, [r6, #12] +1002261a: e00a b.n 10022632 + +1002261c : +1002261c: f814 0008 ldrb.w r0, [r4, r8] +10022620: 19a1 adds r1, r4, r6 +10022622: 7348 strb r0, [r1, #13] +10022624: 19b9 adds r1, r7, r6 +10022626: f814 0009 ldrb.w r0, [r4, r9] +1002262a: 1861 adds r1, r4, r1 +1002262c: 1c64 adds r4, r4, #1 +1002262e: f8a1 000d strh.w r0, [r1, #13] + +10022632 : +10022632: 42bc cmp r4, r7 +10022634: dbf2 blt.n 1002261c +10022636: 0078 lsls r0, r7, #1 +10022638: 300d adds r0, #13 +1002263a: f8ad 0014 strh.w r0, [sp, #20] +1002263e: 9604 str r6, [sp, #16] +10022640: aa00 add r2, sp, #0 +10022642: f648 11f0 movw r1, #35312 ; 0x89f0 +10022646: 4650 mov r0, sl +10022648: f7ff fdce bl 100221e8 +1002264c: 2800 cmp r0, #0 +1002264e: d505 bpl.n 1002265c +10022650: f20f 4020 addw r0, pc, #1056 ; 0x420 +10022654: f7e9 fe55 bl 1000c302 +10022658: f04f 35ff mov.w r5, #4294967295 + +1002265c : +1002265c: 4630 mov r0, r6 +1002265e: f7ea f9b0 bl 1000c9c2 +10022662: 4628 mov r0, r5 +10022664: b008 add sp, #32 +10022666: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + +1002266a : +1002266a: b570 push {r4, r5, r6, lr} +1002266c: b088 sub sp, #32 +1002266e: f7ff ffb3 bl 100225d8 + +10022672 : +10022672: 9604 str r6, [sp, #16] +10022674: f8ad 6014 strh.w r6, [sp, #20] +10022678: f88d 5016 strb.w r5, [sp, #22] +1002267c: aa00 add r2, sp, #0 +1002267e: f648 3104 movw r1, #35588 ; 0x8b04 +10022682: f7ff ffa7 bl 100225d4 + +10022686 : +10022686: 2800 cmp r0, #0 +10022688: d505 bpl.n 10022696 +1002268a: f20f 4020 addw r0, pc, #1056 ; 0x420 +1002268e: f7e9 fe38 bl 1000c302 +10022692: f04f 36ff mov.w r6, #4294967295 + +10022696 : +10022696: e754 b.n 10022542 + +10022698 : +10022698: b570 push {r4, r5, r6, lr} +1002269a: b088 sub sp, #32 +1002269c: f7ff ff9c bl 100225d8 + +100226a0 : +100226a0: aa00 add r2, sp, #0 +100226a2: f648 3105 movw r1, #35589 ; 0x8b05 +100226a6: f7ff ff95 bl 100225d4 + +100226aa : +100226aa: 2800 cmp r0, #0 +100226ac: d506 bpl.n 100226bc +100226ae: f20f 4018 addw r0, pc, #1048 ; 0x418 +100226b2: f7e9 fe26 bl 1000c302 +100226b6: f04f 36ff mov.w r6, #4294967295 +100226ba: e002 b.n 100226c2 + +100226bc : +100226bc: f89d 0016 ldrb.w r0, [sp, #22] +100226c0: 7028 strb r0, [r5, #0] + +100226c2 : +100226c2: e73e b.n 10022542 + +100226c4 : +100226c4: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +100226c8: b088 sub sp, #32 +100226ca: f000 f8e1 bl 10022890 + +100226ce : +100226ce: 9504 str r5, [sp, #16] +100226d0: f8ad 8016 strh.w r8, [sp, #22] +100226d4: f8ad 6014 strh.w r6, [sp, #20] +100226d8: aa00 add r2, sp, #0 +100226da: f648 3118 movw r1, #35608 ; 0x8b18 +100226de: f7ff ff79 bl 100225d4 + +100226e2 : +100226e2: 2800 cmp r0, #0 +100226e4: d505 bpl.n 100226f2 +100226e6: f20f 30fc addw r0, pc, #1020 ; 0x3fc +100226ea: f7e9 fe0a bl 1000c302 +100226ee: f04f 37ff mov.w r7, #4294967295 + +100226f2 : +100226f2: e0c9 b.n 10022888 + +100226f4 : +100226f4: b500 push {lr} +100226f6: b089 sub sp, #36 ; 0x24 +100226f8: 9104 str r1, [sp, #16] +100226fa: f8ad 2014 strh.w r2, [sp, #20] +100226fe: f648 3119 movw r1, #35609 ; 0x8b19 +10022702: aa00 add r2, sp, #0 +10022704: f7ff fd70 bl 100221e8 +10022708: 2800 cmp r0, #0 +1002270a: d506 bpl.n 1002271a +1002270c: f20f 30f0 addw r0, pc, #1008 ; 0x3f0 +10022710: f7e9 fdf7 bl 1000c302 +10022714: f04f 30ff mov.w r0, #4294967295 +10022718: e001 b.n 1002271e + +1002271a : +1002271a: f8bd 0016 ldrh.w r0, [sp, #22] + +1002271e : +1002271e: b009 add sp, #36 ; 0x24 +10022720: bd00 pop {pc} + +10022722 : +10022722: b009 add sp, #36 ; 0x24 +10022724: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + +10022728 : +10022728: 2100 movs r1, #0 +1002272a: f7e9 be0f b.w 1000c34c + +1002272e : +1002272e: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +10022732: 4607 mov r7, r0 +10022734: 4688 mov r8, r1 +10022736: b088 sub sp, #32 +10022738: 4614 mov r4, r2 +1002273a: f44f 6500 mov.w r5, #2048 ; 0x800 +1002273e: f000 f840 bl 100227c2 + +10022742 : +10022742: f5b0 6f00 cmp.w r0, #2048 ; 0x800 +10022746: d302 bcc.n 1002274e +10022748: f000 f83b bl 100227c2 + +1002274c : +1002274c: 1c45 adds r5, r0, #1 + +1002274e : +1002274e: 4628 mov r0, r5 +10022750: f7ea f8b0 bl 1000c8b4 +10022754: 0006 movs r6, r0 +10022756: d106 bne.n 10022766 +10022758: f20f 30c0 addw r0, pc, #960 ; 0x3c0 +1002275c: f7e9 fdd1 bl 1000c302 +10022760: f04f 30ff mov.w r0, #4294967295 +10022764: e02c b.n 100227c0 + +10022766 : +10022766: 462a mov r2, r5 +10022768: f7ff ffde bl 10022728 + +1002276c : +1002276c: 4641 mov r1, r8 +1002276e: 4630 mov r0, r6 +10022770: f7e9 fdf0 bl 1000c354 +10022774: f000 f89c bl 100228b0 + +10022778 : +10022778: 2000 movs r0, #0 +1002277a: f8ad 0016 strh.w r0, [sp, #22] +1002277e: 9604 str r6, [sp, #16] +10022780: f8ad 5014 strh.w r5, [sp, #20] +10022784: f000 f88e bl 100228a4 + +10022788 : +10022788: 0007 movs r7, r0 +1002278a: d504 bpl.n 10022796 +1002278c: 4639 mov r1, r7 +1002278e: f20f 30a8 addw r0, pc, #936 ; 0x3a8 +10022792: f7e9 fdb6 bl 1000c302 + +10022796 : +10022796: 2c00 cmp r4, #0 +10022798: bf1c itt ne +1002279a: f8bd 0014 ldrhne.w r0, [sp, #20] +1002279e: 2800 cmpne r0, #0 +100227a0: d00a beq.n 100227b8 +100227a2: 4285 cmp r5, r0 +100227a4: bfbc itt lt +100227a6: f20f 30b8 addwlt r0, pc, #952 ; 0x3b8 +100227aa: f7e9 fdaa bllt 1000c302 +100227ae: 9904 ldr r1, [sp, #16] +100227b0: f20f 30d0 addw r0, pc, #976 ; 0x3d0 +100227b4: f7e9 fda5 bl 1000c302 + +100227b8 : +100227b8: 4630 mov r0, r6 +100227ba: f7ea f902 bl 1000c9c2 +100227be: 4638 mov r0, r7 + +100227c0 : +100227c0: e063 b.n 1002288a + +100227c2 : +100227c2: 4640 mov r0, r8 +100227c4: f7e9 bdc8 b.w 1000c358 + +100227c8 : +100227c8: b530 push {r4, r5, lr} +100227ca: b083 sub sp, #12 +100227cc: 460d mov r5, r1 +100227ce: 4614 mov r4, r2 +100227d0: a900 add r1, sp, #0 +100227d2: 2200 movs r2, #0 +100227d4: 2300 movs r3, #0 +100227d6: c10c stmia r1!, {r2, r3} +100227d8: f648 3115 movw r1, #35605 ; 0x8b15 +100227dc: 1a40 subs r0, r0, r1 +100227de: d004 beq.n 100227ea +100227e0: 1f00 subs r0, r0, #4 +100227e2: d041 beq.n 10022868 +100227e4: 38e9 subs r0, #233 ; 0xe9 +100227e6: d013 beq.n 10022810 +100227e8: bd37 pop {r0, r1, r2, r4, r5, pc} + +100227ea : +100227ea: 7868 ldrb r0, [r5, #1] +100227ec: 2801 cmp r0, #1 +100227ee: d142 bne.n 10022876 +100227f0: 2206 movs r2, #6 +100227f2: a900 add r1, sp, #0 +100227f4: 1ca8 adds r0, r5, #2 +100227f6: f7e9 fda5 bl 1000c344 +100227fa: b920 cbnz r0, 10022806 +100227fc: 2200 movs r2, #0 +100227fe: 2300 movs r3, #0 +10022800: 4611 mov r1, r2 +10022802: 2001 movs r0, #1 +10022804: e035 b.n 10022872 + +10022806 : +10022806: 2300 movs r3, #0 +10022808: 2206 movs r2, #6 +1002280a: 1ca9 adds r1, r5, #2 +1002280c: 2000 movs r0, #0 +1002280e: e030 b.n 10022872 + +10022810 : +10022810: 2c00 cmp r4, #0 +10022812: d030 beq.n 10022876 +10022814: f20f 3584 addw r5, pc, #900 ; 0x384 +10022818: f000 f833 bl 10022882 + +1002281c : +1002281c: f000 f82c bl 10022878 + +10022820 : +10022820: b930 cbnz r0, 10022830 +10022822: f000 f82e bl 10022882 + +10022826 : +10022826: 4602 mov r2, r0 +10022828: 2300 movs r3, #0 +1002282a: 4621 mov r1, r4 +1002282c: 2002 movs r0, #2 +1002282e: e020 b.n 10022872 + +10022830 : +10022830: f20f 3580 addw r5, pc, #896 ; 0x380 +10022834: f000 f825 bl 10022882 + +10022838 : +10022838: f000 f81e bl 10022878 + +1002283c : +1002283c: b930 cbnz r0, 1002284c +1002283e: f000 f820 bl 10022882 + +10022842 : +10022842: 4602 mov r2, r0 +10022844: 2300 movs r3, #0 +10022846: 4621 mov r1, r4 +10022848: 2005 movs r0, #5 +1002284a: e012 b.n 10022872 + +1002284c : +1002284c: f20f 357c addw r5, pc, #892 ; 0x37c +10022850: f000 f817 bl 10022882 + +10022854 : +10022854: f000 f810 bl 10022878 + +10022858 : +10022858: b968 cbnz r0, 10022876 +1002285a: f000 f812 bl 10022882 + +1002285e : +1002285e: 4602 mov r2, r0 +10022860: 2300 movs r3, #0 +10022862: 4621 mov r1, r4 +10022864: 200c movs r0, #12 +10022866: e004 b.n 10022872 + +10022868 : +10022868: 6829 ldr r1, [r5, #0] +1002286a: 2900 cmp r1, #0 +1002286c: bf0c ite eq +1002286e: 2004 moveq r0, #4 +10022870: 2003 movne r0, #3 + +10022872 : +10022872: f00d facb bl 1002fe0c + +10022876 : +10022876: bd37 pop {r0, r1, r2, r4, r5, pc} + +10022878 : +10022878: 4602 mov r2, r0 +1002287a: 4621 mov r1, r4 +1002287c: 4628 mov r0, r5 +1002287e: f7e9 bd61 b.w 1000c344 + +10022882 : +10022882: 4628 mov r0, r5 +10022884: f7e9 bd68 b.w 1000c358 + +10022888 : +10022888: 4638 mov r0, r7 + +1002288a : +1002288a: b008 add sp, #32 +1002288c: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +10022890 : +10022890: 4604 mov r4, r0 +10022892: 460d mov r5, r1 +10022894: 4616 mov r6, r2 +10022896: 4698 mov r8, r3 +10022898: 2700 movs r7, #0 +1002289a: 2220 movs r2, #32 +1002289c: 2100 movs r1, #0 +1002289e: a800 add r0, sp, #0 +100228a0: f7e9 bd54 b.w 1000c34c + +100228a4 : +100228a4: aa00 add r2, sp, #0 +100228a6: f648 11f0 movw r1, #35312 ; 0x89f0 +100228aa: 4638 mov r0, r7 +100228ac: f7ff bc9c b.w 100221e8 + +100228b0 : +100228b0: 2220 movs r2, #32 +100228b2: 2100 movs r1, #0 +100228b4: a800 add r0, sp, #0 +100228b6: f7e9 bd49 b.w 1000c34c + ... + +100228bc : +100228bc: 0d0a 6f69 7463 5b6c 4953 434f 4947 4557 ..ioctl[SIOCGIWE +100228cc: 5353 4449 205d 7373 6469 3d20 4e20 4c55 SSID] ssid = NUL +100228dc: 2c4c 6e20 746f 6320 6e6f 656e 7463 6465 L, not connected +100228ec: 0000 0000 .... + +100228f0 : +100228f0: 0d0a 6f69 7463 5b6c 4953 434f 4953 4557 ..ioctl[SIOCSIWE +10022900: 5353 4449 205d 7265 6f72 0072 SSID] error. + +1002290c : +1002290c: 0d0a 6f69 7463 5b6c 4953 434f 4953 4157 ..ioctl[SIOCSIWA +1002291c: 5d50 6520 7272 726f 0000 0000 P] error.... + +10022928 : +10022928: 0d0a 4557 5458 203a 4953 434f 4953 4157 ..WEXT: SIOCSIWA +10022938: 5455 2848 6170 6172 206d 6425 7620 6c61 UTH(param %d val +10022948: 6575 3020 2578 2978 6620 6961 656c 2964 ue 0x%x) failed) +10022958: 0000 0000 .... + +1002295c : +1002295c: 0d0a 6f69 7463 5b6c 4953 434f 4953 4557 ..ioctl[SIOCSIWE +1002296c: 434e 444f 4545 5458 205d 6573 2074 656b NCODEEXT] set ke +1002297c: 2079 6166 6c69 0000 y fail.. + +10022984 : +10022984: 0d0a 6f69 7463 5b6c 4953 434f 4947 4557 ..ioctl[SIOCGIWE +10022994: 434e 444f 4545 5458 205d 7265 6f72 0072 NCODEEXT] error. + +100229a4 : +100229a4: 0d0a 6f69 7463 5b6c 4953 434f 4953 4557 ..ioctl[SIOCSIWE +100229b4: 5353 4449 302b 3178 5d66 6520 7272 726f SSID+0x1f] error +100229c4: 0000 0000 .... + +100229c8 : +100229c8: 0d0a 6f69 7463 5b6c 4953 434f 4947 5057 ..ioctl[SIOCGIWP +100229d8: 4952 5056 5341 5053 5248 5341 5d45 6520 RIVPASSPHRASE] e +100229e8: 7272 726f 0000 0000 rror.... + +100229f0 : +100229f0: 0d0a 6f69 7463 5b6c 4953 434f 4953 5057 ..ioctl[SIOCSIWP +10022a00: 4952 4156 4550 5353 4449 205d 7265 6f72 RIVAPESSID] erro +10022a10: 0072 0000 r... + +10022a14 : +10022a14: 0d0a 6f69 7463 5b6c 4953 434f 4953 4d57 ..ioctl[SIOCSIWM +10022a24: 444f 5d45 6520 7272 726f 0000 ODE] error.. + +10022a30 : +10022a30: 0d0a 6f69 7463 5b6c 4953 434f 4947 4d57 ..ioctl[SIOCGIWM +10022a40: 444f 5d45 6520 7272 726f 0000 ODE] error.. + +10022a4c : +10022a4c: 0d0a 6f69 7463 5b6c 4953 434f 4947 5357 ..ioctl[SIOCGIWS +10022a5c: 4e45 5d53 6520 7272 726f 0000 ENS] error.. + +10022a68 : +10022a68: 6150 7472 6169 536c 6163 006e PartialScan. + +10022a74 : +10022a74: 0d0a 6577 7478 735f 7465 705f 6373 6e61 ..wext_set_pscan +10022a84: 635f 6168 6e6e 6c65 2928 693a 636f 6c74 _channel():ioctl +10022a94: 535b 4f49 4443 5645 5250 5649 5441 5d45 [SIOCDEVPRIVATE] +10022aa4: 6520 7272 726f 0000 error.. + +10022aac : +10022aac: 0d0a 6f69 7463 5b6c 4953 434f 4953 4657 ..ioctl[SIOCSIWF +10022abc: 4552 5d51 6520 7272 726f 0000 REQ] error.. + +10022ac8 : +10022ac8: 0d0a 6f69 7463 5b6c 4953 434f 4947 4657 ..ioctl[SIOCGIWF +10022ad8: 4552 5d51 6520 7272 726f 0000 REQ] error.. + +10022ae4 : +10022ae4: 0d0a 6f69 7463 5b6c 4953 434f 4953 5357 ..ioctl[SIOCSIWS +10022af4: 4143 5d4e 6520 7272 726f 0000 CAN] error.. + +10022b00 : +10022b00: 0d0a 6f69 7463 5b6c 4953 434f 4947 5357 ..ioctl[SIOCGIWS +10022b10: 4143 5d4e 6520 7272 726f 0000 CAN] error.. + +10022b1c : +10022b1c: 0d0a 4557 5458 203a 6143 276e 2074 616d ..WEXT: Can't ma +10022b2c: 6c6c 636f 6d20 6d65 726f 0079 lloc memory. + +10022b38 : +10022b38: 0d0a 6f69 7463 5b6c 4953 434f 4544 5056 ..ioctl[SIOCDEVP +10022b48: 4952 4156 4554 205d 7265 6f72 2e72 7220 RIVATE] error. r +10022b58: 7465 253d 0a64 0000 et=%d... + +10022b60 : +10022b60: 0d0a 4557 5458 203a 614d 6c6c 636f 6d20 ..WEXT: Malloc m +10022b70: 6d65 726f 2079 7369 6e20 746f 6520 6f6e emory is not eno +10022b80: 6775 0068 ugh. + +10022b84 : +10022b84: 0d0a 7250 7669 7461 2065 654d 7373 6761 ..Private Messag +10022b94: 3a65 2520 0073 0000 e: %s... + +10022b9c : +10022b9c: 5057 2f41 5057 3241 6820 6e61 7364 6168 WPA/WPA2 handsha +10022bac: 656b 6420 6e6f 0065 ke done. + +10022bb4 : +10022bb4: 4552 4f43 4e4e 4345 4954 4e4f 4620 4941 RECONNECTION FAI +10022bc4: 554c 4552 0000 0000 LURE.... + +10022bcc : +10022bcc: 6f4e 4120 7373 636f 4e20 7465 6f77 6b72 No Assoc Network +10022bdc: 4120 7466 7265 5320 6163 206e 6f44 656e After Scan Done +10022bec: 0000 0000 .... + +10022bf0 : +10022bf0: 6840 ldr r0, [r0, #4] +10022bf2: 4208 tst r0, r1 +10022bf4: d001 beq.n 10022bfa +10022bf6: 2001 movs r0, #1 +10022bf8: 4770 bx lr +10022bfa: 2000 movs r0, #0 +10022bfc: 4770 bx lr + +10022bfe : +10022bfe: 6842 ldr r2, [r0, #4] +10022c00: 430a orrs r2, r1 +10022c02: 6042 str r2, [r0, #4] +10022c04: f5b1 6f00 cmp.w r1, #2048 ; 0x800 +10022c08: bf04 itt eq +10022c0a: 2101 moveq r1, #1 +10022c0c: 7201 strbeq r1, [r0, #8] +10022c0e: 4770 bx lr + +10022c10 <_clr_fwstate_>: +10022c10: 6842 ldr r2, [r0, #4] +10022c12: 438a bics r2, r1 +10022c14: 6042 str r2, [r0, #4] +10022c16: f5b1 6f00 cmp.w r1, #2048 ; 0x800 +10022c1a: bf04 itt eq +10022c1c: 2100 moveq r1, #0 +10022c1e: 7201 strbeq r1, [r0, #8] +10022c20: 4770 bx lr + +10022c22 : +10022c22: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +10022c26: 4680 mov r8, r0 +10022c28: b082 sub sp, #8 +10022c2a: f108 050c add.w r5, r8, #12 +10022c2e: f105 0720 add.w r7, r5, #32 +10022c32: 2401 movs r4, #1 +10022c34: a900 add r1, sp, #0 +10022c36: f105 0028 add.w r0, r5, #40 ; 0x28 +10022c3a: f7ed fe6b bl 10010914 +10022c3e: 683e ldr r6, [r7, #0] +10022c40: f06f 0001 mvn.w r0, #1 +10022c44: f8c5 0088 str.w r0, [r5, #136] ; 0x88 +10022c48: 2180 movs r1, #128 ; 0x80 +10022c4a: 4628 mov r0, r5 +10022c4c: f7ff ffd7 bl 10022bfe +10022c50: 612e str r6, [r5, #16] +10022c52: 726c strb r4, [r5, #9] +10022c54: 4638 mov r0, r7 +10022c56: f7ed fe77 bl 10010948 +10022c5a: 2801 cmp r0, #1 +10022c5c: a900 add r1, sp, #0 +10022c5e: f105 0028 add.w r0, r5, #40 ; 0x28 +10022c62: d102 bne.n 10022c6a +10022c64: f7ed fe57 bl 10010916 +10022c68: e00f b.n 10022c8a +10022c6a: f7ed fe54 bl 10010916 +10022c6e: 4628 mov r0, r5 +10022c70: f7fc fb74 bl 1001f35c +10022c74: 2801 cmp r0, #1 +10022c76: d108 bne.n 10022c8a +10022c78: 2000 movs r0, #0 +10022c7a: 7268 strb r0, [r5, #9] +10022c7c: f641 1164 movw r1, #6500 ; 0x1964 +10022c80: f505 6084 add.w r0, r5, #1056 ; 0x420 +10022c84: f7ed fed9 bl 10010a3a +10022c88: e00d b.n 10022ca6 +10022c8a: 2180 movs r1, #128 ; 0x80 +10022c8c: 4628 mov r0, r5 +10022c8e: f7ff ffbf bl 10022c10 <_clr_fwstate_> +10022c92: f895 047c ldrb.w r0, [r5, #1148] ; 0x47c +10022c96: b930 cbnz r0, 10022ca6 +10022c98: 2201 movs r2, #1 +10022c9a: f105 0140 add.w r1, r5, #64 ; 0x40 +10022c9e: 4640 mov r0, r8 +10022ca0: f7f3 fc4c bl 1001653c +10022ca4: 4604 mov r4, r0 +10022ca6: e154 b.n 10022f52 <.text_10> + +10022ca8 : +10022ca8: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +10022cac: b090 sub sp, #64 ; 0x40 +10022cae: 4680 mov r8, r0 +10022cb0: 2000 movs r0, #0 +10022cb2: 9003 str r0, [sp, #12] +10022cb4: 460d mov r5, r1 +10022cb6: 2601 movs r6, #1 +10022cb8: f108 070c add.w r7, r8, #12 +10022cbc: 2228 movs r2, #40 ; 0x28 +10022cbe: 2100 movs r1, #0 +10022cc0: a805 add r0, sp, #20 +10022cc2: f7ed fdb9 bl 10010838 +10022cc6: 7828 ldrb r0, [r5, #0] +10022cc8: 2800 cmp r0, #0 +10022cca: bf04 itt eq +10022ccc: 7869 ldrbeq r1, [r5, #1] +10022cce: 2900 cmpeq r1, #0 +10022cd0: d10b bne.n 10022cea +10022cd2: 78a9 ldrb r1, [r5, #2] +10022cd4: 2900 cmp r1, #0 +10022cd6: bf04 itt eq +10022cd8: 78e9 ldrbeq r1, [r5, #3] +10022cda: 2900 cmpeq r1, #0 +10022cdc: d105 bne.n 10022cea +10022cde: 7929 ldrb r1, [r5, #4] +10022ce0: 2900 cmp r1, #0 +10022ce2: bf04 itt eq +10022ce4: 7969 ldrbeq r1, [r5, #5] +10022ce6: 2900 cmpeq r1, #0 +10022ce8: d010 beq.n 10022d0c +10022cea: 28ff cmp r0, #255 ; 0xff +10022cec: bf04 itt eq +10022cee: 7868 ldrbeq r0, [r5, #1] +10022cf0: 28ff cmpeq r0, #255 ; 0xff +10022cf2: d10d bne.n 10022d10 +10022cf4: 78a8 ldrb r0, [r5, #2] +10022cf6: 28ff cmp r0, #255 ; 0xff +10022cf8: bf04 itt eq +10022cfa: 78e8 ldrbeq r0, [r5, #3] +10022cfc: 28ff cmpeq r0, #255 ; 0xff +10022cfe: d107 bne.n 10022d10 +10022d00: 7928 ldrb r0, [r5, #4] +10022d02: 28ff cmp r0, #255 ; 0xff +10022d04: bf04 itt eq +10022d06: 7968 ldrbeq r0, [r5, #5] +10022d08: 28ff cmpeq r0, #255 ; 0xff +10022d0a: d101 bne.n 10022d10 +10022d0c: 2600 movs r6, #0 +10022d0e: e087 b.n 10022e20 +10022d10: a445 add r4, pc, #276 ; (adr r4, 10022e28 <.text_7>) +10022d12: 4620 mov r0, r4 +10022d14: f7e9 faf5 bl 1000c302 +10022d18: 7968 ldrb r0, [r5, #5] +10022d1a: 9002 str r0, [sp, #8] +10022d1c: 7928 ldrb r0, [r5, #4] +10022d1e: 9001 str r0, [sp, #4] +10022d20: 78e8 ldrb r0, [r5, #3] +10022d22: 9000 str r0, [sp, #0] +10022d24: 78ab ldrb r3, [r5, #2] +10022d26: 786a ldrb r2, [r5, #1] +10022d28: 7829 ldrb r1, [r5, #0] +10022d2a: f20f 30dc addw r0, pc, #988 ; 0x3dc +10022d2e: f7e9 fae8 bl 1000c302 +10022d32: a904 add r1, sp, #16 +10022d34: 4638 mov r0, r7 +10022d36: f7ed fded bl 10010914 +10022d3a: f000 f877 bl 10022e2c <.text_8> +10022d3e: 2801 cmp r0, #1 +10022d40: d032 beq.n 10022da8 +10022d42: 2180 movs r1, #128 ; 0x80 +10022d44: f000 f874 bl 10022e30 <.text_8+0x4> +10022d48: 2801 cmp r0, #1 +10022d4a: d065 beq.n 10022e18 +10022d4c: 2141 movs r1, #65 ; 0x41 +10022d4e: f000 f86f bl 10022e30 <.text_8+0x4> +10022d52: 2801 cmp r0, #1 +10022d54: d128 bne.n 10022da8 +10022d56: 2206 movs r2, #6 +10022d58: 4629 mov r1, r5 +10022d5a: f107 0090 add.w r0, r7, #144 ; 0x90 +10022d5e: f7ed fd60 bl 10010822 +10022d62: 2801 cmp r0, #1 +10022d64: d104 bne.n 10022d70 +10022d66: 2108 movs r1, #8 +10022d68: f000 f862 bl 10022e30 <.text_8+0x4> +10022d6c: b9e0 cbnz r0, 10022da8 +10022d6e: e053 b.n 10022e18 +10022d70: 4640 mov r0, r8 +10022d72: f7f3 fd4d bl 10016810 +10022d76: 2101 movs r1, #1 +10022d78: f000 f85a bl 10022e30 <.text_8+0x4> +10022d7c: 2801 cmp r0, #1 +10022d7e: bf04 itt eq +10022d80: 4640 moveq r0, r8 +10022d82: f7fc f84b bleq 1001ee1c +10022d86: 2101 movs r1, #1 +10022d88: 4640 mov r0, r8 +10022d8a: f7fb ffc8 bl 1001ed1e +10022d8e: 2140 movs r1, #64 ; 0x40 +10022d90: f000 f84e bl 10022e30 <.text_8+0x4> +10022d94: 2801 cmp r0, #1 +10022d96: d107 bne.n 10022da8 +10022d98: 2140 movs r1, #64 ; 0x40 +10022d9a: 4638 mov r0, r7 +10022d9c: f7ff ff38 bl 10022c10 <_clr_fwstate_> +10022da0: 2120 movs r1, #32 +10022da2: 4638 mov r0, r7 +10022da4: f7ff ff2b bl 10022bfe +10022da8: 79a8 ldrb r0, [r5, #6] +10022daa: 2823 cmp r0, #35 ; 0x23 +10022dac: bf04 itt eq +10022dae: 79e8 ldrbeq r0, [r5, #7] +10022db0: 2840 cmpeq r0, #64 ; 0x40 +10022db2: d119 bne.n 10022de8 +10022db4: 2204 movs r2, #4 +10022db6: f105 0108 add.w r1, r5, #8 +10022dba: a803 add r0, sp, #12 +10022dbc: f7ed fd27 bl 1001080e +10022dc0: 9803 ldr r0, [sp, #12] +10022dc2: b188 cbz r0, 10022de8 +10022dc4: 4620 mov r0, r4 +10022dc6: f7e9 fa9c bl 1000c302 +10022dca: 9803 ldr r0, [sp, #12] +10022dcc: 1c41 adds r1, r0, #1 +10022dce: f20f 3074 addw r0, pc, #884 ; 0x374 +10022dd2: f7e9 fa96 bl 1000c302 +10022dd6: 9803 ldr r0, [sp, #12] +10022dd8: 7800 ldrb r0, [r0, #0] +10022dda: 9005 str r0, [sp, #20] +10022ddc: 9803 ldr r0, [sp, #12] +10022dde: 7802 ldrb r2, [r0, #0] +10022de0: 1c41 adds r1, r0, #1 +10022de2: a806 add r0, sp, #24 +10022de4: f7ed fd13 bl 1001080e +10022de8: 2228 movs r2, #40 ; 0x28 +10022dea: a905 add r1, sp, #20 +10022dec: f107 0040 add.w r0, r7, #64 ; 0x40 +10022df0: f7ed fd0d bl 1001080e +10022df4: 2206 movs r2, #6 +10022df6: 4629 mov r1, r5 +10022df8: f107 0068 add.w r0, r7, #104 ; 0x68 +10022dfc: f7ed fd07 bl 1001080e +10022e00: f887 642c strb.w r6, [r7, #1068] ; 0x42c +10022e04: f000 f812 bl 10022e2c <.text_8> +10022e08: 2801 cmp r0, #1 +10022e0a: bf08 it eq +10022e0c: 7278 strbeq r0, [r7, #9] +10022e0e: d003 beq.n 10022e18 +10022e10: 4640 mov r0, r8 +10022e12: f7ff ff06 bl 10022c22 +10022e16: 4606 mov r6, r0 +10022e18: a904 add r1, sp, #16 +10022e1a: 4638 mov r0, r7 +10022e1c: f7ed fd7b bl 10010916 +10022e20: 4630 mov r0, r6 +10022e22: b010 add sp, #64 ; 0x40 +10022e24: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +10022e28 <.text_7>: +10022e28: 00000d0a .word 0x00000d0a + +10022e2c <.text_8>: +10022e2c: f44f 6100 mov.w r1, #2048 ; 0x800 +10022e30: 4638 mov r0, r7 +10022e32: e6dd b.n 10022bf0 + +10022e34 : +10022e34: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +10022e38: 4605 mov r5, r0 +10022e3a: f105 060c add.w r6, r5, #12 +10022e3e: b082 sub sp, #8 +10022e40: 460f mov r7, r1 +10022e42: 2401 movs r4, #1 +10022e44: f106 0870 add.w r8, r6, #112 ; 0x70 +10022e48: a006 add r0, pc, #24 ; (adr r0, 10022e64 ) +10022e4a: f7e9 fa5a bl 1000c302 +10022e4e: 1d39 adds r1, r7, #4 +10022e50: f20f 20f0 addw r0, pc, #752 ; 0x2f0 +10022e54: f7e9 fa55 bl 1000c302 +10022e58: f641 40b5 movw r0, #7349 ; 0x1cb5 +10022e5c: 5d40 ldrb r0, [r0, r5] +10022e5e: b918 cbnz r0, 10022e68 +10022e60: 2400 movs r4, #0 +10022e62: e076 b.n 10022f52 <.text_10> +10022e64: 00000d0a .word 0x00000d0a +10022e68: a900 add r1, sp, #0 +10022e6a: 4630 mov r0, r6 +10022e6c: f7ed fd52 bl 10010914 +10022e70: f000 f872 bl 10022f58 <.text_11> +10022e74: 2801 cmp r0, #1 +10022e76: d055 beq.n 10022f24 +10022e78: 2180 movs r1, #128 ; 0x80 +10022e7a: f000 f86f bl 10022f5c <.text_11+0x4> +10022e7e: 2801 cmp r0, #1 +10022e80: d063 beq.n 10022f4a +10022e82: 2141 movs r1, #65 ; 0x41 +10022e84: f000 f86a bl 10022f5c <.text_11+0x4> +10022e88: 2801 cmp r0, #1 +10022e8a: d14b bne.n 10022f24 +10022e8c: 683a ldr r2, [r7, #0] +10022e8e: 6c30 ldr r0, [r6, #64] ; 0x40 +10022e90: 4290 cmp r0, r2 +10022e92: d12b bne.n 10022eec +10022e94: 1d39 adds r1, r7, #4 +10022e96: f106 0044 add.w r0, r6, #68 ; 0x44 +10022e9a: f7ed fcc2 bl 10010822 +10022e9e: 2801 cmp r0, #1 +10022ea0: d124 bne.n 10022eec +10022ea2: 2108 movs r1, #8 +10022ea4: f000 f85a bl 10022f5c <.text_11+0x4> +10022ea8: b9d0 cbnz r0, 10022ee0 +10022eaa: 4641 mov r1, r8 +10022eac: 4628 mov r0, r5 +10022eae: f7fb fd30 bl 1001e912 +10022eb2: 2800 cmp r0, #0 +10022eb4: d149 bne.n 10022f4a +10022eb6: 4628 mov r0, r5 +10022eb8: f7f3 fcaa bl 10016810 +10022ebc: 2101 movs r1, #1 +10022ebe: f000 f84d bl 10022f5c <.text_11+0x4> +10022ec2: 2801 cmp r0, #1 +10022ec4: bf04 itt eq +10022ec6: 4628 moveq r0, r5 +10022ec8: f7fb ffa8 bleq 1001ee1c +10022ecc: 2101 movs r1, #1 +10022ece: 4628 mov r0, r5 +10022ed0: f7fb ff25 bl 1001ed1e +10022ed4: 2140 movs r1, #64 ; 0x40 +10022ed6: f000 f841 bl 10022f5c <.text_11+0x4> +10022eda: 2801 cmp r0, #1 +10022edc: d122 bne.n 10022f24 +10022ede: e019 b.n 10022f14 +10022ee0: 2201 movs r2, #1 +10022ee2: 4611 mov r1, r2 +10022ee4: 4628 mov r0, r5 +10022ee6: f7f3 fe6a bl 10016bbe +10022eea: e01b b.n 10022f24 +10022eec: 4628 mov r0, r5 +10022eee: f7f3 fc8f bl 10016810 +10022ef2: 2101 movs r1, #1 +10022ef4: f000 f832 bl 10022f5c <.text_11+0x4> +10022ef8: 2801 cmp r0, #1 +10022efa: bf04 itt eq +10022efc: 4628 moveq r0, r5 +10022efe: f7fb ff8d bleq 1001ee1c +10022f02: 2101 movs r1, #1 +10022f04: 4628 mov r0, r5 +10022f06: f7fb ff0a bl 1001ed1e +10022f0a: 2140 movs r1, #64 ; 0x40 +10022f0c: f000 f826 bl 10022f5c <.text_11+0x4> +10022f10: 2801 cmp r0, #1 +10022f12: d107 bne.n 10022f24 +10022f14: 2140 movs r1, #64 ; 0x40 +10022f16: 4630 mov r0, r6 +10022f18: f7ff fe7a bl 10022c10 <_clr_fwstate_> +10022f1c: 2120 movs r1, #32 +10022f1e: 4630 mov r0, r6 +10022f20: f7ff fe6d bl 10022bfe +10022f24: 2228 movs r2, #40 ; 0x28 +10022f26: 4639 mov r1, r7 +10022f28: f106 0040 add.w r0, r6, #64 ; 0x40 +10022f2c: f7ed fc6f bl 1001080e +10022f30: 2000 movs r0, #0 +10022f32: f886 042c strb.w r0, [r6, #1068] ; 0x42c +10022f36: f000 f80f bl 10022f58 <.text_11> +10022f3a: 2801 cmp r0, #1 +10022f3c: bf08 it eq +10022f3e: 7270 strbeq r0, [r6, #9] +10022f40: d003 beq.n 10022f4a +10022f42: 4628 mov r0, r5 +10022f44: f7ff fe6d bl 10022c22 +10022f48: 4604 mov r4, r0 +10022f4a: a900 add r1, sp, #0 +10022f4c: 4630 mov r0, r6 +10022f4e: f7ed fce2 bl 10010916 + +10022f52 <.text_10>: +10022f52: 4620 mov r0, r4 +10022f54: e8bd 81f6 ldmia.w sp!, {r1, r2, r4, r5, r6, r7, r8, pc} + +10022f58 <.text_11>: +10022f58: f44f 6100 mov.w r1, #2048 ; 0x800 +10022f5c: 4630 mov r0, r6 +10022f5e: e647 b.n 10022bf0 + +10022f60 : +10022f60: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +10022f64: 4604 mov r4, r0 +10022f66: f104 080c add.w r8, r4, #12 +10022f6a: f108 0670 add.w r6, r8, #112 ; 0x70 +10022f6e: f106 077c add.w r7, r6, #124 ; 0x7c +10022f72: b082 sub sp, #8 +10022f74: 6838 ldr r0, [r7, #0] +10022f76: 460d mov r5, r1 +10022f78: 42a8 cmp r0, r5 +10022f7a: d04b beq.n 10023014 +10022f7c: a900 add r1, sp, #0 +10022f7e: 4640 mov r0, r8 +10022f80: f7ed fcc8 bl 10010914 +10022f84: 6838 ldr r0, [r7, #0] +10022f86: 2804 cmp r0, #4 +10022f88: d105 bne.n 10022f96 +10022f8a: f04f 30ff mov.w r0, #4294967295 +10022f8e: 61b0 str r0, [r6, #24] +10022f90: 4620 mov r0, r4 +10022f92: f7f6 fb76 bl 10019682 +10022f96: f000 f871 bl 1002307c <.text_14> +10022f9a: 2801 cmp r0, #1 +10022f9c: bf19 ittee ne +10022f9e: 6838 ldrne r0, [r7, #0] +10022fa0: 2800 cmpne r0, #0 +10022fa2: 4620 moveq r0, r4 +10022fa4: f7f3 fc34 bleq 10016810 +10022fa8: f000 f868 bl 1002307c <.text_14> +10022fac: 2801 cmp r0, #1 +10022fae: d004 beq.n 10022fba +10022fb0: 2140 movs r1, #64 ; 0x40 +10022fb2: f000 f864 bl 1002307e <.text_14+0x2> +10022fb6: 2801 cmp r0, #1 +10022fb8: d103 bne.n 10022fc2 +10022fba: 2101 movs r1, #1 +10022fbc: 4620 mov r0, r4 +10022fbe: f7fb feae bl 1001ed1e +10022fc2: f000 f85b bl 1002307c <.text_14> +10022fc6: 2801 cmp r0, #1 +10022fc8: bf1c itt ne +10022fca: 6838 ldrne r0, [r7, #0] +10022fcc: 2801 cmpne r0, #1 +10022fce: d000 beq.n 10022fd2 +10022fd0: b910 cbnz r0, 10022fd8 +10022fd2: 4620 mov r0, r4 +10022fd4: f7fb ff22 bl 1001ee1c +10022fd8: 603d str r5, [r7, #0] +10022fda: f04f 31ff mov.w r1, #4294967295 +10022fde: 4640 mov r0, r8 +10022fe0: f7ff fe16 bl 10022c10 <_clr_fwstate_> +10022fe4: b125 cbz r5, 10022ff0 +10022fe6: 2d01 cmp r5, #1 +10022fe8: d004 beq.n 10022ff4 +10022fea: 2d04 cmp r5, #4 +10022fec: d007 beq.n 10022ffe +10022fee: e00d b.n 1002300c +10022ff0: 2120 movs r1, #32 +10022ff2: e000 b.n 10022ff6 +10022ff4: 2108 movs r1, #8 +10022ff6: 4640 mov r0, r8 +10022ff8: f7ff fe01 bl 10022bfe +10022ffc: e006 b.n 1002300c +10022ffe: 2110 movs r1, #16 +10023000: 4640 mov r0, r8 +10023002: f7ff fdfc bl 10022bfe +10023006: 4620 mov r0, r4 +10023008: f7f6 fb1b bl 10019642 +1002300c: a900 add r1, sp, #0 +1002300e: 4640 mov r0, r8 +10023010: f7ed fc81 bl 10010916 +10023014: 2001 movs r0, #1 +10023016: e8bd 81f6 ldmia.w sp!, {r1, r2, r4, r5, r6, r7, r8, pc} + +1002301a : +1002301a: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1002301e: 4604 mov r4, r0 +10023020: 2701 movs r7, #1 +10023022: b082 sub sp, #8 +10023024: 2c00 cmp r4, #0 +10023026: bf1d ittte ne +10023028: f641 40b5 movwne r0, #7349 ; 0x1cb5 +1002302c: 5d00 ldrbne r0, [r0, r4] +1002302e: 2800 cmpne r0, #0 +10023030: 2700 moveq r7, #0 +10023032: 460d mov r5, r1 +10023034: 4616 mov r6, r2 +10023036: f104 080c add.w r8, r4, #12 +1002303a: d01c beq.n 10023076 +1002303c: f44f 6108 mov.w r1, #2176 ; 0x880 +10023040: f000 f81d bl 1002307e <.text_14+0x2> +10023044: 2801 cmp r0, #1 +10023046: bf1c itt ne +10023048: f898 047c ldrbne.w r0, [r8, #1148] ; 0x47c +1002304c: 2801 cmpne r0, #1 +1002304e: d104 bne.n 1002305a +10023050: f44f 6108 mov.w r1, #2176 ; 0x880 +10023054: f000 f813 bl 1002307e <.text_14+0x2> +10023058: e00d b.n 10023076 +1002305a: a900 add r1, sp, #0 +1002305c: 4640 mov r0, r8 +1002305e: f7ed fc59 bl 10010914 +10023062: 4632 mov r2, r6 +10023064: 4629 mov r1, r5 +10023066: 4620 mov r0, r4 +10023068: f7f3 fa68 bl 1001653c +1002306c: 4607 mov r7, r0 +1002306e: a900 add r1, sp, #0 +10023070: 4640 mov r0, r8 +10023072: f7ed fc50 bl 10010916 +10023076: 4638 mov r0, r7 +10023078: e8bd 81f6 ldmia.w sp!, {r1, r2, r4, r5, r6, r7, r8, pc} + +1002307c <.text_14>: +1002307c: 2101 movs r1, #1 +1002307e: 4640 mov r0, r8 +10023080: e5b6 b.n 10022bf0 + +10023082 : +10023082: b580 push {r7, lr} +10023084: f500 5288 add.w r2, r0, #4352 ; 0x1100 +10023088: 32f0 adds r2, #240 ; 0xf0 +1002308a: 2904 cmp r1, #4 +1002308c: f8c2 1364 str.w r1, [r2, #868] ; 0x364 +10023090: bf24 itt cs +10023092: 2102 movcs r1, #2 +10023094: 6011 strcs r1, [r2, #0] +10023096: 4611 mov r1, r2 +10023098: f7fc f9ca bl 1001f430 +1002309c: 2801 cmp r0, #1 +1002309e: bf18 it ne +100230a0: 2000 movne r0, #0 +100230a2: bd02 pop {r1, pc} + +100230a4 : +100230a4: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +100230a8: 460e mov r6, r1 +100230aa: 4680 mov r8, r0 +100230ac: 6870 ldr r0, [r6, #4] +100230ae: f508 5788 add.w r7, r8, #4352 ; 0x1100 +100230b2: 0085 lsls r5, r0, #2 +100230b4: 37f0 adds r7, #240 ; 0xf0 +100230b6: 2401 movs r4, #1 +100230b8: 08ad lsrs r5, r5, #2 +100230ba: 2d05 cmp r5, #5 +100230bc: da1f bge.n 100230fe +100230be: 68b0 ldr r0, [r6, #8] +100230c0: 2805 cmp r0, #5 +100230c2: d002 beq.n 100230ca +100230c4: 280d cmp r0, #13 +100230c6: d002 beq.n 100230ce +100230c8: e003 b.n 100230d2 +100230ca: 607c str r4, [r7, #4] +100230cc: e003 b.n 100230d6 +100230ce: 2005 movs r0, #5 +100230d0: e000 b.n 100230d4 +100230d2: 2000 movs r0, #0 +100230d4: 6078 str r0, [r7, #4] +100230d6: 68b2 ldr r2, [r6, #8] +100230d8: eb07 1005 add.w r0, r7, r5, lsl #4 +100230dc: f106 010c add.w r1, r6, #12 +100230e0: 300c adds r0, #12 +100230e2: f7ed fb94 bl 1001080e +100230e6: 68b0 ldr r0, [r6, #8] +100230e8: eb07 0185 add.w r1, r7, r5, lsl #2 +100230ec: 2301 movs r3, #1 +100230ee: 64c8 str r0, [r1, #76] ; 0x4c +100230f0: 60bd str r5, [r7, #8] +100230f2: 462a mov r2, r5 +100230f4: 4639 mov r1, r7 +100230f6: 4640 mov r0, r8 +100230f8: f7fc f9c1 bl 1001f47e +100230fc: b900 cbnz r0, 10023100 +100230fe: 2400 movs r4, #0 +10023100: 4620 mov r0, r4 +10023102: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + ... + +10023108 : +10023108: 5452 384c 3931 4135 445b 6972 6576 5d72 RTL8195A[Driver] +10023118: 203a 6573 2074 5342 4953 3a44 2520 3230 : set BSSID: %02 +10023128: 3a78 3025 7832 253a 3230 3a78 3025 7832 x:%02x:%02x:%02x +10023138: 253a 3230 3a78 3025 7832 000a :%02x:%02x.. + +10023144 : +10023144: 5452 384c 3931 4135 445b 6972 6576 5d72 RTL8195A[Driver] +10023154: 203a 6573 2074 7373 6469 5b20 7325 205d : set ssid [%s] +10023164: 000a 0000 .... + +10023168 : +10023168: f8df f000 ldr.w pc, [pc] ; 1002316c +1002316c: 00015909 .word 0x00015909 + +10023170 : +10023170: f8df f000 ldr.w pc, [pc] ; 10023174 +10023174: 000128bd .word 0x000128bd + +10023178 : +10023178: f8df f000 ldr.w pc, [pc] ; 1002317c +1002317c: 00012901 .word 0x00012901 + +10023180 : +10023180: f8df f000 ldr.w pc, [pc] ; 10023184 +10023184: 000125c9 .word 0x000125c9 + +10023188 : +10023188: f8df f000 ldr.w pc, [pc] ; 1002318c +1002318c: 000132d5 .word 0x000132d5 + +10023190 : +10023190: f8df f000 ldr.w pc, [pc] ; 10023194 +10023194: 00012701 .word 0x00012701 + +10023198 : +10023198: f8df f000 ldr.w pc, [pc] ; 1002319c +1002319c: 00013ed5 .word 0x00013ed5 + +100231a0 : +100231a0: f8df f000 ldr.w pc, [pc] ; 100231a4 +100231a4: 00013f69 .word 0x00013f69 + +100231a8 : +100231a8: f8df f000 ldr.w pc, [pc] ; 100231ac +100231ac: 00013e9d .word 0x00013e9d + +100231b0 : +100231b0: 6840 ldr r0, [r0, #4] +100231b2: 4208 tst r0, r1 +100231b4: d001 beq.n 100231ba +100231b6: 2001 movs r0, #1 +100231b8: 4770 bx lr +100231ba: 2000 movs r0, #0 +100231bc: 4770 bx lr + +100231be : +100231be: b5f0 push {r4, r5, r6, r7, lr} +100231c0: 9f05 ldr r7, [sp, #20] +100231c2: b29b uxth r3, r3 +100231c4: 1859 adds r1, r3, r1 +100231c6: e9c0 1700 strd r1, r7, [r0] +100231ca: bd8e pop {r1, r2, r3, r7, pc} + +100231cc : +100231cc: b510 push {r4, lr} +100231ce: 7a03 ldrb r3, [r0, #8] +100231d0: 79c4 ldrb r4, [r0, #7] +100231d2: eb03 2304 add.w r3, r3, r4, lsl #8 +100231d6: 7984 ldrb r4, [r0, #6] +100231d8: eb03 4304 add.w r3, r3, r4, lsl #16 +100231dc: 7944 ldrb r4, [r0, #5] +100231de: eb03 6304 add.w r3, r3, r4, lsl #24 +100231e2: 6013 str r3, [r2, #0] +100231e4: 7ac4 ldrb r4, [r0, #11] +100231e6: 7b03 ldrb r3, [r0, #12] +100231e8: eb03 2304 add.w r3, r3, r4, lsl #8 +100231ec: 7a84 ldrb r4, [r0, #10] +100231ee: 7a40 ldrb r0, [r0, #9] +100231f0: eb03 4304 add.w r3, r3, r4, lsl #16 +100231f4: eb03 6000 add.w r0, r3, r0, lsl #24 +100231f8: 6050 str r0, [r2, #4] +100231fa: bd10 pop {r4, pc} + +100231fc : +100231fc: b530 push {r4, r5, lr} +100231fe: 4604 mov r4, r0 +10023200: b083 sub sp, #12 +10023202: 460d mov r5, r1 +10023204: 4610 mov r0, r2 +10023206: 4619 mov r1, r3 +10023208: aa00 add r2, sp, #0 +1002320a: f7ff ffdf bl 100231cc +1002320e: 9900 ldr r1, [sp, #0] +10023210: 428c cmp r4, r1 +10023212: d304 bcc.n 1002321e +10023214: 42a1 cmp r1, r4 +10023216: d304 bcc.n 10023222 +10023218: 9901 ldr r1, [sp, #4] +1002321a: 428d cmp r5, r1 +1002321c: d201 bcs.n 10023222 +1002321e: 2000 movs r0, #0 +10023220: bd3e pop {r1, r2, r3, r4, r5, pc} +10023222: 2001 movs r0, #1 +10023224: bd3e pop {r1, r2, r3, r4, r5, pc} + +10023226 : +10023226: 0e11 lsrs r1, r2, #24 +10023228: f800 1f05 strb.w r1, [r0, #5]! +1002322c: 0c11 lsrs r1, r2, #16 +1002322e: 7041 strb r1, [r0, #1] +10023230: 0a11 lsrs r1, r2, #8 +10023232: 7081 strb r1, [r0, #2] +10023234: 70c2 strb r2, [r0, #3] +10023236: 0e19 lsrs r1, r3, #24 +10023238: 7101 strb r1, [r0, #4] +1002323a: 0c19 lsrs r1, r3, #16 +1002323c: 7141 strb r1, [r0, #5] +1002323e: 0a19 lsrs r1, r3, #8 +10023240: 7181 strb r1, [r0, #6] +10023242: 71c3 strb r3, [r0, #7] +10023244: 4770 bx lr + +10023246 : +10023246: 6841 ldr r1, [r0, #4] +10023248: f111 0f01 cmn.w r1, #1 +1002324c: d10a bne.n 10023264 +1002324e: 6801 ldr r1, [r0, #0] +10023250: f111 0f01 cmn.w r1, #1 +10023254: d102 bne.n 1002325c +10023256: 2100 movs r1, #0 +10023258: 6001 str r1, [r0, #0] +1002325a: e004 b.n 10023266 +1002325c: 1c49 adds r1, r1, #1 +1002325e: 6001 str r1, [r0, #0] +10023260: 2100 movs r1, #0 +10023262: e000 b.n 10023266 +10023264: 1c49 adds r1, r1, #1 +10023266: 6041 str r1, [r0, #4] +10023268: 4770 bx lr + +1002326a : +1002326a: b510 push {r4, lr} +1002326c: 4604 mov r4, r0 +1002326e: 68a0 ldr r0, [r4, #8] +10023270: f110 0f01 cmn.w r0, #1 +10023274: bf04 itt eq +10023276: 68e0 ldreq r0, [r4, #12] +10023278: f110 0f01 cmneq.w r0, #1 +1002327c: d118 bne.n 100232b0 +1002327e: 6820 ldr r0, [r4, #0] +10023280: f110 0f01 cmn.w r0, #1 +10023284: bf04 itt eq +10023286: 6860 ldreq r0, [r4, #4] +10023288: f110 0f01 cmneq.w r0, #1 +1002328c: d105 bne.n 1002329a +1002328e: 2208 movs r2, #8 +10023290: 2100 movs r1, #0 +10023292: 4620 mov r0, r4 +10023294: f7e9 f85a bl 1000c34c +10023298: e002 b.n 100232a0 +1002329a: 4620 mov r0, r4 +1002329c: f7ff ffd3 bl 10023246 +100232a0: f104 0008 add.w r0, r4, #8 +100232a4: e8bd 4010 ldmia.w sp!, {r4, lr} +100232a8: 2208 movs r2, #8 +100232aa: 2100 movs r1, #0 +100232ac: f7e9 b84e b.w 1000c34c +100232b0: f104 0008 add.w r0, r4, #8 +100232b4: e8bd 4010 ldmia.w sp!, {r4, lr} +100232b8: e7c5 b.n 10023246 + +100232ba : +100232ba: b510 push {r4, lr} +100232bc: 4604 mov r4, r0 +100232be: 6920 ldr r0, [r4, #16] +100232c0: f110 0f01 cmn.w r0, #1 +100232c4: bf04 itt eq +100232c6: 6960 ldreq r0, [r4, #20] +100232c8: f110 0f01 cmneq.w r0, #1 +100232cc: d127 bne.n 1002331e +100232ce: 69a0 ldr r0, [r4, #24] +100232d0: f110 0f01 cmn.w r0, #1 +100232d4: bf04 itt eq +100232d6: 69e0 ldreq r0, [r4, #28] +100232d8: f110 0f01 cmneq.w r0, #1 +100232dc: d11f bne.n 1002331e +100232de: 6820 ldr r0, [r4, #0] +100232e0: f110 0f01 cmn.w r0, #1 +100232e4: bf04 itt eq +100232e6: 6860 ldreq r0, [r4, #4] +100232e8: f110 0f01 cmneq.w r0, #1 +100232ec: d10d bne.n 1002330a +100232ee: 68a0 ldr r0, [r4, #8] +100232f0: f110 0f01 cmn.w r0, #1 +100232f4: bf04 itt eq +100232f6: 68e0 ldreq r0, [r4, #12] +100232f8: f110 0f01 cmneq.w r0, #1 +100232fc: d105 bne.n 1002330a +100232fe: 2210 movs r2, #16 +10023300: 2100 movs r1, #0 +10023302: 4620 mov r0, r4 +10023304: f7e9 f822 bl 1000c34c +10023308: e002 b.n 10023310 +1002330a: 4620 mov r0, r4 +1002330c: f7ff ffad bl 1002326a +10023310: 2210 movs r2, #16 +10023312: 2100 movs r1, #0 +10023314: f104 0010 add.w r0, r4, #16 +10023318: f7e9 f818 bl 1000c34c +1002331c: e003 b.n 10023326 +1002331e: f104 0010 add.w r0, r4, #16 +10023322: f7ff ffa2 bl 1002326a +10023326: 4620 mov r0, r4 +10023328: bd10 pop {r4, pc} + +1002332a : +1002332a: b40c push {r2, r3} +1002332c: b570 push {r4, r5, r6, lr} +1002332e: b082 sub sp, #8 +10023330: 460d mov r5, r1 +10023332: 9200 str r2, [sp, #0] +10023334: 4604 mov r4, r0 +10023336: 2204 movs r2, #4 +10023338: a900 add r1, sp, #0 +1002333a: f7e9 f805 bl 1000c348 +1002333e: 9807 ldr r0, [sp, #28] +10023340: f000 f828 bl 10023394 <.text_15> +10023344: 9808 ldr r0, [sp, #32] +10023346: 9000 str r0, [sp, #0] +10023348: 1d36 adds r6, r6, #4 +1002334a: f000 f825 bl 10023398 <.text_15+0x4> +1002334e: 9809 ldr r0, [sp, #36] ; 0x24 +10023350: 9000 str r0, [sp, #0] +10023352: 1d36 adds r6, r6, #4 +10023354: f000 f820 bl 10023398 <.text_15+0x4> +10023358: 2d10 cmp r5, #16 +1002335a: d013 beq.n 10023384 +1002335c: 980a ldr r0, [sp, #40] ; 0x28 +1002335e: 9000 str r0, [sp, #0] +10023360: 1d34 adds r4, r6, #4 +10023362: f000 f812 bl 1002338a <.text_14> +10023366: 980b ldr r0, [sp, #44] ; 0x2c +10023368: 9000 str r0, [sp, #0] +1002336a: 1d24 adds r4, r4, #4 +1002336c: f000 f80d bl 1002338a <.text_14> +10023370: 980c ldr r0, [sp, #48] ; 0x30 +10023372: f000 f80f bl 10023394 <.text_15> +10023376: 980d ldr r0, [sp, #52] ; 0x34 +10023378: 9000 str r0, [sp, #0] +1002337a: 2204 movs r2, #4 +1002337c: a900 add r1, sp, #0 +1002337e: 1d30 adds r0, r6, #4 +10023380: f7e8 ffe2 bl 1000c348 +10023384: bc73 pop {r0, r1, r4, r5, r6} +10023386: f85d fb0c ldr.w pc, [sp], #12 + +1002338a <.text_14>: +1002338a: 2204 movs r2, #4 +1002338c: a900 add r1, sp, #0 +1002338e: 4620 mov r0, r4 +10023390: f7e8 bfda b.w 1000c348 + +10023394 <.text_15>: +10023394: 9000 str r0, [sp, #0] +10023396: 1d26 adds r6, r4, #4 +10023398: 2204 movs r2, #4 +1002339a: a900 add r1, sp, #0 +1002339c: 4630 mov r0, r6 +1002339e: f7e8 bfd3 b.w 1000c348 + +100233a2 : +100233a2: b5f0 push {r4, r5, r6, r7, lr} +100233a4: b087 sub sp, #28 +100233a6: f20f 0540 addw r5, pc, #64 ; 0x40 +100233aa: cdc0 ldmia r5!, {r6, r7} +100233ac: ac04 add r4, sp, #16 +100233ae: c4c0 stmia r4!, {r6, r7} +100233b0: f8d1 10fc ldr.w r1, [r1, #252] ; 0xfc +100233b4: eb00 0081 add.w r0, r0, r1, lsl #2 +100233b8: f641 011c movw r1, #6172 ; 0x181c +100233bc: 5808 ldr r0, [r1, r0] +100233be: f8d0 00ec ldr.w r0, [r0, #236] ; 0xec +100233c2: 7880 ldrb r0, [r0, #2] +100233c4: f000 0007 and.w r0, r0, #7 +100233c8: 2801 cmp r0, #1 +100233ca: d00b beq.n 100233e4 +100233cc: 980f ldr r0, [sp, #60] ; 0x3c +100233ce: 990d ldr r1, [sp, #52] ; 0x34 +100233d0: 9003 str r0, [sp, #12] +100233d2: 9301 str r3, [sp, #4] +100233d4: 9200 str r2, [sp, #0] +100233d6: 2308 movs r3, #8 +100233d8: 980e ldr r0, [sp, #56] ; 0x38 +100233da: 9002 str r0, [sp, #8] +100233dc: aa04 add r2, sp, #16 +100233de: 980c ldr r0, [sp, #48] ; 0x30 +100233e0: f7ff fece bl 10023180 +100233e4: b007 add sp, #28 +100233e6: bdf0 pop {r4, r5, r6, r7, pc} + +100233e8 : +100233e8: a6a6 a6a6 a6a6 a6a6 ........ + +100233f0 : +100233f0: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} +100233f4: f100 0712 add.w r7, r0, #18 +100233f8: f5ad 7d07 sub.w sp, sp, #540 ; 0x21c +100233fc: 4614 mov r4, r2 +100233fe: 78ba ldrb r2, [r7, #2] +10023400: 4689 mov r9, r1 +10023402: f002 0507 and.w r5, r2, #7 +10023406: 4601 mov r1, r0 +10023408: 4698 mov r8, r3 +1002340a: 2600 movs r6, #0 +1002340c: 464a mov r2, r9 +1002340e: a806 add r0, sp, #24 +10023410: f7e8 ff9a bl 1000c348 +10023414: 2210 movs r2, #16 +10023416: 2100 movs r1, #0 +10023418: f10d 0077 add.w r0, sp, #119 ; 0x77 +1002341c: f7e8 ff96 bl 1000c34c +10023420: 2d01 cmp r5, #1 +10023422: d10b bne.n 1002343c +10023424: f10d 0077 add.w r0, sp, #119 ; 0x77 +10023428: f000 f81c bl 10023464 <.text_19> +1002342c: f7ff feac bl 10023188 +10023430: 2210 movs r2, #16 +10023432: f107 014d add.w r1, r7, #77 ; 0x4d +10023436: f10d 0077 add.w r0, sp, #119 ; 0x77 +1002343a: e00a b.n 10023452 +1002343c: 2d02 cmp r5, #2 +1002343e: d10c bne.n 1002345a +10023440: a801 add r0, sp, #4 +10023442: f000 f80f bl 10023464 <.text_19> +10023446: f7ff fe8f bl 10023168 +1002344a: 2210 movs r2, #16 +1002344c: f107 014d add.w r1, r7, #77 ; 0x4d +10023450: a801 add r0, sp, #4 +10023452: f7e8 ff77 bl 1000c344 +10023456: b900 cbnz r0, 1002345a +10023458: 2601 movs r6, #1 +1002345a: 4630 mov r0, r6 +1002345c: f50d 7d07 add.w sp, sp, #540 ; 0x21c +10023460: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + +10023464 <.text_19>: +10023464: 9000 str r0, [sp, #0] +10023466: 4643 mov r3, r8 +10023468: 4622 mov r2, r4 +1002346a: f1a9 010e sub.w r1, r9, #14 +1002346e: f10d 0026 add.w r0, sp, #38 ; 0x26 +10023472: 4770 bx lr + +10023474 : +10023474: e92d 42f0 stmdb sp!, {r4, r5, r6, r7, r9, lr} +10023478: 460d mov r5, r1 +1002347a: 4614 mov r4, r2 +1002347c: f100 070e add.w r7, r0, #14 +10023480: f100 0912 add.w r9, r0, #18 +10023484: b088 sub sp, #32 +10023486: 461e mov r6, r3 +10023488: 2210 movs r2, #16 +1002348a: 2100 movs r1, #0 +1002348c: f109 004d add.w r0, r9, #77 ; 0x4d +10023490: f7e8 ff5c bl 1000c34c +10023494: 9b0e ldr r3, [sp, #56] ; 0x38 +10023496: 2c01 cmp r4, #1 +10023498: d106 bne.n 100234a8 +1002349a: f109 004d add.w r0, r9, #77 ; 0x4d +1002349e: f000 f813 bl 100234c8 <.text_21> +100234a2: f7ff fe71 bl 10023188 +100234a6: e00c b.n 100234c2 +100234a8: 2c02 cmp r4, #2 +100234aa: d10a bne.n 100234c2 +100234ac: a801 add r0, sp, #4 +100234ae: f000 f80b bl 100234c8 <.text_21> +100234b2: f7ff fe59 bl 10023168 +100234b6: 2210 movs r2, #16 +100234b8: a901 add r1, sp, #4 +100234ba: f109 004d add.w r0, r9, #77 ; 0x4d +100234be: f7e8 ff43 bl 1000c348 +100234c2: b008 add sp, #32 +100234c4: e8bd 82f0 ldmia.w sp!, {r4, r5, r6, r7, r9, pc} + +100234c8 <.text_21>: +100234c8: 9000 str r0, [sp, #0] +100234ca: 4632 mov r2, r6 +100234cc: f1a5 010e sub.w r1, r5, #14 +100234d0: 4638 mov r0, r7 +100234d2: 4770 bx lr + +100234d4 : +100234d4: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +100234d8: 4691 mov r9, r2 +100234da: f5ad 7d48 sub.w sp, sp, #800 ; 0x320 +100234de: 469a mov sl, r3 +100234e0: f20f 028c addw r2, pc, #140 ; 0x8c +100234e4: 4688 mov r8, r1 +100234e6: e8b2 1008 ldmia.w r2!, {r3, ip} +100234ea: a901 add r1, sp, #4 +100234ec: f100 04d4 add.w r4, r0, #212 ; 0xd4 +100234f0: e8a1 1008 stmia.w r1!, {r3, ip} +100234f4: 6921 ldr r1, [r4, #16] +100234f6: 9dd0 ldr r5, [sp, #832] ; 0x340 +100234f8: 7889 ldrb r1, [r1, #2] +100234fa: 2700 movs r7, #0 +100234fc: f001 0107 and.w r1, r1, #7 +10023500: 9ed1 ldr r6, [sp, #836] ; 0x344 +10023502: 2901 cmp r1, #1 +10023504: d11d bne.n 10023542 +10023506: f8d0 00d4 ldr.w r0, [r0, #212] ; 0xd4 +1002350a: f100 013f add.w r1, r0, #63 ; 0x3f +1002350e: 2210 movs r2, #16 +10023510: a845 add r0, sp, #276 ; 0x114 +10023512: f7e8 ff19 bl 1000c348 +10023516: 462a mov r2, r5 +10023518: 4651 mov r1, sl +1002351a: a849 add r0, sp, #292 ; 0x124 +1002351c: f7e8 ff14 bl 1000c348 +10023520: f105 0210 add.w r2, r5, #16 +10023524: a945 add r1, sp, #276 ; 0x114 +10023526: a803 add r0, sp, #12 +10023528: f7ff fe22 bl 10023170 +1002352c: f000 f87e bl 1002362c <.text_26> +10023530: 6920 ldr r0, [r4, #16] +10023532: f100 025f add.w r2, r0, #95 ; 0x5f +10023536: 464b mov r3, r9 +10023538: f000 f87b bl 10023632 <.text_26+0x6> +1002353c: 464a mov r2, r9 +1002353e: a986 add r1, sp, #536 ; 0x218 +10023540: e00c b.n 1002355c +10023542: a886 add r0, sp, #536 ; 0x218 +10023544: 9000 str r0, [sp, #0] +10023546: 462b mov r3, r5 +10023548: 4652 mov r2, sl +1002354a: 4649 mov r1, r9 +1002354c: 4640 mov r0, r8 +1002354e: f7ff fe1f bl 10023190 +10023552: f000 f872 bl 1002363a <.text_27> +10023556: b928 cbnz r0, 10023564 +10023558: 464a mov r2, r9 +1002355a: a988 add r1, sp, #544 ; 0x220 +1002355c: 4630 mov r0, r6 +1002355e: f7e8 fef3 bl 1000c348 +10023562: 2701 movs r7, #1 +10023564: 4638 mov r0, r7 +10023566: f50d 7d48 add.w sp, sp, #800 ; 0x320 +1002356a: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + ... + +10023570 : +10023570: a6a6 a6a6 a6a6 a6a6 ........ + +10023578 : +10023578: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} +1002357c: 4699 mov r9, r3 +1002357e: f5ad 7d47 sub.w sp, sp, #796 ; 0x31c +10023582: f20f 03a0 addw r3, pc, #160 ; 0xa0 +10023586: 4690 mov r8, r2 +10023588: e8b3 1080 ldmia.w r3!, {r7, ip} +1002358c: aa01 add r2, sp, #4 +1002358e: f100 0312 add.w r3, r0, #18 +10023592: e8a2 1080 stmia.w r2!, {r7, ip} +10023596: f100 0712 add.w r7, r0, #18 +1002359a: 2600 movs r6, #0 +1002359c: 78b8 ldrb r0, [r7, #2] +1002359e: 9cce ldr r4, [sp, #824] ; 0x338 +100235a0: 9dcf ldr r5, [sp, #828] ; 0x33c +100235a2: f000 0107 and.w r1, r0, #7 +100235a6: 2901 cmp r1, #1 +100235a8: d11a bne.n 100235e0 +100235aa: 2210 movs r2, #16 +100235ac: f103 012d add.w r1, r3, #45 ; 0x2d +100235b0: a845 add r0, sp, #276 ; 0x114 +100235b2: f7e8 fec9 bl 1000c348 +100235b6: 464a mov r2, r9 +100235b8: 4641 mov r1, r8 +100235ba: a849 add r0, sp, #292 ; 0x124 +100235bc: f7e8 fec4 bl 1000c348 +100235c0: f109 0210 add.w r2, r9, #16 +100235c4: a945 add r1, sp, #276 ; 0x114 +100235c6: a803 add r0, sp, #12 +100235c8: f7ff fdd2 bl 10023170 +100235cc: f000 f82e bl 1002362c <.text_26> +100235d0: 4623 mov r3, r4 +100235d2: f107 025f add.w r2, r7, #95 ; 0x5f +100235d6: f000 f82c bl 10023632 <.text_26+0x6> +100235da: 4622 mov r2, r4 +100235dc: a986 add r1, sp, #536 ; 0x218 +100235de: e017 b.n 10023610 +100235e0: f000 0007 and.w r0, r0, #7 +100235e4: 2802 cmp r0, #2 +100235e6: d117 bne.n 10023618 +100235e8: f897 005d ldrb.w r0, [r7, #93] ; 0x5d +100235ec: f897 105e ldrb.w r1, [r7, #94] ; 0x5e +100235f0: eb01 2400 add.w r4, r1, r0, lsl #8 +100235f4: a886 add r0, sp, #536 ; 0x218 +100235f6: 9000 str r0, [sp, #0] +100235f8: 464b mov r3, r9 +100235fa: 4642 mov r2, r8 +100235fc: 4621 mov r1, r4 +100235fe: f107 005f add.w r0, r7, #95 ; 0x5f +10023602: f7ff fdc5 bl 10023190 +10023606: f000 f818 bl 1002363a <.text_27> +1002360a: b928 cbnz r0, 10023618 +1002360c: 4622 mov r2, r4 +1002360e: a988 add r1, sp, #544 ; 0x220 +10023610: 4628 mov r0, r5 +10023612: f7e8 fe99 bl 1000c348 +10023616: 2601 movs r6, #1 +10023618: 4630 mov r0, r6 +1002361a: f50d 7d47 add.w sp, sp, #796 ; 0x31c +1002361e: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + ... + +10023624 : +10023624: a6a6 a6a6 a6a6 a6a6 ........ + +1002362c <.text_26>: +1002362c: f44f 7380 mov.w r3, #256 ; 0x100 +10023630: aa45 add r2, sp, #276 ; 0x114 +10023632: a986 add r1, sp, #536 ; 0x218 +10023634: a803 add r0, sp, #12 +10023636: f7ff bd9f b.w 10023178 + +1002363a <.text_27>: +1002363a: 2208 movs r2, #8 +1002363c: a901 add r1, sp, #4 +1002363e: a886 add r0, sp, #536 ; 0x218 +10023640: f7e8 be80 b.w 1000c344 + +10023644 : +10023644: b510 push {r4, lr} +10023646: b098 sub sp, #96 ; 0x60 +10023648: 4604 mov r4, r0 +1002364a: 2108 movs r1, #8 +1002364c: a801 add r0, sp, #4 +1002364e: f7ed fa3d bl 10010acc +10023652: 2208 movs r2, #8 +10023654: a901 add r1, sp, #4 +10023656: a803 add r0, sp, #12 +10023658: f7ed f8d9 bl 1001080e +1002365c: 2000 movs r0, #0 +1002365e: aa01 add r2, sp, #4 +10023660: a903 add r1, sp, #12 +10023662: 5c82 ldrb r2, [r0, r2] +10023664: 1841 adds r1, r0, r1 +10023666: 43d2 mvns r2, r2 +10023668: 720a strb r2, [r1, #8] +1002366a: aa01 add r2, sp, #4 +1002366c: 1a12 subs r2, r2, r0 +1002366e: 1c40 adds r0, r0, #1 +10023670: 79d2 ldrb r2, [r2, #7] +10023672: 740a strb r2, [r1, #16] +10023674: 43d2 mvns r2, r2 +10023676: 2808 cmp r0, #8 +10023678: 760a strb r2, [r1, #24] +1002367a: dbf0 blt.n 1002365e +1002367c: a813 add r0, sp, #76 ; 0x4c +1002367e: 9000 str r0, [sp, #0] +10023680: 2310 movs r3, #16 +10023682: aa05 add r2, sp, #20 +10023684: 2120 movs r1, #32 +10023686: a803 add r0, sp, #12 +10023688: f7ff fd6e bl 10023168 +1002368c: 2000 movs r0, #0 +1002368e: a913 add r1, sp, #76 ; 0x4c +10023690: aa0b add r2, sp, #44 ; 0x2c +10023692: 5c41 ldrb r1, [r0, r1] +10023694: 5481 strb r1, [r0, r2] +10023696: 1882 adds r2, r0, r2 +10023698: a913 add r1, sp, #76 ; 0x4c +1002369a: 1a09 subs r1, r1, r0 +1002369c: 1c40 adds r0, r0, #1 +1002369e: 7cc9 ldrb r1, [r1, #19] +100236a0: 7411 strb r1, [r2, #16] +100236a2: 2810 cmp r0, #16 +100236a4: dbf3 blt.n 1002368e +100236a6: 2220 movs r2, #32 +100236a8: a90b add r1, sp, #44 ; 0x2c +100236aa: 4620 mov r0, r4 +100236ac: f7ed f8af bl 1001080e +100236b0: b018 add sp, #96 ; 0x60 +100236b2: bd10 pop {r4, pc} + +100236b4 : +100236b4: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +100236b8: 4604 mov r4, r0 +100236ba: f504 5088 add.w r0, r4, #4352 ; 0x1100 +100236be: 460d mov r5, r1 +100236c0: f100 08f0 add.w r8, r0, #240 ; 0xf0 +100236c4: f104 070c add.w r7, r4, #12 +100236c8: f000 f90e bl 100238e8 <.text_34> +100236cc: 2801 cmp r0, #1 +100236ce: d106 bne.n 100236de +100236d0: f8d5 00fc ldr.w r0, [r5, #252] ; 0xfc +100236d4: eb08 0080 add.w r0, r8, r0, lsl #2 +100236d8: f8d0 662c ldr.w r6, [r0, #1580] ; 0x62c +100236dc: e006 b.n 100236ec +100236de: 2108 movs r1, #8 +100236e0: f000 f903 bl 100238ea <.text_34+0x2> +100236e4: 2801 cmp r0, #1 +100236e6: d143 bne.n 10023770 +100236e8: f8d8 6630 ldr.w r6, [r8, #1584] ; 0x630 +100236ec: 2e00 cmp r6, #0 +100236ee: d03f beq.n 10023770 +100236f0: 7c30 ldrb r0, [r6, #16] +100236f2: f8c5 0114 str.w r0, [r5, #276] ; 0x114 +100236f6: 2210 movs r2, #16 +100236f8: f106 01b4 add.w r1, r6, #180 ; 0xb4 +100236fc: f505 709c add.w r0, r5, #312 ; 0x138 +10023700: f7e8 fe22 bl 1000c348 +10023704: 7c30 ldrb r0, [r6, #16] +10023706: 2802 cmp r0, #2 +10023708: d126 bne.n 10023758 +1002370a: f505 7894 add.w r8, r5, #296 ; 0x128 +1002370e: f106 09cc add.w r9, r6, #204 ; 0xcc +10023712: f505 7a8c add.w sl, r5, #280 ; 0x118 +10023716: f106 0bc4 add.w fp, r6, #196 ; 0xc4 +1002371a: f000 f8e5 bl 100238e8 <.text_34> +1002371e: 2801 cmp r0, #1 +10023720: d107 bne.n 10023732 +10023722: 2208 movs r2, #8 +10023724: 4659 mov r1, fp +10023726: 4650 mov r0, sl +10023728: f7e8 fe0e bl 1000c348 +1002372c: 2208 movs r2, #8 +1002372e: 4649 mov r1, r9 +10023730: e00b b.n 1002374a +10023732: 2108 movs r1, #8 +10023734: f000 f8d9 bl 100238ea <.text_34+0x2> +10023738: 2801 cmp r0, #1 +1002373a: d109 bne.n 10023750 +1002373c: 2208 movs r2, #8 +1002373e: 4649 mov r1, r9 +10023740: 4650 mov r0, sl +10023742: f7e8 fe01 bl 1000c348 +10023746: 2208 movs r2, #8 +10023748: 4659 mov r1, fp +1002374a: 4640 mov r0, r8 +1002374c: f7e8 fdfc bl 1000c348 +10023750: f241 5145 movw r1, #5445 ; 0x1545 +10023754: 2000 movs r0, #0 +10023756: 5508 strb r0, [r1, r4] +10023758: 2201 movs r2, #1 +1002375a: 4629 mov r1, r5 +1002375c: 4620 mov r0, r4 +1002375e: f7f3 f86f bl 10016840 +10023762: 4620 mov r0, r4 +10023764: f001 fd68 bl 10025238 +10023768: b110 cbz r0, 10023770 +1002376a: 7c31 ldrb r1, [r6, #16] +1002376c: f8c0 1114 str.w r1, [r0, #276] ; 0x114 +10023770: e8bd 8ff1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +10023774 : +10023774: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +10023778: 4680 mov r8, r0 +1002377a: f508 5688 add.w r6, r8, #4352 ; 0x1100 +1002377e: 36f0 adds r6, #240 ; 0xf0 +10023780: f206 4994 addw r9, r6, #1172 ; 0x494 +10023784: f108 0a0c add.w sl, r8, #12 +10023788: f8d9 7188 ldr.w r7, [r9, #392] ; 0x188 +1002378c: eb09 1547 add.w r5, r9, r7, lsl #5 +10023790: eb06 1407 add.w r4, r6, r7, lsl #4 +10023794: 2210 movs r2, #16 +10023796: f105 01e8 add.w r1, r5, #232 ; 0xe8 +1002379a: f104 0064 add.w r0, r4, #100 ; 0x64 +1002379e: f7e8 fdd3 bl 1000c348 +100237a2: f899 00bc ldrb.w r0, [r9, #188] ; 0xbc +100237a6: 2802 cmp r0, #2 +100237a8: d123 bne.n 100237f2 +100237aa: f505 7980 add.w r9, r5, #256 ; 0x100 +100237ae: f104 0be4 add.w fp, r4, #228 ; 0xe4 +100237b2: 35f8 adds r5, #248 ; 0xf8 +100237b4: 34a4 adds r4, #164 ; 0xa4 +100237b6: 2110 movs r1, #16 +100237b8: 4650 mov r0, sl +100237ba: f7ff fcf9 bl 100231b0 +100237be: 2801 cmp r0, #1 +100237c0: d107 bne.n 100237d2 +100237c2: 2208 movs r2, #8 +100237c4: 4629 mov r1, r5 +100237c6: 4620 mov r0, r4 +100237c8: f7e8 fdbe bl 1000c348 +100237cc: 2208 movs r2, #8 +100237ce: 4649 mov r1, r9 +100237d0: e00c b.n 100237ec +100237d2: 2108 movs r1, #8 +100237d4: 4650 mov r0, sl +100237d6: f7ff fceb bl 100231b0 +100237da: 2801 cmp r0, #1 +100237dc: d109 bne.n 100237f2 +100237de: 2208 movs r2, #8 +100237e0: 4649 mov r1, r9 +100237e2: 4620 mov r0, r4 +100237e4: f7e8 fdb0 bl 1000c348 +100237e8: 2208 movs r2, #8 +100237ea: 4629 mov r1, r5 +100237ec: 4658 mov r0, fp +100237ee: f7e8 fdab bl 1000c348 +100237f2: 2001 movs r0, #1 +100237f4: f886 0354 strb.w r0, [r6, #852] ; 0x354 +100237f8: 6637 str r7, [r6, #96] ; 0x60 +100237fa: 463a mov r2, r7 +100237fc: 4631 mov r1, r6 +100237fe: 4640 mov r0, r8 +10023800: b001 add sp, #4 +10023802: e8bd 4ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +10023806: 2301 movs r3, #1 +10023808: f7fb be39 b.w 1001f47e + +1002380c : +1002380c: b119 cbz r1, 10023816 +1002380e: 2901 cmp r1, #1 +10023810: d104 bne.n 1002381c +10023812: 2100 movs r1, #0 +10023814: e000 b.n 10023818 +10023816: 2101 movs r1, #1 +10023818: f8c0 1110 str.w r1, [r0, #272] ; 0x110 +1002381c: 4770 bx lr + +1002381e : +1002381e: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +10023822: 4604 mov r4, r0 +10023824: 460d mov r5, r1 +10023826: f104 070c add.w r7, r4, #12 +1002382a: 4616 mov r6, r2 +1002382c: 2108 movs r1, #8 +1002382e: f000 f85c bl 100238ea <.text_34+0x2> +10023832: 2801 cmp r0, #1 +10023834: d124 bne.n 10023880 +10023836: b2b2 uxth r2, r6 +10023838: f505 7184 add.w r1, r5, #264 ; 0x108 +1002383c: 4620 mov r0, r4 +1002383e: f7f9 f9e1 bl 1001cc04 +10023842: f894 08cc ldrb.w r0, [r4, #2252] ; 0x8cc +10023846: 2800 cmp r0, #0 +10023848: d03f beq.n 100238ca +1002384a: f894 0842 ldrb.w r0, [r4, #2114] ; 0x842 +1002384e: 1c40 adds r0, r0, #1 +10023850: f884 0842 strb.w r0, [r4, #2114] ; 0x842 +10023854: b2c0 uxtb r0, r0 +10023856: 2803 cmp r0, #3 +10023858: da06 bge.n 10023868 +1002385a: f241 3188 movw r1, #5000 ; 0x1388 +1002385e: f604 0034 addw r0, r4, #2100 ; 0x834 +10023862: f7ed f8ea bl 10010a3a +10023866: e030 b.n 100238ca +10023868: 2000 movs r0, #0 +1002386a: f884 0842 strb.w r0, [r4, #2114] ; 0x842 +1002386e: 4620 mov r0, r4 +10023870: f7ed feac bl 100115cc +10023874: f20f 0158 addw r1, pc, #88 ; 0x58 +10023878: 4620 mov r0, r4 +1002387a: f7f0 fb15 bl 10013ea8 +1002387e: e024 b.n 100238ca +10023880: f000 f832 bl 100238e8 <.text_34> +10023884: 2801 cmp r0, #1 +10023886: d120 bne.n 100238ca +10023888: f504 5088 add.w r0, r4, #4352 ; 0x1100 +1002388c: 3028 adds r0, #40 ; 0x28 +1002388e: f100 088c add.w r8, r0, #140 ; 0x8c +10023892: 2700 movs r7, #0 +10023894: a900 add r1, sp, #0 +10023896: 4640 mov r0, r8 +10023898: f7ed f83c bl 10010914 +1002389c: f505 7907 add.w r9, r5, #540 ; 0x21c +100238a0: 4648 mov r0, r9 +100238a2: f7ec ffd4 bl 1001084e +100238a6: b940 cbnz r0, 100238ba +100238a8: 4648 mov r0, r9 +100238aa: f7ec ffdb bl 10010864 +100238ae: b2b2 uxth r2, r6 +100238b0: 4629 mov r1, r5 +100238b2: 4620 mov r0, r4 +100238b4: f7f5 fe0b bl 100194ce +100238b8: 4607 mov r7, r0 +100238ba: a900 add r1, sp, #0 +100238bc: 4640 mov r0, r8 +100238be: f7ed f82a bl 10010916 +100238c2: 4639 mov r1, r7 +100238c4: 4620 mov r0, r4 +100238c6: f7f5 fcc1 bl 1001924c +100238ca: e8bd 83f1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, pc} + ... + +100238d0 : +100238d0: 4552 4f43 4e4e 4345 4954 4e4f 4620 4941 RECONNECTION FAI +100238e0: 554c 4552 0000 0000 LURE.... + +100238e8 <.text_34>: +100238e8: 2110 movs r1, #16 +100238ea: 4638 mov r0, r7 +100238ec: e460 b.n 100231b0 + +100238ee : +100238ee: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +100238f2: 4604 mov r4, r0 +100238f4: f504 5088 add.w r0, r4, #4352 ; 0x1100 +100238f8: f100 06f0 add.w r6, r0, #240 ; 0xf0 +100238fc: f641 5051 movw r0, #7505 ; 0x1d51 +10023900: 460d mov r5, r1 +10023902: 5d00 ldrb r0, [r0, r4] +10023904: 2800 cmp r0, #0 +10023906: f104 080c add.w r8, r4, #12 +1002390a: bf0c ite eq +1002390c: 2700 moveq r7, #0 +1002390e: 2728 movne r7, #40 ; 0x28 +10023910: f000 f870 bl 100239f4 <.text_37> +10023914: 2801 cmp r0, #1 +10023916: d106 bne.n 10023926 +10023918: f8d5 00fc ldr.w r0, [r5, #252] ; 0xfc +1002391c: eb06 0080 add.w r0, r6, r0, lsl #2 +10023920: f8d0 662c ldr.w r6, [r0, #1580] ; 0x62c +10023924: e006 b.n 10023934 +10023926: 2108 movs r1, #8 +10023928: f000 f865 bl 100239f6 <.text_37+0x2> +1002392c: 2801 cmp r0, #1 +1002392e: d158 bne.n 100239e2 +10023930: f8d6 6630 ldr.w r6, [r6, #1584] ; 0x630 +10023934: 2e00 cmp r6, #0 +10023936: d054 beq.n 100239e2 +10023938: f506 793d add.w r9, r6, #756 ; 0x2f4 +1002393c: 4648 mov r0, r9 +1002393e: f7ed f88c bl 10010a5a +10023942: f000 f857 bl 100239f4 <.text_37> +10023946: 2801 cmp r0, #1 +10023948: d10c bne.n 10023964 +1002394a: f8d5 0100 ldr.w r0, [r5, #256] ; 0x100 +1002394e: 1cc2 adds r2, r0, #3 +10023950: 2301 movs r3, #1 +10023952: b2d2 uxtb r2, r2 +10023954: 4629 mov r1, r5 +10023956: 4620 mov r0, r4 +10023958: f7f2 ffe4 bl 10016924 +1002395c: 2100 movs r1, #0 +1002395e: 4628 mov r0, r5 +10023960: f7ff ff54 bl 1002380c +10023964: f44f 7246 mov.w r2, #792 ; 0x318 +10023968: 2100 movs r1, #0 +1002396a: 4630 mov r0, r6 +1002396c: f7e8 fcee bl 1000c34c +10023970: f106 0034 add.w r0, r6, #52 ; 0x34 +10023974: 6270 str r0, [r6, #36] ; 0x24 +10023976: 462b mov r3, r5 +10023978: 2020 movs r0, #32 +1002397a: 62b0 str r0, [r6, #40] ; 0x28 +1002397c: f106 0054 add.w r0, r6, #84 ; 0x54 +10023980: 62f0 str r0, [r6, #44] ; 0x2c +10023982: 2020 movs r0, #32 +10023984: 6330 str r0, [r6, #48] ; 0x30 +10023986: f106 00f4 add.w r0, r6, #244 ; 0xf4 +1002398a: f8c6 00dc str.w r0, [r6, #220] ; 0xdc +1002398e: f20f 026d addw r2, pc, #109 ; 0x6d +10023992: f20f 0054 addw r0, pc, #84 ; 0x54 +10023996: 9000 str r0, [sp, #0] +10023998: f641 5024 movw r0, #7460 ; 0x1d24 +1002399c: 5901 ldr r1, [r0, r4] +1002399e: 4648 mov r0, r9 +100239a0: f7ed f841 bl 10010a26 +100239a4: f8df 0c4c ldr.w r0, [pc, #3148] ; 100245f4 <.text_75> +100239a8: 616c str r4, [r5, #20] +100239aa: 1838 adds r0, r7, r0 +100239ac: f100 01cc add.w r1, r0, #204 ; 0xcc +100239b0: 2220 movs r2, #32 +100239b2: f106 0074 add.w r0, r6, #116 ; 0x74 +100239b6: f7e8 fcc7 bl 1000c348 +100239ba: f000 f81b bl 100239f4 <.text_37> +100239be: 2801 cmp r0, #1 +100239c0: bf08 it eq +100239c2: 6030 streq r0, [r6, #0] +100239c4: d00d beq.n 100239e2 +100239c6: 2108 movs r1, #8 +100239c8: f000 f815 bl 100239f6 <.text_37+0x2> +100239cc: 2801 cmp r0, #1 +100239ce: d108 bne.n 100239e2 +100239d0: 2000 movs r0, #0 +100239d2: f8c6 0304 str.w r0, [r6, #772] ; 0x304 +100239d6: f8c6 0308 str.w r0, [r6, #776] ; 0x308 +100239da: f04f 30ff mov.w r0, #4294967295 +100239de: 6170 str r0, [r6, #20] +100239e0: 61b0 str r0, [r6, #24] +100239e2: e8bd 83f1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, pc} + ... + +100239e8 : +100239e8: 6552 6573 646e 6954 656d 0072 ResendTimer. + +100239f4 <.text_37>: +100239f4: 2110 movs r1, #16 +100239f6: 4640 mov r0, r8 +100239f8: f7ff bbda b.w 100231b0 + +100239fc : +100239fc: b5f8 push {r3, r4, r5, r6, r7, lr} +100239fe: 0004 movs r4, r0 +10023a00: d03a beq.n 10023a78 +10023a02: 6965 ldr r5, [r4, #20] +10023a04: f105 060c add.w r6, r5, #12 +10023a08: f505 5788 add.w r7, r5, #4352 ; 0x1100 +10023a0c: 37f0 adds r7, #240 ; 0xf0 +10023a0e: f000 f834 bl 10023a7a <.text_39> +10023a12: 2801 cmp r0, #1 +10023a14: d106 bne.n 10023a24 +10023a16: f8d4 00fc ldr.w r0, [r4, #252] ; 0xfc +10023a1a: eb07 0080 add.w r0, r7, r0, lsl #2 +10023a1e: f8d0 062c ldr.w r0, [r0, #1580] ; 0x62c +10023a22: e006 b.n 10023a32 +10023a24: 2108 movs r1, #8 +10023a26: f000 f829 bl 10023a7c <.text_39+0x2> +10023a2a: 2801 cmp r0, #1 +10023a2c: d124 bne.n 10023a78 +10023a2e: f8d7 0630 ldr.w r0, [r7, #1584] ; 0x630 +10023a32: b308 cbz r0, 10023a78 +10023a34: f8d0 1300 ldr.w r1, [r0, #768] ; 0x300 +10023a38: 1c49 adds r1, r1, #1 +10023a3a: 2906 cmp r1, #6 +10023a3c: f8c0 1300 str.w r1, [r0, #768] ; 0x300 +10023a40: db05 blt.n 10023a4e +10023a42: 4621 mov r1, r4 +10023a44: 4628 mov r0, r5 +10023a46: e8bd 40f8 ldmia.w sp!, {r3, r4, r5, r6, r7, lr} +10023a4a: 220f movs r2, #15 +10023a4c: e6e7 b.n 1002381e +10023a4e: f000 f814 bl 10023a7a <.text_39> +10023a52: 2801 cmp r0, #1 +10023a54: d105 bne.n 10023a62 +10023a56: 4621 mov r1, r4 +10023a58: 4628 mov r0, r5 +10023a5a: e8bd 40f8 ldmia.w sp!, {r3, r4, r5, r6, r7, lr} +10023a5e: 2201 movs r2, #1 +10023a60: e010 b.n 10023a84 +10023a62: 2108 movs r1, #8 +10023a64: f000 f80a bl 10023a7c <.text_39+0x2> +10023a68: 2801 cmp r0, #1 +10023a6a: d105 bne.n 10023a78 +10023a6c: 4621 mov r1, r4 +10023a6e: 4628 mov r0, r5 +10023a70: e8bd 40f8 ldmia.w sp!, {r3, r4, r5, r6, r7, lr} +10023a74: 2201 movs r2, #1 +10023a76: e2ec b.n 10024052 +10023a78: bdf1 pop {r0, r4, r5, r6, r7, pc} + +10023a7a <.text_39>: +10023a7a: 2110 movs r1, #16 +10023a7c: 4630 mov r0, r6 +10023a7e: f7ff bb97 b.w 100231b0 + ... + +10023a84 : +10023a84: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +10023a88: 4682 mov sl, r0 +10023a8a: f50a 5088 add.w r0, sl, #4352 ; 0x1100 +10023a8e: 30f0 adds r0, #240 ; 0xf0 +10023a90: 2500 movs r5, #0 +10023a92: 460f mov r7, r1 +10023a94: 2800 cmp r0, #0 +10023a96: bf18 it ne +10023a98: 2f00 cmpne r7, #0 +10023a9a: b0db sub sp, #364 ; 0x16c +10023a9c: 4691 mov r9, r2 +10023a9e: f04f 0801 mov.w r8, #1 +10023aa2: d038 beq.n 10023b16 +10023aa4: f8d7 10fc ldr.w r1, [r7, #252] ; 0xfc +10023aa8: eb00 0181 add.w r1, r0, r1, lsl #2 +10023aac: f200 4b94 addw fp, r0, #1172 ; 0x494 +10023ab0: f8d1 462c ldr.w r4, [r1, #1580] ; 0x62c +10023ab4: 6820 ldr r0, [r4, #0] +10023ab6: 2800 cmp r0, #0 +10023ab8: d02d beq.n 10023b16 +10023aba: 2208 movs r2, #8 +10023abc: 2100 movs r1, #0 +10023abe: a806 add r0, sp, #24 +10023ac0: f7e8 fc44 bl 1000c34c +10023ac4: f8d4 00dc ldr.w r0, [r4, #220] ; 0xdc +10023ac8: 9009 str r0, [sp, #36] ; 0x24 +10023aca: 3012 adds r0, #18 +10023acc: 9006 str r0, [sp, #24] +10023ace: f8c4 00ec str.w r0, [r4, #236] ; 0xec +10023ad2: f89b 00bc ldrb.w r0, [fp, #188] ; 0xbc +10023ad6: 2804 cmp r0, #4 +10023ad8: bf1a itte ne +10023ada: 7c20 ldrbne r0, [r4, #16] +10023adc: 2804 cmpne r0, #4 +10023ade: f04f 0802 moveq.w r8, #2 +10023ae2: f1b9 0f00 cmp.w r9, #0 +10023ae6: d00b beq.n 10023b00 +10023ae8: f8d4 00e0 ldr.w r0, [r4, #224] ; 0xe0 +10023aec: 900a str r0, [sp, #40] ; 0x28 +10023aee: f8d4 00f0 ldr.w r0, [r4, #240] ; 0xf0 +10023af2: 9007 str r0, [sp, #28] +10023af4: f000 fa4d bl 10023f92 <.text_45+0x2> +10023af8: f000 fa8b bl 10024012 <.text_51> +10023afc: 2501 movs r5, #1 +10023afe: e099 b.n 10023c34 +10023b00: a811 add r0, sp, #68 ; 0x44 +10023b02: 900f str r0, [sp, #60] ; 0x3c +10023b04: 2010 movs r0, #16 +10023b06: 9010 str r0, [sp, #64] ; 0x40 +10023b08: a003 add r0, pc, #12 ; (adr r0, 10023b18 ) +10023b0a: 6821 ldr r1, [r4, #0] +10023b0c: 2901 cmp r1, #1 +10023b0e: d005 beq.n 10023b1c +10023b10: 2902 cmp r1, #2 +10023b12: f000 80be beq.w 10023c92 +10023b16: e20b b.n 10023f30 +10023b18: 00000d0a .word 0x00000d0a +10023b1c: f7e8 fbf1 bl 1000c302 +10023b20: f20f 4014 addw r0, pc, #1044 ; 0x414 +10023b24: f7e8 fbed bl 1000c302 +10023b28: 9806 ldr r0, [sp, #24] +10023b2a: f44f 72f7 mov.w r2, #494 ; 0x1ee +10023b2e: f000 ffab bl 10024a88 <.text_82+0x6> +10023b32: 7a20 ldrb r0, [r4, #8] +10023b34: 9906 ldr r1, [sp, #24] +10023b36: 0780 lsls r0, r0, #30 +10023b38: bf4c ite mi +10023b3a: 2002 movmi r0, #2 +10023b3c: 20fe movpl r0, #254 ; 0xfe +10023b3e: f000 fa1f bl 10023f80 <.text_44> +10023b42: 9806 ldr r0, [sp, #24] +10023b44: 9906 ldr r1, [sp, #24] +10023b46: 7880 ldrb r0, [r0, #2] +10023b48: ea48 0000 orr.w r0, r8, r0 +10023b4c: 7088 strb r0, [r1, #2] +10023b4e: 9806 ldr r0, [sp, #24] +10023b50: 9906 ldr r1, [sp, #24] +10023b52: 7880 ldrb r0, [r0, #2] +10023b54: f040 0008 orr.w r0, r0, #8 +10023b58: f000 fa50 bl 10023ffc <.text_50> +10023b5c: f000 00bf and.w r0, r0, #191 ; 0xbf +10023b60: f000 fa41 bl 10023fe6 <.text_49> +10023b64: f000 00fe and.w r0, r0, #254 ; 0xfe +10023b68: f000 fa19 bl 10023f9e <.text_46> +10023b6c: bf0c ite eq +10023b6e: 2020 moveq r0, #32 +10023b70: 2010 movne r0, #16 +10023b72: f000 fa0d bl 10023f90 <.text_45> +10023b76: 2208 movs r2, #8 +10023b78: f104 0114 add.w r1, r4, #20 +10023b7c: f104 001c add.w r0, r4, #28 +10023b80: f7e8 fbe2 bl 1000c348 +10023b84: f000 fa45 bl 10024012 <.text_51> +10023b88: 4658 mov r0, fp +10023b8a: f7ff fb96 bl 100232ba +10023b8e: b082 sub sp, #8 +10023b90: f000 fa24 bl 10023fdc <.text_48> +10023b94: f104 0624 add.w r6, r4, #36 ; 0x24 +10023b98: bc0c pop {r2, r3} +10023b9a: e9d6 0100 ldrd r0, r1, [r6] +10023b9e: f7ff fbc4 bl 1002332a +10023ba2: f000 fa15 bl 10023fd0 <.text_47> +10023ba6: f000 fa38 bl 1002401a <.text_52> +10023baa: f000 fa3b bl 10024024 <.text_53> +10023bae: 2208 movs r2, #8 +10023bb0: 4629 mov r1, r5 +10023bb2: a80b add r0, sp, #44 ; 0x2c +10023bb4: f7e8 fbca bl 1000c34c +10023bb8: f000 fa40 bl 1002403c <.text_55> +10023bbc: f000 fa44 bl 10024048 <.text_56> +10023bc0: f000 fa36 bl 10024030 <.text_54> +10023bc4: 7a20 ldrb r0, [r4, #8] +10023bc6: 9906 ldr r1, [sp, #24] +10023bc8: 0780 lsls r0, r0, #30 +10023bca: f881 505d strb.w r5, [r1, #93] ; 0x5d +10023bce: d50b bpl.n 10023be8 +10023bd0: 9906 ldr r1, [sp, #24] +10023bd2: 2016 movs r0, #22 +10023bd4: f881 005e strb.w r0, [r1, #94] ; 0x5e +10023bd8: 2206 movs r2, #6 +10023bda: 9806 ldr r0, [sp, #24] +10023bdc: f8df 1e18 ldr.w r1, [pc, #3608] ; 100249f8 <.text_80> +10023be0: 305f adds r0, #95 ; 0x5f +10023be2: f7e8 fbb1 bl 1000c348 +10023be6: e002 b.n 10023bee +10023be8: 9906 ldr r1, [sp, #24] +10023bea: f881 505e strb.w r5, [r1, #94] ; 0x5e +10023bee: 2210 movs r2, #16 +10023bf0: 2100 movs r1, #0 +10023bf2: a817 add r0, sp, #92 ; 0x5c +10023bf4: f7e8 fbaa bl 1000c34c +10023bf8: 9806 ldr r0, [sp, #24] +10023bfa: 2210 movs r2, #16 +10023bfc: a917 add r1, sp, #92 ; 0x5c +10023bfe: 304d adds r0, #77 ; 0x4d +10023c00: f7e8 fba2 bl 1000c348 +10023c04: 7a20 ldrb r0, [r4, #8] +10023c06: 0780 lsls r0, r0, #30 +10023c08: d509 bpl.n 10023c1e +10023c0a: 9806 ldr r0, [sp, #24] +10023c0c: 9906 ldr r1, [sp, #24] +10023c0e: f890 005d ldrb.w r0, [r0, #93] ; 0x5d +10023c12: f891 105e ldrb.w r1, [r1, #94] ; 0x5e +10023c16: eb01 2000 add.w r0, r1, r0, lsl #8 +10023c1a: 305f adds r0, #95 ; 0x5f +10023c1c: e000 b.n 10023c20 +10023c1e: 205f movs r0, #95 ; 0x5f +10023c20: 9007 str r0, [sp, #28] +10023c22: 9807 ldr r0, [sp, #28] +10023c24: 3012 adds r0, #18 +10023c26: 900a str r0, [sp, #40] ; 0x28 +10023c28: 980a ldr r0, [sp, #40] ; 0x28 +10023c2a: f8c4 00e0 str.w r0, [r4, #224] ; 0xe0 +10023c2e: 9807 ldr r0, [sp, #28] +10023c30: f8c4 00f0 str.w r0, [r4, #240] ; 0xf0 +10023c34: 2206 movs r2, #6 +10023c36: 9e09 ldr r6, [sp, #36] ; 0x24 +10023c38: f507 7184 add.w r1, r7, #264 ; 0x108 +10023c3c: 4630 mov r0, r6 +10023c3e: f7e8 fb83 bl 1000c348 +10023c42: f50a 51c8 add.w r1, sl, #6400 ; 0x1900 +10023c46: 2206 movs r2, #6 +10023c48: 3195 adds r1, #149 ; 0x95 +10023c4a: 1db0 adds r0, r6, #6 +10023c4c: f7e8 fb7c bl 1000c348 +10023c50: f648 008e movw r0, #34958 ; 0x888e +10023c54: f7ec fd64 bl 10010720 <_htons> +10023c58: 81b0 strh r0, [r6, #12] +10023c5a: 9809 ldr r0, [sp, #36] ; 0x24 +10023c5c: f100 070e add.w r7, r0, #14 +10023c60: 2001 movs r0, #1 +10023c62: 7038 strb r0, [r7, #0] +10023c64: 2003 movs r0, #3 +10023c66: 7078 strb r0, [r7, #1] +10023c68: 9807 ldr r0, [sp, #28] +10023c6a: b280 uxth r0, r0 +10023c6c: f7ec fd58 bl 10010720 <_htons> +10023c70: 8078 strh r0, [r7, #2] +10023c72: b145 cbz r5, 10023c86 +10023c74: 2010 movs r0, #16 +10023c76: 9000 str r0, [sp, #0] +10023c78: f104 0394 add.w r3, r4, #148 ; 0x94 +10023c7c: e9dd 0109 ldrd r0, r1, [sp, #36] ; 0x24 +10023c80: 4642 mov r2, r8 +10023c82: f7ff fbf7 bl 10023474 +10023c86: f000 fb73 bl 10024370 <.text_58> +10023c8a: 0005 movs r5, r0 +10023c8c: f040 813d bne.w 10023f0a +10023c90: e14e b.n 10023f30 +10023c92: f7e8 fb36 bl 1000c302 +10023c96: f20f 20c0 addw r0, pc, #704 ; 0x2c0 +10023c9a: f7e8 fb32 bl 1000c302 +10023c9e: 7a20 ldrb r0, [r4, #8] +10023ca0: 9906 ldr r1, [sp, #24] +10023ca2: 0780 lsls r0, r0, #30 +10023ca4: bf4c ite mi +10023ca6: 2002 movmi r0, #2 +10023ca8: 20fe movpl r0, #254 ; 0xfe +10023caa: f000 f969 bl 10023f80 <.text_44> +10023cae: f8d4 10e4 ldr.w r1, [r4, #228] ; 0xe4 +10023cb2: 9806 ldr r0, [sp, #24] +10023cb4: 7889 ldrb r1, [r1, #2] +10023cb6: 7880 ldrb r0, [r0, #2] +10023cb8: f001 0107 and.w r1, r1, #7 +10023cbc: 4308 orrs r0, r1 +10023cbe: 9906 ldr r1, [sp, #24] +10023cc0: 7088 strb r0, [r1, #2] +10023cc2: f8d4 00e4 ldr.w r0, [r4, #228] ; 0xe4 +10023cc6: 9906 ldr r1, [sp, #24] +10023cc8: 7880 ldrb r0, [r0, #2] +10023cca: 7889 ldrb r1, [r1, #2] +10023ccc: 0700 lsls r0, r0, #28 +10023cce: bf4c ite mi +10023cd0: 2008 movmi r0, #8 +10023cd2: 2000 movpl r0, #0 +10023cd4: f001 01f7 and.w r1, r1, #247 ; 0xf7 +10023cd8: 4308 orrs r0, r1 +10023cda: 9906 ldr r1, [sp, #24] +10023cdc: f000 f98e bl 10023ffc <.text_50> +10023ce0: f040 0040 orr.w r0, r0, #64 ; 0x40 +10023ce4: f000 f97f bl 10023fe6 <.text_49> +10023ce8: f040 0001 orr.w r0, r0, #1 +10023cec: f000 f957 bl 10023f9e <.text_46> +10023cf0: bf0c ite eq +10023cf2: 2020 moveq r0, #32 +10023cf4: 2010 movne r0, #16 +10023cf6: f000 f94b bl 10023f90 <.text_45> +10023cfa: f000 f98a bl 10024012 <.text_51> +10023cfe: f000 f967 bl 10023fd0 <.text_47> +10023d02: f000 f98a bl 1002401a <.text_52> +10023d06: f000 f98d bl 10024024 <.text_53> +10023d0a: 7a20 ldrb r0, [r4, #8] +10023d0c: 0780 lsls r0, r0, #30 +10023d0e: f140 80d1 bpl.w 10023eb4 +10023d12: f20f 2164 addw r1, pc, #612 ; 0x264 +10023d16: c90c ldmia r1!, {r2, r3} +10023d18: a815 add r0, sp, #84 ; 0x54 +10023d1a: ad1b add r5, sp, #108 ; 0x6c +10023d1c: c00c stmia r0!, {r2, r3} +10023d1e: 9906 ldr r1, [sp, #24] +10023d20: 2013 movs r0, #19 +10023d22: f1b8 0f02 cmp.w r8, #2 +10023d26: 7048 strb r0, [r1, #1] +10023d28: d10c bne.n 10023d44 +10023d2a: 4658 mov r0, fp +10023d2c: f7ff fac5 bl 100232ba +10023d30: b082 sub sp, #8 +10023d32: f000 f953 bl 10023fdc <.text_48> +10023d36: bc0c pop {r2, r3} +10023d38: e9dd 010f ldrd r0, r1, [sp, #60] ; 0x3c +10023d3c: f7ff faf5 bl 1002332a +10023d40: f000 f970 bl 10024024 <.text_53> +10023d44: f8db 1034 ldr.w r1, [fp, #52] ; 0x34 +10023d48: 7808 ldrb r0, [r1, #0] +10023d4a: 2830 cmp r0, #48 ; 0x30 +10023d4c: d109 bne.n 10023d62 +10023d4e: 7848 ldrb r0, [r1, #1] +10023d50: 1c85 adds r5, r0, #2 +10023d52: 2d65 cmp r5, #101 ; 0x65 +10023d54: da9c bge.n 10023c90 +10023d56: 462a mov r2, r5 +10023d58: a81b add r0, sp, #108 ; 0x6c +10023d5a: f7e8 faf5 bl 1000c348 +10023d5e: a81b add r0, sp, #108 ; 0x6c +10023d60: 182d adds r5, r5, r0 +10023d62: 2208 movs r2, #8 +10023d64: a915 add r1, sp, #84 ; 0x54 +10023d66: 4628 mov r0, r5 +10023d68: f7e8 faee bl 1000c348 +10023d6c: f89b 00bc ldrb.w r0, [fp, #188] ; 0xbc +10023d70: 2802 cmp r0, #2 +10023d72: bf0c ite eq +10023d74: 2020 moveq r0, #32 +10023d76: 2010 movne r0, #16 +10023d78: 1d80 adds r0, r0, #6 +10023d7a: 7068 strb r0, [r5, #1] +10023d7c: f105 0608 add.w r6, r5, #8 +10023d80: f8db 0020 ldr.w r0, [fp, #32] +10023d84: b380 cbz r0, 10023de8 +10023d86: f50b 71c4 add.w r1, fp, #392 ; 0x188 +10023d8a: f10b 0020 add.w r0, fp, #32 +10023d8e: 688a ldr r2, [r1, #8] +10023d90: 2a00 cmp r2, #0 +10023d92: bf04 itt eq +10023d94: 6882 ldreq r2, [r0, #8] +10023d96: 2a00 cmpeq r2, #0 +10023d98: d026 beq.n 10023de8 +10023d9a: 6882 ldr r2, [r0, #8] +10023d9c: b10a cbz r2, 10023da2 +10023d9e: 2200 movs r2, #0 +10023da0: 60c2 str r2, [r0, #12] +10023da2: 2200 movs r2, #0 +10023da4: 608a str r2, [r1, #8] +10023da6: 6082 str r2, [r0, #8] +10023da8: 6102 str r2, [r0, #16] +10023daa: 4658 mov r0, fp +10023dac: f7ff fa85 bl 100232ba +10023db0: b082 sub sp, #8 +10023db2: f000 f913 bl 10023fdc <.text_48> +10023db6: f10b 0cc0 add.w ip, fp, #192 ; 0xc0 +10023dba: bc0c pop {r2, r3} +10023dbc: e9dc 0100 ldrd r0, r1, [ip] +10023dc0: f7ff fab3 bl 1002332a +10023dc4: 2020 movs r0, #32 +10023dc6: 9001 str r0, [sp, #4] +10023dc8: 2320 movs r3, #32 +10023dca: f8db 0188 ldr.w r0, [fp, #392] ; 0x188 +10023dce: eb0b 1040 add.w r0, fp, r0, lsl #5 +10023dd2: 30e8 adds r0, #232 ; 0xe8 +10023dd4: 9000 str r0, [sp, #0] +10023dd6: f50b 72b4 add.w r2, fp, #360 ; 0x168 +10023dda: f8db 10c0 ldr.w r1, [fp, #192] ; 0xc0 +10023dde: f50a 50c8 add.w r0, sl, #6400 ; 0x1900 +10023de2: 3095 adds r0, #149 ; 0x95 +10023de4: f7ff f9d8 bl 10023198 +10023de8: f89b 00bc ldrb.w r0, [fp, #188] ; 0xbc +10023dec: 2802 cmp r0, #2 +10023dee: f8db 0188 ldr.w r0, [fp, #392] ; 0x188 +10023df2: eb0b 1040 add.w r0, fp, r0, lsl #5 +10023df6: f100 01e8 add.w r1, r0, #232 ; 0xe8 +10023dfa: bf0c ite eq +10023dfc: 2220 moveq r2, #32 +10023dfe: 2210 movne r2, #16 +10023e00: 4630 mov r0, r6 +10023e02: f7e8 faa1 bl 1000c348 +10023e06: f89b 00bc ldrb.w r0, [fp, #188] ; 0xbc +10023e0a: 2802 cmp r0, #2 +10023e0c: bf0c ite eq +10023e0e: 2020 moveq r0, #32 +10023e10: 2010 movne r0, #16 +10023e12: 1985 adds r5, r0, r6 +10023e14: ae1b add r6, sp, #108 ; 0x6c +10023e16: 1ba8 subs r0, r5, r6 +10023e18: 1081 asrs r1, r0, #2 +10023e1a: eb00 7151 add.w r1, r0, r1, lsr #29 +10023e1e: 10c9 asrs r1, r1, #3 +10023e20: ebb0 00c1 subs.w r0, r0, r1, lsl #3 +10023e24: d00c beq.n 10023e40 +10023e26: 21dd movs r1, #221 ; 0xdd +10023e28: 1c40 adds r0, r0, #1 +10023e2a: 2808 cmp r0, #8 +10023e2c: f805 1b01 strb.w r1, [r5], #1 +10023e30: f1c0 0908 rsb r9, r0, #8 +10023e34: da04 bge.n 10023e40 +10023e36: 4649 mov r1, r9 +10023e38: 4628 mov r0, r5 +10023e3a: f7ea f97b bl 1000e134 <__aeabi_memclr> +10023e3e: 444d add r5, r9 +10023e40: a808 add r0, sp, #32 +10023e42: 9003 str r0, [sp, #12] +10023e44: 2310 movs r3, #16 +10023e46: a83b add r0, sp, #236 ; 0xec +10023e48: 9002 str r0, [sp, #8] +10023e4a: f104 02a4 add.w r2, r4, #164 ; 0xa4 +10023e4e: 1ba8 subs r0, r5, r6 +10023e50: 9001 str r0, [sp, #4] +10023e52: 4639 mov r1, r7 +10023e54: a81b add r0, sp, #108 ; 0x6c +10023e56: 9000 str r0, [sp, #0] +10023e58: 4650 mov r0, sl +10023e5a: f7ff faa2 bl 100233a2 +10023e5e: f8bd 5020 ldrh.w r5, [sp, #32] +10023e62: 9806 ldr r0, [sp, #24] +10023e64: 462a mov r2, r5 +10023e66: a93b add r1, sp, #236 ; 0xec +10023e68: 305f adds r0, #95 ; 0x5f +10023e6a: f7e8 fa6d bl 1000c348 +10023e6e: 9906 ldr r1, [sp, #24] +10023e70: 0a28 lsrs r0, r5, #8 +10023e72: f881 005d strb.w r0, [r1, #93] ; 0x5d +10023e76: a90b add r1, sp, #44 ; 0x2c +10023e78: 9806 ldr r0, [sp, #24] +10023e7a: f880 505e strb.w r5, [r0, #94] ; 0x5e +10023e7e: f105 005f add.w r0, r5, #95 ; 0x5f +10023e82: 9007 str r0, [sp, #28] +10023e84: f897 0148 ldrb.w r0, [r7, #328] ; 0x148 +10023e88: f88d 002c strb.w r0, [sp, #44] ; 0x2c +10023e8c: f507 70a4 add.w r0, r7, #328 ; 0x148 +10023e90: 7842 ldrb r2, [r0, #1] +10023e92: 704a strb r2, [r1, #1] +10023e94: 7882 ldrb r2, [r0, #2] +10023e96: 708a strb r2, [r1, #2] +10023e98: 78c2 ldrb r2, [r0, #3] +10023e9a: 70ca strb r2, [r1, #3] +10023e9c: 7902 ldrb r2, [r0, #4] +10023e9e: 710a strb r2, [r1, #4] +10023ea0: 2208 movs r2, #8 +10023ea2: 7940 ldrb r0, [r0, #5] +10023ea4: 7148 strb r0, [r1, #5] +10023ea6: 2000 movs r0, #0 +10023ea8: 80c8 strh r0, [r1, #6] +10023eaa: 9806 ldr r0, [sp, #24] +10023eac: 303d adds r0, #61 ; 0x3d +10023eae: f7e8 fa4b bl 1000c348 +10023eb2: e028 b.n 10023f06 +10023eb4: 2208 movs r2, #8 +10023eb6: 2100 movs r1, #0 +10023eb8: a80b add r0, sp, #44 ; 0x2c +10023eba: f7e8 fa47 bl 1000c34c +10023ebe: f000 f8bd bl 1002403c <.text_55> +10023ec2: f000 f8c1 bl 10024048 <.text_56> +10023ec6: f000 f8b3 bl 10024030 <.text_54> +10023eca: f8db 1034 ldr.w r1, [fp, #52] ; 0x34 +10023ece: 7808 ldrb r0, [r1, #0] +10023ed0: 28dd cmp r0, #221 ; 0xdd +10023ed2: d106 bne.n 10023ee2 +10023ed4: 7848 ldrb r0, [r1, #1] +10023ed6: f100 0902 add.w r9, r0, #2 +10023eda: 464a mov r2, r9 +10023edc: a83b add r0, sp, #236 ; 0xec +10023ede: f7e8 fa33 bl 1000c348 +10023ee2: 9906 ldr r1, [sp, #24] +10023ee4: ea4f 4009 mov.w r0, r9, lsl #16 +10023ee8: 0e00 lsrs r0, r0, #24 +10023eea: f881 005d strb.w r0, [r1, #93] ; 0x5d +10023eee: 464a mov r2, r9 +10023ef0: 9806 ldr r0, [sp, #24] +10023ef2: f880 905e strb.w r9, [r0, #94] ; 0x5e +10023ef6: a93b add r1, sp, #236 ; 0xec +10023ef8: 9806 ldr r0, [sp, #24] +10023efa: 305f adds r0, #95 ; 0x5f +10023efc: f7e8 fa24 bl 1000c348 +10023f00: f109 005f add.w r0, r9, #95 ; 0x5f +10023f04: 9007 str r0, [sp, #28] +10023f06: 2501 movs r5, #1 +10023f08: e68b b.n 10023c22 +10023f0a: 9f0a ldr r7, [sp, #40] ; 0x28 +10023f0c: 6928 ldr r0, [r5, #16] +10023f0e: 463a mov r2, r7 +10023f10: 4631 mov r1, r6 +10023f12: f7e8 fa19 bl 1000c348 +10023f16: 4639 mov r1, r7 +10023f18: 4628 mov r0, r5 +10023f1a: f7ed fa6b bl 100113f4 +10023f1e: f000 fa2c bl 1002437a <.text_59> +10023f22: 4628 mov r0, r5 +10023f24: 4790 blx r2 +10023f26: 2164 movs r1, #100 ; 0x64 +10023f28: f504 703d add.w r0, r4, #756 ; 0x2f4 +10023f2c: f7ec fd85 bl 10010a3a +10023f30: b05b add sp, #364 ; 0x16c +10023f32: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + ... + +10023f38 : +10023f38: 5452 384c 3931 4135 445b 6972 6576 5d72 RTL8195A[Driver] +10023f48: 203a 7061 6d20 646f 2065 2d34 0a31 0000 : ap mode 4-1... + +10023f58 : +10023f58: 5452 384c 3931 4135 445b 6972 6576 5d72 RTL8195A[Driver] +10023f68: 203a 7061 6d20 646f 2065 2d34 0a33 0000 : ap mode 4-3... + +10023f78 : +10023f78: 16dd 0f00 01ac 0001 ........ + +10023f80 <.text_44>: +10023f80: 7008 strb r0, [r1, #0] +10023f82: 9806 ldr r0, [sp, #24] +10023f84: 9906 ldr r1, [sp, #24] +10023f86: 7880 ldrb r0, [r0, #2] +10023f88: f000 00f8 and.w r0, r0, #248 ; 0xf8 +10023f8c: 7088 strb r0, [r1, #2] +10023f8e: 4770 bx lr + +10023f90 <.text_45>: +10023f90: 7108 strb r0, [r1, #4] +10023f92: e9dd 0106 ldrd r0, r1, [sp, #24] +10023f96: 69a3 ldr r3, [r4, #24] +10023f98: 6962 ldr r2, [r4, #20] +10023f9a: f7ff b944 b.w 10023226 + +10023f9e <.text_46>: +10023f9e: 7048 strb r0, [r1, #1] +10023fa0: 9806 ldr r0, [sp, #24] +10023fa2: 9906 ldr r1, [sp, #24] +10023fa4: 7840 ldrb r0, [r0, #1] +10023fa6: f000 00fd and.w r0, r0, #253 ; 0xfd +10023faa: 7048 strb r0, [r1, #1] +10023fac: 9806 ldr r0, [sp, #24] +10023fae: 9906 ldr r1, [sp, #24] +10023fb0: 7840 ldrb r0, [r0, #1] +10023fb2: f000 00fb and.w r0, r0, #251 ; 0xfb +10023fb6: 7048 strb r0, [r1, #1] +10023fb8: 9806 ldr r0, [sp, #24] +10023fba: 9906 ldr r1, [sp, #24] +10023fbc: 7840 ldrb r0, [r0, #1] +10023fbe: f000 00f7 and.w r0, r0, #247 ; 0xf7 +10023fc2: 7048 strb r0, [r1, #1] +10023fc4: 9906 ldr r1, [sp, #24] +10023fc6: 70cd strb r5, [r1, #3] +10023fc8: 7c20 ldrb r0, [r4, #16] +10023fca: 9906 ldr r1, [sp, #24] +10023fcc: 2802 cmp r0, #2 +10023fce: 4770 bx lr + +10023fd0 <.text_47>: +10023fd0: 9806 ldr r0, [sp, #24] +10023fd2: 6aa2 ldr r2, [r4, #40] ; 0x28 +10023fd4: 6a61 ldr r1, [r4, #36] ; 0x24 +10023fd6: 300d adds r0, #13 +10023fd8: f7e8 b9b6 b.w 1000c348 + +10023fdc <.text_48>: +10023fdc: 4659 mov r1, fp +10023fde: 4668 mov r0, sp +10023fe0: 2220 movs r2, #32 +10023fe2: f00a ba63 b.w 1002e4ac <__iar_unaligned___aeabi_memcpy4> + +10023fe6 <.text_49>: +10023fe6: 7088 strb r0, [r1, #2] +10023fe8: 9806 ldr r0, [sp, #24] +10023fea: 9906 ldr r1, [sp, #24] +10023fec: 7880 ldrb r0, [r0, #2] +10023fee: f040 0080 orr.w r0, r0, #128 ; 0x80 +10023ff2: 7088 strb r0, [r1, #2] +10023ff4: 9806 ldr r0, [sp, #24] +10023ff6: 9906 ldr r1, [sp, #24] +10023ff8: 7840 ldrb r0, [r0, #1] +10023ffa: 4770 bx lr + +10023ffc <.text_50>: +10023ffc: 7088 strb r0, [r1, #2] +10023ffe: 9806 ldr r0, [sp, #24] +10024000: 9906 ldr r1, [sp, #24] +10024002: 7880 ldrb r0, [r0, #2] +10024004: f000 00cf and.w r0, r0, #207 ; 0xcf +10024008: 7088 strb r0, [r1, #2] +1002400a: 9806 ldr r0, [sp, #24] +1002400c: 9906 ldr r1, [sp, #24] +1002400e: 7880 ldrb r0, [r0, #2] +10024010: 4770 bx lr + +10024012 <.text_51>: +10024012: f104 0014 add.w r0, r4, #20 +10024016: f7ff b916 b.w 10023246 + +1002401a <.text_52>: +1002401a: 2210 movs r2, #16 +1002401c: 2100 movs r1, #0 +1002401e: a811 add r0, sp, #68 ; 0x44 +10024020: f7e8 b994 b.w 1000c34c + +10024024 <.text_53>: +10024024: 9806 ldr r0, [sp, #24] +10024026: 2210 movs r2, #16 +10024028: a911 add r1, sp, #68 ; 0x44 +1002402a: 302d adds r0, #45 ; 0x2d +1002402c: f7e8 b98c b.w 1000c348 + +10024030 <.text_54>: +10024030: 9806 ldr r0, [sp, #24] +10024032: 2208 movs r2, #8 +10024034: a90d add r1, sp, #52 ; 0x34 +10024036: 3045 adds r0, #69 ; 0x45 +10024038: f7e8 b986 b.w 1000c348 + +1002403c <.text_55>: +1002403c: 9806 ldr r0, [sp, #24] +1002403e: 2208 movs r2, #8 +10024040: a90b add r1, sp, #44 ; 0x2c +10024042: 303d adds r0, #61 ; 0x3d +10024044: f7e8 b980 b.w 1000c348 + +10024048 <.text_56>: +10024048: 2208 movs r2, #8 +1002404a: 4629 mov r1, r5 +1002404c: a80d add r0, sp, #52 ; 0x34 +1002404e: f7e8 b97d b.w 1000c34c + +10024052 : +10024052: e92d 4ff6 stmdb sp!, {r1, r2, r4, r5, r6, r7, r8, r9, sl, fp, lr} +10024056: 4682 mov sl, r0 +10024058: f50a 5088 add.w r0, sl, #4352 ; 0x1100 +1002405c: 30f0 adds r0, #240 ; 0xf0 +1002405e: 2400 movs r4, #0 +10024060: 2800 cmp r0, #0 +10024062: bf18 it ne +10024064: 2900 cmpne r1, #0 +10024066: b095 sub sp, #84 ; 0x54 +10024068: f04f 0801 mov.w r8, #1 +1002406c: d018 beq.n 100240a0 +1002406e: f8d0 b630 ldr.w fp, [r0, #1584] ; 0x630 +10024072: f200 4994 addw r9, r0, #1172 ; 0x494 +10024076: f8db 00dc ldr.w r0, [fp, #220] ; 0xdc +1002407a: 9002 str r0, [sp, #8] +1002407c: f10b 06dc add.w r6, fp, #220 ; 0xdc +10024080: 3012 adds r0, #18 +10024082: 9000 str r0, [sp, #0] +10024084: 6130 str r0, [r6, #16] +10024086: f50b 7741 add.w r7, fp, #772 ; 0x304 +1002408a: 9816 ldr r0, [sp, #88] ; 0x58 +1002408c: b148 cbz r0, 100240a2 +1002408e: 6870 ldr r0, [r6, #4] +10024090: 9003 str r0, [sp, #12] +10024092: 2800 cmp r0, #0 +10024094: 6971 ldr r1, [r6, #20] +10024096: 9101 str r1, [sp, #4] +10024098: d002 beq.n 100240a0 +1002409a: 2900 cmp r1, #0 +1002409c: f040 8116 bne.w 100242cc +100240a0: e163 b.n 1002436a +100240a2: 6878 ldr r0, [r7, #4] +100240a4: 2800 cmp r0, #0 +100240a6: f10b 0508 add.w r5, fp, #8 +100240aa: f040 8095 bne.w 100241d8 +100240ae: f8db 0304 ldr.w r0, [fp, #772] ; 0x304 +100240b2: 2800 cmp r0, #0 +100240b4: d160 bne.n 10024178 +100240b6: f8cb 8304 str.w r8, [fp, #772] ; 0x304 +100240ba: f000 fce2 bl 10024a82 <.text_82> +100240be: f000 f9c0 bl 10024442 <.text_72> +100240c2: bf4c ite mi +100240c4: 2108 movmi r1, #8 +100240c6: 2100 movpl r1, #0 +100240c8: 4308 orrs r0, r1 +100240ca: 9900 ldr r1, [sp, #0] +100240cc: f000 00cf and.w r0, r0, #207 ; 0xcf +100240d0: 7088 strb r0, [r1, #2] +100240d2: 68b1 ldr r1, [r6, #8] +100240d4: 7889 ldrb r1, [r1, #2] +100240d6: f3c1 1101 ubfx r1, r1, #4, #2 +100240da: b101 cbz r1, 100240de +100240dc: 2140 movs r1, #64 ; 0x40 +100240de: f000 00bf and.w r0, r0, #191 ; 0xbf +100240e2: 4308 orrs r0, r1 +100240e4: 9900 ldr r1, [sp, #0] +100240e6: f000 007f and.w r0, r0, #127 ; 0x7f +100240ea: f000 f988 bl 100243fe <.text_70> +100240ee: bf4c ite mi +100240f0: 2102 movmi r1, #2 +100240f2: 2100 movpl r1, #0 +100240f4: 4308 orrs r0, r1 +100240f6: 9900 ldr r1, [sp, #0] +100240f8: 7048 strb r0, [r1, #1] +100240fa: f000 00fb and.w r0, r0, #251 ; 0xfb +100240fe: 68b1 ldr r1, [r6, #8] +10024100: 7849 ldrb r1, [r1, #1] +10024102: 0749 lsls r1, r1, #29 +10024104: bf4c ite mi +10024106: 2104 movmi r1, #4 +10024108: 2100 movpl r1, #0 +1002410a: 4308 orrs r0, r1 +1002410c: 9900 ldr r1, [sp, #0] +1002410e: 7048 strb r0, [r1, #1] +10024110: f000 00f7 and.w r0, r0, #247 ; 0xf7 +10024114: 68b1 ldr r1, [r6, #8] +10024116: 7849 ldrb r1, [r1, #1] +10024118: 0709 lsls r1, r1, #28 +1002411a: bf4c ite mi +1002411c: 2108 movmi r1, #8 +1002411e: 2100 movpl r1, #0 +10024120: 4308 orrs r0, r1 +10024122: 9900 ldr r1, [sp, #0] +10024124: f000 f978 bl 10024418 <.text_71> +10024128: 9800 ldr r0, [sp, #0] +1002412a: 6aaa ldr r2, [r5, #40] ; 0x28 +1002412c: 6a69 ldr r1, [r5, #36] ; 0x24 +1002412e: f7ff ff52 bl 10023fd6 <.text_47+0x6> +10024132: f000 f93e bl 100243b2 <.text_64> +10024136: f000 f936 bl 100243a6 <.text_63> +1002413a: f000 f950 bl 100243de <.text_68> +1002413e: f000 f948 bl 100243d2 <.text_67> +10024142: f000 f941 bl 100243c8 <.text_66> +10024146: f000 f939 bl 100243bc <.text_65> +1002414a: f109 0534 add.w r5, r9, #52 ; 0x34 +1002414e: 9900 ldr r1, [sp, #0] +10024150: 6868 ldr r0, [r5, #4] +10024152: 1200 asrs r0, r0, #8 +10024154: f881 005d strb.w r0, [r1, #93] ; 0x5d +10024158: 9900 ldr r1, [sp, #0] +1002415a: 6868 ldr r0, [r5, #4] +1002415c: f881 005e strb.w r0, [r1, #94] ; 0x5e +10024160: 9800 ldr r0, [sp, #0] +10024162: 686a ldr r2, [r5, #4] +10024164: f8d9 1034 ldr.w r1, [r9, #52] ; 0x34 +10024168: 305f adds r0, #95 ; 0x5f +1002416a: f7e8 f8ed bl 1000c348 +1002416e: 6868 ldr r0, [r5, #4] +10024170: 305f adds r0, #95 ; 0x5f +10024172: 9001 str r0, [sp, #4] +10024174: 3012 adds r0, #18 +10024176: e0a4 b.n 100242c2 +10024178: f8c7 8004 str.w r8, [r7, #4] +1002417c: f8cb 4304 str.w r4, [fp, #772] ; 0x304 +10024180: f000 fc7f bl 10024a82 <.text_82> +10024184: f000 f95d bl 10024442 <.text_72> +10024188: bf4c ite mi +1002418a: 2108 movmi r1, #8 +1002418c: 2100 movpl r1, #0 +1002418e: 4308 orrs r0, r1 +10024190: 9900 ldr r1, [sp, #0] +10024192: f000 000f and.w r0, r0, #15 +10024196: f000 f932 bl 100243fe <.text_70> +1002419a: bf4c ite mi +1002419c: 2102 movmi r1, #2 +1002419e: 2100 movpl r1, #0 +100241a0: 4308 orrs r0, r1 +100241a2: 9900 ldr r1, [sp, #0] +100241a4: f000 00f3 and.w r0, r0, #243 ; 0xf3 +100241a8: f000 f936 bl 10024418 <.text_71> +100241ac: f000 f901 bl 100243b2 <.text_64> +100241b0: f000 f8f9 bl 100243a6 <.text_63> +100241b4: f000 f913 bl 100243de <.text_68> +100241b8: f000 f90b bl 100243d2 <.text_67> +100241bc: f000 f904 bl 100243c8 <.text_66> +100241c0: f000 f8fc bl 100243bc <.text_65> +100241c4: f000 f910 bl 100243e8 <.text_69> +100241c8: 60fc str r4, [r7, #12] +100241ca: 613c str r4, [r7, #16] +100241cc: 4650 mov r0, sl +100241ce: f60f 11cc addw r1, pc, #2508 ; 0x9cc +100241d2: f7ef fe69 bl 10013ea8 +100241d6: e075 b.n 100242c4 +100241d8: 68b8 ldr r0, [r7, #8] +100241da: 2800 cmp r0, #0 +100241dc: 9800 ldr r0, [sp, #0] +100241de: f44f 72f7 mov.w r2, #494 ; 0x1ee +100241e2: 4621 mov r1, r4 +100241e4: d02a beq.n 1002423c +100241e6: f7e8 f8b1 bl 1000c34c +100241ea: f000 f92a bl 10024442 <.text_72> +100241ee: bf4c ite mi +100241f0: 2108 movmi r1, #8 +100241f2: 2100 movpl r1, #0 +100241f4: 4308 orrs r0, r1 +100241f6: 9900 ldr r1, [sp, #0] +100241f8: f000 000f and.w r0, r0, #15 +100241fc: 7088 strb r0, [r1, #2] +100241fe: 2208 movs r2, #8 +10024200: 9800 ldr r0, [sp, #0] +10024202: 7840 ldrb r0, [r0, #1] +10024204: 9900 ldr r1, [sp, #0] +10024206: f000 00f3 and.w r0, r0, #243 ; 0xf3 +1002420a: f040 0003 orr.w r0, r0, #3 +1002420e: 7048 strb r0, [r1, #1] +10024210: f000 f904 bl 1002441c <.text_71+0x4> +10024214: f000 f8b7 bl 10024386 <.text_60> +10024218: f000 f8ba bl 10024390 <.text_61> +1002421c: f000 f8be bl 1002439c <.text_62> +10024220: f000 f8c1 bl 100243a6 <.text_63> +10024224: f000 f8db bl 100243de <.text_68> +10024228: f000 f8d3 bl 100243d2 <.text_67> +1002422c: f000 f8cc bl 100243c8 <.text_66> +10024230: f000 f8c4 bl 100243bc <.text_65> +10024234: f000 f8d8 bl 100243e8 <.text_69> +10024238: 60bc str r4, [r7, #8] +1002423a: e043 b.n 100242c4 +1002423c: f7e8 f886 bl 1000c34c +10024240: f89b 0008 ldrb.w r0, [fp, #8] +10024244: 9900 ldr r1, [sp, #0] +10024246: 0780 lsls r0, r0, #30 +10024248: bf4c ite mi +1002424a: 2002 movmi r0, #2 +1002424c: 20fe movpl r0, #254 ; 0xfe +1002424e: 7008 strb r0, [r1, #0] +10024250: f899 00bc ldrb.w r0, [r9, #188] ; 0xbc +10024254: 2804 cmp r0, #4 +10024256: bf1a itte ne +10024258: 7a28 ldrbne r0, [r5, #8] +1002425a: 2804 cmpne r0, #4 +1002425c: f04f 0802 moveq.w r8, #2 +10024260: 9800 ldr r0, [sp, #0] +10024262: f880 8002 strb.w r8, [r0, #2] +10024266: 9800 ldr r0, [sp, #0] +10024268: 9900 ldr r1, [sp, #0] +1002426a: 7840 ldrb r0, [r0, #1] +1002426c: f040 000f orr.w r0, r0, #15 +10024270: 7048 strb r0, [r1, #1] +10024272: 9900 ldr r1, [sp, #0] +10024274: 70cc strb r4, [r1, #3] +10024276: 9900 ldr r1, [sp, #0] +10024278: 710c strb r4, [r1, #4] +1002427a: e9dd 0100 ldrd r0, r1, [sp] +1002427e: 693b ldr r3, [r7, #16] +10024280: 68fa ldr r2, [r7, #12] +10024282: f7fe ffd0 bl 10023226 +10024286: f50b 7044 add.w r0, fp, #784 ; 0x310 +1002428a: f7fe ffdc bl 10023246 +1002428e: f000 f87a bl 10024386 <.text_60> +10024292: f000 f87d bl 10024390 <.text_61> +10024296: f000 f881 bl 1002439c <.text_62> +1002429a: f000 f884 bl 100243a6 <.text_63> +1002429e: f000 f89e bl 100243de <.text_68> +100242a2: f000 f896 bl 100243d2 <.text_67> +100242a6: f000 f88f bl 100243c8 <.text_66> +100242aa: f000 f887 bl 100243bc <.text_65> +100242ae: 9900 ldr r1, [sp, #0] +100242b0: f881 405d strb.w r4, [r1, #93] ; 0x5d +100242b4: 205f movs r0, #95 ; 0x5f +100242b6: 9900 ldr r1, [sp, #0] +100242b8: f881 405e strb.w r4, [r1, #94] ; 0x5e +100242bc: 9001 str r0, [sp, #4] +100242be: 2401 movs r4, #1 +100242c0: 2071 movs r0, #113 ; 0x71 +100242c2: 9003 str r0, [sp, #12] +100242c4: 9803 ldr r0, [sp, #12] +100242c6: 6070 str r0, [r6, #4] +100242c8: 9801 ldr r0, [sp, #4] +100242ca: 6170 str r0, [r6, #20] +100242cc: 2206 movs r2, #6 +100242ce: 9815 ldr r0, [sp, #84] ; 0x54 +100242d0: f8dd 9008 ldr.w r9, [sp, #8] +100242d4: f500 7184 add.w r1, r0, #264 ; 0x108 +100242d8: 4648 mov r0, r9 +100242da: f7e8 f835 bl 1000c348 +100242de: f50a 51c8 add.w r1, sl, #6400 ; 0x1900 +100242e2: 2206 movs r2, #6 +100242e4: 3195 adds r1, #149 ; 0x95 +100242e6: f109 0006 add.w r0, r9, #6 +100242ea: f7e8 f82d bl 1000c348 +100242ee: f648 008e movw r0, #34958 ; 0x888e +100242f2: f7ec fa15 bl 10010720 <_htons> +100242f6: f8a9 000c strh.w r0, [r9, #12] +100242fa: 9802 ldr r0, [sp, #8] +100242fc: f100 050e add.w r5, r0, #14 +10024300: 2001 movs r0, #1 +10024302: 7028 strb r0, [r5, #0] +10024304: 2003 movs r0, #3 +10024306: 7068 strb r0, [r5, #1] +10024308: 9801 ldr r0, [sp, #4] +1002430a: b280 uxth r0, r0 +1002430c: f7ec fa08 bl 10010720 <_htons> +10024310: 8068 strh r0, [r5, #2] +10024312: 9816 ldr r0, [sp, #88] ; 0x58 +10024314: b980 cbnz r0, 10024338 +10024316: f10b 0394 add.w r3, fp, #148 ; 0x94 +1002431a: b11c cbz r4, 10024324 +1002431c: 2010 movs r0, #16 +1002431e: 9000 str r0, [sp, #0] +10024320: 4642 mov r2, r8 +10024322: e005 b.n 10024330 +10024324: 2010 movs r0, #16 +10024326: 9000 str r0, [sp, #0] +10024328: 68b0 ldr r0, [r6, #8] +1002432a: 7880 ldrb r0, [r0, #2] +1002432c: f000 0207 and.w r2, r0, #7 +10024330: e9dd 0102 ldrd r0, r1, [sp, #8] +10024334: f7ff f89e bl 10023474 +10024338: f000 f81a bl 10024370 <.text_58> +1002433c: 0006 movs r6, r0 +1002433e: d014 beq.n 1002436a +10024340: 9c03 ldr r4, [sp, #12] +10024342: 6930 ldr r0, [r6, #16] +10024344: 4622 mov r2, r4 +10024346: 4649 mov r1, r9 +10024348: f7e7 fffe bl 1000c348 +1002434c: 4621 mov r1, r4 +1002434e: 4630 mov r0, r6 +10024350: f7ed f850 bl 100113f4 +10024354: f000 f811 bl 1002437a <.text_59> +10024358: 4630 mov r0, r6 +1002435a: 4790 blx r2 +1002435c: 6878 ldr r0, [r7, #4] +1002435e: b920 cbnz r0, 1002436a +10024360: 2164 movs r1, #100 ; 0x64 +10024362: f50b 703d add.w r0, fp, #756 ; 0x2f4 +10024366: f7ec fb68 bl 10010a3a +1002436a: b017 add sp, #92 ; 0x5c +1002436c: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +10024370 <.text_58>: +10024370: 214a movs r1, #74 ; 0x4a +10024372: f44f 7000 mov.w r0, #512 ; 0x200 +10024376: f7ed b811 b.w 1001139c + +1002437a <.text_59>: +1002437a: f641 5024 movw r0, #7460 ; 0x1d24 +1002437e: f850 100a ldr.w r1, [r0, sl] +10024382: 6a8a ldr r2, [r1, #40] ; 0x28 +10024384: 4770 bx lr + +10024386 <.text_60>: +10024386: 2220 movs r2, #32 +10024388: 2100 movs r1, #0 +1002438a: a80c add r0, sp, #48 ; 0x30 +1002438c: f7e7 bfde b.w 1000c34c + +10024390 <.text_61>: +10024390: 9800 ldr r0, [sp, #0] +10024392: 2220 movs r2, #32 +10024394: a90c add r1, sp, #48 ; 0x30 +10024396: 300d adds r0, #13 +10024398: f7e7 bfd6 b.w 1000c348 + +1002439c <.text_62>: +1002439c: 2210 movs r2, #16 +1002439e: 4621 mov r1, r4 +100243a0: a808 add r0, sp, #32 +100243a2: f7e7 bfd3 b.w 1000c34c + +100243a6 <.text_63>: +100243a6: 9800 ldr r0, [sp, #0] +100243a8: 2210 movs r2, #16 +100243aa: a908 add r1, sp, #32 +100243ac: 302d adds r0, #45 ; 0x2d +100243ae: f7e7 bfcb b.w 1000c348 + +100243b2 <.text_64>: +100243b2: 2210 movs r2, #16 +100243b4: 2100 movs r1, #0 +100243b6: a808 add r0, sp, #32 +100243b8: f7e7 bfc8 b.w 1000c34c + +100243bc <.text_65>: +100243bc: 9800 ldr r0, [sp, #0] +100243be: 2208 movs r2, #8 +100243c0: a904 add r1, sp, #16 +100243c2: 3045 adds r0, #69 ; 0x45 +100243c4: f7e7 bfc0 b.w 1000c348 + +100243c8 <.text_66>: +100243c8: 2208 movs r2, #8 +100243ca: 4621 mov r1, r4 +100243cc: a804 add r0, sp, #16 +100243ce: f7e7 bfbd b.w 1000c34c + +100243d2 <.text_67>: +100243d2: 9800 ldr r0, [sp, #0] +100243d4: 2208 movs r2, #8 +100243d6: a906 add r1, sp, #24 +100243d8: 303d adds r0, #61 ; 0x3d +100243da: f7e7 bfb5 b.w 1000c348 + +100243de <.text_68>: +100243de: 2208 movs r2, #8 +100243e0: 4621 mov r1, r4 +100243e2: a806 add r0, sp, #24 +100243e4: f7e7 bfb2 b.w 1000c34c + +100243e8 <.text_69>: +100243e8: 9900 ldr r1, [sp, #0] +100243ea: f881 405d strb.w r4, [r1, #93] ; 0x5d +100243ee: 205f movs r0, #95 ; 0x5f +100243f0: 9900 ldr r1, [sp, #0] +100243f2: f881 405e strb.w r4, [r1, #94] ; 0x5e +100243f6: 9001 str r0, [sp, #4] +100243f8: 2071 movs r0, #113 ; 0x71 +100243fa: 9003 str r0, [sp, #12] +100243fc: 4770 bx lr + +100243fe <.text_70>: +100243fe: 7088 strb r0, [r1, #2] +10024400: 9800 ldr r0, [sp, #0] +10024402: 9900 ldr r1, [sp, #0] +10024404: 7840 ldrb r0, [r0, #1] +10024406: f040 0001 orr.w r0, r0, #1 +1002440a: 7048 strb r0, [r1, #1] +1002440c: f000 00fd and.w r0, r0, #253 ; 0xfd +10024410: 68b1 ldr r1, [r6, #8] +10024412: 7849 ldrb r1, [r1, #1] +10024414: 0789 lsls r1, r1, #30 +10024416: 4770 bx lr + +10024418 <.text_71>: +10024418: 7048 strb r0, [r1, #1] +1002441a: 2208 movs r2, #8 +1002441c: 68b0 ldr r0, [r6, #8] +1002441e: 78c1 ldrb r1, [r0, #3] +10024420: 7900 ldrb r0, [r0, #4] +10024422: eb00 2001 add.w r0, r0, r1, lsl #8 +10024426: 9900 ldr r1, [sp, #0] +10024428: 0400 lsls r0, r0, #16 +1002442a: 0e00 lsrs r0, r0, #24 +1002442c: 70c8 strb r0, [r1, #3] +1002442e: 68b0 ldr r0, [r6, #8] +10024430: 9900 ldr r1, [sp, #0] +10024432: 7900 ldrb r0, [r0, #4] +10024434: 7108 strb r0, [r1, #4] +10024436: 68b0 ldr r0, [r6, #8] +10024438: 1d41 adds r1, r0, #5 +1002443a: 9800 ldr r0, [sp, #0] +1002443c: 1d40 adds r0, r0, #5 +1002443e: f7e7 bf83 b.w 1000c348 + +10024442 <.text_72>: +10024442: 68b0 ldr r0, [r6, #8] +10024444: 9900 ldr r1, [sp, #0] +10024446: 7800 ldrb r0, [r0, #0] +10024448: 7008 strb r0, [r1, #0] +1002444a: 9800 ldr r0, [sp, #0] +1002444c: 9900 ldr r1, [sp, #0] +1002444e: 7880 ldrb r0, [r0, #2] +10024450: f000 00f8 and.w r0, r0, #248 ; 0xf8 +10024454: 7088 strb r0, [r1, #2] +10024456: 68b1 ldr r1, [r6, #8] +10024458: 7889 ldrb r1, [r1, #2] +1002445a: f001 0107 and.w r1, r1, #7 +1002445e: 4308 orrs r0, r1 +10024460: 9900 ldr r1, [sp, #0] +10024462: 7088 strb r0, [r1, #2] +10024464: f000 00f7 and.w r0, r0, #247 ; 0xf7 +10024468: 68b1 ldr r1, [r6, #8] +1002446a: 7889 ldrb r1, [r1, #2] +1002446c: 0709 lsls r1, r1, #28 +1002446e: 4770 bx lr + +10024470 : +10024470: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +10024474: 4604 mov r4, r0 +10024476: 4688 mov r8, r1 +10024478: b087 sub sp, #28 +1002447a: f504 5088 add.w r0, r4, #4352 ; 0x1100 +1002447e: 30f0 adds r0, #240 ; 0xf0 +10024480: f8d8 10fc ldr.w r1, [r8, #252] ; 0xfc +10024484: f200 4694 addw r6, r0, #1172 ; 0x494 +10024488: eb00 0081 add.w r0, r0, r1, lsl #2 +1002448c: f8d0 762c ldr.w r7, [r0, #1580] ; 0x62c +10024490: f8d7 00d4 ldr.w r0, [r7, #212] ; 0xd4 +10024494: 7bc1 ldrb r1, [r0, #15] +10024496: 2903 cmp r1, #3 +10024498: d114 bne.n 100244c4 +1002449a: 3012 adds r0, #18 +1002449c: f8c7 00e4 str.w r0, [r7, #228] ; 0xe4 +100244a0: 7841 ldrb r1, [r0, #1] +100244a2: f001 010d and.w r1, r1, #13 +100244a6: 290d cmp r1, #13 +100244a8: d00c beq.n 100244c4 +100244aa: 7880 ldrb r0, [r0, #2] +100244ac: 0700 lsls r0, r0, #28 +100244ae: d509 bpl.n 100244c4 +100244b0: 6839 ldr r1, [r7, #0] +100244b2: 2901 cmp r1, #1 +100244b4: f107 0594 add.w r5, r7, #148 ; 0x94 +100244b8: f507 793d add.w r9, r7, #756 ; 0x2f4 +100244bc: a04c add r0, pc, #304 ; (adr r0, 100245f0 <.text_74>) +100244be: d002 beq.n 100244c6 +100244c0: 2902 cmp r1, #2 +100244c2: d050 beq.n 10024566 +100244c4: e091 b.n 100245ea +100244c6: f7e7 ff1c bl 1000c302 +100244ca: f20f 60e8 addw r0, pc, #1768 ; 0x6e8 +100244ce: f7e7 ff18 bl 1000c302 +100244d2: f107 03e4 add.w r3, r7, #228 ; 0xe4 +100244d6: aa04 add r2, sp, #16 +100244d8: e9d3 0100 ldrd r0, r1, [r3] +100244dc: f7fe fe76 bl 100231cc +100244e0: a804 add r0, sp, #16 +100244e2: f7fe feb0 bl 10023246 +100244e6: 6978 ldr r0, [r7, #20] +100244e8: 9904 ldr r1, [sp, #16] +100244ea: 4288 cmp r0, r1 +100244ec: bf02 ittt eq +100244ee: 69b8 ldreq r0, [r7, #24] +100244f0: 9905 ldreq r1, [sp, #20] +100244f2: 4288 cmpeq r0, r1 +100244f4: d179 bne.n 100245ea +100244f6: 4648 mov r0, r9 +100244f8: f7ec faa6 bl 10010a48 +100244fc: 2020 movs r0, #32 +100244fe: 9000 str r0, [sp, #0] +10024500: f107 02e4 add.w r2, r7, #228 ; 0xe4 +10024504: 230d movs r3, #13 +10024506: e9d2 0100 ldrd r0, r1, [r2] +1002450a: 460a mov r2, r1 +1002450c: 4601 mov r1, r0 +1002450e: a801 add r0, sp, #4 +10024510: f7fe fe55 bl 100231be +10024514: 9901 ldr r1, [sp, #4] +10024516: 6af8 ldr r0, [r7, #44] ; 0x2c +10024518: 2220 movs r2, #32 +1002451a: f7ec f978 bl 1001080e +1002451e: f8d7 00d4 ldr.w r0, [r7, #212] ; 0xd4 +10024522: 2140 movs r1, #64 ; 0x40 +10024524: 9103 str r1, [sp, #12] +10024526: 9502 str r5, [sp, #8] +10024528: 2120 movs r1, #32 +1002452a: 9101 str r1, [sp, #4] +1002452c: f107 0174 add.w r1, r7, #116 ; 0x74 +10024530: 9100 str r1, [sp, #0] +10024532: 6afb ldr r3, [r7, #44] ; 0x2c +10024534: 6a7a ldr r2, [r7, #36] ; 0x24 +10024536: 1d81 adds r1, r0, #6 +10024538: f7fe fe32 bl 100231a0 +1002453c: f107 06d4 add.w r6, r7, #212 ; 0xd4 +10024540: 2310 movs r3, #16 +10024542: e9d6 0100 ldrd r0, r1, [r6] +10024546: 462a mov r2, r5 +10024548: f7fe ff52 bl 100233f0 +1002454c: 2800 cmp r0, #0 +1002454e: d04c beq.n 100245ea +10024550: 2000 movs r0, #0 +10024552: f8c7 0300 str.w r0, [r7, #768] ; 0x300 +10024556: 2200 movs r2, #0 +10024558: 2002 movs r0, #2 +1002455a: 6038 str r0, [r7, #0] +1002455c: 4641 mov r1, r8 +1002455e: 4620 mov r0, r4 +10024560: f7ff fa90 bl 10023a84 +10024564: e041 b.n 100245ea +10024566: f7e7 fecc bl 1000c302 +1002456a: f20f 6068 addw r0, pc, #1640 ; 0x668 +1002456e: f7e7 fec8 bl 1000c302 +10024572: f107 001c add.w r0, r7, #28 +10024576: f107 03e4 add.w r3, r7, #228 ; 0xe4 +1002457a: e9d0 ab00 ldrd sl, fp, [r0] +1002457e: e9d3 0100 ldrd r0, r1, [r3] +10024582: aa00 add r2, sp, #0 +10024584: f7fe fe22 bl 100231cc +10024588: 9900 ldr r1, [sp, #0] +1002458a: 458a cmp sl, r1 +1002458c: bf04 itt eq +1002458e: 9901 ldreq r1, [sp, #4] +10024590: 458b cmpeq fp, r1 +10024592: d0b0 beq.n 100244f6 +10024594: 4648 mov r0, r9 +10024596: f7ec fa57 bl 10010a48 +1002459a: f107 0cd4 add.w ip, r7, #212 ; 0xd4 +1002459e: 2310 movs r3, #16 +100245a0: e9dc 0100 ldrd r0, r1, [ip] +100245a4: 462a mov r2, r5 +100245a6: f7fe ff23 bl 100233f0 +100245aa: b938 cbnz r0, 100245bc +100245ac: 220e movs r2, #14 +100245ae: 4641 mov r1, r8 +100245b0: 4620 mov r0, r4 +100245b2: f7ff f934 bl 1002381e +100245b6: 2000 movs r0, #0 +100245b8: 6038 str r0, [r7, #0] +100245ba: e016 b.n 100245ea +100245bc: 4641 mov r1, r8 +100245be: 4620 mov r0, r4 +100245c0: f7ff f878 bl 100236b4 +100245c4: 2101 movs r1, #1 +100245c6: 4640 mov r0, r8 +100245c8: f7ff f920 bl 1002380c +100245cc: 2003 movs r0, #3 +100245ce: 6038 str r0, [r7, #0] +100245d0: 2001 movs r0, #1 +100245d2: 6078 str r0, [r7, #4] +100245d4: 6a70 ldr r0, [r6, #36] ; 0x24 +100245d6: 2800 cmp r0, #0 +100245d8: bf04 itt eq +100245da: 6b30 ldreq r0, [r6, #48] ; 0x30 +100245dc: 2800 cmpeq r0, #0 +100245de: d104 bne.n 100245ea +100245e0: 4620 mov r0, r4 +100245e2: f7ff f8c7 bl 10023774 +100245e6: 2001 movs r0, #1 +100245e8: 6330 str r0, [r6, #48] ; 0x30 +100245ea: b007 add sp, #28 +100245ec: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +100245f0 <.text_74>: +100245f0: 00000d0a .word 0x00000d0a + +100245f4 <.text_75>: +100245f4: 1004817c .word 0x1004817c + +100245f8 : +100245f8: e92d 4ff2 stmdb sp!, {r1, r4, r5, r6, r7, r8, r9, sl, fp, lr} +100245fc: 4681 mov r9, r0 +100245fe: f509 5088 add.w r0, r9, #4352 ; 0x1100 +10024602: f100 0bf0 add.w fp, r0, #240 ; 0xf0 +10024606: b0e8 sub sp, #416 ; 0x1a0 +10024608: f8db 8630 ldr.w r8, [fp, #1584] ; 0x630 +1002460c: f8d8 00d4 ldr.w r0, [r8, #212] ; 0xd4 +10024610: 7bc1 ldrb r1, [r0, #15] +10024612: 2600 movs r6, #0 +10024614: 2903 cmp r1, #3 +10024616: f20b 4a94 addw sl, fp, #1172 ; 0x494 +1002461a: d12f bne.n 1002467c +1002461c: f108 07d4 add.w r7, r8, #212 ; 0xd4 +10024620: 3012 adds r0, #18 +10024622: 6138 str r0, [r7, #16] +10024624: f508 7440 add.w r4, r8, #768 ; 0x300 +10024628: 7881 ldrb r1, [r0, #2] +1002462a: 0709 lsls r1, r1, #28 +1002462c: f108 0510 add.w r5, r8, #16 +10024630: f140 8112 bpl.w 10024858 +10024634: 7840 ldrb r0, [r0, #1] +10024636: 07c0 lsls r0, r0, #31 +10024638: d459 bmi.n 100246ee +1002463a: 68a0 ldr r0, [r4, #8] +1002463c: 2800 cmp r0, #0 +1002463e: bf04 itt eq +10024640: 6860 ldreq r0, [r4, #4] +10024642: 2800 cmpeq r0, #0 +10024644: d007 beq.n 10024656 +10024646: f04f 30ff mov.w r0, #4294967295 +1002464a: 6068 str r0, [r5, #4] +1002464c: 60a8 str r0, [r5, #8] +1002464e: 6066 str r6, [r4, #4] +10024650: 60a6 str r6, [r4, #8] +10024652: f8ca 6030 str.w r6, [sl, #48] ; 0x30 +10024656: 6868 ldr r0, [r5, #4] +10024658: f110 0f01 cmn.w r0, #1 +1002465c: bf04 itt eq +1002465e: 68a8 ldreq r0, [r5, #8] +10024660: f110 0f01 cmneq.w r0, #1 +10024664: d00c beq.n 10024680 +10024666: f108 00e4 add.w r0, r8, #228 ; 0xe4 +1002466a: f108 0714 add.w r7, r8, #20 +1002466e: e9d0 2300 ldrd r2, r3, [r0] +10024672: e9d7 0100 ldrd r0, r1, [r7] +10024676: f7fe fdc1 bl 100231fc +1002467a: 2800 cmp r0, #0 +1002467c: f040 815d bne.w 1002493a +10024680: f241 10f4 movw r0, #4596 ; 0x11f4 +10024684: f850 0009 ldr.w r0, [r0, r9] +10024688: f888 0010 strb.w r0, [r8, #16] +1002468c: 4650 mov r0, sl +1002468e: f7fe fe14 bl 100232ba +10024692: b082 sub sp, #8 +10024694: 4651 mov r1, sl +10024696: f7ff fca2 bl 10023fde <.text_48+0x2> +1002469a: f108 0a2c add.w sl, r8, #44 ; 0x2c +1002469e: bc0c pop {r2, r3} +100246a0: e9da 0100 ldrd r0, r1, [sl] +100246a4: f7fe fe41 bl 1002332a +100246a8: 2020 movs r0, #32 +100246aa: 9000 str r0, [sp, #0] +100246ac: 230d movs r3, #13 +100246ae: f108 00e4 add.w r0, r8, #228 ; 0xe4 +100246b2: e9d0 a700 ldrd sl, r7, [r0] +100246b6: 4651 mov r1, sl +100246b8: 463a mov r2, r7 +100246ba: a801 add r0, sp, #4 +100246bc: f7fe fd7f bl 100231be +100246c0: 9901 ldr r1, [sp, #4] +100246c2: 6968 ldr r0, [r5, #20] +100246c4: 2220 movs r2, #32 +100246c6: f7ec f8a2 bl 1001080e +100246ca: f8d8 00d4 ldr.w r0, [r8, #212] ; 0xd4 +100246ce: 2140 movs r1, #64 ; 0x40 +100246d0: 9103 str r1, [sp, #12] +100246d2: f108 0194 add.w r1, r8, #148 ; 0x94 +100246d6: 9102 str r1, [sp, #8] +100246d8: 2120 movs r1, #32 +100246da: 9101 str r1, [sp, #4] +100246dc: f108 0174 add.w r1, r8, #116 ; 0x74 +100246e0: 9100 str r1, [sp, #0] +100246e2: 69eb ldr r3, [r5, #28] +100246e4: 696a ldr r2, [r5, #20] +100246e6: 1d81 adds r1, r0, #6 +100246e8: f7fe fd5a bl 100231a0 +100246ec: e120 b.n 10024930 +100246ee: f8c8 6300 str.w r6, [r8, #768] ; 0x300 +100246f2: f899 08cc ldrb.w r0, [r9, #2252] ; 0x8cc +100246f6: b108 cbz r0, 100246fc +100246f8: f889 6842 strb.w r6, [r9, #2114] ; 0x842 +100246fc: 6860 ldr r0, [r4, #4] +100246fe: 2800 cmp r0, #0 +10024700: d021 beq.n 10024746 +10024702: f508 703d add.w r0, r8, #756 ; 0x2f4 +10024706: f7ec f99f bl 10010a48 +1002470a: f108 03e4 add.w r3, r8, #228 ; 0xe4 +1002470e: aa06 add r2, sp, #24 +10024710: e9d3 0100 ldrd r0, r1, [r3] +10024714: f7fe fd5a bl 100231cc +10024718: 6868 ldr r0, [r5, #4] +1002471a: f110 0f01 cmn.w r0, #1 +1002471e: bf04 itt eq +10024720: 68a8 ldreq r0, [r5, #8] +10024722: f110 0f01 cmneq.w r0, #1 +10024726: d003 beq.n 10024730 +10024728: f000 f90a bl 10024940 <.text_77> +1002472c: 2800 cmp r0, #0 +1002472e: d1a5 bne.n 1002467c +10024730: 6938 ldr r0, [r7, #16] +10024732: 6969 ldr r1, [r5, #20] +10024734: 2220 movs r2, #32 +10024736: 300d adds r0, #13 +10024738: f7e7 fe04 bl 1000c344 +1002473c: 2800 cmp r0, #0 +1002473e: d19d bne.n 1002467c +10024740: f000 f908 bl 10024954 <.text_78> +10024744: 2800 cmp r0, #0 +10024746: f000 80f8 beq.w 1002493a +1002474a: 9806 ldr r0, [sp, #24] +1002474c: 6068 str r0, [r5, #4] +1002474e: 9807 ldr r0, [sp, #28] +10024750: 60a8 str r0, [r5, #8] +10024752: 6938 ldr r0, [r7, #16] +10024754: 7800 ldrb r0, [r0, #0] +10024756: 2802 cmp r0, #2 +10024758: d153 bne.n 10024802 +1002475a: f20f 4198 addw r1, pc, #1176 ; 0x498 +1002475e: 680a ldr r2, [r1, #0] +10024760: f20f 4194 addw r1, pc, #1172 ; 0x494 +10024764: a803 add r0, sp, #12 +10024766: f108 03a4 add.w r3, r8, #164 ; 0xa4 +1002476a: 6002 str r2, [r0, #0] +1002476c: a802 add r0, sp, #8 +1002476e: 680a ldr r2, [r1, #0] +10024770: 6002 str r2, [r0, #0] +10024772: a948 add r1, sp, #288 ; 0x120 +10024774: 6938 ldr r0, [r7, #16] +10024776: 9101 str r1, [sp, #4] +10024778: 2110 movs r1, #16 +1002477a: 9100 str r1, [sp, #0] +1002477c: f890 205e ldrb.w r2, [r0, #94] ; 0x5e +10024780: f890 105d ldrb.w r1, [r0, #93] ; 0x5d +10024784: eb02 2201 add.w r2, r2, r1, lsl #8 +10024788: f100 015f add.w r1, r0, #95 ; 0x5f +1002478c: b292 uxth r2, r2 +1002478e: 4640 mov r0, r8 +10024790: f7fe fea0 bl 100234d4 +10024794: 2800 cmp r0, #0 +10024796: d05e beq.n 10024856 +10024798: f89d 0120 ldrb.w r0, [sp, #288] ; 0x120 +1002479c: 2830 cmp r0, #48 ; 0x30 +1002479e: d149 bne.n 10024834 +100247a0: ac48 add r4, sp, #288 ; 0x120 +100247a2: a848 add r0, sp, #288 ; 0x120 +100247a4: 7861 ldrb r1, [r4, #1] +100247a6: 1808 adds r0, r1, r0 +100247a8: 1c85 adds r5, r0, #2 +100247aa: 7828 ldrb r0, [r5, #0] +100247ac: 2830 cmp r0, #48 ; 0x30 +100247ae: d052 beq.n 10024856 +100247b0: 28dd cmp r0, #221 ; 0xdd +100247b2: d120 bne.n 100247f6 +100247b4: 2204 movs r2, #4 +100247b6: a902 add r1, sp, #8 +100247b8: 1ca8 adds r0, r5, #2 +100247ba: f7e7 fdc3 bl 1000c344 +100247be: b910 cbnz r0, 100247c6 +100247c0: 7868 ldrb r0, [r5, #1] +100247c2: 1940 adds r0, r0, r5 +100247c4: 1c85 adds r5, r0, #2 +100247c6: 2204 movs r2, #4 +100247c8: a903 add r1, sp, #12 +100247ca: 1ca8 adds r0, r5, #2 +100247cc: f7e7 fdba bl 1000c344 +100247d0: b988 cbnz r0, 100247f6 +100247d2: 7868 ldrb r0, [r5, #1] +100247d4: 1f82 subs r2, r0, #6 +100247d6: 79a8 ldrb r0, [r5, #6] +100247d8: f000 0003 and.w r0, r0, #3 +100247dc: f8ca 0188 str.w r0, [sl, #392] ; 0x188 +100247e0: b2d2 uxtb r2, r2 +100247e2: eb0a 1040 add.w r0, sl, r0, lsl #5 +100247e6: f105 0108 add.w r1, r5, #8 +100247ea: 30e8 adds r0, #232 ; 0xe8 +100247ec: f7e7 fdac bl 1000c348 +100247f0: 2601 movs r6, #1 +100247f2: f8ca 6030 str.w r6, [sl, #48] ; 0x30 +100247f6: 79e0 ldrb r0, [r4, #7] +100247f8: 2802 cmp r0, #2 +100247fa: d012 beq.n 10024822 +100247fc: 2804 cmp r0, #4 +100247fe: d119 bne.n 10024834 +10024800: e013 b.n 1002482a +10024802: 28fe cmp r0, #254 ; 0xfe +10024804: d116 bne.n 10024834 +10024806: 22ff movs r2, #255 ; 0xff +10024808: f7ff fdd4 bl 100243b4 <.text_64+0x2> +1002480c: 6938 ldr r0, [r7, #16] +1002480e: f100 015f add.w r1, r0, #95 ; 0x5f +10024812: 22ff movs r2, #255 ; 0xff +10024814: a808 add r0, sp, #32 +10024816: f7e7 fd97 bl 1000c348 +1002481a: f89d 002b ldrb.w r0, [sp, #43] ; 0x2b +1002481e: 2802 cmp r0, #2 +10024820: d101 bne.n 10024826 +10024822: 2002 movs r0, #2 +10024824: e002 b.n 1002482c +10024826: 2804 cmp r0, #4 +10024828: d104 bne.n 10024834 +1002482a: 2004 movs r0, #4 +1002482c: f88a 00bc strb.w r0, [sl, #188] ; 0xbc +10024830: f8cb 005c str.w r0, [fp, #92] ; 0x5c +10024834: 2200 movs r2, #0 +10024836: 9968 ldr r1, [sp, #416] ; 0x1a0 +10024838: 4648 mov r0, r9 +1002483a: f7ff fc0a bl 10024052 +1002483e: b116 cbz r6, 10024846 +10024840: 4648 mov r0, r9 +10024842: f7fe ff97 bl 10023774 +10024846: 9968 ldr r1, [sp, #416] ; 0x1a0 +10024848: 4648 mov r0, r9 +1002484a: f7fe ff33 bl 100236b4 +1002484e: 9868 ldr r0, [sp, #416] ; 0x1a0 +10024850: 2101 movs r1, #1 +10024852: f7fe ffdb bl 1002380c +10024856: e070 b.n 1002493a +10024858: f20f 31a0 addw r1, pc, #928 ; 0x3a0 +1002485c: 680a ldr r2, [r1, #0] +1002485e: a802 add r0, sp, #8 +10024860: f108 03e4 add.w r3, r8, #228 ; 0xe4 +10024864: 6002 str r2, [r0, #0] +10024866: f8c8 6300 str.w r6, [r8, #768] ; 0x300 +1002486a: e9d3 0100 ldrd r0, r1, [r3] +1002486e: aa06 add r2, sp, #24 +10024870: f7fe fcac bl 100231cc +10024874: f000 f864 bl 10024940 <.text_77> +10024878: 2800 cmp r0, #0 +1002487a: d15e bne.n 1002493a +1002487c: f000 f86a bl 10024954 <.text_78> +10024880: 2800 cmp r0, #0 +10024882: d05a beq.n 1002493a +10024884: 6939 ldr r1, [r7, #16] +10024886: f89a 00bc ldrb.w r0, [sl, #188] ; 0xbc +1002488a: 7889 ldrb r1, [r1, #2] +1002488c: 2802 cmp r0, #2 +1002488e: bf0c ite eq +10024890: 2020 moveq r0, #32 +10024892: 2010 movne r0, #16 +10024894: 0049 lsls r1, r1, #1 +10024896: f001 0160 and.w r1, r1, #96 ; 0x60 +1002489a: 4451 add r1, sl +1002489c: 31e8 adds r1, #232 ; 0xe8 +1002489e: f108 02a4 add.w r2, r8, #164 ; 0xa4 +100248a2: 9101 str r1, [sp, #4] +100248a4: 9000 str r0, [sp, #0] +100248a6: f108 08d4 add.w r8, r8, #212 ; 0xd4 +100248aa: 2310 movs r3, #16 +100248ac: e9d8 0100 ldrd r0, r1, [r8] +100248b0: f7fe fe62 bl 10023578 +100248b4: 2800 cmp r0, #0 +100248b6: d040 beq.n 1002493a +100248b8: 6938 ldr r0, [r7, #16] +100248ba: 7881 ldrb r1, [r0, #2] +100248bc: f3c1 1301 ubfx r3, r1, #4, #2 +100248c0: 7801 ldrb r1, [r0, #0] +100248c2: 2902 cmp r1, #2 +100248c4: d127 bne.n 10024916 +100248c6: f890 105d ldrb.w r1, [r0, #93] ; 0x5d +100248ca: f890 005e ldrb.w r0, [r0, #94] ; 0x5e +100248ce: eb00 2201 add.w r2, r0, r1, lsl #8 +100248d2: eb0a 1043 add.w r0, sl, r3, lsl #5 +100248d6: f100 01e8 add.w r1, r0, #232 ; 0xe8 +100248da: a808 add r0, sp, #32 +100248dc: f7e7 fd34 bl 1000c348 +100248e0: f89d 0020 ldrb.w r0, [sp, #32] +100248e4: 28dd cmp r0, #221 ; 0xdd +100248e6: d118 bne.n 1002491a +100248e8: 2204 movs r2, #4 +100248ea: a902 add r1, sp, #8 +100248ec: f10d 0022 add.w r0, sp, #34 ; 0x22 +100248f0: f7e7 fd28 bl 1000c344 +100248f4: b988 cbnz r0, 1002491a +100248f6: a808 add r0, sp, #32 +100248f8: 7841 ldrb r1, [r0, #1] +100248fa: 7980 ldrb r0, [r0, #6] +100248fc: f000 0303 and.w r3, r0, #3 +10024900: 1f8a subs r2, r1, #6 +10024902: eb0a 1043 add.w r0, sl, r3, lsl #5 +10024906: f8ca 3188 str.w r3, [sl, #392] ; 0x188 +1002490a: b2d2 uxtb r2, r2 +1002490c: a90a add r1, sp, #40 ; 0x28 +1002490e: 30e8 adds r0, #232 ; 0xe8 +10024910: f7e7 fd1a bl 1000c348 +10024914: e001 b.n 1002491a +10024916: f8ca 3188 str.w r3, [sl, #392] ; 0x188 +1002491a: 9806 ldr r0, [sp, #24] +1002491c: 6068 str r0, [r5, #4] +1002491e: 9807 ldr r0, [sp, #28] +10024920: 60a8 str r0, [r5, #8] +10024922: 2001 movs r0, #1 +10024924: 60e0 str r0, [r4, #12] +10024926: f8ca 0030 str.w r0, [sl, #48] ; 0x30 +1002492a: 4648 mov r0, r9 +1002492c: f7fe ff22 bl 10023774 +10024930: 9968 ldr r1, [sp, #416] ; 0x1a0 +10024932: 2200 movs r2, #0 +10024934: 4648 mov r0, r9 +10024936: f7ff fb8c bl 10024052 +1002493a: b069 add sp, #420 ; 0x1a4 +1002493c: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +10024940 <.text_77>: +10024940: f108 00e4 add.w r0, r8, #228 ; 0xe4 +10024944: f108 0c14 add.w ip, r8, #20 +10024948: e9d0 2300 ldrd r2, r3, [r0] +1002494c: e9dc 0100 ldrd r0, r1, [ip] +10024950: f7fe bc54 b.w 100231fc + +10024954 <.text_78>: +10024954: f108 0cd4 add.w ip, r8, #212 ; 0xd4 +10024958: 2310 movs r3, #16 +1002495a: e9dc 0100 ldrd r0, r1, [ip] +1002495e: f108 0294 add.w r2, r8, #148 ; 0x94 +10024962: f7fe bd45 b.w 100233f0 + +10024966 : +10024966: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1002496a: 460c mov r4, r1 +1002496c: f641 5151 movw r1, #7505 ; 0x1d51 +10024970: 4690 mov r8, r2 +10024972: 5c0d ldrb r5, [r1, r0] +10024974: b105 cbz r5, 10024978 +10024976: 2501 movs r5, #1 +10024978: 7820 ldrb r0, [r4, #0] +1002497a: 2800 cmp r0, #0 +1002497c: d039 beq.n 100249f2 +1002497e: f8df 9170 ldr.w r9, [pc, #368] ; 10024af0 <.text_84> +10024982: 2024 movs r0, #36 ; 0x24 +10024984: fb00 9a05 mla sl, r0, r5, r9 +10024988: eb05 1085 add.w r0, r5, r5, lsl #6 +1002498c: eb00 0b09 add.w fp, r0, r9 +10024990: f10b 0148 add.w r1, fp, #72 ; 0x48 +10024994: 4620 mov r0, r4 +10024996: f7e7 fcdb bl 1000c350 +1002499a: b920 cbnz r0, 100249a6 +1002499c: 4651 mov r1, sl +1002499e: 4640 mov r0, r8 +100249a0: f7e7 fcd6 bl 1000c350 +100249a4: b328 cbz r0, 100249f2 +100249a6: 4620 mov r0, r4 +100249a8: f7e7 fcd6 bl 1000c358 +100249ac: 4606 mov r6, r0 +100249ae: 4640 mov r0, r8 +100249b0: f7e7 fcd2 bl 1000c358 +100249b4: 4607 mov r7, r0 +100249b6: 4621 mov r1, r4 +100249b8: f10b 0048 add.w r0, fp, #72 ; 0x48 +100249bc: f7e7 fcca bl 1000c354 +100249c0: 4641 mov r1, r8 +100249c2: 4650 mov r0, sl +100249c4: f7e7 fcc6 bl 1000c354 +100249c8: 2028 movs r0, #40 ; 0x28 +100249ca: fb00 9005 mla r0, r0, r5, r9 +100249ce: f100 05cc add.w r5, r0, #204 ; 0xcc +100249d2: 2228 movs r2, #40 ; 0x28 +100249d4: 2100 movs r1, #0 +100249d6: 4628 mov r0, r5 +100249d8: f7e7 fcb8 bl 1000c34c +100249dc: 2e40 cmp r6, #64 ; 0x40 +100249de: bfb8 it lt +100249e0: 2f21 cmplt r7, #33 ; 0x21 +100249e2: da06 bge.n 100249f2 +100249e4: 9500 str r5, [sp, #0] +100249e6: 463b mov r3, r7 +100249e8: 4642 mov r2, r8 +100249ea: 4631 mov r1, r6 +100249ec: 4620 mov r0, r4 +100249ee: f7fe fbdb bl 100231a8 +100249f2: e8bd 8ff1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, sl, fp, pc} + ... + +100249f8 <.text_80>: +100249f8: 10044164 .word 0x10044164 + +100249fc : +100249fc: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +10024a00: 4681 mov r9, r0 +10024a02: f509 5688 add.w r6, r9, #4352 ; 0x1100 +10024a06: 36f0 adds r6, #240 ; 0xf0 +10024a08: 4688 mov r8, r1 +10024a0a: 4615 mov r5, r2 +10024a0c: f206 4794 addw r7, r6, #1172 ; 0x494 +10024a10: f44f 72ca mov.w r2, #404 ; 0x194 +10024a14: 2100 movs r1, #0 +10024a16: 4638 mov r0, r7 +10024a18: f7e7 fc98 bl 1000c34c +10024a1c: f8d6 262c ldr.w r2, [r6, #1580] ; 0x62c +10024a20: f8d6 0628 ldr.w r0, [r6, #1576] ; 0x628 +10024a24: f000 f830 bl 10024a88 <.text_82+0x6> +10024a28: f20f 11d4 addw r1, pc, #468 ; 0x1d4 +10024a2c: 4638 mov r0, r7 +10024a2e: f7fe fe09 bl 10023644 +10024a32: f107 0420 add.w r4, r7, #32 +10024a36: 2110 movs r1, #16 +10024a38: f109 000c add.w r0, r9, #12 +10024a3c: f7fe fbb8 bl 100231b0 +10024a40: 2801 cmp r0, #1 +10024a42: d112 bne.n 10024a6a +10024a44: f107 00bc add.w r0, r7, #188 ; 0xbc +10024a48: f107 01c8 add.w r1, r7, #200 ; 0xc8 +10024a4c: 6041 str r1, [r0, #4] +10024a4e: 2120 movs r1, #32 +10024a50: 6081 str r1, [r0, #8] +10024a52: 2001 movs r0, #1 +10024a54: 6238 str r0, [r7, #32] +10024a56: f8c7 0188 str.w r0, [r7, #392] ; 0x188 +10024a5a: 2002 movs r0, #2 +10024a5c: f8c7 018c str.w r0, [r7, #396] ; 0x18c +10024a60: 2001 movs r0, #1 +10024a62: 60a0 str r0, [r4, #8] +10024a64: 6df0 ldr r0, [r6, #92] ; 0x5c +10024a66: f887 00bc strb.w r0, [r7, #188] ; 0xbc +10024a6a: 462a mov r2, r5 +10024a6c: 4641 mov r1, r8 +10024a6e: f107 003c add.w r0, r7, #60 ; 0x3c +10024a72: f7eb fecc bl 1001080e +10024a76: f107 003c add.w r0, r7, #60 ; 0x3c +10024a7a: 6160 str r0, [r4, #20] +10024a7c: 61a5 str r5, [r4, #24] +10024a7e: e8bd 83f1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, pc} + +10024a82 <.text_82>: +10024a82: f44f 72f7 mov.w r2, #494 ; 0x1ee +10024a86: 9800 ldr r0, [sp, #0] +10024a88: 2100 movs r1, #0 +10024a8a: f7e7 bc5f b.w 1000c34c + +10024a8e : +10024a8e: b570 push {r4, r5, r6, lr} +10024a90: b084 sub sp, #16 +10024a92: f000 f875 bl 10024b80 <.text_91> +10024a96: f104 0008 add.w r0, r4, #8 +10024a9a: f000 f86b bl 10024b74 <.text_90> +10024a9e: db25 blt.n 10024aec +10024aa0: f000 f874 bl 10024b8c <.text_92> +10024aa4: f7ef f9e4 bl 10013e70 +10024aa8: 9801 ldr r0, [sp, #4] +10024aaa: 06c0 lsls r0, r0, #27 +10024aac: d502 bpl.n 10024ab4 +10024aae: 2204 movs r2, #4 +10024ab0: 4910 ldr r1, [pc, #64] ; (10024af4 <.text_85>) +10024ab2: e004 b.n 10024abe +10024ab4: 9801 ldr r0, [sp, #4] +10024ab6: 0700 lsls r0, r0, #28 +10024ab8: d505 bpl.n 10024ac6 +10024aba: 2204 movs r2, #4 +10024abc: 490e ldr r1, [pc, #56] ; (10024af8 <.text_86>) +10024abe: f104 000a add.w r0, r4, #10 +10024ac2: f7eb fea4 bl 1001080e +10024ac6: 2000 movs r0, #0 +10024ac8: e006 b.n 10024ad8 +10024aca: eb00 0286 add.w r2, r0, r6, lsl #2 +10024ace: 1912 adds r2, r2, r4 +10024ad0: 1903 adds r3, r0, r4 +10024ad2: 7a92 ldrb r2, [r2, #10] +10024ad4: 739a strb r2, [r3, #14] +10024ad6: 1c40 adds r0, r0, #1 +10024ad8: f1a5 020a sub.w r2, r5, #10 +10024adc: eba2 0286 sub.w r2, r2, r6, lsl #2 +10024ae0: 4290 cmp r0, r2 +10024ae2: dbf2 blt.n 10024aca +10024ae4: 2001 movs r0, #1 +10024ae6: 7220 strb r0, [r4, #8] +10024ae8: f000 f83e bl 10024b68 <.text_89> +10024aec: e039 b.n 10024b62 <.text_88> + ... + +10024af0 <.text_84>: +10024af0: 1004817c .word 0x1004817c + +10024af4 <.text_85>: +10024af4: 00035430 .word 0x00035430 + +10024af8 <.text_86>: +10024af8: 0003542c .word 0x0003542c + +10024afc : +10024afc: b570 push {r4, r5, r6, lr} +10024afe: b084 sub sp, #16 +10024b00: f000 f83e bl 10024b80 <.text_91> +10024b04: f104 000c add.w r0, r4, #12 +10024b08: f000 f834 bl 10024b74 <.text_90> +10024b0c: db29 blt.n 10024b62 <.text_88> +10024b0e: f000 f83d bl 10024b8c <.text_92> +10024b12: f7ef f9b1 bl 10013e78 +10024b16: 9801 ldr r0, [sp, #4] +10024b18: 06c0 lsls r0, r0, #27 +10024b1a: d502 bpl.n 10024b22 +10024b1c: 2204 movs r2, #4 +10024b1e: 4906 ldr r1, [pc, #24] ; (10024b38 ) +10024b20: e004 b.n 10024b2c +10024b22: 9801 ldr r0, [sp, #4] +10024b24: 0700 lsls r0, r0, #28 +10024b26: d505 bpl.n 10024b34 +10024b28: 2204 movs r2, #4 +10024b2a: 4904 ldr r1, [pc, #16] ; (10024b3c ) +10024b2c: f104 000e add.w r0, r4, #14 +10024b30: f7eb fe6d bl 1001080e +10024b34: 2000 movs r0, #0 +10024b36: e00a b.n 10024b4e +10024b38: 0003541c .word 0x0003541c +10024b3c: 00035418 .word 0x00035418 +10024b40: eb00 0286 add.w r2, r0, r6, lsl #2 +10024b44: 1912 adds r2, r2, r4 +10024b46: 1903 adds r3, r0, r4 +10024b48: 7b92 ldrb r2, [r2, #14] +10024b4a: 749a strb r2, [r3, #18] +10024b4c: 1c40 adds r0, r0, #1 +10024b4e: f1a5 020e sub.w r2, r5, #14 +10024b52: eba2 0286 sub.w r2, r2, r6, lsl #2 +10024b56: 4290 cmp r0, r2 +10024b58: dbf2 blt.n 10024b40 +10024b5a: 2001 movs r0, #1 +10024b5c: 7320 strb r0, [r4, #12] +10024b5e: f000 f803 bl 10024b68 <.text_89> + +10024b62 <.text_88>: +10024b62: b2a8 uxth r0, r5 +10024b64: b004 add sp, #16 +10024b66: bd70 pop {r4, r5, r6, pc} + +10024b68 <.text_89>: +10024b68: 1e70 subs r0, r6, #1 +10024b6a: eba5 0580 sub.w r5, r5, r0, lsl #2 +10024b6e: 1ea8 subs r0, r5, #2 +10024b70: 7060 strb r0, [r4, #1] +10024b72: 4770 bx lr + +10024b74 <.text_90>: +10024b74: 7841 ldrb r1, [r0, #1] +10024b76: 7800 ldrb r0, [r0, #0] +10024b78: ea40 2601 orr.w r6, r0, r1, lsl #8 +10024b7c: 2e02 cmp r6, #2 +10024b7e: 4770 bx lr + +10024b80 <.text_91>: +10024b80: 4604 mov r4, r0 +10024b82: 2000 movs r0, #0 +10024b84: 9002 str r0, [sp, #8] +10024b86: 9001 str r0, [sp, #4] +10024b88: 460d mov r5, r1 +10024b8a: 4770 bx lr + +10024b8c <.text_92>: +10024b8c: 2000 movs r0, #0 +10024b8e: 9000 str r0, [sp, #0] +10024b90: ab01 add r3, sp, #4 +10024b92: aa02 add r2, sp, #8 +10024b94: 4629 mov r1, r5 +10024b96: 4620 mov r0, r4 +10024b98: 4770 bx lr + ... + +10024b9c : +10024b9c: 5057 2f41 5057 3241 6820 6e61 7364 6168 WPA/WPA2 handsha +10024bac: 656b 6420 6e6f 0065 ke done. + +10024bb4 : +10024bb4: 5452 384c 3931 4135 445b 6972 6576 5d72 RTL8195A[Driver] +10024bc4: 203a 7061 6d20 646f 2065 2d34 0a32 0000 : ap mode 4-2... + +10024bd4 : +10024bd4: 5452 384c 3931 4135 445b 6972 6576 5d72 RTL8195A[Driver] +10024be4: 203a 7061 6d20 646f 2065 2d34 0a34 0000 : ap mode 4-4... + +10024bf4 : +10024bf4: 0f00 01ac .... + +10024bf8 : +10024bf8: 5000 01f2 .P.. + +10024bfc : +10024bfc: 0f00 01ac .... + +10024c00 : +10024c00: 6461 7264 0000 0000 addr.... + +10024c08 : +10024c08: b40d push {r0, r2, r3} +10024c0a: b500 push {lr} +10024c0c: b082 sub sp, #8 +10024c0e: a804 add r0, sp, #16 +10024c10: 9000 str r0, [sp, #0] +10024c12: 460a mov r2, r1 +10024c14: ab00 add r3, sp, #0 +10024c16: a903 add r1, sp, #12 +10024c18: 4803 ldr r0, [pc, #12] ; (10024c28 ) +10024c1a: 4478 add r0, pc +10024c1c: 300a adds r0, #10 +10024c1e: f00c f9d1 bl 10030fc4 <_ScanfSmallNoMb> +10024c22: bc06 pop {r1, r2} +10024c24: f85d fb10 ldr.w pc, [sp], #16 +10024c28: fffe132f .word 0xfffe132f + +10024c2c : +10024c2c: 4603 mov r3, r0 +10024c2e: 2200 movs r2, #0 +10024c30: 6898 ldr r0, [r3, #8] +10024c32: f8d3 3904 ldr.w r3, [r3, #2308] ; 0x904 + +10024c36 <__iar_annotation$$tailcall>: +10024c36: 4718 bx r3 + +10024c38 : +10024c38: 4603 mov r3, r0 +10024c3a: 2200 movs r2, #0 +10024c3c: 6898 ldr r0, [r3, #8] +10024c3e: f8d3 3908 ldr.w r3, [r3, #2312] ; 0x908 + +10024c42 <__iar_annotation$$tailcall>: +10024c42: 4718 bx r3 + +10024c44 : +10024c44: 4603 mov r3, r0 +10024c46: 2200 movs r2, #0 +10024c48: 6898 ldr r0, [r3, #8] +10024c4a: f8d3 390c ldr.w r3, [r3, #2316] ; 0x90c + +10024c4e <__iar_annotation$$tailcall>: +10024c4e: 4718 bx r3 + +10024c50 : +10024c50: b510 push {r4, lr} +10024c52: 4604 mov r4, r0 +10024c54: 2300 movs r3, #0 +10024c56: 68a0 ldr r0, [r4, #8] +10024c58: f8d4 4910 ldr.w r4, [r4, #2320] ; 0x910 +10024c5c: 47a0 blx r4 +10024c5e: bd10 pop {r4, pc} + +10024c60 : +10024c60: b510 push {r4, lr} +10024c62: 4604 mov r4, r0 +10024c64: 2300 movs r3, #0 +10024c66: 68a0 ldr r0, [r4, #8] +10024c68: f8d4 4914 ldr.w r4, [r4, #2324] ; 0x914 +10024c6c: 47a0 blx r4 +10024c6e: bd10 pop {r4, pc} + +10024c70 : +10024c70: b510 push {r4, lr} +10024c72: 4604 mov r4, r0 +10024c74: 2300 movs r3, #0 +10024c76: 68a0 ldr r0, [r4, #8] +10024c78: f8d4 4918 ldr.w r4, [r4, #2328] ; 0x918 +10024c7c: 47a0 blx r4 +10024c7e: bd10 pop {r4, pc} + +10024c80 : +10024c80: 7801 ldrb r1, [r0, #0] +10024c82: 7842 ldrb r2, [r0, #1] +10024c84: ea82 0181 eor.w r1, r2, r1, lsl #2 +10024c88: 7882 ldrb r2, [r0, #2] +10024c8a: ea82 0181 eor.w r1, r2, r1, lsl #2 +10024c8e: 78c2 ldrb r2, [r0, #3] +10024c90: ea82 0181 eor.w r1, r2, r1, lsl #2 +10024c94: 7902 ldrb r2, [r0, #4] +10024c96: 7940 ldrb r0, [r0, #5] +10024c98: ea82 0181 eor.w r1, r2, r1, lsl #2 +10024c9c: ea80 0081 eor.w r0, r0, r1, lsl #2 +10024ca0: ea80 2010 eor.w r0, r0, r0, lsr #8 +10024ca4: f000 0007 and.w r0, r0, #7 +10024ca8: 4770 bx lr + +10024caa : +10024caa: 6840 ldr r0, [r0, #4] +10024cac: 4208 tst r0, r1 +10024cae: d001 beq.n 10024cb4 +10024cb0: 2001 movs r0, #1 +10024cb2: 4770 bx lr +10024cb4: 2000 movs r0, #0 +10024cb6: 4770 bx lr + +10024cb8 <_rtw_init_stainfo>: +10024cb8: b510 push {r4, lr} +10024cba: 4604 mov r4, r0 +10024cbc: f44f 7250 mov.w r2, #832 ; 0x340 +10024cc0: 2100 movs r1, #0 +10024cc2: f7eb fdb9 bl 10010838 +10024cc6: 4620 mov r0, r4 +10024cc8: f7eb fe45 bl 10010956 +10024ccc: 1d20 adds r0, r4, #4 +10024cce: f7eb fdbd bl 1001084c +10024cd2: f104 000c add.w r0, r4, #12 +10024cd6: f7eb fdb9 bl 1001084c +10024cda: f104 00e8 add.w r0, r4, #232 ; 0xe8 +10024cde: f7eb fe2a bl 10010936 +10024ce2: 2000 movs r0, #0 +10024ce4: f8c4 00f4 str.w r0, [r4, #244] ; 0xf4 +10024ce8: f104 0018 add.w r0, r4, #24 +10024cec: f006 fdaf bl 1002b84e <_rtw_init_sta_xmit_priv> +10024cf0: f104 00b4 add.w r0, r4, #180 ; 0xb4 +10024cf4: f008 f914 bl 1002cf20 <_rtw_init_sta_recv_priv> +10024cf8: f504 7007 add.w r0, r4, #540 ; 0x21c +10024cfc: f7eb fda6 bl 1001084c +10024d00: f504 7009 add.w r0, r4, #548 ; 0x224 +10024d04: f7eb fda2 bl 1001084c +10024d08: 2000 movs r0, #0 +10024d0a: f8c4 022c str.w r0, [r4, #556] ; 0x22c +10024d0e: f8c4 02bc str.w r0, [r4, #700] ; 0x2bc +10024d12: f8a4 02b8 strh.w r0, [r4, #696] ; 0x2b8 +10024d16: f884 02d8 strb.w r0, [r4, #728] ; 0x2d8 +10024d1a: f884 02f9 strb.w r0, [r4, #761] ; 0x2f9 +10024d1e: 2100 movs r1, #0 +10024d20: f204 20f9 addw r0, r4, #761 ; 0x2f9 +10024d24: f000 f801 bl 10024d2a <.text_5> +10024d28: bd10 pop {r4, pc} + +10024d2a <.text_5>: +10024d2a: 7041 strb r1, [r0, #1] +10024d2c: 7081 strb r1, [r0, #2] +10024d2e: 70c1 strb r1, [r0, #3] +10024d30: 7101 strb r1, [r0, #4] +10024d32: 7141 strb r1, [r0, #5] +10024d34: 4770 bx lr + +10024d36 <_rtw_init_sta_priv>: +10024d36: b5f8 push {r3, r4, r5, r6, r7, lr} +10024d38: f500 5488 add.w r4, r0, #4352 ; 0x1100 +10024d3c: 6841 ldr r1, [r0, #4] +10024d3e: 3428 adds r4, #40 ; 0x28 +10024d40: 2502 movs r5, #2 +10024d42: 2901 cmp r1, #1 +10024d44: bf18 it ne +10024d46: 2904 cmpne r1, #4 +10024d48: d009 beq.n 10024d5e <_rtw_init_sta_priv+0x28> +10024d4a: 2902 cmp r1, #2 +10024d4c: d006 beq.n 10024d5c <_rtw_init_sta_priv+0x26> +10024d4e: 2903 cmp r1, #3 +10024d50: bf02 ittt eq +10024d52: f641 5151 movweq r1, #7505 ; 0x1d51 +10024d56: 5c08 ldrbeq r0, [r1, r0] +10024d58: 2800 cmpeq r0, #0 +10024d5a: d000 beq.n 10024d5e <_rtw_init_sta_priv+0x28> +10024d5c: 2505 movs r5, #5 +10024d5e: f44f 7050 mov.w r0, #832 ; 0x340 +10024d62: 4368 muls r0, r5 +10024d64: 1d00 adds r0, r0, #4 +10024d66: 6060 str r0, [r4, #4] +10024d68: f7eb fd36 bl 100107d8 +10024d6c: 2800 cmp r0, #0 +10024d6e: 6020 str r0, [r4, #0] +10024d70: d04f beq.n 10024e12 <_rtw_init_sta_priv+0xdc> +10024d72: f000 0103 and.w r1, r0, #3 +10024d76: 1a40 subs r0, r0, r1 +10024d78: 1d00 adds r0, r0, #4 +10024d7a: 60a0 str r0, [r4, #8] +10024d7c: f104 000c add.w r0, r4, #12 +10024d80: f7eb fdd9 bl 10010936 +10024d84: f104 0018 add.w r0, r4, #24 +10024d88: f7eb fde5 bl 10010956 +10024d8c: 2000 movs r0, #0 +10024d8e: 65e0 str r0, [r4, #92] ; 0x5c +10024d90: f104 0060 add.w r0, r4, #96 ; 0x60 +10024d94: f7eb fdcf bl 10010936 +10024d98: f104 006c add.w r0, r4, #108 ; 0x6c +10024d9c: f7eb fdcb bl 10010936 +10024da0: 68a6 ldr r6, [r4, #8] +10024da2: 2700 movs r7, #0 +10024da4: e00a b.n 10024dbc <_rtw_init_sta_priv+0x86> +10024da6: 1d30 adds r0, r6, #4 +10024da8: f7eb fd50 bl 1001084c +10024dac: f104 010c add.w r1, r4, #12 +10024db0: 1d30 adds r0, r6, #4 +10024db2: f7eb fd55 bl 10010860 +10024db6: f506 7650 add.w r6, r6, #832 ; 0x340 +10024dba: 1c7f adds r7, r7, #1 +10024dbc: 42af cmp r7, r5 +10024dbe: d3f2 bcc.n 10024da6 <_rtw_init_sta_priv+0x70> +10024dc0: 2600 movs r6, #0 +10024dc2: eb04 00c6 add.w r0, r4, r6, lsl #3 +10024dc6: 301c adds r0, #28 +10024dc8: f7eb fd40 bl 1001084c +10024dcc: 1c76 adds r6, r6, #1 +10024dce: 2e08 cmp r6, #8 +10024dd0: dbf7 blt.n 10024dc2 <_rtw_init_sta_priv+0x8c> +10024dd2: 2000 movs r0, #0 +10024dd4: f8a4 00c0 strh.w r0, [r4, #192] ; 0xc0 +10024dd8: f8a4 00c2 strh.w r0, [r4, #194] ; 0xc2 +10024ddc: f104 007c add.w r0, r4, #124 ; 0x7c +10024de0: f7eb fd34 bl 1001084c +10024de4: f104 0084 add.w r0, r4, #132 ; 0x84 +10024de8: f7eb fd30 bl 1001084c +10024dec: f104 008c add.w r0, r4, #140 ; 0x8c +10024df0: f7eb fdb1 bl 10010956 +10024df4: f104 0090 add.w r0, r4, #144 ; 0x90 +10024df8: f7eb fdad bl 10010956 +10024dfc: 2003 movs r0, #3 +10024dfe: f8c4 0094 str.w r0, [r4, #148] ; 0x94 +10024e02: f8c4 0098 str.w r0, [r4, #152] ; 0x98 +10024e06: 203c movs r0, #60 ; 0x3c +10024e08: f8c4 009c str.w r0, [r4, #156] ; 0x9c +10024e0c: f8a4 50c4 strh.w r5, [r4, #196] ; 0xc4 +10024e10: 2001 movs r0, #1 +10024e12: bdf2 pop {r1, r4, r5, r6, r7, pc} + +10024e14 <_rtw_free_sta_xmit_priv_lock>: +10024e14: b510 push {r4, lr} +10024e16: 4604 mov r4, r0 +10024e18: f7eb fda4 bl 10010964 +10024e1c: f104 001c add.w r0, r4, #28 +10024e20: f7eb fda0 bl 10010964 +10024e24: f104 0034 add.w r0, r4, #52 ; 0x34 +10024e28: f7eb fd9c bl 10010964 +10024e2c: f104 004c add.w r0, r4, #76 ; 0x4c +10024e30: f7eb fd98 bl 10010964 +10024e34: f104 0064 add.w r0, r4, #100 ; 0x64 +10024e38: e02e b.n 10024e98 <.text_10> + +10024e3a : +10024e3a: b538 push {r3, r4, r5, lr} +10024e3c: 4604 mov r4, r0 +10024e3e: f7eb fd91 bl 10010964 +10024e42: f104 0018 add.w r0, r4, #24 +10024e46: f7ff ffe5 bl 10024e14 <_rtw_free_sta_xmit_priv_lock> +10024e4a: f104 05b4 add.w r5, r4, #180 ; 0xb4 +10024e4e: 4628 mov r0, r5 +10024e50: f7eb fd88 bl 10010964 +10024e54: f105 0010 add.w r0, r5, #16 +10024e58: f7eb fd84 bl 10010964 +10024e5c: f104 00f0 add.w r0, r4, #240 ; 0xf0 +10024e60: e8bd 4032 ldmia.w sp!, {r1, r4, r5, lr} +10024e64: f7eb bd7e b.w 10010964 + +10024e68 : +10024e68: b510 push {r4, lr} +10024e6a: 4604 mov r4, r0 +10024e6c: f104 0014 add.w r0, r4, #20 +10024e70: f7eb fd78 bl 10010964 +10024e74: f104 0018 add.w r0, r4, #24 +10024e78: f7eb fd74 bl 10010964 +10024e7c: f104 0074 add.w r0, r4, #116 ; 0x74 +10024e80: f7eb fd70 bl 10010964 +10024e84: f104 0068 add.w r0, r4, #104 ; 0x68 +10024e88: f7eb fd6c bl 10010964 +10024e8c: f104 008c add.w r0, r4, #140 ; 0x8c +10024e90: f7eb fd68 bl 10010964 +10024e94: f104 0090 add.w r0, r4, #144 ; 0x90 + +10024e98 <.text_10>: +10024e98: e8bd 4010 ldmia.w sp!, {r4, lr} +10024e9c: f7eb bd62 b.w 10010964 + +10024ea0 <_rtw_free_sta_priv>: +10024ea0: b510 push {r4, lr} +10024ea2: 0004 movs r4, r0 +10024ea4: d00c beq.n 10024ec0 <_rtw_free_sta_priv+0x20> +10024ea6: f7ff ffdf bl 10024e68 +10024eaa: 6820 ldr r0, [r4, #0] +10024eac: 2800 cmp r0, #0 +10024eae: bf1c itt ne +10024eb0: 6861 ldrne r1, [r4, #4] +10024eb2: 2900 cmpne r1, #0 +10024eb4: d004 beq.n 10024ec0 <_rtw_free_sta_priv+0x20> +10024eb6: f7eb fc9e bl 100107f6 +10024eba: 2000 movs r0, #0 +10024ebc: 6020 str r0, [r4, #0] +10024ebe: 6060 str r0, [r4, #4] +10024ec0: 2001 movs r0, #1 +10024ec2: bd10 pop {r4, pc} + +10024ec4 <_addba_timer_hdl>: +10024ec4: f7f8 bcf9 b.w 1001d8ba + +10024ec8 : +10024ec8: b580 push {r7, lr} +10024eca: 460b mov r3, r1 +10024ecc: f20f 3188 addw r1, pc, #904 ; 0x388 +10024ed0: 4a04 ldr r2, [pc, #16] ; (10024ee4 <.text_14>) +10024ed2: 9100 str r1, [sp, #0] +10024ed4: f641 5124 movw r1, #7460 ; 0x1d24 +10024ed8: 5809 ldr r1, [r1, r0] +10024eda: f503 70e4 add.w r0, r3, #456 ; 0x1c8 +10024ede: f7eb fda2 bl 10010a26 +10024ee2: bd01 pop {r0, pc} + +10024ee4 <.text_14>: +10024ee4: 10024ec5 .word 0x10024ec5 + +10024ee8 : +10024ee8: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +10024eec: b084 sub sp, #16 +10024eee: 4604 mov r4, r0 +10024ef0: f64f 70ff movw r0, #65535 ; 0xffff +10024ef4: f8ad 0008 strh.w r0, [sp, #8] +10024ef8: 460e mov r6, r1 +10024efa: f104 080c add.w r8, r4, #12 +10024efe: 2500 movs r5, #0 +10024f00: f000 f917 bl 10025132 <.text_17> +10024f04: 4640 mov r0, r8 +10024f06: f7eb fd1f bl 10010948 +10024f0a: 2801 cmp r0, #1 +10024f0c: d102 bne.n 10024f14 +10024f0e: f000 f918 bl 10025142 <.text_19> +10024f12: e018 b.n 10024f46 +10024f14: f8d8 0000 ldr.w r0, [r8] +10024f18: 2104 movs r1, #4 +10024f1a: 1a47 subs r7, r0, r1 +10024f1c: f7eb fca2 bl 10010864 +10024f20: f000 f90f bl 10025142 <.text_19> +10024f24: 4638 mov r0, r7 +10024f26: f7ff fec7 bl 10024cb8 <_rtw_init_stainfo> +10024f2a: 6fa0 ldr r0, [r4, #120] ; 0x78 +10024f2c: 6178 str r0, [r7, #20] +10024f2e: 2206 movs r2, #6 +10024f30: 4631 mov r1, r6 +10024f32: f507 7084 add.w r0, r7, #264 ; 0x108 +10024f36: f7eb fc6a bl 1001080e +10024f3a: 4630 mov r0, r6 +10024f3c: f7ff fea0 bl 10024c80 +10024f40: 4606 mov r6, r0 +10024f42: 2e08 cmp r6, #8 +10024f44: db01 blt.n 10024f4a +10024f46: 2700 movs r7, #0 +10024f48: e028 b.n 10024f9c +10024f4a: a901 add r1, sp, #4 +10024f4c: f104 0018 add.w r0, r4, #24 +10024f50: f7eb fce0 bl 10010914 +10024f54: eb04 00c6 add.w r0, r4, r6, lsl #3 +10024f58: f100 011c add.w r1, r0, #28 +10024f5c: f107 000c add.w r0, r7, #12 +10024f60: f7eb fc7e bl 10010860 +10024f64: 6de0 ldr r0, [r4, #92] ; 0x5c +10024f66: 1c40 adds r0, r0, #1 +10024f68: 65e0 str r0, [r4, #92] ; 0x5c +10024f6a: a901 add r1, sp, #4 +10024f6c: f104 0018 add.w r0, r4, #24 +10024f70: f7eb fcd1 bl 10010916 +10024f74: eb07 0045 add.w r0, r7, r5, lsl #1 +10024f78: 2202 movs r2, #2 +10024f7a: a902 add r1, sp, #8 +10024f7c: 30c8 adds r0, #200 ; 0xc8 +10024f7e: f7eb fc46 bl 1001080e +10024f82: 1c6d adds r5, r5, #1 +10024f84: 2d10 cmp r5, #16 +10024f86: dbf5 blt.n 10024f74 +10024f88: 6fa0 ldr r0, [r4, #120] ; 0x78 +10024f8a: 4639 mov r1, r7 +10024f8c: f7ff ff9c bl 10024ec8 +10024f90: f04f 30ff mov.w r0, #4294967295 +10024f94: f8c7 0310 str.w r0, [r7, #784] ; 0x310 +10024f98: f8c7 0314 str.w r0, [r7, #788] ; 0x314 +10024f9c: 4638 mov r0, r7 +10024f9e: e13b b.n 10025218 <.text_22> + +10024fa0 : +10024fa0: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +10024fa4: 4604 mov r4, r0 +10024fa6: f504 5688 add.w r6, r4, #4352 ; 0x1100 +10024faa: 460d mov r5, r1 +10024fac: 3628 adds r6, #40 ; 0x28 +10024fae: 2d00 cmp r5, #0 +10024fb0: b082 sub sp, #8 +10024fb2: f604 1728 addw r7, r4, #2344 ; 0x928 +10024fb6: f104 090c add.w r9, r4, #12 +10024fba: f000 80b7 beq.w 1002512c +10024fbe: f106 080c add.w r8, r6, #12 +10024fc2: f105 0a18 add.w sl, r5, #24 +10024fc6: a900 add r1, sp, #0 +10024fc8: 4638 mov r0, r7 +10024fca: f7eb fca3 bl 10010914 +10024fce: f105 01e8 add.w r1, r5, #232 ; 0xe8 +10024fd2: f000 f8b3 bl 1002513c <.text_18> +10024fd6: 2000 movs r0, #0 +10024fd8: f8c5 00f4 str.w r0, [r5, #244] ; 0xf4 +10024fdc: f10a 015c add.w r1, sl, #92 ; 0x5c +10024fe0: f000 f8ac bl 1002513c <.text_18> +10024fe4: f10a 0054 add.w r0, sl, #84 ; 0x54 +10024fe8: f7eb fc3c bl 10010864 +10024fec: f10a 0144 add.w r1, sl, #68 ; 0x44 +10024ff0: f000 f8a4 bl 1002513c <.text_18> +10024ff4: f10a 003c add.w r0, sl, #60 ; 0x3c +10024ff8: f7eb fc34 bl 10010864 +10024ffc: f10a 012c add.w r1, sl, #44 ; 0x2c +10025000: f000 f89c bl 1002513c <.text_18> +10025004: f10a 0024 add.w r0, sl, #36 ; 0x24 +10025008: f7eb fc2c bl 10010864 +1002500c: f10a 0114 add.w r1, sl, #20 +10025010: f000 f894 bl 1002513c <.text_18> +10025014: f10a 000c add.w r0, sl, #12 +10025018: f7eb fc24 bl 10010864 +1002501c: a900 add r1, sp, #0 +1002501e: 4638 mov r0, r7 +10025020: f7eb fc79 bl 10010916 +10025024: f105 000c add.w r0, r5, #12 +10025028: f7eb fc1c bl 10010864 +1002502c: 6df0 ldr r0, [r6, #92] ; 0x5c +1002502e: 1e40 subs r0, r0, #1 +10025030: 65f0 str r0, [r6, #92] ; 0x5c +10025032: f505 70e4 add.w r0, r5, #456 ; 0x1c8 +10025036: f7eb fd10 bl 10010a5a +1002503a: 2300 movs r3, #0 +1002503c: 462a mov r2, r5 +1002503e: 2100 movs r1, #0 +10025040: 4620 mov r0, r4 +10025042: f7f2 f98f bl 10017364 +10025046: f505 7707 add.w r7, r5, #540 ; 0x21c +1002504a: 4638 mov r0, r7 +1002504c: f7eb fbff bl 1001084e +10025050: b960 cbnz r0, 1002506c +10025052: f106 0a8c add.w sl, r6, #140 ; 0x8c +10025056: a900 add r1, sp, #0 +10025058: 4650 mov r0, sl +1002505a: f7eb fc5b bl 10010914 +1002505e: 4638 mov r0, r7 +10025060: f7eb fc00 bl 10010864 +10025064: a900 add r1, sp, #0 +10025066: 4650 mov r0, sl +10025068: f7eb fc55 bl 10010916 +1002506c: f505 7709 add.w r7, r5, #548 ; 0x224 +10025070: 4638 mov r0, r7 +10025072: f7eb fbec bl 1001084e +10025076: b960 cbnz r0, 10025092 +10025078: f106 0a90 add.w sl, r6, #144 ; 0x90 +1002507c: a900 add r1, sp, #0 +1002507e: 4650 mov r0, sl +10025080: f7eb fc48 bl 10010914 +10025084: 4638 mov r0, r7 +10025086: f7eb fbed bl 10010864 +1002508a: a900 add r1, sp, #0 +1002508c: 4650 mov r0, sl +1002508e: f7eb fc42 bl 10010916 +10025092: f105 07f4 add.w r7, r5, #244 ; 0xf4 +10025096: 2110 movs r1, #16 +10025098: 4648 mov r0, r9 +1002509a: f7ff fe06 bl 10024caa +1002509e: 2801 cmp r0, #1 +100250a0: d107 bne.n 100250b2 +100250a2: 68b8 ldr r0, [r7, #8] +100250a4: b128 cbz r0, 100250b2 +100250a6: eb04 0080 add.w r0, r4, r0, lsl #2 +100250aa: f641 011c movw r1, #6172 ; 0x181c +100250ae: 5808 ldr r0, [r1, r0] +100250b0: e008 b.n 100250c4 +100250b2: 2108 movs r1, #8 +100250b4: 4648 mov r0, r9 +100250b6: f7ff fdf8 bl 10024caa +100250ba: 2801 cmp r0, #1 +100250bc: d106 bne.n 100250cc +100250be: f504 50c1 add.w r0, r4, #6176 ; 0x1820 +100250c2: 6800 ldr r0, [r0, #0] +100250c4: f500 703d add.w r0, r0, #756 ; 0x2f4 +100250c8: f7eb fcc7 bl 10010a5a +100250cc: 2000 movs r0, #0 +100250ce: f8c5 022c str.w r0, [r5, #556] ; 0x22c +100250d2: 2100 movs r1, #0 +100250d4: f505 7041 add.w r0, r5, #772 ; 0x304 +100250d8: 6081 str r1, [r0, #8] +100250da: f885 1304 strb.w r1, [r5, #772] ; 0x304 +100250de: f7ff fe24 bl 10024d2a <.text_5> +100250e2: 7181 strb r1, [r0, #6] +100250e4: 2101 movs r1, #1 +100250e6: 68b8 ldr r0, [r7, #8] +100250e8: f8b6 20c0 ldrh.w r2, [r6, #192] ; 0xc0 +100250ec: 4081 lsls r1, r0 +100250ee: 43c9 mvns r1, r1 +100250f0: 400a ands r2, r1 +100250f2: f8a6 20c0 strh.w r2, [r6, #192] ; 0xc0 +100250f6: f106 02c0 add.w r2, r6, #192 ; 0xc0 +100250fa: 8853 ldrh r3, [r2, #2] +100250fc: 4019 ands r1, r3 +100250fe: 8051 strh r1, [r2, #2] +10025100: b148 cbz r0, 10025116 +10025102: eb06 0080 add.w r0, r6, r0, lsl #2 +10025106: f8d0 109c ldr.w r1, [r0, #156] ; 0x9c +1002510a: 42a9 cmp r1, r5 +1002510c: d103 bne.n 10025116 +1002510e: 2100 movs r1, #0 +10025110: f8c0 109c str.w r1, [r0, #156] ; 0x9c +10025114: 60b9 str r1, [r7, #8] +10025116: f000 f80c bl 10025132 <.text_17> +1002511a: 4641 mov r1, r8 +1002511c: 1d28 adds r0, r5, #4 +1002511e: f7eb fb9f bl 10010860 +10025122: f000 f80e bl 10025142 <.text_19> +10025126: 4628 mov r0, r5 +10025128: f7ff fe87 bl 10024e3a +1002512c: 2001 movs r0, #1 +1002512e: e8bd 87f6 ldmia.w sp!, {r1, r2, r4, r5, r6, r7, r8, r9, sl, pc} + +10025132 <.text_17>: +10025132: a900 add r1, sp, #0 +10025134: f108 0008 add.w r0, r8, #8 +10025138: f7eb bbec b.w 10010914 + +1002513c <.text_18>: +1002513c: 4638 mov r0, r7 +1002513e: f007 ba94 b.w 1002c66a + +10025142 <.text_19>: +10025142: a900 add r1, sp, #0 +10025144: f108 0008 add.w r0, r8, #8 +10025148: f7eb bbe5 b.w 10010916 + +1002514c : +1002514c: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +10025150: 4680 mov r8, r0 +10025152: f508 5588 add.w r5, r8, #4352 ; 0x1100 +10025156: 3528 adds r5, #40 ; 0x28 +10025158: f000 f86e bl 10025238 +1002515c: 4681 mov r9, r0 +1002515e: 6de8 ldr r0, [r5, #92] ; 0x5c +10025160: 2801 cmp r0, #1 +10025162: d021 beq.n 100251a8 +10025164: a900 add r1, sp, #0 +10025166: f105 0018 add.w r0, r5, #24 +1002516a: f7eb fbd3 bl 10010914 +1002516e: 2700 movs r7, #0 +10025170: eb05 00c7 add.w r0, r5, r7, lsl #3 +10025174: f100 041c add.w r4, r0, #28 +10025178: 6826 ldr r6, [r4, #0] +1002517a: e007 b.n 1002518c +1002517c: 200c movs r0, #12 +1002517e: 1a31 subs r1, r6, r0 +10025180: 6836 ldr r6, [r6, #0] +10025182: 4589 cmp r9, r1 +10025184: bf1c itt ne +10025186: 4640 movne r0, r8 +10025188: f7ff ff0a blne 10024fa0 +1002518c: 4631 mov r1, r6 +1002518e: 4620 mov r0, r4 +10025190: f7eb fbdb bl 1001094a +10025194: 2800 cmp r0, #0 +10025196: d0f1 beq.n 1002517c +10025198: 1c7f adds r7, r7, #1 +1002519a: 2f08 cmp r7, #8 +1002519c: dbe8 blt.n 10025170 +1002519e: a900 add r1, sp, #0 +100251a0: f105 0018 add.w r0, r5, #24 +100251a4: f7eb fbb7 bl 10010916 +100251a8: e8bd 83f1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, pc} + +100251ac : +100251ac: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +100251b0: 460d mov r5, r1 +100251b2: b084 sub sp, #16 +100251b4: f20f 01b4 addw r1, pc, #180 ; 0xb4 +100251b8: 4680 mov r8, r0 +100251ba: c90c ldmia r1!, {r2, r3} +100251bc: a801 add r0, sp, #4 +100251be: 2600 movs r6, #0 +100251c0: c00c stmia r0!, {r2, r3} +100251c2: b345 cbz r5, 10025216 +100251c4: 7828 ldrb r0, [r5, #0] +100251c6: 07c0 lsls r0, r0, #31 +100251c8: bf48 it mi +100251ca: ad01 addmi r5, sp, #4 +100251cc: 4628 mov r0, r5 +100251ce: f7ff fd57 bl 10024c80 +100251d2: 4607 mov r7, r0 +100251d4: a900 add r1, sp, #0 +100251d6: f108 0018 add.w r0, r8, #24 +100251da: f7eb fb9b bl 10010914 +100251de: eb08 00c7 add.w r0, r8, r7, lsl #3 +100251e2: f100 071c add.w r7, r0, #28 +100251e6: 683c ldr r4, [r7, #0] +100251e8: e001 b.n 100251ee +100251ea: 6824 ldr r4, [r4, #0] +100251ec: 2600 movs r6, #0 +100251ee: 4621 mov r1, r4 +100251f0: 4638 mov r0, r7 +100251f2: f7eb fbaa bl 1001094a +100251f6: b948 cbnz r0, 1002520c +100251f8: 200c movs r0, #12 +100251fa: 1a26 subs r6, r4, r0 +100251fc: 2206 movs r2, #6 +100251fe: 4629 mov r1, r5 +10025200: f506 7084 add.w r0, r6, #264 ; 0x108 +10025204: f7eb fb0d bl 10010822 +10025208: 2801 cmp r0, #1 +1002520a: d1ee bne.n 100251ea +1002520c: a900 add r1, sp, #0 +1002520e: f108 0018 add.w r0, r8, #24 +10025212: f7eb fb80 bl 10010916 +10025216: 4630 mov r0, r6 + +10025218 <.text_22>: +10025218: b004 add sp, #16 +1002521a: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +1002521e : +1002521e: b51c push {r2, r3, r4, lr} +10025220: f20f 0250 addw r2, pc, #80 ; 0x50 +10025224: f000 f810 bl 10025248 <.text_25> +10025228: f7ff fe5e bl 10024ee8 +1002522c: b110 cbz r0, 10025234 +1002522e: 2101 movs r1, #1 +10025230: f8c0 1100 str.w r1, [r0, #256] ; 0x100 +10025234: 2001 movs r0, #1 +10025236: bd16 pop {r1, r2, r4, pc} + +10025238 : +10025238: b51c push {r2, r3, r4, lr} +1002523a: f20f 0240 addw r2, pc, #64 ; 0x40 +1002523e: f000 f803 bl 10025248 <.text_25> +10025242: f7ff ffb3 bl 100251ac +10025246: bd16 pop {r1, r2, r4, pc} + +10025248 <.text_25>: +10025248: ca18 ldmia r2!, {r3, r4} +1002524a: a900 add r1, sp, #0 +1002524c: f500 5088 add.w r0, r0, #4352 ; 0x1100 +10025250: c118 stmia r1!, {r3, r4} +10025252: a900 add r1, sp, #0 +10025254: 3028 adds r0, #40 ; 0x28 +10025256: 4770 bx lr + +10025258 : +10025258: 6461 6264 5f61 6572 7274 5f79 6974 656d addba_retry_time +10025268: 0072 0000 r... + +1002526c : +1002526c: ffff ffff ffff 0000 ........ + +10025274 : +10025274: ffff ffff ffff 0000 ........ + +1002527c : +1002527c: ffff ffff ffff 0000 ........ + +10025284 : +10025284: f8df f000 ldr.w pc, [pc] ; 10025288 +10025288: 000065f9 .word 0x000065f9 + +1002528c : +1002528c: f8df f000 ldr.w pc, [pc] ; 10025290 +10025290: 00006699 .word 0x00006699 + +10025294 : +10025294: f641 4368 movw r3, #7272 ; 0x1c68 +10025298: 581b ldr r3, [r3, r0] + +1002529a <__iar_annotation$$tailcall>: +1002529a: 4718 bx r3 + +1002529c : +1002529c: f641 4374 movw r3, #7284 ; 0x1c74 +100252a0: 581b ldr r3, [r3, r0] + +100252a2 <__iar_annotation$$tailcall>: +100252a2: 4718 bx r3 + +100252a4 : +100252a4: 2100 movs r1, #0 +100252a6: 07c2 lsls r2, r0, #31 +100252a8: bf58 it pl +100252aa: 2101 movpl r1, #1 +100252ac: 0782 lsls r2, r0, #30 +100252ae: bf58 it pl +100252b0: 1c49 addpl r1, r1, #1 +100252b2: 0742 lsls r2, r0, #29 +100252b4: bf58 it pl +100252b6: 1c49 addpl r1, r1, #1 +100252b8: 0700 lsls r0, r0, #28 +100252ba: bf58 it pl +100252bc: 1c49 addpl r1, r1, #1 +100252be: b2c8 uxtb r0, r1 +100252c0: 4770 bx lr + +100252c2 : +100252c2: b570 push {r4, r5, r6, lr} +100252c4: 2b00 cmp r3, #0 +100252c6: 4605 mov r5, r0 +100252c8: 460e mov r6, r1 +100252ca: 4614 mov r4, r2 +100252cc: d12d bne.n 1002532a +100252ce: 8828 ldrh r0, [r5, #0] +100252d0: 281f cmp r0, #31 +100252d2: d107 bne.n 100252e4 +100252d4: f8df 023c ldr.w r0, [pc, #572] ; 10025514 <.text_30> +100252d8: 6800 ldr r0, [r0, #0] +100252da: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +100252de: 2307 movs r3, #7 +100252e0: f7ff bfd0 b.w 10025284 +100252e4: b2f2 uxtb r2, r6 +100252e6: 2131 movs r1, #49 ; 0x31 +100252e8: f000 f88c bl 10025404 <.text_18> +100252ec: 2132 movs r1, #50 ; 0x32 +100252ee: f000 f88d bl 1002540c <.text_19+0x2> +100252f2: f000 f87f bl 100253f4 <.text_17> +100252f6: f000 f888 bl 1002540a <.text_19> +100252fa: f000 027f and.w r2, r0, #127 ; 0x7f +100252fe: 2133 movs r1, #51 ; 0x33 +10025300: f000 f880 bl 10025404 <.text_18> +10025304: f000 f8e0 bl 100254c8 <.text_21> +10025308: f242 7610 movw r6, #10000 ; 0x2710 +1002530c: e002 b.n 10025314 +1002530e: f000 f8db bl 100254c8 <.text_21> +10025312: 1e76 subs r6, r6, #1 +10025314: 0e00 lsrs r0, r0, #24 +10025316: 0600 lsls r0, r0, #24 +10025318: d401 bmi.n 1002531e +1002531a: 2e00 cmp r6, #0 +1002531c: d1f7 bne.n 1002530e +1002531e: 2032 movs r0, #50 ; 0x32 +10025320: f7eb fb7a bl 10010a18 +10025324: f000 f8d0 bl 100254c8 <.text_21> +10025328: 7020 strb r0, [r4, #0] +1002532a: bd70 pop {r4, r5, r6, pc} + +1002532c : +1002532c: b51c push {r2, r3, r4, lr} +1002532e: 9c05 ldr r4, [sp, #20] +10025330: 9401 str r4, [sp, #4] +10025332: 9c04 ldr r4, [sp, #16] +10025334: 9400 str r4, [sp, #0] +10025336: f641 446c movw r4, #7276 ; 0x1c6c +1002533a: 5824 ldr r4, [r4, r0] +1002533c: 47a0 blx r4 +1002533e: bd13 pop {r0, r1, r4, pc} + +10025340 : +10025340: b510 push {r4, lr} +10025342: b082 sub sp, #8 +10025344: 9c04 ldr r4, [sp, #16] +10025346: 9400 str r4, [sp, #0] +10025348: f641 4470 movw r4, #7280 ; 0x1c70 +1002534c: 5824 ldr r4, [r4, r0] +1002534e: 47a0 blx r4 +10025350: bd13 pop {r0, r1, r4, pc} + +10025352 : +10025352: b5f8 push {r3, r4, r5, r6, r7, lr} +10025354: 4605 mov r5, r0 +10025356: 460e mov r6, r1 +10025358: 4614 mov r4, r2 +1002535a: 2700 movs r7, #0 +1002535c: b10b cbz r3, 10025362 +1002535e: 2000 movs r0, #0 +10025360: bdf2 pop {r1, r4, r5, r6, r7, pc} +10025362: f641 30a4 movw r0, #7076 ; 0x1ba4 +10025366: 5940 ldr r0, [r0, r5] +10025368: 6801 ldr r1, [r0, #0] +1002536a: 2905 cmp r1, #5 +1002536c: d10e bne.n 1002538c +1002536e: 6880 ldr r0, [r0, #8] +10025370: 2808 cmp r0, #8 +10025372: db0b blt.n 1002538c +10025374: 2134 movs r1, #52 ; 0x34 +10025376: 4628 mov r0, r5 +10025378: f7ff fc5e bl 10024c38 +1002537c: f24f 71ff movw r1, #63487 ; 0xf7ff +10025380: ea01 0200 and.w r2, r1, r0 +10025384: 2134 movs r1, #52 ; 0x34 +10025386: 4628 mov r0, r5 +10025388: f7ff fc6a bl 10024c60 +1002538c: 8828 ldrh r0, [r5, #0] +1002538e: 281f cmp r0, #31 +10025390: d107 bne.n 100253a2 +10025392: 4860 ldr r0, [pc, #384] ; (10025514 <.text_30>) +10025394: 6800 ldr r0, [r0, #0] +10025396: 2307 movs r3, #7 +10025398: 4622 mov r2, r4 +1002539a: 4631 mov r1, r6 +1002539c: f7ff ff72 bl 10025284 +100253a0: e026 b.n 100253f0 +100253a2: b2f2 uxtb r2, r6 +100253a4: 2131 movs r1, #49 ; 0x31 +100253a6: f000 f82d bl 10025404 <.text_18> +100253aa: 2132 movs r1, #50 ; 0x32 +100253ac: f000 f82e bl 1002540c <.text_19+0x2> +100253b0: f000 f820 bl 100253f4 <.text_17> +100253b4: f000 f829 bl 1002540a <.text_19> +100253b8: f000 027f and.w r2, r0, #127 ; 0x7f +100253bc: 2133 movs r1, #51 ; 0x33 +100253be: f000 f821 bl 10025404 <.text_18> +100253c2: e003 b.n 100253cc +100253c4: 2001 movs r0, #1 +100253c6: f7eb fb20 bl 10010a0a +100253ca: 1c7f adds r7, r7, #1 +100253cc: f000 f81d bl 1002540a <.text_19> +100253d0: 0600 lsls r0, r0, #24 +100253d2: d402 bmi.n 100253da +100253d4: f5b7 7f7a cmp.w r7, #1000 ; 0x3e8 +100253d8: d3f4 bcc.n 100253c4 +100253da: 2f64 cmp r7, #100 ; 0x64 +100253dc: d205 bcs.n 100253ea +100253de: 2130 movs r1, #48 ; 0x30 +100253e0: f000 f814 bl 1002540c <.text_19+0x2> +100253e4: 7020 strb r0, [r4, #0] +100253e6: 2001 movs r0, #1 +100253e8: e002 b.n 100253f0 +100253ea: 20ff movs r0, #255 ; 0xff +100253ec: 7020 strb r0, [r4, #0] +100253ee: 2000 movs r0, #0 +100253f0: b2c0 uxtb r0, r0 +100253f2: bdf2 pop {r1, r4, r5, r6, r7, pc} + +100253f4 <.text_17>: +100253f4: 0a31 lsrs r1, r6, #8 +100253f6: f001 0103 and.w r1, r1, #3 +100253fa: f000 00fc and.w r0, r0, #252 ; 0xfc +100253fe: ea40 0201 orr.w r2, r0, r1 +10025402: 2132 movs r1, #50 ; 0x32 + +10025404 <.text_18>: +10025404: 4628 mov r0, r5 +10025406: f7ff bc23 b.w 10024c50 + +1002540a <.text_19>: +1002540a: 2133 movs r1, #51 ; 0x33 +1002540c: 4628 mov r0, r5 +1002540e: f7ff bc0d b.w 10024c2c + +10025412 : +10025412: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +10025416: 4605 mov r5, r0 +10025418: 460e mov r6, r1 +1002541a: 4690 mov r8, r2 +1002541c: 2700 movs r7, #0 +1002541e: 2400 movs r4, #0 +10025420: b10b cbz r3, 10025426 +10025422: 2000 movs r0, #0 +10025424: e04e b.n 100254c4 +10025426: 8828 ldrh r0, [r5, #0] +10025428: 281f cmp r0, #31 +1002542a: d106 bne.n 1002543a +1002542c: 4839 ldr r0, [pc, #228] ; (10025514 <.text_30>) +1002542e: 6800 ldr r0, [r0, #0] +10025430: 2307 movs r3, #7 +10025432: f7ff ff2b bl 1002528c +10025436: 4604 mov r4, r0 +10025438: e043 b.n 100254c2 +1002543a: f000 f845 bl 100254c8 <.text_21> +1002543e: f368 0007 bfi r0, r8, #0, #8 +10025442: f366 2011 bfi r0, r6, #8, #10 +10025446: 4934 ldr r1, [pc, #208] ; (10025518 <.text_31>) +10025448: f641 39a4 movw r9, #7076 ; 0x1ba4 +1002544c: ea41 0200 orr.w r2, r1, r0 +10025450: f859 0005 ldr.w r0, [r9, r5] +10025454: 6801 ldr r1, [r0, #0] +10025456: 2905 cmp r1, #5 +10025458: d111 bne.n 1002547e +1002545a: 6880 ldr r0, [r0, #8] +1002545c: 2808 cmp r0, #8 +1002545e: db0e blt.n 1002547e +10025460: 2134 movs r1, #52 ; 0x34 +10025462: 4628 mov r0, r5 +10025464: f7ff fbe8 bl 10024c38 +10025468: f440 6200 orr.w r2, r0, #2048 ; 0x800 +1002546c: 2134 movs r1, #52 ; 0x34 +1002546e: 4628 mov r0, r5 +10025470: f7ff fbf6 bl 10024c60 +10025474: ea48 2006 orr.w r0, r8, r6, lsl #8 +10025478: 4928 ldr r1, [pc, #160] ; (1002551c <.text_32>) +1002547a: ea41 0200 orr.w r2, r1, r0 +1002547e: 2130 movs r1, #48 ; 0x30 +10025480: 4628 mov r0, r5 +10025482: f7ff fbf5 bl 10024c70 +10025486: e003 b.n 10025490 +10025488: 2001 movs r0, #1 +1002548a: f7eb fabe bl 10010a0a +1002548e: 1c77 adds r7, r6, #1 +10025490: b2fe uxtb r6, r7 +10025492: f7ff ffba bl 1002540a <.text_19> +10025496: 0600 lsls r0, r0, #24 +10025498: d501 bpl.n 1002549e +1002549a: 2e64 cmp r6, #100 ; 0x64 +1002549c: dbf4 blt.n 10025488 +1002549e: f859 0005 ldr.w r0, [r9, r5] +100254a2: 6801 ldr r1, [r0, #0] +100254a4: 2e64 cmp r6, #100 ; 0x64 +100254a6: bfb8 it lt +100254a8: 2401 movlt r4, #1 +100254aa: 2905 cmp r1, #5 +100254ac: d109 bne.n 100254c2 +100254ae: 6880 ldr r0, [r0, #8] +100254b0: 2808 cmp r0, #8 +100254b2: db06 blt.n 100254c2 +100254b4: 2300 movs r3, #0 +100254b6: f44f 6200 mov.w r2, #2048 ; 0x800 +100254ba: 2134 movs r1, #52 ; 0x34 +100254bc: 4628 mov r0, r5 +100254be: f7f2 f85d bl 1001757c +100254c2: b2e0 uxtb r0, r4 +100254c4: e8bd 83f2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, pc} + +100254c8 <.text_21>: +100254c8: 2130 movs r1, #48 ; 0x30 +100254ca: 4628 mov r0, r5 +100254cc: f7ff bbba b.w 10024c44 + +100254d0 : +100254d0: 07c3 lsls r3, r0, #31 +100254d2: d403 bmi.n 100254dc +100254d4: 780b ldrb r3, [r1, #0] +100254d6: 7013 strb r3, [r2, #0] +100254d8: 784b ldrb r3, [r1, #1] +100254da: 7053 strb r3, [r2, #1] +100254dc: 0783 lsls r3, r0, #30 +100254de: d403 bmi.n 100254e8 +100254e0: 788b ldrb r3, [r1, #2] +100254e2: 7093 strb r3, [r2, #2] +100254e4: 78cb ldrb r3, [r1, #3] +100254e6: 70d3 strb r3, [r2, #3] +100254e8: 0743 lsls r3, r0, #29 +100254ea: d403 bmi.n 100254f4 +100254ec: 790b ldrb r3, [r1, #4] +100254ee: 7113 strb r3, [r2, #4] +100254f0: 794b ldrb r3, [r1, #5] +100254f2: 7153 strb r3, [r2, #5] +100254f4: 0700 lsls r0, r0, #28 +100254f6: d403 bmi.n 10025500 +100254f8: 7988 ldrb r0, [r1, #6] +100254fa: 7190 strb r0, [r2, #6] +100254fc: 79c8 ldrb r0, [r1, #7] +100254fe: 71d0 strb r0, [r2, #7] +10025500: 4770 bx lr + +10025502 : +10025502: b510 push {r4, lr} +10025504: b082 sub sp, #8 +10025506: 9c04 ldr r4, [sp, #16] +10025508: 9400 str r4, [sp, #0] +1002550a: f500 54e4 add.w r4, r0, #7296 ; 0x1c80 +1002550e: 6824 ldr r4, [r4, #0] +10025510: 47a0 blx r4 +10025512: bd16 pop {r1, r2, r4, pc} + +10025514 <.text_30>: +10025514: 400000e8 .word 0x400000e8 + +10025518 <.text_31>: +10025518: 80200000 .word 0x80200000 + +1002551c <.text_32>: +1002551c: 90600000 .word 0x90600000 + +10025520 <.text_41>: +10025520: 2201 movs r2, #1 +10025522: 2100 movs r1, #0 +10025524: 4620 mov r0, r4 +10025526: e6b5 b.n 10025294 + +10025528 : +10025528: b5fe push {r1, r2, r3, r4, r5, r6, r7, lr} +1002552a: 4604 mov r4, r0 +1002552c: 2000 movs r0, #0 +1002552e: f8ad 0008 strh.w r0, [sp, #8] +10025532: 460d mov r5, r1 +10025534: 4616 mov r6, r2 +10025536: 461f mov r7, r3 +10025538: f7ff fff2 bl 10025520 <.text_41> +1002553c: 9700 str r7, [sp, #0] +1002553e: ab02 add r3, sp, #8 +10025540: 2204 movs r2, #4 +10025542: 4629 mov r1, r5 +10025544: f000 f811 bl 1002556a <.text_62> +10025548: f8bd 3008 ldrh.w r3, [sp, #8] +1002554c: 9701 str r7, [sp, #4] +1002554e: 9600 str r6, [sp, #0] +10025550: 2200 movs r2, #0 +10025552: 4629 mov r1, r5 +10025554: 4620 mov r0, r4 +10025556: f7ff fee9 bl 1002532c +1002555a: f000 f801 bl 10025560 <.text_61> +1002555e: bdf7 pop {r0, r1, r2, r4, r5, r6, r7, pc} + +10025560 <.text_61>: +10025560: 2200 movs r2, #0 +10025562: 4611 mov r1, r2 +10025564: 4620 mov r0, r4 +10025566: f7ff be95 b.w 10025294 + +1002556a <.text_62>: +1002556a: 4620 mov r0, r4 +1002556c: e6e8 b.n 10025340 + +1002556e : +1002556e: b570 push {r4, r5, r6, lr} +10025570: b084 sub sp, #16 +10025572: 4604 mov r4, r0 +10025574: f000 f8e7 bl 10025746 <.text_69> +10025578: f8bd 0008 ldrh.w r0, [sp, #8] +1002557c: f248 1195 movw r1, #33173 ; 0x8195 +10025580: 4288 cmp r0, r1 +10025582: d11e bne.n 100255c2 +10025584: 2602 movs r6, #2 +10025586: f64f 75ff movw r5, #65535 ; 0xffff +1002558a: f10d 0302 add.w r3, sp, #2 +1002558e: 2202 movs r2, #2 +10025590: f506 4120 add.w r1, r6, #40960 ; 0xa000 +10025594: f000 f8ce bl 10025734 <.text_67> +10025598: f8bd 0002 ldrh.w r0, [sp, #2] +1002559c: 42a8 cmp r0, r5 +1002559e: d021 beq.n 100255e4 +100255a0: f506 4120 add.w r1, r6, #40960 ; 0xa000 +100255a4: ab00 add r3, sp, #0 +100255a6: 2202 movs r2, #2 +100255a8: 1c89 adds r1, r1, #2 +100255aa: f000 f8c3 bl 10025734 <.text_67> +100255ae: f8bd 0000 ldrh.w r0, [sp] +100255b2: 42a8 cmp r0, r5 +100255b4: d016 beq.n 100255e4 +100255b6: f8bd 1002 ldrh.w r1, [sp, #2] +100255ba: 1840 adds r0, r0, r1 +100255bc: f5b0 5f80 cmp.w r0, #4096 ; 0x1000 +100255c0: dd01 ble.n 100255c6 +100255c2: 2000 movs r0, #0 +100255c4: e00f b.n 100255e6 +100255c6: 190b adds r3, r1, r4 +100255c8: f8bd 2000 ldrh.w r2, [sp] +100255cc: f506 4120 add.w r1, r6, #40960 ; 0xa000 +100255d0: 1d09 adds r1, r1, #4 +100255d2: f000 f8af bl 10025734 <.text_67> +100255d6: f8bd 0000 ldrh.w r0, [sp] +100255da: 1d00 adds r0, r0, #4 +100255dc: 1986 adds r6, r0, r6 +100255de: f5b6 5f80 cmp.w r6, #4096 ; 0x1000 +100255e2: d3d2 bcc.n 1002558a +100255e4: 2001 movs r0, #1 +100255e6: b004 add sp, #16 +100255e8: bd70 pop {r4, r5, r6, pc} + +100255ea : +100255ea: b500 push {lr} +100255ec: b083 sub sp, #12 +100255ee: f44f 4120 mov.w r1, #40960 ; 0xa000 +100255f2: a801 add r0, sp, #4 +100255f4: f00b ff70 bl 100314d8 +100255f8: f248 1095 movw r0, #33173 ; 0x8195 +100255fc: f8ad 0000 strh.w r0, [sp] +10025600: ab00 add r3, sp, #0 +10025602: 2202 movs r2, #2 +10025604: f44f 4120 mov.w r1, #40960 ; 0xa000 +10025608: f000 f89a bl 10025740 <.text_68+0x6> +1002560c: bd07 pop {r0, r1, r2, pc} + +1002560e : +1002560e: e92d 47f3 stmdb sp!, {r0, r1, r4, r5, r6, r7, r8, r9, sl, lr} +10025612: f241 0701 movw r7, #4097 ; 0x1001 +10025616: 1808 adds r0, r1, r0 +10025618: 42b8 cmp r0, r7 +1002561a: b084 sub sp, #16 +1002561c: 4691 mov r9, r2 +1002561e: da39 bge.n 10025694 +10025620: f000 f891 bl 10025746 <.text_69> +10025624: f8bd 0008 ldrh.w r0, [sp, #8] +10025628: f248 1195 movw r1, #33173 ; 0x8195 +1002562c: 4288 cmp r0, r1 +1002562e: bf18 it ne +10025630: f7ff ffdb blne 100255ea +10025634: f24a 0502 movw r5, #40962 ; 0xa002 +10025638: 2402 movs r4, #2 +1002563a: f10d 0302 add.w r3, sp, #2 +1002563e: 2202 movs r2, #2 +10025640: 4629 mov r1, r5 +10025642: f000 f877 bl 10025734 <.text_67> +10025646: f8bd 0002 ldrh.w r0, [sp, #2] +1002564a: f64f 78ff movw r8, #65535 ; 0xffff +1002564e: 4540 cmp r0, r8 +10025650: d00d beq.n 1002566e +10025652: ab00 add r3, sp, #0 +10025654: 2202 movs r2, #2 +10025656: 1929 adds r1, r5, r4 +10025658: f000 f86c bl 10025734 <.text_67> +1002565c: f8bd 0000 ldrh.w r0, [sp] +10025660: 4540 cmp r0, r8 +10025662: d004 beq.n 1002566e +10025664: 1d00 adds r0, r0, #4 +10025666: 1904 adds r4, r0, r4 +10025668: f5b4 5f80 cmp.w r4, #4096 ; 0x1000 +1002566c: d3f1 bcc.n 10025652 +1002566e: f8bd 0014 ldrh.w r0, [sp, #20] +10025672: 1900 adds r0, r0, r4 +10025674: 1d00 adds r0, r0, #4 +10025676: 42b8 cmp r0, r7 +10025678: f24a 0a04 movw sl, #40964 ; 0xa004 +1002567c: d347 bcc.n 1002570e +1002567e: f44f 7000 mov.w r0, #512 ; 0x200 +10025682: f7eb f8be bl 10010802 +10025686: 4607 mov r7, r0 +10025688: f44f 7200 mov.w r2, #512 ; 0x200 +1002568c: 21ff movs r1, #255 ; 0xff +1002568e: f7eb f8d3 bl 10010838 +10025692: b90f cbnz r7, 10025698 +10025694: 2000 movs r0, #0 +10025696: e04a b.n 1002572e +10025698: 4638 mov r0, r7 +1002569a: f7ff ff68 bl 1002556e +1002569e: b918 cbnz r0, 100256a8 +100256a0: f7ff ffa3 bl 100255ea +100256a4: 2402 movs r4, #2 +100256a6: e030 b.n 1002570a +100256a8: f7ff ff9f bl 100255ea +100256ac: 2402 movs r4, #2 +100256ae: 2600 movs r6, #0 +100256b0: 5df0 ldrb r0, [r6, r7] +100256b2: 28ff cmp r0, #255 ; 0xff +100256b4: d024 beq.n 10025700 +100256b6: f8ad 6002 strh.w r6, [sp, #2] +100256ba: 2001 movs r0, #1 +100256bc: e002 b.n 100256c4 +100256be: f8bd 0000 ldrh.w r0, [sp] +100256c2: 1c40 adds r0, r0, #1 +100256c4: f8ad 0000 strh.w r0, [sp] +100256c8: 1c70 adds r0, r6, #1 +100256ca: b286 uxth r6, r0 +100256cc: 5df0 ldrb r0, [r6, r7] +100256ce: 28ff cmp r0, #255 ; 0xff +100256d0: d1f5 bne.n 100256be +100256d2: 4446 add r6, r8 +100256d4: f10d 0302 add.w r3, sp, #2 +100256d8: f000 f82f bl 1002573a <.text_68> +100256dc: ab00 add r3, sp, #0 +100256de: 2202 movs r2, #2 +100256e0: 1929 adds r1, r5, r4 +100256e2: f000 f82d bl 10025740 <.text_68+0x6> +100256e6: f8bd 0002 ldrh.w r0, [sp, #2] +100256ea: f8bd 2000 ldrh.w r2, [sp] +100256ee: 19c3 adds r3, r0, r7 +100256f0: eb0a 0104 add.w r1, sl, r4 +100256f4: f000 f824 bl 10025740 <.text_68+0x6> +100256f8: f8bd 0000 ldrh.w r0, [sp] +100256fc: 1d00 adds r0, r0, #4 +100256fe: 1904 adds r4, r0, r4 +10025700: 1c70 adds r0, r6, #1 +10025702: b286 uxth r6, r0 +10025704: f5b6 7f00 cmp.w r6, #512 ; 0x200 +10025708: dbd2 blt.n 100256b0 +1002570a: f000 f823 bl 10025754 <.text_74> +1002570e: ab04 add r3, sp, #16 +10025710: f000 f813 bl 1002573a <.text_68> +10025714: ab05 add r3, sp, #20 +10025716: 2202 movs r2, #2 +10025718: 1929 adds r1, r5, r4 +1002571a: f000 f811 bl 10025740 <.text_68+0x6> +1002571e: f8bd 2014 ldrh.w r2, [sp, #20] +10025722: 464b mov r3, r9 +10025724: eb0a 0104 add.w r1, sl, r4 +10025728: f000 f80a bl 10025740 <.text_68+0x6> +1002572c: 2001 movs r0, #1 +1002572e: b006 add sp, #24 +10025730: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + +10025734 <.text_67>: +10025734: a801 add r0, sp, #4 +10025736: f00b befd b.w 10031534 + +1002573a <.text_68>: +1002573a: 2202 movs r2, #2 +1002573c: f504 4120 add.w r1, r4, #40960 ; 0xa000 +10025740: a801 add r0, sp, #4 +10025742: f00b bf47 b.w 100315d4 + +10025746 <.text_69>: +10025746: ab02 add r3, sp, #8 +10025748: 2202 movs r2, #2 +1002574a: f44f 4120 mov.w r1, #40960 ; 0xa000 +1002574e: a801 add r0, sp, #4 +10025750: f00b bef0 b.w 10031534 + +10025754 <.text_74>: +10025754: f44f 7100 mov.w r1, #512 ; 0x200 +10025758: 4638 mov r0, r7 +1002575a: f7eb b857 b.w 1001080c + +1002575e : +1002575e: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +10025762: 460c mov r4, r1 +10025764: 1910 adds r0, r2, r4 +10025766: 4699 mov r9, r3 +10025768: 1e46 subs r6, r0, #1 +1002576a: 2101 movs r1, #1 +1002576c: 4623 mov r3, r4 +1002576e: b2b6 uxth r6, r6 +10025770: 2700 movs r7, #0 +10025772: f20f 089c addw r8, pc, #156 ; 0x9c +10025776: b29b uxth r3, r3 +10025778: f838 2027 ldrh.w r2, [r8, r7, lsl #2] +1002577c: 4618 mov r0, r3 +1002577e: 4290 cmp r0, r2 +10025780: bfb8 it lt +10025782: 4610 movlt r0, r2 +10025784: eb08 0287 add.w r2, r8, r7, lsl #2 +10025788: 4635 mov r5, r6 +1002578a: 8852 ldrh r2, [r2, #2] +1002578c: 42aa cmp r2, r5 +1002578e: bfb8 it lt +10025790: 4615 movlt r5, r2 +10025792: 4285 cmp r5, r0 +10025794: db0b blt.n 100257ae +10025796: eba9 0104 sub.w r1, r9, r4 +1002579a: 1842 adds r2, r0, r1 +1002579c: 1a29 subs r1, r5, r0 +1002579e: 1c49 adds r1, r1, #1 +100257a0: b289 uxth r1, r1 +100257a2: f7ff ff34 bl 1002560e +100257a6: 4601 mov r1, r0 +100257a8: 2901 cmp r1, #1 +100257aa: d106 bne.n 100257ba +100257ac: 1c6b adds r3, r5, #1 +100257ae: 42b5 cmp r5, r6 +100257b0: d003 beq.n 100257ba +100257b2: 1c7f adds r7, r7, #1 +100257b4: b2ff uxtb r7, r7 +100257b6: 2f03 cmp r7, #3 +100257b8: dbdd blt.n 10025776 +100257ba: 4608 mov r0, r1 +100257bc: e8bd 83f2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, pc} + +100257c0 : +100257c0: b5f0 push {r4, r5, r6, r7, lr} +100257c2: b083 sub sp, #12 +100257c4: 4604 mov r4, r0 +100257c6: 2000 movs r0, #0 +100257c8: f8ad 0004 strh.w r0, [sp, #4] +100257cc: 4616 mov r6, r2 +100257ce: 460d mov r5, r1 +100257d0: f504 57c8 add.w r7, r4, #6400 ; 0x1900 +100257d4: 9600 str r6, [sp, #0] +100257d6: ab01 add r3, sp, #4 +100257d8: 2204 movs r2, #4 +100257da: f7ff fec6 bl 1002556a <.text_62> +100257de: f817 0f94 ldrb.w r0, [r7, #148]! +100257e2: 2801 cmp r0, #1 +100257e4: d107 bne.n 100257f6 +100257e6: f8bd 2004 ldrh.w r2, [sp, #4] +100257ea: 21ff movs r1, #255 ; 0xff +100257ec: f107 000d add.w r0, r7, #13 +100257f0: f7eb f822 bl 10010838 +100257f4: bdf7 pop {r0, r1, r2, r4, r5, r6, r7, pc} +100257f6: 4633 mov r3, r6 +100257f8: f107 020d add.w r2, r7, #13 +100257fc: 4629 mov r1, r5 +100257fe: 4620 mov r0, r4 +10025800: f7ff fe92 bl 10025528 +10025804: f107 000d add.w r0, r7, #13 +10025808: f7ff feb1 bl 1002556e +1002580c: bdf7 pop {r0, r1, r2, r4, r5, r6, r7, pc} + ... + +10025810 : +10025810: 0020 002f 00c0 011f 0130 013f ./.....0.?. + +1002581c <__aeabi_memclr4>: +1002581c: 2200 movs r2, #0 +1002581e: f00b bf51 b.w 100316c4 <__iar_Memset4_word> + ... + +10025824 : +10025824: 6840 ldr r0, [r0, #4] +10025826: 4208 tst r0, r1 +10025828: d001 beq.n 1002582e +1002582a: 2001 movs r0, #1 +1002582c: 4770 bx lr +1002582e: 2000 movs r0, #0 +10025830: 4770 bx lr + +10025832 : +10025832: b510 push {r4, lr} +10025834: 2200 movs r2, #0 +10025836: e000 b.n 1002583a +10025838: 1c52 adds r2, r2, #1 +1002583a: 428a cmp r2, r1 +1002583c: da0b bge.n 10025856 +1002583e: f000 f821 bl 10025884 <.text_5> +10025842: bf18 it ne +10025844: 2c04 cmpne r4, #4 +10025846: bf1e ittt ne +10025848: 2c0b cmpne r4, #11 +1002584a: f003 037f andne.w r3, r3, #127 ; 0x7f +1002584e: 2b16 cmpne r3, #22 +10025850: d1f2 bne.n 10025838 +10025852: 2001 movs r0, #1 +10025854: bd10 pop {r4, pc} +10025856: 2000 movs r0, #0 +10025858: bd10 pop {r4, pc} + +1002585a : +1002585a: b510 push {r4, lr} +1002585c: 2200 movs r2, #0 +1002585e: e000 b.n 10025862 +10025860: 1c52 adds r2, r2, #1 +10025862: 428a cmp r2, r1 +10025864: da0c bge.n 10025880 +10025866: f000 f80d bl 10025884 <.text_5> +1002586a: bf18 it ne +1002586c: 2c04 cmpne r4, #4 +1002586e: d0f7 beq.n 10025860 +10025870: 2c0b cmp r4, #11 +10025872: bf1c itt ne +10025874: f003 037f andne.w r3, r3, #127 ; 0x7f +10025878: 2b16 cmpne r3, #22 +1002587a: d0f1 beq.n 10025860 +1002587c: 2000 movs r0, #0 +1002587e: bd10 pop {r4, pc} +10025880: 2001 movs r0, #1 +10025882: bd10 pop {r4, pc} + +10025884 <.text_5>: +10025884: 5c13 ldrb r3, [r2, r0] +10025886: f003 047f and.w r4, r3, #127 ; 0x7f +1002588a: 2c02 cmp r4, #2 +1002588c: 4770 bx lr + +1002588e : +1002588e: 2801 cmp r0, #1 +10025890: d00e beq.n 100258b0 +10025892: 2802 cmp r0, #2 +10025894: bf18 it ne +10025896: 2804 cmpne r0, #4 +10025898: d00c beq.n 100258b4 +1002589a: 2808 cmp r0, #8 +1002589c: d00c beq.n 100258b8 +1002589e: 280a cmp r0, #10 +100258a0: d00c beq.n 100258bc +100258a2: 280b cmp r0, #11 +100258a4: d00c beq.n 100258c0 +100258a6: 2810 cmp r0, #16 +100258a8: d006 beq.n 100258b8 +100258aa: 2814 cmp r0, #20 +100258ac: d006 beq.n 100258bc +100258ae: e009 b.n 100258c4 +100258b0: 2006 movs r0, #6 +100258b2: 4770 bx lr +100258b4: 2005 movs r0, #5 +100258b6: 4770 bx lr +100258b8: 2003 movs r0, #3 +100258ba: 4770 bx lr +100258bc: 2001 movs r0, #1 +100258be: 4770 bx lr +100258c0: 2000 movs r0, #0 +100258c2: 4770 bx lr +100258c4: 2004 movs r0, #4 +100258c6: 4770 bx lr + +100258c8 : +100258c8: f641 32a4 movw r2, #7076 ; 0x1ba4 +100258cc: 2901 cmp r1, #1 +100258ce: 5812 ldr r2, [r2, r0] +100258d0: d010 beq.n 100258f4 +100258d2: 2902 cmp r1, #2 +100258d4: d010 beq.n 100258f8 +100258d6: 2903 cmp r1, #3 +100258d8: d010 beq.n 100258fc +100258da: 2904 cmp r1, #4 +100258dc: d00c beq.n 100258f8 +100258de: 2908 cmp r1, #8 +100258e0: bf18 it ne +100258e2: 290a cmpne r1, #10 +100258e4: d00c beq.n 10025900 +100258e6: 290b cmp r1, #11 +100258e8: d012 beq.n 10025910 +100258ea: 2910 cmp r1, #16 +100258ec: bf18 it ne +100258ee: 2914 cmpne r1, #20 +100258f0: d006 beq.n 10025900 +100258f2: e01c b.n 1002592e +100258f4: 2008 movs r0, #8 +100258f6: 4770 bx lr +100258f8: 2007 movs r0, #7 +100258fa: 4770 bx lr +100258fc: 2006 movs r0, #6 +100258fe: 4770 bx lr +10025900: f892 004b ldrb.w r0, [r2, #75] ; 0x4b +10025904: 2802 cmp r0, #2 +10025906: d101 bne.n 1002590c +10025908: 2004 movs r0, #4 +1002590a: 4770 bx lr +1002590c: 2005 movs r0, #5 +1002590e: 4770 bx lr +10025910: f892 104b ldrb.w r1, [r2, #75] ; 0x4b +10025914: f890 04f7 ldrb.w r0, [r0, #1271] ; 0x4f7 +10025918: b928 cbnz r0, 10025926 +1002591a: 2902 cmp r1, #2 +1002591c: d101 bne.n 10025922 +1002591e: 2002 movs r0, #2 +10025920: 4770 bx lr +10025922: 2003 movs r0, #3 +10025924: 4770 bx lr +10025926: 2902 cmp r1, #2 +10025928: d001 beq.n 1002592e +1002592a: 2001 movs r0, #1 +1002592c: 4770 bx lr +1002592e: 2000 movs r0, #0 +10025930: 4770 bx lr + +10025932 : +10025932: b570 push {r4, r5, r6, lr} +10025934: 460c mov r4, r1 +10025936: f500 609d add.w r0, r0, #1256 ; 0x4e8 +1002593a: f500 7188 add.w r1, r0, #272 ; 0x110 +1002593e: 7b80 ldrb r0, [r0, #14] +10025940: f891 10b4 ldrb.w r1, [r1, #180] ; 0xb4 +10025944: 2600 movs r6, #0 +10025946: 280f cmp r0, #15 +10025948: 4615 mov r5, r2 +1002594a: db04 blt.n 10025956 +1002594c: b101 cbz r1, 10025950 +1002594e: 2610 movs r6, #16 +10025950: f046 0004 orr.w r0, r6, #4 +10025954: bd70 pop {r4, r5, r6, pc} +10025956: b101 cbz r1, 1002595a +10025958: 2608 movs r6, #8 +1002595a: 4629 mov r1, r5 +1002595c: 4620 mov r0, r4 +1002595e: f7ff ff7c bl 1002585a +10025962: 2801 cmp r0, #1 +10025964: d102 bne.n 1002596c +10025966: f046 0001 orr.w r0, r6, #1 +1002596a: bd70 pop {r4, r5, r6, pc} +1002596c: 4629 mov r1, r5 +1002596e: 4620 mov r0, r4 +10025970: f7ff ff5f bl 10025832 +10025974: 2801 cmp r0, #1 +10025976: d102 bne.n 1002597e +10025978: f046 0003 orr.w r0, r6, #3 +1002597c: bd70 pop {r4, r5, r6, pc} +1002597e: f046 0002 orr.w r0, r6, #2 +10025982: bd70 pop {r4, r5, r6, pc} + +10025984 : +10025984: 2100 movs r1, #0 +10025986: f000 007f and.w r0, r0, #127 ; 0x7f +1002598a: 280b cmp r0, #11 +1002598c: d81e bhi.n 100259cc +1002598e: e8df f000 tbb [pc, r0] +10025992: 0806 .short 0x0806 +10025994: 100e0c0a .word 0x100e0c0a +10025998: 18161412 .word 0x18161412 +1002599c: 1c1a .short 0x1c1a +1002599e: 2102 movs r1, #2 +100259a0: e014 b.n 100259cc +100259a2: 2104 movs r1, #4 +100259a4: e012 b.n 100259cc +100259a6: 210b movs r1, #11 +100259a8: e010 b.n 100259cc +100259aa: 2116 movs r1, #22 +100259ac: e00e b.n 100259cc +100259ae: 210c movs r1, #12 +100259b0: e00c b.n 100259cc +100259b2: 2112 movs r1, #18 +100259b4: e00a b.n 100259cc +100259b6: 2118 movs r1, #24 +100259b8: e008 b.n 100259cc +100259ba: 2124 movs r1, #36 ; 0x24 +100259bc: e006 b.n 100259cc +100259be: 2130 movs r1, #48 ; 0x30 +100259c0: e004 b.n 100259cc +100259c2: 2148 movs r1, #72 ; 0x48 +100259c4: e002 b.n 100259cc +100259c6: 2160 movs r1, #96 ; 0x60 +100259c8: e000 b.n 100259cc +100259ca: 216c movs r1, #108 ; 0x6c +100259cc: 4608 mov r0, r1 +100259ce: 4770 bx lr + +100259d0 : +100259d0: b570 push {r4, r5, r6, lr} +100259d2: 460c mov r4, r1 +100259d4: f500 659d add.w r5, r0, #1256 ; 0x4e8 +100259d8: 2600 movs r6, #0 +100259da: 1970 adds r0, r6, r5 +100259dc: f890 00bc ldrb.w r0, [r0, #188] ; 0xbc +100259e0: 28ff cmp r0, #255 ; 0xff +100259e2: bf18 it ne +100259e4: 28fe cmpne r0, #254 ; 0xfe +100259e6: d005 beq.n 100259f4 +100259e8: f7ff ffcc bl 10025984 +100259ec: 4284 cmp r4, r0 +100259ee: d101 bne.n 100259f4 +100259f0: 2001 movs r0, #1 +100259f2: bd70 pop {r4, r5, r6, pc} +100259f4: 1c76 adds r6, r6, #1 +100259f6: 2e0d cmp r6, #13 +100259f8: dbef blt.n 100259da +100259fa: 2000 movs r0, #0 +100259fc: bd70 pop {r4, r5, r6, pc} + +100259fe : +100259fe: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +10025a02: 4604 mov r4, r0 +10025a04: 4688 mov r8, r1 +10025a06: 2600 movs r6, #0 +10025a08: f504 679d add.w r7, r4, #1256 ; 0x4e8 +10025a0c: 2500 movs r5, #0 +10025a0e: 19e8 adds r0, r5, r7 +10025a10: f890 00c9 ldrb.w r0, [r0, #201] ; 0xc9 +10025a14: 28fe cmp r0, #254 ; 0xfe +10025a16: d00f beq.n 10025a38 +10025a18: 28ff cmp r0, #255 ; 0xff +10025a1a: d010 beq.n 10025a3e +10025a1c: f7ff ffb2 bl 10025984 +10025a20: 4681 mov r9, r0 +10025a22: 4649 mov r1, r9 +10025a24: 4620 mov r0, r4 +10025a26: f7ff ffd3 bl 100259d0 +10025a2a: 2801 cmp r0, #1 +10025a2c: bf08 it eq +10025a2e: f049 0980 orreq.w r9, r9, #128 ; 0x80 +10025a32: f806 9008 strb.w r9, [r6, r8] +10025a36: 1c76 adds r6, r6, #1 +10025a38: 1c6d adds r5, r5, #1 +10025a3a: 2d0d cmp r5, #13 +10025a3c: dbe7 blt.n 10025a0e +10025a3e: 4630 mov r0, r6 +10025a40: e8bd 83f2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, pc} + +10025a44 : +10025a44: b57f push {r0, r1, r2, r3, r4, r5, r6, lr} +10025a46: 4604 mov r4, r0 +10025a48: 460d mov r5, r1 +10025a4a: 4616 mov r6, r2 +10025a4c: 220d movs r2, #13 +10025a4e: 2100 movs r1, #0 +10025a50: a800 add r0, sp, #0 +10025a52: f7ea fef1 bl 10010838 +10025a56: a900 add r1, sp, #0 +10025a58: 4620 mov r0, r4 +10025a5a: f7ff ffd0 bl 100259fe +10025a5e: 6030 str r0, [r6, #0] +10025a60: 4602 mov r2, r0 +10025a62: a900 add r1, sp, #0 +10025a64: 4628 mov r0, r5 +10025a66: f7ea fed2 bl 1001080e +10025a6a: bd7f pop {r0, r1, r2, r3, r4, r5, r6, pc} + +10025a6c : +10025a6c: 2000 movs r0, #0 +10025a6e: 5c42 ldrb r2, [r0, r1] +10025a70: f002 037f and.w r3, r2, #127 ; 0x7f +10025a74: 2b02 cmp r3, #2 +10025a76: bf18 it ne +10025a78: 2b04 cmpne r3, #4 +10025a7a: d008 beq.n 10025a8e +10025a7c: 2b0b cmp r3, #11 +10025a7e: bf18 it ne +10025a80: 2b0c cmpne r3, #12 +10025a82: d004 beq.n 10025a8e +10025a84: 2b16 cmp r3, #22 +10025a86: bf1c itt ne +10025a88: 2b18 cmpne r3, #24 +10025a8a: 2b30 cmpne r3, #48 ; 0x30 +10025a8c: d102 bne.n 10025a94 +10025a8e: f042 0280 orr.w r2, r2, #128 ; 0x80 +10025a92: 5442 strb r2, [r0, r1] +10025a94: 1c40 adds r0, r0, #1 +10025a96: 2810 cmp r0, #16 +10025a98: dbe9 blt.n 10025a6e +10025a9a: 4770 bx lr + +10025a9c : +10025a9c: b510 push {r4, lr} +10025a9e: 2200 movs r2, #0 +10025aa0: e00d b.n 10025abe +10025aa2: f7ff feef bl 10025884 <.text_5> +10025aa6: bf18 it ne +10025aa8: 2c04 cmpne r4, #4 +10025aaa: d003 beq.n 10025ab4 +10025aac: 2c0b cmp r4, #11 +10025aae: bf18 it ne +10025ab0: 2c16 cmpne r4, #22 +10025ab2: d102 bne.n 10025aba +10025ab4: f043 0380 orr.w r3, r3, #128 ; 0x80 +10025ab8: 5413 strb r3, [r2, r0] +10025aba: 1c52 adds r2, r2, #1 +10025abc: b2d2 uxtb r2, r2 +10025abe: 428a cmp r2, r1 +10025ac0: d3ef bcc.n 10025aa2 +10025ac2: bd10 pop {r4, pc} + +10025ac4 : +10025ac4: b580 push {r7, lr} +10025ac6: 2101 movs r1, #1 +10025ac8: e001 b.n 10025ace <.text_17> + +10025aca : +10025aca: b580 push {r7, lr} +10025acc: 2100 movs r1, #0 + +10025ace <.text_17>: +10025ace: f88d 1000 strb.w r1, [sp] +10025ad2: aa00 add r2, sp, #0 +10025ad4: 2118 movs r1, #24 + +10025ad6 <.text_18>: +10025ad6: f7f1 fc1b bl 10017310 +10025ada: bd01 pop {r0, pc} + +10025adc : +10025adc: b502 push {r1, lr} +10025ade: 2a01 cmp r2, #1 +10025ae0: aa00 add r2, sp, #0 +10025ae2: bf0c ite eq +10025ae4: 2119 moveq r1, #25 +10025ae6: 211a movne r1, #26 +10025ae8: e7f5 b.n 10025ad6 <.text_18> + +10025aea : +10025aea: b580 push {r7, lr} +10025aec: f641 5252 movw r2, #7506 ; 0x1d52 +10025af0: 5c12 ldrb r2, [r2, r0] +10025af2: f88d 1000 strb.w r1, [sp] +10025af6: 2a01 cmp r2, #1 +10025af8: aa00 add r2, sp, #0 +10025afa: bf0c ite eq +10025afc: 2101 moveq r1, #1 +10025afe: 2100 movne r1, #0 +10025b00: e7e9 b.n 10025ad6 <.text_18> + +10025b02 : +10025b02: b580 push {r7, lr} +10025b04: 2904 cmp r1, #4 +10025b06: f500 62bf add.w r2, r0, #1528 ; 0x5f8 +10025b0a: d102 bne.n 10025b12 +10025b0c: 2103 movs r1, #3 +10025b0e: 6011 str r1, [r2, #0] +10025b10: e00a b.n 10025b28 +10025b12: 2901 cmp r1, #1 +10025b14: d105 bne.n 10025b22 +10025b16: 6813 ldr r3, [r2, #0] +10025b18: 2102 movs r1, #2 +10025b1a: f361 0301 bfi r3, r1, #0, #2 +10025b1e: 6013 str r3, [r2, #0] +10025b20: e002 b.n 10025b28 +10025b22: 1e49 subs r1, r1, #1 +10025b24: 4189 sbcs r1, r1 +10025b26: 0fc9 lsrs r1, r1, #31 +10025b28: f88d 1000 strb.w r1, [sp] +10025b2c: aa00 add r2, sp, #0 +10025b2e: 2102 movs r1, #2 +10025b30: f7f1 fbee bl 10017310 +10025b34: 2000 movs r0, #0 +10025b36: bd02 pop {r1, pc} + +10025b38 : +10025b38: b570 push {r4, r5, r6, lr} +10025b3a: 4604 mov r4, r0 +10025b3c: f641 5658 movw r6, #7512 ; 0x1d58 +10025b40: 460d mov r5, r1 +10025b42: 5930 ldr r0, [r6, r4] +10025b44: 2100 movs r1, #0 +10025b46: f7ea fee7 bl 10010918 +10025b4a: 1930 adds r0, r6, r4 +10025b4c: 6880 ldr r0, [r0, #8] +10025b4e: b100 cbz r0, 10025b52 +10025b50: 7005 strb r5, [r0, #0] +10025b52: 4629 mov r1, r5 +10025b54: 4620 mov r0, r4 +10025b56: f7f1 fce8 bl 1001752a +10025b5a: 5930 ldr r0, [r6, r4] +10025b5c: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +10025b60: e017 b.n 10025b92 <.text_24> + +10025b62 : +10025b62: b5f8 push {r3, r4, r5, r6, r7, lr} +10025b64: 4604 mov r4, r0 +10025b66: f641 575c movw r7, #7516 ; 0x1d5c +10025b6a: 460d mov r5, r1 +10025b6c: 5938 ldr r0, [r7, r4] +10025b6e: 4616 mov r6, r2 +10025b70: 2100 movs r1, #0 +10025b72: f7ea fed1 bl 10010918 +10025b76: 1938 adds r0, r7, r4 +10025b78: 6841 ldr r1, [r0, #4] +10025b7a: b111 cbz r1, 10025b82 +10025b7c: 704d strb r5, [r1, #1] +10025b7e: 6840 ldr r0, [r0, #4] +10025b80: 7086 strb r6, [r0, #2] +10025b82: 4632 mov r2, r6 +10025b84: 4629 mov r1, r5 +10025b86: 4620 mov r0, r4 +10025b88: f7f1 fcc5 bl 10017516 +10025b8c: 5938 ldr r0, [r7, r4] +10025b8e: e8bd 40f4 ldmia.w sp!, {r2, r4, r5, r6, r7, lr} + +10025b92 <.text_24>: +10025b92: 2100 movs r1, #0 +10025b94: f7ea bec8 b.w 10010928 + +10025b98 : +10025b98: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +10025b9c: 460d mov r5, r1 +10025b9e: 4690 mov r8, r2 +10025ba0: ea5f 0903 movs.w r9, r3 +10025ba4: bf14 ite ne +10025ba6: f1b8 0f00 cmpne.w r8, #0 +10025baa: 462e moveq r6, r5 +10025bac: 4604 mov r4, r0 +10025bae: d004 beq.n 10025bba +10025bb0: f1b8 0f01 cmp.w r8, #1 +10025bb4: bf0c ite eq +10025bb6: 1cae addeq r6, r5, #2 +10025bb8: 1eae subne r6, r5, #2 +10025bba: f641 5758 movw r7, #7512 ; 0x1d58 +10025bbe: 2100 movs r1, #0 +10025bc0: 5938 ldr r0, [r7, r4] +10025bc2: f7ea fea9 bl 10010918 +10025bc6: 1938 adds r0, r7, r4 +10025bc8: 6880 ldr r0, [r0, #8] +10025bca: b100 cbz r0, 10025bce +10025bcc: 7005 strb r5, [r0, #0] +10025bce: b2f1 uxtb r1, r6 +10025bd0: 4620 mov r0, r4 +10025bd2: f7f1 fcaa bl 1001752a +10025bd6: 5938 ldr r0, [r7, r4] +10025bd8: 2100 movs r1, #0 +10025bda: f7ea fea5 bl 10010928 +10025bde: 4642 mov r2, r8 +10025be0: 4649 mov r1, r9 +10025be2: 4620 mov r0, r4 +10025be4: e8bd 43f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +10025be8: e7bb b.n 10025b62 + +10025bea : +10025bea: 1d00 adds r0, r0, #4 +10025bec: 4770 bx lr + +10025bee : +10025bee: b580 push {r7, lr} +10025bf0: 307c adds r0, #124 ; 0x7c +10025bf2: f7f8 fe7b bl 1001e8ec +10025bf6: 4601 mov r1, r0 +10025bf8: 2202 movs r2, #2 +10025bfa: a800 add r0, sp, #0 +10025bfc: f7ea fe07 bl 1001080e +10025c00: f8bd 0000 ldrh.w r0, [sp] +10025c04: bd02 pop {r1, pc} + +10025c06 : +10025c06: b158 cbz r0, 10025c20 +10025c08: f8d0 05f8 ldr.w r0, [r0, #1528] ; 0x5f8 +10025c0c: f244 0103 movw r1, #16387 ; 0x4003 +10025c10: 4008 ands r0, r1 +10025c12: f244 0102 movw r1, #16386 ; 0x4002 +10025c16: 4288 cmp r0, r1 +10025c18: d101 bne.n 10025c1e +10025c1a: 2001 movs r0, #1 +10025c1c: 4770 bx lr +10025c1e: 2000 movs r0, #0 +10025c20: 4770 bx lr + +10025c22 : +10025c22: f8d0 05f8 ldr.w r0, [r0, #1528] ; 0x5f8 +10025c26: f244 0103 movw r1, #16387 ; 0x4003 +10025c2a: 4008 ands r0, r1 +10025c2c: f244 0101 movw r1, #16385 ; 0x4001 +10025c30: 4288 cmp r0, r1 +10025c32: d101 bne.n 10025c38 +10025c34: 2001 movs r0, #1 +10025c36: 4770 bx lr +10025c38: 2000 movs r0, #0 +10025c3a: 4770 bx lr + +10025c3c : +10025c3c: f500 60bf add.w r0, r0, #1528 ; 0x5f8 +10025c40: 2102 movs r1, #2 +10025c42: eb00 1241 add.w r2, r0, r1, lsl #5 +10025c46: f8d2 2110 ldr.w r2, [r2, #272] ; 0x110 +10025c4a: 2a01 cmp r2, #1 +10025c4c: d101 bne.n 10025c52 +10025c4e: 2000 movs r0, #0 +10025c50: 4770 bx lr +10025c52: 1c49 adds r1, r1, #1 +10025c54: 2908 cmp r1, #8 +10025c56: d3f4 bcc.n 10025c42 +10025c58: 2001 movs r0, #1 +10025c5a: 4770 bx lr + +10025c5c : +10025c5c: 0081 lsls r1, r0, #2 +10025c5e: f241 7070 movw r0, #6000 ; 0x1770 +10025c62: 4281 cmp r1, r0 +10025c64: d307 bcc.n 10025c76 +10025c66: f644 6021 movw r0, #20001 ; 0x4e21 +10025c6a: 4281 cmp r1, r0 +10025c6c: d302 bcc.n 10025c74 +10025c6e: f644 6020 movw r0, #20000 ; 0x4e20 +10025c72: 4770 bx lr +10025c74: 4608 mov r0, r1 +10025c76: 4770 bx lr + +10025c78 : +10025c78: 2200 movs r2, #0 +10025c7a: 211c movs r1, #28 +10025c7c: f7f1 bb48 b.w 10017310 + +10025c80 : +10025c80: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} +10025c84: b083 sub sp, #12 +10025c86: 4680 mov r8, r0 +10025c88: 9d0a ldr r5, [sp, #40] ; 0x28 +10025c8a: 4691 mov r9, r2 +10025c8c: 461e mov r6, r3 +10025c8e: 00cf lsls r7, r1, #3 +10025c90: 2405 movs r4, #5 +10025c92: 1ea0 subs r0, r4, #2 +10025c94: 0080 lsls r0, r0, #2 +10025c96: 1941 adds r1, r0, r5 +10025c98: 5d40 ldrb r0, [r0, r5] +10025c9a: 784a ldrb r2, [r1, #1] +10025c9c: ea40 2002 orr.w r0, r0, r2, lsl #8 +10025ca0: 788a ldrb r2, [r1, #2] +10025ca2: 78c9 ldrb r1, [r1, #3] +10025ca4: ea40 4002 orr.w r0, r0, r2, lsl #16 +10025ca8: e00f b.n 10025cca +10025caa: d00a beq.n 10025cc2 +10025cac: 2c01 cmp r4, #1 +10025cae: d1f0 bne.n 10025c92 +10025cb0: 78b0 ldrb r0, [r6, #2] +10025cb2: 78f1 ldrb r1, [r6, #3] +10025cb4: ea40 2001 orr.w r0, r0, r1, lsl #8 +10025cb8: 7931 ldrb r1, [r6, #4] +10025cba: ea40 4001 orr.w r0, r0, r1, lsl #16 +10025cbe: 7971 ldrb r1, [r6, #5] +10025cc0: e003 b.n 10025cca +10025cc2: 7830 ldrb r0, [r6, #0] +10025cc4: 7871 ldrb r1, [r6, #1] +10025cc6: ea49 4000 orr.w r0, r9, r0, lsl #16 +10025cca: ea40 6001 orr.w r0, r0, r1, lsl #24 +10025cce: 9000 str r0, [sp, #0] +10025cd0: aa00 add r2, sp, #0 +10025cd2: 19e0 adds r0, r4, r7 +10025cd4: 9001 str r0, [sp, #4] +10025cd6: 211d movs r1, #29 +10025cd8: 4640 mov r0, r8 +10025cda: f7f1 fb19 bl 10017310 +10025cde: 1e64 subs r4, r4, #1 +10025ce0: d5e3 bpl.n 10025caa +10025ce2: e8bd 83f7 ldmia.w sp!, {r0, r1, r2, r4, r5, r6, r7, r8, r9, pc} + +10025ce6 : +10025ce6: b530 push {r4, r5, lr} +10025ce8: b087 sub sp, #28 +10025cea: 4604 mov r4, r0 +10025cec: 460d mov r5, r1 +10025cee: a801 add r0, sp, #4 +10025cf0: 2100 movs r1, #0 +10025cf2: 2200 movs r2, #0 +10025cf4: c006 stmia r0!, {r1, r2} +10025cf6: 2110 movs r1, #16 +10025cf8: f7ff fd90 bl 1002581c <__aeabi_memclr4> +10025cfc: a803 add r0, sp, #12 +10025cfe: 9000 str r0, [sp, #0] +10025d00: ab01 add r3, sp, #4 +10025d02: 2200 movs r2, #0 +10025d04: 4629 mov r1, r5 +10025d06: 4620 mov r0, r4 +10025d08: f7ff ffba bl 10025c80 +10025d0c: b007 add sp, #28 +10025d0e: bd30 pop {r4, r5, pc} + +10025d10 : +10025d10: b5f8 push {r3, r4, r5, r6, r7, lr} +10025d12: 4604 mov r4, r0 +10025d14: f504 65bf add.w r5, r4, #1528 ; 0x5f8 +10025d18: f104 060c add.w r6, r4, #12 +10025d1c: 2101 movs r1, #1 +10025d1e: f7f9 fd96 bl 1001f84e +10025d22: b928 cbnz r0, 10025d30 +10025d24: 2200 movs r2, #0 +10025d26: 211c movs r1, #28 +10025d28: 4620 mov r0, r4 +10025d2a: f7f1 faf1 bl 10017310 +10025d2e: e022 b.n 10025d76 +10025d30: 2108 movs r1, #8 +10025d32: 4630 mov r0, r6 +10025d34: f7ff fd76 bl 10025824 +10025d38: b1c8 cbz r0, 10025d6e +10025d3a: f504 5088 add.w r0, r4, #4352 ; 0x1100 +10025d3e: 2700 movs r7, #0 +10025d40: f106 0190 add.w r1, r6, #144 ; 0x90 +10025d44: 3028 adds r0, #40 ; 0x28 +10025d46: f7ff fa31 bl 100251ac +10025d4a: b1a0 cbz r0, 10025d76 +10025d4c: f890 10f8 ldrb.w r1, [r0, #248] ; 0xf8 +10025d50: 06c9 lsls r1, r1, #27 +10025d52: d405 bmi.n 10025d60 +10025d54: f8d0 1100 ldr.w r1, [r0, #256] ; 0x100 +10025d58: 2902 cmp r1, #2 +10025d5a: bf0c ite eq +10025d5c: 2705 moveq r7, #5 +10025d5e: 2704 movne r7, #4 +10025d60: 4601 mov r1, r0 +10025d62: 2300 movs r3, #0 +10025d64: 463a mov r2, r7 +10025d66: 4620 mov r0, r4 +10025d68: f7f0 fddc bl 10016924 +10025d6c: e003 b.n 10025d76 +10025d6e: 2110 movs r1, #16 +10025d70: 4630 mov r0, r6 +10025d72: f7ff fd57 bl 10025824 +10025d76: f505 7086 add.w r0, r5, #268 ; 0x10c +10025d7a: e8bd 40f8 ldmia.w sp!, {r3, r4, r5, r6, r7, lr} +10025d7e: f44f 7280 mov.w r2, #256 ; 0x100 +10025d82: 2100 movs r1, #0 +10025d84: f7ea bd58 b.w 10010838 + +10025d88 : +10025d88: b580 push {r7, lr} +10025d8a: f500 63bf add.w r3, r0, #1528 ; 0x5f8 +10025d8e: f8d0 044c ldr.w r0, [r0, #1100] ; 0x44c +10025d92: b910 cbnz r0, 10025d9a +10025d94: f883 00b1 strb.w r0, [r3, #177] ; 0xb1 +10025d98: bd02 pop {r1, pc} +10025d9a: 2001 movs r0, #1 +10025d9c: f883 00b1 strb.w r0, [r3, #177] ; 0xb1 +10025da0: 2212 movs r2, #18 +10025da2: 3108 adds r1, #8 +10025da4: f103 00c8 add.w r0, r3, #200 ; 0xc8 +10025da8: f7ea fd31 bl 1001080e +10025dac: 2001 movs r0, #1 +10025dae: bd02 pop {r1, pc} + +10025db0 : +10025db0: e92d 41fc stmdb sp!, {r2, r3, r4, r5, r6, r7, r8, lr} +10025db4: 4604 mov r4, r0 +10025db6: f504 609d add.w r0, r4, #1256 ; 0x4e8 +10025dba: f500 7888 add.w r8, r0, #272 ; 0x110 +10025dbe: f898 10b1 ldrb.w r1, [r8, #177] ; 0xb1 +10025dc2: b909 cbnz r1, 10025dc8 +10025dc4: 2000 movs r0, #0 +10025dc6: e05e b.n 10025e86 +10025dc8: 2100 movs r1, #0 +10025dca: f88d 1000 strb.w r1, [sp] +10025dce: 7c40 ldrb r0, [r0, #17] +10025dd0: 2801 cmp r0, #1 +10025dd2: bf0c ite eq +10025dd4: 260a moveq r6, #10 +10025dd6: 2610 movne r6, #16 +10025dd8: 2700 movs r7, #0 +10025dda: eb08 0187 add.w r1, r8, r7, lsl #2 +10025dde: f891 20ca ldrb.w r2, [r1, #202] ; 0xca +10025de2: f898 c0af ldrb.w ip, [r8, #175] ; 0xaf +10025de6: 31ca adds r1, #202 ; 0xca +10025de8: f3c2 1041 ubfx r0, r2, #5, #2 +10025dec: f3c2 1500 ubfx r5, r2, #4, #1 +10025df0: 784b ldrb r3, [r1, #1] +10025df2: 8849 ldrh r1, [r1, #2] +10025df4: f002 020f and.w r2, r2, #15 +10025df8: fb0c 6202 mla r2, ip, r2, r6 +10025dfc: b2d2 uxtb r2, r2 +10025dfe: f003 0c0f and.w ip, r3, #15 +10025e02: ea42 220c orr.w r2, r2, ip, lsl #8 +10025e06: 091b lsrs r3, r3, #4 +10025e08: ea42 3203 orr.w r2, r2, r3, lsl #12 +10025e0c: ea42 4101 orr.w r1, r2, r1, lsl #16 +10025e10: 9101 str r1, [sp, #4] +10025e12: b128 cbz r0, 10025e20 +10025e14: 2802 cmp r0, #2 +10025e16: d011 beq.n 10025e3c +10025e18: d30b bcc.n 10025e32 +10025e1a: 2803 cmp r0, #3 +10025e1c: d017 beq.n 10025e4e +10025e1e: e023 b.n 10025e68 +10025e20: aa01 add r2, sp, #4 +10025e22: 2121 movs r1, #33 ; 0x21 +10025e24: f000 fb60 bl 100264e8 <.text_61> +10025e28: 2d00 cmp r5, #0 +10025e2a: bf0c ite eq +10025e2c: 2000 moveq r0, #0 +10025e2e: 2002 movne r0, #2 +10025e30: e015 b.n 10025e5e +10025e32: aa01 add r2, sp, #4 +10025e34: 2122 movs r1, #34 ; 0x22 +10025e36: f000 fb57 bl 100264e8 <.text_61> +10025e3a: e015 b.n 10025e68 +10025e3c: aa01 add r2, sp, #4 +10025e3e: 2120 movs r1, #32 +10025e40: f000 fb52 bl 100264e8 <.text_61> +10025e44: 2d00 cmp r5, #0 +10025e46: bf0c ite eq +10025e48: 2000 moveq r0, #0 +10025e4a: 2004 movne r0, #4 +10025e4c: e007 b.n 10025e5e +10025e4e: aa01 add r2, sp, #4 +10025e50: 211f movs r1, #31 +10025e52: f000 fb49 bl 100264e8 <.text_61> +10025e56: 2d00 cmp r5, #0 +10025e58: bf14 ite ne +10025e5a: 2008 movne r0, #8 +10025e5c: 2000 moveq r0, #0 +10025e5e: f89d 1000 ldrb.w r1, [sp] +10025e62: 4308 orrs r0, r1 +10025e64: f88d 0000 strb.w r0, [sp] +10025e68: 1c7f adds r7, r7, #1 +10025e6a: 2f04 cmp r7, #4 +10025e6c: d3b5 bcc.n 10025dda +10025e6e: f641 00c4 movw r0, #6340 ; 0x18c4 +10025e72: 5d00 ldrb r0, [r0, r4] +10025e74: 2801 cmp r0, #1 +10025e76: d104 bne.n 10025e82 +10025e78: aa00 add r2, sp, #0 +10025e7a: 2123 movs r1, #35 ; 0x23 +10025e7c: f000 fb34 bl 100264e8 <.text_61> +10025e80: e003 b.n 10025e8a +10025e82: f89d 0000 ldrb.w r0, [sp] +10025e86: f884 049d strb.w r0, [r4, #1181] ; 0x49d +10025e8a: e8bd 81f3 ldmia.w sp!, {r0, r1, r4, r5, r6, r7, r8, pc} + +10025e8e : +10025e8e: b570 push {r4, r5, r6, lr} +10025e90: f100 020c add.w r2, r0, #12 +10025e94: 2900 cmp r1, #0 +10025e96: f500 649d add.w r4, r0, #1256 ; 0x4e8 +10025e9a: bf1c itt ne +10025e9c: f8d2 6448 ldrne.w r6, [r2, #1096] ; 0x448 +10025ea0: 2e00 cmpne r6, #0 +10025ea2: f504 7388 add.w r3, r4, #272 ; 0x110 +10025ea6: f500 55c4 add.w r5, r0, #6272 ; 0x1880 +10025eaa: d03b beq.n 10025f24 +10025eac: 784e ldrb r6, [r1, #1] +10025eae: 2e17 cmp r6, #23 +10025eb0: d238 bcs.n 10025f24 +10025eb2: 1c89 adds r1, r1, #2 +10025eb4: 7849 ldrb r1, [r1, #1] +10025eb6: 074e lsls r6, r1, #29 +10025eb8: d50c bpl.n 10025ed4 +10025eba: f895 5051 ldrb.w r5, [r5, #81] ; 0x51 +10025ebe: b14d cbz r5, 10025ed4 +10025ec0: 2501 movs r5, #1 +10025ec2: f001 0103 and.w r1, r1, #3 +10025ec6: 2901 cmp r1, #1 +10025ec8: d006 beq.n 10025ed8 +10025eca: 2903 cmp r1, #3 +10025ecc: bf14 ite ne +10025ece: 2100 movne r1, #0 +10025ed0: 2102 moveq r1, #2 +10025ed2: e001 b.n 10025ed8 +10025ed4: 2500 movs r5, #0 +10025ed6: 2100 movs r1, #0 +10025ed8: 7be6 ldrb r6, [r4, #15] +10025eda: 42b5 cmp r5, r6 +10025edc: bf04 itt eq +10025ede: 7c26 ldrbeq r6, [r4, #16] +10025ee0: 42b1 cmpeq r1, r6 +10025ee2: d01a beq.n 10025f1a +10025ee4: 2601 movs r6, #1 +10025ee6: f883 60bf strb.w r6, [r3, #191] ; 0xbf +10025eea: 73e5 strb r5, [r4, #15] +10025eec: 7421 strb r1, [r4, #16] +10025eee: f893 10bf ldrb.w r1, [r3, #191] ; 0xbf +10025ef2: 2901 cmp r1, #1 +10025ef4: d116 bne.n 10025f24 +10025ef6: f500 5088 add.w r0, r0, #4352 ; 0x1100 +10025efa: f102 0190 add.w r1, r2, #144 ; 0x90 +10025efe: 3028 adds r0, #40 ; 0x28 +10025f00: f7ff f954 bl 100251ac +10025f04: b170 cbz r0, 10025f24 +10025f06: f500 70fa add.w r0, r0, #500 ; 0x1f4 +10025f0a: 6801 ldr r1, [r0, #0] +10025f0c: 2900 cmp r1, #0 +10025f0e: bf1d ittte ne +10025f10: 7be1 ldrbne r1, [r4, #15] +10025f12: 7201 strbne r1, [r0, #8] +10025f14: 7c21 ldrbne r1, [r4, #16] +10025f16: 7201 strbeq r1, [r0, #8] +10025f18: e003 b.n 10025f22 +10025f1a: 2000 movs r0, #0 +10025f1c: f883 00bf strb.w r0, [r3, #191] ; 0xbf +10025f20: bd70 pop {r4, r5, r6, pc} +10025f22: 7241 strb r1, [r0, #9] +10025f24: bd70 pop {r4, r5, r6, pc} + +10025f26 : +10025f26: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +10025f2a: b082 sub sp, #8 +10025f2c: 2900 cmp r1, #0 +10025f2e: bf1c itt ne +10025f30: f8d0 2454 ldrne.w r2, [r0, #1108] ; 0x454 +10025f34: 2a00 cmpne r2, #0 +10025f36: f500 64bf add.w r4, r0, #1528 ; 0x5f8 +10025f3a: d050 beq.n 10025fde +10025f3c: 2201 movs r2, #1 +10025f3e: f884 20b5 strb.w r2, [r4, #181] ; 0xb5 +10025f42: 2300 movs r3, #0 +10025f44: f104 02da add.w r2, r4, #218 ; 0xda +10025f48: e002 b.n 10025f50 +10025f4a: 4335 orrs r5, r6 +10025f4c: 7095 strb r5, [r2, #2] +10025f4e: 1c5b adds r3, r3, #1 +10025f50: 784d ldrb r5, [r1, #1] +10025f52: 42ab cmp r3, r5 +10025f54: d21f bcs.n 10025f96 +10025f56: 2b02 cmp r3, #2 +10025f58: d008 beq.n 10025f6c +10025f5a: 191d adds r5, r3, r4 +10025f5c: 185f adds r7, r3, r1 +10025f5e: f895 60da ldrb.w r6, [r5, #218] ; 0xda +10025f62: 78bf ldrb r7, [r7, #2] +10025f64: 403e ands r6, r7 +10025f66: f885 60da strb.w r6, [r5, #218] ; 0xda +10025f6a: e7f0 b.n 10025f4e +10025f6c: 7897 ldrb r7, [r2, #2] +10025f6e: 790d ldrb r5, [r1, #4] +10025f70: f005 0603 and.w r6, r5, #3 +10025f74: f007 0803 and.w r8, r7, #3 +10025f78: 4546 cmp r6, r8 +10025f7a: bfa8 it ge +10025f7c: f007 0603 andge.w r6, r7, #3 +10025f80: f005 0e1c and.w lr, r5, #28 +10025f84: f007 0c1c and.w ip, r7, #28 +10025f88: 45e6 cmp lr, ip +10025f8a: bfb4 ite lt +10025f8c: f007 051c andlt.w r5, r7, #28 +10025f90: f005 051c andge.w r5, r5, #28 +10025f94: e7d9 b.n 10025f4a +10025f96: f8b4 10da ldrh.w r1, [r4, #218] ; 0xda +10025f9a: f8a4 10da strh.w r1, [r4, #218] ; 0xda +10025f9e: aa00 add r2, sp, #0 +10025fa0: f8b4 10ed ldrh.w r1, [r4, #237] ; 0xed +10025fa4: f8a4 10ed strh.w r1, [r4, #237] ; 0xed +10025fa8: 2116 movs r1, #22 +10025faa: f7f1 f9bb bl 10017324 +10025fae: 2000 movs r0, #0 +10025fb0: f8df 1768 ldr.w r1, [pc, #1896] ; 1002671c <.text_67> +10025fb4: f8df 2768 ldr.w r2, [pc, #1896] ; 10026720 <.text_68> +10025fb8: f89d 5000 ldrb.w r5, [sp] +10025fbc: 1903 adds r3, r0, r4 +10025fbe: 2d03 cmp r5, #3 +10025fc0: bf18 it ne +10025fc2: 2d00 cmpne r5, #0 +10025fc4: bf07 ittee eq +10025fc6: f893 50dd ldrbeq.w r5, [r3, #221] ; 0xdd +10025fca: 5c46 ldrbeq r6, [r0, r1] +10025fcc: f893 50dd ldrbne.w r5, [r3, #221] ; 0xdd +10025fd0: 5c86 ldrbne r6, [r0, r2] +10025fd2: 4035 ands r5, r6 +10025fd4: 1c40 adds r0, r0, #1 +10025fd6: 2810 cmp r0, #16 +10025fd8: f883 50dd strb.w r5, [r3, #221] ; 0xdd +10025fdc: d3ec bcc.n 10025fb8 +10025fde: e8bd 81f3 ldmia.w sp!, {r0, r1, r4, r5, r6, r7, r8, pc} + +10025fe2 : +10025fe2: f500 63bf add.w r3, r0, #1528 ; 0x5f8 +10025fe6: 2900 cmp r1, #0 +10025fe8: bf1c itt ne +10025fea: f8d0 0454 ldrne.w r0, [r0, #1108] ; 0x454 +10025fee: 2800 cmpne r0, #0 +10025ff0: d008 beq.n 10026004 +10025ff2: 7848 ldrb r0, [r1, #1] +10025ff4: 2817 cmp r0, #23 +10025ff6: d205 bcs.n 10026004 +10025ff8: 2001 movs r0, #1 +10025ffa: f883 00b6 strb.w r0, [r3, #182] ; 0xb6 +10025ffe: f103 00f4 add.w r0, r3, #244 ; 0xf4 +10026002: e035 b.n 10026070 <.text_43> +10026004: 4770 bx lr + +10026006 : +10026006: b510 push {r4, lr} +10026008: 4604 mov r4, r0 +1002600a: f504 60bf add.w r0, r4, #1528 ; 0x5f8 +1002600e: f100 01b4 add.w r1, r0, #180 ; 0xb4 +10026012: b082 sub sp, #8 +10026014: 788a ldrb r2, [r1, #2] +10026016: 2a00 cmp r2, #0 +10026018: bf1c itt ne +1002601a: 7849 ldrbne r1, [r1, #1] +1002601c: 2900 cmpne r1, #0 +1002601e: d018 beq.n 10026052 +10026020: 2101 movs r1, #1 +10026022: f880 10b4 strb.w r1, [r0, #180] ; 0xb4 +10026026: aa00 add r2, sp, #0 +10026028: f890 10dc ldrb.w r1, [r0, #220] ; 0xdc +1002602c: f001 0103 and.w r1, r1, #3 +10026030: f88d 1001 strb.w r1, [sp, #1] +10026034: 2124 movs r1, #36 ; 0x24 +10026036: f890 00dc ldrb.w r0, [r0, #220] ; 0xdc +1002603a: f3c0 0082 ubfx r0, r0, #2, #3 +1002603e: f88d 0000 strb.w r0, [sp] +10026042: f000 fa51 bl 100264e8 <.text_61> +10026046: f10d 0201 add.w r2, sp, #1 +1002604a: 2125 movs r1, #37 ; 0x25 +1002604c: f000 fa4c bl 100264e8 <.text_61> +10026050: bd13 pop {r0, r1, r4, pc} +10026052: 2100 movs r1, #0 +10026054: f880 10b4 strb.w r1, [r0, #180] ; 0xb4 +10026058: bd13 pop {r0, r1, r4, pc} + +1002605a : +1002605a: 784a ldrb r2, [r1, #1] +1002605c: 2a02 cmp r2, #2 +1002605e: f500 60bf add.w r0, r0, #1528 ; 0x5f8 +10026062: da04 bge.n 1002606e +10026064: 2201 movs r2, #1 +10026066: f880 20b2 strb.w r2, [r0, #178] ; 0xb2 +1002606a: 30b3 adds r0, #179 ; 0xb3 +1002606c: e000 b.n 10026070 <.text_43> +1002606e: 4770 bx lr + +10026070 <.text_43>: +10026070: 784a ldrb r2, [r1, #1] +10026072: 1c89 adds r1, r1, #2 +10026074: f7ea bbcb b.w 1001080e + +10026078 : +10026078: f500 52c4 add.w r2, r0, #6272 ; 0x1880 +1002607c: f500 60bf add.w r0, r0, #1528 ; 0x5f8 +10026080: f892 3032 ldrb.w r3, [r2, #50] ; 0x32 +10026084: b183 cbz r3, 100260a8 +10026086: 2b01 cmp r3, #1 +10026088: d006 beq.n 10026098 +1002608a: f890 30b2 ldrb.w r3, [r0, #178] ; 0xb2 +1002608e: b15b cbz r3, 100260a8 +10026090: f890 00b3 ldrb.w r0, [r0, #179] ; 0xb3 +10026094: 0780 lsls r0, r0, #30 +10026096: d507 bpl.n 100260a8 +10026098: f892 0033 ldrb.w r0, [r2, #51] ; 0x33 +1002609c: 2801 cmp r0, #1 +1002609e: bf1a itte ne +100260a0: 2000 movne r0, #0 +100260a2: 2201 movne r2, #1 +100260a4: 2200 moveq r2, #0 +100260a6: e001 b.n 100260ac +100260a8: 2000 movs r0, #0 +100260aa: 2200 movs r2, #0 +100260ac: f881 0175 strb.w r0, [r1, #373] ; 0x175 +100260b0: f881 2174 strb.w r2, [r1, #372] ; 0x174 +100260b4: 4770 bx lr + +100260b6 : +100260b6: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +100260ba: b093 sub sp, #76 ; 0x4c +100260bc: 4604 mov r4, r0 +100260be: 2000 movs r0, #0 +100260c0: 9004 str r0, [sp, #16] +100260c2: 9008 str r0, [sp, #32] +100260c4: 9007 str r0, [sp, #28] +100260c6: 9006 str r0, [sp, #24] +100260c8: 9003 str r0, [sp, #12] +100260ca: 4688 mov r8, r1 +100260cc: 4606 mov r6, r0 +100260ce: 4691 mov r9, r2 +100260d0: f104 0a7c add.w sl, r4, #124 ; 0x7c +100260d4: 2500 movs r5, #0 +100260d6: f108 0710 add.w r7, r8, #16 +100260da: a80a add r0, sp, #40 ; 0x28 +100260dc: 2120 movs r1, #32 +100260de: f7ff fb9d bl 1002581c <__aeabi_memclr4> +100260e2: 4620 mov r0, r4 +100260e4: f7ff fd8f bl 10025c06 +100260e8: 2800 cmp r0, #0 +100260ea: d012 beq.n 10026112 +100260ec: f641 0079 movw r0, #6265 ; 0x1879 +100260f0: 5d00 ldrb r0, [r0, r4] +100260f2: 2800 cmp r0, #0 +100260f4: f040 80cc bne.w 10026290 +100260f8: f1a9 0018 sub.w r0, r9, #24 +100260fc: f5b0 7f40 cmp.w r0, #768 ; 0x300 +10026100: 9002 str r0, [sp, #8] +10026102: d869 bhi.n 100261d8 +10026104: 2206 movs r2, #6 +10026106: 4639 mov r1, r7 +10026108: f10a 0020 add.w r0, sl, #32 +1002610c: f7ea fb89 bl 10010822 +10026110: 2800 cmp r0, #0 +10026112: f000 80bd beq.w 10026290 +10026116: 9802 ldr r0, [sp, #8] +10026118: 9009 str r0, [sp, #36] ; 0x24 +1002611a: f108 0818 add.w r8, r8, #24 +1002611e: f1a0 090c sub.w r9, r0, #12 +10026122: 464b mov r3, r9 +10026124: aa02 add r2, sp, #8 +10026126: 212d movs r1, #45 ; 0x2d +10026128: f000 f8c2 bl 100262b0 <.text_47+0x6> +1002612c: 2800 cmp r0, #0 +1002612e: bf1d ittte ne +10026130: 9902 ldrne r1, [sp, #8] +10026132: 2900 cmpne r1, #0 +10026134: f8b0 b002 ldrhne.w fp, [r0, #2] +10026138: 46ab moveq fp, r5 +1002613a: f000 f8b6 bl 100262aa <.text_47> +1002613e: 2800 cmp r0, #0 +10026140: f50a 7766 add.w r7, sl, #920 ; 0x398 +10026144: bf1c itt ne +10026146: 9902 ldrne r1, [sp, #8] +10026148: 2900 cmpne r1, #0 +1002614a: 8a39 ldrh r1, [r7, #16] +1002614c: bf1a itte ne +1002614e: 1c86 addne r6, r0, #2 +10026150: 7870 ldrbne r0, [r6, #1] +10026152: 2000 moveq r0, #0 +10026154: 458b cmp fp, r1 +10026156: bf01 itttt eq +10026158: f000 0103 andeq.w r1, r0, #3 +1002615c: 7cba ldrbeq r2, [r7, #18] +1002615e: f002 0203 andeq.w r2, r2, #3 +10026162: 4291 cmpeq r1, r2 +10026164: bf1c itt ne +10026166: f8a7 b010 strhne.w fp, [r7, #16] +1002616a: 74b8 strbne r0, [r7, #18] +1002616c: 464b mov r3, r9 +1002616e: aa02 add r2, sp, #8 +10026170: 2103 movs r1, #3 +10026172: f000 f89d bl 100262b0 <.text_47+0x6> +10026176: b108 cbz r0, 1002617c +10026178: 7880 ldrb r0, [r0, #2] +1002617a: e006 b.n 1002618a +1002617c: f000 f895 bl 100262aa <.text_47> +10026180: 2e00 cmp r6, #0 +10026182: bf14 ite ne +10026184: 7830 ldrbne r0, [r6, #0] +10026186: f894 04f6 ldrbeq.w r0, [r4, #1270] ; 0x4f6 +1002618a: f894 14f6 ldrb.w r1, [r4, #1270] ; 0x4f6 +1002618e: 4288 cmp r0, r1 +10026190: d122 bne.n 100261d8 +10026192: 464b mov r3, r9 +10026194: aa02 add r2, sp, #8 +10026196: 2100 movs r1, #0 +10026198: f000 f88a bl 100262b0 <.text_47+0x6> +1002619c: 0004 movs r4, r0 +1002619e: bf1c itt ne +100261a0: 7862 ldrbne r2, [r4, #1] +100261a2: 2a00 cmpne r2, #0 +100261a4: d005 beq.n 100261b2 +100261a6: 1ca1 adds r1, r4, #2 +100261a8: a80a add r0, sp, #40 ; 0x28 +100261aa: f7ea fb30 bl 1001080e +100261ae: 7864 ldrb r4, [r4, #1] +100261b0: e002 b.n 100261b8 +100261b2: 2400 movs r4, #0 +100261b4: f88d 4028 strb.w r4, [sp, #40] ; 0x28 +100261b8: 2220 movs r2, #32 +100261ba: f10a 012c add.w r1, sl, #44 ; 0x2c +100261be: a80a add r0, sp, #40 ; 0x28 +100261c0: f7ea fb2f bl 10010822 +100261c4: b118 cbz r0, 100261ce +100261c6: f8da 0028 ldr.w r0, [sl, #40] ; 0x28 +100261ca: 4284 cmp r4, r0 +100261cc: d005 beq.n 100261da +100261ce: f89d 0028 ldrb.w r0, [sp, #40] ; 0x28 +100261d2: 2800 cmp r0, #0 +100261d4: bf18 it ne +100261d6: 2c00 cmpne r4, #0 +100261d8: d15c bne.n 10026294 +100261da: 4640 mov r0, r8 +100261dc: f7f8 fb7a bl 1001e8d4 +100261e0: 4601 mov r1, r0 +100261e2: 2202 movs r2, #2 +100261e4: a805 add r0, sp, #20 +100261e6: f7ea fb12 bl 1001080e +100261ea: f8bd 0014 ldrh.w r0, [sp, #20] +100261ee: 0600 lsls r0, r0, #24 +100261f0: 0f00 lsrs r0, r0, #28 +100261f2: f000 0401 and.w r4, r0, #1 +100261f6: f8da 0050 ldr.w r0, [sl, #80] ; 0x50 +100261fa: 42a0 cmp r0, r4 +100261fc: d14a bne.n 10026294 +100261fe: f10d 0012 add.w r0, sp, #18 +10026202: 9001 str r0, [sp, #4] +10026204: 9500 str r5, [sp, #0] +10026206: ab04 add r3, sp, #16 +10026208: 9909 ldr r1, [sp, #36] ; 0x24 +1002620a: 2200 movs r2, #0 +1002620c: 4640 mov r0, r8 +1002620e: f7f0 f841 bl 10016294 +10026212: f8bd 0010 ldrh.w r0, [sp, #16] +10026216: b108 cbz r0, 1002621c +10026218: 2503 movs r5, #3 +1002621a: e006 b.n 1002622a +1002621c: f8bd 0012 ldrh.w r0, [sp, #18] +10026220: b108 cbz r0, 10026226 +10026222: 2502 movs r5, #2 +10026224: e001 b.n 1002622a +10026226: b104 cbz r4, 1002622a +10026228: 2501 movs r5, #1 +1002622a: f89a 0398 ldrb.w r0, [sl, #920] ; 0x398 +1002622e: 42a8 cmp r0, r5 +10026230: d130 bne.n 10026294 +10026232: 2d02 cmp r5, #2 +10026234: bf18 it ne +10026236: 2d03 cmpne r5, #3 +10026238: d12a bne.n 10026290 +1002623a: 464a mov r2, r9 +1002623c: a903 add r1, sp, #12 +1002623e: f108 000c add.w r0, r8, #12 +10026242: f7f3 fbad bl 100199a0 +10026246: 2800 cmp r0, #0 +10026248: bf1c itt ne +1002624a: 9903 ldrne r1, [sp, #12] +1002624c: 2900 cmpne r1, #0 +1002624e: d004 beq.n 1002625a +10026250: f000 f824 bl 1002629c <.text_46> +10026254: f7ed fe0c bl 10013e70 +10026258: e00e b.n 10026278 +1002625a: 464a mov r2, r9 +1002625c: a903 add r1, sp, #12 +1002625e: f108 000c add.w r0, r8, #12 +10026262: f7f3 fb99 bl 10019998 +10026266: 2800 cmp r0, #0 +10026268: bf1c itt ne +1002626a: 9903 ldrne r1, [sp, #12] +1002626c: 2900 cmpne r1, #0 +1002626e: d003 beq.n 10026278 +10026270: f000 f814 bl 1002629c <.text_46> +10026274: f7ed fe00 bl 10013e78 +10026278: 9807 ldr r0, [sp, #28] +1002627a: 68b9 ldr r1, [r7, #8] +1002627c: 4208 tst r0, r1 +1002627e: bf1e ittt ne +10026280: 9808 ldrne r0, [sp, #32] +10026282: 6879 ldrne r1, [r7, #4] +10026284: 4208 tstne r0, r1 +10026286: d005 beq.n 10026294 +10026288: 9806 ldr r0, [sp, #24] +1002628a: 68f9 ldr r1, [r7, #12] +1002628c: 4288 cmp r0, r1 +1002628e: d101 bne.n 10026294 +10026290: 2001 movs r0, #1 +10026292: e000 b.n 10026296 +10026294: 2000 movs r0, #0 +10026296: b013 add sp, #76 ; 0x4c +10026298: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1002629c <.text_46>: +1002629c: a906 add r1, sp, #24 +1002629e: 9100 str r1, [sp, #0] +100262a0: ab07 add r3, sp, #28 +100262a2: 9903 ldr r1, [sp, #12] +100262a4: aa08 add r2, sp, #32 +100262a6: 1c89 adds r1, r1, #2 +100262a8: 4770 bx lr + +100262aa <.text_47>: +100262aa: 464b mov r3, r9 +100262ac: aa02 add r2, sp, #8 +100262ae: 213d movs r1, #61 ; 0x3d +100262b0: f108 000c add.w r0, r8, #12 +100262b4: f7ed bde4 b.w 10013e80 + +100262b8 : +100262b8: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +100262bc: 4604 mov r4, r0 +100262be: 460d mov r5, r1 +100262c0: 4698 mov r8, r3 +100262c2: f1a2 0924 sub.w r9, r2, #36 ; 0x24 +100262c6: 2600 movs r6, #0 +100262c8: e00a b.n 100262e0 +100262ca: 4639 mov r1, r7 +100262cc: 4620 mov r0, r4 +100262ce: f7ff fec4 bl 1002605a +100262d2: 4641 mov r1, r8 +100262d4: 4620 mov r0, r4 +100262d6: f7ff fecf bl 10026078 +100262da: 7878 ldrb r0, [r7, #1] +100262dc: 1c80 adds r0, r0, #2 +100262de: 1986 adds r6, r0, r6 +100262e0: 454e cmp r6, r9 +100262e2: d20c bcs.n 100262fe +100262e4: 1970 adds r0, r6, r5 +100262e6: f100 0724 add.w r7, r0, #36 ; 0x24 +100262ea: 7838 ldrb r0, [r7, #0] +100262ec: 282a cmp r0, #42 ; 0x2a +100262ee: d0ec beq.n 100262ca +100262f0: 283d cmp r0, #61 ; 0x3d +100262f2: d1f2 bne.n 100262da +100262f4: 4639 mov r1, r7 +100262f6: 4620 mov r0, r4 +100262f8: f7ff fdc9 bl 10025e8e +100262fc: e7ed b.n 100262da +100262fe: e8bd 83f1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, pc} + +10026302 : +10026302: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +10026306: f100 0498 add.w r4, r0, #152 ; 0x98 +1002630a: 4620 mov r0, r4 +1002630c: f7f8 fae4 bl 1001e8d8 +10026310: 06c0 lsls r0, r0, #27 +10026312: d52c bpl.n 1002636e +10026314: 260c movs r6, #12 +10026316: f8df 540c ldr.w r5, [pc, #1036] ; 10026724 <.text_69> +1002631a: f8df 840c ldr.w r8, [pc, #1036] ; 10026728 <.text_70> +1002631e: f8df 940c ldr.w r9, [pc, #1036] ; 1002672c <.text_71> +10026322: e00e b.n 10026342 +10026324: 2204 movs r2, #4 +10026326: 4641 mov r1, r8 +10026328: f000 f942 bl 100265b0 <.text_63+0x4> +1002632c: b130 cbz r0, 1002633c +1002632e: 2204 movs r2, #4 +10026330: 4629 mov r1, r5 +10026332: f107 000e add.w r0, r7, #14 +10026336: f7ea fa74 bl 10010822 +1002633a: b9b0 cbnz r0, 1002636a +1002633c: 7878 ldrb r0, [r7, #1] +1002633e: 1c80 adds r0, r0, #2 +10026340: 1986 adds r6, r0, r6 +10026342: 6fa0 ldr r0, [r4, #120] ; 0x78 +10026344: 4286 cmp r6, r0 +10026346: d212 bcs.n 1002636e +10026348: 1930 adds r0, r6, r4 +1002634a: f100 077c add.w r7, r0, #124 ; 0x7c +1002634e: 7838 ldrb r0, [r7, #0] +10026350: 2830 cmp r0, #48 ; 0x30 +10026352: d002 beq.n 1002635a +10026354: 28dd cmp r0, #221 ; 0xdd +10026356: d0e5 beq.n 10026324 +10026358: e7f0 b.n 1002633c +1002635a: 2204 movs r2, #4 +1002635c: 4649 mov r1, r9 +1002635e: f107 000a add.w r0, r7, #10 +10026362: f7ea fa5e bl 10010822 +10026366: 2800 cmp r0, #0 +10026368: d0e8 beq.n 1002633c +1002636a: 2001 movs r0, #1 +1002636c: e000 b.n 10026370 +1002636e: 2000 movs r0, #0 +10026370: e8bd 83f2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, pc} + +10026374 : +10026374: 2100 movs r1, #0 +10026376: f000 007f and.w r0, r0, #127 ; 0x7f +1002637a: 2804 cmp r0, #4 +1002637c: d027 beq.n 100263ce +1002637e: 280b cmp r0, #11 +10026380: d023 beq.n 100263ca +10026382: 280c cmp r0, #12 +10026384: d01d beq.n 100263c2 +10026386: 2812 cmp r0, #18 +10026388: d019 beq.n 100263be +1002638a: 2816 cmp r0, #22 +1002638c: d01b beq.n 100263c6 +1002638e: 2818 cmp r0, #24 +10026390: d013 beq.n 100263ba +10026392: 2824 cmp r0, #36 ; 0x24 +10026394: d00f beq.n 100263b6 +10026396: 2830 cmp r0, #48 ; 0x30 +10026398: d00b beq.n 100263b2 +1002639a: 2848 cmp r0, #72 ; 0x48 +1002639c: d007 beq.n 100263ae +1002639e: 2860 cmp r0, #96 ; 0x60 +100263a0: d003 beq.n 100263aa +100263a2: 286c cmp r0, #108 ; 0x6c +100263a4: d114 bne.n 100263d0 +100263a6: 210b movs r1, #11 +100263a8: e012 b.n 100263d0 +100263aa: 210a movs r1, #10 +100263ac: e010 b.n 100263d0 +100263ae: 2109 movs r1, #9 +100263b0: e00e b.n 100263d0 +100263b2: 2108 movs r1, #8 +100263b4: e00c b.n 100263d0 +100263b6: 2107 movs r1, #7 +100263b8: e00a b.n 100263d0 +100263ba: 2106 movs r1, #6 +100263bc: e008 b.n 100263d0 +100263be: 2105 movs r1, #5 +100263c0: e006 b.n 100263d0 +100263c2: 2104 movs r1, #4 +100263c4: e004 b.n 100263d0 +100263c6: 2103 movs r1, #3 +100263c8: e002 b.n 100263d0 +100263ca: 2102 movs r1, #2 +100263cc: e000 b.n 100263d0 +100263ce: 2101 movs r1, #1 +100263d0: 4608 mov r0, r1 +100263d2: 4770 bx lr + +100263d4 : +100263d4: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +100263d8: 460d mov r5, r1 +100263da: 2600 movs r6, #0 +100263dc: 2d0e cmp r5, #14 +100263de: bf28 it cs +100263e0: 250d movcs r5, #13 +100263e2: 4604 mov r4, r0 +100263e4: 2700 movs r7, #0 +100263e6: f04f 0801 mov.w r8, #1 +100263ea: e008 b.n 100263fe +100263ec: 5d38 ldrb r0, [r7, r4] +100263ee: 0601 lsls r1, r0, #24 +100263f0: d504 bpl.n 100263fc +100263f2: f7ff ffbf bl 10026374 +100263f6: fa08 f000 lsl.w r0, r8, r0 +100263fa: 4306 orrs r6, r0 +100263fc: 1c7f adds r7, r7, #1 +100263fe: 42af cmp r7, r5 +10026400: d3f4 bcc.n 100263ec +10026402: e014 b.n 1002642e <.text_53> + +10026404 : +10026404: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +10026408: 460d mov r5, r1 +1002640a: 2600 movs r6, #0 +1002640c: 2d0e cmp r5, #14 +1002640e: bf28 it cs +10026410: 250d movcs r5, #13 +10026412: 4604 mov r4, r0 +10026414: 2700 movs r7, #0 +10026416: f04f 0801 mov.w r8, #1 +1002641a: e006 b.n 1002642a +1002641c: 5d38 ldrb r0, [r7, r4] +1002641e: f7ff ffa9 bl 10026374 +10026422: fa08 f000 lsl.w r0, r8, r0 +10026426: 4306 orrs r6, r0 +10026428: 1c7f adds r7, r7, #1 +1002642a: 42af cmp r7, r5 +1002642c: d3f6 bcc.n 1002641c + +1002642e <.text_53>: +1002642e: 4630 mov r0, r6 +10026430: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +10026434 : +10026434: 78c1 ldrb r1, [r0, #3] +10026436: 7900 ldrb r0, [r0, #4] +10026438: 0500 lsls r0, r0, #20 +1002643a: ea40 3001 orr.w r0, r0, r1, lsl #12 +1002643e: 4770 bx lr + +10026440 : +10026440: f500 609d add.w r0, r0, #1256 ; 0x4e8 +10026444: f500 7288 add.w r2, r0, #272 ; 0x110 +10026448: f892 30b4 ldrb.w r3, [r2, #180] ; 0xb4 +1002644c: 2b00 cmp r3, #0 +1002644e: bf1c itt ne +10026450: f892 20ae ldrbne.w r2, [r2, #174] ; 0xae +10026454: 2a04 cmpne r2, #4 +10026456: d00b beq.n 10026470 +10026458: 7bc0 ldrb r0, [r0, #15] +1002645a: 8809 ldrh r1, [r1, #0] +1002645c: 07c0 lsls r0, r0, #31 +1002645e: bf4c ite mi +10026460: 2006 movmi r0, #6 +10026462: 2005 movpl r0, #5 +10026464: fa21 f200 lsr.w r2, r1, r0 +10026468: 07d0 lsls r0, r2, #31 +1002646a: d501 bpl.n 10026470 +1002646c: 2001 movs r0, #1 +1002646e: 4770 bx lr +10026470: 2000 movs r0, #0 +10026472: 4770 bx lr + +10026474 : +10026474: 2100 movs r1, #0 +10026476: 221b movs r2, #27 +10026478: fa20 f302 lsr.w r3, r0, r2 +1002647c: 07db lsls r3, r3, #31 +1002647e: d501 bpl.n 10026484 +10026480: 4611 mov r1, r2 +10026482: e001 b.n 10026488 +10026484: 1e52 subs r2, r2, #1 +10026486: d5f7 bpl.n 10026478 +10026488: b2c8 uxtb r0, r1 +1002648a: 4770 bx lr + +1002648c : +1002648c: 4608 mov r0, r1 +1002648e: 2100 movs r1, #0 +10026490: f7f0 bfdc b.w 1001744c + +10026494 : +10026494: e7fa b.n 1002648c + +10026496 : +10026496: e7fd b.n 10026494 + +10026498 : +10026498: b530 push {r4, r5, lr} +1002649a: b085 sub sp, #20 +1002649c: 4604 mov r4, r0 +1002649e: 460d mov r5, r1 +100264a0: 2210 movs r2, #16 +100264a2: 2100 movs r1, #0 +100264a4: a800 add r0, sp, #0 +100264a6: f7ea f9c7 bl 10010838 +100264aa: 07e8 lsls r0, r5, #31 +100264ac: d514 bpl.n 100264d8 +100264ae: 2d01 cmp r5, #1 +100264b0: bf19 ittee ne +100264b2: 2207 movne r2, #7 +100264b4: f20f 21e4 addwne r1, pc, #740 ; 0x2e4 +100264b8: 2204 moveq r2, #4 +100264ba: f20f 21d8 addweq r1, pc, #728 ; 0x2d8 +100264be: a800 add r0, sp, #0 +100264c0: f7ea f9a5 bl 1001080e +100264c4: 2102 movs r1, #2 +100264c6: 4620 mov r0, r4 +100264c8: f7f4 fd8b bl 1001afe2 +100264cc: aa00 add r2, sp, #0 +100264ce: 2106 movs r1, #6 +100264d0: f000 f80a bl 100264e8 <.text_61> +100264d4: b005 add sp, #20 +100264d6: bd30 pop {r4, r5, pc} +100264d8: 2203 movs r2, #3 +100264da: f20f 21bc addw r1, pc, #700 ; 0x2bc +100264de: a800 add r0, sp, #0 +100264e0: f7ea f995 bl 1001080e +100264e4: 210c movs r1, #12 +100264e6: e7ee b.n 100264c6 + +100264e8 <.text_61>: +100264e8: 4620 mov r0, r4 +100264ea: f7f0 bf11 b.w 10017310 + +100264ee : +100264ee: e92d 4ff3 stmdb sp!, {r0, r1, r4, r5, r6, r7, r8, r9, sl, fp, lr} +100264f2: b081 sub sp, #4 +100264f4: 260c movs r6, #12 +100264f6: f20f 2490 addw r4, pc, #656 ; 0x290 +100264fa: f20f 2588 addw r5, pc, #648 ; 0x288 +100264fe: f20f 2a7c addw sl, pc, #636 ; 0x27c +10026502: f20f 2b74 addw fp, pc, #628 ; 0x274 +10026506: f20f 286c addw r8, pc, #620 ; 0x26c +1002650a: f20f 2964 addw r9, pc, #612 ; 0x264 +1002650e: e002 b.n 10026516 +10026510: 7878 ldrb r0, [r7, #1] +10026512: 1c80 adds r0, r0, #2 +10026514: 1986 adds r6, r0, r6 +10026516: 9802 ldr r0, [sp, #8] +10026518: 4286 cmp r6, r0 +1002651a: d244 bcs.n 100265a6 +1002651c: 9801 ldr r0, [sp, #4] +1002651e: 1837 adds r7, r6, r0 +10026520: 7838 ldrb r0, [r7, #0] +10026522: 28dd cmp r0, #221 ; 0xdd +10026524: d1f4 bne.n 10026510 +10026526: 2203 movs r2, #3 +10026528: 4649 mov r1, r9 +1002652a: f000 f841 bl 100265b0 <.text_63+0x4> +1002652e: b920 cbnz r0, 1002653a +10026530: 2203 movs r2, #3 +10026532: 4641 mov r1, r8 +10026534: f000 f83c bl 100265b0 <.text_63+0x4> +10026538: b108 cbz r0, 1002653e +1002653a: 2005 movs r0, #5 +1002653c: e034 b.n 100265a8 +1002653e: 2203 movs r2, #3 +10026540: 4659 mov r1, fp +10026542: f000 f835 bl 100265b0 <.text_63+0x4> +10026546: b928 cbnz r0, 10026554 +10026548: f000 f830 bl 100265ac <.text_63> +1002654c: b910 cbnz r0, 10026554 +1002654e: f000 f82d bl 100265ac <.text_63> +10026552: b108 cbz r0, 10026558 +10026554: 2003 movs r0, #3 +10026556: e027 b.n 100265a8 +10026558: 2203 movs r2, #3 +1002655a: 4629 mov r1, r5 +1002655c: f000 f828 bl 100265b0 <.text_63+0x4> +10026560: b108 cbz r0, 10026566 +10026562: 2008 movs r0, #8 +10026564: e020 b.n 100265a8 +10026566: 2203 movs r2, #3 +10026568: 4621 mov r1, r4 +1002656a: f000 f821 bl 100265b0 <.text_63+0x4> +1002656e: b108 cbz r0, 10026574 +10026570: 2004 movs r0, #4 +10026572: e019 b.n 100265a8 +10026574: 2203 movs r2, #3 +10026576: f20f 2108 addw r1, pc, #520 ; 0x208 +1002657a: f000 f819 bl 100265b0 <.text_63+0x4> +1002657e: b108 cbz r0, 10026584 +10026580: 2006 movs r0, #6 +10026582: e011 b.n 100265a8 +10026584: 2203 movs r2, #3 +10026586: f20f 2104 addw r1, pc, #516 ; 0x204 +1002658a: f000 f811 bl 100265b0 <.text_63+0x4> +1002658e: b108 cbz r0, 10026594 +10026590: 2001 movs r0, #1 +10026592: e009 b.n 100265a8 +10026594: 2203 movs r2, #3 +10026596: f20f 11f8 addw r1, pc, #504 ; 0x1f8 +1002659a: f000 f809 bl 100265b0 <.text_63+0x4> +1002659e: 2800 cmp r0, #0 +100265a0: d0b6 beq.n 10026510 +100265a2: 200b movs r0, #11 +100265a4: e000 b.n 100265a8 +100265a6: 2000 movs r0, #0 +100265a8: e8bd 8ffe ldmia.w sp!, {r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +100265ac <.text_63>: +100265ac: 2203 movs r2, #3 +100265ae: 4651 mov r1, sl +100265b0: 1cb8 adds r0, r7, #2 +100265b2: f7ea b936 b.w 10010822 + +100265b6 : +100265b6: f500 62bf add.w r2, r0, #1528 ; 0x5f8 +100265ba: f102 03ae add.w r3, r2, #174 ; 0xae +100265be: f892 20ae ldrb.w r2, [r2, #174] ; 0xae +100265c2: 2a01 cmp r2, #1 +100265c4: f06f 0104 mvn.w r1, #4 +100265c8: d00b beq.n 100265e2 +100265ca: 2a04 cmp r2, #4 +100265cc: d005 beq.n 100265da +100265ce: 2a08 cmp r2, #8 +100265d0: d10a bne.n 100265e8 +100265d2: 2001 movs r0, #1 +100265d4: 7298 strb r0, [r3, #10] +100265d6: 2000 movs r0, #0 +100265d8: e009 b.n 100265ee +100265da: 2200 movs r2, #0 +100265dc: 729a strb r2, [r3, #10] +100265de: 2201 movs r2, #1 +100265e0: 72da strb r2, [r3, #11] +100265e2: 2200 movs r2, #0 +100265e4: f7ff ba7a b.w 10025adc +100265e8: 2000 movs r0, #0 +100265ea: 7298 strb r0, [r3, #10] +100265ec: 2001 movs r0, #1 +100265ee: 72d8 strb r0, [r3, #11] +100265f0: 4770 bx lr + +100265f2 : +100265f2: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +100265f6: 4604 mov r4, r0 +100265f8: f504 679d add.w r7, r4, #1256 ; 0x4e8 +100265fc: f507 7888 add.w r8, r7, #272 ; 0x110 +10026600: 460e mov r6, r1 +10026602: f108 05af add.w r5, r8, #175 ; 0xaf +10026606: b082 sub sp, #8 +10026608: 06b0 lsls r0, r6, #26 +1002660a: 7868 ldrb r0, [r5, #1] +1002660c: d506 bpl.n 1002661c +1002660e: 2803 cmp r0, #3 +10026610: d00f beq.n 10026632 +10026612: 2001 movs r0, #1 +10026614: f88d 0000 strb.w r0, [sp] +10026618: 2003 movs r0, #3 +1002661a: e005 b.n 10026628 +1002661c: 2801 cmp r0, #1 +1002661e: d008 beq.n 10026632 +10026620: 2000 movs r0, #0 +10026622: f88d 0000 strb.w r0, [sp] +10026626: 2001 movs r0, #1 +10026628: 7068 strb r0, [r5, #1] +1002662a: aa00 add r2, sp, #0 +1002662c: 2113 movs r1, #19 +1002662e: f7ff ff5b bl 100264e8 <.text_61> +10026632: 07b0 lsls r0, r6, #30 +10026634: bf48 it mi +10026636: 2014 movmi r0, #20 +10026638: d412 bmi.n 10026660 +1002663a: 7c78 ldrb r0, [r7, #17] +1002663c: 210a movs r1, #10 +1002663e: 4208 tst r0, r1 +10026640: d00a beq.n 10026658 +10026642: f898 00af ldrb.w r0, [r8, #175] ; 0xaf +10026646: 0571 lsls r1, r6, #21 +10026648: d502 bpl.n 10026650 +1002664a: 2809 cmp r0, #9 +1002664c: d00d beq.n 1002666a +1002664e: e006 b.n 1002665e +10026650: 2814 cmp r0, #20 +10026652: d00a beq.n 1002666a +10026654: 2014 movs r0, #20 +10026656: e003 b.n 10026660 +10026658: 2114 movs r1, #20 +1002665a: 4208 tst r0, r1 +1002665c: d003 beq.n 10026666 +1002665e: 2009 movs r0, #9 +10026660: f888 00af strb.w r0, [r8, #175] ; 0xaf +10026664: e001 b.n 1002666a +10026666: f888 10af strb.w r1, [r8, #175] ; 0xaf +1002666a: 462a mov r2, r5 +1002666c: 2111 movs r1, #17 +1002666e: 4620 mov r0, r4 +10026670: f7f0 fe4e bl 10017310 +10026674: e8bd 81f3 ldmia.w sp!, {r0, r1, r4, r5, r6, r7, r8, pc} + +10026678 : +10026678: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +1002667c: 4604 mov r4, r0 +1002667e: f104 0098 add.w r0, r4, #152 ; 0x98 +10026682: f504 659d add.w r5, r4, #1256 ; 0x4e8 +10026686: f100 0864 add.w r8, r0, #100 ; 0x64 +1002668a: 2600 movs r6, #0 +1002668c: f505 7788 add.w r7, r5, #272 ; 0x110 +10026690: 3064 adds r0, #100 ; 0x64 +10026692: f7f1 fe7d bl 10018390 +10026696: 4681 mov r9, r0 +10026698: f107 00b4 add.w r0, r7, #180 ; 0xb4 +1002669c: 7881 ldrb r1, [r0, #2] +1002669e: 2900 cmp r1, #0 +100266a0: bf1f itttt ne +100266a2: 7840 ldrbne r0, [r0, #1] +100266a4: 2800 cmpne r0, #0 +100266a6: 2001 movne r0, #1 +100266a8: f887 00b4 strbne.w r0, [r7, #180] ; 0xb4 +100266ac: 7ba8 ldrb r0, [r5, #14] +100266ae: 280f cmp r0, #15 +100266b0: f897 00b4 ldrb.w r0, [r7, #180] ; 0xb4 +100266b4: db04 blt.n 100266c0 +100266b6: b100 cbz r0, 100266ba +100266b8: 2610 movs r6, #16 +100266ba: f046 0004 orr.w r0, r6, #4 +100266be: e014 b.n 100266ea +100266c0: b100 cbz r0, 100266c4 +100266c2: 2608 movs r6, #8 +100266c4: 4649 mov r1, r9 +100266c6: 4640 mov r0, r8 +100266c8: f7ff f8c7 bl 1002585a +100266cc: 2801 cmp r0, #1 +100266ce: bf08 it eq +100266d0: f046 0001 orreq.w r0, r6, #1 +100266d4: d009 beq.n 100266ea +100266d6: 4649 mov r1, r9 +100266d8: 4640 mov r0, r8 +100266da: f7ff f8aa bl 10025832 +100266de: 2801 cmp r0, #1 +100266e0: bf0c ite eq +100266e2: f046 0003 orreq.w r0, r6, #3 +100266e6: f046 0002 orrne.w r0, r6, #2 +100266ea: f641 01ae movw r1, #6318 ; 0x18ae +100266ee: f641 431c movw r3, #7196 ; 0x1c1c +100266f2: 5d09 ldrb r1, [r1, r4] +100266f4: 4008 ands r0, r1 +100266f6: 7468 strb r0, [r5, #17] +100266f8: aa00 add r2, sp, #0 +100266fa: 480d ldr r0, [pc, #52] ; (10026730 <.text_72>) +100266fc: 9000 str r0, [sp, #0] +100266fe: 2112 movs r1, #18 +10026700: 591b ldr r3, [r3, r4] +10026702: 4620 mov r0, r4 +10026704: 4798 blx r3 +10026706: 7c68 ldrb r0, [r5, #17] +10026708: 07c0 lsls r0, r0, #31 +1002670a: bf4c ite mi +1002670c: 2102 movmi r1, #2 +1002670e: 210c movpl r1, #12 +10026710: 4620 mov r0, r4 +10026712: f7f4 fc66 bl 1001afe2 +10026716: e8bd 83f1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, pc} + ... + +1002671c <.text_67>: +1002671c: 1001be94 .word 0x1001be94 + +10026720 <.text_68>: +10026720: 1001bea4 .word 0x1001bea4 + +10026724 <.text_69>: +10026724: 00035418 .word 0x00035418 + +10026728 <.text_70>: +10026728: 1001beb8 .word 0x1001beb8 + +1002672c <.text_71>: +1002672c: 10004460 .word 0x10004460 + +10026730 <.text_72>: +10026730: 0a0a0808 .word 0x0a0a0808 + +10026734 : +10026734: f500 629d add.w r2, r0, #1256 ; 0x4e8 +10026738: f502 7088 add.w r0, r2, #272 ; 0x110 +1002673c: eb00 1041 add.w r0, r0, r1, lsl #5 +10026740: 7c51 ldrb r1, [r2, #17] +10026742: 07c9 lsls r1, r1, #31 +10026744: f500 708e add.w r0, r0, #284 ; 0x11c +10026748: bf47 ittee mi +1002674a: 2204 movmi r2, #4 +1002674c: f20f 0144 addwmi r1, pc, #68 ; 0x44 +10026750: 2204 movpl r2, #4 +10026752: f20f 0144 addwpl r1, pc, #68 ; 0x44 +10026756: f7ea b85a b.w 1001080e + +1002675a : +1002675a: 3118 adds r1, #24 +1002675c: 684b ldr r3, [r1, #4] +1002675e: 680a ldr r2, [r1, #0] +10026760: e9c0 23d0 strd r2, r3, [r0, #832] ; 0x340 +10026764: 4770 bx lr + +10026766 : +10026766: 2200 movs r2, #0 +10026768: 2109 movs r1, #9 +1002676a: f7f0 bdd1 b.w 10017310 + ... + +10026770 : +10026770: 0300 007f .... + +10026774 : +10026774: 1300 0074 ..t. + +10026778 : +10026778: 1000 0018 .... + +1002677c : +1002677c: 0a00 00f7 .... + +10026780 : +10026780: 4000 0096 .@.. + +10026784 : +10026784: 5000 0043 .PC. + +10026788 : +10026788: 0c00 0043 ..C. + +1002678c : +1002678c: e000 004c ..L. + +10026790 : +10026790: 0a00 00f5 .... + +10026794 : +10026794: 8482 968b .... + +10026798 : +10026798: 988c 00b0 .... + +1002679c : +1002679c: 8482 968b 988c 00b0 ........ + +100267a4 : +100267a4: b40f push {r0, r1, r2, r3} +100267a6: b530 push {r4, r5, lr} +100267a8: 2400 movs r4, #0 +100267aa: 2802 cmp r0, #2 +100267ac: bf18 it ne +100267ae: 2801 cmpne r0, #1 +100267b0: b0a1 sub sp, #132 ; 0x84 +100267b2: d004 beq.n 100267be +100267b4: 2803 cmp r0, #3 +100267b6: d10f bne.n 100267d8 +100267b8: f60f 1128 addw r1, pc, #2344 ; 0x928 +100267bc: e029 b.n 10026812 +100267be: 9828 ldr r0, [sp, #160] ; 0xa0 +100267c0: f60f 01f0 addw r1, pc, #2288 ; 0x8f0 +100267c4: 2802 cmp r0, #2 +100267c6: bf0c ite eq +100267c8: f60f 1200 addweq r2, pc, #2304 ; 0x900 +100267cc: f60f 1208 addwne r2, pc, #2312 ; 0x908 +100267d0: a800 add r0, sp, #0 +100267d2: f7e5 fd6b bl 1000c2ac +100267d6: e01f b.n 10026818 +100267d8: 2804 cmp r0, #4 +100267da: bf08 it eq +100267dc: f60f 1124 addweq r1, pc, #2340 ; 0x924 +100267e0: d017 beq.n 10026812 +100267e2: 2805 cmp r0, #5 +100267e4: bf08 it eq +100267e6: f60f 113c addweq r1, pc, #2364 ; 0x93c +100267ea: d012 beq.n 10026812 +100267ec: 2806 cmp r0, #6 +100267ee: bf08 it eq +100267f0: f60f 1150 addweq r1, pc, #2384 ; 0x950 +100267f4: d00d beq.n 10026812 +100267f6: 2809 cmp r0, #9 +100267f8: bf08 it eq +100267fa: f60f 1168 addweq r1, pc, #2408 ; 0x968 +100267fe: d008 beq.n 10026812 +10026800: 2807 cmp r0, #7 +10026802: bf08 it eq +10026804: f60f 117c addweq r1, pc, #2428 ; 0x97c +10026808: d003 beq.n 10026812 +1002680a: 2808 cmp r0, #8 +1002680c: d105 bne.n 1002681a +1002680e: f60f 1194 addw r1, pc, #2452 ; 0x994 +10026812: a800 add r0, sp, #0 +10026814: f7e5 fd4a bl 1000c2ac +10026818: 4604 mov r4, r0 +1002681a: 9825 ldr r0, [sp, #148] ; 0x94 +1002681c: 2801 cmp r0, #1 +1002681e: bf0c ite eq +10026820: f60f 12a0 addweq r2, pc, #2464 ; 0x9a0 +10026824: f60f 12a8 addwne r2, pc, #2472 ; 0x9a8 +10026828: a532 add r5, pc, #200 ; (adr r5, 100268f4 <.text_3>) +1002682a: a800 add r0, sp, #0 +1002682c: 4629 mov r1, r5 +1002682e: 1820 adds r0, r4, r0 +10026830: f7e5 fd3c bl 1000c2ac +10026834: 1904 adds r4, r0, r4 +10026836: a800 add r0, sp, #0 +10026838: 9927 ldr r1, [sp, #156] ; 0x9c +1002683a: 1820 adds r0, r4, r0 +1002683c: b911 cbnz r1, 10026844 +1002683e: f60f 129c addw r2, pc, #2460 ; 0x99c +10026842: e007 b.n 10026854 +10026844: 2901 cmp r1, #1 +10026846: bf08 it eq +10026848: a22b addeq r2, pc, #172 ; (adr r2, 100268f8 <.text_4>) +1002684a: d003 beq.n 10026854 +1002684c: 2902 cmp r1, #2 +1002684e: d105 bne.n 1002685c +10026850: f60f 1290 addw r2, pc, #2448 ; 0x990 +10026854: 4629 mov r1, r5 +10026856: f7e5 fd29 bl 1000c2ac +1002685a: 1904 adds r4, r0, r4 +1002685c: a800 add r0, sp, #0 +1002685e: 9a26 ldr r2, [sp, #152] ; 0x98 +10026860: 1820 adds r0, r4, r0 +10026862: b912 cbnz r2, 1002686a +10026864: f60f 1184 addw r1, pc, #2436 ; 0x984 +10026868: e017 b.n 1002689a +1002686a: 2a01 cmp r2, #1 +1002686c: d102 bne.n 10026874 +1002686e: f60f 1184 addw r1, pc, #2436 ; 0x984 +10026872: e012 b.n 1002689a +10026874: 2a02 cmp r2, #2 +10026876: d102 bne.n 1002687e +10026878: f60f 1180 addw r1, pc, #2432 ; 0x980 +1002687c: e00d b.n 1002689a +1002687e: 2a03 cmp r2, #3 +10026880: d102 bne.n 10026888 +10026882: f60f 1180 addw r1, pc, #2432 ; 0x980 +10026886: e008 b.n 1002689a +10026888: 2a04 cmp r2, #4 +1002688a: d102 bne.n 10026892 +1002688c: f60f 117c addw r1, pc, #2428 ; 0x97c +10026890: e003 b.n 1002689a +10026892: 2a08 cmp r2, #8 +10026894: d104 bne.n 100268a0 +10026896: f60f 117c addw r1, pc, #2428 ; 0x97c +1002689a: f7e5 fd07 bl 1000c2ac +1002689e: e003 b.n 100268a8 +100268a0: f60f 1178 addw r1, pc, #2424 ; 0x978 +100268a4: f7e5 fd02 bl 1000c2ac +100268a8: 1904 adds r4, r0, r4 +100268aa: a800 add r0, sp, #0 +100268ac: 9a28 ldr r2, [sp, #160] ; 0xa0 +100268ae: 1820 adds r0, r4, r0 +100268b0: b912 cbnz r2, 100268b8 +100268b2: f60f 117c addw r1, pc, #2428 ; 0x97c +100268b6: e008 b.n 100268ca +100268b8: 2a01 cmp r2, #1 +100268ba: d102 bne.n 100268c2 +100268bc: f60f 1178 addw r1, pc, #2424 ; 0x978 +100268c0: e003 b.n 100268ca +100268c2: 2a02 cmp r2, #2 +100268c4: d104 bne.n 100268d0 +100268c6: f60f 1178 addw r1, pc, #2424 ; 0x978 +100268ca: f7e5 fcef bl 1000c2ac +100268ce: e003 b.n 100268d8 +100268d0: f60f 1174 addw r1, pc, #2420 ; 0x974 +100268d4: f7e5 fcea bl 1000c2ac +100268d8: 1900 adds r0, r0, r4 +100268da: f89d 20a4 ldrb.w r2, [sp, #164] ; 0xa4 +100268de: f60f 117c addw r1, pc, #2428 ; 0x97c +100268e2: ab00 add r3, sp, #0 +100268e4: 18c0 adds r0, r0, r3 +100268e6: f7e5 fce1 bl 1000c2ac +100268ea: b021 add sp, #132 ; 0x84 +100268ec: bc30 pop {r4, r5} +100268ee: f85d fb14 ldr.w pc, [sp], #20 + ... + +100268f4 <.text_3>: +100268f4: 005f7325 .word 0x005f7325 + +100268f8 <.text_4>: +100268f8: 00434d55 .word 0x00434d55 + +100268fc : +100268fc: 9800 ldr r0, [sp, #0] +100268fe: b938 cbnz r0, 10026910 +10026900: 2a59 cmp r2, #89 ; 0x59 +10026902: db01 blt.n 10026908 +10026904: 2a7f cmp r2, #127 ; 0x7f +10026906: d101 bne.n 1002690c +10026908: 0608 lsls r0, r1, #24 +1002690a: d501 bpl.n 10026910 +1002690c: f001 027f and.w r2, r1, #127 ; 0x7f +10026910: 2a59 cmp r2, #89 ; 0x59 +10026912: db02 blt.n 1002691a +10026914: 2a7f cmp r2, #127 ; 0x7f +10026916: bf18 it ne +10026918: 461a movne r2, r3 +1002691a: 4610 mov r0, r2 +1002691c: 4770 bx lr + +1002691e : +1002691e: 2201 movs r2, #1 +10026920: 290f cmp r1, #15 +10026922: f641 03ae movw r3, #6318 ; 0x18ae +10026926: d304 bcc.n 10026932 +10026928: 5c18 ldrb r0, [r3, r0] +1002692a: 2114 movs r1, #20 +1002692c: 4208 tst r0, r1 +1002692e: d107 bne.n 10026940 +10026930: e005 b.n 1002693e +10026932: 2900 cmp r1, #0 +10026934: bf1e ittt ne +10026936: 5c18 ldrbne r0, [r3, r0] +10026938: 210b movne r1, #11 +1002693a: 4208 tstne r0, r1 +1002693c: d100 bne.n 10026940 +1002693e: 2200 movs r2, #0 +10026940: 4610 mov r0, r2 +10026942: 4770 bx lr + +10026944 : +10026944: 2100 movs r1, #0 +10026946: 2804 cmp r0, #4 +10026948: d05d beq.n 10026a06 +1002694a: 280b cmp r0, #11 +1002694c: d05d beq.n 10026a0a +1002694e: 280c cmp r0, #12 +10026950: d05f beq.n 10026a12 +10026952: 2812 cmp r0, #18 +10026954: d05f beq.n 10026a16 +10026956: 2816 cmp r0, #22 +10026958: d059 beq.n 10026a0e +1002695a: 2818 cmp r0, #24 +1002695c: d05d beq.n 10026a1a +1002695e: 2824 cmp r0, #36 ; 0x24 +10026960: d05d beq.n 10026a1e +10026962: 2830 cmp r0, #48 ; 0x30 +10026964: d05d beq.n 10026a22 +10026966: 2848 cmp r0, #72 ; 0x48 +10026968: d05d beq.n 10026a26 +1002696a: 2860 cmp r0, #96 ; 0x60 +1002696c: d05d beq.n 10026a2a +1002696e: 286c cmp r0, #108 ; 0x6c +10026970: d05d beq.n 10026a2e +10026972: 2880 cmp r0, #128 ; 0x80 +10026974: d05d beq.n 10026a32 +10026976: 2881 cmp r0, #129 ; 0x81 +10026978: d05d beq.n 10026a36 +1002697a: 2882 cmp r0, #130 ; 0x82 +1002697c: d05d beq.n 10026a3a +1002697e: 2883 cmp r0, #131 ; 0x83 +10026980: d05d beq.n 10026a3e +10026982: 2884 cmp r0, #132 ; 0x84 +10026984: d05d beq.n 10026a42 +10026986: 2885 cmp r0, #133 ; 0x85 +10026988: d05d beq.n 10026a46 +1002698a: 2886 cmp r0, #134 ; 0x86 +1002698c: d05d beq.n 10026a4a +1002698e: 2887 cmp r0, #135 ; 0x87 +10026990: d05d beq.n 10026a4e +10026992: 2888 cmp r0, #136 ; 0x88 +10026994: d05d beq.n 10026a52 +10026996: 2889 cmp r0, #137 ; 0x89 +10026998: d05d beq.n 10026a56 +1002699a: 288a cmp r0, #138 ; 0x8a +1002699c: d05d beq.n 10026a5a +1002699e: 288b cmp r0, #139 ; 0x8b +100269a0: d05d beq.n 10026a5e +100269a2: 288c cmp r0, #140 ; 0x8c +100269a4: d05d beq.n 10026a62 +100269a6: 288d cmp r0, #141 ; 0x8d +100269a8: d05d beq.n 10026a66 +100269aa: 288e cmp r0, #142 ; 0x8e +100269ac: d05d beq.n 10026a6a +100269ae: 288f cmp r0, #143 ; 0x8f +100269b0: d05d beq.n 10026a6e +100269b2: 28a0 cmp r0, #160 ; 0xa0 +100269b4: d05d beq.n 10026a72 +100269b6: 28a1 cmp r0, #161 ; 0xa1 +100269b8: d05d beq.n 10026a76 +100269ba: 28a2 cmp r0, #162 ; 0xa2 +100269bc: d05d beq.n 10026a7a +100269be: 28a3 cmp r0, #163 ; 0xa3 +100269c0: d05d beq.n 10026a7e +100269c2: 28a4 cmp r0, #164 ; 0xa4 +100269c4: d05d beq.n 10026a82 +100269c6: 28a5 cmp r0, #165 ; 0xa5 +100269c8: d05d beq.n 10026a86 +100269ca: 28a6 cmp r0, #166 ; 0xa6 +100269cc: d05d beq.n 10026a8a +100269ce: 28a7 cmp r0, #167 ; 0xa7 +100269d0: d05d beq.n 10026a8e +100269d2: 28a8 cmp r0, #168 ; 0xa8 +100269d4: d05d beq.n 10026a92 +100269d6: 28a9 cmp r0, #169 ; 0xa9 +100269d8: d05d beq.n 10026a96 +100269da: 28aa cmp r0, #170 ; 0xaa +100269dc: d05d beq.n 10026a9a +100269de: 28ab cmp r0, #171 ; 0xab +100269e0: d05d beq.n 10026a9e +100269e2: 28ac cmp r0, #172 ; 0xac +100269e4: d05d beq.n 10026aa2 +100269e6: 28ad cmp r0, #173 ; 0xad +100269e8: d05d beq.n 10026aa6 +100269ea: 28ae cmp r0, #174 ; 0xae +100269ec: d05d beq.n 10026aaa +100269ee: 28af cmp r0, #175 ; 0xaf +100269f0: d05d beq.n 10026aae +100269f2: 28b0 cmp r0, #176 ; 0xb0 +100269f4: d05d beq.n 10026ab2 +100269f6: 28b1 cmp r0, #177 ; 0xb1 +100269f8: d05d beq.n 10026ab6 +100269fa: 28b2 cmp r0, #178 ; 0xb2 +100269fc: d05d beq.n 10026aba +100269fe: 28b3 cmp r0, #179 ; 0xb3 +10026a00: bf08 it eq +10026a02: 213f moveq r1, #63 ; 0x3f +10026a04: e05a b.n 10026abc +10026a06: 2101 movs r1, #1 +10026a08: e058 b.n 10026abc +10026a0a: 2102 movs r1, #2 +10026a0c: e056 b.n 10026abc +10026a0e: 2103 movs r1, #3 +10026a10: e054 b.n 10026abc +10026a12: 2104 movs r1, #4 +10026a14: e052 b.n 10026abc +10026a16: 2105 movs r1, #5 +10026a18: e050 b.n 10026abc +10026a1a: 2106 movs r1, #6 +10026a1c: e04e b.n 10026abc +10026a1e: 2107 movs r1, #7 +10026a20: e04c b.n 10026abc +10026a22: 2108 movs r1, #8 +10026a24: e04a b.n 10026abc +10026a26: 2109 movs r1, #9 +10026a28: e048 b.n 10026abc +10026a2a: 210a movs r1, #10 +10026a2c: e046 b.n 10026abc +10026a2e: 210b movs r1, #11 +10026a30: e044 b.n 10026abc +10026a32: 210c movs r1, #12 +10026a34: e042 b.n 10026abc +10026a36: 210d movs r1, #13 +10026a38: e040 b.n 10026abc +10026a3a: 210e movs r1, #14 +10026a3c: e03e b.n 10026abc +10026a3e: 210f movs r1, #15 +10026a40: e03c b.n 10026abc +10026a42: 2110 movs r1, #16 +10026a44: e03a b.n 10026abc +10026a46: 2111 movs r1, #17 +10026a48: e038 b.n 10026abc +10026a4a: 2112 movs r1, #18 +10026a4c: e036 b.n 10026abc +10026a4e: 2113 movs r1, #19 +10026a50: e034 b.n 10026abc +10026a52: 2114 movs r1, #20 +10026a54: e032 b.n 10026abc +10026a56: 2115 movs r1, #21 +10026a58: e030 b.n 10026abc +10026a5a: 2116 movs r1, #22 +10026a5c: e02e b.n 10026abc +10026a5e: 2117 movs r1, #23 +10026a60: e02c b.n 10026abc +10026a62: 2118 movs r1, #24 +10026a64: e02a b.n 10026abc +10026a66: 2119 movs r1, #25 +10026a68: e028 b.n 10026abc +10026a6a: 211a movs r1, #26 +10026a6c: e026 b.n 10026abc +10026a6e: 211b movs r1, #27 +10026a70: e024 b.n 10026abc +10026a72: 212c movs r1, #44 ; 0x2c +10026a74: e022 b.n 10026abc +10026a76: 212d movs r1, #45 ; 0x2d +10026a78: e020 b.n 10026abc +10026a7a: 212e movs r1, #46 ; 0x2e +10026a7c: e01e b.n 10026abc +10026a7e: 212f movs r1, #47 ; 0x2f +10026a80: e01c b.n 10026abc +10026a82: 2130 movs r1, #48 ; 0x30 +10026a84: e01a b.n 10026abc +10026a86: 2131 movs r1, #49 ; 0x31 +10026a88: e018 b.n 10026abc +10026a8a: 2132 movs r1, #50 ; 0x32 +10026a8c: e016 b.n 10026abc +10026a8e: 2133 movs r1, #51 ; 0x33 +10026a90: e014 b.n 10026abc +10026a92: 2134 movs r1, #52 ; 0x34 +10026a94: e012 b.n 10026abc +10026a96: 2135 movs r1, #53 ; 0x35 +10026a98: e010 b.n 10026abc +10026a9a: 2136 movs r1, #54 ; 0x36 +10026a9c: e00e b.n 10026abc +10026a9e: 2137 movs r1, #55 ; 0x37 +10026aa0: e00c b.n 10026abc +10026aa2: 2138 movs r1, #56 ; 0x38 +10026aa4: e00a b.n 10026abc +10026aa6: 2139 movs r1, #57 ; 0x39 +10026aa8: e008 b.n 10026abc +10026aaa: 213a movs r1, #58 ; 0x3a +10026aac: e006 b.n 10026abc +10026aae: 213b movs r1, #59 ; 0x3b +10026ab0: e004 b.n 10026abc +10026ab2: 213c movs r1, #60 ; 0x3c +10026ab4: e002 b.n 10026abc +10026ab6: 213d movs r1, #61 ; 0x3d +10026ab8: e000 b.n 10026abc +10026aba: 213e movs r1, #62 ; 0x3e +10026abc: 4608 mov r0, r1 +10026abe: 4770 bx lr + +10026ac0 : +10026ac0: 2102 movs r1, #2 +10026ac2: 1e40 subs r0, r0, #1 +10026ac4: 2852 cmp r0, #82 ; 0x52 +10026ac6: d82c bhi.n 10026b22 +10026ac8: e8df f000 tbb [pc, r0] +10026acc: 302e2c2a .word 0x302e2c2a +10026ad0: 38363432 .word 0x38363432 +10026ad4: 403e3c3a .word 0x403e3c3a +10026ad8: 48464442 .word 0x48464442 +10026adc: 504e4c4a .word 0x504e4c4a +10026ae0: 58565452 .word 0x58565452 +10026ae4: 605e5c5a .word 0x605e5c5a +10026ae8: 68666462 .word 0x68666462 +10026aec: 706e6c6a .word 0x706e6c6a +10026af0: 78767472 .word 0x78767472 +10026af4: 807e7c7a .word 0x807e7c7a +10026af8: 88868482 .word 0x88868482 +10026afc: 908e8c8a .word 0x908e8c8a +10026b00: 98969492 .word 0x98969492 +10026b04: a09e9c9a .word 0xa09e9c9a +10026b08: a8a6a4a2 .word 0xa8a6a4a2 +10026b0c: b0aeacaa .word 0xb0aeacaa +10026b10: b8b6b4b2 .word 0xb8b6b4b2 +10026b14: c0bebcba .word 0xc0bebcba +10026b18: c8c6c4c2 .word 0xc8c6c4c2 +10026b1c: 00ceccca .word 0x00ceccca +10026b20: 2104 movs r1, #4 +10026b22: e0a2 b.n 10026c6a +10026b24: 210b movs r1, #11 +10026b26: e0a0 b.n 10026c6a +10026b28: 2116 movs r1, #22 +10026b2a: e09e b.n 10026c6a +10026b2c: 210c movs r1, #12 +10026b2e: e09c b.n 10026c6a +10026b30: 2112 movs r1, #18 +10026b32: e09a b.n 10026c6a +10026b34: 2118 movs r1, #24 +10026b36: e098 b.n 10026c6a +10026b38: 2124 movs r1, #36 ; 0x24 +10026b3a: e096 b.n 10026c6a +10026b3c: 2130 movs r1, #48 ; 0x30 +10026b3e: e094 b.n 10026c6a +10026b40: 2148 movs r1, #72 ; 0x48 +10026b42: e092 b.n 10026c6a +10026b44: 2160 movs r1, #96 ; 0x60 +10026b46: e090 b.n 10026c6a +10026b48: 216c movs r1, #108 ; 0x6c +10026b4a: e08e b.n 10026c6a +10026b4c: 2180 movs r1, #128 ; 0x80 +10026b4e: e08c b.n 10026c6a +10026b50: 2181 movs r1, #129 ; 0x81 +10026b52: e08a b.n 10026c6a +10026b54: 2182 movs r1, #130 ; 0x82 +10026b56: e088 b.n 10026c6a +10026b58: 2183 movs r1, #131 ; 0x83 +10026b5a: e086 b.n 10026c6a +10026b5c: 2184 movs r1, #132 ; 0x84 +10026b5e: e084 b.n 10026c6a +10026b60: 2185 movs r1, #133 ; 0x85 +10026b62: e082 b.n 10026c6a +10026b64: 2186 movs r1, #134 ; 0x86 +10026b66: e080 b.n 10026c6a +10026b68: 2187 movs r1, #135 ; 0x87 +10026b6a: e07e b.n 10026c6a +10026b6c: 2188 movs r1, #136 ; 0x88 +10026b6e: e07c b.n 10026c6a +10026b70: 2189 movs r1, #137 ; 0x89 +10026b72: e07a b.n 10026c6a +10026b74: 218a movs r1, #138 ; 0x8a +10026b76: e078 b.n 10026c6a +10026b78: 218b movs r1, #139 ; 0x8b +10026b7a: e076 b.n 10026c6a +10026b7c: 218c movs r1, #140 ; 0x8c +10026b7e: e074 b.n 10026c6a +10026b80: 218d movs r1, #141 ; 0x8d +10026b82: e072 b.n 10026c6a +10026b84: 218e movs r1, #142 ; 0x8e +10026b86: e070 b.n 10026c6a +10026b88: 218f movs r1, #143 ; 0x8f +10026b8a: e06e b.n 10026c6a +10026b8c: 2190 movs r1, #144 ; 0x90 +10026b8e: e06c b.n 10026c6a +10026b90: 2191 movs r1, #145 ; 0x91 +10026b92: e06a b.n 10026c6a +10026b94: 2192 movs r1, #146 ; 0x92 +10026b96: e068 b.n 10026c6a +10026b98: 2193 movs r1, #147 ; 0x93 +10026b9a: e066 b.n 10026c6a +10026b9c: 2194 movs r1, #148 ; 0x94 +10026b9e: e064 b.n 10026c6a +10026ba0: 2195 movs r1, #149 ; 0x95 +10026ba2: e062 b.n 10026c6a +10026ba4: 2196 movs r1, #150 ; 0x96 +10026ba6: e060 b.n 10026c6a +10026ba8: 2197 movs r1, #151 ; 0x97 +10026baa: e05e b.n 10026c6a +10026bac: 2198 movs r1, #152 ; 0x98 +10026bae: e05c b.n 10026c6a +10026bb0: 2199 movs r1, #153 ; 0x99 +10026bb2: e05a b.n 10026c6a +10026bb4: 219a movs r1, #154 ; 0x9a +10026bb6: e058 b.n 10026c6a +10026bb8: 219b movs r1, #155 ; 0x9b +10026bba: e056 b.n 10026c6a +10026bbc: 219c movs r1, #156 ; 0x9c +10026bbe: e054 b.n 10026c6a +10026bc0: 219d movs r1, #157 ; 0x9d +10026bc2: e052 b.n 10026c6a +10026bc4: 219e movs r1, #158 ; 0x9e +10026bc6: e050 b.n 10026c6a +10026bc8: 219f movs r1, #159 ; 0x9f +10026bca: e04e b.n 10026c6a +10026bcc: 21a0 movs r1, #160 ; 0xa0 +10026bce: e04c b.n 10026c6a +10026bd0: 21a1 movs r1, #161 ; 0xa1 +10026bd2: e04a b.n 10026c6a +10026bd4: 21a2 movs r1, #162 ; 0xa2 +10026bd6: e048 b.n 10026c6a +10026bd8: 21a3 movs r1, #163 ; 0xa3 +10026bda: e046 b.n 10026c6a +10026bdc: 21a4 movs r1, #164 ; 0xa4 +10026bde: e044 b.n 10026c6a +10026be0: 21a5 movs r1, #165 ; 0xa5 +10026be2: e042 b.n 10026c6a +10026be4: 21a6 movs r1, #166 ; 0xa6 +10026be6: e040 b.n 10026c6a +10026be8: 21a7 movs r1, #167 ; 0xa7 +10026bea: e03e b.n 10026c6a +10026bec: 21a8 movs r1, #168 ; 0xa8 +10026bee: e03c b.n 10026c6a +10026bf0: 21a9 movs r1, #169 ; 0xa9 +10026bf2: e03a b.n 10026c6a +10026bf4: 21aa movs r1, #170 ; 0xaa +10026bf6: e038 b.n 10026c6a +10026bf8: 21ab movs r1, #171 ; 0xab +10026bfa: e036 b.n 10026c6a +10026bfc: 21ac movs r1, #172 ; 0xac +10026bfe: e034 b.n 10026c6a +10026c00: 21ad movs r1, #173 ; 0xad +10026c02: e032 b.n 10026c6a +10026c04: 21ae movs r1, #174 ; 0xae +10026c06: e030 b.n 10026c6a +10026c08: 21af movs r1, #175 ; 0xaf +10026c0a: e02e b.n 10026c6a +10026c0c: 21b0 movs r1, #176 ; 0xb0 +10026c0e: e02c b.n 10026c6a +10026c10: 21b1 movs r1, #177 ; 0xb1 +10026c12: e02a b.n 10026c6a +10026c14: 21b2 movs r1, #178 ; 0xb2 +10026c16: e028 b.n 10026c6a +10026c18: 21b3 movs r1, #179 ; 0xb3 +10026c1a: e026 b.n 10026c6a +10026c1c: 21b4 movs r1, #180 ; 0xb4 +10026c1e: e024 b.n 10026c6a +10026c20: 21b5 movs r1, #181 ; 0xb5 +10026c22: e022 b.n 10026c6a +10026c24: 21b6 movs r1, #182 ; 0xb6 +10026c26: e020 b.n 10026c6a +10026c28: 21b7 movs r1, #183 ; 0xb7 +10026c2a: e01e b.n 10026c6a +10026c2c: 21b8 movs r1, #184 ; 0xb8 +10026c2e: e01c b.n 10026c6a +10026c30: 21b9 movs r1, #185 ; 0xb9 +10026c32: e01a b.n 10026c6a +10026c34: 21ba movs r1, #186 ; 0xba +10026c36: e018 b.n 10026c6a +10026c38: 21bb movs r1, #187 ; 0xbb +10026c3a: e016 b.n 10026c6a +10026c3c: 21bc movs r1, #188 ; 0xbc +10026c3e: e014 b.n 10026c6a +10026c40: 21bd movs r1, #189 ; 0xbd +10026c42: e012 b.n 10026c6a +10026c44: 21be movs r1, #190 ; 0xbe +10026c46: e010 b.n 10026c6a +10026c48: 21bf movs r1, #191 ; 0xbf +10026c4a: e00e b.n 10026c6a +10026c4c: 21c0 movs r1, #192 ; 0xc0 +10026c4e: e00c b.n 10026c6a +10026c50: 21c1 movs r1, #193 ; 0xc1 +10026c52: e00a b.n 10026c6a +10026c54: 21c2 movs r1, #194 ; 0xc2 +10026c56: e008 b.n 10026c6a +10026c58: 21c3 movs r1, #195 ; 0xc3 +10026c5a: e006 b.n 10026c6a +10026c5c: 21c4 movs r1, #196 ; 0xc4 +10026c5e: e004 b.n 10026c6a +10026c60: 21c5 movs r1, #197 ; 0xc5 +10026c62: e002 b.n 10026c6a +10026c64: 21c6 movs r1, #198 ; 0xc6 +10026c66: e000 b.n 10026c6a +10026c68: 21c7 movs r1, #199 ; 0xc7 +10026c6a: 4608 mov r0, r1 +10026c6c: 4770 bx lr + +10026c6e : +10026c6e: b510 push {r4, lr} +10026c70: 2000 movs r0, #0 +10026c72: 5c43 ldrb r3, [r0, r1] +10026c74: 061c lsls r4, r3, #24 +10026c76: d54a bpl.n 10026d0e +10026c78: f003 037f and.w r3, r3, #127 ; 0x7f +10026c7c: 2b02 cmp r3, #2 +10026c7e: d016 beq.n 10026cae +10026c80: 2b04 cmp r3, #4 +10026c82: d018 beq.n 10026cb6 +10026c84: 2b0b cmp r3, #11 +10026c86: d01a beq.n 10026cbe +10026c88: 2b0c cmp r3, #12 +10026c8a: d020 beq.n 10026cce +10026c8c: 2b12 cmp r3, #18 +10026c8e: d022 beq.n 10026cd6 +10026c90: 2b16 cmp r3, #22 +10026c92: d018 beq.n 10026cc6 +10026c94: 2b18 cmp r3, #24 +10026c96: d022 beq.n 10026cde +10026c98: 2b24 cmp r3, #36 ; 0x24 +10026c9a: d024 beq.n 10026ce6 +10026c9c: 2b30 cmp r3, #48 ; 0x30 +10026c9e: d026 beq.n 10026cee +10026ca0: 2b48 cmp r3, #72 ; 0x48 +10026ca2: d028 beq.n 10026cf6 +10026ca4: 2b60 cmp r3, #96 ; 0x60 +10026ca6: d02a beq.n 10026cfe +10026ca8: 2b6c cmp r3, #108 ; 0x6c +10026caa: d02c beq.n 10026d06 +10026cac: e02f b.n 10026d0e +10026cae: 8813 ldrh r3, [r2, #0] +10026cb0: f043 0301 orr.w r3, r3, #1 +10026cb4: e02a b.n 10026d0c +10026cb6: 8813 ldrh r3, [r2, #0] +10026cb8: f043 0302 orr.w r3, r3, #2 +10026cbc: e026 b.n 10026d0c +10026cbe: 8813 ldrh r3, [r2, #0] +10026cc0: f043 0304 orr.w r3, r3, #4 +10026cc4: e022 b.n 10026d0c +10026cc6: 8813 ldrh r3, [r2, #0] +10026cc8: f043 0308 orr.w r3, r3, #8 +10026ccc: e01e b.n 10026d0c +10026cce: 8813 ldrh r3, [r2, #0] +10026cd0: f043 0310 orr.w r3, r3, #16 +10026cd4: e01a b.n 10026d0c +10026cd6: 8813 ldrh r3, [r2, #0] +10026cd8: f043 0320 orr.w r3, r3, #32 +10026cdc: e016 b.n 10026d0c +10026cde: 8813 ldrh r3, [r2, #0] +10026ce0: f043 0340 orr.w r3, r3, #64 ; 0x40 +10026ce4: e012 b.n 10026d0c +10026ce6: 8813 ldrh r3, [r2, #0] +10026ce8: f043 0380 orr.w r3, r3, #128 ; 0x80 +10026cec: e00e b.n 10026d0c +10026cee: 8813 ldrh r3, [r2, #0] +10026cf0: f443 7380 orr.w r3, r3, #256 ; 0x100 +10026cf4: e00a b.n 10026d0c +10026cf6: 8813 ldrh r3, [r2, #0] +10026cf8: f443 7300 orr.w r3, r3, #512 ; 0x200 +10026cfc: e006 b.n 10026d0c +10026cfe: 8813 ldrh r3, [r2, #0] +10026d00: f443 6380 orr.w r3, r3, #1024 ; 0x400 +10026d04: e002 b.n 10026d0c +10026d06: 8813 ldrh r3, [r2, #0] +10026d08: f443 6300 orr.w r3, r3, #2048 ; 0x800 +10026d0c: 8013 strh r3, [r2, #0] +10026d0e: 1c40 adds r0, r0, #1 +10026d10: 2810 cmp r0, #16 +10026d12: dbae blt.n 10026c72 +10026d14: bd10 pop {r4, pc} + +10026d16 <_TwoOutPipeMapping>: +10026d16: 6880 ldr r0, [r0, #8] +10026d18: 7c82 ldrb r2, [r0, #18] +10026d1a: b129 cbz r1, 10026d28 <_TwoOutPipeMapping+0x12> +10026d1c: 7502 strb r2, [r0, #20] +10026d1e: 7c41 ldrb r1, [r0, #17] +10026d20: 7541 strb r1, [r0, #21] +10026d22: 7582 strb r2, [r0, #22] +10026d24: 75c1 strb r1, [r0, #23] +10026d26: e004 b.n 10026d32 <_TwoOutPipeMapping+0x1c> +10026d28: 7c41 ldrb r1, [r0, #17] +10026d2a: 7501 strb r1, [r0, #20] +10026d2c: 7541 strb r1, [r0, #21] +10026d2e: 7582 strb r2, [r0, #22] +10026d30: 75c2 strb r2, [r0, #23] +10026d32: 7601 strb r1, [r0, #24] +10026d34: 7641 strb r1, [r0, #25] +10026d36: 7681 strb r1, [r0, #26] +10026d38: 76c1 strb r1, [r0, #27] +10026d3a: 4770 bx lr + +10026d3c <_ThreeOutPipeMapping>: +10026d3c: 6880 ldr r0, [r0, #8] +10026d3e: 7c42 ldrb r2, [r0, #17] +10026d40: 7502 strb r2, [r0, #20] +10026d42: 2900 cmp r1, #0 +10026d44: 7c81 ldrb r1, [r0, #18] +10026d46: 7541 strb r1, [r0, #21] +10026d48: bf19 ittee ne +10026d4a: 7cc3 ldrbne r3, [r0, #19] +10026d4c: 7583 strbne r3, [r0, #22] +10026d4e: 7cc1 ldrbeq r1, [r0, #19] +10026d50: 7581 strbeq r1, [r0, #22] +10026d52: 75c1 strb r1, [r0, #23] +10026d54: 7602 strb r2, [r0, #24] +10026d56: 7642 strb r2, [r0, #25] +10026d58: 7682 strb r2, [r0, #26] +10026d5a: 76c2 strb r2, [r0, #27] +10026d5c: 4770 bx lr + +10026d5e : +10026d5e: b510 push {r4, lr} +10026d60: f641 02d8 movw r2, #6360 ; 0x18d8 +10026d64: 5c12 ldrb r2, [r2, r0] +10026d66: b102 cbz r2, 10026d6a +10026d68: 2201 movs r2, #1 +10026d6a: 2401 movs r4, #1 +10026d6c: 2901 cmp r1, #1 +10026d6e: d00e beq.n 10026d8e +10026d70: d318 bcc.n 10026da4 +10026d72: 2903 cmp r1, #3 +10026d74: d007 beq.n 10026d86 +10026d76: d302 bcc.n 10026d7e +10026d78: 2904 cmp r1, #4 +10026d7a: d004 beq.n 10026d86 +10026d7c: e012 b.n 10026da4 +10026d7e: 4611 mov r1, r2 +10026d80: f7ff ffc9 bl 10026d16 <_TwoOutPipeMapping> +10026d84: e00f b.n 10026da6 +10026d86: 4611 mov r1, r2 +10026d88: f7ff ffd8 bl 10026d3c <_ThreeOutPipeMapping> +10026d8c: e00b b.n 10026da6 +10026d8e: 6880 ldr r0, [r0, #8] +10026d90: 7c41 ldrb r1, [r0, #17] +10026d92: 7501 strb r1, [r0, #20] +10026d94: 7541 strb r1, [r0, #21] +10026d96: 7581 strb r1, [r0, #22] +10026d98: 75c1 strb r1, [r0, #23] +10026d9a: 7601 strb r1, [r0, #24] +10026d9c: 7641 strb r1, [r0, #25] +10026d9e: 7681 strb r1, [r0, #26] +10026da0: 76c1 strb r1, [r0, #27] +10026da2: e000 b.n 10026da6 +10026da4: 2400 movs r4, #0 +10026da6: 4620 mov r0, r4 +10026da8: bd10 pop {r4, pc} + +10026daa : +10026daa: b538 push {r3, r4, r5, lr} +10026dac: 4604 mov r4, r0 +10026dae: f641 1595 movw r5, #6549 ; 0x1995 +10026db2: 192a adds r2, r5, r4 +10026db4: 2103 movs r1, #3 +10026db6: f7f0 faab bl 10017310 +10026dba: f641 5048 movw r0, #7496 ; 0x1d48 +10026dbe: 5900 ldr r0, [r0, r4] +10026dc0: b128 cbz r0, 10026dce +10026dc2: 182a adds r2, r5, r0 +10026dc4: e8bd 4038 ldmia.w sp!, {r3, r4, r5, lr} +10026dc8: 2103 movs r1, #3 +10026dca: f7f0 baa1 b.w 10017310 +10026dce: bd31 pop {r0, r4, r5, pc} + +10026dd0 : +10026dd0: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +10026dd4: b08f sub sp, #60 ; 0x3c +10026dd6: 4680 mov r8, r0 +10026dd8: f44f 7181 mov.w r1, #258 ; 0x102 +10026ddc: f7fd ff26 bl 10024c2c +10026de0: 4605 mov r5, r0 +10026de2: f44f 61aa mov.w r1, #1360 ; 0x550 +10026de6: f000 f90d bl 10027004 <.text_16> +10026dea: f88d 0002 strb.w r0, [sp, #2] +10026dee: f240 5951 movw r9, #1361 ; 0x551 +10026df2: 4649 mov r1, r9 +10026df4: f000 f906 bl 10027004 <.text_16> +10026df8: f88d 0001 strb.w r0, [sp, #1] +10026dfc: 2400 movs r4, #0 +10026dfe: f10d 0a06 add.w sl, sp, #6 +10026e02: f204 515a addw r1, r4, #1370 ; 0x55a +10026e06: f000 f8fd bl 10027004 <.text_16> +10026e0a: f804 000a strb.w r0, [r4, sl] +10026e0e: 1c64 adds r4, r4, #1 +10026e10: 2c02 cmp r4, #2 +10026e12: dbf6 blt.n 10026e02 +10026e14: 2600 movs r6, #0 +10026e16: ac01 add r4, sp, #4 +10026e18: f506 61ae add.w r1, r6, #1392 ; 0x570 +10026e1c: f000 f8f2 bl 10027004 <.text_16> +10026e20: 5530 strb r0, [r6, r4] +10026e22: 1c76 adds r6, r6, #1 +10026e24: 2e02 cmp r6, #2 +10026e26: dbf7 blt.n 10026e18 +10026e28: 2600 movs r6, #0 +10026e2a: f506 61ac add.w r1, r6, #1376 ; 0x560 +10026e2e: f000 f8e9 bl 10027004 <.text_16> +10026e32: a908 add r1, sp, #32 +10026e34: 5470 strb r0, [r6, r1] +10026e36: 1c76 adds r6, r6, #1 +10026e38: 2e08 cmp r6, #8 +10026e3a: dbf6 blt.n 10026e2a +10026e3c: 2600 movs r6, #0 +10026e3e: f506 61ad add.w r1, r6, #1384 ; 0x568 +10026e42: f000 f8df bl 10027004 <.text_16> +10026e46: a906 add r1, sp, #24 +10026e48: 5470 strb r0, [r6, r1] +10026e4a: 1c76 adds r6, r6, #1 +10026e4c: 2e08 cmp r6, #8 +10026e4e: dbf6 blt.n 10026e3e +10026e50: 2600 movs r6, #0 +10026e52: f506 61c2 add.w r1, r6, #1552 ; 0x610 +10026e56: f000 f8d5 bl 10027004 <.text_16> +10026e5a: a904 add r1, sp, #16 +10026e5c: 5470 strb r0, [r6, r1] +10026e5e: 1c76 adds r6, r6, #1 +10026e60: 2e06 cmp r6, #6 +10026e62: dbf6 blt.n 10026e52 +10026e64: 2600 movs r6, #0 +10026e66: f506 61c3 add.w r1, r6, #1560 ; 0x618 +10026e6a: f000 f8cb bl 10027004 <.text_16> +10026e6e: a902 add r1, sp, #8 +10026e70: 5470 strb r0, [r6, r1] +10026e72: 1c76 adds r6, r6, #1 +10026e74: 2e06 cmp r6, #6 +10026e76: dbf6 blt.n 10026e66 +10026e78: 2700 movs r7, #0 +10026e7a: ae0c add r6, sp, #48 ; 0x30 +10026e7c: f507 61e0 add.w r1, r7, #1792 ; 0x700 +10026e80: f000 f8c0 bl 10027004 <.text_16> +10026e84: 55b8 strb r0, [r7, r6] +10026e86: 1c7f adds r7, r7, #1 +10026e88: 2f06 cmp r7, #6 +10026e8a: dbf7 blt.n 10026e7c +10026e8c: f04f 0b00 mov.w fp, #0 +10026e90: af0a add r7, sp, #40 ; 0x28 +10026e92: f50b 61e1 add.w r1, fp, #1800 ; 0x708 +10026e96: f000 f8b5 bl 10027004 <.text_16> +10026e9a: f80b 0007 strb.w r0, [fp, r7] +10026e9e: f10b 0b01 add.w fp, fp, #1 +10026ea2: f1bb 0f06 cmp.w fp, #6 +10026ea6: dbf4 blt.n 10026e92 +10026ea8: f89d 0002 ldrb.w r0, [sp, #2] +10026eac: f000 00f7 and.w r0, r0, #247 ; 0xf7 +10026eb0: f88d 0000 strb.w r0, [sp] +10026eb4: f040 0210 orr.w r2, r0, #16 +10026eb8: f000 f8a7 bl 1002700a <.text_17> +10026ebc: f89d 0001 ldrb.w r0, [sp, #1] +10026ec0: f000 0bf7 and.w fp, r0, #247 ; 0xf7 +10026ec4: f04b 0210 orr.w r2, fp, #16 +10026ec8: 4649 mov r1, r9 +10026eca: f000 f8a0 bl 1002700e <.text_17+0x4> +10026ece: f005 00f0 and.w r0, r5, #240 ; 0xf0 +10026ed2: f005 0103 and.w r1, r5, #3 +10026ed6: ea40 0081 orr.w r0, r0, r1, lsl #2 +10026eda: f3c5 0181 ubfx r1, r5, #2, #2 +10026ede: ea41 0200 orr.w r2, r1, r0 +10026ee2: f44f 7181 mov.w r1, #258 ; 0x102 +10026ee6: f000 f892 bl 1002700e <.text_17+0x4> +10026eea: 465a mov r2, fp +10026eec: f000 f88d bl 1002700a <.text_17> +10026ef0: f89d 2004 ldrb.w r2, [sp, #4] +10026ef4: f240 515a movw r1, #1370 ; 0x55a +10026ef8: f000 f889 bl 1002700e <.text_17+0x4> +10026efc: 7862 ldrb r2, [r4, #1] +10026efe: f240 515b movw r1, #1371 ; 0x55b +10026f02: f000 f884 bl 1002700e <.text_17+0x4> +10026f06: 2500 movs r5, #0 +10026f08: a806 add r0, sp, #24 +10026f0a: f505 61ac add.w r1, r5, #1376 ; 0x560 +10026f0e: 5c2a ldrb r2, [r5, r0] +10026f10: f000 f87d bl 1002700e <.text_17+0x4> +10026f14: 1c6d adds r5, r5, #1 +10026f16: 2d08 cmp r5, #8 +10026f18: dbf6 blt.n 10026f08 +10026f1a: 2500 movs r5, #0 +10026f1c: 5daa ldrb r2, [r5, r6] +10026f1e: f505 61c2 add.w r1, r5, #1552 ; 0x610 +10026f22: f000 f874 bl 1002700e <.text_17+0x4> +10026f26: 1c6d adds r5, r5, #1 +10026f28: 2d06 cmp r5, #6 +10026f2a: dbf7 blt.n 10026f1c +10026f2c: 2500 movs r5, #0 +10026f2e: 5dea ldrb r2, [r5, r7] +10026f30: f505 61c3 add.w r1, r5, #1560 ; 0x618 +10026f34: f000 f86b bl 1002700e <.text_17+0x4> +10026f38: 1c6d adds r5, r5, #1 +10026f3a: 2d06 cmp r5, #6 +10026f3c: dbf7 blt.n 10026f2e +10026f3e: f89d 2000 ldrb.w r2, [sp] +10026f42: 4649 mov r1, r9 +10026f44: f000 f863 bl 1002700e <.text_17+0x4> +10026f48: f240 5571 movw r5, #1393 ; 0x571 +10026f4c: f89d 2006 ldrb.w r2, [sp, #6] +10026f50: 4629 mov r1, r5 +10026f52: f000 f85c bl 1002700e <.text_17+0x4> +10026f56: f89a 2001 ldrb.w r2, [sl, #1] +10026f5a: 4629 mov r1, r5 +10026f5c: f000 f857 bl 1002700e <.text_17+0x4> +10026f60: 2500 movs r5, #0 +10026f62: a808 add r0, sp, #32 +10026f64: f505 61ad add.w r1, r5, #1384 ; 0x568 +10026f68: 5c2a ldrb r2, [r5, r0] +10026f6a: f000 f850 bl 1002700e <.text_17+0x4> +10026f6e: 1c6d adds r5, r5, #1 +10026f70: 2d08 cmp r5, #8 +10026f72: dbf6 blt.n 10026f62 +10026f74: 2500 movs r5, #0 +10026f76: a804 add r0, sp, #16 +10026f78: f505 61e0 add.w r1, r5, #1792 ; 0x700 +10026f7c: 5c2a ldrb r2, [r5, r0] +10026f7e: f000 f846 bl 1002700e <.text_17+0x4> +10026f82: 1c6d adds r5, r5, #1 +10026f84: 2d06 cmp r5, #6 +10026f86: dbf6 blt.n 10026f76 +10026f88: 2500 movs r5, #0 +10026f8a: a802 add r0, sp, #8 +10026f8c: f505 61e1 add.w r1, r5, #1800 ; 0x708 +10026f90: 5c2a ldrb r2, [r5, r0] +10026f92: f000 f83c bl 1002700e <.text_17+0x4> +10026f96: 1c6d adds r5, r5, #1 +10026f98: 2d06 cmp r5, #6 +10026f9a: dbf6 blt.n 10026f8a +10026f9c: f89d 2001 ldrb.w r2, [sp, #1] +10026fa0: f000 f833 bl 1002700a <.text_17> +10026fa4: f89d 2002 ldrb.w r2, [sp, #2] +10026fa8: 4649 mov r1, r9 +10026faa: f000 f830 bl 1002700e <.text_17+0x4> +10026fae: f641 5152 movw r1, #7506 ; 0x1d52 +10026fb2: f641 5524 movw r5, #7460 ; 0x1d24 +10026fb6: f811 2008 ldrb.w r2, [r1, r8] +10026fba: f20f 26ac addw r6, pc, #684 ; 0x2ac +10026fbe: eb05 0408 add.w r4, r5, r8 +10026fc2: a03a add r0, pc, #232 ; (adr r0, 100270ac <.text_23>) +10026fc4: b962 cbnz r2, 10026fe0 +10026fc6: 2201 movs r2, #1 +10026fc8: f801 2008 strb.w r2, [r1, r8] +10026fcc: 2200 movs r2, #0 +10026fce: 6a63 ldr r3, [r4, #36] ; 0x24 +10026fd0: 54ca strb r2, [r1, r3] +10026fd2: f7e5 f996 bl 1000c302 +10026fd6: 6a60 ldr r0, [r4, #36] ; 0x24 +10026fd8: f855 2008 ldr.w r2, [r5, r8] +10026fdc: 5829 ldr r1, [r5, r0] +10026fde: e00b b.n 10026ff8 +10026fe0: 2200 movs r2, #0 +10026fe2: f801 2008 strb.w r2, [r1, r8] +10026fe6: 2201 movs r2, #1 +10026fe8: 6a63 ldr r3, [r4, #36] ; 0x24 +10026fea: 54ca strb r2, [r1, r3] +10026fec: f7e5 f989 bl 1000c302 +10026ff0: 6a60 ldr r0, [r4, #36] ; 0x24 +10026ff2: f855 1008 ldr.w r1, [r5, r8] +10026ff6: 582a ldr r2, [r5, r0] +10026ff8: 4630 mov r0, r6 +10026ffa: f7e5 f982 bl 1000c302 +10026ffe: b00f add sp, #60 ; 0x3c +10027000: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +10027004 <.text_16>: +10027004: 4640 mov r0, r8 +10027006: f7fd be11 b.w 10024c2c + +1002700a <.text_17>: +1002700a: f44f 61aa mov.w r1, #1360 ; 0x550 +1002700e: 4640 mov r0, r8 +10027010: f7fd be1e b.w 10024c50 + +10027014 : +10027014: 2948 cmp r1, #72 ; 0x48 +10027016: bf08 it eq +10027018: f7ff beda beq.w 10026dd0 +1002701c: 4770 bx lr + +1002701e : +1002701e: 4770 bx lr + +10027020 : +10027020: b510 push {r4, lr} +10027022: b142 cbz r2, 10027036 +10027024: 1e52 subs r2, r2, #1 +10027026: 5c13 ldrb r3, [r2, r0] +10027028: 5c54 ldrb r4, [r2, r1] +1002702a: 42a3 cmp r3, r4 +1002702c: d103 bne.n 10027036 +1002702e: 2a00 cmp r2, #0 +10027030: d1f8 bne.n 10027024 +10027032: 2001 movs r0, #1 +10027034: bd10 pop {r4, pc} +10027036: 2000 movs r0, #0 +10027038: bd10 pop {r4, pc} + +1002703a : +1002703a: b510 push {r4, lr} +1002703c: 2200 movs r2, #0 +1002703e: 700a strb r2, [r1, #0] +10027040: e009 b.n 10027056 +10027042: 780b ldrb r3, [r1, #0] +10027044: 240a movs r4, #10 +10027046: 4363 muls r3, r4 +10027048: 700b strb r3, [r1, #0] +1002704a: 5614 ldrsb r4, [r2, r0] +1002704c: 3c30 subs r4, #48 ; 0x30 +1002704e: 18e3 adds r3, r4, r3 +10027050: 1c52 adds r2, r2, #1 +10027052: 700b strb r3, [r1, #0] +10027054: b292 uxth r2, r2 +10027056: 5613 ldrsb r3, [r2, r0] +10027058: b123 cbz r3, 10027064 +1002705a: 3b30 subs r3, #48 ; 0x30 +1002705c: 2b0a cmp r3, #10 +1002705e: d3f0 bcc.n 10027042 +10027060: 2000 movs r0, #0 +10027062: bd10 pop {r4, pc} +10027064: 2001 movs r0, #1 +10027066: bd10 pop {r4, pc} + +10027068 : +10027068: b538 push {r3, r4, r5, lr} +1002706a: 4604 mov r4, r0 +1002706c: f641 30a1 movw r0, #7073 ; 0x1ba1 +10027070: 5d01 ldrb r1, [r0, r4] +10027072: 2901 cmp r1, #1 +10027074: d118 bne.n 100270a8 +10027076: 1905 adds r5, r0, r4 +10027078: 7868 ldrb r0, [r5, #1] +1002707a: 28ff cmp r0, #255 ; 0xff +1002707c: d014 beq.n 100270a8 +1002707e: f04f 33ff mov.w r3, #4294967295 +10027082: 2255 movs r2, #85 ; 0x55 +10027084: 2100 movs r1, #0 +10027086: 4620 mov r0, r4 +10027088: f7f0 fa28 bl 100174dc +1002708c: 7869 ldrb r1, [r5, #1] +1002708e: f420 20f0 bic.w r0, r0, #491520 ; 0x78000 +10027092: f001 010f and.w r1, r1, #15 +10027096: ea40 30c1 orr.w r0, r0, r1, lsl #15 +1002709a: 9000 str r0, [sp, #0] +1002709c: 2255 movs r2, #85 ; 0x55 +1002709e: 4b04 ldr r3, [pc, #16] ; (100270b0 <.text_24>) +100270a0: 2100 movs r1, #0 +100270a2: 4620 mov r0, r4 +100270a4: f7f0 fa25 bl 100174f2 +100270a8: bd31 pop {r0, r4, r5, pc} + ... + +100270ac <.text_23>: +100270ac: 00000d0a .word 0x00000d0a + +100270b0 <.text_24>: +100270b0: 000fffff .word 0x000fffff + +100270b4 : +100270b4: 70696843 72655620 6e6f6973 666e4920 Chip Version Inf +100270c4: 25203a6f 00005f73 o: %s_.. + +100270cc : +100270cc: 50494843 3931385f 00004332 CHIP_8192C.. + +100270d8 : +100270d8: 50494843 3831385f 00004338 CHIP_8188C.. + +100270e4 : +100270e4: 70696843 72655620 6e6f6973 666e4920 Chip Version Inf +100270f4: 43203a6f 5f504948 32393138 00005f44 o: CHIP_8192D_.. + +10027104 : +10027104: 70696843 72655620 6e6f6973 666e4920 Chip Version Inf +10027114: 43203a6f 5f504948 33323738 00005f41 o: CHIP_8723A_.. + +10027124 : +10027124: 70696843 72655620 6e6f6973 666e4920 Chip Version Inf +10027134: 43203a6f 5f504948 38383138 00005f45 o: CHIP_8188E_.. + +10027144 : +10027144: 70696843 72655620 6e6f6973 666e4920 Chip Version Inf +10027154: 43203a6f 5f504948 32313838 0000005f o: CHIP_8812_... + +10027164 : +10027164: 70696843 72655620 6e6f6973 666e4920 Chip Version Inf +10027174: 43203a6f 5f504948 32393138 00005f45 o: CHIP_8192E_.. + +10027184 : +10027184: 70696843 72655620 6e6f6973 666e4920 Chip Version Inf +10027194: 43203a6f 5f504948 31323838 0000005f o: CHIP_8821_... + +100271a4 : +100271a4: 70696843 72655620 6e6f6973 666e4920 Chip Version Inf +100271b4: 43203a6f 5f504948 33323738 00005f42 o: CHIP_8723B_.. + +100271c4 : +100271c4: 6d726f4e 435f6c61 00706968 Normal_Chip. + +100271d0 : +100271d0: 74736554 6968435f 00000070 Test_Chip... + +100271dc : +100271dc: 434d5354 00000000 TSMC.... + +100271e4 : +100271e4: 43494d53 00000000 SMIC.... + +100271ec : +100271ec: 55435f41 00005f54 A_CUT_.. + +100271f4 : +100271f4: 55435f42 00005f54 B_CUT_.. + +100271fc : +100271fc: 55435f43 00005f54 C_CUT_.. + +10027204 : +10027204: 55435f44 00005f54 D_CUT_.. + +1002720c : +1002720c: 55435f45 00005f54 E_CUT_.. + +10027214 : +10027214: 55435f49 00005f54 I_CUT_.. + +1002721c : +1002721c: 4e4b4e55 5f4e574f 28545543 5f296425 UNKNOWN_CUT(%d)_ +1002722c: 00000000 .... + +10027230 : +10027230: 52315431 0000005f 1T1R_... + +10027238 : +10027238: 52325431 0000005f 1T2R_... + +10027240 : +10027240: 52325432 0000005f 2T2R_... + +10027248 : +10027248: 4e4b4e55 5f4e574f 59544652 25284550 UNKNOWN_RFTYPE(% +10027258: 005f2964 d)_. + +1002725c : +1002725c: 566d6f52 25287265 000a2964 RomVer(%d).. + +10027268 : +10027268: 384c5452 41353931 6972445b 5d726576 RTL8195A[Driver] +10027278: 6f70203a 73207472 63746977 202d2068 : port switch - +10027288: 74726f70 73252830 70202c29 3174726f port0(%s), port1 +10027298: 29732528 0000000a (%s).... + +100272a0 : +100272a0: f8df f000 ldr.w pc, [pc] ; 100272a4 +100272a4: 00006561 .word 0x00006561 + +100272a8 : +100272a8: 6840 ldr r0, [r0, #4] +100272aa: 4208 tst r0, r1 +100272ac: d001 beq.n 100272b2 +100272ae: 2001 movs r0, #1 +100272b0: 4770 bx lr +100272b2: 2000 movs r0, #0 +100272b4: 4770 bx lr + +100272b6 : +100272b6: 2001 movs r0, #1 +100272b8: 4770 bx lr + +100272ba : +100272ba: 4770 bx lr + +100272bc : +100272bc: b538 push {r3, r4, r5, lr} +100272be: 4604 mov r4, r0 +100272c0: f641 35a4 movw r5, #7076 ; 0x1ba4 +100272c4: 5928 ldr r0, [r5, r4] +100272c6: b128 cbz r0, 100272d4 +100272c8: f44f 5127 mov.w r1, #10688 ; 0x29c0 +100272cc: f7e9 fa9e bl 1001080c +100272d0: 2000 movs r0, #0 +100272d2: 5128 str r0, [r5, r4] +100272d4: bd31 pop {r0, r4, r5, pc} + +100272d6 : +100272d6: b510 push {r4, lr} +100272d8: b10a cbz r2, 100272de +100272da: 2001 movs r0, #1 +100272dc: bd10 pop {r4, pc} +100272de: f8df 2cd8 ldr.w r2, [pc, #3288] ; 10027fb8 <.text_49> +100272e2: 6813 ldr r3, [r2, #0] +100272e4: 2001 movs r0, #1 +100272e6: f423 7440 bic.w r4, r3, #768 ; 0x300 +100272ea: b179 cbz r1, 1002730c +100272ec: 2902 cmp r1, #2 +100272ee: d006 beq.n 100272fe +100272f0: d302 bcc.n 100272f8 +100272f2: 2903 cmp r1, #3 +100272f4: d006 beq.n 10027304 +100272f6: e008 b.n 1002730a +100272f8: f444 7480 orr.w r4, r4, #256 ; 0x100 +100272fc: e006 b.n 1002730c +100272fe: f444 7400 orr.w r4, r4, #512 ; 0x200 +10027302: e003 b.n 1002730c +10027304: f443 7440 orr.w r4, r3, #768 ; 0x300 +10027308: e000 b.n 1002730c +1002730a: 2000 movs r0, #0 +1002730c: 6014 str r4, [r2, #0] +1002730e: bd10 pop {r4, pc} + +10027310 : +10027310: b510 push {r4, lr} +10027312: 2a06 cmp r2, #6 +10027314: f44f 7000 mov.w r0, #512 ; 0x200 +10027318: f44f 7480 mov.w r4, #256 ; 0x100 +1002731c: d828 bhi.n 10027370 +1002731e: e8df f002 tbb [pc, r2] +10027322: 0904 .short 0x0904 +10027324: 1d19130d .word 0x1d19130d +10027328: 0022 .short 0x0022 +1002732a: 2900 cmp r1, #0 +1002732c: bf14 ite ne +1002732e: 2080 movne r0, #128 ; 0x80 +10027330: 2040 moveq r0, #64 ; 0x40 +10027332: e01e b.n 10027372 +10027334: b1c1 cbz r1, 10027368 +10027336: f44f 60c0 mov.w r0, #1536 ; 0x600 +1002733a: e017 b.n 1002736c +1002733c: 2900 cmp r1, #0 +1002733e: bf14 ite ne +10027340: f44f 70f8 movne.w r0, #496 ; 0x1f0 +10027344: 20f1 moveq r0, #241 ; 0xf1 +10027346: e011 b.n 1002736c +10027348: 2900 cmp r1, #0 +1002734a: bf14 ite ne +1002734c: f44f 60ba movne.w r0, #1488 ; 0x5d0 +10027350: 20f1 moveq r0, #241 ; 0xf1 +10027352: e00b b.n 1002736c +10027354: b151 cbz r1, 1002736c +10027356: f44f 6080 mov.w r0, #1024 ; 0x400 +1002735a: e007 b.n 1002736c +1002735c: 2900 cmp r1, #0 +1002735e: bf14 ite ne +10027360: 2010 movne r0, #16 +10027362: 200f moveq r0, #15 +10027364: e005 b.n 10027372 +10027366: b909 cbnz r1, 1002736c +10027368: 801c strh r4, [r3, #0] +1002736a: bd10 pop {r4, pc} +1002736c: 8018 strh r0, [r3, #0] +1002736e: bd10 pop {r4, pc} +10027370: 2000 movs r0, #0 +10027372: 7018 strb r0, [r3, #0] +10027374: bd10 pop {r4, pc} + +10027376 : +10027376: 4608 mov r0, r1 +10027378: 4611 mov r1, r2 +1002737a: 2207 movs r2, #7 +1002737c: f7ff bf90 b.w 100272a0 + +10027380 : +10027380: e92d 4ffa stmdb sp!, {r1, r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +10027384: b083 sub sp, #12 +10027386: 4681 mov r9, r0 +10027388: f8bd 000c ldrh.w r0, [sp, #12] +1002738c: 4693 mov fp, r2 +1002738e: 2600 movs r6, #0 +10027390: 4458 add r0, fp +10027392: f5b0 7f00 cmp.w r0, #512 ; 0x200 +10027396: f88d 6007 strb.w r6, [sp, #7] +1002739a: f300 8096 bgt.w 100274ca +1002739e: f44f 7000 mov.w r0, #512 ; 0x200 +100273a2: f7e9 fa29 bl 100107f8 +100273a6: ea5f 0a00 movs.w sl, r0 +100273aa: f000 808e beq.w 100274ca +100273ae: f44f 7200 mov.w r2, #512 ; 0x200 +100273b2: 21ff movs r1, #255 ; 0xff +100273b4: f7e9 fa40 bl 10010838 +100273b8: 9c0e ldr r4, [sp, #56] ; 0x38 +100273ba: 4622 mov r2, r4 +100273bc: 2100 movs r1, #0 +100273be: 4648 mov r0, r9 +100273c0: f7ff ff89 bl 100272d6 +100273c4: 4623 mov r3, r4 +100273c6: aa01 add r2, sp, #4 +100273c8: 4631 mov r1, r6 +100273ca: 4648 mov r0, r9 +100273cc: f7fd ffc1 bl 10025352 +100273d0: f89d 0004 ldrb.w r0, [sp, #4] +100273d4: 1c76 adds r6, r6, #1 +100273d6: 28ff cmp r0, #255 ; 0xff +100273d8: d044 beq.n 10027464 +100273da: f000 fa0d bl 100277f8 <.text_21> +100273de: d117 bne.n 10027410 +100273e0: 0945 lsrs r5, r0, #5 +100273e2: 4623 mov r3, r4 +100273e4: f10d 0206 add.w r2, sp, #6 +100273e8: b2b1 uxth r1, r6 +100273ea: 4648 mov r0, r9 +100273ec: f7fd ff69 bl 100252c2 +100273f0: f89d 0006 ldrb.w r0, [sp, #6] +100273f4: 1c76 adds r6, r6, #1 +100273f6: f000 000f and.w r0, r0, #15 +100273fa: 280f cmp r0, #15 +100273fc: d02f beq.n 1002745e +100273fe: f89d 0006 ldrb.w r0, [sp, #6] +10027402: 0840 lsrs r0, r0, #1 +10027404: f000 0078 and.w r0, r0, #120 ; 0x78 +10027408: 4305 orrs r5, r0 +1002740a: f89d 0006 ldrb.w r0, [sp, #6] +1002740e: e000 b.n 10027412 +10027410: 0905 lsrs r5, r0, #4 +10027412: 2d40 cmp r5, #64 ; 0x40 +10027414: f000 080f and.w r8, r0, #15 +10027418: da1b bge.n 10027452 +1002741a: 00ed lsls r5, r5, #3 +1002741c: 2700 movs r7, #0 +1002741e: 2101 movs r1, #1 +10027420: 40b9 lsls r1, r7 +10027422: ea18 0f01 tst.w r8, r1 +10027426: d10e bne.n 10027446 +10027428: f000 f852 bl 100274d0 <.text_12> +1002742c: f89d 0005 ldrb.w r0, [sp, #5] +10027430: f805 000a strb.w r0, [r5, sl] +10027434: 1c76 adds r6, r6, #1 +10027436: f000 f84b bl 100274d0 <.text_12> +1002743a: f89d 0005 ldrb.w r0, [sp, #5] +1002743e: eb05 010a add.w r1, r5, sl +10027442: 1c76 adds r6, r6, #1 +10027444: 7048 strb r0, [r1, #1] +10027446: 1ca8 adds r0, r5, #2 +10027448: 1c7f adds r7, r7, #1 +1002744a: 2f04 cmp r7, #4 +1002744c: b285 uxth r5, r0 +1002744e: dbe6 blt.n 1002741e +10027450: e005 b.n 1002745e +10027452: b2b6 uxth r6, r6 +10027454: 4640 mov r0, r8 +10027456: f7fd ff25 bl 100252a4 +1002745a: eb06 0640 add.w r6, r6, r0, lsl #1 +1002745e: b2b6 uxth r6, r6 +10027460: 2eff cmp r6, #255 ; 0xff +10027462: ddaf ble.n 100273c4 +10027464: 2000 movs r0, #0 +10027466: e007 b.n 10027478 +10027468: f8bd 100c ldrh.w r1, [sp, #12] +1002746c: 9a04 ldr r2, [sp, #16] +1002746e: 1841 adds r1, r0, r1 +10027470: f811 100a ldrb.w r1, [r1, sl] +10027474: 5481 strb r1, [r0, r2] +10027476: 1c40 adds r0, r0, #1 +10027478: b280 uxth r0, r0 +1002747a: 4558 cmp r0, fp +1002747c: d3f4 bcc.n 10027468 +1002747e: 9400 str r4, [sp, #0] +10027480: f10d 030a add.w r3, sp, #10 +10027484: 2203 movs r2, #3 +10027486: 2100 movs r1, #0 +10027488: 4648 mov r0, r9 +1002748a: f7fd ff59 bl 10025340 +1002748e: 1e70 subs r0, r6, #1 +10027490: f8ad 0008 strh.w r0, [sp, #8] +10027494: 2164 movs r1, #100 ; 0x64 +10027496: f8bd 0008 ldrh.w r0, [sp, #8] +1002749a: 4348 muls r0, r1 +1002749c: f8bd 100a ldrh.w r1, [sp, #10] +100274a0: fb90 f0f1 sdiv r0, r0, r1 +100274a4: f88d 0007 strb.w r0, [sp, #7] +100274a8: b954 cbnz r4, 100274c0 +100274aa: aa02 add r2, sp, #8 +100274ac: 213b movs r1, #59 ; 0x3b +100274ae: 4648 mov r0, r9 +100274b0: f7ef ff2e bl 10017310 +100274b4: f10d 0207 add.w r2, sp, #7 +100274b8: 213a movs r1, #58 ; 0x3a +100274ba: 4648 mov r0, r9 +100274bc: f7ef ff28 bl 10017310 +100274c0: f44f 7100 mov.w r1, #512 ; 0x200 +100274c4: 4650 mov r0, sl +100274c6: f7e9 f9a1 bl 1001080c +100274ca: b005 add sp, #20 +100274cc: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +100274d0 <.text_12>: +100274d0: 4623 mov r3, r4 +100274d2: f10d 0205 add.w r2, sp, #5 +100274d6: b2b1 uxth r1, r6 +100274d8: 4648 mov r0, r9 +100274da: f7fd bef2 b.w 100252c2 + +100274de : +100274de: b510 push {r4, lr} +100274e0: 4614 mov r4, r2 +100274e2: b082 sub sp, #8 +100274e4: 461a mov r2, r3 +100274e6: b929 cbnz r1, 100274f4 +100274e8: 9905 ldr r1, [sp, #20] +100274ea: 9b04 ldr r3, [sp, #16] +100274ec: 9100 str r1, [sp, #0] +100274ee: 4621 mov r1, r4 +100274f0: f7ff ff46 bl 10027380 +100274f4: bd13 pop {r0, r1, r4, pc} + +100274f6 : +100274f6: b5f0 push {r4, r5, r6, r7, lr} +100274f8: b083 sub sp, #12 +100274fa: 4604 mov r4, r0 +100274fc: 2000 movs r0, #0 +100274fe: 460d mov r5, r1 +10027500: f8ad 0004 strh.w r0, [sp, #4] +10027504: 2600 movs r6, #0 +10027506: b925 cbnz r5, 10027512 +10027508: aa01 add r2, sp, #4 +1002750a: 213b movs r1, #59 ; 0x3b +1002750c: 4620 mov r0, r4 +1002750e: f7ef ff09 bl 10017324 +10027512: f8bd 7004 ldrh.w r7, [sp, #4] +10027516: 462a mov r2, r5 +10027518: 2100 movs r1, #0 +1002751a: 4620 mov r0, r4 +1002751c: f7ff fedb bl 100272d6 +10027520: e025 b.n 1002756e +10027522: b11f cbz r7, 1002752c +10027524: f8bd 1004 ldrh.w r1, [sp, #4] +10027528: 42b9 cmp r1, r7 +1002752a: d025 beq.n 10027578 +1002752c: f000 001f and.w r0, r0, #31 +10027530: 280f cmp r0, #15 +10027532: d10f bne.n 10027554 +10027534: f8bd 0004 ldrh.w r0, [sp, #4] +10027538: 1c40 adds r0, r0, #1 +1002753a: f8ad 0004 strh.w r0, [sp, #4] +1002753e: 462b mov r3, r5 +10027540: f8bd 1004 ldrh.w r1, [sp, #4] +10027544: f000 f83f bl 100275c6 <.text_15> +10027548: f89d 0006 ldrb.w r0, [sp, #6] +1002754c: f000 000f and.w r0, r0, #15 +10027550: 280f cmp r0, #15 +10027552: d00c beq.n 1002756e +10027554: f89d 0006 ldrb.w r0, [sp, #6] +10027558: f000 000f and.w r0, r0, #15 +1002755c: f7fd fea2 bl 100252a4 +10027560: f8bd 1004 ldrh.w r1, [sp, #4] +10027564: 0040 lsls r0, r0, #1 +10027566: 1c40 adds r0, r0, #1 +10027568: 1840 adds r0, r0, r1 +1002756a: f8ad 0004 strh.w r0, [sp, #4] +1002756e: f8bd 0004 ldrh.w r0, [sp, #4] +10027572: 28ff cmp r0, #255 ; 0xff +10027574: dc16 bgt.n 100275a4 +10027576: e00b b.n 10027590 +10027578: 1c76 adds r6, r6, #1 +1002757a: 20ff movs r0, #255 ; 0xff +1002757c: 2e04 cmp r6, #4 +1002757e: f88d 0006 strb.w r0, [sp, #6] +10027582: d216 bcs.n 100275b2 +10027584: 2e03 cmp r6, #3 +10027586: d3f2 bcc.n 1002756e +10027588: 2000 movs r0, #0 +1002758a: f8ad 0004 strh.w r0, [sp, #4] +1002758e: 2700 movs r7, #0 +10027590: f8bd 1004 ldrh.w r1, [sp, #4] +10027594: 462b mov r3, r5 +10027596: f000 f816 bl 100275c6 <.text_15> +1002759a: b150 cbz r0, 100275b2 +1002759c: f89d 0006 ldrb.w r0, [sp, #6] +100275a0: 28ff cmp r0, #255 ; 0xff +100275a2: d1be bne.n 10027522 +100275a4: b965 cbnz r5, 100275c0 +100275a6: aa01 add r2, sp, #4 +100275a8: 213b movs r1, #59 ; 0x3b +100275aa: 4620 mov r0, r4 +100275ac: f7ef feb0 bl 10017310 +100275b0: e006 b.n 100275c0 +100275b2: 9500 str r5, [sp, #0] +100275b4: ab01 add r3, sp, #4 +100275b6: 2203 movs r2, #3 +100275b8: 2100 movs r1, #0 +100275ba: 4620 mov r0, r4 +100275bc: f7fd fec0 bl 10025340 +100275c0: f8bd 0004 ldrh.w r0, [sp, #4] +100275c4: bdfe pop {r1, r2, r3, r4, r5, r6, r7, pc} + +100275c6 <.text_15>: +100275c6: f10d 0206 add.w r2, sp, #6 +100275ca: 4620 mov r0, r4 +100275cc: f7fd bec1 b.w 10025352 + +100275d0 : +100275d0: 4603 mov r3, r0 +100275d2: 2000 movs r0, #0 +100275d4: b911 cbnz r1, 100275dc +100275d6: 4611 mov r1, r2 +100275d8: 4618 mov r0, r3 +100275da: e78c b.n 100274f6 +100275dc: 4770 bx lr + +100275de : +100275de: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +100275e2: b083 sub sp, #12 +100275e4: 4682 mov sl, r0 +100275e6: 4617 mov r7, r2 +100275e8: 460d mov r5, r1 +100275ea: 461c mov r4, r3 +100275ec: f04f 090f mov.w r9, #15 +100275f0: 2208 movs r2, #8 +100275f2: 21ff movs r1, #255 ; 0xff +100275f4: a800 add r0, sp, #0 +100275f6: f7e9 f91f bl 10010838 +100275fa: f8dd 8030 ldr.w r8, [sp, #48] ; 0x30 +100275fe: 07f8 lsls r0, r7, #31 +10027600: ae00 add r6, sp, #0 +10027602: d420 bmi.n 10027646 +10027604: 7822 ldrb r2, [r4, #0] +10027606: 46ab mov fp, r5 +10027608: 4643 mov r3, r8 +1002760a: 4629 mov r1, r5 +1002760c: f000 f881 bl 10027712 <.text_18+0x6> +10027610: 1c6d adds r5, r5, #1 +10027612: 7862 ldrb r2, [r4, #1] +10027614: f000 f87b bl 1002770e <.text_18+0x2> +10027618: 1c6d adds r5, r5, #1 +1002761a: 4643 mov r3, r8 +1002761c: aa00 add r2, sp, #0 +1002761e: 4659 mov r1, fp +10027620: f000 f87b bl 1002771a <.text_19+0x2> +10027624: f10b 0101 add.w r1, fp, #1 +10027628: 4643 mov r3, r8 +1002762a: f10d 0201 add.w r2, sp, #1 +1002762e: f000 f873 bl 10027718 <.text_19> +10027632: 7820 ldrb r0, [r4, #0] +10027634: f89d 1000 ldrb.w r1, [sp] +10027638: 4288 cmp r0, r1 +1002763a: bf03 ittte eq +1002763c: 7860 ldrbeq r0, [r4, #1] +1002763e: 7871 ldrbeq r1, [r6, #1] +10027640: 4288 cmpeq r0, r1 +10027642: f04f 090e movne.w r9, #14 +10027646: 07b8 lsls r0, r7, #30 +10027648: d41e bmi.n 10027688 +1002764a: 78a2 ldrb r2, [r4, #2] +1002764c: f000 f85e bl 1002770c <.text_18> +10027650: 1c6d adds r5, r5, #1 +10027652: 78e2 ldrb r2, [r4, #3] +10027654: f000 f85b bl 1002770e <.text_18+0x2> +10027658: 1c6d adds r5, r5, #1 +1002765a: 4643 mov r3, r8 +1002765c: f10d 0202 add.w r2, sp, #2 +10027660: fa1f f18b uxth.w r1, fp +10027664: f000 f859 bl 1002771a <.text_19+0x2> +10027668: f10b 0101 add.w r1, fp, #1 +1002766c: 4643 mov r3, r8 +1002766e: f10d 0203 add.w r2, sp, #3 +10027672: f000 f851 bl 10027718 <.text_19> +10027676: 78a0 ldrb r0, [r4, #2] +10027678: 78b1 ldrb r1, [r6, #2] +1002767a: 4288 cmp r0, r1 +1002767c: bf03 ittte eq +1002767e: 78e0 ldrbeq r0, [r4, #3] +10027680: 78f1 ldrbeq r1, [r6, #3] +10027682: 4288 cmpeq r0, r1 +10027684: f029 0902 bicne.w r9, r9, #2 +10027688: 0778 lsls r0, r7, #29 +1002768a: d41d bmi.n 100276c8 +1002768c: 7922 ldrb r2, [r4, #4] +1002768e: f000 f83d bl 1002770c <.text_18> +10027692: 1c6d adds r5, r5, #1 +10027694: 7962 ldrb r2, [r4, #5] +10027696: f000 f83a bl 1002770e <.text_18+0x2> +1002769a: 1c6d adds r5, r5, #1 +1002769c: 4643 mov r3, r8 +1002769e: aa01 add r2, sp, #4 +100276a0: fa1f f18b uxth.w r1, fp +100276a4: f000 f839 bl 1002771a <.text_19+0x2> +100276a8: f10b 0101 add.w r1, fp, #1 +100276ac: 4643 mov r3, r8 +100276ae: f10d 0205 add.w r2, sp, #5 +100276b2: f000 f831 bl 10027718 <.text_19> +100276b6: 7920 ldrb r0, [r4, #4] +100276b8: 7931 ldrb r1, [r6, #4] +100276ba: 4288 cmp r0, r1 +100276bc: bf03 ittte eq +100276be: 7960 ldrbeq r0, [r4, #5] +100276c0: 7971 ldrbeq r1, [r6, #5] +100276c2: 4288 cmpeq r0, r1 +100276c4: f029 0904 bicne.w r9, r9, #4 +100276c8: 0738 lsls r0, r7, #28 +100276ca: d41c bmi.n 10027706 +100276cc: 79a2 ldrb r2, [r4, #6] +100276ce: 462f mov r7, r5 +100276d0: f000 f81d bl 1002770e <.text_18+0x2> +100276d4: 1c6d adds r5, r5, #1 +100276d6: 79e2 ldrb r2, [r4, #7] +100276d8: f000 f819 bl 1002770e <.text_18+0x2> +100276dc: 4643 mov r3, r8 +100276de: f10d 0206 add.w r2, sp, #6 +100276e2: b2b9 uxth r1, r7 +100276e4: f000 f819 bl 1002771a <.text_19+0x2> +100276e8: 4643 mov r3, r8 +100276ea: f10d 0207 add.w r2, sp, #7 +100276ee: b2a9 uxth r1, r5 +100276f0: f000 f813 bl 1002771a <.text_19+0x2> +100276f4: 79a0 ldrb r0, [r4, #6] +100276f6: 79b1 ldrb r1, [r6, #6] +100276f8: 4288 cmp r0, r1 +100276fa: bf03 ittte eq +100276fc: 79e0 ldrbeq r0, [r4, #7] +100276fe: 79f1 ldrbeq r1, [r6, #7] +10027700: 4288 cmpeq r0, r1 +10027702: f029 0908 bicne.w r9, r9, #8 +10027706: 4648 mov r0, r9 +10027708: e8bd 8ffe ldmia.w sp!, {r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1002770c <.text_18>: +1002770c: 46ab mov fp, r5 +1002770e: 4643 mov r3, r8 +10027710: b2a9 uxth r1, r5 +10027712: 4650 mov r0, sl +10027714: f7fd be7d b.w 10025412 + +10027718 <.text_19>: +10027718: b289 uxth r1, r1 +1002771a: 4650 mov r0, sl +1002771c: f7fd be19 b.w 10025352 + +10027720 : +10027720: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +10027724: b083 sub sp, #12 +10027726: 2700 movs r7, #0 +10027728: 4680 mov r8, r0 +1002772a: 468b mov fp, r1 +1002772c: 4615 mov r5, r2 +1002772e: 469a mov sl, r3 +10027730: f88d 7005 strb.w r7, [sp, #5] +10027734: b15d cbz r5, 1002774e +10027736: f8cd a000 str.w sl, [sp] +1002773a: f10d 0305 add.w r3, sp, #5 +1002773e: 2200 movs r2, #0 +10027740: 4639 mov r1, r7 +10027742: f7fd fdfd bl 10025340 +10027746: f89d 0005 ldrb.w r0, [sp, #5] +1002774a: 4558 cmp r0, fp +1002774c: d201 bcs.n 10027752 +1002774e: 2000 movs r0, #0 +10027750: e050 b.n 100277f4 +10027752: 2208 movs r2, #8 +10027754: 21ff movs r1, #255 ; 0xff +10027756: f001 f8b6 bl 100288c6 <.text_106+0x4> +1002775a: 2401 movs r4, #1 +1002775c: 4653 mov r3, sl +1002775e: aa01 add r2, sp, #4 +10027760: 4639 mov r1, r7 +10027762: 4640 mov r0, r8 +10027764: f7fd fdf5 bl 10025352 +10027768: 1c7f adds r7, r7, #1 +1002776a: b908 cbnz r0, 10027770 +1002776c: 2400 movs r4, #0 +1002776e: e040 b.n 100277f2 +10027770: f89d 0004 ldrb.w r0, [sp, #4] +10027774: 28ff cmp r0, #255 ; 0xff +10027776: d03c beq.n 100277f2 +10027778: f000 f83e bl 100277f8 <.text_21> +1002777c: d112 bne.n 100277a4 +1002777e: 0946 lsrs r6, r0, #5 +10027780: f000 f840 bl 10027804 <.text_22> +10027784: f89d 0004 ldrb.w r0, [sp, #4] +10027788: 1c7f adds r7, r7, #1 +1002778a: f000 000f and.w r0, r0, #15 +1002778e: 280f cmp r0, #15 +10027790: d02c beq.n 100277ec +10027792: f89d 0004 ldrb.w r0, [sp, #4] +10027796: 0840 lsrs r0, r0, #1 +10027798: f000 0078 and.w r0, r0, #120 ; 0x78 +1002779c: 4306 orrs r6, r0 +1002779e: f89d 0004 ldrb.w r0, [sp, #4] +100277a2: e000 b.n 100277a6 +100277a4: 0906 lsrs r6, r0, #4 +100277a6: 455e cmp r6, fp +100277a8: f000 090f and.w r9, r0, #15 +100277ac: d118 bne.n 100277e0 +100277ae: 2600 movs r6, #0 +100277b0: fa04 f106 lsl.w r1, r4, r6 +100277b4: ea19 0f01 tst.w r9, r1 +100277b8: d10e bne.n 100277d8 +100277ba: f000 f823 bl 10027804 <.text_22> +100277be: f89d 0004 ldrb.w r0, [sp, #4] +100277c2: f805 0016 strb.w r0, [r5, r6, lsl #1] +100277c6: 1c7f adds r7, r7, #1 +100277c8: f000 f81c bl 10027804 <.text_22> +100277cc: f89d 0004 ldrb.w r0, [sp, #4] +100277d0: eb05 0146 add.w r1, r5, r6, lsl #1 +100277d4: 1c7f adds r7, r7, #1 +100277d6: 7048 strb r0, [r1, #1] +100277d8: 1c76 adds r6, r6, #1 +100277da: 2e04 cmp r6, #4 +100277dc: dbe8 blt.n 100277b0 +100277de: e005 b.n 100277ec +100277e0: b2bf uxth r7, r7 +100277e2: 4648 mov r0, r9 +100277e4: f7fd fd5e bl 100252a4 +100277e8: eb07 0740 add.w r7, r7, r0, lsl #1 +100277ec: b2bf uxth r7, r7 +100277ee: 2fff cmp r7, #255 ; 0xff +100277f0: ddb4 ble.n 1002775c +100277f2: 4620 mov r0, r4 +100277f4: e8bd 8ffe ldmia.w sp!, {r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +100277f8 <.text_21>: +100277f8: f000 001f and.w r0, r0, #31 +100277fc: 280f cmp r0, #15 +100277fe: f89d 0004 ldrb.w r0, [sp, #4] +10027802: 4770 bx lr + +10027804 <.text_22>: +10027804: 4653 mov r3, sl +10027806: aa01 add r2, sp, #4 +10027808: b2b9 uxth r1, r7 +1002780a: 4640 mov r0, r8 +1002780c: f7fd bda1 b.w 10025352 + +10027810 : +10027810: e92d 47fc stmdb sp!, {r2, r3, r4, r5, r6, r7, r8, r9, sl, lr} +10027814: 4680 mov r8, r0 +10027816: 2000 movs r0, #0 +10027818: f8ad 0006 strh.w r0, [sp, #6] +1002781c: f88d 0004 strb.w r0, [sp, #4] +10027820: 4616 mov r6, r2 +10027822: 9c0a ldr r4, [sp, #40] ; 0x28 +10027824: 461f mov r7, r3 +10027826: 4682 mov sl, r0 +10027828: 9400 str r4, [sp, #0] +1002782a: f10d 0306 add.w r3, sp, #6 +1002782e: 2202 movs r2, #2 +10027830: 4640 mov r0, r8 +10027832: f7fd fd85 bl 10025340 +10027836: 8835 ldrh r5, [r6, #0] +10027838: f8bd 0006 ldrh.w r0, [sp, #6] +1002783c: 4285 cmp r5, r0 +1002783e: bf28 it cs +10027840: 2000 movcs r0, #0 +10027842: d23e bcs.n 100278c2 +10027844: 7838 ldrb r0, [r7, #0] +10027846: 0140 lsls r0, r0, #5 +10027848: f040 090f orr.w r9, r0, #15 +1002784c: 4623 mov r3, r4 +1002784e: fa5f f289 uxtb.w r2, r9 +10027852: 4629 mov r1, r5 +10027854: 4640 mov r0, r8 +10027856: f7fd fddc bl 10025412 +1002785a: 4623 mov r3, r4 +1002785c: aa01 add r2, sp, #4 +1002785e: 4629 mov r1, r5 +10027860: 4640 mov r0, r8 +10027862: f7fd fd76 bl 10025352 +10027866: f89d 0004 ldrb.w r0, [sp, #4] +1002786a: 28ff cmp r0, #255 ; 0xff +1002786c: d004 beq.n 10027878 +1002786e: fa5f f189 uxtb.w r1, r9 +10027872: 4288 cmp r0, r1 +10027874: d004 beq.n 10027880 +10027876: e020 b.n 100278ba +10027878: f000 f825 bl 100278c6 <.text_24> +1002787c: dbe6 blt.n 1002784c +1002787e: e01c b.n 100278ba +10027880: 7838 ldrb r0, [r7, #0] +10027882: 7879 ldrb r1, [r7, #1] +10027884: f000 0078 and.w r0, r0, #120 ; 0x78 +10027888: 1c6d adds r5, r5, #1 +1002788a: ea41 0740 orr.w r7, r1, r0, lsl #1 +1002788e: 4623 mov r3, r4 +10027890: 463a mov r2, r7 +10027892: b2a9 uxth r1, r5 +10027894: 4640 mov r0, r8 +10027896: f7fd fdbc bl 10025412 +1002789a: 4623 mov r3, r4 +1002789c: aa01 add r2, sp, #4 +1002789e: b2a9 uxth r1, r5 +100278a0: 4640 mov r0, r8 +100278a2: f7fd fd56 bl 10025352 +100278a6: f89d 0004 ldrb.w r0, [sp, #4] +100278aa: 28ff cmp r0, #255 ; 0xff +100278ac: d002 beq.n 100278b4 +100278ae: 42b8 cmp r0, r7 +100278b0: d005 beq.n 100278be +100278b2: e002 b.n 100278ba +100278b4: f000 f807 bl 100278c6 <.text_24> +100278b8: dbe9 blt.n 1002788e +100278ba: 2000 movs r0, #0 +100278bc: e001 b.n 100278c2 +100278be: 8035 strh r5, [r6, #0] +100278c0: 2001 movs r0, #1 +100278c2: e8bd 87f6 ldmia.w sp!, {r1, r2, r4, r5, r6, r7, r8, r9, sl, pc} + +100278c6 <.text_24>: +100278c6: 4650 mov r0, sl +100278c8: f100 0a01 add.w sl, r0, #1 +100278cc: b2c0 uxtb r0, r0 +100278ce: 2804 cmp r0, #4 +100278d0: 4770 bx lr + +100278d2 : +100278d2: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +100278d6: b082 sub sp, #8 +100278d8: 4681 mov r9, r0 +100278da: 7818 ldrb r0, [r3, #0] +100278dc: 9c0a ldr r4, [sp, #40] ; 0x28 +100278de: 2500 movs r5, #0 +100278e0: 2810 cmp r0, #16 +100278e2: 4692 mov sl, r2 +100278e4: db05 blt.n 100278f2 +100278e6: 9400 str r4, [sp, #0] +100278e8: 4648 mov r0, r9 +100278ea: f7ff ff91 bl 10027810 +100278ee: 4605 mov r5, r0 +100278f0: e024 b.n 1002793c +100278f2: f88d 5000 strb.w r5, [sp] +100278f6: 7818 ldrb r0, [r3, #0] +100278f8: 7859 ldrb r1, [r3, #1] +100278fa: f8ba 8000 ldrh.w r8, [sl] +100278fe: 2600 movs r6, #0 +10027900: ea41 1700 orr.w r7, r1, r0, lsl #4 +10027904: 4623 mov r3, r4 +10027906: b2fa uxtb r2, r7 +10027908: 4641 mov r1, r8 +1002790a: 4648 mov r0, r9 +1002790c: f7fd fd81 bl 10025412 +10027910: 4623 mov r3, r4 +10027912: aa00 add r2, sp, #0 +10027914: 4641 mov r1, r8 +10027916: 4648 mov r0, r9 +10027918: f7fd fd1b bl 10025352 +1002791c: f89d 0000 ldrb.w r0, [sp] +10027920: 28ff cmp r0, #255 ; 0xff +10027922: d006 beq.n 10027932 +10027924: b2f9 uxtb r1, r7 +10027926: 4288 cmp r0, r1 +10027928: d108 bne.n 1002793c +1002792a: f8aa 8000 strh.w r8, [sl] +1002792e: 2501 movs r5, #1 +10027930: e004 b.n 1002793c +10027932: 4630 mov r0, r6 +10027934: 1c46 adds r6, r0, #1 +10027936: b2c0 uxtb r0, r0 +10027938: 2804 cmp r0, #4 +1002793a: dbe3 blt.n 10027904 +1002793c: 4628 mov r0, r5 +1002793e: e8bd 87f6 ldmia.w sp!, {r1, r2, r4, r5, r6, r7, r8, r9, sl, pc} + +10027942 : +10027942: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +10027946: b088 sub sp, #32 +10027948: 4605 mov r5, r0 +1002794a: 2000 movs r0, #0 +1002794c: f8ad 0008 strh.w r0, [sp, #8] +10027950: f8ad 0004 strh.w r0, [sp, #4] +10027954: 4688 mov r8, r1 +10027956: 9c0e ldr r4, [sp, #56] ; 0x38 +10027958: 4616 mov r6, r2 +1002795a: 461f mov r7, r3 +1002795c: 9400 str r4, [sp, #0] +1002795e: ab01 add r3, sp, #4 +10027960: f000 f875 bl 10027a4e <.text_27> +10027964: 4622 mov r2, r4 +10027966: 2100 movs r1, #0 +10027968: 4628 mov r0, r5 +1002796a: f7fd fc97 bl 1002529c +1002796e: f8bd 1004 ldrh.w r1, [sp, #4] +10027972: 4288 cmp r0, r1 +10027974: d265 bcs.n 10027a42 +10027976: 2208 movs r2, #8 +10027978: 21ff movs r1, #255 ; 0xff +1002797a: f10d 0012 add.w r0, sp, #18 +1002797e: f7e8 ff5b bl 10010838 +10027982: f88d 8010 strb.w r8, [sp, #16] +10027986: f88d 6011 strb.w r6, [sp, #17] +1002798a: f10d 0212 add.w r2, sp, #18 +1002798e: 4639 mov r1, r7 +10027990: 4630 mov r0, r6 +10027992: f7fd fd9d bl 100254d0 +10027996: f89d 0011 ldrb.w r0, [sp, #17] +1002799a: f7fd fc83 bl 100252a4 +1002799e: f88d 001a strb.w r0, [sp, #26] +100279a2: 9400 str r4, [sp, #0] +100279a4: 2000 movs r0, #0 +100279a6: f8ad 0004 strh.w r0, [sp, #4] +100279aa: f8ad 000c strh.w r0, [sp, #12] +100279ae: f8ad 000a strh.w r0, [sp, #10] +100279b2: f88d 0006 strb.w r0, [sp, #6] +100279b6: ab03 add r3, sp, #12 +100279b8: f000 f849 bl 10027a4e <.text_27> +100279bc: 9400 str r4, [sp, #0] +100279be: f10d 030a add.w r3, sp, #10 +100279c2: 2206 movs r2, #6 +100279c4: f000 f844 bl 10027a50 <.text_27+0x2> +100279c8: b924 cbnz r4, 100279d4 +100279ca: aa01 add r2, sp, #4 +100279cc: 213b movs r1, #59 ; 0x3b +100279ce: 4628 mov r0, r5 +100279d0: f7ef fca8 bl 10017324 +100279d4: f8bd 0004 ldrh.w r0, [sp, #4] +100279d8: f8bd 100a ldrh.w r1, [sp, #10] +100279dc: fb90 f2f1 sdiv r2, r0, r1 +100279e0: fb01 0012 mls r0, r1, r2, r0 +100279e4: f8ad 0004 strh.w r0, [sp, #4] +100279e8: f8bd 100c ldrh.w r1, [sp, #12] +100279ec: f8bd 0004 ldrh.w r0, [sp, #4] +100279f0: 4288 cmp r0, r1 +100279f2: d226 bcs.n 10027a42 +100279f4: 4601 mov r1, r0 +100279f6: 4623 mov r3, r4 +100279f8: f10d 0206 add.w r2, sp, #6 +100279fc: 4628 mov r0, r5 +100279fe: f7fd fca8 bl 10025352 +10027a02: 2800 cmp r0, #0 +10027a04: bf1c itt ne +10027a06: f89d 0006 ldrbne.w r0, [sp, #6] +10027a0a: 28ff cmpne r0, #255 ; 0xff +10027a0c: d119 bne.n 10027a42 +10027a0e: f8bd 0004 ldrh.w r0, [sp, #4] +10027a12: f8ad 0008 strh.w r0, [sp, #8] +10027a16: 9400 str r4, [sp, #0] +10027a18: ab04 add r3, sp, #16 +10027a1a: aa02 add r2, sp, #8 +10027a1c: 2100 movs r1, #0 +10027a1e: 4628 mov r0, r5 +10027a20: f7ff ff57 bl 100278d2 +10027a24: b180 cbz r0, 10027a48 +10027a26: f8bd 0008 ldrh.w r0, [sp, #8] +10027a2a: f89d 2011 ldrb.w r2, [sp, #17] +10027a2e: 9400 str r4, [sp, #0] +10027a30: 1c41 adds r1, r0, #1 +10027a32: f10d 0312 add.w r3, sp, #18 +10027a36: b289 uxth r1, r1 +10027a38: 4628 mov r0, r5 +10027a3a: f7fd fd62 bl 10025502 +10027a3e: 280f cmp r0, #15 +10027a40: d001 beq.n 10027a46 +10027a42: 2000 movs r0, #0 +10027a44: e000 b.n 10027a48 +10027a46: 2001 movs r0, #1 +10027a48: b008 add sp, #32 +10027a4a: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +10027a4e <.text_27>: +10027a4e: 2203 movs r2, #3 +10027a50: 2100 movs r1, #0 +10027a52: 4628 mov r0, r5 +10027a54: f7fd bc74 b.w 10025340 + +10027a58 : +10027a58: 2001 movs r0, #1 +10027a5a: 4770 bx lr + +10027a5c : +10027a5c: b570 push {r4, r5, r6, lr} +10027a5e: f641 31a4 movw r1, #7076 ; 0x1ba4 +10027a62: b088 sub sp, #32 +10027a64: 580c ldr r4, [r1, r0] +10027a66: f8df 5554 ldr.w r5, [pc, #1364] ; 10027fbc <.text_50> +10027a6a: 682e ldr r6, [r5, #0] +10027a6c: 2218 movs r2, #24 +10027a6e: 2100 movs r1, #0 +10027a70: a802 add r0, sp, #8 +10027a72: f7e8 fee1 bl 10010838 +10027a76: 200a movs r0, #10 +10027a78: 9002 str r0, [sp, #8] +10027a7a: 0c30 lsrs r0, r6, #16 +10027a7c: f000 0001 and.w r0, r0, #1 +10027a80: f080 0001 eor.w r0, r0, #1 +10027a84: 9003 str r0, [sp, #12] +10027a86: 2000 movs r0, #0 +10027a88: 9006 str r0, [sp, #24] +10027a8a: 0a30 lsrs r0, r6, #8 +10027a8c: f010 0003 ands.w r0, r0, #3 +10027a90: d006 beq.n 10027aa0 +10027a92: 2801 cmp r0, #1 +10027a94: bf08 it eq +10027a96: 2002 moveq r0, #2 +10027a98: d002 beq.n 10027aa0 +10027a9a: 2802 cmp r0, #2 +10027a9c: d101 bne.n 10027aa2 +10027a9e: 2001 movs r0, #1 +10027aa0: 9005 str r0, [sp, #20] +10027aa2: f3c6 1003 ubfx r0, r6, #4, #4 +10027aa6: 9004 str r0, [sp, #16] +10027aa8: a902 add r1, sp, #8 +10027aaa: 6868 ldr r0, [r5, #4] +10027aac: 0e40 lsrs r0, r0, #25 +10027aae: f000 0001 and.w r0, r0, #1 +10027ab2: 6220 str r0, [r4, #32] +10027ab4: b084 sub sp, #16 +10027ab6: 4668 mov r0, sp +10027ab8: 2218 movs r2, #24 +10027aba: f006 fcf7 bl 1002e4ac <__iar_unaligned___aeabi_memcpy4> +10027abe: bc0f pop {r0, r1, r2, r3} +10027ac0: f7fe fe70 bl 100267a4 +10027ac4: 4620 mov r0, r4 +10027ac6: a902 add r1, sp, #8 +10027ac8: 2218 movs r2, #24 +10027aca: f006 fcef bl 1002e4ac <__iar_unaligned___aeabi_memcpy4> +10027ace: 9806 ldr r0, [sp, #24] +10027ad0: 2801 cmp r0, #1 +10027ad2: bf08 it eq +10027ad4: 2000 moveq r0, #0 +10027ad6: d002 beq.n 10027ade +10027ad8: 2802 cmp r0, #2 +10027ada: bf18 it ne +10027adc: 2003 movne r0, #3 +10027ade: f884 004b strb.w r0, [r4, #75] ; 0x4b +10027ae2: b008 add sp, #32 +10027ae4: bd70 pop {r4, r5, r6, pc} + +10027ae6 : +10027ae6: b538 push {r3, r4, r5, lr} +10027ae8: f001 f9d9 bl 10028e9e <.text_132> +10027aec: f241 0210 movw r2, #4112 ; 0x1010 +10027af0: 5905 ldr r5, [r0, r4] +10027af2: f44f 61aa mov.w r1, #1360 ; 0x550 +10027af6: f001 f9c6 bl 10028e86 <.text_129> +10027afa: f246 4204 movw r2, #25604 ; 0x6404 +10027afe: f001 f9c0 bl 10028e82 <.text_128+0x4> +10027b02: 2108 movs r1, #8 +10027b04: f104 000c add.w r0, r4, #12 +10027b08: f7ff fbce bl 100272a8 +10027b0c: b920 cbnz r0, 10027b18 +10027b0e: 2205 movs r2, #5 +10027b10: f44f 61ab mov.w r1, #1368 ; 0x558 +10027b14: f001 f85d bl 10028bd2 <.text_115+0x4> +10027b18: 2202 movs r2, #2 +10027b1a: f240 5159 movw r1, #1369 ; 0x559 +10027b1e: f001 f858 bl 10028bd2 <.text_115+0x4> +10027b22: f246 620f movw r2, #26127 ; 0x660f +10027b26: f44f 61a2 mov.w r1, #1296 ; 0x510 +10027b2a: f001 f9ac bl 10028e86 <.text_129> +10027b2e: f001 f9ad bl 10028e8c <.text_130> +10027b32: f505 51ca add.w r1, r5, #6464 ; 0x1940 +10027b36: 6008 str r0, [r1, #0] +10027b38: f240 5122 movw r1, #1314 ; 0x522 +10027b3c: f001 f9a8 bl 10028e90 <.text_130+0x4> +10027b40: f641 113f movw r1, #6463 ; 0x193f +10027b44: 5548 strb r0, [r1, r5] +10027b46: f505 55ca add.w r5, r5, #6464 ; 0x1940 +10027b4a: f240 4122 movw r1, #1058 ; 0x422 +10027b4e: f001 f99f bl 10028e90 <.text_130+0x4> +10027b52: 7128 strb r0, [r5, #4] +10027b54: f240 5142 movw r1, #1346 ; 0x542 +10027b58: f001 f99a bl 10028e90 <.text_130+0x4> +10027b5c: 7168 strb r0, [r5, #5] +10027b5e: f240 1101 movw r1, #257 ; 0x101 +10027b62: f001 f995 bl 10028e90 <.text_130+0x4> +10027b66: 71a8 strb r0, [r5, #6] +10027b68: bd31 pop {r0, r4, r5, pc} + +10027b6a : +10027b6a: 4770 bx lr + +10027b6c <_InitBurstPktLen_8195AB>: +10027b6c: 2204 movs r2, #4 +10027b6e: f240 610c movw r1, #1548 ; 0x60c +10027b72: f7fd b86d b.w 10024c50 + +10027b76 : +10027b76: b570 push {r4, r5, r6, lr} +10027b78: f000 f835 bl 10027be6 <.text_35> +10027b7c: f040 0240 orr.w r2, r0, #64 ; 0x40 +10027b80: 5572 strb r2, [r6, r5] +10027b82: f240 4122 movw r1, #1058 ; 0x422 +10027b86: f001 f824 bl 10028bd2 <.text_115+0x4> +10027b8a: 22ff movs r2, #255 ; 0xff +10027b8c: f240 5141 movw r1, #1345 ; 0x541 +10027b90: f001 f81f bl 10028bd2 <.text_115+0x4> +10027b94: 1970 adds r0, r6, r5 +10027b96: 7841 ldrb r1, [r0, #1] +10027b98: f041 0201 orr.w r2, r1, #1 +10027b9c: 7042 strb r2, [r0, #1] +10027b9e: 4620 mov r0, r4 +10027ba0: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +10027ba4: f240 5142 movw r1, #1346 ; 0x542 +10027ba8: f7fd b852 b.w 10024c50 + +10027bac : +10027bac: b570 push {r4, r5, r6, lr} +10027bae: f000 f81a bl 10027be6 <.text_35> +10027bb2: f000 02bf and.w r2, r0, #191 ; 0xbf +10027bb6: 5572 strb r2, [r6, r5] +10027bb8: f240 4122 movw r1, #1058 ; 0x422 +10027bbc: f001 f809 bl 10028bd2 <.text_115+0x4> +10027bc0: 2264 movs r2, #100 ; 0x64 +10027bc2: f240 5141 movw r1, #1345 ; 0x541 +10027bc6: f001 f804 bl 10028bd2 <.text_115+0x4> +10027bca: 1970 adds r0, r6, r5 +10027bcc: 7841 ldrb r1, [r0, #1] +10027bce: f001 02fe and.w r2, r1, #254 ; 0xfe +10027bd2: 7042 strb r2, [r0, #1] +10027bd4: f240 5142 movw r1, #1346 ; 0x542 +10027bd8: f000 fffb bl 10028bd2 <.text_115+0x4> +10027bdc: 4620 mov r0, r4 +10027bde: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +10027be2: f009 beb9 b.w 10031958 + +10027be6 <.text_35>: +10027be6: 4604 mov r4, r0 +10027be8: f641 30a4 movw r0, #7076 ; 0x1ba4 +10027bec: f641 1644 movw r6, #6468 ; 0x1944 +10027bf0: 5905 ldr r5, [r0, r4] +10027bf2: 5d70 ldrb r0, [r6, r5] +10027bf4: 4770 bx lr + +10027bf6 : +10027bf6: b5f8 push {r3, r4, r5, r6, r7, lr} +10027bf8: 4604 mov r4, r0 +10027bfa: f641 5052 movw r0, #7506 ; 0x1d52 +10027bfe: f44f 66aa mov.w r6, #1360 ; 0x550 +10027c02: 5d00 ldrb r0, [r0, r4] +10027c04: 2801 cmp r0, #1 +10027c06: bf08 it eq +10027c08: f240 5651 movweq r6, #1361 ; 0x551 +10027c0c: f504 65bf add.w r5, r4, #1528 ; 0x5f8 +10027c10: 2202 movs r2, #2 +10027c12: f240 515a movw r1, #1370 ; 0x55a +10027c16: f001 f936 bl 10028e86 <.text_129> +10027c1a: f8b5 20aa ldrh.w r2, [r5, #170] ; 0xaa +10027c1e: f240 5154 movw r1, #1364 ; 0x554 +10027c22: f001 f930 bl 10028e86 <.text_129> +10027c26: 4620 mov r0, r4 +10027c28: f7ff ff5d bl 10027ae6 +10027c2c: 2209 movs r2, #9 +10027c2e: f240 511b movw r1, #1307 ; 0x51b +10027c32: f000 ffce bl 10028bd2 <.text_115+0x4> +10027c36: f240 6504 movw r5, #1540 ; 0x604 +10027c3a: 4629 mov r1, r5 +10027c3c: f001 fc4f bl 100294de <.text_141+0x4> +10027c40: 0847 lsrs r7, r0, #1 +10027c42: 007f lsls r7, r7, #1 +10027c44: 463a mov r2, r7 +10027c46: 4629 mov r1, r5 +10027c48: f001 f916 bl 10028e78 <.text_127+0x6> +10027c4c: f047 0201 orr.w r2, r7, #1 +10027c50: 4629 mov r1, r5 +10027c52: f001 f911 bl 10028e78 <.text_127+0x6> +10027c56: 2170 movs r1, #112 ; 0x70 +10027c58: f104 000c add.w r0, r4, #12 +10027c5c: f7ff fb24 bl 100272a8 +10027c60: 2801 cmp r0, #1 +10027c62: d109 bne.n 10027c78 +10027c64: 2250 movs r2, #80 ; 0x50 +10027c66: f240 515e movw r1, #1374 ; 0x55e +10027c6a: f000 ffb2 bl 10028bd2 <.text_115+0x4> +10027c6e: 2250 movs r2, #80 ; 0x50 +10027c70: f240 515f movw r1, #1375 ; 0x55f +10027c74: f000 ffad bl 10028bd2 <.text_115+0x4> +10027c78: 221a movs r2, #26 +10027c7a: f000 ffa8 bl 10028bce <.text_115> +10027c7e: 226f movs r2, #111 ; 0x6f +10027c80: f240 5125 movw r1, #1317 ; 0x525 +10027c84: f000 ffa5 bl 10028bd2 <.text_115+0x4> +10027c88: f000 ff9a bl 10028bc0 <.text_113> +10027c8c: 4631 mov r1, r6 +10027c8e: f001 f8ff bl 10028e90 <.text_130+0x4> +10027c92: f040 0202 orr.w r2, r0, #2 +10027c96: 4631 mov r1, r6 +10027c98: 4620 mov r0, r4 +10027c9a: e8bd 40f8 ldmia.w sp!, {r3, r4, r5, r6, r7, lr} +10027c9e: f7fc bfd7 b.w 10024c50 + +10027ca2 : +10027ca2: 4770 bx lr + +10027ca4 : +10027ca4: b5f8 push {r3, r4, r5, r6, r7, lr} +10027ca6: 4615 mov r5, r2 +10027ca8: f641 37a4 movw r7, #7076 ; 0x1ba4 +10027cac: 461a mov r2, r3 +10027cae: 583b ldr r3, [r7, r0] +10027cb0: f641 16a8 movw r6, #6568 ; 0x19a8 +10027cb4: 18f4 adds r4, r6, r3 +10027cb6: 2300 movs r3, #0 +10027cb8: b119 cbz r1, 10027cc2 +10027cba: 2902 cmp r1, #2 +10027cbc: d024 beq.n 10027d08 +10027cbe: d321 bcc.n 10027d04 +10027cc0: bdf1 pop {r0, r4, r5, r6, r7, pc} +10027cc2: f641 5148 movw r1, #7496 ; 0x1d48 +10027cc6: 180b adds r3, r1, r0 +10027cc8: 7a5b ldrb r3, [r3, #9] +10027cca: 2b00 cmp r3, #0 +10027ccc: bf1f itttt ne +10027cce: 5808 ldrne r0, [r1, r0] +10027cd0: 2800 cmpne r0, #0 +10027cd2: 5838 ldrne r0, [r7, r0] +10027cd4: 1834 addne r4, r6, r0 +10027cd6: f8d5 0100 ldr.w r0, [r5, #256] ; 0x100 +10027cda: b152 cbz r2, 10027cf2 +10027cdc: b282 uxth r2, r0 +10027cde: 462b mov r3, r5 +10027ce0: 2146 movs r1, #70 ; 0x46 +10027ce2: 4620 mov r0, r4 +10027ce4: f008 fa8f bl 10030206 +10027ce8: 4620 mov r0, r4 +10027cea: e8bd 40f2 ldmia.w sp!, {r1, r4, r5, r6, r7, lr} +10027cee: f009 bf78 b.w 10031be2 +10027cf2: b282 uxth r2, r0 +10027cf4: 4620 mov r0, r4 +10027cf6: b001 add sp, #4 +10027cf8: e8bd 40f0 ldmia.w sp!, {r4, r5, r6, r7, lr} +10027cfc: 2300 movs r3, #0 +10027cfe: 2146 movs r1, #70 ; 0x46 +10027d00: f008 ba81 b.w 10030206 +10027d04: 2135 movs r1, #53 ; 0x35 +10027d06: e000 b.n 10027d0a +10027d08: 2136 movs r1, #54 ; 0x36 +10027d0a: 4620 mov r0, r4 +10027d0c: b001 add sp, #4 +10027d0e: e8bd 40f0 ldmia.w sp!, {r4, r5, r6, r7, lr} +10027d12: f008 ba7f b.w 10030214 + +10027d16 : +10027d16: 4770 bx lr + +10027d18 : +10027d18: e92d 4ff4 stmdb sp!, {r2, r4, r5, r6, r7, r8, r9, sl, fp, lr} +10027d1c: 4604 mov r4, r0 +10027d1e: f641 38a4 movw r8, #7076 ; 0x1ba4 +10027d22: b086 sub sp, #24 +10027d24: f858 9004 ldr.w r9, [r8, r4] +10027d28: f509 50c8 add.w r0, r9, #6400 ; 0x1900 +10027d2c: 304c adds r0, #76 ; 0x4c +10027d2e: 9004 str r0, [sp, #16] +10027d30: 460d mov r5, r1 +10027d32: f504 609d add.w r0, r4, #1256 ; 0x4e8 +10027d36: 9003 str r0, [sp, #12] +10027d38: f500 7b88 add.w fp, r0, #272 ; 0x110 +10027d3c: 2600 movs r6, #0 +10027d3e: f104 0798 add.w r7, r4, #152 ; 0x98 +10027d42: 4620 mov r0, r4 +10027d44: f7f7 fd6b bl 1001f81e +10027d48: 2800 cmp r0, #0 +10027d4a: bf1f itttt ne +10027d4c: f641 5048 movwne r0, #7496 ; 0x1d48 +10027d50: 1901 addne r1, r0, r4 +10027d52: 7a49 ldrbne r1, [r1, #9] +10027d54: 2900 cmpne r1, #0 +10027d56: bf1c itt ne +10027d58: 5900 ldrne r0, [r0, r4] +10027d5a: f858 9000 ldrne.w r9, [r8, r0] +10027d5e: 2d08 cmp r5, #8 +10027d60: d27a bcs.n 10027e58 +10027d62: eb0b 1045 add.w r0, fp, r5, lsl #5 +10027d66: f8d0 110c ldr.w r1, [r0, #268] ; 0x10c +10027d6a: 9102 str r1, [sp, #8] +10027d6c: 2900 cmp r1, #0 +10027d6e: d073 beq.n 10027e58 +10027d70: 2d00 cmp r5, #0 +10027d72: bf18 it ne +10027d74: 2d02 cmpne r5, #2 +10027d76: d001 beq.n 10027d7c +10027d78: d320 bcc.n 10027dbc +10027d7a: e034 b.n 10027de6 +10027d7c: f107 0064 add.w r0, r7, #100 ; 0x64 +10027d80: f7f0 fb06 bl 10018390 +10027d84: 4682 mov sl, r0 +10027d86: 4652 mov r2, sl +10027d88: f107 0164 add.w r1, r7, #100 ; 0x64 +10027d8c: 4620 mov r0, r4 +10027d8e: f7fd fdd0 bl 10025932 +10027d92: f000 f863 bl 10027e5c <.text_41> +10027d96: f000 f866 bl 10027e66 <.text_42> +10027d9a: 4607 mov r7, r0 +10027d9c: f89b 00b4 ldrb.w r0, [fp, #180] ; 0xb4 +10027da0: f10b 0ada add.w sl, fp, #218 ; 0xda +10027da4: b110 cbz r0, 10027dac +10027da6: 4650 mov r0, sl +10027da8: f7fe fb44 bl 10026434 +10027dac: 4307 orrs r7, r0 +10027dae: 4651 mov r1, sl +10027db0: 4620 mov r0, r4 +10027db2: f7fe fb45 bl 10026440 +10027db6: b330 cbz r0, 10027e06 +10027db8: 2601 movs r6, #1 +10027dba: e024 b.n 10027e06 +10027dbc: f50b 709e add.w r0, fp, #316 ; 0x13c +10027dc0: f7f0 fae6 bl 10018390 +10027dc4: 4682 mov sl, r0 +10027dc6: 9803 ldr r0, [sp, #12] +10027dc8: 7c40 ldrb r0, [r0, #17] +10027dca: 07c0 lsls r0, r0, #31 +10027dcc: bf4c ite mi +10027dce: 2101 movmi r1, #1 +10027dd0: 2102 movpl r1, #2 +10027dd2: 4620 mov r0, r4 +10027dd4: f7fd fd78 bl 100258c8 +10027dd8: 4680 mov r8, r0 +10027dda: 4651 mov r1, sl +10027ddc: f107 0064 add.w r0, r7, #100 ; 0x64 +10027de0: f7fe faf8 bl 100263d4 +10027de4: e00e b.n 10027e04 +10027de6: f500 788e add.w r8, r0, #284 ; 0x11c +10027dea: 4640 mov r0, r8 +10027dec: f7f0 fad0 bl 10018390 +10027df0: 4682 mov sl, r0 +10027df2: 4652 mov r2, sl +10027df4: 4641 mov r1, r8 +10027df6: 4620 mov r0, r4 +10027df8: f7fd fd9b bl 10025932 +10027dfc: f000 f82e bl 10027e5c <.text_41> +10027e00: f000 f831 bl 10027e66 <.text_42> +10027e04: 4607 mov r7, r0 +10027e06: f89d 3018 ldrb.w r3, [sp, #24] +10027e0a: f509 50c8 add.w r0, r9, #6400 ; 0x1900 +10027e0e: 463a mov r2, r7 +10027e10: 4629 mov r1, r5 +10027e12: 30a8 adds r0, #168 ; 0xa8 +10027e14: f00a f810 bl 10031e38 +10027e18: 4007 ands r7, r0 +10027e1a: 4638 mov r0, r7 +10027e1c: f7fe fb2a bl 10026474 +10027e20: f000 0a3f and.w sl, r0, #63 ; 0x3f +10027e24: f641 103e movw r0, #6462 ; 0x193e +10027e28: f810 0009 ldrb.w r0, [r0, r9] +10027e2c: 2801 cmp r0, #1 +10027e2e: d109 bne.n 10027e44 +10027e30: 9701 str r7, [sp, #4] +10027e32: 9600 str r6, [sp, #0] +10027e34: fa5f f288 uxtb.w r2, r8 +10027e38: 9803 ldr r0, [sp, #12] +10027e3a: 7bc3 ldrb r3, [r0, #15] +10027e3c: b2e9 uxtb r1, r5 +10027e3e: 4620 mov r0, r4 +10027e40: f009 fda1 bl 10031986 +10027e44: 9802 ldr r0, [sp, #8] +10027e46: f880 8176 strb.w r8, [r0, #374] ; 0x176 +10027e4a: 9802 ldr r0, [sp, #8] +10027e4c: f880 a177 strb.w sl, [r0, #375] ; 0x177 +10027e50: 9804 ldr r0, [sp, #16] +10027e52: 1828 adds r0, r5, r0 +10027e54: f880 a035 strb.w sl, [r0, #53] ; 0x35 +10027e58: f000 beab b.w 10028bb2 <.text_111> + +10027e5c <.text_41>: +10027e5c: f000 010f and.w r1, r0, #15 +10027e60: 4620 mov r0, r4 +10027e62: f7fd bd31 b.w 100258c8 + +10027e66 <.text_42>: +10027e66: 4680 mov r8, r0 +10027e68: 4651 mov r1, sl +10027e6a: f107 0064 add.w r0, r7, #100 ; 0x64 +10027e6e: f7fe bac9 b.w 10026404 + +10027e72 : +10027e72: b570 push {r4, r5, r6, lr} +10027e74: 4604 mov r4, r0 +10027e76: f20f 003c addw r0, pc, #60 ; 0x3c +10027e7a: f7e8 fe89 bl 10010b90 +10027e7e: f641 30a4 movw r0, #7076 ; 0x1ba4 +10027e82: 5900 ldr r0, [r0, r4] +10027e84: f500 5524 add.w r5, r0, #10496 ; 0x2900 +10027e88: 355c adds r5, #92 ; 0x5c +10027e8a: 4620 mov r0, r4 +10027e8c: f7eb fb53 bl 10013536 +10027e90: f641 469c movw r6, #7324 ; 0x1c9c +10027e94: e002 b.n 10027e9c +10027e96: 4620 mov r0, r4 +10027e98: f7eb fb7b bl 10013592 +10027e9c: f105 0008 add.w r0, r5, #8 +10027ea0: f7e8 fd04 bl 100108ac +10027ea4: 5930 ldr r0, [r6, r4] +10027ea6: 2801 cmp r0, #1 +10027ea8: bf1e ittt ne +10027eaa: 1930 addne r0, r6, r4 +10027eac: 6840 ldrne r0, [r0, #4] +10027eae: 2801 cmpne r0, #1 +10027eb0: d1f1 bne.n 10027e96 +10027eb2: e028 b.n 10027f06 <.text_46> + +10027eb4 : +10027eb4: 5452 5f57 4957 4946 4d5f 5543 545f 5248 RTW_WIFI_MCU_THR +10027ec4: 4145 0a44 0000 0000 EAD..... + +10027ecc : +10027ecc: b570 push {r4, r5, r6, lr} +10027ece: 4604 mov r4, r0 +10027ed0: f20f 0044 addw r0, pc, #68 ; 0x44 +10027ed4: f7e8 fe5c bl 10010b90 +10027ed8: f641 30a4 movw r0, #7076 ; 0x1ba4 +10027edc: f641 469c movw r6, #7324 ; 0x1c9c +10027ee0: 5900 ldr r0, [r0, r4] +10027ee2: f500 5524 add.w r5, r0, #10496 ; 0x2900 +10027ee6: 358c adds r5, #140 ; 0x8c +10027ee8: e002 b.n 10027ef0 +10027eea: 4620 mov r0, r4 +10027eec: f7eb facc bl 10013488 +10027ef0: f105 0008 add.w r0, r5, #8 +10027ef4: f7e8 fcda bl 100108ac +10027ef8: 5930 ldr r0, [r6, r4] +10027efa: 2801 cmp r0, #1 +10027efc: bf1e ittt ne +10027efe: 1930 addne r0, r6, r4 +10027f00: 6840 ldrne r0, [r0, #4] +10027f02: 2801 cmpne r0, #1 +10027f04: d1f1 bne.n 10027eea + +10027f06 <.text_46>: +10027f06: f105 000c add.w r0, r5, #12 +10027f0a: f7e8 fcc0 bl 1001088e +10027f0e: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +10027f12: f7e8 be44 b.w 10010b9e + ... + +10027f18 : +10027f18: 5452 5f57 4e49 4554 5252 5055 5f54 4854 RTW_INTERRUPT_TH +10027f28: 4552 4441 000a 0000 READ.... + +10027f30 : +10027f30: 4923 ldr r1, [pc, #140] ; (10027fc0 <.text_51>) +10027f32: 4a24 ldr r2, [pc, #144] ; (10027fc4 <.text_52>) +10027f34: 4b24 ldr r3, [pc, #144] ; (10027fc8 <.text_53>) +10027f36: 60c1 str r1, [r0, #12] +10027f38: f100 010c add.w r1, r0, #12 +10027f3c: 62ca str r2, [r1, #44] ; 0x2c +10027f3e: 4a23 ldr r2, [pc, #140] ; (10027fcc <.text_54>) +10027f40: 630a str r2, [r1, #48] ; 0x30 +10027f42: 4a23 ldr r2, [pc, #140] ; (10027fd0 <.text_55>) +10027f44: 65ca str r2, [r1, #92] ; 0x5c +10027f46: 4a23 ldr r2, [pc, #140] ; (10027fd4 <.text_56>) +10027f48: 660a str r2, [r1, #96] ; 0x60 +10027f4a: f100 028c add.w r2, r0, #140 ; 0x8c +10027f4e: 6053 str r3, [r2, #4] +10027f50: 4b21 ldr r3, [pc, #132] ; (10027fd8 <.text_57>) +10027f52: 634b str r3, [r1, #52] ; 0x34 +10027f54: 4b21 ldr r3, [pc, #132] ; (10027fdc <.text_58>) +10027f56: 67cb str r3, [r1, #124] ; 0x7c +10027f58: 4b21 ldr r3, [pc, #132] ; (10027fe0 <.text_59>) +10027f5a: 650b str r3, [r1, #80] ; 0x50 +10027f5c: 4b21 ldr r3, [pc, #132] ; (10027fe4 <.text_60>) +10027f5e: 654b str r3, [r1, #84] ; 0x54 +10027f60: 4b21 ldr r3, [pc, #132] ; (10027fe8 <.text_61>) +10027f62: 658b str r3, [r1, #88] ; 0x58 +10027f64: 4b21 ldr r3, [pc, #132] ; (10027fec <.text_62>) +10027f66: 6213 str r3, [r2, #32] +10027f68: 4b21 ldr r3, [pc, #132] ; (10027ff0 <.text_63>) +10027f6a: 6253 str r3, [r2, #36] ; 0x24 +10027f6c: 4b21 ldr r3, [pc, #132] ; (10027ff4 <.text_64>) +10027f6e: 6293 str r3, [r2, #40] ; 0x28 +10027f70: 4b21 ldr r3, [pc, #132] ; (10027ff8 <.text_65>) +10027f72: 62d3 str r3, [r2, #44] ; 0x2c +10027f74: 4b21 ldr r3, [pc, #132] ; (10027ffc <.text_66>) +10027f76: f8c0 308c str.w r3, [r0, #140] ; 0x8c +10027f7a: 4821 ldr r0, [pc, #132] ; (10028000 <.text_67>) +10027f7c: 60d0 str r0, [r2, #12] +10027f7e: 4821 ldr r0, [pc, #132] ; (10028004 <.text_68>) +10027f80: 6110 str r0, [r2, #16] +10027f82: 4821 ldr r0, [pc, #132] ; (10028008 <.text_69>) +10027f84: 6310 str r0, [r2, #48] ; 0x30 +10027f86: 4821 ldr r0, [pc, #132] ; (1002800c <.text_70>) +10027f88: 6350 str r0, [r2, #52] ; 0x34 +10027f8a: 4821 ldr r0, [pc, #132] ; (10028010 <.text_71>) +10027f8c: 6390 str r0, [r2, #56] ; 0x38 +10027f8e: 4821 ldr r0, [pc, #132] ; (10028014 <.text_72>) +10027f90: 63d0 str r0, [r2, #60] ; 0x3c +10027f92: 4821 ldr r0, [pc, #132] ; (10028018 <.text_73>) +10027f94: 6410 str r0, [r2, #64] ; 0x40 +10027f96: 4821 ldr r0, [pc, #132] ; (1002801c <.text_74>) +10027f98: 6450 str r0, [r2, #68] ; 0x44 +10027f9a: 4821 ldr r0, [pc, #132] ; (10028020 <.text_75>) +10027f9c: 6490 str r0, [r2, #72] ; 0x48 +10027f9e: 4821 ldr r0, [pc, #132] ; (10028024 <.text_76>) +10027fa0: 64d0 str r0, [r2, #76] ; 0x4c +10027fa2: 4821 ldr r0, [pc, #132] ; (10028028 <.text_77>) +10027fa4: 6748 str r0, [r1, #116] ; 0x74 +10027fa6: 4821 ldr r0, [pc, #132] ; (1002802c <.text_78>) +10027fa8: 6788 str r0, [r1, #120] ; 0x78 +10027faa: 4821 ldr r0, [pc, #132] ; (10028030 <.text_79>) +10027fac: 6550 str r0, [r2, #84] ; 0x54 +10027fae: 4821 ldr r0, [pc, #132] ; (10028034 <.text_80>) +10027fb0: 65d0 str r0, [r2, #92] ; 0x5c +10027fb2: 4821 ldr r0, [pc, #132] ; (10028038 <.text_81>) +10027fb4: 6610 str r0, [r2, #96] ; 0x60 +10027fb6: 4770 bx lr + +10027fb8 <.text_49>: +10027fb8: 400000ec .word 0x400000ec + +10027fbc <.text_50>: +10027fbc: 400001f0 .word 0x400001f0 + +10027fc0 <.text_51>: +10027fc0: 100272bd .word 0x100272bd + +10027fc4 <.text_52>: +10027fc4: 10020d37 .word 0x10020d37 + +10027fc8 <.text_53>: +10027fc8: 10031b71 .word 0x10031b71 + +10027fcc <.text_54>: +10027fcc: 10020d57 .word 0x10020d57 + +10027fd0 <.text_55>: +10027fd0: 10020c5f .word 0x10020c5f + +10027fd4 <.text_56>: +10027fd4: 10020d35 .word 0x10020d35 + +10027fd8 <.text_57>: +10027fd8: 10027a5d .word 0x10027a5d + +10027fdc <.text_58>: +10027fdc: 10027d19 .word 0x10027d19 + +10027fe0 <.text_59>: +10027fe0: 10029f11 .word 0x10029f11 + +10027fe4 <.text_60>: +10027fe4: 10029f2d .word 0x10029f2d + +10027fe8 <.text_61>: +10027fe8: 10029f47 .word 0x10029f47 + +10027fec <.text_62>: +10027fec: 00018279 .word 0x00018279 + +10027ff0 <.text_63>: +10027ff0: 00018239 .word 0x00018239 + +10027ff4 <.text_64>: +10027ff4: 10029751 .word 0x10029751 + +10027ff8 <.text_65>: +10027ff8: 10029769 .word 0x10029769 + +10027ffc <.text_66>: +10027ffc: 10027bf7 .word 0x10027bf7 + +10028000 <.text_67>: +10028000: 100295c1 .word 0x100295c1 + +10028004 <.text_68>: +10028004: 1002961d .word 0x1002961d + +10028008 <.text_69>: +10028008: 10027377 .word 0x10027377 + +1002800c <.text_70>: +1002800c: 100274df .word 0x100274df + +10028010 <.text_71>: +10028010: 10027311 .word 0x10027311 + +10028014 <.text_72>: +10028014: 100275d1 .word 0x100275d1 + +10028018 <.text_73>: +10028018: 10027721 .word 0x10027721 + +1002801c <.text_74>: +1002801c: 10027943 .word 0x10027943 + +10028020 <.text_75>: +10028020: 100275df .word 0x100275df + +10028024 <.text_76>: +10028024: 10027a59 .word 0x10027a59 + +10028028 <.text_77>: +10028028: 10027ca3 .word 0x10027ca3 + +1002802c <.text_78>: +1002802c: 10027ca5 .word 0x10027ca5 + +10028030 <.text_79>: +10028030: 10027d17 .word 0x10027d17 + +10028034 <.text_80>: +10028034: 10028fb9 .word 0x10028fb9 + +10028038 <.text_81>: +10028038: 10028fb5 .word 0x10028fb5 + +1002803c : +1002803c: 4770 bx lr + +1002803e : +1002803e: 4770 bx lr + +10028040 : +10028040: b570 push {r4, r5, r6, lr} +10028042: 4604 mov r4, r0 +10028044: 2500 movs r5, #0 +10028046: f44f 7109 mov.w r1, #548 ; 0x224 +1002804a: f7fc fdfb bl 10024c44 +1002804e: f440 3280 orr.w r2, r0, #65536 ; 0x10000 +10028052: f44f 7109 mov.w r1, #548 ; 0x224 +10028056: f000 ff0f bl 10028e78 <.text_127+0x6> +1002805a: f7e8 fc98 bl 1001098e +1002805e: 4606 mov r6, r0 +10028060: e002 b.n 10028068 +10028062: 2002 movs r0, #2 +10028064: f7e8 fcca bl 100109fc +10028068: f44f 7109 mov.w r1, #548 ; 0x224 +1002806c: f001 fa37 bl 100294de <.text_141+0x4> +10028070: 03c0 lsls r0, r0, #15 +10028072: d401 bmi.n 10028078 +10028074: 2501 movs r5, #1 +10028076: e005 b.n 10028084 +10028078: 4630 mov r0, r6 +1002807a: f7e8 fcb0 bl 100109de +1002807e: f5b0 7f7a cmp.w r0, #1000 ; 0x3e8 +10028082: d9ee bls.n 10028062 +10028084: 4628 mov r0, r5 +10028086: bd70 pop {r4, r5, r6, pc} + +10028088 : +10028088: 460a mov r2, r1 +1002808a: 2101 movs r1, #1 +1002808c: 280f cmp r0, #15 +1002808e: 4603 mov r3, r0 +10028090: da12 bge.n 100280b8 +10028092: b108 cbz r0, 10028098 +10028094: 2803 cmp r0, #3 +10028096: db14 blt.n 100280c2 +10028098: 1ed8 subs r0, r3, #3 +1002809a: 2803 cmp r0, #3 +1002809c: d317 bcc.n 100280ce +1002809e: 1f98 subs r0, r3, #6 +100280a0: 2803 cmp r0, #3 +100280a2: d31a bcc.n 100280da +100280a4: f1a3 0009 sub.w r0, r3, #9 +100280a8: 2803 cmp r0, #3 +100280aa: d31c bcc.n 100280e6 +100280ac: f1a3 000c sub.w r0, r3, #12 +100280b0: 2803 cmp r0, #3 +100280b2: d256 bcs.n 10028162 +100280b4: 2004 movs r0, #4 +100280b6: e053 b.n 10028160 +100280b8: 2100 movs r1, #0 +100280ba: f1a3 0024 sub.w r0, r3, #36 ; 0x24 +100280be: 2807 cmp r0, #7 +100280c0: d201 bcs.n 100280c6 +100280c2: 2000 movs r0, #0 +100280c4: e04c b.n 10028160 +100280c6: f1a3 002c sub.w r0, r3, #44 ; 0x2c +100280ca: 2805 cmp r0, #5 +100280cc: d201 bcs.n 100280d2 +100280ce: 2001 movs r0, #1 +100280d0: e046 b.n 10028160 +100280d2: f1a3 0032 sub.w r0, r3, #50 ; 0x32 +100280d6: 2809 cmp r0, #9 +100280d8: d201 bcs.n 100280de +100280da: 2002 movs r0, #2 +100280dc: e040 b.n 10028160 +100280de: f1a3 003c sub.w r0, r3, #60 ; 0x3c +100280e2: 2805 cmp r0, #5 +100280e4: d201 bcs.n 100280ea +100280e6: 2003 movs r0, #3 +100280e8: e03a b.n 10028160 +100280ea: f1a3 0064 sub.w r0, r3, #100 ; 0x64 +100280ee: 2807 cmp r0, #7 +100280f0: bf38 it cc +100280f2: 2004 movcc r0, #4 +100280f4: d334 bcc.n 10028160 +100280f6: f1a3 006c sub.w r0, r3, #108 ; 0x6c +100280fa: 2807 cmp r0, #7 +100280fc: bf38 it cc +100280fe: 2005 movcc r0, #5 +10028100: d32e bcc.n 10028160 +10028102: f1a3 0074 sub.w r0, r3, #116 ; 0x74 +10028106: 2807 cmp r0, #7 +10028108: bf38 it cc +1002810a: 2006 movcc r0, #6 +1002810c: d328 bcc.n 10028160 +1002810e: f1a3 007c sub.w r0, r3, #124 ; 0x7c +10028112: 2807 cmp r0, #7 +10028114: bf38 it cc +10028116: 2007 movcc r0, #7 +10028118: d322 bcc.n 10028160 +1002811a: f1a3 0084 sub.w r0, r3, #132 ; 0x84 +1002811e: 2807 cmp r0, #7 +10028120: bf38 it cc +10028122: 2008 movcc r0, #8 +10028124: d31c bcc.n 10028160 +10028126: f1a3 008c sub.w r0, r3, #140 ; 0x8c +1002812a: 2805 cmp r0, #5 +1002812c: bf38 it cc +1002812e: 2009 movcc r0, #9 +10028130: d316 bcc.n 10028160 +10028132: f1a3 0095 sub.w r0, r3, #149 ; 0x95 +10028136: 2807 cmp r0, #7 +10028138: bf38 it cc +1002813a: 200a movcc r0, #10 +1002813c: d310 bcc.n 10028160 +1002813e: f1a3 009d sub.w r0, r3, #157 ; 0x9d +10028142: 2805 cmp r0, #5 +10028144: bf38 it cc +10028146: 200b movcc r0, #11 +10028148: d30a bcc.n 10028160 +1002814a: f1a3 00a5 sub.w r0, r3, #165 ; 0xa5 +1002814e: 2807 cmp r0, #7 +10028150: bf38 it cc +10028152: 200c movcc r0, #12 +10028154: d304 bcc.n 10028160 +10028156: f1a3 00ad sub.w r0, r3, #173 ; 0xad +1002815a: 2805 cmp r0, #5 +1002815c: d201 bcs.n 10028162 +1002815e: 200d movs r0, #13 +10028160: 7010 strb r0, [r2, #0] +10028162: 4608 mov r0, r1 +10028164: 4770 bx lr + +10028166 : +10028166: b538 push {r3, r4, r5, lr} +10028168: f500 55c8 add.w r5, r0, #6400 ; 0x1900 +1002816c: 3594 adds r5, #148 ; 0x94 +1002816e: 460c mov r4, r1 +10028170: 7b29 ldrb r1, [r5, #12] +10028172: 782a ldrb r2, [r5, #0] +10028174: b91a cbnz r2, 1002817e +10028176: 2901 cmp r1, #1 +10028178: d00e beq.n 10028198 +1002817a: 2100 movs r1, #0 +1002817c: e001 b.n 10028182 +1002817e: b911 cbnz r1, 10028186 +10028180: 2200 movs r2, #0 +10028182: f7fd fb1d bl 100257c0 +10028186: f105 010d add.w r1, r5, #13 +1002818a: 4620 mov r0, r4 +1002818c: e8bd 4038 ldmia.w sp!, {r3, r4, r5, lr} +10028190: f44f 7200 mov.w r2, #512 ; 0x200 +10028194: f7e8 bb3b b.w 1001080e +10028198: bd31 pop {r0, r4, r5, pc} + +1002819a : +1002819a: f500 50c8 add.w r0, r0, #6400 ; 0x1900 +1002819e: 8809 ldrh r1, [r1, #0] +100281a0: 3094 adds r0, #148 ; 0x94 +100281a2: f248 1295 movw r2, #33173 ; 0x8195 +100281a6: 4291 cmp r1, r2 +100281a8: bf14 ite ne +100281aa: 2101 movne r1, #1 +100281ac: 2100 moveq r1, #0 +100281ae: 7001 strb r1, [r0, #0] +100281b0: 4770 bx lr + +100281b2 : +100281b2: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +100281b6: 4688 mov r8, r1 +100281b8: f641 31a4 movw r1, #7076 ; 0x1ba4 +100281bc: 4615 mov r5, r2 +100281be: 580c ldr r4, [r1, r0] +100281c0: 461f mov r7, r3 +100281c2: 2620 movs r6, #32 +100281c4: 2238 movs r2, #56 ; 0x38 +100281c6: 2100 movs r1, #0 +100281c8: 4640 mov r0, r8 +100281ca: f7e8 fb35 bl 10010838 +100281ce: f895 2021 ldrb.w r2, [r5, #33] ; 0x21 +100281d2: 2106 movs r1, #6 +100281d4: 2aff cmp r2, #255 ; 0xff +100281d6: f06f 0001 mvn.w r0, #1 +100281da: d001 beq.n 100281e0 +100281dc: 2f00 cmp r7, #0 +100281de: d021 beq.n 10028224 +100281e0: 2200 movs r2, #0 +100281e2: 2300 movs r3, #0 +100281e4: fb01 8502 mla r5, r1, r2, r8 +100281e8: 262d movs r6, #45 ; 0x2d +100281ea: 555e strb r6, [r3, r5] +100281ec: 195c adds r4, r3, r5 +100281ee: 1c5b adds r3, r3, #1 +100281f0: 2b06 cmp r3, #6 +100281f2: 7326 strb r6, [r4, #12] +100281f4: d3f9 bcc.n 100281ea +100281f6: eb08 0582 add.w r5, r8, r2, lsl #2 +100281fa: 2300 movs r3, #0 +100281fc: f885 3028 strb.w r3, [r5, #40] ; 0x28 +10028200: 2302 movs r3, #2 +10028202: f885 3020 strb.w r3, [r5, #32] +10028206: 2301 movs r3, #1 +10028208: 195e adds r6, r3, r5 +1002820a: f106 0418 add.w r4, r6, #24 +1002820e: 1c5b adds r3, r3, #1 +10028210: 7420 strb r0, [r4, #16] +10028212: 7620 strb r0, [r4, #24] +10028214: 7630 strb r0, [r6, #24] +10028216: 2b04 cmp r3, #4 +10028218: 7220 strb r0, [r4, #8] +1002821a: d3f5 bcc.n 10028208 +1002821c: 1c52 adds r2, r2, #1 +1002821e: 2a02 cmp r2, #2 +10028220: d3df bcc.n 100281e2 +10028222: e09c b.n 1002835e +10028224: 2201 movs r2, #1 +10028226: f884 205c strb.w r2, [r4, #92] ; 0x5c +1002822a: 2200 movs r2, #0 +1002822c: 2300 movs r3, #0 +1002822e: fb01 8902 mla r9, r1, r2, r8 +10028232: 5d74 ldrb r4, [r6, r5] +10028234: f803 4009 strb.w r4, [r3, r9] +10028238: 1c76 adds r6, r6, #1 +1002823a: 2cff cmp r4, #255 ; 0xff +1002823c: bf04 itt eq +1002823e: 242d moveq r4, #45 ; 0x2d +10028240: f803 4009 strbeq.w r4, [r3, r9] +10028244: 1c5b adds r3, r3, #1 +10028246: 2b06 cmp r3, #6 +10028248: d3f3 bcc.n 10028232 +1002824a: 2300 movs r3, #0 +1002824c: 5d74 ldrb r4, [r6, r5] +1002824e: eb03 0709 add.w r7, r3, r9 +10028252: 1c76 adds r6, r6, #1 +10028254: 733c strb r4, [r7, #12] +10028256: 2cff cmp r4, #255 ; 0xff +10028258: bf04 itt eq +1002825a: 242d moveq r4, #45 ; 0x2d +1002825c: 733c strbeq r4, [r7, #12] +1002825e: 1c5b adds r3, r3, #1 +10028260: 2b05 cmp r3, #5 +10028262: d3f3 bcc.n 1002824c +10028264: eb08 0982 add.w r9, r8, r2, lsl #2 +10028268: 2300 movs r3, #0 +1002826a: f109 0c18 add.w ip, r9, #24 +1002826e: e000 b.n 10028272 +10028270: bb5b cbnz r3, 100282ca +10028272: 2400 movs r4, #0 +10028274: f88c 4018 strb.w r4, [ip, #24] +10028278: 5d74 ldrb r4, [r6, r5] +1002827a: 2cff cmp r4, #255 ; 0xff +1002827c: d103 bne.n 10028286 +1002827e: 2400 movs r4, #0 +10028280: f88c 4010 strb.w r4, [ip, #16] +10028284: e00b b.n 1002829e +10028286: 0924 lsrs r4, r4, #4 +10028288: f88c 4010 strb.w r4, [ip, #16] +1002828c: f99c e010 ldrsb.w lr, [ip, #16] +10028290: ea5f 740e movs.w r4, lr, lsl #28 +10028294: bf44 itt mi +10028296: f06e 0e0f ornmi lr, lr, #15 +1002829a: f88c e010 strbmi.w lr, [ip, #16] +1002829e: 5d74 ldrb r4, [r6, r5] +100282a0: 2cff cmp r4, #255 ; 0xff +100282a2: d103 bne.n 100282ac +100282a4: 2402 movs r4, #2 +100282a6: f88c 4008 strb.w r4, [ip, #8] +100282aa: e00a b.n 100282c2 +100282ac: f004 0e0f and.w lr, r4, #15 +100282b0: f88c e008 strb.w lr, [ip, #8] +100282b4: ea5f 740e movs.w r4, lr, lsl #28 +100282b8: bf44 itt mi +100282ba: f06e 0e0f ornmi lr, lr, #15 +100282be: f88c e008 strbmi.w lr, [ip, #8] +100282c2: 2400 movs r4, #0 +100282c4: f889 4018 strb.w r4, [r9, #24] +100282c8: e040 b.n 1002834c +100282ca: 5d77 ldrb r7, [r6, r5] +100282cc: eb03 0e09 add.w lr, r3, r9 +100282d0: f10e 0418 add.w r4, lr, #24 +100282d4: 2fff cmp r7, #255 ; 0xff +100282d6: bf08 it eq +100282d8: 7620 strbeq r0, [r4, #24] +100282da: d009 beq.n 100282f0 +100282dc: 093f lsrs r7, r7, #4 +100282de: 7627 strb r7, [r4, #24] +100282e0: f994 7018 ldrsb.w r7, [r4, #24] +100282e4: ea5f 7a07 movs.w sl, r7, lsl #28 +100282e8: bf44 itt mi +100282ea: f067 070f ornmi r7, r7, #15 +100282ee: 7627 strbmi r7, [r4, #24] +100282f0: 5d77 ldrb r7, [r6, r5] +100282f2: 2fff cmp r7, #255 ; 0xff +100282f4: bf08 it eq +100282f6: 7420 strbeq r0, [r4, #16] +100282f8: d008 beq.n 1002830c +100282fa: f007 070f and.w r7, r7, #15 +100282fe: 7427 strb r7, [r4, #16] +10028300: ea5f 7a07 movs.w sl, r7, lsl #28 +10028304: bf44 itt mi +10028306: f067 070f ornmi r7, r7, #15 +1002830a: 7427 strbmi r7, [r4, #16] +1002830c: 1c76 adds r6, r6, #1 +1002830e: 5d77 ldrb r7, [r6, r5] +10028310: 2fff cmp r7, #255 ; 0xff +10028312: bf08 it eq +10028314: 7220 strbeq r0, [r4, #8] +10028316: d009 beq.n 1002832c +10028318: 093f lsrs r7, r7, #4 +1002831a: 7227 strb r7, [r4, #8] +1002831c: f994 7008 ldrsb.w r7, [r4, #8] +10028320: ea5f 7a07 movs.w sl, r7, lsl #28 +10028324: bf44 itt mi +10028326: f067 070f ornmi r7, r7, #15 +1002832a: 7227 strbmi r7, [r4, #8] +1002832c: 5d74 ldrb r4, [r6, r5] +1002832e: 2cff cmp r4, #255 ; 0xff +10028330: bf08 it eq +10028332: f88e 0018 strbeq.w r0, [lr, #24] +10028336: d009 beq.n 1002834c +10028338: f004 040f and.w r4, r4, #15 +1002833c: f88e 4018 strb.w r4, [lr, #24] +10028340: 0727 lsls r7, r4, #28 +10028342: bf44 itt mi +10028344: f064 040f ornmi r4, r4, #15 +10028348: f88e 4018 strbmi.w r4, [lr, #24] +1002834c: 1c76 adds r6, r6, #1 +1002834e: 1c5b adds r3, r3, #1 +10028350: 2b04 cmp r3, #4 +10028352: d38d bcc.n 10028270 +10028354: 3618 adds r6, #24 +10028356: 1c52 adds r2, r2, #1 +10028358: 2a02 cmp r2, #2 +1002835a: f4ff af67 bcc.w 1002822c +1002835e: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + +10028362 : +10028362: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} +10028366: 4688 mov r8, r1 +10028368: f641 31a4 movw r1, #7076 ; 0x1ba4 +1002836c: b08f sub sp, #60 ; 0x3c +1002836e: f851 9000 ldr.w r9, [r1, r0] +10028372: 4615 mov r5, r2 +10028374: 462b mov r3, r5 +10028376: 4642 mov r2, r8 +10028378: a901 add r1, sp, #4 +1002837a: f7ff ff1a bl 100281b2 +1002837e: 2700 movs r7, #0 +10028380: a801 add r0, sp, #4 +10028382: 2106 movs r1, #6 +10028384: 2400 movs r4, #0 +10028386: fb01 0607 mla r6, r1, r7, r0 +1002838a: 1c60 adds r0, r4, #1 +1002838c: a900 add r1, sp, #0 +1002838e: b2c0 uxtb r0, r0 +10028390: f7ff fe7a bl 10028088 +10028394: 200e movs r0, #14 +10028396: fb00 9007 mla r0, r0, r7, r9 +1002839a: 1821 adds r1, r4, r0 +1002839c: 2c0d cmp r4, #13 +1002839e: bf0e itee eq +100283a0: 7972 ldrbeq r2, [r6, #5] +100283a2: f89d 2000 ldrbne.w r2, [sp] +100283a6: 5d92 ldrbne r2, [r2, r6] +100283a8: f101 0061 add.w r0, r1, #97 ; 0x61 +100283ac: f881 2061 strb.w r2, [r1, #97] ; 0x61 +100283b0: 1c64 adds r4, r4, #1 +100283b2: f89d 1000 ldrb.w r1, [sp] +100283b6: 1989 adds r1, r1, r6 +100283b8: 2c0e cmp r4, #14 +100283ba: 7b09 ldrb r1, [r1, #12] +100283bc: 7701 strb r1, [r0, #28] +100283be: dbe4 blt.n 1002838a +100283c0: 2000 movs r0, #0 +100283c2: aa01 add r2, sp, #4 +100283c4: eb02 0287 add.w r2, r2, r7, lsl #2 +100283c8: 1882 adds r2, r0, r2 +100283ca: eb09 0187 add.w r1, r9, r7, lsl #2 +100283ce: 1841 adds r1, r0, r1 +100283d0: 7e13 ldrb r3, [r2, #24] +100283d2: f881 3099 strb.w r3, [r1, #153] ; 0x99 +100283d6: 3199 adds r1, #153 ; 0x99 +100283d8: f892 3020 ldrb.w r3, [r2, #32] +100283dc: 720b strb r3, [r1, #8] +100283de: 1c40 adds r0, r0, #1 +100283e0: f892 3028 ldrb.w r3, [r2, #40] ; 0x28 +100283e4: 740b strb r3, [r1, #16] +100283e6: 2804 cmp r0, #4 +100283e8: f892 2030 ldrb.w r2, [r2, #48] ; 0x30 +100283ec: 760a strb r2, [r1, #24] +100283ee: dbe8 blt.n 100283c2 +100283f0: 1c7f adds r7, r7, #1 +100283f2: 2f02 cmp r7, #2 +100283f4: dbc4 blt.n 10028380 +100283f6: b94d cbnz r5, 1002840c +100283f8: f898 0131 ldrb.w r0, [r8, #305] ; 0x131 +100283fc: f000 0007 and.w r0, r0, #7 +10028400: f889 005b strb.w r0, [r9, #91] ; 0x5b +10028404: f898 0131 ldrb.w r0, [r8, #305] ; 0x131 +10028408: 28ff cmp r0, #255 ; 0xff +1002840a: d102 bne.n 10028412 +1002840c: 2001 movs r0, #1 +1002840e: f889 005b strb.w r0, [r9, #91] ; 0x5b +10028412: b00f add sp, #60 ; 0x3c +10028414: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + +10028418 : +10028418: f641 33a4 movw r3, #7076 ; 0x1ba4 +1002841c: 2a00 cmp r2, #0 +1002841e: 5818 ldr r0, [r3, r0] +10028420: bf0c ite eq +10028422: f891 1134 ldrbeq.w r1, [r1, #308] ; 0x134 +10028426: 2101 movne r1, #1 +10028428: f880 105a strb.w r1, [r0, #90] ; 0x5a +1002842c: 4770 bx lr + +1002842e : +1002842e: b538 push {r3, r4, r5, lr} +10028430: f000 fd35 bl 10028e9e <.text_132> +10028434: 2201 movs r2, #1 +10028436: 5905 ldr r5, [r0, r4] +10028438: 2100 movs r1, #0 +1002843a: 4620 mov r0, r4 +1002843c: f7fc ff2a bl 10025294 +10028440: 2300 movs r3, #0 +10028442: aa00 add r2, sp, #0 +10028444: 21f8 movs r1, #248 ; 0xf8 +10028446: f7ff f8c0 bl 100275ca <.text_15+0x4> +1002844a: 2200 movs r2, #0 +1002844c: 2100 movs r1, #0 +1002844e: 4620 mov r0, r4 +10028450: f7fc ff20 bl 10025294 +10028454: f89d 0000 ldrb.w r0, [sp] +10028458: 28fd cmp r0, #253 ; 0xfd +1002845a: d008 beq.n 1002846e +1002845c: 28fe cmp r0, #254 ; 0xfe +1002845e: d004 beq.n 1002846a +10028460: 28ff cmp r0, #255 ; 0xff +10028462: bf0c ite eq +10028464: 2001 moveq r0, #1 +10028466: 2000 movne r0, #0 +10028468: e002 b.n 10028470 +1002846a: 2004 movs r0, #4 +1002846c: e000 b.n 10028470 +1002846e: 2005 movs r0, #5 +10028470: f885 004c strb.w r0, [r5, #76] ; 0x4c +10028474: bd31 pop {r0, r4, r5, pc} + +10028476 : +10028476: b510 push {r4, lr} +10028478: b082 sub sp, #8 +1002847a: 4604 mov r4, r0 +1002847c: b911 cbnz r1, 10028484 +1002847e: 2201 movs r2, #1 +10028480: 21ff movs r1, #255 ; 0xff +10028482: e004 b.n 1002848e +10028484: f891 10c8 ldrb.w r1, [r1, #200] ; 0xc8 +10028488: 29ff cmp r1, #255 ; 0xff +1002848a: bf08 it eq +1002848c: 2201 moveq r2, #1 +1002848e: 9200 str r2, [sp, #0] +10028490: f641 00d9 movw r0, #6361 ; 0x18d9 +10028494: 230a movs r3, #10 +10028496: 5d02 ldrb r2, [r0, r4] +10028498: 4620 mov r0, r4 +1002849a: f7fe fa2f bl 100268fc +1002849e: f884 049e strb.w r0, [r4, #1182] ; 0x49e +100284a2: 4601 mov r1, r0 +100284a4: 4620 mov r0, r4 +100284a6: e8bd 401c ldmia.w sp!, {r2, r3, r4, lr} +100284aa: f007 bc33 b.w 1002fd14 + +100284ae : +100284ae: f641 33a4 movw r3, #7076 ; 0x1ba4 +100284b2: 2a00 cmp r2, #0 +100284b4: 5818 ldr r0, [r3, r0] +100284b6: bf0c ite eq +100284b8: f891 1135 ldrbeq.w r1, [r1, #309] ; 0x135 +100284bc: 2100 movne r1, #0 +100284be: f880 1058 strb.w r1, [r0, #88] ; 0x58 +100284c2: 4770 bx lr + +100284c4 : +100284c4: f641 33a4 movw r3, #7076 ; 0x1ba4 +100284c8: 5818 ldr r0, [r3, r0] +100284ca: b91a cbnz r2, 100284d4 +100284cc: f891 10c9 ldrb.w r1, [r1, #201] ; 0xc9 +100284d0: 29ff cmp r1, #255 ; 0xff +100284d2: d100 bne.n 100284d6 +100284d4: 2120 movs r1, #32 +100284d6: f641 02b8 movw r2, #6328 ; 0x18b8 +100284da: 5411 strb r1, [r2, r0] +100284dc: 4770 bx lr + +100284de : +100284de: f641 33a4 movw r3, #7076 ; 0x1ba4 +100284e2: 2a00 cmp r2, #0 +100284e4: 5818 ldr r0, [r3, r0] +100284e6: bf0c ite eq +100284e8: f891 10ca ldrbeq.w r1, [r1, #202] ; 0xca +100284ec: 211a movne r1, #26 +100284ee: f880 105d strb.w r1, [r0, #93] ; 0x5d +100284f2: f890 105d ldrb.w r1, [r0, #93] ; 0x5d +100284f6: 29ff cmp r1, #255 ; 0xff +100284f8: bf18 it ne +100284fa: 2a01 cmpne r2, #1 +100284fc: d105 bne.n 1002850a +100284fe: 2101 movs r1, #1 +10028500: f880 105e strb.w r1, [r0, #94] ; 0x5e +10028504: 211a movs r1, #26 +10028506: f880 105d strb.w r1, [r0, #93] ; 0x5d +1002850a: 4770 bx lr + +1002850c : +1002850c: b5f8 push {r3, r4, r5, r6, r7, lr} +1002850e: 4605 mov r5, r0 +10028510: f641 36a1 movw r6, #7073 ; 0x1ba1 +10028514: 460f mov r7, r1 +10028516: 1974 adds r4, r6, r5 +10028518: b99a cbnz r2, 10028542 +1002851a: 2300 movs r3, #0 +1002851c: aa00 add r2, sp, #0 +1002851e: 21ee movs r1, #238 ; 0xee +10028520: f7fc fecf bl 100252c2 +10028524: f897 0138 ldrb.w r0, [r7, #312] ; 0x138 +10028528: 28ff cmp r0, #255 ; 0xff +1002852a: d00a beq.n 10028542 +1002852c: 06c0 lsls r0, r0, #27 +1002852e: d508 bpl.n 10028542 +10028530: f89d 0000 ldrb.w r0, [sp] +10028534: 28ff cmp r0, #255 ; 0xff +10028536: d004 beq.n 10028542 +10028538: 2001 movs r0, #1 +1002853a: 5570 strb r0, [r6, r5] +1002853c: f89d 0000 ldrb.w r0, [sp] +10028540: e002 b.n 10028548 +10028542: 2000 movs r0, #0 +10028544: 5570 strb r0, [r6, r5] +10028546: 20ff movs r0, #255 ; 0xff +10028548: 7060 strb r0, [r4, #1] +1002854a: bdf1 pop {r0, r4, r5, r6, r7, pc} + +1002854c : +1002854c: f641 33a4 movw r3, #7076 ; 0x1ba4 +10028550: 2200 movs r2, #0 +10028552: 5818 ldr r0, [r3, r0] +10028554: 6bc0 ldr r0, [r0, #60] ; 0x3c +10028556: 2802 cmp r0, #2 +10028558: d108 bne.n 1002856c +1002855a: f891 0059 ldrb.w r0, [r1, #89] ; 0x59 +1002855e: 2802 cmp r0, #2 +10028560: bf08 it eq +10028562: 2202 moveq r2, #2 +10028564: d00b beq.n 1002857e +10028566: 2801 cmp r0, #1 +10028568: d109 bne.n 1002857e +1002856a: e007 b.n 1002857c +1002856c: 2801 cmp r0, #1 +1002856e: d106 bne.n 1002857e +10028570: f891 0059 ldrb.w r0, [r1, #89] ; 0x59 +10028574: 2801 cmp r0, #1 +10028576: bf18 it ne +10028578: 2802 cmpne r0, #2 +1002857a: d100 bne.n 1002857e +1002857c: 2201 movs r2, #1 +1002857e: 4610 mov r0, r2 +10028580: 4770 bx lr + +10028582 : +10028582: f641 33a4 movw r3, #7076 ; 0x1ba4 +10028586: 2200 movs r2, #0 +10028588: 5818 ldr r0, [r3, r0] +1002858a: 6bc3 ldr r3, [r0, #60] ; 0x3c +1002858c: 303c adds r0, #60 ; 0x3c +1002858e: 2b02 cmp r3, #2 +10028590: d123 bne.n 100285da +10028592: f891 1059 ldrb.w r1, [r1, #89] ; 0x59 +10028596: 2902 cmp r1, #2 +10028598: d02e beq.n 100285f8 +1002859a: 2901 cmp r1, #1 +1002859c: d108 bne.n 100285b0 +1002859e: 7ac0 ldrb r0, [r0, #11] +100285a0: 2801 cmp r0, #1 +100285a2: bf08 it eq +100285a4: 220a moveq r2, #10 +100285a6: d027 beq.n 100285f8 +100285a8: 2802 cmp r0, #2 +100285aa: d125 bne.n 100285f8 +100285ac: 2209 movs r2, #9 +100285ae: e023 b.n 100285f8 +100285b0: 7a41 ldrb r1, [r0, #9] +100285b2: 2901 cmp r1, #1 +100285b4: d104 bne.n 100285c0 +100285b6: 7ac0 ldrb r0, [r0, #11] +100285b8: 2801 cmp r0, #1 +100285ba: d107 bne.n 100285cc +100285bc: 2204 movs r2, #4 +100285be: e01b b.n 100285f8 +100285c0: 2902 cmp r1, #2 +100285c2: d119 bne.n 100285f8 +100285c4: 7ac0 ldrb r0, [r0, #11] +100285c6: 2801 cmp r0, #1 +100285c8: d103 bne.n 100285d2 +100285ca: e014 b.n 100285f6 +100285cc: 2802 cmp r0, #2 +100285ce: d113 bne.n 100285f8 +100285d0: e00d b.n 100285ee +100285d2: 2802 cmp r0, #2 +100285d4: d110 bne.n 100285f8 +100285d6: 2203 movs r2, #3 +100285d8: e00e b.n 100285f8 +100285da: 2b01 cmp r3, #1 +100285dc: d10c bne.n 100285f8 +100285de: f891 1059 ldrb.w r1, [r1, #89] ; 0x59 +100285e2: 2901 cmp r1, #1 +100285e4: d008 beq.n 100285f8 +100285e6: b939 cbnz r1, 100285f8 +100285e8: 7a41 ldrb r1, [r0, #9] +100285ea: 2902 cmp r1, #2 +100285ec: d101 bne.n 100285f2 +100285ee: 2201 movs r2, #1 +100285f0: e002 b.n 100285f8 +100285f2: 2901 cmp r1, #1 +100285f4: d100 bne.n 100285f8 +100285f6: 2202 movs r2, #2 +100285f8: 4610 mov r0, r2 +100285fa: 4770 bx lr + +100285fc : +100285fc: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +10028600: 4682 mov sl, r0 +10028602: 460d mov r5, r1 +10028604: b083 sub sp, #12 +10028606: f000 f95c bl 100288c2 <.text_106> +1002860a: f8da b07c ldr.w fp, [sl, #124] ; 0x7c +1002860e: f641 30a4 movw r0, #7076 ; 0x1ba4 +10028612: f50b 689d add.w r8, fp, #1256 ; 0x4e8 +10028616: f850 700b ldr.w r7, [r0, fp] +1002861a: f508 7088 add.w r0, r8, #272 ; 0x110 +1002861e: f10a 0908 add.w r9, sl, #8 +10028622: 9001 str r0, [sp, #4] +10028624: f109 043b add.w r4, r9, #59 ; 0x3b +10028628: 7d20 ldrb r0, [r4, #20] +1002862a: f000 0001 and.w r0, r0, #1 +1002862e: 9000 str r0, [sp, #0] +10028630: 4658 mov r0, fp +10028632: f7f7 f8f4 bl 1001f81e +10028636: 2800 cmp r0, #0 +10028638: bf1f itttt ne +1002863a: f50b 50e8 addne.w r0, fp, #7424 ; 0x1d00 +1002863e: 3048 addne r0, #72 ; 0x48 +10028640: 7a40 ldrbne r0, [r0, #9] +10028642: 2800 cmpne r0, #0 +10028644: d006 beq.n 10028654 +10028646: f641 5048 movw r0, #7496 ; 0x1d48 +1002864a: f641 31a4 movw r1, #7076 ; 0x1ba4 +1002864e: f850 000b ldr.w r0, [r0, fp] +10028652: 580f ldr r7, [r1, r0] +10028654: f8da 1078 ldr.w r1, [sl, #120] ; 0x78 +10028658: 2901 cmp r1, #1 +1002865a: f109 005c add.w r0, r9, #92 ; 0x5c +1002865e: f109 0602 add.w r6, r9, #2 +10028662: f040 80cc bne.w 100287fe +10028666: f000 f917 bl 10028898 <.text_105> +1002866a: 2000 movs r0, #0 +1002866c: f109 0110 add.w r1, r9, #16 +10028670: 7909 ldrb r1, [r1, #4] +10028672: b169 cbz r1, 10028690 +10028674: f899 2002 ldrb.w r2, [r9, #2] +10028678: b952 cbnz r2, 10028690 +1002867a: 1e49 subs r1, r1, #1 +1002867c: 2902 cmp r1, #2 +1002867e: d906 bls.n 1002868e +10028680: 1ec9 subs r1, r1, #3 +10028682: d002 beq.n 1002868a +10028684: 1e49 subs r1, r1, #1 +10028686: d002 beq.n 1002868e +10028688: e002 b.n 10028690 +1002868a: 2003 movs r0, #3 +1002868c: e000 b.n 10028690 +1002868e: 2001 movs r0, #1 +10028690: 6869 ldr r1, [r5, #4] +10028692: f421 0140 bic.w r1, r1, #12582912 ; 0xc00000 +10028696: ea41 5080 orr.w r0, r1, r0, lsl #22 +1002869a: 6068 str r0, [r5, #4] +1002869c: 7860 ldrb r0, [r4, #1] +1002869e: b328 cbz r0, 100286ec +100286a0: 2801 cmp r0, #1 +100286a2: d005 beq.n 100286b0 +100286a4: 2802 cmp r0, #2 +100286a6: d107 bne.n 100286b8 +100286a8: 68e8 ldr r0, [r5, #12] +100286aa: f440 6000 orr.w r0, r0, #2048 ; 0x800 +100286ae: e002 b.n 100286b6 +100286b0: 68e8 ldr r0, [r5, #12] +100286b2: f440 5040 orr.w r0, r0, #12288 ; 0x3000 +100286b6: 60e8 str r0, [r5, #12] +100286b8: 6928 ldr r0, [r5, #16] +100286ba: f020 50f8 bic.w r0, r0, #520093696 ; 0x1f000000 +100286be: f040 6000 orr.w r0, r0, #134217728 ; 0x8000000 +100286c2: f440 30f0 orr.w r0, r0, #122880 ; 0x1e000 +100286c6: 6128 str r0, [r5, #16] +100286c8: f89b 06a8 ldrb.w r0, [fp, #1704] ; 0x6a8 +100286cc: 2803 cmp r0, #3 +100286ce: d103 bne.n 100286d8 +100286d0: 6968 ldr r0, [r5, #20] +100286d2: f440 5080 orr.w r0, r0, #4096 ; 0x1000 +100286d6: 6168 str r0, [r5, #20] +100286d8: 7f20 ldrb r0, [r4, #28] +100286da: b138 cbz r0, 100286ec +100286dc: 4649 mov r1, r9 +100286de: 4658 mov r0, fp +100286e0: f7ff ff4f bl 10028582 +100286e4: 6969 ldr r1, [r5, #20] +100286e6: f360 3150 bfi r1, r0, #13, #4 +100286ea: 6169 str r1, [r5, #20] +100286ec: f648 018e movw r1, #34958 ; 0x888e +100286f0: 8870 ldrh r0, [r6, #2] +100286f2: 4288 cmp r0, r1 +100286f4: bf1c itt ne +100286f6: f640 0106 movwne r1, #2054 ; 0x806 +100286fa: 4288 cmpne r0, r1 +100286fc: d06f beq.n 100287de +100286fe: f648 01b4 movw r1, #34996 ; 0x88b4 +10028702: 4288 cmp r0, r1 +10028704: bf1c itt ne +10028706: 7870 ldrbne r0, [r6, #1] +10028708: 2801 cmpne r0, #1 +1002870a: d068 beq.n 100287de +1002870c: f899 005c ldrb.w r0, [r9, #92] ; 0x5c +10028710: 2801 cmp r0, #1 +10028712: 68a8 ldr r0, [r5, #8] +10028714: d10e bne.n 10028734 +10028716: f440 5080 orr.w r0, r0, #4096 ; 0x1000 +1002871a: 60a8 str r0, [r5, #8] +1002871c: 68e8 ldr r0, [r5, #12] +1002871e: f440 1078 orr.w r0, r0, #4063232 ; 0x3e0000 +10028722: 60e8 str r0, [r5, #12] +10028724: f642 101a movw r0, #10522 ; 0x291a +10028728: 68a9 ldr r1, [r5, #8] +1002872a: 5dc0 ldrb r0, [r0, r7] +1002872c: f360 5116 bfi r1, r0, #20, #3 +10028730: 60a9 str r1, [r5, #8] +10028732: e002 b.n 1002873a +10028734: f440 3080 orr.w r0, r0, #65536 ; 0x10000 +10028738: 60a8 str r0, [r5, #8] +1002873a: 7f20 ldrb r0, [r4, #28] +1002873c: b178 cbz r0, 1002875e +1002873e: 4649 mov r1, r9 +10028740: 4658 mov r0, fp +10028742: f7ff ff03 bl 1002854c +10028746: 6969 ldr r1, [r5, #20] +10028748: f360 1146 bfi r1, r0, #5, #2 +1002874c: 6169 str r1, [r5, #20] +1002874e: 4658 mov r0, fp +10028750: 4649 mov r1, r9 +10028752: f7ff ff16 bl 10028582 +10028756: 6969 ldr r1, [r5, #20] +10028758: f360 0103 bfi r1, r0, #0, #4 +1002875c: 6169 str r1, [r5, #20] +1002875e: 6928 ldr r0, [r5, #16] +10028760: f440 50f8 orr.w r0, r0, #7936 ; 0x1f00 +10028764: 6128 str r0, [r5, #16] +10028766: f641 103e movw r0, #6462 ; 0x193e +1002876a: 5dc0 ldrb r0, [r0, r7] +1002876c: b9c0 cbnz r0, 100287a0 +1002876e: f000 f929 bl 100289c4 <.text_109> +10028772: f641 1081 movw r0, #6529 ; 0x1981 +10028776: f899 103b ldrb.w r1, [r9, #59] ; 0x3b +1002877a: 19c9 adds r1, r1, r7 +1002877c: 5c41 ldrb r1, [r0, r1] +1002877e: 0609 lsls r1, r1, #24 +10028780: d503 bpl.n 1002878a +10028782: 6969 ldr r1, [r5, #20] +10028784: f041 0110 orr.w r1, r1, #16 +10028788: 6169 str r1, [r5, #20] +1002878a: f899 103b ldrb.w r1, [r9, #59] ; 0x3b +1002878e: 19c9 adds r1, r1, r7 +10028790: 5c40 ldrb r0, [r0, r1] +10028792: 6929 ldr r1, [r5, #16] +10028794: f000 007f and.w r0, r0, #127 ; 0x7f +10028798: 09c9 lsrs r1, r1, #7 +1002879a: ea40 10c1 orr.w r0, r0, r1, lsl #7 +1002879e: 6128 str r0, [r5, #16] +100287a0: f50b 50e8 add.w r0, fp, #7424 ; 0x1d00 +100287a4: 3048 adds r0, #72 ; 0x48 +100287a6: 7f00 ldrb r0, [r0, #28] +100287a8: 28ff cmp r0, #255 ; 0xff +100287aa: d05e beq.n 1002886a +100287ac: f000 f90a bl 100289c4 <.text_109> +100287b0: f50b 50e8 add.w r0, fp, #7424 ; 0x1d00 +100287b4: 3048 adds r0, #72 ; 0x48 +100287b6: 7f00 ldrb r0, [r0, #28] +100287b8: 0600 lsls r0, r0, #24 +100287ba: d503 bpl.n 100287c4 +100287bc: 6968 ldr r0, [r5, #20] +100287be: f040 0010 orr.w r0, r0, #16 +100287c2: 6168 str r0, [r5, #20] +100287c4: f50b 50e8 add.w r0, fp, #7424 ; 0x1d00 +100287c8: 3048 adds r0, #72 ; 0x48 +100287ca: 6929 ldr r1, [r5, #16] +100287cc: 7f00 ldrb r0, [r0, #28] +100287ce: f360 0106 bfi r1, r0, #0, #7 +100287d2: 6129 str r1, [r5, #16] +100287d4: 68e8 ldr r0, [r5, #12] +100287d6: f440 6080 orr.w r0, r0, #1024 ; 0x400 +100287da: 60e8 str r0, [r5, #12] +100287dc: e045 b.n 1002886a +100287de: 68a8 ldr r0, [r5, #8] +100287e0: f440 3080 orr.w r0, r0, #65536 ; 0x10000 +100287e4: 60a8 str r0, [r5, #8] +100287e6: f000 f8ed bl 100289c4 <.text_109> +100287ea: 9801 ldr r0, [sp, #4] +100287ec: f890 00b0 ldrb.w r0, [r0, #176] ; 0xb0 +100287f0: 2803 cmp r0, #3 +100287f2: d132 bne.n 1002885a +100287f4: 6968 ldr r0, [r5, #20] +100287f6: f040 0010 orr.w r0, r0, #16 +100287fa: 6168 str r0, [r5, #20] +100287fc: e02d b.n 1002885a +100287fe: 2903 cmp r1, #3 +10028800: d125 bne.n 1002884e +10028802: f899 103b ldrb.w r1, [r9, #59] ; 0x3b +10028806: 686a ldr r2, [r5, #4] +10028808: f361 0206 bfi r2, r1, #0, #7 +1002880c: 606a str r2, [r5, #4] +1002880e: 7901 ldrb r1, [r0, #4] +10028810: f361 220c bfi r2, r1, #8, #5 +10028814: 606a str r2, [r5, #4] +10028816: 7f61 ldrb r1, [r4, #29] +10028818: 686a ldr r2, [r5, #4] +1002881a: f361 4214 bfi r2, r1, #16, #5 +1002881e: 606a str r2, [r5, #4] +10028820: 88b1 ldrh r1, [r6, #4] +10028822: 6a6a ldr r2, [r5, #36] ; 0x24 +10028824: f361 3217 bfi r2, r1, #12, #12 +10028828: 626a str r2, [r5, #36] ; 0x24 +1002882a: 68e9 ldr r1, [r5, #12] +1002882c: f441 7180 orr.w r1, r1, #256 ; 0x100 +10028830: 60e9 str r1, [r5, #12] +10028832: 6929 ldr r1, [r5, #16] +10028834: f441 3100 orr.w r1, r1, #131072 ; 0x20000 +10028838: 6129 str r1, [r5, #16] +1002883a: 7a00 ldrb r0, [r0, #8] +1002883c: 6929 ldr r1, [r5, #16] +1002883e: 2801 cmp r0, #1 +10028840: bf0c ite eq +10028842: 2006 moveq r0, #6 +10028844: 200c movne r0, #12 +10028846: f360 4197 bfi r1, r0, #18, #6 +1002884a: 6129 str r1, [r5, #16] +1002884c: e005 b.n 1002885a +1002884e: 2908 cmp r1, #8 +10028850: d00b beq.n 1002886a +10028852: f000 f821 bl 10028898 <.text_105> +10028856: f000 f8b5 bl 100289c4 <.text_109> +1002885a: f898 0337 ldrb.w r0, [r8, #823] ; 0x337 +1002885e: f7fe f871 bl 10026944 +10028862: 6929 ldr r1, [r5, #16] +10028864: f360 0106 bfi r1, r0, #0, #7 +10028868: 6129 str r1, [r5, #16] +1002886a: 6828 ldr r0, [r5, #0] +1002886c: f8d9 1010 ldr.w r1, [r9, #16] +10028870: f000 407f and.w r0, r0, #4278190080 ; 0xff000000 +10028874: b289 uxth r1, r1 +10028876: 4308 orrs r0, r1 +10028878: f440 1020 orr.w r0, r0, #2621440 ; 0x280000 +1002887c: 6028 str r0, [r5, #0] +1002887e: 9900 ldr r1, [sp, #0] +10028880: b111 cbz r1, 10028888 +10028882: f040 7080 orr.w r0, r0, #16777216 ; 0x1000000 +10028886: 6028 str r0, [r5, #0] +10028888: 7ee0 ldrb r0, [r4, #27] +1002888a: b918 cbnz r0, 10028894 +1002888c: 6a28 ldr r0, [r5, #32] +1002888e: f440 4000 orr.w r0, r0, #32768 ; 0x8000 +10028892: 6228 str r0, [r5, #32] +10028894: e8bd 8ff7 ldmia.w sp!, {r0, r1, r2, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +10028898 <.text_105>: +10028898: f899 103b ldrb.w r1, [r9, #59] ; 0x3b +1002889c: 686a ldr r2, [r5, #4] +1002889e: f361 0206 bfi r2, r1, #0, #7 +100288a2: 606a str r2, [r5, #4] +100288a4: 7f61 ldrb r1, [r4, #29] +100288a6: f361 4214 bfi r2, r1, #16, #5 +100288aa: 606a str r2, [r5, #4] +100288ac: 7900 ldrb r0, [r0, #4] +100288ae: 6869 ldr r1, [r5, #4] +100288b0: f360 210c bfi r1, r0, #8, #5 +100288b4: 6069 str r1, [r5, #4] +100288b6: 88b0 ldrh r0, [r6, #4] +100288b8: 6a69 ldr r1, [r5, #36] ; 0x24 +100288ba: f360 3117 bfi r1, r0, #12, #12 +100288be: 6269 str r1, [r5, #36] ; 0x24 +100288c0: 4770 bx lr + +100288c2 <.text_106>: +100288c2: 2228 movs r2, #40 ; 0x28 +100288c4: 2100 movs r1, #0 +100288c6: 4628 mov r0, r5 +100288c8: f7e7 bfb6 b.w 10010838 + +100288cc : +100288cc: b510 push {r4, lr} +100288ce: 460c mov r4, r1 +100288d0: f7ff fe94 bl 100285fc +100288d4: 6820 ldr r0, [r4, #0] +100288d6: 6020 str r0, [r4, #0] +100288d8: 6860 ldr r0, [r4, #4] +100288da: 6060 str r0, [r4, #4] +100288dc: 68a0 ldr r0, [r4, #8] +100288de: 60a0 str r0, [r4, #8] +100288e0: 68e0 ldr r0, [r4, #12] +100288e2: 60e0 str r0, [r4, #12] +100288e4: 6920 ldr r0, [r4, #16] +100288e6: 6120 str r0, [r4, #16] +100288e8: 6960 ldr r0, [r4, #20] +100288ea: 6160 str r0, [r4, #20] +100288ec: 69a0 ldr r0, [r4, #24] +100288ee: 61a0 str r0, [r4, #24] +100288f0: 69e0 ldr r0, [r4, #28] +100288f2: 61e0 str r0, [r4, #28] +100288f4: 6a20 ldr r0, [r4, #32] +100288f6: 6220 str r0, [r4, #32] +100288f8: 6a60 ldr r0, [r4, #36] ; 0x24 +100288fa: 6260 str r0, [r4, #36] ; 0x24 +100288fc: bd10 pop {r4, pc} + +100288fe : +100288fe: b5f8 push {r3, r4, r5, r6, r7, lr} +10028900: 4604 mov r4, r0 +10028902: 460d mov r5, r1 +10028904: 4616 mov r6, r2 +10028906: 461f mov r7, r3 +10028908: f7ff ffdb bl 100288c2 <.text_106> +1002890c: 6828 ldr r0, [r5, #0] +1002890e: f040 6000 orr.w r0, r0, #134217728 ; 0x8000000 +10028912: 6028 str r0, [r5, #0] +10028914: b2b1 uxth r1, r6 +10028916: f040 6080 orr.w r0, r0, #67108864 ; 0x4000000 +1002891a: 6028 str r0, [r5, #0] +1002891c: f420 007f bic.w r0, r0, #16711680 ; 0xff0000 +10028920: f440 1020 orr.w r0, r0, #2621440 ; 0x280000 +10028924: 6028 str r0, [r5, #0] +10028926: 0c00 lsrs r0, r0, #16 +10028928: ea41 4000 orr.w r0, r1, r0, lsl #16 +1002892c: 6028 str r0, [r5, #0] +1002892e: 2f01 cmp r7, #1 +10028930: 6868 ldr r0, [r5, #4] +10028932: f420 50f8 bic.w r0, r0, #7936 ; 0x1f00 +10028936: f440 5090 orr.w r0, r0, #4608 ; 0x1200 +1002893a: 6068 str r0, [r5, #4] +1002893c: d103 bne.n 10028946 +1002893e: 68e8 ldr r0, [r5, #12] +10028940: f440 4000 orr.w r0, r0, #32768 ; 0x8000 +10028944: e006 b.n 10028954 +10028946: 6a28 ldr r0, [r5, #32] +10028948: f440 4000 orr.w r0, r0, #32768 ; 0x8000 +1002894c: 6228 str r0, [r5, #32] +1002894e: 68e8 ldr r0, [r5, #12] +10028950: f020 00c0 bic.w r0, r0, #192 ; 0xc0 +10028954: 60e8 str r0, [r5, #12] +10028956: 9806 ldr r0, [sp, #24] +10028958: 2801 cmp r0, #1 +1002895a: d103 bne.n 10028964 +1002895c: 68a8 ldr r0, [r5, #8] +1002895e: f440 0000 orr.w r0, r0, #8388608 ; 0x800000 +10028962: 60a8 str r0, [r5, #8] +10028964: f000 f82e bl 100289c4 <.text_109> +10028968: 6828 ldr r0, [r5, #0] +1002896a: f040 4000 orr.w r0, r0, #2147483648 ; 0x80000000 +1002896e: 6028 str r0, [r5, #0] +10028970: 6928 ldr r0, [r5, #16] +10028972: 09c0 lsrs r0, r0, #7 +10028974: 01c0 lsls r0, r0, #7 +10028976: 6128 str r0, [r5, #16] +10028978: 9807 ldr r0, [sp, #28] +1002897a: 2801 cmp r0, #1 +1002897c: d121 bne.n 100289c2 +1002897e: f241 10f4 movw r0, #4596 ; 0x11f4 +10028982: 5900 ldr r0, [r0, r4] +10028984: 2801 cmp r0, #1 +10028986: bf18 it ne +10028988: 2802 cmpne r0, #2 +1002898a: d006 beq.n 1002899a +1002898c: 2804 cmp r0, #4 +1002898e: d010 beq.n 100289b2 +10028990: 2805 cmp r0, #5 +10028992: d002 beq.n 1002899a +10028994: 2806 cmp r0, #6 +10028996: d006 beq.n 100289a6 +10028998: e00f b.n 100289ba +1002899a: 6868 ldr r0, [r5, #4] +1002899c: f420 0040 bic.w r0, r0, #12582912 ; 0xc00000 +100289a0: f440 0080 orr.w r0, r0, #4194304 ; 0x400000 +100289a4: e00c b.n 100289c0 +100289a6: 6868 ldr r0, [r5, #4] +100289a8: f420 0040 bic.w r0, r0, #12582912 ; 0xc00000 +100289ac: f440 0000 orr.w r0, r0, #8388608 ; 0x800000 +100289b0: e006 b.n 100289c0 +100289b2: 6868 ldr r0, [r5, #4] +100289b4: f440 0040 orr.w r0, r0, #12582912 ; 0xc00000 +100289b8: e002 b.n 100289c0 +100289ba: 6868 ldr r0, [r5, #4] +100289bc: f420 0040 bic.w r0, r0, #12582912 ; 0xc00000 +100289c0: 6068 str r0, [r5, #4] +100289c2: bdf1 pop {r0, r4, r5, r6, r7, pc} + +100289c4 <.text_109>: +100289c4: 68e8 ldr r0, [r5, #12] +100289c6: f440 7080 orr.w r0, r0, #256 ; 0x100 +100289ca: 60e8 str r0, [r5, #12] +100289cc: 4770 bx lr + +100289ce : +100289ce: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +100289d2: 4604 mov r4, r0 +100289d4: f641 5052 movw r0, #7506 ; 0x1d52 +100289d8: b087 sub sp, #28 +100289da: 5d00 ldrb r0, [r0, r4] +100289dc: 7815 ldrb r5, [r2, #0] +100289de: f8df 8c24 ldr.w r8, [pc, #3108] ; 10029604 <.text_146> +100289e2: f8df 6c24 ldr.w r6, [pc, #3108] ; 10029608 <.text_147> +100289e6: f8df 7c24 ldr.w r7, [pc, #3108] ; 1002960c <.text_148> +100289ea: 2801 cmp r0, #1 +100289ec: f240 69a4 movw r9, #1700 ; 0x6a4 +100289f0: f64f 7aff movw sl, #65535 ; 0xffff +100289f4: f240 5b51 movw fp, #1361 ; 0x551 +100289f8: d16c bne.n 10028ad4 +100289fa: 4659 mov r1, fp +100289fc: f000 fa48 bl 10028e90 <.text_130+0x4> +10028a00: f040 0210 orr.w r2, r0, #16 +10028a04: 4659 mov r1, fp +10028a06: f000 f8e4 bl 10028bd2 <.text_115+0x4> +10028a0a: f44f 7181 mov.w r1, #258 ; 0x102 +10028a0e: f000 fa3f bl 10028e90 <.text_130+0x4> +10028a12: f000 0003 and.w r0, r0, #3 +10028a16: ea40 0285 orr.w r2, r0, r5, lsl #2 +10028a1a: b2d2 uxtb r2, r2 +10028a1c: f44f 7181 mov.w r1, #258 ; 0x102 +10028a20: f000 f8d7 bl 10028bd2 <.text_115+0x4> +10028a24: 2d02 cmp r5, #2 +10028a26: bf18 it ne +10028a28: 2d00 cmpne r5, #0 +10028a2a: d109 bne.n 10028a40 +10028a2c: f000 f8cb bl 10028bc6 <.text_114> +10028a30: b920 cbnz r0, 10028a3c +10028a32: 4620 mov r0, r4 +10028a34: f7ff f8ba bl 10027bac +10028a38: f000 f8dc bl 10028bf4 <.text_117> +10028a3c: 2211 movs r2, #17 +10028a3e: e0b5 b.n 10028bac +10028a40: 2d01 cmp r5, #1 +10028a42: d103 bne.n 10028a4c +10028a44: f000 f8bc bl 10028bc0 <.text_113> +10028a48: 221a movs r2, #26 +10028a4a: e0af b.n 10028bac +10028a4c: 2d03 cmp r5, #3 +10028a4e: d16a bne.n 10028b26 +10028a50: f000 f8c2 bl 10028bd8 <.text_116> +10028a54: f000 f8b4 bl 10028bc0 <.text_113> +10028a58: 2212 movs r2, #18 +10028a5a: 4659 mov r1, fp +10028a5c: f000 f8b9 bl 10028bd2 <.text_115+0x4> +10028a60: f000 fa07 bl 10028e72 <.text_127> +10028a64: 4652 mov r2, sl +10028a66: 4649 mov r1, r9 +10028a68: f000 fa0d bl 10028e86 <.text_129> +10028a6c: f44f 6280 mov.w r2, #1024 ; 0x400 +10028a70: f240 61a2 movw r1, #1698 ; 0x6a2 +10028a74: f000 fa07 bl 10028e86 <.text_129> +10028a78: 2202 movs r2, #2 +10028a7a: f240 5159 movw r1, #1369 ; 0x559 +10028a7e: f000 f8a8 bl 10028bd2 <.text_115+0x4> +10028a82: 220a movs r2, #10 +10028a84: f44f 61ae mov.w r1, #1392 ; 0x570 +10028a88: f000 f8a3 bl 10028bd2 <.text_115+0x4> +10028a8c: 2200 movs r2, #0 +10028a8e: f44f 61a2 mov.w r1, #1296 ; 0x510 +10028a92: f000 f9f8 bl 10028e86 <.text_129> +10028a96: f000 f9f2 bl 10028e7e <.text_128> +10028a9a: f647 72ff movw r2, #32767 ; 0x7fff +10028a9e: f44f 61a3 mov.w r1, #1304 ; 0x518 +10028aa2: f000 f9f0 bl 10028e86 <.text_129> +10028aa6: 2202 movs r2, #2 +10028aa8: f240 5153 movw r1, #1363 ; 0x553 +10028aac: f000 f891 bl 10028bd2 <.text_115+0x4> +10028ab0: 221e movs r2, #30 +10028ab2: 4659 mov r1, fp +10028ab4: f000 f88d bl 10028bd2 <.text_115+0x4> +10028ab8: f000 f87e bl 10028bb8 <.text_112> +10028abc: b128 cbz r0, 10028aca +10028abe: f000 f9e5 bl 10028e8c <.text_130> +10028ac2: f000 02f7 and.w r2, r0, #247 ; 0xf7 +10028ac6: f000 f882 bl 10028bce <.text_115> +10028aca: f000 f9df bl 10028e8c <.text_130> +10028ace: f040 0201 orr.w r2, r0, #1 +10028ad2: e024 b.n 10028b1e +10028ad4: f000 f9da bl 10028e8c <.text_130> +10028ad8: f040 0210 orr.w r2, r0, #16 +10028adc: f000 f877 bl 10028bce <.text_115> +10028ae0: f44f 7181 mov.w r1, #258 ; 0x102 +10028ae4: f000 f9d4 bl 10028e90 <.text_130+0x4> +10028ae8: f000 000c and.w r0, r0, #12 +10028aec: ea45 0200 orr.w r2, r5, r0 +10028af0: f44f 7181 mov.w r1, #258 ; 0x102 +10028af4: f000 f86d bl 10028bd2 <.text_115+0x4> +10028af8: 2d02 cmp r5, #2 +10028afa: bf18 it ne +10028afc: 2d00 cmpne r5, #0 +10028afe: d109 bne.n 10028b14 +10028b00: f000 f861 bl 10028bc6 <.text_114> +10028b04: b920 cbnz r0, 10028b10 +10028b06: 4620 mov r0, r4 +10028b08: f7ff f850 bl 10027bac +10028b0c: f000 f872 bl 10028bf4 <.text_117> +10028b10: 2219 movs r2, #25 +10028b12: e004 b.n 10028b1e +10028b14: 2d01 cmp r5, #1 +10028b16: d105 bne.n 10028b24 +10028b18: f000 f852 bl 10028bc0 <.text_113> +10028b1c: 221a movs r2, #26 +10028b1e: f44f 61aa mov.w r1, #1360 ; 0x550 +10028b22: e044 b.n 10028bae +10028b24: 2d03 cmp r5, #3 +10028b26: d144 bne.n 10028bb2 <.text_111> +10028b28: f000 f856 bl 10028bd8 <.text_116> +10028b2c: f000 f848 bl 10028bc0 <.text_113> +10028b30: 2212 movs r2, #18 +10028b32: f000 f84c bl 10028bce <.text_115> +10028b36: f000 f99c bl 10028e72 <.text_127> +10028b3a: 4652 mov r2, sl +10028b3c: 4649 mov r1, r9 +10028b3e: f000 f9a2 bl 10028e86 <.text_129> +10028b42: f44f 6280 mov.w r2, #1024 ; 0x400 +10028b46: f240 61a2 movw r1, #1698 ; 0x6a2 +10028b4a: f000 f99c bl 10028e86 <.text_129> +10028b4e: 2202 movs r2, #2 +10028b50: f240 5159 movw r1, #1369 ; 0x559 +10028b54: f000 f83d bl 10028bd2 <.text_115+0x4> +10028b58: 220a movs r2, #10 +10028b5a: f240 515a movw r1, #1370 ; 0x55a +10028b5e: f000 f838 bl 10028bd2 <.text_115+0x4> +10028b62: 2200 movs r2, #0 +10028b64: f44f 61a2 mov.w r1, #1296 ; 0x510 +10028b68: f000 f98d bl 10028e86 <.text_129> +10028b6c: f000 f987 bl 10028e7e <.text_128> +10028b70: f647 72ff movw r2, #32767 ; 0x7fff +10028b74: f44f 61a3 mov.w r1, #1304 ; 0x518 +10028b78: f000 f985 bl 10028e86 <.text_129> +10028b7c: 2201 movs r2, #1 +10028b7e: f240 5153 movw r1, #1363 ; 0x553 +10028b82: f000 f826 bl 10028bd2 <.text_115+0x4> +10028b86: 221e movs r2, #30 +10028b88: f000 f821 bl 10028bce <.text_115> +10028b8c: f000 f814 bl 10028bb8 <.text_112> +10028b90: b138 cbz r0, 10028ba2 +10028b92: 4659 mov r1, fp +10028b94: f000 f97c bl 10028e90 <.text_130+0x4> +10028b98: f000 02f7 and.w r2, r0, #247 ; 0xf7 +10028b9c: 4659 mov r1, fp +10028b9e: f000 f818 bl 10028bd2 <.text_115+0x4> +10028ba2: 4659 mov r1, fp +10028ba4: f000 f974 bl 10028e90 <.text_130+0x4> +10028ba8: f040 0201 orr.w r2, r0, #1 +10028bac: 4659 mov r1, fp +10028bae: f000 f810 bl 10028bd2 <.text_115+0x4> + +10028bb2 <.text_111>: +10028bb2: b007 add sp, #28 +10028bb4: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +10028bb8 <.text_112>: +10028bb8: 2100 movs r1, #0 +10028bba: 4620 mov r0, r4 +10028bbc: f7f6 be47 b.w 1001f84e + +10028bc0 <.text_113>: +10028bc0: 4620 mov r0, r4 +10028bc2: f7fe bfd8 b.w 10027b76 + +10028bc6 <.text_114>: +10028bc6: 2103 movs r1, #3 +10028bc8: 4620 mov r0, r4 +10028bca: f7f5 b974 b.w 1001deb6 + +10028bce <.text_115>: +10028bce: f44f 61aa mov.w r1, #1360 ; 0x550 +10028bd2: 4620 mov r0, r4 +10028bd4: f7fc b83c b.w 10024c50 + +10028bd8 <.text_116>: +10028bd8: a803 add r0, sp, #12 +10028bda: 9703 str r7, [sp, #12] +10028bdc: 6046 str r6, [r0, #4] +10028bde: 2100 movs r1, #0 +10028be0: 6081 str r1, [r0, #8] +10028be2: a800 add r0, sp, #0 +10028be4: 9100 str r1, [sp, #0] +10028be6: 6041 str r1, [r0, #4] +10028be8: 6081 str r1, [r0, #8] +10028bea: aa00 add r2, sp, #0 +10028bec: a903 add r1, sp, #12 +10028bee: 4620 mov r0, r4 +10028bf0: f7f8 bc18 b.w 10021424 + +10028bf4 <.text_117>: +10028bf4: 2000 movs r0, #0 +10028bf6: 9000 str r0, [sp, #0] +10028bf8: 2100 movs r1, #0 +10028bfa: a800 add r0, sp, #0 +10028bfc: 6041 str r1, [r0, #4] +10028bfe: 6081 str r1, [r0, #8] +10028c00: a803 add r0, sp, #12 +10028c02: 9703 str r7, [sp, #12] +10028c04: 6046 str r6, [r0, #4] +10028c06: 6081 str r1, [r0, #8] +10028c08: aa03 add r2, sp, #12 +10028c0a: a900 add r1, sp, #0 +10028c0c: 4620 mov r0, r4 +10028c0e: f7f8 bc09 b.w 10021424 + +10028c12 : +10028c12: e92d 4ef0 stmdb sp!, {r4, r5, r6, r7, r9, sl, fp, lr} +10028c16: 4606 mov r6, r0 +10028c18: f506 649d add.w r4, r6, #1256 ; 0x4e8 +10028c1c: f504 7788 add.w r7, r4, #272 ; 0x110 +10028c20: 2300 movs r3, #0 +10028c22: f8b7 00aa ldrh.w r0, [r7, #170] ; 0xaa +10028c26: 0282 lsls r2, r0, #10 +10028c28: e9d4 01d0 ldrd r0, r1, [r4, #832] ; 0x340 +10028c2c: f7e7 ff43 bl 10010ab6 +10028c30: e9d4 23d0 ldrd r2, r3, [r4, #832] ; 0x340 +10028c34: 1a10 subs r0, r2, r0 +10028c36: eb63 0101 sbc.w r1, r3, r1 +10028c3a: f5b0 6480 subs.w r4, r0, #1024 ; 0x400 +10028c3e: 6838 ldr r0, [r7, #0] +10028c40: f161 0500 sbc.w r5, r1, #0 +10028c44: f000 0103 and.w r1, r0, #3 +10028c48: 2901 cmp r1, #1 +10028c4a: bf19 ittee ne +10028c4c: f000 0003 andne.w r0, r0, #3 +10028c50: 2803 cmpne r0, #3 +10028c52: 4630 moveq r0, r6 +10028c54: f7fe ffaa bleq 10027bac +10028c58: f641 5052 movw r0, #7506 ; 0x1d52 +10028c5c: f240 5964 movw r9, #1380 ; 0x564 +10028c60: 5d80 ldrb r0, [r0, r6] +10028c62: 2801 cmp r0, #1 +10028c64: f240 5b6c movw fp, #1388 ; 0x56c +10028c68: f240 5a51 movw sl, #1361 ; 0x551 +10028c6c: d12d bne.n 10028cca +10028c6e: 4651 mov r1, sl +10028c70: f000 f870 bl 10028d54 <.text_121+0x4> +10028c74: f000 02f7 and.w r2, r0, #247 ; 0xf7 +10028c78: 4651 mov r1, sl +10028c7a: f000 f866 bl 10028d4a <.text_120> +10028c7e: f000 f87c bl 10028d7a <.text_125> +10028c82: f000 f86f bl 10028d64 <.text_123> +10028c86: 4651 mov r1, sl +10028c88: f000 f864 bl 10028d54 <.text_121+0x4> +10028c8c: f040 0208 orr.w r2, r0, #8 +10028c90: 4651 mov r1, sl +10028c92: f000 f85a bl 10028d4a <.text_120> +10028c96: 7838 ldrb r0, [r7, #0] +10028c98: f000 0003 and.w r0, r0, #3 +10028c9c: 2802 cmp r0, #2 +10028c9e: d140 bne.n 10028d22 +10028ca0: 2110 movs r1, #16 +10028ca2: 4630 mov r0, r6 +10028ca4: f7f6 fdd3 bl 1001f84e +10028ca8: 2800 cmp r0, #0 +10028caa: d03a beq.n 10028d22 +10028cac: f000 f850 bl 10028d50 <.text_121> +10028cb0: f000 f847 bl 10028d42 <.text_119> +10028cb4: f000 f85b bl 10028d6e <.text_124> +10028cb8: f000 f84f bl 10028d5a <.text_122> +10028cbc: f000 f848 bl 10028d50 <.text_121> +10028cc0: f040 0208 orr.w r2, r0, #8 +10028cc4: f44f 61aa mov.w r1, #1360 ; 0x550 +10028cc8: e029 b.n 10028d1e +10028cca: f000 f841 bl 10028d50 <.text_121> +10028cce: f000 f838 bl 10028d42 <.text_119> +10028cd2: f000 f84c bl 10028d6e <.text_124> +10028cd6: f000 f840 bl 10028d5a <.text_122> +10028cda: f000 f839 bl 10028d50 <.text_121> +10028cde: f040 0208 orr.w r2, r0, #8 +10028ce2: f000 f830 bl 10028d46 <.text_119+0x4> +10028ce6: 7838 ldrb r0, [r7, #0] +10028ce8: f000 0003 and.w r0, r0, #3 +10028cec: 2802 cmp r0, #2 +10028cee: d118 bne.n 10028d22 +10028cf0: 2110 movs r1, #16 +10028cf2: 4630 mov r0, r6 +10028cf4: f7f6 fdab bl 1001f84e +10028cf8: b198 cbz r0, 10028d22 +10028cfa: 4651 mov r1, sl +10028cfc: f000 f82a bl 10028d54 <.text_121+0x4> +10028d00: f000 02f7 and.w r2, r0, #247 ; 0xf7 +10028d04: 4651 mov r1, sl +10028d06: f000 f820 bl 10028d4a <.text_120> +10028d0a: f000 f836 bl 10028d7a <.text_125> +10028d0e: f000 f829 bl 10028d64 <.text_123> +10028d12: 4651 mov r1, sl +10028d14: f000 f81e bl 10028d54 <.text_121+0x4> +10028d18: f040 0208 orr.w r2, r0, #8 +10028d1c: 4651 mov r1, sl +10028d1e: f000 f814 bl 10028d4a <.text_120> +10028d22: 6838 ldr r0, [r7, #0] +10028d24: f000 0103 and.w r1, r0, #3 +10028d28: 2901 cmp r1, #1 +10028d2a: bf1c itt ne +10028d2c: f000 0003 andne.w r0, r0, #3 +10028d30: 2803 cmpne r0, #3 +10028d32: d104 bne.n 10028d3e +10028d34: 4630 mov r0, r6 +10028d36: e8bd 4ef0 ldmia.w sp!, {r4, r5, r6, r7, r9, sl, fp, lr} +10028d3a: f7fe bf1c b.w 10027b76 +10028d3e: e8bd 8ef0 ldmia.w sp!, {r4, r5, r6, r7, r9, sl, fp, pc} + +10028d42 <.text_119>: +10028d42: f000 02f7 and.w r2, r0, #247 ; 0xf7 +10028d46: f44f 61aa mov.w r1, #1360 ; 0x550 + +10028d4a <.text_120>: +10028d4a: 4630 mov r0, r6 +10028d4c: f7fb bf80 b.w 10024c50 + +10028d50 <.text_121>: +10028d50: f44f 61aa mov.w r1, #1360 ; 0x550 +10028d54: 4630 mov r0, r6 +10028d56: f7fb bf69 b.w 10024c2c + +10028d5a <.text_122>: +10028d5a: 462a mov r2, r5 +10028d5c: 4649 mov r1, r9 +10028d5e: 4630 mov r0, r6 +10028d60: f7fb bf86 b.w 10024c70 + +10028d64 <.text_123>: +10028d64: 462a mov r2, r5 +10028d66: 4659 mov r1, fp +10028d68: 4630 mov r0, r6 +10028d6a: f7fb bf81 b.w 10024c70 + +10028d6e <.text_124>: +10028d6e: 4622 mov r2, r4 +10028d70: f44f 61ac mov.w r1, #1376 ; 0x560 +10028d74: 4630 mov r0, r6 +10028d76: f7fb bf7b b.w 10024c70 + +10028d7a <.text_125>: +10028d7a: 4622 mov r2, r4 +10028d7c: f44f 61ad mov.w r1, #1384 ; 0x568 +10028d80: 4630 mov r0, r6 +10028d82: f7fb bf75 b.w 10024c70 + +10028d86 : +10028d86: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +10028d8a: f000 f888 bl 10028e9e <.text_132> +10028d8e: f104 0a0c add.w sl, r4, #12 +10028d92: 5906 ldr r6, [r0, r4] +10028d94: f641 5052 movw r0, #7506 ; 0x1d52 +10028d98: 4615 mov r5, r2 +10028d9a: 5d00 ldrb r0, [r0, r4] +10028d9c: 2801 cmp r0, #1 +10028d9e: bf0c ite eq +10028da0: f240 5851 movweq r8, #1361 ; 0x551 +10028da4: f44f 68aa movne.w r8, #1360 ; 0x550 +10028da8: 2110 movs r1, #16 +10028daa: f000 f875 bl 10028e98 <.text_131+0x2> +10028dae: 2801 cmp r0, #1 +10028db0: d002 beq.n 10028db8 +10028db2: 2110 movs r1, #16 +10028db4: f7ff ff01 bl 10028bba <.text_112+0x2> +10028db8: f000 fb8f bl 100294da <.text_141> +10028dbc: 4681 mov r9, r0 +10028dbe: 7828 ldrb r0, [r5, #0] +10028dc0: f641 1748 movw r7, #6472 ; 0x1948 +10028dc4: f240 6ba4 movw fp, #1700 ; 0x6a4 +10028dc8: b328 cbz r0, 10028e16 +10028dca: f029 0280 bic.w r2, r9, #128 ; 0x80 +10028dce: f000 f851 bl 10028e74 <.text_127+0x2> +10028dd2: 2200 movs r2, #0 +10028dd4: 4659 mov r1, fp +10028dd6: f000 f856 bl 10028e86 <.text_129> +10028dda: f000 f85c bl 10028e96 <.text_131> +10028dde: b138 cbz r0, 10028df0 +10028de0: 4641 mov r1, r8 +10028de2: f000 f855 bl 10028e90 <.text_130+0x4> +10028de6: f040 0210 orr.w r2, r0, #16 +10028dea: 4641 mov r1, r8 +10028dec: f7ff fef1 bl 10028bd2 <.text_115+0x4> +10028df0: f44f 6188 mov.w r1, #1088 ; 0x440 +10028df4: 4620 mov r0, r4 +10028df6: f7fb ff1f bl 10024c38 +10028dfa: 53b8 strh r0, [r7, r6] +10028dfc: f7ff fee3 bl 10028bc6 <.text_114> +10028e00: 2800 cmp r0, #0 +10028e02: d034 beq.n 10028e6e +10028e04: f000 f8d2 bl 10028fac <.text_134> +10028e08: 2800 cmp r0, #0 +10028e0a: d030 beq.n 10028e6e +10028e0c: 4620 mov r0, r4 +10028e0e: e8bd 4ff2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, sl, fp, lr} +10028e12: f7fe becb b.w 10027bac +10028e16: 2111 movs r1, #17 +10028e18: f000 f83e bl 10028e98 <.text_131+0x2> +10028e1c: b918 cbnz r0, 10028e26 +10028e1e: 2111 movs r1, #17 +10028e20: f7ff fecb bl 10028bba <.text_112+0x2> +10028e24: b120 cbz r0, 10028e30 +10028e26: f64f 72ff movw r2, #65535 ; 0xffff +10028e2a: 4659 mov r1, fp +10028e2c: f000 f82b bl 10028e86 <.text_129> +10028e30: f000 f831 bl 10028e96 <.text_131> +10028e34: b138 cbz r0, 10028e46 +10028e36: 4641 mov r1, r8 +10028e38: f000 f82a bl 10028e90 <.text_130+0x4> +10028e3c: f000 02ef and.w r2, r0, #239 ; 0xef +10028e40: 4641 mov r1, r8 +10028e42: f7ff fec6 bl 10028bd2 <.text_115+0x4> +10028e46: f049 0280 orr.w r2, r9, #128 ; 0x80 +10028e4a: f000 f813 bl 10028e74 <.text_127+0x2> +10028e4e: 5bba ldrh r2, [r7, r6] +10028e50: f44f 6188 mov.w r1, #1088 ; 0x440 +10028e54: f000 f817 bl 10028e86 <.text_129> +10028e58: f7ff feb5 bl 10028bc6 <.text_114> +10028e5c: b138 cbz r0, 10028e6e +10028e5e: f000 f8a5 bl 10028fac <.text_134> +10028e62: b120 cbz r0, 10028e6e +10028e64: 4620 mov r0, r4 +10028e66: e8bd 4ff2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, sl, fp, lr} +10028e6a: f7fe be84 b.w 10027b76 +10028e6e: e8bd 8ff1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +10028e72 <.text_127>: +10028e72: 4642 mov r2, r8 +10028e74: f44f 61c1 mov.w r1, #1544 ; 0x608 +10028e78: 4620 mov r0, r4 +10028e7a: f7fb bef9 b.w 10024c70 + +10028e7e <.text_128>: +10028e7e: f64f 7204 movw r2, #65284 ; 0xff04 +10028e82: f44f 61a8 mov.w r1, #1344 ; 0x540 + +10028e86 <.text_129>: +10028e86: 4620 mov r0, r4 +10028e88: f7fb beea b.w 10024c60 + +10028e8c <.text_130>: +10028e8c: f44f 61aa mov.w r1, #1360 ; 0x550 +10028e90: 4620 mov r0, r4 +10028e92: f7fb becb b.w 10024c2c + +10028e96 <.text_131>: +10028e96: 2168 movs r1, #104 ; 0x68 +10028e98: 4650 mov r0, sl +10028e9a: f7fe ba05 b.w 100272a8 + +10028e9e <.text_132>: +10028e9e: 4604 mov r4, r0 +10028ea0: f641 30a4 movw r0, #7076 ; 0x1ba4 +10028ea4: 4770 bx lr + +10028ea6 : +10028ea6: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +10028eaa: 4604 mov r4, r0 +10028eac: 7810 ldrb r0, [r2, #0] +10028eae: f504 57c8 add.w r7, r4, #6400 ; 0x1900 +10028eb2: 2530 movs r5, #48 ; 0x30 +10028eb4: f104 060c add.w r6, r4, #12 +10028eb8: 3794 adds r7, #148 ; 0x94 +10028eba: f240 68a4 movw r8, #1700 ; 0x6a4 +10028ebe: bb50 cbnz r0, 10028f16 +10028ec0: f7ff fe81 bl 10028bc6 <.text_114> +10028ec4: b128 cbz r0, 10028ed2 +10028ec6: f000 f871 bl 10028fac <.text_134> +10028eca: b110 cbz r0, 10028ed2 +10028ecc: 4620 mov r0, r4 +10028ece: f7fe fe6d bl 10027bac +10028ed2: f64f 72ff movw r2, #65535 ; 0xffff +10028ed6: 4641 mov r1, r8 +10028ed8: f7ff ffd5 bl 10028e86 <.text_129> +10028edc: f7ff fe73 bl 10028bc6 <.text_114> +10028ee0: 2800 cmp r0, #0 +10028ee2: f44f 61c1 mov.w r1, #1544 ; 0x608 +10028ee6: 4620 mov r0, r4 +10028ee8: d004 beq.n 10028ef4 +10028eea: f7fb feab bl 10024c44 +10028eee: f040 0280 orr.w r2, r0, #128 ; 0x80 +10028ef2: e003 b.n 10028efc +10028ef4: f7fb fea6 bl 10024c44 +10028ef8: f040 02c0 orr.w r2, r0, #192 ; 0xc0 +10028efc: f7ff ffba bl 10028e74 <.text_127+0x2> +10028f00: 2108 movs r1, #8 +10028f02: 4630 mov r0, r6 +10028f04: f7fe f9d0 bl 100272a8 +10028f08: 2801 cmp r0, #1 +10028f0a: d102 bne.n 10028f12 +10028f0c: 8978 ldrh r0, [r7, #10] +10028f0e: 2812 cmp r0, #18 +10028f10: d143 bne.n 10028f9a +10028f12: 2507 movs r5, #7 +10028f14: e041 b.n 10028f9a +10028f16: 2801 cmp r0, #1 +10028f18: d10f bne.n 10028f3a +10028f1a: 2100 movs r1, #0 +10028f1c: f7ff fe54 bl 10028bc8 <.text_114+0x2> +10028f20: b118 cbz r0, 10028f2a +10028f22: 2200 movs r2, #0 +10028f24: 4641 mov r1, r8 +10028f26: f7ff ffae bl 10028e86 <.text_129> +10028f2a: f7ff fe4c bl 10028bc6 <.text_114> +10028f2e: 2800 cmp r0, #0 +10028f30: d033 beq.n 10028f9a +10028f32: f000 f83b bl 10028fac <.text_134> +10028f36: bb48 cbnz r0, 10028f8c +10028f38: e02f b.n 10028f9a +10028f3a: 2802 cmp r0, #2 +10028f3c: d12d bne.n 10028f9a +10028f3e: f641 5052 movw r0, #7506 ; 0x1d52 +10028f42: 5d00 ldrb r0, [r0, r4] +10028f44: 2801 cmp r0, #1 +10028f46: d108 bne.n 10028f5a +10028f48: f240 5751 movw r7, #1361 ; 0x551 +10028f4c: 4639 mov r1, r7 +10028f4e: f7ff ff9f bl 10028e90 <.text_130+0x4> +10028f52: f000 02ef and.w r2, r0, #239 ; 0xef +10028f56: 4639 mov r1, r7 +10028f58: e005 b.n 10028f66 +10028f5a: f7ff ff97 bl 10028e8c <.text_130> +10028f5e: f000 02ef and.w r2, r0, #239 ; 0xef +10028f62: f44f 61aa mov.w r1, #1360 ; 0x550 +10028f66: f7ff fe34 bl 10028bd2 <.text_115+0x4> +10028f6a: 2160 movs r1, #96 ; 0x60 +10028f6c: 4630 mov r0, r6 +10028f6e: f7fe f99b bl 100272a8 +10028f72: b128 cbz r0, 10028f80 +10028f74: 2202 movs r2, #2 +10028f76: f240 5142 movw r1, #1346 ; 0x542 +10028f7a: f7ff fe2a bl 10028bd2 <.text_115+0x4> +10028f7e: 2507 movs r5, #7 +10028f80: f7ff fe21 bl 10028bc6 <.text_114> +10028f84: b148 cbz r0, 10028f9a +10028f86: f000 f811 bl 10028fac <.text_134> +10028f8a: b130 cbz r0, 10028f9a +10028f8c: f7ff fe18 bl 10028bc0 <.text_113> +10028f90: 2203 movs r2, #3 +10028f92: f240 5153 movw r1, #1363 ; 0x553 +10028f96: f7ff fe1c bl 10028bd2 <.text_115+0x4> +10028f9a: ea45 2205 orr.w r2, r5, r5, lsl #8 +10028f9e: 4620 mov r0, r4 +10028fa0: e8bd 41f0 ldmia.w sp!, {r4, r5, r6, r7, r8, lr} +10028fa4: f240 412a movw r1, #1066 ; 0x42a +10028fa8: f7fb be5a b.w 10024c60 + +10028fac <.text_134>: +10028fac: 2101 movs r1, #1 +10028fae: 4620 mov r0, r4 +10028fb0: f7f6 bc4d b.w 1001f84e + +10028fb4 : +10028fb4: 2001 movs r0, #1 +10028fb6: 4770 bx lr + +10028fb8 : +10028fb8: 2001 movs r0, #1 +10028fba: 4770 bx lr + +10028fbc : +10028fbc: e92d 4ff2 stmdb sp!, {r1, r4, r5, r6, r7, r8, r9, sl, fp, lr} +10028fc0: f7ff ff6d bl 10028e9e <.text_132> +10028fc4: b082 sub sp, #8 +10028fc6: 5907 ldr r7, [r0, r4] +10028fc8: f89d e008 ldrb.w lr, [sp, #8] +10028fcc: 4616 mov r6, r2 +10028fce: f642 1318 movw r3, #10520 ; 0x2918 +10028fd2: 19da adds r2, r3, r7 +10028fd4: f1be 0f49 cmp.w lr, #73 ; 0x49 +10028fd8: f240 5851 movw r8, #1361 ; 0x551 +10028fdc: f641 10d0 movw r0, #6608 ; 0x19d0 +10028fe0: f8df 962c ldr.w r9, [pc, #1580] ; 10029610 <.text_149> +10028fe4: f240 6a74 movw sl, #1652 ; 0x674 +10028fe8: f240 5122 movw r1, #1314 ; 0x522 +10028fec: f240 252a movw r5, #554 ; 0x22a +10028ff0: f641 5b52 movw fp, #7506 ; 0x1d52 +10028ff4: f200 8266 bhi.w 100294c4 +10028ff8: e8df f01e tbh [pc, lr, lsl #1] +10028ffc: 0054004a .word 0x0054004a +10029000: 00670061 .word 0x00670061 +10029004: 0264006f .word 0x0264006f +10029008: 00ba0087 .word 0x00ba0087 +1002900c: 00cb00bc .word 0x00cb00bc +10029010: 00db00d1 .word 0x00db00d1 +10029014: 010b0105 .word 0x010b0105 +10029018: 01160111 .word 0x01160111 +1002901c: 0121011d .word 0x0121011d +10029020: 01380125 .word 0x01380125 +10029024: 0242013f .word 0x0242013f +10029028: 01490264 .word 0x01490264 +1002902c: 0153014b .word 0x0153014b +10029030: 01690164 .word 0x01690164 +10029034: 01880185 .word 0x01880185 +10029038: 01920264 .word 0x01920264 +1002903c: 019a0196 .word 0x019a0196 +10029040: 01a801a2 .word 0x01a801a2 +10029044: 026901ba .word 0x026901ba +10029048: 02640264 .word 0x02640264 +1002904c: 01bd0264 .word 0x01bd0264 +10029050: 01c20269 .word 0x01c20269 +10029054: 02640264 .word 0x02640264 +10029058: 02640264 .word 0x02640264 +1002905c: 02640264 .word 0x02640264 +10029060: 026401c7 .word 0x026401c7 +10029064: 02640264 .word 0x02640264 +10029068: 02640264 .word 0x02640264 +1002906c: 02640264 .word 0x02640264 +10029070: 01db01d7 .word 0x01db01d7 +10029074: 02690269 .word 0x02690269 +10029078: 020f01de .word 0x020f01de +1002907c: 0231022e .word 0x0231022e +10029080: 02640269 .word 0x02640269 +10029084: 023b0264 .word 0x023b0264 +10029088: 024d0264 .word 0x024d0264 +1002908c: 025f0264 .word 0x025f0264 +10029090: f44f 7181 mov.w r1, #258 ; 0x102 +10029094: f7ff fefc bl 10028e90 <.text_130+0x4> +10029098: 7831 ldrb r1, [r6, #0] +1002909a: f000 000c and.w r0, r0, #12 +1002909e: ea41 0200 orr.w r2, r1, r0 +100290a2: e009 b.n 100290b8 +100290a4: f44f 7181 mov.w r1, #258 ; 0x102 +100290a8: f7ff fef2 bl 10028e90 <.text_130+0x4> +100290ac: 7831 ldrb r1, [r6, #0] +100290ae: f000 0003 and.w r0, r0, #3 +100290b2: ea40 0281 orr.w r2, r0, r1, lsl #2 +100290b6: b2d2 uxtb r2, r2 +100290b8: f44f 7181 mov.w r1, #258 ; 0x102 +100290bc: e1fa b.n 100294b4 +100290be: 4632 mov r2, r6 +100290c0: 2102 movs r1, #2 +100290c2: 4620 mov r0, r4 +100290c4: f7ff fc83 bl 100289ce +100290c8: e201 b.n 100294ce +100290ca: f000 fa02 bl 100294d2 <.text_140> +100290ce: bf0c ite eq +100290d0: f44f 65e0 moveq.w r5, #1792 ; 0x700 +100290d4: f44f 65c2 movne.w r5, #1552 ; 0x610 +100290d8: e00e b.n 100290f8 +100290da: f000 f9fa bl 100294d2 <.text_140> +100290de: 7830 ldrb r0, [r6, #0] +100290e0: bf0c ite eq +100290e2: f44f 65e1 moveq.w r5, #1800 ; 0x708 +100290e6: f44f 65c3 movne.w r5, #1560 ; 0x618 +100290ea: 2800 cmp r0, #0 +100290ec: bf01 itttt eq +100290ee: 7870 ldrbeq r0, [r6, #1] +100290f0: 2800 cmpeq r0, #0 +100290f2: 78b0 ldrbeq r0, [r6, #2] +100290f4: 2800 cmpeq r0, #0 +100290f6: d007 beq.n 10029108 +100290f8: 2700 movs r7, #0 +100290fa: 5dba ldrb r2, [r7, r6] +100290fc: 1979 adds r1, r7, r5 +100290fe: f7ff fd68 bl 10028bd2 <.text_115+0x4> +10029102: 1c7f adds r7, r7, #1 +10029104: 2f06 cmp r7, #6 +10029106: dbf8 blt.n 100290fa +10029108: e1e1 b.n 100294ce +1002910a: 2000 movs r0, #0 +1002910c: f8ad 0000 strh.w r0, [sp] +10029110: 2500 movs r5, #0 +10029112: aa00 add r2, sp, #0 +10029114: 4631 mov r1, r6 +10029116: 4620 mov r0, r4 +10029118: f7fd fda9 bl 10026c6e +1002911c: f8bd 0000 ldrh.w r0, [sp] +10029120: f240 115d movw r1, #349 ; 0x15d +10029124: 4008 ands r0, r1 +10029126: f040 000d orr.w r0, r0, #13 +1002912a: f8ad 0000 strh.w r0, [sp] +1002912e: f8a7 0048 strh.w r0, [r7, #72] ; 0x48 +10029132: f44f 6188 mov.w r1, #1088 ; 0x440 +10029136: f8bd 0000 ldrh.w r0, [sp] +1002913a: f040 0001 orr.w r0, r0, #1 +1002913e: f8ad 0000 strh.w r0, [sp] +10029142: b2c2 uxtb r2, r0 +10029144: f7ff fd45 bl 10028bd2 <.text_115+0x4> +10029148: f8bd 0000 ldrh.w r0, [sp] +1002914c: 0a02 lsrs r2, r0, #8 +1002914e: f240 4141 movw r1, #1089 ; 0x441 +10029152: f7ff fd3e bl 10028bd2 <.text_115+0x4> +10029156: e003 b.n 10029160 +10029158: 0840 lsrs r0, r0, #1 +1002915a: f8ad 0000 strh.w r0, [sp] +1002915e: 1c6d adds r5, r5, #1 +10029160: f8bd 0000 ldrh.w r0, [sp] +10029164: 2802 cmp r0, #2 +10029166: daf7 bge.n 10029158 +10029168: b2ea uxtb r2, r5 +1002916a: f44f 6190 mov.w r1, #1152 ; 0x480 +1002916e: e1a1 b.n 100294b4 +10029170: 7832 ldrb r2, [r6, #0] +10029172: e19f b.n 100294b4 +10029174: f000 f9ad bl 100294d2 <.text_140> +10029178: 7830 ldrb r0, [r6, #0] +1002917a: bf18 it ne +1002917c: f44f 68aa movne.w r8, #1360 ; 0x550 +10029180: b108 cbz r0, 10029186 +10029182: 220c movs r2, #12 +10029184: e033 b.n 100291ee +10029186: 4641 mov r1, r8 +10029188: f7ff fe82 bl 10028e90 <.text_130+0x4> +1002918c: f000 02f3 and.w r2, r0, #243 ; 0xf3 +10029190: e02d b.n 100291ee +10029192: 4632 mov r2, r6 +10029194: 2109 movs r1, #9 +10029196: 4620 mov r0, r4 +10029198: f7ff fd3b bl 10028c12 +1002919c: e197 b.n 100294ce +1002919e: f000 f99c bl 100294da <.text_141> +100291a2: 7831 ldrb r1, [r6, #0] +100291a4: 2900 cmp r1, #0 +100291a6: bf14 ite ne +100291a8: f040 02c0 orrne.w r2, r0, #192 ; 0xc0 +100291ac: f020 02c0 biceq.w r2, r0, #192 ; 0xc0 +100291b0: e03e b.n 10029230 +100291b2: 2100 movs r1, #0 +100291b4: f7ff fd08 bl 10028bc8 <.text_114+0x2> +100291b8: b120 cbz r0, 100291c4 +100291ba: 2200 movs r2, #0 +100291bc: f240 61a4 movw r1, #1700 ; 0x6a4 +100291c0: f7ff fe61 bl 10028e86 <.text_129> +100291c4: f000 f985 bl 100294d2 <.text_140> +100291c8: f240 5153 movw r1, #1363 ; 0x553 +100291cc: d111 bne.n 100291f2 +100291ce: 2202 movs r2, #2 +100291d0: f7ff fcff bl 10028bd2 <.text_115+0x4> +100291d4: 4641 mov r1, r8 +100291d6: f7ff fe5b bl 10028e90 <.text_130+0x4> +100291da: f040 0210 orr.w r2, r0, #16 +100291de: 4641 mov r1, r8 +100291e0: f7ff fcf7 bl 10028bd2 <.text_115+0x4> +100291e4: 4641 mov r1, r8 +100291e6: f7ff fe53 bl 10028e90 <.text_130+0x4> +100291ea: f000 02f7 and.w r2, r0, #247 ; 0xf7 +100291ee: 4641 mov r1, r8 +100291f0: e160 b.n 100294b4 +100291f2: 2201 movs r2, #1 +100291f4: f7ff fced bl 10028bd2 <.text_115+0x4> +100291f8: f7ff fe48 bl 10028e8c <.text_130> +100291fc: f040 0210 orr.w r2, r0, #16 +10029200: f44f 61aa mov.w r1, #1360 ; 0x550 +10029204: e156 b.n 100294b4 +10029206: 4632 mov r2, r6 +10029208: 210c movs r1, #12 +1002920a: 4620 mov r0, r4 +1002920c: f7ff fdbb bl 10028d86 +10029210: e15d b.n 100294ce +10029212: 4632 mov r2, r6 +10029214: 210d movs r1, #13 +10029216: 4620 mov r0, r4 +10029218: f7ff fe45 bl 10028ea6 +1002921c: e157 b.n 100294ce +1002921e: f000 f95c bl 100294da <.text_141> +10029222: f040 0204 orr.w r2, r0, #4 +10029226: e003 b.n 10029230 +10029228: f000 f957 bl 100294da <.text_141> +1002922c: f020 0204 bic.w r2, r0, #4 +10029230: f44f 61c1 mov.w r1, #1544 ; 0x608 +10029234: e087 b.n 10029346 +10029236: 8832 ldrh r2, [r6, #0] +10029238: f240 5154 movw r1, #1364 ; 0x554 +1002923c: e109 b.n 10029452 +1002923e: 7832 ldrb r2, [r6, #0] +10029240: f240 511b movw r1, #1307 ; 0x51b +10029244: e136 b.n 100294b4 +10029246: 7832 ldrb r2, [r6, #0] +10029248: f240 613c movw r1, #1596 ; 0x63c +1002924c: f7ff fcc1 bl 10028bd2 <.text_115+0x4> +10029250: 7872 ldrb r2, [r6, #1] +10029252: f240 613d movw r1, #1597 ; 0x63d +10029256: f7ff fcbc bl 10028bd2 <.text_115+0x4> +1002925a: 78b2 ldrb r2, [r6, #2] +1002925c: f240 613e movw r1, #1598 ; 0x63e +10029260: f7ff fcb7 bl 10028bd2 <.text_115+0x4> +10029264: 78f2 ldrb r2, [r6, #3] +10029266: f240 613f movw r1, #1599 ; 0x63f +1002926a: e123 b.n 100294b4 +1002926c: 7830 ldrb r0, [r6, #0] +1002926e: 2200 movs r2, #0 +10029270: b100 cbz r0, 10029274 +10029272: 2280 movs r2, #128 ; 0x80 +10029274: f240 4142 movw r1, #1090 ; 0x442 +10029278: e11c b.n 100294b4 +1002927a: 6860 ldr r0, [r4, #4] +1002927c: 2803 cmp r0, #3 +1002927e: bf19 ittee ne +10029280: 7832 ldrbne r2, [r6, #0] +10029282: f44f 61d0 movne.w r1, #1664 ; 0x680 +10029286: 222c moveq r2, #44 ; 0x2c +10029288: f44f 61d0 moveq.w r1, #1664 ; 0x680 +1002928c: e112 b.n 100294b4 +1002928e: 6831 ldr r1, [r6, #0] +10029290: e01b b.n 100292ca +10029292: 7832 ldrb r2, [r6, #0] +10029294: 19c1 adds r1, r0, r7 +10029296: b112 cbz r2, 1002929e +10029298: 59c0 ldr r0, [r0, r7] +1002929a: 6208 str r0, [r1, #32] +1002929c: e117 b.n 100294ce +1002929e: 6a09 ldr r1, [r1, #32] +100292a0: e013 b.n 100292ca +100292a2: 6831 ldr r1, [r6, #0] +100292a4: f06f 4270 mvn.w r2, #4026531840 ; 0xf0000000 +100292a8: 4291 cmp r1, r2 +100292aa: d108 bne.n 100292be +100292ac: f641 114d movw r1, #6477 ; 0x194d +100292b0: 19ca adds r2, r1, r7 +100292b2: 7852 ldrb r2, [r2, #1] +100292b4: 55ca strb r2, [r1, r7] +100292b6: f641 1150 movw r1, #6480 ; 0x1950 +100292ba: 59c9 ldr r1, [r1, r7] +100292bc: e005 b.n 100292ca +100292be: 59c2 ldr r2, [r0, r7] +100292c0: 4311 orrs r1, r2 +100292c2: e002 b.n 100292ca +100292c4: 59c1 ldr r1, [r0, r7] +100292c6: 6832 ldr r2, [r6, #0] +100292c8: 4011 ands r1, r2 +100292ca: 51c1 str r1, [r0, r7] +100292cc: e0ff b.n 100294ce +100292ce: 7835 ldrb r5, [r6, #0] +100292d0: 2700 movs r7, #0 +100292d2: 2600 movs r6, #0 +100292d4: e011 b.n 100292fa +100292d6: 2700 movs r7, #0 +100292d8: 463a mov r2, r7 +100292da: 4651 mov r1, sl +100292dc: f7ff fdcc bl 10028e78 <.text_127+0x6> +100292e0: eb06 00c5 add.w r0, r6, r5, lsl #3 +100292e4: ea49 0200 orr.w r2, r9, r0 +100292e8: f44f 61ce mov.w r1, #1648 ; 0x670 +100292ec: f7ff fdc4 bl 10028e78 <.text_127+0x6> +100292f0: 1c76 adds r6, r6, #1 +100292f2: 2e08 cmp r6, #8 +100292f4: daea bge.n 100292cc +100292f6: 2e00 cmp r6, #0 +100292f8: d1ed bne.n 100292d6 +100292fa: f005 0003 and.w r0, r5, #3 +100292fe: f040 0010 orr.w r0, r0, #16 +10029302: 4307 orrs r7, r0 +10029304: e7e8 b.n 100292d8 +10029306: f04f 4240 mov.w r2, #3221225472 ; 0xc0000000 +1002930a: e006 b.n 1002931a +1002930c: 6832 ldr r2, [r6, #0] +1002930e: 4651 mov r1, sl +10029310: f7ff fdb2 bl 10028e78 <.text_127+0x6> +10029314: 6870 ldr r0, [r6, #4] +10029316: ea49 0200 orr.w r2, r9, r0 +1002931a: f44f 61ce mov.w r1, #1648 ; 0x670 +1002931e: e012 b.n 10029346 +10029320: 6832 ldr r2, [r6, #0] +10029322: f44f 61a0 mov.w r1, #1280 ; 0x500 +10029326: e00e b.n 10029346 +10029328: 6832 ldr r2, [r6, #0] +1002932a: f240 5104 movw r1, #1284 ; 0x504 +1002932e: e00a b.n 10029346 +10029330: 6830 ldr r0, [r6, #0] +10029332: f507 51c6 add.w r1, r7, #6336 ; 0x18c0 +10029336: 6008 str r0, [r1, #0] +10029338: f44f 61a1 mov.w r1, #1288 ; 0x508 +1002933c: 6832 ldr r2, [r6, #0] +1002933e: e002 b.n 10029346 +10029340: 6832 ldr r2, [r6, #0] +10029342: f240 510c movw r1, #1292 ; 0x50c +10029346: f7ff fd97 bl 10028e78 <.text_127+0x6> +1002934a: e0c0 b.n 100294ce +1002934c: 7830 ldrb r0, [r6, #0] +1002934e: 2200 movs r2, #0 +10029350: b158 cbz r0, 1002936a +10029352: 2201 movs r2, #1 +10029354: 0781 lsls r1, r0, #30 +10029356: bf48 it mi +10029358: 2203 movmi r2, #3 +1002935a: 0741 lsls r1, r0, #29 +1002935c: bf48 it mi +1002935e: f042 0204 orrmi.w r2, r2, #4 +10029362: 0700 lsls r0, r0, #28 +10029364: bf48 it mi +10029366: f042 0208 orrmi.w r2, r2, #8 +1002936a: f44f 61b8 mov.w r1, #1472 ; 0x5c0 +1002936e: e0a1 b.n 100294b4 +10029370: 7830 ldrb r0, [r6, #0] +10029372: 7090 strb r0, [r2, #2] +10029374: e0ab b.n 100294ce +10029376: 7831 ldrb r1, [r6, #0] +10029378: 4620 mov r0, r4 +1002937a: f008 fb2c bl 100319d6 +1002937e: e0a6 b.n 100294ce +10029380: 7831 ldrb r1, [r6, #0] +10029382: 4620 mov r0, r4 +10029384: f008 fbef bl 10031b66 +10029388: e0a1 b.n 100294ce +1002938a: f507 52f8 add.w r2, r7, #7936 ; 0x1f00 +1002938e: 6831 ldr r1, [r6, #0] +10029390: f507 50c8 add.w r0, r7, #6400 ; 0x1900 +10029394: 32fc adds r2, #252 ; 0xfc +10029396: 30a8 adds r0, #168 ; 0xa8 +10029398: 29ff cmp r1, #255 ; 0xff +1002939a: bf0f iteee eq +1002939c: 7f51 ldrbeq r1, [r2, #29] +1002939e: 7f13 ldrbne r3, [r2, #28] +100293a0: 7753 strbne r3, [r2, #29] +100293a2: b2c9 uxtbne r1, r1 +100293a4: f008 fdea bl 10031f7c +100293a8: e091 b.n 100294ce +100293aa: 7830 ldrb r0, [r6, #0] +100293ac: f887 0060 strb.w r0, [r7, #96] ; 0x60 +100293b0: e08d b.n 100294ce +100293b2: 8830 ldrh r0, [r6, #0] +100293b4: 53d8 strh r0, [r3, r7] +100293b6: e08a b.n 100294ce +100293b8: 22ff movs r2, #255 ; 0xff +100293ba: f7ff fc0a bl 10028bd2 <.text_115+0x4> +100293be: f240 41dc movw r1, #1244 ; 0x4dc +100293c2: 4620 mov r0, r4 +100293c4: f7fb fc38 bl 10024c38 +100293c8: f8a4 0b18 strh.w r0, [r4, #2840] ; 0xb18 +100293cc: f641 107f movw r0, #6527 ; 0x197f +100293d0: 5d00 ldrb r0, [r0, r4] +100293d2: 2801 cmp r0, #1 +100293d4: d07b beq.n 100294ce +100293d6: f44f 7121 mov.w r1, #644 ; 0x284 +100293da: f000 f880 bl 100294de <.text_141+0x4> +100293de: f440 2280 orr.w r2, r0, #262144 ; 0x40000 +100293e2: f44f 7121 mov.w r1, #644 ; 0x284 +100293e6: f7ff fd47 bl 10028e78 <.text_127+0x6> +100293ea: 2564 movs r5, #100 ; 0x64 +100293ec: f44f 7121 mov.w r1, #644 ; 0x284 +100293f0: f000 f875 bl 100294de <.text_141+0x4> +100293f4: 0380 lsls r0, r0, #14 +100293f6: d401 bmi.n 100293fc +100293f8: 1e6d subs r5, r5, #1 +100293fa: d1f7 bne.n 100293ec +100293fc: 2200 movs r2, #0 +100293fe: f44f 7105 mov.w r1, #532 ; 0x214 +10029402: f7ff fd40 bl 10028e86 <.text_129> +10029406: f04f 4200 mov.w r2, #2147483648 ; 0x80000000 +1002940a: f44f 7100 mov.w r1, #512 ; 0x200 +1002940e: f7ff fd33 bl 10028e78 <.text_127+0x6> +10029412: 2002 movs r0, #2 +10029414: f7e7 faf9 bl 10010a0a +10029418: e059 b.n 100294ce +1002941a: f240 452a movw r5, #1066 ; 0x42a +1002941e: f240 1201 movw r2, #257 ; 0x101 +10029422: 4629 mov r1, r5 +10029424: f7ff fd2f bl 10028e86 <.text_129> +10029428: f44f 767a mov.w r6, #1000 ; 0x3e8 +1002942c: f44f 7100 mov.w r1, #512 ; 0x200 +10029430: f000 f855 bl 100294de <.text_141+0x4> +10029434: 4607 mov r7, r0 +10029436: f44f 7101 mov.w r1, #516 ; 0x204 +1002943a: f000 f850 bl 100294de <.text_141+0x4> +1002943e: 4287 cmp r7, r0 +10029440: d004 beq.n 1002944c +10029442: 200a movs r0, #10 +10029444: f7e7 fad3 bl 100109ee +10029448: 1e76 subs r6, r6, #1 +1002944a: d1ef bne.n 1002942c +1002944c: f243 0230 movw r2, #12336 ; 0x3030 +10029450: 4629 mov r1, r5 +10029452: f7ff fd18 bl 10028e86 <.text_129> +10029456: e03a b.n 100294ce +10029458: 7830 ldrb r0, [r6, #0] +1002945a: 70d0 strb r0, [r2, #3] +1002945c: e037 b.n 100294ce +1002945e: 6830 ldr r0, [r6, #0] +10029460: f5b0 4fff cmp.w r0, #32640 ; 0x7f80 +10029464: d833 bhi.n 100294ce +10029466: 307f adds r0, #127 ; 0x7f +10029468: 0442 lsls r2, r0, #17 +1002946a: 0e12 lsrs r2, r2, #24 +1002946c: f240 6152 movw r1, #1618 ; 0x652 +10029470: e020 b.n 100294b4 +10029472: 8831 ldrh r1, [r6, #0] +10029474: 0a0a lsrs r2, r1, #8 +10029476: b2c9 uxtb r1, r1 +10029478: 4620 mov r0, r4 +1002947a: f008 fa72 bl 10031962 +1002947e: e026 b.n 100294ce +10029480: f000 f827 bl 100294d2 <.text_140> +10029484: d001 beq.n 1002948a +10029486: f240 250a movw r5, #522 ; 0x20a +1002948a: 4629 mov r1, r5 +1002948c: f7ff fd00 bl 10028e90 <.text_130+0x4> +10029490: f040 0201 orr.w r2, r0, #1 +10029494: e00d b.n 100294b2 +10029496: f000 f81c bl 100294d2 <.text_140> +1002949a: 4629 mov r1, r5 +1002949c: 4620 mov r0, r4 +1002949e: d104 bne.n 100294aa +100294a0: f7fb fbc4 bl 10024c2c +100294a4: f040 0210 orr.w r2, r0, #16 +100294a8: e003 b.n 100294b2 +100294aa: f7fb fbbf bl 10024c2c +100294ae: f000 02ef and.w r2, r0, #239 ; 0xef +100294b2: 4629 mov r1, r5 +100294b4: f7ff fb8d bl 10028bd2 <.text_115+0x4> +100294b8: e009 b.n 100294ce +100294ba: f641 01bd movw r1, #6333 ; 0x18bd +100294be: 2001 movs r0, #1 +100294c0: 55c8 strb r0, [r1, r7] +100294c2: e004 b.n 100294ce +100294c4: 4632 mov r2, r6 +100294c6: 4671 mov r1, lr +100294c8: 4620 mov r0, r4 +100294ca: f7fd fda3 bl 10027014 +100294ce: e8bd 8ff7 ldmia.w sp!, {r0, r1, r2, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +100294d2 <.text_140>: +100294d2: f81b 0004 ldrb.w r0, [fp, r4] +100294d6: 2801 cmp r0, #1 +100294d8: 4770 bx lr + +100294da <.text_141>: +100294da: f44f 61c1 mov.w r1, #1544 ; 0x608 +100294de: 4620 mov r0, r4 +100294e0: f7fb bbb0 b.w 10024c44 + +100294e4 : +100294e4: b538 push {r3, r4, r5, lr} +100294e6: 4614 mov r4, r2 +100294e8: f641 32a4 movw r2, #7076 ; 0x1ba4 +100294ec: 2906 cmp r1, #6 +100294ee: 5812 ldr r2, [r2, r0] +100294f0: f102 0348 add.w r3, r2, #72 ; 0x48 +100294f4: f642 1518 movw r5, #10520 ; 0x2918 +100294f8: d016 beq.n 10029528 +100294fa: 2907 cmp r1, #7 +100294fc: d017 beq.n 1002952e +100294fe: 2915 cmp r1, #21 +10029500: d01a beq.n 10029538 +10029502: 2916 cmp r1, #22 +10029504: d025 beq.n 10029552 +10029506: 2917 cmp r1, #23 +10029508: d025 beq.n 10029556 +1002950a: 292c cmp r1, #44 ; 0x2c +1002950c: d028 beq.n 10029560 +1002950e: 293a cmp r1, #58 ; 0x3a +10029510: d03b beq.n 1002958a +10029512: 293b cmp r1, #59 ; 0x3b +10029514: d03b beq.n 1002958e +10029516: 293c cmp r1, #60 ; 0x3c +10029518: bf18 it ne +1002951a: 293d cmpne r1, #61 ; 0x3d +1002951c: d04b beq.n 100295b6 +1002951e: 2940 cmp r1, #64 ; 0x40 +10029520: d038 beq.n 10029594 +10029522: 2946 cmp r1, #70 ; 0x46 +10029524: d039 beq.n 1002959a +10029526: e041 b.n 100295ac +10029528: f8b2 0048 ldrh.w r0, [r2, #72] ; 0x48 +1002952c: e030 b.n 10029590 +1002952e: f240 5122 movw r1, #1314 ; 0x522 +10029532: f7fb fb7b bl 10024c2c +10029536: e037 b.n 100295a8 +10029538: f641 5152 movw r1, #7506 ; 0x1d52 +1002953c: 5c09 ldrb r1, [r1, r0] +1002953e: 2901 cmp r1, #1 +10029540: d102 bne.n 10029548 +10029542: f240 212a movw r1, #554 ; 0x22a +10029546: e001 b.n 1002954c +10029548: f240 210a movw r1, #522 ; 0x20a +1002954c: f7fb fb6e bl 10024c2c +10029550: e028 b.n 100295a4 +10029552: 78d8 ldrb r0, [r3, #3] +10029554: e028 b.n 100295a8 +10029556: f641 10d0 movw r0, #6608 ; 0x19d0 +1002955a: 5880 ldr r0, [r0, r2] +1002955c: 6020 str r0, [r4, #0] +1002955e: bd31 pop {r0, r4, r5, pc} +10029560: f500 51e5 add.w r1, r0, #7328 ; 0x1ca0 +10029564: 6809 ldr r1, [r1, #0] +10029566: 2901 cmp r1, #1 +10029568: bf1d ittte ne +1002956a: f641 1174 movwne r1, #6516 ; 0x1974 +1002956e: 5809 ldrne r1, [r1, r0] +10029570: 2902 cmpne r1, #2 +10029572: 2001 moveq r0, #1 +10029574: d018 beq.n 100295a8 +10029576: f44f 61c1 mov.w r1, #1544 ; 0x608 +1002957a: f7fb fb63 bl 10024c44 +1002957e: f400 20e0 and.w r0, r0, #458752 ; 0x70000 +10029582: 1e40 subs r0, r0, #1 +10029584: 4180 sbcs r0, r0 +10029586: 0fc0 lsrs r0, r0, #31 +10029588: e00e b.n 100295a8 +1002958a: 7e18 ldrb r0, [r3, #24] +1002958c: e00c b.n 100295a8 +1002958e: 5aa8 ldrh r0, [r5, r2] +10029590: 8020 strh r0, [r4, #0] +10029592: bd31 pop {r0, r4, r5, pc} +10029594: 18a8 adds r0, r5, r2 +10029596: 78c0 ldrb r0, [r0, #3] +10029598: e006 b.n 100295a8 +1002959a: f240 411a movw r1, #1050 ; 0x41a +1002959e: f7fb fb4b bl 10024c38 +100295a2: 0a80 lsrs r0, r0, #10 +100295a4: f000 0001 and.w r0, r0, #1 +100295a8: 7020 strb r0, [r4, #0] +100295aa: bd31 pop {r0, r4, r5, pc} +100295ac: 4622 mov r2, r4 +100295ae: e8bd 4038 ldmia.w sp!, {r3, r4, r5, lr} +100295b2: f7fd bd34 b.w 1002701e +100295b6: bd31 pop {r0, r4, r5, pc} + +100295b8 : +100295b8: 2000 movs r0, #0 +100295ba: 4770 bx lr + +100295bc : +100295bc: 2000 movs r0, #0 +100295be: 4770 bx lr + +100295c0 : +100295c0: b530 push {r4, r5, lr} +100295c2: f7ff fc6c bl 10028e9e <.text_132> +100295c6: b083 sub sp, #12 +100295c8: 5905 ldr r5, [r0, r4] +100295ca: 4812 ldr r0, [pc, #72] ; (10029614 <.text_150>) +100295cc: f20f 016c addw r1, pc, #108 ; 0x6c +100295d0: 9000 str r0, [sp, #0] +100295d2: 9401 str r4, [sp, #4] +100295d4: f505 5024 add.w r0, r5, #10496 ; 0x2900 +100295d8: 2306 movs r3, #6 +100295da: f44f 7200 mov.w r2, #512 ; 0x200 +100295de: 305c adds r0, #92 ; 0x5c +100295e0: f7e7 fa8a bl 10010af8 +100295e4: 2801 cmp r0, #1 +100295e6: d10c bne.n 10029602 +100295e8: 480b ldr r0, [pc, #44] ; (10029618 <.text_151>) +100295ea: f20f 016c addw r1, pc, #108 ; 0x6c +100295ee: 9000 str r0, [sp, #0] +100295f0: 9401 str r4, [sp, #4] +100295f2: f505 5024 add.w r0, r5, #10496 ; 0x2900 +100295f6: 2301 movs r3, #1 +100295f8: f44f 7280 mov.w r2, #256 ; 0x100 +100295fc: 308c adds r0, #140 ; 0x8c +100295fe: f7e7 fa7b bl 10010af8 +10029602: bd37 pop {r0, r1, r2, r4, r5, pc} + +10029604 <.text_146>: +10029604: 7000208e .word 0x7000208e + +10029608 <.text_147>: +10029608: 01010000 .word 0x01010000 + +1002960c <.text_148>: +1002960c: 01800100 .word 0x01800100 + +10029610 <.text_149>: +10029610: 80010000 .word 0x80010000 + +10029614 <.text_150>: +10029614: 10027e73 .word 0x10027e73 + +10029618 <.text_151>: +10029618: 10027ecd .word 0x10027ecd + +1002961c : +1002961c: b510 push {r4, lr} +1002961e: f641 31a4 movw r1, #7076 ; 0x1ba4 +10029622: 580c ldr r4, [r1, r0] +10029624: f504 5024 add.w r0, r4, #10496 ; 0x2900 +10029628: 305c adds r0, #92 ; 0x5c +1002962a: f7e7 fa74 bl 10010b16 +1002962e: f504 5024 add.w r0, r4, #10496 ; 0x2900 +10029632: e8bd 4010 ldmia.w sp!, {r4, lr} +10029636: 308c adds r0, #140 ; 0x8c +10029638: f7e7 ba6d b.w 10010b16 + +1002963c : +1002963c: 7472 5f77 696c 7474 656c 775f 6669 5f69 rtw_little_wifi_ +1002964c: 636d 5f75 6874 6572 6461 0000 mcu_thread.. + +10029658 : +10029658: 7472 5f77 6e65 6574 5f72 3233 5f4b 6874 rtw_enter_32K_th +10029668: 6572 6461 0000 0000 read.... + +10029670 : +10029670: f8df f000 ldr.w pc, [pc] ; 10029674 +10029674: 00018279 .word 0x00018279 + +10029678 : +10029678: f8df f000 ldr.w pc, [pc] ; 1002967c +1002967c: 00018221 .word 0x00018221 + +10029680 : +10029680: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +10029684: f000 fabf bl 10029c06 <.text_26> +10029688: 460e mov r6, r1 +1002968a: 5900 ldr r0, [r0, r4] +1002968c: 211c movs r1, #28 +1002968e: fb01 0006 mla r0, r1, r6, r0 +10029692: f500 55c0 add.w r5, r0, #6144 ; 0x1800 +10029696: 35c4 adds r5, #196 ; 0xc4 +10029698: 05d7 lsls r7, r2, #23 +1002969a: f640 0824 movw r8, #2084 ; 0x824 +1002969e: b92e cbnz r6, 100296ac +100296a0: f000 f850 bl 10029744 <.text_4> +100296a4: f000 f846 bl 10029734 <.text_3> +100296a8: 4641 mov r1, r8 +100296aa: e00a b.n 100296c2 +100296ac: f640 092c movw r9, #2092 ; 0x82c +100296b0: f04f 32ff mov.w r2, #4294967295 +100296b4: 4649 mov r1, r9 +100296b6: 4620 mov r0, r4 +100296b8: f7ff ffda bl 10029670 +100296bc: f000 f83a bl 10029734 <.text_3> +100296c0: 4649 mov r1, r9 +100296c2: f000 fb44 bl 10029d4e <.text_32> +100296c6: f000 f83d bl 10029744 <.text_4> +100296ca: 4607 mov r7, r0 +100296cc: 007b lsls r3, r7, #1 +100296ce: 085b lsrs r3, r3, #1 +100296d0: f04f 32ff mov.w r2, #4294967295 +100296d4: f000 fb41 bl 10029d5a <.text_33+0x6> +100296d8: f047 4300 orr.w r3, r7, #2147483648 ; 0x80000000 +100296dc: f04f 32ff mov.w r2, #4294967295 +100296e0: f000 fb3b bl 10029d5a <.text_33+0x6> +100296e4: 200a movs r0, #10 +100296e6: f7e7 f997 bl 10010a18 +100296ea: 2032 movs r0, #50 ; 0x32 +100296ec: f7e7 f994 bl 10010a18 +100296f0: 2032 movs r0, #50 ; 0x32 +100296f2: f7e7 f991 bl 10010a18 +100296f6: 200a movs r0, #10 +100296f8: f7e7 f98e bl 10010a18 +100296fc: f8df 76f0 ldr.w r7, [pc, #1776] ; 10029df0 <.text_35> +10029700: b926 cbnz r6, 1002970c +10029702: f44f 7280 mov.w r2, #256 ; 0x100 +10029706: f44f 6102 mov.w r1, #2080 ; 0x820 +1002970a: e005 b.n 10029718 +1002970c: 2e01 cmp r6, #1 +1002970e: d10a bne.n 10029726 +10029710: f44f 7280 mov.w r2, #256 ; 0x100 +10029714: f640 0128 movw r1, #2088 ; 0x828 +10029718: 4620 mov r0, r4 +1002971a: f7ff ffa9 bl 10029670 +1002971e: b2c0 uxtb r0, r0 +10029720: b108 cbz r0, 10029726 +10029722: 69a9 ldr r1, [r5, #24] +10029724: e000 b.n 10029728 +10029726: 6969 ldr r1, [r5, #20] +10029728: 463a mov r2, r7 +1002972a: 4620 mov r0, r4 +1002972c: e8bd 43f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +10029730: f7ff bf9e b.w 10029670 + +10029734 <.text_3>: +10029734: f020 40ff bic.w r0, r0, #2139095040 ; 0x7f800000 +10029738: 4338 orrs r0, r7 +1002973a: 0043 lsls r3, r0, #1 +1002973c: 085b lsrs r3, r3, #1 +1002973e: f04f 32ff mov.w r2, #4294967295 +10029742: 4770 bx lr + +10029744 <.text_4>: +10029744: f04f 32ff mov.w r2, #4294967295 +10029748: 4641 mov r1, r8 +1002974a: 4620 mov r0, r4 +1002974c: f7ff bf90 b.w 10029670 + +10029750 : +10029750: b538 push {r3, r4, r5, lr} +10029752: 461c mov r4, r3 +10029754: f7ff ff94 bl 10029680 +10029758: ea04 0500 and.w r5, r4, r0 +1002975c: 4620 mov r0, r4 +1002975e: f7ff ff8b bl 10029678 +10029762: fa25 f000 lsr.w r0, r5, r0 +10029766: bd32 pop {r1, r4, r5, pc} + +10029768 : +10029768: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +1002976c: 4604 mov r4, r0 +1002976e: 4698 mov r8, r3 +10029770: f8df 067c ldr.w r0, [pc, #1660] ; 10029df0 <.text_35> +10029774: 9f08 ldr r7, [sp, #32] +10029776: 4580 cmp r8, r0 +10029778: 460d mov r5, r1 +1002977a: 4616 mov r6, r2 +1002977c: d00b beq.n 10029796 +1002977e: 4620 mov r0, r4 +10029780: f7ff ff7e bl 10029680 +10029784: ea20 0908 bic.w r9, r0, r8 +10029788: 4640 mov r0, r8 +1002978a: f7ff ff75 bl 10029678 +1002978e: fa07 f000 lsl.w r0, r7, r0 +10029792: ea40 0709 orr.w r7, r0, r9 +10029796: 0338 lsls r0, r7, #12 +10029798: 0b00 lsrs r0, r0, #12 +1002979a: ea40 5006 orr.w r0, r0, r6, lsl #20 +1002979e: 0103 lsls r3, r0, #4 +100297a0: f641 30a4 movw r0, #7076 ; 0x1ba4 +100297a4: 211c movs r1, #28 +100297a6: 5900 ldr r0, [r0, r4] +100297a8: fb01 0005 mla r0, r1, r5, r0 +100297ac: f641 01d0 movw r1, #6352 ; 0x18d0 +100297b0: 091b lsrs r3, r3, #4 +100297b2: 5809 ldr r1, [r1, r0] +100297b4: 4620 mov r0, r4 +100297b6: b001 add sp, #4 +100297b8: e8bd 43f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, lr} +100297bc: f04f 32ff mov.w r2, #4294967295 +100297c0: f7ed bedc b.w 1001757c + +100297c4 : +100297c4: b510 push {r4, lr} +100297c6: f641 31a4 movw r1, #7076 ; 0x1ba4 +100297ca: 2401 movs r4, #1 +100297cc: 5808 ldr r0, [r1, r0] +100297ce: f500 50c8 add.w r0, r0, #6400 ; 0x1900 +100297d2: 30a8 adds r0, #168 ; 0xa8 +100297d4: f009 f828 bl 10032828 +100297d8: 2801 cmp r0, #1 +100297da: bf08 it eq +100297dc: 2400 moveq r4, #0 +100297de: 4620 mov r0, r4 +100297e0: bd10 pop {r4, pc} + +100297e2 : +100297e2: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +100297e6: f000 fa0e bl 10029c06 <.text_26> +100297ea: 2501 movs r5, #1 +100297ec: 5906 ldr r6, [r0, r4] +100297ee: 4620 mov r0, r4 +100297f0: f006 f902 bl 1002f9f8 +100297f4: f641 1701 movw r7, #6401 ; 0x1901 +100297f8: f506 51c8 add.w r1, r6, #6400 ; 0x1900 +100297fc: 5d38 ldrb r0, [r7, r4] +100297fe: 2801 cmp r0, #1 +10029800: f101 08a8 add.w r8, r1, #168 ; 0xa8 +10029804: d005 beq.n 10029812 +10029806: 2802 cmp r0, #2 +10029808: bf04 itt eq +1002980a: f896 005b ldrbeq.w r0, [r6, #91] ; 0x5b +1002980e: 2801 cmpeq r0, #1 +10029810: d105 bne.n 1002981e +10029812: 2200 movs r2, #0 +10029814: 2101 movs r1, #1 +10029816: 4640 mov r0, r8 +10029818: f008 ffcd bl 100327b6 +1002981c: bb80 cbnz r0, 10029880 +1002981e: 2100 movs r1, #0 +10029820: 4640 mov r0, r8 +10029822: f008 ffed bl 10032800 +10029826: bb58 cbnz r0, 10029880 +10029828: 4620 mov r0, r4 +1002982a: f005 fa69 bl 1002ed00 +1002982e: 1938 adds r0, r7, r4 +10029830: 7840 ldrb r0, [r0, #1] +10029832: 2801 cmp r0, #1 +10029834: d005 beq.n 10029842 +10029836: 2802 cmp r0, #2 +10029838: d11d bne.n 10029876 +1002983a: f896 005b ldrb.w r0, [r6, #91] ; 0x5b +1002983e: 2802 cmp r0, #2 +10029840: d019 beq.n 10029876 +10029842: 2104 movs r1, #4 +10029844: 4640 mov r0, r8 +10029846: f008 ffdb bl 10032800 +1002984a: b100 cbz r0, 1002984e +1002984c: 2500 movs r5, #0 +1002984e: f641 10b4 movw r0, #6580 ; 0x19b4 +10029852: 5980 ldr r0, [r0, r6] +10029854: 2801 cmp r0, #1 +10029856: bf04 itt eq +10029858: 4620 moveq r0, r4 +1002985a: f005 fb8e bleq 1002ef7a +1002985e: 5d38 ldrb r0, [r7, r4] +10029860: 2801 cmp r0, #1 +10029862: d005 beq.n 10029870 +10029864: 2802 cmp r0, #2 +10029866: bf04 itt eq +10029868: f896 005b ldrbeq.w r0, [r6, #91] ; 0x5b +1002986c: 2801 cmpeq r0, #1 +1002986e: d102 bne.n 10029876 +10029870: 4620 mov r0, r4 +10029872: f006 f853 bl 1002f91c +10029876: 2101 movs r1, #1 +10029878: 4640 mov r0, r8 +1002987a: f008 ffc1 bl 10032800 +1002987e: b100 cbz r0, 10029882 +10029880: 2500 movs r5, #0 +10029882: 4628 mov r0, r5 +10029884: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +10029888 : +10029888: b510 push {r4, lr} +1002988a: f000 f9bc bl 10029c06 <.text_26> +1002988e: f641 01c4 movw r1, #6340 ; 0x18c4 +10029892: 5900 ldr r0, [r0, r4] +10029894: f44f 6207 mov.w r2, #2160 ; 0x870 +10029898: 500a str r2, [r1, r0] +1002989a: 1808 adds r0, r1, r0 +1002989c: f640 0174 movw r1, #2164 ; 0x874 +100298a0: 61c2 str r2, [r0, #28] +100298a2: 6381 str r1, [r0, #56] ; 0x38 +100298a4: 6541 str r1, [r0, #84] ; 0x54 +100298a6: f640 0264 movw r2, #2148 ; 0x864 +100298aa: f44f 6106 mov.w r1, #2144 ; 0x860 +100298ae: 6041 str r1, [r0, #4] +100298b0: 6202 str r2, [r0, #32] +100298b2: 6081 str r1, [r0, #8] +100298b4: 6242 str r2, [r0, #36] ; 0x24 +100298b6: f44f 6104 mov.w r1, #2112 ; 0x840 +100298ba: 60c1 str r1, [r0, #12] +100298bc: f640 0144 movw r1, #2116 ; 0x844 +100298c0: 6281 str r1, [r0, #40] ; 0x28 +100298c2: f640 0124 movw r1, #2084 ; 0x824 +100298c6: 6101 str r1, [r0, #16] +100298c8: f640 012c movw r1, #2092 ; 0x82c +100298cc: 62c1 str r1, [r0, #44] ; 0x2c +100298ce: f44f 610a mov.w r1, #2208 ; 0x8a0 +100298d2: 6141 str r1, [r0, #20] +100298d4: f640 01a4 movw r1, #2212 ; 0x8a4 +100298d8: 6301 str r1, [r0, #48] ; 0x30 +100298da: f640 01a8 movw r1, #2216 ; 0x8a8 +100298de: 64c1 str r1, [r0, #76] ; 0x4c +100298e0: f640 01ac movw r1, #2220 ; 0x8ac +100298e4: 6681 str r1, [r0, #104] ; 0x68 +100298e6: f640 01b8 movw r1, #2232 ; 0x8b8 +100298ea: 6181 str r1, [r0, #24] +100298ec: f640 01bc movw r1, #2236 ; 0x8bc +100298f0: 6341 str r1, [r0, #52] ; 0x34 +100298f2: 4620 mov r0, r4 +100298f4: 2104 movs r1, #4 +100298f6: f7fb f9a5 bl 10024c44 +100298fa: f440 3240 orr.w r2, r0, #196608 ; 0x30000 +100298fe: 2104 movs r1, #4 +10029900: 4620 mov r0, r4 +10029902: f7fb f9b5 bl 10024c70 +10029906: 2207 movs r2, #7 +10029908: 2107 movs r1, #7 +1002990a: 4620 mov r0, r4 +1002990c: f7fb f9a0 bl 10024c50 +10029910: 2200 movs r2, #0 +10029912: 2150 movs r1, #80 ; 0x50 +10029914: 4620 mov r0, r4 +10029916: f7fb f99b bl 10024c50 +1002991a: 4620 mov r0, r4 +1002991c: e8bd 4010 ldmia.w sp!, {r4, lr} +10029920: e75f b.n 100297e2 + +10029922 : +10029922: f009 b853 b.w 100329cc + +10029926 : +10029926: b5f8 push {r3, r4, r5, r6, r7, lr} +10029928: 2a00 cmp r2, #0 +1002992a: 460f mov r7, r1 +1002992c: f040 808e bne.w 10029a4c +10029930: 2b02 cmp r3, #2 +10029932: f640 066c movw r6, #2156 ; 0x86c +10029936: f640 6504 movw r5, #3588 ; 0xe04 +1002993a: f640 6414 movw r4, #3604 ; 0xe14 +1002993e: f640 6118 movw r1, #3608 ; 0xe18 +10029942: d02e beq.n 100299a2 +10029944: 2b04 cmp r3, #4 +10029946: d031 beq.n 100299ac +10029948: 2b0b cmp r3, #11 +1002994a: d032 beq.n 100299b2 +1002994c: 2b0c cmp r3, #12 +1002994e: d037 beq.n 100299c0 +10029950: 2b12 cmp r3, #18 +10029952: d038 beq.n 100299c6 +10029954: 2b16 cmp r3, #22 +10029956: d02f beq.n 100299b8 +10029958: 2b18 cmp r3, #24 +1002995a: d037 beq.n 100299cc +1002995c: 2b24 cmp r3, #36 ; 0x24 +1002995e: d038 beq.n 100299d2 +10029960: 2b30 cmp r3, #48 ; 0x30 +10029962: d03b beq.n 100299dc +10029964: 2b48 cmp r3, #72 ; 0x48 +10029966: d03c beq.n 100299e2 +10029968: 2b60 cmp r3, #96 ; 0x60 +1002996a: d03d beq.n 100299e8 +1002996c: 2b6c cmp r3, #108 ; 0x6c +1002996e: d03e beq.n 100299ee +10029970: 2b80 cmp r3, #128 ; 0x80 +10029972: d040 beq.n 100299f6 +10029974: 2b81 cmp r3, #129 ; 0x81 +10029976: d041 beq.n 100299fc +10029978: 2b82 cmp r3, #130 ; 0x82 +1002997a: d042 beq.n 10029a02 +1002997c: 2b83 cmp r3, #131 ; 0x83 +1002997e: d043 beq.n 10029a08 +10029980: 2b84 cmp r3, #132 ; 0x84 +10029982: d046 beq.n 10029a12 +10029984: 2b85 cmp r3, #133 ; 0x85 +10029986: d047 beq.n 10029a18 +10029988: 2b86 cmp r3, #134 ; 0x86 +1002998a: d048 beq.n 10029a1e +1002998c: 2b87 cmp r3, #135 ; 0x87 +1002998e: d049 beq.n 10029a24 +10029990: 2b88 cmp r3, #136 ; 0x88 +10029992: d04b beq.n 10029a2c +10029994: 2b89 cmp r3, #137 ; 0x89 +10029996: d04c beq.n 10029a32 +10029998: 2b8a cmp r3, #138 ; 0x8a +1002999a: d04d beq.n 10029a38 +1002999c: 2b8b cmp r3, #139 ; 0x8b +1002999e: d04e beq.n 10029a3e +100299a0: bdf1 pop {r0, r4, r5, r6, r7, pc} +100299a2: f000 f85c bl 10029a5e <.text_18> +100299a6: f640 6108 movw r1, #3592 ; 0xe08 +100299aa: e04a b.n 10029a42 +100299ac: f000 f857 bl 10029a5e <.text_18> +100299b0: e004 b.n 100299bc +100299b2: f000 f850 bl 10029a56 <.text_17> +100299b6: e001 b.n 100299bc +100299b8: f000 f849 bl 10029a4e <.text_16> +100299bc: 4631 mov r1, r6 +100299be: e040 b.n 10029a42 +100299c0: 463b mov r3, r7 +100299c2: 22ff movs r2, #255 ; 0xff +100299c4: e007 b.n 100299d6 +100299c6: f000 f84a bl 10029a5e <.text_18> +100299ca: e004 b.n 100299d6 +100299cc: f000 f843 bl 10029a56 <.text_17> +100299d0: e001 b.n 100299d6 +100299d2: f000 f83c bl 10029a4e <.text_16> +100299d6: f44f 6160 mov.w r1, #3584 ; 0xe00 +100299da: e032 b.n 10029a42 +100299dc: 463b mov r3, r7 +100299de: 22ff movs r2, #255 ; 0xff +100299e0: e007 b.n 100299f2 +100299e2: f000 f83c bl 10029a5e <.text_18> +100299e6: e004 b.n 100299f2 +100299e8: f000 f835 bl 10029a56 <.text_17> +100299ec: e001 b.n 100299f2 +100299ee: f000 f82e bl 10029a4e <.text_16> +100299f2: 4629 mov r1, r5 +100299f4: e025 b.n 10029a42 +100299f6: 463b mov r3, r7 +100299f8: 22ff movs r2, #255 ; 0xff +100299fa: e007 b.n 10029a0c +100299fc: f000 f82f bl 10029a5e <.text_18> +10029a00: e004 b.n 10029a0c +10029a02: f000 f828 bl 10029a56 <.text_17> +10029a06: e001 b.n 10029a0c +10029a08: f000 f821 bl 10029a4e <.text_16> +10029a0c: f44f 6161 mov.w r1, #3600 ; 0xe10 +10029a10: e017 b.n 10029a42 +10029a12: 463b mov r3, r7 +10029a14: 22ff movs r2, #255 ; 0xff +10029a16: e007 b.n 10029a28 +10029a18: f000 f821 bl 10029a5e <.text_18> +10029a1c: e004 b.n 10029a28 +10029a1e: f000 f81a bl 10029a56 <.text_17> +10029a22: e001 b.n 10029a28 +10029a24: f000 f813 bl 10029a4e <.text_16> +10029a28: 4621 mov r1, r4 +10029a2a: e00a b.n 10029a42 +10029a2c: 463b mov r3, r7 +10029a2e: 22ff movs r2, #255 ; 0xff +10029a30: e007 b.n 10029a42 +10029a32: f000 f814 bl 10029a5e <.text_18> +10029a36: e004 b.n 10029a42 +10029a38: f000 f80d bl 10029a56 <.text_17> +10029a3c: e001 b.n 10029a42 +10029a3e: f000 f806 bl 10029a4e <.text_16> +10029a42: b001 add sp, #4 +10029a44: e8bd 40f0 ldmia.w sp!, {r4, r5, r6, r7, lr} +10029a48: f7ed bd98 b.w 1001757c +10029a4c: bdf1 pop {r0, r4, r5, r6, r7, pc} + +10029a4e <.text_16>: +10029a4e: 463b mov r3, r7 +10029a50: f04f 427f mov.w r2, #4278190080 ; 0xff000000 +10029a54: 4770 bx lr + +10029a56 <.text_17>: +10029a56: 463b mov r3, r7 +10029a58: f44f 027f mov.w r2, #16711680 ; 0xff0000 +10029a5c: 4770 bx lr + +10029a5e <.text_18>: +10029a5e: 463b mov r3, r7 +10029a60: f44f 427f mov.w r2, #65280 ; 0xff00 +10029a64: 4770 bx lr + +10029a66 : +10029a66: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} +10029a6a: f000 f8cc bl 10029c06 <.text_26> +10029a6e: b085 sub sp, #20 +10029a70: 5907 ldr r7, [r0, r4] +10029a72: 2000 movs r0, #0 +10029a74: f88d 000c strb.w r0, [sp, #12] +10029a78: 460d mov r5, r1 +10029a7a: a803 add r0, sp, #12 +10029a7c: 9001 str r0, [sp, #4] +10029a7e: 4616 mov r6, r2 +10029a80: 980c ldr r0, [sp, #48] ; 0x30 +10029a82: 9000 str r0, [sp, #0] +10029a84: 4620 mov r0, r4 +10029a86: f005 fb09 bl 1002f09c +10029a8a: 4680 mov r8, r0 +10029a8c: 2200 movs r2, #0 +10029a8e: 9600 str r6, [sp, #0] +10029a90: 2300 movs r3, #0 +10029a92: 4611 mov r1, r2 +10029a94: 4620 mov r0, r4 +10029a96: f005 fd5e bl 1002f556 +10029a9a: 4681 mov r9, r0 +10029a9c: f89d 000c ldrb.w r0, [sp, #12] +10029aa0: 1e42 subs r2, r0, #1 +10029aa2: f897 0044 ldrb.w r0, [r7, #68] ; 0x44 +10029aa6: 9002 str r0, [sp, #8] +10029aa8: 9601 str r6, [sp, #4] +10029aaa: f641 1004 movw r0, #6404 ; 0x1904 +10029aae: 9500 str r5, [sp, #0] +10029ab0: 4192 sbcs r2, r2 +10029ab2: 5d01 ldrb r1, [r0, r4] +10029ab4: 6bfb ldr r3, [r7, #60] ; 0x3c +10029ab6: 0fd2 lsrs r2, r2, #31 +10029ab8: 4620 mov r0, r4 +10029aba: f005 fe32 bl 1002f722 +10029abe: 4548 cmp r0, r9 +10029ac0: bfc8 it gt +10029ac2: 4648 movgt r0, r9 +10029ac4: eb00 0708 add.w r7, r0, r8 +10029ac8: 4632 mov r2, r6 +10029aca: 4629 mov r1, r5 +10029acc: 4620 mov r0, r4 +10029ace: f005 fb88 bl 1002f1e2 +10029ad2: 19c0 adds r0, r0, r7 +10029ad4: b240 sxtb r0, r0 +10029ad6: 2840 cmp r0, #64 ; 0x40 +10029ad8: bfa8 it ge +10029ada: 203f movge r0, #63 ; 0x3f +10029adc: b2c0 uxtb r0, r0 +10029ade: b005 add sp, #20 +10029ae0: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + +10029ae4 : +10029ae4: 2200 movs r2, #0 +10029ae6: f005 bd8d b.w 1002f604 + +10029aea : +10029aea: b5f8 push {r3, r4, r5, r6, r7, lr} +10029aec: f000 f88b bl 10029c06 <.text_26> +10029af0: f640 47e4 movw r7, #3300 ; 0xce4 +10029af4: 5900 ldr r0, [r0, r4] +10029af6: f500 55c8 add.w r5, r0, #6400 ; 0x1900 +10029afa: f100 063c add.w r6, r0, #60 ; 0x3c +10029afe: 6bc0 ldr r0, [r0, #60] ; 0x3c +10029b00: 35a8 adds r5, #168 ; 0xa8 +10029b02: 2800 cmp r0, #0 +10029b04: d14e bne.n 10029ba4 +10029b06: 7a30 ldrb r0, [r6, #8] +10029b08: 280d cmp r0, #13 +10029b0a: bf18 it ne +10029b0c: 280e cmpne r0, #14 +10029b0e: d109 bne.n 10029b24 +10029b10: 2306 movs r3, #6 +10029b12: f000 f86e bl 10029bf2 <.text_24+0x2> +10029b16: f000 f91a bl 10029d4e <.text_32> +10029b1a: 2300 movs r3, #0 +10029b1c: f000 f913 bl 10029d46 <.text_31+0x2> +10029b20: 2300 movs r3, #0 +10029b22: e006 b.n 10029b32 +10029b24: f000 f864 bl 10029bf0 <.text_24> +10029b28: f000 f911 bl 10029d4e <.text_32> +10029b2c: f000 f90a bl 10029d44 <.text_31> +10029b30: 2301 movs r3, #1 +10029b32: f04f 5240 mov.w r2, #805306368 ; 0x30000000 +10029b36: 4639 mov r1, r7 +10029b38: f000 f909 bl 10029d4e <.text_32> +10029b3c: 7a30 ldrb r0, [r6, #8] +10029b3e: 280e cmp r0, #14 +10029b40: f640 1754 movw r7, #2388 ; 0x954 +10029b44: d115 bne.n 10029b72 +10029b46: 2301 movs r3, #1 +10029b48: f44f 7200 mov.w r2, #512 ; 0x200 +10029b4c: f44f 6144 mov.w r1, #3136 ; 0xc40 +10029b50: f000 f8fd bl 10029d4e <.text_32> +10029b54: 2303 movs r3, #3 +10029b56: f04f 52f8 mov.w r2, #520093696 ; 0x1f000000 +10029b5a: f44f 6144 mov.w r1, #3136 ; 0xc40 +10029b5e: f000 f8f6 bl 10029d4e <.text_32> +10029b62: 2301 movs r3, #1 +10029b64: f04f 4270 mov.w r2, #4026531840 ; 0xf0000000 +10029b68: 4639 mov r1, r7 +10029b6a: f000 f8f0 bl 10029d4e <.text_32> +10029b6e: 2307 movs r3, #7 +10029b70: e014 b.n 10029b9c +10029b72: 2300 movs r3, #0 +10029b74: f44f 7200 mov.w r2, #512 ; 0x200 +10029b78: f44f 6144 mov.w r1, #3136 ; 0xc40 +10029b7c: f000 f8e7 bl 10029d4e <.text_32> +10029b80: 231f movs r3, #31 +10029b82: f04f 52f8 mov.w r2, #520093696 ; 0x1f000000 +10029b86: f44f 6144 mov.w r1, #3136 ; 0xc40 +10029b8a: f000 f8e0 bl 10029d4e <.text_32> +10029b8e: 2303 movs r3, #3 +10029b90: f04f 4270 mov.w r2, #4026531840 ; 0xf0000000 +10029b94: 4639 mov r1, r7 +10029b96: f000 f8da bl 10029d4e <.text_32> +10029b9a: 230a movs r3, #10 +10029b9c: 220f movs r2, #15 +10029b9e: f44f 6143 mov.w r1, #3120 ; 0xc30 +10029ba2: e009 b.n 10029bb8 +10029ba4: f000 f824 bl 10029bf0 <.text_24> +10029ba8: f000 f8d1 bl 10029d4e <.text_32> +10029bac: f000 f8ca bl 10029d44 <.text_31> +10029bb0: 2301 movs r3, #1 +10029bb2: f04f 5240 mov.w r2, #805306368 ; 0x30000000 +10029bb6: 4639 mov r1, r7 +10029bb8: f000 f8c9 bl 10029d4e <.text_32> +10029bbc: 7a30 ldrb r0, [r6, #8] +10029bbe: 280b cmp r0, #11 +10029bc0: f640 542c movw r4, #3372 ; 0xd2c +10029bc4: f640 5144 movw r1, #3396 ; 0xd44 +10029bc8: d105 bne.n 10029bd6 +10029bca: f04f 63c0 mov.w r3, #100663296 ; 0x6000000 +10029bce: f000 f815 bl 10029bfc <.text_25> +10029bd2: 2301 movs r3, #1 +10029bd4: e003 b.n 10029bde +10029bd6: 2300 movs r3, #0 +10029bd8: f000 f810 bl 10029bfc <.text_25> +10029bdc: 2300 movs r3, #0 +10029bde: 4621 mov r1, r4 +10029be0: 4628 mov r0, r5 +10029be2: b001 add sp, #4 +10029be4: e8bd 40f0 ldmia.w sp!, {r4, r5, r6, r7, lr} +10029be8: f04f 5280 mov.w r2, #268435456 ; 0x10000000 +10029bec: f007 b9b0 b.w 10030f50 + +10029bf0 <.text_24>: +10029bf0: 2307 movs r3, #7 +10029bf2: f44f 62e0 mov.w r2, #1792 ; 0x700 +10029bf6: f44f 6100 mov.w r1, #2048 ; 0x800 +10029bfa: 4770 bx lr + +10029bfc <.text_25>: +10029bfc: f04f 32ff mov.w r2, #4294967295 +10029c00: 4628 mov r0, r5 +10029c02: f007 b9a5 b.w 10030f50 + +10029c06 <.text_26>: +10029c06: 4604 mov r4, r0 +10029c08: f641 30a4 movw r0, #7076 ; 0x1ba4 +10029c0c: 4770 bx lr + +10029c0e : +10029c0e: b538 push {r3, r4, r5, lr} +10029c10: 460d mov r5, r1 +10029c12: 4604 mov r4, r0 +10029c14: f44f 61cd mov.w r1, #1640 ; 0x668 +10029c18: f7fb f80e bl 10024c38 +10029c1c: b11d cbz r5, 10029c26 +10029c1e: 2d02 cmp r5, #2 +10029c20: d00c beq.n 10029c3c +10029c22: d305 bcc.n 10029c30 +10029c24: bd31 pop {r0, r4, r5, pc} +10029c26: f64f 617f movw r1, #65151 ; 0xfe7f +10029c2a: ea01 0200 and.w r2, r1, r0 +10029c2e: e00a b.n 10029c46 +10029c30: f64f 61ff movw r1, #65279 ; 0xfeff +10029c34: 4008 ands r0, r1 +10029c36: f040 0280 orr.w r2, r0, #128 ; 0x80 +10029c3a: e004 b.n 10029c46 +10029c3c: f64f 717f movw r1, #65407 ; 0xff7f +10029c40: 4008 ands r0, r1 +10029c42: f440 7280 orr.w r2, r0, #256 ; 0x100 +10029c46: 4620 mov r0, r4 +10029c48: e8bd 4038 ldmia.w sp!, {r3, r4, r5, lr} +10029c4c: f44f 61cd mov.w r1, #1640 ; 0x668 +10029c50: f7fb b806 b.w 10024c60 + +10029c54 : +10029c54: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +10029c58: f7ff ffd5 bl 10029c06 <.text_26> +10029c5c: 5905 ldr r5, [r0, r4] +10029c5e: 6be9 ldr r1, [r5, #60] ; 0x3c +10029c60: 4620 mov r0, r4 +10029c62: f7ff ffd4 bl 10029c0e +10029c66: 6be8 ldr r0, [r5, #60] ; 0x3c +10029c68: f105 073c add.w r7, r5, #60 ; 0x3c +10029c6c: f640 1654 movw r6, #2388 ; 0x954 +10029c70: f640 48e4 movw r8, #3300 ; 0xce4 +10029c74: b110 cbz r0, 10029c7c +10029c76: 2801 cmp r0, #1 +10029c78: d020 beq.n 10029cbc +10029c7a: e057 b.n 10029d2c +10029c7c: 2300 movs r3, #0 +10029c7e: 2201 movs r2, #1 +10029c80: f44f 6100 mov.w r1, #2048 ; 0x800 +10029c84: f000 f863 bl 10029d4e <.text_32> +10029c88: 2300 movs r3, #0 +10029c8a: 2201 movs r2, #1 +10029c8c: f44f 6110 mov.w r1, #2304 ; 0x900 +10029c90: f000 f85d bl 10029d4e <.text_32> +10029c94: f000 f850 bl 10029d38 <.text_30> +10029c98: f000 f859 bl 10029d4e <.text_32> +10029c9c: f000 f85a bl 10029d54 <.text_33> +10029ca0: f000 f850 bl 10029d44 <.text_31> +10029ca4: 7a38 ldrb r0, [r7, #8] +10029ca6: 280d cmp r0, #13 +10029ca8: bf14 ite ne +10029caa: 280e cmpne r0, #14 +10029cac: 230b moveq r3, #11 +10029cae: d033 beq.n 10029d18 +10029cb0: f000 f8a2 bl 10029df8 <.text_37> +10029cb4: f000 f84b bl 10029d4e <.text_32> +10029cb8: 2301 movs r3, #1 +10029cba: e032 b.n 10029d22 +10029cbc: 2301 movs r3, #1 +10029cbe: 2201 movs r2, #1 +10029cc0: f44f 6100 mov.w r1, #2048 ; 0x800 +10029cc4: f000 f843 bl 10029d4e <.text_32> +10029cc8: 2301 movs r3, #1 +10029cca: 461a mov r2, r3 +10029ccc: f44f 6110 mov.w r1, #2304 ; 0x900 +10029cd0: f000 f83d bl 10029d4e <.text_32> +10029cd4: 7a78 ldrb r0, [r7, #9] +10029cd6: 0843 lsrs r3, r0, #1 +10029cd8: 2210 movs r2, #16 +10029cda: f44f 6120 mov.w r1, #2560 ; 0xa00 +10029cde: f000 f836 bl 10029d4e <.text_32> +10029ce2: 7a7b ldrb r3, [r7, #9] +10029ce4: f44f 6240 mov.w r2, #3072 ; 0xc00 +10029ce8: f44f 6150 mov.w r1, #3328 ; 0xd00 +10029cec: f000 f82f bl 10029d4e <.text_32> +10029cf0: 7a78 ldrb r0, [r7, #9] +10029cf2: 2801 cmp r0, #1 +10029cf4: bf0c ite eq +10029cf6: 2302 moveq r3, #2 +10029cf8: 2301 movne r3, #1 +10029cfa: f04f 6240 mov.w r2, #201326592 ; 0xc000000 +10029cfe: f640 0118 movw r1, #2072 ; 0x818 +10029d02: f000 f824 bl 10029d4e <.text_32> +10029d06: f000 f817 bl 10029d38 <.text_30> +10029d0a: f000 f820 bl 10029d4e <.text_32> +10029d0e: f000 f821 bl 10029d54 <.text_33> +10029d12: f000 f817 bl 10029d44 <.text_31> +10029d16: 2306 movs r3, #6 +10029d18: f000 f86f bl 10029dfa <.text_37+0x2> +10029d1c: f000 f817 bl 10029d4e <.text_32> +10029d20: 2300 movs r3, #0 +10029d22: f44f 2200 mov.w r2, #524288 ; 0x80000 +10029d26: 4631 mov r1, r6 +10029d28: f000 f811 bl 10029d4e <.text_32> +10029d2c: 6be9 ldr r1, [r5, #60] ; 0x3c +10029d2e: 4620 mov r0, r4 +10029d30: e8bd 41f0 ldmia.w sp!, {r4, r5, r6, r7, r8, lr} +10029d34: f008 bd82 b.w 1003283c + +10029d38 <.text_30>: +10029d38: 2303 movs r3, #3 +10029d3a: f44f 7240 mov.w r2, #768 ; 0x300 +10029d3e: f44f 6100 mov.w r1, #2048 ; 0x800 +10029d42: 4770 bx lr + +10029d44 <.text_31>: +10029d44: 2301 movs r3, #1 +10029d46: f04f 5240 mov.w r2, #805306368 ; 0x30000000 +10029d4a: f44f 6141 mov.w r1, #3088 ; 0xc10 + +10029d4e <.text_32>: +10029d4e: 4620 mov r0, r4 +10029d50: f7ed bc14 b.w 1001757c + +10029d54 <.text_33>: +10029d54: 2301 movs r3, #1 +10029d56: f04f 4270 mov.w r2, #4026531840 ; 0xf0000000 +10029d5a: 4641 mov r1, r8 +10029d5c: 4620 mov r0, r4 +10029d5e: f7ed bc0d b.w 1001757c + +10029d62 : +10029d62: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +10029d66: f7ff ff4e bl 10029c06 <.text_26> +10029d6a: b082 sub sp, #8 +10029d6c: 5906 ldr r6, [r0, r4] +10029d6e: f106 053c add.w r5, r6, #60 ; 0x3c +10029d72: 7ba8 ldrb r0, [r5, #14] +10029d74: 2805 cmp r0, #5 +10029d76: d039 beq.n 10029dec +10029d78: f641 1734 movw r7, #6452 ; 0x1934 +10029d7c: 491d ldr r1, [pc, #116] ; (10029df4 <.text_36>) +10029d7e: 59b8 ldr r0, [r7, r6] +10029d80: f8df 806c ldr.w r8, [pc, #108] ; 10029df0 <.text_35> +10029d84: 4008 ands r0, r1 +10029d86: 7a29 ldrb r1, [r5, #8] +10029d88: 4308 orrs r0, r1 +10029d8a: 51b8 str r0, [r7, r6] +10029d8c: 9000 str r0, [sp, #0] +10029d8e: 4643 mov r3, r8 +10029d90: 2218 movs r2, #24 +10029d92: 2100 movs r1, #0 +10029d94: 4620 mov r0, r4 +10029d96: f7ff fce7 bl 10029768 +10029d9a: 59b8 ldr r0, [r7, r6] +10029d9c: 9000 str r0, [sp, #0] +10029d9e: 4643 mov r3, r8 +10029da0: 2218 movs r2, #24 +10029da2: 2101 movs r1, #1 +10029da4: 4620 mov r0, r4 +10029da6: f7ff fcdf bl 10029768 +10029daa: 6bf0 ldr r0, [r6, #60] ; 0x3c +10029dac: f640 1654 movw r6, #2388 ; 0x954 +10029db0: b958 cbnz r0, 10029dca +10029db2: 7a28 ldrb r0, [r5, #8] +10029db4: 280d cmp r0, #13 +10029db6: bf14 ite ne +10029db8: 280e cmpne r0, #14 +10029dba: 230b moveq r3, #11 +10029dbc: d008 beq.n 10029dd0 +10029dbe: f000 f81b bl 10029df8 <.text_37> +10029dc2: f7ff ffc4 bl 10029d4e <.text_32> +10029dc6: 2301 movs r3, #1 +10029dc8: e007 b.n 10029dda +10029dca: 2801 cmp r0, #1 +10029dcc: d10e bne.n 10029dec +10029dce: 2306 movs r3, #6 +10029dd0: f000 f813 bl 10029dfa <.text_37+0x2> +10029dd4: f7ff ffbb bl 10029d4e <.text_32> +10029dd8: 2300 movs r3, #0 +10029dda: 4631 mov r1, r6 +10029ddc: 4620 mov r0, r4 +10029dde: b002 add sp, #8 +10029de0: e8bd 41f0 ldmia.w sp!, {r4, r5, r6, r7, r8, lr} +10029de4: f44f 2200 mov.w r2, #524288 ; 0x80000 +10029de8: f7ed bbc8 b.w 1001757c +10029dec: e8bd 81f3 ldmia.w sp!, {r0, r1, r4, r5, r6, r7, r8, pc} + +10029df0 <.text_35>: +10029df0: 000fffff .word 0x000fffff + +10029df4 <.text_36>: +10029df4: 0ffffc00 .word 0x0ffffc00 + +10029df8 <.text_37>: +10029df8: 23a8 movs r3, #168 ; 0xa8 +10029dfa: f04f 627f mov.w r2, #267386880 ; 0xff00000 +10029dfe: 4631 mov r1, r6 +10029e00: 4770 bx lr + +10029e02 : +10029e02: b570 push {r4, r5, r6, lr} +10029e04: f7ff feff bl 10029c06 <.text_26> +10029e08: 5905 ldr r5, [r0, r4] +10029e0a: f641 409c movw r0, #7324 ; 0x1c9c +10029e0e: 5901 ldr r1, [r0, r4] +10029e10: 2900 cmp r1, #0 +10029e12: bf02 ittt eq +10029e14: 1900 addeq r0, r0, r4 +10029e16: 6840 ldreq r0, [r0, #4] +10029e18: 2800 cmpeq r0, #0 +10029e1a: d119 bne.n 10029e50 +10029e1c: f641 06ba movw r6, #6330 ; 0x18ba +10029e20: 5d70 ldrb r0, [r6, r5] +10029e22: b120 cbz r0, 10029e2e +10029e24: 4620 mov r0, r4 +10029e26: f7ff ff9c bl 10029d62 +10029e2a: 2000 movs r0, #0 +10029e2c: 5570 strb r0, [r6, r5] +10029e2e: 1976 adds r6, r6, r5 +10029e30: 7870 ldrb r0, [r6, #1] +10029e32: b120 cbz r0, 10029e3e +10029e34: 4620 mov r0, r4 +10029e36: f7ff ff0d bl 10029c54 +10029e3a: 2000 movs r0, #0 +10029e3c: 7070 strb r0, [r6, #1] +10029e3e: 4620 mov r0, r4 +10029e40: f7ff fe53 bl 10029aea +10029e44: 4620 mov r0, r4 +10029e46: f895 1044 ldrb.w r1, [r5, #68] ; 0x44 +10029e4a: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +10029e4e: e649 b.n 10029ae4 +10029e50: bd70 pop {r4, r5, r6, pc} + +10029e52 : +10029e52: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +10029e56: 4680 mov r8, r0 +10029e58: f641 30a4 movw r0, #7076 ; 0x1ba4 +10029e5c: b083 sub sp, #12 +10029e5e: f850 7008 ldr.w r7, [r0, r8] +10029e62: 6bf8 ldr r0, [r7, #60] ; 0x3c +10029e64: f107 043c add.w r4, r7, #60 ; 0x3c +10029e68: 4691 mov r9, r2 +10029e6a: 7a25 ldrb r5, [r4, #8] +10029e6c: 9001 str r0, [sp, #4] +10029e6e: 469b mov fp, r3 +10029e70: 7a60 ldrb r0, [r4, #9] +10029e72: f88d 0001 strb.w r0, [sp, #1] +10029e76: 7ae0 ldrb r0, [r4, #11] +10029e78: f88d 0000 strb.w r0, [sp] +10029e7c: ea59 0001 orrs.w r0, r9, r1 +10029e80: f894 a00a ldrb.w sl, [r4, #10] +10029e84: d042 beq.n 10029f0c +10029e86: f641 06ba movw r6, #6330 ; 0x18ba +10029e8a: b131 cbz r1, 10029e9a +10029e8c: 4659 mov r1, fp +10029e8e: 4640 mov r0, r8 +10029e90: f7fc fd45 bl 1002691e +10029e94: b108 cbz r0, 10029e9a +10029e96: 2001 movs r0, #1 +10029e98: 55f0 strb r0, [r6, r7] +10029e9a: 19f0 adds r0, r6, r7 +10029e9c: f1b9 0f00 cmp.w r9, #0 +10029ea0: d01f beq.n 10029ee2 +10029ea2: 2101 movs r1, #1 +10029ea4: 7041 strb r1, [r0, #1] +10029ea6: 5df1 ldrb r1, [r6, r7] +10029ea8: b119 cbz r1, 10029eb2 +10029eaa: f884 b008 strb.w fp, [r4, #8] +10029eae: f884 b00a strb.w fp, [r4, #10] +10029eb2: 7842 ldrb r2, [r0, #1] +10029eb4: b13a cbz r2, 10029ec6 +10029eb6: 980c ldr r0, [sp, #48] ; 0x30 +10029eb8: 63f8 str r0, [r7, #60] ; 0x3c +10029eba: 980d ldr r0, [sp, #52] ; 0x34 +10029ebc: 7260 strb r0, [r4, #9] +10029ebe: 980e ldr r0, [sp, #56] ; 0x38 +10029ec0: 72e0 strb r0, [r4, #11] +10029ec2: 980f ldr r0, [sp, #60] ; 0x3c +10029ec4: 72a0 strb r0, [r4, #10] +10029ec6: f641 409c movw r0, #7324 ; 0x1c9c +10029eca: f850 3008 ldr.w r3, [r0, r8] +10029ece: 2b00 cmp r3, #0 +10029ed0: bf02 ittt eq +10029ed2: 4440 addeq r0, r8 +10029ed4: 6840 ldreq r0, [r0, #4] +10029ed6: 2800 cmpeq r0, #0 +10029ed8: d10a bne.n 10029ef0 +10029eda: 4640 mov r0, r8 +10029edc: e8bd 4ffe ldmia.w sp!, {r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +10029ee0: e78f b.n 10029e02 +10029ee2: 7841 ldrb r1, [r0, #1] +10029ee4: 2900 cmp r1, #0 +10029ee6: bf04 itt eq +10029ee8: 5df1 ldrbeq r1, [r6, r7] +10029eea: 2900 cmpeq r1, #0 +10029eec: d1db bne.n 10029ea6 +10029eee: e00d b.n 10029f0c +10029ef0: b109 cbz r1, 10029ef6 +10029ef2: 7225 strb r5, [r4, #8] +10029ef4: 72a5 strb r5, [r4, #10] +10029ef6: b14a cbz r2, 10029f0c +10029ef8: 9801 ldr r0, [sp, #4] +10029efa: 63f8 str r0, [r7, #60] ; 0x3c +10029efc: f89d 0001 ldrb.w r0, [sp, #1] +10029f00: 7260 strb r0, [r4, #9] +10029f02: f89d 0000 ldrb.w r0, [sp] +10029f06: 72e0 strb r0, [r4, #11] +10029f08: f884 a00a strb.w sl, [r4, #10] +10029f0c: e8bd 8ff7 ldmia.w sp!, {r0, r1, r2, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +10029f10 : +10029f10: b500 push {lr} +10029f12: f641 33a4 movw r3, #7076 ; 0x1ba4 +10029f16: b085 sub sp, #20 +10029f18: 581b ldr r3, [r3, r0] +10029f1a: f893 3044 ldrb.w r3, [r3, #68] ; 0x44 +10029f1e: 9202 str r2, [sp, #8] +10029f20: 9201 str r2, [sp, #4] +10029f22: 9100 str r1, [sp, #0] +10029f24: 9303 str r3, [sp, #12] +10029f26: 2201 movs r2, #1 +10029f28: 2100 movs r1, #0 +10029f2a: e008 b.n 10029f3e <.text_42> + +10029f2c : +10029f2c: b500 push {lr} +10029f2e: b085 sub sp, #20 +10029f30: 2200 movs r2, #0 +10029f32: 9103 str r1, [sp, #12] +10029f34: 460b mov r3, r1 +10029f36: 9202 str r2, [sp, #8] +10029f38: 9201 str r2, [sp, #4] +10029f3a: 9200 str r2, [sp, #0] +10029f3c: 2101 movs r1, #1 + +10029f3e <.text_42>: +10029f3e: f7ff ff88 bl 10029e52 +10029f42: b005 add sp, #20 +10029f44: bd00 pop {pc} + +10029f46 : +10029f46: b51f push {r0, r1, r2, r3, r4, lr} +10029f48: 9301 str r3, [sp, #4] +10029f4a: 9103 str r1, [sp, #12] +10029f4c: 9200 str r2, [sp, #0] +10029f4e: 460b mov r3, r1 +10029f50: 9c06 ldr r4, [sp, #24] +10029f52: 9402 str r4, [sp, #8] +10029f54: 2201 movs r2, #1 +10029f56: 2101 movs r1, #1 +10029f58: f7ff ff7b bl 10029e52 +10029f5c: bd1f pop {r0, r1, r2, r3, r4, pc} + ... + +10029f60 : +10029f60: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +10029f64: 292b cmp r1, #43 ; 0x2b +10029f66: 4604 mov r4, r0 +10029f68: bfa8 it ge +10029f6a: 212a movge r1, #42 ; 0x2a +10029f6c: da02 bge.n 10029f74 +10029f6e: 2900 cmp r1, #0 +10029f70: bf48 it mi +10029f72: 2100 movmi r1, #0 +10029f74: f8df 0b7c ldr.w r0, [pc, #2940] ; 1002aaf4 <.text_47> +10029f78: f850 0021 ldr.w r0, [r0, r1, lsl #2] +10029f7c: 0d81 lsrs r1, r0, #22 +10029f7e: f640 454c movw r5, #3148 ; 0xc4c +10029f82: f640 4894 movw r8, #3220 ; 0xc94 +10029f86: b33b cbz r3, 10029fd8 +10029f88: 6ea7 ldr r7, [r4, #104] ; 0x68 +10029f8a: 783f ldrb r7, [r7, #0] +10029f8c: bb27 cbnz r7, 10029fd8 +10029f8e: f8df 6c78 ldr.w r6, [pc, #3192] ; 1002ac08 <.text_51> +10029f92: 0598 lsls r0, r3, #22 +10029f94: bf48 it mi +10029f96: 4333 orrmi r3, r6 +10029f98: fb01 f703 mul.w r7, r1, r3 +10029f9c: 9b06 ldr r3, [sp, #24] +10029f9e: 03b8 lsls r0, r7, #14 +10029fa0: ea5f 5e83 movs.w lr, r3, lsl #22 +10029fa4: bf48 it mi +10029fa6: 4333 orrmi r3, r6 +10029fa8: 434b muls r3, r1 +10029faa: 039b lsls r3, r3, #14 +10029fac: 0d9e lsrs r6, r3, #22 +10029fae: 2a00 cmp r2, #0 +10029fb0: d13a bne.n 1002a028 +10029fb2: f006 023f and.w r2, r6, #63 ; 0x3f +10029fb6: 0412 lsls r2, r2, #16 +10029fb8: ea42 5181 orr.w r1, r2, r1, lsl #22 +10029fbc: ea41 5390 orr.w r3, r1, r0, lsr #22 +10029fc0: f000 f834 bl 1002a02c <.text_3> +10029fc4: 09b3 lsrs r3, r6, #6 +10029fc6: f04f 4270 mov.w r2, #4026531840 ; 0xf0000000 +10029fca: 4641 mov r1, r8 +10029fcc: f000 ff43 bl 1002ae56 <.text_80+0x4> +10029fd0: 11f8 asrs r0, r7, #7 +10029fd2: f000 0301 and.w r3, r0, #1 +10029fd6: e00d b.n 10029ff4 +10029fd8: b112 cbz r2, 10029fe0 +10029fda: 2a01 cmp r2, #1 +10029fdc: d00d beq.n 10029ffa +10029fde: e023 b.n 1002a028 +10029fe0: 4603 mov r3, r0 +10029fe2: f000 f823 bl 1002a02c <.text_3> +10029fe6: 2300 movs r3, #0 +10029fe8: f04f 4270 mov.w r2, #4026531840 ; 0xf0000000 +10029fec: 4641 mov r1, r8 +10029fee: f000 ff32 bl 1002ae56 <.text_80+0x4> +10029ff2: 2300 movs r3, #0 +10029ff4: f04f 7280 mov.w r2, #16777216 ; 0x1000000 +10029ff8: e010 b.n 1002a01c +10029ffa: 4603 mov r3, r0 +10029ffc: f04f 32ff mov.w r2, #4294967295 +1002a000: f640 4188 movw r1, #3208 ; 0xc88 +1002a004: f000 ff27 bl 1002ae56 <.text_80+0x4> +1002a008: 2300 movs r3, #0 +1002a00a: f04f 4270 mov.w r2, #4026531840 ; 0xf0000000 +1002a00e: f640 419c movw r1, #3228 ; 0xc9c +1002a012: f000 ff20 bl 1002ae56 <.text_80+0x4> +1002a016: 2300 movs r3, #0 +1002a018: f04f 5280 mov.w r2, #268435456 ; 0x10000000 +1002a01c: 4629 mov r1, r5 +1002a01e: 4620 mov r0, r4 +1002a020: e8bd 41f0 ldmia.w sp!, {r4, r5, r6, r7, r8, lr} +1002a024: f006 bf94 b.w 10030f50 +1002a028: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +1002a02c <.text_3>: +1002a02c: f04f 32ff mov.w r2, #4294967295 +1002a030: f44f 6148 mov.w r1, #3200 ; 0xc80 +1002a034: 4620 mov r0, r4 +1002a036: f006 bf8b b.w 10030f50 + +1002a03a : +1002a03a: b570 push {r4, r5, r6, lr} +1002a03c: 4604 mov r4, r0 +1002a03e: 4615 mov r5, r2 +1002a040: 6826 ldr r6, [r4, #0] +1002a042: f008 fee1 bl 10032e08 +1002a046: f884 5957 strb.w r5, [r4, #2391] ; 0x957 +1002a04a: 4630 mov r0, r6 +1002a04c: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +1002a050: 2200 movs r2, #0 +1002a052: 2100 movs r1, #0 +1002a054: f001 b98e b.w 1002b374 + +1002a058 : +1002a058: e92d 4ff7 stmdb sp!, {r0, r1, r2, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1002a05c: 4680 mov r8, r0 +1002a05e: 460f mov r7, r1 +1002a060: f8d8 0000 ldr.w r0, [r8] +1002a064: 9001 str r0, [sp, #4] +1002a066: f641 31a4 movw r1, #7076 ; 0x1ba4 +1002a06a: 461c mov r4, r3 +1002a06c: f851 b000 ldr.w fp, [r1, r0] +1002a070: f8d8 00ac ldr.w r0, [r8, #172] ; 0xac +1002a074: 8800 ldrh r0, [r0, #0] +1002a076: 2522 movs r5, #34 ; 0x22 +1002a078: b928 cbnz r0, 1002a086 +1002a07a: f898 00ea ldrb.w r0, [r8, #234] ; 0xea +1002a07e: 28ff cmp r0, #255 ; 0xff +1002a080: d01e beq.n 1002a0c0 +1002a082: f7fc fd1d bl 10026ac0 +1002a086: b2c0 uxtb r0, r0 +1002a088: 28ff cmp r0, #255 ; 0xff +1002a08a: d019 beq.n 1002a0c0 +1002a08c: 1e81 subs r1, r0, #2 +1002a08e: 2915 cmp r1, #21 +1002a090: d316 bcc.n 1002a0c0 +1002a092: f1a0 010c sub.w r1, r0, #12 +1002a096: 2955 cmp r1, #85 ; 0x55 +1002a098: d30b bcc.n 1002a0b2 +1002a09a: 286c cmp r0, #108 ; 0x6c +1002a09c: d010 beq.n 1002a0c0 +1002a09e: f1a0 0180 sub.w r1, r0, #128 ; 0x80 +1002a0a2: 2903 cmp r1, #3 +1002a0a4: bf38 it cc +1002a0a6: 2526 movcc r5, #38 ; 0x26 +1002a0a8: d30a bcc.n 1002a0c0 +1002a0aa: f1a0 0183 sub.w r1, r0, #131 ; 0x83 +1002a0ae: 2902 cmp r1, #2 +1002a0b0: d201 bcs.n 1002a0b6 +1002a0b2: 2524 movs r5, #36 ; 0x24 +1002a0b4: e004 b.n 1002a0c0 +1002a0b6: 3885 subs r0, #133 ; 0x85 +1002a0b8: 2803 cmp r0, #3 +1002a0ba: bf28 it cs +1002a0bc: f898 5f0b ldrbcs.w r5, [r8, #3851] ; 0xf0b +1002a0c0: f89d 0008 ldrb.w r0, [sp, #8] +1002a0c4: 2f01 cmp r7, #1 +1002a0c6: eb00 0108 add.w r1, r0, r8 +1002a0ca: f640 2928 movw r9, #2600 ; 0xa28 +1002a0ce: f640 2a24 movw sl, #2596 ; 0xa24 +1002a0d2: d157 bne.n 1002a184 +1002a0d4: f601 700e addw r0, r1, #3854 ; 0xf0e +1002a0d8: f8d8 5000 ldr.w r5, [r8] +1002a0dc: f891 1f0e ldrb.w r1, [r1, #3854] ; 0xf0e +1002a0e0: 7101 strb r1, [r0, #4] +1002a0e2: 7881 ldrb r1, [r0, #2] +1002a0e4: 7181 strb r1, [r0, #6] +1002a0e6: 2001 movs r0, #1 +1002a0e8: f888 0f17 strb.w r0, [r8, #3863] ; 0xf17 +1002a0ec: f888 0f19 strb.w r0, [r8, #3865] ; 0xf19 +1002a0f0: f89d 0008 ldrb.w r0, [sp, #8] +1002a0f4: b970 cbnz r0, 1002a114 +1002a0f6: f89b 2044 ldrb.w r2, [fp, #68] ; 0x44 +1002a0fa: 2300 movs r3, #0 +1002a0fc: f000 f9e7 bl 1002a4ce <.text_10> +1002a100: f89b 2044 ldrb.w r2, [fp, #68] ; 0x44 +1002a104: 2301 movs r3, #1 +1002a106: f000 f9e2 bl 1002a4ce <.text_10> +1002a10a: f89b 2044 ldrb.w r2, [fp, #68] ; 0x44 +1002a10e: 2302 movs r3, #2 +1002a110: f000 f9dd bl 1002a4ce <.text_10> +1002a114: f895 049e ldrb.w r0, [r5, #1182] ; 0x49e +1002a118: 2820 cmp r0, #32 +1002a11a: bf18 it ne +1002a11c: 2821 cmpne r0, #33 ; 0x21 +1002a11e: f640 259c movw r5, #2716 ; 0xa9c +1002a122: f640 2498 movw r4, #2712 ; 0xa98 +1002a126: d008 beq.n 1002a13a +1002a128: 2822 cmp r0, #34 ; 0x22 +1002a12a: d126 bne.n 1002a17a +1002a12c: f89b 0044 ldrb.w r0, [fp, #68] ; 0x44 +1002a130: 280c cmp r0, #12 +1002a132: bf1c itt ne +1002a134: 280d cmpne r0, #13 +1002a136: 280e cmpne r0, #14 +1002a138: d121 bne.n 1002a17e +1002a13a: f8df 6ad0 ldr.w r6, [pc, #2768] ; 1002ac0c <.text_52> +1002a13e: 6832 ldr r2, [r6, #0] +1002a140: f44f 6122 mov.w r1, #2592 ; 0xa20 +1002a144: f000 f9ba bl 1002a4bc <.text_8> +1002a148: 6872 ldr r2, [r6, #4] +1002a14a: 4651 mov r1, sl +1002a14c: f000 f9b6 bl 1002a4bc <.text_8> +1002a150: 68b2 ldr r2, [r6, #8] +1002a152: 4649 mov r1, r9 +1002a154: f000 f9b2 bl 1002a4bc <.text_8> +1002a158: 68f2 ldr r2, [r6, #12] +1002a15a: 4621 mov r1, r4 +1002a15c: f000 f9ae bl 1002a4bc <.text_8> +1002a160: 6932 ldr r2, [r6, #16] +1002a162: 4629 mov r1, r5 +1002a164: f000 f9aa bl 1002a4bc <.text_8> +1002a168: 6972 ldr r2, [r6, #20] +1002a16a: 4640 mov r0, r8 +1002a16c: b003 add sp, #12 +1002a16e: e8bd 4ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +1002a172: f44f 612a mov.w r1, #2720 ; 0xaa0 +1002a176: f006 bee7 b.w 10030f48 +1002a17a: e8bd 8ff7 ldmia.w sp!, {r0, r1, r2, r4, r5, r6, r7, r8, r9, sl, fp, pc} +1002a17e: f8df 6a90 ldr.w r6, [pc, #2704] ; 1002ac10 <.text_53> +1002a182: e7dc b.n 1002a13e +1002a184: 2024 movs r0, #36 ; 0x24 +1002a186: fb00 8004 mla r0, r0, r4, r8 +1002a18a: 2f00 cmp r7, #0 +1002a18c: f500 6219 add.w r2, r0, #2448 ; 0x990 +1002a190: f8df 4a80 ldr.w r4, [pc, #2688] ; 1002ac14 <.text_54> +1002a194: f8df 6c54 ldr.w r6, [pc, #3156] ; 1002adec <.text_75> +1002a198: d154 bne.n 1002a244 +1002a19a: f991 3f0e ldrsb.w r3, [r1, #3854] ; 0xf0e +1002a19e: f998 1f0b ldrsb.w r1, [r8, #3851] ; 0xf0b +1002a1a2: f998 7f0c ldrsb.w r7, [r8, #3852] ; 0xf0c +1002a1a6: 4419 add r1, r3 +1002a1a8: 443b add r3, r7 +1002a1aa: b25f sxtb r7, r3 +1002a1ac: b24b sxtb r3, r1 +1002a1ae: 42ab cmp r3, r5 +1002a1b0: bfa8 it ge +1002a1b2: 4629 movge r1, r5 +1002a1b4: da03 bge.n 1002a1be +1002a1b6: b249 sxtb r1, r1 +1002a1b8: 2900 cmp r1, #0 +1002a1ba: bf48 it mi +1002a1bc: 2100 movmi r1, #0 +1002a1be: 2f21 cmp r7, #33 ; 0x21 +1002a1c0: bfa8 it ge +1002a1c2: 2720 movge r7, #32 +1002a1c4: da02 bge.n 1002a1cc +1002a1c6: 2f00 cmp r7, #0 +1002a1c8: bf48 it mi +1002a1ca: 2700 movmi r7, #0 +1002a1cc: f89d 3008 ldrb.w r3, [sp, #8] +1002a1d0: 2b00 cmp r3, #0 +1002a1d2: d1d2 bne.n 1002a17a +1002a1d4: f000 f96c bl 1002a4b0 <.text_7> +1002a1d8: b249 sxtb r1, r1 +1002a1da: 4640 mov r0, r8 +1002a1dc: f7ff fec0 bl 10029f60 +1002a1e0: f898 0970 ldrb.w r0, [r8, #2416] ; 0x970 +1002a1e4: eb07 05c7 add.w r5, r7, r7, lsl #3 +1002a1e8: bb38 cbnz r0, 1002a23a +1002a1ea: f000 f96a bl 1002a4c2 <.text_9> +1002a1ee: 19ad adds r5, r5, r6 +1002a1f0: 786a ldrb r2, [r5, #1] +1002a1f2: f640 2123 movw r1, #2595 ; 0xa23 +1002a1f6: f000 f967 bl 1002a4c8 <.text_9+0x6> +1002a1fa: 78aa ldrb r2, [r5, #2] +1002a1fc: 4651 mov r1, sl +1002a1fe: f000 f963 bl 1002a4c8 <.text_9+0x6> +1002a202: 78ea ldrb r2, [r5, #3] +1002a204: f640 2125 movw r1, #2597 ; 0xa25 +1002a208: f000 f95e bl 1002a4c8 <.text_9+0x6> +1002a20c: 792a ldrb r2, [r5, #4] +1002a20e: f640 2126 movw r1, #2598 ; 0xa26 +1002a212: f000 f959 bl 1002a4c8 <.text_9+0x6> +1002a216: 796a ldrb r2, [r5, #5] +1002a218: f640 2127 movw r1, #2599 ; 0xa27 +1002a21c: f000 f954 bl 1002a4c8 <.text_9+0x6> +1002a220: 79aa ldrb r2, [r5, #6] +1002a222: 4649 mov r1, r9 +1002a224: f000 f950 bl 1002a4c8 <.text_9+0x6> +1002a228: 79ea ldrb r2, [r5, #7] +1002a22a: 4640 mov r0, r8 +1002a22c: b003 add sp, #12 +1002a22e: e8bd 4ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +1002a232: f640 2129 movw r1, #2601 ; 0xa29 +1002a236: f006 be81 b.w 10030f3c +1002a23a: 5d2a ldrb r2, [r5, r4] +1002a23c: f000 f942 bl 1002a4c4 <.text_9+0x2> +1002a240: 192d adds r5, r5, r4 +1002a242: e7d5 b.n 1002a1f0 +1002a244: 2f02 cmp r7, #2 +1002a246: d198 bne.n 1002a17a +1002a248: f991 3f0e ldrsb.w r3, [r1, #3854] ; 0xf0e +1002a24c: f998 1f0c ldrsb.w r1, [r8, #3852] ; 0xf0c +1002a250: 1859 adds r1, r3, r1 +1002a252: b24f sxtb r7, r1 +1002a254: f998 1f0b ldrsb.w r1, [r8, #3851] ; 0xf0b +1002a258: 4419 add r1, r3 +1002a25a: f89d 3008 ldrb.w r3, [sp, #8] +1002a25e: 2b00 cmp r3, #0 +1002a260: d18b bne.n 1002a17a +1002a262: b24b sxtb r3, r1 +1002a264: 429d cmp r5, r3 +1002a266: da04 bge.n 1002a272 +1002a268: 1b49 subs r1, r1, r5 +1002a26a: f000 f919 bl 1002a4a0 <.text_6> +1002a26e: b269 sxtb r1, r5 +1002a270: e005 b.n 1002a27e +1002a272: b249 sxtb r1, r1 +1002a274: 2900 cmp r1, #0 +1002a276: d50d bpl.n 1002a294 +1002a278: f000 f912 bl 1002a4a0 <.text_6> +1002a27c: 2100 movs r1, #0 +1002a27e: 4640 mov r0, r8 +1002a280: f7ff fe6e bl 10029f60 +1002a284: 2001 movs r0, #1 +1002a286: f888 0f17 strb.w r0, [r8, #3863] ; 0xf17 +1002a28a: f000 f924 bl 1002a4d6 <.text_11> +1002a28e: f000 f929 bl 1002a4e4 <.text_12> +1002a292: e011 b.n 1002a2b8 +1002a294: f000 f90c bl 1002a4b0 <.text_7> +1002a298: 4640 mov r0, r8 +1002a29a: f7ff fe61 bl 10029f60 +1002a29e: f898 0f17 ldrb.w r0, [r8, #3863] ; 0xf17 +1002a2a2: b148 cbz r0, 1002a2b8 +1002a2a4: 2000 movs r0, #0 +1002a2a6: f888 0f12 strb.w r0, [r8, #3858] ; 0xf12 +1002a2aa: f000 f914 bl 1002a4d6 <.text_11> +1002a2ae: f000 f919 bl 1002a4e4 <.text_12> +1002a2b2: 2000 movs r0, #0 +1002a2b4: f888 0f17 strb.w r0, [r8, #3863] ; 0xf17 +1002a2b8: 2f1d cmp r7, #29 +1002a2ba: db58 blt.n 1002a36e +1002a2bc: f1a7 001c sub.w r0, r7, #28 +1002a2c0: f888 0f14 strb.w r0, [r8, #3860] ; 0xf14 +1002a2c4: f898 0970 ldrb.w r0, [r8, #2416] ; 0x970 +1002a2c8: bb40 cbnz r0, 1002a31c +1002a2ca: f896 20fc ldrb.w r2, [r6, #252] ; 0xfc +1002a2ce: f000 f8f9 bl 1002a4c4 <.text_9+0x2> +1002a2d2: f896 20fd ldrb.w r2, [r6, #253] ; 0xfd +1002a2d6: f640 2123 movw r1, #2595 ; 0xa23 +1002a2da: f000 f8f5 bl 1002a4c8 <.text_9+0x6> +1002a2de: f896 20fe ldrb.w r2, [r6, #254] ; 0xfe +1002a2e2: 4651 mov r1, sl +1002a2e4: f000 f8f0 bl 1002a4c8 <.text_9+0x6> +1002a2e8: f896 20ff ldrb.w r2, [r6, #255] ; 0xff +1002a2ec: f640 2125 movw r1, #2597 ; 0xa25 +1002a2f0: f000 f8ea bl 1002a4c8 <.text_9+0x6> +1002a2f4: f896 2100 ldrb.w r2, [r6, #256] ; 0x100 +1002a2f8: f640 2126 movw r1, #2598 ; 0xa26 +1002a2fc: f000 f8e4 bl 1002a4c8 <.text_9+0x6> +1002a300: f896 2101 ldrb.w r2, [r6, #257] ; 0x101 +1002a304: f640 2127 movw r1, #2599 ; 0xa27 +1002a308: f000 f8de bl 1002a4c8 <.text_9+0x6> +1002a30c: f896 2102 ldrb.w r2, [r6, #258] ; 0x102 +1002a310: 4649 mov r1, r9 +1002a312: f000 f8d9 bl 1002a4c8 <.text_9+0x6> +1002a316: f896 2103 ldrb.w r2, [r6, #259] ; 0x103 +1002a31a: e070 b.n 1002a3fe +1002a31c: f894 20fc ldrb.w r2, [r4, #252] ; 0xfc +1002a320: f000 f8d0 bl 1002a4c4 <.text_9+0x2> +1002a324: f894 20fd ldrb.w r2, [r4, #253] ; 0xfd +1002a328: f640 2123 movw r1, #2595 ; 0xa23 +1002a32c: f000 f8cc bl 1002a4c8 <.text_9+0x6> +1002a330: f894 20fe ldrb.w r2, [r4, #254] ; 0xfe +1002a334: 4651 mov r1, sl +1002a336: f000 f8c7 bl 1002a4c8 <.text_9+0x6> +1002a33a: f894 20ff ldrb.w r2, [r4, #255] ; 0xff +1002a33e: f640 2125 movw r1, #2597 ; 0xa25 +1002a342: f000 f8c1 bl 1002a4c8 <.text_9+0x6> +1002a346: f894 2100 ldrb.w r2, [r4, #256] ; 0x100 +1002a34a: f640 2126 movw r1, #2598 ; 0xa26 +1002a34e: f000 f8bb bl 1002a4c8 <.text_9+0x6> +1002a352: f894 2101 ldrb.w r2, [r4, #257] ; 0x101 +1002a356: f640 2127 movw r1, #2599 ; 0xa27 +1002a35a: f000 f8b5 bl 1002a4c8 <.text_9+0x6> +1002a35e: f894 2102 ldrb.w r2, [r4, #258] ; 0x102 +1002a362: 4649 mov r1, r9 +1002a364: f000 f8b0 bl 1002a4c8 <.text_9+0x6> +1002a368: f894 2103 ldrb.w r2, [r4, #259] ; 0x103 +1002a36c: e047 b.n 1002a3fe +1002a36e: 2f00 cmp r7, #0 +1002a370: d556 bpl.n 1002a420 +1002a372: f888 7f14 strb.w r7, [r8, #3860] ; 0xf14 +1002a376: f898 0970 ldrb.w r0, [r8, #2416] ; 0x970 +1002a37a: bb00 cbnz r0, 1002a3be +1002a37c: 7832 ldrb r2, [r6, #0] +1002a37e: f000 f8a1 bl 1002a4c4 <.text_9+0x2> +1002a382: 7872 ldrb r2, [r6, #1] +1002a384: f640 2123 movw r1, #2595 ; 0xa23 +1002a388: f000 f89e bl 1002a4c8 <.text_9+0x6> +1002a38c: 78b2 ldrb r2, [r6, #2] +1002a38e: 4651 mov r1, sl +1002a390: f000 f89a bl 1002a4c8 <.text_9+0x6> +1002a394: 78f2 ldrb r2, [r6, #3] +1002a396: f640 2125 movw r1, #2597 ; 0xa25 +1002a39a: f000 f895 bl 1002a4c8 <.text_9+0x6> +1002a39e: 7932 ldrb r2, [r6, #4] +1002a3a0: f640 2126 movw r1, #2598 ; 0xa26 +1002a3a4: f000 f890 bl 1002a4c8 <.text_9+0x6> +1002a3a8: 7972 ldrb r2, [r6, #5] +1002a3aa: f640 2127 movw r1, #2599 ; 0xa27 +1002a3ae: f000 f88b bl 1002a4c8 <.text_9+0x6> +1002a3b2: 79b2 ldrb r2, [r6, #6] +1002a3b4: 4649 mov r1, r9 +1002a3b6: f000 f887 bl 1002a4c8 <.text_9+0x6> +1002a3ba: 79f2 ldrb r2, [r6, #7] +1002a3bc: e01f b.n 1002a3fe +1002a3be: 7822 ldrb r2, [r4, #0] +1002a3c0: f000 f880 bl 1002a4c4 <.text_9+0x2> +1002a3c4: 7862 ldrb r2, [r4, #1] +1002a3c6: f640 2123 movw r1, #2595 ; 0xa23 +1002a3ca: f000 f87d bl 1002a4c8 <.text_9+0x6> +1002a3ce: 78a2 ldrb r2, [r4, #2] +1002a3d0: 4651 mov r1, sl +1002a3d2: f000 f879 bl 1002a4c8 <.text_9+0x6> +1002a3d6: 78e2 ldrb r2, [r4, #3] +1002a3d8: f640 2125 movw r1, #2597 ; 0xa25 +1002a3dc: f000 f874 bl 1002a4c8 <.text_9+0x6> +1002a3e0: 7922 ldrb r2, [r4, #4] +1002a3e2: f640 2126 movw r1, #2598 ; 0xa26 +1002a3e6: f000 f86f bl 1002a4c8 <.text_9+0x6> +1002a3ea: 7962 ldrb r2, [r4, #5] +1002a3ec: f640 2127 movw r1, #2599 ; 0xa27 +1002a3f0: f000 f86a bl 1002a4c8 <.text_9+0x6> +1002a3f4: 79a2 ldrb r2, [r4, #6] +1002a3f6: 4649 mov r1, r9 +1002a3f8: f000 f866 bl 1002a4c8 <.text_9+0x6> +1002a3fc: 79e2 ldrb r2, [r4, #7] +1002a3fe: f640 2129 movw r1, #2601 ; 0xa29 +1002a402: f000 f861 bl 1002a4c8 <.text_9+0x6> +1002a406: 2001 movs r0, #1 +1002a408: f888 0f19 strb.w r0, [r8, #3865] ; 0xf19 +1002a40c: 2300 movs r3, #0 +1002a40e: f89b 2044 ldrb.w r2, [fp, #68] ; 0x44 +1002a412: 9801 ldr r0, [sp, #4] +1002a414: b003 add sp, #12 +1002a416: e8bd 4ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +1002a41a: 2100 movs r1, #0 +1002a41c: f004 bdb5 b.w 1002ef8a +1002a420: f898 0970 ldrb.w r0, [r8, #2416] ; 0x970 +1002a424: eb07 05c7 add.w r5, r7, r7, lsl #3 +1002a428: b918 cbnz r0, 1002a432 +1002a42a: f000 f84a bl 1002a4c2 <.text_9> +1002a42e: 19ad adds r5, r5, r6 +1002a430: e003 b.n 1002a43a +1002a432: 5d2a ldrb r2, [r5, r4] +1002a434: f000 f846 bl 1002a4c4 <.text_9+0x2> +1002a438: 192d adds r5, r5, r4 +1002a43a: 786a ldrb r2, [r5, #1] +1002a43c: f640 2123 movw r1, #2595 ; 0xa23 +1002a440: f000 f842 bl 1002a4c8 <.text_9+0x6> +1002a444: 78aa ldrb r2, [r5, #2] +1002a446: 4651 mov r1, sl +1002a448: f000 f83e bl 1002a4c8 <.text_9+0x6> +1002a44c: 78ea ldrb r2, [r5, #3] +1002a44e: f640 2125 movw r1, #2597 ; 0xa25 +1002a452: f000 f839 bl 1002a4c8 <.text_9+0x6> +1002a456: 792a ldrb r2, [r5, #4] +1002a458: f640 2126 movw r1, #2598 ; 0xa26 +1002a45c: f000 f834 bl 1002a4c8 <.text_9+0x6> +1002a460: 796a ldrb r2, [r5, #5] +1002a462: f640 2127 movw r1, #2599 ; 0xa27 +1002a466: f000 f82f bl 1002a4c8 <.text_9+0x6> +1002a46a: 79aa ldrb r2, [r5, #6] +1002a46c: 4649 mov r1, r9 +1002a46e: f000 f82b bl 1002a4c8 <.text_9+0x6> +1002a472: 79ea ldrb r2, [r5, #7] +1002a474: f640 2129 movw r1, #2601 ; 0xa29 +1002a478: f000 f826 bl 1002a4c8 <.text_9+0x6> +1002a47c: f898 0f19 ldrb.w r0, [r8, #3865] ; 0xf19 +1002a480: 2800 cmp r0, #0 +1002a482: d00c beq.n 1002a49e +1002a484: 2000 movs r0, #0 +1002a486: f888 0f14 strb.w r0, [r8, #3860] ; 0xf14 +1002a48a: 4601 mov r1, r0 +1002a48c: f89b 2044 ldrb.w r2, [fp, #68] ; 0x44 +1002a490: 9801 ldr r0, [sp, #4] +1002a492: 2300 movs r3, #0 +1002a494: f004 fd79 bl 1002ef8a +1002a498: 2000 movs r0, #0 +1002a49a: f888 0f19 strb.w r0, [r8, #3865] ; 0xf19 +1002a49e: e66c b.n 1002a17a + +1002a4a0 <.text_6>: +1002a4a0: f888 1f12 strb.w r1, [r8, #3858] ; 0xf12 +1002a4a4: 6851 ldr r1, [r2, #4] +1002a4a6: 9100 str r1, [sp, #0] +1002a4a8: 2200 movs r2, #0 +1002a4aa: f8d0 3990 ldr.w r3, [r0, #2448] ; 0x990 +1002a4ae: 4770 bx lr + +1002a4b0 <.text_7>: +1002a4b0: 6852 ldr r2, [r2, #4] +1002a4b2: 9200 str r2, [sp, #0] +1002a4b4: 2200 movs r2, #0 +1002a4b6: f8d0 3990 ldr.w r3, [r0, #2448] ; 0x990 +1002a4ba: 4770 bx lr + +1002a4bc <.text_8>: +1002a4bc: 4640 mov r0, r8 +1002a4be: f006 bd43 b.w 10030f48 + +1002a4c2 <.text_9>: +1002a4c2: 5daa ldrb r2, [r5, r6] +1002a4c4: f640 2122 movw r1, #2594 ; 0xa22 +1002a4c8: 4640 mov r0, r8 +1002a4ca: f006 bd37 b.w 10030f3c + +1002a4ce <.text_10>: +1002a4ce: 2100 movs r1, #0 +1002a4d0: 4628 mov r0, r5 +1002a4d2: f004 bd5a b.w 1002ef8a + +1002a4d6 <.text_11>: +1002a4d6: 2301 movs r3, #1 +1002a4d8: f89b 2044 ldrb.w r2, [fp, #68] ; 0x44 +1002a4dc: 9801 ldr r0, [sp, #4] +1002a4de: 2100 movs r1, #0 +1002a4e0: f004 bd53 b.w 1002ef8a + +1002a4e4 <.text_12>: +1002a4e4: f89b 2044 ldrb.w r2, [fp, #68] ; 0x44 +1002a4e8: 9801 ldr r0, [sp, #4] +1002a4ea: 2302 movs r3, #2 +1002a4ec: 2100 movs r1, #0 +1002a4ee: f004 bd4c b.w 1002ef8a + +1002a4f2 : +1002a4f2: f600 1338 addw r3, r0, #2360 ; 0x938 +1002a4f6: f8d0 00ac ldr.w r0, [r0, #172] ; 0xac +1002a4fa: 8800 ldrh r0, [r0, #0] +1002a4fc: 2802 cmp r0, #2 +1002a4fe: bf18 it ne +1002a500: 2804 cmpne r0, #4 +1002a502: d003 beq.n 1002a50c +1002a504: 280b cmp r0, #11 +1002a506: bf18 it ne +1002a508: 2816 cmpne r0, #22 +1002a50a: d104 bne.n 1002a516 +1002a50c: f203 204f addw r0, r3, #591 ; 0x24f +1002a510: f203 236d addw r3, r3, #621 ; 0x26d +1002a514: e003 b.n 1002a51e +1002a516: f203 303f addw r0, r3, #831 ; 0x33f +1002a51a: f203 335d addw r3, r3, #861 ; 0x35d +1002a51e: 6008 str r0, [r1, #0] +1002a520: 6013 str r3, [r2, #0] +1002a522: 4770 bx lr + +1002a524 : +1002a524: 2121 movs r1, #33 ; 0x21 +1002a526: 7001 strb r1, [r0, #0] +1002a528: 212b movs r1, #43 ; 0x2b +1002a52a: 7041 strb r1, [r0, #1] +1002a52c: 2108 movs r1, #8 +1002a52e: 7081 strb r1, [r0, #2] +1002a530: 2104 movs r1, #4 +1002a532: 70c1 strb r1, [r0, #3] +1002a534: 2101 movs r1, #1 +1002a536: 7101 strb r1, [r0, #4] +1002a538: 2142 movs r1, #66 ; 0x42 +1002a53a: 6081 str r1, [r0, #8] +1002a53c: f8df 1a4c ldr.w r1, [pc, #2636] ; 1002af8c <.text_82> +1002a540: 60c1 str r1, [r0, #12] +1002a542: f8df 1a4c ldr.w r1, [pc, #2636] ; 1002af90 <.text_83> +1002a546: 6101 str r1, [r0, #16] +1002a548: f8df 1a48 ldr.w r1, [pc, #2632] ; 1002af94 <.text_84> +1002a54c: 6141 str r1, [r0, #20] +1002a54e: f8df 1a48 ldr.w r1, [pc, #2632] ; 1002af98 <.text_85> +1002a552: 6181 str r1, [r0, #24] +1002a554: 4770 bx lr + +1002a556 : +1002a556: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +1002a55a: f641 31a4 movw r1, #7076 ; 0x1ba4 +1002a55e: f640 6628 movw r6, #3624 ; 0xe28 +1002a562: 5808 ldr r0, [r1, r0] +1002a564: f500 55c8 add.w r5, r0, #6400 ; 0x1900 +1002a568: 35a8 adds r5, #168 ; 0xa8 +1002a56a: f06f 07ff mvn.w r7, #255 ; 0xff +1002a56e: 2400 movs r4, #0 +1002a570: 2300 movs r3, #0 +1002a572: f000 f890 bl 1002a696 <.text_17> +1002a576: f000 f977 bl 1002a868 <.text_21> +1002a57a: f000 f888 bl 1002a68e <.text_16+0x6> +1002a57e: f44f 3000 mov.w r0, #131072 ; 0x20000 +1002a582: 9000 str r0, [sp, #0] +1002a584: 2230 movs r2, #48 ; 0x30 +1002a586: f8df 8a14 ldr.w r8, [pc, #2580] ; 1002af9c <.text_86> +1002a58a: 4643 mov r3, r8 +1002a58c: f000 f87f bl 1002a68e <.text_16+0x6> +1002a590: 200f movs r0, #15 +1002a592: 9000 str r0, [sp, #0] +1002a594: 4643 mov r3, r8 +1002a596: 2231 movs r2, #49 ; 0x31 +1002a598: f000 f879 bl 1002a68e <.text_16+0x6> +1002a59c: f647 70f7 movw r0, #32759 ; 0x7ff7 +1002a5a0: 9000 str r0, [sp, #0] +1002a5a2: 4643 mov r3, r8 +1002a5a4: 2232 movs r2, #50 ; 0x32 +1002a5a6: f000 f872 bl 1002a68e <.text_16+0x6> +1002a5aa: f44f 6018 mov.w r0, #2432 ; 0x980 +1002a5ae: f000 f86b bl 1002a688 <.text_16> +1002a5b2: f8df 09ec ldr.w r0, [pc, #2540] ; 1002afa0 <.text_87> +1002a5b6: 9000 str r0, [sp, #0] +1002a5b8: 4643 mov r3, r8 +1002a5ba: 2256 movs r2, #86 ; 0x56 +1002a5bc: f000 f867 bl 1002a68e <.text_16+0x6> +1002a5c0: f8df 39e0 ldr.w r3, [pc, #2528] ; 1002afa4 <.text_88> +1002a5c4: f000 f867 bl 1002a696 <.text_17> +1002a5c8: f8df 39dc ldr.w r3, [pc, #2524] ; 1002afa8 <.text_89> +1002a5cc: f04f 32ff mov.w r2, #4294967295 +1002a5d0: f44f 6163 mov.w r1, #3632 ; 0xe30 +1002a5d4: f000 f861 bl 1002a69a <.text_17+0x4> +1002a5d8: f8df 39d0 ldr.w r3, [pc, #2512] ; 1002afac <.text_90> +1002a5dc: f04f 32ff mov.w r2, #4294967295 +1002a5e0: f640 6134 movw r1, #3636 ; 0xe34 +1002a5e4: f000 f859 bl 1002a69a <.text_17+0x4> +1002a5e8: f8df 39c4 ldr.w r3, [pc, #2500] ; 1002afb0 <.text_91> +1002a5ec: f04f 32ff mov.w r2, #4294967295 +1002a5f0: f640 6138 movw r1, #3640 ; 0xe38 +1002a5f4: f000 f851 bl 1002a69a <.text_17+0x4> +1002a5f8: f8df 39b8 ldr.w r3, [pc, #2488] ; 1002afb4 <.text_92> +1002a5fc: f04f 32ff mov.w r2, #4294967295 +1002a600: f640 613c movw r1, #3644 ; 0xe3c +1002a604: f000 f849 bl 1002a69a <.text_17+0x4> +1002a608: f8df 3c4c ldr.w r3, [pc, #3148] ; 1002b258 <.text_94> +1002a60c: f04f 32ff mov.w r2, #4294967295 +1002a610: f640 614c movw r1, #3660 ; 0xe4c +1002a614: f000 f841 bl 1002a69a <.text_17+0x4> +1002a618: f640 6948 movw r9, #3656 ; 0xe48 +1002a61c: f04f 4379 mov.w r3, #4177526784 ; 0xf9000000 +1002a620: f000 f83e bl 1002a6a0 <.text_18> +1002a624: f04f 4378 mov.w r3, #4160749568 ; 0xf8000000 +1002a628: f000 f83a bl 1002a6a0 <.text_18> +1002a62c: f000 f98a bl 1002a944 <.text_26> +1002a630: 4623 mov r3, r4 +1002a632: f000 f830 bl 1002a696 <.text_17> +1002a636: f44f 70c0 mov.w r0, #384 ; 0x180 +1002a63a: f000 f825 bl 1002a688 <.text_16> +1002a63e: f04f 32ff mov.w r2, #4294967295 +1002a642: f640 61ac movw r1, #3756 ; 0xeac +1002a646: 4628 mov r0, r5 +1002a648: f006 fc86 bl 10030f58 +1002a64c: 4606 mov r6, r0 +1002a64e: f04f 32ff mov.w r2, #4294967295 +1002a652: f640 6194 movw r1, #3732 ; 0xe94 +1002a656: 4628 mov r0, r5 +1002a658: f006 fc7e bl 10030f58 +1002a65c: 4607 mov r7, r0 +1002a65e: f04f 32ff mov.w r2, #4294967295 +1002a662: f640 619c movw r1, #3740 ; 0xe9c +1002a666: 4628 mov r0, r5 +1002a668: f006 fc76 bl 10030f58 +1002a66c: 00f1 lsls r1, r6, #3 +1002a66e: d408 bmi.n 1002a682 +1002a670: f3c7 4109 ubfx r1, r7, #16, #10 +1002a674: f5b1 7fa1 cmp.w r1, #322 ; 0x142 +1002a678: bf1e ittt ne +1002a67a: f3c0 4009 ubfxne r0, r0, #16, #10 +1002a67e: 2842 cmpne r0, #66 ; 0x42 +1002a680: 2401 movne r4, #1 +1002a682: 4620 mov r0, r4 +1002a684: e8bd 83f2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, pc} + +1002a688 <.text_16>: +1002a688: 9000 str r0, [sp, #0] +1002a68a: 4643 mov r3, r8 +1002a68c: 22df movs r2, #223 ; 0xdf +1002a68e: 4621 mov r1, r4 +1002a690: 4628 mov r0, r5 +1002a692: f006 bc65 b.w 10030f60 + +1002a696 <.text_17>: +1002a696: 463a mov r2, r7 +1002a698: 4631 mov r1, r6 +1002a69a: 4628 mov r0, r5 +1002a69c: f006 bc58 b.w 10030f50 + +1002a6a0 <.text_18>: +1002a6a0: f04f 32ff mov.w r2, #4294967295 +1002a6a4: 4649 mov r1, r9 +1002a6a6: 4628 mov r0, r5 +1002a6a8: f006 bc52 b.w 10030f50 + +1002a6ac : +1002a6ac: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1002a6b0: f641 31a4 movw r1, #7076 ; 0x1ba4 +1002a6b4: f640 6528 movw r5, #3624 ; 0xe28 +1002a6b8: 5808 ldr r0, [r1, r0] +1002a6ba: f500 54c8 add.w r4, r0, #6400 ; 0x1900 +1002a6be: 34a8 adds r4, #168 ; 0xa8 +1002a6c0: f06f 09ff mvn.w r9, #255 ; 0xff +1002a6c4: 2300 movs r3, #0 +1002a6c6: 464a mov r2, r9 +1002a6c8: f000 fbc4 bl 1002ae54 <.text_80+0x2> +1002a6cc: f000 f8cc bl 1002a868 <.text_21> +1002a6d0: f000 fb93 bl 1002adfa <.text_77> +1002a6d4: f44f 3040 mov.w r0, #196608 ; 0x30000 +1002a6d8: 9000 str r0, [sp, #0] +1002a6da: 2230 movs r2, #48 ; 0x30 +1002a6dc: f8df b8bc ldr.w fp, [pc, #2236] ; 1002af9c <.text_86> +1002a6e0: 465b mov r3, fp +1002a6e2: f000 fb8a bl 1002adfa <.text_77> +1002a6e6: 200f movs r0, #15 +1002a6e8: 9000 str r0, [sp, #0] +1002a6ea: 465b mov r3, fp +1002a6ec: 2231 movs r2, #49 ; 0x31 +1002a6ee: f000 fb84 bl 1002adfa <.text_77> +1002a6f2: f8df 0b68 ldr.w r0, [pc, #2920] ; 1002b25c <.text_95> +1002a6f6: 9000 str r0, [sp, #0] +1002a6f8: 465b mov r3, fp +1002a6fa: 2232 movs r2, #50 ; 0x32 +1002a6fc: f000 fb7d bl 1002adfa <.text_77> +1002a700: f000 fb76 bl 1002adf0 <.text_76> +1002a704: f000 f8aa bl 1002a85c <.text_20> +1002a708: f000 fb77 bl 1002adfa <.text_77> +1002a70c: f8df 3894 ldr.w r3, [pc, #2196] ; 1002afa4 <.text_88> +1002a710: 464a mov r2, r9 +1002a712: f000 fb9f bl 1002ae54 <.text_80+0x2> +1002a716: f8df 3b48 ldr.w r3, [pc, #2888] ; 1002b260 <.text_96> +1002a71a: f000 f95e bl 1002a9da <.text_45> +1002a71e: f000 f8ba bl 1002a896 <.text_24> +1002a722: f8df 3b40 ldr.w r3, [pc, #2880] ; 1002b264 <.text_97> +1002a726: f000 f942 bl 1002a9ae <.text_34> +1002a72a: f8df 3b3c ldr.w r3, [pc, #2876] ; 1002b268 <.text_98> +1002a72e: f000 f937 bl 1002a9a0 <.text_33> +1002a732: f8df 3b38 ldr.w r3, [pc, #2872] ; 1002b26c <.text_99> +1002a736: f000 f92c bl 1002a992 <.text_32> +1002a73a: f000 f921 bl 1002a980 <.text_31> +1002a73e: f000 f899 bl 1002a874 <.text_22> +1002a742: f640 6848 movw r8, #3656 ; 0xe48 +1002a746: f000 f89e bl 1002a886 <.text_23> +1002a74a: f04f 4378 mov.w r3, #4160749568 ; 0xf8000000 +1002a74e: f000 f89c bl 1002a88a <.text_23+0x4> +1002a752: f000 f8f7 bl 1002a944 <.text_26> +1002a756: 2300 movs r3, #0 +1002a758: 464a mov r2, r9 +1002a75a: f000 fb7b bl 1002ae54 <.text_80+0x2> +1002a75e: f44f 70c0 mov.w r0, #384 ; 0x180 +1002a762: f000 fb47 bl 1002adf4 <.text_76+0x4> +1002a766: f000 f904 bl 1002a972 <.text_30> +1002a76a: 4606 mov r6, r0 +1002a76c: f000 f8fa bl 1002a964 <.text_29> +1002a770: 4682 mov sl, r0 +1002a772: f000 f8f0 bl 1002a956 <.text_28> +1002a776: 00f1 lsls r1, r6, #3 +1002a778: d46e bmi.n 1002a858 +1002a77a: f3ca 4109 ubfx r1, sl, #16, #10 +1002a77e: f5b1 7fa1 cmp.w r1, #322 ; 0x142 +1002a782: bf1c itt ne +1002a784: f3c0 4109 ubfxne r1, r0, #16, #10 +1002a788: 2942 cmpne r1, #66 ; 0x42 +1002a78a: d065 beq.n 1002a858 +1002a78c: f000 f919 bl 1002a9c2 <.text_44> +1002a790: 2300 movs r3, #0 +1002a792: 464a mov r2, r9 +1002a794: f000 fb5e bl 1002ae54 <.text_80+0x2> +1002a798: 9700 str r7, [sp, #0] +1002a79a: f44f 2300 mov.w r3, #524288 ; 0x80000 +1002a79e: 22ef movs r2, #239 ; 0xef +1002a7a0: f000 fb2b bl 1002adfa <.text_77> +1002a7a4: f44f 3040 mov.w r0, #196608 ; 0x30000 +1002a7a8: 9000 str r0, [sp, #0] +1002a7aa: 465b mov r3, fp +1002a7ac: 2230 movs r2, #48 ; 0x30 +1002a7ae: f000 fb24 bl 1002adfa <.text_77> +1002a7b2: 200f movs r0, #15 +1002a7b4: 9000 str r0, [sp, #0] +1002a7b6: 465b mov r3, fp +1002a7b8: 2231 movs r2, #49 ; 0x31 +1002a7ba: f000 fb1e bl 1002adfa <.text_77> +1002a7be: f8df 0ab0 ldr.w r0, [pc, #2736] ; 1002b270 <.text_100> +1002a7c2: 9000 str r0, [sp, #0] +1002a7c4: 465b mov r3, fp +1002a7c6: 2232 movs r2, #50 ; 0x32 +1002a7c8: f000 fb17 bl 1002adfa <.text_77> +1002a7cc: f000 fb10 bl 1002adf0 <.text_76> +1002a7d0: f000 f844 bl 1002a85c <.text_20> +1002a7d4: f000 fb11 bl 1002adfa <.text_77> +1002a7d8: f8df 37c8 ldr.w r3, [pc, #1992] ; 1002afa4 <.text_88> +1002a7dc: 464a mov r2, r9 +1002a7de: f000 fb39 bl 1002ae54 <.text_80+0x2> +1002a7e2: f000 f858 bl 1002a896 <.text_24> +1002a7e6: f8df 3a80 ldr.w r3, [pc, #2688] ; 1002b268 <.text_98> +1002a7ea: f000 f8e0 bl 1002a9ae <.text_34> +1002a7ee: f8df 3a74 ldr.w r3, [pc, #2676] ; 1002b264 <.text_97> +1002a7f2: f000 f8d5 bl 1002a9a0 <.text_33> +1002a7f6: f8df 3a7c ldr.w r3, [pc, #2684] ; 1002b274 <.text_101> +1002a7fa: f000 f8ca bl 1002a992 <.text_32> +1002a7fe: f8df 3a78 ldr.w r3, [pc, #2680] ; 1002b278 <.text_102> +1002a802: f000 f8bf bl 1002a984 <.text_31+0x4> +1002a806: f000 f835 bl 1002a874 <.text_22> +1002a80a: f000 f83c bl 1002a886 <.text_23> +1002a80e: f04f 4378 mov.w r3, #4160749568 ; 0xf8000000 +1002a812: f000 f83a bl 1002a88a <.text_23+0x4> +1002a816: f000 f895 bl 1002a944 <.text_26> +1002a81a: 2300 movs r3, #0 +1002a81c: 464a mov r2, r9 +1002a81e: f000 fb19 bl 1002ae54 <.text_80+0x2> +1002a822: f44f 70c0 mov.w r0, #384 ; 0x180 +1002a826: f000 fae5 bl 1002adf4 <.text_76+0x4> +1002a82a: f000 f8a2 bl 1002a972 <.text_30> +1002a82e: 4605 mov r5, r0 +1002a830: f04f 32ff mov.w r2, #4294967295 +1002a834: f640 61a4 movw r1, #3748 ; 0xea4 +1002a838: f000 f8c0 bl 1002a9bc <.text_36> +1002a83c: 0129 lsls r1, r5, #4 +1002a83e: d408 bmi.n 1002a852 +1002a840: f3c0 4009 ubfx r0, r0, #16, #10 +1002a844: f5b0 7f99 cmp.w r0, #306 ; 0x132 +1002a848: bf1e ittt ne +1002a84a: f3c5 4009 ubfxne r0, r5, #16, #10 +1002a84e: 2836 cmpne r0, #54 ; 0x36 +1002a850: 2703 movne r7, #3 +1002a852: 4638 mov r0, r7 +1002a854: e8bd 8ff2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, sl, fp, pc} +1002a858: 2000 movs r0, #0 +1002a85a: e7fb b.n 1002a854 + +1002a85c <.text_20>: +1002a85c: f8df 0740 ldr.w r0, [pc, #1856] ; 1002afa0 <.text_87> +1002a860: 9000 str r0, [sp, #0] +1002a862: 465b mov r3, fp +1002a864: 2256 movs r2, #86 ; 0x56 +1002a866: 4770 bx lr + +1002a868 <.text_21>: +1002a868: 2001 movs r0, #1 +1002a86a: 9000 str r0, [sp, #0] +1002a86c: f44f 2300 mov.w r3, #524288 ; 0x80000 +1002a870: 22ef movs r2, #239 ; 0xef +1002a872: 4770 bx lr + +1002a874 <.text_22>: +1002a874: f8df 3a04 ldr.w r3, [pc, #2564] ; 1002b27c <.text_103> +1002a878: f04f 32ff mov.w r2, #4294967295 +1002a87c: f640 614c movw r1, #3660 ; 0xe4c +1002a880: 4620 mov r0, r4 +1002a882: f006 bb65 b.w 10030f50 + +1002a886 <.text_23>: +1002a886: f04f 4379 mov.w r3, #4177526784 ; 0xf9000000 +1002a88a: f04f 32ff mov.w r2, #4294967295 +1002a88e: 4641 mov r1, r8 +1002a890: 4620 mov r0, r4 +1002a892: f006 bb5d b.w 10030f50 + +1002a896 <.text_24>: +1002a896: f8df 39e8 ldr.w r3, [pc, #2536] ; 1002b280 <.text_104> +1002a89a: f04f 32ff mov.w r2, #4294967295 +1002a89e: f640 6144 movw r1, #3652 ; 0xe44 +1002a8a2: 4620 mov r0, r4 +1002a8a4: f006 bb54 b.w 10030f50 + +1002a8a8 : +1002a8a8: b570 push {r4, r5, r6, lr} +1002a8aa: f641 31a4 movw r1, #7076 ; 0x1ba4 +1002a8ae: b082 sub sp, #8 +1002a8b0: f000 fac6 bl 1002ae40 <.text_79> +1002a8b4: 2380 movs r3, #128 ; 0x80 +1002a8b6: f04f 32ff mov.w r2, #4294967295 +1002a8ba: f640 1148 movw r1, #2376 ; 0x948 +1002a8be: f000 faca bl 1002ae56 <.text_80+0x4> +1002a8c2: f8df 09c0 ldr.w r0, [pc, #2496] ; 1002b284 <.text_105> +1002a8c6: f8df 36d4 ldr.w r3, [pc, #1748] ; 1002af9c <.text_86> +1002a8ca: 9000 str r0, [sp, #0] +1002a8cc: 22b0 movs r2, #176 ; 0xb0 +1002a8ce: f000 fa94 bl 1002adfa <.text_77> +1002a8d2: f8df 36d4 ldr.w r3, [pc, #1748] ; 1002afa8 <.text_89> +1002a8d6: f000 f86a bl 1002a9ae <.text_34> +1002a8da: f8df 36d0 ldr.w r3, [pc, #1744] ; 1002afac <.text_90> +1002a8de: f000 f85f bl 1002a9a0 <.text_33> +1002a8e2: f8df 39a4 ldr.w r3, [pc, #2468] ; 1002b288 <.text_106> +1002a8e6: f000 f854 bl 1002a992 <.text_32> +1002a8ea: f000 f849 bl 1002a980 <.text_31> +1002a8ee: f8df 3968 ldr.w r3, [pc, #2408] ; 1002b258 <.text_94> +1002a8f2: f7ff ffc1 bl 1002a878 <.text_22+0x4> +1002a8f6: f8df 36ac ldr.w r3, [pc, #1708] ; 1002afa4 <.text_88> +1002a8fa: f000 faaa bl 1002ae52 <.text_80> +1002a8fe: f640 6548 movw r5, #3656 ; 0xe48 +1002a902: f04f 4379 mov.w r3, #4177526784 ; 0xf9000000 +1002a906: f000 f820 bl 1002a94a <.text_27> +1002a90a: f04f 4378 mov.w r3, #4160749568 ; 0xf8000000 +1002a90e: f000 f81c bl 1002a94a <.text_27> +1002a912: f000 f817 bl 1002a944 <.text_26> +1002a916: f000 f82c bl 1002a972 <.text_30> +1002a91a: 4605 mov r5, r0 +1002a91c: f000 f822 bl 1002a964 <.text_29> +1002a920: 4606 mov r6, r0 +1002a922: f000 f818 bl 1002a956 <.text_28> +1002a926: 00e9 lsls r1, r5, #3 +1002a928: d40a bmi.n 1002a940 +1002a92a: f3c6 4109 ubfx r1, r6, #16, #10 +1002a92e: f5b1 7fa1 cmp.w r1, #322 ; 0x142 +1002a932: bf1c itt ne +1002a934: f3c0 4009 ubfxne r0, r0, #16, #10 +1002a938: 2842 cmpne r0, #66 ; 0x42 +1002a93a: d001 beq.n 1002a940 +1002a93c: 2001 movs r0, #1 +1002a93e: bd76 pop {r1, r2, r4, r5, r6, pc} +1002a940: 2000 movs r0, #0 +1002a942: bd76 pop {r1, r2, r4, r5, r6, pc} + +1002a944 <.text_26>: +1002a944: 200a movs r0, #10 +1002a946: f006 bb1b b.w 10030f80 + +1002a94a <.text_27>: +1002a94a: f04f 32ff mov.w r2, #4294967295 +1002a94e: 4629 mov r1, r5 +1002a950: 4620 mov r0, r4 +1002a952: f006 bafd b.w 10030f50 + +1002a956 <.text_28>: +1002a956: f04f 32ff mov.w r2, #4294967295 +1002a95a: f640 619c movw r1, #3740 ; 0xe9c +1002a95e: 4620 mov r0, r4 +1002a960: f006 bafa b.w 10030f58 + +1002a964 <.text_29>: +1002a964: f04f 32ff mov.w r2, #4294967295 +1002a968: f640 6194 movw r1, #3732 ; 0xe94 +1002a96c: 4620 mov r0, r4 +1002a96e: f006 baf3 b.w 10030f58 + +1002a972 <.text_30>: +1002a972: f04f 32ff mov.w r2, #4294967295 +1002a976: f640 61ac movw r1, #3756 ; 0xeac +1002a97a: 4620 mov r0, r4 +1002a97c: f006 baec b.w 10030f58 + +1002a980 <.text_31>: +1002a980: f8df 3630 ldr.w r3, [pc, #1584] ; 1002afb4 <.text_92> +1002a984: f04f 32ff mov.w r2, #4294967295 +1002a988: f640 613c movw r1, #3644 ; 0xe3c +1002a98c: 4620 mov r0, r4 +1002a98e: f006 badf b.w 10030f50 + +1002a992 <.text_32>: +1002a992: f04f 32ff mov.w r2, #4294967295 +1002a996: f640 6138 movw r1, #3640 ; 0xe38 +1002a99a: 4620 mov r0, r4 +1002a99c: f006 bad8 b.w 10030f50 + +1002a9a0 <.text_33>: +1002a9a0: f04f 32ff mov.w r2, #4294967295 +1002a9a4: f640 6134 movw r1, #3636 ; 0xe34 +1002a9a8: 4620 mov r0, r4 +1002a9aa: f006 bad1 b.w 10030f50 + +1002a9ae <.text_34>: +1002a9ae: f04f 32ff mov.w r2, #4294967295 +1002a9b2: f44f 6163 mov.w r1, #3632 ; 0xe30 +1002a9b6: 4620 mov r0, r4 +1002a9b8: f006 baca b.w 10030f50 + +1002a9bc <.text_36>: +1002a9bc: 4620 mov r0, r4 +1002a9be: f006 bacb b.w 10030f58 + +1002a9c2 <.text_44>: +1002a9c2: f8df 1c14 ldr.w r1, [pc, #3092] ; 1002b5d8 <.text_126> +1002a9c6: ea01 010a and.w r1, r1, sl +1002a9ca: f3c0 4009 ubfx r0, r0, #16, #10 +1002a9ce: 4308 orrs r0, r1 +1002a9d0: f040 4300 orr.w r3, r0, #2147483648 ; 0x80000000 +1002a9d4: 2701 movs r7, #1 +1002a9d6: f443 43f8 orr.w r3, r3, #31744 ; 0x7c00 + +1002a9da <.text_45>: +1002a9da: f04f 32ff mov.w r2, #4294967295 +1002a9de: f44f 6164 mov.w r1, #3648 ; 0xe40 +1002a9e2: 4620 mov r0, r4 +1002a9e4: f006 bab4 b.w 10030f50 + +1002a9e8 <_PHY_PathAFillIQKMatrix8195A>: +1002a9e8: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1002a9ec: 4616 mov r6, r2 +1002a9ee: f000 f920 bl 1002ac32 <.text_57> +1002a9f2: bf18 it ne +1002a9f4: 2900 cmpne r1, #0 +1002a9f6: f608 1738 addw r7, r8, #2360 ; 0x938 +1002a9fa: d077 beq.n 1002aaec <_PHY_PathAFillIQKMatrix8195A+0x104> +1002a9fc: f04f 32ff mov.w r2, #4294967295 +1002aa00: f44f 6148 mov.w r1, #3200 ; 0xc80 +1002aa04: 4640 mov r0, r8 +1002aa06: f006 faa7 bl 10030f58 +1002aa0a: 0d85 lsrs r5, r0, #22 +1002aa0c: 0160 lsls r0, r4, #5 +1002aa0e: 9000 str r0, [sp, #0] +1002aa10: f240 39ff movw r9, #1023 ; 0x3ff +1002aa14: 9800 ldr r0, [sp, #0] +1002aa16: f8df a1f0 ldr.w sl, [pc, #496] ; 1002ac08 <.text_51> +1002aa1a: 5980 ldr r0, [r0, r6] +1002aa1c: 0581 lsls r1, r0, #22 +1002aa1e: bf48 it mi +1002aa20: ea4a 0000 orrmi.w r0, sl, r0 +1002aa24: fb05 fb00 mul.w fp, r5, r0 +1002aa28: ea4f 231b mov.w r3, fp, lsr #8 +1002aa2c: 464a mov r2, r9 +1002aa2e: f000 f863 bl 1002aaf8 <.text_48> +1002aa32: f000 f8f7 bl 1002ac24 <.text_56> +1002aa36: f04f 4200 mov.w r2, #2147483648 ; 0x80000000 +1002aa3a: f000 f906 bl 1002ac4a <.text_58+0x4> +1002aa3e: 9800 ldr r0, [sp, #0] +1002aa40: 1986 adds r6, r0, r6 +1002aa42: f640 4b94 movw fp, #3220 ; 0xc94 +1002aa46: 6870 ldr r0, [r6, #4] +1002aa48: 0581 lsls r1, r0, #22 +1002aa4a: bf48 it mi +1002aa4c: ea4a 0000 orrmi.w r0, sl, r0 +1002aa50: 4345 muls r5, r0 +1002aa52: ea4f 2a15 mov.w sl, r5, lsr #8 +1002aa56: f000 f8df bl 1002ac18 <.text_55> +1002aa5a: f000 f8f7 bl 1002ac4c <.text_58+0x6> +1002aa5e: f8c7 b52c str.w fp, [r7, #1324] ; 0x52c +1002aa62: f207 572c addw r7, r7, #1324 ; 0x52c +1002aa66: f000 f8f4 bl 1002ac52 <.text_59> +1002aa6a: 6078 str r0, [r7, #4] +1002aa6c: f00a 033f and.w r3, sl, #63 ; 0x3f +1002aa70: f44f 127c mov.w r2, #4128768 ; 0x3f0000 +1002aa74: f000 f840 bl 1002aaf8 <.text_48> +1002aa78: f44f 6048 mov.w r0, #3200 ; 0xc80 +1002aa7c: 60b8 str r0, [r7, #8] +1002aa7e: 4601 mov r1, r0 +1002aa80: f04f 32ff mov.w r2, #4294967295 +1002aa84: 4640 mov r0, r8 +1002aa86: f006 fa67 bl 10030f58 +1002aa8a: 60f8 str r0, [r7, #12] +1002aa8c: f04f 5200 mov.w r2, #536870912 ; 0x20000000 +1002aa90: 09e8 lsrs r0, r5, #7 +1002aa92: f000 f8d8 bl 1002ac46 <.text_58> +1002aa96: 613c str r4, [r7, #16] +1002aa98: f000 f8e8 bl 1002ac6c <.text_61+0x2> +1002aa9c: 6178 str r0, [r7, #20] +1002aa9e: f640 4514 movw r5, #3092 ; 0xc14 +1002aaa2: 980a ldr r0, [sp, #40] ; 0x28 +1002aaa4: f44f 644a mov.w r4, #3232 ; 0xca0 +1002aaa8: b130 cbz r0, 1002aab8 <_PHY_PathAFillIQKMatrix8195A+0xd0> +1002aaaa: f000 f8de bl 1002ac6a <.text_61> +1002aaae: 63f8 str r0, [r7, #60] ; 0x3c +1002aab0: f000 f827 bl 1002ab02 <.text_49> +1002aab4: 6378 str r0, [r7, #52] ; 0x34 +1002aab6: e019 b.n 1002aaec <_PHY_PathAFillIQKMatrix8195A+0x104> +1002aab8: 68b3 ldr r3, [r6, #8] +1002aaba: 464a mov r2, r9 +1002aabc: 4629 mov r1, r5 +1002aabe: f000 f8c5 bl 1002ac4c <.text_58+0x6> +1002aac2: 7b30 ldrb r0, [r6, #12] +1002aac4: f000 033f and.w r3, r0, #63 ; 0x3f +1002aac8: f44f 427c mov.w r2, #64512 ; 0xfc00 +1002aacc: 4629 mov r1, r5 +1002aace: f000 f8bd bl 1002ac4c <.text_58+0x6> +1002aad2: f000 f816 bl 1002ab02 <.text_49> +1002aad6: 6378 str r0, [r7, #52] ; 0x34 +1002aad8: f04f 4270 mov.w r2, #4026531840 ; 0xf0000000 +1002aadc: 68f0 ldr r0, [r6, #12] +1002aade: f3c0 1383 ubfx r3, r0, #6, #4 +1002aae2: f000 f8b2 bl 1002ac4a <.text_58+0x4> +1002aae6: f000 f8c0 bl 1002ac6a <.text_61> +1002aaea: 63f8 str r0, [r7, #60] ; 0x3c +1002aaec: e8bd 8ff1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, sl, fp, pc} +1002aaf0: 0000 movs r0, r0 + ... + +1002aaf4 <.text_47>: +1002aaf4: 10033efc .word 0x10033efc + +1002aaf8 <.text_48>: +1002aaf8: f44f 6148 mov.w r1, #3200 ; 0xc80 +1002aafc: 4640 mov r0, r8 +1002aafe: f006 ba27 b.w 10030f50 + +1002ab02 <.text_49>: +1002ab02: 633d str r5, [r7, #48] ; 0x30 +1002ab04: f04f 32ff mov.w r2, #4294967295 +1002ab08: 4629 mov r1, r5 +1002ab0a: 4640 mov r0, r8 +1002ab0c: f006 ba24 b.w 10030f58 + +1002ab10 <_PHY_PathBFillIQKMatrix8195A>: +1002ab10: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1002ab14: 4615 mov r5, r2 +1002ab16: f000 f88c bl 1002ac32 <.text_57> +1002ab1a: bf18 it ne +1002ab1c: 2900 cmpne r1, #0 +1002ab1e: f608 1638 addw r6, r8, #2360 ; 0x938 +1002ab22: d06f beq.n 1002ac04 <_PHY_PathBFillIQKMatrix8195A+0xf4> +1002ab24: f640 4788 movw r7, #3208 ; 0xc88 +1002ab28: f000 f899 bl 1002ac5e <.text_60> +1002ab2c: eb05 1544 add.w r5, r5, r4, lsl #5 +1002ab30: ea4f 5990 mov.w r9, r0, lsr #22 +1002ab34: 6928 ldr r0, [r5, #16] +1002ab36: f8df a0d0 ldr.w sl, [pc, #208] ; 1002ac08 <.text_51> +1002ab3a: 0581 lsls r1, r0, #22 +1002ab3c: bf48 it mi +1002ab3e: ea4a 0000 orrmi.w r0, sl, r0 +1002ab42: fb09 fb00 mul.w fp, r9, r0 +1002ab46: ea4f 231b mov.w r3, fp, lsr #8 +1002ab4a: f240 32ff movw r2, #1023 ; 0x3ff +1002ab4e: 4639 mov r1, r7 +1002ab50: f000 f87c bl 1002ac4c <.text_58+0x6> +1002ab54: f000 f866 bl 1002ac24 <.text_56> +1002ab58: f04f 6200 mov.w r2, #134217728 ; 0x8000000 +1002ab5c: f000 f875 bl 1002ac4a <.text_58+0x4> +1002ab60: 6968 ldr r0, [r5, #20] +1002ab62: 0581 lsls r1, r0, #22 +1002ab64: bf48 it mi +1002ab66: ea4a 0000 orrmi.w r0, sl, r0 +1002ab6a: fb09 f900 mul.w r9, r9, r0 +1002ab6e: ea4f 2a19 mov.w sl, r9, lsr #8 +1002ab72: f640 4b9c movw fp, #3228 ; 0xc9c +1002ab76: f000 f84f bl 1002ac18 <.text_55> +1002ab7a: f000 f867 bl 1002ac4c <.text_58+0x6> +1002ab7e: f8c6 b544 str.w fp, [r6, #1348] ; 0x544 +1002ab82: f206 5644 addw r6, r6, #1348 ; 0x544 +1002ab86: f000 f864 bl 1002ac52 <.text_59> +1002ab8a: 6070 str r0, [r6, #4] +1002ab8c: f00a 033f and.w r3, sl, #63 ; 0x3f +1002ab90: f44f 127c mov.w r2, #4128768 ; 0x3f0000 +1002ab94: 4639 mov r1, r7 +1002ab96: f000 f859 bl 1002ac4c <.text_58+0x6> +1002ab9a: 60b7 str r7, [r6, #8] +1002ab9c: f000 f85f bl 1002ac5e <.text_60> +1002aba0: 60f0 str r0, [r6, #12] +1002aba2: f04f 7200 mov.w r2, #33554432 ; 0x2000000 +1002aba6: ea4f 10d9 mov.w r0, r9, lsr #7 +1002abaa: f000 f84c bl 1002ac46 <.text_58> +1002abae: 6134 str r4, [r6, #16] +1002abb0: f000 f85c bl 1002ac6c <.text_61+0x2> +1002abb4: 6170 str r0, [r6, #20] +1002abb6: f640 4778 movw r7, #3192 ; 0xc78 +1002abba: 980a ldr r0, [sp, #40] ; 0x28 +1002abbc: f640 441c movw r4, #3100 ; 0xc1c +1002abc0: b120 cbz r0, 1002abcc <_PHY_PathBFillIQKMatrix8195A+0xbc> +1002abc2: 62b4 str r4, [r6, #40] ; 0x28 +1002abc4: f000 f852 bl 1002ac6c <.text_61+0x2> +1002abc8: 62f0 str r0, [r6, #44] ; 0x2c +1002abca: e017 b.n 1002abfc <_PHY_PathBFillIQKMatrix8195A+0xec> +1002abcc: 69ab ldr r3, [r5, #24] +1002abce: f240 32ff movw r2, #1023 ; 0x3ff +1002abd2: f000 f83a bl 1002ac4a <.text_58+0x4> +1002abd6: 7f28 ldrb r0, [r5, #28] +1002abd8: f000 033f and.w r3, r0, #63 ; 0x3f +1002abdc: f44f 427c mov.w r2, #64512 ; 0xfc00 +1002abe0: f000 f833 bl 1002ac4a <.text_58+0x4> +1002abe4: 62b4 str r4, [r6, #40] ; 0x28 +1002abe6: f000 f841 bl 1002ac6c <.text_61+0x2> +1002abea: 62f0 str r0, [r6, #44] ; 0x2c +1002abec: f44f 4270 mov.w r2, #61440 ; 0xf000 +1002abf0: 69e8 ldr r0, [r5, #28] +1002abf2: f3c0 1383 ubfx r3, r0, #6, #4 +1002abf6: 4639 mov r1, r7 +1002abf8: f000 f828 bl 1002ac4c <.text_58+0x6> +1002abfc: 6337 str r7, [r6, #48] ; 0x30 +1002abfe: f000 f82e bl 1002ac5e <.text_60> +1002ac02: 6370 str r0, [r6, #52] ; 0x34 +1002ac04: e8bd 8ff1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1002ac08 <.text_51>: +1002ac08: fffffc00 .word 0xfffffc00 + +1002ac0c <.text_52>: +1002ac0c: 100047b0 .word 0x100047b0 + +1002ac10 <.text_53>: +1002ac10: 10004798 .word 0x10004798 + +1002ac14 <.text_54>: +1002ac14: 1000466c .word 0x1000466c + +1002ac18 <.text_55>: +1002ac18: f3ca 1383 ubfx r3, sl, #6, #4 +1002ac1c: f04f 4270 mov.w r2, #4026531840 ; 0xf0000000 +1002ac20: 4659 mov r1, fp +1002ac22: 4770 bx lr + +1002ac24 <.text_56>: +1002ac24: ea4f 10db mov.w r0, fp, lsr #7 +1002ac28: f640 444c movw r4, #3148 ; 0xc4c +1002ac2c: f000 0301 and.w r3, r0, #1 +1002ac30: 4770 bx lr + +1002ac32 <.text_57>: +1002ac32: f641 32a4 movw r2, #7076 ; 0x1ba4 +1002ac36: 461c mov r4, r3 +1002ac38: 5810 ldr r0, [r2, r0] +1002ac3a: f500 50c8 add.w r0, r0, #6400 ; 0x1900 +1002ac3e: 2cff cmp r4, #255 ; 0xff +1002ac40: f100 08a8 add.w r8, r0, #168 ; 0xa8 +1002ac44: 4770 bx lr + +1002ac46 <.text_58>: +1002ac46: f000 0301 and.w r3, r0, #1 +1002ac4a: 4621 mov r1, r4 +1002ac4c: 4640 mov r0, r8 +1002ac4e: f006 b97f b.w 10030f50 + +1002ac52 <.text_59>: +1002ac52: f04f 32ff mov.w r2, #4294967295 +1002ac56: 4659 mov r1, fp +1002ac58: 4640 mov r0, r8 +1002ac5a: f006 b97d b.w 10030f58 + +1002ac5e <.text_60>: +1002ac5e: f04f 32ff mov.w r2, #4294967295 +1002ac62: 4639 mov r1, r7 +1002ac64: 4640 mov r0, r8 +1002ac66: f006 b977 b.w 10030f58 + +1002ac6a <.text_61>: +1002ac6a: 63bc str r4, [r7, #56] ; 0x38 +1002ac6c: f04f 32ff mov.w r2, #4294967295 +1002ac70: 4621 mov r1, r4 +1002ac72: 4640 mov r0, r8 +1002ac74: f006 b970 b.w 10030f58 + +1002ac78 <_PHY_SaveADDARegisters8195A>: +1002ac78: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1002ac7c: f000 f837 bl 1002acee <.text_67> +1002ac80: e006 b.n 1002ac90 <_PHY_SaveADDARegisters8195A+0x18> +1002ac82: f000 f82e bl 1002ace2 <.text_66> +1002ac86: f006 f967 bl 10030f58 +1002ac8a: f845 0026 str.w r0, [r5, r6, lsl #2] +1002ac8e: 1c76 adds r6, r6, #1 +1002ac90: 4546 cmp r6, r8 +1002ac92: d3f6 bcc.n 1002ac82 <_PHY_SaveADDARegisters8195A+0xa> +1002ac94: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +1002ac98 <_PHY_SaveMACRegisters8195A>: +1002ac98: b5f8 push {r3, r4, r5, r6, r7, lr} +1002ac9a: f000 f849 bl 1002ad30 <.text_69> +1002ac9e: f854 1027 ldr.w r1, [r4, r7, lsl #2] +1002aca2: 4630 mov r0, r6 +1002aca4: f006 f944 bl 10030f30 +1002aca8: f845 0027 str.w r0, [r5, r7, lsl #2] +1002acac: 1c7f adds r7, r7, #1 +1002acae: 2f03 cmp r7, #3 +1002acb0: d3f5 bcc.n 1002ac9e <_PHY_SaveMACRegisters8195A+0x6> +1002acb2: f854 1027 ldr.w r1, [r4, r7, lsl #2] +1002acb6: 4630 mov r0, r6 +1002acb8: f006 f93d bl 10030f36 +1002acbc: f845 0027 str.w r0, [r5, r7, lsl #2] +1002acc0: bdf1 pop {r0, r4, r5, r6, r7, pc} + +1002acc2 <_PHY_ReloadADDARegisters8195A>: +1002acc2: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1002acc6: f000 f812 bl 1002acee <.text_67> +1002acca: e006 b.n 1002acda <_PHY_ReloadADDARegisters8195A+0x18> +1002accc: f855 3026 ldr.w r3, [r5, r6, lsl #2] +1002acd0: f000 f807 bl 1002ace2 <.text_66> +1002acd4: f006 f93c bl 10030f50 +1002acd8: 1c76 adds r6, r6, #1 +1002acda: 4546 cmp r6, r8 +1002acdc: d3f6 bcc.n 1002accc <_PHY_ReloadADDARegisters8195A+0xa> +1002acde: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +1002ace2 <.text_66>: +1002ace2: f854 1026 ldr.w r1, [r4, r6, lsl #2] +1002ace6: f04f 32ff mov.w r2, #4294967295 +1002acea: 4638 mov r0, r7 +1002acec: 4770 bx lr + +1002acee <.text_67>: +1002acee: 460c mov r4, r1 +1002acf0: f641 31a4 movw r1, #7076 ; 0x1ba4 +1002acf4: 4615 mov r5, r2 +1002acf6: 5808 ldr r0, [r1, r0] +1002acf8: f500 57c8 add.w r7, r0, #6400 ; 0x1900 +1002acfc: 4698 mov r8, r3 +1002acfe: 37a8 adds r7, #168 ; 0xa8 +1002ad00: 2600 movs r6, #0 +1002ad02: 4770 bx lr + +1002ad04 <_PHY_ReloadMACRegisters8195A>: +1002ad04: b5f8 push {r3, r4, r5, r6, r7, lr} +1002ad06: f000 f813 bl 1002ad30 <.text_69> +1002ad0a: f855 2027 ldr.w r2, [r5, r7, lsl #2] +1002ad0e: f854 1027 ldr.w r1, [r4, r7, lsl #2] +1002ad12: b2d2 uxtb r2, r2 +1002ad14: f000 f852 bl 1002adbc <.text_73+0x4> +1002ad18: 1c7f adds r7, r7, #1 +1002ad1a: 2f03 cmp r7, #3 +1002ad1c: d3f5 bcc.n 1002ad0a <_PHY_ReloadMACRegisters8195A+0x6> +1002ad1e: f855 2027 ldr.w r2, [r5, r7, lsl #2] +1002ad22: f854 1027 ldr.w r1, [r4, r7, lsl #2] +1002ad26: 4630 mov r0, r6 +1002ad28: e8bd 40f8 ldmia.w sp!, {r3, r4, r5, r6, r7, lr} +1002ad2c: f006 b90c b.w 10030f48 + +1002ad30 <.text_69>: +1002ad30: 460c mov r4, r1 +1002ad32: f641 31a4 movw r1, #7076 ; 0x1ba4 +1002ad36: 4615 mov r5, r2 +1002ad38: 5808 ldr r0, [r1, r0] +1002ad3a: f500 56c8 add.w r6, r0, #6400 ; 0x1900 +1002ad3e: 36a8 adds r6, #168 ; 0xa8 +1002ad40: 2700 movs r7, #0 +1002ad42: 4770 bx lr + +1002ad44 <_PHY_PathADDAOn8195A>: +1002ad44: b5f8 push {r3, r4, r5, r6, r7, lr} +1002ad46: 460c mov r4, r1 +1002ad48: f641 31a4 movw r1, #7076 ; 0x1ba4 +1002ad4c: f8df 688c ldr.w r6, [pc, #2188] ; 1002b5dc <.text_127> +1002ad50: 5808 ldr r0, [r1, r0] +1002ad52: 6821 ldr r1, [r4, #0] +1002ad54: f500 55c8 add.w r5, r0, #6400 ; 0x1900 +1002ad58: 35a8 adds r5, #168 ; 0xa8 +1002ad5a: f000 f809 bl 1002ad70 <.text_71> +1002ad5e: 2701 movs r7, #1 +1002ad60: f854 1027 ldr.w r1, [r4, r7, lsl #2] +1002ad64: f000 f804 bl 1002ad70 <.text_71> +1002ad68: 1c7f adds r7, r7, #1 +1002ad6a: 2f10 cmp r7, #16 +1002ad6c: d3f8 bcc.n 1002ad60 <_PHY_PathADDAOn8195A+0x1c> +1002ad6e: bdf1 pop {r0, r4, r5, r6, r7, pc} + +1002ad70 <.text_71>: +1002ad70: 4633 mov r3, r6 +1002ad72: f04f 32ff mov.w r2, #4294967295 +1002ad76: 4628 mov r0, r5 +1002ad78: f006 b8ea b.w 10030f50 + +1002ad7c <_PHY_MACSettingCalibration8195A>: +1002ad7c: b570 push {r4, r5, r6, lr} +1002ad7e: 460c mov r4, r1 +1002ad80: f641 31a4 movw r1, #7076 ; 0x1ba4 +1002ad84: 4615 mov r5, r2 +1002ad86: 5808 ldr r0, [r1, r0] +1002ad88: 6821 ldr r1, [r4, #0] +1002ad8a: f500 56c8 add.w r6, r0, #6400 ; 0x1900 +1002ad8e: 36a8 adds r6, #168 ; 0xa8 +1002ad90: 223f movs r2, #63 ; 0x3f +1002ad92: f000 f813 bl 1002adbc <.text_73+0x4> +1002ad96: 7928 ldrb r0, [r5, #4] +1002ad98: 6861 ldr r1, [r4, #4] +1002ad9a: f000 f80d bl 1002adb8 <.text_73> +1002ad9e: 7a28 ldrb r0, [r5, #8] +1002ada0: 68a1 ldr r1, [r4, #8] +1002ada2: f000 f809 bl 1002adb8 <.text_73> +1002ada6: 7b28 ldrb r0, [r5, #12] +1002ada8: 68e1 ldr r1, [r4, #12] +1002adaa: f000 02df and.w r2, r0, #223 ; 0xdf +1002adae: 4630 mov r0, r6 +1002adb0: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +1002adb4: f006 b8c2 b.w 10030f3c + +1002adb8 <.text_73>: +1002adb8: f000 02f7 and.w r2, r0, #247 ; 0xf7 +1002adbc: 4630 mov r0, r6 +1002adbe: f006 b8bd b.w 10030f3c + +1002adc2 <_PHY_PathAStandBy8195A>: +1002adc2: b570 push {r4, r5, r6, lr} +1002adc4: f641 31a4 movw r1, #7076 ; 0x1ba4 +1002adc8: b082 sub sp, #8 +1002adca: f000 f839 bl 1002ae40 <.text_79> +1002adce: f000 fa78 bl 1002b2c2 <.text_112> +1002add2: f000 f812 bl 1002adfa <.text_77> +1002add6: 4632 mov r2, r6 +1002add8: 4629 mov r1, r5 +1002adda: 4620 mov r0, r4 +1002addc: b002 add sp, #8 +1002adde: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +1002ade2: f8df 37fc ldr.w r3, [pc, #2044] ; 1002b5e0 <.text_128> +1002ade6: f006 b8b3 b.w 10030f50 + ... + +1002adec <.text_75>: +1002adec: 10004540 .word 0x10004540 + +1002adf0 <.text_76>: +1002adf0: f44f 6018 mov.w r0, #2432 ; 0x980 +1002adf4: 9000 str r0, [sp, #0] +1002adf6: 465b mov r3, fp +1002adf8: 22df movs r2, #223 ; 0xdf + +1002adfa <.text_77>: +1002adfa: 2100 movs r1, #0 +1002adfc: 4620 mov r0, r4 +1002adfe: f006 b8af b.w 10030f60 + +1002ae02 <_PHY_PIModeSwitch8195A>: +1002ae02: b538 push {r3, r4, r5, lr} +1002ae04: f641 32a4 movw r2, #7076 ; 0x1ba4 +1002ae08: 5810 ldr r0, [r2, r0] +1002ae0a: f500 54c8 add.w r4, r0, #6400 ; 0x1900 +1002ae0e: 34a8 adds r4, #168 ; 0xa8 +1002ae10: 2900 cmp r1, #0 +1002ae12: bf14 ite ne +1002ae14: f04f 2501 movne.w r5, #16777472 ; 0x1000100 +1002ae18: f04f 7580 moveq.w r5, #16777216 ; 0x1000000 +1002ae1c: 462b mov r3, r5 +1002ae1e: f04f 32ff mov.w r2, #4294967295 +1002ae22: f44f 6102 mov.w r1, #2080 ; 0x820 +1002ae26: f000 f816 bl 1002ae56 <.text_80+0x4> +1002ae2a: 462b mov r3, r5 +1002ae2c: 4620 mov r0, r4 +1002ae2e: b001 add sp, #4 +1002ae30: e8bd 4030 ldmia.w sp!, {r4, r5, lr} +1002ae34: f04f 32ff mov.w r2, #4294967295 +1002ae38: f640 0128 movw r1, #2088 ; 0x828 +1002ae3c: f006 b888 b.w 10030f50 + +1002ae40 <.text_79>: +1002ae40: 5808 ldr r0, [r1, r0] +1002ae42: f500 54c8 add.w r4, r0, #6400 ; 0x1900 +1002ae46: 34a8 adds r4, #168 ; 0xa8 +1002ae48: f640 6528 movw r5, #3624 ; 0xe28 +1002ae4c: f06f 06ff mvn.w r6, #255 ; 0xff +1002ae50: 2300 movs r3, #0 + +1002ae52 <.text_80>: +1002ae52: 4632 mov r2, r6 +1002ae54: 4629 mov r1, r5 +1002ae56: 4620 mov r0, r4 +1002ae58: f006 b87a b.w 10030f50 + +1002ae5c : +1002ae5c: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1002ae60: f60f 0010 addw r0, pc, #2064 ; 0x810 +1002ae64: f8df e77c ldr.w lr, [pc, #1916] ; 1002b5e4 <.text_129> +1002ae68: 8800 ldrh r0, [r0, #0] +1002ae6a: f8ad 0000 strh.w r0, [sp] +1002ae6e: ea4f 1942 mov.w r9, r2, lsl #5 +1002ae72: 2001 movs r0, #1 +1002ae74: 2400 movs r4, #0 +1002ae76: 2500 movs r5, #0 +1002ae78: eb01 1843 add.w r8, r1, r3, lsl #5 +1002ae7c: eb09 0c01 add.w ip, r9, r1 +1002ae80: ae00 add r6, sp, #0 +1002ae82: f85c 7025 ldr.w r7, [ip, r5, lsl #2] +1002ae86: f858 a025 ldr.w sl, [r8, r5, lsl #2] +1002ae8a: e015 b.n 1002aeb8 +1002ae8c: 2d01 cmp r5, #1 +1002ae8e: bf18 it ne +1002ae90: 2d03 cmpne r5, #3 +1002ae92: d003 beq.n 1002ae9c +1002ae94: 2d05 cmp r5, #5 +1002ae96: bf18 it ne +1002ae98: 2d07 cmpne r5, #7 +1002ae9a: d1f2 bne.n 1002ae82 +1002ae9c: f85c 7025 ldr.w r7, [ip, r5, lsl #2] +1002aea0: ea5f 5a87 movs.w sl, r7, lsl #22 +1002aea4: f858 a025 ldr.w sl, [r8, r5, lsl #2] +1002aea8: bf48 it mi +1002aeaa: ea4e 0707 orrmi.w r7, lr, r7 +1002aeae: ea5f 5b8a movs.w fp, sl, lsl #22 +1002aeb2: bf48 it mi +1002aeb4: ea4e 0a0a orrmi.w sl, lr, sl +1002aeb8: 45ba cmp sl, r7 +1002aeba: bfb4 ite lt +1002aebc: eba7 070a sublt.w r7, r7, sl +1002aec0: ebaa 0707 subge.w r7, sl, r7 +1002aec4: 2f06 cmp r7, #6 +1002aec6: d31e bcc.n 1002af06 +1002aec8: 2d02 cmp r5, #2 +1002aeca: bf18 it ne +1002aecc: 2d06 cmpne r5, #6 +1002aece: d117 bne.n 1002af00 +1002aed0: b9b4 cbnz r4, 1002af00 +1002aed2: eb0c 0b85 add.w fp, ip, r5, lsl #2 +1002aed6: f85c a025 ldr.w sl, [ip, r5, lsl #2] +1002aeda: f8db b004 ldr.w fp, [fp, #4] +1002aede: 08af lsrs r7, r5, #2 +1002aee0: eb1b 0a0a adds.w sl, fp, sl +1002aee4: bf08 it eq +1002aee6: 55bb strbeq r3, [r7, r6] +1002aee8: d00d beq.n 1002af06 +1002aeea: eb08 0b85 add.w fp, r8, r5, lsl #2 +1002aeee: f858 a025 ldr.w sl, [r8, r5, lsl #2] +1002aef2: f8db b004 ldr.w fp, [fp, #4] +1002aef6: eb1b 0a0a adds.w sl, fp, sl +1002aefa: bf08 it eq +1002aefc: 55ba strbeq r2, [r7, r6] +1002aefe: d002 beq.n 1002af06 +1002af00: fa00 f705 lsl.w r7, r0, r5 +1002af04: 433c orrs r4, r7 +1002af06: 1c6d adds r5, r5, #1 +1002af08: 2d08 cmp r5, #8 +1002af0a: d3bf bcc.n 1002ae8c +1002af0c: b9b4 cbnz r4, 1002af3c +1002af0e: 2500 movs r5, #0 +1002af10: 5daa ldrb r2, [r5, r6] +1002af12: 2aff cmp r2, #255 ; 0xff +1002af14: d00e beq.n 1002af34 +1002af16: 00a8 lsls r0, r5, #2 +1002af18: 4603 mov r3, r0 +1002af1a: e007 b.n 1002af2c +1002af1c: eb01 1442 add.w r4, r1, r2, lsl #5 +1002af20: eb01 0783 add.w r7, r1, r3, lsl #2 +1002af24: f854 4023 ldr.w r4, [r4, r3, lsl #2] +1002af28: 663c str r4, [r7, #96] ; 0x60 +1002af2a: 1c5b adds r3, r3, #1 +1002af2c: 1c84 adds r4, r0, #2 +1002af2e: 42a3 cmp r3, r4 +1002af30: d3f4 bcc.n 1002af1c +1002af32: 2000 movs r0, #0 +1002af34: 1c6d adds r5, r5, #1 +1002af36: 2d02 cmp r5, #2 +1002af38: d3ea bcc.n 1002af10 +1002af3a: e024 b.n 1002af86 +1002af3c: f014 0f03 tst.w r4, #3 +1002af40: d105 bne.n 1002af4e +1002af42: f859 0001 ldr.w r0, [r9, r1] +1002af46: 6608 str r0, [r1, #96] ; 0x60 +1002af48: f8dc 0004 ldr.w r0, [ip, #4] +1002af4c: 6648 str r0, [r1, #100] ; 0x64 +1002af4e: f014 0f0c tst.w r4, #12 +1002af52: d105 bne.n 1002af60 +1002af54: f8dc 0008 ldr.w r0, [ip, #8] +1002af58: 6688 str r0, [r1, #104] ; 0x68 +1002af5a: f8dc 000c ldr.w r0, [ip, #12] +1002af5e: 66c8 str r0, [r1, #108] ; 0x6c +1002af60: f014 0f30 tst.w r4, #48 ; 0x30 +1002af64: d105 bne.n 1002af72 +1002af66: f8dc 0010 ldr.w r0, [ip, #16] +1002af6a: 6708 str r0, [r1, #112] ; 0x70 +1002af6c: f8dc 0014 ldr.w r0, [ip, #20] +1002af70: 6748 str r0, [r1, #116] ; 0x74 +1002af72: f014 0fc0 tst.w r4, #192 ; 0xc0 +1002af76: d105 bne.n 1002af84 +1002af78: f8dc 0018 ldr.w r0, [ip, #24] +1002af7c: 6788 str r0, [r1, #120] ; 0x78 +1002af7e: f8dc 001c ldr.w r0, [ip, #28] +1002af82: 67c8 str r0, [r1, #124] ; 0x7c +1002af84: 2000 movs r0, #0 +1002af86: e8bd 8ff2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, sl, fp, pc} + ... + +1002af8c <.text_82>: +1002af8c: 1002a059 .word 0x1002a059 + +1002af90 <.text_83>: +1002af90: 1002a03b .word 0x1002a03b + +1002af94 <.text_84>: +1002af94: 1002b63b .word 0x1002b63b + +1002af98 <.text_85>: +1002af98: 1002a4f3 .word 0x1002a4f3 + +1002af9c <.text_86>: +1002af9c: 000fffff .word 0x000fffff + +1002afa0 <.text_87>: +1002afa0: 0005102a .word 0x0005102a + +1002afa4 <.text_88>: +1002afa4: 00808000 .word 0x00808000 + +1002afa8 <.text_89>: +1002afa8: 18008c1c .word 0x18008c1c + +1002afac <.text_90>: +1002afac: 38008c1c .word 0x38008c1c + +1002afb0 <.text_91>: +1002afb0: 821403ff .word 0x821403ff + +1002afb4 <.text_92>: +1002afb4: 28160000 .word 0x28160000 + +1002afb8 : +1002afb8: e92d 4ff2 stmdb sp!, {r1, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1002afbc: 4604 mov r4, r0 +1002afbe: f641 30a4 movw r0, #7076 ; 0x1ba4 +1002afc2: b0a2 sub sp, #136 ; 0x88 +1002afc4: 5900 ldr r0, [r0, r4] +1002afc6: f500 50c8 add.w r0, r0, #6400 ; 0x1900 +1002afca: 4615 mov r5, r2 +1002afcc: f100 0ba8 add.w fp, r0, #168 ; 0xa8 +1002afd0: 461e mov r6, r3 +1002afd2: 22ff movs r2, #255 ; 0xff +1002afd4: f44f 6145 mov.w r1, #3152 ; 0xc50 +1002afd8: f000 f97a bl 1002b2d0 <.text_113> +1002afdc: f88d 0005 strb.w r0, [sp, #5] +1002afe0: 22ff movs r2, #255 ; 0xff +1002afe2: f640 4158 movw r1, #3160 ; 0xc58 +1002afe6: f000 f973 bl 1002b2d0 <.text_113> +1002afea: f88d 0004 strb.w r0, [sp, #4] +1002afee: 2240 movs r2, #64 ; 0x40 +1002aff0: a811 add r0, sp, #68 ; 0x44 +1002aff2: f20f 6184 addw r1, pc, #1668 ; 0x684 +1002aff6: f003 fa59 bl 1002e4ac <__iar_unaligned___aeabi_memcpy4> +1002affa: f20f 61bc addw r1, pc, #1724 ; 0x6bc +1002affe: a804 add r0, sp, #16 +1002b000: 2210 movs r2, #16 +1002b002: f003 fa53 bl 1002e4ac <__iar_unaligned___aeabi_memcpy4> +1002b006: a808 add r0, sp, #32 +1002b008: f20f 61bc addw r1, pc, #1724 ; 0x6bc +1002b00c: 2224 movs r2, #36 ; 0x24 +1002b00e: f003 fa4d bl 1002e4ac <__iar_unaligned___aeabi_memcpy4> +1002b012: b95d cbnz r5, 1002b02c +1002b014: f000 f94a bl 1002b2ac <.text_110> +1002b018: f7ff fe2e bl 1002ac78 <_PHY_SaveADDARegisters8195A> +1002b01c: f000 f94c bl 1002b2b8 <.text_111> +1002b020: f7ff fe3a bl 1002ac98 <_PHY_SaveMACRegisters8195A> +1002b024: f000 f93c bl 1002b2a0 <.text_109> +1002b028: f7ff fe26 bl 1002ac78 <_PHY_SaveADDARegisters8195A> +1002b02c: 4633 mov r3, r6 +1002b02e: 2201 movs r2, #1 +1002b030: a911 add r1, sp, #68 ; 0x44 +1002b032: 4620 mov r0, r4 +1002b034: f7ff fe86 bl 1002ad44 <_PHY_PathADDAOn8195A> +1002b038: b93d cbnz r5, 1002b04a +1002b03a: f44f 7280 mov.w r2, #256 ; 0x100 +1002b03e: f44f 6102 mov.w r1, #2080 ; 0x820 +1002b042: f000 f945 bl 1002b2d0 <.text_113> +1002b046: f88b 0968 strb.w r0, [fp, #2408] ; 0x968 +1002b04a: f89b 0968 ldrb.w r0, [fp, #2408] ; 0x968 +1002b04e: b918 cbnz r0, 1002b058 +1002b050: 2101 movs r1, #1 +1002b052: 4620 mov r0, r4 +1002b054: f7ff fed5 bl 1002ae02 <_PHY_PIModeSwitch8195A> +1002b058: f000 f943 bl 1002b2e2 <.text_115> +1002b05c: f005 ff7c bl 10030f58 +1002b060: 9003 str r0, [sp, #12] +1002b062: 22b0 movs r2, #176 ; 0xb0 +1002b064: f8df 8580 ldr.w r8, [pc, #1408] ; 1002b5e8 <.text_130> +1002b068: 4643 mov r3, r8 +1002b06a: f000 f915 bl 1002b298 <.text_108> +1002b06e: 9002 str r0, [sp, #8] +1002b070: 2300 movs r3, #0 +1002b072: f04f 7280 mov.w r2, #16777216 ; 0x1000000 +1002b076: f44f 6100 mov.w r1, #2048 ; 0x800 +1002b07a: f000 f92f bl 1002b2dc <.text_114+0x6> +1002b07e: f8df 356c ldr.w r3, [pc, #1388] ; 1002b5ec <.text_131> +1002b082: f04f 32ff mov.w r2, #4294967295 +1002b086: f640 4104 movw r1, #3076 ; 0xc04 +1002b08a: f000 f927 bl 1002b2dc <.text_114+0x6> +1002b08e: f8df 3560 ldr.w r3, [pc, #1376] ; 1002b5f0 <.text_132> +1002b092: f04f 32ff mov.w r2, #4294967295 +1002b096: f640 4108 movw r1, #3080 ; 0xc08 +1002b09a: f000 f91f bl 1002b2dc <.text_114+0x6> +1002b09e: f8df 3554 ldr.w r3, [pc, #1364] ; 1002b5f4 <.text_133> +1002b0a2: f04f 32ff mov.w r2, #4294967295 +1002b0a6: f640 0174 movw r1, #2164 ; 0x874 +1002b0aa: f000 f917 bl 1002b2dc <.text_114+0x6> +1002b0ae: b12e cbz r6, 1002b0bc +1002b0b0: f000 f907 bl 1002b2c2 <.text_112> +1002b0b4: 2101 movs r1, #1 +1002b0b6: 4658 mov r0, fp +1002b0b8: f005 ff52 bl 10030f60 +1002b0bc: f000 f8fc bl 1002b2b8 <.text_111> +1002b0c0: f7ff fe5c bl 1002ad7c <_PHY_MACSettingCalibration8195A> +1002b0c4: f640 6928 movw r9, #3624 ; 0xe28 +1002b0c8: f06f 0aff mvn.w sl, #255 ; 0xff +1002b0cc: f8df 3510 ldr.w r3, [pc, #1296] ; 1002b5e0 <.text_128> +1002b0d0: f000 f902 bl 1002b2d8 <.text_114+0x2> +1002b0d4: 4b62 ldr r3, [pc, #392] ; (1002b260 <.text_96>) +1002b0d6: f04f 32ff mov.w r2, #4294967295 +1002b0da: f44f 6164 mov.w r1, #3648 ; 0xe40 +1002b0de: f000 f8fd bl 1002b2dc <.text_114+0x6> +1002b0e2: 4b67 ldr r3, [pc, #412] ; (1002b280 <.text_104>) +1002b0e4: f04f 32ff mov.w r2, #4294967295 +1002b0e8: f640 6144 movw r1, #3652 ; 0xe44 +1002b0ec: f000 f8f6 bl 1002b2dc <.text_114+0x6> +1002b0f0: 2702 movs r7, #2 +1002b0f2: 4631 mov r1, r6 +1002b0f4: 4620 mov r0, r4 +1002b0f6: f7ff fa2e bl 1002a556 +1002b0fa: 2801 cmp r0, #1 +1002b0fc: d116 bne.n 1002b12c +1002b0fe: f000 f8ea bl 1002b2d6 <.text_114> +1002b102: 4643 mov r3, r8 +1002b104: 2208 movs r2, #8 +1002b106: f000 f8c7 bl 1002b298 <.text_108> +1002b10a: f8cb 0ee0 str.w r0, [fp, #3808] ; 0xee0 +1002b10e: f000 f8f5 bl 1002b2fc <.text_117> +1002b112: 9922 ldr r1, [sp, #136] ; 0x88 +1002b114: 016f lsls r7, r5, #5 +1002b116: f3c0 4009 ubfx r0, r0, #16, #10 +1002b11a: 5078 str r0, [r7, r1] +1002b11c: f000 f8e7 bl 1002b2ee <.text_116> +1002b120: 9922 ldr r1, [sp, #136] ; 0x88 +1002b122: 1879 adds r1, r7, r1 +1002b124: f3c0 4009 ubfx r0, r0, #16, #10 +1002b128: 6048 str r0, [r1, #4] +1002b12a: e001 b.n 1002b130 +1002b12c: 1e7f subs r7, r7, #1 +1002b12e: d1e0 bne.n 1002b0f2 +1002b130: 2702 movs r7, #2 +1002b132: 4631 mov r1, r6 +1002b134: 4620 mov r0, r4 +1002b136: f7ff fab9 bl 1002a6ac +1002b13a: 2803 cmp r0, #3 +1002b13c: d112 bne.n 1002b164 +1002b13e: f04f 32ff mov.w r2, #4294967295 +1002b142: f640 61a4 movw r1, #3748 ; 0xea4 +1002b146: f000 f8c3 bl 1002b2d0 <.text_113> +1002b14a: f000 f89f bl 1002b28c <.text_107> +1002b14e: 60b8 str r0, [r7, #8] +1002b150: f04f 32ff mov.w r2, #4294967295 +1002b154: f640 61ac movw r1, #3756 ; 0xeac +1002b158: f000 f8ba bl 1002b2d0 <.text_113> +1002b15c: f3c0 4009 ubfx r0, r0, #16, #10 +1002b160: 60f8 str r0, [r7, #12] +1002b162: e001 b.n 1002b168 +1002b164: 1e7f subs r7, r7, #1 +1002b166: d1e4 bne.n 1002b132 +1002b168: b326 cbz r6, 1002b1b4 +1002b16a: 4620 mov r0, r4 +1002b16c: f7ff fe29 bl 1002adc2 <_PHY_PathAStandBy8195A> +1002b170: 4633 mov r3, r6 +1002b172: 2200 movs r2, #0 +1002b174: a911 add r1, sp, #68 ; 0x44 +1002b176: 4620 mov r0, r4 +1002b178: f7ff fde4 bl 1002ad44 <_PHY_PathADDAOn8195A> +1002b17c: 2702 movs r7, #2 +1002b17e: 4620 mov r0, r4 +1002b180: f7ff fb92 bl 1002a8a8 +1002b184: 2801 cmp r0, #1 +1002b186: d113 bne.n 1002b1b0 +1002b188: f000 f8a5 bl 1002b2d6 <.text_114> +1002b18c: 4643 mov r3, r8 +1002b18e: 2208 movs r2, #8 +1002b190: 2101 movs r1, #1 +1002b192: f000 f882 bl 1002b29a <.text_108+0x2> +1002b196: f8cb 0ee4 str.w r0, [fp, #3812] ; 0xee4 +1002b19a: f000 f8af bl 1002b2fc <.text_117> +1002b19e: f000 f875 bl 1002b28c <.text_107> +1002b1a2: 6138 str r0, [r7, #16] +1002b1a4: f000 f8a3 bl 1002b2ee <.text_116> +1002b1a8: f3c0 4009 ubfx r0, r0, #16, #10 +1002b1ac: 6178 str r0, [r7, #20] +1002b1ae: e001 b.n 1002b1b4 +1002b1b0: 1e7f subs r7, r7, #1 +1002b1b2: d1e4 bne.n 1002b17e +1002b1b4: f000 f88f bl 1002b2d6 <.text_114> +1002b1b8: 2d00 cmp r5, #0 +1002b1ba: d04a beq.n 1002b252 +1002b1bc: f89b 0968 ldrb.w r0, [fp, #2408] ; 0x968 +1002b1c0: b918 cbnz r0, 1002b1ca +1002b1c2: 2100 movs r1, #0 +1002b1c4: 4620 mov r0, r4 +1002b1c6: f7ff fe1c bl 1002ae02 <_PHY_PIModeSwitch8195A> +1002b1ca: f000 f86f bl 1002b2ac <.text_110> +1002b1ce: f7ff fd78 bl 1002acc2 <_PHY_ReloadADDARegisters8195A> +1002b1d2: f000 f871 bl 1002b2b8 <.text_111> +1002b1d6: f7ff fd95 bl 1002ad04 <_PHY_ReloadMACRegisters8195A> +1002b1da: f000 f861 bl 1002b2a0 <.text_109> +1002b1de: f7ff fd70 bl 1002acc2 <_PHY_ReloadADDARegisters8195A> +1002b1e2: 9b03 ldr r3, [sp, #12] +1002b1e4: f000 f87d bl 1002b2e2 <.text_115> +1002b1e8: f005 feb2 bl 10030f50 +1002b1ec: 9802 ldr r0, [sp, #8] +1002b1ee: 9000 str r0, [sp, #0] +1002b1f0: 4643 mov r3, r8 +1002b1f2: 22b0 movs r2, #176 ; 0xb0 +1002b1f4: 2100 movs r1, #0 +1002b1f6: 4658 mov r0, fp +1002b1f8: f005 feb2 bl 10030f60 +1002b1fc: 2350 movs r3, #80 ; 0x50 +1002b1fe: 22ff movs r2, #255 ; 0xff +1002b200: f44f 6145 mov.w r1, #3152 ; 0xc50 +1002b204: f000 f86a bl 1002b2dc <.text_114+0x6> +1002b208: f89d 3005 ldrb.w r3, [sp, #5] +1002b20c: 22ff movs r2, #255 ; 0xff +1002b20e: f44f 6145 mov.w r1, #3152 ; 0xc50 +1002b212: f000 f863 bl 1002b2dc <.text_114+0x6> +1002b216: b166 cbz r6, 1002b232 +1002b218: 2350 movs r3, #80 ; 0x50 +1002b21a: 22ff movs r2, #255 ; 0xff +1002b21c: f640 4158 movw r1, #3160 ; 0xc58 +1002b220: f000 f85c bl 1002b2dc <.text_114+0x6> +1002b224: f89d 3004 ldrb.w r3, [sp, #4] +1002b228: 22ff movs r2, #255 ; 0xff +1002b22a: f640 4158 movw r1, #3160 ; 0xc58 +1002b22e: f000 f855 bl 1002b2dc <.text_114+0x6> +1002b232: f8df 43c4 ldr.w r4, [pc, #964] ; 1002b5f8 <.text_134> +1002b236: 4623 mov r3, r4 +1002b238: f04f 32ff mov.w r2, #4294967295 +1002b23c: f44f 6163 mov.w r1, #3632 ; 0xe30 +1002b240: f000 f84c bl 1002b2dc <.text_114+0x6> +1002b244: 4623 mov r3, r4 +1002b246: f04f 32ff mov.w r2, #4294967295 +1002b24a: f640 6134 movw r1, #3636 ; 0xe34 +1002b24e: f000 f845 bl 1002b2dc <.text_114+0x6> +1002b252: b023 add sp, #140 ; 0x8c +1002b254: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1002b258 <.text_94>: +1002b258: 00462911 .word 0x00462911 + +1002b25c <.text_95>: +1002b25c: 000f1173 .word 0x000f1173 + +1002b260 <.text_96>: +1002b260: 01007c00 .word 0x01007c00 + +1002b264 <.text_97>: +1002b264: 10008c1c .word 0x10008c1c + +1002b268 <.text_98>: +1002b268: 30008c1c .word 0x30008c1c + +1002b26c <.text_99>: +1002b26c: 82160fff .word 0x82160fff + +1002b270 <.text_100>: +1002b270: 000f7ff2 .word 0x000f7ff2 + +1002b274 <.text_101>: +1002b274: 82160000 .word 0x82160000 + +1002b278 <.text_102>: +1002b278: 28160fff .word 0x28160fff + +1002b27c <.text_103>: +1002b27c: 0046a911 .word 0x0046a911 + +1002b280 <.text_104>: +1002b280: 01004800 .word 0x01004800 + +1002b284 <.text_105>: +1002b284: 000effe0 .word 0x000effe0 + +1002b288 <.text_106>: +1002b288: 82140102 .word 0x82140102 + +1002b28c <.text_107>: +1002b28c: 9922 ldr r1, [sp, #136] ; 0x88 +1002b28e: eb01 1745 add.w r7, r1, r5, lsl #5 +1002b292: f3c0 4009 ubfx r0, r0, #16, #10 +1002b296: 4770 bx lr + +1002b298 <.text_108>: +1002b298: 2100 movs r1, #0 +1002b29a: 4658 mov r0, fp +1002b29c: f005 be68 b.w 10030f70 + +1002b2a0 <.text_109>: +1002b2a0: 2309 movs r3, #9 +1002b2a2: f50b 6264 add.w r2, fp, #3648 ; 0xe40 +1002b2a6: a908 add r1, sp, #32 +1002b2a8: 4620 mov r0, r4 +1002b2aa: 4770 bx lr + +1002b2ac <.text_110>: +1002b2ac: 2310 movs r3, #16 +1002b2ae: f60b 52cc addw r2, fp, #3532 ; 0xdcc +1002b2b2: a911 add r1, sp, #68 ; 0x44 +1002b2b4: 4620 mov r0, r4 +1002b2b6: 4770 bx lr + +1002b2b8 <.text_111>: +1002b2b8: f60b 620c addw r2, fp, #3596 ; 0xe0c +1002b2bc: a904 add r1, sp, #16 +1002b2be: 4620 mov r0, r4 +1002b2c0: 4770 bx lr + +1002b2c2 <.text_112>: +1002b2c2: f44f 3080 mov.w r0, #65536 ; 0x10000 +1002b2c6: 9000 str r0, [sp, #0] +1002b2c8: f04f 33ff mov.w r3, #4294967295 +1002b2cc: 2200 movs r2, #0 +1002b2ce: 4770 bx lr + +1002b2d0 <.text_113>: +1002b2d0: 4658 mov r0, fp +1002b2d2: f005 be41 b.w 10030f58 + +1002b2d6 <.text_114>: +1002b2d6: 2300 movs r3, #0 +1002b2d8: 4652 mov r2, sl +1002b2da: 4649 mov r1, r9 +1002b2dc: 4658 mov r0, fp +1002b2de: f005 be37 b.w 10030f50 + +1002b2e2 <.text_115>: +1002b2e2: f04f 32ff mov.w r2, #4294967295 +1002b2e6: f640 1148 movw r1, #2376 ; 0x948 +1002b2ea: 4658 mov r0, fp +1002b2ec: 4770 bx lr + +1002b2ee <.text_116>: +1002b2ee: f04f 32ff mov.w r2, #4294967295 +1002b2f2: f640 619c movw r1, #3740 ; 0xe9c +1002b2f6: 4658 mov r0, fp +1002b2f8: f005 be2e b.w 10030f58 + +1002b2fc <.text_117>: +1002b2fc: f04f 32ff mov.w r2, #4294967295 +1002b300: f640 6194 movw r1, #3732 ; 0xe94 +1002b304: 4658 mov r0, fp +1002b306: f005 be27 b.w 10030f58 + +1002b30a : +1002b30a: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +1002b30e: 4604 mov r4, r0 +1002b310: f640 5503 movw r5, #3331 ; 0xd03 +1002b314: 6827 ldr r7, [r4, #0] +1002b316: 4629 mov r1, r5 +1002b318: f005 fe0a bl 10030f30 +1002b31c: 4606 mov r6, r0 +1002b31e: f240 5822 movw r8, #1314 ; 0x522 +1002b322: f016 0070 ands.w r0, r6, #112 ; 0x70 +1002b326: bf19 ittee ne +1002b328: f006 028f andne.w r2, r6, #143 ; 0x8f +1002b32c: 4629 movne r1, r5 +1002b32e: 22ff moveq r2, #255 ; 0xff +1002b330: 4641 moveq r1, r8 +1002b332: 4620 mov r0, r4 +1002b334: f005 fe02 bl 10030f3c +1002b338: f640 79ff movw r9, #4095 ; 0xfff +1002b33c: 464b mov r3, r9 +1002b33e: 2218 movs r2, #24 +1002b340: 2100 movs r1, #0 +1002b342: 4638 mov r0, r7 +1002b344: f7fe fa04 bl 10029750 +1002b348: f440 4000 orr.w r0, r0, #32768 ; 0x8000 +1002b34c: 9000 str r0, [sp, #0] +1002b34e: 464b mov r3, r9 +1002b350: 2218 movs r2, #24 +1002b352: f7ff fd52 bl 1002adfa <.text_77> +1002b356: 2064 movs r0, #100 ; 0x64 +1002b358: f005 fe12 bl 10030f80 +1002b35c: f016 0070 ands.w r0, r6, #112 ; 0x70 +1002b360: bf19 ittee ne +1002b362: 4632 movne r2, r6 +1002b364: 4629 movne r1, r5 +1002b366: 2200 moveq r2, #0 +1002b368: 4641 moveq r1, r8 +1002b36a: 4620 mov r0, r4 +1002b36c: e8bd 43f8 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +1002b370: f005 bde4 b.w 10030f3c + +1002b374 : +1002b374: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +1002b378: 4681 mov r9, r0 +1002b37a: f641 30a4 movw r0, #7076 ; 0x1ba4 +1002b37e: b0af sub sp, #188 ; 0xbc +1002b380: f850 0009 ldr.w r0, [r0, r9] +1002b384: 9003 str r0, [sp, #12] +1002b386: 468b mov fp, r1 +1002b388: f500 50c8 add.w r0, r0, #6400 ; 0x1900 +1002b38c: 4617 mov r7, r2 +1002b38e: f100 0aa8 add.w sl, r0, #168 ; 0xa8 +1002b392: 2600 movs r6, #0 +1002b394: a806 add r0, sp, #24 +1002b396: f20f 3154 addw r1, pc, #852 ; 0x354 +1002b39a: 2224 movs r2, #36 ; 0x24 +1002b39c: f003 f886 bl 1002e4ac <__iar_unaligned___aeabi_memcpy4> +1002b3a0: f8da 0028 ldr.w r0, [sl, #40] ; 0x28 +1002b3a4: 0140 lsls r0, r0, #5 +1002b3a6: d556 bpl.n 1002b456 +1002b3a8: 2f00 cmp r7, #0 +1002b3aa: d04d beq.n 1002b448 +1002b3ac: f60a 1038 addw r0, sl, #2360 ; 0x938 +1002b3b0: 9000 str r0, [sp, #0] +1002b3b2: 2700 movs r7, #0 +1002b3b4: 22ff movs r2, #255 ; 0xff +1002b3b6: f640 1148 movw r1, #2376 ; 0x948 +1002b3ba: 4650 mov r0, sl +1002b3bc: f005 fdcc bl 10030f58 +1002b3c0: ea5f 0800 movs.w r8, r0 +1002b3c4: bf18 it ne +1002b3c6: f04f 0801 movne.w r8, #1 +1002b3ca: 2400 movs r4, #0 +1002b3cc: 9800 ldr r0, [sp, #0] +1002b3ce: 2118 movs r1, #24 +1002b3d0: fb01 0008 mla r0, r1, r8, r0 +1002b3d4: eb00 00c4 add.w r0, r0, r4, lsl #3 +1002b3d8: f8d0 152c ldr.w r1, [r0, #1324] ; 0x52c +1002b3dc: f8d0 3530 ldr.w r3, [r0, #1328] ; 0x530 +1002b3e0: 2900 cmp r1, #0 +1002b3e2: bf18 it ne +1002b3e4: 2b00 cmpne r3, #0 +1002b3e6: d101 bne.n 1002b3ec +1002b3e8: 27ff movs r7, #255 ; 0xff +1002b3ea: e005 b.n 1002b3f8 +1002b3ec: f000 f920 bl 1002b630 <.text_140> +1002b3f0: 1c60 adds r0, r4, #1 +1002b3f2: b2c4 uxtb r4, r0 +1002b3f4: 2c03 cmp r4, #3 +1002b3f6: dbe9 blt.n 1002b3cc +1002b3f8: 2500 movs r5, #0 +1002b3fa: 9800 ldr r0, [sp, #0] +1002b3fc: eb00 1008 add.w r0, r0, r8, lsl #4 +1002b400: eb00 00c5 add.w r0, r0, r5, lsl #3 +1002b404: f8d0 155c ldr.w r1, [r0, #1372] ; 0x55c +1002b408: f8d0 3560 ldr.w r3, [r0, #1376] ; 0x560 +1002b40c: 2900 cmp r1, #0 +1002b40e: bf18 it ne +1002b410: 2b00 cmpne r3, #0 +1002b412: d101 bne.n 1002b418 +1002b414: 27ff movs r7, #255 ; 0xff +1002b416: e005 b.n 1002b424 +1002b418: f000 f90a bl 1002b630 <.text_140> +1002b41c: 1c68 adds r0, r5, #1 +1002b41e: b2c5 uxtb r5, r0 +1002b420: 2d02 cmp r5, #2 +1002b422: dbea blt.n 1002b3fa +1002b424: f8da 0ee0 ldr.w r0, [sl, #3808] ; 0xee0 +1002b428: b170 cbz r0, 1002b448 +1002b42a: 9000 str r0, [sp, #0] +1002b42c: 2208 movs r2, #8 +1002b42e: 4b6e ldr r3, [pc, #440] ; (1002b5e8 <.text_130>) +1002b430: f000 f8f0 bl 1002b614 <.text_137> +1002b434: f8da 0ee4 ldr.w r0, [sl, #3812] ; 0xee4 +1002b438: 4b6b ldr r3, [pc, #428] ; (1002b5e8 <.text_130>) +1002b43a: 9000 str r0, [sp, #0] +1002b43c: 2208 movs r2, #8 +1002b43e: 2101 movs r1, #1 +1002b440: f000 f8e9 bl 1002b616 <.text_137+0x2> +1002b444: 2f00 cmp r7, #0 +1002b446: d006 beq.n 1002b456 +1002b448: f1bb 0f00 cmp.w fp, #0 +1002b44c: d004 beq.n 1002b458 +1002b44e: f000 f8db bl 1002b608 <.text_136> +1002b452: f7ff fc36 bl 1002acc2 <_PHY_ReloadADDARegisters8195A> +1002b456: e0ba b.n 1002b5ce +1002b458: f000 f8e4 bl 1002b624 <.text_139> +1002b45c: f005 fd7c bl 10030f58 +1002b460: 9005 str r0, [sp, #20] +1002b462: 22b0 movs r2, #176 ; 0xb0 +1002b464: 4b60 ldr r3, [pc, #384] ; (1002b5e8 <.text_130>) +1002b466: 2100 movs r1, #0 +1002b468: 4650 mov r0, sl +1002b46a: f005 fd81 bl 10030f70 +1002b46e: 9004 str r0, [sp, #16] +1002b470: f10d 0b3c add.w fp, sp, #60 ; 0x3c +1002b474: 4630 mov r0, r6 +1002b476: 4602 mov r2, r0 +1002b478: a90f add r1, sp, #60 ; 0x3c +1002b47a: f84b 2020 str.w r2, [fp, r0, lsl #2] +1002b47e: eb01 0180 add.w r1, r1, r0, lsl #2 +1002b482: 1c40 adds r0, r0, #1 +1002b484: 620a str r2, [r1, #32] +1002b486: 640a str r2, [r1, #64] ; 0x40 +1002b488: 2808 cmp r0, #8 +1002b48a: 660a str r2, [r1, #96] ; 0x60 +1002b48c: dbf4 blt.n 1002b478 +1002b48e: 24ff movs r4, #255 ; 0xff +1002b490: 2700 movs r7, #0 +1002b492: 4690 mov r8, r2 +1002b494: 4615 mov r5, r2 +1002b496: 2300 movs r3, #0 +1002b498: 462a mov r2, r5 +1002b49a: a90f add r1, sp, #60 ; 0x3c +1002b49c: 4648 mov r0, r9 +1002b49e: f7ff fd8b bl 1002afb8 +1002b4a2: 2d01 cmp r5, #1 +1002b4a4: d103 bne.n 1002b4ae +1002b4a6: 2301 movs r3, #1 +1002b4a8: f000 f8b8 bl 1002b61c <.text_138> +1002b4ac: b928 cbnz r0, 1002b4ba +1002b4ae: 2d02 cmp r5, #2 +1002b4b0: d11b bne.n 1002b4ea +1002b4b2: 2302 movs r3, #2 +1002b4b4: f000 f8b2 bl 1002b61c <.text_138> +1002b4b8: b108 cbz r0, 1002b4be +1002b4ba: 2400 movs r4, #0 +1002b4bc: e019 b.n 1002b4f2 +1002b4be: 2302 movs r3, #2 +1002b4c0: 2201 movs r2, #1 +1002b4c2: a90f add r1, sp, #60 ; 0x3c +1002b4c4: 4648 mov r0, r9 +1002b4c6: f7ff fcc9 bl 1002ae5c +1002b4ca: b108 cbz r0, 1002b4d0 +1002b4cc: 2401 movs r4, #1 +1002b4ce: e00c b.n 1002b4ea +1002b4d0: 2500 movs r5, #0 +1002b4d2: a80f add r0, sp, #60 ; 0x3c +1002b4d4: eb00 0085 add.w r0, r0, r5, lsl #2 +1002b4d8: 1c6d adds r5, r5, #1 +1002b4da: 6e00 ldr r0, [r0, #96] ; 0x60 +1002b4dc: 1986 adds r6, r0, r6 +1002b4de: 2d08 cmp r5, #8 +1002b4e0: dbf7 blt.n 1002b4d2 +1002b4e2: 2e00 cmp r6, #0 +1002b4e4: bf14 ite ne +1002b4e6: 2403 movne r4, #3 +1002b4e8: 24ff moveq r4, #255 ; 0xff +1002b4ea: 1c68 adds r0, r5, #1 +1002b4ec: b2c5 uxtb r5, r0 +1002b4ee: 2d03 cmp r5, #3 +1002b4f0: dbd1 blt.n 1002b496 +1002b4f2: 2500 movs r5, #0 +1002b4f4: 0169 lsls r1, r5, #5 +1002b4f6: aa0f add r2, sp, #60 ; 0x3c +1002b4f8: f851 000b ldr.w r0, [r1, fp] +1002b4fc: 188a adds r2, r1, r2 +1002b4fe: 6891 ldr r1, [r2, #8] +1002b500: 6913 ldr r3, [r2, #16] +1002b502: 9302 str r3, [sp, #8] +1002b504: 1c6d adds r5, r5, #1 +1002b506: 6996 ldr r6, [r2, #24] +1002b508: 2d04 cmp r5, #4 +1002b50a: dbf3 blt.n 1002b4f4 +1002b50c: 0162 lsls r2, r4, #5 +1002b50e: ab0f add r3, sp, #60 ; 0x3c +1002b510: 18d3 adds r3, r2, r3 +1002b512: 9301 str r3, [sp, #4] +1002b514: 2cff cmp r4, #255 ; 0xff +1002b516: f60a 133c addw r3, sl, #2364 ; 0x93c +1002b51a: d019 beq.n 1002b550 +1002b51c: f852 000b ldr.w r0, [r2, fp] +1002b520: f8ca 093c str.w r0, [sl, #2364] ; 0x93c +1002b524: f04f 0801 mov.w r8, #1 +1002b528: 9801 ldr r0, [sp, #4] +1002b52a: 6840 ldr r0, [r0, #4] +1002b52c: 6058 str r0, [r3, #4] +1002b52e: 2701 movs r7, #1 +1002b530: 9801 ldr r0, [sp, #4] +1002b532: 6900 ldr r0, [r0, #16] +1002b534: 6098 str r0, [r3, #8] +1002b536: 9801 ldr r0, [sp, #4] +1002b538: 6940 ldr r0, [r0, #20] +1002b53a: 60d8 str r0, [r3, #12] +1002b53c: f852 000b ldr.w r0, [r2, fp] +1002b540: 9901 ldr r1, [sp, #4] +1002b542: 9a01 ldr r2, [sp, #4] +1002b544: 6889 ldr r1, [r1, #8] +1002b546: 6912 ldr r2, [r2, #16] +1002b548: 9202 str r2, [sp, #8] +1002b54a: 9a01 ldr r2, [sp, #4] +1002b54c: 6996 ldr r6, [r2, #24] +1002b54e: e006 b.n 1002b55e +1002b550: f44f 7280 mov.w r2, #256 ; 0x100 +1002b554: 609a str r2, [r3, #8] +1002b556: f8ca 293c str.w r2, [sl, #2364] ; 0x93c +1002b55a: 60df str r7, [r3, #12] +1002b55c: 605f str r7, [r3, #4] +1002b55e: b130 cbz r0, 1002b56e +1002b560: 1e48 subs r0, r1, #1 +1002b562: f000 f84b bl 1002b5fc <.text_135> +1002b566: 4639 mov r1, r7 +1002b568: 4648 mov r0, r9 +1002b56a: f7ff fa3d bl 1002a9e8 <_PHY_PathAFillIQKMatrix8195A> +1002b56e: 9802 ldr r0, [sp, #8] +1002b570: b130 cbz r0, 1002b580 +1002b572: 1e70 subs r0, r6, #1 +1002b574: f000 f842 bl 1002b5fc <.text_135> +1002b578: 4641 mov r1, r8 +1002b57a: 4648 mov r0, r9 +1002b57c: f7ff fac8 bl 1002ab10 <_PHY_PathBFillIQKMatrix8195A> +1002b580: 9803 ldr r0, [sp, #12] +1002b582: f890 0044 ldrb.w r0, [r0, #68] ; 0x44 +1002b586: f007 fc5d bl 10032e44 +1002b58a: 2c04 cmp r4, #4 +1002b58c: da10 bge.n 1002b5b0 +1002b58e: 2124 movs r1, #36 ; 0x24 +1002b590: 2500 movs r5, #0 +1002b592: fb01 a000 mla r0, r1, r0, sl +1002b596: 9901 ldr r1, [sp, #4] +1002b598: f851 1025 ldr.w r1, [r1, r5, lsl #2] +1002b59c: eb00 0285 add.w r2, r0, r5, lsl #2 +1002b5a0: 1c6d adds r5, r5, #1 +1002b5a2: 2d08 cmp r5, #8 +1002b5a4: f8c2 1990 str.w r1, [r2, #2448] ; 0x990 +1002b5a8: dbf5 blt.n 1002b596 +1002b5aa: 2101 movs r1, #1 +1002b5ac: f880 198c strb.w r1, [r0, #2444] ; 0x98c +1002b5b0: f000 f82a bl 1002b608 <.text_136> +1002b5b4: f7ff fb60 bl 1002ac78 <_PHY_SaveADDARegisters8195A> +1002b5b8: 9b05 ldr r3, [sp, #20] +1002b5ba: f000 f833 bl 1002b624 <.text_139> +1002b5be: f005 fcc7 bl 10030f50 +1002b5c2: 9804 ldr r0, [sp, #16] +1002b5c4: 4b08 ldr r3, [pc, #32] ; (1002b5e8 <.text_130>) +1002b5c6: 9000 str r0, [sp, #0] +1002b5c8: 22b0 movs r2, #176 ; 0xb0 +1002b5ca: f000 f823 bl 1002b614 <.text_137> +1002b5ce: b02f add sp, #188 ; 0xbc +1002b5d0: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} +1002b5d4: 0000 movs r0, r0 + ... + +1002b5d8 <.text_126>: +1002b5d8: 03ff0000 .word 0x03ff0000 + +1002b5dc <.text_127>: +1002b5dc: 03c00014 .word 0x03c00014 + +1002b5e0 <.text_128>: +1002b5e0: 00808000 .word 0x00808000 + +1002b5e4 <.text_129>: +1002b5e4: fffffc00 .word 0xfffffc00 + +1002b5e8 <.text_130>: +1002b5e8: 000fffff .word 0x000fffff + +1002b5ec <.text_131>: +1002b5ec: 03a05600 .word 0x03a05600 + +1002b5f0 <.text_132>: +1002b5f0: 000800e4 .word 0x000800e4 + +1002b5f4 <.text_133>: +1002b5f4: 25204000 .word 0x25204000 + +1002b5f8 <.text_134>: +1002b5f8: 01008c00 .word 0x01008c00 + +1002b5fc <.text_135>: +1002b5fc: 4180 sbcs r0, r0 +1002b5fe: 0fc0 lsrs r0, r0, #31 +1002b600: 9000 str r0, [sp, #0] +1002b602: 4623 mov r3, r4 +1002b604: aa0f add r2, sp, #60 ; 0x3c +1002b606: 4770 bx lr + +1002b608 <.text_136>: +1002b608: 2309 movs r3, #9 +1002b60a: f60a 621c addw r2, sl, #3612 ; 0xe1c +1002b60e: a906 add r1, sp, #24 +1002b610: 4648 mov r0, r9 +1002b612: 4770 bx lr + +1002b614 <.text_137>: +1002b614: 2100 movs r1, #0 +1002b616: 4650 mov r0, sl +1002b618: f005 bca2 b.w 10030f60 + +1002b61c <.text_138>: +1002b61c: 2200 movs r2, #0 +1002b61e: a90f add r1, sp, #60 ; 0x3c +1002b620: 4648 mov r0, r9 +1002b622: e41b b.n 1002ae5c + +1002b624 <.text_139>: +1002b624: f04f 32ff mov.w r2, #4294967295 +1002b628: f640 1148 movw r1, #2376 ; 0x948 +1002b62c: 4650 mov r0, sl +1002b62e: 4770 bx lr + +1002b630 <.text_140>: +1002b630: f04f 32ff mov.w r2, #4294967295 +1002b634: 4650 mov r0, sl +1002b636: f005 bc8b b.w 10030f50 + +1002b63a : +1002b63a: b538 push {r3, r4, r5, lr} +1002b63c: 4604 mov r4, r0 +1002b63e: 2500 movs r5, #0 +1002b640: 6aa0 ldr r0, [r4, #40] ; 0x28 +1002b642: 0140 lsls r0, r0, #5 +1002b644: d404 bmi.n 1002b650 +1002b646: bd31 pop {r0, r4, r5, pc} +1002b648: 2032 movs r0, #50 ; 0x32 +1002b64a: f005 fc99 bl 10030f80 +1002b64e: 3532 adds r5, #50 ; 0x32 +1002b650: f8d4 008c ldr.w r0, [r4, #140] ; 0x8c +1002b654: 7800 ldrb r0, [r0, #0] +1002b656: b110 cbz r0, 1002b65e +1002b658: f5b5 6ffa cmp.w r5, #2000 ; 0x7d0 +1002b65c: d3f4 bcc.n 1002b648 +1002b65e: 2001 movs r0, #1 +1002b660: f884 0dc5 strb.w r0, [r4, #3525] ; 0xdc5 +1002b664: 2100 movs r1, #0 +1002b666: 4620 mov r0, r4 +1002b668: f7ff fe4f bl 1002b30a +1002b66c: 2000 movs r0, #0 +1002b66e: f884 0dc5 strb.w r0, [r4, #3525] ; 0xdc5 +1002b672: bd31 pop {r0, r4, r5, pc} + +1002b674 : +1002b674: ffff 0000 .... + +1002b678 : +1002b678: 085c 0000 0e6c 0000 0e70 0000 0e74 0000 \...l...p...t... +1002b688: 0e78 0000 0e7c 0000 0e80 0000 0e84 0000 x...|........... +1002b698: 0e88 0000 0e8c 0000 0ed0 0000 0ed4 0000 ................ +1002b6a8: 0ed8 0000 0edc 0000 0ee0 0000 0eec 0000 ................ + +1002b6b8 : +1002b6b8: 0522 0000 0550 0000 0551 0000 0040 0000 "...P...Q...@... + +1002b6c8 : +1002b6c8: 0c04 0000 0c08 0000 0874 0000 0b68 0000 ........t...h... +1002b6d8: 0b6c 0000 0870 0000 0860 0000 0864 0000 l...p...`...d... +1002b6e8: 0800 0000 .... + +1002b6ec : +1002b6ec: 0c14 0000 0c1c 0000 0c4c 0000 0c78 0000 ........L...x... +1002b6fc: 0c80 0000 0c88 0000 0c94 0000 0c9c 0000 ................ +1002b70c: 0ca0 0000 .... + +1002b710 : +1002b710: e92d 4ff6 stmdb sp!, {r1, r2, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1002b714: b083 sub sp, #12 +1002b716: 2400 movs r4, #0 +1002b718: f8dd b038 ldr.w fp, [sp, #56] ; 0x38 +1002b71c: 4680 mov r8, r0 +1002b71e: 461d mov r5, r3 +1002b720: 46a2 mov sl, r4 +1002b722: e012 b.n 1002b74a +1002b724: f8bd 7000 ldrh.w r7, [sp] +1002b728: 4639 mov r1, r7 +1002b72a: 4640 mov r0, r8 +1002b72c: f7f9 fa7e bl 10024c2c +1002b730: f89d 2005 ldrb.w r2, [sp, #5] +1002b734: f89d 1006 ldrb.w r1, [sp, #6] +1002b738: 4390 bics r0, r2 +1002b73a: 4011 ands r1, r2 +1002b73c: ea41 0200 orr.w r2, r1, r0 +1002b740: 4639 mov r1, r7 +1002b742: 4640 mov r0, r8 +1002b744: f7f9 fa84 bl 10024c50 +1002b748: 1c64 adds r4, r4, #1 +1002b74a: a800 add r0, sp, #0 +1002b74c: eb0b 01c4 add.w r1, fp, r4, lsl #3 +1002b750: 2208 movs r2, #8 +1002b752: f002 fe9b bl 1002e48c <__iar_unaligned___aeabi_memcpy> +1002b756: f89d 0003 ldrb.w r0, [sp, #3] +1002b75a: f89d 1010 ldrb.w r1, [sp, #16] +1002b75e: 4001 ands r1, r0 +1002b760: 220f movs r2, #15 +1002b762: 4211 tst r1, r2 +1002b764: bf1f itttt ne +1002b766: f89d 1002 ldrbne.w r1, [sp, #2] +1002b76a: f89d 200c ldrbne.w r2, [sp, #12] +1002b76e: 4211 tstne r1, r2 +1002b770: ea15 1f10 tstne.w r5, r0, lsr #4 +1002b774: d0e8 beq.n 1002b748 +1002b776: f89d 0004 ldrb.w r0, [sp, #4] +1002b77a: 0900 lsrs r0, r0, #4 +1002b77c: 2801 cmp r0, #1 +1002b77e: d0d1 beq.n 1002b724 +1002b780: d3e2 bcc.n 1002b748 +1002b782: 2803 cmp r0, #3 +1002b784: d022 beq.n 1002b7cc +1002b786: d302 bcc.n 1002b78e +1002b788: 2804 cmp r0, #4 +1002b78a: d02b beq.n 1002b7e4 +1002b78c: e7dc b.n 1002b748 +1002b78e: f8bd 9000 ldrh.w r9, [sp] +1002b792: f89d 6005 ldrb.w r6, [sp, #5] +1002b796: 2700 movs r7, #0 +1002b798: 4649 mov r1, r9 +1002b79a: 4640 mov r0, r8 +1002b79c: f7f9 fa46 bl 10024c2c +1002b7a0: f89d 1006 ldrb.w r1, [sp, #6] +1002b7a4: 4030 ands r0, r6 +1002b7a6: 4031 ands r1, r6 +1002b7a8: 4288 cmp r0, r1 +1002b7aa: bf0e itee eq +1002b7ac: 2701 moveq r7, #1 +1002b7ae: 200a movne r0, #10 +1002b7b0: f7e5 f932 blne 10010a18 +1002b7b4: 4650 mov r0, sl +1002b7b6: f241 3189 movw r1, #5001 ; 0x1389 +1002b7ba: 4288 cmp r0, r1 +1002b7bc: f100 0a01 add.w sl, r0, #1 +1002b7c0: d301 bcc.n 1002b7c6 +1002b7c2: 2000 movs r0, #0 +1002b7c4: e00f b.n 1002b7e6 +1002b7c6: 2f00 cmp r7, #0 +1002b7c8: d0e6 beq.n 1002b798 +1002b7ca: e7bd b.n 1002b748 +1002b7cc: f8bd 0000 ldrh.w r0, [sp] +1002b7d0: f89d 1006 ldrb.w r1, [sp, #6] +1002b7d4: b911 cbnz r1, 1002b7dc +1002b7d6: f7e5 f91f bl 10010a18 +1002b7da: e7b5 b.n 1002b748 +1002b7dc: f44f 717a mov.w r1, #1000 ; 0x3e8 +1002b7e0: 4348 muls r0, r1 +1002b7e2: e7f8 b.n 1002b7d6 +1002b7e4: 2001 movs r0, #1 +1002b7e6: b005 add sp, #20 +1002b7e8: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1002b7ec : +1002b7ec: 4903 ldr r1, [pc, #12] ; (1002b7fc ) +1002b7ee: 4804 ldr r0, [pc, #16] ; (1002b800 ) +1002b7f0: 68ca ldr r2, [r1, #12] +1002b7f2: 6949 ldr r1, [r1, #20] +1002b7f4: 6002 str r2, [r0, #0] +1002b7f6: 6041 str r1, [r0, #4] +1002b7f8: 4770 bx lr +1002b7fa: bf00 nop +1002b7fc: 100042a8 .word 0x100042a8 +1002b800: 100006d4 .word 0x100006d4 + +1002b804 : +1002b804: f8df f000 ldr.w pc, [pc] ; 1002b808 +1002b808: 000143d9 .word 0x000143d9 + +1002b80c : +1002b80c: f8df f000 ldr.w pc, [pc] ; 1002b810 +1002b810: 00014435 .word 0x00014435 + +1002b814 : +1002b814: f8df f000 ldr.w pc, [pc] ; 1002b818 +1002b818: 00014419 .word 0x00014419 + +1002b81c : +1002b81c: 7800 ldrb r0, [r0, #0] +1002b81e: 07c0 lsls r0, r0, #31 +1002b820: d501 bpl.n 1002b826 +1002b822: 2001 movs r0, #1 +1002b824: 4770 bx lr +1002b826: 2000 movs r0, #0 +1002b828: 4770 bx lr + +1002b82a : +1002b82a: 6840 ldr r0, [r0, #4] +1002b82c: 4208 tst r0, r1 +1002b82e: d001 beq.n 1002b834 +1002b830: 2001 movs r0, #1 +1002b832: 4770 bx lr +1002b834: 2000 movs r0, #0 +1002b836: 4770 bx lr + +1002b838 <_init_txservq>: +1002b838: b510 push {r4, lr} +1002b83a: 4604 mov r4, r0 +1002b83c: f7e5 f806 bl 1001084c +1002b840: f104 0008 add.w r0, r4, #8 +1002b844: f7e5 f877 bl 10010936 +1002b848: 2000 movs r0, #0 +1002b84a: 6160 str r0, [r4, #20] +1002b84c: bd10 pop {r4, pc} + +1002b84e <_rtw_init_sta_xmit_priv>: +1002b84e: b510 push {r4, lr} +1002b850: 4604 mov r4, r0 +1002b852: 229c movs r2, #156 ; 0x9c +1002b854: 2100 movs r1, #0 +1002b856: f7e4 ffef bl 10010838 +1002b85a: 4620 mov r0, r4 +1002b85c: f7e5 f87b bl 10010956 +1002b860: f104 000c add.w r0, r4, #12 +1002b864: f7ff ffe8 bl 1002b838 <_init_txservq> +1002b868: f104 0024 add.w r0, r4, #36 ; 0x24 +1002b86c: f7ff ffe4 bl 1002b838 <_init_txservq> +1002b870: f104 003c add.w r0, r4, #60 ; 0x3c +1002b874: f7ff ffe0 bl 1002b838 <_init_txservq> +1002b878: f104 0054 add.w r0, r4, #84 ; 0x54 +1002b87c: f7ff ffdc bl 1002b838 <_init_txservq> +1002b880: f104 006c add.w r0, r4, #108 ; 0x6c +1002b884: f7e4 ffe2 bl 1001084c +1002b888: f104 0074 add.w r0, r4, #116 ; 0x74 +1002b88c: e8bd 4010 ldmia.w sp!, {r4, lr} +1002b890: f7e4 bfdc b.w 1001084c + +1002b894 <_rtw_init_xmit_priv>: +1002b894: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1002b898: 4681 mov r9, r0 +1002b89a: 460f mov r7, r1 +1002b89c: f7e5 f85b bl 10010956 +1002b8a0: f109 0440 add.w r4, r9, #64 ; 0x40 +1002b8a4: f109 0004 add.w r0, r9, #4 +1002b8a8: 61a7 str r7, [r4, #24] +1002b8aa: f7e5 f844 bl 10010936 +1002b8ae: f109 0010 add.w r0, r9, #16 +1002b8b2: f7e5 f840 bl 10010936 +1002b8b6: f109 001c add.w r0, r9, #28 +1002b8ba: f7e5 f83c bl 10010936 +1002b8be: f109 0028 add.w r0, r9, #40 ; 0x28 +1002b8c2: f7e5 f838 bl 10010936 +1002b8c6: f109 0034 add.w r0, r9, #52 ; 0x34 +1002b8ca: f7e5 f834 bl 10010936 +1002b8ce: f109 004c add.w r0, r9, #76 ; 0x4c +1002b8d2: f7e5 f830 bl 10010936 +1002b8d6: f640 5044 movw r0, #3396 ; 0xd44 +1002b8da: f7e4 ff7d bl 100107d8 +1002b8de: f8c9 0040 str.w r0, [r9, #64] ; 0x40 +1002b8e2: b908 cbnz r0, 1002b8e8 <_rtw_init_xmit_priv+0x54> +1002b8e4: 6060 str r0, [r4, #4] +1002b8e6: e073 b.n 1002b9d0 <_rtw_init_xmit_priv+0x13c> +1002b8e8: 1cc0 adds r0, r0, #3 +1002b8ea: 0885 lsrs r5, r0, #2 +1002b8ec: 00ad lsls r5, r5, #2 +1002b8ee: 6065 str r5, [r4, #4] +1002b8f0: f04f 0810 mov.w r8, #16 +1002b8f4: 4628 mov r0, r5 +1002b8f6: f7e4 ffa9 bl 1001084c +1002b8fa: f105 0074 add.w r0, r5, #116 ; 0x74 +1002b8fe: 2100 movs r1, #0 +1002b900: 6087 str r7, [r0, #8] +1002b902: 6041 str r1, [r0, #4] +1002b904: 6769 str r1, [r5, #116] ; 0x74 +1002b906: 60c1 str r1, [r0, #12] +1002b908: 6101 str r1, [r0, #16] +1002b90a: 4628 mov r0, r5 +1002b90c: f109 014c add.w r1, r9, #76 ; 0x4c +1002b910: f7e4 ffa6 bl 10010860 +1002b914: 35d4 adds r5, #212 ; 0xd4 +1002b916: f1b8 0801 subs.w r8, r8, #1 +1002b91a: d1eb bne.n 1002b8f4 <_rtw_init_xmit_priv+0x60> +1002b91c: 2010 movs r0, #16 +1002b91e: 60a0 str r0, [r4, #8] +1002b920: f509 70da add.w r0, r9, #436 ; 0x1b4 +1002b924: f7e5 f807 bl 10010936 +1002b928: f509 70e0 add.w r0, r9, #448 ; 0x1c0 +1002b92c: f7e5 f803 bl 10010936 +1002b930: f44f 7039 mov.w r0, #740 ; 0x2e4 +1002b934: f7e4 ff50 bl 100107d8 +1002b938: 2800 cmp r0, #0 +1002b93a: f8c9 01cc str.w r0, [r9, #460] ; 0x1cc +1002b93e: d047 beq.n 1002b9d0 <_rtw_init_xmit_priv+0x13c> +1002b940: 1cc0 adds r0, r0, #3 +1002b942: 0885 lsrs r5, r0, #2 +1002b944: f509 76e6 add.w r6, r9, #460 ; 0x1cc +1002b948: 00ad lsls r5, r5, #2 +1002b94a: 6075 str r5, [r6, #4] +1002b94c: f04f 0a08 mov.w sl, #8 +1002b950: f240 6b56 movw fp, #1622 ; 0x656 +1002b954: 4628 mov r0, r5 +1002b956: f7e4 ff79 bl 1001084c +1002b95a: 2000 movs r0, #0 +1002b95c: 6168 str r0, [r5, #20] +1002b95e: 60af str r7, [r5, #8] +1002b960: 8328 strh r0, [r5, #24] +1002b962: f000 f84f bl 1002ba04 <.text_8> +1002b966: b938 cbnz r0, 1002b978 <_rtw_init_xmit_priv+0xe4> +1002b968: 200a movs r0, #10 +1002b96a: f7e5 f840 bl 100109ee +1002b96e: f000 f849 bl 1002ba04 <.text_8> +1002b972: ea5f 0800 movs.w r8, r0 +1002b976: d042 beq.n 1002b9fe <_rtw_init_xmit_priv+0x16a> +1002b978: 2000 movs r0, #0 +1002b97a: 8368 strh r0, [r5, #26] +1002b97c: f509 71da add.w r1, r9, #436 ; 0x1b4 +1002b980: f000 fdbd bl 1002c4fe <.text_32+0x2> +1002b984: 355c adds r5, #92 ; 0x5c +1002b986: f1ba 0a01 subs.w sl, sl, #1 +1002b98a: d1e3 bne.n 1002b954 <_rtw_init_xmit_priv+0xc0> +1002b98c: 2008 movs r0, #8 +1002b98e: 60b0 str r0, [r6, #8] +1002b990: f509 7aec add.w sl, r9, #472 ; 0x1d8 +1002b994: 4650 mov r0, sl +1002b996: f7e4 ffce bl 10010936 +1002b99a: f44f 7039 mov.w r0, #740 ; 0x2e4 +1002b99e: f7e4 ff1b bl 100107d8 +1002b9a2: 61b0 str r0, [r6, #24] +1002b9a4: b1a0 cbz r0, 1002b9d0 <_rtw_init_xmit_priv+0x13c> +1002b9a6: 1cc0 adds r0, r0, #3 +1002b9a8: 0885 lsrs r5, r0, #2 +1002b9aa: 00ad lsls r5, r5, #2 +1002b9ac: 61f5 str r5, [r6, #28] +1002b9ae: f04f 0b08 mov.w fp, #8 +1002b9b2: 4628 mov r0, r5 +1002b9b4: f7e4 ff4a bl 1001084c +1002b9b8: 2000 movs r0, #0 +1002b9ba: 6168 str r0, [r5, #20] +1002b9bc: 60af str r7, [r5, #8] +1002b9be: 2001 movs r0, #1 +1002b9c0: 8328 strh r0, [r5, #24] +1002b9c2: f240 6204 movw r2, #1540 ; 0x604 +1002b9c6: f000 f81e bl 1002ba06 <.text_8+0x2> +1002b9ca: ea5f 0800 movs.w r8, r0 +1002b9ce: d102 bne.n 1002b9d6 <_rtw_init_xmit_priv+0x142> +1002b9d0: f04f 0800 mov.w r8, #0 +1002b9d4: e013 b.n 1002b9fe <_rtw_init_xmit_priv+0x16a> +1002b9d6: 4651 mov r1, sl +1002b9d8: f000 fd91 bl 1002c4fe <.text_32+0x2> +1002b9dc: 355c adds r5, #92 ; 0x5c +1002b9de: f1bb 0b01 subs.w fp, fp, #1 +1002b9e2: d1e6 bne.n 1002b9b2 <_rtw_init_xmit_priv+0x11e> +1002b9e4: 2008 movs r0, #8 +1002b9e6: 6230 str r0, [r6, #32] +1002b9e8: 4638 mov r0, r7 +1002b9ea: f000 feb7 bl 1002c75c +1002b9ee: f899 108c ldrb.w r1, [r9, #140] ; 0x8c +1002b9f2: 6ca0 ldr r0, [r4, #72] ; 0x48 +1002b9f4: f000 fee9 bl 1002c7ca +1002b9f8: 4638 mov r0, r7 +1002b9fa: f7eb fd09 bl 10017410 +1002b9fe: 4640 mov r0, r8 +1002ba00: e8bd 8ff2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1002ba04 <.text_8>: +1002ba04: 465a mov r2, fp +1002ba06: 4629 mov r1, r5 +1002ba08: 4638 mov r0, r7 +1002ba0a: f004 ba7c b.w 1002ff06 + +1002ba0e : +1002ba0e: b510 push {r4, lr} +1002ba10: 4604 mov r4, r0 +1002ba12: f7e4 ffa7 bl 10010964 +1002ba16: f104 000c add.w r0, r4, #12 +1002ba1a: f7e4 ffa3 bl 10010964 +1002ba1e: f104 0018 add.w r0, r4, #24 +1002ba22: f7e4 ff9f bl 10010964 +1002ba26: f104 0024 add.w r0, r4, #36 ; 0x24 +1002ba2a: f7e4 ff9b bl 10010964 +1002ba2e: f104 0030 add.w r0, r4, #48 ; 0x30 +1002ba32: f7e4 ff97 bl 10010964 +1002ba36: f104 003c add.w r0, r4, #60 ; 0x3c +1002ba3a: f7e4 ff93 bl 10010964 +1002ba3e: f104 0054 add.w r0, r4, #84 ; 0x54 +1002ba42: f7e4 ff8f bl 10010964 +1002ba46: f504 70de add.w r0, r4, #444 ; 0x1bc +1002ba4a: f7e4 ff8b bl 10010964 +1002ba4e: f504 70e4 add.w r0, r4, #456 ; 0x1c8 +1002ba52: e8bd 4010 ldmia.w sp!, {r4, lr} +1002ba56: f7e4 bf85 b.w 10010964 + +1002ba5a <_rtw_free_xmit_priv>: +1002ba5a: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +1002ba5e: 4605 mov r5, r0 +1002ba60: f105 0440 add.w r4, r5, #64 ; 0x40 +1002ba64: f505 76e6 add.w r6, r5, #460 ; 0x1cc +1002ba68: f8d4 8018 ldr.w r8, [r4, #24] +1002ba6c: f8d4 9004 ldr.w r9, [r4, #4] +1002ba70: 6877 ldr r7, [r6, #4] +1002ba72: 4640 mov r0, r8 +1002ba74: f7eb fcd4 bl 10017420 +1002ba78: 4628 mov r0, r5 +1002ba7a: f7ff ffc8 bl 1002ba0e +1002ba7e: 6860 ldr r0, [r4, #4] +1002ba80: 2800 cmp r0, #0 +1002ba82: d039 beq.n 1002baf8 <_rtw_free_xmit_priv+0x9e> +1002ba84: 2410 movs r4, #16 +1002ba86: 4649 mov r1, r9 +1002ba88: 4640 mov r0, r8 +1002ba8a: f004 fa46 bl 1002ff1a +1002ba8e: 1e64 subs r4, r4, #1 +1002ba90: f109 09d4 add.w r9, r9, #212 ; 0xd4 +1002ba94: d1f7 bne.n 1002ba86 <_rtw_free_xmit_priv+0x2c> +1002ba96: 2408 movs r4, #8 +1002ba98: f240 6256 movw r2, #1622 ; 0x656 +1002ba9c: 4639 mov r1, r7 +1002ba9e: 4640 mov r0, r8 +1002baa0: f004 fa36 bl 1002ff10 +1002baa4: 375c adds r7, #92 ; 0x5c +1002baa6: 1e64 subs r4, r4, #1 +1002baa8: d1f6 bne.n 1002ba98 <_rtw_free_xmit_priv+0x3e> +1002baaa: 6c28 ldr r0, [r5, #64] ; 0x40 +1002baac: b118 cbz r0, 1002bab6 <_rtw_free_xmit_priv+0x5c> +1002baae: f640 5144 movw r1, #3396 ; 0xd44 +1002bab2: f7e4 fea0 bl 100107f6 +1002bab6: f8d5 01cc ldr.w r0, [r5, #460] ; 0x1cc +1002baba: b118 cbz r0, 1002bac4 <_rtw_free_xmit_priv+0x6a> +1002babc: f44f 7139 mov.w r1, #740 ; 0x2e4 +1002bac0: f7e4 fe99 bl 100107f6 +1002bac4: f505 70f0 add.w r0, r5, #480 ; 0x1e0 +1002bac8: f7e4 ff4c bl 10010964 +1002bacc: 69f7 ldr r7, [r6, #28] +1002bace: 2508 movs r5, #8 +1002bad0: f240 6204 movw r2, #1540 ; 0x604 +1002bad4: 4639 mov r1, r7 +1002bad6: 4640 mov r0, r8 +1002bad8: f004 fa1a bl 1002ff10 +1002badc: 375c adds r7, #92 ; 0x5c +1002bade: 1e6d subs r5, r5, #1 +1002bae0: d1f6 bne.n 1002bad0 <_rtw_free_xmit_priv+0x76> +1002bae2: 69b0 ldr r0, [r6, #24] +1002bae4: b118 cbz r0, 1002baee <_rtw_free_xmit_priv+0x94> +1002bae6: f44f 7139 mov.w r1, #740 ; 0x2e4 +1002baea: f7e4 fe84 bl 100107f6 +1002baee: 4640 mov r0, r8 +1002baf0: e8bd 43f2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, lr} +1002baf4: f000 be5e b.w 1002c7b4 +1002baf8: e8bd 83f1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, pc} + +1002bafc : +1002bafc: 000a movs r2, r1 +1002bafe: d008 beq.n 1002bb12 +1002bb00: 1ec9 subs r1, r1, #3 +1002bb02: d006 beq.n 1002bb12 +1002bb04: 1e49 subs r1, r1, #1 +1002bb06: 2901 cmp r1, #1 +1002bb08: d907 bls.n 1002bb1a +1002bb0a: 1e89 subs r1, r1, #2 +1002bb0c: 2901 cmp r1, #1 +1002bb0e: d908 bls.n 1002bb22 +1002bb10: e00a b.n 1002bb28 +1002bb12: 0780 lsls r0, r0, #30 +1002bb14: d508 bpl.n 1002bb28 +1002bb16: 2201 movs r2, #1 +1002bb18: e006 b.n 1002bb28 +1002bb1a: 0740 lsls r0, r0, #29 +1002bb1c: d504 bpl.n 1002bb28 +1002bb1e: 2200 movs r2, #0 +1002bb20: e002 b.n 1002bb28 +1002bb22: 0700 lsls r0, r0, #28 +1002bb24: bf48 it mi +1002bb26: 2205 movmi r2, #5 +1002bb28: 4610 mov r0, r2 +1002bb2a: 4770 bx lr + +1002bb2c : +1002bb2c: b570 push {r4, r5, r6, lr} +1002bb2e: 4604 mov r4, r0 +1002bb30: b08a sub sp, #40 ; 0x28 +1002bb32: 460d mov r5, r1 +1002bb34: 6820 ldr r0, [r4, #0] +1002bb36: 2600 movs r6, #0 +1002bb38: 4621 mov r1, r4 +1002bb3a: f004 f9c1 bl 1002fec0 <_rtw_open_pktfile> +1002bb3e: 220e movs r2, #14 +1002bb40: a905 add r1, sp, #20 +1002bb42: 4620 mov r0, r4 +1002bb44: f004 f9c6 bl 1002fed4 <_rtw_pktfile_read> +1002bb48: 88a8 ldrh r0, [r5, #4] +1002bb4a: f5b0 6f00 cmp.w r0, #2048 ; 0x800 +1002bb4e: d108 bne.n 1002bb62 +1002bb50: 2214 movs r2, #20 +1002bb52: a900 add r1, sp, #0 +1002bb54: 4620 mov r0, r4 +1002bb56: f004 f9bd bl 1002fed4 <_rtw_pktfile_read> +1002bb5a: f89d 0001 ldrb.w r0, [sp, #1] +1002bb5e: 0946 lsrs r6, r0, #5 +1002bb60: e004 b.n 1002bb6c +1002bb62: f648 018e movw r1, #34958 ; 0x888e +1002bb66: 4288 cmp r0, r1 +1002bb68: bf08 it eq +1002bb6a: 2607 moveq r6, #7 +1002bb6c: f885 6039 strb.w r6, [r5, #57] ; 0x39 +1002bb70: 201a movs r0, #26 +1002bb72: 8168 strh r0, [r5, #10] +1002bb74: 2088 movs r0, #136 ; 0x88 +1002bb76: 7068 strb r0, [r5, #1] +1002bb78: b00a add sp, #40 ; 0x28 +1002bb7a: bd70 pop {r4, r5, r6, pc} + +1002bb7c : +1002bb7c: e92d 4ff2 stmdb sp!, {r1, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1002bb80: 4681 mov r9, r0 +1002bb82: f509 5088 add.w r0, r9, #4352 ; 0x1100 +1002bb86: b094 sub sp, #80 ; 0x50 +1002bb88: f100 0628 add.w r6, r0, #40 ; 0x28 +1002bb8c: 30f0 adds r0, #240 ; 0xf0 +1002bb8e: 9001 str r0, [sp, #4] +1002bb90: 4615 mov r5, r2 +1002bb92: f109 000c add.w r0, r9, #12 +1002bb96: 9000 str r0, [sp, #0] +1002bb98: 2701 movs r7, #1 +1002bb9a: f500 6088 add.w r0, r0, #1088 ; 0x440 +1002bb9e: 9002 str r0, [sp, #8] +1002bba0: a907 add r1, sp, #28 +1002bba2: 9814 ldr r0, [sp, #80] ; 0x50 +1002bba4: f004 f98c bl 1002fec0 <_rtw_open_pktfile> +1002bba8: 220e movs r2, #14 +1002bbaa: a903 add r1, sp, #12 +1002bbac: a807 add r0, sp, #28 +1002bbae: f004 f991 bl 1002fed4 <_rtw_pktfile_read> +1002bbb2: f8bd 0018 ldrh.w r0, [sp, #24] +1002bbb6: f7e4 fdb3 bl 10010720 <_htons> +1002bbba: 80a8 strh r0, [r5, #4] +1002bbbc: 2206 movs r2, #6 +1002bbbe: a903 add r1, sp, #12 +1002bbc0: f105 003d add.w r0, r5, #61 ; 0x3d +1002bbc4: f7e4 fe23 bl 1001080e +1002bbc8: 2206 movs r2, #6 +1002bbca: f10d 0112 add.w r1, sp, #18 +1002bbce: f105 0043 add.w r0, r5, #67 ; 0x43 +1002bbd2: f7e4 fe1c bl 1001080e +1002bbd6: f105 0859 add.w r8, r5, #89 ; 0x59 +1002bbda: 2000 movs r0, #0 +1002bbdc: f888 0005 strb.w r0, [r8, #5] +1002bbe0: 2120 movs r1, #32 +1002bbe2: 9800 ldr r0, [sp, #0] +1002bbe4: f7ff fe21 bl 1002b82a +1002bbe8: 2801 cmp r0, #1 +1002bbea: d005 beq.n 1002bbf8 +1002bbec: 9800 ldr r0, [sp, #0] +1002bbee: 2140 movs r1, #64 ; 0x40 +1002bbf0: f7ff fe1b bl 1002b82a +1002bbf4: 2801 cmp r0, #1 +1002bbf6: d103 bne.n 1002bc00 +1002bbf8: 2206 movs r2, #6 +1002bbfa: f105 013d add.w r1, r5, #61 ; 0x3d +1002bbfe: e008 b.n 1002bc12 +1002bc00: 9800 ldr r0, [sp, #0] +1002bc02: f100 0490 add.w r4, r0, #144 ; 0x90 +1002bc06: 2108 movs r1, #8 +1002bc08: f7ff fe0f bl 1002b82a +1002bc0c: b148 cbz r0, 1002bc22 +1002bc0e: 2206 movs r2, #6 +1002bc10: 4621 mov r1, r4 +1002bc12: f105 004f add.w r0, r5, #79 ; 0x4f +1002bc16: f7e4 fdfa bl 1001080e +1002bc1a: 2206 movs r2, #6 +1002bc1c: f105 0143 add.w r1, r5, #67 ; 0x43 +1002bc20: e00d b.n 1002bc3e +1002bc22: 9800 ldr r0, [sp, #0] +1002bc24: 2110 movs r1, #16 +1002bc26: f7ff fe00 bl 1002b82a +1002bc2a: b160 cbz r0, 1002bc46 +1002bc2c: 2206 movs r2, #6 +1002bc2e: f105 013d add.w r1, r5, #61 ; 0x3d +1002bc32: f105 004f add.w r0, r5, #79 ; 0x4f +1002bc36: f7e4 fdea bl 1001080e +1002bc3a: 2206 movs r2, #6 +1002bc3c: 4621 mov r1, r4 +1002bc3e: f105 0049 add.w r0, r5, #73 ; 0x49 +1002bc42: f7e4 fde4 bl 1001080e +1002bc46: 1d2c adds r4, r5, #4 +1002bc48: 9808 ldr r0, [sp, #32] +1002bc4a: 60a0 str r0, [r4, #8] +1002bc4c: 88a8 ldrh r0, [r5, #4] +1002bc4e: f5b0 6f00 cmp.w r0, #2048 ; 0x800 +1002bc52: d11e bne.n 1002bc92 +1002bc54: 2218 movs r2, #24 +1002bc56: a90d add r1, sp, #52 ; 0x34 +1002bc58: a807 add r0, sp, #28 +1002bc5a: f004 f93b bl 1002fed4 <_rtw_pktfile_read> +1002bc5e: 1c69 adds r1, r5, #1 +1002bc60: 2000 movs r0, #0 +1002bc62: 7088 strb r0, [r1, #2] +1002bc64: 9808 ldr r0, [sp, #32] +1002bc66: f5b0 7f8d cmp.w r0, #282 ; 0x11a +1002bc6a: d912 bls.n 1002bc92 +1002bc6c: 88a8 ldrh r0, [r5, #4] +1002bc6e: f5b0 6f00 cmp.w r0, #2048 ; 0x800 +1002bc72: d10e bne.n 1002bc92 +1002bc74: a80d add r0, sp, #52 ; 0x34 +1002bc76: 7d41 ldrb r1, [r0, #21] +1002bc78: 2944 cmp r1, #68 ; 0x44 +1002bc7a: d103 bne.n 1002bc84 +1002bc7c: 7dc0 ldrb r0, [r0, #23] +1002bc7e: 2843 cmp r0, #67 ; 0x43 +1002bc80: d107 bne.n 1002bc92 +1002bc82: e004 b.n 1002bc8e +1002bc84: 2943 cmp r1, #67 ; 0x43 +1002bc86: bf04 itt eq +1002bc88: 7dc0 ldrbeq r0, [r0, #23] +1002bc8a: 2844 cmpeq r0, #68 ; 0x44 +1002bc8c: d101 bne.n 1002bc92 +1002bc8e: 1c69 adds r1, r5, #1 +1002bc90: 708f strb r7, [r1, #2] +1002bc92: f640 0106 movw r1, #2054 ; 0x806 +1002bc96: 88a8 ldrh r0, [r5, #4] +1002bc98: 4288 cmp r0, r1 +1002bc9a: bf1c itt ne +1002bc9c: f648 018e movwne r1, #34958 ; 0x888e +1002bca0: 4288 cmpne r0, r1 +1002bca2: bf1e ittt ne +1002bca4: 1c68 addne r0, r5, #1 +1002bca6: 7880 ldrbne r0, [r0, #2] +1002bca8: 2801 cmpne r0, #1 +1002bcaa: d104 bne.n 1002bcb6 +1002bcac: 2201 movs r2, #1 +1002bcae: 2104 movs r1, #4 +1002bcb0: 4648 mov r0, r9 +1002bcb2: f7ea ff84 bl 10016bbe +1002bcb6: f105 004f add.w r0, r5, #79 ; 0x4f +1002bcba: f7ff fdaf bl 1002b81c +1002bcbe: ea5f 0a00 movs.w sl, r0 +1002bcc2: d041 beq.n 1002bd48 +1002bcc4: 4648 mov r0, r9 +1002bcc6: f7f9 fab7 bl 10025238 +1002bcca: ea5f 0b00 movs.w fp, r0 +1002bcce: d03a beq.n 1002bd46 +1002bcd0: f105 0639 add.w r6, r5, #57 ; 0x39 +1002bcd4: f8db 0100 ldr.w r0, [fp, #256] ; 0x100 +1002bcd8: 70b0 strb r0, [r6, #2] +1002bcda: f8c5 b068 str.w fp, [r5, #104] ; 0x68 +1002bcde: 2000 movs r0, #0 +1002bce0: 7070 strb r0, [r6, #1] +1002bce2: 2170 movs r1, #112 ; 0x70 +1002bce4: 200e movs r0, #14 +1002bce6: 80a0 strh r0, [r4, #4] +1002bce8: 2018 movs r0, #24 +1002bcea: 80e0 strh r0, [r4, #6] +1002bcec: 2008 movs r0, #8 +1002bcee: 7068 strb r0, [r5, #1] +1002bcf0: 2000 movs r0, #0 +1002bcf2: f885 0039 strb.w r0, [r5, #57] ; 0x39 +1002bcf6: 9800 ldr r0, [sp, #0] +1002bcf8: f7ff fd97 bl 1002b82a +1002bcfc: 2800 cmp r0, #0 +1002bcfe: d136 bne.n 1002bd6e +1002bd00: 9802 ldr r0, [sp, #8] +1002bd02: 6800 ldr r0, [r0, #0] +1002bd04: b168 cbz r0, 1002bd22 +1002bd06: 4629 mov r1, r5 +1002bd08: a807 add r0, sp, #28 +1002bd0a: f7ff ff0f bl 1002bb2c +1002bd0e: 9800 ldr r0, [sp, #0] +1002bd10: f890 0491 ldrb.w r0, [r0, #1169] ; 0x491 +1002bd14: b128 cbz r0, 1002bd22 +1002bd16: f895 1039 ldrb.w r1, [r5, #57] ; 0x39 +1002bd1a: f7ff feef bl 1002bafc +1002bd1e: f885 0039 strb.w r0, [r5, #57] ; 0x39 +1002bd22: f8db 0110 ldr.w r0, [fp, #272] ; 0x110 +1002bd26: 2801 cmp r0, #1 +1002bd28: d12a bne.n 1002bd80 +1002bd2a: 2000 movs r0, #0 +1002bd2c: 7420 strb r0, [r4, #16] +1002bd2e: f648 018e movw r1, #34958 ; 0x888e +1002bd32: 88a8 ldrh r0, [r5, #4] +1002bd34: 4288 cmp r0, r1 +1002bd36: d065 beq.n 1002be04 +1002bd38: 9800 ldr r0, [sp, #0] +1002bd3a: f44f 3180 mov.w r1, #65536 ; 0x10000 +1002bd3e: f7ff fd74 bl 1002b82a +1002bd42: 2800 cmp r0, #0 +1002bd44: d144 bne.n 1002bdd0 +1002bd46: e057 b.n 1002bdf8 +1002bd48: f105 014f add.w r1, r5, #79 ; 0x4f +1002bd4c: 4630 mov r0, r6 +1002bd4e: f7f9 fa2d bl 100251ac +1002bd52: ea5f 0b00 movs.w fp, r0 +1002bd56: d04f beq.n 1002bdf8 +1002bd58: 9800 ldr r0, [sp, #0] +1002bd5a: 2110 movs r1, #16 +1002bd5c: f7ff fd65 bl 1002b82a +1002bd60: 2801 cmp r0, #1 +1002bd62: d1b5 bne.n 1002bcd0 +1002bd64: f89b 00f8 ldrb.w r0, [fp, #248] ; 0xf8 +1002bd68: 07c0 lsls r0, r0, #31 +1002bd6a: d4b1 bmi.n 1002bcd0 +1002bd6c: e044 b.n 1002bdf8 +1002bd6e: f8db 0104 ldr.w r0, [fp, #260] ; 0x104 +1002bd72: 2800 cmp r0, #0 +1002bd74: d0d5 beq.n 1002bd22 +1002bd76: 4629 mov r1, r5 +1002bd78: a807 add r0, sp, #28 +1002bd7a: f7ff fed7 bl 1002bb2c +1002bd7e: e7d0 b.n 1002bd22 +1002bd80: 9801 ldr r0, [sp, #4] +1002bd82: 6800 ldr r0, [r0, #0] +1002bd84: b170 cbz r0, 1002bda4 +1002bd86: 2802 cmp r0, #2 +1002bd88: d004 beq.n 1002bd94 +1002bd8a: d30b bcc.n 1002bda4 +1002bd8c: 2804 cmp r0, #4 +1002bd8e: d009 beq.n 1002bda4 +1002bd90: d308 bcc.n 1002bda4 +1002bd92: e00a b.n 1002bdaa +1002bd94: f1ba 0f00 cmp.w sl, #0 +1002bd98: bf0e itee eq +1002bd9a: f8db 0114 ldreq.w r0, [fp, #276] ; 0x114 +1002bd9e: 9801 ldrne r0, [sp, #4] +1002bda0: 6dc0 ldrne r0, [r0, #92] ; 0x5c +1002bda2: e001 b.n 1002bda8 +1002bda4: 9801 ldr r0, [sp, #4] +1002bda6: 6840 ldr r0, [r0, #4] +1002bda8: 7420 strb r0, [r4, #16] +1002bdaa: 9801 ldr r0, [sp, #4] +1002bdac: 6800 ldr r0, [r0, #0] +1002bdae: b120 cbz r0, 1002bdba +1002bdb0: 2802 cmp r0, #2 +1002bdb2: d005 beq.n 1002bdc0 +1002bdb4: d301 bcc.n 1002bdba +1002bdb6: 2803 cmp r0, #3 +1002bdb8: d108 bne.n 1002bdcc +1002bdba: 9801 ldr r0, [sp, #4] +1002bdbc: 6880 ldr r0, [r0, #8] +1002bdbe: e006 b.n 1002bdce +1002bdc0: f1ba 0f00 cmp.w sl, #0 +1002bdc4: d002 beq.n 1002bdcc +1002bdc6: 9801 ldr r0, [sp, #4] +1002bdc8: 6e00 ldr r0, [r0, #96] ; 0x60 +1002bdca: e000 b.n 1002bdce +1002bdcc: 2000 movs r0, #0 +1002bdce: 7730 strb r0, [r6, #28] +1002bdd0: 7c20 ldrb r0, [r4, #16] +1002bdd2: 2801 cmp r0, #1 +1002bdd4: d005 beq.n 1002bde2 +1002bdd6: 2802 cmp r0, #2 +1002bdd8: d005 beq.n 1002bde6 +1002bdda: 2804 cmp r0, #4 +1002bddc: d00e beq.n 1002bdfc +1002bdde: 2805 cmp r0, #5 +1002bde0: d110 bne.n 1002be04 +1002bde2: 2004 movs r0, #4 +1002bde4: e00f b.n 1002be06 +1002bde6: 2008 movs r0, #8 +1002bde8: 7460 strb r0, [r4, #17] +1002bdea: 2004 movs r0, #4 +1002bdec: 74a0 strb r0, [r4, #18] +1002bdee: f241 5045 movw r0, #5445 ; 0x1545 +1002bdf2: f810 0009 ldrb.w r0, [r0, r9] +1002bdf6: b950 cbnz r0, 1002be0e +1002bdf8: 2700 movs r7, #0 +1002bdfa: e04a b.n 1002be92 +1002bdfc: 2008 movs r0, #8 +1002bdfe: 7460 strb r0, [r4, #17] +1002be00: 74a0 strb r0, [r4, #18] +1002be02: e004 b.n 1002be0e +1002be04: 2000 movs r0, #0 +1002be06: 7460 strb r0, [r4, #17] +1002be08: 74a0 strb r0, [r4, #18] +1002be0a: 7c20 ldrb r0, [r4, #16] +1002be0c: b158 cbz r0, 1002be26 +1002be0e: f241 5048 movw r0, #5448 ; 0x1548 +1002be12: f850 0009 ldr.w r0, [r0, r9] +1002be16: 2801 cmp r0, #1 +1002be18: d005 beq.n 1002be26 +1002be1a: 9801 ldr r0, [sp, #4] +1002be1c: f8d0 0360 ldr.w r0, [r0, #864] ; 0x360 +1002be20: 1e40 subs r0, r0, #1 +1002be22: 4180 sbcs r0, r0 +1002be24: 0fc0 lsrs r0, r0, #31 +1002be26: 1c69 adds r1, r5, #1 +1002be28: 7048 strb r0, [r1, #1] +1002be2a: f8d9 0004 ldr.w r0, [r9, #4] +1002be2e: 2803 cmp r0, #3 +1002be30: d10a bne.n 1002be48 +1002be32: 7c20 ldrb r0, [r4, #16] +1002be34: 2800 cmp r0, #0 +1002be36: bf18 it ne +1002be38: f1ba 0f00 cmpne.w sl, #0 +1002be3c: d103 bne.n 1002be46 +1002be3e: 2801 cmp r0, #1 +1002be40: bf18 it ne +1002be42: 2805 cmpne r0, #5 +1002be44: d100 bne.n 1002be48 +1002be46: 704f strb r7, [r1, #1] +1002be48: 9814 ldr r0, [sp, #80] ; 0x50 +1002be4a: 4629 mov r1, r5 +1002be4c: f004 f85a bl 1002ff04 +1002be50: 2000 movs r0, #0 +1002be52: f888 0004 strb.w r0, [r8, #4] +1002be56: f888 0008 strb.w r0, [r8, #8] +1002be5a: f888 0006 strb.w r0, [r8, #6] +1002be5e: f8db 0104 ldr.w r0, [fp, #260] ; 0x104 +1002be62: 7770 strb r0, [r6, #29] +1002be64: f89b 0176 ldrb.w r0, [fp, #374] ; 0x176 +1002be68: 77f0 strb r0, [r6, #31] +1002be6a: f8db 01f4 ldr.w r0, [fp, #500] ; 0x1f4 +1002be6e: 77b0 strb r0, [r6, #30] +1002be70: f89b 01fc ldrb.w r0, [fp, #508] ; 0x1fc +1002be74: f885 0059 strb.w r0, [r5, #89] ; 0x59 +1002be78: f89b 01fd ldrb.w r0, [fp, #509] ; 0x1fd +1002be7c: f888 0001 strb.w r0, [r8, #1] +1002be80: f89b 01fe ldrb.w r0, [fp, #510] ; 0x1fe +1002be84: f888 0002 strb.w r0, [r8, #2] +1002be88: 2000 movs r0, #0 +1002be8a: f888 0003 strb.w r0, [r8, #3] +1002be8e: f888 000b strb.w r0, [r8, #11] +1002be92: 4638 mov r0, r7 +1002be94: b015 add sp, #84 ; 0x54 +1002be96: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1002be9a : +1002be9a: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +1002be9e: b08f sub sp, #60 ; 0x3c +1002bea0: 4604 mov r4, r0 +1002bea2: a800 add r0, sp, #0 +1002bea4: 4689 mov r9, r1 +1002bea6: f04f 0b00 mov.w fp, #0 +1002beaa: f109 0608 add.w r6, r9, #8 +1002beae: f504 5788 add.w r7, r4, #4352 ; 0x1100 +1002beb2: f8c0 b000 str.w fp, [r0] +1002beb6: 37f0 adds r7, #240 ; 0xf0 +1002beb8: f106 004f add.w r0, r6, #79 ; 0x4f +1002bebc: f7ff fcae bl 1002b81c +1002bec0: f8d6 a068 ldr.w sl, [r6, #104] ; 0x68 +1002bec4: f1ba 0f00 cmp.w sl, #0 +1002bec8: 4680 mov r8, r0 +1002beca: d104 bne.n 1002bed6 +1002becc: f504 5088 add.w r0, r4, #4352 ; 0x1100 +1002bed0: f000 f8aa bl 1002c028 <.text_16> +1002bed4: 4682 mov sl, r0 +1002bed6: f106 0410 add.w r4, r6, #16 +1002beda: 7920 ldrb r0, [r4, #4] +1002bedc: 2802 cmp r0, #2 +1002bede: f040 809c bne.w 1002c01a +1002bee2: f1ba 0f00 cmp.w sl, #0 +1002bee6: f000 8098 beq.w 1002c01a +1002beea: a80b add r0, sp, #44 ; 0x2c +1002beec: 2110 movs r1, #16 +1002beee: f7f9 fc95 bl 1002581c <__aeabi_memclr4> +1002bef2: f8d9 0080 ldr.w r0, [r9, #128] ; 0x80 +1002bef6: f1b8 0f00 cmp.w r8, #0 +1002befa: f100 0528 add.w r5, r0, #40 ; 0x28 +1002befe: d00f beq.n 1002bf20 +1002bf00: 6e38 ldr r0, [r7, #96] ; 0x60 +1002bf02: eb07 1000 add.w r0, r7, r0, lsl #4 +1002bf06: 2210 movs r2, #16 +1002bf08: a90b add r1, sp, #44 ; 0x2c +1002bf0a: 30a4 adds r0, #164 ; 0xa4 +1002bf0c: f7e4 fc89 bl 10010822 +1002bf10: 2801 cmp r0, #1 +1002bf12: d00e beq.n 1002bf32 +1002bf14: 6e38 ldr r0, [r7, #96] ; 0x60 +1002bf16: eb07 1000 add.w r0, r7, r0, lsl #4 +1002bf1a: f100 01a4 add.w r1, r0, #164 ; 0xa4 +1002bf1e: e00b b.n 1002bf38 +1002bf20: f50a 778c add.w r7, sl, #280 ; 0x118 +1002bf24: 2210 movs r2, #16 +1002bf26: a90b add r1, sp, #44 ; 0x2c +1002bf28: 4638 mov r0, r7 +1002bf2a: f7e4 fc7a bl 10010822 +1002bf2e: 2801 cmp r0, #1 +1002bf30: d101 bne.n 1002bf36 +1002bf32: 2000 movs r0, #0 +1002bf34: e072 b.n 1002c01c +1002bf36: 4639 mov r1, r7 +1002bf38: a803 add r0, sp, #12 +1002bf3a: f7ff fc63 bl 1002b804 +1002bf3e: 7868 ldrb r0, [r5, #1] +1002bf40: 07c0 lsls r0, r0, #31 +1002bf42: d50b bpl.n 1002bf5c +1002bf44: 2206 movs r2, #6 +1002bf46: f105 0110 add.w r1, r5, #16 +1002bf4a: f000 f86a bl 1002c022 <.text_15> +1002bf4e: 7868 ldrb r0, [r5, #1] +1002bf50: 0780 lsls r0, r0, #30 +1002bf52: d50e bpl.n 1002bf72 +1002bf54: 2206 movs r2, #6 +1002bf56: f105 0118 add.w r1, r5, #24 +1002bf5a: e00d b.n 1002bf78 +1002bf5c: 2206 movs r2, #6 +1002bf5e: 1d29 adds r1, r5, #4 +1002bf60: f000 f85f bl 1002c022 <.text_15> +1002bf64: 7868 ldrb r0, [r5, #1] +1002bf66: 0780 lsls r0, r0, #30 +1002bf68: d503 bpl.n 1002bf72 +1002bf6a: 2206 movs r2, #6 +1002bf6c: f105 0110 add.w r1, r5, #16 +1002bf70: e002 b.n 1002bf78 +1002bf72: 2206 movs r2, #6 +1002bf74: f105 010a add.w r1, r5, #10 +1002bf78: f000 f853 bl 1002c022 <.text_15> +1002bf7c: f896 0056 ldrb.w r0, [r6, #86] ; 0x56 +1002bf80: b118 cbz r0, 1002bf8a +1002bf82: f899 0041 ldrb.w r0, [r9, #65] ; 0x41 +1002bf86: f88d 0000 strb.w r0, [sp] +1002bf8a: 2204 movs r2, #4 +1002bf8c: a900 add r1, sp, #0 +1002bf8e: f000 f848 bl 1002c022 <.text_15> +1002bf92: f015 0103 ands.w r1, r5, #3 +1002bf96: bf18 it ne +1002bf98: 2101 movne r1, #1 +1002bf9a: 1cb2 adds r2, r6, #2 +1002bf9c: eb01 0195 add.w r1, r1, r5, lsr #2 +1002bfa0: 8912 ldrh r2, [r2, #8] +1002bfa2: 7960 ldrb r0, [r4, #5] +1002bfa4: eb02 0181 add.w r1, r2, r1, lsl #2 +1002bfa8: eb00 0901 add.w r9, r0, r1 +1002bfac: 78b1 ldrb r1, [r6, #2] +1002bfae: b101 cbz r1, 1002bfb2 +1002bfb0: 79a1 ldrb r1, [r4, #6] +1002bfb2: 6933 ldr r3, [r6, #16] +1002bfb4: 1a9a subs r2, r3, r2 +1002bfb6: 1a10 subs r0, r2, r0 +1002bfb8: 1a47 subs r7, r0, r1 +1002bfba: 463a mov r2, r7 +1002bfbc: 4649 mov r1, r9 +1002bfbe: f000 f830 bl 1002c022 <.text_15> +1002bfc2: 44b9 add r9, r7 +1002bfc4: a909 add r1, sp, #36 ; 0x24 +1002bfc6: a803 add r0, sp, #12 +1002bfc8: f7ff fc20 bl 1002b80c +1002bfcc: 78b0 ldrb r0, [r6, #2] +1002bfce: 2800 cmp r0, #0 +1002bfd0: bf1c itt ne +1002bfd2: 79a0 ldrbne r0, [r4, #6] +1002bfd4: 2800 cmpne r0, #0 +1002bfd6: d009 beq.n 1002bfec +1002bfd8: 2208 movs r2, #8 +1002bfda: 2100 movs r1, #0 +1002bfdc: a801 add r0, sp, #4 +1002bfde: f7e4 fc2b bl 10010838 +1002bfe2: 79a2 ldrb r2, [r4, #6] +1002bfe4: 4649 mov r1, r9 +1002bfe6: a801 add r0, sp, #4 +1002bfe8: f7e4 fc11 bl 1001080e +1002bfec: 2208 movs r2, #8 +1002bfee: a909 add r1, sp, #36 ; 0x24 +1002bff0: 4648 mov r0, r9 +1002bff2: f7e4 fc0c bl 1001080e +1002bff6: 6930 ldr r0, [r6, #16] +1002bff8: 3008 adds r0, #8 +1002bffa: 6130 str r0, [r6, #16] +1002bffc: 78b0 ldrb r0, [r6, #2] +1002bffe: b148 cbz r0, 1002c014 +1002c000: 79a2 ldrb r2, [r4, #6] +1002c002: b13a cbz r2, 1002c014 +1002c004: a901 add r1, sp, #4 +1002c006: f109 0008 add.w r0, r9, #8 +1002c00a: f7e4 fc00 bl 1001080e +1002c00e: e001 b.n 1002c014 +1002c010: f10b 0b08 add.w fp, fp, #8 +1002c014: 6930 ldr r0, [r6, #16] +1002c016: 4583 cmp fp, r0 +1002c018: d3fa bcc.n 1002c010 +1002c01a: 2001 movs r0, #1 +1002c01c: b00f add sp, #60 ; 0x3c +1002c01e: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1002c022 <.text_15>: +1002c022: a803 add r0, sp, #12 +1002c024: f7ff bbf6 b.w 1002b814 + +1002c028 <.text_16>: +1002c028: f106 014f add.w r1, r6, #79 ; 0x4f +1002c02c: 3028 adds r0, #40 ; 0x28 +1002c02e: f7f9 b8bd b.w 100251ac + +1002c032 : +1002c032: b580 push {r7, lr} +1002c034: f101 0208 add.w r2, r1, #8 +1002c038: 7893 ldrb r3, [r2, #2] +1002c03a: b183 cbz r3, 1002c05e +1002c03c: 7d12 ldrb r2, [r2, #20] +1002c03e: 2a01 cmp r2, #1 +1002c040: d005 beq.n 1002c04e +1002c042: 2a02 cmp r2, #2 +1002c044: d006 beq.n 1002c054 +1002c046: 2a04 cmp r2, #4 +1002c048: d007 beq.n 1002c05a +1002c04a: 2a05 cmp r2, #5 +1002c04c: d107 bne.n 1002c05e +1002c04e: f002 f890 bl 1002e172 +1002c052: e004 b.n 1002c05e +1002c054: f002 f8d5 bl 1002e202 +1002c058: e001 b.n 1002c05e +1002c05a: f002 f955 bl 1002e308 +1002c05e: 2001 movs r0, #1 +1002c060: bd02 pop {r1, pc} + +1002c062 : +1002c062: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1002c066: 4683 mov fp, r0 +1002c068: f10b 0a0c add.w sl, fp, #12 +1002c06c: f50a 6088 add.w r0, sl, #1088 ; 0x440 +1002c070: 9000 str r0, [sp, #0] +1002c072: 4616 mov r6, r2 +1002c074: 460d mov r5, r1 +1002c076: f04f 0800 mov.w r8, #0 +1002c07a: f04f 0901 mov.w r9, #1 +1002c07e: f106 004f add.w r0, r6, #79 ; 0x4f +1002c082: f7ff fbcb bl 1002b81c +1002c086: f106 075c add.w r7, r6, #92 ; 0x5c +1002c08a: 68fc ldr r4, [r7, #12] +1002c08c: b94c cbnz r4, 1002c0a2 +1002c08e: b118 cbz r0, 1002c098 +1002c090: 4658 mov r0, fp +1002c092: f7f9 f8d1 bl 10025238 +1002c096: e003 b.n 1002c0a0 +1002c098: f50b 5088 add.w r0, fp, #4352 ; 0x1100 +1002c09c: f7ff ffc4 bl 1002c028 <.text_16> +1002c0a0: 4604 mov r4, r0 +1002c0a2: 221e movs r2, #30 +1002c0a4: 2100 movs r1, #0 +1002c0a6: 4628 mov r0, r5 +1002c0a8: f7e4 fbc6 bl 10010838 +1002c0ac: 8828 ldrh r0, [r5, #0] +1002c0ae: f64f 7103 movw r1, #65283 ; 0xff03 +1002c0b2: 4008 ands r0, r1 +1002c0b4: 7871 ldrb r1, [r6, #1] +1002c0b6: 4308 orrs r0, r1 +1002c0b8: 8028 strh r0, [r5, #0] +1002c0ba: 7870 ldrb r0, [r6, #1] +1002c0bc: 0700 lsls r0, r0, #28 +1002c0be: f140 80c1 bpl.w 1002c244 +1002c0c2: f10a 0b90 add.w fp, sl, #144 ; 0x90 +1002c0c6: 2108 movs r1, #8 +1002c0c8: f000 f8d3 bl 1002c272 <.text_22> +1002c0cc: 2801 cmp r0, #1 +1002c0ce: d16d bne.n 1002c1ac +1002c0d0: 8828 ldrh r0, [r5, #0] +1002c0d2: f440 7080 orr.w r0, r0, #256 ; 0x100 +1002c0d6: 8028 strh r0, [r5, #0] +1002c0d8: 2206 movs r2, #6 +1002c0da: 4659 mov r1, fp +1002c0dc: 1d28 adds r0, r5, #4 +1002c0de: f7e4 fb96 bl 1001080e +1002c0e2: f000 f8bf bl 1002c264 <.text_21> +1002c0e6: 2206 movs r2, #6 +1002c0e8: f106 013d add.w r1, r6, #61 ; 0x3d +1002c0ec: f105 0010 add.w r0, r5, #16 +1002c0f0: f7e4 fb8d bl 1001080e +1002c0f4: 9800 ldr r0, [sp, #0] +1002c0f6: 6800 ldr r0, [r0, #0] +1002c0f8: b100 cbz r0, 1002c0fc +1002c0fa: 46c8 mov r8, r9 +1002c0fc: 7878 ldrb r0, [r7, #1] +1002c0fe: b118 cbz r0, 1002c108 +1002c100: 8828 ldrh r0, [r5, #0] +1002c102: f440 5000 orr.w r0, r0, #8192 ; 0x2000 +1002c106: 8028 strh r0, [r5, #0] +1002c108: 1db1 adds r1, r6, #6 +1002c10a: 7b88 ldrb r0, [r1, #14] +1002c10c: b118 cbz r0, 1002c116 +1002c10e: 8828 ldrh r0, [r5, #0] +1002c110: f440 4080 orr.w r0, r0, #16384 ; 0x4000 +1002c114: 8028 strh r0, [r5, #0] +1002c116: f1b8 0f00 cmp.w r8, #0 +1002c11a: f106 0039 add.w r0, r6, #57 ; 0x39 +1002c11e: d017 beq.n 1002c150 +1002c120: 8889 ldrh r1, [r1, #4] +1002c122: f896 2039 ldrb.w r2, [r6, #57] ; 0x39 +1002c126: 1949 adds r1, r1, r5 +1002c128: 1e89 subs r1, r1, #2 +1002c12a: b122 cbz r2, 1002c136 +1002c12c: 880b ldrh r3, [r1, #0] +1002c12e: f002 020f and.w r2, r2, #15 +1002c132: 431a orrs r2, r3 +1002c134: 800a strh r2, [r1, #0] +1002c136: 797b ldrb r3, [r7, #5] +1002c138: 880a ldrh r2, [r1, #0] +1002c13a: f003 0301 and.w r3, r3, #1 +1002c13e: ea42 1203 orr.w r2, r2, r3, lsl #4 +1002c142: 800a strh r2, [r1, #0] +1002c144: 7843 ldrb r3, [r0, #1] +1002c146: f003 0303 and.w r3, r3, #3 +1002c14a: ea42 1243 orr.w r2, r2, r3, lsl #5 +1002c14e: 800a strh r2, [r1, #0] +1002c150: 2c00 cmp r4, #0 +1002c152: d077 beq.n 1002c244 +1002c154: f000 f879 bl 1002c24a <.text_19> +1002c158: 1c52 adds r2, r2, #1 +1002c15a: f8a1 2094 strh.w r2, [r1, #148] ; 0x94 +1002c15e: f000 f874 bl 1002c24a <.text_19> +1002c162: 0512 lsls r2, r2, #20 +1002c164: 0d12 lsrs r2, r2, #20 +1002c166: f8a1 2094 strh.w r2, [r1, #148] ; 0x94 +1002c16a: f105 0216 add.w r2, r5, #22 +1002c16e: f896 1039 ldrb.w r1, [r6, #57] ; 0x39 +1002c172: eb04 0141 add.w r1, r4, r1, lsl #1 +1002c176: f8b1 1094 ldrh.w r1, [r1, #148] ; 0x94 +1002c17a: 80f1 strh r1, [r6, #6] +1002c17c: 7813 ldrb r3, [r2, #0] +1002c17e: f003 030f and.w r3, r3, #15 +1002c182: ea43 1101 orr.w r1, r3, r1, lsl #4 +1002c186: 8011 strh r1, [r2, #0] +1002c188: 7f80 ldrb r0, [r0, #30] +1002c18a: 2800 cmp r0, #0 +1002c18c: bf1c itt ne +1002c18e: f8d4 01f8 ldrne.w r0, [r4, #504] ; 0x1f8 +1002c192: 2800 cmpne r0, #0 +1002c194: bf1f itttt ne +1002c196: f894 01ff ldrbne.w r0, [r4, #511] ; 0x1ff +1002c19a: f896 2039 ldrbne.w r2, [r6, #57] ; 0x39 +1002c19e: fa09 f102 lslne.w r1, r9, r2 +1002c1a2: 4208 tstne r0, r1 +1002c1a4: d030 beq.n 1002c208 +1002c1a6: f886 905c strb.w r9, [r6, #92] ; 0x5c +1002c1aa: e031 b.n 1002c210 +1002c1ac: 2110 movs r1, #16 +1002c1ae: f000 f860 bl 1002c272 <.text_22> +1002c1b2: 2801 cmp r0, #1 +1002c1b4: d115 bne.n 1002c1e2 +1002c1b6: 8828 ldrh r0, [r5, #0] +1002c1b8: f440 7000 orr.w r0, r0, #512 ; 0x200 +1002c1bc: 8028 strh r0, [r5, #0] +1002c1be: f000 f84b bl 1002c258 <.text_20> +1002c1c2: 2206 movs r2, #6 +1002c1c4: 4659 mov r1, fp +1002c1c6: f105 000a add.w r0, r5, #10 +1002c1ca: f7e4 fb20 bl 1001080e +1002c1ce: 2206 movs r2, #6 +1002c1d0: f106 0143 add.w r1, r6, #67 ; 0x43 +1002c1d4: f105 0010 add.w r0, r5, #16 +1002c1d8: f7e4 fb19 bl 1001080e +1002c1dc: f8d4 0104 ldr.w r0, [r4, #260] ; 0x104 +1002c1e0: e78a b.n 1002c0f8 +1002c1e2: 2120 movs r1, #32 +1002c1e4: f000 f845 bl 1002c272 <.text_22> +1002c1e8: 2801 cmp r0, #1 +1002c1ea: d004 beq.n 1002c1f6 +1002c1ec: 2140 movs r1, #64 ; 0x40 +1002c1ee: f000 f840 bl 1002c272 <.text_22> +1002c1f2: 2801 cmp r0, #1 +1002c1f4: d106 bne.n 1002c204 +1002c1f6: f000 f82f bl 1002c258 <.text_20> +1002c1fa: f000 f833 bl 1002c264 <.text_21> +1002c1fe: 2206 movs r2, #6 +1002c200: 4659 mov r1, fp +1002c202: e7e7 b.n 1002c1d4 +1002c204: 46c1 mov r9, r8 +1002c206: e01d b.n 1002c244 +1002c208: f896 005c ldrb.w r0, [r6, #92] ; 0x5c +1002c20c: 2801 cmp r0, #1 +1002c20e: d119 bne.n 1002c244 +1002c210: f896 0039 ldrb.w r0, [r6, #57] ; 0x39 +1002c214: 88f2 ldrh r2, [r6, #6] +1002c216: f000 000f and.w r0, r0, #15 +1002c21a: eb04 0040 add.w r0, r4, r0, lsl #1 +1002c21e: f8b0 11d4 ldrh.w r1, [r0, #468] ; 0x1d4 +1002c222: 1a54 subs r4, r2, r1 +1002c224: 0524 lsls r4, r4, #20 +1002c226: d503 bpl.n 1002c230 +1002c228: 2000 movs r0, #0 +1002c22a: f886 005c strb.w r0, [r6, #92] ; 0x5c +1002c22e: e009 b.n 1002c244 +1002c230: 428a cmp r2, r1 +1002c232: bf0c ite eq +1002c234: 1c49 addeq r1, r1, #1 +1002c236: 1c51 addne r1, r2, #1 +1002c238: 0509 lsls r1, r1, #20 +1002c23a: 0d09 lsrs r1, r1, #20 +1002c23c: f8a0 11d4 strh.w r1, [r0, #468] ; 0x1d4 +1002c240: f886 905c strb.w r9, [r6, #92] ; 0x5c +1002c244: 4648 mov r0, r9 +1002c246: e8bd 8ff2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1002c24a <.text_19>: +1002c24a: f896 1039 ldrb.w r1, [r6, #57] ; 0x39 +1002c24e: eb04 0141 add.w r1, r4, r1, lsl #1 +1002c252: f8b1 2094 ldrh.w r2, [r1, #148] ; 0x94 +1002c256: 4770 bx lr + +1002c258 <.text_20>: +1002c258: 2206 movs r2, #6 +1002c25a: f106 013d add.w r1, r6, #61 ; 0x3d +1002c25e: 1d28 adds r0, r5, #4 +1002c260: f7e4 bad5 b.w 1001080e + +1002c264 <.text_21>: +1002c264: 2206 movs r2, #6 +1002c266: f106 0143 add.w r1, r6, #67 ; 0x43 +1002c26a: f105 000a add.w r0, r5, #10 +1002c26e: f7e4 bace b.w 1001080e + +1002c272 <.text_22>: +1002c272: 4650 mov r0, sl +1002c274: f7ff bad9 b.w 1002b82a + +1002c278 : +1002c278: b510 push {r4, lr} +1002c27a: f600 1428 addw r4, r0, #2344 ; 0x928 +1002c27e: 1d20 adds r0, r4, #4 +1002c280: f7e4 fb62 bl 10010948 +1002c284: b188 cbz r0, 1002c2aa +1002c286: f104 0010 add.w r0, r4, #16 +1002c28a: f7e4 fb5d bl 10010948 +1002c28e: b160 cbz r0, 1002c2aa +1002c290: f104 001c add.w r0, r4, #28 +1002c294: f7e4 fb58 bl 10010948 +1002c298: b138 cbz r0, 1002c2aa +1002c29a: f104 0028 add.w r0, r4, #40 ; 0x28 +1002c29e: f7e4 fb53 bl 10010948 +1002c2a2: 1e40 subs r0, r0, #1 +1002c2a4: 4180 sbcs r0, r0 +1002c2a6: 0fc0 lsrs r0, r0, #31 +1002c2a8: bd10 pop {r4, pc} +1002c2aa: 2001 movs r0, #1 +1002c2ac: bd10 pop {r4, pc} + +1002c2ae : +1002c2ae: 6e88 ldr r0, [r1, #104] ; 0x68 +1002c2b0: f891 1039 ldrb.w r1, [r1, #57] ; 0x39 +1002c2b4: 1e49 subs r1, r1, #1 +1002c2b6: 2901 cmp r1, #1 +1002c2b8: d906 bls.n 1002c2c8 +1002c2ba: 1ec9 subs r1, r1, #3 +1002c2bc: 2901 cmp r1, #1 +1002c2be: d905 bls.n 1002c2cc +1002c2c0: 1e89 subs r1, r1, #2 +1002c2c2: 2901 cmp r1, #1 +1002c2c4: d904 bls.n 1002c2d0 +1002c2c6: e005 b.n 1002c2d4 +1002c2c8: 303c adds r0, #60 ; 0x3c +1002c2ca: e004 b.n 1002c2d6 +1002c2cc: 3054 adds r0, #84 ; 0x54 +1002c2ce: e002 b.n 1002c2d6 +1002c2d0: 306c adds r0, #108 ; 0x6c +1002c2d2: e000 b.n 1002c2d6 +1002c2d4: 3024 adds r0, #36 ; 0x24 +1002c2d6: 6940 ldr r0, [r0, #20] +1002c2d8: 4770 bx lr + +1002c2da : +1002c2da: b5f0 push {r4, r5, r6, r7, lr} +1002c2dc: f500 649d add.w r4, r0, #1256 ; 0x4e8 +1002c2e0: 3108 adds r1, #8 +1002c2e2: f894 c011 ldrb.w ip, [r4, #17] +1002c2e6: 6e8a ldr r2, [r1, #104] ; 0x68 +1002c2e8: 690b ldr r3, [r1, #16] +1002c2ea: f1bc 0f08 cmp.w ip, #8 +1002c2ee: f504 7788 add.w r7, r4, #272 ; 0x110 +1002c2f2: f502 75ba add.w r5, r2, #372 ; 0x174 +1002c2f6: f641 06b4 movw r6, #6324 ; 0x18b4 +1002c2fa: db06 blt.n 1002c30a +1002c2fc: f641 0cd8 movw ip, #6360 ; 0x18d8 +1002c300: f81c c000 ldrb.w ip, [ip, r0] +1002c304: f1bc 0f00 cmp.w ip, #0 +1002c308: d00b beq.n 1002c322 +1002c30a: 5a30 ldrh r0, [r6, r0] +1002c30c: 4298 cmp r0, r3 +1002c30e: bf38 it cc +1002c310: 2001 movcc r0, #1 +1002c312: d337 bcc.n 1002c384 +1002c314: 7868 ldrb r0, [r5, #1] +1002c316: bb38 cbnz r0, 1002c368 +1002c318: f892 0174 ldrb.w r0, [r2, #372] ; 0x174 +1002c31c: 2800 cmp r0, #0 +1002c31e: d031 beq.n 1002c384 +1002c320: e024 b.n 1002c36c +1002c322: f897 c0ae ldrb.w ip, [r7, #174] ; 0xae +1002c326: f1bc 0f05 cmp.w ip, #5 +1002c32a: bf04 itt eq +1002c32c: f891 c05c ldrbeq.w ip, [r1, #92] ; 0x5c +1002c330: f1bc 0f01 cmpeq.w ip, #1 +1002c334: d108 bne.n 1002c348 +1002c336: f241 1cf4 movw ip, #4596 ; 0x11f4 +1002c33a: f85c c000 ldr.w ip, [ip, r0] +1002c33e: f1bc 0f04 cmp.w ip, #4 +1002c342: bf08 it eq +1002c344: 2002 moveq r0, #2 +1002c346: d01d beq.n 1002c384 +1002c348: 786d ldrb r5, [r5, #1] +1002c34a: b96d cbnz r5, 1002c368 +1002c34c: f892 2174 ldrb.w r2, [r2, #372] ; 0x174 +1002c350: b962 cbnz r2, 1002c36c +1002c352: f891 2057 ldrb.w r2, [r1, #87] ; 0x57 +1002c356: b15a cbz r2, 1002c370 +1002c358: f897 20b7 ldrb.w r2, [r7, #183] ; 0xb7 +1002c35c: 7be4 ldrb r4, [r4, #15] +1002c35e: b10c cbz r4, 1002c364 +1002c360: 2a02 cmp r2, #2 +1002c362: d001 beq.n 1002c368 +1002c364: 2a03 cmp r2, #3 +1002c366: d103 bne.n 1002c370 +1002c368: 2001 movs r0, #1 +1002c36a: e00b b.n 1002c384 +1002c36c: 2002 movs r0, #2 +1002c36e: e009 b.n 1002c384 +1002c370: 5a30 ldrh r0, [r6, r0] +1002c372: 4298 cmp r0, r3 +1002c374: bf38 it cc +1002c376: 2001 movcc r0, #1 +1002c378: d304 bcc.n 1002c384 +1002c37a: f891 005c ldrb.w r0, [r1, #92] ; 0x5c +1002c37e: 2801 cmp r0, #1 +1002c380: bf18 it ne +1002c382: 2000 movne r0, #0 +1002c384: f881 003c strb.w r0, [r1, #60] ; 0x3c +1002c388: bdf0 pop {r4, r5, r6, r7, pc} + +1002c38a : +1002c38a: b510 push {r4, lr} +1002c38c: 4604 mov r4, r0 +1002c38e: 4608 mov r0, r1 +1002c390: 21aa movs r1, #170 ; 0xaa +1002c392: 7021 strb r1, [r4, #0] +1002c394: 7061 strb r1, [r4, #1] +1002c396: f248 1337 movw r3, #33079 ; 0x8137 +1002c39a: 2103 movs r1, #3 +1002c39c: f8df 25ec ldr.w r2, [pc, #1516] ; 1002c98c <.text_50> +1002c3a0: 70a1 strb r1, [r4, #2] +1002c3a2: 4298 cmp r0, r3 +1002c3a4: bf1e ittt ne +1002c3a6: f248 03f3 movwne r3, #33011 ; 0x80f3 +1002c3aa: 4298 cmpne r0, r3 +1002c3ac: 1d12 addne r2, r2, #4 +1002c3ae: 7811 ldrb r1, [r2, #0] +1002c3b0: 70e1 strb r1, [r4, #3] +1002c3b2: 7851 ldrb r1, [r2, #1] +1002c3b4: 7121 strb r1, [r4, #4] +1002c3b6: 7891 ldrb r1, [r2, #2] +1002c3b8: 7161 strb r1, [r4, #5] +1002c3ba: f7e4 f9b1 bl 10010720 <_htons> +1002c3be: 80e0 strh r0, [r4, #6] +1002c3c0: 2008 movs r0, #8 +1002c3c2: bd10 pop {r4, pc} + +1002c3c4 : +1002c3c4: b538 push {r3, r4, r5, lr} +1002c3c6: 4603 mov r3, r0 +1002c3c8: 4608 mov r0, r1 +1002c3ca: f603 1128 addw r1, r3, #2344 ; 0x928 +1002c3ce: f101 045c add.w r4, r1, #92 ; 0x5c +1002c3d2: f891 105c ldrb.w r1, [r1, #92] ; 0x5c +1002c3d6: f503 55c4 add.w r5, r3, #6272 ; 0x1880 +1002c3da: b181 cbz r1, 1002c3fe +1002c3dc: 2901 cmp r1, #1 +1002c3de: d010 beq.n 1002c402 +1002c3e0: 4613 mov r3, r2 +1002c3e2: aa00 add r2, sp, #0 +1002c3e4: 212a movs r1, #42 ; 0x2a +1002c3e6: f7e7 fd4b bl 10013e80 +1002c3ea: b140 cbz r0, 1002c3fe +1002c3ec: 7880 ldrb r0, [r0, #2] +1002c3ee: 0780 lsls r0, r0, #30 +1002c3f0: d505 bpl.n 1002c3fe +1002c3f2: f895 0033 ldrb.w r0, [r5, #51] ; 0x33 +1002c3f6: 2801 cmp r0, #1 +1002c3f8: d002 beq.n 1002c400 +1002c3fa: 2002 movs r0, #2 +1002c3fc: e000 b.n 1002c400 +1002c3fe: 2000 movs r0, #0 +1002c400: 7060 strb r0, [r4, #1] +1002c402: bd31 pop {r0, r4, r5, pc} + +1002c404 : +1002c404: b5d0 push {r4, r6, r7, lr} +1002c406: f891 3078 ldrb.w r3, [r1, #120] ; 0x78 +1002c40a: f600 1428 addw r4, r0, #2344 ; 0x928 +1002c40e: 300c adds r0, #12 +1002c410: f003 030f and.w r3, r3, #15 +1002c414: 2b01 cmp r3, #1 +1002c416: d11d bne.n 1002c454 +1002c418: e9d4 6718 ldrd r6, r7, [r4, #96] ; 0x60 +1002c41c: 18b6 adds r6, r6, r2 +1002c41e: eb47 77e2 adc.w r7, r7, r2, asr #31 +1002c422: e9c4 6718 strd r6, r7, [r4, #96] ; 0x60 +1002c426: f8d0 4470 ldr.w r4, [r0, #1136] ; 0x470 +1002c42a: 1c64 adds r4, r4, #1 +1002c42c: f8c0 4470 str.w r4, [r0, #1136] ; 0x470 +1002c430: 6f08 ldr r0, [r1, #112] ; 0x70 +1002c432: b178 cbz r0, 1002c454 +1002c434: f500 74c0 add.w r4, r0, #384 ; 0x180 +1002c438: e9d4 010e ldrd r0, r1, [r4, #56] ; 0x38 +1002c43c: 1c40 adds r0, r0, #1 +1002c43e: f141 0100 adc.w r1, r1, #0 +1002c442: e9c4 010e strd r0, r1, [r4, #56] ; 0x38 +1002c446: e9d4 0110 ldrd r0, r1, [r4, #64] ; 0x40 +1002c44a: 1880 adds r0, r0, r2 +1002c44c: eb41 71e2 adc.w r1, r1, r2, asr #31 +1002c450: e9c4 0110 strd r0, r1, [r4, #64] ; 0x40 +1002c454: bdd0 pop {r4, r6, r7, pc} + +1002c456 : +1002c456: b570 push {r4, r5, r6, lr} +1002c458: 4604 mov r4, r0 +1002c45a: b082 sub sp, #8 +1002c45c: f504 75ec add.w r5, r4, #472 ; 0x1d8 +1002c460: 2600 movs r6, #0 +1002c462: f000 f91c bl 1002c69e <.text_41> +1002c466: f7e4 fa47 bl 100108f8 +1002c46a: 4628 mov r0, r5 +1002c46c: f7e4 fa6c bl 10010948 +1002c470: 2801 cmp r0, #1 +1002c472: d01d beq.n 1002c4b0 +1002c474: 682e ldr r6, [r5, #0] +1002c476: 4630 mov r0, r6 +1002c478: f7e4 f9f4 bl 10010864 +1002c47c: b1c6 cbz r6, 1002c4b0 +1002c47e: f8d4 01ec ldr.w r0, [r4, #492] ; 0x1ec +1002c482: 1e40 subs r0, r0, #1 +1002c484: f8c4 01ec str.w r0, [r4, #492] ; 0x1ec +1002c488: 2000 movs r0, #0 +1002c48a: 6170 str r0, [r6, #20] +1002c48c: 6a70 ldr r0, [r6, #36] ; 0x24 +1002c48e: b120 cbz r0, 1002c49a +1002c490: 2102 movs r1, #2 +1002c492: f106 0024 add.w r0, r6, #36 ; 0x24 +1002c496: f000 fcf6 bl 1002ce86 +1002c49a: 2100 movs r1, #0 +1002c49c: f240 6052 movw r0, #1618 ; 0x652 +1002c4a0: f7e4 ff7c bl 1001139c +1002c4a4: 60f0 str r0, [r6, #12] +1002c4a6: b118 cbz r0, 1002c4b0 +1002c4a8: 2100 movs r1, #0 +1002c4aa: 6231 str r1, [r6, #32] +1002c4ac: 6900 ldr r0, [r0, #16] +1002c4ae: 6130 str r0, [r6, #16] +1002c4b0: f000 f8f5 bl 1002c69e <.text_41> +1002c4b4: f7e4 fa27 bl 10010906 +1002c4b8: b136 cbz r6, 1002c4c8 +1002c4ba: 68f0 ldr r0, [r6, #12] +1002c4bc: b920 cbnz r0, 1002c4c8 +1002c4be: 4631 mov r1, r6 +1002c4c0: 4620 mov r0, r4 +1002c4c2: f000 f84d bl 1002c560 +1002c4c6: 2600 movs r6, #0 +1002c4c8: 4630 mov r0, r6 +1002c4ca: bd76 pop {r1, r2, r4, r5, r6, pc} + +1002c4cc : +1002c4cc: b570 push {r4, r5, r6, lr} +1002c4ce: 4604 mov r4, r0 +1002c4d0: 000d movs r5, r1 +1002c4d2: b082 sub sp, #8 +1002c4d4: f504 76ec add.w r6, r4, #472 ; 0x1d8 +1002c4d8: d101 bne.n 1002c4de +1002c4da: 2000 movs r0, #0 +1002c4dc: bd76 pop {r1, r2, r4, r5, r6, pc} +1002c4de: f000 f83a bl 1002c556 <.text_35> +1002c4e2: f000 f896 bl 1002c612 <.text_38> +1002c4e6: f000 f809 bl 1002c4fc <.text_32> +1002c4ea: f8d4 01ec ldr.w r0, [r4, #492] ; 0x1ec +1002c4ee: 1c40 adds r0, r0, #1 +1002c4f0: f8c4 01ec str.w r0, [r4, #492] ; 0x1ec +1002c4f4: f000 f82a bl 1002c54c <.text_34> +1002c4f8: 2001 movs r0, #1 +1002c4fa: bd76 pop {r1, r2, r4, r5, r6, pc} + +1002c4fc <.text_32>: +1002c4fc: 4631 mov r1, r6 +1002c4fe: 4628 mov r0, r5 +1002c500: f7e4 b9ae b.w 10010860 + +1002c504 : +1002c504: b570 push {r4, r5, r6, lr} +1002c506: 4604 mov r4, r0 +1002c508: b082 sub sp, #8 +1002c50a: f504 76da add.w r6, r4, #436 ; 0x1b4 +1002c50e: 2500 movs r5, #0 +1002c510: f000 f821 bl 1002c556 <.text_35> +1002c514: 4630 mov r0, r6 +1002c516: f7e4 fa17 bl 10010948 +1002c51a: 2801 cmp r0, #1 +1002c51c: d012 beq.n 1002c544 +1002c51e: 6835 ldr r5, [r6, #0] +1002c520: f000 f877 bl 1002c612 <.text_38> +1002c524: b175 cbz r5, 1002c544 +1002c526: f8d4 01d4 ldr.w r0, [r4, #468] ; 0x1d4 +1002c52a: 1e40 subs r0, r0, #1 +1002c52c: f8c4 01d4 str.w r0, [r4, #468] ; 0x1d4 +1002c530: 2000 movs r0, #0 +1002c532: 6168 str r0, [r5, #20] +1002c534: 6228 str r0, [r5, #32] +1002c536: 6a68 ldr r0, [r5, #36] ; 0x24 +1002c538: b120 cbz r0, 1002c544 +1002c53a: 2102 movs r1, #2 +1002c53c: f105 0024 add.w r0, r5, #36 ; 0x24 +1002c540: f000 fca1 bl 1002ce86 +1002c544: f000 f802 bl 1002c54c <.text_34> +1002c548: 4628 mov r0, r5 +1002c54a: bd76 pop {r1, r2, r4, r5, r6, pc} + +1002c54c <.text_34>: +1002c54c: a900 add r1, sp, #0 +1002c54e: f106 0008 add.w r0, r6, #8 +1002c552: f7e4 b9d8 b.w 10010906 + +1002c556 <.text_35>: +1002c556: a900 add r1, sp, #0 +1002c558: f106 0008 add.w r0, r6, #8 +1002c55c: f7e4 b9cc b.w 100108f8 + +1002c560 : +1002c560: b570 push {r4, r5, r6, lr} +1002c562: 4604 mov r4, r0 +1002c564: 000d movs r5, r1 +1002c566: b082 sub sp, #8 +1002c568: f504 76da add.w r6, r4, #436 ; 0x1b4 +1002c56c: d101 bne.n 1002c572 +1002c56e: 2000 movs r0, #0 +1002c570: bd76 pop {r1, r2, r4, r5, r6, pc} +1002c572: 68e8 ldr r0, [r5, #12] +1002c574: b120 cbz r0, 1002c580 +1002c576: 69c1 ldr r1, [r0, #28] +1002c578: f7e4 ff3b bl 100113f2 +1002c57c: 2000 movs r0, #0 +1002c57e: 60e8 str r0, [r5, #12] +1002c580: 6a68 ldr r0, [r5, #36] ; 0x24 +1002c582: b120 cbz r0, 1002c58e +1002c584: 2103 movs r1, #3 +1002c586: f105 0024 add.w r0, r5, #36 ; 0x24 +1002c58a: f000 fc7c bl 1002ce86 +1002c58e: 8b28 ldrh r0, [r5, #24] +1002c590: 2801 cmp r0, #1 +1002c592: d104 bne.n 1002c59e +1002c594: 4629 mov r1, r5 +1002c596: 4620 mov r0, r4 +1002c598: f7ff ff98 bl 1002c4cc +1002c59c: e00d b.n 1002c5ba +1002c59e: b960 cbnz r0, 1002c5ba +1002c5a0: f7ff ffd9 bl 1002c556 <.text_35> +1002c5a4: f000 f835 bl 1002c612 <.text_38> +1002c5a8: f7ff ffa8 bl 1002c4fc <.text_32> +1002c5ac: f8d4 01d4 ldr.w r0, [r4, #468] ; 0x1d4 +1002c5b0: 1c40 adds r0, r0, #1 +1002c5b2: f8c4 01d4 str.w r0, [r4, #468] ; 0x1d4 +1002c5b6: f7ff ffc9 bl 1002c54c <.text_34> +1002c5ba: 2001 movs r0, #1 +1002c5bc: bd76 pop {r1, r2, r4, r5, r6, pc} + +1002c5be : +1002c5be: b570 push {r4, r5, r6, lr} +1002c5c0: 4606 mov r6, r0 +1002c5c2: b082 sub sp, #8 +1002c5c4: f106 044c add.w r4, r6, #76 ; 0x4c +1002c5c8: 2500 movs r5, #0 +1002c5ca: a900 add r1, sp, #0 +1002c5cc: f104 0008 add.w r0, r4, #8 +1002c5d0: f7e4 f9a0 bl 10010914 +1002c5d4: 4620 mov r0, r4 +1002c5d6: f7e4 f9b7 bl 10010948 +1002c5da: 2801 cmp r0, #1 +1002c5dc: d012 beq.n 1002c604 +1002c5de: 6825 ldr r5, [r4, #0] +1002c5e0: f000 f817 bl 1002c612 <.text_38> +1002c5e4: b175 cbz r5, 1002c604 +1002c5e6: 6cb0 ldr r0, [r6, #72] ; 0x48 +1002c5e8: 1e40 subs r0, r0, #1 +1002c5ea: 64b0 str r0, [r6, #72] ; 0x48 +1002c5ec: 2100 movs r1, #0 +1002c5ee: f105 0078 add.w r0, r5, #120 ; 0x78 +1002c5f2: 226c movs r2, #108 ; 0x6c +1002c5f4: 6081 str r1, [r0, #8] +1002c5f6: 60c1 str r1, [r0, #12] +1002c5f8: f105 0008 add.w r0, r5, #8 +1002c5fc: f7e4 f91c bl 10010838 +1002c600: 2001 movs r0, #1 +1002c602: 67a8 str r0, [r5, #120] ; 0x78 +1002c604: a900 add r1, sp, #0 +1002c606: f104 0008 add.w r0, r4, #8 +1002c60a: f7e4 f984 bl 10010916 +1002c60e: 4628 mov r0, r5 +1002c610: bd76 pop {r1, r2, r4, r5, r6, pc} + +1002c612 <.text_38>: +1002c612: 4628 mov r0, r5 +1002c614: f7e4 b926 b.w 10010864 + +1002c618 : +1002c618: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1002c61c: 4604 mov r4, r0 +1002c61e: b082 sub sp, #8 +1002c620: 6da6 ldr r6, [r4, #88] ; 0x58 +1002c622: 460d mov r5, r1 +1002c624: f104 084c add.w r8, r4, #76 ; 0x4c +1002c628: 2700 movs r7, #0 +1002c62a: b1dd cbz r5, 1002c664 +1002c62c: a900 add r1, sp, #0 +1002c62e: f108 0008 add.w r0, r8, #8 +1002c632: f7e4 f96f bl 10010914 +1002c636: f7ff ffec bl 1002c612 <.text_38> +1002c63a: 6f68 ldr r0, [r5, #116] ; 0x74 +1002c63c: b110 cbz r0, 1002c644 +1002c63e: 4607 mov r7, r0 +1002c640: 2000 movs r0, #0 +1002c642: 6768 str r0, [r5, #116] ; 0x74 +1002c644: 4641 mov r1, r8 +1002c646: f7ff ff5a bl 1002c4fe <.text_32+0x2> +1002c64a: 6ca0 ldr r0, [r4, #72] ; 0x48 +1002c64c: 1c40 adds r0, r0, #1 +1002c64e: 64a0 str r0, [r4, #72] ; 0x48 +1002c650: a900 add r1, sp, #0 +1002c652: f108 0008 add.w r0, r8, #8 +1002c656: f7e4 f95e bl 10010916 +1002c65a: b11f cbz r7, 1002c664 +1002c65c: 4639 mov r1, r7 +1002c65e: 4630 mov r0, r6 +1002c660: f003 fc57 bl 1002ff12 +1002c664: 2001 movs r0, #1 +1002c666: e8bd 81f6 ldmia.w sp!, {r1, r2, r4, r5, r6, r7, r8, pc} + +1002c66a : +1002c66a: b570 push {r4, r5, r6, lr} +1002c66c: b082 sub sp, #8 +1002c66e: 4604 mov r4, r0 +1002c670: 460d mov r5, r1 +1002c672: f000 f814 bl 1002c69e <.text_41> +1002c676: f7e4 f94d bl 10010914 +1002c67a: 682e ldr r6, [r5, #0] +1002c67c: e004 b.n 1002c688 +1002c67e: 4631 mov r1, r6 +1002c680: 6836 ldr r6, [r6, #0] +1002c682: 4620 mov r0, r4 +1002c684: f7ff ffc8 bl 1002c618 +1002c688: 4631 mov r1, r6 +1002c68a: 4628 mov r0, r5 +1002c68c: f7e4 f95d bl 1001094a +1002c690: 2800 cmp r0, #0 +1002c692: d0f4 beq.n 1002c67e +1002c694: f000 f803 bl 1002c69e <.text_41> +1002c698: f7e4 f93d bl 10010916 +1002c69c: bd73 pop {r0, r1, r4, r5, r6, pc} + +1002c69e <.text_41>: +1002c69e: a900 add r1, sp, #0 +1002c6a0: f105 0008 add.w r0, r5, #8 +1002c6a4: 4770 bx lr + +1002c6a6 : +1002c6a6: b580 push {r7, lr} +1002c6a8: f000 f81e bl 1002c6e8 +1002c6ac: b100 cbz r0, 1002c6b0 +1002c6ae: 2001 movs r0, #1 +1002c6b0: bd02 pop {r1, pc} + +1002c6b2 : +1002c6b2: 1e52 subs r2, r2, #1 +1002c6b4: 2a01 cmp r2, #1 +1002c6b6: d906 bls.n 1002c6c6 +1002c6b8: 1ed2 subs r2, r2, #3 +1002c6ba: 2a01 cmp r2, #1 +1002c6bc: d907 bls.n 1002c6ce +1002c6be: 1e92 subs r2, r2, #2 +1002c6c0: 2a01 cmp r2, #1 +1002c6c2: d908 bls.n 1002c6d6 +1002c6c4: e00b b.n 1002c6de +1002c6c6: f101 003c add.w r0, r1, #60 ; 0x3c +1002c6ca: 2103 movs r1, #3 +1002c6cc: e00a b.n 1002c6e4 +1002c6ce: f101 0054 add.w r0, r1, #84 ; 0x54 +1002c6d2: 2101 movs r1, #1 +1002c6d4: e006 b.n 1002c6e4 +1002c6d6: f101 006c add.w r0, r1, #108 ; 0x6c +1002c6da: 2100 movs r1, #0 +1002c6dc: e002 b.n 1002c6e4 +1002c6de: f101 0024 add.w r0, r1, #36 ; 0x24 +1002c6e2: 2102 movs r1, #2 +1002c6e4: 7019 strb r1, [r3, #0] +1002c6e6: 4770 bx lr + +1002c6e8 : +1002c6e8: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1002c6ec: 4688 mov r8, r1 +1002c6ee: 4606 mov r6, r0 +1002c6f0: f108 0708 add.w r7, r8, #8 +1002c6f4: b082 sub sp, #8 +1002c6f6: f8d6 59b0 ldr.w r5, [r6, #2480] ; 0x9b0 +1002c6fa: 6eb8 ldr r0, [r7, #104] ; 0x68 +1002c6fc: 2401 movs r4, #1 +1002c6fe: b318 cbz r0, 1002c748 +1002c700: f897 2039 ldrb.w r2, [r7, #57] ; 0x39 +1002c704: 4601 mov r1, r0 +1002c706: ab00 add r3, sp, #0 +1002c708: 4630 mov r0, r6 +1002c70a: f7ff ffd2 bl 1002c6b2 +1002c70e: 4606 mov r6, r0 +1002c710: f7e4 f89d bl 1001084e +1002c714: b130 cbz r0, 1002c724 +1002c716: f89d 0000 ldrb.w r0, [sp] +1002c71a: f855 1030 ldr.w r1, [r5, r0, lsl #3] +1002c71e: 4630 mov r0, r6 +1002c720: f7e4 f89e bl 10010860 +1002c724: f106 0108 add.w r1, r6, #8 +1002c728: 4640 mov r0, r8 +1002c72a: f7e4 f899 bl 10010860 +1002c72e: 6970 ldr r0, [r6, #20] +1002c730: 1c40 adds r0, r0, #1 +1002c732: 6170 str r0, [r6, #20] +1002c734: f89d 0000 ldrb.w r0, [sp] +1002c738: eb05 00c0 add.w r0, r5, r0, lsl #3 +1002c73c: 6841 ldr r1, [r0, #4] +1002c73e: 1c49 adds r1, r1, #1 +1002c740: 6041 str r1, [r0, #4] +1002c742: 4620 mov r0, r4 +1002c744: e8bd 81f6 ldmia.w sp!, {r1, r2, r4, r5, r6, r7, r8, pc} +1002c748: f506 5088 add.w r0, r6, #4352 ; 0x1100 +1002c74c: f107 014f add.w r1, r7, #79 ; 0x4f +1002c750: f7ff fc6c bl 1002c02c <.text_16+0x4> +1002c754: 2800 cmp r0, #0 +1002c756: d1d3 bne.n 1002c700 +1002c758: 2400 movs r4, #0 +1002c75a: e7f2 b.n 1002c742 + +1002c75c : +1002c75c: b538 push {r3, r4, r5, lr} +1002c75e: f600 1428 addw r4, r0, #2344 ; 0x928 +1002c762: f104 0588 add.w r5, r4, #136 ; 0x88 +1002c766: 2004 movs r0, #4 +1002c768: 7128 strb r0, [r5, #4] +1002c76a: 2020 movs r0, #32 +1002c76c: f7e4 f849 bl 10010802 +1002c770: f8c4 0088 str.w r0, [r4, #136] ; 0x88 +1002c774: 7929 ldrb r1, [r5, #4] +1002c776: 2905 cmp r1, #5 +1002c778: d10e bne.n 1002c798 +1002c77a: f104 0134 add.w r1, r4, #52 ; 0x34 +1002c77e: 6001 str r1, [r0, #0] +1002c780: f104 0128 add.w r1, r4, #40 ; 0x28 +1002c784: 6081 str r1, [r0, #8] +1002c786: f104 011c add.w r1, r4, #28 +1002c78a: 6101 str r1, [r0, #16] +1002c78c: f104 0110 add.w r1, r4, #16 +1002c790: 6181 str r1, [r0, #24] +1002c792: 1d21 adds r1, r4, #4 +1002c794: 6201 str r1, [r0, #32] +1002c796: bd31 pop {r0, r4, r5, pc} +1002c798: 2904 cmp r1, #4 +1002c79a: d10a bne.n 1002c7b2 +1002c79c: f104 0128 add.w r1, r4, #40 ; 0x28 +1002c7a0: 6001 str r1, [r0, #0] +1002c7a2: f104 011c add.w r1, r4, #28 +1002c7a6: 6081 str r1, [r0, #8] +1002c7a8: 1d21 adds r1, r4, #4 +1002c7aa: 6101 str r1, [r0, #16] +1002c7ac: f104 0110 add.w r1, r4, #16 +1002c7b0: 6181 str r1, [r0, #24] +1002c7b2: bd31 pop {r0, r4, r5, pc} + +1002c7b4 : +1002c7b4: f600 1128 addw r1, r0, #2344 ; 0x928 +1002c7b8: f8d1 0088 ldr.w r0, [r1, #136] ; 0x88 +1002c7bc: b120 cbz r0, 1002c7c8 +1002c7be: f891 108c ldrb.w r1, [r1, #140] ; 0x8c +1002c7c2: 00c9 lsls r1, r1, #3 +1002c7c4: f7e4 b822 b.w 1001080c +1002c7c8: 4770 bx lr + +1002c7ca : +1002c7ca: 2200 movs r2, #0 +1002c7cc: 2300 movs r3, #0 +1002c7ce: e002 b.n 1002c7d6 +1002c7d0: 6043 str r3, [r0, #4] +1002c7d2: 1c52 adds r2, r2, #1 +1002c7d4: 3008 adds r0, #8 +1002c7d6: 428a cmp r2, r1 +1002c7d8: dbfa blt.n 1002c7d0 +1002c7da: 4770 bx lr + +1002c7dc : +1002c7dc: f890 0068 ldrb.w r0, [r0, #104] ; 0x68 +1002c7e0: b178 cbz r0, 1002c802 +1002c7e2: 1e40 subs r0, r0, #1 +1002c7e4: 2801 cmp r0, #1 +1002c7e6: d90e bls.n 1002c806 +1002c7e8: 1e80 subs r0, r0, #2 +1002c7ea: d00a beq.n 1002c802 +1002c7ec: 1e40 subs r0, r0, #1 +1002c7ee: 2801 cmp r0, #1 +1002c7f0: d90b bls.n 1002c80a +1002c7f2: 1e80 subs r0, r0, #2 +1002c7f4: 2801 cmp r0, #1 +1002c7f6: d90a bls.n 1002c80e +1002c7f8: 380a subs r0, #10 +1002c7fa: d00a beq.n 1002c812 +1002c7fc: 1e40 subs r0, r0, #1 +1002c7fe: d00a beq.n 1002c816 +1002c800: e00b b.n 1002c81a +1002c802: 2002 movs r0, #2 +1002c804: 4770 bx lr +1002c806: 2003 movs r0, #3 +1002c808: 4770 bx lr +1002c80a: 2001 movs r0, #1 +1002c80c: 4770 bx lr +1002c80e: 2000 movs r0, #0 +1002c810: 4770 bx lr +1002c812: 2004 movs r0, #4 +1002c814: 4770 bx lr +1002c816: 2006 movs r0, #6 +1002c818: 4770 bx lr +1002c81a: 2005 movs r0, #5 +1002c81c: 4770 bx lr + +1002c81e : +1002c81e: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1002c822: 4682 mov sl, r0 +1002c824: 468b mov fp, r1 +1002c826: f50a 5088 add.w r0, sl, #4352 ; 0x1100 +1002c82a: f100 0828 add.w r8, r0, #40 ; 0x28 +1002c82e: f10b 0908 add.w r9, fp, #8 +1002c832: 2700 movs r7, #0 +1002c834: f109 004f add.w r0, r9, #79 ; 0x4f +1002c838: f7fe fff0 bl 1002b81c +1002c83c: 4605 mov r5, r0 +1002c83e: 2110 movs r1, #16 +1002c840: f10a 000c add.w r0, sl, #12 +1002c844: f7fe fff1 bl 1002b82a +1002c848: 2800 cmp r0, #0 +1002c84a: d023 beq.n 1002c894 +1002c84c: f8d9 4068 ldr.w r4, [r9, #104] ; 0x68 +1002c850: b934 cbnz r4, 1002c860 +1002c852: f109 014f add.w r1, r9, #79 ; 0x4f +1002c856: 4640 mov r0, r8 +1002c858: f7f8 fca8 bl 100251ac +1002c85c: 0004 movs r4, r0 +1002c85e: d019 beq.n 1002c894 +1002c860: f8da 1970 ldr.w r1, [sl, #2416] ; 0x970 +1002c864: 2906 cmp r1, #6 +1002c866: bf21 itttt cs +1002c868: f8da 1afc ldrcs.w r1, [sl, #2812] ; 0xafc +1002c86c: 2903 cmpcs r1, #3 +1002c86e: f8da 1b14 ldrcs.w r1, [sl, #2836] ; 0xb14 +1002c872: 2903 cmpcs r1, #3 +1002c874: f109 005f add.w r0, r9, #95 ; 0x5f +1002c878: d30b bcc.n 1002c892 +1002c87a: 4945 ldr r1, [pc, #276] ; (1002c990 <.text_51>) +1002c87c: 6809 ldr r1, [r1, #0] +1002c87e: 291a cmp r1, #26 +1002c880: bfbe ittt lt +1002c882: 4944 ldrlt r1, [pc, #272] ; (1002c994 <.text_52>) +1002c884: 6809 ldrlt r1, [r1, #0] +1002c886: 290a cmplt r1, #10 +1002c888: da03 bge.n 1002c892 +1002c88a: f899 105f ldrb.w r1, [r9, #95] ; 0x5f +1002c88e: 2901 cmp r1, #1 +1002c890: d104 bne.n 1002c89c +1002c892: 2d00 cmp r5, #0 +1002c894: d077 beq.n 1002c986 +1002c896: 2111 movs r1, #17 +1002c898: 7041 strb r1, [r0, #1] +1002c89a: e074 b.n 1002c986 +1002c89c: 2d00 cmp r5, #0 +1002c89e: f108 06c0 add.w r6, r8, #192 ; 0xc0 +1002c8a2: a900 add r1, sp, #0 +1002c8a4: f104 00f0 add.w r0, r4, #240 ; 0xf0 +1002c8a8: d01d beq.n 1002c8e6 +1002c8aa: f7e4 f833 bl 10010914 +1002c8ae: f8b8 00c0 ldrh.w r0, [r8, #192] ; 0xc0 +1002c8b2: 2800 cmp r0, #0 +1002c8b4: d062 beq.n 1002c97c +1002c8b6: 4658 mov r0, fp +1002c8b8: f7e3 ffd4 bl 10010864 +1002c8bc: f000 f872 bl 1002c9a4 <.text_54> +1002c8c0: f000 f86a bl 1002c998 <.text_53> +1002c8c4: 2300 movs r3, #0 +1002c8c6: 8870 ldrh r0, [r6, #2] +1002c8c8: f040 0001 orr.w r0, r0, #1 +1002c8cc: 8070 strh r0, [r6, #2] +1002c8ce: 461a mov r2, r3 +1002c8d0: f8b8 00c0 ldrh.w r0, [r8, #192] ; 0xc0 +1002c8d4: f040 0001 orr.w r0, r0, #1 +1002c8d8: f8a8 00c0 strh.w r0, [r8, #192] ; 0xc0 +1002c8dc: 2105 movs r1, #5 +1002c8de: 4650 mov r0, sl +1002c8e0: f7ec fc0e bl 10019100 +1002c8e4: e049 b.n 1002c97a +1002c8e6: f7e4 f815 bl 10010914 +1002c8ea: f104 00f4 add.w r0, r4, #244 ; 0xf4 +1002c8ee: 7900 ldrb r0, [r0, #4] +1002c8f0: 0740 lsls r0, r0, #29 +1002c8f2: d543 bpl.n 1002c97c +1002c8f4: f104 01f4 add.w r1, r4, #244 ; 0xf4 +1002c8f8: 2501 movs r5, #1 +1002c8fa: 6889 ldr r1, [r1, #8] +1002c8fc: f8b8 00c0 ldrh.w r0, [r8, #192] ; 0xc0 +1002c900: fa05 f101 lsl.w r1, r5, r1 +1002c904: 4208 tst r0, r1 +1002c906: d039 beq.n 1002c97c +1002c908: 4658 mov r0, fp +1002c90a: f7e3 ffab bl 10010864 +1002c90e: f000 f849 bl 1002c9a4 <.text_54> +1002c912: f000 f841 bl 1002c998 <.text_53> +1002c916: f204 3106 addw r1, r4, #774 ; 0x306 +1002c91a: f899 2039 ldrb.w r2, [r9, #57] ; 0x39 +1002c91e: 1e52 subs r2, r2, #1 +1002c920: 2a01 cmp r2, #1 +1002c922: d906 bls.n 1002c932 +1002c924: 1ed2 subs r2, r2, #3 +1002c926: 2a01 cmp r2, #1 +1002c928: d906 bls.n 1002c938 +1002c92a: 1e92 subs r2, r2, #2 +1002c92c: 2a01 cmp r2, #1 +1002c92e: d905 bls.n 1002c93c +1002c930: e006 b.n 1002c940 +1002c932: f894 2306 ldrb.w r2, [r4, #774] ; 0x306 +1002c936: e004 b.n 1002c942 +1002c938: 788a ldrb r2, [r1, #2] +1002c93a: e002 b.n 1002c942 +1002c93c: 78ca ldrb r2, [r1, #3] +1002c93e: e000 b.n 1002c942 +1002c940: 784a ldrb r2, [r1, #1] +1002c942: f012 0201 ands.w r2, r2, #1 +1002c946: 7909 ldrb r1, [r1, #4] +1002c948: d006 beq.n 1002c958 +1002c94a: f8d4 230c ldr.w r2, [r4, #780] ; 0x30c +1002c94e: 1c52 adds r2, r2, #1 +1002c950: f8c4 230c str.w r2, [r4, #780] ; 0x30c +1002c954: b989 cbnz r1, 1002c97a +1002c956: e000 b.n 1002c95a +1002c958: b179 cbz r1, 1002c97a +1002c95a: f104 02f4 add.w r2, r4, #244 ; 0xf4 +1002c95e: 6892 ldr r2, [r2, #8] +1002c960: 8871 ldrh r1, [r6, #2] +1002c962: fa05 f202 lsl.w r2, r5, r2 +1002c966: 4311 orrs r1, r2 +1002c968: 2801 cmp r0, #1 +1002c96a: 8071 strh r1, [r6, #2] +1002c96c: d105 bne.n 1002c97a +1002c96e: 2300 movs r3, #0 +1002c970: 461a mov r2, r3 +1002c972: 2105 movs r1, #5 +1002c974: 4650 mov r0, sl +1002c976: f7ec fbc3 bl 10019100 +1002c97a: 2701 movs r7, #1 +1002c97c: a900 add r1, sp, #0 +1002c97e: f104 00f0 add.w r0, r4, #240 ; 0xf0 +1002c982: f7e3 ffc8 bl 10010916 +1002c986: 4638 mov r0, r7 +1002c988: e8bd 8ff2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1002c98c <.text_50>: +1002c98c: 10044300 .word 0x10044300 + +1002c990 <.text_51>: +1002c990: 10048818 .word 0x10048818 + +1002c994 <.text_52>: +1002c994: 10048820 .word 0x10048820 + +1002c998 <.text_53>: +1002c998: f8d4 00f4 ldr.w r0, [r4, #244] ; 0xf4 +1002c99c: 1c40 adds r0, r0, #1 +1002c99e: f8c4 00f4 str.w r0, [r4, #244] ; 0xf4 +1002c9a2: 4770 bx lr + +1002c9a4 <.text_54>: +1002c9a4: f104 01e8 add.w r1, r4, #232 ; 0xe8 +1002c9a8: 4658 mov r0, fp +1002c9aa: f7e3 bf59 b.w 10010860 + +1002c9ae : +1002c9ae: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +1002c9b2: 4604 mov r4, r0 +1002c9b4: 4616 mov r6, r2 +1002c9b6: f8d4 89b0 ldr.w r8, [r4, #2480] ; 0x9b0 +1002c9ba: 6837 ldr r7, [r6, #0] +1002c9bc: 460d mov r5, r1 +1002c9be: e010 b.n 1002c9e2 +1002c9c0: f899 2041 ldrb.w r2, [r9, #65] ; 0x41 +1002c9c4: ab00 add r3, sp, #0 +1002c9c6: 4629 mov r1, r5 +1002c9c8: 4620 mov r0, r4 +1002c9ca: f7ff fe72 bl 1002c6b2 +1002c9ce: 6941 ldr r1, [r0, #20] +1002c9d0: 1e49 subs r1, r1, #1 +1002c9d2: 6141 str r1, [r0, #20] +1002c9d4: f89d 0000 ldrb.w r0, [sp] +1002c9d8: eb08 00c0 add.w r0, r8, r0, lsl #3 +1002c9dc: 6841 ldr r1, [r0, #4] +1002c9de: 1e49 subs r1, r1, #1 +1002c9e0: 6041 str r1, [r0, #4] +1002c9e2: 4639 mov r1, r7 +1002c9e4: 4630 mov r0, r6 +1002c9e6: f7e3 ffb0 bl 1001094a +1002c9ea: b938 cbnz r0, 1002c9fc +1002c9ec: 46b9 mov r9, r7 +1002c9ee: 683f ldr r7, [r7, #0] +1002c9f0: 4649 mov r1, r9 +1002c9f2: 4620 mov r0, r4 +1002c9f4: f7ff ff13 bl 1002c81e +1002c9f8: 2800 cmp r0, #0 +1002c9fa: d1e1 bne.n 1002c9c0 +1002c9fc: e8bd 83f1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, pc} + +1002ca00 : +1002ca00: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +1002ca04: 4604 mov r4, r0 +1002ca06: 460f mov r7, r1 +1002ca08: f504 5188 add.w r1, r4, #4352 ; 0x1100 +1002ca0c: f101 0828 add.w r8, r1, #40 ; 0x28 +1002ca10: f604 1528 addw r5, r4, #2344 ; 0x928 +1002ca14: f107 0918 add.w r9, r7, #24 +1002ca18: f7f8 fc0e bl 10025238 +1002ca1c: 4606 mov r6, r0 +1002ca1e: a900 add r1, sp, #0 +1002ca20: 4628 mov r0, r5 +1002ca22: f7e3 ff77 bl 10010914 +1002ca26: f8d7 00f8 ldr.w r0, [r7, #248] ; 0xf8 +1002ca2a: f040 0004 orr.w r0, r0, #4 +1002ca2e: f8c7 00f8 str.w r0, [r7, #248] ; 0xf8 +1002ca32: 2101 movs r1, #1 +1002ca34: f8d7 20fc ldr.w r2, [r7, #252] ; 0xfc +1002ca38: f8b8 00c0 ldrh.w r0, [r8, #192] ; 0xc0 +1002ca3c: 4091 lsls r1, r2 +1002ca3e: 4308 orrs r0, r1 +1002ca40: f8a8 00c0 strh.w r0, [r8, #192] ; 0xc0 +1002ca44: f109 025c add.w r2, r9, #92 ; 0x5c +1002ca48: f000 f846 bl 1002cad8 <.text_57> +1002ca4c: f109 005c add.w r0, r9, #92 ; 0x5c +1002ca50: f7e3 ff7a bl 10010948 +1002ca54: b118 cbz r0, 1002ca5e +1002ca56: f109 0054 add.w r0, r9, #84 ; 0x54 +1002ca5a: f7e3 ff03 bl 10010864 +1002ca5e: f109 0244 add.w r2, r9, #68 ; 0x44 +1002ca62: f000 f839 bl 1002cad8 <.text_57> +1002ca66: f109 0044 add.w r0, r9, #68 ; 0x44 +1002ca6a: f7e3 ff6d bl 10010948 +1002ca6e: b118 cbz r0, 1002ca78 +1002ca70: f109 003c add.w r0, r9, #60 ; 0x3c +1002ca74: f7e3 fef6 bl 10010864 +1002ca78: f109 0214 add.w r2, r9, #20 +1002ca7c: f000 f82c bl 1002cad8 <.text_57> +1002ca80: f109 0014 add.w r0, r9, #20 +1002ca84: f7e3 ff60 bl 10010948 +1002ca88: b118 cbz r0, 1002ca92 +1002ca8a: f109 000c add.w r0, r9, #12 +1002ca8e: f7e3 fee9 bl 10010864 +1002ca92: f109 022c add.w r2, r9, #44 ; 0x2c +1002ca96: f000 f81f bl 1002cad8 <.text_57> +1002ca9a: f109 002c add.w r0, r9, #44 ; 0x2c +1002ca9e: f7e3 ff53 bl 10010948 +1002caa2: b118 cbz r0, 1002caac +1002caa4: f109 0024 add.w r0, r9, #36 ; 0x24 +1002caa8: f7e3 fedc bl 10010864 +1002caac: f106 0718 add.w r7, r6, #24 +1002cab0: f107 0214 add.w r2, r7, #20 +1002cab4: 4631 mov r1, r6 +1002cab6: f000 f810 bl 1002cada <.text_57+0x2> +1002caba: f107 0014 add.w r0, r7, #20 +1002cabe: f7e3 ff43 bl 10010948 +1002cac2: b118 cbz r0, 1002cacc +1002cac4: f107 000c add.w r0, r7, #12 +1002cac8: f7e3 fecc bl 10010864 +1002cacc: a900 add r1, sp, #0 +1002cace: 4628 mov r0, r5 +1002cad0: f7e3 ff21 bl 10010916 +1002cad4: e8bd 83f1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, pc} + +1002cad8 <.text_57>: +1002cad8: 4639 mov r1, r7 +1002cada: 4620 mov r0, r4 +1002cadc: e767 b.n 1002c9ae + +1002cade : +1002cade: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1002cae2: 4680 mov r8, r0 +1002cae4: f508 5088 add.w r0, r8, #4352 ; 0x1100 +1002cae8: 468a mov sl, r1 +1002caea: f100 0928 add.w r9, r0, #40 ; 0x28 +1002caee: 2700 movs r7, #0 +1002caf0: f000 f8dc bl 1002ccac <.text_61> +1002caf4: f10a 04e8 add.w r4, sl, #232 ; 0xe8 +1002caf8: f608 1b28 addw fp, r8, #2344 ; 0x928 +1002cafc: 6825 ldr r5, [r4, #0] +1002cafe: 2601 movs r6, #1 +1002cb00: e024 b.n 1002cb4c +1002cb02: f885 1065 strb.w r1, [r5, #101] ; 0x65 +1002cb06: 7106 strb r6, [r0, #4] +1002cb08: 7086 strb r6, [r0, #2] +1002cb0a: f000 f8ca bl 1002cca2 <.text_60> +1002cb0e: f000 f94f bl 1002cdb0 <.text_65> +1002cb12: f000 f951 bl 1002cdb8 <.text_66> +1002cb16: 2801 cmp r0, #1 +1002cb18: d003 beq.n 1002cb22 +1002cb1a: 4629 mov r1, r5 +1002cb1c: 4658 mov r0, fp +1002cb1e: f7ff fd7b bl 1002c618 +1002cb22: f000 f941 bl 1002cda8 <.text_64> +1002cb26: f000 f8c1 bl 1002ccac <.text_61> +1002cb2a: 6825 ldr r5, [r4, #0] +1002cb2c: f8da 00f4 ldr.w r0, [sl, #244] ; 0xf4 +1002cb30: b960 cbnz r0, 1002cb4c +1002cb32: f10a 01f4 add.w r1, sl, #244 ; 0xf4 +1002cb36: f109 00c0 add.w r0, r9, #192 ; 0xc0 +1002cb3a: 6889 ldr r1, [r1, #8] +1002cb3c: 8840 ldrh r0, [r0, #2] +1002cb3e: fa06 f101 lsl.w r1, r6, r1 +1002cb42: 4388 bics r0, r1 +1002cb44: f109 01c0 add.w r1, r9, #192 ; 0xc0 +1002cb48: 2701 movs r7, #1 +1002cb4a: 8048 strh r0, [r1, #2] +1002cb4c: f000 f937 bl 1002cdbe <.text_67> +1002cb50: bb90 cbnz r0, 1002cbb8 +1002cb52: f7ff fd5e bl 1002c612 <.text_38> +1002cb56: f895 0041 ldrb.w r0, [r5, #65] ; 0x41 +1002cb5a: 1e40 subs r0, r0, #1 +1002cb5c: 2801 cmp r0, #1 +1002cb5e: d906 bls.n 1002cb6e +1002cb60: 1ec0 subs r0, r0, #3 +1002cb62: 2801 cmp r0, #1 +1002cb64: d906 bls.n 1002cb74 +1002cb66: 1e80 subs r0, r0, #2 +1002cb68: 2801 cmp r0, #1 +1002cb6a: d907 bls.n 1002cb7c +1002cb6c: e00a b.n 1002cb84 +1002cb6e: f89a 0306 ldrb.w r0, [sl, #774] ; 0x306 +1002cb72: e00a b.n 1002cb8a +1002cb74: f20a 3006 addw r0, sl, #774 ; 0x306 +1002cb78: 7880 ldrb r0, [r0, #2] +1002cb7a: e006 b.n 1002cb8a +1002cb7c: f20a 3006 addw r0, sl, #774 ; 0x306 +1002cb80: 78c0 ldrb r0, [r0, #3] +1002cb82: e002 b.n 1002cb8a +1002cb84: f20a 3006 addw r0, sl, #774 ; 0x306 +1002cb88: 7840 ldrb r0, [r0, #1] +1002cb8a: f000 0102 and.w r1, r0, #2 +1002cb8e: f000 f882 bl 1002cc96 <.text_59> +1002cb92: bf18 it ne +1002cb94: 2001 movne r0, #1 +1002cb96: f885 0065 strb.w r0, [r5, #101] ; 0x65 +1002cb9a: 2900 cmp r1, #0 +1002cb9c: f105 0065 add.w r0, r5, #101 ; 0x65 +1002cba0: d0b2 beq.n 1002cb08 +1002cba2: f8da 130c ldr.w r1, [sl, #780] ; 0x30c +1002cba6: 1e49 subs r1, r1, #1 +1002cba8: f8ca 130c str.w r1, [sl, #780] ; 0x30c +1002cbac: d0a9 beq.n 1002cb02 +1002cbae: f885 6065 strb.w r6, [r5, #101] ; 0x65 +1002cbb2: 2100 movs r1, #0 +1002cbb4: 7101 strb r1, [r0, #4] +1002cbb6: e7a7 b.n 1002cb08 +1002cbb8: f10a 00f4 add.w r0, sl, #244 ; 0xf4 +1002cbbc: 6840 ldr r0, [r0, #4] +1002cbbe: 0741 lsls r1, r0, #29 +1002cbc0: d504 bpl.n 1002cbcc +1002cbc2: f10a 01f4 add.w r1, sl, #244 ; 0xf4 +1002cbc6: f080 0004 eor.w r0, r0, #4 +1002cbca: 6048 str r0, [r1, #4] +1002cbcc: f10a 01f4 add.w r1, sl, #244 ; 0xf4 +1002cbd0: 6889 ldr r1, [r1, #8] +1002cbd2: f8b9 00c0 ldrh.w r0, [r9, #192] ; 0xc0 +1002cbd6: fa06 f101 lsl.w r1, r6, r1 +1002cbda: 4388 bics r0, r1 +1002cbdc: f8a9 00c0 strh.w r0, [r9, #192] ; 0xc0 +1002cbe0: f000 f85f bl 1002cca2 <.text_60> +1002cbe4: 4640 mov r0, r8 +1002cbe6: f7f8 fb27 bl 10025238 +1002cbea: ea5f 0a00 movs.w sl, r0 +1002cbee: d050 beq.n 1002cc92 +1002cbf0: f8b9 00c0 ldrh.w r0, [r9, #192] ; 0xc0 +1002cbf4: f64f 71fe movw r1, #65534 ; 0xfffe +1002cbf8: 4208 tst r0, r1 +1002cbfa: d146 bne.n 1002cc8a +1002cbfc: f10a 06f0 add.w r6, sl, #240 ; 0xf0 +1002cc00: a900 add r1, sp, #0 +1002cc02: 4630 mov r0, r6 +1002cc04: f7e3 fe86 bl 10010914 +1002cc08: f10a 04e8 add.w r4, sl, #232 ; 0xe8 +1002cc0c: 6825 ldr r5, [r4, #0] +1002cc0e: e02d b.n 1002cc6c +1002cc10: f7ff fcff bl 1002c612 <.text_38> +1002cc14: f000 f83f bl 1002cc96 <.text_59> +1002cc18: a900 add r1, sp, #0 +1002cc1a: bf18 it ne +1002cc1c: 2001 movne r0, #1 +1002cc1e: f885 0065 strb.w r0, [r5, #101] ; 0x65 +1002cc22: 2001 movs r0, #1 +1002cc24: f885 0067 strb.w r0, [r5, #103] ; 0x67 +1002cc28: 4630 mov r0, r6 +1002cc2a: f7e3 fe74 bl 10010916 +1002cc2e: f000 f8bf bl 1002cdb0 <.text_65> +1002cc32: f000 f8c1 bl 1002cdb8 <.text_66> +1002cc36: 2801 cmp r0, #1 +1002cc38: d003 beq.n 1002cc42 +1002cc3a: 4629 mov r1, r5 +1002cc3c: 4658 mov r0, fp +1002cc3e: f7ff fceb bl 1002c618 +1002cc42: f000 f8b1 bl 1002cda8 <.text_64> +1002cc46: a900 add r1, sp, #0 +1002cc48: 4630 mov r0, r6 +1002cc4a: f7e3 fe63 bl 10010914 +1002cc4e: 6825 ldr r5, [r4, #0] +1002cc50: f8da 00f4 ldr.w r0, [sl, #244] ; 0xf4 +1002cc54: b950 cbnz r0, 1002cc6c +1002cc56: f109 00c0 add.w r0, r9, #192 ; 0xc0 +1002cc5a: f64f 71fe movw r1, #65534 ; 0xfffe +1002cc5e: 8840 ldrh r0, [r0, #2] +1002cc60: 4008 ands r0, r1 +1002cc62: f109 01c0 add.w r1, r9, #192 ; 0xc0 +1002cc66: f047 0702 orr.w r7, r7, #2 +1002cc6a: 8048 strh r0, [r1, #2] +1002cc6c: f000 f8a7 bl 1002cdbe <.text_67> +1002cc70: 2800 cmp r0, #0 +1002cc72: d0cd beq.n 1002cc10 +1002cc74: f8b9 00c0 ldrh.w r0, [r9, #192] ; 0xc0 +1002cc78: f64f 71fe movw r1, #65534 ; 0xfffe +1002cc7c: 4008 ands r0, r1 +1002cc7e: f8a9 00c0 strh.w r0, [r9, #192] ; 0xc0 +1002cc82: a900 add r1, sp, #0 +1002cc84: 4630 mov r0, r6 +1002cc86: f7e3 fe46 bl 10010916 +1002cc8a: b2ff uxtb r7, r7 +1002cc8c: b10f cbz r7, 1002cc92 +1002cc8e: f000 f885 bl 1002cd9c <.text_63> +1002cc92: e8bd 8ff1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1002cc96 <.text_59>: +1002cc96: f8da 00f4 ldr.w r0, [sl, #244] ; 0xf4 +1002cc9a: 1e40 subs r0, r0, #1 +1002cc9c: f8ca 00f4 str.w r0, [sl, #244] ; 0xf4 +1002cca0: 4770 bx lr + +1002cca2 <.text_60>: +1002cca2: a900 add r1, sp, #0 +1002cca4: f10a 00f0 add.w r0, sl, #240 ; 0xf0 +1002cca8: f7e3 be35 b.w 10010916 + +1002ccac <.text_61>: +1002ccac: a900 add r1, sp, #0 +1002ccae: f10a 00f0 add.w r0, sl, #240 ; 0xf0 +1002ccb2: f7e3 be2f b.w 10010914 + +1002ccb6 : +1002ccb6: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1002ccba: 4680 mov r8, r0 +1002ccbc: 4689 mov r9, r1 +1002ccbe: f508 5688 add.w r6, r8, #4352 ; 0x1100 +1002ccc2: f109 0bf0 add.w fp, r9, #240 ; 0xf0 +1002ccc6: 3628 adds r6, #40 ; 0x28 +1002ccc8: f000 f872 bl 1002cdb0 <.text_65> +1002cccc: f109 04e8 add.w r4, r9, #232 ; 0xe8 +1002ccd0: f608 1a28 addw sl, r8, #2344 ; 0x928 +1002ccd4: 6825 ldr r5, [r4, #0] +1002ccd6: f209 3706 addw r7, r9, #774 ; 0x306 +1002ccda: e030 b.n 1002cd3e +1002ccdc: f105 0265 add.w r2, r5, #101 ; 0x65 +1002cce0: 7111 strb r1, [r2, #4] +1002cce2: f885 0065 strb.w r0, [r5, #101] ; 0x65 +1002cce6: a900 add r1, sp, #0 +1002cce8: 2001 movs r0, #1 +1002ccea: 7090 strb r0, [r2, #2] +1002ccec: 4658 mov r0, fp +1002ccee: f7e3 fe12 bl 10010916 +1002ccf2: a900 add r1, sp, #0 +1002ccf4: 4650 mov r0, sl +1002ccf6: f7e3 fe0d bl 10010914 +1002ccfa: f000 f85d bl 1002cdb8 <.text_66> +1002ccfe: 2801 cmp r0, #1 +1002cd00: d003 beq.n 1002cd0a +1002cd02: 4629 mov r1, r5 +1002cd04: 4650 mov r0, sl +1002cd06: f7ff fc87 bl 1002c618 +1002cd0a: a900 add r1, sp, #0 +1002cd0c: 4650 mov r0, sl +1002cd0e: f7e3 fe02 bl 10010916 +1002cd12: f000 f84d bl 1002cdb0 <.text_65> +1002cd16: f8d9 030c ldr.w r0, [r9, #780] ; 0x30c +1002cd1a: 2800 cmp r0, #0 +1002cd1c: bf04 itt eq +1002cd1e: 7938 ldrbeq r0, [r7, #4] +1002cd20: 2800 cmpeq r0, #0 +1002cd22: d10b bne.n 1002cd3c +1002cd24: f109 02f4 add.w r2, r9, #244 ; 0xf4 +1002cd28: 2101 movs r1, #1 +1002cd2a: 6892 ldr r2, [r2, #8] +1002cd2c: f8b6 00c2 ldrh.w r0, [r6, #194] ; 0xc2 +1002cd30: 4091 lsls r1, r2 +1002cd32: 4388 bics r0, r1 +1002cd34: f8a6 00c2 strh.w r0, [r6, #194] ; 0xc2 +1002cd38: f000 f830 bl 1002cd9c <.text_63> +1002cd3c: 6825 ldr r5, [r4, #0] +1002cd3e: f000 f83e bl 1002cdbe <.text_67> +1002cd42: bb38 cbnz r0, 1002cd94 +1002cd44: f895 0041 ldrb.w r0, [r5, #65] ; 0x41 +1002cd48: 1e40 subs r0, r0, #1 +1002cd4a: 2801 cmp r0, #1 +1002cd4c: d906 bls.n 1002cd5c +1002cd4e: 1ec0 subs r0, r0, #3 +1002cd50: 2801 cmp r0, #1 +1002cd52: d906 bls.n 1002cd62 +1002cd54: 1e80 subs r0, r0, #2 +1002cd56: 2801 cmp r0, #1 +1002cd58: d905 bls.n 1002cd66 +1002cd5a: e006 b.n 1002cd6a +1002cd5c: f899 0306 ldrb.w r0, [r9, #774] ; 0x306 +1002cd60: e004 b.n 1002cd6c +1002cd62: 78b8 ldrb r0, [r7, #2] +1002cd64: e002 b.n 1002cd6c +1002cd66: 78f8 ldrb r0, [r7, #3] +1002cd68: e000 b.n 1002cd6c +1002cd6a: 7878 ldrb r0, [r7, #1] +1002cd6c: f010 0002 ands.w r0, r0, #2 +1002cd70: d0e5 beq.n 1002cd3e +1002cd72: f7ff fc4e bl 1002c612 <.text_38> +1002cd76: f8d9 00f4 ldr.w r0, [r9, #244] ; 0xf4 +1002cd7a: 1e40 subs r0, r0, #1 +1002cd7c: f8c9 00f4 str.w r0, [r9, #244] ; 0xf4 +1002cd80: f8d9 030c ldr.w r0, [r9, #780] ; 0x30c +1002cd84: 1e40 subs r0, r0, #1 +1002cd86: f8c9 030c str.w r0, [r9, #780] ; 0x30c +1002cd8a: bf1a itte ne +1002cd8c: 2001 movne r0, #1 +1002cd8e: 2100 movne r1, #0 +1002cd90: 2101 moveq r1, #1 +1002cd92: e7a3 b.n 1002ccdc +1002cd94: f000 f808 bl 1002cda8 <.text_64> +1002cd98: e8bd 8ff1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1002cd9c <.text_63>: +1002cd9c: 2300 movs r3, #0 +1002cd9e: 2200 movs r2, #0 +1002cda0: 2105 movs r1, #5 +1002cda2: 4640 mov r0, r8 +1002cda4: f7ec b9ac b.w 10019100 + +1002cda8 <.text_64>: +1002cda8: a900 add r1, sp, #0 +1002cdaa: 4658 mov r0, fp +1002cdac: f7e3 bdb3 b.w 10010916 + +1002cdb0 <.text_65>: +1002cdb0: a900 add r1, sp, #0 +1002cdb2: 4658 mov r0, fp +1002cdb4: f7e3 bdae b.w 10010914 + +1002cdb8 <.text_66>: +1002cdb8: 4629 mov r1, r5 +1002cdba: 4640 mov r0, r8 +1002cdbc: e473 b.n 1002c6a6 + +1002cdbe <.text_67>: +1002cdbe: 4629 mov r1, r5 +1002cdc0: 4620 mov r0, r4 +1002cdc2: f7e3 bdc2 b.w 1001094a + +1002cdc6 : +1002cdc6: b570 push {r4, r5, r6, lr} +1002cdc8: 4604 mov r4, r0 +1002cdca: f20f 00cc addw r0, pc, #204 ; 0xcc +1002cdce: f7e3 fedf bl 10010b90 +1002cdd2: f641 459c movw r5, #7324 ; 0x1c9c +1002cdd6: 192e adds r6, r5, r4 +1002cdd8: e002 b.n 1002cde0 +1002cdda: 4620 mov r0, r4 +1002cddc: f7f4 fe6d bl 10021aba +1002cde0: f504 50e8 add.w r0, r4, #7424 ; 0x1d00 +1002cde4: 300c adds r0, #12 +1002cde6: f7e3 fd61 bl 100108ac +1002cdea: b138 cbz r0, 1002cdfc +1002cdec: 6fb0 ldr r0, [r6, #120] ; 0x78 +1002cdee: b928 cbnz r0, 1002cdfc +1002cdf0: 5928 ldr r0, [r5, r4] +1002cdf2: 2801 cmp r0, #1 +1002cdf4: bf1c itt ne +1002cdf6: 6870 ldrne r0, [r6, #4] +1002cdf8: 2801 cmpne r0, #1 +1002cdfa: d1ee bne.n 1002cdda +1002cdfc: f504 50e8 add.w r0, r4, #7424 ; 0x1d00 +1002ce00: 3010 adds r0, #16 +1002ce02: f7e3 fd44 bl 1001088e +1002ce06: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +1002ce0a: f7e3 bec8 b.w 10010b9e + +1002ce0e : +1002ce0e: f7ea baf2 b.w 100173f6 + +1002ce12 : +1002ce12: f7ea bae8 b.w 100173e6 + +1002ce16 : +1002ce16: b5f8 push {r3, r4, r5, r6, r7, lr} +1002ce18: 4604 mov r4, r0 +1002ce1a: f604 1728 addw r7, r4, #2344 ; 0x928 +1002ce1e: 460e mov r6, r1 +1002ce20: 4638 mov r0, r7 +1002ce22: f7ff fbcc bl 1002c5be +1002ce26: 0005 movs r5, r0 +1002ce28: d00a beq.n 1002ce40 +1002ce2a: 6831 ldr r1, [r6, #0] +1002ce2c: f105 0208 add.w r2, r5, #8 +1002ce30: 4620 mov r0, r4 +1002ce32: f7fe fea3 bl 1002bb7c +1002ce36: b930 cbnz r0, 1002ce46 +1002ce38: 4629 mov r1, r5 +1002ce3a: 4638 mov r0, r7 +1002ce3c: f7ff fbec bl 1002c618 +1002ce40: f04f 30ff mov.w r0, #4294967295 +1002ce44: bdf2 pop {r1, r4, r5, r6, r7, pc} +1002ce46: 6830 ldr r0, [r6, #0] +1002ce48: 6768 str r0, [r5, #116] ; 0x74 +1002ce4a: f105 0608 add.w r6, r5, #8 +1002ce4e: 2110 movs r1, #16 +1002ce50: f896 7039 ldrb.w r7, [r6, #57] ; 0x39 +1002ce54: f104 000c add.w r0, r4, #12 +1002ce58: f7fe fce7 bl 1002b82a +1002ce5c: 2801 cmp r0, #1 +1002ce5e: d107 bne.n 1002ce70 +1002ce60: 88b0 ldrh r0, [r6, #4] +1002ce62: f648 018e movw r1, #34958 ; 0x888e +1002ce66: 4288 cmp r0, r1 +1002ce68: bf1a itte ne +1002ce6a: 78f0 ldrbne r0, [r6, #3] +1002ce6c: 2801 cmpne r0, #1 +1002ce6e: 2707 moveq r7, #7 +1002ce70: f886 7060 strb.w r7, [r6, #96] ; 0x60 +1002ce74: 4629 mov r1, r5 +1002ce76: 4620 mov r0, r4 +1002ce78: f7ff ffcb bl 1002ce12 +1002ce7c: b908 cbnz r0, 1002ce82 +1002ce7e: 2001 movs r0, #1 +1002ce80: bdf2 pop {r1, r4, r5, r6, r7, pc} +1002ce82: 2000 movs r0, #0 +1002ce84: bdf2 pop {r1, r4, r5, r6, r7, pc} + +1002ce86 : +1002ce86: 6802 ldr r2, [r0, #0] +1002ce88: b112 cbz r2, 1002ce90 +1002ce8a: 6091 str r1, [r2, #8] +1002ce8c: 2100 movs r1, #0 +1002ce8e: 6001 str r1, [r0, #0] +1002ce90: 4770 bx lr + +1002ce92 : +1002ce92: 2100 movs r1, #0 +1002ce94: e7f7 b.n 1002ce86 + ... + +1002ce98 : +1002ce98: 5452 5f57 4d58 5449 545f 5341 4c4b 5445 RTW_XMIT_TASKLET +1002cea8: 0000 0000 .... + +1002ceac : +1002ceac: f8df f000 ldr.w pc, [pc] ; 1002ceb0 +1002ceb0: 0001449d .word 0x0001449d + +1002ceb4 : +1002ceb4: 7800 ldrb r0, [r0, #0] +1002ceb6: 07c0 lsls r0, r0, #31 +1002ceb8: d501 bpl.n 1002cebe +1002ceba: 2001 movs r0, #1 +1002cebc: 4770 bx lr +1002cebe: 2000 movs r0, #0 +1002cec0: 4770 bx lr + +1002cec2 : +1002cec2: b108 cbz r0, 1002cec8 +1002cec4: f8d0 0084 ldr.w r0, [r0, #132] ; 0x84 +1002cec8: 4770 bx lr + +1002ceca : +1002ceca: b900 cbnz r0, 1002cece +1002cecc: 4770 bx lr +1002cece: b510 push {r4, lr} +1002ced0: f100 037c add.w r3, r0, #124 ; 0x7c +1002ced4: 689a ldr r2, [r3, #8] +1002ced6: 188a adds r2, r1, r2 +1002ced8: 609a str r2, [r3, #8] +1002ceda: 68dc ldr r4, [r3, #12] +1002cedc: 4294 cmp r4, r2 +1002cede: d203 bcs.n 1002cee8 +1002cee0: 1a50 subs r0, r2, r1 +1002cee2: 6098 str r0, [r3, #8] +1002cee4: 2000 movs r0, #0 +1002cee6: bd10 pop {r4, pc} +1002cee8: e00e b.n 1002cf08 <.text_6> + +1002ceea : +1002ceea: b900 cbnz r0, 1002ceee +1002ceec: 4770 bx lr +1002ceee: b510 push {r4, lr} +1002cef0: f100 037c add.w r3, r0, #124 ; 0x7c +1002cef4: 68da ldr r2, [r3, #12] +1002cef6: 1a52 subs r2, r2, r1 +1002cef8: 60da str r2, [r3, #12] +1002cefa: 689c ldr r4, [r3, #8] +1002cefc: 42a2 cmp r2, r4 +1002cefe: d203 bcs.n 1002cf08 <.text_6> +1002cf00: 1888 adds r0, r1, r2 +1002cf02: 60d8 str r0, [r3, #12] +1002cf04: 2000 movs r0, #0 +1002cf06: bd10 pop {r4, pc} + +1002cf08 <.text_6>: +1002cf08: 6fc3 ldr r3, [r0, #124] ; 0x7c +1002cf0a: 1a59 subs r1, r3, r1 +1002cf0c: 67c1 str r1, [r0, #124] ; 0x7c +1002cf0e: 4610 mov r0, r2 +1002cf10: bd10 pop {r4, pc} + +1002cf12 : +1002cf12: 6840 ldr r0, [r0, #4] +1002cf14: 4208 tst r0, r1 +1002cf16: d001 beq.n 1002cf1c +1002cf18: 2001 movs r0, #1 +1002cf1a: 4770 bx lr +1002cf1c: 2000 movs r0, #0 +1002cf1e: 4770 bx lr + +1002cf20 <_rtw_init_sta_recv_priv>: +1002cf20: b510 push {r4, lr} +1002cf22: 4604 mov r4, r0 +1002cf24: 2234 movs r2, #52 ; 0x34 +1002cf26: 2100 movs r1, #0 +1002cf28: f7e3 fc86 bl 10010838 +1002cf2c: 4620 mov r0, r4 +1002cf2e: f7e3 fd12 bl 10010956 +1002cf32: f104 0008 add.w r0, r4, #8 +1002cf36: e8bd 4010 ldmia.w sp!, {r4, lr} +1002cf3a: f7e3 bcfc b.w 10010936 + +1002cf3e <_rtw_init_recv_priv>: +1002cf3e: b5f8 push {r3, r4, r5, r6, r7, lr} +1002cf40: 4604 mov r4, r0 +1002cf42: 460d mov r5, r1 +1002cf44: f7e3 fd07 bl 10010956 +1002cf48: f504 60bf add.w r0, r4, #1528 ; 0x5f8 +1002cf4c: f7e3 fd03 bl 10010956 +1002cf50: 1d20 adds r0, r4, #4 +1002cf52: f7e3 fcf0 bl 10010936 +1002cf56: f104 0010 add.w r0, r4, #16 +1002cf5a: f7e3 fcec bl 10010936 +1002cf5e: f104 001c add.w r0, r4, #28 +1002cf62: f7e3 fce8 bl 10010936 +1002cf66: 6365 str r5, [r4, #52] ; 0x34 +1002cf68: 2002 movs r0, #2 +1002cf6a: 6320 str r0, [r4, #48] ; 0x30 +1002cf6c: 4629 mov r1, r5 +1002cf6e: 4620 mov r0, r4 +1002cf70: f005 ffa7 bl 10032ec2 +1002cf74: f44f 700c mov.w r0, #560 ; 0x230 +1002cf78: f7e3 fc2e bl 100107d8 +1002cf7c: 62a0 str r0, [r4, #40] ; 0x28 +1002cf7e: b1d0 cbz r0, 1002cfb6 <_rtw_init_recv_priv+0x78> +1002cf80: 30ff adds r0, #255 ; 0xff +1002cf82: 0a06 lsrs r6, r0, #8 +1002cf84: 0236 lsls r6, r6, #8 +1002cf86: 62e6 str r6, [r4, #44] ; 0x2c +1002cf88: 2702 movs r7, #2 +1002cf8a: 4630 mov r0, r6 +1002cf8c: f7e3 fc5e bl 1001084c +1002cf90: 1d21 adds r1, r4, #4 +1002cf92: 4630 mov r0, r6 +1002cf94: f7e3 fc64 bl 10010860 +1002cf98: 4631 mov r1, r6 +1002cf9a: 4628 mov r0, r5 +1002cf9c: f005 ff93 bl 10032ec6 +1002cfa0: 2000 movs r0, #0 +1002cfa2: 67f0 str r0, [r6, #124] ; 0x7c +1002cfa4: 6135 str r5, [r6, #16] +1002cfa6: 3698 adds r6, #152 ; 0x98 +1002cfa8: 1e7f subs r7, r7, #1 +1002cfaa: d1ee bne.n 1002cf8a <_rtw_init_recv_priv+0x4c> +1002cfac: 4628 mov r0, r5 +1002cfae: e8bd 40f2 ldmia.w sp!, {r1, r4, r5, r6, r7, lr} +1002cfb2: f7ea ba3c b.w 1001742e +1002cfb6: bdf2 pop {r1, r4, r5, r6, r7, pc} + +1002cfb8 : +1002cfb8: b510 push {r4, lr} +1002cfba: 4604 mov r4, r0 +1002cfbc: f7e3 fcd2 bl 10010964 +1002cfc0: f504 60bf add.w r0, r4, #1528 ; 0x5f8 +1002cfc4: f7e3 fcce bl 10010964 +1002cfc8: f104 000c add.w r0, r4, #12 +1002cfcc: f7e3 fcca bl 10010964 +1002cfd0: f104 0018 add.w r0, r4, #24 +1002cfd4: f7e3 fcc6 bl 10010964 +1002cfd8: f104 0024 add.w r0, r4, #36 ; 0x24 +1002cfdc: f7e3 fcc2 bl 10010964 +1002cfe0: f104 0080 add.w r0, r4, #128 ; 0x80 +1002cfe4: e8bd 4010 ldmia.w sp!, {r4, lr} +1002cfe8: f7e3 bcbc b.w 10010964 + +1002cfec <_rtw_free_recv_priv>: +1002cfec: b538 push {r3, r4, r5, lr} +1002cfee: 4604 mov r4, r0 +1002cff0: 6b65 ldr r5, [r4, #52] ; 0x34 +1002cff2: 4628 mov r0, r5 +1002cff4: f006 f8b0 bl 10033158 +1002cff8: 4628 mov r0, r5 +1002cffa: f000 f8c3 bl 1002d184 +1002cffe: 4620 mov r0, r4 +1002d000: f7ff ffda bl 1002cfb8 +1002d004: 4620 mov r0, r4 +1002d006: f005 ff63 bl 10032ed0 +1002d00a: 6aa0 ldr r0, [r4, #40] ; 0x28 +1002d00c: b118 cbz r0, 1002d016 <_rtw_free_recv_priv+0x2a> +1002d00e: f44f 710c mov.w r1, #560 ; 0x230 +1002d012: f7e3 fbf0 bl 100107f6 +1002d016: 4628 mov r0, r5 +1002d018: e8bd 4032 ldmia.w sp!, {r1, r4, r5, lr} +1002d01c: f7ea ba0f b.w 1001743e + +1002d020 <_rtw_alloc_recvframe>: +1002d020: b538 push {r3, r4, r5, lr} +1002d022: 4604 mov r4, r0 +1002d024: f7e3 fc90 bl 10010948 +1002d028: 2801 cmp r0, #1 +1002d02a: bf08 it eq +1002d02c: 2500 moveq r5, #0 +1002d02e: d00d beq.n 1002d04c <_rtw_alloc_recvframe+0x2c> +1002d030: 6825 ldr r5, [r4, #0] +1002d032: 4628 mov r0, r5 +1002d034: f7e3 fc16 bl 10010864 +1002d038: 6928 ldr r0, [r5, #16] +1002d03a: b138 cbz r0, 1002d04c <_rtw_alloc_recvframe+0x2c> +1002d03c: f500 6032 add.w r0, r0, #2848 ; 0xb20 +1002d040: 1d01 adds r1, r0, #4 +1002d042: 428c cmp r4, r1 +1002d044: d102 bne.n 1002d04c <_rtw_alloc_recvframe+0x2c> +1002d046: 6b01 ldr r1, [r0, #48] ; 0x30 +1002d048: 1e49 subs r1, r1, #1 +1002d04a: 6301 str r1, [r0, #48] ; 0x30 +1002d04c: 4628 mov r0, r5 +1002d04e: bd32 pop {r1, r4, r5, pc} + +1002d050 : +1002d050: b538 push {r3, r4, r5, lr} +1002d052: f000 f8c1 bl 1002d1d8 <.text_32> +1002d056: 4620 mov r0, r4 +1002d058: f7ff ffe2 bl 1002d020 <_rtw_alloc_recvframe> +1002d05c: 4605 mov r5, r0 +1002d05e: e0b4 b.n 1002d1ca <.text_31> + +1002d060 : +1002d060: b5f8 push {r3, r4, r5, r6, r7, lr} +1002d062: 0004 movs r4, r0 +1002d064: 460f mov r7, r1 +1002d066: 6925 ldr r5, [r4, #16] +1002d068: f505 6632 add.w r6, r5, #2848 ; 0xb20 +1002d06c: d035 beq.n 1002d0da +1002d06e: f641 5048 movw r0, #7496 ; 0x1d48 +1002d072: 1941 adds r1, r0, r5 +1002d074: 7a49 ldrb r1, [r1, #9] +1002d076: b121 cbz r1, 1002d082 +1002d078: 5945 ldr r5, [r0, r5] +1002d07a: 6125 str r5, [r4, #16] +1002d07c: f505 6632 add.w r6, r5, #2848 ; 0xb20 +1002d080: 1d37 adds r7, r6, #4 +1002d082: 68a0 ldr r0, [r4, #8] +1002d084: b120 cbz r0, 1002d090 +1002d086: 69c1 ldr r1, [r0, #28] +1002d088: f7e4 f9b3 bl 100113f2 +1002d08c: 2000 movs r0, #0 +1002d08e: 60a0 str r0, [r4, #8] +1002d090: a900 add r1, sp, #0 +1002d092: f107 0008 add.w r0, r7, #8 +1002d096: f7e3 fc3d bl 10010914 +1002d09a: f000 f893 bl 1002d1c4 <.text_29> +1002d09e: 2000 movs r0, #0 +1002d0a0: 67e0 str r0, [r4, #124] ; 0x7c +1002d0a2: f000 f84b bl 1002d13c <.text_18> +1002d0a6: b12d cbz r5, 1002d0b4 +1002d0a8: 1d30 adds r0, r6, #4 +1002d0aa: 4287 cmp r7, r0 +1002d0ac: d102 bne.n 1002d0b4 +1002d0ae: 6b30 ldr r0, [r6, #48] ; 0x30 +1002d0b0: 1c40 adds r0, r0, #1 +1002d0b2: 6330 str r0, [r6, #48] ; 0x30 +1002d0b4: 6b30 ldr r0, [r6, #48] ; 0x30 +1002d0b6: 2803 cmp r0, #3 +1002d0b8: d30a bcc.n 1002d0d0 +1002d0ba: a009 add r0, pc, #36 ; (adr r0, 1002d0e0 <.text_15>) +1002d0bc: f7df f921 bl 1000c302 +1002d0c0: 6b32 ldr r2, [r6, #48] ; 0x30 +1002d0c2: f20f 0120 addw r1, pc, #32 +1002d0c6: f20f 0030 addw r0, pc, #48 ; 0x30 +1002d0ca: 2302 movs r3, #2 +1002d0cc: f7df f919 bl 1000c302 +1002d0d0: a900 add r1, sp, #0 +1002d0d2: f107 0008 add.w r0, r7, #8 +1002d0d6: f7e3 fc1e bl 10010916 +1002d0da: 2001 movs r0, #1 +1002d0dc: bdf2 pop {r1, r4, r5, r6, r7, pc} + ... + +1002d0e0 <.text_15>: +1002d0e0: 00000d0a .word 0x00000d0a + +1002d0e4 : +1002d0e4: 5f777472 65657266 6365725f 61726676 rtw_free_recvfra +1002d0f4: 0000656d me.. + +1002d0f8 : +1002d0f8: 384c5452 41353931 6972445b 5d726576 RTL8195A[Driver] +1002d108: 7325203a 65726620 65725f65 72667663 : %s free_recvfr +1002d118: 5f656d61 3a746e63 3e206425 20642520 ame_cnt:%d > %d +1002d128: 72666572 68206565 65707061 2121206e refree happen !! +1002d138: 000a2121 !!.. + +1002d13c <.text_18>: +1002d13c: 4639 mov r1, r7 +1002d13e: 4620 mov r0, r4 +1002d140: f7e3 bb8e b.w 10010860 + +1002d144 <_rtw_enqueue_recvframe>: +1002d144: b5f8 push {r3, r4, r5, r6, r7, lr} +1002d146: 4604 mov r4, r0 +1002d148: 460d mov r5, r1 +1002d14a: 6926 ldr r6, [r4, #16] +1002d14c: f506 6732 add.w r7, r6, #2848 ; 0xb20 +1002d150: f7e3 fb88 bl 10010864 +1002d154: 4629 mov r1, r5 +1002d156: f7ff fff2 bl 1002d13e <.text_18+0x2> +1002d15a: b12e cbz r6, 1002d168 <_rtw_enqueue_recvframe+0x24> +1002d15c: 1d38 adds r0, r7, #4 +1002d15e: 4285 cmp r5, r0 +1002d160: d102 bne.n 1002d168 <_rtw_enqueue_recvframe+0x24> +1002d162: 6b38 ldr r0, [r7, #48] ; 0x30 +1002d164: 1c40 adds r0, r0, #1 +1002d166: 6338 str r0, [r7, #48] ; 0x30 +1002d168: 2001 movs r0, #1 +1002d16a: bdf2 pop {r1, r4, r5, r6, r7, pc} + +1002d16c : +1002d16c: b538 push {r3, r4, r5, lr} +1002d16e: f000 f81b bl 1002d1a8 <.text_24> +1002d172: 4629 mov r1, r5 +1002d174: 4620 mov r0, r4 +1002d176: f7ff ffe5 bl 1002d144 <_rtw_enqueue_recvframe> +1002d17a: 4604 mov r4, r0 +1002d17c: f000 f81d bl 1002d1ba <.text_28> +1002d180: 4620 mov r0, r4 +1002d182: bd32 pop {r1, r4, r5, pc} + +1002d184 : +1002d184: b570 push {r4, r5, r6, lr} +1002d186: 4604 mov r4, r0 +1002d188: 2500 movs r5, #0 +1002d18a: f604 363c addw r6, r4, #2876 ; 0xb3c +1002d18e: e004 b.n 1002d19a +1002d190: f604 3124 addw r1, r4, #2852 ; 0xb24 +1002d194: f7ff ff64 bl 1002d060 +1002d198: 1c6d adds r5, r5, #1 +1002d19a: 4630 mov r0, r6 +1002d19c: f7ff ff58 bl 1002d050 +1002d1a0: 2800 cmp r0, #0 +1002d1a2: d1f5 bne.n 1002d190 +1002d1a4: 4628 mov r0, r5 +1002d1a6: bd70 pop {r4, r5, r6, pc} + +1002d1a8 <.text_24>: +1002d1a8: 4604 mov r4, r0 +1002d1aa: 460d mov r5, r1 +1002d1ac: a900 add r1, sp, #0 +1002d1ae: f105 0008 add.w r0, r5, #8 +1002d1b2: f7e3 bbaf b.w 10010914 + +1002d1b6 : +1002d1b6: 2000 movs r0, #0 +1002d1b8: 4770 bx lr + +1002d1ba <.text_28>: +1002d1ba: a900 add r1, sp, #0 +1002d1bc: f105 0008 add.w r0, r5, #8 +1002d1c0: f7e3 bba9 b.w 10010916 + +1002d1c4 <.text_29>: +1002d1c4: 4620 mov r0, r4 +1002d1c6: f7e3 bb4d b.w 10010864 + +1002d1ca <.text_31>: +1002d1ca: a900 add r1, sp, #0 +1002d1cc: f104 0008 add.w r0, r4, #8 +1002d1d0: f7e3 fba1 bl 10010916 +1002d1d4: 4628 mov r0, r5 +1002d1d6: bd32 pop {r1, r4, r5, pc} + +1002d1d8 <.text_32>: +1002d1d8: 4604 mov r4, r0 +1002d1da: a900 add r1, sp, #0 +1002d1dc: f104 0008 add.w r0, r4, #8 +1002d1e0: f7e3 bb98 b.w 10010914 + +1002d1e4 : +1002d1e4: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +1002d1e8: 4689 mov r9, r1 +1002d1ea: f500 5188 add.w r1, r0, #4352 ; 0x1100 +1002d1ee: f109 071c add.w r7, r9, #28 +1002d1f2: f101 08f0 add.w r8, r1, #240 ; 0xf0 +1002d1f6: f500 5088 add.w r0, r0, #4352 ; 0x1100 +1002d1fa: b085 sub sp, #20 +1002d1fc: 2501 movs r5, #1 +1002d1fe: 2600 movs r6, #0 +1002d200: f107 0126 add.w r1, r7, #38 ; 0x26 +1002d204: f000 f924 bl 1002d450 <.text_39> +1002d208: 1d7c adds r4, r7, #5 +1002d20a: 4682 mov sl, r0 +1002d20c: 7ba0 ldrb r0, [r4, #14] +1002d20e: 2802 cmp r0, #2 +1002d210: d14a bne.n 1002d2a8 +1002d212: f1ba 0f00 cmp.w sl, #0 +1002d216: d043 beq.n 1002d2a0 +1002d218: f107 002c add.w r0, r7, #44 ; 0x2c +1002d21c: f7ff fe4a bl 1002ceb4 +1002d220: b148 cbz r0, 1002d236 +1002d222: f897 003c ldrb.w r0, [r7, #60] ; 0x3c +1002d226: f898 1354 ldrb.w r1, [r8, #852] ; 0x354 +1002d22a: eb08 1000 add.w r0, r8, r0, lsl #4 +1002d22e: 30e4 adds r0, #228 ; 0xe4 +1002d230: b919 cbnz r1, 1002d23a +1002d232: 2500 movs r5, #0 +1002d234: e038 b.n 1002d2a8 +1002d236: f50a 7094 add.w r0, sl, #296 ; 0x128 +1002d23a: 797b ldrb r3, [r7, #5] +1002d23c: f8d9 107c ldr.w r1, [r9, #124] ; 0x7c +1002d240: 7be2 ldrb r2, [r4, #15] +1002d242: f894 c010 ldrb.w ip, [r4, #16] +1002d246: 1ac9 subs r1, r1, r3 +1002d248: 1a89 subs r1, r1, r2 +1002d24a: eba1 010c sub.w r1, r1, ip +1002d24e: f1a1 0a08 sub.w sl, r1, #8 +1002d252: f8d9 1084 ldr.w r1, [r9, #132] ; 0x84 +1002d256: 185b adds r3, r3, r1 +1002d258: eb02 0b03 add.w fp, r2, r3 +1002d25c: 7922 ldrb r2, [r4, #4] +1002d25e: 9201 str r2, [sp, #4] +1002d260: 4653 mov r3, sl +1002d262: aa02 add r2, sp, #8 +1002d264: 9200 str r2, [sp, #0] +1002d266: 465a mov r2, fp +1002d268: f7ff fe20 bl 1002ceac +1002d26c: eb0a 000b add.w r0, sl, fp +1002d270: 2100 movs r1, #0 +1002d272: aa02 add r2, sp, #8 +1002d274: 5c0b ldrb r3, [r1, r0] +1002d276: 5c8a ldrb r2, [r1, r2] +1002d278: 429a cmp r2, r3 +1002d27a: bf18 it ne +1002d27c: 2601 movne r6, #1 +1002d27e: 1c49 adds r1, r1, #1 +1002d280: 2908 cmp r1, #8 +1002d282: dbf6 blt.n 1002d272 +1002d284: b10e cbz r6, 1002d28a +1002d286: 2500 movs r5, #0 +1002d288: e00a b.n 1002d2a0 +1002d28a: f508 7655 add.w r6, r8, #852 ; 0x354 +1002d28e: 78b0 ldrb r0, [r6, #2] +1002d290: b930 cbnz r0, 1002d2a0 +1002d292: f107 002c add.w r0, r7, #44 ; 0x2c +1002d296: f7ff fe0d bl 1002ceb4 +1002d29a: 2801 cmp r0, #1 +1002d29c: bf08 it eq +1002d29e: 70b0 strbeq r0, [r6, #2] +1002d2a0: 2108 movs r1, #8 +1002d2a2: 4648 mov r0, r9 +1002d2a4: f7ff fe21 bl 1002ceea +1002d2a8: 4628 mov r0, r5 +1002d2aa: b005 add sp, #20 +1002d2ac: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1002d2b0 : +1002d2b0: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +1002d2b4: 4680 mov r8, r0 +1002d2b6: 4689 mov r9, r1 +1002d2b8: f109 001c add.w r0, r9, #28 +1002d2bc: 1d44 adds r4, r0, #5 +1002d2be: f508 5188 add.w r1, r8, #4352 ; 0x1100 +1002d2c2: 7ba2 ldrb r2, [r4, #14] +1002d2c4: 31f0 adds r1, #240 ; 0xf0 +1002d2c6: 2701 movs r7, #1 +1002d2c8: 2a00 cmp r2, #0 +1002d2ca: 464e mov r6, r9 +1002d2cc: d039 beq.n 1002d342 +1002d2ce: f8d9 3084 ldr.w r3, [r9, #132] ; 0x84 +1002d2d2: 7945 ldrb r5, [r0, #5] +1002d2d4: 442b add r3, r5 +1002d2d6: 78db ldrb r3, [r3, #3] +1002d2d8: 099b lsrs r3, r3, #6 +1002d2da: 2b05 cmp r3, #5 +1002d2dc: f880 303c strb.w r3, [r0, #60] ; 0x3c +1002d2e0: db06 blt.n 1002d2f0 +1002d2e2: 2a01 cmp r2, #1 +1002d2e4: bf16 itet ne +1002d2e6: 2a05 cmpne r2, #5 +1002d2e8: 688b ldreq r3, [r1, #8] +1002d2ea: 6e0b ldrne r3, [r1, #96] ; 0x60 +1002d2ec: f880 303c strb.w r3, [r0, #60] ; 0x3c +1002d2f0: f501 7557 add.w r5, r1, #860 ; 0x35c +1002d2f4: 7b63 ldrb r3, [r4, #13] +1002d2f6: 2b00 cmp r3, #0 +1002d2f8: bf1c itt ne +1002d2fa: f8d1 c35c ldrne.w ip, [r1, #860] ; 0x35c +1002d2fe: f1bc 0f01 cmpne.w ip, #1 +1002d302: d126 bne.n 1002d352 +1002d304: 302c adds r0, #44 ; 0x2c +1002d306: f7ff fdd5 bl 1002ceb4 +1002d30a: b900 cbnz r0, 1002d30e +1002d30c: 6068 str r0, [r5, #4] +1002d30e: 7ba0 ldrb r0, [r4, #14] +1002d310: 2801 cmp r0, #1 +1002d312: d005 beq.n 1002d320 +1002d314: 2802 cmp r0, #2 +1002d316: d008 beq.n 1002d32a +1002d318: 2804 cmp r0, #4 +1002d31a: d015 beq.n 1002d348 +1002d31c: 2805 cmp r0, #5 +1002d31e: d109 bne.n 1002d334 +1002d320: 4649 mov r1, r9 +1002d322: 4640 mov r0, r8 +1002d324: f000 ff4c bl 1002e1c0 +1002d328: e00b b.n 1002d342 +1002d32a: 4649 mov r1, r9 +1002d32c: 4640 mov r0, r8 +1002d32e: f000 ffa5 bl 1002e27c +1002d332: 4607 mov r7, r0 +1002d334: b92f cbnz r7, 1002d342 +1002d336: f608 3124 addw r1, r8, #2852 ; 0xb24 +1002d33a: 4630 mov r0, r6 +1002d33c: f7ff fe90 bl 1002d060 +1002d340: 2600 movs r6, #0 +1002d342: 4630 mov r0, r6 +1002d344: e8bd 83f2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, pc} +1002d348: 4649 mov r1, r9 +1002d34a: 4640 mov r0, r8 +1002d34c: f001 f817 bl 1002e37e +1002d350: e7ef b.n 1002d332 +1002d352: 2b01 cmp r3, #1 +1002d354: d1f5 bne.n 1002d342 +1002d356: f891 0355 ldrb.w r0, [r1, #853] ; 0x355 +1002d35a: 2801 cmp r0, #1 +1002d35c: bf0c ite eq +1002d35e: 6068 streq r0, [r5, #4] +1002d360: 2a02 cmpne r2, #2 +1002d362: d0ee beq.n 1002d342 +1002d364: 606f str r7, [r5, #4] +1002d366: e7ec b.n 1002d342 + +1002d368 : +1002d368: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1002d36c: b082 sub sp, #8 +1002d36e: 4604 mov r4, r0 +1002d370: 2000 movs r0, #0 +1002d372: f8ad 0000 strh.w r0, [sp] +1002d376: 460d mov r5, r1 +1002d378: f241 10f0 movw r0, #4592 ; 0x11f0 +1002d37c: 5906 ldr r6, [r0, r4] +1002d37e: 4628 mov r0, r5 +1002d380: f7ff fd9f bl 1002cec2 +1002d384: 4680 mov r8, r0 +1002d386: f504 5088 add.w r0, r4, #4352 ; 0x1100 +1002d38a: f105 0142 add.w r1, r5, #66 ; 0x42 +1002d38e: f000 f85f bl 1002d450 <.text_39> +1002d392: 4607 mov r7, r0 +1002d394: f895 0021 ldrb.w r0, [r5, #33] ; 0x21 +1002d398: f895 1030 ldrb.w r1, [r5, #48] ; 0x30 +1002d39c: 4440 add r0, r8 +1002d39e: 1808 adds r0, r1, r0 +1002d3a0: 1d81 adds r1, r0, #6 +1002d3a2: f000 f81b bl 1002d3dc <.text_36> +1002d3a6: f000 fd73 bl 1002de90 <.text_58> +1002d3aa: 2e02 cmp r6, #2 +1002d3ac: f8ad 0000 strh.w r0, [sp] +1002d3b0: d111 bne.n 1002d3d6 +1002d3b2: 2f00 cmp r7, #0 +1002d3b4: bf1c itt ne +1002d3b6: f8d7 0110 ldrne.w r0, [r7, #272] ; 0x110 +1002d3ba: 2800 cmpne r0, #0 +1002d3bc: bf1e ittt ne +1002d3be: f8bd 0000 ldrhne.w r0, [sp] +1002d3c2: f648 018e movwne r1, #34958 ; 0x888e +1002d3c6: 4288 cmpne r0, r1 +1002d3c8: d005 beq.n 1002d3d6 +1002d3ca: f604 3124 addw r1, r4, #2852 ; 0xb24 +1002d3ce: 4628 mov r0, r5 +1002d3d0: f7ff fe46 bl 1002d060 +1002d3d4: 2500 movs r5, #0 +1002d3d6: 4628 mov r0, r5 +1002d3d8: e8bd 81f6 ldmia.w sp!, {r1, r2, r4, r5, r6, r7, r8, pc} + +1002d3dc <.text_36>: +1002d3dc: 2202 movs r2, #2 +1002d3de: a800 add r0, sp, #0 +1002d3e0: f7e3 ba15 b.w 1001080e + +1002d3e4 : +1002d3e4: f890 1025 ldrb.w r1, [r0, #37] ; 0x25 +1002d3e8: 8d03 ldrh r3, [r0, #40] ; 0x28 +1002d3ea: f890 002a ldrb.w r0, [r0, #42] ; 0x2a +1002d3ee: f000 000f and.w r0, r0, #15 +1002d3f2: 2910 cmp r1, #16 +1002d3f4: ea40 1003 orr.w r0, r0, r3, lsl #4 +1002d3f8: da04 bge.n 1002d404 +1002d3fa: f832 3011 ldrh.w r3, [r2, r1, lsl #1] +1002d3fe: b280 uxth r0, r0 +1002d400: 4298 cmp r0, r3 +1002d402: d101 bne.n 1002d408 +1002d404: 2000 movs r0, #0 +1002d406: 4770 bx lr +1002d408: f822 0011 strh.w r0, [r2, r1, lsl #1] +1002d40c: 2001 movs r0, #1 +1002d40e: 4770 bx lr + +1002d410 : +1002d410: b538 push {r3, r4, r5, lr} +1002d412: 4604 mov r4, r0 +1002d414: f8d1 5084 ldr.w r5, [r1, #132] ; 0x84 +1002d418: f504 5088 add.w r0, r4, #4352 ; 0x1100 +1002d41c: 313c adds r1, #60 ; 0x3c +1002d41e: f000 f817 bl 1002d450 <.text_39> +1002d422: b1a0 cbz r0, 1002d44e +1002d424: 882a ldrh r2, [r5, #0] +1002d426: f8d0 10f8 ldr.w r1, [r0, #248] ; 0xf8 +1002d42a: 04d2 lsls r2, r2, #19 +1002d42c: d507 bpl.n 1002d43e +1002d42e: 0749 lsls r1, r1, #29 +1002d430: d40d bmi.n 1002d44e +1002d432: 4601 mov r1, r0 +1002d434: 4620 mov r0, r4 +1002d436: e8bd 4034 ldmia.w sp!, {r2, r4, r5, lr} +1002d43a: f7ff bae1 b.w 1002ca00 +1002d43e: 0749 lsls r1, r1, #29 +1002d440: d505 bpl.n 1002d44e +1002d442: 4601 mov r1, r0 +1002d444: 4620 mov r0, r4 +1002d446: e8bd 4034 ldmia.w sp!, {r2, r4, r5, lr} +1002d44a: f7ff bb48 b.w 1002cade +1002d44e: bd31 pop {r0, r4, r5, pc} + +1002d450 <.text_39>: +1002d450: 3028 adds r0, #40 ; 0x28 +1002d452: f7f7 beab b.w 100251ac + +1002d456 : +1002d456: b538 push {r3, r4, r5, lr} +1002d458: 4604 mov r4, r0 +1002d45a: f101 051c add.w r5, r1, #28 +1002d45e: f504 5088 add.w r0, r4, #4352 ; 0x1100 +1002d462: f105 0120 add.w r1, r5, #32 +1002d466: f7ff fff3 bl 1002d450 <.text_39> +1002d46a: 2800 cmp r0, #0 +1002d46c: bf1c itt ne +1002d46e: f8d0 1104 ldrne.w r1, [r0, #260] ; 0x104 +1002d472: 2900 cmpne r1, #0 +1002d474: bf1e ittt ne +1002d476: f890 1304 ldrbne.w r1, [r0, #772] ; 0x304 +1002d47a: 220f movne r2, #15 +1002d47c: 4211 tstne r1, r2 +1002d47e: d029 beq.n 1002d4d4 +1002d480: f890 10f8 ldrb.w r1, [r0, #248] ; 0xf8 +1002d484: 0749 lsls r1, r1, #29 +1002d486: d525 bpl.n 1002d4d4 +1002d488: 7a6a ldrb r2, [r5, #9] +1002d48a: 1e53 subs r3, r2, #1 +1002d48c: 2b01 cmp r3, #1 +1002d48e: f500 7141 add.w r1, r0, #772 ; 0x304 +1002d492: d906 bls.n 1002d4a2 +1002d494: 1edb subs r3, r3, #3 +1002d496: 2b01 cmp r3, #1 +1002d498: d905 bls.n 1002d4a6 +1002d49a: 1e9b subs r3, r3, #2 +1002d49c: 2b01 cmp r3, #1 +1002d49e: d904 bls.n 1002d4aa +1002d4a0: e005 b.n 1002d4ae +1002d4a2: 788b ldrb r3, [r1, #2] +1002d4a4: e004 b.n 1002d4b0 +1002d4a6: 790b ldrb r3, [r1, #4] +1002d4a8: e002 b.n 1002d4b0 +1002d4aa: 794b ldrb r3, [r1, #5] +1002d4ac: e000 b.n 1002d4b0 +1002d4ae: 78cb ldrb r3, [r1, #3] +1002d4b0: f013 0302 ands.w r3, r3, #2 +1002d4b4: d00e beq.n 1002d4d4 +1002d4b6: 6889 ldr r1, [r1, #8] +1002d4b8: b129 cbz r1, 1002d4c6 +1002d4ba: 4601 mov r1, r0 +1002d4bc: 4620 mov r0, r4 +1002d4be: e8bd 4034 ldmia.w sp!, {r2, r4, r5, lr} +1002d4c2: f7ff bbf8 b.w 1002ccb6 +1002d4c6: f500 7184 add.w r1, r0, #264 ; 0x108 +1002d4ca: 4620 mov r0, r4 +1002d4cc: e8bd 4038 ldmia.w sp!, {r3, r4, r5, lr} +1002d4d0: f7ee bd87 b.w 1001bfe2 +1002d4d4: bd31 pop {r0, r4, r5, pc} + +1002d4d6 : +1002d4d6: b5f8 push {r3, r4, r5, r6, r7, lr} +1002d4d8: 4607 mov r7, r0 +1002d4da: f507 6332 add.w r3, r7, #2848 ; 0xb20 +1002d4de: 460d mov r5, r1 +1002d4e0: e9d3 0110 ldrd r0, r1, [r3, #64] ; 0x40 +1002d4e4: 6fec ldr r4, [r5, #124] ; 0x7c +1002d4e6: 1900 adds r0, r0, r4 +1002d4e8: eb41 71e4 adc.w r1, r1, r4, asr #31 +1002d4ec: e9c3 0110 strd r0, r1, [r3, #64] ; 0x40 +1002d4f0: 4616 mov r6, r2 +1002d4f2: f8d7 0480 ldr.w r0, [r7, #1152] ; 0x480 +1002d4f6: 1c40 adds r0, r0, #1 +1002d4f8: f105 021c add.w r2, r5, #28 +1002d4fc: f8c7 0480 str.w r0, [r7, #1152] ; 0x480 +1002d500: 7e90 ldrb r0, [r2, #26] +1002d502: 28ff cmp r0, #255 ; 0xff +1002d504: bf04 itt eq +1002d506: 7ed0 ldrbeq r0, [r2, #27] +1002d508: 28ff cmpeq r0, #255 ; 0xff +1002d50a: d10b bne.n 1002d524 +1002d50c: 7f10 ldrb r0, [r2, #28] +1002d50e: 28ff cmp r0, #255 ; 0xff +1002d510: bf04 itt eq +1002d512: 7f50 ldrbeq r0, [r2, #29] +1002d514: 28ff cmpeq r0, #255 ; 0xff +1002d516: d105 bne.n 1002d524 +1002d518: 7f90 ldrb r0, [r2, #30] +1002d51a: 28ff cmp r0, #255 ; 0xff +1002d51c: bf04 itt eq +1002d51e: 7fd0 ldrbeq r0, [r2, #31] +1002d520: 28ff cmpeq r0, #255 ; 0xff +1002d522: d009 beq.n 1002d538 +1002d524: f102 001a add.w r0, r2, #26 +1002d528: f7ff fcc4 bl 1002ceb4 +1002d52c: b920 cbnz r0, 1002d538 +1002d52e: f507 6090 add.w r0, r7, #1152 ; 0x480 +1002d532: 6841 ldr r1, [r0, #4] +1002d534: 1c49 adds r1, r1, #1 +1002d536: 6041 str r1, [r0, #4] +1002d538: 2e00 cmp r6, #0 +1002d53a: bf04 itt eq +1002d53c: f8d5 6094 ldreq.w r6, [r5, #148] ; 0x94 +1002d540: 2e00 cmpeq r6, #0 +1002d542: d00e beq.n 1002d562 +1002d544: f506 70c0 add.w r0, r6, #384 ; 0x180 +1002d548: e9d0 2304 ldrd r2, r3, [r0, #16] +1002d54c: f000 fc05 bl 1002dd5a <.text_56> +1002d550: e9c0 2304 strd r2, r3, [r0, #16] +1002d554: e9d0 230c ldrd r2, r3, [r0, #48] ; 0x30 +1002d558: 1912 adds r2, r2, r4 +1002d55a: eb43 73e4 adc.w r3, r3, r4, asr #31 +1002d55e: e9c0 230c strd r2, r3, [r0, #48] ; 0x30 +1002d562: bdf1 pop {r0, r4, r5, r6, r7, pc} + +1002d564 : +1002d564: e92d 4ffe stmdb sp!, {r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1002d568: 4680 mov r8, r0 +1002d56a: f8d1 0084 ldr.w r0, [r1, #132] ; 0x84 +1002d56e: 9002 str r0, [sp, #8] +1002d570: f101 0a1c add.w sl, r1, #28 +1002d574: f508 5088 add.w r0, r8, #4352 ; 0x1100 +1002d578: 3028 adds r0, #40 ; 0x28 +1002d57a: 9001 str r0, [sp, #4] +1002d57c: f108 040c add.w r4, r8, #12 +1002d580: f508 50c8 add.w r0, r8, #6400 ; 0x1900 +1002d584: 3095 adds r0, #149 ; 0x95 +1002d586: 9000 str r0, [sp, #0] +1002d588: 4615 mov r5, r2 +1002d58a: 2601 movs r6, #1 +1002d58c: f104 0990 add.w r9, r4, #144 ; 0x90 +1002d590: f04f 0b00 mov.w fp, #0 +1002d594: f10a 001a add.w r0, sl, #26 +1002d598: f7ff fc8c bl 1002ceb4 +1002d59c: 4607 mov r7, r0 +1002d59e: 2120 movs r1, #32 +1002d5a0: f000 f895 bl 1002d6ce <.text_44> +1002d5a4: 2801 cmp r0, #1 +1002d5a6: d004 beq.n 1002d5b2 +1002d5a8: 2140 movs r1, #64 ; 0x40 +1002d5aa: f000 f890 bl 1002d6ce <.text_44> +1002d5ae: 2801 cmp r0, #1 +1002d5b0: d125 bne.n 1002d5fe +1002d5b2: 9800 ldr r0, [sp, #0] +1002d5b4: 2206 movs r2, #6 +1002d5b6: f10a 0120 add.w r1, sl, #32 +1002d5ba: f7e3 f932 bl 10010822 +1002d5be: 2800 cmp r0, #0 +1002d5c0: d147 bne.n 1002d652 +1002d5c2: 9800 ldr r0, [sp, #0] +1002d5c4: 2206 movs r2, #6 +1002d5c6: f10a 011a add.w r1, sl, #26 +1002d5ca: f7e3 f92a bl 10010822 +1002d5ce: 4338 orrs r0, r7 +1002d5d0: d03f beq.n 1002d652 +1002d5d2: f20f 244c addw r4, pc, #588 ; 0x24c +1002d5d6: 2206 movs r2, #6 +1002d5d8: 4621 mov r1, r4 +1002d5da: f000 f874 bl 1002d6c6 <.text_43> +1002d5de: 2800 cmp r0, #0 +1002d5e0: d137 bne.n 1002d652 +1002d5e2: 2206 movs r2, #6 +1002d5e4: 4621 mov r1, r4 +1002d5e6: 4648 mov r0, r9 +1002d5e8: f7e3 f91b bl 10010822 +1002d5ec: 2800 cmp r0, #0 +1002d5ee: d130 bne.n 1002d652 +1002d5f0: 2206 movs r2, #6 +1002d5f2: 4649 mov r1, r9 +1002d5f4: f000 f867 bl 1002d6c6 <.text_43> +1002d5f8: 2800 cmp r0, #0 +1002d5fa: d12f bne.n 1002d65c +1002d5fc: e029 b.n 1002d652 +1002d5fe: 2108 movs r1, #8 +1002d600: f000 f865 bl 1002d6ce <.text_44> +1002d604: 2801 cmp r0, #1 +1002d606: d108 bne.n 1002d61a +1002d608: 2206 movs r2, #6 +1002d60a: f10a 0120 add.w r1, sl, #32 +1002d60e: f000 f85a bl 1002d6c6 <.text_43> +1002d612: b310 cbz r0, 1002d65a +1002d614: f10a 0b32 add.w fp, sl, #50 ; 0x32 +1002d618: e04f b.n 1002d6ba +1002d61a: 2110 movs r1, #16 +1002d61c: f000 f857 bl 1002d6ce <.text_44> +1002d620: 2801 cmp r0, #1 +1002d622: d11e bne.n 1002d662 +1002d624: b137 cbz r7, 1002d634 +1002d626: f10a 0032 add.w r0, sl, #50 ; 0x32 +1002d62a: f7ff fc43 bl 1002ceb4 +1002d62e: 2800 cmp r0, #0 +1002d630: d145 bne.n 1002d6be +1002d632: e00e b.n 1002d652 +1002d634: 2206 movs r2, #6 +1002d636: f10a 011a add.w r1, sl, #26 +1002d63a: f000 f844 bl 1002d6c6 <.text_43> +1002d63e: b160 cbz r0, 1002d65a +1002d640: f10a 0b20 add.w fp, sl, #32 +1002d644: 9801 ldr r0, [sp, #4] +1002d646: 4659 mov r1, fp +1002d648: f7f7 fdb0 bl 100251ac +1002d64c: 6028 str r0, [r5, #0] +1002d64e: 6828 ldr r0, [r5, #0] +1002d650: b900 cbnz r0, 1002d654 +1002d652: 2600 movs r6, #0 +1002d654: 4630 mov r0, r6 +1002d656: e8bd 8ffe ldmia.w sp!, {r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, pc} +1002d65a: e7fa b.n 1002d652 +1002d65c: f10a 0b20 add.w fp, sl, #32 +1002d660: e02b b.n 1002d6ba +1002d662: f44f 3180 mov.w r1, #65536 ; 0x10000 +1002d666: f000 f832 bl 1002d6ce <.text_44> +1002d66a: 2801 cmp r0, #1 +1002d66c: d124 bne.n 1002d6b8 +1002d66e: 9c02 ldr r4, [sp, #8] +1002d670: 2206 movs r2, #6 +1002d672: 1d21 adds r1, r4, #4 +1002d674: f10a 001a add.w r0, sl, #26 +1002d678: f7e3 f8c9 bl 1001080e +1002d67c: 2206 movs r2, #6 +1002d67e: f104 010a add.w r1, r4, #10 +1002d682: f10a 0020 add.w r0, sl, #32 +1002d686: f7e3 f8c2 bl 1001080e +1002d68a: 2206 movs r2, #6 +1002d68c: f104 0110 add.w r1, r4, #16 +1002d690: f10a 0032 add.w r0, sl, #50 ; 0x32 +1002d694: f7e3 f8bb bl 1001080e +1002d698: 2206 movs r2, #6 +1002d69a: f10a 011a add.w r1, sl, #26 +1002d69e: f10a 002c add.w r0, sl, #44 ; 0x2c +1002d6a2: f7e3 f8b4 bl 1001080e +1002d6a6: 2206 movs r2, #6 +1002d6a8: f10a 0120 add.w r1, sl, #32 +1002d6ac: f10a 0026 add.w r0, sl, #38 ; 0x26 +1002d6b0: f7e3 f8ad bl 1001080e +1002d6b4: 46cb mov fp, r9 +1002d6b6: e000 b.n 1002d6ba +1002d6b8: 2600 movs r6, #0 +1002d6ba: 2f00 cmp r7, #0 +1002d6bc: d0c2 beq.n 1002d644 +1002d6be: 4640 mov r0, r8 +1002d6c0: f7f7 fdba bl 10025238 +1002d6c4: e7c2 b.n 1002d64c + +1002d6c6 <.text_43>: +1002d6c6: f10a 0032 add.w r0, sl, #50 ; 0x32 +1002d6ca: f7e3 b8aa b.w 10010822 + +1002d6ce <.text_44>: +1002d6ce: 4620 mov r0, r4 +1002d6d0: f7ff bc1f b.w 1002cf12 + +1002d6d4 : +1002d6d4: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +1002d6d8: b083 sub sp, #12 +1002d6da: 4680 mov r8, r0 +1002d6dc: f8d1 6084 ldr.w r6, [r1, #132] ; 0x84 +1002d6e0: f508 5088 add.w r0, r8, #4352 ; 0x1100 +1002d6e4: 3028 adds r0, #40 ; 0x28 +1002d6e6: 9001 str r0, [sp, #4] +1002d6e8: f101 0b1c add.w fp, r1, #28 +1002d6ec: f508 50c8 add.w r0, r8, #6400 ; 0x1900 +1002d6f0: 3095 adds r0, #149 ; 0x95 +1002d6f2: 9000 str r0, [sp, #0] +1002d6f4: f108 090c add.w r9, r8, #12 +1002d6f8: 4615 mov r5, r2 +1002d6fa: 2401 movs r4, #1 +1002d6fc: f109 0a90 add.w sl, r9, #144 ; 0x90 +1002d700: f10b 001a add.w r0, fp, #26 +1002d704: f7ff fbd6 bl 1002ceb4 +1002d708: 4607 mov r7, r0 +1002d70a: 2108 movs r1, #8 +1002d70c: f000 f88d bl 1002d82a <.text_47+0x2> +1002d710: 2801 cmp r0, #1 +1002d712: d149 bne.n 1002d7a8 +1002d714: f000 f888 bl 1002d828 <.text_47> +1002d718: 2801 cmp r0, #1 +1002d71a: d004 beq.n 1002d726 +1002d71c: 2180 movs r1, #128 ; 0x80 +1002d71e: f000 f884 bl 1002d82a <.text_47+0x2> +1002d722: 2801 cmp r0, #1 +1002d724: d140 bne.n 1002d7a8 +1002d726: 8830 ldrh r0, [r6, #0] +1002d728: f000 02fc and.w r2, r0, #252 ; 0xfc +1002d72c: 2a48 cmp r2, #72 ; 0x48 +1002d72e: d071 beq.n 1002d814 +1002d730: f000 0188 and.w r1, r0, #136 ; 0x88 +1002d734: 2988 cmp r1, #136 ; 0x88 +1002d736: d102 bne.n 1002d73e +1002d738: 2170 movs r1, #112 ; 0x70 +1002d73a: 4208 tst r0, r1 +1002d73c: d16a bne.n 1002d814 +1002d73e: 9800 ldr r0, [sp, #0] +1002d740: 2206 movs r2, #6 +1002d742: f10b 0120 add.w r1, fp, #32 +1002d746: f7e3 f86c bl 10010822 +1002d74a: 2800 cmp r0, #0 +1002d74c: d162 bne.n 1002d814 +1002d74e: 9800 ldr r0, [sp, #0] +1002d750: 2206 movs r2, #6 +1002d752: f10b 011a add.w r1, fp, #26 +1002d756: f7e3 f864 bl 10010822 +1002d75a: 4338 orrs r0, r7 +1002d75c: d05a beq.n 1002d814 +1002d75e: f20f 06c0 addw r6, pc, #192 ; 0xc0 +1002d762: 2206 movs r2, #6 +1002d764: 4631 mov r1, r6 +1002d766: f10b 0032 add.w r0, fp, #50 ; 0x32 +1002d76a: f7e3 f85a bl 10010822 +1002d76e: 2800 cmp r0, #0 +1002d770: d150 bne.n 1002d814 +1002d772: 2206 movs r2, #6 +1002d774: 4631 mov r1, r6 +1002d776: 4650 mov r0, sl +1002d778: f7e3 f853 bl 10010822 +1002d77c: 2800 cmp r0, #0 +1002d77e: d149 bne.n 1002d814 +1002d780: 2206 movs r2, #6 +1002d782: 4651 mov r1, sl +1002d784: f10b 0032 add.w r0, fp, #50 ; 0x32 +1002d788: f7e3 f84b bl 10010822 +1002d78c: 2800 cmp r0, #0 +1002d78e: d041 beq.n 1002d814 +1002d790: b11f cbz r7, 1002d79a +1002d792: 4640 mov r0, r8 +1002d794: f7f7 fd50 bl 10025238 +1002d798: e001 b.n 1002d79e +1002d79a: f000 f849 bl 1002d830 <.text_48> +1002d79e: 6028 str r0, [r5, #0] +1002d7a0: 6828 ldr r0, [r5, #0] +1002d7a2: 2800 cmp r0, #0 +1002d7a4: d137 bne.n 1002d816 +1002d7a6: e035 b.n 1002d814 +1002d7a8: f44f 3180 mov.w r1, #65536 ; 0x10000 +1002d7ac: f000 f83d bl 1002d82a <.text_47+0x2> +1002d7b0: 2801 cmp r0, #1 +1002d7b2: d12f bne.n 1002d814 +1002d7b4: f000 f838 bl 1002d828 <.text_47> +1002d7b8: 2801 cmp r0, #1 +1002d7ba: d12b bne.n 1002d814 +1002d7bc: 2206 movs r2, #6 +1002d7be: 1d31 adds r1, r6, #4 +1002d7c0: f10b 001a add.w r0, fp, #26 +1002d7c4: f7e3 f823 bl 1001080e +1002d7c8: 2206 movs r2, #6 +1002d7ca: f106 010a add.w r1, r6, #10 +1002d7ce: f10b 0020 add.w r0, fp, #32 +1002d7d2: f7e3 f81c bl 1001080e +1002d7d6: 2206 movs r2, #6 +1002d7d8: f106 0110 add.w r1, r6, #16 +1002d7dc: f10b 0032 add.w r0, fp, #50 ; 0x32 +1002d7e0: f7e3 f815 bl 1001080e +1002d7e4: 2206 movs r2, #6 +1002d7e6: f10b 011a add.w r1, fp, #26 +1002d7ea: f10b 002c add.w r0, fp, #44 ; 0x2c +1002d7ee: f7e3 f80e bl 1001080e +1002d7f2: 2206 movs r2, #6 +1002d7f4: f10b 0120 add.w r1, fp, #32 +1002d7f8: f10b 0026 add.w r0, fp, #38 ; 0x26 +1002d7fc: f7e3 f807 bl 1001080e +1002d800: 2206 movs r2, #6 +1002d802: 4651 mov r1, sl +1002d804: f10b 0032 add.w r0, fp, #50 ; 0x32 +1002d808: f7e3 f801 bl 1001080e +1002d80c: f000 f810 bl 1002d830 <.text_48> +1002d810: 6028 str r0, [r5, #0] +1002d812: b900 cbnz r0, 1002d816 +1002d814: 2400 movs r4, #0 +1002d816: 4620 mov r0, r4 +1002d818: e8bd 8ffe ldmia.w sp!, {r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, pc} +1002d81c: 0000 movs r0, r0 + ... + +1002d820 : + ... + +1002d828 <.text_47>: +1002d828: 2101 movs r1, #1 +1002d82a: 4648 mov r0, r9 +1002d82c: f7ff bb71 b.w 1002cf12 + +1002d830 <.text_48>: +1002d830: 9801 ldr r0, [sp, #4] +1002d832: f10b 0132 add.w r1, fp, #50 ; 0x32 +1002d836: f7f7 bcb9 b.w 100251ac + +1002d83a : +1002d83a: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1002d83e: 4605 mov r5, r0 +1002d840: 4688 mov r8, r1 +1002d842: f505 5088 add.w r0, r5, #4352 ; 0x1100 +1002d846: f8d8 6084 ldr.w r6, [r8, #132] ; 0x84 +1002d84a: f100 0a28 add.w sl, r0, #40 ; 0x28 +1002d84e: f105 0b0c add.w fp, r5, #12 +1002d852: 4617 mov r7, r2 +1002d854: f108 091c add.w r9, r8, #28 +1002d858: 2401 movs r4, #1 +1002d85a: 2110 movs r1, #16 +1002d85c: 4658 mov r0, fp +1002d85e: f7ff fb58 bl 1002cf12 +1002d862: 2801 cmp r0, #1 +1002d864: d131 bne.n 1002d8ca +1002d866: 2206 movs r2, #6 +1002d868: f10b 0190 add.w r1, fp, #144 ; 0x90 +1002d86c: f109 0032 add.w r0, r9, #50 ; 0x32 +1002d870: f7e2 ffd7 bl 10010822 +1002d874: b318 cbz r0, 1002d8be +1002d876: f109 0120 add.w r1, r9, #32 +1002d87a: 4650 mov r0, sl +1002d87c: f7f7 fc96 bl 100251ac +1002d880: 6038 str r0, [r7, #0] +1002d882: b930 cbnz r0, 1002d892 +1002d884: 2207 movs r2, #7 +1002d886: f109 0120 add.w r1, r9, #32 +1002d88a: 4628 mov r0, r5 +1002d88c: f7ee fc44 bl 1001c118 +1002d890: e015 b.n 1002d8be +1002d892: 4641 mov r1, r8 +1002d894: 4628 mov r0, r5 +1002d896: f7ff fdbb bl 1002d410 +1002d89a: 8830 ldrh r0, [r6, #0] +1002d89c: f000 01fc and.w r1, r0, #252 ; 0xfc +1002d8a0: 2948 cmp r1, #72 ; 0x48 +1002d8a2: d007 beq.n 1002d8b4 +1002d8a4: f000 0188 and.w r1, r0, #136 ; 0x88 +1002d8a8: 2988 cmp r1, #136 ; 0x88 +1002d8aa: d10e bne.n 1002d8ca +1002d8ac: f000 00fc and.w r0, r0, #252 ; 0xfc +1002d8b0: 28c8 cmp r0, #200 ; 0xc8 +1002d8b2: d106 bne.n 1002d8c2 +1002d8b4: 683a ldr r2, [r7, #0] +1002d8b6: 4641 mov r1, r8 +1002d8b8: 4628 mov r0, r5 +1002d8ba: f7ff fe0c bl 1002d4d6 +1002d8be: 2400 movs r4, #0 +1002d8c0: e003 b.n 1002d8ca +1002d8c2: 4641 mov r1, r8 +1002d8c4: 4628 mov r0, r5 +1002d8c6: f7ff fdc6 bl 1002d456 +1002d8ca: 4620 mov r0, r4 +1002d8cc: e8bd 8ff2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1002d8d0 : +1002d8d0: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1002d8d4: f8d1 7084 ldr.w r7, [r1, #132] ; 0x84 +1002d8d8: 4680 mov r8, r0 +1002d8da: 7838 ldrb r0, [r7, #0] +1002d8dc: f508 5688 add.w r6, r8, #4352 ; 0x1100 +1002d8e0: 3628 adds r6, #40 ; 0x28 +1002d8e2: f000 000c and.w r0, r0, #12 +1002d8e6: 2804 cmp r0, #4 +1002d8e8: f101 051c add.w r5, r1, #28 +1002d8ec: d13b bne.n 1002d966 +1002d8ee: f508 51c8 add.w r1, r8, #6400 ; 0x1900 +1002d8f2: 2206 movs r2, #6 +1002d8f4: 3195 adds r1, #149 ; 0x95 +1002d8f6: 1d38 adds r0, r7, #4 +1002d8f8: f7e2 ff93 bl 10010822 +1002d8fc: 2800 cmp r0, #0 +1002d8fe: d03c beq.n 1002d97a +1002d900: 7838 ldrb r0, [r7, #0] +1002d902: f000 00fc and.w r0, r0, #252 ; 0xfc +1002d906: 28a4 cmp r0, #164 ; 0xa4 +1002d908: d12d bne.n 1002d966 +1002d90a: 8878 ldrh r0, [r7, #2] +1002d90c: ea4f 4980 mov.w r9, r0, lsl #18 +1002d910: f107 010a add.w r1, r7, #10 +1002d914: 4630 mov r0, r6 +1002d916: f7f7 fc49 bl 100251ac +1002d91a: 0007 movs r7, r0 +1002d91c: d02d beq.n 1002d97a +1002d91e: f107 04f4 add.w r4, r7, #244 ; 0xf4 +1002d922: 68a2 ldr r2, [r4, #8] +1002d924: ebb2 4f99 cmp.w r2, r9, lsr #18 +1002d928: d11d bne.n 1002d966 +1002d92a: e9d7 0162 ldrd r0, r1, [r7, #392] ; 0x188 +1002d92e: 1c40 adds r0, r0, #1 +1002d930: f141 0100 adc.w r1, r1, #0 +1002d934: e9c7 0162 strd r0, r1, [r7, #392] ; 0x188 +1002d938: 7a69 ldrb r1, [r5, #9] +1002d93a: 1e49 subs r1, r1, #1 +1002d93c: 2901 cmp r1, #1 +1002d93e: f207 3006 addw r0, r7, #774 ; 0x306 +1002d942: d906 bls.n 1002d952 +1002d944: 1ec9 subs r1, r1, #3 +1002d946: 2901 cmp r1, #1 +1002d948: d906 bls.n 1002d958 +1002d94a: 1e89 subs r1, r1, #2 +1002d94c: 2901 cmp r1, #1 +1002d94e: d905 bls.n 1002d95c +1002d950: e006 b.n 1002d960 +1002d952: f897 0306 ldrb.w r0, [r7, #774] ; 0x306 +1002d956: e004 b.n 1002d962 +1002d958: 7880 ldrb r0, [r0, #2] +1002d95a: e002 b.n 1002d962 +1002d95c: 78c0 ldrb r0, [r0, #3] +1002d95e: e000 b.n 1002d962 +1002d960: 7840 ldrb r0, [r0, #1] +1002d962: f010 0001 ands.w r0, r0, #1 +1002d966: d162 bne.n 1002da2e +1002d968: 7920 ldrb r0, [r4, #4] +1002d96a: 0740 lsls r0, r0, #29 +1002d96c: d55f bpl.n 1002da2e +1002d96e: 2501 movs r5, #1 +1002d970: f8b6 00c0 ldrh.w r0, [r6, #192] ; 0xc0 +1002d974: fa05 f102 lsl.w r1, r5, r2 +1002d978: 4208 tst r0, r1 +1002d97a: d058 beq.n 1002da2e +1002d97c: f107 09f0 add.w r9, r7, #240 ; 0xf0 +1002d980: a900 add r1, sp, #0 +1002d982: 4648 mov r0, r9 +1002d984: f7e2 ffc6 bl 10010914 +1002d988: f107 00e8 add.w r0, r7, #232 ; 0xe8 +1002d98c: 36c0 adds r6, #192 ; 0xc0 +1002d98e: f8d0 a000 ldr.w sl, [r0] +1002d992: 4651 mov r1, sl +1002d994: f7e2 ffd9 bl 1001094a +1002d998: bb68 cbnz r0, 1002d9f6 +1002d99a: 4650 mov r0, sl +1002d99c: f7e2 ff62 bl 10010864 +1002d9a0: f8d7 00f4 ldr.w r0, [r7, #244] ; 0xf4 +1002d9a4: 1e40 subs r0, r0, #1 +1002d9a6: f8c7 00f4 str.w r0, [r7, #244] ; 0xf4 +1002d9aa: a900 add r1, sp, #0 +1002d9ac: bf18 it ne +1002d9ae: 2001 movne r0, #1 +1002d9b0: f88a 0065 strb.w r0, [sl, #101] ; 0x65 +1002d9b4: f88a 5067 strb.w r5, [sl, #103] ; 0x67 +1002d9b8: 4648 mov r0, r9 +1002d9ba: f7e2 ffac bl 10010916 +1002d9be: f608 1b28 addw fp, r8, #2344 ; 0x928 +1002d9c2: a900 add r1, sp, #0 +1002d9c4: 4658 mov r0, fp +1002d9c6: f7e2 ffa5 bl 10010914 +1002d9ca: 4651 mov r1, sl +1002d9cc: 4640 mov r0, r8 +1002d9ce: f7fe fe6a bl 1002c6a6 +1002d9d2: 2801 cmp r0, #1 +1002d9d4: d003 beq.n 1002d9de +1002d9d6: 4651 mov r1, sl +1002d9d8: 4658 mov r0, fp +1002d9da: f7fe fe1d bl 1002c618 +1002d9de: a900 add r1, sp, #0 +1002d9e0: 4658 mov r0, fp +1002d9e2: f7e2 ff98 bl 10010916 +1002d9e6: a900 add r1, sp, #0 +1002d9e8: 4648 mov r0, r9 +1002d9ea: f7e2 ff93 bl 10010914 +1002d9ee: f8d7 00f4 ldr.w r0, [r7, #244] ; 0xf4 +1002d9f2: b9c0 cbnz r0, 1002da26 +1002d9f4: e00b b.n 1002da0e +1002d9f6: 68a1 ldr r1, [r4, #8] +1002d9f8: 8870 ldrh r0, [r6, #2] +1002d9fa: fa05 f101 lsl.w r1, r5, r1 +1002d9fe: 4208 tst r0, r1 +1002da00: d011 beq.n 1002da26 +1002da02: f8d7 00f4 ldr.w r0, [r7, #244] ; 0xf4 +1002da06: b110 cbz r0, 1002da0e +1002da08: 2000 movs r0, #0 +1002da0a: f8c7 00f4 str.w r0, [r7, #244] ; 0xf4 +1002da0e: 2300 movs r3, #0 +1002da10: 68a1 ldr r1, [r4, #8] +1002da12: 8870 ldrh r0, [r6, #2] +1002da14: fa05 f101 lsl.w r1, r5, r1 +1002da18: 4388 bics r0, r1 +1002da1a: 8070 strh r0, [r6, #2] +1002da1c: 2200 movs r2, #0 +1002da1e: 2105 movs r1, #5 +1002da20: 4640 mov r0, r8 +1002da22: f7eb fb6d bl 10019100 +1002da26: a900 add r1, sp, #0 +1002da28: 4648 mov r0, r9 +1002da2a: f7e2 ff74 bl 10010916 +1002da2e: 2000 movs r0, #0 +1002da30: e8bd 8ff2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1002da34 : +1002da34: b570 push {r4, r5, r6, lr} +1002da36: 460d mov r5, r1 +1002da38: 4604 mov r4, r0 +1002da3a: 682e ldr r6, [r5, #0] +1002da3c: f8d6 0084 ldr.w r0, [r6, #132] ; 0x84 +1002da40: f100 010a add.w r1, r0, #10 +1002da44: f504 5088 add.w r0, r4, #4352 ; 0x1100 +1002da48: f7ff fd02 bl 1002d450 <.text_39> +1002da4c: b128 cbz r0, 1002da5a +1002da4e: e9d0 2360 ldrd r2, r3, [r0, #384] ; 0x180 +1002da52: f000 f982 bl 1002dd5a <.text_56> +1002da56: e9c0 2360 strd r2, r3, [r0, #384] ; 0x180 +1002da5a: 4631 mov r1, r6 +1002da5c: 4620 mov r0, r4 +1002da5e: f000 fa1b bl 1002de98 +1002da62: 0001 movs r1, r0 +1002da64: 6029 str r1, [r5, #0] +1002da66: bf1c itt ne +1002da68: 4620 movne r0, r4 +1002da6a: f7ec f97f blne 10019d6c +1002da6e: 2001 movs r0, #1 +1002da70: bd70 pop {r4, r5, r6, pc} + +1002da72 : +1002da72: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +1002da76: b087 sub sp, #28 +1002da78: 4680 mov r8, r0 +1002da7a: 468b mov fp, r1 +1002da7c: 2000 movs r0, #0 +1002da7e: 9000 str r0, [sp, #0] +1002da80: f10b 051c add.w r5, fp, #28 +1002da84: f8db 7084 ldr.w r7, [fp, #132] ; 0x84 +1002da88: 8839 ldrh r1, [r7, #0] +1002da8a: f508 5088 add.w r0, r8, #4352 ; 0x1100 +1002da8e: f100 09f0 add.w r9, r0, #240 ; 0xf0 +1002da92: 0ac8 lsrs r0, r1, #11 +1002da94: f000 0001 and.w r0, r0, #1 +1002da98: f88d 0014 strb.w r0, [sp, #20] +1002da9c: f107 0410 add.w r4, r7, #16 +1002daa0: 0a08 lsrs r0, r1, #8 +1002daa2: f000 0001 and.w r0, r0, #1 +1002daa6: 0a89 lsrs r1, r1, #10 +1002daa8: 4140 adcs r0, r0 +1002daaa: 1d3a adds r2, r7, #4 +1002daac: 9204 str r2, [sp, #16] +1002daae: f04f 0a01 mov.w sl, #1 +1002dab2: b2c2 uxtb r2, r0 +1002dab4: 2a01 cmp r2, #1 +1002dab6: bf9a itte ls +1002dab8: 9a04 ldrls r2, [sp, #16] +1002daba: 9202 strls r2, [sp, #8] +1002dabc: 9402 strhi r4, [sp, #8] +1002dabe: b2c0 uxtb r0, r0 +1002dac0: 2800 cmp r0, #0 +1002dac2: f107 020a add.w r2, r7, #10 +1002dac6: bf18 it ne +1002dac8: 2802 cmpne r0, #2 +1002daca: 9203 str r2, [sp, #12] +1002dacc: d005 beq.n 1002dada +1002dace: bf32 itee cc +1002dad0: 9401 strcc r4, [sp, #4] +1002dad2: f107 0118 addcs.w r1, r7, #24 +1002dad6: 9101 strcs r1, [sp, #4] +1002dad8: e000 b.n 1002dadc +1002dada: 9201 str r2, [sp, #4] +1002dadc: b138 cbz r0, 1002daee +1002dade: 2802 cmp r0, #2 +1002dae0: d002 beq.n 1002dae8 +1002dae2: d303 bcc.n 1002daec +1002dae4: 2803 cmp r0, #3 +1002dae6: d11e bne.n 1002db26 +1002dae8: 9c04 ldr r4, [sp, #16] +1002daea: e000 b.n 1002daee +1002daec: 4614 mov r4, r2 +1002daee: 2c00 cmp r4, #0 +1002daf0: d019 beq.n 1002db26 +1002daf2: 9902 ldr r1, [sp, #8] +1002daf4: 2206 movs r2, #6 +1002daf6: f105 001a add.w r0, r5, #26 +1002dafa: f7e2 fe88 bl 1001080e +1002dafe: 9901 ldr r1, [sp, #4] +1002db00: 2206 movs r2, #6 +1002db02: f105 0020 add.w r0, r5, #32 +1002db06: f7e2 fe82 bl 1001080e +1002db0a: 2206 movs r2, #6 +1002db0c: 4621 mov r1, r4 +1002db0e: f105 0032 add.w r0, r5, #50 ; 0x32 +1002db12: f7e2 fe7c bl 1001080e +1002db16: 1d6e adds r6, r5, #5 +1002db18: 7870 ldrb r0, [r6, #1] +1002db1a: b128 cbz r0, 1002db28 +1002db1c: 2802 cmp r0, #2 +1002db1e: d03b beq.n 1002db98 +1002db20: d32c bcc.n 1002db7c +1002db22: 2803 cmp r0, #3 +1002db24: d046 beq.n 1002dbb4 +1002db26: e06a b.n 1002dbfe +1002db28: f000 f8b0 bl 1002dc8c <.text_54> +1002db2c: f000 f8a8 bl 1002dc80 <.text_53> +1002db30: aa00 add r2, sp, #0 +1002db32: 4659 mov r1, fp +1002db34: 4640 mov r0, r8 +1002db36: f7ff fd15 bl 1002d564 +1002db3a: 2800 cmp r0, #0 +1002db3c: bf1c itt ne +1002db3e: 9800 ldrne r0, [sp, #0] +1002db40: 2800 cmpne r0, #0 +1002db42: d05c beq.n 1002dbfe +1002db44: f8cb 0094 str.w r0, [fp, #148] ; 0x94 +1002db48: 2000 movs r0, #0 +1002db4a: 70b0 strb r0, [r6, #2] +1002db4c: f885 0038 strb.w r0, [r5, #56] ; 0x38 +1002db50: 78f0 ldrb r0, [r6, #3] +1002db52: 2801 cmp r0, #1 +1002db54: d13d bne.n 1002dbd2 +1002db56: 7e38 ldrb r0, [r7, #24] +1002db58: f000 000f and.w r0, r0, #15 +1002db5c: 7130 strb r0, [r6, #4] +1002db5e: 8b39 ldrh r1, [r7, #24] +1002db60: f3c1 1141 ubfx r1, r1, #5, #2 +1002db64: f885 1038 strb.w r1, [r5, #56] ; 0x38 +1002db68: 8b39 ldrh r1, [r7, #24] +1002db6a: 0609 lsls r1, r1, #24 +1002db6c: 0fc9 lsrs r1, r1, #31 +1002db6e: 70b1 strb r1, [r6, #2] +1002db70: 7871 ldrb r1, [r6, #1] +1002db72: 2903 cmp r1, #3 +1002db74: bf0c ite eq +1002db76: 2120 moveq r1, #32 +1002db78: 211a movne r1, #26 +1002db7a: e022 b.n 1002dbc2 +1002db7c: f000 f886 bl 1002dc8c <.text_54> +1002db80: 2206 movs r2, #6 +1002db82: 4621 mov r1, r4 +1002db84: f105 0026 add.w r0, r5, #38 ; 0x26 +1002db88: f7e2 fe41 bl 1001080e +1002db8c: aa00 add r2, sp, #0 +1002db8e: 4659 mov r1, fp +1002db90: 4640 mov r0, r8 +1002db92: f7ff fd9f bl 1002d6d4 +1002db96: e7d0 b.n 1002db3a +1002db98: 2206 movs r2, #6 +1002db9a: 4621 mov r1, r4 +1002db9c: f105 002c add.w r0, r5, #44 ; 0x2c +1002dba0: f7e2 fe35 bl 1001080e +1002dba4: f000 f86c bl 1002dc80 <.text_53> +1002dba8: aa00 add r2, sp, #0 +1002dbaa: 4659 mov r1, fp +1002dbac: 4640 mov r0, r8 +1002dbae: f7ff fe44 bl 1002d83a +1002dbb2: e7c2 b.n 1002db3a +1002dbb4: 9904 ldr r1, [sp, #16] +1002dbb6: f000 f86a bl 1002dc8e <.text_54+0x2> +1002dbba: 9903 ldr r1, [sp, #12] +1002dbbc: f000 f861 bl 1002dc82 <.text_53+0x2> +1002dbc0: e01d b.n 1002dbfe +1002dbc2: 2800 cmp r0, #0 +1002dbc4: bf18 it ne +1002dbc6: 2803 cmpne r0, #3 +1002dbc8: 7169 strb r1, [r5, #5] +1002dbca: d00a beq.n 1002dbe2 +1002dbcc: f8c8 ab58 str.w sl, [r8, #2904] ; 0xb58 +1002dbd0: e007 b.n 1002dbe2 +1002dbd2: 2000 movs r0, #0 +1002dbd4: 7130 strb r0, [r6, #4] +1002dbd6: 7870 ldrb r0, [r6, #1] +1002dbd8: 2803 cmp r0, #3 +1002dbda: bf0c ite eq +1002dbdc: 201e moveq r0, #30 +1002dbde: 2018 movne r0, #24 +1002dbe0: 7168 strb r0, [r5, #5] +1002dbe2: 7af0 ldrb r0, [r6, #11] +1002dbe4: b110 cbz r0, 1002dbec +1002dbe6: 7968 ldrb r0, [r5, #5] +1002dbe8: 1d00 adds r0, r0, #4 +1002dbea: 7168 strb r0, [r5, #5] +1002dbec: 9800 ldr r0, [sp, #0] +1002dbee: f89d 1014 ldrb.w r1, [sp, #20] +1002dbf2: f100 02c8 add.w r2, r0, #200 ; 0xc8 +1002dbf6: 4658 mov r0, fp +1002dbf8: f7ff fbf4 bl 1002d3e4 +1002dbfc: b910 cbnz r0, 1002dc04 +1002dbfe: f04f 0a00 mov.w sl, #0 +1002dc02: e039 b.n 1002dc78 +1002dc04: 7b30 ldrb r0, [r6, #12] +1002dc06: b3a0 cbz r0, 1002dc72 +1002dc08: f8d9 0000 ldr.w r0, [r9] +1002dc0c: b190 cbz r0, 1002dc34 +1002dc0e: 2802 cmp r0, #2 +1002dc10: d004 beq.n 1002dc1c +1002dc12: d30f bcc.n 1002dc34 +1002dc14: 2804 cmp r0, #4 +1002dc16: d00d beq.n 1002dc34 +1002dc18: d30c bcc.n 1002dc34 +1002dc1a: e00e b.n 1002dc3a +1002dc1c: f105 002c add.w r0, r5, #44 ; 0x2c +1002dc20: f7ff f948 bl 1002ceb4 +1002dc24: 2800 cmp r0, #0 +1002dc26: bf06 itte eq +1002dc28: 9800 ldreq r0, [sp, #0] +1002dc2a: f8d0 0114 ldreq.w r0, [r0, #276] ; 0x114 +1002dc2e: f8d9 005c ldrne.w r0, [r9, #92] ; 0x5c +1002dc32: e001 b.n 1002dc38 +1002dc34: f8d9 0004 ldr.w r0, [r9, #4] +1002dc38: 73b0 strb r0, [r6, #14] +1002dc3a: 7bb0 ldrb r0, [r6, #14] +1002dc3c: 2801 cmp r0, #1 +1002dc3e: d008 beq.n 1002dc52 +1002dc40: 2802 cmp r0, #2 +1002dc42: d008 beq.n 1002dc56 +1002dc44: 2804 cmp r0, #4 +1002dc46: d00a beq.n 1002dc5e +1002dc48: 2805 cmp r0, #5 +1002dc4a: d002 beq.n 1002dc52 +1002dc4c: 2806 cmp r0, #6 +1002dc4e: d008 beq.n 1002dc62 +1002dc50: e00b b.n 1002dc6a +1002dc52: 2004 movs r0, #4 +1002dc54: e00a b.n 1002dc6c +1002dc56: 2008 movs r0, #8 +1002dc58: 73f0 strb r0, [r6, #15] +1002dc5a: 2004 movs r0, #4 +1002dc5c: e007 b.n 1002dc6e +1002dc5e: 2008 movs r0, #8 +1002dc60: e004 b.n 1002dc6c +1002dc62: 2012 movs r0, #18 +1002dc64: 73f0 strb r0, [r6, #15] +1002dc66: 2010 movs r0, #16 +1002dc68: e001 b.n 1002dc6e +1002dc6a: 2000 movs r0, #0 +1002dc6c: 73f0 strb r0, [r6, #15] +1002dc6e: 7430 strb r0, [r6, #16] +1002dc70: e002 b.n 1002dc78 +1002dc72: 73b0 strb r0, [r6, #14] +1002dc74: 7430 strb r0, [r6, #16] +1002dc76: 73f0 strb r0, [r6, #15] +1002dc78: 4650 mov r0, sl +1002dc7a: b007 add sp, #28 +1002dc7c: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1002dc80 <.text_53>: +1002dc80: 9901 ldr r1, [sp, #4] +1002dc82: 2206 movs r2, #6 +1002dc84: f105 0026 add.w r0, r5, #38 ; 0x26 +1002dc88: f7e2 bdc1 b.w 1001080e + +1002dc8c <.text_54>: +1002dc8c: 9902 ldr r1, [sp, #8] +1002dc8e: 2206 movs r2, #6 +1002dc90: f105 002c add.w r0, r5, #44 ; 0x2c +1002dc94: f7e2 bdbb b.w 1001080e + +1002dc98 : +1002dc98: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1002dc9c: 460d mov r5, r1 +1002dc9e: b082 sub sp, #8 +1002dca0: 4680 mov r8, r0 +1002dca2: 6828 ldr r0, [r5, #0] +1002dca4: f100 061c add.w r6, r0, #28 +1002dca8: f8d0 0084 ldr.w r0, [r0, #132] ; 0x84 +1002dcac: 7801 ldrb r1, [r0, #0] +1002dcae: 2203 movs r2, #3 +1002dcb0: 4211 tst r1, r2 +1002dcb2: d139 bne.n 1002dd28 +1002dcb4: 8801 ldrh r1, [r0, #0] +1002dcb6: f001 070c and.w r7, r1, #12 +1002dcba: f001 04fc and.w r4, r1, #252 ; 0xfc +1002dcbe: 0a0a lsrs r2, r1, #8 +1002dcc0: f002 0201 and.w r2, r2, #1 +1002dcc4: 0a89 lsrs r1, r1, #10 +1002dcc6: 4152 adcs r2, r2 +1002dcc8: 71b2 strb r2, [r6, #6] +1002dcca: f100 0116 add.w r1, r0, #22 +1002dcce: 780a ldrb r2, [r1, #0] +1002dcd0: f002 020f and.w r2, r2, #15 +1002dcd4: 73b2 strb r2, [r6, #14] +1002dcd6: aa00 add r2, sp, #0 +1002dcd8: 8809 ldrh r1, [r1, #0] +1002dcda: 0909 lsrs r1, r1, #4 +1002dcdc: 81b1 strh r1, [r6, #12] +1002dcde: 8801 ldrh r1, [r0, #0] +1002dce0: 0b09 lsrs r1, r1, #12 +1002dce2: f001 0101 and.w r1, r1, #1 +1002dce6: 72b1 strb r1, [r6, #10] +1002dce8: 8801 ldrh r1, [r0, #0] +1002dcea: 0a89 lsrs r1, r1, #10 +1002dcec: f001 0101 and.w r1, r1, #1 +1002dcf0: 73f1 strb r1, [r6, #15] +1002dcf2: 8801 ldrh r1, [r0, #0] +1002dcf4: 0b49 lsrs r1, r1, #13 +1002dcf6: f001 0101 and.w r1, r1, #1 +1002dcfa: 72f1 strb r1, [r6, #11] +1002dcfc: 8801 ldrh r1, [r0, #0] +1002dcfe: 0b89 lsrs r1, r1, #14 +1002dd00: f001 0101 and.w r1, r1, #1 +1002dd04: 7471 strb r1, [r6, #17] +1002dd06: 2106 movs r1, #6 +1002dd08: 8800 ldrh r0, [r0, #0] +1002dd0a: 0bc0 lsrs r0, r0, #15 +1002dd0c: 7430 strb r0, [r6, #16] +1002dd0e: 4640 mov r0, r8 +1002dd10: f7e9 fb1d bl 1001734e +1002dd14: b127 cbz r7, 1002dd20 +1002dd16: 2f04 cmp r7, #4 +1002dd18: d009 beq.n 1002dd2e +1002dd1a: 2f08 cmp r7, #8 +1002dd1c: d00c beq.n 1002dd38 +1002dd1e: e003 b.n 1002dd28 +1002dd20: 4629 mov r1, r5 +1002dd22: 4640 mov r0, r8 +1002dd24: f7ff fe86 bl 1002da34 +1002dd28: 2000 movs r0, #0 +1002dd2a: e8bd 81f6 ldmia.w sp!, {r1, r2, r4, r5, r6, r7, r8, pc} +1002dd2e: 6829 ldr r1, [r5, #0] +1002dd30: 4640 mov r0, r8 +1002dd32: f7ff fdcd bl 1002d8d0 +1002dd36: e7f7 b.n 1002dd28 +1002dd38: 09e0 lsrs r0, r4, #7 +1002dd3a: 7230 strb r0, [r6, #8] +1002dd3c: 4640 mov r0, r8 +1002dd3e: 6829 ldr r1, [r5, #0] +1002dd40: f7ff fe97 bl 1002da72 +1002dd44: 2800 cmp r0, #0 +1002dd46: d1f0 bne.n 1002dd2a +1002dd48: f508 6132 add.w r1, r8, #2848 ; 0xb20 +1002dd4c: e9d1 2314 ldrd r2, r3, [r1, #80] ; 0x50 +1002dd50: f000 f803 bl 1002dd5a <.text_56> +1002dd54: e9c1 2314 strd r2, r3, [r1, #80] ; 0x50 +1002dd58: e7e7 b.n 1002dd2a + +1002dd5a <.text_56>: +1002dd5a: 1c52 adds r2, r2, #1 +1002dd5c: f143 0300 adc.w r3, r3, #0 +1002dd60: 4770 bx lr + +1002dd62 : +1002dd62: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +1002dd66: 4604 mov r4, r0 +1002dd68: b082 sub sp, #8 +1002dd6a: 6927 ldr r7, [r4, #16] +1002dd6c: f107 080c add.w r8, r7, #12 +1002dd70: f7ff f8a7 bl 1002cec2 +1002dd74: f104 051c add.w r5, r4, #28 +1002dd78: 4681 mov r9, r0 +1002dd7a: 7ce8 ldrb r0, [r5, #19] +1002dd7c: b118 cbz r0, 1002dd86 +1002dd7e: 7d69 ldrb r1, [r5, #21] +1002dd80: 4620 mov r0, r4 +1002dd82: f7ff f8b2 bl 1002ceea +1002dd86: 7968 ldrb r0, [r5, #5] +1002dd88: 7d29 ldrb r1, [r5, #20] +1002dd8a: 4448 add r0, r9 +1002dd8c: 180e adds r6, r1, r0 +1002dd8e: f106 0a06 add.w sl, r6, #6 +1002dd92: 2206 movs r2, #6 +1002dd94: f20f 318c addw r1, pc, #908 ; 0x38c +1002dd98: 4630 mov r0, r6 +1002dd9a: f7e2 fd42 bl 10010822 +1002dd9e: b168 cbz r0, 1002ddbc +1002dda0: 2202 movs r2, #2 +1002dda2: f20f 3178 addw r1, pc, #888 ; 0x378 +1002dda6: 4650 mov r0, sl +1002dda8: f7e2 fd3b bl 10010822 +1002ddac: b930 cbnz r0, 1002ddbc +1002ddae: 2202 movs r2, #2 +1002ddb0: f20f 316c addw r1, pc, #876 ; 0x36c +1002ddb4: 4650 mov r0, sl +1002ddb6: f7e2 fd34 bl 10010822 +1002ddba: b138 cbz r0, 1002ddcc +1002ddbc: 2206 movs r2, #6 +1002ddbe: f20f 316c addw r1, pc, #876 ; 0x36c +1002ddc2: 4630 mov r0, r6 +1002ddc4: f7e2 fd2d bl 10010822 +1002ddc8: 0006 movs r6, r0 +1002ddca: d000 beq.n 1002ddce +1002ddcc: 2601 movs r6, #1 +1002ddce: f241 100c movw r0, #4364 ; 0x110c +1002ddd2: 5dc0 ldrb r0, [r0, r7] +1002ddd4: b108 cbz r0, 1002ddda +1002ddd6: 2601 movs r6, #1 +1002ddd8: e001 b.n 1002ddde +1002ddda: b2f6 uxtb r6, r6 +1002dddc: b106 cbz r6, 1002dde0 +1002ddde: 2006 movs r0, #6 +1002dde0: 7969 ldrb r1, [r5, #5] +1002dde2: 7d2a ldrb r2, [r5, #20] +1002dde4: 1851 adds r1, r2, r1 +1002dde6: 1847 adds r7, r0, r1 +1002dde8: 6fe0 ldr r0, [r4, #124] ; 0x7c +1002ddea: 1bc0 subs r0, r0, r7 +1002ddec: f8ad 0002 strh.w r0, [sp, #2] +1002ddf0: 2202 movs r2, #2 +1002ddf2: eb07 0109 add.w r1, r7, r9 +1002ddf6: f7ff faf2 bl 1002d3de <.text_36+0x2> +1002ddfa: f000 f849 bl 1002de90 <.text_58> +1002ddfe: f8ad 0000 strh.w r0, [sp] +1002de02: 8328 strh r0, [r5, #24] +1002de04: f44f 3180 mov.w r1, #65536 ; 0x10000 +1002de08: 4640 mov r0, r8 +1002de0a: f7ff f882 bl 1002cf12 +1002de0e: 2801 cmp r0, #1 +1002de10: d119 bne.n 1002de46 +1002de12: eb07 0009 add.w r0, r7, r9 +1002de16: 2187 movs r1, #135 ; 0x87 +1002de18: 7001 strb r1, [r0, #0] +1002de1a: 2112 movs r1, #18 +1002de1c: 7041 strb r1, [r0, #1] +1002de1e: f248 7012 movw r0, #34578 ; 0x8712 +1002de22: f8ad 0000 strh.w r0, [sp] +1002de26: f1a7 0124 sub.w r1, r7, #36 ; 0x24 +1002de2a: f000 f85d bl 1002dee8 <.text_62+0x4> +1002de2e: 2c00 cmp r4, #0 +1002de30: bf0c ite eq +1002de32: 2100 moveq r1, #0 +1002de34: f8d4 1080 ldrne.w r1, [r4, #128] ; 0x80 +1002de38: 4607 mov r7, r0 +1002de3a: 2218 movs r2, #24 +1002de3c: f7e2 fce7 bl 1001080e +1002de40: f107 0418 add.w r4, r7, #24 +1002de44: e007 b.n 1002de56 +1002de46: 2e00 cmp r6, #0 +1002de48: bf14 ite ne +1002de4a: 2002 movne r0, #2 +1002de4c: 2000 moveq r0, #0 +1002de4e: 19c0 adds r0, r0, r7 +1002de50: f000 f848 bl 1002dee4 <.text_62> +1002de54: 4604 mov r4, r0 +1002de56: 2206 movs r2, #6 +1002de58: f105 011a add.w r1, r5, #26 +1002de5c: 4620 mov r0, r4 +1002de5e: f7e2 fcd6 bl 1001080e +1002de62: 2206 movs r2, #6 +1002de64: f105 0120 add.w r1, r5, #32 +1002de68: 1da0 adds r0, r4, #6 +1002de6a: f7e2 fcd0 bl 1001080e +1002de6e: b966 cbnz r6, 1002de8a +1002de70: f8bd 0002 ldrh.w r0, [sp, #2] +1002de74: f7e2 fc54 bl 10010720 <_htons> +1002de78: f8ad 0002 strh.w r0, [sp, #2] +1002de7c: 2202 movs r2, #2 +1002de7e: f10d 0102 add.w r1, sp, #2 +1002de82: f104 000c add.w r0, r4, #12 +1002de86: f7e2 fcc2 bl 1001080e +1002de8a: 2001 movs r0, #1 +1002de8c: e8bd 87f6 ldmia.w sp!, {r1, r2, r4, r5, r6, r7, r8, r9, sl, pc} + +1002de90 <.text_58>: +1002de90: f8bd 0000 ldrh.w r0, [sp] +1002de94: f7e2 bc44 b.w 10010720 <_htons> + +1002de98 : +1002de98: b538 push {r3, r4, r5, lr} +1002de9a: 460a mov r2, r1 +1002de9c: 2400 movs r4, #0 +1002de9e: f892 102b ldrb.w r1, [r2, #43] ; 0x2b +1002dea2: 2900 cmp r1, #0 +1002dea4: bf04 itt eq +1002dea6: f892 102a ldrbeq.w r1, [r2, #42] ; 0x2a +1002deaa: 2900 cmpeq r1, #0 +1002deac: f600 3524 addw r5, r0, #2852 ; 0xb24 +1002deb0: d10f bne.n 1002ded2 +1002deb2: 0014 movs r4, r2 +1002deb4: bf1c itt ne +1002deb6: f894 102d ldrbne.w r1, [r4, #45] ; 0x2d +1002deba: 2900 cmpne r1, #0 +1002debc: d007 beq.n 1002dece +1002debe: 4621 mov r1, r4 +1002dec0: f7ff f990 bl 1002d1e4 +1002dec4: b918 cbnz r0, 1002dece +1002dec6: 4629 mov r1, r5 +1002dec8: f000 f809 bl 1002dede <.text_61+0x2> +1002decc: 2400 movs r4, #0 +1002dece: 4620 mov r0, r4 +1002ded0: bd32 pop {r1, r4, r5, pc} +1002ded2: 4629 mov r1, r5 +1002ded4: 4610 mov r0, r2 +1002ded6: f7ff f8c3 bl 1002d060 +1002deda: e7f8 b.n 1002dece + +1002dedc <.text_61>: +1002dedc: 4651 mov r1, sl +1002dede: 4620 mov r0, r4 +1002dee0: f7ff b8be b.w 1002d060 + +1002dee4 <.text_62>: +1002dee4: f1a0 010e sub.w r1, r0, #14 +1002dee8: 4620 mov r0, r4 +1002deea: f7fe bfee b.w 1002ceca + +1002deee : +1002deee: b538 push {r3, r4, r5, lr} +1002def0: 460d mov r5, r1 +1002def2: 4604 mov r4, r0 +1002def4: f895 0023 ldrb.w r0, [r5, #35] ; 0x23 +1002def8: b940 cbnz r0, 1002df0c +1002defa: 4628 mov r0, r5 +1002defc: f7ff ff31 bl 1002dd62 +1002df00: 4629 mov r1, r5 +1002df02: 4620 mov r0, r4 +1002df04: f004 ffe5 bl 10032ed2 +1002df08: 2001 movs r0, #1 +1002df0a: bd32 pop {r1, r4, r5, pc} +1002df0c: 2000 movs r0, #0 +1002df0e: bd32 pop {r1, r4, r5, pc} + +1002df10 : +1002df10: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1002df14: 4605 mov r5, r0 +1002df16: f641 479c movw r7, #7324 ; 0x1c9c +1002df1a: f8d5 0454 ldr.w r0, [r5, #1108] ; 0x454 +1002df1e: 2401 movs r4, #1 +1002df20: 197e adds r6, r7, r5 +1002df22: 2801 cmp r0, #1 +1002df24: 4688 mov r8, r1 +1002df26: d10c bne.n 1002df42 +1002df28: 4628 mov r0, r5 +1002df2a: f7ff ffe0 bl 1002deee +1002df2e: 2801 cmp r0, #1 +1002df30: d017 beq.n 1002df62 +1002df32: 5978 ldr r0, [r7, r5] +1002df34: 2800 cmp r0, #0 +1002df36: bf04 itt eq +1002df38: 6870 ldreq r0, [r6, #4] +1002df3a: 2800 cmpeq r0, #0 +1002df3c: d111 bne.n 1002df62 +1002df3e: 2000 movs r0, #0 +1002df40: e010 b.n 1002df64 +1002df42: 4640 mov r0, r8 +1002df44: f7ff ff0d bl 1002dd62 +1002df48: 4604 mov r4, r0 +1002df4a: 2c01 cmp r4, #1 +1002df4c: d109 bne.n 1002df62 +1002df4e: 5978 ldr r0, [r7, r5] +1002df50: 2800 cmp r0, #0 +1002df52: bf04 itt eq +1002df54: 6870 ldreq r0, [r6, #4] +1002df56: 2800 cmpeq r0, #0 +1002df58: d1f1 bne.n 1002df3e +1002df5a: 4641 mov r1, r8 +1002df5c: 4628 mov r0, r5 +1002df5e: f004 ffb8 bl 10032ed2 +1002df62: 4620 mov r0, r4 +1002df64: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +1002df68 : +1002df68: b532 push {r1, r4, r5, lr} +1002df6a: f600 3424 addw r4, r0, #2852 ; 0xb24 +1002df6e: a900 add r1, sp, #0 +1002df70: f7ff fe92 bl 1002dc98 +1002df74: 4605 mov r5, r0 +1002df76: 2d01 cmp r5, #1 +1002df78: bf1f itttt ne +1002df7a: 9800 ldrne r0, [sp, #0] +1002df7c: 2800 cmpne r0, #0 +1002df7e: 4621 movne r1, r4 +1002df80: f7ff f86e blne 1002d060 +1002df84: 4628 mov r0, r5 +1002df86: bd32 pop {r1, r4, r5, pc} + +1002df88 : +1002df88: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1002df8c: 4606 mov r6, r0 +1002df8e: 460f mov r7, r1 +1002df90: 2501 movs r5, #1 +1002df92: f506 6432 add.w r4, r6, #2848 ; 0xb20 +1002df96: f606 3824 addw r8, r6, #2852 ; 0xb24 +1002df9a: f7ff f989 bl 1002d2b0 +1002df9e: b150 cbz r0, 1002dfb6 +1002dfa0: 4601 mov r1, r0 +1002dfa2: 4630 mov r0, r6 +1002dfa4: f7ff ff78 bl 1002de98 +1002dfa8: b1b8 cbz r0, 1002dfda +1002dfaa: 4601 mov r1, r0 +1002dfac: 4630 mov r0, r6 +1002dfae: f7ff f9db bl 1002d368 +1002dfb2: 0005 movs r5, r0 +1002dfb4: d101 bne.n 1002dfba +1002dfb6: 2500 movs r5, #0 +1002dfb8: e00f b.n 1002dfda +1002dfba: 2200 movs r2, #0 +1002dfbc: 4629 mov r1, r5 +1002dfbe: 4630 mov r0, r6 +1002dfc0: f7ff fa89 bl 1002d4d6 +1002dfc4: 4629 mov r1, r5 +1002dfc6: 4630 mov r0, r6 +1002dfc8: f7ff ffa2 bl 1002df10 +1002dfcc: 4605 mov r5, r0 +1002dfce: 2d01 cmp r5, #1 +1002dfd0: d003 beq.n 1002dfda +1002dfd2: 4641 mov r1, r8 +1002dfd4: 4638 mov r0, r7 +1002dfd6: f7ff f843 bl 1002d060 +1002dfda: e9d4 0114 ldrd r0, r1, [r4, #80] ; 0x50 +1002dfde: 1c40 adds r0, r0, #1 +1002dfe0: f141 0100 adc.w r1, r1, #0 +1002dfe4: e9c4 0114 strd r0, r1, [r4, #80] ; 0x50 +1002dfe8: 4628 mov r0, r5 +1002dfea: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +1002dfee : +1002dfee: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +1002dff2: 4604 mov r4, r0 +1002dff4: 4688 mov r8, r1 +1002dff6: f504 5688 add.w r6, r4, #4352 ; 0x1100 +1002dffa: f104 0a0c add.w sl, r4, #12 +1002dffe: f108 051c add.w r5, r8, #28 +1002e002: 36f0 adds r6, #240 ; 0xf0 +1002e004: f604 393c addw r9, r4, #2876 ; 0xb3c +1002e008: 2108 movs r1, #8 +1002e00a: 4650 mov r0, sl +1002e00c: f7fe ff81 bl 1002cf12 +1002e010: 2800 cmp r0, #0 +1002e012: bf1c itt ne +1002e014: f896 0355 ldrbne.w r0, [r6, #853] ; 0x355 +1002e018: 2800 cmpne r0, #0 +1002e01a: d009 beq.n 1002e030 +1002e01c: e003 b.n 1002e026 +1002e01e: 4601 mov r1, r0 +1002e020: 4620 mov r0, r4 +1002e022: f7ff ffb1 bl 1002df88 +1002e026: 4648 mov r0, r9 +1002e028: f7ff f812 bl 1002d050 +1002e02c: 2800 cmp r0, #0 +1002e02e: d1f6 bne.n 1002e01e +1002e030: 4641 mov r1, r8 +1002e032: 4620 mov r0, r4 +1002e034: f7ff ff98 bl 1002df68 +1002e038: 4607 mov r7, r0 +1002e03a: 2f01 cmp r7, #1 +1002e03c: d124 bne.n 1002e088 +1002e03e: 2108 movs r1, #8 +1002e040: 4650 mov r0, sl +1002e042: f7fe ff66 bl 1002cf12 +1002e046: b1d0 cbz r0, 1002e07e +1002e048: f105 002c add.w r0, r5, #44 ; 0x2c +1002e04c: f7fe ff32 bl 1002ceb4 +1002e050: b9a8 cbnz r0, 1002e07e +1002e052: 7ce8 ldrb r0, [r5, #19] +1002e054: b198 cbz r0, 1002e07e +1002e056: 7ca8 ldrb r0, [r5, #18] +1002e058: 2800 cmp r0, #0 +1002e05a: bf1c itt ne +1002e05c: f8d6 035c ldrne.w r0, [r6, #860] ; 0x35c +1002e060: 2801 cmpne r0, #1 +1002e062: d10c bne.n 1002e07e +1002e064: 6870 ldr r0, [r6, #4] +1002e066: 2801 cmp r0, #1 +1002e068: bf18 it ne +1002e06a: 2805 cmpne r0, #5 +1002e06c: d007 beq.n 1002e07e +1002e06e: f896 0355 ldrb.w r0, [r6, #853] ; 0x355 +1002e072: b920 cbnz r0, 1002e07e +1002e074: 4649 mov r1, r9 +1002e076: 4640 mov r0, r8 +1002e078: f7ff f878 bl 1002d16c +1002e07c: e004 b.n 1002e088 +1002e07e: 4641 mov r1, r8 +1002e080: 4620 mov r0, r4 +1002e082: f7ff ff81 bl 1002df88 +1002e086: 4607 mov r7, r0 +1002e088: 4638 mov r0, r7 +1002e08a: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + +1002e08e : +1002e08e: b510 push {r4, lr} +1002e090: 4601 mov r1, r0 +1002e092: 6908 ldr r0, [r1, #16] +1002e094: f500 6432 add.w r4, r0, #2848 ; 0xb20 +1002e098: f894 25ec ldrb.w r2, [r4, #1516] ; 0x5ec +1002e09c: 2a00 cmp r2, #0 +1002e09e: bf1c itt ne +1002e0a0: e8bd 4010 ldmiane.w sp!, {r4, lr} +1002e0a4: f005 bba0 bne.w 100337e8 +1002e0a8: f7ff ffa1 bl 1002dfee +1002e0ac: b128 cbz r0, 1002e0ba +1002e0ae: e9d4 2312 ldrd r2, r3, [r4, #72] ; 0x48 +1002e0b2: f7ff fe52 bl 1002dd5a <.text_56> +1002e0b6: e9c4 2312 strd r2, r3, [r4, #72] ; 0x48 +1002e0ba: bd10 pop {r4, pc} + +1002e0bc : +1002e0bc: b570 push {r4, r5, r6, lr} +1002e0be: 4604 mov r4, r0 +1002e0c0: f20f 0044 addw r0, pc, #68 ; 0x44 +1002e0c4: f7e2 fd64 bl 10010b90 +1002e0c8: f641 459c movw r5, #7324 ; 0x1c9c +1002e0cc: 192e adds r6, r5, r4 +1002e0ce: e002 b.n 1002e0d6 +1002e0d0: 4620 mov r0, r4 +1002e0d2: f7f3 fca3 bl 10021a1c +1002e0d6: f504 50e0 add.w r0, r4, #7168 ; 0x1c00 +1002e0da: 30f4 adds r0, #244 ; 0xf4 +1002e0dc: f7e2 fbe6 bl 100108ac +1002e0e0: b138 cbz r0, 1002e0f2 +1002e0e2: 6e30 ldr r0, [r6, #96] ; 0x60 +1002e0e4: b928 cbnz r0, 1002e0f2 +1002e0e6: 5928 ldr r0, [r5, r4] +1002e0e8: 2801 cmp r0, #1 +1002e0ea: bf1c itt ne +1002e0ec: 6870 ldrne r0, [r6, #4] +1002e0ee: 2801 cmpne r0, #1 +1002e0f0: d1ee bne.n 1002e0d0 +1002e0f2: f504 50e0 add.w r0, r4, #7168 ; 0x1c00 +1002e0f6: 30f8 adds r0, #248 ; 0xf8 +1002e0f8: f7e2 fbc9 bl 1001088e +1002e0fc: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +1002e100: f7e2 bd4d b.w 10010b9e +1002e104: 0000 movs r0, r0 + ... + +1002e108 : +1002e108: 5452 5f57 4552 5643 545f 5341 4c4b 5445 RTW_RECV_TASKLET +1002e118: 0000 0000 .... + +1002e11c : +1002e11c: 3781 0000 .7.. + +1002e120 : +1002e120: f380 0000 .... + +1002e124 : +1002e124: aaaa 0003 0000 0000 ........ + +1002e12c : +1002e12c: aaaa 0003 f800 0000 ........ + +1002e134 : +1002e134: f8df f000 ldr.w pc, [pc] ; 1002e138 +1002e138: 00014295 .word 0x00014295 + +1002e13c : +1002e13c: f8df f000 ldr.w pc, [pc] ; 1002e140 +1002e140: 000142f5 .word 0x000142f5 + +1002e144 : +1002e144: f8df f000 ldr.w pc, [pc] ; 1002e148 +1002e148: 00014941 .word 0x00014941 + +1002e14c : +1002e14c: f8df f000 ldr.w pc, [pc] ; 1002e150 +1002e150: 000149d5 .word 0x000149d5 + +1002e154 : +1002e154: f8df f000 ldr.w pc, [pc] ; 1002e158 +1002e158: 00014e29 .word 0x00014e29 + +1002e15c : +1002e15c: f8df f000 ldr.w pc, [pc] ; 1002e160 +1002e160: 000151ad .word 0x000151ad + +1002e164 : +1002e164: 7800 ldrb r0, [r0, #0] +1002e166: 07c0 lsls r0, r0, #31 +1002e168: d501 bpl.n 1002e16e +1002e16a: 2001 movs r0, #1 +1002e16c: 4770 bx lr +1002e16e: 2000 movs r0, #0 +1002e170: 4770 bx lr + +1002e172 : +1002e172: b5f0 push {r4, r5, r6, r7, lr} +1002e174: b083 sub sp, #12 +1002e176: f8d1 4080 ldr.w r4, [r1, #128] ; 0x80 +1002e17a: f101 0308 add.w r3, r1, #8 +1002e17e: b1f4 cbz r4, 1002e1be +1002e180: 7d19 ldrb r1, [r3, #20] +1002e182: 2901 cmp r1, #1 +1002e184: bf18 it ne +1002e186: 2905 cmpne r1, #5 +1002e188: d119 bne.n 1002e1be +1002e18a: f241 15f8 movw r5, #4600 ; 0x11f8 +1002e18e: f241 273c movw r7, #4668 ; 0x123c +1002e192: 582d ldr r5, [r5, r0] +1002e194: 7d5a ldrb r2, [r3, #21] +1002e196: 8959 ldrh r1, [r3, #10] +1002e198: eb00 0685 add.w r6, r0, r5, lsl #2 +1002e19c: eb00 1005 add.w r0, r0, r5, lsl #4 +1002e1a0: 59be ldr r6, [r7, r6] +1002e1a2: 9601 str r6, [sp, #4] +1002e1a4: f500 5088 add.w r0, r0, #4352 ; 0x1100 +1002e1a8: 30fc adds r0, #252 ; 0xfc +1002e1aa: 9000 str r0, [sp, #0] +1002e1ac: 6918 ldr r0, [r3, #16] +1002e1ae: 7d9b ldrb r3, [r3, #22] +1002e1b0: 1a40 subs r0, r0, r1 +1002e1b2: 1a80 subs r0, r0, r2 +1002e1b4: 1ac3 subs r3, r0, r3 +1002e1b6: f104 0028 add.w r0, r4, #40 ; 0x28 +1002e1ba: f7ff ffbb bl 1002e134 +1002e1be: bdf7 pop {r0, r1, r2, r4, r5, r6, r7, pc} + +1002e1c0 : +1002e1c0: b57f push {r0, r1, r2, r3, r4, r5, r6, lr} +1002e1c2: 460c mov r4, r1 +1002e1c4: f104 031c add.w r3, r4, #28 +1002e1c8: 1d59 adds r1, r3, #5 +1002e1ca: 7b8a ldrb r2, [r1, #14] +1002e1cc: 2a01 cmp r2, #1 +1002e1ce: bf18 it ne +1002e1d0: 2a05 cmpne r2, #5 +1002e1d2: d115 bne.n 1002e200 +1002e1d4: 7bca ldrb r2, [r1, #15] +1002e1d6: 7959 ldrb r1, [r3, #5] +1002e1d8: f893 303c ldrb.w r3, [r3, #60] ; 0x3c +1002e1dc: ad03 add r5, sp, #12 +1002e1de: 9502 str r5, [sp, #8] +1002e1e0: f241 263c movw r6, #4668 ; 0x123c +1002e1e4: eb00 0583 add.w r5, r0, r3, lsl #2 +1002e1e8: eb00 1003 add.w r0, r0, r3, lsl #4 +1002e1ec: 5975 ldr r5, [r6, r5] +1002e1ee: 9501 str r5, [sp, #4] +1002e1f0: f500 5088 add.w r0, r0, #4352 ; 0x1100 +1002e1f4: 30fc adds r0, #252 ; 0xfc +1002e1f6: 9000 str r0, [sp, #0] +1002e1f8: f000 f87b bl 1002e2f2 <.text_8> +1002e1fc: f7ff ff9e bl 1002e13c +1002e200: bd7f pop {r0, r1, r2, r3, r4, r5, r6, pc} + +1002e202 : +1002e202: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1002e206: 4688 mov r8, r1 +1002e208: b084 sub sp, #16 +1002e20a: 4607 mov r7, r0 +1002e20c: f8d8 0080 ldr.w r0, [r8, #128] ; 0x80 +1002e210: f108 0508 add.w r5, r8, #8 +1002e214: 2601 movs r6, #1 +1002e216: b110 cbz r0, 1002e21e +1002e218: 7d28 ldrb r0, [r5, #20] +1002e21a: 2802 cmp r0, #2 +1002e21c: d001 beq.n 1002e222 +1002e21e: 2000 movs r0, #0 +1002e220: e02b b.n 1002e27a +1002e222: 6eac ldr r4, [r5, #104] ; 0x68 +1002e224: b934 cbnz r4, 1002e234 +1002e226: f507 5088 add.w r0, r7, #4352 ; 0x1100 +1002e22a: f105 014f add.w r1, r5, #79 ; 0x4f +1002e22e: f000 f868 bl 1002e302 <.text_9+0x4> +1002e232: 4604 mov r4, r0 +1002e234: f105 004f add.w r0, r5, #79 ; 0x4f +1002e238: f7ff ff94 bl 1002e164 +1002e23c: b128 cbz r0, 1002e24a +1002e23e: f241 2050 movw r0, #4688 ; 0x1250 +1002e242: 59c0 ldr r0, [r0, r7] +1002e244: f000 f84f bl 1002e2e6 <.text_7> +1002e248: e001 b.n 1002e24e +1002e24a: f504 709c add.w r0, r4, #312 ; 0x138 +1002e24e: b194 cbz r4, 1002e276 +1002e250: 7d6a ldrb r2, [r5, #21] +1002e252: 8969 ldrh r1, [r5, #10] +1002e254: 9000 str r0, [sp, #0] +1002e256: f105 0349 add.w r3, r5, #73 ; 0x49 +1002e25a: 9302 str r3, [sp, #8] +1002e25c: 2310 movs r3, #16 +1002e25e: 9301 str r3, [sp, #4] +1002e260: 6928 ldr r0, [r5, #16] +1002e262: 7dab ldrb r3, [r5, #22] +1002e264: 1a40 subs r0, r0, r1 +1002e266: 1a80 subs r0, r0, r2 +1002e268: 1ac3 subs r3, r0, r3 +1002e26a: f8d8 0080 ldr.w r0, [r8, #128] ; 0x80 +1002e26e: 3028 adds r0, #40 ; 0x28 +1002e270: f7ff ff68 bl 1002e144 +1002e274: e000 b.n 1002e278 +1002e276: 2600 movs r6, #0 +1002e278: 4630 mov r0, r6 +1002e27a: e07d b.n 1002e378 <.text_11> + +1002e27c : +1002e27c: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1002e280: 460c mov r4, r1 +1002e282: f104 051c add.w r5, r4, #28 +1002e286: 1d6e adds r6, r5, #5 +1002e288: b086 sub sp, #24 +1002e28a: 4607 mov r7, r0 +1002e28c: 7bb0 ldrb r0, [r6, #14] +1002e28e: 2802 cmp r0, #2 +1002e290: d10f bne.n 1002e2b2 +1002e292: f507 5088 add.w r0, r7, #4352 ; 0x1100 +1002e296: f000 f832 bl 1002e2fe <.text_9> +1002e29a: ea5f 0800 movs.w r8, r0 +1002e29e: d01f beq.n 1002e2e0 +1002e2a0: f105 002c add.w r0, r5, #44 ; 0x2c +1002e2a4: f7ff ff5e bl 1002e164 +1002e2a8: b150 cbz r0, 1002e2c0 +1002e2aa: f241 5044 movw r0, #5444 ; 0x1544 +1002e2ae: 5dc0 ldrb r0, [r0, r7] +1002e2b0: b908 cbnz r0, 1002e2b6 +1002e2b2: 2000 movs r0, #0 +1002e2b4: e014 b.n 1002e2e0 +1002e2b6: f895 003c ldrb.w r0, [r5, #60] ; 0x3c +1002e2ba: f000 f814 bl 1002e2e6 <.text_7> +1002e2be: e001 b.n 1002e2c4 +1002e2c0: f508 709c add.w r0, r8, #312 ; 0x138 +1002e2c4: 7bf2 ldrb r2, [r6, #15] +1002e2c6: 7969 ldrb r1, [r5, #5] +1002e2c8: 9000 str r0, [sp, #0] +1002e2ca: ab04 add r3, sp, #16 +1002e2cc: 9303 str r3, [sp, #12] +1002e2ce: f105 0326 add.w r3, r5, #38 ; 0x26 +1002e2d2: 9302 str r3, [sp, #8] +1002e2d4: 2310 movs r3, #16 +1002e2d6: 9301 str r3, [sp, #4] +1002e2d8: f000 f80b bl 1002e2f2 <.text_8> +1002e2dc: f7ff ff36 bl 1002e14c +1002e2e0: b006 add sp, #24 +1002e2e2: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +1002e2e6 <.text_7>: +1002e2e6: eb07 1000 add.w r0, r7, r0, lsl #4 +1002e2ea: f500 5090 add.w r0, r0, #4608 ; 0x1200 +1002e2ee: 3054 adds r0, #84 ; 0x54 +1002e2f0: 4770 bx lr + +1002e2f2 <.text_8>: +1002e2f2: 6fe0 ldr r0, [r4, #124] ; 0x7c +1002e2f4: 1a40 subs r0, r0, r1 +1002e2f6: 1a83 subs r3, r0, r2 +1002e2f8: f8d4 0084 ldr.w r0, [r4, #132] ; 0x84 +1002e2fc: 4770 bx lr + +1002e2fe <.text_9>: +1002e2fe: f105 0126 add.w r1, r5, #38 ; 0x26 +1002e302: 3028 adds r0, #40 ; 0x28 +1002e304: f7f6 bf52 b.w 100251ac + +1002e308 : +1002e308: e92d 41ff stmdb sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, lr} +1002e30c: f101 0408 add.w r4, r1, #8 +1002e310: f500 5788 add.w r7, r0, #4352 ; 0x1100 +1002e314: f8d1 1080 ldr.w r1, [r1, #128] ; 0x80 +1002e318: 37f0 adds r7, #240 ; 0xf0 +1002e31a: 2501 movs r5, #1 +1002e31c: b909 cbnz r1, 1002e322 +1002e31e: 2000 movs r0, #0 +1002e320: e02a b.n 1002e378 <.text_11> +1002e322: f101 0828 add.w r8, r1, #40 ; 0x28 +1002e326: 7d21 ldrb r1, [r4, #20] +1002e328: 2904 cmp r1, #4 +1002e32a: d124 bne.n 1002e376 +1002e32c: 6ea6 ldr r6, [r4, #104] ; 0x68 +1002e32e: b93e cbnz r6, 1002e340 +1002e330: f500 5088 add.w r0, r0, #4352 ; 0x1100 +1002e334: f104 014f add.w r1, r4, #79 ; 0x4f +1002e338: f7ff ffe3 bl 1002e302 <.text_9+0x4> +1002e33c: 0006 movs r6, r0 +1002e33e: d019 beq.n 1002e374 +1002e340: f104 004f add.w r0, r4, #79 ; 0x4f +1002e344: f7ff ff0e bl 1002e164 +1002e348: 2800 cmp r0, #0 +1002e34a: bf1d ittte ne +1002e34c: 6e38 ldrne r0, [r7, #96] ; 0x60 +1002e34e: eb07 1000 addne.w r0, r7, r0, lsl #4 +1002e352: f100 0364 addne.w r3, r0, #100 ; 0x64 +1002e356: f506 739c addeq.w r3, r6, #312 ; 0x138 +1002e35a: 8961 ldrh r1, [r4, #10] +1002e35c: f000 f847 bl 1002e3ee <.text_13> +1002e360: 6920 ldr r0, [r4, #16] +1002e362: 7d62 ldrb r2, [r4, #21] +1002e364: 1a40 subs r0, r0, r1 +1002e366: 1a80 subs r0, r0, r2 +1002e368: 7da2 ldrb r2, [r4, #22] +1002e36a: 1a82 subs r2, r0, r2 +1002e36c: 4640 mov r0, r8 +1002e36e: f7ff fef1 bl 1002e154 +1002e372: e000 b.n 1002e376 +1002e374: 2500 movs r5, #0 +1002e376: 4628 mov r0, r5 + +1002e378 <.text_11>: +1002e378: b004 add sp, #16 +1002e37a: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +1002e37e : +1002e37e: e92d 47ff stmdb sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, lr} +1002e382: 460c mov r4, r1 +1002e384: f104 051c add.w r5, r4, #28 +1002e388: f500 5188 add.w r1, r0, #4352 ; 0x1100 +1002e38c: 1d6e adds r6, r5, #5 +1002e38e: f101 09f0 add.w r9, r1, #240 ; 0xf0 +1002e392: 7bb1 ldrb r1, [r6, #14] +1002e394: f8d4 8084 ldr.w r8, [r4, #132] ; 0x84 +1002e398: 2701 movs r7, #1 +1002e39a: 2904 cmp r1, #4 +1002e39c: d123 bne.n 1002e3e6 +1002e39e: f500 5088 add.w r0, r0, #4352 ; 0x1100 +1002e3a2: f7ff ffac bl 1002e2fe <.text_9> +1002e3a6: ea5f 0a00 movs.w sl, r0 +1002e3aa: d01b beq.n 1002e3e4 +1002e3ac: f105 002c add.w r0, r5, #44 ; 0x2c +1002e3b0: f7ff fed8 bl 1002e164 +1002e3b4: b148 cbz r0, 1002e3ca +1002e3b6: f899 0354 ldrb.w r0, [r9, #852] ; 0x354 +1002e3ba: b198 cbz r0, 1002e3e4 +1002e3bc: f895 003c ldrb.w r0, [r5, #60] ; 0x3c +1002e3c0: eb09 1000 add.w r0, r9, r0, lsl #4 +1002e3c4: f100 0364 add.w r3, r0, #100 ; 0x64 +1002e3c8: e001 b.n 1002e3ce +1002e3ca: f50a 739c add.w r3, sl, #312 ; 0x138 +1002e3ce: 7969 ldrb r1, [r5, #5] +1002e3d0: f000 f80d bl 1002e3ee <.text_13> +1002e3d4: 6fe0 ldr r0, [r4, #124] ; 0x7c +1002e3d6: 7bf2 ldrb r2, [r6, #15] +1002e3d8: 1a40 subs r0, r0, r1 +1002e3da: 1a82 subs r2, r0, r2 +1002e3dc: 4640 mov r0, r8 +1002e3de: f7ff febd bl 1002e15c +1002e3e2: e000 b.n 1002e3e6 +1002e3e4: 2700 movs r7, #0 +1002e3e6: 4638 mov r0, r7 +1002e3e8: b004 add sp, #16 +1002e3ea: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + +1002e3ee <.text_13>: +1002e3ee: a802 add r0, sp, #8 +1002e3f0: 9001 str r0, [sp, #4] +1002e3f2: f898 0000 ldrb.w r0, [r8] +1002e3f6: f000 000c and.w r0, r0, #12 +1002e3fa: 9000 str r0, [sp, #0] +1002e3fc: 4770 bx lr + +1002e3fe : +1002e3fe: b5f8 push {r3, r4, r5, r6, r7, lr} +1002e400: f500 5488 add.w r4, r0, #4352 ; 0x1100 +1002e404: 6841 ldr r1, [r0, #4] +1002e406: 34f0 adds r4, #240 ; 0xf0 +1002e408: 2901 cmp r1, #1 +1002e40a: d00b beq.n 1002e424 +1002e40c: 2902 cmp r1, #2 +1002e40e: bf18 it ne +1002e410: 2905 cmpne r1, #5 +1002e412: d005 beq.n 1002e420 +1002e414: 2903 cmp r1, #3 +1002e416: d105 bne.n 1002e424 +1002e418: f641 5151 movw r1, #7505 ; 0x1d51 +1002e41c: 5c08 ldrb r0, [r1, r0] +1002e41e: b108 cbz r0, 1002e424 +1002e420: 2503 movs r5, #3 +1002e422: e000 b.n 1002e426 +1002e424: 2501 movs r5, #1 +1002e426: f44f 7646 mov.w r6, #792 ; 0x318 +1002e42a: fb06 f005 mul.w r0, r6, r5 +1002e42e: f504 67c5 add.w r7, r4, #1576 ; 0x628 +1002e432: 1d00 adds r0, r0, #4 +1002e434: 6078 str r0, [r7, #4] +1002e436: f7e2 f9cf bl 100107d8 +1002e43a: f8c4 0628 str.w r0, [r4, #1576] ; 0x628 +1002e43e: b188 cbz r0, 1002e464 +1002e440: f000 0103 and.w r1, r0, #3 +1002e444: 1a40 subs r0, r0, r1 +1002e446: 1d00 adds r0, r0, #4 +1002e448: 60b8 str r0, [r7, #8] +1002e44a: 2001 movs r0, #1 +1002e44c: e007 b.n 1002e45e +1002e44e: 68b9 ldr r1, [r7, #8] +1002e450: eb04 0280 add.w r2, r4, r0, lsl #2 +1002e454: fb06 1100 mla r1, r6, r0, r1 +1002e458: f8c2 1630 str.w r1, [r2, #1584] ; 0x630 +1002e45c: 1c40 adds r0, r0, #1 +1002e45e: 42a8 cmp r0, r5 +1002e460: dbf5 blt.n 1002e44e +1002e462: 2001 movs r0, #1 +1002e464: bdf2 pop {r1, r4, r5, r6, r7, pc} + +1002e466 : +1002e466: b538 push {r3, r4, r5, lr} +1002e468: 4604 mov r4, r0 +1002e46a: f8d4 0628 ldr.w r0, [r4, #1576] ; 0x628 +1002e46e: 2800 cmp r0, #0 +1002e470: bf1e ittt ne +1002e472: f504 65c5 addne.w r5, r4, #1576 ; 0x628 +1002e476: 6869 ldrne r1, [r5, #4] +1002e478: 2900 cmpne r1, #0 +1002e47a: d005 beq.n 1002e488 +1002e47c: f7e2 f9bb bl 100107f6 +1002e480: 2000 movs r0, #0 +1002e482: f8c4 0628 str.w r0, [r4, #1576] ; 0x628 +1002e486: 6068 str r0, [r5, #4] +1002e488: bd31 pop {r0, r4, r5, pc} + ... + +1002e48c <__iar_unaligned___aeabi_memcpy>: +1002e48c: b362 cbz r2, 1002e4e8 <__iar_unaligned___aeabi_memcpy4+0x3c> +1002e48e: 078b lsls r3, r1, #30 +1002e490: d008 beq.n 1002e4a4 <__iar_unaligned___aeabi_memcpy+0x18> +1002e492: 1e52 subs r2, r2, #1 +1002e494: f811 3b01 ldrb.w r3, [r1], #1 +1002e498: f800 3b01 strb.w r3, [r0], #1 +1002e49c: f000 8024 beq.w 1002e4e8 <__iar_unaligned___aeabi_memcpy4+0x3c> +1002e4a0: 078b lsls r3, r1, #30 +1002e4a2: d1f6 bne.n 1002e492 <__iar_unaligned___aeabi_memcpy+0x6> +1002e4a4: 0783 lsls r3, r0, #30 +1002e4a6: f040 8020 bne.w 1002e4ea <__iar_unaligned___aeabi_memcpy4+0x3e> +1002e4aa: bf00 nop + +1002e4ac <__iar_unaligned___aeabi_memcpy4>: +1002e4ac: 3a10 subs r2, #16 +1002e4ae: d307 bcc.n 1002e4c0 <__iar_unaligned___aeabi_memcpy4+0x14> +1002e4b0: b430 push {r4, r5} +1002e4b2: e8b1 1038 ldmia.w r1!, {r3, r4, r5, ip} +1002e4b6: 3a10 subs r2, #16 +1002e4b8: e8a0 1038 stmia.w r0!, {r3, r4, r5, ip} +1002e4bc: d2f9 bcs.n 1002e4b2 <__iar_unaligned___aeabi_memcpy4+0x6> +1002e4be: bc30 pop {r4, r5} +1002e4c0: 0753 lsls r3, r2, #29 +1002e4c2: bf24 itt cs +1002e4c4: e8b1 1008 ldmiacs.w r1!, {r3, ip} +1002e4c8: e8a0 1008 stmiacs.w r0!, {r3, ip} +1002e4cc: bf44 itt mi +1002e4ce: f851 3b04 ldrmi.w r3, [r1], #4 +1002e4d2: f840 3b04 strmi.w r3, [r0], #4 +1002e4d6: 07d2 lsls r2, r2, #31 +1002e4d8: bf24 itt cs +1002e4da: f831 2b02 ldrhcs.w r2, [r1], #2 +1002e4de: f820 2b02 strhcs.w r2, [r0], #2 +1002e4e2: bf44 itt mi +1002e4e4: 780b ldrbmi r3, [r1, #0] +1002e4e6: 7003 strbmi r3, [r0, #0] +1002e4e8: 4770 bx lr +1002e4ea: 3a08 subs r2, #8 +1002e4ec: d307 bcc.n 1002e4fe <__iar_unaligned___aeabi_memcpy4+0x52> +1002e4ee: e8b1 1008 ldmia.w r1!, {r3, ip} +1002e4f2: 3a08 subs r2, #8 +1002e4f4: f840 3b04 str.w r3, [r0], #4 +1002e4f8: f840 cb04 str.w ip, [r0], #4 +1002e4fc: d2f7 bcs.n 1002e4ee <__iar_unaligned___aeabi_memcpy4+0x42> +1002e4fe: 0753 lsls r3, r2, #29 +1002e500: e7e4 b.n 1002e4cc <__iar_unaligned___aeabi_memcpy4+0x20> + ... + +1002e504 : +1002e504: b510 push {r4, lr} +1002e506: f641 34a4 movw r4, #7076 ; 0x1ba4 +1002e50a: 5824 ldr r4, [r4, r0] +1002e50c: 2000 movs r0, #0 +1002e50e: 2a04 cmp r2, #4 +1002e510: da26 bge.n 1002e560 +1002e512: bb29 cbnz r1, 1002e560 +1002e514: 2128 movs r1, #40 ; 0x28 +1002e516: fb01 4102 mla r1, r1, r2, r4 +1002e51a: 220a movs r2, #10 +1002e51c: fb02 1103 mla r1, r2, r3, r1 +1002e520: f241 4287 movw r2, #5255 ; 0x1487 +1002e524: 9c02 ldr r4, [sp, #8] +1002e526: 1853 adds r3, r2, r1 +1002e528: 2c09 cmp r4, #9 +1002e52a: d819 bhi.n 1002e560 +1002e52c: e8df f004 tbb [pc, r4] +1002e530: 0b090705 .word 0x0b090705 +1002e534: 13110f0d .word 0x13110f0d +1002e538: 1715 .short 0x1715 +1002e53a: 5c50 ldrb r0, [r2, r1] +1002e53c: bd10 pop {r4, pc} +1002e53e: 7858 ldrb r0, [r3, #1] +1002e540: bd10 pop {r4, pc} +1002e542: 7898 ldrb r0, [r3, #2] +1002e544: bd10 pop {r4, pc} +1002e546: 78d8 ldrb r0, [r3, #3] +1002e548: bd10 pop {r4, pc} +1002e54a: 7918 ldrb r0, [r3, #4] +1002e54c: bd10 pop {r4, pc} +1002e54e: 7958 ldrb r0, [r3, #5] +1002e550: bd10 pop {r4, pc} +1002e552: 7998 ldrb r0, [r3, #6] +1002e554: bd10 pop {r4, pc} +1002e556: 79d8 ldrb r0, [r3, #7] +1002e558: bd10 pop {r4, pc} +1002e55a: 7a18 ldrb r0, [r3, #8] +1002e55c: bd10 pop {r4, pc} +1002e55e: 7a58 ldrb r0, [r3, #9] +1002e560: bd10 pop {r4, pc} + ... + +1002e564 : +1002e564: b510 push {r4, lr} +1002e566: f641 34a4 movw r4, #7076 ; 0x1ba4 +1002e56a: 2a04 cmp r2, #4 +1002e56c: 5824 ldr r4, [r4, r0] +1002e56e: da27 bge.n 1002e5c0 +1002e570: bb31 cbnz r1, 1002e5c0 +1002e572: 2128 movs r1, #40 ; 0x28 +1002e574: 9802 ldr r0, [sp, #8] +1002e576: fb01 4102 mla r1, r1, r2, r4 +1002e57a: 220a movs r2, #10 +1002e57c: fb02 1100 mla r1, r2, r0, r1 +1002e580: f241 4287 movw r2, #5255 ; 0x1487 +1002e584: 1854 adds r4, r2, r1 +1002e586: 9803 ldr r0, [sp, #12] +1002e588: 2b09 cmp r3, #9 +1002e58a: d819 bhi.n 1002e5c0 +1002e58c: e8df f003 tbb [pc, r3] +1002e590: 0b090705 .word 0x0b090705 +1002e594: 13110f0d .word 0x13110f0d +1002e598: 1715 .short 0x1715 +1002e59a: 5450 strb r0, [r2, r1] +1002e59c: bd10 pop {r4, pc} +1002e59e: 7060 strb r0, [r4, #1] +1002e5a0: bd10 pop {r4, pc} +1002e5a2: 70a0 strb r0, [r4, #2] +1002e5a4: bd10 pop {r4, pc} +1002e5a6: 70e0 strb r0, [r4, #3] +1002e5a8: bd10 pop {r4, pc} +1002e5aa: 7120 strb r0, [r4, #4] +1002e5ac: bd10 pop {r4, pc} +1002e5ae: 7160 strb r0, [r4, #5] +1002e5b0: bd10 pop {r4, pc} +1002e5b2: 71a0 strb r0, [r4, #6] +1002e5b4: bd10 pop {r4, pc} +1002e5b6: 71e0 strb r0, [r4, #7] +1002e5b8: bd10 pop {r4, pc} +1002e5ba: 7220 strb r0, [r4, #8] +1002e5bc: bd10 pop {r4, pc} +1002e5be: 7260 strb r0, [r4, #9] +1002e5c0: bd10 pop {r4, pc} + +1002e5c2 : +1002e5c2: b530 push {r4, r5, lr} +1002e5c4: b083 sub sp, #12 +1002e5c6: 4604 mov r4, r0 +1002e5c8: 2500 movs r5, #0 +1002e5ca: 2016 movs r0, #22 +1002e5cc: 9000 str r0, [sp, #0] +1002e5ce: 2300 movs r3, #0 +1002e5d0: 462a mov r2, r5 +1002e5d2: 2100 movs r1, #0 +1002e5d4: f000 fcc9 bl 1002ef6a <.text_38> +1002e5d8: b2c0 uxtb r0, r0 +1002e5da: 9001 str r0, [sp, #4] +1002e5dc: 462a mov r2, r5 +1002e5de: 2000 movs r0, #0 +1002e5e0: 9000 str r0, [sp, #0] +1002e5e2: 4603 mov r3, r0 +1002e5e4: 4601 mov r1, r0 +1002e5e6: 4620 mov r0, r4 +1002e5e8: f7ff ffbc bl 1002e564 +1002e5ec: 206c movs r0, #108 ; 0x6c +1002e5ee: f000 f8a8 bl 1002e742 <.text_12> +1002e5f2: b2c0 uxtb r0, r0 +1002e5f4: 9001 str r0, [sp, #4] +1002e5f6: 2301 movs r3, #1 +1002e5f8: f000 f8b6 bl 1002e768 <.text_15> +1002e5fc: 2087 movs r0, #135 ; 0x87 +1002e5fe: f000 f8a0 bl 1002e742 <.text_12> +1002e602: b2c0 uxtb r0, r0 +1002e604: 9001 str r0, [sp, #4] +1002e606: 2302 movs r3, #2 +1002e608: f000 f8ae bl 1002e768 <.text_15> +1002e60c: 208f movs r0, #143 ; 0x8f +1002e60e: f000 f88a bl 1002e726 <.text_10> +1002e612: b2c0 uxtb r0, r0 +1002e614: 9001 str r0, [sp, #4] +1002e616: 2303 movs r3, #3 +1002e618: f000 f89a bl 1002e750 <.text_13> +1002e61c: 2097 movs r0, #151 ; 0x97 +1002e61e: f000 f87b bl 1002e718 <.text_9> +1002e622: b2c0 uxtb r0, r0 +1002e624: 9001 str r0, [sp, #4] +1002e626: 2304 movs r3, #4 +1002e628: 2002 movs r0, #2 +1002e62a: f000 f892 bl 1002e752 <.text_13+0x2> +1002e62e: 20a7 movs r0, #167 ; 0xa7 +1002e630: f000 f887 bl 1002e742 <.text_12> +1002e634: b2c0 uxtb r0, r0 +1002e636: 9001 str r0, [sp, #4] +1002e638: 2306 movs r3, #6 +1002e63a: f000 f895 bl 1002e768 <.text_15> +1002e63e: 20b1 movs r0, #177 ; 0xb1 +1002e640: f000 f871 bl 1002e726 <.text_10> +1002e644: b2c0 uxtb r0, r0 +1002e646: 9001 str r0, [sp, #4] +1002e648: 2307 movs r3, #7 +1002e64a: f000 f881 bl 1002e750 <.text_13> +1002e64e: 20bb movs r0, #187 ; 0xbb +1002e650: f000 f862 bl 1002e718 <.text_9> +1002e654: b2c0 uxtb r0, r0 +1002e656: 9001 str r0, [sp, #4] +1002e658: 2308 movs r3, #8 +1002e65a: 2002 movs r0, #2 +1002e65c: f000 f879 bl 1002e752 <.text_13+0x2> +1002e660: 206c movs r0, #108 ; 0x6c +1002e662: f000 f867 bl 1002e734 <.text_11> +1002e666: b2c0 uxtb r0, r0 +1002e668: 9001 str r0, [sp, #4] +1002e66a: 2301 movs r3, #1 +1002e66c: 2000 movs r0, #0 +1002e66e: 9000 str r0, [sp, #0] +1002e670: 462a mov r2, r5 +1002e672: 4619 mov r1, r3 +1002e674: 4620 mov r0, r4 +1002e676: f7ff ff75 bl 1002e564 +1002e67a: 2087 movs r0, #135 ; 0x87 +1002e67c: f000 f85a bl 1002e734 <.text_11> +1002e680: b2c0 uxtb r0, r0 +1002e682: 9001 str r0, [sp, #4] +1002e684: 2302 movs r3, #2 +1002e686: f000 f869 bl 1002e75c <.text_14> +1002e68a: 208f movs r0, #143 ; 0x8f +1002e68c: f000 f83d bl 1002e70a <.text_8> +1002e690: b2c0 uxtb r0, r0 +1002e692: 9001 str r0, [sp, #4] +1002e694: 2303 movs r3, #3 +1002e696: f000 f825 bl 1002e6e4 <.text_5> +1002e69a: 2097 movs r0, #151 ; 0x97 +1002e69c: f000 f82e bl 1002e6fc <.text_7> +1002e6a0: b2c0 uxtb r0, r0 +1002e6a2: 9001 str r0, [sp, #4] +1002e6a4: 2304 movs r3, #4 +1002e6a6: f000 f823 bl 1002e6f0 <.text_6> +1002e6aa: 20a7 movs r0, #167 ; 0xa7 +1002e6ac: f000 f842 bl 1002e734 <.text_11> +1002e6b0: b2c0 uxtb r0, r0 +1002e6b2: 9001 str r0, [sp, #4] +1002e6b4: 2306 movs r3, #6 +1002e6b6: f000 f851 bl 1002e75c <.text_14> +1002e6ba: 20b1 movs r0, #177 ; 0xb1 +1002e6bc: f000 f825 bl 1002e70a <.text_8> +1002e6c0: b2c0 uxtb r0, r0 +1002e6c2: 9001 str r0, [sp, #4] +1002e6c4: 2307 movs r3, #7 +1002e6c6: f000 f80d bl 1002e6e4 <.text_5> +1002e6ca: 20b1 movs r0, #177 ; 0xb1 +1002e6cc: f000 f816 bl 1002e6fc <.text_7> +1002e6d0: b2c0 uxtb r0, r0 +1002e6d2: 9001 str r0, [sp, #4] +1002e6d4: 2308 movs r3, #8 +1002e6d6: f000 f80b bl 1002e6f0 <.text_6> +1002e6da: 1c6d adds r5, r5, #1 +1002e6dc: 2d02 cmp r5, #2 +1002e6de: f6ff af74 blt.w 1002e5ca +1002e6e2: bd37 pop {r0, r1, r2, r4, r5, pc} + +1002e6e4 <.text_5>: +1002e6e4: 2001 movs r0, #1 +1002e6e6: 9000 str r0, [sp, #0] +1002e6e8: 4601 mov r1, r0 +1002e6ea: 462a mov r2, r5 +1002e6ec: 4620 mov r0, r4 +1002e6ee: e739 b.n 1002e564 + +1002e6f0 <.text_6>: +1002e6f0: 2002 movs r0, #2 +1002e6f2: 9000 str r0, [sp, #0] +1002e6f4: 462a mov r2, r5 +1002e6f6: 2101 movs r1, #1 +1002e6f8: 4620 mov r0, r4 +1002e6fa: e733 b.n 1002e564 + +1002e6fc <.text_7>: +1002e6fc: 9000 str r0, [sp, #0] +1002e6fe: 2302 movs r3, #2 +1002e700: 462a mov r2, r5 +1002e702: 2101 movs r1, #1 +1002e704: 4620 mov r0, r4 +1002e706: f000 bf26 b.w 1002f556 + +1002e70a <.text_8>: +1002e70a: 9000 str r0, [sp, #0] +1002e70c: 2301 movs r3, #1 +1002e70e: 462a mov r2, r5 +1002e710: 4619 mov r1, r3 +1002e712: 4620 mov r0, r4 +1002e714: f000 bf1f b.w 1002f556 + +1002e718 <.text_9>: +1002e718: 9000 str r0, [sp, #0] +1002e71a: 2302 movs r3, #2 +1002e71c: 462a mov r2, r5 +1002e71e: 2100 movs r1, #0 +1002e720: 4620 mov r0, r4 +1002e722: f000 bf18 b.w 1002f556 + +1002e726 <.text_10>: +1002e726: 9000 str r0, [sp, #0] +1002e728: 2301 movs r3, #1 +1002e72a: 462a mov r2, r5 +1002e72c: 2100 movs r1, #0 +1002e72e: 4620 mov r0, r4 +1002e730: f000 bf11 b.w 1002f556 + +1002e734 <.text_11>: +1002e734: 9000 str r0, [sp, #0] +1002e736: 2300 movs r3, #0 +1002e738: 462a mov r2, r5 +1002e73a: 2101 movs r1, #1 +1002e73c: 4620 mov r0, r4 +1002e73e: f000 bf0a b.w 1002f556 + +1002e742 <.text_12>: +1002e742: 9000 str r0, [sp, #0] +1002e744: 2300 movs r3, #0 +1002e746: 462a mov r2, r5 +1002e748: 4619 mov r1, r3 +1002e74a: 4620 mov r0, r4 +1002e74c: f000 bf03 b.w 1002f556 + +1002e750 <.text_13>: +1002e750: 2001 movs r0, #1 +1002e752: 9000 str r0, [sp, #0] +1002e754: 462a mov r2, r5 +1002e756: 2100 movs r1, #0 +1002e758: 4620 mov r0, r4 +1002e75a: e703 b.n 1002e564 + +1002e75c <.text_14>: +1002e75c: 2000 movs r0, #0 +1002e75e: 9000 str r0, [sp, #0] +1002e760: 462a mov r2, r5 +1002e762: 2101 movs r1, #1 +1002e764: 4620 mov r0, r4 +1002e766: e6fd b.n 1002e564 + +1002e768 <.text_15>: +1002e768: 2000 movs r0, #0 +1002e76a: 9000 str r0, [sp, #0] +1002e76c: 4601 mov r1, r0 +1002e76e: 462a mov r2, r5 +1002e770: 4620 mov r0, r4 +1002e772: e6f7 b.n 1002e564 + +1002e774 : +1002e774: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1002e778: 250a movs r5, #10 +1002e77a: f44f 6003 mov.w r0, #2096 ; 0x830 +1002e77e: 9c06 ldr r4, [sp, #24] +1002e780: 9e07 ldr r6, [sp, #28] +1002e782: 9f08 ldr r7, [sp, #32] +1002e784: 1a09 subs r1, r1, r0 +1002e786: 4698 mov r8, r3 +1002e788: d036 beq.n 1002e7f8 +1002e78a: 1f09 subs r1, r1, #4 +1002e78c: d037 beq.n 1002e7fe +1002e78e: 1f09 subs r1, r1, #4 +1002e790: f000 813d beq.w 1002ea0e +1002e794: 1f09 subs r1, r1, #4 +1002e796: d038 beq.n 1002e80a +1002e798: 390c subs r1, #12 +1002e79a: d039 beq.n 1002e810 +1002e79c: 1f09 subs r1, r1, #4 +1002e79e: d03a beq.n 1002e816 +1002e7a0: 391c subs r1, #28 +1002e7a2: d03b beq.n 1002e81c +1002e7a4: 1f09 subs r1, r1, #4 +1002e7a6: f000 80dc beq.w 1002e962 +1002e7aa: f44f 706d mov.w r0, #948 ; 0x3b4 +1002e7ae: 1a09 subs r1, r1, r0 +1002e7b0: d037 beq.n 1002e822 +1002e7b2: 1f09 subs r1, r1, #4 +1002e7b4: d038 beq.n 1002e828 +1002e7b6: 1f09 subs r1, r1, #4 +1002e7b8: d039 beq.n 1002e82e +1002e7ba: 1f09 subs r1, r1, #4 +1002e7bc: d03a beq.n 1002e834 +1002e7be: 1f09 subs r1, r1, #4 +1002e7c0: d03b beq.n 1002e83a +1002e7c2: 1f09 subs r1, r1, #4 +1002e7c4: d03c beq.n 1002e840 +1002e7c6: 1f09 subs r1, r1, #4 +1002e7c8: d03d beq.n 1002e846 +1002e7ca: 1f09 subs r1, r1, #4 +1002e7cc: d03e beq.n 1002e84c +1002e7ce: 1f09 subs r1, r1, #4 +1002e7d0: d03f beq.n 1002e852 +1002e7d2: 1f09 subs r1, r1, #4 +1002e7d4: d040 beq.n 1002e858 +1002e7d6: 1f09 subs r1, r1, #4 +1002e7d8: d041 beq.n 1002e85e +1002e7da: 1f09 subs r1, r1, #4 +1002e7dc: d042 beq.n 1002e864 +1002e7de: 398c subs r1, #140 ; 0x8c +1002e7e0: d043 beq.n 1002e86a +1002e7e2: 1f09 subs r1, r1, #4 +1002e7e4: d044 beq.n 1002e870 +1002e7e6: 1f09 subs r1, r1, #4 +1002e7e8: d045 beq.n 1002e876 +1002e7ea: 1f09 subs r1, r1, #4 +1002e7ec: d046 beq.n 1002e87c +1002e7ee: 1f09 subs r1, r1, #4 +1002e7f0: d047 beq.n 1002e882 +1002e7f2: f44f 708c mov.w r0, #280 ; 0x118 +1002e7f6: 1a09 subs r1, r1, r0 +1002e7f8: f000 808e beq.w 1002e918 +1002e7fc: 1f09 subs r1, r1, #4 +1002e7fe: f000 8099 beq.w 1002e934 +1002e802: 1f09 subs r1, r1, #4 +1002e804: f000 80a4 beq.w 1002e950 +1002e808: 3908 subs r1, #8 +1002e80a: f000 80c8 beq.w 1002e99e +1002e80e: 1f09 subs r1, r1, #4 +1002e810: f000 80d3 beq.w 1002e9ba +1002e814: 1f09 subs r1, r1, #4 +1002e816: f000 80de beq.w 1002e9d6 +1002e81a: 1f09 subs r1, r1, #4 +1002e81c: f000 80e9 beq.w 1002e9f2 +1002e820: 1f09 subs r1, r1, #4 +1002e822: f000 80ff beq.w 1002ea24 +1002e826: 1f09 subs r1, r1, #4 +1002e828: f000 8106 beq.w 1002ea38 +1002e82c: 1f09 subs r1, r1, #4 +1002e82e: f000 8111 beq.w 1002ea54 +1002e832: 1f09 subs r1, r1, #4 +1002e834: f000 811c beq.w 1002ea70 +1002e838: 1f09 subs r1, r1, #4 +1002e83a: f000 8127 beq.w 1002ea8c +1002e83e: 1f09 subs r1, r1, #4 +1002e840: f000 8132 beq.w 1002eaa8 +1002e844: 1f09 subs r1, r1, #4 +1002e846: f000 813d beq.w 1002eac4 +1002e84a: 1f09 subs r1, r1, #4 +1002e84c: f000 8148 beq.w 1002eae0 +1002e850: 1f09 subs r1, r1, #4 +1002e852: f000 8153 beq.w 1002eafc +1002e856: 1f09 subs r1, r1, #4 +1002e858: f000 815e beq.w 1002eb18 +1002e85c: 1f09 subs r1, r1, #4 +1002e85e: f000 8169 beq.w 1002eb34 +1002e862: 1f09 subs r1, r1, #4 +1002e864: f000 8174 beq.w 1002eb50 +1002e868: 398c subs r1, #140 ; 0x8c +1002e86a: f000 817f beq.w 1002eb6c +1002e86e: 1f09 subs r1, r1, #4 +1002e870: f000 818a beq.w 1002eb88 +1002e874: 1f09 subs r1, r1, #4 +1002e876: f000 8195 beq.w 1002eba4 +1002e87a: 1f09 subs r1, r1, #4 +1002e87c: f000 81a0 beq.w 1002ebc0 +1002e880: 1f09 subs r1, r1, #4 +1002e882: f000 81b3 beq.w 1002ebec +1002e886: f640 1038 movw r0, #2360 ; 0x938 +1002e88a: 1a09 subs r1, r1, r0 +1002e88c: d0c9 beq.n 1002e822 +1002e88e: 1f09 subs r1, r1, #4 +1002e890: d0ca beq.n 1002e828 +1002e892: 1f09 subs r1, r1, #4 +1002e894: d0cb beq.n 1002e82e +1002e896: 1f09 subs r1, r1, #4 +1002e898: d0cc beq.n 1002e834 +1002e89a: 1f09 subs r1, r1, #4 +1002e89c: d0cd beq.n 1002e83a +1002e89e: 1f09 subs r1, r1, #4 +1002e8a0: d0ce beq.n 1002e840 +1002e8a2: 1f09 subs r1, r1, #4 +1002e8a4: d0cf beq.n 1002e846 +1002e8a6: 1f09 subs r1, r1, #4 +1002e8a8: d0d0 beq.n 1002e84c +1002e8aa: 1f09 subs r1, r1, #4 +1002e8ac: d0d1 beq.n 1002e852 +1002e8ae: 1f09 subs r1, r1, #4 +1002e8b0: d0d2 beq.n 1002e858 +1002e8b2: 1f09 subs r1, r1, #4 +1002e8b4: d0d3 beq.n 1002e85e +1002e8b6: 1f09 subs r1, r1, #4 +1002e8b8: d0d4 beq.n 1002e864 +1002e8ba: 398c subs r1, #140 ; 0x8c +1002e8bc: d0d5 beq.n 1002e86a +1002e8be: 1f09 subs r1, r1, #4 +1002e8c0: d0d6 beq.n 1002e870 +1002e8c2: 1f09 subs r1, r1, #4 +1002e8c4: d0d7 beq.n 1002e876 +1002e8c6: 1f09 subs r1, r1, #4 +1002e8c8: d0d8 beq.n 1002e87c +1002e8ca: 1f09 subs r1, r1, #4 +1002e8cc: d0d9 beq.n 1002e882 +1002e8ce: f44f 709c mov.w r0, #312 ; 0x138 +1002e8d2: 1a09 subs r1, r1, r0 +1002e8d4: d0a5 beq.n 1002e822 +1002e8d6: 1f09 subs r1, r1, #4 +1002e8d8: d0a6 beq.n 1002e828 +1002e8da: 1f09 subs r1, r1, #4 +1002e8dc: d0a7 beq.n 1002e82e +1002e8de: 1f09 subs r1, r1, #4 +1002e8e0: d0a8 beq.n 1002e834 +1002e8e2: 1f09 subs r1, r1, #4 +1002e8e4: d0a9 beq.n 1002e83a +1002e8e6: 1f09 subs r1, r1, #4 +1002e8e8: d0aa beq.n 1002e840 +1002e8ea: 1f09 subs r1, r1, #4 +1002e8ec: d0ab beq.n 1002e846 +1002e8ee: 1f09 subs r1, r1, #4 +1002e8f0: d0ac beq.n 1002e84c +1002e8f2: 1f09 subs r1, r1, #4 +1002e8f4: d0ad beq.n 1002e852 +1002e8f6: 1f09 subs r1, r1, #4 +1002e8f8: d0ae beq.n 1002e858 +1002e8fa: 1f09 subs r1, r1, #4 +1002e8fc: d0af beq.n 1002e85e +1002e8fe: 1f09 subs r1, r1, #4 +1002e900: d0b0 beq.n 1002e864 +1002e902: 398c subs r1, #140 ; 0x8c +1002e904: d0b1 beq.n 1002e86a +1002e906: 1f09 subs r1, r1, #4 +1002e908: d0b2 beq.n 1002e870 +1002e90a: 1f09 subs r1, r1, #4 +1002e90c: d0b3 beq.n 1002e876 +1002e90e: 1f09 subs r1, r1, #4 +1002e910: d0b4 beq.n 1002e87c +1002e912: 1f09 subs r1, r1, #4 +1002e914: d0b5 beq.n 1002e882 +1002e916: e178 b.n 1002ec0a +1002e918: 200c movs r0, #12 +1002e91a: f000 fc7c bl 1002f216 +1002e91e: 7020 strb r0, [r4, #0] +1002e920: 2012 movs r0, #18 +1002e922: f000 fc78 bl 1002f216 +1002e926: 7060 strb r0, [r4, #1] +1002e928: 2018 movs r0, #24 +1002e92a: f000 fc74 bl 1002f216 +1002e92e: 70a0 strb r0, [r4, #2] +1002e930: 2024 movs r0, #36 ; 0x24 +1002e932: e152 b.n 1002ebda +1002e934: 2030 movs r0, #48 ; 0x30 +1002e936: f000 fc6e bl 1002f216 +1002e93a: 7020 strb r0, [r4, #0] +1002e93c: 2048 movs r0, #72 ; 0x48 +1002e93e: f000 fc6a bl 1002f216 +1002e942: 7060 strb r0, [r4, #1] +1002e944: 2060 movs r0, #96 ; 0x60 +1002e946: f000 fc66 bl 1002f216 +1002e94a: 70a0 strb r0, [r4, #2] +1002e94c: 206c movs r0, #108 ; 0x6c +1002e94e: e144 b.n 1002ebda +1002e950: 2002 movs r0, #2 +1002e952: f000 fc60 bl 1002f216 +1002e956: 7020 strb r0, [r4, #0] +1002e958: f3c8 2103 ubfx r1, r8, #8, #4 +1002e95c: f3c8 3003 ubfx r0, r8, #12, #4 +1002e960: e018 b.n 1002e994 +1002e962: f512 7f80 cmn.w r2, #256 ; 0x100 +1002e966: d10b bne.n 1002e980 +1002e968: f000 f965 bl 1002ec36 <.text_19+0x2> +1002e96c: 7020 strb r0, [r4, #0] +1002e96e: f000 f95f bl 1002ec30 <.text_18+0x2> +1002e972: 7060 strb r0, [r4, #1] +1002e974: 2016 movs r0, #22 +1002e976: f000 fc4e bl 1002f216 +1002e97a: f000 f95e bl 1002ec3a <.text_20> +1002e97e: e04f b.n 1002ea20 +1002e980: 2aff cmp r2, #255 ; 0xff +1002e982: d1c8 bne.n 1002e916 +1002e984: 2016 movs r0, #22 +1002e986: f000 fc46 bl 1002f216 +1002e98a: 7020 strb r0, [r4, #0] +1002e98c: f008 010f and.w r1, r8, #15 +1002e990: f3c8 1003 ubfx r0, r8, #4, #4 +1002e994: fb05 1000 mla r0, r5, r0, r1 +1002e998: 7030 strb r0, [r6, #0] +1002e99a: 2001 movs r0, #1 +1002e99c: e134 b.n 1002ec08 +1002e99e: 2080 movs r0, #128 ; 0x80 +1002e9a0: f000 fc39 bl 1002f216 +1002e9a4: 7020 strb r0, [r4, #0] +1002e9a6: 2081 movs r0, #129 ; 0x81 +1002e9a8: f000 fc35 bl 1002f216 +1002e9ac: 7060 strb r0, [r4, #1] +1002e9ae: 2082 movs r0, #130 ; 0x82 +1002e9b0: f000 fc31 bl 1002f216 +1002e9b4: 70a0 strb r0, [r4, #2] +1002e9b6: 2083 movs r0, #131 ; 0x83 +1002e9b8: e10f b.n 1002ebda +1002e9ba: 2084 movs r0, #132 ; 0x84 +1002e9bc: f000 fc2b bl 1002f216 +1002e9c0: 7020 strb r0, [r4, #0] +1002e9c2: 2085 movs r0, #133 ; 0x85 +1002e9c4: f000 fc27 bl 1002f216 +1002e9c8: 7060 strb r0, [r4, #1] +1002e9ca: 2086 movs r0, #134 ; 0x86 +1002e9cc: f000 fc23 bl 1002f216 +1002e9d0: 70a0 strb r0, [r4, #2] +1002e9d2: 2087 movs r0, #135 ; 0x87 +1002e9d4: e101 b.n 1002ebda +1002e9d6: 2088 movs r0, #136 ; 0x88 +1002e9d8: f000 fc1d bl 1002f216 +1002e9dc: 7020 strb r0, [r4, #0] +1002e9de: 2089 movs r0, #137 ; 0x89 +1002e9e0: f000 fc19 bl 1002f216 +1002e9e4: 7060 strb r0, [r4, #1] +1002e9e6: 208a movs r0, #138 ; 0x8a +1002e9e8: f000 fc15 bl 1002f216 +1002e9ec: 70a0 strb r0, [r4, #2] +1002e9ee: 208b movs r0, #139 ; 0x8b +1002e9f0: e0f3 b.n 1002ebda +1002e9f2: 208c movs r0, #140 ; 0x8c +1002e9f4: f000 fc0f bl 1002f216 +1002e9f8: 7020 strb r0, [r4, #0] +1002e9fa: 208d movs r0, #141 ; 0x8d +1002e9fc: f000 fc0b bl 1002f216 +1002ea00: 7060 strb r0, [r4, #1] +1002ea02: 208e movs r0, #142 ; 0x8e +1002ea04: f000 fc07 bl 1002f216 +1002ea08: 70a0 strb r0, [r4, #2] +1002ea0a: 208f movs r0, #143 ; 0x8f +1002ea0c: e0e5 b.n 1002ebda +1002ea0e: 2002 movs r0, #2 +1002ea10: f000 fc01 bl 1002f216 +1002ea14: f000 f90e bl 1002ec34 <.text_19> +1002ea18: f000 f909 bl 1002ec2e <.text_18> +1002ea1c: f000 f90d bl 1002ec3a <.text_20> +1002ea20: 2003 movs r0, #3 +1002ea22: e0f1 b.n 1002ec08 +1002ea24: 2002 movs r0, #2 +1002ea26: f000 fbf6 bl 1002f216 +1002ea2a: f000 f903 bl 1002ec34 <.text_19> +1002ea2e: f000 f8fe bl 1002ec2e <.text_18> +1002ea32: 70a0 strb r0, [r4, #2] +1002ea34: 2016 movs r0, #22 +1002ea36: e0d0 b.n 1002ebda +1002ea38: 200c movs r0, #12 +1002ea3a: f000 fbec bl 1002f216 +1002ea3e: 7020 strb r0, [r4, #0] +1002ea40: 2012 movs r0, #18 +1002ea42: f000 fbe8 bl 1002f216 +1002ea46: 7060 strb r0, [r4, #1] +1002ea48: 2018 movs r0, #24 +1002ea4a: f000 fbe4 bl 1002f216 +1002ea4e: 70a0 strb r0, [r4, #2] +1002ea50: 2024 movs r0, #36 ; 0x24 +1002ea52: e0c2 b.n 1002ebda +1002ea54: 2030 movs r0, #48 ; 0x30 +1002ea56: f000 fbde bl 1002f216 +1002ea5a: 7020 strb r0, [r4, #0] +1002ea5c: 2048 movs r0, #72 ; 0x48 +1002ea5e: f000 fbda bl 1002f216 +1002ea62: 7060 strb r0, [r4, #1] +1002ea64: 2060 movs r0, #96 ; 0x60 +1002ea66: f000 fbd6 bl 1002f216 +1002ea6a: 70a0 strb r0, [r4, #2] +1002ea6c: 206c movs r0, #108 ; 0x6c +1002ea6e: e0b4 b.n 1002ebda +1002ea70: 2080 movs r0, #128 ; 0x80 +1002ea72: f000 fbd0 bl 1002f216 +1002ea76: 7020 strb r0, [r4, #0] +1002ea78: 2081 movs r0, #129 ; 0x81 +1002ea7a: f000 fbcc bl 1002f216 +1002ea7e: 7060 strb r0, [r4, #1] +1002ea80: 2082 movs r0, #130 ; 0x82 +1002ea82: f000 fbc8 bl 1002f216 +1002ea86: 70a0 strb r0, [r4, #2] +1002ea88: 2083 movs r0, #131 ; 0x83 +1002ea8a: e0a6 b.n 1002ebda +1002ea8c: 2084 movs r0, #132 ; 0x84 +1002ea8e: f000 fbc2 bl 1002f216 +1002ea92: 7020 strb r0, [r4, #0] +1002ea94: 2085 movs r0, #133 ; 0x85 +1002ea96: f000 fbbe bl 1002f216 +1002ea9a: 7060 strb r0, [r4, #1] +1002ea9c: 2086 movs r0, #134 ; 0x86 +1002ea9e: f000 fbba bl 1002f216 +1002eaa2: 70a0 strb r0, [r4, #2] +1002eaa4: 2087 movs r0, #135 ; 0x87 +1002eaa6: e098 b.n 1002ebda +1002eaa8: 2088 movs r0, #136 ; 0x88 +1002eaaa: f000 fbb4 bl 1002f216 +1002eaae: 7020 strb r0, [r4, #0] +1002eab0: 2089 movs r0, #137 ; 0x89 +1002eab2: f000 fbb0 bl 1002f216 +1002eab6: 7060 strb r0, [r4, #1] +1002eab8: 208a movs r0, #138 ; 0x8a +1002eaba: f000 fbac bl 1002f216 +1002eabe: 70a0 strb r0, [r4, #2] +1002eac0: 208b movs r0, #139 ; 0x8b +1002eac2: e08a b.n 1002ebda +1002eac4: 208c movs r0, #140 ; 0x8c +1002eac6: f000 fba6 bl 1002f216 +1002eaca: 7020 strb r0, [r4, #0] +1002eacc: 208d movs r0, #141 ; 0x8d +1002eace: f000 fba2 bl 1002f216 +1002ead2: 7060 strb r0, [r4, #1] +1002ead4: 208e movs r0, #142 ; 0x8e +1002ead6: f000 fb9e bl 1002f216 +1002eada: 70a0 strb r0, [r4, #2] +1002eadc: 208f movs r0, #143 ; 0x8f +1002eade: e07c b.n 1002ebda +1002eae0: 20a0 movs r0, #160 ; 0xa0 +1002eae2: f000 fb98 bl 1002f216 +1002eae6: 7020 strb r0, [r4, #0] +1002eae8: 20a1 movs r0, #161 ; 0xa1 +1002eaea: f000 fb94 bl 1002f216 +1002eaee: 7060 strb r0, [r4, #1] +1002eaf0: 20a2 movs r0, #162 ; 0xa2 +1002eaf2: f000 fb90 bl 1002f216 +1002eaf6: 70a0 strb r0, [r4, #2] +1002eaf8: 20a3 movs r0, #163 ; 0xa3 +1002eafa: e06e b.n 1002ebda +1002eafc: 20a4 movs r0, #164 ; 0xa4 +1002eafe: f000 fb8a bl 1002f216 +1002eb02: 7020 strb r0, [r4, #0] +1002eb04: 20a5 movs r0, #165 ; 0xa5 +1002eb06: f000 fb86 bl 1002f216 +1002eb0a: 7060 strb r0, [r4, #1] +1002eb0c: 20a6 movs r0, #166 ; 0xa6 +1002eb0e: f000 fb82 bl 1002f216 +1002eb12: 70a0 strb r0, [r4, #2] +1002eb14: 20a7 movs r0, #167 ; 0xa7 +1002eb16: e060 b.n 1002ebda +1002eb18: 20a8 movs r0, #168 ; 0xa8 +1002eb1a: f000 fb7c bl 1002f216 +1002eb1e: 7020 strb r0, [r4, #0] +1002eb20: 20a9 movs r0, #169 ; 0xa9 +1002eb22: f000 fb78 bl 1002f216 +1002eb26: 7060 strb r0, [r4, #1] +1002eb28: 20aa movs r0, #170 ; 0xaa +1002eb2a: f000 fb74 bl 1002f216 +1002eb2e: 70a0 strb r0, [r4, #2] +1002eb30: 20ab movs r0, #171 ; 0xab +1002eb32: e052 b.n 1002ebda +1002eb34: 20ac movs r0, #172 ; 0xac +1002eb36: f000 fb6e bl 1002f216 +1002eb3a: 7020 strb r0, [r4, #0] +1002eb3c: 20ad movs r0, #173 ; 0xad +1002eb3e: f000 fb6a bl 1002f216 +1002eb42: 7060 strb r0, [r4, #1] +1002eb44: 20ae movs r0, #174 ; 0xae +1002eb46: f000 fb66 bl 1002f216 +1002eb4a: 70a0 strb r0, [r4, #2] +1002eb4c: 20af movs r0, #175 ; 0xaf +1002eb4e: e044 b.n 1002ebda +1002eb50: 20b0 movs r0, #176 ; 0xb0 +1002eb52: f000 fb60 bl 1002f216 +1002eb56: 7020 strb r0, [r4, #0] +1002eb58: 20b1 movs r0, #177 ; 0xb1 +1002eb5a: f000 fb5c bl 1002f216 +1002eb5e: 7060 strb r0, [r4, #1] +1002eb60: 20b2 movs r0, #178 ; 0xb2 +1002eb62: f000 fb58 bl 1002f216 +1002eb66: 70a0 strb r0, [r4, #2] +1002eb68: 20b3 movs r0, #179 ; 0xb3 +1002eb6a: e036 b.n 1002ebda +1002eb6c: 2090 movs r0, #144 ; 0x90 +1002eb6e: f000 fb52 bl 1002f216 +1002eb72: 7020 strb r0, [r4, #0] +1002eb74: 2091 movs r0, #145 ; 0x91 +1002eb76: f000 fb4e bl 1002f216 +1002eb7a: 7060 strb r0, [r4, #1] +1002eb7c: 2092 movs r0, #146 ; 0x92 +1002eb7e: f000 fb4a bl 1002f216 +1002eb82: 70a0 strb r0, [r4, #2] +1002eb84: 2093 movs r0, #147 ; 0x93 +1002eb86: e028 b.n 1002ebda +1002eb88: 2094 movs r0, #148 ; 0x94 +1002eb8a: f000 fb44 bl 1002f216 +1002eb8e: 7020 strb r0, [r4, #0] +1002eb90: 2095 movs r0, #149 ; 0x95 +1002eb92: f000 fb40 bl 1002f216 +1002eb96: 7060 strb r0, [r4, #1] +1002eb98: 2096 movs r0, #150 ; 0x96 +1002eb9a: f000 fb3c bl 1002f216 +1002eb9e: 70a0 strb r0, [r4, #2] +1002eba0: 2097 movs r0, #151 ; 0x97 +1002eba2: e01a b.n 1002ebda +1002eba4: 20b4 movs r0, #180 ; 0xb4 +1002eba6: f000 fb36 bl 1002f216 +1002ebaa: 7020 strb r0, [r4, #0] +1002ebac: 20b5 movs r0, #181 ; 0xb5 +1002ebae: f000 fb32 bl 1002f216 +1002ebb2: 7060 strb r0, [r4, #1] +1002ebb4: 20b6 movs r0, #182 ; 0xb6 +1002ebb6: f000 fb2e bl 1002f216 +1002ebba: 70a0 strb r0, [r4, #2] +1002ebbc: 20b7 movs r0, #183 ; 0xb7 +1002ebbe: e00c b.n 1002ebda +1002ebc0: 20b8 movs r0, #184 ; 0xb8 +1002ebc2: f000 fb28 bl 1002f216 +1002ebc6: 7020 strb r0, [r4, #0] +1002ebc8: 20b9 movs r0, #185 ; 0xb9 +1002ebca: f000 fb24 bl 1002f216 +1002ebce: 7060 strb r0, [r4, #1] +1002ebd0: 20ba movs r0, #186 ; 0xba +1002ebd2: f000 fb20 bl 1002f216 +1002ebd6: 70a0 strb r0, [r4, #2] +1002ebd8: 20bb movs r0, #187 ; 0xbb +1002ebda: f000 fb1c bl 1002f216 +1002ebde: 70e0 strb r0, [r4, #3] +1002ebe0: 2000 movs r0, #0 +1002ebe2: f000 f814 bl 1002ec0e <.text_17> +1002ebe6: 2804 cmp r0, #4 +1002ebe8: dbfb blt.n 1002ebe2 +1002ebea: e00c b.n 1002ec06 +1002ebec: 20bc movs r0, #188 ; 0xbc +1002ebee: f000 fb12 bl 1002f216 +1002ebf2: 7020 strb r0, [r4, #0] +1002ebf4: 20bd movs r0, #189 ; 0xbd +1002ebf6: f000 fb0e bl 1002f216 +1002ebfa: 7060 strb r0, [r4, #1] +1002ebfc: 2000 movs r0, #0 +1002ebfe: f000 f806 bl 1002ec0e <.text_17> +1002ec02: 2802 cmp r0, #2 +1002ec04: dbfb blt.n 1002ebfe +1002ec06: 2004 movs r0, #4 +1002ec08: 7038 strb r0, [r7, #0] +1002ec0a: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +1002ec0e <.text_17>: +1002ec0e: 00c1 lsls r1, r0, #3 +1002ec10: 1d09 adds r1, r1, #4 +1002ec12: fa28 f201 lsr.w r2, r8, r1 +1002ec16: f002 010f and.w r1, r2, #15 +1002ec1a: 00c2 lsls r2, r0, #3 +1002ec1c: fa28 f302 lsr.w r3, r8, r2 +1002ec20: f003 020f and.w r2, r3, #15 +1002ec24: fb05 2101 mla r1, r5, r1, r2 +1002ec28: 5581 strb r1, [r0, r6] +1002ec2a: 1c40 adds r0, r0, #1 +1002ec2c: 4770 bx lr + +1002ec2e <.text_18>: +1002ec2e: 7060 strb r0, [r4, #1] +1002ec30: 200b movs r0, #11 +1002ec32: e2f0 b.n 1002f216 + +1002ec34 <.text_19>: +1002ec34: 7020 strb r0, [r4, #0] +1002ec36: 2004 movs r0, #4 +1002ec38: e2ed b.n 1002f216 + +1002ec3a <.text_20>: +1002ec3a: 70a0 strb r0, [r4, #2] +1002ec3c: 2001 movs r0, #1 +1002ec3e: 00c1 lsls r1, r0, #3 +1002ec40: 1d09 adds r1, r1, #4 +1002ec42: fa28 f201 lsr.w r2, r8, r1 +1002ec46: f002 010f and.w r1, r2, #15 +1002ec4a: 00c2 lsls r2, r0, #3 +1002ec4c: fa28 f302 lsr.w r3, r8, r2 +1002ec50: f003 020f and.w r2, r3, #15 +1002ec54: fb05 2101 mla r1, r5, r1, r2 +1002ec58: 1982 adds r2, r0, r6 +1002ec5a: 1c40 adds r0, r0, #1 +1002ec5c: 2804 cmp r0, #4 +1002ec5e: f802 1c01 strb.w r1, [r2, #-1] +1002ec62: dbec blt.n 1002ec3e <.text_20+0x4> +1002ec64: 4770 bx lr + +1002ec66 : +1002ec66: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} +1002ec6a: 460c mov r4, r1 +1002ec6c: f641 31a4 movw r1, #7076 ; 0x1ba4 +1002ec70: b087 sub sp, #28 +1002ec72: f851 8000 ldr.w r8, [r1, r0] +1002ec76: 4615 mov r5, r2 +1002ec78: a905 add r1, sp, #20 +1002ec7a: 2200 movs r2, #0 +1002ec7c: 600a str r2, [r1, #0] +1002ec7e: a904 add r1, sp, #16 +1002ec80: f88d 200c strb.w r2, [sp, #12] +1002ec84: 600a str r2, [r1, #0] +1002ec86: a903 add r1, sp, #12 +1002ec88: 9102 str r1, [sp, #8] +1002ec8a: 461e mov r6, r3 +1002ec8c: a904 add r1, sp, #16 +1002ec8e: 9101 str r1, [sp, #4] +1002ec90: a905 add r1, sp, #20 +1002ec92: 9100 str r1, [sp, #0] +1002ec94: 9b10 ldr r3, [sp, #64] ; 0x40 +1002ec96: 9a0f ldr r2, [sp, #60] ; 0x3c +1002ec98: 990e ldr r1, [sp, #56] ; 0x38 +1002ec9a: f7ff fd6b bl 1002e774 +1002ec9e: 2c00 cmp r4, #0 +1002eca0: bf18 it ne +1002eca2: 2c01 cmpne r4, #1 +1002eca4: d129 bne.n 1002ecfa +1002eca6: 2d04 cmp r5, #4 +1002eca8: bf38 it cc +1002ecaa: 2e04 cmpcc r6, #4 +1002ecac: d225 bcs.n 1002ecfa +1002ecae: 2700 movs r7, #0 +1002ecb0: e01f b.n 1002ecf2 +1002ecb2: a805 add r0, sp, #20 +1002ecb4: f817 9000 ldrb.w r9, [r7, r0] +1002ecb8: 20aa movs r0, #170 ; 0xaa +1002ecba: f000 faac bl 1002f216 +1002ecbe: 4581 cmp r9, r0 +1002ecc0: d004 beq.n 1002eccc +1002ecc2: 20ab movs r0, #171 ; 0xab +1002ecc4: f000 faa7 bl 1002f216 +1002ecc8: 4581 cmp r9, r0 +1002ecca: d100 bne.n 1002ecce +1002eccc: 2601 movs r6, #1 +1002ecce: f44f 60a8 mov.w r0, #1344 ; 0x540 +1002ecd2: fb00 8004 mla r0, r0, r4, r8 +1002ecd6: f44f 71a8 mov.w r1, #336 ; 0x150 +1002ecda: fb01 0005 mla r0, r1, r5, r0 +1002ecde: 2154 movs r1, #84 ; 0x54 +1002ece0: fb01 0006 mla r0, r1, r6, r0 +1002ece4: a904 add r1, sp, #16 +1002ece6: 4448 add r0, r9 +1002ece8: 5c79 ldrb r1, [r7, r1] +1002ecea: f880 10bb strb.w r1, [r0, #187] ; 0xbb +1002ecee: 1c78 adds r0, r7, #1 +1002ecf0: b2c7 uxtb r7, r0 +1002ecf2: f89d 000c ldrb.w r0, [sp, #12] +1002ecf6: 4287 cmp r7, r0 +1002ecf8: dbdb blt.n 1002ecb2 +1002ecfa: b007 add sp, #28 +1002ecfc: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + +1002ed00 : +1002ed00: b5f8 push {r3, r4, r5, r6, r7, lr} +1002ed02: f641 31a4 movw r1, #7076 ; 0x1ba4 +1002ed06: 580c ldr r4, [r1, r0] +1002ed08: 8800 ldrh r0, [r0, #0] +1002ed0a: 2810 cmp r0, #16 +1002ed0c: bf18 it ne +1002ed0e: 2811 cmpne r0, #17 +1002ed10: d007 beq.n 1002ed22 +1002ed12: 2812 cmp r0, #18 +1002ed14: bf18 it ne +1002ed16: 280d cmpne r0, #13 +1002ed18: d003 beq.n 1002ed22 +1002ed1a: 280e cmp r0, #14 +1002ed1c: bf18 it ne +1002ed1e: 280f cmpne r0, #15 +1002ed20: d10c bne.n 1002ed3c +1002ed22: 2500 movs r5, #0 +1002ed24: eb04 1085 add.w r0, r4, r5, lsl #6 +1002ed28: f500 50a8 add.w r0, r0, #5376 ; 0x1500 +1002ed2c: 2140 movs r1, #64 ; 0x40 +1002ed2e: 3074 adds r0, #116 ; 0x74 +1002ed30: f7df fa00 bl 1000e134 <__aeabi_memclr> +1002ed34: 1c6d adds r5, r5, #1 +1002ed36: 2d0d cmp r5, #13 +1002ed38: dbf4 blt.n 1002ed24 +1002ed3a: bdf1 pop {r0, r4, r5, r6, r7, pc} +1002ed3c: 2500 movs r5, #0 +1002ed3e: 2600 movs r6, #0 +1002ed40: 2700 movs r7, #0 +1002ed42: f44f 60a8 mov.w r0, #1344 ; 0x540 +1002ed46: fb00 4005 mla r0, r0, r5, r4 +1002ed4a: f44f 72a8 mov.w r2, #336 ; 0x150 +1002ed4e: 2154 movs r1, #84 ; 0x54 +1002ed50: fb02 0006 mla r0, r2, r6, r0 +1002ed54: fb01 0007 mla r0, r1, r7, r0 +1002ed58: 30bb adds r0, #187 ; 0xbb +1002ed5a: f7df f9eb bl 1000e134 <__aeabi_memclr> +1002ed5e: 1c7f adds r7, r7, #1 +1002ed60: 2f04 cmp r7, #4 +1002ed62: dbee blt.n 1002ed42 +1002ed64: 1c76 adds r6, r6, #1 +1002ed66: 2e04 cmp r6, #4 +1002ed68: dbea blt.n 1002ed40 +1002ed6a: 1c6d adds r5, r5, #1 +1002ed6c: 2d02 cmp r5, #2 +1002ed6e: dbe6 blt.n 1002ed3e +1002ed70: bdf1 pop {r0, r4, r5, r6, r7, pc} + +1002ed72 : +1002ed72: b53e push {r1, r2, r3, r4, r5, lr} +1002ed74: f641 34a4 movw r4, #7076 ; 0x1ba4 +1002ed78: f641 15b8 movw r5, #6584 ; 0x19b8 +1002ed7c: 5824 ldr r4, [r4, r0] +1002ed7e: 5d2c ldrb r4, [r5, r4] +1002ed80: b13c cbz r4, 1002ed92 +1002ed82: 9c08 ldr r4, [sp, #32] +1002ed84: 9402 str r4, [sp, #8] +1002ed86: 9c07 ldr r4, [sp, #28] +1002ed88: 9401 str r4, [sp, #4] +1002ed8a: 9c06 ldr r4, [sp, #24] +1002ed8c: 9400 str r4, [sp, #0] +1002ed8e: f7ff ff6a bl 1002ec66 +1002ed92: bd37 pop {r0, r1, r2, r4, r5, pc} + +1002ed94 : +1002ed94: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +1002ed98: f20f 1144 addw r1, pc, #324 ; 0x144 +1002ed9c: b094 sub sp, #80 ; 0x50 +1002ed9e: 4604 mov r4, r0 +1002eda0: a802 add r0, sp, #8 +1002eda2: 680a ldr r2, [r1, #0] +1002eda4: f20f 113c addw r1, pc, #316 ; 0x13c +1002eda8: 6002 str r2, [r0, #0] +1002edaa: a809 add r0, sp, #36 ; 0x24 +1002edac: c90c ldmia r1!, {r2, r3} +1002edae: c00c stmia r0!, {r2, r3} +1002edb0: f20f 1138 addw r1, pc, #312 ; 0x138 +1002edb4: c90c ldmia r1!, {r2, r3} +1002edb6: a807 add r0, sp, #28 +1002edb8: f20f 1138 addw r1, pc, #312 ; 0x138 +1002edbc: c00c stmia r0!, {r2, r3} +1002edbe: c90c ldmia r1!, {r2, r3} +1002edc0: a805 add r0, sp, #20 +1002edc2: f20f 1138 addw r1, pc, #312 ; 0x138 +1002edc6: c00c stmia r0!, {r2, r3} +1002edc8: c90c ldmia r1!, {r2, r3} +1002edca: a803 add r0, sp, #12 +1002edcc: f20f 1134 addw r1, pc, #308 ; 0x134 +1002edd0: c00c stmia r0!, {r2, r3} +1002edd2: c94c ldmia r1!, {r2, r3, r6} +1002edd4: a811 add r0, sp, #68 ; 0x44 +1002edd6: f20f 1138 addw r1, pc, #312 ; 0x138 +1002edda: c04c stmia r0!, {r2, r3, r6} +1002eddc: c94c ldmia r1!, {r2, r3, r6} +1002edde: a80e add r0, sp, #56 ; 0x38 +1002ede0: f20f 1138 addw r1, pc, #312 ; 0x138 +1002ede4: c04c stmia r0!, {r2, r3, r6} +1002ede6: c94c ldmia r1!, {r2, r3, r6} +1002ede8: a80b add r0, sp, #44 ; 0x2c +1002edea: 2500 movs r5, #0 +1002edec: c04c stmia r0!, {r2, r3, r6} +1002edee: 2600 movs r6, #0 +1002edf0: 2700 movs r7, #0 +1002edf2: 2016 movs r0, #22 +1002edf4: f000 f8bb bl 1002ef6e <.text_39> +1002edf8: f000 f8a0 bl 1002ef3c <.text_35> +1002edfc: a802 add r0, sp, #8 +1002edfe: f000 f8ad bl 1002ef5c <.text_37> +1002ee02: f000 f8a0 bl 1002ef46 <.text_36> +1002ee06: f109 0901 add.w r9, r9, #1 +1002ee0a: f1b9 0f04 cmp.w r9, #4 +1002ee0e: d3f5 bcc.n 1002edfc +1002ee10: 206c movs r0, #108 ; 0x6c +1002ee12: f000 f8ac bl 1002ef6e <.text_39> +1002ee16: f000 f891 bl 1002ef3c <.text_35> +1002ee1a: a809 add r0, sp, #36 ; 0x24 +1002ee1c: f000 f89e bl 1002ef5c <.text_37> +1002ee20: f000 f891 bl 1002ef46 <.text_36> +1002ee24: f000 f885 bl 1002ef32 <.text_34> +1002ee28: d3f7 bcc.n 1002ee1a +1002ee2a: 2087 movs r0, #135 ; 0x87 +1002ee2c: f000 f89f bl 1002ef6e <.text_39> +1002ee30: f000 f884 bl 1002ef3c <.text_35> +1002ee34: a807 add r0, sp, #28 +1002ee36: f000 f891 bl 1002ef5c <.text_37> +1002ee3a: f000 f884 bl 1002ef46 <.text_36> +1002ee3e: f000 f878 bl 1002ef32 <.text_34> +1002ee42: d3f7 bcc.n 1002ee34 +1002ee44: 208f movs r0, #143 ; 0x8f +1002ee46: f000 f892 bl 1002ef6e <.text_39> +1002ee4a: f000 f877 bl 1002ef3c <.text_35> +1002ee4e: a805 add r0, sp, #20 +1002ee50: f000 f884 bl 1002ef5c <.text_37> +1002ee54: f000 f877 bl 1002ef46 <.text_36> +1002ee58: f000 f86b bl 1002ef32 <.text_34> +1002ee5c: d3f7 bcc.n 1002ee4e +1002ee5e: 2097 movs r0, #151 ; 0x97 +1002ee60: f000 f885 bl 1002ef6e <.text_39> +1002ee64: f000 f86a bl 1002ef3c <.text_35> +1002ee68: a803 add r0, sp, #12 +1002ee6a: f000 f877 bl 1002ef5c <.text_37> +1002ee6e: f000 f86a bl 1002ef46 <.text_36> +1002ee72: f000 f85e bl 1002ef32 <.text_34> +1002ee76: d3f7 bcc.n 1002ee68 +1002ee78: 20a7 movs r0, #167 ; 0xa7 +1002ee7a: f000 f878 bl 1002ef6e <.text_39> +1002ee7e: f000 f85d bl 1002ef3c <.text_35> +1002ee82: a811 add r0, sp, #68 ; 0x44 +1002ee84: f000 f86a bl 1002ef5c <.text_37> +1002ee88: f000 f85d bl 1002ef46 <.text_36> +1002ee8c: f000 f84c bl 1002ef28 <.text_33> +1002ee90: d3f7 bcc.n 1002ee82 +1002ee92: 20b1 movs r0, #177 ; 0xb1 +1002ee94: f000 f86b bl 1002ef6e <.text_39> +1002ee98: f000 f850 bl 1002ef3c <.text_35> +1002ee9c: a80e add r0, sp, #56 ; 0x38 +1002ee9e: f000 f85d bl 1002ef5c <.text_37> +1002eea2: f000 f850 bl 1002ef46 <.text_36> +1002eea6: f000 f83f bl 1002ef28 <.text_33> +1002eeaa: d3f7 bcc.n 1002ee9c +1002eeac: 20bb movs r0, #187 ; 0xbb +1002eeae: f000 f85e bl 1002ef6e <.text_39> +1002eeb2: f000 f843 bl 1002ef3c <.text_35> +1002eeb6: a80b add r0, sp, #44 ; 0x2c +1002eeb8: f000 f850 bl 1002ef5c <.text_37> +1002eebc: f000 f843 bl 1002ef46 <.text_36> +1002eec0: f000 f832 bl 1002ef28 <.text_33> +1002eec4: d3f7 bcc.n 1002eeb6 +1002eec6: 1c7f adds r7, r7, #1 +1002eec8: 2f04 cmp r7, #4 +1002eeca: db92 blt.n 1002edf2 +1002eecc: 1c76 adds r6, r6, #1 +1002eece: 2e04 cmp r6, #4 +1002eed0: db8e blt.n 1002edf0 +1002eed2: 1c6d adds r5, r5, #1 +1002eed4: 2d02 cmp r5, #2 +1002eed6: db8a blt.n 1002edee +1002eed8: b014 add sp, #80 ; 0x50 +1002eeda: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + ... + +1002eee0 : +1002eee0: 0402 160b .... + +1002eee4 : +1002eee4: 120c 2418 4830 6c60 ...$0H`l + +1002eeec : +1002eeec: 8180 8382 8584 8786 ........ + +1002eef4 : +1002eef4: 8988 8b8a 8d8c 8f8e ........ + +1002eefc : +1002eefc: 9190 9392 9594 9796 ........ + +1002ef04 : +1002ef04: a1a0 a3a2 a5a4 a7a6 a9a8 0000 ............ + +1002ef10 : +1002ef10: abaa adac afae b1b0 b3b2 0000 ............ + +1002ef1c : +1002ef1c: b5b4 b7b6 b9b8 bbba bdbc 0000 ............ + +1002ef28 <.text_33>: +1002ef28: f109 0901 add.w r9, r9, #1 +1002ef2c: f1b9 0f0a cmp.w r9, #10 +1002ef30: 4770 bx lr + +1002ef32 <.text_34>: +1002ef32: f109 0901 add.w r9, r9, #1 +1002ef36: f1b9 0f08 cmp.w r9, #8 +1002ef3a: 4770 bx lr + +1002ef3c <.text_35>: +1002ef3c: fa5f f880 uxtb.w r8, r0 +1002ef40: f04f 0900 mov.w r9, #0 +1002ef44: 4770 bx lr + +1002ef46 <.text_36>: +1002ef46: eba0 0008 sub.w r0, r0, r8 +1002ef4a: b240 sxtb r0, r0 +1002ef4c: 9001 str r0, [sp, #4] +1002ef4e: f8cd a000 str.w sl, [sp] +1002ef52: 463b mov r3, r7 +1002ef54: 4632 mov r2, r6 +1002ef56: 4629 mov r1, r5 +1002ef58: 4620 mov r0, r4 +1002ef5a: e32d b.n 1002f5b8 + +1002ef5c <.text_37>: +1002ef5c: 463b mov r3, r7 +1002ef5e: f819 a000 ldrb.w sl, [r9, r0] +1002ef62: f8cd a000 str.w sl, [sp] +1002ef66: 4632 mov r2, r6 +1002ef68: 4629 mov r1, r5 + +1002ef6a <.text_38>: +1002ef6a: 4620 mov r0, r4 +1002ef6c: e2f3 b.n 1002f556 + +1002ef6e <.text_39>: +1002ef6e: 9000 str r0, [sp, #0] +1002ef70: 463b mov r3, r7 +1002ef72: 4632 mov r2, r6 +1002ef74: 4629 mov r1, r5 +1002ef76: 4620 mov r0, r4 +1002ef78: e2ed b.n 1002f556 + +1002ef7a : +1002ef7a: b510 push {r4, lr} +1002ef7c: 4604 mov r4, r0 +1002ef7e: f7ff fb20 bl 1002e5c2 +1002ef82: 4620 mov r0, r4 +1002ef84: e8bd 4010 ldmia.w sp!, {r4, lr} +1002ef88: e704 b.n 1002ed94 + +1002ef8a : +1002ef8a: b5f0 push {r4, r5, r6, r7, lr} +1002ef8c: f641 34a4 movw r4, #7076 ; 0x1ba4 +1002ef90: b085 sub sp, #20 +1002ef92: 5824 ldr r4, [r4, r0] +1002ef94: b94b cbnz r3, 1002efaa +1002ef96: f20f 0598 addw r5, pc, #152 ; 0x98 +1002ef9a: 682e ldr r6, [r5, #0] +1002ef9c: ab02 add r3, sp, #8 +1002ef9e: 601e str r6, [r3, #0] +1002efa0: 6c23 ldr r3, [r4, #64] ; 0x40 +1002efa2: 2b00 cmp r3, #0 +1002efa4: d141 bne.n 1002f02a +1002efa6: 2304 movs r3, #4 +1002efa8: e038 b.n 1002f01c +1002efaa: 2b01 cmp r3, #1 +1002efac: d102 bne.n 1002efb4 +1002efae: f20f 0584 addw r5, pc, #132 ; 0x84 +1002efb2: e012 b.n 1002efda +1002efb4: 2b02 cmp r3, #2 +1002efb6: d102 bne.n 1002efbe +1002efb8: f20f 0580 addw r5, pc, #128 ; 0x80 +1002efbc: e00d b.n 1002efda +1002efbe: 2b03 cmp r3, #3 +1002efc0: d102 bne.n 1002efc8 +1002efc2: f20f 0580 addw r5, pc, #128 ; 0x80 +1002efc6: e008 b.n 1002efda +1002efc8: 2b04 cmp r3, #4 +1002efca: d102 bne.n 1002efd2 +1002efcc: f20f 057c addw r5, pc, #124 ; 0x7c +1002efd0: e003 b.n 1002efda +1002efd2: 2b05 cmp r3, #5 +1002efd4: d106 bne.n 1002efe4 +1002efd6: f20f 057c addw r5, pc, #124 ; 0x7c +1002efda: cdc0 ldmia r5!, {r6, r7} +1002efdc: ab02 add r3, sp, #8 +1002efde: c3c0 stmia r3!, {r6, r7} +1002efe0: 2308 movs r3, #8 +1002efe2: e01b b.n 1002f01c +1002efe4: 2b06 cmp r3, #6 +1002efe6: d103 bne.n 1002eff0 +1002efe8: ab02 add r3, sp, #8 +1002efea: f20f 0570 addw r5, pc, #112 ; 0x70 +1002efee: e010 b.n 1002f012 +1002eff0: 2b07 cmp r3, #7 +1002eff2: d103 bne.n 1002effc +1002eff4: ab02 add r3, sp, #8 +1002eff6: f20f 0570 addw r5, pc, #112 ; 0x70 +1002effa: e00a b.n 1002f012 +1002effc: 2b08 cmp r3, #8 +1002effe: d103 bne.n 1002f008 +1002f000: ab02 add r3, sp, #8 +1002f002: f20f 0570 addw r5, pc, #112 ; 0x70 +1002f006: e004 b.n 1002f012 +1002f008: 2b09 cmp r3, #9 +1002f00a: d10e bne.n 1002f02a +1002f00c: ab02 add r3, sp, #8 +1002f00e: f20f 0570 addw r5, pc, #112 ; 0x70 +1002f012: e8b5 10c0 ldmia.w r5!, {r6, r7, ip} +1002f016: e8a3 10c0 stmia.w r3!, {r6, r7, ip} +1002f01a: 230a movs r3, #10 +1002f01c: 9301 str r3, [sp, #4] +1002f01e: ab02 add r3, sp, #8 +1002f020: 9300 str r3, [sp, #0] +1002f022: 4613 mov r3, r2 +1002f024: 6be2 ldr r2, [r4, #60] ; 0x3c +1002f026: f000 fb30 bl 1002f68a +1002f02a: b005 add sp, #20 +1002f02c: bdf0 pop {r4, r5, r6, r7, pc} + ... + +1002f030 : +1002f030: 0402 160b .... + +1002f034 : +1002f034: 120c 2418 4830 6c60 ...$0H`l + +1002f03c : +1002f03c: 8180 8382 8584 8786 ........ + +1002f044 : +1002f044: 8988 8b8a 8d8c 8f8e ........ + +1002f04c : +1002f04c: 9190 9392 9594 9796 ........ + +1002f054 : +1002f054: 9998 9b9a 9d9c 9f9e ........ + +1002f05c : +1002f05c: a1a0 a3a2 a5a4 a7a6 a9a8 0000 ............ + +1002f068 : +1002f068: abaa adac afae b1b0 b3b2 0000 ............ + +1002f074 : +1002f074: b5b4 b7b6 b9b8 bbba bdbc 0000 ............ + +1002f080 : +1002f080: bfbe c1c0 c3c2 c5c4 c7c6 0000 ............ + +1002f08c : +1002f08c: 2201 movs r2, #1 +1002f08e: 280f cmp r0, #15 +1002f090: bfba itte lt +1002f092: 1e40 sublt r0, r0, #1 +1002f094: 7008 strblt r0, [r1, #0] +1002f096: 2200 movge r2, #0 +1002f098: 4610 mov r0, r2 +1002f09a: 4770 bx lr + +1002f09c : +1002f09c: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +1002f0a0: 460d mov r5, r1 +1002f0a2: f641 31a4 movw r1, #7076 ; 0x1ba4 +1002f0a6: 9c08 ldr r4, [sp, #32] +1002f0a8: f851 8000 ldr.w r8, [r1, r0] +1002f0ac: 1e61 subs r1, r4, #1 +1002f0ae: f88d 1000 strb.w r1, [sp] +1002f0b2: 4616 mov r6, r2 +1002f0b4: 4699 mov r9, r3 +1002f0b6: 2700 movs r7, #0 +1002f0b8: 4621 mov r1, r4 +1002f0ba: f7f7 fc30 bl 1002691e +1002f0be: b908 cbnz r0, 1002f0c4 +1002f0c0: f88d 0000 strb.w r0, [sp] +1002f0c4: a900 add r1, sp, #0 +1002f0c6: 4620 mov r0, r4 +1002f0c8: f7ff ffe0 bl 1002f08c +1002f0cc: 9909 ldr r1, [sp, #36] ; 0x24 +1002f0ce: 7008 strb r0, [r1, #0] +1002f0d0: 2800 cmp r0, #0 +1002f0d2: f000 8083 beq.w 1002f1dc +1002f0d6: 200e movs r0, #14 +1002f0d8: f89d 1000 ldrb.w r1, [sp] +1002f0dc: fb00 8005 mla r0, r0, r5, r8 +1002f0e0: 1808 adds r0, r1, r0 +1002f0e2: 2e02 cmp r6, #2 +1002f0e4: bf18 it ne +1002f0e6: 2e04 cmpne r6, #4 +1002f0e8: d003 beq.n 1002f0f2 +1002f0ea: 2e0b cmp r6, #11 +1002f0ec: bf18 it ne +1002f0ee: 2e16 cmpne r6, #22 +1002f0f0: d102 bne.n 1002f0f8 +1002f0f2: f890 7061 ldrb.w r7, [r0, #97] ; 0x61 +1002f0f6: e003 b.n 1002f100 +1002f0f8: 2e0c cmp r6, #12 +1002f0fa: bfa8 it ge +1002f0fc: f890 707d ldrbge.w r7, [r0, #125] ; 0x7d +1002f100: f1a6 020c sub.w r2, r6, #12 +1002f104: 2a61 cmp r2, #97 ; 0x61 +1002f106: eb08 0085 add.w r0, r8, r5, lsl #2 +1002f10a: d20b bcs.n 1002f124 +1002f10c: 2e02 cmp r6, #2 +1002f10e: bf18 it ne +1002f110: 2e04 cmpne r6, #4 +1002f112: d007 beq.n 1002f124 +1002f114: 2e0b cmp r6, #11 +1002f116: bf18 it ne +1002f118: 2e16 cmpne r6, #22 +1002f11a: d003 beq.n 1002f124 +1002f11c: f990 10a1 ldrsb.w r1, [r0, #161] ; 0xa1 +1002f120: 19c9 adds r1, r1, r7 +1002f122: b2cf uxtb r7, r1 +1002f124: f1a6 01be sub.w r1, r6, #190 ; 0xbe +1002f128: f1a6 0298 sub.w r2, r6, #152 ; 0x98 +1002f12c: f1a6 03b4 sub.w r3, r6, #180 ; 0xb4 +1002f130: f1a6 0490 sub.w r4, r6, #144 ; 0x90 +1002f134: f1a6 05aa sub.w r5, r6, #170 ; 0xaa +1002f138: f1a6 0c88 sub.w ip, r6, #136 ; 0x88 +1002f13c: f1a6 0ea0 sub.w lr, r6, #160 ; 0xa0 +1002f140: 30a1 adds r0, #161 ; 0xa1 +1002f142: 3e80 subs r6, #128 ; 0x80 +1002f144: f1b9 0f00 cmp.w r9, #0 +1002f148: d120 bne.n 1002f18c +1002f14a: 2e20 cmp r6, #32 +1002f14c: bf28 it cs +1002f14e: f1be 0f28 cmpcs.w lr, #40 ; 0x28 +1002f152: d203 bcs.n 1002f15c +1002f154: f990 6008 ldrsb.w r6, [r0, #8] +1002f158: 19f6 adds r6, r6, r7 +1002f15a: b2f7 uxtb r7, r6 +1002f15c: f1bc 0f18 cmp.w ip, #24 +1002f160: bf28 it cs +1002f162: 2d1e cmpcs r5, #30 +1002f164: d203 bcs.n 1002f16e +1002f166: f990 5009 ldrsb.w r5, [r0, #9] +1002f16a: 19ed adds r5, r5, r7 +1002f16c: b2ef uxtb r7, r5 +1002f16e: 2c10 cmp r4, #16 +1002f170: bf28 it cs +1002f172: 2b14 cmpcs r3, #20 +1002f174: d203 bcs.n 1002f17e +1002f176: f990 300a ldrsb.w r3, [r0, #10] +1002f17a: 19db adds r3, r3, r7 +1002f17c: b2df uxtb r7, r3 +1002f17e: 2a08 cmp r2, #8 +1002f180: bf28 it cs +1002f182: 290a cmpcs r1, #10 +1002f184: d22a bcs.n 1002f1dc +1002f186: f990 000b ldrsb.w r0, [r0, #11] +1002f18a: e025 b.n 1002f1d8 +1002f18c: f1b9 0f01 cmp.w r9, #1 +1002f190: bf18 it ne +1002f192: f1b9 0f02 cmpne.w r9, #2 +1002f196: d121 bne.n 1002f1dc +1002f198: 2e20 cmp r6, #32 +1002f19a: bf28 it cs +1002f19c: f1be 0f28 cmpcs.w lr, #40 ; 0x28 +1002f1a0: d203 bcs.n 1002f1aa +1002f1a2: f990 6010 ldrsb.w r6, [r0, #16] +1002f1a6: 19f6 adds r6, r6, r7 +1002f1a8: b2f7 uxtb r7, r6 +1002f1aa: f1bc 0f18 cmp.w ip, #24 +1002f1ae: bf28 it cs +1002f1b0: 2d1e cmpcs r5, #30 +1002f1b2: d203 bcs.n 1002f1bc +1002f1b4: f990 5011 ldrsb.w r5, [r0, #17] +1002f1b8: 19ed adds r5, r5, r7 +1002f1ba: b2ef uxtb r7, r5 +1002f1bc: 2c10 cmp r4, #16 +1002f1be: bf28 it cs +1002f1c0: 2b14 cmpcs r3, #20 +1002f1c2: d203 bcs.n 1002f1cc +1002f1c4: f990 3012 ldrsb.w r3, [r0, #18] +1002f1c8: 19db adds r3, r3, r7 +1002f1ca: b2df uxtb r7, r3 +1002f1cc: 2a08 cmp r2, #8 +1002f1ce: bf28 it cs +1002f1d0: 290a cmpcs r1, #10 +1002f1d2: d203 bcs.n 1002f1dc +1002f1d4: f990 0013 ldrsb.w r0, [r0, #19] +1002f1d8: 19c0 adds r0, r0, r7 +1002f1da: b2c7 uxtb r7, r0 +1002f1dc: 4638 mov r0, r7 +1002f1de: e8bd 83f2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, pc} + +1002f1e2 : +1002f1e2: f641 33a4 movw r3, #7076 ; 0x1ba4 +1002f1e6: 5818 ldr r0, [r3, r0] +1002f1e8: f500 50c8 add.w r0, r0, #6400 ; 0x1900 +1002f1ec: 30a8 adds r0, #168 ; 0xa8 +1002f1ee: f890 394f ldrb.w r3, [r0, #2383] ; 0x94f +1002f1f2: b90b cbnz r3, 1002f1f8 +1002f1f4: 2000 movs r0, #0 +1002f1f6: 4770 bx lr +1002f1f8: 1808 adds r0, r1, r0 +1002f1fa: 2a02 cmp r2, #2 +1002f1fc: bf18 it ne +1002f1fe: 2a04 cmpne r2, #4 +1002f200: d003 beq.n 1002f20a +1002f202: 2a0b cmp r2, #11 +1002f204: bf18 it ne +1002f206: 2a16 cmpne r2, #22 +1002f208: d102 bne.n 1002f210 +1002f20a: f990 0f14 ldrsb.w r0, [r0, #3860] ; 0xf14 +1002f20e: 4770 bx lr +1002f210: f990 0f12 ldrsb.w r0, [r0, #3858] ; 0xf12 +1002f214: 4770 bx lr + +1002f216 : +1002f216: 2100 movs r1, #0 +1002f218: 2804 cmp r0, #4 +1002f21a: f000 80f7 beq.w 1002f40c +1002f21e: 280b cmp r0, #11 +1002f220: f000 80f6 beq.w 1002f410 +1002f224: 280c cmp r0, #12 +1002f226: f000 80f7 beq.w 1002f418 +1002f22a: 2812 cmp r0, #18 +1002f22c: f000 80f6 beq.w 1002f41c +1002f230: 2816 cmp r0, #22 +1002f232: f000 80ef beq.w 1002f414 +1002f236: 2818 cmp r0, #24 +1002f238: f000 80f2 beq.w 1002f420 +1002f23c: 2824 cmp r0, #36 ; 0x24 +1002f23e: f000 80f1 beq.w 1002f424 +1002f242: 2830 cmp r0, #48 ; 0x30 +1002f244: f000 80f0 beq.w 1002f428 +1002f248: 2848 cmp r0, #72 ; 0x48 +1002f24a: f000 80ef beq.w 1002f42c +1002f24e: 2860 cmp r0, #96 ; 0x60 +1002f250: f000 80ee beq.w 1002f430 +1002f254: 286c cmp r0, #108 ; 0x6c +1002f256: f000 80ed beq.w 1002f434 +1002f25a: 2880 cmp r0, #128 ; 0x80 +1002f25c: f000 80ec beq.w 1002f438 +1002f260: 2881 cmp r0, #129 ; 0x81 +1002f262: f000 80eb beq.w 1002f43c +1002f266: 2882 cmp r0, #130 ; 0x82 +1002f268: f000 80ea beq.w 1002f440 +1002f26c: 2883 cmp r0, #131 ; 0x83 +1002f26e: f000 80e9 beq.w 1002f444 +1002f272: 2884 cmp r0, #132 ; 0x84 +1002f274: f000 80e8 beq.w 1002f448 +1002f278: 2885 cmp r0, #133 ; 0x85 +1002f27a: f000 80e7 beq.w 1002f44c +1002f27e: 2886 cmp r0, #134 ; 0x86 +1002f280: f000 80e6 beq.w 1002f450 +1002f284: 2887 cmp r0, #135 ; 0x87 +1002f286: f000 80e5 beq.w 1002f454 +1002f28a: 2888 cmp r0, #136 ; 0x88 +1002f28c: f000 80e4 beq.w 1002f458 +1002f290: 2889 cmp r0, #137 ; 0x89 +1002f292: f000 80e3 beq.w 1002f45c +1002f296: 288a cmp r0, #138 ; 0x8a +1002f298: f000 80e2 beq.w 1002f460 +1002f29c: 288b cmp r0, #139 ; 0x8b +1002f29e: f000 80e1 beq.w 1002f464 +1002f2a2: 288c cmp r0, #140 ; 0x8c +1002f2a4: f000 80e0 beq.w 1002f468 +1002f2a8: 288d cmp r0, #141 ; 0x8d +1002f2aa: f000 80df beq.w 1002f46c +1002f2ae: 288e cmp r0, #142 ; 0x8e +1002f2b0: f000 80de beq.w 1002f470 +1002f2b4: 288f cmp r0, #143 ; 0x8f +1002f2b6: f000 80dd beq.w 1002f474 +1002f2ba: 2890 cmp r0, #144 ; 0x90 +1002f2bc: f000 80dc beq.w 1002f478 +1002f2c0: 2891 cmp r0, #145 ; 0x91 +1002f2c2: f000 80db beq.w 1002f47c +1002f2c6: 2892 cmp r0, #146 ; 0x92 +1002f2c8: f000 80da beq.w 1002f480 +1002f2cc: 2893 cmp r0, #147 ; 0x93 +1002f2ce: f000 80d9 beq.w 1002f484 +1002f2d2: 2894 cmp r0, #148 ; 0x94 +1002f2d4: f000 80d8 beq.w 1002f488 +1002f2d8: 2895 cmp r0, #149 ; 0x95 +1002f2da: f000 80d7 beq.w 1002f48c +1002f2de: 2896 cmp r0, #150 ; 0x96 +1002f2e0: f000 80d6 beq.w 1002f490 +1002f2e4: 2897 cmp r0, #151 ; 0x97 +1002f2e6: f000 80d5 beq.w 1002f494 +1002f2ea: 2898 cmp r0, #152 ; 0x98 +1002f2ec: f000 80d4 beq.w 1002f498 +1002f2f0: 2899 cmp r0, #153 ; 0x99 +1002f2f2: f000 80d3 beq.w 1002f49c +1002f2f6: 289a cmp r0, #154 ; 0x9a +1002f2f8: f000 80d2 beq.w 1002f4a0 +1002f2fc: 289b cmp r0, #155 ; 0x9b +1002f2fe: f000 80d1 beq.w 1002f4a4 +1002f302: 289c cmp r0, #156 ; 0x9c +1002f304: f000 80d0 beq.w 1002f4a8 +1002f308: 289d cmp r0, #157 ; 0x9d +1002f30a: f000 80cf beq.w 1002f4ac +1002f30e: 289e cmp r0, #158 ; 0x9e +1002f310: f000 80ce beq.w 1002f4b0 +1002f314: 289f cmp r0, #159 ; 0x9f +1002f316: f000 80cd beq.w 1002f4b4 +1002f31a: 28a0 cmp r0, #160 ; 0xa0 +1002f31c: f000 80cc beq.w 1002f4b8 +1002f320: 28a1 cmp r0, #161 ; 0xa1 +1002f322: f000 80cb beq.w 1002f4bc +1002f326: 28a2 cmp r0, #162 ; 0xa2 +1002f328: f000 80ca beq.w 1002f4c0 +1002f32c: 28a3 cmp r0, #163 ; 0xa3 +1002f32e: f000 80c9 beq.w 1002f4c4 +1002f332: 28a4 cmp r0, #164 ; 0xa4 +1002f334: f000 80c8 beq.w 1002f4c8 +1002f338: 28a5 cmp r0, #165 ; 0xa5 +1002f33a: f000 80c7 beq.w 1002f4cc +1002f33e: 28a6 cmp r0, #166 ; 0xa6 +1002f340: f000 80c6 beq.w 1002f4d0 +1002f344: 28a7 cmp r0, #167 ; 0xa7 +1002f346: f000 80c5 beq.w 1002f4d4 +1002f34a: 28a8 cmp r0, #168 ; 0xa8 +1002f34c: f000 80c4 beq.w 1002f4d8 +1002f350: 28a9 cmp r0, #169 ; 0xa9 +1002f352: f000 80c3 beq.w 1002f4dc +1002f356: 28aa cmp r0, #170 ; 0xaa +1002f358: f000 80c2 beq.w 1002f4e0 +1002f35c: 28ab cmp r0, #171 ; 0xab +1002f35e: f000 80c1 beq.w 1002f4e4 +1002f362: 28ac cmp r0, #172 ; 0xac +1002f364: f000 80c0 beq.w 1002f4e8 +1002f368: 28ad cmp r0, #173 ; 0xad +1002f36a: f000 80bf beq.w 1002f4ec +1002f36e: 28ae cmp r0, #174 ; 0xae +1002f370: f000 80be beq.w 1002f4f0 +1002f374: 28af cmp r0, #175 ; 0xaf +1002f376: f000 80bd beq.w 1002f4f4 +1002f37a: 28b0 cmp r0, #176 ; 0xb0 +1002f37c: f000 80bc beq.w 1002f4f8 +1002f380: 28b1 cmp r0, #177 ; 0xb1 +1002f382: f000 80bb beq.w 1002f4fc +1002f386: 28b2 cmp r0, #178 ; 0xb2 +1002f388: f000 80ba beq.w 1002f500 +1002f38c: 28b3 cmp r0, #179 ; 0xb3 +1002f38e: f000 80b9 beq.w 1002f504 +1002f392: 28b4 cmp r0, #180 ; 0xb4 +1002f394: f000 80b8 beq.w 1002f508 +1002f398: 28b5 cmp r0, #181 ; 0xb5 +1002f39a: f000 80b7 beq.w 1002f50c +1002f39e: 28b6 cmp r0, #182 ; 0xb6 +1002f3a0: f000 80b6 beq.w 1002f510 +1002f3a4: 28b7 cmp r0, #183 ; 0xb7 +1002f3a6: f000 80b5 beq.w 1002f514 +1002f3aa: 28b8 cmp r0, #184 ; 0xb8 +1002f3ac: f000 80b4 beq.w 1002f518 +1002f3b0: 28b9 cmp r0, #185 ; 0xb9 +1002f3b2: f000 80b3 beq.w 1002f51c +1002f3b6: 28ba cmp r0, #186 ; 0xba +1002f3b8: f000 80b2 beq.w 1002f520 +1002f3bc: 28bb cmp r0, #187 ; 0xbb +1002f3be: f000 80b1 beq.w 1002f524 +1002f3c2: 28bc cmp r0, #188 ; 0xbc +1002f3c4: f000 80b0 beq.w 1002f528 +1002f3c8: 28bd cmp r0, #189 ; 0xbd +1002f3ca: f000 80af beq.w 1002f52c +1002f3ce: 28be cmp r0, #190 ; 0xbe +1002f3d0: f000 80ae beq.w 1002f530 +1002f3d4: 28bf cmp r0, #191 ; 0xbf +1002f3d6: f000 80ad beq.w 1002f534 +1002f3da: 28c0 cmp r0, #192 ; 0xc0 +1002f3dc: f000 80ac beq.w 1002f538 +1002f3e0: 28c1 cmp r0, #193 ; 0xc1 +1002f3e2: f000 80ab beq.w 1002f53c +1002f3e6: 28c2 cmp r0, #194 ; 0xc2 +1002f3e8: f000 80aa beq.w 1002f540 +1002f3ec: 28c3 cmp r0, #195 ; 0xc3 +1002f3ee: f000 80a9 beq.w 1002f544 +1002f3f2: 28c4 cmp r0, #196 ; 0xc4 +1002f3f4: f000 80a8 beq.w 1002f548 +1002f3f8: 28c5 cmp r0, #197 ; 0xc5 +1002f3fa: f000 80a7 beq.w 1002f54c +1002f3fe: 28c6 cmp r0, #198 ; 0xc6 +1002f400: f000 80a6 beq.w 1002f550 +1002f404: 28c7 cmp r0, #199 ; 0xc7 +1002f406: bf08 it eq +1002f408: 2153 moveq r1, #83 ; 0x53 +1002f40a: e0a2 b.n 1002f552 +1002f40c: 2101 movs r1, #1 +1002f40e: e0a0 b.n 1002f552 +1002f410: 2102 movs r1, #2 +1002f412: e09e b.n 1002f552 +1002f414: 2103 movs r1, #3 +1002f416: e09c b.n 1002f552 +1002f418: 2104 movs r1, #4 +1002f41a: e09a b.n 1002f552 +1002f41c: 2105 movs r1, #5 +1002f41e: e098 b.n 1002f552 +1002f420: 2106 movs r1, #6 +1002f422: e096 b.n 1002f552 +1002f424: 2107 movs r1, #7 +1002f426: e094 b.n 1002f552 +1002f428: 2108 movs r1, #8 +1002f42a: e092 b.n 1002f552 +1002f42c: 2109 movs r1, #9 +1002f42e: e090 b.n 1002f552 +1002f430: 210a movs r1, #10 +1002f432: e08e b.n 1002f552 +1002f434: 210b movs r1, #11 +1002f436: e08c b.n 1002f552 +1002f438: 210c movs r1, #12 +1002f43a: e08a b.n 1002f552 +1002f43c: 210d movs r1, #13 +1002f43e: e088 b.n 1002f552 +1002f440: 210e movs r1, #14 +1002f442: e086 b.n 1002f552 +1002f444: 210f movs r1, #15 +1002f446: e084 b.n 1002f552 +1002f448: 2110 movs r1, #16 +1002f44a: e082 b.n 1002f552 +1002f44c: 2111 movs r1, #17 +1002f44e: e080 b.n 1002f552 +1002f450: 2112 movs r1, #18 +1002f452: e07e b.n 1002f552 +1002f454: 2113 movs r1, #19 +1002f456: e07c b.n 1002f552 +1002f458: 2114 movs r1, #20 +1002f45a: e07a b.n 1002f552 +1002f45c: 2115 movs r1, #21 +1002f45e: e078 b.n 1002f552 +1002f460: 2116 movs r1, #22 +1002f462: e076 b.n 1002f552 +1002f464: 2117 movs r1, #23 +1002f466: e074 b.n 1002f552 +1002f468: 2118 movs r1, #24 +1002f46a: e072 b.n 1002f552 +1002f46c: 2119 movs r1, #25 +1002f46e: e070 b.n 1002f552 +1002f470: 211a movs r1, #26 +1002f472: e06e b.n 1002f552 +1002f474: 211b movs r1, #27 +1002f476: e06c b.n 1002f552 +1002f478: 211c movs r1, #28 +1002f47a: e06a b.n 1002f552 +1002f47c: 211d movs r1, #29 +1002f47e: e068 b.n 1002f552 +1002f480: 211e movs r1, #30 +1002f482: e066 b.n 1002f552 +1002f484: 211f movs r1, #31 +1002f486: e064 b.n 1002f552 +1002f488: 2120 movs r1, #32 +1002f48a: e062 b.n 1002f552 +1002f48c: 2121 movs r1, #33 ; 0x21 +1002f48e: e060 b.n 1002f552 +1002f490: 2122 movs r1, #34 ; 0x22 +1002f492: e05e b.n 1002f552 +1002f494: 2123 movs r1, #35 ; 0x23 +1002f496: e05c b.n 1002f552 +1002f498: 2124 movs r1, #36 ; 0x24 +1002f49a: e05a b.n 1002f552 +1002f49c: 2125 movs r1, #37 ; 0x25 +1002f49e: e058 b.n 1002f552 +1002f4a0: 2126 movs r1, #38 ; 0x26 +1002f4a2: e056 b.n 1002f552 +1002f4a4: 2127 movs r1, #39 ; 0x27 +1002f4a6: e054 b.n 1002f552 +1002f4a8: 2128 movs r1, #40 ; 0x28 +1002f4aa: e052 b.n 1002f552 +1002f4ac: 2129 movs r1, #41 ; 0x29 +1002f4ae: e050 b.n 1002f552 +1002f4b0: 212a movs r1, #42 ; 0x2a +1002f4b2: e04e b.n 1002f552 +1002f4b4: 212b movs r1, #43 ; 0x2b +1002f4b6: e04c b.n 1002f552 +1002f4b8: 212c movs r1, #44 ; 0x2c +1002f4ba: e04a b.n 1002f552 +1002f4bc: 212d movs r1, #45 ; 0x2d +1002f4be: e048 b.n 1002f552 +1002f4c0: 212e movs r1, #46 ; 0x2e +1002f4c2: e046 b.n 1002f552 +1002f4c4: 212f movs r1, #47 ; 0x2f +1002f4c6: e044 b.n 1002f552 +1002f4c8: 2130 movs r1, #48 ; 0x30 +1002f4ca: e042 b.n 1002f552 +1002f4cc: 2131 movs r1, #49 ; 0x31 +1002f4ce: e040 b.n 1002f552 +1002f4d0: 2132 movs r1, #50 ; 0x32 +1002f4d2: e03e b.n 1002f552 +1002f4d4: 2133 movs r1, #51 ; 0x33 +1002f4d6: e03c b.n 1002f552 +1002f4d8: 2134 movs r1, #52 ; 0x34 +1002f4da: e03a b.n 1002f552 +1002f4dc: 2135 movs r1, #53 ; 0x35 +1002f4de: e038 b.n 1002f552 +1002f4e0: 2136 movs r1, #54 ; 0x36 +1002f4e2: e036 b.n 1002f552 +1002f4e4: 2137 movs r1, #55 ; 0x37 +1002f4e6: e034 b.n 1002f552 +1002f4e8: 2138 movs r1, #56 ; 0x38 +1002f4ea: e032 b.n 1002f552 +1002f4ec: 2139 movs r1, #57 ; 0x39 +1002f4ee: e030 b.n 1002f552 +1002f4f0: 213a movs r1, #58 ; 0x3a +1002f4f2: e02e b.n 1002f552 +1002f4f4: 213b movs r1, #59 ; 0x3b +1002f4f6: e02c b.n 1002f552 +1002f4f8: 213c movs r1, #60 ; 0x3c +1002f4fa: e02a b.n 1002f552 +1002f4fc: 213d movs r1, #61 ; 0x3d +1002f4fe: e028 b.n 1002f552 +1002f500: 213e movs r1, #62 ; 0x3e +1002f502: e026 b.n 1002f552 +1002f504: 213f movs r1, #63 ; 0x3f +1002f506: e024 b.n 1002f552 +1002f508: 2140 movs r1, #64 ; 0x40 +1002f50a: e022 b.n 1002f552 +1002f50c: 2141 movs r1, #65 ; 0x41 +1002f50e: e020 b.n 1002f552 +1002f510: 2142 movs r1, #66 ; 0x42 +1002f512: e01e b.n 1002f552 +1002f514: 2143 movs r1, #67 ; 0x43 +1002f516: e01c b.n 1002f552 +1002f518: 2144 movs r1, #68 ; 0x44 +1002f51a: e01a b.n 1002f552 +1002f51c: 2145 movs r1, #69 ; 0x45 +1002f51e: e018 b.n 1002f552 +1002f520: 2146 movs r1, #70 ; 0x46 +1002f522: e016 b.n 1002f552 +1002f524: 2147 movs r1, #71 ; 0x47 +1002f526: e014 b.n 1002f552 +1002f528: 2148 movs r1, #72 ; 0x48 +1002f52a: e012 b.n 1002f552 +1002f52c: 2149 movs r1, #73 ; 0x49 +1002f52e: e010 b.n 1002f552 +1002f530: 214a movs r1, #74 ; 0x4a +1002f532: e00e b.n 1002f552 +1002f534: 214b movs r1, #75 ; 0x4b +1002f536: e00c b.n 1002f552 +1002f538: 214c movs r1, #76 ; 0x4c +1002f53a: e00a b.n 1002f552 +1002f53c: 214d movs r1, #77 ; 0x4d +1002f53e: e008 b.n 1002f552 +1002f540: 214e movs r1, #78 ; 0x4e +1002f542: e006 b.n 1002f552 +1002f544: 214f movs r1, #79 ; 0x4f +1002f546: e004 b.n 1002f552 +1002f548: 2150 movs r1, #80 ; 0x50 +1002f54a: e002 b.n 1002f552 +1002f54c: 2151 movs r1, #81 ; 0x51 +1002f54e: e000 b.n 1002f552 +1002f550: 2152 movs r1, #82 ; 0x52 +1002f552: 4608 mov r0, r1 +1002f554: 4770 bx lr + +1002f556 : +1002f556: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1002f55a: 4604 mov r4, r0 +1002f55c: f641 30a4 movw r0, #7076 ; 0x1ba4 +1002f560: 4688 mov r8, r1 +1002f562: 5907 ldr r7, [r0, r4] +1002f564: 9806 ldr r0, [sp, #24] +1002f566: 4615 mov r5, r2 +1002f568: 461e mov r6, r3 +1002f56a: f7ff fe54 bl 1002f216 +1002f56e: f641 1102 movw r1, #6402 ; 0x1902 +1002f572: 5d09 ldrb r1, [r1, r4] +1002f574: 2902 cmp r1, #2 +1002f576: d109 bne.n 1002f58c +1002f578: f897 105b ldrb.w r1, [r7, #91] ; 0x5b +1002f57c: 2902 cmp r1, #2 +1002f57e: d00d beq.n 1002f59c +1002f580: ea5f 0108 movs.w r1, r8 +1002f584: bf18 it ne +1002f586: 2901 cmpne r1, #1 +1002f588: d003 beq.n 1002f592 +1002f58a: e007 b.n 1002f59c +1002f58c: 2900 cmp r1, #0 +1002f58e: d1f7 bne.n 1002f580 +1002f590: e004 b.n 1002f59c +1002f592: 2d04 cmp r5, #4 +1002f594: bfbc itt lt +1002f596: 2e04 cmplt r6, #4 +1002f598: 2854 cmplt r0, #84 ; 0x54 +1002f59a: db01 blt.n 1002f5a0 +1002f59c: 2000 movs r0, #0 +1002f59e: e009 b.n 1002f5b4 +1002f5a0: f000 f829 bl 1002f5f6 <.text_58> +1002f5a4: fb02 1105 mla r1, r2, r5, r1 +1002f5a8: 2254 movs r2, #84 ; 0x54 +1002f5aa: fb02 1106 mla r1, r2, r6, r1 +1002f5ae: 1840 adds r0, r0, r1 +1002f5b0: f990 00bb ldrsb.w r0, [r0, #187] ; 0xbb +1002f5b4: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +1002f5b8 : +1002f5b8: b5f8 push {r3, r4, r5, r6, r7, lr} +1002f5ba: 460e mov r6, r1 +1002f5bc: f641 31a4 movw r1, #7076 ; 0x1ba4 +1002f5c0: 4614 mov r4, r2 +1002f5c2: 580f ldr r7, [r1, r0] +1002f5c4: 9806 ldr r0, [sp, #24] +1002f5c6: 461d mov r5, r3 +1002f5c8: f7ff fe25 bl 1002f216 +1002f5cc: 0031 movs r1, r6 +1002f5ce: bf18 it ne +1002f5d0: 2901 cmpne r1, #1 +1002f5d2: d10f bne.n 1002f5f4 +1002f5d4: 2c04 cmp r4, #4 +1002f5d6: bfbc itt lt +1002f5d8: 2d04 cmplt r5, #4 +1002f5da: 2854 cmplt r0, #84 ; 0x54 +1002f5dc: da0a bge.n 1002f5f4 +1002f5de: f000 f80a bl 1002f5f6 <.text_58> +1002f5e2: fb02 1104 mla r1, r2, r4, r1 +1002f5e6: 2254 movs r2, #84 ; 0x54 +1002f5e8: fb02 1105 mla r1, r2, r5, r1 +1002f5ec: 1841 adds r1, r0, r1 +1002f5ee: 9807 ldr r0, [sp, #28] +1002f5f0: f881 00bb strb.w r0, [r1, #187] ; 0xbb +1002f5f4: bdf1 pop {r0, r4, r5, r6, r7, pc} + +1002f5f6 <.text_58>: +1002f5f6: f44f 62a8 mov.w r2, #1344 ; 0x540 +1002f5fa: fb02 7101 mla r1, r2, r1, r7 +1002f5fe: f44f 72a8 mov.w r2, #336 ; 0x150 +1002f602: 4770 bx lr + +1002f604 : +1002f604: b5f8 push {r3, r4, r5, r6, r7, lr} +1002f606: 4604 mov r4, r0 +1002f608: f641 30a4 movw r0, #7076 ; 0x1ba4 +1002f60c: 460d mov r5, r1 +1002f60e: 5907 ldr r7, [r0, r4] +1002f610: 6c38 ldr r0, [r7, #64] ; 0x40 +1002f612: 4616 mov r6, r2 +1002f614: b910 cbnz r0, 1002f61c +1002f616: 2300 movs r3, #0 +1002f618: f000 f833 bl 1002f682 <.text_60> +1002f61c: 2301 movs r3, #1 +1002f61e: f000 f830 bl 1002f682 <.text_60> +1002f622: 2302 movs r3, #2 +1002f624: f000 f82d bl 1002f682 <.text_60> +1002f628: 8820 ldrh r0, [r4, #0] +1002f62a: 2816 cmp r0, #22 +1002f62c: bf18 it ne +1002f62e: 2817 cmpne r0, #23 +1002f630: d007 beq.n 1002f642 +1002f632: 2819 cmp r0, #25 +1002f634: bf18 it ne +1002f636: 281a cmpne r0, #26 +1002f638: d003 beq.n 1002f642 +1002f63a: 2818 cmp r0, #24 +1002f63c: bf18 it ne +1002f63e: 281b cmpne r0, #27 +1002f640: d102 bne.n 1002f648 +1002f642: 2306 movs r3, #6 +1002f644: f000 f81d bl 1002f682 <.text_60> +1002f648: f897 004d ldrb.w r0, [r7, #77] ; 0x4d +1002f64c: 2802 cmp r0, #2 +1002f64e: db17 blt.n 1002f680 +1002f650: 2303 movs r3, #3 +1002f652: f000 f816 bl 1002f682 <.text_60> +1002f656: 8820 ldrh r0, [r4, #0] +1002f658: 2816 cmp r0, #22 +1002f65a: bf18 it ne +1002f65c: 2817 cmpne r0, #23 +1002f65e: d007 beq.n 1002f670 +1002f660: 2819 cmp r0, #25 +1002f662: bf18 it ne +1002f664: 281a cmpne r0, #26 +1002f666: d003 beq.n 1002f670 +1002f668: 2818 cmp r0, #24 +1002f66a: bf18 it ne +1002f66c: 281b cmpne r0, #27 +1002f66e: d107 bne.n 1002f680 +1002f670: 462a mov r2, r5 +1002f672: 4631 mov r1, r6 +1002f674: 4620 mov r0, r4 +1002f676: b001 add sp, #4 +1002f678: e8bd 40f0 ldmia.w sp!, {r4, r5, r6, r7, lr} +1002f67c: 2307 movs r3, #7 +1002f67e: e484 b.n 1002ef8a +1002f680: bdf1 pop {r0, r4, r5, r6, r7, pc} + +1002f682 <.text_60>: +1002f682: 462a mov r2, r5 +1002f684: 4631 mov r1, r6 +1002f686: 4620 mov r0, r4 +1002f688: e47f b.n 1002ef8a + +1002f68a : +1002f68a: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +1002f68e: b082 sub sp, #8 +1002f690: 9e0a ldr r6, [sp, #40] ; 0x28 +1002f692: 9c0b ldr r4, [sp, #44] ; 0x2c +1002f694: 4680 mov r8, r0 +1002f696: 4689 mov r9, r1 +1002f698: 4692 mov sl, r2 +1002f69a: 461d mov r5, r3 +1002f69c: 2700 movs r7, #0 +1002f69e: e00d b.n 1002f6bc +1002f6a0: 9500 str r5, [sp, #0] +1002f6a2: 4653 mov r3, sl +1002f6a4: 5dba ldrb r2, [r7, r6] +1002f6a6: 4649 mov r1, r9 +1002f6a8: 4640 mov r0, r8 +1002f6aa: f000 fae4 bl 1002fc76 +1002f6ae: 5dbb ldrb r3, [r7, r6] +1002f6b0: 4601 mov r1, r0 +1002f6b2: 464a mov r2, r9 +1002f6b4: 4640 mov r0, r8 +1002f6b6: f000 fb07 bl 1002fcc8 +1002f6ba: 1c7f adds r7, r7, #1 +1002f6bc: 42a7 cmp r7, r4 +1002f6be: dbef blt.n 1002f6a0 +1002f6c0: e8bd 87f3 ldmia.w sp!, {r0, r1, r4, r5, r6, r7, r8, r9, sl, pc} + +1002f6c4 : +1002f6c4: b081 sub sp, #4 +1002f6c6: f990 1000 ldrsb.w r1, [r0] +1002f6ca: 2200 movs r2, #0 +1002f6cc: 9200 str r2, [sp, #0] +1002f6ce: 9a00 ldr r2, [sp, #0] +1002f6d0: 5612 ldrsb r2, [r2, r0] +1002f6d2: 428a cmp r2, r1 +1002f6d4: bfb8 it lt +1002f6d6: 4611 movlt r1, r2 +1002f6d8: 9a00 ldr r2, [sp, #0] +1002f6da: 1c52 adds r2, r2, #1 +1002f6dc: 2a04 cmp r2, #4 +1002f6de: 9200 str r2, [sp, #0] +1002f6e0: dbf5 blt.n 1002f6ce +1002f6e2: 4608 mov r0, r1 +1002f6e4: b001 add sp, #4 +1002f6e6: 4770 bx lr + +1002f6e8 : +1002f6e8: b570 push {r4, r5, r6, lr} +1002f6ea: b08e sub sp, #56 ; 0x38 +1002f6ec: 4604 mov r4, r0 +1002f6ee: 460d mov r5, r1 +1002f6f0: f04f 36ff mov.w r6, #4294967295 +1002f6f4: a800 add r0, sp, #0 +1002f6f6: f20f 61b4 addw r1, pc, #1716 ; 0x6b4 +1002f6fa: 2238 movs r2, #56 ; 0x38 +1002f6fc: f7fe fed6 bl 1002e4ac <__iar_unaligned___aeabi_memcpy4> +1002f700: b90c cbnz r4, 1002f706 +1002f702: 1e6e subs r6, r5, #1 +1002f704: e00a b.n 1002f71c +1002f706: 2c01 cmp r4, #1 +1002f708: d108 bne.n 1002f71c +1002f70a: 2000 movs r0, #0 +1002f70c: a900 add r1, sp, #0 +1002f70e: 5c41 ldrb r1, [r0, r1] +1002f710: 42a9 cmp r1, r5 +1002f712: bf08 it eq +1002f714: 4606 moveq r6, r0 +1002f716: 1c40 adds r0, r0, #1 +1002f718: 2836 cmp r0, #54 ; 0x36 +1002f71a: d3f7 bcc.n 1002f70c +1002f71c: b270 sxtb r0, r6 +1002f71e: b00e add sp, #56 ; 0x38 +1002f720: bd70 pop {r4, r5, r6, pc} + +1002f722 : +1002f722: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +1002f726: 4601 mov r1, r0 +1002f728: 4615 mov r5, r2 +1002f72a: f641 30a4 movw r0, #7076 ; 0x1ba4 +1002f72e: f641 1201 movw r2, #6401 ; 0x1901 +1002f732: b084 sub sp, #16 +1002f734: 5846 ldr r6, [r0, r1] +1002f736: f812 c001 ldrb.w ip, [r2, r1] +1002f73a: f04f 37ff mov.w r7, #4294967295 +1002f73e: 243f movs r4, #63 ; 0x3f +1002f740: 4638 mov r0, r7 +1002f742: f1bc 0f02 cmp.w ip, #2 +1002f746: 4680 mov r8, r0 +1002f748: 4681 mov r9, r0 +1002f74a: d106 bne.n 1002f75a +1002f74c: f896 c05b ldrb.w ip, [r6, #91] ; 0x5b +1002f750: f1bc 0f01 cmp.w ip, #1 +1002f754: f040 80a6 bne.w 1002f8a4 +1002f758: e003 b.n 1002f762 +1002f75a: f1bc 0f00 cmp.w ip, #0 +1002f75e: f000 80a1 beq.w 1002f8a4 +1002f762: 1851 adds r1, r2, r1 +1002f764: 78c9 ldrb r1, [r1, #3] +1002f766: 2901 cmp r1, #1 +1002f768: d006 beq.n 1002f778 +1002f76a: d313 bcc.n 1002f794 +1002f76c: 2903 cmp r1, #3 +1002f76e: d00b beq.n 1002f788 +1002f770: d307 bcc.n 1002f782 +1002f772: 2904 cmp r1, #4 +1002f774: d00b beq.n 1002f78e +1002f776: e00d b.n 1002f794 +1002f778: f04f 0a02 mov.w sl, #2 +1002f77c: b985 cbnz r5, 1002f7a0 +1002f77e: 2700 movs r7, #0 +1002f780: e011 b.n 1002f7a6 +1002f782: f04f 0a01 mov.w sl, #1 +1002f786: e7f9 b.n 1002f77c +1002f788: f04f 0a00 mov.w sl, #0 +1002f78c: e7f6 b.n 1002f77c +1002f78e: f04f 0a03 mov.w sl, #3 +1002f792: e7f3 b.n 1002f77c +1002f794: b915 cbnz r5, 1002f79c +1002f796: f896 a0b9 ldrb.w sl, [r6, #185] ; 0xb9 +1002f79a: e7f0 b.n 1002f77e +1002f79c: f896 a0ba ldrb.w sl, [r6, #186] ; 0xba +1002f7a0: 2d01 cmp r5, #1 +1002f7a2: bf08 it eq +1002f7a4: 2701 moveq r7, #1 +1002f7a6: b913 cbnz r3, 1002f7ae +1002f7a8: f04f 0800 mov.w r8, #0 +1002f7ac: e00d b.n 1002f7ca +1002f7ae: 2b01 cmp r3, #1 +1002f7b0: bf08 it eq +1002f7b2: f04f 0801 moveq.w r8, #1 +1002f7b6: d008 beq.n 1002f7ca +1002f7b8: 2b02 cmp r3, #2 +1002f7ba: bf08 it eq +1002f7bc: f04f 0802 moveq.w r8, #2 +1002f7c0: d003 beq.n 1002f7ca +1002f7c2: 2b03 cmp r3, #3 +1002f7c4: bf08 it eq +1002f7c6: f04f 0803 moveq.w r8, #3 +1002f7ca: 9a0d ldr r2, [sp, #52] ; 0x34 +1002f7cc: 990e ldr r1, [sp, #56] ; 0x38 +1002f7ce: 1e92 subs r2, r2, #2 +1002f7d0: d030 beq.n 1002f834 +1002f7d2: 1e92 subs r2, r2, #2 +1002f7d4: d02e beq.n 1002f834 +1002f7d6: 1fd2 subs r2, r2, #7 +1002f7d8: d02c beq.n 1002f834 +1002f7da: 1e52 subs r2, r2, #1 +1002f7dc: d030 beq.n 1002f840 +1002f7de: 1f92 subs r2, r2, #6 +1002f7e0: d02e beq.n 1002f840 +1002f7e2: 1f12 subs r2, r2, #4 +1002f7e4: d026 beq.n 1002f834 +1002f7e6: 1e92 subs r2, r2, #2 +1002f7e8: d02a beq.n 1002f840 +1002f7ea: 3a0c subs r2, #12 +1002f7ec: d028 beq.n 1002f840 +1002f7ee: 3a0c subs r2, #12 +1002f7f0: d026 beq.n 1002f840 +1002f7f2: 3a18 subs r2, #24 +1002f7f4: d024 beq.n 1002f840 +1002f7f6: 3a18 subs r2, #24 +1002f7f8: d022 beq.n 1002f840 +1002f7fa: 3a0c subs r2, #12 +1002f7fc: d020 beq.n 1002f840 +1002f7fe: 3a14 subs r2, #20 +1002f800: 2a07 cmp r2, #7 +1002f802: d922 bls.n 1002f84a +1002f804: 3a08 subs r2, #8 +1002f806: 2a07 cmp r2, #7 +1002f808: d929 bls.n 1002f85e +1002f80a: 3a08 subs r2, #8 +1002f80c: 2a07 cmp r2, #7 +1002f80e: d929 bls.n 1002f864 +1002f810: 3a08 subs r2, #8 +1002f812: 2a07 cmp r2, #7 +1002f814: d929 bls.n 1002f86a +1002f816: 3a08 subs r2, #8 +1002f818: 2a09 cmp r2, #9 +1002f81a: d929 bls.n 1002f870 +1002f81c: 3a0a subs r2, #10 +1002f81e: 2a09 cmp r2, #9 +1002f820: d929 bls.n 1002f876 +1002f822: 3a0a subs r2, #10 +1002f824: 2a09 cmp r2, #9 +1002f826: d929 bls.n 1002f87c +1002f828: 3a0a subs r2, #10 +1002f82a: 2a09 cmp r2, #9 +1002f82c: bf98 it ls +1002f82e: f04f 0909 movls.w r9, #9 +1002f832: e002 b.n 1002f83a +1002f834: f04f 0900 mov.w r9, #0 +1002f838: 46c8 mov r8, r9 +1002f83a: bb15 cbnz r5, 1002f882 +1002f83c: 2000 movs r0, #0 +1002f83e: e023 b.n 1002f888 +1002f840: f04f 0901 mov.w r9, #1 +1002f844: f04f 0800 mov.w r8, #0 +1002f848: e7f7 b.n 1002f83a +1002f84a: f04f 0902 mov.w r9, #2 +1002f84e: 2d01 cmp r5, #1 +1002f850: d1f3 bne.n 1002f83a +1002f852: f1b8 0f02 cmp.w r8, #2 +1002f856: d116 bne.n 1002f886 +1002f858: f04f 0801 mov.w r8, #1 +1002f85c: e013 b.n 1002f886 +1002f85e: f04f 0903 mov.w r9, #3 +1002f862: e7f4 b.n 1002f84e +1002f864: f04f 0904 mov.w r9, #4 +1002f868: e7e7 b.n 1002f83a +1002f86a: f04f 0905 mov.w r9, #5 +1002f86e: e7e4 b.n 1002f83a +1002f870: f04f 0906 mov.w r9, #6 +1002f874: e7e1 b.n 1002f83a +1002f876: f04f 0907 mov.w r9, #7 +1002f87a: e7de b.n 1002f83a +1002f87c: f04f 0908 mov.w r9, #8 +1002f880: e7db b.n 1002f83a +1002f882: 2d01 cmp r5, #1 +1002f884: d102 bne.n 1002f88c +1002f886: 2001 movs r0, #1 +1002f888: f7ff ff2e bl 1002f6e8 +1002f88c: f117 0f01 cmn.w r7, #1 +1002f890: bf18 it ne +1002f892: f118 0f01 cmnne.w r8, #1 +1002f896: d005 beq.n 1002f8a4 +1002f898: f119 0f01 cmn.w r9, #1 +1002f89c: bf18 it ne +1002f89e: f110 0f01 cmnne.w r0, #1 +1002f8a2: d101 bne.n 1002f8a8 +1002f8a4: 203f movs r0, #63 ; 0x3f +1002f8a6: e036 b.n 1002f916 +1002f8a8: bba5 cbnz r5, 1002f914 +1002f8aa: a900 add r1, sp, #0 +1002f8ac: 2200 movs r2, #0 +1002f8ae: 2300 movs r3, #0 +1002f8b0: 4614 mov r4, r2 +1002f8b2: c11c stmia r1!, {r2, r3, r4} +1002f8b4: f1b8 0f02 cmp.w r8, #2 +1002f8b8: bfa8 it ge +1002f8ba: f04f 0801 movge.w r8, #1 +1002f8be: 990c ldr r1, [sp, #48] ; 0x30 +1002f8c0: 231c movs r3, #28 +1002f8c2: f44f 748c mov.w r4, #280 ; 0x118 +1002f8c6: fb03 f309 mul.w r3, r3, r9 +1002f8ca: fb04 f408 mul.w r4, r4, r8 +1002f8ce: f44f 750c mov.w r5, #560 ; 0x230 +1002f8d2: f10d 0c00 add.w ip, sp, #0 +1002f8d6: 19a7 adds r7, r4, r6 +1002f8d8: 19df adds r7, r3, r7 +1002f8da: eb07 0740 add.w r7, r7, r0, lsl #1 +1002f8de: 19cf adds r7, r1, r7 +1002f8e0: fb05 7702 mla r7, r5, r2, r7 +1002f8e4: f897 7bc7 ldrb.w r7, [r7, #3015] ; 0xbc7 +1002f8e8: f802 700c strb.w r7, [r2, ip] +1002f8ec: 1c52 adds r2, r2, #1 +1002f8ee: 2a04 cmp r2, #4 +1002f8f0: dbf1 blt.n 1002f8d6 +1002f8f2: f1ba 0f03 cmp.w sl, #3 +1002f8f6: d103 bne.n 1002f900 +1002f8f8: a800 add r0, sp, #0 +1002f8fa: f7ff fee3 bl 1002f6c4 +1002f8fe: e008 b.n 1002f912 +1002f900: fb05 620a mla r2, r5, sl, r6 +1002f904: 18a2 adds r2, r4, r2 +1002f906: 189a adds r2, r3, r2 +1002f908: eb02 0040 add.w r0, r2, r0, lsl #1 +1002f90c: 1808 adds r0, r1, r0 +1002f90e: f990 0bc7 ldrsb.w r0, [r0, #3015] ; 0xbc7 +1002f912: 4604 mov r4, r0 +1002f914: 4620 mov r0, r4 +1002f916: b004 add sp, #16 +1002f918: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + +1002f91c : +1002f91c: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +1002f920: 4680 mov r8, r0 +1002f922: f641 30a4 movw r0, #7076 ; 0x1ba4 +1002f926: b083 sub sp, #12 +1002f928: f850 b008 ldr.w fp, [r0, r8] +1002f92c: 2100 movs r1, #0 +1002f92e: 202e movs r0, #46 ; 0x2e +1002f930: 9101 str r1, [sp, #4] +1002f932: 2600 movs r6, #0 +1002f934: 2700 movs r7, #0 +1002f936: 2400 movs r4, #0 +1002f938: 9901 ldr r1, [sp, #4] +1002f93a: f44f 720c mov.w r2, #560 ; 0x230 +1002f93e: fb02 b101 mla r1, r2, r1, fp +1002f942: f44f 728c mov.w r2, #280 ; 0x118 +1002f946: fb02 1106 mla r1, r2, r6, r1 +1002f94a: eb01 0147 add.w r1, r1, r7, lsl #1 +1002f94e: 221c movs r2, #28 +1002f950: fb02 1904 mla r9, r2, r4, r1 +1002f954: 2500 movs r5, #0 +1002f956: f999 abc7 ldrsb.w sl, [r9, #3015] ; 0xbc7 +1002f95a: f641 11b4 movw r1, #6580 ; 0x19b4 +1002f95e: f851 100b ldr.w r1, [r1, fp] +1002f962: 2901 cmp r1, #1 +1002f964: d127 bne.n 1002f9b6 +1002f966: 2c05 cmp r4, #5 +1002f968: d103 bne.n 1002f972 +1002f96a: 2005 movs r0, #5 +1002f96c: 9000 str r0, [sp, #0] +1002f96e: 2303 movs r3, #3 +1002f970: e014 b.n 1002f99c +1002f972: 2c04 cmp r4, #4 +1002f974: d103 bne.n 1002f97e +1002f976: 2004 movs r0, #4 +1002f978: 9000 str r0, [sp, #0] +1002f97a: 2302 movs r3, #2 +1002f97c: e00e b.n 1002f99c +1002f97e: 2c03 cmp r4, #3 +1002f980: d103 bne.n 1002f98a +1002f982: 2003 movs r0, #3 +1002f984: 9000 str r0, [sp, #0] +1002f986: 2301 movs r3, #1 +1002f988: e008 b.n 1002f99c +1002f98a: 2c02 cmp r4, #2 +1002f98c: d101 bne.n 1002f992 +1002f98e: 2002 movs r0, #2 +1002f990: e002 b.n 1002f998 +1002f992: 2c01 cmp r4, #1 +1002f994: d105 bne.n 1002f9a2 +1002f996: 2001 movs r0, #1 +1002f998: 9000 str r0, [sp, #0] +1002f99a: 2300 movs r3, #0 +1002f99c: 462a mov r2, r5 +1002f99e: 2100 movs r1, #0 +1002f9a0: e005 b.n 1002f9ae +1002f9a2: b96c cbnz r4, 1002f9c0 +1002f9a4: 2000 movs r0, #0 +1002f9a6: 9000 str r0, [sp, #0] +1002f9a8: 2300 movs r3, #0 +1002f9aa: 462a mov r2, r5 +1002f9ac: 4601 mov r1, r0 +1002f9ae: 4640 mov r0, r8 +1002f9b0: f7fe fda8 bl 1002e504 +1002f9b4: e004 b.n 1002f9c0 +1002f9b6: f641 1003 movw r0, #6403 ; 0x1903 +1002f9ba: f810 0008 ldrb.w r0, [r0, r8] +1002f9be: 0040 lsls r0, r0, #1 +1002f9c0: f1ba 0f3f cmp.w sl, #63 ; 0x3f +1002f9c4: d005 beq.n 1002f9d2 +1002f9c6: eb05 0209 add.w r2, r5, r9 +1002f9ca: ebaa 0100 sub.w r1, sl, r0 +1002f9ce: f882 1bc7 strb.w r1, [r2, #3015] ; 0xbc7 +1002f9d2: 1c6d adds r5, r5, #1 +1002f9d4: 2d02 cmp r5, #2 +1002f9d6: dbc0 blt.n 1002f95a +1002f9d8: 1c64 adds r4, r4, #1 +1002f9da: 2c0a cmp r4, #10 +1002f9dc: dbac blt.n 1002f938 +1002f9de: 1c7f adds r7, r7, #1 +1002f9e0: 2f0e cmp r7, #14 +1002f9e2: dba8 blt.n 1002f936 +1002f9e4: 1c76 adds r6, r6, #1 +1002f9e6: 2e02 cmp r6, #2 +1002f9e8: dba4 blt.n 1002f934 +1002f9ea: 9901 ldr r1, [sp, #4] +1002f9ec: 1c49 adds r1, r1, #1 +1002f9ee: 2904 cmp r1, #4 +1002f9f0: 9101 str r1, [sp, #4] +1002f9f2: db9e blt.n 1002f932 +1002f9f4: e8bd 8ff7 ldmia.w sp!, {r0, r1, r2, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1002f9f8 : +1002f9f8: b570 push {r4, r5, r6, lr} +1002f9fa: f641 31a4 movw r1, #7076 ; 0x1ba4 +1002f9fe: 5808 ldr r0, [r1, r0] +1002fa00: 2100 movs r1, #0 +1002fa02: 2200 movs r2, #0 +1002fa04: 2300 movs r3, #0 +1002fa06: 2400 movs r4, #0 +1002fa08: f44f 750c mov.w r5, #560 ; 0x230 +1002fa0c: fb05 0501 mla r5, r5, r1, r0 +1002fa10: f44f 768c mov.w r6, #280 ; 0x118 +1002fa14: fb06 5502 mla r5, r6, r2, r5 +1002fa18: 261c movs r6, #28 +1002fa1a: fb06 5503 mla r5, r6, r3, r5 +1002fa1e: eb05 0544 add.w r5, r5, r4, lsl #1 +1002fa22: 263f movs r6, #63 ; 0x3f +1002fa24: 1c64 adds r4, r4, #1 +1002fa26: f885 6bc7 strb.w r6, [r5, #3015] ; 0xbc7 +1002fa2a: 2c0e cmp r4, #14 +1002fa2c: f885 6bc8 strb.w r6, [r5, #3016] ; 0xbc8 +1002fa30: dbea blt.n 1002fa08 +1002fa32: 1c5b adds r3, r3, #1 +1002fa34: 2b0a cmp r3, #10 +1002fa36: dbe6 blt.n 1002fa06 +1002fa38: 1c52 adds r2, r2, #1 +1002fa3a: 2a02 cmp r2, #2 +1002fa3c: dbe2 blt.n 1002fa04 +1002fa3e: 1c49 adds r1, r1, #1 +1002fa40: 2904 cmp r1, #4 +1002fa42: dbde blt.n 1002fa02 +1002fa44: bd70 pop {r4, r5, r6, pc} + +1002fa46 : +1002fa46: e92d 4ff7 stmdb sp!, {r0, r1, r2, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1002fa4a: 460c mov r4, r1 +1002fa4c: f641 31a4 movw r1, #7076 ; 0x1ba4 +1002fa50: 2500 movs r5, #0 +1002fa52: 5808 ldr r0, [r1, r0] +1002fa54: 9001 str r0, [sp, #4] +1002fa56: 469b mov fp, r3 +1002fa58: 980e ldr r0, [sp, #56] ; 0x38 +1002fa5a: f88d 5000 strb.w r5, [sp] +1002fa5e: 2700 movs r7, #0 +1002fa60: 462e mov r6, r5 +1002fa62: f10d 0101 add.w r1, sp, #1 +1002fa66: f7f7 fae8 bl 1002703a +1002fa6a: b118 cbz r0, 1002fa74 +1002fa6c: 980f ldr r0, [sp, #60] ; 0x3c +1002fa6e: a900 add r1, sp, #0 +1002fa70: f7f7 fae3 bl 1002703a +1002fa74: f99d 0000 ldrsb.w r0, [sp] +1002fa78: 2840 cmp r0, #64 ; 0x40 +1002fa7a: bfa4 itt ge +1002fa7c: 203f movge r0, #63 ; 0x3f +1002fa7e: f88d 0000 strbge.w r0, [sp] +1002fa82: 2203 movs r2, #3 +1002fa84: a169 add r1, pc, #420 ; (adr r1, 1002fc2c <.text_70>) +1002fa86: f000 f8f3 bl 1002fc70 <.text_84> +1002fa8a: b9c0 cbnz r0, 1002fabe +1002fa8c: 2203 movs r2, #3 +1002fa8e: a168 add r1, pc, #416 ; (adr r1, 1002fc30 <.text_71>) +1002fa90: f000 f8ee bl 1002fc70 <.text_84> +1002fa94: b110 cbz r0, 1002fa9c +1002fa96: f44f 770c mov.w r7, #560 ; 0x230 +1002fa9a: e010 b.n 1002fabe +1002fa9c: 2204 movs r2, #4 +1002fa9e: f20f 3144 addw r1, pc, #836 ; 0x344 +1002faa2: f000 f8e5 bl 1002fc70 <.text_84> +1002faa6: b110 cbz r0, 1002faae +1002faa8: f44f 678c mov.w r7, #1120 ; 0x460 +1002faac: e007 b.n 1002fabe +1002faae: 2204 movs r2, #4 +1002fab0: f20f 3138 addw r1, pc, #824 ; 0x338 +1002fab4: f000 f8dc bl 1002fc70 <.text_84> +1002fab8: b108 cbz r0, 1002fabe +1002faba: f44f 67d2 mov.w r7, #1680 ; 0x690 +1002fabe: f8dd 8030 ldr.w r8, [sp, #48] ; 0x30 +1002fac2: f8dd 9034 ldr.w r9, [sp, #52] ; 0x34 +1002fac6: f20f 1a6c addw sl, pc, #364 ; 0x16c +1002faca: 2203 movs r2, #3 +1002facc: a15a add r1, pc, #360 ; (adr r1, 1002fc38 <.text_73>) +1002face: 4640 mov r0, r8 +1002fad0: f7f7 faa6 bl 10027020 +1002fad4: b110 cbz r0, 1002fadc +1002fad6: f000 f8c1 bl 1002fc5c <.text_82> +1002fada: b950 cbnz r0, 1002faf2 +1002fadc: 2204 movs r2, #4 +1002fade: f20f 3114 addw r1, pc, #788 ; 0x314 +1002fae2: 4640 mov r0, r8 +1002fae4: f7f7 fa9c bl 10027020 +1002fae8: b188 cbz r0, 1002fb0e +1002faea: f000 f8b7 bl 1002fc5c <.text_82> +1002faee: b170 cbz r0, 1002fb0e +1002faf0: 2601 movs r6, #1 +1002faf2: 2203 movs r2, #3 +1002faf4: a151 add r1, pc, #324 ; (adr r1, 1002fc3c <.text_74>) +1002faf6: f000 f891 bl 1002fc1c <.text_68> +1002fafa: 2800 cmp r0, #0 +1002fafc: d166 bne.n 1002fbcc +1002fafe: 2203 movs r2, #3 +1002fb00: a14f add r1, pc, #316 ; (adr r1, 1002fc40 <.text_75>) +1002fb02: f000 f88b bl 1002fc1c <.text_68> +1002fb06: 2800 cmp r0, #0 +1002fb08: d052 beq.n 1002fbb0 +1002fb0a: 2501 movs r5, #1 +1002fb0c: e05e b.n 1002fbcc +1002fb0e: a44d add r4, pc, #308 ; (adr r4, 1002fc44 <.text_76>) +1002fb10: f000 f8a9 bl 1002fc66 <.text_83> +1002fb14: b120 cbz r0, 1002fb20 +1002fb16: f000 f8a1 bl 1002fc5c <.text_82> +1002fb1a: b108 cbz r0, 1002fb20 +1002fb1c: 2602 movs r6, #2 +1002fb1e: e7e8 b.n 1002faf2 +1002fb20: f000 f8a1 bl 1002fc66 <.text_83> +1002fb24: b120 cbz r0, 1002fb30 +1002fb26: f000 f87c bl 1002fc22 <.text_69> +1002fb2a: b108 cbz r0, 1002fb30 +1002fb2c: 2603 movs r6, #3 +1002fb2e: e7e0 b.n 1002faf2 +1002fb30: f000 f899 bl 1002fc66 <.text_83> +1002fb34: b130 cbz r0, 1002fb44 +1002fb36: 2202 movs r2, #2 +1002fb38: a143 add r1, pc, #268 ; (adr r1, 1002fc48 <.text_77>) +1002fb3a: f000 f874 bl 1002fc26 <.text_69+0x4> +1002fb3e: b108 cbz r0, 1002fb44 +1002fb40: 2604 movs r6, #4 +1002fb42: e7d6 b.n 1002faf2 +1002fb44: a641 add r6, pc, #260 ; (adr r6, 1002fc4c <.text_78>) +1002fb46: f000 f88e bl 1002fc66 <.text_83> +1002fb4a: b130 cbz r0, 1002fb5a +1002fb4c: 2202 movs r2, #2 +1002fb4e: 4631 mov r1, r6 +1002fb50: f000 f869 bl 1002fc26 <.text_69+0x4> +1002fb54: b108 cbz r0, 1002fb5a +1002fb56: 2605 movs r6, #5 +1002fb58: e7cb b.n 1002faf2 +1002fb5a: a43d add r4, pc, #244 ; (adr r4, 1002fc50 <.text_79>) +1002fb5c: 2203 movs r2, #3 +1002fb5e: f000 f883 bl 1002fc68 <.text_83+0x2> +1002fb62: b120 cbz r0, 1002fb6e +1002fb64: f000 f87a bl 1002fc5c <.text_82> +1002fb68: b108 cbz r0, 1002fb6e +1002fb6a: 2606 movs r6, #6 +1002fb6c: e7c1 b.n 1002faf2 +1002fb6e: 2203 movs r2, #3 +1002fb70: f000 f87a bl 1002fc68 <.text_83+0x2> +1002fb74: b120 cbz r0, 1002fb80 +1002fb76: f000 f854 bl 1002fc22 <.text_69> +1002fb7a: b108 cbz r0, 1002fb80 +1002fb7c: 2607 movs r6, #7 +1002fb7e: e7b8 b.n 1002faf2 +1002fb80: 2203 movs r2, #3 +1002fb82: f000 f871 bl 1002fc68 <.text_83+0x2> +1002fb86: b130 cbz r0, 1002fb96 +1002fb88: 2202 movs r2, #2 +1002fb8a: a12f add r1, pc, #188 ; (adr r1, 1002fc48 <.text_77>) +1002fb8c: f000 f84b bl 1002fc26 <.text_69+0x4> +1002fb90: b108 cbz r0, 1002fb96 +1002fb92: 2608 movs r6, #8 +1002fb94: e7ad b.n 1002faf2 +1002fb96: 2203 movs r2, #3 +1002fb98: f000 f866 bl 1002fc68 <.text_83+0x2> +1002fb9c: 2800 cmp r0, #0 +1002fb9e: d03b beq.n 1002fc18 +1002fba0: 2202 movs r2, #2 +1002fba2: 4631 mov r1, r6 +1002fba4: f000 f83f bl 1002fc26 <.text_69+0x4> +1002fba8: 2800 cmp r0, #0 +1002fbaa: d035 beq.n 1002fc18 +1002fbac: 2609 movs r6, #9 +1002fbae: e7a0 b.n 1002faf2 +1002fbb0: 2203 movs r2, #3 +1002fbb2: a128 add r1, pc, #160 ; (adr r1, 1002fc54 <.text_80>) +1002fbb4: f000 f832 bl 1002fc1c <.text_68> +1002fbb8: b108 cbz r0, 1002fbbe +1002fbba: 2502 movs r5, #2 +1002fbbc: e006 b.n 1002fbcc +1002fbbe: 2204 movs r2, #4 +1002fbc0: f20f 2138 addw r1, pc, #568 ; 0x238 +1002fbc4: f000 f82a bl 1002fc1c <.text_68> +1002fbc8: b100 cbz r0, 1002fbcc +1002fbca: 2503 movs r5, #3 +1002fbcc: 9802 ldr r0, [sp, #8] +1002fbce: f20f 2134 addw r1, pc, #564 ; 0x234 +1002fbd2: 2204 movs r2, #4 +1002fbd4: f7f7 fa24 bl 10027020 +1002fbd8: b1f0 cbz r0, 1002fc18 +1002fbda: f89d 1001 ldrb.w r1, [sp, #1] +1002fbde: 2000 movs r0, #0 +1002fbe0: f7ff fd82 bl 1002f6e8 +1002fbe4: f110 0f01 cmn.w r0, #1 +1002fbe8: d016 beq.n 1002fc18 +1002fbea: 2d02 cmp r5, #2 +1002fbec: 9901 ldr r1, [sp, #4] +1002fbee: bfa8 it ge +1002fbf0: 2501 movge r5, #1 +1002fbf2: 1879 adds r1, r7, r1 +1002fbf4: f44f 728c mov.w r2, #280 ; 0x118 +1002fbf8: fb02 1105 mla r1, r2, r5, r1 +1002fbfc: 221c movs r2, #28 +1002fbfe: fb02 1106 mla r1, r2, r6, r1 +1002fc02: eb01 0140 add.w r1, r1, r0, lsl #1 +1002fc06: f99d 2000 ldrsb.w r2, [sp] +1002fc0a: f991 3bc7 ldrsb.w r3, [r1, #3015] ; 0xbc7 +1002fc0e: 429a cmp r2, r3 +1002fc10: bfc8 it gt +1002fc12: 461a movgt r2, r3 +1002fc14: f881 2bc7 strb.w r2, [r1, #3015] ; 0xbc7 +1002fc18: e8bd 8ff7 ldmia.w sp!, {r0, r1, r2, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1002fc1c <.text_68>: +1002fc1c: 4658 mov r0, fp +1002fc1e: f7f7 b9ff b.w 10027020 + +1002fc22 <.text_69>: +1002fc22: 2202 movs r2, #2 +1002fc24: a10c add r1, pc, #48 ; (adr r1, 1002fc58 <.text_81>) +1002fc26: 4648 mov r0, r9 +1002fc28: f7f7 b9fa b.w 10027020 + +1002fc2c <.text_70>: +1002fc2c: 00434346 .word 0x00434346 + +1002fc30 <.text_71>: +1002fc30: 004b4b4d .word 0x004b4b4d + +1002fc34 <.text_72>: +1002fc34: 00005431 .word 0x00005431 + +1002fc38 <.text_73>: +1002fc38: 004b4343 .word 0x004b4343 + +1002fc3c <.text_74>: +1002fc3c: 004d3032 .word 0x004d3032 + +1002fc40 <.text_75>: +1002fc40: 004d3034 .word 0x004d3034 + +1002fc44 <.text_76>: +1002fc44: 00005448 .word 0x00005448 + +1002fc48 <.text_77>: +1002fc48: 00005433 .word 0x00005433 + +1002fc4c <.text_78>: +1002fc4c: 00005434 .word 0x00005434 + +1002fc50 <.text_79>: +1002fc50: 00544856 .word 0x00544856 + +1002fc54 <.text_80>: +1002fc54: 004d3038 .word 0x004d3038 + +1002fc58 <.text_81>: +1002fc58: 00005432 .word 0x00005432 + +1002fc5c <.text_82>: +1002fc5c: 2202 movs r2, #2 +1002fc5e: 4651 mov r1, sl +1002fc60: 4648 mov r0, r9 +1002fc62: f7f7 b9dd b.w 10027020 + +1002fc66 <.text_83>: +1002fc66: 2202 movs r2, #2 +1002fc68: 4621 mov r1, r4 +1002fc6a: 4640 mov r0, r8 +1002fc6c: f7f7 b9d8 b.w 10027020 + +1002fc70 <.text_84>: +1002fc70: 4620 mov r0, r4 +1002fc72: f7f7 b9d5 b.w 10027020 + +1002fc76 : +1002fc76: b538 push {r3, r4, r5, lr} +1002fc78: 8805 ldrh r5, [r0, #0] +1002fc7a: 243e movs r4, #62 ; 0x3e +1002fc7c: 2d16 cmp r5, #22 +1002fc7e: bf18 it ne +1002fc80: 2d17 cmpne r5, #23 +1002fc82: d01f beq.n 1002fcc4 +1002fc84: 2d19 cmp r5, #25 +1002fc86: bf18 it ne +1002fc88: 2d1a cmpne r5, #26 +1002fc8a: d01b beq.n 1002fcc4 +1002fc8c: 2d18 cmp r5, #24 +1002fc8e: bf18 it ne +1002fc90: 2d1b cmpne r5, #27 +1002fc92: d017 beq.n 1002fcc4 +1002fc94: 2d1c cmp r5, #28 +1002fc96: bf18 it ne +1002fc98: 2d1d cmpne r5, #29 +1002fc9a: d013 beq.n 1002fcc4 +1002fc9c: 2d1e cmp r5, #30 +1002fc9e: bf18 it ne +1002fca0: 2d13 cmpne r5, #19 +1002fca2: d00f beq.n 1002fcc4 +1002fca4: 2d14 cmp r5, #20 +1002fca6: bf18 it ne +1002fca8: 2d15 cmpne r5, #21 +1002fcaa: d00b beq.n 1002fcc4 +1002fcac: 2d10 cmp r5, #16 +1002fcae: bf1c itt ne +1002fcb0: 2d11 cmpne r5, #17 +1002fcb2: 2d12 cmpne r5, #18 +1002fcb4: d006 beq.n 1002fcc4 +1002fcb6: 2d1f cmp r5, #31 +1002fcb8: d104 bne.n 1002fcc4 +1002fcba: 9c04 ldr r4, [sp, #16] +1002fcbc: 9400 str r4, [sp, #0] +1002fcbe: f7f9 fed2 bl 10029a66 +1002fcc2: 4604 mov r4, r0 +1002fcc4: 4620 mov r0, r4 +1002fcc6: bd32 pop {r1, r4, r5, pc} + +1002fcc8 : +1002fcc8: b510 push {r4, lr} +1002fcca: 8804 ldrh r4, [r0, #0] +1002fccc: 2c16 cmp r4, #22 +1002fcce: bf18 it ne +1002fcd0: 2c17 cmpne r4, #23 +1002fcd2: d01e beq.n 1002fd12 +1002fcd4: 2c19 cmp r4, #25 +1002fcd6: bf18 it ne +1002fcd8: 2c1a cmpne r4, #26 +1002fcda: d01a beq.n 1002fd12 +1002fcdc: 2c18 cmp r4, #24 +1002fcde: bf18 it ne +1002fce0: 2c1b cmpne r4, #27 +1002fce2: d016 beq.n 1002fd12 +1002fce4: 2c1c cmp r4, #28 +1002fce6: bf18 it ne +1002fce8: 2c1d cmpne r4, #29 +1002fcea: d012 beq.n 1002fd12 +1002fcec: 2c1e cmp r4, #30 +1002fcee: bf18 it ne +1002fcf0: 2c13 cmpne r4, #19 +1002fcf2: d00e beq.n 1002fd12 +1002fcf4: 2c14 cmp r4, #20 +1002fcf6: bf18 it ne +1002fcf8: 2c15 cmpne r4, #21 +1002fcfa: d00a beq.n 1002fd12 +1002fcfc: 2c10 cmp r4, #16 +1002fcfe: bf1c itt ne +1002fd00: 2c11 cmpne r4, #17 +1002fd02: 2c12 cmpne r4, #18 +1002fd04: d005 beq.n 1002fd12 +1002fd06: 2c1f cmp r4, #31 +1002fd08: bf04 itt eq +1002fd0a: e8bd 4010 ldmiaeq.w sp!, {r4, lr} +1002fd0e: f7f9 be0a beq.w 10029926 +1002fd12: bd10 pop {r4, pc} + +1002fd14 : +1002fd14: f641 32a4 movw r2, #7076 ; 0x1ba4 +1002fd18: 2303 movs r3, #3 +1002fd1a: 5812 ldr r2, [r2, r0] +1002fd1c: 2003 movs r0, #3 +1002fd1e: f882 00b9 strb.w r0, [r2, #185] ; 0xb9 +1002fd22: 3921 subs r1, #33 ; 0x21 +1002fd24: f102 00b9 add.w r0, r2, #185 ; 0xb9 +1002fd28: 2936 cmp r1, #54 ; 0x36 +1002fd2a: 7043 strb r3, [r0, #1] +1002fd2c: d83c bhi.n 1002fda8 +1002fd2e: e8df f001 tbb [pc, r1] +1002fd32: 1c20 .short 0x1c20 +1002fd34: 2437201e .word 0x2437201e +1002fd38: 3b372b29 .word 0x3b372b29 +1002fd3c: 3b3b3b3b .word 0x3b3b3b3b +1002fd40: 3737373b .word 0x3737373b +1002fd44: 37373737 .word 0x37373737 +1002fd48: 3b373030 .word 0x3b373030 +1002fd4c: 3b3b3b3b .word 0x3b3b3b3b +1002fd50: 353b373b .word 0x353b373b +1002fd54: 37353737 .word 0x37353737 +1002fd58: 3b353535 .word 0x3b353535 +1002fd5c: 3b3b3b3b .word 0x3b3b3b3b +1002fd60: 3535353b .word 0x3535353b +1002fd64: 35373537 .word 0x35373537 +1002fd68: 0037 .short 0x0037 +1002fd6a: 2000 movs r0, #0 +1002fd6c: e002 b.n 1002fd74 +1002fd6e: 2001 movs r0, #1 +1002fd70: e000 b.n 1002fd74 +1002fd72: 2002 movs r0, #2 +1002fd74: f882 00b9 strb.w r0, [r2, #185] ; 0xb9 +1002fd78: 4770 bx lr +1002fd7a: 2100 movs r1, #0 +1002fd7c: f882 10b9 strb.w r1, [r2, #185] ; 0xb9 +1002fd80: 2102 movs r1, #2 +1002fd82: e010 b.n 1002fda6 +1002fd84: 2101 movs r1, #1 +1002fd86: e00c b.n 1002fda2 +1002fd88: 2100 movs r1, #0 +1002fd8a: f882 10b9 strb.w r1, [r2, #185] ; 0xb9 +1002fd8e: 2101 movs r1, #1 +1002fd90: e009 b.n 1002fda6 +1002fd92: 2101 movs r1, #1 +1002fd94: f882 10b9 strb.w r1, [r2, #185] ; 0xb9 +1002fd98: 2100 movs r1, #0 +1002fd9a: e004 b.n 1002fda6 +1002fd9c: 2102 movs r1, #2 +1002fd9e: e000 b.n 1002fda2 +1002fda0: 2100 movs r1, #0 +1002fda2: f882 10b9 strb.w r1, [r2, #185] ; 0xb9 +1002fda6: 7041 strb r1, [r0, #1] +1002fda8: 4770 bx lr + ... + +1002fdac : +1002fdac: 2624 2a28 2e2c 3230 3634 3a38 3e3c 6440 $&(*,.02468:<>@d +1002fdbc: 6866 6c6a 706e 7472 7876 7c7a 807e 8482 fhjlnprtvxz|~... +1002fdcc: 8886 8c8a 908e 9795 9b99 9f9d a3a1 a7a5 ................ +1002fddc: a9a8 adab b1af 0000 ........ + +1002fde4 : +1002fde4: 5445 4953 0000 0000 ETSI.... + +1002fdec : +1002fdec: 5757 3331 0000 0000 WW13.... + +1002fdf4 : +1002fdf4: 464f 4d44 0000 0000 OFDM.... + +1002fdfc : +1002fdfc: 3631 4d30 0000 0000 160M.... + +1002fe04 : +1002fe04: 2e32 4734 0000 0000 2.4G.... + +1002fe0c : +1002fe0c: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1002fe10: 460c mov r4, r1 +1002fe12: 4615 mov r5, r2 +1002fe14: 461e mov r6, r3 +1002fe16: 280e cmp r0, #14 +1002fe18: da13 bge.n 1002fe42 +1002fe1a: 4925 ldr r1, [pc, #148] ; (1002feb0 ) +1002fe1c: 2218 movs r2, #24 +1002fe1e: 2700 movs r7, #0 +1002fe20: fb02 1800 mla r8, r2, r0, r1 + +1002fe24 : +1002fe24: f858 c037 ldr.w ip, [r8, r7, lsl #3] +1002fe28: f1bc 0f00 cmp.w ip, #0 +1002fe2c: d006 beq.n 1002fe3c +1002fe2e: eb08 00c7 add.w r0, r8, r7, lsl #3 +1002fe32: 4632 mov r2, r6 +1002fe34: 6843 ldr r3, [r0, #4] +1002fe36: 4629 mov r1, r5 +1002fe38: 4620 mov r0, r4 +1002fe3a: 47e0 blx ip + +1002fe3c : +1002fe3c: 1c7f adds r7, r7, #1 +1002fe3e: 2f03 cmp r7, #3 +1002fe40: dbf0 blt.n 1002fe24 + +1002fe42 : +1002fe42: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +1002fe46 : +1002fe46: 2300 movs r3, #0 +1002fe48: 280e cmp r0, #14 +1002fe4a: d300 bcc.n 1002fe4e +1002fe4c: 4770 bx lr + +1002fe4e : +1002fe4e: b530 push {r4, r5, lr} + +1002fe50 : +1002fe50: 4c17 ldr r4, [pc, #92] ; (1002feb0 ) +1002fe52: 2518 movs r5, #24 +1002fe54: fb05 4400 mla r4, r5, r0, r4 +1002fe58: f854 5033 ldr.w r5, [r4, r3, lsl #3] +1002fe5c: b92d cbnz r5, 1002fe6a +1002fe5e: f844 1033 str.w r1, [r4, r3, lsl #3] +1002fe62: eb04 00c3 add.w r0, r4, r3, lsl #3 +1002fe66: 6042 str r2, [r0, #4] +1002fe68: bd30 pop {r4, r5, pc} + +1002fe6a : +1002fe6a: 1c5b adds r3, r3, #1 +1002fe6c: 2b03 cmp r3, #3 +1002fe6e: dbef blt.n 1002fe50 +1002fe70: bd30 pop {r4, r5, pc} + +1002fe72 : +1002fe72: 280e cmp r0, #14 +1002fe74: d300 bcc.n 1002fe78 +1002fe76: 4770 bx lr + +1002fe78 : +1002fe78: b510 push {r4, lr} +1002fe7a: 4b0d ldr r3, [pc, #52] ; (1002feb0 ) +1002fe7c: 2418 movs r4, #24 +1002fe7e: 2200 movs r2, #0 +1002fe80: fb04 3000 mla r0, r4, r0, r3 + +1002fe84 : +1002fe84: f850 3032 ldr.w r3, [r0, r2, lsl #3] +1002fe88: 428b cmp r3, r1 +1002fe8a: d106 bne.n 1002fe9a +1002fe8c: 2100 movs r1, #0 +1002fe8e: f840 1032 str.w r1, [r0, r2, lsl #3] +1002fe92: eb00 00c2 add.w r0, r0, r2, lsl #3 +1002fe96: 6041 str r1, [r0, #4] +1002fe98: bd10 pop {r4, pc} + +1002fe9a : +1002fe9a: 1c52 adds r2, r2, #1 +1002fe9c: 2a03 cmp r2, #3 +1002fe9e: dbf1 blt.n 1002fe84 +1002fea0: bd10 pop {r4, pc} + +1002fea2 : +1002fea2: f44f 72a8 mov.w r2, #336 ; 0x150 +1002fea6: 2100 movs r1, #0 +1002fea8: 4801 ldr r0, [pc, #4] ; (1002feb0 ) +1002feaa: f7dc ba4f b.w 1000c34c + ... + +1002feb0 : +1002feb0: 7f24 1004 $... + +1002feb4 : +1002feb4: 6941 ldr r1, [r0, #20] +1002feb6: 6902 ldr r2, [r0, #16] +1002feb8: 68c0 ldr r0, [r0, #12] +1002feba: 1a89 subs r1, r1, r2 +1002febc: 1840 adds r0, r0, r1 +1002febe: 4770 bx lr + +1002fec0 <_rtw_open_pktfile>: +1002fec0: 6008 str r0, [r1, #0] +1002fec2: 6902 ldr r2, [r0, #16] +1002fec4: 60ca str r2, [r1, #12] +1002fec6: 610a str r2, [r1, #16] +1002fec8: 6a00 ldr r0, [r0, #32] +1002feca: 6148 str r0, [r1, #20] +1002fecc: 6048 str r0, [r1, #4] +1002fece: 68c8 ldr r0, [r1, #12] +1002fed0: 6088 str r0, [r1, #8] +1002fed2: 4770 bx lr + +1002fed4 <_rtw_pktfile_read>: +1002fed4: b5f8 push {r3, r4, r5, r6, r7, lr} +1002fed6: 4604 mov r4, r0 +1002fed8: 460d mov r5, r1 +1002feda: 4616 mov r6, r2 +1002fedc: f7ff ffea bl 1002feb4 +1002fee0: 4607 mov r7, r0 +1002fee2: 42b7 cmp r7, r6 +1002fee4: bf88 it hi +1002fee6: 4637 movhi r7, r6 +1002fee8: b125 cbz r5, 1002fef4 <_rtw_pktfile_read+0x20> +1002feea: 6921 ldr r1, [r4, #16] +1002feec: 463a mov r2, r7 +1002feee: 4628 mov r0, r5 +1002fef0: f7e0 fc8d bl 1001080e +1002fef4: 6920 ldr r0, [r4, #16] +1002fef6: 1838 adds r0, r7, r0 +1002fef8: 6120 str r0, [r4, #16] +1002fefa: 6860 ldr r0, [r4, #4] +1002fefc: 1bc0 subs r0, r0, r7 +1002fefe: 6060 str r0, [r4, #4] +1002ff00: 4638 mov r0, r7 +1002ff02: bdf2 pop {r1, r4, r5, r6, r7, pc} + +1002ff04 : +1002ff04: 4770 bx lr + +1002ff06 : +1002ff06: 2000 movs r0, #0 +1002ff08: 60c8 str r0, [r1, #12] +1002ff0a: 6108 str r0, [r1, #16] +1002ff0c: 2001 movs r0, #1 +1002ff0e: 4770 bx lr + +1002ff10 : +1002ff10: 4770 bx lr + +1002ff12 : +1002ff12: 4608 mov r0, r1 +1002ff14: 69c1 ldr r1, [r0, #28] +1002ff16: f7e1 ba6c b.w 100113f2 + +1002ff1a : +1002ff1a: b510 push {r4, lr} +1002ff1c: 460c mov r4, r1 +1002ff1e: 6f61 ldr r1, [r4, #116] ; 0x74 +1002ff20: b109 cbz r1, 1002ff26 +1002ff22: f7ff fff6 bl 1002ff12 +1002ff26: 2000 movs r0, #0 +1002ff28: 6760 str r0, [r4, #116] ; 0x74 +1002ff2a: bd10 pop {r4, pc} + +1002ff2c : +1002ff2c: b538 push {r3, r4, r5, lr} +1002ff2e: 0004 movs r4, r0 +1002ff30: d019 beq.n 1002ff66 +1002ff32: f641 5151 movw r1, #7505 ; 0x1d51 +1002ff36: 5c09 ldrb r1, [r1, r0] +1002ff38: b111 cbz r1, 1002ff40 +1002ff3a: f641 5148 movw r1, #7496 ; 0x1d48 +1002ff3e: 580c ldr r4, [r1, r0] +1002ff40: f604 1528 addw r5, r4, #2344 ; 0x928 +1002ff44: a900 add r1, sp, #0 +1002ff46: 4628 mov r0, r5 +1002ff48: f7e0 fce4 bl 10010914 +1002ff4c: 4620 mov r0, r4 +1002ff4e: f7fc f993 bl 1002c278 +1002ff52: b120 cbz r0, 1002ff5e +1002ff54: f504 50e8 add.w r0, r4, #7424 ; 0x1d00 +1002ff58: 1d00 adds r0, r0, #4 +1002ff5a: f7e0 fde3 bl 10010b24 +1002ff5e: a900 add r1, sp, #0 +1002ff60: 4628 mov r0, r5 +1002ff62: f7e0 fcd8 bl 10010916 +1002ff66: bd31 pop {r0, r4, r5, pc} + +1002ff68 : +1002ff68: b531 push {r0, r4, r5, lr} +1002ff6a: 6908 ldr r0, [r1, #16] +1002ff6c: 6805 ldr r5, [r0, #0] +1002ff6e: f605 1428 addw r4, r5, #2344 ; 0x928 +1002ff72: 4628 mov r0, r5 +1002ff74: f7ee fc9b bl 1001e8ae +1002ff78: b168 cbz r0, 1002ff96 +1002ff7a: a900 add r1, sp, #0 +1002ff7c: 4628 mov r0, r5 +1002ff7e: f7fc ff4a bl 1002ce16 +1002ff82: 2800 cmp r0, #0 +1002ff84: d407 bmi.n 1002ff96 +1002ff86: e9d4 011a ldrd r0, r1, [r4, #104] ; 0x68 +1002ff8a: 1c40 adds r0, r0, #1 +1002ff8c: f141 0100 adc.w r1, r1, #0 +1002ff90: e9c4 011a strd r0, r1, [r4, #104] ; 0x68 +1002ff94: e00a b.n 1002ffac +1002ff96: e9d4 011c ldrd r0, r1, [r4, #112] ; 0x70 +1002ff9a: 1c40 adds r0, r0, #1 +1002ff9c: f141 0100 adc.w r1, r1, #0 +1002ffa0: e9c4 011c strd r0, r1, [r4, #112] ; 0x70 +1002ffa4: 9800 ldr r0, [sp, #0] +1002ffa6: 69c1 ldr r1, [r0, #28] +1002ffa8: f7e1 fa23 bl 100113f2 +1002ffac: 2000 movs r0, #0 +1002ffae: bd32 pop {r1, r4, r5, pc} + +1002ffb0 : +1002ffb0: b510 push {r4, lr} +1002ffb2: 4604 mov r4, r0 +1002ffb4: f000 f981 bl 100302ba +1002ffb8: 4620 mov r0, r4 +1002ffba: f002 f886 bl 100320ca +1002ffbe: 4620 mov r0, r4 +1002ffc0: f003 fcd5 bl 1003396e +1002ffc4: 4620 mov r0, r4 +1002ffc6: f003 fdd8 bl 10033b7a +1002ffca: 4620 mov r0, r4 +1002ffcc: f001 fec6 bl 10031d5c +1002ffd0: 4620 mov r0, r4 +1002ffd2: f003 fe85 bl 10033ce0 +1002ffd6: 4620 mov r0, r4 +1002ffd8: f001 fdff bl 10031bda +1002ffdc: 4620 mov r0, r4 +1002ffde: f003 febd bl 10033d5c +1002ffe2: 6b20 ldr r0, [r4, #48] ; 0x30 +1002ffe4: f242 119f movw r1, #8607 ; 0x219f +1002ffe8: 4208 tst r0, r1 +1002ffea: d007 beq.n 1002fffc +1002ffec: f5b0 5f00 cmp.w r0, #8192 ; 0x2000 +1002fff0: d104 bne.n 1002fffc +1002fff2: 4620 mov r0, r4 +1002fff4: e8bd 4010 ldmia.w sp!, {r4, lr} +1002fff8: f7f1 bd9c b.w 10021b34 +1002fffc: bd10 pop {r4, pc} + +1002fffe : +1002fffe: b510 push {r4, lr} +10030000: 4604 mov r4, r0 +10030002: f000 f986 bl 10030312 +10030006: 4620 mov r0, r4 +10030008: f002 f9cf bl 100323aa +1003000c: 4620 mov r0, r4 +1003000e: f001 fdec bl 10031bea +10030012: f8d4 0090 ldr.w r0, [r4, #144] ; 0x90 +10030016: 7800 ldrb r0, [r0, #0] +10030018: 2801 cmp r0, #1 +1003001a: 4620 mov r0, r4 +1003001c: d108 bne.n 10030030 +1003001e: f001 ffd1 bl 10031fc4 +10030022: f894 1670 ldrb.w r1, [r4, #1648] ; 0x670 +10030026: 4620 mov r0, r4 +10030028: e8bd 4010 ldmia.w sp!, {r4, lr} +1003002c: f003 be15 b.w 10033c5a +10030030: f003 fc76 bl 10033920 +10030034: 4620 mov r0, r4 +10030036: f002 f8bb bl 100321b0 +1003003a: f894 1670 ldrb.w r1, [r4, #1648] ; 0x670 +1003003e: 4620 mov r0, r4 +10030040: f003 fe0b bl 10033c5a +10030044: 4620 mov r0, r4 +10030046: f002 f9b7 bl 100323b8 +1003004a: 4620 mov r0, r4 +1003004c: f001 fe97 bl 10031d7e +10030050: 4620 mov r0, r4 +10030052: f003 fe5a bl 10033d0a +10030056: 4620 mov r0, r4 +10030058: f003 ff04 bl 10033e64 +1003005c: 6b20 ldr r0, [r4, #48] ; 0x30 +1003005e: f410 5fd3 tst.w r0, #6752 ; 0x1a60 +10030062: bf1c itt ne +10030064: 4620 movne r0, r4 +10030066: f000 f98b blne 10030380 +1003006a: 2000 movs r0, #0 +1003006c: f884 04f4 strb.w r0, [r4, #1268] ; 0x4f4 +10030070: bd10 pop {r4, pc} + +10030072 : +10030072: b530 push {r4, r5, lr} +10030074: 2900 cmp r1, #0 +10030076: f100 0328 add.w r3, r0, #40 ; 0x28 +1003007a: f100 044c add.w r4, r0, #76 ; 0x4c +1003007e: f8df 5308 ldr.w r5, [pc, #776] ; 10030388 <.text_36> +10030082: d03c beq.n 100300fe +10030084: 2901 cmp r1, #1 +10030086: d036 beq.n 100300f6 +10030088: 2902 cmp r1, #2 +1003008a: d03b beq.n 10030104 +1003008c: 2903 cmp r1, #3 +1003008e: d03b beq.n 10030108 +10030090: 2904 cmp r1, #4 +10030092: d03c beq.n 1003010e +10030094: 2905 cmp r1, #5 +10030096: d03c beq.n 10030112 +10030098: 2906 cmp r1, #6 +1003009a: d03c beq.n 10030116 +1003009c: 2907 cmp r1, #7 +1003009e: d02c beq.n 100300fa +100300a0: 2908 cmp r1, #8 +100300a2: d03a beq.n 1003011a +100300a4: 2909 cmp r1, #9 +100300a6: d03d beq.n 10030124 +100300a8: 290a cmp r1, #10 +100300aa: d03d beq.n 10030128 +100300ac: 290b cmp r1, #11 +100300ae: d03d beq.n 1003012c +100300b0: 290c cmp r1, #12 +100300b2: d03d beq.n 10030130 +100300b4: 290d cmp r1, #13 +100300b6: d03d beq.n 10030134 +100300b8: 290e cmp r1, #14 +100300ba: d03d beq.n 10030138 +100300bc: 290f cmp r1, #15 +100300be: d03d beq.n 1003013c +100300c0: 2910 cmp r1, #16 +100300c2: d03d beq.n 10030140 +100300c4: 2911 cmp r1, #17 +100300c6: d03d beq.n 10030144 +100300c8: 2912 cmp r1, #18 +100300ca: d03d beq.n 10030148 +100300cc: 2913 cmp r1, #19 +100300ce: d03d beq.n 1003014c +100300d0: 2914 cmp r1, #20 +100300d2: d03d beq.n 10030150 +100300d4: 2915 cmp r1, #21 +100300d6: d03d beq.n 10030154 +100300d8: 2916 cmp r1, #22 +100300da: d03d beq.n 10030158 +100300dc: 2917 cmp r1, #23 +100300de: d03d beq.n 1003015c +100300e0: 2918 cmp r1, #24 +100300e2: d03d beq.n 10030160 +100300e4: 2919 cmp r1, #25 +100300e6: d03d beq.n 10030164 +100300e8: 291a cmp r1, #26 +100300ea: d03c beq.n 10030166 +100300ec: 291b cmp r1, #27 +100300ee: d03c beq.n 1003016a +100300f0: 293f cmp r1, #63 ; 0x3f +100300f2: d014 beq.n 1003011e +100300f4: bd30 pop {r4, r5, pc} +100300f6: 6282 str r2, [r0, #40] ; 0x28 +100300f8: bd30 pop {r4, r5, pc} +100300fa: 739a strb r2, [r3, #14] +100300fc: bd30 pop {r4, r5, pc} +100300fe: f880 2025 strb.w r2, [r0, #37] ; 0x25 +10030102: bd30 pop {r4, r5, pc} +10030104: 711a strb r2, [r3, #4] +10030106: bd30 pop {r4, r5, pc} +10030108: f880 20b7 strb.w r2, [r0, #183] ; 0xb7 +1003010c: bd30 pop {r4, r5, pc} +1003010e: 609a str r2, [r3, #8] +10030110: bd30 pop {r4, r5, pc} +10030112: 731a strb r2, [r3, #12] +10030114: bd30 pop {r4, r5, pc} +10030116: 735a strb r2, [r3, #13] +10030118: bd30 pop {r4, r5, pc} +1003011a: 73da strb r2, [r3, #15] +1003011c: bd30 pop {r4, r5, pc} +1003011e: f880 204c strb.w r2, [r0, #76] ; 0x4c +10030122: bd30 pop {r4, r5, pc} +10030124: 741a strb r2, [r3, #16] +10030126: bd30 pop {r4, r5, pc} +10030128: 745a strb r2, [r3, #17] +1003012a: bd30 pop {r4, r5, pc} +1003012c: 759a strb r2, [r3, #22] +1003012e: bd30 pop {r4, r5, pc} +10030130: 75da strb r2, [r3, #23] +10030132: bd30 pop {r4, r5, pc} +10030134: 761a strb r2, [r3, #24] +10030136: bd30 pop {r4, r5, pc} +10030138: 765a strb r2, [r3, #25] +1003013a: bd30 pop {r4, r5, pc} +1003013c: 74da strb r2, [r3, #19] +1003013e: bd30 pop {r4, r5, pc} +10030140: 755a strb r2, [r3, #21] +10030142: bd30 pop {r4, r5, pc} +10030144: 749a strb r2, [r3, #18] +10030146: bd30 pop {r4, r5, pc} +10030148: 751a strb r2, [r3, #20] +1003014a: bd30 pop {r4, r5, pc} +1003014c: 769a strb r2, [r3, #26] +1003014e: bd30 pop {r4, r5, pc} +10030150: 76da strb r2, [r3, #27] +10030152: bd30 pop {r4, r5, pc} +10030154: 771a strb r2, [r3, #28] +10030156: bd30 pop {r4, r5, pc} +10030158: 775a strb r2, [r3, #29] +1003015a: bd30 pop {r4, r5, pc} +1003015c: 779a strb r2, [r3, #30] +1003015e: bd30 pop {r4, r5, pc} +10030160: 7062 strb r2, [r4, #1] +10030162: bd30 pop {r4, r5, pc} +10030164: 70a2 strb r2, [r4, #2] +10030166: 702a strb r2, [r5, #0] +10030168: bd30 pop {r4, r5, pc} +1003016a: 706a strb r2, [r5, #1] +1003016c: bd30 pop {r4, r5, pc} + ... + +10030170 : +10030170: b510 push {r4, lr} +10030172: 391c subs r1, #28 +10030174: 2918 cmp r1, #24 +10030176: f100 0358 add.w r3, r0, #88 ; 0x58 +1003017a: f600 04f4 addw r4, r0, #2292 ; 0x8f4 +1003017e: d841 bhi.n 10030204 +10030180: e8df f001 tbb [pc, r1] +10030184: 13110f0d .word 0x13110f0d +10030188: 1b191715 .word 0x1b191715 +1003018c: 211f361d .word 0x211f361d +10030190: 29272523 .word 0x29272523 +10030194: 32302e2b .word 0x32302e2b +10030198: 3c383a34 .word 0x3c383a34 +1003019c: 003f .short 0x003f +1003019e: 6582 str r2, [r0, #88] ; 0x58 +100301a0: bd10 pop {r4, pc} +100301a2: 605a str r2, [r3, #4] +100301a4: bd10 pop {r4, pc} +100301a6: 609a str r2, [r3, #8] +100301a8: bd10 pop {r4, pc} +100301aa: 60da str r2, [r3, #12] +100301ac: bd10 pop {r4, pc} +100301ae: 611a str r2, [r3, #16] +100301b0: bd10 pop {r4, pc} +100301b2: 615a str r2, [r3, #20] +100301b4: bd10 pop {r4, pc} +100301b6: 619a str r2, [r3, #24] +100301b8: bd10 pop {r4, pc} +100301ba: 61da str r2, [r3, #28] +100301bc: bd10 pop {r4, pc} +100301be: 621a str r2, [r3, #32] +100301c0: bd10 pop {r4, pc} +100301c2: 629a str r2, [r3, #40] ; 0x28 +100301c4: bd10 pop {r4, pc} +100301c6: 62da str r2, [r3, #44] ; 0x2c +100301c8: bd10 pop {r4, pc} +100301ca: 631a str r2, [r3, #48] ; 0x30 +100301cc: bd10 pop {r4, pc} +100301ce: 635a str r2, [r3, #52] ; 0x34 +100301d0: bd10 pop {r4, pc} +100301d2: 639a str r2, [r3, #56] ; 0x38 +100301d4: bd10 pop {r4, pc} +100301d6: 63da str r2, [r3, #60] ; 0x3c +100301d8: bd10 pop {r4, pc} +100301da: f8c0 28f4 str.w r2, [r0, #2292] ; 0x8f4 +100301de: bd10 pop {r4, pc} +100301e0: 6062 str r2, [r4, #4] +100301e2: bd10 pop {r4, pc} +100301e4: 60a2 str r2, [r4, #8] +100301e6: bd10 pop {r4, pc} +100301e8: 641a str r2, [r3, #64] ; 0x40 +100301ea: bd10 pop {r4, pc} +100301ec: 645a str r2, [r3, #68] ; 0x44 +100301ee: bd10 pop {r4, pc} +100301f0: 655a str r2, [r3, #84] ; 0x54 +100301f2: bd10 pop {r4, pc} +100301f4: 64da str r2, [r3, #76] ; 0x4c +100301f6: bd10 pop {r4, pc} +100301f8: 649a str r2, [r3, #72] ; 0x48 +100301fa: bd10 pop {r4, pc} +100301fc: f8c0 2694 str.w r2, [r0, #1684] ; 0x694 +10030200: bd10 pop {r4, pc} +10030202: 651a str r2, [r3, #80] ; 0x50 +10030204: bd10 pop {r4, pc} + +10030206 : +10030206: 2946 cmp r1, #70 ; 0x46 +10030208: bf04 itt eq +1003020a: eb00 0082 addeq.w r0, r0, r2, lsl #2 +1003020e: f8c0 3144 streq.w r3, [r0, #324] ; 0x144 +10030212: 4770 bx lr + +10030214 : +10030214: b530 push {r4, r5, lr} +10030216: 2901 cmp r1, #1 +10030218: f100 04b0 add.w r4, r0, #176 ; 0xb0 +1003021c: f8df 5168 ldr.w r5, [pc, #360] ; 10030388 <.text_36> +10030220: d025 beq.n 1003026e +10030222: 2907 cmp r1, #7 +10030224: d025 beq.n 10030272 +10030226: 2935 cmp r1, #53 ; 0x35 +10030228: d026 beq.n 10030278 +1003022a: 2936 cmp r1, #54 ; 0x36 +1003022c: d026 beq.n 1003027c +1003022e: 2937 cmp r1, #55 ; 0x37 +10030230: d01a beq.n 10030268 +10030232: 2938 cmp r1, #56 ; 0x38 +10030234: d024 beq.n 10030280 +10030236: 2939 cmp r1, #57 ; 0x39 +10030238: d024 beq.n 10030284 +1003023a: 293a cmp r1, #58 ; 0x3a +1003023c: d024 beq.n 10030288 +1003023e: 293b cmp r1, #59 ; 0x3b +10030240: d024 beq.n 1003028c +10030242: 293c cmp r1, #60 ; 0x3c +10030244: d025 beq.n 10030292 +10030246: 293d cmp r1, #61 ; 0x3d +10030248: d025 beq.n 10030296 +1003024a: 293e cmp r1, #62 ; 0x3e +1003024c: d026 beq.n 1003029c +1003024e: 2940 cmp r1, #64 ; 0x40 +10030250: d027 beq.n 100302a2 +10030252: 2941 cmp r1, #65 ; 0x41 +10030254: d027 beq.n 100302a6 +10030256: 2942 cmp r1, #66 ; 0x42 +10030258: d027 beq.n 100302aa +1003025a: 2943 cmp r1, #67 ; 0x43 +1003025c: d027 beq.n 100302ae +1003025e: 2944 cmp r1, #68 ; 0x44 +10030260: d027 beq.n 100302b2 +10030262: 2945 cmp r1, #69 ; 0x45 +10030264: d027 beq.n 100302b6 +10030266: bd30 pop {r4, r5, pc} +10030268: f880 20b0 strb.w r2, [r0, #176] ; 0xb0 +1003026c: bd30 pop {r4, r5, pc} +1003026e: 6282 str r2, [r0, #40] ; 0x28 +10030270: bd30 pop {r4, r5, pc} +10030272: f880 2036 strb.w r2, [r0, #54] ; 0x36 +10030276: bd30 pop {r4, r5, pc} +10030278: 7062 strb r2, [r4, #1] +1003027a: bd30 pop {r4, r5, pc} +1003027c: 70a2 strb r2, [r4, #2] +1003027e: bd30 pop {r4, r5, pc} +10030280: 70e2 strb r2, [r4, #3] +10030282: bd30 pop {r4, r5, pc} +10030284: 7122 strb r2, [r4, #4] +10030286: bd30 pop {r4, r5, pc} +10030288: 7162 strb r2, [r4, #5] +1003028a: bd30 pop {r4, r5, pc} +1003028c: e9c5 2302 strd r2, r3, [r5, #8] +10030290: bd30 pop {r4, r5, pc} +10030292: 612a str r2, [r5, #16] +10030294: bd30 pop {r4, r5, pc} +10030296: f880 2922 strb.w r2, [r0, #2338] ; 0x922 +1003029a: bd30 pop {r4, r5, pc} +1003029c: f880 2923 strb.w r2, [r0, #2339] ; 0x923 +100302a0: bd30 pop {r4, r5, pc} +100302a2: 7262 strb r2, [r4, #9] +100302a4: bd30 pop {r4, r5, pc} +100302a6: 72a2 strb r2, [r4, #10] +100302a8: bd30 pop {r4, r5, pc} +100302aa: 72e2 strb r2, [r4, #11] +100302ac: bd30 pop {r4, r5, pc} +100302ae: 7322 strb r2, [r4, #12] +100302b0: bd30 pop {r4, r5, pc} +100302b2: 73a2 strb r2, [r4, #14] +100302b4: bd30 pop {r4, r5, pc} +100302b6: 7362 strb r2, [r4, #13] +100302b8: bd30 pop {r4, r5, pc} + +100302ba : +100302ba: b538 push {r3, r4, r5, lr} +100302bc: 4604 mov r4, r0 +100302be: f242 159f movw r5, #8607 ; 0x219f +100302c2: 6b20 ldr r0, [r4, #48] ; 0x30 +100302c4: 4228 tst r0, r5 +100302c6: bf07 ittee eq +100302c8: f44f 3280 moveq.w r2, #65536 ; 0x10000 +100302cc: f640 0104 movweq r1, #2052 ; 0x804 +100302d0: f44f 7200 movne.w r2, #512 ; 0x200 +100302d4: f640 0124 movwne r1, #2084 ; 0x824 +100302d8: f000 f853 bl 10030382 <.text_26> +100302dc: f884 0022 strb.w r0, [r4, #34] ; 0x22 +100302e0: 6b20 ldr r0, [r4, #48] ; 0x30 +100302e2: 4228 tst r0, r5 +100302e4: bf14 ite ne +100302e6: f640 4104 movwne r1, #3076 ; 0xc04 +100302ea: f640 0108 movweq r1, #2056 ; 0x808 +100302ee: 220f movs r2, #15 +100302f0: f000 f847 bl 10030382 <.text_26> +100302f4: f884 0023 strb.w r0, [r4, #35] ; 0x23 +100302f8: 4620 mov r0, r4 +100302fa: f003 fe55 bl 10033fa8 +100302fe: 6b20 ldr r0, [r4, #48] ; 0x30 +10030300: 2808 cmp r0, #8 +10030302: bf04 itt eq +10030304: 2000 moveq r0, #0 +10030306: f884 004c strbeq.w r0, [r4, #76] ; 0x4c +1003030a: 20ff movs r0, #255 ; 0xff +1003030c: f884 00ea strb.w r0, [r4, #234] ; 0xea +10030310: bd31 pop {r0, r4, r5, pc} + +10030312 : +10030312: f100 0224 add.w r2, r0, #36 ; 0x24 +10030316: 2100 movs r1, #0 +10030318: 6d13 ldr r3, [r2, #80] ; 0x50 +1003031a: 781b ldrb r3, [r3, #0] +1003031c: 2b01 cmp r3, #1 +1003031e: d10d bne.n 1003033c +10030320: 6c93 ldr r3, [r2, #72] ; 0x48 +10030322: 781b ldrb r3, [r3, #0] +10030324: 2b01 cmp r3, #1 +10030326: d103 bne.n 10030330 +10030328: 6d52 ldr r2, [r2, #84] ; 0x54 +1003032a: 7812 ldrb r2, [r2, #0] +1003032c: 1e92 subs r2, r2, #2 +1003032e: e007 b.n 10030340 +10030330: 2b02 cmp r3, #2 +10030332: d107 bne.n 10030344 +10030334: 6d52 ldr r2, [r2, #84] ; 0x54 +10030336: 7812 ldrb r2, [r2, #0] +10030338: 1c92 adds r2, r2, #2 +1003033a: e001 b.n 10030340 +1003033c: 6d52 ldr r2, [r2, #84] ; 0x54 +1003033e: 7812 ldrb r2, [r2, #0] +10030340: f880 2024 strb.w r2, [r0, #36] ; 0x24 +10030344: 2200 movs r2, #0 +10030346: eb00 0382 add.w r3, r0, r2, lsl #2 +1003034a: f8d3 3144 ldr.w r3, [r3, #324] ; 0x144 +1003034e: b103 cbz r3, 10030352 +10030350: 1c49 adds r1, r1, #1 +10030352: 1c52 adds r2, r2, #1 +10030354: 2a0a cmp r2, #10 +10030356: dbf6 blt.n 10030346 +10030358: b2c9 uxtb r1, r1 +1003035a: 2901 cmp r1, #1 +1003035c: bf18 it ne +1003035e: 2100 movne r1, #0 +10030360: f880 10b8 strb.w r1, [r0, #184] ; 0xb8 +10030364: 4770 bx lr + +10030366 : +10030366: 2200 movs r2, #0 +10030368: b121 cbz r1, 10030374 +1003036a: 2902 cmp r1, #2 +1003036c: d004 beq.n 10030378 +1003036e: bf38 it cc +10030370: 4a06 ldrcc r2, [pc, #24] ; (1003038c <.text_37>) +10030372: e003 b.n 1003037c +10030374: 4a06 ldr r2, [pc, #24] ; (10030390 <.text_38>) +10030376: e001 b.n 1003037c +10030378: f200 1231 addw r2, r0, #305 ; 0x131 +1003037c: 4610 mov r0, r2 +1003037e: 4770 bx lr + +10030380 : +10030380: 4770 bx lr + +10030382 <.text_26>: +10030382: 4620 mov r0, r4 +10030384: f000 bde8 b.w 10030f58 + +10030388 <.text_36>: +10030388: 10000720 .word 0x10000720 + +1003038c <.text_37>: +1003038c: 10000738 .word 0x10000738 + +10030390 <.text_38>: +10030390: 100006e0 .word 0x100006e0 + +10030394 : +10030394: b580 push {r7, lr} +10030396: 6880 ldr r0, [r0, #8] +10030398: 3020 adds r0, #32 +1003039a: f7e0 fadc bl 10010956 +1003039e: 2001 movs r0, #1 +100303a0: bd02 pop {r1, pc} + +100303a2 : +100303a2: 6880 ldr r0, [r0, #8] +100303a4: 3020 adds r0, #32 +100303a6: f7e0 badd b.w 10010964 + +100303aa : +100303aa: 2803 cmp r0, #3 +100303ac: d90d bls.n 100303ca +100303ae: 1f01 subs r1, r0, #4 +100303b0: d004 beq.n 100303bc +100303b2: 1e49 subs r1, r1, #1 +100303b4: d004 beq.n 100303c0 +100303b6: 1e49 subs r1, r1, #1 +100303b8: d004 beq.n 100303c4 +100303ba: e005 b.n 100303c8 +100303bc: 200e movs r0, #14 +100303be: 4770 bx lr +100303c0: 2004 movs r0, #4 +100303c2: 4770 bx lr +100303c4: 2006 movs r0, #6 +100303c6: 4770 bx lr +100303c8: 2010 movs r0, #16 +100303ca: 4770 bx lr + +100303cc : +100303cc: b538 push {r3, r4, r5, lr} +100303ce: 000d movs r5, r1 +100303d0: 4604 mov r4, r0 +100303d2: d101 bne.n 100303d8 +100303d4: 2000 movs r0, #0 +100303d6: bd32 pop {r1, r4, r5, pc} +100303d8: 4628 mov r0, r5 +100303da: f7e0 fa43 bl 10010864 +100303de: f104 0110 add.w r1, r4, #16 +100303e2: 4628 mov r0, r5 +100303e4: f7e0 fa3c bl 10010860 +100303e8: 69e0 ldr r0, [r4, #28] +100303ea: 1c40 adds r0, r0, #1 +100303ec: 61e0 str r0, [r4, #28] +100303ee: 2001 movs r0, #1 +100303f0: bd32 pop {r1, r4, r5, pc} + +100303f2 : +100303f2: b570 push {r4, r5, r6, lr} +100303f4: 4604 mov r4, r0 +100303f6: f104 0610 add.w r6, r4, #16 +100303fa: 2500 movs r5, #0 +100303fc: 4630 mov r0, r6 +100303fe: f7e0 faa3 bl 10010948 +10030402: 2801 cmp r0, #1 +10030404: d006 beq.n 10030414 +10030406: 6835 ldr r5, [r6, #0] +10030408: 4628 mov r0, r5 +1003040a: f7e0 fa2b bl 10010864 +1003040e: 69e0 ldr r0, [r4, #28] +10030410: 1e40 subs r0, r0, #1 +10030412: 61e0 str r0, [r4, #28] +10030414: 4628 mov r0, r5 +10030416: bd70 pop {r4, r5, r6, pc} + +10030418 : +10030418: b570 push {r4, r5, r6, lr} +1003041a: 4605 mov r5, r0 +1003041c: 460c mov r4, r1 +1003041e: f605 1628 addw r6, r5, #2344 ; 0x928 +10030422: f7ef f9fc bl 1001f81e +10030426: 2800 cmp r0, #0 +10030428: bf1f itttt ne +1003042a: f641 5048 movwne r0, #7496 ; 0x1d48 +1003042e: 1941 addne r1, r0, r5 +10030430: 7a49 ldrbne r1, [r1, #9] +10030432: 2900 cmpne r1, #0 +10030434: bf1c itt ne +10030436: 5940 ldrne r0, [r0, r5] +10030438: f600 1628 addwne r6, r0, #2344 ; 0x928 +1003043c: eb06 1044 add.w r0, r6, r4, lsl #5 +10030440: 3090 adds r0, #144 ; 0x90 +10030442: 2c04 cmp r4, #4 +10030444: d009 beq.n 1003045a +10030446: 6881 ldr r1, [r0, #8] +10030448: 69c2 ldr r2, [r0, #28] +1003044a: 1851 adds r1, r2, r1 +1003044c: 68c2 ldr r2, [r0, #12] +1003044e: fbb1 f3f2 udiv r3, r1, r2 +10030452: fb02 1113 mls r1, r2, r3, r1 +10030456: 0149 lsls r1, r1, #5 +10030458: e000 b.n 1003045c +1003045a: 2100 movs r1, #0 +1003045c: 6800 ldr r0, [r0, #0] +1003045e: 1808 adds r0, r1, r0 +10030460: bd70 pop {r4, r5, r6, pc} + +10030462 : +10030462: b5f0 push {r4, r5, r6, r7, lr} +10030464: f8d1 0084 ldr.w r0, [r1, #132] ; 0x84 +10030468: 2400 movs r4, #0 +1003046a: 2300 movs r3, #0 +1003046c: 210c movs r1, #12 +1003046e: e004 b.n 1003047a +10030470: fb01 0503 mla r5, r1, r3, r0 +10030474: 1c5b adds r3, r3, #1 +10030476: 6b2d ldr r5, [r5, #48] ; 0x30 +10030478: 192c adds r4, r5, r4 +1003047a: 6d85 ldr r5, [r0, #88] ; 0x58 +1003047c: 42ab cmp r3, r5 +1003047e: d3f7 bcc.n 10030470 +10030480: f014 037f ands.w r3, r4, #127 ; 0x7f +10030484: bf18 it ne +10030486: 2301 movne r3, #1 +10030488: 6815 ldr r5, [r2, #0] +1003048a: eb03 13d4 add.w r3, r3, r4, lsr #7 +1003048e: f425 057f bic.w r5, r5, #16711680 ; 0xff0000 +10030492: b2db uxtb r3, r3 +10030494: ea45 4303 orr.w r3, r5, r3, lsl #16 +10030498: 6013 str r3, [r2, #0] +1003049a: 0c1b lsrs r3, r3, #16 +1003049c: 6b04 ldr r4, [r0, #48] ; 0x30 +1003049e: b2a4 uxth r4, r4 +100304a0: ea44 4303 orr.w r3, r4, r3, lsl #16 +100304a4: 6013 str r3, [r2, #0] +100304a6: 6ac3 ldr r3, [r0, #44] ; 0x2c +100304a8: 6053 str r3, [r2, #4] +100304aa: 6d83 ldr r3, [r0, #88] ; 0x58 +100304ac: 2b05 cmp r3, #5 +100304ae: d215 bcs.n 100304dc +100304b0: 2301 movs r3, #1 +100304b2: e010 b.n 100304d6 +100304b4: fb01 0403 mla r4, r1, r3, r0 +100304b8: 00dd lsls r5, r3, #3 +100304ba: 6b27 ldr r7, [r4, #48] ; 0x30 +100304bc: 58ae ldr r6, [r5, r2] +100304be: 0c36 lsrs r6, r6, #16 +100304c0: b2bf uxth r7, r7 +100304c2: ea47 4606 orr.w r6, r7, r6, lsl #16 +100304c6: 50ae str r6, [r5, r2] +100304c8: 1c5b adds r3, r3, #1 +100304ca: 0076 lsls r6, r6, #1 +100304cc: 0876 lsrs r6, r6, #1 +100304ce: 50ae str r6, [r5, r2] +100304d0: 18ad adds r5, r5, r2 +100304d2: 6ae4 ldr r4, [r4, #44] ; 0x2c +100304d4: 606c str r4, [r5, #4] +100304d6: 6d84 ldr r4, [r0, #88] ; 0x58 +100304d8: 42a3 cmp r3, r4 +100304da: d3eb bcc.n 100304b4 +100304dc: 2001 movs r0, #1 +100304de: bdf0 pop {r4, r5, r6, r7, pc} + +100304e0 : +100304e0: b570 push {r4, r5, r6, lr} +100304e2: 4605 mov r5, r0 +100304e4: 4608 mov r0, r1 +100304e6: eb05 1140 add.w r1, r5, r0, lsl #5 +100304ea: f601 16b8 addw r6, r1, #2488 ; 0x9b8 +100304ee: f7ff ff5c bl 100303aa +100304f2: 4604 mov r4, r0 +100304f4: 68b0 ldr r0, [r6, #8] +100304f6: 69f1 ldr r1, [r6, #28] +100304f8: 1808 adds r0, r1, r0 +100304fa: 68f1 ldr r1, [r6, #12] +100304fc: fbb0 f2f1 udiv r2, r0, r1 +10030500: fb01 0612 mls r6, r1, r2, r0 +10030504: 00a0 lsls r0, r4, #2 +10030506: f500 7168 add.w r1, r0, #928 ; 0x3a0 +1003050a: 4632 mov r2, r6 +1003050c: 4628 mov r0, r5 +1003050e: f7f4 fbaf bl 10024c70 +10030512: f641 30a4 movw r0, #7076 ; 0x1ba4 +10030516: 2c02 cmp r4, #2 +10030518: 5940 ldr r0, [r0, r5] +1003051a: f642 1154 movw r1, #10580 ; 0x2954 +1003051e: d101 bne.n 10030524 +10030520: 520e strh r6, [r1, r0] +10030522: bd70 pop {r4, r5, r6, pc} +10030524: 2c04 cmp r4, #4 +10030526: bf04 itt eq +10030528: 1808 addeq r0, r1, r0 +1003052a: 8046 strheq r6, [r0, #2] +1003052c: bd70 pop {r4, r5, r6, pc} + +1003052e : +1003052e: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +10030532: 468a mov sl, r1 +10030534: b087 sub sp, #28 +10030536: 4680 mov r8, r0 +10030538: f8da 7084 ldr.w r7, [sl, #132] ; 0x84 +1003053c: f608 1028 addw r0, r8, #2344 ; 0x928 +10030540: 9002 str r0, [sp, #8] +10030542: 2601 movs r6, #1 +10030544: f8d8 9008 ldr.w r9, [r8, #8] +10030548: f10a 0408 add.w r4, sl, #8 +1003054c: 4650 mov r0, sl +1003054e: f7fc f945 bl 1002c7dc +10030552: 4605 mov r5, r0 +10030554: 0168 lsls r0, r5, #5 +10030556: 9003 str r0, [sp, #12] +10030558: f641 5b48 movw fp, #7496 ; 0x1d48 +1003055c: 6920 ldr r0, [r4, #16] +1003055e: 9005 str r0, [sp, #20] +10030560: 4640 mov r0, r8 +10030562: f7ef f95c bl 1001f81e +10030566: 2800 cmp r0, #0 +10030568: bf1e ittt ne +1003056a: eb0b 0008 addne.w r0, fp, r8 +1003056e: 7a40 ldrbne r0, [r0, #9] +10030570: 2800 cmpne r0, #0 +10030572: d052 beq.n 1003061a +10030574: f85b 0008 ldr.w r0, [fp, r8] +10030578: 9000 str r0, [sp, #0] +1003057a: a901 add r1, sp, #4 +1003057c: f8d0 b008 ldr.w fp, [r0, #8] +10030580: f600 1028 addw r0, r0, #2344 ; 0x928 +10030584: 9004 str r0, [sp, #16] +10030586: f10b 0020 add.w r0, fp, #32 +1003058a: f7e0 f9b5 bl 100108f8 +1003058e: 2d04 cmp r5, #4 +10030590: d019 beq.n 100305c6 +10030592: 9800 ldr r0, [sp, #0] +10030594: 4621 mov r1, r4 +10030596: f000 f8a5 bl 100306e4 +1003059a: b9a0 cbnz r0, 100305c6 +1003059c: 2600 movs r6, #0 +1003059e: a901 add r1, sp, #4 +100305a0: f10b 0020 add.w r0, fp, #32 +100305a4: f7e0 f9af bl 10010906 +100305a8: 9802 ldr r0, [sp, #8] +100305aa: 4639 mov r1, r7 +100305ac: f7fb ffd8 bl 1002c560 +100305b0: 2101 movs r1, #1 +100305b2: f107 0024 add.w r0, r7, #36 ; 0x24 +100305b6: f7fc fc66 bl 1002ce86 +100305ba: 9802 ldr r0, [sp, #8] +100305bc: 4651 mov r1, sl +100305be: f7fc f82b bl 1002c618 +100305c2: 4630 mov r0, r6 +100305c4: e135 b.n 10030832 <.text_22> +100305c6: 9800 ldr r0, [sp, #0] +100305c8: b2e9 uxtb r1, r5 +100305ca: f7ff ff25 bl 10030418 +100305ce: 4604 mov r4, r0 +100305d0: 9800 ldr r0, [sp, #0] +100305d2: 4651 mov r1, sl +100305d4: f000 f8c2 bl 1003075c +100305d8: 6861 ldr r1, [r4, #4] +100305da: 62f9 str r1, [r7, #44] ; 0x2c +100305dc: 2d04 cmp r5, #4 +100305de: bf08 it eq +100305e0: f888 6ad8 strbeq.w r6, [r8, #2776] ; 0xad8 +100305e4: b931 cbnz r1, 100305f4 +100305e6: a901 add r1, sp, #4 +100305e8: f10b 0020 add.w r0, fp, #32 +100305ec: f7e0 f98b bl 10010906 +100305f0: 2600 movs r6, #0 +100305f2: e7d9 b.n 100305a8 +100305f4: 4650 mov r0, sl +100305f6: f7f8 f969 bl 100288cc +100305fa: 9800 ldr r0, [sp, #0] +100305fc: 4622 mov r2, r4 +100305fe: 4651 mov r1, sl +10030600: f7ff ff2f bl 10030462 +10030604: 8b38 ldrh r0, [r7, #24] +10030606: 2802 cmp r0, #2 +10030608: d002 beq.n 10030610 +1003060a: 9804 ldr r0, [sp, #16] +1003060c: f000 f84b bl 100306a6 <.text_15> +10030610: 2d04 cmp r5, #4 +10030612: d034 beq.n 1003067e +10030614: 9800 ldr r0, [sp, #0] +10030616: 4629 mov r1, r5 +10030618: e038 b.n 1003068c +1003061a: a901 add r1, sp, #4 +1003061c: f109 0020 add.w r0, r9, #32 +10030620: f7e0 f96a bl 100108f8 +10030624: 2d04 cmp r5, #4 +10030626: d004 beq.n 10030632 +10030628: 4621 mov r1, r4 +1003062a: 4640 mov r0, r8 +1003062c: f000 f85a bl 100306e4 +10030630: b180 cbz r0, 10030654 +10030632: f8da 007c ldr.w r0, [sl, #124] ; 0x7c +10030636: b2e9 uxtb r1, r5 +10030638: f7ff feee bl 10030418 +1003063c: 4604 mov r4, r0 +1003063e: 4651 mov r1, sl +10030640: 4640 mov r0, r8 +10030642: f000 f88b bl 1003075c +10030646: 6861 ldr r1, [r4, #4] +10030648: 62f9 str r1, [r7, #44] ; 0x2c +1003064a: 2d04 cmp r5, #4 +1003064c: bf08 it eq +1003064e: f888 6ad8 strbeq.w r6, [r8, #2776] ; 0xad8 +10030652: b921 cbnz r1, 1003065e +10030654: 2600 movs r6, #0 +10030656: a901 add r1, sp, #4 +10030658: f109 0020 add.w r0, r9, #32 +1003065c: e7a2 b.n 100305a4 +1003065e: 4650 mov r0, sl +10030660: f7f8 f934 bl 100288cc +10030664: 4622 mov r2, r4 +10030666: 4651 mov r1, sl +10030668: 4640 mov r0, r8 +1003066a: f7ff fefa bl 10030462 +1003066e: 8b38 ldrh r0, [r7, #24] +10030670: 2802 cmp r0, #2 +10030672: d002 beq.n 1003067a +10030674: 9802 ldr r0, [sp, #8] +10030676: f000 f816 bl 100306a6 <.text_15> +1003067a: 2d04 cmp r5, #4 +1003067c: d104 bne.n 10030688 +1003067e: 6820 ldr r0, [r4, #0] +10030680: f040 4000 orr.w r0, r0, #2147483648 ; 0x80000000 +10030684: 6020 str r0, [r4, #0] +10030686: e003 b.n 10030690 +10030688: 4629 mov r1, r5 +1003068a: 4640 mov r0, r8 +1003068c: f7ff ff28 bl 100304e0 +10030690: a901 add r1, sp, #4 +10030692: f109 0020 add.w r0, r9, #32 +10030696: f7e0 f936 bl 10010906 +1003069a: 9a05 ldr r2, [sp, #20] +1003069c: 4651 mov r1, sl +1003069e: 4640 mov r0, r8 +100306a0: f7fb feb0 bl 1002c404 +100306a4: e789 b.n 100305ba + +100306a6 <.text_15>: +100306a6: 9a03 ldr r2, [sp, #12] +100306a8: 1810 adds r0, r2, r0 +100306aa: 4639 mov r1, r7 +100306ac: 3090 adds r0, #144 ; 0x90 +100306ae: e68d b.n 100303cc + +100306b0 : +100306b0: b570 push {r4, r5, r6, lr} +100306b2: f000 f84d bl 10030750 <.text_18> +100306b6: 2800 cmp r0, #0 +100306b8: bf1f itttt ne +100306ba: f641 5048 movwne r0, #7496 ; 0x1d48 +100306be: 1901 addne r1, r0, r4 +100306c0: 7a49 ldrbne r1, [r1, #9] +100306c2: 2900 cmpne r1, #0 +100306c4: bf1c itt ne +100306c6: 5900 ldrne r0, [r0, r4] +100306c8: f600 1628 addwne r6, r0, #2344 ; 0x928 +100306cc: eb06 1045 add.w r0, r6, r5, lsl #5 +100306d0: 3090 adds r0, #144 ; 0x90 +100306d2: 68c1 ldr r1, [r0, #12] +100306d4: 69c0 ldr r0, [r0, #28] +100306d6: 1a08 subs r0, r1, r0 +100306d8: 2802 cmp r0, #2 +100306da: d301 bcc.n 100306e0 +100306dc: 2001 movs r0, #1 +100306de: bd70 pop {r4, r5, r6, pc} +100306e0: 2000 movs r0, #0 +100306e2: bd70 pop {r4, r5, r6, pc} + +100306e4 : +100306e4: b570 push {r4, r5, r6, lr} +100306e6: f000 f833 bl 10030750 <.text_18> +100306ea: 2800 cmp r0, #0 +100306ec: bf1f itttt ne +100306ee: f641 5048 movwne r0, #7496 ; 0x1d48 +100306f2: 1901 addne r1, r0, r4 +100306f4: 7a49 ldrbne r1, [r1, #9] +100306f6: 2900 cmpne r1, #0 +100306f8: bf1c itt ne +100306fa: 5900 ldrne r0, [r0, r4] +100306fc: f600 1628 addwne r6, r0, #2344 ; 0x928 +10030700: f895 0060 ldrb.w r0, [r5, #96] ; 0x60 +10030704: 1e40 subs r0, r0, #1 +10030706: 2801 cmp r0, #1 +10030708: d90c bls.n 10030724 +1003070a: 1ec0 subs r0, r0, #3 +1003070c: 2801 cmp r0, #1 +1003070e: d90b bls.n 10030728 +10030710: 1e80 subs r0, r0, #2 +10030712: 2801 cmp r0, #1 +10030714: d911 bls.n 1003073a +10030716: 380a subs r0, #10 +10030718: d008 beq.n 1003072c +1003071a: 1e40 subs r0, r0, #1 +1003071c: d008 beq.n 10030730 +1003071e: 1e40 subs r0, r0, #1 +10030720: d008 beq.n 10030734 +10030722: e009 b.n 10030738 +10030724: 3660 adds r6, #96 ; 0x60 +10030726: e008 b.n 1003073a +10030728: 3620 adds r6, #32 +1003072a: e006 b.n 1003073a +1003072c: 3680 adds r6, #128 ; 0x80 +1003072e: e004 b.n 1003073a +10030730: 36c0 adds r6, #192 ; 0xc0 +10030732: e002 b.n 1003073a +10030734: 36a0 adds r6, #160 ; 0xa0 +10030736: e000 b.n 1003073a +10030738: 3640 adds r6, #64 ; 0x40 +1003073a: f106 0090 add.w r0, r6, #144 ; 0x90 +1003073e: 68c1 ldr r1, [r0, #12] +10030740: 69c0 ldr r0, [r0, #28] +10030742: 1a08 subs r0, r1, r0 +10030744: 2802 cmp r0, #2 +10030746: d301 bcc.n 1003074c +10030748: 2001 movs r0, #1 +1003074a: bd70 pop {r4, r5, r6, pc} +1003074c: 2000 movs r0, #0 +1003074e: bd70 pop {r4, r5, r6, pc} + +10030750 <.text_18>: +10030750: 4604 mov r4, r0 +10030752: 460d mov r5, r1 +10030754: f604 1628 addw r6, r4, #2344 ; 0x928 +10030758: f7ef b861 b.w 1001f81e + +1003075c : +1003075c: f8d1 0084 ldr.w r0, [r1, #132] ; 0x84 +10030760: f891 20d0 ldrb.w r2, [r1, #208] ; 0xd0 +10030764: b112 cbz r2, 1003076c +10030766: 2140 movs r1, #64 ; 0x40 +10030768: 6301 str r1, [r0, #48] ; 0x30 +1003076a: 4770 bx lr +1003076c: 2228 movs r2, #40 ; 0x28 +1003076e: 6302 str r2, [r0, #48] ; 0x30 +10030770: 698a ldr r2, [r1, #24] +10030772: 63c2 str r2, [r0, #60] ; 0x3c +10030774: 6902 ldr r2, [r0, #16] +10030776: 3228 adds r2, #40 ; 0x28 +10030778: 6382 str r2, [r0, #56] ; 0x38 +1003077a: 2202 movs r2, #2 +1003077c: 6582 str r2, [r0, #88] ; 0x58 +1003077e: f101 0098 add.w r0, r1, #152 ; 0x98 +10030782: 6902 ldr r2, [r0, #16] +10030784: 69c0 ldr r0, [r0, #28] +10030786: 1880 adds r0, r0, r2 +10030788: f8c1 0098 str.w r0, [r1, #152] ; 0x98 +1003078c: 4770 bx lr + +1003078e : +1003078e: b570 push {r4, r5, r6, lr} +10030790: 681e ldr r6, [r3, #0] +10030792: 4614 mov r4, r2 +10030794: 2500 movs r5, #0 +10030796: 4631 mov r1, r6 +10030798: 4618 mov r0, r3 +1003079a: f7e0 f8d6 bl 1001094a +1003079e: b930 cbnz r0, 100307ae +100307a0: 4635 mov r5, r6 +100307a2: 4628 mov r0, r5 +100307a4: f7e0 f85e bl 10010864 +100307a8: 6960 ldr r0, [r4, #20] +100307aa: 1e40 subs r0, r0, #1 +100307ac: 6160 str r0, [r4, #20] +100307ae: 4628 mov r0, r5 +100307b0: bd70 pop {r4, r5, r6, pc} + +100307b2 : +100307b2: e92d 4ff6 stmdb sp!, {r1, r2, r4, r5, r6, r7, r8, r9, sl, fp, lr} +100307b6: b085 sub sp, #20 +100307b8: 4680 mov r8, r0 +100307ba: ae01 add r6, sp, #4 +100307bc: 2001 movs r0, #1 +100307be: 6070 str r0, [r6, #4] +100307c0: 2500 movs r5, #0 +100307c2: 2002 movs r0, #2 +100307c4: 60b0 str r0, [r6, #8] +100307c6: 9501 str r5, [sp, #4] +100307c8: 2003 movs r0, #3 +100307ca: 9004 str r0, [sp, #16] +100307cc: a900 add r1, sp, #0 +100307ce: 4640 mov r0, r8 +100307d0: f7e0 f8a0 bl 10010914 +100307d4: 2700 movs r7, #0 +100307d6: e000 b.n 100307da +100307d8: 1c7f adds r7, r7, #1 +100307da: 9806 ldr r0, [sp, #24] +100307dc: 4287 cmp r7, r0 +100307de: da25 bge.n 1003082c +100307e0: 9805 ldr r0, [sp, #20] +100307e2: f856 1027 ldr.w r1, [r6, r7, lsl #2] +100307e6: eb00 04c1 add.w r4, r0, r1, lsl #3 +100307ea: f8d4 b000 ldr.w fp, [r4] +100307ee: f8db 9000 ldr.w r9, [fp] +100307f2: e001 b.n 100307f8 +100307f4: f8d9 9000 ldr.w r9, [r9] +100307f8: 4649 mov r1, r9 +100307fa: 4658 mov r0, fp +100307fc: f7e0 f8a5 bl 1001094a +10030800: 2800 cmp r0, #0 +10030802: d1e9 bne.n 100307d8 +10030804: f109 0a08 add.w sl, r9, #8 +10030808: 4653 mov r3, sl +1003080a: 464a mov r2, r9 +1003080c: 4621 mov r1, r4 +1003080e: 4640 mov r0, r8 +10030810: f7ff ffbd bl 1003078e +10030814: 0005 movs r5, r0 +10030816: d0ed beq.n 100307f4 +10030818: 6860 ldr r0, [r4, #4] +1003081a: 1e40 subs r0, r0, #1 +1003081c: 6060 str r0, [r4, #4] +1003081e: 4650 mov r0, sl +10030820: f7e0 f892 bl 10010948 +10030824: b110 cbz r0, 1003082c +10030826: 4648 mov r0, r9 +10030828: f7e0 f81c bl 10010864 +1003082c: f000 f9ec bl 10030c08 <.text_30> +10030830: 4628 mov r0, r5 + +10030832 <.text_22>: +10030832: b007 add sp, #28 +10030834: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +10030838 : +10030838: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +1003083c: 4604 mov r4, r0 +1003083e: f604 1828 addw r8, r4, #2344 ; 0x928 +10030842: 2601 movs r6, #1 +10030844: f641 479c movw r7, #7324 ; 0x1c9c +10030848: e003 b.n 10030852 +1003084a: 4649 mov r1, r9 +1003084c: 4620 mov r0, r4 +1003084e: f7ff fe6e bl 1003052e +10030852: 5938 ldr r0, [r7, r4] +10030854: 2801 cmp r0, #1 +10030856: bf1e ittt ne +10030858: 1938 addne r0, r7, r4 +1003085a: 6840 ldrne r0, [r0, #4] +1003085c: 2801 cmpne r0, #1 +1003085e: d057 beq.n 10030910 +10030860: 2101 movs r1, #1 +10030862: f000 f857 bl 10030914 <.text_24> +10030866: 2800 cmp r0, #0 +10030868: d052 beq.n 10030910 +1003086a: 2100 movs r1, #0 +1003086c: f000 f852 bl 10030914 <.text_24> +10030870: 2800 cmp r0, #0 +10030872: d04d beq.n 10030910 +10030874: 2102 movs r1, #2 +10030876: f000 f84d bl 10030914 <.text_24> +1003087a: 2800 cmp r0, #0 +1003087c: d048 beq.n 10030910 +1003087e: 2103 movs r1, #3 +10030880: f000 f848 bl 10030914 <.text_24> +10030884: 2800 cmp r0, #0 +10030886: d043 beq.n 10030910 +10030888: 2105 movs r1, #5 +1003088a: f000 f843 bl 10030914 <.text_24> +1003088e: 2800 cmp r0, #0 +10030890: d03e beq.n 10030910 +10030892: 2106 movs r1, #6 +10030894: f000 f83e bl 10030914 <.text_24> +10030898: b3d0 cbz r0, 10030910 +1003089a: 4640 mov r0, r8 +1003089c: f7fb fe32 bl 1002c504 +100308a0: 0005 movs r5, r0 +100308a2: d035 beq.n 10030910 +100308a4: f108 0088 add.w r0, r8, #136 ; 0x88 +100308a8: 7902 ldrb r2, [r0, #4] +100308aa: f8d8 1088 ldr.w r1, [r8, #136] ; 0x88 +100308ae: 4640 mov r0, r8 +100308b0: f7ff ff7f bl 100307b2 +100308b4: ea5f 0900 movs.w r9, r0 +100308b8: d024 beq.n 10030904 +100308ba: f8c9 5084 str.w r5, [r9, #132] ; 0x84 +100308be: 6928 ldr r0, [r5, #16] +100308c0: f8c9 0080 str.w r0, [r9, #128] ; 0x80 +100308c4: f8c5 9014 str.w r9, [r5, #20] +100308c8: f899 0078 ldrb.w r0, [r9, #120] ; 0x78 +100308cc: f000 000f and.w r0, r0, #15 +100308d0: 2801 cmp r0, #1 +100308d2: d10d bne.n 100308f0 +100308d4: f899 0041 ldrb.w r0, [r9, #65] ; 0x41 +100308d8: 2810 cmp r0, #16 +100308da: da09 bge.n 100308f0 +100308dc: f8d9 1074 ldr.w r1, [r9, #116] ; 0x74 +100308e0: 464a mov r2, r9 +100308e2: 4620 mov r0, r4 +100308e4: f000 f818 bl 10030918 +100308e8: 4606 mov r6, r0 +100308ea: 2000 movs r0, #0 +100308ec: f889 00d0 strb.w r0, [r9, #208] ; 0xd0 +100308f0: 2e01 cmp r6, #1 +100308f2: d0aa beq.n 1003084a +100308f4: 4629 mov r1, r5 +100308f6: 4640 mov r0, r8 +100308f8: f7fb fe32 bl 1002c560 +100308fc: 4649 mov r1, r9 +100308fe: f000 f980 bl 10030c02 <.text_29+0x2> +10030902: e7a6 b.n 10030852 +10030904: 4629 mov r1, r5 +10030906: 4640 mov r0, r8 +10030908: e8bd 43f4 ldmia.w sp!, {r2, r4, r5, r6, r7, r8, r9, lr} +1003090c: f7fb be28 b.w 1002c560 +10030910: e8bd 83f1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, pc} + +10030914 <.text_24>: +10030914: 4620 mov r0, r4 +10030916: e6cb b.n 100306b0 + +10030918 : +10030918: e92d 4ff3 stmdb sp!, {r0, r1, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1003091c: 4692 mov sl, r2 +1003091e: f10a 0408 add.w r4, sl, #8 +10030922: f104 053c add.w r5, r4, #60 ; 0x3c +10030926: b095 sub sp, #84 ; 0x54 +10030928: 7ce8 ldrb r0, [r5, #19] +1003092a: f000 0001 and.w r0, r0, #1 +1003092e: 9000 str r0, [sp, #0] +10030930: f04f 0b01 mov.w fp, #1 +10030934: 9815 ldr r0, [sp, #84] ; 0x54 +10030936: f500 5088 add.w r0, r0, #4352 ; 0x1100 +1003093a: f104 014f add.w r1, r4, #79 ; 0x4f +1003093e: 3028 adds r0, #40 ; 0x28 +10030940: f7f4 fc34 bl 100251ac +10030944: ea5f 0800 movs.w r8, r0 +10030948: bf08 it eq +1003094a: 2000 moveq r0, #0 +1003094c: f000 80d2 beq.w 10030af4 +10030950: 9815 ldr r0, [sp, #84] ; 0x54 +10030952: 4622 mov r2, r4 +10030954: a902 add r1, sp, #8 +10030956: f7fb fb84 bl 1002c062 +1003095a: 2800 cmp r0, #0 +1003095c: f000 80b2 beq.w 10030ac4 +10030960: 9816 ldr r0, [sp, #88] ; 0x58 +10030962: a90e add r1, sp, #56 ; 0x38 +10030964: f7ff faac bl 1002fec0 <_rtw_open_pktfile> +10030968: 1ca0 adds r0, r4, #2 +1003096a: 2100 movs r1, #0 +1003096c: 88c2 ldrh r2, [r0, #6] +1003096e: a80e add r0, sp, #56 ; 0x38 +10030970: f7ff fab0 bl 1002fed4 <_rtw_pktfile_read> +10030974: f8bd 0008 ldrh.w r0, [sp, #8] +10030978: f440 6080 orr.w r0, r0, #1024 ; 0x400 +1003097c: 1ca1 adds r1, r4, #2 +1003097e: f8ad 0008 strh.w r0, [sp, #8] +10030982: a802 add r0, sp, #8 +10030984: 8909 ldrh r1, [r1, #8] +10030986: f104 060c add.w r6, r4, #12 +1003098a: 180f adds r7, r1, r0 +1003098c: 7a70 ldrb r0, [r6, #9] +1003098e: 2800 cmp r0, #0 +10030990: d057 beq.n 10030a42 +10030992: 7a33 ldrb r3, [r6, #8] +10030994: 2000 movs r0, #0 +10030996: 2100 movs r1, #0 +10030998: 2b01 cmp r3, #1 +1003099a: f508 72a4 add.w r2, r8, #328 ; 0x148 +1003099e: d005 beq.n 100309ac +100309a0: 2b02 cmp r3, #2 +100309a2: d010 beq.n 100309c6 +100309a4: 2b04 cmp r3, #4 +100309a6: d01c beq.n 100309e2 +100309a8: 2b05 cmp r3, #5 +100309aa: d142 bne.n 10030a32 +100309ac: f000 f8a5 bl 10030afa <.text_26> +100309b0: 7892 ldrb r2, [r2, #2] +100309b2: 7372 strb r2, [r6, #13] +100309b4: 7e6a ldrb r2, [r5, #25] +100309b6: 0192 lsls r2, r2, #6 +100309b8: 73b2 strb r2, [r6, #14] +100309ba: f06f 457f mvn.w r5, #4278190080 ; 0xff000000 +100309be: e9d8 2352 ldrd r2, r3, [r8, #328] ; 0x148 +100309c2: 4283 cmp r3, r0 +100309c4: e02d b.n 10030a22 +100309c6: 9b00 ldr r3, [sp, #0] +100309c8: 2b00 cmp r3, #0 +100309ca: 7853 ldrb r3, [r2, #1] +100309cc: 72f3 strb r3, [r6, #11] +100309ce: 7853 ldrb r3, [r2, #1] +100309d0: f003 037f and.w r3, r3, #127 ; 0x7f +100309d4: f043 0320 orr.w r3, r3, #32 +100309d8: 7333 strb r3, [r6, #12] +100309da: f898 3148 ldrb.w r3, [r8, #328] ; 0x148 +100309de: 7373 strb r3, [r6, #13] +100309e0: e004 b.n 100309ec +100309e2: 9b00 ldr r3, [sp, #0] +100309e4: 2b00 cmp r3, #0 +100309e6: f000 f888 bl 10030afa <.text_26> +100309ea: 7370 strb r0, [r6, #13] +100309ec: d00f beq.n 10030a0e +100309ee: f64f 79ff movw r9, #65535 ; 0xffff +100309f2: 7e6b ldrb r3, [r5, #25] +100309f4: 019b lsls r3, r3, #6 +100309f6: f043 0320 orr.w r3, r3, #32 +100309fa: 73b3 strb r3, [r6, #14] +100309fc: f04f 35ff mov.w r5, #4294967295 +10030a00: 7893 ldrb r3, [r2, #2] +10030a02: 73f3 strb r3, [r6, #15] +10030a04: f000 f87f bl 10030b06 <.text_27> +10030a08: bf08 it eq +10030a0a: 42aa cmpeq r2, r5 +10030a0c: e00b b.n 10030a26 +10030a0e: 2320 movs r3, #32 +10030a10: 73b3 strb r3, [r6, #14] +10030a12: f64f 79ff movw r9, #65535 ; 0xffff +10030a16: 7893 ldrb r3, [r2, #2] +10030a18: 73f3 strb r3, [r6, #15] +10030a1a: f04f 35ff mov.w r5, #4294967295 +10030a1e: f000 f872 bl 10030b06 <.text_27> +10030a22: bf08 it eq +10030a24: 42aa cmpeq r2, r5 +10030a26: d002 beq.n 10030a2e +10030a28: 1c50 adds r0, r2, #1 +10030a2a: f143 0100 adc.w r1, r3, #0 +10030a2e: e9c8 0152 strd r0, r1, [r8, #328] ; 0x148 +10030a32: 7a72 ldrb r2, [r6, #9] +10030a34: f104 0117 add.w r1, r4, #23 +10030a38: 4638 mov r0, r7 +10030a3a: f7df fee8 bl 1001080e +10030a3e: 7a70 ldrb r0, [r6, #9] +10030a40: 19c7 adds r7, r0, r7 +10030a42: 1ca0 adds r0, r4, #2 +10030a44: 8841 ldrh r1, [r0, #2] +10030a46: 4638 mov r0, r7 +10030a48: f7fb fc9f bl 1002c38a +10030a4c: 4680 mov r8, r0 +10030a4e: eb08 0007 add.w r0, r8, r7 +10030a52: a902 add r1, sp, #8 +10030a54: 1a42 subs r2, r0, r1 +10030a56: 9816 ldr r0, [sp, #88] ; 0x58 +10030a58: 6900 ldr r0, [r0, #16] +10030a5a: 1ca1 adds r1, r4, #2 +10030a5c: 88c9 ldrh r1, [r1, #6] +10030a5e: eb01 0900 add.w r9, r1, r0 +10030a62: eba9 0702 sub.w r7, r9, r2 +10030a66: a902 add r1, sp, #8 +10030a68: 4638 mov r0, r7 +10030a6a: f7df fed0 bl 1001080e +10030a6e: 68e0 ldr r0, [r4, #12] +10030a70: 9001 str r0, [sp, #4] +10030a72: f10a 0574 add.w r5, sl, #116 ; 0x74 +10030a76: f1a7 0028 sub.w r0, r7, #40 ; 0x28 +10030a7a: 6929 ldr r1, [r5, #16] +10030a7c: 6108 str r0, [r1, #16] +10030a7e: 60e8 str r0, [r5, #12] +10030a80: 9801 ldr r0, [sp, #4] +10030a82: 7ab2 ldrb r2, [r6, #10] +10030a84: 4448 add r0, r9 +10030a86: b12a cbz r2, 10030a94 +10030a88: 78a1 ldrb r1, [r4, #2] +10030a8a: b139 cbz r1, 10030a9c +10030a8c: f104 0129 add.w r1, r4, #41 ; 0x29 +10030a90: f7df febd bl 1001080e +10030a94: 78a0 ldrb r0, [r4, #2] +10030a96: b108 cbz r0, 10030a9c +10030a98: 7ab0 ldrb r0, [r6, #10] +10030a9a: e000 b.n 10030a9e +10030a9c: 2000 movs r0, #0 +10030a9e: 1ca1 adds r1, r4, #2 +10030aa0: 7a72 ldrb r2, [r6, #9] +10030aa2: 8909 ldrh r1, [r1, #8] +10030aa4: 1851 adds r1, r2, r1 +10030aa6: 4441 add r1, r8 +10030aa8: 1840 adds r0, r0, r1 +10030aaa: 9901 ldr r1, [sp, #4] +10030aac: 1808 adds r0, r1, r0 +10030aae: 6070 str r0, [r6, #4] +10030ab0: f64f 31ff movw r1, #64511 ; 0xfbff +10030ab4: 8838 ldrh r0, [r7, #0] +10030ab6: 4008 ands r0, r1 +10030ab8: 8038 strh r0, [r7, #0] +10030aba: 4651 mov r1, sl +10030abc: 9815 ldr r0, [sp, #84] ; 0x54 +10030abe: f7fb f9ec bl 1002be9a +10030ac2: b910 cbnz r0, 10030aca +10030ac4: f04f 0b00 mov.w fp, #0 +10030ac8: e013 b.n 10030af2 +10030aca: 9815 ldr r0, [sp, #84] ; 0x54 +10030acc: 4651 mov r1, sl +10030ace: f7fb fab0 bl 1002c032 +10030ad2: 9800 ldr r0, [sp, #0] +10030ad4: b118 cbz r0, 10030ade +10030ad6: 2000 movs r0, #0 +10030ad8: f884 003c strb.w r0, [r4, #60] ; 0x3c +10030adc: e003 b.n 10030ae6 +10030ade: 9815 ldr r0, [sp, #84] ; 0x54 +10030ae0: 4651 mov r1, sl +10030ae2: f7fb fbfa bl 1002c2da +10030ae6: 2000 movs r0, #0 +10030ae8: f8ca 0074 str.w r0, [sl, #116] ; 0x74 +10030aec: 6929 ldr r1, [r5, #16] +10030aee: 9816 ldr r0, [sp, #88] ; 0x58 +10030af0: 60c8 str r0, [r1, #12] +10030af2: 4658 mov r0, fp +10030af4: b017 add sp, #92 ; 0x5c +10030af6: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +10030afa <.text_26>: +10030afa: f898 3148 ldrb.w r3, [r8, #328] ; 0x148 +10030afe: 72f3 strb r3, [r6, #11] +10030b00: 7853 ldrb r3, [r2, #1] +10030b02: 7333 strb r3, [r6, #12] +10030b04: 4770 bx lr + +10030b06 <.text_27>: +10030b06: 78d3 ldrb r3, [r2, #3] +10030b08: 7433 strb r3, [r6, #16] +10030b0a: 7913 ldrb r3, [r2, #4] +10030b0c: 7473 strb r3, [r6, #17] +10030b0e: 7952 ldrb r2, [r2, #5] +10030b10: 74b2 strb r2, [r6, #18] +10030b12: e9d8 2352 ldrd r2, r3, [r8, #328] ; 0x148 +10030b16: 454b cmp r3, r9 +10030b18: 4770 bx lr + +10030b1a : +10030b1a: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +10030b1e: 4606 mov r6, r0 +10030b20: b082 sub sp, #8 +10030b22: 460c mov r4, r1 +10030b24: f606 1828 addw r8, r6, #2344 ; 0x928 +10030b28: f104 0708 add.w r7, r4, #8 +10030b2c: f106 050c add.w r5, r6, #12 +10030b30: a900 add r1, sp, #0 +10030b32: 4640 mov r0, r8 +10030b34: f7df feee bl 10010914 +10030b38: 4639 mov r1, r7 +10030b3a: 4630 mov r0, r6 +10030b3c: f7fb fbb7 bl 1002c2ae +10030b40: 2801 cmp r0, #1 +10030b42: da04 bge.n 10030b4e +10030b44: 4639 mov r1, r7 +10030b46: 4630 mov r0, r6 +10030b48: f7ff fdcc bl 100306e4 +10030b4c: b918 cbnz r0, 10030b56 +10030b4e: f897 0060 ldrb.w r0, [r7, #96] ; 0x60 +10030b52: 2811 cmp r0, #17 +10030b54: d12d bne.n 10030bb2 +10030b56: 6868 ldr r0, [r5, #4] +10030b58: f410 6f08 tst.w r0, #2176 ; 0x880 +10030b5c: d129 bne.n 10030bb2 +10030b5e: f44f 6108 mov.w r1, #2176 ; 0x880 +10030b62: 4630 mov r0, r6 +10030b64: f7ee fe73 bl 1001f84e +10030b68: 2801 cmp r0, #1 +10030b6a: d022 beq.n 10030bb2 +10030b6c: 4640 mov r0, r8 +10030b6e: f7fb fcc9 bl 1002c504 +10030b72: 0007 movs r7, r0 +10030b74: d01d beq.n 10030bb2 +10030b76: f000 f847 bl 10030c08 <.text_30> +10030b7a: f8c4 7084 str.w r7, [r4, #132] ; 0x84 +10030b7e: 4622 mov r2, r4 +10030b80: 6938 ldr r0, [r7, #16] +10030b82: f8c4 0080 str.w r0, [r4, #128] ; 0x80 +10030b86: 617c str r4, [r7, #20] +10030b88: 2000 movs r0, #0 +10030b8a: f884 00d0 strb.w r0, [r4, #208] ; 0xd0 +10030b8e: 4630 mov r0, r6 +10030b90: 6f61 ldr r1, [r4, #116] ; 0x74 +10030b92: f7ff fec1 bl 10030918 +10030b96: 2801 cmp r0, #1 +10030b98: d104 bne.n 10030ba4 +10030b9a: 4621 mov r1, r4 +10030b9c: 4630 mov r0, r6 +10030b9e: f7ff fcc6 bl 1003052e +10030ba2: e028 b.n 10030bf6 +10030ba4: 4639 mov r1, r7 +10030ba6: 4640 mov r0, r8 +10030ba8: f7fb fcda bl 1002c560 +10030bac: f000 f828 bl 10030c00 <.text_29> +10030bb0: e021 b.n 10030bf6 +10030bb2: 4621 mov r1, r4 +10030bb4: 4630 mov r0, r6 +10030bb6: f7fb fe32 bl 1002c81e +10030bba: 2801 cmp r0, #1 +10030bbc: d102 bne.n 10030bc4 +10030bbe: f000 f823 bl 10030c08 <.text_30> +10030bc2: e018 b.n 10030bf6 +10030bc4: 4621 mov r1, r4 +10030bc6: 4630 mov r0, r6 +10030bc8: f7fb fd6d bl 1002c6a6 +10030bcc: 4606 mov r6, r0 +10030bce: f000 f81b bl 10030c08 <.text_30> +10030bd2: 2e01 cmp r6, #1 +10030bd4: d011 beq.n 10030bfa +10030bd6: f000 f813 bl 10030c00 <.text_29> +10030bda: e9d8 011a ldrd r0, r1, [r8, #104] ; 0x68 +10030bde: 1e40 subs r0, r0, #1 +10030be0: f161 0100 sbc.w r1, r1, #0 +10030be4: e9c8 011a strd r0, r1, [r8, #104] ; 0x68 +10030be8: e9d8 011c ldrd r0, r1, [r8, #112] ; 0x70 +10030bec: 1c40 adds r0, r0, #1 +10030bee: f141 0100 adc.w r1, r1, #0 +10030bf2: e9c8 011c strd r0, r1, [r8, #112] ; 0x70 +10030bf6: 2001 movs r0, #1 +10030bf8: e000 b.n 10030bfc +10030bfa: 2000 movs r0, #0 +10030bfc: e8bd 81f6 ldmia.w sp!, {r1, r2, r4, r5, r6, r7, r8, pc} + +10030c00 <.text_29>: +10030c00: 4621 mov r1, r4 +10030c02: 4640 mov r0, r8 +10030c04: f7fb bd08 b.w 1002c618 + +10030c08 <.text_30>: +10030c08: a900 add r1, sp, #0 +10030c0a: 4640 mov r0, r8 +10030c0c: f7df be83 b.w 10010916 + +10030c10 : +10030c10: b5f8 push {r3, r4, r5, r6, r7, lr} +10030c12: 460d mov r5, r1 +10030c14: 4604 mov r4, r0 +10030c16: f8d5 6084 ldr.w r6, [r5, #132] ; 0x84 +10030c1a: f604 1728 addw r7, r4, #2344 ; 0x928 +10030c1e: f105 0108 add.w r1, r5, #8 +10030c22: f7ff fd5f bl 100306e4 +10030c26: b948 cbnz r0, 10030c3c +10030c28: 4631 mov r1, r6 +10030c2a: 4638 mov r0, r7 +10030c2c: f7fb fc98 bl 1002c560 +10030c30: 4629 mov r1, r5 +10030c32: 4638 mov r0, r7 +10030c34: f7fb fcf0 bl 1002c618 +10030c38: 2000 movs r0, #0 +10030c3a: bdf2 pop {r1, r4, r5, r6, r7, pc} +10030c3c: 2000 movs r0, #0 +10030c3e: f885 00d0 strb.w r0, [r5, #208] ; 0xd0 +10030c42: 4629 mov r1, r5 +10030c44: 4620 mov r0, r4 +10030c46: e8bd 40f4 ldmia.w sp!, {r2, r4, r5, r6, r7, lr} +10030c4a: e470 b.n 1003052e + +10030c4c : +10030c4c: e765 b.n 10030b1a + +10030c4e : +10030c4e: 6840 ldr r0, [r0, #4] +10030c50: 4208 tst r0, r1 +10030c52: d001 beq.n 10030c58 +10030c54: 2001 movs r0, #1 +10030c56: 4770 bx lr +10030c58: 2000 movs r0, #0 +10030c5a: 4770 bx lr + +10030c5c : +10030c5c: 1c40 adds r0, r0, #1 +10030c5e: 1040 asrs r0, r0, #1 +10030c60: 385f subs r0, #95 ; 0x5f +10030c62: 4770 bx lr + +10030c64 : +10030c64: b538 push {r3, r4, r5, lr} +10030c66: f500 5288 add.w r2, r0, #4352 ; 0x1100 +10030c6a: 311c adds r1, #28 +10030c6c: 6854 ldr r4, [r2, #4] +10030c6e: 1c63 adds r3, r4, #1 +10030c70: 6053 str r3, [r2, #4] +10030c72: 2c64 cmp r4, #100 ; 0x64 +10030c74: f44f 5388 mov.w r3, #4352 ; 0x1100 +10030c78: d309 bcc.n 10030c8e +10030c7a: 2464 movs r4, #100 ; 0x64 +10030c7c: 6054 str r4, [r2, #4] +10030c7e: 581d ldr r5, [r3, r0] +10030c80: 6894 ldr r4, [r2, #8] +10030c82: eb00 0585 add.w r5, r0, r5, lsl #2 +10030c86: f8d5 5f70 ldr.w r5, [r5, #3952] ; 0xf70 +10030c8a: 1b64 subs r4, r4, r5 +10030c8c: 6094 str r4, [r2, #8] +10030c8e: 6894 ldr r4, [r2, #8] +10030c90: f891 505b ldrb.w r5, [r1, #91] ; 0x5b +10030c94: 192c adds r4, r5, r4 +10030c96: 6094 str r4, [r2, #8] +10030c98: 581c ldr r4, [r3, r0] +10030c9a: 1c65 adds r5, r4, #1 +10030c9c: 501d str r5, [r3, r0] +10030c9e: eb00 0484 add.w r4, r0, r4, lsl #2 +10030ca2: f891 105b ldrb.w r1, [r1, #91] ; 0x5b +10030ca6: f8c4 1f70 str.w r1, [r4, #3952] ; 0xf70 +10030caa: f600 54ba addw r4, r0, #3514 ; 0xdba +10030cae: 5819 ldr r1, [r3, r0] +10030cb0: 2964 cmp r1, #100 ; 0x64 +10030cb2: bf24 itt cs +10030cb4: 2100 movcs r1, #0 +10030cb6: 5019 strcs r1, [r3, r0] +10030cb8: 6891 ldr r1, [r2, #8] +10030cba: 6852 ldr r2, [r2, #4] +10030cbc: f890 0dba ldrb.w r0, [r0, #3514] ; 0xdba +10030cc0: fbb1 f1f2 udiv r1, r1, r2 +10030cc4: b118 cbz r0, 10030cce +10030cc6: 7860 ldrb r0, [r4, #1] +10030cc8: 7120 strb r0, [r4, #4] +10030cca: 7860 ldrb r0, [r4, #1] +10030ccc: e001 b.n 10030cd2 +10030cce: 7121 strb r1, [r4, #4] +10030cd0: b2c8 uxtb r0, r1 +10030cd2: f7ff ffc3 bl 10030c5c +10030cd6: 70a0 strb r0, [r4, #2] +10030cd8: bd31 pop {r0, r4, r5, pc} + +10030cda : +10030cda: e7c3 b.n 10030c64 + +10030cdc : +10030cdc: b538 push {r3, r4, r5, lr} +10030cde: 460c mov r4, r1 +10030ce0: f100 051c add.w r5, r0, #28 +10030ce4: 2260 movs r2, #96 ; 0x60 +10030ce6: 2100 movs r1, #0 +10030ce8: 4628 mov r0, r5 +10030cea: f7df fda5 bl 10010838 +10030cee: 6820 ldr r0, [r4, #0] +10030cf0: 0480 lsls r0, r0, #18 +10030cf2: 0c80 lsrs r0, r0, #18 +10030cf4: 8028 strh r0, [r5, #0] +10030cf6: 6820 ldr r0, [r4, #0] +10030cf8: 0b80 lsrs r0, r0, #14 +10030cfa: f000 0001 and.w r0, r0, #1 +10030cfe: 75a8 strb r0, [r5, #22] +10030d00: 6820 ldr r0, [r4, #0] +10030d02: 0bc0 lsrs r0, r0, #15 +10030d04: f000 0001 and.w r0, r0, #1 +10030d08: 75e8 strb r0, [r5, #23] +10030d0a: 6820 ldr r0, [r4, #0] +10030d0c: 0c00 lsrs r0, r0, #16 +10030d0e: f000 000f and.w r0, r0, #15 +10030d12: 00c0 lsls r0, r0, #3 +10030d14: 70e8 strb r0, [r5, #3] +10030d16: 6820 ldr r0, [r4, #0] +10030d18: 0d00 lsrs r0, r0, #20 +10030d1a: f000 0007 and.w r0, r0, #7 +10030d1e: 74e8 strb r0, [r5, #19] +10030d20: 6820 ldr r0, [r4, #0] +10030d22: 0dc0 lsrs r0, r0, #23 +10030d24: f000 0001 and.w r0, r0, #1 +10030d28: 7228 strb r0, [r5, #8] +10030d2a: 6820 ldr r0, [r4, #0] +10030d2c: 0e00 lsrs r0, r0, #24 +10030d2e: f000 0003 and.w r0, r0, #3 +10030d32: 7128 strb r0, [r5, #4] +10030d34: 6820 ldr r0, [r4, #0] +10030d36: 0e80 lsrs r0, r0, #26 +10030d38: f000 0001 and.w r0, r0, #1 +10030d3c: 70a8 strb r0, [r5, #2] +10030d3e: 6820 ldr r0, [r4, #0] +10030d40: 0ec0 lsrs r0, r0, #27 +10030d42: f000 0001 and.w r0, r0, #1 +10030d46: f080 0001 eor.w r0, r0, #1 +10030d4a: 74a8 strb r0, [r5, #18] +10030d4c: 6860 ldr r0, [r4, #4] +10030d4e: 0a00 lsrs r0, r0, #8 +10030d50: f000 000f and.w r0, r0, #15 +10030d54: 7268 strb r0, [r5, #9] +10030d56: 6860 ldr r0, [r4, #4] +10030d58: 0e80 lsrs r0, r0, #26 +10030d5a: f000 0001 and.w r0, r0, #1 +10030d5e: 72e8 strb r0, [r5, #11] +10030d60: 6860 ldr r0, [r4, #4] +10030d62: 0ec0 lsrs r0, r0, #27 +10030d64: f000 0001 and.w r0, r0, #1 +10030d68: 73e8 strb r0, [r5, #15] +10030d6a: 68a0 ldr r0, [r4, #8] +10030d6c: 0500 lsls r0, r0, #20 +10030d6e: 0d00 lsrs r0, r0, #20 +10030d70: 81a8 strh r0, [r5, #12] +10030d72: 68a0 ldr r0, [r4, #8] +10030d74: 0b00 lsrs r0, r0, #12 +10030d76: f000 000f and.w r0, r0, #15 +10030d7a: 73a8 strb r0, [r5, #14] +10030d7c: 68a0 ldr r0, [r4, #8] +10030d7e: f3c0 7000 ubfx r0, r0, #28, #1 +10030d82: b100 cbz r0, 10030d86 +10030d84: 2004 movs r0, #4 +10030d86: f885 0040 strb.w r0, [r5, #64] ; 0x40 +10030d8a: 7b20 ldrb r0, [r4, #12] +10030d8c: f000 007f and.w r0, r0, #127 ; 0x7f +10030d90: f885 004c strb.w r0, [r5, #76] ; 0x4c +10030d94: bd31 pop {r0, r4, r5, pc} + +10030d96 : +10030d96: e92d 4dfa stmdb sp!, {r1, r3, r4, r5, r6, r7, r8, sl, fp, lr} +10030d9a: 4604 mov r4, r0 +10030d9c: b086 sub sp, #24 +10030d9e: f8d4 8010 ldr.w r8, [r4, #16] +10030da2: f641 30a4 movw r0, #7076 ; 0x1ba4 +10030da6: f104 061c add.w r6, r4, #28 +10030daa: f850 b008 ldr.w fp, [r0, r8] +10030dae: f106 004e add.w r0, r6, #78 ; 0x4e +10030db2: 2700 movs r7, #0 +10030db4: 9004 str r0, [sp, #16] +10030db6: f8ad 7002 strh.w r7, [sp, #2] +10030dba: f88d 7004 strb.w r7, [sp, #4] +10030dbe: 2c00 cmp r4, #0 +10030dc0: bf0c ite eq +10030dc2: 2500 moveq r5, #0 +10030dc4: f8d4 5084 ldrne.w r5, [r4, #132] ; 0x84 +10030dc8: f105 0010 add.w r0, r5, #16 +10030dcc: 9002 str r0, [sp, #8] +10030dce: f105 0a04 add.w sl, r5, #4 +10030dd2: f105 000a add.w r0, r5, #10 +10030dd6: 9003 str r0, [sp, #12] +10030dd8: 8828 ldrh r0, [r5, #0] +10030dda: f000 010c and.w r1, r0, #12 +10030dde: 2904 cmp r1, #4 +10030de0: d01d beq.n 10030e1e +10030de2: 7df1 ldrb r1, [r6, #23] +10030de4: 2900 cmp r1, #0 +10030de6: bf04 itt eq +10030de8: 7db1 ldrbeq r1, [r6, #22] +10030dea: 2900 cmpeq r1, #0 +10030dec: d117 bne.n 10030e1e +10030dee: f000 f896 bl 10030f1e <.text_8> +10030df2: f108 019c add.w r1, r8, #156 ; 0x9c +10030df6: b2d2 uxtb r2, r2 +10030df8: b142 cbz r2, 10030e0c +10030dfa: 2a02 cmp r2, #2 +10030dfc: d002 beq.n 10030e04 +10030dfe: d303 bcc.n 10030e08 +10030e00: 2a03 cmp r2, #3 +10030e02: d105 bne.n 10030e10 +10030e04: 4650 mov r0, sl +10030e06: e004 b.n 10030e12 +10030e08: 9803 ldr r0, [sp, #12] +10030e0a: e002 b.n 10030e12 +10030e0c: 9802 ldr r0, [sp, #8] +10030e0e: e000 b.n 10030e12 +10030e10: 2000 movs r0, #0 +10030e12: 2206 movs r2, #6 +10030e14: f7df fd05 bl 10010822 +10030e18: b110 cbz r0, 10030e20 +10030e1a: 2001 movs r0, #1 +10030e1c: e000 b.n 10030e20 +10030e1e: 2000 movs r0, #0 +10030e20: f88d 0002 strb.w r0, [sp, #2] +10030e24: f89d 0002 ldrb.w r0, [sp, #2] +10030e28: b178 cbz r0, 10030e4a +10030e2a: 8828 ldrh r0, [r5, #0] +10030e2c: f508 51c8 add.w r1, r8, #6400 ; 0x1900 +10030e30: 3195 adds r1, #149 ; 0x95 +10030e32: f000 f874 bl 10030f1e <.text_8> +10030e36: b2d2 uxtb r2, r2 +10030e38: 2a01 cmp r2, #1 +10030e3a: bf94 ite ls +10030e3c: 4650 movls r0, sl +10030e3e: 9802 ldrhi r0, [sp, #8] +10030e40: 2206 movs r2, #6 +10030e42: f7df fcee bl 10010822 +10030e46: b100 cbz r0, 10030e4a +10030e48: 2001 movs r0, #1 +10030e4a: f88d 0003 strb.w r0, [sp, #3] +10030e4e: f89d 0002 ldrb.w r0, [sp, #2] +10030e52: b130 cbz r0, 10030e62 +10030e54: 7828 ldrb r0, [r5, #0] +10030e56: f000 00fc and.w r0, r0, #252 ; 0xfc +10030e5a: 2880 cmp r0, #128 ; 0x80 +10030e5c: bf08 it eq +10030e5e: 2001 moveq r0, #1 +10030e60: d000 beq.n 10030e64 +10030e62: 2000 movs r0, #0 +10030e64: f88d 0004 strb.w r0, [sp, #4] +10030e68: f89d 0004 ldrb.w r0, [sp, #4] +10030e6c: b138 cbz r0, 10030e7e +10030e6e: 2108 movs r1, #8 +10030e70: f000 f85b bl 10030f2a <.text_9> +10030e74: 2801 cmp r0, #1 +10030e76: d113 bne.n 10030ea0 +10030e78: f108 079c add.w r7, r8, #156 ; 0x9c +10030e7c: e010 b.n 10030ea0 +10030e7e: 8828 ldrh r0, [r5, #0] +10030e80: 0a01 lsrs r1, r0, #8 +10030e82: f001 0101 and.w r1, r1, #1 +10030e86: 0a80 lsrs r0, r0, #10 +10030e88: 4149 adcs r1, r1 +10030e8a: b2c9 uxtb r1, r1 +10030e8c: 2900 cmp r1, #0 +10030e8e: bf18 it ne +10030e90: 2902 cmpne r1, #2 +10030e92: d004 beq.n 10030e9e +10030e94: bf34 ite cc +10030e96: 9f02 ldrcc r7, [sp, #8] +10030e98: f105 0718 addcs.w r7, r5, #24 +10030e9c: e000 b.n 10030ea0 +10030e9e: 9f03 ldr r7, [sp, #12] +10030ea0: 20ff movs r0, #255 ; 0xff +10030ea2: f88d 0001 strb.w r0, [sp, #1] +10030ea6: 4639 mov r1, r7 +10030ea8: f508 5088 add.w r0, r8, #4352 ; 0x1100 +10030eac: 3028 adds r0, #40 ; 0x28 +10030eae: f7f4 f97d bl 100251ac +10030eb2: 0007 movs r7, r0 +10030eb4: bf1c itt ne +10030eb6: f8d7 0100 ldrne.w r0, [r7, #256] ; 0x100 +10030eba: f88d 0001 strbne.w r0, [sp, #1] +10030ebe: f896 004c ldrb.w r0, [r6, #76] ; 0x4c +10030ec2: 9a06 ldr r2, [sp, #24] +10030ec4: 9904 ldr r1, [sp, #16] +10030ec6: f88d 0000 strb.w r0, [sp] +10030eca: ab00 add r3, sp, #0 +10030ecc: f50b 50c8 add.w r0, fp, #6400 ; 0x1900 +10030ed0: 30a8 adds r0, #168 ; 0xa8 +10030ed2: f001 fc6f bl 100327b4 +10030ed6: 2000 movs r0, #0 +10030ed8: f8c4 0094 str.w r0, [r4, #148] ; 0x94 +10030edc: f89d 0002 ldrb.w r0, [sp, #2] +10030ee0: b130 cbz r0, 10030ef0 +10030ee2: 2110 movs r1, #16 +10030ee4: f000 f821 bl 10030f2a <.text_9> +10030ee8: 2801 cmp r0, #1 +10030eea: d101 bne.n 10030ef0 +10030eec: b1a7 cbz r7, 10030f18 +10030eee: e00d b.n 10030f0c +10030ef0: f89d 0003 ldrb.w r0, [sp, #3] +10030ef4: 2800 cmp r0, #0 +10030ef6: bf04 itt eq +10030ef8: f89d 0004 ldrbeq.w r0, [sp, #4] +10030efc: 2800 cmpeq r0, #0 +10030efe: d00b beq.n 10030f18 +10030f00: 2160 movs r1, #96 ; 0x60 +10030f02: f000 f812 bl 10030f2a <.text_9> +10030f06: 2801 cmp r0, #1 +10030f08: d102 bne.n 10030f10 +10030f0a: b10f cbz r7, 10030f10 +10030f0c: f8c4 7094 str.w r7, [r4, #148] ; 0x94 +10030f10: 4621 mov r1, r4 +10030f12: 4640 mov r0, r8 +10030f14: f7ff fee1 bl 10030cda +10030f18: b008 add sp, #32 +10030f1a: e8bd 8df0 ldmia.w sp!, {r4, r5, r6, r7, r8, sl, fp, pc} + +10030f1e <.text_8>: +10030f1e: 0a02 lsrs r2, r0, #8 +10030f20: f002 0201 and.w r2, r2, #1 +10030f24: 0a80 lsrs r0, r0, #10 +10030f26: 4152 adcs r2, r2 +10030f28: 4770 bx lr + +10030f2a <.text_9>: +10030f2a: f108 000c add.w r0, r8, #12 +10030f2e: e68e b.n 10030c4e + +10030f30 : +10030f30: 6800 ldr r0, [r0, #0] +10030f32: f7f3 be7b b.w 10024c2c + +10030f36 : +10030f36: 6800 ldr r0, [r0, #0] +10030f38: f7f3 be84 b.w 10024c44 + +10030f3c : +10030f3c: 6800 ldr r0, [r0, #0] +10030f3e: f7f3 be87 b.w 10024c50 + +10030f42 : +10030f42: 6800 ldr r0, [r0, #0] +10030f44: f7f3 be8c b.w 10024c60 + +10030f48 : +10030f48: 6800 ldr r0, [r0, #0] +10030f4a: f7f3 be91 b.w 10024c70 + +10030f4e : +10030f4e: e000 b.n 10030f52 <.text_11> + +10030f50 : +10030f50: bf00 nop + +10030f52 <.text_11>: +10030f52: 6800 ldr r0, [r0, #0] +10030f54: f7e6 bb12 b.w 1001757c + +10030f58 : +10030f58: bf00 nop + +10030f5a <.text_13>: +10030f5a: 6800 ldr r0, [r0, #0] +10030f5c: f7f8 bb88 b.w 10029670 + +10030f60 : +10030f60: b510 push {r4, lr} +10030f62: b082 sub sp, #8 +10030f64: 9c04 ldr r4, [sp, #16] +10030f66: 9400 str r4, [sp, #0] +10030f68: 6800 ldr r0, [r0, #0] +10030f6a: f7f8 fbfd bl 10029768 +10030f6e: bd13 pop {r0, r1, r4, pc} + +10030f70 : +10030f70: 6800 ldr r0, [r0, #0] +10030f72: f7f8 bbed b.w 10029750 + +10030f76 : +10030f76: 4608 mov r0, r1 +10030f78: 4611 mov r1, r2 +10030f7a: 461a mov r2, r3 +10030f7c: f7df bc47 b.w 1001080e + +10030f80 : +10030f80: f7df bd43 b.w 10010a0a + +10030f84 : +10030f84: f7df bd48 b.w 10010a18 + +10030f88 <_GetN>: +10030f88: 4603 mov r3, r0 +10030f8a: 4608 mov r0, r1 +10030f8c: 6901 ldr r1, [r0, #16] +10030f8e: 1e49 subs r1, r1, #1 +10030f90: 6101 str r1, [r0, #16] +10030f92: 68c2 ldr r2, [r0, #12] +10030f94: 1c52 adds r2, r2, #1 +10030f96: 2900 cmp r1, #0 +10030f98: 60c2 str r2, [r0, #12] +10030f9a: d403 bmi.n 10030fa4 <__iar_annotation$$tailcall+0x2> +10030f9c: 2201 movs r2, #1 +10030f9e: 6800 ldr r0, [r0, #0] +10030fa0: 2100 movs r1, #0 + +10030fa2 <__iar_annotation$$tailcall>: +10030fa2: 4718 bx r3 +10030fa4: f04f 30ff mov.w r0, #4294967295 +10030fa8: 4770 bx lr + +10030faa <_UngetN>: +10030faa: 4603 mov r3, r0 +10030fac: 4608 mov r0, r1 +10030fae: 4611 mov r1, r2 +10030fb0: 68c2 ldr r2, [r0, #12] +10030fb2: 1e52 subs r2, r2, #1 +10030fb4: f111 0f01 cmn.w r1, #1 +10030fb8: 60c2 str r2, [r0, #12] +10030fba: d002 beq.n 10030fc2 <__iar_annotation$$tailcall+0x2> +10030fbc: 2200 movs r2, #0 +10030fbe: 6800 ldr r0, [r0, #0] + +10030fc0 <__iar_annotation$$tailcall>: +10030fc0: 4718 bx r3 +10030fc2: 4770 bx lr + +10030fc4 <_ScanfSmallNoMb>: +10030fc4: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +10030fc8: b088 sub sp, #32 +10030fca: 4604 mov r4, r0 +10030fcc: 9100 str r1, [sp, #0] +10030fce: f04f 35ff mov.w r5, #4294967295 +10030fd2: 6818 ldr r0, [r3, #0] +10030fd4: 9001 str r0, [sp, #4] +10030fd6: 462e mov r6, r5 +10030fd8: 2000 movs r0, #0 +10030fda: 9003 str r0, [sp, #12] +10030fdc: 9202 str r2, [sp, #8] +10030fde: f20f 47b4 addw r7, pc, #1204 ; 0x4b4 +10030fe2: f20f 48a8 addw r8, pc, #1192 ; 0x4a8 +10030fe6: f06f 4900 mvn.w r9, #2147483648 ; 0x80000000 +10030fea: e002 b.n 10030ff2 <_ScanfSmallNoMb+0x2e> +10030fec: 9802 ldr r0, [sp, #8] +10030fee: 1c40 adds r0, r0, #1 +10030ff0: 9002 str r0, [sp, #8] +10030ff2: f8dd a008 ldr.w sl, [sp, #8] +10030ff6: f89a 0000 ldrb.w r0, [sl] +10030ffa: f1a0 0309 sub.w r3, r0, #9 +10030ffe: 2b05 cmp r3, #5 +10031000: d307 bcc.n 10031012 <_ScanfSmallNoMb+0x4e> +10031002: 2820 cmp r0, #32 +10031004: d005 beq.n 10031012 <_ScanfSmallNoMb+0x4e> +10031006: b9e0 cbnz r0, 10031042 <_ScanfSmallNoMb+0x7e> +10031008: 2e00 cmp r6, #0 +1003100a: bfb8 it lt +1003100c: 2600 movlt r6, #0 +1003100e: 4630 mov r0, r6 +10031010: e0cc b.n 100311ac <.text_5> +10031012: 9803 ldr r0, [sp, #12] +10031014: 1c40 adds r0, r0, #1 +10031016: 9003 str r0, [sp, #12] +10031018: 2201 movs r2, #1 +1003101a: 9800 ldr r0, [sp, #0] +1003101c: 2100 movs r1, #0 +1003101e: 47a0 blx r4 +10031020: f1a0 0109 sub.w r1, r0, #9 +10031024: 2905 cmp r1, #5 +10031026: d3f4 bcc.n 10031012 <_ScanfSmallNoMb+0x4e> +10031028: 2820 cmp r0, #32 +1003102a: d0f2 beq.n 10031012 <_ScanfSmallNoMb+0x4e> +1003102c: 9903 ldr r1, [sp, #12] +1003102e: 1e49 subs r1, r1, #1 +10031030: f110 0f01 cmn.w r0, #1 +10031034: 9103 str r1, [sp, #12] +10031036: d0d9 beq.n 10030fec <_ScanfSmallNoMb+0x28> +10031038: 4601 mov r1, r0 +1003103a: 9800 ldr r0, [sp, #0] +1003103c: 2200 movs r2, #0 +1003103e: 47a0 blx r4 +10031040: e7d4 b.n 10030fec <_ScanfSmallNoMb+0x28> +10031042: 2825 cmp r0, #37 ; 0x25 +10031044: d105 bne.n 10031052 <_ScanfSmallNoMb+0x8e> +10031046: f10a 0001 add.w r0, sl, #1 +1003104a: 9002 str r0, [sp, #8] +1003104c: 2000 movs r0, #0 +1003104e: 9005 str r0, [sp, #20] +10031050: e01b b.n 1003108a <_ScanfSmallNoMb+0xc6> +10031052: 2201 movs r2, #1 +10031054: 9803 ldr r0, [sp, #12] +10031056: 1c40 adds r0, r0, #1 +10031058: 9003 str r0, [sp, #12] +1003105a: 2100 movs r1, #0 +1003105c: 9800 ldr r0, [sp, #0] +1003105e: 47a0 blx r4 +10031060: f89a 1000 ldrb.w r1, [sl] +10031064: 4288 cmp r0, r1 +10031066: d0c1 beq.n 10030fec <_ScanfSmallNoMb+0x28> +10031068: 4602 mov r2, r0 +1003106a: a900 add r1, sp, #0 +1003106c: 4620 mov r0, r4 +1003106e: f7ff ff9c bl 10030faa <_UngetN> +10031072: e7c9 b.n 10031008 <_ScanfSmallNoMb+0x44> +10031074: 9905 ldr r1, [sp, #20] +10031076: 4549 cmp r1, r9 +10031078: d005 beq.n 10031086 <_ScanfSmallNoMb+0xc2> +1003107a: eb01 0381 add.w r3, r1, r1, lsl #2 +1003107e: eb02 0143 add.w r1, r2, r3, lsl #1 +10031082: 3930 subs r1, #48 ; 0x30 +10031084: 9105 str r1, [sp, #20] +10031086: 1c40 adds r0, r0, #1 +10031088: 9002 str r0, [sp, #8] +1003108a: 9802 ldr r0, [sp, #8] +1003108c: 7802 ldrb r2, [r0, #0] +1003108e: f1a2 0130 sub.w r1, r2, #48 ; 0x30 +10031092: 290a cmp r1, #10 +10031094: d3ee bcc.n 10031074 <_ScanfSmallNoMb+0xb0> +10031096: 9506 str r5, [sp, #24] +10031098: 7801 ldrb r1, [r0, #0] +1003109a: 4640 mov r0, r8 +1003109c: f002 ff8e bl 10033fbc <__iar_Strchr> +100310a0: b120 cbz r0, 100310ac <_ScanfSmallNoMb+0xe8> +100310a2: 9802 ldr r0, [sp, #8] +100310a4: 1c40 adds r0, r0, #1 +100310a6: 9002 str r0, [sp, #8] +100310a8: 1e40 subs r0, r0, #1 +100310aa: 7800 ldrb r0, [r0, #0] +100310ac: f88d 001c strb.w r0, [sp, #28] +100310b0: f89d 001c ldrb.w r0, [sp, #28] +100310b4: 2868 cmp r0, #104 ; 0x68 +100310b6: bf01 itttt eq +100310b8: 9902 ldreq r1, [sp, #8] +100310ba: 780a ldrbeq r2, [r1, #0] +100310bc: 2a68 cmpeq r2, #104 ; 0x68 +100310be: 2062 moveq r0, #98 ; 0x62 +100310c0: d006 beq.n 100310d0 <_ScanfSmallNoMb+0x10c> +100310c2: 286c cmp r0, #108 ; 0x6c +100310c4: bf02 ittt eq +100310c6: 9902 ldreq r1, [sp, #8] +100310c8: 7808 ldrbeq r0, [r1, #0] +100310ca: 286c cmpeq r0, #108 ; 0x6c +100310cc: d104 bne.n 100310d8 <_ScanfSmallNoMb+0x114> +100310ce: 2071 movs r0, #113 ; 0x71 +100310d0: f88d 001c strb.w r0, [sp, #28] +100310d4: 1c48 adds r0, r1, #1 +100310d6: 9002 str r0, [sp, #8] +100310d8: 9802 ldr r0, [sp, #8] +100310da: 7801 ldrb r1, [r0, #0] +100310dc: 4638 mov r0, r7 +100310de: f002 ff6d bl 10033fbc <__iar_Strchr> +100310e2: b9b0 cbnz r0, 10031112 <_ScanfSmallNoMb+0x14e> +100310e4: 9803 ldr r0, [sp, #12] +100310e6: 1c40 adds r0, r0, #1 +100310e8: 9003 str r0, [sp, #12] +100310ea: 2201 movs r2, #1 +100310ec: 9800 ldr r0, [sp, #0] +100310ee: 2100 movs r1, #0 +100310f0: 47a0 blx r4 +100310f2: f1a0 0109 sub.w r1, r0, #9 +100310f6: 2905 cmp r1, #5 +100310f8: d3f4 bcc.n 100310e4 <_ScanfSmallNoMb+0x120> +100310fa: 2820 cmp r0, #32 +100310fc: d0f2 beq.n 100310e4 <_ScanfSmallNoMb+0x120> +100310fe: 9903 ldr r1, [sp, #12] +10031100: 1e49 subs r1, r1, #1 +10031102: f110 0f01 cmn.w r0, #1 +10031106: 9103 str r1, [sp, #12] +10031108: d003 beq.n 10031112 <_ScanfSmallNoMb+0x14e> +1003110a: 4601 mov r1, r0 +1003110c: 9800 ldr r0, [sp, #0] +1003110e: 2200 movs r2, #0 +10031110: 47a0 blx r4 +10031112: 2000 movs r0, #0 +10031114: f88d 001d strb.w r0, [sp, #29] +10031118: 9802 ldr r0, [sp, #8] +1003111a: 7800 ldrb r0, [r0, #0] +1003111c: 2825 cmp r0, #37 ; 0x25 +1003111e: d012 beq.n 10031146 <_ScanfSmallNoMb+0x182> +10031120: 2858 cmp r0, #88 ; 0x58 +10031122: d032 beq.n 1003118a <_ScanfSmallNoMb+0x1c6> +10031124: 2863 cmp r0, #99 ; 0x63 +10031126: d035 beq.n 10031194 <_ScanfSmallNoMb+0x1d0> +10031128: 2864 cmp r0, #100 ; 0x64 +1003112a: bf18 it ne +1003112c: 2869 cmpne r0, #105 ; 0x69 +1003112e: d02c beq.n 1003118a <_ScanfSmallNoMb+0x1c6> +10031130: 286f cmp r0, #111 ; 0x6f +10031132: bf18 it ne +10031134: 2870 cmpne r0, #112 ; 0x70 +10031136: d028 beq.n 1003118a <_ScanfSmallNoMb+0x1c6> +10031138: 2873 cmp r0, #115 ; 0x73 +1003113a: d01b beq.n 10031174 <_ScanfSmallNoMb+0x1b0> +1003113c: 2875 cmp r0, #117 ; 0x75 +1003113e: bf18 it ne +10031140: 2878 cmpne r0, #120 ; 0x78 +10031142: d022 beq.n 1003118a <_ScanfSmallNoMb+0x1c6> +10031144: e012 b.n 1003116c <_ScanfSmallNoMb+0x1a8> +10031146: 9803 ldr r0, [sp, #12] +10031148: 1c40 adds r0, r0, #1 +1003114a: 9003 str r0, [sp, #12] +1003114c: 2201 movs r2, #1 +1003114e: 9800 ldr r0, [sp, #0] +10031150: 2100 movs r1, #0 +10031152: 47a0 blx r4 +10031154: 2825 cmp r0, #37 ; 0x25 +10031156: d01f beq.n 10031198 <_ScanfSmallNoMb+0x1d4> +10031158: 9903 ldr r1, [sp, #12] +1003115a: 1e49 subs r1, r1, #1 +1003115c: f110 0f01 cmn.w r0, #1 +10031160: 9103 str r1, [sp, #12] +10031162: d005 beq.n 10031170 <_ScanfSmallNoMb+0x1ac> +10031164: 4601 mov r1, r0 +10031166: 9800 ldr r0, [sp, #0] +10031168: 2200 movs r2, #0 +1003116a: 47a0 blx r4 +1003116c: 2000 movs r0, #0 +1003116e: e008 b.n 10031182 <_ScanfSmallNoMb+0x1be> +10031170: 4628 mov r0, r5 +10031172: e006 b.n 10031182 <_ScanfSmallNoMb+0x1be> +10031174: 2201 movs r2, #1 +10031176: a900 add r1, sp, #0 +10031178: 4620 mov r0, r4 +1003117a: f000 f81a bl 100311b2 <_GetstrSmallNoMb> +1003117e: 2801 cmp r0, #1 +10031180: da0a bge.n 10031198 <_ScanfSmallNoMb+0x1d4> +10031182: 2e00 cmp r6, #0 +10031184: f57f af43 bpl.w 1003100e <_ScanfSmallNoMb+0x4a> +10031188: e010 b.n 100311ac <.text_5> +1003118a: a900 add r1, sp, #0 +1003118c: 4620 mov r0, r4 +1003118e: f000 f86b bl 10031268 <_GetintSmallNoMb> +10031192: e7f4 b.n 1003117e <_ScanfSmallNoMb+0x1ba> +10031194: 2200 movs r2, #0 +10031196: e7ee b.n 10031176 <_ScanfSmallNoMb+0x1b2> +10031198: 2e00 cmp r6, #0 +1003119a: bf48 it mi +1003119c: 2600 movmi r6, #0 +1003119e: f89d 001d ldrb.w r0, [sp, #29] +100311a2: 2800 cmp r0, #0 +100311a4: f43f af22 beq.w 10030fec <_ScanfSmallNoMb+0x28> +100311a8: 1c76 adds r6, r6, #1 +100311aa: e71f b.n 10030fec <_ScanfSmallNoMb+0x28> + +100311ac <.text_5>: +100311ac: b008 add sp, #32 +100311ae: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + +100311b2 <_GetstrSmallNoMb>: +100311b2: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +100311b6: 460d mov r5, r1 +100311b8: 4680 mov r8, r0 +100311ba: 6968 ldr r0, [r5, #20] +100311bc: 2700 movs r7, #0 +100311be: 4616 mov r6, r2 +100311c0: 2801 cmp r0, #1 +100311c2: da04 bge.n 100311ce <_GetstrSmallNoMb+0x1c> +100311c4: 2e00 cmp r6, #0 +100311c6: bf14 ite ne +100311c8: f06f 4000 mvnne.w r0, #2147483648 ; 0x80000000 +100311cc: 2001 moveq r0, #1 +100311ce: 6128 str r0, [r5, #16] +100311d0: 6868 ldr r0, [r5, #4] +100311d2: 6068 str r0, [r5, #4] +100311d4: f850 4b04 ldr.w r4, [r0], #4 +100311d8: 6068 str r0, [r5, #4] +100311da: e007 b.n 100311ec <_GetstrSmallNoMb+0x3a> +100311dc: f804 9b01 strb.w r9, [r4], #1 +100311e0: 2001 movs r0, #1 +100311e2: 7768 strb r0, [r5, #29] +100311e4: 2702 movs r7, #2 +100311e6: 69a8 ldr r0, [r5, #24] +100311e8: 1e40 subs r0, r0, #1 +100311ea: 61a8 str r0, [r5, #24] +100311ec: 6928 ldr r0, [r5, #16] +100311ee: 1e40 subs r0, r0, #1 +100311f0: 6128 str r0, [r5, #16] +100311f2: 68e9 ldr r1, [r5, #12] +100311f4: 1c49 adds r1, r1, #1 +100311f6: 2800 cmp r0, #0 +100311f8: 60e9 str r1, [r5, #12] +100311fa: d41f bmi.n 1003123c <_GetstrSmallNoMb+0x8a> +100311fc: 2201 movs r2, #1 +100311fe: 6828 ldr r0, [r5, #0] +10031200: 2100 movs r1, #0 +10031202: 47c0 blx r8 +10031204: 4681 mov r9, r0 +10031206: f119 0f01 cmn.w r9, #1 +1003120a: d00c beq.n 10031226 <_GetstrSmallNoMb+0x74> +1003120c: 2e01 cmp r6, #1 +1003120e: db06 blt.n 1003121e <_GetstrSmallNoMb+0x6c> +10031210: f1a9 0009 sub.w r0, r9, #9 +10031214: 2805 cmp r0, #5 +10031216: d306 bcc.n 10031226 <_GetstrSmallNoMb+0x74> +10031218: f1b9 0f20 cmp.w r9, #32 +1003121c: d003 beq.n 10031226 <_GetstrSmallNoMb+0x74> +1003121e: 69a8 ldr r0, [r5, #24] +10031220: 2800 cmp r0, #0 +10031222: d1db bne.n 100311dc <_GetstrSmallNoMb+0x2a> +10031224: 2701 movs r7, #1 +10031226: 464a mov r2, r9 +10031228: 4629 mov r1, r5 +1003122a: 4640 mov r0, r8 +1003122c: f7ff febd bl 10030faa <_UngetN> +10031230: b10e cbz r6, 10031236 <_GetstrSmallNoMb+0x84> +10031232: 2f02 cmp r7, #2 +10031234: d011 beq.n 1003125a <_GetstrSmallNoMb+0xa8> +10031236: 2f02 cmp r7, #2 +10031238: d103 bne.n 10031242 <_GetstrSmallNoMb+0x90> +1003123a: e012 b.n 10031262 <_GetstrSmallNoMb+0xb0> +1003123c: f04f 39ff mov.w r9, #4294967295 +10031240: e7f1 b.n 10031226 <_GetstrSmallNoMb+0x74> +10031242: 07f8 lsls r0, r7, #31 +10031244: d402 bmi.n 1003124c <_GetstrSmallNoMb+0x9a> +10031246: f119 0f01 cmn.w r9, #1 +1003124a: d103 bne.n 10031254 <_GetstrSmallNoMb+0xa2> +1003124c: f04f 30ff mov.w r0, #4294967295 +10031250: e8bd 83f2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, pc} +10031254: 2000 movs r0, #0 +10031256: e8bd 83f2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, pc} +1003125a: 69a8 ldr r0, [r5, #24] +1003125c: b110 cbz r0, 10031264 <_GetstrSmallNoMb+0xb2> +1003125e: 2000 movs r0, #0 +10031260: 7020 strb r0, [r4, #0] +10031262: 2001 movs r0, #1 +10031264: e8bd 83f2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, pc} + +10031268 <_GetintSmallNoMb>: +10031268: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} +1003126c: 460c mov r4, r1 +1003126e: b089 sub sp, #36 ; 0x24 +10031270: 4680 mov r8, r0 +10031272: 6960 ldr r0, [r4, #20] +10031274: 2801 cmp r0, #1 +10031276: bfb8 it lt +10031278: f06f 4000 mvnlt.w r0, #2147483648 ; 0x80000000 +1003127c: 6120 str r0, [r4, #16] +1003127e: f10d 0900 add.w r9, sp, #0 +10031282: 4640 mov r0, r8 +10031284: f7ff fe80 bl 10030f88 <_GetN> +10031288: 4607 mov r7, r0 +1003128a: 2f2b cmp r7, #43 ; 0x2b +1003128c: bf18 it ne +1003128e: 2f2d cmpne r7, #45 ; 0x2d +10031290: d113 bne.n 100312ba <_GetintSmallNoMb+0x52> +10031292: f88d 7000 strb.w r7, [sp] +10031296: f10d 0901 add.w r9, sp, #1 +1003129a: 6920 ldr r0, [r4, #16] +1003129c: 1e40 subs r0, r0, #1 +1003129e: 6120 str r0, [r4, #16] +100312a0: 68e1 ldr r1, [r4, #12] +100312a2: 1c49 adds r1, r1, #1 +100312a4: 2800 cmp r0, #0 +100312a6: 60e1 str r1, [r4, #12] +100312a8: d405 bmi.n 100312b6 <_GetintSmallNoMb+0x4e> +100312aa: 2201 movs r2, #1 +100312ac: 6820 ldr r0, [r4, #0] +100312ae: 2100 movs r1, #0 +100312b0: 47c0 blx r8 +100312b2: 4607 mov r7, r0 +100312b4: e001 b.n 100312ba <_GetintSmallNoMb+0x52> +100312b6: f04f 37ff mov.w r7, #4294967295 +100312ba: 68a0 ldr r0, [r4, #8] +100312bc: 7800 ldrb r0, [r0, #0] +100312be: 2500 movs r5, #0 +100312c0: 2864 cmp r0, #100 ; 0x64 +100312c2: bf14 ite ne +100312c4: 2875 cmpne r0, #117 ; 0x75 +100312c6: 260a moveq r6, #10 +100312c8: d00d beq.n 100312e6 <_GetintSmallNoMb+0x7e> +100312ca: 2869 cmp r0, #105 ; 0x69 +100312cc: bf08 it eq +100312ce: 2600 moveq r6, #0 +100312d0: d009 beq.n 100312e6 <_GetintSmallNoMb+0x7e> +100312d2: 286f cmp r0, #111 ; 0x6f +100312d4: bf08 it eq +100312d6: 2608 moveq r6, #8 +100312d8: d005 beq.n 100312e6 <_GetintSmallNoMb+0x7e> +100312da: 2870 cmp r0, #112 ; 0x70 +100312dc: bf1a itte ne +100312de: f040 0020 orrne.w r0, r0, #32 +100312e2: 2878 cmpne r0, #120 ; 0x78 +100312e4: 2610 moveq r6, #16 +100312e6: 2f30 cmp r7, #48 ; 0x30 +100312e8: d130 bne.n 1003134c <_GetintSmallNoMb+0xe4> +100312ea: 6920 ldr r0, [r4, #16] +100312ec: 1e40 subs r0, r0, #1 +100312ee: 6120 str r0, [r4, #16] +100312f0: 2501 movs r5, #1 +100312f2: 68e1 ldr r1, [r4, #12] +100312f4: 1c49 adds r1, r1, #1 +100312f6: 2800 cmp r0, #0 +100312f8: 60e1 str r1, [r4, #12] +100312fa: d405 bmi.n 10031308 <_GetintSmallNoMb+0xa0> +100312fc: 2201 movs r2, #1 +100312fe: 6820 ldr r0, [r4, #0] +10031300: 2100 movs r1, #0 +10031302: 47c0 blx r8 +10031304: 4607 mov r7, r0 +10031306: e001 b.n 1003130c <_GetintSmallNoMb+0xa4> +10031308: f04f 37ff mov.w r7, #4294967295 +1003130c: f047 0020 orr.w r0, r7, #32 +10031310: b2c0 uxtb r0, r0 +10031312: 2878 cmp r0, #120 ; 0x78 +10031314: d117 bne.n 10031346 <_GetintSmallNoMb+0xde> +10031316: 2e00 cmp r6, #0 +10031318: bf18 it ne +1003131a: 2e10 cmpne r6, #16 +1003131c: d11f bne.n 1003135e <_GetintSmallNoMb+0xf6> +1003131e: 6920 ldr r0, [r4, #16] +10031320: 1e40 subs r0, r0, #1 +10031322: 6120 str r0, [r4, #16] +10031324: 2610 movs r6, #16 +10031326: 68e1 ldr r1, [r4, #12] +10031328: 1c49 adds r1, r1, #1 +1003132a: 2800 cmp r0, #0 +1003132c: 60e1 str r1, [r4, #12] +1003132e: d406 bmi.n 1003133e <_GetintSmallNoMb+0xd6> +10031330: 2201 movs r2, #1 +10031332: 6820 ldr r0, [r4, #0] +10031334: 2100 movs r1, #0 +10031336: 47c0 blx r8 +10031338: 4607 mov r7, r0 +1003133a: 2500 movs r5, #0 +1003133c: e00f b.n 1003135e <_GetintSmallNoMb+0xf6> +1003133e: f04f 37ff mov.w r7, #4294967295 +10031342: 2500 movs r5, #0 +10031344: e04b b.n 100313de <_GetintSmallNoMb+0x176> +10031346: b956 cbnz r6, 1003135e <_GetintSmallNoMb+0xf6> +10031348: 2608 movs r6, #8 +1003134a: e008 b.n 1003135e <_GetintSmallNoMb+0xf6> +1003134c: bb06 cbnz r6, 10031390 <_GetintSmallNoMb+0x128> +1003134e: 260a movs r6, #10 +10031350: e01e b.n 10031390 <_GetintSmallNoMb+0x128> +10031352: 2201 movs r2, #1 +10031354: 6820 ldr r0, [r4, #0] +10031356: 2100 movs r1, #0 +10031358: 47c0 blx r8 +1003135a: 4607 mov r7, r0 +1003135c: 2501 movs r5, #1 +1003135e: 2f30 cmp r7, #48 ; 0x30 +10031360: d10b bne.n 1003137a <_GetintSmallNoMb+0x112> +10031362: 6920 ldr r0, [r4, #16] +10031364: 1e41 subs r1, r0, #1 +10031366: 6121 str r1, [r4, #16] +10031368: 68e0 ldr r0, [r4, #12] +1003136a: 1c40 adds r0, r0, #1 +1003136c: 2900 cmp r1, #0 +1003136e: 60e0 str r0, [r4, #12] +10031370: d5ef bpl.n 10031352 <_GetintSmallNoMb+0xea> +10031372: f04f 37ff mov.w r7, #4294967295 +10031376: 2501 movs r5, #1 +10031378: e000 b.n 1003137c <_GetintSmallNoMb+0x114> +1003137a: b14d cbz r5, 10031390 <_GetintSmallNoMb+0x128> +1003137c: 2030 movs r0, #48 ; 0x30 +1003137e: f809 0b01 strb.w r0, [r9], #1 +10031382: e005 b.n 10031390 <_GetintSmallNoMb+0x128> +10031384: 6820 ldr r0, [r4, #0] +10031386: 2201 movs r2, #1 +10031388: 2100 movs r1, #0 +1003138a: 47c0 blx r8 +1003138c: 4607 mov r7, r0 +1003138e: 2501 movs r5, #1 +10031390: f117 0f01 cmn.w r7, #1 +10031394: d023 beq.n 100313de <_GetintSmallNoMb+0x176> +10031396: b2f9 uxtb r1, r7 +10031398: 2961 cmp r1, #97 ; 0x61 +1003139a: bfa8 it ge +1003139c: 3957 subge r1, #87 ; 0x57 +1003139e: da09 bge.n 100313b4 <_GetintSmallNoMb+0x14c> +100313a0: 2941 cmp r1, #65 ; 0x41 +100313a2: bfa8 it ge +100313a4: 3937 subge r1, #55 ; 0x37 +100313a6: da05 bge.n 100313b4 <_GetintSmallNoMb+0x14c> +100313a8: f1a1 0230 sub.w r2, r1, #48 ; 0x30 +100313ac: 2a0a cmp r2, #10 +100313ae: bf34 ite cc +100313b0: 3930 subcc r1, #48 ; 0x30 +100313b2: 21ff movcs r1, #255 ; 0xff +100313b4: b2c9 uxtb r1, r1 +100313b6: b2f0 uxtb r0, r6 +100313b8: 4281 cmp r1, r0 +100313ba: d210 bcs.n 100313de <_GetintSmallNoMb+0x176> +100313bc: f10d 001f add.w r0, sp, #31 +100313c0: 4581 cmp r9, r0 +100313c2: bf38 it cc +100313c4: f809 7b01 strbcc.w r7, [r9], #1 +100313c8: 6920 ldr r0, [r4, #16] +100313ca: 1e41 subs r1, r0, #1 +100313cc: 6121 str r1, [r4, #16] +100313ce: 68e0 ldr r0, [r4, #12] +100313d0: 1c40 adds r0, r0, #1 +100313d2: 2900 cmp r1, #0 +100313d4: 60e0 str r0, [r4, #12] +100313d6: d5d5 bpl.n 10031384 <_GetintSmallNoMb+0x11c> +100313d8: f04f 37ff mov.w r7, #4294967295 +100313dc: 2501 movs r5, #1 +100313de: 463a mov r2, r7 +100313e0: 4621 mov r1, r4 +100313e2: 4640 mov r0, r8 +100313e4: f7ff fde1 bl 10030faa <_UngetN> +100313e8: b945 cbnz r5, 100313fc <_GetintSmallNoMb+0x194> +100313ea: a800 add r0, sp, #0 +100313ec: 4581 cmp r9, r0 +100313ee: bf0a itet eq +100313f0: f117 0f01 cmneq.w r7, #1 +100313f4: 2000 movne r0, #0 +100313f6: f04f 30ff moveq.w r0, #4294967295 +100313fa: e043 b.n 10031484 <.text_8> +100313fc: 2000 movs r0, #0 +100313fe: f889 0000 strb.w r0, [r9] +10031402: 68a0 ldr r0, [r4, #8] +10031404: 7800 ldrb r0, [r0, #0] +10031406: 2864 cmp r0, #100 ; 0x64 +10031408: bf18 it ne +1003140a: 2869 cmpne r0, #105 ; 0x69 +1003140c: d108 bne.n 10031420 <_GetintSmallNoMb+0x1b8> +1003140e: 2300 movs r3, #0 +10031410: 4632 mov r2, r6 +10031412: 2100 movs r1, #0 +10031414: a800 add r0, sp, #0 +10031416: f002 fddc bl 10033fd2 <__iar_Stolx> +1003141a: 2101 movs r1, #1 +1003141c: 7761 strb r1, [r4, #29] +1003141e: e00a b.n 10031436 <_GetintSmallNoMb+0x1ce> +10031420: 4632 mov r2, r6 +10031422: 2100 movs r1, #0 +10031424: a800 add r0, sp, #0 +10031426: f002 febb bl 100341a0 <__iar_Stoul> +1003142a: 2101 movs r1, #1 +1003142c: 7761 strb r1, [r4, #29] +1003142e: 68a1 ldr r1, [r4, #8] +10031430: 7809 ldrb r1, [r1, #0] +10031432: 2970 cmp r1, #112 ; 0x70 +10031434: d01f beq.n 10031476 <_GetintSmallNoMb+0x20e> +10031436: 7f21 ldrb r1, [r4, #28] +10031438: 2962 cmp r1, #98 ; 0x62 +1003143a: d007 beq.n 1003144c <_GetintSmallNoMb+0x1e4> +1003143c: 2968 cmp r1, #104 ; 0x68 +1003143e: d00c beq.n 1003145a <_GetintSmallNoMb+0x1f2> +10031440: 296c cmp r1, #108 ; 0x6c +10031442: bf1c itt ne +10031444: 2974 cmpne r1, #116 ; 0x74 +10031446: 297a cmpne r1, #122 ; 0x7a +10031448: d00e beq.n 10031468 <_GetintSmallNoMb+0x200> +1003144a: e014 b.n 10031476 <_GetintSmallNoMb+0x20e> +1003144c: 6861 ldr r1, [r4, #4] +1003144e: 6061 str r1, [r4, #4] +10031450: f851 2b04 ldr.w r2, [r1], #4 +10031454: 6061 str r1, [r4, #4] +10031456: 7010 strb r0, [r2, #0] +10031458: e013 b.n 10031482 <_GetintSmallNoMb+0x21a> +1003145a: 6861 ldr r1, [r4, #4] +1003145c: 6061 str r1, [r4, #4] +1003145e: f851 2b04 ldr.w r2, [r1], #4 +10031462: 6061 str r1, [r4, #4] +10031464: 8010 strh r0, [r2, #0] +10031466: e00c b.n 10031482 <_GetintSmallNoMb+0x21a> +10031468: 6861 ldr r1, [r4, #4] +1003146a: 6061 str r1, [r4, #4] +1003146c: f851 2b04 ldr.w r2, [r1], #4 +10031470: 6061 str r1, [r4, #4] +10031472: 6010 str r0, [r2, #0] +10031474: e005 b.n 10031482 <_GetintSmallNoMb+0x21a> +10031476: 6861 ldr r1, [r4, #4] +10031478: 6061 str r1, [r4, #4] +1003147a: f851 2b04 ldr.w r2, [r1], #4 +1003147e: 6061 str r1, [r4, #4] +10031480: 6010 str r0, [r2, #0] +10031482: 2001 movs r0, #1 + +10031484 <.text_8>: +10031484: b009 add sp, #36 ; 0x24 +10031486: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + ... + +1003148c : +1003148c: 6c68 7a74 004c 0000 hltzL... + +10031494 : +10031494: 4363 5b6e 0000 0000 cCn[.... + +1003149c : +1003149c: b580 push {r7, lr} +1003149e: 480b ldr r0, [pc, #44] ; (100314cc ) +100314a0: 6801 ldr r1, [r0, #0] +100314a2: f041 0101 orr.w r1, r1, #1 +100314a6: 6001 str r1, [r0, #0] +100314a8: 2000 movs r0, #0 +100314aa: f7d3 fabf bl 10004a2c +100314ae: b960 cbnz r0, 100314ca +100314b0: 4807 ldr r0, [pc, #28] ; (100314d0 ) +100314b2: 6800 ldr r0, [r0, #0] +100314b4: 0040 lsls r0, r0, #1 +100314b6: bf44 itt mi +100314b8: f20f 10f0 addwmi r0, pc, #496 ; 0x1f0 +100314bc: f7d2 fdc0 blmi 10004040 +100314c0: 4804 ldr r0, [pc, #16] ; (100314d4 ) +100314c2: 6801 ldr r1, [r0, #0] +100314c4: f041 010f orr.w r1, r1, #15 +100314c8: 6001 str r1, [r0, #0] + +100314ca : +100314ca: bd01 pop {r0, pc} + +100314cc : +100314cc: 02c0 4000 ...@ + +100314d0 : +100314d0: 0314 1000 .... + +100314d4 : +100314d4: 00fc 4000 ...@ + +100314d8 : +100314d8: b510 push {r4, lr} +100314da: 460c mov r4, r1 +100314dc: f7ff ffde bl 1003149c +100314e0: f1a4 40d0 sub.w r0, r4, #1744830464 ; 0x68000000 +100314e4: f7d3 fa92 bl 10004a0c + +100314e8 : +100314e8: e8bd 4010 ldmia.w sp!, {r4, lr} +100314ec: f7d3 bd22 b.w 10004f34 + +100314f0 : +100314f0: b570 push {r4, r5, r6, lr} +100314f2: b082 sub sp, #8 +100314f4: f000 f81a bl 1003152c + +100314f8 : +100314f8: 6820 ldr r0, [r4, #0] +100314fa: 9000 str r0, [sp, #0] +100314fc: f7d3 fc14 bl 10004d28 +10031500: f1a5 40d0 sub.w r0, r5, #1744830464 ; 0x68000000 +10031504: 6800 ldr r0, [r0, #0] +10031506: 6030 str r0, [r6, #0] +10031508: e00c b.n 10031524 + +1003150a : +1003150a: b570 push {r4, r5, r6, lr} +1003150c: b082 sub sp, #8 +1003150e: f000 f80d bl 1003152c + +10031512 : +10031512: f1a5 40d0 sub.w r0, r5, #1744830464 ; 0x68000000 +10031516: 6006 str r6, [r0, #0] +10031518: f7d3 fa0a bl 10004930 +1003151c: 6820 ldr r0, [r4, #0] +1003151e: 9000 str r0, [sp, #0] +10031520: f7d3 fc02 bl 10004d28 + +10031524 : +10031524: f7d3 fd06 bl 10004f34 +10031528: 2001 movs r0, #1 +1003152a: bd76 pop {r1, r2, r4, r5, r6, pc} + +1003152c : +1003152c: 4604 mov r4, r0 +1003152e: 460d mov r5, r1 +10031530: 4616 mov r6, r2 +10031532: e7b3 b.n 1003149c + +10031534 : +10031534: b5f0 push {r4, r5, r6, r7, lr} +10031536: b083 sub sp, #12 +10031538: 4607 mov r7, r0 +1003153a: 460e mov r6, r1 +1003153c: 4614 mov r4, r2 +1003153e: 461d mov r5, r3 +10031540: f7ff ffac bl 1003149c +10031544: 6838 ldr r0, [r7, #0] +10031546: 9001 str r0, [sp, #4] +10031548: f7d3 fbee bl 10004d28 +1003154c: f016 0003 ands.w r0, r6, #3 +10031550: d012 beq.n 10031578 +10031552: 1a31 subs r1, r6, r0 +10031554: f1a1 41d0 sub.w r1, r1, #1744830464 ; 0x68000000 +10031558: 2200 movs r2, #0 +1003155a: 6809 ldr r1, [r1, #0] +1003155c: 9100 str r1, [sp, #0] +1003155e: a900 add r1, sp, #0 +10031560: 1841 adds r1, r0, r1 +10031562: f1c0 0004 rsb r0, r0, #4 +10031566: e000 b.n 1003156a + +10031568 : +10031568: 1c52 adds r2, r2, #1 + +1003156a : +1003156a: 4282 cmp r2, r0 +1003156c: d204 bcs.n 10031578 +1003156e: 5c53 ldrb r3, [r2, r1] +10031570: f805 3b01 strb.w r3, [r5], #1 +10031574: 1e64 subs r4, r4, #1 +10031576: d1f7 bne.n 10031568 + +10031578 : +10031578: 1cf0 adds r0, r6, #3 +1003157a: 0880 lsrs r0, r0, #2 +1003157c: 0080 lsls r0, r0, #2 +1003157e: f015 0103 ands.w r1, r5, #3 +10031582: d017 beq.n 100315b4 + +10031584 : +10031584: 2c04 cmp r4, #4 +10031586: d317 bcc.n 100315b8 +10031588: f1a0 41d0 sub.w r1, r0, #1744830464 ; 0x68000000 +1003158c: 2200 movs r2, #0 +1003158e: 6809 ldr r1, [r1, #0] +10031590: 9100 str r1, [sp, #0] + +10031592 : +10031592: a900 add r1, sp, #0 +10031594: 5c51 ldrb r1, [r2, r1] +10031596: f805 1b01 strb.w r1, [r5], #1 +1003159a: 1c52 adds r2, r2, #1 +1003159c: 2a04 cmp r2, #4 +1003159e: d3f8 bcc.n 10031592 +100315a0: 1d00 adds r0, r0, #4 +100315a2: 1f24 subs r4, r4, #4 +100315a4: e7ee b.n 10031584 + +100315a6 : +100315a6: f1a0 41d0 sub.w r1, r0, #1744830464 ; 0x68000000 +100315aa: 1d00 adds r0, r0, #4 +100315ac: 6809 ldr r1, [r1, #0] +100315ae: f845 1b04 str.w r1, [r5], #4 +100315b2: 1f24 subs r4, r4, #4 + +100315b4 : +100315b4: 2c04 cmp r4, #4 +100315b6: d2f6 bcs.n 100315a6 + +100315b8 : +100315b8: b15c cbz r4, 100315d2 +100315ba: f1a0 40d0 sub.w r0, r0, #1744830464 ; 0x68000000 +100315be: 2200 movs r2, #0 +100315c0: 6800 ldr r0, [r0, #0] +100315c2: 9000 str r0, [sp, #0] + +100315c4 : +100315c4: a800 add r0, sp, #0 +100315c6: 5c10 ldrb r0, [r2, r0] +100315c8: f805 0b01 strb.w r0, [r5], #1 +100315cc: 1c52 adds r2, r2, #1 +100315ce: 42a2 cmp r2, r4 +100315d0: d3f8 bcc.n 100315c4 + +100315d2 : +100315d2: e062 b.n 1003169a + +100315d4 : +100315d4: b5f0 push {r4, r5, r6, r7, lr} +100315d6: b083 sub sp, #12 +100315d8: 4604 mov r4, r0 +100315da: 460f mov r7, r1 +100315dc: 4615 mov r5, r2 +100315de: 461e mov r6, r3 +100315e0: f7ff ff5c bl 1003149c +100315e4: f017 0003 ands.w r0, r7, #3 +100315e8: d019 beq.n 1003161e +100315ea: 1a39 subs r1, r7, r0 +100315ec: f1a1 41d0 sub.w r1, r1, #1744830464 ; 0x68000000 +100315f0: 2300 movs r3, #0 +100315f2: 680a ldr r2, [r1, #0] +100315f4: 9200 str r2, [sp, #0] +100315f6: aa00 add r2, sp, #0 +100315f8: 1882 adds r2, r0, r2 +100315fa: f1c0 0004 rsb r0, r0, #4 +100315fe: e000 b.n 10031602 + +10031600 : +10031600: 1c5b adds r3, r3, #1 + +10031602 : +10031602: 4283 cmp r3, r0 +10031604: d205 bcs.n 10031612 +10031606: f816 cb01 ldrb.w ip, [r6], #1 +1003160a: f803 c002 strb.w ip, [r3, r2] +1003160e: 1e6d subs r5, r5, #1 +10031610: d1f6 bne.n 10031600 + +10031612 : +10031612: 9800 ldr r0, [sp, #0] +10031614: 6008 str r0, [r1, #0] +10031616: f7d3 f98b bl 10004930 +1003161a: f000 f842 bl 100316a2 + +1003161e : +1003161e: 1cf8 adds r0, r7, #3 +10031620: 0887 lsrs r7, r0, #2 +10031622: 00bf lsls r7, r7, #2 +10031624: f016 0003 ands.w r0, r6, #3 +10031628: d022 beq.n 10031670 + +1003162a : +1003162a: 2d04 cmp r5, #4 +1003162c: d322 bcc.n 10031674 +1003162e: 7830 ldrb r0, [r6, #0] +10031630: 7871 ldrb r1, [r6, #1] +10031632: ea40 2001 orr.w r0, r0, r1, lsl #8 +10031636: 78b1 ldrb r1, [r6, #2] +10031638: ea40 4001 orr.w r0, r0, r1, lsl #16 +1003163c: 78f1 ldrb r1, [r6, #3] +1003163e: ea40 6001 orr.w r0, r0, r1, lsl #24 +10031642: f1a7 41d0 sub.w r1, r7, #1744830464 ; 0x68000000 +10031646: 9000 str r0, [sp, #0] +10031648: 6008 str r0, [r1, #0] +1003164a: f7d3 f971 bl 10004930 +1003164e: f000 f828 bl 100316a2 + +10031652 : +10031652: 1d36 adds r6, r6, #4 +10031654: 1d3f adds r7, r7, #4 +10031656: 1f2d subs r5, r5, #4 +10031658: e7e7 b.n 1003162a + +1003165a : +1003165a: f856 0b04 ldr.w r0, [r6], #4 +1003165e: f1a7 41d0 sub.w r1, r7, #1744830464 ; 0x68000000 +10031662: 6008 str r0, [r1, #0] +10031664: f7d3 f964 bl 10004930 +10031668: f000 f81b bl 100316a2 + +1003166c : +1003166c: 1d3f adds r7, r7, #4 +1003166e: 1f2d subs r5, r5, #4 + +10031670 : +10031670: 2d04 cmp r5, #4 +10031672: d2f2 bcs.n 1003165a + +10031674 : +10031674: b18d cbz r5, 1003169a +10031676: f1a7 40d0 sub.w r0, r7, #1744830464 ; 0x68000000 +1003167a: 2300 movs r3, #0 +1003167c: 6801 ldr r1, [r0, #0] +1003167e: 9100 str r1, [sp, #0] +10031680: aa00 add r2, sp, #0 + +10031682 : +10031682: f816 1b01 ldrb.w r1, [r6], #1 +10031686: 5499 strb r1, [r3, r2] +10031688: 1c5b adds r3, r3, #1 +1003168a: 42ab cmp r3, r5 +1003168c: d3f9 bcc.n 10031682 +1003168e: 9900 ldr r1, [sp, #0] +10031690: 6001 str r1, [r0, #0] +10031692: f7d3 f94d bl 10004930 +10031696: f000 f804 bl 100316a2 + +1003169a : +1003169a: f7d3 fc4b bl 10004f34 +1003169e: 2001 movs r0, #1 +100316a0: bdfe pop {r1, r2, r3, r4, r5, r6, r7, pc} + +100316a2 : +100316a2: 6820 ldr r0, [r4, #0] +100316a4: 9001 str r0, [sp, #4] +100316a6: f7d3 bb3f b.w 10004d28 + ... + +100316ac : +100316ac: 530d 4950 4920 696e 2074 6146 6c69 2121 .SPI Init Fail!! +100316bc: 2121 2121 000a 0000 !!!!.... + +100316c4 <__iar_Memset4_word>: +100316c4: b500 push {lr} +100316c6: bf00 nop + +100316c8 : +100316c8: 0013 movs r3, r2 +100316ca: 4696 mov lr, r2 +100316cc: 4694 mov ip, r2 +100316ce: 3910 subs r1, #16 +100316d0: bf28 it cs +100316d2: e8a0 500c stmiacs.w r0!, {r2, r3, ip, lr} +100316d6: d8fa bhi.n 100316ce +100316d8: ea5f 7c41 movs.w ip, r1, lsl #29 +100316dc: bf28 it cs +100316de: c00c stmiacs r0!, {r2, r3} +100316e0: bf48 it mi +100316e2: f840 2b04 strmi.w r2, [r0], #4 +100316e6: 07c9 lsls r1, r1, #31 +100316e8: bf28 it cs +100316ea: f820 2b02 strhcs.w r2, [r0], #2 +100316ee: bf48 it mi +100316f0: f800 2b01 strbmi.w r2, [r0], #1 +100316f4: bd00 pop {pc} + ... + +100316f8 : +100316f8: b510 push {r4, lr} +100316fa: 4604 mov r4, r0 +100316fc: 2000 movs r0, #0 +100316fe: b15b cbz r3, 10031718 +10031700: 2a08 cmp r2, #8 +10031702: d209 bcs.n 10031718 +10031704: f504 52e5 add.w r2, r4, #7328 ; 0x1ca0 +10031708: 6812 ldr r2, [r2, #0] +1003170a: 2a01 cmp r2, #1 +1003170c: d004 beq.n 10031718 +1003170e: 461a mov r2, r3 +10031710: 4620 mov r0, r4 +10031712: f002 fe07 bl 10034324 +10031716: 2001 movs r0, #1 +10031718: bd10 pop {r4, pc} + +1003171a : +1003171a: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1003171e: 4680 mov r8, r0 +10031720: 460f mov r7, r1 +10031722: b086 sub sp, #24 +10031724: 4614 mov r4, r2 +10031726: f108 000c add.w r0, r8, #12 +1003172a: f20f 4198 addw r1, pc, #1176 ; 0x498 +1003172e: f100 058c add.w r5, r0, #140 ; 0x8c +10031732: c90c ldmia r1!, {r2, r3} +10031734: a803 add r0, sp, #12 +10031736: f508 66bf add.w r6, r8, #1528 ; 0x5f8 +1003173a: c00c stmia r0!, {r2, r3} +1003173c: 2000 movs r0, #0 +1003173e: 8038 strh r0, [r7, #0] +10031740: 2206 movs r2, #6 +10031742: a903 add r1, sp, #12 +10031744: 1d38 adds r0, r7, #4 +10031746: f7df f862 bl 1001080e +1003174a: f508 51c8 add.w r1, r8, #6400 ; 0x1900 +1003174e: 2206 movs r2, #6 +10031750: 3195 adds r1, #149 ; 0x95 +10031752: f107 000a add.w r0, r7, #10 +10031756: f7df f85a bl 1001080e +1003175a: 4628 mov r0, r5 +1003175c: f7f4 fa45 bl 10025bea +10031760: 4601 mov r1, r0 +10031762: 2206 movs r2, #6 +10031764: f107 0010 add.w r0, r7, #16 +10031768: f7df f851 bl 1001080e +1003176c: f107 0016 add.w r0, r7, #22 +10031770: f000 f8e5 bl 1003193e <.text_7> +10031774: 8838 ldrh r0, [r7, #0] +10031776: 4008 ands r0, r1 +10031778: 8038 strh r0, [r7, #0] +1003177a: f040 0080 orr.w r0, r0, #128 ; 0x80 +1003177e: f827 0b20 strh.w r0, [r7], #32 +10031782: 2020 movs r0, #32 +10031784: 9001 str r0, [sp, #4] +10031786: f105 007c add.w r0, r5, #124 ; 0x7c +1003178a: f7ed f8af bl 1001e8ec +1003178e: f000 f863 bl 10031858 <.text_4> +10031792: 9801 ldr r0, [sp, #4] +10031794: 1c80 adds r0, r0, #2 +10031796: 9001 str r0, [sp, #4] +10031798: 1cbf adds r7, r7, #2 +1003179a: f105 007c add.w r0, r5, #124 ; 0x7c +1003179e: f7ed f899 bl 1001e8d4 +100317a2: f000 f859 bl 10031858 <.text_4> +100317a6: 9901 ldr r1, [sp, #4] +100317a8: 1c89 adds r1, r1, #2 +100317aa: 9101 str r1, [sp, #4] +100317ac: 1cb8 adds r0, r7, #2 +100317ae: 7831 ldrb r1, [r6, #0] +100317b0: f001 0103 and.w r1, r1, #3 +100317b4: 2903 cmp r1, #3 +100317b6: d10a bne.n 100317ce +100317b8: 6faa ldr r2, [r5, #120] ; 0x78 +100317ba: 9901 ldr r1, [sp, #4] +100317bc: 3a0c subs r2, #12 +100317be: 1851 adds r1, r2, r1 +100317c0: 9101 str r1, [sp, #4] +100317c2: 460a mov r2, r1 +100317c4: f105 0188 add.w r1, r5, #136 ; 0x88 +100317c8: f7df f821 bl 1001080e +100317cc: e03a b.n 10031844 +100317ce: a901 add r1, sp, #4 +100317d0: 9100 str r1, [sp, #0] +100317d2: f105 0310 add.w r3, r5, #16 +100317d6: 68ea ldr r2, [r5, #12] +100317d8: 2100 movs r1, #0 +100317da: f7e6 fdd1 bl 10018380 +100317de: 4680 mov r8, r0 +100317e0: f105 0064 add.w r0, r5, #100 ; 0x64 +100317e4: f7e6 fdd4 bl 10018390 +100317e8: 4607 mov r7, r0 +100317ea: a801 add r0, sp, #4 +100317ec: 2f09 cmp r7, #9 +100317ee: 9000 str r0, [sp, #0] +100317f0: bf2c ite cs +100317f2: 2208 movcs r2, #8 +100317f4: 463a movcc r2, r7 +100317f6: f105 0364 add.w r3, r5, #100 ; 0x64 +100317fa: 2101 movs r1, #1 +100317fc: 4640 mov r0, r8 +100317fe: f7e6 fdbf bl 10018380 +10031802: a901 add r1, sp, #4 +10031804: 9100 str r1, [sp, #0] +10031806: f105 034c add.w r3, r5, #76 ; 0x4c +1003180a: 2201 movs r2, #1 +1003180c: 2103 movs r1, #3 +1003180e: f7e6 fdb7 bl 10018380 +10031812: 7831 ldrb r1, [r6, #0] +10031814: f001 0103 and.w r1, r1, #3 +10031818: 2901 cmp r1, #1 +1003181a: d108 bne.n 1003182e +1003181c: 2100 movs r1, #0 +1003181e: 9102 str r1, [sp, #8] +10031820: ab02 add r3, sp, #8 +10031822: a901 add r1, sp, #4 +10031824: 9100 str r1, [sp, #0] +10031826: 2202 movs r2, #2 +10031828: 2106 movs r1, #6 +1003182a: f7e6 fda9 bl 10018380 +1003182e: 2f09 cmp r7, #9 +10031830: d308 bcc.n 10031844 +10031832: a901 add r1, sp, #4 +10031834: 9100 str r1, [sp, #0] +10031836: f105 036c add.w r3, r5, #108 ; 0x6c +1003183a: f1a7 0208 sub.w r2, r7, #8 +1003183e: 2132 movs r1, #50 ; 0x32 +10031840: f7e6 fd9e bl 10018380 +10031844: 9801 ldr r0, [sp, #4] +10031846: 3028 adds r0, #40 ; 0x28 +10031848: f5b0 7f00 cmp.w r0, #512 ; 0x200 +1003184c: bf9c itt ls +1003184e: 9801 ldrls r0, [sp, #4] +10031850: 6020 strls r0, [r4, #0] +10031852: b006 add sp, #24 +10031854: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +10031858 <.text_4>: +10031858: 4601 mov r1, r0 +1003185a: 2202 movs r2, #2 +1003185c: 4638 mov r0, r7 +1003185e: f7de bfd6 b.w 1001080e + +10031862 : +10031862: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +10031866: 460c mov r4, r1 +10031868: 2100 movs r1, #0 +1003186a: 8021 strh r1, [r4, #0] +1003186c: 4615 mov r5, r2 +1003186e: 461e mov r6, r3 +10031870: f100 020c add.w r2, r0, #12 +10031874: 9909 ldr r1, [sp, #36] ; 0x24 +10031876: f102 0370 add.w r3, r2, #112 ; 0x70 +1003187a: b111 cbz r1, 10031882 +1003187c: f44f 5180 mov.w r1, #4096 ; 0x1000 +10031880: 8021 strh r1, [r4, #0] +10031882: f500 57c8 add.w r7, r0, #6400 ; 0x1900 +10031886: 6fd8 ldr r0, [r3, #124] ; 0x7c +10031888: 3795 adds r7, #149 ; 0x95 +1003188a: 2801 cmp r0, #1 +1003188c: f102 088c add.w r8, r2, #140 ; 0x8c +10031890: d002 beq.n 10031898 +10031892: 2804 cmp r0, #4 +10031894: d00e beq.n 100318b4 +10031896: e01f b.n 100318d8 +10031898: 8820 ldrh r0, [r4, #0] +1003189a: f440 7080 orr.w r0, r0, #256 ; 0x100 +1003189e: 8020 strh r0, [r4, #0] +100318a0: 4640 mov r0, r8 +100318a2: f7f4 f9a2 bl 10025bea +100318a6: f000 f946 bl 10031b36 <.text_20> +100318aa: f000 f84f bl 1003194c <.text_8> +100318ae: 2206 movs r2, #6 +100318b0: 4631 mov r1, r6 +100318b2: e01a b.n 100318ea +100318b4: 8820 ldrh r0, [r4, #0] +100318b6: f440 7000 orr.w r0, r0, #512 ; 0x200 +100318ba: 8020 strh r0, [r4, #0] +100318bc: f000 f83a bl 10031934 <.text_6> +100318c0: 4640 mov r0, r8 +100318c2: f7f4 f992 bl 10025bea +100318c6: 4601 mov r1, r0 +100318c8: 2206 movs r2, #6 +100318ca: f104 000a add.w r0, r4, #10 +100318ce: f7de ff9e bl 1001080e +100318d2: 2206 movs r2, #6 +100318d4: 4639 mov r1, r7 +100318d6: e008 b.n 100318ea +100318d8: f000 f82c bl 10031934 <.text_6> +100318dc: f000 f836 bl 1003194c <.text_8> +100318e0: 4640 mov r0, r8 +100318e2: f7f4 f982 bl 10025bea +100318e6: 2206 movs r2, #6 +100318e8: 4601 mov r1, r0 +100318ea: f104 0010 add.w r0, r4, #16 +100318ee: f7de ff8e bl 1001080e +100318f2: f104 0016 add.w r0, r4, #22 +100318f6: f000 f822 bl 1003193e <.text_7> +100318fa: 8820 ldrh r0, [r4, #0] +100318fc: 4001 ands r1, r0 +100318fe: 9806 ldr r0, [sp, #24] +10031900: 8021 strh r1, [r4, #0] +10031902: 2801 cmp r0, #1 +10031904: d10f bne.n 10031926 +10031906: f041 00c8 orr.w r0, r1, #200 ; 0xc8 +1003190a: 8020 strh r0, [r4, #0] +1003190c: 9807 ldr r0, [sp, #28] +1003190e: 8b21 ldrh r1, [r4, #24] +10031910: f000 020f and.w r2, r0, #15 +10031914: 9808 ldr r0, [sp, #32] +10031916: f000 0001 and.w r0, r0, #1 +1003191a: ea42 1000 orr.w r0, r2, r0, lsl #4 +1003191e: 4308 orrs r0, r1 +10031920: 8320 strh r0, [r4, #24] +10031922: 201a movs r0, #26 +10031924: e003 b.n 1003192e +10031926: f041 0048 orr.w r0, r1, #72 ; 0x48 +1003192a: 8020 strh r0, [r4, #0] +1003192c: 2018 movs r0, #24 +1003192e: 6028 str r0, [r5, #0] +10031930: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +10031934 <.text_6>: +10031934: 2206 movs r2, #6 +10031936: 4631 mov r1, r6 +10031938: 1d20 adds r0, r4, #4 +1003193a: f7de bf68 b.w 1001080e + +1003193e <.text_7>: +1003193e: 7801 ldrb r1, [r0, #0] +10031940: f001 010f and.w r1, r1, #15 +10031944: 8001 strh r1, [r0, #0] +10031946: f64f 7103 movw r1, #65283 ; 0xff03 +1003194a: 4770 bx lr + +1003194c <.text_8>: +1003194c: 2206 movs r2, #6 +1003194e: 4639 mov r1, r7 +10031950: f104 000a add.w r0, r4, #10 +10031954: f7de bf5b b.w 1001080e + +10031958 : +10031958: 4770 bx lr + +1003195a : +1003195a: 460b mov r3, r1 +1003195c: 2201 movs r2, #1 +1003195e: 2100 movs r1, #0 +10031960: e6ca b.n 100316f8 + +10031962 : +10031962: b510 push {r4, lr} +10031964: b082 sub sp, #8 +10031966: ab00 add r3, sp, #0 +10031968: 2400 movs r4, #0 +1003196a: 601c str r4, [r3, #0] +1003196c: f001 0101 and.w r1, r1, #1 +10031970: f88d 1000 strb.w r1, [sp] +10031974: f88d 2001 strb.w r2, [sp, #1] +10031978: f88d 4002 strb.w r4, [sp, #2] +1003197c: 2203 movs r2, #3 +1003197e: 2101 movs r1, #1 +10031980: f7ff feba bl 100316f8 +10031984: bd13 pop {r0, r1, r4, pc} + +10031986 : +10031986: b57c push {r2, r3, r4, r5, r6, lr} +10031988: ac00 add r4, sp, #0 +1003198a: 2500 movs r5, #0 +1003198c: 2600 movs r6, #0 +1003198e: c460 stmia r4!, {r5, r6} +10031990: f88d 1000 strb.w r1, [sp] +10031994: ac00 add r4, sp, #0 +10031996: 2100 movs r1, #0 +10031998: f362 0104 bfi r1, r2, #0, #5 +1003199c: 7061 strb r1, [r4, #1] +1003199e: 9906 ldr r1, [sp, #24] +100319a0: b101 cbz r1, 100319a4 +100319a2: 2180 movs r1, #128 ; 0x80 +100319a4: 7862 ldrb r2, [r4, #1] +100319a6: 4311 orrs r1, r2 +100319a8: 7061 strb r1, [r4, #1] +100319aa: 78a1 ldrb r1, [r4, #2] +100319ac: f363 0101 bfi r1, r3, #0, #2 +100319b0: 70a1 strb r1, [r4, #2] +100319b2: ab00 add r3, sp, #0 +100319b4: 9907 ldr r1, [sp, #28] +100319b6: f88d 1003 strb.w r1, [sp, #3] +100319ba: 0a0a lsrs r2, r1, #8 +100319bc: f88d 2004 strb.w r2, [sp, #4] +100319c0: 0c0a lsrs r2, r1, #16 +100319c2: 0e09 lsrs r1, r1, #24 +100319c4: f88d 2005 strb.w r2, [sp, #5] +100319c8: f88d 1006 strb.w r1, [sp, #6] +100319cc: 2207 movs r2, #7 +100319ce: 2140 movs r1, #64 ; 0x40 +100319d0: f7ff fe92 bl 100316f8 +100319d4: bd73 pop {r0, r1, r4, r5, r6, pc} + +100319d6 : +100319d6: b530 push {r4, r5, lr} +100319d8: b083 sub sp, #12 +100319da: ab00 add r3, sp, #0 +100319dc: 2400 movs r4, #0 +100319de: 2500 movs r5, #0 +100319e0: c330 stmia r3!, {r4, r5} +100319e2: f500 52c8 add.w r2, r0, #6400 ; 0x1900 +100319e6: 320c adds r2, #12 +100319e8: b919 cbnz r1, 100319f2 +100319ea: 210c movs r1, #12 +100319ec: f88d 4000 strb.w r4, [sp] +100319f0: e003 b.n 100319fa +100319f2: 2301 movs r3, #1 +100319f4: 2100 movs r1, #0 +100319f6: f88d 3000 strb.w r3, [sp] +100319fa: ab00 add r3, sp, #0 +100319fc: 7a52 ldrb r2, [r2, #9] +100319fe: 0112 lsls r2, r2, #4 +10031a00: 705a strb r2, [r3, #1] +10031a02: 2201 movs r2, #1 +10031a04: f88d 2002 strb.w r2, [sp, #2] +10031a08: f641 02c6 movw r2, #6342 ; 0x18c6 +10031a0c: 5c12 ldrb r2, [r2, r0] +10031a0e: 7119 strb r1, [r3, #4] +10031a10: f88d 2003 strb.w r2, [sp, #3] +10031a14: 2140 movs r1, #64 ; 0x40 +10031a16: f88d 1005 strb.w r1, [sp, #5] +10031a1a: 2207 movs r2, #7 +10031a1c: 2120 movs r1, #32 +10031a1e: f7ff fe6b bl 100316f8 +10031a22: bd37 pop {r0, r1, r2, r4, r5, pc} + +10031a24 : +10031a24: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} +10031a28: 4681 mov r9, r0 +10031a2a: b08b sub sp, #44 ; 0x2c +10031a2c: f44f 6080 mov.w r0, #1024 ; 0x400 +10031a30: f7de fee7 bl 10010802 +10031a34: 0005 movs r5, r0 +10031a36: d07b beq.n 10031b30 +10031a38: 2210 movs r2, #16 +10031a3a: 2100 movs r1, #0 +10031a3c: a806 add r0, sp, #24 +10031a3e: f7de fefb bl 10010838 +10031a42: 2000 movs r0, #0 +10031a44: 9005 str r0, [sp, #20] +10031a46: 9508 str r5, [sp, #32] +10031a48: aa05 add r2, sp, #20 +10031a4a: f105 0128 add.w r1, r5, #40 ; 0x28 +10031a4e: 4648 mov r0, r9 +10031a50: f7ff fe63 bl 1003171a +10031a54: 9805 ldr r0, [sp, #20] +10031a56: 3028 adds r0, #40 ; 0x28 +10031a58: f010 017f ands.w r1, r0, #127 ; 0x7f +10031a5c: bf18 it ne +10031a5e: 2101 movne r1, #1 +10031a60: eb01 10d0 add.w r0, r1, r0, lsr #7 +10031a64: b2c0 uxtb r0, r0 +10031a66: 2801 cmp r0, #1 +10031a68: bf08 it eq +10031a6a: 2002 moveq r0, #2 +10031a6c: 01c7 lsls r7, r0, #7 +10031a6e: 2002 movs r0, #2 +10031a70: f88d 0019 strb.w r0, [sp, #25] +10031a74: eb07 0805 add.w r8, r7, r5 +10031a78: f108 0428 add.w r4, r8, #40 ; 0x28 +10031a7c: f44f 5080 mov.w r0, #4096 ; 0x1000 +10031a80: 8020 strh r0, [r4, #0] +10031a82: 8020 strh r0, [r4, #0] +10031a84: f109 0698 add.w r6, r9, #152 ; 0x98 +10031a88: f241 00a4 movw r0, #4260 ; 0x10a4 +10031a8c: 8020 strh r0, [r4, #0] +10031a8e: f8b9 06a0 ldrh.w r0, [r9, #1696] ; 0x6a0 +10031a92: f440 4040 orr.w r0, r0, #49152 ; 0xc000 +10031a96: 8060 strh r0, [r4, #2] +10031a98: 4630 mov r0, r6 +10031a9a: f7f4 f8a6 bl 10025bea +10031a9e: f000 f84a bl 10031b36 <.text_20> +10031aa2: f509 51c8 add.w r1, r9, #6400 ; 0x1900 +10031aa6: 2206 movs r2, #6 +10031aa8: 3195 adds r1, #149 ; 0x95 +10031aaa: f104 000a add.w r0, r4, #10 +10031aae: f7de feae bl 1001080e +10031ab2: 2000 movs r0, #0 +10031ab4: 9001 str r0, [sp, #4] +10031ab6: 9000 str r0, [sp, #0] +10031ab8: 2301 movs r3, #1 +10031aba: 2210 movs r2, #16 +10031abc: 4641 mov r1, r8 +10031abe: 4648 mov r0, r9 +10031ac0: f7f6 ff1d bl 100288fe +10031ac4: 2000 movs r0, #0 +10031ac6: 9004 str r0, [sp, #16] +10031ac8: 3780 adds r7, #128 ; 0x80 +10031aca: 2003 movs r0, #3 +10031acc: f88d 001a strb.w r0, [sp, #26] +10031ad0: b2bf uxth r7, r7 +10031ad2: 4630 mov r0, r6 +10031ad4: f7f4 f889 bl 10025bea +10031ad8: 4603 mov r3, r0 +10031ada: 2000 movs r0, #0 +10031adc: 9003 str r0, [sp, #12] +10031ade: 9002 str r0, [sp, #8] +10031ae0: 9001 str r0, [sp, #4] +10031ae2: 9000 str r0, [sp, #0] +10031ae4: 197e adds r6, r7, r5 +10031ae6: aa04 add r2, sp, #16 +10031ae8: f106 0128 add.w r1, r6, #40 ; 0x28 +10031aec: 4648 mov r0, r9 +10031aee: f7ff feb8 bl 10031862 +10031af2: 2000 movs r0, #0 +10031af4: 9001 str r0, [sp, #4] +10031af6: 9000 str r0, [sp, #0] +10031af8: 2300 movs r3, #0 +10031afa: 9a04 ldr r2, [sp, #16] +10031afc: 4631 mov r1, r6 +10031afe: 4648 mov r0, r9 +10031b00: f7f6 fefd bl 100288fe +10031b04: 9804 ldr r0, [sp, #16] +10031b06: 3028 adds r0, #40 ; 0x28 +10031b08: f010 017f ands.w r1, r0, #127 ; 0x7f +10031b0c: bf18 it ne +10031b0e: 2101 movne r1, #1 +10031b10: eb01 10d0 add.w r0, r1, r0, lsr #7 +10031b14: b2c0 uxtb r0, r0 +10031b16: eb07 10c0 add.w r0, r7, r0, lsl #7 +10031b1a: b280 uxth r0, r0 +10031b1c: 9009 str r0, [sp, #36] ; 0x24 +10031b1e: a906 add r1, sp, #24 +10031b20: 4648 mov r0, r9 +10031b22: f7ff ff1a bl 1003195a +10031b26: f44f 6180 mov.w r1, #1024 ; 0x400 +10031b2a: 4628 mov r0, r5 +10031b2c: f7de fe6e bl 1001080c +10031b30: b00b add sp, #44 ; 0x2c +10031b32: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + +10031b36 <.text_20>: +10031b36: 4601 mov r1, r0 +10031b38: 2206 movs r2, #6 +10031b3a: 1d20 adds r0, r4, #4 +10031b3c: f7de be67 b.w 1001080e + +10031b40 : +10031b40: b510 push {r4, lr} +10031b42: 2901 cmp r1, #1 +10031b44: 4604 mov r4, r0 +10031b46: d10d bne.n 10031b64 +10031b48: f8b4 06a0 ldrh.w r0, [r4, #1696] ; 0x6a0 +10031b4c: f440 4240 orr.w r2, r0, #49152 ; 0xc000 +10031b50: f44f 61d5 mov.w r1, #1704 ; 0x6a8 +10031b54: 4620 mov r0, r4 +10031b56: f7f3 f883 bl 10024c60 +10031b5a: 4620 mov r0, r4 +10031b5c: e8bd 4010 ldmia.w sp!, {r4, lr} +10031b60: 2100 movs r1, #0 +10031b62: e75f b.n 10031a24 +10031b64: bd10 pop {r4, pc} + +10031b66 : +10031b66: 2901 cmp r1, #1 +10031b68: bf08 it eq +10031b6a: f7ff bfe9 beq.w 10031b40 +10031b6e: 4770 bx lr + +10031b70 : +10031b70: e92d 41fc stmdb sp!, {r2, r3, r4, r5, r6, r7, r8, lr} +10031b74: 4604 mov r4, r0 +10031b76: 7816 ldrb r6, [r2, #0] +10031b78: 460d mov r5, r1 +10031b7a: f641 30a4 movw r0, #7076 ; 0x1ba4 +10031b7e: f504 619d add.w r1, r4, #1256 ; 0x4e8 +10031b82: f006 081f and.w r8, r6, #31 +10031b86: f850 c004 ldr.w ip, [r0, r4] +10031b8a: eb01 1248 add.w r2, r1, r8, lsl #5 +10031b8e: 0128 lsls r0, r5, #4 +10031b90: f8d2 221c ldr.w r2, [r2, #540] ; 0x21c +10031b94: 0900 lsrs r0, r0, #4 +10031b96: b19a cbz r2, 10031bc0 +10031b98: 7bcf ldrb r7, [r1, #15] +10031b9a: b133 cbz r3, 10031baa +10031b9c: 4602 mov r2, r0 +10031b9e: f50c 50c8 add.w r0, ip, #6400 ; 0x1900 +10031ba2: 4641 mov r1, r8 +10031ba4: 30a8 adds r0, #168 ; 0xa8 +10031ba6: f000 f947 bl 10031e38 +10031baa: 9001 str r0, [sp, #4] +10031bac: 463b mov r3, r7 +10031bae: 0970 lsrs r0, r6, #5 +10031bb0: f000 0001 and.w r0, r0, #1 +10031bb4: 9000 str r0, [sp, #0] +10031bb6: 0f2a lsrs r2, r5, #28 +10031bb8: 4641 mov r1, r8 +10031bba: 4620 mov r0, r4 +10031bbc: f7ff fee3 bl 10031986 +10031bc0: e8bd 81f3 ldmia.w sp!, {r0, r1, r4, r5, r6, r7, r8, pc} + +10031bc4 : +10031bc4: ffff ffff ffff 0000 ........ + +10031bcc : +10031bcc: 7800 ldrb r0, [r0, #0] +10031bce: 07c0 lsls r0, r0, #31 +10031bd0: d501 bpl.n 10031bd6 +10031bd2: 2001 movs r0, #1 +10031bd4: 4770 bx lr +10031bd6: 2000 movs r0, #0 +10031bd8: 4770 bx lr + +10031bda : +10031bda: 2100 movs r1, #0 +10031bdc: f880 1724 strb.w r1, [r0, #1828] ; 0x724 +10031be0: 4770 bx lr + +10031be2 : +10031be2: 2101 movs r1, #1 +10031be4: f880 1123 strb.w r1, [r0, #291] ; 0x123 +10031be8: 4770 bx lr + +10031bea : +10031bea: f890 1028 ldrb.w r1, [r0, #40] ; 0x28 +10031bee: 06c9 lsls r1, r1, #27 +10031bf0: d505 bpl.n 10031bfe +10031bf2: f890 1025 ldrb.w r1, [r0, #37] ; 0x25 +10031bf6: 2904 cmp r1, #4 +10031bf8: bf08 it eq +10031bfa: f000 b801 beq.w 10031c00 +10031bfe: 4770 bx lr + +10031c00 : +10031c00: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +10031c04: 4604 mov r4, r0 +10031c06: b08d sub sp, #52 ; 0x34 +10031c08: 6825 ldr r5, [r4, #0] +10031c0a: f641 30a4 movw r0, #7076 ; 0x1ba4 +10031c0e: f04f 0900 mov.w r9, #0 +10031c12: 5940 ldr r0, [r0, r5] +10031c14: 9002 str r0, [sp, #8] +10031c16: 27ff movs r7, #255 ; 0xff +10031c18: f500 50c8 add.w r0, r0, #6400 ; 0x1900 +10031c1c: 304c adds r0, #76 ; 0x4c +10031c1e: 9000 str r0, [sp, #0] +10031c20: 46c8 mov r8, r9 +10031c22: f8cd 9004 str.w r9, [sp, #4] +10031c26: a804 add r0, sp, #16 +10031c28: 2120 movs r1, #32 +10031c2a: f7f3 fdf7 bl 1002581c <__aeabi_memclr4> +10031c2e: f894 10b3 ldrb.w r1, [r4, #179] ; 0xb3 +10031c32: 2901 cmp r1, #1 +10031c34: f204 7024 addw r0, r4, #1828 ; 0x724 +10031c38: f040 808d bne.w 10031d56 +10031c3c: 7801 ldrb r1, [r0, #0] +10031c3e: 1e4a subs r2, r1, #1 +10031c40: 4192 sbcs r2, r2 +10031c42: 0fd2 lsrs r2, r2, #31 +10031c44: 9203 str r2, [sp, #12] +10031c46: 2600 movs r6, #0 +10031c48: f894 10b3 ldrb.w r1, [r4, #179] ; 0xb3 +10031c4c: 7001 strb r1, [r0, #0] +10031c4e: f10d 0a10 add.w sl, sp, #16 +10031c52: eb04 0086 add.w r0, r4, r6, lsl #2 +10031c56: f8d0 b144 ldr.w fp, [r0, #324] ; 0x144 +10031c5a: f1bb 0f00 cmp.w fp, #0 +10031c5e: d045 beq.n 10031cec +10031c60: f50b 7084 add.w r0, fp, #264 ; 0x108 +10031c64: f7ff ffb2 bl 10031bcc +10031c68: 2800 cmp r0, #0 +10031c6a: d13f bne.n 10031cec +10031c6c: f8db 0310 ldr.w r0, [fp, #784] ; 0x310 +10031c70: f110 0f01 cmn.w r0, #1 +10031c74: d03a beq.n 10031cec +10031c76: 42b8 cmp r0, r7 +10031c78: bfd8 it le +10031c7a: 4607 movle r7, r0 +10031c7c: 4581 cmp r9, r0 +10031c7e: 6b21 ldr r1, [r4, #48] ; 0x30 +10031c80: bfb8 it lt +10031c82: 4681 movlt r9, r0 +10031c84: 2980 cmp r1, #128 ; 0x80 +10031c86: bf18 it ne +10031c88: 2920 cmpne r1, #32 +10031c8a: d105 bne.n 10031c98 +10031c8c: f89b 2201 ldrb.w r2, [fp, #513] ; 0x201 +10031c90: 0852 lsrs r2, r2, #1 +10031c92: f002 0201 and.w r2, r2, #1 +10031c96: 9201 str r2, [sp, #4] +10031c98: f108 0201 add.w r2, r8, #1 +10031c9c: 2904 cmp r1, #4 +10031c9e: fa5f f888 uxtb.w r8, r8 +10031ca2: d10a bne.n 10031cba +10031ca4: f8db 1100 ldr.w r1, [fp, #256] ; 0x100 +10031ca8: ea41 4000 orr.w r0, r1, r0, lsl #16 +10031cac: f241 1184 movw r1, #4484 ; 0x1184 +10031cb0: 5949 ldr r1, [r1, r5] +10031cb2: 1c49 adds r1, r1, #1 +10031cb4: ea40 2001 orr.w r0, r0, r1, lsl #8 +10031cb8: e015 b.n 10031ce6 +10031cba: 2980 cmp r1, #128 ; 0x80 +10031cbc: bf1c itt ne +10031cbe: 2920 cmpne r1, #32 +10031cc0: 2940 cmpne r1, #64 ; 0x40 +10031cc2: d10c bne.n 10031cde +10031cc4: 9b01 ldr r3, [sp, #4] +10031cc6: 9903 ldr r1, [sp, #12] +10031cc8: 065b lsls r3, r3, #25 +10031cca: ea43 7141 orr.w r1, r3, r1, lsl #29 +10031cce: f89b 3100 ldrb.w r3, [fp, #256] ; 0x100 +10031cd2: f000 007f and.w r0, r0, #127 ; 0x7f +10031cd6: ea43 4000 orr.w r0, r3, r0, lsl #16 +10031cda: 4308 orrs r0, r1 +10031cdc: e003 b.n 10031ce6 +10031cde: f8db 1100 ldr.w r1, [fp, #256] ; 0x100 +10031ce2: ea41 4000 orr.w r0, r1, r0, lsl #16 +10031ce6: f84a 0028 str.w r0, [sl, r8, lsl #2] +10031cea: 4690 mov r8, r2 +10031cec: 1c76 adds r6, r6, #1 +10031cee: 2e0a cmp r6, #10 +10031cf0: dbaf blt.n 10031c52 +10031cf2: 2600 movs r6, #0 +10031cf4: e010 b.n 10031d18 +10031cf6: f85a 1026 ldr.w r1, [sl, r6, lsl #2] +10031cfa: b161 cbz r1, 10031d16 +10031cfc: 6b20 ldr r0, [r4, #48] ; 0x30 +10031cfe: f5b0 5f00 cmp.w r0, #8192 ; 0x2000 +10031d02: d108 bne.n 10031d16 +10031d04: 9802 ldr r0, [sp, #8] +10031d06: 020a lsls r2, r1, #8 +10031d08: f500 50c8 add.w r0, r0, #6400 ; 0x1900 +10031d0c: 0e12 lsrs r2, r2, #24 +10031d0e: b2c9 uxtb r1, r1 +10031d10: 30a8 adds r0, #168 ; 0xa8 +10031d12: f7f0 fa50 bl 100221b6 +10031d16: 1c76 adds r6, r6, #1 +10031d18: fa5f f888 uxtb.w r8, r8 +10031d1c: 4546 cmp r6, r8 +10031d1e: dbea blt.n 10031cf6 +10031d20: 9800 ldr r0, [sp, #0] +10031d22: f8c0 9014 str.w r9, [r0, #20] +10031d26: 2fff cmp r7, #255 ; 0xff +10031d28: 9800 ldr r0, [sp, #0] +10031d2a: bf08 it eq +10031d2c: 2700 moveq r7, #0 +10031d2e: 6107 str r7, [r0, #16] +10031d30: f641 30a4 movw r0, #7076 ; 0x1ba4 +10031d34: f641 225b movw r2, #6747 ; 0x1a5b +10031d38: 5940 ldr r0, [r0, r5] +10031d3a: f500 51c8 add.w r1, r0, #6400 ; 0x1900 +10031d3e: 5c10 ldrb r0, [r2, r0] +10031d40: 314c adds r1, #76 ; 0x4c +10031d42: 2801 cmp r0, #1 +10031d44: d001 beq.n 10031d4a +10031d46: 6908 ldr r0, [r1, #16] +10031d48: b100 cbz r0, 10031d4c +10031d4a: 6908 ldr r0, [r1, #16] +10031d4c: 6188 str r0, [r1, #24] +10031d4e: 9800 ldr r0, [sp, #0] +10031d50: 6980 ldr r0, [r0, #24] +10031d52: f884 00b5 strb.w r0, [r4, #181] ; 0xb5 +10031d56: b00d add sp, #52 ; 0x34 +10031d58: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +10031d5c : +10031d5c: f600 1121 addw r1, r0, #2337 ; 0x921 +10031d60: 2201 movs r2, #1 +10031d62: 700a strb r2, [r1, #0] +10031d64: f880 2920 strb.w r2, [r0, #2336] ; 0x920 +10031d68: 2000 movs r0, #0 +10031d6a: 70c8 strb r0, [r1, #3] +10031d6c: 2023 movs r0, #35 ; 0x23 +10031d6e: 7108 strb r0, [r1, #4] +10031d70: 2000 movs r0, #0 +10031d72: 7188 strb r0, [r1, #6] +10031d74: 2032 movs r0, #50 ; 0x32 +10031d76: 7048 strb r0, [r1, #1] +10031d78: 2014 movs r0, #20 +10031d7a: 7088 strb r0, [r1, #2] +10031d7c: 4770 bx lr + +10031d7e : +10031d7e: f890 1028 ldrb.w r1, [r0, #40] ; 0x28 +10031d82: 0789 lsls r1, r1, #30 +10031d84: d505 bpl.n 10031d92 +10031d86: f890 1025 ldrb.w r1, [r0, #37] ; 0x25 +10031d8a: 2904 cmp r1, #4 +10031d8c: bf08 it eq +10031d8e: f000 b801 beq.w 10031d94 +10031d92: 4770 bx lr + +10031d94 : +10031d94: b5f8 push {r3, r4, r5, r6, r7, lr} +10031d96: 4604 mov r4, r0 +10031d98: f641 419c movw r1, #7324 ; 0x1c9c +10031d9c: 6820 ldr r0, [r4, #0] +10031d9e: 5808 ldr r0, [r1, r0] +10031da0: bb38 cbnz r0, 10031df2 +10031da2: f894 0920 ldrb.w r0, [r4, #2336] ; 0x920 +10031da6: b320 cbz r0, 10031df2 +10031da8: 2500 movs r5, #0 +10031daa: eb04 0085 add.w r0, r4, r5, lsl #2 +10031dae: f8d0 6144 ldr.w r6, [r0, #324] ; 0x144 +10031db2: b1de cbz r6, 10031dec +10031db4: f506 7784 add.w r7, r6, #264 ; 0x108 +10031db8: 4638 mov r0, r7 +10031dba: f7ff ff07 bl 10031bcc +10031dbe: b9a8 cbnz r0, 10031dec +10031dc0: 4638 mov r0, r7 +10031dc2: f7ff ff03 bl 10031bcc +10031dc6: b988 cbnz r0, 10031dec +10031dc8: f8d6 1310 ldr.w r1, [r6, #784] ; 0x310 +10031dcc: f206 3332 addw r3, r6, #818 ; 0x332 +10031dd0: 2200 movs r2, #0 +10031dd2: 4620 mov r0, r4 +10031dd4: f000 f80e bl 10031df4 +10031dd8: 2801 cmp r0, #1 +10031dda: d002 beq.n 10031de2 +10031ddc: f894 0f1c ldrb.w r0, [r4, #3868] ; 0xf1c +10031de0: b120 cbz r0, 10031dec +10031de2: f896 1332 ldrb.w r1, [r6, #818] ; 0x332 +10031de6: 4630 mov r0, r6 +10031de8: f7e5 fb30 bl 1001744c +10031dec: 1c6d adds r5, r5, #1 +10031dee: 2d0a cmp r5, #10 +10031df0: dbdb blt.n 10031daa +10031df2: bdf1 pop {r0, r4, r5, r6, r7, pc} + +10031df4 : +10031df4: b570 push {r4, r5, r6, lr} +10031df6: f600 1021 addw r0, r0, #2337 ; 0x921 +10031dfa: 7844 ldrb r4, [r0, #1] +10031dfc: 781e ldrb r6, [r3, #0] +10031dfe: 7880 ldrb r0, [r0, #2] +10031e00: 1d65 adds r5, r4, #5 +10031e02: 2e02 cmp r6, #2 +10031e04: b2ed uxtb r5, r5 +10031e06: d004 beq.n 10031e12 +10031e08: 2e03 cmp r6, #3 +10031e0a: bf04 itt eq +10031e0c: 462c moveq r4, r5 +10031e0e: 1d40 addeq r0, r0, #5 +10031e10: e000 b.n 10031e14 +10031e12: 462c mov r4, r5 +10031e14: 428c cmp r4, r1 +10031e16: bfb8 it lt +10031e18: 2001 movlt r0, #1 +10031e1a: db04 blt.n 10031e26 +10031e1c: b2c0 uxtb r0, r0 +10031e1e: 4288 cmp r0, r1 +10031e20: bfb4 ite lt +10031e22: 2002 movlt r0, #2 +10031e24: 2003 movge r0, #3 +10031e26: 4286 cmp r6, r0 +10031e28: bf08 it eq +10031e2a: 2a00 cmpeq r2, #0 +10031e2c: d002 beq.n 10031e34 +10031e2e: 7018 strb r0, [r3, #0] +10031e30: 2001 movs r0, #1 +10031e32: bd70 pop {r4, r5, r6, pc} +10031e34: 2000 movs r0, #0 +10031e36: bd70 pop {r4, r5, r6, pc} + +10031e38 : +10031e38: b570 push {r4, r5, r6, lr} +10031e3a: 4604 mov r4, r0 +10031e3c: eb04 0181 add.w r1, r4, r1, lsl #2 +10031e40: 4610 mov r0, r2 +10031e42: f8d1 1144 ldr.w r1, [r1, #324] ; 0x144 +10031e46: 2900 cmp r1, #0 +10031e48: d078 beq.n 10031f3c +10031e4a: f891 117c ldrb.w r1, [r1, #380] ; 0x17c +10031e4e: 4e3c ldr r6, [pc, #240] ; (10031f40 <.text_17>) +10031e50: 2901 cmp r1, #1 +10031e52: f44f 627f mov.w r2, #4080 ; 0xff0 +10031e56: f44f 6570 mov.w r5, #3840 ; 0xf00 +10031e5a: d012 beq.n 10031e82 +10031e5c: 2902 cmp r1, #2 +10031e5e: d012 beq.n 10031e86 +10031e60: 2903 cmp r1, #3 +10031e62: d013 beq.n 10031e8c +10031e64: 2904 cmp r1, #4 +10031e66: d00e beq.n 10031e86 +10031e68: 2909 cmp r1, #9 +10031e6a: bf18 it ne +10031e6c: 290a cmpne r1, #10 +10031e6e: d016 beq.n 10031e9e +10031e70: 290b cmp r1, #11 +10031e72: bf18 it ne +10031e74: 2914 cmpne r1, #20 +10031e76: d012 beq.n 10031e9e +10031e78: 2942 cmp r1, #66 ; 0x42 +10031e7a: d036 beq.n 10031eea +10031e7c: 2944 cmp r1, #68 ; 0x44 +10031e7e: d03d beq.n 10031efc +10031e80: e054 b.n 10031f2c +10031e82: 220f movs r2, #15 +10031e84: e059 b.n 10031f3a +10031e86: 2b01 cmp r3, #1 +10031e88: d157 bne.n 10031f3a +10031e8a: e001 b.n 10031e90 +10031e8c: 2b01 cmp r3, #1 +10031e8e: d101 bne.n 10031e94 +10031e90: 462a mov r2, r5 +10031e92: e052 b.n 10031f3a +10031e94: 2b02 cmp r3, #2 +10031e96: d050 beq.n 10031f3a +10031e98: f640 72f5 movw r2, #4085 ; 0xff5 +10031e9c: e04d b.n 10031f3a +10031e9e: f894 1036 ldrb.w r1, [r4, #54] ; 0x36 +10031ea2: 2901 cmp r1, #1 +10031ea4: bf18 it ne +10031ea6: 2900 cmpne r1, #0 +10031ea8: d110 bne.n 10031ecc +10031eaa: 2b01 cmp r3, #1 +10031eac: bf08 it eq +10031eae: f44f 2270 moveq.w r2, #983040 ; 0xf0000 +10031eb2: d042 beq.n 10031f3a +10031eb4: 2b02 cmp r3, #2 +10031eb6: bf08 it eq +10031eb8: f44f 227f moveq.w r2, #1044480 ; 0xff000 +10031ebc: d03d beq.n 10031f3a +10031ebe: 6f61 ldr r1, [r4, #116] ; 0x74 +10031ec0: 7809 ldrb r1, [r1, #0] +10031ec2: 2901 cmp r1, #1 +10031ec4: bf14 ite ne +10031ec6: 4a1f ldrne r2, [pc, #124] ; (10031f44 <.text_18>) +10031ec8: 4a1f ldreq r2, [pc, #124] ; (10031f48 <.text_19>) +10031eca: e036 b.n 10031f3a +10031ecc: 2b01 cmp r3, #1 +10031ece: bf08 it eq +10031ed0: 4a1e ldreq r2, [pc, #120] ; (10031f4c <.text_20>) +10031ed2: d032 beq.n 10031f3a +10031ed4: 2b02 cmp r3, #2 +10031ed6: bf08 it eq +10031ed8: 4a1d ldreq r2, [pc, #116] ; (10031f50 <.text_21>) +10031eda: d02e beq.n 10031f3a +10031edc: 6f61 ldr r1, [r4, #116] ; 0x74 +10031ede: 7809 ldrb r1, [r1, #0] +10031ee0: 2901 cmp r1, #1 +10031ee2: bf14 ite ne +10031ee4: 4a1b ldrne r2, [pc, #108] ; (10031f54 <.text_22>) +10031ee6: 4a1c ldreq r2, [pc, #112] ; (10031f58 <.text_23>) +10031ee8: e027 b.n 10031f3a +10031eea: 2b01 cmp r3, #1 +10031eec: bf08 it eq +10031eee: 4a1b ldreq r2, [pc, #108] ; (10031f5c <.text_24>) +10031ef0: d023 beq.n 10031f3a +10031ef2: 2b02 cmp r3, #2 +10031ef4: d016 beq.n 10031f24 +10031ef6: f04f 32ff mov.w r2, #4294967295 +10031efa: e01e b.n 10031f3a +10031efc: f894 1036 ldrb.w r1, [r4, #54] ; 0x36 +10031f00: 2903 cmp r1, #3 +10031f02: d109 bne.n 10031f18 +10031f04: 2b01 cmp r3, #1 +10031f06: bf08 it eq +10031f08: f44f 127e moveq.w r2, #4161536 ; 0x3f8000 +10031f0c: d015 beq.n 10031f3a +10031f0e: 2b02 cmp r3, #2 +10031f10: bf14 ite ne +10031f12: 4a13 ldrne r2, [pc, #76] ; (10031f60 <.text_25>) +10031f14: 4a13 ldreq r2, [pc, #76] ; (10031f64 <.text_26>) +10031f16: e010 b.n 10031f3a +10031f18: 2b01 cmp r3, #1 +10031f1a: bf08 it eq +10031f1c: 4a12 ldreq r2, [pc, #72] ; (10031f68 <.text_27>) +10031f1e: d00c beq.n 10031f3a +10031f20: 2b02 cmp r3, #2 +10031f22: d101 bne.n 10031f28 +10031f24: 4632 mov r2, r6 +10031f26: e008 b.n 10031f3a +10031f28: 4a10 ldr r2, [pc, #64] ; (10031f6c <.text_28>) +10031f2a: e006 b.n 10031f3a +10031f2c: f894 1036 ldrb.w r1, [r4, #54] ; 0x36 +10031f30: 2900 cmp r1, #0 +10031f32: bf0c ite eq +10031f34: 4a0e ldreq r2, [pc, #56] ; (10031f70 <.text_29>) +10031f36: f06f 4270 mvnne.w r2, #4026531840 ; 0xf0000000 +10031f3a: 4010 ands r0, r2 +10031f3c: bd70 pop {r4, r5, r6, pc} + ... + +10031f40 <.text_17>: +10031f40: fffff000 .word 0xfffff000 + +10031f44 <.text_18>: +10031f44: 000ff005 .word 0x000ff005 + +10031f48 <.text_19>: +10031f48: 000ff015 .word 0x000ff015 + +10031f4c <.text_20>: +10031f4c: 0f8f0000 .word 0x0f8f0000 + +10031f50 <.text_21>: +10031f50: 0f8ff000 .word 0x0f8ff000 + +10031f54 <.text_22>: +10031f54: 0f8ff005 .word 0x0f8ff005 + +10031f58 <.text_23>: +10031f58: 0f8ff015 .word 0x0f8ff015 + +10031f5c <.text_24>: +10031f5c: fc3f0000 .word 0xfc3f0000 + +10031f60 <.text_25>: +10031f60: 003ff010 .word 0x003ff010 + +10031f64 <.text_26>: +10031f64: 003ff000 .word 0x003ff000 + +10031f68 <.text_27>: +10031f68: fe3f8000 .word 0xfe3f8000 + +10031f6c <.text_28>: +10031f6c: fffff010 .word 0xfffff010 + +10031f70 <.text_29>: +10031f70: 000fffff .word 0x000fffff + +10031f74 : +10031f74: f8df f000 ldr.w pc, [pc] ; 10031f78 +10031f78: 000183cd .word 0x000183cd + +10031f7c : +10031f7c: b538 push {r3, r4, r5, lr} +10031f7e: f200 6454 addw r4, r0, #1620 ; 0x654 +10031f82: 460d mov r5, r1 +10031f84: 7821 ldrb r1, [r4, #0] +10031f86: b9e1 cbnz r1, 10031fc2 +10031f88: 7f21 ldrb r1, [r4, #28] +10031f8a: 42a9 cmp r1, r5 +10031f8c: d019 beq.n 10031fc2 +10031f8e: 78e1 ldrb r1, [r4, #3] +10031f90: b921 cbnz r1, 10031f9c +10031f92: f894 1023 ldrb.w r1, [r4, #35] ; 0x23 +10031f96: 42a9 cmp r1, r5 +10031f98: bf98 it ls +10031f9a: 460d movls r5, r1 +10031f9c: f890 1025 ldrb.w r1, [r0, #37] ; 0x25 +10031fa0: 220c movs r2, #12 +10031fa2: 4211 tst r1, r2 +10031fa4: d00c beq.n 10031fc0 +10031fa6: 6b01 ldr r1, [r0, #48] ; 0x30 +10031fa8: f242 129f movw r2, #8607 ; 0x219f +10031fac: 4211 tst r1, r2 +10031fae: bf14 ite ne +10031fb0: 227f movne r2, #127 ; 0x7f +10031fb2: f04f 32ff moveq.w r2, #4294967295 +10031fb6: 462b mov r3, r5 +10031fb8: f44f 6145 mov.w r1, #3152 ; 0xc50 +10031fbc: f7fe ffc8 bl 10030f50 +10031fc0: 7725 strb r5, [r4, #28] +10031fc2: bd31 pop {r0, r4, r5, pc} + +10031fc4 : +10031fc4: b5f8 push {r3, r4, r5, r6, r7, lr} +10031fc6: f000 f82d bl 10032024 <.text_8> +10031fca: 4605 mov r5, r0 +10031fcc: f894 70b5 ldrb.w r7, [r4, #181] ; 0xb5 +10031fd0: 261e movs r6, #30 +10031fd2: 4620 mov r0, r4 +10031fd4: f000 f8c5 bl 10032162 +10031fd8: 2801 cmp r0, #1 +10031fda: d022 beq.n 10032022 +10031fdc: 69e8 ldr r0, [r5, #28] +10031fde: 1d7f adds r7, r7, #5 +10031fe0: 281f cmp r0, #31 +10031fe2: bf28 it cs +10031fe4: 1d3f addcs r7, r7, #4 +10031fe6: d206 bcs.n 10031ff6 +10031fe8: 2810 cmp r0, #16 +10031fea: bf28 it cs +10031fec: 1cbf addcs r7, r7, #2 +10031fee: d202 bcs.n 10031ff6 +10031ff0: 2804 cmp r0, #4 +10031ff2: bf38 it cc +10031ff4: 1ebf subcc r7, r7, #2 +10031ff6: f894 00b5 ldrb.w r0, [r4, #181] ; 0xb5 +10031ffa: f1a0 010a sub.w r1, r0, #10 +10031ffe: 291f cmp r1, #31 +10032000: bfa8 it ge +10032002: f1a0 060a subge.w r6, r0, #10 +10032006: b2ff uxtb r7, r7 +10032008: 2f3f cmp r7, #63 ; 0x3f +1003200a: bfa8 it ge +1003200c: 273e movge r7, #62 ; 0x3e +1003200e: da03 bge.n 10032018 +10032010: b2f6 uxtb r6, r6 +10032012: 42b7 cmp r7, r6 +10032014: bf38 it cc +10032016: 4637 movcc r7, r6 +10032018: 4639 mov r1, r7 +1003201a: 4620 mov r0, r4 +1003201c: e8bd 40f4 ldmia.w sp!, {r2, r4, r5, r6, r7, lr} +10032020: e7ac b.n 10031f7c +10032022: bdf1 pop {r0, r4, r5, r6, r7, pc} + +10032024 <.text_8>: +10032024: 4604 mov r4, r0 +10032026: 2100 movs r1, #0 +10032028: f7fe b99d b.w 10030366 + +1003202c : +1003202c: b570 push {r4, r5, r6, lr} +1003202e: 460d mov r5, r1 +10032030: 4616 mov r6, r2 +10032032: f200 6454 addw r4, r0, #1620 ; 0x654 +10032036: f7ff fff6 bl 10032026 <.text_8+0x2> +1003203a: 4601 mov r1, r0 +1003203c: f104 0223 add.w r2, r4, #35 ; 0x23 +10032040: 69c9 ldr r1, [r1, #28] +10032042: 7850 ldrb r0, [r2, #1] +10032044: f242 7311 movw r3, #10001 ; 0x2711 +10032048: 4299 cmp r1, r3 +1003204a: d316 bcc.n 1003207a +1003204c: 7a11 ldrb r1, [r2, #8] +1003204e: 2903 cmp r1, #3 +10032050: bf1c itt ne +10032052: 1c49 addne r1, r1, #1 +10032054: 7211 strbne r1, [r2, #8] +10032056: 7a51 ldrb r1, [r2, #9] +10032058: 42b1 cmp r1, r6 +1003205a: d202 bcs.n 10032062 +1003205c: 7256 strb r6, [r2, #9] +1003205e: 2101 movs r1, #1 +10032060: e01d b.n 1003209e +10032062: 7a12 ldrb r2, [r2, #8] +10032064: 2a03 cmp r2, #3 +10032066: db1b blt.n 100320a0 +10032068: f894 0023 ldrb.w r0, [r4, #35] ; 0x23 +1003206c: 1c8a adds r2, r1, #2 +1003206e: 4290 cmp r0, r2 +10032070: bfa8 it ge +10032072: 1c88 addge r0, r1, #2 +10032074: f44f 61e1 mov.w r1, #1800 ; 0x708 +10032078: e002 b.n 10032080 +1003207a: 6b21 ldr r1, [r4, #48] ; 0x30 +1003207c: b111 cbz r1, 10032084 +1003207e: 1e49 subs r1, r1, #1 +10032080: 6321 str r1, [r4, #48] ; 0x30 +10032082: e00d b.n 100320a0 +10032084: 7a11 ldrb r1, [r2, #8] +10032086: 2903 cmp r1, #3 +10032088: da08 bge.n 1003209c +1003208a: 7a51 ldrb r1, [r2, #9] +1003208c: 1e88 subs r0, r1, #2 +1003208e: 42a8 cmp r0, r5 +10032090: bfa7 ittee ge +10032092: 7250 strbge r0, [r2, #9] +10032094: 1c80 addge r0, r0, #2 +10032096: 7255 strblt r5, [r2, #9] +10032098: 4628 movlt r0, r5 +1003209a: e001 b.n 100320a0 +1003209c: 2100 movs r1, #0 +1003209e: 7211 strb r1, [r2, #8] +100320a0: b2c0 uxtb r0, r0 +100320a2: bd70 pop {r4, r5, r6, pc} + +100320a4 : +100320a4: b570 push {r4, r5, r6, lr} +100320a6: f200 6554 addw r5, r0, #1620 ; 0x654 +100320aa: f105 0626 add.w r6, r5, #38 ; 0x26 +100320ae: 460c mov r4, r1 +100320b0: 7871 ldrb r1, [r6, #1] +100320b2: 42a1 cmp r1, r4 +100320b4: d004 beq.n 100320c0 +100320b6: 4622 mov r2, r4 +100320b8: f640 210a movw r1, #2570 ; 0xa0a +100320bc: f7fe ff3e bl 10030f3c +100320c0: 7870 ldrb r0, [r6, #1] +100320c2: f885 0026 strb.w r0, [r5, #38] ; 0x26 +100320c6: 7074 strb r4, [r6, #1] +100320c8: bd70 pop {r4, r5, r6, pc} + +100320ca : +100320ca: b538 push {r3, r4, r5, lr} +100320cc: 4604 mov r4, r0 +100320ce: f204 6554 addw r5, r4, #1620 ; 0x654 +100320d2: 2000 movs r0, #0 +100320d4: 7028 strb r0, [r5, #0] +100320d6: 7068 strb r0, [r5, #1] +100320d8: 70a8 strb r0, [r5, #2] +100320da: f242 119f movw r1, #8607 ; 0x219f +100320de: 6b20 ldr r0, [r4, #48] ; 0x30 +100320e0: 4208 tst r0, r1 +100320e2: bf14 ite ne +100320e4: 227f movne r2, #127 ; 0x7f +100320e6: f04f 32ff moveq.w r2, #4294967295 +100320ea: f44f 6145 mov.w r1, #3152 ; 0xc50 +100320ee: 4620 mov r0, r4 +100320f0: f7fe ff32 bl 10030f58 +100320f4: 7728 strb r0, [r5, #28] +100320f6: 2023 movs r0, #35 ; 0x23 +100320f8: 60a8 str r0, [r5, #8] +100320fa: 2028 movs r0, #40 ; 0x28 +100320fc: 60e8 str r0, [r5, #12] +100320fe: f44f 70c8 mov.w r0, #400 ; 0x190 +10032102: 6128 str r0, [r5, #16] +10032104: f44f 707a mov.w r0, #1000 ; 0x3e8 +10032108: 6168 str r0, [r5, #20] +1003210a: 200a movs r0, #10 +1003210c: f885 0020 strb.w r0, [r5, #32] +10032110: 200c movs r0, #12 +10032112: f885 0021 strb.w r0, [r5, #33] ; 0x21 +10032116: f06f 0003 mvn.w r0, #3 +1003211a: f885 0022 strb.w r0, [r5, #34] ; 0x22 +1003211e: 20ff movs r0, #255 ; 0xff +10032120: f885 0026 strb.w r0, [r5, #38] ; 0x26 +10032124: 2083 movs r0, #131 ; 0x83 +10032126: f885 0027 strb.w r0, [r5, #39] ; 0x27 +1003212a: 201e movs r0, #30 +1003212c: f885 002c strb.w r0, [r5, #44] ; 0x2c +10032130: 2000 movs r0, #0 +10032132: f885 002b strb.w r0, [r5, #43] ; 0x2b +10032136: 6328 str r0, [r5, #48] ; 0x30 +10032138: f885 0036 strb.w r0, [r5, #54] ; 0x36 +1003213c: f885 0037 strb.w r0, [r5, #55] ; 0x37 +10032140: 2001 movs r0, #1 +10032142: f884 0913 strb.w r0, [r4, #2323] ; 0x913 +10032146: 201e movs r0, #30 +10032148: f885 0034 strb.w r0, [r5, #52] ; 0x34 +1003214c: f885 0035 strb.w r0, [r5, #53] ; 0x35 +10032150: 2032 movs r0, #50 ; 0x32 +10032152: 77a8 strb r0, [r5, #30] +10032154: 203e movs r0, #62 ; 0x3e +10032156: f885 0023 strb.w r0, [r5, #35] ; 0x23 +1003215a: 201e movs r0, #30 +1003215c: f885 0024 strb.w r0, [r5, #36] ; 0x24 +10032160: bd31 pop {r0, r4, r5, pc} + +10032162 : +10032162: 6a82 ldr r2, [r0, #40] ; 0x28 +10032164: 0713 lsls r3, r2, #28 +10032166: f200 6154 addw r1, r0, #1620 ; 0x654 +1003216a: d509 bpl.n 10032180 +1003216c: 07d2 lsls r2, r2, #31 +1003216e: d507 bpl.n 10032180 +10032170: f8d0 008c ldr.w r0, [r0, #140] ; 0x8c +10032174: 7800 ldrb r0, [r0, #0] +10032176: b918 cbnz r0, 10032180 +10032178: 7888 ldrb r0, [r1, #2] +1003217a: b110 cbz r0, 10032182 +1003217c: 2000 movs r0, #0 +1003217e: 7088 strb r0, [r1, #2] +10032180: 2001 movs r0, #1 +10032182: 4770 bx lr + +10032184 : +10032184: f890 00b3 ldrb.w r0, [r0, #179] ; 0xb3 +10032188: b140 cbz r0, 1003219c +1003218a: f44f 7000 mov.w r0, #512 ; 0x200 +1003218e: 6008 str r0, [r1, #0] +10032190: f44f 7040 mov.w r0, #768 ; 0x300 +10032194: 6048 str r0, [r1, #4] +10032196: f44f 6080 mov.w r0, #1024 ; 0x400 +1003219a: e007 b.n 100321ac +1003219c: f44f 60fa mov.w r0, #2000 ; 0x7d0 +100321a0: 6008 str r0, [r1, #0] +100321a2: f44f 607a mov.w r0, #4000 ; 0xfa0 +100321a6: 6048 str r0, [r1, #4] +100321a8: f241 3088 movw r0, #5000 ; 0x1388 +100321ac: 6088 str r0, [r1, #8] +100321ae: 4770 bx lr + +100321b0 : +100321b0: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +100321b4: b085 sub sp, #20 +100321b6: 4682 mov sl, r0 +100321b8: f20a 6054 addw r0, sl, #1620 ; 0x654 +100321bc: 9000 str r0, [sp, #0] +100321be: 2100 movs r1, #0 +100321c0: 4650 mov r0, sl +100321c2: f7fe f8d0 bl 10030366 +100321c6: 4683 mov fp, r0 +100321c8: 9800 ldr r0, [sp, #0] +100321ca: 7f06 ldrb r6, [r0, #28] +100321cc: 2000 movs r0, #0 +100321ce: f88d 0004 strb.w r0, [sp, #4] +100321d2: 4650 mov r0, sl +100321d4: f7ff ffc5 bl 10032162 +100321d8: 2801 cmp r0, #1 +100321da: f000 80e3 beq.w 100323a4 +100321de: f50a 7096 add.w r0, sl, #300 ; 0x12c +100321e2: 7840 ldrb r0, [r0, #1] +100321e4: 2801 cmp r0, #1 +100321e6: bf04 itt eq +100321e8: f89a 012c ldrbeq.w r0, [sl, #300] ; 0x12c +100321ec: f88d 0004 strbeq.w r0, [sp, #4] +100321f0: 9800 ldr r0, [sp, #0] +100321f2: f89a 10b3 ldrb.w r1, [sl, #179] ; 0xb3 +100321f6: f100 071c add.w r7, r0, #28 +100321fa: 7eb8 ldrb r0, [r7, #26] +100321fc: b911 cbnz r1, 10032204 +100321fe: f04f 0800 mov.w r8, #0 +10032202: e006 b.n 10032212 +10032204: f1b0 0801 subs.w r8, r0, #1 +10032208: eb68 0808 sbc.w r8, r8, r8 +1003220c: ea4f 78d8 mov.w r8, r8, lsr #31 +10032210: b921 cbnz r1, 1003221c +10032212: 2801 cmp r0, #1 +10032214: bf08 it eq +10032216: f04f 0901 moveq.w r9, #1 +1003221a: d001 beq.n 10032220 +1003221c: f04f 0900 mov.w r9, #0 +10032220: f10a 04b3 add.w r4, sl, #179 ; 0xb3 +10032224: b1b1 cbz r1, 10032254 +10032226: 7ae0 ldrb r0, [r4, #11] +10032228: 78a1 ldrb r1, [r4, #2] +1003222a: 2801 cmp r0, #1 +1003222c: bf0c ite eq +1003222e: 200a moveq r0, #10 +10032230: 200f movne r0, #15 +10032232: 1842 adds r2, r0, r1 +10032234: 2a5b cmp r2, #91 ; 0x5b +10032236: bfa8 it ge +10032238: 205a movge r0, #90 ; 0x5a +1003223a: da03 bge.n 10032244 +1003223c: 2a1e cmp r2, #30 +1003223e: bfb4 ite lt +10032240: 201e movlt r0, #30 +10032242: 1840 addge r0, r0, r1 +10032244: 71f8 strb r0, [r7, #7] +10032246: 78a5 ldrb r5, [r4, #2] +10032248: 2d1e cmp r5, #30 +1003224a: db05 blt.n 10032258 +1003224c: 2d3f cmp r5, #63 ; 0x3f +1003224e: db04 blt.n 1003225a +10032250: 253e movs r5, #62 ; 0x3e +10032252: e002 b.n 1003225a +10032254: 202a movs r0, #42 ; 0x2a +10032256: 71f8 strb r0, [r7, #7] +10032258: 251e movs r5, #30 +1003225a: f89a 00b3 ldrb.w r0, [sl, #179] ; 0xb3 +1003225e: b1e0 cbz r0, 1003229a +10032260: 7960 ldrb r0, [r4, #5] +10032262: b998 cbnz r0, 1003228c +10032264: f8da 0030 ldr.w r0, [sl, #48] ; 0x30 +10032268: f410 7ff8 tst.w r0, #496 ; 0x1f0 +1003226c: d00e beq.n 1003228c +1003226e: f89a 0028 ldrb.w r0, [sl, #40] ; 0x28 +10032272: 0640 lsls r0, r0, #25 +10032274: d50a bpl.n 1003228c +10032276: f89a 004c ldrb.w r0, [sl, #76] ; 0x4c +1003227a: 2801 cmp r0, #1 +1003227c: bf1c itt ne +1003227e: 2804 cmpne r0, #4 +10032280: 2806 cmpne r0, #6 +10032282: d103 bne.n 1003228c +10032284: 69fd ldr r5, [r7, #28] +10032286: 2d3f cmp r5, #63 ; 0x3f +10032288: bf28 it cs +1003228a: 253e movcs r5, #62 ; 0x3e +1003228c: 4632 mov r2, r6 +1003228e: b2e9 uxtb r1, r5 +10032290: 4650 mov r0, sl +10032292: f7ff fecb bl 1003202c +10032296: 7238 strb r0, [r7, #8] +10032298: e004 b.n 100322a4 +1003229a: 723d strb r5, [r7, #8] +1003229c: f1b9 0f00 cmp.w r9, #0 +100322a0: bf18 it ne +100322a2: 743d strbne r5, [r7, #16] +100322a4: f89a 00b3 ldrb.w r0, [sl, #179] ; 0xb3 +100322a8: b150 cbz r0, 100322c0 +100322aa: f1b8 0f00 cmp.w r8, #0 +100322ae: d107 bne.n 100322c0 +100322b0: f89a 04f4 ldrb.w r0, [sl, #1268] ; 0x4f4 +100322b4: 2805 cmp r0, #5 +100322b6: da03 bge.n 100322c0 +100322b8: 7860 ldrb r0, [r4, #1] +100322ba: b108 cbz r0, 100322c0 +100322bc: 201e movs r0, #30 +100322be: 7238 strb r0, [r7, #8] +100322c0: 79f8 ldrb r0, [r7, #7] +100322c2: 7a39 ldrb r1, [r7, #8] +100322c4: 4288 cmp r0, r1 +100322c6: bf88 it hi +100322c8: 4608 movhi r0, r1 +100322ca: 7238 strb r0, [r7, #8] +100322cc: a902 add r1, sp, #8 +100322ce: 4650 mov r0, sl +100322d0: f7ff ff58 bl 10032184 +100322d4: f10d 0c08 add.w ip, sp, #8 +100322d8: f89a e0b3 ldrb.w lr, [sl, #179] ; 0xb3 +100322dc: f8dc 3004 ldr.w r3, [ip, #4] +100322e0: 1eb0 subs r0, r6, #2 +100322e2: 1cb1 adds r1, r6, #2 +100322e4: 1d32 adds r2, r6, #4 +100322e6: f8dc c008 ldr.w ip, [ip, #8] +100322ea: f1be 0f00 cmp.w lr, #0 +100322ee: d026 beq.n 1003233e +100322f0: f1b8 0f00 cmp.w r8, #0 +100322f4: d00a beq.n 1003230c +100322f6: 2000 movs r0, #0 +100322f8: 73f8 strb r0, [r7, #15] +100322fa: 78a0 ldrb r0, [r4, #2] +100322fc: 283e cmp r0, #62 ; 0x3e +100322fe: da01 bge.n 10032304 +10032300: 4286 cmp r6, r0 +10032302: e02d b.n 10032360 +10032304: 2e3e cmp r6, #62 ; 0x3e +10032306: da2d bge.n 10032364 +10032308: 263e movs r6, #62 ; 0x3e +1003230a: e02b b.n 10032364 +1003230c: f8db b01c ldr.w fp, [fp, #28] +10032310: 45dc cmp ip, fp +10032312: bf38 it cc +10032314: 4616 movcc r6, r2 +10032316: d307 bcc.n 10032328 +10032318: 455b cmp r3, fp +1003231a: bf38 it cc +1003231c: 460e movcc r6, r1 +1003231e: d303 bcc.n 10032328 +10032320: 9902 ldr r1, [sp, #8] +10032322: 458b cmp fp, r1 +10032324: bf38 it cc +10032326: 4606 movcc r6, r0 +10032328: f89a 04f4 ldrb.w r0, [sl, #1268] ; 0x4f4 +1003232c: 2805 cmp r0, #5 +1003232e: da19 bge.n 10032364 +10032330: f5bb 7f40 cmp.w fp, #768 ; 0x300 +10032334: d216 bcs.n 10032364 +10032336: 7860 ldrb r0, [r4, #1] +10032338: b1a0 cbz r0, 10032364 +1003233a: 7a3e ldrb r6, [r7, #8] +1003233c: e012 b.n 10032364 +1003233e: f1b9 0f00 cmp.w r9, #0 +10032342: bf18 it ne +10032344: 261e movne r6, #30 +10032346: d10d bne.n 10032364 +10032348: f8db 401c ldr.w r4, [fp, #28] +1003234c: 45a4 cmp ip, r4 +1003234e: bf38 it cc +10032350: 4616 movcc r6, r2 +10032352: d307 bcc.n 10032364 +10032354: 42a3 cmp r3, r4 +10032356: bf38 it cc +10032358: 460e movcc r6, r1 +1003235a: d303 bcc.n 10032364 +1003235c: 9902 ldr r1, [sp, #8] +1003235e: 428c cmp r4, r1 +10032360: bf38 it cc +10032362: 4606 movcc r6, r0 +10032364: 7a38 ldrb r0, [r7, #8] +10032366: b2f6 uxtb r6, r6 +10032368: 4286 cmp r6, r0 +1003236a: bf38 it cc +1003236c: 4606 movcc r6, r0 +1003236e: 4630 mov r0, r6 +10032370: 79fe ldrb r6, [r7, #7] +10032372: 4286 cmp r6, r0 +10032374: bf88 it hi +10032376: 4606 movhi r6, r0 +10032378: f8da 0028 ldr.w r0, [sl, #40] ; 0x28 +1003237c: 0480 lsls r0, r0, #18 +1003237e: d509 bpl.n 10032394 +10032380: f50a 7096 add.w r0, sl, #300 ; 0x12c +10032384: 7840 ldrb r0, [r0, #1] +10032386: 2801 cmp r0, #1 +10032388: d104 bne.n 10032394 +1003238a: f89d 0004 ldrb.w r0, [sp, #4] +1003238e: 42b0 cmp r0, r6 +10032390: bf98 it ls +10032392: 4606 movls r6, r0 +10032394: 4631 mov r1, r6 +10032396: 4650 mov r0, sl +10032398: f7ff fdf0 bl 10031f7c +1003239c: f89a 00b3 ldrb.w r0, [sl, #179] ; 0xb3 +100323a0: 76b8 strb r0, [r7, #26] +100323a2: 763d strb r5, [r7, #24] +100323a4: b005 add sp, #20 +100323a6: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +100323aa : +100323aa: f890 1028 ldrb.w r1, [r0, #40] ; 0x28 +100323ae: 0709 lsls r1, r1, #28 +100323b0: bf48 it mi +100323b2: f7ff bddf bmi.w 10031f74 +100323b6: 4770 bx lr + +100323b8 : +100323b8: b510 push {r4, lr} +100323ba: f7ff fe33 bl 10032024 <.text_8> +100323be: f894 1028 ldrb.w r1, [r4, #40] ; 0x28 +100323c2: f001 0128 and.w r1, r1, #40 ; 0x28 +100323c6: 2928 cmp r1, #40 ; 0x28 +100323c8: bf04 itt eq +100323ca: f894 103e ldrbeq.w r1, [r4, #62] ; 0x3e +100323ce: 2900 cmpeq r1, #0 +100323d0: d118 bne.n 10032404 +100323d2: f894 20b3 ldrb.w r2, [r4, #179] ; 0xb3 +100323d6: f240 31e9 movw r1, #1001 ; 0x3e9 +100323da: b14a cbz r2, 100323f0 +100323dc: f104 02b3 add.w r2, r4, #179 ; 0xb3 +100323e0: 7892 ldrb r2, [r2, #2] +100323e2: 2a1a cmp r2, #26 +100323e4: bfa8 it ge +100323e6: 21cd movge r1, #205 ; 0xcd +100323e8: da08 bge.n 100323fc +100323ea: 3a0b subs r2, #11 +100323ec: 2a0f cmp r2, #15 +100323ee: d302 bcc.n 100323f6 +100323f0: 6980 ldr r0, [r0, #24] +100323f2: 4288 cmp r0, r1 +100323f4: d301 bcc.n 100323fa +100323f6: 2183 movs r1, #131 ; 0x83 +100323f8: e000 b.n 100323fc +100323fa: 2140 movs r1, #64 ; 0x40 +100323fc: 4620 mov r0, r4 +100323fe: e8bd 4010 ldmia.w sp!, {r4, lr} +10032402: e64f b.n 100320a4 +10032404: bd10 pop {r4, pc} + ... + +10032408 : +10032408: f8df f000 ldr.w pc, [pc] ; 1003240c +1003240c: 0001829d .word 0x0001829d + +10032410 : +10032410: f8df f000 ldr.w pc, [pc] ; 10032414 +10032414: 000182bd .word 0x000182bd + +10032418 : +10032418: f890 002c ldrb.w r0, [r0, #44] ; 0x2c +1003241c: 2200 movs r2, #0 +1003241e: 2801 cmp r0, #1 +10032420: bf18 it ne +10032422: 2810 cmpne r0, #16 +10032424: d140 bne.n 100324a8 +10032426: f1a1 003d sub.w r0, r1, #61 ; 0x3d +1003242a: 2828 cmp r0, #40 ; 0x28 +1003242c: d208 bcs.n 10032440 +1003242e: f1a1 003c sub.w r0, r1, #60 ; 0x3c +10032432: 1041 asrs r1, r0, #1 +10032434: eb00 7091 add.w r0, r0, r1, lsr #30 +10032438: 1080 asrs r0, r0, #2 +1003243a: f100 025a add.w r2, r0, #90 ; 0x5a +1003243e: e033 b.n 100324a8 +10032440: f1a1 0029 sub.w r0, r1, #41 ; 0x29 +10032444: 2814 cmp r0, #20 +10032446: d207 bcs.n 10032458 +10032448: f1a1 0028 sub.w r0, r1, #40 ; 0x28 +1003244c: eb00 70d0 add.w r0, r0, r0, lsr #31 +10032450: 1040 asrs r0, r0, #1 +10032452: f100 024e add.w r2, r0, #78 ; 0x4e +10032456: e027 b.n 100324a8 +10032458: f1a1 001f sub.w r0, r1, #31 +1003245c: 280a cmp r0, #10 +1003245e: bf38 it cc +10032460: f101 0224 addcc.w r2, r1, #36 ; 0x24 +10032464: d320 bcc.n 100324a8 +10032466: f1a1 0015 sub.w r0, r1, #21 +1003246a: 280a cmp r0, #10 +1003246c: bf38 it cc +1003246e: f101 0222 addcc.w r2, r1, #34 ; 0x22 +10032472: d319 bcc.n 100324a8 +10032474: 1f48 subs r0, r1, #5 +10032476: 2810 cmp r0, #16 +10032478: d206 bcs.n 10032488 +1003247a: 0040 lsls r0, r0, #1 +1003247c: 2103 movs r1, #3 +1003247e: fb90 f0f1 sdiv r0, r0, r1 +10032482: f100 022a add.w r2, r0, #42 ; 0x2a +10032486: e00f b.n 100324a8 +10032488: 2904 cmp r1, #4 +1003248a: bf08 it eq +1003248c: 2224 moveq r2, #36 ; 0x24 +1003248e: d00b beq.n 100324a8 +10032490: 2903 cmp r1, #3 +10032492: bf08 it eq +10032494: 221b moveq r2, #27 +10032496: d007 beq.n 100324a8 +10032498: 2902 cmp r1, #2 +1003249a: bf08 it eq +1003249c: 2212 moveq r2, #18 +1003249e: d003 beq.n 100324a8 +100324a0: 2901 cmp r1, #1 +100324a2: bf0c ite eq +100324a4: 2209 moveq r2, #9 +100324a6: 460a movne r2, r1 +100324a8: 4610 mov r0, r2 +100324aa: 4770 bx lr + +100324ac : +100324ac: e7b4 b.n 10032418 + +100324ae : +100324ae: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +100324b2: 4698 mov r8, r3 +100324b4: 460e mov r6, r1 +100324b6: 4683 mov fp, r0 +100324b8: f898 1000 ldrb.w r1, [r8] +100324bc: 4617 mov r7, r2 +100324be: 2000 movs r0, #0 +100324c0: 2904 cmp r1, #4 +100324c2: f04f 32ff mov.w r2, #4294967295 +100324c6: bfb4 ite lt +100324c8: 2101 movlt r1, #1 +100324ca: 2100 movge r1, #0 +100324cc: 70b2 strb r2, [r6, #2] +100324ce: 2900 cmp r1, #0 +100324d0: 4681 mov r9, r0 +100324d2: f20b 42e4 addw r2, fp, #1252 ; 0x4e4 +100324d6: d051 beq.n 1003257c +100324d8: 6891 ldr r1, [r2, #8] +100324da: 1c49 adds r1, r1, #1 +100324dc: 6091 str r1, [r2, #8] +100324de: 7979 ldrb r1, [r7, #5] +100324e0: f89b 5022 ldrb.w r5, [fp, #34] ; 0x22 +100324e4: f001 021f and.w r2, r1, #31 +100324e8: 4253 negs r3, r2 +100324ea: 005b lsls r3, r3, #1 +100324ec: 0949 lsrs r1, r1, #5 +100324ee: 2901 cmp r1, #1 +100324f0: d013 beq.n 1003251a +100324f2: 2903 cmp r1, #3 +100324f4: d00e beq.n 10032514 +100324f6: 2905 cmp r1, #5 +100324f8: d009 beq.n 1003250e +100324fa: 2907 cmp r1, #7 +100324fc: d112 bne.n 10032524 +100324fe: 2a1c cmp r2, #28 +10032500: bfb8 it lt +10032502: f1a3 0038 sublt.w r0, r3, #56 ; 0x38 +10032506: db0c blt.n 10032522 +10032508: f06f 0063 mvn.w r0, #99 ; 0x63 +1003250c: e00a b.n 10032524 +1003250e: f1a3 0024 sub.w r0, r3, #36 ; 0x24 +10032512: e006 b.n 10032522 +10032514: f1a3 0018 sub.w r0, r3, #24 +10032518: e003 b.n 10032522 +1003251a: f06f 000b mvn.w r0, #11 +1003251e: eba0 0042 sub.w r0, r0, r2, lsl #1 +10032522: b240 sxtb r0, r0 +10032524: 1d84 adds r4, r0, #6 +10032526: b260 sxtb r0, r4 +10032528: f7ff ff6e bl 10032408 +1003252c: 2d00 cmp r5, #0 +1003252e: 4601 mov r1, r0 +10032530: d10d bne.n 1003254e +10032532: 2850 cmp r0, #80 ; 0x50 +10032534: db02 blt.n 1003253c +10032536: f000 f86d bl 10032614 <.text_12> +1003253a: e004 b.n 10032546 +1003253c: f1a1 0014 sub.w r0, r1, #20 +10032540: 283b cmp r0, #59 ; 0x3b +10032542: bf38 it cc +10032544: 1cc9 addcc r1, r1, #3 +10032546: b2c9 uxtb r1, r1 +10032548: 2965 cmp r1, #101 ; 0x65 +1003254a: bfa8 it ge +1003254c: 2164 movge r1, #100 ; 0x64 +1003254e: 7031 strb r1, [r6, #0] +10032550: 7331 strb r1, [r6, #12] +10032552: 72f4 strb r4, [r6, #11] +10032554: 7830 ldrb r0, [r6, #0] +10032556: 2829 cmp r0, #41 ; 0x29 +10032558: db02 blt.n 10032560 +1003255a: f89b 0044 ldrb.w r0, [fp, #68] ; 0x44 +1003255e: b130 cbz r0, 1003256e +10032560: 7938 ldrb r0, [r7, #4] +10032562: 2841 cmp r0, #65 ; 0x41 +10032564: bfa8 it ge +10032566: 2000 movge r0, #0 +10032568: da05 bge.n 10032576 +1003256a: 2814 cmp r0, #20 +1003256c: da01 bge.n 10032572 +1003256e: 2064 movs r0, #100 ; 0x64 +10032570: e001 b.n 10032576 +10032572: f000 f856 bl 10032622 <.text_13> +10032576: 7070 strb r0, [r6, #1] +10032578: 70b0 strb r0, [r6, #2] +1003257a: e045 b.n 10032608 +1003257c: 68d0 ldr r0, [r2, #12] +1003257e: 1c40 adds r0, r0, #1 +10032580: 60d0 str r0, [r2, #12] +10032582: f89b 0023 ldrb.w r0, [fp, #35] ; 0x23 +10032586: 07c0 lsls r0, r0, #31 +10032588: 7838 ldrb r0, [r7, #0] +1003258a: bf48 it mi +1003258c: f04f 0901 movmi.w r9, #1 +10032590: f000 003f and.w r0, r0, #63 ; 0x3f +10032594: 0040 lsls r0, r0, #1 +10032596: 386e subs r0, #110 ; 0x6e +10032598: 73b0 strb r0, [r6, #14] +1003259a: f996 000e ldrsb.w r0, [r6, #14] +1003259e: f7ff ff33 bl 10032408 +100325a2: 7130 strb r0, [r6, #4] +100325a4: 4682 mov sl, r0 +100325a6: 7bf8 ldrb r0, [r7, #15] +100325a8: 0840 lsrs r0, r0, #1 +100325aa: f88b 04e4 strb.w r0, [fp, #1252] ; 0x4e4 +100325ae: 73f0 strb r0, [r6, #15] +100325b0: 7938 ldrb r0, [r7, #4] +100325b2: 0840 lsrs r0, r0, #1 +100325b4: f1a0 046e sub.w r4, r0, #110 ; 0x6e +100325b8: b260 sxtb r0, r4 +100325ba: f7ff ff25 bl 10032408 +100325be: 7030 strb r0, [r6, #0] +100325c0: 7330 strb r0, [r6, #12] +100325c2: 72b4 strb r4, [r6, #10] +100325c4: 72f4 strb r4, [r6, #11] +100325c6: f898 0000 ldrb.w r0, [r8] +100325ca: 3814 subs r0, #20 +100325cc: 2808 cmp r0, #8 +100325ce: bf34 ite cc +100325d0: 2402 movcc r4, #2 +100325d2: 2401 movcs r4, #1 +100325d4: 2500 movs r5, #0 +100325d6: e009 b.n 100325ec +100325d8: 19e8 adds r0, r5, r7 +100325da: f990 000d ldrsb.w r0, [r0, #13] +100325de: f7ff ff17 bl 10032410 +100325e2: b905 cbnz r5, 100325e6 +100325e4: 7070 strb r0, [r6, #1] +100325e6: 19a9 adds r1, r5, r6 +100325e8: 1c6d adds r5, r5, #1 +100325ea: 7088 strb r0, [r1, #2] +100325ec: 42a5 cmp r5, r4 +100325ee: dbf3 blt.n 100325d8 +100325f0: f107 0209 add.w r2, r7, #9 +100325f4: 4641 mov r1, r8 +100325f6: 4658 mov r0, fp +100325f8: f001 fb96 bl 10033d28 +100325fc: f1b9 0f00 cmp.w r9, #0 +10032600: d006 beq.n 10032610 +10032602: fb9a f1f9 sdiv r1, sl, r9 +10032606: b2c9 uxtb r1, r1 +10032608: 4658 mov r0, fp +1003260a: f7ff ff4f bl 100324ac +1003260e: 7370 strb r0, [r6, #13] +10032610: e8bd 8ff1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +10032614 <.text_12>: +10032614: 3850 subs r0, #80 ; 0x50 +10032616: 1040 asrs r0, r0, #1 +10032618: eb00 0041 add.w r0, r0, r1, lsl #1 +1003261c: f1a0 0150 sub.w r1, r0, #80 ; 0x50 +10032620: 4770 bx lr + +10032622 <.text_13>: +10032622: f1c0 0040 rsb r0, r0, #64 ; 0x40 +10032626: 2264 movs r2, #100 ; 0x64 +10032628: 4350 muls r0, r2 +1003262a: 222c movs r2, #44 ; 0x2c +1003262c: fb90 f0f2 sdiv r0, r0, r2 +10032630: 4770 bx lr + +10032632 : +10032632: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +10032636: 7854 ldrb r4, [r2, #1] +10032638: 2300 movs r3, #0 +1003263a: 2cff cmp r4, #255 ; 0xff +1003263c: bf1e ittt ne +1003263e: eb00 0484 addne.w r4, r0, r4, lsl #2 +10032642: f8d4 4144 ldrne.w r4, [r4, #324] ; 0x144 +10032646: 2c00 cmpne r4, #0 +10032648: bf1c itt ne +1003264a: 7895 ldrbne r5, [r2, #2] +1003264c: 2d00 cmpne r5, #0 +1003264e: 469a mov sl, r3 +10032650: d064 beq.n 1003271c +10032652: f000 f881 bl 10032758 <.text_24> +10032656: bfb8 it lt +10032658: 2301 movlt r3, #1 +1003265a: f504 7544 add.w r5, r4, #784 ; 0x310 +1003265e: f1bc 0f00 cmp.w ip, #0 +10032662: 686e ldr r6, [r5, #4] +10032664: 68af ldr r7, [r5, #8] +10032666: bf04 itt eq +10032668: 7912 ldrbeq r2, [r2, #4] +1003266a: 2a00 cmpeq r2, #0 +1003266c: d056 beq.n 1003271c +1003266e: 2213 movs r2, #19 +10032670: b993 cbnz r3, 10032698 +10032672: 790b ldrb r3, [r1, #4] +10032674: f880 30bf strb.w r3, [r0, #191] ; 0xbf +10032678: 2f01 cmp r7, #1 +1003267a: 7808 ldrb r0, [r1, #0] +1003267c: bfb8 it lt +1003267e: 4607 movlt r7, r0 +10032680: db07 blt.n 10032692 +10032682: fb02 3107 mla r1, r2, r7, r3 +10032686: f000 f857 bl 10032738 <.text_21> +1003268a: 4287 cmp r7, r0 +1003268c: bf34 ite cc +1003268e: 1c4f addcc r7, r1, #1 +10032690: 460f movcs r7, r1 +10032692: f000 f86f bl 10032774 <.text_25> +10032696: e011 b.n 100326bc +10032698: 780b ldrb r3, [r1, #0] +1003269a: f880 30bf strb.w r3, [r0, #191] ; 0xbf +1003269e: 2e01 cmp r6, #1 +100326a0: 7808 ldrb r0, [r1, #0] +100326a2: 4601 mov r1, r0 +100326a4: db07 blt.n 100326b6 +100326a6: fb02 1106 mla r1, r2, r6, r1 +100326aa: f000 f845 bl 10032738 <.text_21> +100326ae: 4286 cmp r6, r0 +100326b0: bf38 it cc +100326b2: 1c4e addcc r6, r1, #1 +100326b4: d300 bcc.n 100326b8 +100326b6: 460e mov r6, r1 +100326b8: f000 f847 bl 1003274a <.text_23> +100326bc: f000 f836 bl 1003272c <.text_20> +100326c0: bfac ite ge +100326c2: 2040 movge r0, #64 ; 0x40 +100326c4: 1c40 addlt r0, r0, #1 +100326c6: 7628 strb r0, [r5, #24] +100326c8: f895 9018 ldrb.w r9, [r5, #24] +100326cc: e003 b.n 100326d6 +100326ce: f000 f837 bl 10032740 <.text_22> +100326d2: f000 f825 bl 10032720 <.text_19> +100326d6: fa5f f888 uxtb.w r8, r8 +100326da: 45c8 cmp r8, r9 +100326dc: d3f7 bcc.n 100326ce +100326de: f1b9 0f40 cmp.w r9, #64 ; 0x40 +100326e2: d10b bne.n 100326fc +100326e4: ea4f 100a mov.w r0, sl, lsl #4 +100326e8: 2841 cmp r0, #65 ; 0x41 +100326ea: bf28 it cs +100326ec: 2040 movcs r0, #64 ; 0x40 +100326ee: f1c0 0140 rsb r1, r0, #64 ; 0x40 +100326f2: 4371 muls r1, r6 +100326f4: fb07 1000 mla r0, r7, r0, r1 +100326f8: 0980 lsrs r0, r0, #6 +100326fa: e00b b.n 10032714 +100326fc: f1b9 0f00 cmp.w r9, #0 +10032700: d007 beq.n 10032712 +10032702: eba9 000a sub.w r0, r9, sl +10032706: 4370 muls r0, r6 +10032708: fb07 000a mla r0, r7, sl, r0 +1003270c: fbb0 f0f9 udiv r0, r0, r9 +10032710: e000 b.n 10032714 +10032712: 2000 movs r0, #0 +10032714: 606e str r6, [r5, #4] +10032716: 60af str r7, [r5, #8] +10032718: f8c4 0310 str.w r0, [r4, #784] ; 0x310 +1003271c: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + +10032720 <.text_19>: +10032720: f000 0001 and.w r0, r0, #1 +10032724: 4482 add sl, r0 +10032726: f108 0801 add.w r8, r8, #1 +1003272a: 4770 bx lr + +1003272c <.text_20>: +1003272c: e9c5 0104 strd r0, r1, [r5, #16] +10032730: 46d0 mov r8, sl +10032732: 7e28 ldrb r0, [r5, #24] +10032734: 2840 cmp r0, #64 ; 0x40 +10032736: 4770 bx lr + +10032738 <.text_21>: +10032738: 2214 movs r2, #20 +1003273a: fb91 f1f2 sdiv r1, r1, r2 +1003273e: 4770 bx lr + +10032740 <.text_22>: +10032740: e9d5 0104 ldrd r0, r1, [r5, #16] +10032744: 4642 mov r2, r8 +10032746: f001 be0d b.w 10034364 <__aeabi_llsr> + +1003274a <.text_23>: +1003274a: e9d5 0104 ldrd r0, r1, [r5, #16] +1003274e: 0049 lsls r1, r1, #1 +10032750: ea41 71d0 orr.w r1, r1, r0, lsr #31 +10032754: 0040 lsls r0, r0, #1 +10032756: 4770 bx lr + +10032758 <.text_24>: +10032758: 7915 ldrb r5, [r2, #4] +1003275a: b125 cbz r5, 10032766 <.text_24+0xe> +1003275c: f890 54f4 ldrb.w r5, [r0, #1268] ; 0x4f4 +10032760: 1c6d adds r5, r5, #1 +10032762: f880 54f4 strb.w r5, [r0, #1268] ; 0x4f4 +10032766: 7815 ldrb r5, [r2, #0] +10032768: f880 50e8 strb.w r5, [r0, #232] ; 0xe8 +1003276c: 2d04 cmp r5, #4 +1003276e: f892 c003 ldrb.w ip, [r2, #3] +10032772: 4770 bx lr + +10032774 <.text_25>: +10032774: e9d5 0104 ldrd r0, r1, [r5, #16] +10032778: 0049 lsls r1, r1, #1 +1003277a: ea41 71d0 orr.w r1, r1, r0, lsr #31 +1003277e: 0040 lsls r0, r0, #1 +10032780: f040 0001 orr.w r0, r0, #1 +10032784: 4770 bx lr + +10032786 : +10032786: b5f8 push {r3, r4, r5, r6, r7, lr} +10032788: f000 f80f bl 100327aa <.text_28> +1003278c: f7ff fe8f bl 100324ae +10032790: f894 0838 ldrb.w r0, [r4, #2104] ; 0x838 +10032794: 2801 cmp r0, #1 +10032796: d007 beq.n 100327a8 +10032798: 4633 mov r3, r6 +1003279a: 463a mov r2, r7 +1003279c: 4629 mov r1, r5 +1003279e: 4620 mov r0, r4 +100327a0: b001 add sp, #4 +100327a2: e8bd 40f0 ldmia.w sp!, {r4, r5, r6, r7, lr} +100327a6: e744 b.n 10032632 +100327a8: bdf1 pop {r0, r4, r5, r6, r7, pc} + +100327aa <.text_28>: +100327aa: 4604 mov r4, r0 +100327ac: 460d mov r5, r1 +100327ae: 4616 mov r6, r2 +100327b0: 461f mov r7, r3 +100327b2: 4770 bx lr + +100327b4 : +100327b4: e7e7 b.n 10032786 + +100327b6 : +100327b6: b580 push {r7, lr} +100327b8: 6b02 ldr r2, [r0, #48] ; 0x30 +100327ba: f5b2 5f00 cmp.w r2, #8192 ; 0x2000 +100327be: d107 bne.n 100327d0 +100327c0: b911 cbnz r1, 100327c8 +100327c2: f001 fe43 bl 1003444c +100327c6: e003 b.n 100327d0 +100327c8: 2901 cmp r1, #1 +100327ca: bf08 it eq +100327cc: f001 fec4 bleq 10034558 +100327d0: 2000 movs r0, #0 +100327d2: bd02 pop {r1, pc} + +100327d4 : +100327d4: b580 push {r7, lr} +100327d6: 6b01 ldr r1, [r0, #48] ; 0x30 +100327d8: f5b1 5f00 cmp.w r1, #8192 ; 0x2000 +100327dc: d10e bne.n 100327fc +100327de: f100 0130 add.w r1, r0, #48 ; 0x30 +100327e2: 7a49 ldrb r1, [r1, #9] +100327e4: 2905 cmp r1, #5 +100327e6: d102 bne.n 100327ee +100327e8: f001 fe65 bl 100344b6 +100327ec: e006 b.n 100327fc +100327ee: 2904 cmp r1, #4 +100327f0: d102 bne.n 100327f8 +100327f2: f001 feab bl 1003454c +100327f6: e001 b.n 100327fc +100327f8: f001 fe63 bl 100344c2 +100327fc: 2000 movs r0, #0 +100327fe: bd02 pop {r1, pc} + +10032800 : +10032800: b580 push {r7, lr} +10032802: 6b02 ldr r2, [r0, #48] ; 0x30 +10032804: f5b2 5f00 cmp.w r2, #8192 ; 0x2000 +10032808: d10c bne.n 10032824 +1003280a: b911 cbnz r1, 10032812 +1003280c: f001 ff61 bl 100346d2 +10032810: e008 b.n 10032824 +10032812: 2901 cmp r1, #1 +10032814: d102 bne.n 1003281c +10032816: f001 ff2b bl 10034670 +1003281a: e003 b.n 10032824 +1003281c: 2904 cmp r1, #4 +1003281e: bf08 it eq +10032820: f001 ff90 bleq 10034744 +10032824: 2000 movs r0, #0 +10032826: bd02 pop {r1, pc} + +10032828 : +10032828: b580 push {r7, lr} +1003282a: 6b01 ldr r1, [r0, #48] ; 0x30 +1003282c: f5b1 5f00 cmp.w r1, #8192 ; 0x2000 +10032830: bf08 it eq +10032832: f002 f80f bleq 10034854 +10032836: 2000 movs r0, #0 +10032838: bd02 pop {r1, pc} + ... + +1003283c : +1003283c: b5f8 push {r3, r4, r5, r6, r7, lr} +1003283e: 4604 mov r4, r0 +10032840: f641 30a4 movw r0, #7076 ; 0x1ba4 +10032844: 4d16 ldr r5, [pc, #88] ; (100328a0 <.text_4>) +10032846: 5906 ldr r6, [r0, r4] +10032848: f641 1734 movw r7, #6452 ; 0x1934 +1003284c: b111 cbz r1, 10032854 +1003284e: 2901 cmp r1, #1 +10032850: d010 beq.n 10032874 +10032852: bdf1 pop {r0, r4, r5, r6, r7, pc} +10032854: 59b8 ldr r0, [r7, r6] +10032856: f440 6040 orr.w r0, r0, #3072 ; 0xc00 +1003285a: 51b8 str r0, [r7, r6] +1003285c: 9000 str r0, [sp, #0] +1003285e: 462b mov r3, r5 +10032860: 2218 movs r2, #24 +10032862: f000 f820 bl 100328a6 <.text_5+0x2> +10032866: f000 f827 bl 100328b8 <.text_7> +1003286a: f000 f81f bl 100328ac <.text_6> +1003286e: f040 0040 orr.w r0, r0, #64 ; 0x40 +10032872: e00f b.n 10032894 +10032874: 59b9 ldr r1, [r7, r6] +10032876: 2001 movs r0, #1 +10032878: f360 218b bfi r1, r0, #10, #2 +1003287c: 51b9 str r1, [r7, r6] +1003287e: 9100 str r1, [sp, #0] +10032880: 462b mov r3, r5 +10032882: 2218 movs r2, #24 +10032884: f000 f80e bl 100328a4 <.text_5> +10032888: f000 f816 bl 100328b8 <.text_7> +1003288c: f000 f80e bl 100328ac <.text_6> +10032890: f020 0040 bic.w r0, r0, #64 ; 0x40 +10032894: 9000 str r0, [sp, #0] +10032896: 462b mov r3, r5 +10032898: 2287 movs r2, #135 ; 0x87 +1003289a: f000 f803 bl 100328a4 <.text_5> +1003289e: bdf1 pop {r0, r4, r5, r6, r7, pc} + +100328a0 <.text_4>: +100328a0: 000fffff .word 0x000fffff + +100328a4 <.text_5>: +100328a4: 2100 movs r1, #0 +100328a6: 4620 mov r0, r4 +100328a8: f7f6 bf5e b.w 10029768 + +100328ac <.text_6>: +100328ac: 462b mov r3, r5 +100328ae: 2287 movs r2, #135 ; 0x87 +100328b0: 2100 movs r1, #0 +100328b2: 4620 mov r0, r4 +100328b4: f7f6 bf4c b.w 10029750 + +100328b8 <.text_7>: +100328b8: 59b8 ldr r0, [r7, r6] +100328ba: 9000 str r0, [sp, #0] +100328bc: 462b mov r3, r5 +100328be: 2218 movs r2, #24 +100328c0: 2101 movs r1, #1 +100328c2: 4620 mov r0, r4 +100328c4: f7f6 bf50 b.w 10029768 + +100328c8 : +100328c8: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +100328cc: 4681 mov r9, r0 +100328ce: f641 30a4 movw r0, #7076 ; 0x1ba4 +100328d2: 2500 movs r5, #0 +100328d4: f850 a009 ldr.w sl, [r0, r9] +100328d8: f50a 50c8 add.w r0, sl, #6400 ; 0x1900 +100328dc: 2601 movs r6, #1 +100328de: 2400 movs r4, #0 +100328e0: f100 08a8 add.w r8, r0, #168 ; 0xa8 +100328e4: e001 b.n 100328ea +100328e6: 1c60 adds r0, r4, #1 +100328e8: b2c4 uxtb r4, r0 +100328ea: f89a 004d ldrb.w r0, [sl, #77] ; 0x4d +100328ee: 4284 cmp r4, r0 +100328f0: da60 bge.n 100329b4 +100328f2: 201c movs r0, #28 +100328f4: fb00 a004 mla r0, r0, r4, sl +100328f8: 2c00 cmp r4, #0 +100328fa: f500 50c0 add.w r0, r0, #6144 ; 0x1800 +100328fe: bf18 it ne +10032900: 2c02 cmpne r4, #2 +10032902: f100 07c4 add.w r7, r0, #196 ; 0xc4 +10032906: d003 beq.n 10032910 +10032908: d304 bcc.n 10032914 +1003290a: 2c03 cmp r4, #3 +1003290c: d002 beq.n 10032914 +1003290e: e008 b.n 10032922 +10032910: 2210 movs r2, #16 +10032912: e001 b.n 10032918 +10032914: f44f 1280 mov.w r2, #1048576 ; 0x100000 +10032918: 6839 ldr r1, [r7, #0] +1003291a: 4648 mov r0, r9 +1003291c: f7f6 fea8 bl 10029670 +10032920: 4605 mov r5, r0 +10032922: 68b9 ldr r1, [r7, #8] +10032924: 2301 movs r3, #1 +10032926: f44f 1280 mov.w r2, #1048576 ; 0x100000 +1003292a: f000 f84c bl 100329c6 <.text_10> +1003292e: f000 f847 bl 100329c0 <.text_9> +10032932: 6879 ldr r1, [r7, #4] +10032934: 2301 movs r3, #1 +10032936: 2210 movs r2, #16 +10032938: f000 f845 bl 100329c6 <.text_10> +1003293c: f000 f840 bl 100329c0 <.text_9> +10032940: 6939 ldr r1, [r7, #16] +10032942: 2300 movs r3, #0 +10032944: f44f 6280 mov.w r2, #1024 ; 0x400 +10032948: f000 f83d bl 100329c6 <.text_10> +1003294c: f000 f838 bl 100329c0 <.text_9> +10032950: 6939 ldr r1, [r7, #16] +10032952: 2300 movs r3, #0 +10032954: f44f 6200 mov.w r2, #2048 ; 0x800 +10032958: f000 f835 bl 100329c6 <.text_10> +1003295c: f000 f830 bl 100329c0 <.text_9> +10032960: b114 cbz r4, 10032968 +10032962: 2c01 cmp r4, #1 +10032964: d009 beq.n 1003297a +10032966: e01a b.n 1003299e +10032968: 2200 movs r2, #0 +1003296a: 2100 movs r1, #0 +1003296c: 4640 mov r0, r8 +1003296e: f7ff ff22 bl 100327b6 +10032972: 2801 cmp r0, #1 +10032974: d11b bne.n 100329ae +10032976: 2600 movs r6, #0 +10032978: e019 b.n 100329ae +1003297a: 2201 movs r2, #1 +1003297c: 2100 movs r1, #0 +1003297e: 4640 mov r0, r8 +10032980: f7ff ff19 bl 100327b6 +10032984: 2801 cmp r0, #1 +10032986: bf08 it eq +10032988: 2600 moveq r6, #0 +1003298a: 462b mov r3, r5 +1003298c: f44f 1280 mov.w r2, #1048576 ; 0x100000 +10032990: 6839 ldr r1, [r7, #0] +10032992: f000 f818 bl 100329c6 <.text_10> +10032996: 2e00 cmp r6, #0 +10032998: d1a5 bne.n 100328e6 +1003299a: 2000 movs r0, #0 +1003299c: e00e b.n 100329bc +1003299e: 2c00 cmp r4, #0 +100329a0: bf18 it ne +100329a2: 2c02 cmpne r4, #2 +100329a4: d003 beq.n 100329ae +100329a6: d3f0 bcc.n 1003298a +100329a8: 2c03 cmp r4, #3 +100329aa: d0ee beq.n 1003298a +100329ac: e7f3 b.n 10032996 +100329ae: 462b mov r3, r5 +100329b0: 2210 movs r2, #16 +100329b2: e7ed b.n 10032990 +100329b4: 4640 mov r0, r8 +100329b6: f7ff ff0d bl 100327d4 +100329ba: 4630 mov r0, r6 +100329bc: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + +100329c0 <.text_9>: +100329c0: 2001 movs r0, #1 +100329c2: f7de b829 b.w 10010a18 + +100329c6 <.text_10>: +100329c6: 4648 mov r0, r9 +100329c8: f7e4 bdd8 b.w 1001757c + +100329cc : +100329cc: f641 31a4 movw r1, #7076 ; 0x1ba4 +100329d0: 5809 ldr r1, [r1, r0] +100329d2: f891 204b ldrb.w r2, [r1, #75] ; 0x4b +100329d6: 2a03 cmp r2, #3 +100329d8: bf0c ite eq +100329da: 2201 moveq r2, #1 +100329dc: 2202 movne r2, #2 +100329de: f881 204d strb.w r2, [r1, #77] ; 0x4d +100329e2: e771 b.n 100328c8 + +100329e4 : +100329e4: 6b00 ldr r0, [r0, #48] ; 0x30 +100329e6: f5b0 5f00 cmp.w r0, #8192 ; 0x2000 +100329ea: bf04 itt eq +100329ec: 4608 moveq r0, r1 +100329ee: f7f7 bd99 beq.w 1002a524 +100329f2: 4770 bx lr + +100329f4 : +100329f4: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +100329f8: f641 31a4 movw r1, #7076 ; 0x1ba4 +100329fc: b090 sub sp, #64 ; 0x40 +100329fe: 580c ldr r4, [r1, r0] +10032a00: f504 50c8 add.w r0, r4, #6400 ; 0x1900 +10032a04: f100 09a8 add.w r9, r0, #168 ; 0xa8 +10032a08: f109 0630 add.w r6, r9, #48 ; 0x30 +10032a0c: f04f 0800 mov.w r8, #0 +10032a10: 6ff0 ldr r0, [r6, #124] ; 0x7c +10032a12: 8807 ldrh r7, [r0, #0] +10032a14: 2500 movs r5, #0 +10032a16: a901 add r1, sp, #4 +10032a18: 4648 mov r0, r9 +10032a1a: f7ff ffe3 bl 100329e4 +10032a1e: 6ff1 ldr r1, [r6, #124] ; 0x7c +10032a20: 2002 movs r0, #2 +10032a22: 8008 strh r0, [r1, #0] +10032a24: a80a add r0, sp, #40 ; 0x28 +10032a26: 9000 str r0, [sp, #0] +10032a28: ab0b add r3, sp, #44 ; 0x2c +10032a2a: f8dd c01c ldr.w ip, [sp, #28] +10032a2e: aa0e add r2, sp, #56 ; 0x38 +10032a30: a90f add r1, sp, #60 ; 0x3c +10032a32: 4648 mov r0, r9 +10032a34: 47e0 blx ip +10032a36: 6ff1 ldr r1, [r6, #124] ; 0x7c +10032a38: 200c movs r0, #12 +10032a3a: 8008 strh r0, [r1, #0] +10032a3c: a808 add r0, sp, #32 +10032a3e: 9000 str r0, [sp, #0] +10032a40: ab09 add r3, sp, #36 ; 0x24 +10032a42: f8dd c01c ldr.w ip, [sp, #28] +10032a46: aa0c add r2, sp, #48 ; 0x30 +10032a48: a90d add r1, sp, #52 ; 0x34 +10032a4a: 4648 mov r0, r9 +10032a4c: 47e0 blx ip +10032a4e: 6ff0 ldr r0, [r6, #124] ; 0x7c +10032a50: 8007 strh r7, [r0, #0] +10032a52: f609 164c addw r6, r9, #2380 ; 0x94c +10032a56: f44f 437c mov.w r3, #64512 ; 0xfc00 +10032a5a: 6a30 ldr r0, [r6, #32] +10032a5c: 1c40 adds r0, r0, #1 +10032a5e: 6230 str r0, [r6, #32] +10032a60: 4641 mov r1, r8 +10032a62: 2001 movs r0, #1 +10032a64: 7070 strb r0, [r6, #1] +10032a66: 4648 mov r0, r9 +10032a68: 9a03 ldr r2, [sp, #12] +10032a6a: f7fe fa81 bl 10030f70 +10032a6e: b2c7 uxtb r7, r0 +10032a70: 78f0 ldrb r0, [r6, #3] +10032a72: 2800 cmp r0, #0 +10032a74: bf1e ittt ne +10032a76: f894 005d ldrbne.w r0, [r4, #93] ; 0x5d +10032a7a: 2800 cmpne r0, #0 +10032a7c: 28ff cmpne r0, #255 ; 0xff +10032a7e: f000 81a1 beq.w 10032dc4 +10032a82: 7d70 ldrb r0, [r6, #21] +10032a84: 4448 add r0, r9 +10032a86: f880 7959 strb.w r7, [r0, #2393] ; 0x959 +10032a8a: 7d70 ldrb r0, [r6, #21] +10032a8c: 1c40 adds r0, r0, #1 +10032a8e: 7570 strb r0, [r6, #21] +10032a90: b2c0 uxtb r0, r0 +10032a92: f89d 1007 ldrb.w r1, [sp, #7] +10032a96: 4288 cmp r0, r1 +10032a98: bf08 it eq +10032a9a: f886 8015 strbeq.w r8, [r6, #21] +10032a9e: 2000 movs r0, #0 +10032aa0: e008 b.n 10032ab4 +10032aa2: eb00 0109 add.w r1, r0, r9 +10032aa6: f891 1959 ldrb.w r1, [r1, #2393] ; 0x959 +10032aaa: b111 cbz r1, 10032ab2 +10032aac: 194d adds r5, r1, r5 +10032aae: f108 0801 add.w r8, r8, #1 +10032ab2: 1c40 adds r0, r0, #1 +10032ab4: f89d 1007 ldrb.w r1, [sp, #7] +10032ab8: 4288 cmp r0, r1 +10032aba: dbf2 blt.n 10032aa2 +10032abc: fa5f f088 uxtb.w r0, r8 +10032ac0: b110 cbz r0, 10032ac8 +10032ac2: fbb5 f7f0 udiv r7, r5, r0 +10032ac6: b2ff uxtb r7, r7 +10032ac8: 7a70 ldrb r0, [r6, #9] +10032aca: 7af1 ldrb r1, [r6, #11] +10032acc: 42b8 cmp r0, r7 +10032ace: bfb4 ite lt +10032ad0: 1a38 sublt r0, r7, r0 +10032ad2: 1bc0 subge r0, r0, r7 +10032ad4: b2c5 uxtb r5, r0 +10032ad6: 7ab0 ldrb r0, [r6, #10] +10032ad8: 42b8 cmp r0, r7 +10032ada: bfb4 ite lt +10032adc: 1a38 sublt r0, r7, r0 +10032ade: 1bc0 subge r0, r0, r7 +10032ae0: 42b9 cmp r1, r7 +10032ae2: bfb4 ite lt +10032ae4: eba7 0801 sublt.w r8, r7, r1 +10032ae8: eba1 0807 subge.w r8, r1, r7 +10032aec: f89d 1006 ldrb.w r1, [sp, #6] +10032af0: b2c0 uxtb r0, r0 +10032af2: 4288 cmp r0, r1 +10032af4: d305 bcc.n 10032b02 +10032af6: 72b7 strb r7, [r6, #10] +10032af8: 9906 ldr r1, [sp, #24] +10032afa: 0008 movs r0, r1 +10032afc: bf1c itt ne +10032afe: 4648 movne r0, r9 +10032b00: 4788 blxne r1 +10032b02: 2d00 cmp r5, #0 +10032b04: bf1c itt ne +10032b06: 78f1 ldrbne r1, [r6, #3] +10032b08: 2900 cmpne r1, #0 +10032b0a: f609 1075 addw r0, r9, #2421 ; 0x975 +10032b0e: f000 80b1 beq.w 10032c74 +10032b12: f894 105d ldrb.w r1, [r4, #93] ; 0x5d +10032b16: f990 3008 ldrsb.w r3, [r0, #8] +10032b1a: 7283 strb r3, [r0, #10] +10032b1c: 460a mov r2, r1 +10032b1e: 42ba cmp r2, r7 +10032b20: bfb4 ite lt +10032b22: 1a79 sublt r1, r7, r1 +10032b24: 1bc9 subge r1, r1, r7 +10032b26: b2cd uxtb r5, r1 +10032b28: 2d1e cmp r5, #30 +10032b2a: bfa8 it ge +10032b2c: 251d movge r5, #29 +10032b2e: 42ba cmp r2, r7 +10032b30: f609 710e addw r1, r9, #3854 ; 0xf0e +10032b34: da21 bge.n 10032b7a +10032b36: 9a0d ldr r2, [sp, #52] ; 0x34 +10032b38: 56aa ldrsb r2, [r5, r2] +10032b3a: 7202 strb r2, [r0, #8] +10032b3c: 9a0d ldr r2, [sp, #52] ; 0x34 +10032b3e: 56aa ldrsb r2, [r5, r2] +10032b40: f000 f95c bl 10032dfc <.text_9> +10032b44: 9a0f ldr r2, [sp, #60] ; 0x3c +10032b46: 56aa ldrsb r2, [r5, r2] +10032b48: f889 2975 strb.w r2, [r9, #2421] ; 0x975 +10032b4c: 9a0f ldr r2, [sp, #60] ; 0x3c +10032b4e: 56aa ldrsb r2, [r5, r2] +10032b50: 708a strb r2, [r1, #2] +10032b52: f89d 2008 ldrb.w r2, [sp, #8] +10032b56: 2a02 cmp r2, #2 +10032b58: db39 blt.n 10032bce +10032b5a: 7a42 ldrb r2, [r0, #9] +10032b5c: 72c2 strb r2, [r0, #11] +10032b5e: 9a09 ldr r2, [sp, #36] ; 0x24 +10032b60: 56aa ldrsb r2, [r5, r2] +10032b62: 7242 strb r2, [r0, #9] +10032b64: 9a09 ldr r2, [sp, #36] ; 0x24 +10032b66: 56aa ldrsb r2, [r5, r2] +10032b68: 704a strb r2, [r1, #1] +10032b6a: 7842 ldrb r2, [r0, #1] +10032b6c: 70c2 strb r2, [r0, #3] +10032b6e: 9a0b ldr r2, [sp, #44] ; 0x2c +10032b70: 56aa ldrsb r2, [r5, r2] +10032b72: 7042 strb r2, [r0, #1] +10032b74: 9a0b ldr r2, [sp, #44] ; 0x2c +10032b76: 56aa ldrsb r2, [r5, r2] +10032b78: e028 b.n 10032bcc +10032b7a: 9a0c ldr r2, [sp, #48] ; 0x30 +10032b7c: 56aa ldrsb r2, [r5, r2] +10032b7e: 4252 negs r2, r2 +10032b80: 7202 strb r2, [r0, #8] +10032b82: 9a0c ldr r2, [sp, #48] ; 0x30 +10032b84: 56aa ldrsb r2, [r5, r2] +10032b86: 4252 negs r2, r2 +10032b88: f000 f938 bl 10032dfc <.text_9> +10032b8c: 9a0e ldr r2, [sp, #56] ; 0x38 +10032b8e: 56aa ldrsb r2, [r5, r2] +10032b90: 4252 negs r2, r2 +10032b92: f889 2975 strb.w r2, [r9, #2421] ; 0x975 +10032b96: 9a0e ldr r2, [sp, #56] ; 0x38 +10032b98: 56aa ldrsb r2, [r5, r2] +10032b9a: 4252 negs r2, r2 +10032b9c: 708a strb r2, [r1, #2] +10032b9e: f89d 2008 ldrb.w r2, [sp, #8] +10032ba2: 2a02 cmp r2, #2 +10032ba4: db13 blt.n 10032bce +10032ba6: 7a42 ldrb r2, [r0, #9] +10032ba8: 72c2 strb r2, [r0, #11] +10032baa: 9a08 ldr r2, [sp, #32] +10032bac: 56aa ldrsb r2, [r5, r2] +10032bae: 4252 negs r2, r2 +10032bb0: 7242 strb r2, [r0, #9] +10032bb2: 9a08 ldr r2, [sp, #32] +10032bb4: 56aa ldrsb r2, [r5, r2] +10032bb6: 4252 negs r2, r2 +10032bb8: 704a strb r2, [r1, #1] +10032bba: 7842 ldrb r2, [r0, #1] +10032bbc: 70c2 strb r2, [r0, #3] +10032bbe: 9a0a ldr r2, [sp, #40] ; 0x28 +10032bc0: 56aa ldrsb r2, [r5, r2] +10032bc2: 4252 negs r2, r2 +10032bc4: 7042 strb r2, [r0, #1] +10032bc6: 9a0a ldr r2, [sp, #40] ; 0x28 +10032bc8: 56aa ldrsb r2, [r5, r2] +10032bca: 4252 negs r2, r2 +10032bcc: 70ca strb r2, [r1, #3] +10032bce: 2100 movs r1, #0 +10032bd0: e035 b.n 10032c3e +10032bd2: f502 6c70 add.w ip, r2, #3840 ; 0xf00 +10032bd6: f882 3973 strb.w r3, [r2, #2419] ; 0x973 +10032bda: f89c e003 ldrb.w lr, [ip, #3] +10032bde: f992 a97b ldrsb.w sl, [r2, #2427] ; 0x97b +10032be2: f602 1371 addw r3, r2, #2417 ; 0x971 +10032be6: 44d6 add lr, sl +10032be8: f883 e008 strb.w lr, [r3, #8] +10032bec: f992 a973 ldrsb.w sl, [r2, #2419] ; 0x973 +10032bf0: f89c e009 ldrb.w lr, [ip, #9] +10032bf4: 44d6 add lr, sl +10032bf6: f882 e971 strb.w lr, [r2, #2417] ; 0x971 +10032bfa: f893 e008 ldrb.w lr, [r3, #8] +10032bfe: f882 ef00 strb.w lr, [r2, #3840] ; 0xf00 +10032c02: f892 e971 ldrb.w lr, [r2, #2417] ; 0x971 +10032c06: f88c e006 strb.w lr, [ip, #6] +10032c0a: f89d c005 ldrb.w ip, [sp, #5] +10032c0e: f893 a008 ldrb.w sl, [r3, #8] +10032c12: f1ac 0e01 sub.w lr, ip, #1 +10032c16: 45d6 cmp lr, sl +10032c18: bfbc itt lt +10032c1a: f1ac 0c01 sublt.w ip, ip, #1 +10032c1e: f883 c008 strblt.w ip, [r3, #8] +10032c22: f89d 3004 ldrb.w r3, [sp, #4] +10032c26: f892 c971 ldrb.w ip, [r2, #2417] ; 0x971 +10032c2a: 1e5b subs r3, r3, #1 +10032c2c: 4563 cmp r3, ip +10032c2e: da04 bge.n 10032c3a +10032c30: f89d 3004 ldrb.w r3, [sp, #4] +10032c34: 1e5b subs r3, r3, #1 +10032c36: f882 3971 strb.w r3, [r2, #2417] ; 0x971 +10032c3a: 1c49 adds r1, r1, #1 +10032c3c: b2c9 uxtb r1, r1 +10032c3e: f89d 2008 ldrb.w r2, [sp, #8] +10032c42: 4291 cmp r1, r2 +10032c44: da26 bge.n 10032c94 +10032c46: eb01 0209 add.w r2, r1, r9 +10032c4a: f992 397f ldrsb.w r3, [r2, #2431] ; 0x97f +10032c4e: f992 c97d ldrsb.w ip, [r2, #2429] ; 0x97d +10032c52: 459c cmp ip, r3 +10032c54: bf0c ite eq +10032c56: 2300 moveq r3, #0 +10032c58: ebac 0303 subne.w r3, ip, r3 +10032c5c: f882 397b strb.w r3, [r2, #2427] ; 0x97b +10032c60: f992 c977 ldrsb.w ip, [r2, #2423] ; 0x977 +10032c64: f992 3975 ldrsb.w r3, [r2, #2421] ; 0x975 +10032c68: 4563 cmp r3, ip +10032c6a: bf0c ite eq +10032c6c: 2300 moveq r3, #0 +10032c6e: eba3 030c subne.w r3, r3, ip +10032c72: e7ae b.n 10032bd2 +10032c74: 2100 movs r1, #0 +10032c76: e004 b.n 10032c82 +10032c78: 2300 movs r3, #0 +10032c7a: 1c49 adds r1, r1, #1 +10032c7c: f882 397b strb.w r3, [r2, #2427] ; 0x97b +10032c80: b2c9 uxtb r1, r1 +10032c82: f89d 3008 ldrb.w r3, [sp, #8] +10032c86: 4299 cmp r1, r3 +10032c88: eb01 0209 add.w r2, r1, r9 +10032c8c: dbf4 blt.n 10032c78 +10032c8e: 2100 movs r1, #0 +10032c90: f882 1973 strb.w r1, [r2, #2419] ; 0x973 +10032c94: 2100 movs r1, #0 +10032c96: e000 b.n 10032c9a +10032c98: 1c49 adds r1, r1, #1 +10032c9a: f89d 2008 ldrb.w r2, [sp, #8] +10032c9e: 4291 cmp r1, r2 +10032ca0: dbfa blt.n 10032c98 +10032ca2: f990 1006 ldrsb.w r1, [r0, #6] +10032ca6: 2900 cmp r1, #0 +10032ca8: bf04 itt eq +10032caa: f990 1007 ldrsbeq.w r1, [r0, #7] +10032cae: 2900 cmpeq r1, #0 +10032cb0: d107 bne.n 10032cc2 +10032cb2: f996 1027 ldrsb.w r1, [r6, #39] ; 0x27 +10032cb6: 2900 cmp r1, #0 +10032cb8: bf04 itt eq +10032cba: f996 1028 ldrsbeq.w r1, [r6, #40] ; 0x28 +10032cbe: 2900 cmpeq r1, #0 +10032cc0: d06e beq.n 10032da0 +10032cc2: 2d00 cmp r5, #0 +10032cc4: bf1c itt ne +10032cc6: 78f1 ldrbne r1, [r6, #3] +10032cc8: 2900 cmpne r1, #0 +10032cca: d069 beq.n 10032da0 +10032ccc: 2101 movs r1, #1 +10032cce: 7301 strb r1, [r0, #12] +10032cd0: f894 105d ldrb.w r1, [r4, #93] ; 0x5d +10032cd4: f8d9 0030 ldr.w r0, [r9, #48] ; 0x30 +10032cd8: 42b9 cmp r1, r7 +10032cda: da27 bge.n 10032d2c +10032cdc: 2810 cmp r0, #16 +10032cde: bf18 it ne +10032ce0: 2880 cmpne r0, #128 ; 0x80 +10032ce2: d005 beq.n 10032cf0 +10032ce4: 2840 cmp r0, #64 ; 0x40 +10032ce6: bf1c itt ne +10032ce8: 2820 cmpne r0, #32 +10032cea: f5b0 7f80 cmpne.w r0, #256 ; 0x100 +10032cee: d108 bne.n 10032d02 +10032cf0: 2400 movs r4, #0 +10032cf2: f000 f86a bl 10032dca <.text_5> +10032cf6: d241 bcs.n 10032d7c +10032cf8: f000 f879 bl 10032dee <.text_8> +10032cfc: 1c64 adds r4, r4, #1 +10032cfe: b2e4 uxtb r4, r4 +10032d00: e7f7 b.n 10032cf2 +10032d02: f5b0 5f00 cmp.w r0, #8192 ; 0x2000 +10032d06: d108 bne.n 10032d1a +10032d08: 2400 movs r4, #0 +10032d0a: f000 f85e bl 10032dca <.text_5> +10032d0e: d235 bcs.n 10032d7c +10032d10: f000 f866 bl 10032de0 <.text_7> +10032d14: 1c64 adds r4, r4, #1 +10032d16: b2e4 uxtb r4, r4 +10032d18: e7f7 b.n 10032d0a +10032d1a: 2400 movs r4, #0 +10032d1c: f000 f855 bl 10032dca <.text_5> +10032d20: d22c bcs.n 10032d7c +10032d22: f000 f856 bl 10032dd2 <.text_6> +10032d26: 1c64 adds r4, r4, #1 +10032d28: b2e4 uxtb r4, r4 +10032d2a: e7f7 b.n 10032d1c +10032d2c: 2810 cmp r0, #16 +10032d2e: bf18 it ne +10032d30: 2880 cmpne r0, #128 ; 0x80 +10032d32: d005 beq.n 10032d40 +10032d34: 2840 cmp r0, #64 ; 0x40 +10032d36: bf1c itt ne +10032d38: 2820 cmpne r0, #32 +10032d3a: f5b0 7f80 cmpne.w r0, #256 ; 0x100 +10032d3e: d108 bne.n 10032d52 +10032d40: 2400 movs r4, #0 +10032d42: f000 f842 bl 10032dca <.text_5> +10032d46: d219 bcs.n 10032d7c +10032d48: f000 f851 bl 10032dee <.text_8> +10032d4c: 1c64 adds r4, r4, #1 +10032d4e: b2e4 uxtb r4, r4 +10032d50: e7f7 b.n 10032d42 +10032d52: f5b0 5f00 cmp.w r0, #8192 ; 0x2000 +10032d56: d108 bne.n 10032d6a +10032d58: 2400 movs r4, #0 +10032d5a: f000 f836 bl 10032dca <.text_5> +10032d5e: d20d bcs.n 10032d7c +10032d60: f000 f83e bl 10032de0 <.text_7> +10032d64: 1c64 adds r4, r4, #1 +10032d66: b2e4 uxtb r4, r4 +10032d68: e7f7 b.n 10032d5a +10032d6a: 2400 movs r4, #0 +10032d6c: e003 b.n 10032d76 +10032d6e: f000 f830 bl 10032dd2 <.text_6> +10032d72: 1c64 adds r4, r4, #1 +10032d74: b2e4 uxtb r4, r4 +10032d76: f000 f828 bl 10032dca <.text_5> +10032d7a: d3f8 bcc.n 10032d6e +10032d7c: 2100 movs r1, #0 +10032d7e: e00a b.n 10032d96 +10032d80: eb01 0009 add.w r0, r1, r9 +10032d84: f500 6270 add.w r2, r0, #3840 ; 0xf00 +10032d88: 1c49 adds r1, r1, #1 +10032d8a: 7993 ldrb r3, [r2, #6] +10032d8c: 7253 strb r3, [r2, #9] +10032d8e: b2c9 uxtb r1, r1 +10032d90: f890 0f00 ldrb.w r0, [r0, #3840] ; 0xf00 +10032d94: 70d0 strb r0, [r2, #3] +10032d96: f89d 2008 ldrb.w r2, [sp, #8] +10032d9a: 4291 cmp r1, r2 +10032d9c: d3f0 bcc.n 10032d80 +10032d9e: 7277 strb r7, [r6, #9] +10032da0: f89d 0006 ldrb.w r0, [sp, #6] +10032da4: fa5f f488 uxtb.w r4, r8 +10032da8: 4284 cmp r4, r0 +10032daa: d308 bcc.n 10032dbe +10032dac: f899 0dc8 ldrb.w r0, [r9, #3528] ; 0xdc8 +10032db0: b928 cbnz r0, 10032dbe +10032db2: 4621 mov r1, r4 +10032db4: 9c05 ldr r4, [sp, #20] +10032db6: 2308 movs r3, #8 +10032db8: 463a mov r2, r7 +10032dba: 4648 mov r0, r9 +10032dbc: 47a0 blx r4 +10032dbe: 2000 movs r0, #0 +10032dc0: f889 094c strb.w r0, [r9, #2380] ; 0x94c +10032dc4: b010 add sp, #64 ; 0x40 +10032dc6: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + +10032dca <.text_5>: +10032dca: f89d 1008 ldrb.w r1, [sp, #8] +10032dce: 428c cmp r4, r1 +10032dd0: 4770 bx lr + +10032dd2 <.text_6>: +10032dd2: f8dd c010 ldr.w ip, [sp, #16] +10032dd6: 2300 movs r3, #0 +10032dd8: 4622 mov r2, r4 +10032dda: 2100 movs r1, #0 +10032ddc: 4648 mov r0, r9 + +10032dde <__iar_annotation$$tailcall>: +10032dde: 4760 bx ip + +10032de0 <.text_7>: +10032de0: f8dd c010 ldr.w ip, [sp, #16] +10032de4: 2300 movs r3, #0 +10032de6: 4622 mov r2, r4 +10032de8: 2101 movs r1, #1 +10032dea: 4648 mov r0, r9 + +10032dec <__iar_annotation$$tailcall>: +10032dec: 4760 bx ip + +10032dee <.text_8>: +10032dee: f8dd c010 ldr.w ip, [sp, #16] +10032df2: 2300 movs r3, #0 +10032df4: 4622 mov r2, r4 +10032df6: 2102 movs r1, #2 +10032df8: 4648 mov r0, r9 + +10032dfa <__iar_annotation$$tailcall>: +10032dfa: 4760 bx ip + +10032dfc <.text_9>: +10032dfc: f889 2f0e strb.w r2, [r9, #3854] ; 0xf0e +10032e00: f899 2975 ldrb.w r2, [r9, #2421] ; 0x975 +10032e04: 7082 strb r2, [r0, #2] +10032e06: 4770 bx lr + +10032e08 : +10032e08: b530 push {r4, r5, lr} +10032e0a: 6801 ldr r1, [r0, #0] +10032e0c: 8809 ldrh r1, [r1, #0] +10032e0e: 290b cmp r1, #11 +10032e10: bf18 it ne +10032e12: 290c cmpne r1, #12 +10032e14: d115 bne.n 10032e42 +10032e16: 2100 movs r1, #0 +10032e18: f44f 7280 mov.w r2, #256 ; 0x100 +10032e1c: 2500 movs r5, #0 +10032e1e: 2324 movs r3, #36 ; 0x24 +10032e20: fb03 0301 mla r3, r3, r1, r0 +10032e24: f603 148c addw r4, r3, #2444 ; 0x98c +10032e28: 1c49 adds r1, r1, #1 +10032e2a: 61e2 str r2, [r4, #28] +10032e2c: 6162 str r2, [r4, #20] +10032e2e: 60e2 str r2, [r4, #12] +10032e30: 6062 str r2, [r4, #4] +10032e32: 6225 str r5, [r4, #32] +10032e34: 61a5 str r5, [r4, #24] +10032e36: 6125 str r5, [r4, #16] +10032e38: 60a5 str r5, [r4, #8] +10032e3a: 290e cmp r1, #14 +10032e3c: f883 598c strb.w r5, [r3, #2444] ; 0x98c +10032e40: dbed blt.n 10032e1e +10032e42: bd30 pop {r4, r5, pc} + +10032e44 : +10032e44: b510 push {r4, lr} +10032e46: b090 sub sp, #64 ; 0x40 +10032e48: 4604 mov r4, r0 +10032e4a: a800 add r0, sp, #0 +10032e4c: f20f 0128 addw r1, pc, #40 ; 0x28 +10032e50: 223c movs r2, #60 ; 0x3c +10032e52: f7fb fb2b bl 1002e4ac <__iar_unaligned___aeabi_memcpy4> +10032e56: 2c0f cmp r4, #15 +10032e58: db0b blt.n 10032e72 +10032e5a: 200e movs r0, #14 +10032e5c: a900 add r1, sp, #0 +10032e5e: 5c41 ldrb r1, [r0, r1] +10032e60: 42a1 cmp r1, r4 +10032e62: d102 bne.n 10032e6a +10032e64: 380d subs r0, #13 +10032e66: b2c0 uxtb r0, r0 +10032e68: e004 b.n 10032e74 +10032e6a: 1c40 adds r0, r0, #1 +10032e6c: b2c0 uxtb r0, r0 +10032e6e: 283b cmp r0, #59 ; 0x3b +10032e70: d3f4 bcc.n 10032e5c +10032e72: 2000 movs r0, #0 +10032e74: b010 add sp, #64 ; 0x40 +10032e76: bd10 pop {r4, pc} + +10032e78 : +10032e78: 0201 0403 0605 0807 0a09 0c0b 0e0d 2624 ..............$& +10032e88: 2a28 2e2c 3230 3634 3a38 3e3c 6440 6866 (*,.02468:<>@dfh +10032e98: 6c6a 706e 7472 7876 7c7a 807e 8482 8886 jlnprtvxz|~..... +10032ea8: 8c8a 9795 9b99 9f9d a3a1 00a5 ............ + +10032eb4 : +10032eb4: 6840 ldr r0, [r0, #4] +10032eb6: 4208 tst r0, r1 +10032eb8: d001 beq.n 10032ebe +10032eba: 2001 movs r0, #1 +10032ebc: 4770 bx lr +10032ebe: 2000 movs r0, #0 +10032ec0: 4770 bx lr + +10032ec2 : +10032ec2: 2001 movs r0, #1 +10032ec4: 4770 bx lr + +10032ec6 : +10032ec6: 2000 movs r0, #0 +10032ec8: 6088 str r0, [r1, #8] +10032eca: 60c8 str r0, [r1, #12] +10032ecc: 2001 movs r0, #1 +10032ece: 4770 bx lr + +10032ed0 : +10032ed0: 4770 bx lr + +10032ed2 : +10032ed2: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +10032ed6: b083 sub sp, #12 +10032ed8: 4604 mov r4, r0 +10032eda: 460d mov r5, r1 +10032edc: f604 3024 addw r0, r4, #2852 ; 0xb24 +10032ee0: 9000 str r0, [sp, #0] +10032ee2: f104 080c add.w r8, r4, #12 +10032ee6: 68af ldr r7, [r5, #8] +10032ee8: b367 cbz r7, 10032f44 +10032eea: f105 0608 add.w r6, r5, #8 +10032eee: 6ff0 ldr r0, [r6, #124] ; 0x7c +10032ef0: 6138 str r0, [r7, #16] +10032ef2: 4638 mov r0, r7 +10032ef4: 6f71 ldr r1, [r6, #116] ; 0x74 +10032ef6: f7de fa92 bl 1001141e +10032efa: 6f70 ldr r0, [r6, #116] ; 0x74 +10032efc: 6238 str r0, [r7, #32] +10032efe: f641 5624 movw r6, #7460 ; 0x1d24 +10032f02: 2110 movs r1, #16 +10032f04: f000 f8c9 bl 1003309a <.text_10+0x2> +10032f08: 2801 cmp r0, #1 +10032f0a: d143 bne.n 10032f94 +10032f0c: f504 5088 add.w r0, r4, #4352 ; 0x1100 +10032f10: 3028 adds r0, #40 ; 0x28 +10032f12: 9001 str r0, [sp, #4] +10032f14: f105 0a1c add.w sl, r5, #28 +10032f18: f504 51c8 add.w r1, r4, #6400 ; 0x1900 +10032f1c: f89a 001a ldrb.w r0, [sl, #26] +10032f20: f000 0b01 and.w fp, r0, #1 +10032f24: f04f 0900 mov.w r9, #0 +10032f28: 2206 movs r2, #6 +10032f2a: 3195 adds r1, #149 ; 0x95 +10032f2c: f10a 001a add.w r0, sl, #26 +10032f30: f7dd fc77 bl 10010822 +10032f34: bb70 cbnz r0, 10032f94 +10032f36: f641 40b9 movw r0, #7353 ; 0x1cb9 +10032f3a: 5d00 ldrb r0, [r0, r4] +10032f3c: b150 cbz r0, 10032f54 +10032f3e: f1bb 0f00 cmp.w fp, #0 +10032f42: d127 bne.n 10032f94 +10032f44: b11d cbz r5, 10032f4e +10032f46: 9900 ldr r1, [sp, #0] +10032f48: 4628 mov r0, r5 +10032f4a: f7fa f889 bl 1002d060 +10032f4e: 2000 movs r0, #0 +10032f50: e8bd 8ffe ldmia.w sp!, {r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, pc} +10032f54: f1bb 0f00 cmp.w fp, #0 +10032f58: d00a beq.n 10032f70 +10032f5a: 4620 mov r0, r4 +10032f5c: f7f2 f96c bl 10025238 +10032f60: b1c0 cbz r0, 10032f94 +10032f62: 224a movs r2, #74 ; 0x4a +10032f64: 2101 movs r1, #1 +10032f66: 4638 mov r0, r7 +10032f68: f7de fa69 bl 1001143e +10032f6c: 4681 mov r9, r0 +10032f6e: e005 b.n 10032f7c +10032f70: 9801 ldr r0, [sp, #4] +10032f72: f10a 011a add.w r1, sl, #26 +10032f76: f7f2 f919 bl 100251ac +10032f7a: b158 cbz r0, 10032f94 +10032f7c: 5931 ldr r1, [r6, r4] +10032f7e: 61f9 str r1, [r7, #28] +10032f80: 4638 mov r0, r7 +10032f82: f7fc fff1 bl 1002ff68 +10032f86: f1bb 0f00 cmp.w fp, #0 +10032f8a: bf18 it ne +10032f8c: f1b9 0f00 cmpne.w r9, #0 +10032f90: d075 beq.n 1003307e +10032f92: 464f mov r7, r9 +10032f94: 5930 ldr r0, [r6, r4] +10032f96: 61f8 str r0, [r7, #28] +10032f98: f648 068e movw r6, #34958 ; 0x888e +10032f9c: 6938 ldr r0, [r7, #16] +10032f9e: 8980 ldrh r0, [r0, #12] +10032fa0: f7dd fbbe bl 10010720 <_htons> +10032fa4: 42b0 cmp r0, r6 +10032fa6: d115 bne.n 10032fd4 +10032fa8: f641 0079 movw r0, #6265 ; 0x1879 +10032fac: 5d00 ldrb r0, [r0, r4] +10032fae: 2800 cmp r0, #0 +10032fb0: bf1e ittt ne +10032fb2: 6938 ldrne r0, [r7, #16] +10032fb4: 7bc0 ldrbne r0, [r0, #15] +10032fb6: 2803 cmpne r0, #3 +10032fb8: d00c beq.n 10032fd4 +10032fba: f504 5088 add.w r0, r4, #4352 ; 0x1100 +10032fbe: f000 f866 bl 1003308e <.text_9> +10032fc2: 2800 cmp r0, #0 +10032fc4: d0be beq.n 10032f44 +10032fc6: 2300 movs r3, #0 +10032fc8: 2224 movs r2, #36 ; 0x24 +10032fca: 4639 mov r1, r7 +10032fcc: 200b movs r0, #11 +10032fce: f7fc ff1d bl 1002fe0c +10032fd2: e7b7 b.n 10032f44 +10032fd4: f241 5054 movw r0, #5460 ; 0x1554 +10032fd8: 5900 ldr r0, [r0, r4] +10032fda: 2804 cmp r0, #4 +10032fdc: bf18 it ne +10032fde: 2807 cmpne r0, #7 +10032fe0: d14a bne.n 10033078 +10032fe2: 6938 ldr r0, [r7, #16] +10032fe4: 8980 ldrh r0, [r0, #12] +10032fe6: f7dd fb9b bl 10010720 <_htons> +10032fea: 42b0 cmp r0, r6 +10032fec: d144 bne.n 10033078 +10032fee: f504 5088 add.w r0, r4, #4352 ; 0x1100 +10032ff2: f100 09f0 add.w r9, r0, #240 ; 0xf0 +10032ff6: f000 f84a bl 1003308e <.text_9> +10032ffa: 0006 movs r6, r0 +10032ffc: d0a2 beq.n 10032f44 +10032ffe: 2110 movs r1, #16 +10033000: f000 f84b bl 1003309a <.text_10+0x2> +10033004: 2801 cmp r0, #1 +10033006: d106 bne.n 10033016 +10033008: f8d6 00fc ldr.w r0, [r6, #252] ; 0xfc +1003300c: eb09 0080 add.w r0, r9, r0, lsl #2 +10033010: f8d0 962c ldr.w r9, [r0, #1580] ; 0x62c +10033014: e005 b.n 10033022 +10033016: f000 f83f bl 10033098 <.text_10> +1003301a: 2801 cmp r0, #1 +1003301c: d192 bne.n 10032f44 +1003301e: f8d9 9630 ldr.w r9, [r9, #1584] ; 0x630 +10033022: f1b9 0f00 cmp.w r9, #0 +10033026: d08d beq.n 10032f44 +10033028: f000 f836 bl 10033098 <.text_10> +1003302c: 2801 cmp r0, #1 +1003302e: bf04 itt eq +10033030: f8d9 0304 ldreq.w r0, [r9, #772] ; 0x304 +10033034: 2800 cmpeq r0, #0 +10033036: d106 bne.n 10033046 +10033038: f8d9 0308 ldr.w r0, [r9, #776] ; 0x308 +1003303c: b918 cbnz r0, 10033046 +1003303e: 4631 mov r1, r6 +10033040: 4620 mov r0, r4 +10033042: f7f0 fc54 bl 100238ee +10033046: 6938 ldr r0, [r7, #16] +10033048: f8c9 00d4 str.w r0, [r9, #212] ; 0xd4 +1003304c: 2110 movs r1, #16 +1003304e: 6a38 ldr r0, [r7, #32] +10033050: f8c9 00d8 str.w r0, [r9, #216] ; 0xd8 +10033054: f000 f821 bl 1003309a <.text_10+0x2> +10033058: 2801 cmp r0, #1 +1003305a: d104 bne.n 10033066 +1003305c: 4631 mov r1, r6 +1003305e: 4620 mov r0, r4 +10033060: f7f1 fa06 bl 10024470 +10033064: e76e b.n 10032f44 +10033066: f000 f817 bl 10033098 <.text_10> +1003306a: 2801 cmp r0, #1 +1003306c: d1fa bne.n 10033064 +1003306e: 4631 mov r1, r6 +10033070: 4620 mov r0, r4 +10033072: f7f1 fac1 bl 100245f8 +10033076: e765 b.n 10032f44 +10033078: 4638 mov r0, r7 +1003307a: f7dc ff12 bl 1000fea2 +1003307e: 2000 movs r0, #0 +10033080: 60a8 str r0, [r5, #8] +10033082: 4628 mov r0, r5 +10033084: 9900 ldr r1, [sp, #0] +10033086: f7f9 ffeb bl 1002d060 +1003308a: 2001 movs r0, #1 +1003308c: e760 b.n 10032f50 + +1003308e <.text_9>: +1003308e: f105 0142 add.w r1, r5, #66 ; 0x42 +10033092: 3028 adds r0, #40 ; 0x28 +10033094: f7f2 b88a b.w 100251ac + +10033098 <.text_10>: +10033098: 2108 movs r1, #8 +1003309a: 4640 mov r0, r8 +1003309c: e70a b.n 10032eb4 + ... + +100330a0 : +100330a0: 8801 ldrh r1, [r0, #0] +100330a2: 0a0a lsrs r2, r1, #8 +100330a4: f002 0201 and.w r2, r2, #1 +100330a8: 0a89 lsrs r1, r1, #10 +100330aa: 4152 adcs r2, r2 +100330ac: b2d2 uxtb r2, r2 +100330ae: b12a cbz r2, 100330bc +100330b0: 2a02 cmp r2, #2 +100330b2: d007 beq.n 100330c4 +100330b4: d304 bcc.n 100330c0 +100330b6: 2a03 cmp r2, #3 +100330b8: d004 beq.n 100330c4 +100330ba: e005 b.n 100330c8 +100330bc: 3010 adds r0, #16 +100330be: 4770 bx lr +100330c0: 300a adds r0, #10 +100330c2: 4770 bx lr +100330c4: 1d00 adds r0, r0, #4 +100330c6: 4770 bx lr +100330c8: 2000 movs r0, #0 +100330ca: 4770 bx lr + +100330cc : +100330cc: b108 cbz r0, 100330d2 +100330ce: f8d0 0084 ldr.w r0, [r0, #132] ; 0x84 +100330d2: 4770 bx lr + +100330d4 : +100330d4: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} +100330d8: 2200 movs r2, #0 +100330da: 2700 movs r7, #0 +100330dc: 4613 mov r3, r2 +100330de: f04f 0818 mov.w r8, #24 +100330e2: f8df 981c ldr.w r9, [pc, #2076] ; 10033900 <.text_24> +100330e6: fb08 9603 mla r6, r8, r3, r9 +100330ea: 7d34 ldrb r4, [r6, #20] +100330ec: 2c00 cmp r4, #0 +100330ee: d021 beq.n 10033134 +100330f0: f8b6 c004 ldrh.w ip, [r6, #4] +100330f4: 88f4 ldrh r4, [r6, #6] +100330f6: 1c7f adds r7, r7, #1 +100330f8: 4464 add r4, ip +100330fa: 42a1 cmp r1, r4 +100330fc: db17 blt.n 1003312e +100330fe: f8b6 c004 ldrh.w ip, [r6, #4] +10033102: 4484 add ip, r0 +10033104: f04f 0e00 mov.w lr, #0 +10033108: e002 b.n 10033110 +1003310a: 2201 movs r2, #1 +1003310c: f10e 0e01 add.w lr, lr, #1 +10033110: 88f4 ldrh r4, [r6, #6] +10033112: 45a6 cmp lr, r4 +10033114: da0d bge.n 10033132 +10033116: 68b2 ldr r2, [r6, #8] +10033118: 68f5 ldr r5, [r6, #12] +1003311a: f81e 2002 ldrb.w r2, [lr, r2] +1003311e: f81c 4b01 ldrb.w r4, [ip], #1 +10033122: f81e 5005 ldrb.w r5, [lr, r5] +10033126: 4014 ands r4, r2 +10033128: 402a ands r2, r5 +1003312a: 4294 cmp r4, r2 +1003312c: d0ed beq.n 1003310a +1003312e: 2200 movs r2, #0 +10033130: e000 b.n 10033134 +10033132: b912 cbnz r2, 1003313a +10033134: 1c5b adds r3, r3, #1 +10033136: 2b05 cmp r3, #5 +10033138: dbd5 blt.n 100330e6 +1003313a: b137 cbz r7, 1003314a +1003313c: fb08 9003 mla r0, r8, r3, r9 +10033140: 6900 ldr r0, [r0, #16] +10033142: b130 cbz r0, 10033152 +10033144: 2801 cmp r0, #1 +10033146: d104 bne.n 10033152 +10033148: b90a cbnz r2, 1003314e +1003314a: 2001 movs r0, #1 +1003314c: e002 b.n 10033154 +1003314e: 2000 movs r0, #0 +10033150: e000 b.n 10033154 +10033152: 4610 mov r0, r2 +10033154: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + +10033158 : +10033158: b5f8 push {r3, r4, r5, r6, r7, lr} +1003315a: f500 6432 add.w r4, r0, #2848 ; 0xb20 +1003315e: f504 65bf add.w r5, r4, #1528 ; 0x5f8 +10033162: 2100 movs r1, #0 +10033164: 4628 mov r0, r5 +10033166: f7dd fbc7 bl 100108f8 +1003316a: f894 05ec ldrb.w r0, [r4, #1516] ; 0x5ec +1003316e: b1a8 cbz r0, 1003319c +10033170: 2000 movs r0, #0 +10033172: f204 56ec addw r6, r4, #1516 ; 0x5ec +10033176: f884 05ec strb.w r0, [r4, #1516] ; 0x5ec +1003317a: 7070 strb r0, [r6, #1] +1003317c: e007 b.n 1003318e +1003317e: 6877 ldr r7, [r6, #4] +10033180: 4638 mov r0, r7 +10033182: f7dd fb6f bl 10010864 +10033186: 2134 movs r1, #52 ; 0x34 +10033188: 4638 mov r0, r7 +1003318a: f7dd fb3f bl 1001080c +1003318e: 6871 ldr r1, [r6, #4] +10033190: f504 60be add.w r0, r4, #1520 ; 0x5f0 +10033194: f7dd fbd9 bl 1001094a +10033198: 2800 cmp r0, #0 +1003319a: d0f0 beq.n 1003317e +1003319c: 4628 mov r0, r5 +1003319e: e8bd 40f4 ldmia.w sp!, {r2, r4, r5, r6, r7, lr} + +100331a2 <.text_7>: +100331a2: 2100 movs r1, #0 +100331a4: f7dd bbaf b.w 10010906 + +100331a8 : +100331a8: b5f2 push {r1, r4, r5, r6, r7, lr} +100331aa: 4604 mov r4, r0 +100331ac: f504 6632 add.w r6, r4, #2848 ; 0xb20 +100331b0: 4615 mov r5, r2 +100331b2: f896 05ec ldrb.w r0, [r6, #1516] ; 0x5ec +100331b6: b301 cbz r1, 100331fa +100331b8: bb58 cbnz r0, 10033212 +100331ba: f506 67bf add.w r7, r6, #1528 ; 0x5f8 +100331be: 2100 movs r1, #0 +100331c0: 4638 mov r0, r7 +100331c2: f7dd fb99 bl 100108f8 +100331c6: f896 05ec ldrb.w r0, [r6, #1516] ; 0x5ec +100331ca: b940 cbnz r0, 100331de +100331cc: f506 60be add.w r0, r6, #1520 ; 0x5f0 +100331d0: f7dd fb3c bl 1001084c +100331d4: 2001 movs r0, #1 +100331d6: f886 05ec strb.w r0, [r6, #1516] ; 0x5ec +100331da: f886 55ed strb.w r5, [r6, #1517] ; 0x5ed +100331de: 2100 movs r1, #0 +100331e0: 4638 mov r0, r7 +100331e2: f7dd fb90 bl 10010906 +100331e6: 2100 movs r1, #0 +100331e8: 4620 mov r0, r4 +100331ea: f7ec ff95 bl 10020118 +100331ee: 4620 mov r0, r4 +100331f0: f7ec fe97 bl 1001ff22 +100331f4: f000 f80e bl 10033214 <.text_9> +100331f8: bdf1 pop {r0, r4, r5, r6, r7, pc} +100331fa: b150 cbz r0, 10033212 +100331fc: 4620 mov r0, r4 +100331fe: f7ff ffab bl 10033158 +10033202: f000 f807 bl 10033214 <.text_9> +10033206: f641 00ba movw r0, #6330 ; 0x18ba +1003320a: 5d01 ldrb r1, [r0, r4] +1003320c: 4620 mov r0, r4 +1003320e: f7ec ff83 bl 10020118 +10033212: bdf1 pop {r0, r4, r5, r6, r7, pc} + +10033214 <.text_9>: +10033214: aa00 add r2, sp, #0 +10033216: 214b movs r1, #75 ; 0x4b +10033218: 4620 mov r0, r4 +1003321a: f7e4 b879 b.w 10017310 + +1003321e : +1003321e: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +10033222: f500 6532 add.w r5, r0, #2848 ; 0xb20 +10033226: 460c mov r4, r1 +10033228: f505 68bf add.w r8, r5, #1528 ; 0x5f8 +1003322c: 2600 movs r6, #0 +1003322e: 2100 movs r1, #0 +10033230: 4640 mov r0, r8 +10033232: f7dd fb61 bl 100108f8 +10033236: f8d5 75f0 ldr.w r7, [r5, #1520] ; 0x5f0 +1003323a: f505 65be add.w r5, r5, #1520 ; 0x5f0 +1003323e: e000 b.n 10033242 +10033240: 683f ldr r7, [r7, #0] +10033242: 4639 mov r1, r7 +10033244: 4628 mov r0, r5 +10033246: f7dd fb80 bl 1001094a +1003324a: b940 cbnz r0, 1003325e +1003324c: 2206 movs r2, #6 +1003324e: 4621 mov r1, r4 +10033250: f107 0008 add.w r0, r7, #8 +10033254: f7dd fae5 bl 10010822 +10033258: 2800 cmp r0, #0 +1003325a: d0f1 beq.n 10033240 +1003325c: 7bbe ldrb r6, [r7, #14] +1003325e: 42af cmp r7, r5 +10033260: bf08 it eq +10033262: 26ff moveq r6, #255 ; 0xff +10033264: 2100 movs r1, #0 +10033266: 4640 mov r0, r8 +10033268: f7dd fb4d bl 10010906 +1003326c: 4630 mov r0, r6 +1003326e: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +10033272 : +10033272: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +10033276: f500 6832 add.w r8, r0, #2848 ; 0xb20 +1003327a: 468b mov fp, r1 +1003327c: f898 05ec ldrb.w r0, [r8, #1516] ; 0x5ec +10033280: 2800 cmp r0, #0 +10033282: 4616 mov r6, r2 +10033284: 461f mov r7, r3 +10033286: d03d beq.n 10033304 +10033288: 2206 movs r2, #6 +1003328a: f20f 618c addw r1, pc, #1676 ; 0x68c +1003328e: 4658 mov r0, fp +10033290: f7dd fac7 bl 10010822 +10033294: 2800 cmp r0, #0 +10033296: d135 bne.n 10033304 +10033298: 2100 movs r1, #0 +1003329a: f508 60bf add.w r0, r8, #1528 ; 0x5f8 +1003329e: f7dd fb2b bl 100108f8 +100332a2: f8d8 55f0 ldr.w r5, [r8, #1520] ; 0x5f0 +100332a6: f8dd 9028 ldr.w r9, [sp, #40] ; 0x28 +100332aa: f8dd a02c ldr.w sl, [sp, #44] ; 0x2c +100332ae: 9c0c ldr r4, [sp, #48] ; 0x30 +100332b0: e000 b.n 100332b4 +100332b2: 682d ldr r5, [r5, #0] +100332b4: f000 fb2a bl 1003390c <.text_27> +100332b8: b948 cbnz r0, 100332ce +100332ba: 2206 movs r2, #6 +100332bc: 4659 mov r1, fp +100332be: f105 0008 add.w r0, r5, #8 +100332c2: f7dd faae bl 10010822 +100332c6: 2800 cmp r0, #0 +100332c8: d0f3 beq.n 100332b2 +100332ca: f000 f81d bl 10033308 <.text_12> +100332ce: f508 60be add.w r0, r8, #1520 ; 0x5f0 +100332d2: 4285 cmp r5, r0 +100332d4: d111 bne.n 100332fa +100332d6: 2034 movs r0, #52 ; 0x34 +100332d8: f7dd fa93 bl 10010802 +100332dc: 0005 movs r5, r0 +100332de: d00c beq.n 100332fa +100332e0: 2206 movs r2, #6 +100332e2: 4659 mov r1, fp +100332e4: f105 0008 add.w r0, r5, #8 +100332e8: f7dd fa91 bl 1001080e +100332ec: f000 f80c bl 10033308 <.text_12> +100332f0: f508 61be add.w r1, r8, #1520 ; 0x5f0 +100332f4: 4628 mov r0, r5 +100332f6: f7dd fab1 bl 1001085c +100332fa: f508 60bf add.w r0, r8, #1528 ; 0x5f8 +100332fe: e8bd 4ff4 ldmia.w sp!, {r2, r4, r5, r6, r7, r8, r9, sl, fp, lr} +10033302: e74e b.n 100331a2 <.text_7> +10033304: e8bd 8ff1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +10033308 <.text_12>: +10033308: 73ae strb r6, [r5, #14] +1003330a: 73ef strb r7, [r5, #15] +1003330c: f885 a030 strb.w sl, [r5, #48] ; 0x30 +10033310: f885 4031 strb.w r4, [r5, #49] ; 0x31 +10033314: 4652 mov r2, sl +10033316: 4649 mov r1, r9 +10033318: f105 0010 add.w r0, r5, #16 +1003331c: f7dd ba77 b.w 1001080e + +10033320 : +10033320: b5f8 push {r3, r4, r5, r6, r7, lr} +10033322: 4605 mov r5, r0 +10033324: 4608 mov r0, r1 +10033326: 4614 mov r4, r2 +10033328: f7ff fed0 bl 100330cc +1003332c: 4606 mov r6, r0 +1003332e: f7ff feb7 bl 100330a0 +10033332: 4607 mov r7, r0 +10033334: 8830 ldrh r0, [r6, #0] +10033336: 8020 strh r0, [r4, #0] +10033338: 2206 movs r2, #6 +1003333a: 8af0 ldrh r0, [r6, #22] +1003333c: 0900 lsrs r0, r0, #4 +1003333e: 82e0 strh r0, [r4, #22] +10033340: 1d31 adds r1, r6, #4 +10033342: 8870 ldrh r0, [r6, #2] +10033344: 8060 strh r0, [r4, #2] +10033346: 1d20 adds r0, r4, #4 +10033348: f7dd fa61 bl 1001080e +1003334c: 2206 movs r2, #6 +1003334e: f106 010a add.w r1, r6, #10 +10033352: f104 000a add.w r0, r4, #10 +10033356: f7dd fa5a bl 1001080e +1003335a: 2206 movs r2, #6 +1003335c: f106 0110 add.w r1, r6, #16 +10033360: f104 0010 add.w r0, r4, #16 +10033364: f7dd fa53 bl 1001080e +10033368: 4639 mov r1, r7 +1003336a: 4628 mov r0, r5 +1003336c: f7ff ff57 bl 1003321e +10033370: 77a0 strb r0, [r4, #30] +10033372: 8830 ldrh r0, [r6, #0] +10033374: 05c1 lsls r1, r0, #23 +10033376: bf4c ite mi +10033378: 2102 movmi r1, #2 +1003337a: 2100 movpl r1, #0 +1003337c: 0a40 lsrs r0, r0, #9 +1003337e: f000 0001 and.w r0, r0, #1 +10033382: 4308 orrs r0, r1 +10033384: d003 beq.n 1003338e +10033386: 2802 cmp r0, #2 +10033388: d009 beq.n 1003339e +1003338a: d304 bcc.n 10033396 +1003338c: e00f b.n 100333ae +1003338e: 2206 movs r2, #6 +10033390: f104 0110 add.w r1, r4, #16 +10033394: e005 b.n 100333a2 +10033396: 2206 movs r2, #6 +10033398: f104 010a add.w r1, r4, #10 +1003339c: e001 b.n 100333a2 +1003339e: 2206 movs r2, #6 +100333a0: 1d21 adds r1, r4, #4 +100333a2: f104 0018 add.w r0, r4, #24 +100333a6: e8bd 40f8 ldmia.w sp!, {r3, r4, r5, r6, r7, lr} +100333aa: f7dd ba30 b.w 1001080e +100333ae: f104 0018 add.w r0, r4, #24 +100333b2: e8bd 40f8 ldmia.w sp!, {r3, r4, r5, r6, r7, lr} +100333b6: 2206 movs r2, #6 +100333b8: 2100 movs r1, #0 +100333ba: f7dd ba3d b.w 10010838 + +100333be : +100333be: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +100333c2: 4606 mov r6, r0 +100333c4: 460c mov r4, r1 +100333c6: b088 sub sp, #32 +100333c8: f606 3524 addw r5, r6, #2852 ; 0xb24 +100333cc: 4620 mov r0, r4 +100333ce: f7ff fe7d bl 100330cc +100333d2: f7ff fe65 bl 100330a0 +100333d6: aa00 add r2, sp, #0 +100333d8: 4621 mov r1, r4 +100333da: 4630 mov r0, r6 +100333dc: f7ff ffa0 bl 10033320 +100333e0: f894 002f ldrb.w r0, [r4, #47] ; 0x2f +100333e4: 2802 cmp r0, #2 +100333e6: f104 067c add.w r6, r4, #124 ; 0x7c +100333ea: d10c bne.n 10033406 +100333ec: b15c cbz r4, 10033406 +100333ee: 68f0 ldr r0, [r6, #12] +100333f0: 3808 subs r0, #8 +100333f2: 60f0 str r0, [r6, #12] +100333f4: 68b1 ldr r1, [r6, #8] +100333f6: 4288 cmp r0, r1 +100333f8: d202 bcs.n 10033400 +100333fa: 3008 adds r0, #8 +100333fc: 60f0 str r0, [r6, #12] +100333fe: e002 b.n 10033406 +10033400: 6fe0 ldr r0, [r4, #124] ; 0x7c +10033402: 3808 subs r0, #8 +10033404: 67e0 str r0, [r4, #124] ; 0x7c +10033406: 4620 mov r0, r4 +10033408: f7fa fcab bl 1002dd62 +1003340c: 4680 mov r8, r0 +1003340e: 68a7 ldr r7, [r4, #8] +10033410: b1af cbz r7, 1003343e +10033412: 68b0 ldr r0, [r6, #8] +10033414: 6138 str r0, [r7, #16] +10033416: 4638 mov r0, r7 +10033418: 6fe1 ldr r1, [r4, #124] ; 0x7c +1003341a: f7de f800 bl 1001141e +1003341e: 6fe1 ldr r1, [r4, #124] ; 0x7c +10033420: f8df 04e0 ldr.w r0, [pc, #1248] ; 10033904 <.text_25> +10033424: 6239 str r1, [r7, #32] +10033426: 6806 ldr r6, [r0, #0] +10033428: 0030 movs r0, r6 +1003342a: d008 beq.n 1003343e +1003342c: 6938 ldr r0, [r7, #16] +1003342e: b209 sxth r1, r1 +10033430: f7ff fe50 bl 100330d4 +10033434: b118 cbz r0, 1003343e +10033436: 6a39 ldr r1, [r7, #32] +10033438: 6938 ldr r0, [r7, #16] +1003343a: aa00 add r2, sp, #0 +1003343c: 47b0 blx r6 +1003343e: 4629 mov r1, r5 +10033440: 4620 mov r0, r4 +10033442: f7f9 fe0d bl 1002d060 +10033446: 4640 mov r0, r8 +10033448: b008 add sp, #32 +1003344a: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + ... + +10033450 : +10033450: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +10033454: 4604 mov r4, r0 +10033456: f8d1 0084 ldr.w r0, [r1, #132] ; 0x84 +1003345a: 8802 ldrh r2, [r0, #0] +1003345c: f101 071c add.w r7, r1, #28 +10033460: 2601 movs r6, #1 +10033462: 0a11 lsrs r1, r2, #8 +10033464: f001 0101 and.w r1, r1, #1 +10033468: 0a92 lsrs r2, r2, #10 +1003346a: 4149 adcs r1, r1 +1003346c: 1d03 adds r3, r0, #4 +1003346e: 9300 str r3, [sp, #0] +10033470: f100 0a10 add.w sl, r0, #16 +10033474: b2cb uxtb r3, r1 +10033476: 2b01 cmp r3, #1 +10033478: bf94 ite ls +1003347a: 9d00 ldrls r5, [sp, #0] +1003347c: 4655 movhi r5, sl +1003347e: b2c9 uxtb r1, r1 +10033480: 2900 cmp r1, #0 +10033482: bf18 it ne +10033484: 2902 cmpne r1, #2 +10033486: f504 6832 add.w r8, r4, #2848 ; 0xb20 +1003348a: f100 090a add.w r9, r0, #10 +1003348e: d001 beq.n 10033494 +10033490: d304 bcc.n 1003349c +10033492: e001 b.n 10033498 +10033494: 46ca mov sl, r9 +10033496: e001 b.n 1003349c +10033498: f100 0a18 add.w sl, r0, #24 +1003349c: f7ff fe00 bl 100330a0 +100334a0: 4683 mov fp, r0 +100334a2: 2206 movs r2, #6 +100334a4: 4629 mov r1, r5 +100334a6: f107 001a add.w r0, r7, #26 +100334aa: f7dd f9b0 bl 1001080e +100334ae: 2206 movs r2, #6 +100334b0: 4651 mov r1, sl +100334b2: f107 0020 add.w r0, r7, #32 +100334b6: f7dd f9aa bl 1001080e +100334ba: 79b8 ldrb r0, [r7, #6] +100334bc: b128 cbz r0, 100334ca +100334be: 2802 cmp r0, #2 +100334c0: d01d beq.n 100334fe +100334c2: d315 bcc.n 100334f0 +100334c4: 2803 cmp r0, #3 +100334c6: d01d beq.n 10033504 +100334c8: e03e b.n 10033548 +100334ca: 2206 movs r2, #6 +100334cc: 4629 mov r1, r5 +100334ce: f000 f873 bl 100335b8 <.text_16> +100334d2: 2206 movs r2, #6 +100334d4: 4651 mov r1, sl +100334d6: f107 0026 add.w r0, r7, #38 ; 0x26 +100334da: f7dd f998 bl 1001080e +100334de: 7a39 ldrb r1, [r7, #8] +100334e0: 79b8 ldrb r0, [r7, #6] +100334e2: 2901 cmp r1, #1 +100334e4: d119 bne.n 1003351a +100334e6: 2803 cmp r0, #3 +100334e8: bf14 ite ne +100334ea: 201a movne r0, #26 +100334ec: 2020 moveq r0, #32 +100334ee: e018 b.n 10033522 +100334f0: 2206 movs r2, #6 +100334f2: 4629 mov r1, r5 +100334f4: f000 f860 bl 100335b8 <.text_16> +100334f8: 2206 movs r2, #6 +100334fa: 4659 mov r1, fp +100334fc: e7eb b.n 100334d6 +100334fe: 2206 movs r2, #6 +10033500: 4659 mov r1, fp +10033502: e7e4 b.n 100334ce +10033504: 9900 ldr r1, [sp, #0] +10033506: 2206 movs r2, #6 +10033508: f000 f856 bl 100335b8 <.text_16> +1003350c: 2206 movs r2, #6 +1003350e: 4649 mov r1, r9 +10033510: f107 0026 add.w r0, r7, #38 ; 0x26 +10033514: f7dd f97b bl 1001080e +10033518: e016 b.n 10033548 +1003351a: 2803 cmp r0, #3 +1003351c: bf0c ite eq +1003351e: 201e moveq r0, #30 +10033520: 2018 movne r0, #24 +10033522: 7178 strb r0, [r7, #5] +10033524: 7c38 ldrb r0, [r7, #16] +10033526: b110 cbz r0, 1003352e +10033528: 7978 ldrb r0, [r7, #5] +1003352a: 1d00 adds r0, r0, #4 +1003352c: 7178 strb r0, [r7, #5] +1003352e: 7c78 ldrb r0, [r7, #17] +10033530: 2800 cmp r0, #0 +10033532: bf1c itt ne +10033534: f898 05ed ldrbne.w r0, [r8, #1517] ; 0x5ed +10033538: 2800 cmpne r0, #0 +1003353a: d036 beq.n 100335aa +1003353c: 4659 mov r1, fp +1003353e: 4620 mov r0, r4 +10033540: f7ff fe6d bl 1003321e +10033544: 28ff cmp r0, #255 ; 0xff +10033546: d101 bne.n 1003354c +10033548: 2600 movs r6, #0 +1003354a: e032 b.n 100335b2 +1003354c: 1e80 subs r0, r0, #2 +1003354e: 2807 cmp r0, #7 +10033550: d80d bhi.n 1003356e +10033552: e8df f000 tbb [pc, r0] +10033556: 0604 .short 0x0604 +10033558: 08080608 .word 0x08080608 +1003355c: 0a0c .short 0x0a0c +1003355e: 2001 movs r0, #1 +10033560: e006 b.n 10033570 +10033562: 2002 movs r0, #2 +10033564: e004 b.n 10033570 +10033566: 2004 movs r0, #4 +10033568: e002 b.n 10033570 +1003356a: 2005 movs r0, #5 +1003356c: e000 b.n 10033570 +1003356e: 2000 movs r0, #0 +10033570: 74f8 strb r0, [r7, #19] +10033572: 7cf8 ldrb r0, [r7, #19] +10033574: 2801 cmp r0, #1 +10033576: d008 beq.n 1003358a +10033578: 2802 cmp r0, #2 +1003357a: d008 beq.n 1003358e +1003357c: 2804 cmp r0, #4 +1003357e: d00a beq.n 10033596 +10033580: 2805 cmp r0, #5 +10033582: d002 beq.n 1003358a +10033584: 2806 cmp r0, #6 +10033586: d008 beq.n 1003359a +10033588: e00b b.n 100335a2 +1003358a: 2004 movs r0, #4 +1003358c: e00a b.n 100335a4 +1003358e: 2008 movs r0, #8 +10033590: 7538 strb r0, [r7, #20] +10033592: 2004 movs r0, #4 +10033594: e007 b.n 100335a6 +10033596: 2008 movs r0, #8 +10033598: e004 b.n 100335a4 +1003359a: 2012 movs r0, #18 +1003359c: 7538 strb r0, [r7, #20] +1003359e: 2010 movs r0, #16 +100335a0: e001 b.n 100335a6 +100335a2: 2000 movs r0, #0 +100335a4: 7538 strb r0, [r7, #20] +100335a6: 7578 strb r0, [r7, #21] +100335a8: e003 b.n 100335b2 +100335aa: 2000 movs r0, #0 +100335ac: 74f8 strb r0, [r7, #19] +100335ae: 7578 strb r0, [r7, #21] +100335b0: 7538 strb r0, [r7, #20] +100335b2: 4630 mov r0, r6 +100335b4: e8bd 8ff2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +100335b8 <.text_16>: +100335b8: f107 002c add.w r0, r7, #44 ; 0x2c +100335bc: f7dd b927 b.w 1001080e + +100335c0 : +100335c0: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +100335c4: b093 sub sp, #76 ; 0x4c +100335c6: 4680 mov r8, r0 +100335c8: f8d1 0084 ldr.w r0, [r1, #132] ; 0x84 +100335cc: f100 0210 add.w r2, r0, #16 +100335d0: 920a str r2, [sp, #40] ; 0x28 +100335d2: f100 0918 add.w r9, r0, #24 +100335d6: 6fc8 ldr r0, [r1, #124] ; 0x7c +100335d8: 2500 movs r5, #0 +100335da: f8ad 5014 strh.w r5, [sp, #20] +100335de: f1a0 0b18 sub.w fp, r0, #24 +100335e2: 9503 str r5, [sp, #12] +100335e4: 2700 movs r7, #0 +100335e6: 2401 movs r4, #1 +100335e8: 9504 str r5, [sp, #16] +100335ea: 9507 str r5, [sp, #28] +100335ec: 2220 movs r2, #32 +100335ee: 4629 mov r1, r5 +100335f0: a80b add r0, sp, #44 ; 0x2c +100335f2: f7dd f921 bl 10010838 +100335f6: 4648 mov r0, r9 +100335f8: f7eb f96c bl 1001e8d4 +100335fc: 4601 mov r1, r0 +100335fe: 2202 movs r2, #2 +10033600: a805 add r0, sp, #20 +10033602: f7dd f904 bl 1001080e +10033606: f8bd 0014 ldrh.w r0, [sp, #20] +1003360a: 0600 lsls r0, r0, #24 +1003360c: 0f00 lsrs r0, r0, #28 +1003360e: f000 0601 and.w r6, r0, #1 +10033612: f1ab 0a0c sub.w sl, fp, #12 +10033616: 4653 mov r3, sl +10033618: aa09 add r2, sp, #36 ; 0x24 +1003361a: 2103 movs r1, #3 +1003361c: f000 f894 bl 10033748 <.text_18> +10033620: 2800 cmp r0, #0 +10033622: bf1e ittt ne +10033624: 9909 ldrne r1, [sp, #36] ; 0x24 +10033626: 2900 cmpne r1, #0 +10033628: 7887 ldrbne r7, [r0, #2] +1003362a: 4653 mov r3, sl +1003362c: aa06 add r2, sp, #24 +1003362e: 2100 movs r1, #0 +10033630: f000 f88a bl 10033748 <.text_18> +10033634: b120 cbz r0, 10033640 +10033636: 7841 ldrb r1, [r0, #1] +10033638: b149 cbz r1, 1003364e +1003363a: 9906 ldr r1, [sp, #24] +1003363c: 2921 cmp r1, #33 ; 0x21 +1003363e: d301 bcc.n 10033644 +10033640: 2000 movs r0, #0 +10033642: e07e b.n 10033742 +10033644: 460a mov r2, r1 +10033646: 1c81 adds r1, r0, #2 +10033648: a80b add r0, sp, #44 ; 0x2c +1003364a: f7dd f8e0 bl 1001080e +1003364e: 4653 mov r3, sl +10033650: aa08 add r2, sp, #32 +10033652: 213d movs r1, #61 ; 0x3d +10033654: f000 f878 bl 10033748 <.text_18> +10033658: 2800 cmp r0, #0 +1003365a: bf1c itt ne +1003365c: 9908 ldrne r1, [sp, #32] +1003365e: 2900 cmpne r1, #0 +10033660: d004 beq.n 1003366c +10033662: 78c0 ldrb r0, [r0, #3] +10033664: 0741 lsls r1, r0, #29 +10033666: bf48 it mi +10033668: f000 0503 andmi.w r5, r0, #3 +1003366c: f10d 000e add.w r0, sp, #14 +10033670: 9001 str r0, [sp, #4] +10033672: ab03 add r3, sp, #12 +10033674: 2000 movs r0, #0 +10033676: 9000 str r0, [sp, #0] +10033678: 2200 movs r2, #0 +1003367a: 4659 mov r1, fp +1003367c: 4648 mov r0, r9 +1003367e: f7e2 fe09 bl 10016294 +10033682: f8bd 000e ldrh.w r0, [sp, #14] +10033686: b1f0 cbz r0, 100336c6 +10033688: 4652 mov r2, sl +1003368a: a901 add r1, sp, #4 +1003368c: f109 000c add.w r0, r9, #12 +10033690: f7e6 f982 bl 10019998 +10033694: 2800 cmp r0, #0 +10033696: bf1c itt ne +10033698: 9901 ldrne r1, [sp, #4] +1003369a: 2900 cmpne r1, #0 +1003369c: d007 beq.n 100336ae +1003369e: 2100 movs r1, #0 +100336a0: 9100 str r1, [sp, #0] +100336a2: ab07 add r3, sp, #28 +100336a4: f8bd 100e ldrh.w r1, [sp, #14] +100336a8: aa04 add r2, sp, #16 +100336aa: f7e0 fbe5 bl 10013e78 +100336ae: 9804 ldr r0, [sp, #16] +100336b0: 2802 cmp r0, #2 +100336b2: d006 beq.n 100336c2 +100336b4: 2804 cmp r0, #4 +100336b6: d037 beq.n 10033728 +100336b8: 2808 cmp r0, #8 +100336ba: d021 beq.n 10033700 +100336bc: 2810 cmp r0, #16 +100336be: d029 beq.n 10033714 +100336c0: e033 b.n 1003372a +100336c2: 2402 movs r4, #2 +100336c4: e031 b.n 1003372a +100336c6: f8bd 000c ldrh.w r0, [sp, #12] +100336ca: b198 cbz r0, 100336f4 +100336cc: 4652 mov r2, sl +100336ce: a901 add r1, sp, #4 +100336d0: f109 000c add.w r0, r9, #12 +100336d4: f7e6 f964 bl 100199a0 +100336d8: 2800 cmp r0, #0 +100336da: bf1c itt ne +100336dc: 9901 ldrne r1, [sp, #4] +100336de: 2900 cmpne r1, #0 +100336e0: d0e5 beq.n 100336ae +100336e2: 2100 movs r1, #0 +100336e4: 9100 str r1, [sp, #0] +100336e6: ab07 add r3, sp, #28 +100336e8: f8bd 100c ldrh.w r1, [sp, #12] +100336ec: aa04 add r2, sp, #16 +100336ee: f7e0 fbbf bl 10013e70 +100336f2: e7dc b.n 100336ae +100336f4: b116 cbz r6, 100336fc +100336f6: 2002 movs r0, #2 +100336f8: 9004 str r0, [sp, #16] +100336fa: e7e2 b.n 100336c2 +100336fc: 9404 str r4, [sp, #16] +100336fe: e014 b.n 1003372a +10033700: f8bd 000c ldrh.w r0, [sp, #12] +10033704: b108 cbz r0, 1003370a +10033706: 2405 movs r4, #5 +10033708: e00f b.n 1003372a +1003370a: f8bd 000e ldrh.w r0, [sp, #14] +1003370e: b160 cbz r0, 1003372a +10033710: 2403 movs r4, #3 +10033712: e00a b.n 1003372a +10033714: f8bd 000c ldrh.w r0, [sp, #12] +10033718: b108 cbz r0, 1003371e +1003371a: 2406 movs r4, #6 +1003371c: e005 b.n 1003372a +1003371e: f8bd 000e ldrh.w r0, [sp, #14] +10033722: b110 cbz r0, 1003372a +10033724: 2404 movs r4, #4 +10033726: e000 b.n 1003372a +10033728: 2409 movs r4, #9 +1003372a: 9806 ldr r0, [sp, #24] +1003372c: 990a ldr r1, [sp, #40] ; 0x28 +1003372e: 9001 str r0, [sp, #4] +10033730: 9502 str r5, [sp, #8] +10033732: a80b add r0, sp, #44 ; 0x2c +10033734: 9000 str r0, [sp, #0] +10033736: 463b mov r3, r7 +10033738: 4622 mov r2, r4 +1003373a: 4640 mov r0, r8 +1003373c: f7ff fd99 bl 10033272 +10033740: 2001 movs r0, #1 +10033742: b013 add sp, #76 ; 0x4c +10033744: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +10033748 <.text_18>: +10033748: f109 000c add.w r0, r9, #12 +1003374c: f7e0 bb98 b.w 10013e80 + +10033750 : +10033750: b5f0 push {r4, r5, r6, r7, lr} +10033752: 460d mov r5, r1 +10033754: b089 sub sp, #36 ; 0x24 +10033756: f8d5 6084 ldr.w r6, [r5, #132] ; 0x84 +1003375a: 4604 mov r4, r0 +1003375c: 8830 ldrh r0, [r6, #0] +1003375e: f000 030c and.w r3, r0, #12 +10033762: f000 07fc and.w r7, r0, #252 ; 0xfc +10033766: ea4f 2c10 mov.w ip, r0, lsr #8 +1003376a: f105 021c add.w r2, r5, #28 +1003376e: f00c 0c01 and.w ip, ip, #1 +10033772: 0a80 lsrs r0, r0, #10 +10033774: eb4c 0c0c adc.w ip, ip, ip +10033778: f882 c006 strb.w ip, [r2, #6] +1003377c: f504 6132 add.w r1, r4, #2848 ; 0xb20 +10033780: 8830 ldrh r0, [r6, #0] +10033782: 0b80 lsrs r0, r0, #14 +10033784: f000 0001 and.w r0, r0, #1 +10033788: 7450 strb r0, [r2, #17] +1003378a: 8830 ldrh r0, [r6, #0] +1003378c: 0bc0 lsrs r0, r0, #15 +1003378e: 7410 strb r0, [r2, #16] +10033790: b113 cbz r3, 10033798 +10033792: 2b08 cmp r3, #8 +10033794: d01f beq.n 100337d6 +10033796: e008 b.n 100337aa +10033798: 2f80 cmp r7, #128 ; 0x80 +1003379a: d106 bne.n 100337aa +1003379c: f891 05ed ldrb.w r0, [r1, #1517] ; 0x5ed +100337a0: b118 cbz r0, 100337aa +100337a2: 4629 mov r1, r5 +100337a4: 4620 mov r0, r4 +100337a6: f7ff ff0b bl 100335c0 +100337aa: 2000 movs r0, #0 +100337ac: 4f55 ldr r7, [pc, #340] ; (10033904 <.text_25>) +100337ae: 6879 ldr r1, [r7, #4] +100337b0: b1c1 cbz r1, 100337e4 +100337b2: aa00 add r2, sp, #0 +100337b4: 4629 mov r1, r5 +100337b6: 4620 mov r0, r4 +100337b8: f7ff fdb2 bl 10033320 +100337bc: 6fe9 ldr r1, [r5, #124] ; 0x7c +100337be: b209 sxth r1, r1 +100337c0: 4630 mov r0, r6 +100337c2: f7ff fc87 bl 100330d4 +100337c6: b120 cbz r0, 100337d2 +100337c8: 6fe9 ldr r1, [r5, #124] ; 0x7c +100337ca: 687b ldr r3, [r7, #4] +100337cc: aa00 add r2, sp, #0 +100337ce: 4630 mov r0, r6 +100337d0: 4798 blx r3 +100337d2: 2000 movs r0, #0 +100337d4: e006 b.n 100337e4 +100337d6: 09f8 lsrs r0, r7, #7 +100337d8: 7210 strb r0, [r2, #8] +100337da: 4629 mov r1, r5 +100337dc: 4620 mov r0, r4 +100337de: f7ff fe37 bl 10033450 +100337e2: e7e3 b.n 100337ac +100337e4: b009 add sp, #36 ; 0x24 +100337e6: bdf0 pop {r4, r5, r6, r7, pc} + +100337e8 : +100337e8: b570 push {r4, r5, r6, lr} +100337ea: 4604 mov r4, r0 +100337ec: 460d mov r5, r1 +100337ee: f7ff ffaf bl 10033750 +100337f2: 4606 mov r6, r0 +100337f4: 2e01 cmp r6, #1 +100337f6: d004 beq.n 10033802 +100337f8: f604 3124 addw r1, r4, #2852 ; 0xb24 +100337fc: 4628 mov r0, r5 +100337fe: f7f9 fc2f bl 1002d060 +10033802: 2e01 cmp r6, #1 +10033804: d104 bne.n 10033810 +10033806: 4629 mov r1, r5 +10033808: 4620 mov r0, r4 +1003380a: f7ff fdd8 bl 100333be +1003380e: 4606 mov r6, r0 +10033810: 4630 mov r0, r6 +10033812: bd70 pop {r4, r5, r6, pc} + +10033814 : +10033814: b510 push {r4, lr} +10033816: 4603 mov r3, r0 +10033818: 483b ldr r0, [pc, #236] ; (10033908 <.text_26>) +1003381a: 7c04 ldrb r4, [r0, #16] +1003381c: b1dc cbz r4, 10033856 +1003381e: 6800 ldr r0, [r0, #0] +10033820: 4c38 ldr r4, [pc, #224] ; (10033904 <.text_25>) +10033822: 6900 ldr r0, [r0, #16] +10033824: 6800 ldr r0, [r0, #0] +10033826: b12b cbz r3, 10033834 +10033828: 2b02 cmp r3, #2 +1003382a: d00b beq.n 10033844 +1003382c: d30a bcc.n 10033844 +1003382e: 2b03 cmp r3, #3 +10033830: d00b beq.n 1003384a +10033832: e00e b.n 10033852 +10033834: 2200 movs r2, #0 +10033836: 2100 movs r1, #0 +10033838: f7ff fcb6 bl 100331a8 +1003383c: 2000 movs r0, #0 +1003383e: 6020 str r0, [r4, #0] +10033840: 6060 str r0, [r4, #4] +10033842: e006 b.n 10033852 +10033844: 6021 str r1, [r4, #0] +10033846: b2d9 uxtb r1, r3 +10033848: e001 b.n 1003384e +1003384a: 6061 str r1, [r4, #4] +1003384c: 2101 movs r1, #1 +1003384e: f7ff fcab bl 100331a8 +10033852: 2000 movs r0, #0 +10033854: bd10 pop {r4, pc} +10033856: f04f 30ff mov.w r0, #4294967295 +1003385a: bd10 pop {r4, pc} + +1003385c : +1003385c: 492a ldr r1, [pc, #168] ; (10033908 <.text_26>) +1003385e: 7c0a ldrb r2, [r1, #16] +10033860: 2000 movs r0, #0 +10033862: b12a cbz r2, 10033870 +10033864: 6808 ldr r0, [r1, #0] +10033866: 6900 ldr r0, [r0, #16] +10033868: 6800 ldr r0, [r0, #0] +1003386a: f241 110c movw r1, #4364 ; 0x110c +1003386e: 5c08 ldrb r0, [r1, r0] +10033870: 4770 bx lr + +10033872 : +10033872: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +10033876: 4681 mov r9, r0 +10033878: 4823 ldr r0, [pc, #140] ; (10033908 <.text_26>) +1003387a: 468b mov fp, r1 +1003387c: 7c01 ldrb r1, [r0, #16] +1003387e: 2700 movs r7, #0 +10033880: 2900 cmp r1, #0 +10033882: 4616 mov r6, r2 +10033884: d038 beq.n 100338f8 +10033886: 6800 ldr r0, [r0, #0] +10033888: 6900 ldr r0, [r0, #16] +1003388a: 6800 ldr r0, [r0, #0] +1003388c: f500 6832 add.w r8, r0, #2848 ; 0xb20 +10033890: f500 649d add.w r4, r0, #1256 ; 0x4e8 +10033894: f508 6abf add.w sl, r8, #1528 ; 0x5f8 +10033898: 2100 movs r1, #0 +1003389a: 4650 mov r0, sl +1003389c: f7dd f82c bl 100108f8 +100338a0: f8d8 55f0 ldr.w r5, [r8, #1520] ; 0x5f0 +100338a4: e000 b.n 100338a8 +100338a6: 682d ldr r5, [r5, #0] +100338a8: f000 f830 bl 1003390c <.text_27> +100338ac: bb00 cbnz r0, 100338f0 +100338ae: 2206 movs r2, #6 +100338b0: 4649 mov r1, r9 +100338b2: f105 0008 add.w r0, r5, #8 +100338b6: f7dc ffb4 bl 10010822 +100338ba: 2800 cmp r0, #0 +100338bc: d0f3 beq.n 100338a6 +100338be: 7bef ldrb r7, [r5, #15] +100338c0: f895 2030 ldrb.w r2, [r5, #48] ; 0x30 +100338c4: 6032 str r2, [r6, #0] +100338c6: f105 0110 add.w r1, r5, #16 +100338ca: 4658 mov r0, fp +100338cc: f7dc ff9f bl 1001080e +100338d0: f105 0030 add.w r0, r5, #48 ; 0x30 +100338d4: 7840 ldrb r0, [r0, #1] +100338d6: b908 cbnz r0, 100338dc +100338d8: 73e0 strb r0, [r4, #15] +100338da: e008 b.n 100338ee +100338dc: 2801 cmp r0, #1 +100338de: bf08 it eq +100338e0: 73e0 strbeq r0, [r4, #15] +100338e2: d004 beq.n 100338ee +100338e4: 2803 cmp r0, #3 +100338e6: d103 bne.n 100338f0 +100338e8: 2001 movs r0, #1 +100338ea: 73e0 strb r0, [r4, #15] +100338ec: 2002 movs r0, #2 +100338ee: 7420 strb r0, [r4, #16] +100338f0: 2100 movs r1, #0 +100338f2: 4650 mov r0, sl +100338f4: f7dd f807 bl 10010906 +100338f8: 4638 mov r0, r7 +100338fa: e8bd 8ff2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, sl, fp, pc} + ... + +10033900 <.text_24>: +10033900: 1004807c .word 0x1004807c + +10033904 <.text_25>: +10033904: 1004882c .word 0x1004882c + +10033908 <.text_26>: +10033908: 100482dc .word 0x100482dc + +1003390c <.text_27>: +1003390c: 4629 mov r1, r5 +1003390e: f508 60be add.w r0, r8, #1520 ; 0x5f0 +10033912: f7dd b81a b.w 1001094a + ... + +10033918 : + ... + +10033920 : +10033920: b510 push {r4, lr} +10033922: f000 f996 bl 10033c52 <.text_19> +10033926: 6aa2 ldr r2, [r4, #40] ; 0x28 +10033928: 0492 lsls r2, r2, #18 +1003392a: f204 112d addw r1, r4, #301 ; 0x12d +1003392e: d519 bpl.n 10033964 +10033930: 7a82 ldrb r2, [r0, #10] +10033932: 2a01 cmp r2, #1 +10033934: d10d bne.n 10033952 +10033936: f894 10b3 ldrb.w r1, [r4, #179] ; 0xb3 +1003393a: b141 cbz r1, 1003394e +1003393c: 7a40 ldrb r0, [r0, #9] +1003393e: b9a8 cbnz r0, 1003396c +10033940: 4620 mov r0, r4 +10033942: f000 f84b bl 100339dc +10033946: 4620 mov r0, r4 +10033948: e8bd 4010 ldmia.w sp!, {r4, lr} +1003394c: e0d8 b.n 10033b00 +1003394e: 7241 strb r1, [r0, #9] +10033950: bd10 pop {r4, pc} +10033952: 2001 movs r0, #1 +10033954: 7088 strb r0, [r1, #2] +10033956: 6b20 ldr r0, [r4, #48] ; 0x30 +10033958: f400 5008 and.w r0, r0, #8704 ; 0x2200 +1003395c: 1e40 subs r0, r0, #1 +1003395e: 4180 sbcs r0, r0 +10033960: 0fc0 lsrs r0, r0, #31 +10033962: e001 b.n 10033968 +10033964: 2000 movs r0, #0 +10033966: 7088 strb r0, [r1, #2] +10033968: f884 012d strb.w r0, [r4, #301] ; 0x12d +1003396c: bd10 pop {r4, pc} + +1003396e : +1003396e: b510 push {r4, lr} +10033970: f000 f865 bl 10033a3e <.text_7> +10033974: d031 beq.n 100339da +10033976: f24c 3250 movw r2, #50000 ; 0xc350 +1003397a: f640 0196 movw r1, #2198 ; 0x896 +1003397e: 4620 mov r0, r4 +10033980: f7fd fadf bl 10030f42 +10033984: f64f 72ff movw r2, #65535 ; 0xffff +10033988: f640 0192 movw r1, #2194 ; 0x892 +1003398c: 4620 mov r0, r4 +1003398e: f7fd fad8 bl 10030f42 +10033992: f06f 02af mvn.w r2, #175 ; 0xaf +10033996: f640 0198 movw r1, #2200 ; 0x898 +1003399a: 4620 mov r0, r4 +1003399c: f7fd fad4 bl 10030f48 +100339a0: f04f 32ff mov.w r2, #4294967295 +100339a4: f640 019c movw r1, #2204 ; 0x89c +100339a8: 4620 mov r0, r4 +100339aa: f7fd facd bl 10030f48 +100339ae: 23ff movs r3, #255 ; 0xff +100339b0: 22ff movs r2, #255 ; 0xff +100339b2: f640 6128 movw r1, #3624 ; 0xe28 +100339b6: f000 f860 bl 10033a7a <.text_9+0x6> +100339ba: 2301 movs r3, #1 +100339bc: f44f 62e0 mov.w r2, #1792 ; 0x700 +100339c0: f44f 6109 mov.w r1, #2192 ; 0x890 +100339c4: f000 f859 bl 10033a7a <.text_9+0x6> +100339c8: 4620 mov r0, r4 +100339ca: e8bd 4010 ldmia.w sp!, {r4, lr} +100339ce: 2301 movs r3, #1 +100339d0: 2280 movs r2, #128 ; 0x80 +100339d2: f640 410c movw r1, #3084 ; 0xc0c +100339d6: f7fd babb b.w 10030f50 +100339da: bd10 pop {r4, pc} + +100339dc : +100339dc: b510 push {r4, lr} +100339de: 4604 mov r4, r0 +100339e0: 6aa0 ldr r0, [r4, #40] ; 0x28 +100339e2: 0400 lsls r0, r0, #16 +100339e4: d506 bpl.n 100339f4 +100339e6: 4620 mov r0, r4 +100339e8: f000 f805 bl 100339f6 +100339ec: 4620 mov r0, r4 +100339ee: e8bd 4010 ldmia.w sp!, {r4, lr} +100339f2: e010 b.n 10033a16 +100339f4: bd10 pop {r4, pc} + +100339f6 : +100339f6: b510 push {r4, lr} +100339f8: 4604 mov r4, r0 +100339fa: f04f 32ff mov.w r2, #4294967295 +100339fe: f640 01d8 movw r1, #2264 ; 0x8d8 +10033a02: f7fd faa9 bl 10030f58 +10033a06: b2c1 uxtb r1, r0 +10033a08: 0400 lsls r0, r0, #16 +10033a0a: f8a4 1124 strh.w r1, [r4, #292] ; 0x124 +10033a0e: 0e00 lsrs r0, r0, #24 +10033a10: f8a4 0126 strh.w r0, [r4, #294] ; 0x126 +10033a14: bd10 pop {r4, pc} + +10033a16 : +10033a16: b510 push {r4, lr} +10033a18: f000 f811 bl 10033a3e <.text_7> +10033a1c: d00e beq.n 10033a3c +10033a1e: 2300 movs r3, #0 +10033a20: 2202 movs r2, #2 +10033a22: f44f 6109 mov.w r1, #2192 ; 0x890 +10033a26: f000 f828 bl 10033a7a <.text_9+0x6> +10033a2a: 4620 mov r0, r4 +10033a2c: e8bd 4010 ldmia.w sp!, {r4, lr} +10033a30: 2301 movs r3, #1 +10033a32: 2202 movs r2, #2 +10033a34: f44f 6109 mov.w r1, #2192 ; 0x890 +10033a38: f7fd ba8a b.w 10030f50 +10033a3c: bd10 pop {r4, pc} + +10033a3e <.text_7>: +10033a3e: 4604 mov r4, r0 +10033a40: f242 119f movw r1, #8607 ; 0x219f +10033a44: 6b20 ldr r0, [r4, #48] ; 0x30 +10033a46: 4208 tst r0, r1 +10033a48: 4770 bx lr + +10033a4a : +10033a4a: b570 push {r4, r5, r6, lr} +10033a4c: f000 f818 bl 10033a80 <.text_11> +10033a50: d00f beq.n 10033a72 +10033a52: f640 464c movw r6, #3148 ; 0xc4c +10033a56: b2d3 uxtb r3, r2 +10033a58: 22ff movs r2, #255 ; 0xff +10033a5a: 4631 mov r1, r6 +10033a5c: f000 f80d bl 10033a7a <.text_9+0x6> +10033a60: b2eb uxtb r3, r5 +10033a62: 4631 mov r1, r6 +10033a64: 4620 mov r0, r4 +10033a66: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +10033a6a: f44f 027f mov.w r2, #16711680 ; 0xff0000 +10033a6e: f7fd ba6f b.w 10030f50 +10033a72: bd70 pop {r4, r5, r6, pc} + +10033a74 <.text_9>: +10033a74: 462b mov r3, r5 +10033a76: 220e movs r2, #14 +10033a78: 4639 mov r1, r7 +10033a7a: 4620 mov r0, r4 +10033a7c: f7fd ba68 b.w 10030f50 + +10033a80 <.text_11>: +10033a80: 4604 mov r4, r0 +10033a82: 460d mov r5, r1 +10033a84: 6b20 ldr r0, [r4, #48] ; 0x30 +10033a86: f242 119f movw r1, #8607 ; 0x219f +10033a8a: 4208 tst r0, r1 +10033a8c: 4770 bx lr + +10033a8e : +10033a8e: b538 push {r3, r4, r5, lr} +10033a90: 4604 mov r4, r0 +10033a92: f240 5524 movw r5, #1316 ; 0x524 +10033a96: b921 cbnz r1, 10033aa2 +10033a98: 2301 movs r3, #1 +10033a9a: f000 f80f bl 10033abc <.text_13> +10033a9e: 2300 movs r3, #0 +10033aa0: e003 b.n 10033aaa +10033aa2: 2300 movs r3, #0 +10033aa4: f000 f80a bl 10033abc <.text_13> +10033aa8: 2301 movs r3, #1 +10033aaa: 4629 mov r1, r5 +10033aac: 4620 mov r0, r4 +10033aae: b001 add sp, #4 +10033ab0: e8bd 4030 ldmia.w sp!, {r4, r5, lr} +10033ab4: f44f 6200 mov.w r2, #2048 ; 0x800 +10033ab8: f7fd ba49 b.w 10030f4e + +10033abc <.text_13>: +10033abc: f44f 4200 mov.w r2, #32768 ; 0x8000 +10033ac0: f44f 61a4 mov.w r1, #1312 ; 0x520 +10033ac4: f7fd ba43 b.w 10030f4e + +10033ac8 : +10033ac8: f500 7292 add.w r2, r0, #292 ; 0x124 +10033acc: f8b0 1124 ldrh.w r1, [r0, #292] ; 0x124 +10033ad0: 8853 ldrh r3, [r2, #2] +10033ad2: 185b adds r3, r3, r1 +10033ad4: b29b uxth r3, r3 +10033ad6: b14b cbz r3, 10033aec +10033ad8: 0209 lsls r1, r1, #8 +10033ada: fb91 f1f3 sdiv r1, r1, r3 +10033ade: f8a0 1124 strh.w r1, [r0, #292] ; 0x124 +10033ae2: 8851 ldrh r1, [r2, #2] +10033ae4: 0209 lsls r1, r1, #8 +10033ae6: fb91 f1f3 sdiv r1, r1, r3 +10033aea: 8051 strh r1, [r2, #2] +10033aec: f8b0 0124 ldrh.w r0, [r0, #292] ; 0x124 +10033af0: 8851 ldrh r1, [r2, #2] +10033af2: 1a40 subs r0, r0, r1 +10033af4: 2864 cmp r0, #100 ; 0x64 +10033af6: db01 blt.n 10033afc +10033af8: 2001 movs r0, #1 +10033afa: 4770 bx lr +10033afc: 2000 movs r0, #0 +10033afe: 4770 bx lr + +10033b00 : +10033b00: b570 push {r4, r5, r6, lr} +10033b02: 4605 mov r5, r0 +10033b04: 2102 movs r1, #2 +10033b06: f7fc fc2e bl 10030366 +10033b0a: 4604 mov r4, r0 +10033b0c: 7a20 ldrb r0, [r4, #8] +10033b0e: 2801 cmp r0, #1 +10033b10: d104 bne.n 10033b1c +10033b12: f000 f829 bl 10033b68 <.text_16> +10033b16: 2000 movs r0, #0 +10033b18: 7220 strb r0, [r4, #8] +10033b1a: bd70 pop {r4, r5, r6, pc} +10033b1c: 7960 ldrb r0, [r4, #5] +10033b1e: 2803 cmp r0, #3 +10033b20: da05 bge.n 10033b2e +10033b22: 1c40 adds r0, r0, #1 +10033b24: 7160 strb r0, [r4, #5] +10033b26: 4628 mov r0, r5 +10033b28: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +10033b2c: e756 b.n 100339dc +10033b2e: 4628 mov r0, r5 +10033b30: f7ff ff54 bl 100339dc +10033b34: f205 162d addw r6, r5, #301 ; 0x12d +10033b38: 4628 mov r0, r5 +10033b3a: f7ff ffc5 bl 10033ac8 +10033b3e: 2801 cmp r0, #1 +10033b40: d103 bne.n 10033b4a +10033b42: 70b0 strb r0, [r6, #2] +10033b44: f000 f810 bl 10033b68 <.text_16> +10033b48: e008 b.n 10033b5c +10033b4a: 227f movs r2, #127 ; 0x7f +10033b4c: 217f movs r1, #127 ; 0x7f +10033b4e: 4628 mov r0, r5 +10033b50: f7ff ff7b bl 10033a4a +10033b54: 2000 movs r0, #0 +10033b56: f885 012d strb.w r0, [r5, #301] ; 0x12d +10033b5a: 70b0 strb r0, [r6, #2] +10033b5c: 2000 movs r0, #0 +10033b5e: 7160 strb r0, [r4, #5] +10033b60: 2001 movs r0, #1 +10033b62: 7220 strb r0, [r4, #8] +10033b64: 7260 strb r0, [r4, #9] +10033b66: bd70 pop {r4, r5, r6, pc} + +10033b68 <.text_16>: +10033b68: 6b28 ldr r0, [r5, #48] ; 0x30 +10033b6a: f400 5008 and.w r0, r0, #8704 ; 0x2200 +10033b6e: 1e40 subs r0, r0, #1 +10033b70: 4180 sbcs r0, r0 +10033b72: 0fc0 lsrs r0, r0, #31 +10033b74: f885 012d strb.w r0, [r5, #301] ; 0x12d +10033b78: 4770 bx lr + +10033b7a : +10033b7a: b5f8 push {r3, r4, r5, r6, r7, lr} +10033b7c: f000 f869 bl 10033c52 <.text_19> +10033b80: 4605 mov r5, r0 +10033b82: 6820 ldr r0, [r4, #0] +10033b84: f641 1106 movw r1, #6406 ; 0x1906 +10033b88: 5c08 ldrb r0, [r1, r0] +10033b8a: b100 cbz r0, 10033b8e +10033b8c: 2001 movs r0, #1 +10033b8e: f504 7694 add.w r6, r4, #296 ; 0x128 +10033b92: f641 1108 movw r1, #6408 ; 0x1908 +10033b96: 70f0 strb r0, [r6, #3] +10033b98: 6820 ldr r0, [r4, #0] +10033b9a: 5c08 ldrb r0, [r1, r0] +10033b9c: 71b0 strb r0, [r6, #6] +10033b9e: f641 1107 movw r1, #6407 ; 0x1907 +10033ba2: 6820 ldr r0, [r4, #0] +10033ba4: 5c08 ldrb r0, [r1, r0] +10033ba6: b100 cbz r0, 10033baa +10033ba8: 2001 movs r0, #1 +10033baa: 72a8 strb r0, [r5, #10] +10033bac: f242 179f movw r7, #8607 ; 0x219f +10033bb0: 78f0 ldrb r0, [r6, #3] +10033bb2: b9b0 cbnz r0, 10033be2 +10033bb4: f06f 000a mvn.w r0, #10 +10033bb8: f884 0128 strb.w r0, [r4, #296] ; 0x128 +10033bbc: 6b20 ldr r0, [r4, #48] ; 0x30 +10033bbe: 4238 tst r0, r7 +10033bc0: d005 beq.n 10033bce +10033bc2: 2300 movs r3, #0 +10033bc4: f44f 7240 mov.w r2, #768 ; 0x300 +10033bc8: f640 414c movw r1, #3148 ; 0xc4c +10033bcc: e006 b.n 10033bdc +10033bce: f410 5fd3 tst.w r0, #6752 ; 0x1a60 +10033bd2: d009 beq.n 10033be8 +10033bd4: 2300 movs r3, #0 +10033bd6: 2203 movs r2, #3 +10033bd8: f44f 610a mov.w r1, #2208 ; 0x8a0 +10033bdc: f7ff ff4d bl 10033a7a <.text_9+0x6> +10033be0: e002 b.n 10033be8 +10033be2: 200a movs r0, #10 +10033be4: f884 0128 strb.w r0, [r4, #296] ; 0x128 +10033be8: 2007 movs r0, #7 +10033bea: 7070 strb r0, [r6, #1] +10033bec: 2101 movs r1, #1 +10033bee: 2000 movs r0, #0 +10033bf0: 7130 strb r0, [r6, #4] +10033bf2: 71f0 strb r0, [r6, #7] +10033bf4: 2032 movs r0, #50 ; 0x32 +10033bf6: 70e8 strb r0, [r5, #3] +10033bf8: 201c movs r0, #28 +10033bfa: 7128 strb r0, [r5, #4] +10033bfc: 2000 movs r0, #0 +10033bfe: 71a8 strb r0, [r5, #6] +10033c00: 71e8 strb r0, [r5, #7] +10033c02: 7168 strb r0, [r5, #5] +10033c04: 7268 strb r0, [r5, #9] +10033c06: 2001 movs r0, #1 +10033c08: 7228 strb r0, [r5, #8] +10033c0a: 4620 mov r0, r4 +10033c0c: f7ff ff3f bl 10033a8e +10033c10: 6b20 ldr r0, [r4, #48] ; 0x30 +10033c12: 4238 tst r0, r7 +10033c14: d007 beq.n 10033c26 +10033c16: f44f 7302 mov.w r3, #520 ; 0x208 +10033c1a: f04f 32ff mov.w r2, #4294967295 +10033c1e: f640 1108 movw r1, #2312 ; 0x908 +10033c22: f7ff ff2a bl 10033a7a <.text_9+0x6> +10033c26: 6b20 ldr r0, [r4, #48] ; 0x30 +10033c28: 0480 lsls r0, r0, #18 +10033c2a: d511 bpl.n 10033c50 +10033c2c: 2307 movs r3, #7 +10033c2e: f44f 52e0 mov.w r2, #7168 ; 0x1c00 +10033c32: f640 1148 movw r1, #2376 ; 0x948 +10033c36: f7ff ff20 bl 10033a7a <.text_9+0x6> +10033c3a: 4620 mov r0, r4 +10033c3c: b001 add sp, #4 +10033c3e: e8bd 40f0 ldmia.w sp!, {r4, r5, r6, r7, lr} +10033c42: 2301 movs r3, #1 +10033c44: f44f 1240 mov.w r2, #3145728 ; 0x300000 +10033c48: f640 6124 movw r1, #3620 ; 0xe24 +10033c4c: f7fd b980 b.w 10030f50 +10033c50: bdf1 pop {r0, r4, r5, r6, r7, pc} + +10033c52 <.text_19>: +10033c52: 4604 mov r4, r0 +10033c54: 2102 movs r1, #2 +10033c56: f7fc bb86 b.w 10030366 + +10033c5a : +10033c5a: b570 push {r4, r5, r6, lr} +10033c5c: f7ff fff9 bl 10033c52 <.text_19> +10033c60: 6aa1 ldr r1, [r4, #40] ; 0x28 +10033c62: 0489 lsls r1, r1, #18 +10033c64: d52f bpl.n 10033cc6 +10033c66: f104 0128 add.w r1, r4, #40 ; 0x28 +10033c6a: 6cca ldr r2, [r1, #76] ; 0x4c +10033c6c: f990 3003 ldrsb.w r3, [r0, #3] +10033c70: 7812 ldrb r2, [r2, #0] +10033c72: b112 cbz r2, 10033c7a +10033c74: 2a01 cmp r2, #1 +10033c76: bf08 it eq +10033c78: 1c9b addeq r3, r3, #2 +10033c7a: 7103 strb r3, [r0, #4] +10033c7c: 7a80 ldrb r0, [r0, #10] +10033c7e: 2801 cmp r0, #1 +10033c80: bf04 itt eq +10033c82: f894 20b3 ldrbeq.w r2, [r4, #179] ; 0xb3 +10033c86: 2a00 cmpeq r2, #0 +10033c88: d102 bne.n 10033c90 +10033c8a: f894 212f ldrb.w r2, [r4, #303] ; 0x12f +10033c8e: b12a cbz r2, 10033c9c +10033c90: 2801 cmp r0, #1 +10033c92: bf04 itt eq +10033c94: f894 012f ldrbeq.w r0, [r4, #303] ; 0x12f +10033c98: 2800 cmpeq r0, #0 +10033c9a: d102 bne.n 10033ca2 +10033c9c: 227f movs r2, #127 ; 0x7f +10033c9e: 217f movs r1, #127 ; 0x7f +10033ca0: e00d b.n 10033cbe +10033ca2: 6888 ldr r0, [r1, #8] +10033ca4: f410 5f08 tst.w r0, #8704 ; 0x2200 +10033ca8: d007 beq.n 10033cba +10033caa: f104 00b3 add.w r0, r4, #179 ; 0xb3 +10033cae: f890 1075 ldrb.w r1, [r0, #117] ; 0x75 +10033cb2: f890 0076 ldrb.w r0, [r0, #118] ; 0x76 +10033cb6: 185d adds r5, r3, r1 +10033cb8: 1a2e subs r6, r5, r0 +10033cba: b26a sxtb r2, r5 +10033cbc: b271 sxtb r1, r6 +10033cbe: 4620 mov r0, r4 +10033cc0: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +10033cc4: e6c1 b.n 10033a4a +10033cc6: bd70 pop {r4, r5, r6, pc} + +10033cc8 : +10033cc8: f8df f000 ldr.w pc, [pc] ; 10033ccc +10033ccc: 000187d5 .word 0x000187d5 + +10033cd0 : +10033cd0: f8df f000 ldr.w pc, [pc] ; 10033cd4 +10033cd4: 000187e9 .word 0x000187e9 + +10033cd8 : +10033cd8: f8df f000 ldr.w pc, [pc] ; 10033cdc +10033cdc: 00018811 .word 0x00018811 + +10033ce0 : +10033ce0: b538 push {r3, r4, r5, lr} +10033ce2: 4604 mov r4, r0 +10033ce4: 2101 movs r1, #1 +10033ce6: f7fc fb3e bl 10030366 +10033cea: 4605 mov r5, r0 +10033cec: 4620 mov r0, r4 +10033cee: f7ff ffeb bl 10033cc8 +10033cf2: 70e8 strb r0, [r5, #3] +10033cf4: 7128 strb r0, [r5, #4] +10033cf6: 2001 movs r0, #1 +10033cf8: 70a8 strb r0, [r5, #2] +10033cfa: 2014 movs r0, #20 +10033cfc: 77a8 strb r0, [r5, #30] +10033cfe: 200a movs r0, #10 +10033d00: 77e8 strb r0, [r5, #31] +10033d02: 2050 movs r0, #80 ; 0x50 +10033d04: f885 0020 strb.w r0, [r5, #32] +10033d08: bd31 pop {r0, r4, r5, pc} + +10033d0a : +10033d0a: 6a81 ldr r1, [r0, #40] ; 0x28 +10033d0c: 0449 lsls r1, r1, #17 +10033d0e: d50a bpl.n 10033d26 +10033d10: f890 10b3 ldrb.w r1, [r0, #179] ; 0xb3 +10033d14: 2900 cmp r1, #0 +10033d16: bf1a itte ne +10033d18: f890 10b8 ldrbne.w r1, [r0, #184] ; 0xb8 +10033d1c: 2900 cmpne r1, #0 +10033d1e: f7ff bfd7 beq.w 10033cd0 +10033d22: f7ff bfd9 b.w 10033cd8 +10033d26: 4770 bx lr + +10033d28 : +10033d28: b570 push {r4, r5, r6, lr} +10033d2a: 460d mov r5, r1 +10033d2c: 4604 mov r4, r0 +10033d2e: 4616 mov r6, r2 +10033d30: 2101 movs r1, #1 +10033d32: f7fc fb18 bl 10030366 +10033d36: 6aa1 ldr r1, [r4, #40] ; 0x28 +10033d38: 0449 lsls r1, r1, #17 +10033d3a: d50e bpl.n 10033d5a +10033d3c: 78a9 ldrb r1, [r5, #2] +10033d3e: b161 cbz r1, 10033d5a +10033d40: f996 1000 ldrsb.w r1, [r6] +10033d44: 6081 str r1, [r0, #8] +10033d46: f996 1001 ldrsb.w r1, [r6, #1] +10033d4a: 60c1 str r1, [r0, #12] +10033d4c: 6941 ldr r1, [r0, #20] +10033d4e: f111 0f01 cmn.w r1, #1 +10033d52: bf0c ite eq +10033d54: 2100 moveq r1, #0 +10033d56: 1c49 addne r1, r1, #1 +10033d58: 6141 str r1, [r0, #20] +10033d5a: bd70 pop {r4, r5, r6, pc} + +10033d5c : +10033d5c: e025 b.n 10033daa + +10033d5e : +10033d5e: b538 push {r3, r4, r5, lr} +10033d60: 6803 ldr r3, [r0, #0] +10033d62: 6b00 ldr r0, [r0, #48] ; 0x30 +10033d64: 2400 movs r4, #0 +10033d66: 2810 cmp r0, #16 +10033d68: bf18 it ne +10033d6a: f5b0 7f80 cmpne.w r0, #256 ; 0x100 +10033d6e: d004 beq.n 10033d7a +10033d70: 2880 cmp r0, #128 ; 0x80 +10033d72: bf18 it ne +10033d74: f5b0 5f00 cmpne.w r0, #8192 ; 0x2000 +10033d78: d112 bne.n 10033da0 +10033d7a: 4a5e ldr r2, [pc, #376] ; (10033ef4 <.text_7>) +10033d7c: f44f 6148 mov.w r1, #3200 ; 0xc80 +10033d80: 4618 mov r0, r3 +10033d82: f7f5 fc75 bl 10029670 +10033d86: 4601 mov r1, r0 +10033d88: f20f 1570 addw r5, pc, #368 ; 0x170 +10033d8c: 222b movs r2, #43 ; 0x2b +10033d8e: f855 0024 ldr.w r0, [r5, r4, lsl #2] +10033d92: f5b0 1f80 cmp.w r0, #1048576 ; 0x100000 +10033d96: bf28 it cs +10033d98: 0d80 lsrcs r0, r0, #22 +10033d9a: 4281 cmp r1, r0 +10033d9c: d003 beq.n 10033da6 +10033d9e: 1c64 adds r4, r4, #1 +10033da0: b2e4 uxtb r4, r4 +10033da2: 4294 cmp r4, r2 +10033da4: d3f3 bcc.n 10033d8e +10033da6: 4620 mov r0, r4 +10033da8: bd32 pop {r1, r4, r5, pc} + +10033daa : +10033daa: b538 push {r3, r4, r5, lr} +10033dac: 4604 mov r4, r0 +10033dae: f7ff ffd6 bl 10033d5e +10033db2: 6821 ldr r1, [r4, #0] +10033db4: f641 32a4 movw r2, #7076 ; 0x1ba4 +10033db8: 2301 movs r3, #1 +10033dba: 5851 ldr r1, [r2, r1] +10033dbc: f604 124c addw r2, r4, #2380 ; 0x94c +10033dc0: 7093 strb r3, [r2, #2] +10033dc2: 2300 movs r3, #0 +10033dc4: f884 394c strb.w r3, [r4, #2380] ; 0x94c +10033dc8: 7053 strb r3, [r2, #1] +10033dca: f8d4 30a0 ldr.w r3, [r4, #160] ; 0xa0 +10033dce: 781b ldrb r3, [r3, #0] +10033dd0: 1e5d subs r5, r3, #1 +10033dd2: 41ad sbcs r5, r5 +10033dd4: 0fed lsrs r5, r5, #31 +10033dd6: 70d5 strb r5, [r2, #3] +10033dd8: f891 305d ldrb.w r3, [r1, #93] ; 0x5d +10033ddc: 7253 strb r3, [r2, #9] +10033dde: f891 305d ldrb.w r3, [r1, #93] ; 0x5d +10033de2: 72d3 strb r3, [r2, #11] +10033de4: f891 105d ldrb.w r1, [r1, #93] ; 0x5d +10033de8: 7291 strb r1, [r2, #10] +10033dea: f604 710b addw r1, r4, #3851 ; 0xf0b +10033dee: 6b22 ldr r2, [r4, #48] ; 0x30 +10033df0: 2a10 cmp r2, #16 +10033df2: bf18 it ne +10033df4: f5b2 7f80 cmpne.w r2, #256 ; 0x100 +10033df8: d004 beq.n 10033e04 +10033dfa: 2a80 cmp r2, #128 ; 0x80 +10033dfc: bf18 it ne +10033dfe: f5b2 5f00 cmpne.w r2, #8192 ; 0x2000 +10033e02: d106 bne.n 10033e12 +10033e04: 282b cmp r0, #43 ; 0x2b +10033e06: bfa8 it ge +10033e08: 201e movge r0, #30 +10033e0a: f884 0f0b strb.w r0, [r4, #3851] ; 0xf0b +10033e0e: 2014 movs r0, #20 +10033e10: e005 b.n 10033e1e +10033e12: 2825 cmp r0, #37 ; 0x25 +10033e14: bfa8 it ge +10033e16: 2018 movge r0, #24 +10033e18: f884 0f0b strb.w r0, [r4, #3851] ; 0xf0b +10033e1c: 2018 movs r0, #24 +10033e1e: 7048 strb r0, [r1, #1] +10033e20: 2000 movs r0, #0 +10033e22: 1902 adds r2, r0, r4 +10033e24: 784b ldrb r3, [r1, #1] +10033e26: f882 3f09 strb.w r3, [r2, #3849] ; 0xf09 +10033e2a: 1c40 adds r0, r0, #1 +10033e2c: 784b ldrb r3, [r1, #1] +10033e2e: f882 3971 strb.w r3, [r2, #2417] ; 0x971 +10033e32: 2300 movs r3, #0 +10033e34: f882 3975 strb.w r3, [r2, #2421] ; 0x975 +10033e38: f882 3977 strb.w r3, [r2, #2423] ; 0x977 +10033e3c: f882 3973 strb.w r3, [r2, #2419] ; 0x973 +10033e40: f894 3f0b ldrb.w r3, [r4, #3851] ; 0xf0b +10033e44: f882 3f03 strb.w r3, [r2, #3843] ; 0xf03 +10033e48: f894 3f0b ldrb.w r3, [r4, #3851] ; 0xf0b +10033e4c: f882 3979 strb.w r3, [r2, #2425] ; 0x979 +10033e50: 2300 movs r3, #0 +10033e52: f882 397d strb.w r3, [r2, #2429] ; 0x97d +10033e56: f882 397f strb.w r3, [r2, #2431] ; 0x97f +10033e5a: 2802 cmp r0, #2 +10033e5c: f882 397b strb.w r3, [r2, #2427] ; 0x97b +10033e60: dbdf blt.n 10033e22 +10033e62: bd31 pop {r0, r4, r5, pc} + +10033e64 : +10033e64: f890 1025 ldrb.w r1, [r0, #37] ; 0x25 +10033e68: 2904 cmp r1, #4 +10033e6a: bf08 it eq +10033e6c: f000 b801 beq.w 10033e72 +10033e70: 4770 bx lr + +10033e72 : +10033e72: b510 push {r4, lr} +10033e74: 4604 mov r4, r0 +10033e76: b082 sub sp, #8 +10033e78: 6aa1 ldr r1, [r4, #40] ; 0x28 +10033e7a: 6820 ldr r0, [r4, #0] +10033e7c: 01c9 lsls r1, r1, #7 +10033e7e: d537 bpl.n 10033ef0 +10033e80: f894 1950 ldrb.w r1, [r4, #2384] ; 0x950 +10033e84: bb79 cbnz r1, 10033ee6 +10033e86: 8800 ldrh r0, [r0, #0] +10033e88: 2810 cmp r0, #16 +10033e8a: bf18 it ne +10033e8c: 2811 cmpne r0, #17 +10033e8e: d01b beq.n 10033ec8 +10033e90: 2812 cmp r0, #18 +10033e92: bf18 it ne +10033e94: 2816 cmpne r0, #22 +10033e96: d017 beq.n 10033ec8 +10033e98: 2817 cmp r0, #23 +10033e9a: bf18 it ne +10033e9c: 2819 cmpne r0, #25 +10033e9e: d013 beq.n 10033ec8 +10033ea0: 281a cmp r0, #26 +10033ea2: bf18 it ne +10033ea4: 2818 cmpne r0, #24 +10033ea6: d00f beq.n 10033ec8 +10033ea8: 281b cmp r0, #27 +10033eaa: bf18 it ne +10033eac: 2813 cmpne r0, #19 +10033eae: d00b beq.n 10033ec8 +10033eb0: 2814 cmp r0, #20 +10033eb2: bf18 it ne +10033eb4: 2815 cmpne r0, #21 +10033eb6: d007 beq.n 10033ec8 +10033eb8: 281c cmp r0, #28 +10033eba: bf18 it ne +10033ebc: 281d cmpne r0, #29 +10033ebe: d003 beq.n 10033ec8 +10033ec0: 281e cmp r0, #30 +10033ec2: bf18 it ne +10033ec4: 281f cmpne r0, #31 +10033ec6: d105 bne.n 10033ed4 +10033ec8: 2003 movs r0, #3 +10033eca: 9000 str r0, [sp, #0] +10033ecc: f44f 3340 mov.w r3, #196608 ; 0x30000 +10033ed0: 2242 movs r2, #66 ; 0x42 +10033ed2: e003 b.n 10033edc +10033ed4: 2060 movs r0, #96 ; 0x60 +10033ed6: 9000 str r0, [sp, #0] +10033ed8: 2224 movs r2, #36 ; 0x24 +10033eda: 4b07 ldr r3, [pc, #28] ; (10033ef8 <.text_8>) +10033edc: 4620 mov r0, r4 +10033ede: f7fd f83f bl 10030f60 +10033ee2: 2001 movs r0, #1 +10033ee4: e002 b.n 10033eec +10033ee6: f7fe fd85 bl 100329f4 +10033eea: 2000 movs r0, #0 +10033eec: f884 0950 strb.w r0, [r4, #2384] ; 0x950 +10033ef0: bd13 pop {r0, r1, r4, pc} + ... + +10033ef4 <.text_7>: +10033ef4: ffc00000 .word 0xffc00000 + +10033ef8 <.text_8>: +10033ef8: 000fffff .word 0x000fffff + +10033efc : +10033efc: 0b40002d 0c000030 0cc00033 0d800036 -.@.0...3...6... +10033f0c: 0e400039 0f00003c 10000040 11000044 9.@.<...@...D... +10033f1c: 12000048 1300004c 14400051 15800056 H...L...Q.@.V... +10033f2c: 16c0005b 18000060 19800066 1b00006c [...`...f...l... +10033f3c: 1c800072 1e400079 20000080 22000088 r...y.@.... ..." +10033f4c: 24000090 26000098 288000a2 2ac000ab ...$...&...(...* +10033f5c: 2d4000b5 300000c0 32c000cb 35c000d7 ..@-...0...2...5 +10033f6c: 390000e4 3c8000f2 40000100 43c0010f ...9...<...@...C +10033f7c: 47c0011f 4c000130 50800142 55400155 ...G0..LB..PU.@U +10033f8c: 5a400169 5fc0017f 65400195 6b8001ae i.@Z..._..@e...k +10033f9c: 71c001c7 788001e2 7f8001fe ...q...x.... + +10033fa8 : +10033fa8: 4803 ldr r0, [pc, #12] ; (10033fb8 ) +10033faa: 2200 movs r2, #0 +10033fac: e9c0 2202 strd r2, r2, [r0, #8] +10033fb0: 2104 movs r1, #4 +10033fb2: 6101 str r1, [r0, #16] +10033fb4: 4770 bx lr +10033fb6: bf00 nop +10033fb8: 10000720 .word 0x10000720 + +10033fbc <__iar_Strchr>: +10033fbc: 7802 ldrb r2, [r0, #0] +10033fbe: b2c9 uxtb r1, r1 +10033fc0: 428a cmp r2, r1 +10033fc2: b11a cbz r2, 10033fcc <__iar_Strchr+0x10> +10033fc4: bf1c itt ne +10033fc6: f810 2f01 ldrbne.w r2, [r0, #1]! +10033fca: e7f9 bne.n 10033fc0 <__iar_Strchr+0x4> +10033fcc: bf18 it ne +10033fce: 2000 movne r0, #0 +10033fd0: 4770 bx lr + +10033fd2 <__iar_Stolx>: +10033fd2: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +10033fd6: b082 sub sp, #8 +10033fd8: 4680 mov r8, r0 +10033fda: 000e movs r6, r1 +10033fdc: 461d mov r5, r3 +10033fde: bf08 it eq +10033fe0: ae00 addeq r6, sp, #0 +10033fe2: 4647 mov r7, r8 +10033fe4: e000 b.n 10033fe8 <__iar_Stolx+0x16> +10033fe6: 1c7f adds r7, r7, #1 +10033fe8: 7838 ldrb r0, [r7, #0] +10033fea: f1a0 0109 sub.w r1, r0, #9 +10033fee: 2905 cmp r1, #5 +10033ff0: d3f9 bcc.n 10033fe6 <__iar_Stolx+0x14> +10033ff2: 2820 cmp r0, #32 +10033ff4: d0f7 beq.n 10033fe6 <__iar_Stolx+0x14> +10033ff6: 282d cmp r0, #45 ; 0x2d +10033ff8: bf16 itet ne +10033ffa: 282b cmpne r0, #43 ; 0x2b +10033ffc: f817 4b01 ldrbeq.w r4, [r7], #1 +10034000: 242b movne r4, #43 ; 0x2b +10034002: 4631 mov r1, r6 +10034004: 4638 mov r0, r7 +10034006: f000 f827 bl 10034058 <__iar_Stoulx> +1003400a: 6831 ldr r1, [r6, #0] +1003400c: 428f cmp r7, r1 +1003400e: bf08 it eq +10034010: f8c6 8000 streq.w r8, [r6] +10034014: 6831 ldr r1, [r6, #0] +10034016: 4588 cmp r8, r1 +10034018: d114 bne.n 10034044 <__iar_Stolx+0x72> +1003401a: b920 cbnz r0, 10034026 <__iar_Stolx+0x54> +1003401c: 2c2d cmp r4, #45 ; 0x2d +1003401e: d116 bne.n 1003404e <__iar_Stolx+0x7c> +10034020: f1b0 4f00 cmp.w r0, #2147483648 ; 0x80000000 +10034024: d915 bls.n 10034052 <__iar_Stolx+0x80> +10034026: f7d1 ff5f bl 10005ee8 <__aeabi_errno_addr> +1003402a: 2122 movs r1, #34 ; 0x22 +1003402c: 6001 str r1, [r0, #0] +1003402e: b10d cbz r5, 10034034 <__iar_Stolx+0x62> +10034030: 2001 movs r0, #1 +10034032: 6028 str r0, [r5, #0] +10034034: 2c2d cmp r4, #45 ; 0x2d +10034036: bf14 ite ne +10034038: f06f 4000 mvnne.w r0, #2147483648 ; 0x80000000 +1003403c: f04f 4000 moveq.w r0, #2147483648 ; 0x80000000 +10034040: e8bd 81f6 ldmia.w sp!, {r1, r2, r4, r5, r6, r7, r8, pc} +10034044: 2c2b cmp r4, #43 ; 0x2b +10034046: d1e9 bne.n 1003401c <__iar_Stolx+0x4a> +10034048: f1b0 4f00 cmp.w r0, #2147483648 ; 0x80000000 +1003404c: d2eb bcs.n 10034026 <__iar_Stolx+0x54> +1003404e: e8bd 81f6 ldmia.w sp!, {r1, r2, r4, r5, r6, r7, r8, pc} +10034052: 4240 negs r0, r0 +10034054: e8bd 81f6 ldmia.w sp!, {r1, r2, r4, r5, r6, r7, r8, pc} + +10034058 <__iar_Stoulx>: +10034058: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +1003405c: b085 sub sp, #20 +1003405e: 4604 mov r4, r0 +10034060: 460d mov r5, r1 +10034062: 4690 mov r8, r2 +10034064: 001e movs r6, r3 +10034066: bf1c itt ne +10034068: 2000 movne r0, #0 +1003406a: 6030 strne r0, [r6, #0] +1003406c: 46a1 mov r9, r4 +1003406e: e001 b.n 10034074 <__iar_Stoulx+0x1c> +10034070: f109 0901 add.w r9, r9, #1 +10034074: f899 0000 ldrb.w r0, [r9] +10034078: f1a0 0109 sub.w r1, r0, #9 +1003407c: 2905 cmp r1, #5 +1003407e: d3f7 bcc.n 10034070 <__iar_Stoulx+0x18> +10034080: 2820 cmp r0, #32 +10034082: d0f5 beq.n 10034070 <__iar_Stoulx+0x18> +10034084: 282d cmp r0, #45 ; 0x2d +10034086: bf16 itet ne +10034088: 282b cmpne r0, #43 ; 0x2b +1003408a: f819 7b01 ldrbeq.w r7, [r9], #1 +1003408e: 272b movne r7, #43 ; 0x2b +10034090: f1b8 0f00 cmp.w r8, #0 +10034094: d457 bmi.n 10034146 <__iar_Stoulx+0xee> +10034096: f1b8 0f01 cmp.w r8, #1 +1003409a: d054 beq.n 10034146 <__iar_Stoulx+0xee> +1003409c: f1b8 0f25 cmp.w r8, #37 ; 0x25 +100340a0: da51 bge.n 10034146 <__iar_Stoulx+0xee> +100340a2: f1b8 0f01 cmp.w r8, #1 +100340a6: db0d blt.n 100340c4 <__iar_Stoulx+0x6c> +100340a8: f1b8 0f10 cmp.w r8, #16 +100340ac: bf04 itt eq +100340ae: f899 0000 ldrbeq.w r0, [r9] +100340b2: 2830 cmpeq r0, #48 ; 0x30 +100340b4: bf02 ittt eq +100340b6: f899 0001 ldrbeq.w r0, [r9, #1] +100340ba: f040 0020 orreq.w r0, r0, #32 +100340be: 2878 cmpeq r0, #120 ; 0x78 +100340c0: d114 bne.n 100340ec <__iar_Stoulx+0x94> +100340c2: e00e b.n 100340e2 <__iar_Stoulx+0x8a> +100340c4: f899 0000 ldrb.w r0, [r9] +100340c8: 2830 cmp r0, #48 ; 0x30 +100340ca: bf18 it ne +100340cc: f04f 080a movne.w r8, #10 +100340d0: d10c bne.n 100340ec <__iar_Stoulx+0x94> +100340d2: f899 0001 ldrb.w r0, [r9, #1] +100340d6: f040 0020 orr.w r0, r0, #32 +100340da: 2878 cmp r0, #120 ; 0x78 +100340dc: d104 bne.n 100340e8 <__iar_Stoulx+0x90> +100340de: f04f 0810 mov.w r8, #16 +100340e2: f109 0902 add.w r9, r9, #2 +100340e6: e001 b.n 100340ec <__iar_Stoulx+0x94> +100340e8: f04f 0808 mov.w r8, #8 +100340ec: f8cd 9010 str.w r9, [sp, #16] +100340f0: e001 b.n 100340f6 <__iar_Stoulx+0x9e> +100340f2: f109 0901 add.w r9, r9, #1 +100340f6: f899 0000 ldrb.w r0, [r9] +100340fa: 2830 cmp r0, #48 ; 0x30 +100340fc: d0f9 beq.n 100340f2 <__iar_Stoulx+0x9a> +100340fe: f20f 0ba4 addw fp, pc, #164 ; 0xa4 +10034102: f04f 0a00 mov.w sl, #0 +10034106: f8cd 900c str.w r9, [sp, #12] +1003410a: f88d b008 strb.w fp, [sp, #8] +1003410e: e00a b.n 10034126 <__iar_Stoulx+0xce> +10034110: f89d 1008 ldrb.w r1, [sp, #8] +10034114: f8cd a004 str.w sl, [sp, #4] +10034118: 1a40 subs r0, r0, r1 +1003411a: b2c0 uxtb r0, r0 +1003411c: 9000 str r0, [sp, #0] +1003411e: fb08 0a0a mla sl, r8, sl, r0 +10034122: f109 0901 add.w r9, r9, #1 +10034126: f899 1000 ldrb.w r1, [r9] +1003412a: f1a1 0041 sub.w r0, r1, #65 ; 0x41 +1003412e: 281a cmp r0, #26 +10034130: bf38 it cc +10034132: 3120 addcc r1, #32 +10034134: 4642 mov r2, r8 +10034136: 4658 mov r0, fp +10034138: f000 fbc4 bl 100348c4 <__iar_Memchr> +1003413c: 2800 cmp r0, #0 +1003413e: d1e7 bne.n 10034110 <__iar_Stoulx+0xb8> +10034140: 9804 ldr r0, [sp, #16] +10034142: 4548 cmp r0, r9 +10034144: d103 bne.n 1003414e <__iar_Stoulx+0xf6> +10034146: b105 cbz r5, 1003414a <__iar_Stoulx+0xf2> +10034148: 602c str r4, [r5, #0] +1003414a: 2000 movs r0, #0 +1003414c: e025 b.n 1003419a <.text_3> +1003414e: f20f 017c addw r1, pc, #124 ; 0x7c +10034152: 9803 ldr r0, [sp, #12] +10034154: f818 1001 ldrb.w r1, [r8, r1] +10034158: eba9 0000 sub.w r0, r9, r0 +1003415c: 1a40 subs r0, r0, r1 +1003415e: d414 bmi.n 1003418a <__iar_Stoulx+0x132> +10034160: 2801 cmp r0, #1 +10034162: da08 bge.n 10034176 <__iar_Stoulx+0x11e> +10034164: 9800 ldr r0, [sp, #0] +10034166: ebba 0000 subs.w r0, sl, r0 +1003416a: d304 bcc.n 10034176 <__iar_Stoulx+0x11e> +1003416c: 9901 ldr r1, [sp, #4] +1003416e: fbb0 f0f8 udiv r0, r0, r8 +10034172: 4288 cmp r0, r1 +10034174: d009 beq.n 1003418a <__iar_Stoulx+0x132> +10034176: f7d1 feb7 bl 10005ee8 <__aeabi_errno_addr> +1003417a: 2122 movs r1, #34 ; 0x22 +1003417c: 6001 str r1, [r0, #0] +1003417e: b10e cbz r6, 10034184 <__iar_Stoulx+0x12c> +10034180: 2001 movs r0, #1 +10034182: 6030 str r0, [r6, #0] +10034184: f04f 3aff mov.w sl, #4294967295 +10034188: e003 b.n 10034192 <__iar_Stoulx+0x13a> +1003418a: 2f2d cmp r7, #45 ; 0x2d +1003418c: bf08 it eq +1003418e: f1ca 0a00 rsbeq sl, sl, #0 +10034192: b10d cbz r5, 10034198 <__iar_Stoulx+0x140> +10034194: f8c5 9000 str.w r9, [r5] +10034198: 4650 mov r0, sl + +1003419a <.text_3>: +1003419a: b005 add sp, #20 +1003419c: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +100341a0 <__iar_Stoul>: +100341a0: 2300 movs r3, #0 +100341a2: e759 b.n 10034058 <__iar_Stoulx> + +100341a4 : +100341a4: 3130 3332 3534 3736 3938 6261 6463 6665 0123456789abcdef +100341b4: 6867 6a69 6c6b 6e6d 706f 7271 7473 7675 ghijklmnopqrstuv +100341c4: 7877 7a79 0000 0000 wxyz.... + +100341cc : +100341cc: 0000 1521 0e11 0c0d 0b0b 0a0a 0909 0909 ..!............. +100341dc: 0809 0808 0808 0808 0707 0707 0707 0707 ................ +100341ec: 0707 0707 0007 0000 ........ + +100341f4 : +100341f4: b510 push {r4, lr} +100341f6: 4604 mov r4, r0 +100341f8: 2105 movs r1, #5 +100341fa: f7ec fb86 bl 1002090a +100341fe: f000 02fb and.w r2, r0, #251 ; 0xfb +10034202: e006 b.n 10034212 <.text_4> + +10034204 : +10034204: b510 push {r4, lr} +10034206: 4604 mov r4, r0 +10034208: 2105 movs r1, #5 +1003420a: f7ec fb7e bl 1002090a +1003420e: f040 0204 orr.w r2, r0, #4 + +10034212 <.text_4>: +10034212: 4620 mov r0, r4 +10034214: e8bd 4010 ldmia.w sp!, {r4, lr} +10034218: 2105 movs r1, #5 +1003421a: f7ec bb7b b.w 10020914 + +1003421e : +1003421e: b510 push {r4, lr} +10034220: f641 31a4 movw r1, #7076 ; 0x1ba4 +10034224: 2200 movs r2, #0 +10034226: 5808 ldr r0, [r1, r0] +10034228: 2100 movs r1, #0 +1003422a: f642 1478 movw r4, #10616 ; 0x2978 +1003422e: 1813 adds r3, r2, r0 +10034230: 1c52 adds r2, r2, #1 +10034232: 5ce3 ldrb r3, [r4, r3] +10034234: 4319 orrs r1, r3 +10034236: 2a10 cmp r2, #16 +10034238: dbf9 blt.n 1003422e +1003423a: b101 cbz r1, 1003423e +1003423c: 2101 movs r1, #1 +1003423e: f642 1288 movw r2, #10632 ; 0x2988 +10034242: 5411 strb r1, [r2, r0] +10034244: bd10 pop {r4, pc} + +10034246 : +10034246: b570 push {r4, r5, r6, lr} +10034248: 4603 mov r3, r0 +1003424a: 4608 mov r0, r1 +1003424c: f641 31a4 movw r1, #7076 ; 0x1ba4 +10034250: f000 0407 and.w r4, r0, #7 +10034254: 58c9 ldr r1, [r1, r3] +10034256: eb01 01d0 add.w r1, r1, r0, lsr #3 +1003425a: f642 1378 movw r3, #10616 ; 0x2978 +1003425e: 2601 movs r6, #1 +10034260: 5c5d ldrb r5, [r3, r1] +10034262: fa06 f404 lsl.w r4, r6, r4 +10034266: b92a cbnz r2, 10034274 +10034268: ea25 0204 bic.w r2, r5, r4 +1003426c: 545a strb r2, [r3, r1] +1003426e: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +10034272: e7c7 b.n 10034204 +10034274: ea44 0205 orr.w r2, r4, r5 +10034278: 545a strb r2, [r3, r1] +1003427a: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +1003427e: e7b9 b.n 100341f4 + +10034280 : +10034280: b5f8 push {r3, r4, r5, r6, r7, lr} +10034282: 460d mov r5, r1 +10034284: 4604 mov r4, r0 +10034286: 786e ldrb r6, [r5, #1] +10034288: 7828 ldrb r0, [r5, #0] +1003428a: 4637 mov r7, r6 +1003428c: f3c0 0040 ubfx r0, r0, #1, #1 +10034290: b148 cbz r0, 100342a6 +10034292: 78ae ldrb r6, [r5, #2] +10034294: e007 b.n 100342a6 +10034296: 7828 ldrb r0, [r5, #0] +10034298: f000 0201 and.w r2, r0, #1 +1003429c: 4639 mov r1, r7 +1003429e: 4620 mov r0, r4 +100342a0: f7ff ffd1 bl 10034246 +100342a4: 1c7f adds r7, r7, #1 +100342a6: b2ff uxtb r7, r7 +100342a8: 42be cmp r6, r7 +100342aa: daf4 bge.n 10034296 +100342ac: 4620 mov r0, r4 +100342ae: e8bd 40f2 ldmia.w sp!, {r1, r4, r5, r6, r7, lr} +100342b2: e7b4 b.n 1003421e + +100342b4 : +100342b4: b5f0 push {r4, r5, r6, r7, lr} +100342b6: 4818 ldr r0, [pc, #96] ; (10034318 <.text_9>) +100342b8: 4a18 ldr r2, [pc, #96] ; (1003431c <.text_10>) +100342ba: 6800 ldr r0, [r0, #0] +100342bc: 784d ldrb r5, [r1, #1] +100342be: 4b18 ldr r3, [pc, #96] ; (10034320 <.text_11>) +100342c0: f240 7487 movw r4, #1927 ; 0x787 +100342c4: b195 cbz r5, 100342ec +100342c6: 182e adds r6, r5, r0 +100342c8: 688f ldr r7, [r1, #8] +100342ca: 801c strh r4, [r3, #0] +100342cc: 06f6 lsls r6, r6, #27 +100342ce: 0d36 lsrs r6, r6, #20 +100342d0: eb07 15c5 add.w r5, r7, r5, lsl #7 +100342d4: f506 4600 add.w r6, r6, #32768 ; 0x8000 +100342d8: 2700 movs r7, #0 +100342da: f855 c027 ldr.w ip, [r5, r7, lsl #2] +100342de: eb06 0e87 add.w lr, r6, r7, lsl #2 +100342e2: 1c7f adds r7, r7, #1 +100342e4: f842 c00e str.w ip, [r2, lr] +100342e8: 2f0e cmp r7, #14 +100342ea: d3f6 bcc.n 100342da +100342ec: 788d ldrb r5, [r1, #2] +100342ee: b18d cbz r5, 10034314 +100342f0: 1828 adds r0, r5, r0 +100342f2: 06c0 lsls r0, r0, #27 +100342f4: 0d00 lsrs r0, r0, #20 +100342f6: f500 4600 add.w r6, r0, #32768 ; 0x8000 +100342fa: 6888 ldr r0, [r1, #8] +100342fc: 801c strh r4, [r3, #0] +100342fe: eb00 15c5 add.w r5, r0, r5, lsl #7 +10034302: 2700 movs r7, #0 +10034304: f855 0027 ldr.w r0, [r5, r7, lsl #2] +10034308: eb06 0187 add.w r1, r6, r7, lsl #2 +1003430c: 1c7f adds r7, r7, #1 +1003430e: 5050 str r0, [r2, r1] +10034310: 2f10 cmp r7, #16 +10034312: d3f7 bcc.n 10034304 +10034314: bdf0 pop {r4, r5, r6, r7, pc} + ... + +10034318 <.text_9>: +10034318: 40080424 .word 0x40080424 + +1003431c <.text_10>: +1003431c: 40080000 .word 0x40080000 + +10034320 <.text_11>: +10034320: 40080140 .word 0x40080140 + +10034324 : +10034324: b580 push {r7, lr} +10034326: b1c1 cbz r1, 1003435a +10034328: 2901 cmp r1, #1 +1003432a: d004 beq.n 10034336 +1003432c: 2920 cmp r1, #32 +1003432e: d010 beq.n 10034352 +10034330: 2940 cmp r1, #64 ; 0x40 +10034332: d004 beq.n 1003433e +10034334: e014 b.n 10034360 +10034336: 4611 mov r1, r2 +10034338: f7ff ffa2 bl 10034280 +1003433c: e010 b.n 10034360 +1003433e: 4611 mov r1, r2 +10034340: f641 32a4 movw r2, #7076 ; 0x1ba4 +10034344: 5810 ldr r0, [r2, r0] +10034346: f500 50c8 add.w r0, r0, #6400 ; 0x1900 +1003434a: 30a8 adds r0, #168 ; 0xa8 +1003434c: f7ed fef8 bl 10022140 +10034350: e006 b.n 10034360 +10034352: 4611 mov r1, r2 +10034354: f7df f82b bl 100133ae +10034358: e002 b.n 10034360 +1003435a: 4611 mov r1, r2 +1003435c: f7ff ffaa bl 100342b4 +10034360: 2000 movs r0, #0 +10034362: bd02 pop {r1, pc} + +10034364 <__aeabi_llsr>: +10034364: b2d2 uxtb r2, r2 +10034366: 3a20 subs r2, #32 +10034368: bf22 ittt cs +1003436a: fa21 f002 lsrcs.w r0, r1, r2 +1003436e: 2100 movcs r1, #0 +10034370: 4770 bxcs lr +10034372: 3220 adds r2, #32 +10034374: 41d1 rors r1, r2 +10034376: 40d0 lsrs r0, r2 +10034378: 4048 eors r0, r1 +1003437a: 4091 lsls r1, r2 +1003437c: 40d1 lsrs r1, r2 +1003437e: 4048 eors r0, r1 +10034380: 4770 bx lr + ... + +10034384 : +10034384: b5f0 push {r4, r5, r6, r7, lr} +10034386: f100 0325 add.w r3, r0, #37 ; 0x25 +1003438a: 79dd ldrb r5, [r3, #7] +1003438c: f890 0025 ldrb.w r0, [r0, #37] ; 0x25 +10034390: 7cdc ldrb r4, [r3, #19] +10034392: 7bde ldrb r6, [r3, #15] +10034394: f005 07f0 and.w r7, r5, #240 ; 0xf0 +10034398: 4338 orrs r0, r7 +1003439a: 0400 lsls r0, r0, #16 +1003439c: ea40 6006 orr.w r0, r0, r6, lsl #24 +100343a0: 7d1e ldrb r6, [r3, #20] +100343a2: ea40 3006 orr.w r0, r0, r6, lsl #12 +100343a6: f005 050f and.w r5, r5, #15 +100343aa: ea40 2005 orr.w r0, r0, r5, lsl #8 +100343ae: 08a6 lsrs r6, r4, #2 +100343b0: f3c4 1500 ubfx r5, r4, #4, #1 +100343b4: f006 0602 and.w r6, r6, #2 +100343b8: 4335 orrs r5, r6 +100343ba: 09e6 lsrs r6, r4, #7 +100343bc: ea45 0586 orr.w r5, r5, r6, lsl #2 +100343c0: 08e6 lsrs r6, r4, #3 +100343c2: f006 0608 and.w r6, r6, #8 +100343c6: 00a4 lsls r4, r4, #2 +100343c8: 4335 orrs r5, r6 +100343ca: f004 0410 and.w r4, r4, #16 +100343ce: 432c orrs r4, r5 +100343d0: 4320 orrs r0, r4 +100343d2: 7d5c ldrb r4, [r3, #21] +100343d4: 7d9d ldrb r5, [r3, #22] +100343d6: ea44 2405 orr.w r4, r4, r5, lsl #8 +100343da: 7ddd ldrb r5, [r3, #23] +100343dc: 7e1b ldrb r3, [r3, #24] +100343de: ea44 4405 orr.w r4, r4, r5, lsl #16 +100343e2: ea44 6303 orr.w r3, r4, r3, lsl #24 +100343e6: f411 4f70 tst.w r1, #61440 ; 0xf000 +100343ea: bf1e ittt ne +100343ec: f401 4470 andne.w r4, r1, #61440 ; 0xf000 +100343f0: f400 4570 andne.w r5, r0, #61440 ; 0xf000 +100343f4: 42ac cmpne r4, r5 +100343f6: d127 bne.n 10034448 +100343f8: f011 6f70 tst.w r1, #251658240 ; 0xf000000 +100343fc: bf1e ittt ne +100343fe: f001 6470 andne.w r4, r1, #251658240 ; 0xf000000 +10034402: f000 6570 andne.w r5, r0, #251658240 ; 0xf000000 +10034406: 42ac cmpne r4, r5 +10034408: bf01 itttt eq +1003440a: 4c61 ldreq r4, [pc, #388] ; (10034590 <.text_33>) +1003440c: 4021 andeq r1, r4 +1003440e: 4008 andeq r0, r1 +10034410: 4288 cmpeq r0, r1 +10034412: d119 bne.n 10034448 +10034414: 2000 movs r0, #0 +10034416: f011 0f0f tst.w r1, #15 +1003441a: d013 beq.n 10034444 +1003441c: 07cc lsls r4, r1, #31 +1003441e: bf48 it mi +10034420: 20ff movmi r0, #255 ; 0xff +10034422: 078c lsls r4, r1, #30 +10034424: bf48 it mi +10034426: f440 407f orrmi.w r0, r0, #65280 ; 0xff00 +1003442a: 074c lsls r4, r1, #29 +1003442c: bf48 it mi +1003442e: f440 007f orrmi.w r0, r0, #16711680 ; 0xff0000 +10034432: 0709 lsls r1, r1, #28 +10034434: bf48 it mi +10034436: f040 407f orrmi.w r0, r0, #4278190080 ; 0xff000000 +1003443a: ea00 0102 and.w r1, r0, r2 +1003443e: 4018 ands r0, r3 +10034440: 4281 cmp r1, r0 +10034442: d101 bne.n 10034448 +10034444: 2001 movs r0, #1 +10034446: bdf0 pop {r4, r5, r6, r7, pc} +10034448: 2000 movs r0, #0 +1003444a: bdf0 pop {r4, r5, r6, r7, pc} + +1003444c : +1003444c: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +10034450: 4604 mov r4, r0 +10034452: 2500 movs r5, #0 +10034454: 2701 movs r7, #1 +10034456: 2600 movs r6, #0 +10034458: f8df 8138 ldr.w r8, [pc, #312] ; 10034594 <.text_34> +1003445c: f000 f823 bl 100344a6 <.text_26> +10034460: d017 beq.n 10034492 +10034462: d51a bpl.n 1003449a +10034464: 0f08 lsrs r0, r1, #28 +10034466: f000 0003 and.w r0, r0, #3 +1003446a: 2803 cmp r0, #3 +1003446c: d102 bne.n 10034474 +1003446e: 2701 movs r7, #1 +10034470: 2600 movs r6, #0 +10034472: e012 b.n 1003449a +10034474: 2802 cmp r0, #2 +10034476: bf08 it eq +10034478: f086 0701 eoreq.w r7, r6, #1 +1003447c: d00d beq.n 1003449a +1003447e: b936 cbnz r6, 1003448e +10034480: 4620 mov r0, r4 +10034482: f7ff ff7f bl 10034384 +10034486: b110 cbz r0, 1003448e +10034488: 2701 movs r7, #1 +1003448a: 2601 movs r6, #1 +1003448c: e005 b.n 1003449a +1003448e: 2700 movs r7, #0 +10034490: e003 b.n 1003449a +10034492: b117 cbz r7, 1003449a +10034494: 4620 mov r0, r4 +10034496: f000 fa59 bl 1003494c +1003449a: 1cad adds r5, r5, #2 +1003449c: 1c68 adds r0, r5, #1 +1003449e: 28e6 cmp r0, #230 ; 0xe6 +100344a0: d3dc bcc.n 1003445c +100344a2: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +100344a6 <.text_26>: +100344a6: f858 1025 ldr.w r1, [r8, r5, lsl #2] +100344aa: eb08 0085 add.w r0, r8, r5, lsl #2 +100344ae: f011 4f40 tst.w r1, #3221225472 ; 0xc0000000 +100344b2: 6842 ldr r2, [r0, #4] +100344b4: 4770 bx lr + +100344b6 : +100344b6: b570 push {r4, r5, r6, lr} +100344b8: 4604 mov r4, r0 +100344ba: f604 1538 addw r5, r4, #2360 ; 0x938 +100344be: 4e36 ldr r6, [pc, #216] ; (10034598 <.text_35>) +100344c0: e004 b.n 100344cc <.text_30> + +100344c2 : +100344c2: b570 push {r4, r5, r6, lr} +100344c4: 4604 mov r4, r0 +100344c6: f604 1538 addw r5, r4, #2360 ; 0x938 +100344ca: 4e34 ldr r6, [pc, #208] ; (1003459c <.text_36>) + +100344cc <.text_30>: +100344cc: 231e movs r3, #30 +100344ce: f106 0260 add.w r2, r6, #96 ; 0x60 +100344d2: f205 313f addw r1, r5, #831 ; 0x33f +100344d6: f7fc fd4e bl 10030f76 +100344da: 231e movs r3, #30 +100344dc: f106 0240 add.w r2, r6, #64 ; 0x40 +100344e0: f205 315d addw r1, r5, #861 ; 0x35d +100344e4: 4620 mov r0, r4 +100344e6: f7fc fd46 bl 10030f76 +100344ea: 231e movs r3, #30 +100344ec: f106 0220 add.w r2, r6, #32 +100344f0: f205 317b addw r1, r5, #891 ; 0x37b +100344f4: 4620 mov r0, r4 +100344f6: f7fc fd3e bl 10030f76 +100344fa: 231e movs r3, #30 +100344fc: 4632 mov r2, r6 +100344fe: f205 3199 addw r1, r5, #921 ; 0x399 +10034502: 4620 mov r0, r4 +10034504: f7fc fd37 bl 10030f76 +10034508: 231e movs r3, #30 +1003450a: f106 02e0 add.w r2, r6, #224 ; 0xe0 +1003450e: f205 214f addw r1, r5, #591 ; 0x24f +10034512: 4620 mov r0, r4 +10034514: f7fc fd2f bl 10030f76 +10034518: 231e movs r3, #30 +1003451a: f106 02c0 add.w r2, r6, #192 ; 0xc0 +1003451e: f205 216d addw r1, r5, #621 ; 0x26d +10034522: 4620 mov r0, r4 +10034524: f7fc fd27 bl 10030f76 +10034528: 231e movs r3, #30 +1003452a: f106 02a0 add.w r2, r6, #160 ; 0xa0 +1003452e: f205 218b addw r1, r5, #651 ; 0x28b +10034532: 4620 mov r0, r4 +10034534: f7fc fd1f bl 10030f76 +10034538: f106 0280 add.w r2, r6, #128 ; 0x80 +1003453c: f205 21a9 addw r1, r5, #681 ; 0x2a9 +10034540: 4620 mov r0, r4 +10034542: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +10034546: 231e movs r3, #30 +10034548: f7fc bd15 b.w 10030f76 + +1003454c : +1003454c: b570 push {r4, r5, r6, lr} +1003454e: 4604 mov r4, r0 +10034550: f604 1538 addw r5, r4, #2360 ; 0x938 +10034554: 4e12 ldr r6, [pc, #72] ; (100345a0 <.text_37>) +10034556: e7b9 b.n 100344cc <.text_30> + +10034558 : +10034558: b57f push {r0, r1, r2, r3, r4, r5, r6, lr} +1003455a: 4604 mov r4, r0 +1003455c: 2500 movs r5, #0 +1003455e: 4e11 ldr r6, [pc, #68] ; (100345a4 <.text_38>) +10034560: eb06 0085 add.w r0, r6, r5, lsl #2 +10034564: 6981 ldr r1, [r0, #24] +10034566: 9103 str r1, [sp, #12] +10034568: 6941 ldr r1, [r0, #20] +1003456a: 9102 str r1, [sp, #8] +1003456c: 6901 ldr r1, [r0, #16] +1003456e: 9101 str r1, [sp, #4] +10034570: 68c1 ldr r1, [r0, #12] +10034572: 9100 str r1, [sp, #0] +10034574: 6883 ldr r3, [r0, #8] +10034576: 6842 ldr r2, [r0, #4] +10034578: f856 1025 ldr.w r1, [r6, r5, lsl #2] +1003457c: 4620 mov r0, r4 +1003457e: f000 fa2d bl 100349dc +10034582: 1ded adds r5, r5, #7 +10034584: f5b5 6f93 cmp.w r5, #1176 ; 0x498 +10034588: d3ea bcc.n 10034560 +1003458a: bd7f pop {r0, r1, r2, r3, r4, r5, r6, pc} +1003458c: 0000 movs r0, r0 + ... + +10034590 <.text_33>: +10034590: 00ff0fff .word 0x00ff0fff + +10034594 <.text_34>: +10034594: 10045540 .word 0x10045540 + +10034598 <.text_35>: +10034598: 100458d8 .word 0x100458d8 + +1003459c <.text_36>: +1003459c: 100459d8 .word 0x100459d8 + +100345a0 <.text_37>: +100345a0: 10045ad8 .word 0x10045ad8 + +100345a4 <.text_38>: +100345a4: 10045bd8 .word 0x10045bd8 + +100345a8 : +100345a8: b5f0 push {r4, r5, r6, r7, lr} +100345aa: f100 0325 add.w r3, r0, #37 ; 0x25 +100345ae: 79dd ldrb r5, [r3, #7] +100345b0: f890 0025 ldrb.w r0, [r0, #37] ; 0x25 +100345b4: 7cdc ldrb r4, [r3, #19] +100345b6: 7bde ldrb r6, [r3, #15] +100345b8: f005 07f0 and.w r7, r5, #240 ; 0xf0 +100345bc: 4338 orrs r0, r7 +100345be: 0400 lsls r0, r0, #16 +100345c0: ea40 6006 orr.w r0, r0, r6, lsl #24 +100345c4: 7d1e ldrb r6, [r3, #20] +100345c6: ea40 3006 orr.w r0, r0, r6, lsl #12 +100345ca: f005 050f and.w r5, r5, #15 +100345ce: ea40 2005 orr.w r0, r0, r5, lsl #8 +100345d2: 08a6 lsrs r6, r4, #2 +100345d4: f3c4 1500 ubfx r5, r4, #4, #1 +100345d8: f006 0602 and.w r6, r6, #2 +100345dc: 4335 orrs r5, r6 +100345de: 09e6 lsrs r6, r4, #7 +100345e0: ea45 0586 orr.w r5, r5, r6, lsl #2 +100345e4: 08e6 lsrs r6, r4, #3 +100345e6: f006 0608 and.w r6, r6, #8 +100345ea: 00a4 lsls r4, r4, #2 +100345ec: 4335 orrs r5, r6 +100345ee: f004 0410 and.w r4, r4, #16 +100345f2: 432c orrs r4, r5 +100345f4: 4320 orrs r0, r4 +100345f6: 7d5c ldrb r4, [r3, #21] +100345f8: 7d9d ldrb r5, [r3, #22] +100345fa: ea44 2405 orr.w r4, r4, r5, lsl #8 +100345fe: 7ddd ldrb r5, [r3, #23] +10034600: 7e1b ldrb r3, [r3, #24] +10034602: ea44 4405 orr.w r4, r4, r5, lsl #16 +10034606: ea44 6303 orr.w r3, r4, r3, lsl #24 +1003460a: f411 4f70 tst.w r1, #61440 ; 0xf000 +1003460e: bf1e ittt ne +10034610: f401 4470 andne.w r4, r1, #61440 ; 0xf000 +10034614: f400 4570 andne.w r5, r0, #61440 ; 0xf000 +10034618: 42ac cmpne r4, r5 +1003461a: d127 bne.n 1003466c +1003461c: f011 6f70 tst.w r1, #251658240 ; 0xf000000 +10034620: bf1e ittt ne +10034622: f001 6470 andne.w r4, r1, #251658240 ; 0xf000000 +10034626: f000 6570 andne.w r5, r0, #251658240 ; 0xf000000 +1003462a: 42ac cmpne r4, r5 +1003462c: bf01 itttt eq +1003462e: 4c53 ldreq r4, [pc, #332] ; (1003477c <.text_12>) +10034630: 4021 andeq r1, r4 +10034632: 4008 andeq r0, r1 +10034634: 4288 cmpeq r0, r1 +10034636: d119 bne.n 1003466c +10034638: 2000 movs r0, #0 +1003463a: f011 0f0f tst.w r1, #15 +1003463e: d013 beq.n 10034668 +10034640: 07cc lsls r4, r1, #31 +10034642: bf48 it mi +10034644: 20ff movmi r0, #255 ; 0xff +10034646: 078c lsls r4, r1, #30 +10034648: bf48 it mi +1003464a: f440 407f orrmi.w r0, r0, #65280 ; 0xff00 +1003464e: 074c lsls r4, r1, #29 +10034650: bf48 it mi +10034652: f440 007f orrmi.w r0, r0, #16711680 ; 0xff0000 +10034656: 0709 lsls r1, r1, #28 +10034658: bf48 it mi +1003465a: f040 407f orrmi.w r0, r0, #4278190080 ; 0xff000000 +1003465e: ea00 0102 and.w r1, r0, r2 +10034662: 4018 ands r0, r3 +10034664: 4281 cmp r1, r0 +10034666: d101 bne.n 1003466c +10034668: 2001 movs r0, #1 +1003466a: bdf0 pop {r4, r5, r6, r7, pc} +1003466c: 2000 movs r0, #0 +1003466e: bdf0 pop {r4, r5, r6, r7, pc} + +10034670 : +10034670: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +10034674: 4604 mov r4, r0 +10034676: 2500 movs r5, #0 +10034678: 2701 movs r7, #1 +1003467a: 2600 movs r6, #0 +1003467c: f8df 8100 ldr.w r8, [pc, #256] ; 10034780 <.text_13> +10034680: f000 f858 bl 10034734 <.text_9> +10034684: d017 beq.n 100346b6 +10034686: d51d bpl.n 100346c4 +10034688: 0f08 lsrs r0, r1, #28 +1003468a: f000 0003 and.w r0, r0, #3 +1003468e: 2803 cmp r0, #3 +10034690: d102 bne.n 10034698 +10034692: 2701 movs r7, #1 +10034694: 2600 movs r6, #0 +10034696: e015 b.n 100346c4 +10034698: 2802 cmp r0, #2 +1003469a: bf08 it eq +1003469c: f086 0701 eoreq.w r7, r6, #1 +100346a0: d010 beq.n 100346c4 +100346a2: b936 cbnz r6, 100346b2 +100346a4: 4620 mov r0, r4 +100346a6: f7ff ff7f bl 100345a8 +100346aa: b110 cbz r0, 100346b2 +100346ac: 2701 movs r7, #1 +100346ae: 2601 movs r6, #1 +100346b0: e008 b.n 100346c4 +100346b2: 2700 movs r7, #0 +100346b4: e006 b.n 100346c4 +100346b6: b12f cbz r7, 100346c4 +100346b8: 4613 mov r3, r2 +100346ba: f04f 32ff mov.w r2, #4294967295 +100346be: 4620 mov r0, r4 +100346c0: f000 f94d bl 1003495e +100346c4: 1cad adds r5, r5, #2 +100346c6: 1c68 adds r0, r5, #1 +100346c8: f5b0 7fc8 cmp.w r0, #400 ; 0x190 +100346cc: d3d8 bcc.n 10034680 +100346ce: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +100346d2 : +100346d2: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +100346d6: 4604 mov r4, r0 +100346d8: 2500 movs r5, #0 +100346da: 2701 movs r7, #1 +100346dc: 2600 movs r6, #0 +100346de: f8df 80a4 ldr.w r8, [pc, #164] ; 10034784 <.text_14> +100346e2: f000 f827 bl 10034734 <.text_9> +100346e6: d017 beq.n 10034718 +100346e8: d51d bpl.n 10034726 +100346ea: 0f08 lsrs r0, r1, #28 +100346ec: f000 0003 and.w r0, r0, #3 +100346f0: 2803 cmp r0, #3 +100346f2: d102 bne.n 100346fa +100346f4: 2701 movs r7, #1 +100346f6: 2600 movs r6, #0 +100346f8: e015 b.n 10034726 +100346fa: 2802 cmp r0, #2 +100346fc: bf08 it eq +100346fe: f086 0701 eoreq.w r7, r6, #1 +10034702: d010 beq.n 10034726 +10034704: b936 cbnz r6, 10034714 +10034706: 4620 mov r0, r4 +10034708: f7ff ff4e bl 100345a8 +1003470c: b110 cbz r0, 10034714 +1003470e: 2701 movs r7, #1 +10034710: 2601 movs r6, #1 +10034712: e008 b.n 10034726 +10034714: 2700 movs r7, #0 +10034716: e006 b.n 10034726 +10034718: b12f cbz r7, 10034726 +1003471a: 4613 mov r3, r2 +1003471c: f04f 32ff mov.w r2, #4294967295 +10034720: 4620 mov r0, r4 +10034722: f000 f937 bl 10034994 +10034726: 1cad adds r5, r5, #2 +10034728: 1c68 adds r0, r5, #1 +1003472a: f5b0 7fcf cmp.w r0, #414 ; 0x19e +1003472e: d3d8 bcc.n 100346e2 +10034730: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +10034734 <.text_9>: +10034734: f858 1025 ldr.w r1, [r8, r5, lsl #2] +10034738: eb08 0085 add.w r0, r8, r5, lsl #2 +1003473c: f011 4f40 tst.w r1, #3221225472 ; 0xc0000000 +10034740: 6842 ldr r2, [r0, #4] +10034742: 4770 bx lr + +10034744 : +10034744: b570 push {r4, r5, r6, lr} +10034746: 4604 mov r4, r0 +10034748: b084 sub sp, #16 +1003474a: 2001 movs r0, #1 +1003474c: 7420 strb r0, [r4, #16] +1003474e: 2500 movs r5, #0 +10034750: 60e0 str r0, [r4, #12] +10034752: 4e0d ldr r6, [pc, #52] ; (10034788 <.text_15>) +10034754: eb06 0085 add.w r0, r6, r5, lsl #2 +10034758: 6941 ldr r1, [r0, #20] +1003475a: 9102 str r1, [sp, #8] +1003475c: 6901 ldr r1, [r0, #16] +1003475e: 9101 str r1, [sp, #4] +10034760: 68c1 ldr r1, [r0, #12] +10034762: 9100 str r1, [sp, #0] +10034764: 6883 ldr r3, [r0, #8] +10034766: 6842 ldr r2, [r0, #4] +10034768: f856 1025 ldr.w r1, [r6, r5, lsl #2] +1003476c: 4620 mov r0, r4 +1003476e: f000 f8fa bl 10034966 +10034772: 1dad adds r5, r5, #6 +10034774: 2d24 cmp r5, #36 ; 0x24 +10034776: d3ed bcc.n 10034754 +10034778: bd7f pop {r0, r1, r2, r3, r4, r5, r6, pc} + ... + +1003477c <.text_12>: +1003477c: 00ff0fff .word 0x00ff0fff + +10034780 <.text_13>: +10034780: 100444f0 .word 0x100444f0 + +10034784 <.text_14>: +10034784: 10044b30 .word 0x10044b30 + +10034788 <.text_15>: +10034788: 100451a8 .word 0x100451a8 + +1003478c : +1003478c: b5f0 push {r4, r5, r6, r7, lr} +1003478e: f100 0325 add.w r3, r0, #37 ; 0x25 +10034792: 79dd ldrb r5, [r3, #7] +10034794: f890 0025 ldrb.w r0, [r0, #37] ; 0x25 +10034798: 7cdc ldrb r4, [r3, #19] +1003479a: 7bde ldrb r6, [r3, #15] +1003479c: f005 07f0 and.w r7, r5, #240 ; 0xf0 +100347a0: 4338 orrs r0, r7 +100347a2: 0400 lsls r0, r0, #16 +100347a4: ea40 6006 orr.w r0, r0, r6, lsl #24 +100347a8: 7d1e ldrb r6, [r3, #20] +100347aa: ea40 3006 orr.w r0, r0, r6, lsl #12 +100347ae: f005 050f and.w r5, r5, #15 +100347b2: ea40 2005 orr.w r0, r0, r5, lsl #8 +100347b6: 08a6 lsrs r6, r4, #2 +100347b8: f3c4 1500 ubfx r5, r4, #4, #1 +100347bc: f006 0602 and.w r6, r6, #2 +100347c0: 4335 orrs r5, r6 +100347c2: 09e6 lsrs r6, r4, #7 +100347c4: ea45 0586 orr.w r5, r5, r6, lsl #2 +100347c8: 08e6 lsrs r6, r4, #3 +100347ca: f006 0608 and.w r6, r6, #8 +100347ce: 00a4 lsls r4, r4, #2 +100347d0: 4335 orrs r5, r6 +100347d2: f004 0410 and.w r4, r4, #16 +100347d6: 432c orrs r4, r5 +100347d8: 4320 orrs r0, r4 +100347da: 7d5c ldrb r4, [r3, #21] +100347dc: 7d9d ldrb r5, [r3, #22] +100347de: ea44 2405 orr.w r4, r4, r5, lsl #8 +100347e2: 7ddd ldrb r5, [r3, #23] +100347e4: 7e1b ldrb r3, [r3, #24] +100347e6: ea44 4405 orr.w r4, r4, r5, lsl #16 +100347ea: ea44 6303 orr.w r3, r4, r3, lsl #24 +100347ee: f411 4f70 tst.w r1, #61440 ; 0xf000 +100347f2: bf1e ittt ne +100347f4: f401 4470 andne.w r4, r1, #61440 ; 0xf000 +100347f8: f400 4570 andne.w r5, r0, #61440 ; 0xf000 +100347fc: 42ac cmpne r4, r5 +100347fe: d127 bne.n 10034850 +10034800: f011 6f70 tst.w r1, #251658240 ; 0xf000000 +10034804: bf1e ittt ne +10034806: f001 6470 andne.w r4, r1, #251658240 ; 0xf000000 +1003480a: f000 6570 andne.w r5, r0, #251658240 ; 0xf000000 +1003480e: 42ac cmpne r4, r5 +10034810: bf01 itttt eq +10034812: 4c2a ldreq r4, [pc, #168] ; (100348bc <.text_5>) +10034814: 4021 andeq r1, r4 +10034816: 4008 andeq r0, r1 +10034818: 4288 cmpeq r0, r1 +1003481a: d119 bne.n 10034850 +1003481c: 2000 movs r0, #0 +1003481e: f011 0f0f tst.w r1, #15 +10034822: d013 beq.n 1003484c +10034824: 07cc lsls r4, r1, #31 +10034826: bf48 it mi +10034828: 20ff movmi r0, #255 ; 0xff +1003482a: 078c lsls r4, r1, #30 +1003482c: bf48 it mi +1003482e: f440 407f orrmi.w r0, r0, #65280 ; 0xff00 +10034832: 074c lsls r4, r1, #29 +10034834: bf48 it mi +10034836: f440 007f orrmi.w r0, r0, #16711680 ; 0xff0000 +1003483a: 0709 lsls r1, r1, #28 +1003483c: bf48 it mi +1003483e: f040 407f orrmi.w r0, r0, #4278190080 ; 0xff000000 +10034842: ea00 0102 and.w r1, r0, r2 +10034846: 4018 ands r0, r3 +10034848: 4281 cmp r1, r0 +1003484a: d101 bne.n 10034850 +1003484c: 2001 movs r0, #1 +1003484e: bdf0 pop {r4, r5, r6, r7, pc} +10034850: 2000 movs r0, #0 +10034852: bdf0 pop {r4, r5, r6, r7, pc} + +10034854 : +10034854: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +10034858: 4604 mov r4, r0 +1003485a: 2500 movs r5, #0 +1003485c: 2701 movs r7, #1 +1003485e: 2600 movs r6, #0 +10034860: f8df 805c ldr.w r8, [pc, #92] ; 100348c0 <.text_6> +10034864: f858 1025 ldr.w r1, [r8, r5, lsl #2] +10034868: eb08 0085 add.w r0, r8, r5, lsl #2 +1003486c: f011 4f40 tst.w r1, #3221225472 ; 0xc0000000 +10034870: 6842 ldr r2, [r0, #4] +10034872: d017 beq.n 100348a4 +10034874: d51b bpl.n 100348ae +10034876: 0f08 lsrs r0, r1, #28 +10034878: f000 0003 and.w r0, r0, #3 +1003487c: 2803 cmp r0, #3 +1003487e: d102 bne.n 10034886 +10034880: 2701 movs r7, #1 +10034882: 2600 movs r6, #0 +10034884: e013 b.n 100348ae +10034886: 2802 cmp r0, #2 +10034888: bf08 it eq +1003488a: f086 0701 eoreq.w r7, r6, #1 +1003488e: d00e beq.n 100348ae +10034890: b936 cbnz r6, 100348a0 +10034892: 4620 mov r0, r4 +10034894: f7ff ff7a bl 1003478c +10034898: b110 cbz r0, 100348a0 +1003489a: 2701 movs r7, #1 +1003489c: 2601 movs r6, #1 +1003489e: e006 b.n 100348ae +100348a0: 2700 movs r7, #0 +100348a2: e004 b.n 100348ae +100348a4: b11f cbz r7, 100348ae +100348a6: b2d2 uxtb r2, r2 +100348a8: 4620 mov r0, r4 +100348aa: f000 f856 bl 1003495a +100348ae: 1cad adds r5, r5, #2 +100348b0: 1c68 adds r0, r5, #1 +100348b2: 28c2 cmp r0, #194 ; 0xc2 +100348b4: d3d6 bcc.n 10034864 +100348b6: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + ... + +100348bc <.text_5>: +100348bc: 00ff0fff .word 0x00ff0fff + +100348c0 <.text_6>: +100348c0: 10045238 .word 0x10045238 + +100348c4 <__iar_Memchr>: +100348c4: b2c9 uxtb r1, r1 +100348c6: 0783 lsls r3, r0, #30 +100348c8: d006 beq.n 100348d8 <__iar_Memchr+0x14> +100348ca: 1e52 subs r2, r2, #1 +100348cc: d322 bcc.n 10034914 <__iar_Memchr+0x50> +100348ce: f810 3b01 ldrb.w r3, [r0], #1 +100348d2: 4299 cmp r1, r3 +100348d4: d1f7 bne.n 100348c6 <__iar_Memchr+0x2> +100348d6: e01f b.n 10034918 <__iar_Memchr+0x54> +100348d8: 3a08 subs r2, #8 +100348da: d313 bcc.n 10034904 <__iar_Memchr+0x40> +100348dc: f102 0204 add.w r2, r2, #4 +100348e0: ea41 2101 orr.w r1, r1, r1, lsl #8 +100348e4: ea41 4101 orr.w r1, r1, r1, lsl #16 +100348e8: f850 3b04 ldr.w r3, [r0], #4 +100348ec: 1f12 subs r2, r2, #4 +100348ee: bf21 itttt cs +100348f0: 404b eorcs r3, r1 +100348f2: f1a3 3c01 subcs.w ip, r3, #16843009 ; 0x1010101 +100348f6: ea2c 0c03 biccs.w ip, ip, r3 +100348fa: f01c 3f80 tstcs.w ip, #2155905152 ; 0x80808080 +100348fe: d0f3 beq.n 100348e8 <__iar_Memchr+0x24> +10034900: b2c9 uxtb r1, r1 +10034902: 1f00 subs r0, r0, #4 +10034904: 3208 adds r2, #8 +10034906: f810 3b01 ldrb.w r3, [r0], #1 +1003490a: 1e52 subs r2, r2, #1 +1003490c: bf28 it cs +1003490e: ea91 0f03 teqcs r1, r3 +10034912: d8f8 bhi.n 10034906 <__iar_Memchr+0x42> +10034914: bf18 it ne +10034916: 2001 movne r0, #1 +10034918: 1e40 subs r0, r0, #1 +1003491a: 4770 bx lr + +1003491c : +1003491c: b510 push {r4, lr} +1003491e: 461c mov r4, r3 +10034920: 29fe cmp r1, #254 ; 0xfe +10034922: bf1c itt ne +10034924: f640 73fe movwne r3, #4094 ; 0xffe +10034928: 4299 cmpne r1, r3 +1003492a: b082 sub sp, #8 +1003492c: d102 bne.n 10034934 +1003492e: e8bd 4016 ldmia.w sp!, {r1, r2, r4, lr} +10034932: e02c b.n 1003498e <.text_10> +10034934: 9200 str r2, [sp, #0] +10034936: 4621 mov r1, r4 +10034938: 9a04 ldr r2, [sp, #16] +1003493a: 4b03 ldr r3, [pc, #12] ; (10034948 <.text_3>) +1003493c: f7fc fb10 bl 10030f60 +10034940: e8bd 4016 ldmia.w sp!, {r1, r2, r4, lr} +10034944: e047 b.n 100349d6 <.text_12+0x4> + ... + +10034948 <.text_3>: +10034948: 000fffff .word 0x000fffff + +1003494c : +1003494c: b580 push {r7, lr} +1003494e: 9100 str r1, [sp, #0] +10034950: 2300 movs r3, #0 +10034952: e7ff b.n 10034954 <.text_6> + +10034954 <.text_6>: +10034954: f7ff ffe2 bl 1003491c +10034958: bd01 pop {r0, pc} + +1003495a : +1003495a: f7fc baef b.w 10030f3c + +1003495e : +1003495e: b580 push {r7, lr} +10034960: f7fc faf6 bl 10030f50 +10034964: e035 b.n 100349d2 <.text_12> + +10034966 : +10034966: b53e push {r1, r2, r3, r4, r5, lr} +10034968: 9c06 ldr r4, [sp, #24] +1003496a: 2cfe cmp r4, #254 ; 0xfe +1003496c: bf1c itt ne +1003496e: f640 75fe movwne r5, #4094 ; 0xffe +10034972: 42ac cmpne r4, r5 +10034974: d102 bne.n 1003497c +10034976: e8bd 403e ldmia.w sp!, {r1, r2, r3, r4, r5, lr} +1003497a: e008 b.n 1003498e <.text_10> +1003497c: 9d08 ldr r5, [sp, #32] +1003497e: 9502 str r5, [sp, #8] +10034980: 9400 str r4, [sp, #0] +10034982: 9d07 ldr r5, [sp, #28] +10034984: 9501 str r5, [sp, #4] +10034986: 6800 ldr r0, [r0, #0] +10034988: f7fa f9f3 bl 1002ed72 +1003498c: bd37 pop {r0, r1, r2, r4, r5, pc} + +1003498e <.text_10>: +1003498e: 2032 movs r0, #50 ; 0x32 +10034990: f7fc baf6 b.w 10030f80 + +10034994 : +10034994: b580 push {r7, lr} +10034996: 29fe cmp r1, #254 ; 0xfe +10034998: bf08 it eq +1003499a: 2032 moveq r0, #50 ; 0x32 +1003499c: d006 beq.n 100349ac +1003499e: 29fd cmp r1, #253 ; 0xfd +100349a0: bf08 it eq +100349a2: 2005 moveq r0, #5 +100349a4: d002 beq.n 100349ac +100349a6: 29fc cmp r1, #252 ; 0xfc +100349a8: d103 bne.n 100349b2 +100349aa: 2001 movs r0, #1 +100349ac: f7fc fae8 bl 10030f80 +100349b0: e00f b.n 100349d2 <.text_12> +100349b2: 29fb cmp r1, #251 ; 0xfb +100349b4: bf08 it eq +100349b6: 2032 moveq r0, #50 ; 0x32 +100349b8: d006 beq.n 100349c8 +100349ba: 29fa cmp r1, #250 ; 0xfa +100349bc: bf08 it eq +100349be: 2005 moveq r0, #5 +100349c0: d002 beq.n 100349c8 +100349c2: 29f9 cmp r1, #249 ; 0xf9 +100349c4: d103 bne.n 100349ce +100349c6: 2001 movs r0, #1 +100349c8: f7fc fadc bl 10030f84 +100349cc: e001 b.n 100349d2 <.text_12> +100349ce: f7fc fabf bl 10030f50 + +100349d2 <.text_12>: +100349d2: e8bd 4002 ldmia.w sp!, {r1, lr} +100349d6: 2001 movs r0, #1 +100349d8: f7fc bad4 b.w 10030f84 + +100349dc : +100349dc: b51f push {r0, r1, r2, r3, r4, lr} +100349de: 9c09 ldr r4, [sp, #36] ; 0x24 +100349e0: 9403 str r4, [sp, #12] +100349e2: 9c08 ldr r4, [sp, #32] +100349e4: 9402 str r4, [sp, #8] +100349e6: 9c07 ldr r4, [sp, #28] +100349e8: 9401 str r4, [sp, #4] +100349ea: 9c06 ldr r4, [sp, #24] +100349ec: 9400 str r4, [sp, #0] +100349ee: 6800 ldr r0, [r0, #0] +100349f0: f7fb f829 bl 1002fa46 +100349f4: bd1f pop {r0, r1, r2, r3, r4, pc} + ... + +100349f8 : +100349f8: f8df f000 ldr.w pc, [pc] ; 100349fc +100349fc: 0000e5f1 .word 0x0000e5f1 + +10034a00 : +10034a00: f8df f000 ldr.w pc, [pc] ; 10034a04 +10034a04: 0000e491 .word 0x0000e491 + +10034a08 : +10034a08: f8df f000 ldr.w pc, [pc] ; 10034a0c +10034a0c: 0000f965 .word 0x0000f965 + +10034a10 : +10034a10: f8df f000 ldr.w pc, [pc] ; 10034a14 +10034a14: 0000f769 .word 0x0000f769 + +10034a18 : +10034a18: b530 push {r4, r5, lr} +10034a1a: b087 sub sp, #28 +10034a1c: f000 fc44 bl 100352a8 + +10034a20 : +10034a20: f8df 59b0 ldr.w r5, [pc, #2480] ; 100353d4 +10034a24: 7928 ldrb r0, [r5, #4] +10034a26: 07c0 lsls r0, r0, #31 +10034a28: d505 bpl.n 10034a36 +10034a2a: 7828 ldrb r0, [r5, #0] +10034a2c: b118 cbz r0, 10034a36 +10034a2e: f60f 10bc addw r0, pc, #2492 ; 0x9bc +10034a32: f7d7 fc66 bl 1000c302 + +10034a36 : +10034a36: b94c cbnz r4, 10034a4c +10034a38: 7928 ldrb r0, [r5, #4] +10034a3a: 07c0 lsls r0, r0, #31 +10034a3c: d511 bpl.n 10034a62 +10034a3e: 7828 ldrb r0, [r5, #0] +10034a40: b178 cbz r0, 10034a62 +10034a42: f60f 10cc addw r0, pc, #2508 ; 0x9cc +10034a46: f7d7 fc5c bl 1000c302 +10034a4a: e00a b.n 10034a62 + +10034a4c : +10034a4c: f000 f82f bl 10034aae + +10034a50 : +10034a50: 2802 cmp r0, #2 +10034a52: bf18 it ne +10034a54: 2803 cmpne r0, #3 +10034a56: d104 bne.n 10034a62 +10034a58: 1e40 subs r0, r0, #1 +10034a5a: a901 add r1, sp, #4 +10034a5c: b280 uxth r0, r0 +10034a5e: f7ff ffcb bl 100349f8 + +10034a62 : +10034a62: b007 add sp, #28 +10034a64: bd30 pop {r4, r5, pc} + +10034a66 : +10034a66: b530 push {r4, r5, lr} +10034a68: b087 sub sp, #28 +10034a6a: f000 fc1d bl 100352a8 + +10034a6e : +10034a6e: f8df 5964 ldr.w r5, [pc, #2404] ; 100353d4 +10034a72: 7928 ldrb r0, [r5, #4] +10034a74: 0780 lsls r0, r0, #30 +10034a76: d505 bpl.n 10034a84 +10034a78: 7828 ldrb r0, [r5, #0] +10034a7a: b118 cbz r0, 10034a84 +10034a7c: f60f 10b0 addw r0, pc, #2480 ; 0x9b0 +10034a80: f7d7 fc3f bl 1000c302 + +10034a84 : +10034a84: b94c cbnz r4, 10034a9a +10034a86: 7928 ldrb r0, [r5, #4] +10034a88: 0780 lsls r0, r0, #30 +10034a8a: d50e bpl.n 10034aaa +10034a8c: 7828 ldrb r0, [r5, #0] +10034a8e: b160 cbz r0, 10034aaa +10034a90: f60f 10c0 addw r0, pc, #2496 ; 0x9c0 +10034a94: f7d7 fc35 bl 1000c302 +10034a98: e007 b.n 10034aaa + +10034a9a : +10034a9a: f000 f808 bl 10034aae + +10034a9e : +10034a9e: 2803 cmp r0, #3 +10034aa0: d103 bne.n 10034aaa +10034aa2: a901 add r1, sp, #4 +10034aa4: 2002 movs r0, #2 +10034aa6: f7ff ffab bl 10034a00 + +10034aaa : +10034aaa: b007 add sp, #28 +10034aac: bd30 pop {r4, r5, pc} + +10034aae : +10034aae: a900 add r1, sp, #0 +10034ab0: 4620 mov r0, r4 +10034ab2: f000 bfa1 b.w 100359f8 + +10034ab6 : +10034ab6: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +10034aba: f8df 491c ldr.w r4, [pc, #2332] ; 100353d8 +10034abe: b0fa sub sp, #488 ; 0x1e8 +10034ac0: 4605 mov r5, r0 +10034ac2: f8d4 8000 ldr.w r8, [r4] +10034ac6: a802 add r0, sp, #8 +10034ac8: f000 fbf0 bl 100352ac + +10034acc : +10034acc: f8df 6904 ldr.w r6, [pc, #2308] ; 100353d4 +10034ad0: 7930 ldrb r0, [r6, #4] +10034ad2: 0740 lsls r0, r0, #29 +10034ad4: d505 bpl.n 10034ae2 +10034ad6: 7830 ldrb r0, [r6, #0] +10034ad8: b118 cbz r0, 10034ae2 +10034ada: f60f 10a0 addw r0, pc, #2464 ; 0x9a0 +10034ade: f7d7 fc10 bl 1000c302 + +10034ae2 : +10034ae2: f60f 19f8 addw r9, pc, #2552 ; 0x9f8 +10034ae6: f60f 1ab4 addw sl, pc, #2484 ; 0x9b4 +10034aea: b99d cbnz r5, 10034b14 +10034aec: 7930 ldrb r0, [r6, #4] +10034aee: 0740 lsls r0, r0, #29 +10034af0: d507 bpl.n 10034b02 +10034af2: 7830 ldrb r0, [r6, #0] +10034af4: 2800 cmp r0, #0 +10034af6: d07d beq.n 10034bf4 +10034af8: 4650 mov r0, sl +10034afa: f7d7 fc02 bl 1000c302 +10034afe: 7930 ldrb r0, [r6, #4] +10034b00: 0740 lsls r0, r0, #29 + +10034b02 : +10034b02: d577 bpl.n 10034bf4 +10034b04: 7830 ldrb r0, [r6, #0] +10034b06: 2800 cmp r0, #0 +10034b08: d074 beq.n 10034bf4 +10034b0a: f60f 10b4 addw r0, pc, #2484 ; 0x9b4 +10034b0e: f7d7 fbf8 bl 1000c302 +10034b12: e01c b.n 10034b4e + +10034b14 : +10034b14: a902 add r1, sp, #8 +10034b16: 4628 mov r0, r5 +10034b18: f000 ff6e bl 100359f8 +10034b1c: af02 add r7, sp, #8 +10034b1e: 4605 mov r5, r0 +10034b20: 6878 ldr r0, [r7, #4] +10034b22: f60f 11ec addw r1, pc, #2540 ; 0x9ec +10034b26: f7d7 fc13 bl 1000c350 +10034b2a: b940 cbnz r0, 10034b3e +10034b2c: aa00 add r2, sp, #0 +10034b2e: f10d 0102 add.w r1, sp, #2 +10034b32: f001 f8a0 bl 10035c76 +10034b36: 7930 ldrb r0, [r6, #4] +10034b38: 0740 lsls r0, r0, #29 +10034b3a: d427 bmi.n 10034b8c +10034b3c: e05a b.n 10034bf4 + +10034b3e : +10034b3e: 6878 ldr r0, [r7, #4] +10034b40: f60f 11fc addw r1, pc, #2556 ; 0x9fc +10034b44: f7d7 fc04 bl 1000c350 +10034b48: bb48 cbnz r0, 10034b9e +10034b4a: 2d04 cmp r5, #4 +10034b4c: d007 beq.n 10034b5e + +10034b4e : +10034b4e: 7930 ldrb r0, [r6, #4] +10034b50: 0740 lsls r0, r0, #29 +10034b52: d54f bpl.n 10034bf4 +10034b54: 7830 ldrb r0, [r6, #0] +10034b56: 2800 cmp r0, #0 +10034b58: d04c beq.n 10034bf4 +10034b5a: 4648 mov r0, r9 +10034b5c: e02b b.n 10034bb6 + +10034b5e : +10034b5e: 9804 ldr r0, [sp, #16] +10034b60: 2210 movs r2, #16 +10034b62: a901 add r1, sp, #4 +10034b64: f7ff ff50 bl 10034a08 +10034b68: f8ad 0002 strh.w r0, [sp, #2] +10034b6c: 2210 movs r2, #16 +10034b6e: 9805 ldr r0, [sp, #20] +10034b70: a901 add r1, sp, #4 +10034b72: f7ff ff49 bl 10034a08 +10034b76: f8ad 0000 strh.w r0, [sp] +10034b7a: aa00 add r2, sp, #0 +10034b7c: f10d 0102 add.w r1, sp, #2 +10034b80: 2001 movs r0, #1 +10034b82: f001 f878 bl 10035c76 +10034b86: 7930 ldrb r0, [r6, #4] +10034b88: 0740 lsls r0, r0, #29 +10034b8a: d533 bpl.n 10034bf4 + +10034b8c : +10034b8c: 7830 ldrb r0, [r6, #0] +10034b8e: b388 cbz r0, 10034bf4 +10034b90: f8bd 2000 ldrh.w r2, [sp] +10034b94: f8bd 1002 ldrh.w r1, [sp, #2] +10034b98: f60f 107c addw r0, pc, #2428 ; 0x97c +10034b9c: e028 b.n 10034bf0 + +10034b9e : +10034b9e: 6878 ldr r0, [r7, #4] +10034ba0: f7ff ff36 bl 10034a10 +10034ba4: 4605 mov r5, r0 +10034ba6: 2d03 cmp r5, #3 +10034ba8: d308 bcc.n 10034bbc +10034baa: 7930 ldrb r0, [r6, #4] +10034bac: 0740 lsls r0, r0, #29 +10034bae: d521 bpl.n 10034bf4 +10034bb0: 7830 ldrb r0, [r6, #0] +10034bb2: b1f8 cbz r0, 10034bf4 +10034bb4: 4650 mov r0, sl + +10034bb6 : +10034bb6: f7d7 fba4 bl 1000c302 +10034bba: e01b b.n 10034bf4 + +10034bbc : +10034bbc: 2000 movs r0, #0 +10034bbe: 6020 str r0, [r4, #0] +10034bc0: b90d cbnz r5, 10034bc6 +10034bc2: 21b1 movs r1, #177 ; 0xb1 +10034bc4: e003 b.n 10034bce + +10034bc6 : +10034bc6: 2d01 cmp r5, #1 +10034bc8: bf0c ite eq +10034bca: 21b2 moveq r1, #178 ; 0xb2 +10034bcc: 21b3 movne r1, #179 ; 0xb3 + +10034bce : +10034bce: a808 add r0, sp, #32 +10034bd0: f7d1 ff9a bl 10006b08 +10034bd4: a808 add r0, sp, #32 +10034bd6: f7d2 f805 bl 10006be4 +10034bda: 0902 lsrs r2, r0, #4 +10034bdc: 7930 ldrb r0, [r6, #4] +10034bde: f8c4 8000 str.w r8, [r4] +10034be2: 0740 lsls r0, r0, #29 +10034be4: d506 bpl.n 10034bf4 +10034be6: 7830 ldrb r0, [r6, #0] +10034be8: b120 cbz r0, 10034bf4 +10034bea: 4629 mov r1, r5 +10034bec: f60f 1058 addw r0, pc, #2392 ; 0x958 + +10034bf0 : +10034bf0: f7d7 fb87 bl 1000c302 + +10034bf4 : +10034bf4: b07a add sp, #488 ; 0x1e8 +10034bf6: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + +10034bfa : +10034bfa: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +10034bfe: b08c sub sp, #48 ; 0x30 +10034c00: 4607 mov r7, r0 +10034c02: a805 add r0, sp, #20 +10034c04: f000 fb52 bl 100352ac + +10034c08 : +10034c08: f8df 67c8 ldr.w r6, [pc, #1992] ; 100353d4 +10034c0c: f8df 47c8 ldr.w r4, [pc, #1992] ; 100353d8 +10034c10: 7930 ldrb r0, [r6, #4] +10034c12: f8d4 8000 ldr.w r8, [r4] +10034c16: 0700 lsls r0, r0, #28 +10034c18: d505 bpl.n 10034c26 +10034c1a: 7830 ldrb r0, [r6, #0] +10034c1c: b118 cbz r0, 10034c26 +10034c1e: f60f 1040 addw r0, pc, #2368 ; 0x940 +10034c22: f7d7 fb6e bl 1000c302 + +10034c26 : +10034c26: f60f 1558 addw r5, pc, #2392 ; 0x958 +10034c2a: b12f cbz r7, 10034c38 +10034c2c: a905 add r1, sp, #20 +10034c2e: 4638 mov r0, r7 +10034c30: f000 fee2 bl 100359f8 +10034c34: 2802 cmp r0, #2 +10034c36: d009 beq.n 10034c4c + +10034c38 : +10034c38: 7930 ldrb r0, [r6, #4] +10034c3a: 0700 lsls r0, r0, #28 +10034c3c: d561 bpl.n 10034d02 +10034c3e: 7830 ldrb r0, [r6, #0] +10034c40: 2800 cmp r0, #0 +10034c42: d05e beq.n 10034d02 +10034c44: 4628 mov r0, r5 + +10034c46 : +10034c46: f7d7 fb5c bl 1000c302 +10034c4a: e05a b.n 10034d02 + +10034c4c : +10034c4c: 9806 ldr r0, [sp, #24] +10034c4e: f990 7000 ldrsb.w r7, [r0] +10034c52: f990 5001 ldrsb.w r5, [r0, #1] +10034c56: f1a7 0061 sub.w r0, r7, #97 ; 0x61 +10034c5a: 281a cmp r0, #26 +10034c5c: bf3c itt cc +10034c5e: 3f20 subcc r7, #32 +10034c60: b27f sxtbcc r7, r7 +10034c62: f1a5 0061 sub.w r0, r5, #97 ; 0x61 +10034c66: 281a cmp r0, #26 +10034c68: bf3c itt cc +10034c6a: f1a5 0020 subcc.w r0, r5, #32 +10034c6e: b245 sxtbcc r5, r0 +10034c70: 2f41 cmp r7, #65 ; 0x41 +10034c72: d018 beq.n 10034ca6 +10034c74: d316 bcc.n 10034ca4 +10034c76: 2f43 cmp r7, #67 ; 0x43 +10034c78: d073 beq.n 10034d62 +10034c7a: d353 bcc.n 10034d24 +10034c7c: 2f45 cmp r7, #69 ; 0x45 +10034c7e: f000 80bc beq.w 10034dfa +10034c82: f0c0 8094 bcc.w 10034dae +10034c86: 2f47 cmp r7, #71 ; 0x47 +10034c88: f000 80fc beq.w 10034e84 +10034c8c: f0c0 80e2 bcc.w 10034e54 +10034c90: 2f49 cmp r7, #73 ; 0x49 +10034c92: f000 8135 beq.w 10034f00 +10034c96: f0c0 8114 bcc.w 10034ec2 +10034c9a: 2f4b cmp r7, #75 ; 0x4b +10034c9c: f000 816a beq.w 10034f74 +10034ca0: f0c0 814d bcc.w 10034f3e + +10034ca4 : +10034ca4: e181 b.n 10034faa + +10034ca6 : +10034ca6: 2d30 cmp r5, #48 ; 0x30 +10034ca8: d00c beq.n 10034cc4 +10034caa: d3fb bcc.n 10034ca4 +10034cac: 2d32 cmp r5, #50 ; 0x32 +10034cae: d02d beq.n 10034d0c +10034cb0: d32a bcc.n 10034d08 +10034cb2: 2d34 cmp r5, #52 ; 0x34 +10034cb4: d02e beq.n 10034d14 +10034cb6: d32b bcc.n 10034d10 +10034cb8: 2d36 cmp r5, #54 ; 0x36 +10034cba: d02f beq.n 10034d1c +10034cbc: d32c bcc.n 10034d18 +10034cbe: 2d37 cmp r5, #55 ; 0x37 +10034cc0: d02e beq.n 10034d20 +10034cc2: e172 b.n 10034faa + +10034cc4 : +10034cc4: 2100 movs r1, #0 + +10034cc6 : +10034cc6: 2000 movs r0, #0 +10034cc8: 6020 str r0, [r4, #0] +10034cca: a800 add r0, sp, #0 +10034ccc: f001 f8c2 bl 10035e54 +10034cd0: 2100 movs r1, #0 +10034cd2: a800 add r0, sp, #0 +10034cd4: f001 f8da bl 10035e8c +10034cd8: 2101 movs r1, #1 +10034cda: a800 add r0, sp, #0 +10034cdc: f001 f8cb bl 10035e76 +10034ce0: a800 add r0, sp, #0 +10034ce2: f001 f902 bl 10035eea +10034ce6: 7931 ldrb r1, [r6, #4] +10034ce8: f8c4 8000 str.w r8, [r4] +10034cec: 0709 lsls r1, r1, #28 +10034cee: d508 bpl.n 10034d02 +10034cf0: 7831 ldrb r1, [r6, #0] +10034cf2: b131 cbz r1, 10034d02 +10034cf4: 4603 mov r3, r0 +10034cf6: 462a mov r2, r5 +10034cf8: 4639 mov r1, r7 +10034cfa: f60f 00c4 addw r0, pc, #2244 ; 0x8c4 +10034cfe: f7d7 fb00 bl 1000c302 + +10034d02 : +10034d02: b00c add sp, #48 ; 0x30 +10034d04: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +10034d08 : +10034d08: 2101 movs r1, #1 +10034d0a: e7dc b.n 10034cc6 + +10034d0c : +10034d0c: 2102 movs r1, #2 +10034d0e: e7da b.n 10034cc6 + +10034d10 : +10034d10: 2103 movs r1, #3 +10034d12: e7d8 b.n 10034cc6 + +10034d14 : +10034d14: 2104 movs r1, #4 +10034d16: e7d6 b.n 10034cc6 + +10034d18 : +10034d18: 2105 movs r1, #5 +10034d1a: e7d4 b.n 10034cc6 + +10034d1c : +10034d1c: 2106 movs r1, #6 +10034d1e: e7d2 b.n 10034cc6 + +10034d20 : +10034d20: 2107 movs r1, #7 +10034d22: e7d0 b.n 10034cc6 + +10034d24 : +10034d24: 2d30 cmp r5, #48 ; 0x30 +10034d26: d00c beq.n 10034d42 +10034d28: d30a bcc.n 10034d40 +10034d2a: 2d32 cmp r5, #50 ; 0x32 +10034d2c: d00d beq.n 10034d4a +10034d2e: d30a bcc.n 10034d46 +10034d30: 2d34 cmp r5, #52 ; 0x34 +10034d32: d00e beq.n 10034d52 +10034d34: d30b bcc.n 10034d4e +10034d36: 2d36 cmp r5, #54 ; 0x36 +10034d38: d00f beq.n 10034d5a +10034d3a: d30c bcc.n 10034d56 +10034d3c: 2d37 cmp r5, #55 ; 0x37 +10034d3e: d00e beq.n 10034d5e + +10034d40 : +10034d40: e133 b.n 10034faa + +10034d42 : +10034d42: 2110 movs r1, #16 +10034d44: e7bf b.n 10034cc6 + +10034d46 : +10034d46: 2111 movs r1, #17 +10034d48: e7bd b.n 10034cc6 + +10034d4a : +10034d4a: 2112 movs r1, #18 +10034d4c: e7bb b.n 10034cc6 + +10034d4e : +10034d4e: 2113 movs r1, #19 +10034d50: e7b9 b.n 10034cc6 + +10034d52 : +10034d52: 2114 movs r1, #20 +10034d54: e7b7 b.n 10034cc6 + +10034d56 : +10034d56: 2115 movs r1, #21 +10034d58: e7b5 b.n 10034cc6 + +10034d5a : +10034d5a: 2116 movs r1, #22 +10034d5c: e7b3 b.n 10034cc6 + +10034d5e : +10034d5e: 2117 movs r1, #23 +10034d60: e7b1 b.n 10034cc6 + +10034d62 : +10034d62: 2d30 cmp r5, #48 ; 0x30 +10034d64: d00f beq.n 10034d86 +10034d66: d30d bcc.n 10034d84 +10034d68: 2d32 cmp r5, #50 ; 0x32 +10034d6a: d010 beq.n 10034d8e +10034d6c: d30d bcc.n 10034d8a +10034d6e: 2d34 cmp r5, #52 ; 0x34 +10034d70: d011 beq.n 10034d96 +10034d72: d30e bcc.n 10034d92 +10034d74: 2d36 cmp r5, #54 ; 0x36 +10034d76: d012 beq.n 10034d9e +10034d78: d30f bcc.n 10034d9a +10034d7a: 2d38 cmp r5, #56 ; 0x38 +10034d7c: d013 beq.n 10034da6 +10034d7e: d310 bcc.n 10034da2 +10034d80: 2d39 cmp r5, #57 ; 0x39 +10034d82: d012 beq.n 10034daa + +10034d84 : +10034d84: e111 b.n 10034faa + +10034d86 : +10034d86: 2120 movs r1, #32 +10034d88: e79d b.n 10034cc6 + +10034d8a : +10034d8a: 2121 movs r1, #33 ; 0x21 +10034d8c: e79b b.n 10034cc6 + +10034d8e : +10034d8e: 2122 movs r1, #34 ; 0x22 +10034d90: e799 b.n 10034cc6 + +10034d92 : +10034d92: 2123 movs r1, #35 ; 0x23 +10034d94: e797 b.n 10034cc6 + +10034d96 : +10034d96: 2124 movs r1, #36 ; 0x24 +10034d98: e795 b.n 10034cc6 + +10034d9a : +10034d9a: 2125 movs r1, #37 ; 0x25 +10034d9c: e793 b.n 10034cc6 + +10034d9e : +10034d9e: 2126 movs r1, #38 ; 0x26 +10034da0: e791 b.n 10034cc6 + +10034da2 : +10034da2: 2127 movs r1, #39 ; 0x27 +10034da4: e78f b.n 10034cc6 + +10034da6 : +10034da6: 2128 movs r1, #40 ; 0x28 +10034da8: e78d b.n 10034cc6 + +10034daa : +10034daa: 2129 movs r1, #41 ; 0x29 +10034dac: e78b b.n 10034cc6 + +10034dae : +10034dae: 2d30 cmp r5, #48 ; 0x30 +10034db0: d00f beq.n 10034dd2 +10034db2: d30d bcc.n 10034dd0 +10034db4: 2d32 cmp r5, #50 ; 0x32 +10034db6: d010 beq.n 10034dda +10034db8: d30d bcc.n 10034dd6 +10034dba: 2d34 cmp r5, #52 ; 0x34 +10034dbc: d011 beq.n 10034de2 +10034dbe: d30e bcc.n 10034dde +10034dc0: 2d36 cmp r5, #54 ; 0x36 +10034dc2: d012 beq.n 10034dea +10034dc4: d30f bcc.n 10034de6 +10034dc6: 2d38 cmp r5, #56 ; 0x38 +10034dc8: d013 beq.n 10034df2 +10034dca: d310 bcc.n 10034dee +10034dcc: 2d39 cmp r5, #57 ; 0x39 +10034dce: d012 beq.n 10034df6 + +10034dd0 : +10034dd0: e0eb b.n 10034faa + +10034dd2 : +10034dd2: 2130 movs r1, #48 ; 0x30 +10034dd4: e777 b.n 10034cc6 + +10034dd6 : +10034dd6: 2131 movs r1, #49 ; 0x31 +10034dd8: e775 b.n 10034cc6 + +10034dda : +10034dda: 2132 movs r1, #50 ; 0x32 +10034ddc: e773 b.n 10034cc6 + +10034dde : +10034dde: 2133 movs r1, #51 ; 0x33 +10034de0: e771 b.n 10034cc6 + +10034de2 : +10034de2: 2134 movs r1, #52 ; 0x34 +10034de4: e76f b.n 10034cc6 + +10034de6 : +10034de6: 2135 movs r1, #53 ; 0x35 +10034de8: e76d b.n 10034cc6 + +10034dea : +10034dea: 2136 movs r1, #54 ; 0x36 +10034dec: e76b b.n 10034cc6 + +10034dee : +10034dee: 2137 movs r1, #55 ; 0x37 +10034df0: e769 b.n 10034cc6 + +10034df2 : +10034df2: 2138 movs r1, #56 ; 0x38 +10034df4: e767 b.n 10034cc6 + +10034df6 : +10034df6: 2139 movs r1, #57 ; 0x39 +10034df8: e765 b.n 10034cc6 + +10034dfa : +10034dfa: 2d30 cmp r5, #48 ; 0x30 +10034dfc: d014 beq.n 10034e28 +10034dfe: 2d31 cmp r5, #49 ; 0x31 +10034e00: d014 beq.n 10034e2c +10034e02: 2d32 cmp r5, #50 ; 0x32 +10034e04: d014 beq.n 10034e30 +10034e06: 2d33 cmp r5, #51 ; 0x33 +10034e08: d014 beq.n 10034e34 +10034e0a: 2d34 cmp r5, #52 ; 0x34 +10034e0c: d014 beq.n 10034e38 +10034e0e: 2d35 cmp r5, #53 ; 0x35 +10034e10: d014 beq.n 10034e3c +10034e12: 2d36 cmp r5, #54 ; 0x36 +10034e14: d014 beq.n 10034e40 +10034e16: 2d37 cmp r5, #55 ; 0x37 +10034e18: d014 beq.n 10034e44 +10034e1a: 2d38 cmp r5, #56 ; 0x38 +10034e1c: d014 beq.n 10034e48 +10034e1e: 2d39 cmp r5, #57 ; 0x39 +10034e20: d014 beq.n 10034e4c +10034e22: 2d41 cmp r5, #65 ; 0x41 +10034e24: d014 beq.n 10034e50 +10034e26: e0c0 b.n 10034faa + +10034e28 : +10034e28: 2140 movs r1, #64 ; 0x40 +10034e2a: e74c b.n 10034cc6 + +10034e2c : +10034e2c: 2141 movs r1, #65 ; 0x41 +10034e2e: e74a b.n 10034cc6 + +10034e30 : +10034e30: 2142 movs r1, #66 ; 0x42 +10034e32: e748 b.n 10034cc6 + +10034e34 : +10034e34: 2143 movs r1, #67 ; 0x43 +10034e36: e746 b.n 10034cc6 + +10034e38 : +10034e38: 2144 movs r1, #68 ; 0x44 +10034e3a: e744 b.n 10034cc6 + +10034e3c : +10034e3c: 2145 movs r1, #69 ; 0x45 +10034e3e: e742 b.n 10034cc6 + +10034e40 : +10034e40: 2146 movs r1, #70 ; 0x46 +10034e42: e740 b.n 10034cc6 + +10034e44 : +10034e44: 2147 movs r1, #71 ; 0x47 +10034e46: e73e b.n 10034cc6 + +10034e48 : +10034e48: 2148 movs r1, #72 ; 0x48 +10034e4a: e73c b.n 10034cc6 + +10034e4c : +10034e4c: 2149 movs r1, #73 ; 0x49 +10034e4e: e73a b.n 10034cc6 + +10034e50 : +10034e50: 214a movs r1, #74 ; 0x4a +10034e52: e738 b.n 10034cc6 + +10034e54 : +10034e54: 2d30 cmp r5, #48 ; 0x30 +10034e56: d009 beq.n 10034e6c +10034e58: d307 bcc.n 10034e6a +10034e5a: 2d32 cmp r5, #50 ; 0x32 +10034e5c: d00a beq.n 10034e74 +10034e5e: d307 bcc.n 10034e70 +10034e60: 2d34 cmp r5, #52 ; 0x34 +10034e62: d00b beq.n 10034e7c +10034e64: d308 bcc.n 10034e78 +10034e66: 2d35 cmp r5, #53 ; 0x35 +10034e68: d00a beq.n 10034e80 + +10034e6a : +10034e6a: e09e b.n 10034faa + +10034e6c : +10034e6c: 2150 movs r1, #80 ; 0x50 +10034e6e: e72a b.n 10034cc6 + +10034e70 : +10034e70: 2151 movs r1, #81 ; 0x51 +10034e72: e728 b.n 10034cc6 + +10034e74 : +10034e74: 2152 movs r1, #82 ; 0x52 +10034e76: e726 b.n 10034cc6 + +10034e78 : +10034e78: 2153 movs r1, #83 ; 0x53 +10034e7a: e724 b.n 10034cc6 + +10034e7c : +10034e7c: 2154 movs r1, #84 ; 0x54 +10034e7e: e722 b.n 10034cc6 + +10034e80 : +10034e80: 2155 movs r1, #85 ; 0x55 +10034e82: e720 b.n 10034cc6 + +10034e84 : +10034e84: 2d30 cmp r5, #48 ; 0x30 +10034e86: d00c beq.n 10034ea2 +10034e88: d30a bcc.n 10034ea0 +10034e8a: 2d32 cmp r5, #50 ; 0x32 +10034e8c: d00d beq.n 10034eaa +10034e8e: d30a bcc.n 10034ea6 +10034e90: 2d34 cmp r5, #52 ; 0x34 +10034e92: d00e beq.n 10034eb2 +10034e94: d30b bcc.n 10034eae +10034e96: 2d36 cmp r5, #54 ; 0x36 +10034e98: d00f beq.n 10034eba +10034e9a: d30c bcc.n 10034eb6 +10034e9c: 2d37 cmp r5, #55 ; 0x37 +10034e9e: d00e beq.n 10034ebe + +10034ea0 : +10034ea0: e083 b.n 10034faa + +10034ea2 : +10034ea2: 2160 movs r1, #96 ; 0x60 +10034ea4: e70f b.n 10034cc6 + +10034ea6 : +10034ea6: 2161 movs r1, #97 ; 0x61 +10034ea8: e70d b.n 10034cc6 + +10034eaa : +10034eaa: 2162 movs r1, #98 ; 0x62 +10034eac: e70b b.n 10034cc6 + +10034eae : +10034eae: 2163 movs r1, #99 ; 0x63 +10034eb0: e709 b.n 10034cc6 + +10034eb2 : +10034eb2: 2164 movs r1, #100 ; 0x64 +10034eb4: e707 b.n 10034cc6 + +10034eb6 : +10034eb6: 2165 movs r1, #101 ; 0x65 +10034eb8: e705 b.n 10034cc6 + +10034eba : +10034eba: 2166 movs r1, #102 ; 0x66 +10034ebc: e703 b.n 10034cc6 + +10034ebe : +10034ebe: 2167 movs r1, #103 ; 0x67 +10034ec0: e701 b.n 10034cc6 + +10034ec2 : +10034ec2: 2d30 cmp r5, #48 ; 0x30 +10034ec4: d00c beq.n 10034ee0 +10034ec6: d370 bcc.n 10034faa +10034ec8: 2d32 cmp r5, #50 ; 0x32 +10034eca: d00d beq.n 10034ee8 +10034ecc: d30a bcc.n 10034ee4 +10034ece: 2d34 cmp r5, #52 ; 0x34 +10034ed0: d00e beq.n 10034ef0 +10034ed2: d30b bcc.n 10034eec +10034ed4: 2d36 cmp r5, #54 ; 0x36 +10034ed6: d00f beq.n 10034ef8 +10034ed8: d30c bcc.n 10034ef4 +10034eda: 2d37 cmp r5, #55 ; 0x37 +10034edc: d00e beq.n 10034efc +10034ede: e064 b.n 10034faa + +10034ee0 : +10034ee0: 2170 movs r1, #112 ; 0x70 +10034ee2: e6f0 b.n 10034cc6 + +10034ee4 : +10034ee4: 2171 movs r1, #113 ; 0x71 +10034ee6: e6ee b.n 10034cc6 + +10034ee8 : +10034ee8: 2172 movs r1, #114 ; 0x72 +10034eea: e6ec b.n 10034cc6 + +10034eec : +10034eec: 2173 movs r1, #115 ; 0x73 +10034eee: e6ea b.n 10034cc6 + +10034ef0 : +10034ef0: 2174 movs r1, #116 ; 0x74 +10034ef2: e6e8 b.n 10034cc6 + +10034ef4 : +10034ef4: 2175 movs r1, #117 ; 0x75 +10034ef6: e6e6 b.n 10034cc6 + +10034ef8 : +10034ef8: 2176 movs r1, #118 ; 0x76 +10034efa: e6e4 b.n 10034cc6 + +10034efc : +10034efc: 2177 movs r1, #119 ; 0x77 +10034efe: e6e2 b.n 10034cc6 + +10034f00 : +10034f00: 2d30 cmp r5, #48 ; 0x30 +10034f02: d00c beq.n 10034f1e +10034f04: d351 bcc.n 10034faa +10034f06: 2d32 cmp r5, #50 ; 0x32 +10034f08: d00d beq.n 10034f26 +10034f0a: d30a bcc.n 10034f22 +10034f0c: 2d34 cmp r5, #52 ; 0x34 +10034f0e: d00e beq.n 10034f2e +10034f10: d30b bcc.n 10034f2a +10034f12: 2d36 cmp r5, #54 ; 0x36 +10034f14: d00f beq.n 10034f36 +10034f16: d30c bcc.n 10034f32 +10034f18: 2d37 cmp r5, #55 ; 0x37 +10034f1a: d00e beq.n 10034f3a +10034f1c: e045 b.n 10034faa + +10034f1e : +10034f1e: 2180 movs r1, #128 ; 0x80 +10034f20: e6d1 b.n 10034cc6 + +10034f22 : +10034f22: 2181 movs r1, #129 ; 0x81 +10034f24: e6cf b.n 10034cc6 + +10034f26 : +10034f26: 2182 movs r1, #130 ; 0x82 +10034f28: e6cd b.n 10034cc6 + +10034f2a : +10034f2a: 2183 movs r1, #131 ; 0x83 +10034f2c: e6cb b.n 10034cc6 + +10034f2e : +10034f2e: 2184 movs r1, #132 ; 0x84 +10034f30: e6c9 b.n 10034cc6 + +10034f32 : +10034f32: 2185 movs r1, #133 ; 0x85 +10034f34: e6c7 b.n 10034cc6 + +10034f36 : +10034f36: 2186 movs r1, #134 ; 0x86 +10034f38: e6c5 b.n 10034cc6 + +10034f3a : +10034f3a: 2187 movs r1, #135 ; 0x87 +10034f3c: e6c3 b.n 10034cc6 + +10034f3e : +10034f3e: 2d30 cmp r5, #48 ; 0x30 +10034f40: d00a beq.n 10034f58 +10034f42: d332 bcc.n 10034faa +10034f44: 2d32 cmp r5, #50 ; 0x32 +10034f46: d00b beq.n 10034f60 +10034f48: d308 bcc.n 10034f5c +10034f4a: 2d34 cmp r5, #52 ; 0x34 +10034f4c: d00c beq.n 10034f68 +10034f4e: d309 bcc.n 10034f64 +10034f50: 2d36 cmp r5, #54 ; 0x36 +10034f52: d00d beq.n 10034f70 +10034f54: d30a bcc.n 10034f6c +10034f56: e028 b.n 10034faa + +10034f58 : +10034f58: 2190 movs r1, #144 ; 0x90 +10034f5a: e6b4 b.n 10034cc6 + +10034f5c : +10034f5c: 2191 movs r1, #145 ; 0x91 +10034f5e: e6b2 b.n 10034cc6 + +10034f60 : +10034f60: 2192 movs r1, #146 ; 0x92 +10034f62: e6b0 b.n 10034cc6 + +10034f64 : +10034f64: 2193 movs r1, #147 ; 0x93 +10034f66: e6ae b.n 10034cc6 + +10034f68 : +10034f68: 2194 movs r1, #148 ; 0x94 +10034f6a: e6ac b.n 10034cc6 + +10034f6c : +10034f6c: 2195 movs r1, #149 ; 0x95 +10034f6e: e6aa b.n 10034cc6 + +10034f70 : +10034f70: 2196 movs r1, #150 ; 0x96 +10034f72: e6a8 b.n 10034cc6 + +10034f74 : +10034f74: 2d30 cmp r5, #48 ; 0x30 +10034f76: d00a beq.n 10034f8e +10034f78: d317 bcc.n 10034faa +10034f7a: 2d32 cmp r5, #50 ; 0x32 +10034f7c: d00b beq.n 10034f96 +10034f7e: d308 bcc.n 10034f92 +10034f80: 2d34 cmp r5, #52 ; 0x34 +10034f82: d00c beq.n 10034f9e +10034f84: d309 bcc.n 10034f9a +10034f86: 2d36 cmp r5, #54 ; 0x36 +10034f88: d00d beq.n 10034fa6 +10034f8a: d30a bcc.n 10034fa2 +10034f8c: e00d b.n 10034faa + +10034f8e : +10034f8e: 21a0 movs r1, #160 ; 0xa0 +10034f90: e699 b.n 10034cc6 + +10034f92 : +10034f92: 21a1 movs r1, #161 ; 0xa1 +10034f94: e697 b.n 10034cc6 + +10034f96 : +10034f96: 21a2 movs r1, #162 ; 0xa2 +10034f98: e695 b.n 10034cc6 + +10034f9a : +10034f9a: 21a3 movs r1, #163 ; 0xa3 +10034f9c: e693 b.n 10034cc6 + +10034f9e : +10034f9e: 21a4 movs r1, #164 ; 0xa4 +10034fa0: e691 b.n 10034cc6 + +10034fa2 : +10034fa2: 21a5 movs r1, #165 ; 0xa5 +10034fa4: e68f b.n 10034cc6 + +10034fa6 : +10034fa6: 21a6 movs r1, #166 ; 0xa6 +10034fa8: e68d b.n 10034cc6 + +10034faa : +10034faa: 7930 ldrb r0, [r6, #4] +10034fac: 0700 lsls r0, r0, #28 +10034fae: f57f aea8 bpl.w 10034d02 +10034fb2: 7830 ldrb r0, [r6, #0] +10034fb4: 2800 cmp r0, #0 +10034fb6: f43f aea4 beq.w 10034d02 +10034fba: f20f 50e8 addw r0, pc, #1512 ; 0x5e8 +10034fbe: e642 b.n 10034c46 + +10034fc0 : +10034fc0: f8df 0410 ldr.w r0, [pc, #1040] ; 100353d4 +10034fc4: 7901 ldrb r1, [r0, #4] +10034fc6: 06c9 lsls r1, r1, #27 +10034fc8: bf58 it pl +10034fca: f000 bd5d bpl.w 10035a88 +10034fce: b580 push {r7, lr} +10034fd0: 7800 ldrb r0, [r0, #0] +10034fd2: b118 cbz r0, 10034fdc +10034fd4: f20f 50fc addw r0, pc, #1532 ; 0x5fc +10034fd8: f7d7 f993 bl 1000c302 + +10034fdc : +10034fdc: e8bd 4001 ldmia.w sp!, {r0, lr} +10034fe0: f000 bd52 b.w 10035a88 + +10034fe4 : +10034fe4: f8df 03ec ldr.w r0, [pc, #1004] ; 100353d4 +10034fe8: 7901 ldrb r1, [r0, #4] +10034fea: 06c9 lsls r1, r1, #27 +10034fec: bf58 it pl +10034fee: f000 bda2 bpl.w 10035b36 +10034ff2: b580 push {r7, lr} +10034ff4: 7800 ldrb r0, [r0, #0] +10034ff6: b118 cbz r0, 10035000 +10034ff8: f20f 6004 addw r0, pc, #1540 ; 0x604 +10034ffc: f7d7 f981 bl 1000c302 + +10035000 : +10035000: e8bd 4001 ldmia.w sp!, {r0, lr} +10035004: f000 bd97 b.w 10035b36 + +10035008 : +10035008: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +1003500c: b08c sub sp, #48 ; 0x30 +1003500e: 4606 mov r6, r0 +10035010: 2500 movs r5, #0 +10035012: a805 add r0, sp, #20 +10035014: f000 f94a bl 100352ac + +10035018 : +10035018: f8df 43b8 ldr.w r4, [pc, #952] ; 100353d4 +1003501c: 7920 ldrb r0, [r4, #4] +1003501e: 0700 lsls r0, r0, #28 +10035020: d505 bpl.n 1003502e +10035022: 7820 ldrb r0, [r4, #0] +10035024: b118 cbz r0, 1003502e +10035026: f20f 6004 addw r0, pc, #1540 ; 0x604 +1003502a: f7d7 f96a bl 1000c302 + +1003502e : +1003502e: f20f 6724 addw r7, pc, #1572 ; 0x624 +10035032: b996 cbnz r6, 1003505a +10035034: 7920 ldrb r0, [r4, #4] +10035036: 0700 lsls r0, r0, #28 +10035038: d504 bpl.n 10035044 +1003503a: 7820 ldrb r0, [r4, #0] +1003503c: b110 cbz r0, 10035044 +1003503e: 4638 mov r0, r7 +10035040: f7d7 f95f bl 1000c302 + +10035044 : +10035044: ae05 add r6, sp, #20 +10035046: f20f 613c addw r1, pc, #1596 ; 0x63c +1003504a: 6870 ldr r0, [r6, #4] +1003504c: f7d7 f980 bl 1000c350 +10035050: 2800 cmp r0, #0 +10035052: d15a bne.n 1003510a +10035054: 2d04 cmp r5, #4 +10035056: da0f bge.n 10035078 +10035058: e006 b.n 10035068 + +1003505a : +1003505a: a905 add r1, sp, #20 +1003505c: 4630 mov r0, r6 +1003505e: f000 fccb bl 100359f8 +10035062: 4605 mov r5, r0 +10035064: 2d02 cmp r5, #2 +10035066: daed bge.n 10035044 + +10035068 : +10035068: 7920 ldrb r0, [r4, #4] +1003506a: 0700 lsls r0, r0, #28 +1003506c: d54d bpl.n 1003510a +1003506e: 7820 ldrb r0, [r4, #0] +10035070: 2800 cmp r0, #0 +10035072: d04a beq.n 1003510a +10035074: 4638 mov r0, r7 +10035076: e03c b.n 100350f2 + +10035078 : +10035078: 68b0 ldr r0, [r6, #8] +1003507a: 2500 movs r5, #0 +1003507c: 220a movs r2, #10 +1003507e: f000 f89a bl 100351b6 + +10035082 : +10035082: 4682 mov sl, r0 +10035084: 9808 ldr r0, [sp, #32] +10035086: f7ff fcc3 bl 10034a10 +1003508a: 4680 mov r8, r0 +1003508c: 462e mov r6, r5 +1003508e: 2701 movs r7, #1 +10035090: f000 fdef bl 10035c72 +10035094: 2111 movs r1, #17 +10035096: a800 add r0, sp, #0 +10035098: f000 fedc bl 10035e54 +1003509c: 4629 mov r1, r5 +1003509e: a800 add r0, sp, #0 +100350a0: f000 fef4 bl 10035e8c +100350a4: 2102 movs r1, #2 +100350a6: a800 add r0, sp, #0 +100350a8: f000 fee5 bl 10035e76 +100350ac: f7d5 fe25 bl 1000acfa +100350b0: 4681 mov r9, r0 +100350b2: e002 b.n 100350ba + +100350b4 : +100350b4: 4607 mov r7, r0 +100350b6: f7d5 fe20 bl 1000acfa + +100350ba : +100350ba: eb0a 0109 add.w r1, sl, r9 +100350be: 4288 cmp r0, r1 +100350c0: d20a bcs.n 100350d8 +100350c2: a800 add r0, sp, #0 +100350c4: f000 ff11 bl 10035eea +100350c8: 42b8 cmp r0, r7 +100350ca: d0f3 beq.n 100350b4 +100350cc: 2800 cmp r0, #0 +100350ce: bf04 itt eq +100350d0: 1c76 addeq r6, r6, #1 +100350d2: 4546 cmpeq r6, r8 +100350d4: d1ee bne.n 100350b4 +100350d6: 2501 movs r5, #1 + +100350d8 : +100350d8: f000 fdc9 bl 10035c6e +100350dc: 7920 ldrb r0, [r4, #4] +100350de: 7821 ldrb r1, [r4, #0] +100350e0: f000 0008 and.w r0, r0, #8 +100350e4: b145 cbz r5, 100350f8 +100350e6: 2800 cmp r0, #0 +100350e8: bf18 it ne +100350ea: 2900 cmpne r1, #0 +100350ec: d00d beq.n 1003510a +100350ee: f20f 509c addw r0, pc, #1436 ; 0x59c + +100350f2 : +100350f2: f7d7 f906 bl 1000c302 +100350f6: e008 b.n 1003510a + +100350f8 : +100350f8: 2800 cmp r0, #0 +100350fa: bf18 it ne +100350fc: 2900 cmpne r1, #0 +100350fe: d004 beq.n 1003510a +10035100: 4631 mov r1, r6 +10035102: f20f 509c addw r0, pc, #1436 ; 0x59c +10035106: f7d7 f8fc bl 1000c302 + +1003510a : +1003510a: b00c add sp, #48 ; 0x30 +1003510c: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + +10035110 : +10035110: b5f0 push {r4, r5, r6, r7, lr} +10035112: b087 sub sp, #28 +10035114: f000 f8c8 bl 100352a8 + +10035118 : +10035118: 4dae ldr r5, [pc, #696] ; (100353d4 ) +1003511a: 7928 ldrb r0, [r5, #4] +1003511c: 0640 lsls r0, r0, #25 +1003511e: d505 bpl.n 1003512c +10035120: 7828 ldrb r0, [r5, #0] +10035122: b118 cbz r0, 1003512c +10035124: f20f 50a0 addw r0, pc, #1440 ; 0x5a0 +10035128: f7d7 f8eb bl 1000c302 + +1003512c : +1003512c: f20f 56bc addw r6, pc, #1468 ; 0x5bc +10035130: b92c cbnz r4, 1003513e +10035132: 7928 ldrb r0, [r5, #4] +10035134: 0640 lsls r0, r0, #25 +10035136: d53b bpl.n 100351b0 +10035138: 7828 ldrb r0, [r5, #0] +1003513a: 2800 cmp r0, #0 +1003513c: e034 b.n 100351a8 + +1003513e : +1003513e: f7ff fcb6 bl 10034aae + +10035142 : +10035142: 4601 mov r1, r0 +10035144: 686a ldr r2, [r5, #4] +10035146: 782b ldrb r3, [r5, #0] +10035148: 2902 cmp r1, #2 +1003514a: db2a blt.n 100351a2 +1003514c: af00 add r7, sp, #0 +1003514e: f20f 54c4 addw r4, pc, #1476 ; 0x5c4 +10035152: 68b8 ldr r0, [r7, #8] +10035154: 687f ldr r7, [r7, #4] +10035156: f997 7000 ldrsb.w r7, [r7] +1003515a: 2f3f cmp r7, #63 ; 0x3f +1003515c: d017 beq.n 1003518e +1003515e: 2f61 cmp r7, #97 ; 0x61 +10035160: d002 beq.n 10035168 +10035162: 2f72 cmp r7, #114 ; 0x72 +10035164: d007 beq.n 10035176 +10035166: e01c b.n 100351a2 + +10035168 : +10035168: 2903 cmp r1, #3 +1003516a: d10a bne.n 10035182 +1003516c: f000 f822 bl 100351b4 + +10035170 : +10035170: f7d7 fdf4 bl 1000cd5c +10035174: e005 b.n 10035182 + +10035176 : +10035176: 2903 cmp r1, #3 +10035178: d103 bne.n 10035182 +1003517a: f000 f81b bl 100351b4 + +1003517e : +1003517e: f7d7 fdef bl 1000cd60 + +10035182 : +10035182: 7928 ldrb r0, [r5, #4] +10035184: 0640 lsls r0, r0, #25 +10035186: d513 bpl.n 100351b0 +10035188: 7828 ldrb r0, [r5, #0] +1003518a: 2800 cmp r0, #0 +1003518c: e002 b.n 10035194 + +1003518e : +1003518e: 0650 lsls r0, r2, #25 +10035190: d50e bpl.n 100351b0 +10035192: 2b00 cmp r3, #0 + +10035194 : +10035194: d00c beq.n 100351b0 +10035196: f7d7 fde9 bl 1000cd6c +1003519a: 4601 mov r1, r0 +1003519c: f000 f912 bl 100353c4 + +100351a0 : +100351a0: e006 b.n 100351b0 + +100351a2 : +100351a2: 0650 lsls r0, r2, #25 +100351a4: d504 bpl.n 100351b0 +100351a6: 2b00 cmp r3, #0 + +100351a8 : +100351a8: bf1c itt ne +100351aa: 4630 movne r0, r6 +100351ac: f7d7 f8a9 blne 1000c302 + +100351b0 : +100351b0: b007 add sp, #28 +100351b2: bdf0 pop {r4, r5, r6, r7, pc} + +100351b4 : +100351b4: 2210 movs r2, #16 + +100351b6 : +100351b6: 2100 movs r1, #0 +100351b8: f7ff bc26 b.w 10034a08 + +100351bc : +100351bc: b530 push {r4, r5, lr} +100351be: b087 sub sp, #28 +100351c0: 4604 mov r4, r0 +100351c2: a801 add r0, sp, #4 +100351c4: f000 f872 bl 100352ac + +100351c8 : +100351c8: f20f 5064 addw r0, pc, #1380 ; 0x564 +100351cc: f7d7 f899 bl 1000c302 +100351d0: 4d80 ldr r5, [pc, #512] ; (100353d4 ) +100351d2: b924 cbnz r4, 100351de +100351d4: f20f 507c addw r0, pc, #1404 ; 0x57c +100351d8: f7d7 f893 bl 1000c302 +100351dc: e00e b.n 100351fc + +100351de : +100351de: a901 add r1, sp, #4 +100351e0: 4620 mov r0, r4 +100351e2: f000 fc09 bl 100359f8 +100351e6: 2803 cmp r0, #3 +100351e8: d108 bne.n 100351fc +100351ea: 9802 ldr r0, [sp, #8] +100351ec: f7ff fc10 bl 10034a10 +100351f0: 7028 strb r0, [r5, #0] +100351f2: 2210 movs r2, #16 +100351f4: 9803 ldr r0, [sp, #12] +100351f6: f000 f854 bl 100352a2 + +100351fa : +100351fa: 6068 str r0, [r5, #4] + +100351fc : +100351fc: 686a ldr r2, [r5, #4] +100351fe: 7829 ldrb r1, [r5, #0] +10035200: f20f 5074 addw r0, pc, #1396 ; 0x574 +10035204: f7d7 f87d bl 1000c302 +10035208: b007 add sp, #28 +1003520a: bd30 pop {r4, r5, pc} + +1003520c : +1003520c: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +10035210: b088 sub sp, #32 +10035212: 4604 mov r4, r0 +10035214: a801 add r0, sp, #4 +10035216: f000 f849 bl 100352ac + +1003521a : +1003521a: f20f 5080 addw r0, pc, #1408 ; 0x580 +1003521e: f7d7 f870 bl 1000c302 +10035222: 4d6e ldr r5, [pc, #440] ; (100353dc ) +10035224: 4e6c ldr r6, [pc, #432] ; (100353d8 ) +10035226: f8df 81b8 ldr.w r8, [pc, #440] ; 100353e0 +1003522a: b924 cbnz r4, 10035236 +1003522c: f20f 5094 addw r0, pc, #1428 ; 0x594 +10035230: f7d7 f867 bl 1000c302 +10035234: e021 b.n 1003527a + +10035236 : +10035236: a901 add r1, sp, #4 +10035238: 4620 mov r0, r4 +1003523a: f000 fbdd bl 100359f8 +1003523e: 2803 cmp r0, #3 +10035240: d11b bne.n 1003527a +10035242: ac01 add r4, sp, #4 +10035244: 6860 ldr r0, [r4, #4] +10035246: f7ff fbe3 bl 10034a10 +1003524a: 4607 mov r7, r0 +1003524c: 68a0 ldr r0, [r4, #8] +1003524e: f000 f827 bl 100352a0 + +10035252 : +10035252: 4960 ldr r1, [pc, #384] ; (100353d4 ) +10035254: 6048 str r0, [r1, #4] +10035256: 68a0 ldr r0, [r4, #8] +10035258: b927 cbnz r7, 10035264 +1003525a: f000 f821 bl 100352a0 + +1003525e : +1003525e: f8c8 0000 str.w r0, [r8] +10035262: e00a b.n 1003527a + +10035264 : +10035264: 2f01 cmp r7, #1 +10035266: d103 bne.n 10035270 +10035268: f000 f81a bl 100352a0 + +1003526c : +1003526c: 6030 str r0, [r6, #0] +1003526e: e004 b.n 1003527a + +10035270 : +10035270: 2f02 cmp r7, #2 +10035272: d102 bne.n 1003527a +10035274: f000 f814 bl 100352a0 + +10035278 : +10035278: 6028 str r0, [r5, #0] + +1003527a : +1003527a: f8d8 1000 ldr.w r1, [r8] +1003527e: f20f 5070 addw r0, pc, #1392 ; 0x570 +10035282: f7d7 f83e bl 1000c302 +10035286: 6831 ldr r1, [r6, #0] +10035288: f20f 5088 addw r0, pc, #1416 ; 0x588 +1003528c: f7d7 f839 bl 1000c302 +10035290: 6829 ldr r1, [r5, #0] +10035292: f20f 50a4 addw r0, pc, #1444 ; 0x5a4 +10035296: f7d7 f834 bl 1000c302 +1003529a: b008 add sp, #32 +1003529c: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +100352a0 : +100352a0: 2210 movs r2, #16 + +100352a2 : +100352a2: a900 add r1, sp, #0 +100352a4: f7ff bbb0 b.w 10034a08 + +100352a8 : +100352a8: 4604 mov r4, r0 +100352aa: a800 add r0, sp, #0 + +100352ac : +100352ac: 2118 movs r1, #24 +100352ae: f7f0 bab5 b.w 1002581c <__aeabi_memclr4> + +100352b2 : +100352b2: f20f 50a8 addw r0, pc, #1448 ; 0x5a8 +100352b6: f7d7 b824 b.w 1000c302 + +100352ba : +100352ba: b580 push {r7, lr} +100352bc: f20f 50b8 addw r0, pc, #1464 ; 0x5b8 +100352c0: f7d7 f81f bl 1000c302 +100352c4: f20f 51e8 addw r1, pc, #1512 ; 0x5e8 +100352c8: f20f 50c8 addw r0, pc, #1480 ; 0x5c8 +100352cc: e8bd 4004 ldmia.w sp!, {r2, lr} +100352d0: f7d7 b817 b.w 1000c302 + +100352d4 : +100352d4: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +100352d8: b086 sub sp, #24 +100352da: f20f 50e8 addw r0, pc, #1512 ; 0x5e8 +100352de: f7d7 f810 bl 1000c302 +100352e2: 4d40 ldr r5, [pc, #256] ; (100353e4 ) +100352e4: f20f 54f4 addw r4, pc, #1524 ; 0x5f4 +100352e8: f000 f86b bl 100353c2 + +100352ec : +100352ec: f20f 6608 addw r6, pc, #1544 ; 0x608 +100352f0: f000 f85f bl 100353b2 + +100352f4 : +100352f4: f20f 671c addw r7, pc, #1564 ; 0x61c +100352f8: f000 f85f bl 100353ba + +100352fc : +100352fc: f20f 6030 addw r0, pc, #1584 ; 0x630 +10035300: f7d6 ffff bl 1000c302 +10035304: f20f 6030 addw r0, pc, #1584 ; 0x630 +10035308: f7d6 fffb bl 1000c302 +1003530c: 2100 movs r1, #0 +1003530e: a800 add r0, sp, #0 +10035310: f000 fda0 bl 10035e54 +10035314: f000 f855 bl 100353c2 + +10035318 : +10035318: f000 f84b bl 100353b2 + +1003531c : +1003531c: f000 f84d bl 100353ba + +10035320 : +10035320: f20f 6020 addw r0, pc, #1568 ; 0x620 +10035324: f7d6 ffed bl 1000c302 +10035328: 2101 movs r1, #1 +1003532a: a800 add r0, sp, #0 +1003532c: f000 fdae bl 10035e8c +10035330: f000 f847 bl 100353c2 + +10035334 : +10035334: f000 f83d bl 100353b2 + +10035338 : +10035338: f000 f83f bl 100353ba + +1003533c : +1003533c: f20f 601c addw r0, pc, #1564 ; 0x61c +10035340: f7d6 ffdf bl 1000c302 +10035344: 2100 movs r1, #0 +10035346: a800 add r0, sp, #0 +10035348: f000 fd95 bl 10035e76 +1003534c: f000 f839 bl 100353c2 + +10035350 : +10035350: f000 f82f bl 100353b2 + +10035354 : +10035354: f000 f831 bl 100353ba + +10035358 : +10035358: f20f 6814 addw r8, pc, #1556 ; 0x614 +1003535c: 4640 mov r0, r8 +1003535e: f7d6 ffd0 bl 1000c302 +10035362: 2101 movs r1, #1 +10035364: a800 add r0, sp, #0 +10035366: f000 fda4 bl 10035eb2 +1003536a: f000 f82a bl 100353c2 + +1003536e : +1003536e: f000 f820 bl 100353b2 + +10035372 : +10035372: f000 f822 bl 100353ba + +10035376 : +10035376: f20f 6008 addw r0, pc, #1544 ; 0x608 +1003537a: f7d6 ffc2 bl 1000c302 +1003537e: 2100 movs r1, #0 +10035380: a800 add r0, sp, #0 +10035382: f000 fd96 bl 10035eb2 +10035386: f000 f81c bl 100353c2 + +1003538a : +1003538a: f000 f812 bl 100353b2 + +1003538e : +1003538e: f000 f814 bl 100353ba + +10035392 : +10035392: 4640 mov r0, r8 +10035394: f7d6 ffb5 bl 1000c302 +10035398: 2001 movs r0, #1 +1003539a: 6028 str r0, [r5, #0] +1003539c: 4620 mov r0, r4 +1003539e: 6829 ldr r1, [r5, #0] +100353a0: f7d6 ffaf bl 1000c302 +100353a4: f000 f805 bl 100353b2 + +100353a8 : +100353a8: f000 f807 bl 100353ba + +100353ac : +100353ac: b006 add sp, #24 +100353ae: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +100353b2 : +100353b2: 6869 ldr r1, [r5, #4] +100353b4: 4630 mov r0, r6 +100353b6: f7d6 bfa4 b.w 1000c302 + +100353ba : +100353ba: 68a9 ldr r1, [r5, #8] +100353bc: 4638 mov r0, r7 +100353be: f7d6 bfa0 b.w 1000c302 + +100353c2 : +100353c2: 6829 ldr r1, [r5, #0] + +100353c4 : +100353c4: 4620 mov r0, r4 +100353c6: f7d6 bf9c b.w 1000c302 + +100353ca : +100353ca: 210d movs r1, #13 +100353cc: 4806 ldr r0, [pc, #24] ; (100353e8 ) +100353ce: f000 bb06 b.w 100359de + ... + +100353d4 : +100353d4: 3cd0 1004 .<.. + +100353d8 : +100353d8: 0310 1000 .... + +100353dc : +100353dc: 030c 1000 .... + +100353e0 : +100353e0: 0314 1000 .... + +100353e4 : +100353e4: 1000 4000 ...@ + +100353e8 : +100353e8: 3cd8 1004 .<.. + +100353ec : +100353ec: 415b 5354 5d44 203a 415f 5f54 5953 5453 [ATSD]: _AT_SYST +100353fc: 4d45 445f 4d55 5f50 4552 4947 5453 5245 EM_DUMP_REGISTER +1003540c: 0d5f 000a _... + +10035410 : +10035410: 415b 5354 5d44 5520 6173 6567 203a 5441 [ATSD] Usage: AT +10035420: 4453 523d 4745 5349 4554 0d52 000a 0000 SD=REGISTER..... + +10035430 : +10035430: 415b 5354 5d45 203a 415f 5f54 5953 5453 [ATSE]: _AT_SYST +10035440: 4d45 455f 4944 5f54 4552 4947 5453 5245 EM_EDIT_REGISTER +10035450: 0d5f 000a _... + +10035454 : +10035454: 415b 5354 5d45 5520 6173 6567 203a 5441 [ATSE] Usage: AT +10035464: 4553 523d 4745 5349 4554 5b52 4156 554c SE=REGISTER[VALU +10035474: 5d45 0a0d 0000 0000 E]...... + +1003547c : +1003547c: 415b 5354 5d41 203a 415f 5f54 5953 5453 [ATSA]: _AT_SYST +1003548c: 4d45 415f 4344 545f 5345 5f54 0a0d 0000 EM_ADC_TEST_.... + +1003549c : +1003549c: 415b 5354 5d41 5520 6173 6567 203a 5441 [ATSA] Usage: AT +100354ac: 4153 433d 4148 4e4e 4c45 3028 327e 0d29 SA=CHANNEL(0~2). +100354bc: 000a 0000 .... + +100354c0 : +100354c0: 415b 5354 5d41 5520 6173 6567 203a 5441 [ATSA] Usage: AT +100354d0: 4153 6b3d 675f 7465 0a0d 0000 SA=k_get.... + +100354dc : +100354dc: 415b 5354 5d41 5520 6173 6567 203a 5441 [ATSA] Usage: AT +100354ec: 4153 6b3d 735f 7465 6f5b 6666 7465 6828 SA=k_set[offet(h +100354fc: 7865 2c29 6167 6e69 6828 7865 5d29 0a0d ex),gain(hex)].. +1003550c: 0000 0000 .... + +10035510 : +10035510: 5f6b 6567 0074 0000 k_get... + +10035518 : +10035518: 415b 5354 5d41 6f20 6666 6573 2074 203d [ATSA] offset = +10035528: 7830 3025 5834 202c 6167 6e69 3d20 3020 0x%04X, gain = 0 +10035538: 2578 3430 0d58 000a x%04X... + +10035540 : +10035540: 5f6b 6573 0074 0000 k_set... + +10035548 : +10035548: 415b 5354 5d41 4120 6425 3d20 3020 2578 [ATSA] A%d = 0x% +10035558: 3430 0d58 000a 0000 04X..... + +10035560 : +10035560: 415b 5354 5d47 203a 415f 5f54 5953 5453 [ATSG]: _AT_SYST +10035570: 4d45 475f 4950 5f4f 4554 5453 0d5f 000a EM_GPIO_TEST_... + +10035580 : +10035580: 415b 5354 5d47 5520 6173 6567 203a 5441 [ATSG] Usage: AT +10035590: 4753 503d 4e49 414e 454d 6528 3a78 3041 SG=PINNAME(ex:A0 +100355a0: 0d29 000a )... + +100355a4 : +100355a4: 415b 5354 5d47 203a 6e49 6176 696c 2064 [ATSG]: Invalid +100355b4: 6950 206e 614e 656d 0a0d 0000 Pin Name.... + +100355c0 : +100355c0: 415b 5354 5d47 2520 2563 2063 203d 6425 [ATSG] %c%c = %d +100355d0: 0a0d 0000 .... + +100355d4 : +100355d4: 415b 5354 5d43 203a 415f 5f54 5953 5453 [ATSC]: _AT_SYST +100355e4: 4d45 435f 454c 5241 4f5f 4154 535f 4749 EM_CLEAR_OTA_SIG +100355f4: 414e 5554 4552 0d5f 000a 0000 NATURE_..... + +10035600 : +10035600: 415b 5354 5d52 203a 415f 5f54 5953 5453 [ATSR]: _AT_SYST +10035610: 4d45 525f 4345 564f 5245 4f5f 4154 535f EM_RECOVER_OTA_S +10035620: 4749 414e 5554 4552 0d5f 000a IGNATURE_... + +1003562c : +1003562c: 415b 5354 5d50 203a 415f 5f54 5953 5453 [ATSP]: _AT_SYST +1003563c: 4d45 505f 574f 5245 505f 4e49 545f 5345 EM_POWER_PIN_TES +1003564c: 5f54 0a0d 0000 0000 T_...... + +10035654 : +10035654: 415b 5354 5d50 203a 7355 6761 3a65 4120 [ATSP]: Usage: A +10035664: 5354 3d50 7067 6f69 3162 745b 6d69 6f65 TSP=gpiob1[timeo +10035674: 7475 7a2c 7265 636f 756f 746e 0d5d 000a ut,zerocount]... + +10035684 : +10035684: 7067 6f69 3162 0000 gpiob1.. + +1003568c : +1003568c: 415b 5354 5d50 203a 7573 6363 7365 0d73 [ATSP]: success. +1003569c: 000a 0000 .... + +100356a0 : +100356a0: 415b 5354 5d50 203a 6166 6c69 202c 7469 [ATSP]: fail, it +100356b0: 6f20 6c6e 2079 6f67 2074 6425 7a20 7265 only got %d zer +100356c0: 736f 0a0d 0000 0000 os...... + +100356c8 : +100356c8: 415b 5354 5d4c 203a 415f 5f54 5953 5f53 [ATSL]: _AT_SYS_ +100356d8: 4157 454b 4f4c 4b43 545f 5345 5f54 0a0d WAKELOCK_TEST_.. +100356e8: 0000 0000 .... + +100356ec : +100356ec: 415b 5354 5d4c 5520 6173 6567 4120 5354 [ATSL] Usage ATS +100356fc: 3d4c 615b 722f 3f2f 5b5d 6962 6d74 7361 L=[a/r/?][bitmas +1003570c: 5d6b 0a0d 0000 0000 k]...... + +10035714 : +10035714: 415b 5354 5d4c 7720 6b61 6c65 636f 3a6b [ATSL] wakelock: +10035724: 7830 3025 7838 0a0d 0000 0000 0x%08x...... + +10035730 : +10035730: 415b 5354 5d40 203a 415f 5f54 5953 5453 [ATS@]: _AT_SYST +10035740: 4d45 445f 4742 535f 5445 4954 474e 0d5f EM_DBG_SETTING_. +10035750: 000a 0000 .... + +10035754 : +10035754: 415b 5354 5d40 5520 6173 6567 203a 5441 [ATS@] Usage: AT +10035764: 4053 5b3d 454c 4c56 2c45 4c46 4741 0d5d S@=[LEVLE,FLAG]. +10035774: 000a 0000 .... + +10035778 : +10035778: 415b 5354 5d40 6c20 7665 6c65 3d20 2520 [ATS@] level = % +10035788: 2c64 6620 616c 2067 203d 7830 3025 5838 d, flag = 0x%08X +10035798: 0a0d 0000 .... + +1003579c : +1003579c: 415b 5354 5d21 203a 415f 5f54 5953 5453 [ATS!]: _AT_SYST +100357ac: 4d45 435f 4e4f 4946 5f47 4553 5454 4e49 EM_CONFIG_SETTIN +100357bc: 5f47 0a0d 0000 0000 G_...... + +100357c4 : +100357c4: 415b 5354 5d21 5520 6173 6567 203a 5441 [ATS!] Usage: AT +100357d4: 2153 5b3d 4f43 464e 4749 3028 312c 322c S!=[CONFIG(0,1,2 +100357e4: 2c29 4c46 4741 0d5d 000a 0000 ),FLAG]..... + +100357f0 : +100357f0: 415b 5354 5d21 4320 6e6f 6966 4467 6265 [ATS!] ConfigDeb +10035800: 6775 7245 2072 3d20 3020 2578 3830 0d58 ugErr = 0x%08X. +10035810: 000a 0000 .... + +10035814 : +10035814: 415b 5354 5d21 4320 6e6f 6966 4467 6265 [ATS!] ConfigDeb +10035824: 6775 6e49 6f66 3d20 3020 2578 3830 0d58 ugInfo = 0x%08X. +10035834: 000a 0000 .... + +10035838 : +10035838: 415b 5354 5d21 4320 6e6f 6966 4467 6265 [ATS!] ConfigDeb +10035848: 6775 6157 6e72 3d20 3020 2578 3830 0d58 ugWarn = 0x%08X. +10035858: 000a 0000 .... + +1003585c : +1003585c: 415b 5354 5d23 203a 415f 5f54 5953 5453 [ATS#]: _AT_SYST +1003586c: 4d45 545f 5345 5f54 0a0d 0000 EM_TEST_.... + +10035878 : +10035878: 415b 5354 5d3f 203a 415f 5f54 5953 5453 [ATS?]: _AT_SYST +10035888: 4d45 485f 4c45 5f50 0a0d 0000 EM_HELP_.... + +10035894 : +10035894: 415b 5354 5d3f 203a 4f43 504d 4c49 2045 [ATS?]: COMPILE +100358a4: 4954 454d 203a 7325 0a0d 0000 TIME: %s.... + +100358b0 : +100358b0: 3032 3531 312f 2f31 3731 202d 3a39 3235 2015/11/17- 9:52 +100358c0: 333a 0033 :33. + +100358c4 : +100358c4: 3d3d 203d 5047 4f49 525f 4745 425f 5341 === GPIO_REG_BAS +100358d4: 2045 3d3d 0a3d 0000 E ===... + +100358dc : +100358dc: 5047 4f49 505f 524f 4154 445f 2052 2020 GPIO_PORTA_DR +100358ec: 203d 7830 3025 7838 000a 0000 = 0x%08x.... + +100358f8 : +100358f8: 5047 4f49 505f 524f 4154 445f 5244 2020 GPIO_PORTA_DDR +10035908: 203d 7830 3025 7838 000a 0000 = 0x%08x.... + +10035914 : +10035914: 5047 4f49 505f 524f 4154 435f 5254 204c GPIO_PORTA_CTRL +10035924: 203d 7830 3025 7838 000a 0000 = 0x%08x.... + +10035930 : +10035930: 4150 305f 000a 0000 PA_0.... + +10035938 : +10035938: 7067 6f69 695f 696e 0a74 0000 gpio_init... + +10035944 : +10035944: 7067 6f69 645f 7269 5020 4e49 4f5f 5455 gpio_dir PIN_OUT +10035954: 5550 0a54 0000 0000 PUT..... + +1003595c : +1003595c: 7067 6f69 6d5f 646f 2065 7550 6c6c 6f4e gpio_mode PullNo +1003596c: 656e 000a ne.. + +10035970 : +10035970: 7067 6f69 775f 6972 6574 3120 000a 0000 gpio_write 1.... + +10035980 : +10035980: 7067 6f69 775f 6972 6574 3020 000a 0000 gpio_write 0.... + +10035990 : +10035990: 680a ldr r2, [r1, #0] +10035992: 6050 str r0, [r2, #4] +10035994: 6002 str r2, [r0, #0] +10035996: 6041 str r1, [r0, #4] +10035998: 6008 str r0, [r1, #0] +1003599a: 4770 bx lr + +1003599c : +1003599c: 2100 movs r1, #0 +1003599e: e004 b.n 100359aa + +100359a0 : +100359a0: f910 3b01 ldrsb.w r3, [r0], #1 +100359a4: 2283 movs r2, #131 ; 0x83 +100359a6: fb02 3101 mla r1, r2, r1, r3 + +100359aa : +100359aa: f990 2000 ldrsb.w r2, [r0] +100359ae: 2a00 cmp r2, #0 +100359b0: d1f6 bne.n 100359a0 +100359b2: 0048 lsls r0, r1, #1 +100359b4: 0840 lsrs r0, r0, #1 +100359b6: 4770 bx lr + +100359b8 : +100359b8: b510 push {r4, lr} +100359ba: 4604 mov r4, r0 +100359bc: 6820 ldr r0, [r4, #0] +100359be: f7ff ffed bl 1003599c +100359c2: 492a ldr r1, [pc, #168] ; (10035a6c ) +100359c4: 1102 asrs r2, r0, #4 +100359c6: eb00 62d2 add.w r2, r0, r2, lsr #27 +100359ca: 1152 asrs r2, r2, #5 +100359cc: eba0 1042 sub.w r0, r0, r2, lsl #5 +100359d0: eb01 01c0 add.w r1, r1, r0, lsl #3 +100359d4: f104 0008 add.w r0, r4, #8 +100359d8: e8bd 4010 ldmia.w sp!, {r4, lr} +100359dc: e7d8 b.n 10035990 + +100359de : +100359de: b570 push {r4, r5, r6, lr} +100359e0: 4604 mov r4, r0 +100359e2: 460d mov r5, r1 +100359e4: 2600 movs r6, #0 +100359e6: e004 b.n 100359f2 + +100359e8 : +100359e8: eb04 1006 add.w r0, r4, r6, lsl #4 +100359ec: f7ff ffe4 bl 100359b8 +100359f0: 1c76 adds r6, r6, #1 + +100359f2 : +100359f2: 42ae cmp r6, r5 +100359f4: dbf8 blt.n 100359e8 +100359f6: bd70 pop {r4, r5, r6, pc} + +100359f8 : +100359f8: 2201 movs r2, #1 + +100359fa : +100359fa: f990 3000 ldrsb.w r3, [r0] +100359fe: b90b cbnz r3, 10035a04 +10035a00: e01f b.n 10035a42 + +10035a02 : +10035a02: 1c40 adds r0, r0, #1 + +10035a04 : +10035a04: f990 3000 ldrsb.w r3, [r0] +10035a08: 2b5b cmp r3, #91 ; 0x5b +10035a0a: bf18 it ne +10035a0c: 2b20 cmpne r3, #32 +10035a0e: d0f8 beq.n 10035a02 +10035a10: 2b5d cmp r3, #93 ; 0x5d +10035a12: bf18 it ne +10035a14: 2b00 cmpne r3, #0 +10035a16: d014 beq.n 10035a42 +10035a18: f841 0022 str.w r0, [r1, r2, lsl #2] +10035a1c: 1c52 adds r2, r2, #1 + +10035a1e : +10035a1e: f910 3f01 ldrsb.w r3, [r0, #1]! +10035a22: 2b2c cmp r3, #44 ; 0x2c +10035a24: bf18 it ne +10035a26: 2b5b cmpne r3, #91 ; 0x5b +10035a28: bf1c itt ne +10035a2a: 2b5d cmpne r3, #93 ; 0x5d +10035a2c: 2b00 cmpne r3, #0 +10035a2e: d1f6 bne.n 10035a1e + +10035a30 : +10035a30: f990 3000 ldrsb.w r3, [r0] +10035a34: 2b2c cmp r3, #44 ; 0x2c +10035a36: bf1c itt ne +10035a38: 2b5b cmpne r3, #91 ; 0x5b +10035a3a: 2b5d cmpne r3, #93 ; 0x5d +10035a3c: d003 beq.n 10035a46 +10035a3e: 2a06 cmp r2, #6 +10035a40: dbdb blt.n 100359fa + +10035a42 : +10035a42: 4610 mov r0, r2 +10035a44: 4770 bx lr + +10035a46 : +10035a46: 2300 movs r3, #0 +10035a48: f800 3b01 strb.w r3, [r0], #1 +10035a4c: e7f0 b.n 10035a30 + +10035a4e : +10035a4e: b580 push {r7, lr} +10035a50: f20f 0020 addw r0, pc, #32 +10035a54: f000 faa2 bl 10035f9c +10035a58: e8bd 4002 ldmia.w sp!, {r1, lr} +10035a5c: 2000 movs r0, #0 +10035a5e: f7d4 bfef b.w 1000aa40 + +10035a62 : +10035a62: 2102 movs r1, #2 +10035a64: 4802 ldr r0, [pc, #8] ; (10035a70 ) +10035a66: e7ba b.n 100359de +10035a68: 0000 movs r0, r0 + ... + +10035a6c : +10035a6c: 7724 1004 $w.. + +10035a70 : +10035a70: 3fb4 1004 .?.. + +10035a74 : +10035a74: 0d0a 654c 7661 2065 4f4c 2047 4553 5652 ..Leave LOG SERV +10035a84: 4349 0045 ICE. + +10035a88 : +10035a88: b5f0 push {r4, r5, r6, r7, lr} +10035a8a: b087 sub sp, #28 +10035a8c: f000 f8d6 bl 10035c3c + +10035a90 : +10035a90: f000 f8ea bl 10035c68 + +10035a94 : +10035a94: 9801 ldr r0, [sp, #4] +10035a96: 0400 lsls r0, r0, #16 +10035a98: 0980 lsrs r0, r0, #6 +10035a9a: 9001 str r0, [sp, #4] +10035a9c: f000 f8e0 bl 10035c60 + +10035aa0 : +10035aa0: f20f 2580 addw r5, pc, #640 ; 0x280 +10035aa4: f000 f842 bl 10035b2c + +10035aa8 : +10035aa8: b900 cbnz r0, 10035aac +10035aaa: 9c01 ldr r4, [sp, #4] + +10035aac : +10035aac: ab05 add r3, sp, #20 +10035aae: 2204 movs r2, #4 +10035ab0: f44f 4110 mov.w r1, #36864 ; 0x9000 +10035ab4: f000 f8d8 bl 10035c68 + +10035ab8 : +10035ab8: 9805 ldr r0, [sp, #20] +10035aba: f000 f8d1 bl 10035c60 + +10035abe : +10035abe: f000 f835 bl 10035b2c + +10035ac2 : +10035ac2: b900 cbnz r0, 10035ac6 +10035ac4: 9c05 ldr r4, [sp, #20] + +10035ac6 : +10035ac6: f000 f8b4 bl 10035c32 + +10035aca : +10035aca: f5b4 1f80 cmp.w r4, #1048576 ; 0x100000 +10035ace: d22b bcs.n 10035b28 +10035ad0: 3408 adds r4, #8 +10035ad2: ab02 add r3, sp, #8 +10035ad4: 2208 movs r2, #8 +10035ad6: 4621 mov r1, r4 +10035ad8: f000 f8c6 bl 10035c68 + +10035adc : +10035adc: ae02 add r6, sp, #8 +10035ade: 2000 movs r0, #0 +10035ae0: 7230 strb r0, [r6, #8] +10035ae2: a902 add r1, sp, #8 +10035ae4: f20f 2760 addw r7, pc, #608 ; 0x260 +10035ae8: 4638 mov r0, r7 +10035aea: f7ce faa9 bl 10004040 +10035aee: f000 f81d bl 10035b2c + +10035af2 : +10035af2: b9c8 cbnz r0, 10035b28 +10035af4: 2208 movs r2, #8 +10035af6: f20f 2164 addw r1, pc, #612 ; 0x264 +10035afa: a802 add r0, sp, #8 +10035afc: f7d1 f894 bl 10006c28 +10035b00: ab02 add r3, sp, #8 +10035b02: 2208 movs r2, #8 +10035b04: 4621 mov r1, r4 +10035b06: f000 f8a3 bl 10035c50 + +10035b0a : +10035b0a: ab02 add r3, sp, #8 +10035b0c: 2208 movs r2, #8 +10035b0e: 4621 mov r1, r4 +10035b10: f000 f8aa bl 10035c68 + +10035b14 : +10035b14: 2000 movs r0, #0 +10035b16: 7230 strb r0, [r6, #8] +10035b18: a902 add r1, sp, #8 +10035b1a: 4638 mov r0, r7 +10035b1c: f7ce fa90 bl 10004040 +10035b20: f20f 2044 addw r0, pc, #580 ; 0x244 +10035b24: f7ce fa8c bl 10004040 + +10035b28 : +10035b28: b007 add sp, #28 +10035b2a: bdf0 pop {r4, r5, r6, r7, pc} + +10035b2c : +10035b2c: 2208 movs r2, #8 +10035b2e: 4629 mov r1, r5 +10035b30: a802 add r0, sp, #8 +10035b32: f7d1 b885 b.w 10006c40 + +10035b36 : +10035b36: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +10035b3a: b086 sub sp, #24 +10035b3c: f000 f87e bl 10035c3c + +10035b40 : +10035b40: f000 f892 bl 10035c68 + +10035b44 : +10035b44: 9801 ldr r0, [sp, #4] +10035b46: 0400 lsls r0, r0, #16 +10035b48: 0980 lsrs r0, r0, #6 +10035b4a: 9001 str r0, [sp, #4] +10035b4c: f100 0108 add.w r1, r0, #8 +10035b50: ab03 add r3, sp, #12 +10035b52: f000 f888 bl 10035c66 + +10035b56 : +10035b56: f20f 2504 addw r5, pc, #516 ; 0x204 +10035b5a: f000 f87c bl 10035c56 + +10035b5e : +10035b5e: b900 cbnz r0, 10035b62 +10035b60: 9c01 ldr r4, [sp, #4] + +10035b62 : +10035b62: ab02 add r3, sp, #8 +10035b64: 2204 movs r2, #4 +10035b66: f44f 4110 mov.w r1, #36864 ; 0x9000 +10035b6a: f000 f87d bl 10035c68 + +10035b6e : +10035b6e: 9802 ldr r0, [sp, #8] +10035b70: f100 0108 add.w r1, r0, #8 +10035b74: ab03 add r3, sp, #12 +10035b76: f000 f876 bl 10035c66 + +10035b7a : +10035b7a: f000 f86c bl 10035c56 + +10035b7e : +10035b7e: b900 cbnz r0, 10035b82 +10035b80: 9c02 ldr r4, [sp, #8] + +10035b82 : +10035b82: f000 f856 bl 10035c32 + +10035b86 : +10035b86: f5b4 1f80 cmp.w r4, #1048576 ; 0x100000 +10035b8a: d24f bcs.n 10035c2c +10035b8c: f104 0608 add.w r6, r4, #8 +10035b90: ab03 add r3, sp, #12 +10035b92: 2208 movs r2, #8 +10035b94: 4631 mov r1, r6 +10035b96: f000 f867 bl 10035c68 + +10035b9a : +10035b9a: af03 add r7, sp, #12 +10035b9c: 2000 movs r0, #0 +10035b9e: 7238 strb r0, [r7, #8] +10035ba0: a903 add r1, sp, #12 +10035ba2: f20f 18a4 addw r8, pc, #420 ; 0x1a4 +10035ba6: 4640 mov r0, r8 +10035ba8: f7ce fa4a bl 10004040 +10035bac: f000 f853 bl 10035c56 + +10035bb0 : +10035bb0: 2800 cmp r0, #0 +10035bb2: d13b bne.n 10035c2c +10035bb4: f44f 5080 mov.w r0, #4096 ; 0x1000 +10035bb8: f7de f93c bl 10013e34 +10035bbc: 0005 movs r5, r0 +10035bbe: d035 beq.n 10035c2c +10035bc0: 462b mov r3, r5 +10035bc2: f44f 5280 mov.w r2, #4096 ; 0x1000 +10035bc6: 4621 mov r1, r4 +10035bc8: f000 f84e bl 10035c68 + +10035bcc : +10035bcc: 2208 movs r2, #8 +10035bce: f20f 1154 addw r1, pc, #340 ; 0x154 +10035bd2: f105 0008 add.w r0, r5, #8 +10035bd6: f7d1 f827 bl 10006c28 +10035bda: f000 f89e bl 10035d1a + +10035bde : +10035bde: 462b mov r3, r5 +10035be0: f000 f832 bl 10035c48 + +10035be4 : +10035be4: 462b mov r3, r5 +10035be6: f44f 5280 mov.w r2, #4096 ; 0x1000 +10035bea: f44f 4100 mov.w r1, #32768 ; 0x8000 +10035bee: f000 f83b bl 10035c68 + +10035bf2 : +10035bf2: 4621 mov r1, r4 +10035bf4: f000 f893 bl 10035d1e + +10035bf8 : +10035bf8: 462b mov r3, r5 +10035bfa: f44f 5280 mov.w r2, #4096 ; 0x1000 +10035bfe: 4621 mov r1, r4 +10035c00: f000 f826 bl 10035c50 + +10035c04 : +10035c04: ab03 add r3, sp, #12 +10035c06: 2208 movs r2, #8 +10035c08: 4631 mov r1, r6 +10035c0a: f000 f82d bl 10035c68 + +10035c0e : +10035c0e: 2000 movs r0, #0 +10035c10: 7238 strb r0, [r7, #8] +10035c12: a903 add r1, sp, #12 +10035c14: 4640 mov r0, r8 +10035c16: f7ce fa13 bl 10004040 +10035c1a: f44f 5180 mov.w r1, #4096 ; 0x1000 +10035c1e: 4628 mov r0, r5 +10035c20: f7de f914 bl 10013e4c +10035c24: f20f 1060 addw r0, pc, #352 ; 0x160 +10035c28: f7ce fa0a bl 10004040 + +10035c2c : +10035c2c: b006 add sp, #24 +10035c2e: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +10035c32 : +10035c32: 4621 mov r1, r4 +10035c34: f20f 00f8 addw r0, pc, #248 ; 0xf8 +10035c38: f7ce ba02 b.w 10004040 + +10035c3c : +10035c3c: f04f 34ff mov.w r4, #4294967295 +10035c40: ab01 add r3, sp, #4 +10035c42: 2204 movs r2, #4 +10035c44: 2118 movs r1, #24 +10035c46: 4770 bx lr + +10035c48 : +10035c48: f44f 5280 mov.w r2, #4096 ; 0x1000 +10035c4c: f44f 4100 mov.w r1, #32768 ; 0x8000 + +10035c50 : +10035c50: a800 add r0, sp, #0 +10035c52: f7fb bcbf b.w 100315d4 + +10035c56 : +10035c56: 2208 movs r2, #8 +10035c58: 4629 mov r1, r5 +10035c5a: a803 add r0, sp, #12 +10035c5c: f7d0 bff0 b.w 10006c40 + +10035c60 : +10035c60: f100 0108 add.w r1, r0, #8 +10035c64: ab02 add r3, sp, #8 + +10035c66 : +10035c66: 2208 movs r2, #8 + +10035c68 : +10035c68: a800 add r0, sp, #0 +10035c6a: f7fb bc63 b.w 10031534 + +10035c6e : +10035c6e: f000 b9d4 b.w 1003601a + +10035c72 : +10035c72: f000 ba09 b.w 10036088 + +10035c76 : +10035c76: b570 push {r4, r5, r6, lr} +10035c78: b082 sub sp, #8 +10035c7a: 460c mov r4, r1 +10035c7c: 4615 mov r5, r2 +10035c7e: 2800 cmp r0, #0 +10035c80: d032 beq.n 10035ce8 +10035c82: f44f 5080 mov.w r0, #4096 ; 0x1000 +10035c86: f7de f8d5 bl 10013e34 +10035c8a: 0006 movs r6, r0 +10035c8c: d03e beq.n 10035d0c +10035c8e: f000 f83e bl 10035d0e + +10035c92 : +10035c92: f7ff ffe9 bl 10035c68 + +10035c96 : +10035c96: 2202 movs r2, #2 +10035c98: 4621 mov r1, r4 +10035c9a: f506 7000 add.w r0, r6, #512 ; 0x200 +10035c9e: f7d0 ffc3 bl 10006c28 +10035ca2: 2202 movs r2, #2 +10035ca4: 4629 mov r1, r5 +10035ca6: f206 2002 addw r0, r6, #514 ; 0x202 +10035caa: f7d0 ffbd bl 10006c28 +10035cae: f000 f834 bl 10035d1a + +10035cb2 : +10035cb2: 4633 mov r3, r6 +10035cb4: f7ff ffc8 bl 10035c48 + +10035cb8 : +10035cb8: 4633 mov r3, r6 +10035cba: f44f 5280 mov.w r2, #4096 ; 0x1000 +10035cbe: f44f 4100 mov.w r1, #32768 ; 0x8000 +10035cc2: f7ff ffd1 bl 10035c68 + +10035cc6 : +10035cc6: f44f 4110 mov.w r1, #36864 ; 0x9000 +10035cca: f000 f828 bl 10035d1e + +10035cce : +10035cce: f000 f81e bl 10035d0e + +10035cd2 : +10035cd2: f7ff ffbd bl 10035c50 + +10035cd6 : +10035cd6: f44f 5180 mov.w r1, #4096 ; 0x1000 +10035cda: 4630 mov r0, r6 +10035cdc: f7de f8b6 bl 10013e4c +10035ce0: f20f 00c8 addw r0, pc, #200 ; 0xc8 +10035ce4: f7ce f9ac bl 10004040 + +10035ce8 : +10035ce8: 4623 mov r3, r4 +10035cea: 2202 movs r2, #2 +10035cec: f44f 4112 mov.w r1, #37376 ; 0x9200 +10035cf0: f7ff ffba bl 10035c68 + +10035cf4 : +10035cf4: 462b mov r3, r5 +10035cf6: 2202 movs r2, #2 +10035cf8: f249 2102 movw r1, #37378 ; 0x9202 +10035cfc: f7ff ffb4 bl 10035c68 + +10035d00 : +10035d00: 882a ldrh r2, [r5, #0] +10035d02: 8821 ldrh r1, [r4, #0] +10035d04: f20f 00c8 addw r0, pc, #200 ; 0xc8 +10035d08: f7ce f99a bl 10004040 + +10035d0c : +10035d0c: bd73 pop {r0, r1, r4, r5, r6, pc} + +10035d0e : +10035d0e: 4633 mov r3, r6 +10035d10: f44f 5280 mov.w r2, #4096 ; 0x1000 +10035d14: f44f 4110 mov.w r1, #36864 ; 0x9000 +10035d18: 4770 bx lr + +10035d1a : +10035d1a: f44f 4100 mov.w r1, #32768 ; 0x8000 + +10035d1e : +10035d1e: a800 add r0, sp, #0 +10035d20: f7fb bbda b.w 100314d8 + +10035d24 : +10035d24: 3138 3539 3738 3131 0000 0000 81958711.... + +10035d30 : +10035d30: 0d0a 544f 2041 666f 7366 7465 3d20 3020 ..OTA offset = 0 +10035d40: 2578 3830 0058 0000 x%08X... + +10035d48 : +10035d48: 0d0a 6953 6e67 7461 7275 2065 203d 7325 ..Signature = %s +10035d58: 0000 0000 .... + +10035d5c : +10035d5c: 3030 3030 3030 3030 0000 0000 00000000.... + +10035d68 : +10035d68: 0d0a 6c43 6165 2072 544f 2041 6973 6e67 ..Clear OTA sign +10035d78: 7461 7275 2065 7573 6363 7365 2e73 0000 ature success... + +10035d88 : +10035d88: 0d0a 6552 6f63 6576 2072 544f 2041 6973 ..Recover OTA si +10035d98: 6e67 7461 7275 2065 7573 6363 7365 2e73 gnature success. +10035da8: 0000 0000 .... + +10035dac : +10035dac: 0d0a 7453 726f 2065 4441 2043 6163 696c ..Store ADC cali +10035dbc: 7262 7461 6f69 206e 7573 6363 7365 2e73 bration success. +10035dcc: 0000 0000 .... + +10035dd0 : +10035dd0: 0d0a 4441 2043 666f 7366 7465 3d20 3020 ..ADC offset = 0 +10035de0: 2578 3430 2c58 6720 6961 206e 203d 7830 x%04X, gain = 0x +10035df0: 3025 5834 0a2e 000d %04X.... + +10035df8 : +10035df8: f8df f000 ldr.w pc, [pc] ; 10035dfc +10035dfc: 0000dc91 .word 0x0000dc91 + +10035e00 : +10035e00: f8df f000 ldr.w pc, [pc] ; 10035e04 +10035e04: 0000dbd1 .word 0x0000dbd1 + +10035e08 : +10035e08: 6882 ldr r2, [r0, #8] +10035e0a: 6841 ldr r1, [r0, #4] +10035e0c: 2a01 cmp r2, #1 +10035e0e: d104 bne.n 10035e1a +10035e10: 2903 cmp r1, #3 +10035e12: bf14 ite ne +10035e14: 2103 movne r1, #3 +10035e16: 2104 moveq r1, #4 +10035e18: e007 b.n 10035e2a + +10035e1a : +10035e1a: 2901 cmp r1, #1 +10035e1c: d004 beq.n 10035e28 +10035e1e: 2902 cmp r1, #2 +10035e20: bf0c ite eq +10035e22: 2101 moveq r1, #1 +10035e24: 2100 movne r1, #0 +10035e26: e000 b.n 10035e2a + +10035e28 : +10035e28: 2102 movs r1, #2 + +10035e2a : +10035e2a: 60c1 str r1, [r0, #12] +10035e2c: 4770 bx lr + +10035e2e : +10035e2e: b510 push {r4, lr} +10035e30: 4604 mov r4, r0 +10035e32: f114 0f01 cmn.w r4, #1 +10035e36: d104 bne.n 10035e42 +10035e38: 233f movs r3, #63 ; 0x3f +10035e3a: f20f 02d0 addw r2, pc, #208 ; 0xd0 +10035e3e: f000 f84e bl 10035ede + +10035e42 : +10035e42: 2100 movs r1, #0 +10035e44: 4620 mov r0, r4 +10035e46: f000 f937 bl 100360b8 +10035e4a: 4620 mov r0, r4 +10035e4c: e8bd 4010 ldmia.w sp!, {r4, lr} +10035e50: f7cf bb76 b.w 10005540 + +10035e54 : +10035e54: b510 push {r4, lr} +10035e56: 4604 mov r4, r0 +10035e58: 4608 mov r0, r1 +10035e5a: f110 0f01 cmn.w r0, #1 +10035e5e: d009 beq.n 10035e74 +10035e60: 6020 str r0, [r4, #0] +10035e62: 2100 movs r1, #0 +10035e64: 6061 str r1, [r4, #4] +10035e66: 60a1 str r1, [r4, #8] +10035e68: f7ff ffe1 bl 10035e2e +10035e6c: 6120 str r0, [r4, #16] +10035e6e: 2000 movs r0, #0 +10035e70: 60e0 str r0, [r4, #12] +10035e72: e005 b.n 10035e80 + +10035e74 : +10035e74: bd10 pop {r4, pc} + +10035e76 : +10035e76: b510 push {r4, lr} +10035e78: 4604 mov r4, r0 +10035e7a: 6061 str r1, [r4, #4] +10035e7c: f7ff ffc4 bl 10035e08 + +10035e80 : +10035e80: f104 000c add.w r0, r4, #12 +10035e84: e8bd 4010 ldmia.w sp!, {r4, lr} +10035e88: f7cf bb5c b.w 10005544 + +10035e8c : +10035e8c: b538 push {r3, r4, r5, lr} +10035e8e: f000 f820 bl 10035ed2 + +10035e92 : +10035e92: d104 bne.n 10035e9e +10035e94: 235e movs r3, #94 ; 0x5e +10035e96: f20f 02e0 addw r2, pc, #224 ; 0xe0 +10035e9a: f000 f820 bl 10035ede + +10035e9e : +10035e9e: 60a5 str r5, [r4, #8] +10035ea0: 4620 mov r0, r4 +10035ea2: f7ff ffb1 bl 10035e08 +10035ea6: f104 000c add.w r0, r4, #12 +10035eaa: e8bd 4032 ldmia.w sp!, {r1, r4, r5, lr} +10035eae: f7cf bb49 b.w 10005544 + +10035eb2 : +10035eb2: b538 push {r3, r4, r5, lr} +10035eb4: f000 f80d bl 10035ed2 + +10035eb8 : +10035eb8: d104 bne.n 10035ec4 +10035eba: 2368 movs r3, #104 ; 0x68 +10035ebc: f20f 02c4 addw r2, pc, #196 ; 0xc4 +10035ec0: f000 f80d bl 10035ede + +10035ec4 : +10035ec4: 4629 mov r1, r5 +10035ec6: f104 000c add.w r0, r4, #12 +10035eca: e8bd 4034 ldmia.w sp!, {r2, r4, r5, lr} +10035ece: f7ff bf93 b.w 10035df8 + +10035ed2 : +10035ed2: 4604 mov r4, r0 +10035ed4: 460d mov r5, r1 +10035ed6: 6820 ldr r0, [r4, #0] +10035ed8: f110 0f01 cmn.w r0, #1 +10035edc: 4770 bx lr + +10035ede : +10035ede: f20f 0150 addw r1, pc, #80 ; 0x50 +10035ee2: f20f 0034 addw r0, pc, #52 ; 0x34 +10035ee6: f7ce b8ab b.w 10004040 + +10035eea : +10035eea: b510 push {r4, lr} +10035eec: 4604 mov r4, r0 +10035eee: 6820 ldr r0, [r4, #0] +10035ef0: f110 0f01 cmn.w r0, #1 +10035ef4: d104 bne.n 10035f00 +10035ef6: 236e movs r3, #110 ; 0x6e +10035ef8: f20f 0294 addw r2, pc, #148 ; 0x94 +10035efc: f7ff ffef bl 10035ede + +10035f00 : +10035f00: f104 000c add.w r0, r4, #12 +10035f04: e8bd 4010 ldmia.w sp!, {r4, lr} +10035f08: f7ff bf7a b.w 10035e00 + +10035f0c : +10035f0c: 7067 6f69 735f 7465 0000 0000 gpio_set.... + +10035f18 : +10035f18: 7341 6573 7472 6f69 3a6e 2520 3a73 7325 Assertion: %s:%s +10035f28: 202c 6425 000a 0000 , %d.... + +10035f30 : +10035f30: 3a44 615c 656d 6162 775f 3273 3138 6232 D:\ameba_ws2812b +10035f40: 635c 6d6f 6f70 656e 746e 635c 6d6f 6f6d \component\commo +10035f50: 5c6e 626d 6465 745c 7261 6567 7374 685c n\mbed\targets\h +10035f60: 6c61 725c 6c74 3138 3539 5c61 7067 6f69 al\rtl8195a\gpio +10035f70: 615f 6970 632e 0000 _api.c.. + +10035f78 : +10035f78: 7067 6f69 645f 7269 0000 0000 gpio_dir.... + +10035f84 : +10035f84: 7067 6f69 775f 6972 6574 0000 gpio_write.. + +10035f90 : +10035f90: 7067 6f69 725f 6165 0064 0000 gpio_read... + +10035f9c : +10035f9c: b40e push {r1, r2, r3} +10035f9e: b500 push {lr} +10035fa0: b082 sub sp, #8 +10035fa2: a903 add r1, sp, #12 +10035fa4: 9100 str r1, [sp, #0] +10035fa6: 4602 mov r2, r0 +10035fa8: ab00 add r3, sp, #0 +10035faa: 2101 movs r1, #1 +10035fac: 4803 ldr r0, [pc, #12] ; (10035fbc ) +10035fae: 4478 add r0, pc +10035fb0: 300a adds r0, #10 +10035fb2: f000 f88e bl 100360d2 <_PrintfTiny> +10035fb6: bc06 pop {r1, r2} +10035fb8: f85d fb10 ldr.w pc, [sp], #16 +10035fbc: 0000dbb1 .word 0x0000dbb1 + +10035fc0 : +10035fc0: b51f push {r0, r1, r2, r3, r4, lr} +10035fc2: 4c39 ldr r4, [pc, #228] ; (100360a8 <.text_5>) +10035fc4: 2000 movs r0, #0 +10035fc6: 6060 str r0, [r4, #4] +10035fc8: 2080 movs r0, #128 ; 0x80 +10035fca: 60e0 str r0, [r4, #12] +10035fcc: f7dd fc78 bl 100138c0 +10035fd0: 0880 lsrs r0, r0, #2 +10035fd2: 9900 ldr r1, [sp, #0] +10035fd4: 0109 lsls r1, r1, #4 +10035fd6: fbb0 f2f1 udiv r2, r0, r1 +10035fda: 230a movs r3, #10 +10035fdc: 4358 muls r0, r3 +10035fde: fbb0 f0f1 udiv r0, r0, r1 +10035fe2: fb03 0012 mls r0, r3, r2, r0 +10035fe6: 2805 cmp r0, #5 +10035fe8: bf28 it cs +10035fea: 1c52 addcs r2, r2, #1 +10035fec: b2d0 uxtb r0, r2 +10035fee: 6020 str r0, [r4, #0] +10035ff0: f3c2 2007 ubfx r0, r2, #8, #8 +10035ff4: 6060 str r0, [r4, #4] +10035ff6: 2000 movs r0, #0 +10035ff8: 60e0 str r0, [r4, #12] +10035ffa: f89d 100d ldrb.w r1, [sp, #13] +10035ffe: f89d 000c ldrb.w r0, [sp, #12] +10036002: 4308 orrs r0, r1 +10036004: f89d 100e ldrb.w r1, [sp, #14] +10036008: 4308 orrs r0, r1 +1003600a: 60e0 str r0, [r4, #12] +1003600c: 9801 ldr r0, [sp, #4] +1003600e: 60a0 str r0, [r4, #8] +10036010: 9802 ldr r0, [sp, #8] +10036012: 6060 str r0, [r4, #4] +10036014: b004 add sp, #16 +10036016: 2000 movs r0, #0 +10036018: bd10 pop {r4, pc} + +1003601a : +1003601a: b500 push {lr} +1003601c: 4822 ldr r0, [pc, #136] ; (100360a8 <.text_5>) +1003601e: b089 sub sp, #36 ; 0x24 +10036020: 6800 ldr r0, [r0, #0] +10036022: 4822 ldr r0, [pc, #136] ; (100360ac <.text_6>) +10036024: 6801 ldr r1, [r0, #0] +10036026: f421 5180 bic.w r1, r1, #4096 ; 0x1000 +1003602a: 6001 str r1, [r0, #0] +1003602c: 2201 movs r2, #1 +1003602e: 6801 ldr r1, [r0, #0] +10036030: f441 5180 orr.w r1, r1, #4096 ; 0x1000 +10036034: 6001 str r1, [r0, #0] +10036036: 6a01 ldr r1, [r0, #32] +10036038: f441 5180 orr.w r1, r1, #4096 ; 0x1000 +1003603c: 6201 str r1, [r0, #32] +1003603e: 20dc movs r0, #220 ; 0xdc +10036040: 2100 movs r1, #0 +10036042: f7dd fc41 bl 100138c8 +10036046: f44f 4016 mov.w r0, #38400 ; 0x9600 +1003604a: 9000 str r0, [sp, #0] +1003604c: 2003 movs r0, #3 +1003604e: f88d 000e strb.w r0, [sp, #14] +10036052: 20c1 movs r0, #193 ; 0xc1 +10036054: 9001 str r0, [sp, #4] +10036056: 2005 movs r0, #5 +10036058: 9002 str r0, [sp, #8] +1003605a: 2000 movs r0, #0 +1003605c: f8ad 000c strh.w r0, [sp, #12] +10036060: a800 add r0, sp, #0 +10036062: c80f ldmia r0, {r0, r1, r2, r3} +10036064: f7ff ffac bl 10035fc0 +10036068: 2000 movs r0, #0 +1003606a: 9006 str r0, [sp, #24] +1003606c: 2058 movs r0, #88 ; 0x58 +1003606e: 9005 str r0, [sp, #20] +10036070: 480f ldr r0, [pc, #60] ; (100360b0 <.text_7>) +10036072: 9004 str r0, [sp, #16] +10036074: 2000 movs r0, #0 +10036076: 9007 str r0, [sp, #28] +10036078: a804 add r0, sp, #16 +1003607a: f7ea f92d bl 100202d8 +1003607e: a804 add r0, sp, #16 +10036080: f7d0 fdd6 bl 10006c30 +10036084: b009 add sp, #36 ; 0x24 +10036086: bd00 pop {pc} + +10036088 : +10036088: b580 push {r7, lr} +1003608a: 2064 movs r0, #100 ; 0x64 +1003608c: f7d0 fdc8 bl 10006c20 +10036090: 4808 ldr r0, [pc, #32] ; (100360b4 <.text_8>) +10036092: 7800 ldrb r0, [r0, #0] +10036094: 0640 lsls r0, r0, #25 +10036096: d5f8 bpl.n 1003608a +10036098: e8bd 4008 ldmia.w sp!, {r3, lr} +1003609c: 2200 movs r2, #0 +1003609e: 2100 movs r1, #0 +100360a0: 20dc movs r0, #220 ; 0xdc +100360a2: f7dd bc11 b.w 100138c8 + ... + +100360a8 <.text_5>: +100360a8: 40003000 .word 0x40003000 + +100360ac <.text_6>: +100360ac: 40000210 .word 0x40000210 + +100360b0 <.text_7>: +100360b0: 10004879 .word 0x10004879 + +100360b4 <.text_8>: +100360b4: 40003014 .word 0x40003014 + +100360b8 : +100360b8: 4770 bx lr + +100360ba : +100360ba: b570 push {r4, r5, r6, lr} +100360bc: 4604 mov r4, r0 +100360be: 4608 mov r0, r1 +100360c0: 4615 mov r5, r2 +100360c2: 001e movs r6, r3 +100360c4: d004 beq.n 100360d0 +100360c6: f815 1b01 ldrb.w r1, [r5], #1 +100360ca: 47a0 blx r4 +100360cc: 1e76 subs r6, r6, #1 +100360ce: d1fa bne.n 100360c6 +100360d0: bd70 pop {r4, r5, r6, pc} + +100360d2 <_PrintfTiny>: +100360d2: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +100360d6: b084 sub sp, #16 +100360d8: 4682 mov sl, r0 +100360da: 4689 mov r9, r1 +100360dc: 4614 mov r4, r2 +100360de: 461f mov r7, r3 +100360e0: f10d 0800 add.w r8, sp, #0 +100360e4: e007 b.n 100360f6 <_PrintfTiny+0x24> +100360e6: 2301 movs r3, #1 +100360e8: 4622 mov r2, r4 +100360ea: 4649 mov r1, r9 +100360ec: 4650 mov r0, sl +100360ee: f7ff ffe4 bl 100360ba +100360f2: 4681 mov r9, r0 +100360f4: 1c64 adds r4, r4, #1 +100360f6: 7820 ldrb r0, [r4, #0] +100360f8: b910 cbnz r0, 10036100 <_PrintfTiny+0x2e> +100360fa: b004 add sp, #16 +100360fc: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} +10036100: 2825 cmp r0, #37 ; 0x25 +10036102: d1f0 bne.n 100360e6 <_PrintfTiny+0x14> +10036104: 1c64 adds r4, r4, #1 +10036106: f814 0b01 ldrb.w r0, [r4], #1 +1003610a: 4601 mov r1, r0 +1003610c: 2825 cmp r0, #37 ; 0x25 +1003610e: d018 beq.n 10036142 <_PrintfTiny+0x70> +10036110: 2858 cmp r0, #88 ; 0x58 +10036112: d05c beq.n 100361ce <_PrintfTiny+0xfc> +10036114: 2863 cmp r0, #99 ; 0x63 +10036116: d00e beq.n 10036136 <_PrintfTiny+0x64> +10036118: 2864 cmp r0, #100 ; 0x64 +1003611a: bf18 it ne +1003611c: 2869 cmpne r0, #105 ; 0x69 +1003611e: d014 beq.n 1003614a <_PrintfTiny+0x78> +10036120: 286f cmp r0, #111 ; 0x6f +10036122: d054 beq.n 100361ce <_PrintfTiny+0xfc> +10036124: 2870 cmp r0, #112 ; 0x70 +10036126: d058 beq.n 100361da <_PrintfTiny+0x108> +10036128: 2873 cmp r0, #115 ; 0x73 +1003612a: d05d beq.n 100361e8 <_PrintfTiny+0x116> +1003612c: 2875 cmp r0, #117 ; 0x75 +1003612e: bf18 it ne +10036130: 2878 cmpne r0, #120 ; 0x78 +10036132: d04c beq.n 100361ce <_PrintfTiny+0xfc> +10036134: e7df b.n 100360f6 <_PrintfTiny+0x24> +10036136: 6838 ldr r0, [r7, #0] +10036138: 6038 str r0, [r7, #0] +1003613a: f850 1b04 ldr.w r1, [r0], #4 +1003613e: 6038 str r0, [r7, #0] +10036140: b2c9 uxtb r1, r1 +10036142: 4648 mov r0, r9 +10036144: 47d0 blx sl +10036146: 4681 mov r9, r0 +10036148: e7d5 b.n 100360f6 <_PrintfTiny+0x24> +1003614a: 6838 ldr r0, [r7, #0] +1003614c: 6038 str r0, [r7, #0] +1003614e: f850 5b04 ldr.w r5, [r0], #4 +10036152: 6038 str r0, [r7, #0] +10036154: 2d00 cmp r5, #0 +10036156: d503 bpl.n 10036160 <_PrintfTiny+0x8e> +10036158: 212d movs r1, #45 ; 0x2d +1003615a: 4648 mov r0, r9 +1003615c: 47d0 blx sl +1003615e: 4681 mov r9, r0 +10036160: 2064 movs r0, #100 ; 0x64 +10036162: 286f cmp r0, #111 ; 0x6f +10036164: bf08 it eq +10036166: 2208 moveq r2, #8 +10036168: d005 beq.n 10036176 <_PrintfTiny+0xa4> +1003616a: f040 0120 orr.w r1, r0, #32 +1003616e: 2978 cmp r1, #120 ; 0x78 +10036170: bf14 ite ne +10036172: 220a movne r2, #10 +10036174: 2210 moveq r2, #16 +10036176: 210b movs r1, #11 +10036178: 46ac mov ip, r5 +1003617a: 2864 cmp r0, #100 ; 0x64 +1003617c: d103 bne.n 10036186 <_PrintfTiny+0xb4> +1003617e: 2d00 cmp r5, #0 +10036180: bf48 it mi +10036182: f1cc 0c00 rsbmi ip, ip, #0 +10036186: fbbc f5f2 udiv r5, ip, r2 +1003618a: fb02 cc15 mls ip, r2, r5, ip +1003618e: f10c 0630 add.w r6, ip, #48 ; 0x30 +10036192: 1e4b subs r3, r1, #1 +10036194: fa5f fc86 uxtb.w ip, r6 +10036198: 4619 mov r1, r3 +1003619a: f1bc 0f3a cmp.w ip, #58 ; 0x3a +1003619e: bfa4 itt ge +100361a0: f1a0 0e51 subge.w lr, r0, #81 ; 0x51 +100361a4: 44f4 addge ip, lr +100361a6: f803 c008 strb.w ip, [r3, r8] +100361aa: ea5f 0c05 movs.w ip, r5 +100361ae: d001 beq.n 100361b4 <_PrintfTiny+0xe2> +100361b0: 2901 cmp r1, #1 +100361b2: dae8 bge.n 10036186 <_PrintfTiny+0xb4> +100361b4: a800 add r0, sp, #0 +100361b6: 180d adds r5, r1, r0 +100361b8: 4648 mov r0, r9 +100361ba: f1d1 090b rsbs r9, r1, #11 +100361be: d0c2 beq.n 10036146 <_PrintfTiny+0x74> +100361c0: f815 1b01 ldrb.w r1, [r5], #1 +100361c4: 47d0 blx sl +100361c6: f1b9 0901 subs.w r9, r9, #1 +100361ca: d1f9 bne.n 100361c0 <_PrintfTiny+0xee> +100361cc: e7bb b.n 10036146 <_PrintfTiny+0x74> +100361ce: 6839 ldr r1, [r7, #0] +100361d0: 6039 str r1, [r7, #0] +100361d2: f851 5b04 ldr.w r5, [r1], #4 +100361d6: 6039 str r1, [r7, #0] +100361d8: e7c3 b.n 10036162 <_PrintfTiny+0x90> +100361da: 6838 ldr r0, [r7, #0] +100361dc: 6038 str r0, [r7, #0] +100361de: f850 5b04 ldr.w r5, [r0], #4 +100361e2: 6038 str r0, [r7, #0] +100361e4: 2078 movs r0, #120 ; 0x78 +100361e6: e7bc b.n 10036162 <_PrintfTiny+0x90> +100361e8: 6838 ldr r0, [r7, #0] +100361ea: 6038 str r0, [r7, #0] +100361ec: f850 5b04 ldr.w r5, [r0], #4 +100361f0: 6038 str r0, [r7, #0] +100361f2: 4628 mov r0, r5 +100361f4: f000 f80a bl 1003620c +100361f8: 0006 movs r6, r0 +100361fa: 4648 mov r0, r9 +100361fc: d0a3 beq.n 10036146 <_PrintfTiny+0x74> +100361fe: f815 1b01 ldrb.w r1, [r5], #1 +10036202: 47d0 blx sl +10036204: 1e76 subs r6, r6, #1 +10036206: d1fa bne.n 100361fe <_PrintfTiny+0x12c> +10036208: e79d b.n 10036146 <_PrintfTiny+0x74> + ... + +1003620c : +1003620c: f100 0301 add.w r3, r0, #1 +10036210: 0781 lsls r1, r0, #30 +10036212: d004 beq.n 1003621e +10036214: f810 1b01 ldrb.w r1, [r0], #1 +10036218: b189 cbz r1, 1003623e +1003621a: 0781 lsls r1, r0, #30 +1003621c: d1fa bne.n 10036214 +1003621e: 6802 ldr r2, [r0, #0] +10036220: f1b2 3101 subs.w r1, r2, #16843009 ; 0x1010101 +10036224: 4391 bics r1, r2 +10036226: f011 3f80 tst.w r1, #2155905152 ; 0x80808080 +1003622a: bf04 itt eq +1003622c: f850 2f04 ldreq.w r2, [r0, #4]! +10036230: e7f6 beq.n 10036220 +10036232: f810 1b01 ldrb.w r1, [r0], #1 +10036236: b111 cbz r1, 1003623e +10036238: f810 1b01 ldrb.w r1, [r0], #1 +1003623c: e7fb b.n 10036236 +1003623e: 1ac0 subs r0, r0, r3 +10036240: 4770 bx lr + ... + +10036244 : +10036244: b538 push {r3, r4, r5, lr} +10036246: f8df 5b5c ldr.w r5, [pc, #2908] ; 10036da4 +1003624a: 2221 movs r2, #33 ; 0x21 +1003624c: 2100 movs r1, #0 +1003624e: 1c68 adds r0, r5, #1 +10036250: f7d6 f87c bl 1000c34c +10036254: 2206 movs r2, #6 +10036256: 2100 movs r1, #0 +10036258: f105 0022 add.w r0, r5, #34 ; 0x22 +1003625c: f7d6 f876 bl 1000c34c +10036260: f8df 4b44 ldr.w r4, [pc, #2884] ; 10036da8 +10036264: 2241 movs r2, #65 ; 0x41 +10036266: 2100 movs r1, #0 +10036268: f104 0034 add.w r0, r4, #52 ; 0x34 +1003626c: f7d6 f86e bl 1000c34c +10036270: 2000 movs r0, #0 +10036272: 7028 strb r0, [r5, #0] +10036274: 62e8 str r0, [r5, #44] ; 0x2c +10036276: 6328 str r0, [r5, #48] ; 0x30 +10036278: 2221 movs r2, #33 ; 0x21 +1003627a: f04f 30ff mov.w r0, #4294967295 +1003627e: 6368 str r0, [r5, #52] ; 0x34 +10036280: 2100 movs r1, #0 +10036282: 1c60 adds r0, r4, #1 +10036284: f7d6 f862 bl 1000c34c +10036288: 2000 movs r0, #0 +1003628a: 7020 strb r0, [r4, #0] +1003628c: 62a0 str r0, [r4, #40] ; 0x28 +1003628e: 62e0 str r0, [r4, #44] ; 0x2c +10036290: 2001 movs r0, #1 +10036292: 6320 str r0, [r4, #48] ; 0x30 +10036294: bd31 pop {r0, r4, r5, pc} + +10036296 : +10036296: b570 push {r4, r5, r6, lr} +10036298: 4604 mov r4, r0 +1003629a: b084 sub sp, #16 +1003629c: 6ae0 ldr r0, [r4, #44] ; 0x2c +1003629e: 2801 cmp r0, #1 +100362a0: bf0c ite eq +100362a2: f20f 01c0 addweq r1, pc, #192 ; 0xc0 +100362a6: f20f 01c4 addwne r1, pc, #196 ; 0xc4 +100362aa: f20f 00c8 addw r0, pc, #200 ; 0xc8 +100362ae: f7d6 f828 bl 1000c302 +100362b2: f104 0522 add.w r5, r4, #34 ; 0x22 +100362b6: f000 fd31 bl 10036d1c + +100362ba : +100362ba: f894 1022 ldrb.w r1, [r4, #34] ; 0x22 +100362be: f20f 2094 addw r0, pc, #660 ; 0x294 +100362c2: f7d6 f81e bl 1000c302 +100362c6: f9b5 1006 ldrsh.w r1, [r5, #6] +100362ca: f20f 00b0 addw r0, pc, #176 ; 0xb0 +100362ce: f7d6 f818 bl 1000c302 +100362d2: f20f 06b0 addw r6, pc, #176 ; 0xb0 +100362d6: f104 052c add.w r5, r4, #44 ; 0x2c +100362da: 4630 mov r0, r6 +100362dc: 7b29 ldrb r1, [r5, #12] +100362de: f7d6 f810 bl 1000c302 +100362e2: 68a9 ldr r1, [r5, #8] +100362e4: 4630 mov r0, r6 +100362e6: f7d6 f80c bl 1000c302 +100362ea: 6868 ldr r0, [r5, #4] +100362ec: b910 cbnz r0, 100362f4 +100362ee: f20f 019c addw r1, pc, #156 ; 0x9c +100362f2: e027 b.n 10036344 + +100362f4 : +100362f4: 2801 cmp r0, #1 +100362f6: bf08 it eq +100362f8: a195 addeq r1, pc, #596 ; (adr r1, 10036550 ) +100362fa: d023 beq.n 10036344 +100362fc: f8df 1ab0 ldr.w r1, [pc, #2736] ; 10036db0 +10036300: 4288 cmp r0, r1 +10036302: bf08 it eq +10036304: f60f 21e0 addweq r1, pc, #2784 ; 0xae0 +10036308: d01c beq.n 10036344 +1003630a: f8df 1aa8 ldr.w r1, [pc, #2728] ; 10036db4 +1003630e: 4288 cmp r0, r1 +10036310: bf08 it eq +10036312: f60f 21e0 addweq r1, pc, #2784 ; 0xae0 +10036316: d015 beq.n 10036344 +10036318: f8df 1a9c ldr.w r1, [pc, #2716] ; 10036db8 +1003631c: 4288 cmp r0, r1 +1003631e: bf08 it eq +10036320: f60f 21d8 addweq r1, pc, #2776 ; 0xad8 +10036324: d00e beq.n 10036344 +10036326: f8df 1a94 ldr.w r1, [pc, #2708] ; 10036dbc +1003632a: 4288 cmp r0, r1 +1003632c: bf08 it eq +1003632e: f60f 21d8 addweq r1, pc, #2776 ; 0xad8 +10036332: d007 beq.n 10036344 +10036334: f8df 1a88 ldr.w r1, [pc, #2696] ; 10036dc0 +10036338: 4288 cmp r0, r1 +1003633a: bf0c ite eq +1003633c: f60f 21d4 addweq r1, pc, #2772 ; 0xad4 +10036340: f60f 21dc addwne r1, pc, #2780 ; 0xadc + +10036344 : +10036344: f60f 2098 addw r0, pc, #2712 ; 0xa98 +10036348: f7d5 ffdb bl 1000c302 +1003634c: 1c61 adds r1, r4, #1 +1003634e: f60f 20d8 addw r0, pc, #2776 ; 0xad8 +10036352: f7d5 ffd6 bl 1000c302 +10036356: b004 add sp, #16 +10036358: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +1003635c: a0cb add r0, pc, #812 ; (adr r0, 1003668c ) +1003635e: f7d5 bfd0 b.w 1000c302 + ... + +10036364 : +10036364: 6441 6f68 0063 0000 Adhoc... + +1003636c : +1003636c: 6e49 7266 0061 0000 Infra... + +10036374 : +10036374: 7325 2009 0000 0000 %s. .... + +1003637c : +1003637c: 2520 0964 0020 0000 %d. ... + +10036384 : +10036384: 2520 0964 2020 0000 %d. .. + +1003638c : +1003638c: 704f 6e65 0000 0000 Open.... + +10036394 : +10036394: b510 push {r4, lr} +10036396: 4604 mov r4, r0 +10036398: f8df 0a28 ldr.w r0, [pc, #2600] ; 10036dc4 +1003639c: 6c21 ldr r1, [r4, #64] ; 0x40 +1003639e: 2901 cmp r1, #1 +100363a0: d00e beq.n 100363c0 +100363a2: 7822 ldrb r2, [r4, #0] +100363a4: 1912 adds r2, r2, r4 +100363a6: 2100 movs r1, #0 +100363a8: 7051 strb r1, [r2, #1] +100363aa: 6801 ldr r1, [r0, #0] +100363ac: 1c49 adds r1, r1, #1 +100363ae: 6001 str r1, [r0, #0] +100363b0: f60f 207c addw r0, pc, #2684 ; 0xa7c +100363b4: f7d5 ffa5 bl 1000c302 +100363b8: 4620 mov r0, r4 +100363ba: f7ff ff6c bl 10036296 +100363be: e001 b.n 100363c4 + +100363c0 : +100363c0: 2100 movs r1, #0 +100363c2: 6001 str r1, [r0, #0] + +100363c4 : +100363c4: 2000 movs r0, #0 +100363c6: bd10 pop {r4, pc} + +100363c8 : +100363c8: b538 push {r3, r4, r5, lr} +100363ca: 0004 movs r4, r0 +100363cc: d105 bne.n 100363da +100363ce: e8bd 4032 ldmia.w sp!, {r1, r4, r5, lr} +100363d2: f60f 2064 addw r0, pc, #2660 ; 0xa64 +100363d6: f7d5 bf94 b.w 1000c302 + +100363da : +100363da: f60f 2078 addw r0, pc, #2680 ; 0xa78 +100363de: 4621 mov r1, r4 +100363e0: f7d5 ff8f bl 1000c302 +100363e4: f8df 59bc ldr.w r5, [pc, #2492] ; 10036da4 +100363e8: 4621 mov r1, r4 +100363ea: 1c68 adds r0, r5, #1 +100363ec: f7d5 ffb2 bl 1000c354 +100363f0: f000 f83a bl 10036468 + +100363f4 : +100363f4: 7028 strb r0, [r5, #0] +100363f6: bd31 pop {r0, r4, r5, pc} + +100363f8 : +100363f8: b570 push {r4, r5, r6, lr} +100363fa: 4604 mov r4, r0 +100363fc: 4621 mov r1, r4 +100363fe: f60f 2078 addw r0, pc, #2680 ; 0xa78 +10036402: f7d5 ff7e bl 1000c302 +10036406: f000 f862 bl 100364ce + +1003640a : +1003640a: f8df 6998 ldr.w r6, [pc, #2456] ; 10036da4 +1003640e: f105 0034 add.w r0, r5, #52 ; 0x34 +10036412: 62f0 str r0, [r6, #44] ; 0x2c +10036414: f000 f828 bl 10036468 + +10036418 : +10036418: 6330 str r0, [r6, #48] ; 0x30 +1003641a: 2840 cmp r0, #64 ; 0x40 +1003641c: d106 bne.n 1003642c +1003641e: 6af1 ldr r1, [r6, #44] ; 0x2c +10036420: f8df 09a4 ldr.w r0, [pc, #2468] ; 10036dc8 +10036424: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +10036428: f7d5 bf94 b.w 1000c354 + +1003642c : +1003642c: bd70 pop {r4, r5, r6, pc} + +1003642e : +1003642e: b510 push {r4, lr} +10036430: 4604 mov r4, r0 +10036432: 4621 mov r1, r4 +10036434: f60f 2068 addw r0, pc, #2664 ; 0xa68 +10036438: f7d5 ff63 bl 1000c302 +1003643c: f000 f814 bl 10036468 + +10036440 : +10036440: 2801 cmp r0, #1 +10036442: d104 bne.n 1003644e +10036444: f994 0000 ldrsb.w r0, [r4] +10036448: 3830 subs r0, #48 ; 0x30 +1003644a: 2804 cmp r0, #4 +1003644c: d305 bcc.n 1003645a + +1003644e : +1003644e: e8bd 4010 ldmia.w sp!, {r4, lr} +10036452: f60f 2070 addw r0, pc, #2672 ; 0xa70 +10036456: f7d5 bf54 b.w 1000c302 + +1003645a : +1003645a: 4620 mov r0, r4 +1003645c: f7fe fad8 bl 10034a10 +10036460: f8df 1940 ldr.w r1, [pc, #2368] ; 10036da4 +10036464: 6348 str r0, [r1, #52] ; 0x34 +10036466: bd10 pop {r4, pc} + +10036468 : +10036468: 4620 mov r0, r4 +1003646a: f7d5 bf75 b.w 1000c358 + +1003646e : +1003646e: b538 push {r3, r4, r5, lr} +10036470: 0004 movs r4, r0 +10036472: bf08 it eq +10036474: f60f 207c addweq r0, pc, #2684 ; 0xa7c +10036478: d009 beq.n 1003648e +1003647a: f8df 592c ldr.w r5, [pc, #2348] ; 10036da8 +1003647e: f7d5 ff6b bl 1000c358 +10036482: 7028 strb r0, [r5, #0] +10036484: 7828 ldrb r0, [r5, #0] +10036486: 2821 cmp r0, #33 ; 0x21 +10036488: db05 blt.n 10036496 +1003648a: f60f 2084 addw r0, pc, #2692 ; 0xa84 + +1003648e : +1003648e: e8bd 4032 ldmia.w sp!, {r1, r4, r5, lr} +10036492: f7d5 bf36 b.w 1000c302 + +10036496 : +10036496: 4621 mov r1, r4 +10036498: 1c68 adds r0, r5, #1 +1003649a: f7d5 ff5b bl 1000c354 +1003649e: 1c69 adds r1, r5, #1 +100364a0: e8bd 4034 ldmia.w sp!, {r2, r4, r5, lr} +100364a4: f60f 2094 addw r0, pc, #2708 ; 0xa94 +100364a8: f7d5 bf2b b.w 1000c302 + +100364ac : +100364ac: b538 push {r3, r4, r5, lr} +100364ae: 4604 mov r4, r0 +100364b0: f000 f80d bl 100364ce + +100364b4 : +100364b4: f105 0034 add.w r0, r5, #52 ; 0x34 +100364b8: 62a8 str r0, [r5, #40] ; 0x28 +100364ba: f7ff ffd5 bl 10036468 + +100364be : +100364be: 6aa9 ldr r1, [r5, #40] ; 0x28 +100364c0: 62e8 str r0, [r5, #44] ; 0x2c +100364c2: e8bd 4034 ldmia.w sp!, {r2, r4, r5, lr} +100364c6: f60f 209c addw r0, pc, #2716 ; 0xa9c +100364ca: f7d5 bf1a b.w 1000c302 + +100364ce : +100364ce: f8df 58d8 ldr.w r5, [pc, #2264] ; 10036da8 +100364d2: 4621 mov r1, r4 +100364d4: f105 0034 add.w r0, r5, #52 ; 0x34 +100364d8: f7d5 bf3c b.w 1000c354 + +100364dc : +100364dc: b510 push {r4, lr} +100364de: f8df 48c8 ldr.w r4, [pc, #2248] ; 10036da8 +100364e2: f7fe fa95 bl 10034a10 +100364e6: b2c0 uxtb r0, r0 +100364e8: 6320 str r0, [r4, #48] ; 0x30 +100364ea: 4601 mov r1, r0 +100364ec: e8bd 4010 ldmia.w sp!, {r4, lr} +100364f0: f60f 2098 addw r0, pc, #2712 ; 0xa98 +100364f4: f7d5 bf05 b.w 1000c302 + +100364f8 : +100364f8: b510 push {r4, lr} +100364fa: b08a sub sp, #40 ; 0x28 +100364fc: 0004 movs r4, r0 +100364fe: d104 bne.n 1003650a +10036500: f60f 20b8 addw r0, pc, #2744 ; 0xab8 +10036504: f7d5 fefd bl 1000c302 +10036508: e01f b.n 1003654a + +1003650a : +1003650a: 4621 mov r1, r4 +1003650c: f60f 20c8 addw r0, pc, #2760 ; 0xac8 +10036510: f7d5 fef7 bl 1000c302 +10036514: f20f 013c addw r1, pc, #60 ; 0x3c +10036518: a809 add r0, sp, #36 ; 0x24 +1003651a: 9003 str r0, [sp, #12] +1003651c: ab05 add r3, sp, #20 +1003651e: a808 add r0, sp, #32 +10036520: 9002 str r0, [sp, #8] +10036522: aa04 add r2, sp, #16 +10036524: a807 add r0, sp, #28 +10036526: 9001 str r0, [sp, #4] +10036528: a806 add r0, sp, #24 +1003652a: 9000 str r0, [sp, #0] +1003652c: 4620 mov r0, r4 +1003652e: f7ee fb6b bl 10024c08 +10036532: 2000 movs r0, #0 +10036534: f8df 186c ldr.w r1, [pc, #2156] ; 10036da4 + +10036538 : +10036538: aa04 add r2, sp, #16 +1003653a: 1843 adds r3, r0, r1 +1003653c: f852 2020 ldr.w r2, [r2, r0, lsl #2] +10036540: f883 2022 strb.w r2, [r3, #34] ; 0x22 +10036544: 1c40 adds r0, r0, #1 +10036546: 2806 cmp r0, #6 +10036548: d3f6 bcc.n 10036538 + +1003654a : +1003654a: b00a add sp, #40 ; 0x28 +1003654c: bd10 pop {r4, pc} + ... + +10036550 : +10036550: 4557 0050 WEP. + +10036554 : +10036554: 3025 7832 253a 3230 3a78 3025 7832 253a %02x:%02x:%02x:% +10036564: 3230 3a78 3025 7832 253a 3230 0078 0000 02x:%02x:%02x... + +10036574 : +10036574: b570 push {r4, r5, r6, lr} +10036576: b08e sub sp, #56 ; 0x38 +10036578: 2414 movs r4, #20 +1003657a: f60f 2080 addw r0, pc, #2688 ; 0xa80 +1003657e: f7d5 fec0 bl 1000c302 +10036582: f8df 5824 ldr.w r5, [pc, #2084] ; 10036da8 +10036586: 7868 ldrb r0, [r5, #1] +10036588: b910 cbnz r0, 10036590 +1003658a: f60f 2090 addw r0, pc, #2704 ; 0xa90 +1003658e: e05a b.n 10036646 + +10036590 : +10036590: 6aa8 ldr r0, [r5, #40] ; 0x28 +10036592: b108 cbz r0, 10036598 +10036594: f8df 0820 ldr.w r0, [pc, #2080] ; 10036db8 + +10036598 : +10036598: f8df 6830 ldr.w r6, [pc, #2096] ; 10036dcc +1003659c: 6268 str r0, [r5, #36] ; 0x24 +1003659e: 2221 movs r2, #33 ; 0x21 +100365a0: 2100 movs r1, #0 +100365a2: 1d30 adds r0, r6, #4 +100365a4: f7d5 fed2 bl 1000c34c +100365a8: 1c68 adds r0, r5, #1 +100365aa: f7d5 fed5 bl 1000c358 +100365ae: 4602 mov r2, r0 +100365b0: 1c69 adds r1, r5, #1 +100365b2: 1d30 adds r0, r6, #4 +100365b4: f7d5 fec8 bl 1000c348 +100365b8: 7829 ldrb r1, [r5, #0] +100365ba: 1989 adds r1, r1, r6 +100365bc: 2000 movs r0, #0 +100365be: 7108 strb r0, [r1, #4] +100365c0: 6a68 ldr r0, [r5, #36] ; 0x24 +100365c2: 62b0 str r0, [r6, #40] ; 0x28 +100365c4: b100 cbz r0, 100365c8 +100365c6: 2001 movs r0, #1 + +100365c8 : +100365c8: 62b0 str r0, [r6, #40] ; 0x28 +100365ca: 6aa8 ldr r0, [r5, #40] ; 0x28 +100365cc: b140 cbz r0, 100365e0 +100365ce: f7d5 fec3 bl 1000c358 +100365d2: 6aa9 ldr r1, [r5, #40] ; 0x28 +100365d4: 4602 mov r2, r0 +100365d6: f106 002c add.w r0, r6, #44 ; 0x2c +100365da: f7d5 feb5 bl 1000c348 +100365de: e005 b.n 100365ec + +100365e0 : +100365e0: 2241 movs r2, #65 ; 0x41 +100365e2: 2100 movs r1, #0 +100365e4: f106 002c add.w r0, r6, #44 ; 0x2c +100365e8: f7d5 feb0 bl 1000c34c + +100365ec : +100365ec: 6b28 ldr r0, [r5, #48] ; 0x30 +100365ee: f886 0025 strb.w r0, [r6, #37] ; 0x25 +100365f2: f001 f936 bl 10037862 +100365f6: f001 fffb bl 100385f0 +100365fa: f06f 417f mvn.w r1, #4278190080 ; 0xff000000 +100365fe: f8df 07d0 ldr.w r0, [pc, #2000] ; 10036dd0 +10036602: 9004 str r0, [sp, #16] +10036604: 9103 str r1, [sp, #12] +10036606: 9002 str r0, [sp, #8] +10036608: ab02 add r3, sp, #8 +1003660a: f8df 67c8 ldr.w r6, [pc, #1992] ; 10036dd4 +1003660e: aa03 add r2, sp, #12 +10036610: a904 add r1, sp, #16 +10036612: 4630 mov r0, r6 +10036614: f7d8 fd07 bl 1000f026 +10036618: f002 fd7e bl 10039118 +1003661c: 2014 movs r0, #20 +1003661e: f7d4 fa58 bl 1000aad2 +10036622: 2002 movs r0, #2 +10036624: f002 fd31 bl 1003908a +10036628: 2800 cmp r0, #0 +1003662a: bf48 it mi +1003662c: f60f 2010 addwmi r0, pc, #2576 ; 0xa10 +10036630: d409 bmi.n 10036646 +10036632: f60f 2028 addw r0, pc, #2600 ; 0xa28 +10036636: f7d5 fe64 bl 1000c302 +1003663a: f000 f9f7 bl 10036a2c + +1003663e : +1003663e: 2800 cmp r0, #0 +10036640: d507 bpl.n 10036652 +10036642: f60f 202c addw r0, pc, #2604 ; 0xa2c + +10036646 : +10036646: f7d5 fe5c bl 1000c302 +1003664a: e01c b.n 10036686 + +1003664c : +1003664c: f000 f8eb bl 10036826 + +10036650 : +10036650: 1e64 subs r4, r4, #1 + +10036652 : +10036652: a905 add r1, sp, #20 +10036654: f60f 2034 addw r0, pc, #2612 ; 0xa34 +10036658: f7eb fdd4 bl 10022204 +1003665c: 2801 cmp r0, #1 +1003665e: db07 blt.n 10036670 +10036660: 1c69 adds r1, r5, #1 +10036662: a805 add r0, sp, #20 +10036664: f7d5 fe74 bl 1000c350 +10036668: b910 cbnz r0, 10036670 +1003666a: f000 f9e9 bl 10036a40 + +1003666e : +1003666e: e005 b.n 1003667c + +10036670 : +10036670: 2c00 cmp r4, #0 +10036672: d1eb bne.n 1003664c +10036674: f60f 202c addw r0, pc, #2604 ; 0xa2c +10036678: f7d5 fe43 bl 1000c302 + +1003667c : +1003667c: 4630 mov r0, r6 +1003667e: f001 ff5f bl 10038540 +10036682: f7ff fddf bl 10036244 + +10036686 : +10036686: b00e add sp, #56 ; 0x38 +10036688: bd70 pop {r4, r5, r6, pc} + ... + +1003668c : +1003668c: 0a0d 0000 .... + +10036690 : +10036690: b570 push {r4, r5, r6, lr} +10036692: b088 sub sp, #32 +10036694: f7d4 fb31 bl 1000acfa +10036698: 4604 mov r4, r0 +1003669a: a806 add r0, sp, #24 +1003669c: 2100 movs r1, #0 +1003669e: 2200 movs r2, #0 +100366a0: c006 stmia r0!, {r1, r2} +100366a2: 460e mov r6, r1 +100366a4: f60f 2018 addw r0, pc, #2584 ; 0xa18 +100366a8: f7d5 fe2b bl 1000c302 +100366ac: f8df 56f4 ldr.w r5, [pc, #1780] ; 10036da4 +100366b0: 2206 movs r2, #6 +100366b2: a906 add r1, sp, #24 +100366b4: f105 0022 add.w r0, r5, #34 ; 0x22 +100366b8: f7d5 fe44 bl 1000c344 +100366bc: b148 cbz r0, 100366d2 +100366be: 2601 movs r6, #1 + +100366c0 : +100366c0: 6ae8 ldr r0, [r5, #44] ; 0x2c +100366c2: b160 cbz r0, 100366de +100366c4: 6b68 ldr r0, [r5, #52] ; 0x34 +100366c6: 2804 cmp r0, #4 +100366c8: bf34 ite cc +100366ca: 2001 movcc r0, #1 +100366cc: f8df 06e8 ldrcs.w r0, [pc, #1768] ; 10036db8 +100366d0: e005 b.n 100366de + +100366d2 : +100366d2: 7868 ldrb r0, [r5, #1] +100366d4: 2800 cmp r0, #0 +100366d6: d1f3 bne.n 100366c0 +100366d8: f60f 2004 addw r0, pc, #2564 ; 0xa04 +100366dc: e065 b.n 100367aa + +100366de : +100366de: 62a8 str r0, [r5, #40] ; 0x28 +100366e0: a905 add r1, sp, #20 +100366e2: f60f 10a8 addw r0, pc, #2472 ; 0x9a8 +100366e6: f7eb ff2f bl 10022548 +100366ea: 9805 ldr r0, [sp, #20] +100366ec: 2803 cmp r0, #3 +100366ee: d10e bne.n 1003670e +100366f0: f001 ff7e bl 100385f0 +100366f4: f002 fd10 bl 10039118 +100366f8: 2014 movs r0, #20 +100366fa: f7d4 f9ea bl 1000aad2 +100366fe: 2001 movs r0, #1 +10036700: f002 fcc3 bl 1003908a +10036704: 2800 cmp r0, #0 +10036706: bf48 it mi +10036708: f60f 1034 addwmi r0, pc, #2356 ; 0x934 +1003670c: d44d bmi.n 100367aa + +1003670e : +1003670e: b326 cbz r6, 1003675a +10036710: f895 0027 ldrb.w r0, [r5, #39] ; 0x27 +10036714: f895 3024 ldrb.w r3, [r5, #36] ; 0x24 +10036718: f895 2023 ldrb.w r2, [r5, #35] ; 0x23 +1003671c: f895 1022 ldrb.w r1, [r5, #34] ; 0x22 +10036720: 9002 str r0, [sp, #8] +10036722: f895 0026 ldrb.w r0, [r5, #38] ; 0x26 +10036726: 9001 str r0, [sp, #4] +10036728: f895 0025 ldrb.w r0, [r5, #37] ; 0x25 +1003672c: 9000 str r0, [sp, #0] +1003672e: f60f 10d4 addw r0, pc, #2516 ; 0x9d4 +10036732: f7d5 fde6 bl 1000c302 +10036736: 6aeb ldr r3, [r5, #44] ; 0x2c +10036738: 6aaa ldr r2, [r5, #40] ; 0x28 +1003673a: 2000 movs r0, #0 +1003673c: 9004 str r0, [sp, #16] +1003673e: 1c69 adds r1, r5, #1 +10036740: 6b68 ldr r0, [r5, #52] ; 0x34 +10036742: 9003 str r0, [sp, #12] +10036744: 6b28 ldr r0, [r5, #48] ; 0x30 +10036746: 9002 str r0, [sp, #8] +10036748: 7828 ldrb r0, [r5, #0] +1003674a: 9001 str r0, [sp, #4] +1003674c: 2006 movs r0, #6 +1003674e: 9000 str r0, [sp, #0] +10036750: f105 0022 add.w r0, r5, #34 ; 0x22 +10036754: f002 fb40 bl 10038dd8 +10036758: e010 b.n 1003677c + +1003675a : +1003675a: 1c69 adds r1, r5, #1 +1003675c: f60f 10e0 addw r0, pc, #2528 ; 0x9e0 +10036760: f7d5 fdcf bl 1000c302 +10036764: 782b ldrb r3, [r5, #0] +10036766: 6aea ldr r2, [r5, #44] ; 0x2c +10036768: 6aa9 ldr r1, [r5, #40] ; 0x28 +1003676a: 2000 movs r0, #0 +1003676c: 9002 str r0, [sp, #8] +1003676e: 6b68 ldr r0, [r5, #52] ; 0x34 +10036770: 9001 str r0, [sp, #4] +10036772: 6b28 ldr r0, [r5, #48] ; 0x30 +10036774: 9000 str r0, [sp, #0] +10036776: 1c68 adds r0, r5, #1 +10036778: f002 f9fa bl 10038b70 + +1003677c : +1003677c: b110 cbz r0, 10036784 +1003677e: f60f 00f0 addw r0, pc, #2288 ; 0x8f0 +10036782: e012 b.n 100367aa + +10036784 : +10036784: f7d4 fab9 bl 1000acfa +10036788: 1b01 subs r1, r0, r4 +1003678a: f60f 10d4 addw r0, pc, #2516 ; 0x9d4 +1003678e: f7d5 fdb8 bl 1000c302 +10036792: 2100 movs r1, #0 +10036794: 2000 movs r0, #0 +10036796: f003 fa3a bl 10039c0e +1003679a: f7d4 faae bl 1000acfa +1003679e: 1b01 subs r1, r0, r4 +100367a0: f60f 10d8 addw r0, pc, #2520 ; 0x9d8 +100367a4: f7d5 fdad bl 1000c302 +100367a8: a09d add r0, pc, #628 ; (adr r0, 10036a20 ) + +100367aa : +100367aa: f7d5 fdaa bl 1000c302 +100367ae: f7ff fd49 bl 10036244 +100367b2: b008 add sp, #32 +100367b4: bd70 pop {r4, r5, r6, pc} + +100367b6 : +100367b6: b570 push {r4, r5, r6, lr} +100367b8: b08a sub sp, #40 ; 0x28 +100367ba: 2414 movs r4, #20 +100367bc: f60f 10d4 addw r0, pc, #2516 ; 0x9d4 +100367c0: f7d5 fd9f bl 1000c302 +100367c4: f60f 10ec addw r0, pc, #2540 ; 0x9ec +100367c8: f7d5 fd9b bl 1000c302 +100367cc: f60f 06bc addw r6, pc, #2236 ; 0x8bc +100367d0: f60f 15f8 addw r5, pc, #2552 ; 0x9f8 +100367d4: a900 add r1, sp, #0 +100367d6: 4630 mov r0, r6 +100367d8: f7eb fd14 bl 10022204 +100367dc: 2800 cmp r0, #0 +100367de: bf48 it mi +100367e0: 4628 movmi r0, r5 +100367e2: d405 bmi.n 100367f0 +100367e4: f002 fbd4 bl 10038f90 +100367e8: 2800 cmp r0, #0 +100367ea: d507 bpl.n 100367fc +100367ec: f60f 0080 addw r0, pc, #2176 ; 0x880 + +100367f0 : +100367f0: f7d5 fd87 bl 1000c302 +100367f4: e015 b.n 10036822 + +100367f6 : +100367f6: f000 f816 bl 10036826 + +100367fa : +100367fa: 1e64 subs r4, r4, #1 + +100367fc : +100367fc: a900 add r1, sp, #0 +100367fe: 4630 mov r0, r6 +10036800: f7eb fd00 bl 10022204 +10036804: 2800 cmp r0, #0 +10036806: d501 bpl.n 1003680c +10036808: 4628 mov r0, r5 +1003680a: e003 b.n 10036814 + +1003680c : +1003680c: 2c00 cmp r4, #0 +1003680e: d1f2 bne.n 100367f6 +10036810: f60f 10cc addw r0, pc, #2508 ; 0x9cc + +10036814 : +10036814: f7d5 fd75 bl 1000c302 +10036818: a081 add r0, pc, #516 ; (adr r0, 10036a20 ) +1003681a: f7d5 fd72 bl 1000c302 +1003681e: f7ff fd11 bl 10036244 + +10036822 : +10036822: b00a add sp, #40 ; 0x28 +10036824: bd70 pop {r4, r5, r6, pc} + +10036826 : +10036826: f44f 707a mov.w r0, #1000 ; 0x3e8 +1003682a: f7d4 b952 b.w 1000aad2 + +1003682e : +1003682e: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} +10036832: b08f sub sp, #60 ; 0x3c +10036834: 4605 mov r5, r0 +10036836: f000 f860 bl 100368fa + +1003683a : +1003683a: 2400 movs r4, #0 +1003683c: a800 add r0, sp, #0 +1003683e: 2118 movs r1, #24 +10036840: f7ee ffec bl 1002581c <__aeabi_memclr4> +10036844: f60f 10b4 addw r0, pc, #2484 ; 0x9b4 +10036848: f7d5 fd5b bl 1000c302 +1003684c: 2d00 cmp r5, #0 +1003684e: d040 beq.n 100368d2 +10036850: 4629 mov r1, r5 +10036852: a806 add r0, sp, #24 +10036854: f7d5 fd7e bl 1000c354 +10036858: a900 add r1, sp, #0 +1003685a: a806 add r0, sp, #24 +1003685c: f7ff f8cc bl 100359f8 +10036860: 4606 mov r6, r0 +10036862: 2e02 cmp r6, #2 +10036864: db46 blt.n 100368f4 +10036866: 9801 ldr r0, [sp, #4] +10036868: f7fe f8d2 bl 10034a10 +1003686c: 4681 mov r9, r0 +1003686e: f7d6 f821 bl 1000c8b4 +10036872: 0004 movs r4, r0 +10036874: d104 bne.n 10036880 +10036876: f60f 10a0 addw r0, pc, #2464 ; 0x9a0 +1003687a: f7d5 fd42 bl 1000c302 +1003687e: e039 b.n 100368f4 + +10036880 : +10036880: 4648 mov r0, r9 +10036882: f7d6 f817 bl 1000c8b4 +10036886: ea5f 0800 movs.w r8, r0 +1003688a: bf08 it eq +1003688c: f60f 10bc addweq r0, pc, #2492 ; 0x9bc +10036890: d01c beq.n 100368cc +10036892: 2702 movs r7, #2 +10036894: e00d b.n 100368b2 + +10036896 : +10036896: a800 add r0, sp, #0 +10036898: f850 0027 ldr.w r0, [r0, r7, lsl #2] +1003689c: f7fe f8b8 bl 10034a10 +100368a0: 1939 adds r1, r7, r4 +100368a2: f801 0c02 strb.w r0, [r1, #-2] +100368a6: eb07 0108 add.w r1, r7, r8 +100368aa: 2001 movs r0, #1 +100368ac: f801 0c02 strb.w r0, [r1, #-2] +100368b0: 1c7f adds r7, r7, #1 + +100368b2 : +100368b2: 1e70 subs r0, r6, #1 +100368b4: 42b8 cmp r0, r7 +100368b6: daee bge.n 10036896 +100368b8: fa5f f289 uxtb.w r2, r9 +100368bc: 4641 mov r1, r8 +100368be: 4620 mov r0, r4 +100368c0: f002 fe1c bl 100394fc +100368c4: 2800 cmp r0, #0 +100368c6: d504 bpl.n 100368d2 +100368c8: f60f 10b4 addw r0, pc, #2484 ; 0x9b4 + +100368cc : +100368cc: f7d5 fd19 bl 1000c302 +100368d0: e00d b.n 100368ee + +100368d2 : +100368d2: 2100 movs r1, #0 +100368d4: f8df 0500 ldr.w r0, [pc, #1280] ; 10036dd8 +100368d8: f002 fdc4 bl 10039464 +100368dc: b118 cbz r0, 100368e6 +100368de: f60f 10d4 addw r0, pc, #2516 ; 0x9d4 +100368e2: f7d5 fd0e bl 1000c302 + +100368e6 : +100368e6: 2d00 cmp r5, #0 +100368e8: bf18 it ne +100368ea: 2c00 cmpne r4, #0 +100368ec: d002 beq.n 100368f4 + +100368ee : +100368ee: 4620 mov r0, r4 +100368f0: f7d6 f867 bl 1000c9c2 + +100368f4 : +100368f4: b00f add sp, #60 ; 0x3c +100368f6: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + +100368fa : +100368fa: a806 add r0, sp, #24 + +100368fc : +100368fc: 2120 movs r1, #32 +100368fe: f7ee bf8d b.w 1002581c <__aeabi_memclr4> + +10036902 : +10036902: b580 push {r7, lr} +10036904: 2000 movs r0, #0 +10036906: 9000 str r0, [sp, #0] +10036908: f60f 10c8 addw r0, pc, #2504 ; 0x9c8 +1003690c: f7d5 fcf9 bl 1000c302 +10036910: a800 add r0, sp, #0 +10036912: f002 fbb0 bl 10039076 +10036916: 9900 ldr r1, [sp, #0] +10036918: f60f 10d8 addw r0, pc, #2520 ; 0x9d8 +1003691c: f7d5 fcf1 bl 1000c302 +10036920: a03f add r0, pc, #252 ; (adr r0, 10036a20 ) +10036922: f7d5 fcee bl 1000c302 +10036926: bd01 pop {r0, pc} + +10036928 : +10036928: b510 push {r4, lr} +1003692a: f7fe f871 bl 10034a10 +1003692e: 0004 movs r4, r0 +10036930: bf14 ite ne +10036932: a13c addne r1, pc, #240 ; (adr r1, 10036a24 ) +10036934: a13c addeq r1, pc, #240 ; (adr r1, 10036a28 ) +10036936: f60f 10d8 addw r0, pc, #2520 ; 0x9d8 +1003693a: f7d5 fce2 bl 1000c302 +1003693e: 2c01 cmp r4, #1 +10036940: d107 bne.n 10036952 +10036942: 2001 movs r0, #1 +10036944: f002 fba1 bl 1003908a +10036948: 2800 cmp r0, #0 +1003694a: d50f bpl.n 1003696c +1003694c: f60f 10e0 addw r0, pc, #2528 ; 0x9e0 +10036950: e008 b.n 10036964 + +10036952 : +10036952: b92c cbnz r4, 10036960 +10036954: f001 f988 bl 10037c68 +10036958: e8bd 4010 ldmia.w sp!, {r4, lr} +1003695c: f002 bbdc b.w 10039118 + +10036960 : +10036960: f60f 10e8 addw r0, pc, #2536 ; 0x9e8 + +10036964 : +10036964: e8bd 4010 ldmia.w sp!, {r4, lr} +10036968: f7d5 bccb b.w 1000c302 + +1003696c : +1003696c: bd10 pop {r4, pc} + +1003696e : +1003696e: b530 push {r4, r5, lr} +10036970: b089 sub sp, #36 ; 0x24 +10036972: 2414 movs r4, #20 +10036974: f60f 10ec addw r0, pc, #2540 ; 0x9ec +10036978: f7d5 fcc3 bl 1000c302 +1003697c: f8df 5428 ldr.w r5, [pc, #1064] ; 10036da8 +10036980: 7868 ldrb r0, [r5, #1] +10036982: b910 cbnz r0, 1003698a +10036984: f60f 2000 addw r0, pc, #2560 ; 0xa00 +10036988: e023 b.n 100369d2 + +1003698a : +1003698a: 6b28 ldr r0, [r5, #48] ; 0x30 +1003698c: 280f cmp r0, #15 +1003698e: bfa8 it ge +10036990: f60f 2018 addwge r0, pc, #2584 ; 0xa18 +10036994: da1d bge.n 100369d2 +10036996: 6aa8 ldr r0, [r5, #40] ; 0x28 +10036998: b108 cbz r0, 1003699e +1003699a: f8df 041c ldr.w r0, [pc, #1052] ; 10036db8 + +1003699e : +1003699e: 6268 str r0, [r5, #36] ; 0x24 +100369a0: f001 fe26 bl 100385f0 +100369a4: f002 fbb8 bl 10039118 +100369a8: 2014 movs r0, #20 +100369aa: f7d4 f892 bl 1000aad2 +100369ae: 2003 movs r0, #3 +100369b0: f002 fb6b bl 1003908a +100369b4: 2800 cmp r0, #0 +100369b6: bf48 it mi +100369b8: f20f 6084 addwmi r0, pc, #1668 ; 0x684 +100369bc: d409 bmi.n 100369d2 +100369be: f20f 609c addw r0, pc, #1692 ; 0x69c +100369c2: f7d5 fc9e bl 1000c302 +100369c6: f000 f831 bl 10036a2c + +100369ca : +100369ca: 2800 cmp r0, #0 +100369cc: d507 bpl.n 100369de +100369ce: f20f 60a0 addw r0, pc, #1696 ; 0x6a0 + +100369d2 : +100369d2: f7d5 fc96 bl 1000c302 +100369d6: e021 b.n 10036a1c + +100369d8 : +100369d8: f7ff ff25 bl 10036826 + +100369dc : +100369dc: 1e64 subs r4, r4, #1 + +100369de : +100369de: a900 add r1, sp, #0 +100369e0: f60f 10fc addw r0, pc, #2556 ; 0x9fc +100369e4: f7eb fc0e bl 10022204 +100369e8: 2801 cmp r0, #1 +100369ea: db07 blt.n 100369fc +100369ec: 1c69 adds r1, r5, #1 +100369ee: a800 add r0, sp, #0 +100369f0: f7d5 fcae bl 1000c350 +100369f4: b910 cbnz r0, 100369fc +100369f6: f000 f823 bl 10036a40 + +100369fa : +100369fa: e005 b.n 10036a08 + +100369fc : +100369fc: 2c00 cmp r4, #0 +100369fe: d1eb bne.n 100369d8 +10036a00: f20f 60a0 addw r0, pc, #1696 ; 0x6a0 +10036a04: f7d5 fc7d bl 1000c302 + +10036a08 : +10036a08: f8df 43c8 ldr.w r4, [pc, #968] ; 10036dd4 +10036a0c: f104 0038 add.w r0, r4, #56 ; 0x38 +10036a10: f003 f97e bl 10039d10 +10036a14: f104 0038 add.w r0, r4, #56 ; 0x38 +10036a18: f001 fd92 bl 10038540 + +10036a1c : +10036a1c: b009 add sp, #36 ; 0x24 +10036a1e: bd30 pop {r4, r5, pc} + +10036a20 : +10036a20: 0d0a 0000 .... + +10036a24 : +10036a24: 4e4f 0000 ON.. + +10036a28 : +10036a28: 464f 0046 OFF. + +10036a2c : +10036a2c: 6b28 ldr r0, [r5, #48] ; 0x30 +10036a2e: 782b ldrb r3, [r5, #0] +10036a30: 6aaa ldr r2, [r5, #40] ; 0x28 +10036a32: 6a69 ldr r1, [r5, #36] ; 0x24 +10036a34: 9001 str r0, [sp, #4] +10036a36: 6ae8 ldr r0, [r5, #44] ; 0x2c +10036a38: 9000 str r0, [sp, #0] +10036a3a: 1c68 adds r0, r5, #1 +10036a3c: f002 bba8 b.w 10039190 + +10036a40 : +10036a40: 1c69 adds r1, r5, #1 +10036a42: f20f 6050 addw r0, pc, #1616 ; 0x650 +10036a46: f7d5 bc5c b.w 1000c302 + +10036a4a : +10036a4a: b530 push {r4, r5, lr} +10036a4c: b08f sub sp, #60 ; 0x3c +10036a4e: 4604 mov r4, r0 +10036a50: f7ff ff53 bl 100368fa + +10036a54 : +10036a54: a800 add r0, sp, #0 +10036a56: 2118 movs r1, #24 +10036a58: f7ee fee0 bl 1002581c <__aeabi_memclr4> +10036a5c: f60f 1088 addw r0, pc, #2440 ; 0x988 +10036a60: f7d5 fc4f bl 1000c302 +10036a64: b924 cbnz r4, 10036a70 +10036a66: f60f 10a0 addw r0, pc, #2464 ; 0x9a0 +10036a6a: f7d5 fc4a bl 1000c302 +10036a6e: e036 b.n 10036ade + +10036a70 : +10036a70: 4621 mov r1, r4 +10036a72: a806 add r0, sp, #24 +10036a74: f7d5 fc6e bl 1000c354 +10036a78: f60f 10bc addw r0, pc, #2492 ; 0x9bc +10036a7c: 9000 str r0, [sp, #0] +10036a7e: a900 add r1, sp, #0 +10036a80: a806 add r0, sp, #24 +10036a82: f7fe ffb9 bl 100359f8 +10036a86: ad00 add r5, sp, #0 +10036a88: 4604 mov r4, r0 +10036a8a: 6869 ldr r1, [r5, #4] +10036a8c: f60f 10b0 addw r0, pc, #2480 ; 0x9b0 +10036a90: f7d5 fc37 bl 1000c302 +10036a94: 2c02 cmp r4, #2 +10036a96: d105 bne.n 10036aa4 +10036a98: f60f 10c0 addw r0, pc, #2496 ; 0x9c0 +10036a9c: f7d5 fc31 bl 1000c302 +10036aa0: 2205 movs r2, #5 +10036aa2: e018 b.n 10036ad6 + +10036aa4 : +10036aa4: f60f 14cc addw r4, pc, #2508 ; 0x9cc +10036aa8: 68a8 ldr r0, [r5, #8] +10036aaa: 4621 mov r1, r4 +10036aac: f7d5 fc50 bl 1000c350 +10036ab0: b938 cbnz r0, 10036ac2 +10036ab2: 4621 mov r1, r4 +10036ab4: f60f 10c4 addw r0, pc, #2500 ; 0x9c4 +10036ab8: f7d5 fc23 bl 1000c302 +10036abc: 2200 movs r2, #0 +10036abe: 2101 movs r1, #1 +10036ac0: e00a b.n 10036ad8 + +10036ac2 : +10036ac2: 68a8 ldr r0, [r5, #8] +10036ac4: f7fd ffa4 bl 10034a10 +10036ac8: 4604 mov r4, r0 +10036aca: 4621 mov r1, r4 +10036acc: f60f 10c8 addw r0, pc, #2504 ; 0x9c8 +10036ad0: f7d5 fc17 bl 1000c302 +10036ad4: 4622 mov r2, r4 + +10036ad6 : +10036ad6: 2100 movs r1, #0 + +10036ad8 : +10036ad8: 6868 ldr r0, [r5, #4] +10036ada: f003 fa41 bl 10039f60 + +10036ade : +10036ade: b00f add sp, #60 ; 0x3c +10036ae0: bd30 pop {r4, r5, pc} + +10036ae2 : +10036ae2: b510 push {r4, lr} +10036ae4: b086 sub sp, #24 +10036ae6: f000 f81a bl 10036b1e + +10036aea : +10036aea: f60f 10c8 addw r0, pc, #2504 ; 0x9c8 +10036aee: 9000 str r0, [sp, #0] +10036af0: f60f 10d0 addw r0, pc, #2512 ; 0x9d0 +10036af4: f7d5 fc05 bl 1000c302 +10036af8: b924 cbnz r4, 10036b04 +10036afa: f60f 10e4 addw r0, pc, #2532 ; 0x9e4 +10036afe: f7d5 fc00 bl 1000c302 +10036b02: e006 b.n 10036b12 + +10036b04 : +10036b04: f000 f807 bl 10036b16 + +10036b08 : +10036b08: 2802 cmp r0, #2 +10036b0a: bfa4 itt ge +10036b0c: a900 addge r1, sp, #0 +10036b0e: f003 fc55 blge 1003a3bc + +10036b12 : +10036b12: b006 add sp, #24 +10036b14: bd10 pop {r4, pc} + +10036b16 : +10036b16: a900 add r1, sp, #0 +10036b18: 4620 mov r0, r4 +10036b1a: f7fe bf6d b.w 100359f8 + +10036b1e : +10036b1e: 4604 mov r4, r0 +10036b20: a800 add r0, sp, #0 +10036b22: 2118 movs r1, #24 +10036b24: f7ee be7a b.w 1002581c <__aeabi_memclr4> + +10036b28 : +10036b28: b580 push {r7, lr} +10036b2a: f60f 10e4 addw r0, pc, #2532 ; 0x9e4 +10036b2e: f7d5 fbe8 bl 1000c302 +10036b32: e8bd 4001 ldmia.w sp!, {r0, lr} +10036b36: f001 b868 b.w 10037c0a + +10036b3a : +10036b3a: b51c push {r2, r3, r4, lr} +10036b3c: 4604 mov r4, r0 +10036b3e: a800 add r0, sp, #0 +10036b40: 2100 movs r1, #0 +10036b42: 2200 movs r2, #0 +10036b44: c006 stmia r0!, {r1, r2} +10036b46: f60f 10f0 addw r0, pc, #2544 ; 0x9f0 +10036b4a: f7d5 fbda bl 1000c302 +10036b4e: f60f 200c addw r0, pc, #2572 ; 0xa0c +10036b52: 9000 str r0, [sp, #0] +10036b54: 2001 movs r0, #1 +10036b56: b10c cbz r4, 10036b5c +10036b58: 9401 str r4, [sp, #4] +10036b5a: 2002 movs r0, #2 + +10036b5c : +10036b5c: a900 add r1, sp, #0 +10036b5e: f003 ffc1 bl 1003aae4 +10036b62: bd13 pop {r0, r1, r4, pc} + +10036b64 : +10036b64: b51f push {r0, r1, r2, r3, r4, lr} +10036b66: 4604 mov r4, r0 +10036b68: f60f 2004 addw r0, pc, #2564 ; 0xa04 +10036b6c: f7d5 fbc9 bl 1000c302 +10036b70: b924 cbnz r4, 10036b7c +10036b72: f60f 2014 addw r0, pc, #2580 ; 0xa14 +10036b76: f7d5 fbc4 bl 1000c302 +10036b7a: bd1f pop {r0, r1, r2, r3, r4, pc} + +10036b7c : +10036b7c: f60f 2024 addw r0, pc, #2596 ; 0xa24 +10036b80: 9000 str r0, [sp, #0] +10036b82: 9401 str r4, [sp, #4] +10036b84: a900 add r1, sp, #0 +10036b86: 2002 movs r0, #2 +10036b88: f004 fc0f bl 1003b3aa +10036b8c: bd1f pop {r0, r1, r2, r3, r4, pc} + +10036b8e : +10036b8e: 4770 bx lr + +10036b90 : +10036b90: b530 push {r4, r5, lr} +10036b92: b087 sub sp, #28 +10036b94: f7ff ffc3 bl 10036b1e + +10036b98 : +10036b98: f60f 2014 addw r0, pc, #2580 ; 0xa14 +10036b9c: f7d5 fbb1 bl 1000c302 +10036ba0: f60f 252c addw r5, pc, #2604 ; 0xa2c +10036ba4: b134 cbz r4, 10036bb4 +10036ba6: f60f 2064 addw r0, pc, #2660 ; 0xa64 +10036baa: 9000 str r0, [sp, #0] +10036bac: f7ff ffb3 bl 10036b16 + +10036bb0 : +10036bb0: 2803 cmp r0, #3 +10036bb2: d003 beq.n 10036bbc + +10036bb4 : +10036bb4: 4628 mov r0, r5 +10036bb6: f7d5 fba4 bl 1000c302 +10036bba: e002 b.n 10036bc2 + +10036bbc : +10036bbc: a900 add r1, sp, #0 +10036bbe: f005 f84f bl 1003bc60 + +10036bc2 : +10036bc2: b007 add sp, #28 +10036bc4: bd30 pop {r4, r5, pc} + +10036bc6 : +10036bc6: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +10036bca: f8df 8208 ldr.w r8, [pc, #520] ; 10036dd4 +10036bce: b0a7 sub sp, #156 ; 0x9c +10036bd0: 2400 movs r4, #0 +10036bd2: 4640 mov r0, r8 +10036bd4: f003 f896 bl 10039d04 +10036bd8: 4640 mov r0, r8 +10036bda: f003 f895 bl 10039d08 +10036bde: 4640 mov r0, r8 +10036be0: f003 f894 bl 10039d0c +10036be4: f60f 212c addw r1, pc, #2604 ; 0xa2c +10036be8: c90c ldmia r1!, {r2, r3} +10036bea: a809 add r0, sp, #36 ; 0x24 +10036bec: c00c stmia r0!, {r2, r3} +10036bee: f60f 202c addw r0, pc, #2604 ; 0xa2c +10036bf2: f7d5 fb86 bl 1000c302 +10036bf6: f60f 2994 addw r9, pc, #2708 ; 0xa94 +10036bfa: f60f 2a58 addw sl, pc, #2648 ; 0xa58 + +10036bfe : +10036bfe: b2e0 uxtb r0, r4 +10036c00: f7d9 f9dd bl 1000ffbe +10036c04: 2800 cmp r0, #0 +10036c06: d05d beq.n 10036cc4 +10036c08: 2038 movs r0, #56 ; 0x38 +10036c0a: fb00 8704 mla r7, r0, r4, r8 +10036c0e: 4638 mov r0, r7 +10036c10: f003 f878 bl 10039d04 +10036c14: 4605 mov r5, r0 +10036c16: 4638 mov r0, r7 +10036c18: f003 f876 bl 10039d08 +10036c1c: 4606 mov r6, r0 +10036c1e: 4638 mov r0, r7 +10036c20: f003 f874 bl 10039d0c +10036c24: 4607 mov r7, r0 +10036c26: a809 add r0, sp, #36 ; 0x24 +10036c28: f850 b024 ldr.w fp, [r0, r4, lsl #2] +10036c2c: f60f 2008 addw r0, pc, #2568 ; 0xa08 +10036c30: 4659 mov r1, fp +10036c32: f7d5 fb66 bl 1000c302 +10036c36: 4650 mov r0, sl +10036c38: f7d5 fb63 bl 1000c302 +10036c3c: b2e0 uxtb r0, r4 +10036c3e: f7d9 f9c3 bl 1000ffc8 +10036c42: a90b add r1, sp, #44 ; 0x2c +10036c44: 4658 mov r0, fp +10036c46: f002 fc62 bl 1003950e +10036c4a: a90b add r1, sp, #44 ; 0x2c +10036c4c: 4658 mov r0, fp +10036c4e: f002 fcbb bl 100395c8 +10036c52: 4659 mov r1, fp +10036c54: f60f 2020 addw r0, pc, #2592 ; 0xa20 +10036c58: f7d5 fb53 bl 1000c302 +10036c5c: 4650 mov r0, sl +10036c5e: f7d5 fb50 bl 1000c302 +10036c62: f000 f85b bl 10036d1c + +10036c66 : +10036c66: 7829 ldrb r1, [r5, #0] +10036c68: 4648 mov r0, r9 +10036c6a: f7d5 fb4a bl 1000c302 +10036c6e: 78f0 ldrb r0, [r6, #3] +10036c70: 9000 str r0, [sp, #0] +10036c72: 78b3 ldrb r3, [r6, #2] +10036c74: 7872 ldrb r2, [r6, #1] +10036c76: 7831 ldrb r1, [r6, #0] +10036c78: f60f 2038 addw r0, pc, #2616 ; 0xa38 +10036c7c: f7d5 fb41 bl 1000c302 +10036c80: 78f8 ldrb r0, [r7, #3] +10036c82: 9000 str r0, [sp, #0] +10036c84: 78bb ldrb r3, [r7, #2] +10036c86: 787a ldrb r2, [r7, #1] +10036c88: 7839 ldrb r1, [r7, #0] +10036c8a: f60f 2040 addw r0, pc, #2624 ; 0xa40 +10036c8e: f7d5 fb38 bl 1000c302 +10036c92: 980b ldr r0, [sp, #44] ; 0x2c +10036c94: 2802 cmp r0, #2 +10036c96: bf18 it ne +10036c98: 2c01 cmpne r4, #1 +10036c9a: d138 bne.n 10036d0e +10036c9c: 2003 movs r0, #3 +10036c9e: 9003 str r0, [sp, #12] +10036ca0: 2118 movs r1, #24 +10036ca2: a803 add r0, sp, #12 +10036ca4: f002 f9c4 bl 10039030 +10036ca8: f60f 2038 addw r0, pc, #2616 ; 0xa38 +10036cac: f7d5 fb29 bl 1000c302 +10036cb0: 4650 mov r0, sl +10036cb2: f7d5 fb26 bl 1000c302 +10036cb6: 9803 ldr r0, [sp, #12] +10036cb8: b928 cbnz r0, 10036cc6 +10036cba: 2100 movs r1, #0 +10036cbc: f60f 2040 addw r0, pc, #2624 ; 0xa40 +10036cc0: f7d5 fb1f bl 1000c302 + +10036cc4 : +10036cc4: e023 b.n 10036d0e + +10036cc6 : +10036cc6: 4601 mov r1, r0 +10036cc8: f60f 2048 addw r0, pc, #2632 ; 0xa48 +10036ccc: f7d5 fb19 bl 1000c302 +10036cd0: 2600 movs r6, #0 +10036cd2: e016 b.n 10036d02 + +10036cd4 : +10036cd4: 1c75 adds r5, r6, #1 +10036cd6: 4629 mov r1, r5 +10036cd8: f60f 204c addw r0, pc, #2636 ; 0xa4c +10036cdc: f7d5 fb11 bl 1000c302 +10036ce0: a803 add r0, sp, #12 +10036ce2: 2106 movs r1, #6 +10036ce4: fb01 0006 mla r0, r1, r6, r0 +10036ce8: 7a41 ldrb r1, [r0, #9] +10036cea: 9102 str r1, [sp, #8] +10036cec: 7a01 ldrb r1, [r0, #8] +10036cee: 9101 str r1, [sp, #4] +10036cf0: 79c1 ldrb r1, [r0, #7] +10036cf2: 9100 str r1, [sp, #0] +10036cf4: 7983 ldrb r3, [r0, #6] +10036cf6: 7942 ldrb r2, [r0, #5] +10036cf8: 7901 ldrb r1, [r0, #4] +10036cfa: 4648 mov r0, r9 +10036cfc: f7d5 fb01 bl 1000c302 +10036d00: 462e mov r6, r5 + +10036d02 : +10036d02: 9803 ldr r0, [sp, #12] +10036d04: 4286 cmp r6, r0 +10036d06: dbe5 blt.n 10036cd4 +10036d08: a028 add r0, pc, #160 ; (adr r0, 10036dac ) +10036d0a: f7d5 fafa bl 1000c302 + +10036d0e : +10036d0e: 1c64 adds r4, r4, #1 +10036d10: 2c02 cmp r4, #2 +10036d12: f6ff af74 blt.w 10036bfe +10036d16: b027 add sp, #156 ; 0x9c +10036d18: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +10036d1c : +10036d1c: 7968 ldrb r0, [r5, #5] +10036d1e: 9002 str r0, [sp, #8] +10036d20: 7928 ldrb r0, [r5, #4] +10036d22: 9001 str r0, [sp, #4] +10036d24: 78e8 ldrb r0, [r5, #3] +10036d26: 9000 str r0, [sp, #0] +10036d28: 78ab ldrb r3, [r5, #2] +10036d2a: 786a ldrb r2, [r5, #1] +10036d2c: 4770 bx lr + +10036d2e : +10036d2e: b530 push {r4, r5, lr} +10036d30: b089 sub sp, #36 ; 0x24 +10036d32: 4604 mov r4, r0 +10036d34: a800 add r0, sp, #0 +10036d36: f7ff fde1 bl 100368fc + +10036d3a : +10036d3a: 2500 movs r5, #0 +10036d3c: f60f 10f8 addw r0, pc, #2552 ; 0x9f8 +10036d40: f7d5 fadf bl 1000c302 +10036d44: b924 cbnz r4, 10036d50 +10036d46: f60f 200c addw r0, pc, #2572 ; 0xa0c +10036d4a: f7d5 fada bl 1000c302 +10036d4e: e01d b.n 10036d8c + +10036d50 : +10036d50: 4621 mov r1, r4 +10036d52: a800 add r0, sp, #0 +10036d54: f7d5 fafe bl 1000c354 +10036d58: a800 add r0, sp, #0 +10036d5a: f7d5 fafd bl 1000c358 +10036d5e: a900 add r1, sp, #0 + +10036d60 : +10036d60: 566a ldrsb r2, [r5, r1] +10036d62: 2a5b cmp r2, #91 ; 0x5b +10036d64: bf04 itt eq +10036d66: 2220 moveq r2, #32 +10036d68: 546a strbeq r2, [r5, r1] +10036d6a: 566a ldrsb r2, [r5, r1] +10036d6c: 2a5d cmp r2, #93 ; 0x5d +10036d6e: bf18 it ne +10036d70: 2a00 cmpne r2, #0 +10036d72: d102 bne.n 10036d7a +10036d74: 2000 movs r0, #0 +10036d76: 5468 strb r0, [r5, r1] +10036d78: e003 b.n 10036d82 + +10036d7a : +10036d7a: 462a mov r2, r5 +10036d7c: 1c55 adds r5, r2, #1 +10036d7e: 4282 cmp r2, r0 +10036d80: dbee blt.n 10036d60 + +10036d82 : +10036d82: 2201 movs r2, #1 +10036d84: f20f 3004 addw r0, pc, #772 ; 0x304 +10036d88: f7eb fcd1 bl 1002272e + +10036d8c : +10036d8c: b009 add sp, #36 ; 0x24 +10036d8e: bd30 pop {r4, r5, pc} + +10036d90 : +10036d90: b580 push {r7, lr} +10036d92: f7ff fa57 bl 10036244 +10036d96: e8bd 4004 ldmia.w sp!, {r2, lr} +10036d9a: 2118 movs r1, #24 +10036d9c: 480f ldr r0, [pc, #60] ; (10036ddc ) +10036d9e: f7fe be1e b.w 100359de + ... + +10036da4 : +10036da4: 71e8 1004 .q.. + +10036da8 : +10036da8: 7220 1004 r.. + +10036dac : +10036dac: 0d0a 0000 .... + +10036db0 : +10036db0: 0002 0020 .. . + +10036db4 : +10036db4: 0004 0020 .. . + +10036db8 : +10036db8: 0004 0040 ..@. + +10036dbc : +10036dbc: 0002 0040 ..@. + +10036dc0 : +10036dc0: 0006 0040 ..@. + +10036dc4 : +10036dc4: 7298 1004 .r.. + +10036dc8 : +10036dc8: 8298 1004 .... + +10036dcc : +10036dcc: 7b48 1004 H{.. + +10036dd0 : +10036dd0: a8c0 0101 .... + +10036dd4 : +10036dd4: 7824 1004 $x.. + +10036dd8 : +10036dd8: 6395 1003 .c.. + +10036ddc : +10036ddc: 3da8 1004 .=.. + +10036de0 : +10036de0: 7325 0909 0020 0000 %s.. ... + +10036de8 : +10036de8: 5057 2041 4b54 5049 0000 0000 WPA TKIP.... + +10036df4 : +10036df4: 5057 2041 4541 0053 WPA AES. + +10036dfc : +10036dfc: 5057 3241 4120 5345 0000 0000 WPA2 AES.... + +10036e08 : +10036e08: 5057 3241 5420 494b 0050 0000 WPA2 TKIP... + +10036e14 : +10036e14: 5057 3241 4d20 7869 6465 0000 WPA2 Mixed.. + +10036e20 : +10036e20: 6e55 6e6b 776f 006e Unknown. + +10036e28 : +10036e28: 2520 2073 0000 0000 %s .... + +10036e30 : +10036e30: 6425 2009 0000 0000 %d. .... + +10036e38 : +10036e38: 415b 5754 5d30 7355 6761 3a65 4120 5754 [ATW0]Usage: ATW +10036e48: 3d30 5353 4449 0d0a 0000 0000 0=SSID...... + +10036e54 : +10036e54: 415b 5754 5d30 203a 415f 5f54 4c57 4e41 [ATW0]: _AT_WLAN +10036e64: 535f 5445 535f 4953 5f44 5b20 7325 0a5d _SET_SSID_ [%s]. +10036e74: 000d 0000 .... + +10036e78 : +10036e78: 415b 5754 5d31 203a 415f 5f54 4c57 4e41 [ATW1]: _AT_WLAN +10036e88: 535f 5445 505f 5341 5053 5248 5341 5f45 _SET_PASSPHRASE_ +10036e98: 5b20 7325 0a5d 000d [%s]... + +10036ea0 : +10036ea0: 415b 5754 5d32 203a 415f 5f54 4c57 4e41 [ATW2]: _AT_WLAN +10036eb0: 535f 5445 4b5f 5945 495f 5f44 5b20 7325 _SET_KEY_ID_ [%s +10036ec0: 0a5d 000d ]... + +10036ec4 : +10036ec4: 0d0a 7257 6e6f 2067 4557 2050 656b 2079 ..Wrong WEP key +10036ed4: 6469 202e 754d 7473 6220 2065 6e6f 2065 id. Must be one +10036ee4: 666f 3020 312c 322c 202c 726f 3320 002e of 0,1,2, or 3.. + +10036ef4 : +10036ef4: 415b 5754 5d33 7355 6761 3a65 4120 5754 [ATW3]Usage: ATW +10036f04: 3d33 5353 4449 0d0a 0000 0000 3=SSID...... + +10036f10 : +10036f10: 415b 5754 5d33 7245 6f72 3a72 5320 4953 [ATW3]Error: SSI +10036f20: 2044 656c 676e 6874 6320 6e61 7427 6520 D length can't e +10036f30: 6378 6565 2064 3233 0d0a 0000 xceed 32.... + +10036f3c : +10036f3c: 415b 5754 5d33 203a 415f 5f54 4c57 4e41 [ATW3]: _AT_WLAN +10036f4c: 415f 5f50 4553 5f54 5353 4449 205f 255b _AP_SET_SSID_ [% +10036f5c: 5d73 0d0a 0000 0000 s]...... + +10036f64 : +10036f64: 415b 5754 5d34 203a 415f 5f54 4c57 4e41 [ATW4]: _AT_WLAN +10036f74: 415f 5f50 4553 5f54 4553 5f43 454b 5f59 _AP_SET_SEC_KEY_ +10036f84: 5b20 7325 0a5d 000d [%s]... + +10036f8c : +10036f8c: 415b 5754 5d35 203a 415f 5f54 4c57 4e41 [ATW5]: _AT_WLAN +10036f9c: 415f 5f50 4553 5f54 4843 4e41 454e 5f4c _AP_SET_CHANNEL_ +10036fac: 5b20 6863 6e61 656e 206c 6425 0a5d 000d [channel %d]... + +10036fbc : +10036fbc: 415b 5754 5d36 7355 6761 3a65 4120 5754 [ATW6]Usage: ATW +10036fcc: 3d36 5342 4953 0a44 000d 0000 6=BSSID..... + +10036fd8 : +10036fd8: 415b 5754 5d36 203a 415f 5f54 4c57 4e41 [ATW6]: _AT_WLAN +10036fe8: 535f 5445 425f 5353 4449 205f 255b 5d73 _SET_BSSID_ [%s] +10036ff8: 0d0a 0000 .... + +10036ffc : +10036ffc: 415b 5754 5d41 203a 415f 5f54 4c57 4e41 [ATWA]: _AT_WLAN +1003700c: 415f 5f50 4341 4954 4156 4554 0a5f 000d _AP_ACTIVATE_... + +1003701c : +1003701c: 415b 5754 5d41 7245 6f72 3a72 5320 4953 [ATWA]Error: SSI +1003702c: 2044 6163 276e 2074 6562 6520 706d 7974 D can't be empty +1003703c: 0d0a 0000 .... + +10037040 : +10037040: 0d0a 5245 4f52 3a52 5720 6669 2069 6e6f ..ERROR: Wifi on +10037050: 6620 6961 656c 2164 0000 0000 failed!.... + +1003705c : +1003705c: 0d0a 7453 7261 6974 676e 4120 2050 2e2e ..Starting AP .. +1003706c: 002e 0000 .... + +10037070 : +10037070: 0d0a 5245 4f52 3a52 4f20 6570 6172 6974 ..ERROR: Operati +10037080: 6e6f 6620 6961 656c 2164 0000 on failed!.. + +1003708c : +1003708c: 6c77 6e61 0030 0000 wlan0... + +10037094 : +10037094: 0d0a 7325 7320 6174 7472 6465 000a 0000 ..%s started.... + +100370a4 : +100370a4: 0d0a 5245 4f52 3a52 5320 6174 7472 4120 ..ERROR: Start A +100370b4: 2050 6974 656d 756f 2174 0000 P timeout!.. + +100370c0 : +100370c0: 415b 5754 5d43 203a 415f 5f54 4c57 4e41 [ATWC]: _AT_WLAN +100370d0: 4a5f 494f 5f4e 454e 5f54 0d0a 0000 0000 _JOIN_NET_...... + +100370e0 : +100370e0: 415b 5754 5d43 7245 6f72 3a72 5320 4953 [ATWC]Error: SSI +100370f0: 2044 6163 276e 2074 6562 6520 706d 7974 D can't be empty +10037100: 0d0a 0000 .... + +10037104 : +10037104: 0d0a 6f4a 6e69 6e69 2067 5342 2053 7962 ..Joining BSS by +10037114: 4220 5353 4449 2520 3230 3a78 3025 7832 BSSID %02x:%02x +10037124: 253a 3230 3a78 3025 7832 253a 3230 3a78 :%02x:%02x:%02x: +10037134: 3025 7832 2e20 2e2e 0d0a 0000 %02x ....... + +10037140 : +10037140: 0d0a 6f4a 6e69 6e69 2067 5342 2053 7962 ..Joining BSS by +10037150: 5320 4953 2044 7325 2e2e 0a2e 000d 0000 SSID %s........ + +10037160 : +10037160: 0a0d 6f43 6e6e 6365 6574 2064 6661 6574 ..Connected afte +10037170: 2072 6425 736d 0a2e 0000 0000 r %dms...... + +1003717c : +1003717c: 0a0d 470a 746f 4920 2050 6661 6574 2072 ...Got IP after +1003718c: 6425 736d 0a2e 0000 %dms.... + +10037194 : +10037194: 415b 5754 5d44 203a 415f 5f54 4c57 4e41 [ATWD]: _AT_WLAN +100371a4: 445f 5349 5f43 454e 5f54 0d0a 0000 0000 _DISC_NET_...... + +100371b4 : +100371b4: 0d0a 6544 7361 6f73 6963 7461 6e69 2067 ..Deassociating +100371c4: 5041 2e20 2e2e 0000 AP ..... + +100371cc : +100371cc: 0d0a 4957 4946 6420 7369 6f63 6e6e 6365 ..WIFI disconnec +100371dc: 6574 0064 ted. + +100371e0 : +100371e0: 0d0a 5245 4f52 3a52 4420 6165 7373 636f ..ERROR: Deassoc +100371f0: 7420 6d69 6f65 7475 0021 0000 timeout!... + +100371fc : +100371fc: 415b 5754 5d53 203a 415f 5f54 4c57 4e41 [ATWS]: _AT_WLAN +1003720c: 535f 4143 5f4e 0d0a 0000 0000 _SCAN_...... + +10037218 : +10037218: 415b 5754 5d53 5245 4f52 3a52 4320 6e61 [ATWS]ERROR: Can +10037228: 7427 6d20 6c61 6f6c 2063 656d 6f6d 7972 't malloc memory +10037238: 6620 726f 6320 6168 6e6e 6c65 6c20 7369 for channel lis +10037248: 0a74 000d t... + +1003724c : +1003724c: 415b 5754 5d53 5245 4f52 3a52 4320 6e61 [ATWS]ERROR: Can +1003725c: 7427 6d20 6c61 6f6c 2063 656d 6f6d 7972 't malloc memory +1003726c: 6620 726f 7020 6373 6e61 635f 6e6f 6966 for pscan_confi +1003727c: 0a67 000d g... + +10037280 : +10037280: 415b 5754 5d53 5245 4f52 3a52 7720 6669 [ATWS]ERROR: wif +10037290: 2069 6573 2074 6170 7472 6169 206c 6373 i set partial sc +100372a0: 6e61 6320 6168 6e6e 6c65 6620 6961 0a6c an channel fail. +100372b0: 000d 0000 .... + +100372b4 : +100372b4: 415b 5754 5d53 5245 4f52 3a52 7720 6669 [ATWS]ERROR: wif +100372c4: 2069 6373 6e61 6620 6961 656c 0a64 000d i scan failed... + +100372d4 : +100372d4: 415b 5754 5d52 203a 415f 5f54 4c57 4e41 [ATWR]: _AT_WLAN +100372e4: 475f 5445 525f 5353 5f49 0d0a 0000 0000 _GET_RSSI_...... + +100372f4 : +100372f4: 0d0a 6977 6966 675f 7465 725f 7373 3a69 ..wifi_get_rssi: +10037304: 7220 7373 2069 203d 6425 0000 rssi = %d.. + +10037310 : +10037310: 415b 5754 5d50 203a 415f 5f54 4c57 4e41 [ATWP]: _AT_WLAN +10037320: 505f 574f 5245 5b5f 7325 0a5d 000d 0000 _POWER_[%s]..... + +10037330 : +10037330: 0d0a 5245 4f52 3a52 5720 6669 2069 6e6f ..ERROR: Wifi on +10037340: 6620 6961 656c 2164 000a 0000 failed!.... + +1003734c : +1003734c: 415b 5754 5d50 7355 6761 3a65 4120 5754 [ATWP]Usage: ATW +1003735c: 3d50 2f30 0a31 000d P=0/1... + +10037364 : +10037364: 415b 5754 5d42 5f28 5441 575f 414c 5f4e [ATWB](_AT_WLAN_ +10037374: 5041 535f 4154 415f 5443 5649 5441 5f45 AP_STA_ACTIVATE_ +10037384: 0a29 000d )... + +10037388 : +10037388: 415b 5754 5d42 7245 6f72 3a72 5320 4953 [ATWB]Error: SSI +10037398: 2044 6163 276e 2074 6562 6520 706d 7974 D can't be empty +100373a8: 0d0a 0000 .... + +100373ac : +100373ac: 415b 5754 5d42 7245 6f72 3a72 6162 2064 [ATWB]Error:bad +100373bc: 6863 6e61 656e 216c 6320 6168 6e6e 6c65 channel! channel +100373cc: 6920 2073 7266 6d6f 3120 7420 206f 3431 is from 1 to 14 +100373dc: 0d0a 0000 .... + +100373e0 : +100373e0: 6c77 6e61 0031 0000 wlan1... + +100373e8 : +100373e8: 415b 5754 5d49 203a 415f 5f54 4c57 4e41 [ATWI]: _AT_WLAN +100373f8: 505f 4e49 5f47 4554 5453 0a5f 000d 0000 _PING_TEST_..... + +10037408 : +10037408: 415b 5754 5d49 7355 6761 3a65 4120 5754 [ATWI]Usage: ATW +10037418: 3d49 7878 7878 782e 7878 2e78 7878 7878 I=xxxx.xxxx.xxxx +10037428: 782e 7878 5b78 2f79 6f6c 706f 0a5d 000d .xxxx[y/loop]... + +10037438 : +10037438: 6970 676e 0000 0000 ping.... + +10037440 : +10037440: 415b 5754 5d49 6154 6772 7465 6120 6464 [ATWI]Target add +10037450: 6572 7373 203a 7325 0d0a 0000 ress: %s.... + +1003745c : +1003745c: 415b 5754 5d49 6552 6570 7461 4320 756f [ATWI]Repeat Cou +1003746c: 746e 203a 0a35 000d nt: 5... + +10037474 : +10037474: 6f6c 706f 0000 0000 loop.... + +1003747c : +1003747c: 415b 5754 5d49 6552 6570 7461 4320 756f [ATWI]Repeat Cou +1003748c: 746e 203a 7325 0d0a 0000 0000 nt: %s...... + +10037498 : +10037498: 415b 5754 5d49 6552 6570 7461 4320 756f [ATWI]Repeat Cou +100374a8: 746e 203a 6425 0d0a 0000 0000 nt: %d...... + +100374b4 : +100374b4: 6977 6966 705f 6f72 696d 6373 0000 0000 wifi_promisc.... + +100374c4 : +100374c4: 415b 5754 5d4d 203a 415f 5f54 4c57 4e41 [ATWM]: _AT_WLAN +100374d4: 505f 4f52 494d 4353 0a5f 000d _PROMISC_... + +100374e0 : +100374e0: 415b 5754 5d4d 7355 6761 3a65 4120 5754 [ATWM]Usage: ATW +100374f0: 3d4d 5544 4152 4954 4e4f 535f 4345 4e4f M=DURATION_SECON +10037500: 5344 775b 7469 5f68 656c 5d6e 0000 0000 DS[with_len].... + +10037510 : +10037510: 415b 5754 5d45 203a 415f 5f54 4c57 4e41 [ATWE]: _AT_WLAN +10037520: 535f 4154 5452 575f 4245 535f 5245 4556 _START_WEB_SERVE +10037530: 5f52 0d0a 0000 0000 R_...... + +10037538 : +10037538: 415b 5754 5d51 203a 415f 5f54 4c57 4e41 [ATWQ]: _AT_WLAN +10037548: 535f 4d49 4c50 5f45 4f43 464e 4749 0a5f _SIMPLE_CONFIG_. +10037558: 000d 0000 .... + +1003755c : +1003755c: 6977 6966 735f 6d69 6c70 5f65 6f63 666e wifi_simple_conf +1003756c: 6769 0000 ig.. + +10037570 : +10037570: 415b 5754 5d57 203a 415f 5f54 4c57 4e41 [ATWW]: _AT_WLAN +10037580: 575f 5350 0a5f 000d _WPS_... + +10037588 : +10037588: 415b 5754 5d57 7355 6761 3a65 4120 5754 [ATWW]Usage: ATW +10037598: 3d57 6270 2f63 6970 0a6e 000d W=pbc/pin... + +100375a4 : +100375a4: 6977 6966 775f 7370 0000 0000 wifi_wps.... + +100375b0 : +100375b0: 415b 5754 5d4f 203a 415f 5f54 4c57 4e41 [ATWO]: _AT_WLAN +100375c0: 4f5f 4154 555f 4450 5441 5f45 0d0a 0000 _OTA_UPDATE_.... + +100375d0 : +100375d0: 415b 5754 5d4f 7355 6761 3a65 4120 5754 [ATWO]Usage: ATW +100375e0: 3d4f 5049 505b 524f 5d54 6f20 2072 5441 O=IP[PORT] or AT +100375f0: 4f57 203d 4552 4f50 4953 4f54 5952 465b WO= REPOSITORY[F +10037600: 4c49 5f45 4150 4854 0a5d 000d ILE_PATH]... + +1003760c : +1003760c: 7075 6164 6574 0000 update.. + +10037614 : +10037614: 708c 1003 73e0 1003 .p...s.. + +1003761c : +1003761c: 415b 5754 5d3f 203a 415f 5f54 4c57 4e41 [ATW?]: _AT_WLAN +1003762c: 495f 464e 5f4f 0d0a 0000 0000 _INFO_...... + +10037638 : +10037638: 0d0a 570a 4649 2049 7325 5320 6174 7574 ...WIFI %s Statu +10037648: 3a73 5220 6e75 696e 676e 0000 s: Running.. + +10037654 : +10037654: 0d0a 3d3d 3d3d 3d3d 3d3d 3d3d 3d3d 3d3d ..============== +10037664: 3d3d 3d3d 3d3d 3d3d 3d3d 3d3d 3d3d 3d3d ================ +10037674: 0000 0000 .... + +10037678 : +10037678: 0d0a 6e49 6574 6672 6361 2065 2528 2973 ..Interface (%s) +10037688: 0000 0000 .... + +1003768c : +1003768c: 0d0a 4d09 4341 3d20 203e 3025 7832 253a ...MAC => %02x:% +1003769c: 3230 3a78 3025 7832 253a 3230 3a78 3025 02x:%02x:%02x:%0 +100376ac: 7832 253a 3230 0078 2x:%02x. + +100376b4 : +100376b4: 0d0a 4909 2050 3d20 203e 6425 252e 2e64 ...IP => %d.%d. +100376c4: 6425 252e 0064 0000 %d.%d... + +100376cc : +100376cc: 0d0a 4709 2057 3d20 203e 6425 252e 2e64 ...GW => %d.%d. +100376dc: 6425 252e 0a64 000d %d.%d... + +100376e4 : +100376e4: 0d0a 7341 6f73 6963 7461 6465 4320 696c ..Associated Cli +100376f4: 6e65 2074 694c 7473 003a 0000 ent List:... + +10037700 : +10037700: 0d0a 6c43 6569 746e 4e20 6d75 203a 0a30 ..Client Num: 0. +10037710: 000d 0000 .... + +10037714 : +10037714: 0d0a 6c43 6569 746e 4e20 6d75 203a 6425 ..Client Num: %d +10037724: 0000 0000 .... + +10037728 : +10037728: 0d0a 6c43 6569 746e 2520 3a64 0000 0000 ..Client %d:.... + +10037738 : +10037738: 415b 5754 5d5a 203a 415f 5f54 4c57 4e41 [ATWZ]: _AT_WLAN +10037748: 495f 5057 4952 5f56 0d0a 0000 _IWPRIV_.... + +10037754 : +10037754: 415b 5754 5d5a 7355 6761 3a65 4120 5754 [ATWZ]Usage: ATW +10037764: 3d5a 4f43 4d4d 4e41 5b44 4150 4152 454d Z=COMMAND[PARAME +10037774: 4554 5352 0a5d 000d TERS]... + +1003777c : +1003777c: b570 push {r4, r5, r6, lr} +1003777e: b09c sub sp, #112 ; 0x70 +10037780: f20f 5098 addw r0, pc, #1432 ; 0x598 +10037784: f7d4 fdbd bl 1000c302 +10037788: ab01 add r3, sp, #4 +1003778a: 226c movs r2, #108 ; 0x6c +1003778c: f44f 217e mov.w r1, #1040384 ; 0xfe000 +10037790: a800 add r0, sp, #0 +10037792: f7f9 fecf bl 10031534 +10037796: 9901 ldr r1, [sp, #4] +10037798: f20f 50a8 addw r0, pc, #1448 ; 0x5a8 +1003779c: f7d4 fdb1 bl 1000c302 +100377a0: f20f 50d4 addw r0, pc, #1492 ; 0x5d4 +100377a4: a902 add r1, sp, #8 +100377a6: f7d4 fdac bl 1000c302 +100377aa: f10d 056b add.w r5, sp, #107 ; 0x6b +100377ae: f20f 50f4 addw r0, pc, #1524 ; 0x5f4 +100377b2: 7869 ldrb r1, [r5, #1] +100377b4: f7d4 fda5 bl 1000c302 +100377b8: f20f 6018 addw r0, pc, #1560 ; 0x618 +100377bc: ae0a add r6, sp, #40 ; 0x28 +100377be: 7871 ldrb r1, [r6, #1] +100377c0: f7d4 fd9f bl 1000c302 +100377c4: f20f 6040 addw r0, pc, #1600 ; 0x640 +100377c8: f10d 012a add.w r1, sp, #42 ; 0x2a +100377cc: f7d4 fd99 bl 1000c302 +100377d0: 9801 ldr r0, [sp, #4] +100377d2: f8df 1500 ldr.w r1, [pc, #1280] ; 10037cd4 +100377d6: f8df 4500 ldr.w r4, [pc, #1280] ; 10037cd8 +100377da: 4288 cmp r0, r1 +100377dc: d133 bne.n 10037846 +100377de: 2002 movs r0, #2 +100377e0: 6020 str r0, [r4, #0] +100377e2: f89d 0028 ldrb.w r0, [sp, #40] ; 0x28 +100377e6: 2821 cmp r0, #33 ; 0x21 +100377e8: bfa4 itt ge +100377ea: 2020 movge r0, #32 +100377ec: f88d 0028 strbge.w r0, [sp, #40] ; 0x28 +100377f0: f89d 2028 ldrb.w r2, [sp, #40] ; 0x28 +100377f4: a902 add r1, sp, #8 +100377f6: 1d20 adds r0, r4, #4 +100377f8: f7d4 fda6 bl 1000c348 +100377fc: f89d 1028 ldrb.w r1, [sp, #40] ; 0x28 +10037800: 1909 adds r1, r1, r4 +10037802: 2000 movs r0, #0 +10037804: 7108 strb r0, [r1, #4] +10037806: 7868 ldrb r0, [r5, #1] +10037808: f884 0025 strb.w r0, [r4, #37] ; 0x25 +1003780c: 7870 ldrb r0, [r6, #1] +1003780e: 2801 cmp r0, #1 +10037810: bf0c ite eq +10037812: f8df 04c8 ldreq.w r0, [pc, #1224] ; 10037cdc +10037816: 2000 movne r0, #0 +10037818: 62a0 str r0, [r4, #40] ; 0x28 +1003781a: f89d 006b ldrb.w r0, [sp, #107] ; 0x6b +1003781e: 2821 cmp r0, #33 ; 0x21 +10037820: bfa4 itt ge +10037822: 2020 movge r0, #32 +10037824: f88d 006b strbge.w r0, [sp, #107] ; 0x6b +10037828: f89d 206b ldrb.w r2, [sp, #107] ; 0x6b +1003782c: f10d 012a add.w r1, sp, #42 ; 0x2a +10037830: f104 002c add.w r0, r4, #44 ; 0x2c +10037834: f7d4 fd88 bl 1000c348 +10037838: f89d 106b ldrb.w r1, [sp, #107] ; 0x6b +1003783c: 1909 adds r1, r1, r4 +1003783e: 2000 movs r0, #0 +10037840: f881 002c strb.w r0, [r1, #44] ; 0x2c +10037844: e00b b.n 1003785e + +10037846 : +10037846: 2001 movs r0, #1 +10037848: f20f 45c0 addw r5, pc, #1216 ; 0x4c0 +1003784c: f7d8 fbb7 bl 1000ffbe +10037850: b108 cbz r0, 10037856 +10037852: f20f 45c0 addw r5, pc, #1216 ; 0x4c0 + +10037856 : +10037856: 4621 mov r1, r4 +10037858: 4628 mov r0, r5 +1003785a: f001 fe58 bl 1003950e + +1003785e : +1003785e: b01c add sp, #112 ; 0x70 +10037860: bd70 pop {r4, r5, r6, pc} + +10037862 : +10037862: b530 push {r4, r5, lr} +10037864: b09d sub sp, #116 ; 0x74 +10037866: f8df 046c ldr.w r0, [pc, #1132] ; 10037cd4 +1003786a: f8df 546c ldr.w r5, [pc, #1132] ; 10037cd8 +1003786e: 9002 str r0, [sp, #8] +10037870: 2400 movs r4, #0 +10037872: 1d28 adds r0, r5, #4 +10037874: f7d4 fd70 bl 1000c358 +10037878: 4602 mov r2, r0 +1003787a: 1d29 adds r1, r5, #4 +1003787c: a803 add r0, sp, #12 +1003787e: f7d4 fd63 bl 1000c348 +10037882: 1d28 adds r0, r5, #4 +10037884: f7d4 fd68 bl 1000c358 +10037888: f88d 002c strb.w r0, [sp, #44] ; 0x2c +1003788c: a80b add r0, sp, #44 ; 0x2c +1003788e: 6aa9 ldr r1, [r5, #40] ; 0x28 +10037890: 7041 strb r1, [r0, #1] +10037892: 6aa9 ldr r1, [r5, #40] ; 0x28 +10037894: b101 cbz r1, 10037898 +10037896: 2101 movs r1, #1 + +10037898 : +10037898: 7041 strb r1, [r0, #1] +1003789a: f000 f9b2 bl 10037c02 + +1003789e : +1003789e: 4602 mov r2, r0 +100378a0: f105 012c add.w r1, r5, #44 ; 0x2c +100378a4: f10d 002e add.w r0, sp, #46 ; 0x2e +100378a8: f7d4 fd4e bl 1000c348 +100378ac: f000 f9a9 bl 10037c02 + +100378b0 : +100378b0: f88d 006f strb.w r0, [sp, #111] ; 0x6f +100378b4: f895 0025 ldrb.w r0, [r5, #37] ; 0x25 +100378b8: f88d 0070 strb.w r0, [sp, #112] ; 0x70 +100378bc: f20f 5078 addw r0, pc, #1400 ; 0x578 +100378c0: f7d4 fd1f bl 1000c302 +100378c4: aa01 add r2, sp, #4 +100378c6: f44f 217e mov.w r1, #1040384 ; 0xfe000 +100378ca: f000 f849 bl 10037960 + +100378ce : +100378ce: 9801 ldr r0, [sp, #4] +100378d0: f110 0f01 cmn.w r0, #1 +100378d4: d107 bne.n 100378e6 +100378d6: ab02 add r3, sp, #8 +100378d8: 226c movs r2, #108 ; 0x6c +100378da: f44f 217e mov.w r1, #1040384 ; 0xfe000 +100378de: a800 add r0, sp, #0 +100378e0: f7f9 fe78 bl 100315d4 +100378e4: e034 b.n 10037950 + +100378e6 : +100378e6: f000 f836 bl 10037956 + +100378ea : +100378ea: aa01 add r2, sp, #4 +100378ec: f504 217e add.w r1, r4, #1040384 ; 0xfe000 +100378f0: f000 f836 bl 10037960 + +100378f4 : +100378f4: 2c6c cmp r4, #108 ; 0x6c +100378f6: d205 bcs.n 10037904 +100378f8: a802 add r0, sp, #8 +100378fa: 1821 adds r1, r4, r0 +100378fc: 2204 movs r2, #4 +100378fe: a801 add r0, sp, #4 +10037900: f7d4 fd22 bl 1000c348 + +10037904 : +10037904: 9a01 ldr r2, [sp, #4] +10037906: f504 4100 add.w r1, r4, #32768 ; 0x8000 +1003790a: a800 add r0, sp, #0 +1003790c: f7f9 fdfd bl 1003150a +10037910: 1d24 adds r4, r4, #4 +10037912: f5b4 5f80 cmp.w r4, #4096 ; 0x1000 +10037916: d3e8 bcc.n 100378ea +10037918: aa01 add r2, sp, #4 +1003791a: f248 0144 movw r1, #32836 ; 0x8044 +1003791e: f000 f81f bl 10037960 + +10037922 : +10037922: f44f 217e mov.w r1, #1040384 ; 0xfe000 +10037926: a800 add r0, sp, #0 +10037928: f7f9 fdd6 bl 100314d8 +1003792c: 2400 movs r4, #0 + +1003792e : +1003792e: aa01 add r2, sp, #4 +10037930: f504 4100 add.w r1, r4, #32768 ; 0x8000 +10037934: f000 f814 bl 10037960 + +10037938 : +10037938: 9a01 ldr r2, [sp, #4] +1003793a: f504 217e add.w r1, r4, #1040384 ; 0xfe000 +1003793e: a800 add r0, sp, #0 +10037940: f7f9 fde3 bl 1003150a +10037944: 1d24 adds r4, r4, #4 +10037946: f5b4 5f80 cmp.w r4, #4096 ; 0x1000 +1003794a: d3f0 bcc.n 1003792e +1003794c: f000 f803 bl 10037956 + +10037950 : +10037950: 2000 movs r0, #0 +10037952: b01d add sp, #116 ; 0x74 +10037954: bd30 pop {r4, r5, pc} + +10037956 : +10037956: f44f 4100 mov.w r1, #32768 ; 0x8000 +1003795a: a800 add r0, sp, #0 +1003795c: f7f9 bdbc b.w 100314d8 + +10037960 : +10037960: a800 add r0, sp, #0 +10037962: f7f9 bdc5 b.w 100314f0 + +10037966 : +10037966: b580 push {r7, lr} +10037968: 2100 movs r1, #0 +1003796a: 2200 movs r2, #0 +1003796c: 4608 mov r0, r1 +1003796e: f004 fbb9 bl 1003c0e4 +10037972: e8bd 4001 ldmia.w sp!, {r0, lr} +10037976: f004 bbc8 b.w 1003c10a + +1003797a : +1003797a: b580 push {r7, lr} +1003797c: f004 fbb2 bl 1003c0e4 +10037980: e8bd 4001 ldmia.w sp!, {r0, lr} +10037984: f004 bbc1 b.w 1003c10a + +10037988 <_handle_post_rgb_json>: +10037988: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +1003798c: f004 fef6 bl 1003c77c +10037990: ea5f 0800 movs.w r8, r0 +10037994: d07b beq.n 10037a8e +10037996: a1b1 add r1, pc, #708 ; (adr r1, 10037c5c ) +10037998: f004 ffd0 bl 1003c93c +1003799c: 4606 mov r6, r0 +1003799e: a1b0 add r1, pc, #704 ; (adr r1, 10037c60 ) +100379a0: f000 f877 bl 10037a92 + +100379a4 : +100379a4: 4607 mov r7, r0 +100379a6: a1af add r1, pc, #700 ; (adr r1, 10037c64 ) +100379a8: f000 f873 bl 10037a92 + +100379ac : +100379ac: 4604 mov r4, r0 +100379ae: f20f 41c8 addw r1, pc, #1224 ; 0x4c8 +100379b2: f000 f86e bl 10037a92 + +100379b6 : +100379b6: 4605 mov r5, r0 +100379b8: f20f 41c4 addw r1, pc, #1220 ; 0x4c4 +100379bc: f000 f869 bl 10037a92 + +100379c0 : +100379c0: 4681 mov r9, r0 +100379c2: 6971 ldr r1, [r6, #20] +100379c4: f20f 40c0 addw r0, pc, #1216 ; 0x4c0 +100379c8: f7d4 fc9b bl 1000c302 +100379cc: 6979 ldr r1, [r7, #20] +100379ce: f20f 40c0 addw r0, pc, #1216 ; 0x4c0 +100379d2: f7d4 fc96 bl 1000c302 +100379d6: 6961 ldr r1, [r4, #20] +100379d8: f20f 40bc addw r0, pc, #1212 ; 0x4bc +100379dc: f7d4 fc91 bl 1000c302 +100379e0: 6929 ldr r1, [r5, #16] +100379e2: f20f 40bc addw r0, pc, #1212 ; 0x4bc +100379e6: f7d4 fc8c bl 1000c302 +100379ea: f8d9 1014 ldr.w r1, [r9, #20] +100379ee: f20f 40bc addw r0, pc, #1212 ; 0x4bc +100379f2: f7d4 fc86 bl 1000c302 +100379f6: 6970 ldr r0, [r6, #20] +100379f8: 49b9 ldr r1, [pc, #740] ; (10037ce0 ) +100379fa: 7008 strb r0, [r1, #0] +100379fc: 49b9 ldr r1, [pc, #740] ; (10037ce4 ) +100379fe: 6978 ldr r0, [r7, #20] +10037a00: 7008 strb r0, [r1, #0] +10037a02: 49b9 ldr r1, [pc, #740] ; (10037ce8 ) +10037a04: 6960 ldr r0, [r4, #20] +10037a06: 7008 strb r0, [r1, #0] +10037a08: f8d9 0014 ldr.w r0, [r9, #20] +10037a0c: 280a cmp r0, #10 +10037a0e: bfb8 it lt +10037a10: 200a movlt r0, #10 +10037a12: 49b6 ldr r1, [pc, #728] ; (10037cec ) +10037a14: 8008 strh r0, [r1, #0] +10037a16: a1ad add r1, pc, #692 ; (adr r1, 10037ccc ) +10037a18: 6928 ldr r0, [r5, #16] +10037a1a: f7d4 fc99 bl 1000c350 +10037a1e: b928 cbnz r0, 10037a2c +10037a20: f20f 4094 addw r0, pc, #1172 ; 0x494 +10037a24: f7d4 fc6d bl 1000c302 +10037a28: f7ff ff9d bl 10037966 + +10037a2c : +10037a2c: 6928 ldr r0, [r5, #16] +10037a2e: a1a8 add r1, pc, #672 ; (adr r1, 10037cd0 ) +10037a30: f7d4 fc8e bl 1000c350 +10037a34: b940 cbnz r0, 10037a48 +10037a36: f20f 4098 addw r0, pc, #1176 ; 0x498 +10037a3a: f7d4 fc62 bl 1000c302 +10037a3e: 6962 ldr r2, [r4, #20] +10037a40: 6979 ldr r1, [r7, #20] +10037a42: 6970 ldr r0, [r6, #20] +10037a44: f7ff ff99 bl 1003797a + +10037a48 : +10037a48: 6928 ldr r0, [r5, #16] +10037a4a: f20f 4198 addw r1, pc, #1176 ; 0x498 +10037a4e: f7d4 fc7f bl 1000c350 +10037a52: b928 cbnz r0, 10037a60 +10037a54: f20f 4094 addw r0, pc, #1172 ; 0x494 +10037a58: f7d4 fc53 bl 1000c302 +10037a5c: 2001 movs r0, #1 +10037a5e: e000 b.n 10037a62 + +10037a60 : +10037a60: 2000 movs r0, #0 + +10037a62 : +10037a62: 49a3 ldr r1, [pc, #652] ; (10037cf0 ) +10037a64: 7008 strb r0, [r1, #0] +10037a66: f20f 419c addw r1, pc, #1180 ; 0x49c +10037a6a: 6928 ldr r0, [r5, #16] +10037a6c: f7d4 fc70 bl 1000c350 +10037a70: b928 cbnz r0, 10037a7e +10037a72: f20f 4098 addw r0, pc, #1176 ; 0x498 +10037a76: f7d4 fc44 bl 1000c302 +10037a7a: 2001 movs r0, #1 +10037a7c: e000 b.n 10037a80 + +10037a7e : +10037a7e: 2000 movs r0, #0 + +10037a80 : +10037a80: 499c ldr r1, [pc, #624] ; (10037cf4 ) +10037a82: 7008 strb r0, [r1, #0] +10037a84: 4640 mov r0, r8 +10037a86: e8bd 43f2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, lr} +10037a8a: f004 bc6e b.w 1003c36a + +10037a8e : +10037a8e: e8bd 83f1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, pc} + +10037a92 : +10037a92: 4640 mov r0, r8 +10037a94: f004 bf52 b.w 1003c93c + +10037a98 <_handle_post_rgb>: +10037a98: b5f8 push {r3, r4, r5, r6, r7, lr} +10037a9a: 6806 ldr r6, [r0, #0] +10037a9c: 8937 ldrh r7, [r6, #8] +10037a9e: 460c mov r4, r1 +10037aa0: 4625 mov r5, r4 +10037aa2: e007 b.n 10037ab4 + +10037aa4 : +10037aa4: 8972 ldrh r2, [r6, #10] +10037aa6: 6871 ldr r1, [r6, #4] +10037aa8: 4628 mov r0, r5 +10037aaa: f7d4 fc4d bl 1000c348 +10037aae: 8970 ldrh r0, [r6, #10] +10037ab0: 6836 ldr r6, [r6, #0] +10037ab2: 1945 adds r5, r0, r5 + +10037ab4 : +10037ab4: 2e00 cmp r6, #0 +10037ab6: d1f5 bne.n 10037aa4 +10037ab8: 2000 movs r0, #0 +10037aba: 5538 strb r0, [r7, r4] +10037abc: 4620 mov r0, r4 +10037abe: f20f 4164 addw r1, pc, #1124 ; 0x464 +10037ac2: f7d4 fc4f bl 1000c364 +10037ac6: b118 cbz r0, 10037ad0 +10037ac8: e8bd 40f2 ldmia.w sp!, {r1, r4, r5, r6, r7, lr} +10037acc: 1d00 adds r0, r0, #4 +10037ace: e75b b.n 10037988 <_handle_post_rgb_json> + +10037ad0 : +10037ad0: bdf1 pop {r0, r4, r5, r6, r7, pc} + +10037ad2 : +10037ad2: b5f0 push {r4, r5, r6, r7, lr} +10037ad4: b085 sub sp, #20 +10037ad6: 4604 mov r4, r0 +10037ad8: a901 add r1, sp, #4 +10037ada: f7cf fc41 bl 10007360 +10037ade: 9901 ldr r1, [sp, #4] +10037ae0: 2900 cmp r1, #0 +10037ae2: d036 beq.n 10037b52 +10037ae4: bba8 cbnz r0, 10037b52 +10037ae6: 9801 ldr r0, [sp, #4] +10037ae8: aa02 add r2, sp, #8 +10037aea: a903 add r1, sp, #12 +10037aec: f7d0 ffa2 bl 10008a34 +10037af0: 9803 ldr r0, [sp, #12] +10037af2: f20f 41a0 addw r1, pc, #1184 ; 0x4a0 +10037af6: 2204 movs r2, #4 +10037af8: f7d4 fc30 bl 1000c35c +10037afc: bb30 cbnz r0, 10037b4c +10037afe: 9d01 ldr r5, [sp, #4] +10037b00: 9e03 ldr r6, [sp, #12] +10037b02: f20f 4728 addw r7, pc, #1064 ; 0x428 +10037b06: 4638 mov r0, r7 +10037b08: f7d4 fc26 bl 1000c358 +10037b0c: 4602 mov r2, r0 +10037b0e: 2000 movs r0, #0 +10037b10: 9000 str r0, [sp, #0] +10037b12: 2301 movs r3, #1 +10037b14: 4639 mov r1, r7 +10037b16: 4620 mov r0, r4 +10037b18: f7cf fc9c bl 10007454 +10037b1c: f20f 4140 addw r1, pc, #1088 ; 0x440 +10037b20: 4630 mov r0, r6 +10037b22: f7d4 fc1f bl 1000c364 +10037b26: b140 cbz r0, 10037b3a +10037b28: f20f 403c addw r0, pc, #1084 ; 0x43c +10037b2c: f7d4 fbe9 bl 1000c302 +10037b30: 4971 ldr r1, [pc, #452] ; (10037cf8 ) +10037b32: 4628 mov r0, r5 +10037b34: f7ff ffb0 bl 10037a98 <_handle_post_rgb> +10037b38: e008 b.n 10037b4c + +10037b3a : +10037b3a: f20f 4038 addw r0, pc, #1080 ; 0x438 +10037b3e: f7d4 fbe0 bl 1000c302 +10037b42: 4631 mov r1, r6 +10037b44: f20f 403c addw r0, pc, #1084 ; 0x43c +10037b48: f7d4 fbdb bl 1000c302 + +10037b4c : +10037b4c: 9801 ldr r0, [sp, #4] +10037b4e: f7d0 ff37 bl 100089c0 + +10037b52 : +10037b52: 4620 mov r0, r4 +10037b54: f7cf fcea bl 1000752c +10037b58: b005 add sp, #20 +10037b5a: bdf0 pop {r4, r5, r6, r7, pc} + +10037b5c : +10037b5c: b570 push {r4, r5, r6, lr} +10037b5e: b084 sub sp, #16 +10037b60: 2200 movs r2, #0 +10037b62: 2100 movs r1, #0 +10037b64: 2010 movs r0, #16 +10037b66: f7cf faad bl 100070c4 +10037b6a: 4c64 ldr r4, [pc, #400] ; (10037cfc ) +10037b6c: 2250 movs r2, #80 ; 0x50 +10037b6e: 60e0 str r0, [r4, #12] +10037b70: 2100 movs r1, #0 +10037b72: f7cf fb04 bl 1000717e +10037b76: 68e0 ldr r0, [r4, #12] +10037b78: 21ff movs r1, #255 ; 0xff +10037b7a: f7cf fb2f bl 100071dc +10037b7e: f7ff fdfd bl 1003777c +10037b82: 4d55 ldr r5, [pc, #340] ; (10037cd8 ) +10037b84: f000 f83d bl 10037c02 + +10037b88 : +10037b88: 4606 mov r6, r0 +10037b8a: 1d28 adds r0, r5, #4 +10037b8c: f7d4 fbe4 bl 1000c358 +10037b90: 4603 mov r3, r0 +10037b92: f895 0025 ldrb.w r0, [r5, #37] ; 0x25 +10037b96: 6aa9 ldr r1, [r5, #40] ; 0x28 +10037b98: 9001 str r0, [sp, #4] +10037b9a: 9600 str r6, [sp, #0] +10037b9c: f105 022c add.w r2, r5, #44 ; 0x2c +10037ba0: 1d28 adds r0, r5, #4 +10037ba2: f001 fda1 bl 100396e8 +10037ba6: 4856 ldr r0, [pc, #344] ; (10037d00 ) +10037ba8: 6060 str r0, [r4, #4] +10037baa: 4856 ldr r0, [pc, #344] ; (10037d04 ) +10037bac: 60a0 str r0, [r4, #8] +10037bae: 1d20 adds r0, r4, #4 +10037bb0: f004 fbb9 bl 1003c326 + +10037bb4 : +10037bb4: 68e0 ldr r0, [r4, #12] +10037bb6: 7821 ldrb r1, [r4, #0] +10037bb8: b171 cbz r1, 10037bd8 +10037bba: b130 cbz r0, 10037bca +10037bbc: f7cf fcb6 bl 1000752c +10037bc0: 68e0 ldr r0, [r4, #12] +10037bc2: f7cf faad bl 10007120 +10037bc6: 2000 movs r0, #0 +10037bc8: 60e0 str r0, [r4, #12] + +10037bca : +10037bca: 2200 movs r2, #0 +10037bcc: 6960 ldr r0, [r4, #20] +10037bce: 2300 movs r3, #0 +10037bd0: 4611 mov r1, r2 +10037bd2: f7d2 fcd3 bl 1000a57c +10037bd6: bd7f pop {r0, r1, r2, r3, r4, r5, r6, pc} + +10037bd8 : +10037bd8: a902 add r1, sp, #8 +10037bda: f7cf fb1b bl 10007214 +10037bde: 9902 ldr r1, [sp, #8] +10037be0: 2900 cmp r1, #0 +10037be2: d0e7 beq.n 10037bb4 +10037be4: 2800 cmp r0, #0 +10037be6: d1e5 bne.n 10037bb4 +10037be8: 4608 mov r0, r1 +10037bea: f7ff ff72 bl 10037ad2 +10037bee: e002 b.n 10037bf6 + +10037bf0 : +10037bf0: 200a movs r0, #10 +10037bf2: f7d2 ff6e bl 1000aad2 + +10037bf6 : +10037bf6: 9802 ldr r0, [sp, #8] +10037bf8: f7cf fa92 bl 10007120 +10037bfc: 2800 cmp r0, #0 +10037bfe: d1f7 bne.n 10037bf0 +10037c00: e7d8 b.n 10037bb4 + +10037c02 : +10037c02: f105 002c add.w r0, r5, #44 ; 0x2c +10037c06: f7d4 bba7 b.w 1000c358 + +10037c0a : +10037c0a: b51f push {r0, r1, r2, r3, r4, lr} +10037c0c: f20f 308c addw r0, pc, #908 ; 0x38c +10037c10: f7d4 fb77 bl 1000c302 +10037c14: 4c39 ldr r4, [pc, #228] ; (10037cfc ) +10037c16: 2000 movs r0, #0 +10037c18: 7020 strb r0, [r4, #0] +10037c1a: 6920 ldr r0, [r4, #16] +10037c1c: b9a0 cbnz r0, 10037c48 +10037c1e: 9003 str r0, [sp, #12] +10037c20: 9002 str r0, [sp, #8] +10037c22: 2300 movs r3, #0 +10037c24: f104 0010 add.w r0, r4, #16 +10037c28: 9001 str r0, [sp, #4] +10037c2a: f44f 7200 mov.w r2, #512 ; 0x200 +10037c2e: 2001 movs r0, #1 +10037c30: 9000 str r0, [sp, #0] +10037c32: f20f 3188 addw r1, pc, #904 ; 0x388 +10037c36: 4834 ldr r0, [pc, #208] ; (10037d08 ) +10037c38: f7d2 fe76 bl 1000a928 +10037c3c: 2801 cmp r0, #1 +10037c3e: bf1c itt ne +10037c40: f20f 3084 addwne r0, pc, #900 ; 0x384 +10037c44: f7d4 fb5d blne 1000c302 + +10037c48 : +10037c48: 6960 ldr r0, [r4, #20] +10037c4a: b928 cbnz r0, 10037c58 +10037c4c: 2100 movs r1, #0 +10037c4e: f04f 30ff mov.w r0, #4294967295 +10037c52: f7d2 fc8a bl 1000a56a +10037c56: 6160 str r0, [r4, #20] + +10037c58 : +10037c58: bd1f pop {r0, r1, r2, r3, r4, pc} + ... + +10037c5c : +10037c5c: 0052 0000 R... + +10037c60 : +10037c60: 0047 0000 G... + +10037c64 : +10037c64: 0042 0000 B... + +10037c68 : +10037c68: b510 push {r4, lr} +10037c6a: 4c24 ldr r4, [pc, #144] ; (10037cfc ) +10037c6c: 2001 movs r0, #1 +10037c6e: 7020 strb r0, [r4, #0] +10037c70: 68e0 ldr r0, [r4, #12] +10037c72: b108 cbz r0, 10037c78 +10037c74: f7cf fc5c bl 10007530 + +10037c78 : +10037c78: 6960 ldr r0, [r4, #20] +10037c7a: b1d0 cbz r0, 10037cb2 +10037c7c: 2300 movs r3, #0 +10037c7e: f643 2298 movw r2, #15000 ; 0x3a98 +10037c82: 2100 movs r1, #0 +10037c84: f7d2 fd12 bl 1000a6ac +10037c88: 2801 cmp r0, #1 +10037c8a: d00d beq.n 10037ca8 +10037c8c: 68e0 ldr r0, [r4, #12] +10037c8e: b130 cbz r0, 10037c9e +10037c90: f7cf fc4c bl 1000752c +10037c94: 68e0 ldr r0, [r4, #12] +10037c96: f7cf fa43 bl 10007120 +10037c9a: 2000 movs r0, #0 +10037c9c: 60e0 str r0, [r4, #12] + +10037c9e : +10037c9e: 6961 ldr r1, [r4, #20] +10037ca0: f20f 304c addw r0, pc, #844 ; 0x34c +10037ca4: f7d4 fb2d bl 1000c302 + +10037ca8 : +10037ca8: 6960 ldr r0, [r4, #20] +10037caa: f7d2 fd8f bl 1000a7cc +10037cae: 2000 movs r0, #0 +10037cb0: 6160 str r0, [r4, #20] + +10037cb2 : +10037cb2: 6920 ldr r0, [r4, #16] +10037cb4: b118 cbz r0, 10037cbe +10037cb6: f7d2 fec3 bl 1000aa40 +10037cba: 2000 movs r0, #0 +10037cbc: 6120 str r0, [r4, #16] + +10037cbe : +10037cbe: e8bd 4010 ldmia.w sp!, {r4, lr} +10037cc2: f20f 305c addw r0, pc, #860 ; 0x35c +10037cc6: f7d4 bb1c b.w 1000c302 + ... + +10037ccc : +10037ccc: 464f 0046 OFF. + +10037cd0 : +10037cd0: 4e4f 0000 ON.. + +10037cd4 : +10037cd4: 5502 7766 .Ufw + +10037cd8 : +10037cd8: 7b48 1004 H{.. + +10037cdc : +10037cdc: 0004 0040 ..@. + +10037ce0 : +10037ce0: 4156 1004 VA.. + +10037ce4 : +10037ce4: 4157 1004 WA.. + +10037ce8 : +10037ce8: 4158 1004 XA.. + +10037cec : +10037cec: 415a 1004 ZA.. + +10037cf0 : +10037cf0: 4154 1004 TA.. + +10037cf4 : +10037cf4: 4155 1004 UA.. + +10037cf8 : +10037cf8: 7bd0 1004 .{.. + +10037cfc : +10037cfc: 7bb8 1004 .{.. + +10037d00 : +10037d00: c8b5 1000 .... + +10037d04 : +10037d04: c9c3 1000 .... + +10037d08 : +10037d08: 7b5d 1003 ]{.. + +10037d0c : +10037d0c: 6c77 6e61 0030 0000 wlan0... + +10037d14 : +10037d14: 6c77 6e61 0031 0000 wlan1... + +10037d1c : +10037d1c: 0a0d 6f4c 6461 6957 6966 6f43 666e 6769 ..LoadWifiConfig +10037d2c: 2928 203a 6552 6461 6620 6f72 206d 4c46 (): Read from FL +10037d3c: 5341 2148 000a 0000 ASH!.... + +10037d44 : +10037d44: 0a0d 6f4c 6461 6957 6966 6f43 666e 6769 ..LoadWifiConfig +10037d54: 2928 203a 6f6c 6163 5f6c 6f63 666e 6769 (): local_config +10037d64: 622e 6f6f 5f74 6f6d 6564 303d 2578 0a78 .boot_mode=0x%x. +10037d74: 0000 0000 .... + +10037d78 : +10037d78: 0a0d 6f4c 6461 6957 6966 6f43 666e 6769 ..LoadWifiConfig +10037d88: 2928 203a 6f6c 6163 5f6c 6f63 666e 6769 (): local_config +10037d98: 732e 6973 3d64 7325 000a 0000 .ssid=%s.... + +10037da4 : +10037da4: 0a0d 6f4c 6461 6957 6966 6f43 666e 6769 ..LoadWifiConfig +10037db4: 2928 203a 6f6c 6163 5f6c 6f63 666e 6769 (): local_config +10037dc4: 632e 6168 6e6e 6c65 253d 0a64 0000 0000 .channel=%d..... + +10037dd4 : +10037dd4: 0a0d 6f4c 6461 6957 6966 6f43 666e 6769 ..LoadWifiConfig +10037de4: 2928 203a 6f6c 6163 5f6c 6f63 666e 6769 (): local_config +10037df4: 732e 6365 7275 7469 5f79 7974 6570 253d .security_type=% +10037e04: 0a64 0000 d... + +10037e08 : +10037e08: 0a0d 6f4c 6461 6957 6966 6f43 666e 6769 ..LoadWifiConfig +10037e18: 2928 203a 6f6c 6163 5f6c 6f63 666e 6769 (): local_config +10037e28: 702e 7361 7773 726f 3d64 7325 000a 0000 .password=%s.... + +10037e38 : +10037e38: 0d0a 7257 7469 6974 676e 6220 6f6f 2074 ..Writting boot +10037e48: 6f6d 6564 3020 3778 3637 3536 3035 2032 mode 0x77665502 +10037e58: 6e61 2064 6957 462d 2069 6573 7474 6e69 and Wi-Fi settin +10037e68: 2067 6f74 6620 616c 6873 2e20 2e2e 0000 g to flash ..... + +10037e78 : +10037e78: 6f4d 6564 0000 0000 Mode.... + +10037e80 : +10037e80: 7053 6565 0064 0000 Speed... + +10037e88 : +10037e88: 3a52 2520 0a64 0000 R: %d... + +10037e90 : +10037e90: 3a47 2520 0a64 0000 G: %d... + +10037e98 : +10037e98: 3a42 2520 0a64 0000 B: %d... + +10037ea0 : +10037ea0: 6f4d 6564 203a 7325 000a 0000 Mode: %s.... + +10037eac : +10037eac: 7053 6565 3a64 2520 0a64 0000 Speed: %d... + +10037eb8 : +10037eb8: 6772 5f62 6f6d 6564 685f 6e61 6c64 5f65 rgb_mode_handle_ +10037ec8: 666f 0a66 0000 0000 off..... + +10037ed0 : +10037ed0: 6772 5f62 6f6d 6564 685f 6e61 6c64 5f65 rgb_mode_handle_ +10037ee0: 6e6f 000a on.. + +10037ee4 : +10037ee4: 6c42 6e69 006b 0000 Blink... + +10037eec : +10037eec: 6772 5f62 6f6d 6564 685f 6e61 6c64 5f65 rgb_mode_handle_ +10037efc: 6c62 6e69 0a6b 0000 blink... + +10037f04 : +10037f04: 654d 6574 726f 0000 Meteor.. + +10037f0c : +10037f0c: 6772 5f62 6f6d 6564 685f 6e61 6c64 5f65 rgb_mode_handle_ +10037f1c: 656d 6574 726f 000a meteor.. + +10037f24 : +10037f24: 0a0d 0a0d 0000 0000 ........ + +10037f2c : +10037f2c: 5448 5054 312f 302e 3220 3030 4f20 0d4b HTTP/1.0 200 OK. +10037f3c: 430a 6e6f 6574 746e 742d 7079 3a65 6120 .Content-type: a +10037f4c: 7070 696c 6163 6974 6e6f 6a2f 6f73 0d6e pplication/json. +10037f5c: 0d0a 000a .... + +10037f60 : +10037f60: 722f 6267 0000 0000 /rgb.... + +10037f68 : +10037f68: 4f50 5453 2f20 6772 0a62 0000 POST /rgb... + +10037f74 : +10037f74: 4f50 5453 5520 6b6e 6f6e 6e77 000a 0000 POST Unknown.... + +10037f84 : +10037f84: 6370 7852 7453 6972 676e 203a 7325 000a pcRxString: %s.. + +10037f94 : +10037f94: 4f50 5453 0000 0000 POST.... + +10037f9c : +10037f9c: 0a0d 4557 3a42 6e45 6574 2072 7473 7261 ..WEB:Enter star +10037fac: 2074 6577 2062 6573 7672 7265 0a21 0000 t web server!... + +10037fbc : +10037fbc: 6577 5f62 6573 7672 7265 0000 web_server.. + +10037fc8 : +10037fc8: 0d0a 4557 3a42 4320 6572 7461 2065 6577 ..WEB: Create we +10037fd8: 7362 7265 6576 2072 6174 6b73 6620 6961 bserver task fai +10037fe8: 656c 2164 000a 0000 led!.... + +10037ff0 : +10037ff0: 0a0d 4557 3a42 5420 6b61 2065 6577 7362 ..WEB: Take webs +10038000: 7320 6d65 2861 7025 2029 6166 6c69 6465 sema(%p) failed +10038010: 2121 2121 2121 2121 2121 0a21 0000 0000 !!!!!!!!!!!..... + +10038020 : +10038020: 0a0d 4557 3a42 7845 7469 7320 6f74 2070 ..WEB:Exit stop +10038030: 6577 2062 6573 7672 7265 0a21 0000 0000 web server!..... + +10038040 : +10038040: b538 push {r3, r4, r5, lr} +10038042: f8df 45cc ldr.w r4, [pc, #1484] ; 10038610 +10038046: 4605 mov r5, r0 +10038048: 6ca0 ldr r0, [r4, #72] ; 0x48 +1003804a: f000 f979 bl 10038340 + +1003804e : +1003804e: 2001 movs r0, #1 +10038050: b13d cbz r5, 10038062 +10038052: 2d21 cmp r5, #33 ; 0x21 +10038054: da05 bge.n 10038062 +10038056: 6a21 ldr r1, [r4, #32] +10038058: 1e6a subs r2, r5, #1 +1003805a: 4090 lsls r0, r2 +1003805c: 4308 orrs r0, r1 +1003805e: 6220 str r0, [r4, #32] +10038060: e020 b.n 100380a4 + +10038062 : +10038062: f1a5 0221 sub.w r2, r5, #33 ; 0x21 +10038066: 2a20 cmp r2, #32 +10038068: d204 bcs.n 10038074 +1003806a: 6a61 ldr r1, [r4, #36] ; 0x24 +1003806c: 4090 lsls r0, r2 +1003806e: 4308 orrs r0, r1 +10038070: 6260 str r0, [r4, #36] ; 0x24 +10038072: e017 b.n 100380a4 + +10038074 : +10038074: f1a5 0241 sub.w r2, r5, #65 ; 0x41 +10038078: 2a20 cmp r2, #32 +1003807a: d204 bcs.n 10038086 +1003807c: 6aa1 ldr r1, [r4, #40] ; 0x28 +1003807e: 4090 lsls r0, r2 +10038080: 4308 orrs r0, r1 +10038082: 62a0 str r0, [r4, #40] ; 0x28 +10038084: e00e b.n 100380a4 + +10038086 : +10038086: f1a5 0161 sub.w r1, r5, #97 ; 0x61 +1003808a: 2920 cmp r1, #32 +1003808c: d206 bcs.n 1003809c +1003808e: 6ae1 ldr r1, [r4, #44] ; 0x2c +10038090: f1a5 0261 sub.w r2, r5, #97 ; 0x61 +10038094: 4090 lsls r0, r2 +10038096: 4308 orrs r0, r1 +10038098: 62e0 str r0, [r4, #44] ; 0x2c +1003809a: e003 b.n 100380a4 + +1003809c : +1003809c: f20f 507c addw r0, pc, #1404 ; 0x57c +100380a0: f7d4 f92f bl 1000c302 + +100380a4 : +100380a4: 2300 movs r3, #0 +100380a6: 6ca0 ldr r0, [r4, #72] ; 0x48 +100380a8: b001 add sp, #4 +100380aa: e8bd 4030 ldmia.w sp!, {r4, r5, lr} +100380ae: 2200 movs r2, #0 +100380b0: 4611 mov r1, r2 +100380b2: f7d2 ba63 b.w 1000a57c + +100380b6 : +100380b6: 2235 movs r2, #53 ; 0x35 +100380b8: 7002 strb r2, [r0, #0] +100380ba: 2201 movs r2, #1 +100380bc: 7042 strb r2, [r0, #1] +100380be: 7081 strb r1, [r0, #2] +100380c0: 1cc0 adds r0, r0, #3 +100380c2: 2906 cmp r1, #6 +100380c4: bf04 itt eq +100380c6: 21ff moveq r1, #255 ; 0xff +100380c8: f800 1b01 strbeq.w r1, [r0], #1 +100380cc: 4770 bx lr + +100380ce : +100380ce: b510 push {r4, lr} +100380d0: 4604 mov r4, r0 +100380d2: 2000 movs r0, #0 +100380d4: 7021 strb r1, [r4, #0] +100380d6: 7062 strb r2, [r4, #1] +100380d8: 1ca4 adds r4, r4, #2 +100380da: 2a01 cmp r2, #1 +100380dc: d00b beq.n 100380f6 +100380de: 2a02 cmp r2, #2 +100380e0: d005 beq.n 100380ee +100380e2: 2a04 cmp r2, #4 +100380e4: d10a bne.n 100380fc +100380e6: f000 f80a bl 100380fe + +100380ea : +100380ea: 1d20 adds r0, r4, #4 +100380ec: bd10 pop {r4, pc} + +100380ee : +100380ee: f000 f806 bl 100380fe + +100380f2 : +100380f2: 1ca0 adds r0, r4, #2 +100380f4: bd10 pop {r4, pc} + +100380f6 : +100380f6: f000 f802 bl 100380fe + +100380fa : +100380fa: 1c60 adds r0, r4, #1 + +100380fc : +100380fc: bd10 pop {r4, pc} + +100380fe : +100380fe: 4619 mov r1, r3 +10038100: 4620 mov r0, r4 +10038102: f7d4 b921 b.w 1000c348 + +10038106 : +10038106: b510 push {r4, lr} +10038108: f8df 4504 ldr.w r4, [pc, #1284] ; 10038610 +1003810c: f104 0354 add.w r3, r4, #84 ; 0x54 +10038110: 2204 movs r2, #4 +10038112: 2101 movs r1, #1 +10038114: f7ff ffdb bl 100380ce +10038118: 1d23 adds r3, r4, #4 +1003811a: 2204 movs r2, #4 +1003811c: 2103 movs r1, #3 +1003811e: f7ff ffd6 bl 100380ce +10038122: 1d23 adds r3, r4, #4 +10038124: 2204 movs r2, #4 +10038126: 2106 movs r1, #6 +10038128: f7ff ffd1 bl 100380ce +1003812c: f20f 5364 addw r3, pc, #1380 ; 0x564 +10038130: 2204 movs r2, #4 +10038132: 2133 movs r1, #51 ; 0x33 +10038134: f7ff ffcb bl 100380ce +10038138: 1d23 adds r3, r4, #4 +1003813a: 2204 movs r2, #4 +1003813c: 2136 movs r1, #54 ; 0x36 +1003813e: f7ff ffc6 bl 100380ce +10038142: f104 0338 add.w r3, r4, #56 ; 0x38 +10038146: 2204 movs r2, #4 +10038148: 211c movs r1, #28 +1003814a: f7ff ffc0 bl 100380ce +1003814e: f20f 5348 addw r3, pc, #1352 ; 0x548 +10038152: 2202 movs r2, #2 +10038154: 211a movs r1, #26 +10038156: f7ff ffba bl 100380ce +1003815a: 2300 movs r3, #0 +1003815c: 2201 movs r2, #1 +1003815e: 211f movs r1, #31 +10038160: f7ff ffb5 bl 100380ce +10038164: 21ff movs r1, #255 ; 0xff +10038166: 7001 strb r1, [r0, #0] +10038168: bd10 pop {r4, pc} + +1003816a : +1003816a: b532 push {r1, r4, r5, lr} +1003816c: 4604 mov r4, r0 +1003816e: 2002 movs r0, #2 +10038170: 7020 strb r0, [r4, #0] +10038172: 2001 movs r0, #1 +10038174: 7060 strb r0, [r4, #1] +10038176: 2006 movs r0, #6 +10038178: 70a0 strb r0, [r4, #2] +1003817a: 2000 movs r0, #0 +1003817c: 70e0 strb r0, [r4, #3] +1003817e: 2204 movs r2, #4 +10038180: f8df 548c ldr.w r5, [pc, #1164] ; 10038610 +10038184: 1d21 adds r1, r4, #4 +10038186: f105 0050 add.w r0, r5, #80 ; 0x50 +1003818a: f7d4 f8dd bl 1000c348 +1003818e: 2000 movs r0, #0 +10038190: 8120 strh r0, [r4, #8] +10038192: f44f 4000 mov.w r0, #32768 ; 0x8000 +10038196: f7d4 f9d6 bl 1000c546 +1003819a: 8160 strh r0, [r4, #10] +1003819c: 2204 movs r2, #4 +1003819e: a900 add r1, sp, #0 +100381a0: f104 0010 add.w r0, r4, #16 +100381a4: f7d4 f8d0 bl 1000c348 +100381a8: 2204 movs r2, #4 +100381aa: 2100 movs r1, #0 +100381ac: f104 000c add.w r0, r4, #12 +100381b0: f7d4 f8cc bl 1000c34c +100381b4: 2204 movs r2, #4 +100381b6: 2100 movs r1, #0 +100381b8: f104 0014 add.w r0, r4, #20 +100381bc: f7d4 f8c6 bl 1000c34c +100381c0: 2204 movs r2, #4 +100381c2: 2100 movs r1, #0 +100381c4: f104 0018 add.w r0, r4, #24 +100381c8: f7d4 f8c0 bl 1000c34c +100381cc: 2210 movs r2, #16 +100381ce: f105 0158 add.w r1, r5, #88 ; 0x58 +100381d2: f104 001c add.w r0, r4, #28 +100381d6: f7d4 f8b7 bl 1000c348 +100381da: 2240 movs r2, #64 ; 0x40 +100381dc: 2100 movs r1, #0 +100381de: f104 002c add.w r0, r4, #44 ; 0x2c +100381e2: f7d4 f8b3 bl 1000c34c +100381e6: 2280 movs r2, #128 ; 0x80 +100381e8: 2100 movs r1, #0 +100381ea: f104 006c add.w r0, r4, #108 ; 0x6c +100381ee: f7d4 f8ad bl 1000c34c +100381f2: 34ec adds r4, #236 ; 0xec +100381f4: 6c6a ldr r2, [r5, #68] ; 0x44 +100381f6: 2100 movs r1, #0 +100381f8: 4620 mov r0, r4 +100381fa: f7d4 f8a7 bl 1000c34c +100381fe: 2204 movs r2, #4 +10038200: f20f 418c addw r1, pc, #1164 ; 0x48c +10038204: 4620 mov r0, r4 +10038206: f7d4 f89f bl 1000c348 +1003820a: bd31 pop {r0, r4, r5, pc} + +1003820c : +1003820c: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +10038210: 4680 mov r8, r0 +10038212: f8df 53fc ldr.w r5, [pc, #1020] ; 10038610 +10038216: f8d8 0004 ldr.w r0, [r8, #4] +1003821a: 6428 str r0, [r5, #64] ; 0x40 +1003821c: 78e8 ldrb r0, [r5, #3] +1003821e: b168 cbz r0, 1003823c +10038220: 2204 movs r2, #4 +10038222: f105 0114 add.w r1, r5, #20 +10038226: 4628 mov r0, r5 +10038228: f7d4 f88c bl 1000c344 +1003822c: b930 cbnz r0, 1003823c +1003822e: f000 f87b bl 10038328 + +10038232 : +10038232: f7d4 f887 bl 1000c344 +10038236: b908 cbnz r0, 1003823c +10038238: 7dee ldrb r6, [r5, #23] +1003823a: e01d b.n 10038278 + +1003823c : +1003823c: 7d28 ldrb r0, [r5, #20] +1003823e: 7e29 ldrb r1, [r5, #24] +10038240: 4288 cmp r0, r1 +10038242: bf02 ittt eq +10038244: 7d68 ldrbeq r0, [r5, #21] +10038246: 7e69 ldrbeq r1, [r5, #25] +10038248: 4288 cmpeq r0, r1 +1003824a: bf02 ittt eq +1003824c: 7da8 ldrbeq r0, [r5, #22] +1003824e: 7ea9 ldrbeq r1, [r5, #26] +10038250: 4288 cmpeq r0, r1 +10038252: d112 bne.n 1003827a +10038254: 7dee ldrb r6, [r5, #23] +10038256: b186 cbz r6, 1003827a +10038258: 1e70 subs r0, r6, #1 +1003825a: 1101 asrs r1, r0, #4 +1003825c: eb00 61d1 add.w r1, r0, r1, lsr #27 +10038260: 1149 asrs r1, r1, #5 +10038262: 2904 cmp r1, #4 +10038264: d209 bcs.n 1003827a +10038266: eb05 0281 add.w r2, r5, r1, lsl #2 +1003826a: eba0 1141 sub.w r1, r0, r1, lsl #5 +1003826e: 6a12 ldr r2, [r2, #32] +10038270: fa22 f101 lsr.w r1, r2, r1 +10038274: 07c9 lsls r1, r1, #31 +10038276: d400 bmi.n 1003827a + +10038278 : +10038278: bb36 cbnz r6, 100382c8 + +1003827a : +1003827a: 6be8 ldr r0, [r5, #60] ; 0x3c +1003827c: 2800 cmp r0, #0 +1003827e: bf19 ittee ne +10038280: 7bee ldrbne r6, [r5, #15] +10038282: f895 9013 ldrbne.w r9, [r5, #19] +10038286: 2600 moveq r6, #0 +10038288: f04f 09ff moveq.w r9, #255 ; 0xff +1003828c: 6ca8 ldr r0, [r5, #72] ; 0x48 +1003828e: f000 f857 bl 10038340 + +10038292 : +10038292: 2400 movs r4, #0 + +10038294 : +10038294: 2700 movs r7, #0 + +10038296 : +10038296: f105 0020 add.w r0, r5, #32 +1003829a: f850 0024 ldr.w r0, [r0, r4, lsl #2] +1003829e: 40f8 lsrs r0, r7 +100382a0: 07c0 lsls r0, r0, #31 +100382a2: d406 bmi.n 100382b2 +100382a4: eb07 1044 add.w r0, r7, r4, lsl #5 +100382a8: 1c40 adds r0, r0, #1 +100382aa: 42b0 cmp r0, r6 +100382ac: bfa8 it ge +100382ae: 4581 cmpge r9, r0 +100382b0: da34 bge.n 1003831c + +100382b2 : +100382b2: 1c78 adds r0, r7, #1 +100382b4: b2c7 uxtb r7, r0 +100382b6: 2f20 cmp r7, #32 +100382b8: dbed blt.n 10038296 +100382ba: 1c60 adds r0, r4, #1 +100382bc: b2c4 uxtb r4, r0 +100382be: 2c04 cmp r4, #4 +100382c0: dbe8 blt.n 10038294 +100382c2: f000 f837 bl 10038334 + +100382c6 : +100382c6: 2600 movs r6, #0 + +100382c8 : +100382c8: b2f6 uxtb r6, r6 +100382ca: b91e cbnz r6, 100382d4 +100382cc: f20f 3074 addw r0, pc, #884 ; 0x374 +100382d0: f7d4 f817 bl 1000c302 + +100382d4 : +100382d4: 7ea8 ldrb r0, [r5, #26] +100382d6: 7e69 ldrb r1, [r5, #25] +100382d8: 0400 lsls r0, r0, #16 +100382da: ea40 6006 orr.w r0, r0, r6, lsl #24 +100382de: ea40 2001 orr.w r0, r0, r1, lsl #8 +100382e2: 7e29 ldrb r1, [r5, #24] +100382e4: 4308 orrs r0, r1 +100382e6: 6028 str r0, [r5, #0] +100382e8: f000 f81e bl 10038328 + +100382ec : +100382ec: f7d4 f82c bl 1000c348 +100382f0: 6829 ldr r1, [r5, #0] +100382f2: 6c28 ldr r0, [r5, #64] ; 0x40 +100382f4: f7ff ff39 bl 1003816a +100382f8: 6c28 ldr r0, [r5, #64] ; 0x40 +100382fa: 2102 movs r1, #2 +100382fc: 30f0 adds r0, #240 ; 0xf0 +100382fe: f7ff feda bl 100380b6 +10038302: f7ff ff00 bl 10038106 +10038306: 6ce8 ldr r0, [r5, #76] ; 0x4c +10038308: 9000 str r0, [sp, #0] +1003830a: 2344 movs r3, #68 ; 0x44 +1003830c: 6b28 ldr r0, [r5, #48] ; 0x30 +1003830e: f105 0234 add.w r2, r5, #52 ; 0x34 +10038312: 4641 mov r1, r8 +10038314: f7d1 f9d7 bl 100096c6 +10038318: e8bd 83f1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, pc} + +1003831c : +1003831c: f000 f80a bl 10038334 + +10038320 : +10038320: eb07 1044 add.w r0, r7, r4, lsl #5 +10038324: 1c46 adds r6, r0, #1 +10038326: e7cf b.n 100382c8 + +10038328 : +10038328: 2210 movs r2, #16 +1003832a: f105 0158 add.w r1, r5, #88 ; 0x58 +1003832e: f105 0068 add.w r0, r5, #104 ; 0x68 +10038332: 4770 bx lr + +10038334 : +10038334: 2200 movs r2, #0 +10038336: 6ca8 ldr r0, [r5, #72] ; 0x48 +10038338: 2300 movs r3, #0 +1003833a: 4611 mov r1, r2 +1003833c: f7d2 b91e b.w 1000a57c + +10038340 : +10038340: 2300 movs r3, #0 +10038342: f04f 32ff mov.w r2, #4294967295 +10038346: 2100 movs r1, #0 +10038348: f7d2 b9b0 b.w 1000a6ac + +1003834c : +1003834c: b5f8 push {r3, r4, r5, r6, r7, lr} +1003834e: 4cb0 ldr r4, [pc, #704] ; (10038610 ) +10038350: 7f21 ldrb r1, [r4, #28] +10038352: 2801 cmp r0, #1 +10038354: d006 beq.n 10038364 +10038356: 2803 cmp r0, #3 +10038358: d007 beq.n 1003836a +1003835a: 2804 cmp r0, #4 +1003835c: bf18 it ne +1003835e: 2807 cmpne r0, #7 +10038360: d047 beq.n 100383f2 +10038362: e048 b.n 100383f6 + +10038364 : +10038364: 2905 cmp r1, #5 +10038366: d146 bne.n 100383f6 +10038368: e044 b.n 100383f4 + +1003836a : +1003836a: 78e0 ldrb r0, [r4, #3] +1003836c: 2901 cmp r1, #1 +1003836e: d108 bne.n 10038382 +10038370: b130 cbz r0, 10038380 +10038372: f000 f848 bl 10038406 + +10038376 : +10038376: 2800 cmp r0, #0 +10038378: bf14 ite ne +1003837a: 2004 movne r0, #4 +1003837c: 2003 moveq r0, #3 +1003837e: e039 b.n 100383f4 + +10038380 : +10038380: e035 b.n 100383ee + +10038382 : +10038382: 2905 cmp r1, #5 +10038384: d133 bne.n 100383ee +10038386: b138 cbz r0, 10038398 +10038388: f000 f83d bl 10038406 + +1003838c : +1003838c: b920 cbnz r0, 10038398 +1003838e: f000 f834 bl 100383fa + +10038392 : +10038392: f7d3 ffd7 bl 1000c344 +10038396: b340 cbz r0, 100383ea + +10038398 : +10038398: 7e20 ldrb r0, [r4, #24] +1003839a: 7d21 ldrb r1, [r4, #20] +1003839c: 4281 cmp r1, r0 +1003839e: bf02 ittt eq +100383a0: 7e61 ldrbeq r1, [r4, #25] +100383a2: 7d62 ldrbeq r2, [r4, #21] +100383a4: 428a cmpeq r2, r1 +100383a6: bf02 ittt eq +100383a8: 7ea2 ldrbeq r2, [r4, #26] +100383aa: 7da3 ldrbeq r3, [r4, #22] +100383ac: 4293 cmpeq r3, r2 +100383ae: d11e bne.n 100383ee +100383b0: 7de3 ldrb r3, [r4, #23] +100383b2: b1e3 cbz r3, 100383ee +100383b4: 1e5d subs r5, r3, #1 +100383b6: 112e asrs r6, r5, #4 +100383b8: eb05 66d6 add.w r6, r5, r6, lsr #27 +100383bc: 1176 asrs r6, r6, #5 +100383be: 2e04 cmp r6, #4 +100383c0: d215 bcs.n 100383ee +100383c2: eb04 0786 add.w r7, r4, r6, lsl #2 +100383c6: eba5 1646 sub.w r6, r5, r6, lsl #5 +100383ca: 6a3f ldr r7, [r7, #32] +100383cc: fa27 f606 lsr.w r6, r7, r6 +100383d0: 07f6 lsls r6, r6, #31 +100383d2: d40c bmi.n 100383ee +100383d4: 0412 lsls r2, r2, #16 +100383d6: ea42 6203 orr.w r2, r2, r3, lsl #24 +100383da: ea42 2101 orr.w r1, r2, r1, lsl #8 +100383de: 4308 orrs r0, r1 +100383e0: 6020 str r0, [r4, #0] +100383e2: f000 f80a bl 100383fa + +100383e6 : +100383e6: f7d3 ffaf bl 1000c348 + +100383ea : +100383ea: 2003 movs r0, #3 +100383ec: e002 b.n 100383f4 + +100383ee : +100383ee: 2004 movs r0, #4 +100383f0: e000 b.n 100383f4 + +100383f2 : +100383f2: 2005 movs r0, #5 + +100383f4 : +100383f4: 7720 strb r0, [r4, #28] + +100383f6 : +100383f6: 7f20 ldrb r0, [r4, #28] +100383f8: bdf2 pop {r1, r4, r5, r6, r7, pc} + +100383fa : +100383fa: 2210 movs r2, #16 +100383fc: f104 0158 add.w r1, r4, #88 ; 0x58 +10038400: f104 0068 add.w r0, r4, #104 ; 0x68 +10038404: 4770 bx lr + +10038406 : +10038406: 2204 movs r2, #4 +10038408: f104 0114 add.w r1, r4, #20 +1003840c: 4620 mov r0, r4 +1003840e: f7d3 bf99 b.w 1000c344 + +10038412 : +10038412: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +10038416: 4615 mov r5, r2 +10038418: b082 sub sp, #8 +1003841a: 4f7d ldr r7, [pc, #500] ; (10038610 ) +1003841c: 6868 ldr r0, [r5, #4] +1003841e: 6438 str r0, [r7, #64] ; 0x40 +10038420: 4688 mov r8, r1 +10038422: 2600 movs r6, #0 +10038424: b92d cbnz r5, 10038432 +10038426: e8bd 47f6 ldmia.w sp!, {r1, r2, r4, r5, r6, r7, r8, r9, sl, lr} +1003842a: f20f 2030 addw r0, pc, #560 ; 0x230 +1003842e: f7d3 bf68 b.w 1000c302 + +10038432 : +10038432: 980a ldr r0, [sp, #40] ; 0x28 +10038434: 2844 cmp r0, #68 ; 0x44 +10038436: d16f bne.n 10038518 +10038438: f9b5 4008 ldrsh.w r4, [r5, #8] +1003843c: 6828 ldr r0, [r5, #0] +1003843e: b138 cbz r0, 10038450 +10038440: 2100 movs r1, #0 +10038442: 4628 mov r0, r5 +10038444: f7d0 faa7 bl 10008996 +10038448: 4606 mov r6, r0 +1003844a: 8930 ldrh r0, [r6, #8] +1003844c: 42a0 cmp r0, r4 +1003844e: d169 bne.n 10038524 + +10038450 : +10038450: 6868 ldr r0, [r5, #4] +10038452: 6438 str r0, [r7, #64] ; 0x40 +10038454: f100 011c add.w r1, r0, #28 +10038458: 2210 movs r2, #16 +1003845a: f107 0058 add.w r0, r7, #88 ; 0x58 +1003845e: f7d3 ff73 bl 1000c348 +10038462: 6c38 ldr r0, [r7, #64] ; 0x40 +10038464: 8969 ldrh r1, [r5, #10] +10038466: 686a ldr r2, [r5, #4] +10038468: 30ec adds r0, #236 ; 0xec +1003846a: 1a09 subs r1, r1, r0 +1003846c: 1851 adds r1, r2, r1 +1003846e: 6479 str r1, [r7, #68] ; 0x44 +10038470: 2204 movs r2, #4 +10038472: f20f 211c addw r1, pc, #540 ; 0x21c +10038476: f7d3 ff65 bl 1000c344 +1003847a: 2800 cmp r0, #0 +1003847c: d14c bne.n 10038518 +1003847e: 6c38 ldr r0, [r7, #64] ; 0x40 +10038480: f100 04f0 add.w r4, r0, #240 ; 0xf0 +10038484: 6c78 ldr r0, [r7, #68] ; 0x44 +10038486: 1f00 subs r0, r0, #4 +10038488: b200 sxth r0, r0 +1003848a: f04f 0900 mov.w r9, #0 +1003848e: eb00 0a04 add.w sl, r0, r4 +10038492: e002 b.n 1003849a + +10038494 : +10038494: 7860 ldrb r0, [r4, #1] +10038496: 1900 adds r0, r0, r4 +10038498: 1c84 adds r4, r0, #2 + +1003849a : +1003849a: 4554 cmp r4, sl +1003849c: d20e bcs.n 100384bc +1003849e: 7820 ldrb r0, [r4, #0] +100384a0: 2832 cmp r0, #50 ; 0x32 +100384a2: d004 beq.n 100384ae +100384a4: 2835 cmp r0, #53 ; 0x35 +100384a6: bf08 it eq +100384a8: f894 9002 ldrbeq.w r9, [r4, #2] +100384ac: e7f2 b.n 10038494 + +100384ae : +100384ae: 2204 movs r2, #4 +100384b0: 1ca1 adds r1, r4, #2 +100384b2: f107 0014 add.w r0, r7, #20 +100384b6: f7d3 ff47 bl 1000c348 +100384ba: e7eb b.n 10038494 + +100384bc : +100384bc: 4648 mov r0, r9 +100384be: f7ff ff45 bl 1003834c +100384c2: 2801 cmp r0, #1 +100384c4: d004 beq.n 100384d0 +100384c6: 2803 cmp r0, #3 +100384c8: d006 beq.n 100384d8 +100384ca: 2804 cmp r0, #4 +100384cc: d016 beq.n 100384fc +100384ce: e023 b.n 10038518 + +100384d0 : +100384d0: 4628 mov r0, r5 +100384d2: f7ff fe9b bl 1003820c +100384d6: e01f b.n 10038518 + +100384d8 : +100384d8: 6868 ldr r0, [r5, #4] +100384da: 6839 ldr r1, [r7, #0] +100384dc: 6438 str r0, [r7, #64] ; 0x40 +100384de: f7ff fe44 bl 1003816a +100384e2: 2105 movs r1, #5 +100384e4: 6c38 ldr r0, [r7, #64] ; 0x40 +100384e6: 30f0 adds r0, #240 ; 0xf0 +100384e8: f7ff fde5 bl 100380b6 +100384ec: f7ff fe0b bl 10038106 +100384f0: f000 f81d bl 1003852e + +100384f4 : +100384f4: 78f8 ldrb r0, [r7, #3] +100384f6: f7ff fda3 bl 10038040 +100384fa: e00b b.n 10038514 + +100384fc : +100384fc: 6868 ldr r0, [r5, #4] +100384fe: 6438 str r0, [r7, #64] ; 0x40 +10038500: 2100 movs r1, #0 +10038502: f7ff fe32 bl 1003816a +10038506: 6c38 ldr r0, [r7, #64] ; 0x40 +10038508: 2106 movs r1, #6 +1003850a: 30f0 adds r0, #240 ; 0xf0 +1003850c: f7ff fdd3 bl 100380b6 +10038510: f000 f80d bl 1003852e + +10038514 : +10038514: 2005 movs r0, #5 +10038516: 7738 strb r0, [r7, #28] + +10038518 : +10038518: 4640 mov r0, r8 +1003851a: f7d1 f9a6 bl 1000986a +1003851e: b10e cbz r6, 10038524 +10038520: 4630 mov r0, r6 +10038522: e000 b.n 10038526 + +10038524 : +10038524: 4628 mov r0, r5 + +10038526 : +10038526: e8bd 47f6 ldmia.w sp!, {r1, r2, r4, r5, r6, r7, r8, r9, sl, lr} +1003852a: f7d0 b95d b.w 100087e8 + +1003852e : +1003852e: 6cf8 ldr r0, [r7, #76] ; 0x4c +10038530: 9000 str r0, [sp, #0] +10038532: 2344 movs r3, #68 ; 0x44 +10038534: 6b38 ldr r0, [r7, #48] ; 0x30 +10038536: f107 0234 add.w r2, r7, #52 ; 0x34 +1003853a: 4629 mov r1, r5 +1003853c: f7d1 b8c3 b.w 100096c6 + +10038540 : +10038540: b538 push {r3, r4, r5, lr} +10038542: 4c33 ldr r4, [pc, #204] ; (10038610 ) +10038544: 4605 mov r5, r0 +10038546: 6b20 ldr r0, [r4, #48] ; 0x30 +10038548: 64e5 str r5, [r4, #76] ; 0x4c +1003854a: b118 cbz r0, 10038554 +1003854c: f7d1 f998 bl 10009880 +10038550: 2000 movs r0, #0 +10038552: 6320 str r0, [r4, #48] ; 0x30 + +10038554 : +10038554: f7d1 f9ae bl 100098b4 +10038558: 6320 str r0, [r4, #48] ; 0x30 +1003855a: 2204 movs r2, #4 +1003855c: f04f 30ff mov.w r0, #4294967295 +10038560: 6360 str r0, [r4, #52] ; 0x34 +10038562: 1d29 adds r1, r5, #4 +10038564: 1d20 adds r0, r4, #4 +10038566: f7d3 feef bl 1000c348 +1003856a: 2204 movs r2, #4 +1003856c: f105 0108 add.w r1, r5, #8 +10038570: f104 0054 add.w r0, r4, #84 ; 0x54 +10038574: f7d3 fee8 bl 1000c348 +10038578: 2204 movs r2, #4 +1003857a: f105 010c add.w r1, r5, #12 +1003857e: f104 0008 add.w r0, r4, #8 +10038582: f7d3 fee1 bl 1000c348 +10038586: 6868 ldr r0, [r5, #4] +10038588: 68a9 ldr r1, [r5, #8] +1003858a: 4008 ands r0, r1 +1003858c: 61a0 str r0, [r4, #24] +1003858e: 68a9 ldr r1, [r5, #8] +10038590: ea60 0001 orn r0, r0, r1 +10038594: 63a0 str r0, [r4, #56] ; 0x38 +10038596: 6ca0 ldr r0, [r4, #72] ; 0x48 +10038598: b118 cbz r0, 100385a2 +1003859a: f7d2 f917 bl 1000a7cc +1003859e: 2000 movs r0, #0 +100385a0: 64a0 str r0, [r4, #72] ; 0x48 + +100385a2 : +100385a2: 2001 movs r0, #1 +100385a4: f7d1 ffbc bl 1000a520 +100385a8: 64a0 str r0, [r4, #72] ; 0x48 +100385aa: 2210 movs r2, #16 +100385ac: 2100 movs r1, #0 +100385ae: f104 0020 add.w r0, r4, #32 +100385b2: f7d3 fecb bl 1000c34c +100385b6: 2204 movs r2, #4 +100385b8: 2100 movs r1, #0 +100385ba: 4620 mov r0, r4 +100385bc: f7d3 fec6 bl 1000c34c +100385c0: 2210 movs r2, #16 +100385c2: 2100 movs r1, #0 +100385c4: f104 0068 add.w r0, r4, #104 ; 0x68 +100385c8: f7d3 fec0 bl 1000c34c +100385cc: 79e0 ldrb r0, [r4, #7] +100385ce: f7ff fd37 bl 10038040 +100385d2: 7ae0 ldrb r0, [r4, #11] +100385d4: f7ff fd34 bl 10038040 +100385d8: 6b20 ldr r0, [r4, #48] ; 0x30 +100385da: 490e ldr r1, [pc, #56] ; (10038614 ) +100385dc: 2243 movs r2, #67 ; 0x43 +100385de: f7d1 f8e1 bl 100097a4 +100385e2: 6b20 ldr r0, [r4, #48] ; 0x30 +100385e4: 490c ldr r1, [pc, #48] ; (10038618 ) +100385e6: e8bd 4038 ldmia.w sp!, {r3, r4, r5, lr} +100385ea: 2200 movs r2, #0 +100385ec: f7d1 b945 b.w 1000987a + +100385f0 : +100385f0: b510 push {r4, lr} +100385f2: 4c07 ldr r4, [pc, #28] ; (10038610 ) +100385f4: 6b20 ldr r0, [r4, #48] ; 0x30 +100385f6: b118 cbz r0, 10038600 +100385f8: f7d1 f942 bl 10009880 +100385fc: 2000 movs r0, #0 +100385fe: 6320 str r0, [r4, #48] ; 0x30 + +10038600 : +10038600: 6ca0 ldr r0, [r4, #72] ; 0x48 +10038602: b118 cbz r0, 1003860c +10038604: f7d2 f8e2 bl 1000a7cc +10038608: 2000 movs r0, #0 +1003860a: 64a0 str r0, [r4, #72] ; 0x48 + +1003860c : +1003860c: bd10 pop {r4, pc} + ... + +10038610 : +10038610: 3f34 1004 4?.. + +10038614 : +10038614: 4290 1000 .B.. + +10038618 : +10038618: 8413 1003 .... + +1003861c : +1003861c: 0a0d 5220 7165 6575 7473 6920 2070 766f .. Request ip ov +1003862c: 7265 7420 6568 7220 6e61 6567 3128 312d er the range(1-1 +1003863c: 3832 2029 0a0d 0000 28) .... + +10038644 : +10038644: 0a0d 4e20 206f 7375 6165 6c62 2065 7069 .. No useable ip +10038654: 2121 2121 0a0d 0000 !!!!.... + +1003865c : +1003865c: 0d0a 4520 7272 726f 2121 2121 5320 7379 .. Error!!!! Sys +1003866c: 6574 206d 6f64 7365 276e 2074 6c61 6f6c tem doesn't allo +1003867c: 6163 6574 6120 796e 6220 6675 6566 2072 cate any buffer +1003868c: 0d0a 0000 .... + +10038690 : +10038690: 8263 6353 c.Sc + +10038694 : +10038694: 0100 8051 ..Q. + +10038698 : +10038698: 4002 0000 .@.. + +1003869c : +1003869c: b570 push {r4, r5, r6, lr} +1003869e: b086 sub sp, #24 +100386a0: 4604 mov r4, r0 +100386a2: f7fb f8db bl 1003385c +100386a6: b120 cbz r0, 100386b2 +100386a8: 2100 movs r1, #0 +100386aa: 2200 movs r2, #0 +100386ac: 4608 mov r0, r1 +100386ae: f7fb f8b1 bl 10033814 + +100386b2 : +100386b2: b914 cbnz r4, 100386ba +100386b4: f04f 30ff mov.w r0, #4294967295 +100386b8: e028 b.n 1003870c + +100386ba : +100386ba: 6aa1 ldr r1, [r4, #40] ; 0x28 +100386bc: f8df 5ac8 ldr.w r5, [pc, #2760] ; 10039188 +100386c0: 0008 movs r0, r1 +100386c2: d014 beq.n 100386ee +100386c4: 1e48 subs r0, r1, #1 +100386c6: d023 beq.n 10038710 +100386c8: f44f 4200 mov.w r2, #32768 ; 0x8000 +100386cc: 1a80 subs r0, r0, r2 +100386ce: d01f beq.n 10038710 +100386d0: f8df 2ab8 ldr.w r2, [pc, #2744] ; 1003918c +100386d4: 1a80 subs r0, r0, r2 +100386d6: d02a beq.n 1003872e +100386d8: 1e80 subs r0, r0, #2 +100386da: d02f beq.n 1003873c +100386dc: f8df 2b8c ldr.w r2, [pc, #2956] ; 1003926c +100386e0: 1a80 subs r0, r0, r2 +100386e2: d024 beq.n 1003872e +100386e4: 1e80 subs r0, r0, #2 +100386e6: d029 beq.n 1003873c +100386e8: 1e80 subs r0, r0, #2 +100386ea: d027 beq.n 1003873c +100386ec: e039 b.n 10038762 + +100386ee : +100386ee: f000 f8f2 bl 100388d6 + +100386f2 : +100386f2: 4601 mov r1, r0 +100386f4: 4628 mov r0, r5 +100386f6: f7e9 fe16 bl 10022326 + +100386fa : +100386fa: 4606 mov r6, r0 + +100386fc : +100386fc: b92e cbnz r6, 1003870a +100386fe: 7822 ldrb r2, [r4, #0] +10038700: 1c61 adds r1, r4, #1 +10038702: 4628 mov r0, r5 +10038704: f7e9 fda4 bl 10022250 +10038708: 4606 mov r6, r0 + +1003870a : +1003870a: 4630 mov r0, r6 + +1003870c : +1003870c: b006 add sp, #24 +1003870e: bd70 pop {r4, r5, r6, pc} + +10038710 : +10038710: 2202 movs r2, #2 +10038712: f000 f82e bl 10038772 + +10038716 : +10038716: 0006 movs r6, r0 +10038718: d1f0 bne.n 100386fc +1003871a: 6b20 ldr r0, [r4, #48] ; 0x30 +1003871c: b280 uxth r0, r0 +1003871e: 9004 str r0, [sp, #16] +10038720: 2200 movs r2, #0 +10038722: 6ae0 ldr r0, [r4, #44] ; 0x2c +10038724: 9003 str r0, [sp, #12] +10038726: f000 f828 bl 1003877a + +1003872a : +1003872a: 6b63 ldr r3, [r4, #52] ; 0x34 +1003872c: e7e1 b.n 100386f2 + +1003872e : +1003872e: f000 f81f bl 10038770 + +10038732 : +10038732: 0006 movs r6, r0 +10038734: d10c bne.n 10038750 +10038736: f000 f8e1 bl 100388fc + +1003873a : +1003873a: e005 b.n 10038748 + +1003873c : +1003873c: f000 f818 bl 10038770 + +10038740 : +10038740: 0006 movs r6, r0 +10038742: d105 bne.n 10038750 +10038744: f000 f8d0 bl 100388e8 + +10038748 : +10038748: 4628 mov r0, r5 +1003874a: f7e9 fdec bl 10022326 +1003874e: 4606 mov r6, r0 + +10038750 : +10038750: 2e00 cmp r6, #0 +10038752: d1d3 bne.n 100386fc +10038754: 6b22 ldr r2, [r4, #48] ; 0x30 +10038756: 6ae1 ldr r1, [r4, #44] ; 0x2c +10038758: b292 uxth r2, r2 +1003875a: 4628 mov r0, r5 +1003875c: f7e9 fe97 bl 1002248e +10038760: e7cb b.n 100386fa + +10038762 : +10038762: f04f 36ff mov.w r6, #4294967295 +10038766: f20f 1030 addw r0, pc, #304 ; 0x130 +1003876a: f7d3 fdca bl 1000c302 +1003876e: e7cc b.n 1003870a + +10038770 : +10038770: 2201 movs r2, #1 + +10038772 : +10038772: 2106 movs r1, #6 +10038774: 4628 mov r0, r5 +10038776: f7e9 bdba b.w 100222ee + +1003877a : +1003877a: 2000 movs r0, #0 + +1003877c : +1003877c: 9002 str r0, [sp, #8] +1003877e: 9001 str r0, [sp, #4] +10038780: 2001 movs r0, #1 +10038782: 9000 str r0, [sp, #0] +10038784: 4770 bx lr + +10038786 : +10038786: b531 push {r0, r4, r5, lr} +10038788: b088 sub sp, #32 +1003878a: a805 add r0, sp, #20 +1003878c: 2100 movs r1, #0 +1003878e: 2200 movs r2, #0 +10038790: 460b mov r3, r1 +10038792: c00e stmia r0!, {r1, r2, r3} +10038794: f7fb f862 bl 1003385c +10038798: b120 cbz r0, 100387a4 +1003879a: 2100 movs r1, #0 +1003879c: 2200 movs r2, #0 +1003879e: 4608 mov r0, r1 +100387a0: f7fb f838 bl 10033814 + +100387a4 : +100387a4: 9808 ldr r0, [sp, #32] +100387a6: b910 cbnz r0, 100387ae +100387a8: f04f 30ff mov.w r0, #4294967295 +100387ac: e03c b.n 10038828 + +100387ae : +100387ae: 6a81 ldr r1, [r0, #40] ; 0x28 +100387b0: f8df 49d4 ldr.w r4, [pc, #2516] ; 10039188 +100387b4: 0008 movs r0, r1 +100387b6: d014 beq.n 100387e2 +100387b8: 1e48 subs r0, r1, #1 +100387ba: d037 beq.n 1003882c +100387bc: f44f 4200 mov.w r2, #32768 ; 0x8000 +100387c0: 1a80 subs r0, r0, r2 +100387c2: d033 beq.n 1003882c +100387c4: f8df 29c4 ldr.w r2, [pc, #2500] ; 1003918c +100387c8: 1a80 subs r0, r0, r2 +100387ca: d042 beq.n 10038852 +100387cc: 1e80 subs r0, r0, #2 +100387ce: d047 beq.n 10038860 +100387d0: f8df 2a98 ldr.w r2, [pc, #2712] ; 1003926c +100387d4: 1a80 subs r0, r0, r2 +100387d6: d03c beq.n 10038852 +100387d8: 1e80 subs r0, r0, #2 +100387da: d041 beq.n 10038860 +100387dc: 1e80 subs r0, r0, #2 +100387de: d03f beq.n 10038860 +100387e0: e052 b.n 10038888 + +100387e2 : +100387e2: f000 f878 bl 100388d6 + +100387e6 : +100387e6: 4601 mov r1, r0 + +100387e8 : +100387e8: 4620 mov r0, r4 +100387ea: f7e9 fd9c bl 10022326 + +100387ee : +100387ee: 4605 mov r5, r0 + +100387f0 : +100387f0: b9cd cbnz r5, 10038826 +100387f2: 9808 ldr r0, [sp, #32] +100387f4: f100 0122 add.w r1, r0, #34 ; 0x22 +100387f8: 2206 movs r2, #6 +100387fa: a805 add r0, sp, #20 +100387fc: f7d3 fda4 bl 1000c348 +10038800: 9808 ldr r0, [sp, #32] +10038802: 7800 ldrb r0, [r0, #0] +10038804: b150 cbz r0, 1003881c +10038806: 2023 movs r0, #35 ; 0x23 +10038808: f88d 001a strb.w r0, [sp, #26] +1003880c: 2204 movs r2, #4 +1003880e: 2040 movs r0, #64 ; 0x40 +10038810: f88d 001b strb.w r0, [sp, #27] +10038814: a908 add r1, sp, #32 +10038816: a807 add r0, sp, #28 +10038818: f7d3 fd96 bl 1000c348 + +1003881c : +1003881c: a905 add r1, sp, #20 +1003881e: 4620 mov r0, r4 +10038820: f7e9 fd2e bl 10022280 +10038824: 4605 mov r5, r0 + +10038826 : +10038826: 4628 mov r0, r5 + +10038828 : +10038828: b009 add sp, #36 ; 0x24 +1003882a: bd30 pop {r4, r5, pc} + +1003882c : +1003882c: 2202 movs r2, #2 +1003882e: f000 f84e bl 100388ce + +10038832 : +10038832: 0005 movs r5, r0 +10038834: d1dc bne.n 100387f0 +10038836: 9808 ldr r0, [sp, #32] +10038838: 6b00 ldr r0, [r0, #48] ; 0x30 +1003883a: b280 uxth r0, r0 +1003883c: 9004 str r0, [sp, #16] +1003883e: 2200 movs r2, #0 +10038840: 9808 ldr r0, [sp, #32] +10038842: 6ac0 ldr r0, [r0, #44] ; 0x2c +10038844: 9003 str r0, [sp, #12] +10038846: 2101 movs r1, #1 +10038848: f7ff ff97 bl 1003877a + +1003884c : +1003884c: 9808 ldr r0, [sp, #32] +1003884e: 6b43 ldr r3, [r0, #52] ; 0x34 +10038850: e7ca b.n 100387e8 + +10038852 : +10038852: f000 f83b bl 100388cc + +10038856 : +10038856: 0005 movs r5, r0 +10038858: d10c bne.n 10038874 +1003885a: f000 f84f bl 100388fc + +1003885e : +1003885e: e005 b.n 1003886c + +10038860 : +10038860: f000 f834 bl 100388cc + +10038864 : +10038864: 0005 movs r5, r0 +10038866: d105 bne.n 10038874 +10038868: f000 f83e bl 100388e8 + +1003886c : +1003886c: 4620 mov r0, r4 +1003886e: f7e9 fd5a bl 10022326 +10038872: 4605 mov r5, r0 + +10038874 : +10038874: 2d00 cmp r5, #0 +10038876: d1bb bne.n 100387f0 +10038878: 9808 ldr r0, [sp, #32] +1003887a: 6b02 ldr r2, [r0, #48] ; 0x30 +1003887c: 6ac1 ldr r1, [r0, #44] ; 0x2c +1003887e: b292 uxth r2, r2 +10038880: 4620 mov r0, r4 +10038882: f7e9 fe04 bl 1002248e +10038886: e7b2 b.n 100387ee + +10038888 : +10038888: f04f 35ff mov.w r5, #4294967295 +1003888c: f20f 0008 addw r0, pc, #8 +10038890: f7d3 fd37 bl 1000c302 +10038894: e7c7 b.n 10038826 + ... + +10038898 : +10038898: 0d0a 4957 4946 4f43 464e 203a 6573 7563 ..WIFICONF: secu +100388a8: 6972 7974 7420 7079 2865 7830 7825 2029 rity type(0x%x) +100388b8: 7369 6e20 746f 7320 7075 6f70 7472 6465 is not supported +100388c8: 0a2e 000d .... + +100388cc : +100388cc: 2201 movs r2, #1 + +100388ce : +100388ce: 2106 movs r1, #6 +100388d0: 4620 mov r0, r4 +100388d2: f7e9 bd0c b.w 100222ee + +100388d6 : +100388d6: 2000 movs r0, #0 +100388d8: 9004 str r0, [sp, #16] +100388da: 9003 str r0, [sp, #12] +100388dc: 9002 str r0, [sp, #8] +100388de: 9001 str r0, [sp, #4] +100388e0: 9000 str r0, [sp, #0] +100388e2: 2300 movs r3, #0 +100388e4: 4602 mov r2, r0 +100388e6: 4770 bx lr + +100388e8 : +100388e8: 2000 movs r0, #0 +100388ea: 9004 str r0, [sp, #16] +100388ec: 9003 str r0, [sp, #12] +100388ee: 9002 str r0, [sp, #8] +100388f0: 9001 str r0, [sp, #4] +100388f2: 9000 str r0, [sp, #0] +100388f4: 2300 movs r3, #0 +100388f6: 4602 mov r2, r0 +100388f8: 2103 movs r1, #3 +100388fa: 4770 bx lr + +100388fc : +100388fc: 2000 movs r0, #0 +100388fe: 9004 str r0, [sp, #16] +10038900: 9003 str r0, [sp, #12] +10038902: 9002 str r0, [sp, #8] +10038904: 9001 str r0, [sp, #4] +10038906: 9000 str r0, [sp, #0] +10038908: 2300 movs r3, #0 +1003890a: 4602 mov r2, r0 +1003890c: 2102 movs r1, #2 +1003890e: 4770 bx lr + +10038910 : +10038910: f8df 0b38 ldr.w r0, [pc, #2872] ; 1003944c +10038914: 6801 ldr r1, [r0, #0] +10038916: b109 cbz r1, 1003891c +10038918: 2120 movs r1, #32 +1003891a: 6081 str r1, [r0, #8] + +1003891c : +1003891c: 4770 bx lr + +1003891e : +1003891e: f8df 0b2c ldr.w r0, [pc, #2860] ; 1003944c +10038922: 6801 ldr r1, [r0, #0] +10038924: b191 cbz r1, 1003894c +10038926: 6a8a ldr r2, [r1, #40] ; 0x28 +10038928: 2a00 cmp r2, #0 +1003892a: bf18 it ne +1003892c: 2a01 cmpne r2, #1 +1003892e: d107 bne.n 10038940 +10038930: 2200 movs r2, #0 +10038932: 6042 str r2, [r0, #4] +10038934: 221f movs r2, #31 +10038936: 6082 str r2, [r0, #8] +10038938: f101 0038 add.w r0, r1, #56 ; 0x38 +1003893c: f7d7 bfa7 b.w 1001088e + +10038940 : +10038940: f8df 1b0c ldr.w r1, [pc, #2828] ; 10039450 +10038944: 428a cmp r2, r1 +10038946: bf04 itt eq +10038948: 211f moveq r1, #31 +1003894a: 6081 streq r1, [r0, #8] + +1003894c : +1003894c: 4770 bx lr + +1003894e : +1003894e: f8df 0afc ldr.w r0, [pc, #2812] ; 1003944c +10038952: 2100 movs r1, #0 +10038954: 6041 str r1, [r0, #4] +10038956: 219f movs r1, #159 ; 0x9f +10038958: 6081 str r1, [r0, #8] +1003895a: 6800 ldr r0, [r0, #0] +1003895c: 2800 cmp r0, #0 +1003895e: bf1c itt ne +10038960: 3038 addne r0, #56 ; 0x38 +10038962: f7d7 bf94 bne.w 1001088e +10038966: 4770 bx lr + +10038968 : +10038968: b510 push {r4, lr} +1003896a: f8df 4ae0 ldr.w r4, [pc, #2784] ; 1003944c +1003896e: 6820 ldr r0, [r4, #0] +10038970: b348 cbz r0, 100389c6 +10038972: 68a1 ldr r1, [r4, #8] +10038974: 6a80 ldr r0, [r0, #40] ; 0x28 +10038976: b950 cbnz r0, 1003898e +10038978: 2920 cmp r1, #32 +1003897a: d01d beq.n 100389b8 +1003897c: 2004 movs r0, #4 + +1003897e : +1003897e: 6060 str r0, [r4, #4] + +10038980 : +10038980: 6820 ldr r0, [r4, #0] +10038982: e8bd 4010 ldmia.w sp!, {r4, lr} +10038986: 3038 adds r0, #56 ; 0x38 +10038988: f7d7 bf81 b.w 1001088e + +1003898c : +1003898c: bd10 pop {r4, pc} + +1003898e : +1003898e: 2801 cmp r0, #1 +10038990: d10c bne.n 100389ac +10038992: 2920 cmp r1, #32 +10038994: d010 beq.n 100389b8 +10038996: b191 cbz r1, 100389be +10038998: 2004 movs r0, #4 +1003899a: 6060 str r0, [r4, #4] +1003899c: f20f 0034 addw r0, pc, #52 ; 0x34 +100389a0: f7d3 fcaf bl 1000c302 +100389a4: 6820 ldr r0, [r4, #0] +100389a6: 2800 cmp r0, #0 +100389a8: d0f0 beq.n 1003898c +100389aa: e7e9 b.n 10038980 + +100389ac : +100389ac: f8df 2aa0 ldr.w r2, [pc, #2720] ; 10039450 +100389b0: 4290 cmp r0, r2 +100389b2: d1e5 bne.n 10038980 +100389b4: 2920 cmp r1, #32 +100389b6: d101 bne.n 100389bc + +100389b8 : +100389b8: 2001 movs r0, #1 +100389ba: e7e0 b.n 1003897e + +100389bc : +100389bc: b909 cbnz r1, 100389c2 + +100389be : +100389be: 2002 movs r0, #2 +100389c0: e7dd b.n 1003897e + +100389c2 : +100389c2: 2003 movs r0, #3 +100389c4: e7db b.n 1003897e + +100389c6 : +100389c6: 6860 ldr r0, [r4, #4] +100389c8: 2800 cmp r0, #0 +100389ca: d1df bne.n 1003898c +100389cc: 2004 movs r0, #4 +100389ce: 6060 str r0, [r4, #4] +100389d0: bd10 pop {r4, pc} + ... + +100389d4 : +100389d4: 0a0d 4920 204e 4557 2050 4553 5543 4952 .. IN WEP SECURI +100389e4: 5954 4d20 444f 2c45 7277 6e6f 2067 6170 TY MODE,wrong pa +100389f4: 7373 6f77 6472 6920 2073 6874 2065 6173 ssword is the sa +10038a04: 656d 7420 206f 6864 7063 6620 6961 006c me to dhcp fail. + +10038a14 : +10038a14: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +10038a18: b09e sub sp, #120 ; 0x78 +10038a1a: 2000 movs r0, #0 +10038a1c: 9000 str r0, [sp, #0] +10038a1e: a801 add r0, sp, #4 +10038a20: f20f 01ec addw r1, pc, #236 ; 0xec +10038a24: 680a ldr r2, [r1, #0] +10038a26: 6002 str r2, [r0, #0] +10038a28: 2091 movs r0, #145 ; 0x91 +10038a2a: f7d7 feea bl 10010802 +10038a2e: 0004 movs r4, r0 +10038a30: bf1e ittt ne +10038a32: f8df 5a20 ldrne.w r5, [pc, #2592] ; 10039454 +10038a36: 6828 ldrne r0, [r5, #0] +10038a38: 2800 cmpne r0, #0 +10038a3a: d065 beq.n 10038b08 +10038a3c: 9801 ldr r0, [sp, #4] +10038a3e: a902 add r1, sp, #8 +10038a40: f000 fd65 bl 1003950e +10038a44: b910 cbnz r0, 10038a4c +10038a46: 9802 ldr r0, [sp, #8] +10038a48: 2802 cmp r0, #2 +10038a4a: d106 bne.n 10038a5a + +10038a4c : +10038a4c: f20f 01c4 addw r1, pc, #196 ; 0xc4 +10038a50: f20f 00dc addw r0, pc, #220 ; 0xdc +10038a54: f7d3 fc55 bl 1000c302 +10038a58: e056 b.n 10038b08 + +10038a5a : +10038a5a: f89d 002d ldrb.w r0, [sp, #45] ; 0x2d +10038a5e: f8df 89f8 ldr.w r8, [pc, #2552] ; 10039458 +10038a62: 9000 str r0, [sp, #0] +10038a64: 2224 movs r2, #36 ; 0x24 +10038a66: 2100 movs r1, #0 +10038a68: 4640 mov r0, r8 +10038a6a: f7d7 fee5 bl 10010838 +10038a6e: a803 add r0, sp, #12 +10038a70: f7d3 fc72 bl 1000c358 +10038a74: 4602 mov r2, r0 +10038a76: a903 add r1, sp, #12 +10038a78: 4640 mov r0, r8 +10038a7a: f7d3 fc71 bl 1000c360 +10038a7e: 980c ldr r0, [sp, #48] ; 0x30 +10038a80: f8df 69d8 ldr.w r6, [pc, #2520] ; 1003945c +10038a84: f8df 79d8 ldr.w r7, [pc, #2520] ; 10039460 +10038a88: b110 cbz r0, 10038a90 +10038a8a: 2801 cmp r0, #1 +10038a8c: d005 beq.n 10038a9a +10038a8e: e013 b.n 10038ab8 + +10038a90 : +10038a90: f000 f869 bl 10038b66 + +10038a94 : +10038a94: f000 f862 bl 10038b5c + +10038a98 : +10038a98: e00e b.n 10038ab8 + +10038a9a : +10038a9a: 9800 ldr r0, [sp, #0] +10038a9c: f89d 1075 ldrb.w r1, [sp, #117] ; 0x75 +10038aa0: ea40 7001 orr.w r0, r0, r1, lsl #28 +10038aa4: 9000 str r0, [sp, #0] +10038aa6: f000 f85e bl 10038b66 + +10038aaa : +10038aaa: f000 f857 bl 10038b5c + +10038aae : +10038aae: 2241 movs r2, #65 ; 0x41 +10038ab0: a90d add r1, sp, #52 ; 0x34 +10038ab2: 4638 mov r0, r7 +10038ab4: f7d7 feab bl 1001080e + +10038ab8 : +10038ab8: 2224 movs r2, #36 ; 0x24 +10038aba: 4641 mov r1, r8 +10038abc: 4620 mov r0, r4 +10038abe: f7d3 fc43 bl 1000c348 +10038ac2: f8df 8a34 ldr.w r8, [pc, #2612] ; 100394f8 +10038ac6: 4640 mov r0, r8 +10038ac8: f7d3 fc46 bl 1000c358 +10038acc: 2840 cmp r0, #64 ; 0x40 +10038ace: bf07 ittee eq +10038ad0: 2241 moveq r2, #65 ; 0x41 +10038ad2: 4641 moveq r1, r8 +10038ad4: 2241 movne r2, #65 ; 0x41 +10038ad6: 4639 movne r1, r7 +10038ad8: f104 0024 add.w r0, r4, #36 ; 0x24 +10038adc: f7d3 fc34 bl 1000c348 +10038ae0: 2228 movs r2, #40 ; 0x28 +10038ae2: 4631 mov r1, r6 +10038ae4: f104 0065 add.w r0, r4, #101 ; 0x65 +10038ae8: f7d3 fc2e bl 1000c348 +10038aec: 2204 movs r2, #4 +10038aee: a900 add r1, sp, #0 +10038af0: f104 008d add.w r0, r4, #141 ; 0x8d +10038af4: f7d3 fc28 bl 1000c348 +10038af8: 682a ldr r2, [r5, #0] +10038afa: 2191 movs r1, #145 ; 0x91 +10038afc: 4620 mov r0, r4 +10038afe: 4790 blx r2 +10038b00: 2100 movs r1, #0 +10038b02: 4620 mov r0, r4 +10038b04: f7d7 fe82 bl 1001080c + +10038b08 : +10038b08: b01e add sp, #120 ; 0x78 +10038b0a: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + ... + +10038b10 : +10038b10: 9824 1003 $... + +10038b14 : +10038b14: 6572 7473 726f 5f65 6977 6966 695f 666e restore_wifi_inf +10038b24: 5f6f 6f74 665f 616c 6873 0000 o_to_flash.. + +10038b30 : +10038b30: 0a0d 2520 2873 3a29 6977 6966 675f 7465 .. %s():wifi_get +10038b40: 735f 7465 6974 676e 6620 6961 206c 726f _setting fail or +10038b50: 6120 2070 6f6d 6564 0000 0000 ap mode.... + +10038b5c : +10038b5c: 2228 movs r2, #40 ; 0x28 +10038b5e: 2100 movs r1, #0 +10038b60: 4630 mov r0, r6 +10038b62: f7d7 be69 b.w 10010838 + +10038b66 : +10038b66: 2241 movs r2, #65 ; 0x41 +10038b68: 2100 movs r1, #0 +10038b6a: 4638 mov r0, r7 +10038b6c: f7d7 be64 b.w 10010838 + +10038b70 : +10038b70: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +10038b74: b09d sub sp, #116 ; 0x74 +10038b76: 4604 mov r4, r0 +10038b78: 460d mov r5, r1 +10038b7a: f04f 0800 mov.w r8, #0 +10038b7e: 4693 mov fp, r2 +10038b80: 461f mov r7, r3 +10038b82: 46c1 mov r9, r8 +10038b84: a819 add r0, sp, #100 ; 0x64 +10038b86: 2110 movs r1, #16 +10038b88: f7ec fe48 bl 1002581c <__aeabi_memclr4> +10038b8c: f8df a8bc ldr.w sl, [pc, #2236] ; 1003944c +10038b90: f8ca 8008 str.w r8, [sl, #8] +10038b94: f8ca 8004 str.w r8, [sl, #4] +10038b98: 203c movs r0, #60 ; 0x3c +10038b9a: f7d7 fe32 bl 10010802 +10038b9e: 0006 movs r6, r0 +10038ba0: d07c beq.n 10038c9c +10038ba2: 2f21 cmp r7, #33 ; 0x21 +10038ba4: bfac ite ge +10038ba6: 2020 movge r0, #32 +10038ba8: 4638 movlt r0, r7 +10038baa: 7030 strb r0, [r6, #0] +10038bac: 463a mov r2, r7 +10038bae: 4621 mov r1, r4 +10038bb0: 1c70 adds r0, r6, #1 +10038bb2: f7d7 fe2c bl 1001080e +10038bb6: 9c26 ldr r4, [sp, #152] ; 0x98 +10038bb8: f1a4 0008 sub.w r0, r4, #8 +10038bbc: 2839 cmp r0, #57 ; 0x39 +10038bbe: d312 bcc.n 10038be6 +10038bc0: f8df 09f4 ldr.w r0, [pc, #2548] ; 100395b8 +10038bc4: 4285 cmp r5, r0 +10038bc6: bf1c itt ne +10038bc8: f8df 09f0 ldrne.w r0, [pc, #2544] ; 100395bc +10038bcc: 4285 cmpne r5, r0 +10038bce: d019 beq.n 10038c04 +10038bd0: f8df 087c ldr.w r0, [pc, #2172] ; 10039450 +10038bd4: 4285 cmp r5, r0 +10038bd6: bf1f itttt ne +10038bd8: f8df 09e4 ldrne.w r0, [pc, #2532] ; 100395c0 +10038bdc: 4285 cmpne r5, r0 +10038bde: f8df 09e4 ldrne.w r0, [pc, #2532] ; 100395c4 +10038be2: 4285 cmpne r5, r0 +10038be4: d00e beq.n 10038c04 + +10038be6 : +10038be6: 2d01 cmp r5, #1 +10038be8: bf1c itt ne +10038bea: f248 0001 movwne r0, #32769 ; 0x8001 +10038bee: 4285 cmpne r5, r0 +10038bf0: d14d bne.n 10038c8e +10038bf2: 2c05 cmp r4, #5 +10038bf4: bf18 it ne +10038bf6: 2c0d cmpne r4, #13 +10038bf8: d049 beq.n 10038c8e +10038bfa: af19 add r7, sp, #100 ; 0x64 +10038bfc: 2c0a cmp r4, #10 +10038bfe: d003 beq.n 10038c08 +10038c00: 2c1a cmp r4, #26 +10038c02: d01a beq.n 10038c3a + +10038c04 : +10038c04: 2004 movs r0, #4 +10038c06: e0b7 b.n 10038d78 + +10038c08 : +10038c08: a807 add r0, sp, #28 +10038c0a: 9002 str r0, [sp, #8] +10038c0c: ab04 add r3, sp, #16 +10038c0e: a806 add r0, sp, #24 +10038c10: 9001 str r0, [sp, #4] +10038c12: aa03 add r2, sp, #12 +10038c14: a805 add r0, sp, #20 +10038c16: 9000 str r0, [sp, #0] +10038c18: 4658 mov r0, fp +10038c1a: f20f 1164 addw r1, pc, #356 ; 0x164 +10038c1e: f7eb fff3 bl 10024c08 +10038c22: 2000 movs r0, #0 + +10038c24 : +10038c24: a903 add r1, sp, #12 +10038c26: f851 1020 ldr.w r1, [r1, r0, lsl #2] +10038c2a: 55c1 strb r1, [r0, r7] +10038c2c: 1c40 adds r0, r0, #1 +10038c2e: 2805 cmp r0, #5 +10038c30: dbf8 blt.n 10038c24 +10038c32: f887 8005 strb.w r8, [r7, #5] +10038c36: 2405 movs r4, #5 +10038c38: e027 b.n 10038c8a + +10038c3a : +10038c3a: a818 add r0, sp, #96 ; 0x60 +10038c3c: 900a str r0, [sp, #40] ; 0x28 +10038c3e: ab0d add r3, sp, #52 ; 0x34 +10038c40: a817 add r0, sp, #92 ; 0x5c +10038c42: 9009 str r0, [sp, #36] ; 0x24 +10038c44: aa0c add r2, sp, #48 ; 0x30 +10038c46: a816 add r0, sp, #88 ; 0x58 +10038c48: 9008 str r0, [sp, #32] +10038c4a: a815 add r0, sp, #84 ; 0x54 +10038c4c: 9007 str r0, [sp, #28] +10038c4e: a814 add r0, sp, #80 ; 0x50 +10038c50: 9006 str r0, [sp, #24] +10038c52: a813 add r0, sp, #76 ; 0x4c +10038c54: 9005 str r0, [sp, #20] +10038c56: a812 add r0, sp, #72 ; 0x48 +10038c58: 9004 str r0, [sp, #16] +10038c5a: a811 add r0, sp, #68 ; 0x44 +10038c5c: 9003 str r0, [sp, #12] +10038c5e: a810 add r0, sp, #64 ; 0x40 +10038c60: 9002 str r0, [sp, #8] +10038c62: a80f add r0, sp, #60 ; 0x3c +10038c64: 9001 str r0, [sp, #4] +10038c66: a80e add r0, sp, #56 ; 0x38 +10038c68: 9000 str r0, [sp, #0] +10038c6a: 4658 mov r0, fp +10038c6c: f20f 1128 addw r1, pc, #296 ; 0x128 +10038c70: f7eb ffca bl 10024c08 +10038c74: 2000 movs r0, #0 + +10038c76 : +10038c76: a90c add r1, sp, #48 ; 0x30 +10038c78: f851 1020 ldr.w r1, [r1, r0, lsl #2] +10038c7c: 55c1 strb r1, [r0, r7] +10038c7e: 1c40 adds r0, r0, #1 +10038c80: 280d cmp r0, #13 +10038c82: dbf8 blt.n 10038c76 +10038c84: f887 800d strb.w r8, [r7, #13] +10038c88: 240d movs r4, #13 + +10038c8a : +10038c8a: f04f 0901 mov.w r9, #1 + +10038c8e : +10038c8e: 6334 str r4, [r6, #48] ; 0x30 +10038c90: b194 cbz r4, 10038cb8 +10038c92: 1c60 adds r0, r4, #1 +10038c94: f7d7 fdb5 bl 10010802 +10038c98: 62f0 str r0, [r6, #44] ; 0x2c +10038c9a: b910 cbnz r0, 10038ca2 + +10038c9c : +10038c9c: f06f 001a mvn.w r0, #26 +10038ca0: e06a b.n 10038d78 + +10038ca2 : +10038ca2: f1b9 0f00 cmp.w r9, #0 +10038ca6: 4622 mov r2, r4 +10038ca8: d103 bne.n 10038cb2 +10038caa: 4659 mov r1, fp +10038cac: f7d7 fdaf bl 1001080e +10038cb0: e002 b.n 10038cb8 + +10038cb2 : +10038cb2: a919 add r1, sp, #100 ; 0x64 +10038cb4: f7d7 fdab bl 1001080e + +10038cb8 : +10038cb8: 62b5 str r5, [r6, #40] ; 0x28 +10038cba: 9827 ldr r0, [sp, #156] ; 0x9c +10038cbc: 6370 str r0, [r6, #52] ; 0x34 +10038cbe: 9d28 ldr r5, [sp, #160] ; 0xa0 +10038cc0: b945 cbnz r5, 10038cd4 +10038cc2: f000 f95c bl 10038f7e + +10038cc6 : +10038cc6: 6bb0 ldr r0, [r6, #56] ; 0x38 +10038cc8: b910 cbnz r0, 10038cd0 +10038cca: f06f 0015 mvn.w r0, #21 +10038cce: e053 b.n 10038d78 + +10038cd0 : +10038cd0: 900b str r0, [sp, #44] ; 0x2c +10038cd2: e000 b.n 10038cd6 + +10038cd4 : +10038cd4: 63b5 str r5, [r6, #56] ; 0x38 + +10038cd6 : +10038cd6: f8df ba04 ldr.w fp, [pc, #2564] ; 100396dc +10038cda: 2200 movs r2, #0 +10038cdc: 4659 mov r1, fp +10038cde: 200c movs r0, #12 +10038ce0: f7f7 f8b1 bl 1002fe46 +10038ce4: f8df 79f8 ldr.w r7, [pc, #2552] ; 100396e0 +10038ce8: 4642 mov r2, r8 +10038cea: 4639 mov r1, r7 +10038cec: 4610 mov r0, r2 +10038cee: f7f7 f8aa bl 1002fe46 +10038cf2: 4642 mov r2, r8 +10038cf4: f000 f938 bl 10038f68 + +10038cf8 : +10038cf8: f8df 99e8 ldr.w r9, [pc, #2536] ; 100396e4 +10038cfc: 4642 mov r2, r8 +10038cfe: 4649 mov r1, r9 +10038d00: 2002 movs r0, #2 +10038d02: f7f7 f8a0 bl 1002fe46 +10038d06: 4630 mov r0, r6 +10038d08: f7ff fcc8 bl 1003869c +10038d0c: f8ca 6000 str.w r6, [sl] +10038d10: bb0d cbnz r5, 10038d56 +10038d12: f000 f92e bl 10038f72 + +10038d16 : +10038d16: b970 cbnz r0, 10038d36 +10038d18: f20f 2030 addw r0, pc, #560 ; 0x230 +10038d1c: f7d3 faf1 bl 1000c302 +10038d20: b10c cbz r4, 10038d26 +10038d22: f000 f855 bl 10038dd0 + +10038d26 : +10038d26: f000 f92f bl 10038f88 + +10038d2a : +10038d2a: a80b add r0, sp, #44 ; 0x2c +10038d2c: f7d7 fda8 bl 10010880 +10038d30: f04f 0802 mov.w r8, #2 +10038d34: e011 b.n 10038d5a + +10038d36 : +10038d36: a80b add r0, sp, #44 ; 0x2c +10038d38: f7d7 fda2 bl 10010880 +10038d3c: 6b30 ldr r0, [r6, #48] ; 0x30 +10038d3e: b108 cbz r0, 10038d44 +10038d40: f000 f846 bl 10038dd0 + +10038d44 : +10038d44: f000 f920 bl 10038f88 + +10038d48 : +10038d48: 4640 mov r0, r8 +10038d4a: f000 f942 bl 10038fd2 +10038d4e: b110 cbz r0, 10038d56 +10038d50: f04f 38ff mov.w r8, #4294967295 +10038d54: e001 b.n 10038d5a + +10038d56 : +10038d56: f7ff fe5d bl 10038a14 + +10038d5a : +10038d5a: 2000 movs r0, #0 +10038d5c: f8ca 0000 str.w r0, [sl] +10038d60: 4639 mov r1, r7 +10038d62: f7f7 f886 bl 1002fe72 +10038d66: 4659 mov r1, fp +10038d68: 200c movs r0, #12 +10038d6a: f7f7 f882 bl 1002fe72 +10038d6e: 4649 mov r1, r9 +10038d70: 2002 movs r0, #2 +10038d72: f7f7 f87e bl 1002fe72 +10038d76: 4640 mov r0, r8 + +10038d78 : +10038d78: b01d add sp, #116 ; 0x74 +10038d7a: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + ... + +10038d80 : +10038d80: 3025 7832 3025 7832 3025 7832 3025 7832 %02x%02x%02x%02x +10038d90: 3025 7832 0000 0000 %02x.... + +10038d98 : +10038d98: 3025 7832 3025 7832 3025 7832 3025 7832 %02x%02x%02x%02x +10038da8: 3025 7832 3025 7832 3025 7832 3025 7832 %02x%02x%02x%02x +10038db8: 3025 7832 3025 7832 3025 7832 3025 7832 %02x%02x%02x%02x +10038dc8: 3025 7832 0000 0000 %02x.... + +10038dd0 : +10038dd0: 6af0 ldr r0, [r6, #44] ; 0x2c + +10038dd2 : +10038dd2: 2100 movs r1, #0 +10038dd4: f7d7 bd1a b.w 1001080c + +10038dd8 : +10038dd8: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +10038ddc: f8df 866c ldr.w r8, [pc, #1644] ; 1003944c +10038de0: 4607 mov r7, r0 +10038de2: 2400 movs r4, #0 +10038de4: 468a mov sl, r1 +10038de6: 4615 mov r5, r2 +10038de8: 4699 mov r9, r3 +10038dea: f8c8 4008 str.w r4, [r8, #8] +10038dee: f8c8 4004 str.w r4, [r8, #4] +10038df2: 203c movs r0, #60 ; 0x3c +10038df4: f7d7 fd05 bl 10010802 +10038df8: 0006 movs r6, r0 +10038dfa: d03f beq.n 10038e7c +10038dfc: 9a0b ldr r2, [sp, #44] ; 0x2c +10038dfe: 2a00 cmp r2, #0 +10038e00: bf18 it ne +10038e02: f1ba 0f00 cmpne.w sl, #0 +10038e06: d008 beq.n 10038e1a +10038e08: 2a21 cmp r2, #33 ; 0x21 +10038e0a: bfac ite ge +10038e0c: 2020 movge r0, #32 +10038e0e: 4610 movlt r0, r2 +10038e10: 7030 strb r0, [r6, #0] +10038e12: 4651 mov r1, sl +10038e14: 1c70 adds r0, r6, #1 +10038e16: f7d7 fcfa bl 1001080e + +10038e1a : +10038e1a: 9a0a ldr r2, [sp, #40] ; 0x28 +10038e1c: 4639 mov r1, r7 +10038e1e: f106 0022 add.w r0, r6, #34 ; 0x22 +10038e22: f7d7 fcf4 bl 1001080e +10038e26: 9f0c ldr r7, [sp, #48] ; 0x30 +10038e28: f1a7 0008 sub.w r0, r7, #8 +10038e2c: 2839 cmp r0, #57 ; 0x39 +10038e2e: d312 bcc.n 10038e56 +10038e30: f8df 0784 ldr.w r0, [pc, #1924] ; 100395b8 +10038e34: 4285 cmp r5, r0 +10038e36: bf1c itt ne +10038e38: f8df 0780 ldrne.w r0, [pc, #1920] ; 100395bc +10038e3c: 4285 cmpne r5, r0 +10038e3e: d014 beq.n 10038e6a +10038e40: f8df 060c ldr.w r0, [pc, #1548] ; 10039450 +10038e44: 4285 cmp r5, r0 +10038e46: bf1f itttt ne +10038e48: f8df 0774 ldrne.w r0, [pc, #1908] ; 100395c0 +10038e4c: 4285 cmpne r5, r0 +10038e4e: f8df 0774 ldrne.w r0, [pc, #1908] ; 100395c4 +10038e52: 4285 cmpne r5, r0 +10038e54: d009 beq.n 10038e6a + +10038e56 : +10038e56: 2f05 cmp r7, #5 +10038e58: bf18 it ne +10038e5a: 2f0d cmpne r7, #13 +10038e5c: d007 beq.n 10038e6e +10038e5e: 2d01 cmp r5, #1 +10038e60: bf1c itt ne +10038e62: f248 0001 movwne r0, #32769 ; 0x8001 +10038e66: 4285 cmpne r5, r0 +10038e68: d101 bne.n 10038e6e + +10038e6a : +10038e6a: 2004 movs r0, #4 +10038e6c: e06c b.n 10038f48 + +10038e6e : +10038e6e: 6337 str r7, [r6, #48] ; 0x30 +10038e70: b15f cbz r7, 10038e8a +10038e72: 1c78 adds r0, r7, #1 +10038e74: f7d7 fcc5 bl 10010802 +10038e78: 62f0 str r0, [r6, #44] ; 0x2c +10038e7a: b910 cbnz r0, 10038e82 + +10038e7c : +10038e7c: f06f 001a mvn.w r0, #26 +10038e80: e062 b.n 10038f48 + +10038e82 : +10038e82: 463a mov r2, r7 +10038e84: 4649 mov r1, r9 +10038e86: f7d7 fcc2 bl 1001080e + +10038e8a : +10038e8a: 62b5 str r5, [r6, #40] ; 0x28 +10038e8c: 980d ldr r0, [sp, #52] ; 0x34 +10038e8e: 6370 str r0, [r6, #52] ; 0x34 +10038e90: 9d0e ldr r5, [sp, #56] ; 0x38 +10038e92: b945 cbnz r5, 10038ea6 +10038e94: f000 f873 bl 10038f7e + +10038e98 : +10038e98: 6bb0 ldr r0, [r6, #56] ; 0x38 +10038e9a: b910 cbnz r0, 10038ea2 +10038e9c: f06f 0015 mvn.w r0, #21 +10038ea0: e052 b.n 10038f48 + +10038ea2 : +10038ea2: 9000 str r0, [sp, #0] +10038ea4: e000 b.n 10038ea8 + +10038ea6 : +10038ea6: 63b5 str r5, [r6, #56] ; 0x38 + +10038ea8 : +10038ea8: f8df 9830 ldr.w r9, [pc, #2096] ; 100396dc +10038eac: 2200 movs r2, #0 +10038eae: 4649 mov r1, r9 +10038eb0: 200c movs r0, #12 +10038eb2: f7f6 ffc8 bl 1002fe46 +10038eb6: f8df a828 ldr.w sl, [pc, #2088] ; 100396e0 +10038eba: 4622 mov r2, r4 +10038ebc: 4651 mov r1, sl +10038ebe: 4610 mov r0, r2 +10038ec0: f7f6 ffc1 bl 1002fe46 +10038ec4: 4622 mov r2, r4 +10038ec6: f000 f84f bl 10038f68 + +10038eca : +10038eca: f8df b818 ldr.w fp, [pc, #2072] ; 100396e4 +10038ece: 4622 mov r2, r4 +10038ed0: 4659 mov r1, fp +10038ed2: 2002 movs r0, #2 +10038ed4: f7f6 ffb7 bl 1002fe46 +10038ed8: 4630 mov r0, r6 +10038eda: f7ff fc54 bl 10038786 +10038ede: f8c8 6000 str.w r6, [r8] +10038ee2: bb05 cbnz r5, 10038f26 +10038ee4: f000 f845 bl 10038f72 + +10038ee8 : +10038ee8: b968 cbnz r0, 10038f06 +10038eea: f20f 0060 addw r0, pc, #96 ; 0x60 +10038eee: f7d3 fa08 bl 1000c302 +10038ef2: b10f cbz r7, 10038ef8 +10038ef4: f7ff ff6c bl 10038dd0 + +10038ef8 : +10038ef8: f000 f846 bl 10038f88 + +10038efc : +10038efc: a800 add r0, sp, #0 +10038efe: f7d7 fcbf bl 10010880 +10038f02: 2402 movs r4, #2 +10038f04: e011 b.n 10038f2a + +10038f06 : +10038f06: a800 add r0, sp, #0 +10038f08: f7d7 fcba bl 10010880 +10038f0c: 6b30 ldr r0, [r6, #48] ; 0x30 +10038f0e: b108 cbz r0, 10038f14 +10038f10: f7ff ff5e bl 10038dd0 + +10038f14 : +10038f14: f000 f838 bl 10038f88 + +10038f18 : +10038f18: 4620 mov r0, r4 +10038f1a: f000 f85a bl 10038fd2 +10038f1e: b110 cbz r0, 10038f26 +10038f20: f04f 34ff mov.w r4, #4294967295 +10038f24: e001 b.n 10038f2a + +10038f26 : +10038f26: f7ff fd75 bl 10038a14 + +10038f2a : +10038f2a: 2000 movs r0, #0 +10038f2c: f8c8 0000 str.w r0, [r8] +10038f30: 4651 mov r1, sl +10038f32: f7f6 ff9e bl 1002fe72 +10038f36: 4649 mov r1, r9 +10038f38: 200c movs r0, #12 +10038f3a: f7f6 ff9a bl 1002fe72 +10038f3e: 4659 mov r1, fp +10038f40: 2002 movs r0, #2 +10038f42: f7f6 ff96 bl 1002fe72 +10038f46: 4620 mov r0, r4 + +10038f48 : +10038f48: e8bd 8ff2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +10038f4c : +10038f4c: 5452 2057 5041 3a49 4a20 696f 206e 7362 RTW API: Join bs +10038f5c: 2073 6974 656d 756f 0d74 000a s timeout... + +10038f68 : +10038f68: f8df 1878 ldr.w r1, [pc, #2168] ; 100397e4 +10038f6c: 2001 movs r0, #1 +10038f6e: f7f6 bf6a b.w 1002fe46 + +10038f72 : +10038f72: f643 2198 movw r1, #15000 ; 0x3a98 +10038f76: f106 0038 add.w r0, r6, #56 ; 0x38 +10038f7a: f7d7 bc8f b.w 1001089c + +10038f7e : +10038f7e: 2100 movs r1, #0 +10038f80: f106 0038 add.w r0, r6, #56 ; 0x38 +10038f84: f7d7 bc75 b.w 10010872 + +10038f88 : +10038f88: 2100 movs r1, #0 +10038f8a: 4630 mov r0, r6 +10038f8c: f7d7 bc3e b.w 1001080c + +10038f90 : +10038f90: b51c push {r2, r3, r4, lr} +10038f92: f60f 0198 addw r1, pc, #2200 ; 0x898 +10038f96: c90c ldmia r1!, {r2, r3} +10038f98: a800 add r0, sp, #0 +10038f9a: 2400 movs r4, #0 +10038f9c: c00c stmia r0!, {r2, r3} +10038f9e: a900 add r1, sp, #0 +10038fa0: f60f 0080 addw r0, pc, #2176 ; 0x880 +10038fa4: f7e9 f96c bl 10022280 +10038fa8: 2800 cmp r0, #0 +10038faa: d505 bpl.n 10038fb8 +10038fac: f60f 0084 addw r0, pc, #2180 ; 0x884 +10038fb0: f7d3 f9a7 bl 1000c302 +10038fb4: f04f 34ff mov.w r4, #4294967295 + +10038fb8 : +10038fb8: 4620 mov r0, r4 +10038fba: bd16 pop {r1, r2, r4, pc} + +10038fbc : +10038fbc: 2801 cmp r0, #1 +10038fbe: bf02 ittt eq +10038fc0: f8df 0824 ldreq.w r0, [pc, #2084] ; 100397e8 +10038fc4: 6800 ldreq r0, [r0, #0] +10038fc6: 2803 cmpeq r0, #3 +10038fc8: bf0c ite eq +10038fca: 2001 moveq r0, #1 +10038fcc: 2000 movne r0, #0 +10038fce: f7d6 bff6 b.w 1000ffbe + +10038fd2 : +10038fd2: b580 push {r7, lr} +10038fd4: b130 cbz r0, 10038fe4 +10038fd6: 2801 cmp r0, #1 +10038fd8: d129 bne.n 1003902e +10038fda: f7ff ffef bl 10038fbc +10038fde: 2801 cmp r0, #1 +10038fe0: d125 bne.n 1003902e +10038fe2: e01b b.n 1003901c + +10038fe4 : +10038fe4: f8df 0464 ldr.w r0, [pc, #1124] ; 1003944c +10038fe8: 6881 ldr r1, [r0, #8] +10038fea: b1c9 cbz r1, 10039020 +10038fec: 2906 cmp r1, #6 +10038fee: d01c beq.n 1003902a +10038ff0: 2908 cmp r1, #8 +10038ff2: d015 beq.n 10039020 +10038ff4: 290e cmp r1, #14 +10038ff6: d015 beq.n 10039024 +10038ff8: 2916 cmp r1, #22 +10038ffa: d016 beq.n 1003902a +10038ffc: 291f cmp r1, #31 +10038ffe: d007 beq.n 10039010 +10039000: 2920 cmp r1, #32 +10039002: d002 beq.n 1003900a +10039004: 299f cmp r1, #159 ; 0x9f +10039006: d009 beq.n 1003901c +10039008: e011 b.n 1003902e + +1003900a : +1003900a: f06f 001d mvn.w r0, #29 +1003900e: bd02 pop {r1, pc} + +10039010 : +10039010: 6800 ldr r0, [r0, #0] +10039012: f8df 17d8 ldr.w r1, [pc, #2008] ; 100397ec +10039016: 6a80 ldr r0, [r0, #40] ; 0x28 +10039018: 4288 cmp r0, r1 +1003901a: d008 beq.n 1003902e + +1003901c : +1003901c: 2000 movs r0, #0 +1003901e: bd02 pop {r1, pc} + +10039020 : +10039020: 2006 movs r0, #6 +10039022: bd02 pop {r1, pc} + +10039024 : +10039024: f06f 0028 mvn.w r0, #40 ; 0x28 +10039028: bd02 pop {r1, pc} + +1003902a : +1003902a: 2007 movs r0, #7 +1003902c: bd02 pop {r1, pc} + +1003902e : +1003902e: e01f b.n 10039070 + +10039030 : +10039030: b530 push {r4, r5, lr} +10039032: f000 f86d bl 10039110 + +10039036 : +10039036: f20f 75ec addw r5, pc, #2028 ; 0x7ec +1003903a: 6800 ldr r0, [r0, #0] +1003903c: b087 sub sp, #28 +1003903e: 2803 cmp r0, #3 +10039040: bf08 it eq +10039042: f60f 0520 addweq r5, pc, #2080 ; 0x820 +10039046: 2219 movs r2, #25 +10039048: f000 f80e bl 10039068 + +1003904c : +1003904c: 4623 mov r3, r4 +1003904e: f60f 021c addw r2, pc, #2076 ; 0x81c +10039052: 2119 movs r1, #25 +10039054: a800 add r0, sp, #0 +10039056: f7d3 f8eb bl 1000c230 +1003905a: 2200 movs r2, #0 +1003905c: a900 add r1, sp, #0 +1003905e: 4628 mov r0, r5 +10039060: f7e9 fb65 bl 1002272e +10039064: b007 add sp, #28 +10039066: bd30 pop {r4, r5, pc} + +10039068 : +10039068: 2100 movs r1, #0 +1003906a: a800 add r0, sp, #0 +1003906c: f7d7 bbe4 b.w 10010838 + +10039070 : +10039070: f04f 30ff mov.w r0, #4294967295 +10039074: bd02 pop {r1, pc} + +10039076 : +10039076: 4601 mov r1, r0 +10039078: f20f 70a8 addw r0, pc, #1960 ; 0x7a8 +1003907c: f7e9 ba91 b.w 100225a2 + +10039080 : +10039080: b2c1 uxtb r1, r0 +10039082: f20f 70a0 addw r0, pc, #1952 ; 0x7a0 +10039086: f7e9 baf0 b.w 1002266a + +1003908a : +1003908a: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1003908e: f000 f83f bl 10039110 + +10039092 : +10039092: f04f 0801 mov.w r8, #1 +10039096: 2614 movs r6, #20 +10039098: 2701 movs r7, #1 +1003909a: 6004 str r4, [r0, #0] +1003909c: f7f6 ff01 bl 1002fea2 +100390a0: 2c03 cmp r4, #3 +100390a2: bf08 it eq +100390a4: 2702 moveq r7, #2 +100390a6: 2000 movs r0, #0 +100390a8: f7d6 ff89 bl 1000ffbe +100390ac: b110 cbz r0, 100390b4 +100390ae: f20f 70d0 addw r0, pc, #2000 ; 0x7d0 +100390b2: e01e b.n 100390f2 + +100390b4 : +100390b4: f20f 70e4 addw r0, pc, #2020 ; 0x7e4 +100390b8: f7d3 f923 bl 1000c302 +100390bc: 2500 movs r5, #0 +100390be: e007 b.n 100390d0 + +100390c0 : +100390c0: 4621 mov r1, r4 +100390c2: 4628 mov r0, r5 +100390c4: f7d6 fde2 bl 1000fc8c +100390c8: ea5f 0800 movs.w r8, r0 +100390cc: d413 bmi.n 100390f6 +100390ce: 1c6d adds r5, r5, #1 + +100390d0 : +100390d0: 42bd cmp r5, r7 +100390d2: dbf5 blt.n 100390c0 +100390d4: 2500 movs r5, #0 +100390d6: e003 b.n 100390e0 + +100390d8 : +100390d8: 4628 mov r0, r5 +100390da: f7d6 fe81 bl 1000fde0 +100390de: 1c6d adds r5, r5, #1 + +100390e0 : +100390e0: 42bd cmp r5, r7 +100390e2: dbf9 blt.n 100390d8 + +100390e4 : +100390e4: 1e78 subs r0, r7, #1 +100390e6: b2c0 uxtb r0, r0 +100390e8: f7d6 ff69 bl 1000ffbe +100390ec: b130 cbz r0, 100390fc +100390ee: f20f 70c4 addw r0, pc, #1988 ; 0x7c4 + +100390f2 : +100390f2: f7d3 f906 bl 1000c302 + +100390f6 : +100390f6: 4640 mov r0, r8 +100390f8: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +100390fc : +100390fc: b916 cbnz r6, 10039104 +100390fe: f20f 70c8 addw r0, pc, #1992 ; 0x7c8 +10039102: e7f6 b.n 100390f2 + +10039104 : +10039104: f44f 707a mov.w r0, #1000 ; 0x3e8 +10039108: f7d1 fce3 bl 1000aad2 +1003910c: 1e76 subs r6, r6, #1 +1003910e: e7e9 b.n 100390e4 + +10039110 : +10039110: 4604 mov r4, r0 +10039112: f8df 06d4 ldr.w r0, [pc, #1748] ; 100397e8 +10039116: 4770 bx lr + +10039118 : +10039118: b510 push {r4, lr} +1003911a: 2414 movs r4, #20 +1003911c: 2000 movs r0, #0 +1003911e: f7d6 ff4e bl 1000ffbe +10039122: b930 cbnz r0, 10039132 +10039124: 2001 movs r0, #1 +10039126: f7d6 ff4a bl 1000ffbe +1003912a: b910 cbnz r0, 10039132 +1003912c: f20f 70b4 addw r0, pc, #1972 ; 0x7b4 +10039130: e298 b.n 10039664 + +10039132 : +10039132: f7ff fa5d bl 100385f0 +10039136: 2104 movs r1, #4 +10039138: 2000 movs r0, #0 +1003913a: f000 fd68 bl 10039c0e +1003913e: f20f 70bc addw r0, pc, #1980 ; 0x7bc +10039142: f7d3 f8de bl 1000c302 +10039146: f7d6 fde5 bl 1000fd14 +1003914a: e004 b.n 10039156 + +1003914c : +1003914c: f44f 707a mov.w r0, #1000 ; 0x3e8 +10039150: f7d1 fcbf bl 1000aad2 +10039154: 1e64 subs r4, r4, #1 + +10039156 : +10039156: 2000 movs r0, #0 +10039158: f7d6 ff31 bl 1000ffbe +1003915c: b930 cbnz r0, 1003916c +1003915e: 2001 movs r0, #1 +10039160: f7d6 ff2d bl 1000ffbe +10039164: b910 cbnz r0, 1003916c +10039166: f20f 70b0 addw r0, pc, #1968 ; 0x7b0 +1003916a: e003 b.n 10039174 + +1003916c : +1003916c: 2c00 cmp r4, #0 +1003916e: d1ed bne.n 1003914c +10039170: f20f 70bc addw r0, pc, #1980 ; 0x7bc + +10039174 : +10039174: f7d3 f8c5 bl 1000c302 +10039178: f8df 166c ldr.w r1, [pc, #1644] ; 100397e8 +1003917c: 2000 movs r0, #0 +1003917e: 6008 str r0, [r1, #0] +10039180: bd10 pop {r4, pc} + +10039182 : +10039182: 4770 bx lr + +10039184 : +10039184: 4770 bx lr + ... + +10039188 : +10039188: 9824 1003 $... + +1003918c : +1003918c: 8001 001f .... + +10039190 : +10039190: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} +10039194: f7ff ffbc bl 10039110 + +10039198 : +10039198: f20f 6988 addw r9, pc, #1672 ; 0x688 +1003919c: 6800 ldr r0, [r0, #0] +1003919e: b085 sub sp, #20 +100391a0: 460d mov r5, r1 +100391a2: 4690 mov r8, r2 +100391a4: 461e mov r6, r3 +100391a6: 2803 cmp r0, #3 +100391a8: bf08 it eq +100391aa: f20f 69b8 addweq r9, pc, #1720 ; 0x6b8 +100391ae: f7fa fb55 bl 1003385c +100391b2: b120 cbz r0, 100391be +100391b4: 2100 movs r1, #0 +100391b6: 2200 movs r2, #0 +100391b8: 4608 mov r0, r1 +100391ba: f7fa fb2b bl 10033814 + +100391be : +100391be: 2200 movs r2, #0 +100391c0: f8df 162c ldr.w r1, [pc, #1580] ; 100397f0 +100391c4: 2008 movs r0, #8 +100391c6: f7f6 fe3e bl 1002fe46 +100391ca: 2200 movs r2, #0 +100391cc: f8df 1624 ldr.w r1, [pc, #1572] ; 100397f4 +100391d0: 2009 movs r0, #9 +100391d2: f7f6 fe38 bl 1002fe46 +100391d6: 2103 movs r1, #3 +100391d8: 4648 mov r0, r9 +100391da: f7e9 f9a0 bl 1002251e +100391de: 4607 mov r7, r0 +100391e0: 2f00 cmp r7, #0 +100391e2: d439 bmi.n 10039258 +100391e4: 990d ldr r1, [sp, #52] ; 0x34 +100391e6: b2c9 uxtb r1, r1 +100391e8: 4648 mov r0, r9 +100391ea: f7e9 fa3e bl 1002266a +100391ee: 4607 mov r7, r0 +100391f0: 2f00 cmp r7, #0 +100391f2: d431 bmi.n 10039258 +100391f4: f04f 30ff mov.w r0, #4294967295 +100391f8: b335 cbz r5, 10039248 +100391fa: f8df 15f0 ldr.w r1, [pc, #1520] ; 100397ec +100391fe: 428d cmp r5, r1 +10039200: d12e bne.n 10039260 +10039202: 9d0c ldr r5, [sp, #48] ; 0x30 +10039204: f1a5 0108 sub.w r1, r5, #8 +10039208: 2939 cmp r1, #57 ; 0x39 +1003920a: d303 bcc.n 10039214 +1003920c: 4607 mov r7, r0 +1003920e: f20f 7040 addw r0, pc, #1856 ; 0x740 +10039212: e028 b.n 10039266 + +10039214 : +10039214: 2201 movs r2, #1 +10039216: 2106 movs r1, #6 +10039218: 4648 mov r0, r9 +1003921a: f7e9 f868 bl 100222ee +1003921e: 0007 movs r7, r0 +10039220: d10b bne.n 1003923a +10039222: 9004 str r0, [sp, #16] +10039224: 9003 str r0, [sp, #12] +10039226: 9002 str r0, [sp, #8] +10039228: 9001 str r0, [sp, #4] +1003922a: 9000 str r0, [sp, #0] +1003922c: 2300 movs r3, #0 +1003922e: 2200 movs r2, #0 +10039230: 2103 movs r1, #3 +10039232: 4648 mov r0, r9 +10039234: f7e9 f877 bl 10022326 +10039238: 4607 mov r7, r0 + +1003923a : +1003923a: b92f cbnz r7, 10039248 +1003923c: b2aa uxth r2, r5 +1003923e: 4641 mov r1, r8 +10039240: 4648 mov r0, r9 +10039242: f7e9 f924 bl 1002248e +10039246: 4607 mov r7, r0 + +10039248 : +10039248: 2f00 cmp r7, #0 +1003924a: d405 bmi.n 10039258 +1003924c: b2b2 uxth r2, r6 +1003924e: 4621 mov r1, r4 +10039250: 4648 mov r0, r9 +10039252: f7e9 f98e bl 10022572 +10039256: 4607 mov r7, r0 + +10039258 : +10039258: 4638 mov r0, r7 +1003925a: b005 add sp, #20 +1003925c: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + +10039260 : +10039260: 4607 mov r7, r0 +10039262: f20f 701c addw r0, pc, #1820 ; 0x71c + +10039266 : +10039266: f7d3 f84c bl 1000c302 +1003926a: e7f5 b.n 10039258 + +1003926c : +1003926c: fffe 001f .... + +10039270 : +10039270: b5f8 push {r3, r4, r5, r6, r7, lr} +10039272: f8df 5584 ldr.w r5, [pc, #1412] ; 100397f8 +10039276: 68aa ldr r2, [r5, #8] +10039278: 4604 mov r4, r0 +1003927a: 2100 movs r1, #0 +1003927c: 2600 movs r6, #0 +1003927e: e000 b.n 10039282 + +10039280 : +10039280: 1c49 adds r1, r1, #1 + +10039282 : +10039282: 4291 cmp r1, r2 +10039284: da2e bge.n 100392e4 +10039286: 6868 ldr r0, [r5, #4] +10039288: eb00 1381 add.w r3, r0, r1, lsl #6 +1003928c: 6820 ldr r0, [r4, #0] +1003928e: f893 7022 ldrb.w r7, [r3, #34] ; 0x22 +10039292: f890 c022 ldrb.w ip, [r0, #34] ; 0x22 +10039296: 4567 cmp r7, ip +10039298: d1f2 bne.n 10039280 +1003929a: 3322 adds r3, #34 ; 0x22 +1003929c: f100 0722 add.w r7, r0, #34 ; 0x22 +100392a0: f893 c001 ldrb.w ip, [r3, #1] +100392a4: f897 e001 ldrb.w lr, [r7, #1] +100392a8: 45f4 cmp ip, lr +100392aa: bf02 ittt eq +100392ac: f893 c002 ldrbeq.w ip, [r3, #2] +100392b0: f897 e002 ldrbeq.w lr, [r7, #2] +100392b4: 45f4 cmpeq ip, lr +100392b6: d1e3 bne.n 10039280 +100392b8: f893 c003 ldrb.w ip, [r3, #3] +100392bc: f897 e003 ldrb.w lr, [r7, #3] +100392c0: 45f4 cmp ip, lr +100392c2: bf02 ittt eq +100392c4: f893 c004 ldrbeq.w ip, [r3, #4] +100392c8: f897 e004 ldrbeq.w lr, [r7, #4] +100392cc: 45f4 cmpeq ip, lr +100392ce: bf02 ittt eq +100392d0: 795b ldrbeq r3, [r3, #5] +100392d2: 797f ldrbeq r7, [r7, #5] +100392d4: 42bb cmpeq r3, r7 +100392d6: d1d3 bne.n 10039280 +100392d8: e8bd 40f8 ldmia.w sp!, {r3, r4, r5, r6, r7, lr} +100392dc: 2240 movs r2, #64 ; 0x40 +100392de: 2100 movs r1, #0 +100392e0: f7d3 b834 b.w 1000c34c + +100392e4 : +100392e4: 1c53 adds r3, r2, #1 +100392e6: 60ab str r3, [r5, #8] +100392e8: 7c29 ldrb r1, [r5, #16] +100392ea: 6820 ldr r0, [r4, #0] +100392ec: 4299 cmp r1, r3 +100392ee: da19 bge.n 10039324 +100392f0: 60a9 str r1, [r5, #8] +100392f2: 682a ldr r2, [r5, #0] +100392f4: eb02 0181 add.w r1, r2, r1, lsl #2 +100392f8: f100 0222 add.w r2, r0, #34 ; 0x22 +100392fc: f851 3c04 ldr.w r3, [r1, #-4] +10039300: f9b2 2006 ldrsh.w r2, [r2, #6] +10039304: f9b3 1028 ldrsh.w r1, [r3, #40] ; 0x28 +10039308: 4291 cmp r1, r2 +1003930a: da40 bge.n 1003938e +1003930c: 4601 mov r1, r0 +1003930e: 2240 movs r2, #64 ; 0x40 +10039310: 4618 mov r0, r3 +10039312: f7d7 fa7c bl 1001080e +10039316: 6828 ldr r0, [r5, #0] +10039318: 7c29 ldrb r1, [r5, #16] +1003931a: eb00 0081 add.w r0, r0, r1, lsl #2 +1003931e: f850 6c04 ldr.w r6, [r0, #-4] +10039322: e007 b.n 10039334 + +10039324 : +10039324: 4601 mov r1, r0 +10039326: 6868 ldr r0, [r5, #4] +10039328: eb00 1083 add.w r0, r0, r3, lsl #6 +1003932c: 2240 movs r2, #64 ; 0x40 +1003932e: 3840 subs r0, #64 ; 0x40 +10039330: f7d7 fa6d bl 1001080e + +10039334 : +10039334: 68a8 ldr r0, [r5, #8] +10039336: 2200 movs r2, #0 +10039338: 1e41 subs r1, r0, #1 +1003933a: e000 b.n 1003933e + +1003933c : +1003933c: 1c52 adds r2, r2, #1 + +1003933e : +1003933e: 428a cmp r2, r1 +10039340: da09 bge.n 10039356 +10039342: 682b ldr r3, [r5, #0] +10039344: 6827 ldr r7, [r4, #0] +10039346: f853 3022 ldr.w r3, [r3, r2, lsl #2] +1003934a: f9b7 7028 ldrsh.w r7, [r7, #40] ; 0x28 +1003934e: f9b3 3028 ldrsh.w r3, [r3, #40] ; 0x28 +10039352: 42bb cmp r3, r7 +10039354: daf2 bge.n 1003933c + +10039356 : +10039356: 682b ldr r3, [r5, #0] +10039358: e006 b.n 10039368 + +1003935a : +1003935a: eb03 0781 add.w r7, r3, r1, lsl #2 +1003935e: f857 7c04 ldr.w r7, [r7, #-4] +10039362: f843 7021 str.w r7, [r3, r1, lsl #2] +10039366: 1e49 subs r1, r1, #1 + +10039368 : +10039368: 428a cmp r2, r1 +1003936a: dbf6 blt.n 1003935a +1003936c: b116 cbz r6, 10039374 +1003936e: f843 6022 str.w r6, [r3, r2, lsl #2] +10039372: e005 b.n 10039380 + +10039374 : +10039374: 6869 ldr r1, [r5, #4] +10039376: eb01 1080 add.w r0, r1, r0, lsl #6 +1003937a: 3840 subs r0, #64 ; 0x40 +1003937c: f843 0022 str.w r0, [r3, r2, lsl #2] + +10039380 : +10039380: 2240 movs r2, #64 ; 0x40 +10039382: 6820 ldr r0, [r4, #0] +10039384: e8bd 40f8 ldmia.w sp!, {r3, r4, r5, r6, r7, lr} +10039388: 2100 movs r1, #0 +1003938a: f7d7 ba55 b.w 10010838 + +1003938e : +1003938e: bdf1 pop {r0, r4, r5, r6, r7, pc} + +10039390 : +10039390: b530 push {r4, r5, lr} +10039392: b093 sub sp, #76 ; 0x4c +10039394: 2500 movs r5, #0 +10039396: f8df 4460 ldr.w r4, [pc, #1120] ; 100397f8 +1003939a: e00e b.n 100393ba + +1003939c : +1003939c: 6820 ldr r0, [r4, #0] +1003939e: f850 1025 ldr.w r1, [r0, r5, lsl #2] +100393a2: 2240 movs r2, #64 ; 0x40 +100393a4: a800 add r0, sp, #0 +100393a6: f7d7 fa32 bl 1001080e +100393aa: 68e0 ldr r0, [r4, #12] +100393ac: 6961 ldr r1, [r4, #20] +100393ae: 9010 str r0, [sp, #64] ; 0x40 +100393b0: 69e0 ldr r0, [r4, #28] +100393b2: 9011 str r0, [sp, #68] ; 0x44 +100393b4: a800 add r0, sp, #0 +100393b6: 4788 blx r1 +100393b8: 1c6d adds r5, r5, #1 + +100393ba : +100393ba: 68a0 ldr r0, [r4, #8] +100393bc: 4285 cmp r5, r0 +100393be: dbed blt.n 1003939c +100393c0: 6961 ldr r1, [r4, #20] +100393c2: 2001 movs r0, #1 +100393c4: 60e0 str r0, [r4, #12] +100393c6: 9010 str r0, [sp, #64] ; 0x40 +100393c8: a800 add r0, sp, #0 +100393ca: 4788 blx r1 +100393cc: 6860 ldr r0, [r4, #4] +100393ce: f7ff fd00 bl 10038dd2 + +100393d2 : +100393d2: 6820 ldr r0, [r4, #0] +100393d4: f7ff fcfd bl 10038dd2 + +100393d8 : +100393d8: 2000 movs r0, #0 +100393da: 61a0 str r0, [r4, #24] +100393dc: 2003 movs r0, #3 +100393de: f8df 141c ldr.w r1, [pc, #1052] ; 100397fc +100393e2: f7f6 fd46 bl 1002fe72 +100393e6: f8df 1418 ldr.w r1, [pc, #1048] ; 10039800 +100393ea: 2004 movs r0, #4 +100393ec: f7f6 fd41 bl 1002fe72 +100393f0: b013 add sp, #76 ; 0x4c +100393f2: bd30 pop {r4, r5, pc} + +100393f4 : +100393f4: b570 push {r4, r5, r6, lr} +100393f6: 0014 movs r4, r2 +100393f8: ea40 2501 orr.w r5, r0, r1, lsl #8 +100393fc: f20f 4624 addw r6, pc, #1060 ; 0x424 +10039400: d010 beq.n 10039424 +10039402: 6862 ldr r2, [r4, #4] +10039404: 6821 ldr r1, [r4, #0] +10039406: b2ab uxth r3, r5 +10039408: b292 uxth r2, r2 +1003940a: 4630 mov r0, r6 +1003940c: f7e9 f95a bl 100226c4 +10039410: b938 cbnz r0, 10039422 +10039412: 6862 ldr r2, [r4, #4] +10039414: 6821 ldr r1, [r4, #0] +10039416: 4630 mov r0, r6 +10039418: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +1003941c: b292 uxth r2, r2 +1003941e: f7e9 b969 b.w 100226f4 + +10039422 : +10039422: bd70 pop {r4, r5, r6, pc} + +10039424 : +10039424: f8df 13d4 ldr.w r1, [pc, #980] ; 100397fc +10039428: 2003 movs r0, #3 +1003942a: f7f6 fd0c bl 1002fe46 +1003942e: 2200 movs r2, #0 +10039430: f8df 13cc ldr.w r1, [pc, #972] ; 10039800 +10039434: 2004 movs r0, #4 +10039436: f7f6 fd06 bl 1002fe46 +1003943a: b2ab uxth r3, r5 +1003943c: 4630 mov r0, r6 +1003943e: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +10039442: 2200 movs r2, #0 +10039444: 2100 movs r1, #0 +10039446: f7e9 b93d b.w 100226c4 + ... + +1003944c : +1003944c: 7f14 1004 .... + +10039450 : +10039450: 0004 0040 ..@. + +10039454 : +10039454: 73a0 1004 .s.. + +10039458 : +10039458: 817c 1004 |... + +1003945c : +1003945c: 8248 1004 H... + +10039460 : +10039460: 81c4 1004 .... + +10039464 : +10039464: b5f8 push {r3, r4, r5, r6, r7, lr} +10039466: f8df 5390 ldr.w r5, [pc, #912] ; 100397f8 +1003946a: 4606 mov r6, r0 +1003946c: 69a8 ldr r0, [r5, #24] +1003946e: 460c mov r4, r1 +10039470: b190 cbz r0, 10039498 +10039472: 2764 movs r7, #100 ; 0x64 + +10039474 : +10039474: 2014 movs r0, #20 +10039476: f7d7 faba bl 100109ee +1003947a: 69a8 ldr r0, [r5, #24] +1003947c: 1e7f subs r7, r7, #1 +1003947e: b108 cbz r0, 10039484 +10039480: 2f01 cmp r7, #1 +10039482: daf7 bge.n 10039474 + +10039484 : +10039484: b947 cbnz r7, 10039498 +10039486: f7d7 fa82 bl 1001098e +1003948a: 4601 mov r1, r0 +1003948c: f20f 501c addw r0, pc, #1308 ; 0x51c +10039490: f7d2 ff37 bl 1000c302 +10039494: 2002 movs r0, #2 +10039496: bdf2 pop {r1, r4, r5, r6, r7, pc} + +10039498 : +10039498: f7d7 fa79 bl 1001098e +1003949c: 6228 str r0, [r5, #32] +1003949e: 616e str r6, [r5, #20] +100394a0: 2001 movs r0, #1 +100394a2: 61a8 str r0, [r5, #24] +100394a4: 2040 movs r0, #64 ; 0x40 +100394a6: 7428 strb r0, [r5, #16] +100394a8: f44f 5080 mov.w r0, #4096 ; 0x1000 +100394ac: f7d7 f9a9 bl 10010802 +100394b0: 6068 str r0, [r5, #4] +100394b2: b1c0 cbz r0, 100394e6 +100394b4: f44f 5280 mov.w r2, #4096 ; 0x1000 +100394b8: 2100 movs r1, #0 +100394ba: f7d7 f9bd bl 10010838 +100394be: f44f 7080 mov.w r0, #256 ; 0x100 +100394c2: f7d7 f99e bl 10010802 +100394c6: 6028 str r0, [r5, #0] +100394c8: b190 cbz r0, 100394f0 +100394ca: 2240 movs r2, #64 ; 0x40 +100394cc: 2100 movs r1, #0 +100394ce: f7d7 f9b3 bl 10010838 +100394d2: 2000 movs r0, #0 +100394d4: 60a8 str r0, [r5, #8] +100394d6: 60e8 str r0, [r5, #12] +100394d8: 61ec str r4, [r5, #28] +100394da: 2200 movs r2, #0 +100394dc: 2102 movs r1, #2 +100394de: 2010 movs r0, #16 +100394e0: f7ff ff88 bl 100393f4 +100394e4: b130 cbz r0, 100394f4 + +100394e6 : +100394e6: 6828 ldr r0, [r5, #0] +100394e8: f7ff fc73 bl 10038dd2 + +100394ec : +100394ec: 2000 movs r0, #0 +100394ee: 6028 str r0, [r5, #0] + +100394f0 : +100394f0: f04f 30ff mov.w r0, #4294967295 + +100394f4 : +100394f4: bdf2 pop {r1, r4, r5, r6, r7, pc} + ... + +100394f8 : +100394f8: 8298 1004 .... + +100394fc : +100394fc: b130 cbz r0, 1003950c +100394fe: 4613 mov r3, r2 +10039500: 460a mov r2, r1 +10039502: 4601 mov r1, r0 +10039504: f20f 301c addw r0, pc, #796 ; 0x31c +10039508: f7e9 b86e b.w 100225e8 + +1003950c : +1003950c: e0ae b.n 1003966c + +1003950e : +1003950e: b5f0 push {r4, r5, r6, r7, lr} +10039510: b083 sub sp, #12 +10039512: 4604 mov r4, r0 +10039514: 460d mov r5, r1 +10039516: 2600 movs r6, #0 +10039518: 9601 str r6, [sp, #4] +1003951a: f8ad 6000 strh.w r6, [sp] +1003951e: 2270 movs r2, #112 ; 0x70 +10039520: 2100 movs r1, #0 +10039522: 4628 mov r0, r5 +10039524: f7d2 ff12 bl 1000c34c +10039528: f04f 37ff mov.w r7, #4294967295 +1003952c: a901 add r1, sp, #4 +1003952e: 4620 mov r0, r4 +10039530: f7e9 f80a bl 10022548 +10039534: 2800 cmp r0, #0 +10039536: bf48 it mi +10039538: 463e movmi r6, r7 +1003953a: 9801 ldr r0, [sp, #4] +1003953c: 2803 cmp r0, #3 +1003953e: bf0c ite eq +10039540: 2002 moveq r0, #2 +10039542: 2001 movne r0, #1 +10039544: 6028 str r0, [r5, #0] +10039546: 1d29 adds r1, r5, #4 +10039548: 4620 mov r0, r4 +1003954a: f7e8 fe5b bl 10022204 +1003954e: 2800 cmp r0, #0 +10039550: bf48 it mi +10039552: 463e movmi r6, r7 +10039554: f105 0125 add.w r1, r5, #37 ; 0x25 +10039558: 4620 mov r0, r4 +1003955a: f7e9 f89d bl 10022698 +1003955e: 2800 cmp r0, #0 +10039560: bf48 it mi +10039562: 463e movmi r6, r7 +10039564: f105 032c add.w r3, r5, #44 ; 0x2c +10039568: f105 026d add.w r2, r5, #109 ; 0x6d +1003956c: a900 add r1, sp, #0 +1003956e: 4620 mov r0, r4 +10039570: f7e8 ff57 bl 10022422 +10039574: 2800 cmp r0, #0 +10039576: bf48 it mi +10039578: 463e movmi r6, r7 +1003957a: f8bd 0000 ldrh.w r0, [sp] +1003957e: b150 cbz r0, 10039596 +10039580: 2802 cmp r0, #2 +10039582: d005 beq.n 10039590 +10039584: d302 bcc.n 1003958c +10039586: 2803 cmp r0, #3 +10039588: d004 beq.n 10039594 +1003958a: e005 b.n 10039598 + +1003958c : +1003958c: 2001 movs r0, #1 +1003958e: e002 b.n 10039596 + +10039590 : +10039590: 4809 ldr r0, [pc, #36] ; (100395b8 ) +10039592: e000 b.n 10039596 + +10039594 : +10039594: 4895 ldr r0, [pc, #596] ; (100397ec ) + +10039596 : +10039596: 62a8 str r0, [r5, #40] ; 0x28 + +10039598 : +10039598: f8bd 0000 ldrh.w r0, [sp] +1003959c: 2802 cmp r0, #2 +1003959e: bf18 it ne +100395a0: 2803 cmpne r0, #3 +100395a2: d107 bne.n 100395b4 +100395a4: f105 012c add.w r1, r5, #44 ; 0x2c +100395a8: 4620 mov r0, r4 +100395aa: f7e8 ff98 bl 100224de +100395ae: 2800 cmp r0, #0 +100395b0: bf48 it mi +100395b2: 463e movmi r6, r7 + +100395b4 : +100395b4: 4630 mov r0, r6 +100395b6: bdfe pop {r1, r2, r3, r4, r5, r6, r7, pc} + +100395b8 : +100395b8: 0002 0020 .. . + +100395bc : +100395bc: 0004 0020 .. . + +100395c0 : +100395c0: 0002 0040 ..@. + +100395c4 : +100395c4: 0006 0040 ..@. + +100395c8 : +100395c8: b510 push {r4, lr} +100395ca: 460c mov r4, r1 +100395cc: 4601 mov r1, r0 +100395ce: f20f 400c addw r0, pc, #1036 ; 0x40c +100395d2: f7d2 fe96 bl 1000c302 +100395d6: f20f 401c addw r0, pc, #1052 ; 0x41c +100395da: f7d2 fe92 bl 1000c302 +100395de: 6820 ldr r0, [r4, #0] +100395e0: 2801 cmp r0, #1 +100395e2: d006 beq.n 100395f2 +100395e4: 2802 cmp r0, #2 +100395e6: bf0c ite eq +100395e8: f20f 402c addweq r0, pc, #1068 ; 0x42c +100395ec: f20f 4054 addwne r0, pc, #1108 ; 0x454 +100395f0: e001 b.n 100395f6 + +100395f2 : +100395f2: f20f 4038 addw r0, pc, #1080 ; 0x438 + +100395f6 : +100395f6: f7d2 fe84 bl 1000c302 +100395fa: 1d21 adds r1, r4, #4 +100395fc: f20f 405c addw r0, pc, #1116 ; 0x45c +10039600: f7d2 fe7f bl 1000c302 +10039604: f894 1025 ldrb.w r1, [r4, #37] ; 0x25 +10039608: f20f 4064 addw r0, pc, #1124 ; 0x464 +1003960c: f7d2 fe79 bl 1000c302 +10039610: 6aa0 ldr r0, [r4, #40] ; 0x28 +10039612: b140 cbz r0, 10039626 +10039614: 2801 cmp r0, #1 +10039616: d009 beq.n 1003962c +10039618: 497a ldr r1, [pc, #488] ; (10039804 ) +1003961a: 4288 cmp r0, r1 +1003961c: d011 beq.n 10039642 +1003961e: 4973 ldr r1, [pc, #460] ; (100397ec ) +10039620: 4288 cmp r0, r1 +10039622: d011 beq.n 10039648 +10039624: e013 b.n 1003964e + +10039626 : +10039626: f20f 405c addw r0, pc, #1116 ; 0x45c +1003962a: e012 b.n 10039652 + +1003962c : +1003962c: f20f 406c addw r0, pc, #1132 ; 0x46c +10039630: f7d2 fe67 bl 1000c302 +10039634: f894 106d ldrb.w r1, [r4, #109] ; 0x6d +10039638: f20f 4074 addw r0, pc, #1140 ; 0x474 +1003963c: f7d2 fe61 bl 1000c302 +10039640: e009 b.n 10039656 + +10039642 : +10039642: f20f 4080 addw r0, pc, #1152 ; 0x480 +10039646: e004 b.n 10039652 + +10039648 : +10039648: f20f 4090 addw r0, pc, #1168 ; 0x490 +1003964c: e001 b.n 10039652 + +1003964e : +1003964e: f20f 40a0 addw r0, pc, #1184 ; 0x4a0 + +10039652 : +10039652: f7d2 fe56 bl 1000c302 + +10039656 : +10039656: f20f 40b0 addw r0, pc, #1200 ; 0x4b0 +1003965a: f104 012c add.w r1, r4, #44 ; 0x2c +1003965e: f7d2 fe50 bl 1000c302 +10039662: a05f add r0, pc, #380 ; (adr r0, 100397e0 ) + +10039664 : +10039664: f7d2 fe4d bl 1000c302 +10039668: 2000 movs r0, #0 +1003966a: bd10 pop {r4, pc} + +1003966c : +1003966c: f04f 30ff mov.w r0, #4294967295 +10039670: 4770 bx lr + +10039672 : +10039672: f7d6 bd14 b.w 1001009e + +10039676 : +10039676: f7fa b8cd b.w 10033814 + +1003967a : +1003967a: b510 push {r4, lr} +1003967c: b08a sub sp, #40 ; 0x28 +1003967e: 2000 movs r0, #0 +10039680: 9000 str r0, [sp, #0] +10039682: 4859 ldr r0, [pc, #356] ; (100397e8 ) +10039684: 6800 ldr r0, [r0, #0] +10039686: 2803 cmp r0, #3 +10039688: d107 bne.n 1003969a +1003968a: f7ff fd45 bl 10039118 +1003968e: f000 f8a3 bl 100397d8 + +10039692 : +10039692: 2004 movs r0, #4 +10039694: f7ff fcf9 bl 1003908a +10039698: e01e b.n 100396d8 + +1003969a : +1003969a: f20f 1488 addw r4, pc, #392 ; 0x188 +1003969e: a900 add r1, sp, #0 +100396a0: 4620 mov r0, r4 +100396a2: f7e8 ff51 bl 10022548 +100396a6: 9800 ldr r0, [sp, #0] +100396a8: 2802 cmp r0, #2 +100396aa: d00d beq.n 100396c8 +100396ac: 2803 cmp r0, #3 +100396ae: d113 bne.n 100396d8 +100396b0: f7d6 fb30 bl 1000fd14 +100396b4: f000 f890 bl 100397d8 + +100396b8 : +100396b8: 2104 movs r1, #4 +100396ba: 2000 movs r0, #0 +100396bc: f7d6 fae6 bl 1000fc8c +100396c0: 2000 movs r0, #0 +100396c2: f7d6 fb8d bl 1000fde0 +100396c6: e007 b.n 100396d8 + +100396c8 : +100396c8: a901 add r1, sp, #4 +100396ca: 4620 mov r0, r4 +100396cc: f7e8 fd9a bl 10022204 +100396d0: 2801 cmp r0, #1 +100396d2: bfa8 it ge +100396d4: f7ff fc5c blge 10038f90 + +100396d8 : +100396d8: b00a add sp, #40 ; 0x28 +100396da: bd10 pop {r4, pc} + +100396dc : +100396dc: 8911 1003 .... + +100396e0 : +100396e0: 891f 1003 .... + +100396e4 : +100396e4: 894f 1003 O... + +100396e8 : +100396e8: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +100396ec: 4604 mov r4, r0 +100396ee: b0a2 sub sp, #136 ; 0x88 +100396f0: 460d mov r5, r1 +100396f2: 4690 mov r8, r2 +100396f4: 469a mov sl, r3 +100396f6: 2600 movs r6, #0 +100396f8: 2700 movs r7, #0 +100396fa: 2001 movs r0, #1 +100396fc: f7d6 fc5f bl 1000ffbe +10039700: b100 cbz r0, 10039704 +10039702: 2601 movs r6, #1 + +10039704 : +10039704: f7fe ff74 bl 100385f0 +10039708: f8df 90fc ldr.w r9, [pc, #252] ; 10039808 +1003970c: b15e cbz r6, 10039726 +1003970e: a906 add r1, sp, #24 +10039710: f20f 1010 addw r0, pc, #272 ; 0x110 +10039714: f7ff fefb bl 1003950e +10039718: 4607 mov r7, r0 +1003971a: f7ff fcfd bl 10039118 +1003971e: f000 f85b bl 100397d8 + +10039722 : +10039722: 2003 movs r0, #3 +10039724: e010 b.n 10039748 + +10039726 : +10039726: 4839 ldr r0, [pc, #228] ; (1003980c ) +10039728: 9005 str r0, [sp, #20] +1003972a: f06f 417f mvn.w r1, #4278190080 ; 0xff000000 +1003972e: 9104 str r1, [sp, #16] +10039730: 9003 str r0, [sp, #12] +10039732: ab03 add r3, sp, #12 +10039734: aa04 add r2, sp, #16 +10039736: a905 add r1, sp, #20 +10039738: 4648 mov r0, r9 +1003973a: f7d5 fc74 bl 1000f026 +1003973e: f7ff fceb bl 10039118 +10039742: f000 f849 bl 100397d8 + +10039746 : +10039746: 2002 movs r0, #2 + +10039748 : +10039748: f7ff fc9f bl 1003908a +1003974c: 982b ldr r0, [sp, #172] ; 0xac +1003974e: 9001 str r0, [sp, #4] +10039750: 4653 mov r3, sl +10039752: 982a ldr r0, [sp, #168] ; 0xa8 +10039754: 9000 str r0, [sp, #0] +10039756: 4642 mov r2, r8 +10039758: 4629 mov r1, r5 +1003975a: 4620 mov r0, r4 +1003975c: f7ff fd18 bl 10039190 +10039760: 2800 cmp r0, #0 +10039762: d506 bpl.n 10039772 +10039764: f20f 30b4 addw r0, pc, #948 ; 0x3b4 +10039768: f7d2 fdcb bl 1000c302 +1003976c: f04f 30ff mov.w r0, #4294967295 +10039770: e02f b.n 100397d2 + +10039772 : +10039772: b346 cbz r6, 100397c6 +10039774: bb3f cbnz r7, 100397c6 +10039776: a907 add r1, sp, #28 +10039778: f20f 30bc addw r0, pc, #956 ; 0x3bc +1003977c: f7d2 fdc1 bl 1000c302 +10039780: 9910 ldr r1, [sp, #64] ; 0x40 +10039782: f20f 30c4 addw r0, pc, #964 ; 0x3c4 +10039786: f7d2 fdbc bl 1000c302 +1003978a: f20f 30d4 addw r0, pc, #980 ; 0x3d4 +1003978e: a911 add r1, sp, #68 ; 0x44 +10039790: f7d2 fdb7 bl 1000c302 +10039794: f89d 1085 ldrb.w r1, [sp, #133] ; 0x85 +10039798: f20f 30d8 addw r0, pc, #984 ; 0x3d8 +1003979c: f7d2 fdb1 bl 1000c302 +100397a0: a811 add r0, sp, #68 ; 0x44 +100397a2: f7d2 fdd9 bl 1000c358 +100397a6: 4604 mov r4, r0 +100397a8: a807 add r0, sp, #28 +100397aa: f7d2 fdd5 bl 1000c358 +100397ae: 2100 movs r1, #0 +100397b0: 9102 str r1, [sp, #8] +100397b2: 4603 mov r3, r0 +100397b4: f89d 1085 ldrb.w r1, [sp, #133] ; 0x85 +100397b8: 9101 str r1, [sp, #4] +100397ba: 9400 str r4, [sp, #0] +100397bc: aa11 add r2, sp, #68 ; 0x44 +100397be: 9910 ldr r1, [sp, #64] ; 0x40 +100397c0: a807 add r0, sp, #28 +100397c2: f7ff f9d5 bl 10038b70 + +100397c6 : +100397c6: 2038 movs r0, #56 ; 0x38 +100397c8: fb00 9006 mla r0, r0, r6, r9 +100397cc: f7fe feb8 bl 10038540 +100397d0: 2000 movs r0, #0 + +100397d2 : +100397d2: b022 add sp, #136 ; 0x88 +100397d4: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + +100397d8 : +100397d8: 2014 movs r0, #20 +100397da: f7d1 b97a b.w 1000aad2 + ... + +100397e0 : +100397e0: 0d0a 0000 .... + +100397e4 : +100397e4: 8969 1003 i... + +100397e8 : +100397e8: 7f20 1004 ... + +100397ec : +100397ec: 0004 0040 ..@. + +100397f0 : +100397f0: 9183 1003 .... + +100397f4 : +100397f4: 9185 1003 .... + +100397f8 : +100397f8: 7ef0 1004 .~.. + +100397fc : +100397fc: 9271 1003 q... + +10039800 : +10039800: 9391 1003 .... + +10039804 : +10039804: 0002 0020 .. . + +10039808 : +10039808: 7824 1004 $x.. + +1003980c : +1003980c: a8c0 0101 .... + +10039810 : +10039810: f000 bc04 b.w 1003a01c + +10039814 : +10039814: f000 bc17 b.w 1003a046 + +10039818 : +10039818: f000 bc44 b.w 1003a0a4 + +1003981c : +1003981c: f000 bc5a b.w 1003a0d4 + +10039820 : +10039820: f000 bc76 b.w 1003a110 + +10039824 : +10039824: 6c77 6e61 0030 0000 wlan0... + +1003982c : +1003982c: 0000 0000 0100 0000 ........ + +10039834 : +10039834: 0d0a 4557 5458 203a 6146 6c69 6465 7420 ..WEXT: Failed t +10039844: 206f 6573 2074 6f62 7567 2073 5342 4953 o set bogus BSSI +10039854: 2044 6f74 6420 7369 6f63 6e6e 6365 0074 D to disconnect. + +10039864 : +10039864: 6c77 6e61 0031 0000 wlan1... + +1003986c : +1003986c: 6567 5f74 6c63 6569 746e 6c5f 7369 2074 get_client_list +1003987c: 7825 0000 %x.. + +10039880 : +10039880: 0d0a 4957 4946 6920 2073 6c61 6572 6461 ..WIFI is alread +10039890: 2079 7572 6e6e 6e69 0067 0000 y running... + +1003989c : +1003989c: 0d0a 6e49 7469 6169 696c 697a 676e 5720 ..Initializing W +100398ac: 4649 2049 2e2e 002e IFI .... + +100398b4 : +100398b4: 0d0a 4957 4946 6920 696e 6974 6c61 7a69 ..WIFI initializ +100398c4: 6465 000a ed.. + +100398c8 : +100398c8: 0d0a 5245 4f52 3a52 4920 696e 2074 4957 ..ERROR: Init WI +100398d8: 4946 7420 6d69 6f65 7475 0021 FI timeout!. + +100398e4 : +100398e4: 0d0a 4957 4946 6920 2073 6f6e 2074 7572 ..WIFI is not ru +100398f4: 6e6e 6e69 0067 0000 nning... + +100398fc : +100398fc: 0d0a 6544 6e69 7469 6169 696c 697a 676e ..Deinitializing +1003990c: 5720 4649 2049 2e2e 002e 0000 WIFI ...... + +10039918 : +10039918: 0d0a 4957 4946 6420 6965 696e 6974 6c61 ..WIFI deinitial +10039928: 7a69 6465 0000 0000 ized.... + +10039930 : +10039930: 0d0a 5245 4f52 3a52 4420 6965 696e 2074 ..ERROR: Deinit +10039940: 4957 4946 7420 6d69 6f65 7475 0021 0000 WIFI timeout!... + +10039950 : +10039950: 730a 6174 7472 6120 2070 6166 6c69 202c .start ap fail, +10039960: 6c70 6165 6573 6320 6568 6b63 7020 7361 please check pas +10039970: 7773 726f 2064 656c 676e 6874 000a 0000 sword length.... + +10039980 : +10039980: 0d0a 4957 4946 4f43 464e 203a 6573 7563 ..WIFICONF: secu +10039990: 6972 7974 7420 7079 2065 7369 6e20 746f rity type is not +100399a0: 7320 7075 6f70 7472 6465 0000 supported.. + +100399ac : +100399ac: 0d0a 255b 5d64 6957 6946 203a 6353 6e61 ..[%d]WiFi: Scan +100399bc: 6920 2073 7572 6e6e 6e69 2e67 5720 6961 is running. Wai +100399cc: 2074 7332 7420 6d69 6f65 7475 002e 0000 t 2s timeout.... + +100399dc : +100399dc: 0d0a 570a 4649 2049 2520 2073 6553 7474 ...WIFI %s Sett +100399ec: 6e69 3a67 0000 0000 ing:.... + +100399f4 : +100399f4: 0d0a 3d3d 3d3d 3d3d 3d3d 3d3d 3d3d 3d3d ..============== +10039a04: 3d3d 3d3d 3d3d 3d3d 3d3d 3d3d 3d3d 3d3d ================ +10039a14: 0000 0000 .... + +10039a18 : +10039a18: 0d0a 2020 2020 2020 4f4d 4544 3d20 203e .. MODE => +10039a28: 5041 0000 AP.. + +10039a2c : +10039a2c: 0d0a 2020 2020 2020 4f4d 4544 3d20 203e .. MODE => +10039a3c: 5453 5441 4f49 004e STATION. + +10039a44 : +10039a44: 0d0a 2020 2020 2020 4f4d 4544 3d20 203e .. MODE => +10039a54: 4e55 4e4b 574f 004e UNKNOWN. + +10039a5c : +10039a5c: 0d0a 2020 2020 2020 5353 4449 3d20 203e .. SSID => +10039a6c: 7325 0000 %s.. + +10039a70 : +10039a70: 0d0a 2020 4320 4148 4e4e 4c45 3d20 203e .. CHANNEL => +10039a80: 6425 0000 %d.. + +10039a84 : +10039a84: 0d0a 2020 4553 5543 4952 5954 3d20 203e .. SECURITY => +10039a94: 504f 4e45 0000 0000 OPEN.... + +10039a9c : +10039a9c: 0d0a 2020 4553 5543 4952 5954 3d20 203e .. SECURITY => +10039aac: 4557 0050 WEP. + +10039ab0 : +10039ab0: 0d0a 4b20 5945 4920 444e 5845 3d20 203e .. KEY INDEX => +10039ac0: 6425 0000 %d.. + +10039ac4 : +10039ac4: 0d0a 2020 4553 5543 4952 5954 3d20 203e .. SECURITY => +10039ad4: 4b54 5049 0000 0000 TKIP.... + +10039adc : +10039adc: 0d0a 2020 4553 5543 4952 5954 3d20 203e .. SECURITY => +10039aec: 4541 0053 AES. + +10039af0 : +10039af0: 0d0a 2020 4553 5543 4952 5954 3d20 203e .. SECURITY => +10039b00: 4e55 4e4b 574f 004e UNKNOWN. + +10039b08 : +10039b08: 0d0a 2020 4150 5353 4f57 4452 3d20 203e .. PASSWORD => +10039b18: 7325 0000 %s.. + +10039b1c : +10039b1c: 0d0a 5245 4f52 3a52 4f20 6570 6172 6974 ..ERROR: Operati +10039b2c: 6e6f 6620 6961 656c 2164 0000 on failed!.. + +10039b38 : +10039b38: 0a0d 5041 203a 7373 6469 253d 0073 0000 ..AP: ssid=%s... + +10039b48 : +10039b48: 0a0d 5041 203a 6573 7563 6972 7974 745f ..AP: security_t +10039b58: 7079 3d65 6425 0000 ype=%d.. + +10039b60 : +10039b60: 0a0d 5041 203a 6170 7373 6f77 6472 253d ..AP: password=% +10039b70: 0073 0000 s... + +10039b74 : +10039b74: 0a0d 5041 203a 656b 5f79 6469 2078 253d ..AP: key_idx =% +10039b84: 0a64 0000 d... + +10039b88 : +10039b88: 4770 bx lr + +10039b8a : +10039b8a: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +10039b8e: b086 sub sp, #24 +10039b90: 2100 movs r1, #0 +10039b92: 2000 movs r0, #0 +10039b94: f7ce fcc5 bl 10008522 +10039b98: 2401 movs r4, #1 +10039b9a: 4d6e ldr r5, [pc, #440] ; (10039d54 ) +10039b9c: f8df 91b8 ldr.w r9, [pc, #440] ; 10039d58 +10039ba0: f8df 81b8 ldr.w r8, [pc, #440] ; 10039d5c +10039ba4: 4f6e ldr r7, [pc, #440] ; (10039d60 ) +10039ba6: f04f 0a38 mov.w sl, #56 ; 0x38 +10039baa: f06f 467f mvn.w r6, #4278190080 ; 0xff000000 +10039bae: e000 b.n 10039bb2 + +10039bb0 : +10039bb0: d003 beq.n 10039bba + +10039bb2 : +10039bb2: 9705 str r7, [sp, #20] +10039bb4: 9604 str r6, [sp, #16] +10039bb6: 9703 str r7, [sp, #12] +10039bb8: e004 b.n 10039bc4 + +10039bba : +10039bba: 486a ldr r0, [pc, #424] ; (10039d64 ) +10039bbc: 9005 str r0, [sp, #20] +10039bbe: 9604 str r6, [sp, #16] +10039bc0: 4869 ldr r0, [pc, #420] ; (10039d68 ) +10039bc2: 9003 str r0, [sp, #12] + +10039bc4 : +10039bc4: fb0a 8004 mla r0, sl, r4, r8 +10039bc8: 2172 movs r1, #114 ; 0x72 +10039bca: f880 1032 strb.w r1, [r0, #50] ; 0x32 +10039bce: ab03 add r3, sp, #12 +10039bd0: f104 0130 add.w r1, r4, #48 ; 0x30 +10039bd4: f880 1033 strb.w r1, [r0, #51] ; 0x33 +10039bd8: f8cd 9008 str.w r9, [sp, #8] +10039bdc: 2100 movs r1, #0 +10039bde: 9100 str r1, [sp, #0] +10039be0: 9501 str r5, [sp, #4] +10039be2: aa04 add r2, sp, #16 +10039be4: a905 add r1, sp, #20 +10039be6: f7d5 f9fc bl 1000efe2 +10039bea: 1e64 subs r4, r4, #1 +10039bec: b264 sxtb r4, r4 +10039bee: 2c00 cmp r4, #0 +10039bf0: d5de bpl.n 10039bb0 +10039bf2: 4640 mov r0, r8 +10039bf4: f7d5 fa5a bl 1000f0ac +10039bf8: 2400 movs r4, #0 + +10039bfa : +10039bfa: fb0a 8004 mla r0, sl, r4, r8 +10039bfe: f7d5 fa5f bl 1000f0c0 +10039c02: 1c64 adds r4, r4, #1 +10039c04: 2c02 cmp r4, #2 +10039c06: dbf8 blt.n 10039bfa +10039c08: b006 add sp, #24 +10039c0a: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + +10039c0e : +10039c0e: b5f0 push {r4, r5, r6, r7, lr} +10039c10: 2400 movs r4, #0 +10039c12: b085 sub sp, #20 +10039c14: 2802 cmp r0, #2 +10039c16: bfa8 it ge +10039c18: 2001 movge r0, #1 +10039c1a: 4a50 ldr r2, [pc, #320] ; (10039d5c ) +10039c1c: 4e53 ldr r6, [pc, #332] ; (10039d6c ) +10039c1e: 2338 movs r3, #56 ; 0x38 +10039c20: fb03 2500 mla r5, r3, r0, r2 +10039c24: b919 cbnz r1, 10039c2e +10039c26: 606c str r4, [r5, #4] +10039c28: 60ac str r4, [r5, #8] +10039c2a: 60ec str r4, [r5, #12] +10039c2c: e008 b.n 10039c40 + +10039c2e : +10039c2e: 0008 movs r0, r1 +10039c30: d006 beq.n 10039c40 +10039c32: 2901 cmp r1, #1 +10039c34: d019 beq.n 10039c6a +10039c36: 2903 cmp r1, #3 +10039c38: d049 beq.n 10039cce +10039c3a: 2904 cmp r1, #4 +10039c3c: d1f7 bne.n 10039c2e +10039c3e: e051 b.n 10039ce4 + +10039c40 : +10039c40: f000 f85c bl 10039cfc + +10039c44 : +10039c44: 4628 mov r0, r5 +10039c46: f7d3 fbe2 bl 1000d40e +10039c4a: e00e b.n 10039c6a + +10039c4c : +10039c4c: f44f 70fa mov.w r0, #500 ; 0x1f4 +10039c50: f7d0 ff3f bl 1000aad2 +10039c54: f7d3 fb82 bl 1000d35c +10039c58: f504 74fa add.w r4, r4, #500 ; 0x1f4 +10039c5c: f64e 2060 movw r0, #60000 ; 0xea60 +10039c60: 4284 cmp r4, r0 +10039c62: db02 blt.n 10039c6a +10039c64: f7d3 fb54 bl 1000d310 +10039c68: 2400 movs r4, #0 + +10039c6a : +10039c6a: 686f ldr r7, [r5, #4] +10039c6c: b1a7 cbz r7, 10039c98 +10039c6e: 2200 movs r2, #0 +10039c70: 4631 mov r1, r6 +10039c72: 200d movs r0, #13 +10039c74: f7f6 f8e7 bl 1002fe46 +10039c78: 4628 mov r0, r5 +10039c7a: f7d3 fe45 bl 1000d908 +10039c7e: 0e38 lsrs r0, r7, #24 +10039c80: 9000 str r0, [sp, #0] +10039c82: 023b lsls r3, r7, #8 +10039c84: 043a lsls r2, r7, #16 +10039c86: 0e1b lsrs r3, r3, #24 +10039c88: 0e12 lsrs r2, r2, #24 +10039c8a: b2f9 uxtb r1, r7 +10039c8c: f20f 00e0 addw r0, pc, #224 ; 0xe0 +10039c90: f7d2 fb37 bl 1000c302 +10039c94: 2002 movs r0, #2 +10039c96: e02f b.n 10039cf8 + +10039c98 : +10039c98: 6a28 ldr r0, [r5, #32] +10039c9a: 7b40 ldrb r0, [r0, #13] +10039c9c: 2806 cmp r0, #6 +10039c9e: dbd5 blt.n 10039c4c +10039ca0: 4628 mov r0, r5 +10039ca2: f7d3 fe31 bl 1000d908 +10039ca6: f000 f84a bl 10039d3e + +10039caa : +10039caa: 4628 mov r0, r5 +10039cac: f7d5 f9bb bl 1000f026 +10039cb0: f20f 00d8 addw r0, pc, #216 ; 0xd8 +10039cb4: f7d2 fb25 bl 1000c302 +10039cb8: 2050 movs r0, #80 ; 0x50 +10039cba: 9000 str r0, [sp, #0] +10039cbc: 2301 movs r3, #1 +10039cbe: 22a8 movs r2, #168 ; 0xa8 +10039cc0: 21c0 movs r1, #192 ; 0xc0 +10039cc2: f20f 00d8 addw r0, pc, #216 ; 0xd8 +10039cc6: f7d2 fb1c bl 1000c302 +10039cca: 2005 movs r0, #5 +10039ccc: e014 b.n 10039cf8 + +10039cce : +10039cce: f000 f815 bl 10039cfc + +10039cd2 : +10039cd2: f20f 00ec addw r0, pc, #236 ; 0xec +10039cd6: f7d2 fb14 bl 1000c302 +10039cda: 4628 mov r0, r5 +10039cdc: f7d3 fdb3 bl 1000d846 +10039ce0: 2003 movs r0, #3 +10039ce2: e009 b.n 10039cf8 + +10039ce4 : +10039ce4: f000 f80a bl 10039cfc + +10039ce8 : +10039ce8: f20f 00ec addw r0, pc, #236 ; 0xec +10039cec: f7d2 fb09 bl 1000c302 +10039cf0: 4628 mov r0, r5 +10039cf2: f7d3 fe09 bl 1000d908 +10039cf6: 2004 movs r0, #4 + +10039cf8 : +10039cf8: b005 add sp, #20 +10039cfa: bdf0 pop {r4, r5, r6, r7, pc} + +10039cfc : +10039cfc: 4631 mov r1, r6 +10039cfe: 200d movs r0, #13 +10039d00: f7f6 b8b7 b.w 1002fe72 + +10039d04 : +10039d04: 302b adds r0, #43 ; 0x2b +10039d06: 4770 bx lr + +10039d08 : +10039d08: 1d00 adds r0, r0, #4 +10039d0a: 4770 bx lr + +10039d0c : +10039d0c: 300c adds r0, #12 +10039d0e: 4770 bx lr + +10039d10 : +10039d10: b5e0 push {r5, r6, r7, lr} +10039d12: f990 2033 ldrsb.w r2, [r0, #51] ; 0x33 +10039d16: f06f 417f mvn.w r1, #4278190080 ; 0xff000000 +10039d1a: 2a30 cmp r2, #48 ; 0x30 +10039d1c: d105 bne.n 10039d2a +10039d1e: 9101 str r1, [sp, #4] +10039d20: 4a10 ldr r2, [pc, #64] ; (10039d64 ) +10039d22: 4911 ldr r1, [pc, #68] ; (10039d68 ) +10039d24: 9202 str r2, [sp, #8] +10039d26: 9100 str r1, [sp, #0] +10039d28: e003 b.n 10039d32 + +10039d2a : +10039d2a: 9101 str r1, [sp, #4] +10039d2c: 4a0c ldr r2, [pc, #48] ; (10039d60 ) +10039d2e: 9202 str r2, [sp, #8] +10039d30: 9200 str r2, [sp, #0] + +10039d32 : +10039d32: ab00 add r3, sp, #0 +10039d34: aa01 add r2, sp, #4 +10039d36: a902 add r1, sp, #8 +10039d38: f7d5 f975 bl 1000f026 +10039d3c: bd07 pop {r0, r1, r2, pc} + +10039d3e : +10039d3e: 4809 ldr r0, [pc, #36] ; (10039d64 ) +10039d40: 9003 str r0, [sp, #12] +10039d42: ab01 add r3, sp, #4 +10039d44: f06f 407f mvn.w r0, #4278190080 ; 0xff000000 +10039d48: 9002 str r0, [sp, #8] +10039d4a: aa02 add r2, sp, #8 +10039d4c: 4806 ldr r0, [pc, #24] ; (10039d68 ) +10039d4e: 9001 str r0, [sp, #4] +10039d50: a903 add r1, sp, #12 +10039d52: 4770 bx lr + +10039d54 : +10039d54: 024d 1002 M... + +10039d58 : +10039d58: 8405 1000 .... + +10039d5c : +10039d5c: 7824 1004 $x.. + +10039d60 : +10039d60: a8c0 012b ..+. + +10039d64 : +10039d64: a8c0 5001 ...P + +10039d68 : +10039d68: a8c0 0101 .... + +10039d6c : +10039d6c: 9b89 1003 .... + +10039d70 : +10039d70: 0d0a 5049 6120 6464 6572 7373 3a20 2520 ..IP address : % +10039d80: 2e64 6425 252e 2e64 6425 0000 d.%d.%d.%d.. + +10039d8c : +10039d8c: 0d0a 4844 5043 7420 6d69 6f65 7475 0000 ..DHCP timeout.. + +10039d9c : +10039d9c: 0d0a 7453 7461 6369 4920 2050 6461 7264 ..Static IP addr +10039dac: 7365 2073 203a 6425 252e 2e64 6425 252e ess : %d.%d.%d.% +10039dbc: 0064 0000 d... + +10039dc0 : +10039dc0: 0d0a 774c 5049 445f 4348 3a50 5220 6c65 ..LwIP_DHCP: Rel +10039dd0: 6165 6573 6920 0070 ease ip. + +10039dd8 : +10039dd8: 0d0a 774c 5049 445f 4348 3a50 6420 6368 ..LwIP_DHCP: dhc +10039de8: 2070 7473 706f 002e p stop.. + +10039df0 : +10039df0: f20f 119c addw r1, pc, #412 ; 0x19c +10039df4: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +10039df8: b0f1 sub sp, #452 ; 0x1c4 +10039dfa: 4c64 ldr r4, [pc, #400] ; (10039f8c ) +10039dfc: 68e3 ldr r3, [r4, #12] +10039dfe: f44f 707a mov.w r0, #1000 ; 0x3e8 +10039e02: 9004 str r0, [sp, #16] +10039e04: f104 0218 add.w r2, r4, #24 +10039e08: f103 0008 add.w r0, r3, #8 +10039e0c: 9002 str r0, [sp, #8] +10039e0e: f103 001c add.w r0, r3, #28 +10039e12: 9000 str r0, [sp, #0] +10039e14: f20f 1084 addw r0, pc, #388 ; 0x184 +10039e18: f7d2 fa73 bl 1000c302 +10039e1c: 2600 movs r6, #0 +10039e1e: ad3f add r5, sp, #252 ; 0xfc +10039e20: e010 b.n 10039e44 + +10039e22 : +10039e22: 8822 ldrh r2, [r4, #0] +10039e24: f20f 1168 addw r1, pc, #360 ; 0x168 +10039e28: f20f 10c8 addw r0, pc, #456 ; 0x1c8 +10039e2c: f7d2 fa69 bl 1000c302 + +10039e30 : +10039e30: 4658 mov r0, fp +10039e32: f7d5 f99e bl 1000f172 +10039e36: 6920 ldr r0, [r4, #16] +10039e38: f44f 717a mov.w r1, #1000 ; 0x3e8 +10039e3c: 4348 muls r0, r1 +10039e3e: f7d0 fe48 bl 1000aad2 +10039e42: 1c76 adds r6, r6, #1 + +10039e44 : +10039e44: 68a0 ldr r0, [r4, #8] +10039e46: 4286 cmp r6, r0 +10039e48: db03 blt.n 10039e52 +10039e4a: 6860 ldr r0, [r4, #4] +10039e4c: 2801 cmp r0, #1 +10039e4e: f040 8080 bne.w 10039f52 + +10039e52 : +10039e52: 2201 movs r2, #1 +10039e54: 2103 movs r1, #3 +10039e56: 2002 movs r0, #2 +10039e58: f7d5 fb4e bl 1000f4f8 +10039e5c: 4683 mov fp, r0 +10039e5e: 2004 movs r0, #4 +10039e60: 9000 str r0, [sp, #0] +10039e62: ab04 add r3, sp, #16 +10039e64: f241 0206 movw r2, #4102 ; 0x1006 +10039e68: f640 71ff movw r1, #4095 ; 0xfff +10039e6c: 4658 mov r0, fp +10039e6e: f7d5 fc15 bl 1000f69c +10039e72: 2010 movs r0, #16 +10039e74: f88d 0014 strb.w r0, [sp, #20] +10039e78: 2002 movs r0, #2 +10039e7a: f88d 0015 strb.w r0, [sp, #21] +10039e7e: f104 0018 add.w r0, r4, #24 +10039e82: f7d2 fa8d bl 1000c3a0 +10039e86: 9006 str r0, [sp, #24] +10039e88: 2000 movs r0, #0 +10039e8a: 68e7 ldr r7, [r4, #12] +10039e8c: e003 b.n 10039e96 + +10039e8e : +10039e8e: a93f add r1, sp, #252 ; 0xfc +10039e90: 1841 adds r1, r0, r1 +10039e92: 7208 strb r0, [r1, #8] +10039e94: 1c40 adds r0, r0, #1 + +10039e96 : +10039e96: 42b8 cmp r0, r7 +10039e98: dbf9 blt.n 10039e8e +10039e9a: 2008 movs r0, #8 +10039e9c: f88d 00fc strb.w r0, [sp, #252] ; 0xfc +10039ea0: 2000 movs r0, #0 +10039ea2: 7068 strb r0, [r5, #1] +10039ea4: 8068 strh r0, [r5, #2] +10039ea6: f64a 30cd movw r0, #43981 ; 0xabcd +10039eaa: 80a8 strh r0, [r5, #4] +10039eac: 8820 ldrh r0, [r4, #0] +10039eae: 1c40 adds r0, r0, #1 +10039eb0: 8020 strh r0, [r4, #0] +10039eb2: b280 uxth r0, r0 +10039eb4: f7d2 fb47 bl 1000c546 +10039eb8: 80e8 strh r0, [r5, #6] +10039eba: f107 0108 add.w r1, r7, #8 +10039ebe: b289 uxth r1, r1 +10039ec0: a83f add r0, sp, #252 ; 0xfc +10039ec2: f7d2 fbc0 bl 1000c646 +10039ec6: 8068 strh r0, [r5, #2] +10039ec8: 2010 movs r0, #16 +10039eca: 9001 str r0, [sp, #4] +10039ecc: a805 add r0, sp, #20 +10039ece: 9000 str r0, [sp, #0] +10039ed0: 2300 movs r3, #0 +10039ed2: 9a02 ldr r2, [sp, #8] +10039ed4: a93f add r1, sp, #252 ; 0xfc +10039ed6: 4658 mov r0, fp +10039ed8: f7d5 fab9 bl 1000f44e +10039edc: f7d0 ff0d bl 1000acfa +10039ee0: 4680 mov r8, r0 +10039ee2: a803 add r0, sp, #12 +10039ee4: 9001 str r0, [sp, #4] +10039ee6: 2300 movs r3, #0 +10039ee8: a809 add r0, sp, #36 ; 0x24 +10039eea: 9000 str r0, [sp, #0] +10039eec: 22c8 movs r2, #200 ; 0xc8 +10039eee: a90d add r1, sp, #52 ; 0x34 +10039ef0: 4658 mov r0, fp +10039ef2: f7d5 f990 bl 1000f216 +10039ef6: 4681 mov r9, r0 +10039ef8: f1b9 0f1c cmp.w r9, #28 +10039efc: db91 blt.n 10039e22 +10039efe: f7d0 fefc bl 1000acfa +10039f02: f89d 1034 ldrb.w r1, [sp, #52] ; 0x34 +10039f06: 4682 mov sl, r0 +10039f08: a80d add r0, sp, #52 ; 0x34 +10039f0a: f001 010f and.w r1, r1, #15 +10039f0e: eb00 0781 add.w r7, r0, r1, lsl #2 +10039f12: f64a 31cd movw r1, #43981 ; 0xabcd +10039f16: 88b8 ldrh r0, [r7, #4] +10039f18: 4288 cmp r0, r1 +10039f1a: d189 bne.n 10039e30 +10039f1c: 8820 ldrh r0, [r4, #0] +10039f1e: f7d2 fb12 bl 1000c546 +10039f22: 4601 mov r1, r0 +10039f24: 88f8 ldrh r0, [r7, #6] +10039f26: 4288 cmp r0, r1 +10039f28: d182 bne.n 10039e30 +10039f2a: f7d2 fb0c bl 1000c546 +10039f2e: 4607 mov r7, r0 +10039f30: a80a add r0, sp, #40 ; 0x28 +10039f32: f7d2 fabb bl 1000c4ac +10039f36: 4603 mov r3, r0 +10039f38: ebaa 0008 sub.w r0, sl, r8 +10039f3c: 9001 str r0, [sp, #4] +10039f3e: 9700 str r7, [sp, #0] +10039f40: f1a9 0214 sub.w r2, r9, #20 +10039f44: f20f 0148 addw r1, pc, #72 ; 0x48 +10039f48: f20f 0078 addw r0, pc, #120 ; 0x78 +10039f4c: f7d2 f9d9 bl 1000c302 +10039f50: e76e b.n 10039e30 + +10039f52 : +10039f52: 6960 ldr r0, [r4, #20] +10039f54: b908 cbnz r0, 10039f5a +10039f56: f7d0 fd73 bl 1000aa40 + +10039f5a : +10039f5a: b071 add sp, #452 ; 0x1c4 +10039f5c: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +10039f60 : +10039f60: b510 push {r4, lr} +10039f62: 4b0a ldr r3, [pc, #40] ; (10039f8c ) +10039f64: 2401 movs r4, #1 +10039f66: 615c str r4, [r3, #20] +10039f68: 6059 str r1, [r3, #4] +10039f6a: 2400 movs r4, #0 +10039f6c: 801c strh r4, [r3, #0] +10039f6e: 4601 mov r1, r0 +10039f70: 2478 movs r4, #120 ; 0x78 +10039f72: 60dc str r4, [r3, #12] +10039f74: 609a str r2, [r3, #8] +10039f76: 2401 movs r4, #1 +10039f78: 611c str r4, [r3, #16] +10039f7a: f103 0018 add.w r0, r3, #24 +10039f7e: f7d2 f9e9 bl 1000c354 +10039f82: e8bd 4010 ldmia.w sp!, {r4, lr} +10039f86: 2000 movs r0, #0 +10039f88: e732 b.n 10039df0 + ... + +10039f8c : +10039f8c: 78a8 1004 .x.. + +10039f90 : +10039f90: 6970 676e 745f 7365 0074 0000 ping_test... + +10039f9c : +10039f9c: 0d0a 255b 5d73 5020 4e49 2047 7325 2520 ..[%s] PING %s % +10039fac: 2864 6425 2029 7962 6574 2073 666f 6420 d(%d) bytes of d +10039fbc: 7461 0a61 0000 0000 ata..... + +10039fc4 : +10039fc4: 0d0a 255b 5d73 2520 2064 7962 6574 2073 ..[%s] %d bytes +10039fd4: 7266 6d6f 2520 3a73 6920 6d63 5f70 6573 from %s: icmp_se +10039fe4: 3d71 6425 7420 6d69 3d65 6425 6d20 0073 q=%d time=%d ms. + +10039ff4 : +10039ff4: 0d0a 255b 5d73 5220 7165 6575 7473 7420 ..[%s] Request t +1003a004: 6d69 6f65 7475 6620 726f 6920 6d63 5f70 imeout for icmp_ +1003a014: 6573 2071 6425 000a seq %d.. + +1003a01c : +1003a01c: 2000 movs r0, #0 +1003a01e: f8df 1388 ldr.w r1, [pc, #904] ; 1003a3a8 + +1003a022 : +1003a022: 2218 movs r2, #24 +1003a024: 4342 muls r2, r0 +1003a026: 230a movs r3, #10 +1003a028: 5453 strb r3, [r2, r1] +1003a02a: 1852 adds r2, r2, r1 +1003a02c: 2300 movs r3, #0 +1003a02e: 7513 strb r3, [r2, #20] +1003a030: 80d3 strh r3, [r2, #6] +1003a032: 6113 str r3, [r2, #16] +1003a034: 6093 str r3, [r2, #8] +1003a036: 1c40 adds r0, r0, #1 +1003a038: 60d3 str r3, [r2, #12] +1003a03a: 2805 cmp r0, #5 +1003a03c: dbf1 blt.n 1003a022 +1003a03e: f8df 136c ldr.w r1, [pc, #876] ; 1003a3ac +1003a042: 700b strb r3, [r1, #0] +1003a044: 4770 bx lr + +1003a046 : +1003a046: b570 push {r4, r5, r6, lr} +1003a048: 460c mov r4, r1 +1003a04a: 4615 mov r5, r2 +1003a04c: 2100 movs r1, #0 +1003a04e: 2218 movs r2, #24 +1003a050: 4bd5 ldr r3, [pc, #852] ; (1003a3a8 ) + +1003a052 : +1003a052: fb02 3601 mla r6, r2, r1, r3 +1003a056: f996 6000 ldrsb.w r6, [r6] +1003a05a: 2e0a cmp r6, #10 +1003a05c: d002 beq.n 1003a064 +1003a05e: 1c49 adds r1, r1, #1 +1003a060: 2905 cmp r1, #5 +1003a062: dbf6 blt.n 1003a052 + +1003a064 : +1003a064: 2905 cmp r1, #5 +1003a066: d102 bne.n 1003a06e +1003a068: f04f 30ff mov.w r0, #4294967295 +1003a06c: bd70 pop {r4, r5, r6, pc} + +1003a06e : +1003a06e: 4351 muls r1, r2 +1003a070: 18ce adds r6, r1, r3 +1003a072: 54c8 strb r0, [r1, r3] +1003a074: 8820 ldrh r0, [r4, #0] +1003a076: 80b0 strh r0, [r6, #4] +1003a078: 8860 ldrh r0, [r4, #2] +1003a07a: 80f0 strh r0, [r6, #6] +1003a07c: 8860 ldrh r0, [r4, #2] +1003a07e: f7d2 fc19 bl 1000c8b4 +1003a082: 60b0 str r0, [r6, #8] +1003a084: 8862 ldrh r2, [r4, #2] +1003a086: 6861 ldr r1, [r4, #4] +1003a088: f7d2 f95e bl 1000c348 +1003a08c: 8860 ldrh r0, [r4, #2] +1003a08e: f7d2 fc11 bl 1000c8b4 +1003a092: 60f0 str r0, [r6, #12] +1003a094: 8862 ldrh r2, [r4, #2] +1003a096: 68a1 ldr r1, [r4, #8] +1003a098: f7d2 f956 bl 1000c348 +1003a09c: 6135 str r5, [r6, #16] +1003a09e: 2000 movs r0, #0 +1003a0a0: 7530 strb r0, [r6, #20] +1003a0a2: bd70 pop {r4, r5, r6, pc} + +1003a0a4 : +1003a0a4: b530 push {r4, r5, lr} +1003a0a6: 2100 movs r1, #0 +1003a0a8: 2218 movs r2, #24 +1003a0aa: 4bbf ldr r3, [pc, #764] ; (1003a3a8 ) + +1003a0ac : +1003a0ac: fb02 3401 mla r4, r2, r1, r3 +1003a0b0: f994 4000 ldrsb.w r4, [r4] +1003a0b4: 4284 cmp r4, r0 +1003a0b6: d002 beq.n 1003a0be +1003a0b8: 1c49 adds r1, r1, #1 +1003a0ba: 2905 cmp r1, #5 +1003a0bc: dbf6 blt.n 1003a0ac + +1003a0be : +1003a0be: 2905 cmp r1, #5 +1003a0c0: d100 bne.n 1003a0c4 +1003a0c2: e01f b.n 1003a104 + +1003a0c4 : +1003a0c4: fb02 3101 mla r1, r2, r1, r3 +1003a0c8: 2001 movs r0, #1 +1003a0ca: 7508 strb r0, [r1, #20] +1003a0cc: 48b7 ldr r0, [pc, #732] ; (1003a3ac ) +1003a0ce: 7801 ldrb r1, [r0, #0] +1003a0d0: 1c49 adds r1, r1, #1 +1003a0d2: e01a b.n 1003a10a + +1003a0d4 : +1003a0d4: b530 push {r4, r5, lr} +1003a0d6: 2100 movs r1, #0 +1003a0d8: 2218 movs r2, #24 +1003a0da: 4bb3 ldr r3, [pc, #716] ; (1003a3a8 ) + +1003a0dc : +1003a0dc: fb02 3401 mla r4, r2, r1, r3 +1003a0e0: f994 4000 ldrsb.w r4, [r4] +1003a0e4: 4284 cmp r4, r0 +1003a0e6: d002 beq.n 1003a0ee +1003a0e8: 1c49 adds r1, r1, #1 +1003a0ea: 2905 cmp r1, #5 +1003a0ec: dbf6 blt.n 1003a0dc + +1003a0ee : +1003a0ee: 2905 cmp r1, #5 +1003a0f0: d100 bne.n 1003a0f4 +1003a0f2: e007 b.n 1003a104 + +1003a0f4 : +1003a0f4: fb02 3101 mla r1, r2, r1, r3 +1003a0f8: 2000 movs r0, #0 +1003a0fa: 7508 strb r0, [r1, #20] +1003a0fc: 48ab ldr r0, [pc, #684] ; (1003a3ac ) +1003a0fe: 7801 ldrb r1, [r0, #0] +1003a100: 1e49 subs r1, r1, #1 +1003a102: e002 b.n 1003a10a + +1003a104 : +1003a104: f04f 30ff mov.w r0, #4294967295 +1003a108: bd30 pop {r4, r5, pc} + +1003a10a : +1003a10a: 7001 strb r1, [r0, #0] +1003a10c: 2000 movs r0, #0 +1003a10e: bd30 pop {r4, r5, pc} + +1003a110 : +1003a110: b538 push {r3, r4, r5, lr} +1003a112: 2100 movs r1, #0 +1003a114: 2218 movs r2, #24 +1003a116: 4ba4 ldr r3, [pc, #656] ; (1003a3a8 ) + +1003a118 : +1003a118: fb02 3401 mla r4, r2, r1, r3 +1003a11c: f994 4000 ldrsb.w r4, [r4] +1003a120: 4284 cmp r4, r0 +1003a122: d002 beq.n 1003a12a +1003a124: 1c49 adds r1, r1, #1 +1003a126: 2905 cmp r1, #5 +1003a128: dbf6 blt.n 1003a118 + +1003a12a : +1003a12a: 2905 cmp r1, #5 +1003a12c: d102 bne.n 1003a134 +1003a12e: f04f 30ff mov.w r0, #4294967295 +1003a132: bd32 pop {r1, r4, r5, pc} + +1003a134 : +1003a134: fb02 f001 mul.w r0, r2, r1 +1003a138: 210a movs r1, #10 +1003a13a: 54c1 strb r1, [r0, r3] +1003a13c: 18c4 adds r4, r0, r3 +1003a13e: 2000 movs r0, #0 +1003a140: 7520 strb r0, [r4, #20] +1003a142: 80e0 strh r0, [r4, #6] +1003a144: 6120 str r0, [r4, #16] +1003a146: 68a0 ldr r0, [r4, #8] +1003a148: b118 cbz r0, 1003a152 +1003a14a: f7d2 fc3a bl 1000c9c2 +1003a14e: 2000 movs r0, #0 +1003a150: 60a0 str r0, [r4, #8] + +1003a152 : +1003a152: 68e0 ldr r0, [r4, #12] +1003a154: b118 cbz r0, 1003a15e +1003a156: f7d2 fc34 bl 1000c9c2 +1003a15a: 2000 movs r0, #0 +1003a15c: 60e0 str r0, [r4, #12] + +1003a15e : +1003a15e: 2000 movs r0, #0 +1003a160: bd32 pop {r1, r4, r5, pc} + +1003a162 : +1003a162: b570 push {r4, r5, r6, lr} +1003a164: f000 f8a3 bl 1003a2ae + +1003a168 : +1003a168: 0006 movs r6, r0 +1003a16a: d019 beq.n 1003a1a0 +1003a16c: 2000 movs r0, #0 +1003a16e: 6030 str r0, [r6, #0] +1003a170: 6070 str r0, [r6, #4] +1003a172: 2206 movs r2, #6 +1003a174: 4621 mov r1, r4 +1003a176: f106 0008 add.w r0, r6, #8 +1003a17a: f7d2 f8e5 bl 1000c348 +1003a17e: 2206 movs r2, #6 +1003a180: 1da1 adds r1, r4, #6 +1003a182: f106 000e add.w r0, r6, #14 +1003a186: f7d2 f8df bl 1000c348 +1003a18a: 6175 str r5, [r6, #20] +1003a18c: f7d1 f850 bl 1000b230 +1003a190: 4887 ldr r0, [pc, #540] ; (1003a3b0 ) +1003a192: 6841 ldr r1, [r0, #4] +1003a194: 2900 cmp r1, #0 +1003a196: bf1a itte ne +1003a198: 604e strne r6, [r1, #4] +1003a19a: 6031 strne r1, [r6, #0] +1003a19c: 6006 streq r6, [r0, #0] +1003a19e: e08b b.n 1003a2b8 + +1003a1a0 : +1003a1a0: bd70 pop {r4, r5, r6, pc} + +1003a1a2 : +1003a1a2: b510 push {r4, lr} +1003a1a4: 2400 movs r4, #0 +1003a1a6: f7d1 f843 bl 1000b230 +1003a1aa: 4881 ldr r0, [pc, #516] ; (1003a3b0 ) +1003a1ac: 6801 ldr r1, [r0, #0] +1003a1ae: b139 cbz r1, 1003a1c0 +1003a1b0: 460c mov r4, r1 +1003a1b2: 6849 ldr r1, [r1, #4] +1003a1b4: 2900 cmp r1, #0 +1003a1b6: bf19 ittee ne +1003a1b8: 2200 movne r2, #0 +1003a1ba: 600a strne r2, [r1, #0] +1003a1bc: 2200 moveq r2, #0 +1003a1be: 6042 streq r2, [r0, #4] + +1003a1c0 : +1003a1c0: 6001 str r1, [r0, #0] +1003a1c2: f7d1 f841 bl 1000b248 +1003a1c6: 4620 mov r0, r4 +1003a1c8: bd10 pop {r4, pc} + +1003a1ca : +1003a1ca: e92d 4ff1 stmdb sp!, {r0, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1003a1ce: f000 f8e2 bl 1003a396 + +1003a1d2 : +1003a1d2: f7ff fa52 bl 1003967a +1003a1d6: 4622 mov r2, r4 +1003a1d8: 4976 ldr r1, [pc, #472] ; (1003a3b4 ) +1003a1da: 2001 movs r0, #1 +1003a1dc: f7ff fa4b bl 10039676 +1003a1e0: 2401 movs r4, #1 +1003a1e2: f20f 2960 addw r9, pc, #608 ; 0x260 +1003a1e6: f20f 2a54 addw sl, pc, #596 ; 0x254 +1003a1ea: f20f 2b48 addw fp, pc, #584 ; 0x248 +1003a1ee: f20f 283c addw r8, pc, #572 ; 0x23c + +1003a1f2 : +1003a1f2: 4620 mov r0, r4 +1003a1f4: f7fe ff44 bl 10039080 +1003a1f8: b908 cbnz r0, 1003a1fe +1003a1fa: f000 f8c7 bl 1003a38c + +1003a1fe : +1003a1fe: f7d0 fd7c bl 1000acfa +1003a202: 4605 mov r5, r0 +1003a204: e01b b.n 1003a23e + +1003a206 : +1003a206: 4640 mov r0, r8 +1003a208: f7d2 f87b bl 1000c302 +1003a20c: 2700 movs r7, #0 + +1003a20e : +1003a20e: 19b8 adds r0, r7, r6 +1003a210: f000 f8b8 bl 1003a384 + +1003a214 : +1003a214: 1c7f adds r7, r7, #1 +1003a216: 2f06 cmp r7, #6 +1003a218: dbf9 blt.n 1003a20e +1003a21a: 4650 mov r0, sl +1003a21c: f7d2 f871 bl 1000c302 +1003a220: 2700 movs r7, #0 + +1003a222 : +1003a222: 19b8 adds r0, r7, r6 +1003a224: 7b81 ldrb r1, [r0, #14] +1003a226: f000 f8ae bl 1003a386 + +1003a22a : +1003a22a: 1c7f adds r7, r7, #1 +1003a22c: 2f06 cmp r7, #6 +1003a22e: dbf8 blt.n 1003a222 +1003a230: 6971 ldr r1, [r6, #20] +1003a232: 4648 mov r0, r9 +1003a234: f7d2 f865 bl 1000c302 +1003a238: 4630 mov r0, r6 +1003a23a: f7d2 fbc2 bl 1000c9c2 + +1003a23e : +1003a23e: f7d0 fd5c bl 1000acfa +1003a242: 9900 ldr r1, [sp, #0] +1003a244: f44f 727a mov.w r2, #1000 ; 0x3e8 +1003a248: 1b40 subs r0, r0, r5 +1003a24a: 4351 muls r1, r2 +1003a24c: 4288 cmp r0, r1 +1003a24e: d207 bcs.n 1003a260 +1003a250: f7ff ffa7 bl 1003a1a2 +1003a254: 0006 movs r6, r0 +1003a256: d1d6 bne.n 1003a206 +1003a258: 2001 movs r0, #1 +1003a25a: f7d0 fc3a bl 1000aad2 +1003a25e: e7ee b.n 1003a23e + +1003a260 : +1003a260: 1c64 adds r4, r4, #1 +1003a262: 2c0e cmp r4, #14 +1003a264: dbc5 blt.n 1003a1f2 +1003a266: e07f b.n 1003a368 + +1003a268 : +1003a268: b570 push {r4, r5, r6, lr} +1003a26a: f000 f820 bl 1003a2ae + +1003a26e : +1003a26e: 0006 movs r6, r0 +1003a270: d01c beq.n 1003a2ac +1003a272: 2000 movs r0, #0 +1003a274: 6030 str r0, [r6, #0] +1003a276: 6070 str r0, [r6, #4] +1003a278: 2206 movs r2, #6 +1003a27a: 1d21 adds r1, r4, #4 +1003a27c: f106 0008 add.w r0, r6, #8 +1003a280: f7d2 f862 bl 1000c348 +1003a284: 2206 movs r2, #6 +1003a286: f104 010a add.w r1, r4, #10 +1003a28a: f106 000e add.w r0, r6, #14 +1003a28e: f7d2 f85b bl 1000c348 +1003a292: 6175 str r5, [r6, #20] +1003a294: 7820 ldrb r0, [r4, #0] +1003a296: 7630 strb r0, [r6, #24] +1003a298: f7d0 ffca bl 1000b230 +1003a29c: 4844 ldr r0, [pc, #272] ; (1003a3b0 ) +1003a29e: 6841 ldr r1, [r0, #4] +1003a2a0: 2900 cmp r1, #0 +1003a2a2: bf1a itte ne +1003a2a4: 604e strne r6, [r1, #4] +1003a2a6: 6031 strne r1, [r6, #0] +1003a2a8: 6006 streq r6, [r0, #0] +1003a2aa: e005 b.n 1003a2b8 + +1003a2ac : +1003a2ac: bd70 pop {r4, r5, r6, pc} + +1003a2ae : +1003a2ae: 4604 mov r4, r0 +1003a2b0: 460d mov r5, r1 +1003a2b2: 201c movs r0, #28 +1003a2b4: f7d2 bafe b.w 1000c8b4 + +1003a2b8 : +1003a2b8: 6046 str r6, [r0, #4] +1003a2ba: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +1003a2be: f7d0 bfc3 b.w 1000b248 + +1003a2c2 : +1003a2c2: e92d 4ff1 stmdb sp!, {r0, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1003a2c6: f000 f866 bl 1003a396 + +1003a2ca : +1003a2ca: f7ff f9d6 bl 1003967a +1003a2ce: 4622 mov r2, r4 +1003a2d0: 4939 ldr r1, [pc, #228] ; (1003a3b8 ) +1003a2d2: 2003 movs r0, #3 +1003a2d4: f7ff f9cf bl 10039676 +1003a2d8: 2401 movs r4, #1 +1003a2da: f20f 1a60 addw sl, pc, #352 ; 0x160 +1003a2de: f20f 1b54 addw fp, pc, #340 ; 0x154 +1003a2e2: f20f 186c addw r8, pc, #364 ; 0x16c +1003a2e6: a72f add r7, pc, #188 ; (adr r7, 1003a3a4 ) + +1003a2e8 : +1003a2e8: 4620 mov r0, r4 +1003a2ea: f7fe fec9 bl 10039080 +1003a2ee: b908 cbnz r0, 1003a2f4 +1003a2f0: f000 f84c bl 1003a38c + +1003a2f4 : +1003a2f4: f7d0 fd01 bl 1000acfa +1003a2f8: 4681 mov r9, r0 +1003a2fa: e020 b.n 1003a33e + +1003a2fc : +1003a2fc: 7e29 ldrb r1, [r5, #24] +1003a2fe: 4640 mov r0, r8 +1003a300: f7d1 ffff bl 1000c302 +1003a304: 4638 mov r0, r7 +1003a306: f7d1 fffc bl 1000c302 +1003a30a: 2600 movs r6, #0 + +1003a30c : +1003a30c: 1970 adds r0, r6, r5 +1003a30e: f000 f839 bl 1003a384 + +1003a312 : +1003a312: 1c76 adds r6, r6, #1 +1003a314: 2e06 cmp r6, #6 +1003a316: dbf9 blt.n 1003a30c +1003a318: 4650 mov r0, sl +1003a31a: f7d1 fff2 bl 1000c302 +1003a31e: 2600 movs r6, #0 + +1003a320 : +1003a320: 1970 adds r0, r6, r5 +1003a322: 7b81 ldrb r1, [r0, #14] +1003a324: f000 f82f bl 1003a386 + +1003a328 : +1003a328: 1c76 adds r6, r6, #1 +1003a32a: 2e06 cmp r6, #6 +1003a32c: dbf8 blt.n 1003a320 +1003a32e: 6969 ldr r1, [r5, #20] +1003a330: f20f 1010 addw r0, pc, #272 ; 0x110 +1003a334: f7d1 ffe5 bl 1000c302 +1003a338: 4628 mov r0, r5 +1003a33a: f7d2 fb42 bl 1000c9c2 + +1003a33e : +1003a33e: f7d0 fcdc bl 1000acfa +1003a342: 9900 ldr r1, [sp, #0] +1003a344: f44f 727a mov.w r2, #1000 ; 0x3e8 +1003a348: eba0 0009 sub.w r0, r0, r9 +1003a34c: 4351 muls r1, r2 +1003a34e: 4288 cmp r0, r1 +1003a350: d207 bcs.n 1003a362 +1003a352: f7ff ff26 bl 1003a1a2 +1003a356: 0005 movs r5, r0 +1003a358: d1d0 bne.n 1003a2fc +1003a35a: 2001 movs r0, #1 +1003a35c: f7d0 fbb9 bl 1000aad2 +1003a360: e7ed b.n 1003a33e + +1003a362 : +1003a362: 1c64 adds r4, r4, #1 +1003a364: 2c0e cmp r4, #14 +1003a366: dbbf blt.n 1003a2e8 + +1003a368 : +1003a368: 2100 movs r1, #0 +1003a36a: 2200 movs r2, #0 +1003a36c: 4608 mov r0, r1 +1003a36e: f7ff f982 bl 10039676 +1003a372: e001 b.n 1003a378 + +1003a374 : +1003a374: f7d2 fb25 bl 1000c9c2 + +1003a378 : +1003a378: f7ff ff13 bl 1003a1a2 +1003a37c: 2800 cmp r0, #0 +1003a37e: d1f9 bne.n 1003a374 +1003a380: e8bd 8ff1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1003a384 : +1003a384: 7a01 ldrb r1, [r0, #8] + +1003a386 : +1003a386: 4658 mov r0, fp +1003a388: f7d1 bfbb b.w 1000c302 + +1003a38c : +1003a38c: 4621 mov r1, r4 +1003a38e: f20f 0080 addw r0, pc, #128 ; 0x80 +1003a392: f7d1 bfb6 b.w 1000c302 + +1003a396 : +1003a396: 460c mov r4, r1 +1003a398: 4805 ldr r0, [pc, #20] ; (1003a3b0 ) +1003a39a: 2100 movs r1, #0 +1003a39c: 6001 str r1, [r0, #0] +1003a39e: 6041 str r1, [r0, #4] +1003a3a0: 4770 bx lr + ... + +1003a3a4 : +1003a3a4: 4144 003a DA:. + +1003a3a8 : +1003a3a8: 807c 1004 |... + +1003a3ac : +1003a3ac: 8b11 1004 .... + +1003a3b0 : +1003a3b0: 8074 1004 t... + +1003a3b4 : +1003a3b4: a163 1003 c... + +1003a3b8 : +1003a3b8: a269 1003 i... + +1003a3bc : +1003a3bc: b538 push {r3, r4, r5, lr} +1003a3be: 4604 mov r4, r0 +1003a3c0: 460d mov r5, r1 +1003a3c2: f7ff fa25 bl 10039810 +1003a3c6: 2c02 cmp r4, #2 +1003a3c8: d108 bne.n 1003a3dc +1003a3ca: 6868 ldr r0, [r5, #4] +1003a3cc: f7fa fb20 bl 10034a10 +1003a3d0: 2801 cmp r0, #1 +1003a3d2: db16 blt.n 1003a402 +1003a3d4: e8bd 4034 ldmia.w sp!, {r2, r4, r5, lr} +1003a3d8: 2100 movs r1, #0 +1003a3da: e772 b.n 1003a2c2 + +1003a3dc : +1003a3dc: 2c03 cmp r4, #3 +1003a3de: d110 bne.n 1003a402 +1003a3e0: 6868 ldr r0, [r5, #4] +1003a3e2: f7fa fb15 bl 10034a10 +1003a3e6: 4604 mov r4, r0 +1003a3e8: 2c01 cmp r4, #1 +1003a3ea: db0a blt.n 1003a402 +1003a3ec: 68a8 ldr r0, [r5, #8] +1003a3ee: f20f 0170 addw r1, pc, #112 ; 0x70 +1003a3f2: f7d1 ffad bl 1000c350 +1003a3f6: b920 cbnz r0, 1003a402 +1003a3f8: 4620 mov r0, r4 +1003a3fa: e8bd 4034 ldmia.w sp!, {r2, r4, r5, lr} +1003a3fe: 2101 movs r1, #1 +1003a400: e6e3 b.n 1003a1ca + +1003a402 : +1003a402: 6829 ldr r1, [r5, #0] +1003a404: f20f 0064 addw r0, pc, #100 ; 0x64 +1003a408: e8bd 4034 ldmia.w sp!, {r2, r4, r5, lr} +1003a40c: f7d1 bf79 b.w 1000c302 + +1003a410 : +1003a410: 0a0a 530d 6977 6374 2068 6f74 6320 6168 ...Switch to cha +1003a420: 6e6e 6c65 2528 2964 0000 0000 nnel(%d).... + +1003a42c : +1003a42c: 0d0a 4144 003a 0000 ..DA:... + +1003a434 : +1003a434: 2520 3230 0078 0000 %02x... + +1003a43c : +1003a43c: 202c 4153 003a 0000 , SA:... + +1003a444 : +1003a444: 202c 656c 3d6e 6425 0000 0000 , len=%d.... + +1003a450 : +1003a450: 0d0a 5954 4550 203a 7830 7825 202c 0000 ..TYPE: 0x%x, .. + +1003a460 : +1003a460: 6977 6874 6c5f 6e65 0000 0000 with_len.... + +1003a46c : +1003a46c: 0d0a 7355 6761 3a65 2520 2073 5544 4152 ..Usage: %s DURA +1003a47c: 4954 4e4f 535f 4345 4e4f 5344 5b20 6977 TION_SECONDS [wi +1003a48c: 6874 6c5f 6e65 005d th_len]. + +1003a494 : +1003a494: b538 push {r3, r4, r5, lr} +1003a496: f8df 4630 ldr.w r4, [pc, #1584] ; 1003aac8 +1003a49a: 6960 ldr r0, [r4, #20] +1003a49c: 2250 movs r2, #80 ; 0x50 +1003a49e: f000 fa10 bl 1003a8c2 + +1003a4a2 : +1003a4a2: 6961 ldr r1, [r4, #20] +1003a4a4: 2020 movs r0, #32 +1003a4a6: 7008 strb r0, [r1, #0] +1003a4a8: 204d movs r0, #77 ; 0x4d +1003a4aa: f7d2 f84c bl 1000c546 +1003a4ae: 6963 ldr r3, [r4, #20] +1003a4b0: f8df 5618 ldr.w r5, [pc, #1560] ; 1003aacc +1003a4b4: f8a3 0001 strh.w r0, [r3, #1] +1003a4b8: 2206 movs r2, #6 +1003a4ba: f105 012b add.w r1, r5, #43 ; 0x2b +1003a4be: 1cd8 adds r0, r3, #3 +1003a4c0: f7d1 ff42 bl 1000c348 +1003a4c4: 6960 ldr r0, [r4, #20] +1003a4c6: 2100 movs r1, #0 +1003a4c8: 7241 strb r1, [r0, #9] +1003a4ca: 8141 strh r1, [r0, #10] +1003a4cc: 2240 movs r2, #64 ; 0x40 +1003a4ce: 6869 ldr r1, [r5, #4] +1003a4d0: 60c1 str r1, [r0, #12] +1003a4d2: 2100 movs r1, #0 +1003a4d4: e8bd 4038 ldmia.w sp!, {r3, r4, r5, lr} +1003a4d8: 3010 adds r0, #16 +1003a4da: f7d1 bf37 b.w 1000c34c + +1003a4de : +1003a4de: b5f0 push {r4, r5, r6, r7, lr} +1003a4e0: b087 sub sp, #28 +1003a4e2: f7ff ffd7 bl 1003a494 +1003a4e6: 2211 movs r2, #17 +1003a4e8: 2102 movs r1, #2 +1003a4ea: 2002 movs r0, #2 +1003a4ec: f7d5 f804 bl 1000f4f8 +1003a4f0: 4604 mov r4, r0 +1003a4f2: f114 0f01 cmn.w r4, #1 +1003a4f6: bf08 it eq +1003a4f8: f04f 30ff moveq.w r0, #4294967295 +1003a4fc: d029 beq.n 1003a552 +1003a4fe: 2210 movs r2, #16 +1003a500: 2100 movs r1, #0 +1003a502: a802 add r0, sp, #8 +1003a504: f7d1 ff22 bl 1000c34c +1003a508: 2002 movs r0, #2 +1003a50a: f88d 0009 strb.w r0, [sp, #9] +1003a50e: f242 20a0 movw r0, #8864 ; 0x22a0 +1003a512: f7d2 f818 bl 1000c546 +1003a516: f8ad 000a strh.w r0, [sp, #10] +1003a51a: 260a movs r6, #10 +1003a51c: f8df 55a8 ldr.w r5, [pc, #1448] ; 1003aac8 +1003a520: 69a8 ldr r0, [r5, #24] +1003a522: 6f40 ldr r0, [r0, #116] ; 0x74 +1003a524: 9003 str r0, [sp, #12] + +1003a526 : +1003a526: 2714 movs r7, #20 + +1003a528 : +1003a528: 2010 movs r0, #16 +1003a52a: 9001 str r0, [sp, #4] +1003a52c: a802 add r0, sp, #8 +1003a52e: 9000 str r0, [sp, #0] +1003a530: 2300 movs r3, #0 +1003a532: 6969 ldr r1, [r5, #20] +1003a534: 2250 movs r2, #80 ; 0x50 +1003a536: 4620 mov r0, r4 +1003a538: f7d4 ff89 bl 1000f44e +1003a53c: 2032 movs r0, #50 ; 0x32 +1003a53e: f7d0 fac8 bl 1000aad2 +1003a542: 1e7f subs r7, r7, #1 +1003a544: d1f0 bne.n 1003a528 +1003a546: 1e76 subs r6, r6, #1 +1003a548: d1ed bne.n 1003a526 +1003a54a: 4620 mov r0, r4 +1003a54c: f7d4 fe11 bl 1000f172 +1003a550: 2000 movs r0, #0 + +1003a552 : +1003a552: b007 add sp, #28 +1003a554: bdf0 pop {r4, r5, r6, r7, pc} + +1003a556 : +1003a556: b570 push {r4, r5, r6, lr} +1003a558: 4605 mov r5, r0 +1003a55a: b09c sub sp, #112 ; 0x70 +1003a55c: 460c mov r4, r1 +1003a55e: f20f 6088 addw r0, pc, #1672 ; 0x688 +1003a562: f7d1 fece bl 1000c302 +1003a566: f8df 6568 ldr.w r6, [pc, #1384] ; 1003aad0 +1003a56a: 42b5 cmp r5, r6 +1003a56c: bf08 it eq +1003a56e: f20f 50b4 addweq r0, pc, #1460 ; 0x5b4 +1003a572: d010 beq.n 1003a596 +1003a574: 2d01 cmp r5, #1 +1003a576: d108 bne.n 1003a58a +1003a578: f20f 50dc addw r0, pc, #1500 ; 0x5dc +1003a57c: f7d1 fec1 bl 1000c302 +1003a580: 2001 movs r0, #1 +1003a582: 62a0 str r0, [r4, #40] ; 0x28 +1003a584: 2000 movs r0, #0 +1003a586: 6360 str r0, [r4, #52] ; 0x34 +1003a588: e00f b.n 1003a5aa + +1003a58a : +1003a58a: f8df 6548 ldr.w r6, [pc, #1352] ; 1003aad4 +1003a58e: 42b5 cmp r5, r6 +1003a590: d105 bne.n 1003a59e +1003a592: f20f 50f4 addw r0, pc, #1524 ; 0x5f4 + +1003a596 : +1003a596: f7d1 feb4 bl 1000c302 +1003a59a: 62a6 str r6, [r4, #40] ; 0x28 +1003a59c: e005 b.n 1003a5aa + +1003a59e : +1003a59e: f20f 601c addw r0, pc, #1564 ; 0x61c +1003a5a2: f7d1 feae bl 1000c302 +1003a5a6: 2000 movs r0, #0 +1003a5a8: 62a0 str r0, [r4, #40] ; 0x28 + +1003a5aa : +1003a5aa: f8df 551c ldr.w r5, [pc, #1308] ; 1003aac8 +1003a5ae: 69a8 ldr r0, [r5, #24] +1003a5b0: f100 0130 add.w r1, r0, #48 ; 0x30 +1003a5b4: 62e1 str r1, [r4, #44] ; 0x2c +1003a5b6: 3030 adds r0, #48 ; 0x30 +1003a5b8: f7d1 fece bl 1000c358 +1003a5bc: 6320 str r0, [r4, #48] ; 0x30 +1003a5be: 68e8 ldr r0, [r5, #12] +1003a5c0: 1e41 subs r1, r0, #1 +1003a5c2: 2920 cmp r1, #32 +1003a5c4: d22f bcs.n 1003a626 +1003a5c6: 7020 strb r0, [r4, #0] +1003a5c8: f105 0120 add.w r1, r5, #32 +1003a5cc: 7822 ldrb r2, [r4, #0] + +1003a5ce : +1003a5ce: 1c60 adds r0, r4, #1 +1003a5d0: f7d6 f91d bl 1001080e +1003a5d4: 6aa0 ldr r0, [r4, #40] ; 0x28 +1003a5d6: 2801 cmp r0, #1 +1003a5d8: d16f bne.n 1003a6ba +1003a5da: 6b21 ldr r1, [r4, #48] ; 0x30 +1003a5dc: 69a8 ldr r0, [r5, #24] +1003a5de: 290a cmp r1, #10 +1003a5e0: d137 bne.n 1003a652 +1003a5e2: a909 add r1, sp, #36 ; 0x24 +1003a5e4: 9102 str r1, [sp, #8] +1003a5e6: ab06 add r3, sp, #24 +1003a5e8: a908 add r1, sp, #32 +1003a5ea: 9101 str r1, [sp, #4] +1003a5ec: aa05 add r2, sp, #20 +1003a5ee: a907 add r1, sp, #28 +1003a5f0: 9100 str r1, [sp, #0] +1003a5f2: 3030 adds r0, #48 ; 0x30 +1003a5f4: f20f 6148 addw r1, pc, #1608 ; 0x648 +1003a5f8: f7ea fb06 bl 10024c08 +1003a5fc: 2000 movs r0, #0 +1003a5fe: a903 add r1, sp, #12 + +1003a600 : +1003a600: aa05 add r2, sp, #20 +1003a602: f852 2020 ldr.w r2, [r2, r0, lsl #2] +1003a606: 5442 strb r2, [r0, r1] +1003a608: 1c40 adds r0, r0, #1 +1003a60a: 2805 cmp r0, #5 +1003a60c: dbf8 blt.n 1003a600 +1003a60e: 2000 movs r0, #0 +1003a610: 7148 strb r0, [r1, #5] +1003a612: 2241 movs r2, #65 ; 0x41 +1003a614: f000 f871 bl 1003a6fa + +1003a618 : +1003a618: 69a8 ldr r0, [r5, #24] +1003a61a: a903 add r1, sp, #12 +1003a61c: 3030 adds r0, #48 ; 0x30 +1003a61e: f7d1 fe99 bl 1000c354 +1003a622: 2005 movs r0, #5 +1003a624: e048 b.n 1003a6b8 + +1003a626 : +1003a626: f000 f86d bl 1003a704 + +1003a62a : +1003a62a: b158 cbz r0, 1003a644 +1003a62c: f000 f86a bl 1003a704 + +1003a630 : +1003a630: 2821 cmp r0, #33 ; 0x21 +1003a632: d207 bcs.n 1003a644 +1003a634: f000 f866 bl 1003a704 + +1003a638 : +1003a638: 7020 strb r0, [r4, #0] +1003a63a: 69a8 ldr r0, [r5, #24] +1003a63c: 7822 ldrb r2, [r4, #0] +1003a63e: f100 0110 add.w r1, r0, #16 +1003a642: e7c4 b.n 1003a5ce + +1003a644 : +1003a644: f20f 50cc addw r0, pc, #1484 ; 0x5cc +1003a648: f7d1 fe5b bl 1000c302 +1003a64c: f04f 30ff mov.w r0, #4294967295 +1003a650: e051 b.n 1003a6f6 + +1003a652 : +1003a652: 291a cmp r1, #26 +1003a654: d131 bne.n 1003a6ba +1003a656: a917 add r1, sp, #92 ; 0x5c +1003a658: 910a str r1, [sp, #40] ; 0x28 +1003a65a: ab0c add r3, sp, #48 ; 0x30 +1003a65c: a916 add r1, sp, #88 ; 0x58 +1003a65e: 9109 str r1, [sp, #36] ; 0x24 +1003a660: aa0b add r2, sp, #44 ; 0x2c +1003a662: a915 add r1, sp, #84 ; 0x54 +1003a664: 9108 str r1, [sp, #32] +1003a666: 3030 adds r0, #48 ; 0x30 +1003a668: a914 add r1, sp, #80 ; 0x50 +1003a66a: 9107 str r1, [sp, #28] +1003a66c: a913 add r1, sp, #76 ; 0x4c +1003a66e: 9106 str r1, [sp, #24] +1003a670: a912 add r1, sp, #72 ; 0x48 +1003a672: 9105 str r1, [sp, #20] +1003a674: a911 add r1, sp, #68 ; 0x44 +1003a676: 9104 str r1, [sp, #16] +1003a678: a910 add r1, sp, #64 ; 0x40 +1003a67a: 9103 str r1, [sp, #12] +1003a67c: a90f add r1, sp, #60 ; 0x3c +1003a67e: 9102 str r1, [sp, #8] +1003a680: a90e add r1, sp, #56 ; 0x38 +1003a682: 9101 str r1, [sp, #4] +1003a684: a90d add r1, sp, #52 ; 0x34 +1003a686: 9100 str r1, [sp, #0] +1003a688: f20f 51cc addw r1, pc, #1484 ; 0x5cc +1003a68c: f7ea fabc bl 10024c08 +1003a690: 2000 movs r0, #0 +1003a692: a918 add r1, sp, #96 ; 0x60 + +1003a694 : +1003a694: aa0b add r2, sp, #44 ; 0x2c +1003a696: f852 2020 ldr.w r2, [r2, r0, lsl #2] +1003a69a: 5442 strb r2, [r0, r1] +1003a69c: 1c40 adds r0, r0, #1 +1003a69e: 280d cmp r0, #13 +1003a6a0: dbf8 blt.n 1003a694 +1003a6a2: 2000 movs r0, #0 +1003a6a4: 7348 strb r0, [r1, #13] +1003a6a6: 2240 movs r2, #64 ; 0x40 +1003a6a8: f000 f827 bl 1003a6fa + +1003a6ac : +1003a6ac: 69a8 ldr r0, [r5, #24] +1003a6ae: a918 add r1, sp, #96 ; 0x60 +1003a6b0: 3030 adds r0, #48 ; 0x30 +1003a6b2: f7d1 fe4f bl 1000c354 +1003a6b6: 200d movs r0, #13 + +1003a6b8 : +1003a6b8: 6320 str r0, [r4, #48] ; 0x30 + +1003a6ba : +1003a6ba: 6ae1 ldr r1, [r4, #44] ; 0x2c +1003a6bc: f20f 50d0 addw r0, pc, #1488 ; 0x5d0 +1003a6c0: f7d1 fe1f bl 1000c302 +1003a6c4: 6b21 ldr r1, [r4, #48] ; 0x30 +1003a6c6: f20f 50e0 addw r0, pc, #1504 ; 0x5e0 +1003a6ca: f7d1 fe1a bl 1000c302 +1003a6ce: f20f 50f4 addw r0, pc, #1524 ; 0x5f4 +1003a6d2: 1c61 adds r1, r4, #1 +1003a6d4: f7d1 fe15 bl 1000c302 +1003a6d8: 7821 ldrb r1, [r4, #0] +1003a6da: f20f 50fc addw r0, pc, #1532 ; 0x5fc +1003a6de: f7d1 fe10 bl 1000c302 +1003a6e2: 68a9 ldr r1, [r5, #8] +1003a6e4: f20f 6008 addw r0, pc, #1544 ; 0x608 +1003a6e8: f7d1 fe0b bl 1000c302 +1003a6ec: f20f 6018 addw r0, pc, #1560 ; 0x618 +1003a6f0: f7d1 fe07 bl 1000c302 +1003a6f4: 2000 movs r0, #0 + +1003a6f6 : +1003a6f6: b01c add sp, #112 ; 0x70 +1003a6f8: bd70 pop {r4, r5, r6, pc} + +1003a6fa : +1003a6fa: 69a8 ldr r0, [r5, #24] +1003a6fc: 2100 movs r1, #0 +1003a6fe: 3030 adds r0, #48 ; 0x30 +1003a700: f7d1 be24 b.w 1000c34c + +1003a704 : +1003a704: 69a8 ldr r0, [r5, #24] +1003a706: 3010 adds r0, #16 +1003a708: f7d1 be26 b.w 1000c358 + +1003a70c : +1003a70c: b530 push {r4, r5, lr} +1003a70e: b0b1 sub sp, #196 ; 0xc4 +1003a710: 2403 movs r4, #3 +1003a712: a806 add r0, sp, #24 +1003a714: 2138 movs r1, #56 ; 0x38 +1003a716: f7eb f881 bl 1002581c <__aeabi_memclr4> +1003a71a: f8df 03ac ldr.w r0, [pc, #940] ; 1003aac8 +1003a71e: 6880 ldr r0, [r0, #8] +1003a720: b108 cbz r0, 1003a726 +1003a722: f88d 0014 strb.w r0, [sp, #20] + +1003a726 : +1003a726: f8df 13b0 ldr.w r1, [pc, #944] ; 1003aad8 +1003a72a: 2001 movs r0, #1 +1003a72c: f88d 0015 strb.w r0, [sp, #21] +1003a730: 7808 ldrb r0, [r1, #0] +1003a732: 1e40 subs r0, r0, #1 +1003a734: d007 beq.n 1003a746 +1003a736: 1e40 subs r0, r0, #1 +1003a738: d00f beq.n 1003a75a +1003a73a: 1e40 subs r0, r0, #1 +1003a73c: 2804 cmp r0, #4 +1003a73e: d90e bls.n 1003a75e +1003a740: 1f80 subs r0, r0, #6 +1003a742: d00a beq.n 1003a75a +1003a744: e00e b.n 1003a764 + +1003a746 : +1003a746: 22ff movs r2, #255 ; 0xff +1003a748: 700a strb r2, [r1, #0] +1003a74a: a906 add r1, sp, #24 +1003a74c: f7ff ff03 bl 1003a556 +1003a750: f110 0f01 cmn.w r0, #1 +1003a754: d10e bne.n 1003a774 +1003a756: 2002 movs r0, #2 +1003a758: e04b b.n 1003a7f2 + +1003a75a : +1003a75a: 2001 movs r0, #1 +1003a75c: e7f3 b.n 1003a746 + +1003a75e : +1003a75e: f8df 0370 ldr.w r0, [pc, #880] ; 1003aad0 +1003a762: e7f0 b.n 1003a746 + +1003a764 : +1003a764: f20f 50cc addw r0, pc, #1484 ; 0x5cc +1003a768: f7d1 fdcb bl 1000c302 +1003a76c: f04f 30ff mov.w r0, #4294967295 +1003a770: e03f b.n 1003a7f2 + +1003a772 : +1003a772: 1e64 subs r4, r4, #1 + +1003a774 : +1003a774: 2201 movs r2, #1 +1003a776: f10d 0115 add.w r1, sp, #21 +1003a77a: a805 add r0, sp, #20 +1003a77c: f7fe febe bl 100394fc +1003a780: 2800 cmp r0, #0 +1003a782: d505 bpl.n 1003a790 +1003a784: f20f 50d4 addw r0, pc, #1492 ; 0x5d4 +1003a788: f7d1 fdbb bl 1000c302 +1003a78c: 2003 movs r0, #3 +1003a78e: e030 b.n 1003a7f2 + +1003a790 : +1003a790: 2000 movs r0, #0 +1003a792: 9004 str r0, [sp, #16] +1003a794: f10d 0119 add.w r1, sp, #25 +1003a798: 9813 ldr r0, [sp, #76] ; 0x4c +1003a79a: 9b11 ldr r3, [sp, #68] ; 0x44 +1003a79c: 9a10 ldr r2, [sp, #64] ; 0x40 +1003a79e: 9003 str r0, [sp, #12] +1003a7a0: 9812 ldr r0, [sp, #72] ; 0x48 +1003a7a2: 9002 str r0, [sp, #8] +1003a7a4: f89d 0018 ldrb.w r0, [sp, #24] +1003a7a8: 9001 str r0, [sp, #4] +1003a7aa: 2006 movs r0, #6 +1003a7ac: 9000 str r0, [sp, #0] +1003a7ae: 48cb ldr r0, [pc, #812] ; (1003aadc ) +1003a7b0: f7fe fb12 bl 10038dd8 +1003a7b4: b9d0 cbnz r0, 1003a7ec +1003a7b6: 2103 movs r1, #3 +1003a7b8: f7d0 f9ae bl 1000ab18 +1003a7bc: 2100 movs r1, #0 +1003a7be: 2000 movs r0, #0 +1003a7c0: f7ff fa25 bl 10039c0e +1003a7c4: 4604 mov r4, r0 +1003a7c6: 2101 movs r1, #1 +1003a7c8: 2000 movs r0, #0 +1003a7ca: f7d0 f9a5 bl 1000ab18 +1003a7ce: f20f 354c addw r5, pc, #844 ; 0x34c +1003a7d2: a914 add r1, sp, #80 ; 0x50 +1003a7d4: 4628 mov r0, r5 +1003a7d6: f7fe fe9a bl 1003950e +1003a7da: a914 add r1, sp, #80 ; 0x50 +1003a7dc: 4628 mov r0, r5 +1003a7de: f7fe fef3 bl 100395c8 +1003a7e2: 2c02 cmp r4, #2 +1003a7e4: bf14 ite ne +1003a7e6: 2005 movne r0, #5 +1003a7e8: 2007 moveq r0, #7 +1003a7ea: e002 b.n 1003a7f2 + +1003a7ec : +1003a7ec: 2c00 cmp r4, #0 +1003a7ee: d1c0 bne.n 1003a772 +1003a7f0: 2004 movs r0, #4 + +1003a7f2 : +1003a7f2: b031 add sp, #196 ; 0xc4 +1003a7f4: bd30 pop {r4, r5, pc} + +1003a7f6 : +1003a7f6: b5f8 push {r3, r4, r5, r6, r7, lr} +1003a7f8: 4604 mov r4, r0 +1003a7fa: 460d mov r5, r1 +1003a7fc: 4616 mov r6, r2 +1003a7fe: f7d0 fd17 bl 1000b230 +1003a802: 4fb1 ldr r7, [pc, #708] ; (1003aac8 ) +1003a804: 6838 ldr r0, [r7, #0] +1003a806: 2801 cmp r0, #1 +1003a808: d108 bne.n 1003a81c +1003a80a: 69b8 ldr r0, [r7, #24] +1003a80c: 9000 str r0, [sp, #0] +1003a80e: 4633 mov r3, r6 +1003a810: 462a mov r2, r5 +1003a812: 1da1 adds r1, r4, #6 +1003a814: 4620 mov r0, r4 +1003a816: f002 fba4 bl 1003cf62 +1003a81a: 6138 str r0, [r7, #16] + +1003a81c : +1003a81c: e8bd 40f1 ldmia.w sp!, {r0, r4, r5, r6, r7, lr} +1003a820: f7d0 bd12 b.w 1000b248 + +1003a824 : +1003a824: b538 push {r3, r4, r5, lr} +1003a826: 4605 mov r5, r0 +1003a828: 4ca7 ldr r4, [pc, #668] ; (1003aac8 ) +1003a82a: 2001 movs r0, #1 +1003a82c: 6020 str r0, [r4, #0] +1003a82e: 2220 movs r2, #32 +1003a830: 2000 movs r0, #0 +1003a832: 6060 str r0, [r4, #4] +1003a834: 60a0 str r0, [r4, #8] +1003a836: 6120 str r0, [r4, #16] +1003a838: 2100 movs r1, #0 +1003a83a: f104 0020 add.w r0, r4, #32 +1003a83e: f7d5 fffb bl 10010838 +1003a842: 2000 movs r0, #0 +1003a844: 60e0 str r0, [r4, #12] +1003a846: f7d0 fa58 bl 1000acfa +1003a84a: 61e0 str r0, [r4, #28] +1003a84c: 6960 ldr r0, [r4, #20] +1003a84e: b118 cbz r0, 1003a858 +1003a850: f7d2 f8b7 bl 1000c9c2 +1003a854: 2000 movs r0, #0 +1003a856: 6160 str r0, [r4, #20] + +1003a858 : +1003a858: 2050 movs r0, #80 ; 0x50 +1003a85a: f7d2 f82b bl 1000c8b4 +1003a85e: 6160 str r0, [r4, #20] +1003a860: b918 cbnz r0, 1003a86a +1003a862: f20f 5024 addw r0, pc, #1316 ; 0x524 +1003a866: f7d1 fd4c bl 1000c302 + +1003a86a : +1003a86a: 2250 movs r2, #80 ; 0x50 +1003a86c: 6960 ldr r0, [r4, #20] +1003a86e: f000 f828 bl 1003a8c2 + +1003a872 : +1003a872: 2d00 cmp r5, #0 +1003a874: f44f 602b mov.w r0, #2736 ; 0xab0 +1003a878: d00c beq.n 1003a894 +1003a87a: f7d2 f81b bl 1000c8b4 +1003a87e: 61a0 str r0, [r4, #24] +1003a880: b160 cbz r0, 1003a89c +1003a882: f000 f81c bl 1003a8be + +1003a886 : +1003a886: 4628 mov r0, r5 +1003a888: f002 fae2 bl 1003ce50 +1003a88c: 2800 cmp r0, #0 +1003a88e: d40f bmi.n 1003a8b0 + +1003a890 : +1003a890: 2000 movs r0, #0 +1003a892: bd32 pop {r1, r4, r5, pc} + +1003a894 : +1003a894: f7d2 f80e bl 1000c8b4 +1003a898: 61a0 str r0, [r4, #24] +1003a89a: b910 cbnz r0, 1003a8a2 + +1003a89c : +1003a89c: f20f 500c addw r0, pc, #1292 ; 0x50c +1003a8a0: e008 b.n 1003a8b4 + +1003a8a2 : +1003a8a2: f000 f80c bl 1003a8be + +1003a8a6 : +1003a8a6: 2000 movs r0, #0 +1003a8a8: f002 fad2 bl 1003ce50 +1003a8ac: 2800 cmp r0, #0 +1003a8ae: d5ef bpl.n 1003a890 + +1003a8b0 : +1003a8b0: f20f 5018 addw r0, pc, #1304 ; 0x518 + +1003a8b4 : +1003a8b4: f7d1 fd25 bl 1000c302 +1003a8b8: f04f 30ff mov.w r0, #4294967295 +1003a8bc: bd32 pop {r1, r4, r5, pc} + +1003a8be : +1003a8be: f44f 622b mov.w r2, #2736 ; 0xab0 + +1003a8c2 : +1003a8c2: 2100 movs r1, #0 +1003a8c4: f7d1 bd42 b.w 1000c34c + +1003a8c8 : +1003a8c8: b510 push {r4, lr} +1003a8ca: f002 fb38 bl 1003cf3e +1003a8ce: 4c7e ldr r4, [pc, #504] ; (1003aac8 ) +1003a8d0: 69a0 ldr r0, [r4, #24] +1003a8d2: b118 cbz r0, 1003a8dc +1003a8d4: f7d2 f875 bl 1000c9c2 +1003a8d8: 2000 movs r0, #0 +1003a8da: 61a0 str r0, [r4, #24] + +1003a8dc : +1003a8dc: 6960 ldr r0, [r4, #20] +1003a8de: b118 cbz r0, 1003a8e8 +1003a8e0: f7d2 f86f bl 1000c9c2 +1003a8e4: 2000 movs r0, #0 +1003a8e6: 6160 str r0, [r4, #20] + +1003a8e8 : +1003a8e8: bd10 pop {r4, pc} + +1003a8ea : +1003a8ea: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1003a8ee: 2500 movs r5, #0 +1003a8f0: 2201 movs r2, #1 +1003a8f2: 2601 movs r6, #1 +1003a8f4: 2407 movs r4, #7 +1003a8f6: 46a9 mov r9, r5 +1003a8f8: 4979 ldr r1, [pc, #484] ; (1003aae0 ) +1003a8fa: 4610 mov r0, r2 +1003a8fc: f7fe febb bl 10039676 +1003a900: f7d0 f9fb bl 1000acfa +1003a904: 4682 mov sl, r0 +1003a906: a06e add r0, pc, #440 ; (adr r0, 1003aac0 ) +1003a908: f7d1 fcfb bl 1000c302 +1003a90c: 4630 mov r0, r6 +1003a90e: f7fe fbb7 bl 10039080 +1003a912: f20f 5b20 addw fp, pc, #1312 ; 0x520 +1003a916: 4f6c ldr r7, [pc, #432] ; (1003aac8 ) +1003a918: f44f 787a mov.w r8, #1000 ; 0x3e8 +1003a91c: e00a b.n 1003a934 + +1003a91e : +1003a91e: 4630 mov r0, r6 +1003a920: f7fe fbae bl 10039080 +1003a924: b930 cbnz r0, 1003a934 +1003a926: f7d0 f9e8 bl 1000acfa +1003a92a: 4682 mov sl, r0 +1003a92c: 4631 mov r1, r6 +1003a92e: 4658 mov r0, fp +1003a930: f7d1 fce7 bl 1000c302 + +1003a934 : +1003a934: 2032 movs r0, #50 ; 0x32 +1003a936: f7d0 f8cc bl 1000aad2 +1003a93a: f7d0 f9de bl 1000acfa +1003a93e: 69f9 ldr r1, [r7, #28] +1003a940: 1a40 subs r0, r0, r1 +1003a942: f109 0178 add.w r1, r9, #120 ; 0x78 +1003a946: fb08 f101 mul.w r1, r8, r1 +1003a94a: 4288 cmp r0, r1 +1003a94c: d24b bcs.n 1003a9e6 +1003a94e: f7d0 f9d4 bl 1000acfa +1003a952: eba0 000a sub.w r0, r0, sl +1003a956: fb08 f000 mul.w r0, r8, r0 +1003a95a: fbb0 f0f8 udiv r0, r0, r8 +1003a95e: 2864 cmp r0, #100 ; 0x64 +1003a960: 6878 ldr r0, [r7, #4] +1003a962: d307 bcc.n 1003a974 +1003a964: 2801 cmp r0, #1 +1003a966: d013 beq.n 1003a990 +1003a968: 1c76 adds r6, r6, #1 +1003a96a: 1e70 subs r0, r6, #1 +1003a96c: 280d cmp r0, #13 +1003a96e: d3d6 bcc.n 1003a91e +1003a970: 2601 movs r6, #1 +1003a972: e7d4 b.n 1003a91e + +1003a974 : +1003a974: b960 cbnz r0, 1003a990 +1003a976: f107 020c add.w r2, r7, #12 +1003a97a: f107 0120 add.w r1, r7, #32 +1003a97e: 4857 ldr r0, [pc, #348] ; (1003aadc ) +1003a980: f7f8 ff77 bl 10033872 +1003a984: b120 cbz r0, 1003a990 +1003a986: 2101 movs r1, #1 +1003a988: 6079 str r1, [r7, #4] +1003a98a: 60b8 str r0, [r7, #8] +1003a98c: f7fe fb78 bl 10039080 + +1003a990 : +1003a990: 6938 ldr r0, [r7, #16] +1003a992: 2801 cmp r0, #1 +1003a994: d103 bne.n 1003a99e +1003a996: 2000 movs r0, #0 +1003a998: 2501 movs r5, #1 +1003a99a: 6078 str r0, [r7, #4] +1003a99c: e024 b.n 1003a9e8 + +1003a99e : +1003a99e: f110 0f01 cmn.w r0, #1 +1003a9a2: d117 bne.n 1003a9d4 +1003a9a4: f20f 4038 addw r0, pc, #1080 ; 0x438 +1003a9a8: f7d1 fcab bl 1000c302 +1003a9ac: f04f 093c mov.w r9, #60 ; 0x3c +1003a9b0: 2001 movs r0, #1 +1003a9b2: f7fe fb65 bl 10039080 +1003a9b6: 607d str r5, [r7, #4] +1003a9b8: 60bd str r5, [r7, #8] +1003a9ba: 2220 movs r2, #32 +1003a9bc: 2100 movs r1, #0 +1003a9be: f107 0020 add.w r0, r7, #32 +1003a9c2: f7d1 fcc3 bl 1000c34c +1003a9c6: 60fd str r5, [r7, #12] +1003a9c8: 613d str r5, [r7, #16] +1003a9ca: 20ff movs r0, #255 ; 0xff +1003a9cc: 4942 ldr r1, [pc, #264] ; (1003aad8 ) +1003a9ce: 7008 strb r0, [r1, #0] +1003a9d0: f002 fa1e bl 1003ce10 + +1003a9d4 : +1003a9d4: 6938 ldr r0, [r7, #16] +1003a9d6: f110 0f02 cmn.w r0, #2 +1003a9da: d1ab bne.n 1003a934 +1003a9dc: f20f 4030 addw r0, pc, #1072 ; 0x430 +1003a9e0: f7d1 fc8f bl 1000c302 +1003a9e4: e000 b.n 1003a9e8 + +1003a9e6 : +1003a9e6: 2401 movs r4, #1 + +1003a9e8 : +1003a9e8: 2100 movs r1, #0 +1003a9ea: 2200 movs r2, #0 +1003a9ec: 4608 mov r0, r1 +1003a9ee: f7fe fe42 bl 10039676 +1003a9f2: b155 cbz r5, 1003aa0a +1003a9f4: f7ff fe8a bl 1003a70c +1003a9f8: 2807 cmp r0, #7 +1003a9fa: d10a bne.n 1003aa12 +1003a9fc: f7ff fd6f bl 1003a4de +1003aa00: f110 0f01 cmn.w r0, #1 +1003aa04: d102 bne.n 1003aa0c +1003aa06: 2406 movs r4, #6 +1003aa08: e000 b.n 1003aa0c + +1003aa0a : +1003aa0a: 2401 movs r4, #1 + +1003aa0c : +1003aa0c: f7ff ff5c bl 1003a8c8 +1003aa10: 4620 mov r0, r4 + +1003aa12 : +1003aa12: e8bd 8ff2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1003aa16 : +1003aa16: b500 push {lr} +1003aa18: f20f 4134 addw r1, pc, #1076 ; 0x434 +1003aa1c: 680a ldr r2, [r1, #0] +1003aa1e: f20f 4134 addw r1, pc, #1076 ; 0x434 +1003aa22: b085 sub sp, #20 +1003aa24: a804 add r0, sp, #16 +1003aa26: 6002 str r2, [r0, #0] +1003aa28: a803 add r0, sp, #12 +1003aa2a: 680a ldr r2, [r1, #0] +1003aa2c: 6002 str r2, [r0, #0] +1003aa2e: 2000 movs r0, #0 +1003aa30: f8ad 0000 strh.w r0, [sp] +1003aa34: 2003 movs r0, #3 +1003aa36: f8ad 0002 strh.w r0, [sp, #2] +1003aa3a: a804 add r0, sp, #16 +1003aa3c: 9001 str r0, [sp, #4] +1003aa3e: a803 add r0, sp, #12 +1003aa40: 9002 str r0, [sp, #8] +1003aa42: f7fe fee5 bl 10039810 +1003aa46: 2200 movs r2, #0 +1003aa48: a900 add r1, sp, #0 +1003aa4a: 2001 movs r0, #1 +1003aa4c: f7fe fee2 bl 10039814 +1003aa50: 2001 movs r0, #1 +1003aa52: f7fe fee1 bl 10039818 +1003aa56: b005 add sp, #20 +1003aa58: bd00 pop {pc} + +1003aa5a : +1003aa5a: b580 push {r7, lr} +1003aa5c: 2001 movs r0, #1 +1003aa5e: f7fe fedd bl 1003981c +1003aa62: e8bd 4002 ldmia.w sp!, {r1, lr} +1003aa66: 2001 movs r0, #1 +1003aa68: f7fe beda b.w 10039820 + +1003aa6c : +1003aa6c: b510 push {r4, lr} +1003aa6e: 4604 mov r4, r0 +1003aa70: a014 add r0, pc, #80 ; (adr r0, 1003aac4 ) +1003aa72: f7d1 fc46 bl 1000c302 +1003aa76: 1e64 subs r4, r4, #1 +1003aa78: 2c06 cmp r4, #6 +1003aa7a: d81a bhi.n 1003aab2 +1003aa7c: e8df f004 tbb [pc, r4] + +1003aa80 : +1003aa80: 0704 0d0a 1310 0016 ........ + +1003aa88 : +1003aa88: f20f 30cc addw r0, pc, #972 ; 0x3cc +1003aa8c: e013 b.n 1003aab6 + +1003aa8e : +1003aa8e: f20f 4008 addw r0, pc, #1032 ; 0x408 +1003aa92: e010 b.n 1003aab6 + +1003aa94 : +1003aa94: f20f 4044 addw r0, pc, #1092 ; 0x444 +1003aa98: e00d b.n 1003aab6 + +1003aa9a : +1003aa9a: f20f 4070 addw r0, pc, #1136 ; 0x470 +1003aa9e: e00a b.n 1003aab6 + +1003aaa0 : +1003aaa0: f20f 4088 addw r0, pc, #1160 ; 0x488 +1003aaa4: e007 b.n 1003aab6 + +1003aaa6 : +1003aaa6: f20f 40b4 addw r0, pc, #1204 ; 0x4b4 +1003aaaa: e004 b.n 1003aab6 + +1003aaac : +1003aaac: f20f 40d8 addw r0, pc, #1240 ; 0x4d8 +1003aab0: e001 b.n 1003aab6 + +1003aab2 : +1003aab2: f20f 40ec addw r0, pc, #1260 ; 0x4ec + +1003aab6 : +1003aab6: e8bd 4010 ldmia.w sp!, {r4, lr} +1003aaba: f7d1 bc22 b.w 1000c302 + ... + +1003aac0 : +1003aac0: 0d0a 0000 .... + +1003aac4 : +1003aac4: 0a0d 0000 .... + +1003aac8 : +1003aac8: 80f4 1004 .... + +1003aacc : +1003aacc: 7824 1004 $x.. + +1003aad0 : +1003aad0: 0004 0040 ..@. + +1003aad4 : +1003aad4: 0004 0020 .. . + +1003aad8 : +1003aad8: 4170 1004 pA.. + +1003aadc : +1003aadc: 419c 1004 .A.. + +1003aae0 : +1003aae0: a7f7 1003 .... + +1003aae4 : +1003aae4: b510 push {r4, lr} +1003aae6: 2400 movs r4, #0 +1003aae8: 2803 cmp r0, #3 +1003aaea: db04 blt.n 1003aaf6 +1003aaec: f20f 40d4 addw r0, pc, #1236 ; 0x4d4 +1003aaf0: f7d1 fc07 bl 1000c302 +1003aaf4: e002 b.n 1003aafc + +1003aaf6 : +1003aaf6: 2802 cmp r0, #2 +1003aaf8: bf08 it eq +1003aafa: 684c ldreq r4, [r1, #4] + +1003aafc : +1003aafc: f7fe fdbd bl 1003967a +1003ab00: 4620 mov r0, r4 +1003ab02: f7ff fe8f bl 1003a824 +1003ab06: b940 cbnz r0, 1003ab1a +1003ab08: f7ff ff85 bl 1003aa16 +1003ab0c: f7ff feed bl 1003a8ea +1003ab10: f7ff ffac bl 1003aa6c +1003ab14: e8bd 4010 ldmia.w sp!, {r4, lr} +1003ab18: e79f b.n 1003aa5a + +1003ab1a : +1003ab1a: bd10 pop {r4, pc} + +1003ab1c : +1003ab1c: 6c77 6e61 0030 0000 wlan0... + +1003ab24 : +1003ab24: 0a0d 6977 6966 3e2d 6573 7563 6972 7974 ..wifi->security +1003ab34: 745f 7079 2065 203d 5452 5f57 4553 5543 _type = RTW_SECU +1003ab44: 4952 5954 575f 4150 5f32 4541 5f53 5350 RITY_WPA2_AES_PS +1003ab54: 0a4b 0000 K... + +1003ab58 : +1003ab58: 0a0d 6977 6966 3e2d 6573 7563 6972 7974 ..wifi->security +1003ab68: 745f 7079 2065 203d 5452 5f57 4553 5543 _type = RTW_SECU +1003ab78: 4952 5954 575f 5045 505f 4b53 000a 0000 RITY_WEP_PSK.... + +1003ab88 : +1003ab88: 0a0d 6977 6966 3e2d 6573 7563 6972 7974 ..wifi->security +1003ab98: 745f 7079 2065 203d 5452 5f57 4553 5543 _type = RTW_SECU +1003aba8: 4952 5954 575f 4150 415f 5345 505f 4b53 RITY_WPA_AES_PSK +1003abb8: 000a 0000 .... + +1003abbc : +1003abbc: 0a0d 6977 6966 3e2d 6573 7563 6972 7974 ..wifi->security +1003abcc: 745f 7079 2065 203d 5452 5f57 4553 5543 _type = RTW_SECU +1003abdc: 4952 5954 4f5f 4550 0a4e 0000 RITY_OPEN... + +1003abe8 : +1003abe8: 0a0d 3d3d 3d3d 3d3d 203d 6f43 6e6e 6365 ..======= Connec +1003abf8: 6974 6e6f 4920 666e 726f 616d 6974 6e6f tion Information +1003ac08: 3d20 3d3d 3d3d 3d3d 000a 0000 =======.... + +1003ac14 : +1003ac14: 0a0d 5320 4953 2044 7369 4e20 4c55 204c .. SSID is NULL +1003ac24: 726f 5320 4953 2044 656c 676e 6874 6920 or SSID length i +1003ac34: 2073 766f 7265 3320 2132 0021 s over 32!!. + +1003ac40 : +1003ac40: 3025 7832 3025 7832 3025 7832 3025 7832 %02x%02x%02x%02x +1003ac50: 3025 7832 0000 0000 %02x.... + +1003ac58 : +1003ac58: 3025 7832 3025 7832 3025 7832 3025 7832 %02x%02x%02x%02x +1003ac68: 3025 7832 3025 7832 3025 7832 3025 7832 %02x%02x%02x%02x +1003ac78: 3025 7832 3025 7832 3025 7832 3025 7832 %02x%02x%02x%02x +1003ac88: 3025 7832 0000 0000 %02x.... + +1003ac90 : +1003ac90: 0a0d 6977 6966 702e 7361 7773 726f 2064 ..wifi.password +1003aca0: 203d 7325 000a 0000 = %s.... + +1003aca8 : +1003aca8: 0a0d 6977 6966 702e 7361 7773 726f 5f64 ..wifi.password_ +1003acb8: 656c 206e 203d 6425 000a 0000 len = %d.... + +1003acc4 : +1003acc4: 0a0d 6977 6966 732e 6973 2064 203d 7325 ..wifi.ssid = %s +1003acd4: 000a 0000 .... + +1003acd8 : +1003acd8: 0a0d 6977 6966 732e 6973 5f64 656c 206e ..wifi.ssid_len +1003ace8: 203d 6425 000a 0000 = %d.... + +1003acf0 : +1003acf0: 0a0d 6977 6966 632e 6168 6e6e 6c65 3d20 ..wifi.channel = +1003ad00: 2520 0a64 0000 0000 %d..... + +1003ad08 : +1003ad08: 0a0d 3d3d 3d3d 203d 7473 7261 2074 6f74 ..===== start to +1003ad18: 6320 6e6f 656e 7463 7420 7261 6567 2074 connect target +1003ad28: 5041 3d20 3d3d 3d3d 000a 0000 AP =====.... + +1003ad34 : +1003ad34: 0a0d 7520 6b6e 6f6e 2077 6573 7563 6972 .. unknow securi +1003ad44: 7974 6d20 646f 2c65 6f63 6e6e 6365 2074 ty mode,connect +1003ad54: 6166 6c69 0021 0000 fail!... + +1003ad5c : +1003ad5c: 0d0a 5245 4f52 3a52 7720 6669 2069 6573 ..ERROR: wifi se +1003ad6c: 2074 6170 7472 6169 206c 6373 6e61 6320 t partial scan c +1003ad7c: 6168 6e6e 6c65 6620 6961 006c hannel fail. + +1003ad88 : +1003ad88: 0d0a 7472 5f6b 6373 695f 696e 2074 6166 ..rtk_sc_init fa +1003ad98: 6c69 6220 2079 6c61 6f6c 6163 6574 6120 il by allocate a +1003ada8: 6b63 000a ck.. + +1003adac : +1003adac: 0d0a 4d5b 6d65 6d5d 6c61 6f6c 2063 4353 ..[Mem]malloc SC +1003adbc: 6320 6e6f 6574 7478 6620 6961 0a6c 0000 context fail... + +1003adcc : +1003adcc: 0d0a 7452 5f6b 6373 695f 696e 2074 6166 ..Rtk_sc_init fa +1003addc: 6c69 000a il.. + +1003ade0 : +1003ade0: 0a0d 6973 706d 656c 635f 6e6f 6966 5f67 ..simple_config_ +1003adf0: 6574 7473 7220 7365 6174 7472 6620 726f test restart for +1003ae00: 7220 7365 6c75 2074 203d 312d 0000 0000 result = -1.... + +1003ae10 : +1003ae10: 0d0a 6854 2065 5041 2050 726f 6320 696c ..The APP or cli +1003ae20: 6e65 2074 756d 7473 6820 7661 2065 6970 ent must have pi +1003ae30: 216e 000a n!.. + +1003ae34 : +1003ae34: 0d0a 7753 7469 6863 7420 206f 6863 6e61 ..Switch to chan +1003ae44: 656e 286c 6425 0a29 0000 0000 nel(%d)..... + +1003ae50 : +1003ae50: ffff 00ff .... + +1003ae54 : +1003ae54: 0001 005e ..^. + +1003ae58 : +1003ae58: 6953 706d 656c 4320 6e6f 6966 2067 6974 Simple Config ti +1003ae68: 656d 756f 2174 2021 6143 276e 2074 6567 meout!! Can't ge +1003ae78: 2074 7041 7020 6f72 6966 656c 202e 6c50 t Ap profile. Pl +1003ae88: 6165 6573 7420 7972 6120 6167 6e69 000a ease try again.. + +1003ae98 : +1003ae98: 6953 706d 656c 4320 6e6f 6966 2067 6166 Simple Config fa +1003aea8: 6c69 202c 6163 6e6e 746f 7020 7261 6573 il, cannot parse +1003aeb8: 7420 7261 6567 2074 7061 6920 666e 206f target ap info +1003aec8: 7266 6d6f 6320 6e6f 7274 6c6f 656c 0a72 from controller. +1003aed8: 0000 0000 .... + +1003aedc : +1003aedc: 6953 706d 656c 4320 6e6f 6966 2067 6163 Simple Config ca +1003aeec: 6e6e 746f 7320 6163 206e 6874 2065 6174 nnot scan the ta +1003aefc: 6772 7465 6320 6168 6e6e 6c65 000a 0000 rget channel.... + +1003af0c : +1003af0c: 6953 706d 656c 4320 6e6f 6966 2067 6f4a Simple Config Jo +1003af1c: 6e69 6220 7373 6620 6961 656c 0a64 0000 in bss failed... + +1003af2c : +1003af2c: 6953 706d 656c 4320 6e6f 6966 2067 6166 Simple Config fa +1003af3c: 6c69 202c 6163 6e6e 746f 6720 7465 6420 il, cannot get d +1003af4c: 6368 2070 7069 6120 6464 6572 7373 000a hcp ip address.. + +1003af5c : +1003af5c: 6953 706d 656c 4320 6e6f 6966 2067 6341 Simple Config Ac +1003af6c: 206b 6f73 6b63 7465 6320 6572 7461 2065 k socket create +1003af7c: 6166 6c69 2121 0a21 0000 0000 fail!!!..... + +1003af88 : +1003af88: 6953 706d 656c 4320 6e6f 6966 2067 7573 Simple Config su +1003af98: 6363 7365 0a73 0000 ccess... + +1003afa0 : +1003afa0: 6e75 6e6b 776f 206e 7265 6f72 2072 6877 unknown error wh +1003afb0: 6e65 7320 6d69 6c70 2065 6f63 666e 6769 en simple config +1003afc0: 0a21 0000 !... + +1003afc4 : +1003afc4: 0d0a 6e49 7570 2074 7245 6f72 2172 0000 ..Input Error!.. + +1003afd4 : +1003afd4: b510 push {r4, lr} +1003afd6: b09c sub sp, #112 ; 0x70 +1003afd8: 2100 movs r1, #0 +1003afda: 2000 movs r0, #0 +1003afdc: f7fe fe17 bl 10039c0e +1003afe0: f20f 4480 addw r4, pc, #1152 ; 0x480 +1003afe4: a900 add r1, sp, #0 +1003afe6: 4620 mov r0, r4 +1003afe8: f7fe fa91 bl 1003950e +1003afec: a900 add r1, sp, #0 +1003afee: 4620 mov r0, r4 +1003aff0: f7fe faea bl 100395c8 +1003aff4: b01c add sp, #112 ; 0x70 +1003aff6: bd10 pop {r4, pc} + +1003aff8 : +1003aff8: b538 push {r3, r4, r5, lr} +1003affa: 4604 mov r4, r0 +1003affc: 6c20 ldr r0, [r4, #64] ; 0x40 +1003affe: 6c65 ldr r5, [r4, #68] ; 0x44 +1003b000: 2801 cmp r0, #1 +1003b002: d02f beq.n 1003b064 +1003b004: 7821 ldrb r1, [r4, #0] +1003b006: 1909 adds r1, r1, r4 +1003b008: 2000 movs r0, #0 +1003b00a: 7048 strb r0, [r1, #1] +1003b00c: 6b60 ldr r0, [r4, #52] ; 0x34 +1003b00e: 6c65 ldr r5, [r4, #68] ; 0x44 +1003b010: 28ff cmp r0, #255 ; 0xff +1003b012: d02f beq.n 1003b074 +1003b014: 88a9 ldrh r1, [r5, #4] +1003b016: f8df 2434 ldr.w r2, [pc, #1076] ; 1003b44c +1003b01a: 2980 cmp r1, #128 ; 0x80 +1003b01c: d110 bne.n 1003b040 +1003b01e: 2804 cmp r0, #4 +1003b020: d128 bne.n 1003b074 +1003b022: 7010 strb r0, [r2, #0] +1003b024: 68e8 ldr r0, [r5, #12] +1003b026: 1c40 adds r0, r0, #1 +1003b028: 60e8 str r0, [r5, #12] +1003b02a: d123 bne.n 1003b074 +1003b02c: 7822 ldrb r2, [r4, #0] +1003b02e: 6828 ldr r0, [r5, #0] +1003b030: 1c61 adds r1, r4, #1 +1003b032: f7d1 f989 bl 1000c348 +1003b036: f000 f81f bl 1003b078 + +1003b03a : +1003b03a: f20f 50f8 addw r0, pc, #1528 ; 0x5f8 +1003b03e: e00e b.n 1003b05e + +1003b040 : +1003b040: 2908 cmp r1, #8 +1003b042: bf08 it eq +1003b044: 2800 cmpeq r0, #0 +1003b046: d115 bne.n 1003b074 +1003b048: 60e8 str r0, [r5, #12] +1003b04a: 7010 strb r0, [r2, #0] +1003b04c: 1c61 adds r1, r4, #1 +1003b04e: 7822 ldrb r2, [r4, #0] +1003b050: 6828 ldr r0, [r5, #0] +1003b052: f7d1 f979 bl 1000c348 +1003b056: f000 f80f bl 1003b078 + +1003b05a : +1003b05a: f20f 6000 addw r0, pc, #1536 ; 0x600 + +1003b05e : +1003b05e: f7d1 f950 bl 1000c302 +1003b062: e007 b.n 1003b074 + +1003b064 : +1003b064: f20f 6020 addw r0, pc, #1568 ; 0x620 +1003b068: f7d1 f94b bl 1000c302 +1003b06c: f105 0008 add.w r0, r5, #8 +1003b070: f7d5 fc0d bl 1001088e + +1003b074 : +1003b074: 2000 movs r0, #0 +1003b076: bd32 pop {r1, r4, r5, pc} + +1003b078 : +1003b078: 6829 ldr r1, [r5, #0] +1003b07a: 7822 ldrb r2, [r4, #0] +1003b07c: 2000 movs r0, #0 +1003b07e: 5450 strb r0, [r2, r1] +1003b080: 6829 ldr r1, [r5, #0] +1003b082: 4770 bx lr + +1003b084 : +1003b084: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} +1003b088: b0c3 sub sp, #268 ; 0x10c +1003b08a: 4604 mov r4, r0 +1003b08c: 460f mov r7, r1 +1003b08e: 461d mov r5, r3 +1003b090: a804 add r0, sp, #16 +1003b092: 2138 movs r1, #56 ; 0x38 +1003b094: f7ea fbc2 bl 1002581c <__aeabi_memclr4> +1003b098: f7d5 fc79 bl 1001098e +1003b09c: 4680 mov r8, r0 +1003b09e: 2284 movs r2, #132 ; 0x84 +1003b0a0: 2100 movs r1, #0 +1003b0a2: a822 add r0, sp, #136 ; 0x88 +1003b0a4: f7d1 f952 bl 1000c34c +1003b0a8: 2240 movs r2, #64 ; 0x40 +1003b0aa: 2100 movs r1, #0 +1003b0ac: a812 add r0, sp, #72 ; 0x48 +1003b0ae: f7d1 f94d bl 1000c34c +1003b0b2: 4621 mov r1, r4 +1003b0b4: f8df 6394 ldr.w r6, [pc, #916] ; 1003b44c +1003b0b8: 2980 cmp r1, #128 ; 0x80 +1003b0ba: d126 bne.n 1003b10a +1003b0bc: 8074 strh r4, [r6, #2] + +1003b0be : +1003b0be: 2d00 cmp r5, #0 +1003b0c0: d153 bne.n 1003b16a + +1003b0c2 : +1003b0c2: f7d5 fc64 bl 1001098e +1003b0c6: eba0 0008 sub.w r0, r0, r8 +1003b0ca: f7d5 fc70 bl 100109ae +1003b0ce: 2878 cmp r0, #120 ; 0x78 +1003b0d0: d246 bcs.n 1003b160 +1003b0d2: a800 add r0, sp, #0 +1003b0d4: 2110 movs r1, #16 +1003b0d6: f7ea fba1 bl 1002581c <__aeabi_memclr4> +1003b0da: 20ff movs r0, #255 ; 0xff +1003b0dc: 7030 strb r0, [r6, #0] +1003b0de: f8ad 4004 strh.w r4, [sp, #4] +1003b0e2: f04f 30ff mov.w r0, #4294967295 +1003b0e6: 9003 str r0, [sp, #12] +1003b0e8: 2100 movs r1, #0 +1003b0ea: a812 add r0, sp, #72 ; 0x48 +1003b0ec: 9000 str r0, [sp, #0] +1003b0ee: a802 add r0, sp, #8 +1003b0f0: f7d5 fbbf bl 10010872 +1003b0f4: 9802 ldr r0, [sp, #8] +1003b0f6: 2800 cmp r0, #0 +1003b0f8: d0e3 beq.n 1003b0c2 +1003b0fa: a900 add r1, sp, #0 +1003b0fc: 48d4 ldr r0, [pc, #848] ; (1003b450 ) +1003b0fe: f7fe f9b1 bl 10039464 +1003b102: b1c8 cbz r0, 1003b138 +1003b104: f20f 5094 addw r0, pc, #1428 ; 0x594 +1003b108: e01e b.n 1003b148 + +1003b10a : +1003b10a: 2908 cmp r1, #8 +1003b10c: bf18 it ne +1003b10e: f5b1 7f80 cmpne.w r1, #256 ; 0x100 +1003b112: d107 bne.n 1003b124 +1003b114: 8074 strh r4, [r6, #2] +1003b116: b157 cbz r7, 1003b12e +1003b118: 4639 mov r1, r7 +1003b11a: f106 0008 add.w r0, r6, #8 +1003b11e: f7d1 f919 bl 1000c354 +1003b122: e7cc b.n 1003b0be + +1003b124 : +1003b124: f20f 50ac addw r0, pc, #1452 ; 0x5ac +1003b128: f7d1 f8eb bl 1000c302 +1003b12c: e031 b.n 1003b192 + +1003b12e : +1003b12e: f20f 50d8 addw r0, pc, #1496 ; 0x5d8 +1003b132: f7d1 f8e6 bl 1000c302 +1003b136: e02c b.n 1003b192 + +1003b138 : +1003b138: f241 1194 movw r1, #4500 ; 0x1194 +1003b13c: a802 add r0, sp, #8 +1003b13e: f7d5 fbad bl 1001089c +1003b142: b918 cbnz r0, 1003b14c +1003b144: f20f 5070 addw r0, pc, #1392 ; 0x570 + +1003b148 : +1003b148: f7d1 f8db bl 1000c302 + +1003b14c : +1003b14c: a802 add r0, sp, #8 +1003b14e: f7d5 fb97 bl 10010880 +1003b152: 9803 ldr r0, [sp, #12] +1003b154: b188 cbz r0, 1003b17a +1003b156: 2801 cmp r0, #1 +1003b158: dbb3 blt.n 1003b0c2 +1003b15a: f20f 50f4 addw r0, pc, #1524 ; 0x5f4 +1003b15e: e001 b.n 1003b164 + +1003b160 : +1003b160: f20f 50cc addw r0, pc, #1484 ; 0x5cc + +1003b164 : +1003b164: f7d1 f8cd bl 1000c302 +1003b168: e0f3 b.n 1003b352 + +1003b16a : +1003b16a: 4628 mov r0, r5 +1003b16c: f7d1 f8f4 bl 1000c358 +1003b170: 4602 mov r2, r0 +1003b172: 4629 mov r1, r5 +1003b174: a812 add r0, sp, #72 ; 0x48 +1003b176: f7d5 fb4a bl 1001080e + +1003b17a : +1003b17a: 6870 ldr r0, [r6, #4] +1003b17c: b118 cbz r0, 1003b186 +1003b17e: f002 f8a1 bl 1003d2c4 +1003b182: 2000 movs r0, #0 +1003b184: 6070 str r0, [r6, #4] + +1003b186 : +1003b186: 2184 movs r1, #132 ; 0x84 +1003b188: 2001 movs r0, #1 +1003b18a: f002 f88f bl 1003d2ac +1003b18e: 6070 str r0, [r6, #4] +1003b190: b910 cbnz r0, 1003b198 + +1003b192 : +1003b192: f04f 30ff mov.w r0, #4294967295 +1003b196: e0dd b.n 1003b354 + +1003b198 : +1003b198: 4cae ldr r4, [pc, #696] ; (1003b454 ) +1003b19a: 2200 movs r2, #0 +1003b19c: 4621 mov r1, r4 +1003b19e: 200a movs r0, #10 +1003b1a0: f7f4 fe51 bl 1002fe46 +1003b1a4: f8df 82b0 ldr.w r8, [pc, #688] ; 1003b458 +1003b1a8: 2200 movs r2, #0 +1003b1aa: 4641 mov r1, r8 +1003b1ac: 200b movs r0, #11 +1003b1ae: f7f4 fe4a bl 1002fe46 +1003b1b2: 2001 movs r0, #1 +1003b1b4: f7fe fa5d bl 10039672 +1003b1b8: f44f 70fa mov.w r0, #500 ; 0x1f4 +1003b1bc: f7d5 fc17 bl 100109ee +1003b1c0: 2703 movs r7, #3 +1003b1c2: e000 b.n 1003b1c6 + +1003b1c4 : +1003b1c4: 1e7f subs r7, r7, #1 + +1003b1c6 : +1003b1c6: a812 add r0, sp, #72 ; 0x48 +1003b1c8: f7d1 f8c6 bl 1000c358 +1003b1cc: 2100 movs r1, #0 +1003b1ce: 4603 mov r3, r0 +1003b1d0: 9102 str r1, [sp, #8] +1003b1d2: 9101 str r1, [sp, #4] +1003b1d4: 9100 str r1, [sp, #0] +1003b1d6: 2200 movs r2, #0 +1003b1d8: a812 add r0, sp, #72 ; 0x48 +1003b1da: f7fd fcc9 bl 10038b70 +1003b1de: b140 cbz r0, 1003b1f2 +1003b1e0: 2f00 cmp r7, #0 +1003b1e2: d1ef bne.n 1003b1c4 +1003b1e4: f20f 4034 addw r0, pc, #1076 ; 0x434 +1003b1e8: f7d1 f88b bl 1000c302 +1003b1ec: f20f 5090 addw r0, pc, #1424 ; 0x590 +1003b1f0: e09c b.n 1003b32c + +1003b1f2 : +1003b1f2: 6870 ldr r0, [r6, #4] +1003b1f4: 2278 movs r2, #120 ; 0x78 +1003b1f6: a922 add r1, sp, #136 ; 0x88 +1003b1f8: f002 f85b bl 1003d2b2 +1003b1fc: f89d 0088 ldrb.w r0, [sp, #136] ; 0x88 +1003b200: 2800 cmp r0, #0 +1003b202: f000 8091 beq.w 1003b328 +1003b206: 982a ldr r0, [sp, #168] ; 0xa8 +1003b208: 2821 cmp r0, #33 ; 0x21 +1003b20a: f080 808d bcs.w 1003b328 +1003b20e: f20f 205c addw r0, pc, #604 ; 0x25c +1003b212: f7d1 f876 bl 1000c302 +1003b216: a922 add r1, sp, #136 ; 0x88 +1003b218: f10d 0011 add.w r0, sp, #17 +1003b21c: f7d1 f89a bl 1000c354 +1003b220: f20f 2764 addw r7, pc, #612 ; 0x264 +1003b224: f000 f899 bl 1003b35a + +1003b228 : +1003b228: 982a ldr r0, [sp, #168] ; 0xa8 +1003b22a: f88d 0010 strb.w r0, [sp, #16] +1003b22e: f89d 1010 ldrb.w r1, [sp, #16] +1003b232: f20f 206c addw r0, pc, #620 ; 0x26c +1003b236: f7d1 f864 bl 1000c302 +1003b23a: f8bd 00ac ldrh.w r0, [sp, #172] ; 0xac +1003b23e: 2801 cmp r0, #1 +1003b240: d013 beq.n 1003b26a +1003b242: 2802 cmp r0, #2 +1003b244: bf18 it ne +1003b246: 2808 cmpne r0, #8 +1003b248: d009 beq.n 1003b25e +1003b24a: 2810 cmp r0, #16 +1003b24c: bf18 it ne +1003b24e: 2820 cmpne r0, #32 +1003b250: d111 bne.n 1003b276 +1003b252: f20f 20bc addw r0, pc, #700 ; 0x2bc +1003b256: f7d1 f854 bl 1000c302 +1003b25a: 4880 ldr r0, [pc, #512] ; (1003b45c ) +1003b25c: e00a b.n 1003b274 + +1003b25e : +1003b25e: f20f 2084 addw r0, pc, #644 ; 0x284 +1003b262: f7d1 f84e bl 1000c302 +1003b266: 487e ldr r0, [pc, #504] ; (1003b460 ) +1003b268: e004 b.n 1003b274 + +1003b26a : +1003b26a: f20f 2050 addw r0, pc, #592 ; 0x250 +1003b26e: f7d1 f848 bl 1000c302 +1003b272: 2000 movs r0, #0 + +1003b274 : +1003b274: 900e str r0, [sp, #56] ; 0x38 + +1003b276 : +1003b276: 990e ldr r1, [sp, #56] ; 0x38 +1003b278: f20f 20c4 addw r0, pc, #708 ; 0x2c4 +1003b27c: f7d1 f841 bl 1000c302 +1003b280: f20f 29dc addw r9, pc, #732 ; 0x2dc +1003b284: f10d 00b1 add.w r0, sp, #177 ; 0xb1 +1003b288: 900f str r0, [sp, #60] ; 0x3c +1003b28a: f10d 01b1 add.w r1, sp, #177 ; 0xb1 +1003b28e: 4648 mov r0, r9 +1003b290: f7d1 f837 bl 1000c302 +1003b294: 983d ldr r0, [sp, #244] ; 0xf4 +1003b296: 9010 str r0, [sp, #64] ; 0x40 +1003b298: 4601 mov r1, r0 +1003b29a: f20f 20e0 addw r0, pc, #736 ; 0x2e0 +1003b29e: f7d1 f830 bl 1000c302 +1003b2a2: 2000 movs r0, #0 +1003b2a4: f7fe f9e5 bl 10039672 +1003b2a8: f20f 20f0 addw r0, pc, #752 ; 0x2f0 +1003b2ac: 2503 movs r5, #3 +1003b2ae: f7d1 f828 bl 1000c302 +1003b2b2: f000 f852 bl 1003b35a + +1003b2b6 : +1003b2b6: 990e ldr r1, [sp, #56] ; 0x38 +1003b2b8: f20f 301c addw r0, pc, #796 ; 0x31c +1003b2bc: f7d1 f821 bl 1000c302 +1003b2c0: 990f ldr r1, [sp, #60] ; 0x3c +1003b2c2: 4648 mov r0, r9 +1003b2c4: f7d1 f81d bl 1000c302 +1003b2c8: f89d 1010 ldrb.w r1, [sp, #16] +1003b2cc: f20f 3020 addw r0, pc, #800 ; 0x320 +1003b2d0: f7d1 f817 bl 1000c302 +1003b2d4: 9910 ldr r1, [sp, #64] ; 0x40 +1003b2d6: f20f 302c addw r0, pc, #812 ; 0x32c +1003b2da: f7d1 f812 bl 1000c302 +1003b2de: e000 b.n 1003b2e2 + +1003b2e0 : +1003b2e0: 1e6d subs r5, r5, #1 + +1003b2e2 : +1003b2e2: 2000 movs r0, #0 +1003b2e4: 9002 str r0, [sp, #8] +1003b2e6: 9811 ldr r0, [sp, #68] ; 0x44 +1003b2e8: f89d 3010 ldrb.w r3, [sp, #16] +1003b2ec: 9a0f ldr r2, [sp, #60] ; 0x3c +1003b2ee: 990e ldr r1, [sp, #56] ; 0x38 +1003b2f0: 9001 str r0, [sp, #4] +1003b2f2: 9810 ldr r0, [sp, #64] ; 0x40 +1003b2f4: 9000 str r0, [sp, #0] +1003b2f6: f10d 0011 add.w r0, sp, #17 +1003b2fa: f7fd fc39 bl 10038b70 +1003b2fe: b960 cbnz r0, 1003b31a +1003b300: 2d03 cmp r5, #3 +1003b302: bf04 itt eq +1003b304: f44f 707a moveq.w r0, #1000 ; 0x3e8 +1003b308: f7d5 fb71 bleq 100109ee +1003b30c: 2000 movs r0, #0 +1003b30e: f7fd fe60 bl 10038fd2 +1003b312: b910 cbnz r0, 1003b31a +1003b314: f7ff fe5e bl 1003afd4 +1003b318: e00d b.n 1003b336 + +1003b31a : +1003b31a: 2d00 cmp r5, #0 +1003b31c: d1e0 bne.n 1003b2e0 +1003b31e: f20f 20fc addw r0, pc, #764 ; 0x2fc +1003b322: f7d0 ffee bl 1000c302 +1003b326: e006 b.n 1003b336 + +1003b328 : +1003b328: f20f 4068 addw r0, pc, #1128 ; 0x468 + +1003b32c : +1003b32c: f7d0 ffe9 bl 1000c302 +1003b330: 2000 movs r0, #0 +1003b332: f7fe f99e bl 10039672 + +1003b336 : +1003b336: 6870 ldr r0, [r6, #4] +1003b338: b118 cbz r0, 1003b342 +1003b33a: f001 ffc3 bl 1003d2c4 +1003b33e: 2000 movs r0, #0 +1003b340: 6070 str r0, [r6, #4] + +1003b342 : +1003b342: 4621 mov r1, r4 +1003b344: 200a movs r0, #10 +1003b346: f7f4 fd94 bl 1002fe72 +1003b34a: 4641 mov r1, r8 +1003b34c: 200b movs r0, #11 +1003b34e: f7f4 fd90 bl 1002fe72 + +1003b352 : +1003b352: 2000 movs r0, #0 + +1003b354 : +1003b354: b043 add sp, #268 ; 0x10c +1003b356: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + +1003b35a : +1003b35a: f10d 0111 add.w r1, sp, #17 +1003b35e: 4638 mov r0, r7 +1003b360: f7d0 bfcf b.w 1000c302 + +1003b364 : +1003b364: b510 push {r4, lr} +1003b366: b08a sub sp, #40 ; 0x28 +1003b368: 2000 movs r0, #0 +1003b36a: 9000 str r0, [sp, #0] +1003b36c: a900 add r1, sp, #0 +1003b36e: f20f 04f4 addw r4, pc, #244 ; 0xf4 +1003b372: 4620 mov r0, r4 +1003b374: f7e7 f8e8 bl 10022548 +1003b378: 9800 ldr r0, [sp, #0] +1003b37a: 2802 cmp r0, #2 +1003b37c: d00b beq.n 1003b396 +1003b37e: 2803 cmp r0, #3 +1003b380: d111 bne.n 1003b3a6 +1003b382: f7d4 fcc7 bl 1000fd14 +1003b386: 2101 movs r1, #1 +1003b388: 2000 movs r0, #0 +1003b38a: f7d4 fc7f bl 1000fc8c +1003b38e: 2000 movs r0, #0 +1003b390: f7d4 fd26 bl 1000fde0 +1003b394: e007 b.n 1003b3a6 + +1003b396 : +1003b396: a901 add r1, sp, #4 +1003b398: 4620 mov r0, r4 +1003b39a: f7e6 ff33 bl 10022204 +1003b39e: 2801 cmp r0, #1 +1003b3a0: bfa8 it ge +1003b3a2: f7fd fdf5 blge 10038f90 + +1003b3a6 : +1003b3a6: b00a add sp, #40 ; 0x28 +1003b3a8: bd10 pop {r4, pc} + +1003b3aa : +1003b3aa: b53e push {r1, r2, r3, r4, r5, lr} +1003b3ac: 4604 mov r4, r0 +1003b3ae: 460d mov r5, r1 +1003b3b0: f7ff ffd8 bl 1003b364 +1003b3b4: 2c02 cmp r4, #2 +1003b3b6: bf18 it ne +1003b3b8: 2c03 cmpne r4, #3 +1003b3ba: d11a bne.n 1003b3f2 +1003b3bc: 6868 ldr r0, [r5, #4] +1003b3be: b1c0 cbz r0, 1003b3f2 +1003b3c0: a120 add r1, pc, #128 ; (adr r1, 1003b444 ) +1003b3c2: f7d0 ffc5 bl 1000c350 +1003b3c6: bb60 cbnz r0, 1003b422 +1003b3c8: 2c02 cmp r4, #2 +1003b3ca: d113 bne.n 1003b3f4 +1003b3cc: f002 f8f2 bl 1003d5b4 +1003b3d0: 4602 mov r2, r0 +1003b3d2: f20f 31d4 addw r1, pc, #980 ; 0x3d4 +1003b3d6: a800 add r0, sp, #0 +1003b3d8: f7d0 ff68 bl 1000c2ac +1003b3dc: a900 add r1, sp, #0 +1003b3de: f20f 30d0 addw r0, pc, #976 ; 0x3d0 +1003b3e2: f7d0 ff8e bl 1000c302 +1003b3e6: 2300 movs r3, #0 +1003b3e8: 2200 movs r2, #0 +1003b3ea: a900 add r1, sp, #0 +1003b3ec: 2008 movs r0, #8 +1003b3ee: f7ff fe49 bl 1003b084 + +1003b3f2 : +1003b3f2: bd37 pop {r0, r1, r2, r4, r5, pc} + +1003b3f4 : +1003b3f4: 68a8 ldr r0, [r5, #8] +1003b3f6: f7f9 fb0b bl 10034a10 +1003b3fa: f002 f8ca bl 1003d592 +1003b3fe: b920 cbnz r0, 1003b40a +1003b400: f20f 30d4 addw r0, pc, #980 ; 0x3d4 + +1003b404 : +1003b404: f7d0 ff7d bl 1000c302 +1003b408: bd37 pop {r0, r1, r2, r4, r5, pc} + +1003b40a : +1003b40a: f20f 4000 addw r0, pc, #1024 ; 0x400 +1003b40e: f7d0 ff78 bl 1000c302 +1003b412: 68a9 ldr r1, [r5, #8] +1003b414: 2300 movs r3, #0 +1003b416: 2200 movs r2, #0 +1003b418: f44f 7080 mov.w r0, #256 ; 0x100 + +1003b41c : +1003b41c: f7ff fe32 bl 1003b084 +1003b420: bd37 pop {r0, r1, r2, r4, r5, pc} + +1003b422 : +1003b422: 6868 ldr r0, [r5, #4] +1003b424: a108 add r1, pc, #32 ; (adr r1, 1003b448 ) +1003b426: f7d0 ff93 bl 1000c350 +1003b42a: b940 cbnz r0, 1003b43e +1003b42c: f20f 30fc addw r0, pc, #1020 ; 0x3fc +1003b430: f7d0 ff67 bl 1000c302 +1003b434: 2200 movs r2, #0 +1003b436: 2300 movs r3, #0 +1003b438: 4611 mov r1, r2 +1003b43a: 2080 movs r0, #128 ; 0x80 +1003b43c: e7ee b.n 1003b41c + +1003b43e : +1003b43e: f20f 4004 addw r0, pc, #1028 ; 0x404 +1003b442: e7df b.n 1003b404 + +1003b444 : +1003b444: 6970 006e pin. + +1003b448 : +1003b448: 6270 0063 pbc. + +1003b44c : +1003b44c: 8134 1004 4... + +1003b450 : +1003b450: aff9 1003 .... + +1003b454 : +1003b454: feb5 1003 .... + +1003b458 : +1003b458: 00d9 1004 .... + +1003b45c : +1003b45c: 0004 0040 ..@. + +1003b460 : +1003b460: 0004 0020 .. . + +1003b464 : +1003b464: 6c77 6e61 0030 0000 wlan0... + +1003b46c : +1003b46c: 0a0d 7077 5f73 6f63 666e 6769 775f 6669 ..wps_config_wif +1003b47c: 5f69 6573 7474 6e69 0a67 0000 i_setting... + +1003b488 : +1003b488: 0a0d 7077 5f73 6977 6966 732e 6973 2064 ..wps_wifi.ssid +1003b498: 203d 7325 000a 0000 = %s.... + +1003b4a0 : +1003b4a0: 0a0d 7077 5f73 6977 6966 732e 6973 5f64 ..wps_wifi.ssid_ +1003b4b0: 656c 206e 203d 6425 000a 0000 len = %d.... + +1003b4bc : +1003b4bc: 0a0d 6573 7563 6972 7974 745f 7079 2065 ..security_type +1003b4cc: 203d 5452 5f57 4553 5543 4952 5954 4f5f = RTW_SECURITY_O +1003b4dc: 4550 0a4e 0000 0000 PEN..... + +1003b4e4 : +1003b4e4: 0a0d 6573 7563 6972 7974 745f 7079 2065 ..security_type +1003b4f4: 203d 5452 5f57 4553 5543 4952 5954 575f = RTW_SECURITY_W +1003b504: 4150 415f 5345 505f 4b53 000a PA_AES_PSK.. + +1003b510 : +1003b510: 0a0d 6573 7563 6972 7974 745f 7079 2065 ..security_type +1003b520: 203d 5452 5f57 4553 5543 4952 5954 575f = RTW_SECURITY_W +1003b530: 4150 5f32 4541 5f53 5350 0a4b 0000 0000 PA2_AES_PSK..... + +1003b540 : +1003b540: 0a0d 7077 5f73 6977 6966 732e 6365 7275 ..wps_wifi.secur +1003b550: 7469 5f79 7974 6570 3d20 2520 0a64 0000 ity_type = %d... + +1003b560 : +1003b560: 0a0d 7077 5f73 6977 6966 702e 7361 7773 ..wps_wifi.passw +1003b570: 726f 2064 203d 7325 000a 0000 ord = %s.... + +1003b57c : +1003b57c: 0a0d 7077 5f73 6977 6966 702e 7361 7773 ..wps_wifi.passw +1003b58c: 726f 5f64 656c 206e 203d 6425 0000 0000 ord_len = %d.... + +1003b59c : +1003b59c: 0a0d 3d3d 3d3d 3d3d 3d3d 3d3d 3d3d 3d3d ..============== +1003b5ac: 203d 6977 6966 635f 7265 6974 6966 6163 = wifi_certifica +1003b5bc: 6574 695f 666e 206f 3d3d 3d3d 3d3d 3d3d te_info ======== +1003b5cc: 3d3d 3d3d 3d3d 0a3d 0000 0000 =======..... + +1003b5d8 : +1003b5d8: 0a0d 6573 7563 6972 7974 745f 7079 2065 ..security_type +1003b5e8: 203d 6425 000a 0000 = %d.... + +1003b5f0 : +1003b5f0: 0a0d 7373 6469 6c5f 6e65 3d20 2520 0a64 ..ssid_len = %d. +1003b600: 0000 0000 .... + +1003b604 : +1003b604: 0a0d 6170 7373 6f77 6472 6c5f 6e65 3d20 ..password_len = +1003b614: 2520 0a64 0000 0000 %d..... + +1003b61c : +1003b61c: 0a0d 575b 5350 4a5d 696f 206e 7362 2073 ..[WPS]Join bss +1003b62c: 6166 6c69 6465 000a failed.. + +1003b634 : +1003b634: 0a0d 705b 6362 525d 6365 726f 2064 6966 ..[pbc]Record fi +1003b644: 7372 2074 7274 6769 7265 7720 7370 4120 rst triger wps A +1003b654: 2050 203d 7325 000a P = %s.. + +1003b65c : +1003b65c: 0a0d 705b 6e69 665d 6e69 2064 756f 2074 ..[pin]find out +1003b66c: 6966 7372 2074 7274 6769 7265 7720 7370 first triger wps +1003b67c: 4120 2050 203d 7325 000a 0000 AP = %s.... + +1003b688 : +1003b688: 0a0d 5057 2053 6373 6e61 6420 6e6f 2165 ..WPS scan done! +1003b698: 0a0d 0000 .... + +1003b69c : +1003b69c: 0d0a 5245 4f52 3a52 7720 6669 2069 6373 ..ERROR: wifi sc +1003b6ac: 6e61 6620 6961 656c 0064 0000 an failed... + +1003b6b8 : +1003b6b8: 0a0d 5057 2053 6373 6e61 6420 6e6f 2065 ..WPS scan done +1003b6c8: 6165 6c72 2179 0a0d 0000 0000 early!...... + +1003b6d4 : +1003b6d4: 0d0a 5057 3a53 5720 7370 6d20 7465 6f68 ..WPS: Wps metho +1003b6e4: 2864 6425 2029 7369 7720 6f72 676e 202e d(%d) is wrong. +1003b6f4: 6f4e 2074 7274 6769 7265 5720 5350 0a2e Not triger WPS.. +1003b704: 0000 0000 .... + +1003b708 : +1003b708: 0d0a 5057 3a53 5020 4e49 6920 2073 554e ..WPS: PIN is NU +1003b718: 4c4c 202e 6f4e 2074 7274 6769 7265 5720 LL. Not triger W +1003b728: 5350 0a2e 0000 0000 PS...... + +1003b730 : +1003b730: 0a0d 5057 3a53 5720 5350 5720 6c61 696b ..WPS: WPS Walki +1003b740: 676e 5420 6d69 2065 754f 0a74 0000 0000 ng Time Out..... + +1003b750 : +1003b750: 0a0d 5057 3a53 5720 5350 7320 7365 6973 ..WPS: WPS sessi +1003b760: 6e6f 6f20 6576 6c72 7061 202e 6f4e 2074 on overlap. Not +1003b770: 7274 6769 7265 5720 5350 0a2e 0000 0000 triger WPS...... + +1003b780 : +1003b780: 0d0a 5057 3a53 5720 5350 4620 6961 216c ..WPS: WPS Fail! +1003b790: 0a21 0000 !... + +1003b794 : +1003b794: 0d0a 5057 3a53 5720 5350 4620 4941 214c ..WPS: WPS FAIL! +1003b7a4: 2121 000a !!.. + +1003b7a8 : +1003b7a8: 3025 6438 0000 0000 %08d.... + +1003b7b0 : +1003b7b0: 0d0a 5057 3a53 5320 6174 7472 5720 5350 ..WPS: Start WPS +1003b7c0: 5020 4e49 4420 7369 6c70 7961 202e 4950 PIN Display. PI +1003b7d0: 3a4e 2520 0a73 000d N: %s... + +1003b7d8 : +1003b7d8: 0d0a 5057 3a53 4420 7665 6369 2065 6970 ..WPS: Device pi +1003b7e8: 206e 6f63 6564 6920 2073 6e69 6176 696c n code is invali +1003b7f8: 2e64 4e20 746f 7420 6972 6567 2072 5057 d. Not triger WP +1003b808: 2e53 000a S... + +1003b80c : +1003b80c: 0d0a 5057 3a53 5320 6174 7472 5720 5350 ..WPS: Start WPS +1003b81c: 5020 4e49 4b20 7965 6170 2e64 0d0a 0000 PIN Keypad..... + +1003b82c : +1003b82c: 0d0a 5057 3a53 5320 6174 7472 5720 5350 ..WPS: Start WPS +1003b83c: 5020 4342 0a2e 000d PBC.... + +1003b844 : +1003b844: 0d0a 5057 3a53 5720 7370 4d20 7465 6f68 ..WPS: Wps Metho +1003b854: 2064 7369 7720 6f72 676e 202e 6f4e 2074 d is wrong. Not +1003b864: 7274 6769 7265 5720 5350 0a2e 0000 0000 triger WPS...... + +1003b874 : +1003b874: b580 push {r7, lr} +1003b876: f8df 13c8 ldr.w r1, [pc, #968] ; 1003bc40 +1003b87a: 2021 movs r0, #33 ; 0x21 +1003b87c: 6008 str r0, [r1, #0] +1003b87e: 2064 movs r0, #100 ; 0x64 +1003b880: f001 ff24 bl 1003d6cc +1003b884: f8df 03bc ldr.w r0, [pc, #956] ; 1003bc44 +1003b888: f8df 23bc ldr.w r2, [pc, #956] ; 1003bc48 +1003b88c: 6801 ldr r1, [r0, #0] +1003b88e: f401 61e0 and.w r1, r1, #1792 ; 0x700 +1003b892: 4311 orrs r1, r2 +1003b894: 6001 str r1, [r0, #0] + +1003b896 : +1003b896: f44f 707a mov.w r0, #1000 ; 0x3e8 +1003b89a: f001 ff17 bl 1003d6cc +1003b89e: e7fa b.n 1003b896 + +1003b8a0 : +1003b8a0: e92d 4ff1 stmdb sp!, {r0, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1003b8a4: b0a0 sub sp, #128 ; 0x80 +1003b8a6: 2600 movs r6, #0 +1003b8a8: 9603 str r6, [sp, #12] +1003b8aa: 9601 str r6, [sp, #4] +1003b8ac: 9605 str r6, [sp, #20] +1003b8ae: 9604 str r6, [sp, #16] +1003b8b0: 2700 movs r7, #0 +1003b8b2: f04f 39ff mov.w r9, #4294967295 +1003b8b6: 9608 str r6, [sp, #32] +1003b8b8: a818 add r0, sp, #96 ; 0x60 +1003b8ba: f20f 31e4 addw r1, pc, #996 ; 0x3e4 +1003b8be: 2220 movs r2, #32 +1003b8c0: f7f2 fdf4 bl 1002e4ac <__iar_unaligned___aeabi_memcpy4> +1003b8c4: f20f 3ac0 addw sl, pc, #960 ; 0x3c0 +1003b8c8: f20f 30f4 addw r0, pc, #1012 ; 0x3f4 +1003b8cc: 4651 mov r1, sl +1003b8ce: f7d0 fd18 bl 1000c302 +1003b8d2: f44f 7000 mov.w r0, #512 ; 0x200 +1003b8d6: f7d0 ffed bl 1000c8b4 +1003b8da: ea5f 0b00 movs.w fp, r0 +1003b8de: d105 bne.n 1003b8ec +1003b8e0: 4651 mov r1, sl +1003b8e2: f20f 30f8 addw r0, pc, #1016 ; 0x3f8 +1003b8e6: f7d0 fd0c bl 1000c302 +1003b8ea: e128 b.n 1003bb3e + +1003b8ec : +1003b8ec: 2200 movs r2, #0 +1003b8ee: 2101 movs r1, #1 +1003b8f0: 2002 movs r0, #2 +1003b8f2: f7d3 fe01 bl 1000f4f8 +1003b8f6: ea5f 0800 movs.w r8, r0 +1003b8fa: d503 bpl.n 1003b904 +1003b8fc: 4651 mov r1, sl +1003b8fe: f20f 30f8 addw r0, pc, #1016 ; 0x3f8 +1003b902: e142 b.n 1003bb8a + +1003b904 : +1003b904: 2002 movs r0, #2 +1003b906: f88d 0031 strb.w r0, [sp, #49] ; 0x31 +1003b90a: 2210 movs r2, #16 +1003b90c: 9820 ldr r0, [sp, #128] ; 0x80 +1003b90e: 6800 ldr r0, [r0, #0] +1003b910: 900d str r0, [sp, #52] ; 0x34 +1003b912: a90c add r1, sp, #48 ; 0x30 +1003b914: 9820 ldr r0, [sp, #128] ; 0x80 +1003b916: 8880 ldrh r0, [r0, #4] +1003b918: f8ad 0032 strh.w r0, [sp, #50] ; 0x32 +1003b91c: 4640 mov r0, r8 +1003b91e: f7d3 fc4f bl 1000f1c0 +1003b922: f110 0f01 cmn.w r0, #1 +1003b926: d103 bne.n 1003b930 +1003b928: 4651 mov r1, sl +1003b92a: f20f 30e8 addw r0, pc, #1000 ; 0x3e8 +1003b92e: e12c b.n 1003bb8a + +1003b930 : +1003b930: 48c6 ldr r0, [pc, #792] ; (1003bc4c ) +1003b932: 6801 ldr r1, [r0, #0] +1003b934: f421 5180 bic.w r1, r1, #4096 ; 0x1000 +1003b938: 6001 str r1, [r0, #0] +1003b93a: aa05 add r2, sp, #20 +1003b93c: f44f 4130 mov.w r1, #45056 ; 0xb000 +1003b940: f000 f93f bl 1003bbc2 + +1003b944 : +1003b944: 9805 ldr r0, [sp, #20] +1003b946: f500 4030 add.w r0, r0, #45056 ; 0xb000 +1003b94a: f100 0410 add.w r4, r0, #16 +1003b94e: aa04 add r2, sp, #16 +1003b950: 4621 mov r1, r4 +1003b952: f000 f936 bl 1003bbc2 + +1003b956 : +1003b956: aa08 add r2, sp, #32 +1003b958: 1d21 adds r1, r4, #4 +1003b95a: f000 f932 bl 1003bbc2 + +1003b95e : +1003b95e: 9808 ldr r0, [sp, #32] +1003b960: f1b0 5f40 cmp.w r0, #805306368 ; 0x30000000 +1003b964: d107 bne.n 1003b976 +1003b966: 9b04 ldr r3, [sp, #16] +1003b968: f20f 30c8 addw r0, pc, #968 ; 0x3c8 +1003b96c: 4622 mov r2, r4 +1003b96e: 4651 mov r1, sl +1003b970: f7d0 fcc7 bl 1000c302 +1003b974: e008 b.n 1003b988 + +1003b976 : +1003b976: 4651 mov r1, sl +1003b978: f20f 30dc addw r0, pc, #988 ; 0x3dc +1003b97c: f7d0 fcc1 bl 1000c302 +1003b980: 9805 ldr r0, [sp, #20] +1003b982: 9004 str r0, [sp, #16] +1003b984: f44f 4430 mov.w r4, #45056 ; 0xb000 + +1003b988 : +1003b988: aa01 add r2, sp, #4 +1003b98a: f44f 4110 mov.w r1, #36864 ; 0x9000 +1003b98e: f000 f918 bl 1003bbc2 + +1003b992 : +1003b992: 9801 ldr r0, [sp, #4] +1003b994: 4284 cmp r4, r0 +1003b996: d204 bcs.n 1003b9a2 +1003b998: 9904 ldr r1, [sp, #16] +1003b99a: 1909 adds r1, r1, r4 +1003b99c: 4288 cmp r0, r1 +1003b99e: d308 bcc.n 1003b9b2 +1003b9a0: e001 b.n 1003b9a6 + +1003b9a2 : +1003b9a2: 42a0 cmp r0, r4 +1003b9a4: d305 bcc.n 1003b9b2 + +1003b9a6 : +1003b9a6: 0500 lsls r0, r0, #20 +1003b9a8: d103 bne.n 1003b9b2 +1003b9aa: 9801 ldr r0, [sp, #4] +1003b9ac: f110 0f01 cmn.w r0, #1 +1003b9b0: d107 bne.n 1003b9c2 + +1003b9b2 : +1003b9b2: 9b05 ldr r3, [sp, #20] +1003b9b4: 9a01 ldr r2, [sp, #4] +1003b9b6: f20f 30b4 addw r0, pc, #948 ; 0x3b4 +1003b9ba: 4651 mov r1, sl +1003b9bc: f7d0 fca1 bl 1000c302 +1003b9c0: e0ba b.n 1003bb38 + +1003b9c2 : +1003b9c2: 220c movs r2, #12 +1003b9c4: 2100 movs r1, #0 +1003b9c6: a809 add r0, sp, #36 ; 0x24 +1003b9c8: f7d0 fcc0 bl 1000c34c +1003b9cc: 9809 ldr r0, [sp, #36] ; 0x24 +1003b9ce: ad09 add r5, sp, #36 ; 0x24 +1003b9d0: b9e0 cbnz r0, 1003ba0c +1003b9d2: 4651 mov r1, sl +1003b9d4: f20f 30c8 addw r0, pc, #968 ; 0x3c8 +1003b9d8: f7d0 fc93 bl 1000c302 +1003b9dc: 220c movs r2, #12 +1003b9de: a909 add r1, sp, #36 ; 0x24 +1003b9e0: 4640 mov r0, r8 +1003b9e2: f7d3 fcf1 bl 1000f3c8 +1003b9e6: 4602 mov r2, r0 +1003b9e8: 4651 mov r1, sl +1003b9ea: f20f 30d0 addw r0, pc, #976 ; 0x3d0 +1003b9ee: f7d0 fc88 bl 1000c302 +1003b9f2: 68ab ldr r3, [r5, #8] +1003b9f4: 9a09 ldr r2, [sp, #36] ; 0x24 +1003b9f6: f20f 30e4 addw r0, pc, #996 ; 0x3e4 +1003b9fa: 4651 mov r1, sl +1003b9fc: f7d0 fc81 bl 1000c302 +1003ba00: 68a8 ldr r0, [r5, #8] +1003ba02: b918 cbnz r0, 1003ba0c +1003ba04: 4651 mov r1, sl +1003ba06: f20f 30fc addw r0, pc, #1020 ; 0x3fc +1003ba0a: e0be b.n 1003bb8a + +1003ba0c : +1003ba0c: 68ac ldr r4, [r5, #8] +1003ba0e: f20f 4018 addw r0, pc, #1048 ; 0x418 +1003ba12: 4622 mov r2, r4 +1003ba14: 4651 mov r1, sl +1003ba16: f7d0 fc74 bl 1000c302 +1003ba1a: 2c01 cmp r4, #1 +1003ba1c: db13 blt.n 1003ba46 +1003ba1e: 1e60 subs r0, r4, #1 +1003ba20: 0b00 lsrs r0, r0, #12 +1003ba22: 1c44 adds r4, r0, #1 +1003ba24: 4623 mov r3, r4 +1003ba26: 4622 mov r2, r4 +1003ba28: 4651 mov r1, sl +1003ba2a: f20f 4014 addw r0, pc, #1044 ; 0x414 +1003ba2e: f7d0 fc68 bl 1000c302 + +1003ba32 : +1003ba32: 42a7 cmp r7, r4 +1003ba34: d20a bcs.n 1003ba4c +1003ba36: 9801 ldr r0, [sp, #4] +1003ba38: eb00 3107 add.w r1, r0, r7, lsl #12 +1003ba3c: a802 add r0, sp, #8 +1003ba3e: f7f5 fd4b bl 100314d8 +1003ba42: 1c7f adds r7, r7, #1 +1003ba44: e7f5 b.n 1003ba32 + +1003ba46 : +1003ba46: f20f 4018 addw r0, pc, #1048 ; 0x418 +1003ba4a: e0ac b.n 1003bba6 + +1003ba4c : +1003ba4c: 9a01 ldr r2, [sp, #4] +1003ba4e: f20f 4024 addw r0, pc, #1060 ; 0x424 +1003ba52: 4651 mov r1, sl +1003ba54: f7d0 fc55 bl 1000c302 +1003ba58: 9801 ldr r0, [sp, #4] +1003ba5a: f110 0f01 cmn.w r0, #1 +1003ba5e: d06b beq.n 1003bb38 +1003ba60: 9000 str r0, [sp, #0] +1003ba62: a576 add r5, pc, #472 ; (adr r5, 1003bc3c ) +1003ba64: 4628 mov r0, r5 +1003ba66: f7d0 fc4c bl 1000c302 + +1003ba6a : +1003ba6a: f44f 7200 mov.w r2, #512 ; 0x200 +1003ba6e: 2100 movs r1, #0 +1003ba70: 4658 mov r0, fp +1003ba72: f7d0 fc6b bl 1000c34c +1003ba76: f44f 7200 mov.w r2, #512 ; 0x200 +1003ba7a: 4659 mov r1, fp +1003ba7c: 4640 mov r0, r8 +1003ba7e: f7d3 fca3 bl 1000f3c8 +1003ba82: 4604 mov r4, r0 +1003ba84: 2c00 cmp r4, #0 +1003ba86: d17c bne.n 1003bb82 +1003ba88: 4628 mov r0, r5 +1003ba8a: f7d0 fc3a bl 1000c302 +1003ba8e: 9a03 ldr r2, [sp, #12] +1003ba90: f20f 4030 addw r0, pc, #1072 ; 0x430 +1003ba94: 4631 mov r1, r6 +1003ba96: f7d0 fc34 bl 1000c302 +1003ba9a: 9a09 ldr r2, [sp, #36] ; 0x24 +1003ba9c: 9903 ldr r1, [sp, #12] +1003ba9e: f20f 4050 addw r0, pc, #1104 ; 0x450 +1003baa2: f7d0 fc2e bl 1000c302 +1003baa6: 2700 movs r7, #0 + +1003baa8 : +1003baa8: a810 add r0, sp, #64 ; 0x40 +1003baaa: eb00 0287 add.w r2, r0, r7, lsl #2 +1003baae: 9801 ldr r0, [sp, #4] +1003bab0: eb00 0087 add.w r0, r0, r7, lsl #2 +1003bab4: f100 0128 add.w r1, r0, #40 ; 0x28 +1003bab8: f000 f883 bl 1003bbc2 + +1003babc : +1003babc: 1c7f adds r7, r7, #1 +1003babe: 2f08 cmp r7, #8 +1003bac0: dbf2 blt.n 1003baa8 +1003bac2: f20f 4054 addw r0, pc, #1108 ; 0x454 +1003bac6: aa10 add r2, sp, #64 ; 0x40 +1003bac8: 4651 mov r1, sl +1003baca: f7d0 fc1a bl 1000c302 +1003bace: 2204 movs r2, #4 +1003bad0: a909 add r1, sp, #36 ; 0x24 +1003bad2: a803 add r0, sp, #12 +1003bad4: f7d0 fc36 bl 1000c344 +1003bad8: bb70 cbnz r0, 1003bb38 +1003bada: a918 add r1, sp, #96 ; 0x60 +1003badc: a810 add r0, sp, #64 ; 0x40 +1003bade: f7d0 fc37 bl 1000c350 +1003bae2: bb48 cbnz r0, 1003bb38 +1003bae4: 9801 ldr r0, [sp, #4] +1003bae6: 4a5a ldr r2, [pc, #360] ; (1003bc50 ) +1003bae8: f100 0108 add.w r1, r0, #8 +1003baec: a802 add r0, sp, #8 +1003baee: f7f5 fd0c bl 1003150a +1003baf2: 9801 ldr r0, [sp, #4] +1003baf4: 4a57 ldr r2, [pc, #348] ; (1003bc54 ) +1003baf6: f100 010c add.w r1, r0, #12 +1003bafa: a802 add r0, sp, #8 +1003bafc: f7f5 fd05 bl 1003150a +1003bb00: 9801 ldr r0, [sp, #4] +1003bb02: f100 0108 add.w r1, r0, #8 +1003bb06: aa07 add r2, sp, #28 +1003bb08: f000 f85b bl 1003bbc2 + +1003bb0c : +1003bb0c: 9801 ldr r0, [sp, #4] +1003bb0e: f100 010c add.w r1, r0, #12 +1003bb12: aa06 add r2, sp, #24 +1003bb14: f000 f855 bl 1003bbc2 + +1003bb18 : +1003bb18: 9803 ldr r0, [sp, #12] +1003bb1a: 9b06 ldr r3, [sp, #24] +1003bb1c: 9a07 ldr r2, [sp, #28] +1003bb1e: 9000 str r0, [sp, #0] +1003bb20: 4651 mov r1, sl +1003bb22: f20f 4010 addw r0, pc, #1040 ; 0x410 +1003bb26: f7d0 fbec bl 1000c302 +1003bb2a: f20f 4030 addw r0, pc, #1072 ; 0x430 +1003bb2e: 4651 mov r1, sl +1003bb30: f7d0 fbe7 bl 1000c302 +1003bb34: f04f 0900 mov.w r9, #0 + +1003bb38 : +1003bb38: 4658 mov r0, fp +1003bb3a: f7d0 ff42 bl 1000c9c2 + +1003bb3e : +1003bb3e: f1b8 0f00 cmp.w r8, #0 +1003bb42: bf5c itt pl +1003bb44: 4640 movpl r0, r8 +1003bb46: f7d3 fb14 blpl 1000f172 +1003bb4a: 9820 ldr r0, [sp, #128] ; 0x80 +1003bb4c: b108 cbz r0, 1003bb52 +1003bb4e: f7d0 ff38 bl 1000c9c2 + +1003bb52 : +1003bb52: 4941 ldr r1, [pc, #260] ; (1003bc58 ) +1003bb54: 2000 movs r0, #0 +1003bb56: 6008 str r0, [r1, #0] +1003bb58: 4651 mov r1, sl +1003bb5a: f20f 401c addw r0, pc, #1052 ; 0x41c +1003bb5e: f7d0 fbd0 bl 1000c302 +1003bb62: f1b9 0f00 cmp.w r9, #0 +1003bb66: d106 bne.n 1003bb76 +1003bb68: f20f 4024 addw r0, pc, #1060 ; 0x424 +1003bb6c: 4651 mov r1, sl +1003bb6e: f7d0 fbc8 bl 1000c302 +1003bb72: f7ff fe7f bl 1003b874 + +1003bb76 : +1003bb76: 2000 movs r0, #0 +1003bb78: f7ce ff62 bl 1000aa40 +1003bb7c: b021 add sp, #132 ; 0x84 +1003bb7e: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1003bb82 : +1003bb82: d505 bpl.n 1003bb90 +1003bb84: 4651 mov r1, sl +1003bb86: f20f 3004 addw r0, pc, #772 ; 0x304 + +1003bb8a : +1003bb8a: f7d0 fbba bl 1000c302 +1003bb8e: e7d3 b.n 1003bb38 + +1003bb90 : +1003bb90: 9800 ldr r0, [sp, #0] +1003bb92: 1831 adds r1, r6, r0 +1003bb94: 465b mov r3, fp +1003bb96: 4622 mov r2, r4 +1003bb98: a802 add r0, sp, #8 +1003bb9a: f7f5 fd1b bl 100315d4 +1003bb9e: 2800 cmp r0, #0 +1003bba0: d503 bpl.n 1003bbaa +1003bba2: f20f 3004 addw r0, pc, #772 ; 0x304 + +1003bba6 : +1003bba6: 4651 mov r1, sl +1003bba8: e7ef b.n 1003bb8a + +1003bbaa : +1003bbaa: 19a6 adds r6, r4, r6 +1003bbac: 2700 movs r7, #0 +1003bbae: e005 b.n 1003bbbc + +1003bbb0 : +1003bbb0: 9803 ldr r0, [sp, #12] +1003bbb2: f817 100b ldrb.w r1, [r7, fp] +1003bbb6: 1808 adds r0, r1, r0 +1003bbb8: 9003 str r0, [sp, #12] +1003bbba: 1c7f adds r7, r7, #1 + +1003bbbc : +1003bbbc: 42a7 cmp r7, r4 +1003bbbe: dbf7 blt.n 1003bbb0 +1003bbc0: e753 b.n 1003ba6a + +1003bbc2 : +1003bbc2: a802 add r0, sp, #8 +1003bbc4: f7f5 bc94 b.w 100314f0 + +1003bbc8 : +1003bbc8: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1003bbcc: 4f22 ldr r7, [pc, #136] ; (1003bc58 ) +1003bbce: f20f 38d8 addw r8, pc, #984 ; 0x3d8 +1003bbd2: 4604 mov r4, r0 +1003bbd4: 6838 ldr r0, [r7, #0] +1003bbd6: b082 sub sp, #8 +1003bbd8: 460d mov r5, r1 +1003bbda: b118 cbz r0, 1003bbe4 +1003bbdc: 4641 mov r1, r8 +1003bbde: f20f 30dc addw r0, pc, #988 ; 0x3dc +1003bbe2: e026 b.n 1003bc32 + +1003bbe4 : +1003bbe4: 2008 movs r0, #8 +1003bbe6: f7d0 fe65 bl 1000c8b4 +1003bbea: 0006 movs r6, r0 +1003bbec: d107 bne.n 1003bbfe +1003bbee: f20f 30ec addw r0, pc, #1004 ; 0x3ec +1003bbf2: 4641 mov r1, r8 +1003bbf4: f7d0 fb85 bl 1000c302 +1003bbf8: f04f 30ff mov.w r0, #4294967295 +1003bbfc: e01c b.n 1003bc38 + +1003bbfe : +1003bbfe: 4620 mov r0, r4 +1003bc00: f7d0 fbce bl 1000c3a0 +1003bc04: 6030 str r0, [r6, #0] +1003bc06: b2a8 uxth r0, r5 +1003bc08: f7d0 fca2 bl 1000c550 +1003bc0c: 80b0 strh r0, [r6, #4] +1003bc0e: f44f 6380 mov.w r3, #1024 ; 0x400 +1003bc12: 2001 movs r0, #1 +1003bc14: 9000 str r0, [sp, #0] +1003bc16: 4632 mov r2, r6 +1003bc18: 4910 ldr r1, [pc, #64] ; (1003bc5c ) +1003bc1a: f20f 30e0 addw r0, pc, #992 ; 0x3e0 +1003bc1e: f7cc fb04 bl 1000822a +1003bc22: 6038 str r0, [r7, #0] +1003bc24: b938 cbnz r0, 1003bc36 +1003bc26: 4630 mov r0, r6 +1003bc28: f7d0 fecb bl 1000c9c2 +1003bc2c: f20f 30d8 addw r0, pc, #984 ; 0x3d8 +1003bc30: 4641 mov r1, r8 + +1003bc32 : +1003bc32: f7d0 fb66 bl 1000c302 + +1003bc36 : +1003bc36: 2000 movs r0, #0 + +1003bc38 : +1003bc38: e8bd 81f6 ldmia.w sp!, {r1, r2, r4, r5, r6, r7, r8, pc} + +1003bc3c : +1003bc3c: 0d0a 0000 .... + +1003bc40 : +1003bc40: 0014 4000 ...@ + +1003bc44 : +1003bc44: ed0c e000 .... + +1003bc48 : +1003bc48: 0004 05fa .... + +1003bc4c : +1003bc4c: 0310 1000 .... + +1003bc50 : +1003bc50: 3138 3539 8195 + +1003bc54 : +1003bc54: 3738 3131 8711 + +1003bc58 : +1003bc58: 7b44 1004 D{.. + +1003bc5c : +1003bc5c: b8a1 1003 .... + +1003bc60 : +1003bc60: b510 push {r4, lr} +1003bc62: 460c mov r4, r1 +1003bc64: 2803 cmp r0, #3 +1003bc66: d007 beq.n 1003bc78 +1003bc68: e8bd 4010 ldmia.w sp!, {r4, lr} +1003bc6c: f20f 31bc addw r1, pc, #956 ; 0x3bc +1003bc70: f20f 30c4 addw r0, pc, #964 ; 0x3c4 +1003bc74: f7d0 bb45 b.w 1000c302 + +1003bc78 : +1003bc78: 68a0 ldr r0, [r4, #8] +1003bc7a: f7f8 fec9 bl 10034a10 +1003bc7e: 4601 mov r1, r0 +1003bc80: 6860 ldr r0, [r4, #4] +1003bc82: e8bd 4010 ldmia.w sp!, {r4, lr} +1003bc86: e79f b.n 1003bbc8 + +1003bc88 : +1003bc88: 7075 6164 6574 6f5f 6174 6c5f 636f 6c61 update_ota_local +1003bc98: 745f 7361 006b 0000 _task... + +1003bca0 : +1003bca0: 7543 7473 6d6f 7265 5320 6769 616e 7574 Customer Signatu +1003bcb0: 6572 6d2d 646f 6c65 7878 0078 0000 0000 re-modelxxx..... + +1003bcc0 : +1003bcc0: 0d0a 255b 5d73 5520 6470 7461 2065 6174 ..[%s] Update ta +1003bcd0: 6b73 7320 6174 7472 0000 0000 sk start.... + +1003bcdc : +1003bcdc: 0d0a 255b 5d73 4120 6c6c 636f 6220 6675 ..[%s] Alloc buf +1003bcec: 6566 2072 6166 6c69 6465 0000 fer failed.. + +1003bcf8 : +1003bcf8: 0d0a 255b 5d73 4320 6572 7461 2065 6f73 ..[%s] Create so +1003bd08: 6b63 7465 6620 6961 656c 0064 cket failed. + +1003bd14 : +1003bd14: 0d0a 255b 5d73 7320 636f 656b 2074 6f63 ..[%s] socket co +1003bd24: 6e6e 6365 2074 6166 6c69 6465 0000 0000 nnect failed.... + +1003bd34 : +1003bd34: 0d0a 255b 5d73 4920 414d 4547 335f 3020 ..[%s] IMAGE_3 0 +1003bd44: 2578 2078 6d49 3367 654c 206e 7830 7825 x%x Img3Len 0x%x +1003bd54: 0000 0000 .... + +1003bd58 : +1003bd58: 0d0a 255b 5d73 6e20 206f 4d49 4741 5f45 ..[%s] no IMAGE_ +1003bd68: 0033 0000 3... + +1003bd6c : +1003bd6c: 0d0a 255b 5d73 6120 7466 7265 7220 6165 ..[%s] after rea +1003bd7c: 2c64 4e20 7765 6d49 3267 6441 7264 3020 d, NewImg2Addr 0 +1003bd8c: 2578 2c78 4920 676d 4c32 6e65 3020 2578 x%x, Img2Len 0x% +1003bd9c: 0078 0000 x... + +1003bda0 : +1003bda0: 0d0a 255b 5d73 5220 6165 2064 6863 6365 ..[%s] Read chec +1003bdb0: 7368 6d75 6620 7269 7473 0000 hsum first.. + +1003bdbc : +1003bdbc: 0d0a 255b 5d73 6320 6568 6863 7573 206d ..[%s] chechsum +1003bdcc: 6572 6461 625f 7479 7365 2520 0064 0000 read_bytes %d... + +1003bddc : +1003bddc: 0d0a 255b 5d73 6320 6568 6863 7573 206d ..[%s] chechsum +1003bdec: 7830 7825 202c 6966 656c 7320 7a69 2065 0x%x, file size +1003bdfc: 7830 7825 0000 0000 0x%x.... + +1003be04 : +1003be04: 0d0a 255b 5d73 4e20 206f 6863 6365 736b ..[%s] No checks +1003be14: 6d75 6120 646e 6620 6c69 2065 6973 657a um and file size +1003be24: 0000 0000 .... + +1003be28 : +1003be28: 0d0a 255b 5d73 4e20 7765 6d49 3267 654c ..[%s] NewImg2Le +1003be38: 206e 6425 2020 0000 n %d .. + +1003be40 : +1003be40: 0d0a 255b 5d73 4e20 7765 6d49 3267 6c42 ..[%s] NewImg2Bl +1003be50: 536b 7a69 2065 6425 2020 7830 3825 0078 kSize %d 0x%8x. + +1003be60 : +1003be60: 0d0a 255b 5d73 5320 7a69 2065 4e49 4156 ..[%s] Size INVA +1003be70: 494c 0044 LID. + +1003be74 : +1003be74: 0d0a 255b 5d73 4e20 7765 6d49 3267 6441 ..[%s] NewImg2Ad +1003be84: 7264 3020 2578 0078 dr 0x%x. + +1003be8c : +1003be8c: 0d0a 255b 5d73 5220 6165 2064 6f73 6b63 ..[%s] Read sock +1003be9c: 7465 6620 6961 656c 0064 0000 et failed... + +1003bea8 : +1003bea8: 0d0a 255b 5d73 5720 6972 6574 7320 6365 ..[%s] Write sec +1003beb8: 6f74 2072 6166 6c69 6465 0000 tor failed.. + +1003bec4 : +1003bec4: 0d0a 7055 6164 6574 6620 6c69 2065 6973 ..Update file si +1003bed4: 657a 3d20 2520 2064 6320 6568 6b63 7573 ze = %d checksu +1003bee4: 206d 7830 7825 2020 0000 0000 m 0x%x .... + +1003bef0 : +1003bef0: 0d0a 6320 6568 6b63 7573 206d 7830 7825 .. checksum 0x%x +1003bf00: 2020 6966 656c 635f 6568 6b63 7573 206d file_checksum +1003bf10: 7830 7825 2020 0000 0x%x .. + +1003bf18 : +1003bf18: 0d0a 255b 5d73 7220 6165 5f64 7563 7473 ..[%s] read_cust +1003bf28: 6d6f 735f 6769 2520 0073 0000 om_sig %s... + +1003bf34 : +1003bf34: 0d0a 255b 5d73 7320 6769 616e 7574 6572 ..[%s] signature +1003bf44: 2520 2c78 7825 202c 6320 6568 6b63 7573 %x,%x, checksu +1003bf54: 206d 7830 7825 0000 m 0x%x.. + +1003bf5c : +1003bf5c: 0d0a 255b 5d73 5520 6470 7461 2065 544f ..[%s] Update OT +1003bf6c: 2041 7573 6363 7365 2173 0000 A success!.. + +1003bf78 : +1003bf78: 0d0a 255b 5d73 5520 6470 7461 2065 6174 ..[%s] Update ta +1003bf88: 6b73 6520 6978 0074 sk exit. + +1003bf90 : +1003bf90: 0d0a 255b 5d73 5220 6165 7964 7420 206f ..[%s] Ready to +1003bfa0: 6572 6f62 746f 0000 reboot.. + +1003bfa8 : +1003bfa8: 7075 6164 6574 6f5f 6174 6c5f 636f 6c61 update_ota_local +1003bfb8: 0000 0000 .... + +1003bfbc : +1003bfbc: 0d0a 255b 5d73 5520 6470 7461 2065 6174 ..[%s] Update ta +1003bfcc: 6b73 6820 7361 6320 6572 7461 6465 002e sk has created.. + +1003bfdc : +1003bfdc: 0d0a 255b 5d73 4120 6c6c 636f 7520 6470 ..[%s] Alloc upd +1003bfec: 7461 2065 6663 2067 6166 6c69 6465 0000 ate cfg failed.. + +1003bffc : +1003bffc: 544f 5f41 6573 7672 7265 0000 OTA_server.. + +1003c008 : +1003c008: 0d0a 255b 5d73 4320 6572 7461 2065 7075 ..[%s] Create up +1003c018: 6164 6574 7420 7361 206b 6166 6c69 6465 date task failed +1003c028: 0000 0000 .... + +1003c02c : +1003c02c: 6d63 5f64 7075 6164 6574 0000 cmd_update.. + +1003c038 : +1003c038: 0d0a 255b 5d73 5520 6173 6567 203a 7075 ..[%s] Usage: up +1003c048: 6164 6574 4920 2050 4f50 5452 0000 0000 date IP PORT.... + +1003c058 <_wlan_init_done_callback>: +1003c058: b580 push {r7, lr} +1003c05a: f20f 11f8 addw r1, pc, #504 ; 0x1f8 +1003c05e: f20f 2010 addw r0, pc, #528 ; 0x210 +1003c062: f7f9 ff9b bl 10035f9c +1003c066: f20f 2010 addw r0, pc, #528 ; 0x210 +1003c06a: f7fa fa00 bl 1003646e +1003c06e: f20f 2020 addw r0, pc, #544 ; 0x220 +1003c072: f7fa fa1b bl 100364ac +1003c076: a06e add r0, pc, #440 ; (adr r0, 1003c230 ) +1003c078: f7fa fa30 bl 100364dc +1003c07c: f7fa fa7a bl 10036574 +1003c080: f7fa fd52 bl 10036b28 +1003c084: 2000 movs r0, #0 +1003c086: bd02 pop {r1, pc} + +1003c088 : +1003c088: 2108 movs r1, #8 +1003c08a: 4a6b ldr r2, [pc, #428] ; (1003c238 ) + +1003c08c : +1003c08c: 0603 lsls r3, r0, #24 +1003c08e: d40a bmi.n 1003c0a6 +1003c090: 2301 movs r3, #1 +1003c092: 6013 str r3, [r2, #0] +1003c094: 6013 str r3, [r2, #0] +1003c096: 6013 str r3, [r2, #0] +1003c098: 6013 str r3, [r2, #0] +1003c09a: 2300 movs r3, #0 +1003c09c: 6013 str r3, [r2, #0] +1003c09e: 6013 str r3, [r2, #0] +1003c0a0: 6013 str r3, [r2, #0] +1003c0a2: 6013 str r3, [r2, #0] +1003c0a4: e009 b.n 1003c0ba + +1003c0a6 : +1003c0a6: 2301 movs r3, #1 +1003c0a8: 6013 str r3, [r2, #0] +1003c0aa: 6013 str r3, [r2, #0] +1003c0ac: 6013 str r3, [r2, #0] +1003c0ae: 6013 str r3, [r2, #0] +1003c0b0: 6013 str r3, [r2, #0] +1003c0b2: 6013 str r3, [r2, #0] +1003c0b4: 6013 str r3, [r2, #0] +1003c0b6: 6013 str r3, [r2, #0] +1003c0b8: 2300 movs r3, #0 + +1003c0ba : +1003c0ba: 6013 str r3, [r2, #0] +1003c0bc: 6013 str r3, [r2, #0] +1003c0be: 6013 str r3, [r2, #0] +1003c0c0: 6013 str r3, [r2, #0] +1003c0c2: 0040 lsls r0, r0, #1 +1003c0c4: 6013 str r3, [r2, #0] +1003c0c6: 1e49 subs r1, r1, #1 +1003c0c8: d1e0 bne.n 1003c08c +1003c0ca: 4770 bx lr + +1003c0cc : +1003c0cc: b510 push {r4, lr} +1003c0ce: 4c5b ldr r4, [pc, #364] ; (1003c23c ) +1003c0d0: 7860 ldrb r0, [r4, #1] +1003c0d2: f7ff ffd9 bl 1003c088 +1003c0d6: 7820 ldrb r0, [r4, #0] +1003c0d8: f7ff ffd6 bl 1003c088 +1003c0dc: 78a0 ldrb r0, [r4, #2] +1003c0de: e8bd 4010 ldmia.w sp!, {r4, lr} +1003c0e2: e7d1 b.n 1003c088 + +1003c0e4 : +1003c0e4: b570 push {r4, r5, r6, lr} +1003c0e6: b082 sub sp, #8 +1003c0e8: 4604 mov r4, r0 +1003c0ea: 460d mov r5, r1 +1003c0ec: 4616 mov r6, r2 +1003c0ee: 9600 str r6, [sp, #0] +1003c0f0: 462b mov r3, r5 +1003c0f2: 4622 mov r2, r4 +1003c0f4: f20f 11a8 addw r1, pc, #424 ; 0x1a8 +1003c0f8: f20f 10b8 addw r0, pc, #440 ; 0x1b8 +1003c0fc: f7f9 ff4e bl 10035f9c +1003c100: 484e ldr r0, [pc, #312] ; (1003c23c ) +1003c102: 7004 strb r4, [r0, #0] +1003c104: 7045 strb r5, [r0, #1] +1003c106: 7086 strb r6, [r0, #2] +1003c108: bd73 pop {r0, r1, r4, r5, r6, pc} + +1003c10a : +1003c10a: b510 push {r4, lr} +1003c10c: f7cf f890 bl 1000b230 +1003c110: 243c movs r4, #60 ; 0x3c + +1003c112 : +1003c112: f7ff ffdb bl 1003c0cc +1003c116: 1e64 subs r4, r4, #1 +1003c118: d1fb bne.n 1003c112 +1003c11a: e8bd 4010 ldmia.w sp!, {r4, lr} +1003c11e: f7cf b893 b.w 1000b248 + +1003c122 : +1003c122: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +1003c126: 2400 movs r4, #0 +1003c128: f06f 0806 mvn.w r8, #6 +1003c12c: f7ce fde5 bl 1000acfa +1003c130: f8df 910c ldr.w r9, [pc, #268] ; 1003c240 +1003c134: 9000 str r0, [sp, #0] +1003c136: f109 07b4 add.w r7, r9, #180 ; 0xb4 +1003c13a: e01e b.n 1003c17a + +1003c13c : +1003c13c: eb05 0645 add.w r6, r5, r5, lsl #1 +1003c140: f816 0009 ldrb.w r0, [r6, r9] +1003c144: f7ff ffa0 bl 1003c088 +1003c148: 444e add r6, r9 +1003c14a: 7870 ldrb r0, [r6, #1] +1003c14c: f7ff ff9c bl 1003c088 +1003c150: 78b0 ldrb r0, [r6, #2] + +1003c152 : +1003c152: f7ff ff99 bl 1003c088 +1003c156: 1c6d adds r5, r5, #1 +1003c158: 2d3c cmp r5, #60 ; 0x3c +1003c15a: db28 blt.n 1003c1ae +1003c15c: f7cf f874 bl 1000b248 +1003c160: 1c60 adds r0, r4, #1 +1003c162: 2143 movs r1, #67 ; 0x43 +1003c164: fb90 f1f1 sdiv r1, r0, r1 +1003c168: 2243 movs r2, #67 ; 0x43 +1003c16a: fb02 0411 mls r4, r2, r1, r0 +1003c16e: f1a4 0807 sub.w r8, r4, #7 + +1003c172 : +1003c172: 88f9 ldrh r1, [r7, #6] +1003c174: a800 add r0, sp, #0 +1003c176: f7ce fc88 bl 1000aa8a + +1003c17a : +1003c17a: f899 00b4 ldrb.w r0, [r9, #180] ; 0xb4 +1003c17e: b180 cbz r0, 1003c1a2 +1003c180: 68b8 ldr r0, [r7, #8] +1003c182: b118 cbz r0, 1003c18c +1003c184: 793a ldrb r2, [r7, #4] +1003c186: 78f9 ldrb r1, [r7, #3] +1003c188: 78b8 ldrb r0, [r7, #2] +1003c18a: e001 b.n 1003c190 + +1003c18c : +1003c18c: 2200 movs r2, #0 +1003c18e: 2100 movs r1, #0 + +1003c190 : +1003c190: f7ff ffa8 bl 1003c0e4 +1003c194: f7ff ffb9 bl 1003c10a +1003c198: 68b8 ldr r0, [r7, #8] +1003c19a: f080 0001 eor.w r0, r0, #1 +1003c19e: 60b8 str r0, [r7, #8] +1003c1a0: e7e7 b.n 1003c172 + +1003c1a2 : +1003c1a2: 7878 ldrb r0, [r7, #1] +1003c1a4: 2800 cmp r0, #0 +1003c1a6: d0e4 beq.n 1003c172 +1003c1a8: f7cf f842 bl 1000b230 +1003c1ac: 2500 movs r5, #0 + +1003c1ae : +1003c1ae: 42ac cmp r4, r5 +1003c1b0: bfa8 it ge +1003c1b2: 4545 cmpge r5, r8 +1003c1b4: dbc2 blt.n 1003c13c +1003c1b6: 78f8 ldrb r0, [r7, #3] +1003c1b8: 1b2e subs r6, r5, r4 +1003c1ba: f000 f809 bl 1003c1d0 + +1003c1be : +1003c1be: 78b8 ldrb r0, [r7, #2] +1003c1c0: f000 f806 bl 1003c1d0 + +1003c1c4 : +1003c1c4: 7938 ldrb r0, [r7, #4] +1003c1c6: 08c1 lsrs r1, r0, #3 +1003c1c8: fb06 0001 mla r0, r6, r1, r0 +1003c1cc: b2c0 uxtb r0, r0 +1003c1ce: e7c0 b.n 1003c152 + +1003c1d0 : +1003c1d0: 08c1 lsrs r1, r0, #3 +1003c1d2: fb06 0001 mla r0, r6, r1, r0 +1003c1d6: b2c0 uxtb r0, r0 +1003c1d8: e756 b.n 1003c088 + +1003c1da <_init>: +1003c1da: b51f push {r0, r1, r2, r3, r4, lr} +1003c1dc: f20f 01f0 addw r1, pc, #240 ; 0xf0 +1003c1e0: a014 add r0, pc, #80 ; (adr r0, 1003c234 ) +1003c1e2: f7f9 fedb bl 10035f9c +1003c1e6: 4c17 ldr r4, [pc, #92] ; (1003c244 ) +1003c1e8: 2100 movs r1, #0 +1003c1ea: 4620 mov r0, r4 +1003c1ec: f7f9 fe32 bl 10035e54 +1003c1f0: 2101 movs r1, #1 +1003c1f2: 4620 mov r0, r4 +1003c1f4: f7f9 fe4a bl 10035e8c +1003c1f8: 2100 movs r1, #0 +1003c1fa: 4620 mov r0, r4 +1003c1fc: f7f9 fe3b bl 10035e76 +1003c200: 4911 ldr r1, [pc, #68] ; (1003c248 ) +1003c202: 4812 ldr r0, [pc, #72] ; (1003c24c ) +1003c204: 6008 str r0, [r1, #0] +1003c206: f001 fa82 bl 1003d70e +1003c20a: 2100 movs r1, #0 +1003c20c: 9103 str r1, [sp, #12] +1003c20e: 9102 str r1, [sp, #8] +1003c210: 9101 str r1, [sp, #4] +1003c212: 2101 movs r1, #1 +1003c214: 9100 str r1, [sp, #0] +1003c216: f44f 727a mov.w r2, #1000 ; 0x3e8 +1003c21a: 480d ldr r0, [pc, #52] ; (1003c250 ) +1003c21c: f20f 01b8 addw r1, pc, #184 ; 0xb8 +1003c220: 4603 mov r3, r0 +1003c222: f7ce fb81 bl 1000a928 +1003c226: e8bd 401f ldmia.w sp!, {r0, r1, r2, r3, r4, lr} +1003c22a: f7ce bce6 b.w 1000abfa + ... + +1003c230 : +1003c230: 0031 0000 1... + +1003c234 : +1003c234: 7325 000a %s.. + +1003c238 : +1003c238: 1000 4000 ...@ + +1003c23c : +1003c23c: 8b12 1004 .... + +1003c240 : +1003c240: 40a0 1004 .@.. + +1003c244 : +1003c244: 815c 1004 \... + +1003c248 : +1003c248: 8320 1004 ... + +1003c24c : +1003c24c: c059 1003 Y... + +1003c250 : +1003c250: c123 1003 #... + +1003c254 : +1003c254: 775f 616c 5f6e 6e69 7469 645f 6e6f 5f65 _wlan_init_done_ +1003c264: 6163 6c6c 6162 6b63 0000 0000 callback.... + +1003c270 : +1003c270: 7325 2928 000a 0000 %s().... + +1003c278 : +1003c278: 6d61 6265 5f61 6d73 7261 5f74 696c 6867 ameba_smart_ligh +1003c288: 6974 676e 0000 0000 ting.... + +1003c290 : +1003c290: 7270 736f 6563 646e 6d61 6265 0061 0000 proscendameba... + +1003c2a0 : +1003c2a0: 6941 575f 3253 3138 5f31 6573 4374 6c6f Ai_WS2811_setCol +1003c2b0: 726f 0000 or.. + +1003c2b4 : +1003c2b4: 7325 203a 7228 672c 622c 2029 203d 2528 %s: (r,g,b) = (% +1003c2c4: 2c64 6425 252c 2964 000a 0000 d,%d,%d).... + +1003c2d0 : +1003c2d0: 695f 696e 0074 0000 _init... + +1003c2d8 : +1003c2d8: 6154 6b73 0000 0000 Task.... + +1003c2e0 : +1003c2e0: b570 push {r4, r5, r6, lr} +1003c2e2: 0004 movs r4, r0 +1003c2e4: 460d mov r5, r1 +1003c2e6: d101 bne.n 1003c2ec +1003c2e8: b1e5 cbz r5, 1003c324 +1003c2ea: e000 b.n 1003c2ee + +1003c2ec : +1003c2ec: b915 cbnz r5, 1003c2f4 + +1003c2ee : +1003c2ee: 2001 movs r0, #1 +1003c2f0: bd70 pop {r4, r5, r6, pc} + +1003c2f2 : +1003c2f2: 1c6d adds r5, r5, #1 + +1003c2f4 : +1003c2f4: f994 0000 ldrsb.w r0, [r4] +1003c2f8: f001 fa5e bl 1003d7b8 +1003c2fc: 4606 mov r6, r0 +1003c2fe: f995 0000 ldrsb.w r0, [r5] +1003c302: f001 fa59 bl 1003d7b8 +1003c306: 4286 cmp r6, r0 +1003c308: d104 bne.n 1003c314 +1003c30a: f914 0b01 ldrsb.w r0, [r4], #1 +1003c30e: 2800 cmp r0, #0 +1003c310: d1ef bne.n 1003c2f2 +1003c312: bd70 pop {r4, r5, r6, pc} + +1003c314 : +1003c314: 7820 ldrb r0, [r4, #0] +1003c316: f001 fa4f bl 1003d7b8 +1003c31a: 4604 mov r4, r0 +1003c31c: 7828 ldrb r0, [r5, #0] +1003c31e: f001 fa4b bl 1003d7b8 +1003c322: 1a20 subs r0, r4, r0 + +1003c324 : +1003c324: bd70 pop {r4, r5, r6, pc} + +1003c326 : +1003c326: b530 push {r4, r5, lr} +1003c328: f8df 1630 ldr.w r1, [pc, #1584] ; 1003c95c +1003c32c: f8df 2628 ldr.w r2, [pc, #1576] ; 1003c958 +1003c330: f8df 362c ldr.w r3, [pc, #1580] ; 1003c960 +1003c334: b908 cbnz r0, 1003c33a +1003c336: 6053 str r3, [r2, #4] +1003c338: e008 b.n 1003c34c + +1003c33a : +1003c33a: 6804 ldr r4, [r0, #0] +1003c33c: 0025 movs r5, r4 +1003c33e: bf18 it ne +1003c340: 4623 movne r3, r4 +1003c342: 6053 str r3, [r2, #4] +1003c344: 6840 ldr r0, [r0, #4] +1003c346: 0003 movs r3, r0 +1003c348: bf18 it ne +1003c34a: 4601 movne r1, r0 + +1003c34c : +1003c34c: 6091 str r1, [r2, #8] +1003c34e: bd30 pop {r4, r5, pc} + +1003c350 : +1003c350: b510 push {r4, lr} +1003c352: f8df 1604 ldr.w r1, [pc, #1540] ; 1003c958 +1003c356: 6849 ldr r1, [r1, #4] +1003c358: 2028 movs r0, #40 ; 0x28 +1003c35a: 4788 blx r1 +1003c35c: 0004 movs r4, r0 +1003c35e: bf1c itt ne +1003c360: 2128 movne r1, #40 ; 0x28 +1003c362: f7d1 fee7 blne 1000e134 <__aeabi_memclr> +1003c366: 4620 mov r0, r4 +1003c368: bd10 pop {r4, pc} + +1003c36a : +1003c36a: b570 push {r4, r5, r6, lr} +1003c36c: 0004 movs r4, r0 +1003c36e: f8df 65e8 ldr.w r6, [pc, #1512] ; 1003c958 +1003c372: e016 b.n 1003c3a2 + +1003c374 : +1003c374: 68e0 ldr r0, [r4, #12] +1003c376: 6825 ldr r5, [r4, #0] +1003c378: 05c0 lsls r0, r0, #23 +1003c37a: d403 bmi.n 1003c384 +1003c37c: 68a0 ldr r0, [r4, #8] +1003c37e: b108 cbz r0, 1003c384 +1003c380: f7ff fff3 bl 1003c36a + +1003c384 : +1003c384: 68e0 ldr r0, [r4, #12] +1003c386: 05c0 lsls r0, r0, #23 +1003c388: d403 bmi.n 1003c392 +1003c38a: 6920 ldr r0, [r4, #16] +1003c38c: b108 cbz r0, 1003c392 +1003c38e: 68b1 ldr r1, [r6, #8] +1003c390: 4788 blx r1 + +1003c392 : +1003c392: 6a20 ldr r0, [r4, #32] +1003c394: b108 cbz r0, 1003c39a +1003c396: 68b1 ldr r1, [r6, #8] +1003c398: 4788 blx r1 + +1003c39a : +1003c39a: 68b1 ldr r1, [r6, #8] +1003c39c: 4620 mov r0, r4 +1003c39e: 4788 blx r1 +1003c3a0: 002c movs r4, r5 + +1003c3a2 : +1003c3a2: d1e7 bne.n 1003c374 +1003c3a4: bd70 pop {r4, r5, r6, pc} + +1003c3a6 : +1003c3a6: e92d 4bf9 stmdb sp!, {r0, r3, r4, r5, r6, r7, r8, r9, fp, lr} +1003c3aa: b082 sub sp, #8 +1003c3ac: 2001 movs r0, #1 +1003c3ae: 460e mov r6, r1 +1003c3b0: 2400 movs r4, #0 +1003c3b2: 9000 str r0, [sp, #0] +1003c3b4: 2500 movs r5, #0 +1003c3b6: 5730 ldrsb r0, [r6, r4] +1003c3b8: f8df b5a8 ldr.w fp, [pc, #1448] ; 1003c964 +1003c3bc: 46a0 mov r8, r4 +1003c3be: 46a9 mov r9, r5 +1003c3c0: 4627 mov r7, r4 +1003c3c2: 282d cmp r0, #45 ; 0x2d +1003c3c4: bf04 itt eq +1003c3c6: f8df b5a0 ldreq.w fp, [pc, #1440] ; 1003c968 +1003c3ca: 1c76 addeq r6, r6, #1 +1003c3cc: 5730 ldrsb r0, [r6, r4] +1003c3ce: 2830 cmp r0, #48 ; 0x30 +1003c3d0: bf08 it eq +1003c3d2: 1c76 addeq r6, r6, #1 +1003c3d4: 5730 ldrsb r0, [r6, r4] +1003c3d6: 3831 subs r0, #49 ; 0x31 +1003c3d8: 2809 cmp r0, #9 +1003c3da: d212 bcs.n 1003c402 + +1003c3dc : +1003c3dc: f000 f87b bl 1003c4d6 + +1003c3e0 : +1003c3e0: 4680 mov r8, r0 +1003c3e2: 5730 ldrsb r0, [r6, r4] +1003c3e4: 4689 mov r9, r1 +1003c3e6: 3830 subs r0, #48 ; 0x30 +1003c3e8: f7c9 ff40 bl 1000626c <__aeabi_i2d> +1003c3ec: 4642 mov r2, r8 +1003c3ee: 464b mov r3, r9 +1003c3f0: f7c9 fea2 bl 10006138 <__aeabi_dadd> +1003c3f4: 4680 mov r8, r0 +1003c3f6: f916 0f01 ldrsb.w r0, [r6, #1]! +1003c3fa: 3830 subs r0, #48 ; 0x30 +1003c3fc: 4689 mov r9, r1 +1003c3fe: 280a cmp r0, #10 +1003c400: d3ec bcc.n 1003c3dc + +1003c402 : +1003c402: 5730 ldrsb r0, [r6, r4] +1003c404: 282e cmp r0, #46 ; 0x2e +1003c406: d121 bne.n 1003c44c +1003c408: f996 0001 ldrsb.w r0, [r6, #1] +1003c40c: 3830 subs r0, #48 ; 0x30 +1003c40e: 280a cmp r0, #10 +1003c410: d21c bcs.n 1003c44c +1003c412: 1c76 adds r6, r6, #1 + +1003c414 : +1003c414: f000 f85f bl 1003c4d6 + +1003c418 : +1003c418: 4680 mov r8, r0 +1003c41a: 57f0 ldrsb r0, [r6, r7] +1003c41c: 4689 mov r9, r1 +1003c41e: 3830 subs r0, #48 ; 0x30 +1003c420: f7c9 ff24 bl 1000626c <__aeabi_i2d> +1003c424: 4642 mov r2, r8 +1003c426: 464b mov r3, r9 +1003c428: f7c9 fe86 bl 10006138 <__aeabi_dadd> +1003c42c: 4680 mov r8, r0 +1003c42e: 4689 mov r9, r1 +1003c430: 4638 mov r0, r7 +1003c432: f8df 1534 ldr.w r1, [pc, #1332] ; 1003c968 +1003c436: 4622 mov r2, r4 +1003c438: 462b mov r3, r5 +1003c43a: f7c9 fe7d bl 10006138 <__aeabi_dadd> +1003c43e: 4604 mov r4, r0 +1003c440: f916 0f01 ldrsb.w r0, [r6, #1]! +1003c444: 3830 subs r0, #48 ; 0x30 +1003c446: 460d mov r5, r1 +1003c448: 280a cmp r0, #10 +1003c44a: d3e3 bcc.n 1003c414 + +1003c44c : +1003c44c: 57f0 ldrsb r0, [r6, r7] +1003c44e: 2865 cmp r0, #101 ; 0x65 +1003c450: bf18 it ne +1003c452: 2845 cmpne r0, #69 ; 0x45 +1003c454: d116 bne.n 1003c484 +1003c456: f916 0f01 ldrsb.w r0, [r6, #1]! +1003c45a: 282b cmp r0, #43 ; 0x2b +1003c45c: d004 beq.n 1003c468 +1003c45e: 282d cmp r0, #45 ; 0x2d +1003c460: d10b bne.n 1003c47a +1003c462: f04f 30ff mov.w r0, #4294967295 +1003c466: 9000 str r0, [sp, #0] + +1003c468 : +1003c468: 1c76 adds r6, r6, #1 +1003c46a: e006 b.n 1003c47a + +1003c46c : +1003c46c: f916 1b01 ldrsb.w r1, [r6], #1 +1003c470: 200a movs r0, #10 +1003c472: fb00 1007 mla r0, r0, r7, r1 +1003c476: f1a0 0730 sub.w r7, r0, #48 ; 0x30 + +1003c47a : +1003c47a: f996 0000 ldrsb.w r0, [r6] +1003c47e: 3830 subs r0, #48 ; 0x30 +1003c480: 280a cmp r0, #10 +1003c482: d3f3 bcc.n 1003c46c + +1003c484 : +1003c484: 4642 mov r2, r8 +1003c486: 464b mov r3, r9 +1003c488: 2000 movs r0, #0 +1003c48a: 4659 mov r1, fp +1003c48c: f7c9 fd72 bl 10005f74 <__aeabi_dmul> +1003c490: 4680 mov r8, r0 +1003c492: 9800 ldr r0, [sp, #0] +1003c494: 4689 mov r9, r1 +1003c496: 4378 muls r0, r7 +1003c498: f7c9 fee8 bl 1000626c <__aeabi_i2d> +1003c49c: 4622 mov r2, r4 +1003c49e: 462b mov r3, r5 +1003c4a0: f7c9 fe4a bl 10006138 <__aeabi_dadd> +1003c4a4: 4602 mov r2, r0 +1003c4a6: 460b mov r3, r1 +1003c4a8: 2000 movs r0, #0 +1003c4aa: f8df 14c0 ldr.w r1, [pc, #1216] ; 1003c96c +1003c4ae: f7c9 fa92 bl 100059d6 +1003c4b2: 4642 mov r2, r8 +1003c4b4: 464b mov r3, r9 +1003c4b6: f7c9 fd5d bl 10005f74 <__aeabi_dmul> +1003c4ba: 9a02 ldr r2, [sp, #8] +1003c4bc: e9c2 0106 strd r0, r1, [r2, #24] +1003c4c0: f7c9 feae bl 10006220 <__aeabi_d2iz> +1003c4c4: 9902 ldr r1, [sp, #8] +1003c4c6: 6148 str r0, [r1, #20] +1003c4c8: 2003 movs r0, #3 +1003c4ca: 9902 ldr r1, [sp, #8] +1003c4cc: 60c8 str r0, [r1, #12] +1003c4ce: b004 add sp, #16 +1003c4d0: 4630 mov r0, r6 +1003c4d2: e8bd 8bf0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, fp, pc} + +1003c4d6 : +1003c4d6: 2000 movs r0, #0 +1003c4d8: f8df 1490 ldr.w r1, [pc, #1168] ; 1003c96c +1003c4dc: 4642 mov r2, r8 +1003c4de: 464b mov r3, r9 +1003c4e0: f7c9 bd48 b.w 10005f74 <__aeabi_dmul> + +1003c4e4 : +1003c4e4: b510 push {r4, lr} +1003c4e6: f990 1000 ldrsb.w r1, [r0] +1003c4ea: f1a1 0330 sub.w r3, r1, #48 ; 0x30 +1003c4ee: 2b0a cmp r3, #10 +1003c4f0: bf38 it cc +1003c4f2: 3930 subcc r1, #48 ; 0x30 +1003c4f4: d30a bcc.n 1003c50c +1003c4f6: f1a1 0341 sub.w r3, r1, #65 ; 0x41 +1003c4fa: 2b06 cmp r3, #6 +1003c4fc: bf38 it cc +1003c4fe: 3937 subcc r1, #55 ; 0x37 +1003c500: d304 bcc.n 1003c50c +1003c502: f1a1 0261 sub.w r2, r1, #97 ; 0x61 +1003c506: 2a06 cmp r2, #6 +1003c508: d243 bcs.n 1003c592 +1003c50a: 3957 subs r1, #87 ; 0x57 + +1003c50c : +1003c50c: f910 2f01 ldrsb.w r2, [r0, #1]! +1003c510: 3a30 subs r2, #48 ; 0x30 +1003c512: 2a0a cmp r2, #10 +1003c514: f990 2000 ldrsb.w r2, [r0] +1003c518: bf38 it cc +1003c51a: 3a30 subcc r2, #48 ; 0x30 +1003c51c: d30a bcc.n 1003c534 +1003c51e: f1a2 0441 sub.w r4, r2, #65 ; 0x41 +1003c522: 2c06 cmp r4, #6 +1003c524: bf38 it cc +1003c526: 3a37 subcc r2, #55 ; 0x37 +1003c528: d304 bcc.n 1003c534 +1003c52a: f1a2 0361 sub.w r3, r2, #97 ; 0x61 +1003c52e: 2b06 cmp r3, #6 +1003c530: d22f bcs.n 1003c592 +1003c532: 3a57 subs r2, #87 ; 0x57 + +1003c534 : +1003c534: eb02 1101 add.w r1, r2, r1, lsl #4 +1003c538: f910 2f01 ldrsb.w r2, [r0, #1]! +1003c53c: 3a30 subs r2, #48 ; 0x30 +1003c53e: 2a0a cmp r2, #10 +1003c540: f990 2000 ldrsb.w r2, [r0] +1003c544: bf38 it cc +1003c546: 3a30 subcc r2, #48 ; 0x30 +1003c548: d30a bcc.n 1003c560 +1003c54a: f1a2 0441 sub.w r4, r2, #65 ; 0x41 +1003c54e: 2c06 cmp r4, #6 +1003c550: bf38 it cc +1003c552: 3a37 subcc r2, #55 ; 0x37 +1003c554: d304 bcc.n 1003c560 +1003c556: f1a2 0361 sub.w r3, r2, #97 ; 0x61 +1003c55a: 2b06 cmp r3, #6 +1003c55c: d219 bcs.n 1003c592 +1003c55e: 3a57 subs r2, #87 ; 0x57 + +1003c560 : +1003c560: eb02 1101 add.w r1, r2, r1, lsl #4 +1003c564: f910 2f01 ldrsb.w r2, [r0, #1]! +1003c568: f990 0000 ldrsb.w r0, [r0] +1003c56c: 3a30 subs r2, #48 ; 0x30 +1003c56e: 2a0a cmp r2, #10 +1003c570: d203 bcs.n 1003c57a +1003c572: 3830 subs r0, #48 ; 0x30 + +1003c574 : +1003c574: eb00 1001 add.w r0, r0, r1, lsl #4 +1003c578: bd10 pop {r4, pc} + +1003c57a : +1003c57a: f1a0 0341 sub.w r3, r0, #65 ; 0x41 +1003c57e: 2b06 cmp r3, #6 +1003c580: bf38 it cc +1003c582: 3837 subcc r0, #55 ; 0x37 +1003c584: d3f6 bcc.n 1003c574 +1003c586: f1a0 0261 sub.w r2, r0, #97 ; 0x61 +1003c58a: 2a06 cmp r2, #6 +1003c58c: bf38 it cc +1003c58e: 3857 subcc r0, #87 ; 0x57 +1003c590: d3f0 bcc.n 1003c574 + +1003c592 : +1003c592: 2000 movs r0, #0 +1003c594: bd10 pop {r4, pc} + +1003c596 : +1003c596: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +1003c59a: 4604 mov r4, r0 +1003c59c: 460f mov r7, r1 +1003c59e: 2000 movs r0, #0 +1003c5a0: 1c7d adds r5, r7, #1 +1003c5a2: 563a ldrsb r2, [r7, r0] +1003c5a4: f8df 13b0 ldr.w r1, [pc, #944] ; 1003c958 +1003c5a8: 2a22 cmp r2, #34 ; 0x22 +1003c5aa: d006 beq.n 1003c5ba +1003c5ac: 600f str r7, [r1, #0] + +1003c5ae : +1003c5ae: e0a6 b.n 1003c6fe + +1003c5b0 : +1003c5b0: f915 2b01 ldrsb.w r2, [r5], #1 +1003c5b4: 2a5c cmp r2, #92 ; 0x5c +1003c5b6: bf08 it eq +1003c5b8: 1c6d addeq r5, r5, #1 + +1003c5ba : +1003c5ba: f995 2000 ldrsb.w r2, [r5] +1003c5be: 2a22 cmp r2, #34 ; 0x22 +1003c5c0: bf18 it ne +1003c5c2: 2a00 cmpne r2, #0 +1003c5c4: d001 beq.n 1003c5ca +1003c5c6: 1c40 adds r0, r0, #1 +1003c5c8: d1f2 bne.n 1003c5b0 + +1003c5ca : +1003c5ca: 6849 ldr r1, [r1, #4] +1003c5cc: 1c40 adds r0, r0, #1 +1003c5ce: 4788 blx r1 +1003c5d0: ea5f 0900 movs.w r9, r0 +1003c5d4: bf08 it eq +1003c5d6: 2000 moveq r0, #0 +1003c5d8: d0e9 beq.n 1003c5ae +1003c5da: 1c7d adds r5, r7, #1 +1003c5dc: 464f mov r7, r9 +1003c5de: f20f 1824 addw r8, pc, #292 ; 0x124 +1003c5e2: e003 b.n 1003c5ec + +1003c5e4 : +1003c5e4: f815 0b01 ldrb.w r0, [r5], #1 +1003c5e8: f807 0b01 strb.w r0, [r7], #1 + +1003c5ec : +1003c5ec: f995 0000 ldrsb.w r0, [r5] +1003c5f0: 2822 cmp r0, #34 ; 0x22 +1003c5f2: bf18 it ne +1003c5f4: 2800 cmpne r0, #0 +1003c5f6: d077 beq.n 1003c6e8 +1003c5f8: 285c cmp r0, #92 ; 0x5c +1003c5fa: d1f3 bne.n 1003c5e4 +1003c5fc: f915 0f01 ldrsb.w r0, [r5, #1]! +1003c600: 2862 cmp r0, #98 ; 0x62 +1003c602: d00a beq.n 1003c61a +1003c604: 2866 cmp r0, #102 ; 0x66 +1003c606: d00a beq.n 1003c61e +1003c608: 286e cmp r0, #110 ; 0x6e +1003c60a: d00a beq.n 1003c622 +1003c60c: 2872 cmp r0, #114 ; 0x72 +1003c60e: d00a beq.n 1003c626 +1003c610: 2874 cmp r0, #116 ; 0x74 +1003c612: d00a beq.n 1003c62a +1003c614: 2875 cmp r0, #117 ; 0x75 +1003c616: d00a beq.n 1003c62e +1003c618: e061 b.n 1003c6de + +1003c61a : +1003c61a: 2008 movs r0, #8 +1003c61c: e060 b.n 1003c6e0 + +1003c61e : +1003c61e: 200c movs r0, #12 +1003c620: e05e b.n 1003c6e0 + +1003c622 : +1003c622: 200a movs r0, #10 +1003c624: e05c b.n 1003c6e0 + +1003c626 : +1003c626: 200d movs r0, #13 +1003c628: e05a b.n 1003c6e0 + +1003c62a : +1003c62a: 2009 movs r0, #9 +1003c62c: e058 b.n 1003c6e0 + +1003c62e : +1003c62e: 1c68 adds r0, r5, #1 +1003c630: f7ff ff58 bl 1003c4e4 +1003c634: 4606 mov r6, r0 +1003c636: 1d2d adds r5, r5, #4 +1003c638: f5a6 405c sub.w r0, r6, #56320 ; 0xdc00 +1003c63c: f5b0 6f80 cmp.w r0, #1024 ; 0x400 +1003c640: d350 bcc.n 1003c6e4 +1003c642: 2e00 cmp r6, #0 +1003c644: d04e beq.n 1003c6e4 +1003c646: f5a6 4058 sub.w r0, r6, #55296 ; 0xd800 +1003c64a: f5b0 6f80 cmp.w r0, #1024 ; 0x400 +1003c64e: d218 bcs.n 1003c682 +1003c650: f995 0001 ldrsb.w r0, [r5, #1] +1003c654: 285c cmp r0, #92 ; 0x5c +1003c656: bf04 itt eq +1003c658: f995 0002 ldrsbeq.w r0, [r5, #2] +1003c65c: 2875 cmpeq r0, #117 ; 0x75 +1003c65e: d141 bne.n 1003c6e4 +1003c660: 1ce8 adds r0, r5, #3 +1003c662: f7ff ff3f bl 1003c4e4 +1003c666: 1dad adds r5, r5, #6 +1003c668: f5a0 415c sub.w r1, r0, #56320 ; 0xdc00 +1003c66c: f5b1 6f80 cmp.w r1, #1024 ; 0x400 +1003c670: d238 bcs.n 1003c6e4 +1003c672: 05b1 lsls r1, r6, #22 +1003c674: 0580 lsls r0, r0, #22 +1003c676: 0d89 lsrs r1, r1, #22 +1003c678: 0d80 lsrs r0, r0, #22 +1003c67a: ea40 2081 orr.w r0, r0, r1, lsl #10 +1003c67e: f500 3680 add.w r6, r0, #65536 ; 0x10000 + +1003c682 : +1003c682: 2004 movs r0, #4 +1003c684: 2e80 cmp r6, #128 ; 0x80 +1003c686: d202 bcs.n 1003c68e +1003c688: 2001 movs r0, #1 +1003c68a: 1c7f adds r7, r7, #1 +1003c68c: e020 b.n 1003c6d0 + +1003c68e : +1003c68e: f5b6 6f00 cmp.w r6, #2048 ; 0x800 +1003c692: d202 bcs.n 1003c69a +1003c694: 2002 movs r0, #2 +1003c696: 1cbf adds r7, r7, #2 +1003c698: e013 b.n 1003c6c2 + +1003c69a : +1003c69a: f5b6 3f80 cmp.w r6, #65536 ; 0x10000 +1003c69e: d307 bcc.n 1003c6b0 +1003c6a0: f026 0140 bic.w r1, r6, #64 ; 0x40 +1003c6a4: f061 017f orn r1, r1, #127 ; 0x7f +1003c6a8: f807 1f03 strb.w r1, [r7, #3]! +1003c6ac: 09b6 lsrs r6, r6, #6 +1003c6ae: e001 b.n 1003c6b4 + +1003c6b0 : +1003c6b0: 2003 movs r0, #3 +1003c6b2: 1cff adds r7, r7, #3 + +1003c6b4 : +1003c6b4: f026 0140 bic.w r1, r6, #64 ; 0x40 +1003c6b8: f061 017f orn r1, r1, #127 ; 0x7f +1003c6bc: f807 1d01 strb.w r1, [r7, #-1]! +1003c6c0: 09b6 lsrs r6, r6, #6 + +1003c6c2 : +1003c6c2: f026 0140 bic.w r1, r6, #64 ; 0x40 +1003c6c6: f061 017f orn r1, r1, #127 ; 0x7f +1003c6ca: f807 1d01 strb.w r1, [r7, #-1]! +1003c6ce: 09b6 lsrs r6, r6, #6 + +1003c6d0 : +1003c6d0: f910 1008 ldrsb.w r1, [r0, r8] +1003c6d4: 4331 orrs r1, r6 +1003c6d6: f807 1d01 strb.w r1, [r7, #-1]! +1003c6da: 19c7 adds r7, r0, r7 +1003c6dc: e002 b.n 1003c6e4 + +1003c6de : +1003c6de: 7828 ldrb r0, [r5, #0] + +1003c6e0 : +1003c6e0: f807 0b01 strb.w r0, [r7], #1 + +1003c6e4 : +1003c6e4: 1c6d adds r5, r5, #1 +1003c6e6: e781 b.n 1003c5ec + +1003c6e8 : +1003c6e8: 2000 movs r0, #0 +1003c6ea: 7038 strb r0, [r7, #0] +1003c6ec: 5628 ldrsb r0, [r5, r0] +1003c6ee: 2822 cmp r0, #34 ; 0x22 +1003c6f0: bf08 it eq +1003c6f2: 1c6d addeq r5, r5, #1 +1003c6f4: f8c4 9010 str.w r9, [r4, #16] +1003c6f8: 2004 movs r0, #4 +1003c6fa: 60e0 str r0, [r4, #12] +1003c6fc: 4628 mov r0, r5 + +1003c6fe : +1003c6fe: e8bd 83f2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, pc} + ... + +1003c704 : +1003c704: 0000 e0c0 f8f0 00fc ........ + +1003c70c : +1003c70c: e000 b.n 1003c710 + +1003c70e : +1003c70e: 1c40 adds r0, r0, #1 + +1003c710 : +1003c710: b128 cbz r0, 1003c71e +1003c712: f990 1000 ldrsb.w r1, [r0] +1003c716: b111 cbz r1, 1003c71e +1003c718: b2c9 uxtb r1, r1 +1003c71a: 2921 cmp r1, #33 ; 0x21 +1003c71c: dbf7 blt.n 1003c70e + +1003c71e : +1003c71e: 4770 bx lr + +1003c720 : +1003c720: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1003c724: 4604 mov r4, r0 +1003c726: 460d mov r5, r1 +1003c728: 4616 mov r6, r2 +1003c72a: f7ff fe11 bl 1003c350 +1003c72e: 4680 mov r8, r0 +1003c730: f8df 7224 ldr.w r7, [pc, #548] ; 1003c958 +1003c734: 2000 movs r0, #0 +1003c736: 6038 str r0, [r7, #0] +1003c738: f1b8 0f00 cmp.w r8, #0 +1003c73c: d01c beq.n 1003c778 +1003c73e: 4620 mov r0, r4 +1003c740: f7ff ffe4 bl 1003c70c +1003c744: 4601 mov r1, r0 +1003c746: 4640 mov r0, r8 +1003c748: f000 f81b bl 1003c782 +1003c74c: 0004 movs r4, r0 +1003c74e: d103 bne.n 1003c758 +1003c750: 4640 mov r0, r8 +1003c752: f7ff fe0a bl 1003c36a +1003c756: e00a b.n 1003c76e + +1003c758 : +1003c758: b15e cbz r6, 1003c772 +1003c75a: f7ff ffd7 bl 1003c70c +1003c75e: 4604 mov r4, r0 +1003c760: f994 0000 ldrsb.w r0, [r4] +1003c764: b128 cbz r0, 1003c772 +1003c766: 4640 mov r0, r8 +1003c768: f7ff fdff bl 1003c36a +1003c76c: 603c str r4, [r7, #0] + +1003c76e : +1003c76e: 2000 movs r0, #0 +1003c770: e002 b.n 1003c778 + +1003c772 : +1003c772: b105 cbz r5, 1003c776 +1003c774: 602c str r4, [r5, #0] + +1003c776 : +1003c776: 4640 mov r0, r8 + +1003c778 : +1003c778: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +1003c77c : +1003c77c: 2200 movs r2, #0 +1003c77e: 2100 movs r1, #0 +1003c780: e7ce b.n 1003c720 + +1003c782 : +1003c782: b5f8 push {r3, r4, r5, r6, r7, lr} +1003c784: 4607 mov r7, r0 +1003c786: 000e movs r6, r1 +1003c788: d074 beq.n 1003c874 +1003c78a: 2204 movs r2, #4 +1003c78c: f20f 11e0 addw r1, pc, #480 ; 0x1e0 +1003c790: 4630 mov r0, r6 +1003c792: f001 f817 bl 1003d7c4 +1003c796: b910 cbnz r0, 1003c79e +1003c798: 2002 movs r0, #2 +1003c79a: 60f8 str r0, [r7, #12] +1003c79c: e013 b.n 1003c7c6 + +1003c79e : +1003c79e: 2205 movs r2, #5 +1003c7a0: f20f 11d4 addw r1, pc, #468 ; 0x1d4 +1003c7a4: 4630 mov r0, r6 +1003c7a6: f001 f80d bl 1003d7c4 +1003c7aa: b910 cbnz r0, 1003c7b2 +1003c7ac: 60f8 str r0, [r7, #12] +1003c7ae: 1d70 adds r0, r6, #5 +1003c7b0: bdf2 pop {r1, r4, r5, r6, r7, pc} + +1003c7b2 : +1003c7b2: 2204 movs r2, #4 +1003c7b4: f20f 11c8 addw r1, pc, #456 ; 0x1c8 +1003c7b8: 4630 mov r0, r6 +1003c7ba: f001 f803 bl 1003d7c4 +1003c7be: b920 cbnz r0, 1003c7ca +1003c7c0: 2001 movs r0, #1 +1003c7c2: 60f8 str r0, [r7, #12] +1003c7c4: 6178 str r0, [r7, #20] + +1003c7c6 : +1003c7c6: 1d30 adds r0, r6, #4 +1003c7c8: bdf2 pop {r1, r4, r5, r6, r7, pc} + +1003c7ca : +1003c7ca: f996 0000 ldrsb.w r0, [r6] +1003c7ce: 4601 mov r1, r0 +1003c7d0: 2922 cmp r1, #34 ; 0x22 +1003c7d2: d104 bne.n 1003c7de +1003c7d4: 4631 mov r1, r6 +1003c7d6: 4638 mov r0, r7 +1003c7d8: e8bd 40f4 ldmia.w sp!, {r2, r4, r5, r6, r7, lr} +1003c7dc: e6db b.n 1003c596 + +1003c7de : +1003c7de: 292d cmp r1, #45 ; 0x2d +1003c7e0: d002 beq.n 1003c7e8 +1003c7e2: 3830 subs r0, #48 ; 0x30 +1003c7e4: 280a cmp r0, #10 +1003c7e6: d204 bcs.n 1003c7f2 + +1003c7e8 : +1003c7e8: 4631 mov r1, r6 +1003c7ea: 4638 mov r0, r7 +1003c7ec: e8bd 40f4 ldmia.w sp!, {r2, r4, r5, r6, r7, lr} +1003c7f0: e5d9 b.n 1003c3a6 + +1003c7f2 : +1003c7f2: f8df 4164 ldr.w r4, [pc, #356] ; 1003c958 +1003c7f6: 295b cmp r1, #91 ; 0x5b +1003c7f8: d134 bne.n 1003c864 +1003c7fa: d13a bne.n 1003c872 +1003c7fc: 2005 movs r0, #5 +1003c7fe: 60f8 str r0, [r7, #12] +1003c800: 1c70 adds r0, r6, #1 +1003c802: f7ff ff83 bl 1003c70c +1003c806: 4606 mov r6, r0 +1003c808: f996 0000 ldrsb.w r0, [r6] +1003c80c: 285d cmp r0, #93 ; 0x5d +1003c80e: d027 beq.n 1003c860 +1003c810: f7ff fd9e bl 1003c350 +1003c814: 0005 movs r5, r0 +1003c816: 60bd str r5, [r7, #8] +1003c818: d02c beq.n 1003c874 +1003c81a: 4630 mov r0, r6 +1003c81c: f7ff ff76 bl 1003c70c +1003c820: 4601 mov r1, r0 +1003c822: 4628 mov r0, r5 +1003c824: f7ff ffad bl 1003c782 +1003c828: f7ff ff70 bl 1003c70c +1003c82c: 0006 movs r6, r0 +1003c82e: d021 beq.n 1003c874 + +1003c830 : +1003c830: f996 0000 ldrsb.w r0, [r6] +1003c834: 282c cmp r0, #44 ; 0x2c +1003c836: d111 bne.n 1003c85c +1003c838: f7ff fd8a bl 1003c350 +1003c83c: b1d0 cbz r0, 1003c874 +1003c83e: 6028 str r0, [r5, #0] +1003c840: 6045 str r5, [r0, #4] +1003c842: 4605 mov r5, r0 +1003c844: 1c70 adds r0, r6, #1 +1003c846: f7ff ff61 bl 1003c70c +1003c84a: 4601 mov r1, r0 +1003c84c: 4628 mov r0, r5 +1003c84e: f7ff ff98 bl 1003c782 +1003c852: f7ff ff5b bl 1003c70c +1003c856: 0006 movs r6, r0 +1003c858: d1ea bne.n 1003c830 +1003c85a: e00b b.n 1003c874 + +1003c85c : +1003c85c: 285d cmp r0, #93 ; 0x5d +1003c85e: d108 bne.n 1003c872 + +1003c860 : +1003c860: 1c70 adds r0, r6, #1 +1003c862: bdf2 pop {r1, r4, r5, r6, r7, pc} + +1003c864 : +1003c864: 297b cmp r1, #123 ; 0x7b +1003c866: d104 bne.n 1003c872 +1003c868: 4631 mov r1, r6 +1003c86a: 4638 mov r0, r7 +1003c86c: e8bd 40f4 ldmia.w sp!, {r2, r4, r5, r6, r7, lr} +1003c870: e003 b.n 1003c87a + +1003c872 : +1003c872: 6026 str r6, [r4, #0] + +1003c874 : +1003c874: 2000 movs r0, #0 +1003c876: bdf2 pop {r1, r4, r5, r6, r7, pc} + ... + +1003c87a : +1003c87a: b570 push {r4, r5, r6, lr} +1003c87c: 460d mov r5, r1 +1003c87e: 4606 mov r6, r0 +1003c880: f995 0000 ldrsb.w r0, [r5] +1003c884: 287b cmp r0, #123 ; 0x7b +1003c886: d154 bne.n 1003c932 +1003c888: 2006 movs r0, #6 +1003c88a: 60f0 str r0, [r6, #12] +1003c88c: f000 f854 bl 1003c938 + +1003c890 : +1003c890: 4605 mov r5, r0 +1003c892: f995 0000 ldrsb.w r0, [r5] +1003c896: 287d cmp r0, #125 ; 0x7d +1003c898: d049 beq.n 1003c92e +1003c89a: f7ff fd59 bl 1003c350 +1003c89e: 0004 movs r4, r0 +1003c8a0: 60b4 str r4, [r6, #8] +1003c8a2: d040 beq.n 1003c926 +1003c8a4: 4628 mov r0, r5 +1003c8a6: f7ff ff31 bl 1003c70c +1003c8aa: 4601 mov r1, r0 +1003c8ac: 4620 mov r0, r4 +1003c8ae: f7ff fe72 bl 1003c596 +1003c8b2: f7ff ff2b bl 1003c70c +1003c8b6: 0005 movs r5, r0 +1003c8b8: d035 beq.n 1003c926 +1003c8ba: 6920 ldr r0, [r4, #16] +1003c8bc: 6220 str r0, [r4, #32] +1003c8be: 2000 movs r0, #0 +1003c8c0: 6120 str r0, [r4, #16] +1003c8c2: 5628 ldrsb r0, [r5, r0] +1003c8c4: 283a cmp r0, #58 ; 0x3a +1003c8c6: d134 bne.n 1003c932 +1003c8c8: f000 f836 bl 1003c938 + +1003c8cc : +1003c8cc: 4601 mov r1, r0 +1003c8ce: 4620 mov r0, r4 +1003c8d0: f7ff ff57 bl 1003c782 +1003c8d4: f7ff ff1a bl 1003c70c +1003c8d8: 0005 movs r5, r0 +1003c8da: d024 beq.n 1003c926 + +1003c8dc : +1003c8dc: f995 0000 ldrsb.w r0, [r5] +1003c8e0: 282c cmp r0, #44 ; 0x2c +1003c8e2: d122 bne.n 1003c92a +1003c8e4: f7ff fd34 bl 1003c350 +1003c8e8: b1e8 cbz r0, 1003c926 +1003c8ea: 6020 str r0, [r4, #0] +1003c8ec: 6044 str r4, [r0, #4] +1003c8ee: 4604 mov r4, r0 +1003c8f0: f000 f822 bl 1003c938 + +1003c8f4 : +1003c8f4: 4601 mov r1, r0 +1003c8f6: 4620 mov r0, r4 +1003c8f8: f7ff fe4d bl 1003c596 +1003c8fc: f7ff ff06 bl 1003c70c +1003c900: 0005 movs r5, r0 +1003c902: d010 beq.n 1003c926 +1003c904: 6920 ldr r0, [r4, #16] +1003c906: 6220 str r0, [r4, #32] +1003c908: 2000 movs r0, #0 +1003c90a: 6120 str r0, [r4, #16] +1003c90c: 5628 ldrsb r0, [r5, r0] +1003c90e: 283a cmp r0, #58 ; 0x3a +1003c910: d10f bne.n 1003c932 +1003c912: f000 f811 bl 1003c938 + +1003c916 : +1003c916: 4601 mov r1, r0 +1003c918: 4620 mov r0, r4 +1003c91a: f7ff ff32 bl 1003c782 +1003c91e: f7ff fef5 bl 1003c70c +1003c922: 0005 movs r5, r0 +1003c924: d1da bne.n 1003c8dc + +1003c926 : +1003c926: 2000 movs r0, #0 +1003c928: bd70 pop {r4, r5, r6, pc} + +1003c92a : +1003c92a: 287d cmp r0, #125 ; 0x7d +1003c92c: d101 bne.n 1003c932 + +1003c92e : +1003c92e: 1c68 adds r0, r5, #1 +1003c930: bd70 pop {r4, r5, r6, pc} + +1003c932 : +1003c932: 4809 ldr r0, [pc, #36] ; (1003c958 ) +1003c934: 6005 str r5, [r0, #0] +1003c936: e7f6 b.n 1003c926 + +1003c938 : +1003c938: 1c68 adds r0, r5, #1 +1003c93a: e6e7 b.n 1003c70c + +1003c93c : +1003c93c: b538 push {r3, r4, r5, lr} +1003c93e: 6885 ldr r5, [r0, #8] +1003c940: 460c mov r4, r1 +1003c942: e000 b.n 1003c946 + +1003c944 : +1003c944: 682d ldr r5, [r5, #0] + +1003c946 : +1003c946: b12d cbz r5, 1003c954 +1003c948: 6a28 ldr r0, [r5, #32] +1003c94a: 4621 mov r1, r4 +1003c94c: f7ff fcc8 bl 1003c2e0 +1003c950: 2800 cmp r0, #0 +1003c952: d1f7 bne.n 1003c944 + +1003c954 : +1003c954: 4628 mov r0, r5 +1003c956: bd32 pop {r1, r4, r5, pc} + +1003c958 : +1003c958: 3f28 1004 (?.. + +1003c95c : +1003c95c: 35bd 1004 .5.. + +1003c960 : +1003c960: 3307 1004 .3.. + +1003c964 : +1003c964: 0000 3ff0 ...? + +1003c968 : +1003c968: 0000 bff0 .... + +1003c96c : +1003c96c: 0000 4024 ..$@ + +1003c970 : +1003c970: 756e 6c6c 0000 0000 null.... + +1003c978 : +1003c978: 6166 736c 0065 0000 false... + +1003c980 : +1003c980: 7274 6575 0000 0000 true.... + +1003c988 : +1003c988: f8df f000 ldr.w pc, [pc] ; 1003c98c +1003c98c: 000131f5 .word 0x000131f5 + +1003c990 : +1003c990: f8df f000 ldr.w pc, [pc] ; 1003c994 +1003c994: 0001327d .word 0x0001327d + +1003c998 : +1003c998: f8df f000 ldr.w pc, [pc] ; 1003c99c +1003c99c: 000131c1 .word 0x000131c1 + +1003c9a0 : +1003c9a0: b510 push {r4, lr} +1003c9a2: 2300 movs r3, #0 +1003c9a4: e002 b.n 1003c9ac +1003c9a6: 5c1c ldrb r4, [r3, r0] +1003c9a8: 545c strb r4, [r3, r1] +1003c9aa: 1c5b adds r3, r3, #1 +1003c9ac: 4293 cmp r3, r2 +1003c9ae: d3fa bcc.n 1003c9a6 +1003c9b0: 2000 movs r0, #0 +1003c9b2: bd10 pop {r4, pc} + +1003c9b4 : +1003c9b4: f8df 17a0 ldr.w r1, [pc, #1952] ; 1003d158 <.text_34> +1003c9b8: 6a49 ldr r1, [r1, #36] ; 0x24 +1003c9ba: f8d1 29e4 ldr.w r2, [r1, #2532] ; 0x9e4 +1003c9be: eb01 0282 add.w r2, r1, r2, lsl #2 +1003c9c2: f8d2 38e4 ldr.w r3, [r2, #2276] ; 0x8e4 +1003c9c6: b90b cbnz r3, 1003c9cc +1003c9c8: f8c2 08e4 str.w r0, [r2, #2276] ; 0x8e4 +1003c9cc: f8d1 09e4 ldr.w r0, [r1, #2532] ; 0x9e4 +1003c9d0: 1c40 adds r0, r0, #1 +1003c9d2: f8c1 09e4 str.w r0, [r1, #2532] ; 0x9e4 +1003c9d6: 2000 movs r0, #0 +1003c9d8: 4770 bx lr + +1003c9da : +1003c9da: b510 push {r4, lr} +1003c9dc: 4602 mov r2, r0 +1003c9de: 2000 movs r0, #0 +1003c9e0: 6a93 ldr r3, [r2, #40] ; 0x28 +1003c9e2: 001c movs r4, r3 +1003c9e4: d003 beq.n 1003c9ee <__iar_annotation$$tailcall+0x2> +1003c9e6: e8bd 4010 ldmia.w sp!, {r4, lr} +1003c9ea: 4610 mov r0, r2 + +1003c9ec <__iar_annotation$$tailcall>: +1003c9ec: 4718 bx r3 +1003c9ee: bd10 pop {r4, pc} + +1003c9f0 : +1003c9f0: b510 push {r4, lr} +1003c9f2: 4602 mov r2, r0 +1003c9f4: 2000 movs r0, #0 +1003c9f6: 6b13 ldr r3, [r2, #48] ; 0x30 +1003c9f8: 001c movs r4, r3 +1003c9fa: d003 beq.n 1003ca04 <__iar_annotation$$tailcall+0x2> +1003c9fc: e8bd 4010 ldmia.w sp!, {r4, lr} +1003ca00: 4610 mov r0, r2 + +1003ca02 <__iar_annotation$$tailcall>: +1003ca02: 4718 bx r3 +1003ca04: bd10 pop {r4, pc} + +1003ca06 : +1003ca06: b510 push {r4, lr} +1003ca08: 4602 mov r2, r0 +1003ca0a: 2000 movs r0, #0 +1003ca0c: 6ad3 ldr r3, [r2, #44] ; 0x2c +1003ca0e: 001c movs r4, r3 +1003ca10: d003 beq.n 1003ca1a <__iar_annotation$$tailcall+0x2> +1003ca12: e8bd 4010 ldmia.w sp!, {r4, lr} +1003ca16: 4610 mov r0, r2 + +1003ca18 <__iar_annotation$$tailcall>: +1003ca18: 4718 bx r3 +1003ca1a: bd10 pop {r4, pc} + +1003ca1c : +1003ca1c: b510 push {r4, lr} +1003ca1e: 4602 mov r2, r0 +1003ca20: 2000 movs r0, #0 +1003ca22: 6b53 ldr r3, [r2, #52] ; 0x34 +1003ca24: 001c movs r4, r3 +1003ca26: d003 beq.n 1003ca30 <__iar_annotation$$tailcall+0x2> +1003ca28: e8bd 4010 ldmia.w sp!, {r4, lr} +1003ca2c: 4610 mov r0, r2 + +1003ca2e <__iar_annotation$$tailcall>: +1003ca2e: 4718 bx r3 +1003ca30: bd10 pop {r4, pc} + +1003ca32 : +1003ca32: b510 push {r4, lr} +1003ca34: 4602 mov r2, r0 +1003ca36: 2000 movs r0, #0 +1003ca38: 6b93 ldr r3, [r2, #56] ; 0x38 +1003ca3a: 001c movs r4, r3 +1003ca3c: d003 beq.n 1003ca46 <__iar_annotation$$tailcall+0x2> +1003ca3e: e8bd 4010 ldmia.w sp!, {r4, lr} +1003ca42: 4610 mov r0, r2 + +1003ca44 <__iar_annotation$$tailcall>: +1003ca44: 4718 bx r3 +1003ca46: bd10 pop {r4, pc} + +1003ca48 : +1003ca48: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1003ca4c: 4604 mov r4, r0 +1003ca4e: 4690 mov r8, r2 +1003ca50: 2600 movs r6, #0 +1003ca52: 2000 movs r0, #0 +1003ca54: e00a b.n 1003ca6c +1003ca56: 1c4f adds r7, r1, #1 +1003ca58: f104 0110 add.w r1, r4, #16 +1003ca5c: f817 5b01 ldrb.w r5, [r7], #1 +1003ca60: 462a mov r2, r5 +1003ca62: 4638 mov r0, r7 +1003ca64: f7ff ff9c bl 1003c9a0 +1003ca68: 19e9 adds r1, r5, r7 +1003ca6a: 1ca8 adds r0, r5, #2 +1003ca6c: 4540 cmp r0, r8 +1003ca6e: da13 bge.n 1003ca98 +1003ca70: 7808 ldrb r0, [r1, #0] +1003ca72: 2801 cmp r0, #1 +1003ca74: d0ef beq.n 1003ca56 +1003ca76: 2802 cmp r0, #2 +1003ca78: d103 bne.n 1003ca82 +1003ca7a: 1c4f adds r7, r1, #1 +1003ca7c: f104 0130 add.w r1, r4, #48 ; 0x30 +1003ca80: e7ec b.n 1003ca5c +1003ca82: 2803 cmp r0, #3 +1003ca84: bf01 itttt eq +1003ca86: 1c4f addeq r7, r1, #1 +1003ca88: f817 5b01 ldrbeq.w r5, [r7], #1 +1003ca8c: 462a moveq r2, r5 +1003ca8e: f104 0174 addeq.w r1, r4, #116 ; 0x74 +1003ca92: d0e6 beq.n 1003ca62 +1003ca94: b100 cbz r0, 1003ca98 +1003ca96: e7fe b.n 1003ca96 +1003ca98: 6f60 ldr r0, [r4, #116] ; 0x74 +1003ca9a: b908 cbnz r0, 1003caa0 +1003ca9c: f04f 36ff mov.w r6, #4294967295 +1003caa0: 4630 mov r0, r6 +1003caa2: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +1003caa6 : +1003caa6: 2000 movs r0, #0 +1003caa8: e008 b.n 1003cabc +1003caaa: 2206 movs r2, #6 +1003caac: fb02 1200 mla r2, r2, r0, r1 +1003cab0: 1843 adds r3, r0, r1 +1003cab2: f892 20b3 ldrb.w r2, [r2, #179] ; 0xb3 +1003cab6: f883 27dc strb.w r2, [r3, #2012] ; 0x7dc +1003caba: 1c40 adds r0, r0, #1 +1003cabc: f8d1 26b0 ldr.w r2, [r1, #1712] ; 0x6b0 +1003cac0: 4290 cmp r0, r2 +1003cac2: d3f2 bcc.n 1003caaa +1003cac4: f8c1 28dc str.w r2, [r1, #2268] ; 0x8dc +1003cac8: 2000 movs r0, #0 +1003caca: 4770 bx lr + +1003cacc : +1003cacc: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1003cad0: b0dc sub sp, #368 ; 0x170 +1003cad2: 4605 mov r5, r0 +1003cad4: 460c mov r4, r1 +1003cad6: f44f 7280 mov.w r2, #256 ; 0x100 +1003cada: 2100 movs r1, #0 +1003cadc: a81b add r0, sp, #108 ; 0x6c +1003cade: f7cf fc35 bl 1000c34c +1003cae2: f8df 6674 ldr.w r6, [pc, #1652] ; 1003d158 <.text_34> +1003cae6: 6a30 ldr r0, [r6, #32] +1003cae8: 2800 cmp r0, #0 +1003caea: bf19 ittee ne +1003caec: 2206 movne r2, #6 +1003caee: f106 0134 addne.w r1, r6, #52 ; 0x34 +1003caf2: 2206 moveq r2, #6 +1003caf4: 1d21 addeq r1, r4, #4 +1003caf6: a81b add r0, sp, #108 ; 0x6c +1003caf8: f7cf fc26 bl 1000c348 +1003cafc: f894 0a6a ldrb.w r0, [r4, #2666] ; 0xa6a +1003cb00: b138 cbz r0, 1003cb12 +1003cb02: f604 17e8 addw r7, r4, #2536 ; 0x9e8 +1003cb06: 4638 mov r0, r7 +1003cb08: f7cf fc26 bl 1000c358 +1003cb0c: 4602 mov r2, r0 +1003cb0e: 4639 mov r1, r7 +1003cb10: e002 b.n 1003cb18 +1003cb12: 69f2 ldr r2, [r6, #28] +1003cb14: f604 2129 addw r1, r4, #2601 ; 0xa29 +1003cb18: f10d 0072 add.w r0, sp, #114 ; 0x72 +1003cb1c: f7cf fc14 bl 1000c348 +1003cb20: 69f0 ldr r0, [r6, #28] +1003cb22: f20f 68f0 addw r8, pc, #1776 ; 0x6f0 +1003cb26: 1d87 adds r7, r0, #6 +1003cb28: 4640 mov r0, r8 +1003cb2a: f7cf fc15 bl 1000c358 +1003cb2e: 4602 mov r2, r0 +1003cb30: a81b add r0, sp, #108 ; 0x6c +1003cb32: 4641 mov r1, r8 +1003cb34: 1838 adds r0, r7, r0 +1003cb36: f7cf fc07 bl 1000c348 +1003cb3a: 4640 mov r0, r8 +1003cb3c: f7cf fc0c bl 1000c358 +1003cb40: 19c7 adds r7, r0, r7 +1003cb42: 1d30 adds r0, r6, #4 +1003cb44: f7cf fc08 bl 1000c358 +1003cb48: 4602 mov r2, r0 +1003cb4a: a81b add r0, sp, #108 ; 0x6c +1003cb4c: 1d31 adds r1, r6, #4 +1003cb4e: 1838 adds r0, r7, r0 +1003cb50: f7cf fbfa bl 1000c348 +1003cb54: 1d3e adds r6, r7, #4 +1003cb56: a805 add r0, sp, #20 +1003cb58: f7ff ff1e bl 1003c998 +1003cb5c: 4632 mov r2, r6 +1003cb5e: a91b add r1, sp, #108 ; 0x6c +1003cb60: a805 add r0, sp, #20 +1003cb62: f7ff ff11 bl 1003c988 +1003cb66: a905 add r1, sp, #20 +1003cb68: a801 add r0, sp, #4 +1003cb6a: f7ff ff11 bl 1003c990 +1003cb6e: f105 0008 add.w r0, r5, #8 +1003cb72: f7cf fbf1 bl 1000c358 +1003cb76: 4602 mov r2, r0 +1003cb78: a81b add r0, sp, #108 ; 0x6c +1003cb7a: f105 0108 add.w r1, r5, #8 +1003cb7e: 1830 adds r0, r6, r0 +1003cb80: f7cf fbe2 bl 1000c348 +1003cb84: f105 0008 add.w r0, r5, #8 +1003cb88: f7cf fbe6 bl 1000c358 +1003cb8c: f504 61f7 add.w r1, r4, #1976 ; 0x7b8 +1003cb90: 9100 str r1, [sp, #0] +1003cb92: 2310 movs r3, #16 +1003cb94: 1981 adds r1, r0, r6 +1003cb96: aa01 add r2, sp, #4 +1003cb98: a81b add r0, sp, #108 ; 0x6c +1003cb9a: f7e6 fae5 bl 10023168 +1003cb9e: 2010 movs r0, #16 +1003cba0: f8c4 07d8 str.w r0, [r4, #2008] ; 0x7d8 +1003cba4: b05c add sp, #368 ; 0x170 +1003cba6: 2000 movs r0, #0 +1003cba8: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +1003cbac : +1003cbac: b570 push {r4, r5, r6, lr} +1003cbae: f8df 55a8 ldr.w r5, [pc, #1448] ; 1003d158 <.text_34> +1003cbb2: 460c mov r4, r1 +1003cbb4: 68e9 ldr r1, [r5, #12] +1003cbb6: f06f 0001 mvn.w r0, #1 +1003cbba: 4281 cmp r1, r0 +1003cbbc: d04c beq.n 1003cc58 +1003cbbe: f894 2089 ldrb.w r2, [r4, #137] ; 0x89 +1003cbc2: f894 1083 ldrb.w r1, [r4, #131] ; 0x83 +1003cbc6: f894 307d ldrb.w r3, [r4, #125] ; 0x7d +1003cbca: eb02 2101 add.w r1, r2, r1, lsl #8 +1003cbce: eb01 4303 add.w r3, r1, r3, lsl #16 +1003cbd2: 68a9 ldr r1, [r5, #8] +1003cbd4: 2b02 cmp r3, #2 +1003cbd6: d140 bne.n 1003cc5a +1003cbd8: 2900 cmp r1, #0 +1003cbda: d16d bne.n 1003ccb8 +1003cbdc: f894 007b ldrb.w r0, [r4, #123] ; 0x7b +1003cbe0: f894 1082 ldrb.w r1, [r4, #130] ; 0x82 +1003cbe4: 1808 adds r0, r1, r0 +1003cbe6: f894 108f ldrb.w r1, [r4, #143] ; 0x8f +1003cbea: 1810 adds r0, r2, r0 +1003cbec: 1808 adds r0, r1, r0 +1003cbee: f894 1095 ldrb.w r1, [r4, #149] ; 0x95 +1003cbf2: b2c0 uxtb r0, r0 +1003cbf4: 4288 cmp r0, r1 +1003cbf6: d119 bne.n 1003cc2c +1003cbf8: 2002 movs r0, #2 +1003cbfa: 6020 str r0, [r4, #0] +1003cbfc: f20f 6658 addw r6, pc, #1624 ; 0x658 +1003cc00: f894 008f ldrb.w r0, [r4, #143] ; 0x8f +1003cc04: 3809 subs r0, #9 +1003cc06: f8c4 06b0 str.w r0, [r4, #1712] ; 0x6b0 +1003cc0a: 4630 mov r0, r6 +1003cc0c: f7cf fba4 bl 1000c358 +1003cc10: 4602 mov r2, r0 +1003cc12: 4631 mov r1, r6 +1003cc14: f604 2029 addw r0, r4, #2601 ; 0xa29 +1003cc18: f7cf fb96 bl 1000c348 +1003cc1c: 4630 mov r0, r6 +1003cc1e: f7cf fb9b bl 1000c358 +1003cc22: 61e8 str r0, [r5, #28] +1003cc24: 2100 movs r1, #0 +1003cc26: 1900 adds r0, r0, r4 +1003cc28: f880 1a29 strb.w r1, [r0, #2601] ; 0xa29 +1003cc2c: 2005 movs r0, #5 +1003cc2e: 2106 movs r1, #6 +1003cc30: fb01 4100 mla r1, r1, r0, r4 +1003cc34: 1942 adds r2, r0, r5 +1003cc36: f891 107d ldrb.w r1, [r1, #125] ; 0x7d +1003cc3a: f802 1c01 strb.w r1, [r2, #-1] +1003cc3e: 1c40 adds r0, r0, #1 +1003cc40: 2809 cmp r0, #9 +1003cc42: dbf4 blt.n 1003cc2e +1003cc44: 2001 movs r0, #1 +1003cc46: f8a4 0a6c strh.w r0, [r4, #2668] ; 0xa6c +1003cc4a: f604 206e addw r0, r4, #2670 ; 0xa6e +1003cc4e: f20f 51ac addw r1, pc, #1452 ; 0x5ac +1003cc52: f7cf fb7f bl 1000c354 +1003cc56: 2000 movs r0, #0 +1003cc58: bd70 pop {r4, r5, r6, pc} +1003cc5a: 2b03 cmp r3, #3 +1003cc5c: d12e bne.n 1003ccbc +1003cc5e: f894 307b ldrb.w r3, [r4, #123] ; 0x7b +1003cc62: f894 6082 ldrb.w r6, [r4, #130] ; 0x82 +1003cc66: 18f3 adds r3, r6, r3 +1003cc68: 18d2 adds r2, r2, r3 +1003cc6a: f894 308f ldrb.w r3, [r4, #143] ; 0x8f +1003cc6e: 189a adds r2, r3, r2 +1003cc70: f894 3095 ldrb.w r3, [r4, #149] ; 0x95 +1003cc74: b2d2 uxtb r2, r2 +1003cc76: 429a cmp r2, r3 +1003cc78: d1d8 bne.n 1003cc2c +1003cc7a: 2203 movs r2, #3 +1003cc7c: 6022 str r2, [r4, #0] +1003cc7e: f894 208f ldrb.w r2, [r4, #143] ; 0x8f +1003cc82: 3a09 subs r2, #9 +1003cc84: f8c4 26b0 str.w r2, [r4, #1712] ; 0x6b0 +1003cc88: 2201 movs r2, #1 +1003cc8a: f884 2a6a strb.w r2, [r4, #2666] ; 0xa6a +1003cc8e: b199 cbz r1, 1003ccb8 +1003cc90: 4608 mov r0, r1 +1003cc92: f7cf fb61 bl 1000c358 +1003cc96: 61e8 str r0, [r5, #28] +1003cc98: b140 cbz r0, 1003ccac +1003cc9a: 68a8 ldr r0, [r5, #8] +1003cc9c: f7cf fb5c bl 1000c358 +1003cca0: 4602 mov r2, r0 +1003cca2: 68a9 ldr r1, [r5, #8] +1003cca4: f604 10e8 addw r0, r4, #2536 ; 0x9e8 +1003cca8: f7cf fb4e bl 1000c348 +1003ccac: 69e9 ldr r1, [r5, #28] +1003ccae: 1909 adds r1, r1, r4 +1003ccb0: 2000 movs r0, #0 +1003ccb2: f881 09e8 strb.w r0, [r1, #2536] ; 0x9e8 +1003ccb6: e7b9 b.n 1003cc2c +1003ccb8: 60e8 str r0, [r5, #12] +1003ccba: bd70 pop {r4, r5, r6, pc} +1003ccbc: f04f 30ff mov.w r0, #4294967295 +1003ccc0: bd70 pop {r4, r5, r6, pc} + +1003ccc2 : +1003ccc2: b570 push {r4, r5, r6, lr} +1003ccc4: 460c mov r4, r1 +1003ccc6: b086 sub sp, #24 +1003ccc8: f8d4 07b4 ldr.w r0, [r4, #1972] ; 0x7b4 +1003cccc: f1a0 0508 sub.w r5, r0, #8 +1003ccd0: f204 66b4 addw r6, r4, #1716 ; 0x6b4 +1003ccd4: 2208 movs r2, #8 +1003ccd6: f20f 518c addw r1, pc, #1420 ; 0x58c +1003ccda: 4630 mov r0, r6 +1003ccdc: f7cf fb32 bl 1000c344 +1003cce0: b1a0 cbz r0, 1003cd0c +1003cce2: 79f0 ldrb r0, [r6, #7] +1003cce4: 9004 str r0, [sp, #16] +1003cce6: 79b0 ldrb r0, [r6, #6] +1003cce8: 9003 str r0, [sp, #12] +1003ccea: 7970 ldrb r0, [r6, #5] +1003ccec: 9002 str r0, [sp, #8] +1003ccee: 7930 ldrb r0, [r6, #4] +1003ccf0: 9001 str r0, [sp, #4] +1003ccf2: 78f0 ldrb r0, [r6, #3] +1003ccf4: 9000 str r0, [sp, #0] +1003ccf6: 78b3 ldrb r3, [r6, #2] +1003ccf8: 7872 ldrb r2, [r6, #1] +1003ccfa: f894 16b4 ldrb.w r1, [r4, #1716] ; 0x6b4 +1003ccfe: f20f 4074 addw r0, pc, #1140 ; 0x474 +1003cd02: f7cf fafe bl 1000c302 +1003cd06: f04f 30ff mov.w r0, #4294967295 +1003cd0a: e007 b.n 1003cd1c +1003cd0c: b2ea uxtb r2, r5 +1003cd0e: f204 61bc addw r1, r4, #1724 ; 0x6bc +1003cd12: 4620 mov r0, r4 +1003cd14: b006 add sp, #24 +1003cd16: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +1003cd1a: e695 b.n 1003ca48 +1003cd1c: b006 add sp, #24 +1003cd1e: bd70 pop {r4, r5, r6, pc} + +1003cd20 : +1003cd20: b510 push {r4, lr} +1003cd22: b082 sub sp, #8 +1003cd24: 460c mov r4, r1 +1003cd26: f204 60b4 addw r0, r4, #1716 ; 0x6b4 +1003cd2a: 9000 str r0, [sp, #0] +1003cd2c: f8d4 37d8 ldr.w r3, [r4, #2008] ; 0x7d8 +1003cd30: f8d4 18dc ldr.w r1, [r4, #2268] ; 0x8dc +1003cd34: f504 62f7 add.w r2, r4, #1976 ; 0x7b8 +1003cd38: f204 70dc addw r0, r4, #2012 ; 0x7dc +1003cd3c: f7e6 fa28 bl 10023190 +1003cd40: f8d4 08dc ldr.w r0, [r4, #2268] ; 0x8dc +1003cd44: f8c4 07b4 str.w r0, [r4, #1972] ; 0x7b4 +1003cd48: 2000 movs r0, #0 +1003cd4a: bd16 pop {r1, r2, r4, pc} + +1003cd4c : +1003cd4c: b510 push {r4, lr} +1003cd4e: 2100 movs r1, #0 +1003cd50: 2300 movs r3, #0 +1003cd52: 5c1c ldrb r4, [r3, r0] +1003cd54: 1861 adds r1, r4, r1 +1003cd56: 1c5b adds r3, r3, #1 +1003cd58: 2b06 cmp r3, #6 +1003cd5a: b2c9 uxtb r1, r1 +1003cd5c: dbf9 blt.n 1003cd52 +1003cd5e: b949 cbnz r1, 1003cd74 +1003cd60: 78c0 ldrb r0, [r0, #3] +1003cd62: f100 012a add.w r1, r0, #42 ; 0x2a +1003cd66: 428a cmp r2, r1 +1003cd68: bf1c itt ne +1003cd6a: 3026 addne r0, #38 ; 0x26 +1003cd6c: 4282 cmpne r2, r0 +1003cd6e: d101 bne.n 1003cd74 +1003cd70: 2001 movs r0, #1 +1003cd72: bd10 pop {r4, pc} +1003cd74: 2000 movs r0, #0 +1003cd76: bd10 pop {r4, pc} + +1003cd78 : +1003cd78: b510 push {r4, lr} +1003cd7a: f8df 43dc ldr.w r4, [pc, #988] ; 1003d158 <.text_34> +1003cd7e: 2000 movs r0, #0 +1003cd80: 6120 str r0, [r4, #16] +1003cd82: 6160 str r0, [r4, #20] +1003cd84: 61a0 str r0, [r4, #24] +1003cd86: 2100 movs r1, #0 +1003cd88: 6a60 ldr r0, [r4, #36] ; 0x24 +1003cd8a: 6001 str r1, [r0, #0] +1003cd8c: f8c0 17b4 str.w r1, [r0, #1972] ; 0x7b4 +1003cd90: f8c0 17d8 str.w r1, [r0, #2008] ; 0x7d8 +1003cd94: f8c0 18dc str.w r1, [r0, #2268] ; 0x8dc +1003cd98: f8c0 18e0 str.w r1, [r0, #2272] ; 0x8e0 +1003cd9c: 2206 movs r2, #6 +1003cd9e: 1d00 adds r0, r0, #4 +1003cda0: f7cf fad4 bl 1000c34c +1003cda4: 6a60 ldr r0, [r4, #36] ; 0x24 +1003cda6: 2206 movs r2, #6 +1003cda8: 2100 movs r1, #0 +1003cdaa: 300a adds r0, #10 +1003cdac: f7cf face bl 1000c34c +1003cdb0: 6a60 ldr r0, [r4, #36] ; 0x24 +1003cdb2: 2220 movs r2, #32 +1003cdb4: 2100 movs r1, #0 +1003cdb6: 3010 adds r0, #16 +1003cdb8: f7cf fac8 bl 1000c34c +1003cdbc: f000 f824 bl 1003ce08 <.text_23> +1003cdc0: 3030 adds r0, #48 ; 0x30 +1003cdc2: f7cf fac3 bl 1000c34c +1003cdc6: f000 f81f bl 1003ce08 <.text_23> +1003cdca: f600 2029 addw r0, r0, #2601 ; 0xa29 +1003cdce: f7cf fabd bl 1000c34c +1003cdd2: f000 f819 bl 1003ce08 <.text_23> +1003cdd6: f600 10e8 addw r0, r0, #2536 ; 0x9e8 +1003cdda: f7cf fab7 bl 1000c34c +1003cdde: f000 f813 bl 1003ce08 <.text_23> +1003cde2: f600 206e addw r0, r0, #2670 ; 0xa6e +1003cde6: f7cf fab1 bl 1000c34c +1003cdea: 6a60 ldr r0, [r4, #36] ; 0x24 +1003cdec: 2236 movs r2, #54 ; 0x36 +1003cdee: 2100 movs r1, #0 +1003cdf0: 3078 adds r0, #120 ; 0x78 +1003cdf2: f7cf faab bl 1000c34c +1003cdf6: 6a60 ldr r0, [r4, #36] ; 0x24 +1003cdf8: f44f 62c0 mov.w r2, #1536 ; 0x600 +1003cdfc: 2100 movs r1, #0 +1003cdfe: 30ae adds r0, #174 ; 0xae +1003ce00: f7cf faa4 bl 1000c34c +1003ce04: 2000 movs r0, #0 +1003ce06: bd10 pop {r4, pc} + +1003ce08 <.text_23>: +1003ce08: 6a60 ldr r0, [r4, #36] ; 0x24 +1003ce0a: 2241 movs r2, #65 ; 0x41 +1003ce0c: 2100 movs r1, #0 +1003ce0e: 4770 bx lr + +1003ce10 : +1003ce10: b510 push {r4, lr} +1003ce12: f7ff ffb1 bl 1003cd78 +1003ce16: f000 f814 bl 1003ce42 <.text_27> +1003ce1a: 49d0 ldr r1, [pc, #832] ; (1003d15c <.text_35>) +1003ce1c: 2001 movs r0, #1 +1003ce1e: 60e0 str r0, [r4, #12] +1003ce20: 6008 str r0, [r1, #0] +1003ce22: bd10 pop {r4, pc} + +1003ce24 : +1003ce24: b580 push {r7, lr} +1003ce26: f7ff ffa7 bl 1003cd78 +1003ce2a: 49cb ldr r1, [pc, #812] ; (1003d158 <.text_34>) +1003ce2c: 2000 movs r0, #0 +1003ce2e: 60c8 str r0, [r1, #12] +1003ce30: bd01 pop {r0, pc} + +1003ce32 : +1003ce32: b510 push {r4, lr} +1003ce34: f7ff ffa0 bl 1003cd78 +1003ce38: f000 f803 bl 1003ce42 <.text_27> +1003ce3c: 2001 movs r0, #1 +1003ce3e: 60e0 str r0, [r4, #12] +1003ce40: bd10 pop {r4, pc} + +1003ce42 <.text_27>: +1003ce42: 4cc5 ldr r4, [pc, #788] ; (1003d158 <.text_34>) +1003ce44: 2206 movs r2, #6 +1003ce46: 2100 movs r1, #0 +1003ce48: f104 002c add.w r0, r4, #44 ; 0x2c +1003ce4c: f7cf ba7e b.w 1000c34c + +1003ce50 : +1003ce50: b538 push {r3, r4, r5, lr} +1003ce52: 4cc1 ldr r4, [pc, #772] ; (1003d158 <.text_34>) +1003ce54: 4605 mov r5, r0 +1003ce56: 6a60 ldr r0, [r4, #36] ; 0x24 +1003ce58: b118 cbz r0, 1003ce62 +1003ce5a: f000 f87f bl 1003cf5c <.text_32> +1003ce5e: 2000 movs r0, #0 +1003ce60: 6260 str r0, [r4, #36] ; 0x24 +1003ce62: f44f 602b mov.w r0, #2736 ; 0xab0 +1003ce66: f7d3 fccc bl 10010802 +1003ce6a: 6260 str r0, [r4, #36] ; 0x24 +1003ce6c: b910 cbnz r0, 1003ce74 +1003ce6e: f04f 30ff mov.w r0, #4294967295 +1003ce72: bd32 pop {r1, r4, r5, pc} +1003ce74: f44f 622b mov.w r2, #2736 ; 0xab0 +1003ce78: 2100 movs r1, #0 +1003ce7a: f7cf fa67 bl 1000c34c +1003ce7e: 6a61 ldr r1, [r4, #36] ; 0x24 +1003ce80: f44f 7080 mov.w r0, #256 ; 0x100 +1003ce84: f8c1 07b4 str.w r0, [r1, #1972] ; 0x7b4 +1003ce88: 68a0 ldr r0, [r4, #8] +1003ce8a: b118 cbz r0, 1003ce94 +1003ce8c: f000 f866 bl 1003cf5c <.text_32> +1003ce90: 2000 movs r0, #0 +1003ce92: 60a0 str r0, [r4, #8] +1003ce94: f104 003c add.w r0, r4, #60 ; 0x3c +1003ce98: f7ff fd8c bl 1003c9b4 +1003ce9c: f104 0078 add.w r0, r4, #120 ; 0x78 +1003cea0: f7ff fd88 bl 1003c9b4 +1003cea4: 2d00 cmp r5, #0 +1003cea6: d03d beq.n 1003cf24 +1003cea8: f000 f841 bl 1003cf2e <.text_29+0x2> +1003ceac: 2808 cmp r0, #8 +1003ceae: d216 bcs.n 1003cede +1003ceb0: 2009 movs r0, #9 +1003ceb2: f7d3 fca1 bl 100107f8 +1003ceb6: f000 f839 bl 1003cf2c <.text_29> +1003ceba: f000 f83b bl 1003cf34 <.text_30> +1003cebe: f000 f836 bl 1003cf2e <.text_29+0x2> +1003cec2: 4603 mov r3, r0 +1003cec4: 2b08 cmp r3, #8 +1003cec6: da06 bge.n 1003ced6 +1003cec8: f1c0 0108 rsb r1, r0, #8 +1003cecc: 68a0 ldr r0, [r4, #8] +1003cece: 2230 movs r2, #48 ; 0x30 +1003ced0: 1818 adds r0, r3, r0 +1003ced2: f7d3 fbf1 bl 100106b8 <__aeabi_memset> +1003ced6: 68a1 ldr r1, [r4, #8] +1003ced8: 2000 movs r0, #0 +1003ceda: 7208 strb r0, [r1, #8] +1003cedc: e022 b.n 1003cf24 +1003cede: f000 f826 bl 1003cf2e <.text_29+0x2> +1003cee2: 2808 cmp r0, #8 +1003cee4: d312 bcc.n 1003cf0c +1003cee6: f000 f822 bl 1003cf2e <.text_29+0x2> +1003ceea: 2841 cmp r0, #65 ; 0x41 +1003ceec: d20e bcs.n 1003cf0c +1003ceee: f000 f81e bl 1003cf2e <.text_29+0x2> +1003cef2: 1c40 adds r0, r0, #1 +1003cef4: f7d3 fc80 bl 100107f8 +1003cef8: f000 f818 bl 1003cf2c <.text_29> +1003cefc: f000 f81a bl 1003cf34 <.text_30> +1003cf00: f000 f815 bl 1003cf2e <.text_29+0x2> +1003cf04: 68a2 ldr r2, [r4, #8] +1003cf06: 2100 movs r1, #0 +1003cf08: 5481 strb r1, [r0, r2] +1003cf0a: e00b b.n 1003cf24 +1003cf0c: 2041 movs r0, #65 ; 0x41 +1003cf0e: f7d3 fc73 bl 100107f8 +1003cf12: 60a0 str r0, [r4, #8] +1003cf14: 2241 movs r2, #65 ; 0x41 +1003cf16: 4629 mov r1, r5 +1003cf18: f7cf fa16 bl 1000c348 +1003cf1c: 68a1 ldr r1, [r4, #8] +1003cf1e: 2000 movs r0, #0 +1003cf20: f881 0040 strb.w r0, [r1, #64] ; 0x40 +1003cf24: f7ff ff85 bl 1003ce32 +1003cf28: 2000 movs r0, #0 +1003cf2a: bd32 pop {r1, r4, r5, pc} + +1003cf2c <.text_29>: +1003cf2c: 60a0 str r0, [r4, #8] +1003cf2e: 4628 mov r0, r5 +1003cf30: f7cf ba12 b.w 1000c358 + +1003cf34 <.text_30>: +1003cf34: 4602 mov r2, r0 +1003cf36: 68a0 ldr r0, [r4, #8] +1003cf38: 4629 mov r1, r5 +1003cf3a: f7cf ba05 b.w 1000c348 + +1003cf3e : +1003cf3e: b510 push {r4, lr} +1003cf40: 4c85 ldr r4, [pc, #532] ; (1003d158 <.text_34>) +1003cf42: 68a0 ldr r0, [r4, #8] +1003cf44: b118 cbz r0, 1003cf4e +1003cf46: f000 f809 bl 1003cf5c <.text_32> +1003cf4a: 2000 movs r0, #0 +1003cf4c: 60a0 str r0, [r4, #8] +1003cf4e: 6a60 ldr r0, [r4, #36] ; 0x24 +1003cf50: b118 cbz r0, 1003cf5a +1003cf52: f000 f803 bl 1003cf5c <.text_32> +1003cf56: 2000 movs r0, #0 +1003cf58: 6260 str r0, [r4, #36] ; 0x24 +1003cf5a: bd10 pop {r4, pc} + +1003cf5c <.text_32>: +1003cf5c: 2100 movs r1, #0 +1003cf5e: f7d3 bc55 b.w 1001080c + +1003cf62 : +1003cf62: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1003cf66: 4e7c ldr r6, [pc, #496] ; (1003d158 <.text_34>) +1003cf68: f8d6 b024 ldr.w fp, [r6, #36] ; 0x24 +1003cf6c: 4604 mov r4, r0 +1003cf6e: 68f0 ldr r0, [r6, #12] +1003cf70: 2700 movs r7, #0 +1003cf72: 2500 movs r5, #0 +1003cf74: 2801 cmp r0, #1 +1003cf76: bf18 it ne +1003cf78: 2802 cmpne r0, #2 +1003cf7a: 4689 mov r9, r1 +1003cf7c: 469a mov sl, r3 +1003cf7e: f04f 0806 mov.w r8, #6 +1003cf82: d173 bne.n 1003d06c +1003cf84: f000 f8ec bl 1003d160 <.text_36> +1003cf88: 2800 cmp r0, #0 +1003cf8a: d04c beq.n 1003d026 +1003cf8c: 69b0 ldr r0, [r6, #24] +1003cf8e: 2801 cmp r0, #1 +1003cf90: d14d bne.n 1003d02e +1003cf92: f000 f8e9 bl 1003d168 <.text_37> +1003cf96: 2800 cmp r0, #0 +1003cf98: d149 bne.n 1003d02e +1003cf9a: 78e0 ldrb r0, [r4, #3] +1003cf9c: 6a71 ldr r1, [r6, #36] ; 0x24 +1003cf9e: fb08 1100 mla r1, r8, r0, r1 +1003cfa2: f891 2078 ldrb.w r2, [r1, #120] ; 0x78 +1003cfa6: 2a00 cmp r2, #0 +1003cfa8: d13d bne.n 1003d026 +1003cfaa: 2809 cmp r0, #9 +1003cfac: db0a blt.n 1003cfc4 +1003cfae: 5d28 ldrb r0, [r5, r4] +1003cfb0: 186a adds r2, r5, r1 +1003cfb2: 1c6d adds r5, r5, #1 +1003cfb4: 2d06 cmp r5, #6 +1003cfb6: f882 0078 strb.w r0, [r2, #120] ; 0x78 +1003cfba: dbf8 blt.n 1003cfae +1003cfbc: 6970 ldr r0, [r6, #20] +1003cfbe: 1c40 adds r0, r0, #1 +1003cfc0: 6170 str r0, [r6, #20] +1003cfc2: e00c b.n 1003cfde +1003cfc4: 5d2a ldrb r2, [r5, r4] +1003cfc6: 186b adds r3, r5, r1 +1003cfc8: 1c6d adds r5, r5, #1 +1003cfca: 2d06 cmp r5, #6 +1003cfcc: f883 2078 strb.w r2, [r3, #120] ; 0x78 +1003cfd0: dbf8 blt.n 1003cfc4 +1003cfd2: 6931 ldr r1, [r6, #16] +1003cfd4: 2201 movs r2, #1 +1003cfd6: fa02 f000 lsl.w r0, r2, r0 +1003cfda: 4308 orrs r0, r1 +1003cfdc: 6130 str r0, [r6, #16] +1003cfde: f240 11ff movw r1, #511 ; 0x1ff +1003cfe2: 6930 ldr r0, [r6, #16] +1003cfe4: 05c0 lsls r0, r0, #23 +1003cfe6: 0dc0 lsrs r0, r0, #23 +1003cfe8: 4288 cmp r0, r1 +1003cfea: d11c bne.n 1003d026 +1003cfec: e004 b.n 1003cff8 +1003cfee: f110 0f02 cmn.w r0, #2 +1003cff2: f000 80a8 beq.w 1003d146 +1003cff6: 1c7f adds r7, r7, #1 +1003cff8: 6a71 ldr r1, [r6, #36] ; 0x24 +1003cffa: f8d1 09e4 ldr.w r0, [r1, #2532] ; 0x9e4 +1003cffe: 4287 cmp r7, r0 +1003d000: da12 bge.n 1003d028 +1003d002: eb01 0087 add.w r0, r1, r7, lsl #2 +1003d006: f8d0 08e4 ldr.w r0, [r0, #2276] ; 0x8e4 +1003d00a: 62b0 str r0, [r6, #40] ; 0x28 +1003d00c: 2800 cmp r0, #0 +1003d00e: d0f2 beq.n 1003cff6 +1003d010: 7902 ldrb r2, [r0, #4] +1003d012: 0792 lsls r2, r2, #30 +1003d014: d5ef bpl.n 1003cff6 +1003d016: f7ff fce0 bl 1003c9da +1003d01a: 0004 movs r4, r0 +1003d01c: d1e7 bne.n 1003cfee +1003d01e: 2003 movs r0, #3 +1003d020: 60f0 str r0, [r6, #12] +1003d022: 2000 movs r0, #0 +1003d024: 6130 str r0, [r6, #16] +1003d026: e093 b.n 1003d150 +1003d028: 2000 movs r0, #0 +1003d02a: 61b0 str r0, [r6, #24] +1003d02c: e08e b.n 1003d14c +1003d02e: 69b0 ldr r0, [r6, #24] +1003d030: 2800 cmp r0, #0 +1003d032: d1f8 bne.n 1003d026 +1003d034: 6a70 ldr r0, [r6, #36] ; 0x24 +1003d036: 2206 movs r2, #6 +1003d038: 4649 mov r1, r9 +1003d03a: 1d00 adds r0, r0, #4 +1003d03c: f7cf f984 bl 1000c348 +1003d040: 6a70 ldr r0, [r6, #36] ; 0x24 +1003d042: 4642 mov r2, r8 +1003d044: 4621 mov r1, r4 +1003d046: 300a adds r0, #10 +1003d048: f7cf f97e bl 1000c348 +1003d04c: 4642 mov r2, r8 +1003d04e: f10a 0118 add.w r1, sl, #24 +1003d052: f106 002c add.w r0, r6, #44 ; 0x2c +1003d056: f7cf f977 bl 1000c348 +1003d05a: f89a 001e ldrb.w r0, [sl, #30] +1003d05e: 7030 strb r0, [r6, #0] +1003d060: 6135 str r5, [r6, #16] +1003d062: 2002 movs r0, #2 +1003d064: 60f0 str r0, [r6, #12] +1003d066: 2001 movs r0, #1 +1003d068: 61b0 str r0, [r6, #24] +1003d06a: e071 b.n 1003d150 +1003d06c: 2803 cmp r0, #3 +1003d06e: d167 bne.n 1003d140 +1003d070: f000 f876 bl 1003d160 <.text_36> +1003d074: 2800 cmp r0, #0 +1003d076: d06b beq.n 1003d150 +1003d078: f000 f876 bl 1003d168 <.text_37> +1003d07c: 2800 cmp r0, #0 +1003d07e: d167 bne.n 1003d150 +1003d080: 78e0 ldrb r0, [r4, #3] +1003d082: 2809 cmp r0, #9 +1003d084: db64 blt.n 1003d150 +1003d086: 6a71 ldr r1, [r6, #36] ; 0x24 +1003d088: 6972 ldr r2, [r6, #20] +1003d08a: f8d1 36b0 ldr.w r3, [r1, #1712] ; 0x6b0 +1003d08e: 429a cmp r2, r3 +1003d090: d00f beq.n 1003d0b2 +1003d092: fb08 1000 mla r0, r8, r0, r1 +1003d096: f890 3078 ldrb.w r3, [r0, #120] ; 0x78 +1003d09a: 2b00 cmp r3, #0 +1003d09c: d158 bne.n 1003d150 +1003d09e: 5d2b ldrb r3, [r5, r4] +1003d0a0: eb05 0800 add.w r8, r5, r0 +1003d0a4: 1c6d adds r5, r5, #1 +1003d0a6: 2d06 cmp r5, #6 +1003d0a8: f888 3078 strb.w r3, [r8, #120] ; 0x78 +1003d0ac: dbf7 blt.n 1003d09e +1003d0ae: 1c50 adds r0, r2, #1 +1003d0b0: 6170 str r0, [r6, #20] +1003d0b2: 6970 ldr r0, [r6, #20] +1003d0b4: f8d1 26b0 ldr.w r2, [r1, #1712] ; 0x6b0 +1003d0b8: 4290 cmp r0, r2 +1003d0ba: d149 bne.n 1003d150 +1003d0bc: 6237 str r7, [r6, #32] +1003d0be: 6ab0 ldr r0, [r6, #40] ; 0x28 +1003d0c0: f7ff fca1 bl 1003ca06 +1003d0c4: 6a71 ldr r1, [r6, #36] ; 0x24 +1003d0c6: 6ab0 ldr r0, [r6, #40] ; 0x28 +1003d0c8: f7ff fc92 bl 1003c9f0 +1003d0cc: 0004 movs r4, r0 +1003d0ce: d10a bne.n 1003d0e6 +1003d0d0: 6a71 ldr r1, [r6, #36] ; 0x24 +1003d0d2: 6ab0 ldr r0, [r6, #40] ; 0x28 +1003d0d4: f7ff fca2 bl 1003ca1c +1003d0d8: 0004 movs r4, r0 +1003d0da: d104 bne.n 1003d0e6 +1003d0dc: 6a71 ldr r1, [r6, #36] ; 0x24 +1003d0de: 6ab0 ldr r0, [r6, #40] ; 0x28 +1003d0e0: f7ff fca7 bl 1003ca32 +1003d0e4: 4604 mov r4, r0 +1003d0e6: b1a4 cbz r4, 1003d112 +1003d0e8: 6a71 ldr r1, [r6, #36] ; 0x24 +1003d0ea: 2001 movs r0, #1 +1003d0ec: 6230 str r0, [r6, #32] +1003d0ee: 6ab0 ldr r0, [r6, #40] ; 0x28 +1003d0f0: f7ff fc7e bl 1003c9f0 +1003d0f4: 0004 movs r4, r0 +1003d0f6: d10a bne.n 1003d10e +1003d0f8: 6a71 ldr r1, [r6, #36] ; 0x24 +1003d0fa: 6ab0 ldr r0, [r6, #40] ; 0x28 +1003d0fc: f7ff fc8e bl 1003ca1c +1003d100: 0004 movs r4, r0 +1003d102: d104 bne.n 1003d10e +1003d104: 6a71 ldr r1, [r6, #36] ; 0x24 +1003d106: 6ab0 ldr r0, [r6, #40] ; 0x28 +1003d108: f7ff fc93 bl 1003ca32 +1003d10c: 4604 mov r4, r0 +1003d10e: 6237 str r7, [r6, #32] +1003d110: b92c cbnz r4, 1003d11e +1003d112: 6a71 ldr r1, [r6, #36] ; 0x24 +1003d114: 980a ldr r0, [sp, #40] ; 0x28 +1003d116: f44f 622b mov.w r2, #2736 ; 0xab0 +1003d11a: f7cf f915 bl 1000c348 +1003d11e: 6177 str r7, [r6, #20] +1003d120: f7ff fe80 bl 1003ce24 +1003d124: f114 0f01 cmn.w r4, #1 +1003d128: d106 bne.n 1003d138 +1003d12a: f20f 0088 addw r0, pc, #136 ; 0x88 +1003d12e: f7cf f8e8 bl 1000c302 +1003d132: f04f 30ff mov.w r0, #4294967295 +1003d136: e00c b.n 1003d152 +1003d138: 4908 ldr r1, [pc, #32] ; (1003d15c <.text_35>) +1003d13a: 600f str r7, [r1, #0] +1003d13c: 2001 movs r0, #1 +1003d13e: e008 b.n 1003d152 +1003d140: f110 0f02 cmn.w r0, #2 +1003d144: d102 bne.n 1003d14c +1003d146: f06f 0001 mvn.w r0, #1 +1003d14a: e002 b.n 1003d152 +1003d14c: f7ff fe60 bl 1003ce10 +1003d150: 2000 movs r0, #0 +1003d152: e8bd 8ff2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, sl, fp, pc} + ... + +1003d158 <.text_34>: +1003d158: 10044170 .word 0x10044170 + +1003d15c <.text_35>: +1003d15c: 100480f4 .word 0x100480f4 + +1003d160 <.text_36>: +1003d160: f10a 0118 add.w r1, sl, #24 +1003d164: 4620 mov r0, r4 +1003d166: e5f1 b.n 1003cd4c + +1003d168 <.text_37>: +1003d168: 2206 movs r2, #6 +1003d16a: 4649 mov r1, r9 +1003d16c: f10b 0004 add.w r0, fp, #4 +1003d170: f7cf b8e8 b.w 1000c344 + +1003d174 : +1003d174: 0a0d 6b20 7965 6920 2076 7369 2020 7830 .. key iv is 0x +1003d184: 7825 302c 2578 2c78 3020 2578 2c78 3020 %x,0x%x, 0x%x, 0 +1003d194: 2578 2c78 3020 2578 2c78 3020 2578 2c78 x%x, 0x%x, 0x%x, +1003d1a4: 3020 2578 2c78 3020 2578 2078 0000 0000 0x%x, 0x%x .... + +1003d1b4 : +1003d1b4: 0a0d 6f43 666e 6769 4120 7070 7720 6f72 ..Config App wro +1003d1c4: 676e 2121 6552 7473 7261 2074 6f63 666e ng!!Restart conf +1003d1d4: 6769 6320 726f 6572 7463 796c 732c 6d69 ig correctly,sim +1003d1e4: 6c70 5f65 6f63 666e 6769 735f 6174 7574 ple_config_statu +1003d1f4: 2073 203d 312d 0000 s = -1.. + +1003d1fc : +1003d1fc: 6973 706d 656c 635f 6e6f 6966 5f67 6c63 simple_config_cl +1003d20c: 6569 746e 0000 0000 ient.... + +1003d214 : +1003d214: 4338 546d 202f 284a 5f33 4561 5220 555f 8CmT/ J(3_aE R_U +1003d224: 5246 607d 746d 4677 293d 6651 746a 5e6e FR}`mtwF=)Qfjtn^ +1003d234: 5f53 2f31 6666 3c67 435f 7937 2777 7d73 S_1/ffg<_C7yw's} +1003d244: 273f 275f 266e 7e32 6c42 266d 6b5f 363f ?'_'n&2~Blm&_k?6 +1003d254: 0000 0000 .... + +1003d258 : +1003d258: 3735 3832 3939 3136 0000 0000 57289961.... + +1003d264 : +1003d264: a6a6 a6a6 a6a6 a6a6 ........ + +1003d26c : +1003d26c: f8df f000 ldr.w pc, [pc] ; 1003d270 +1003d270: 00017d99 .word 0x00017d99 + +1003d274 : +1003d274: b538 push {r3, r4, r5, lr} +1003d276: 4604 mov r4, r0 +1003d278: f7cf f86e bl 1000c358 +1003d27c: 1c40 adds r0, r0, #1 +1003d27e: f7ff fff5 bl 1003d26c +1003d282: 4605 mov r5, r0 +1003d284: 4620 mov r0, r4 +1003d286: f7cf f867 bl 1000c358 +1003d28a: 4602 mov r2, r0 +1003d28c: 4621 mov r1, r4 +1003d28e: 4628 mov r0, r5 +1003d290: f7d3 fabd bl 1001080e +1003d294: 4620 mov r0, r4 +1003d296: f7cf f85f bl 1000c358 +1003d29a: 2100 movs r1, #0 +1003d29c: 5541 strb r1, [r0, r5] +1003d29e: 4628 mov r0, r5 +1003d2a0: bd32 pop {r1, r4, r5, pc} + +1003d2a2 : +1003d2a2: b580 push {r7, lr} +1003d2a4: f7d3 fc12 bl 10010acc +1003d2a8: 2000 movs r0, #0 +1003d2aa: bd02 pop {r1, pc} + +1003d2ac : +1003d2ac: 2200 movs r2, #0 +1003d2ae: f7cd b919 b.w 1000a4e4 + +1003d2b2 : +1003d2b2: b510 push {r4, lr} +1003d2b4: f44f 747a mov.w r4, #1000 ; 0x3e8 +1003d2b8: 4362 muls r2, r4 +1003d2ba: e8bd 4010 ldmia.w sp!, {r4, lr} +1003d2be: 2300 movs r3, #0 +1003d2c0: f7cd b9f4 b.w 1000a6ac + +1003d2c4 : +1003d2c4: f7cd ba82 b.w 1000a7cc + +1003d2c8 : +1003d2c8: b510 push {r4, lr} +1003d2ca: f44f 747a mov.w r4, #1000 ; 0x3e8 +1003d2ce: 4362 muls r2, r4 +1003d2d0: e8bd 4010 ldmia.w sp!, {r4, lr} +1003d2d4: 2300 movs r3, #0 +1003d2d6: f7cd b951 b.w 1000a57c + ... + +1003d2dc : +1003d2dc: f8df f000 ldr.w pc, [pc] ; 1003d2e0 +1003d2e0: 00018009 .word 0x00018009 + +1003d2e4 : +1003d2e4: f8df f000 ldr.w pc, [pc] ; 1003d2e8 +1003d2e8: 00017dc1 .word 0x00017dc1 + +1003d2ec : +1003d2ec: f8df f000 ldr.w pc, [pc] ; 1003d2f0 +1003d2f0: 00017ebd .word 0x00017ebd + +1003d2f4 : +1003d2f4: f8df f000 ldr.w pc, [pc] ; 1003d2f8 +1003d2f8: 00015ae1 .word 0x00015ae1 + +1003d2fc : +1003d2fc: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} +1003d300: b095 sub sp, #84 ; 0x54 +1003d302: 4681 mov r9, r0 +1003d304: 9d1d ldr r5, [sp, #116] ; 0x74 +1003d306: 0d68 lsrs r0, r5, #21 +1003d308: f88d 0008 strb.w r0, [sp, #8] +1003d30c: 0b6e lsrs r6, r5, #13 +1003d30e: a802 add r0, sp, #8 +1003d310: af04 add r7, sp, #16 +1003d312: 7046 strb r6, [r0, #1] +1003d314: 607a str r2, [r7, #4] +1003d316: 096e lsrs r6, r5, #5 +1003d318: 7086 strb r6, [r0, #2] +1003d31a: 00ee lsls r6, r5, #3 +1003d31c: 70c6 strb r6, [r0, #3] +1003d31e: a803 add r0, sp, #12 +1003d320: 9008 str r0, [sp, #32] +1003d322: ae08 add r6, sp, #32 +1003d324: 2004 movs r0, #4 +1003d326: 9004 str r0, [sp, #16] +1003d328: 6071 str r1, [r6, #4] +1003d32a: 60b3 str r3, [r6, #8] +1003d32c: 4618 mov r0, r3 +1003d32e: f7cf f813 bl 1000c358 +1003d332: 60b8 str r0, [r7, #8] +1003d334: 2401 movs r4, #1 +1003d336: a802 add r0, sp, #8 +1003d338: 60f0 str r0, [r6, #12] +1003d33a: f10d 080c add.w r8, sp, #12 +1003d33e: 2004 movs r0, #4 +1003d340: 60f8 str r0, [r7, #12] +1003d342: f105 001f add.w r0, r5, #31 +1003d346: 9f1c ldr r7, [sp, #112] ; 0x70 +1003d348: 0946 lsrs r6, r0, #5 +1003d34a: e005 b.n 1003d358 +1003d34c: 462a mov r2, r5 +1003d34e: a90c add r1, sp, #48 ; 0x30 +1003d350: 4638 mov r0, r7 +1003d352: f7d3 fa5c bl 1001080e +1003d356: 1c64 adds r4, r4, #1 +1003d358: 42a6 cmp r6, r4 +1003d35a: db1e blt.n 1003d39a +1003d35c: 0e20 lsrs r0, r4, #24 +1003d35e: f88d 000c strb.w r0, [sp, #12] +1003d362: f888 4003 strb.w r4, [r8, #3] +1003d366: 0c20 lsrs r0, r4, #16 +1003d368: f888 0001 strb.w r0, [r8, #1] +1003d36c: ab08 add r3, sp, #32 +1003d36e: 0a20 lsrs r0, r4, #8 +1003d370: f888 0002 strb.w r0, [r8, #2] +1003d374: 2204 movs r2, #4 +1003d376: a80c add r0, sp, #48 ; 0x30 +1003d378: 9001 str r0, [sp, #4] +1003d37a: 2120 movs r1, #32 +1003d37c: a804 add r0, sp, #16 +1003d37e: 9000 str r0, [sp, #0] +1003d380: 4648 mov r0, r9 +1003d382: f7ff ffaf bl 1003d2e4 +1003d386: 42b4 cmp r4, r6 +1003d388: dae0 bge.n 1003d34c +1003d38a: 2220 movs r2, #32 +1003d38c: a90c add r1, sp, #48 ; 0x30 +1003d38e: 4638 mov r0, r7 +1003d390: f7d3 fa3d bl 1001080e +1003d394: 3720 adds r7, #32 +1003d396: 3d20 subs r5, #32 +1003d398: e7dd b.n 1003d356 +1003d39a: b015 add sp, #84 ; 0x54 +1003d39c: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + +1003d3a0 : +1003d3a0: b530 push {r4, r5, lr} +1003d3a2: 4604 mov r4, r0 +1003d3a4: b0ad sub sp, #180 ; 0xb4 +1003d3a6: f8d4 20d8 ldr.w r2, [r4, #216] ; 0xd8 +1003d3aa: b1ca cbz r2, 1003d3e0 +1003d3ac: 6861 ldr r1, [r4, #4] +1003d3ae: f104 00d8 add.w r0, r4, #216 ; 0xd8 +1003d3b2: 2900 cmp r1, #0 +1003d3b4: bf14 ite ne +1003d3b6: 6841 ldrne r1, [r0, #4] +1003d3b8: 6881 ldreq r1, [r0, #8] +1003d3ba: b189 cbz r1, 1003d3e0 +1003d3bc: f8d4 0278 ldr.w r0, [r4, #632] ; 0x278 +1003d3c0: f000 fa22 bl 1003d808 +1003d3c4: 4605 mov r5, r0 +1003d3c6: f8d4 0278 ldr.w r0, [r4, #632] ; 0x278 +1003d3ca: f000 fa2a bl 1003d822 +1003d3ce: 2000 movs r0, #0 +1003d3d0: f8c4 0278 str.w r0, [r4, #632] ; 0x278 +1003d3d4: 21c0 movs r1, #192 ; 0xc0 +1003d3d6: 4628 mov r0, r5 +1003d3d8: f000 fa7d bl 1003d8d6 +1003d3dc: 0005 movs r5, r0 +1003d3de: d102 bne.n 1003d3e6 +1003d3e0: f04f 30ff mov.w r0, #4294967295 +1003d3e4: e04c b.n 1003d480 +1003d3e6: f8d4 00d8 ldr.w r0, [r4, #216] ; 0xd8 +1003d3ea: f000 fa58 bl 1003d89e +1003d3ee: 2000 movs r0, #0 +1003d3f0: f8c4 00d8 str.w r0, [r4, #216] ; 0xd8 +1003d3f4: ab24 add r3, sp, #144 ; 0x90 +1003d3f6: 68a8 ldr r0, [r5, #8] +1003d3f8: 9005 str r0, [sp, #20] +1003d3fa: aa02 add r2, sp, #8 +1003d3fc: 6868 ldr r0, [r5, #4] +1003d3fe: 9002 str r0, [sp, #8] +1003d400: a905 add r1, sp, #20 +1003d402: 2001 movs r0, #1 +1003d404: f7ff ff6a bl 1003d2dc +1003d408: 4628 mov r0, r5 +1003d40a: f000 fa48 bl 1003d89e +1003d40e: f104 0036 add.w r0, r4, #54 ; 0x36 +1003d412: 9005 str r0, [sp, #20] +1003d414: f104 0130 add.w r1, r4, #48 ; 0x30 +1003d418: 2010 movs r0, #16 +1003d41a: 9002 str r0, [sp, #8] +1003d41c: 2206 movs r2, #6 +1003d41e: a805 add r0, sp, #20 +1003d420: ab05 add r3, sp, #20 +1003d422: 6041 str r1, [r0, #4] +1003d424: a902 add r1, sp, #8 +1003d426: 604a str r2, [r1, #4] +1003d428: f104 0246 add.w r2, r4, #70 ; 0x46 +1003d42c: 6082 str r2, [r0, #8] +1003d42e: 2010 movs r0, #16 +1003d430: 6088 str r0, [r1, #8] +1003d432: 2203 movs r2, #3 +1003d434: a81c add r0, sp, #112 ; 0x70 +1003d436: 9001 str r0, [sp, #4] +1003d438: 2120 movs r1, #32 +1003d43a: a802 add r0, sp, #8 +1003d43c: 9000 str r0, [sp, #0] +1003d43e: a824 add r0, sp, #144 ; 0x90 +1003d440: f7ff ff50 bl 1003d2e4 +1003d444: 2050 movs r0, #80 ; 0x50 +1003d446: 9001 str r0, [sp, #4] +1003d448: a808 add r0, sp, #32 +1003d44a: 9000 str r0, [sp, #0] +1003d44c: 2200 movs r2, #0 +1003d44e: f20f 2354 addw r3, pc, #596 ; 0x254 +1003d452: 2100 movs r1, #0 +1003d454: a81c add r0, sp, #112 ; 0x70 +1003d456: f7ff ff51 bl 1003d2fc +1003d45a: 2220 movs r2, #32 +1003d45c: a908 add r1, sp, #32 +1003d45e: f104 00e4 add.w r0, r4, #228 ; 0xe4 +1003d462: f7d3 f9d4 bl 1001080e +1003d466: 2210 movs r2, #16 +1003d468: a910 add r1, sp, #64 ; 0x40 +1003d46a: f504 7082 add.w r0, r4, #260 ; 0x104 +1003d46e: f7d3 f9ce bl 1001080e +1003d472: 2220 movs r2, #32 +1003d474: a914 add r1, sp, #80 ; 0x50 +1003d476: f504 708a add.w r0, r4, #276 ; 0x114 +1003d47a: f7d3 f9c8 bl 1001080e +1003d47e: 2000 movs r0, #0 +1003d480: b02d add sp, #180 ; 0xb4 +1003d482: bd30 pop {r4, r5, pc} + +1003d484 : +1003d484: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1003d488: 4604 mov r4, r0 +1003d48a: 4616 mov r6, r2 +1003d48c: 1c70 adds r0, r6, #1 +1003d48e: b08a sub sp, #40 ; 0x28 +1003d490: 0847 lsrs r7, r0, #1 +1003d492: a801 add r0, sp, #4 +1003d494: 9000 str r0, [sp, #0] +1003d496: 460d mov r5, r1 +1003d498: f104 08e4 add.w r8, r4, #228 ; 0xe4 +1003d49c: 463b mov r3, r7 +1003d49e: 462a mov r2, r5 +1003d4a0: 2120 movs r1, #32 +1003d4a2: 4640 mov r0, r8 +1003d4a4: f7ff ff22 bl 1003d2ec +1003d4a8: 2210 movs r2, #16 +1003d4aa: a901 add r1, sp, #4 +1003d4ac: f104 0056 add.w r0, r4, #86 ; 0x56 +1003d4b0: f7d3 f9ad bl 1001080e +1003d4b4: a801 add r0, sp, #4 +1003d4b6: 9000 str r0, [sp, #0] +1003d4b8: 0873 lsrs r3, r6, #1 +1003d4ba: 197a adds r2, r7, r5 +1003d4bc: 2120 movs r1, #32 +1003d4be: 4640 mov r0, r8 +1003d4c0: f7ff ff14 bl 1003d2ec +1003d4c4: 2210 movs r2, #16 +1003d4c6: a901 add r1, sp, #4 +1003d4c8: f104 0066 add.w r0, r4, #102 ; 0x66 +1003d4cc: f7d3 f99f bl 1001080e +1003d4d0: b00a add sp, #40 ; 0x28 +1003d4d2: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +1003d4d6 : +1003d4d6: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1003d4da: 000e movs r6, r1 +1003d4dc: 4605 mov r5, r0 +1003d4de: d00c beq.n 1003d4fa +1003d4e0: 2a20 cmp r2, #32 +1003d4e2: d30a bcc.n 1003d4fa +1003d4e4: 0910 lsrs r0, r2, #4 +1003d4e6: ebb2 1000 subs.w r0, r2, r0, lsl #4 +1003d4ea: d106 bne.n 1003d4fa +1003d4ec: f1a2 0710 sub.w r7, r2, #16 +1003d4f0: 4638 mov r0, r7 +1003d4f2: f000 f9ad bl 1003d850 +1003d4f6: 0004 movs r4, r0 +1003d4f8: d101 bne.n 1003d4fe +1003d4fa: 2000 movs r0, #0 +1003d4fc: e028 b.n 1003d550 +1003d4fe: f116 0810 adds.w r8, r6, #16 +1003d502: d006 beq.n 1003d512 +1003d504: 4639 mov r1, r7 +1003d506: f000 f9df bl 1003d8c8 +1003d50a: 463a mov r2, r7 +1003d50c: 4641 mov r1, r8 +1003d50e: f7d3 f97e bl 1001080e +1003d512: 6863 ldr r3, [r4, #4] +1003d514: 68a2 ldr r2, [r4, #8] +1003d516: 4631 mov r1, r6 +1003d518: f505 7082 add.w r0, r5, #260 ; 0x104 +1003d51c: f7ff feea bl 1003d2f4 +1003d520: b978 cbnz r0, 1003d542 +1003d522: 6860 ldr r0, [r4, #4] +1003d524: 68a1 ldr r1, [r4, #8] +1003d526: 1841 adds r1, r0, r1 +1003d528: f811 2d01 ldrb.w r2, [r1, #-1]! +1003d52c: 4290 cmp r0, r2 +1003d52e: d308 bcc.n 1003d542 +1003d530: 2300 movs r3, #0 +1003d532: e000 b.n 1003d536 +1003d534: 1c5b adds r3, r3, #1 +1003d536: 4293 cmp r3, r2 +1003d538: d207 bcs.n 1003d54a +1003d53a: f811 5901 ldrb.w r5, [r1], #-1 +1003d53e: 4295 cmp r5, r2 +1003d540: d0f8 beq.n 1003d534 +1003d542: 4620 mov r0, r4 +1003d544: f000 f9ab bl 1003d89e +1003d548: e7d7 b.n 1003d4fa +1003d54a: 1a80 subs r0, r0, r2 +1003d54c: 6060 str r0, [r4, #4] +1003d54e: 4620 mov r0, r4 +1003d550: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +1003d554 : +1003d554: 2200 movs r2, #0 +1003d556: 210a movs r1, #10 +1003d558: e00d b.n 1003d576 +1003d55a: 230a movs r3, #10 +1003d55c: fbb0 f3f3 udiv r3, r0, r3 +1003d560: fb01 0013 mls r0, r1, r3, r0 +1003d564: eb00 0040 add.w r0, r0, r0, lsl #1 +1003d568: 1882 adds r2, r0, r2 +1003d56a: 4608 mov r0, r1 +1003d56c: fbb3 f0f0 udiv r0, r3, r0 +1003d570: 189a adds r2, r3, r2 +1003d572: fb01 2210 mls r2, r1, r0, r2 +1003d576: 2800 cmp r0, #0 +1003d578: d1ef bne.n 1003d55a +1003d57a: f1c2 000a rsb r0, r2, #10 +1003d57e: fbb2 f2f1 udiv r2, r2, r1 +1003d582: fb01 0002 mla r0, r1, r2, r0 +1003d586: 220a movs r2, #10 +1003d588: fbb0 f2f2 udiv r2, r0, r2 +1003d58c: fb01 0012 mls r0, r1, r2, r0 +1003d590: 4770 bx lr + +1003d592 : +1003d592: b538 push {r3, r4, r5, lr} +1003d594: 4604 mov r4, r0 +1003d596: 200a movs r0, #10 +1003d598: fbb4 f5f0 udiv r5, r4, r0 +1003d59c: 4628 mov r0, r5 +1003d59e: f7ff ffd9 bl 1003d554 +1003d5a2: 210a movs r1, #10 +1003d5a4: fb01 4115 mls r1, r1, r5, r4 +1003d5a8: 4288 cmp r0, r1 +1003d5aa: d101 bne.n 1003d5b0 +1003d5ac: 2001 movs r0, #1 +1003d5ae: bd32 pop {r1, r4, r5, pc} +1003d5b0: 2000 movs r0, #0 +1003d5b2: bd32 pop {r1, r4, r5, pc} + +1003d5b4 : +1003d5b4: b538 push {r3, r4, r5, lr} +1003d5b6: 2104 movs r1, #4 +1003d5b8: a800 add r0, sp, #0 +1003d5ba: f7d3 fa87 bl 10010acc +1003d5be: 9800 ldr r0, [sp, #0] +1003d5c0: 4a0b ldr r2, [pc, #44] ; (1003d5f0 <.text_9>) +1003d5c2: 4601 mov r1, r0 +1003d5c4: fbb1 f1f2 udiv r1, r1, r2 +1003d5c8: fb02 0011 mls r0, r2, r1, r0 +1003d5cc: 9000 str r0, [sp, #0] +1003d5ce: 4909 ldr r1, [pc, #36] ; (1003d5f4 <.text_10>) +1003d5d0: fbb0 f0f1 udiv r0, r0, r1 +1003d5d4: b918 cbnz r0, 1003d5de +1003d5d6: 9800 ldr r0, [sp, #0] +1003d5d8: 4907 ldr r1, [pc, #28] ; (1003d5f8 <.text_11>) +1003d5da: 1808 adds r0, r1, r0 +1003d5dc: 9000 str r0, [sp, #0] +1003d5de: 250a movs r5, #10 +1003d5e0: 9c00 ldr r4, [sp, #0] +1003d5e2: 4620 mov r0, r4 +1003d5e4: f7ff ffb6 bl 1003d554 +1003d5e8: fb05 0004 mla r0, r5, r4, r0 +1003d5ec: bd32 pop {r1, r4, r5, pc} + ... + +1003d5f0 <.text_9>: +1003d5f0: 00989680 .word 0x00989680 + +1003d5f4 <.text_10>: +1003d5f4: 000f4240 .word 0x000f4240 + +1003d5f8 <.text_11>: +1003d5f8: 002dc6c0 .word 0x002dc6c0 + +1003d5fc : +1003d5fc: b538 push {r3, r4, r5, lr} +1003d5fe: f000 f845 bl 1003d68c <.text_14> +1003d602: 0005 movs r5, r0 +1003d604: d017 beq.n 1003d636 +1003d606: f000 fa54 bl 1003dab2 +1003d60a: b988 cbnz r0, 1003d630 +1003d60c: 210d movs r1, #13 +1003d60e: 4628 mov r0, r5 +1003d610: f000 fa5c bl 1003dacc +1003d614: b960 cbnz r0, 1003d630 +1003d616: 4629 mov r1, r5 +1003d618: 4620 mov r0, r4 +1003d61a: f000 fa5d bl 1003dad8 +1003d61e: b938 cbnz r0, 1003d630 +1003d620: 4629 mov r1, r5 +1003d622: 4620 mov r0, r4 +1003d624: f000 fa67 bl 1003daf6 +1003d628: b910 cbnz r0, 1003d630 +1003d62a: f000 f834 bl 1003d696 <.text_15> +1003d62e: b120 cbz r0, 1003d63a +1003d630: 4628 mov r0, r5 +1003d632: f000 f934 bl 1003d89e +1003d636: 2000 movs r0, #0 +1003d638: bd32 pop {r1, r4, r5, pc} +1003d63a: 4628 mov r0, r5 +1003d63c: bd32 pop {r1, r4, r5, pc} + +1003d63e : +1003d63e: b538 push {r3, r4, r5, lr} +1003d640: f000 f824 bl 1003d68c <.text_14> +1003d644: 0005 movs r5, r0 +1003d646: d01d beq.n 1003d684 +1003d648: f000 fa33 bl 1003dab2 +1003d64c: b9b8 cbnz r0, 1003d67e +1003d64e: 210e movs r1, #14 +1003d650: 4628 mov r0, r5 +1003d652: f000 fa3b bl 1003dacc +1003d656: b990 cbnz r0, 1003d67e +1003d658: 4629 mov r1, r5 +1003d65a: 4620 mov r0, r4 +1003d65c: f000 fa3c bl 1003dad8 +1003d660: b968 cbnz r0, 1003d67e +1003d662: 4629 mov r1, r5 +1003d664: 4620 mov r0, r4 +1003d666: f000 fa46 bl 1003daf6 +1003d66a: b940 cbnz r0, 1003d67e +1003d66c: f8b4 1268 ldrh.w r1, [r4, #616] ; 0x268 +1003d670: 4628 mov r0, r5 +1003d672: f000 f9ef bl 1003da54 +1003d676: b910 cbnz r0, 1003d67e +1003d678: f000 f80d bl 1003d696 <.text_15> +1003d67c: b120 cbz r0, 1003d688 +1003d67e: 4628 mov r0, r5 +1003d680: f000 f90d bl 1003d89e +1003d684: 2000 movs r0, #0 +1003d686: bd32 pop {r1, r4, r5, pc} +1003d688: 4628 mov r0, r5 +1003d68a: bd32 pop {r1, r4, r5, pc} + +1003d68c <.text_14>: +1003d68c: 4604 mov r4, r0 +1003d68e: f44f 707a mov.w r0, #1000 ; 0x3e8 +1003d692: f000 b8dd b.w 1003d850 + +1003d696 <.text_15>: +1003d696: 2200 movs r2, #0 +1003d698: 2300 movs r3, #0 +1003d69a: 4611 mov r1, r2 +1003d69c: 4628 mov r0, r5 +1003d69e: f000 ba13 b.w 1003dac8 + ... + +1003d6a4 : +1003d6a4: 6957 462d 2069 6145 7973 6120 646e 5320 Wi-Fi Easy and S +1003d6b4: 6365 7275 2065 654b 2079 6544 6972 6176 ecure Key Deriva +1003d6c4: 6974 6e6f 0000 0000 tion.... + +1003d6cc : +1003d6cc: b580 push {r7, lr} +1003d6ce: f44f 717a mov.w r1, #1000 ; 0x3e8 +1003d6d2: 4348 muls r0, r1 +1003d6d4: fbb0 f0f1 udiv r0, r0, r1 +1003d6d8: b900 cbnz r0, 1003d6dc +1003d6da: 2001 movs r0, #1 + +1003d6dc : +1003d6dc: f7cd f9f9 bl 1000aad2 +1003d6e0: 2000 movs r0, #0 +1003d6e2: bd02 pop {r1, pc} + +1003d6e4 : +1003d6e4: b580 push {r7, lr} +1003d6e6: f7fc fa50 bl 10039b8a +1003d6ea: 2001 movs r0, #1 +1003d6ec: f7fb fccd bl 1003908a +1003d6f0: f7cf f974 bl 1000c9dc +1003d6f4: 4603 mov r3, r0 +1003d6f6: 222f movs r2, #47 ; 0x2f +1003d6f8: f20f 0150 addw r1, pc, #80 ; 0x50 +1003d6fc: f20f 0058 addw r0, pc, #88 ; 0x58 +1003d700: f7ce fdff bl 1000c302 +1003d704: e8bd 4002 ldmia.w sp!, {r1, lr} +1003d708: 2000 movs r0, #0 +1003d70a: f7cd b999 b.w 1000aa40 + +1003d70e : +1003d70e: b500 push {lr} +1003d710: b085 sub sp, #20 +1003d712: 2000 movs r0, #0 +1003d714: 9003 str r0, [sp, #12] +1003d716: 9002 str r0, [sp, #8] +1003d718: 9001 str r0, [sp, #4] +1003d71a: 2300 movs r3, #0 +1003d71c: 2007 movs r0, #7 +1003d71e: 9000 str r0, [sp, #0] +1003d720: f44f 62a0 mov.w r2, #1280 ; 0x500 +1003d724: f20f 0160 addw r1, pc, #96 ; 0x60 +1003d728: 4807 ldr r0, [pc, #28] ; (1003d748 ) +1003d72a: f7cd f8fd bl 1000a928 +1003d72e: 2801 cmp r0, #1 +1003d730: d008 beq.n 1003d744 +1003d732: f20f 0144 addw r1, pc, #68 ; 0x44 +1003d736: f20f 0058 addw r0, pc, #88 ; 0x58 +1003d73a: b005 add sp, #20 +1003d73c: f85d eb04 ldr.w lr, [sp], #4 +1003d740: f7ce bddf b.w 1000c302 + +1003d744 : +1003d744: b005 add sp, #20 +1003d746: bd00 pop {pc} + +1003d748 : +1003d748: d6e5 1003 .... + +1003d74c : +1003d74c: 6e69 7469 745f 7268 6165 0064 init_thread. + +1003d758 : +1003d758: 0d0a 7325 2528 2964 202c 7641 6961 616c ..%s(%d), Availa +1003d768: 6c62 2065 6568 7061 3020 2578 0078 0000 ble heap 0x%x... + +1003d778 : +1003d778: 6c77 6e61 6e5f 7465 6f77 6b72 0000 0000 wlan_network.... + +1003d788 : +1003d788: 6e69 7469 0000 0000 init.... + +1003d790 : +1003d790: 0d0a 7325 7820 6154 6b73 7243 6165 6574 ..%s xTaskCreate +1003d7a0: 6928 696e 5f74 6874 6572 6461 2029 6166 (init_thread) fa +1003d7b0: 6c69 6465 0000 0000 iled.... + +1003d7b8 : +1003d7b8: f1a0 0141 sub.w r1, r0, #65 ; 0x41 +1003d7bc: 291a cmp r1, #26 +1003d7be: bf38 it cc +1003d7c0: 3020 addcc r0, #32 +1003d7c2: 4770 bx lr + +1003d7c4 : +1003d7c4: e001 b.n 1003d7ca +1003d7c6: 1c49 adds r1, r1, #1 +1003d7c8: 1e52 subs r2, r2, #1 +1003d7ca: b172 cbz r2, 1003d7ea +1003d7cc: 780b ldrb r3, [r1, #0] +1003d7ce: f890 c000 ldrb.w ip, [r0] +1003d7d2: 459c cmp ip, r3 +1003d7d4: d005 beq.n 1003d7e2 +1003d7d6: d202 bcs.n 1003d7de +1003d7d8: f04f 30ff mov.w r0, #4294967295 +1003d7dc: 4770 bx lr +1003d7de: 2001 movs r0, #1 +1003d7e0: 4770 bx lr +1003d7e2: f810 3b01 ldrb.w r3, [r0], #1 +1003d7e6: 2b00 cmp r3, #0 +1003d7e8: d1ed bne.n 1003d7c6 +1003d7ea: 2000 movs r0, #0 +1003d7ec: 4770 bx lr + +1003d7ee : +1003d7ee: b538 push {r3, r4, r5, lr} +1003d7f0: 4604 mov r4, r0 +1003d7f2: 460d mov r5, r1 +1003d7f4: 2005 movs r0, #5 +1003d7f6: f000 fa2d bl 1003dc54 +1003d7fa: 4621 mov r1, r4 +1003d7fc: f000 fa34 bl 1003dc68 +1003d800: 6028 str r0, [r5, #0] +1003d802: b100 cbz r0, 1003d806 +1003d804: 2001 movs r0, #1 +1003d806: bd32 pop {r1, r4, r5, pc} + +1003d808 : +1003d808: b538 push {r3, r4, r5, lr} +1003d80a: 460c mov r4, r1 +1003d80c: 4615 mov r5, r2 +1003d80e: 2005 movs r0, #5 +1003d810: f000 fa20 bl 1003dc54 +1003d814: 4602 mov r2, r0 +1003d816: 4629 mov r1, r5 +1003d818: 4620 mov r0, r4 +1003d81a: e8bd 4038 ldmia.w sp!, {r3, r4, r5, lr} +1003d81e: f000 ba6d b.w 1003dcfc + +1003d822 : +1003d822: 4770 bx lr + +1003d824 : +1003d824: b538 push {r3, r4, r5, lr} +1003d826: 460c mov r4, r1 +1003d828: 2800 cmp r0, #0 +1003d82a: bf18 it ne +1003d82c: 2c00 cmpne r4, #0 +1003d82e: 4615 mov r5, r2 +1003d830: d008 beq.n 1003d844 +1003d832: 4629 mov r1, r5 +1003d834: f000 f848 bl 1003d8c8 +1003d838: 462a mov r2, r5 +1003d83a: 4621 mov r1, r4 +1003d83c: e8bd 4038 ldmia.w sp!, {r3, r4, r5, lr} +1003d840: f7d2 bfe5 b.w 1001080e +1003d844: bd31 pop {r0, r4, r5, pc} + +1003d846 : +1003d846: b110 cbz r0, 1003d84e +1003d848: 684a ldr r2, [r1, #4] +1003d84a: 6889 ldr r1, [r1, #8] +1003d84c: e7ea b.n 1003d824 +1003d84e: 4770 bx lr + +1003d850 : +1003d850: b510 push {r4, lr} +1003d852: 4604 mov r4, r0 +1003d854: f104 0010 add.w r0, r4, #16 +1003d858: f7ff fd08 bl 1003d26c +1003d85c: b118 cbz r0, 1003d866 +1003d85e: 6004 str r4, [r0, #0] +1003d860: f100 0110 add.w r1, r0, #16 +1003d864: 6081 str r1, [r0, #8] +1003d866: bd10 pop {r4, pc} + +1003d868 : +1003d868: b570 push {r4, r5, r6, lr} +1003d86a: 4604 mov r4, r0 +1003d86c: 460d mov r5, r1 +1003d86e: 4628 mov r0, r5 +1003d870: f7ff ffee bl 1003d850 +1003d874: 0006 movs r6, r0 +1003d876: d003 beq.n 1003d880 +1003d878: 462a mov r2, r5 +1003d87a: 4621 mov r1, r4 +1003d87c: f7ff ffd2 bl 1003d824 +1003d880: 4630 mov r0, r6 +1003d882: bd70 pop {r4, r5, r6, pc} + +1003d884 : +1003d884: b538 push {r3, r4, r5, lr} +1003d886: 4604 mov r4, r0 +1003d888: 6860 ldr r0, [r4, #4] +1003d88a: f7ff ffe1 bl 1003d850 +1003d88e: 0005 movs r5, r0 +1003d890: d003 beq.n 1003d89a +1003d892: 6862 ldr r2, [r4, #4] +1003d894: 68a1 ldr r1, [r4, #8] +1003d896: f7ff ffc5 bl 1003d824 +1003d89a: 4628 mov r0, r5 +1003d89c: bd32 pop {r1, r4, r5, pc} + +1003d89e : +1003d89e: b538 push {r3, r4, r5, lr} +1003d8a0: 0004 movs r4, r0 +1003d8a2: d00d beq.n 1003d8c0 <__iar_annotation$$tailcall+0x2> +1003d8a4: 7b20 ldrb r0, [r4, #12] +1003d8a6: 4d07 ldr r5, [pc, #28] ; (1003d8c4 <.text_10>) +1003d8a8: 07c0 lsls r0, r0, #31 +1003d8aa: d503 bpl.n 1003d8b4 +1003d8ac: 68a0 ldr r0, [r4, #8] +1003d8ae: 686a ldr r2, [r5, #4] +1003d8b0: 2100 movs r1, #0 +1003d8b2: 4790 blx r2 +1003d8b4: 686a ldr r2, [r5, #4] +1003d8b6: 4620 mov r0, r4 +1003d8b8: e8bd 4038 ldmia.w sp!, {r3, r4, r5, lr} +1003d8bc: 2100 movs r1, #0 + +1003d8be <__iar_annotation$$tailcall>: +1003d8be: 4710 bx r2 +1003d8c0: bd31 pop {r0, r4, r5, pc} + ... + +1003d8c4 <.text_10>: +1003d8c4: 100006d4 .word 0x100006d4 + +1003d8c8 : +1003d8c8: 6843 ldr r3, [r0, #4] +1003d8ca: 6882 ldr r2, [r0, #8] +1003d8cc: 18c9 adds r1, r1, r3 +1003d8ce: 189a adds r2, r3, r2 +1003d8d0: 6041 str r1, [r0, #4] +1003d8d2: 4610 mov r0, r2 +1003d8d4: 4770 bx lr + +1003d8d6 : +1003d8d6: b5f8 push {r3, r4, r5, r6, r7, lr} +1003d8d8: 0004 movs r4, r0 +1003d8da: 460d mov r5, r1 +1003d8dc: d017 beq.n 1003d90e +1003d8de: 6866 ldr r6, [r4, #4] +1003d8e0: 42ae cmp r6, r5 +1003d8e2: d214 bcs.n 1003d90e +1003d8e4: 4628 mov r0, r5 +1003d8e6: f7ff ffb3 bl 1003d850 +1003d8ea: 0007 movs r7, r0 +1003d8ec: d00b beq.n 1003d906 +1003d8ee: 1bad subs r5, r5, r6 +1003d8f0: 4629 mov r1, r5 +1003d8f2: f7ff ffe9 bl 1003d8c8 +1003d8f6: 462a mov r2, r5 +1003d8f8: 2100 movs r1, #0 +1003d8fa: f7d2 ff9d bl 10010838 +1003d8fe: 4621 mov r1, r4 +1003d900: 4638 mov r0, r7 +1003d902: f7ff ffa0 bl 1003d846 +1003d906: 4620 mov r0, r4 +1003d908: f7ff ffc9 bl 1003d89e +1003d90c: 4638 mov r0, r7 +1003d90e: bdf2 pop {r1, r4, r5, r6, r7, pc} + +1003d910 : +1003d910: f8df f000 ldr.w pc, [pc] ; 1003d914 +1003d914: 00015a65 .word 0x00015a65 + +1003d918 : +1003d918: b510 push {r4, lr} +1003d91a: 460c mov r4, r1 +1003d91c: b118 cbz r0, 1003d926 +1003d91e: 2101 movs r1, #1 +1003d920: f7ff ffd2 bl 1003d8c8 +1003d924: 7004 strb r4, [r0, #0] +1003d926: bd10 pop {r4, pc} + +1003d928 : +1003d928: b510 push {r4, lr} +1003d92a: 460c mov r4, r1 +1003d92c: b128 cbz r0, 1003d93a +1003d92e: 2102 movs r1, #2 +1003d930: f7ff ffca bl 1003d8c8 +1003d934: 0a21 lsrs r1, r4, #8 +1003d936: 7001 strb r1, [r0, #0] +1003d938: 7044 strb r4, [r0, #1] +1003d93a: bd10 pop {r4, pc} + +1003d93c : +1003d93c: b538 push {r3, r4, r5, lr} +1003d93e: 460c mov r4, r1 +1003d940: 2800 cmp r0, #0 +1003d942: bf18 it ne +1003d944: 2c00 cmpne r4, #0 +1003d946: 4615 mov r5, r2 +1003d948: d008 beq.n 1003d95c +1003d94a: 4629 mov r1, r5 +1003d94c: f7ff ffbc bl 1003d8c8 +1003d950: 462a mov r2, r5 +1003d952: 4621 mov r1, r4 +1003d954: e8bd 4038 ldmia.w sp!, {r3, r4, r5, lr} +1003d958: f7d2 bf59 b.w 1001080e +1003d95c: bd31 pop {r0, r4, r5, pc} + +1003d95e : +1003d95e: b110 cbz r0, 1003d966 +1003d960: 684a ldr r2, [r1, #4] +1003d962: 6889 ldr r1, [r1, #8] +1003d964: e7ea b.n 1003d93c +1003d966: 4770 bx lr + +1003d968 : +1003d968: b570 push {r4, r5, r6, lr} +1003d96a: 4604 mov r4, r0 +1003d96c: b082 sub sp, #8 +1003d96e: f8d4 00d8 ldr.w r0, [r4, #216] ; 0xd8 +1003d972: 460d mov r5, r1 +1003d974: f7ff ff93 bl 1003d89e +1003d978: 2000 movs r0, #0 +1003d97a: f8c4 00d8 str.w r0, [r4, #216] ; 0xd8 +1003d97e: f8d4 0278 ldr.w r0, [r4, #632] ; 0x278 +1003d982: f7ff ff4e bl 1003d822 +1003d986: f104 06d8 add.w r6, r4, #216 ; 0xd8 +1003d98a: a900 add r1, sp, #0 +1003d98c: 4630 mov r0, r6 +1003d98e: f7ff ff2e bl 1003d7ee +1003d992: f8c4 0278 str.w r0, [r4, #632] ; 0x278 +1003d996: 21c0 movs r1, #192 ; 0xc0 +1003d998: 9800 ldr r0, [sp, #0] +1003d99a: f7ff ff9c bl 1003d8d6 +1003d99e: 9000 str r0, [sp, #0] +1003d9a0: f8d4 0278 ldr.w r0, [r4, #632] ; 0x278 +1003d9a4: 2800 cmp r0, #0 +1003d9a6: bf1c itt ne +1003d9a8: f8d4 00d8 ldrne.w r0, [r4, #216] ; 0xd8 +1003d9ac: 2800 cmpne r0, #0 +1003d9ae: d001 beq.n 1003d9b4 +1003d9b0: 9800 ldr r0, [sp, #0] +1003d9b2: b928 cbnz r0, 1003d9c0 +1003d9b4: 9800 ldr r0, [sp, #0] +1003d9b6: f7ff ff72 bl 1003d89e +1003d9ba: f04f 30ff mov.w r0, #4294967295 +1003d9be: bd76 pop {r1, r2, r4, r5, r6, pc} +1003d9c0: f241 0132 movw r1, #4146 ; 0x1032 +1003d9c4: f000 f8a7 bl 1003db16 <.text_21+0x2> +1003d9c8: 9800 ldr r0, [sp, #0] +1003d9ca: 6841 ldr r1, [r0, #4] +1003d9cc: f000 f8a2 bl 1003db14 <.text_21> +1003d9d0: 9900 ldr r1, [sp, #0] +1003d9d2: 4628 mov r0, r5 +1003d9d4: f7ff ffc3 bl 1003d95e +1003d9d8: 6860 ldr r0, [r4, #4] +1003d9da: b128 cbz r0, 1003d9e8 +1003d9dc: 68b0 ldr r0, [r6, #8] +1003d9de: f7ff ff5e bl 1003d89e +1003d9e2: 9800 ldr r0, [sp, #0] +1003d9e4: 60b0 str r0, [r6, #8] +1003d9e6: e004 b.n 1003d9f2 +1003d9e8: 6870 ldr r0, [r6, #4] +1003d9ea: f7ff ff58 bl 1003d89e +1003d9ee: 9800 ldr r0, [sp, #0] +1003d9f0: 6070 str r0, [r6, #4] +1003d9f2: 2000 movs r0, #0 +1003d9f4: bd76 pop {r1, r2, r4, r5, r6, pc} + +1003d9f6 <.text_9>: +1003d9f6: f7ff ff97 bl 1003d928 +1003d9fa: 2101 movs r1, #1 +1003d9fc: 4620 mov r0, r4 +1003d9fe: f7ff ff93 bl 1003d928 +1003da02: b2e9 uxtb r1, r5 +1003da04: 4620 mov r0, r4 +1003da06: f7ff ff87 bl 1003d918 +1003da0a: 2000 movs r0, #0 +1003da0c: bd32 pop {r1, r4, r5, pc} + +1003da0e : +1003da0e: b538 push {r3, r4, r5, lr} +1003da10: 460d mov r5, r1 +1003da12: 4604 mov r4, r0 +1003da14: f241 0108 movw r1, #4104 ; 0x1008 +1003da18: e010 b.n 1003da3c <.text_13> + +1003da1a : +1003da1a: b538 push {r3, r4, r5, lr} +1003da1c: 460d mov r5, r1 +1003da1e: 4604 mov r4, r0 +1003da20: f241 0147 movw r1, #4167 ; 0x1047 +1003da24: f7ff ff80 bl 1003d928 +1003da28: 2110 movs r1, #16 +1003da2a: f000 f88f bl 1003db4c <.text_25+0x2> +1003da2e: 2210 movs r2, #16 +1003da30: e109 b.n 1003dc46 <.text_34> + +1003da32 : +1003da32: b538 push {r3, r4, r5, lr} +1003da34: 460d mov r5, r1 +1003da36: 4604 mov r4, r0 +1003da38: f241 0112 movw r1, #4114 ; 0x1012 + +1003da3c <.text_13>: +1003da3c: f7ff ff74 bl 1003d928 +1003da40: 2102 movs r1, #2 +1003da42: 4620 mov r0, r4 +1003da44: f7ff ff70 bl 1003d928 +1003da48: 4629 mov r1, r5 +1003da4a: 4620 mov r0, r4 +1003da4c: f7ff ff6c bl 1003d928 +1003da50: 2000 movs r0, #0 +1003da52: bd32 pop {r1, r4, r5, pc} + +1003da54 : +1003da54: b538 push {r3, r4, r5, lr} +1003da56: 460d mov r5, r1 +1003da58: 4604 mov r4, r0 +1003da5a: f241 0109 movw r1, #4105 ; 0x1009 +1003da5e: e7ed b.n 1003da3c <.text_13> + +1003da60 : +1003da60: b510 push {r4, lr} +1003da62: b08e sub sp, #56 ; 0x38 +1003da64: 460c mov r4, r1 +1003da66: f8d0 1134 ldr.w r1, [r0, #308] ; 0x134 +1003da6a: b911 cbnz r1, 1003da72 +1003da6c: f04f 30ff mov.w r0, #4294967295 +1003da70: e01d b.n 1003daae +1003da72: 688a ldr r2, [r1, #8] +1003da74: 9204 str r2, [sp, #16] +1003da76: ab04 add r3, sp, #16 +1003da78: 6849 ldr r1, [r1, #4] +1003da7a: 9102 str r1, [sp, #8] +1003da7c: 2202 movs r2, #2 +1003da7e: 68a1 ldr r1, [r4, #8] +1003da80: 9105 str r1, [sp, #20] +1003da82: 30e4 adds r0, #228 ; 0xe4 +1003da84: 6861 ldr r1, [r4, #4] +1003da86: 9103 str r1, [sp, #12] +1003da88: a906 add r1, sp, #24 +1003da8a: 9101 str r1, [sp, #4] +1003da8c: a902 add r1, sp, #8 +1003da8e: 9100 str r1, [sp, #0] +1003da90: 2120 movs r1, #32 +1003da92: f7ff fc27 bl 1003d2e4 +1003da96: f241 0105 movw r1, #4101 ; 0x1005 +1003da9a: f000 f857 bl 1003db4c <.text_25+0x2> +1003da9e: f000 f854 bl 1003db4a <.text_25> +1003daa2: 2208 movs r2, #8 +1003daa4: a906 add r1, sp, #24 +1003daa6: 4620 mov r0, r4 +1003daa8: f7ff ff48 bl 1003d93c +1003daac: 2000 movs r0, #0 +1003daae: b00e add sp, #56 ; 0x38 +1003dab0: bd10 pop {r4, pc} + +1003dab2 : +1003dab2: b510 push {r4, lr} +1003dab4: 4604 mov r4, r0 +1003dab6: f241 014a movw r1, #4170 ; 0x104a +1003daba: f7ff ff35 bl 1003d928 +1003dabe: 2101 movs r1, #1 +1003dac0: f000 f844 bl 1003db4c <.text_25+0x2> +1003dac4: 2110 movs r1, #16 +1003dac6: e050 b.n 1003db6a <.text_28> + +1003dac8 : +1003dac8: 2000 movs r0, #0 +1003daca: 4770 bx lr + +1003dacc : +1003dacc: b538 push {r3, r4, r5, lr} +1003dace: 460d mov r5, r1 +1003dad0: 4604 mov r4, r0 +1003dad2: f241 0122 movw r1, #4130 ; 0x1022 +1003dad6: e78e b.n 1003d9f6 <.text_9> + +1003dad8 : +1003dad8: b538 push {r3, r4, r5, lr} +1003dada: 4604 mov r4, r0 +1003dadc: 460d mov r5, r1 +1003dade: f241 011a movw r1, #4122 ; 0x101a +1003dae2: f000 f818 bl 1003db16 <.text_21+0x2> +1003dae6: 2110 movs r1, #16 +1003dae8: f000 f815 bl 1003db16 <.text_21+0x2> +1003daec: 2210 movs r2, #16 +1003daee: f104 0136 add.w r1, r4, #54 ; 0x36 +1003daf2: 4628 mov r0, r5 +1003daf4: e0a9 b.n 1003dc4a <.text_34+0x4> + +1003daf6 : +1003daf6: b538 push {r3, r4, r5, lr} +1003daf8: 4604 mov r4, r0 +1003dafa: 460d mov r5, r1 +1003dafc: f241 0139 movw r1, #4153 ; 0x1039 +1003db00: f000 f809 bl 1003db16 <.text_21+0x2> +1003db04: 2110 movs r1, #16 +1003db06: f000 f806 bl 1003db16 <.text_21+0x2> +1003db0a: 2210 movs r2, #16 +1003db0c: f104 0146 add.w r1, r4, #70 ; 0x46 +1003db10: 4628 mov r0, r5 +1003db12: e09a b.n 1003dc4a <.text_34+0x4> + +1003db14 <.text_21>: +1003db14: b289 uxth r1, r1 +1003db16: 4628 mov r0, r5 +1003db18: e706 b.n 1003d928 + +1003db1a : +1003db1a: b510 push {r4, lr} +1003db1c: 460c mov r4, r1 +1003db1e: f241 0104 movw r1, #4100 ; 0x1004 +1003db22: f000 f813 bl 1003db4c <.text_25+0x2> +1003db26: f000 f813 bl 1003db50 <.text_26> +1003db2a: 213f movs r1, #63 ; 0x3f +1003db2c: e008 b.n 1003db40 <.text_24> + +1003db2e : +1003db2e: b510 push {r4, lr} +1003db30: 460c mov r4, r1 +1003db32: f241 0110 movw r1, #4112 ; 0x1010 +1003db36: f000 f809 bl 1003db4c <.text_25+0x2> +1003db3a: f000 f809 bl 1003db50 <.text_26> +1003db3e: 210f movs r1, #15 + +1003db40 <.text_24>: +1003db40: 4620 mov r0, r4 +1003db42: f7ff fef1 bl 1003d928 +1003db46: 2000 movs r0, #0 +1003db48: bd10 pop {r4, pc} + +1003db4a <.text_25>: +1003db4a: 2108 movs r1, #8 +1003db4c: 4620 mov r0, r4 +1003db4e: e6eb b.n 1003d928 + +1003db50 <.text_26>: +1003db50: 2102 movs r1, #2 +1003db52: 4620 mov r0, r4 +1003db54: e6e8 b.n 1003d928 + +1003db56 : +1003db56: b510 push {r4, lr} +1003db58: 460c mov r4, r1 +1003db5a: f241 010d movw r1, #4109 ; 0x100d +1003db5e: f7ff fff5 bl 1003db4c <.text_25+0x2> +1003db62: 2101 movs r1, #1 +1003db64: f7ff fff2 bl 1003db4c <.text_25+0x2> +1003db68: 2101 movs r1, #1 + +1003db6a <.text_28>: +1003db6a: 4620 mov r0, r4 +1003db6c: f7ff fed4 bl 1003d918 +1003db70: 2000 movs r0, #0 +1003db72: bd10 pop {r4, pc} + +1003db74 : +1003db74: b510 push {r4, lr} +1003db76: 460c mov r4, r1 +1003db78: f241 0102 movw r1, #4098 ; 0x1002 +1003db7c: f7ff ffe6 bl 1003db4c <.text_25+0x2> +1003db80: f7ff ffe6 bl 1003db50 <.text_26> +1003db84: 2100 movs r1, #0 +1003db86: e7db b.n 1003db40 <.text_24> + +1003db88 : +1003db88: b510 push {r4, lr} +1003db8a: b08a sub sp, #40 ; 0x28 +1003db8c: 460c mov r4, r1 +1003db8e: a901 add r1, sp, #4 +1003db90: 9100 str r1, [sp, #0] +1003db92: 6863 ldr r3, [r4, #4] +1003db94: 68a2 ldr r2, [r4, #8] +1003db96: 2120 movs r1, #32 +1003db98: 30e4 adds r0, #228 ; 0xe4 +1003db9a: f7ff fba7 bl 1003d2ec +1003db9e: f241 011e movw r1, #4126 ; 0x101e +1003dba2: f7ff ffd3 bl 1003db4c <.text_25+0x2> +1003dba6: f7ff ffd0 bl 1003db4a <.text_25> +1003dbaa: 2208 movs r2, #8 +1003dbac: a901 add r1, sp, #4 +1003dbae: 4620 mov r0, r4 +1003dbb0: f7ff fec4 bl 1003d93c +1003dbb4: 2000 movs r0, #0 +1003dbb6: b00a add sp, #40 ; 0x28 +1003dbb8: bd10 pop {r4, pc} + +1003dbba : +1003dbba: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1003dbbe: 4616 mov r6, r2 +1003dbc0: 4604 mov r4, r0 +1003dbc2: 6870 ldr r0, [r6, #4] +1003dbc4: 460d mov r5, r1 +1003dbc6: f1c0 0110 rsb r1, r0, #16 +1003dbca: 0900 lsrs r0, r0, #4 +1003dbcc: eb01 1700 add.w r7, r1, r0, lsl #4 +1003dbd0: 4639 mov r1, r7 +1003dbd2: 4630 mov r0, r6 +1003dbd4: f7ff fe78 bl 1003d8c8 +1003dbd8: 463a mov r2, r7 +1003dbda: 4639 mov r1, r7 +1003dbdc: f7d2 fe2c bl 10010838 +1003dbe0: f241 0118 movw r1, #4120 ; 0x1018 +1003dbe4: f7ff ff97 bl 1003db16 <.text_21+0x2> +1003dbe8: 6870 ldr r0, [r6, #4] +1003dbea: f100 0110 add.w r1, r0, #16 +1003dbee: f7ff ff91 bl 1003db14 <.text_21> +1003dbf2: 2110 movs r1, #16 +1003dbf4: 4628 mov r0, r5 +1003dbf6: f7ff fe67 bl 1003d8c8 +1003dbfa: 4607 mov r7, r0 +1003dbfc: 2110 movs r1, #16 +1003dbfe: f000 f8f4 bl 1003ddea +1003dc02: 2800 cmp r0, #0 +1003dc04: d410 bmi.n 1003dc28 +1003dc06: 2100 movs r1, #0 +1003dc08: 4628 mov r0, r5 +1003dc0a: f7ff fe5d bl 1003d8c8 +1003dc0e: 4680 mov r8, r0 +1003dc10: 4631 mov r1, r6 +1003dc12: 4628 mov r0, r5 +1003dc14: f7ff fea3 bl 1003d95e +1003dc18: 6873 ldr r3, [r6, #4] +1003dc1a: 4642 mov r2, r8 +1003dc1c: 4639 mov r1, r7 +1003dc1e: f504 7082 add.w r0, r4, #260 ; 0x104 +1003dc22: f7ff fe75 bl 1003d910 +1003dc26: b108 cbz r0, 1003dc2c +1003dc28: f04f 30ff mov.w r0, #4294967295 +1003dc2c: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +1003dc30 : +1003dc30: b538 push {r3, r4, r5, lr} +1003dc32: 460d mov r5, r1 +1003dc34: 4604 mov r4, r0 +1003dc36: f44f 5181 mov.w r1, #4128 ; 0x1020 +1003dc3a: f7ff fe75 bl 1003d928 +1003dc3e: 2106 movs r1, #6 +1003dc40: f7ff ff84 bl 1003db4c <.text_25+0x2> +1003dc44: 2206 movs r2, #6 + +1003dc46 <.text_34>: +1003dc46: 4629 mov r1, r5 +1003dc48: 4620 mov r0, r4 +1003dc4a: f7ff fe77 bl 1003d93c +1003dc4e: 2000 movs r0, #0 +1003dc50: bd32 pop {r1, r4, r5, pc} + ... + +1003dc54 : +1003dc54: 4903 ldr r1, [pc, #12] ; (1003dc64 <.text_4>) +1003dc56: 680a ldr r2, [r1, #0] +1003dc58: 4282 cmp r2, r0 +1003dc5a: d101 bne.n 1003dc60 +1003dc5c: 4608 mov r0, r1 +1003dc5e: 4770 bx lr +1003dc60: 2000 movs r0, #0 +1003dc62: 4770 bx lr + +1003dc64 <.text_4>: +1003dc64: 100444dc .word 0x100444dc + +1003dc68 : +1003dc68: b570 push {r4, r5, r6, lr} +1003dc6a: 0004 movs r4, r0 +1003dc6c: b086 sub sp, #24 +1003dc6e: 460d mov r5, r1 +1003dc70: d042 beq.n 1003dcf8 +1003dc72: 6828 ldr r0, [r5, #0] +1003dc74: f7ff fe13 bl 1003d89e +1003dc78: 6920 ldr r0, [r4, #16] +1003dc7a: f7ff fde9 bl 1003d850 +1003dc7e: 2800 cmp r0, #0 +1003dc80: 6028 str r0, [r5, #0] +1003dc82: d039 beq.n 1003dcf8 +1003dc84: 6921 ldr r1, [r4, #16] +1003dc86: f7ff fe1f bl 1003d8c8 +1003dc8a: 6921 ldr r1, [r4, #16] +1003dc8c: f000 f8ad bl 1003ddea +1003dc90: b128 cbz r0, 1003dc9e +1003dc92: 6828 ldr r0, [r5, #0] +1003dc94: f7ff fe03 bl 1003d89e +1003dc98: 2000 movs r0, #0 +1003dc9a: 6028 str r0, [r5, #0] +1003dc9c: e02c b.n 1003dcf8 +1003dc9e: 6828 ldr r0, [r5, #0] +1003dca0: 6922 ldr r2, [r4, #16] +1003dca2: 68e1 ldr r1, [r4, #12] +1003dca4: 6880 ldr r0, [r0, #8] +1003dca6: f7ce fb4d bl 1000c344 +1003dcaa: 2801 cmp r0, #1 +1003dcac: db03 blt.n 1003dcb6 +1003dcae: 6829 ldr r1, [r5, #0] +1003dcb0: 6889 ldr r1, [r1, #8] +1003dcb2: 2000 movs r0, #0 +1003dcb4: 7008 strb r0, [r1, #0] +1003dcb6: 6920 ldr r0, [r4, #16] +1003dcb8: 9004 str r0, [sp, #16] +1003dcba: f7ff fdc9 bl 1003d850 +1003dcbe: 0006 movs r6, r0 +1003dcc0: d013 beq.n 1003dcea +1003dcc2: 6828 ldr r0, [r5, #0] +1003dcc4: a904 add r1, sp, #16 +1003dcc6: 9103 str r1, [sp, #12] +1003dcc8: 68b1 ldr r1, [r6, #8] +1003dcca: 9102 str r1, [sp, #8] +1003dccc: 6921 ldr r1, [r4, #16] +1003dcce: 9101 str r1, [sp, #4] +1003dcd0: 68e1 ldr r1, [r4, #12] +1003dcd2: 9100 str r1, [sp, #0] +1003dcd4: 6843 ldr r3, [r0, #4] +1003dcd6: 6882 ldr r2, [r0, #8] +1003dcd8: 68a1 ldr r1, [r4, #8] +1003dcda: 6860 ldr r0, [r4, #4] +1003dcdc: f000 f900 bl 1003dee0 +1003dce0: 2800 cmp r0, #0 +1003dce2: d504 bpl.n 1003dcee +1003dce4: 4630 mov r0, r6 +1003dce6: f7ff fdda bl 1003d89e +1003dcea: 2000 movs r0, #0 +1003dcec: e004 b.n 1003dcf8 +1003dcee: 9904 ldr r1, [sp, #16] +1003dcf0: 4630 mov r0, r6 +1003dcf2: f7ff fde9 bl 1003d8c8 +1003dcf6: 4630 mov r0, r6 +1003dcf8: b006 add sp, #24 +1003dcfa: bd70 pop {r4, r5, r6, pc} + +1003dcfc : +1003dcfc: b5f0 push {r4, r5, r6, r7, lr} +1003dcfe: 4604 mov r4, r0 +1003dd00: 0016 movs r6, r2 +1003dd02: bf18 it ne +1003dd04: 2c00 cmpne r4, #0 +1003dd06: b085 sub sp, #20 +1003dd08: 460d mov r5, r1 +1003dd0a: d019 beq.n 1003dd40 +1003dd0c: b1c5 cbz r5, 1003dd40 +1003dd0e: 6930 ldr r0, [r6, #16] +1003dd10: 9004 str r0, [sp, #16] +1003dd12: f7ff fd9d bl 1003d850 +1003dd16: 0007 movs r7, r0 +1003dd18: d012 beq.n 1003dd40 +1003dd1a: a804 add r0, sp, #16 +1003dd1c: 9003 str r0, [sp, #12] +1003dd1e: 68b8 ldr r0, [r7, #8] +1003dd20: 9002 str r0, [sp, #8] +1003dd22: 6930 ldr r0, [r6, #16] +1003dd24: 9001 str r0, [sp, #4] +1003dd26: 68f0 ldr r0, [r6, #12] +1003dd28: 9000 str r0, [sp, #0] +1003dd2a: 686b ldr r3, [r5, #4] +1003dd2c: 68aa ldr r2, [r5, #8] +1003dd2e: 6861 ldr r1, [r4, #4] +1003dd30: 68a0 ldr r0, [r4, #8] +1003dd32: f000 f8d5 bl 1003dee0 +1003dd36: 2800 cmp r0, #0 +1003dd38: d504 bpl.n 1003dd44 +1003dd3a: 4638 mov r0, r7 +1003dd3c: f7ff fdaf bl 1003d89e +1003dd40: 2000 movs r0, #0 +1003dd42: e004 b.n 1003dd4e +1003dd44: 9904 ldr r1, [sp, #16] +1003dd46: 4638 mov r0, r7 +1003dd48: f7ff fdbe bl 1003d8c8 +1003dd4c: 4638 mov r0, r7 +1003dd4e: b005 add sp, #20 +1003dd50: bdf0 pop {r4, r5, r6, r7, pc} + ... + +1003dd54 : +1003dd54: b5f0 push {r4, r5, r6, r7, lr} +1003dd56: f20f 1240 addw r2, pc, #320 ; 0x140 +1003dd5a: 4b4a ldr r3, [pc, #296] ; (1003de84 <.text_7>) +1003dd5c: 4c4a ldr r4, [pc, #296] ; (1003de88 <.text_8>) +1003dd5e: e029 b.n 1003ddb4 +1003dd60: 19f6 adds r6, r6, r7 +1003dd62: 6026 str r6, [r4, #0] +1003dd64: f1ac 0601 sub.w r6, ip, #1 +1003dd68: f006 061f and.w r6, r6, #31 +1003dd6c: f106 0c1a add.w ip, r6, #26 +1003dd70: 6066 str r6, [r4, #4] +1003dd72: f00c 0c1f and.w ip, ip, #31 +1003dd76: f853 7026 ldr.w r7, [r3, r6, lsl #2] +1003dd7a: f853 c02c ldr.w ip, [r3, ip, lsl #2] +1003dd7e: ea8c 0707 eor.w r7, ip, r7 +1003dd82: f106 0c14 add.w ip, r6, #20 +1003dd86: f000 f829 bl 1003dddc <.text_5> +1003dd8a: f106 0c0e add.w ip, r6, #14 +1003dd8e: f000 f825 bl 1003dddc <.text_5> +1003dd92: f106 0c07 add.w ip, r6, #7 +1003dd96: f000 f821 bl 1003dddc <.text_5> +1003dd9a: f106 0c01 add.w ip, r6, #1 +1003dd9e: f000 f81d bl 1003dddc <.text_5> +1003dda2: 407d eors r5, r7 +1003dda4: f005 0707 and.w r7, r5, #7 +1003dda8: f852 7027 ldr.w r7, [r2, r7, lsl #2] +1003ddac: ea87 05d5 eor.w r5, r7, r5, lsr #3 +1003ddb0: f843 5026 str.w r5, [r3, r6, lsl #2] +1003ddb4: 460d mov r5, r1 +1003ddb6: 1e69 subs r1, r5, #1 +1003ddb8: b17d cbz r5, 1003ddda +1003ddba: 6827 ldr r7, [r4, #0] +1003ddbc: f810 5b01 ldrb.w r5, [r0], #1 +1003ddc0: f8d4 c004 ldr.w ip, [r4, #4] +1003ddc4: f007 061f and.w r6, r7, #31 +1003ddc8: f1c6 0620 rsb r6, r6, #32 +1003ddcc: 41f5 rors r5, r6 +1003ddce: f1bc 0f00 cmp.w ip, #0 +1003ddd2: bf14 ite ne +1003ddd4: 2607 movne r6, #7 +1003ddd6: 260e moveq r6, #14 +1003ddd8: e7c2 b.n 1003dd60 +1003ddda: bdf0 pop {r4, r5, r6, r7, pc} + +1003dddc <.text_5>: +1003dddc: f00c 0c1f and.w ip, ip, #31 +1003dde0: f853 c02c ldr.w ip, [r3, ip, lsl #2] +1003dde4: ea8c 0707 eor.w r7, ip, r7 +1003dde8: 4770 bx lr + +1003ddea : +1003ddea: e92d 43f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, lr} +1003ddee: b09b sub sp, #108 ; 0x6c +1003ddf0: 460d mov r5, r1 +1003ddf2: 4604 mov r4, r0 +1003ddf4: f7ff fa55 bl 1003d2a2 +1003ddf8: 4681 mov r9, r0 +1003ddfa: 002f movs r7, r5 +1003ddfc: f8df 8084 ldr.w r8, [pc, #132] ; 1003de84 <.text_7> +1003de00: 4e21 ldr r6, [pc, #132] ; (1003de88 <.text_8>) +1003de02: e009 b.n 1003de18 +1003de04: ab06 add r3, sp, #24 +1003de06: 7822 ldrb r2, [r4, #0] +1003de08: 5cc3 ldrb r3, [r0, r3] +1003de0a: 405a eors r2, r3 +1003de0c: f804 2b01 strb.w r2, [r4], #1 +1003de10: 1c40 adds r0, r0, #1 +1003de12: 4288 cmp r0, r1 +1003de14: d3f6 bcc.n 1003de04 +1003de16: 1a7f subs r7, r7, r1 +1003de18: d02a beq.n 1003de70 +1003de1a: a801 add r0, sp, #4 +1003de1c: 9000 str r0, [sp, #0] +1003de1e: 2380 movs r3, #128 ; 0x80 +1003de20: 4642 mov r2, r8 +1003de22: f000 f833 bl 1003de8c <.text_9> +1003de26: 2114 movs r1, #20 +1003de28: a801 add r0, sp, #4 +1003de2a: f7ff ff93 bl 1003dd54 +1003de2e: 2000 movs r0, #0 +1003de30: aa0a add r2, sp, #40 ; 0x28 +1003de32: 6871 ldr r1, [r6, #4] +1003de34: 1a09 subs r1, r1, r0 +1003de36: f001 011f and.w r1, r1, #31 +1003de3a: f858 1021 ldr.w r1, [r8, r1, lsl #2] +1003de3e: f842 1020 str.w r1, [r2, r0, lsl #2] +1003de42: 1c40 adds r0, r0, #1 +1003de44: 2810 cmp r0, #16 +1003de46: d3f4 bcc.n 1003de32 +1003de48: a801 add r0, sp, #4 +1003de4a: 9000 str r0, [sp, #0] +1003de4c: 2340 movs r3, #64 ; 0x40 +1003de4e: f000 f81d bl 1003de8c <.text_9> +1003de52: 9801 ldr r0, [sp, #4] +1003de54: 9905 ldr r1, [sp, #20] +1003de56: 4048 eors r0, r1 +1003de58: 9001 str r0, [sp, #4] +1003de5a: 2210 movs r2, #16 +1003de5c: a901 add r1, sp, #4 +1003de5e: a806 add r0, sp, #24 +1003de60: f7d2 fcd5 bl 1001080e +1003de64: 2f11 cmp r7, #17 +1003de66: bf2c ite cs +1003de68: 2110 movcs r1, #16 +1003de6a: 4639 movcc r1, r7 +1003de6c: 2000 movs r0, #0 +1003de6e: e7d0 b.n 1003de12 +1003de70: 68b0 ldr r0, [r6, #8] +1003de72: 42a8 cmp r0, r5 +1003de74: bf34 ite cc +1003de76: 2000 movcc r0, #0 +1003de78: 1b40 subcs r0, r0, r5 +1003de7a: 60b0 str r0, [r6, #8] +1003de7c: b01b add sp, #108 ; 0x6c +1003de7e: 4648 mov r0, r9 +1003de80: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} + +1003de84 <.text_7>: +1003de84: 10048878 .word 0x10048878 + +1003de88 <.text_8>: +1003de88: 100488f8 .word 0x100488f8 + +1003de8c <.text_9>: +1003de8c: 2114 movs r1, #20 +1003de8e: f106 000c add.w r0, r6, #12 +1003de92: f7e5 b969 b.w 10023168 + ... + +1003de98 : +1003de98: 0000 0000 20c8 3b6e 4190 76dc 6158 4db2 ..... n;.A.vXa.M +1003dea8: 8320 edb8 a3e8 d6d6 c2b0 9b64 e278 a00a .........d.x... + +1003deb8 : +1003deb8: f8df f000 ldr.w pc, [pc] ; 1003debc +1003debc: 00017b35 .word 0x00017b35 + +1003dec0 : +1003dec0: f8df f000 ldr.w pc, [pc] ; 1003dec4 +1003dec4: 00017c21 .word 0x00017c21 + +1003dec8 : +1003dec8: f8df f000 ldr.w pc, [pc] ; 1003decc +1003decc: 00017d2d .word 0x00017d2d + +1003ded0 : +1003ded0: f8df f000 ldr.w pc, [pc] ; 1003ded4 +1003ded4: 00017b85 .word 0x00017b85 + +1003ded8 : +1003ded8: f8df f000 ldr.w pc, [pc] ; 1003dedc +1003dedc: 00017b61 .word 0x00017b61 + +1003dee0 : +1003dee0: e92d 4ff1 stmdb sp!, {r0, r4, r5, r6, r7, r8, r9, sl, fp, lr} +1003dee4: 4688 mov r8, r1 +1003dee6: 4691 mov r9, r2 +1003dee8: 469a mov sl, r3 +1003deea: f04f 3bff mov.w fp, #4294967295 +1003deee: f7ff ffe3 bl 1003deb8 +1003def2: 4604 mov r4, r0 +1003def4: f7ff ffe0 bl 1003deb8 +1003def8: 4605 mov r5, r0 +1003defa: f7ff ffdd bl 1003deb8 +1003defe: 4606 mov r6, r0 +1003df00: f7ff ffda bl 1003deb8 +1003df04: 2c00 cmp r4, #0 +1003df06: bf18 it ne +1003df08: 2d00 cmpne r5, #0 +1003df0a: 4607 mov r7, r0 +1003df0c: d026 beq.n 1003df5c +1003df0e: 2e00 cmp r6, #0 +1003df10: bf18 it ne +1003df12: 2f00 cmpne r7, #0 +1003df14: d022 beq.n 1003df5c +1003df16: 9900 ldr r1, [sp, #0] +1003df18: 4642 mov r2, r8 +1003df1a: 4620 mov r0, r4 +1003df1c: f7ff ffd0 bl 1003dec0 +1003df20: 2800 cmp r0, #0 +1003df22: d41b bmi.n 1003df5c +1003df24: 4652 mov r2, sl +1003df26: 4649 mov r1, r9 +1003df28: 4628 mov r0, r5 +1003df2a: f7ff ffc9 bl 1003dec0 +1003df2e: 2800 cmp r0, #0 +1003df30: d414 bmi.n 1003df5c +1003df32: 9a0b ldr r2, [sp, #44] ; 0x2c +1003df34: 990a ldr r1, [sp, #40] ; 0x28 +1003df36: 4630 mov r0, r6 +1003df38: f7ff ffc2 bl 1003dec0 +1003df3c: 2800 cmp r0, #0 +1003df3e: d40d bmi.n 1003df5c +1003df40: 463b mov r3, r7 +1003df42: 4632 mov r2, r6 +1003df44: 4629 mov r1, r5 +1003df46: 4620 mov r0, r4 +1003df48: f7ff ffbe bl 1003dec8 +1003df4c: 2800 cmp r0, #0 +1003df4e: d405 bmi.n 1003df5c +1003df50: 9a0d ldr r2, [sp, #52] ; 0x34 +1003df52: 990c ldr r1, [sp, #48] ; 0x30 +1003df54: 4638 mov r0, r7 +1003df56: f7ff ffbb bl 1003ded0 +1003df5a: 4683 mov fp, r0 +1003df5c: 4620 mov r0, r4 +1003df5e: f7ff ffbb bl 1003ded8 +1003df62: 4628 mov r0, r5 +1003df64: f7ff ffb8 bl 1003ded8 +1003df68: 4630 mov r0, r6 +1003df6a: f7ff ffb5 bl 1003ded8 +1003df6e: 4638 mov r0, r7 +1003df70: f7ff ffb2 bl 1003ded8 +1003df74: 4658 mov r0, fp +1003df76: e8bd 8ff2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, sl, fp, pc} + ... + +1003df7c : +1003df7c: b538 push {r3, r4, r5, lr} +1003df7e: 4d17 ldr r5, [pc, #92] ; (1003dfdc ) +1003df80: 4817 ldr r0, [pc, #92] ; (1003dfe0 ) +1003df82: 2400 movs r4, #0 +1003df84: 602c str r4, [r5, #0] +1003df86: f000 f824 bl 1003dfd2 + +1003df8a : +1003df8a: 602c str r4, [r5, #0] +1003df8c: 4815 ldr r0, [pc, #84] ; (1003dfe4 ) +1003df8e: f000 f820 bl 1003dfd2 + +1003df92 : +1003df92: 602c str r4, [r5, #0] +1003df94: 4814 ldr r0, [pc, #80] ; (1003dfe8 ) +1003df96: f000 f81c bl 1003dfd2 + +1003df9a : +1003df9a: 602c str r4, [r5, #0] +1003df9c: 4813 ldr r0, [pc, #76] ; (1003dfec ) +1003df9e: f000 f818 bl 1003dfd2 + +1003dfa2 : +1003dfa2: 602c str r4, [r5, #0] + +1003dfa4 : +1003dfa4: f44f 1088 mov.w r0, #1114112 ; 0x110000 +1003dfa8: f000 f813 bl 1003dfd2 + +1003dfac : +1003dfac: 6868 ldr r0, [r5, #4] +1003dfae: f410 5f40 tst.w r0, #12288 ; 0x3000 +1003dfb2: d10d bne.n 1003dfd0 +1003dfb4: 1c64 adds r4, r4, #1 +1003dfb6: 201e movs r0, #30 +1003dfb8: f7c8 fe32 bl 10006c20 +1003dfbc: 480c ldr r0, [pc, #48] ; (1003dff0 ) +1003dfbe: 4284 cmp r4, r0 +1003dfc0: d3f0 bcc.n 1003dfa4 +1003dfc2: 4621 mov r1, r4 +1003dfc4: e8bd 4034 ldmia.w sp!, {r2, r4, r5, lr} +1003dfc8: f20f 0028 addw r0, pc, #40 ; 0x28 +1003dfcc: f7c6 b838 b.w 10004040 + +1003dfd0 : +1003dfd0: bd31 pop {r0, r4, r5, pc} + +1003dfd2 : +1003dfd2: 6028 str r0, [r5, #0] +1003dfd4: 2028 movs r0, #40 ; 0x28 +1003dfd6: f7c8 be23 b.w 10006c20 + ... + +1003dfdc : +1003dfdc: 0274 4000 t..@ + +1003dfe0 : +1003dfe0: 1500 0081 .... + +1003dfe4 : +1003dfe4: 01c0 0082 .... + +1003dfe8 : +1003dfe8: 0100 0084 .... + +1003dfec : +1003dfec: f980 0080 .... + +1003dff0 : +1003dff0: 86a1 0001 .... + +1003dff4 : +1003dff4: 3233 204b 6143 696c 7262 7461 6f69 206e 32K Calibration +1003e004: 6146 6c69 2121 000a Fail!!.. + +1003e00c : +1003e00c: 490a ldr r1, [pc, #40] ; (1003e038 ) +1003e00e: 6001 str r1, [r0, #0] +1003e010: 490a ldr r1, [pc, #40] ; (1003e03c ) +1003e012: 6041 str r1, [r0, #4] +1003e014: 490a ldr r1, [pc, #40] ; (1003e040 ) +1003e016: 6101 str r1, [r0, #16] +1003e018: 490a ldr r1, [pc, #40] ; (1003e044 ) +1003e01a: 6141 str r1, [r0, #20] +1003e01c: 490a ldr r1, [pc, #40] ; (1003e048 ) +1003e01e: 6081 str r1, [r0, #8] +1003e020: 490a ldr r1, [pc, #40] ; (1003e04c ) +1003e022: 60c1 str r1, [r0, #12] +1003e024: 490a ldr r1, [pc, #40] ; (1003e050 ) +1003e026: 6181 str r1, [r0, #24] +1003e028: 490a ldr r1, [pc, #40] ; (1003e054 ) +1003e02a: 61c1 str r1, [r0, #28] +1003e02c: 490a ldr r1, [pc, #40] ; (1003e058 ) +1003e02e: 6201 str r1, [r0, #32] +1003e030: 490a ldr r1, [pc, #40] ; (1003e05c ) +1003e032: 6241 str r1, [r0, #36] ; 0x24 +1003e034: 4770 bx lr + ... + +1003e038 : +1003e038: 5df1 0000 .].. + +1003e03c : +1003e03c: 5e91 0000 .^.. + +1003e040 : +1003e040: 5e6d 0000 m^.. + +1003e044 : +1003e044: 5e51 0000 Q^.. + +1003e048 : +1003e048: 5ebd 0000 .^.. + +1003e04c : +1003e04c: 60dd 0000 .`.. + +1003e050 : +1003e050: 5e0d 0000 .^.. + +1003e054 : +1003e054: 6419 0000 .d.. + +1003e058 : +1003e058: 64a1 0000 .d.. + +1003e05c : +1003e05c: 6501 0000 .e.. + +1003e060 : +1003e060: f8df f000 ldr.w pc, [pc] ; 1003e064 +1003e064: 0000a061 .word 0x0000a061 + +1003e068 : +1003e068: f8df f000 ldr.w pc, [pc] ; 1003e06c +1003e06c: 0000a761 .word 0x0000a761 + +1003e070 : +1003e070: f8df f000 ldr.w pc, [pc] ; 1003e074 +1003e074: 0000a389 .word 0x0000a389 + +1003e078 : +1003e078: f8df f000 ldr.w pc, [pc] ; 1003e07c +1003e07c: 0000a09d .word 0x0000a09d + +1003e080 : +1003e080: f8df f000 ldr.w pc, [pc] ; 1003e084 +1003e084: 0000bee5 .word 0x0000bee5 + +1003e088 : +1003e088: f8df f000 ldr.w pc, [pc] ; 1003e08c +1003e08c: 0000ac65 .word 0x0000ac65 + +1003e090 : +1003e090: f8df f000 ldr.w pc, [pc] ; 1003e094 +1003e094: 0000be4d .word 0x0000be4d + +1003e098 : +1003e098: f8df f000 ldr.w pc, [pc] ; 1003e09c +1003e09c: 0000bc95 .word 0x0000bc95 + +1003e0a0 : +1003e0a0: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +1003e0a4: 7804 ldrb r4, [r0, #0] +1003e0a6: 6945 ldr r5, [r0, #20] +1003e0a8: 7b86 ldrb r6, [r0, #14] +1003e0aa: f890 9011 ldrb.w r9, [r0, #17] +1003e0ae: f890 8009 ldrb.w r8, [r0, #9] +1003e0b2: f8df 7744 ldr.w r7, [pc, #1860] ; 1003e7f8 +1003e0b6: 7838 ldrb r0, [r7, #0] +1003e0b8: 06c0 lsls r0, r0, #27 +1003e0ba: d50b bpl.n 1003e0d4 +1003e0bc: f20f 003c addw r0, pc, #60 ; 0x3c +1003e0c0: f7c5 ffbe bl 10004040 +1003e0c4: 7838 ldrb r0, [r7, #0] +1003e0c6: 06c0 lsls r0, r0, #27 +1003e0c8: d504 bpl.n 1003e0d4 +1003e0ca: 4621 mov r1, r4 +1003e0cc: f20f 004c addw r0, pc, #76 ; 0x4c +1003e0d0: f7c5 ffb6 bl 10004040 + +1003e0d4 : +1003e0d4: 7828 ldrb r0, [r5, #0] +1003e0d6: f008 0101 and.w r1, r8, #1 +1003e0da: ea40 2081 orr.w r0, r0, r1, lsl #10 +1003e0de: f006 0101 and.w r1, r6, #1 +1003e0e2: ea40 2001 orr.w r0, r0, r1, lsl #8 +1003e0e6: f009 0101 and.w r1, r9, #1 +1003e0ea: ea40 2241 orr.w r2, r0, r1, lsl #9 +1003e0ee: 2110 movs r1, #16 +1003e0f0: 4620 mov r0, r4 +1003e0f2: f7ff ffb5 bl 1003e060 +1003e0f6: 2000 movs r0, #0 +1003e0f8: e8bd 83f2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, pc} + +1003e0fc : +1003e0fc: 5b0d 3249 2043 4920 666e 485d 6c61 3249 .[I2C Inf]HalI2 +1003e10c: 5343 6e65 5264 6c74 3138 3539 0a61 0000 CSendRtl8195a... + +1003e11c : +1003e11c: 5b0d 3249 2043 4920 666e 495d 4332 4920 .[I2C Inf]I2C I +1003e12c: 646e 7865 203a 7825 000a 0000 ndex: %x.... + +1003e138 : +1003e138: e92d 4df0 stmdb sp!, {r4, r5, r6, r7, r8, sl, fp, lr} +1003e13c: 4604 mov r4, r0 +1003e13e: 1ca6 adds r6, r4, #2 +1003e140: b088 sub sp, #32 +1003e142: 7825 ldrb r5, [r4, #0] +1003e144: 78b0 ldrb r0, [r6, #2] +1003e146: 9005 str r0, [sp, #20] +1003e148: 2200 movs r2, #0 +1003e14a: 7870 ldrb r0, [r6, #1] +1003e14c: 9004 str r0, [sp, #16] +1003e14e: 216c movs r1, #108 ; 0x6c +1003e150: f8b6 801a ldrh.w r8, [r6, #26] +1003e154: 78a0 ldrb r0, [r4, #2] +1003e156: 9003 str r0, [sp, #12] +1003e158: 8bb0 ldrh r0, [r6, #28] +1003e15a: f8ad 0018 strh.w r0, [sp, #24] +1003e15e: 78f0 ldrb r0, [r6, #3] +1003e160: f88d 0006 strb.w r0, [sp, #6] +1003e164: f896 a007 ldrb.w sl, [r6, #7] +1003e168: 7a30 ldrb r0, [r6, #8] +1003e16a: f88d 0005 strb.w r0, [sp, #5] +1003e16e: 7a70 ldrb r0, [r6, #9] +1003e170: 9002 str r0, [sp, #8] +1003e172: 7ab0 ldrb r0, [r6, #10] +1003e174: f88d 0004 strb.w r0, [sp, #4] +1003e178: 7930 ldrb r0, [r6, #4] +1003e17a: f88d 0003 strb.w r0, [sp, #3] +1003e17e: 7970 ldrb r0, [r6, #5] +1003e180: f88d 0002 strb.w r0, [sp, #2] +1003e184: f894 0024 ldrb.w r0, [r4, #36] ; 0x24 +1003e188: f88d 0001 strb.w r0, [sp, #1] +1003e18c: f894 0025 ldrb.w r0, [r4, #37] ; 0x25 +1003e190: f88d 0000 strb.w r0, [sp] +1003e194: f000 fb2c bl 1003e7f0 + +1003e198 : +1003e198: 9904 ldr r1, [sp, #16] +1003e19a: 9805 ldr r0, [sp, #20] +1003e19c: f8df 7658 ldr.w r7, [pc, #1624] ; 1003e7f8 +1003e1a0: f001 0b01 and.w fp, r1, #1 +1003e1a4: f000 0003 and.w r0, r0, #3 +1003e1a8: 9903 ldr r1, [sp, #12] +1003e1aa: 0040 lsls r0, r0, #1 +1003e1ac: 2900 cmp r1, #0 +1003e1ae: d048 beq.n 1003e242 +1003e1b0: 9904 ldr r1, [sp, #16] +1003e1b2: 2901 cmp r1, #1 +1003e1b4: bf1a itte ne +1003e1b6: 9905 ldrne r1, [sp, #20] +1003e1b8: 2903 cmpne r1, #3 +1003e1ba: f04f 0a01 moveq.w sl, #1 +1003e1be: f00a 0101 and.w r1, sl, #1 +1003e1c2: ea4f 120b mov.w r2, fp, lsl #4 +1003e1c6: ea42 1141 orr.w r1, r2, r1, lsl #5 +1003e1ca: 4308 orrs r0, r1 +1003e1cc: 9903 ldr r1, [sp, #12] +1003e1ce: f001 0101 and.w r1, r1, #1 +1003e1d2: 4308 orrs r0, r1 +1003e1d4: f040 0240 orr.w r2, r0, #64 ; 0x40 +1003e1d8: 2100 movs r1, #0 +1003e1da: f000 fb09 bl 1003e7f0 + +1003e1de : +1003e1de: 7838 ldrb r0, [r7, #0] +1003e1e0: 06c0 lsls r0, r0, #27 +1003e1e2: d508 bpl.n 1003e1f6 +1003e1e4: f000 faff bl 1003e7e6 + +1003e1e8 : +1003e1e8: 4603 mov r3, r0 +1003e1ea: 2200 movs r2, #0 +1003e1ec: 4629 mov r1, r5 +1003e1ee: f20f 1058 addw r0, pc, #344 ; 0x158 +1003e1f2: f7c5 ff25 bl 10004040 + +1003e1f6 : +1003e1f6: f89d 1005 ldrb.w r1, [sp, #5] +1003e1fa: 9a02 ldr r2, [sp, #8] +1003e1fc: 2000 movs r0, #0 +1003e1fe: 4311 orrs r1, r2 +1003e200: bf18 it ne +1003e202: 2001 movne r0, #1 +1003e204: 02c0 lsls r0, r0, #11 +1003e206: ea40 300b orr.w r0, r0, fp, lsl #12 +1003e20a: f002 0101 and.w r1, r2, #1 +1003e20e: ea40 2081 orr.w r0, r0, r1, lsl #10 +1003e212: ea4f 5188 mov.w r1, r8, lsl #22 +1003e216: ea40 5291 orr.w r2, r0, r1, lsr #22 +1003e21a: 2104 movs r1, #4 +1003e21c: f000 fae8 bl 1003e7f0 + +1003e220 : +1003e220: 4620 mov r0, r4 +1003e222: f000 f93b bl 1003e49c +1003e226: 7838 ldrb r0, [r7, #0] +1003e228: 06c0 lsls r0, r0, #27 +1003e22a: d551 bpl.n 1003e2d0 +1003e22c: 2104 movs r1, #4 +1003e22e: f000 fadb bl 1003e7e8 + +1003e232 : +1003e232: 4603 mov r3, r0 +1003e234: 2204 movs r2, #4 +1003e236: 4629 mov r1, r5 +1003e238: f20f 1038 addw r0, pc, #312 ; 0x138 +1003e23c: f7c5 ff00 bl 10004040 +1003e240: e046 b.n 1003e2d0 + +1003e242 : +1003e242: ea40 02cb orr.w r2, r0, fp, lsl #3 +1003e246: f000 fad3 bl 1003e7f0 + +1003e24a : +1003e24a: 7838 ldrb r0, [r7, #0] +1003e24c: 06c0 lsls r0, r0, #27 +1003e24e: d508 bpl.n 1003e262 +1003e250: f000 fac9 bl 1003e7e6 + +1003e254 : +1003e254: 4603 mov r3, r0 +1003e256: 2200 movs r2, #0 +1003e258: 4629 mov r1, r5 +1003e25a: f20f 1044 addw r0, pc, #324 ; 0x144 +1003e25e: f7c5 feef bl 10004040 + +1003e262 : +1003e262: ea4f 5288 mov.w r2, r8, lsl #22 +1003e266: 0d92 lsrs r2, r2, #22 +1003e268: 2108 movs r1, #8 +1003e26a: f000 fac1 bl 1003e7f0 + +1003e26e : +1003e26e: 7838 ldrb r0, [r7, #0] +1003e270: 06c0 lsls r0, r0, #27 +1003e272: d509 bpl.n 1003e288 +1003e274: 2108 movs r1, #8 +1003e276: f000 fab7 bl 1003e7e8 + +1003e27a : +1003e27a: 4603 mov r3, r0 +1003e27c: 2208 movs r2, #8 +1003e27e: 4629 mov r1, r5 +1003e280: f20f 1048 addw r0, pc, #328 ; 0x148 +1003e284: f7c5 fedc bl 10004040 + +1003e288 : +1003e288: f89d 0004 ldrb.w r0, [sp, #4] +1003e28c: f000 0201 and.w r2, r0, #1 +1003e290: 2184 movs r1, #132 ; 0x84 +1003e292: f000 faad bl 1003e7f0 + +1003e296 : +1003e296: 7bb0 ldrb r0, [r6, #14] +1003e298: f000 0201 and.w r2, r0, #1 +1003e29c: 2198 movs r1, #152 ; 0x98 +1003e29e: f000 faa7 bl 1003e7f0 + +1003e2a2 : +1003e2a2: 7838 ldrb r0, [r7, #0] +1003e2a4: 06c0 lsls r0, r0, #27 +1003e2a6: d509 bpl.n 1003e2bc +1003e2a8: 2198 movs r1, #152 ; 0x98 +1003e2aa: f000 fa9d bl 1003e7e8 + +1003e2ae : +1003e2ae: 4603 mov r3, r0 +1003e2b0: 2298 movs r2, #152 ; 0x98 +1003e2b2: 4629 mov r1, r5 +1003e2b4: f20f 1040 addw r0, pc, #320 ; 0x140 +1003e2b8: f7c5 fec2 bl 10004040 + +1003e2bc : +1003e2bc: f8bd 2018 ldrh.w r2, [sp, #24] +1003e2c0: 217c movs r1, #124 ; 0x7c +1003e2c2: f000 fa95 bl 1003e7f0 + +1003e2c6 : +1003e2c6: f89d 2006 ldrb.w r2, [sp, #6] +1003e2ca: 2194 movs r1, #148 ; 0x94 +1003e2cc: f000 fa90 bl 1003e7f0 + +1003e2d0 : +1003e2d0: f89d 2002 ldrb.w r2, [sp, #2] +1003e2d4: 213c movs r1, #60 ; 0x3c +1003e2d6: f000 fa8b bl 1003e7f0 + +1003e2da : +1003e2da: f89d 2003 ldrb.w r2, [sp, #3] +1003e2de: 2138 movs r1, #56 ; 0x38 +1003e2e0: f000 fa86 bl 1003e7f0 + +1003e2e4 : +1003e2e4: f89d 2001 ldrb.w r2, [sp, #1] +1003e2e8: 218c movs r1, #140 ; 0x8c +1003e2ea: f000 fa81 bl 1003e7f0 + +1003e2ee : +1003e2ee: f89d 2000 ldrb.w r2, [sp] +1003e2f2: 2190 movs r1, #144 ; 0x90 +1003e2f4: f000 fa7c bl 1003e7f0 + +1003e2f8 : +1003e2f8: 7838 ldrb r0, [r7, #0] +1003e2fa: 06c0 lsls r0, r0, #27 +1003e2fc: d516 bpl.n 1003e32c +1003e2fe: 218c movs r1, #140 ; 0x8c +1003e300: f000 fa72 bl 1003e7e8 + +1003e304 : +1003e304: 4603 mov r3, r0 +1003e306: 228c movs r2, #140 ; 0x8c +1003e308: 4629 mov r1, r5 +1003e30a: f20f 1020 addw r0, pc, #288 ; 0x120 +1003e30e: f7c5 fe97 bl 10004040 +1003e312: 7838 ldrb r0, [r7, #0] +1003e314: 06c0 lsls r0, r0, #27 +1003e316: d509 bpl.n 1003e32c +1003e318: 2190 movs r1, #144 ; 0x90 +1003e31a: f000 fa65 bl 1003e7e8 + +1003e31e : +1003e31e: 4603 mov r3, r0 +1003e320: 2290 movs r2, #144 ; 0x90 +1003e322: 4629 mov r1, r5 +1003e324: f20f 103c addw r0, pc, #316 ; 0x13c +1003e328: f7c5 fe8a bl 10004040 + +1003e32c : +1003e32c: 4620 mov r0, r4 +1003e32e: f7ff fe9b bl 1003e068 +1003e332: 8af5 ldrh r5, [r6, #22] +1003e334: 2000 movs r0, #0 +1003e336: 82f0 strh r0, [r6, #22] +1003e338: 4620 mov r0, r4 +1003e33a: f7ff fe99 bl 1003e070 +1003e33e: 82f5 strh r5, [r6, #22] +1003e340: 2000 movs r0, #0 +1003e342: b008 add sp, #32 +1003e344: e8bd 8df0 ldmia.w sp!, {r4, r5, r6, r7, r8, sl, fp, pc} + +1003e348 : +1003e348: 5b0d 3249 2043 4920 666e 495d 696e 2074 .[I2C Inf]Init +1003e358: 616d 7473 7265 202c 4349 435f 4e4f 6425 master, IC_CON%d +1003e368: 255b 7832 3a5d 2520 0a78 0000 [%2x]: %x... + +1003e374 : +1003e374: 5b0d 3249 2043 4920 666e 495d 696e 2074 .[I2C Inf]Init +1003e384: 616d 7473 7265 202c 4349 545f 5241 6425 master, IC_TAR%d +1003e394: 255b 7832 3a5d 2520 0a78 0000 [%2x]: %x... + +1003e3a0 : +1003e3a0: 5b0d 3249 2043 4920 666e 495d 696e 2074 .[I2C Inf]Init +1003e3b0: 6c73 7661 2c65 4920 5f43 4f43 254e 5b64 slave, IC_CON%d[ +1003e3c0: 3225 5d78 203a 7825 000a 0000 %2x]: %x.... + +1003e3cc : +1003e3cc: 5b0d 3249 2043 4920 666e 495d 696e 2074 .[I2C Inf]Init +1003e3dc: 6c73 7661 2c65 4920 5f43 4153 2552 5b64 slave, IC_SAR%d[ +1003e3ec: 3225 5d78 203a 7825 000a 0000 %2x]: %x.... + +1003e3f8 : +1003e3f8: 5b0d 3249 2043 4920 666e 495d 696e 2074 .[I2C Inf]Init +1003e408: 6c73 7661 2c65 4920 4332 495f 5f43 4341 slave, I2C_IC_AC +1003e418: 5f4b 4347 6425 255b 7832 3a5d 2520 0a78 K_GC%d[%2x]: %x. +1003e428: 0000 0000 .... + +1003e42c : +1003e42c: 5b0d 3249 2043 4920 666e 495d 696e 2074 .[I2C Inf]Init +1003e43c: 3269 2063 6564 2c76 4920 4332 495f 5f43 i2c dev, I2C_IC_ +1003e44c: 4d44 5f41 4454 524c 6425 255b 7832 3a5d DMA_TDLR%d[%2x]: +1003e45c: 2520 0a78 0000 0000 %x..... + +1003e464 : +1003e464: 5b0d 3249 2043 4920 666e 495d 696e 2074 .[I2C Inf]Init +1003e474: 3269 2063 6564 2c76 4920 4332 495f 5f43 i2c dev, I2C_IC_ +1003e484: 4d44 5f41 4452 524c 6425 255b 7832 3a5d DMA_RDLR%d[%2x]: +1003e494: 2520 0a78 0000 0000 %x..... + +1003e49c : +1003e49c: e92d 42f0 stmdb sp!, {r4, r5, r6, r7, r9, lr} +1003e4a0: 7904 ldrb r4, [r0, #4] +1003e4a2: f8d0 9020 ldr.w r9, [r0, #32] +1003e4a6: 7805 ldrb r5, [r0, #0] +1003e4a8: f7d5 fa0a bl 100138c0 +1003e4ac: f8df 6348 ldr.w r6, [pc, #840] ; 1003e7f8 +1003e4b0: 4607 mov r7, r0 +1003e4b2: 7830 ldrb r0, [r6, #0] +1003e4b4: 06c0 lsls r0, r0, #27 +1003e4b6: d506 bpl.n 1003e4c6 +1003e4b8: 463a mov r2, r7 +1003e4ba: f20f 11ac addw r1, pc, #428 ; 0x1ac +1003e4be: f20f 10c0 addw r0, pc, #448 ; 0x1c0 +1003e4c2: f7c5 fdbd bl 10004040 + +1003e4c6 : +1003e4c6: f8df 0334 ldr.w r0, [pc, #820] ; 1003e7fc +1003e4ca: 6801 ldr r1, [r0, #0] +1003e4cc: f421 3140 bic.w r1, r1, #196608 ; 0x30000 +1003e4d0: 6001 str r1, [r0, #0] +1003e4d2: f8df 032c ldr.w r0, [pc, #812] ; 1003e800 +1003e4d6: fbb7 f0f0 udiv r0, r7, r0 +1003e4da: 0847 lsrs r7, r0, #1 +1003e4dc: 2c01 cmp r4, #1 +1003e4de: d004 beq.n 1003e4ea +1003e4e0: d302 bcc.n 1003e4e8 +1003e4e2: 2c03 cmp r4, #3 +1003e4e4: d062 beq.n 1003e5ac +1003e4e6: d32d bcc.n 1003e544 + +1003e4e8 : +1003e4e8: e0ba b.n 1003e660 + +1003e4ea : +1003e4ea: f000 f96e bl 1003e7ca + +1003e4ee : +1003e4ee: f241 215c movw r1, #4700 ; 0x125c +1003e4f2: 4341 muls r1, r0 +1003e4f4: f242 12fc movw r2, #8700 ; 0x21fc +1003e4f8: fbb1 f4f2 udiv r4, r1, r2 +1003e4fc: f44f 617a mov.w r1, #4000 ; 0xfa0 +1003e500: f000 f968 bl 1003e7d4 + +1003e504 : +1003e504: f000 f973 bl 1003e7ee + +1003e508 : +1003e508: 7830 ldrb r0, [r6, #0] +1003e50a: 06c0 lsls r0, r0, #27 +1003e50c: d509 bpl.n 1003e522 +1003e50e: 2114 movs r1, #20 +1003e510: f000 f96a bl 1003e7e8 + +1003e514 : +1003e514: 4603 mov r3, r0 +1003e516: 2214 movs r2, #20 +1003e518: 4629 mov r1, r5 +1003e51a: f20f 1080 addw r0, pc, #384 ; 0x180 +1003e51e: f7c5 fd8f bl 10004040 + +1003e522 : +1003e522: f000 f94b bl 1003e7bc + +1003e526 : +1003e526: 2118 movs r1, #24 +1003e528: f000 f962 bl 1003e7f0 + +1003e52c : +1003e52c: 7830 ldrb r0, [r6, #0] +1003e52e: 06c0 lsls r0, r0, #27 +1003e530: d5da bpl.n 1003e4e8 +1003e532: 2118 movs r1, #24 +1003e534: f000 f958 bl 1003e7e8 + +1003e538 : +1003e538: 4603 mov r3, r0 +1003e53a: 2218 movs r2, #24 +1003e53c: 4629 mov r1, r5 +1003e53e: f20f 1084 addw r0, pc, #388 ; 0x184 +1003e542: e08b b.n 1003e65c + +1003e544 : +1003e544: f000 f941 bl 1003e7ca + +1003e548 : +1003e548: f240 5114 movw r1, #1300 ; 0x514 +1003e54c: 4341 muls r1, r0 +1003e54e: f240 726c movw r2, #1900 ; 0x76c +1003e552: fbb1 f4f2 udiv r4, r1, r2 +1003e556: f44f 7116 mov.w r1, #600 ; 0x258 +1003e55a: f000 f93b bl 1003e7d4 + +1003e55e : +1003e55e: 2a05 cmp r2, #5 +1003e560: bf28 it cs +1003e562: 1f12 subcs r2, r2, #4 +1003e564: 211c movs r1, #28 +1003e566: f000 f943 bl 1003e7f0 + +1003e56a : +1003e56a: 7830 ldrb r0, [r6, #0] +1003e56c: 06c0 lsls r0, r0, #27 +1003e56e: d509 bpl.n 1003e584 +1003e570: 211c movs r1, #28 +1003e572: f000 f939 bl 1003e7e8 + +1003e576 : +1003e576: 4603 mov r3, r0 +1003e578: 221c movs r2, #28 +1003e57a: 4629 mov r1, r5 +1003e57c: f20f 106c addw r0, pc, #364 ; 0x16c +1003e580: f7c5 fd5e bl 10004040 + +1003e584 : +1003e584: f000 f91a bl 1003e7bc + +1003e588 : +1003e588: 2a04 cmp r2, #4 +1003e58a: bf28 it cs +1003e58c: 1ed2 subcs r2, r2, #3 +1003e58e: 2120 movs r1, #32 +1003e590: f000 f92e bl 1003e7f0 + +1003e594 : +1003e594: 7830 ldrb r0, [r6, #0] +1003e596: 06c0 lsls r0, r0, #27 +1003e598: d562 bpl.n 1003e660 +1003e59a: 2120 movs r1, #32 +1003e59c: f000 f924 bl 1003e7e8 + +1003e5a0 : +1003e5a0: 4603 mov r3, r0 +1003e5a2: 2220 movs r2, #32 +1003e5a4: 4629 mov r1, r5 +1003e5a6: f20f 106c addw r0, pc, #364 ; 0x16c +1003e5aa: e057 b.n 1003e65c + +1003e5ac : +1003e5ac: f44f 72c8 mov.w r2, #400 ; 0x190 +1003e5b0: f000 f91d bl 1003e7ee + +1003e5b4 : +1003e5b4: f44f 72eb mov.w r2, #470 ; 0x1d6 +1003e5b8: 2118 movs r1, #24 +1003e5ba: f000 f919 bl 1003e7f0 + +1003e5be : +1003e5be: 223c movs r2, #60 ; 0x3c +1003e5c0: 211c movs r1, #28 +1003e5c2: f000 f915 bl 1003e7f0 + +1003e5c6 : +1003e5c6: 2282 movs r2, #130 ; 0x82 +1003e5c8: 2120 movs r1, #32 +1003e5ca: f000 f911 bl 1003e7f0 + +1003e5ce : +1003e5ce: f000 f8fc bl 1003e7ca + +1003e5d2 : +1003e5d2: 213c movs r1, #60 ; 0x3c +1003e5d4: 4341 muls r1, r0 +1003e5d6: 22b4 movs r2, #180 ; 0xb4 +1003e5d8: fbb1 f9f2 udiv r9, r1, r2 +1003e5dc: 2178 movs r1, #120 ; 0x78 +1003e5de: 4348 muls r0, r1 +1003e5e0: fbb0 f4f2 udiv r4, r0, r2 +1003e5e4: 7830 ldrb r0, [r6, #0] +1003e5e6: 06c0 lsls r0, r0, #27 +1003e5e8: d50c bpl.n 1003e604 +1003e5ea: 4649 mov r1, r9 +1003e5ec: f20f 104c addw r0, pc, #332 ; 0x14c +1003e5f0: f7c5 fd26 bl 10004040 +1003e5f4: 7830 ldrb r0, [r6, #0] +1003e5f6: 06c0 lsls r0, r0, #27 +1003e5f8: d504 bpl.n 1003e604 +1003e5fa: 4621 mov r1, r4 +1003e5fc: f20f 1054 addw r0, pc, #340 ; 0x154 +1003e600: f7c5 fd1e bl 10004040 + +1003e604 : +1003e604: fb07 f009 mul.w r0, r7, r9 +1003e608: f44f 717a mov.w r1, #1000 ; 0x3e8 +1003e60c: fbb0 f2f1 udiv r2, r0, r1 +1003e610: 2a09 cmp r2, #9 +1003e612: bf28 it cs +1003e614: 1ed2 subcs r2, r2, #3 +1003e616: 2124 movs r1, #36 ; 0x24 +1003e618: f000 f8ea bl 1003e7f0 + +1003e61c : +1003e61c: 7830 ldrb r0, [r6, #0] +1003e61e: 06c0 lsls r0, r0, #27 +1003e620: d509 bpl.n 1003e636 +1003e622: 2124 movs r1, #36 ; 0x24 +1003e624: f000 f8e0 bl 1003e7e8 + +1003e628 : +1003e628: 4603 mov r3, r0 +1003e62a: 2224 movs r2, #36 ; 0x24 +1003e62c: 4629 mov r1, r5 +1003e62e: f20f 103c addw r0, pc, #316 ; 0x13c +1003e632: f7c5 fd05 bl 10004040 + +1003e636 : +1003e636: f000 f8c1 bl 1003e7bc + +1003e63a : +1003e63a: 2a07 cmp r2, #7 +1003e63c: bf28 it cs +1003e63e: 1f92 subcs r2, r2, #6 +1003e640: 2128 movs r1, #40 ; 0x28 +1003e642: f000 f8d5 bl 1003e7f0 + +1003e646 : +1003e646: 7830 ldrb r0, [r6, #0] +1003e648: 06c0 lsls r0, r0, #27 +1003e64a: d509 bpl.n 1003e660 +1003e64c: 2128 movs r1, #40 ; 0x28 +1003e64e: f000 f8cb bl 1003e7e8 + +1003e652 : +1003e652: 4603 mov r3, r0 +1003e654: 2228 movs r2, #40 ; 0x28 +1003e656: 4629 mov r1, r5 +1003e658: f20f 1038 addw r0, pc, #312 ; 0x138 + +1003e65c : +1003e65c: f7c5 fcf0 bl 10004040 + +1003e660 : +1003e660: 2000 movs r0, #0 +1003e662: e8bd 82f0 ldmia.w sp!, {r4, r5, r6, r7, r9, pc} + ... + +1003e668 : +1003e668: 6148 496c 4332 6553 4374 4b4c 7452 386c HalI2CSetCLKRtl8 +1003e678: 3931 6135 0000 0000 195a.... + +1003e680 : +1003e680: 5b0d 3249 2043 4920 666e 255d 2c73 4320 .[I2C Inf]%s, C +1003e690: 5550 4320 6b6c 253a 0a78 0000 PU Clk:%x... + +1003e69c : +1003e69c: 5b0d 3249 2043 4920 666e 495d 5f43 5353 .[I2C Inf]IC_SS +1003e6ac: 535f 4c43 485f 4e43 2554 5b64 3225 5d78 _SCL_HCNT%d[%2x] +1003e6bc: 203a 7825 000a 0000 : %x.... + +1003e6c4 : +1003e6c4: 5b0d 3249 2043 4920 666e 495d 5f43 5353 .[I2C Inf]IC_SS +1003e6d4: 535f 4c43 4c5f 4e43 2554 5b64 3225 5d78 _SCL_LCNT%d[%2x] +1003e6e4: 203a 7825 000a 0000 : %x.... + +1003e6ec : +1003e6ec: 5b0d 3249 2043 4920 666e 495d 5f43 5346 .[I2C Inf]IC_FS +1003e6fc: 535f 4c43 485f 4e43 2554 5b64 3225 5d78 _SCL_HCNT%d[%2x] +1003e70c: 203a 7825 000a 0000 : %x.... + +1003e714 : +1003e714: 5b0d 3249 2043 4920 666e 495d 5f43 5346 .[I2C Inf]IC_FS +1003e724: 535f 4c43 4c5f 4e43 2554 5b64 3225 5d78 _SCL_LCNT%d[%2x] +1003e734: 203a 7825 000a 0000 : %x.... + +1003e73c : +1003e73c: 5b0d 3249 2043 4920 666e 495d 4843 6974 .[I2C Inf]ICHti +1003e74c: 656d 253a 0a78 0000 me:%x... + +1003e754 : +1003e754: 5b0d 3249 2043 4920 666e 495d 4c43 6974 .[I2C Inf]ICLti +1003e764: 656d 253a 0a78 0000 me:%x... + +1003e76c : +1003e76c: 5b0d 3249 2043 4920 666e 495d 5f43 5348 .[I2C Inf]IC_HS +1003e77c: 535f 4c43 485f 4e43 2554 5b64 3225 5d78 _SCL_HCNT%d[%2x] +1003e78c: 203a 7825 000a 0000 : %x.... + +1003e794 : +1003e794: 5b0d 3249 2043 4920 666e 495d 5f43 5348 .[I2C Inf]IC_HS +1003e7a4: 535f 4c43 4c5f 4e43 2554 5b64 3225 5d78 _SCL_LCNT%d[%2x] +1003e7b4: 203a 7825 000a 0000 : %x.... + +1003e7bc : +1003e7bc: fb07 f004 mul.w r0, r7, r4 +1003e7c0: f44f 717a mov.w r1, #1000 ; 0x3e8 +1003e7c4: fbb0 f2f1 udiv r2, r0, r1 +1003e7c8: 4770 bx lr + +1003e7ca : +1003e7ca: f8df 0034 ldr.w r0, [pc, #52] ; 1003e800 +1003e7ce: fbb0 f0f9 udiv r0, r0, r9 +1003e7d2: 4770 bx lr + +1003e7d4 : +1003e7d4: 4348 muls r0, r1 +1003e7d6: fbb0 f0f2 udiv r0, r0, r2 +1003e7da: 4378 muls r0, r7 +1003e7dc: f44f 717a mov.w r1, #1000 ; 0x3e8 +1003e7e0: fbb0 f2f1 udiv r2, r0, r1 +1003e7e4: 4770 bx lr + +1003e7e6 : +1003e7e6: 2100 movs r1, #0 + +1003e7e8 : +1003e7e8: 4628 mov r0, r5 +1003e7ea: f7ff bc45 b.w 1003e078 + +1003e7ee : +1003e7ee: 2114 movs r1, #20 + +1003e7f0 : +1003e7f0: 4628 mov r0, r5 +1003e7f2: f7ff bc35 b.w 1003e060 + ... + +1003e7f8 : +1003e7f8: 0310 1000 .... + +1003e7fc : +1003e7fc: 0250 4000 P..@ + +1003e800 : +1003e800: 4240 000f @B.. + +1003e804 : +1003e804: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +1003e808: 4680 mov r8, r0 +1003e80a: b087 sub sp, #28 +1003e80c: f858 0c04 ldr.w r0, [r8, #-4] +1003e810: f8df b5ec ldr.w fp, [pc, #1516] ; 1003ee00 +1003e814: 9001 str r0, [sp, #4] +1003e816: 6845 ldr r5, [r0, #4] +1003e818: 6886 ldr r6, [r0, #8] +1003e81a: 6a80 ldr r0, [r0, #40] ; 0x28 +1003e81c: 9002 str r0, [sp, #8] +1003e81e: f108 0702 add.w r7, r8, #2 +1003e822: 9801 ldr r0, [sp, #4] +1003e824: 6b00 ldr r0, [r0, #48] ; 0x30 +1003e826: 9004 str r0, [sp, #16] +1003e828: f04f 0900 mov.w r9, #0 +1003e82c: 78b8 ldrb r0, [r7, #2] +1003e82e: 46ca mov sl, r9 +1003e830: f108 0414 add.w r4, r8, #20 +1003e834: 2801 cmp r0, #1 +1003e836: f040 8200 bne.w 1003ec3a +1003e83a: f8d8 0014 ldr.w r0, [r8, #20] +1003e83e: 0580 lsls r0, r0, #22 +1003e840: d571 bpl.n 1003e926 +1003e842: 68a0 ldr r0, [r4, #8] +1003e844: 9000 str r0, [sp, #0] +1003e846: b128 cbz r0, 1003e854 +1003e848: f110 0f01 cmn.w r0, #1 +1003e84c: d002 beq.n 1003e854 +1003e84e: f000 fdce bl 1003f3ee + +1003e852 : +1003e852: 4682 mov sl, r0 + +1003e854 : +1003e854: f000 fe00 bl 1003f458 + +1003e858 : +1003e858: 0680 lsls r0, r0, #26 +1003e85a: d524 bpl.n 1003e8a6 +1003e85c: f1b9 0f00 cmp.w r9, #0 +1003e860: d010 beq.n 1003e884 +1003e862: f000 fdc0 bl 1003f3e6 + +1003e866 : +1003e866: 2802 cmp r0, #2 +1003e868: d1f4 bne.n 1003e854 +1003e86a: 2011 movs r0, #17 +1003e86c: 7078 strb r0, [r7, #1] +1003e86e: 2025 movs r0, #37 ; 0x25 +1003e870: 6060 str r0, [r4, #4] +1003e872: f89b 0000 ldrb.w r0, [fp] +1003e876: 06c0 lsls r0, r0, #27 +1003e878: d50e bpl.n 1003e898 +1003e87a: f898 1000 ldrb.w r1, [r8] +1003e87e: f20f 40bc addw r0, pc, #1212 ; 0x4bc +1003e882: e230 b.n 1003ece6 + +1003e884 : +1003e884: 9800 ldr r0, [sp, #0] +1003e886: 2800 cmp r0, #0 +1003e888: d1e4 bne.n 1003e854 +1003e88a: 2011 movs r0, #17 +1003e88c: 7078 strb r0, [r7, #1] +1003e88e: 2025 movs r0, #37 ; 0x25 +1003e890: 6060 str r0, [r4, #4] +1003e892: f89b 0000 ldrb.w r0, [fp] +1003e896: 06c0 lsls r0, r0, #27 + +1003e898 : +1003e898: f140 822d bpl.w 1003ecf6 +1003e89c: f898 1000 ldrb.w r1, [r8] +1003e8a0: f20f 40c4 addw r0, pc, #1220 ; 0x4c4 +1003e8a4: e21f b.n 1003ece6 + +1003e8a6 : +1003e8a6: 68a0 ldr r0, [r4, #8] +1003e8a8: 9000 str r0, [sp, #0] +1003e8aa: b128 cbz r0, 1003e8b8 +1003e8ac: f110 0f01 cmn.w r0, #1 +1003e8b0: d002 beq.n 1003e8b8 +1003e8b2: f000 fd9c bl 1003f3ee + +1003e8b6 : +1003e8b6: 4682 mov sl, r0 + +1003e8b8 : +1003e8b8: f000 fdce bl 1003f458 + +1003e8bc : +1003e8bc: 0740 lsls r0, r0, #29 +1003e8be: d423 bmi.n 1003e908 +1003e8c0: f1b9 0f00 cmp.w r9, #0 +1003e8c4: d010 beq.n 1003e8e8 +1003e8c6: f000 fd8e bl 1003f3e6 + +1003e8ca : +1003e8ca: 2802 cmp r0, #2 +1003e8cc: d1f4 bne.n 1003e8b8 +1003e8ce: 2011 movs r0, #17 +1003e8d0: 7078 strb r0, [r7, #1] +1003e8d2: 2025 movs r0, #37 ; 0x25 +1003e8d4: 6060 str r0, [r4, #4] +1003e8d6: f89b 0000 ldrb.w r0, [fp] +1003e8da: 06c0 lsls r0, r0, #27 +1003e8dc: d570 bpl.n 1003e9c0 +1003e8de: f898 1000 ldrb.w r1, [r8] +1003e8e2: f20f 40b0 addw r0, pc, #1200 ; 0x4b0 +1003e8e6: e1fe b.n 1003ece6 + +1003e8e8 : +1003e8e8: 9800 ldr r0, [sp, #0] +1003e8ea: 2800 cmp r0, #0 +1003e8ec: d1e4 bne.n 1003e8b8 +1003e8ee: 2011 movs r0, #17 +1003e8f0: 7078 strb r0, [r7, #1] +1003e8f2: 2025 movs r0, #37 ; 0x25 +1003e8f4: 6060 str r0, [r4, #4] +1003e8f6: f89b 0000 ldrb.w r0, [fp] +1003e8fa: 06c0 lsls r0, r0, #27 +1003e8fc: d560 bpl.n 1003e9c0 +1003e8fe: f898 1000 ldrb.w r1, [r8] +1003e902: f20f 40bc addw r0, pc, #1212 ; 0x4bc +1003e906: e1ee b.n 1003ece6 + +1003e908 : +1003e908: 69b2 ldr r2, [r6, #24] +1003e90a: 2104 movs r1, #4 +1003e90c: 4628 mov r0, r5 +1003e90e: 4790 blx r2 +1003e910: 6921 ldr r1, [r4, #16] +1003e912: 69f3 ldr r3, [r6, #28] +1003e914: 8849 ldrh r1, [r1, #2] +1003e916: 0589 lsls r1, r1, #22 +1003e918: 0a80 lsrs r0, r0, #10 +1003e91a: 0d89 lsrs r1, r1, #22 +1003e91c: ea41 2280 orr.w r2, r1, r0, lsl #10 +1003e920: 2104 movs r1, #4 +1003e922: 4628 mov r0, r5 +1003e924: 4798 blx r3 + +1003e926 : +1003e926: 2100 movs r1, #0 +1003e928: 4640 mov r0, r8 +1003e92a: f7ff fba9 bl 1003e080 +1003e92e: f898 0002 ldrb.w r0, [r8, #2] +1003e932: 2800 cmp r0, #0 +1003e934: d16e bne.n 1003ea14 +1003e936: 2003 movs r0, #3 +1003e938: 7078 strb r0, [r7, #1] +1003e93a: 68a0 ldr r0, [r4, #8] +1003e93c: 9000 str r0, [sp, #0] +1003e93e: 2800 cmp r0, #0 +1003e940: bf18 it ne +1003e942: f110 0f01 cmnne.w r0, #1 +1003e946: d026 beq.n 1003e996 +1003e948: f000 fd51 bl 1003f3ee + +1003e94c : +1003e94c: 4682 mov sl, r0 +1003e94e: e022 b.n 1003e996 + +1003e950 : +1003e950: f000 fa71 bl 1003ee36 + +1003e954 : +1003e954: d104 bne.n 1003e960 +1003e956: f000 fd0a bl 1003f36e + +1003e95a : +1003e95a: bf5c itt pl +1003e95c: 2001 movpl r0, #1 +1003e95e: 7468 strbpl r0, [r5, #17] + +1003e960 : +1003e960: 6a71 ldr r1, [r6, #36] ; 0x24 +1003e962: 4628 mov r0, r5 +1003e964: 4788 blx r1 +1003e966: f000 fa4d bl 1003ee04 + +1003e96a : +1003e96a: f000 fcfc bl 1003f366 + +1003e96e : +1003e96e: d512 bpl.n 1003e996 +1003e970: 6a29 ldr r1, [r5, #32] +1003e972: f000 fd0e bl 1003f392 + +1003e976 : +1003e976: f000 fd6b bl 1003f450 + +1003e97a : +1003e97a: 0640 lsls r0, r0, #25 +1003e97c: d50b bpl.n 1003e996 +1003e97e: 69b2 ldr r2, [r6, #24] +1003e980: 2154 movs r1, #84 ; 0x54 +1003e982: 4628 mov r0, r5 +1003e984: 4790 blx r2 +1003e986: 6920 ldr r0, [r4, #16] +1003e988: 68c1 ldr r1, [r0, #12] +1003e98a: 1e49 subs r1, r1, #1 +1003e98c: 60c1 str r1, [r0, #12] +1003e98e: 6920 ldr r0, [r4, #16] +1003e990: 8801 ldrh r1, [r0, #0] +1003e992: 1c49 adds r1, r1, #1 +1003e994: 8001 strh r1, [r0, #0] + +1003e996 : +1003e996: 6920 ldr r0, [r4, #16] +1003e998: 8800 ldrh r0, [r0, #0] +1003e99a: b340 cbz r0, 1003e9ee +1003e99c: f000 fa3b bl 1003ee16 + +1003e9a0 : +1003e9a0: 0780 lsls r0, r0, #30 +1003e9a2: d4d5 bmi.n 1003e950 +1003e9a4: f1b9 0f00 cmp.w r9, #0 +1003e9a8: d011 beq.n 1003e9ce +1003e9aa: f000 fd1c bl 1003f3e6 + +1003e9ae : +1003e9ae: 2802 cmp r0, #2 +1003e9b0: d1db bne.n 1003e96a +1003e9b2: 2011 movs r0, #17 +1003e9b4: 7078 strb r0, [r7, #1] +1003e9b6: 2023 movs r0, #35 ; 0x23 +1003e9b8: 6060 str r0, [r4, #4] +1003e9ba: f89b 0000 ldrb.w r0, [fp] +1003e9be: 06c0 lsls r0, r0, #27 + +1003e9c0 : +1003e9c0: f140 8199 bpl.w 1003ecf6 +1003e9c4: f898 1000 ldrb.w r1, [r8] +1003e9c8: f60f 20bc addw r0, pc, #2748 ; 0xabc +1003e9cc: e18b b.n 1003ece6 + +1003e9ce : +1003e9ce: 9800 ldr r0, [sp, #0] +1003e9d0: 2800 cmp r0, #0 +1003e9d2: d1ca bne.n 1003e96a +1003e9d4: 2011 movs r0, #17 +1003e9d6: 7078 strb r0, [r7, #1] +1003e9d8: 2023 movs r0, #35 ; 0x23 +1003e9da: 6060 str r0, [r4, #4] +1003e9dc: f89b 0000 ldrb.w r0, [fp] +1003e9e0: 06c0 lsls r0, r0, #27 +1003e9e2: d5ed bpl.n 1003e9c0 +1003e9e4: f898 1000 ldrb.w r1, [r8] +1003e9e8: f60f 20c8 addw r0, pc, #2760 ; 0xac8 +1003e9ec: e17b b.n 1003ece6 + +1003e9ee : +1003e9ee: 9801 ldr r0, [sp, #4] +1003e9f0: 69c0 ldr r0, [r0, #28] +1003e9f2: 9003 str r0, [sp, #12] +1003e9f4: 2800 cmp r0, #0 +1003e9f6: bf18 it ne +1003e9f8: f110 0f01 cmnne.w r0, #1 +1003e9fc: d002 beq.n 1003ea04 +1003e9fe: f000 fcf6 bl 1003f3ee + +1003ea02 : +1003ea02: 4682 mov sl, r0 + +1003ea04 : +1003ea04: f000 fd28 bl 1003f458 + +1003ea08 : +1003ea08: f000 0006 and.w r0, r0, #6 +1003ea0c: 2806 cmp r0, #6 +1003ea0e: d11c bne.n 1003ea4a +1003ea10: 2002 movs r0, #2 +1003ea12: 7078 strb r0, [r7, #1] + +1003ea14 : +1003ea14: f898 0002 ldrb.w r0, [r8, #2] +1003ea18: 2802 cmp r0, #2 +1003ea1a: f040 80c9 bne.w 1003ebb0 +1003ea1e: 68a0 ldr r0, [r4, #8] +1003ea20: f000 fcdb bl 1003f3da + +1003ea24 : +1003ea24: bf18 it ne +1003ea26: f110 0f01 cmnne.w r0, #1 +1003ea2a: d002 beq.n 1003ea32 +1003ea2c: f000 fcdf bl 1003f3ee + +1003ea30 : +1003ea30: 4682 mov sl, r0 + +1003ea32 : +1003ea32: 6920 ldr r0, [r4, #16] +1003ea34: 8801 ldrh r1, [r0, #0] +1003ea36: 9106 str r1, [sp, #24] +1003ea38: 68c0 ldr r0, [r0, #12] +1003ea3a: 9005 str r0, [sp, #20] +1003ea3c: 2002 movs r0, #2 +1003ea3e: f000 fa07 bl 1003ee50 + +1003ea42 : +1003ea42: 6af1 ldr r1, [r6, #44] ; 0x2c +1003ea44: 4628 mov r0, r5 +1003ea46: 4788 blx r1 +1003ea48: e03e b.n 1003eac8 + +1003ea4a : +1003ea4a: f1b9 0f00 cmp.w r9, #0 +1003ea4e: d010 beq.n 1003ea72 +1003ea50: f000 fcc9 bl 1003f3e6 + +1003ea54 : +1003ea54: 2802 cmp r0, #2 +1003ea56: d1d5 bne.n 1003ea04 +1003ea58: 2011 movs r0, #17 +1003ea5a: 7078 strb r0, [r7, #1] +1003ea5c: 2024 movs r0, #36 ; 0x24 +1003ea5e: 6060 str r0, [r4, #4] +1003ea60: f89b 0000 ldrb.w r0, [fp] +1003ea64: 06c0 lsls r0, r0, #27 +1003ea66: d5ab bpl.n 1003e9c0 +1003ea68: f898 1000 ldrb.w r1, [r8] +1003ea6c: f60f 2070 addw r0, pc, #2672 ; 0xa70 +1003ea70: e139 b.n 1003ece6 + +1003ea72 : +1003ea72: 9803 ldr r0, [sp, #12] +1003ea74: 2800 cmp r0, #0 +1003ea76: d1c5 bne.n 1003ea04 +1003ea78: 2011 movs r0, #17 +1003ea7a: 7078 strb r0, [r7, #1] +1003ea7c: 2024 movs r0, #36 ; 0x24 +1003ea7e: 6060 str r0, [r4, #4] +1003ea80: f89b 0000 ldrb.w r0, [fp] +1003ea84: 06c0 lsls r0, r0, #27 +1003ea86: d59b bpl.n 1003e9c0 +1003ea88: f898 1000 ldrb.w r1, [r8] +1003ea8c: f60f 207c addw r0, pc, #2684 ; 0xa7c +1003ea90: e129 b.n 1003ece6 + +1003ea92 : +1003ea92: f000 f9c6 bl 1003ee22 + +1003ea96 : +1003ea96: 07c0 lsls r0, r0, #31 +1003ea98: d5fb bpl.n 1003ea92 + +1003ea9a : +1003ea9a: 2003 movs r0, #3 +1003ea9c: 7078 strb r0, [r7, #1] +1003ea9e: f04f 0900 mov.w r9, #0 +1003eaa2: 2000 movs r0, #0 +1003eaa4: 6060 str r0, [r4, #4] +1003eaa6: 46ca mov sl, r9 +1003eaa8: 6921 ldr r1, [r4, #16] +1003eaaa: 9806 ldr r0, [sp, #24] +1003eaac: 8008 strh r0, [r1, #0] +1003eaae: 6921 ldr r1, [r4, #16] +1003eab0: 9805 ldr r0, [sp, #20] +1003eab2: 60c8 str r0, [r1, #12] +1003eab4: 68a0 ldr r0, [r4, #8] +1003eab6: 9000 str r0, [sp, #0] +1003eab8: 2800 cmp r0, #0 +1003eaba: bf18 it ne +1003eabc: f110 0f01 cmnne.w r0, #1 +1003eac0: d002 beq.n 1003eac8 +1003eac2: f000 fc94 bl 1003f3ee + +1003eac6 : +1003eac6: 4682 mov sl, r0 + +1003eac8 : +1003eac8: f000 f9a5 bl 1003ee16 + +1003eacc : +1003eacc: 0740 lsls r0, r0, #29 +1003eace: d50f bpl.n 1003eaf0 +1003ead0: 6920 ldr r0, [r4, #16] +1003ead2: 8800 ldrh r0, [r0, #0] +1003ead4: b160 cbz r0, 1003eaf0 +1003ead6: f000 f9ae bl 1003ee36 + +1003eada : +1003eada: d104 bne.n 1003eae6 +1003eadc: f000 fc47 bl 1003f36e + +1003eae0 : +1003eae0: bf5c itt pl +1003eae2: 2001 movpl r0, #1 +1003eae4: 7468 strbpl r0, [r5, #17] + +1003eae6 : +1003eae6: 6a71 ldr r1, [r6, #36] ; 0x24 +1003eae8: 4628 mov r0, r5 +1003eaea: 4788 blx r1 +1003eaec: f000 f98a bl 1003ee04 + +1003eaf0 : +1003eaf0: f000 fc39 bl 1003f366 + +1003eaf4 : +1003eaf4: d54a bpl.n 1003eb8c +1003eaf6: f8d4 9008 ldr.w r9, [r4, #8] +1003eafa: f04f 0a00 mov.w sl, #0 +1003eafe: 46d3 mov fp, sl +1003eb00: f1b9 0f00 cmp.w r9, #0 +1003eb04: bf18 it ne +1003eb06: f119 0f01 cmnne.w r9, #1 +1003eb0a: d010 beq.n 1003eb2e +1003eb0c: f44f 707a mov.w r0, #1000 ; 0x3e8 +1003eb10: fb00 f009 mul.w r0, r0, r9 +1003eb14: 211f movs r1, #31 +1003eb16: fbb0 faf1 udiv sl, r0, r1 +1003eb1a: f000 f96b bl 1003edf4 + +1003eb1e : +1003eb1e: 4683 mov fp, r0 +1003eb20: e005 b.n 1003eb2e + +1003eb22 : +1003eb22: 4651 mov r1, sl +1003eb24: 4658 mov r0, fp +1003eb26: f7ff faaf bl 1003e088 +1003eb2a: 2802 cmp r0, #2 +1003eb2c: d00d beq.n 1003eb4a + +1003eb2e : +1003eb2e: f000 fc93 bl 1003f458 + +1003eb32 : +1003eb32: 0740 lsls r0, r0, #29 +1003eb34: d409 bmi.n 1003eb4a +1003eb36: f000 fc8b bl 1003f450 + +1003eb3a : +1003eb3a: 0640 lsls r0, r0, #25 +1003eb3c: d405 bmi.n 1003eb4a +1003eb3e: f1ba 0f00 cmp.w sl, #0 +1003eb42: d1ee bne.n 1003eb22 +1003eb44: f1b9 0f00 cmp.w r9, #0 +1003eb48: d1f1 bne.n 1003eb2e + +1003eb4a : +1003eb4a: 6a29 ldr r1, [r5, #32] +1003eb4c: f000 fc21 bl 1003f392 + +1003eb50 : +1003eb50: f000 fc7e bl 1003f450 + +1003eb54 : +1003eb54: 0640 lsls r0, r0, #25 +1003eb56: d50c bpl.n 1003eb72 +1003eb58: f000 fbff bl 1003f35a + +1003eb5c : +1003eb5c: f000 f961 bl 1003ee22 + +1003eb60 : +1003eb60: 07c0 lsls r0, r0, #31 +1003eb62: d4fb bmi.n 1003eb5c +1003eb64: f000 fbfc bl 1003f360 + +1003eb68 : +1003eb68: f000 f95b bl 1003ee22 + +1003eb6c : +1003eb6c: 07c0 lsls r0, r0, #31 +1003eb6e: d5fb bpl.n 1003eb68 +1003eb70: e793 b.n 1003ea9a + +1003eb72 : +1003eb72: f000 fc71 bl 1003f458 + +1003eb76 : +1003eb76: 0740 lsls r0, r0, #29 +1003eb78: d412 bmi.n 1003eba0 +1003eb7a: f000 fbee bl 1003f35a + +1003eb7e : +1003eb7e: f000 f950 bl 1003ee22 + +1003eb82 : +1003eb82: 07c0 lsls r0, r0, #31 +1003eb84: d4fb bmi.n 1003eb7e +1003eb86: f000 fbeb bl 1003f360 + +1003eb8a : +1003eb8a: e782 b.n 1003ea92 + +1003eb8c : +1003eb8c: 69b2 ldr r2, [r6, #24] + +1003eb8e : +1003eb8e: f000 fc64 bl 1003f45a + +1003eb92 : +1003eb92: 69b2 ldr r2, [r6, #24] +1003eb94: 0740 lsls r0, r0, #29 +1003eb96: d5fa bpl.n 1003eb8e +1003eb98: f000 fc5f bl 1003f45a + +1003eb9c : +1003eb9c: 0740 lsls r0, r0, #29 +1003eb9e: d534 bpl.n 1003ec0a + +1003eba0 : +1003eba0: 69b2 ldr r2, [r6, #24] +1003eba2: 2130 movs r1, #48 ; 0x30 +1003eba4: 4628 mov r0, r5 +1003eba6: 4790 blx r2 +1003eba8: f040 0058 orr.w r0, r0, #88 ; 0x58 +1003ebac: f000 f91e bl 1003edec + +1003ebb0 : +1003ebb0: f898 0002 ldrb.w r0, [r8, #2] +1003ebb4: 2801 cmp r0, #1 +1003ebb6: d127 bne.n 1003ec08 +1003ebb8: 2003 movs r0, #3 +1003ebba: 7078 strb r0, [r7, #1] +1003ebbc: 2130 movs r1, #48 ; 0x30 +1003ebbe: f000 f92d bl 1003ee1c + +1003ebc2 : +1003ebc2: f040 0048 orr.w r0, r0, #72 ; 0x48 +1003ebc6: f000 f911 bl 1003edec + +1003ebca : +1003ebca: 9901 ldr r1, [sp, #4] +1003ebcc: 9804 ldr r0, [sp, #16] +1003ebce: 6b49 ldr r1, [r1, #52] ; 0x34 +1003ebd0: 4788 blx r1 +1003ebd2: 6920 ldr r0, [r4, #16] +1003ebd4: 9902 ldr r1, [sp, #8] +1003ebd6: 8800 ldrh r0, [r0, #0] +1003ebd8: 8548 strh r0, [r1, #42] ; 0x2a +1003ebda: 6920 ldr r0, [r4, #16] +1003ebdc: 9902 ldr r1, [sp, #8] +1003ebde: 68c0 ldr r0, [r0, #12] +1003ebe0: 6008 str r0, [r1, #0] +1003ebe2: f000 fbb4 bl 1003f34e + +1003ebe6 : +1003ebe6: 9902 ldr r1, [sp, #8] +1003ebe8: 6048 str r0, [r1, #4] +1003ebea: 9904 ldr r1, [sp, #16] +1003ebec: 9802 ldr r0, [sp, #8] +1003ebee: 6889 ldr r1, [r1, #8] +1003ebf0: 4788 blx r1 +1003ebf2: 9904 ldr r1, [sp, #16] +1003ebf4: 9802 ldr r0, [sp, #8] +1003ebf6: 6949 ldr r1, [r1, #20] +1003ebf8: 4788 blx r1 +1003ebfa: 2004 movs r0, #4 +1003ebfc: 7078 strb r0, [r7, #1] +1003ebfe: 2002 movs r0, #2 +1003ec00: 7368 strb r0, [r5, #13] +1003ec02: 4628 mov r0, r5 +1003ec04: 6b31 ldr r1, [r6, #48] ; 0x30 +1003ec06: 4788 blx r1 + +1003ec08 : +1003ec08: e094 b.n 1003ed34 + +1003ec0a : +1003ec0a: f1b9 0f00 cmp.w r9, #0 +1003ec0e: d003 beq.n 1003ec18 +1003ec10: f000 fbe9 bl 1003f3e6 + +1003ec14 : +1003ec14: 2802 cmp r0, #2 +1003ec16: e001 b.n 1003ec1c + +1003ec18 : +1003ec18: 9800 ldr r0, [sp, #0] +1003ec1a: 2800 cmp r0, #0 + +1003ec1c : +1003ec1c: f47f af54 bne.w 1003eac8 +1003ec20: f000 fba9 bl 1003f376 + +1003ec24 : +1003ec24: f000 f8fd bl 1003ee22 + +1003ec28 : +1003ec28: 07c0 lsls r0, r0, #31 +1003ec2a: d4fb bmi.n 1003ec24 +1003ec2c: f000 fb98 bl 1003f360 + +1003ec30 : +1003ec30: f000 f8f7 bl 1003ee22 + +1003ec34 : +1003ec34: 07c0 lsls r0, r0, #31 +1003ec36: d5fb bpl.n 1003ec30 +1003ec38: e05d b.n 1003ecf6 + +1003ec3a : +1003ec3a: f898 0002 ldrb.w r0, [r8, #2] +1003ec3e: 2800 cmp r0, #0 +1003ec40: d15d bne.n 1003ecfe +1003ec42: 68a0 ldr r0, [r4, #8] +1003ec44: 9000 str r0, [sp, #0] +1003ec46: 2800 cmp r0, #0 +1003ec48: bf18 it ne +1003ec4a: f110 0f01 cmnne.w r0, #1 +1003ec4e: d002 beq.n 1003ec56 +1003ec50: f000 fbcd bl 1003f3ee + +1003ec54 : +1003ec54: 4682 mov sl, r0 + +1003ec56 : +1003ec56: 2003 movs r0, #3 +1003ec58: 7078 strb r0, [r7, #1] +1003ec5a: e016 b.n 1003ec8a + +1003ec5c : +1003ec5c: f000 fbfc bl 1003f458 + +1003ec60 : +1003ec60: 0780 lsls r0, r0, #30 +1003ec62: d512 bpl.n 1003ec8a +1003ec64: 2001 movs r0, #1 +1003ec66: 73e8 strb r0, [r5, #15] +1003ec68: 6920 ldr r0, [r4, #16] +1003ec6a: 68c0 ldr r0, [r0, #12] +1003ec6c: 6168 str r0, [r5, #20] +1003ec6e: 4628 mov r0, r5 +1003ec70: 6a71 ldr r1, [r6, #36] ; 0x24 +1003ec72: 4788 blx r1 +1003ec74: 2050 movs r0, #80 ; 0x50 +1003ec76: f000 f8ed bl 1003ee54 + +1003ec7a : +1003ec7a: 6920 ldr r0, [r4, #16] +1003ec7c: 68c1 ldr r1, [r0, #12] +1003ec7e: 1c49 adds r1, r1, #1 +1003ec80: 60c1 str r1, [r0, #12] +1003ec82: 6920 ldr r0, [r4, #16] +1003ec84: 8801 ldrh r1, [r0, #0] +1003ec86: 1e49 subs r1, r1, #1 +1003ec88: 8001 strh r1, [r0, #0] + +1003ec8a : +1003ec8a: 6920 ldr r0, [r4, #16] +1003ec8c: 8800 ldrh r0, [r0, #0] +1003ec8e: 2800 cmp r0, #0 +1003ec90: d033 beq.n 1003ecfa +1003ec92: 2004 movs r0, #4 +1003ec94: 7078 strb r0, [r7, #1] +1003ec96: 2134 movs r1, #52 ; 0x34 +1003ec98: f000 f8c0 bl 1003ee1c + +1003ec9c : +1003ec9c: 0680 lsls r0, r0, #26 +1003ec9e: d4dd bmi.n 1003ec5c +1003eca0: f1b9 0f00 cmp.w r9, #0 +1003eca4: d010 beq.n 1003ecc8 +1003eca6: f000 fb9e bl 1003f3e6 + +1003ecaa : +1003ecaa: 2802 cmp r0, #2 +1003ecac: d1ed bne.n 1003ec8a +1003ecae: 2011 movs r0, #17 +1003ecb0: 7078 strb r0, [r7, #1] +1003ecb2: 2024 movs r0, #36 ; 0x24 +1003ecb4: 6060 str r0, [r4, #4] +1003ecb6: f89b 0000 ldrb.w r0, [fp] +1003ecba: 06c0 lsls r0, r0, #27 +1003ecbc: d51b bpl.n 1003ecf6 +1003ecbe: f898 1000 ldrb.w r1, [r8] +1003ecc2: f60f 0074 addw r0, pc, #2164 ; 0x874 +1003ecc6: e00e b.n 1003ece6 + +1003ecc8 : +1003ecc8: 9800 ldr r0, [sp, #0] +1003ecca: 2800 cmp r0, #0 +1003eccc: d1dd bne.n 1003ec8a +1003ecce: 2011 movs r0, #17 +1003ecd0: 7078 strb r0, [r7, #1] +1003ecd2: 2024 movs r0, #36 ; 0x24 +1003ecd4: 6060 str r0, [r4, #4] +1003ecd6: f89b 0000 ldrb.w r0, [fp] +1003ecda: 06c0 lsls r0, r0, #27 +1003ecdc: d50b bpl.n 1003ecf6 +1003ecde: f898 1000 ldrb.w r1, [r8] +1003ece2: f60f 0080 addw r0, pc, #2176 ; 0x880 + +1003ece6 : +1003ece6: f7c5 f9ab bl 10004040 +1003ecea: f89b 0000 ldrb.w r0, [fp] +1003ecee: 06c0 lsls r0, r0, #27 +1003ecf0: d501 bpl.n 1003ecf6 +1003ecf2: f000 f89a bl 1003ee2a + +1003ecf6 : +1003ecf6: 2002 movs r0, #2 +1003ecf8: e01d b.n 1003ed36 + +1003ecfa : +1003ecfa: 2002 movs r0, #2 +1003ecfc: 7078 strb r0, [r7, #1] + +1003ecfe : +1003ecfe: f898 0002 ldrb.w r0, [r8, #2] +1003ed02: 2802 cmp r0, #2 +1003ed04: d116 bne.n 1003ed34 +1003ed06: f000 f8a3 bl 1003ee50 + +1003ed0a : +1003ed0a: 204c movs r0, #76 ; 0x4c +1003ed0c: f000 f8a2 bl 1003ee54 + +1003ed10 : +1003ed10: 2050 movs r0, #80 ; 0x50 +1003ed12: f000 f89f bl 1003ee54 + +1003ed16 : +1003ed16: 205c movs r0, #92 ; 0x5c +1003ed18: f000 f89c bl 1003ee54 + +1003ed1c : +1003ed1c: 6af1 ldr r1, [r6, #44] ; 0x2c +1003ed1e: 4628 mov r0, r5 +1003ed20: 4788 blx r1 +1003ed22: 2003 movs r0, #3 +1003ed24: 7078 strb r0, [r7, #1] +1003ed26: 2130 movs r1, #48 ; 0x30 +1003ed28: f000 f878 bl 1003ee1c + +1003ed2c : +1003ed2c: f040 00e8 orr.w r0, r0, #232 ; 0xe8 +1003ed30: f000 f85c bl 1003edec + +1003ed34 : +1003ed34: 2000 movs r0, #0 + +1003ed36 : +1003ed36: b007 add sp, #28 +1003ed38: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1003ed3c : +1003ed3c: 5b0d 3249 2043 4520 7272 525d 6b74 3249 .[I2C Err]RtkI2 +1003ed4c: 5343 6e65 2064 6954 656d 756f 2c74 4920 CSend Timeout, I +1003ed5c: 4332 3225 2c78 0a31 0000 0000 2C%2x,1..... + +1003ed68 : +1003ed68: 5b0d 3249 2043 4520 7272 525d 6b74 3249 .[I2C Err]RtkI2 +1003ed78: 5343 6e65 2064 6954 656d 756f 2c74 4920 CSend Timeout, I +1003ed88: 4332 3225 2c78 0a32 0000 0000 2C%2x,2..... + +1003ed94 : +1003ed94: 5b0d 3249 2043 4520 7272 525d 6b74 3249 .[I2C Err]RtkI2 +1003eda4: 5343 6e65 2064 6954 656d 756f 2c74 4920 CSend Timeout, I +1003edb4: 4332 3225 2c78 0a33 0000 0000 2C%2x,3..... + +1003edc0 : +1003edc0: 5b0d 3249 2043 4520 7272 525d 6b74 3249 .[I2C Err]RtkI2 +1003edd0: 5343 6e65 2064 6954 656d 756f 2c74 4920 CSend Timeout, I +1003ede0: 4332 3225 2c78 0a34 0000 0000 2C%2x,4..... + +1003edec : +1003edec: 8328 strh r0, [r5, #24] +1003edee: 4628 mov r0, r5 +1003edf0: 6971 ldr r1, [r6, #20] + +1003edf2 <__iar_annotation$$tailcall>: +1003edf2: 4708 bx r1 + +1003edf4 : +1003edf4: f8df 164c ldr.w r1, [pc, #1612] ; 1003f444 +1003edf8: 6889 ldr r1, [r1, #8] +1003edfa: 2001 movs r0, #1 + +1003edfc <__iar_annotation$$tailcall>: +1003edfc: 4708 bx r1 + ... + +1003ee00 : +1003ee00: 0314 1000 .... + +1003ee04 : +1003ee04: 6920 ldr r0, [r4, #16] +1003ee06: 68c1 ldr r1, [r0, #12] +1003ee08: 1c49 adds r1, r1, #1 +1003ee0a: 60c1 str r1, [r0, #12] +1003ee0c: 6920 ldr r0, [r4, #16] +1003ee0e: 8801 ldrh r1, [r0, #0] +1003ee10: 1e49 subs r1, r1, #1 +1003ee12: 8001 strh r1, [r0, #0] +1003ee14: 4770 bx lr + +1003ee16 : +1003ee16: 2004 movs r0, #4 +1003ee18: 7078 strb r0, [r7, #1] +1003ee1a: 2170 movs r1, #112 ; 0x70 + +1003ee1c : +1003ee1c: 69b2 ldr r2, [r6, #24] +1003ee1e: 4628 mov r0, r5 + +1003ee20 <__iar_annotation$$tailcall>: +1003ee20: 4710 bx r2 + +1003ee22 : +1003ee22: 69b2 ldr r2, [r6, #24] +1003ee24: 219c movs r1, #156 ; 0x9c +1003ee26: 4628 mov r0, r5 + +1003ee28 <__iar_annotation$$tailcall>: +1003ee28: 4710 bx r2 + +1003ee2a : +1003ee2a: 6862 ldr r2, [r4, #4] +1003ee2c: 7879 ldrb r1, [r7, #1] + +1003ee2e : +1003ee2e: f20f 6034 addw r0, pc, #1588 ; 0x634 +1003ee32: f7c5 b905 b.w 10004040 + +1003ee36 : +1003ee36: 2000 movs r0, #0 +1003ee38: 73a8 strb r0, [r5, #14] +1003ee3a: 2001 movs r0, #1 +1003ee3c: 73e8 strb r0, [r5, #15] +1003ee3e: 6920 ldr r0, [r4, #16] +1003ee40: 68c0 ldr r0, [r0, #12] +1003ee42: 6168 str r0, [r5, #20] +1003ee44: 2000 movs r0, #0 +1003ee46: 7468 strb r0, [r5, #17] +1003ee48: 6920 ldr r0, [r4, #16] +1003ee4a: 8800 ldrh r0, [r0, #0] +1003ee4c: 2801 cmp r0, #1 +1003ee4e: 4770 bx lr + +1003ee50 : +1003ee50: 7078 strb r0, [r7, #1] +1003ee52: 2054 movs r0, #84 ; 0x54 + +1003ee54 : +1003ee54: 8368 strh r0, [r5, #26] +1003ee56: 4628 mov r0, r5 +1003ee58: 6ab1 ldr r1, [r6, #40] ; 0x28 + +1003ee5a <__iar_annotation$$tailcall>: +1003ee5a: 4708 bx r1 + +1003ee5c : +1003ee5c: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +1003ee60: 4680 mov r8, r0 +1003ee62: b08b sub sp, #44 ; 0x2c +1003ee64: f858 0c04 ldr.w r0, [r8, #-4] +1003ee68: f8df 55dc ldr.w r5, [pc, #1500] ; 1003f448 +1003ee6c: 9001 str r0, [sp, #4] +1003ee6e: f8d0 b004 ldr.w fp, [r0, #4] +1003ee72: 6886 ldr r6, [r0, #8] +1003ee74: 6ac0 ldr r0, [r0, #44] ; 0x2c +1003ee76: 9004 str r0, [sp, #16] +1003ee78: f108 0702 add.w r7, r8, #2 +1003ee7c: 9801 ldr r0, [sp, #4] +1003ee7e: 6b00 ldr r0, [r0, #48] ; 0x30 +1003ee80: 9006 str r0, [sp, #24] +1003ee82: f04f 0900 mov.w r9, #0 +1003ee86: 78b8 ldrb r0, [r7, #2] +1003ee88: 46ca mov sl, r9 +1003ee8a: f108 0414 add.w r4, r8, #20 +1003ee8e: 2801 cmp r0, #1 +1003ee90: f040 81d5 bne.w 1003f23e +1003ee94: f8d8 0014 ldr.w r0, [r8, #20] +1003ee98: 0580 lsls r0, r0, #22 +1003ee9a: d571 bpl.n 1003ef80 +1003ee9c: 68a0 ldr r0, [r4, #8] +1003ee9e: 9000 str r0, [sp, #0] +1003eea0: b128 cbz r0, 1003eeae +1003eea2: f110 0f01 cmn.w r0, #1 +1003eea6: d002 beq.n 1003eeae +1003eea8: f000 faa1 bl 1003f3ee + +1003eeac : +1003eeac: 4682 mov sl, r0 + +1003eeae : +1003eeae: f000 fa90 bl 1003f3d2 + +1003eeb2 : +1003eeb2: 0680 lsls r0, r0, #26 +1003eeb4: d524 bpl.n 1003ef00 +1003eeb6: 6af1 ldr r1, [r6, #44] ; 0x2c +1003eeb8: 4658 mov r0, fp +1003eeba: 4788 blx r1 +1003eebc: f1b9 0f00 cmp.w r9, #0 +1003eec0: d00f beq.n 1003eee2 +1003eec2: f000 fa90 bl 1003f3e6 + +1003eec6 : +1003eec6: 2802 cmp r0, #2 +1003eec8: d1f1 bne.n 1003eeae +1003eeca: 2011 movs r0, #17 +1003eecc: 7078 strb r0, [r7, #1] +1003eece: 2026 movs r0, #38 ; 0x26 +1003eed0: 6060 str r0, [r4, #4] +1003eed2: 7828 ldrb r0, [r5, #0] +1003eed4: 06c0 lsls r0, r0, #27 +1003eed6: d53c bpl.n 1003ef52 +1003eed8: f898 1000 ldrb.w r1, [r8] +1003eedc: f20f 60b0 addw r0, pc, #1712 ; 0x6b0 +1003eee0: e1f2 b.n 1003f2c8 + +1003eee2 : +1003eee2: 9800 ldr r0, [sp, #0] +1003eee4: 2800 cmp r0, #0 +1003eee6: d1e2 bne.n 1003eeae +1003eee8: 2011 movs r0, #17 +1003eeea: 7078 strb r0, [r7, #1] +1003eeec: 2026 movs r0, #38 ; 0x26 +1003eeee: 6060 str r0, [r4, #4] +1003eef0: 7828 ldrb r0, [r5, #0] +1003eef2: 06c0 lsls r0, r0, #27 +1003eef4: d52d bpl.n 1003ef52 +1003eef6: f898 1000 ldrb.w r1, [r8] +1003eefa: f20f 60c0 addw r0, pc, #1728 ; 0x6c0 +1003eefe: e1e3 b.n 1003f2c8 + +1003ef00 : +1003ef00: 68a0 ldr r0, [r4, #8] +1003ef02: 9000 str r0, [sp, #0] +1003ef04: b128 cbz r0, 1003ef12 +1003ef06: f110 0f01 cmn.w r0, #1 +1003ef0a: d002 beq.n 1003ef12 +1003ef0c: f000 fa6f bl 1003f3ee + +1003ef10 : +1003ef10: 4682 mov sl, r0 + +1003ef12 : +1003ef12: f000 fa5e bl 1003f3d2 + +1003ef16 : +1003ef16: 0740 lsls r0, r0, #29 +1003ef18: d422 bmi.n 1003ef60 +1003ef1a: f1b9 0f00 cmp.w r9, #0 +1003ef1e: d00f beq.n 1003ef40 +1003ef20: f000 fa61 bl 1003f3e6 + +1003ef24 : +1003ef24: 2802 cmp r0, #2 +1003ef26: d1f4 bne.n 1003ef12 +1003ef28: 2011 movs r0, #17 +1003ef2a: 7078 strb r0, [r7, #1] +1003ef2c: 2026 movs r0, #38 ; 0x26 +1003ef2e: 6060 str r0, [r4, #4] +1003ef30: 7828 ldrb r0, [r5, #0] +1003ef32: 06c0 lsls r0, r0, #27 +1003ef34: d50d bpl.n 1003ef52 +1003ef36: f898 1000 ldrb.w r1, [r8] +1003ef3a: f20f 60ac addw r0, pc, #1708 ; 0x6ac +1003ef3e: e1c3 b.n 1003f2c8 + +1003ef40 : +1003ef40: 9800 ldr r0, [sp, #0] +1003ef42: 2800 cmp r0, #0 +1003ef44: d1e5 bne.n 1003ef12 +1003ef46: 2011 movs r0, #17 +1003ef48: 7078 strb r0, [r7, #1] +1003ef4a: 2026 movs r0, #38 ; 0x26 +1003ef4c: 6060 str r0, [r4, #4] +1003ef4e: 7828 ldrb r0, [r5, #0] +1003ef50: 06c0 lsls r0, r0, #27 + +1003ef52 : +1003ef52: f140 81c0 bpl.w 1003f2d6 +1003ef56: f898 1000 ldrb.w r1, [r8] +1003ef5a: f20f 60b8 addw r0, pc, #1720 ; 0x6b8 +1003ef5e: e1b3 b.n 1003f2c8 + +1003ef60 : +1003ef60: 69b2 ldr r2, [r6, #24] +1003ef62: 2104 movs r1, #4 +1003ef64: 4658 mov r0, fp +1003ef66: 4790 blx r2 +1003ef68: 9003 str r0, [sp, #12] +1003ef6a: 0a80 lsrs r0, r0, #10 +1003ef6c: 6961 ldr r1, [r4, #20] +1003ef6e: 8849 ldrh r1, [r1, #2] +1003ef70: 69f3 ldr r3, [r6, #28] +1003ef72: 0589 lsls r1, r1, #22 +1003ef74: 0d89 lsrs r1, r1, #22 +1003ef76: ea41 2280 orr.w r2, r1, r0, lsl #10 +1003ef7a: 2104 movs r1, #4 +1003ef7c: 4658 mov r0, fp +1003ef7e: 4798 blx r3 + +1003ef80 : +1003ef80: 2101 movs r1, #1 +1003ef82: 4640 mov r0, r8 +1003ef84: f7ff f87c bl 1003e080 +1003ef88: f898 0002 ldrb.w r0, [r8, #2] +1003ef8c: b9b8 cbnz r0, 1003efbe +1003ef8e: 2005 movs r0, #5 +1003ef90: 7078 strb r0, [r7, #1] +1003ef92: 6960 ldr r0, [r4, #20] +1003ef94: 9901 ldr r1, [sp, #4] +1003ef96: 8800 ldrh r0, [r0, #0] +1003ef98: 6188 str r0, [r1, #24] +1003ef9a: 6960 ldr r0, [r4, #20] +1003ef9c: 8800 ldrh r0, [r0, #0] +1003ef9e: 9003 str r0, [sp, #12] +1003efa0: 68a0 ldr r0, [r4, #8] +1003efa2: 9000 str r0, [sp, #0] +1003efa4: b128 cbz r0, 1003efb2 +1003efa6: f110 0f01 cmn.w r0, #1 +1003efaa: d002 beq.n 1003efb2 +1003efac: f000 fa1f bl 1003f3ee + +1003efb0 : +1003efb0: 4682 mov sl, r0 + +1003efb2 : +1003efb2: 6960 ldr r0, [r4, #20] +1003efb4: 8800 ldrh r0, [r0, #0] +1003efb6: 2800 cmp r0, #0 +1003efb8: d12a bne.n 1003f010 +1003efba: 2002 movs r0, #2 +1003efbc: 7078 strb r0, [r7, #1] + +1003efbe : +1003efbe: f898 0002 ldrb.w r0, [r8, #2] +1003efc2: 2802 cmp r0, #2 +1003efc4: f040 81bf bne.w 1003f346 +1003efc8: 9801 ldr r0, [sp, #4] +1003efca: 69c0 ldr r0, [r0, #28] +1003efcc: f000 fa05 bl 1003f3da + +1003efd0 : +1003efd0: bf18 it ne +1003efd2: f110 0f01 cmnne.w r0, #1 +1003efd6: d002 beq.n 1003efde +1003efd8: f000 fa09 bl 1003f3ee + +1003efdc : +1003efdc: 4682 mov sl, r0 + +1003efde : +1003efde: 6960 ldr r0, [r4, #20] +1003efe0: 8801 ldrh r1, [r0, #0] +1003efe2: 9109 str r1, [sp, #36] ; 0x24 +1003efe4: 68c0 ldr r0, [r0, #12] +1003efe6: 9008 str r0, [sp, #32] +1003efe8: 2005 movs r0, #5 +1003efea: 7078 strb r0, [r7, #1] +1003efec: f000 f9dd bl 1003f3aa + +1003eff0 : +1003eff0: 205c movs r0, #92 ; 0x5c +1003eff2: f000 f9db bl 1003f3ac + +1003eff6 : +1003eff6: 6af1 ldr r1, [r6, #44] ; 0x2c +1003eff8: 4658 mov r0, fp +1003effa: 4788 blx r1 +1003effc: e06b b.n 1003f0d6 + +1003effe : +1003effe: 69b2 ldr r2, [r6, #24] +1003f000: 2154 movs r1, #84 ; 0x54 +1003f002: 4658 mov r0, fp +1003f004: 4790 blx r2 +1003f006: 9801 ldr r0, [sp, #4] +1003f008: 6980 ldr r0, [r0, #24] +1003f00a: 9901 ldr r1, [sp, #4] +1003f00c: 1c40 adds r0, r0, #1 +1003f00e: 6188 str r0, [r1, #24] + +1003f010 : +1003f010: 2006 movs r0, #6 +1003f012: 7078 strb r0, [r7, #1] +1003f014: 2170 movs r1, #112 ; 0x70 +1003f016: f000 f9d5 bl 1003f3c4 + +1003f01a : +1003f01a: 0780 lsls r0, r0, #30 +1003f01c: d513 bpl.n 1003f046 +1003f01e: 9801 ldr r0, [sp, #4] +1003f020: 6980 ldr r0, [r0, #24] +1003f022: b180 cbz r0, 1003f046 +1003f024: f000 f9ed bl 1003f402 + +1003f028 : +1003f028: d105 bne.n 1003f036 +1003f02a: f000 f9a0 bl 1003f36e + +1003f02e : +1003f02e: bf5c itt pl +1003f030: 2001 movpl r0, #1 +1003f032: f88b 0011 strbpl.w r0, [fp, #17] + +1003f036 : +1003f036: 6a71 ldr r1, [r6, #36] ; 0x24 +1003f038: 4658 mov r0, fp +1003f03a: 4788 blx r1 +1003f03c: 9801 ldr r0, [sp, #4] +1003f03e: 6980 ldr r0, [r0, #24] +1003f040: b108 cbz r0, 1003f046 +1003f042: f000 f9ac bl 1003f39e + +1003f046 : +1003f046: 6961 ldr r1, [r4, #20] +1003f048: 9803 ldr r0, [sp, #12] +1003f04a: 8809 ldrh r1, [r1, #0] +1003f04c: 4288 cmp r0, r1 +1003f04e: d108 bne.n 1003f062 +1003f050: f000 f989 bl 1003f366 + +1003f054 : +1003f054: d505 bpl.n 1003f062 +1003f056: f000 f99a bl 1003f38e + +1003f05a : +1003f05a: f000 f9ac bl 1003f3b6 + +1003f05e : +1003f05e: 0640 lsls r0, r0, #25 +1003f060: d4cd bmi.n 1003effe + +1003f062 : +1003f062: f000 f9b6 bl 1003f3d2 + +1003f066 : +1003f066: f010 0f18 tst.w r0, #24 +1003f06a: d011 beq.n 1003f090 +1003f06c: 68f1 ldr r1, [r6, #12] +1003f06e: 4658 mov r0, fp +1003f070: 4788 blx r1 +1003f072: 6961 ldr r1, [r4, #20] +1003f074: 68c9 ldr r1, [r1, #12] +1003f076: 7008 strb r0, [r1, #0] +1003f078: 6960 ldr r0, [r4, #20] +1003f07a: 68c1 ldr r1, [r0, #12] +1003f07c: 1c49 adds r1, r1, #1 +1003f07e: 60c1 str r1, [r0, #12] +1003f080: 6960 ldr r0, [r4, #20] +1003f082: 8801 ldrh r1, [r0, #0] +1003f084: 1e49 subs r1, r1, #1 +1003f086: 8001 strh r1, [r0, #0] +1003f088: 6960 ldr r0, [r4, #20] +1003f08a: 8800 ldrh r0, [r0, #0] +1003f08c: 2800 cmp r0, #0 +1003f08e: d1e8 bne.n 1003f062 + +1003f090 : +1003f090: f1b9 0f00 cmp.w r9, #0 +1003f094: d00f beq.n 1003f0b6 +1003f096: f000 f9a6 bl 1003f3e6 + +1003f09a : +1003f09a: 2802 cmp r0, #2 + +1003f09c : +1003f09c: d189 bne.n 1003efb2 +1003f09e: 2011 movs r0, #17 +1003f0a0: 7078 strb r0, [r7, #1] +1003f0a2: 2022 movs r0, #34 ; 0x22 +1003f0a4: 6060 str r0, [r4, #4] +1003f0a6: 7828 ldrb r0, [r5, #0] +1003f0a8: 06c0 lsls r0, r0, #27 +1003f0aa: d50d bpl.n 1003f0c8 +1003f0ac: f898 1000 ldrb.w r1, [r8] +1003f0b0: f20f 508c addw r0, pc, #1420 ; 0x58c +1003f0b4: e108 b.n 1003f2c8 + +1003f0b6 : +1003f0b6: 9800 ldr r0, [sp, #0] +1003f0b8: 2800 cmp r0, #0 +1003f0ba: d1ef bne.n 1003f09c +1003f0bc: 2011 movs r0, #17 +1003f0be: 7078 strb r0, [r7, #1] +1003f0c0: 2022 movs r0, #34 ; 0x22 +1003f0c2: 6060 str r0, [r4, #4] +1003f0c4: 7828 ldrb r0, [r5, #0] +1003f0c6: 06c0 lsls r0, r0, #27 + +1003f0c8 : +1003f0c8: f140 8105 bpl.w 1003f2d6 +1003f0cc: f898 1000 ldrb.w r1, [r8] +1003f0d0: f20f 5098 addw r0, pc, #1432 ; 0x598 +1003f0d4: e0f8 b.n 1003f2c8 + +1003f0d6 : +1003f0d6: 69b2 ldr r2, [r6, #24] +1003f0d8: 2178 movs r1, #120 ; 0x78 +1003f0da: 4658 mov r0, fp +1003f0dc: 4790 blx r2 +1003f0de: 0005 movs r5, r0 +1003f0e0: d1f9 bne.n 1003f0d6 +1003f0e2: 6960 ldr r0, [r4, #20] +1003f0e4: 9901 ldr r1, [sp, #4] +1003f0e6: 8800 ldrh r0, [r0, #0] +1003f0e8: 6188 str r0, [r1, #24] +1003f0ea: 2002 movs r0, #2 +1003f0ec: 9002 str r0, [sp, #8] +1003f0ee: 2005 movs r0, #5 +1003f0f0: 7078 strb r0, [r7, #1] +1003f0f2: e00d b.n 1003f110 + +1003f0f4 : +1003f0f4: f000 f969 bl 1003f3ca + +1003f0f8 : +1003f0f8: 07c0 lsls r0, r0, #31 +1003f0fa: d5fb bpl.n 1003f0f4 +1003f0fc: f000 f991 bl 1003f422 + +1003f100 : +1003f100: b130 cbz r0, 1003f110 + +1003f102 : +1003f102: 9800 ldr r0, [sp, #0] +1003f104: f110 0f01 cmn.w r0, #1 +1003f108: d002 beq.n 1003f110 +1003f10a: f000 f970 bl 1003f3ee + +1003f10e : +1003f10e: 4682 mov sl, r0 + +1003f110 : +1003f110: 2500 movs r5, #0 +1003f112: 9503 str r5, [sp, #12] +1003f114: 68a0 ldr r0, [r4, #8] +1003f116: 9005 str r0, [sp, #20] +1003f118: 2800 cmp r0, #0 +1003f11a: bf18 it ne +1003f11c: f110 0f01 cmnne.w r0, #1 +1003f120: d008 beq.n 1003f134 +1003f122: f44f 717a mov.w r1, #1000 ; 0x3e8 +1003f126: 4348 muls r0, r1 +1003f128: 211f movs r1, #31 +1003f12a: fbb0 f5f1 udiv r5, r0, r1 +1003f12e: f7ff fe61 bl 1003edf4 + +1003f132 : +1003f132: 9003 str r0, [sp, #12] + +1003f134 : +1003f134: f000 f94d bl 1003f3d2 + +1003f138 : +1003f138: 9801 ldr r0, [sp, #4] +1003f13a: 6980 ldr r0, [r0, #24] +1003f13c: 2800 cmp r0, #0 +1003f13e: bf1c itt ne +1003f140: 9802 ldrne r0, [sp, #8] +1003f142: 2800 cmpne r0, #0 +1003f144: d00b beq.n 1003f15e +1003f146: f000 f95c bl 1003f402 + +1003f14a : +1003f14a: d105 bne.n 1003f158 +1003f14c: f000 f90f bl 1003f36e + +1003f150 : +1003f150: bf5c itt pl +1003f152: 2001 movpl r0, #1 +1003f154: f88b 0011 strbpl.w r0, [fp, #17] + +1003f158 : +1003f158: 6a71 ldr r1, [r6, #36] ; 0x24 +1003f15a: 4658 mov r0, fp +1003f15c: 4788 blx r1 + +1003f15e : +1003f15e: 9802 ldr r0, [sp, #8] +1003f160: 1e40 subs r0, r0, #1 +1003f162: 9007 str r0, [sp, #28] +1003f164: f000 f8ff bl 1003f366 + +1003f168 : +1003f168: d53a bpl.n 1003f1e0 +1003f16a: e005 b.n 1003f178 + +1003f16c : +1003f16c: 9803 ldr r0, [sp, #12] +1003f16e: 4629 mov r1, r5 +1003f170: f7fe ff8a bl 1003e088 +1003f174: 2802 cmp r0, #2 +1003f176: d00c beq.n 1003f192 + +1003f178 : +1003f178: f000 f92b bl 1003f3d2 + +1003f17c : +1003f17c: 0740 lsls r0, r0, #29 +1003f17e: d408 bmi.n 1003f192 +1003f180: f000 f919 bl 1003f3b6 + +1003f184 : +1003f184: 0640 lsls r0, r0, #25 +1003f186: d404 bmi.n 1003f192 +1003f188: 2d00 cmp r5, #0 +1003f18a: d1ef bne.n 1003f16c +1003f18c: 9805 ldr r0, [sp, #20] +1003f18e: 2800 cmp r0, #0 +1003f190: d1f2 bne.n 1003f178 + +1003f192 : +1003f192: f000 f8fc bl 1003f38e + +1003f196 : +1003f196: f000 f90e bl 1003f3b6 + +1003f19a : +1003f19a: 4605 mov r5, r0 +1003f19c: f000 f919 bl 1003f3d2 + +1003f1a0 : +1003f1a0: 0669 lsls r1, r5, #25 +1003f1a2: d510 bpl.n 1003f1c6 +1003f1a4: f000 f8d9 bl 1003f35a + +1003f1a8 : +1003f1a8: f000 f90f bl 1003f3ca + +1003f1ac : +1003f1ac: 07c0 lsls r0, r0, #31 +1003f1ae: d4fb bmi.n 1003f1a8 +1003f1b0: f000 f8d6 bl 1003f360 + +1003f1b4 : +1003f1b4: f000 f909 bl 1003f3ca + +1003f1b8 : +1003f1b8: 07c0 lsls r0, r0, #31 +1003f1ba: d5fb bpl.n 1003f1b4 +1003f1bc: f000 f931 bl 1003f422 + +1003f1c0 : +1003f1c0: 2800 cmp r0, #0 +1003f1c2: d19e bne.n 1003f102 + +1003f1c4 : +1003f1c4: e7a4 b.n 1003f110 + +1003f1c6 : +1003f1c6: 0740 lsls r0, r0, #29 +1003f1c8: d408 bmi.n 1003f1dc +1003f1ca: f000 f8c6 bl 1003f35a + +1003f1ce : +1003f1ce: f000 f8fc bl 1003f3ca + +1003f1d2 : +1003f1d2: 07c0 lsls r0, r0, #31 +1003f1d4: d4fb bmi.n 1003f1ce +1003f1d6: f000 f8c3 bl 1003f360 + +1003f1da : +1003f1da: e78b b.n 1003f0f4 + +1003f1dc : +1003f1dc: f000 f8f9 bl 1003f3d2 + +1003f1e0 : +1003f1e0: 9802 ldr r0, [sp, #8] +1003f1e2: b150 cbz r0, 1003f1fa +1003f1e4: 9807 ldr r0, [sp, #28] +1003f1e6: 9002 str r0, [sp, #8] +1003f1e8: f000 f8d9 bl 1003f39e + +1003f1ec : +1003f1ec: 9802 ldr r0, [sp, #8] +1003f1ee: 2800 cmp r0, #0 +1003f1f0: bf1e ittt ne +1003f1f2: 6960 ldrne r0, [r4, #20] +1003f1f4: 8800 ldrhne r0, [r0, #0] +1003f1f6: 2801 cmpne r0, #1 +1003f1f8: d10a bne.n 1003f210 + +1003f1fa : +1003f1fa: f000 f8d6 bl 1003f3aa + +1003f1fe : +1003f1fe: 69b2 ldr r2, [r6, #24] +1003f200: 2130 movs r1, #48 ; 0x30 +1003f202: 4658 mov r0, fp +1003f204: 4790 blx r2 +1003f206: f040 0047 orr.w r0, r0, #71 ; 0x47 +1003f20a: f000 f8bb bl 1003f384 + +1003f20e : +1003f20e: e09a b.n 1003f346 + +1003f210 : +1003f210: f1b9 0f00 cmp.w r9, #0 +1003f214: d003 beq.n 1003f21e +1003f216: f000 f8e6 bl 1003f3e6 + +1003f21a : +1003f21a: 2802 cmp r0, #2 +1003f21c: e001 b.n 1003f222 + +1003f21e : +1003f21e: 9800 ldr r0, [sp, #0] +1003f220: 2800 cmp r0, #0 + +1003f222 : +1003f222: d1cf bne.n 1003f1c4 +1003f224: f000 f8a7 bl 1003f376 + +1003f228 : +1003f228: f000 f8cf bl 1003f3ca + +1003f22c : +1003f22c: 07c0 lsls r0, r0, #31 +1003f22e: d4fb bmi.n 1003f228 +1003f230: f000 f896 bl 1003f360 + +1003f234 : +1003f234: f000 f8c9 bl 1003f3ca + +1003f238 : +1003f238: 07c0 lsls r0, r0, #31 +1003f23a: d5fb bpl.n 1003f234 +1003f23c: e04b b.n 1003f2d6 + +1003f23e : +1003f23e: f898 0002 ldrb.w r0, [r8, #2] +1003f242: 2800 cmp r0, #0 +1003f244: d14b bne.n 1003f2de +1003f246: 68a0 ldr r0, [r4, #8] +1003f248: 9000 str r0, [sp, #0] +1003f24a: b1a0 cbz r0, 1003f276 +1003f24c: f110 0f01 cmn.w r0, #1 +1003f250: d011 beq.n 1003f276 +1003f252: f000 f8cc bl 1003f3ee + +1003f256 : +1003f256: 4682 mov sl, r0 +1003f258: e00d b.n 1003f276 + +1003f25a : +1003f25a: 68f1 ldr r1, [r6, #12] +1003f25c: 4658 mov r0, fp +1003f25e: 4788 blx r1 +1003f260: 6961 ldr r1, [r4, #20] +1003f262: 68c9 ldr r1, [r1, #12] +1003f264: 7008 strb r0, [r1, #0] +1003f266: 6960 ldr r0, [r4, #20] +1003f268: 68c1 ldr r1, [r0, #12] +1003f26a: 1c49 adds r1, r1, #1 +1003f26c: 60c1 str r1, [r0, #12] +1003f26e: 6960 ldr r0, [r4, #20] +1003f270: 8801 ldrh r1, [r0, #0] +1003f272: 1e49 subs r1, r1, #1 +1003f274: 8001 strh r1, [r0, #0] + +1003f276 : +1003f276: 6960 ldr r0, [r4, #20] +1003f278: 8800 ldrh r0, [r0, #0] +1003f27a: b370 cbz r0, 1003f2da +1003f27c: f000 f8a9 bl 1003f3d2 + +1003f280 : +1003f280: f010 0f18 tst.w r0, #24 +1003f284: d1e9 bne.n 1003f25a +1003f286: f1b9 0f00 cmp.w r9, #0 +1003f28a: d00f beq.n 1003f2ac +1003f28c: f000 f8ab bl 1003f3e6 + +1003f290 : +1003f290: 2802 cmp r0, #2 +1003f292: d1f0 bne.n 1003f276 +1003f294: 2011 movs r0, #17 +1003f296: 7078 strb r0, [r7, #1] +1003f298: 2022 movs r0, #34 ; 0x22 +1003f29a: 6060 str r0, [r4, #4] +1003f29c: 7828 ldrb r0, [r5, #0] +1003f29e: 06c0 lsls r0, r0, #27 +1003f2a0: d519 bpl.n 1003f2d6 +1003f2a2: f898 1000 ldrb.w r1, [r8] +1003f2a6: f20f 30f0 addw r0, pc, #1008 ; 0x3f0 +1003f2aa: e00d b.n 1003f2c8 + +1003f2ac : +1003f2ac: 9800 ldr r0, [sp, #0] +1003f2ae: 2800 cmp r0, #0 +1003f2b0: d1e1 bne.n 1003f276 +1003f2b2: 2011 movs r0, #17 +1003f2b4: 7078 strb r0, [r7, #1] +1003f2b6: 2022 movs r0, #34 ; 0x22 +1003f2b8: 6060 str r0, [r4, #4] +1003f2ba: 7828 ldrb r0, [r5, #0] +1003f2bc: 06c0 lsls r0, r0, #27 +1003f2be: d50a bpl.n 1003f2d6 +1003f2c0: f898 1000 ldrb.w r1, [r8] +1003f2c4: f20f 30fc addw r0, pc, #1020 ; 0x3fc + +1003f2c8 : +1003f2c8: f7c4 feba bl 10004040 +1003f2cc: 7828 ldrb r0, [r5, #0] +1003f2ce: 06c0 lsls r0, r0, #27 +1003f2d0: d501 bpl.n 1003f2d6 +1003f2d2: f7ff fdaa bl 1003ee2a + +1003f2d6 : +1003f2d6: 2002 movs r0, #2 +1003f2d8: e036 b.n 1003f348 + +1003f2da : +1003f2da: 2002 movs r0, #2 +1003f2dc: 7078 strb r0, [r7, #1] + +1003f2de : +1003f2de: f898 0002 ldrb.w r0, [r8, #2] +1003f2e2: 2802 cmp r0, #2 +1003f2e4: d105 bne.n 1003f2f2 +1003f2e6: f000 f86a bl 1003f3be + +1003f2ea : +1003f2ea: f040 0007 orr.w r0, r0, #7 +1003f2ee: f000 f849 bl 1003f384 + +1003f2f2 : +1003f2f2: f898 0002 ldrb.w r0, [r8, #2] +1003f2f6: 2801 cmp r0, #1 +1003f2f8: d125 bne.n 1003f346 +1003f2fa: f000 f860 bl 1003f3be + +1003f2fe : +1003f2fe: f040 0003 orr.w r0, r0, #3 +1003f302: f000 f83f bl 1003f384 + +1003f306 : +1003f306: 9901 ldr r1, [sp, #4] +1003f308: 9806 ldr r0, [sp, #24] +1003f30a: 6b49 ldr r1, [r1, #52] ; 0x34 +1003f30c: 4788 blx r1 +1003f30e: 6960 ldr r0, [r4, #20] +1003f310: 9904 ldr r1, [sp, #16] +1003f312: 8800 ldrh r0, [r0, #0] +1003f314: 8548 strh r0, [r1, #42] ; 0x2a +1003f316: f000 f81a bl 1003f34e + +1003f31a : +1003f31a: 9904 ldr r1, [sp, #16] +1003f31c: 6008 str r0, [r1, #0] +1003f31e: 6960 ldr r0, [r4, #20] +1003f320: 9904 ldr r1, [sp, #16] +1003f322: 68c0 ldr r0, [r0, #12] +1003f324: 6048 str r0, [r1, #4] +1003f326: 9906 ldr r1, [sp, #24] +1003f328: 9804 ldr r0, [sp, #16] +1003f32a: 6889 ldr r1, [r1, #8] +1003f32c: 4788 blx r1 +1003f32e: 9906 ldr r1, [sp, #24] +1003f330: 9804 ldr r0, [sp, #16] +1003f332: 6949 ldr r1, [r1, #20] +1003f334: 4788 blx r1 +1003f336: 2006 movs r0, #6 +1003f338: 7078 strb r0, [r7, #1] +1003f33a: 2001 movs r0, #1 +1003f33c: f88b 000d strb.w r0, [fp, #13] +1003f340: 4658 mov r0, fp +1003f342: 6b31 ldr r1, [r6, #48] ; 0x30 +1003f344: 4788 blx r1 + +1003f346 : +1003f346: 2000 movs r0, #0 + +1003f348 : +1003f348: b00b add sp, #44 ; 0x2c +1003f34a: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +1003f34e : +1003f34e: 493f ldr r1, [pc, #252] ; (1003f44c ) +1003f350: f898 0000 ldrb.w r0, [r8] +1003f354: eb01 2080 add.w r0, r1, r0, lsl #10 +1003f358: 4770 bx lr + +1003f35a : +1003f35a: 4640 mov r0, r8 +1003f35c: f7fe be98 b.w 1003e090 + +1003f360 : +1003f360: 4640 mov r0, r8 +1003f362: f7fe be99 b.w 1003e098 + +1003f366 : +1003f366: f8d8 0014 ldr.w r0, [r8, #20] +1003f36a: 05c0 lsls r0, r0, #23 +1003f36c: 4770 bx lr + +1003f36e : +1003f36e: f8d8 0014 ldr.w r0, [r8, #20] +1003f372: 0540 lsls r0, r0, #21 +1003f374: 4770 bx lr + +1003f376 : +1003f376: 2011 movs r0, #17 +1003f378: 7078 strb r0, [r7, #1] +1003f37a: 2024 movs r0, #36 ; 0x24 +1003f37c: 6060 str r0, [r4, #4] +1003f37e: 4640 mov r0, r8 +1003f380: f7fe be86 b.w 1003e090 + +1003f384 : +1003f384: f8ab 0018 strh.w r0, [fp, #24] +1003f388: 4658 mov r0, fp +1003f38a: 6971 ldr r1, [r6, #20] + +1003f38c <__iar_annotation$$tailcall>: +1003f38c: 4708 bx r1 + +1003f38e : +1003f38e: f8db 1020 ldr.w r1, [fp, #32] + +1003f392 : +1003f392: f247 5030 movw r0, #30000 ; 0x7530 +1003f396: fbb0 f0f1 udiv r0, r0, r1 +1003f39a: f7c7 bc41 b.w 10006c20 + +1003f39e : +1003f39e: 9801 ldr r0, [sp, #4] +1003f3a0: 6980 ldr r0, [r0, #24] +1003f3a2: 9901 ldr r1, [sp, #4] +1003f3a4: 1e40 subs r0, r0, #1 +1003f3a6: 6188 str r0, [r1, #24] +1003f3a8: 4770 bx lr + +1003f3aa : +1003f3aa: 2054 movs r0, #84 ; 0x54 + +1003f3ac : +1003f3ac: f8ab 001a strh.w r0, [fp, #26] +1003f3b0: 4658 mov r0, fp +1003f3b2: 6ab1 ldr r1, [r6, #40] ; 0x28 + +1003f3b4 <__iar_annotation$$tailcall>: +1003f3b4: 4708 bx r1 + +1003f3b6 : +1003f3b6: 69b2 ldr r2, [r6, #24] +1003f3b8: 2134 movs r1, #52 ; 0x34 +1003f3ba: 4658 mov r0, fp + +1003f3bc <__iar_annotation$$tailcall>: +1003f3bc: 4710 bx r2 + +1003f3be : +1003f3be: 2005 movs r0, #5 +1003f3c0: 7078 strb r0, [r7, #1] +1003f3c2: 2130 movs r1, #48 ; 0x30 + +1003f3c4 : +1003f3c4: 69b2 ldr r2, [r6, #24] +1003f3c6: 4658 mov r0, fp + +1003f3c8 <__iar_annotation$$tailcall>: +1003f3c8: 4710 bx r2 + +1003f3ca : +1003f3ca: 69b2 ldr r2, [r6, #24] +1003f3cc: 219c movs r1, #156 ; 0x9c +1003f3ce: 4658 mov r0, fp + +1003f3d0 <__iar_annotation$$tailcall>: +1003f3d0: 4710 bx r2 + +1003f3d2 : +1003f3d2: 69b2 ldr r2, [r6, #24] +1003f3d4: 2170 movs r1, #112 ; 0x70 +1003f3d6: 4658 mov r0, fp + +1003f3d8 <__iar_annotation$$tailcall>: +1003f3d8: 4710 bx r2 + +1003f3da : +1003f3da: 9000 str r0, [sp, #0] +1003f3dc: f04f 0900 mov.w r9, #0 +1003f3e0: 46ca mov sl, r9 +1003f3e2: 2800 cmp r0, #0 +1003f3e4: 4770 bx lr + +1003f3e6 : +1003f3e6: 4649 mov r1, r9 +1003f3e8: 4650 mov r0, sl +1003f3ea: f7fe be4d b.w 1003e088 + +1003f3ee : +1003f3ee: f44f 717a mov.w r1, #1000 ; 0x3e8 +1003f3f2: 4348 muls r0, r1 +1003f3f4: 211f movs r1, #31 +1003f3f6: fbb0 f9f1 udiv r9, r0, r1 +1003f3fa: 4912 ldr r1, [pc, #72] ; (1003f444 ) +1003f3fc: 6889 ldr r1, [r1, #8] +1003f3fe: 2001 movs r0, #1 + +1003f400 <__iar_annotation$$tailcall>: +1003f400: 4708 bx r1 + +1003f402 : +1003f402: 2001 movs r0, #1 +1003f404: f88b 000e strb.w r0, [fp, #14] +1003f408: f88b 000f strb.w r0, [fp, #15] +1003f40c: 6960 ldr r0, [r4, #20] +1003f40e: 68c0 ldr r0, [r0, #12] +1003f410: f8cb 0014 str.w r0, [fp, #20] +1003f414: 2000 movs r0, #0 +1003f416: f88b 0011 strb.w r0, [fp, #17] +1003f41a: 9801 ldr r0, [sp, #4] +1003f41c: 6980 ldr r0, [r0, #24] +1003f41e: 2801 cmp r0, #1 +1003f420: 4770 bx lr + +1003f422 : +1003f422: 2005 movs r0, #5 +1003f424: 7078 strb r0, [r7, #1] +1003f426: f04f 0900 mov.w r9, #0 +1003f42a: 2000 movs r0, #0 +1003f42c: 6060 str r0, [r4, #4] +1003f42e: 46ca mov sl, r9 +1003f430: 6961 ldr r1, [r4, #20] +1003f432: 9809 ldr r0, [sp, #36] ; 0x24 +1003f434: 8008 strh r0, [r1, #0] +1003f436: 6961 ldr r1, [r4, #20] +1003f438: 9808 ldr r0, [sp, #32] +1003f43a: 60c8 str r0, [r1, #12] +1003f43c: 9801 ldr r0, [sp, #4] +1003f43e: 69c0 ldr r0, [r0, #28] +1003f440: 9000 str r0, [sp, #0] +1003f442: 4770 bx lr + +1003f444 : +1003f444: 0318 1000 .... + +1003f448 : +1003f448: 0314 1000 .... + +1003f44c : +1003f44c: 4010 4004 .@.@ + +1003f450 : +1003f450: 69b2 ldr r2, [r6, #24] +1003f452: 2134 movs r1, #52 ; 0x34 +1003f454: 4628 mov r0, r5 + +1003f456 <__iar_annotation$$tailcall>: +1003f456: 4710 bx r2 + +1003f458 : +1003f458: 69b2 ldr r2, [r6, #24] + +1003f45a : +1003f45a: 2170 movs r1, #112 ; 0x70 +1003f45c: 4628 mov r0, r5 + +1003f45e <__iar_annotation$$tailcall>: +1003f45e: 4710 bx r2 +1003f460: 0000 movs r0, r0 + ... + +1003f464 : +1003f464: 5b0d 3249 2043 4520 7272 445d 7665 7453 .[I2C Err]DevSt +1003f474: 3a73 7825 202c 7245 5472 7079 3a65 7825 s:%x, ErrType:%x +1003f484: 000a 0000 .... + +1003f488 : +1003f488: 5b0d 3249 2043 4520 7272 525d 6b74 3249 .[I2C Err]RtkI2 +1003f498: 5343 6e65 2064 6954 656d 756f 2c74 4920 CSend Timeout, I +1003f4a8: 4332 3225 2c78 0a35 0000 0000 2C%2x,5..... + +1003f4b4 : +1003f4b4: 5b0d 3249 2043 4520 7272 525d 6b74 3249 .[I2C Err]RtkI2 +1003f4c4: 5343 6e65 2064 6954 656d 756f 2c74 4920 CSend Timeout, I +1003f4d4: 4332 3225 2c78 0a36 0000 0000 2C%2x,6..... + +1003f4e0 : +1003f4e0: 5b0d 3249 2043 4520 7272 525d 6b74 3249 .[I2C Err]RtkI2 +1003f4f0: 5343 6e65 2064 6954 656d 756f 2c74 4920 CSend Timeout, I +1003f500: 4332 3225 2c78 0a37 0000 0000 2C%2x,7..... + +1003f50c : +1003f50c: 5b0d 3249 2043 4520 7272 525d 6b74 3249 .[I2C Err]RtkI2 +1003f51c: 5343 6e65 2064 6954 656d 756f 2c74 4920 CSend Timeout, I +1003f52c: 4332 3225 2c78 0a38 0000 0000 2C%2x,8..... + +1003f538 : +1003f538: 5b0d 3249 2043 4520 7272 525d 6b74 3249 .[I2C Err]RtkI2 +1003f548: 5343 6e65 2064 6954 656d 756f 2c74 4920 CSend Timeout, I +1003f558: 4332 3225 2c78 0a39 0000 0000 2C%2x,9..... + +1003f564 : +1003f564: 5b0d 3249 2043 4520 7272 525d 6b74 3249 .[I2C Err]RtkI2 +1003f574: 5343 6e65 2064 6954 656d 756f 2c74 4920 CSend Timeout, I +1003f584: 4332 3225 2c78 3031 000a 0000 2C%2x,10.... + +1003f590 : +1003f590: 5b0d 3249 2043 4520 7272 525d 6b74 3249 .[I2C Err]RtkI2 +1003f5a0: 5243 6365 6965 6576 5420 6d69 6f65 7475 CReceive Timeout +1003f5b0: 202c 3249 2543 7832 312c 000a , I2C%2x,1.. + +1003f5bc : +1003f5bc: 5b0d 3249 2043 4520 7272 525d 6b74 3249 .[I2C Err]RtkI2 +1003f5cc: 5243 6365 6965 6576 5420 6d69 6f65 7475 CReceive Timeout +1003f5dc: 202c 3249 2543 7832 322c 000a , I2C%2x,2.. + +1003f5e8 : +1003f5e8: 5b0d 3249 2043 4520 7272 525d 6b74 3249 .[I2C Err]RtkI2 +1003f5f8: 5243 6365 6965 6576 5420 6d69 6f65 7475 CReceive Timeout +1003f608: 202c 3249 2543 7832 332c 000a , I2C%2x,3.. + +1003f614 : +1003f614: 5b0d 3249 2043 4520 7272 525d 6b74 3249 .[I2C Err]RtkI2 +1003f624: 5243 6365 6965 6576 5420 6d69 6f65 7475 CReceive Timeout +1003f634: 202c 3249 2543 7832 342c 000a , I2C%2x,4.. + +1003f640 : +1003f640: 5b0d 3249 2043 4520 7272 525d 6b74 3249 .[I2C Err]RtkI2 +1003f650: 5243 6365 6965 6576 5420 6d69 6f65 7475 CReceive Timeout +1003f660: 202c 3249 2543 7832 352c 000a , I2C%2x,5.. + +1003f66c : +1003f66c: 5b0d 3249 2043 4520 7272 525d 6b74 3249 .[I2C Err]RtkI2 +1003f67c: 5243 6365 6965 6576 5420 6d69 6f65 7475 CReceive Timeout +1003f68c: 202c 3249 2543 7832 362c 000a , I2C%2x,6.. + +1003f698 : +1003f698: 5b0d 3249 2043 4520 7272 525d 6b74 3249 .[I2C Err]RtkI2 +1003f6a8: 5243 6365 6965 6576 5420 6d69 6f65 7475 CReceive Timeout +1003f6b8: 202c 3249 2543 7832 392c 000a , I2C%2x,9.. + +1003f6c4 : +1003f6c4: 5b0d 3249 2043 4520 7272 525d 6b74 3249 .[I2C Err]RtkI2 +1003f6d4: 5243 6365 6965 6576 5420 6d69 6f65 7475 CReceive Timeout +1003f6e4: 202c 3249 2543 7832 312c 0a30 0000 0000 , I2C%2x,10..... + +1003f6f4
: +1003f6f4: b580 push {r7, lr} +1003f6f6: 4802 ldr r0, [pc, #8] ; (1003f700 ) +1003f6f8: 6800 ldr r0, [r0, #0] +1003f6fa: 4780 blx r0 +1003f6fc: 2000 movs r0, #0 +1003f6fe: bd02 pop {r1, pc} + +1003f700 : +1003f700: 4160 1004 `A.. + +1003f704 : +1003f704: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1003f708: 4606 mov r6, r0 +1003f70a: 4c7e ldr r4, [pc, #504] ; (1003f904 ) +1003f70c: 7931 ldrb r1, [r6, #4] +1003f70e: 7972 ldrb r2, [r6, #5] +1003f710: 7830 ldrb r0, [r6, #0] +1003f712: 0849 lsrs r1, r1, #1 +1003f714: 79b1 ldrb r1, [r6, #6] +1003f716: f002 0201 and.w r2, r2, #1 +1003f71a: 4152 adcs r2, r2 +1003f71c: f001 0101 and.w r1, r1, #1 +1003f720: ea42 0181 orr.w r1, r2, r1, lsl #2 +1003f724: 78b2 ldrb r2, [r6, #2] +1003f726: f002 0201 and.w r2, r2, #1 +1003f72a: ea41 01c2 orr.w r1, r1, r2, lsl #3 +1003f72e: 78f2 ldrb r2, [r6, #3] +1003f730: f002 021f and.w r2, r2, #31 +1003f734: ea41 2102 orr.w r1, r1, r2, lsl #8 +1003f738: 79f2 ldrb r2, [r6, #7] +1003f73a: f002 023f and.w r2, r2, #63 ; 0x3f +1003f73e: ea41 4102 orr.w r1, r1, r2, lsl #16 +1003f742: 7bf2 ldrb r2, [r6, #15] +1003f744: f002 0207 and.w r2, r2, #7 +1003f748: ea41 6102 orr.w r1, r1, r2, lsl #24 +1003f74c: 6021 str r1, [r4, #0] +1003f74e: b128 cbz r0, 1003f75c +1003f750: 2802 cmp r0, #2 +1003f752: d041 beq.n 1003f7d8 +1003f754: d33a bcc.n 1003f7cc +1003f756: 2803 cmp r0, #3 +1003f758: d045 beq.n 1003f7e6 +1003f75a: e04a b.n 1003f7f2 + +1003f75c : +1003f75c: 68e0 ldr r0, [r4, #12] +1003f75e: 8971 ldrh r1, [r6, #10] +1003f760: 0c00 lsrs r0, r0, #16 +1003f762: ea41 4000 orr.w r0, r1, r0, lsl #16 + +1003f766 : +1003f766: 60e0 str r0, [r4, #12] + +1003f768 : +1003f768: 6960 ldr r0, [r4, #20] +1003f76a: 7831 ldrb r1, [r6, #0] +1003f76c: f20f 18b8 addw r8, pc, #440 ; 0x1b8 +1003f770: 4d65 ldr r5, [pc, #404] ; (1003f908 ) +1003f772: 2201 movs r2, #1 +1003f774: 408a lsls r2, r1 +1003f776: 4390 bics r0, r2 +1003f778: 7a32 ldrb r2, [r6, #8] +1003f77a: f002 0201 and.w r2, r2, #1 +1003f77e: fa02 f101 lsl.w r1, r2, r1 +1003f782: 4308 orrs r0, r1 +1003f784: 6160 str r0, [r4, #20] +1003f786: 69e0 ldr r0, [r4, #28] +1003f788: 7b71 ldrb r1, [r6, #13] +1003f78a: f020 0002 bic.w r0, r0, #2 +1003f78e: f001 0101 and.w r1, r1, #1 +1003f792: ea40 0041 orr.w r0, r0, r1, lsl #1 +1003f796: 61e0 str r0, [r4, #28] +1003f798: 69e0 ldr r0, [r4, #28] +1003f79a: 7bb1 ldrb r1, [r6, #14] +1003f79c: 0840 lsrs r0, r0, #1 +1003f79e: f001 0101 and.w r1, r1, #1 +1003f7a2: ea41 0040 orr.w r0, r1, r0, lsl #1 +1003f7a6: 61e0 str r0, [r4, #28] +1003f7a8: 69e7 ldr r7, [r4, #28] +1003f7aa: 6828 ldr r0, [r5, #0] +1003f7ac: 0340 lsls r0, r0, #13 +1003f7ae: d503 bpl.n 1003f7b8 +1003f7b0: 4639 mov r1, r7 +1003f7b2: 4640 mov r0, r8 +1003f7b4: f7c4 fc44 bl 10004040 + +1003f7b8 : +1003f7b8: 6a71 ldr r1, [r6, #36] ; 0x24 +1003f7ba: f047 0001 orr.w r0, r7, #1 +1003f7be: 2901 cmp r1, #1 +1003f7c0: bf0c ite eq +1003f7c2: f420 4080 biceq.w r0, r0, #16384 ; 0x4000 +1003f7c6: f440 4080 orrne.w r0, r0, #16384 ; 0x4000 +1003f7ca: e014 b.n 1003f7f6 + +1003f7cc : +1003f7cc: 68e0 ldr r0, [r4, #12] +1003f7ce: 8971 ldrh r1, [r6, #10] +1003f7d0: b280 uxth r0, r0 +1003f7d2: ea40 4001 orr.w r0, r0, r1, lsl #16 +1003f7d6: e7c6 b.n 1003f766 + +1003f7d8 : +1003f7d8: 6920 ldr r0, [r4, #16] +1003f7da: 8971 ldrh r1, [r6, #10] +1003f7dc: 0c00 lsrs r0, r0, #16 +1003f7de: ea41 4000 orr.w r0, r1, r0, lsl #16 + +1003f7e2 : +1003f7e2: 6120 str r0, [r4, #16] +1003f7e4: e7c0 b.n 1003f768 + +1003f7e6 : +1003f7e6: 6920 ldr r0, [r4, #16] +1003f7e8: 8971 ldrh r1, [r6, #10] +1003f7ea: b280 uxth r0, r0 +1003f7ec: ea40 4001 orr.w r0, r0, r1, lsl #16 +1003f7f0: e7f7 b.n 1003f7e2 + +1003f7f2 : +1003f7f2: 2001 movs r0, #1 +1003f7f4: e068 b.n 1003f8c8 + +1003f7f6 : +1003f7f6: f020 000c bic.w r0, r0, #12 +1003f7fa: 61e0 str r0, [r4, #28] +1003f7fc: 69e1 ldr r1, [r4, #28] +1003f7fe: 6828 ldr r0, [r5, #0] +1003f800: 0340 lsls r0, r0, #13 +1003f802: bf44 itt mi +1003f804: 4640 movmi r0, r8 +1003f806: f7c4 fc1b blmi 10004040 +1003f80a: 6a20 ldr r0, [r4, #32] +1003f80c: f20f 1640 addw r6, pc, #320 ; 0x140 +1003f810: f020 0002 bic.w r0, r0, #2 +1003f814: f040 0005 orr.w r0, r0, #5 +1003f818: 6220 str r0, [r4, #32] +1003f81a: 6a21 ldr r1, [r4, #32] +1003f81c: 6828 ldr r0, [r5, #0] +1003f81e: 0340 lsls r0, r0, #13 +1003f820: bf58 it pl +1003f822: 6a60 ldrpl r0, [r4, #36] ; 0x24 +1003f824: d50a bpl.n 1003f83c +1003f826: f20f 1014 addw r0, pc, #276 ; 0x114 +1003f82a: f7c4 fc09 bl 10004040 +1003f82e: 6a61 ldr r1, [r4, #36] ; 0x24 +1003f830: 6828 ldr r0, [r5, #0] +1003f832: 0340 lsls r0, r0, #13 +1003f834: bf44 itt mi +1003f836: 4630 movmi r0, r6 +1003f838: f7c4 fc02 blmi 10004040 + +1003f83c : +1003f83c: 4833 ldr r0, [pc, #204] ; (1003f90c ) +1003f83e: f20f 1724 addw r7, pc, #292 ; 0x124 +1003f842: 6260 str r0, [r4, #36] ; 0x24 +1003f844: 6a61 ldr r1, [r4, #36] ; 0x24 +1003f846: 6828 ldr r0, [r5, #0] +1003f848: 0340 lsls r0, r0, #13 +1003f84a: bf58 it pl +1003f84c: 6aa0 ldrpl r0, [r4, #40] ; 0x28 +1003f84e: d509 bpl.n 1003f864 +1003f850: 4630 mov r0, r6 +1003f852: f7c4 fbf5 bl 10004040 +1003f856: 6aa1 ldr r1, [r4, #40] ; 0x28 +1003f858: 6828 ldr r0, [r5, #0] +1003f85a: 0340 lsls r0, r0, #13 +1003f85c: bf44 itt mi +1003f85e: 4638 movmi r0, r7 +1003f860: f7c4 fbee blmi 10004040 + +1003f864 : +1003f864: 482a ldr r0, [pc, #168] ; (1003f910 ) +1003f866: f20f 1610 addw r6, pc, #272 ; 0x110 +1003f86a: 62a0 str r0, [r4, #40] ; 0x28 +1003f86c: 6aa1 ldr r1, [r4, #40] ; 0x28 +1003f86e: 6828 ldr r0, [r5, #0] +1003f870: 0340 lsls r0, r0, #13 +1003f872: bf58 it pl +1003f874: 6ae0 ldrpl r0, [r4, #44] ; 0x2c +1003f876: d509 bpl.n 1003f88c +1003f878: 4638 mov r0, r7 +1003f87a: f7c4 fbe1 bl 10004040 +1003f87e: 6ae1 ldr r1, [r4, #44] ; 0x2c +1003f880: 6828 ldr r0, [r5, #0] +1003f882: 0340 lsls r0, r0, #13 +1003f884: bf44 itt mi +1003f886: 4630 movmi r0, r6 +1003f888: f7c4 fbda blmi 10004040 + +1003f88c : +1003f88c: 4821 ldr r0, [pc, #132] ; (1003f914 ) +1003f88e: f20f 07fc addw r7, pc, #252 ; 0xfc +1003f892: 62e0 str r0, [r4, #44] ; 0x2c +1003f894: 6ae1 ldr r1, [r4, #44] ; 0x2c +1003f896: 6828 ldr r0, [r5, #0] +1003f898: 0340 lsls r0, r0, #13 +1003f89a: bf58 it pl +1003f89c: 6b20 ldrpl r0, [r4, #48] ; 0x30 +1003f89e: d509 bpl.n 1003f8b4 +1003f8a0: 4630 mov r0, r6 +1003f8a2: f7c4 fbcd bl 10004040 +1003f8a6: 6b21 ldr r1, [r4, #48] ; 0x30 +1003f8a8: 6828 ldr r0, [r5, #0] +1003f8aa: 0340 lsls r0, r0, #13 +1003f8ac: bf44 itt mi +1003f8ae: 4638 movmi r0, r7 +1003f8b0: f7c4 fbc6 blmi 10004040 + +1003f8b4 : +1003f8b4: 4818 ldr r0, [pc, #96] ; (1003f918 ) +1003f8b6: 6320 str r0, [r4, #48] ; 0x30 +1003f8b8: 6b21 ldr r1, [r4, #48] ; 0x30 +1003f8ba: 6828 ldr r0, [r5, #0] +1003f8bc: 0340 lsls r0, r0, #13 +1003f8be: bf44 itt mi +1003f8c0: 4638 movmi r0, r7 +1003f8c2: f7c4 fbbd blmi 10004040 +1003f8c6: 2000 movs r0, #0 + +1003f8c8 : +1003f8c8: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +1003f8cc : +1003f8cc: 4813 ldr r0, [pc, #76] ; (1003f91c ) +1003f8ce: 6801 ldr r1, [r0, #0] +1003f8d0: 0849 lsrs r1, r1, #1 +1003f8d2: 0049 lsls r1, r1, #1 +1003f8d4: 6001 str r1, [r0, #0] +1003f8d6: 2000 movs r0, #0 +1003f8d8: 4770 bx lr + +1003f8da : +1003f8da: 4910 ldr r1, [pc, #64] ; (1003f91c ) +1003f8dc: 680a ldr r2, [r1, #0] +1003f8de: 7840 ldrb r0, [r0, #1] +1003f8e0: 0852 lsrs r2, r2, #1 +1003f8e2: f000 0001 and.w r0, r0, #1 +1003f8e6: ea40 0042 orr.w r0, r0, r2, lsl #1 +1003f8ea: e001 b.n 1003f8f0 + +1003f8ec : +1003f8ec: 69c0 ldr r0, [r0, #28] +1003f8ee: 490c ldr r1, [pc, #48] ; (1003f920 ) + +1003f8f0 : +1003f8f0: 6008 str r0, [r1, #0] +1003f8f2: 2000 movs r0, #0 +1003f8f4: 4770 bx lr + +1003f8f6 : +1003f8f6: 480b ldr r0, [pc, #44] ; (1003f924 ) +1003f8f8: 6800 ldr r0, [r0, #0] +1003f8fa: 4770 bx lr + +1003f8fc : +1003f8fc: 4809 ldr r0, [pc, #36] ; (1003f924 ) +1003f8fe: 5840 ldr r0, [r0, r1] +1003f900: 4770 bx lr + ... + +1003f904 : +1003f904: 0004 4001 ...@ + +1003f908 : +1003f908: 0310 1000 .... + +1003f90c : +1003f90c: 4400 6788 .D.g + +1003f910 : +1003f910: 0039 7778 9.xw + +1003f914 : +1003f914: d501 0004 .... + +1003f918 : +1003f918: 0800 1e01 .... + +1003f91c : +1003f91c: 001c 4001 ...@ + +1003f920 : +1003f920: 0008 4001 ...@ + +1003f924 : +1003f924: 0000 4001 ...@ + +1003f928 : +1003f928: 5b0d 4441 2043 4920 666e 415d 3044 253a .[ADC Inf]AD0:% +1003f938: 0a78 0000 x... + +1003f93c : +1003f93c: 5b0d 4441 2043 4920 666e 415d 3144 253a .[ADC Inf]AD1:% +1003f94c: 0a78 0000 x... + +1003f950 : +1003f950: 5b0d 4441 2043 4920 666e 415d 3244 253a .[ADC Inf]AD2:% +1003f960: 0a78 0000 x... + +1003f964 : +1003f964: 5b0d 4441 2043 4920 666e 415d 3344 253a .[ADC Inf]AD3:% +1003f974: 0a78 0000 x... + +1003f978 : +1003f978: 5b0d 4441 2043 4920 666e 415d 3444 253a .[ADC Inf]AD4:% +1003f988: 0a78 0000 x... + +1003f98c : +1003f98c: 5b0d 4441 2043 4920 666e 415d 3544 253a .[ADC Inf]AD5:% +1003f99c: 0a78 0000 x... + +1003f9a0 : +1003f9a0: b580 push {r7, lr} +1003f9a2: e7ff b.n 1003f9a4 + +1003f9a4 : +1003f9a4: f7d3 ff8c bl 100138c0 +1003f9a8: 4901 ldr r1, [pc, #4] ; (1003f9b0 ) +1003f9aa: 6008 str r0, [r1, #0] +1003f9ac: bd01 pop {r0, pc} + ... + +1003f9b0 : +1003f9b0: 3fd8 1004 .?.. + +1003f9b4 : +1003f9b4: f8df f000 ldr.w pc, [pc] ; 1003f9b8 +1003f9b8: 00003485 .word 0x00003485 + +1003f9bc <__iar_data_init_app>: +1003f9bc: 4844 ldr r0, [pc, #272] ; (1003fad0 <.text_63>) +1003f9be: 4945 ldr r1, [pc, #276] ; (1003fad4 <.text_64>) +1003f9c0: 6001 str r1, [r0, #0] +1003f9c2: 4945 ldr r1, [pc, #276] ; (1003fad8 <.text_65>) +1003f9c4: 6041 str r1, [r0, #4] +1003f9c6: 4770 bx lr + +1003f9c8 : +1003f9c8: 4944 ldr r1, [pc, #272] ; (1003fadc <.text_66>) +1003f9ca: f04f 30ff mov.w r0, #4294967295 +1003f9ce: 6008 str r0, [r1, #0] +1003f9d0: 2000 movs r0, #0 +1003f9d2: 4943 ldr r1, [pc, #268] ; (1003fae0 <.text_67>) +1003f9d4: 6008 str r0, [r1, #0] +1003f9d6: 4943 ldr r1, [pc, #268] ; (1003fae4 <.text_68>) +1003f9d8: 6008 str r0, [r1, #0] +1003f9da: 4770 bx lr + +1003f9dc : +1003f9dc: b51f push {r0, r1, r2, r3, r4, lr} +1003f9de: 4c42 ldr r4, [pc, #264] ; (1003fae8 <.text_69>) +1003f9e0: 2000 movs r0, #0 +1003f9e2: 6060 str r0, [r4, #4] +1003f9e4: 2080 movs r0, #128 ; 0x80 +1003f9e6: 60e0 str r0, [r4, #12] +1003f9e8: f7d3 ff6a bl 100138c0 +1003f9ec: 0880 lsrs r0, r0, #2 +1003f9ee: 9900 ldr r1, [sp, #0] +1003f9f0: 0109 lsls r1, r1, #4 +1003f9f2: fbb0 f2f1 udiv r2, r0, r1 +1003f9f6: 230a movs r3, #10 +1003f9f8: 4358 muls r0, r3 +1003f9fa: fbb0 f0f1 udiv r0, r0, r1 +1003f9fe: fb03 0012 mls r0, r3, r2, r0 +1003fa02: 2805 cmp r0, #5 +1003fa04: bf28 it cs +1003fa06: 1c52 addcs r2, r2, #1 +1003fa08: b2d0 uxtb r0, r2 +1003fa0a: 6020 str r0, [r4, #0] +1003fa0c: f3c2 2007 ubfx r0, r2, #8, #8 +1003fa10: 6060 str r0, [r4, #4] +1003fa12: 2000 movs r0, #0 +1003fa14: 60e0 str r0, [r4, #12] +1003fa16: f89d 100d ldrb.w r1, [sp, #13] +1003fa1a: f89d 000c ldrb.w r0, [sp, #12] +1003fa1e: 4308 orrs r0, r1 +1003fa20: f89d 100e ldrb.w r1, [sp, #14] +1003fa24: 4308 orrs r0, r1 +1003fa26: 60e0 str r0, [r4, #12] +1003fa28: 9801 ldr r0, [sp, #4] +1003fa2a: 60a0 str r0, [r4, #8] +1003fa2c: 9802 ldr r0, [sp, #8] +1003fa2e: 6060 str r0, [r4, #4] +1003fa30: b190 cbz r0, 1003fa58 +1003fa32: 492e ldr r1, [pc, #184] ; (1003faec <.text_70>) +1003fa34: f04f 7080 mov.w r0, #16777216 ; 0x1000000 +1003fa38: 6008 str r0, [r1, #0] +1003fa3a: f64f 02ff movw r2, #63743 ; 0xf8ff +1003fa3e: 482c ldr r0, [pc, #176] ; (1003faf0 <.text_71>) +1003fa40: 6801 ldr r1, [r0, #0] +1003fa42: 4011 ands r1, r2 +1003fa44: 4a2b ldr r2, [pc, #172] ; (1003faf4 <.text_72>) +1003fa46: 4311 orrs r1, r2 +1003fa48: 6001 str r1, [r0, #0] +1003fa4a: 20e0 movs r0, #224 ; 0xe0 +1003fa4c: 492a ldr r1, [pc, #168] ; (1003faf8 <.text_73>) +1003fa4e: 7008 strb r0, [r1, #0] +1003fa50: f44f 2000 mov.w r0, #524288 ; 0x80000 +1003fa54: 4929 ldr r1, [pc, #164] ; (1003fafc <.text_74>) +1003fa56: 6008 str r0, [r1, #0] +1003fa58: 2000 movs r0, #0 +1003fa5a: b004 add sp, #16 +1003fa5c: bd10 pop {r4, pc} + +1003fa5e : +1003fa5e: 4822 ldr r0, [pc, #136] ; (1003fae8 <.text_69>) +1003fa60: b084 sub sp, #16 +1003fa62: 6800 ldr r0, [r0, #0] +1003fa64: 4826 ldr r0, [pc, #152] ; (1003fb00 <.text_75>) +1003fa66: 6801 ldr r1, [r0, #0] +1003fa68: f421 5180 bic.w r1, r1, #4096 ; 0x1000 +1003fa6c: 6001 str r1, [r0, #0] +1003fa6e: 6801 ldr r1, [r0, #0] +1003fa70: f441 5180 orr.w r1, r1, #4096 ; 0x1000 +1003fa74: 6001 str r1, [r0, #0] +1003fa76: 6a01 ldr r1, [r0, #32] +1003fa78: f441 5180 orr.w r1, r1, #4096 ; 0x1000 +1003fa7c: 6201 str r1, [r0, #32] +1003fa7e: f44f 4016 mov.w r0, #38400 ; 0x9600 +1003fa82: 9000 str r0, [sp, #0] +1003fa84: 2003 movs r0, #3 +1003fa86: f88d 000e strb.w r0, [sp, #14] +1003fa8a: 20c1 movs r0, #193 ; 0xc1 +1003fa8c: 9001 str r0, [sp, #4] +1003fa8e: 2005 movs r0, #5 +1003fa90: 9002 str r0, [sp, #8] +1003fa92: 2000 movs r0, #0 +1003fa94: f8ad 000c strh.w r0, [sp, #12] +1003fa98: a800 add r0, sp, #0 +1003fa9a: c80f ldmia r0, {r0, r1, r2, r3} +1003fa9c: b004 add sp, #16 +1003fa9e: e79d b.n 1003f9dc + +1003faa0 : +1003faa0: b580 push {r7, lr} +1003faa2: 480e ldr r0, [pc, #56] ; (1003fadc <.text_66>) +1003faa4: 4917 ldr r1, [pc, #92] ; (1003fb04 <.text_76>) +1003faa6: 6800 ldr r0, [r0, #0] +1003faa8: 4208 tst r0, r1 +1003faaa: d005 beq.n 1003fab8 +1003faac: f20f 015c addw r1, pc, #92 ; 0x5c +1003fab0: f20f 006c addw r0, pc, #108 ; 0x6c +1003fab4: f7c4 fac4 bl 10004040 +1003fab8: 4813 ldr r0, [pc, #76] ; (1003fb08 <.text_77>) +1003faba: 6800 ldr r0, [r0, #0] +1003fabc: 9000 str r0, [sp, #0] +1003fabe: f89d 0003 ldrb.w r0, [sp, #3] +1003fac2: 09c0 lsrs r0, r0, #7 +1003fac4: bf1c itt ne +1003fac6: e8bd 4001 ldmiane.w sp!, {r0, lr} +1003faca: f7ff bf73 bne.w 1003f9b4 +1003face: bd01 pop {r0, pc} + +1003fad0 <.text_63>: +1003fad0: 10048170 .word 0x10048170 + +1003fad4 <.text_64>: +1003fad4: 10046ea8 .word 0x10046ea8 + +1003fad8 <.text_65>: +1003fad8: 1004dab8 .word 0x1004dab8 + +1003fadc <.text_66>: +1003fadc: 10000314 .word 0x10000314 + +1003fae0 <.text_67>: +1003fae0: 1000030c .word 0x1000030c + +1003fae4 <.text_68>: +1003fae4: 10000310 .word 0x10000310 + +1003fae8 <.text_69>: +1003fae8: 40003000 .word 0x40003000 + +1003faec <.text_70>: +1003faec: 4000280c .word 0x4000280c + +1003faf0 <.text_71>: +1003faf0: e000ed0c .word 0xe000ed0c + +1003faf4 <.text_72>: +1003faf4: 05fa0300 .word 0x05fa0300 + +1003faf8 <.text_73>: +1003faf8: e000e413 .word 0xe000e413 + +1003fafc <.text_74>: +1003fafc: e000e100 .word 0xe000e100 + +1003fb00 <.text_75>: +1003fb00: 40000210 .word 0x40000210 + +1003fb04 <.text_76>: +1003fb04: 40002000 .word 0x40002000 + +1003fb08 <.text_77>: +1003fb08: 40002800 .word 0x40002800 + +1003fb0c : +1003fb0c: 4e6c6148 6148494d 656c646e 61505f72 HalNMIHandler_Pa +1003fb1c: 00686374 tch. + +1003fb20 : +1003fb20: 4c54520d 35393138 41485b41 203a5d4c .RTL8195A[HAL]: +1003fb30: 4e3a7325 4520494d 726f7272 21212121 %s:NMI Error!!!! +1003fb40: 0000000a .... + +1003fb44 : +1003fb44: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1003fb48: 4604 mov r4, r0 +1003fb4a: f20f 0060 addw r0, pc, #96 ; 0x60 +1003fb4e: f7d1 f81f bl 10010b90 +1003fb52: 4e15 ldr r6, [pc, #84] ; (1003fba8 <.text_4>) +1003fb54: f504 55e0 add.w r5, r4, #7168 ; 0x1c00 +1003fb58: 35bc adds r5, #188 ; 0xbc +1003fb5a: f105 0008 add.w r0, r5, #8 +1003fb5e: f641 489c movw r8, #7324 ; 0x1c9c +1003fb62: 6030 str r0, [r6, #0] +1003fb64: eb08 0704 add.w r7, r8, r4 +1003fb68: e002 b.n 1003fb70 +1003fb6a: 4620 mov r0, r4 +1003fb6c: f7d7 fccb bl 10017506 +1003fb70: f105 0008 add.w r0, r5, #8 +1003fb74: f7d0 fe9a bl 100108ac +1003fb78: 7b38 ldrb r0, [r7, #12] +1003fb7a: b940 cbnz r0, 1003fb8e +1003fb7c: 6928 ldr r0, [r5, #16] +1003fb7e: b930 cbnz r0, 1003fb8e +1003fb80: f858 0004 ldr.w r0, [r8, r4] +1003fb84: 2801 cmp r0, #1 +1003fb86: d002 beq.n 1003fb8e +1003fb88: 6878 ldr r0, [r7, #4] +1003fb8a: 2801 cmp r0, #1 +1003fb8c: d1ed bne.n 1003fb6a +1003fb8e: 2002 movs r0, #2 +1003fb90: 7338 strb r0, [r7, #12] +1003fb92: f105 000c add.w r0, r5, #12 +1003fb96: f7d0 fe7a bl 1001088e +1003fb9a: 2000 movs r0, #0 +1003fb9c: 6030 str r0, [r6, #0] +1003fb9e: e8bd 41f0 ldmia.w sp!, {r4, r5, r6, r7, r8, lr} +1003fba2: f7d0 bffc b.w 10010b9e + ... + +1003fba8 <.text_4>: +1003fba8: 10048828 .word 0x10048828 + +1003fbac : +1003fbac: 5f575452 45544e49 50555252 48545f54 RTW_INTERRUPT_TH +1003fbbc: 44414552 00000000 READ.... + +1003fbc4 : +1003fbc4: b580 push {r7, lr} +1003fbc6: f000 fc62 bl 1004048e +1003fbca: f8df 04fc ldr.w r0, [pc, #1276] ; 100400c8 <.text_30> +1003fbce: 68c0 ldr r0, [r0, #12] +1003fbd0: e8bd 4002 ldmia.w sp!, {r1, lr} + +1003fbd4 <__iar_annotation$$tailcall>: +1003fbd4: 4700 bx r0 + +1003fbd6 : +1003fbd6: 2101 movs r1, #1 +1003fbd8: 2802 cmp r0, #2 +1003fbda: d003 beq.n 1003fbe4 +1003fbdc: 2803 cmp r0, #3 +1003fbde: bf08 it eq +1003fbe0: 2120 moveq r1, #32 +1003fbe2: e000 b.n 1003fbe6 +1003fbe4: 2102 movs r1, #2 +1003fbe6: 4608 mov r0, r1 +1003fbe8: 4770 bx lr + +1003fbea : +1003fbea: 2100 movs r1, #0 +1003fbec: b130 cbz r0, 1003fbfc +1003fbee: 2802 cmp r0, #2 +1003fbf0: d008 beq.n 1003fc04 +1003fbf2: d305 bcc.n 1003fc00 +1003fbf4: 2803 cmp r0, #3 +1003fbf6: bf08 it eq +1003fbf8: 2108 moveq r1, #8 +1003fbfa: e004 b.n 1003fc06 +1003fbfc: 2101 movs r1, #1 +1003fbfe: e002 b.n 1003fc06 +1003fc00: 2102 movs r1, #2 +1003fc02: e000 b.n 1003fc06 +1003fc04: 2104 movs r1, #4 +1003fc06: 4608 mov r0, r1 +1003fc08: 4770 bx lr + +1003fc0a : +1003fc0a: b5f0 push {r4, r5, r6, r7, lr} +1003fc0c: f8df 44bc ldr.w r4, [pc, #1212] ; 100400cc <.text_31> +1003fc10: 4606 mov r6, r0 +1003fc12: 68e0 ldr r0, [r4, #12] +1003fc14: 2800 cmp r0, #0 +1003fc16: b085 sub sp, #20 +1003fc18: d15c bne.n 1003fcd4 +1003fc1a: f44f 7094 mov.w r0, #296 ; 0x128 +1003fc1e: f7fd fb25 bl 1003d26c +1003fc22: 0005 movs r5, r0 +1003fc24: bf08 it eq +1003fc26: f04f 30ff moveq.w r0, #4294967295 +1003fc2a: d054 beq.n 1003fcd6 +1003fc2c: 2002 movs r0, #2 +1003fc2e: 60a8 str r0, [r5, #8] +1003fc30: f105 0008 add.w r0, r5, #8 +1003fc34: f20f 41cc addw r1, pc, #1228 ; 0x4cc +1003fc38: 6441 str r1, [r0, #68] ; 0x44 +1003fc3a: f105 0790 add.w r7, r5, #144 ; 0x90 +1003fc3e: f20f 41d0 addw r1, pc, #1232 ; 0x4d0 +1003fc42: 6481 str r1, [r0, #72] ; 0x48 +1003fc44: 2208 movs r2, #8 +1003fc46: f20f 41d4 addw r1, pc, #1236 ; 0x4d4 +1003fc4a: 64c1 str r1, [r0, #76] ; 0x4c +1003fc4c: f20f 41d4 addw r1, pc, #1236 ; 0x4d4 +1003fc50: 6501 str r1, [r0, #80] ; 0x50 +1003fc52: a1ab add r1, pc, #684 ; (adr r1, 1003ff00 <.text_23>) +1003fc54: 6541 str r1, [r0, #84] ; 0x54 +1003fc56: 2084 movs r0, #132 ; 0x84 +1003fc58: f8a5 00d8 strh.w r0, [r5, #216] ; 0xd8 +1003fc5c: f8a5 00d8 strh.w r0, [r5, #216] ; 0xd8 +1003fc60: 8178 strh r0, [r7, #10] +1003fc62: f105 0060 add.w r0, r5, #96 ; 0x60 +1003fc66: f20f 41ec addw r1, pc, #1260 ; 0x4ec +1003fc6a: f7d0 fdd0 bl 1001080e +1003fc6e: 2000 movs r0, #0 +1003fc70: f885 0090 strb.w r0, [r5, #144] ; 0x90 +1003fc74: 2228 movs r2, #40 ; 0x28 +1003fc76: 2100 movs r1, #0 +1003fc78: f105 0068 add.w r0, r5, #104 ; 0x68 +1003fc7c: f7d0 fddc bl 10010838 +1003fc80: f8df 044c ldr.w r0, [pc, #1100] ; 100400d0 <.text_32> +1003fc84: 6078 str r0, [r7, #4] +1003fc86: 2206 movs r2, #6 +1003fc88: 2001 movs r0, #1 +1003fc8a: 7238 strb r0, [r7, #8] +1003fc8c: 4631 mov r1, r6 +1003fc8e: f105 0044 add.w r0, r5, #68 ; 0x44 +1003fc92: f7d0 fdbc bl 1001080e +1003fc96: f105 0610 add.w r6, r5, #16 +1003fc9a: a800 add r0, sp, #0 +1003fc9c: 2110 movs r1, #16 +1003fc9e: f7e5 fdbd bl 1002581c <__aeabi_memclr4> +1003fca2: 2206 movs r2, #6 +1003fca4: f105 0144 add.w r1, r5, #68 ; 0x44 +1003fca8: f10d 000a add.w r0, sp, #10 +1003fcac: f7d0 fdaf bl 1001080e +1003fcb0: 2210 movs r2, #16 +1003fcb2: a900 add r1, sp, #0 +1003fcb4: 4630 mov r0, r6 +1003fcb6: f7d0 fdaa bl 1001080e +1003fcba: 7a30 ldrb r0, [r6, #8] +1003fcbc: f000 003f and.w r0, r0, #63 ; 0x3f +1003fcc0: f040 0080 orr.w r0, r0, #128 ; 0x80 +1003fcc4: 7230 strb r0, [r6, #8] +1003fcc6: 2120 movs r1, #32 +1003fcc8: f105 00d8 add.w r0, r5, #216 ; 0xd8 +1003fccc: 8081 strh r1, [r0, #4] +1003fcce: 2108 movs r1, #8 +1003fcd0: 8041 strh r1, [r0, #2] +1003fcd2: 60e5 str r5, [r4, #12] +1003fcd4: 2000 movs r0, #0 +1003fcd6: b005 add sp, #20 +1003fcd8: bdf0 pop {r4, r5, r6, r7, pc} + +1003fcda : +1003fcda: b530 push {r4, r5, lr} +1003fcdc: b091 sub sp, #68 ; 0x44 +1003fcde: 4604 mov r4, r0 +1003fce0: 2000 movs r0, #0 +1003fce2: f8ad 0000 strh.w r0, [sp] +1003fce6: f8df 03e4 ldr.w r0, [pc, #996] ; 100400cc <.text_31> +1003fcea: 68c5 ldr r5, [r0, #12] +1003fcec: b13d cbz r5, 1003fcfe +1003fcee: 2300 movs r3, #0 +1003fcf0: 2200 movs r2, #0 +1003fcf2: a900 add r1, sp, #0 +1003fcf4: 4620 mov r0, r4 +1003fcf6: f7e2 fb94 bl 10022422 +1003fcfa: 2800 cmp r0, #0 +1003fcfc: d502 bpl.n 1003fd04 +1003fcfe: f04f 30ff mov.w r0, #4294967295 +1003fd02: e027 b.n 1003fd54 +1003fd04: f8bd 0000 ldrh.w r0, [sp] +1003fd08: f7ff ff65 bl 1003fbd6 +1003fd0c: f8a5 00dc strh.w r0, [r5, #220] ; 0xdc +1003fd10: f8bd 0000 ldrh.w r0, [sp] +1003fd14: f7ff ff69 bl 1003fbea +1003fd18: f8a5 00da strh.w r0, [r5, #218] ; 0xda +1003fd1c: f105 0120 add.w r1, r5, #32 +1003fd20: 4620 mov r0, r4 +1003fd22: f7e2 fa6f bl 10022204 +1003fd26: 6428 str r0, [r5, #64] ; 0x40 +1003fd28: a901 add r1, sp, #4 +1003fd2a: 4620 mov r0, r4 +1003fd2c: f7e2 fc0c bl 10022548 +1003fd30: 9801 ldr r0, [sp, #4] +1003fd32: 2803 cmp r0, #3 +1003fd34: d108 bne.n 1003fd48 +1003fd36: 2208 movs r2, #8 +1003fd38: f20f 4110 addw r1, pc, #1040 ; 0x410 +1003fd3c: f105 0060 add.w r0, r5, #96 ; 0x60 +1003fd40: f7d0 fd65 bl 1001080e +1003fd44: 2001 movs r0, #1 +1003fd46: 6028 str r0, [r5, #0] +1003fd48: 2238 movs r2, #56 ; 0x38 +1003fd4a: 2100 movs r1, #0 +1003fd4c: a802 add r0, sp, #8 +1003fd4e: f7d0 fd73 bl 10010838 +1003fd52: 2000 movs r0, #0 +1003fd54: b011 add sp, #68 ; 0x44 +1003fd56: bd30 pop {r4, r5, pc} + +1003fd58 : +1003fd58: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +1003fd5c: 4604 mov r4, r0 +1003fd5e: 460d mov r5, r1 +1003fd60: 4690 mov r8, r2 +1003fd62: 461e mov r6, r3 +1003fd64: f000 f86f bl 1003fe46 <.text_16> +1003fd68: ea5f 0900 movs.w r9, r0 +1003fd6c: d025 beq.n 1003fdba +1003fd6e: f8d9 7010 ldr.w r7, [r9, #16] +1003fd72: f000 f874 bl 1003fe5e <.text_18> +1003fd76: f000 f86b bl 1003fe50 <.text_17> +1003fd7a: f648 008e movw r0, #34958 ; 0x888e +1003fd7e: f7d0 fccf bl 10010720 <_htons> +1003fd82: f000 f858 bl 1003fe36 <.text_15> +1003fd86: fa1f f088 uxth.w r0, r8 +1003fd8a: f7d0 fcc9 bl 10010720 <_htons> +1003fd8e: 8070 strh r0, [r6, #2] +1003fd90: 686a ldr r2, [r5, #4] +1003fd92: 68a9 ldr r1, [r5, #8] +1003fd94: 1d30 adds r0, r6, #4 +1003fd96: f7d0 fd3a bl 1001080e +1003fd9a: f108 0112 add.w r1, r8, #18 +1003fd9e: 4648 mov r0, r9 +1003fda0: f7d1 fb28 bl 100113f4 +1003fda4: f242 306c movw r0, #9068 ; 0x236c +1003fda8: 5901 ldr r1, [r0, r4] +1003fdaa: 6a8a ldr r2, [r1, #40] ; 0x28 +1003fdac: 4648 mov r0, r9 +1003fdae: 4790 blx r2 +1003fdb0: 4628 mov r0, r5 +1003fdb2: e8bd 43f2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, lr} +1003fdb6: f7fd bd72 b.w 1003d89e +1003fdba: e8bd 83f1 ldmia.w sp!, {r0, r4, r5, r6, r7, r8, r9, pc} + +1003fdbe : +1003fdbe: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +1003fdc2: 000e movs r6, r1 +1003fdc4: 4604 mov r4, r0 +1003fdc6: 4690 mov r8, r2 +1003fdc8: d033 beq.n 1003fe32 +1003fdca: f000 f83c bl 1003fe46 <.text_16> +1003fdce: 0005 movs r5, r0 +1003fdd0: d02f beq.n 1003fe32 +1003fdd2: 692f ldr r7, [r5, #16] +1003fdd4: f000 f843 bl 1003fe5e <.text_18> +1003fdd8: f000 f83a bl 1003fe50 <.text_17> +1003fddc: f648 008e movw r0, #34958 ; 0x888e +1003fde0: f7d0 fc9e bl 10010720 <_htons> +1003fde4: f000 f827 bl 1003fe36 <.text_15> +1003fde8: 2022 movs r0, #34 ; 0x22 +1003fdea: f7d0 fc99 bl 10010720 <_htons> +1003fdee: 8070 strh r0, [r6, #2] +1003fdf0: 2102 movs r1, #2 +1003fdf2: f8d8 0010 ldr.w r0, [r8, #16] +1003fdf6: f806 1f04 strb.w r1, [r6, #4]! +1003fdfa: 3012 adds r0, #18 +1003fdfc: 7840 ldrb r0, [r0, #1] +1003fdfe: 7070 strb r0, [r6, #1] +1003fe00: 2022 movs r0, #34 ; 0x22 +1003fe02: f7d0 fc8d bl 10010720 <_htons> +1003fe06: 8070 strh r0, [r6, #2] +1003fe08: 221d movs r2, #29 +1003fe0a: 2001 movs r0, #1 +1003fe0c: 7130 strb r0, [r6, #4] +1003fe0e: 1d70 adds r0, r6, #5 +1003fe10: f20f 3118 addw r1, pc, #792 ; 0x318 +1003fe14: f7d0 fcfb bl 1001080e +1003fe18: 2134 movs r1, #52 ; 0x34 +1003fe1a: 4628 mov r0, r5 +1003fe1c: f7d1 faea bl 100113f4 +1003fe20: f242 306c movw r0, #9068 ; 0x236c +1003fe24: 5901 ldr r1, [r0, r4] +1003fe26: 6a8a ldr r2, [r1, #40] ; 0x28 +1003fe28: 4628 mov r0, r5 +1003fe2a: 4790 blx r2 +1003fe2c: 48a7 ldr r0, [pc, #668] ; (100400cc <.text_31>) +1003fe2e: 2100 movs r1, #0 +1003fe30: 8001 strh r1, [r0, #0] +1003fe32: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} + +1003fe36 <.text_15>: +1003fe36: 81b8 strh r0, [r7, #12] +1003fe38: f107 060e add.w r6, r7, #14 +1003fe3c: 2001 movs r0, #1 +1003fe3e: 7030 strb r0, [r6, #0] +1003fe40: 2000 movs r0, #0 +1003fe42: 7070 strb r0, [r6, #1] +1003fe44: 4770 bx lr + +1003fe46 <.text_16>: +1003fe46: 214a movs r1, #74 ; 0x4a +1003fe48: f44f 7000 mov.w r0, #512 ; 0x200 +1003fe4c: f7d1 baa6 b.w 1001139c + +1003fe50 <.text_17>: +1003fe50: f504 51c8 add.w r1, r4, #6400 ; 0x1900 +1003fe54: 2206 movs r2, #6 +1003fe56: 3195 adds r1, #149 ; 0x95 +1003fe58: 1db8 adds r0, r7, #6 +1003fe5a: f7d0 bcd8 b.w 1001080e + +1003fe5e <.text_18>: +1003fe5e: 2206 movs r2, #6 +1003fe60: f506 7184 add.w r1, r6, #264 ; 0x108 +1003fe64: 4638 mov r0, r7 +1003fe66: f7d0 bcd2 b.w 1001080e + +1003fe6a : +1003fe6a: b538 push {r3, r4, r5, lr} +1003fe6c: 4604 mov r4, r0 +1003fe6e: 460d mov r5, r1 +1003fe70: f000 f848 bl 1003ff04 <.text_24> +1003fe74: 4a94 ldr r2, [pc, #592] ; (100400c8 <.text_30>) +1003fe76: 6952 ldr r2, [r2, #20] +1003fe78: 4629 mov r1, r5 +1003fe7a: 4620 mov r0, r4 +1003fe7c: 4790 blx r2 +1003fe7e: bd32 pop {r1, r4, r5, pc} + +1003fe80 : +1003fe80: b510 push {r4, lr} +1003fe82: 4c92 ldr r4, [pc, #584] ; (100400cc <.text_31>) +1003fe84: 68a0 ldr r0, [r4, #8] +1003fe86: 6a00 ldr r0, [r0, #32] +1003fe88: f500 71ae add.w r1, r0, #348 ; 0x15c +1003fe8c: 4891 ldr r0, [pc, #580] ; (100400d4 <.text_34>) +1003fe8e: 6800 ldr r0, [r0, #0] +1003fe90: 2200 movs r2, #0 +1003fe92: f7fd fa19 bl 1003d2c8 +1003fe96: 7860 ldrb r0, [r4, #1] +1003fe98: 2801 cmp r0, #1 +1003fe9a: d10a bne.n 1003feb2 +1003fe9c: 498a ldr r1, [pc, #552] ; (100400c8 <.text_30>) +1003fe9e: 68a0 ldr r0, [r4, #8] +1003fea0: 6909 ldr r1, [r1, #16] +1003fea2: 4788 blx r1 +1003fea4: 7820 ldrb r0, [r4, #0] +1003fea6: 2801 cmp r0, #1 +1003fea8: bf04 itt eq +1003feaa: 2000 moveq r0, #0 +1003feac: 7020 strbeq r0, [r4, #0] +1003feae: 2000 movs r0, #0 +1003feb0: 7060 strb r0, [r4, #1] +1003feb2: bd10 pop {r4, pc} + +1003feb4 : +1003feb4: e7e4 b.n 1003fe80 + +1003feb6 : +1003feb6: b51c push {r2, r3, r4, lr} +1003feb8: 4604 mov r4, r0 +1003feba: 2000 movs r0, #0 +1003febc: 9001 str r0, [sp, #4] +1003febe: 4883 ldr r0, [pc, #524] ; (100400cc <.text_31>) +1003fec0: 7841 ldrb r1, [r0, #1] +1003fec2: b951 cbnz r1, 1003feda +1003fec4: 6880 ldr r0, [r0, #8] +1003fec6: 6a00 ldr r0, [r0, #32] +1003fec8: 2220 movs r2, #32 +1003feca: f500 70ae add.w r0, r0, #348 ; 0x15c +1003fece: f7d0 fcb3 bl 10010838 +1003fed2: f44f 707a mov.w r0, #1000 ; 0x3e8 +1003fed6: f7d0 fd8a bl 100109ee +1003feda: f000 f813 bl 1003ff04 <.text_24> +1003fede: 9800 ldr r0, [sp, #0] +1003fee0: 2802 cmp r0, #2 +1003fee2: d10b bne.n 1003fefc +1003fee4: 4620 mov r0, r4 +1003fee6: f7d6 fc93 bl 10016810 +1003feea: 4620 mov r0, r4 +1003feec: f7de ff96 bl 1001ee1c +1003fef0: 2101 movs r1, #1 +1003fef2: 4620 mov r0, r4 +1003fef4: f7de ff13 bl 1001ed1e +1003fef8: f7ff ffc2 bl 1003fe80 +1003fefc: bd13 pop {r0, r1, r4, pc} + ... + +1003ff00 <.text_23>: +1003ff00: 00000038 .word 0x00000038 + +1003ff04 <.text_24>: +1003ff04: a900 add r1, sp, #0 +1003ff06: f20f 10f4 addw r0, pc, #500 ; 0x1f4 +1003ff0a: f7e2 bb1d b.w 10022548 + +1003ff0e : +1003ff0e: e92d 41ff stmdb sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, lr} +1003ff12: 4604 mov r4, r0 +1003ff14: 4688 mov r8, r1 +1003ff16: 4615 mov r5, r2 +1003ff18: 2210 movs r2, #16 +1003ff1a: 2100 movs r1, #0 +1003ff1c: a800 add r0, sp, #0 +1003ff1e: f7d0 fc8b bl 10010838 +1003ff22: f1b8 0f00 cmp.w r8, #0 +1003ff26: d042 beq.n 1003ffae +1003ff28: 9f0a ldr r7, [sp, #40] ; 0x28 +1003ff2a: 4e68 ldr r6, [pc, #416] ; (100400cc <.text_31>) +1003ff2c: b165 cbz r5, 1003ff48 +1003ff2e: 2d05 cmp r5, #5 +1003ff30: d027 beq.n 1003ff82 +1003ff32: 2d06 cmp r5, #6 +1003ff34: d044 beq.n 1003ffc0 +1003ff36: 2d08 cmp r5, #8 +1003ff38: d028 beq.n 1003ff8c +1003ff3a: 2d0a cmp r5, #10 +1003ff3c: d039 beq.n 1003ffb2 +1003ff3e: 2d0c cmp r5, #12 +1003ff40: d03e beq.n 1003ffc0 +1003ff42: 2d0e cmp r5, #14 +1003ff44: d041 beq.n 1003ffca +1003ff46: e032 b.n 1003ffae +1003ff48: 68f0 ldr r0, [r6, #12] +1003ff4a: b930 cbnz r0, 1003ff5a +1003ff4c: f242 306c movw r0, #9068 ; 0x236c +1003ff50: 2100 movs r1, #0 +1003ff52: 5900 ldr r0, [r0, r4] +1003ff54: 3014 adds r0, #20 +1003ff56: f7ff fe58 bl 1003fc0a +1003ff5a: f20f 10a0 addw r0, pc, #416 ; 0x1a0 +1003ff5e: f7ff febc bl 1003fcda +1003ff62: f7ff fe2f bl 1003fbc4 +1003ff66: 60b0 str r0, [r6, #8] +1003ff68: 6a02 ldr r2, [r0, #32] +1003ff6a: 68f1 ldr r1, [r6, #12] +1003ff6c: 6011 str r1, [r2, #0] +1003ff6e: f000 f839 bl 1003ffe4 <.text_27+0x2> +1003ff72: 0001 movs r1, r0 +1003ff74: d121 bne.n 1003ffba +1003ff76: 7870 ldrb r0, [r6, #1] +1003ff78: 2801 cmp r0, #1 +1003ff7a: d118 bne.n 1003ffae +1003ff7c: 2000 movs r0, #0 +1003ff7e: 7070 strb r0, [r6, #1] +1003ff80: e015 b.n 1003ffae +1003ff82: f000 f82e bl 1003ffe2 <.text_27> +1003ff86: 0001 movs r1, r0 +1003ff88: d117 bne.n 1003ffba +1003ff8a: e010 b.n 1003ffae +1003ff8c: f000 f829 bl 1003ffe2 <.text_27> +1003ff90: 0001 movs r1, r0 +1003ff92: d00c beq.n 1003ffae +1003ff94: f000 f821 bl 1003ffda <.text_26> +1003ff98: 68b0 ldr r0, [r6, #8] +1003ff9a: 6a00 ldr r0, [r0, #32] +1003ff9c: 68c0 ldr r0, [r0, #12] +1003ff9e: 280c cmp r0, #12 +1003ffa0: d105 bne.n 1003ffae +1003ffa2: 2001 movs r0, #1 +1003ffa4: 7030 strb r0, [r6, #0] +1003ffa6: 4641 mov r1, r8 +1003ffa8: 4620 mov r0, r4 +1003ffaa: f7ff ff84 bl 1003feb6 +1003ffae: e8bd 81ff ldmia.w sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, pc} +1003ffb2: f000 f816 bl 1003ffe2 <.text_27> +1003ffb6: 0001 movs r1, r0 +1003ffb8: d0f9 beq.n 1003ffae +1003ffba: f000 f80e bl 1003ffda <.text_26> +1003ffbe: e7f6 b.n 1003ffae +1003ffc0: f000 f80f bl 1003ffe2 <.text_27> +1003ffc4: 0001 movs r1, r0 +1003ffc6: d103 bne.n 1003ffd0 +1003ffc8: e7f1 b.n 1003ffae +1003ffca: f000 f80a bl 1003ffe2 <.text_27> +1003ffce: 4601 mov r1, r0 +1003ffd0: f000 f803 bl 1003ffda <.text_26> +1003ffd4: 2001 movs r0, #1 +1003ffd6: 7030 strb r0, [r6, #0] +1003ffd8: e7e9 b.n 1003ffae + +1003ffda <.text_26>: +1003ffda: 684a ldr r2, [r1, #4] +1003ffdc: 4643 mov r3, r8 +1003ffde: 4620 mov r0, r4 +1003ffe0: e6ba b.n 1003fd58 + +1003ffe2 <.text_27>: +1003ffe2: 68b0 ldr r0, [r6, #8] +1003ffe4: 9702 str r7, [sp, #8] +1003ffe6: a900 add r1, sp, #0 +1003ffe8: e73f b.n 1003fe6a + +1003ffea : +1003ffea: b5f0 push {r4, r5, r6, r7, lr} +1003ffec: b083 sub sp, #12 +1003ffee: 4604 mov r4, r0 +1003fff0: 460d mov r5, r1 +1003fff2: 4616 mov r6, r2 +1003fff4: 461f mov r7, r3 +1003fff6: a901 add r1, sp, #4 +1003fff8: f20f 1000 addw r0, pc, #256 ; 0x100 +1003fffc: f7e2 faa4 bl 10022548 +10040000: 9801 ldr r0, [sp, #4] +10040002: 2802 cmp r0, #2 +10040004: d108 bne.n 10040018 +10040006: 7838 ldrb r0, [r7, #0] +10040008: 2801 cmp r0, #1 +1004000a: d129 bne.n 10040060 +1004000c: 7b78 ldrb r0, [r7, #13] +1004000e: 0780 lsls r0, r0, #30 +10040010: bf4c ite mi +10040012: 2016 movmi r0, #22 +10040014: 2017 movpl r0, #23 +10040016: e005 b.n 10040024 +10040018: 2803 cmp r0, #3 +1004001a: d121 bne.n 10040060 +1004001c: 7838 ldrb r0, [r7, #0] +1004001e: 2802 cmp r0, #2 +10040020: d0f4 beq.n 1004000c +10040022: bdf7 pop {r0, r1, r2, r4, r5, r6, r7, pc} +10040024: 7b39 ldrb r1, [r7, #12] +10040026: 5dc2 ldrb r2, [r0, r7] +10040028: 4828 ldr r0, [pc, #160] ; (100400cc <.text_31>) +1004002a: 2901 cmp r1, #1 +1004002c: d006 beq.n 1004003c +1004002e: d317 bcc.n 10040060 +10040030: 2903 cmp r1, #3 +10040032: d00f beq.n 10040054 +10040034: d30e bcc.n 10040054 +10040036: 2904 cmp r1, #4 +10040038: d008 beq.n 1004004c +1004003a: bdf7 pop {r0, r1, r2, r4, r5, r6, r7, pc} +1004003c: 7841 ldrb r1, [r0, #1] +1004003e: b979 cbnz r1, 10040060 +10040040: 2101 movs r1, #1 +10040042: 7041 strb r1, [r0, #1] +10040044: 9700 str r7, [sp, #0] +10040046: 4633 mov r3, r6 +10040048: 2200 movs r2, #0 +1004004a: e005 b.n 10040058 +1004004c: 7881 ldrb r1, [r0, #2] +1004004e: 4291 cmp r1, r2 +10040050: d006 beq.n 10040060 +10040052: 7082 strb r2, [r0, #2] +10040054: 9700 str r7, [sp, #0] +10040056: 4633 mov r3, r6 +10040058: 4629 mov r1, r5 +1004005a: 4620 mov r0, r4 +1004005c: f7ff ff57 bl 1003ff0e +10040060: bdf7 pop {r0, r1, r2, r4, r5, r6, r7, pc} + +10040062 : +10040062: b57c push {r2, r3, r4, r5, r6, lr} +10040064: 4604 mov r4, r0 +10040066: 2000 movs r0, #0 +10040068: 9001 str r0, [sp, #4] +1004006a: 460d mov r5, r1 +1004006c: 4616 mov r6, r2 +1004006e: f7ff ff49 bl 1003ff04 <.text_24> +10040072: 6930 ldr r0, [r6, #16] +10040074: 4915 ldr r1, [pc, #84] ; (100400cc <.text_31>) +10040076: f100 0312 add.w r3, r0, #18 +1004007a: 7818 ldrb r0, [r3, #0] +1004007c: 2801 cmp r0, #1 +1004007e: d108 bne.n 10040092 +10040080: 7918 ldrb r0, [r3, #4] +10040082: 2801 cmp r0, #1 +10040084: d110 bne.n 100400a8 +10040086: 4632 mov r2, r6 +10040088: 4629 mov r1, r5 +1004008a: 4620 mov r0, r4 +1004008c: f7ff fe97 bl 1003fdbe +10040090: bd73 pop {r0, r1, r4, r5, r6, pc} +10040092: 2804 cmp r0, #4 +10040094: d108 bne.n 100400a8 +10040096: 6888 ldr r0, [r1, #8] +10040098: 6a00 ldr r0, [r0, #32] +1004009a: 6840 ldr r0, [r0, #4] +1004009c: b998 cbnz r0, 100400c6 +1004009e: 4629 mov r1, r5 +100400a0: 4620 mov r0, r4 +100400a2: f7ff ff08 bl 1003feb6 +100400a6: bd73 pop {r0, r1, r4, r5, r6, pc} +100400a8: 7918 ldrb r0, [r3, #4] +100400aa: 28fe cmp r0, #254 ; 0xfe +100400ac: d10b bne.n 100400c6 +100400ae: 7b18 ldrb r0, [r3, #12] +100400b0: 2801 cmp r0, #1 +100400b2: bf1e ittt ne +100400b4: 6888 ldrne r0, [r1, #8] +100400b6: 6840 ldrne r0, [r0, #4] +100400b8: 2800 cmpne r0, #0 +100400ba: d104 bne.n 100400c6 +100400bc: 4632 mov r2, r6 +100400be: 4629 mov r1, r5 +100400c0: 4620 mov r0, r4 +100400c2: f7ff ff92 bl 1003ffea +100400c6: bd73 pop {r0, r1, r4, r5, r6, pc} + +100400c8 <.text_30>: +100400c8: 1004885c .word 0x1004885c + +100400cc <.text_31>: +100400cc: 10048838 .word 0x10048838 + +100400d0 <.text_32>: +100400d0: 01020304 .word 0x01020304 + +100400d4 <.text_34>: +100400d4: 10048138 .word 0x10048138 + +100400d8 : +100400d8: b538 push {r3, r4, r5, lr} +100400da: 4604 mov r4, r0 +100400dc: 69e0 ldr r0, [r4, #28] +100400de: 6900 ldr r0, [r0, #16] +100400e0: 6805 ldr r5, [r0, #0] +100400e2: 6920 ldr r0, [r4, #16] +100400e4: 1d81 adds r1, r0, #6 +100400e6: f505 5088 add.w r0, r5, #4352 ; 0x1100 +100400ea: 3028 adds r0, #40 ; 0x28 +100400ec: f7e5 f85e bl 100251ac +100400f0: 4601 mov r1, r0 +100400f2: 4622 mov r2, r4 +100400f4: 4628 mov r0, r5 +100400f6: e8bd 4038 ldmia.w sp!, {r3, r4, r5, lr} +100400fa: e7b2 b.n 10040062 + +100400fc : +100400fc: 6c77 6e61 0030 0000 wlan0... + +10040104 : +10040104: 4552 4c41 4554 444b 5645 0000 REALTEKDEV.. + +10040110 : +10040110: 7962 7220 6165 746c 6b65 0000 by realtek.. + +1004011c : +1004011c: 6572 6c61 6574 006b realtek. + +10040124 : +10040124: 3176 302e 0000 0000 v1.0.... + +1004012c : +1004012c: 4657 2d41 6953 706d 656c 6f43 666e 6769 WFA-SimpleConfig +1004013c: 452d 726e 6c6f 656c 2d65 2d31 0030 0000 -Enrollee-1-0... + +1004014c : +1004014c: 0600 5000 04f2 0100 ...P.... + +10040154 : +10040154: 0100 5000 04f2 0100 ...P.... + +1004015c : +1004015c: b510 push {r4, lr} +1004015e: 460c mov r4, r1 +10040160: b118 cbz r0, 1004016a +10040162: 2101 movs r1, #1 +10040164: f7fd fbb0 bl 1003d8c8 +10040168: 7004 strb r4, [r0, #0] +1004016a: bd10 pop {r4, pc} + +1004016c : +1004016c: b538 push {r3, r4, r5, lr} +1004016e: 460c mov r4, r1 +10040170: 2800 cmp r0, #0 +10040172: bf18 it ne +10040174: 2c00 cmpne r4, #0 +10040176: 4615 mov r5, r2 +10040178: d008 beq.n 1004018c +1004017a: 4629 mov r1, r5 +1004017c: f7fd fba4 bl 1003d8c8 +10040180: 462a mov r2, r5 +10040182: 4621 mov r1, r4 +10040184: e8bd 4038 ldmia.w sp!, {r3, r4, r5, lr} +10040188: f7d0 bb41 b.w 1001080e +1004018c: bd31 pop {r0, r4, r5, pc} + +1004018e : +1004018e: b510 push {r4, lr} +10040190: b094 sub sp, #80 ; 0x50 +10040192: a80b add r0, sp, #44 ; 0x2c +10040194: f20f 3124 addw r1, pc, #804 ; 0x324 +10040198: 2220 movs r2, #32 +1004019a: f7ee f987 bl 1002e4ac <__iar_unaligned___aeabi_memcpy4> +1004019e: 221d movs r2, #29 +100401a0: f20f 3138 addw r1, pc, #824 ; 0x338 +100401a4: a80b add r0, sp, #44 ; 0x2c +100401a6: f7d0 fb3c bl 10010822 +100401aa: 2801 cmp r0, #1 +100401ac: d104 bne.n 100401b8 +100401ae: 2028 movs r0, #40 ; 0x28 +100401b0: f7fd f85c bl 1003d26c +100401b4: 0004 movs r4, r0 +100401b6: d101 bne.n 100401bc +100401b8: 2000 movs r0, #0 +100401ba: e033 b.n 10040224 +100401bc: 2000 movs r0, #0 +100401be: 6020 str r0, [r4, #0] +100401c0: 6060 str r0, [r4, #4] +100401c2: 222c movs r2, #44 ; 0x2c +100401c4: 2100 movs r1, #0 +100401c6: a800 add r0, sp, #0 +100401c8: f7d0 fb36 bl 10010838 +100401cc: 2000 movs r0, #0 +100401ce: 9001 str r0, [sp, #4] +100401d0: 48b3 ldr r0, [pc, #716] ; (100404a0 <.text_12>) +100401d2: 8800 ldrh r0, [r0, #0] +100401d4: 0601 lsls r1, r0, #24 +100401d6: d505 bpl.n 100401e4 +100401d8: 2001 movs r0, #1 +100401da: 9004 str r0, [sp, #16] +100401dc: 2004 movs r0, #4 +100401de: f8ad 0020 strh.w r0, [sp, #32] +100401e2: e010 b.n 10040206 +100401e4: f44f 7184 mov.w r1, #264 ; 0x108 +100401e8: 4208 tst r0, r1 +100401ea: d006 beq.n 100401fa +100401ec: 48ad ldr r0, [pc, #692] ; (100404a4 <.text_13>) +100401ee: 9002 str r0, [sp, #8] +100401f0: 2008 movs r0, #8 +100401f2: 9003 str r0, [sp, #12] +100401f4: 2000 movs r0, #0 +100401f6: f8ad 0020 strh.w r0, [sp, #32] +100401fa: 9802 ldr r0, [sp, #8] +100401fc: 2800 cmp r0, #0 +100401fe: bf04 itt eq +10040200: 9804 ldreq r0, [sp, #16] +10040202: 2800 cmpeq r0, #0 +10040204: d004 beq.n 10040210 +10040206: a800 add r0, sp, #0 +10040208: f000 f978 bl 100404fc +1004020c: 6220 str r0, [r4, #32] +1004020e: b928 cbnz r0, 1004021c +10040210: 4aa5 ldr r2, [pc, #660] ; (100404a8 <.text_14>) +10040212: 6852 ldr r2, [r2, #4] +10040214: 2100 movs r1, #0 +10040216: 4620 mov r0, r4 +10040218: 4790 blx r2 +1004021a: e7cd b.n 100401b8 +1004021c: f44f 60af mov.w r0, #1400 ; 0x578 +10040220: 61e0 str r0, [r4, #28] +10040222: 4620 mov r0, r4 +10040224: b014 add sp, #80 ; 0x50 +10040226: bd10 pop {r4, pc} + +10040228 : +10040228: b510 push {r4, lr} +1004022a: 0004 movs r4, r0 +1004022c: d00f beq.n 1004024e <__iar_annotation$$tailcall+0x2> +1004022e: 68a0 ldr r0, [r4, #8] +10040230: f7fd fb35 bl 1003d89e +10040234: 68e0 ldr r0, [r4, #12] +10040236: f7fd fb32 bl 1003d89e +1004023a: 6a20 ldr r0, [r4, #32] +1004023c: f000 f9d4 bl 100405e8 +10040240: 4620 mov r0, r4 +10040242: 4a99 ldr r2, [pc, #612] ; (100404a8 <.text_14>) +10040244: 6852 ldr r2, [r2, #4] +10040246: e8bd 4010 ldmia.w sp!, {r4, lr} +1004024a: 2100 movs r1, #0 + +1004024c <__iar_annotation$$tailcall>: +1004024c: 4710 bx r2 +1004024e: bd10 pop {r4, pc} + +10040250 : +10040250: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +10040254: 4604 mov r4, r0 +10040256: b082 sub sp, #8 +10040258: 68e2 ldr r2, [r4, #12] +1004025a: 69a0 ldr r0, [r4, #24] +1004025c: 6852 ldr r2, [r2, #4] +1004025e: 1a17 subs r7, r2, r0 +10040260: 69e2 ldr r2, [r4, #28] +10040262: 2600 movs r6, #0 +10040264: 1cbb adds r3, r7, #2 +10040266: 429a cmp r2, r3 +10040268: d204 bcs.n 10040274 +1004026a: 1e97 subs r7, r2, #2 +1004026c: 2601 movs r6, #1 +1004026e: b908 cbnz r0, 10040274 +10040270: 2603 movs r6, #3 +10040272: 1ebf subs r7, r7, #2 +10040274: 1cba adds r2, r7, #2 +10040276: f016 0502 ands.w r5, r6, #2 +1004027a: 9100 str r1, [sp, #0] +1004027c: bf18 it ne +1004027e: 1c92 addne r2, r2, #2 +10040280: 2302 movs r3, #2 +10040282: 2101 movs r1, #1 +10040284: f243 702a movw r0, #14122 ; 0x372a +10040288: f000 fa36 bl 100406f8 +1004028c: ea5f 0800 movs.w r8, r0 +10040290: bf08 it eq +10040292: 2000 moveq r0, #0 +10040294: d037 beq.n 10040306 +10040296: 6961 ldr r1, [r4, #20] +10040298: b2c9 uxtb r1, r1 +1004029a: f7ff ff5f bl 1004015c +1004029e: 4631 mov r1, r6 +100402a0: 4640 mov r0, r8 +100402a2: f7ff ff5b bl 1004015c +100402a6: b14d cbz r5, 100402bc +100402a8: 68e0 ldr r0, [r4, #12] +100402aa: 6846 ldr r6, [r0, #4] +100402ac: 2102 movs r1, #2 +100402ae: 4640 mov r0, r8 +100402b0: f7fd fb0a bl 1003d8c8 +100402b4: b2b6 uxth r6, r6 +100402b6: 0a31 lsrs r1, r6, #8 +100402b8: 7001 strb r1, [r0, #0] +100402ba: 7046 strb r6, [r0, #1] +100402bc: 463a mov r2, r7 +100402be: 68e0 ldr r0, [r4, #12] +100402c0: 69a1 ldr r1, [r4, #24] +100402c2: 6880 ldr r0, [r0, #8] +100402c4: 1809 adds r1, r1, r0 +100402c6: 4640 mov r0, r8 +100402c8: f7ff ff50 bl 1004016c +100402cc: 69a0 ldr r0, [r4, #24] +100402ce: 1839 adds r1, r7, r0 +100402d0: 61a1 str r1, [r4, #24] +100402d2: 68e0 ldr r0, [r4, #12] +100402d4: 6842 ldr r2, [r0, #4] +100402d6: 4291 cmp r1, r2 +100402d8: d112 bne.n 10040300 +100402da: f7fd fae0 bl 1003d89e +100402de: 2000 movs r0, #0 +100402e0: 60e0 str r0, [r4, #12] +100402e2: 61a0 str r0, [r4, #24] +100402e4: 6821 ldr r1, [r4, #0] +100402e6: 6960 ldr r0, [r4, #20] +100402e8: 2905 cmp r1, #5 +100402ea: bf08 it eq +100402ec: 2802 cmpeq r0, #2 +100402ee: d003 beq.n 100402f8 +100402f0: 2803 cmp r0, #3 +100402f2: bf18 it ne +100402f4: 2805 cmpne r0, #5 +100402f6: d101 bne.n 100402fc +100402f8: 2006 movs r0, #6 +100402fa: e002 b.n 10040302 +100402fc: 2002 movs r0, #2 +100402fe: e000 b.n 10040302 +10040300: 2004 movs r0, #4 +10040302: 6020 str r0, [r4, #0] +10040304: 4640 mov r0, r8 +10040306: e8bd 81f6 ldmia.w sp!, {r1, r2, r4, r5, r6, r7, r8, pc} + +1004030a : +1004030a: b538 push {r3, r4, r5, lr} +1004030c: 6904 ldr r4, [r0, #16] +1004030e: 42a3 cmp r3, r4 +10040310: d107 bne.n 10040322 +10040312: 6883 ldr r3, [r0, #8] +10040314: 681c ldr r4, [r3, #0] +10040316: 685d ldr r5, [r3, #4] +10040318: 1b64 subs r4, r4, r5 +1004031a: 4294 cmp r4, r2 +1004031c: d204 bcs.n 10040328 +1004031e: 2106 movs r1, #6 +10040320: 6001 str r1, [r0, #0] +10040322: f04f 30ff mov.w r0, #4294967295 +10040326: bd32 pop {r1, r4, r5, pc} +10040328: 4618 mov r0, r3 +1004032a: f7ff ff1f bl 1004016c +1004032e: 2000 movs r0, #0 +10040330: bd32 pop {r1, r4, r5, pc} + +10040332 : +10040332: b570 push {r4, r5, r6, lr} +10040334: 4604 mov r4, r0 +10040336: 460d mov r5, r1 +10040338: 68a0 ldr r0, [r4, #8] +1004033a: 461e mov r6, r3 +1004033c: b968 cbnz r0, 1004035a +1004033e: 0790 lsls r0, r2, #30 +10040340: d504 bpl.n 1004034c +10040342: 9804 ldr r0, [sp, #16] +10040344: f7fd fa84 bl 1003d850 +10040348: 60a0 str r0, [r4, #8] +1004034a: b908 cbnz r0, 10040350 +1004034c: 2000 movs r0, #0 +1004034e: bd70 pop {r4, r5, r6, pc} +10040350: 6126 str r6, [r4, #16] +10040352: 9a06 ldr r2, [sp, #24] +10040354: 9905 ldr r1, [sp, #20] +10040356: f7ff ff09 bl 1004016c +1004035a: 4628 mov r0, r5 +1004035c: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +10040360: 2102 movs r1, #2 +10040362: f000 ba12 b.w 1004078a + +10040366 : +10040366: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +1004036a: b088 sub sp, #32 +1004036c: 4604 mov r4, r0 +1004036e: 460d mov r5, r1 +10040370: f04f 0900 mov.w r9, #0 +10040374: ab03 add r3, sp, #12 +10040376: 462a mov r2, r5 +10040378: 2101 movs r1, #1 +1004037a: f243 702a movw r0, #14122 ; 0x372a +1004037e: f000 f983 bl 10040688 +10040382: 0007 movs r7, r0 +10040384: d03b beq.n 100403fe +10040386: 9803 ldr r0, [sp, #12] +10040388: 2802 cmp r0, #2 +1004038a: d338 bcc.n 100403fe +1004038c: 4628 mov r0, r5 +1004038e: f000 f9f1 bl 10040774 +10040392: 4680 mov r8, r0 +10040394: 9803 ldr r0, [sp, #12] +10040396: 19c5 adds r5, r0, r7 +10040398: f817 6b01 ldrb.w r6, [r7], #1 +1004039c: f817 ab01 ldrb.w sl, [r7], #1 +100403a0: ea5f 708a movs.w r0, sl, lsl #30 +100403a4: d50a bpl.n 100403bc +100403a6: 1be8 subs r0, r5, r7 +100403a8: 2802 cmp r0, #2 +100403aa: db28 blt.n 100403fe +100403ac: 7838 ldrb r0, [r7, #0] +100403ae: 7879 ldrb r1, [r7, #1] +100403b0: ea41 2900 orr.w r9, r1, r0, lsl #8 +100403b4: 1cbf adds r7, r7, #2 +100403b6: 1be8 subs r0, r5, r7 +100403b8: 4581 cmp r9, r0 +100403ba: db20 blt.n 100403fe +100403bc: 6820 ldr r0, [r4, #0] +100403be: 2804 cmp r0, #4 +100403c0: d102 bne.n 100403c8 +100403c2: 2e06 cmp r6, #6 +100403c4: d05a beq.n 1004047c +100403c6: e01a b.n 100403fe +100403c8: 2e02 cmp r6, #2 +100403ca: bf18 it ne +100403cc: 2e03 cmpne r6, #3 +100403ce: d004 beq.n 100403da +100403d0: 2e04 cmp r6, #4 +100403d2: bf1c itt ne +100403d4: 2e05 cmpne r6, #5 +100403d6: 2e01 cmpne r6, #1 +100403d8: d111 bne.n 100403fe +100403da: b920 cbnz r0, 100403e6 +100403dc: 2e01 cmp r6, #1 +100403de: d153 bne.n 10040488 +100403e0: 2002 movs r0, #2 +100403e2: 6020 str r0, [r4, #0] +100403e4: e03f b.n 10040466 +100403e6: 2e01 cmp r6, #1 +100403e8: d009 beq.n 100403fe +100403ea: 68a0 ldr r0, [r4, #8] +100403ec: b148 cbz r0, 10040402 +100403ee: 4633 mov r3, r6 +100403f0: 1bea subs r2, r5, r7 +100403f2: 4639 mov r1, r7 +100403f4: 4620 mov r0, r4 +100403f6: f7ff ff88 bl 1004030a +100403fa: 2800 cmp r0, #0 +100403fc: d501 bpl.n 10040402 +100403fe: 2000 movs r0, #0 +10040400: e042 b.n 10040488 +10040402: ea5f 70ca movs.w r0, sl, lsl #31 +10040406: d50b bpl.n 10040420 +10040408: 1be8 subs r0, r5, r7 +1004040a: 9002 str r0, [sp, #8] +1004040c: 9701 str r7, [sp, #4] +1004040e: f8cd 9000 str.w r9, [sp] +10040412: 4633 mov r3, r6 +10040414: 4652 mov r2, sl +10040416: 4641 mov r1, r8 +10040418: 4620 mov r0, r4 +1004041a: f7ff ff8a bl 10040332 +1004041e: e033 b.n 10040488 +10040420: 68a0 ldr r0, [r4, #8] +10040422: b938 cbnz r0, 10040434 +10040424: 2001 movs r0, #1 +10040426: 9007 str r0, [sp, #28] +10040428: 9706 str r7, [sp, #24] +1004042a: 1be8 subs r0, r5, r7 +1004042c: 9005 str r0, [sp, #20] +1004042e: 9004 str r0, [sp, #16] +10040430: a804 add r0, sp, #16 +10040432: 60a0 str r0, [r4, #8] +10040434: 68a2 ldr r2, [r4, #8] +10040436: 6a20 ldr r0, [r4, #32] +10040438: 4631 mov r1, r6 +1004043a: f000 f905 bl 10040648 +1004043e: 2800 cmp r0, #0 +10040440: bf18 it ne +10040442: 2802 cmpne r0, #2 +10040444: d005 beq.n 10040452 +10040446: d302 bcc.n 1004044e +10040448: 2803 cmp r0, #3 +1004044a: d002 beq.n 10040452 +1004044c: e003 b.n 10040456 +1004044e: 2002 movs r0, #2 +10040450: e000 b.n 10040454 +10040452: 2006 movs r0, #6 +10040454: 6020 str r0, [r4, #0] +10040456: 68a0 ldr r0, [r4, #8] +10040458: a904 add r1, sp, #16 +1004045a: 4288 cmp r0, r1 +1004045c: bf18 it ne +1004045e: f7fd fa1e blne 1003d89e +10040462: 2000 movs r0, #0 +10040464: 60a0 str r0, [r4, #8] +10040466: 68e0 ldr r0, [r4, #12] +10040468: b940 cbnz r0, 1004047c +1004046a: 6a20 ldr r0, [r4, #32] +1004046c: f104 0114 add.w r1, r4, #20 +10040470: f000 f8ec bl 1004064c +10040474: 60e0 str r0, [r4, #12] +10040476: b138 cbz r0, 10040488 +10040478: 2000 movs r0, #0 +1004047a: 61a0 str r0, [r4, #24] +1004047c: 2002 movs r0, #2 +1004047e: 6020 str r0, [r4, #0] +10040480: 4641 mov r1, r8 +10040482: 4620 mov r0, r4 +10040484: f7ff fee4 bl 10040250 +10040488: b008 add sp, #32 +1004048a: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + +1004048e : +1004048e: 4807 ldr r0, [pc, #28] ; (100404ac <.text_15>) +10040490: 4907 ldr r1, [pc, #28] ; (100404b0 <.text_16>) +10040492: 60c1 str r1, [r0, #12] +10040494: 4907 ldr r1, [pc, #28] ; (100404b4 <.text_17>) +10040496: 6101 str r1, [r0, #16] +10040498: 4907 ldr r1, [pc, #28] ; (100404b8 <.text_18>) +1004049a: 6141 str r1, [r0, #20] +1004049c: 2000 movs r0, #0 +1004049e: 4770 bx lr + +100404a0 <.text_12>: +100404a0: 10048136 .word 0x10048136 + +100404a4 <.text_13>: +100404a4: 1004813c .word 0x1004813c + +100404a8 <.text_14>: +100404a8: 100006d4 .word 0x100006d4 + +100404ac <.text_15>: +100404ac: 1004885c .word 0x1004885c + +100404b0 <.text_16>: +100404b0: 1004018f .word 0x1004018f + +100404b4 <.text_17>: +100404b4: 10040229 .word 0x10040229 + +100404b8 <.text_18>: +100404b8: 10040367 .word 0x10040367 + +100404bc : +100404bc: 2d414657 706d6953 6f43656c 6769666e WFA-SimpleConfig +100404cc: 726e452d 656c6c6f 2d312d65 00000030 -Enrollee-1-0... + +100404dc : +100404dc: 2d414657 706d6953 6f43656c 6769666e WFA-SimpleConfig +100404ec: 726e452d 656c6c6f 2d312d65 00000030 -Enrollee-1-0... + +100404fc : +100404fc: b5f0 push {r4, r5, r6, r7, lr} +100404fe: 4605 mov r5, r0 +10040500: b085 sub sp, #20 +10040502: 2000 movs r0, #0 +10040504: f7d1 fe10 bl 10012128 +10040508: 4606 mov r6, r0 +1004050a: a800 add r0, sp, #0 +1004050c: 2110 movs r1, #16 +1004050e: f7e5 f985 bl 1002581c <__aeabi_memclr4> +10040512: f44f 7024 mov.w r0, #656 ; 0x290 +10040516: f7fc fea9 bl 1003d26c +1004051a: 0004 movs r4, r0 +1004051c: bf18 it ne +1004051e: 2e00 cmpne r6, #0 +10040520: d046 beq.n 100405b0 +10040522: 6868 ldr r0, [r5, #4] +10040524: 6060 str r0, [r4, #4] +10040526: f000 f859 bl 100405dc <.text_4> +1004052a: f000 f851 bl 100405d0 <.text_3> +1004052e: 6868 ldr r0, [r5, #4] +10040530: b120 cbz r0, 1004053c +10040532: 2210 movs r2, #16 +10040534: a900 add r1, sp, #0 +10040536: f104 0020 add.w r0, r4, #32 +1004053a: e007 b.n 1004054c +1004053c: f000 f84e bl 100405dc <.text_4> +10040540: f000 f846 bl 100405d0 <.text_3> +10040544: 2210 movs r2, #16 +10040546: a900 add r1, sp, #0 +10040548: f104 0010 add.w r0, r4, #16 +1004054c: f7d0 f95f bl 1001080e +10040550: 68a8 ldr r0, [r5, #8] +10040552: 4f3c ldr r7, [pc, #240] ; (10040644 <.text_6>) +10040554: f504 769c add.w r6, r4, #312 ; 0x138 +10040558: b198 cbz r0, 10040582 +1004055a: 2000 movs r0, #0 +1004055c: 8130 strh r0, [r6, #8] +1004055e: f8d4 0138 ldr.w r0, [r4, #312] ; 0x138 +10040562: b110 cbz r0, 1004056a +10040564: 687a ldr r2, [r7, #4] +10040566: 2100 movs r1, #0 +10040568: 4790 blx r2 +1004056a: 68e8 ldr r0, [r5, #12] +1004056c: 6839 ldr r1, [r7, #0] +1004056e: 4788 blx r1 +10040570: f8c4 0138 str.w r0, [r4, #312] ; 0x138 +10040574: b1c0 cbz r0, 100405a8 +10040576: 68ea ldr r2, [r5, #12] +10040578: 68a9 ldr r1, [r5, #8] +1004057a: f7d0 f948 bl 1001080e +1004057e: 68e8 ldr r0, [r5, #12] +10040580: 6070 str r0, [r6, #4] +10040582: 6928 ldr r0, [r5, #16] +10040584: 60f0 str r0, [r6, #12] +10040586: 6928 ldr r0, [r5, #16] +10040588: b1b0 cbz r0, 100405b8 +1004058a: 2004 movs r0, #4 +1004058c: 8130 strh r0, [r6, #8] +1004058e: f8d4 0138 ldr.w r0, [r4, #312] ; 0x138 +10040592: b110 cbz r0, 1004059a +10040594: 687a ldr r2, [r7, #4] +10040596: 2100 movs r1, #0 +10040598: 4790 blx r2 +1004059a: f20f 00b4 addw r0, pc, #180 ; 0xb4 +1004059e: f7fc fe69 bl 1003d274 +100405a2: f8c4 0138 str.w r0, [r4, #312] ; 0x138 +100405a6: b928 cbnz r0, 100405b4 +100405a8: 687a ldr r2, [r7, #4] +100405aa: 2100 movs r1, #0 +100405ac: 4620 mov r0, r4 +100405ae: 4790 blx r2 +100405b0: 2000 movs r0, #0 +100405b2: e00b b.n 100405cc +100405b4: 2008 movs r0, #8 +100405b6: 6070 str r0, [r6, #4] +100405b8: 6860 ldr r0, [r4, #4] +100405ba: b100 cbz r0, 100405be +100405bc: 200d movs r0, #13 +100405be: 60e0 str r0, [r4, #12] +100405c0: 2000 movs r0, #0 +100405c2: f8c4 0280 str.w r0, [r4, #640] ; 0x280 +100405c6: f8c4 028c str.w r0, [r4, #652] ; 0x28c +100405ca: 4620 mov r0, r4 +100405cc: b005 add sp, #20 +100405ce: bdf0 pop {r4, r5, r6, r7, pc} + +100405d0 <.text_3>: +100405d0: 2206 movs r2, #6 +100405d2: 4631 mov r1, r6 +100405d4: f104 0030 add.w r0, r4, #48 ; 0x30 +100405d8: f7d0 b919 b.w 1001080e + +100405dc <.text_4>: +100405dc: 2206 movs r2, #6 +100405de: 4631 mov r1, r6 +100405e0: f10d 000a add.w r0, sp, #10 +100405e4: f7d0 b913 b.w 1001080e + +100405e8 : +100405e8: b570 push {r4, r5, r6, lr} +100405ea: 4604 mov r4, r0 +100405ec: f8d4 00d8 ldr.w r0, [r4, #216] ; 0xd8 +100405f0: f7fd f955 bl 1003d89e +100405f4: f104 05d8 add.w r5, r4, #216 ; 0xd8 +100405f8: 6868 ldr r0, [r5, #4] +100405fa: f7fd f950 bl 1003d89e +100405fe: 68a8 ldr r0, [r5, #8] +10040600: f7fd f94d bl 1003d89e +10040604: 6de8 ldr r0, [r5, #92] ; 0x5c +10040606: f7fd f94a bl 1003d89e +1004060a: 4e0e ldr r6, [pc, #56] ; (10040644 <.text_6>) +1004060c: 6e28 ldr r0, [r5, #96] ; 0x60 +1004060e: 6872 ldr r2, [r6, #4] +10040610: 2100 movs r1, #0 +10040612: 4790 blx r2 +10040614: 6fa8 ldr r0, [r5, #120] ; 0x78 +10040616: 6872 ldr r2, [r6, #4] +10040618: 2100 movs r1, #0 +1004061a: 4790 blx r2 +1004061c: f504 70f0 add.w r0, r4, #480 ; 0x1e0 +10040620: f000 fa21 bl 10040a66 +10040624: f8d4 0274 ldr.w r0, [r4, #628] ; 0x274 +10040628: 6872 ldr r2, [r6, #4] +1004062a: 2100 movs r1, #0 +1004062c: 4790 blx r2 +1004062e: f8d4 0278 ldr.w r0, [r4, #632] ; 0x278 +10040632: f7fd f8f6 bl 1003d822 +10040636: 6872 ldr r2, [r6, #4] +10040638: 4620 mov r0, r4 +1004063a: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +1004063e: 2100 movs r1, #0 + +10040640 <__iar_annotation$$tailcall>: +10040640: 4710 bx r2 + ... + +10040644 <.text_6>: +10040644: 100006d4 .word 0x100006d4 + +10040648 : +10040648: f000 befe b.w 10041448 + +1004064c : +1004064c: f000 bc41 b.w 10040ed2 + +10040650 : +10040650: 3030 3030 3030 3030 0000 0000 00000000.... + +1004065c : +1004065c: b510 push {r4, lr} +1004065e: 460c mov r4, r1 +10040660: b118 cbz r0, 1004066a +10040662: 2101 movs r1, #1 +10040664: f7fd f930 bl 1003d8c8 +10040668: 7004 strb r4, [r0, #0] +1004066a: bd10 pop {r4, pc} + +1004066c : +1004066c: b510 push {r4, lr} +1004066e: 460c mov r4, r1 +10040670: b148 cbz r0, 10040686 +10040672: 6880 ldr r0, [r0, #8] +10040674: 8840 ldrh r0, [r0, #2] +10040676: f7cb ff6b bl 1000c550 +1004067a: 1d21 adds r1, r4, #4 +1004067c: 4288 cmp r0, r1 +1004067e: d201 bcs.n 10040684 +10040680: 2000 movs r0, #0 +10040682: bd10 pop {r4, pc} +10040684: 2001 movs r0, #1 +10040686: bd10 pop {r4, pc} + +10040688 : +10040688: b5f8 push {r3, r4, r5, r6, r7, lr} +1004068a: 4604 mov r4, r0 +1004068c: 460d mov r5, r1 +1004068e: 4617 mov r7, r2 +10040690: 461e mov r6, r3 +10040692: 2101 movs r1, #1 +10040694: 4638 mov r0, r7 +10040696: f7ff ffe9 bl 1004066c +1004069a: b340 cbz r0, 100406ee +1004069c: 68bf ldr r7, [r7, #8] +1004069e: 8878 ldrh r0, [r7, #2] +100406a0: f7cb ff56 bl 1000c550 +100406a4: 4601 mov r1, r0 +100406a6: 1d38 adds r0, r7, #4 +100406a8: f810 2b01 ldrb.w r2, [r0], #1 +100406ac: 2afe cmp r2, #254 ; 0xfe +100406ae: d11a bne.n 100406e6 +100406b0: 290c cmp r1, #12 +100406b2: d31c bcc.n 100406ee +100406b4: 7843 ldrb r3, [r0, #1] +100406b6: 7802 ldrb r2, [r0, #0] +100406b8: 021b lsls r3, r3, #8 +100406ba: ea43 4202 orr.w r2, r3, r2, lsl #16 +100406be: 7883 ldrb r3, [r0, #2] +100406c0: 431a orrs r2, r3 +100406c2: f810 3f03 ldrb.w r3, [r0, #3]! +100406c6: 7847 ldrb r7, [r0, #1] +100406c8: 043f lsls r7, r7, #16 +100406ca: ea47 6303 orr.w r3, r7, r3, lsl #24 +100406ce: 7887 ldrb r7, [r0, #2] +100406d0: ea43 2307 orr.w r3, r3, r7, lsl #8 +100406d4: 78c7 ldrb r7, [r0, #3] +100406d6: 433b orrs r3, r7 +100406d8: 1d00 adds r0, r0, #4 +100406da: 42a2 cmp r2, r4 +100406dc: bf08 it eq +100406de: 42ab cmpeq r3, r5 +100406e0: d105 bne.n 100406ee +100406e2: 390c subs r1, #12 +100406e4: e006 b.n 100406f4 +100406e6: 2c00 cmp r4, #0 +100406e8: bf08 it eq +100406ea: 42aa cmpeq r2, r5 +100406ec: d001 beq.n 100406f2 +100406ee: 2000 movs r0, #0 +100406f0: bdf2 pop {r1, r4, r5, r6, r7, pc} +100406f2: 1f49 subs r1, r1, #5 +100406f4: 6031 str r1, [r6, #0] +100406f6: bdf2 pop {r1, r4, r5, r6, r7, pc} + +100406f8 : +100406f8: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +100406fc: 0006 movs r6, r0 +100406fe: bf0c ite eq +10040700: 2005 moveq r0, #5 +10040702: 200c movne r0, #12 +10040704: 1815 adds r5, r2, r0 +10040706: 460c mov r4, r1 +10040708: 4699 mov r9, r3 +1004070a: 4628 mov r0, r5 +1004070c: f7fd f8a0 bl 1003d850 +10040710: ea5f 0800 movs.w r8, r0 +10040714: bf08 it eq +10040716: 2000 moveq r0, #0 +10040718: d02a beq.n 10040770 +1004071a: 2104 movs r1, #4 +1004071c: f7fd f8d4 bl 1003d8c8 +10040720: 4607 mov r7, r0 +10040722: f887 9000 strb.w r9, [r7] +10040726: 9808 ldr r0, [sp, #32] +10040728: 7078 strb r0, [r7, #1] +1004072a: b2a8 uxth r0, r5 +1004072c: f7cb ff0b bl 1000c546 +10040730: 8078 strh r0, [r7, #2] +10040732: b926 cbnz r6, 1004073e +10040734: b2e1 uxtb r1, r4 +10040736: 4640 mov r0, r8 +10040738: f7ff ff90 bl 1004065c +1004073c: e017 b.n 1004076e +1004073e: 21fe movs r1, #254 ; 0xfe +10040740: 4640 mov r0, r8 +10040742: f7ff ff8b bl 1004065c +10040746: 2103 movs r1, #3 +10040748: 4640 mov r0, r8 +1004074a: f7fd f8bd bl 1003d8c8 +1004074e: 0c31 lsrs r1, r6, #16 +10040750: 7001 strb r1, [r0, #0] +10040752: 0a31 lsrs r1, r6, #8 +10040754: 7041 strb r1, [r0, #1] +10040756: 7086 strb r6, [r0, #2] +10040758: 2104 movs r1, #4 +1004075a: 4640 mov r0, r8 +1004075c: f7fd f8b4 bl 1003d8c8 +10040760: 0e21 lsrs r1, r4, #24 +10040762: 7001 strb r1, [r0, #0] +10040764: 0c21 lsrs r1, r4, #16 +10040766: 7041 strb r1, [r0, #1] +10040768: 0a21 lsrs r1, r4, #8 +1004076a: 7081 strb r1, [r0, #2] +1004076c: 70c4 strb r4, [r0, #3] +1004076e: 4640 mov r0, r8 +10040770: e8bd 83f2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, pc} + +10040774 : +10040774: 6880 ldr r0, [r0, #8] +10040776: 7840 ldrb r0, [r0, #1] +10040778: 4770 bx lr + +1004077a : +1004077a: b510 push {r4, lr} +1004077c: 460c mov r4, r1 +1004077e: b118 cbz r0, 10040788 +10040780: 2101 movs r1, #1 +10040782: f7fd f8a1 bl 1003d8c8 +10040786: 7004 strb r4, [r0, #0] +10040788: bd10 pop {r4, pc} + +1004078a : +1004078a: b510 push {r4, lr} +1004078c: b082 sub sp, #8 +1004078e: 460b mov r3, r1 +10040790: 9000 str r0, [sp, #0] +10040792: 2202 movs r2, #2 +10040794: 2101 movs r1, #1 +10040796: f243 702a movw r0, #14122 ; 0x372a +1004079a: f7ff ffad bl 100406f8 +1004079e: 0004 movs r4, r0 +100407a0: d101 bne.n 100407a6 +100407a2: 2000 movs r0, #0 +100407a4: bd16 pop {r1, r2, r4, pc} +100407a6: 2106 movs r1, #6 +100407a8: f7ff ffe7 bl 1004077a +100407ac: 2100 movs r1, #0 +100407ae: 4620 mov r0, r4 +100407b0: f7ff ffe3 bl 1004077a +100407b4: 4620 mov r0, r4 +100407b6: bd16 pop {r1, r2, r4, pc} + +100407b8 : +100407b8: b510 push {r4, lr} +100407ba: 460c mov r4, r1 +100407bc: b128 cbz r0, 100407ca +100407be: 2102 movs r1, #2 +100407c0: f7fd f882 bl 1003d8c8 +100407c4: 0a21 lsrs r1, r4, #8 +100407c6: 7001 strb r1, [r0, #0] +100407c8: 7044 strb r4, [r0, #1] +100407ca: bd10 pop {r4, pc} + +100407cc : +100407cc: b538 push {r3, r4, r5, lr} +100407ce: 460c mov r4, r1 +100407d0: 2800 cmp r0, #0 +100407d2: bf18 it ne +100407d4: 2c00 cmpne r4, #0 +100407d6: 4615 mov r5, r2 +100407d8: d008 beq.n 100407ec +100407da: 4629 mov r1, r5 +100407dc: f7fd f874 bl 1003d8c8 +100407e0: 462a mov r2, r5 +100407e2: 4621 mov r1, r4 +100407e4: e8bd 4038 ldmia.w sp!, {r3, r4, r5, lr} +100407e8: f7d0 b811 b.w 1001080e +100407ec: bd31 pop {r0, r4, r5, pc} + +100407ee : +100407ee: b570 push {r4, r5, r6, lr} +100407f0: 4604 mov r4, r0 +100407f2: 460d mov r5, r1 +100407f4: 68e0 ldr r0, [r4, #12] +100407f6: b118 cbz r0, 10040800 +100407f8: f7cb fdae bl 1000c358 +100407fc: 4606 mov r6, r0 +100407fe: e000 b.n 10040802 +10040800: 2600 movs r6, #0 +10040802: f241 0121 movw r1, #4129 ; 0x1021 +10040806: f000 f840 bl 1004088a <.text_11+0x2> +1004080a: f000 f83d bl 10040888 <.text_11> +1004080e: 68e1 ldr r1, [r4, #12] +10040810: e010 b.n 10040834 <.text_7> + +10040812 : +10040812: b570 push {r4, r5, r6, lr} +10040814: 4604 mov r4, r0 +10040816: 460d mov r5, r1 +10040818: f241 0123 movw r1, #4131 ; 0x1023 +1004081c: f000 f835 bl 1004088a <.text_11+0x2> +10040820: 6920 ldr r0, [r4, #16] +10040822: b118 cbz r0, 1004082c +10040824: f7cb fd98 bl 1000c358 +10040828: 4606 mov r6, r0 +1004082a: e000 b.n 1004082e +1004082c: 2600 movs r6, #0 +1004082e: f000 f82b bl 10040888 <.text_11> +10040832: 6921 ldr r1, [r4, #16] + +10040834 <.text_7>: +10040834: 4632 mov r2, r6 +10040836: 4628 mov r0, r5 +10040838: f7ff ffc8 bl 100407cc +1004083c: 2000 movs r0, #0 +1004083e: bd70 pop {r4, r5, r6, pc} + +10040840 : +10040840: b570 push {r4, r5, r6, lr} +10040842: 4604 mov r4, r0 +10040844: 460d mov r5, r1 +10040846: f241 0124 movw r1, #4132 ; 0x1024 +1004084a: f000 f81e bl 1004088a <.text_11+0x2> +1004084e: 6960 ldr r0, [r4, #20] +10040850: b118 cbz r0, 1004085a +10040852: f7cb fd81 bl 1000c358 +10040856: 4606 mov r6, r0 +10040858: e000 b.n 1004085c +1004085a: 2600 movs r6, #0 +1004085c: f000 f814 bl 10040888 <.text_11> +10040860: 6961 ldr r1, [r4, #20] +10040862: e7e7 b.n 10040834 <.text_7> + +10040864 : +10040864: b538 push {r3, r4, r5, lr} +10040866: 4604 mov r4, r0 +10040868: 460d mov r5, r1 +1004086a: f241 0154 movw r1, #4180 ; 0x1054 +1004086e: f000 f80c bl 1004088a <.text_11+0x2> +10040872: 2108 movs r1, #8 +10040874: f000 f809 bl 1004088a <.text_11+0x2> +10040878: 2208 movs r2, #8 +1004087a: f104 011c add.w r1, r4, #28 +1004087e: 4628 mov r0, r5 +10040880: f7ff ffa4 bl 100407cc +10040884: 2000 movs r0, #0 +10040886: bd32 pop {r1, r4, r5, pc} + +10040888 <.text_11>: +10040888: b2b1 uxth r1, r6 +1004088a: 4628 mov r0, r5 +1004088c: e794 b.n 100407b8 + +1004088e : +1004088e: b570 push {r4, r5, r6, lr} +10040890: 4604 mov r4, r0 +10040892: 460d mov r5, r1 +10040894: f241 0111 movw r1, #4113 ; 0x1011 +10040898: f7ff fff7 bl 1004088a <.text_11+0x2> +1004089c: 68a0 ldr r0, [r4, #8] +1004089e: b118 cbz r0, 100408a8 +100408a0: f7cb fd5a bl 1000c358 +100408a4: 4606 mov r6, r0 +100408a6: e000 b.n 100408aa +100408a8: 2600 movs r6, #0 +100408aa: f7ff ffed bl 10040888 <.text_11> +100408ae: 68a1 ldr r1, [r4, #8] +100408b0: e7c0 b.n 10040834 <.text_7> + +100408b2 : +100408b2: b570 push {r4, r5, r6, lr} +100408b4: 4604 mov r4, r0 +100408b6: 460d mov r5, r1 +100408b8: f7ff ff99 bl 100407ee +100408bc: bb28 cbnz r0, 1004090a +100408be: 4629 mov r1, r5 +100408c0: 4620 mov r0, r4 +100408c2: f7ff ffa6 bl 10040812 +100408c6: bb00 cbnz r0, 1004090a +100408c8: 4629 mov r1, r5 +100408ca: 4620 mov r0, r4 +100408cc: f7ff ffb8 bl 10040840 +100408d0: b9d8 cbnz r0, 1004090a +100408d2: f241 0142 movw r1, #4162 ; 0x1042 +100408d6: f7ff ffd8 bl 1004088a <.text_11+0x2> +100408da: 69a0 ldr r0, [r4, #24] +100408dc: b118 cbz r0, 100408e6 +100408de: f7cb fd3b bl 1000c358 +100408e2: 4606 mov r6, r0 +100408e4: e000 b.n 100408e8 +100408e6: 2600 movs r6, #0 +100408e8: f7ff ffce bl 10040888 <.text_11> +100408ec: 69a1 ldr r1, [r4, #24] +100408ee: 4632 mov r2, r6 +100408f0: 4628 mov r0, r5 +100408f2: f7ff ff6b bl 100407cc +100408f6: 4629 mov r1, r5 +100408f8: 4620 mov r0, r4 +100408fa: f7ff ffb3 bl 10040864 +100408fe: b920 cbnz r0, 1004090a +10040900: 4629 mov r1, r5 +10040902: 4620 mov r0, r4 +10040904: f7ff ffc3 bl 1004088e +10040908: b108 cbz r0, 1004090e +1004090a: f04f 30ff mov.w r0, #4294967295 +1004090e: bd70 pop {r4, r5, r6, pc} + +10040910 : +10040910: b510 push {r4, lr} +10040912: 460c mov r4, r1 +10040914: f241 012d movw r1, #4141 ; 0x102d +10040918: f000 f812 bl 10040940 <.text_16> +1004091c: 2104 movs r1, #4 +1004091e: f000 f80f bl 10040940 <.text_16> +10040922: b15c cbz r4, 1004093c +10040924: 2104 movs r1, #4 +10040926: 4620 mov r0, r4 +10040928: f7fc ffce bl 1003d8c8 +1004092c: 2181 movs r1, #129 ; 0x81 +1004092e: 7001 strb r1, [r0, #0] +10040930: 2102 movs r1, #2 +10040932: 7041 strb r1, [r0, #1] +10040934: 2103 movs r1, #3 +10040936: 7081 strb r1, [r0, #2] +10040938: 2100 movs r1, #0 +1004093a: 70c1 strb r1, [r0, #3] +1004093c: 2000 movs r0, #0 +1004093e: bd10 pop {r4, pc} + +10040940 <.text_16>: +10040940: 4620 mov r0, r4 +10040942: e739 b.n 100407b8 + +10040944 : +10040944: b510 push {r4, lr} +10040946: 460c mov r4, r1 +10040948: f241 013c movw r1, #4156 ; 0x103c +1004094c: f7ff fff8 bl 10040940 <.text_16> +10040950: 2101 movs r1, #1 +10040952: f7ff fff5 bl 10040940 <.text_16> +10040956: b12c cbz r4, 10040964 +10040958: 2101 movs r1, #1 +1004095a: 4620 mov r0, r4 +1004095c: f7fc ffb4 bl 1003d8c8 +10040960: 2101 movs r1, #1 +10040962: 7001 strb r1, [r0, #0] +10040964: 2000 movs r0, #0 +10040966: bd10 pop {r4, pc} + +10040968 : +10040968: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +1004096c: 4688 mov r8, r1 +1004096e: f108 06b0 add.w r6, r8, #176 ; 0xb0 +10040972: f8d8 90b0 ldr.w r9, [r8, #176] ; 0xb0 +10040976: 6875 ldr r5, [r6, #4] +10040978: f1b9 0f00 cmp.w r9, #0 +1004097c: 4604 mov r4, r0 +1004097e: d064 beq.n 10040a4a +10040980: 68e0 ldr r0, [r4, #12] +10040982: 4f4a ldr r7, [pc, #296] ; (10040aac <.text_29>) +10040984: b108 cbz r0, 1004098a +10040986: f000 f867 bl 10040a58 <.text_22> +1004098a: f000 f862 bl 10040a52 <.text_21> +1004098e: 2800 cmp r0, #0 +10040990: 60e0 str r0, [r4, #12] +10040992: d05a beq.n 10040a4a +10040994: f000 f863 bl 10040a5e <.text_23> +10040998: 68e1 ldr r1, [r4, #12] +1004099a: 2000 movs r0, #0 +1004099c: 5468 strb r0, [r5, r1] +1004099e: f8d6 9008 ldr.w r9, [r6, #8] +100409a2: 68f5 ldr r5, [r6, #12] +100409a4: f1b9 0f00 cmp.w r9, #0 +100409a8: d04f beq.n 10040a4a +100409aa: 6920 ldr r0, [r4, #16] +100409ac: b108 cbz r0, 100409b2 +100409ae: f000 f853 bl 10040a58 <.text_22> +100409b2: f000 f84e bl 10040a52 <.text_21> +100409b6: 2800 cmp r0, #0 +100409b8: 6120 str r0, [r4, #16] +100409ba: d046 beq.n 10040a4a +100409bc: f000 f84f bl 10040a5e <.text_23> +100409c0: 6921 ldr r1, [r4, #16] +100409c2: 2000 movs r0, #0 +100409c4: 5468 strb r0, [r5, r1] +100409c6: f8d6 9010 ldr.w r9, [r6, #16] +100409ca: 6975 ldr r5, [r6, #20] +100409cc: f1b9 0f00 cmp.w r9, #0 +100409d0: d03b beq.n 10040a4a +100409d2: 6960 ldr r0, [r4, #20] +100409d4: b108 cbz r0, 100409da +100409d6: f000 f83f bl 10040a58 <.text_22> +100409da: f000 f83a bl 10040a52 <.text_21> +100409de: 2800 cmp r0, #0 +100409e0: 6160 str r0, [r4, #20] +100409e2: d032 beq.n 10040a4a +100409e4: f000 f83b bl 10040a5e <.text_23> +100409e8: 6961 ldr r1, [r4, #20] +100409ea: 2000 movs r0, #0 +100409ec: 5468 strb r0, [r5, r1] +100409ee: f8d6 9018 ldr.w r9, [r6, #24] +100409f2: 69f5 ldr r5, [r6, #28] +100409f4: f1b9 0f00 cmp.w r9, #0 +100409f8: d027 beq.n 10040a4a +100409fa: 69a0 ldr r0, [r4, #24] +100409fc: b108 cbz r0, 10040a02 +100409fe: f000 f82b bl 10040a58 <.text_22> +10040a02: f000 f826 bl 10040a52 <.text_21> +10040a06: 61a0 str r0, [r4, #24] +10040a08: b1f8 cbz r0, 10040a4a +10040a0a: f000 f828 bl 10040a5e <.text_23> +10040a0e: 69a1 ldr r1, [r4, #24] +10040a10: 2000 movs r0, #0 +10040a12: 5468 strb r0, [r5, r1] +10040a14: f8d8 1030 ldr.w r1, [r8, #48] ; 0x30 +10040a18: b1b9 cbz r1, 10040a4a +10040a1a: 2208 movs r2, #8 +10040a1c: f104 001c add.w r0, r4, #28 +10040a20: f7cf fef5 bl 1001080e +10040a24: 6a75 ldr r5, [r6, #36] ; 0x24 +10040a26: 6a36 ldr r6, [r6, #32] +10040a28: b17e cbz r6, 10040a4a +10040a2a: 68a0 ldr r0, [r4, #8] +10040a2c: b108 cbz r0, 10040a32 +10040a2e: f000 f813 bl 10040a58 <.text_22> +10040a32: f000 f80e bl 10040a52 <.text_21> +10040a36: 60a0 str r0, [r4, #8] +10040a38: b138 cbz r0, 10040a4a +10040a3a: 462a mov r2, r5 +10040a3c: 4631 mov r1, r6 +10040a3e: f7cf fee6 bl 1001080e +10040a42: 68a1 ldr r1, [r4, #8] +10040a44: 2000 movs r0, #0 +10040a46: 5468 strb r0, [r5, r1] +10040a48: e001 b.n 10040a4e +10040a4a: f04f 30ff mov.w r0, #4294967295 +10040a4e: e8bd 83f2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, pc} + +10040a52 <.text_21>: +10040a52: 6839 ldr r1, [r7, #0] +10040a54: 1c68 adds r0, r5, #1 + +10040a56 <__iar_annotation$$tailcall>: +10040a56: 4708 bx r1 + +10040a58 <.text_22>: +10040a58: 687a ldr r2, [r7, #4] +10040a5a: 2100 movs r1, #0 + +10040a5c <__iar_annotation$$tailcall>: +10040a5c: 4710 bx r2 + +10040a5e <.text_23>: +10040a5e: 462a mov r2, r5 +10040a60: 4649 mov r1, r9 +10040a62: f7cf bed4 b.w 1001080e + +10040a66 : +10040a66: b538 push {r3, r4, r5, lr} +10040a68: 4604 mov r4, r0 +10040a6a: 4d10 ldr r5, [pc, #64] ; (10040aac <.text_29>) +10040a6c: 68a0 ldr r0, [r4, #8] +10040a6e: 686a ldr r2, [r5, #4] +10040a70: 2100 movs r1, #0 +10040a72: 4790 blx r2 +10040a74: 2000 movs r0, #0 +10040a76: 60a0 str r0, [r4, #8] +10040a78: 2100 movs r1, #0 +10040a7a: 68e0 ldr r0, [r4, #12] +10040a7c: 686a ldr r2, [r5, #4] +10040a7e: 4790 blx r2 +10040a80: 2000 movs r0, #0 +10040a82: 60e0 str r0, [r4, #12] +10040a84: 4601 mov r1, r0 +10040a86: 6920 ldr r0, [r4, #16] +10040a88: 686a ldr r2, [r5, #4] +10040a8a: 4790 blx r2 +10040a8c: 2000 movs r0, #0 +10040a8e: 6120 str r0, [r4, #16] +10040a90: 4601 mov r1, r0 +10040a92: 6960 ldr r0, [r4, #20] +10040a94: 686a ldr r2, [r5, #4] +10040a96: 4790 blx r2 +10040a98: 2000 movs r0, #0 +10040a9a: 6160 str r0, [r4, #20] +10040a9c: 4601 mov r1, r0 +10040a9e: 69a0 ldr r0, [r4, #24] +10040aa0: 686a ldr r2, [r5, #4] +10040aa2: 4790 blx r2 +10040aa4: 2000 movs r0, #0 +10040aa6: 61a0 str r0, [r4, #24] +10040aa8: bd31 pop {r0, r4, r5, pc} + ... + +10040aac <.text_29>: +10040aac: 100006d4 .word 0x100006d4 + +10040ab0 : +10040ab0: b510 push {r4, lr} +10040ab2: 460c mov r4, r1 +10040ab4: b128 cbz r0, 10040ac2 +10040ab6: 2102 movs r1, #2 +10040ab8: f7fc ff06 bl 1003d8c8 +10040abc: 0a21 lsrs r1, r4, #8 +10040abe: 7001 strb r1, [r0, #0] +10040ac0: 7044 strb r4, [r0, #1] +10040ac2: bd10 pop {r4, pc} + +10040ac4 : +10040ac4: b538 push {r3, r4, r5, lr} +10040ac6: 460c mov r4, r1 +10040ac8: 2800 cmp r0, #0 +10040aca: bf18 it ne +10040acc: 2c00 cmpne r4, #0 +10040ace: 4615 mov r5, r2 +10040ad0: d008 beq.n 10040ae4 +10040ad2: 4629 mov r1, r5 +10040ad4: f7fc fef8 bl 1003d8c8 +10040ad8: 462a mov r2, r5 +10040ada: 4621 mov r1, r4 +10040adc: e8bd 4038 ldmia.w sp!, {r3, r4, r5, lr} +10040ae0: f7cf be95 b.w 1001080e +10040ae4: bd31 pop {r0, r4, r5, pc} + +10040ae6 : +10040ae6: b5f0 push {r4, r5, r6, r7, lr} +10040ae8: 4604 mov r4, r0 +10040aea: 460d mov r5, r1 +10040aec: b08b sub sp, #44 ; 0x2c +10040aee: 2120 movs r1, #32 +10040af0: f104 0076 add.w r0, r4, #118 ; 0x76 +10040af4: f7fd f979 bl 1003ddea +10040af8: 2800 cmp r0, #0 +10040afa: d408 bmi.n 10040b0e +10040afc: f8d4 00dc ldr.w r0, [r4, #220] ; 0xdc +10040b00: 2800 cmp r0, #0 +10040b02: bf1e ittt ne +10040b04: f104 07dc addne.w r7, r4, #220 ; 0xdc +10040b08: 6878 ldrne r0, [r7, #4] +10040b0a: 2800 cmpne r0, #0 +10040b0c: d102 bne.n 10040b14 +10040b0e: f04f 30ff mov.w r0, #4294967295 +10040b12: e037 b.n 10040b84 +10040b14: f241 0114 movw r1, #4116 ; 0x1014 +10040b18: f000 f903 bl 10040d22 <.text_9+0x2> +10040b1c: f000 f900 bl 10040d20 <.text_9> +10040b20: f000 f839 bl 10040b96 <.text_6> +10040b24: f104 0176 add.w r1, r4, #118 ; 0x76 +10040b28: 9102 str r1, [sp, #8] +10040b2a: ae02 add r6, sp, #8 +10040b2c: 2110 movs r1, #16 +10040b2e: 9106 str r1, [sp, #24] +10040b30: 2210 movs r2, #16 +10040b32: f104 0156 add.w r1, r4, #86 ; 0x56 +10040b36: 6071 str r1, [r6, #4] +10040b38: a906 add r1, sp, #24 +10040b3a: 604a str r2, [r1, #4] +10040b3c: f8d4 20dc ldr.w r2, [r4, #220] ; 0xdc +10040b40: 6893 ldr r3, [r2, #8] +10040b42: 60b3 str r3, [r6, #8] +10040b44: 6852 ldr r2, [r2, #4] +10040b46: 608a str r2, [r1, #8] +10040b48: 687a ldr r2, [r7, #4] +10040b4a: 6893 ldr r3, [r2, #8] +10040b4c: 60f3 str r3, [r6, #12] +10040b4e: f104 07e4 add.w r7, r4, #228 ; 0xe4 +10040b52: 6852 ldr r2, [r2, #4] +10040b54: 9001 str r0, [sp, #4] +10040b56: 60ca str r2, [r1, #12] +10040b58: a806 add r0, sp, #24 +10040b5a: f000 f815 bl 10040b88 <.text_5> +10040b5e: f241 0115 movw r1, #4117 ; 0x1015 +10040b62: f000 f8de bl 10040d22 <.text_9+0x2> +10040b66: f000 f8db bl 10040d20 <.text_9> +10040b6a: f000 f814 bl 10040b96 <.text_6> +10040b6e: f104 0186 add.w r1, r4, #134 ; 0x86 +10040b72: 9102 str r1, [sp, #8] +10040b74: 9001 str r0, [sp, #4] +10040b76: f104 0166 add.w r1, r4, #102 ; 0x66 +10040b7a: a806 add r0, sp, #24 +10040b7c: 6071 str r1, [r6, #4] +10040b7e: f000 f803 bl 10040b88 <.text_5> +10040b82: 2000 movs r0, #0 +10040b84: b00b add sp, #44 ; 0x2c +10040b86: bdf0 pop {r4, r5, r6, r7, pc} + +10040b88 <.text_5>: +10040b88: 9000 str r0, [sp, #0] +10040b8a: ab02 add r3, sp, #8 +10040b8c: 2204 movs r2, #4 +10040b8e: 2120 movs r1, #32 +10040b90: 4638 mov r0, r7 +10040b92: f7fc bba7 b.w 1003d2e4 + +10040b96 <.text_6>: +10040b96: 2120 movs r1, #32 +10040b98: 4628 mov r0, r5 +10040b9a: f7fc be95 b.w 1003d8c8 + +10040b9e : +10040b9e: b538 push {r3, r4, r5, lr} +10040ba0: 4604 mov r4, r0 +10040ba2: 2110 movs r1, #16 +10040ba4: f104 0036 add.w r0, r4, #54 ; 0x36 +10040ba8: f7fd f91f bl 1003ddea +10040bac: 2800 cmp r0, #0 +10040bae: d405 bmi.n 10040bbc +10040bb0: f44f 7000 mov.w r0, #512 ; 0x200 +10040bb4: f7fc fe4c bl 1003d850 +10040bb8: 0005 movs r5, r0 +10040bba: d101 bne.n 10040bc0 +10040bbc: 2000 movs r0, #0 +10040bbe: bd32 pop {r1, r4, r5, pc} +10040bc0: f7fc ff77 bl 1003dab2 +10040bc4: 2800 cmp r0, #0 +10040bc6: d163 bne.n 10040c90 +10040bc8: 2104 movs r1, #4 +10040bca: 4628 mov r0, r5 +10040bcc: f7fc ff7e bl 1003dacc +10040bd0: 2800 cmp r0, #0 +10040bd2: d15d bne.n 10040c90 +10040bd4: f104 0110 add.w r1, r4, #16 +10040bd8: 4628 mov r0, r5 +10040bda: f7fc ff1e bl 1003da1a +10040bde: 2800 cmp r0, #0 +10040be0: d156 bne.n 10040c90 +10040be2: f104 0130 add.w r1, r4, #48 ; 0x30 +10040be6: 4628 mov r0, r5 +10040be8: f7fd f822 bl 1003dc30 +10040bec: 2800 cmp r0, #0 +10040bee: d14f bne.n 10040c90 +10040bf0: 4629 mov r1, r5 +10040bf2: 4620 mov r0, r4 +10040bf4: f7fc ff70 bl 1003dad8 +10040bf8: 2800 cmp r0, #0 +10040bfa: d149 bne.n 10040c90 +10040bfc: 4629 mov r1, r5 +10040bfe: 4620 mov r0, r4 +10040c00: f7fc feb2 bl 1003d968 +10040c04: 2800 cmp r0, #0 +10040c06: d143 bne.n 10040c90 +10040c08: 4629 mov r1, r5 +10040c0a: 4620 mov r0, r4 +10040c0c: f7fc ff85 bl 1003db1a +10040c10: 2800 cmp r0, #0 +10040c12: d13d bne.n 10040c90 +10040c14: 4629 mov r1, r5 +10040c16: 4620 mov r0, r4 +10040c18: f7fc ff89 bl 1003db2e +10040c1c: 2800 cmp r0, #0 +10040c1e: d137 bne.n 10040c90 +10040c20: 4629 mov r1, r5 +10040c22: 4620 mov r0, r4 +10040c24: f7fc ff97 bl 1003db56 +10040c28: 2800 cmp r0, #0 +10040c2a: d131 bne.n 10040c90 +10040c2c: f44f 510a mov.w r1, #8832 ; 0x2280 +10040c30: 4628 mov r0, r5 +10040c32: f7fc feec bl 1003da0e +10040c36: bb58 cbnz r0, 10040c90 +10040c38: f241 0144 movw r1, #4164 ; 0x1044 +10040c3c: f000 f871 bl 10040d22 <.text_9+0x2> +10040c40: 2101 movs r1, #1 +10040c42: f000 f86e bl 10040d22 <.text_9+0x2> +10040c46: 2101 movs r1, #1 +10040c48: f7ff ffa6 bl 10040b98 <.text_6+0x2> +10040c4c: 2101 movs r1, #1 +10040c4e: 7001 strb r1, [r0, #0] +10040c50: 4629 mov r1, r5 +10040c52: 6820 ldr r0, [r4, #0] +10040c54: 3044 adds r0, #68 ; 0x44 +10040c56: f7ff fe2c bl 100408b2 +10040c5a: b9c8 cbnz r0, 10040c90 +10040c5c: 6820 ldr r0, [r4, #0] +10040c5e: 4629 mov r1, r5 +10040c60: 3044 adds r0, #68 ; 0x44 +10040c62: f7ff fe6f bl 10040944 +10040c66: b998 cbnz r0, 10040c90 +10040c68: 4629 mov r1, r5 +10040c6a: 4620 mov r0, r4 +10040c6c: f7fc ff82 bl 1003db74 +10040c70: b970 cbnz r0, 10040c90 +10040c72: f8b4 1140 ldrh.w r1, [r4, #320] ; 0x140 +10040c76: 4628 mov r0, r5 +10040c78: f7fc fedb bl 1003da32 +10040c7c: b940 cbnz r0, 10040c90 +10040c7e: 2100 movs r1, #0 +10040c80: 4628 mov r0, r5 +10040c82: f7fc fee7 bl 1003da54 +10040c86: b918 cbnz r0, 10040c90 +10040c88: 4629 mov r1, r5 +10040c8a: f7ff fe41 bl 10040910 +10040c8e: b110 cbz r0, 10040c96 +10040c90: f000 f917 bl 10040ec2 <.text_17> +10040c94: e792 b.n 10040bbc +10040c96: 2001 movs r0, #1 +10040c98: 60e0 str r0, [r4, #12] +10040c9a: 4628 mov r0, r5 +10040c9c: bd32 pop {r1, r4, r5, pc} + +10040c9e : +10040c9e: b570 push {r4, r5, r6, lr} +10040ca0: 4604 mov r4, r0 +10040ca2: 20c8 movs r0, #200 ; 0xc8 +10040ca4: f7fc fdd4 bl 1003d850 +10040ca8: 0005 movs r5, r0 +10040caa: d033 beq.n 10040d14 +10040cac: f000 f905 bl 10040eba <.text_16> +10040cb0: 0006 movs r6, r0 +10040cb2: bf08 it eq +10040cb4: 4628 moveq r0, r5 +10040cb6: d02b beq.n 10040d10 +10040cb8: f7fc fefb bl 1003dab2 +10040cbc: bb28 cbnz r0, 10040d0a +10040cbe: 2109 movs r1, #9 +10040cc0: f000 f8f8 bl 10040eb4 <.text_15> +10040cc4: bb08 cbnz r0, 10040d0a +10040cc6: 4631 mov r1, r6 +10040cc8: 4620 mov r0, r4 +10040cca: f7fc ff14 bl 1003daf6 +10040cce: b9e0 cbnz r0, 10040d0a +10040cd0: f241 0116 movw r1, #4118 ; 0x1016 +10040cd4: f000 f825 bl 10040d22 <.text_9+0x2> +10040cd8: 2110 movs r1, #16 +10040cda: f000 f822 bl 10040d22 <.text_9+0x2> +10040cde: 2210 movs r2, #16 +10040ce0: f104 0176 add.w r1, r4, #118 ; 0x76 +10040ce4: 4628 mov r0, r5 +10040ce6: f7ff feed bl 10040ac4 +10040cea: 4629 mov r1, r5 +10040cec: 4620 mov r0, r4 +10040cee: f7fc ff4b bl 1003db88 +10040cf2: b950 cbnz r0, 10040d0a +10040cf4: f000 f8e8 bl 10040ec8 <.text_18> +10040cf8: b938 cbnz r0, 10040d0a +10040cfa: f000 f8d5 bl 10040ea8 <.text_14> +10040cfe: b920 cbnz r0, 10040d0a +10040d00: 4631 mov r1, r6 +10040d02: 4620 mov r0, r4 +10040d04: f7fc feac bl 1003da60 +10040d08: b130 cbz r0, 10040d18 +10040d0a: f000 f8da bl 10040ec2 <.text_17> +10040d0e: 4630 mov r0, r6 +10040d10: f7fc fdc5 bl 1003d89e +10040d14: 2000 movs r0, #0 +10040d16: bd70 pop {r4, r5, r6, pc} +10040d18: f000 f8d3 bl 10040ec2 <.text_17> +10040d1c: 2005 movs r0, #5 +10040d1e: e0c0 b.n 10040ea2 <.text_13> + +10040d20 <.text_9>: +10040d20: 2120 movs r1, #32 +10040d22: 4628 mov r0, r5 +10040d24: e6c4 b.n 10040ab0 + +10040d26 : +10040d26: b570 push {r4, r5, r6, lr} +10040d28: 4605 mov r5, r0 +10040d2a: 460c mov r4, r1 +10040d2c: f241 0145 movw r1, #4165 ; 0x1045 +10040d30: f000 f86a bl 10040e08 <.text_11+0x2> +10040d34: 6828 ldr r0, [r5, #0] +10040d36: 6c01 ldr r1, [r0, #64] ; 0x40 +10040d38: f000 f865 bl 10040e06 <.text_11> +10040d3c: 6828 ldr r0, [r5, #0] +10040d3e: 6c02 ldr r2, [r0, #64] ; 0x40 +10040d40: f100 0120 add.w r1, r0, #32 +10040d44: 4620 mov r0, r4 +10040d46: f7ff febd bl 10040ac4 +10040d4a: f44f 5181 mov.w r1, #4128 ; 0x1020 +10040d4e: f000 f85b bl 10040e08 <.text_11+0x2> +10040d52: 2106 movs r1, #6 +10040d54: f000 f858 bl 10040e08 <.text_11+0x2> +10040d58: 6828 ldr r0, [r5, #0] +10040d5a: f100 0144 add.w r1, r0, #68 ; 0x44 +10040d5e: 2206 movs r2, #6 +10040d60: 4620 mov r0, r4 +10040d62: f7ff feaf bl 10040ac4 +10040d66: 6828 ldr r0, [r5, #0] +10040d68: f8b0 60dc ldrh.w r6, [r0, #220] ; 0xdc +10040d6c: 06b0 lsls r0, r6, #26 +10040d6e: bf48 it mi +10040d70: 2620 movmi r6, #32 +10040d72: d40a bmi.n 10040d8a +10040d74: 07b0 lsls r0, r6, #30 +10040d76: bf48 it mi +10040d78: 2602 movmi r6, #2 +10040d7a: d406 bmi.n 10040d8a +10040d7c: 07f0 lsls r0, r6, #31 +10040d7e: bf48 it mi +10040d80: 2601 movmi r6, #1 +10040d82: d402 bmi.n 10040d8a +10040d84: 0770 lsls r0, r6, #29 +10040d86: bf48 it mi +10040d88: 2604 movmi r6, #4 +10040d8a: f241 0103 movw r1, #4099 ; 0x1003 +10040d8e: f000 f83b bl 10040e08 <.text_11+0x2> +10040d92: 2102 movs r1, #2 +10040d94: f000 f838 bl 10040e08 <.text_11+0x2> +10040d98: 4631 mov r1, r6 +10040d9a: f000 f835 bl 10040e08 <.text_11+0x2> +10040d9e: 6828 ldr r0, [r5, #0] +10040da0: f8b0 60da ldrh.w r6, [r0, #218] ; 0xda +10040da4: f890 00dc ldrb.w r0, [r0, #220] ; 0xdc +10040da8: 2122 movs r1, #34 ; 0x22 +10040daa: 4208 tst r0, r1 +10040dac: d007 beq.n 10040dbe +10040dae: 0730 lsls r0, r6, #28 +10040db0: bf48 it mi +10040db2: 2608 movmi r6, #8 +10040db4: d40a bmi.n 10040dcc +10040db6: 0770 lsls r0, r6, #29 +10040db8: d508 bpl.n 10040dcc +10040dba: 2604 movs r6, #4 +10040dbc: e006 b.n 10040dcc +10040dbe: 07b0 lsls r0, r6, #30 +10040dc0: bf48 it mi +10040dc2: 2602 movmi r6, #2 +10040dc4: d402 bmi.n 10040dcc +10040dc6: 07f0 lsls r0, r6, #31 +10040dc8: bf48 it mi +10040dca: 2601 movmi r6, #1 +10040dcc: f241 010f movw r1, #4111 ; 0x100f +10040dd0: f000 f81a bl 10040e08 <.text_11+0x2> +10040dd4: 2102 movs r1, #2 +10040dd6: f000 f817 bl 10040e08 <.text_11+0x2> +10040dda: 4631 mov r1, r6 +10040ddc: f000 f814 bl 10040e08 <.text_11+0x2> +10040de0: f241 0127 movw r1, #4135 ; 0x1027 +10040de4: f000 f810 bl 10040e08 <.text_11+0x2> +10040de8: 6828 ldr r0, [r5, #0] +10040dea: f8d0 10e4 ldr.w r1, [r0, #228] ; 0xe4 +10040dee: f000 f80a bl 10040e06 <.text_11> +10040df2: 6828 ldr r0, [r5, #0] +10040df4: f8d0 20e4 ldr.w r2, [r0, #228] ; 0xe4 +10040df8: f8d0 10e0 ldr.w r1, [r0, #224] ; 0xe0 +10040dfc: 4620 mov r0, r4 +10040dfe: f7ff fe61 bl 10040ac4 +10040e02: 2000 movs r0, #0 +10040e04: bd70 pop {r4, r5, r6, pc} + +10040e06 <.text_11>: +10040e06: b289 uxth r1, r1 +10040e08: 4620 mov r0, r4 +10040e0a: e651 b.n 10040ab0 + +10040e0c : +10040e0c: b570 push {r4, r5, r6, lr} +10040e0e: 4604 mov r4, r0 +10040e10: f44f 70fa mov.w r0, #500 ; 0x1f4 +10040e14: f7fc fd1c bl 1003d850 +10040e18: 0005 movs r5, r0 +10040e1a: d03d beq.n 10040e98 +10040e1c: f000 f84d bl 10040eba <.text_16> +10040e20: 0006 movs r6, r0 +10040e22: bf08 it eq +10040e24: 4628 moveq r0, r5 +10040e26: d035 beq.n 10040e94 +10040e28: f7fc fe43 bl 1003dab2 +10040e2c: 2800 cmp r0, #0 +10040e2e: d12e bne.n 10040e8e +10040e30: 210b movs r1, #11 +10040e32: f000 f83f bl 10040eb4 <.text_15> +10040e36: 2800 cmp r0, #0 +10040e38: d129 bne.n 10040e8e +10040e3a: 4631 mov r1, r6 +10040e3c: 4620 mov r0, r4 +10040e3e: f7fc fe5a bl 1003daf6 +10040e42: bb20 cbnz r0, 10040e8e +10040e44: f241 0117 movw r1, #4119 ; 0x1017 +10040e48: f7ff ff6b bl 10040d22 <.text_9+0x2> +10040e4c: 2110 movs r1, #16 +10040e4e: f7ff ff68 bl 10040d22 <.text_9+0x2> +10040e52: 2210 movs r2, #16 +10040e54: f104 0186 add.w r1, r4, #134 ; 0x86 +10040e58: 4628 mov r0, r5 +10040e5a: f7ff fe33 bl 10040ac4 +10040e5e: 6820 ldr r0, [r4, #0] +10040e60: 6800 ldr r0, [r0, #0] +10040e62: b120 cbz r0, 10040e6e +10040e64: 4629 mov r1, r5 +10040e66: 4620 mov r0, r4 +10040e68: f7ff ff5d bl 10040d26 +10040e6c: b978 cbnz r0, 10040e8e +10040e6e: 4629 mov r1, r5 +10040e70: 4620 mov r0, r4 +10040e72: f7fc fe89 bl 1003db88 +10040e76: b950 cbnz r0, 10040e8e +10040e78: f000 f826 bl 10040ec8 <.text_18> +10040e7c: b938 cbnz r0, 10040e8e +10040e7e: f000 f813 bl 10040ea8 <.text_14> +10040e82: b920 cbnz r0, 10040e8e +10040e84: 4631 mov r1, r6 +10040e86: 4620 mov r0, r4 +10040e88: f7fc fdea bl 1003da60 +10040e8c: b130 cbz r0, 10040e9c +10040e8e: f000 f818 bl 10040ec2 <.text_17> +10040e92: 4630 mov r0, r6 +10040e94: f7fc fd03 bl 1003d89e +10040e98: 2000 movs r0, #0 +10040e9a: bd70 pop {r4, r5, r6, pc} +10040e9c: f000 f811 bl 10040ec2 <.text_17> +10040ea0: 2007 movs r0, #7 + +10040ea2 <.text_13>: +10040ea2: 60e0 str r0, [r4, #12] +10040ea4: 4630 mov r0, r6 +10040ea6: bd70 pop {r4, r5, r6, pc} + +10040ea8 <.text_14>: +10040ea8: 2200 movs r2, #0 +10040eaa: 2300 movs r3, #0 +10040eac: 4611 mov r1, r2 +10040eae: 4630 mov r0, r6 +10040eb0: f7fc be0a b.w 1003dac8 + +10040eb4 <.text_15>: +10040eb4: 4630 mov r0, r6 +10040eb6: f7fc be09 b.w 1003dacc + +10040eba <.text_16>: +10040eba: f44f 707a mov.w r0, #1000 ; 0x3e8 +10040ebe: f7fc bcc7 b.w 1003d850 + +10040ec2 <.text_17>: +10040ec2: 4628 mov r0, r5 +10040ec4: f7fc bceb b.w 1003d89e + +10040ec8 <.text_18>: +10040ec8: 462a mov r2, r5 +10040eca: 4631 mov r1, r6 +10040ecc: 4620 mov r0, r4 +10040ece: f7fc be74 b.w 1003dbba + +10040ed2 : +10040ed2: b570 push {r4, r5, r6, lr} +10040ed4: 4605 mov r5, r0 +10040ed6: 460c mov r4, r1 +10040ed8: 68e8 ldr r0, [r5, #12] +10040eda: b160 cbz r0, 10040ef6 +10040edc: 2802 cmp r0, #2 +10040ede: d01c beq.n 10040f1a +10040ee0: 2804 cmp r0, #4 +10040ee2: d04b beq.n 10040f7c +10040ee4: 2806 cmp r0, #6 +10040ee6: d04d beq.n 10040f84 +10040ee8: 2808 cmp r0, #8 +10040eea: d04f beq.n 10040f8c +10040eec: 2809 cmp r0, #9 +10040eee: d05e beq.n 10040fae +10040ef0: 280c cmp r0, #12 +10040ef2: d056 beq.n 10040fa2 +10040ef4: e07c b.n 10040ff0 +10040ef6: 4628 mov r0, r5 +10040ef8: f7ff fe51 bl 10040b9e +10040efc: 4606 mov r6, r0 +10040efe: 2004 movs r0, #4 +10040f00: 6020 str r0, [r4, #0] +10040f02: b146 cbz r6, 10040f16 +10040f04: f8d5 0134 ldr.w r0, [r5, #308] ; 0x134 +10040f08: f7fc fcc9 bl 1003d89e +10040f0c: 4630 mov r0, r6 +10040f0e: f7fc fcb9 bl 1003d884 +10040f12: f8c5 0134 str.w r0, [r5, #308] ; 0x134 +10040f16: 4630 mov r0, r6 +10040f18: bd70 pop {r4, r5, r6, pc} +10040f1a: f505 709a add.w r0, r5, #308 ; 0x134 +10040f1e: 6841 ldr r1, [r0, #4] +10040f20: b341 cbz r1, 10040f74 +10040f22: 6882 ldr r2, [r0, #8] +10040f24: 4628 mov r0, r5 +10040f26: f7fc faad bl 1003d484 +10040f2a: f7ff ffc6 bl 10040eba <.text_16> +10040f2e: 0006 movs r6, r0 +10040f30: d020 beq.n 10040f74 +10040f32: f7fc fdbe bl 1003dab2 +10040f36: b9d0 cbnz r0, 10040f6e +10040f38: 2107 movs r1, #7 +10040f3a: f7ff ffbb bl 10040eb4 <.text_15> +10040f3e: b9b0 cbnz r0, 10040f6e +10040f40: 4631 mov r1, r6 +10040f42: 4628 mov r0, r5 +10040f44: f7fc fdd7 bl 1003daf6 +10040f48: b988 cbnz r0, 10040f6e +10040f4a: 4631 mov r1, r6 +10040f4c: 4628 mov r0, r5 +10040f4e: f7ff fdca bl 10040ae6 +10040f52: b960 cbnz r0, 10040f6e +10040f54: f7ff ffa8 bl 10040ea8 <.text_14> +10040f58: b948 cbnz r0, 10040f6e +10040f5a: 4631 mov r1, r6 +10040f5c: 4628 mov r0, r5 +10040f5e: f7fc fd7f bl 1003da60 +10040f62: b920 cbnz r0, 10040f6e +10040f64: 2003 movs r0, #3 +10040f66: 60e8 str r0, [r5, #12] +10040f68: 2004 movs r0, #4 +10040f6a: 6020 str r0, [r4, #0] +10040f6c: e7ca b.n 10040f04 +10040f6e: 4630 mov r0, r6 +10040f70: f7fc fc95 bl 1003d89e +10040f74: 2600 movs r6, #0 +10040f76: 2004 movs r0, #4 +10040f78: 6020 str r0, [r4, #0] +10040f7a: e7cc b.n 10040f16 +10040f7c: 4628 mov r0, r5 +10040f7e: f7ff fe8e bl 10040c9e +10040f82: e7bb b.n 10040efc +10040f84: 4628 mov r0, r5 +10040f86: f7ff ff41 bl 10040e0c +10040f8a: e7b7 b.n 10040efc +10040f8c: 4628 mov r0, r5 +10040f8e: f7fc fb35 bl 1003d5fc +10040f92: 4606 mov r6, r0 +10040f94: 2002 movs r0, #2 +10040f96: 2e00 cmp r6, #0 +10040f98: 6020 str r0, [r4, #0] +10040f9a: d0bc beq.n 10040f16 +10040f9c: 2001 movs r0, #1 +10040f9e: 60e8 str r0, [r5, #12] +10040fa0: e7b9 b.n 10040f16 +10040fa2: 4628 mov r0, r5 +10040fa4: f7fc fb4b bl 1003d63e +10040fa8: 4606 mov r6, r0 +10040faa: 2003 movs r0, #3 +10040fac: e7e4 b.n 10040f78 +10040fae: f7ff ff84 bl 10040eba <.text_16> +10040fb2: 0006 movs r6, r0 +10040fb4: d019 beq.n 10040fea +10040fb6: f7fc fd7c bl 1003dab2 +10040fba: b998 cbnz r0, 10040fe4 +10040fbc: 210f movs r1, #15 +10040fbe: f7ff ff79 bl 10040eb4 <.text_15> +10040fc2: b978 cbnz r0, 10040fe4 +10040fc4: 4631 mov r1, r6 +10040fc6: 4628 mov r0, r5 +10040fc8: f7fc fd86 bl 1003dad8 +10040fcc: b950 cbnz r0, 10040fe4 +10040fce: 4631 mov r1, r6 +10040fd0: 4628 mov r0, r5 +10040fd2: f7fc fd90 bl 1003daf6 +10040fd6: b928 cbnz r0, 10040fe4 +10040fd8: f7ff ff66 bl 10040ea8 <.text_14> +10040fdc: b910 cbnz r0, 10040fe4 +10040fde: 200b movs r0, #11 +10040fe0: 60e8 str r0, [r5, #12] +10040fe2: e003 b.n 10040fec +10040fe4: 4630 mov r0, r6 +10040fe6: f7fc fc5a bl 1003d89e +10040fea: 2600 movs r6, #0 +10040fec: 2005 movs r0, #5 +10040fee: e7c3 b.n 10040f78 +10040ff0: 2600 movs r6, #0 +10040ff2: e790 b.n 10040f16 + +10040ff4 : +10040ff4: b580 push {r7, lr} +10040ff6: b121 cbz r1, 10041002 +10040ff8: 2210 movs r2, #16 +10040ffa: 3036 adds r0, #54 ; 0x36 +10040ffc: f7cf fc11 bl 10010822 +10041000: b910 cbnz r0, 10041008 +10041002: f04f 30ff mov.w r0, #4294967295 +10041006: bd02 pop {r1, pc} +10041008: 2000 movs r0, #0 +1004100a: bd02 pop {r1, pc} + +1004100c : +1004100c: b510 push {r4, lr} +1004100e: b092 sub sp, #72 ; 0x48 +10041010: 4604 mov r4, r0 +10041012: b189 cbz r1, 10041038 +10041014: 2010 movs r0, #16 +10041016: 9002 str r0, [sp, #8] +10041018: 9106 str r1, [sp, #24] +1004101a: a806 add r0, sp, #24 +1004101c: f104 0156 add.w r1, r4, #86 ; 0x56 +10041020: f000 f82c bl 1004107c <.text_23> +10041024: 2220 movs r2, #32 +10041026: a90a add r1, sp, #40 ; 0x28 +10041028: f104 0096 add.w r0, r4, #150 ; 0x96 +1004102c: f7cf fbf9 bl 10010822 +10041030: b928 cbnz r0, 1004103e +10041032: 2012 movs r0, #18 +10041034: f8a4 0268 strh.w r0, [r4, #616] ; 0x268 +10041038: f04f 30ff mov.w r0, #4294967295 +1004103c: e000 b.n 10041040 +1004103e: 2000 movs r0, #0 +10041040: b012 add sp, #72 ; 0x48 +10041042: bd10 pop {r4, pc} + +10041044 : +10041044: b510 push {r4, lr} +10041046: b092 sub sp, #72 ; 0x48 +10041048: 4604 mov r4, r0 +1004104a: b189 cbz r1, 10041070 +1004104c: 2010 movs r0, #16 +1004104e: 9002 str r0, [sp, #8] +10041050: 9106 str r1, [sp, #24] +10041052: a806 add r0, sp, #24 +10041054: f104 0166 add.w r1, r4, #102 ; 0x66 +10041058: f000 f810 bl 1004107c <.text_23> +1004105c: 2220 movs r2, #32 +1004105e: a90a add r1, sp, #40 ; 0x28 +10041060: f104 00b6 add.w r0, r4, #182 ; 0xb6 +10041064: f7cf fbdd bl 10010822 +10041068: b928 cbnz r0, 10041076 +1004106a: 2012 movs r0, #18 +1004106c: f8a4 0268 strh.w r0, [r4, #616] ; 0x268 +10041070: f04f 30ff mov.w r0, #4294967295 +10041074: e000 b.n 10041078 +10041076: 2000 movs r0, #0 +10041078: b012 add sp, #72 ; 0x48 +1004107a: bd10 pop {r4, pc} + +1004107c <.text_23>: +1004107c: 6041 str r1, [r0, #4] +1004107e: 2210 movs r2, #16 +10041080: a902 add r1, sp, #8 +10041082: 604a str r2, [r1, #4] +10041084: f8d4 20dc ldr.w r2, [r4, #220] ; 0xdc +10041088: 6893 ldr r3, [r2, #8] +1004108a: 6083 str r3, [r0, #8] +1004108c: 6852 ldr r2, [r2, #4] +1004108e: 608a str r2, [r1, #8] +10041090: f104 02dc add.w r2, r4, #220 ; 0xdc +10041094: 6852 ldr r2, [r2, #4] +10041096: 6893 ldr r3, [r2, #8] +10041098: 60c3 str r3, [r0, #12] +1004109a: ab06 add r3, sp, #24 +1004109c: 6850 ldr r0, [r2, #4] +1004109e: 60c8 str r0, [r1, #12] +100410a0: 2204 movs r2, #4 +100410a2: a80a add r0, sp, #40 ; 0x28 +100410a4: 9001 str r0, [sp, #4] +100410a6: 2120 movs r1, #32 +100410a8: a802 add r0, sp, #8 +100410aa: 9000 str r0, [sp, #0] +100410ac: f104 00e4 add.w r0, r4, #228 ; 0xe4 +100410b0: f7fc b918 b.w 1003d2e4 + +100410b4 : +100410b4: b570 push {r4, r5, r6, lr} +100410b6: 460c mov r4, r1 +100410b8: 4615 mov r5, r2 +100410ba: f500 76ae add.w r6, r0, #348 ; 0x15c +100410be: f5ad 7d02 sub.w sp, sp, #520 ; 0x208 +100410c2: 2284 movs r2, #132 ; 0x84 +100410c4: 2100 movs r1, #0 +100410c6: 4630 mov r0, r6 +100410c8: f7cf fbb6 bl 10010838 +100410cc: 2001 movs r0, #1 +100410ce: 9003 str r0, [sp, #12] +100410d0: 9402 str r4, [sp, #8] +100410d2: 9501 str r5, [sp, #4] +100410d4: 9500 str r5, [sp, #0] +100410d6: a904 add r1, sp, #16 +100410d8: a800 add r0, sp, #0 +100410da: f000 fc37 bl 1004194c +100410de: 2800 cmp r0, #0 +100410e0: d404 bmi.n 100410ec +100410e2: 4631 mov r1, r6 +100410e4: a804 add r0, sp, #16 +100410e6: f000 fd20 bl 10041b2a +100410ea: b108 cbz r0, 100410f0 +100410ec: f04f 30ff mov.w r0, #4294967295 +100410f0: f50d 7d02 add.w sp, sp, #520 ; 0x208 +100410f4: bd70 pop {r4, r5, r6, pc} + +100410f6 : +100410f6: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +100410fa: ea5f 0903 movs.w r9, r3 +100410fe: 4604 mov r4, r0 +10041100: 460d mov r5, r1 +10041102: 4690 mov r8, r2 +10041104: d00e beq.n 10041124 +10041106: 9e08 ldr r6, [sp, #32] +10041108: 2700 movs r7, #0 +1004110a: f858 2027 ldr.w r2, [r8, r7, lsl #2] +1004110e: f855 1027 ldr.w r1, [r5, r7, lsl #2] +10041112: 4633 mov r3, r6 +10041114: 4620 mov r0, r4 +10041116: f7ff ffcd bl 100410b4 +1004111a: 2800 cmp r0, #0 +1004111c: bf18 it ne +1004111e: f110 0f02 cmnne.w r0, #2 +10041122: d002 beq.n 1004112a +10041124: f04f 30ff mov.w r0, #4294967295 +10041128: e003 b.n 10041132 +1004112a: 1c7f adds r7, r7, #1 +1004112c: 454f cmp r7, r9 +1004112e: d3ec bcc.n 1004110a +10041130: 2000 movs r0, #0 +10041132: e8bd 83f2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, pc} + +10041136 : +10041136: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +1004113a: 4604 mov r4, r0 +1004113c: 4688 mov r8, r1 +1004113e: 68e0 ldr r0, [r4, #12] +10041140: 2801 cmp r0, #1 +10041142: 4616 mov r6, r2 +10041144: d13a bne.n 100411bc +10041146: f106 070c add.w r7, r6, #12 +1004114a: 6879 ldr r1, [r7, #4] +1004114c: 2900 cmp r1, #0 +1004114e: d035 beq.n 100411bc +10041150: 2210 movs r2, #16 +10041152: f104 0046 add.w r0, r4, #70 ; 0x46 +10041156: f7cf fb5a bl 1001080e +1004115a: 68f1 ldr r1, [r6, #12] +1004115c: 4620 mov r0, r4 +1004115e: f7ff ff49 bl 10040ff4 +10041162: bb58 cbnz r0, 100411bc +10041164: 68b9 ldr r1, [r7, #8] +10041166: b349 cbz r1, 100411bc +10041168: 2210 movs r2, #16 +1004116a: f104 0020 add.w r0, r4, #32 +1004116e: f7cf fb4e bl 1001080e +10041172: f8d6 90d8 ldr.w r9, [r6, #216] ; 0xd8 +10041176: f8d6 50dc ldr.w r5, [r6, #220] ; 0xdc +1004117a: f1b9 0f00 cmp.w r9, #0 +1004117e: bf18 it ne +10041180: 2d00 cmpne r5, #0 +10041182: d01b beq.n 100411bc +10041184: f8d4 00e0 ldr.w r0, [r4, #224] ; 0xe0 +10041188: f7fc fb89 bl 1003d89e +1004118c: 4629 mov r1, r5 +1004118e: 4648 mov r0, r9 +10041190: f7fc fb6a bl 1003d868 +10041194: f8c4 00e0 str.w r0, [r4, #224] ; 0xe0 +10041198: b180 cbz r0, 100411bc +1004119a: 4620 mov r0, r4 +1004119c: f7fc f900 bl 1003d3a0 +100411a0: 2800 cmp r0, #0 +100411a2: d40b bmi.n 100411bc +100411a4: 6c39 ldr r1, [r7, #64] ; 0x40 +100411a6: 4642 mov r2, r8 +100411a8: 4620 mov r0, r4 +100411aa: f000 fc15 bl 100419d8 +100411ae: b928 cbnz r0, 100411bc +100411b0: 4631 mov r1, r6 +100411b2: f504 70f0 add.w r0, r4, #480 ; 0x1e0 +100411b6: f7ff fbd7 bl 10040968 +100411ba: b108 cbz r0, 100411c0 +100411bc: 200c movs r0, #12 +100411be: e000 b.n 100411c2 +100411c0: 2002 movs r0, #2 +100411c2: 60e0 str r0, [r4, #12] +100411c4: 2001 movs r0, #1 +100411c6: e8bd 83f2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, pc} + +100411ca : +100411ca: b5f0 push {r4, r5, r6, r7, lr} +100411cc: 4604 mov r4, r0 +100411ce: b0fd sub sp, #500 ; 0x1f4 +100411d0: 68e0 ldr r0, [r4, #12] +100411d2: 2803 cmp r0, #3 +100411d4: 460d mov r5, r1 +100411d6: 4616 mov r6, r2 +100411d8: d117 bne.n 1004120a +100411da: f000 f87e bl 100412da <.text_31> +100411de: b9a0 cbnz r0, 1004120a +100411e0: f000 f886 bl 100412f0 <.text_33> +100411e4: b988 cbnz r0, 1004120a +100411e6: 6cf9 ldr r1, [r7, #76] ; 0x4c +100411e8: b179 cbz r1, 1004120a +100411ea: 2220 movs r2, #32 +100411ec: f104 0096 add.w r0, r4, #150 ; 0x96 +100411f0: f7cf fb0d bl 1001080e +100411f4: 6d39 ldr r1, [r7, #80] ; 0x50 +100411f6: b141 cbz r1, 1004120a +100411f8: 2220 movs r2, #32 +100411fa: f104 00b6 add.w r0, r4, #182 ; 0xb6 +100411fe: f7cf fb06 bl 1001080e +10041202: f000 f86e bl 100412e2 <.text_32> +10041206: 0005 movs r5, r0 +10041208: d101 bne.n 1004120e +1004120a: 200c movs r0, #12 +1004120c: e01c b.n 10041248 +1004120e: 6870 ldr r0, [r6, #4] +10041210: 2800 cmp r0, #0 +10041212: bf14 ite ne +10041214: 2101 movne r1, #1 +10041216: 2100 moveq r1, #0 +10041218: 4628 mov r0, r5 +1004121a: f000 ffba bl 10042192 +1004121e: 2800 cmp r0, #0 +10041220: d40c bmi.n 1004123c +10041222: f000 f819 bl 10041258 <.text_29> +10041226: 2800 cmp r0, #0 +10041228: d408 bmi.n 1004123c +1004122a: 9a1c ldr r2, [sp, #112] ; 0x70 +1004122c: f000 f810 bl 10041250 <.text_28> +10041230: b920 cbnz r0, 1004123c +10041232: 9918 ldr r1, [sp, #96] ; 0x60 +10041234: 4620 mov r0, r4 +10041236: f7ff fee9 bl 1004100c +1004123a: b110 cbz r0, 10041242 +1004123c: f7ff fe41 bl 10040ec2 <.text_17> +10041240: e7e3 b.n 1004120a +10041242: f7ff fe3e bl 10040ec2 <.text_17> +10041246: 2004 movs r0, #4 +10041248: 60e0 str r0, [r4, #12] +1004124a: b07d add sp, #500 ; 0x1f4 +1004124c: 2001 movs r0, #1 +1004124e: bdf0 pop {r4, r5, r6, r7, pc} + +10041250 <.text_28>: +10041250: 4629 mov r1, r5 +10041252: 4620 mov r0, r4 +10041254: f000 bbe7 b.w 10041a26 + +10041258 <.text_29>: +10041258: a900 add r1, sp, #0 +1004125a: 4628 mov r0, r5 +1004125c: f000 bb76 b.w 1004194c + +10041260 : +10041260: b5f0 push {r4, r5, r6, r7, lr} +10041262: 4604 mov r4, r0 +10041264: b0ff sub sp, #508 ; 0x1fc +10041266: 68e0 ldr r0, [r4, #12] +10041268: 2807 cmp r0, #7 +1004126a: 460d mov r5, r1 +1004126c: 4616 mov r6, r2 +1004126e: d109 bne.n 10041284 +10041270: f000 f833 bl 100412da <.text_31> +10041274: b930 cbnz r0, 10041284 +10041276: f000 f83b bl 100412f0 <.text_33> +1004127a: b918 cbnz r0, 10041284 +1004127c: f000 f831 bl 100412e2 <.text_32> +10041280: 0005 movs r5, r0 +10041282: d101 bne.n 10041288 +10041284: 200c movs r0, #12 +10041286: e024 b.n 100412d2 +10041288: 6870 ldr r0, [r6, #4] +1004128a: 2800 cmp r0, #0 +1004128c: bf14 ite ne +1004128e: 2201 movne r2, #1 +10041290: 2200 moveq r2, #0 +10041292: 2100 movs r1, #0 +10041294: 4628 mov r0, r5 +10041296: f001 f80b bl 100422b0 +1004129a: 2800 cmp r0, #0 +1004129c: d413 bmi.n 100412c6 +1004129e: a901 add r1, sp, #4 +100412a0: f7ff ffdb bl 1004125a <.text_29+0x2> +100412a4: 2800 cmp r0, #0 +100412a6: d40e bmi.n 100412c6 +100412a8: 9a1d ldr r2, [sp, #116] ; 0x74 +100412aa: f7ff ffd1 bl 10041250 <.text_28> +100412ae: b950 cbnz r0, 100412c6 +100412b0: 6870 ldr r0, [r6, #4] +100412b2: b100 cbz r0, 100412b6 +100412b4: 2001 movs r0, #1 +100412b6: 9000 str r0, [sp, #0] +100412b8: aa53 add r2, sp, #332 ; 0x14c +100412ba: 9b5d ldr r3, [sp, #372] ; 0x174 +100412bc: a949 add r1, sp, #292 ; 0x124 +100412be: 4620 mov r0, r4 +100412c0: f7ff ff19 bl 100410f6 +100412c4: b110 cbz r0, 100412cc +100412c6: f7ff fdfc bl 10040ec2 <.text_17> +100412ca: e7db b.n 10041284 +100412cc: f7ff fdf9 bl 10040ec2 <.text_17> +100412d0: 2009 movs r0, #9 +100412d2: 60e0 str r0, [r4, #12] +100412d4: b07f add sp, #508 ; 0x1fc +100412d6: 2001 movs r0, #1 +100412d8: bdf0 pop {r4, r5, r6, r7, pc} + +100412da <.text_31>: +100412da: 1d37 adds r7, r6, #4 +100412dc: 4620 mov r0, r4 +100412de: 68b9 ldr r1, [r7, #8] +100412e0: e688 b.n 10040ff4 + +100412e2 <.text_32>: +100412e2: f8d6 20e4 ldr.w r2, [r6, #228] ; 0xe4 +100412e6: f8d6 10e0 ldr.w r1, [r6, #224] ; 0xe0 +100412ea: 4620 mov r0, r4 +100412ec: f7fc b8f3 b.w 1003d4d6 + +100412f0 <.text_33>: +100412f0: 6cb9 ldr r1, [r7, #72] ; 0x48 +100412f2: 462a mov r2, r5 +100412f4: 4620 mov r0, r4 +100412f6: f000 bb6f b.w 100419d8 + +100412fa : +100412fa: e92d 41f0 stmdb sp!, {r4, r5, r6, r7, r8, lr} +100412fe: f5ad 7d7a sub.w sp, sp, #1000 ; 0x3e8 +10041302: 4604 mov r4, r0 +10041304: 460d mov r5, r1 +10041306: 2601 movs r6, #1 +10041308: a97d add r1, sp, #500 ; 0x1f4 +1004130a: f7ff ffa6 bl 1004125a <.text_29+0x2> +1004130e: 2800 cmp r0, #0 +10041310: d418 bmi.n 10041344 +10041312: af7e add r7, sp, #504 ; 0x1f8 +10041314: 68b9 ldr r1, [r7, #8] +10041316: 2900 cmp r1, #0 +10041318: d014 beq.n 10041344 +1004131a: f000 f8f4 bl 10041506 <.text_37> +1004131e: 2800 cmp r0, #0 +10041320: d010 beq.n 10041344 +10041322: 6878 ldr r0, [r7, #4] +10041324: b918 cbnz r0, 1004132e +10041326: 200c movs r0, #12 +10041328: 60e0 str r0, [r4, #12] +1004132a: 2001 movs r0, #1 +1004132c: e026 b.n 1004137c +1004132e: 7800 ldrb r0, [r0, #0] +10041330: 2805 cmp r0, #5 +10041332: d008 beq.n 10041346 +10041334: 2806 cmp r0, #6 +10041336: d025 beq.n 10041384 +10041338: 2808 cmp r0, #8 +1004133a: d030 beq.n 1004139e +1004133c: 280a cmp r0, #10 +1004133e: d039 beq.n 100413b4 +10041340: 280c cmp r0, #12 +10041342: d074 beq.n 1004142e +10041344: e07e b.n 10041444 +10041346: 4628 mov r0, r5 +10041348: f000 fdfd bl 10041f46 +1004134c: 2800 cmp r0, #0 +1004134e: d479 bmi.n 10041444 +10041350: aa7d add r2, sp, #500 ; 0x1f4 +10041352: 4629 mov r1, r5 +10041354: 4620 mov r0, r4 +10041356: f7ff feee bl 10041136 +1004135a: 4606 mov r6, r0 +1004135c: 2e01 cmp r6, #1 +1004135e: d10c bne.n 1004137a +10041360: 6878 ldr r0, [r7, #4] +10041362: 7800 ldrb r0, [r0, #0] +10041364: 2806 cmp r0, #6 +10041366: d008 beq.n 1004137a +10041368: f8d4 0134 ldr.w r0, [r4, #308] ; 0x134 +1004136c: f7fc fa97 bl 1003d89e +10041370: 4628 mov r0, r5 +10041372: f7fc fa87 bl 1003d884 +10041376: f8c4 0134 str.w r0, [r4, #308] ; 0x134 +1004137a: 4630 mov r0, r6 +1004137c: f50d 7d7a add.w sp, sp, #1000 ; 0x3e8 +10041380: e8bd 81f0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} +10041384: 4628 mov r0, r5 +10041386: f000 fe65 bl 10042054 +1004138a: 2800 cmp r0, #0 +1004138c: d45a bmi.n 10041444 +1004138e: 68e0 ldr r0, [r4, #12] +10041390: 2801 cmp r0, #1 +10041392: d002 beq.n 1004139a +10041394: 200c movs r0, #12 +10041396: 60e0 str r0, [r4, #12] +10041398: e7e2 b.n 10041360 +1004139a: 2008 movs r0, #8 +1004139c: e7fb b.n 10041396 +1004139e: 4628 mov r0, r5 +100413a0: f000 fecc bl 1004213c +100413a4: 2800 cmp r0, #0 +100413a6: d44d bmi.n 10041444 +100413a8: aa7d add r2, sp, #500 ; 0x1f4 +100413aa: 4629 mov r1, r5 +100413ac: 4620 mov r0, r4 +100413ae: f7ff ff0c bl 100411ca +100413b2: e7d2 b.n 1004135a +100413b4: 4628 mov r0, r5 +100413b6: f000 ff12 bl 100421de +100413ba: 2800 cmp r0, #0 +100413bc: d442 bmi.n 10041444 +100413be: 68e0 ldr r0, [r4, #12] +100413c0: 2805 cmp r0, #5 +100413c2: d1e7 bne.n 10041394 +100413c4: 68b9 ldr r1, [r7, #8] +100413c6: 4620 mov r0, r4 +100413c8: f7ff fe14 bl 10040ff4 +100413cc: 2800 cmp r0, #0 +100413ce: d1e1 bne.n 10041394 +100413d0: f7ff ff8e bl 100412f0 <.text_33> +100413d4: 2800 cmp r0, #0 +100413d6: d1dd bne.n 10041394 +100413d8: 9ab6 ldr r2, [sp, #728] ; 0x2d8 +100413da: 99b5 ldr r1, [sp, #724] ; 0x2d4 +100413dc: 4620 mov r0, r4 +100413de: f7fc f87a bl 1003d4d6 +100413e2: ea5f 0800 movs.w r8, r0 +100413e6: d0d5 beq.n 10041394 +100413e8: 987e ldr r0, [sp, #504] ; 0x1f8 +100413ea: 2800 cmp r0, #0 +100413ec: bf14 ite ne +100413ee: 2101 movne r1, #1 +100413f0: 2100 moveq r1, #0 +100413f2: 4640 mov r0, r8 +100413f4: f000 ff23 bl 1004223e +100413f8: 2800 cmp r0, #0 +100413fa: d414 bmi.n 10041426 +100413fc: a900 add r1, sp, #0 +100413fe: 4640 mov r0, r8 +10041400: f000 faa4 bl 1004194c +10041404: 2800 cmp r0, #0 +10041406: d40e bmi.n 10041426 +10041408: 9a1c ldr r2, [sp, #112] ; 0x70 +1004140a: 4641 mov r1, r8 +1004140c: f7ff ff21 bl 10041252 <.text_28+0x2> +10041410: b948 cbnz r0, 10041426 +10041412: 9919 ldr r1, [sp, #100] ; 0x64 +10041414: 4620 mov r0, r4 +10041416: f7ff fe15 bl 10041044 +1004141a: b920 cbnz r0, 10041426 +1004141c: 4640 mov r0, r8 +1004141e: f7fc fa3e bl 1003d89e +10041422: 2006 movs r0, #6 +10041424: e7b7 b.n 10041396 +10041426: 4640 mov r0, r8 +10041428: f7fc fa39 bl 1003d89e +1004142c: e7b2 b.n 10041394 +1004142e: 4628 mov r0, r5 +10041430: f000 ff19 bl 10042266 +10041434: 2800 cmp r0, #0 +10041436: d405 bmi.n 10041444 +10041438: aa7d add r2, sp, #500 ; 0x1f4 +1004143a: 4629 mov r1, r5 +1004143c: 4620 mov r0, r4 +1004143e: f7ff ff0f bl 10041260 +10041442: e78a b.n 1004135a +10041444: 2002 movs r0, #2 +10041446: e799 b.n 1004137c + +10041448 : +10041448: b530 push {r4, r5, lr} +1004144a: 2900 cmp r1, #0 +1004144c: b0fd sub sp, #500 ; 0x1f4 +1004144e: 4604 mov r4, r0 +10041450: 4615 mov r5, r2 +10041452: d10f bne.n 10041474 +10041454: f7ff ff00 bl 10041258 <.text_29> +10041458: b998 cbnz r0, 10041482 +1004145a: 9802 ldr r0, [sp, #8] +1004145c: b188 cbz r0, 10041482 +1004145e: 7800 ldrb r0, [r0, #0] +10041460: 280d cmp r0, #13 +10041462: d013 beq.n 1004148c +10041464: 280e cmp r0, #14 +10041466: d10c bne.n 10041482 +10041468: 4628 mov r0, r5 +1004146a: f000 ff89 bl 10042380 +1004146e: 2800 cmp r0, #0 +10041470: d527 bpl.n 100414c2 +10041472: e040 b.n 100414f6 +10041474: d005 beq.n 10041482 +10041476: 2902 cmp r1, #2 +10041478: d008 beq.n 1004148c +1004147a: 2903 cmp r1, #3 +1004147c: d0f4 beq.n 10041468 +1004147e: 2904 cmp r1, #4 +10041480: d139 bne.n 100414f6 +10041482: 4629 mov r1, r5 +10041484: 4620 mov r0, r4 +10041486: f7ff ff38 bl 100412fa +1004148a: e035 b.n 100414f8 +1004148c: 4628 mov r0, r5 +1004148e: f000 ff54 bl 1004233a +10041492: 2800 cmp r0, #0 +10041494: d42f bmi.n 100414f6 +10041496: f7ff fedf bl 10041258 <.text_29> +1004149a: 2800 cmp r0, #0 +1004149c: d42b bmi.n 100414f6 +1004149e: 9802 ldr r0, [sp, #8] +100414a0: 2800 cmp r0, #0 +100414a2: d028 beq.n 100414f6 +100414a4: 7800 ldrb r0, [r0, #0] +100414a6: 280d cmp r0, #13 +100414a8: d125 bne.n 100414f6 +100414aa: 9904 ldr r1, [sp, #16] +100414ac: b319 cbz r1, 100414f6 +100414ae: f000 f825 bl 100414fc <.text_36> +100414b2: 2800 cmp r0, #0 +100414b4: bf1c itt ne +100414b6: 9903 ldrne r1, [sp, #12] +100414b8: 2900 cmpne r1, #0 +100414ba: d01c beq.n 100414f6 +100414bc: f000 f823 bl 10041506 <.text_37> +100414c0: e019 b.n 100414f6 +100414c2: f7ff fec9 bl 10041258 <.text_29> +100414c6: 2800 cmp r0, #0 +100414c8: d415 bmi.n 100414f6 +100414ca: 9802 ldr r0, [sp, #8] +100414cc: b198 cbz r0, 100414f6 +100414ce: 7800 ldrb r0, [r0, #0] +100414d0: 280e cmp r0, #14 +100414d2: d110 bne.n 100414f6 +100414d4: 9904 ldr r1, [sp, #16] +100414d6: b171 cbz r1, 100414f6 +100414d8: f000 f810 bl 100414fc <.text_36> +100414dc: 2800 cmp r0, #0 +100414de: bf1c itt ne +100414e0: 9903 ldrne r1, [sp, #12] +100414e2: 2900 cmpne r1, #0 +100414e4: d007 beq.n 100414f6 +100414e6: f000 f80e bl 10041506 <.text_37> +100414ea: 2800 cmp r0, #0 +100414ec: bf1f itttt ne +100414ee: 980f ldrne r0, [sp, #60] ; 0x3c +100414f0: 2800 cmpne r0, #0 +100414f2: 200c movne r0, #12 +100414f4: 60e0 strne r0, [r4, #12] +100414f6: 2002 movs r0, #2 +100414f8: b07d add sp, #500 ; 0x1f4 +100414fa: bd30 pop {r4, r5, pc} + +100414fc <.text_36>: +100414fc: 2210 movs r2, #16 +100414fe: f104 0046 add.w r0, r4, #70 ; 0x46 +10041502: f7cf b98e b.w 10010822 + +10041506 <.text_37>: +10041506: 2210 movs r2, #16 +10041508: f104 0036 add.w r0, r4, #54 ; 0x36 +1004150c: f7cf b989 b.w 10010822 + +10041510 : +10041510: b5f0 push {r4, r5, r6, r7, lr} +10041512: 1852 adds r2, r2, r1 +10041514: f100 03a0 add.w r3, r0, #160 ; 0xa0 +10041518: e004 b.n 10041524 +1004151a: 2d01 cmp r5, #1 +1004151c: d123 bne.n 10041566 +1004151e: f8c0 10a0 str.w r1, [r0, #160] ; 0xa0 +10041522: 4631 mov r1, r6 +10041524: 1c8c adds r4, r1, #2 +10041526: 4294 cmp r4, r2 +10041528: d220 bcs.n 1004156c +1004152a: f811 7b01 ldrb.w r7, [r1], #1 +1004152e: f811 5b01 ldrb.w r5, [r1], #1 +10041532: 186e adds r6, r5, r1 +10041534: 42b2 cmp r2, r6 +10041536: d319 bcc.n 1004156c +10041538: b18f cbz r7, 1004155e +1004153a: 2f02 cmp r7, #2 +1004153c: d007 beq.n 1004154e +1004153e: d30b bcc.n 10041558 +10041540: 2f04 cmp r7, #4 +10041542: d0ea beq.n 1004151a +10041544: d2ed bcs.n 10041522 +10041546: 2d01 cmp r5, #1 +10041548: bf08 it eq +1004154a: 6099 streq r1, [r3, #8] +1004154c: e002 b.n 10041554 +1004154e: 2d01 cmp r5, #1 +10041550: bf08 it eq +10041552: 6059 streq r1, [r3, #4] +10041554: d0e5 beq.n 10041522 +10041556: e006 b.n 10041566 +10041558: 6699 str r1, [r3, #104] ; 0x68 +1004155a: 66dd str r5, [r3, #108] ; 0x6c +1004155c: e7e1 b.n 10041522 +1004155e: 2d01 cmp r5, #1 +10041560: bf08 it eq +10041562: 6041 streq r1, [r0, #4] +10041564: d0dd beq.n 10041522 +10041566: f04f 30ff mov.w r0, #4294967295 +1004156a: bdf0 pop {r4, r5, r6, r7, pc} +1004156c: 2000 movs r0, #0 +1004156e: bdf0 pop {r4, r5, r6, r7, pc} + +10041570 : +10041570: b558 push {r3, r4, r6, lr} +10041572: f241 0601 movw r6, #4097 ; 0x1001 +10041576: 1b89 subs r1, r1, r6 +10041578: 4614 mov r4, r2 +1004157a: f000 81de beq.w 1004193a +1004157e: 1e49 subs r1, r1, #1 +10041580: f000 80ce beq.w 10041720 +10041584: 1e49 subs r1, r1, #1 +10041586: f000 8112 beq.w 100417ae +1004158a: 1e49 subs r1, r1, #1 +1004158c: f000 80ac beq.w 100416e8 +10041590: 1e49 subs r1, r1, #1 +10041592: f000 80e3 beq.w 1004175c +10041596: 1ec9 subs r1, r1, #3 +10041598: f000 80b2 beq.w 10041700 +1004159c: 1e49 subs r1, r1, #1 +1004159e: f000 80c3 beq.w 10041728 +100415a2: 1f09 subs r1, r1, #4 +100415a4: f000 80a8 beq.w 100416f8 +100415a8: 1e49 subs r1, r1, #1 +100415aa: f000 8152 beq.w 10041852 +100415ae: 1e49 subs r1, r1, #1 +100415b0: f000 8101 beq.w 100417b6 +100415b4: 1e49 subs r1, r1, #1 +100415b6: f000 809b beq.w 100416f0 +100415ba: 1e49 subs r1, r1, #1 +100415bc: f000 813a beq.w 10041834 +100415c0: 1e49 subs r1, r1, #1 +100415c2: f000 80b5 beq.w 10041730 +100415c6: 1e89 subs r1, r1, #2 +100415c8: f000 80d4 beq.w 10041774 +100415cc: 1e49 subs r1, r1, #1 +100415ce: f000 80d5 beq.w 1004177c +100415d2: 1e49 subs r1, r1, #1 +100415d4: f000 80df beq.w 10041796 +100415d8: 1e49 subs r1, r1, #1 +100415da: f000 80e0 beq.w 1004179e +100415de: 1e49 subs r1, r1, #1 +100415e0: f000 8132 beq.w 10041848 +100415e4: 1e89 subs r1, r1, #2 +100415e6: d06f beq.n 100416c8 +100415e8: 1f09 subs r1, r1, #4 +100415ea: f000 80dc beq.w 100417a6 +100415ee: 1e89 subs r1, r1, #2 +100415f0: f000 80ee beq.w 100417d0 +100415f4: 1e49 subs r1, r1, #1 +100415f6: f000 8109 beq.w 1004180c +100415fa: 1e49 subs r1, r1, #1 +100415fc: d060 beq.n 100416c0 +100415fe: 1e49 subs r1, r1, #1 +10041600: f000 8109 beq.w 10041816 +10041604: 1e49 subs r1, r1, #1 +10041606: f000 810b beq.w 10041820 +1004160a: 1e89 subs r1, r1, #2 +1004160c: f000 80d7 beq.w 100417be +10041610: 1e49 subs r1, r1, #1 +10041612: f000 8137 beq.w 10041884 +10041616: 1e49 subs r1, r1, #1 +10041618: f000 80d5 beq.w 100417c6 +1004161c: 1f09 subs r1, r1, #4 +1004161e: f000 808b beq.w 10041738 +10041622: 1e49 subs r1, r1, #1 +10041624: f000 8092 beq.w 1004174c +10041628: 1f49 subs r1, r1, #5 +1004162a: f000 8108 beq.w 1004183e +1004162e: 1fc9 subs r1, r1, #7 +10041630: d04e beq.n 100416d0 +10041632: 1e49 subs r1, r1, #1 +10041634: f000 80e0 beq.w 100417f8 +10041638: 1e49 subs r1, r1, #1 +1004163a: f000 80e2 beq.w 10041802 +1004163e: 1e49 subs r1, r1, #1 +10041640: d06a beq.n 10041718 +10041642: 1e49 subs r1, r1, #1 +10041644: f000 808e beq.w 10041764 +10041648: 1e49 subs r1, r1, #1 +1004164a: f000 808f beq.w 1004176c +1004164e: 1e49 subs r1, r1, #1 +10041650: f000 8098 beq.w 10041784 +10041654: 1e49 subs r1, r1, #1 +10041656: f000 809a beq.w 1004178e +1004165a: 1e49 subs r1, r1, #1 +1004165c: f000 80c7 beq.w 100417ee +10041660: 1e49 subs r1, r1, #1 +10041662: f000 80e2 beq.w 1004182a +10041666: 1e89 subs r1, r1, #2 +10041668: f000 8074 beq.w 10041754 +1004166c: 1e49 subs r1, r1, #1 +1004166e: f000 8104 beq.w 1004187a +10041672: 1e89 subs r1, r1, #2 +10041674: d030 beq.n 100416d8 +10041676: 1e49 subs r1, r1, #1 +10041678: d032 beq.n 100416e0 +1004167a: 1e49 subs r1, r1, #1 +1004167c: f000 8131 beq.w 100418e2 +10041680: 1e49 subs r1, r1, #1 +10041682: d019 beq.n 100416b8 +10041684: 1ec9 subs r1, r1, #3 +10041686: f000 8107 beq.w 10041898 +1004168a: 1f89 subs r1, r1, #6 +1004168c: d03c beq.n 10041708 +1004168e: 1e49 subs r1, r1, #1 +10041690: d03e beq.n 10041710 +10041692: 1e49 subs r1, r1, #1 +10041694: f000 811a beq.w 100418cc +10041698: 1e89 subs r1, r1, #2 +1004169a: f000 8102 beq.w 100418a2 +1004169e: 1e89 subs r1, r1, #2 +100416a0: f000 80f5 beq.w 1004188e +100416a4: 3908 subs r1, #8 +100416a6: f000 8098 beq.w 100417da +100416aa: 1e49 subs r1, r1, #1 +100416ac: f000 809a beq.w 100417e4 +100416b0: 3908 subs r1, #8 +100416b2: f000 80fb beq.w 100418ac +100416b6: e147 b.n 10041948 +100416b8: 2b01 cmp r3, #1 +100416ba: d164 bne.n 10041786 +100416bc: 6004 str r4, [r0, #0] +100416be: e143 b.n 10041948 +100416c0: 2b01 cmp r3, #1 +100416c2: d160 bne.n 10041786 +100416c4: 6084 str r4, [r0, #8] +100416c6: e13f b.n 10041948 +100416c8: 2b10 cmp r3, #16 +100416ca: d15c bne.n 10041786 +100416cc: 60c4 str r4, [r0, #12] +100416ce: e13b b.n 10041948 +100416d0: 2b10 cmp r3, #16 +100416d2: d158 bne.n 10041786 +100416d4: 6104 str r4, [r0, #16] +100416d6: e137 b.n 10041948 +100416d8: 2b10 cmp r3, #16 +100416da: d154 bne.n 10041786 +100416dc: 6184 str r4, [r0, #24] +100416de: e133 b.n 10041948 +100416e0: 2b10 cmp r3, #16 +100416e2: d150 bne.n 10041786 +100416e4: 6144 str r4, [r0, #20] +100416e6: e12f b.n 10041948 +100416e8: 2b02 cmp r3, #2 +100416ea: d14c bne.n 10041786 +100416ec: 61c4 str r4, [r0, #28] +100416ee: e12b b.n 10041948 +100416f0: 2b02 cmp r3, #2 +100416f2: d148 bne.n 10041786 +100416f4: 6204 str r4, [r0, #32] +100416f6: e127 b.n 10041948 +100416f8: 2b01 cmp r3, #1 +100416fa: d144 bne.n 10041786 +100416fc: 6244 str r4, [r0, #36] ; 0x24 +100416fe: e123 b.n 10041948 +10041700: 2b02 cmp r3, #2 +10041702: d140 bne.n 10041786 +10041704: 6284 str r4, [r0, #40] ; 0x28 +10041706: e11f b.n 10041948 +10041708: 2b02 cmp r3, #2 +1004170a: d13c bne.n 10041786 +1004170c: 62c4 str r4, [r0, #44] ; 0x2c +1004170e: e11b b.n 10041948 +10041710: 2b08 cmp r3, #8 +10041712: d138 bne.n 10041786 +10041714: 6304 str r4, [r0, #48] ; 0x30 +10041716: e117 b.n 10041948 +10041718: 2b01 cmp r3, #1 +1004171a: d134 bne.n 10041786 +1004171c: 6344 str r4, [r0, #52] ; 0x34 +1004171e: e113 b.n 10041948 +10041720: 2b02 cmp r3, #2 +10041722: d130 bne.n 10041786 +10041724: 6384 str r4, [r0, #56] ; 0x38 +10041726: e10f b.n 10041948 +10041728: 2b02 cmp r3, #2 +1004172a: d12c bne.n 10041786 +1004172c: 63c4 str r4, [r0, #60] ; 0x3c +1004172e: e10b b.n 10041948 +10041730: 2b02 cmp r3, #2 +10041732: d128 bne.n 10041786 +10041734: 6404 str r4, [r0, #64] ; 0x40 +10041736: e107 b.n 10041948 +10041738: f1a3 0126 sub.w r1, r3, #38 ; 0x26 +1004173c: 2911 cmp r1, #17 +1004173e: f080 80fe bcs.w 1004193e +10041742: f8c0 4118 str.w r4, [r0, #280] ; 0x118 +10041746: f8c0 311c str.w r3, [r0, #284] ; 0x11c +1004174a: e0fd b.n 10041948 +1004174c: 2b04 cmp r3, #4 +1004174e: d11a bne.n 10041786 +10041750: 6444 str r4, [r0, #68] ; 0x44 +10041752: e0f9 b.n 10041948 +10041754: 2b01 cmp r3, #1 +10041756: d116 bne.n 10041786 +10041758: 6484 str r4, [r0, #72] ; 0x48 +1004175a: e0f5 b.n 10041948 +1004175c: 2b08 cmp r3, #8 +1004175e: d112 bne.n 10041786 +10041760: 64c4 str r4, [r0, #76] ; 0x4c +10041762: e0f1 b.n 10041948 +10041764: 2b20 cmp r3, #32 +10041766: d10e bne.n 10041786 +10041768: 6504 str r4, [r0, #80] ; 0x50 +1004176a: e0ed b.n 10041948 +1004176c: 2b20 cmp r3, #32 +1004176e: d10a bne.n 10041786 +10041770: 6544 str r4, [r0, #84] ; 0x54 +10041772: e0e9 b.n 10041948 +10041774: 2b20 cmp r3, #32 +10041776: d106 bne.n 10041786 +10041778: 6584 str r4, [r0, #88] ; 0x58 +1004177a: e0e5 b.n 10041948 +1004177c: 2b20 cmp r3, #32 +1004177e: d102 bne.n 10041786 +10041780: 65c4 str r4, [r0, #92] ; 0x5c +10041782: e0e1 b.n 10041948 +10041784: 2b10 cmp r3, #16 +10041786: f040 80da bne.w 1004193e +1004178a: 6604 str r4, [r0, #96] ; 0x60 +1004178c: e0dc b.n 10041948 +1004178e: 2b10 cmp r3, #16 +10041790: d1f9 bne.n 10041786 +10041792: 6644 str r4, [r0, #100] ; 0x64 +10041794: e0d8 b.n 10041948 +10041796: 2b10 cmp r3, #16 +10041798: d1f5 bne.n 10041786 +1004179a: 6684 str r4, [r0, #104] ; 0x68 +1004179c: e0d4 b.n 10041948 +1004179e: 2b10 cmp r3, #16 +100417a0: d1f1 bne.n 10041786 +100417a2: 66c4 str r4, [r0, #108] ; 0x6c +100417a4: e0d0 b.n 10041948 +100417a6: 2b08 cmp r3, #8 +100417a8: d1ed bne.n 10041786 +100417aa: 6704 str r4, [r0, #112] ; 0x70 +100417ac: e0cc b.n 10041948 +100417ae: 2b02 cmp r3, #2 +100417b0: d1e9 bne.n 10041786 +100417b2: 6744 str r4, [r0, #116] ; 0x74 +100417b4: e0c8 b.n 10041948 +100417b6: 2b02 cmp r3, #2 +100417b8: d1e5 bne.n 10041786 +100417ba: 6784 str r4, [r0, #120] ; 0x78 +100417bc: e0c4 b.n 10041948 +100417be: 2b01 cmp r3, #1 +100417c0: d170 bne.n 100418a4 +100417c2: 67c4 str r4, [r0, #124] ; 0x7c +100417c4: e0c0 b.n 10041948 +100417c6: 2b01 cmp r3, #1 +100417c8: d16c bne.n 100418a4 +100417ca: f8c0 4080 str.w r4, [r0, #128] ; 0x80 +100417ce: e0bb b.n 10041948 +100417d0: 2b06 cmp r3, #6 +100417d2: d167 bne.n 100418a4 +100417d4: f8c0 4084 str.w r4, [r0, #132] ; 0x84 +100417d8: e0b6 b.n 10041948 +100417da: 2b01 cmp r3, #1 +100417dc: d162 bne.n 100418a4 +100417de: f8c0 4088 str.w r4, [r0, #136] ; 0x88 +100417e2: e0b1 b.n 10041948 +100417e4: 2b01 cmp r3, #1 +100417e6: d15d bne.n 100418a4 +100417e8: f8c0 408c str.w r4, [r0, #140] ; 0x8c +100417ec: e0ac b.n 10041948 +100417ee: 2b01 cmp r3, #1 +100417f0: d158 bne.n 100418a4 +100417f2: f8c0 4090 str.w r4, [r0, #144] ; 0x90 +100417f6: e0a7 b.n 10041948 +100417f8: 2b01 cmp r3, #1 +100417fa: d153 bne.n 100418a4 +100417fc: f8c0 4094 str.w r4, [r0, #148] ; 0x94 +10041800: e0a2 b.n 10041948 +10041802: 2b01 cmp r3, #1 +10041804: d14e bne.n 100418a4 +10041806: f8c0 4098 str.w r4, [r0, #152] ; 0x98 +1004180a: e09d b.n 10041948 +1004180c: f8c0 40b0 str.w r4, [r0, #176] ; 0xb0 +10041810: f8c0 30b4 str.w r3, [r0, #180] ; 0xb4 +10041814: e098 b.n 10041948 +10041816: f8c0 40b8 str.w r4, [r0, #184] ; 0xb8 +1004181a: f8c0 30bc str.w r3, [r0, #188] ; 0xbc +1004181e: e093 b.n 10041948 +10041820: f8c0 40c0 str.w r4, [r0, #192] ; 0xc0 +10041824: f8c0 30c4 str.w r3, [r0, #196] ; 0xc4 +10041828: e08e b.n 10041948 +1004182a: f8c0 40c8 str.w r4, [r0, #200] ; 0xc8 +1004182e: f8c0 30cc str.w r3, [r0, #204] ; 0xcc +10041832: e089 b.n 10041948 +10041834: f8c0 40d0 str.w r4, [r0, #208] ; 0xd0 +10041838: f8c0 30d4 str.w r3, [r0, #212] ; 0xd4 +1004183c: e084 b.n 10041948 +1004183e: f8c0 40d8 str.w r4, [r0, #216] ; 0xd8 +10041842: f8c0 30dc str.w r3, [r0, #220] ; 0xdc +10041846: e07f b.n 10041948 +10041848: f8c0 40e0 str.w r4, [r0, #224] ; 0xe0 +1004184c: f8c0 30e4 str.w r3, [r0, #228] ; 0xe4 +10041850: e07a b.n 10041948 +10041852: f8d0 1170 ldr.w r1, [r0, #368] ; 0x170 +10041856: 290a cmp r1, #10 +10041858: d276 bcs.n 10041948 +1004185a: eb00 0181 add.w r1, r0, r1, lsl #2 +1004185e: f8c1 4120 str.w r4, [r1, #288] ; 0x120 +10041862: f8d0 1170 ldr.w r1, [r0, #368] ; 0x170 +10041866: eb00 0181 add.w r1, r0, r1, lsl #2 +1004186a: f8c1 3148 str.w r3, [r1, #328] ; 0x148 +1004186e: f8d0 1170 ldr.w r1, [r0, #368] ; 0x170 +10041872: 1c49 adds r1, r1, #1 +10041874: f8c0 1170 str.w r1, [r0, #368] ; 0x170 +10041878: e066 b.n 10041948 +1004187a: f8c0 40e8 str.w r4, [r0, #232] ; 0xe8 +1004187e: f8c0 30ec str.w r3, [r0, #236] ; 0xec +10041882: e061 b.n 10041948 +10041884: f8c0 40f0 str.w r4, [r0, #240] ; 0xf0 +10041888: f8c0 30f4 str.w r3, [r0, #244] ; 0xf4 +1004188c: e05c b.n 10041948 +1004188e: f8c0 40f8 str.w r4, [r0, #248] ; 0xf8 +10041892: f8c0 30fc str.w r3, [r0, #252] ; 0xfc +10041896: e057 b.n 10041948 +10041898: f8c0 4100 str.w r4, [r0, #256] ; 0x100 +1004189c: f8c0 3104 str.w r3, [r0, #260] ; 0x104 +100418a0: e052 b.n 10041948 +100418a2: 2b01 cmp r3, #1 +100418a4: d14b bne.n 1004193e +100418a6: f8c0 409c str.w r4, [r0, #156] ; 0x9c +100418aa: e04d b.n 10041948 +100418ac: 2b08 cmp r3, #8 +100418ae: d146 bne.n 1004193e +100418b0: f8d0 119c ldr.w r1, [r0, #412] ; 0x19c +100418b4: 290a cmp r1, #10 +100418b6: d247 bcs.n 10041948 +100418b8: eb00 0181 add.w r1, r0, r1, lsl #2 +100418bc: f8c1 4174 str.w r4, [r1, #372] ; 0x174 +100418c0: f8d0 119c ldr.w r1, [r0, #412] ; 0x19c +100418c4: 1c49 adds r1, r1, #1 +100418c6: f8c0 119c str.w r1, [r0, #412] ; 0x19c +100418ca: e03d b.n 10041948 +100418cc: 2b81 cmp r3, #129 ; 0x81 +100418ce: bfbc itt lt +100418d0: f003 0107 andlt.w r1, r3, #7 +100418d4: 2901 cmplt r1, #1 +100418d6: da32 bge.n 1004193e +100418d8: f8c0 4110 str.w r4, [r0, #272] ; 0x110 +100418dc: f8c0 3114 str.w r3, [r0, #276] ; 0x114 +100418e0: e032 b.n 10041948 +100418e2: 2b03 cmp r3, #3 +100418e4: db30 blt.n 10041948 +100418e6: 7866 ldrb r6, [r4, #1] +100418e8: 7821 ldrb r1, [r4, #0] +100418ea: 0236 lsls r6, r6, #8 +100418ec: ea46 4101 orr.w r1, r6, r1, lsl #16 +100418f0: 78a6 ldrb r6, [r4, #2] +100418f2: 4331 orrs r1, r6 +100418f4: f243 762a movw r6, #14122 ; 0x372a +100418f8: 42b1 cmp r1, r6 +100418fa: d107 bne.n 1004190c +100418fc: 1eda subs r2, r3, #3 +100418fe: b292 uxth r2, r2 +10041900: 1ce1 adds r1, r4, #3 +10041902: f7ff fe05 bl 10041510 +10041906: 2800 cmp r0, #0 +10041908: d51e bpl.n 10041948 +1004190a: e018 b.n 1004193e +1004190c: f5b3 6f80 cmp.w r3, #1024 ; 0x400 +10041910: dc15 bgt.n 1004193e +10041912: f8d0 11f0 ldr.w r1, [r0, #496] ; 0x1f0 +10041916: 290a cmp r1, #10 +10041918: d211 bcs.n 1004193e +1004191a: eb00 0181 add.w r1, r0, r1, lsl #2 +1004191e: f8c1 41a0 str.w r4, [r1, #416] ; 0x1a0 +10041922: f8d0 11f0 ldr.w r1, [r0, #496] ; 0x1f0 +10041926: eb00 0181 add.w r1, r0, r1, lsl #2 +1004192a: f8c1 31c8 str.w r3, [r1, #456] ; 0x1c8 +1004192e: f8d0 11f0 ldr.w r1, [r0, #496] ; 0x1f0 +10041932: 1c49 adds r1, r1, #1 +10041934: f8c0 11f0 str.w r1, [r0, #496] ; 0x1f0 +10041938: e006 b.n 10041948 +1004193a: 2b02 cmp r3, #2 +1004193c: d002 beq.n 10041944 +1004193e: f04f 30ff mov.w r0, #4294967295 +10041942: bd52 pop {r1, r4, r6, pc} +10041944: f8c0 40ac str.w r4, [r0, #172] ; 0xac +10041948: 2000 movs r0, #0 +1004194a: bd52 pop {r1, r4, r6, pc} + +1004194c : +1004194c: e92d 43f8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} +10041950: 4607 mov r7, r0 +10041952: 460c mov r4, r1 +10041954: 2500 movs r5, #0 +10041956: f44f 72fa mov.w r2, #500 ; 0x1f4 +1004195a: 2100 movs r1, #0 +1004195c: 4620 mov r0, r4 +1004195e: f7ce ff6b bl 10010838 +10041962: 68be ldr r6, [r7, #8] +10041964: 6878 ldr r0, [r7, #4] +10041966: 1987 adds r7, r0, r6 +10041968: e009 b.n 1004197e +1004196a: f408 407f and.w r0, r8, #65280 ; 0xff00 +1004196e: f5b0 5f80 cmp.w r0, #4096 ; 0x1000 +10041972: d028 beq.n 100419c6 +10041974: f241 0027 movw r0, #4135 ; 0x1027 +10041978: 4285 cmp r5, r0 +1004197a: d124 bne.n 100419c6 +1004197c: 1ef6 subs r6, r6, #3 +1004197e: 42be cmp r6, r7 +10041980: d227 bcs.n 100419d2 +10041982: 1bb8 subs r0, r7, r6 +10041984: 2804 cmp r0, #4 +10041986: db1e blt.n 100419c6 +10041988: 7830 ldrb r0, [r6, #0] +1004198a: 7871 ldrb r1, [r6, #1] +1004198c: ea41 2800 orr.w r8, r1, r0, lsl #8 +10041990: 1cb0 adds r0, r6, #2 +10041992: 7801 ldrb r1, [r0, #0] +10041994: 7842 ldrb r2, [r0, #1] +10041996: ea42 2901 orr.w r9, r2, r1, lsl #8 +1004199a: 1c86 adds r6, r0, #2 +1004199c: 1bb9 subs r1, r7, r6 +1004199e: 4549 cmp r1, r9 +100419a0: dbe3 blt.n 1004196a +100419a2: ea59 0008 orrs.w r0, r9, r8 +100419a6: d106 bne.n 100419b6 +100419a8: e002 b.n 100419b0 +100419aa: 5d82 ldrb r2, [r0, r6] +100419ac: b91a cbnz r2, 100419b6 +100419ae: 1c40 adds r0, r0, #1 +100419b0: 4288 cmp r0, r1 +100419b2: dbfa blt.n 100419aa +100419b4: d00d beq.n 100419d2 +100419b6: 464b mov r3, r9 +100419b8: 4632 mov r2, r6 +100419ba: 4641 mov r1, r8 +100419bc: 4620 mov r0, r4 +100419be: f7ff fdd7 bl 10041570 +100419c2: 2800 cmp r0, #0 +100419c4: d502 bpl.n 100419cc +100419c6: f04f 30ff mov.w r0, #4294967295 +100419ca: e003 b.n 100419d4 +100419cc: 4645 mov r5, r8 +100419ce: 444e add r6, r9 +100419d0: e7d5 b.n 1004197e +100419d2: 2000 movs r0, #0 +100419d4: e8bd 83f2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, pc} + +100419d8 : +100419d8: b510 push {r4, lr} +100419da: b08e sub sp, #56 ; 0x38 +100419dc: 000c movs r4, r1 +100419de: bf1c itt ne +100419e0: f8d0 1134 ldrne.w r1, [r0, #308] ; 0x134 +100419e4: 2900 cmpne r1, #0 +100419e6: d018 beq.n 10041a1a +100419e8: 688b ldr r3, [r1, #8] +100419ea: 9304 str r3, [sp, #16] +100419ec: ab04 add r3, sp, #16 +100419ee: 6849 ldr r1, [r1, #4] +100419f0: 9102 str r1, [sp, #8] +100419f2: 30e4 adds r0, #228 ; 0xe4 +100419f4: 6891 ldr r1, [r2, #8] +100419f6: 9105 str r1, [sp, #20] +100419f8: 6851 ldr r1, [r2, #4] +100419fa: 390c subs r1, #12 +100419fc: 9103 str r1, [sp, #12] +100419fe: 2202 movs r2, #2 +10041a00: a906 add r1, sp, #24 +10041a02: 9101 str r1, [sp, #4] +10041a04: a902 add r1, sp, #8 +10041a06: 9100 str r1, [sp, #0] +10041a08: 2120 movs r1, #32 +10041a0a: f7fb fc6b bl 1003d2e4 +10041a0e: 2208 movs r2, #8 +10041a10: 4621 mov r1, r4 +10041a12: a806 add r0, sp, #24 +10041a14: f7ce ff05 bl 10010822 +10041a18: b910 cbnz r0, 10041a20 +10041a1a: f04f 30ff mov.w r0, #4294967295 +10041a1e: e000 b.n 10041a22 +10041a20: 2000 movs r0, #0 +10041a22: b00e add sp, #56 ; 0x38 +10041a24: bd10 pop {r4, pc} + +10041a26 : +10041a26: b530 push {r4, r5, lr} +10041a28: 0014 movs r4, r2 +10041a2a: b089 sub sp, #36 ; 0x24 +10041a2c: d013 beq.n 10041a56 +10041a2e: 688a ldr r2, [r1, #8] +10041a30: 6849 ldr r1, [r1, #4] +10041a32: f1a1 030c sub.w r3, r1, #12 +10041a36: 1899 adds r1, r3, r2 +10041a38: 1f25 subs r5, r4, #4 +10041a3a: 42a9 cmp r1, r5 +10041a3c: d10b bne.n 10041a56 +10041a3e: a901 add r1, sp, #4 +10041a40: 9100 str r1, [sp, #0] +10041a42: 30e4 adds r0, #228 ; 0xe4 +10041a44: 2120 movs r1, #32 +10041a46: f7fb fc51 bl 1003d2ec +10041a4a: 2208 movs r2, #8 +10041a4c: 4621 mov r1, r4 +10041a4e: a801 add r0, sp, #4 +10041a50: f7ce fee7 bl 10010822 +10041a54: b910 cbnz r0, 10041a5c +10041a56: f04f 30ff mov.w r0, #4294967295 +10041a5a: e000 b.n 10041a5e +10041a5c: 2000 movs r0, #0 +10041a5e: b009 add sp, #36 ; 0x24 +10041a60: bd30 pop {r4, r5, pc} + +10041a62 : +10041a62: b538 push {r3, r4, r5, lr} +10041a64: 4604 mov r4, r0 +10041a66: 4615 mov r5, r2 +10041a68: b909 cbnz r1, 10041a6e +10041a6a: e03e b.n 10041aea <.text_10> +10041a6c: 1e6d subs r5, r5, #1 +10041a6e: b135 cbz r5, 10041a7e +10041a70: 1868 adds r0, r5, r1 +10041a72: f810 0c01 ldrb.w r0, [r0, #-1] +10041a76: 2800 cmp r0, #0 +10041a78: d0f8 beq.n 10041a6c +10041a7a: 2d21 cmp r5, #33 ; 0x21 +10041a7c: d204 bcs.n 10041a88 +10041a7e: 462a mov r2, r5 +10041a80: 4620 mov r0, r4 +10041a82: f7ce fec4 bl 1001080e +10041a86: 6225 str r5, [r4, #32] +10041a88: 2000 movs r0, #0 +10041a8a: bd32 pop {r1, r4, r5, pc} + +10041a8c : +10041a8c: b901 cbnz r1, 10041a90 +10041a8e: e00f b.n 10041ab0 <.text_7> +10041a90: 780a ldrb r2, [r1, #0] +10041a92: 7849 ldrb r1, [r1, #1] +10041a94: ea41 2102 orr.w r1, r1, r2, lsl #8 +10041a98: 8481 strh r1, [r0, #36] ; 0x24 +10041a9a: 2000 movs r0, #0 +10041a9c: 4770 bx lr + +10041a9e : +10041a9e: b901 cbnz r1, 10041aa2 +10041aa0: e006 b.n 10041ab0 <.text_7> +10041aa2: 780a ldrb r2, [r1, #0] +10041aa4: 7849 ldrb r1, [r1, #1] +10041aa6: ea41 2102 orr.w r1, r1, r2, lsl #8 +10041aaa: 84c1 strh r1, [r0, #38] ; 0x26 +10041aac: 2000 movs r0, #0 +10041aae: 4770 bx lr + +10041ab0 <.text_7>: +10041ab0: f04f 30ff mov.w r0, #4294967295 +10041ab4: 4770 bx lr + +10041ab6 : +10041ab6: b111 cbz r1, 10041abe +10041ab8: 7809 ldrb r1, [r1, #0] +10041aba: f880 1028 strb.w r1, [r0, #40] ; 0x28 +10041abe: 2000 movs r0, #0 +10041ac0: 4770 bx lr + +10041ac2 : +10041ac2: b538 push {r3, r4, r5, lr} +10041ac4: 4604 mov r4, r0 +10041ac6: 4615 mov r5, r2 +10041ac8: b931 cbnz r1, 10041ad8 +10041aca: 8ca0 ldrh r0, [r4, #36] ; 0x24 +10041acc: 2801 cmp r0, #1 +10041ace: bf04 itt eq +10041ad0: 8ce0 ldrheq r0, [r4, #38] ; 0x26 +10041ad2: 2801 cmpeq r0, #1 +10041ad4: d007 beq.n 10041ae6 +10041ad6: e008 b.n 10041aea <.text_10> +10041ad8: 2d41 cmp r5, #65 ; 0x41 +10041ada: d204 bcs.n 10041ae6 +10041adc: f104 0029 add.w r0, r4, #41 ; 0x29 +10041ae0: f7ce fe95 bl 1001080e +10041ae4: 66e5 str r5, [r4, #108] ; 0x6c +10041ae6: 2000 movs r0, #0 +10041ae8: bd32 pop {r1, r4, r5, pc} + +10041aea <.text_10>: +10041aea: f04f 30ff mov.w r0, #4294967295 +10041aee: bd32 pop {r1, r4, r5, pc} + +10041af0 : +10041af0: b580 push {r7, lr} +10041af2: b911 cbnz r1, 10041afa +10041af4: f04f 30ff mov.w r0, #4294967295 +10041af8: bd02 pop {r1, pc} +10041afa: 2206 movs r2, #6 +10041afc: 3070 adds r0, #112 ; 0x70 +10041afe: f7ce fe86 bl 1001080e +10041b02: 2000 movs r0, #0 +10041b04: bd02 pop {r1, pc} + +10041b06 : +10041b06: f890 1024 ldrb.w r1, [r0, #36] ; 0x24 +10041b0a: 2222 movs r2, #34 ; 0x22 +10041b0c: 4211 tst r1, r2 +10041b0e: d00a beq.n 10041b26 +10041b10: 6ec1 ldr r1, [r0, #108] ; 0x6c +10041b12: f1a1 0209 sub.w r2, r1, #9 +10041b16: 2a37 cmp r2, #55 ; 0x37 +10041b18: d205 bcs.n 10041b26 +10041b1a: 180a adds r2, r1, r0 +10041b1c: f892 2028 ldrb.w r2, [r2, #40] ; 0x28 +10041b20: b90a cbnz r2, 10041b26 +10041b22: 1e49 subs r1, r1, #1 +10041b24: 66c1 str r1, [r0, #108] ; 0x6c +10041b26: 2000 movs r0, #0 +10041b28: 4770 bx lr + +10041b2a : +10041b2a: b570 push {r4, r5, r6, lr} +10041b2c: 4604 mov r4, r0 +10041b2e: f104 0674 add.w r6, r4, #116 ; 0x74 +10041b32: 460d mov r5, r1 +10041b34: 68b0 ldr r0, [r6, #8] +10041b36: b310 cbz r0, 10041b7e <.text_14> +10041b38: f000 f828 bl 10041b8c <.text_17> +10041b3c: b9f8 cbnz r0, 10041b7e <.text_14> +10041b3e: 6f61 ldr r1, [r4, #116] ; 0x74 +10041b40: 4628 mov r0, r5 +10041b42: f7ff ffa3 bl 10041a8c +10041b46: b9d0 cbnz r0, 10041b7e <.text_14> +10041b48: 6871 ldr r1, [r6, #4] +10041b4a: 4628 mov r0, r5 +10041b4c: f7ff ffa7 bl 10041a9e +10041b50: b9a8 cbnz r0, 10041b7e <.text_14> +10041b52: 68f1 ldr r1, [r6, #12] +10041b54: 4628 mov r0, r5 +10041b56: f7ff ffae bl 10041ab6 +10041b5a: b980 cbnz r0, 10041b7e <.text_14> +10041b5c: f000 f81a bl 10041b94 <.text_18> +10041b60: b968 cbnz r0, 10041b7e <.text_14> +10041b62: 6931 ldr r1, [r6, #16] +10041b64: 4628 mov r0, r5 +10041b66: f7ff ffc3 bl 10041af0 +10041b6a: b940 cbnz r0, 10041b7e <.text_14> +10041b6c: 6bb0 ldr r0, [r6, #56] ; 0x38 +10041b6e: b128 cbz r0, 10041b7c +10041b70: 7801 ldrb r1, [r0, #0] +10041b72: 7840 ldrb r0, [r0, #1] +10041b74: ea40 2001 orr.w r0, r0, r1, lsl #8 +10041b78: f8a5 0080 strh.w r0, [r5, #128] ; 0x80 +10041b7c: e002 b.n 10041b84 <.text_16> + +10041b7e <.text_14>: +10041b7e: f04f 30ff mov.w r0, #4294967295 +10041b82: bd70 pop {r4, r5, r6, pc} + +10041b84 <.text_16>: +10041b84: 4628 mov r0, r5 +10041b86: e8bd 4070 ldmia.w sp!, {r4, r5, r6, lr} +10041b8a: e7bc b.n 10041b06 + +10041b8c <.text_17>: +10041b8c: 6fb2 ldr r2, [r6, #120] ; 0x78 +10041b8e: 6f71 ldr r1, [r6, #116] ; 0x74 +10041b90: 4628 mov r0, r5 +10041b92: e766 b.n 10041a62 + +10041b94 <.text_18>: +10041b94: f8d4 20f4 ldr.w r2, [r4, #244] ; 0xf4 +10041b98: 6ff1 ldr r1, [r6, #124] ; 0x7c +10041b9a: 4628 mov r0, r5 +10041b9c: e791 b.n 10041ac2 + +10041b9e : +10041b9e: b908 cbnz r0, 10041ba4 +10041ba0: b129 cbz r1, 10041bae +10041ba2: e002 b.n 10041baa +10041ba4: 7800 ldrb r0, [r0, #0] +10041ba6: 2810 cmp r0, #16 +10041ba8: d000 beq.n 10041bac +10041baa: e00a b.n 10041bc2 <.text_4> +10041bac: 2000 movs r0, #0 +10041bae: 4770 bx lr + +10041bb0 : +10041bb0: b908 cbnz r0, 10041bb6 +10041bb2: b129 cbz r1, 10041bc0 +10041bb4: e002 b.n 10041bbc +10041bb6: 7800 ldrb r0, [r0, #0] +10041bb8: 2820 cmp r0, #32 +10041bba: da00 bge.n 10041bbe +10041bbc: e001 b.n 10041bc2 <.text_4> +10041bbe: 2000 movs r0, #0 +10041bc0: 4770 bx lr + +10041bc2 <.text_4>: +10041bc2: f04f 30ff mov.w r0, #4294967295 +10041bc6: 4770 bx lr + +10041bc8 : +10041bc8: b1b1 cbz r1, 10041bf8 +10041bca: f44f 41c0 mov.w r1, #24576 ; 0x6000 +10041bce: 4208 tst r0, r1 +10041bd0: d001 beq.n 10041bd6 +10041bd2: 0701 lsls r1, r0, #28 +10041bd4: d50e bpl.n 10041bf4 +10041bd6: f246 0108 movw r1, #24584 ; 0x6008 +10041bda: 4001 ands r1, r0 +10041bdc: 2908 cmp r1, #8 +10041bde: d009 beq.n 10041bf4 +10041be0: f44f 61c0 mov.w r1, #1536 ; 0x600 +10041be4: 4208 tst r0, r1 +10041be6: d001 beq.n 10041bec +10041be8: 0601 lsls r1, r0, #24 +10041bea: d503 bpl.n 10041bf4 +10041bec: f400 60d0 and.w r0, r0, #1664 ; 0x680 +10041bf0: 2880 cmp r0, #128 ; 0x80 +10041bf2: d101 bne.n 10041bf8 +10041bf4: 2000 movs r0, #0 +10041bf6: 4770 bx lr +10041bf8: 2001 movs r0, #1 +10041bfa: 4770 bx lr + +10041bfc : +10041bfc: b580 push {r7, lr} +10041bfe: b908 cbnz r0, 10041c04 +10041c00: b15a cbz r2, 10041c1a +10041c02: e006 b.n 10041c12 +10041c04: 7802 ldrb r2, [r0, #0] +10041c06: 7840 ldrb r0, [r0, #1] +10041c08: ea40 2002 orr.w r0, r0, r2, lsl #8 +10041c0c: f7ff ffdc bl 10041bc8 +10041c10: b910 cbnz r0, 10041c18 +10041c12: f04f 30ff mov.w r0, #4294967295 +10041c16: bd02 pop {r1, pc} +10041c18: 2000 movs r0, #0 +10041c1a: bd02 pop {r1, pc} + +10041c1c : +10041c1c: b908 cbnz r0, 10041c22 +10041c1e: b109 cbz r1, 10041c24 +10041c20: e7cf b.n 10041bc2 <.text_4> +10041c22: 2000 movs r0, #0 +10041c24: 4770 bx lr + +10041c26 : +10041c26: b908 cbnz r0, 10041c2c +10041c28: b109 cbz r1, 10041c2e +10041c2a: e7ca b.n 10041bc2 <.text_4> +10041c2c: 2000 movs r0, #0 +10041c2e: 4770 bx lr + +10041c30 : +10041c30: b908 cbnz r0, 10041c36 +10041c32: b141 cbz r1, 10041c46 +10041c34: e005 b.n 10041c42 +10041c36: 7800 ldrb r0, [r0, #0] +10041c38: 2801 cmp r0, #1 +10041c3a: bf1c itt ne +10041c3c: 2802 cmpne r0, #2 +10041c3e: 2803 cmpne r0, #3 +10041c40: d000 beq.n 10041c44 +10041c42: e7be b.n 10041bc2 <.text_4> +10041c44: 2000 movs r0, #0 +10041c46: 4770 bx lr + +10041c48 : +10041c48: b908 cbnz r0, 10041c4e +10041c4a: b141 cbz r1, 10041c5e +10041c4c: e005 b.n 10041c5a +10041c4e: 7801 ldrb r1, [r0, #0] +10041c50: 7840 ldrb r0, [r0, #1] +10041c52: ea40 2001 orr.w r0, r0, r1, lsl #8 +10041c56: 2805 cmp r0, #5 +10041c58: db00 blt.n 10041c5c +10041c5a: e7b2 b.n 10041bc2 <.text_4> +10041c5c: 2000 movs r0, #0 +10041c5e: 4770 bx lr + +10041c60 : +10041c60: b908 cbnz r0, 10041c66 +10041c62: b141 cbz r1, 10041c76 +10041c64: e005 b.n 10041c72 +10041c66: 7801 ldrb r1, [r0, #0] +10041c68: 7840 ldrb r0, [r0, #1] +10041c6a: ea40 2001 orr.w r0, r0, r1, lsl #8 +10041c6e: 2813 cmp r0, #19 +10041c70: db00 blt.n 10041c74 +10041c72: e7a6 b.n 10041bc2 <.text_4> +10041c74: 2000 movs r0, #0 +10041c76: 4770 bx lr + +10041c78 : +10041c78: b908 cbnz r0, 10041c7e +10041c7a: b149 cbz r1, 10041c90 +10041c7c: e006 b.n 10041c8c +10041c7e: 7801 ldrb r1, [r0, #0] +10041c80: 7840 ldrb r0, [r0, #1] +10041c82: ea40 2001 orr.w r0, r0, r1, lsl #8 +10041c86: 1f80 subs r0, r0, #6 +10041c88: 280a cmp r0, #10 +10041c8a: d200 bcs.n 10041c8e +10041c8c: e799 b.n 10041bc2 <.text_4> +10041c8e: 2000 movs r0, #0 +10041c90: 4770 bx lr + +10041c92 : +10041c92: b908 cbnz r0, 10041c98 +10041c94: b13a cbz r2, 10041ca6 +10041c96: e004 b.n 10041ca2 +10041c98: b121 cbz r1, 10041ca4 +10041c9a: 1808 adds r0, r1, r0 +10041c9c: f810 0c01 ldrb.w r0, [r0, #-1] +10041ca0: b900 cbnz r0, 10041ca4 +10041ca2: e78e b.n 10041bc2 <.text_4> +10041ca4: 2000 movs r0, #0 +10041ca6: 4770 bx lr + +10041ca8 : +10041ca8: b908 cbnz r0, 10041cae +10041caa: b13a cbz r2, 10041cbc +10041cac: e004 b.n 10041cb8 +10041cae: b121 cbz r1, 10041cba +10041cb0: 1808 adds r0, r1, r0 +10041cb2: f810 0c01 ldrb.w r0, [r0, #-1] +10041cb6: b900 cbnz r0, 10041cba +10041cb8: e783 b.n 10041bc2 <.text_4> +10041cba: 2000 movs r0, #0 +10041cbc: 4770 bx lr + +10041cbe : +10041cbe: b908 cbnz r0, 10041cc4 +10041cc0: b13a cbz r2, 10041cd2 +10041cc2: e004 b.n 10041cce +10041cc4: b121 cbz r1, 10041cd0 +10041cc6: 1808 adds r0, r1, r0 +10041cc8: f810 0c01 ldrb.w r0, [r0, #-1] +10041ccc: b900 cbnz r0, 10041cd0 +10041cce: e778 b.n 10041bc2 <.text_4> +10041cd0: 2000 movs r0, #0 +10041cd2: 4770 bx lr + +10041cd4 : +10041cd4: b908 cbnz r0, 10041cda +10041cd6: b13a cbz r2, 10041ce8 +10041cd8: e004 b.n 10041ce4 +10041cda: b121 cbz r1, 10041ce6 +10041cdc: 1808 adds r0, r1, r0 +10041cde: f810 0c01 ldrb.w r0, [r0, #-1] +10041ce2: b900 cbnz r0, 10041ce6 +10041ce4: e76d b.n 10041bc2 <.text_4> +10041ce6: 2000 movs r0, #0 +10041ce8: 4770 bx lr + +10041cea : +10041cea: b908 cbnz r0, 10041cf0 +10041cec: b13a cbz r2, 10041cfe +10041cee: e004 b.n 10041cfa +10041cf0: b121 cbz r1, 10041cfc +10041cf2: 1808 adds r0, r1, r0 +10041cf4: f810 0c01 ldrb.w r0, [r0, #-1] +10041cf8: b900 cbnz r0, 10041cfc +10041cfa: e762 b.n 10041bc2 <.text_4> +10041cfc: 2000 movs r0, #0 +10041cfe: 4770 bx lr + +10041d00 : +10041d00: b908 cbnz r0, 10041d06 +10041d02: b131 cbz r1, 10041d12 +10041d04: e003 b.n 10041d0e +10041d06: 7800 ldrb r0, [r0, #0] +10041d08: b108 cbz r0, 10041d0e +10041d0a: 2810 cmp r0, #16 +10041d0c: db00 blt.n 10041d10 +10041d0e: e758 b.n 10041bc2 <.text_4> +10041d10: 2000 movs r0, #0 +10041d12: 4770 bx lr + +10041d14 : +10041d14: b908 cbnz r0, 10041d1a +10041d16: b129 cbz r1, 10041d24 +10041d18: e002 b.n 10041d20 +10041d1a: 7800 ldrb r0, [r0, #0] +10041d1c: 07c0 lsls r0, r0, #31 +10041d1e: d500 bpl.n 10041d22 +10041d20: e74f b.n 10041bc2 <.text_4> +10041d22: 2000 movs r0, #0 +10041d24: 4770 bx lr + +10041d26 : +10041d26: b908 cbnz r0, 10041d2c +10041d28: b109 cbz r1, 10041d2e +10041d2a: e74a b.n 10041bc2 <.text_4> +10041d2c: 2000 movs r0, #0 +10041d2e: 4770 bx lr + +10041d30 : +10041d30: b908 cbnz r0, 10041d36 +10041d32: b109 cbz r1, 10041d38 +10041d34: e745 b.n 10041bc2 <.text_4> +10041d36: 2000 movs r0, #0 +10041d38: 4770 bx lr + +10041d3a : +10041d3a: b908 cbnz r0, 10041d40 +10041d3c: b122 cbz r2, 10041d48 +10041d3e: e001 b.n 10041d44 +10041d40: 29c0 cmp r1, #192 ; 0xc0 +10041d42: d000 beq.n 10041d46 +10041d44: e73d b.n 10041bc2 <.text_4> +10041d46: 2000 movs r0, #0 +10041d48: 4770 bx lr + +10041d4a : +10041d4a: 2100 movs r1, #0 +10041d4c: e002 b.n 10041d54 +10041d4e: 1e42 subs r2, r0, #1 +10041d50: 4010 ands r0, r2 +10041d52: 1c49 adds r1, r1, #1 +10041d54: 2800 cmp r0, #0 +10041d56: d1fa bne.n 10041d4e +10041d58: 4608 mov r0, r1 +10041d5a: 4770 bx lr + +10041d5c : +10041d5c: b908 cbnz r0, 10041d62 +10041d5e: b151 cbz r1, 10041d76 +10041d60: e007 b.n 10041d72 +10041d62: 7801 ldrb r1, [r0, #0] +10041d64: 7840 ldrb r0, [r0, #1] +10041d66: ea40 2001 orr.w r0, r0, r1, lsl #8 +10041d6a: 0940 lsrs r0, r0, #5 +10041d6c: 0140 lsls r0, r0, #5 +10041d6e: 2820 cmp r0, #32 +10041d70: d000 beq.n 10041d74 +10041d72: e726 b.n 10041bc2 <.text_4> +10041d74: 2000 movs r0, #0 +10041d76: 4770 bx lr + +10041d78 : +10041d78: b510 push {r4, lr} +10041d7a: b908 cbnz r0, 10041d80 +10041d7c: b189 cbz r1, 10041da2 +10041d7e: e00e b.n 10041d9e +10041d80: 7801 ldrb r1, [r0, #0] +10041d82: 7840 ldrb r0, [r0, #1] +10041d84: ea40 2401 orr.w r4, r0, r1, lsl #8 +10041d88: f034 003f bics.w r0, r4, #63 ; 0x3f +10041d8c: d107 bne.n 10041d9e +10041d8e: b134 cbz r4, 10041d9e +10041d90: 4620 mov r0, r4 +10041d92: f7ff ffda bl 10041d4a +10041d96: 2802 cmp r0, #2 +10041d98: db02 blt.n 10041da0 +10041d9a: 2c22 cmp r4, #34 ; 0x22 +10041d9c: d000 beq.n 10041da0 +10041d9e: e025 b.n 10041dec <.text_31> +10041da0: 2000 movs r0, #0 +10041da2: bd10 pop {r4, pc} + +10041da4 : +10041da4: b908 cbnz r0, 10041daa +10041da6: b151 cbz r1, 10041dbe +10041da8: e007 b.n 10041dba +10041daa: 7801 ldrb r1, [r0, #0] +10041dac: 7840 ldrb r0, [r0, #1] +10041dae: ea40 2001 orr.w r0, r0, r1, lsl #8 +10041db2: 08c0 lsrs r0, r0, #3 +10041db4: 00c0 lsls r0, r0, #3 +10041db6: 2808 cmp r0, #8 +10041db8: d000 beq.n 10041dbc +10041dba: e702 b.n 10041bc2 <.text_4> +10041dbc: 2000 movs r0, #0 +10041dbe: 4770 bx lr + +10041dc0 : +10041dc0: b510 push {r4, lr} +10041dc2: b908 cbnz r0, 10041dc8 +10041dc4: b189 cbz r1, 10041dea +10041dc6: e00e b.n 10041de6 +10041dc8: 7801 ldrb r1, [r0, #0] +10041dca: 7840 ldrb r0, [r0, #1] +10041dcc: ea40 2401 orr.w r4, r0, r1, lsl #8 +10041dd0: f034 000f bics.w r0, r4, #15 +10041dd4: d107 bne.n 10041de6 +10041dd6: b134 cbz r4, 10041de6 +10041dd8: 4620 mov r0, r4 +10041dda: f7ff ffb6 bl 10041d4a +10041dde: 2802 cmp r0, #2 +10041de0: db02 blt.n 10041de8 +10041de2: 2c0c cmp r4, #12 +10041de4: d000 beq.n 10041de8 +10041de6: e001 b.n 10041dec <.text_31> +10041de8: 2000 movs r0, #0 +10041dea: bd10 pop {r4, pc} + +10041dec <.text_31>: +10041dec: f04f 30ff mov.w r0, #4294967295 +10041df0: bd10 pop {r4, pc} + +10041df2 : +10041df2: b908 cbnz r0, 10041df8 +10041df4: b139 cbz r1, 10041e06 +10041df6: e004 b.n 10041e02 +10041df8: 7800 ldrb r0, [r0, #0] +10041dfa: f000 00fd and.w r0, r0, #253 ; 0xfd +10041dfe: 2801 cmp r0, #1 +10041e00: d000 beq.n 10041e04 +10041e02: e6de b.n 10041bc2 <.text_4> +10041e04: 2000 movs r0, #0 +10041e06: 4770 bx lr + +10041e08 : +10041e08: b908 cbnz r0, 10041e0e +10041e0a: b109 cbz r1, 10041e10 +10041e0c: e6d9 b.n 10041bc2 <.text_4> +10041e0e: 2000 movs r0, #0 +10041e10: 4770 bx lr + +10041e12 : +10041e12: b908 cbnz r0, 10041e18 +10041e14: b109 cbz r1, 10041e1a +10041e16: e6d4 b.n 10041bc2 <.text_4> +10041e18: 2000 movs r0, #0 +10041e1a: 4770 bx lr + +10041e1c : +10041e1c: b908 cbnz r0, 10041e22 +10041e1e: b122 cbz r2, 10041e2a +10041e20: e001 b.n 10041e26 +10041e22: 2910 cmp r1, #16 +10041e24: d200 bcs.n 10041e28 +10041e26: e6cc b.n 10041bc2 <.text_4> +10041e28: 2000 movs r0, #0 +10041e2a: 4770 bx lr + +10041e2c : +10041e2c: b908 cbnz r0, 10041e32 +10041e2e: b109 cbz r1, 10041e34 +10041e30: e6c7 b.n 10041bc2 <.text_4> +10041e32: 2000 movs r0, #0 +10041e34: 4770 bx lr + +10041e36 : +10041e36: b908 cbnz r0, 10041e3c +10041e38: b14a cbz r2, 10041e4e +10041e3a: e006 b.n 10041e4a +10041e3c: 2900 cmp r1, #0 +10041e3e: bf1e ittt ne +10041e40: 1808 addne r0, r1, r0 +10041e42: f810 0c01 ldrbne.w r0, [r0, #-1] +10041e46: 2800 cmpne r0, #0 +10041e48: d100 bne.n 10041e4c +10041e4a: e6ba b.n 10041bc2 <.text_4> +10041e4c: 2000 movs r0, #0 +10041e4e: 4770 bx lr + +10041e50 : +10041e50: b908 cbnz r0, 10041e56 +10041e52: b109 cbz r1, 10041e58 +10041e54: e6b5 b.n 10041bc2 <.text_4> +10041e56: 2000 movs r0, #0 +10041e58: 4770 bx lr + +10041e5a : +10041e5a: b908 cbnz r0, 10041e60 +10041e5c: b19b cbz r3, 10041e86 +10041e5e: e010 b.n 10041e82 +10041e60: b12a cbz r2, 10041e6e +10041e62: 7813 ldrb r3, [r2, #0] +10041e64: 7852 ldrb r2, [r2, #1] +10041e66: ea42 2203 orr.w r2, r2, r3, lsl #8 +10041e6a: 2a02 cmp r2, #2 +10041e6c: d007 beq.n 10041e7e +10041e6e: f1a1 0209 sub.w r2, r1, #9 +10041e72: 2a37 cmp r2, #55 ; 0x37 +10041e74: d203 bcs.n 10041e7e +10041e76: 1808 adds r0, r1, r0 +10041e78: f810 0c01 ldrb.w r0, [r0, #-1] +10041e7c: b108 cbz r0, 10041e82 +10041e7e: 2941 cmp r1, #65 ; 0x41 +10041e80: d300 bcc.n 10041e84 +10041e82: e69e b.n 10041bc2 <.text_4> +10041e84: 2000 movs r0, #0 +10041e86: 4770 bx lr + +10041e88 : +10041e88: b530 push {r4, r5, lr} +10041e8a: 2800 cmp r0, #0 +10041e8c: f5ad 7d01 sub.w sp, sp, #516 ; 0x204 +10041e90: d036 beq.n 10041f00 +10041e92: 9002 str r0, [sp, #8] +10041e94: 9101 str r1, [sp, #4] +10041e96: 2001 movs r0, #1 +10041e98: 9003 str r0, [sp, #12] +10041e9a: 9100 str r1, [sp, #0] +10041e9c: a800 add r0, sp, #0 +10041e9e: a904 add r1, sp, #16 +10041ea0: f7ff fd54 bl 1004194c +10041ea4: 2800 cmp r0, #0 +10041ea6: d42b bmi.n 10041f00 +10041ea8: ac21 add r4, sp, #132 ; 0x84 +10041eaa: 68a0 ldr r0, [r4, #8] +10041eac: b340 cbz r0, 10041f00 +10041eae: 6fa1 ldr r1, [r4, #120] ; 0x78 +10041eb0: 6f60 ldr r0, [r4, #116] ; 0x74 +10041eb2: 2201 movs r2, #1 +10041eb4: f7ff ffbf bl 10041e36 +10041eb8: bb10 cbnz r0, 10041f00 +10041eba: 9821 ldr r0, [sp, #132] ; 0x84 +10041ebc: 2101 movs r1, #1 +10041ebe: f7ff ff5b bl 10041d78 +10041ec2: b9e8 cbnz r0, 10041f00 +10041ec4: 6865 ldr r5, [r4, #4] +10041ec6: 2101 movs r1, #1 +10041ec8: 4628 mov r0, r5 +10041eca: f7ff ff79 bl 10041dc0 +10041ece: b9b8 cbnz r0, 10041f00 +10041ed0: 68e0 ldr r0, [r4, #12] +10041ed2: 2100 movs r1, #0 +10041ed4: f7ff ffbc bl 10041e50 +10041ed8: b990 cbnz r0, 10041f00 +10041eda: 9941 ldr r1, [sp, #260] ; 0x104 +10041edc: 6fe0 ldr r0, [r4, #124] ; 0x7c +10041ede: 2301 movs r3, #1 +10041ee0: 462a mov r2, r5 +10041ee2: f7ff ffba bl 10041e5a +10041ee6: b958 cbnz r0, 10041f00 +10041ee8: 6920 ldr r0, [r4, #16] +10041eea: 2101 movs r1, #1 +10041eec: f7ff ff12 bl 10041d14 +10041ef0: b930 cbnz r0, 10041f00 +10041ef2: 6b20 ldr r0, [r4, #48] ; 0x30 +10041ef4: b110 cbz r0, 10041efc +10041ef6: 7800 ldrb r0, [r0, #0] +10041ef8: 2802 cmp r0, #2 +10041efa: da01 bge.n 10041f00 +10041efc: 2000 movs r0, #0 +10041efe: e001 b.n 10041f04 +10041f00: f04f 30ff mov.w r0, #4294967295 +10041f04: f50d 7d01 add.w sp, sp, #516 ; 0x204 +10041f08: bd30 pop {r4, r5, pc} + +10041f0a <.text_42>: +10041f0a: 6bf0 ldr r0, [r6, #60] ; 0x3c +10041f0c: 2101 movs r1, #1 +10041f0e: e6b3 b.n 10041c78 + +10041f10 <.text_43>: +10041f10: 6bb0 ldr r0, [r6, #56] ; 0x38 +10041f12: 2101 movs r1, #1 +10041f14: e6a4 b.n 10041c60 + +10041f16 <.text_46>: +10041f16: 6c30 ldr r0, [r6, #64] ; 0x40 +10041f18: 2101 movs r1, #1 +10041f1a: e775 b.n 10041e08 + +10041f1c <.text_47>: +10041f1c: 6a30 ldr r0, [r6, #32] +10041f1e: 2101 movs r1, #1 +10041f20: e767 b.n 10041df2 + +10041f22 <.text_48>: +10041f22: 69f0 ldr r0, [r6, #28] +10041f24: 2101 movs r1, #1 +10041f26: e73d b.n 10041da4 + +10041f28 <.text_49>: +10041f28: 69b0 ldr r0, [r6, #24] +10041f2a: 2101 movs r1, #1 +10041f2c: e716 b.n 10041d5c + +10041f2e <.text_50>: +10041f2e: 6b70 ldr r0, [r6, #52] ; 0x34 +10041f30: 2101 movs r1, #1 +10041f32: e689 b.n 10041c48 + +10041f34 <.text_51>: +10041f34: 6b30 ldr r0, [r6, #48] ; 0x30 +10041f36: 2101 movs r1, #1 +10041f38: e67a b.n 10041c30 + +10041f3a <.text_52>: +10041f3a: 6af0 ldr r0, [r6, #44] ; 0x2c +10041f3c: 2101 movs r1, #1 +10041f3e: e672 b.n 10041c26 + +10041f40 <.text_53>: +10041f40: 68b0 ldr r0, [r6, #8] +10041f42: 2101 movs r1, #1 +10041f44: e6ef b.n 10041d26 + +10041f46 : +10041f46: b530 push {r4, r5, lr} +10041f48: b0fd sub sp, #500 ; 0x1f4 +10041f4a: b118 cbz r0, 10041f54 +10041f4c: f000 f974 bl 10042238 <.text_71> +10041f50: 2800 cmp r0, #0 +10041f52: d502 bpl.n 10041f5a +10041f54: f04f 30ff mov.w r0, #4294967295 +10041f58: e07a b.n 10042050 +10041f5a: f000 f965 bl 10042228 <.text_69> +10041f5e: 2800 cmp r0, #0 +10041f60: d175 bne.n 1004204e +10041f62: ac01 add r4, sp, #4 +10041f64: 2101 movs r1, #1 +10041f66: 6860 ldr r0, [r4, #4] +10041f68: f7ff feca bl 10041d00 +10041f6c: 2800 cmp r0, #0 +10041f6e: d16e bne.n 1004204e +10041f70: 68a0 ldr r0, [r4, #8] +10041f72: f7ff ffe6 bl 10041f42 <.text_53+0x2> +10041f76: 2800 cmp r0, #0 +10041f78: d169 bne.n 1004204e +10041f7a: 68e0 ldr r0, [r4, #12] +10041f7c: f000 f8dc bl 10042138 <.text_58+0x2> +10041f80: 2800 cmp r0, #0 +10041f82: d164 bne.n 1004204e +10041f84: 6920 ldr r0, [r4, #16] +10041f86: 2101 movs r1, #1 +10041f88: f7ff fe48 bl 10041c1c +10041f8c: 2800 cmp r0, #0 +10041f8e: d15e bne.n 1004204e +10041f90: ad2c add r5, sp, #176 ; 0xb0 +10041f92: 6ae9 ldr r1, [r5, #44] ; 0x2c +10041f94: 6aa8 ldr r0, [r5, #40] ; 0x28 +10041f96: 2201 movs r2, #1 +10041f98: f7ff fecf bl 10041d3a +10041f9c: 2800 cmp r0, #0 +10041f9e: d156 bne.n 1004204e +10041fa0: 69a0 ldr r0, [r4, #24] +10041fa2: f7ff ffc2 bl 10041f2a <.text_49+0x2> +10041fa6: 2800 cmp r0, #0 +10041fa8: d151 bne.n 1004204e +10041faa: 69e0 ldr r0, [r4, #28] +10041fac: f7ff ffba bl 10041f24 <.text_48+0x2> +10041fb0: 2800 cmp r0, #0 +10041fb2: d14c bne.n 1004204e +10041fb4: 6a20 ldr r0, [r4, #32] +10041fb6: f7ff ffb2 bl 10041f1e <.text_47+0x2> +10041fba: 2800 cmp r0, #0 +10041fbc: d147 bne.n 1004204e +10041fbe: 6a60 ldr r0, [r4, #36] ; 0x24 +10041fc0: 2201 movs r2, #1 +10041fc2: 2100 movs r1, #0 +10041fc4: f7ff fe1a bl 10041bfc +10041fc8: 2800 cmp r0, #0 +10041fca: d140 bne.n 1004204e +10041fcc: 6869 ldr r1, [r5, #4] +10041fce: 982c ldr r0, [sp, #176] ; 0xb0 +10041fd0: 2201 movs r2, #1 +10041fd2: f7ff fe5e bl 10041c92 +10041fd6: 2800 cmp r0, #0 +10041fd8: d139 bne.n 1004204e +10041fda: 68e9 ldr r1, [r5, #12] +10041fdc: 68a8 ldr r0, [r5, #8] +10041fde: 2201 movs r2, #1 +10041fe0: f7ff fe62 bl 10041ca8 +10041fe4: 2800 cmp r0, #0 +10041fe6: d132 bne.n 1004204e +10041fe8: 6969 ldr r1, [r5, #20] +10041fea: 6928 ldr r0, [r5, #16] +10041fec: 2201 movs r2, #1 +10041fee: f7ff fe66 bl 10041cbe +10041ff2: 2800 cmp r0, #0 +10041ff4: d12b bne.n 1004204e +10041ff6: 69e9 ldr r1, [r5, #28] +10041ff8: 69a8 ldr r0, [r5, #24] +10041ffa: 2201 movs r2, #1 +10041ffc: f7ff fe6a bl 10041cd4 +10042000: bb28 cbnz r0, 1004204e +10042002: 6ae0 ldr r0, [r4, #44] ; 0x2c +10042004: f7ff ff9a bl 10041f3c <.text_52+0x2> +10042008: bb08 cbnz r0, 1004204e +1004200a: 6a69 ldr r1, [r5, #36] ; 0x24 +1004200c: 6a28 ldr r0, [r5, #32] +1004200e: 2201 movs r2, #1 +10042010: f7ff fe6b bl 10041cea +10042014: b9d8 cbnz r0, 1004204e +10042016: 6b20 ldr r0, [r4, #48] ; 0x30 +10042018: f7ff ff8d bl 10041f36 <.text_51+0x2> +1004201c: b9b8 cbnz r0, 1004204e +1004201e: 6b60 ldr r0, [r4, #52] ; 0x34 +10042020: f7ff ff86 bl 10041f30 <.text_50+0x2> +10042024: b998 cbnz r0, 1004204e +10042026: 6ba0 ldr r0, [r4, #56] ; 0x38 +10042028: f7ff ff73 bl 10041f12 <.text_43+0x2> +1004202c: b978 cbnz r0, 1004204e +1004202e: 6be0 ldr r0, [r4, #60] ; 0x3c +10042030: f7ff ff6c bl 10041f0c <.text_42+0x2> +10042034: b958 cbnz r0, 1004204e +10042036: 6c20 ldr r0, [r4, #64] ; 0x40 +10042038: f7ff ff6e bl 10041f18 <.text_46+0x2> +1004203c: b938 cbnz r0, 1004204e +1004203e: 9801 ldr r0, [sp, #4] +10042040: 2100 movs r1, #0 +10042042: f7ff fdb5 bl 10041bb0 +10042046: b910 cbnz r0, 1004204e +10042048: 6ca0 ldr r0, [r4, #72] ; 0x48 +1004204a: f000 f8bb bl 100421c4 <.text_63+0x2> +1004204e: 2000 movs r0, #0 +10042050: b07d add sp, #500 ; 0x1f4 +10042052: bd30 pop {r4, r5, pc} + +10042054 : +10042054: b5f0 push {r4, r5, r6, r7, lr} +10042056: 2800 cmp r0, #0 +10042058: b0fd sub sp, #500 ; 0x1f4 +1004205a: d062 beq.n 10042122 +1004205c: f000 f8ec bl 10042238 <.text_71> +10042060: 2800 cmp r0, #0 +10042062: d45e bmi.n 10042122 +10042064: f000 f8a9 bl 100421ba <.text_62> +10042068: bf14 ite ne +1004206a: 2501 movne r5, #1 +1004206c: 2500 moveq r5, #0 +1004206e: f000 f8dc bl 1004222a <.text_69+0x2> +10042072: 2800 cmp r0, #0 +10042074: d154 bne.n 10042120 +10042076: f000 f8a7 bl 100421c8 <.text_64> +1004207a: 2800 cmp r0, #0 +1004207c: d150 bne.n 10042120 +1004207e: f7ff ff5f bl 10041f40 <.text_53> +10042082: 2800 cmp r0, #0 +10042084: d14c bne.n 10042120 +10042086: 68f0 ldr r0, [r6, #12] +10042088: f000 f856 bl 10042138 <.text_58+0x2> +1004208c: 2800 cmp r0, #0 +1004208e: d147 bne.n 10042120 +10042090: 6930 ldr r0, [r6, #16] +10042092: 2101 movs r1, #1 +10042094: f7ff fdc2 bl 10041c1c +10042098: 2800 cmp r0, #0 +1004209a: d141 bne.n 10042120 +1004209c: f7ff ff44 bl 10041f28 <.text_49> +100420a0: 2800 cmp r0, #0 +100420a2: d13d bne.n 10042120 +100420a4: f7ff ff3d bl 10041f22 <.text_48> +100420a8: 2800 cmp r0, #0 +100420aa: d139 bne.n 10042120 +100420ac: f7ff ff36 bl 10041f1c <.text_47> +100420b0: 2800 cmp r0, #0 +100420b2: d135 bne.n 10042120 +100420b4: f000 f83b bl 1004212e <.text_56> +100420b8: 2800 cmp r0, #0 +100420ba: d131 bne.n 10042120 +100420bc: af2c add r7, sp, #176 ; 0xb0 +100420be: 982c ldr r0, [sp, #176] ; 0xb0 +100420c0: 6879 ldr r1, [r7, #4] +100420c2: 2201 movs r2, #1 +100420c4: f7ff fde5 bl 10041c92 +100420c8: 2800 cmp r0, #0 +100420ca: d129 bne.n 10042120 +100420cc: 68f9 ldr r1, [r7, #12] +100420ce: 68b8 ldr r0, [r7, #8] +100420d0: 2201 movs r2, #1 +100420d2: f7ff fde9 bl 10041ca8 +100420d6: bb18 cbnz r0, 10042120 +100420d8: 6979 ldr r1, [r7, #20] +100420da: 6938 ldr r0, [r7, #16] +100420dc: 2201 movs r2, #1 +100420de: f7ff fdee bl 10041cbe +100420e2: b9e8 cbnz r0, 10042120 +100420e4: 69f9 ldr r1, [r7, #28] +100420e6: 69b8 ldr r0, [r7, #24] +100420e8: 2201 movs r2, #1 +100420ea: f7ff fdf3 bl 10041cd4 +100420ee: b9b8 cbnz r0, 10042120 +100420f0: f7ff ff23 bl 10041f3a <.text_52> +100420f4: b9a0 cbnz r0, 10042120 +100420f6: 6a79 ldr r1, [r7, #36] ; 0x24 +100420f8: 6a38 ldr r0, [r7, #32] +100420fa: 2201 movs r2, #1 +100420fc: f7ff fdf5 bl 10041cea +10042100: b970 cbnz r0, 10042120 +10042102: f7ff ff17 bl 10041f34 <.text_51> +10042106: b958 cbnz r0, 10042120 +10042108: f7ff ff11 bl 10041f2e <.text_50> +1004210c: b940 cbnz r0, 10042120 +1004210e: f7ff feff bl 10041f10 <.text_43> +10042112: b928 cbnz r0, 10042120 +10042114: f7ff feff bl 10041f16 <.text_46> +10042118: b910 cbnz r0, 10042120 +1004211a: f000 f859 bl 100421d0 <.text_65> +1004211e: b118 cbz r0, 10042128 +10042120: b115 cbz r5, 10042128 +10042122: f04f 30ff mov.w r0, #4294967295 +10042126: e000 b.n 1004212a +10042128: 2000 movs r0, #0 +1004212a: b07d add sp, #500 ; 0x1f4 +1004212c: bdf0 pop {r4, r5, r6, r7, pc} + +1004212e <.text_56>: +1004212e: 6a70 ldr r0, [r6, #36] ; 0x24 +10042130: 2201 movs r2, #1 +10042132: 4629 mov r1, r5 +10042134: e562 b.n 10041bfc + +10042136 <.text_58>: +10042136: 9804 ldr r0, [sp, #16] +10042138: 2101 movs r1, #1 +1004213a: e5f9 b.n 10041d30 + +1004213c : +1004213c: b570 push {r4, r5, r6, lr} +1004213e: b0fe sub sp, #504 ; 0x1f8 +10042140: b308 cbz r0, 10042186 +10042142: f000 f879 bl 10042238 <.text_71> +10042146: 2800 cmp r0, #0 +10042148: d41d bmi.n 10042186 +1004214a: f000 f836 bl 100421ba <.text_62> +1004214e: bf14 ite ne +10042150: 2501 movne r5, #1 +10042152: 2500 moveq r5, #0 +10042154: f000 f869 bl 1004222a <.text_69+0x2> +10042158: b9a0 cbnz r0, 10042184 +1004215a: f000 f835 bl 100421c8 <.text_64> +1004215e: b988 cbnz r0, 10042184 +10042160: f7ff feee bl 10041f40 <.text_53> +10042164: b970 cbnz r0, 10042184 +10042166: 6cf0 ldr r0, [r6, #76] ; 0x4c +10042168: 2800 cmp r0, #0 +1004216a: bf1c itt ne +1004216c: 6d30 ldrne r0, [r6, #80] ; 0x50 +1004216e: 2800 cmpne r0, #0 +10042170: d008 beq.n 10042184 +10042172: f000 f85d bl 10042230 <.text_70> +10042176: b928 cbnz r0, 10042184 +10042178: f000 f82a bl 100421d0 <.text_65> +1004217c: b910 cbnz r0, 10042184 +1004217e: f000 f820 bl 100421c2 <.text_63> +10042182: b118 cbz r0, 1004218c +10042184: b115 cbz r5, 1004218c +10042186: f04f 30ff mov.w r0, #4294967295 +1004218a: e000 b.n 1004218e +1004218c: 2000 movs r0, #0 +1004218e: b07e add sp, #504 ; 0x1f8 +10042190: bd70 pop {r4, r5, r6, pc} + +10042192 : +10042192: b510 push {r4, lr} +10042194: b0fe sub sp, #504 ; 0x1f8 +10042196: 460c mov r4, r1 +10042198: b148 cbz r0, 100421ae +1004219a: f000 f84d bl 10042238 <.text_71> +1004219e: 2800 cmp r0, #0 +100421a0: d405 bmi.n 100421ae +100421a2: 9818 ldr r0, [sp, #96] ; 0x60 +100421a4: b110 cbz r0, 100421ac +100421a6: f000 f817 bl 100421d8 <.text_67> +100421aa: b118 cbz r0, 100421b4 +100421ac: b114 cbz r4, 100421b4 +100421ae: f04f 30ff mov.w r0, #4294967295 +100421b2: e000 b.n 100421b6 +100421b4: 2000 movs r0, #0 +100421b6: b07e add sp, #504 ; 0x1f8 +100421b8: bd10 pop {r4, pc} + +100421ba <.text_62>: +100421ba: 9c01 ldr r4, [sp, #4] +100421bc: 9800 ldr r0, [sp, #0] +100421be: 2c00 cmp r4, #0 +100421c0: 4770 bx lr + +100421c2 <.text_63>: +100421c2: 6cb0 ldr r0, [r6, #72] ; 0x48 +100421c4: 2101 movs r1, #1 +100421c6: e624 b.n 10041e12 + +100421c8 <.text_64>: +100421c8: ae01 add r6, sp, #4 +100421ca: 2101 movs r1, #1 +100421cc: 6870 ldr r0, [r6, #4] +100421ce: e597 b.n 10041d00 + +100421d0 <.text_65>: +100421d0: 4629 mov r1, r5 +100421d2: 4620 mov r0, r4 +100421d4: f7ff bcec b.w 10041bb0 + +100421d8 <.text_67>: +100421d8: 981c ldr r0, [sp, #112] ; 0x70 +100421da: 2101 movs r1, #1 +100421dc: e626 b.n 10041e2c + +100421de : +100421de: b570 push {r4, r5, r6, lr} +100421e0: b0fe sub sp, #504 ; 0x1f8 +100421e2: b1d8 cbz r0, 1004221c +100421e4: f000 f828 bl 10042238 <.text_71> +100421e8: 2800 cmp r0, #0 +100421ea: d417 bmi.n 1004221c +100421ec: f7ff ffe5 bl 100421ba <.text_62> +100421f0: bf14 ite ne +100421f2: 2501 movne r5, #1 +100421f4: 2500 moveq r5, #0 +100421f6: f000 f818 bl 1004222a <.text_69+0x2> +100421fa: b970 cbnz r0, 1004221a +100421fc: f7ff ffe4 bl 100421c8 <.text_64> +10042200: b958 cbnz r0, 1004221a +10042202: f7ff fe9d bl 10041f40 <.text_53> +10042206: b940 cbnz r0, 1004221a +10042208: f000 f812 bl 10042230 <.text_70> +1004220c: b928 cbnz r0, 1004221a +1004220e: f7ff ffdf bl 100421d0 <.text_65> +10042212: b910 cbnz r0, 1004221a +10042214: f7ff ffd5 bl 100421c2 <.text_63> +10042218: b118 cbz r0, 10042222 +1004221a: b115 cbz r5, 10042222 +1004221c: f04f 30ff mov.w r0, #4294967295 +10042220: e000 b.n 10042224 +10042222: 2000 movs r0, #0 +10042224: b07e add sp, #504 ; 0x1f8 +10042226: bd70 pop {r4, r5, r6, pc} + +10042228 <.text_69>: +10042228: 9800 ldr r0, [sp, #0] +1004222a: 2101 movs r1, #1 +1004222c: f7ff bcb7 b.w 10041b9e + +10042230 <.text_70>: +10042230: 9939 ldr r1, [sp, #228] ; 0xe4 +10042232: 9838 ldr r0, [sp, #224] ; 0xe0 +10042234: 2201 movs r2, #1 +10042236: e5f1 b.n 10041e1c + +10042238 <.text_71>: +10042238: a900 add r1, sp, #0 +1004223a: f7ff bb87 b.w 1004194c + +1004223e : +1004223e: b510 push {r4, lr} +10042240: b0fe sub sp, #504 ; 0x1f8 +10042242: 460c mov r4, r1 +10042244: b148 cbz r0, 1004225a +10042246: f7ff fff7 bl 10042238 <.text_71> +1004224a: 2800 cmp r0, #0 +1004224c: d405 bmi.n 1004225a +1004224e: 9819 ldr r0, [sp, #100] ; 0x64 +10042250: b110 cbz r0, 10042258 +10042252: f7ff ffc1 bl 100421d8 <.text_67> +10042256: b118 cbz r0, 10042260 +10042258: b114 cbz r4, 10042260 +1004225a: f04f 30ff mov.w r0, #4294967295 +1004225e: e000 b.n 10042262 +10042260: 2000 movs r0, #0 +10042262: b07e add sp, #504 ; 0x1f8 +10042264: bd10 pop {r4, pc} + +10042266 : +10042266: b570 push {r4, r5, r6, lr} +10042268: b0fe sub sp, #504 ; 0x1f8 +1004226a: b1d8 cbz r0, 100422a4 +1004226c: f7ff ffe4 bl 10042238 <.text_71> +10042270: 2800 cmp r0, #0 +10042272: d417 bmi.n 100422a4 +10042274: f7ff ffa1 bl 100421ba <.text_62> +10042278: bf14 ite ne +1004227a: 2501 movne r5, #1 +1004227c: 2500 moveq r5, #0 +1004227e: f7ff ffd4 bl 1004222a <.text_69+0x2> +10042282: b970 cbnz r0, 100422a2 +10042284: f7ff ffa0 bl 100421c8 <.text_64> +10042288: b958 cbnz r0, 100422a2 +1004228a: f7ff fe59 bl 10041f40 <.text_53> +1004228e: b940 cbnz r0, 100422a2 +10042290: f7ff ffce bl 10042230 <.text_70> +10042294: b928 cbnz r0, 100422a2 +10042296: f7ff ff9b bl 100421d0 <.text_65> +1004229a: b910 cbnz r0, 100422a2 +1004229c: f7ff ff91 bl 100421c2 <.text_63> +100422a0: b118 cbz r0, 100422aa +100422a2: b115 cbz r5, 100422aa +100422a4: f04f 30ff mov.w r0, #4294967295 +100422a8: e000 b.n 100422ac +100422aa: 2000 movs r0, #0 +100422ac: b07e add sp, #504 ; 0x1f8 +100422ae: bd70 pop {r4, r5, r6, pc} + +100422b0 : +100422b0: b570 push {r4, r5, r6, lr} +100422b2: 2800 cmp r0, #0 +100422b4: b0fe sub sp, #504 ; 0x1f8 +100422b6: 460c mov r4, r1 +100422b8: 4615 mov r5, r2 +100422ba: d038 beq.n 1004232e +100422bc: f7ff ffbc bl 10042238 <.text_71> +100422c0: 2800 cmp r0, #0 +100422c2: d434 bmi.n 1004232e +100422c4: ae1c add r6, sp, #112 ; 0x70 +100422c6: 6ff1 ldr r1, [r6, #124] ; 0x7c +100422c8: 6fb0 ldr r0, [r6, #120] ; 0x78 +100422ca: 4622 mov r2, r4 +100422cc: f7ff fdb3 bl 10041e36 +100422d0: bb60 cbnz r0, 1004232c +100422d2: 6870 ldr r0, [r6, #4] +100422d4: 4621 mov r1, r4 +100422d6: f7ff fd4f bl 10041d78 +100422da: bb38 cbnz r0, 1004232c +100422dc: 68b0 ldr r0, [r6, #8] +100422de: 4621 mov r1, r4 +100422e0: f7ff fd6e bl 10041dc0 +100422e4: bb10 cbnz r0, 1004232c +100422e6: 6930 ldr r0, [r6, #16] +100422e8: 2100 movs r1, #0 +100422ea: f7ff fdb1 bl 10041e50 +100422ee: b9e8 cbnz r0, 1004232c +100422f0: 6970 ldr r0, [r6, #20] +100422f2: 4621 mov r1, r4 +100422f4: f7ff fd0e bl 10041d14 +100422f8: b9c0 cbnz r0, 1004232c +100422fa: 1e60 subs r0, r4, #1 +100422fc: 4180 sbcs r0, r0 +100422fe: 9c5c ldr r4, [sp, #368] ; 0x170 +10042300: 0fc0 lsrs r0, r0, #31 +10042302: b90c cbnz r4, 10042308 +10042304: b990 cbnz r0, 1004232c +10042306: e00e b.n 10042326 +10042308: 2600 movs r6, #0 +1004230a: a800 add r0, sp, #0 +1004230c: eb00 0086 add.w r0, r0, r6, lsl #2 +10042310: f8d0 1148 ldr.w r1, [r0, #328] ; 0x148 +10042314: f8d0 0120 ldr.w r0, [r0, #288] ; 0x120 +10042318: f7ff fdb6 bl 10041e88 +1004231c: 2800 cmp r0, #0 +1004231e: d405 bmi.n 1004232c +10042320: 1c76 adds r6, r6, #1 +10042322: 42a6 cmp r6, r4 +10042324: d3f1 bcc.n 1004230a +10042326: f7ff ff57 bl 100421d8 <.text_67> +1004232a: b118 cbz r0, 10042334 +1004232c: b115 cbz r5, 10042334 +1004232e: f04f 30ff mov.w r0, #4294967295 +10042332: e000 b.n 10042336 +10042334: 2000 movs r0, #0 +10042336: b07e add sp, #504 ; 0x1f8 +10042338: bd70 pop {r4, r5, r6, pc} + +1004233a : +1004233a: b530 push {r4, r5, lr} +1004233c: b0fd sub sp, #500 ; 0x1f4 +1004233e: b1c8 cbz r0, 10042374 +10042340: f7ff ff7a bl 10042238 <.text_71> +10042344: 2800 cmp r0, #0 +10042346: d415 bmi.n 10042374 +10042348: f7ff ff37 bl 100421ba <.text_62> +1004234c: bf14 ite ne +1004234e: 2501 movne r5, #1 +10042350: 2500 moveq r5, #0 +10042352: f7ff ff6a bl 1004222a <.text_69+0x2> +10042356: b960 cbnz r0, 10042372 +10042358: f000 f839 bl 100423ce <.text_79> +1004235c: b948 cbnz r0, 10042372 +1004235e: 9803 ldr r0, [sp, #12] +10042360: f7ff fdef bl 10041f42 <.text_53+0x2> +10042364: b928 cbnz r0, 10042372 +10042366: f7ff fee6 bl 10042136 <.text_58> +1004236a: b910 cbnz r0, 10042372 +1004236c: f7ff ff30 bl 100421d0 <.text_65> +10042370: b118 cbz r0, 1004237a +10042372: b115 cbz r5, 1004237a +10042374: f04f 30ff mov.w r0, #4294967295 +10042378: e000 b.n 1004237c +1004237a: 2000 movs r0, #0 +1004237c: b07d add sp, #500 ; 0x1f4 +1004237e: bd30 pop {r4, r5, pc} + +10042380 : +10042380: b530 push {r4, r5, lr} +10042382: b0fd sub sp, #500 ; 0x1f4 +10042384: b1e8 cbz r0, 100423c2 +10042386: f7ff ff57 bl 10042238 <.text_71> +1004238a: 2800 cmp r0, #0 +1004238c: d419 bmi.n 100423c2 +1004238e: f7ff ff14 bl 100421ba <.text_62> +10042392: bf14 ite ne +10042394: 2501 movne r5, #1 +10042396: 2500 moveq r5, #0 +10042398: f7ff ff47 bl 1004222a <.text_69+0x2> +1004239c: b980 cbnz r0, 100423c0 +1004239e: f000 f816 bl 100423ce <.text_79> +100423a2: b968 cbnz r0, 100423c0 +100423a4: 9803 ldr r0, [sp, #12] +100423a6: f7ff fdcc bl 10041f42 <.text_53+0x2> +100423aa: b948 cbnz r0, 100423c0 +100423ac: f7ff fec3 bl 10042136 <.text_58> +100423b0: b930 cbnz r0, 100423c0 +100423b2: 980f ldr r0, [sp, #60] ; 0x3c +100423b4: f7ff fdad bl 10041f12 <.text_43+0x2> +100423b8: b910 cbnz r0, 100423c0 +100423ba: f7ff ff09 bl 100421d0 <.text_65> +100423be: b118 cbz r0, 100423c8 +100423c0: b115 cbz r5, 100423c8 +100423c2: f04f 30ff mov.w r0, #4294967295 +100423c6: e000 b.n 100423ca +100423c8: 2000 movs r0, #0 +100423ca: b07d add sp, #500 ; 0x1f4 +100423cc: bd30 pop {r4, r5, pc} + +100423ce <.text_79>: +100423ce: 9802 ldr r0, [sp, #8] +100423d0: 2101 movs r1, #1 +100423d2: f7ff bc95 b.w 10041d00 + ... + +100423d8 : +100423d8: b580 push {r7, lr} +100423da: 4802 ldr r0, [pc, #8] ; (100423e4 ) +100423dc: f7de fa24 bl 10020828 +100423e0: 2000 movs r0, #0 +100423e2: bd02 pop {r1, pc} +100423e4: 10000318 .word 0x10000318 + +100423e8 : +100423e8: 4770 bx lr + ... + +100423ec <_AppStart>: +100423ec: b580 push {r7, lr} +100423ee: 4806 ldr r0, [pc, #24] ; (10042408 <.text_5>) +100423f0: 6801 ldr r1, [r0, #0] +100423f2: f431 5180 bics.w r1, r1, #4096 ; 0x1000 +100423f6: 6001 str r1, [r0, #0] +100423f8: 4668 mov r0, sp +100423fa: f020 0007 bic.w r0, r0, #7 +100423fe: 4685 mov sp, r0 +10042400: f7fd f978 bl 1003f6f4
+10042404: bd01 pop {r0, pc} + ... + +10042408 <.text_5>: +10042408: 10000310 .word 0x10000310 + +1004240c : +1004240c: b510 push {r4, lr} +1004240e: 4604 mov r4, r0 +10042410: f641 5048 movw r0, #7496 ; 0x1d48 +10042414: 1901 adds r1, r0, r4 +10042416: 7a49 ldrb r1, [r1, #9] +10042418: 2900 cmp r1, #0 +1004241a: bf1e ittt ne +1004241c: 5900 ldrne r0, [r0, r4] +1004241e: 2800 cmpne r0, #0 +10042420: 4604 movne r4, r0 +10042422: f504 50e5 add.w r0, r4, #7328 ; 0x1ca0 +10042426: 6800 ldr r0, [r0, #0] +10042428: b958 cbnz r0, 10042442 +1004242a: f504 50e0 add.w r0, r4, #7168 ; 0x1c00 +1004242e: 6801 ldr r1, [r0, #0] +10042430: 0008 movs r0, r1 +10042432: bf1c itt ne +10042434: 4620 movne r0, r4 +10042436: 4788 blxne r1 +10042438: 4620 mov r0, r4 +1004243a: e8bd 4010 ldmia.w sp!, {r4, lr} +1004243e: f7d4 bfcb b.w 100173d8 +10042442: bd10 pop {r4, pc} + +10042444 : +10042444: b580 push {r7, lr} +10042446: 2024 movs r0, #36 ; 0x24 +10042448: f7ce f9db bl 10010802 +1004244c: b180 cbz r0, 10042470 +1004244e: 4935 ldr r1, [pc, #212] ; (10042524 <.text_9>) +10042450: 6b4a ldr r2, [r1, #52] ; 0x34 +10042452: f042 0201 orr.w r2, r2, #1 +10042456: 634a str r2, [r1, #52] ; 0x34 +10042458: 6b4a ldr r2, [r1, #52] ; 0x34 +1004245a: f042 0202 orr.w r2, r2, #2 +1004245e: 634a str r2, [r1, #52] ; 0x34 +10042460: 680a ldr r2, [r1, #0] +10042462: f042 0204 orr.w r2, r2, #4 +10042466: 600a str r2, [r1, #0] +10042468: 684a ldr r2, [r1, #4] +1004246a: f442 3280 orr.w r2, r2, #65536 ; 0x10000 +1004246e: 604a str r2, [r1, #4] +10042470: bd02 pop {r1, pc} + +10042472 : +10042472: b580 push {r7, lr} +10042474: b110 cbz r0, 1004247c +10042476: 2124 movs r1, #36 ; 0x24 +10042478: f7ce f9c8 bl 1001080c +1004247c: 482a ldr r0, [pc, #168] ; (10042528 <.text_10>) +1004247e: 6800 ldr r0, [r0, #0] +10042480: 4828 ldr r0, [pc, #160] ; (10042524 <.text_9>) +10042482: 6841 ldr r1, [r0, #4] +10042484: f421 3180 bic.w r1, r1, #65536 ; 0x10000 +10042488: 6041 str r1, [r0, #4] +1004248a: 6801 ldr r1, [r0, #0] +1004248c: f021 0104 bic.w r1, r1, #4 +10042490: 6001 str r1, [r0, #0] +10042492: 6b41 ldr r1, [r0, #52] ; 0x34 +10042494: 0849 lsrs r1, r1, #1 +10042496: 0049 lsls r1, r1, #1 +10042498: 6341 str r1, [r0, #52] ; 0x34 +1004249a: 6b41 ldr r1, [r0, #52] ; 0x34 +1004249c: f021 0102 bic.w r1, r1, #2 +100424a0: 6341 str r1, [r0, #52] ; 0x34 +100424a2: bd01 pop {r0, pc} + +100424a4 : +100424a4: b530 push {r4, r5, lr} +100424a6: b089 sub sp, #36 ; 0x24 +100424a8: 4604 mov r4, r0 +100424aa: f000 f831 bl 10042510 <.text_8> +100424ae: f7c4 fbbf bl 10006c30 +100424b2: a804 add r0, sp, #16 +100424b4: f7c4 fbc0 bl 10006c38 +100424b8: f000 f822 bl 10042500 <.text_7> +100424bc: f7c4 fbb8 bl 10006c30 +100424c0: a800 add r0, sp, #0 +100424c2: f7c4 fbb9 bl 10006c38 +100424c6: 2001 movs r0, #1 +100424c8: 7720 strb r0, [r4, #28] +100424ca: 7760 strb r0, [r4, #29] +100424cc: b009 add sp, #36 ; 0x24 +100424ce: bd30 pop {r4, r5, pc} + +100424d0 : +100424d0: b530 push {r4, r5, lr} +100424d2: 4604 mov r4, r0 +100424d4: b089 sub sp, #36 ; 0x24 +100424d6: 7f20 ldrb r0, [r4, #28] +100424d8: b180 cbz r0, 100424fc +100424da: f000 f819 bl 10042510 <.text_8> +100424de: f7dd fef7 bl 100202d0 +100424e2: a804 add r0, sp, #16 +100424e4: f7dd fef8 bl 100202d8 +100424e8: f000 f80a bl 10042500 <.text_7> +100424ec: f7dd fef0 bl 100202d0 +100424f0: a800 add r0, sp, #0 +100424f2: f7dd fef1 bl 100202d8 +100424f6: 2000 movs r0, #0 +100424f8: 7760 strb r0, [r4, #29] +100424fa: 7720 strb r0, [r4, #28] +100424fc: b009 add sp, #36 ; 0x24 +100424fe: bd30 pop {r4, r5, pc} + +10042500 <.text_7>: +10042500: 2010 movs r0, #16 +10042502: 9001 str r0, [sp, #4] +10042504: 9402 str r4, [sp, #8] +10042506: 200f movs r0, #15 +10042508: 9003 str r0, [sp, #12] +1004250a: 9500 str r5, [sp, #0] +1004250c: a800 add r0, sp, #0 +1004250e: 4770 bx lr + +10042510 <.text_8>: +10042510: 200f movs r0, #15 +10042512: 9005 str r0, [sp, #20] +10042514: 9406 str r4, [sp, #24] +10042516: 200e movs r0, #14 +10042518: 9007 str r0, [sp, #28] +1004251a: a804 add r0, sp, #16 +1004251c: 4d03 ldr r5, [pc, #12] ; (1004252c <.text_11>) +1004251e: 9504 str r5, [sp, #16] +10042520: 4770 bx lr + ... + +10042524 <.text_9>: +10042524: 40000210 .word 0x40000210 + +10042528 <.text_10>: +10042528: 40080000 .word 0x40080000 + +1004252c <.text_11>: +1004252c: 10042531 .word 0x10042531 + +10042530 : +10042530: b570 push {r4, r5, r6, lr} +10042532: 4605 mov r5, r0 +10042534: b082 sub sp, #8 +10042536: 682c ldr r4, [r5, #0] +10042538: 2000 movs r0, #0 +1004253a: 9000 str r0, [sp, #0] +1004253c: f641 36a4 movw r6, #7076 ; 0x1ba4 +10042540: 5930 ldr r0, [r6, r4] +10042542: f500 5024 add.w r0, r0, #10496 ; 0x2900 +10042546: f810 1fa4 ldrb.w r1, [r0, #164]! +1004254a: 07c9 lsls r1, r1, #31 +1004254c: bf48 it mi +1004254e: f7d0 fbb5 blmi 10012cbc +10042552: 5930 ldr r0, [r6, r4] +10042554: f642 114c movw r1, #10572 ; 0x294c +10042558: 580a ldr r2, [r1, r0] +1004255a: 1c52 adds r2, r2, #1 +1004255c: 500a str r2, [r1, r0] +1004255e: 7f68 ldrb r0, [r5, #29] +10042560: b300 cbz r0, 100425a4 +10042562: 4620 mov r0, r4 +10042564: f7de ffc7 bl 100214f6 +10042568: 4620 mov r0, r4 +1004256a: f7de ff05 bl 10021378 +1004256e: 490e ldr r1, [pc, #56] ; (100425a8 <.text_4>) +10042570: 680d ldr r5, [r1, #0] +10042572: b93d cbnz r5, 10042584 +10042574: 225b movs r2, #91 ; 0x5b +10042576: f20f 0138 addw r1, pc, #56 ; 0x38 +1004257a: f20f 0050 addw r0, pc, #80 ; 0x50 +1004257e: f7c9 fec0 bl 1000c302 +10042582: e00f b.n 100425a4 +10042584: b158 cbz r0, 1004259e +10042586: 6828 ldr r0, [r5, #0] +10042588: 2300 movs r3, #0 +1004258a: aa00 add r2, sp, #0 +1004258c: 2100 movs r1, #0 +1004258e: f7c8 f857 bl 1000a640 +10042592: 9800 ldr r0, [sp, #0] +10042594: b118 cbz r0, 1004259e +10042596: 4905 ldr r1, [pc, #20] ; (100425ac <.text_5>) +10042598: f04f 5080 mov.w r0, #268435456 ; 0x10000000 +1004259c: 6008 str r0, [r1, #0] +1004259e: 4620 mov r0, r4 +100425a0: f7de ff84 bl 100214ac +100425a4: 2001 movs r0, #1 +100425a6: bd76 pop {r1, r2, r4, r5, r6, pc} + +100425a8 <.text_4>: +100425a8: 10048828 .word 0x10048828 + +100425ac <.text_5>: +100425ac: e000ed04 .word 0xe000ed04 + +100425b0 : +100425b0: 7478656c 625f6172 645f7375 495f616d lextra_bus_dma_I +100425c0: 7265746e 74707572 00000000 nterrupt.... + +100425cc : +100425cc: 25287325 000a2964 %s(%d).. + +100425d4 : +100425d4: f500 70e0 add.w r0, r0, #448 ; 0x1c0 +100425d8: 6802 ldr r2, [r0, #0] +100425da: 4291 cmp r1, r2 +100425dc: d303 bcc.n 100425e6 +100425de: 6843 ldr r3, [r0, #4] +100425e0: 189a adds r2, r3, r2 +100425e2: 4291 cmp r1, r2 +100425e4: d302 bcc.n 100425ec +100425e6: 6880 ldr r0, [r0, #8] +100425e8: 2800 cmp r0, #0 +100425ea: d1f5 bne.n 100425d8 +100425ec: 4770 bx lr + +100425ee : +100425ee: f8df 0760 ldr.w r0, [pc, #1888] ; 10042d50 <.text_12> +100425f2: 6801 ldr r1, [r0, #0] +100425f4: b991 cbnz r1, 1004261c +100425f6: f8df 275c ldr.w r2, [pc, #1884] ; 10042d54 <.text_13> +100425fa: f44f 3180 mov.w r1, #65536 ; 0x10000 +100425fe: 6081 str r1, [r0, #8] +10042600: f44f 5180 mov.w r1, #4096 ; 0x1000 +10042604: 6041 str r1, [r0, #4] +10042606: f04f 31ff mov.w r1, #4294967295 +1004260a: 60c1 str r1, [r0, #12] +1004260c: 6101 str r1, [r0, #16] +1004260e: 2104 movs r1, #4 +10042610: 6141 str r1, [r0, #20] +10042612: f8c2 11bc str.w r1, [r2, #444] ; 0x1bc +10042616: f8df 1740 ldr.w r1, [pc, #1856] ; 10042d58 <.text_14> +1004261a: 6001 str r1, [r0, #0] +1004261c: 2001 movs r0, #1 +1004261e: 4770 bx lr + +10042620 : +10042620: f101 0308 add.w r3, r1, #8 +10042624: f013 0307 ands.w r3, r3, #7 +10042628: d005 beq.n 10042636 +1004262a: f101 0308 add.w r3, r1, #8 +1004262e: f1c3 0308 rsb r3, r3, #8 +10042632: f003 0307 and.w r3, r3, #7 +10042636: 1859 adds r1, r3, r1 +10042638: 1ad2 subs r2, r2, r3 +1004263a: 6181 str r1, [r0, #24] +1004263c: 60c2 str r2, [r0, #12] +1004263e: f042 0301 orr.w r3, r2, #1 +10042642: 604b str r3, [r1, #4] +10042644: 1851 adds r1, r2, r1 +10042646: 2328 movs r3, #40 ; 0x28 +10042648: 604b str r3, [r1, #4] +1004264a: f8df 1704 ldr.w r1, [pc, #1796] ; 10042d50 <.text_12> +1004264e: 6909 ldr r1, [r1, #16] +10042650: 61c1 str r1, [r0, #28] +10042652: 4770 bx lr + +10042654 : +10042654: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +10042658: 4606 mov r6, r0 +1004265a: f101 0008 add.w r0, r1, #8 +1004265e: b083 sub sp, #12 +10042660: f010 0007 ands.w r0, r0, #7 +10042664: bf08 it eq +10042666: 4688 moveq r8, r1 +10042668: d007 beq.n 1004267a +1004266a: f101 0008 add.w r0, r1, #8 +1004266e: f1c0 0008 rsb r0, r0, #8 +10042672: f000 0007 and.w r0, r0, #7 +10042676: eb00 0801 add.w r8, r0, r1 +1004267a: f102 0008 add.w r0, r2, #8 +1004267e: f010 0007 ands.w r0, r0, #7 +10042682: d006 beq.n 10042692 +10042684: f102 0008 add.w r0, r2, #8 +10042688: f1c0 0008 rsb r0, r0, #8 +1004268c: f000 0007 and.w r0, r0, #7 +10042690: 1882 adds r2, r0, r2 +10042692: 4615 mov r5, r2 +10042694: eba5 0008 sub.w r0, r5, r8 +10042698: eba0 0903 sub.w r9, r0, r3 +1004269c: eb03 0b08 add.w fp, r3, r8 +100426a0: f043 0003 orr.w r0, r3, #3 +100426a4: f8c8 0004 str.w r0, [r8, #4] +100426a8: 45ab cmp fp, r5 +100426aa: bf28 it cs +100426ac: f001 fa12 blcs 10043ad4 +100426b0: 7928 ldrb r0, [r5, #4] +100426b2: 07c0 lsls r0, r0, #31 +100426b4: bf58 it pl +100426b6: f001 fa0d blpl 10043ad4 +100426ba: f1b9 0f10 cmp.w r9, #16 +100426be: bf38 it cc +100426c0: f001 fa08 blcc 10043ad4 +100426c4: 69b0 ldr r0, [r6, #24] +100426c6: 4285 cmp r5, r0 +100426c8: d109 bne.n 100426de +100426ca: 68f0 ldr r0, [r6, #12] +100426cc: 4448 add r0, r9 +100426ce: 60f0 str r0, [r6, #12] +100426d0: f8c6 b018 str.w fp, [r6, #24] +100426d4: f040 0001 orr.w r0, r0, #1 +100426d8: f8cb 0004 str.w r0, [fp, #4] +100426dc: e16d b.n 100429ba +100426de: 6970 ldr r0, [r6, #20] +100426e0: 4285 cmp r5, r0 +100426e2: d10b bne.n 100426fc +100426e4: 68b0 ldr r0, [r6, #8] +100426e6: 4448 add r0, r9 +100426e8: 60b0 str r0, [r6, #8] +100426ea: f8c6 b014 str.w fp, [r6, #20] +100426ee: f040 0101 orr.w r1, r0, #1 +100426f2: f8cb 1004 str.w r1, [fp, #4] +100426f6: f840 000b str.w r0, [r0, fp] +100426fa: e15e b.n 100429ba +100426fc: 6868 ldr r0, [r5, #4] +100426fe: f000 0103 and.w r1, r0, #3 +10042702: 2901 cmp r1, #1 +10042704: f040 80ad bne.w 10042862 +10042708: 08c0 lsrs r0, r0, #3 +1004270a: 00c0 lsls r0, r0, #3 +1004270c: 9001 str r0, [sp, #4] +1004270e: 08c0 lsrs r0, r0, #3 +10042710: 2820 cmp r0, #32 +10042712: d23a bcs.n 1004278a +10042714: f8d5 a008 ldr.w sl, [r5, #8] +10042718: 68ef ldr r7, [r5, #12] +1004271a: 9000 str r0, [sp, #0] +1004271c: 42bd cmp r5, r7 +1004271e: bf08 it eq +10042720: f001 f9d8 bleq 10043ad4 +10042724: 4555 cmp r5, sl +10042726: bf08 it eq +10042728: f001 f9d4 bleq 10043ad4 +1004272c: 6868 ldr r0, [r5, #4] +1004272e: 9900 ldr r1, [sp, #0] +10042730: 08c0 lsrs r0, r0, #3 +10042732: 00c0 lsls r0, r0, #3 +10042734: ebb0 0fc1 cmp.w r0, r1, lsl #3 +10042738: bf18 it ne +1004273a: f001 f9cb blne 10043ad4 +1004273e: 9800 ldr r0, [sp, #0] +10042740: eb06 00c0 add.w r0, r6, r0, lsl #3 +10042744: f100 0128 add.w r1, r0, #40 ; 0x28 +10042748: 458a cmp sl, r1 +1004274a: d007 beq.n 1004275c +1004274c: 6931 ldr r1, [r6, #16] +1004274e: 458a cmp sl, r1 +10042750: f0c0 8082 bcc.w 10042858 +10042754: f8da 100c ldr.w r1, [sl, #12] +10042758: 42a9 cmp r1, r5 +1004275a: d17d bne.n 10042858 +1004275c: 4557 cmp r7, sl +1004275e: d106 bne.n 1004276e +10042760: 9a00 ldr r2, [sp, #0] +10042762: 6830 ldr r0, [r6, #0] +10042764: 2101 movs r1, #1 +10042766: 4091 lsls r1, r2 +10042768: 4388 bics r0, r1 +1004276a: 6030 str r0, [r6, #0] +1004276c: e076 b.n 1004285c +1004276e: 3028 adds r0, #40 ; 0x28 +10042770: 4287 cmp r7, r0 +10042772: d005 beq.n 10042780 +10042774: 6930 ldr r0, [r6, #16] +10042776: 4287 cmp r7, r0 +10042778: d36e bcc.n 10042858 +1004277a: 68b8 ldr r0, [r7, #8] +1004277c: 42a8 cmp r0, r5 +1004277e: d16b bne.n 10042858 +10042780: f8ca 700c str.w r7, [sl, #12] +10042784: f8c7 a008 str.w sl, [r7, #8] +10042788: e068 b.n 1004285c +1004278a: 68ef ldr r7, [r5, #12] +1004278c: f8d5 a018 ldr.w sl, [r5, #24] +10042790: 42af cmp r7, r5 +10042792: d00c beq.n 100427ae +10042794: 68a8 ldr r0, [r5, #8] +10042796: 6931 ldr r1, [r6, #16] +10042798: 4288 cmp r0, r1 +1004279a: d323 bcc.n 100427e4 +1004279c: 68c1 ldr r1, [r0, #12] +1004279e: 42a9 cmp r1, r5 +100427a0: bf04 itt eq +100427a2: 68b9 ldreq r1, [r7, #8] +100427a4: 42a9 cmpeq r1, r5 +100427a6: d11d bne.n 100427e4 +100427a8: 60c7 str r7, [r0, #12] +100427aa: 60b8 str r0, [r7, #8] +100427ac: e01c b.n 100427e8 +100427ae: f105 0014 add.w r0, r5, #20 +100427b2: 6807 ldr r7, [r0, #0] +100427b4: b937 cbnz r7, 100427c4 +100427b6: f105 0010 add.w r0, r5, #16 +100427ba: 6807 ldr r7, [r0, #0] +100427bc: b1a7 cbz r7, 100427e8 +100427be: e001 b.n 100427c4 +100427c0: 4608 mov r0, r1 +100427c2: 6807 ldr r7, [r0, #0] +100427c4: f107 0114 add.w r1, r7, #20 +100427c8: 680a ldr r2, [r1, #0] +100427ca: 2a00 cmp r2, #0 +100427cc: bf02 ittt eq +100427ce: f107 0110 addeq.w r1, r7, #16 +100427d2: 680a ldreq r2, [r1, #0] +100427d4: 2a00 cmpeq r2, #0 +100427d6: d1f3 bne.n 100427c0 +100427d8: 6931 ldr r1, [r6, #16] +100427da: 4288 cmp r0, r1 +100427dc: d302 bcc.n 100427e4 +100427de: 2100 movs r1, #0 +100427e0: 6001 str r1, [r0, #0] +100427e2: e001 b.n 100427e8 +100427e4: f001 f976 bl 10043ad4 +100427e8: f1ba 0f00 cmp.w sl, #0 +100427ec: d036 beq.n 1004285c +100427ee: 69e8 ldr r0, [r5, #28] +100427f0: eb06 0080 add.w r0, r6, r0, lsl #2 +100427f4: f500 7098 add.w r0, r0, #304 ; 0x130 +100427f8: 6801 ldr r1, [r0, #0] +100427fa: 428d cmp r5, r1 +100427fc: d108 bne.n 10042810 +100427fe: 6007 str r7, [r0, #0] +10042800: b9a7 cbnz r7, 1004282c +10042802: 69ea ldr r2, [r5, #28] +10042804: 6870 ldr r0, [r6, #4] +10042806: 2101 movs r1, #1 +10042808: 4091 lsls r1, r2 +1004280a: 4388 bics r0, r1 +1004280c: 6070 str r0, [r6, #4] +1004280e: e025 b.n 1004285c +10042810: 6930 ldr r0, [r6, #16] +10042812: 4582 cmp sl, r0 +10042814: d308 bcc.n 10042828 +10042816: f8da 0010 ldr.w r0, [sl, #16] +1004281a: 42a8 cmp r0, r5 +1004281c: bf14 ite ne +1004281e: f8ca 7014 strne.w r7, [sl, #20] +10042822: f8ca 7010 streq.w r7, [sl, #16] +10042826: e001 b.n 1004282c +10042828: f001 f954 bl 10043ad4 +1004282c: b1b7 cbz r7, 1004285c +1004282e: 6930 ldr r0, [r6, #16] +10042830: 4287 cmp r7, r0 +10042832: d311 bcc.n 10042858 +10042834: f8c7 a018 str.w sl, [r7, #24] +10042838: 6929 ldr r1, [r5, #16] +1004283a: b129 cbz r1, 10042848 +1004283c: 4281 cmp r1, r0 +1004283e: bf26 itte cs +10042840: 6139 strcs r1, [r7, #16] +10042842: 618f strcs r7, [r1, #24] +10042844: f001 f946 blcc 10043ad4 +10042848: 6968 ldr r0, [r5, #20] +1004284a: b138 cbz r0, 1004285c +1004284c: 6931 ldr r1, [r6, #16] +1004284e: 4288 cmp r0, r1 +10042850: d302 bcc.n 10042858 +10042852: 6178 str r0, [r7, #20] +10042854: 6187 str r7, [r0, #24] +10042856: e001 b.n 1004285c +10042858: f001 f93c bl 10043ad4 +1004285c: 9801 ldr r0, [sp, #4] +1004285e: 1945 adds r5, r0, r5 +10042860: 4481 add r9, r0 +10042862: 6868 ldr r0, [r5, #4] +10042864: 0840 lsrs r0, r0, #1 +10042866: 0040 lsls r0, r0, #1 +10042868: 6068 str r0, [r5, #4] +1004286a: ea4f 05d9 mov.w r5, r9, lsr #3 +1004286e: f049 0001 orr.w r0, r9, #1 +10042872: f8cb 0004 str.w r0, [fp, #4] +10042876: f849 900b str.w r9, [r9, fp] +1004287a: 2d20 cmp r5, #32 +1004287c: d223 bcs.n 100428c6 +1004287e: eb06 00c5 add.w r0, r6, r5, lsl #3 +10042882: f100 0728 add.w r7, r0, #40 ; 0x28 +10042886: 46ba mov sl, r7 +10042888: f1b9 0f10 cmp.w r9, #16 +1004288c: bf38 it cc +1004288e: f001 f921 blcc 10043ad4 +10042892: 6830 ldr r0, [r6, #0] +10042894: fa20 f105 lsr.w r1, r0, r5 +10042898: 07c9 lsls r1, r1, #31 +1004289a: d404 bmi.n 100428a6 +1004289c: 2101 movs r1, #1 +1004289e: 40a9 lsls r1, r5 +100428a0: 4308 orrs r0, r1 +100428a2: 6030 str r0, [r6, #0] +100428a4: e006 b.n 100428b4 +100428a6: 68b8 ldr r0, [r7, #8] +100428a8: 6931 ldr r1, [r6, #16] +100428aa: 4288 cmp r0, r1 +100428ac: bf2c ite cs +100428ae: 4682 movcs sl, r0 +100428b0: f001 f910 blcc 10043ad4 +100428b4: f8c7 b008 str.w fp, [r7, #8] +100428b8: f8ca b00c str.w fp, [sl, #12] +100428bc: f8cb a008 str.w sl, [fp, #8] +100428c0: f8cb 700c str.w r7, [fp, #12] +100428c4: e079 b.n 100429ba +100428c6: ea5f 2119 movs.w r1, r9, lsr #8 +100428ca: bf08 it eq +100428cc: 2000 moveq r0, #0 +100428ce: d023 beq.n 10042918 +100428d0: f5b1 3f80 cmp.w r1, #65536 ; 0x10000 +100428d4: bf28 it cs +100428d6: 201f movcs r0, #31 +100428d8: d21e bcs.n 10042918 +100428da: f5a1 7080 sub.w r0, r1, #256 ; 0x100 +100428de: 0c00 lsrs r0, r0, #16 +100428e0: f000 0008 and.w r0, r0, #8 +100428e4: 4081 lsls r1, r0 +100428e6: f5a1 5280 sub.w r2, r1, #4096 ; 0x1000 +100428ea: 0c12 lsrs r2, r2, #16 +100428ec: f002 0204 and.w r2, r2, #4 +100428f0: 4091 lsls r1, r2 +100428f2: f5a1 4380 sub.w r3, r1, #16384 ; 0x4000 +100428f6: 0c1b lsrs r3, r3, #16 +100428f8: f1c0 000e rsb r0, r0, #14 +100428fc: f003 0302 and.w r3, r3, #2 +10042900: 1a80 subs r0, r0, r2 +10042902: 1ac0 subs r0, r0, r3 +10042904: 4099 lsls r1, r3 +10042906: eb00 30d1 add.w r0, r0, r1, lsr #15 +1004290a: 1dc1 adds r1, r0, #7 +1004290c: fa29 f101 lsr.w r1, r9, r1 +10042910: f001 0101 and.w r1, r1, #1 +10042914: eb01 0040 add.w r0, r1, r0, lsl #1 +10042918: f8cb 001c str.w r0, [fp, #28] +1004291c: 2200 movs r2, #0 +1004291e: f8cb 2014 str.w r2, [fp, #20] +10042922: f8cb 2010 str.w r2, [fp, #16] +10042926: eb06 0180 add.w r1, r6, r0, lsl #2 +1004292a: 6872 ldr r2, [r6, #4] +1004292c: fa22 f300 lsr.w r3, r2, r0 +10042930: f501 7198 add.w r1, r1, #304 ; 0x130 +10042934: 07db lsls r3, r3, #31 +10042936: d407 bmi.n 10042948 +10042938: 2301 movs r3, #1 +1004293a: fa03 f000 lsl.w r0, r3, r0 +1004293e: 4310 orrs r0, r2 +10042940: 6070 str r0, [r6, #4] +10042942: f8c1 b000 str.w fp, [r1] +10042946: e01d b.n 10042984 +10042948: 281f cmp r0, #31 +1004294a: 6809 ldr r1, [r1, #0] +1004294c: bf0e itee eq +1004294e: 2000 moveq r0, #0 +10042950: 0840 lsrne r0, r0, #1 +10042952: f1c0 0019 rsbne r0, r0, #25 +10042956: fa09 f000 lsl.w r0, r9, r0 +1004295a: e000 b.n 1004295e +1004295c: 4611 mov r1, r2 +1004295e: 684a ldr r2, [r1, #4] +10042960: 08d2 lsrs r2, r2, #3 +10042962: 00d2 lsls r2, r2, #3 +10042964: 454a cmp r2, r9 +10042966: d014 beq.n 10042992 +10042968: 0fc2 lsrs r2, r0, #31 +1004296a: eb01 0282 add.w r2, r1, r2, lsl #2 +1004296e: f102 0310 add.w r3, r2, #16 +10042972: 0040 lsls r0, r0, #1 +10042974: 681a ldr r2, [r3, #0] +10042976: 2a00 cmp r2, #0 +10042978: d1f0 bne.n 1004295c +1004297a: 6930 ldr r0, [r6, #16] +1004297c: 4283 cmp r3, r0 +1004297e: d31a bcc.n 100429b6 +10042980: f8c3 b000 str.w fp, [r3] +10042984: f8cb 1018 str.w r1, [fp, #24] +10042988: f8cb b00c str.w fp, [fp, #12] +1004298c: f8cb b008 str.w fp, [fp, #8] +10042990: e013 b.n 100429ba +10042992: 6932 ldr r2, [r6, #16] +10042994: 6888 ldr r0, [r1, #8] +10042996: 4291 cmp r1, r2 +10042998: bf28 it cs +1004299a: 4290 cmpcs r0, r2 +1004299c: d30b bcc.n 100429b6 +1004299e: f8c0 b00c str.w fp, [r0, #12] +100429a2: f8c1 b008 str.w fp, [r1, #8] +100429a6: f8cb 0008 str.w r0, [fp, #8] +100429aa: f8cb 100c str.w r1, [fp, #12] +100429ae: 2000 movs r0, #0 +100429b0: f8cb 0018 str.w r0, [fp, #24] +100429b4: e001 b.n 100429ba +100429b6: f001 f88d bl 10043ad4 +100429ba: f108 0008 add.w r0, r8, #8 +100429be: f000 bdfa b.w 100435b6 <.text_20> + +100429c2 : +100429c2: e92d 4dfa stmdb sp!, {r1, r3, r4, r5, r6, r7, r8, sl, fp, lr} +100429c6: 4605 mov r5, r0 +100429c8: f8df 0384 ldr.w r0, [pc, #900] ; 10042d50 <.text_12> +100429cc: 6800 ldr r0, [r0, #0] +100429ce: b084 sub sp, #16 +100429d0: b908 cbnz r0, 100429d6 +100429d2: f7ff fe0c bl 100425ee +100429d6: f8df 0378 ldr.w r0, [pc, #888] ; 10042d50 <.text_12> +100429da: 9904 ldr r1, [sp, #16] +100429dc: 6880 ldr r0, [r0, #8] +100429de: 1841 adds r1, r0, r1 +100429e0: 312f adds r1, #47 ; 0x2f +100429e2: 1e40 subs r0, r0, #1 +100429e4: ea21 0000 bic.w r0, r1, r0 +100429e8: 9904 ldr r1, [sp, #16] +100429ea: 4281 cmp r1, r0 +100429ec: f080 81ab bcs.w 10042d46 +100429f0: f505 76d8 add.w r6, r5, #432 ; 0x1b0 +100429f4: 68b1 ldr r1, [r6, #8] +100429f6: b141 cbz r1, 10042a0a +100429f8: f8d5 21b0 ldr.w r2, [r5, #432] ; 0x1b0 +100429fc: 1880 adds r0, r0, r2 +100429fe: 4282 cmp r2, r0 +10042a00: f080 81a1 bcs.w 10042d46 +10042a04: 4281 cmp r1, r0 +10042a06: f0c0 819e bcc.w 10042d46 +10042a0a: f001 f867 bl 10043adc <__data_GetMemChunk> +10042a0e: 2800 cmp r0, #0 +10042a10: bf1e ittt ne +10042a12: 4604 movne r4, r0 +10042a14: f8d0 8000 ldrne.w r8, [r0] +10042a18: f114 0f01 cmnne.w r4, #1 +10042a1c: f000 8193 beq.w 10042d46 +10042a20: f8d5 01b0 ldr.w r0, [r5, #432] ; 0x1b0 +10042a24: 4440 add r0, r8 +10042a26: f8c5 01b0 str.w r0, [r5, #432] ; 0x1b0 +10042a2a: 6871 ldr r1, [r6, #4] +10042a2c: 4281 cmp r1, r0 +10042a2e: bf38 it cc +10042a30: 4601 movcc r1, r0 +10042a32: 6071 str r1, [r6, #4] +10042a34: 69a8 ldr r0, [r5, #24] +10042a36: bb80 cbnz r0, 10042a9a +10042a38: 6928 ldr r0, [r5, #16] +10042a3a: b108 cbz r0, 10042a40 +10042a3c: 4284 cmp r4, r0 +10042a3e: d200 bcs.n 10042a42 +10042a40: 612c str r4, [r5, #16] +10042a42: 6134 str r4, [r6, #16] +10042a44: f8c6 8014 str.w r8, [r6, #20] +10042a48: 2000 movs r0, #0 +10042a4a: 61f0 str r0, [r6, #28] +10042a4c: f105 0128 add.w r1, r5, #40 ; 0x28 +10042a50: 48bf ldr r0, [pc, #764] ; (10042d50 <.text_12>) +10042a52: 6800 ldr r0, [r0, #0] +10042a54: 6268 str r0, [r5, #36] ; 0x24 +10042a56: f04f 30ff mov.w r0, #4294967295 +10042a5a: 6228 str r0, [r5, #32] +10042a5c: 2000 movs r0, #0 +10042a5e: 60c9 str r1, [r1, #12] +10042a60: 6089 str r1, [r1, #8] +10042a62: f101 0208 add.w r2, r1, #8 +10042a66: 1c80 adds r0, r0, #2 +10042a68: 60d2 str r2, [r2, #12] +10042a6a: 3110 adds r1, #16 +10042a6c: 6092 str r2, [r2, #8] +10042a6e: 2820 cmp r0, #32 +10042a70: d3f5 bcc.n 10042a5e +10042a72: 48b8 ldr r0, [pc, #736] ; (10042d54 <.text_13>) +10042a74: 4285 cmp r5, r0 +10042a76: d103 bne.n 10042a80 +10042a78: f1a8 0228 sub.w r2, r8, #40 ; 0x28 +10042a7c: 4621 mov r1, r4 +10042a7e: e029 b.n 10042ad4 +10042a80: f855 0c04 ldr.w r0, [r5, #-4] +10042a84: 08c0 lsrs r0, r0, #3 +10042a86: eb05 00c0 add.w r0, r5, r0, lsl #3 +10042a8a: f1a0 0108 sub.w r1, r0, #8 +10042a8e: eb08 0004 add.w r0, r8, r4 +10042a92: 1a40 subs r0, r0, r1 +10042a94: f1a0 0228 sub.w r2, r0, #40 ; 0x28 +10042a98: e01c b.n 10042ad4 +10042a9a: f505 71e0 add.w r1, r5, #448 ; 0x1c0 +10042a9e: 4608 mov r0, r1 +10042aa0: e000 b.n 10042aa4 +10042aa2: 6880 ldr r0, [r0, #8] +10042aa4: b1d0 cbz r0, 10042adc +10042aa6: 6802 ldr r2, [r0, #0] +10042aa8: 6843 ldr r3, [r0, #4] +10042aaa: 189a adds r2, r3, r2 +10042aac: 4294 cmp r4, r2 +10042aae: d1f8 bne.n 10042aa2 +10042ab0: 7b02 ldrb r2, [r0, #12] +10042ab2: 0712 lsls r2, r2, #28 +10042ab4: d412 bmi.n 10042adc +10042ab6: 69aa ldr r2, [r5, #24] +10042ab8: 6803 ldr r3, [r0, #0] +10042aba: 429a cmp r2, r3 +10042abc: d30e bcc.n 10042adc +10042abe: 6847 ldr r7, [r0, #4] +10042ac0: 443b add r3, r7 +10042ac2: 429a cmp r2, r3 +10042ac4: d20a bcs.n 10042adc +10042ac6: eb08 0107 add.w r1, r8, r7 +10042aca: 6041 str r1, [r0, #4] +10042acc: 68e8 ldr r0, [r5, #12] +10042ace: 69a9 ldr r1, [r5, #24] +10042ad0: eb08 0200 add.w r2, r8, r0 +10042ad4: 4628 mov r0, r5 +10042ad6: f7ff fda3 bl 10042620 +10042ada: e11e b.n 10042d1a +10042adc: 6928 ldr r0, [r5, #16] +10042ade: 4284 cmp r4, r0 +10042ae0: bf38 it cc +10042ae2: 612c strcc r4, [r5, #16] +10042ae4: 4608 mov r0, r1 +10042ae6: eb08 0104 add.w r1, r8, r4 +10042aea: e000 b.n 10042aee +10042aec: 6880 ldr r0, [r0, #8] +10042aee: b180 cbz r0, 10042b12 +10042af0: 6802 ldr r2, [r0, #0] +10042af2: 428a cmp r2, r1 +10042af4: d1fa bne.n 10042aec +10042af6: 7b01 ldrb r1, [r0, #12] +10042af8: 0709 lsls r1, r1, #28 +10042afa: d40a bmi.n 10042b12 +10042afc: 6004 str r4, [r0, #0] +10042afe: 6841 ldr r1, [r0, #4] +10042b00: 4441 add r1, r8 +10042b02: 6041 str r1, [r0, #4] +10042b04: 4621 mov r1, r4 +10042b06: 9b04 ldr r3, [sp, #16] +10042b08: 4628 mov r0, r5 +10042b0a: b006 add sp, #24 +10042b0c: e8bd 4df0 ldmia.w sp!, {r4, r5, r6, r7, r8, sl, fp, lr} +10042b10: e5a0 b.n 10042654 +10042b12: 69af ldr r7, [r5, #24] +10042b14: 4639 mov r1, r7 +10042b16: 4628 mov r0, r5 +10042b18: f7ff fd5c bl 100425d4 +10042b1c: 6801 ldr r1, [r0, #0] +10042b1e: 6840 ldr r0, [r0, #4] +10042b20: 1840 adds r0, r0, r1 +10042b22: 9002 str r0, [sp, #8] +10042b24: 382f subs r0, #47 ; 0x2f +10042b26: f100 0108 add.w r1, r0, #8 +10042b2a: f011 0107 ands.w r1, r1, #7 +10042b2e: d005 beq.n 10042b3c +10042b30: f100 0108 add.w r1, r0, #8 +10042b34: f1c1 0108 rsb r1, r1, #8 +10042b38: f001 0107 and.w r1, r1, #7 +10042b3c: 1808 adds r0, r1, r0 +10042b3e: f107 0110 add.w r1, r7, #16 +10042b42: 4288 cmp r0, r1 +10042b44: bf34 ite cc +10042b46: 9700 strcc r7, [sp, #0] +10042b48: 9000 strcs r0, [sp, #0] +10042b4a: 9800 ldr r0, [sp, #0] +10042b4c: 3008 adds r0, #8 +10042b4e: 9001 str r0, [sp, #4] +10042b50: f104 0108 add.w r1, r4, #8 +10042b54: 9800 ldr r0, [sp, #0] +10042b56: f100 0a18 add.w sl, r0, #24 +10042b5a: f04f 0b00 mov.w fp, #0 +10042b5e: f1a8 0028 sub.w r0, r8, #40 ; 0x28 +10042b62: f011 0107 ands.w r1, r1, #7 +10042b66: d005 beq.n 10042b74 +10042b68: f104 0108 add.w r1, r4, #8 +10042b6c: f1c1 0108 rsb r1, r1, #8 +10042b70: f001 0107 and.w r1, r1, #7 +10042b74: 190a adds r2, r1, r4 +10042b76: 1a40 subs r0, r0, r1 +10042b78: 61aa str r2, [r5, #24] +10042b7a: 60e8 str r0, [r5, #12] +10042b7c: f040 0101 orr.w r1, r0, #1 +10042b80: 6051 str r1, [r2, #4] +10042b82: 1880 adds r0, r0, r2 +10042b84: 2128 movs r1, #40 ; 0x28 +10042b86: 6041 str r1, [r0, #4] +10042b88: 4871 ldr r0, [pc, #452] ; (10042d50 <.text_12>) +10042b8a: 6900 ldr r0, [r0, #16] +10042b8c: 61e8 str r0, [r5, #28] +10042b8e: 9801 ldr r0, [sp, #4] +10042b90: f010 0007 ands.w r0, r0, #7 +10042b94: bf18 it ne +10042b96: f000 ff9d blne 10043ad4 +10042b9a: 9900 ldr r1, [sp, #0] +10042b9c: 201b movs r0, #27 +10042b9e: 6048 str r0, [r1, #4] +10042ba0: f505 71e0 add.w r1, r5, #448 ; 0x1c0 +10042ba4: e8b1 500c ldmia.w r1!, {r2, r3, ip, lr} +10042ba8: 9801 ldr r0, [sp, #4] +10042baa: e8a0 500c stmia.w r0!, {r2, r3, ip, lr} +10042bae: 6134 str r4, [r6, #16] +10042bb0: f8c6 8014 str.w r8, [r6, #20] +10042bb4: f8c6 b01c str.w fp, [r6, #28] +10042bb8: 9801 ldr r0, [sp, #4] +10042bba: 61b0 str r0, [r6, #24] +10042bbc: 9802 ldr r0, [sp, #8] +10042bbe: e000 b.n 10042bc2 +10042bc0: 468a mov sl, r1 +10042bc2: 2207 movs r2, #7 +10042bc4: f8ca 2004 str.w r2, [sl, #4] +10042bc8: f10a 0104 add.w r1, sl, #4 +10042bcc: 1d0a adds r2, r1, #4 +10042bce: f10b 0b01 add.w fp, fp, #1 +10042bd2: 4282 cmp r2, r0 +10042bd4: d3f4 bcc.n 10042bc0 +10042bd6: f1bb 0f02 cmp.w fp, #2 +10042bda: bfb8 it lt +10042bdc: f000 ff7a bllt 10043ad4 +10042be0: 9800 ldr r0, [sp, #0] +10042be2: 42b8 cmp r0, r7 +10042be4: f000 8099 beq.w 10042d1a +10042be8: 1bc0 subs r0, r0, r7 +10042bea: 19c1 adds r1, r0, r7 +10042bec: 08c4 lsrs r4, r0, #3 +10042bee: 684a ldr r2, [r1, #4] +10042bf0: 0852 lsrs r2, r2, #1 +10042bf2: 0052 lsls r2, r2, #1 +10042bf4: 604a str r2, [r1, #4] +10042bf6: f040 0101 orr.w r1, r0, #1 +10042bfa: 6079 str r1, [r7, #4] +10042bfc: 51c0 str r0, [r0, r7] +10042bfe: 2c20 cmp r4, #32 +10042c00: d220 bcs.n 10042c44 +10042c02: eb05 01c4 add.w r1, r5, r4, lsl #3 +10042c06: f101 0628 add.w r6, r1, #40 ; 0x28 +10042c0a: 46b0 mov r8, r6 +10042c0c: 2810 cmp r0, #16 +10042c0e: bf38 it cc +10042c10: f000 ff60 blcc 10043ad4 +10042c14: 6828 ldr r0, [r5, #0] +10042c16: fa20 f104 lsr.w r1, r0, r4 +10042c1a: 07c9 lsls r1, r1, #31 +10042c1c: d404 bmi.n 10042c28 +10042c1e: 2101 movs r1, #1 +10042c20: 40a1 lsls r1, r4 +10042c22: 4308 orrs r0, r1 +10042c24: 6028 str r0, [r5, #0] +10042c26: e006 b.n 10042c36 +10042c28: 68b0 ldr r0, [r6, #8] +10042c2a: 6929 ldr r1, [r5, #16] +10042c2c: 4288 cmp r0, r1 +10042c2e: bf2c ite cs +10042c30: 4680 movcs r8, r0 +10042c32: f000 ff4f blcc 10043ad4 +10042c36: 60b7 str r7, [r6, #8] +10042c38: f8c8 700c str.w r7, [r8, #12] +10042c3c: f8c7 8008 str.w r8, [r7, #8] +10042c40: 60fe str r6, [r7, #12] +10042c42: e06a b.n 10042d1a +10042c44: 0a01 lsrs r1, r0, #8 +10042c46: bf08 it eq +10042c48: 2200 moveq r2, #0 +10042c4a: d023 beq.n 10042c94 +10042c4c: f5b1 3f80 cmp.w r1, #65536 ; 0x10000 +10042c50: bf28 it cs +10042c52: 221f movcs r2, #31 +10042c54: d21e bcs.n 10042c94 +10042c56: f5a1 7280 sub.w r2, r1, #256 ; 0x100 +10042c5a: 0c12 lsrs r2, r2, #16 +10042c5c: f002 0208 and.w r2, r2, #8 +10042c60: 4091 lsls r1, r2 +10042c62: f5a1 5380 sub.w r3, r1, #4096 ; 0x1000 +10042c66: 0c1b lsrs r3, r3, #16 +10042c68: f003 0304 and.w r3, r3, #4 +10042c6c: 4099 lsls r1, r3 +10042c6e: f5a1 4480 sub.w r4, r1, #16384 ; 0x4000 +10042c72: 0c24 lsrs r4, r4, #16 +10042c74: f1c2 020e rsb r2, r2, #14 +10042c78: f004 0402 and.w r4, r4, #2 +10042c7c: 1ad2 subs r2, r2, r3 +10042c7e: 1b12 subs r2, r2, r4 +10042c80: 40a1 lsls r1, r4 +10042c82: eb02 31d1 add.w r1, r2, r1, lsr #15 +10042c86: 1dca adds r2, r1, #7 +10042c88: fa20 f202 lsr.w r2, r0, r2 +10042c8c: f002 0201 and.w r2, r2, #1 +10042c90: eb02 0241 add.w r2, r2, r1, lsl #1 +10042c94: 61fa str r2, [r7, #28] +10042c96: 2300 movs r3, #0 +10042c98: 617b str r3, [r7, #20] +10042c9a: 613b str r3, [r7, #16] +10042c9c: eb05 0182 add.w r1, r5, r2, lsl #2 +10042ca0: 686b ldr r3, [r5, #4] +10042ca2: fa23 f402 lsr.w r4, r3, r2 +10042ca6: f501 7198 add.w r1, r1, #304 ; 0x130 +10042caa: 07e4 lsls r4, r4, #31 +10042cac: d405 bmi.n 10042cba +10042cae: 2001 movs r0, #1 +10042cb0: 4090 lsls r0, r2 +10042cb2: 4318 orrs r0, r3 +10042cb4: 6068 str r0, [r5, #4] +10042cb6: 600f str r7, [r1, #0] +10042cb8: e01c b.n 10042cf4 +10042cba: 2a1f cmp r2, #31 +10042cbc: 6809 ldr r1, [r1, #0] +10042cbe: bf0e itee eq +10042cc0: 2200 moveq r2, #0 +10042cc2: 0852 lsrne r2, r2, #1 +10042cc4: f1c2 0219 rsbne r2, r2, #25 +10042cc8: fa00 f202 lsl.w r2, r0, r2 +10042ccc: e000 b.n 10042cd0 +10042cce: 4619 mov r1, r3 +10042cd0: 684b ldr r3, [r1, #4] +10042cd2: 08db lsrs r3, r3, #3 +10042cd4: 00db lsls r3, r3, #3 +10042cd6: 4283 cmp r3, r0 +10042cd8: d010 beq.n 10042cfc +10042cda: 0fd3 lsrs r3, r2, #31 +10042cdc: eb01 0383 add.w r3, r1, r3, lsl #2 +10042ce0: f103 0410 add.w r4, r3, #16 +10042ce4: 0052 lsls r2, r2, #1 +10042ce6: 6823 ldr r3, [r4, #0] +10042ce8: 2b00 cmp r3, #0 +10042cea: d1f0 bne.n 10042cce +10042cec: 6928 ldr r0, [r5, #16] +10042cee: 4284 cmp r4, r0 +10042cf0: d311 bcc.n 10042d16 +10042cf2: 6027 str r7, [r4, #0] +10042cf4: 61b9 str r1, [r7, #24] +10042cf6: 60ff str r7, [r7, #12] +10042cf8: 60bf str r7, [r7, #8] +10042cfa: e00e b.n 10042d1a +10042cfc: 692a ldr r2, [r5, #16] +10042cfe: 6888 ldr r0, [r1, #8] +10042d00: 4291 cmp r1, r2 +10042d02: bf28 it cs +10042d04: 4290 cmpcs r0, r2 +10042d06: d306 bcc.n 10042d16 +10042d08: 60c7 str r7, [r0, #12] +10042d0a: 608f str r7, [r1, #8] +10042d0c: 60b8 str r0, [r7, #8] +10042d0e: 60f9 str r1, [r7, #12] +10042d10: 2000 movs r0, #0 +10042d12: 61b8 str r0, [r7, #24] +10042d14: e001 b.n 10042d1a +10042d16: f000 fedd bl 10043ad4 +10042d1a: 68e8 ldr r0, [r5, #12] +10042d1c: 9904 ldr r1, [sp, #16] +10042d1e: 4281 cmp r1, r0 +10042d20: d211 bcs.n 10042d46 +10042d22: 1a40 subs r0, r0, r1 +10042d24: 60e8 str r0, [r5, #12] +10042d26: 69a9 ldr r1, [r5, #24] +10042d28: 9a04 ldr r2, [sp, #16] +10042d2a: 1852 adds r2, r2, r1 +10042d2c: 61aa str r2, [r5, #24] +10042d2e: f040 0001 orr.w r0, r0, #1 +10042d32: 6050 str r0, [r2, #4] +10042d34: 9804 ldr r0, [sp, #16] +10042d36: f040 0003 orr.w r0, r0, #3 +10042d3a: 6048 str r0, [r1, #4] +10042d3c: b006 add sp, #24 +10042d3e: f101 0008 add.w r0, r1, #8 +10042d42: e8bd 8df0 ldmia.w sp!, {r4, r5, r6, r7, r8, sl, fp, pc} +10042d46: 2000 movs r0, #0 +10042d48: b006 add sp, #24 +10042d4a: e8bd 8df0 ldmia.w sp!, {r4, r5, r6, r7, r8, sl, fp, pc} + ... + +10042d50 <.text_12>: +10042d50: 10048918 .word 0x10048918 + +10042d54 <.text_13>: +10042d54: 10048930 .word 0x10048930 + +10042d58 <.text_14>: +10042d58: 3c885968 .word 0x3c885968 + +10042d5c : +10042d5c: e92d 4df0 stmdb sp!, {r4, r5, r6, r7, r8, sl, fp, lr} +10042d60: 4604 mov r4, r0 +10042d62: 4688 mov r8, r1 +10042d64: 2600 movs r6, #0 +10042d66: f1c8 0b00 rsb fp, r8, #0 +10042d6a: ea5f 2018 movs.w r0, r8, lsr #8 +10042d6e: bf08 it eq +10042d70: 2100 moveq r1, #0 +10042d72: d023 beq.n 10042dbc +10042d74: f5b0 3f80 cmp.w r0, #65536 ; 0x10000 +10042d78: bf28 it cs +10042d7a: 211f movcs r1, #31 +10042d7c: d21e bcs.n 10042dbc +10042d7e: f5a0 7180 sub.w r1, r0, #256 ; 0x100 +10042d82: 0c09 lsrs r1, r1, #16 +10042d84: f001 0108 and.w r1, r1, #8 +10042d88: 4088 lsls r0, r1 +10042d8a: f5a0 5280 sub.w r2, r0, #4096 ; 0x1000 +10042d8e: 0c12 lsrs r2, r2, #16 +10042d90: f002 0204 and.w r2, r2, #4 +10042d94: 4090 lsls r0, r2 +10042d96: f5a0 4380 sub.w r3, r0, #16384 ; 0x4000 +10042d9a: 0c1b lsrs r3, r3, #16 +10042d9c: f1c1 010e rsb r1, r1, #14 +10042da0: f003 0302 and.w r3, r3, #2 +10042da4: 1a89 subs r1, r1, r2 +10042da6: 1ac9 subs r1, r1, r3 +10042da8: 4098 lsls r0, r3 +10042daa: eb01 30d0 add.w r0, r1, r0, lsr #15 +10042dae: 1dc1 adds r1, r0, #7 +10042db0: fa28 f101 lsr.w r1, r8, r1 +10042db4: f001 0101 and.w r1, r1, #1 +10042db8: eb01 0140 add.w r1, r1, r0, lsl #1 +10042dbc: eb04 0081 add.w r0, r4, r1, lsl #2 +10042dc0: f8d0 0130 ldr.w r0, [r0, #304] ; 0x130 +10042dc4: b330 cbz r0, 10042e14 +10042dc6: 291f cmp r1, #31 +10042dc8: bf0e itee eq +10042dca: 2200 moveq r2, #0 +10042dcc: 084a lsrne r2, r1, #1 +10042dce: f1c2 0219 rsbne r2, r2, #25 +10042dd2: fa08 f202 lsl.w r2, r8, r2 +10042dd6: 2300 movs r3, #0 +10042dd8: e000 b.n 10042ddc +10042dda: 0052 lsls r2, r2, #1 +10042ddc: 6845 ldr r5, [r0, #4] +10042dde: 08ed lsrs r5, r5, #3 +10042de0: 00ed lsls r5, r5, #3 +10042de2: eba5 0508 sub.w r5, r5, r8 +10042de6: 455d cmp r5, fp +10042de8: d203 bcs.n 10042df2 +10042dea: 4606 mov r6, r0 +10042dec: ea5f 0b05 movs.w fp, r5 +10042df0: d00c beq.n 10042e0c +10042df2: 6945 ldr r5, [r0, #20] +10042df4: ea4f 7ed2 mov.w lr, r2, lsr #31 +10042df8: eb00 008e add.w r0, r0, lr, lsl #2 +10042dfc: 2d00 cmp r5, #0 +10042dfe: 6900 ldr r0, [r0, #16] +10042e00: bf1c itt ne +10042e02: 4285 cmpne r5, r0 +10042e04: 462b movne r3, r5 +10042e06: 2800 cmp r0, #0 +10042e08: d1e7 bne.n 10042dda +10042e0a: 4618 mov r0, r3 +10042e0c: 2800 cmp r0, #0 +10042e0e: d13a bne.n 10042e86 +10042e10: 2e00 cmp r6, #0 +10042e12: d13a bne.n 10042e8a +10042e14: 2001 movs r0, #1 +10042e16: 4088 lsls r0, r1 +10042e18: 0040 lsls r0, r0, #1 +10042e1a: 4241 negs r1, r0 +10042e1c: 4308 orrs r0, r1 +10042e1e: 6861 ldr r1, [r4, #4] +10042e20: 4008 ands r0, r1 +10042e22: f000 8165 beq.w 100430f0 +10042e26: 4241 negs r1, r0 +10042e28: 4008 ands r0, r1 +10042e2a: 1e41 subs r1, r0, #1 +10042e2c: 0b08 lsrs r0, r1, #12 +10042e2e: f000 0010 and.w r0, r0, #16 +10042e32: fa21 f200 lsr.w r2, r1, r0 +10042e36: 0951 lsrs r1, r2, #5 +10042e38: f001 0108 and.w r1, r1, #8 +10042e3c: 40ca lsrs r2, r1 +10042e3e: 0893 lsrs r3, r2, #2 +10042e40: f003 0304 and.w r3, r3, #4 +10042e44: 40da lsrs r2, r3 +10042e46: 0855 lsrs r5, r2, #1 +10042e48: f005 0502 and.w r5, r5, #2 +10042e4c: 1808 adds r0, r1, r0 +10042e4e: 40ea lsrs r2, r5 +10042e50: 1818 adds r0, r3, r0 +10042e52: f3c2 0e40 ubfx lr, r2, #1, #1 +10042e56: 4428 add r0, r5 +10042e58: 4470 add r0, lr +10042e5a: fa22 f10e lsr.w r1, r2, lr +10042e5e: 1808 adds r0, r1, r0 +10042e60: eb04 0080 add.w r0, r4, r0, lsl #2 +10042e64: f8d0 0130 ldr.w r0, [r0, #304] ; 0x130 +10042e68: e00d b.n 10042e86 +10042e6a: 4608 mov r0, r1 +10042e6c: 6841 ldr r1, [r0, #4] +10042e6e: 08c9 lsrs r1, r1, #3 +10042e70: 00c9 lsls r1, r1, #3 +10042e72: eba1 0108 sub.w r1, r1, r8 +10042e76: 4559 cmp r1, fp +10042e78: bf3c itt cc +10042e7a: 468b movcc fp, r1 +10042e7c: 4606 movcc r6, r0 +10042e7e: 6901 ldr r1, [r0, #16] +10042e80: 2900 cmp r1, #0 +10042e82: d1f2 bne.n 10042e6a +10042e84: 6940 ldr r0, [r0, #20] +10042e86: 2800 cmp r0, #0 +10042e88: d1f0 bne.n 10042e6c +10042e8a: 2e00 cmp r6, #0 +10042e8c: f000 8130 beq.w 100430f0 +10042e90: 68a0 ldr r0, [r4, #8] +10042e92: eba0 0008 sub.w r0, r0, r8 +10042e96: 4583 cmp fp, r0 +10042e98: f080 812a bcs.w 100430f0 +10042e9c: 6920 ldr r0, [r4, #16] +10042e9e: 4286 cmp r6, r0 +10042ea0: f0c0 8124 bcc.w 100430ec +10042ea4: 6870 ldr r0, [r6, #4] +10042ea6: 08c0 lsrs r0, r0, #3 +10042ea8: 00c0 lsls r0, r0, #3 +10042eaa: eb08 010b add.w r1, r8, fp +10042eae: eb08 0506 add.w r5, r8, r6 +10042eb2: 4288 cmp r0, r1 +10042eb4: bf18 it ne +10042eb6: f000 fe0d blne 10043ad4 +10042eba: 42ae cmp r6, r5 +10042ebc: f080 8116 bcs.w 100430ec +10042ec0: 68f7 ldr r7, [r6, #12] +10042ec2: f8d6 a018 ldr.w sl, [r6, #24] +10042ec6: 42b7 cmp r7, r6 +10042ec8: d00c beq.n 10042ee4 +10042eca: 68b0 ldr r0, [r6, #8] +10042ecc: 6921 ldr r1, [r4, #16] +10042ece: 4288 cmp r0, r1 +10042ed0: d323 bcc.n 10042f1a +10042ed2: 68c1 ldr r1, [r0, #12] +10042ed4: 42b1 cmp r1, r6 +10042ed6: bf04 itt eq +10042ed8: 68b9 ldreq r1, [r7, #8] +10042eda: 42b1 cmpeq r1, r6 +10042edc: d11d bne.n 10042f1a +10042ede: 60c7 str r7, [r0, #12] +10042ee0: 60b8 str r0, [r7, #8] +10042ee2: e01c b.n 10042f1e +10042ee4: f106 0014 add.w r0, r6, #20 +10042ee8: 6807 ldr r7, [r0, #0] +10042eea: b937 cbnz r7, 10042efa +10042eec: f106 0010 add.w r0, r6, #16 +10042ef0: 6807 ldr r7, [r0, #0] +10042ef2: b1a7 cbz r7, 10042f1e +10042ef4: e001 b.n 10042efa +10042ef6: 4608 mov r0, r1 +10042ef8: 6807 ldr r7, [r0, #0] +10042efa: f107 0114 add.w r1, r7, #20 +10042efe: 680a ldr r2, [r1, #0] +10042f00: 2a00 cmp r2, #0 +10042f02: bf02 ittt eq +10042f04: f107 0110 addeq.w r1, r7, #16 +10042f08: 680a ldreq r2, [r1, #0] +10042f0a: 2a00 cmpeq r2, #0 +10042f0c: d1f3 bne.n 10042ef6 +10042f0e: 6921 ldr r1, [r4, #16] +10042f10: 4288 cmp r0, r1 +10042f12: d302 bcc.n 10042f1a +10042f14: 2100 movs r1, #0 +10042f16: 6001 str r1, [r0, #0] +10042f18: e001 b.n 10042f1e +10042f1a: f000 fddb bl 10043ad4 +10042f1e: f1ba 0f00 cmp.w sl, #0 +10042f22: d038 beq.n 10042f96 +10042f24: 69f0 ldr r0, [r6, #28] +10042f26: eb04 0080 add.w r0, r4, r0, lsl #2 +10042f2a: f500 7098 add.w r0, r0, #304 ; 0x130 +10042f2e: 6801 ldr r1, [r0, #0] +10042f30: 428e cmp r6, r1 +10042f32: d109 bne.n 10042f48 +10042f34: 6007 str r7, [r0, #0] +10042f36: 0038 movs r0, r7 +10042f38: d114 bne.n 10042f64 +10042f3a: 69f2 ldr r2, [r6, #28] +10042f3c: 6860 ldr r0, [r4, #4] +10042f3e: 2101 movs r1, #1 +10042f40: 4091 lsls r1, r2 +10042f42: 4388 bics r0, r1 +10042f44: 6060 str r0, [r4, #4] +10042f46: e026 b.n 10042f96 +10042f48: 6920 ldr r0, [r4, #16] +10042f4a: 4582 cmp sl, r0 +10042f4c: d308 bcc.n 10042f60 +10042f4e: f8da 0010 ldr.w r0, [sl, #16] +10042f52: 42b0 cmp r0, r6 +10042f54: bf14 ite ne +10042f56: f8ca 7014 strne.w r7, [sl, #20] +10042f5a: f8ca 7010 streq.w r7, [sl, #16] +10042f5e: e001 b.n 10042f64 +10042f60: f000 fdb8 bl 10043ad4 +10042f64: b1bf cbz r7, 10042f96 +10042f66: 6920 ldr r0, [r4, #16] +10042f68: 4287 cmp r7, r0 +10042f6a: d312 bcc.n 10042f92 +10042f6c: f8c7 a018 str.w sl, [r7, #24] +10042f70: 6930 ldr r0, [r6, #16] +10042f72: b130 cbz r0, 10042f82 +10042f74: 6921 ldr r1, [r4, #16] +10042f76: 4288 cmp r0, r1 +10042f78: bf26 itte cs +10042f7a: 6138 strcs r0, [r7, #16] +10042f7c: 6187 strcs r7, [r0, #24] +10042f7e: f000 fda9 blcc 10043ad4 +10042f82: 6970 ldr r0, [r6, #20] +10042f84: b138 cbz r0, 10042f96 +10042f86: 6921 ldr r1, [r4, #16] +10042f88: 4288 cmp r0, r1 +10042f8a: d302 bcc.n 10042f92 +10042f8c: 6178 str r0, [r7, #20] +10042f8e: 6187 str r7, [r0, #24] +10042f90: e001 b.n 10042f96 +10042f92: f000 fd9f bl 10043ad4 +10042f96: f1bb 0f10 cmp.w fp, #16 +10042f9a: d20c bcs.n 10042fb6 +10042f9c: eb08 000b add.w r0, r8, fp +10042fa0: f040 0003 orr.w r0, r0, #3 +10042fa4: 6070 str r0, [r6, #4] +10042fa6: eb08 000b add.w r0, r8, fp +10042faa: 1980 adds r0, r0, r6 +10042fac: 6841 ldr r1, [r0, #4] +10042fae: f041 0101 orr.w r1, r1, #1 +10042fb2: 6041 str r1, [r0, #4] +10042fb4: e096 b.n 100430e4 +10042fb6: f048 0003 orr.w r0, r8, #3 +10042fba: 6070 str r0, [r6, #4] +10042fbc: f04b 0001 orr.w r0, fp, #1 +10042fc0: 6068 str r0, [r5, #4] +10042fc2: f84b b005 str.w fp, [fp, r5] +10042fc6: ea4f 00db mov.w r0, fp, lsr #3 +10042fca: 2820 cmp r0, #32 +10042fcc: d21d bcs.n 1004300a +10042fce: eb04 01c0 add.w r1, r4, r0, lsl #3 +10042fd2: f101 0728 add.w r7, r1, #40 ; 0x28 +10042fd6: 6821 ldr r1, [r4, #0] +10042fd8: fa21 f200 lsr.w r2, r1, r0 +10042fdc: 46bb mov fp, r7 +10042fde: 07d2 lsls r2, r2, #31 +10042fe0: d405 bmi.n 10042fee +10042fe2: 2201 movs r2, #1 +10042fe4: fa02 f000 lsl.w r0, r2, r0 +10042fe8: 4308 orrs r0, r1 +10042fea: 6020 str r0, [r4, #0] +10042fec: e006 b.n 10042ffc +10042fee: 68b8 ldr r0, [r7, #8] +10042ff0: 6921 ldr r1, [r4, #16] +10042ff2: 4288 cmp r0, r1 +10042ff4: bf2c ite cs +10042ff6: 4683 movcs fp, r0 +10042ff8: f000 fd6c blcc 10043ad4 +10042ffc: 60bd str r5, [r7, #8] +10042ffe: f8cb 500c str.w r5, [fp, #12] +10043002: f8c5 b008 str.w fp, [r5, #8] +10043006: 60ef str r7, [r5, #12] +10043008: e06c b.n 100430e4 +1004300a: ea5f 211b movs.w r1, fp, lsr #8 +1004300e: bf08 it eq +10043010: 2000 moveq r0, #0 +10043012: d023 beq.n 1004305c +10043014: f5b1 3f80 cmp.w r1, #65536 ; 0x10000 +10043018: bf28 it cs +1004301a: 201f movcs r0, #31 +1004301c: d21e bcs.n 1004305c +1004301e: f5a1 7080 sub.w r0, r1, #256 ; 0x100 +10043022: 0c00 lsrs r0, r0, #16 +10043024: f000 0008 and.w r0, r0, #8 +10043028: 4081 lsls r1, r0 +1004302a: f5a1 5280 sub.w r2, r1, #4096 ; 0x1000 +1004302e: 0c12 lsrs r2, r2, #16 +10043030: f002 0204 and.w r2, r2, #4 +10043034: 4091 lsls r1, r2 +10043036: f5a1 4380 sub.w r3, r1, #16384 ; 0x4000 +1004303a: 0c1b lsrs r3, r3, #16 +1004303c: f1c0 000e rsb r0, r0, #14 +10043040: f003 0302 and.w r3, r3, #2 +10043044: 1a80 subs r0, r0, r2 +10043046: 1ac0 subs r0, r0, r3 +10043048: 4099 lsls r1, r3 +1004304a: eb00 30d1 add.w r0, r0, r1, lsr #15 +1004304e: 1dc1 adds r1, r0, #7 +10043050: fa2b f101 lsr.w r1, fp, r1 +10043054: f001 0101 and.w r1, r1, #1 +10043058: eb01 0040 add.w r0, r1, r0, lsl #1 +1004305c: 61e8 str r0, [r5, #28] +1004305e: 2200 movs r2, #0 +10043060: 616a str r2, [r5, #20] +10043062: 612a str r2, [r5, #16] +10043064: eb04 0180 add.w r1, r4, r0, lsl #2 +10043068: 6862 ldr r2, [r4, #4] +1004306a: fa22 f300 lsr.w r3, r2, r0 +1004306e: f501 7198 add.w r1, r1, #304 ; 0x130 +10043072: 07db lsls r3, r3, #31 +10043074: d406 bmi.n 10043084 +10043076: 2301 movs r3, #1 +10043078: fa03 f000 lsl.w r0, r3, r0 +1004307c: 4310 orrs r0, r2 +1004307e: 6060 str r0, [r4, #4] +10043080: 600d str r5, [r1, #0] +10043082: e01c b.n 100430be +10043084: 281f cmp r0, #31 +10043086: 6809 ldr r1, [r1, #0] +10043088: bf0e itee eq +1004308a: 2000 moveq r0, #0 +1004308c: 0840 lsrne r0, r0, #1 +1004308e: f1c0 0019 rsbne r0, r0, #25 +10043092: fa0b f000 lsl.w r0, fp, r0 +10043096: e000 b.n 1004309a +10043098: 4611 mov r1, r2 +1004309a: 684a ldr r2, [r1, #4] +1004309c: 08d2 lsrs r2, r2, #3 +1004309e: 00d2 lsls r2, r2, #3 +100430a0: 455a cmp r2, fp +100430a2: d010 beq.n 100430c6 +100430a4: 0fc2 lsrs r2, r0, #31 +100430a6: eb01 0282 add.w r2, r1, r2, lsl #2 +100430aa: f102 0310 add.w r3, r2, #16 +100430ae: 0040 lsls r0, r0, #1 +100430b0: 681a ldr r2, [r3, #0] +100430b2: 2a00 cmp r2, #0 +100430b4: d1f0 bne.n 10043098 +100430b6: 6920 ldr r0, [r4, #16] +100430b8: 4283 cmp r3, r0 +100430ba: d311 bcc.n 100430e0 +100430bc: 601d str r5, [r3, #0] +100430be: 61a9 str r1, [r5, #24] +100430c0: 60ed str r5, [r5, #12] +100430c2: 60ad str r5, [r5, #8] +100430c4: e00e b.n 100430e4 +100430c6: 6922 ldr r2, [r4, #16] +100430c8: 6888 ldr r0, [r1, #8] +100430ca: 4291 cmp r1, r2 +100430cc: bf28 it cs +100430ce: 4290 cmpcs r0, r2 +100430d0: d306 bcc.n 100430e0 +100430d2: 60c5 str r5, [r0, #12] +100430d4: 608d str r5, [r1, #8] +100430d6: 60a8 str r0, [r5, #8] +100430d8: 60e9 str r1, [r5, #12] +100430da: 2000 movs r0, #0 +100430dc: 61a8 str r0, [r5, #24] +100430de: e001 b.n 100430e4 +100430e0: f000 fcf8 bl 10043ad4 +100430e4: f106 0008 add.w r0, r6, #8 +100430e8: e8bd 8df0 ldmia.w sp!, {r4, r5, r6, r7, r8, sl, fp, pc} +100430ec: f000 fcf2 bl 10043ad4 +100430f0: 2000 movs r0, #0 +100430f2: e8bd 8df0 ldmia.w sp!, {r4, r5, r6, r7, r8, sl, fp, pc} + +100430f6 : +100430f6: e92d 4ff8 stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} +100430fa: 4604 mov r4, r0 +100430fc: 4688 mov r8, r1 +100430fe: 6860 ldr r0, [r4, #4] +10043100: 4241 negs r1, r0 +10043102: 4008 ands r0, r1 +10043104: 1e41 subs r1, r0, #1 +10043106: 0b08 lsrs r0, r1, #12 +10043108: f000 0010 and.w r0, r0, #16 +1004310c: 40c1 lsrs r1, r0 +1004310e: 094a lsrs r2, r1, #5 +10043110: f002 0208 and.w r2, r2, #8 +10043114: 40d1 lsrs r1, r2 +10043116: 088b lsrs r3, r1, #2 +10043118: f003 0304 and.w r3, r3, #4 +1004311c: 40d9 lsrs r1, r3 +1004311e: 084d lsrs r5, r1, #1 +10043120: f005 0502 and.w r5, r5, #2 +10043124: 1810 adds r0, r2, r0 +10043126: 40e9 lsrs r1, r5 +10043128: 1818 adds r0, r3, r0 +1004312a: f3c1 0640 ubfx r6, r1, #1, #1 +1004312e: 4428 add r0, r5 +10043130: 1830 adds r0, r6, r0 +10043132: 40f1 lsrs r1, r6 +10043134: 1808 adds r0, r1, r0 +10043136: eb04 0080 add.w r0, r4, r0, lsl #2 +1004313a: f8d0 0130 ldr.w r0, [r0, #304] ; 0x130 +1004313e: 6841 ldr r1, [r0, #4] +10043140: 08c9 lsrs r1, r1, #3 +10043142: 00c9 lsls r1, r1, #3 +10043144: 4606 mov r6, r0 +10043146: eba1 0a08 sub.w sl, r1, r8 +1004314a: e009 b.n 10043160 +1004314c: 4608 mov r0, r1 +1004314e: 6841 ldr r1, [r0, #4] +10043150: 08c9 lsrs r1, r1, #3 +10043152: 00c9 lsls r1, r1, #3 +10043154: eba1 0108 sub.w r1, r1, r8 +10043158: 4551 cmp r1, sl +1004315a: bf3c itt cc +1004315c: 468a movcc sl, r1 +1004315e: 4606 movcc r6, r0 +10043160: 6901 ldr r1, [r0, #16] +10043162: 2900 cmp r1, #0 +10043164: d1f2 bne.n 1004314c +10043166: 6940 ldr r0, [r0, #20] +10043168: 2800 cmp r0, #0 +1004316a: d1f0 bne.n 1004314e +1004316c: 6920 ldr r0, [r4, #16] +1004316e: 4286 cmp r6, r0 +10043170: f0c0 80c4 bcc.w 100432fc +10043174: 6870 ldr r0, [r6, #4] +10043176: 08c0 lsrs r0, r0, #3 +10043178: eb08 090a add.w r9, r8, sl +1004317c: 00c0 lsls r0, r0, #3 +1004317e: eb08 0b06 add.w fp, r8, r6 +10043182: 4548 cmp r0, r9 +10043184: bf18 it ne +10043186: f000 fca5 blne 10043ad4 +1004318a: 455e cmp r6, fp +1004318c: f080 80b6 bcs.w 100432fc +10043190: 68f7 ldr r7, [r6, #12] +10043192: 69b5 ldr r5, [r6, #24] +10043194: 42b7 cmp r7, r6 +10043196: d00c beq.n 100431b2 +10043198: 68b0 ldr r0, [r6, #8] +1004319a: 6921 ldr r1, [r4, #16] +1004319c: 4288 cmp r0, r1 +1004319e: d323 bcc.n 100431e8 +100431a0: 68c1 ldr r1, [r0, #12] +100431a2: 42b1 cmp r1, r6 +100431a4: bf04 itt eq +100431a6: 68b9 ldreq r1, [r7, #8] +100431a8: 42b1 cmpeq r1, r6 +100431aa: d11d bne.n 100431e8 +100431ac: 60c7 str r7, [r0, #12] +100431ae: 60b8 str r0, [r7, #8] +100431b0: e01c b.n 100431ec +100431b2: f106 0014 add.w r0, r6, #20 +100431b6: 6807 ldr r7, [r0, #0] +100431b8: b937 cbnz r7, 100431c8 +100431ba: f106 0010 add.w r0, r6, #16 +100431be: 6807 ldr r7, [r0, #0] +100431c0: b1a7 cbz r7, 100431ec +100431c2: e001 b.n 100431c8 +100431c4: 4608 mov r0, r1 +100431c6: 6807 ldr r7, [r0, #0] +100431c8: f107 0114 add.w r1, r7, #20 +100431cc: 680a ldr r2, [r1, #0] +100431ce: 2a00 cmp r2, #0 +100431d0: bf02 ittt eq +100431d2: f107 0110 addeq.w r1, r7, #16 +100431d6: 680a ldreq r2, [r1, #0] +100431d8: 2a00 cmpeq r2, #0 +100431da: d1f3 bne.n 100431c4 +100431dc: 6921 ldr r1, [r4, #16] +100431de: 4288 cmp r0, r1 +100431e0: d302 bcc.n 100431e8 +100431e2: 2100 movs r1, #0 +100431e4: 6001 str r1, [r0, #0] +100431e6: e001 b.n 100431ec +100431e8: f000 fc74 bl 10043ad4 +100431ec: 2d00 cmp r5, #0 +100431ee: d034 beq.n 1004325a +100431f0: 69f0 ldr r0, [r6, #28] +100431f2: eb04 0080 add.w r0, r4, r0, lsl #2 +100431f6: f500 7098 add.w r0, r0, #304 ; 0x130 +100431fa: 6801 ldr r1, [r0, #0] +100431fc: 428e cmp r6, r1 +100431fe: d109 bne.n 10043214 +10043200: 6007 str r7, [r0, #0] +10043202: 0038 movs r0, r7 +10043204: d111 bne.n 1004322a +10043206: 69f2 ldr r2, [r6, #28] +10043208: 6860 ldr r0, [r4, #4] +1004320a: 2101 movs r1, #1 +1004320c: 4091 lsls r1, r2 +1004320e: 4388 bics r0, r1 +10043210: 6060 str r0, [r4, #4] +10043212: e022 b.n 1004325a +10043214: 6920 ldr r0, [r4, #16] +10043216: 4285 cmp r5, r0 +10043218: d305 bcc.n 10043226 +1004321a: 6928 ldr r0, [r5, #16] +1004321c: 42b0 cmp r0, r6 +1004321e: bf14 ite ne +10043220: 616f strne r7, [r5, #20] +10043222: 612f streq r7, [r5, #16] +10043224: e001 b.n 1004322a +10043226: f000 fc55 bl 10043ad4 +1004322a: b1b7 cbz r7, 1004325a +1004322c: 6920 ldr r0, [r4, #16] +1004322e: 4287 cmp r7, r0 +10043230: d311 bcc.n 10043256 +10043232: 61bd str r5, [r7, #24] +10043234: 6930 ldr r0, [r6, #16] +10043236: b130 cbz r0, 10043246 +10043238: 6921 ldr r1, [r4, #16] +1004323a: 4288 cmp r0, r1 +1004323c: bf26 itte cs +1004323e: 6138 strcs r0, [r7, #16] +10043240: 6187 strcs r7, [r0, #24] +10043242: f000 fc47 blcc 10043ad4 +10043246: 6970 ldr r0, [r6, #20] +10043248: b138 cbz r0, 1004325a +1004324a: 6921 ldr r1, [r4, #16] +1004324c: 4288 cmp r0, r1 +1004324e: d302 bcc.n 10043256 +10043250: 6178 str r0, [r7, #20] +10043252: 6187 str r7, [r0, #24] +10043254: e001 b.n 1004325a +10043256: f000 fc3d bl 10043ad4 +1004325a: f1ba 0f10 cmp.w sl, #16 +1004325e: d209 bcs.n 10043274 +10043260: f049 0003 orr.w r0, r9, #3 +10043264: 6070 str r0, [r6, #4] +10043266: eb09 0006 add.w r0, r9, r6 +1004326a: 6841 ldr r1, [r0, #4] +1004326c: f041 0101 orr.w r1, r1, #1 +10043270: 6041 str r1, [r0, #4] +10043272: e03f b.n 100432f4 +10043274: f048 0003 orr.w r0, r8, #3 +10043278: 6070 str r0, [r6, #4] +1004327a: f04a 0001 orr.w r0, sl, #1 +1004327e: f8cb 0004 str.w r0, [fp, #4] +10043282: f84a a00b str.w sl, [sl, fp] +10043286: f8d4 8008 ldr.w r8, [r4, #8] +1004328a: ea4f 05d8 mov.w r5, r8, lsr #3 +1004328e: 2d20 cmp r5, #32 +10043290: bf28 it cs +10043292: f000 fc1f blcs 10043ad4 +10043296: f1b8 0f00 cmp.w r8, #0 +1004329a: d027 beq.n 100432ec +1004329c: f8d4 9014 ldr.w r9, [r4, #20] +100432a0: 9500 str r5, [sp, #0] +100432a2: eb04 00c5 add.w r0, r4, r5, lsl #3 +100432a6: f100 0528 add.w r5, r0, #40 ; 0x28 +100432aa: 462f mov r7, r5 +100432ac: f1b8 0f10 cmp.w r8, #16 +100432b0: bf38 it cc +100432b2: f000 fc0f blcc 10043ad4 +100432b6: 6820 ldr r0, [r4, #0] +100432b8: 9900 ldr r1, [sp, #0] +100432ba: fa20 f101 lsr.w r1, r0, r1 +100432be: 07c9 lsls r1, r1, #31 +100432c0: d405 bmi.n 100432ce +100432c2: 9a00 ldr r2, [sp, #0] +100432c4: 2101 movs r1, #1 +100432c6: 4091 lsls r1, r2 +100432c8: 4308 orrs r0, r1 +100432ca: 6020 str r0, [r4, #0] +100432cc: e006 b.n 100432dc +100432ce: 68a8 ldr r0, [r5, #8] +100432d0: 6921 ldr r1, [r4, #16] +100432d2: 4288 cmp r0, r1 +100432d4: bf2c ite cs +100432d6: 4607 movcs r7, r0 +100432d8: f000 fbfc blcc 10043ad4 +100432dc: f8c5 9008 str.w r9, [r5, #8] +100432e0: f8c7 900c str.w r9, [r7, #12] +100432e4: f8c9 7008 str.w r7, [r9, #8] +100432e8: f8c9 500c str.w r5, [r9, #12] +100432ec: f8c4 a008 str.w sl, [r4, #8] +100432f0: f8c4 b014 str.w fp, [r4, #20] +100432f4: f106 0008 add.w r0, r6, #8 +100432f8: e8bd 8ff2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, sl, fp, pc} +100432fc: f000 fbea bl 10043ad4 +10043300: 2000 movs r0, #0 +10043302: e8bd 8ff2 ldmia.w sp!, {r1, r4, r5, r6, r7, r8, r9, sl, fp, pc} + +10043306 <__iar_dlmalloc>: +10043306: e92d 4ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} +1004330a: b083 sub sp, #12 +1004330c: 4605 mov r5, r0 +1004330e: 46c0 nop ; (mov r8, r8) +10043310: 46c0 nop ; (mov r8, r8) +10043312: f8df 47b8 ldr.w r4, [pc, #1976] ; 10043acc <.text_24> +10043316: 2df5 cmp r5, #245 ; 0xf5 +10043318: f080 8102 bcs.w 10043520 <__iar_dlmalloc+0x21a> +1004331c: 2d0b cmp r5, #11 +1004331e: bf31 iteee cc +10043320: 2710 movcc r7, #16 +10043322: f105 000b addcs.w r0, r5, #11 +10043326: 08c0 lsrcs r0, r0, #3 +10043328: 00c7 lslcs r7, r0, #3 +1004332a: 6820 ldr r0, [r4, #0] +1004332c: 08fe lsrs r6, r7, #3 +1004332e: 40f0 lsrs r0, r6 +10043330: f010 0f03 tst.w r0, #3 +10043334: d042 beq.n 100433bc <__iar_dlmalloc+0xb6> +10043336: 43c0 mvns r0, r0 +10043338: f000 0001 and.w r0, r0, #1 +1004333c: 1986 adds r6, r0, r6 +1004333e: eb04 00c6 add.w r0, r4, r6, lsl #3 +10043342: f100 0828 add.w r8, r0, #40 ; 0x28 +10043346: 00f7 lsls r7, r6, #3 +10043348: f8d8 5008 ldr.w r5, [r8, #8] +1004334c: 6868 ldr r0, [r5, #4] +1004334e: 08c0 lsrs r0, r0, #3 +10043350: 00c0 lsls r0, r0, #3 +10043352: 42b8 cmp r0, r7 +10043354: bf18 it ne +10043356: f000 fbbd blne 10043ad4 +1004335a: f8d5 9008 ldr.w r9, [r5, #8] +1004335e: 4545 cmp r5, r8 +10043360: bf08 it eq +10043362: f000 fbb7 bleq 10043ad4 +10043366: 454d cmp r5, r9 +10043368: bf08 it eq +1004336a: f000 fbb3 bleq 10043ad4 +1004336e: 6868 ldr r0, [r5, #4] +10043370: 08c0 lsrs r0, r0, #3 +10043372: 00c0 lsls r0, r0, #3 +10043374: 42b8 cmp r0, r7 +10043376: bf18 it ne +10043378: f000 fbac blne 10043ad4 +1004337c: 45c8 cmp r8, r9 +1004337e: d105 bne.n 1004338c <__iar_dlmalloc+0x86> +10043380: 6820 ldr r0, [r4, #0] +10043382: 2101 movs r1, #1 +10043384: 40b1 lsls r1, r6 +10043386: 4388 bics r0, r1 +10043388: 6020 str r0, [r4, #0] +1004338a: e00d b.n 100433a8 <__iar_dlmalloc+0xa2> +1004338c: 6920 ldr r0, [r4, #16] +1004338e: 4581 cmp r9, r0 +10043390: d308 bcc.n 100433a4 <__iar_dlmalloc+0x9e> +10043392: f8d9 000c ldr.w r0, [r9, #12] +10043396: 42a8 cmp r0, r5 +10043398: d104 bne.n 100433a4 <__iar_dlmalloc+0x9e> +1004339a: f8c8 9008 str.w r9, [r8, #8] +1004339e: f8c9 800c str.w r8, [r9, #12] +100433a2: e001 b.n 100433a8 <__iar_dlmalloc+0xa2> +100433a4: f000 fb96 bl 10043ad4 +100433a8: f047 0003 orr.w r0, r7, #3 +100433ac: 6068 str r0, [r5, #4] +100433ae: 1978 adds r0, r7, r5 +100433b0: 3508 adds r5, #8 +100433b2: 6841 ldr r1, [r0, #4] +100433b4: f041 0101 orr.w r1, r1, #1 +100433b8: 6041 str r1, [r0, #4] +100433ba: e0f9 b.n 100435b0 <.text_19> +100433bc: 68a1 ldr r1, [r4, #8] +100433be: 42b9 cmp r1, r7 +100433c0: f080 80c0 bcs.w 10043544 <__iar_dlmalloc+0x23e> +100433c4: 2800 cmp r0, #0 +100433c6: f000 80a2 beq.w 1004350e <__iar_dlmalloc+0x208> +100433ca: 2501 movs r5, #1 +100433cc: fa05 f106 lsl.w r1, r5, r6 +100433d0: 0049 lsls r1, r1, #1 +100433d2: 424a negs r2, r1 +100433d4: 40b0 lsls r0, r6 +100433d6: 4311 orrs r1, r2 +100433d8: 4008 ands r0, r1 +100433da: 4241 negs r1, r0 +100433dc: 4008 ands r0, r1 +100433de: 1e41 subs r1, r0, #1 +100433e0: 0b08 lsrs r0, r1, #12 +100433e2: f000 0010 and.w r0, r0, #16 +100433e6: 40c1 lsrs r1, r0 +100433e8: 094a lsrs r2, r1, #5 +100433ea: f002 0208 and.w r2, r2, #8 +100433ee: 40d1 lsrs r1, r2 +100433f0: 088b lsrs r3, r1, #2 +100433f2: f003 0304 and.w r3, r3, #4 +100433f6: 40d9 lsrs r1, r3 +100433f8: 084e lsrs r6, r1, #1 +100433fa: f006 0602 and.w r6, r6, #2 +100433fe: 1810 adds r0, r2, r0 +10043400: 40f1 lsrs r1, r6 +10043402: 1818 adds r0, r3, r0 +10043404: f3c1 0840 ubfx r8, r1, #1, #1 +10043408: 1830 adds r0, r6, r0 +1004340a: 4440 add r0, r8 +1004340c: fa21 f108 lsr.w r1, r1, r8 +10043410: eb01 0800 add.w r8, r1, r0 +10043414: eb04 00c8 add.w r0, r4, r8, lsl #3 +10043418: f100 0928 add.w r9, r0, #40 ; 0x28 +1004341c: ea4f 0ac8 mov.w sl, r8, lsl #3 +10043420: f8d9 6008 ldr.w r6, [r9, #8] +10043424: 6870 ldr r0, [r6, #4] +10043426: 08c0 lsrs r0, r0, #3 +10043428: 00c0 lsls r0, r0, #3 +1004342a: 4550 cmp r0, sl +1004342c: bf18 it ne +1004342e: f000 fb51 blne 10043ad4 +10043432: f8d6 b008 ldr.w fp, [r6, #8] +10043436: 454e cmp r6, r9 +10043438: bf08 it eq +1004343a: f000 fb4b bleq 10043ad4 +1004343e: 455e cmp r6, fp +10043440: bf08 it eq +10043442: f000 fb47 bleq 10043ad4 +10043446: 6870 ldr r0, [r6, #4] +10043448: 08c0 lsrs r0, r0, #3 +1004344a: 00c0 lsls r0, r0, #3 +1004344c: 4550 cmp r0, sl +1004344e: bf18 it ne +10043450: f000 fb40 blne 10043ad4 +10043454: 45d9 cmp r9, fp +10043456: d105 bne.n 10043464 <__iar_dlmalloc+0x15e> +10043458: 6820 ldr r0, [r4, #0] +1004345a: fa05 f108 lsl.w r1, r5, r8 +1004345e: 4388 bics r0, r1 +10043460: 6020 str r0, [r4, #0] +10043462: e00d b.n 10043480 <__iar_dlmalloc+0x17a> +10043464: 6920 ldr r0, [r4, #16] +10043466: 4583 cmp fp, r0 +10043468: d308 bcc.n 1004347c <__iar_dlmalloc+0x176> +1004346a: f8db 000c ldr.w r0, [fp, #12] +1004346e: 42b0 cmp r0, r6 +10043470: d104 bne.n 1004347c <__iar_dlmalloc+0x176> +10043472: f8c9 b008 str.w fp, [r9, #8] +10043476: f8cb 900c str.w r9, [fp, #12] +1004347a: e001 b.n 10043480 <__iar_dlmalloc+0x17a> +1004347c: f000 fb2a bl 10043ad4 +10043480: f047 0003 orr.w r0, r7, #3 +10043484: 6070 str r0, [r6, #4] +10043486: ebaa 0807 sub.w r8, sl, r7 +1004348a: 19b8 adds r0, r7, r6 +1004348c: 9001 str r0, [sp, #4] +1004348e: f048 0001 orr.w r0, r8, #1 +10043492: 9901 ldr r1, [sp, #4] +10043494: 6048 str r0, [r1, #4] +10043496: 9801 ldr r0, [sp, #4] +10043498: f848 8000 str.w r8, [r8, r0] +1004349c: 68a7 ldr r7, [r4, #8] +1004349e: ea4f 0ad7 mov.w sl, r7, lsr #3 +100434a2: f1ba 0f20 cmp.w sl, #32 +100434a6: bf28 it cs +100434a8: f000 fb14 blcs 10043ad4 +100434ac: b347 cbz r7, 10043500 <__iar_dlmalloc+0x1fa> +100434ae: f8cd a000 str.w sl, [sp] +100434b2: eb04 00ca add.w r0, r4, sl, lsl #3 +100434b6: f8d4 9014 ldr.w r9, [r4, #20] +100434ba: f100 0a28 add.w sl, r0, #40 ; 0x28 +100434be: 46d3 mov fp, sl +100434c0: 2f10 cmp r7, #16 +100434c2: bf38 it cc +100434c4: f000 fb06 blcc 10043ad4 +100434c8: 6820 ldr r0, [r4, #0] +100434ca: 9900 ldr r1, [sp, #0] +100434cc: fa20 f101 lsr.w r1, r0, r1 +100434d0: 07c9 lsls r1, r1, #31 +100434d2: d405 bmi.n 100434e0 <__iar_dlmalloc+0x1da> +100434d4: 9900 ldr r1, [sp, #0] +100434d6: fa05 f101 lsl.w r1, r5, r1 +100434da: 4308 orrs r0, r1 +100434dc: 6020 str r0, [r4, #0] +100434de: e007 b.n 100434f0 <__iar_dlmalloc+0x1ea> +100434e0: f8da 0008 ldr.w r0, [sl, #8] +100434e4: 6921 ldr r1, [r4, #16] +100434e6: 4288 cmp r0, r1 +100434e8: bf2c ite cs +100434ea: 4683 movcs fp, r0 +100434ec: f000 faf2 blcc 10043ad4 +100434f0: f8ca 9008 str.w r9, [sl, #8] +100434f4: f8cb 900c str.w r9, [fp, #12] +100434f8: f8c9 b008 str.w fp, [r9, #8] +100434fc: f8c9 a00c str.w sl, [r9, #12] +10043500: f8c4 8008 str.w r8, [r4, #8] +10043504: f106 0508 add.w r5, r6, #8 +10043508: 9801 ldr r0, [sp, #4] +1004350a: 6160 str r0, [r4, #20] +1004350c: e050 b.n 100435b0 <.text_19> +1004350e: 6860 ldr r0, [r4, #4] +10043510: b3c0 cbz r0, 10043584 <__iar_dlmalloc+0x27e> +10043512: 4639 mov r1, r7 +10043514: 4620 mov r0, r4 +10043516: f7ff fdee bl 100430f6 +1004351a: 0005 movs r5, r0 +1004351c: d012 beq.n 10043544 <__iar_dlmalloc+0x23e> +1004351e: e047 b.n 100435b0 <.text_19> +10043520: f115 0f40 cmn.w r5, #64 ; 0x40 +10043524: bf28 it cs +10043526: f04f 37ff movcs.w r7, #4294967295 +1004352a: d20b bcs.n 10043544 <__iar_dlmalloc+0x23e> +1004352c: f105 000b add.w r0, r5, #11 +10043530: 08c0 lsrs r0, r0, #3 +10043532: 00c7 lsls r7, r0, #3 +10043534: 6860 ldr r0, [r4, #4] +10043536: b128 cbz r0, 10043544 <__iar_dlmalloc+0x23e> +10043538: 4639 mov r1, r7 +1004353a: 4620 mov r0, r4 +1004353c: f7ff fc0e bl 10042d5c +10043540: 0005 movs r5, r0 +10043542: d135 bne.n 100435b0 <.text_19> +10043544: 68a0 ldr r0, [r4, #8] +10043546: 42b8 cmp r0, r7 +10043548: d31c bcc.n 10043584 <__iar_dlmalloc+0x27e> +1004354a: 1bc1 subs r1, r0, r7 +1004354c: 6962 ldr r2, [r4, #20] +1004354e: 2910 cmp r1, #16 +10043550: d30a bcc.n 10043568 <__iar_dlmalloc+0x262> +10043552: 18b8 adds r0, r7, r2 +10043554: 6160 str r0, [r4, #20] +10043556: 60a1 str r1, [r4, #8] +10043558: f041 0301 orr.w r3, r1, #1 +1004355c: 6043 str r3, [r0, #4] +1004355e: 5009 str r1, [r1, r0] +10043560: f047 0003 orr.w r0, r7, #3 +10043564: 6050 str r0, [r2, #4] +10043566: e00a b.n 1004357e <__iar_dlmalloc+0x278> +10043568: 2100 movs r1, #0 +1004356a: 60a1 str r1, [r4, #8] +1004356c: 6161 str r1, [r4, #20] +1004356e: f040 0103 orr.w r1, r0, #3 +10043572: 6051 str r1, [r2, #4] +10043574: 1880 adds r0, r0, r2 +10043576: 6841 ldr r1, [r0, #4] +10043578: f041 0101 orr.w r1, r1, #1 +1004357c: 6041 str r1, [r0, #4] +1004357e: f102 0508 add.w r5, r2, #8 +10043582: e015 b.n 100435b0 <.text_19> +10043584: 68e0 ldr r0, [r4, #12] +10043586: 4287 cmp r7, r0 +10043588: d20d bcs.n 100435a6 <__iar_dlmalloc+0x2a0> +1004358a: 1bc0 subs r0, r0, r7 +1004358c: 69a1 ldr r1, [r4, #24] +1004358e: 60e0 str r0, [r4, #12] +10043590: 187a adds r2, r7, r1 +10043592: 61a2 str r2, [r4, #24] +10043594: f040 0001 orr.w r0, r0, #1 +10043598: 6050 str r0, [r2, #4] +1004359a: f101 0508 add.w r5, r1, #8 +1004359e: f047 0003 orr.w r0, r7, #3 +100435a2: 6048 str r0, [r1, #4] +100435a4: e004 b.n 100435b0 <.text_19> +100435a6: 4639 mov r1, r7 +100435a8: 4620 mov r0, r4 +100435aa: f7ff fa0a bl 100429c2 +100435ae: 4605 mov r5, r0 + +100435b0 <.text_19>: +100435b0: 46c0 nop ; (mov r8, r8) +100435b2: 46c0 nop ; (mov r8, r8) +100435b4: 4628 mov r0, r5 + +100435b6 <.text_20>: +100435b6: b003 add sp, #12 +100435b8: e8bd 8ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} + +100435bc <__iar_dlfree>: +100435bc: b900 cbnz r0, 100435c0 <__iar_dlfree+0x4> +100435be: 4770 bx lr +100435c0: e92d 47f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} +100435c4: f1a0 0408 sub.w r4, r0, #8 +100435c8: 46c0 nop ; (mov r8, r8) +100435ca: 46c0 nop ; (mov r8, r8) +100435cc: f8df 54fc ldr.w r5, [pc, #1276] ; 10043acc <.text_24> +100435d0: 6928 ldr r0, [r5, #16] +100435d2: 4284 cmp r4, r0 +100435d4: f0c0 8274 bcc.w 10043ac0 <__iar_dlfree+0x504> +100435d8: 6861 ldr r1, [r4, #4] +100435da: f001 0203 and.w r2, r1, #3 +100435de: 2a01 cmp r2, #1 +100435e0: f000 826e beq.w 10043ac0 <__iar_dlfree+0x504> +100435e4: 08ca lsrs r2, r1, #3 +100435e6: ea4f 08c2 mov.w r8, r2, lsl #3 +100435ea: eb08 0904 add.w r9, r8, r4 +100435ee: 07ca lsls r2, r1, #31 +100435f0: d436 bmi.n 10043660 <__iar_dlfree+0xa4> +100435f2: 6822 ldr r2, [r4, #0] +100435f4: f011 0f03 tst.w r1, #3 +100435f8: f000 8264 beq.w 10043ac4 <__iar_dlfree+0x508> +100435fc: 1aa4 subs r4, r4, r2 +100435fe: 4490 add r8, r2 +10043600: 4284 cmp r4, r0 +10043602: f0c0 825d bcc.w 10043ac0 <__iar_dlfree+0x504> +10043606: 6969 ldr r1, [r5, #20] +10043608: 428c cmp r4, r1 +1004360a: f000 80d8 beq.w 100437be <__iar_dlfree+0x202> +1004360e: 08d6 lsrs r6, r2, #3 +10043610: 2e20 cmp r6, #32 +10043612: d270 bcs.n 100436f6 <__iar_dlfree+0x13a> +10043614: f8d4 a00c ldr.w sl, [r4, #12] +10043618: 68a7 ldr r7, [r4, #8] +1004361a: 4554 cmp r4, sl +1004361c: bf08 it eq +1004361e: f000 fa59 bleq 10043ad4 +10043622: 42bc cmp r4, r7 +10043624: bf08 it eq +10043626: f000 fa55 bleq 10043ad4 +1004362a: 6860 ldr r0, [r4, #4] +1004362c: 08c0 lsrs r0, r0, #3 +1004362e: 00c0 lsls r0, r0, #3 +10043630: ebb0 0fc6 cmp.w r0, r6, lsl #3 +10043634: bf18 it ne +10043636: f000 fa4d blne 10043ad4 +1004363a: eb05 00c6 add.w r0, r5, r6, lsl #3 +1004363e: f100 0128 add.w r1, r0, #40 ; 0x28 +10043642: 428f cmp r7, r1 +10043644: d005 beq.n 10043652 <__iar_dlfree+0x96> +10043646: 6929 ldr r1, [r5, #16] +10043648: 428f cmp r7, r1 +1004364a: d351 bcc.n 100436f0 <__iar_dlfree+0x134> +1004364c: 68f9 ldr r1, [r7, #12] +1004364e: 42a1 cmp r1, r4 +10043650: d14e bne.n 100436f0 <__iar_dlfree+0x134> +10043652: 45ba cmp sl, r7 +10043654: d13d bne.n 100436d2 <__iar_dlfree+0x116> +10043656: 6828 ldr r0, [r5, #0] +10043658: 2101 movs r1, #1 +1004365a: 40b1 lsls r1, r6 +1004365c: 4388 bics r0, r1 +1004365e: 6028 str r0, [r5, #0] +10043660: 454c cmp r4, r9 +10043662: f080 822d bcs.w 10043ac0 <__iar_dlfree+0x504> +10043666: f8d9 0004 ldr.w r0, [r9, #4] +1004366a: 07c1 lsls r1, r0, #31 +1004366c: f140 8228 bpl.w 10043ac0 <__iar_dlfree+0x504> +10043670: 0781 lsls r1, r0, #30 +10043672: f100 817a bmi.w 1004396a <__iar_dlfree+0x3ae> +10043676: 69a9 ldr r1, [r5, #24] +10043678: 4589 cmp r9, r1 +1004367a: f040 80b5 bne.w 100437e8 <__iar_dlfree+0x22c> +1004367e: 68e8 ldr r0, [r5, #12] +10043680: 61ac str r4, [r5, #24] +10043682: 4440 add r0, r8 +10043684: 60e8 str r0, [r5, #12] +10043686: f040 0101 orr.w r1, r0, #1 +1004368a: 6061 str r1, [r4, #4] +1004368c: 6969 ldr r1, [r5, #20] +1004368e: 428c cmp r4, r1 +10043690: d102 bne.n 10043698 <__iar_dlfree+0xdc> +10043692: 2100 movs r1, #0 +10043694: 6169 str r1, [r5, #20] +10043696: 60a9 str r1, [r5, #8] +10043698: 69e9 ldr r1, [r5, #28] +1004369a: 4281 cmp r1, r0 +1004369c: f080 8212 bcs.w 10043ac4 <__iar_dlfree+0x508> +100436a0: f8df 042c ldr.w r0, [pc, #1068] ; 10043ad0 <.text_28> +100436a4: 6800 ldr r0, [r0, #0] +100436a6: b908 cbnz r0, 100436ac <__iar_dlfree+0xf0> +100436a8: f7fe ffa1 bl 100425ee +100436ac: 69a9 ldr r1, [r5, #24] +100436ae: 2900 cmp r1, #0 +100436b0: f000 8208 beq.w 10043ac4 <__iar_dlfree+0x508> +100436b4: 68e8 ldr r0, [r5, #12] +100436b6: 2829 cmp r0, #41 ; 0x29 +100436b8: bf24 itt cs +100436ba: 4628 movcs r0, r5 +100436bc: f7fe ff8a blcs 100425d4 +100436c0: 69e8 ldr r0, [r5, #28] +100436c2: 68e9 ldr r1, [r5, #12] +100436c4: 4288 cmp r0, r1 +100436c6: f080 81fd bcs.w 10043ac4 <__iar_dlfree+0x508> +100436ca: f04f 30ff mov.w r0, #4294967295 +100436ce: 61e8 str r0, [r5, #28] +100436d0: e1f8 b.n 10043ac4 <__iar_dlfree+0x508> +100436d2: 3028 adds r0, #40 ; 0x28 +100436d4: 4582 cmp sl, r0 +100436d6: d006 beq.n 100436e6 <__iar_dlfree+0x12a> +100436d8: 6928 ldr r0, [r5, #16] +100436da: 4582 cmp sl, r0 +100436dc: d308 bcc.n 100436f0 <__iar_dlfree+0x134> +100436de: f8da 0008 ldr.w r0, [sl, #8] +100436e2: 42a0 cmp r0, r4 +100436e4: d104 bne.n 100436f0 <__iar_dlfree+0x134> +100436e6: f8c7 a00c str.w sl, [r7, #12] +100436ea: f8ca 7008 str.w r7, [sl, #8] +100436ee: e7b7 b.n 10043660 <__iar_dlfree+0xa4> +100436f0: f000 f9f0 bl 10043ad4 +100436f4: e7b4 b.n 10043660 <__iar_dlfree+0xa4> +100436f6: 68e7 ldr r7, [r4, #12] +100436f8: 69a6 ldr r6, [r4, #24] +100436fa: 42a7 cmp r7, r4 +100436fc: d00b beq.n 10043716 <__iar_dlfree+0x15a> +100436fe: 68a1 ldr r1, [r4, #8] +10043700: 4281 cmp r1, r0 +10043702: d322 bcc.n 1004374a <__iar_dlfree+0x18e> +10043704: 68c8 ldr r0, [r1, #12] +10043706: 42a0 cmp r0, r4 +10043708: bf04 itt eq +1004370a: 68b8 ldreq r0, [r7, #8] +1004370c: 42a0 cmpeq r0, r4 +1004370e: d11c bne.n 1004374a <__iar_dlfree+0x18e> +10043710: 60cf str r7, [r1, #12] +10043712: 60b9 str r1, [r7, #8] +10043714: e01b b.n 1004374e <__iar_dlfree+0x192> +10043716: f104 0114 add.w r1, r4, #20 +1004371a: 680f ldr r7, [r1, #0] +1004371c: b937 cbnz r7, 1004372c <__iar_dlfree+0x170> +1004371e: f104 0110 add.w r1, r4, #16 +10043722: 680f ldr r7, [r1, #0] +10043724: b19f cbz r7, 1004374e <__iar_dlfree+0x192> +10043726: e001 b.n 1004372c <__iar_dlfree+0x170> +10043728: 4611 mov r1, r2 +1004372a: 680f ldr r7, [r1, #0] +1004372c: f107 0214 add.w r2, r7, #20 +10043730: 6813 ldr r3, [r2, #0] +10043732: 2b00 cmp r3, #0 +10043734: bf02 ittt eq +10043736: f107 0210 addeq.w r2, r7, #16 +1004373a: 6813 ldreq r3, [r2, #0] +1004373c: 2b00 cmpeq r3, #0 +1004373e: d1f3 bne.n 10043728 <__iar_dlfree+0x16c> +10043740: 4281 cmp r1, r0 +10043742: d302 bcc.n 1004374a <__iar_dlfree+0x18e> +10043744: 2000 movs r0, #0 +10043746: 6008 str r0, [r1, #0] +10043748: e001 b.n 1004374e <__iar_dlfree+0x192> +1004374a: f000 f9c3 bl 10043ad4 +1004374e: 2e00 cmp r6, #0 +10043750: d086 beq.n 10043660 <__iar_dlfree+0xa4> +10043752: 69e0 ldr r0, [r4, #28] +10043754: eb05 0080 add.w r0, r5, r0, lsl #2 +10043758: f500 7098 add.w r0, r0, #304 ; 0x130 +1004375c: 6801 ldr r1, [r0, #0] +1004375e: 428c cmp r4, r1 +10043760: d109 bne.n 10043776 <__iar_dlfree+0x1ba> +10043762: 6007 str r7, [r0, #0] +10043764: 0038 movs r0, r7 +10043766: d111 bne.n 1004378c <__iar_dlfree+0x1d0> +10043768: 69e2 ldr r2, [r4, #28] +1004376a: 6868 ldr r0, [r5, #4] +1004376c: 2101 movs r1, #1 +1004376e: 4091 lsls r1, r2 +10043770: 4388 bics r0, r1 +10043772: 6068 str r0, [r5, #4] +10043774: e774 b.n 10043660 <__iar_dlfree+0xa4> +10043776: 6928 ldr r0, [r5, #16] +10043778: 4286 cmp r6, r0 +1004377a: d305 bcc.n 10043788 <__iar_dlfree+0x1cc> +1004377c: 6930 ldr r0, [r6, #16] +1004377e: 42a0 cmp r0, r4 +10043780: bf14 ite ne +10043782: 6177 strne r7, [r6, #20] +10043784: 6137 streq r7, [r6, #16] +10043786: e001 b.n 1004378c <__iar_dlfree+0x1d0> +10043788: f000 f9a4 bl 10043ad4 +1004378c: 2f00 cmp r7, #0 +1004378e: f43f af67 beq.w 10043660 <__iar_dlfree+0xa4> +10043792: 6928 ldr r0, [r5, #16] +10043794: 4287 cmp r7, r0 +10043796: d3ab bcc.n 100436f0 <__iar_dlfree+0x134> +10043798: 61be str r6, [r7, #24] +1004379a: 6921 ldr r1, [r4, #16] +1004379c: b129 cbz r1, 100437aa <__iar_dlfree+0x1ee> +1004379e: 4281 cmp r1, r0 +100437a0: bf26 itte cs +100437a2: 6139 strcs r1, [r7, #16] +100437a4: 618f strcs r7, [r1, #24] +100437a6: f000 f995 blcc 10043ad4 +100437aa: 6960 ldr r0, [r4, #20] +100437ac: 2800 cmp r0, #0 +100437ae: f43f af57 beq.w 10043660 <__iar_dlfree+0xa4> +100437b2: 6929 ldr r1, [r5, #16] +100437b4: 4288 cmp r0, r1 +100437b6: d39b bcc.n 100436f0 <__iar_dlfree+0x134> +100437b8: 6178 str r0, [r7, #20] +100437ba: 6187 str r7, [r0, #24] +100437bc: e750 b.n 10043660 <__iar_dlfree+0xa4> +100437be: f899 0004 ldrb.w r0, [r9, #4] +100437c2: f000 0003 and.w r0, r0, #3 +100437c6: 2803 cmp r0, #3 +100437c8: f47f af4a bne.w 10043660 <__iar_dlfree+0xa4> +100437cc: f8c5 8008 str.w r8, [r5, #8] +100437d0: f8d9 0004 ldr.w r0, [r9, #4] +100437d4: 0840 lsrs r0, r0, #1 +100437d6: 0040 lsls r0, r0, #1 +100437d8: f8c9 0004 str.w r0, [r9, #4] +100437dc: f048 0001 orr.w r0, r8, #1 +100437e0: 6060 str r0, [r4, #4] +100437e2: f848 8004 str.w r8, [r8, r4] +100437e6: e16d b.n 10043ac4 <__iar_dlfree+0x508> +100437e8: 6969 ldr r1, [r5, #20] +100437ea: 4589 cmp r9, r1 +100437ec: d108 bne.n 10043800 <__iar_dlfree+0x244> +100437ee: 68a8 ldr r0, [r5, #8] +100437f0: 616c str r4, [r5, #20] +100437f2: 4440 add r0, r8 +100437f4: 60a8 str r0, [r5, #8] +100437f6: f040 0101 orr.w r1, r0, #1 +100437fa: 6061 str r1, [r4, #4] +100437fc: 5100 str r0, [r0, r4] +100437fe: e161 b.n 10043ac4 <__iar_dlfree+0x508> +10043800: 08c0 lsrs r0, r0, #3 +10043802: 00c0 lsls r0, r0, #3 +10043804: ea4f 0ad0 mov.w sl, r0, lsr #3 +10043808: 4480 add r8, r0 +1004380a: f1ba 0f20 cmp.w sl, #32 +1004380e: d236 bcs.n 1004387e <__iar_dlfree+0x2c2> +10043810: f8d9 700c ldr.w r7, [r9, #12] +10043814: f8d9 6008 ldr.w r6, [r9, #8] +10043818: 45b9 cmp r9, r7 +1004381a: bf08 it eq +1004381c: f000 f95a bleq 10043ad4 +10043820: 45b1 cmp r9, r6 +10043822: bf08 it eq +10043824: f000 f956 bleq 10043ad4 +10043828: f8d9 0004 ldr.w r0, [r9, #4] +1004382c: 08c0 lsrs r0, r0, #3 +1004382e: 00c0 lsls r0, r0, #3 +10043830: ebb0 0fca cmp.w r0, sl, lsl #3 +10043834: bf18 it ne +10043836: f000 f94d blne 10043ad4 +1004383a: eb05 00ca add.w r0, r5, sl, lsl #3 +1004383e: f100 0128 add.w r1, r0, #40 ; 0x28 +10043842: 428e cmp r6, r1 +10043844: d006 beq.n 10043854 <__iar_dlfree+0x298> +10043846: 6929 ldr r1, [r5, #16] +10043848: 428e cmp r6, r1 +1004384a: f0c0 8081 bcc.w 10043950 <__iar_dlfree+0x394> +1004384e: 68f1 ldr r1, [r6, #12] +10043850: 4549 cmp r1, r9 +10043852: d17d bne.n 10043950 <__iar_dlfree+0x394> +10043854: 42b7 cmp r7, r6 +10043856: d106 bne.n 10043866 <__iar_dlfree+0x2aa> +10043858: 6828 ldr r0, [r5, #0] +1004385a: 2101 movs r1, #1 +1004385c: fa01 f10a lsl.w r1, r1, sl +10043860: 4388 bics r0, r1 +10043862: 6028 str r0, [r5, #0] +10043864: e076 b.n 10043954 <__iar_dlfree+0x398> +10043866: 3028 adds r0, #40 ; 0x28 +10043868: 4287 cmp r7, r0 +1004386a: d005 beq.n 10043878 <__iar_dlfree+0x2bc> +1004386c: 6928 ldr r0, [r5, #16] +1004386e: 4287 cmp r7, r0 +10043870: d36e bcc.n 10043950 <__iar_dlfree+0x394> +10043872: 68b8 ldr r0, [r7, #8] +10043874: 4548 cmp r0, r9 +10043876: d16b bne.n 10043950 <__iar_dlfree+0x394> +10043878: 60f7 str r7, [r6, #12] +1004387a: 60be str r6, [r7, #8] +1004387c: e06a b.n 10043954 <__iar_dlfree+0x398> +1004387e: f8d9 700c ldr.w r7, [r9, #12] +10043882: f8d9 6018 ldr.w r6, [r9, #24] +10043886: 454f cmp r7, r9 +10043888: d00d beq.n 100438a6 <__iar_dlfree+0x2ea> +1004388a: f8d9 0008 ldr.w r0, [r9, #8] +1004388e: 6929 ldr r1, [r5, #16] +10043890: 4288 cmp r0, r1 +10043892: d323 bcc.n 100438dc <__iar_dlfree+0x320> +10043894: 68c1 ldr r1, [r0, #12] +10043896: 4549 cmp r1, r9 +10043898: bf04 itt eq +1004389a: 68b9 ldreq r1, [r7, #8] +1004389c: 4549 cmpeq r1, r9 +1004389e: d11d bne.n 100438dc <__iar_dlfree+0x320> +100438a0: 60c7 str r7, [r0, #12] +100438a2: 60b8 str r0, [r7, #8] +100438a4: e01c b.n 100438e0 <__iar_dlfree+0x324> +100438a6: f109 0014 add.w r0, r9, #20 +100438aa: 6807 ldr r7, [r0, #0] +100438ac: b937 cbnz r7, 100438bc <__iar_dlfree+0x300> +100438ae: f109 0010 add.w r0, r9, #16 +100438b2: 6807 ldr r7, [r0, #0] +100438b4: b1a7 cbz r7, 100438e0 <__iar_dlfree+0x324> +100438b6: e001 b.n 100438bc <__iar_dlfree+0x300> +100438b8: 4608 mov r0, r1 +100438ba: 6807 ldr r7, [r0, #0] +100438bc: f107 0114 add.w r1, r7, #20 +100438c0: 680a ldr r2, [r1, #0] +100438c2: 2a00 cmp r2, #0 +100438c4: bf02 ittt eq +100438c6: f107 0110 addeq.w r1, r7, #16 +100438ca: 680a ldreq r2, [r1, #0] +100438cc: 2a00 cmpeq r2, #0 +100438ce: d1f3 bne.n 100438b8 <__iar_dlfree+0x2fc> +100438d0: 6929 ldr r1, [r5, #16] +100438d2: 4288 cmp r0, r1 +100438d4: d302 bcc.n 100438dc <__iar_dlfree+0x320> +100438d6: 2100 movs r1, #0 +100438d8: 6001 str r1, [r0, #0] +100438da: e001 b.n 100438e0 <__iar_dlfree+0x324> +100438dc: f000 f8fa bl 10043ad4 +100438e0: 2e00 cmp r6, #0 +100438e2: d037 beq.n 10043954 <__iar_dlfree+0x398> +100438e4: f8d9 001c ldr.w r0, [r9, #28] +100438e8: eb05 0080 add.w r0, r5, r0, lsl #2 +100438ec: f500 7098 add.w r0, r0, #304 ; 0x130 +100438f0: 6801 ldr r1, [r0, #0] +100438f2: 4589 cmp r9, r1 +100438f4: d10a bne.n 1004390c <__iar_dlfree+0x350> +100438f6: 6007 str r7, [r0, #0] +100438f8: 0038 movs r0, r7 +100438fa: d112 bne.n 10043922 <__iar_dlfree+0x366> +100438fc: f8d9 201c ldr.w r2, [r9, #28] +10043900: 6868 ldr r0, [r5, #4] +10043902: 2101 movs r1, #1 +10043904: 4091 lsls r1, r2 +10043906: 4388 bics r0, r1 +10043908: 6068 str r0, [r5, #4] +1004390a: e023 b.n 10043954 <__iar_dlfree+0x398> +1004390c: 6928 ldr r0, [r5, #16] +1004390e: 4286 cmp r6, r0 +10043910: d305 bcc.n 1004391e <__iar_dlfree+0x362> +10043912: 6930 ldr r0, [r6, #16] +10043914: 4548 cmp r0, r9 +10043916: bf14 ite ne +10043918: 6177 strne r7, [r6, #20] +1004391a: 6137 streq r7, [r6, #16] +1004391c: e001 b.n 10043922 <__iar_dlfree+0x366> +1004391e: f000 f8d9 bl 10043ad4 +10043922: b1bf cbz r7, 10043954 <__iar_dlfree+0x398> +10043924: 6928 ldr r0, [r5, #16] +10043926: 4287 cmp r7, r0 +10043928: d312 bcc.n 10043950 <__iar_dlfree+0x394> +1004392a: 61be str r6, [r7, #24] +1004392c: f8d9 1010 ldr.w r1, [r9, #16] +10043930: b129 cbz r1, 1004393e <__iar_dlfree+0x382> +10043932: 4281 cmp r1, r0 +10043934: bf26 itte cs +10043936: 6139 strcs r1, [r7, #16] +10043938: 618f strcs r7, [r1, #24] +1004393a: f000 f8cb blcc 10043ad4 +1004393e: f8d9 0014 ldr.w r0, [r9, #20] +10043942: b138 cbz r0, 10043954 <__iar_dlfree+0x398> +10043944: 6929 ldr r1, [r5, #16] +10043946: 4288 cmp r0, r1 +10043948: d302 bcc.n 10043950 <__iar_dlfree+0x394> +1004394a: 6178 str r0, [r7, #20] +1004394c: 6187 str r7, [r0, #24] +1004394e: e001 b.n 10043954 <__iar_dlfree+0x398> +10043950: f000 f8c0 bl 10043ad4 +10043954: f048 0001 orr.w r0, r8, #1 +10043958: 6060 str r0, [r4, #4] +1004395a: f848 8004 str.w r8, [r8, r4] +1004395e: 6968 ldr r0, [r5, #20] +10043960: 4284 cmp r4, r0 +10043962: d10b bne.n 1004397c <__iar_dlfree+0x3c0> +10043964: f8c5 8008 str.w r8, [r5, #8] +10043968: e0ac b.n 10043ac4 <__iar_dlfree+0x508> +1004396a: 0840 lsrs r0, r0, #1 +1004396c: 0040 lsls r0, r0, #1 +1004396e: f8c9 0004 str.w r0, [r9, #4] +10043972: f048 0001 orr.w r0, r8, #1 +10043976: 6060 str r0, [r4, #4] +10043978: f848 8004 str.w r8, [r8, r4] +1004397c: ea4f 07d8 mov.w r7, r8, lsr #3 +10043980: 2f20 cmp r7, #32 +10043982: d222 bcs.n 100439ca <__iar_dlfree+0x40e> +10043984: eb05 00c7 add.w r0, r5, r7, lsl #3 +10043988: f100 0928 add.w r9, r0, #40 ; 0x28 +1004398c: 464e mov r6, r9 +1004398e: f1b8 0f10 cmp.w r8, #16 +10043992: bf38 it cc +10043994: f000 f89e blcc 10043ad4 +10043998: 6828 ldr r0, [r5, #0] +1004399a: fa20 f107 lsr.w r1, r0, r7 +1004399e: 07c9 lsls r1, r1, #31 +100439a0: d404 bmi.n 100439ac <__iar_dlfree+0x3f0> +100439a2: 2101 movs r1, #1 +100439a4: 40b9 lsls r1, r7 +100439a6: 4308 orrs r0, r1 +100439a8: 6028 str r0, [r5, #0] +100439aa: e007 b.n 100439bc <__iar_dlfree+0x400> +100439ac: f8d9 0008 ldr.w r0, [r9, #8] +100439b0: 6929 ldr r1, [r5, #16] +100439b2: 4288 cmp r0, r1 +100439b4: bf2c ite cs +100439b6: 4606 movcs r6, r0 +100439b8: f000 f88c blcc 10043ad4 +100439bc: f8c9 4008 str.w r4, [r9, #8] +100439c0: 60f4 str r4, [r6, #12] +100439c2: 60a6 str r6, [r4, #8] +100439c4: f8c4 900c str.w r9, [r4, #12] +100439c8: e07c b.n 10043ac4 <__iar_dlfree+0x508> +100439ca: ea5f 2018 movs.w r0, r8, lsr #8 +100439ce: bf08 it eq +100439d0: 2100 moveq r1, #0 +100439d2: d023 beq.n 10043a1c <__iar_dlfree+0x460> +100439d4: f5b0 3f80 cmp.w r0, #65536 ; 0x10000 +100439d8: bf28 it cs +100439da: 211f movcs r1, #31 +100439dc: d21e bcs.n 10043a1c <__iar_dlfree+0x460> +100439de: f5a0 7180 sub.w r1, r0, #256 ; 0x100 +100439e2: 0c09 lsrs r1, r1, #16 +100439e4: f001 0108 and.w r1, r1, #8 +100439e8: 4088 lsls r0, r1 +100439ea: f5a0 5280 sub.w r2, r0, #4096 ; 0x1000 +100439ee: 0c12 lsrs r2, r2, #16 +100439f0: f002 0204 and.w r2, r2, #4 +100439f4: 4090 lsls r0, r2 +100439f6: f5a0 4380 sub.w r3, r0, #16384 ; 0x4000 +100439fa: 0c1b lsrs r3, r3, #16 +100439fc: f1c1 010e rsb r1, r1, #14 +10043a00: f003 0302 and.w r3, r3, #2 +10043a04: 1a89 subs r1, r1, r2 +10043a06: 1ac9 subs r1, r1, r3 +10043a08: 4098 lsls r0, r3 +10043a0a: eb01 30d0 add.w r0, r1, r0, lsr #15 +10043a0e: 1dc1 adds r1, r0, #7 +10043a10: fa28 f101 lsr.w r1, r8, r1 +10043a14: f001 0101 and.w r1, r1, #1 +10043a18: eb01 0140 add.w r1, r1, r0, lsl #1 +10043a1c: 61e1 str r1, [r4, #28] +10043a1e: 2200 movs r2, #0 +10043a20: 6162 str r2, [r4, #20] +10043a22: 6122 str r2, [r4, #16] +10043a24: eb05 0081 add.w r0, r5, r1, lsl #2 +10043a28: 686a ldr r2, [r5, #4] +10043a2a: fa22 f301 lsr.w r3, r2, r1 +10043a2e: f500 7098 add.w r0, r0, #304 ; 0x130 +10043a32: 07db lsls r3, r3, #31 +10043a34: d406 bmi.n 10043a44 <__iar_dlfree+0x488> +10043a36: 2301 movs r3, #1 +10043a38: fa03 f101 lsl.w r1, r3, r1 +10043a3c: 4311 orrs r1, r2 +10043a3e: 6069 str r1, [r5, #4] +10043a40: 6004 str r4, [r0, #0] +10043a42: e01c b.n 10043a7e <__iar_dlfree+0x4c2> +10043a44: 291f cmp r1, #31 +10043a46: 6800 ldr r0, [r0, #0] +10043a48: bf0e itee eq +10043a4a: 2100 moveq r1, #0 +10043a4c: 0849 lsrne r1, r1, #1 +10043a4e: f1c1 0119 rsbne r1, r1, #25 +10043a52: fa08 f101 lsl.w r1, r8, r1 +10043a56: e000 b.n 10043a5a <__iar_dlfree+0x49e> +10043a58: 4610 mov r0, r2 +10043a5a: 6842 ldr r2, [r0, #4] +10043a5c: 08d2 lsrs r2, r2, #3 +10043a5e: 00d2 lsls r2, r2, #3 +10043a60: 4542 cmp r2, r8 +10043a62: d010 beq.n 10043a86 <__iar_dlfree+0x4ca> +10043a64: 0fca lsrs r2, r1, #31 +10043a66: eb00 0282 add.w r2, r0, r2, lsl #2 +10043a6a: f102 0310 add.w r3, r2, #16 +10043a6e: 0049 lsls r1, r1, #1 +10043a70: 681a ldr r2, [r3, #0] +10043a72: 2a00 cmp r2, #0 +10043a74: d1f0 bne.n 10043a58 <__iar_dlfree+0x49c> +10043a76: 6929 ldr r1, [r5, #16] +10043a78: 428b cmp r3, r1 +10043a7a: d311 bcc.n 10043aa0 <__iar_dlfree+0x4e4> +10043a7c: 601c str r4, [r3, #0] +10043a7e: 61a0 str r0, [r4, #24] +10043a80: 60e4 str r4, [r4, #12] +10043a82: 60a4 str r4, [r4, #8] +10043a84: e00e b.n 10043aa4 <__iar_dlfree+0x4e8> +10043a86: 692a ldr r2, [r5, #16] +10043a88: 6881 ldr r1, [r0, #8] +10043a8a: 4290 cmp r0, r2 +10043a8c: bf28 it cs +10043a8e: 4291 cmpcs r1, r2 +10043a90: d306 bcc.n 10043aa0 <__iar_dlfree+0x4e4> +10043a92: 60cc str r4, [r1, #12] +10043a94: 6084 str r4, [r0, #8] +10043a96: 60a1 str r1, [r4, #8] +10043a98: 60e0 str r0, [r4, #12] +10043a9a: 2000 movs r0, #0 +10043a9c: 61a0 str r0, [r4, #24] +10043a9e: e001 b.n 10043aa4 <__iar_dlfree+0x4e8> +10043aa0: f000 f818 bl 10043ad4 +10043aa4: 6a28 ldr r0, [r5, #32] +10043aa6: 1e40 subs r0, r0, #1 +10043aa8: 6228 str r0, [r5, #32] +10043aaa: d10b bne.n 10043ac4 <__iar_dlfree+0x508> +10043aac: f8d5 01c8 ldr.w r0, [r5, #456] ; 0x1c8 +10043ab0: e000 b.n 10043ab4 <__iar_dlfree+0x4f8> +10043ab2: 6880 ldr r0, [r0, #8] +10043ab4: 2800 cmp r0, #0 +10043ab6: d1fc bne.n 10043ab2 <__iar_dlfree+0x4f6> +10043ab8: f04f 30ff mov.w r0, #4294967295 +10043abc: 6228 str r0, [r5, #32] +10043abe: e001 b.n 10043ac4 <__iar_dlfree+0x508> +10043ac0: f000 f808 bl 10043ad4 +10043ac4: 46c0 nop ; (mov r8, r8) +10043ac6: 46c0 nop ; (mov r8, r8) +10043ac8: e8bd 87f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} + +10043acc <.text_24>: +10043acc: 10048930 .word 0x10048930 + +10043ad0 <.text_28>: +10043ad0: 10048918 .word 0x10048918 + +10043ad4 : +10043ad4: 2001 movs r0, #1 +10043ad6: f000 b817 b.w 10043b08 <__exit> + ... + +10043adc <__data_GetMemChunk>: +10043adc: 4907 ldr r1, [pc, #28] ; (10043afc <__data_GetMemChunk+0x20>) +10043ade: 6808 ldr r0, [r1, #0] +10043ae0: b108 cbz r0, 10043ae6 <__data_GetMemChunk+0xa> +10043ae2: 2000 movs r0, #0 +10043ae4: 4770 bx lr +10043ae6: 4806 ldr r0, [pc, #24] ; (10043b00 <__data_GetMemChunk+0x24>) +10043ae8: 08c0 lsrs r0, r0, #3 +10043aea: 00c0 lsls r0, r0, #3 +10043aec: 6008 str r0, [r1, #0] +10043aee: 4905 ldr r1, [pc, #20] ; (10043b04 <__data_GetMemChunk+0x28>) +10043af0: 08c9 lsrs r1, r1, #3 +10043af2: 00c9 lsls r1, r1, #3 +10043af4: 1a09 subs r1, r1, r0 +10043af6: 6001 str r1, [r0, #0] +10043af8: 4770 bx lr +10043afa: bf00 nop +10043afc: 10048b08 .word 0x10048b08 +10043b00: 00000007 .word 0x00000007 +10043b04: 00000000 .word 0x00000000 + +10043b08 <__exit>: +10043b08: 2120 movs r1, #32 +10043b0a: 0309 lsls r1, r1, #12 +10043b0c: 3126 adds r1, #38 ; 0x26 +10043b0e: 2018 movs r0, #24 +10043b10: beab bkpt 0x00ab +10043b12: e7f9 b.n 10043b08 <__exit> + +10043b14 <__iar_data_init3>: +10043b14: b510 push {r4, lr} +10043b16: 4907 ldr r1, [pc, #28] ; (10043b34 <__iar_data_init3+0x20>) +10043b18: 4479 add r1, pc +10043b1a: 3118 adds r1, #24 +10043b1c: 4c06 ldr r4, [pc, #24] ; (10043b38 <__iar_data_init3+0x24>) +10043b1e: 447c add r4, pc +10043b20: 3416 adds r4, #22 +10043b22: e004 b.n 10043b2e <__iar_data_init3+0x1a> +10043b24: 680a ldr r2, [r1, #0] +10043b26: 1d08 adds r0, r1, #4 +10043b28: 1851 adds r1, r2, r1 +10043b2a: 4788 blx r1 +10043b2c: 4601 mov r1, r0 +10043b2e: 42a1 cmp r1, r4 +10043b30: d1f8 bne.n 10043b24 <__iar_data_init3+0x10> +10043b32: bd10 pop {r4, pc} +10043b34: 00003314 .word 0x00003314 +10043b38: 00003370 .word 0x00003370 + +10043b3c <__write>: +10043b3c: b570 push {r4, r5, r6, lr} +10043b3e: 2600 movs r6, #0 +10043b40: 460c mov r4, r1 +10043b42: 4615 mov r5, r2 +10043b44: 2801 cmp r0, #1 +10043b46: bf18 it ne +10043b48: 2802 cmpne r0, #2 +10043b4a: d006 beq.n 10043b5a +10043b4c: e009 b.n 10043b62 + +10043b4e : +10043b4e: f814 0b01 ldrb.w r0, [r4], #1 +10043b52: f7cb fe77 bl 1000f844 +10043b56: 1c76 adds r6, r6, #1 +10043b58: 1e6d subs r5, r5, #1 + +10043b5a : +10043b5a: 2d00 cmp r5, #0 +10043b5c: d1f7 bne.n 10043b4e +10043b5e: 4630 mov r0, r6 +10043b60: bd70 pop {r4, r5, r6, pc} + +10043b62 : +10043b62: f04f 30ff mov.w r0, #4294967295 +10043b66: bd70 pop {r4, r5, r6, pc} + +10043b68 : +10043b68: 4770 bx lr + +10043b6a : +10043b6a: 4770 bx lr + +10043b6c <_Prout>: +10043b6c: b538 push {r3, r4, r5, lr} +10043b6e: 4604 mov r4, r0 +10043b70: 460d mov r5, r1 +10043b72: 4628 mov r0, r5 +10043b74: f000 f805 bl 10043b82 +10043b78: 42a8 cmp r0, r5 +10043b7a: bf18 it ne +10043b7c: 2400 movne r4, #0 +10043b7e: 4620 mov r0, r4 +10043b80: bd32 pop {r1, r4, r5, pc} + +10043b82 : +10043b82: b510 push {r4, lr} +10043b84: 4604 mov r4, r0 +10043b86: b082 sub sp, #8 +10043b88: f114 0f01 cmn.w r4, #1 +10043b8c: d00a beq.n 10043ba4 +10043b8e: f88d 0000 strb.w r0, [sp] +10043b92: 2201 movs r2, #1 +10043b94: a900 add r1, sp, #0 +10043b96: 2001 movs r0, #1 +10043b98: f7ff ffd0 bl 10043b3c <__write> +10043b9c: 2801 cmp r0, #1 +10043b9e: d101 bne.n 10043ba4 +10043ba0: 4620 mov r0, r4 +10043ba2: bd16 pop {r1, r2, r4, pc} +10043ba4: f04f 30ff mov.w r0, #4294967295 +10043ba8: bd16 pop {r1, r2, r4, pc} + ... + +10043bac : +10043bac: f3ef 8009 mrs r0, PSP +10043bb0: f3bf 8f6f isb sy +10043bb4: 4b20 ldr r3, [pc, #128] ; (10043c38 ) +10043bb6: 681a ldr r2, [r3, #0] +10043bb8: e920 0ff0 stmdb r0!, {r4, r5, r6, r7, r8, r9, sl, fp} +10043bbc: 6010 str r0, [r2, #0] +10043bbe: b508 push {r3, lr} +10043bc0: f04f 0050 mov.w r0, #80 ; 0x50 +10043bc4: f380 8811 msr BASEPRI, r0 +10043bc8: f7c7 f905 bl 1000add6 +10043bcc: f04f 0000 mov.w r0, #0 +10043bd0: f380 8811 msr BASEPRI, r0 +10043bd4: e8bd 4008 ldmia.w sp!, {r3, lr} +10043bd8: 6819 ldr r1, [r3, #0] +10043bda: 6808 ldr r0, [r1, #0] +10043bdc: e8b0 0ff0 ldmia.w r0!, {r4, r5, r6, r7, r8, r9, sl, fp} +10043be0: f380 8809 msr PSP, r0 +10043be4: f3bf 8f6f isb sy +10043be8: 4770 bx lr + +10043bea : +10043bea: f3ef 8011 mrs r0, BASEPRI +10043bee: f04f 0150 mov.w r1, #80 ; 0x50 +10043bf2: f381 8811 msr BASEPRI, r1 +10043bf6: 4770 bx lr + +10043bf8 : +10043bf8: f380 8811 msr BASEPRI, r0 +10043bfc: 4770 bx lr + +10043bfe : +10043bfe: 4b0e ldr r3, [pc, #56] ; (10043c38 ) +10043c00: 6819 ldr r1, [r3, #0] +10043c02: 6808 ldr r0, [r1, #0] +10043c04: e8b0 0ff0 ldmia.w r0!, {r4, r5, r6, r7, r8, r9, sl, fp} +10043c08: f380 8809 msr PSP, r0 +10043c0c: f3bf 8f6f isb sy +10043c10: f04f 0000 mov.w r0, #0 +10043c14: f380 8811 msr BASEPRI, r0 +10043c18: f04e 0e0d orr.w lr, lr, #13 +10043c1c: 4770 bx lr + +10043c1e : +10043c1e: 4807 ldr r0, [pc, #28] ; (10043c3c ) +10043c20: 6800 ldr r0, [r0, #0] +10043c22: 6800 ldr r0, [r0, #0] +10043c24: f380 8808 msr MSP, r0 +10043c28: b662 cpsie i +10043c2a: b661 cpsie f +10043c2c: f3bf 8f4f dsb sy +10043c30: f3bf 8f6f isb sy +10043c34: df00 svc 0 +10043c36: 0000 movs r0, r0 +10043c38: 10044004 .word 0x10044004 +10043c3c: e000ed08 .word 0xe000ed08 + +10043c40 <_Randinit>: +10043c40: 00000000 .... + +10043c44 <_Randseed>: +10043c44: 00000001 .... + +10043c48 <_Rand_idx>: +10043c48: 00000000 .... + +10043c4c <_Rand_rv>: + ... + +10043ccc <__iar_Errno>: +10043ccc: 00000000 .... + +10043cd0 <.ram.data$$Base>: +10043cd0: 00000002 .word 0x00000002 + +10043cd4 : +10043cd4: ffffffff .... + +10043cd8 : +10043cd8: 10004168 10034a19 00000000 00000000 hA...J.......... +10043ce8: 10004170 10034a67 00000000 00000000 pA..gJ.......... +10043cf8: 10004178 10034ab7 00000000 00000000 xA...J.......... +10043d08: 10004180 10034bfb 00000000 00000000 .A...K.......... +10043d18: 10004188 10034fc1 00000000 00000000 .A...O.......... +10043d28: 10004190 10034fe5 00000000 00000000 .A...O.......... +10043d38: 10004198 10035009 00000000 00000000 .A...P.......... +10043d48: 100041a0 10035111 00000000 00000000 .A...Q.......... +10043d58: 100041a8 100351bd 00000000 00000000 .A...Q.......... +10043d68: 100041b0 1003520d 00000000 00000000 .A...R.......... +10043d78: 100041b8 100352b3 00000000 00000000 .A...R.......... +10043d88: 100041c0 100352bb 00000000 00000000 .A...R.......... +10043d98: 100041c8 100352d5 00000000 00000000 .A...R.......... + +10043da8 : +10043da8: 100041d0 100363c9 00000000 00000000 .A...c.......... +10043db8: 100041d8 100363f9 00000000 00000000 .A...c.......... +10043dc8: 100041e0 1003642f 00000000 00000000 .A../d.......... +10043dd8: 100041e8 1003646f 00000000 00000000 .A..od.......... +10043de8: 100041f0 100364ad 00000000 00000000 .A...d.......... +10043df8: 100041f8 100364dd 00000000 00000000 .A...d.......... +10043e08: 10004200 100364f9 00000000 00000000 .B...d.......... +10043e18: 10004208 10036575 00000000 00000000 .B..ue.......... +10043e28: 10004210 1003696f 00000000 00000000 .B..oi.......... +10043e38: 10004218 10036691 00000000 00000000 .B...f.......... +10043e48: 10004220 100367b7 00000000 00000000 B...g.......... +10043e58: 10004228 10036929 00000000 00000000 (B..)i.......... +10043e68: 10004230 10036903 00000000 00000000 0B...i.......... +10043e78: 10004238 1003682f 00000000 00000000 8B../h.......... +10043e88: 10004240 10036ae3 00000000 00000000 @B...j.......... +10043e98: 10004248 10036d2f 00000000 00000000 HB../m.......... +10043ea8: 10004250 10036b91 00000000 00000000 PB...k.......... +10043eb8: 10004258 10036b29 00000000 00000000 XB..)k.......... +10043ec8: 10004260 10036b3b 00000000 00000000 `B..;k.......... +10043ed8: 10004268 10036b65 00000000 00000000 hB..ek.......... +10043ee8: 10004270 10036b8f 00000000 00000000 pB...k.......... +10043ef8: 10004278 10036a4b 00000000 00000000 xB..Kj.......... +10043f08: 10004280 10036bc7 00000000 00000000 .B...k.......... +10043f18: 10004288 10036bc7 00000000 00000000 .B...k.......... + +10043f28 : +10043f28: 00000000 .... + +10043f2c : +10043f2c: 10043307 .3.. + +10043f30 : +10043f30: 100435bd .5.. + +10043f34 : +10043f34: 00000000 .... + +10043f38 : +10043f38: 00000000 .... + +10043f3c : +10043f3c: 00000000 .... + +10043f40 : +10043f40: 00000000 .... + +10043f44 : +10043f44: 00000000 .... + +10043f48 : +10043f48: 00000000 .... + +10043f4c : +10043f4c: 00000000 .... + +10043f50 : +10043f50: 00000005 .... + +10043f54 : + ... + +10043f64 : +10043f64: 00000000 .... + +10043f68 : +10043f68: 00000000 .... + +10043f6c : +10043f6c: 00000000 .... + +10043f70 : +10043f70: 00000000 .... + +10043f74 : +10043f74: 00000000 .... + +10043f78 : +10043f78: 00000000 .... + +10043f7c : +10043f7c: 00000000 .... + +10043f80 : +10043f80: 00000000 .... + +10043f84 : +10043f84: ffffffff .... + +10043f88 : +10043f88: 00000000 .... + +10043f8c : + ... + +10043f9c : + ... + +10043fac : +10043fac: 00000007 .... + +10043fb0 : +10043fb0: 00000009 .... + +10043fb4 : +10043fb4: 10004298 10035a4f 00000000 00000000 .B..OZ.......... +10043fc4: 100042a0 10035a4f 00000000 00000000 .B..OZ.......... + +10043fd4 : +10043fd4: aaaaaaaa .... + +10043fd8 : +10043fd8: 09ef21a9 .!.. + +10043fdc : + ... + +10043ff0 : + ... + +10044004 : +10044004: 00000000 .... + +10044008 : +10044008: 00000000 .... + +1004400c : +1004400c: 00000000 .... + +10044010 : +10044010: 00000000 .... + +10044014 : + ... + +10044028 : +10044028: 00000000 .... + +1004402c : +1004402c: 00000000 .... + +10044030 : +10044030: 00000000 .... + +10044034 : +10044034: 00000000 .... + +10044038 : +10044038: 00000000 .... + +1004403c : +1004403c: 00000000 .... + +10044040 : +10044040: 00000000 .... + +10044044 : +10044044: 00000000 .... + +10044048 : +10044048: ffffffff .... + +1004404c : +1004404c: 00000000 .... + +10044050 : + ... + +10044064 : + ... + +10044078 : + ... + +10044079 : +10044079: 00000000 ... + +1004407c : +1004407c: 00000000 .... + +10044080 : +10044080: 00000000 .... + +10044084 : +10044084: 00000000 .... + +10044088 : +10044088: 00000000 .... + +1004408c : +1004408c: 00000000 .... + +10044090 : +10044090: 00000000 .... + +10044094 : +10044094: 0000196e n... + +10044098 : +10044098: 0000c000 .... + +1004409c : +1004409c: 00000000 .... + +100440a0 : + ... + +10044154 : + ... + +10044155 : + ... + +10044156 : + ... + +10044157 : + ... + +10044158 : + ... + +1004415a : +1004415a: 000001f4 .. + +1004415c : +1004415c: 00000000 .... + +10044160 : +10044160: 1003c1db .... + +10044164 : +10044164: 0f0014dd 000004ac ........ + +1004416c : +1004416c: deadb00b .... + +10044170 : +10044170: 000000ff .... + +10044174 : +10044174: 00000000 .... + +10044178 : +10044178: 00000000 .... + +1004417c : +1004417c: 00000000 .... + +10044180 : +10044180: 00000000 .... + +10044184 : +10044184: 00000000 .... + +10044188 : +10044188: 00000000 .... + +1004418c : +1004418c: 00000000 .... + +10044190 : +10044190: 00000000 .... + +10044194 : +10044194: 00000000 .... + +10044198 : +10044198: 00000000 .... + +1004419c : + ... + +100441a4 : +100441a4: 00000002 00000000 ........ + +100441ac : +100441ac: 00000002 0000000a 6d5f6373 74736163 ........sc_mcast +100441bc: 7064755f 00000000 00000000 00000000 _udp............ + ... +100441d4: 1003cbad 1003caa7 1003cacd 1003cd21 ............!... +100441e4: 1003ccc3 .... + +100441e8 : +100441e8: 00000003 0000000a 6d5f6373 74736163 ........sc_mcast +100441f8: 7064755f 00000000 00000000 00000000 _udp............ + ... +10044210: 1003cbad 1003caa7 1003cacd 1003cd21 ............!... +10044220: 1003ccc3 .... + +10044224 : +10044224: 10014bd9 10014b23 10014e67 10014e49 .K..#K..gN..IN.. +10044234: 1001424f 100142c3 100142db 100142e9 OB...B...B...B.. +10044244: 10014391 100143fd 1001444b 10015601 .C...C..KD...V.. +10044254: 10015627 'V.. + +10044258 : +10044258: 00000000 100043c0 1001a3cd 00000010 .....C.......... +10044268: 100043cc 1001a9f5 00000020 100043d8 .C...... ....C.. +10044278: 1001a3cd 00000030 100043e8 1001a9f5 ....0....C...... +10044288: 00000040 100043f8 10019e03 00000050 @....C......P... +10044298: 10004404 10019ec3 00000000 10004410 .D...........D.. +100442a8: 1001afab 00000000 10004410 1001afab .........D...... +100442b8: 00000080 1000441c 10019ed5 00000090 .....D.......... +100442c8: 10004428 1001afab 000000a0 10004430 (D..........0D.. +100442d8: 1001acb9 000000b0 1000443c 1001a2cd ........: +10044300: 00f80000 .... + +10044304 : +10044304: 00000000 .... + +10044308 : +10044308: 0ffff015 15000000 00000ff0 f0050000 ................ +10044318: 00000fff 0ff00500 00000000 0ffff010 ................ +10044328: 10000000 00000ff0 0ff50000 00000000 ................ +10044338: 000ff000 00000000 0000000f 00000000 ................ + +10044348 : +10044348: 00000000 .... + +1004434c : +1004434c: 32323264 241d2f28 0a07181f 1e232d28 d222(/.$....(-#. +1004435c: 0a0b1921 !... + +10044360 : +10044360: 0a0a0a0a 0a0a1414 02020202 0a0a1414 ................ +10044370: 04020201 .... + +10044374 : +10044374: 01010101 04030201 08070605 04030201 ................ +10044384: 08070605 .... + +10044388 : +10044388: 02010101 03030201 05050404 07060402 ................ +10044398: 08080807 .... + +1004439c : +1004439c: ffff0007 00000710 ffff0006 00000310 ................ +100443ac: ffff0020 00020210 ffff0020 00000220 ....... ... ... +100443bc: ffffffff 00000040 00000000 00000000 ....@........... + ... + +1004443c : +1004443c: 3fff0000 00002010 ffff0004 00010110 ...?. .......... +1004444c: ffff0020 00010110 ffff0020 00000120 ....... ... ... +1004445c: ffffffff 00000040 00000000 00000000 ....@........... + ... + +100444dc : +100444dc: 00000005 1000447c 00000001 10004480 ....|D.......D.. +100444ec: 000000c0 .... + +100444f0 : +100444f0: 80002000 00000000 40000000 00000000 . .........@.... +10044500: 00000c78 fc000001 00000c78 fb010001 x.......x....... +10044510: 00000c78 fa020001 00000c78 f9030001 x.......x....... +10044520: 00000c78 f8040001 00000c78 f7050001 x.......x....... +10044530: 00000c78 f6060001 00000c78 f5070001 x.......x....... +10044540: 00000c78 f4080001 00000c78 f3090001 x.......x....... +10044550: 00000c78 f20a0001 00000c78 f10b0001 x.......x....... +10044560: 00000c78 f00c0001 00000c78 ef0d0001 x.......x....... +10044570: 00000c78 ee0e0001 00000c78 ed0f0001 x.......x....... +10044580: 00000c78 ec100001 00000c78 eb110001 x.......x....... +10044590: 00000c78 ea120001 00000c78 e9130001 x.......x....... +100445a0: 00000c78 e8140001 00000c78 e7150001 x.......x....... +100445b0: 00000c78 e6160001 00000c78 e5170001 x.......x....... +100445c0: 00000c78 e4180001 00000c78 e3190001 x.......x....... +100445d0: 00000c78 e21a0001 00000c78 e11b0001 x.......x....... +100445e0: 00000c78 e01c0001 00000c78 c31d0001 x.......x....... +100445f0: 00000c78 c21e0001 00000c78 c11f0001 x.......x....... +10044600: 00000c78 c0200001 00000c78 a3210001 x..... .x.....!. +10044610: 00000c78 a2220001 00000c78 a1230001 x.....".x.....#. +10044620: 00000c78 a0240001 00000c78 84250001 x.....$.x.....%. +10044630: 00000c78 83260001 00000c78 82270001 x.....&.x.....'. +10044640: 00000c78 81280001 00000c78 80290001 x.....(.x.....). +10044650: 00000c78 442a0001 00000c78 432b0001 x.....*Dx.....+C +10044660: 00000c78 422c0001 00000c78 412d0001 x.....,Bx.....-A +10044670: 00000c78 402e0001 00000c78 042f0001 x......@x...../. +10044680: 00000c78 03300001 00000c78 02310001 x.....0.x.....1. +10044690: 00000c78 01320001 00000c78 00330001 x.....2.x.....3. +100446a0: 00000c78 00340001 00000c78 00350001 x.....4.x.....5. +100446b0: 00000c78 00360001 00000c78 00370001 x.....6.x.....7. +100446c0: 00000c78 00380001 00000c78 00390001 x.....8.x.....9. +100446d0: 00000c78 003a0001 00000c78 003b0001 x.....:.x.....;. +100446e0: 00000c78 003c0001 00000c78 003d0001 x.....<.x.....=. +100446f0: 00000c78 003e0001 00000c78 003f0001 x.....>.x.....?. +10044700: 90003000 00000000 40000000 00000000 .0.........@.... +10044710: 00000c78 ff000001 00000c78 ff010001 x.......x....... +10044720: 00000c78 ff020001 00000c78 ff030001 x.......x....... +10044730: 00000c78 ff040001 00000c78 ff050001 x.......x....... +10044740: 00000c78 ff060001 00000c78 fe070001 x.......x....... +10044750: 00000c78 fd080001 00000c78 fc090001 x.......x....... +10044760: 00000c78 fb0a0001 00000c78 fa0b0001 x.......x....... +10044770: 00000c78 f90c0001 00000c78 f80d0001 x.......x....... +10044780: 00000c78 f70e0001 00000c78 f60f0001 x.......x....... +10044790: 00000c78 f5100001 00000c78 f4110001 x.......x....... +100447a0: 00000c78 f3120001 00000c78 f2130001 x.......x....... +100447b0: 00000c78 f1140001 00000c78 ef150001 x.......x....... +100447c0: 00000c78 ee160001 00000c78 ed170001 x.......x....... +100447d0: 00000c78 ec180001 00000c78 eb190001 x.......x....... +100447e0: 00000c78 ea1a0001 00000c78 e91b0001 x.......x....... +100447f0: 00000c78 e81c0001 00000c78 e71d0001 x.......x....... +10044800: 00000c78 e61e0001 00000c78 e51f0001 x.......x....... +10044810: 00000c78 e4200001 00000c78 e3210001 x..... .x.....!. +10044820: 00000c78 e2220001 00000c78 e1230001 x.....".x.....#. +10044830: 00000c78 e0240001 00000c78 c6250001 x.....$.x.....%. +10044840: 00000c78 c5260001 00000c78 c4270001 x.....&.x.....'. +10044850: 00000c78 c3280001 00000c78 a3290001 x.....(.x.....). +10044860: 00000c78 a22a0001 00000c78 a12b0001 x.....*.x.....+. +10044870: 00000c78 a02c0001 00000c78 842d0001 x.....,.x.....-. +10044880: 00000c78 832e0001 00000c78 822f0001 x.......x...../. +10044890: 00000c78 81300001 00000c78 62310001 x.....0.x.....1b +100448a0: 00000c78 61320001 00000c78 60330001 x.....2ax.....3` +100448b0: 00000c78 45340001 00000c78 44350001 x.....4Ex.....5D +100448c0: 00000c78 43360001 00000c78 42370001 x.....6Cx.....7B +100448d0: 00000c78 41380001 00000c78 23390001 x.....8Ax.....9# +100448e0: 00000c78 223a0001 00000c78 213b0001 x.....:"x.....;! +100448f0: 00000c78 203c0001 00000c78 033d0001 x.....< x.....=. +10044900: 00000c78 023e0001 00000c78 013f0001 x.....>.x.....?. +10044910: a0000000 00000000 00000c78 fa000001 ........x....... +10044920: 00000c78 f9010001 00000c78 f8020001 x.......x....... +10044930: 00000c78 f7030001 00000c78 f6040001 x.......x....... +10044940: 00000c78 f5050001 00000c78 f4060001 x.......x....... +10044950: 00000c78 f3070001 00000c78 f2080001 x.......x....... +10044960: 00000c78 f1090001 00000c78 f00a0001 x.......x....... +10044970: 00000c78 ef0b0001 00000c78 ee0c0001 x.......x....... +10044980: 00000c78 ed0d0001 00000c78 ec0e0001 x.......x....... +10044990: 00000c78 eb0f0001 00000c78 ea100001 x.......x....... +100449a0: 00000c78 e9110001 00000c78 e8120001 x.......x....... +100449b0: 00000c78 e7130001 00000c78 e6140001 x.......x....... +100449c0: 00000c78 e5150001 00000c78 e4160001 x.......x....... +100449d0: 00000c78 e3170001 00000c78 e2180001 x.......x....... +100449e0: 00000c78 e1190001 00000c78 e01a0001 x.......x....... +100449f0: 00000c78 c21b0001 00000c78 c11c0001 x.......x....... +10044a00: 00000c78 c01d0001 00000c78 a51e0001 x.......x....... +10044a10: 00000c78 a41f0001 00000c78 a3200001 x.......x..... . +10044a20: 00000c78 a2210001 00000c78 a1220001 x.....!.x.....". +10044a30: 00000c78 a0230001 00000c78 83240001 x.....#.x.....$. +10044a40: 00000c78 82250001 00000c78 81260001 x.....%.x.....&. +10044a50: 00000c78 80270001 00000c78 45280001 x.....'.x.....(E +10044a60: 00000c78 44290001 00000c78 432a0001 x.....)Dx.....*C +10044a70: 00000c78 422b0001 00000c78 412c0001 x.....+Bx.....,A +10044a80: 00000c78 402d0001 00000c78 072e0001 x.....-@x....... +10044a90: 00000c78 062f0001 00000c78 05300001 x...../.x.....0. +10044aa0: 00000c78 04310001 00000c78 03320001 x.....1.x.....2. +10044ab0: 00000c78 02330001 00000c78 01340001 x.....3.x.....4. +10044ac0: 00000c78 00350001 00000c78 00360001 x.....5.x.....6. +10044ad0: 00000c78 00370001 00000c78 00380001 x.....7.x.....8. +10044ae0: 00000c78 00390001 00000c78 003a0001 x.....9.x.....:. +10044af0: 00000c78 003b0001 00000c78 003c0001 x.....;.x.....<. +10044b00: 00000c78 003d0001 00000c78 003e0001 x.....=.x.....>. +10044b10: 00000c78 003f0001 b0000000 00000000 x.....?......... +10044b20: 00000c50 69553422 00000c50 69553420 P..."4UiP... 4Ui + +10044b30 : +10044b30: 00000800 80045700 00000804 00000003 .....W.......... +10044b40: 00000808 0000fc00 0000080c 0000000a ................ +10044b50: 00000810 10001331 00000814 020c3d10 ....1........=.. +10044b60: 00000818 02200385 0000081c 00000000 ...... ......... +10044b70: 00000820 01000100 00000824 00390204 .......$.....9. +10044b80: 00000828 00000000 0000082c 00000000 (.......,....... +10044b90: 00000830 00000000 00000834 00000000 0.......4....... +10044ba0: 00000838 00000000 0000083c 00000000 8.......<....... +10044bb0: 00000840 00010000 00000844 00000000 @.......D....... +10044bc0: 00000848 00000000 0000084c 00000000 H.......L....... +10044bd0: 00000850 00000000 00000854 00000000 P.......T....... +10044be0: 00000858 569a11a9 0000085c 01000014 X......V\....... +10044bf0: 00000860 66f60110 00000864 061f0649 `......fd...I... +10044c00: 00000868 00000000 0000086c 27272700 h.......l....''' +10044c10: 00000870 07000760 00000874 25004000 p...`...t....@.% +10044c20: 00000878 00000808 0000087c 004f0201 x.......|.....O. +10044c30: 00000880 b0000b1e 00000884 00000001 ................ +10044c40: 00000888 00000000 0000088c ccc000c0 ................ +10044c50: 00000890 00000800 00000894 fffffffe ................ +10044c60: 00000898 40302010 0000089c 00706050 ..... 0@....P`p. +10044c70: 00000900 00000000 00000904 00000023 ............#... +10044c80: 00000908 00000000 0000090c 81121111 ................ +10044c90: 00000910 00000002 00000914 00000201 ................ +10044ca0: 00000948 99000000 0000094c 00000010 H.......L....... +10044cb0: 00000950 20003000 00000954 3a880000 P....0. T......: +10044cc0: 00000958 4bc5d87a 0000095c 04eb9b79 X...z..K\...y... +10044cd0: 00000a00 00d047c8 00000a04 80ff800c .....G.......... +10044ce0: 00000a08 8c038300 00000a0c 2e7f120f ................ +10044cf0: 00000a10 9500bb78 00000a14 1114d028 ....x.......(... +10044d00: 00000a18 00881117 00000a1c 89140f00 ................ +10044d10: 00000a20 c8d00000 00000a24 487094b4 .......$.....pH +10044d20: 00000a28 0000102c 00000a2c 00d30000 (...,...,....... +10044d30: 00000a70 101fbf00 00000a74 00000007 p.......t....... +10044d40: 00000a78 00008900 00000a7c 225b0606 x.......|.....[" +10044d50: 00000a80 218075b1 82000000 00000000 .....u.!........ +10044d60: 40000000 00000000 00000a84 00100000 ...@............ +10044d70: a0000000 00000000 00000a84 001f0000 ................ +10044d80: b0000000 00000000 00000a88 040c0000 ................ +10044d90: 00000a8c 12345678 00000a90 abcdef00 ....xV4......... +10044da0: 00000a94 001b1b89 00000a98 00080000 ................ +10044db0: 00000a9c 3f000000 00000aa0 00000000 .......?........ +10044dc0: 00000b2c 00000000 00000c00 48071d40 ,...........@..H +10044dd0: 00000c04 03a05611 00000c08 000000e4 .....V.......... +10044de0: 00000c0c 6c6c6c6c 00000c10 18800000 ....llll........ +10044df0: 00000c14 40000100 00000c18 08800000 .......@........ +10044e00: 00000c1c 40000100 00000c20 00000000 .......@ ....... +10044e10: 00000c24 00000000 00000c28 00000000 $.......(....... +10044e20: 00000c2c 00000000 00000c30 69e9cc4a ,.......0...J..i +10044e30: 00000c34 31000040 00000c38 21688080 4...@..18.....h! +10044e40: 00000c3c 000016cc 00000c40 1f78403f <.......@...?@x. +10044e50: 00000c44 00010036 00000c48 ec020107 D...6...H....... +10044e60: 00000c4c 007f037f 00000c50 69553420 L.......P... 4Ui +10044e70: 00000c54 43bc0094 00000c58 00013169 T......CX...i1.. +10044e80: 00000c5c 00250492 00000c60 00000000 \.....%.`....... +10044e90: 00000c64 7112848b 00000c68 47c07bff d......qh....{.G +10044ea0: 00000c6c 00000036 00000c70 2c7f000d l...6...p......, +10044eb0: 00000c74 020600db 00000c78 0000001f t.......x....... +10044ec0: 00000c7c 00b91612 00000c80 390000e4 |..............9 +10044ed0: 00000c84 11f60000 00000c88 40000100 ...............@ +10044ee0: 00000c8c 20200000 00000c90 00091521 ...... ....!... +10044ef0: 00000c94 00000000 00000c98 00121820 ............ ... +10044f00: 00000c9c 00007f7f 00000ca0 00000000 ................ +10044f10: 00000ca4 000300a0 00000ca8 00000000 ................ +10044f20: 00000cac 00000000 00000cb0 00000000 ................ +10044f30: 00000cb4 00000000 00000cb8 00000000 ................ +10044f40: 00000cbc 28000000 00000cc0 00000000 .......(........ +10044f50: 00000cc4 00000000 00000cc8 00000000 ................ +10044f60: 00000ccc 00000000 00000cd0 00000000 ................ +10044f70: 00000cd4 00000000 00000cd8 64b22427 ............'$.d +10044f80: 00000cdc 00766932 00000ce0 00222222 ....2iv.....""". +10044f90: 00000ce4 10000000 00000ce8 37644302 .............Cd7 +10044fa0: 00000cec 2f97d40c 00000d00 00030740 ......./....@... +10044fb0: 00000d04 40020401 00000d08 0000907f .......@........ +10044fc0: 00000d0c 20010201 00000d10 a0633333 ....... ....33c. +10044fd0: 00000d14 3333bc53 00000d18 7a8f5b6f ....S.33....o[.z +10044fe0: 00000d2c cb979975 00000d30 00000000 ,...u...0....... +10044ff0: 00000d34 80608000 00000d38 98000000 4.....`.8....... +10045000: 00000d3c 40127353 00000d40 00000000 <...Ss.@@....... +10045010: 00000d44 00000000 00000d48 00000000 D.......H....... +10045020: 00000d4c 00000000 00000d50 6437140a L.......P.....7d +10045030: 00000d54 00000000 00000d58 00000282 T.......X....... +10045040: 00000d5c 30032064 00000d60 4653de68 \...d .0`...h.SF +10045050: 00000d64 04518a3c 00000d68 00002101 d...<.Q.h....!.. +10045060: 00000e00 2d2d2d2d 00000e04 2d2d2d2d ....----....---- +10045070: 00000e08 0390272d 00000e10 2d2d2d2d ....-'......---- +10045080: 00000e14 2d2d2d2d 00000e18 2d2d2d2d ....----....---- +10045090: 00000e1c 2d2d2d2d 00000e28 00000000 ....----(....... +100450a0: 00000e30 1000dc1f 00000e34 10008c1f 0.......4....... +100450b0: 00000e38 02140102 00000e3c 681604c2 8.......<......h +100450c0: 00000e40 01007c00 00000e44 01004800 @....|..D....H.. +100450d0: 00000e48 fb000000 00000e4c 000028d1 H.......L....(.. +100450e0: 00000e50 1000dc1f 00000e54 10008c1f P.......T....... +100450f0: 00000e58 02140102 00000e5c 28160d05 X.......\......( +10045100: 00000e60 00000008 00000e68 001b25a4 `.......h....%.. +10045110: 00000e6c 01c00014 00000e70 01c00014 l.......p....... +10045120: 00000e74 02000014 00000e78 02000014 t.......x....... +10045130: 00000e7c 02000014 00000e80 02000014 |............... +10045140: 00000e84 01c00014 00000e88 02000014 ................ +10045150: 00000e8c 01c00014 00000ed0 01c00014 ................ +10045160: 00000ed4 01c00014 00000ed8 01c00014 ................ +10045170: 00000edc 00000014 00000ee0 00000014 ................ +10045180: 00000ee8 21555448 00000eec 03c00014 ....HTU!........ +10045190: 00000f14 00000003 00000f4c 00000000 ........L....... +100451a0: 00000f00 00000300 ........ + +100451a8 : + ... +100451b4: 00000e08 0000ff00 00003200 00000000 .........2...... + ... +100451cc: 0000086c ffffff00 32323200 00000000 l........222.... + ... +100451e4: 00000e00 ffffffff 34363636 00000000 ........6664.... + ... +100451fc: 00000e04 ffffffff 28303234 00000000 ........420(.... + ... +10045214: 00000e10 ffffffff 30343434 00000000 ........4440.... + ... +1004522c: 00000e14 ffffffff 26262830 ........0(&& + +10045238 : +10045238: 00000056 0000000e 00000421 0000000f V.......!....... +10045248: 00000428 0000000a 00000429 00000010 (.......)....... +10045258: 00000430 00000000 00000431 00000000 0.......1....... +10045268: 00000432 00000000 00000433 00000001 2.......3....... +10045278: 00000434 00000004 00000435 00000005 4.......5....... +10045288: 00000436 00000007 00000437 00000008 6.......7....... +10045298: 0000043c 00000004 0000043d 00000005 <.......=....... +100452a8: 0000043e 00000007 0000043f 00000008 >.......?....... +100452b8: 00000440 0000005d 00000441 00000001 @...]...A....... +100452c8: 00000442 00000000 00000444 00000010 B.......D....... +100452d8: 00000445 00000000 00000446 00000000 E.......F....... +100452e8: 00000447 00000000 00000448 00000000 G.......H....... +100452f8: 00000449 000000f0 0000044a 0000000f I.......J....... +10045308: 0000044b 0000003e 0000044c 00000010 K...>...L....... +10045318: 0000044d 00000000 0000044e 00000000 M.......N....... +10045328: 0000044f 00000000 00000450 00000000 O.......P....... +10045338: 00000451 000000f0 00000452 0000000f Q.......R....... +10045348: 00000453 00000000 00000456 0000005e S.......V...^... +10045358: 00000460 00000066 00000461 00000066 `...f...a...f... +10045368: 000004c8 000000ff 000004c9 00000008 ................ +10045378: 000004cc 000000ff 000004cd 000000ff ................ +10045388: 000004ce 00000001 00000500 00000026 ............&... +10045398: 00000501 000000a2 00000502 0000002f ............/... +100453a8: 00000503 00000000 00000504 00000028 ............(... +100453b8: 00000505 000000a3 00000506 0000005e ............^... +100453c8: 00000507 00000000 00000508 0000002b ............+... +100453d8: 00000509 000000a4 0000050a 0000005e ............^... +100453e8: 0000050b 00000000 0000050c 0000004f ............O... +100453f8: 0000050d 000000a4 0000050e 00000000 ................ +10045408: 0000050f 00000000 00000512 0000001c ................ +10045418: 00000514 0000000a 00000516 0000000a ................ +10045428: 00000525 0000004f 00000550 00000010 %...O...P....... +10045438: 00000551 00000010 00000559 00000002 Q.......Y....... +10045448: 0000055c 00000028 0000055d 000000ff \...(...]....... +10045458: 00000605 00000030 00000608 0000000e ....0........... +10045468: 00000609 0000002a 00000620 000000ff ....*... ....... +10045478: 00000621 000000ff 00000622 000000ff !......."....... +10045488: 00000623 000000ff 00000624 000000ff #.......$....... +10045498: 00000625 000000ff 00000626 000000ff %.......&....... +100454a8: 00000627 000000ff 00000638 00000028 '.......8...(... +100454b8: 0000063c 0000000a 0000063d 0000000a <.......=....... +100454c8: 0000063e 0000000e 0000063f 0000000e >.......?....... +100454d8: 00000640 00000040 00000642 00000040 @...@...B...@... +100454e8: 00000643 00000000 00000652 00000020 C.......R... ... +100454f8: 0000066e 00000005 00000700 00000021 n...........!... +10045508: 00000701 00000043 00000702 00000065 ....C.......e... +10045518: 00000703 00000087 00000708 00000021 ............!... +10045528: 00000709 00000043 0000070a 00000065 ....C.......e... +10045538: 0000070b 00000087 ........ + +10045540 : +10045540: 00000000 00030000 00000008 00008400 ................ +10045550: 00000018 00000407 00000019 00000012 ................ +10045560: 0000001b 00000c6c 0000001e 00080009 ....l........... +10045570: 0000001f 00000880 0000002f 0001a060 ......../...`... +10045580: 0000003f 00000000 00000042 000060c0 ?.......B....`.. +10045590: 00000057 000d0000 00000058 000c0160 W.......X...`... +100455a0: 00000067 00001552 00000083 00000000 g...R........... +100455b0: 000000b0 000ff9f0 000000b1 00010018 ................ +100455c0: 000000b2 00054c00 000000b4 0004484b .....L......KH.. +100455d0: 000000b5 0000112a 000000b6 0000053e ....*.......>... +100455e0: 000000b7 00010408 000000b8 00010200 ................ +100455f0: 000000b9 00080001 000000ba 00040001 ................ +10045600: 000000bb 00000400 000000bf 000c0000 ................ +10045610: 000000c2 00002400 000000c3 00000009 .....$.......... +10045620: 000000c4 00040c91 000000c5 00099999 ................ +10045630: 000000c6 000000a3 000000c7 00088820 ............ ... +10045640: 000000c8 00076c06 000000c9 00000000 .....l.......... +10045650: 000000ca 00080000 000000df 00000180 ................ +10045660: 000000ef 000001a0 82000000 00000000 ................ +10045670: 40000000 00000000 00000051 000e8131 ...@....Q...1... +10045680: 00000052 000faa88 a0000000 00000000 R............... +10045690: 00000051 000ec131 00000052 000fb888 Q...1...R....... +100456a0: b0000000 00000000 00000053 00000001 ........S....... +100456b0: 00000056 000517f0 00000035 00000088 V.......5....... +100456c0: 00000035 00000188 00000035 00000288 5.......5....... +100456d0: 82000000 00000000 40000000 00000000 ...........@.... +100456e0: 00000036 00000054 00000036 00008054 6...T...6...T... +100456f0: 00000036 00010054 00000036 00018054 6...T...6...T... +10045700: a0000000 00000000 00000036 000000c6 ........6....... +10045710: 00000036 000080c6 00000036 000100c6 6.......6....... +10045720: 00000036 000180c6 b0000000 00000000 6............... +10045730: 00000018 00000c07 0000005a 00048000 ........Z....... +10045740: 00000019 000739d0 00000034 0000add6 .....9..4....... +10045750: 00000034 00009dd3 00000034 00008cf4 4.......4....... +10045760: 00000034 00007cf1 00000034 00006cee 4....|..4....l.. +10045770: 00000034 00005ceb 00000034 00004cce 4....\..4....L.. +10045780: 00000034 00003ccb 00000034 00002cc8 4....<..4....,.. +10045790: 00000034 00001c4b 00000034 00000c48 4...K...4...H... +100457a0: 00000000 00030159 00000084 00048000 ....Y........... +100457b0: 00000086 0000002a 00000087 00000025 ....*.......%... +100457c0: 0000008e 00065540 0000008f 00088000 ....@U.......... +100457d0: 000000ef 000020a0 0000003b 000f0f00 ..... ..;....... +100457e0: 0000003b 000e0b00 0000003b 000d0900 ;.......;....... +100457f0: 0000003b 000c0700 0000003b 000b0600 ;.......;....... +10045800: 0000003b 000a0400 0000003b 00090200 ;.......;....... +10045810: 0000003b 00080000 0000003b 00070f00 ;.......;....... +10045820: 0000003b 00060b00 0000003b 0005c900 ;.......;....... +10045830: 0000003b 00040700 0000003b 00030600 ;.......;....... +10045840: 0000003b 0002d500 0000003b 00010200 ;.......;....... +10045850: 0000003b 0000e000 000000ef 000000a0 ;............... +10045860: 000000ef 00080000 00000030 00010000 ........0....... +10045870: 00000031 0000000f 00000032 00007efe 1.......2....~.. +10045880: 000000ef 00000000 00000000 00010159 ............Y... +10045890: 00000018 0000fc07 000000fe 00000000 ................ +100458a0: 000000fe 00000000 0000001f 00080003 ................ +100458b0: 000000fe 00000000 000000fe 00000000 ................ +100458c0: 0000001e 00000001 0000001f 00080000 ................ +100458d0: 00000000 00033d95 .....=.. + +100458d8 : +100458d8: 01000000 04030202 06050505 08080707 ................ +100458e8: 0a090908 0c0c0b0b 0d0d0c0c 00000d0d ................ + +100458f8 : +100458f8: 02020100 04040403 07070605 0a090908 ................ +10045908: 0d0c0b0a 0d0d0d0d 0d0d0d0d 00000d0d ................ + +10045918 : +10045918: 01000000 04030202 06050505 08080707 ................ +10045928: 0a090908 0c0c0b0b 0d0d0c0c 00000d0d ................ + +10045938 : +10045938: 02020100 04040403 07070605 0a090908 ................ +10045948: 0d0c0b0a 0d0d0d0d 0d0d0d0d 00000d0d ................ + +10045958 : +10045958: 02020100 05040302 07060505 08080808 ................ +10045968: 0b0b0a09 0e0d0c0b 0e0e0e0e 00000e0e ................ + +10045978 : +10045978: 02010000 04030202 06050505 09080707 ................ +10045988: 0a0a0909 0a0a0a0a 0a0a0a0a 00000a0a ................ + +10045998 : +10045998: 02020100 05040302 07060505 08080808 ................ +100459a8: 0b0b0a09 0e0d0c0b 0e0e0e0e 00000e0e ................ + +100459b8 : +100459b8: 02010000 04030202 06050505 09080707 ................ +100459c8: 0a0a0909 0a0a0a0a 0a0a0a0a 00000a0a ................ + +100459d8 : +100459d8: 01000000 04030202 06050505 08080707 ................ +100459e8: 0a090908 0c0c0b0b 0d0d0c0c 00000d0d ................ + +100459f8 : +100459f8: 02020100 04040403 07070605 0a090908 ................ +10045a08: 0d0c0b0a 0d0d0d0d 0d0d0d0d 00000d0d ................ + +10045a18 : +10045a18: 01000000 04030202 06050505 08080707 ................ +10045a28: 0a090908 0c0c0b0b 0d0d0c0c 00000d0d ................ + +10045a38 : +10045a38: 02020100 04040403 07070605 0a090908 ................ +10045a48: 0d0c0b0a 0d0d0d0d 0d0d0d0d 00000d0d ................ + +10045a58 : +10045a58: 02020100 05040302 07060505 08080808 ................ +10045a68: 0b0b0a09 0e0d0c0b 0e0e0e0e 00000e0e ................ + +10045a78 : +10045a78: 02010000 04030202 06050505 09080707 ................ +10045a88: 0a0a0909 0a0a0a0a 0a0a0a0a 00000a0a ................ + +10045a98 : +10045a98: 02020100 05040302 07060505 08080808 ................ +10045aa8: 0b0b0a09 0e0d0c0b 0e0e0e0e 00000e0e ................ + +10045ab8 : +10045ab8: 02010000 04030202 06050505 09080707 ................ +10045ac8: 0a0a0909 0a0a0a0a 0a0a0a0a 00000a0a ................ + +10045ad8 : +10045ad8: 01000000 04030202 06050505 08080707 ................ +10045ae8: 0a090908 0c0c0b0b 0d0d0c0c 00000d0d ................ + +10045af8 : +10045af8: 02020100 04040403 07070605 0a090908 ................ +10045b08: 0d0c0b0a 0d0d0d0d 0d0d0d0d 00000d0d ................ + +10045b18 : +10045b18: 01000000 04030202 06050505 08080707 ................ +10045b28: 0a090908 0c0c0b0b 0d0d0c0c 00000d0d ................ + +10045b38 : +10045b38: 02020100 04040403 07070605 0a090908 ................ +10045b48: 0d0c0b0a 0d0d0d0d 0d0d0d0d 00000d0d ................ + +10045b58 : +10045b58: 02020100 05040302 07060505 08080808 ................ +10045b68: 0b0b0a09 0e0d0c0b 0e0e0e0e 00000e0e ................ + +10045b78 : +10045b78: 02010000 04030202 06050505 09080707 ................ +10045b88: 0a0a0909 0a0a0a0a 0a0a0a0a 00000a0a ................ + +10045b98 : +10045b98: 02020100 05040302 07060505 08080808 ................ +10045ba8: 0b0b0a09 0e0d0c0b 0e0e0e0e 00000e0e ................ + +10045bb8 : +10045bb8: 02010000 04030202 06050505 09080707 ................ +10045bc8: 0a0a0909 0a0a0a0a 0a0a0a0a 00000a0a ................ + +10045bd8 : +10045bd8: 100047c8 100047cc 100047d4 100047d8 .G...G...G...G.. +10045be8: 100047dc 100047e0 100047e4 100047e8 .G...G...G...G.. +10045bf8: 100047cc 100047d4 100047d8 100047dc .G...G...G...G.. +10045c08: 100047e0 100047e4 100047f0 100047cc .G...G...G...G.. +10045c18: 100047d4 100047d8 100047dc 100047e0 .G...G...G...G.. +10045c28: 100047e4 100047c8 100047cc 100047d4 .G...G...G...G.. +10045c38: 100047d8 100047dc 100047f4 100047e4 .G...G...G...G.. +10045c48: 100047e8 100047cc 100047d4 100047d8 .G...G...G...G.. +10045c58: 100047dc 100047f4 100047e4 100047f0 .G...G...G...G.. +10045c68: 100047cc 100047d4 100047d8 100047dc .G...G...G...G.. +10045c78: 100047f4 100047e4 100047c8 100047cc .G...G...G...G.. +10045c88: 100047d4 100047d8 100047dc 100047f8 .G...G...G...G.. +10045c98: 100047e4 100047e8 100047cc 100047d4 .G...G...G...G.. +10045ca8: 100047d8 100047dc 100047f8 100047e4 .G...G...G...G.. +10045cb8: 100047f0 100047cc 100047d4 100047d8 .G...G...G...G.. +10045cc8: 100047dc 100047f8 100047e4 100047c8 .G...G...G...G.. +10045cd8: 100047cc 100047d4 100047d8 100047dc .G...G...G...G.. +10045ce8: 100047fc 100047e4 100047e8 100047cc .G...G...G...G.. +10045cf8: 100047d4 100047d8 100047dc 100047fc .G...G...G...G.. +10045d08: 100047e4 100047f0 100047cc 100047d4 .G...G...G...G.. +10045d18: 100047d8 100047dc 100047fc 100047e4 .G...G...G...G.. +10045d28: 100047c8 100047cc 100047d4 100047d8 .G...G...G...G.. +10045d38: 100047dc 10004800 100047e4 100047e8 .G...H...G...G.. +10045d48: 100047cc 100047d4 100047d8 100047dc .G...G...G...G.. +10045d58: 10004800 100047e4 100047f0 100047cc .H...G...G...G.. +10045d68: 100047d4 100047d8 100047dc 10004800 .G...G...G...H.. +10045d78: 100047e4 100047c8 100047cc 100047d4 .G...G...G...G.. +10045d88: 100047d8 100047dc 10004804 100047e4 .G...G...H...G.. +10045d98: 100047e8 100047cc 100047d4 100047d8 .G...G...G...G.. +10045da8: 100047dc 10004804 100047e4 100047f0 .G...H...G...G.. +10045db8: 100047cc 100047d4 100047d8 100047dc .G...G...G...G.. +10045dc8: 10004804 100047e4 100047c8 100047cc .H...G...G...G.. +10045dd8: 100047d4 100047d8 100047dc 10004808 .G...G...G...H.. +10045de8: 100047e4 100047e8 100047cc 100047d4 .G...G...G...G.. +10045df8: 100047d8 100047dc 10004808 100047e4 .G...G...H...G.. +10045e08: 100047f0 100047cc 100047d4 100047d8 .G...G...G...G.. +10045e18: 100047dc 10004808 100047e4 100047c8 .G...H...G...G.. +10045e28: 100047cc 100047d4 100047d8 100047dc .G...G...G...G.. +10045e38: 1000480c 100047e4 100047e8 100047cc .H...G...G...G.. +10045e48: 100047d4 100047d8 100047dc 1000480c .G...G...G...H.. +10045e58: 100047e4 100047f0 100047cc 100047d4 .G...G...G...G.. +10045e68: 100047d8 100047dc 1000480c 100047e4 .G...G...H...G.. +10045e78: 100047c8 100047cc 100047d4 100047d8 .G...G...G...G.. +10045e88: 100047dc 10004810 100047e4 100047e8 .G...H...G...G.. +10045e98: 100047cc 100047d4 100047d8 100047dc .G...G...G...G.. +10045ea8: 10004810 100047e4 100047f0 100047cc .H...G...G...G.. +10045eb8: 100047d4 100047d8 100047dc 10004810 .G...G...G...H.. +10045ec8: 100047e4 100047c8 100047cc 100047d4 .G...G...G...G.. +10045ed8: 100047d8 100047dc 10004814 100047e4 .G...G...H...G.. +10045ee8: 100047e8 100047cc 100047d4 100047d8 .G...G...G...G.. +10045ef8: 100047dc 10004814 100047e4 100047f0 .G...H...G...G.. +10045f08: 100047cc 100047d4 100047d8 100047dc .G...G...G...G.. +10045f18: 10004814 100047e4 100047c8 100047cc .H...G...G...G.. +10045f28: 100047d4 100047d8 100047dc 10004818 .G...G...G...H.. +10045f38: 100047e4 100047e8 100047cc 100047d4 .G...G...G...G.. +10045f48: 100047d8 100047dc 10004818 100047e4 .G...G...H...G.. +10045f58: 100047f0 100047cc 100047d4 100047d8 .G...G...G...G.. +10045f68: 100047dc 10004818 100047e4 100047c8 .G...H...G...G.. +10045f78: 100047cc 100047d4 100047d8 100047dc .G...G...G...G.. +10045f88: 1000481c 10004820 100047e8 100047cc .H.. H...G...G.. +10045f98: 100047d4 100047d8 100047dc 1000481c .G...G...G...H.. +10045fa8: 100047e4 100047f0 100047cc 100047d4 .G...G...G...G.. +10045fb8: 100047d8 100047dc 1000481c 100047e4 .G...G...H...G.. +10045fc8: 100047c8 100047cc 100047d4 100047d8 .G...G...G...G.. +10045fd8: 100047dc 10004824 10004820 100047e8 .G..$H.. H...G.. +10045fe8: 100047cc 100047d4 100047d8 100047dc .G...G...G...G.. +10045ff8: 10004824 100047e4 100047f0 100047cc $H...G...G...G.. +10046008: 100047d4 100047d8 100047dc 10004824 .G...G...G..$H.. +10046018: 100047e4 100047c8 100047cc 100047d4 .G...G...G...G.. +10046028: 100047d8 100047dc 10004828 10004820 .G...G..(H.. H.. +10046038: 100047e8 100047cc 100047d4 100047d8 .G...G...G...G.. +10046048: 100047dc 10004828 10004820 100047f0 .G..(H.. H...G.. +10046058: 100047cc 100047d4 100047d8 100047dc .G...G...G...G.. +10046068: 10004828 100047e4 100047c8 100047cc (H...G...G...G.. +10046078: 100047d4 1000482c 100047dc 100047e0 .G..,H...G...G.. +10046088: 10004834 100047e8 100047cc 100047d4 4H...G...G...G.. +10046098: 1000482c 100047dc 100047e0 10004838 ,H...G...G..8H.. +100460a8: 100047f0 100047cc 100047d4 1000482c .G...G...G..,H.. +100460b8: 100047dc 100047e0 10004838 100047c8 .G...G..8H...G.. +100460c8: 100047cc 100047d4 1000482c 100047dc .G...G..,H...G.. +100460d8: 100047f4 10004834 100047e8 100047cc .G..4H...G...G.. +100460e8: 100047d4 1000482c 100047dc 100047f4 .G..,H...G...G.. +100460f8: 10004838 100047f0 100047cc 100047d4 8H...G...G...G.. +10046108: 1000482c 100047dc 100047f4 10004838 ,H...G...G..8H.. +10046118: 100047c8 100047cc 100047d4 1000482c .G...G...G..,H.. +10046128: 100047dc 100047f8 10004838 100047e8 .G...G..8H...G.. +10046138: 100047cc 100047d4 1000482c 100047dc .G...G..,H...G.. +10046148: 100047f8 10004838 100047f0 100047cc .G..8H...G...G.. +10046158: 100047d4 1000482c 100047dc 100047f8 .G..,H...G...G.. +10046168: 10004838 100047c8 100047cc 100047d4 8H...G...G...G.. +10046178: 1000482c 100047dc 100047fc 10004838 ,H...G...G..8H.. +10046188: 100047e8 100047cc 100047d4 1000482c .G...G...G..,H.. +10046198: 100047dc 100047fc 10004838 100047f0 .G...G..8H...G.. +100461a8: 100047cc 100047d4 1000482c 100047dc .G...G..,H...G.. +100461b8: 100047fc 10004838 100047c8 100047cc .G..8H...G...G.. +100461c8: 100047d4 1000482c 100047dc 10004800 .G..,H...G...H.. +100461d8: 10004838 100047e8 100047cc 100047d4 8H...G...G...G.. +100461e8: 1000482c 100047dc 10004800 10004838 ,H...G...H..8H.. +100461f8: 100047f0 100047cc 100047d4 1000482c .G...G...G..,H.. +10046208: 100047dc 10004800 10004838 100047c8 .G...H..8H...G.. +10046218: 100047cc 100047d4 1000482c 100047dc .G...G..,H...G.. +10046228: 10004804 10004838 100047e8 100047cc .H..8H...G...G.. +10046238: 100047d4 1000482c 100047dc 10004804 .G..,H...G...H.. +10046248: 10004838 100047f0 100047cc 100047d4 8H...G...G...G.. +10046258: 1000482c 100047dc 10004804 10004838 ,H...G...H..8H.. +10046268: 100047c8 100047cc 100047d4 1000482c .G...G...G..,H.. +10046278: 100047dc 10004808 10004838 100047e8 .G...H..8H...G.. +10046288: 100047cc 100047d4 1000482c 100047dc .G...G..,H...G.. +10046298: 10004808 10004838 100047f0 100047cc .H..8H...G...G.. +100462a8: 100047d4 1000482c 100047dc 10004808 .G..,H...G...H.. +100462b8: 10004838 100047c8 100047cc 100047d4 8H...G...G...G.. +100462c8: 1000482c 100047dc 1000480c 10004838 ,H...G...H..8H.. +100462d8: 100047e8 100047cc 100047d4 1000482c .G...G...G..,H.. +100462e8: 100047dc 1000480c 10004838 100047f0 .G...H..8H...G.. +100462f8: 100047cc 100047d4 1000482c 100047dc .G...G..,H...G.. +10046308: 1000480c 10004838 100047c8 100047cc .H..8H...G...G.. +10046318: 100047d4 1000482c 100047dc 10004810 .G..,H...G...H.. +10046328: 10004834 100047e8 100047cc 100047d4 4H...G...G...G.. +10046338: 1000482c 100047dc 10004810 10004838 ,H...G...H..8H.. +10046348: 100047f0 100047cc 100047d4 1000482c .G...G...G..,H.. +10046358: 100047dc 10004810 10004838 100047c8 .G...H..8H...G.. +10046368: 100047cc 100047d4 1000482c 100047dc .G...G..,H...G.. +10046378: 10004814 10004834 100047e8 100047cc .H..4H...G...G.. +10046388: 100047d4 1000482c 100047dc 10004814 .G..,H...G...H.. +10046398: 10004838 100047f0 100047cc 100047d4 8H...G...G...G.. +100463a8: 1000482c 100047dc 10004814 10004838 ,H...G...H..8H.. +100463b8: 100047c8 100047cc 100047d4 1000482c .G...G...G..,H.. +100463c8: 100047dc 10004818 10004834 100047e8 .G...H..4H...G.. +100463d8: 100047cc 100047d4 1000482c 100047dc .G...G..,H...G.. +100463e8: 10004818 10004838 100047f0 100047cc .H..8H...G...G.. +100463f8: 100047d4 1000482c 100047dc 10004818 .G..,H...G...H.. +10046408: 10004838 100047c8 100047cc 100047d4 8H...G...G...G.. +10046418: 1000482c 100047dc 1000481c 10004820 ,H...G...H.. H.. +10046428: 100047e8 100047cc 100047d4 1000482c .G...G...G..,H.. +10046438: 100047dc 1000481c 10004838 100047f0 .G...H..8H...G.. +10046448: 100047cc 100047d4 1000482c 100047dc .G...G..,H...G.. +10046458: 1000481c 10004838 100047c8 100047cc .H..8H...G...G.. +10046468: 100047d4 1000482c 100047dc 10004824 .G..,H...G..$H.. +10046478: 10004820 100047e8 100047cc 100047d4 H...G...G...G.. +10046488: 1000482c 100047dc 10004824 10004838 ,H...G..$H..8H.. +10046498: 100047f0 100047cc 100047d4 1000482c .G...G...G..,H.. +100464a8: 100047dc 10004824 10004838 100047c8 .G..$H..8H...G.. +100464b8: 100047cc 100047d4 1000482c 100047dc .G...G..,H...G.. +100464c8: 10004828 10004820 100047e8 100047cc (H.. H...G...G.. +100464d8: 100047d4 1000482c 100047dc 10004828 .G..,H...G..(H.. +100464e8: 10004820 100047f0 100047cc 100047d4 H...G...G...G.. +100464f8: 1000482c 100047dc 10004828 10004820 ,H...G..(H.. H.. +10046508: 100047c8 100047cc 100047d4 1000483c .G...G...G..: +10046e38: 100353cb .S.. + +10046e3c : +10046e3c: 10036d91 .m.. + +10046e40 : +10046e40: 10035a63 cZ.. + +10046e44 : +10046e44: 0000c000 .... + +10046e48 : +10046e48: fffbf2cf .word 0xfffbf2cf +10046e4c: 00000350 .word 0x00000350 +10046e50: 10000384 .word 0x10000384 +10046e54: 00001c70 .word 0x00001c70 +10046e58: 10046ea8 .word 0x10046ea8 +10046e5c: 00000048 .word 0x00000048 +10046e60: 10048b18 .word 0x10048b18 +10046e64: 0000012c .word 0x0000012c +10046e68: 10048b60 .word 0x10048b60 +10046e6c: 00004e08 .word 0x00004e08 +10046e70: 10048c8c .word 0x10048c8c +10046e74: 00000024 .word 0x00000024 +10046e78: 1004da94 .word 0x1004da94 +10046e7c: 00012c00 .word 0x00012c00 +10046e80: 1005d400 .word 0x1005d400 +10046e84: 00000004 .word 0x00000004 +10046e88: 1ffff210 .word 0x1ffff210 +10046e8c: 0000f210 .word 0x0000f210 +10046e90: 1fff0000 .word 0x1fff0000 +10046e94: 00001000 .word 0x00001000 +10046e98: 1fff0094 .word 0x1fff0094 +10046e9c: 00000010 .word 0x00000010 +10046ea0: 1fff14d4 .word 0x1fff14d4 +10046ea4: 00000000 .word 0x00000000 + +10046ea8 : + ... + +100471e8 : + ... + +10047220 : + ... + +10047254 : + ... + +10047298 : +10047298: 00000000 .... + +1004729c : + ... + +100472a8 : + ... + +100472d0 : +100472d0: 00000000 .... + +100472d4 : + ... + +1004739c : +1004739c: 00000000 .... + +100473a0 : +100473a0: 00000000 .... + +100473a4 : +100473a4: 00000000 .... + +100473a8 : + ... + +100473b0 : +100473b0: 00000000 .... + +100473b4 : + ... + +100473dc : + ... + +100476f8 : +100476f8: 00000000 .... + +100476fc : +100476fc: 00000000 .... + +10047700 : +10047700: 00000000 .... + +10047704 : +10047704: 00000000 .... + +10047708 : +10047708: 00000000 .... + +1004770c : + ... + +1004771c : +1004771c: 00000000 .... + +10047720 : +10047720: 00000000 .... + +10047724 : + ... + +10047824 : + ... + +10047894 : +10047894: 00000000 .... + +10047898 : +10047898: 00000000 .... + +1004789c : +1004789c: 00000000 .... + +100478a0 : +100478a0: 00000000 .... + +100478a4 : +100478a4: 00000000 .... + +100478a8 : +100478a8: 00000000 .... + +100478ac : +100478ac: 00000000 .... + +100478b0 : +100478b0: 00000000 .... + +100478b4 : +100478b4: 00000000 .... + +100478b8 : +100478b8: 00000000 .... + +100478bc : +100478bc: 00000000 .... + +100478c0 : + ... + +100478d0 : +100478d0: 00000000 .... + +100478d4 : +100478d4: 00000000 .... + +100478d8 : +100478d8: 00000000 .... + +100478dc : +100478dc: 00000000 .... + +100478e0 : + ... + +100478f8 : + ... + +100479b8 : +100479b8: 00000000 .... + +100479bc : +100479bc: 00000000 .... + +100479c0 : +100479c0: 00000000 .... + +100479c4 : + ... + +100479f4 : + ... + +10047ad0 : + ... + +10047ad1 : +10047ad1: 00000000 ... + +10047ad4 : + ... + +10047ae8 : +10047ae8: 00000000 .... + +10047aec : +10047aec: 00000000 .... + +10047af0 : +10047af0: 00000000 .... + +10047af4 : +10047af4: 00000000 .... + +10047af8 : +10047af8: 00000000 .... + +10047afc : +10047afc: 00000000 .... + +10047b00 : +10047b00: 00000000 .... + +10047b04 : +10047b04: 00000000 .... + +10047b08 : +10047b08: 00000000 .... + +10047b0c : +10047b0c: 00000000 .... + +10047b10 : +10047b10: 00000000 .... + +10047b14 : +10047b14: 00000000 .... + +10047b18 : +10047b18: 00000000 .... + +10047b1c : + ... + +10047b30 : + ... + +10047b44 : +10047b44: 00000000 .... + +10047b48 : + ... + +10047bb8 : +10047bb8: 00000000 .... + +10047bbc : + ... + +10047bc4 : +10047bc4: 00000000 .... + +10047bc8 : +10047bc8: 00000000 .... + +10047bcc : +10047bcc: 00000000 .... + +10047bd0 : + ... + +10047ef0 : + ... + +10047f14 : +10047f14: 00000000 .... + +10047f18 : +10047f18: 00000000 .... + +10047f1c : +10047f1c: 00000000 .... + +10047f20 : +10047f20: 00000000 .... + +10047f24 : + ... + +10048074 : + ... + +1004807c : + ... + +100480f4 : +100480f4: 00000000 .... + +100480f8 : +100480f8: 00000000 .... + +100480fc : +100480fc: 00000000 .... + +10048100 : +10048100: 00000000 .... + +10048104 : +10048104: 00000000 .... + +10048108 : +10048108: 00000000 .... + +1004810c : +1004810c: 00000000 .... + +10048110 : +10048110: 00000000 .... + +10048114 : + ... + +10048134 : + ... + +10048136 : + ... + +10048138 : +10048138: 00000000 .... + +1004813c : + ... + +1004815c : + ... + +10048170 <__bss_start__>: +10048170: 00000000 .... + +10048174 <__bss_end__>: +10048174: 00000000 .... + +10048178 : +10048178: 00000000 .... + +1004817c : + ... + +100481c4 : + ... + +10048248 : + ... + +10048298 : + ... + +100482dc : + ... + +1004830c : + ... + +10048314 : +10048314: 00000000 .... + +10048318 : +10048318: 00000000 .... + +1004831c : +1004831c: 00000000 .... + +10048320 : +10048320: 00000000 .... + +10048324 : +10048324: 00000000 .... + +10048328 : + ... + +1004833c : +1004833c: 00000000 .... + +10048340 : + ... + +10048810 : + ... + +10048818 : +10048818: 00000000 .... + +1004881c : +1004881c: 00000000 .... + +10048820 : +10048820: 00000000 .... + +10048824 : +10048824: 00000000 .... + +10048828 : +10048828: 00000000 .... + +1004882c : +1004882c: 00000000 .... + +10048830 : +10048830: 00000000 .... + +10048834 : +10048834: 00000000 .... + +10048838 : + ... + +10048848 : +10048848: 00000000 .... + +1004884c : +1004884c: 00000000 .... + +10048850 : +10048850: 00000000 .... + +10048854 : +10048854: 00000000 .... + +10048858 : +10048858: 00000000 .... + +1004885c : + ... + +10048878 : + ... + +100488f8 : +100488f8: 00000000 .... + +100488fc : +100488fc: 00000000 .... + +10048900 : +10048900: 00000000 .... + +10048904 : + ... + +10048918 : + ... + +10048930 <__iar_gm_>: + ... + +10048b08 : +10048b08: 00000000 .... + +10048b0c : + ... + +10048b0e : + ... + +10048b0f : + ... + +10048b10 : + ... + +10048b11 : + ... + +10048b12 <_r>: + ... + +10048b13 <_g>: + ... + +10048b14 <_b>: + ... + +10048b15 : + ... + +10048b16 : + ... + +10048b18 : + ... + +10048b60 : + ... + +10048c8c : + ... + +1004da8c : + ... + +1004da94 : + ... + +1004da9c : +1004da9c: 00000000 .... + +1004daa0 : +1004daa0: 00000000 .... + +1004daa4 : +1004daa4: 00000000 .... + +1004daa8 : +1004daa8: 00000000 .... + +1004daac : +1004daac: 00000000 .... + +1004dab0 : +1004dab0: 00000000 .... + +1004dab4 : +1004dab4: 00000000 .... + +Disassembly of section A6 rw: + +1fff0000 : +1fff0000: 00000000 .word 0x00000000 + +1fff0004 : +1fff0004: 00000000 .... + +1fff0008 : +1fff0008: 00000000 .... + +1fff000c : +1fff000c: 00000000 .... + +1fff0010 : +1fff0010: 00000000 .... + +1fff0014 : + ... + +1fff001c : + ... + +1fff002c : + ... + +1fff0048 : + ... + +1fff007c : + ... + +1fff0090 : +1fff0090: 00000000 .... + +1fff0094 : + ... + +1fff1098 <.LANCHOR1>: + ... + +1fff10a0 : + ... + +1fff1420 : +1fff1420: 00000000 .... + +1fff1424 : + ... + +1fff145c : + ... + +1fff14c8 : +1fff14c8: 00000000 .... + +1fff14cc : +1fff14cc: 00000000 .... + +1fff14d0 : +1fff14d0: 00000000 .... + +1fff14d4 <__image2_entry_func__>: +1fff14d4: 00000000 .... + +1fff14d8 <__image2_validate_code__>: +1fff14d8: 00000000 .... + +1fff14dc <__image1_bss_start__>: +1fff14dc: 00000000 .... + +1fff14e0 <__image1_bss_end__>: +1fff14e0: 00000000 .... + +1fff14e4 : + ... + +1fff14ec : + ... + +1fff14f4 : + ... + +1fff14fc : + ... + +1fff1504 : + ... + +1fff150c : + ... + +1fff1514 : + ... + +1fff151c : + ... + +1fff1524 : + ... + +1fff152c : + ... + +1fff1534 : + ... + +1fff153c : + ... + +1fff1544 : + ... + +1fff154c : + ... + +1fff1554 : + ... + +1fff155c : + ... + +1fff1564 : + ... + +1fff156c : + ... + +1fff1574 : + ... + +1fff157c : + ... + +1fff1584 : + ... + +1fff158c : + ... + +1fff1594 <__iar_data_init_boot>: + ... + +1fff15b0 : + ... + +1fff1732 : + ... + +1fff176c : + ... + +1fff17d0 : + ... + +1fff19fa <__iar_annotation$$tailcall>: + ... + +1fff19fc <.hal.ram.text_17>: +1fff19fc: 00000000 .word 0x00000000 + +1fff1a00 <.hal.ram.text_18>: +1fff1a00: 00000000 .word 0x00000000 + +1fff1a04 <.hal.ram.text_19>: +1fff1a04: 00000000 .word 0x00000000 + +1fff1a08 <.hal.ram.text_20>: +1fff1a08: 00000000 .word 0x00000000 + +1fff1a0c <.hal.ram.text_21>: +1fff1a0c: 00000000 .word 0x00000000 + +1fff1a10 <.hal.ram.text_22>: +1fff1a10: 00000000 .word 0x00000000 + +1fff1a14 <.hal.ram.text_23>: +1fff1a14: 00000000 .word 0x00000000 + +1fff1a18 <.hal.ram.text_24>: +1fff1a18: 00000000 .word 0x00000000 + +1fff1a1c <.hal.ram.text_25>: +1fff1a1c: 00000000 .word 0x00000000 + +1fff1a20 <.hal.ram.text_26>: +1fff1a20: 00000000 .word 0x00000000 + +1fff1a24 <.hal.ram.text_27>: +1fff1a24: 00000000 .word 0x00000000 + +1fff1a28 <.hal.ram.text_28>: +1fff1a28: 00000000 .word 0x00000000 + +1fff1a2c <.hal.ram.text_29>: +1fff1a2c: 00000000 .word 0x00000000 + +1fff1a30 <.hal.ram.text_30>: +1fff1a30: 00000000 .word 0x00000000 + +1fff1a34 <.hal.ram.text_31>: +1fff1a34: 00000000 .word 0x00000000 + +1fff1a38 <.hal.ram.text_32>: +1fff1a38: 00000000 .word 0x00000000 + +1fff1a3c <.hal.ram.text_33>: +1fff1a3c: 00000000 .word 0x00000000 + +1fff1a40 <.hal.ram.text_34>: +1fff1a40: 00000000 .word 0x00000000 + +1fff1a44 <.hal.ram.text_35>: +1fff1a44: 00000000 .word 0x00000000 + +1fff1a48 <.hal.ram.text_36>: +1fff1a48: 00000000 .word 0x00000000 + +1fff1a4c <.hal.ram.text_37>: +1fff1a4c: 00000000 .word 0x00000000 + +1fff1a50 <.hal.ram.text_38>: +1fff1a50: 00000000 .word 0x00000000 + +1fff1a54 <.hal.ram.text_39>: +1fff1a54: 00000000 .word 0x00000000 + +1fff1a58 <.hal.ram.text_40>: +1fff1a58: 00000000 .word 0x00000000 + +1fff1a5c <.hal.ram.text_41>: + ... + +1fff1a68 : + ... + +1fff1a88 : + ... + +1fff1aac : + ... + +1fff1ab4 : + ... + +1fff1ad0 : + ... + +1fff1ae0 : + ... + +1fff1af8 : + ... + +1fff1b14 : + ... + +1fff1b2c : + ... + +1fff1b3c : + ... + +1fff1b50 : + ... + +1fff1b64 : + ... + +1fff1b98 : + ... + +1fff1ba8 : + ... + +1fff1bd4 : + ... + +1fff1bfc : + ... + +1fff1c04 : + ... + +1fff1c86 : + ... + +1fff1c88 : + ... + +1fff1ce8 : + ... + +1fff1cf4 : + ... + +1fff1d28 : + ... + +1fff1d6e : + ... + +1fff1d8e : + ... + +1fff1dae : +1fff1dae: 0000 movs r0, r0 + ... + +1fff1db2 : + ... + +1fff1dba : + ... + +1fff1dce : + ... + +1fff1df6 : + ... + +1fff1e50 : + ... + +1fff1ef0 : + ... + +1fff1f00 : + ... + +1fff1f84 : + ... + +1fff1f92 : + ... + +1fff1f9e : + ... + +1fff1fb4 : + ... + +1fff1fd4 : + ... + +1fff1fdc : + ... + +1fff1ffc : + ... + +1fff2020 : + ... + +1fff2030 : + ... + +1fff2064 : +1fff2064: 0000 movs r0, r0 +1fff2066: 0000 movs r0, r0 + ... + +1fff206a : + ... + +1fff209c : + ... + +1fff20cc : +1fff20cc: 0000 movs r0, r0 + ... + +1fff20d0 : + ... + +1fff20e0 : + ... + +1fff2102 : + ... + +1fff211a : + ... + +1fff2122 : + ... + +1fff2142 : + ... + +1fff2152 : + ... + +1fff215e : +1fff215e: 0000 movs r0, r0 + ... + +1fff2162 : +1fff2162: 0000 movs r0, r0 +1fff2164: 0000 movs r0, r0 + ... + +1fff2168 : + ... + +1fff2174 : + ... + +1fff217e : + ... + +1fff218c : + ... + +1fff21c8 : + ... + +1fff21d2 : + ... + +1fff21d4 : + ... + +1fff220c : +1fff220c: 0000 movs r0, r0 + ... + +1fff2210 : + ... + +1fff2218 : +1fff2218: 0000 0000 .... + +1fff221c : +1fff221c: 0000 0000 .... + +1fff2220 : +1fff2220: 0000 0000 .... + +1fff2224 : +1fff2224: 0000 0000 .... + +1fff2228 : +1fff2228: 0000 0000 .... + +1fff222c : +1fff222c: 0000 0000 .... + +1fff2230 : +1fff2230: 0000 0000 .... + +1fff2234 : +1fff2234: 0000 0000 .... + +1fff2238 : +1fff2238: 0000 0000 .... + +1fff223c : +1fff223c: 0000 0000 .... + +1fff2240 : +1fff2240: 0000 0000 .... + +1fff2244 : +1fff2244: 0000 0000 .... + +1fff2248 : +1fff2248: 0000 0000 .... + +1fff224c : +1fff224c: 0000 0000 .... + +1fff2250 : +1fff2250: 0000 0000 .... + +1fff2254 : +1fff2254: 0000 0000 .... + +1fff2258 : +1fff2258: 0000 0000 .... + +1fff225c : +1fff225c: 0000 0000 .... + +1fff2260 : +1fff2260: 0000 0000 .... + +1fff2264 : + ... + +1fff227c : + ... + +1fff22a0 : + ... + +1fff22c4 : + ... + +1fff22e0 : + ... + +1fff2314 : + ... + +1fff2348 : + ... + +1fff237c : + ... + +1fff23ac : + ... + +1fff23c8 : + ... + +1fff23f8 : + ... + +1fff5210 : + ... + +1ffff210 : +1ffff210: 0000 0000 .... diff --git a/project/realtek_ameba1_va0_example/EWARM-RELEASE/Debug/Exe/application.map b/project/realtek_ameba1_va0_example/EWARM-RELEASE/Debug/Exe/application.map new file mode 100644 index 0000000..7af9592 --- /dev/null +++ b/project/realtek_ameba1_va0_example/EWARM-RELEASE/Debug/Exe/application.map @@ -0,0 +1,12506 @@ + U HEAP$$Base + U HEAP$$Limit +00000000 T __vectors_table +00000100 T Reset_Handler +00000108 T NMI_Handler +0000010c T HardFault_Handler +00000120 T MemManage_Handler +00000124 T BusFault_Handler +00000128 T UsageFault_Handler +00000200 T HalLogUartInit +000002d8 T HalSerialPutcRtl8195a +00000308 T HalSerialGetcRtl8195a +00000328 T HalSerialGetIsrEnRegRtl8195a +00000334 T HalSerialSetIrqEnRegRtl8195a +00000340 W HalCpuClkConfig +00000354 W HalGetCpuClk +0000039c W HalRomInfo +000003b4 W HalGetRomInfo +000003c4 W HalResetVsr +00000898 W HalDelayUs +000008e0 T HalNMIHandler +00000910 T HalHardFaultHandler +00000c08 T HalMemManageHandler +00000c38 T HalBusFaultHandler +00000c68 T HalUsageFaultHandler +00000c98 t GPIOCtrl.part.0 +00000cc4 t GPIOCtrl +00000cfc T HalUart0PinCtrlRtl8195A +00000dc8 T HalUart1PinCtrlRtl8195A +00000e9c T HalUart2PinCtrlRtl8195A +00000f74 T HalSPI0PinCtrlRtl8195A +00001014 T HalSPI1PinCtrlRtl8195A +000010e4 T HalSPI2PinCtrlRtl8195A +000011b4 T HalSPI0MCSPinCtrlRtl8195A +00001274 T HalI2C0PinCtrlRtl8195A +00001380 T HalI2C1PinCtrlRtl8195A +00001458 T HalI2C2PinCtrlRtl8195A +00001528 T HalI2C3PinCtrlRtl8195A +00001638 T HalI2S0PinCtrlRtl8195A +0000176c T HalI2S1PinCtrlRtl8195A +00001844 T HalPCM0PinCtrlRtl8195A +00001948 T HalPCM1PinCtrlRtl8195A +00001a1c T HalSDIODPinCtrlRtl8195A +00001a6c T HalSDIOHPinCtrlRtl8195A +00001ab8 T HalMIIPinCtrlRtl8195A +00001b50 T HalWLLEDPinCtrlRtl8195A +00001c0c T HalWLANT0PinCtrlRtl8195A +00001c60 T HalWLANT1PinCtrlRtl8195A +00001cb4 T HalWLBTCOEXPinCtrlRtl8195A +00001d04 T HalWLBTCMDPinCtrlRtl8195A +00001d58 T HalNFCPinCtrlRtl8195A +00001da8 T HalPWM0PinCtrlRtl8195A +00001eac T HalPWM1PinCtrlRtl8195A +00001fb4 T HalPWM2PinCtrlRtl8195A +000020b0 T HalPWM3PinCtrlRtl8195A +000021b8 T HalETE0PinCtrlRtl8195A +000022c0 T HalETE1PinCtrlRtl8195A +000023c8 T HalETE2PinCtrlRtl8195A +000024d0 T HalETE3PinCtrlRtl8195A +000025d8 T HalEGTIMPinCtrlRtl8195A +00002678 T HalSPIFlashPinCtrlRtl8195A +00002724 T HalSDRPinCtrlRtl8195A +0000280c T HalJTAGPinCtrlRtl8195A +00002860 T HalTRACEPinCtrlRtl8195A +000028b8 T HalLOGUartPinCtrlRtl8195A +0000291c T HalLOGUartIRPinCtrlRtl8195A +00002980 T HalSICPinCtrlRtl8195A +000029d8 T HalEEPROMPinCtrlRtl8195A +00002a30 T HalDEBUGPinCtrlRtl8195A +00002b38 T HalPinCtrlRtl8195A +00002e5c T SpicRxCmdRtl8195A +00002ea4 T SpicWaitBusyDoneRtl8195A +00002eb4 T SpicGetFlashStatusRtl8195A +00002f54 T SpicWaitWipDoneRtl8195A +00002f6c T SpicTxCmdRtl8195A +00002fc0 T SpicSetFlashStatusRtl8195A +00003048 T SpicCmpDataForCalibrationRtl8195A +00003080 T SpicLoadInitParaFromClockRtl8195A +000030e4 T SpicInitRtl8195A +000031bc T SpicEraseFlashRtl8195A +00003278 T SpiFlashApp +000033b4 T HalPeripheralIntrHandle +00003438 T HalSysOnIntrHandle +00003484 T HalWdgIntrHandle +000034d4 T HalTimer0IntrHandle +00003524 T HalTimer1IntrHandle +00003574 T HalI2C3IntrHandle +000035c4 T HalTimer2To7IntrHandle +00003614 T HalSpi0IntrHandle +00003664 T HalGpioIntrHandle +000036b4 T HalUart0IntrHandle +00003704 T HalSpiFlashIntrHandle +00003754 T HalUsbOtgIntrHandle +000037a4 T HalSdioHostIntrHandle +000037f4 T HalI2s0OrPcm0IntrHandle +00003844 T HalI2s1OrPcm1IntrHandle +00003894 T HalWlDmaIntrHandle +000038e4 T HalWlProtocolIntrHandle +00003934 T HalCryptoIntrHandle +00003984 T HalGmacIntrHandle +000039d4 T HalGdma0Ch0IntrHandle +00003a24 T HalGdma0Ch1IntrHandle +00003a74 T HalGdma0Ch2IntrHandle +00003ac4 T HalGdma0Ch3IntrHandle +00003b14 T HalGdma0Ch4IntrHandle +00003b64 T HalGdma0Ch5IntrHandle +00003bb4 T HalGdma1Ch0IntrHandle +00003c04 T HalGdma1Ch1IntrHandle +00003c54 T HalGdma1Ch2IntrHandle +00003ca4 T HalGdma1Ch3IntrHandle +00003cf4 T HalGdma1Ch4IntrHandle +00003d44 T HalGdma1Ch5IntrHandle +00003d94 T HalSdioDeviceIntrHandle +00003de4 T VectorTableInitRtl8195A +00004018 T VectorTableInitForOSRtl8195A +00004028 T VectorIrqRegisterRtl8195A +00004090 T VectorIrqUnRegisterRtl8195A +000040f0 T VectorIrqEnRtl8195A +0000418c T VectorIrqDisRtl8195A +0000422c W _UartRxDmaIrqHandle +00004280 W HalRuartPutCRtl8195a +0000429c W HalRuartGetCRtl8195a +000042bc W HalRuartRTSCtrlRtl8195a +000042e0 W HalRuartGetDebugValueRtl8195a +000043e0 W HalRuartGetIMRRtl8195a +0000442c W HalRuartSetIMRRtl8195a +00004464 W _UartIrqHandle +00004680 W HalRuartDmaInitRtl8195a +00004844 W HalRuartIntDisableRtl8195a +00004854 W HalRuartDeInitRtl8195a +00004984 W HalRuartIntEnableRtl8195a +00004994 W _UartTxDmaIrqHandle +000049d0 W HalRuartRegIrqRtl8195a +00004a4c W HalRuartAdapterLoadDefRtl8195a +00004adc W HalRuartTxGdmaLoadDefRtl8195a +00004bc8 W HalRuartRxGdmaLoadDefRtl8195a +00004cc8 W RuartLock +00004cec W RuartUnLock +00004d08 W HalRuartIntSendRtl8195a +00004e34 W HalRuartDmaSendRtl8195a +00004f88 W HalRuartStopSendRtl8195a +0000504c W HalRuartIntRecvRtl8195a +000051ac W HalRuartDmaRecvRtl8195a +000052cc W HalRuartStopRecvRtl8195a +00005384 W RuartIsTimeout +000053b0 W HalRuartSendRtl8195a +00005598 W HalRuartRecvRtl8195a +00005750 W RuartResetRxFifoRtl8195a +00005774 W HalRuartResetRxFifoRtl8195a +00005828 W HalRuartInitRtl8195a +00005df0 W HalGdmaOnOffRtl8195a +00005e0c W HalGdmaChIsrEnAndDisRtl8195a +00005e50 W HalGdmaChEnRtl8195a +00005e6c W HalGdmaChDisRtl8195a +00005e90 W HalGdamChInitRtl8195a +00005ebc W HalGdmaChSetingRtl8195a +000060dc W HalGdmaChBlockSetingRtl8195a +00006418 W HalGdmaChIsrCleanRtl8195a +000064a0 W HalGdmaChCleanAutoSrcRtl8195a +00006500 W HalGdmaChCleanAutoDstRtl8195a +00006560 T HalEFUSEPowerSwitch8195AROM +000065f8 T HALEFUSEOneByteReadROM +00006698 T HALEFUSEOneByteWriteROM +00006744 t __rtl_memDump_v1_00.part.7 +0000681c T __rtl_memcmpb_v1_00 +00006860 T __rtl_random_v1_00 +00006880 T __rtl_align_to_be32_v1_00 +00006898 T __rtl_memsetw_v1_00 +000068ac T __rtl_memsetb_v1_00 +000068bc T __rtl_memcpyw_v1_00 +000068dc T __rtl_memcpyb_v1_00 +000068f4 T __rtl_memDump_v1_00 +00006900 T __rtl_AES_set_encrypt_key +00006c10 T __rtl_cryptoEngine_AES_set_decrypt_key +00006c94 T __rtl_cryptoEngine_set_security_mode_v1_00 +00006ea8 T __rtl_cryptoEngine_init_v1_00 +00007054 T __rtl_cryptoEngine_exit_v1_00 +000070b0 T __rtl_cryptoEngine_reset_v1_00 +000070ec T __rtl_cryptoEngine_v1_00 +00007c68 T __rtl_crypto_cipher_init_v1_00 +00007c88 T __rtl_crypto_cipher_encrypt_v1_00 +00007cac T __rtl_crypto_cipher_decrypt_v1_00 +00007cd4 W HalSsiPinmuxEnableRtl8195a +00007e44 W HalSsiEnableRtl8195a +00007ef8 W HalSsiDisableRtl8195a +00007fac W HalSsiLoadSettingRtl8195a +00008520 W HalSsiSetInterruptMaskRtl8195a +000085c8 W HalSsiGetInterruptMaskRtl8195a +0000863c W HalSsiSetSclkPolarityRtl8195a +00008714 W HalSsiSetSclkPhaseRtl8195a +000087e8 W HalSsiWriteRtl8195a +00008860 W HalSsiSetDeviceRoleRtl8195a +000088c8 W HalSsiSetRxFifoThresholdLevelRtl8195a +00008940 W HalSsiSetTxFifoThresholdLevelRtl8195a +000089b8 W HalSsiReadRtl8195a +00008a2c W HalSsiGetRxFifoLevelRtl8195a +00008aa4 W HalSsiGetTxFifoLevelRtl8195a +00008b1c W HalSsiGetStatusRtl8195a +00008b90 W HalSsiWriteableRtl8195a +00008c08 W HalSsiReadableRtl8195a +00008c80 W HalSsiBusyRtl8195a +00008cf8 W HalSsiReadInterruptRtl8195a +00008efc W HalSsiWriteInterruptRtl8195a +00009008 W HalSsiSetSlaveEnableRegisterRtl8195a +000090d8 W HalSsiGetInterruptStatusRtl8195a +0000914c W HalSsiInterruptEnableRtl8195a +00009298 W HalSsiInterruptDisableRtl8195a +000093e8 W HalSsiGetRawInterruptStatusRtl8195a +0000945c W HalSsiGetSlaveEnableRegisterRtl8195a +000094d0 W HalSsiInitRtl8195a +00009ba4 W _SsiReadInterrupt +00009db0 W _SsiWriteInterrupt +00009eb0 W _SsiIrqHandle +0000a060 W HalI2CWrite32 +0000a09c W HalI2CRead32 +0000a0dc W HalI2CDeInit8195a +0000a25c W HalI2CReceiveRtl8195a +0000a270 W HalI2CEnableRtl8195a +0000a388 W HalI2CIntrCtrl8195a +0000a3a0 W HalI2CReadRegRtl8195a +0000a3b0 W HalI2CWriteRegRtl8195a +0000a6e8 W HalI2CMassSendRtl8195a +0000a748 W HalI2CClrIntrRtl8195a +0000a760 W HalI2CClrAllIntrRtl8195a +0000aa30 W HalI2CDMACtrl8195a +0000aa60 W RtkI2CIoCtrl +0000aa64 W RtkI2CPowerCtrl +0000ac64 W I2CIsTimeout +0000b434 W I2CTXGDMAISRHandle +0000b4c0 W I2CRXGDMAISRHandle +0000b54c W RtkI2CIrqInit +0000b610 W RtkI2CIrqDeInit +0000b674 W RtkI2CPinMuxInit +0000b7c8 W RtkI2CPinMuxDeInit +0000b954 W RtkI2CDMAInit +0000bc94 W RtkI2CInit +0000bdac W RtkI2CDMADeInit +0000be4c W RtkI2CDeInit +0000bee4 W RtkI2CSendUserAddr +0000ce50 W RtkI2CLoadDefault +0000cf20 W RtkSalI2COpInit +0000cf64 W HalI2SWrite32 +0000cf84 W HalI2SRead32 +0000cfa8 W HalI2SDeInitRtl8195a +0000cfc8 W HalI2STxRtl8195a +0000d010 W HalI2SRxRtl8195a +0000d05c W HalI2SEnableRtl8195a +0000d0b0 W HalI2SIntrCtrlRtl8195a +0000d0d0 W HalI2SReadRegRtl8195a +0000d0dc W HalI2SClrIntrRtl8195a +0000d0fc W HalI2SClrAllIntrRtl8195a +0000d11c W HalI2SInitRtl8195a +0000d2e4 W GPIO_GetIPPinName_8195a +0000d330 W GPIO_GetChipPinName_8195a +0000d39c W GPIO_PullCtrl_8195a +0000d420 W GPIO_FuncOn_8195a +0000d480 W GPIO_FuncOff_8195a +0000d4e8 W GPIO_Int_Mask_8195a +0000d510 W GPIO_Int_SetType_8195a +0000d5fc W HAL_GPIO_IrqHandler_8195a +0000d644 W HAL_GPIO_MbedIrqHandler_8195a +0000d6a0 W HAL_GPIO_UserIrqHandler_8195a +0000d6cc W HAL_GPIO_IntCtrl_8195a +0000d804 W HAL_GPIO_Init_8195a +0000dac0 W HAL_GPIO_DeInit_8195a +0000dbd0 W HAL_GPIO_ReadPin_8195a +0000dc90 W HAL_GPIO_WritePin_8195a +0000ddac W HAL_GPIO_RegIrq_8195a +0000ddf4 W HAL_GPIO_UnRegIrq_8195a +0000de14 W HAL_GPIO_UserRegIrq_8195a +0000def8 W HAL_GPIO_UserUnRegIrq_8195a +0000dfc0 W HAL_GPIO_MaskIrq_8195a +0000e060 W HAL_GPIO_UnMaskIrq_8195a +0000e100 W HAL_GPIO_IntDebounce_8195a +0000e1c0 W HAL_GPIO_GetIPPinName_8195a +0000e1c8 W HAL_GPIO_PullCtrl_8195a +0000e258 T DumpForOneBytes +0000e418 T CmdRomHelp +0000e490 T CmdWriteWord +0000e504 T CmdDumpHelfWord +0000e5f0 T CmdDumpWord +0000e6f4 T CmdDumpByte +0000e750 T CmdSpiFlashTool +0000e7a8 T GetRomCmdNum +0000e7ac T CmdWriteByte +0000e7ec T Isspace +0000e800 T Strtoul +0000e8b0 T ArrayInitialize +0000e8c8 T GetArgc +0000e8f8 T GetArgv +0000e95c T UartLogCmdExecute +0000e9fc T UartLogShowBackSpace +0000ea38 T UartLogRecallOldCmd +0000ea70 T UartLogHistoryCmd +0000eadc T UartLogCmdChk +0000ebf4 T UartLogIrqHandle +0000ecc4 T RtlConsolInit +0000ed48 T RtlConsolTaskRom +0000ed78 T RtlExitConsol +0000edcc T RtlConsolRom +0000ee0c W HalTimerOpInit +0000ee58 T HalTimerIrq2To7Handle +0000ef08 T HalGetTimerIdRtl8195a +0000ef3c T HalTimerInitRtl8195a +0000f068 T HalTimerDisRtl8195a +0000f088 T HalTimerEnRtl8195a +0000f0a8 T HalTimerReadCountRtl8195a +0000f0bc T HalTimerIrqClearRtl8195a +0000f0d0 T HalTimerDumpRegRtl8195a +0000f128 T VSprintf +0000f39c T DiagPrintf +0000f3b8 T DiagSPrintf +0000f3d0 T DiagSnPrintf +0000f3ec T prvDiagPrintf +0000f40c T prvDiagSPrintf +0000f428 T _memcmp +0000f464 T _memcpy +0000f510 W _memset +0000f584 T Rand +0000f60c T _strncpy +0000f628 T _strcpy +0000f638 T prvStrCpy +0000f650 T _strlen +0000f668 T _strnlen +0000f698 T prvStrLen +0000f6b0 T _strcmp +0000f6d0 T _strncmp +0000f718 T prvStrCmp +0000f748 T StrUpr +0000f768 T prvAtoi +0000f7bc T prvStrStr +0000f7d4 T _strsep +0000f814 T skip_spaces +0000f830 T skip_atoi +0000f868 T _parse_integer_fixup_radix +0000f8bc T _parse_integer +0000f914 T simple_strtoull +0000f944 T simple_strtoll +0000f964 T simple_strtoul +0000f96c T simple_strtol +0000f984 T _vsscanf +0000ff70 T _sscanf +0000ff90 T div_u64 +0000ff98 T div_s64 +0000ffa0 T div_u64_rem +0000ffb0 T div_s64_rem +0000ffc0 T _strpbrk +0000ffec T _strchr +00010004 T aes_set_key +000103d0 T aes_encrypt +000114a4 T aes_decrypt +000125c8 T AES_WRAP +00012700 T AES_UnWRAP +00012860 T crc32_get +00012894 T arc4_byte +000128bc T rt_arc4_init +00012900 T rt_arc4_crypt +0001292c t md5_encode +00012960 t md5_transform +000131c0 T rt_md5_init +000131f4 T rt_md5_append +0001327c T rt_md5_final +000132d4 T rt_md5_hmac +00013418 t key_char2num +00013448 T rtw_get_bit_value_from_ieee_value +00013474 T rtw_is_cckrates_included +000134b4 T rtw_is_cckratesonly_included +000134dc T rtw_check_network_type +0001350c T rtw_set_fixed_ie +0001352c T rtw_set_ie +0001355c T rtw_get_ie +00013590 T rtw_set_supported_rate +00013610 T rtw_get_rateset_len +0001362c T rtw_get_wpa_ie +000136c8 T rtw_get_wpa2_ie +00013700 T rtw_get_wpa_cipher_suite +00013768 T rtw_get_wpa2_cipher_suite +000137d0 T rtw_parse_wpa_ie +000138ac T rtw_parse_wpa2_ie +00013964 T rtw_get_sec_ie +00013a14 T rtw_get_wps_ie +00013a98 T rtw_get_wps_attr +00013b48 T rtw_get_wps_attr_content +00013b90 T rtw_ieee802_11_parse_elems +00013d9c T str_2char2num +00013db8 T key_2char2num +00013dd0 T convert_ip_addr +00013e04 t F.constprop.0 +00013e9c T rom_psk_PasswordHash +00013ed4 T rom_psk_CalcGTK +00013f68 T rom_psk_CalcPTK +0001406c t aes1_next_key +00014110 t aes1_mix_column +00014294 T wep_80211_encrypt +000142f4 T wep_80211_decrypt +00014388 T tkip_micappendbyte +000143d8 T rtw_secmicsetkey +00014418 T rtw_secmicappend +00014434 T rtw_secgetmic +0001449c T rtw_seccalctkipmic +000145a4 T tkip_phase1 +00014724 T tkip_phase2 +00014940 T tkip_80211_encrypt +000149d4 T tkip_80211_decrypt +00014a8c T aes1_encrypt +00014c64 T aesccmp_construct_mic_iv +00014ccc T aesccmp_construct_mic_header1 +00014d20 T aesccmp_construct_mic_header2 +00014db4 T aesccmp_construct_ctr_preload +00014e28 T aes_80211_encrypt +000151ac T aes_80211_decrypt +000155b8 T _sha1_process_message_block +00015748 T _sha1_pad_message +000157e4 T rt_sha1_init +00015830 T rt_sha1_update +000158a8 T rt_sha1_finish +00015908 T rt_hmac_sha1 +00015a64 T rom_aes_128_cbc_encrypt +00015ae0 T rom_aes_128_cbc_decrypt +00015b5c T rom_rijndaelKeySetupEnc +00015c38 T rom_aes_decrypt_init +00015d14 T rom_aes_internal_decrypt +00016070 T rom_aes_decrypt_deinit +00016084 T rom_aes_encrypt_init +0001609c T rom_aes_internal_encrypt +00016450 T rom_aes_encrypt_deinit +00016464 t mp_init +0001649c t mp_clear +000164d8 t mp_unsigned_bin_size +0001652c t mp_exch +00016550 t mp_init_size +000165a0 t mp_cmp_mag.isra.1 +00016604 t mp_cmp +00016640 t mp_rshd +000166ac t s_mp_sqr.isra.5 +000167d0 t mp_grow.isra.7 +00016824 t mp_copy +000168a0 t mp_lshd +0001690c t s_mp_add +00016a24 t mp_2expt +00016a84 t mp_mod_2d +00016b64 t mp_div_2d +00016ccc t mp_mul_2d +00016df0 t s_mp_sub.isra.10 +00016ee4 t mp_add +00016f4c t mp_sub +00016fb4 t mp_div.part.11 +00017160 t fast_s_mp_mul_digs.isra.12 +000172fc t s_mp_mul_digs +00017428 t mp_mul +00017450 t mp_reduce_2k_l +00017508 t mp_reduce +00017734 t s_mp_exptmod.constprop.13 +00017b34 T bignum_init +00017b60 T bignum_deinit +00017b80 T bignum_get_unsigned_bin_len +00017b84 T bignum_get_unsigned_bin +00017c20 T bignum_set_unsigned_bin +00017cd0 T bignum_cmp +00017cd4 T bignum_cmp_d +00017cfc T bignum_add +00017d0c T bignum_sub +00017d1c T bignum_mul +00017d2c T bignum_exptmod +00017d50 T WPS_realloc +00017d98 T os_zalloc +00017dc0 T rom_hmac_sha256_vector +00017ebc T rom_hmac_sha256 +00017ed8 t sha256_compress +00018008 T rom_sha256_vector +00018220 T phy_CalculateBitShift +00018238 T PHY_SetBBReg_8195A +00018278 T PHY_QueryBBReg_8195A +0001829c T ROM_odm_QueryRxPwrPercentage +000182bc T ROM_odm_EVMdbToPercentage +000182e4 T ROM_odm_SignalScaleMapping_8195A +000183cc T ROM_odm_FalseAlarmCounterStatistics +00018720 T ROM_odm_SetEDCCAThreshold +00018748 T ROM_odm_SetTRxMux +00018770 T ROM_odm_SetCrystalCap +000187d4 T ROM_odm_GetDefaultCrytaltalCap +000187e8 T ROM_ODM_CfoTrackingReset +00018810 T ROM_odm_CfoTrackingFlow +00018a10 t fsum +00018a44 t fproduct +00018df4 t freduce_degree +000190e4 t freduce_coefficients +0001922c t swap_conditional +0001925c t fsquare +00019634 t fmul +0001965c T curve25519_donna +0001a390 T aes_test_alignment_detection +0001a3ec T aes_mode_reset +0001a3f8 T aes_ecb_encrypt +0001a430 T aes_ecb_decrypt +0001a468 T aes_cbc_encrypt +0001a578 T aes_cbc_decrypt +0001a700 T aes_cfb_encrypt +0001a9e4 T aes_cfb_decrypt +0001acc8 T aes_ofb_crypt +0001af7c T aes_ctr_crypt +0001b288 T aes_encrypt_key128 +0001b2a4 T aes_encrypt_key192 +0001b2c0 T aes_encrypt_key256 +0001b2e0 T aes_encrypt_key +0001b350 T aes_decrypt_key128 +0001b36c T aes_decrypt_key192 +0001b388 T aes_decrypt_key256 +0001b3a8 T aes_decrypt_key +0001b418 T aes_init +0001b41c T CRYPTO_chacha_20 +0001b890 t poly1305_update +0001bc24 T CRYPTO_poly1305_init +0001bd08 T CRYPTO_poly1305_update +0001bd8c T CRYPTO_poly1305_finish +0001bfc0 t sha512_process +0001cdec t rom_sha512_update.part.0 +0001ceb4 T rom_sha512_starts +0001d008 T rom_sha512_update +0001d010 T rom_sha512_finish +0001d260 T rom_sha512 +0001d298 T rom_sha512_hmac_starts +0001d35c T rom_sha512_hmac_update +0001d364 T rom_sha512_hmac_finish +0001d3b4 T rom_sha512_hmac_reset +0001d3d0 T rom_sha512_hmac +0001d40c T rom_sha512_hkdf +0001d500 T rom_ed25519_gen_keypair +0001d504 T rom_ed25519_gen_signature +0001d51c T rom_ed25519_verify_signature +0001d520 T rom_ed25519_crypto_sign_seed_keypair +0001d578 T rom_ed25519_crypto_sign_detached +0001d654 T rom_ed25519_crypto_sign_verify_detached +0001d918 t fe_add +0001d988 t fe_cmov +0001da58 t fe_mul +0001e2bc t fe_neg +0001e310 t fe_sq +0001e968 t fe_invert +0001eab0 t fe_sub +0001eb2c t fe_tobytes +0001ecf0 t ge_add +0001ed88 t slide +0001ee3c t ge_madd +0001eec8 t ge_p1p1_to_p2 +0001eefc t ge_p1p1_to_p3 +0001ef40 t ge_p2_dbl +0001f5b0 t ge_p3_to_cached +0001f624 t cmov +0001f650 t ge_select +0001f7e4 t crypto_verify_32.constprop.0 +0001f86c T rom_ed25519_ge_double_scalarmult_vartime +0001fc34 T rom_ed25519_ge_frombytes_negate_vartime +000207d4 T rom_ed25519_ge_p3_tobytes +00020820 T rom_ed25519_ge_scalarmult_base +000209e0 T rom_ed25519_ge_tobytes +00020a2c T rom_ed25519_sc_muladd +0002603c T rom_ed25519_sc_reduce +00028a4c T __rtl_memchr_v1_00 +00028ae0 T __rtl_memcmp_v1_00 +00028b48 T __rtl_memcpy_v1_00 +00028bec T __rtl_memmove_v1_00 +00028cb4 T __rtl_memset_v1_00 +00028d48 T __rtl_strcat_v1_00 +00028d90 T __rtl_strchr_v1_00 +00028e54 T __rtl_strcmp_v1_00 +00028ec8 T __rtl_strcpy_v1_00 +00028f14 T __rtl_strlen_v1_00 +00028f68 T __rtl_strncat_v1_00 +00028fc4 T __rtl_strncmp_v1_00 +0002907c T __rtl_strncpy_v1_00 +000290e4 t __rtl_critical_factorization_v1_00 +0002919c t __rtl_two_way_long_needle_v1_00 +000293cc T __rtl_strstr_v1_00 +0002960c T __rtl_strsep_v1_00 +00029618 T __rtl_strtok_v1_00 +0002962c T __rtl__strtok_r_v1_00 +00029690 T __rtl_strtok_r_v1_00 +00029698 T __rtl_close_v1_00 +000296ac T __rtl_fstat_v1_00 +000296c0 T __rtl_isatty_v1_00 +000296d4 T __rtl_lseek_v1_00 +000296e8 T __rtl_open_v1_00 +000296fc T __rtl_read_v1_00 +00029710 T __rtl_write_v1_00 +00029724 T __rtl_sbrk_v1_00 +00029738 t __rtl_div64_32 +000297bc T __rtl_ltoa_v1_00 +00029854 T __rtl_ultoa_v1_00 +000298c4 T __rtl_dtoi_v1_00 +00029944 T __rtl_dtoi64_v1_00 +000299dc T __rtl_dtoui_v1_00 +000299e4 T __rtl_ftol_v1_00 +00029a50 T __rtl_itof_v1_00 +00029ae8 T __rtl_itod_v1_00 +00029b78 T __rtl_i64tod_v1_00 +00029c54 T __rtl_uitod_v1_00 +00029d2c T __rtl_ftod_v1_00 +00029de8 T __rtl_dtof_v1_00 +00029e88 T __rtl_uitof_v1_00 +00029f64 T __rtl_fadd_v1_00 +0002a260 T __rtl_fsub_v1_00 +0002a558 T __rtl_fmul_v1_00 +0002a694 T __rtl_fdiv_v1_00 +0002a824 T __rtl_dadd_v1_00 +0002aed8 T __rtl_dsub_v1_00 +0002b554 T __rtl_dmul_v1_00 +0002b8ac T __rtl_ddiv_v1_00 +0002be4c T __rtl_dcmpeq_v1_00 +0002bebc T __rtl_dcmplt_v1_00 +0002bf50 T __rtl_dcmpgt_v1_00 +0002c048 T __rtl_dcmple_v1_00 +0002c138 T __rtl_fcmplt_v1_00 +0002c194 T __rtl_fcmpgt_v1_00 +0002c228 T __rtl_cos_f32_v1_00 +0002c434 T __rtl_sin_f32_v1_00 +0002c638 T __rtl_fabs_v1_00 +0002c640 T __rtl_fabsf_v1_00 +0002c648 t quorem +0002c77c T __rtl_dtoa_r_v1_00 +0002d7d0 T __rom_mallocr_init_v1_00 +0002d840 T __rtl_free_r_v1_00 +0002da30 T __rtl_malloc_r_v1_00 +0002df54 T __rtl_realloc_r_v1_00 +0002e330 T __rtl_memalign_r_v1_00 +0002e420 T __rtl_valloc_r_v1_00 +0002e42c T __rtl_pvalloc_r_v1_00 +0002e440 T __rtl_calloc_r_v1_00 +0002e4a8 T __rtl_cfree_r_v1_00 +0002e4b8 t __rtl_lo0bits +0002e514 T __rtl_Balloc_v1_00 +0002e570 T __rtl_Bfree_v1_00 +0002e584 T __rtl_i2b_v1_00 +0002e598 T __rtl_multadd_v1_00 +0002e628 T __rtl_mult_v1_00 +0002e768 T __rtl_pow5mult_v1_00 +0002e808 T __rtl_hi0bits_v1_00 +0002e844 T __rtl_d2b_v1_00 +0002e900 T __rtl_lshift_v1_00 +0002e9bc T __rtl_cmp_v1_00 +0002ea00 T __rtl_diff_v1_00 +0002eae8 T __rtl_sread_v1_00 +0002eb38 T __rtl_seofread_v1_00 +0002eb3c T __rtl_swrite_v1_00 +0002ebc0 T __rtl_sseek_v1_00 +0002ec10 T __rtl_sclose_v1_00 +0002ec40 T __rtl_sbrk_r_v1_00 +0002ec6c t __rtl_sflush_r_v1_00 +0002edc0 t __rtl_sinit.part.3 +0002eec4 t __rtl_fclose_r +0002ef50 t __rtl_cleanup_r +0002ef8c T __rtl_fflush_r_v1_00 +0002efb8 t __rtl_swsetup_r +0002f1b0 t __rtl_swbuf_r_v1_00 +0002f254 t __rtl_sprint_r_v1_00.part.9 +0002f660 T __rtl_vfprintf_r_v1_00 +00030c14 T __rtl_fpclassifyd +00030c68 T CpkClkTbl +00030c68 t .LANCHOR0 +00030c80 T ROM_IMG1_VALID_PATTEN +00030c88 T SpicCalibrationPattern +00030c88 t .LANCHOR0 +00030c98 T SpicInitCPUCLK +00030ca8 T BAUDRATE +00030ca8 t .LANCHOR0 +00030d1c T OVSR +00030d90 T DIV +00030e04 T OVSR_ADJ +00030e78 T __AES_rcon +00030ea0 T __AES_Te4 +000312a0 T I2CDmaChNo +000312a0 t .LANCHOR0 +000312b4 t .LANCHOR0 +000312b4 t _GPIO_PinMap_Chip2IP_8195a +0003136c t _GPIO_PinMap_PullCtrl_8195a +00031594 t _GPIO_SWPORT_DDR_TBL +00031598 t _GPIO_EXT_PORT_TBL +0003159c t _GPIO_SWPORT_DR_TBL +000315a0 t .LANCHOR0 +000315a0 t __countLeadingZerosHigh +000316a0 T UartLogRomCmdTable +000316a0 t .LANCHOR0 +00031700 T _HalRuartOp +00031760 T _HalGdmaOp +00031788 t .LANCHOR0 +00031788 t RCON +000317b0 t FSb +00031bb0 t KT3 +00031fb0 t KT0 +000323b0 t KT1 +000327b0 t KT2 +00032880 t .LANCHOR1 +00032bb0 t FT0 +00032fb0 t FT3 +000333b0 t FT1 +000337b0 t FT2 +00033978 t .LANCHOR2 +00033bb0 t RT0 +00033fb0 t RT3 +000343b0 t RT1 +000347b0 t RT2 +00034a70 t .LANCHOR3 +00034bb0 t RSb +00034fb0 t .LANCHOR0 +00034fb0 t crc32_table +000353b0 t .LANCHOR0 +000353b0 t PADDING +000353f0 t .LANCHOR0 +000353f0 t dot11_rate_table +00035400 t WIFI_CCKRATES +00035404 t WIFI_OFDMRATES +0003540c T RTW_WPA_OUI_TYPE +00035410 T WPA_CIPHER_SUITE_NONE +00035414 T WPA_CIPHER_SUITE_WEP40 +00035418 T WPA_CIPHER_SUITE_TKIP +0003541c T WPA_CIPHER_SUITE_CCMP +00035420 T WPA_CIPHER_SUITE_WEP104 +00035424 T RSN_CIPHER_SUITE_NONE +00035428 T RSN_CIPHER_SUITE_WEP40 +0003542c T RSN_CIPHER_SUITE_TKIP +00035430 T RSN_CIPHER_SUITE_CCMP +00035434 T RSN_CIPHER_SUITE_WEP104 +00035438 t WPA_SUITE_1X +0003543c t WPA2_SUITE_1X +00035440 t wps_oui +00035444 T RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X +00035448 T RSN_AUTH_KEY_MGMT_UNSPEC_802_1X +0003544c T RSN_VERSION_BSD +00035450 t .LANCHOR0 +00035450 t gmk_expansion_const +00035464 t pmk_expansion_const +0003547c t .LANCHOR0 +0003547c t aes1_sbox_table +0003557c t rcon_table +00035588 t TKIP_Sbox1 +00035988 T rom_wps_Te0 +00035988 t .LANCHOR0 +00035d88 T rom_wps_rcons +00035d94 T rom_wps_Td4s +00035e94 T rom_wps_Td0 +00036294 t .LANCHOR0 +00036294 t KK +00036394 t .LANCHOR0 +00036394 t kCurve25519BasePoint +000363b8 t K +00036638 t sha512_padding +000366b8 t .LANCHOR0 +000366b8 t d2 +000366e0 t base +0003dee0 t Bi +0003e2a0 t d +0003e2c8 t sqrtm1 +0003e2f0 t .LANCHOR0 +0003e2f0 t cosTable +0003e6fc t sinTable +0003eb08 t .LANCHOR0 +0003eb08 t tens +0003ebd0 t bigtens +0003ebf8 t .LANCHOR0 +0003ebf8 t p05 +0003ec04 t .LANCHOR0 +0003ec04 t blanks +0003ec14 t zeroes +0003ec24 t .LC0 +0003ec64 t .LC1 +0003ec7c t .LC2 +0003ecd0 t .LC3 +0003ed0c t .LC4 +0003ed18 t .LC5 +0003ed38 t .LC6 +0003ed48 t .LC7 +0003ed70 t .LC8 +0003ed94 t .LC9 +0003edd0 t .LC10 +0003edfc t .LC11 +0003ee1c t .LC12 +0003ee3c t .LC13 +0003ee5c t .LC14 +0003ee7c t .LC15 +0003eea4 t .LC16 +0003eec0 t .LC17 +0003eedc t .LC18 +0003eef8 t .LC19 +0003ef14 t .LC20 +0003ef30 t .LC21 +0003ef4c t .LC22 +0003ef68 t .LC23 +0003ef84 t .LC24 +0003efa4 t .LC25 +0003efc4 t .LC26 +0003efe4 t .LC27 +0003f004 t .LC28 +0003f024 t .LC29 +0003f044 t .LC30 +0003f064 t .LC31 +0003f08c t .LC32 +0003f0b8 t .LC33 +0003f0e4 t .LC34 +0003f110 t .LC35 +0003f138 t .LC36 +0003f160 t .LC0 +0003f178 t .LC1 +0003f190 t .LC2 +0003f1a8 t .LC3 +0003f1b8 t .LC4 +0003f1d8 t .LC5 +0003f1f4 t .LC6 +0003f210 t .LC7 +0003f230 t .LC8 +0003f244 t .LC9 +0003f258 t .LC0 +0003f27c t .LC1 +0003f2ac t .LC2 +0003f2dc t .LC0 +0003f300 t .LC1 +0003f328 t .LC2 +0003f34c t .LC3 +0003f37c t .LC4 +0003f3b0 t .LC5 +0003f3d4 t .LC6 +0003f400 t .LC7 +0003f42c t .LC8 +0003f45c t .LC9 +0003f484 t .LC10 +0003f4ac t .LC11 +0003f4d0 t .LC12 +0003f4f0 t .LC13 +0003f528 t .LC14 +0003f56c t .LC15 +0003f5ac t .LC16 +0003f5e4 t .LC17 +0003f628 t .LC18 +0003f668 t .LC19 +0003f690 t .LC20 +0003f6d0 t .LC21 +0003f708 t .LC22 +0003f74c t .LC23 +0003f78c t .LC24 +0003f7b0 t .LC25 +0003f7f4 t .LC26 +0003f834 t .LC27 +0003f874 t .LC28 +0003f8b4 t .LC29 +0003f8e8 t .LC30 +0003f928 t .LC31 +0003f964 t .LC32 +0003f99c t .LC33 +0003f9d8 t .LC34 +0003fa0c t .LC35 +0003fa4c t .LC36 +0003fa88 t .LC37 +0003fac4 t .LC38 +0003fb08 t .LC39 +0003fb4c t .LC40 +0003fb80 t .LC41 +0003fbc0 t .LC42 +0003fbf8 t .LC43 +0003fc38 t .LC44 +0003fc64 t .LC45 +0003fc90 t .LC46 +0003fcc4 t .LC47 +0003fd00 t .LC48 +0003fd34 t .LC49 +0003fd64 t .LC50 +0003fd94 t .LC51 +0003fdc0 t .LC52 +0003fdec t .LC53 +0003fe1c t .LC54 +0003fe54 t .LC55 +0003fe78 t .LC56 +0003fe9c t .LC57 +0003fed4 t .LC58 +0003ff00 t .LC59 +0003ff28 t .LC60 +0003ff50 t .LC0 +0003ff84 t .LC1 +0003ffa4 t .LC2 +0003ffdc t .LC3 +0003fff8 t .LC4 +00040014 t .LC5 +00040058 t .LC0 +0004005c t .LC1 +00040060 t .LC2 +0004006c t .LC3 +00040070 t .LC4 +00040078 t .LC5 +0004007c t .LC6 +000400b0 t .LC7 +000400c8 t .LC8 +000400f4 t .LC9 +0004010c t .LC10 +00040114 t .LC11 +00040120 t .LC12 +00040128 t .LC13 +00040160 t .LC14 +00040168 t .LC15 +00040170 t .LC16 +0004017c t .LC17 +0004018c t .LC18 +000401c8 t .LC19 +00040218 t .LC20 +00040254 t .LC21 +00040284 t .LC22 +00040290 t .LC0 +000402c8 t .LC1 +000402fc t .LC2 +0004031c t .LC3 +00040350 t .LC4 +00040380 t .LC5 +000403b8 t .LC6 +000403f0 t .LC7 +00040424 t .LC8 +0004045c t .LC9 +0004048c t .LC10 +000404b4 t .LC11 +000404dc t .LC12 +00040504 t .LC13 +0004052c t .LC14 +00040554 t .LC15 +0004057c t .LC16 +000405a4 t .LC17 +000405cc t .LC18 +000405f4 t .LC19 +0004061c t .LC20 +00040644 t .LC21 +0004066c t .LC22 +00040694 t .LC23 +000406bc t .LC24 +000406e4 t .LC25 +0004070c t .LC26 +00040734 t .LC27 +0004075c t .LC28 +00040784 t .LC29 +000407ac t .LC30 +000407d4 t .LC31 +000407fc t .LC32 +00040824 t .LC33 +0004084c t .LC34 +00040874 t .LC35 +0004089c t .LC36 +000408c4 t .LC37 +000408f0 t .LC38 +0004091c t .LC39 +00040948 t .LC40 +00040984 t .LC41 +000409b0 t .LC42 +000409e4 t .LC43 +00040a20 t .LC44 +00040a44 t .LC45 +00040a80 t .LC46 +00040ab8 t .LC47 +00040af0 t .LC48 +00040b28 t .LC49 +00040b5c t .LC50 +00040b8c t .LC51 +00040bb0 t .LC52 +00040be8 t .LC53 +00040c2c t .LC54 +00040c64 t .LC55 +00040ca8 t .LC56 +00040ce0 t .LC57 +00040d10 t .LC58 +00040d30 t .LC59 +00040d68 t .LC60 +00040d94 t .LC61 +00040dcc t .LC62 +00040df8 t .LC63 +00040e2c t .LC64 +00040e50 t .LC65 +00040e84 t .LC66 +00040ea8 t .LC67 +00040edc t .LC68 +00040f00 t .LC69 +00040f30 t .LC70 +00040f50 t .LC71 +00040f88 t .LC72 +00040fa8 t .LC73 +00040fdc t .LC74 +00041024 t .LC75 +00041068 t .LC76 +000410a0 t .LC77 +000410e4 t .LC78 +0004111c t .LC79 +00041150 t .LC80 +00041190 t .LC81 +000411b4 t .LC82 +000411f0 t .LC83 +0004121c t .LC84 +00041258 t .LC85 +00041280 t .LC86 +000412b4 t .LC87 +000412e4 t .LC88 +00041310 t .LC89 +0004133c t .LC90 +0004136c t .LC91 +000413a8 t .LC92 +000413e8 t .LC93 +00041418 t .LC94 +00041458 t .LC95 +0004147c t .LC96 +000414ac t .LC97 +000414e8 t .LC98 +00041524 t .LC99 +0004155c t .LC100 +00041598 t .LC101 +000415d0 t .LC102 +0004160c t .LC103 +00041644 t .LC104 +0004167c t .LC105 +000416b0 t .LC106 +000416ec t .LC107 +00041720 t .LC108 +0004175c t .LC109 +00041790 t .LC110 +000417cc t .LC111 +00041804 t .LC112 +00041840 t .LC113 +00041878 t .LC114 +000418b0 t .LC115 +000418e4 t .LC116 +00041910 t .LC117 +0004194c t .LC118 +00041970 t .LC119 +000419a0 t .LC120 +000419c4 t .LC121 +000419e4 t .LC122 +00041a18 t .LC123 +00041a48 t .LC124 +00041a74 t .LC125 +00041aa0 t .LC126 +00041ae0 t .LC127 +00041b20 t .LC128 +00041b60 t .LC129 +00041ba0 t .LC130 +00041bdc t .LC131 +00041c18 t .LC0 +00041c40 t .LC1 +00041c60 t .LC2 +00041c7c t .LC3 +00041ca4 t .LC4 +00041ccc t .LC5 +00041cf4 t .LC6 +00041d1c t .LC7 +00041d34 t .LC8 +00041d4c t .LC9 +00041d74 t .LC10 +00041d9c t .LC11 +00041dc8 t .LC12 +00041df4 t .LC13 +00041e20 t .LC14 +00041e4c t .LC15 +00041e80 t .LC16 +00041eb8 t .LC17 +00041ef0 t .LC0 +00041f18 t .LC1 +00041f40 t .LC2 +00041f68 t .LC3 +00041f90 t .LC4 +00041fb8 t .LC5 +00041fe4 t .LC6 +0004200c t .LC7 +00042038 t .LC8 +00042060 t .LC9 +0004208c t .LC10 +000420b4 t .LC11 +000420e0 t .LC12 +00042108 t .LC13 +00042128 t .LC14 +0004214c t .LC15 +0004216c t .LC16 +0004218c t .LC17 +000421ac t .LC18 +000421cc t .LC19 +000421f4 t .LC20 +00042224 t .LC21 +00042250 t .LC22 +00042274 t .LC23 +000422a0 t .LC24 +000422c8 t .LC25 +000422e8 t .LC26 +00042310 t .LC27 +00042330 t .LC28 +00042350 t .LC29 +00042370 t .LC30 +00042390 t .LC31 +000423b0 t .LC32 +000423d4 t .LC33 +000423f8 t .LC34 +00042418 t .LC35 +00042450 t .LC36 +00042480 t .LC37 +000424a0 t .LC38 +000424bc t .LC39 +000424d8 t .LC40 +000424f8 t .LC41 +00042518 t .LC42 +00042534 t .LC43 +00042550 t .LC44 +00042580 t .LC45 +000425b4 t .LC46 +000425e0 t .LC47 +0004260c t .LC48 +00042638 t .LC49 +00042664 t .LC50 +00042690 t .LC51 +000426bc t .LC52 +000426e8 t .LC53 +00042714 t .LC54 +00042740 t .LC55 +0004276c t .LC56 +00042798 t .LC57 +000427c4 t .LC58 +000427f0 t .LC59 +0004281c t .LC60 +00042848 t .LC61 +00042874 t .LC62 +000428a0 t .LC63 +000428cc t .LC64 +000428f8 t .LC65 +00042928 t .LC0 +0004296c t .LC1 +000429b8 t .LC2 +000429f0 t .LC3 +00042a10 t .LC4 +00042a34 t .LC5 +00042a64 t .LC6 +00042aa4 t .LC7 +00042ad0 t .LC8 +00042b1c t .LC9 +00042b64 t .LC10 +00042b90 t .LC11 +00042bcc t .LC12 +00042c04 t .LC13 +00042c34 t .LC14 +00042c6c t .LC15 +00042cac t .LC16 +00042cdc t .LC17 +00042d10 t .LC18 +00042d34 t .LC19 +00042d84 t .LC20 +00042db8 t .LC21 +00042e08 t .LC22 +00042e40 t .LC23 +00042e8c t .LC24 +00042edc t .LC25 +00042f2c t .LC26 +00042f60 t .LC0 +00042fa0 t .LC1 +00042fa8 t .LC2 +00042fb0 t .LC3 +00042fb4 t .LC4 +00042fbc t .LC5 +00042fc0 t .LC6 +00042fc4 t .LC7 +00042fc8 t .LC0 +00042fd8 t .LC1 +00042ff0 t .LC2 +00043004 t .LC3 +00043040 t .LC4 +00043078 t .LC5 +000430a0 t .LC6 +000430cc t .LC0 +000430e0 t .LC0 +0004311c t .LC1 +00043124 t .LC2 +00043160 t .LC3 +0004317c t .LC4 +00043198 t .LC5 +000431d4 t .LC6 +000431e4 t .LC7 +000431f0 t .LC8 +00043464 t .LC0 +00043468 t .LC1 +0004346c t .LC2 +00043470 t .LC3 +00043490 t .LC4 +0004349c t .LC0 +000434bc t .LC0 +000434f4 t .LC1 +0004352c t .LC2 +00043564 t .LC3 +00043594 t .LC4 +000435b4 t .LC5 +000435d4 t .LC6 +000435f4 t .LC7 +00043614 t .LC8 +00043634 t .LC9 +00043658 t .LC10 +00043690 t .LC11 +000436d0 t .LC12 +00043704 t .LC13 +0004373c t .LC14 +00043778 t .LC15 +000437c8 t .LC0 +000437d4 t .LC1 +000437d8 t .LC2 +000437e0 t .LC0 +000437e4 t .LC1 +000437e8 t .LC2 +000437ec t .LC3 +000437f0 t .LC4 +00043804 t .LC5 +00043818 t .LC6 +00043820 t .LC7 +00043824 t .LC8 +0008296a A __iar_rom_use_bGf0V$frrBD +10000000 D .vector_table$$Base +10000000 D NewVectorTable +10000000 d .LANCHOR2 +10000100 D .user_vector_table$$Base +10000100 D .vector_table$$Limit +10000100 D UserIrqFunTable +10000100 d .LANCHOR0 +10000200 D .user_data_table$$Base +10000200 D .user_vector_table$$Limit +10000200 D UserIrqDataTable +10000200 d .LANCHOR1 +10000300 A __rom_bss_start__ +10000300 D .rom.bss$$Base +10000300 D .user_data_table$$Limit +10000300 D CfgSysDebugWarn +10000304 D CfgSysDebugInfo +10000308 D CfgSysDebugErr +1000030c D ConfigDebugWarn +10000310 D ConfigDebugInfo +10000314 D ConfigDebugErr +10000318 D HalTimerOp +10000318 d .LANCHOR1 +10000334 D GPIOState +10000334 d .LANCHOR0 +1000034c D gTimerRecord +1000034c d .LANCHOR1 +10000350 D SSI_DBG_CONFIG +10000350 d .LANCHOR0 +10000354 D _pHAL_Gpio_Adapter +10000354 d .LANCHOR1 +10000358 D Timer2To7VectorTable +10000358 d .LANCHOR0 +10000370 d .LANCHOR0 +10000370 d first +10000374 d z1 +10000378 d z2 +1000037c d z3 +10000380 d z4 +10000384 D UartLogCtl +100003ac D UartLogBuf +1000042c D UartLogHistoryBuf +100006a8 D pUartLogCtl +100006ac D ArgvArray +100006d4 D rom_wlan_ram_map +100006e0 D FalseAlmCnt +100006e0 d .LANCHOR0 +10000720 D ROMInfo +10000738 D DM_CfoTrack +10000760 D rom_libgloss_ram_map +10000760 d .LANCHOR0 +10000780 d .LANCHOR0 +10000780 d __rtl_malloc_av_ +10000b88 d __rtl_malloc_trim_threshold +10000b8c d __rtl_malloc_top_pad +10000b90 d __rtl_malloc_sbrk_base +10000b94 d __rtl_malloc_max_sbrked_mem +10000b98 d __rtl_malloc_max_total_mem +10000b9c d __rtl_malloc_current_mallinfo +10000bc4 D __rtl_errno +10000bc4 d .LANCHOR0 +10000bc8 A __ram_start_table_start__ +10000bc8 A __rom_bss_end__ +10000bc8 D .rom.bss$$Limit +10000bc8 D IMAGE1$$Base +10000bc8 D bootloader +10000bdc A __image1_validate_code__ +10001c60 A _rtl_impure_ptr +10003ea4 D IMAGE1$$Limit +10004000 T .image2.start.table1$$Base +10004000 T IMAGE2$$Base +10004000 T gImage2EntryFun0 +10004004 T .image2.start.table1$$Limit +10004004 T .image2.start.table2$$Base +10004004 T RAM_IMG2_VALID_PATTEN +10004018 T cus_sig +10004038 T .image2.start.table2$$Limit +10004038 T .ram_image2.text$$Base +10004038 t ?Veneer (6) for _memset +10004040 t ?Veneer (6) for DiagPrintf +10004048 t ?Veneer (6) for VectorTableInitForOSRtl8195A +10004050 T SYSPlatformInit +1000406c T InfraStart +1000406c t .infra.ram.start_83 +10004104 t .infra.ram.start_84 +10004108 t .infra.ram.start_85 +1000410c t .infra.ram.start_86 +10004110 t .infra.ram.start_87 +10004114 t .infra.ram.start_88 +10004118 t .infra.ram.start_89 +1000411c t .infra.ram.start_90 +10004120 t .infra.ram.start_91 +10004124 t .infra.ram.start_92 +10004128 t .infra.ram.start_93 +1000412c t .infra.ram.start_94 +10004130 t ?_15 +1000414c t ?_16 +10004168 t ?_0 +10004170 t ?_1 +10004178 t ?_2 +10004180 t ?_3 +10004188 t ?_4 +10004190 t ?_5 +10004198 t ?_6 +100041a0 t ?_7 +100041a8 t ?_8 +100041b0 t ?_9 +100041b8 t ?_10 +100041c0 t ?_11 +100041c8 t ?_12 +100041d0 t ?_0 +100041d8 t ?_1 +100041e0 t ?_2 +100041e8 t ?_3 +100041f0 t ?_4 +100041f8 t ?_5 +10004200 t ?_6 +10004208 t ?_7 +10004210 t ?_8 +10004218 t ?_9 +10004220 t ?_10 +10004228 t ?_11 +10004230 t ?_12 +10004238 t ?_13 +10004240 t ?_14 +10004248 t ?_15 +10004250 t ?_16 +10004258 t ?_17 +10004260 t ?_18 +10004268 t ?_19 +10004270 t ?_20 +10004278 t ?_21 +10004280 t ?_22 +10004288 t ?_23 +10004290 T ip_addr_any +10004294 T ip_addr_broadcast +10004294 t .rodata_10 +10004298 t ?_0 +100042a0 t ?_1 +100042a8 T osdep_service +100043c0 t ?_0 +100043cc t ?_1 +100043d8 t ?_2 +100043e8 t ?_3 +100043f8 t ?_4 +10004404 t ?_5 +10004410 t ?_6 +1000441c t ?_7 +10004428 t ?_8 +10004430 t ?_9 +1000443c t ?_10 +10004444 t ?_11 +10004450 t ?_12 +1000445c T P2P_OUI +1000445c t .rodata_269 +10004460 T RSN_TKIP_CIPHER +10004460 t .rodata_271 +10004464 T hci_ops +10004474 T REALTEK_96B_IE +10004474 t .rodata_92 +1000447c t dh_group5_generator +10004480 t dh_group5_prime +10004540 T CCKSwingTable_Ch1_Ch13_8195A +1000466c T CCKSwingTable_Ch14_8195A +1000466c t .rodata_13 +10004798 T CCKFCCTable_8195A +10004798 t .rodata_14 +100047b0 T CCKCETable_8195A +100047b0 t .rodata_15 +100047c8 t ?_0 +100047cc t ?_1 +100047d4 t ?_2 +100047d8 t ?_3 +100047dc t ?_4 +100047e0 t ?_5 +100047e4 t ?_6 +100047e8 t ?_7 +100047f0 t ?_8 +100047f4 t ?_9 +100047f8 t ?_10 +100047fc t ?_11 +10004800 t ?_12 +10004804 t ?_13 +10004808 t ?_14 +1000480c t ?_15 +10004810 t ?_16 +10004814 t ?_17 +10004818 t ?_18 +1000481c t ?_19 +10004820 t ?_20 +10004824 t ?_21 +10004828 t ?_22 +1000482c t ?_23 +10004834 t ?_24 +10004838 t ?_25 +1000483c t ?_26 +10004840 t ?_27 +10004844 t ?_28 +10004848 T CPP_INIT$$Base +10004848 T CPP_INIT$$Limit +10004848 T SHT$$INIT_ARRAY$$Base +10004848 T SHT$$INIT_ARRAY$$Limit +10004848 T SHT$$PREINIT_ARRAY$$Base +10004848 T SHT$$PREINIT_ARRAY$$Limit +10004848 t ?Veneer (6) for UartLogCmdChk +10004848 t __iar_SB +10004850 t ?Veneer (6) for UartLogHistoryCmd +10004858 t ?Veneer (6) for HalSerialGetIsrEnRegRtl8195a +10004860 t ?Veneer (6) for HalSerialSetIrqEnRegRtl8195a +10004868 t ?Veneer (6) for HalSerialGetcRtl8195a +10004870 t ?Veneer (6) for ArrayInitialize +10004878 T UartLogIrqHandleRam +100048a4 t ??UartLogIrqHandleRam_1 +100048b8 t ??UartLogIrqHandleRam_3 +100048bc t ??UartLogIrqHandleRam_0 +100048ca t ??UartLogIrqHandleRam_2 +100048ce t ??UartLogIrqHandleRam_5 +100048ea t ??UartLogIrqHandleRam_6 +1000490c t ??UartLogIrqHandleRam_7 +10004918 t ??UartLogIrqHandleRam_4 +10004924 t ??DataTable5_1 +10004928 t ?Veneer (6) for SpicLoadInitParaFromClockRtl8195A +10004930 t ?Veneer (6) for SpicWaitBusyDoneRtl8195A +10004938 t ?Veneer (6) for SpicCmpDataForCalibrationRtl8195A +10004940 T SpicTxCmdWithDataRtl8195A +100049c0 T SpicTxFlashInstRtl8195A +100049c0 t .hal.flash.text_4 +100049fe t .hal.flash.text_6 +10004a02 t .hal.flash.text_7 +10004a0c T SpicSectorEraseFlashRtl8195A +10004a0c t .hal.flash.text_9 +10004a26 t .hal.flash.text_11 +10004a2c T SpicFlashInitRtl8195A +10004a2c t .hal.flash.text_13 +10004ab4 t .hal.flash.text_14 +10004ab8 T SpicCalibrationRtl8195A +10004ab8 t .hal.flash.text_15 +10004cb8 t .hal.flash.text_16 +10004cc4 t .hal.flash.text_17 +10004cd0 t .hal.flash.text_18 +10004cda t .hal.flash.text_19 +10004ce4 t .hal.flash.text_20 +10004cee T SpicConfigAutoModeRtl8195A +10004cee t .hal.flash.text_21 +10004d28 T SpicWaitWipDoneRefinedRtl8195A +10004d28 t .hal.flash.text_22 +10004d48 t .hal.flash.text_23 +10004d54 T SpicRxCmdRefinedRtl8195A +10004d54 t .hal.flash.text_24 +10004e1c T SpicGetFlashStatusRefinedRtl8195A +10004e1c t .hal.flash.text_25 +10004e4e T SpicInitRefinedRtl8195A +10004e4e t .hal.flash.text_26 +10004ed4 T SpicSetFlashStatusRefinedRtl8195A +10004ed4 t .hal.flash.text_28 +10004f14 T SpicWaitWipRtl8195A +10004f14 t .hal.flash.text_29 +10004f1e T SpicOneBitCalibrationRtl8195A +10004f1e t .hal.flash.text_30 +10004f34 T SpicDisableRtl8195A +10004f34 t .hal.flash.text_31 +10004f40 T SpicNVMCalLoad +10004f40 t .hal.flash.text_32 +10004fce T SpicNVMCalLoadAll +10004fce t .hal.flash.text_33 +10004fea T SpicNVMCalStore +10004fea t .hal.flash.text_34 +100050e4 t .hal.flash.text_35 +100050e8 t .hal.flash.text_36 +100050ec t .hal.flash.text_37 +100050f0 t .hal.flash.text_38 +100050f4 t .hal.flash.text_39 +100050f8 t .hal.flash.text_42 +100050fc t .hal.flash.text_43 +10005100 t .hal.flash.text_44 +10005104 t .hal.flash.text_45 +10005108 t .hal.flash.text_46 +1000510c t .hal.flash.text_47 +10005110 t .hal.flash.text_48 +10005114 t .hal.flash.text_49 +10005118 t .hal.flash.text_50 +1000511c t .hal.flash.text_51 +10005120 t .hal.flash.text_52 +10005124 t .hal.flash.text_53 +10005128 t ??__func__ +10005144 t ?_0 +1000516c t ?_1 +100051a8 t ?_5 +100051c8 t ?_6 +100051e8 t ?_7 +10005218 t ?_8 +1000522c t ?_9 +10005248 t ?_10 +10005280 t ??__func___1 +100052a0 t ?_11 +100052b8 t ??__func___2 +100052d4 t ?_12 +100052f0 t ??__func___3 +10005314 t ?_13 +1000538c t ?_14 +100053d8 t ?_15 +10005410 t ?_16 +10005488 t ?_17 +100054c8 t ?_18 +10005530 t ?Veneer (6) for HAL_GPIO_GetIPPinName_8195a +10005538 t ?Veneer (6) for HAL_GPIO_Init_8195a +10005540 T HAL_GPIO_GetPinName +10005544 T HAL_GPIO_Init +10005544 t .hal.gpio.text_4 +10005566 t ??HAL_GPIO_Init_0 +10005570 t ??DataTable7 +10005574 t ??DataTable7_1 +10005578 t ??DataTable7_2 +1000557c t ??__FUNCTION___1 +1000558c t ?_1 +100055b8 t internal_Pow +100059d0 t .text_3 +100059d6 T pow +100059d6 t .text_4 +100059e8 t lnbias +10005e08 T __iar_Dnorm +10005e4a T __iar_Dint +10005ec8 T __aeabi_cdcmpeq +10005ee8 T __aeabi_errno_addr +10005ef0 t .text_4 +10005ef4 T __aeabi_cdrcmple +10005f22 T rtl8195a_init_recv_priv +10005f26 T rtl8195a_free_recv_priv +10005f26 t .text_3 +10005f28 T __aeabi_cdcmple +10005f56 T _SScin +10005f74 T __aeabi_dmul +10006116 T __iar_zero_init3 +10006138 T __aeabi_dadd +1000614c T __iar_dadd +1000614c t .text_1 +10006220 T __aeabi_d2iz +1000624c T __iar_d2uiz +1000624c t .text_2 +1000626c T __aeabi_i2d +10006280 T __iar_ui2d +10006280 t .text_2 +10006298 T __aeabi_dsub +100062ac T __iar_dsub +100062ac t .text_1 +100062be T __iar_dsubStart +10006418 T __aeabi_ddiv +10006660 T __iar_Logpoly +10006660 t .text_4 +100066d4 t .text_10 +100066d8 t .text_11 +100066dc t .text_12 +100066e0 t .text_13 +100066e4 t .text_14 +100066e8 t .text_15 +100066ec t .text_16 +100066f0 t .text_17 +100066f4 t .text_18 +100066f8 t .text_19 +100066fc t .text_20 +10006700 t .text_21 +10006704 t .text_22 +10006708 t .text_23 +1000670c T __iar_Exp +100069c2 t .text_3 +100069c8 T __iar_dlib_perthread_access +100069ca T __iar_Dtest +100069fc T __iar_Dscale +10006b08 T analogin_init +10006bc8 t ??DataTable3 +10006bcc t ??DataTable3_1 +10006bd0 t ??DataTable3_2 +10006bd4 t ??DataTable3_3 +10006bd8 t ??DataTable3_4 +10006bdc t ??DataTable3_5 +10006be0 t ??DataTable3_6 +10006be4 T analogin_read_u16 +10006be4 t .text_12 +10006bea t ??CrossCallReturnLabel_0 +10006c0c t .text_13 +10006c0c t ?Subroutine0 +10006c20 t ?Veneer (6) for HalDelayUs +10006c28 t ?Veneer (6) for _memcpy +10006c30 t ?Veneer (6) for VectorIrqRegisterRtl8195A +10006c38 t ?Veneer (6) for VectorIrqEnRtl8195A +10006c40 t ?Veneer (6) for _memcmp +10006c48 T HalADCOpInit +10006c70 T ADCISRHandle +10006c70 t .text_7 +10006c9e t __iar_annotation$$tailcall +10006ca0 t ??ADCISRHandle_0 +10006caa t __iar_annotation$$tailcall +10006cac T ADCGDMAISRHandle +10006cac t .text_8 +10006d06 t ??ADCGDMAISRHandle_0 +10006d16 t ??ADCGDMAISRHandle_1 +10006d1a t .text_10 +10006d1a t RtkADCDMAInit +10006db4 t ??RtkADCDMAInit_0 +10006df4 t ??RtkADCDMAInit_1 +10006e08 t ??RtkADCDMAInit_2 +10006e18 T RtkADCInit +10006e18 t .text_11 +10006e32 t ??RtkADCInit_0 +10006e70 t ??RtkADCInit_1 +10006ed4 t ??RtkADCInit_3 +10006ee8 t ??RtkADCInit_4 +10006f02 t ??RtkADCInit_5 +10006f1a t ??RtkADCInit_2 +10006f24 t .text_13 +10006f24 t ??RtkADCDeInit_0 +10006f24 t ?Subroutine0 +10006f2a T RtkADCReceiveBuf +10006f2a t .text_15 +10006f66 t ??RtkADCReceiveBuf_0 +10006f6c t ??RtkADCReceiveBuf_1 +10006f7e t ??RtkADCReceiveBuf_2 +10006fa0 t ??DataTable12 +10006fa4 t ??DataTable12_1 +10006fa8 t ??DataTable12_2 +10006fac t ??DataTable12_3 +10006fb0 t ??DataTable12_4 +10006fb4 t ??DataTable12_5 +10006fb8 t ??DataTable12_8 +10006fbc t ??DataTable12_9 +10006fc0 t ??DataTable12_10 +10006fc4 t ??DataTable12_11 +10006fc8 t ??DataTable12_12 +10006fcc t ??DataTable12_13 +10006fd0 t ??DataTable12_14 +10006fd4 t ??DataTable12_15 +10006fd8 t ??DataTable12_16 +10006fdc t ??DataTable12_17 +10006fe0 T RtkADCLoadDefault +10006fe0 t .text_36 +10007044 t ?_0 +10007068 t ??__func__ +10007074 t ?_1 +10007084 t ?_2 +100070c4 T netconn_new_with_proto_and_callback +100070e4 t ??CrossCallReturnLabel_26 +1000711a t ??netconn_new_with_proto_and_callback_0 +1000711c t ??netconn_new_with_proto_and_callback_1 +10007120 T netconn_delete +10007120 t .text_3 +10007134 t ??CrossCallReturnLabel_25 +1000713a t ??netconn_delete_0 +10007140 T netconn_getaddr +10007140 t .text_4 +1000714e t ??netconn_getaddr_0 +10007154 t ??netconn_getaddr_1 +10007168 t ??CrossCallReturnLabel_24 +1000716c t ??CrossCallReturnLabel_6 +10007170 t ??CrossCallReturnLabel_7 +1000717a t ??netconn_getaddr_2 +1000717e T netconn_bind +1000717e t .text_5 +10007194 t ??CrossCallReturnLabel_28 +10007198 t ??CrossCallReturnLabel_5 +1000719c t ??CrossCallReturnLabel_8 +100071a6 t ??netconn_bind_0 +100071aa T netconn_connect +100071aa t .text_6 +100071c0 t ??CrossCallReturnLabel_27 +100071c4 t ??CrossCallReturnLabel_4 +100071c8 t ??CrossCallReturnLabel_9 +100071d2 t ??netconn_connect_0 +100071d6 t .text_8 +100071d6 t ?Subroutine2 +100071dc T netconn_listen_with_backlog +100071dc t .text_9 +100071f4 t ??CrossCallReturnLabel_22 +100071f8 t ??CrossCallReturnLabel_2 +100071fc t ??CrossCallReturnLabel_11 +10007206 t ??netconn_listen_with_backlog_0 +1000720a t .text_10 +1000720a t ?Subroutine3 +10007214 T netconn_accept +10007214 t .text_11 +10007230 t ??netconn_accept_0 +10007232 t ??netconn_accept_1 +1000725a t ??netconn_accept_3 +10007264 t ??CrossCallReturnLabel_18 +10007270 t ??netconn_accept_4 +10007282 t ??netconn_accept_5 +10007286 t ??netconn_accept_2 +10007288 t .text_12 +10007288 t ?Subroutine4 +1000728a t ??Subroutine4_0 +1000728e t __iar_annotation$$tailcall +10007290 t .text_13 +10007290 t netconn_recv_data +100072ba t ??netconn_recv_data_1 +100072e2 t ??netconn_recv_data_2 +100072f4 t ??netconn_recv_data_5 +1000730e t ??netconn_recv_data_6 +1000731c t ??CrossCallReturnLabel_17 +10007324 t ??netconn_recv_data_3 +10007336 t ??netconn_recv_data_4 +1000733a t ??netconn_recv_data_7 +10007346 t ??CrossCallReturnLabel_16 +1000734c t ??netconn_recv_data_0 +10007350 T netconn_recv_tcp_pbuf +10007350 t .text_14 +10007358 t ??netconn_recv_tcp_pbuf_0 +1000735e t ??netconn_recv_tcp_pbuf_1 +10007360 T netconn_recv +10007360 t .text_15 +10007374 t ??netconn_recv_0 +10007384 t ??netconn_recv_1 +100073a0 t ??CrossCallReturnLabel_12 +100073b2 t ??netconn_recv_3 +100073ca t ??netconn_recv_4 +100073dc t ??netconn_recv_2 +100073e6 t .text_16 +100073e6 t ?Subroutine0 +100073ec T netconn_recved +100073ec t .text_17 +100073f0 t ??netconn_recved_0 +10007410 t ??netconn_recved_1 +10007414 T netconn_send +10007414 t .text_19 +1000742e t ??CrossCallReturnLabel_21 +10007432 t ??CrossCallReturnLabel_1 +10007436 t ??CrossCallReturnLabel_13 +10007440 t ??netconn_send_0 +10007444 t .text_20 +10007444 t ?Subroutine1 +1000744e t .text_21 +1000744e t ??Subroutine5_0 +10007454 T netconn_write_partly +10007454 t .text_22 +10007472 t ??netconn_write_partly_2 +1000748c t ??netconn_write_partly_1 +10007492 t ??netconn_write_partly_3 +100074a4 t ??CrossCallReturnLabel_20 +100074b6 t ??netconn_write_partly_4 +100074be t ??CrossCallReturnLabel_14 +100074ca t ??netconn_write_partly_0 +100074d0 t .text_23 +100074d0 t netconn_close_shutdown +100074ec t ??CrossCallReturnLabel_19 +100074f0 t ??CrossCallReturnLabel_0 +100074f4 t ??CrossCallReturnLabel_15 +100074fe t ??netconn_close_shutdown_0 +10007504 t ??DataTable11 +10007508 t ??DataTable11_1 +1000750c t ??DataTable11_2 +10007510 t ??DataTable11_3 +10007514 t ??DataTable11_4 +10007518 t ??DataTable11_6 +1000751c t ??DataTable11_7 +10007520 t ??DataTable11_8 +10007524 t ??DataTable11_9 +10007528 t ??DataTable11_10 +1000752c T netconn_close +1000752c t .text_35 +10007530 T netconn_abort +10007530 t .text_37 +10007546 t ??netconn_abort_1 +1000754e t ??netconn_abort_0 +10007554 t recv_raw +10007562 t ??CrossCallReturnLabel_3 +10007584 t ??recv_raw_1 +1000758c t ??recv_raw_2 +100075b2 t ??recv_raw_3 +100075c0 t ??recv_raw_0 +100075c4 t .text_3 +100075c4 t recv_udp +100075d2 t ??CrossCallReturnLabel_2 +100075de t ??recv_udp_0 +100075e8 t ??recv_udp_1 +10007612 t ??recv_udp_2 +10007624 t __iar_annotation$$tailcall +10007626 t ??recv_udp_3 +10007628 t .text_4 +10007628 t recv_tcp +10007636 t ??recv_tcp_0 +1000763a t ??CrossCallReturnLabel_1 +1000764e t ??recv_tcp_1 +10007678 t ??recv_tcp_3 +10007686 t ??recv_tcp_2 +1000768a t .text_5 +1000768a t poll_tcp +1000769c t ??poll_tcp_0 +100076a6 t ??poll_tcp_1 +100076de t ??CrossCallReturnLabel_9 +100076e2 t .text_6 +100076e2 t sent_tcp +100076f6 t ??sent_tcp_0 +10007700 t ??sent_tcp_1 +1000773e t ??sent_tcp_2 +10007742 t .text_7 +10007742 t err_tcp +1000777a t ??CrossCallReturnLabel_12 +10007784 t ??CrossCallReturnLabel_8 +10007788 t ??CrossCallReturnLabel_0 +10007794 t ??err_tcp_0 +10007798 t ??CrossCallReturnLabel_16 +100077a4 t ??err_tcp_1 +100077cc t ??err_tcp_2 +100077ce t .text_8 +100077ce t ?Subroutine5 +100077d0 t ??Subroutine5_0 +100077d8 t .text_9 +100077d8 t setup_tcp +10007812 t .text_10 +10007812 t accept_function +1000781e t ??CrossCallReturnLabel_15 +10007822 t ??accept_function_0 +10007888 t ??accept_function_1 +1000788a t ??accept_function_2 +10007894 t ??CrossCallReturnLabel_11 +10007898 t .text_11 +10007898 t ?Subroutine7 +1000789e t __iar_annotation$$tailcall +100078a0 t .text_12 +100078a0 t ?Subroutine1 +100078a6 t .text_13 +100078a6 t ?Subroutine0 +100078ac T do_newconn +100078ac t .text_14 +100078b2 t ??CrossCallReturnLabel_20 +100078ce t ??do_newconn_1 +100078e0 t ??do_newconn_2 +10007902 t ??do_newconn_3 +1000790e t ??do_newconn_5 +10007912 t ??do_newconn_6 +1000791c t ??do_newconn_4 +10007922 t ??do_newconn_0 +1000792a T netconn_alloc +1000792a t .text_15 +1000795e t ??netconn_alloc_1 +10007962 t ??netconn_alloc_2 +10007982 t ??netconn_alloc_3 +1000798c t ??netconn_alloc_0 +10007990 t ??netconn_alloc_4 +100079b8 T netconn_free +100079b8 t .text_16 +100079be t ??CrossCallReturnLabel_5 +100079c2 t ??CrossCallReturnLabel_14 +100079de t .text_17 +100079de t ?Subroutine8 +100079e6 t .text_18 +100079e6 t netconn_drain +100079ec t ??CrossCallReturnLabel_4 +100079f0 t ??netconn_drain_2 +100079f4 t ??netconn_drain_0 +10007a1c t ??netconn_drain_4 +10007a24 t ??netconn_drain_3 +10007a34 t ??netconn_drain_1 +10007a38 t ??CrossCallReturnLabel_13 +10007a3c t ??netconn_drain_6 +10007a50 t ??netconn_drain_7 +10007a56 t ??netconn_drain_5 +10007a78 t .text_19 +10007a78 t do_close_internal +10007a98 t ??do_close_internal_0 +10007a9a t ??do_close_internal_1 +10007aac t ??do_close_internal_4 +10007ab6 t ??do_close_internal_5 +10007ad4 t ??do_close_internal_7 +10007ae0 t ??CrossCallReturnLabel_10 +10007aec t ??CrossCallReturnLabel_7 +10007aee t ??do_close_internal_2 +10007afe t ??do_close_internal_8 +10007b08 t ??do_close_internal_9 +10007b1e t ??do_close_internal_3 +10007b26 t ??do_close_internal_6 +10007b4c t .text_20 +10007b4c t ?Subroutine6 +10007b52 t __iar_annotation$$tailcall +10007b54 t .text_21 +10007b54 t ?Subroutine3 +10007b60 T do_delconn +10007b60 t .text_22 +10007b7a t ??do_delconn_0 +10007b9a t ??do_delconn_5 +10007ba0 t ??do_delconn_2 +10007bbc t ??do_delconn_1 +10007bc8 t ??do_delconn_6 +10007bca t ??do_delconn_4 +10007bd6 t ??do_delconn_3 +10007be0 t .text_23 +10007be0 t ?Subroutine4 +10007be8 T do_bind +10007be8 t .text_24 +10007bee t ??CrossCallReturnLabel_17 +10007c14 t ??do_bind_3 +10007c1e t ??do_bind_2 +10007c26 t ??do_bind_0 +10007c28 t ??do_bind_1 +10007c2a t .text_25 +10007c2a t do_connected +10007c36 t ??do_connected_0 +10007c40 t ??do_connected_1 +10007c84 t ??do_connected_2 +10007c8e t ??CrossCallReturnLabel_6 +10007c98 t ??do_connected_3 +10007c9c T do_connect +10007c9c t .text_26 +10007cac t ??do_connect_0 +10007cc6 t ??do_connect_3 +10007cd0 t ??do_connect_2 +10007cda t ??do_connect_5 +10007d16 t ??do_connect_7 +10007d24 t ??do_connect_4 +10007d28 t ??do_connect_1 +10007d2a t ??do_connect_6 +10007d2c T do_listen +10007d2c t .text_28 +10007d32 t ??CrossCallReturnLabel_18 +10007d76 t ??do_listen_3 +10007d92 t ??do_listen_4 +10007db2 t ??do_listen_5 +10007dc0 t ??do_listen_2 +10007dc4 t ??do_listen_0 +10007dc6 t ??do_listen_1 +10007dd0 t ??DataTable5 +10007dd4 t ??DataTable5_1 +10007dd8 t ??DataTable5_2 +10007ddc t ??DataTable5_3 +10007de0 t ??DataTable5_4 +10007de4 t ??DataTable5_5 +10007de8 t ??DataTable5_6 +10007dec t ??DataTable5_7 +10007df0 t ??DataTable5_8 +10007df4 t .text_38 +10007df4 t ?Subroutine9 +10007e02 T do_send +10007e02 t .text_39 +10007e08 t ??CrossCallReturnLabel_19 +10007e38 t ??do_send_3 +10007e44 t ??do_send_2 +10007e5a t ??do_send_4 +10007e66 t ??do_send_0 +10007e68 t ??do_send_1 +10007e6a T do_recv +10007e6a t .text_40 +10007e70 t ??CrossCallReturnLabel_21 +10007e7a t ??do_recv_1 +10007e96 t ??do_recv_0 +10007e9e t .text_41 +10007e9e t ?Subroutine10 +10007eaa t .text_42 +10007eaa t do_writemore +10007f00 t ??do_writemore_1 +10007f04 t ??do_writemore_0 +10007f18 t ??do_writemore_2 +10007f2e t ??do_writemore_5 +10007f3c t ??do_writemore_4 +10007f54 t ??do_writemore_7 +10007f62 t ??do_writemore_6 +10007f78 t ??do_writemore_8 +10007f82 t ??do_writemore_3 +10007f8c t ??do_writemore_9 +10007f98 t ??do_writemore_10 +10007f9c t ??do_writemore_11 +10007fb2 t ??do_writemore_12 +10007fb8 T do_write +10007fb8 t .text_43 +10007fd4 t ??do_write_2 +10007fe6 t ??do_write_3 +10007fec t ??do_write_1 +10007ff0 t ??do_write_0 +10007ff6 T do_getaddr +10007ff6 t .text_44 +10008032 t ??do_getaddr_2 +1000803c t ??do_getaddr_5 +10008048 t ??do_getaddr_1 +10008054 t ??do_getaddr_4 +1000805a t ??do_getaddr_0 +1000805c t ??do_getaddr_3 +10008060 T do_close +10008060 t .text_45 +1000808e t ??do_close_2 +1000809e t ??do_close_1 +100080a2 t .text_46 +100080a2 t ??do_close_0 +100080a2 t ?Subroutine2 +100080a4 t ??Subroutine2_0 +100080a6 t ??Subroutine2_1 +100080aa t .text_47 +100080aa t ??Subroutine11_0 +100080b0 T sys_mbox_new +100080c8 t ??sys_mbox_new_0 +100080cc T sys_mbox_free +100080cc t .text_4 +100080e0 T sys_mbox_post +100080e0 t .text_5 +100080e4 t ??sys_mbox_post_0 +100080e8 t ??CrossCallReturnLabel_0 +100080f4 T sys_mbox_trypost +100080f4 t .text_6 +1000810a t ??sys_mbox_trypost_0 +1000810c T sys_arch_mbox_fetch +1000810c t .text_7 +1000811e t ??sys_arch_mbox_fetch_0 +1000813a t ??sys_arch_mbox_fetch_1 +1000813e t ??CrossCallReturnLabel_1 +10008148 t ??sys_arch_mbox_fetch_2 +10008150 t .text_8 +10008150 t ?Subroutine3 +1000815a T sys_arch_mbox_tryfetch +1000815a t .text_9 +10008160 t ??sys_arch_mbox_tryfetch_0 +10008172 t .text_10 +10008172 t ??sys_arch_mbox_tryfetch_1 +10008172 t ?Subroutine0 +10008178 T sys_mbox_valid +10008178 t .text_11 +1000817a T sys_mbox_set_invalid +1000817a t .text_12 +1000817c T sys_sem_new +1000817c t .text_13 +1000819e t ??sys_sem_new_0 +100081a4 t ??sys_sem_new_1 +100081b0 t ??sys_sem_new_2 +100081b4 T sys_arch_sem_wait +100081b4 t .text_14 +100081d8 t ??sys_arch_sem_wait_0 +100081dc t ??CrossCallReturnLabel_2 +100081e6 t ??sys_arch_sem_wait_1 +100081ee T sys_sem_signal +100081ee t .text_15 +100081fa T sys_sem_free +100081fa t .text_16 +10008200 T sys_sem_valid +10008200 t .text_17 +10008202 t .text_18 +10008202 t ?Subroutine1 +10008208 t ??Subroutine1_0 +1000820a T sys_sem_set_invalid +1000820a t .text_19 +1000820c t .text_20 +1000820c t ?Subroutine2 +10008212 T sys_init +10008212 t .text_21 +10008218 t ??sys_init_0 +1000822a T sys_thread_new +1000822a t .text_23 +1000827a t ??sys_thread_new_0 +1000827c t ??sys_thread_new_1 +10008284 t ??DataTable3 +10008288 T sys_arch_protect +10008288 t .text_26 +10008292 T sys_arch_unprotect +10008292 t .text_27 +10008298 T memp_init +1000829c t ??memp_init_0 +100082b6 t ??memp_init_1 +100082be t ??memp_init_3 +100082d0 t ??memp_init_2 +100082e2 T memp_malloc +100082e2 t .text_4 +100082ee t ??memp_malloc_0 +10008300 t ??memp_malloc_1 +10008308 T memp_free +10008308 t .text_5 +10008328 t ??memp_free_0 +1000832c t ??DataTable4 +10008330 t memp_sizes +1000834c t memp_num +10008368 t tcpip_thread +1000837a t ??tcpip_thread_2 +10008388 t ??tcpip_thread_1 +1000839e t ??tcpip_thread_0 +100083a4 t ??tcpip_thread_3 +100083a6 t ??tcpip_thread_4 +100083a8 t ??tcpip_thread_5 +100083c2 t ??tcpip_thread_6 +100083c6 t ??tcpip_thread_7 +100083ca t ??tcpip_thread_8 +100083d0 t ??tcpip_thread_9 +100083dc t ??tcpip_thread_10 +100083e2 t ??tcpip_thread_11 +100083ee t ??tcpip_thread_12 +100083f2 t ??CrossCallReturnLabel_3 +100083f4 t ??tcpip_thread_13 +100083f8 t ??CrossCallReturnLabel_2 +100083fa t .text_4 +100083fa t ?Subroutine2 +10008402 t __iar_annotation$$tailcall +10008404 T tcpip_input +10008404 t .text_5 +1000840a t ??CrossCallReturnLabel_1 +1000840e t ??tcpip_input_0 +10008434 t ??tcpip_input_1 +10008438 t ??tcpip_input_2 +1000843a T tcpip_callback_with_block +1000843a t .text_6 +10008456 t ??CrossCallReturnLabel_7 +10008470 t ??tcpip_callback_with_block_3 +10008474 t ??tcpip_callback_with_block_2 +10008484 t ??tcpip_callback_with_block_1 +1000848a t ??tcpip_callback_with_block_0 +1000848e t ??tcpip_callback_with_block_4 +10008492 T tcpip_timeout +10008492 t .text_7 +100084aa t ??CrossCallReturnLabel_6 +100084b2 t ??tcpip_timeout_1 +100084ca t .text_8 +100084ca t ??tcpip_timeout_0 +100084ca t ?Subroutine0 +100084d0 t .text_10 +100084d0 t ?Subroutine3 +100084d6 t .text_11 +100084d6 t ?Subroutine1 +100084e4 T tcpip_apimsg +100084e4 t .text_12 +1000851c t ??tcpip_apimsg_0 +1000851e t ??tcpip_apimsg_1 +10008522 T tcpip_init +10008522 t .text_16 +10008550 t ??DataTable8 +10008554 t ??DataTable8_1 +10008558 t ?_0 +10008560 t pbuf_free_ooseq_callback +10008576 t ??pbuf_free_ooseq_callback_1 +10008578 t ??pbuf_free_ooseq_callback_0 +10008588 t ??pbuf_free_ooseq_callback_2 +1000858a t .text_4 +1000858a t pbuf_pool_is_empty +100085ba t ??pbuf_pool_is_empty_0 +100085bc t ??DataTable1 +100085c0 t ??DataTable1_1 +100085c4 t ??DataTable1_2 +100085c8 T pbuf_alloc +100085c8 t .text_8 +100085dc t ??pbuf_alloc_0 +100085e0 t ??pbuf_alloc_2 +100085e4 t ??pbuf_alloc_1 +100085e8 t ??pbuf_alloc_3 +100085ea t ??pbuf_alloc_5 +10008606 t ??pbuf_alloc_4 +1000860a t ??pbuf_alloc_8 +1000863c t ??pbuf_alloc_9 +1000864a t ??pbuf_alloc_11 +1000865c t ??pbuf_alloc_10 +10008674 t ??pbuf_alloc_13 +10008692 t ??pbuf_alloc_6 +100086c8 t ??pbuf_alloc_7 +100086de t ??pbuf_alloc_12 +100086ea T pbuf_alloced_custom +100086ea t .text_9 +100086fa t ??pbuf_alloced_custom_0 +100086fe t ??pbuf_alloced_custom_2 +10008702 t ??pbuf_alloced_custom_1 +10008706 t ??pbuf_alloced_custom_3 +10008708 t ??pbuf_alloced_custom_5 +10008716 t ??pbuf_alloced_custom_4 +1000871a t ??pbuf_alloced_custom_6 +10008724 t ??pbuf_alloced_custom_7 +10008738 T pbuf_realloc +10008738 t .text_10 +10008748 t ??pbuf_realloc_2 +10008754 t ??pbuf_realloc_1 +10008772 t ??pbuf_realloc_3 +10008780 t ??pbuf_realloc_4 +10008784 t ??pbuf_realloc_0 +10008786 T pbuf_header +10008786 t .text_11 +1000879e t ??pbuf_header_3 +100087a2 t ??pbuf_header_1 +100087a4 t ??pbuf_header_2 +100087c0 t ??pbuf_header_4 +100087d8 t ??pbuf_header_5 +100087e4 t ??pbuf_header_0 +100087e8 T pbuf_free +100087e8 t .text_12 +100087f2 t ??pbuf_free_0 +100087f4 t ??pbuf_free_1 +10008818 t ??pbuf_free_3 +10008822 t ??pbuf_free_5 +1000882e t ??pbuf_free_6 +10008834 t ??pbuf_free_7 +1000883a t ??pbuf_free_4 +10008840 t ??pbuf_free_2 +10008844 T pbuf_clen +10008844 t .text_13 +10008848 t ??pbuf_clen_1 +1000884c t ??pbuf_clen_0 +10008854 T pbuf_ref +10008854 t .text_14 +1000886c t ??pbuf_ref_0 +1000886e T pbuf_cat +1000886e t .text_15 +10008872 t ??pbuf_cat_0 +10008878 t ??pbuf_cat_2 +10008882 t ??pbuf_cat_1 +10008894 T pbuf_chain +10008894 t .text_16 +100088a4 T pbuf_copy +100088a4 t .text_18 +100088c0 t ??pbuf_copy_1 +10008904 t ??pbuf_copy_0 +1000890a t ??pbuf_copy_2 +10008918 t ??pbuf_copy_5 +10008926 t ??pbuf_copy_6 +1000892c t ??pbuf_copy_7 +10008930 t ??pbuf_copy_3 +10008932 t ??pbuf_copy_4 +10008936 T pbuf_copy_partial +10008936 t .text_19 +10008950 t ??pbuf_copy_partial_2 +1000895a t ??pbuf_copy_partial_3 +10008982 t ??pbuf_copy_partial_1 +10008988 t ??pbuf_copy_partial_4 +1000898c t ??pbuf_copy_partial_5 +10008990 t ??pbuf_copy_partial_0 +10008996 T pbuf_coalesce +10008996 t .text_21 +100089ac t ??pbuf_coalesce_0 +100089b0 t ??pbuf_coalesce_1 +100089c0 T netbuf_delete +100089c0 t .text_3 +100089d4 t ??netbuf_delete_1 +100089dc t ??netbuf_delete_0 +100089de T netbuf_free +100089de t .text_5 +100089ec t ??netbuf_free_1 +100089f2 t ??netbuf_free_0 +100089f4 T netbuf_ref +100089f4 t .text_6 +10008a04 t ??netbuf_ref_0 +10008a0c t ??netbuf_ref_1 +10008a22 t ??netbuf_ref_2 +10008a2e t .text_8 +10008a2e t ?Subroutine0 +10008a34 T netbuf_data +10008a34 t .text_9 +10008a3e t ??netbuf_data_0 +10008a44 t ??netbuf_data_1 +10008a4e t ??netbuf_data_2 +10008a5c T tcp_init +10008a5e T tcp_tmr +10008a5e t .text_6 +10008a7c t .text_7 +10008a7c t tcp_close_shutdown +10008ac8 t ??tcp_close_shutdown_2 +10008acc t ??CrossCallReturnLabel_0 +10008aea t ??tcp_close_shutdown_3 +10008aee t ??CrossCallReturnLabel_4 +10008af2 t ??tcp_close_shutdown_1 +10008afa t ??tcp_close_shutdown_0 +10008b02 t ??tcp_close_shutdown_5 +10008b14 t ??tcp_close_shutdown_7 +10008b18 t ??CrossCallReturnLabel_1 +10008b1c t ??tcp_close_shutdown_8 +10008b2e t ??tcp_close_shutdown_10 +10008b3e t ??tcp_close_shutdown_6 +10008b42 t ??tcp_close_shutdown_9 +10008b48 t ??tcp_close_shutdown_12 +10008b54 t ??tcp_close_shutdown_14 +10008b56 t ??tcp_close_shutdown_13 +10008b60 t ??tcp_close_shutdown_11 +10008b64 t ??tcp_close_shutdown_15 +10008b72 t ??tcp_close_shutdown_4 +10008b76 t .text_8 +10008b76 t ?Subroutine2 +10008b86 t ??Subroutine2_0 +10008b88 T tcp_close +10008b88 t .text_9 +10008b9a t ??tcp_close_0 +10008b9e T tcp_shutdown +10008b9e t .text_10 +10008bb8 t ??tcp_shutdown_3 +10008bbe t ??tcp_shutdown_2 +10008bca t ??tcp_shutdown_4 +10008bce t ??tcp_shutdown_1 +10008bdc t ??tcp_shutdown_0 +10008be2 T tcp_abandon +10008be2 t .text_11 +10008c12 t ??tcp_abandon_0 +10008c38 t ??tcp_abandon_1 +10008c40 t ??tcp_abandon_2 +10008c48 t ??tcp_abandon_3 +10008c5e t ??tcp_abandon_4 +10008c62 t ??CrossCallReturnLabel_3 +10008c70 t ??tcp_abandon_5 +10008c74 t .text_12 +10008c74 t ?Subroutine3 +10008c7c T tcp_abort +10008c7c t .text_13 +10008c80 T tcp_bind +10008c80 t .text_14 +10008c8e t ??tcp_bind_0 +10008c98 t ??tcp_bind_1 +10008c9e t ??tcp_bind_2 +10008ca6 t ??tcp_bind_4 +10008ca8 t ??tcp_bind_3 +10008cc0 t ??tcp_bind_6 +10008cc6 t ??tcp_bind_5 +10008cea t .text_15 +10008cea t tcp_accept_null +10008cf0 T tcp_listen_with_backlog +10008cf0 t .text_16 +10008d02 t ??tcp_listen_with_backlog_0 +10008d06 t ??tcp_listen_with_backlog_1 +10008d3e t ??tcp_listen_with_backlog_3 +10008d4e t ??tcp_listen_with_backlog_4 +10008d52 t ??tcp_listen_with_backlog_2 +10008d56 t ??CrossCallReturnLabel_2 +10008d6a T tcp_update_rcv_ann_wnd +10008d6a t .text_17 +10008d8e t ??tcp_update_rcv_ann_wnd_0 +10008d9e T tcp_recved +10008d9e t .text_18 +10008dde t ??tcp_recved_0 +10008de0 t .text_19 +10008de0 t tcp_new_port +10008dec t ??tcp_new_port_0 +10008e02 t ??tcp_new_port_1 +10008e0a t ??tcp_new_port_3 +10008e0c t ??tcp_new_port_2 +10008e22 t ??tcp_new_port_4 +10008e2c T tcp_connect +10008e2c t .text_20 +10008e3e t ??tcp_connect_0 +10008e5e t ??tcp_connect_1 +10008e60 t ??tcp_connect_3 +10008e64 t ??tcp_connect_2 +10008e72 t ??tcp_connect_4 +10008ed6 t ??tcp_connect_7 +10008ee6 t ??tcp_connect_8 +10008eea t ??tcp_connect_6 +10008efe t ??tcp_connect_5 +10008f02 t .text_21 +10008f02 t ?Subroutine1 +10008f08 t .text_22 +10008f08 t ?Subroutine0 +10008f0e T tcp_slowtmr +10008f0e t .text_23 +10008f24 t ??tcp_slowtmr_0 +10008f2a t ??tcp_slowtmr_2 +10008f2c t ??tcp_slowtmr_1 +10008fa2 t ??tcp_slowtmr_6 +10008fde t ??tcp_slowtmr_7 +1000900e t ??tcp_slowtmr_5 +10009028 t ??tcp_slowtmr_4 +1000905c t ??tcp_slowtmr_9 +10009084 t ??tcp_slowtmr_8 +100090a6 t ??tcp_slowtmr_10 +100090b8 t ??tcp_slowtmr_11 +100090c4 t ??tcp_slowtmr_12 +100090c8 t ??tcp_slowtmr_13 +100090f8 t ??tcp_slowtmr_15 +10009102 t ??CrossCallReturnLabel_6 +1000911a t ??tcp_slowtmr_17 +1000911c t ??tcp_slowtmr_14 +1000914e t ??tcp_slowtmr_18 +10009154 t ??tcp_slowtmr_16 +10009156 t ??tcp_slowtmr_3 +1000915c t ??tcp_slowtmr_19 +10009160 t ??CrossCallReturnLabel_5 +1000917e t ??tcp_slowtmr_21 +10009184 t ??tcp_slowtmr_20 +10009188 t .text_24 +10009188 t ?Subroutine4 +10009192 T tcp_fasttmr +10009192 t .text_25 +1000919c t ??tcp_fasttmr_0 +100091a0 t ??tcp_fasttmr_2 +100091c6 t ??tcp_fasttmr_3 +100091dc t ??tcp_fasttmr_4 +100091de t ??tcp_fasttmr_1 +100091e6 T tcp_process_refused_data +100091e6 t .text_26 +1000920e t ??tcp_process_refused_data_0 +1000921a t ??tcp_process_refused_data_1 +10009248 t ??tcp_process_refused_data_2 +1000924c t ??tcp_process_refused_data_4 +10009250 t ??tcp_process_refused_data_5 +10009252 t ??tcp_process_refused_data_3 +10009254 t ??tcp_process_refused_data_6 +10009258 T tcp_segs_free +10009258 t .text_27 +1000925e t ??tcp_segs_free_1 +10009266 t ??tcp_segs_free_0 +1000926a T tcp_seg_free +1000926a t .text_28 +10009278 t ??tcp_seg_free_1 +10009284 t ??tcp_seg_free_0 +10009286 T tcp_seg_copy +10009286 t .text_30 +10009298 t ??tcp_seg_copy_0 +100092aa T tcp_recv_null +100092aa t .text_31 +100092be t ??tcp_recv_null_1 +100092c2 t ??tcp_recv_null_0 +100092cc T tcp_alloc +100092cc t .text_32 +100092e4 t ??tcp_alloc_2 +100092f4 t ??tcp_alloc_1 +100092fe t ??tcp_alloc_3 +10009312 t ??tcp_alloc_5 +10009330 t ??tcp_alloc_6 +10009332 t ??tcp_alloc_4 +1000933c t ??tcp_alloc_7 +10009344 t ??tcp_alloc_0 +100093c0 t ??tcp_alloc_8 +100093c4 T tcp_new +100093c4 t .text_33 +100093c8 T tcp_arg +100093c8 t .text_34 +100093cc T tcp_recv +100093cc t .text_35 +100093d2 T tcp_sent +100093d2 t .text_36 +100093d8 T tcp_err +100093d8 t .text_37 +100093de T tcp_accept +100093de t .text_38 +100093e2 T tcp_poll +100093e2 t .text_39 +100093ec T tcp_pcb_purge +100093ec t .text_40 +1000940c t ??tcp_pcb_purge_1 +10009432 t ??tcp_pcb_purge_0 +10009434 T tcp_pcb_remove +10009434 t .text_41 +10009444 t ??tcp_pcb_remove_0 +10009446 t ??tcp_pcb_remove_2 +10009456 t ??tcp_pcb_remove_1 +10009480 t ??tcp_pcb_remove_3 +10009486 T tcp_next_iss +10009486 t .text_42 +10009494 t ??DataTable26 +10009498 t ??DataTable26_1 +1000949c t ??DataTable26_2 +100094a0 t ??DataTable26_3 +100094a4 t ??DataTable26_4 +100094a8 t ??DataTable26_5 +100094ac t ??DataTable26_6 +100094b0 t ??DataTable26_7 +100094b4 T tcp_eff_send_mss +100094b4 t .text_51 +100094d2 t ??tcp_eff_send_mss_0 +100094d8 T tcp_backoff +100094d8 t .text_54 +100094e8 T tcp_persist_backoff +100094e8 t .text_55 +100094f0 T tcp_pcb_lists +100094f0 t .text_56 +10009500 T udp_init +10009502 T udp_input +10009502 t .text_4 +1000958a t ??udp_input_2 +10009594 t ??udp_input_6 +10009598 t ??udp_input_5 +100095dc t ??udp_input_8 +100095ea t ??udp_input_9 +1000960a t ??udp_input_10 +10009618 t ??udp_input_7 +1000961c t ??udp_input_3 +10009622 t ??udp_input_1 +10009624 t ??udp_input_4 +1000963c t ??udp_input_11 +10009660 t ??udp_input_12 +1000968c t ??udp_input_0 +10009696 t ??udp_input_13 +1000969a T udp_send +1000969a t .text_5 +1000969e T udp_sendto +1000969e t .text_6 +100096b6 t ??udp_sendto_0 +100096c6 T udp_sendto_if +100096c6 t .text_7 +100096e6 t ??udp_sendto_if_0 +10009714 t ??udp_sendto_if_2 +10009716 t ??udp_sendto_if_4 +10009752 t ??udp_sendto_if_6 +10009754 t ??udp_sendto_if_5 +10009778 t ??udp_sendto_if_8 +1000977a t ??udp_sendto_if_7 +1000979c t ??udp_sendto_if_1 +1000979e t ??udp_sendto_if_3 +100097a4 T udp_bind +100097a4 t .text_8 +100097b0 t ??udp_bind_1 +100097ca t ??udp_bind_2 +100097cc t ??udp_bind_0 +100097d6 t ??udp_bind_4 +100097da t ??udp_bind_5 +100097e0 t ??udp_bind_7 +100097f8 t ??udp_bind_9 +100097fa t ??udp_bind_8 +1000980e t ??udp_bind_10 +10009812 t ??udp_bind_3 +10009818 t ??udp_bind_6 +10009820 t ??udp_bind_11 +10009824 T udp_connect +10009824 t .text_9 +1000983c t ??udp_connect_0 +10009858 t ??udp_connect_3 +1000985a t ??udp_connect_2 +10009862 t ??udp_connect_4 +10009866 t ??udp_connect_5 +10009868 t ??udp_connect_1 +1000986a T udp_disconnect +1000986a t .text_10 +1000987a T udp_recv +1000987a t .text_11 +10009880 T udp_remove +10009880 t .text_12 +1000988e t ??udp_remove_2 +1000989a t ??udp_remove_3 +1000989c t ??udp_remove_0 +100098a0 t ??udp_remove_1 +100098a8 t ??DataTable3 +100098ac t ??DataTable3_1 +100098b0 t ??DataTable3_2 +100098b4 T udp_new +100098b4 t .text_16 +100098cc t ??udp_new_0 +100098d0 T raw_input +100098ec t ??raw_input_0 +10009930 t ??raw_input_2 +10009938 t ??raw_input_1 +1000993e T raw_bind +1000993e t .text_4 +10009942 t ??raw_bind_0 +10009948 T raw_connect +10009948 t .text_5 +1000994c t ??raw_connect_0 +10009952 T raw_recv +10009952 t .text_6 +10009958 T raw_sendto +10009958 t .text_7 +10009984 t ??raw_sendto_2 +1000999c t ??raw_sendto_0 +100099ac t ??raw_sendto_1 +100099b2 t ??raw_sendto_3 +100099e2 T raw_send +100099e2 t .text_8 +100099e6 T raw_remove +100099e6 t .text_9 +100099f4 t ??raw_remove_2 +10009a00 t ??raw_remove_3 +10009a02 t ??raw_remove_0 +10009a06 t ??raw_remove_1 +10009a0e T raw_new +10009a0e t .text_10 +10009a32 t ??raw_new_0 +10009a38 t ??DataTable2 +10009a3c t ??DataTable2_1 +10009a40 t ??DataTable2_2 +10009a44 t tcp_output_alloc_header +10009aac t ??tcp_output_alloc_header_0 +10009ab2 T tcp_send_fin +10009ab2 t .text_3 +10009abc t ??tcp_send_fin_2 +10009abe t ??tcp_send_fin_1 +10009aca t ??CrossCallReturnLabel_1 +10009aee t ??tcp_send_fin_0 +10009af8 t .text_4 +10009af8 t tcp_create_segment +10009b26 t ??tcp_create_segment_0 +10009b4c t ??tcp_create_segment_1 +10009b50 t ??tcp_create_segment_2 +10009b94 t ??tcp_create_segment_3 +10009b98 t .text_5 +10009b98 t tcp_pbuf_prealloc +10009bc4 t ??tcp_pbuf_prealloc_1 +10009bde t ??tcp_pbuf_prealloc_0 +10009bf2 t ??tcp_pbuf_prealloc_2 +10009bf4 T tcp_write +10009bf4 t .text_6 +10009c34 t ??tcp_write_1 +10009c36 t ??tcp_write_0 +10009c4e t ??tcp_write_3 +10009c76 t ??tcp_write_5 +10009c80 t ??tcp_write_4 +10009c8e t ??tcp_write_8 +10009cda t ??tcp_write_9 +10009d1a t ??CrossCallReturnLabel_17 +10009d3c t ??CrossCallReturnLabel_20 +10009d3e t ??tcp_write_10 +10009d56 t ??tcp_write_12 +10009d6c t ??tcp_write_13 +10009d76 t ??tcp_write_7 +10009daa t ??CrossCallReturnLabel_18 +10009dc2 t ??CrossCallReturnLabel_19 +10009dc4 t ??tcp_write_15 +10009de8 t ??tcp_write_18 +10009dec t ??tcp_write_11 +10009dfc t ??tcp_write_19 +10009e08 t ??tcp_write_6 +10009e0c t ??tcp_write_2 +10009e12 t ??tcp_write_17 +10009e18 t ??tcp_write_16 +10009e32 t ??tcp_write_20 +10009e36 t ??tcp_write_21 +10009e60 t ??tcp_write_14 +10009e6a t ??tcp_write_24 +10009e88 t ??tcp_write_25 +10009e8a t ??tcp_write_23 +10009e9c t ??tcp_write_22 +10009eba t ??tcp_write_26 +10009f04 t ??tcp_write_27 +10009f08 t .text_7 +10009f08 t ?Subroutine4 +10009f14 t .text_8 +10009f14 t ?Subroutine3 +10009f20 T tcp_enqueue_flags +10009f20 t .text_9 +10009f62 t ??tcp_enqueue_flags_0 +10009f6e t ??tcp_enqueue_flags_1 +10009f74 t ??tcp_enqueue_flags_2 +10009f7c t ??tcp_enqueue_flags_5 +10009f7e t ??tcp_enqueue_flags_3 +10009f86 t ??tcp_enqueue_flags_4 +10009f9c t ??tcp_enqueue_flags_6 +10009fac t ??tcp_enqueue_flags_7 +10009fbc T tcp_send_empty_ack +10009fbc t .text_10 +10009fcc t ??CrossCallReturnLabel_6 +10009fd6 t ??tcp_send_empty_ack_0 +10009fee t ??CrossCallReturnLabel_24 +1000a00e T tcp_output +1000a00e t .text_11 +1000a040 t ??CrossCallReturnLabel_16 +1000a04c t ??tcp_output_2 +1000a054 t ??tcp_output_1 +1000a05a t ??tcp_output_5 +1000a05c t ??tcp_output_4 +1000a062 t ??tcp_output_3 +1000a06a t ??CrossCallReturnLabel_15 +1000a07a t ??CrossCallReturnLabel_4 +1000a096 t ??tcp_output_8 +1000a0a6 t ??tcp_output_7 +1000a0c8 t ??tcp_output_9 +1000a0d4 t ??CrossCallReturnLabel_14 +1000a0da t ??CrossCallReturnLabel_3 +1000a0f4 t ??CrossCallReturnLabel_2 +1000a110 t ??tcp_output_11 +1000a114 t ??CrossCallReturnLabel_13 +1000a11c t ??CrossCallReturnLabel_10 +1000a128 t ??tcp_output_15 +1000a12c t ??tcp_output_14 +1000a138 t ??CrossCallReturnLabel_9 +1000a13e t ??CrossCallReturnLabel_12 +1000a144 t ??tcp_output_16 +1000a150 t ??tcp_output_13 +1000a152 t ??tcp_output_12 +1000a156 t ??tcp_output_10 +1000a15c t ??tcp_output_17 +1000a160 t ??tcp_output_6 +1000a166 t ??tcp_output_18 +1000a16e t ??tcp_output_0 +1000a174 t .text_12 +1000a174 t tcp_output_segment +1000a1b4 t ??tcp_output_segment_0 +1000a1d8 t ??tcp_output_segment_1 +1000a1e6 t ??CrossCallReturnLabel_11 +1000a1e8 t ??tcp_output_segment_3 +1000a22a t ??tcp_output_segment_2 +1000a22c t ??DataTable1 +1000a230 t ??DataTable1_1 +1000a234 T tcp_rst +1000a234 t .text_15 +1000a2b8 t ??tcp_rst_0 +1000a2bc T tcp_rexmit_rto +1000a2bc t .text_16 +1000a2c6 t ??tcp_rexmit_rto_1 +1000a2c8 t ??tcp_rexmit_rto_0 +1000a2e6 T tcp_rexmit +1000a2e6 t .text_17 +1000a2fe t ??tcp_rexmit_2 +1000a300 t ??tcp_rexmit_1 +1000a30a t ??CrossCallReturnLabel_8 +1000a312 t ??CrossCallReturnLabel_7 +1000a318 t ??tcp_rexmit_3 +1000a324 t ??tcp_rexmit_4 +1000a32e t ??tcp_rexmit_0 +1000a332 t .text_18 +1000a332 t ?Subroutine2 +1000a334 t ??Subroutine2_0 +1000a33a T tcp_rexmit_fast +1000a33a t .text_19 +1000a384 t ??tcp_rexmit_fast_0 +1000a386 T tcp_keepalive +1000a386 t .text_20 +1000a396 t ??CrossCallReturnLabel_5 +1000a3a6 t ??CrossCallReturnLabel_23 +1000a3ac t ??CrossCallReturnLabel_21 +1000a3be t ??tcp_keepalive_0 +1000a3c0 t .text_21 +1000a3c0 t ?Subroutine6 +1000a3ca t .text_22 +1000a3ca t ?Subroutine1 +1000a3d6 T tcp_zero_window_probe +1000a3d6 t .text_23 +1000a3e2 t ??tcp_zero_window_probe_0 +1000a3ec t ??CrossCallReturnLabel_0 +1000a3fa t ??tcp_zero_window_probe_2 +1000a3fc t ??tcp_zero_window_probe_3 +1000a42e t ??tcp_zero_window_probe_4 +1000a440 t ??tcp_zero_window_probe_5 +1000a458 t ??CrossCallReturnLabel_22 +1000a46a t ??tcp_zero_window_probe_1 +1000a46e t .text_24 +1000a46e t ?Subroutine5 +1000a47c t .text_25 +1000a47c t ?Subroutine0 +1000a47e t ??Subroutine0_0 +1000a484 T xQueueGenericReset +1000a4c2 t ??CrossCallReturnLabel_8 +1000a4cc t ??xQueueGenericReset_0 +1000a4dc t ??xQueueGenericReset_1 +1000a4e4 T xQueueGenericCreate +1000a4e4 t .text_3 +1000a516 t ??xQueueGenericCreate_1 +1000a51c t ??xQueueGenericCreate_0 +1000a520 T xQueueCreateMutex +1000a520 t .text_4 +1000a55c t ??CrossCallReturnLabel_13 +1000a560 t .text_6 +1000a560 t ?Subroutine8 +1000a56a T xQueueCreateCountingSemaphore +1000a56a t .text_8 +1000a57a t ??xQueueCreateCountingSemaphore_0 +1000a57c T xQueueGenericSend +1000a57c t .text_9 +1000a588 t ??xQueueGenericSend_1 +1000a58c t ??CrossCallReturnLabel_18 +1000a590 t ??xQueueGenericSend_0 +1000a5a0 t ??xQueueGenericSend_2 +1000a5b2 t ??CrossCallReturnLabel_11 +1000a5b8 t ??xQueueGenericSend_4 +1000a5ba t ??xQueueGenericSend_6 +1000a5be t ??xQueueGenericSend_5 +1000a5c6 t ??xQueueGenericSend_3 +1000a5d0 t ??xQueueGenericSend_7 +1000a5da t ??xQueueGenericSend_9 +1000a626 t ??CrossCallReturnLabel_17 +1000a634 t ??xQueueGenericSend_10 +1000a63c t ??xQueueGenericSend_8 +1000a640 T xQueueGenericSendFromISR +1000a640 t .text_10 +1000a65e t ??xQueueGenericSendFromISR_0 +1000a694 t ??xQueueGenericSendFromISR_2 +1000a69a t ??xQueueGenericSendFromISR_3 +1000a69e t ??xQueueGenericSendFromISR_1 +1000a6a0 t ??xQueueGenericSendFromISR_4 +1000a6ac T xQueueGenericReceive +1000a6ac t .text_11 +1000a6bc t ??xQueueGenericReceive_1 +1000a6c0 t ??CrossCallReturnLabel_16 +1000a6c4 t ??xQueueGenericReceive_0 +1000a6e8 t ??xQueueGenericReceive_4 +1000a6f0 t ??CrossCallReturnLabel_7 +1000a6f6 t ??xQueueGenericReceive_3 +1000a700 t ??CrossCallReturnLabel_10 +1000a702 t ??xQueueGenericReceive_6 +1000a706 t ??xQueueGenericReceive_5 +1000a70e t ??xQueueGenericReceive_2 +1000a718 t ??xQueueGenericReceive_8 +1000a722 t ??xQueueGenericReceive_10 +1000a77a t ??xQueueGenericReceive_12 +1000a788 t ??CrossCallReturnLabel_15 +1000a796 t ??xQueueGenericReceive_11 +1000a79a t ??CrossCallReturnLabel_14 +1000a79e t ??xQueueGenericReceive_9 +1000a7a0 t ??xQueueGenericReceive_7 +1000a7a6 t .text_12 +1000a7a6 t ?Subroutine9 +1000a7aa t .text_13 +1000a7aa t ?Subroutine7 +1000a7b2 t .text_14 +1000a7b2 t ?Subroutine6 +1000a7ba T uxQueueMessagesWaiting +1000a7ba t .text_17 +1000a7c0 t ??CrossCallReturnLabel_5 +1000a7c4 t .text_19 +1000a7c4 t ?Subroutine0 +1000a7cc T vQueueDelete +1000a7cc t .text_21 +1000a7d8 t ??vQueueDelete_0 +1000a7e2 t .text_22 +1000a7e2 t prvCopyDataToQueue +1000a800 t ??prvCopyDataToQueue_0 +1000a81c t ??prvCopyDataToQueue_2 +1000a838 t ??prvCopyDataToQueue_3 +1000a846 t ??prvCopyDataToQueue_1 +1000a850 t .text_23 +1000a850 t prvCopyDataFromQueue +1000a874 t ??prvCopyDataFromQueue_0 +1000a876 t .text_24 +1000a876 t prvUnlockQueue +1000a87c t ??CrossCallReturnLabel_3 +1000a87e t ??prvUnlockQueue_1 +1000a882 t ??CrossCallReturnLabel_9 +1000a888 t ??prvUnlockQueue_2 +1000a88e t ??prvUnlockQueue_0 +1000a89a t ??prvUnlockQueue_3 +1000a8aa t ??prvUnlockQueue_5 +1000a8ae t ??CrossCallReturnLabel_6 +1000a8b4 t ??prvUnlockQueue_6 +1000a8ba t ??prvUnlockQueue_4 +1000a8c6 t ??prvUnlockQueue_7 +1000a8d0 t .text_25 +1000a8d0 t ?Subroutine5 +1000a8d6 t .text_27 +1000a8d6 t prvIsQueueFull +1000a8dc t ??CrossCallReturnLabel_2 +1000a8ea T vQueueWaitForMessageRestricted +1000a8ea t .text_37 +1000a91e t ??vQueueWaitForMessageRestricted_0 +1000a928 T xTaskGenericCreate +1000a94a t ??xTaskGenericCreate_1 +1000a954 t ??xTaskGenericCreate_0 +1000a95a t ??xTaskGenericCreate_2 +1000a994 t ??xTaskGenericCreate_4 +1000a9b8 t ??xTaskGenericCreate_7 +1000a9f8 t ??xTaskGenericCreate_5 +1000aa06 t ??xTaskGenericCreate_6 +1000aa3a t ??xTaskGenericCreate_3 +1000aa40 T vTaskDelete +1000aa40 t .text_5 +1000aa4c t ??CrossCallReturnLabel_9 +1000aa50 t ??CrossCallReturnLabel_0 +1000aa5a t ??vTaskDelete_0 +1000aa88 t ??vTaskDelete_1 +1000aa8a T vTaskDelayUntil +1000aa8a t .text_6 +1000aaa6 t ??vTaskDelayUntil_2 +1000aaaa t ??vTaskDelayUntil_0 +1000aaae t ??vTaskDelayUntil_1 +1000aab2 t ??vTaskDelayUntil_3 +1000aac0 t ??CrossCallReturnLabel_3 +1000aad2 T vTaskDelay +1000aad2 t .text_7 +1000aaf0 t ??CrossCallReturnLabel_2 +1000aaf6 t ??vTaskDelay_0 +1000aafe t ??vTaskDelay_1 +1000ab00 t .text_8 +1000ab00 t ?Subroutine8 +1000ab14 t ??Subroutine8_0 +1000ab18 T vTaskPrioritySet +1000ab18 t .text_10 +1000ab34 t ??vTaskPrioritySet_0 +1000ab4c t ??vTaskPrioritySet_2 +1000ab50 t ??vTaskPrioritySet_4 +1000ab52 t ??vTaskPrioritySet_3 +1000ab92 t ??vTaskPrioritySet_6 +1000abaa t ??vTaskPrioritySet_5 +1000abb0 t ??vTaskPrioritySet_1 +1000abb8 t .text_12 +1000abb8 t ?Subroutine11 +1000abc0 t ??Subroutine11_0 +1000abc6 t .text_13 +1000abc6 t ?Subroutine7 +1000abe6 t ??Subroutine7_0 +1000abea t .text_14 +1000abea t ?Subroutine0 +1000abf2 t .text_15 +1000abf2 t ??Subroutine17_0 +1000abfa T vTaskStartScheduler +1000abfa t .text_20 +1000ac3e t ??vTaskStartScheduler_0 +1000ac42 T vTaskSuspendAll +1000ac42 t .text_22 +1000ac4e t .text_23 +1000ac4e t prvGetExpectedIdleTime +1000ac62 t ??prvGetExpectedIdleTime_0 +1000ac66 t ??prvGetExpectedIdleTime_1 +1000ac6e T xTaskResumeAll +1000ac6e t .text_24 +1000ac8c t ??xTaskResumeAll_2 +1000acca t ??xTaskResumeAll_1 +1000acd6 t ??xTaskResumeAll_5 +1000ace0 t ??xTaskResumeAll_6 +1000ace6 t ??xTaskResumeAll_3 +1000acec t ??xTaskResumeAll_4 +1000acf8 t ??xTaskResumeAll_0 +1000acfa T xTaskGetTickCount +1000acfa t .text_25 +1000ad06 t .text_26 +1000ad06 t ?Subroutine2 +1000ad0e T pcTaskGetTaskName +1000ad0e t .text_29 +1000ad16 t ??pcTaskGetTaskName_0 +1000ad1a T vTaskStepTick +1000ad1a t .text_30 +1000ad26 T xTaskIncrementTick +1000ad26 t .text_31 +1000ad52 t ??xTaskIncrementTick_1 +1000ad62 t ??xTaskIncrementTick_4 +1000ad74 t ??xTaskIncrementTick_5 +1000ad98 t ??xTaskIncrementTick_3 +1000ada4 t ??xTaskIncrementTick_6 +1000adb0 t ??xTaskIncrementTick_7 +1000adb2 t ??xTaskIncrementTick_2 +1000adc4 t ??xTaskIncrementTick_0 +1000adca t ??xTaskIncrementTick_8 +1000add0 t ??xTaskIncrementTick_9 +1000add6 T vTaskSwitchContext +1000add6 t .text_32 +1000ade6 t ??vTaskSwitchContext_0 +1000adf8 t ??CrossCallReturnLabel_20 +1000ae0c t ??CrossCallReturnLabel_19 +1000ae3c t .text_33 +1000ae3c t ?Subroutine14 +1000ae48 T vTaskPlaceOnEventList +1000ae48 t .text_34 +1000ae4e t ??CrossCallReturnLabel_21 +1000ae56 t ??CrossCallReturnLabel_12 +1000ae5a t ??CrossCallReturnLabel_4 +1000ae5e t ??vTaskPlaceOnEventList_0 +1000ae60 t .text_36 +1000ae60 t ?Subroutine12 +1000ae68 t .text_37 +1000ae68 t ?Subroutine9 +1000ae7c t ??Subroutine9_0 +1000ae82 t .text_38 +1000ae82 t ?Subroutine5 +1000ae92 t .text_39 +1000ae92 t ?Subroutine4 +1000ae9c T vTaskPlaceOnEventListRestricted +1000ae9c t .text_40 +1000aea2 t ??CrossCallReturnLabel_22 +1000aeaa t ??CrossCallReturnLabel_10 +1000aebe t ??vTaskPlaceOnEventListRestricted_0 +1000aec0 t .text_41 +1000aec0 t ?Subroutine15 +1000aeca T xTaskRemoveFromEventList +1000aeca t .text_42 +1000aee2 t ??CrossCallReturnLabel_16 +1000aee6 t ??CrossCallReturnLabel_6 +1000aee8 t ??xTaskRemoveFromEventList_0 +1000aeee t ??xTaskRemoveFromEventList_1 +1000aefe t ??xTaskRemoveFromEventList_2 +1000af02 t .text_44 +1000af02 t ?Subroutine13 +1000af08 t .text_45 +1000af08 t ?Subroutine10 +1000af22 t .text_46 +1000af22 t ?Subroutine6 +1000af28 T vTaskSetTimeOutState +1000af28 t .text_47 +1000af34 T xTaskCheckForTimeOut +1000af34 t .text_48 +1000af58 t ??xTaskCheckForTimeOut_1 +1000af6a t ??xTaskCheckForTimeOut_0 +1000af6e t ??xTaskCheckForTimeOut_2 +1000af70 t .text_49 +1000af70 t ??xTaskCheckForTimeOut_3 +1000af70 t ?Subroutine1 +1000af78 T vTaskMissedYield +1000af78 t .text_50 +1000af84 t .text_51 +1000af84 t prvIdleTask +1000af88 t ??prvIdleTask_1 +1000afc4 t ??prvIdleTask_0 +1000aff2 t ??prvIdleTask_2 +1000aff8 T eTaskConfirmSleepModeStatus +1000aff8 t .text_52 +1000b00a t .text_53 +1000b00a t prvInitialiseTCBVariables +1000b012 t ??prvInitialiseTCBVariables_0 +1000b024 t ??prvInitialiseTCBVariables_1 +1000b054 t .text_54 +1000b054 t prvAddCurrentTaskToDelayedList +1000b072 t ??prvAddCurrentTaskToDelayedList_0 +1000b084 t .text_55 +1000b084 t prvResetNextTaskUnblockTime +1000b092 t ??prvResetNextTaskUnblockTime_0 +1000b09a t ??prvResetNextTaskUnblockTime_1 +1000b09e T xTaskGetSchedulerState +1000b09e t .text_57 +1000b0a8 t ??xTaskGetSchedulerState_0 +1000b0b0 t ??xTaskGetSchedulerState_1 +1000b0b4 T vTaskPriorityInherit +1000b0b4 t .text_58 +1000b0d8 t ??vTaskPriorityInherit_1 +1000b0f0 t ??CrossCallReturnLabel_14 +1000b10c t ??vTaskPriorityInherit_3 +1000b12a t ??vTaskPriorityInherit_2 +1000b130 t ??vTaskPriorityInherit_0 +1000b134 T xTaskPriorityDisinherit +1000b134 t .text_59 +1000b15c t ??CrossCallReturnLabel_13 +1000b178 t ??xTaskPriorityDisinherit_1 +1000b19a t ??xTaskPriorityDisinherit_0 +1000b19e T pvTaskIncrementMutexHeldCount +1000b19e t .text_61 +1000b1ac t ??pvTaskIncrementMutexHeldCount_0 +1000b1b0 t ??DataTable40 +1000b1b4 t ??DataTable40_1 +1000b1b8 t ?_0 +1000b1c0 t ??ucExpectedStackBytes +1000b1d4 T pxPortInitialiseStack +1000b1f0 t .text_5 +1000b1f0 t prvTaskExitError +1000b1f6 t ??prvTaskExitError_0 +1000b1f8 T xPortStartScheduler +1000b1f8 t .text_6 +1000b21e T vPortYield +1000b21e t .text_8 +1000b230 T vPortEnterCritical +1000b230 t .text_9 +1000b248 T vPortExitCritical +1000b248 t .text_10 +1000b25a T xPortSysTickHandler +1000b25a t .text_11 +1000b26e t ??xPortSysTickHandler_0 +1000b278 W vPortSuppressTicksAndSleep +1000b278 t .text_12 +1000b2c6 t ??vPortSuppressTicksAndSleep_0 +1000b2ea t ??vPortSuppressTicksAndSleep_2 +1000b310 t ??vPortSuppressTicksAndSleep_3 +1000b326 t ??vPortSuppressTicksAndSleep_4 +1000b346 t ??vPortSuppressTicksAndSleep_1 +1000b34a W vPortSetupTimerInterrupt +1000b34a t .text_13 +1000b378 t ??DataTable8 +1000b37c t ??DataTable8_1 +1000b380 t ??DataTable8_2 +1000b384 t ??DataTable8_3 +1000b388 t ??DataTable8_4 +1000b38c t ??DataTable8_5 +1000b390 T vApplicationIdleHook +1000b390 t .text_20 +1000b392 T vApplicationStackOverflowHook +1000b392 t .text_21 +1000b3a2 t ??vApplicationStackOverflowHook_0 +1000b3a4 t ??__FUNCTION__ +1000b3c4 t ?_0 +1000b3ec t tcpip_tcp_timer +1000b408 t ??tcpip_tcp_timer_0 +1000b40e T tcp_timer_needed +1000b40e t .text_5 +1000b42a t ??tcp_timer_needed_0 +1000b42c t .text_6 +1000b42c t ?Subroutine1 +1000b434 t .text_7 +1000b434 t ip_reass_timer +1000b448 t .text_8 +1000b448 t arp_timer +1000b45c t .text_9 +1000b45c t dhcp_timer_coarse +1000b470 t .text_10 +1000b470 t dhcp_timer_fine +1000b484 t .text_11 +1000b484 t autoip_timer +1000b48c T sys_timeouts_init +1000b48c t .text_12 +1000b4be t .text_13 +1000b4be t ?Subroutine0 +1000b4c8 T sys_timeout +1000b4c8 t .text_14 +1000b4f4 t ??sys_timeout_1 +1000b4f8 t ??sys_timeout_3 +1000b4fa t ??sys_timeout_2 +1000b50c t ??sys_timeout_4 +1000b514 t ??sys_timeout_5 +1000b518 t ??sys_timeout_0 +1000b51a T sys_untimeout +1000b51a t .text_15 +1000b522 t ??sys_untimeout_0 +1000b526 t ??sys_untimeout_1 +1000b548 t ??sys_untimeout_3 +1000b554 t ??sys_untimeout_2 +1000b55e T sys_timeouts_mbox_fetch +1000b55e t .text_16 +1000b56a t ??sys_timeouts_mbox_fetch_1 +1000b582 t ??sys_timeouts_mbox_fetch_0 +1000b594 t ??sys_timeouts_mbox_fetch_2 +1000b5bc t ??DataTable9 +1000b5c0 t ??DataTable9_1 +1000b5c4 t ??DataTable9_2 +1000b5c8 t ??DataTable9_3 +1000b5cc t ??DataTable9_4 +1000b5d0 t ??DataTable9_5 +1000b5d4 t ??DataTable9_6 +1000b5d8 t ??DataTable9_7 +1000b5dc t ??DataTable9_8 +1000b5e0 t ??DataTable9_9 +1000b5e4 t etharp_free_entry +1000b5fc t ??etharp_free_entry_0 +1000b614 T etharp_tmr +1000b614 t .text_5 +1000b618 t ??etharp_tmr_0 +1000b63e t ??etharp_tmr_2 +1000b646 t ??etharp_tmr_3 +1000b650 t ??etharp_tmr_1 +1000b658 t .text_6 +1000b658 t etharp_find_entry +1000b670 t ??etharp_find_entry_0 +1000b69e t ??etharp_find_entry_2 +1000b6ba t ??etharp_find_entry_5 +1000b6c4 t ??etharp_find_entry_4 +1000b6d2 t ??etharp_find_entry_1 +1000b6e6 t ??etharp_find_entry_6 +1000b6ec t ??etharp_find_entry_7 +1000b6f4 t ??etharp_find_entry_8 +1000b70e t ??etharp_find_entry_11 +1000b714 t ??etharp_find_entry_10 +1000b726 t ??etharp_find_entry_12 +1000b72a t ??etharp_find_entry_3 +1000b72c t ??etharp_find_entry_9 +1000b730 t .text_7 +1000b730 t etharp_send_ip +1000b75c t __iar_annotation$$tailcall +1000b75e T etharp_cleanup_netif +1000b75e t .text_8 +1000b764 t ??etharp_cleanup_netif_0 +1000b77e t ??etharp_cleanup_netif_1 +1000b786 t .text_10 +1000b786 t etharp_arp_input +1000b7f4 t ??etharp_arp_input_2 +1000b7fa t ??etharp_arp_input_3 +1000b866 t ??CrossCallReturnLabel_4 +1000b86c t ??etharp_arp_input_4 +1000b882 t ??etharp_arp_input_1 +1000b884 t ??etharp_arp_input_5 +1000b8f6 t ??etharp_arp_input_6 +1000b8fc t ??etharp_arp_input_0 +1000b902 t .text_11 +1000b902 t ?Subroutine1 +1000b904 t ??Subroutine1_0 +1000b908 t .text_12 +1000b908 t etharp_output_to_arp_index +1000b930 t ??etharp_output_to_arp_index_0 +1000b942 T etharp_output +1000b942 t .text_13 +1000b95e t ??etharp_output_0 +1000b96c t ??etharp_output_2 +1000b976 t ??CrossCallReturnLabel_2 +1000b978 t ??etharp_output_1 +1000b9ae t ??etharp_output_3 +1000b9e2 t ??etharp_output_4 +1000b9ee t ??CrossCallReturnLabel_0 +1000b9fa t ??etharp_output_7 +1000ba04 t ??etharp_output_5 +1000ba0a t ??etharp_output_6 +1000ba0c t ??etharp_output_8 +1000ba10 t ??CrossCallReturnLabel_1 +1000ba22 t ??etharp_output_9 +1000ba36 t .text_14 +1000ba36 t ?Subroutine0 +1000ba44 T etharp_query +1000ba44 t .text_15 +1000ba74 t ??etharp_query_0 +1000ba7a t ??etharp_query_1 +1000ba9c t ??etharp_query_3 +1000bab2 t ??etharp_query_4 +1000bac8 t ??CrossCallReturnLabel_3 +1000bacc t ??etharp_query_6 +1000bad4 t ??etharp_query_8 +1000bad6 t ??etharp_query_7 +1000bafa t ??etharp_query_10 +1000bafc t ??etharp_query_5 +1000bafe t ??etharp_query_2 +1000bb02 t ??etharp_query_9 +1000bb0e t ??etharp_query_11 +1000bb1c t ??etharp_query_12 +1000bb2c t ??DataTable10 +1000bb30 t ??DataTable10_1 +1000bb34 T etharp_raw +1000bb34 t .text_18 +1000bbe4 t ??etharp_raw_0 +1000bbe8 T etharp_request +1000bbe8 t .text_19 +1000bc10 T ethernet_input +1000bc10 t .text_20 +1000bc3e t ??ethernet_input_2 +1000bc50 t ??ethernet_input_3 +1000bc52 t ??ethernet_input_1 +1000bc5e t ??ethernet_input_4 +1000bc7c t ??ethernet_input_5 +1000bc92 t ??ethernet_input_0 +1000bc98 t ??ethernet_input_6 +1000bc9c T ethbroadcast +1000bc9c t .text_21 +1000bca4 T ethzero +1000bca4 t .text_22 +1000bcac T ip_route +1000bcb0 t ??ip_route_0 +1000bcce t ??ip_route_1 +1000bcdc t ??ip_route_2 +1000bcde t ??ip_route_3 +1000bce0 T ip_input +1000bce0 t .text_5 +1000bd36 t ??ip_input_1 +1000bd62 t ??ip_input_2 +1000bd7e t ??ip_input_3 +1000bd80 t ??ip_input_4 +1000bd94 t ??ip_input_5 +1000bdaa t ??ip_input_6 +1000bdac t ??ip_input_0 +1000bdb4 t ??ip_input_7 +1000bdc8 t ??ip_input_8 +1000bdcc t ??ip_input_10 +1000bdce t ??ip_input_9 +1000bdf6 t ??ip_input_14 +1000be00 t ??ip_input_13 +1000be0a t ??ip_input_15 +1000be26 t ??ip_input_16 +1000be2c t ??ip_input_12 +1000be36 t ??ip_input_11 +1000be3a T ip_output_if +1000be3a t .text_6 +1000be5c t ??ip_output_if_1 +1000bed2 t ??ip_output_if_0 +1000bedc t ??ip_output_if_3 +1000bef2 t ??ip_output_if_4 +1000befc t ??ip_output_if_2 +1000bf00 t ??DataTable2 +1000bf04 t ??DataTable2_1 +1000bf08 t ??DataTable2_2 +1000bf0c t ??DataTable2_3 +1000bf10 T ip_output +1000bf10 t .text_11 +1000bf28 t ??ip_output_0 +1000bf40 T lwip_init +1000bf68 T mem_init +1000bf9e T mem_free +1000bf9e t .text_4 +1000bfb2 t ??mem_free_1 +1000bfbe t ??mem_free_2 +1000c002 t ??mem_free_3 +1000c022 t ??mem_free_4 +1000c02c t ??mem_free_0 +1000c02e T mem_trim +1000c02e t .text_5 +1000c04c t ??mem_trim_0 +1000c05a t ??mem_trim_2 +1000c064 t ??mem_trim_3 +1000c078 t ??mem_trim_1 +1000c07c t ??mem_trim_5 +1000c0c8 t ??mem_trim_7 +1000c0e8 t ??mem_trim_8 +1000c0f2 t ??mem_trim_9 +1000c0f8 t ??mem_trim_4 +1000c0fa t ??mem_trim_6 +1000c0fe T mem_malloc +1000c0fe t .text_6 +1000c114 t ??mem_malloc_2 +1000c12c t ??mem_malloc_1 +1000c132 t ??mem_malloc_0 +1000c136 t ??mem_malloc_4 +1000c138 t ??mem_malloc_3 +1000c192 t ??mem_malloc_6 +1000c196 t ??mem_malloc_7 +1000c19c t ??mem_malloc_10 +1000c1a0 t ??mem_malloc_9 +1000c1ae t ??mem_malloc_8 +1000c1ba t ??mem_malloc_5 +1000c1c4 t ??DataTable3 +1000c1c8 t ?Veneer (6) for __rom_mallocr_init_v1_00 +1000c1d0 t ?Veneer (6) for __rtl_vfprintf_r_v1_00 +1000c1d8 t ?Veneer (6) for __rtl_fflush_r_v1_00 +1000c1e0 t ?Veneer (6) for __rtl_memcmp_v1_00 +1000c1e8 t ?Veneer (6) for __rtl_memcpy_v1_00 +1000c1f0 t ?Veneer (6) for __rtl_memset_v1_00 +1000c1f8 t ?Veneer (6) for __rtl_strcmp_v1_00 +1000c200 t ?Veneer (6) for __rtl_strcpy_v1_00 +1000c208 t ?Veneer (6) for __rtl_strlen_v1_00 +1000c210 t ?Veneer (6) for __rtl_strncmp_v1_00 +1000c218 t ?Veneer (6) for __rtl_strncpy_v1_00 +1000c220 t ?Veneer (6) for __rtl_strstr_v1_00 +1000c228 t ?Veneer (6) for __rtl_strsep_v1_00 +1000c230 T rtl_snprintf +1000c230 t .text_4 +1000c2ac T rtl_sprintf +1000c2ac t .text_5 +1000c302 T rtl_printf +1000c302 t .text_6 +1000c33c t .text_8 +1000c340 t .text_9 +1000c344 T rtl_memcmp +1000c344 t .text_12 +1000c348 T rtl_memcpy +1000c348 t .text_13 +1000c34c T rtl_memset +1000c34c t .text_15 +1000c350 T rtl_strcmp +1000c350 t .text_18 +1000c354 T rtl_strcpy +1000c354 t .text_19 +1000c358 T rtl_strlen +1000c358 t .text_20 +1000c35c T rtl_strncmp +1000c35c t .text_22 +1000c360 T rtl_strncpy +1000c360 t .text_23 +1000c364 T rtl_strstr +1000c364 t .text_24 +1000c368 T rtl_strsep +1000c368 t .text_25 +1000c36c T ip4_addr_isbroadcast +1000c398 t ??ip4_addr_isbroadcast_0 +1000c39c t ??ip4_addr_isbroadcast_1 +1000c3a0 T ipaddr_addr +1000c3a0 t .text_5 +1000c3ae t ??ipaddr_addr_0 +1000c3b4 T ipaddr_aton +1000c3b4 t .text_6 +1000c3c2 t ??ipaddr_aton_1 +1000c3d0 t ??ipaddr_aton_0 +1000c3f2 t ??ipaddr_aton_5 +1000c3f8 t ??ipaddr_aton_4 +1000c3fc t ??ipaddr_aton_3 +1000c42a t ??ipaddr_aton_6 +1000c450 t ??ipaddr_aton_7 +1000c470 t ??ipaddr_aton_8 +1000c47a t ??ipaddr_aton_9 +1000c486 t ??ipaddr_aton_10 +1000c48a t ??ipaddr_aton_2 +1000c48e t ??ipaddr_aton_13 +1000c498 t ??ipaddr_aton_12 +1000c49a t ??ipaddr_aton_11 +1000c4a4 t ??ipaddr_aton_15 +1000c4a6 t ??ipaddr_aton_14 +1000c4ac T ipaddr_ntoa +1000c4ac t .text_7 +1000c4b4 t ??ipaddr_ntoa_0 +1000c4b8 T ipaddr_ntoa_r +1000c4b8 t .text_8 +1000c4b8 t ??ipaddr_ntoa_1 +1000c4d2 t ??ipaddr_ntoa_r_0 +1000c4d4 t ??ipaddr_ntoa_r_1 +1000c4fc t ??ipaddr_ntoa_r_2 +1000c524 t ??ipaddr_ntoa_r_3 +1000c52c t ??ipaddr_ntoa_r_4 +1000c530 t ??ipaddr_ntoa_r_5 +1000c542 t ??ipaddr_ntoa_r_6 +1000c546 T lwip_htons +1000c550 T lwip_ntohs +1000c550 t .text_3 +1000c552 T lwip_htonl +1000c552 t .text_4 +1000c56a T lwip_ntohl +1000c56a t .text_5 +1000c56c t lwip_standard_chksum +1000c58c t ??lwip_standard_chksum_1 +1000c594 t ??lwip_standard_chksum_0 +1000c5c0 t ??lwip_standard_chksum_2 +1000c5c4 T inet_chksum_pseudo +1000c5c4 t .text_3 +1000c5d6 t ??inet_chksum_pseudo_1 +1000c5fa t ??inet_chksum_pseudo_2 +1000c5fc t ??inet_chksum_pseudo_0 +1000c60e t ??inet_chksum_pseudo_3 +1000c646 T inet_chksum +1000c646 t .text_5 +1000c652 T inet_chksum_pbuf +1000c652 t .text_6 +1000c65c t ??inet_chksum_pbuf_1 +1000c680 t ??inet_chksum_pbuf_2 +1000c682 t ??inet_chksum_pbuf_0 +1000c694 t ??inet_chksum_pbuf_3 +1000c69c T icmp_input +1000c6be t ??CrossCallReturnLabel_2 +1000c704 t ??CrossCallReturnLabel_1 +1000c70a t ??CrossCallReturnLabel_4 +1000c73e t ??icmp_input_1 +1000c746 t ??CrossCallReturnLabel_0 +1000c748 t ??icmp_input_2 +1000c77e t ??CrossCallReturnLabel_3 +1000c798 t ??icmp_input_0 +1000c7a4 t ??DataTable0 +1000c7a8 t ??DataTable0_1 +1000c7ac t .text_5 +1000c7ac t ?Subroutine0 +1000c7ae t ??Subroutine0_0 +1000c7b4 T icmp_dest_unreach +1000c7b4 t .text_6 +1000c7ba T icmp_time_exceeded +1000c7ba t .text_7 +1000c7be t .text_8 +1000c7be t icmp_send_response +1000c820 t ??icmp_send_response_0 +1000c824 T vListInitialise +1000c83e T vListInitialiseItem +1000c83e t .text_3 +1000c844 T vListInsertEnd +1000c844 t .text_4 +1000c85c T vListInsert +1000c85c t .text_5 +1000c870 t ??vListInsert_2 +1000c872 t ??vListInsert_1 +1000c87a t ??vListInsert_0 +1000c88e T uxListRemove +1000c88e t .text_6 +1000c8b4 T pvPortMalloc +1000c8de t ??pvPortMalloc_1 +1000c902 t ??pvPortMalloc_0 +1000c91c t ??pvPortMalloc_3 +1000c92a t ??pvPortMalloc_5 +1000c92e t ??pvPortMalloc_4 +1000c93a t ??pvPortMalloc_6 +1000c95c t ??pvPortMalloc_7 +1000c978 t ??pvPortMalloc_2 +1000c980 T __vPortFree +1000c980 t .text_6 +1000c984 t ??__vPortFree_0 +1000c9b6 t ??__vPortFree_1 +1000c9b8 T vPortSetExtFree +1000c9b8 t .text_7 +1000c9c2 T vPortFree +1000c9c2 t .text_8 +1000c9d6 t __iar_annotation$$tailcall +1000c9d8 t ??vPortFree_0 +1000c9da t ??vPortFree_1 +1000c9dc T xPortGetFreeHeapSize +1000c9dc t .text_9 +1000c9e2 t .text_12 +1000c9e2 t prvInsertBlockIntoFreeList +1000c9ea t ??prvInsertBlockIntoFreeList_1 +1000c9ec t ??prvInsertBlockIntoFreeList_0 +1000ca02 t ??prvInsertBlockIntoFreeList_2 +1000ca1c t ??prvInsertBlockIntoFreeList_4 +1000ca1e t ??prvInsertBlockIntoFreeList_3 +1000ca28 t ??DataTable6 +1000ca2c t ??DataTable6_1 +1000ca30 t ??DataTable6_2 +1000ca34 T xTimerCreateTimerTask +1000ca60 t ??xTimerCreateTimerTask_0 +1000ca66 T xTimerCreate +1000ca66 t .text_4 +1000ca9a t ??xTimerCreate_0 +1000caa0 T xTimerGenericCommand +1000caa0 t .text_5 +1000cac8 t ??xTimerGenericCommand_2 +1000cace t ??xTimerGenericCommand_3 +1000cad6 t ??xTimerGenericCommand_1 +1000cade t ??xTimerGenericCommand_4 +1000cae0 t ??xTimerGenericCommand_0 +1000cae8 t .text_7 +1000cae8 t prvTimerTask +1000caf0 t ??prvTimerTask_1 +1000caf4 t ??prvTimerTask_2 +1000caf8 t ??prvTimerTask_0 +1000cb04 t ??prvTimerTask_3 +1000cb0a t ??prvTimerTask_4 +1000cb5a t ??prvTimerTask_6 +1000cb62 t ??prvTimerTask_5 +1000cb78 t .text_8 +1000cb78 t prvSampleTimeNow +1000cb90 t ??prvSampleTimeNow_1 +1000cb9a t ??prvSampleTimeNow_2 +1000cba6 t ??prvSampleTimeNow_0 +1000cbe0 t ??prvSampleTimeNow_3 +1000cbea t .text_9 +1000cbea t prvInsertTimerInActiveList +1000cc06 t ??prvInsertTimerInActiveList_0 +1000cc0e t ??prvInsertTimerInActiveList_1 +1000cc12 t ??prvInsertTimerInActiveList_3 +1000cc16 t ??prvInsertTimerInActiveList_2 +1000cc1a t ??prvInsertTimerInActiveList_4 +1000cc20 t .text_10 +1000cc20 t prvProcessReceivedCommands +1000cc26 t ??prvProcessReceivedCommands_2 +1000cc34 t ??prvProcessReceivedCommands_1 +1000cc54 t ??prvProcessReceivedCommands_4 +1000cc66 t ??prvProcessReceivedCommands_5 +1000cc78 t ??prvProcessReceivedCommands_0 +1000cc82 t ??prvProcessReceivedCommands_6 +1000cc84 t ??prvProcessReceivedCommands_7 +1000cc86 t ??prvProcessReceivedCommands_8 +1000ccba t ??prvProcessReceivedCommands_9 +1000ccc2 t ??prvProcessReceivedCommands_3 +1000ccc6 t .text_11 +1000ccc6 t prvCheckForValidListAndQueue +1000ccfa t ??prvCheckForValidListAndQueue_0 +1000cd02 T xTimerIsTimerActive +1000cd02 t .text_12 +1000cd1c t ??DataTable8 +1000cd20 t ?_0 +1000cd28 T freertos_ready_to_sleep +1000cd28 t .text_6 +1000cd34 T freertos_pre_sleep_processing +1000cd34 t .text_7 +1000cd5c T acquire_wakelock +1000cd5c t .text_8 +1000cd60 T release_wakelock +1000cd60 t .text_9 +1000cd6c T get_wakelock_status +1000cd6c t .text_10 +1000cd72 t .text_12 +1000cd72 t ?Subroutine0 +1000cd7c t ??DataTable5 +1000cd80 t ??DataTable5_1 +1000cd84 T ip_reass_tmr +1000cd90 t ??ip_reass_tmr_1 +1000cd98 t ??ip_reass_tmr_0 +1000cdae t ??ip_reass_tmr_2 +1000cdb0 t .text_4 +1000cdb0 t ip_reass_free_complete_datagram +1000cde8 t ??ip_reass_free_complete_datagram_0 +1000cdec t ??ip_reass_free_complete_datagram_2 +1000ce02 t ??ip_reass_free_complete_datagram_1 +1000ce1e t .text_5 +1000ce1e t ip_reass_remove_oldest_datagram +1000ce26 t ??ip_reass_remove_oldest_datagram_0 +1000ce36 t ??ip_reass_remove_oldest_datagram_2 +1000ce40 t ??ip_reass_remove_oldest_datagram_4 +1000ce42 t ??ip_reass_remove_oldest_datagram_3 +1000ce48 t ??ip_reass_remove_oldest_datagram_5 +1000ce4a t ??ip_reass_remove_oldest_datagram_1 +1000ce72 t ??ip_reass_remove_oldest_datagram_6 +1000ce7a t ??ip_reass_remove_oldest_datagram_7 +1000ce82 t ??ip_reass_remove_oldest_datagram_8 +1000ce86 t .text_6 +1000ce86 t ip_reass_dequeue_datagram +1000cea4 t .text_7 +1000cea4 t ip_reass_chain_frag_into_datagram_and_validate +1000cee4 t ??ip_reass_chain_frag_into_datagram_and_validat_1 +1000cefe t ??ip_reass_chain_frag_into_datagram_and_validat_0 +1000cf12 t ??ip_reass_chain_frag_into_datagram_and_validat_5 +1000cf16 t ??ip_reass_chain_frag_into_datagram_and_validat_4 +1000cf26 t ??ip_reass_chain_frag_into_datagram_and_validat_3 +1000cf36 t ??ip_reass_chain_frag_into_datagram_and_validat_6 +1000cf46 t ??ip_reass_chain_frag_into_datagram_and_validat_10 +1000cf56 t ??ip_reass_chain_frag_into_datagram_and_validat_9 +1000cf58 t ??ip_reass_chain_frag_into_datagram_and_validat_8 +1000cf5c t ??ip_reass_chain_frag_into_datagram_and_validat_2 +1000cf70 t ??ip_reass_chain_frag_into_datagram_and_validat_7 +1000cf72 t ??ip_reass_chain_frag_into_datagram_and_validat_11 +1000cf76 T ip_reass +1000cf76 t .text_8 +1000cfd4 t ??ip_reass_1 +1000cfd8 t ??ip_reass_3 +1000cff4 t ??ip_reass_2 +1000d018 t ??ip_reass_6 +1000d01c t ??ip_reass_5 +1000d036 t ??CrossCallReturnLabel_1 +1000d038 t ??ip_reass_0 +1000d040 t ??ip_reass_7 +1000d044 t ??ip_reass_4 +1000d05e t ??CrossCallReturnLabel_0 +1000d078 t ??ip_reass_8 +1000d0ba t ??ip_reass_10 +1000d0d0 t ??ip_reass_9 +1000d0ec t .text_9 +1000d0ec t ?Subroutine0 +1000d0f6 t .text_10 +1000d0f6 t ip_frag_free_pbuf_custom_ref +1000d0fe t .text_11 +1000d0fe t ipfrag_free_pbuf_custom +1000d10a t ??ipfrag_free_pbuf_custom_0 +1000d112 T ip_frag +1000d112 t .text_12 +1000d154 t ??ip_frag_1 +1000d174 t ??ip_frag_3 +1000d1c4 t ??ip_frag_0 +1000d224 t ??ip_frag_2 +1000d226 t ??ip_frag_6 +1000d25e t ??ip_frag_7 +1000d264 t ??ip_frag_5 +1000d268 t ??ip_frag_4 +1000d270 t ??DataTable6 +1000d274 t ??DataTable6_1 +1000d278 t dhcp_check +1000d29e t .text_5 +1000d29e t dhcp_select +1000d2ac t ??CrossCallReturnLabel_5 +1000d2b0 t ??CrossCallReturnLabel_57 +1000d2b8 t ??CrossCallReturnLabel_16 +1000d2bc t ??CrossCallReturnLabel_41 +1000d2c4 t ??CrossCallReturnLabel_11 +1000d2ce t ??CrossCallReturnLabel_45 +1000d2d6 t ??CrossCallReturnLabel_10 +1000d2e0 t ??CrossCallReturnLabel_44 +1000d2e8 t ??CrossCallReturnLabel_9 +1000d2ec t ??CrossCallReturnLabel_24 +1000d2f2 t ??CrossCallReturnLabel_22 +1000d2f8 t ??CrossCallReturnLabel_21 +1000d2fe t ??CrossCallReturnLabel_20 +1000d302 t ??CrossCallReturnLabel_30 +1000d306 t ??CrossCallReturnLabel_63 +1000d30a t ??CrossCallReturnLabel_68 +1000d30e t ??CrossCallReturnLabel_36 +1000d310 T dhcp_coarse_tmr +1000d310 t .text_6 +1000d31a t ??dhcp_coarse_tmr_1 +1000d334 t ??dhcp_coarse_tmr_2 +1000d336 t ??dhcp_coarse_tmr_0 +1000d35a t ??dhcp_coarse_tmr_3 +1000d35c T dhcp_fine_tmr +1000d35c t .text_7 +1000d366 t ??dhcp_fine_tmr_1 +1000d374 t ??dhcp_fine_tmr_2 +1000d376 t ??dhcp_fine_tmr_0 +1000d38a t ??dhcp_fine_tmr_3 +1000d38c t .text_8 +1000d38c t dhcp_timeout +1000d3b0 t ??dhcp_timeout_1 +1000d3ca t ??dhcp_timeout_3 +1000d3d6 t ??dhcp_timeout_4 +1000d3e8 t ??dhcp_timeout_2 +1000d3f2 t ??dhcp_timeout_5 +1000d406 t ??dhcp_timeout_0 +1000d40c t ??dhcp_timeout_6 +1000d40e T dhcp_start +1000d40e t .text_11 +1000d426 t ??dhcp_start_0 +1000d42a t ??dhcp_start_1 +1000d442 t ??dhcp_start_3 +1000d44a t ??dhcp_start_4 +1000d44e t ??CrossCallReturnLabel_71 +1000d490 t ??dhcp_start_2 +1000d494 t ??dhcp_start_5 +1000d4a0 t .text_12 +1000d4a0 t ?Subroutine17 +1000d4aa T dhcp_arp_reply +1000d4aa t .text_15 +1000d4ca t ??CrossCallReturnLabel_4 +1000d4de t ??CrossCallReturnLabel_8 +1000d4e8 t ??CrossCallReturnLabel_43 +1000d4ec t ??CrossCallReturnLabel_29 +1000d4f0 t ??CrossCallReturnLabel_62 +1000d4f6 t ??CrossCallReturnLabel_64 +1000d4fa t ??CrossCallReturnLabel_35 +1000d504 t ??dhcp_arp_reply_0 +1000d506 t .text_16 +1000d506 t ?Subroutine10 +1000d50c t .text_17 +1000d50c t dhcp_discover +1000d51e t ??CrossCallReturnLabel_3 +1000d530 t ??CrossCallReturnLabel_15 +1000d534 t ??CrossCallReturnLabel_40 +1000d53c t ??CrossCallReturnLabel_7 +1000d540 t ??CrossCallReturnLabel_23 +1000d546 t ??CrossCallReturnLabel_19 +1000d54c t ??CrossCallReturnLabel_18 +1000d552 t ??CrossCallReturnLabel_17 +1000d556 t ??CrossCallReturnLabel_28 +1000d55a t ??CrossCallReturnLabel_61 +1000d55e t ??CrossCallReturnLabel_67 +1000d562 t .text_18 +1000d562 t ??CrossCallReturnLabel_34 +1000d562 t ?Subroutine0 +1000d582 t ??Subroutine0_0 +1000d586 t ??Subroutine0_1 +1000d58e t .text_19 +1000d58e t ??Subroutine21_0 +1000d594 t .text_20 +1000d594 t ?Subroutine15 +1000d596 t ??Subroutine15_0 +1000d5a4 t .text_21 +1000d5a4 t ?Subroutine9 +1000d5a6 t ??Subroutine9_0 +1000d5aa t .text_22 +1000d5aa t ?Subroutine6 +1000d5ac t ??Subroutine6_0 +1000d5b0 t .text_23 +1000d5b0 t dhcp_bind +1000d5d4 t ??CrossCallReturnLabel_73 +1000d5e2 t ??dhcp_bind_1 +1000d5ee t ??CrossCallReturnLabel_74 +1000d5fc t ??dhcp_bind_2 +1000d60a t ??dhcp_bind_3 +1000d612 t ??dhcp_bind_4 +1000d624 t ??dhcp_bind_5 +1000d638 t ??dhcp_bind_6 +1000d63c t ??CrossCallReturnLabel_51 +1000d65a t ??dhcp_bind_0 +1000d65c t .text_24 +1000d65c t ?Subroutine18 +1000d66a T dhcp_renew +1000d66a t .text_25 +1000d678 t ??CrossCallReturnLabel_2 +1000d67c t ??CrossCallReturnLabel_56 +1000d684 t ??CrossCallReturnLabel_14 +1000d688 t ??CrossCallReturnLabel_39 +1000d68c t ??CrossCallReturnLabel_27 +1000d690 t ??CrossCallReturnLabel_60 +1000d6a4 t ??CrossCallReturnLabel_33 +1000d6c6 t ??dhcp_renew_0 +1000d6c8 t ??dhcp_renew_1 +1000d6ca t .text_26 +1000d6ca t ?Subroutine14 +1000d6d8 t .text_27 +1000d6d8 t ?Subroutine8 +1000d6dc t .text_28 +1000d6dc t ?Subroutine7 +1000d6e0 t .text_29 +1000d6e0 t ?Subroutine4 +1000d6e4 t .text_30 +1000d6e4 t dhcp_rebind +1000d6f2 t ??CrossCallReturnLabel_1 +1000d6f6 t ??CrossCallReturnLabel_55 +1000d6fe t ??CrossCallReturnLabel_13 +1000d702 t ??CrossCallReturnLabel_38 +1000d706 t ??CrossCallReturnLabel_26 +1000d70a t ??CrossCallReturnLabel_59 +1000d70e t ??CrossCallReturnLabel_66 +1000d712 t ??CrossCallReturnLabel_32 +1000d734 t ??dhcp_rebind_0 +1000d736 t ??dhcp_rebind_1 +1000d738 t .text_31 +1000d738 t ?Subroutine13 +1000d740 t .text_32 +1000d740 t dhcp_reboot +1000d74e t ??CrossCallReturnLabel_0 +1000d752 t ??CrossCallReturnLabel_54 +1000d75a t ??CrossCallReturnLabel_12 +1000d762 t ??CrossCallReturnLabel_37 +1000d76a t ??CrossCallReturnLabel_6 +1000d774 t ??CrossCallReturnLabel_42 +1000d778 t ??CrossCallReturnLabel_25 +1000d77c t ??CrossCallReturnLabel_58 +1000d780 t ??CrossCallReturnLabel_65 +1000d784 t ??CrossCallReturnLabel_31 +1000d7a6 t ??dhcp_reboot_0 +1000d7a8 t ??dhcp_reboot_1 +1000d7aa t .text_33 +1000d7aa t ?Subroutine5 +1000d7ae t ??Subroutine5_0 +1000d7b2 T dhcp_release +1000d7b2 t .text_34 +1000d80a t ??dhcp_release_0 +1000d814 t ??CrossCallReturnLabel_69 +1000d81a t ??CrossCallReturnLabel_48 +1000d81e t ??CrossCallReturnLabel_53 +1000d822 t ??CrossCallReturnLabel_77 +1000d826 t ??CrossCallReturnLabel_80 +1000d82a t .text_35 +1000d82a t ?Subroutine20 +1000d82c t ??Subroutine20_0 +1000d832 t .text_36 +1000d832 t ?Subroutine19 +1000d834 t ??Subroutine19_0 +1000d83a t .text_37 +1000d83a t ?Subroutine12 +1000d840 t ??Subroutine12_0 +1000d846 T dhcp_release_unicast +1000d846 t .text_38 +1000d8b8 t ??dhcp_release_unicast_0 +1000d8c2 t ??CrossCallReturnLabel_70 +1000d8c8 t ??CrossCallReturnLabel_47 +1000d8d2 t ??CrossCallReturnLabel_50 +1000d8d8 t ??CrossCallReturnLabel_75 +1000d8de t ??CrossCallReturnLabel_78 +1000d8e2 t .text_39 +1000d8e2 t ?Subroutine16 +1000d8fe t ??Subroutine16_0 +1000d900 t ??Subroutine16_1 +1000d902 t .text_40 +1000d902 t ?Subroutine11 +1000d908 T dhcp_stop +1000d908 t .text_41 +1000d90c t ??dhcp_stop_0 +1000d928 t ??dhcp_stop_2 +1000d932 t ??dhcp_stop_1 +1000d934 t .text_42 +1000d934 t dhcp_set_state +1000d942 t ??dhcp_set_state_0 +1000d944 t .text_43 +1000d944 t dhcp_option +1000d962 t .text_44 +1000d962 t dhcp_option_byte +1000d972 t .text_45 +1000d972 t dhcp_option_short +1000d982 t .text_46 +1000d982 t dhcp_option_long +1000d9ac t .text_47 +1000d9ac t ?Subroutine3 +1000d9be t .text_48 +1000d9be t dhcp_parse_reply +1000d9ee t ??dhcp_parse_reply_2 +1000d9f2 t ??dhcp_parse_reply_3 +1000d9f8 t ??dhcp_parse_reply_1 +1000d9fc t ??dhcp_parse_reply_5 +1000da0c t ??dhcp_parse_reply_4 +1000da10 t ??dhcp_parse_reply_0 +1000da16 t ??dhcp_parse_reply_6 +1000da1e t ??dhcp_parse_reply_8 +1000da46 t ??dhcp_parse_reply_10 +1000da4e t ??dhcp_parse_reply_11 +1000da78 t ??dhcp_parse_reply_12 +1000da82 t ??dhcp_parse_reply_13 +1000da8a t ??dhcp_parse_reply_14 +1000da94 t ??dhcp_parse_reply_15 +1000dab0 t ??dhcp_parse_reply_16 +1000dab8 t ??dhcp_parse_reply_17 +1000dac0 t ??dhcp_parse_reply_18 +1000dac8 t ??dhcp_parse_reply_19 +1000dad0 t ??dhcp_parse_reply_20 +1000dad8 t ??dhcp_parse_reply_21 +1000dae0 t ??dhcp_parse_reply_22 +1000dae2 t ??dhcp_parse_reply_23 +1000daf2 t ??dhcp_parse_reply_27 +1000db1a t ??dhcp_parse_reply_26 +1000db4a t ??dhcp_parse_reply_28 +1000db4e t ??dhcp_parse_reply_24 +1000db54 t ??dhcp_parse_reply_30 +1000db58 t ??dhcp_parse_reply_29 +1000db66 t ??dhcp_parse_reply_25 +1000db90 t ??dhcp_parse_reply_9 +1000dbb0 t ??dhcp_parse_reply_31 +1000dbb6 t ??dhcp_parse_reply_32 +1000dbc2 t ??dhcp_parse_reply_33 +1000dbc4 t ??dhcp_parse_reply_7 +1000dbcc t .text_49 +1000dbcc t dhcp_recv +1000dbec t ??dhcp_recv_3 +1000dbfe t ??dhcp_recv_2 +1000dc10 t ??dhcp_recv_1 +1000dc42 t ??dhcp_recv_7 +1000dc70 t ??dhcp_recv_8 +1000dc7e t ??dhcp_recv_9 +1000dc84 t ??dhcp_recv_0 +1000dc86 t ??dhcp_recv_6 +1000dc98 t ??dhcp_recv_5 +1000dcae t ??dhcp_recv_11 +1000dcb4 t ??CrossCallReturnLabel_46 +1000dcb8 t ??CrossCallReturnLabel_52 +1000dcbc t ??CrossCallReturnLabel_76 +1000dcc0 t ??CrossCallReturnLabel_79 +1000dcd0 t ??dhcp_recv_10 +1000dcf8 t ??dhcp_recv_4 +1000dd06 t .text_50 +1000dd06 t dhcp_create_msg +1000dd12 t ??dhcp_create_msg_0 +1000dd1a t ??dhcp_create_msg_1 +1000dd2c t ??dhcp_create_msg_2 +1000dd38 t ??dhcp_create_msg_3 +1000dd82 t ??dhcp_create_msg_4 +1000dd86 t ??dhcp_create_msg_5 +1000dd8e t ??dhcp_create_msg_6 +1000ddb0 t ??dhcp_create_msg_7 +1000ddc0 t ??dhcp_create_msg_8 +1000ddda t ??dhcp_create_msg_9 +1000de00 t ??DataTable9 +1000de04 t ??DataTable9_1 +1000de08 t ??DataTable9_2 +1000de0c t ??DataTable9_3 +1000de10 t ??DataTable9_4 +1000de14 t ??DataTable9_5 +1000de18 t .text_57 +1000de18 t ?Subroutine2 +1000de1e t .text_58 +1000de1e t ?Subroutine1 +1000de24 t .text_59 +1000de24 t dhcp_delete_msg +1000de32 t ??dhcp_delete_msg_1 +1000de38 t ??dhcp_delete_msg_0 +1000de3a t .text_60 +1000de3a t dhcp_option_trailer +1000de3e t ??dhcp_option_trailer_0 +1000de50 t ??dhcp_option_trailer_2 +1000de5a t ??dhcp_option_trailer_1 +1000de66 t ??dhcp_option_trailer_3 +1000de6a t ??dhcp_option_trailer_4 +1000de70 t .text_3 +1000de70 t autoip_restart +1000de7a t .text_4 +1000de7a t autoip_arp_announce +1000de9e T autoip_start +1000de9e t .text_5 +1000dede t ??autoip_start_0 +1000dee8 t ??autoip_start_2 +1000df2a t ??autoip_start_1 +1000df2e t .text_6 +1000df2e t autoip_start_probing +1000df40 t ??autoip_start_probing_0 +1000df74 T autoip_tmr +1000df74 t .text_9 +1000df8a t ??autoip_tmr_1 +1000df90 t ??autoip_tmr_2 +1000dfae t ??autoip_tmr_4 +1000dfb0 t ??autoip_tmr_5 +1000dfb2 t ??autoip_tmr_3 +1000dfb4 t ??autoip_tmr_0 +1000dfc6 t ??autoip_tmr_7 +1000dfd4 t ??autoip_tmr_8 +1000dfee t ??autoip_tmr_11 +1000e04a t ??autoip_tmr_9 +1000e04e t ??autoip_tmr_10 +1000e052 t ??autoip_tmr_12 +1000e07a t ??autoip_tmr_6 +1000e080 t ??DataTable2 +1000e084 t ??DataTable2_1 +1000e088 t ??DataTable2_2 +1000e08c t ??DataTable2_3 +1000e090 t ??DataTable2_4 +1000e094 t ??DataTable2_5 +1000e098 T autoip_arp_reply +1000e098 t .text_16 +1000e0e2 t ??autoip_arp_reply_1 +1000e0f4 t ??CrossCallReturnLabel_1 +1000e0f6 t ??autoip_arp_reply_3 +1000e0fa t ??autoip_arp_reply_2 +1000e106 t ??CrossCallReturnLabel_0 +1000e112 t ??autoip_arp_reply_4 +1000e118 t ??autoip_arp_reply_5 +1000e122 t ??autoip_arp_reply_0 +1000e126 t .text_17 +1000e126 t ?Subroutine0 +1000e134 T __aeabi_memclr +1000e13c T tcp_input +1000e162 t ??CrossCallReturnLabel_1 +1000e1ac t ??CrossCallReturnLabel_19 +1000e1b2 t ??CrossCallReturnLabel_0 +1000e1b4 t ??tcp_input_0 +1000e218 t ??tcp_input_3 +1000e21c t ??tcp_input_2 +1000e25c t ??tcp_input_5 +1000e27a t ??tcp_input_6 +1000e29a t ??tcp_input_7 +1000e2a4 t ??tcp_input_8 +1000e2bc t ??tcp_input_4 +1000e2c4 t ??tcp_input_14 +1000e2c6 t ??tcp_input_13 +1000e31c t ??tcp_input_17 +1000e328 t ??tcp_input_18 +1000e340 t ??tcp_input_16 +1000e342 t ??tcp_input_15 +1000e34c t ??tcp_input_21 +1000e350 t ??tcp_input_20 +1000e37a t ??tcp_input_23 +1000e380 t ??tcp_input_10 +1000e398 t ??tcp_input_12 +1000e39c t ??tcp_input_11 +1000e3ae t ??tcp_input_24 +1000e3c6 t ??tcp_input_25 +1000e3e0 t ??tcp_input_27 +1000e3f4 t ??tcp_input_28 +1000e3fe t ??tcp_input_29 +1000e408 t ??tcp_input_26 +1000e41c t ??tcp_input_31 +1000e442 t ??tcp_input_30 +1000e44c t ??tcp_input_9 +1000e460 t ??tcp_input_22 +1000e466 t ??CrossCallReturnLabel_18 +1000e480 t ??tcp_input_19 +1000e484 t ??tcp_input_1 +1000e48e t ??tcp_input_32 +1000e492 t .text_5 +1000e492 t ?Subroutine0 +1000e49e t .text_6 +1000e49e t tcp_listen_input +1000e4ce t ??CrossCallReturnLabel_38 +1000e4d0 t ??tcp_listen_input_1 +1000e4d4 t ??tcp_listen_input_0 +1000e56e t ??tcp_listen_input_2 +1000e578 t .text_7 +1000e578 t tcp_process +1000e59a t ??tcp_process_2 +1000e5ae t ??tcp_process_4 +1000e5c8 t ??tcp_process_1 +1000e5d6 t ??tcp_process_6 +1000e5e6 t ??tcp_process_8 +1000e60c t ??tcp_process_0 +1000e61c t ??tcp_process_10 +1000e62a t ??CrossCallReturnLabel_32 +1000e69e t ??tcp_process_12 +1000e6a6 t ??tcp_process_13 +1000e6ba t ??tcp_process_7 +1000e6c6 t ??tcp_process_9 +1000e6c8 t ??tcp_process_11 +1000e6ce t ??tcp_process_15 +1000e6e4 t ??CrossCallReturnLabel_37 +1000e6e6 t ??tcp_process_16 +1000e714 t ??tcp_process_18 +1000e71a t ??tcp_process_14 +1000e71e t ??tcp_process_19 +1000e726 t ??CrossCallReturnLabel_44 +1000e732 t ??tcp_process_20 +1000e744 t ??tcp_process_22 +1000e746 t ??tcp_process_17 +1000e75a t ??tcp_process_23 +1000e75c t ??tcp_process_24 +1000e760 t ??CrossCallReturnLabel_43 +1000e766 t ??tcp_process_21 +1000e776 t ??tcp_process_26 +1000e77a t ??CrossCallReturnLabel_42 +1000e794 t ??CrossCallReturnLabel_36 +1000e79a t ??tcp_process_30 +1000e7aa t ??tcp_process_28 +1000e7ba t ??tcp_process_27 +1000e7c6 t ??tcp_process_25 +1000e7ca t ??tcp_process_33 +1000e7ce t ??CrossCallReturnLabel_41 +1000e7d8 t ??CrossCallReturnLabel_35 +1000e7de t ??tcp_process_34 +1000e7ec t ??tcp_process_35 +1000e7f0 t ??CrossCallReturnLabel_40 +1000e80a t ??tcp_process_29 +1000e812 t ??tcp_process_36 +1000e81e t ??tcp_process_32 +1000e824 t ??tcp_process_31 +1000e844 t ??tcp_process_37 +1000e848 t ??CrossCallReturnLabel_39 +1000e85e t ??tcp_process_3 +1000e860 t ??tcp_process_5 +1000e864 t .text_8 +1000e864 t ?Subroutine6 +1000e868 t .text_9 +1000e868 t ?Subroutine5 +1000e872 t .text_10 +1000e872 t ?Subroutine4 +1000e884 t .text_11 +1000e884 t tcp_oos_insert_segment +1000e890 t ??CrossCallReturnLabel_17 +1000e89e t ??tcp_oos_insert_segment_1 +1000e8a2 t ??CrossCallReturnLabel_16 +1000e8b4 t ??tcp_oos_insert_segment_2 +1000e8bc t ??tcp_oos_insert_segment_0 +1000e8e0 t ??CrossCallReturnLabel_51 +1000e8e4 t ??DataTable3 +1000e8e8 t ??DataTable3_1 +1000e8ec t .text_14 +1000e8ec t tcp_receive +1000e91e t ??tcp_receive_2 +1000e92c t ??tcp_receive_1 +1000e954 t ??tcp_receive_4 +1000e958 t ??tcp_receive_5 +1000e95a t ??tcp_receive_3 +1000e9ae t ??tcp_receive_9 +1000e9b0 t ??tcp_receive_8 +1000e9bc t ??tcp_receive_7 +1000e9c2 t ??tcp_receive_6 +1000e9dc t ??tcp_receive_11 +1000ea24 t ??tcp_receive_12 +1000ea38 t ??tcp_receive_13 +1000ea40 t ??CrossCallReturnLabel_55 +1000ea4a t ??CrossCallReturnLabel_15 +1000ea4e t ??CrossCallReturnLabel_58 +1000ea52 t ??CrossCallReturnLabel_54 +1000ea56 t ??CrossCallReturnLabel_47 +1000ea5e t ??CrossCallReturnLabel_31 +1000ea68 t ??CrossCallReturnLabel_14 +1000ea82 t ??tcp_receive_14 +1000ea88 t ??tcp_receive_15 +1000ea8a t ??tcp_receive_16 +1000ea92 t ??tcp_receive_10 +1000ea98 t ??tcp_receive_17 +1000eaa0 t ??tcp_receive_18 +1000eaa4 t ??CrossCallReturnLabel_53 +1000eaae t ??CrossCallReturnLabel_13 +1000eab2 t ??CrossCallReturnLabel_59 +1000eab6 t ??CrossCallReturnLabel_52 +1000eaba t ??CrossCallReturnLabel_46 +1000eac2 t ??CrossCallReturnLabel_30 +1000eacc t ??CrossCallReturnLabel_12 +1000eaec t ??tcp_receive_19 +1000eb30 t ??tcp_receive_0 +1000eb64 t ??tcp_receive_24 +1000eb6e t ??tcp_receive_23 +1000eb74 t ??tcp_receive_22 +1000eb90 t ??tcp_receive_21 +1000eb9c t ??tcp_receive_25 +1000ebbc t ??CrossCallReturnLabel_27 +1000ebc8 t ??CrossCallReturnLabel_65 +1000ebd4 t ??CrossCallReturnLabel_26 +1000ebdc t ??CrossCallReturnLabel_25 +1000ebea t ??CrossCallReturnLabel_48 +1000ebf0 t ??CrossCallReturnLabel_29 +1000ebf4 t ??CrossCallReturnLabel_34 +1000ebf8 t ??CrossCallReturnLabel_24 +1000ec04 t ??CrossCallReturnLabel_66 +1000ec0e t ??CrossCallReturnLabel_23 +1000ec12 t ??tcp_receive_30 +1000ec22 t ??tcp_receive_29 +1000ec26 t ??tcp_receive_32 +1000ec34 t ??CrossCallReturnLabel_22 +1000ec56 t ??CrossCallReturnLabel_67 +1000ec5e t ??tcp_receive_31 +1000ec84 t ??CrossCallReturnLabel_28 +1000ec88 t ??CrossCallReturnLabel_33 +1000ec8c t ??CrossCallReturnLabel_21 +1000ec98 t ??CrossCallReturnLabel_68 +1000ec9a t ??tcp_receive_28 +1000eca8 t ??CrossCallReturnLabel_57 +1000ecb4 t ??tcp_receive_33 +1000ecb8 t ??CrossCallReturnLabel_20 +1000ecc6 t ??tcp_receive_34 +1000ecc8 t ??tcp_receive_35 +1000eccc t ??tcp_receive_36 +1000ecd2 t ??CrossCallReturnLabel_11 +1000ecec t ??tcp_receive_37 +1000ecf4 t ??CrossCallReturnLabel_45 +1000ed0c t ??CrossCallReturnLabel_10 +1000ed24 t ??CrossCallReturnLabel_9 +1000ed2a t ??CrossCallReturnLabel_8 +1000ed3c t ??CrossCallReturnLabel_56 +1000ed50 t ??tcp_receive_38 +1000ed64 t ??tcp_receive_27 +1000ed72 t ??CrossCallReturnLabel_64 +1000ed74 t ??tcp_receive_42 +1000ed76 t ??tcp_receive_41 +1000ed7a t ??tcp_receive_44 +1000ed90 t ??CrossCallReturnLabel_63 +1000eda2 t ??tcp_receive_45 +1000edb0 t ??CrossCallReturnLabel_62 +1000edb6 t ??tcp_receive_46 +1000edba t ??tcp_receive_47 +1000edd2 t ??CrossCallReturnLabel_61 +1000edd4 t ??tcp_receive_49 +1000edfa t ??tcp_receive_51 +1000ee02 t ??tcp_receive_50 +1000ee08 t ??tcp_receive_48 +1000ee1c t ??CrossCallReturnLabel_7 +1000ee24 t ??CrossCallReturnLabel_60 +1000ee40 t ??CrossCallReturnLabel_50 +1000ee58 t ??CrossCallReturnLabel_6 +1000ee64 t ??CrossCallReturnLabel_5 +1000ee74 t ??CrossCallReturnLabel_49 +1000ee92 t ??CrossCallReturnLabel_4 +1000eea4 t ??tcp_receive_52 +1000eeae t ??tcp_receive_26 +1000eeb8 t ??tcp_receive_20 +1000eeca t ??tcp_receive_53 +1000eecc t ??tcp_receive_39 +1000eed0 t ??tcp_receive_40 +1000eed2 t ??tcp_receive_43 +1000eed8 t ??DataTable4 +1000eedc t ??DataTable4_1 +1000eee0 t .text_17 +1000eee0 t ?Subroutine14 +1000eee8 t .text_18 +1000eee8 t ?Subroutine13 +1000eeee t .text_19 +1000eeee t ?Subroutine12 +1000eef8 t ??Subroutine12_0 +1000eefa t .text_20 +1000eefa t ?Subroutine11 +1000ef04 t .text_21 +1000ef04 t ?Subroutine10 +1000ef0a t .text_22 +1000ef0a t ?Subroutine9 +1000ef14 t .text_23 +1000ef14 t ?Subroutine8 +1000ef22 t .text_24 +1000ef22 t ?Subroutine7 +1000ef28 t ??Subroutine7_0 +1000ef2e t .text_25 +1000ef2e t ?Subroutine3 +1000ef38 t ??Subroutine3_0 +1000ef40 t .text_26 +1000ef40 t ?Subroutine2 +1000ef48 t .text_27 +1000ef48 t ?Subroutine1 +1000ef4a t ??Subroutine1_0 +1000ef4c t ??Subroutine1_1 +1000ef52 t .text_28 +1000ef52 t tcp_parseopt +1000ef62 t ??CrossCallReturnLabel_3 +1000ef6e t ??CrossCallReturnLabel_2 +1000ef7a t ??tcp_parseopt_2 +1000ef7e t ??tcp_parseopt_3 +1000ef80 t ??tcp_parseopt_1 +1000ef94 t ??tcp_parseopt_4 +1000efb4 t ??tcp_parseopt_6 +1000efba t ??tcp_parseopt_5 +1000efc4 t ??tcp_parseopt_0 +1000efc8 t ??DataTable5 +1000efcc t ??DataTable5_1 +1000efd0 t ??DataTable5_2 +1000efd4 t ??DataTable5_3 +1000efd8 t ??DataTable5_4 +1000efdc t ??DataTable5_5 +1000efe0 T netif_init +1000efe2 T netif_add +1000efe2 t .text_4 +1000f01c t ??netif_add_0 +1000f026 T netif_set_addr +1000f026 t .text_5 +1000f044 T netif_set_ipaddr +1000f044 t .text_8 +1000f05a t ??netif_set_ipaddr_3 +1000f062 t ??netif_set_ipaddr_2 +1000f076 t ??netif_set_ipaddr_5 +1000f07a t ??netif_set_ipaddr_4 +1000f07e t ??netif_set_ipaddr_6 +1000f08e t ??netif_set_ipaddr_7 +1000f092 t ??netif_set_ipaddr_0 +1000f096 t ??netif_set_ipaddr_1 +1000f098 t ??netif_set_ipaddr_8 +1000f09c T netif_set_gw +1000f09c t .text_9 +1000f0a0 t ??netif_set_gw_0 +1000f0a4 T netif_set_netmask +1000f0a4 t .text_10 +1000f0a8 t ??netif_set_netmask_0 +1000f0ac T netif_set_default +1000f0ac t .text_11 +1000f0b4 t ??DataTable4 +1000f0b8 t ??DataTable4_1 +1000f0bc t ??DataTable4_2 +1000f0c0 T netif_set_up +1000f0c0 t .text_15 +1000f0de t ??netif_set_up_0 +1000f0e0 T netif_set_down +1000f0e0 t .text_16 +1000f0f8 t ??netif_set_down_0 +1000f0fc T lwip_socket_init +1000f0fe t .text_5 +1000f0fe t get_socket +1000f110 t ??get_socket_0 +1000f112 t ??get_socket_1 +1000f114 t .text_7 +1000f114 t alloc_socket +1000f122 t ??alloc_socket_0 +1000f15a t ??alloc_socket_1 +1000f168 t ??alloc_socket_2 +1000f16c t .text_10 +1000f16c t ?Subroutine6 +1000f172 T lwip_close +1000f172 t .text_11 +1000f184 t ??lwip_close_0 +1000f190 t ??lwip_close_1 +1000f1b8 t ??lwip_close_3 +1000f1bc t ??lwip_close_2 +1000f1c0 T lwip_connect +1000f1c0 t .text_12 +1000f1c8 t ??CrossCallReturnLabel_0 +1000f1de t ??lwip_connect_1 +1000f1e2 t ??CrossCallReturnLabel_11 +1000f1fe t ??lwip_connect_2 +1000f200 t ??lwip_connect_0 +1000f202 t ??lwip_connect_3 +1000f206 t .text_13 +1000f206 t ?Subroutine11 +1000f210 t .text_14 +1000f210 t ?Subroutine2 +1000f216 T lwip_recvfrom +1000f216 t .text_16 +1000f232 t ??lwip_recvfrom_2 +1000f242 t ??lwip_recvfrom_3 +1000f254 t ??lwip_recvfrom_4 +1000f264 t ??lwip_recvfrom_6 +1000f268 t ??lwip_recvfrom_7 +1000f26e t ??lwip_recvfrom_5 +1000f274 t ??lwip_recvfrom_9 +1000f290 t ??lwip_recvfrom_1 +1000f294 t ??lwip_recvfrom_11 +1000f296 t ??lwip_recvfrom_8 +1000f29a t ??lwip_recvfrom_13 +1000f2ec t ??lwip_recvfrom_14 +1000f2f2 t ??lwip_recvfrom_15 +1000f2f8 t ??lwip_recvfrom_16 +1000f314 t ??lwip_recvfrom_19 +1000f320 t ??lwip_recvfrom_20 +1000f324 t ??CrossCallReturnLabel_9 +1000f328 t ??CrossCallReturnLabel_7 +1000f344 t ??lwip_recvfrom_18 +1000f34a t ??lwip_recvfrom_17 +1000f366 t ??lwip_recvfrom_22 +1000f37a t ??lwip_recvfrom_23 +1000f37e t ??lwip_recvfrom_21 +1000f38c t ??lwip_recvfrom_10 +1000f390 t ??lwip_recvfrom_25 +1000f396 t ??lwip_recvfrom_12 +1000f39c t ??lwip_recvfrom_0 +1000f39e t ??lwip_recvfrom_24 +1000f3aa t .text_17 +1000f3aa t ?Subroutine10 +1000f3b4 t .text_18 +1000f3b4 t ?Subroutine9 +1000f3c8 T lwip_read +1000f3c8 t .text_19 +1000f3d8 T lwip_send +1000f3d8 t .text_21 +1000f40a t ??lwip_send_1 +1000f448 t ??lwip_send_0 +1000f44c t ??lwip_send_2 +1000f44e T lwip_sendto +1000f44e t .text_22 +1000f478 t ??lwip_sendto_1 +1000f496 t ??lwip_sendto_0 +1000f49c t ??lwip_sendto_3 +1000f4b0 t ??lwip_sendto_4 +1000f4b2 t ??lwip_sendto_5 +1000f4ce t ??lwip_sendto_6 +1000f4f2 t .text_23 +1000f4f2 t ??lwip_sendto_2 +1000f4f2 t ?Subroutine1 +1000f4f8 T lwip_socket +1000f4f8 t .text_24 +1000f50e t ??lwip_socket_2 +1000f512 t ??lwip_socket_4 +1000f51c t ??lwip_socket_3 +1000f528 t ??lwip_socket_0 +1000f540 t ??lwip_socket_5 +1000f554 t ??lwip_socket_1 +1000f558 t ??lwip_socket_6 +1000f55c t .text_30 +1000f55c t event_callback +1000f582 t ??event_callback_2 +1000f586 t ??event_callback_1 +1000f5a6 t ??event_callback_4 +1000f5ac t ??event_callback_6 +1000f5b0 t ??event_callback_10 +1000f5b4 t ??event_callback_5 +1000f5b8 t ??event_callback_8 +1000f5ba t ??event_callback_11 +1000f5be t ??event_callback_7 +1000f5c2 t ??event_callback_9 +1000f5cc t ??event_callback_12 +1000f5d4 t ??event_callback_14 +1000f5f6 t ??event_callback_16 +1000f60c t ??event_callback_18 +1000f622 t ??event_callback_17 +1000f62e t ??event_callback_15 +1000f646 t ??event_callback_13 +1000f64a t ??event_callback_3 +1000f654 t ??event_callback_0 +1000f658 t ??DataTable8 +1000f65c t err_to_errno_table +1000f69c T lwip_setsockopt +1000f69c t .text_39 +1000f6bc t ??lwip_setsockopt_1 +1000f6fa t ??lwip_setsockopt_7 +1000f6fe t ??lwip_setsockopt_3 +1000f704 t ??lwip_setsockopt_6 +1000f70a t ??lwip_setsockopt_10 +1000f710 t ??CrossCallReturnLabel_16 +1000f726 t ??CrossCallReturnLabel_13 +1000f730 t ??lwip_setsockopt_4 +1000f736 t ??lwip_setsockopt_9 +1000f73a t ??lwip_setsockopt_12 +1000f748 t ??lwip_setsockopt_5 +1000f74c t ??lwip_setsockopt_8 +1000f750 t ??lwip_setsockopt_2 +1000f752 t ??lwip_setsockopt_0 +1000f756 t .text_40 +1000f756 t ??lwip_setsockopt_11 +1000f756 t ?Subroutine0 +1000f75c t .text_41 +1000f75c t ?Subroutine13 +1000f76c t .text_42 +1000f76c t ?Subroutine12 +1000f778 t .text_43 +1000f778 t lwip_setsockopt_internal +1000f7a8 t ??lwip_setsockopt_internal_3 +1000f7be t ??lwip_setsockopt_internal_4 +1000f7c6 t ??lwip_setsockopt_internal_5 +1000f7de t ??lwip_setsockopt_internal_0 +1000f7f2 t ??lwip_setsockopt_internal_6 +1000f7fe t ??lwip_setsockopt_internal_1 +1000f812 t ??lwip_setsockopt_internal_7 +1000f82c t .text_44 +1000f82c t ??lwip_setsockopt_internal_2 +1000f82c t ?Subroutine5 +1000f838 t .text_49 +1000f838 t ?Subroutine4 +1000f840 t ??DataTable9 +1000f844 t ?Veneer (6) for HalSerialPutcRtl8195a +1000f84c T ram_libgloss_close +1000f84e T ram_libgloss_fstat +1000f84e t .text_5 +1000f868 T ram_libgloss_isatty +1000f868 t .text_6 +1000f872 T ram_libgloss_lseek +1000f872 t .text_7 +1000f874 t .text_8 +1000f87a t .text_9 +1000f880 T ram_libgloss_open +1000f880 t .text_10 +1000f8b4 T ram_libgloss_read +1000f8b4 t .text_11 +1000f8b6 T ram_libgloss_write +1000f8b6 t .text_12 +1000f8d0 T ram_libgloss_sbrk +1000f8d0 t .text_13 +1000f8e4 T init_rom_libgloss_ram_map +1000f8e4 t .text_14 +1000f908 t .text_15 +1000f90c t .text_16 +1000f910 t .text_17 +1000f914 t .text_18 +1000f918 t .text_19 +1000f91c t .text_20 +1000f920 t .text_21 +1000f924 t .text_22 +1000f928 t .text_23 +1000f92c t .text_24 +1000f930 t .text_25 +1000f934 t .text_26 +1000f938 T __stdin_name +1000f938 t .text_27 +1000f940 T __stdout_name +1000f940 t .text_28 +1000f948 T __stderr_name +1000f948 t .text_29 +1000f950 T alloc_etherdev +1000f9a6 T free_netdev +1000f9a6 t .text_4 +1000f9c4 T dev_alloc_name +1000f9c4 t .text_5 +1000f9ce T init_timer_wrapper +1000f9ce t .text_6 +1000f9e4 T deinit_timer_wrapper +1000f9e4 t .text_7 +1000fa28 T timer_wrapper +1000fa28 t .text_8 +1000fa78 t __iar_annotation$$tailcall +1000fa7a T init_timer +1000fa7a t .text_9 +1000fafe T mod_timer +1000fafe t .text_10 +1000fbac t .text_11 +1000fbb6 t .text_12 +1000fbcc T cancel_timer_ex +1000fbcc t .text_14 +1000fc08 t .text_15 +1000fc10 T del_timer_sync +1000fc10 t .text_16 +1000fc60 t .text_17 +1000fc6a T rltk_get_idx_bydev +1000fc6a t .text_18 +1000fc8c T rltk_wlan_init +1000fc8c t .text_19 +1000fd14 T rltk_wlan_deinit +1000fd14 t .text_20 +1000fde0 T rltk_wlan_start +1000fde0 t .text_21 +1000fdf6 t __iar_annotation$$tailcall +1000fe06 T rltk_wlan_check_isup +1000fe06 t .text_22 +1000fe08 t .text_23 +1000fe16 T rltk_wlan_tx_inc +1000fe16 t .text_24 +1000fe28 T rltk_wlan_tx_dec +1000fe28 t .text_25 +1000fe3a T rltk_wlan_get_recv_skb +1000fe3a t .text_26 +1000fe48 T rltk_wlan_alloc_skb +1000fe48 t .text_27 +1000fe7a T rltk_wlan_send_skb +1000fe7a t .text_28 +1000fea0 t __iar_annotation$$tailcall +1000fea2 T rltk_netif_rx +1000fea2 t .text_29 +1000ff36 T rltk_wlan_control +1000ff36 t .text_30 +1000ffae t __iar_annotation$$tailcall +1000ffbe T rltk_wlan_running +1000ffbe t .text_31 +1000ffc8 T rltk_wlan_statistic +1000ffc8 t .text_32 +10010068 T rltk_wlan_handshake_done +10010068 t .text_33 +1001008e t .text_38 +10010098 t .text_40 +1001009e T rltk_wlan_set_wps_phase +1001009e t .text_41 +100100cc t .text_42 +100100d2 T rltk_wlan_pre_sleep_processing +100100d2 t .text_47 +100100e4 T rltk_wlan_post_sleep_processing +100100e4 t .text_48 +100100f8 t .text_51 +100100fc t .text_52 +10010100 t .text_53 +10010104 t .text_54 +10010108 t .text_55 +1001010c t .text_56 +10010110 t .text_57 +10010114 t .text_58 +10010118 t ??__FUNCTION__ +10010128 t ?_0 +1001014c t ?_1 +10010170 t ??__FUNCTION___1 +10010188 t ?_2 +100101b0 t ??__FUNCTION___2 +100101c0 t ?_3 +100101f4 t ??__FUNCTION___3 +10010200 t ?_4 +10010208 t ?_5 +10010224 t ?_6 +10010248 t ??__FUNCTION___4 +10010254 t ?_7 +10010274 t ??__FUNCTION___5 +10010284 t ?_8 +100102a0 t ?_9 +100102c4 t ??__FUNCTION___6 +100102d8 t ?_10 +100102f8 t ?_11 +10010310 t ??__FUNCTION___7 +10010320 t ?_12 +1001034c t ??__FUNCTION___8 +10010360 t ?_13 +100103a4 t ??__FUNCTION___9 +100103b8 t ?_14 +100103d0 t ??__FUNCTION___10 +100103e0 t ?_15 +100103f4 t ??__FUNCTION___11 +10010408 t ?_16 +10010410 t ??__FUNCTION___12 +10010424 t ?_17 +10010460 t ?_18 +1001049c t ?_19 +100104d4 t ?_20 +10010508 t ?_21 +1001053c t ?_22 +1001055c t ??__FUNCTION___13 +10010578 t ??__FUNCTION___17 +10010590 t ?_28 +100105c4 T sleep_ex +100105ca t ??sleep_ex_0 +100105d8 T rand +100106b8 T __aeabi_memset +100106b8 T __iar_Memset +100106c0 T __iar_Memset_word +100106c0 t .text_1 +10010720 T _htons +1001072a T _rtw_zvmalloc +1001072a t .text_10 +10010744 t __iar_annotation$$tailcall +10010748 T _rtw_vmfree +10010748 t .text_11 +10010764 t __iar_annotation$$tailcall +10010768 T _rtw_malloc +10010768 t .text_12 +10010772 t __iar_annotation$$tailcall +10010778 T _rtw_zmalloc +10010778 t .text_13 +10010782 t __iar_annotation$$tailcall +10010788 T _rtw_mfree +10010788 t .text_14 +10010792 t __iar_annotation$$tailcall +10010796 T init_mem_monitor +10010796 t .text_15 +100107a4 T deinit_mem_monitor +100107a4 t .text_16 +100107a6 T add_mem_usage +100107a6 t .text_17 +100107d8 T rtw_zvmalloc +100107d8 t .text_20 +100107e0 t .text_21 +100107f6 T rtw_vmfree +100107f6 t .text_22 +100107f8 T rtw_malloc +100107f8 t .text_23 +10010802 T rtw_zmalloc +10010802 t .text_24 +1001080c T rtw_mfree +1001080c t .text_25 +1001080e T rtw_memcpy +1001080e t .text_28 +1001081e t __iar_annotation$$tailcall +10010822 T rtw_memcmp +10010822 t .text_29 +10010832 t __iar_annotation$$tailcall +10010838 T rtw_memset +10010838 t .text_30 +10010848 t __iar_annotation$$tailcall +1001084c T rtw_init_listhead +1001084c t .text_31 +1001084e T rtw_is_list_empty +1001084e t .text_32 +1001085c T rtw_list_insert_head +1001085c t .text_33 +10010860 T rtw_list_insert_tail +10010860 t .text_34 +10010864 T rtw_list_delete +10010864 t .text_35 +1001086c t .text_36 +10010872 T rtw_init_sema +10010872 t .text_37 +1001087c t __iar_annotation$$tailcall +10010880 T rtw_free_sema +10010880 t .text_38 +1001088a t __iar_annotation$$tailcall +1001088e T rtw_up_sema +1001088e t .text_39 +10010898 t __iar_annotation$$tailcall +1001089c T rtw_down_timeout_sema +1001089c t .text_40 +100108a6 t __iar_annotation$$tailcall +100108ac T rtw_down_sema +100108ac t .text_41 +100108dc T rtw_mutex_init +100108dc t .text_42 +100108e6 t __iar_annotation$$tailcall +100108ea T rtw_mutex_free +100108ea t .text_43 +100108f4 t __iar_annotation$$tailcall +100108f8 T rtw_enter_critical +100108f8 t .text_46 +10010902 t __iar_annotation$$tailcall +10010906 T rtw_exit_critical +10010906 t .text_47 +10010910 t __iar_annotation$$tailcall +10010914 T rtw_enter_critical_bh +10010914 t .text_48 +10010916 T rtw_exit_critical_bh +10010916 t .text_49 +10010918 T rtw_enter_critical_mutex +10010918 t .text_50 +10010922 t __iar_annotation$$tailcall +10010928 T rtw_exit_critical_mutex +10010928 t .text_51 +10010932 t __iar_annotation$$tailcall +10010936 T rtw_init_queue +10010936 t .text_52 +10010948 T rtw_queue_empty +10010948 t .text_53 +1001094a T rtw_end_of_queue_search +1001094a t .text_54 +10010956 T rtw_spinlock_init +10010956 t .text_55 +10010960 t __iar_annotation$$tailcall +10010964 T rtw_spinlock_free +10010964 t .text_56 +1001096e t __iar_annotation$$tailcall +10010972 T rtw_spin_lock +10010972 t .text_57 +1001097c t __iar_annotation$$tailcall +10010980 T rtw_spin_unlock +10010980 t .text_58 +1001098a t __iar_annotation$$tailcall +1001098e T rtw_get_current_time +1001098e t .text_66 +10010998 t __iar_annotation$$tailcall +1001099e T rtw_systime_to_ms +1001099e t .text_67 +100109a8 t __iar_annotation$$tailcall +100109ae T rtw_systime_to_sec +100109ae t .text_68 +100109b8 t __iar_annotation$$tailcall +100109be T rtw_ms_to_systime +100109be t .text_69 +100109c8 t __iar_annotation$$tailcall +100109ce T rtw_sec_to_systime +100109ce t .text_70 +100109d8 t __iar_annotation$$tailcall +100109de T rtw_get_passing_time_ms +100109de t .text_71 +100109ee T rtw_msleep_os +100109ee t .text_73 +100109f8 t __iar_annotation$$tailcall +100109fc T rtw_usleep_os +100109fc t .text_74 +10010a06 t __iar_annotation$$tailcall +10010a0a T rtw_mdelay_os +10010a0a t .text_75 +10010a14 t __iar_annotation$$tailcall +10010a18 T rtw_udelay_os +10010a18 t .text_76 +10010a22 t __iar_annotation$$tailcall +10010a26 T rtw_init_timer +10010a26 t .text_78 +10010a3a T rtw_set_timer +10010a3a t .text_79 +10010a44 t __iar_annotation$$tailcall +10010a48 T rtw_cancel_timer +10010a48 t .text_80 +10010a5a T rtw_del_timer +10010a5a t .text_81 +10010a64 t __iar_annotation$$tailcall +10010a68 T ATOMIC_SET +10010a68 t .text_82 +10010a72 t __iar_annotation$$tailcall +10010a76 T ATOMIC_INC +10010a76 t .text_86 +10010a80 t __iar_annotation$$tailcall +10010a84 t .text_87 +10010a88 T ATOMIC_INC_RETURN +10010a88 t .text_91 +10010a92 t __iar_annotation$$tailcall +10010a98 T ATOMIC_DEC_RETURN +10010a98 t .text_92 +10010aa2 t __iar_annotation$$tailcall +10010aa8 T ATOMIC_DEC_AND_TEST +10010aa8 t .text_93 +10010ab6 T rtw_modular64 +10010ab6 t .text_94 +10010acc T rtw_get_random_bytes +10010acc t .text_95 +10010ad6 t __iar_annotation$$tailcall +10010adc T rtw_getFreeHeapSize +10010adc t .text_96 +10010ae6 t __iar_annotation$$tailcall +10010aec T rtw_netif_queue_stopped +10010aec t .text_97 +10010af0 T rtw_netif_wake_queue +10010af0 t .text_98 +10010af2 T rtw_netif_start_queue +10010af2 t .text_99 +10010af4 T rtw_netif_stop_queue +10010af4 t .text_100 +10010af6 T flush_signals_thread +10010af6 t .text_101 +10010af8 T rtw_create_task +10010af8 t .text_102 +10010b16 T rtw_delete_task +10010b16 t .text_103 +10010b20 t __iar_annotation$$tailcall +10010b24 T rtw_wakeup_task +10010b24 t .text_104 +10010b2e t __iar_annotation$$tailcall +10010b32 T rtw_timerCreate +10010b32 t .text_108 +10010b4a T rtw_timerDelete +10010b4a t .text_109 +10010b54 t __iar_annotation$$tailcall +10010b5a T rtw_timerIsTimerActive +10010b5a t .text_110 +10010b64 t __iar_annotation$$tailcall +10010b6a T rtw_timerStop +10010b6a t .text_111 +10010b74 t __iar_annotation$$tailcall +10010b7a T rtw_timerChangePeriod +10010b7a t .text_112 +10010b8a t __iar_annotation$$tailcall +10010b90 T rtw_thread_enter +10010b90 t .text_113 +10010b9a t __iar_annotation$$tailcall +10010b9e T rtw_thread_exit +10010b9e t .text_114 +10010ba8 t __iar_annotation$$tailcall +10010bac t .text_115 +10010bb0 t .text_116 +10010bb4 t .text_117 +10010bb8 T rtw_alloc_etherdev_with_old_priv +10010bb8 t .text_119 +10010bce T rtw_alloc_etherdev +10010bce t .text_120 +10010bf8 T rtw_free_netdev +10010bf8 t .text_121 +10010c18 t ??__FUNCTION__ +10010c28 t ?_0 +10010c74 t ??__FUNCTION___1 +10010c84 t ?_2 +10010cac T save_and_cli +10010cb0 T restore_flags +10010cb0 t .text_4 +10010cb4 T _freertos_malloc +10010cb4 t .text_6 +10010cb8 T _freertos_zmalloc +10010cb8 t .text_7 +10010cd0 T _freertos_mfree +10010cd0 t .text_8 +10010cd4 t .text_9 +10010cd4 t _freertos_memcpy +10010cd8 t .text_10 +10010cd8 t _freertos_memcmp +10010ce8 t .text_11 +10010ce8 t _freertos_memset +10010cec t .text_12 +10010cec t _freertos_init_sema +10010cfc t .text_13 +10010cfc t _freertos_free_sema +10010d00 t .text_14 +10010d00 t _freertos_up_sema +10010d02 t .text_15 +10010d02 t _freertos_down_sema +10010d26 t .text_16 +10010d26 t _freertos_mutex_init +10010d2a t .text_17 +10010d2a t _freertos_mutex_free +10010d2c t .text_18 +10010d3c t .text_19 +10010d3c t _freertos_mutex_get +10010d4c t .text_20 +10010d4c t _freertos_mutex_put +10010d4e t .text_21 +10010d5a t .text_22 +10010d5a t _freertos_enter_critical +10010d5e t .text_23 +10010d5e t _freertos_exit_critical +10010d62 t .text_24 +10010d62 t _freertos_enter_critical_mutex +10010d98 t .text_25 +10010d98 t _freertos_exit_critical_mutex +10010d9a t .text_26 +10010d9a t _freertos_spinlock_init +10010d9c t .text_27 +10010da8 t .text_28 +10010da8 t _freertos_spinlock_free +10010dac t .text_29 +10010dac t _freertos_spinlock +10010dba t .text_30 +10010de4 t .text_31 +10010de4 t _freertos_spinunlock +10010de6 t .text_32 +10010de6 t _freertos_spinlock_irqsave +10010dfa t .text_33 +10010dfa t _freertos_spinunlock_irqsave +10010e10 t .text_34 +10010e10 t _freertos_init_xqueue +10010e2c t .text_35 +10010e2c t _freertos_push_to_xqueue +10010e54 t .text_36 +10010e54 t _freertos_pop_from_xqueue +10010e7c t .text_37 +10010e82 t .text_38 +10010e82 t _freertos_deinit_xqueue +10010e9c t .text_39 +10010e9c t _freertos_get_current_time +10010ea0 t .text_40 +10010ea0 t _freertos_systime_to_ms +10010ea2 t .text_41 +10010ea2 t _freertos_systime_to_sec +10010eac t .text_42 +10010eac t _freertos_ms_to_systime +10010eae t .text_43 +10010eae t _freertos_sec_to_systime +10010eb6 t .text_44 +10010eb6 t _freertos_msleep_os +10010eba t .text_45 +10010eba t _freertos_usleep_os +10010ebc t .text_46 +10010ebc t _freertos_mdelay_os +10010ec0 t .text_47 +10010ec0 t _freertos_udelay_os +10010ec4 t .text_48 +10010ec4 t _freertos_yield_os +10010ec8 t .text_49 +10010ec8 t _freertos_init_timer +10010ed0 t .text_50 +10010ed0 t _freertos_set_timer +10010ed4 t .text_51 +10010ed4 t _freertos_cancel_timer_ex +10010ede t .text_52 +10010ede t _freertos_del_timer +10010ee2 t .text_53 +10010ee2 t _freertos_ATOMIC_SET +10010ee6 t .text_54 +10010ee6 t _freertos_ATOMIC_READ +10010eea t .text_55 +10010eea t _freertos_ATOMIC_ADD +10010ef6 t .text_56 +10010ef6 t _freertos_ATOMIC_SUB +10010f00 t .text_57 +10010f0a t .text_58 +10010f0a t _freertos_ATOMIC_INC +10010f0e t .text_59 +10010f0e t _freertos_ATOMIC_DEC +10010f12 t .text_60 +10010f12 t _freertos_ATOMIC_ADD_RETURN +10010f1e t .text_61 +10010f26 t .text_62 +10010f26 t _freertos_ATOMIC_SUB_RETURN +10010f30 t .text_63 +10010f3a t .text_64 +10010f3a t _freertos_ATOMIC_INC_RETURN +10010f3e t .text_65 +10010f3e t _freertos_ATOMIC_DEC_RETURN +10010f42 t .text_66 +10010f42 t _freertos_modular64 +10010fb2 t .text_67 +10010fb2 t _freertos_arc4random +10010fd8 t .text_68 +10010fdc t .text_69 +10010fe0 t .text_70 +10010fe4 t .text_71 +10010fe4 t _freertos_get_random_bytes +10011018 t .text_72 +10011018 t _freertos_GetFreeHeapSize +1001101c t .text_73 +1001101c t _freertos_create_task +10011094 t .text_74 +10011094 t _freertos_delete_task +100110da T _freertos_wakeup_task +100110da t .text_75 +100110de t .text_76 +100110de t _freertos_thread_enter +100110e0 t .text_77 +100110e0 t _freertos_thread_exit +100110e6 T _freertos_timerCreate +100110e6 t .text_78 +100110f4 T _freertos_timerDelete +100110f4 t .text_79 +10011100 T _freertos_timerIsTimerActive +10011100 t .text_80 +10011104 T _freertos_timerStop +10011104 t .text_81 +1001110e t .text_82 +10011114 T _freertos_timerChangePeriod +10011114 t .text_83 +10011124 t ??__FUNCTION__ +10011138 t ?_0 +1001115c t ??__FUNCTION___1 +1001117c t ?_1 +1001119c t ??__FUNCTION___2 +100111b0 t ??__FUNCTION___3 +100111cc t ??__FUNCTION___4 +100111e4 t ?_2 +1001120c t ??__FUNCTION___5 +10011224 t ?_3 +10011254 t __list_add +1001125e t .text_7 +1001125e t get_buf_from_poll +10011280 t .text_8 +10011280 t release_buf_to_poll +10011292 T init_skb_pool +10011292 t .text_9 +100112ba T init_skb_data_pool +100112ba t .text_10 +100112e6 t .text_11 +100112ee t .text_12 +100112fc T alloc_skb +100112fc t .text_13 +1001139c T dev_alloc_skb +1001139c t .text_14 +100113b8 T kfree_skb +100113b8 t .text_15 +100113f2 T kfree_skb_chk_key +100113f2 t .text_16 +100113f4 T skb_put +100113f4 t .text_17 +10011404 T skb_reserve +10011404 t .text_18 +1001140e T skb_assign_buf +1001140e t .text_19 +1001141a T skb_end_pointer +1001141a t .text_21 +1001141e T skb_set_tail_pointer +1001141e t .text_22 +10011420 t .text_23 +10011426 T skb_pull +10011426 t .text_24 +1001143e T skb_copy +1001143e t .text_25 +1001146c t .text_27 +10011470 t .text_28 +10011474 t .text_29 +10011478 t .text_30 +1001147c T list_add +1001147c t .text_31 +10011480 T list_add_tail +10011480 t .text_32 +10011488 t ??__FUNCTION__ +10011494 t ?_0 +100114ac t ?_1 +100114c8 t check_fwstate +100114d6 T rtw_os_indicate_connect +100114d6 t .text_8 +100114da T rtw_os_indicate_scan_done +100114da t .text_9 +100114de T rtw_reset_securitypriv +100114de t .text_10 +100115cc T rtw_os_indicate_disconnect +100115cc t .text_11 +10011614 t .text_12 +10011614 t loadparam +10011764 t .text_13 +10011764 t rtw_net_get_stats +1001179e T rtw_init_netdev_name +1001179e t .text_14 +100117a8 T rtw_init_netdev +100117a8 t .text_15 +100117fc t .text_16 +10011800 T rtw_init_io_priv +10011800 t .text_17 +10011814 T _netdev_if2_open +10011814 t .text_18 +100118d2 T netdev_if2_open +100118d2 t .text_19 +100118e0 t .text_20 +100118e0 t netdev_if2_close +10011904 T rtw_drv_if2_init +10011904 t .text_21 +10011af2 T rtw_drv_if2_stop +10011af2 t .text_22 +10011b3e T rtw_drv_if2_free +10011b3e t .text_23 +10011b8a T _netdev_open +10011b8a t .text_24 +10011c84 T netdev_open +10011c84 t .text_25 +10011c90 t .text_26 +10011c9e t .text_27 +10011cb0 t .text_28 +10011cb0 t netdev_close +10011d0c t .text_29 +10011d0c t rtw_if1_init +10011e1e t .text_30 +10011e1e t rtw_if1_deinit +10011ea2 t .text_31 +10011eaa T rtw_drv_probe +10011eaa t .text_32 +10011efc T rtw_dev_remove +10011efc t .text_33 +10011f3e T rtw_drv_entry +10011f3e t .text_34 +10011f66 T rtw_drv_halt +10011f66 t .text_35 +10011f90 t .text_36 +10011f94 t .text_37 +10011f98 t .text_38 +10011f9c t .text_39 +10011fa0 t .text_40 +10011fa4 t .text_41 +10011fa8 t .text_42 +10011fac t .text_43 +10011fb0 t .text_44 +10011fb4 t .text_45 +10011fb8 t ?_2 +10011fc0 t ?_3 +10011fc8 T rltk_wlan_set_netif_info +10011fe4 T rltk_wlan_send +10011fe4 t .text_3 +1001200a t ??rltk_wlan_send_0 +1001203c t ??rltk_wlan_send_2 +10012048 t ??rltk_wlan_send_1 +1001204e t ??rltk_wlan_send_3 +10012054 t ??rltk_wlan_send_7 +10012068 t ??rltk_wlan_send_6 +10012074 t ??rltk_wlan_send_4 +10012084 t ??rltk_wlan_send_5 +10012088 T rltk_wlan_recv +10012088 t .text_4 +100120a4 t ??rltk_wlan_recv_0 +100120be t ??rltk_wlan_recv_1 +100120c4 t ??rltk_wlan_recv_3 +100120d8 t ??rltk_wlan_recv_4 +100120da t ??rltk_wlan_recv_2 +100120e0 T netif_is_valid_IP +100120e0 t .text_5 +1001210a t ??netif_is_valid_IP_0 +1001210e t ??netif_is_valid_IP_1 +10012112 T netif_get_idx +10012112 t .text_6 +10012128 T netif_get_hwaddr +10012128 t .text_7 +10012134 T netif_rx +10012134 t .text_8 +10012140 t ??DataTable12 +10012144 T netif_post_sleep_processing +10012144 t .text_10 +10012148 t ??__FUNCTION__ +10012158 t ?_0 +10012170 t ?_1 +100121a8 t ??__FUNCTION___1 +100121b8 t ?_2 +100121cc t ?_3 +100121fc t ?_4 +10012210 t ?_5 +10012260 t HalTimerEnable +10012272 t .text_13 +10012272 t HalTimerReLoad +10012276 T Enter32K +10012276 t .text_24 +100122aa T EnterPS +100122aa t .text_25 +100122c8 T GTimer6Handle +100122c8 t .text_26 +100122f6 T GTimer7Handle +100122f6 t .text_27 +1001233c T InitGTimer1ms +1001233c t .text_28 +10012384 T DeInitGTimer1ms +10012384 t .text_29 +100123c2 T ChangeTransmiteRate +100123c2 t .text_30 +1001242a T PowerBitSetting +1001242a t .text_31 +10012462 T ChkandChangePS +10012462 t .text_32 +100124c8 T IssueRsvdPagePacketSetting +100124c8 t .text_33 +10012536 T IssueNullData +10012536 t .text_40 +10012596 t .text_41 +1001259e t .text_42 +100125a6 T IssuePSPoll +100125a6 t .text_43 +100125c2 T WaitTxStateMachineOk +100125c2 t .text_44 +10012608 t ?_7 +10012634 T PsCloseRF +10012634 t .text_47 +10012674 t .text_48 +10012686 T PsOpenRF +10012686 t .text_49 +100126b0 T PsStateTransition +100126b0 t .text_50 +100126c6 T SetPwrStateReg +100126c6 t .text_51 +100126f0 T ChkTxQueueIsEmpty +100126f0 t .text_52 +1001270a T InitPS +1001270a t .text_53 +10012770 T ResetPSParm +10012770 t .text_54 +100127d2 T Legacy_PS_Setting +100127d2 t .text_55 +1001283c T PSModeSetting +1001283c t .text_56 +100128b2 t .text_57 +100128c0 T ConfigListenBeaconPeriod +100128c0 t .text_58 +100128e0 T PSSetMode +100128e0 t .text_59 +1001291e T PS_S2_Condition_Match +1001291e t .text_60 +10012942 T PS_S4_Condition_Match +10012942 t .text_61 +1001299e T PS_32K_Condition_Match +1001299e t .text_62 +100129c6 T PS_S2ToS3ToS0State +100129c6 t .text_63 +10012a28 t ?_8 +10012a7c T PS_S2ToS0State +10012a7c t .text_65 +10012a94 T PS_S3ToS2orS0State +10012a94 t .text_66 +10012aa8 T PS_S0ToS1ToS2State +10012aa8 t .text_67 +10012aec t ?_9 +10012b40 t .text_69 +10012b4a T PS_S1ToS0orS2State +10012b4a t .text_70 +10012b64 t .text_71 +10012b6e t .text_72 +10012b76 T PS_S2ToS4State +10012b76 t .text_73 +10012bb2 T PS_S2ToS5State +10012bb2 t .text_74 +10012bbc T PS_S4ToS2State +10012bbc t .text_75 +10012bd4 t .text_77 +10012bda T PS_S0ToS6State +10012bda t .text_78 +10012c08 t .text_79 +10012c0c T PS_S6ToS0State +10012c0c t .text_80 +10012c22 T CheckTSFIsStable +10012c22 t .text_81 +10012c76 T SysClkDown +10012c76 t .text_83 +10012cbc T SysClkUp +10012cbc t .text_84 +10012cf0 t .text_87 +10012cf4 t .text_88 +10012cf8 t .text_89 +10012cfc t .text_90 +10012d00 t .text_91 +10012d04 t .text_92 +10012d08 t .text_93 +10012d0c t .text_94 +10012d10 t .text_95 +10012d14 t .text_96 +10012d18 T SleepTo32K +10012d18 t .text_97 +10012d38 T Change_PS_State +10012d38 t .text_98 +10012e1e t .text_99 +10012e24 T ChangePSStateByRPWM +10012e24 t .text_100 +10012e34 T SetSmartPSTimer +10012e34 t .text_101 +10012e7c t .text_102 +10012e80 t .text_103 +10012e84 t .text_104 +10012e88 t .text_105 +10012e8c T SmartPS2InitTimerAndToGetRxPkt +10012e8c t .text_106 +10012eb6 T PS_OnBeacon +10012eb6 t .text_107 +10012f3c t .text_108 +10012f40 t .text_109 +10012f44 t .text_110 +10012f48 t .text_111 +10012f4c t .text_112 +10012f50 T PSBcnEarlyProcess +10012f50 t .text_115 +10012fb8 t .text_116 +10012fc8 T PSMtiBcnEarlyProcess +10012fc8 t .text_117 +10013020 t .text_122 +10013028 t .text_123 +10013030 T PSRxBcnProcess +10013030 t .text_124 +10013148 t .text_125 +1001314c t .text_126 +10013150 t .text_127 +10013154 t .text_128 +10013160 T TxPktInPSOn +10013160 t .text_129 +10013194 t .text_130 +1001319c t .text_131 +100131a8 t .text_132 +100131ae T PsBcnToProcess +100131ae t .text_133 +10013248 t .text_134 +10013254 T ISR_BcnEarly +10013254 t .text_136 +10013276 T ISR_TBTT +10013276 t .text_137 +10013278 T ISR_RxBcn +10013278 t .text_138 +1001328e T ISR_RxBCMD1 +1001328e t .text_139 +100132ae t __iar_annotation$$tailcall +100132b4 t .text_140 +100132b8 t .text_141 +100132bc t .text_142 +100132c0 t .text_143 +100132d2 T ISR_RxBCMD0 +100132d2 t .text_144 +100132fc t .text_145 +10013310 t .text_146 +10013318 t __iar_annotation$$tailcall +1001331c t .text_147 +10013320 t .text_148 +10013324 t .text_149 +10013328 t .text_150 +1001332c t .text_151 +10013330 T ISR_RxUCMD1 +10013330 t .text_152 +1001335a t .text_153 +10013370 T ISR_RxUCMD0 +10013370 t .text_154 +10013392 t .text_155 +10013398 T ISR_TxPktIn +10013398 t .text_156 +100133ae T H2CHDL_SetPwrMode +100133ae t .text_157 +10013480 t .text_158 +10013484 t .text_159 +10013488 T Enter32KTask +10013488 t .text_160 +100134aa t .text_161 +100134b4 T HalPreSleepProcessing +100134b4 t .text_163 +100134ec t .text_164 +100134f6 t .text_165 +100134fe T HalPostSleepProcessing +100134fe t .text_166 +10013520 t .text_167 +10013536 T PMUInitial +10013536 t .text_168 +1001356c t .text_169 +10013570 t .text_170 +10013574 t .text_171 +10013584 t .text_172 +10013592 T PMUTask +10013592 t .text_173 +100137ee t .text_174 +100137f8 t .text_175 +100137fe t __iar_annotation$$tailcall +10013800 t .text_176 +10013806 t __iar_annotation$$tailcall +10013808 t .text_177 +1001380c t .text_178 +10013810 t .text_179 +10013814 t .text_180 +10013818 t .text_181 +1001381c t .text_182 +10013820 t .text_183 +10013824 t .text_184 +10013828 t .text_185 +1001382c t .text_186 +10013830 t .text_187 +10013834 t .text_188 +10013838 t .text_189 +1001383c t .text_190 +10013840 t .text_191 +10013844 t .text_192 +10013848 t ?_10 +10013878 t ?_11 +100138ac t ?_12 +100138c0 t ?Veneer (6) for HalGetCpuClk +100138c8 t ?Veneer (6) for HalPinCtrlRtl8195A +100138d0 t ?Veneer (6) for VectorTableInitRtl8195A +100138d8 T PatchHalLogUartInit +10013960 t ??PatchHalLogUartInit_0 +10013966 T PSHalInitPlatformLogUart +10013966 t .text_6 +100139de T SYSIrqHandle +100139de t .text_7 +100139e8 t ??CrossCallReturnLabel_8 +10013a0e T InitSYSIRQ +10013a0e t .text_8 +10013a1c t ??CrossCallReturnLabel_1 +10013a2a T vWFSSVCHandler +10013a2a t .text_9 +10013a2c T WakeFromSLPPG +10013a2c t .text_10 +10013b08 T DurationScaleAndPeriodOP +10013b08 t .text_11 +10013b20 t ??DurationScaleAndPeriodOP_0 +10013b2e t ??DurationScaleAndPeriodOP_1 +10013b36 T CLKCal +10013b36 t .text_12 +10013b40 t ??CLKCal_0 +10013b46 t ??CLKCal_1 +10013b60 t ??CLKCal_2 +10013b64 T BackupCPUClk +10013b64 t .text_13 +10013b7e T ReFillCpuClk +10013b7e t .text_14 +10013b9a t .text_21 +10013b9a t ?Subroutine6 +10013ba4 T SetSYSTimer +10013ba4 t .text_32 +10013bd2 T SleepCG +10013bd2 t .text_33 +10013c16 t ??CrossCallReturnLabel_15 +10013c1a t ??SleepCG_0 +10013c42 t ??SleepCG_1 +10013c46 t ??CrossCallReturnLabel_6 +10013c62 t ??SleepCG_2 +10013c66 t .text_34 +10013c66 t ?Subroutine3 +10013c6c t .text_45 +10013c6c t ?Subroutine1 +10013c80 t ??DataTable39 +10013c84 t ??DataTable40 +10013c88 t ??DataTable40_1 +10013c8c t ??DataTable40_2 +10013c90 t ??DataTable40_3 +10013c94 t ??DataTable40_4 +10013c98 t ??DataTable40_5 +10013c9c t ??DataTable40_6 +10013ca0 t ??DataTable40_7 +10013ca4 t ??DataTable40_8 +10013ca8 t ??DataTable40_9 +10013cac t ??DataTable40_10 +10013cb0 t ??DataTable40_11 +10013cb4 t ??DataTable40_12 +10013cb8 t ??DataTable40_13 +10013cbc t ??DataTable40_14 +10013cc0 t ??DataTable40_15 +10013cc4 t ??DataTable40_16 +10013cc8 t ??DataTable40_17 +10013ccc t ??DataTable40_18 +10013cd0 t ??DataTable40_19 +10013cd4 t ??DataTable40_20 +10013cd8 t ??DataTable40_21 +10013cdc t ??DataTable40_26 +10013ce0 t ??DataTable40_28 +10013ce4 t ??DataTable40_37 +10013ce8 T tcm_heap_init +10013d16 T tcm_heap_allocmem +10013d16 t .text_6 +10013d66 T tcm_heap_freemem +10013d66 t .text_7 +10013dd4 t .text_8 +10013de0 t .text_9 +10013dec t .text_11 +10013df0 t .text_12 +10013df4 t .text_13 +10013df8 T tcm_heap_malloc +10013df8 t .text_14 +10013e0a T tcm_heap_calloc +10013e0a t .text_15 +10013e24 T tcm_heap_free +10013e24 t .text_16 +10013e34 T RtlMalloc +10013e4c T RtlMfree +10013e4c t .text_4 +10013e50 T RtlUpSemaFromISR +10013e50 t .text_10 +10013e68 t ??RtlUpSemaFromISR_0 +10013e6a T RtlUdelayOS +10013e6a t .text_27 +10013e70 t ?Veneer (6) for rtw_parse_wpa2_ie +10013e78 t ?Veneer (6) for rtw_parse_wpa_ie +10013e80 t ?Veneer (6) for rtw_get_ie +10013e88 t ?Veneer (6) for key_2char2num +10013e90 t check_fwstate +10013e9e T wireless_send_event +10013e9e t .text_4 +10013ea8 T indicate_wx_custom_event +10013ea8 t .text_5 +10013f00 t .text_6 +10013f08 T indicate_wx_scan_result_present +10013f08 t .text_7 +10013f1a T indicate_wx_scan_complete_event +10013f1a t .text_8 +10013f3a t .text_9 +10013f48 T rtw_indicate_wx_assoc_event +10013f48 t .text_10 +10013f64 t .text_11 +10013f70 T rtw_indicate_wx_disassoc_event +10013f70 t .text_12 +10013f88 t .text_13 +10013f96 t .text_14 +10013f9c t .text_15 +10013f9c t wpa_set_encryption +10014128 t .text_16 +1001412c t ??__FUNCTION__ +10014140 T rtw_set_wpa_ie +10014140 t .text_18 +10014244 t .text_19 +1001424e t .text_20 +1001424e t rtw_wx_set_pscan_freq +100142c2 t .text_21 +100142c2 t rtw_wx_set_autoreconnect +100142da t .text_22 +100142da t rtw_wx_get_autoreconnect +100142e8 t .text_23 +100142e8 t rtw_wx_set_custome_ie +10014390 t .text_24 +10014390 t rtw_wx_update_custome_ie +100143fc t .text_25 +100143fc t rtw_wx_del_custome_ie +10014444 t .text_26 +1001444a t .text_27 +1001444a t rtw_forwarding_set +1001446c t .text_28 +1001446c t rtw_wx_set_wap +10014574 t ??__FUNCTION___2 +10014584 t .text_30 +1001458a t .text_31 +10014594 t .text_32 +10014594 t rtw_wx_set_scan +10014674 t ??__FUNCTION___3 +10014684 t .text_34 +1001468e t .text_35 +1001468e t rtw_wx_set_essid +100147b8 t ??__FUNCTION___4 +100147cc t .text_37 +100147d8 t .text_38 +100147d8 t rtw_wx_set_auth +100148a4 t .text_39 +100148a4 t rtw_wx_set_enc_ext +1001496c t ?_3 +10014974 t ?_1 +1001497c t ?_2 +10014984 t .text_43 +1001498a T strtopsk +1001498a t .text_44 +100149f2 T rtw_wx_get_passphrase +100149f2 t .text_45 +10014a22 T rtw_wx_set_ap_essid +10014a22 t .text_46 +10014b22 t .text_47 +10014b22 t rtw_wx_read32 +10014bb8 t ?_4 +10014bc0 t ?_5 +10014bc8 t ?_6 +10014bd0 t ?_7 +10014bd8 t .text_52 +10014bd8 t rtw_wx_write32 +10014c3c t ?_8 +10014c48 T mac_reg_dump +10014c48 t .text_54 +10014cc4 t .text_55 +10014cc8 t ?_13 +10014ce4 t .text_57 +10014cf4 T bb_reg_dump +10014cf4 t .text_58 +10014d50 t ?_17 +10014d6c t ?_14 +10014d74 T rf_reg_dump +10014d74 t .text_61 +10014dfc t .text_62 +10014e00 t ?_18 +10014e1c t ?_20 +10014e24 t ?_19 +10014e34 t ?_15 +10014e40 t .text_67 +10014e48 t .text_68 +10014e48 t rtw_pm_set +10014e66 t .text_69 +10014e66 t rtw_dbg_port +10015154 t ?_21 +1001516c t ?_22 +10015188 t ?_23 +100151a4 t ?_24 +100151c0 t ?_25 +100151dc t ?_26 +100151f8 t ?_27 +10015210 t ?_28 +10015228 t ?_29 +10015260 t ?_30 +10015298 t ?_31 +100152b4 t ?_32 +100152e0 t ?_33 +10015308 t ?_34 +10015338 t ?_35 +10015370 t ?_36 +100153a4 t ?_37 +100153dc t ?_38 +10015408 t .text_88 +10015414 t .text_89 +10015422 t .text_90 +1001542c T rtw_ex_write_mac +1001542c t .text_91 +10015496 t .text_92 +10015496 t rtw_ex_get_client_list +1001552a t .text_93 +1001552a t rtw_ex_get_ap_info +10015600 T rtw_ex_set +10015600 t .text_94 +10015626 T rtw_ex_get +10015626 t .text_95 +10015738 t .text_96 +1001573c t .text_97 +10015740 t .text_98 +10015746 t .text_99 +10015746 t get_priv_size +10015758 t .text_100 +10015758 t rtw_ioctl_wext_private +10015b3c t .text_101 +10015b40 t .text_102 +10015b4c t .text_103 +10015b56 t .text_104 +10015b62 t .text_105 +10015b6e t .text_106 +10015b78 t .text_107 +10015b80 T rtw_ioctl +10015b80 t .text_108 +10015f74 t .text_109 +10015f78 t .text_110 +10015f7c t .text_111 +10015f80 t .text_112 +10015f84 t .text_113 +10015f88 t .text_114 +10015f8c t .text_115 +10015f90 t .text_116 +10015f9c t .text_117 +10015fa8 t .text_118 +10015fb4 t .text_119 +10015fba t .text_120 +10015fc4 t ??__FUNCTION___1 +10015fd4 t ?_39 +10015fe8 t ?_40 +10015ff0 t ?_41 +10016014 t ?_42 +10016030 t ?_43 +10016054 t ?_44 +10016090 t ?_45 +100160b0 t ?_48 +100160b4 t ?_50 +100160bc t ?_53 +100160c4 t rtw_private_args +1001628c t iw_priv_type_size +10016294 t ?Veneer (6) for rtw_get_sec_ie +1001629c t get_WLAN_BSSID_EX_sz +100162a2 t .text_3 +100162a2 t check_fwstate +100162b0 t .text_4 +100162b0 t set_fwstate +100162c2 T _rtw_init_evt_priv +100162c2 t .text_6 +100162d4 T _rtw_free_cmd_priv +100162d4 t .text_8 +100162e0 T _rtw_enqueue_cmd +100162e0 t .text_9 +100162fe T _rtw_dequeue_cmd +100162fe t .text_10 +10016324 t .text_11 +1001632e t .text_12 +10016338 T _rtw_observequeue_cmd +10016338 t .text_13 +1001634e T rtw_init_cmd_priv +1001634e t .text_14 +10016350 t .text_15 +10016358 T rtw_init_evt_priv +10016358 t .text_16 +1001635a T rtw_free_evt_priv +1001635a t .text_17 +1001635c T rtw_free_cmd_priv +1001635c t .text_18 +1001635e T rtw_cmd_filter +1001635e t .text_19 +10016382 T rtw_enqueue_cmd +10016382 t .text_20 +100163d8 T rtw_dequeue_cmd +100163d8 t .text_21 +100163da T rtw_observequeue_cmd +100163da t .text_22 +100163dc T rtw_free_cmd_obj +100163dc t .text_23 +10016408 T rtw_cmd_thread +10016408 t .text_24 +1001652c t .text_25 +1001653c T rtw_sitesurvey_cmd +1001653c t .text_26 +10016618 T rtw_joinbss_cmd +10016618 t .text_28 +100167f8 t .text_29 +10016802 t .text_30 +10016810 T rtw_disassoc_cmd +10016810 t .text_31 +10016840 T rtw_setstakey_cmd +10016840 t .text_33 +10016924 T rtw_clearstakey_cmd +10016924 t .text_34 +100169b4 t .text_35 +100169bc t .text_37 +100169c4 t .text_38 +100169cc t .text_39 +100169da T rtw_dynamic_chk_wk_cmd +100169da t .text_40 +10016a10 T rtw_set_chplan_cmd +10016a10 t .text_41 +10016a86 t .text_42 +10016a90 t .text_43 +10016a98 t .text_44 +10016a98 t traffic_status_watchdog +10016b2a T dynamic_chk_wk_hdl +10016b2a t .text_45 +10016b44 T lps_ctrl_wk_hdl +10016b44 t .text_46 +10016bbe T rtw_lps_ctrl_wk_cmd +10016bbe t .text_47 +10016bf8 t .text_48 +10016c00 T rpt_timer_setting_wk_hdl +10016c00 t .text_49 +10016c0c t .text_51 +10016c12 t .text_52 +10016c22 T rtw_ps_cmd +10016c22 t .text_54 +10016c66 T rtw_chk_hi_queue_cmd +10016c66 t .text_55 +10016c94 t .text_57 +10016ca4 T rtw_drvextra_cmd_hdl +10016ca4 t .text_58 +10016d8c T rtw_survey_cmd_callback +10016d8c t .text_59 +10016d9c T rtw_disassoc_cmd_callback +10016d9c t .text_60 +10016dca T rtw_joinbss_cmd_callback +10016dca t .text_61 +10016dd8 t .text_62 +10016dec T rtw_setstaKey_cmdrsp_callback +10016dec t .text_63 +10016e00 t ?_0 +10016e10 T rtw_cmd_callback +10016e10 t .text_65 +10017008 T wlancmds +10017008 t .text_66 +10017200 T rtw_hal_chip_configure +10017212 t __iar_annotation$$tailcall +10017216 T rtw_hal_read_chip_info +10017216 t .text_3 +10017228 t __iar_annotation$$tailcall +1001722c T rtw_hal_read_chip_version +1001722c t .text_4 +1001723e t __iar_annotation$$tailcall +10017242 T rtw_hal_def_value_init +10017242 t .text_5 +10017254 t __iar_annotation$$tailcall +10017258 T rtw_hal_free_data +10017258 t .text_6 +1001726a t __iar_annotation$$tailcall +1001726e T rtw_hal_dm_init +1001726e t .text_7 +10017280 t __iar_annotation$$tailcall +10017284 T rtw_hal_dm_deinit +10017284 t .text_8 +10017296 t __iar_annotation$$tailcall +1001729a T rtw_hal_sw_led_deinit +1001729a t .text_10 +100172ac t __iar_annotation$$tailcall +100172b0 T rtw_hal_init +100172b0 t .text_12 +100172f6 T rtw_hal_deinit +100172f6 t .text_13 +10017310 T rtw_hal_set_hwreg +10017310 t .text_14 +10017320 t __iar_annotation$$tailcall +10017324 T rtw_hal_get_hwreg +10017324 t .text_15 +10017334 t __iar_annotation$$tailcall +10017338 T rtw_hal_set_def_var +10017338 t .text_16 +10017348 t __iar_annotation$$tailcall +1001734e T rtw_hal_get_def_var +1001734e t .text_17 +1001735e t __iar_annotation$$tailcall +10017364 T rtw_hal_set_odm_var +10017364 t .text_18 +10017374 T rtw_hal_enable_interrupt +10017374 t .text_20 +10017390 t __iar_annotation$$tailcall +10017394 T rtw_hal_disable_interrupt +10017394 t .text_21 +100173b0 t __iar_annotation$$tailcall +100173b4 T rtw_hal_inirp_init +100173b4 t .text_22 +100173c4 t __iar_annotation$$tailcall +100173c8 T rtw_hal_inirp_deinit +100173c8 t .text_23 +100173d2 t __iar_annotation$$tailcall +100173d8 T rtw_hal_irp_reset +100173d8 t .text_24 +100173e2 t __iar_annotation$$tailcall +100173e6 T rtw_hal_xmit +100173e6 t .text_26 +100173f0 t __iar_annotation$$tailcall +100173f6 T rtw_hal_mgnt_xmit +100173f6 t .text_27 +1001740c t __iar_annotation$$tailcall +10017410 T rtw_hal_init_xmit_priv +10017410 t .text_28 +1001741a t __iar_annotation$$tailcall +10017420 T rtw_hal_free_xmit_priv +10017420 t .text_29 +1001742a t __iar_annotation$$tailcall +1001742e T rtw_hal_init_recv_priv +1001742e t .text_30 +10017438 t __iar_annotation$$tailcall +1001743e T rtw_hal_free_recv_priv +1001743e t .text_31 +10017448 t __iar_annotation$$tailcall +1001744c T rtw_hal_update_ra_mask +1001744c t .text_32 +1001747c T rtw_hal_add_ra_tid +1001747c t .text_33 +1001748c T rtw_hal_clone_data +1001748c t .text_35 +10017496 t __iar_annotation$$tailcall +1001749a T rtw_hal_start_thread +1001749a t .text_36 +100174a4 t __iar_annotation$$tailcall +100174a8 T rtw_hal_stop_thread +100174a8 t .text_37 +100174b2 t __iar_annotation$$tailcall +100174b6 T rtw_hal_read_bbreg +100174b6 t .text_38 +100174cc T rtw_hal_write_bbreg +100174cc t .text_39 +100174dc T rtw_hal_read_rfreg +100174dc t .text_40 +100174f2 T rtw_hal_write_rfreg +100174f2 t .text_41 +10017506 T rtw_hal_interrupt_handler +10017506 t .text_42 +10017510 t __iar_annotation$$tailcall +10017516 T rtw_hal_set_bwmode +10017516 t .text_43 +10017526 t __iar_annotation$$tailcall +1001752a T rtw_hal_set_chan +1001752a t .text_44 +10017534 t __iar_annotation$$tailcall +10017538 T rtw_hal_set_chnl_bw +10017538 t .text_45 +1001754c T rtw_hal_dm_watchdog +1001754c t .text_46 +10017556 t __iar_annotation$$tailcall +1001755a T rtw_hal_notch_filter +1001755a t .text_50 +10017564 t __iar_annotation$$tailcall +10017568 T rtw_hal_reset_security_engine +10017568 t .text_51 +10017572 t __iar_annotation$$tailcall +10017576 T decide_chip_type_by_device_id +10017576 t .text_52 +1001757c t ?Veneer (6) for PHY_SetBBReg_8195A +10017584 T _InitPowerOn +10017584 t .text_8 +100175e6 t .text_9 +100175ee t .text_10 +100175ee t _InitNormalChipRegPriority +10017646 t .text_11 +10017646 t _InitNormalChipQueuePriority +100176ec T _InitDriverInfoSize +100176ec t .text_12 +100176f6 T _InitNetworkType +100176f6 t .text_13 +10017718 T _InitWMACSetting +10017718 t .text_14 +1001777c T _InitAdaptiveCtrl +1001777c t .text_15 +100177b8 T _InitEDCA +100177b8 t .text_16 +1001781e t .text_17 +10017824 T _InitRateFallback +10017824 t .text_18 +1001785c t .text_19 +10017866 T _InitRetryFunction +10017866 t .text_20 +1001788e T _InitOperationMode +1001788e t .text_21 +100178e4 t .text_22 +100178ea T _InitInterrupt +100178ea t .text_23 +10017924 t .text_25 +10017924 t rtl8195a_hal_init +10017bd0 t .text_26 +10017bda t .text_27 +10017bda t rtl8195a_hal_deinit +10017c00 t .text_28 +10017c0e t .text_29 +10017c0e t rtl8195ab_init_default_value +10017c12 t .text_30 +10017c12 t rtl8195a_interface_configure +10017c60 t .text_31 +10017c60 t _ReadEfuseInfo8195a +10017d0e t .text_32 +10017d16 t .text_33 +10017d16 t ReadAdapterInfo8195a +10017d44 T SetHwReg8195AB +10017d44 t .text_34 +10017dcc t .text_35 +10017dd6 t .text_36 +10017de2 T GetHwReg8195AB +10017de2 t .text_37 +10017de6 T GetHalDefVar8195AB +10017de6 t .text_38 +10017e36 T SetHalDefVar8195AB +10017e36 t .text_39 +10017ed8 T rtl8195ab_set_hal_ops +10017ed8 t .text_40 +10017f74 t .text_41 +10017f78 t .text_42 +10017f7c t .text_43 +10017f80 t .text_44 +10017f84 t .text_45 +10017f88 t .text_46 +10017f8c t .text_47 +10017f90 t .text_48 +10017f94 t .text_49 +10017f98 t .text_50 +10017f9c t .text_51 +10017fa0 t .text_52 +10017fa4 t .text_53 +10017fa8 t .text_54 +10017fac t .text_55 +10017fb0 t .text_56 +10017fb4 t .text_57 +10017fb8 t .text_58 +10017fbc t .text_59 +10017fc0 t .text_60 +10017fc4 t .text_61 +10017fc8 t .text_62 +10017fcc t .text_63 +10017fd0 t .text_64 +10017fd4 t .text_65 +10017fd8 t .text_66 +10017fdc t .text_67 +10017fe0 t .text_68 +10017fe4 t .text_69 +10017fe8 t .text_70 +10017fec t .text_71 +10017ff0 t .text_72 +10017ff4 t .text_73 +10017ff8 t .text_74 +10017ffc t .text_75 +10018000 t .text_76 +10018004 t ?_0 +1001800c t check_fwstate +1001801a T rtw_init_default_value +1001801a t .text_3 +1001808c T rtw_cancel_all_timer +1001808c t .text_4 +100180fa T rtw_free_drv_sw +100180fa t .text_5 +10018172 T rtw_reset_drv_sw +10018172 t .text_6 +100181c6 T rtw_init_drv_sw +100181c6 t .text_7 +10018242 T rtw_drv_deinit +10018242 t .text_8 +10018250 T rtw_start_drv_threads +10018250 t .text_9 +100182ec t .text_10 +100182f0 t .text_11 +100182f4 t .text_12 +100182f8 t .text_13 +100182fc T rtw_stop_drv_threads +100182fc t .text_14 +10018334 t ?_0 +10018348 t ?_1 +1001835c t ?_2 +10018374 t ?_3 +10018380 t ?Veneer (6) for rtw_set_ie +10018388 t ?Veneer (6) for rtw_get_bit_value_from_ieee_value +10018390 t ?Veneer (6) for rtw_get_rateset_len +10018398 t ?Veneer (6) for rtw_check_network_type +100183a0 t ?Veneer (6) for rtw_set_supported_rate +100183a8 t ?Veneer (6) for rtw_get_wps_ie +100183b0 t check_fwstate +100183be T init_mlme_ap_info +100183be t .text_3 +100183d4 T free_mlme_ap_info +100183d4 t .text_4 +1001841e t .text_5 +10018426 t .text_6 +10018426 t update_BCNTIM +10018542 T chk_sta_is_alive +10018542 t .text_7 +10018576 T expire_timeout_chk +10018576 t .text_8 +10018694 t ?_1 +100186d4 t .text_10 +100186dc t .text_11 +100186e4 T add_RATid +100186e4 t .text_12 +100187f8 t .text_13 +100187fc t .text_14 +100187fc t update_bmc_sta +100188d4 t .text_15 +100188dc t .text_16 +100188e8 T update_sta_info_apmode +100188e8 t .text_17 +10018994 t .text_18 +10018994 t start_bss_network +10018c60 t .text_19 +10018c66 T rtw_check_beacon_data +10018c66 t .text_20 +10018fd6 t .text_21 +10018fe8 t .text_22 +10018ffa t .text_23 +10019002 t .text_24 +1001900c t .text_25 +1001900c t update_bcn_wps_ie +100190aa t .text_26 +100190aa t update_bcn_vendor_spec_ie +100190f4 t .text_27 +100190f8 t .text_28 +100190fc t .text_29 +10019100 T update_beacon +10019100 t .text_30 +100191ac t .text_31 +100191ac t rtw_ht_operation_update +1001924c T associated_clients_update +1001924c t .text_32 +10019292 T bss_cap_update_on_sta_join +10019292 t .text_33 +100193f0 T bss_cap_update_on_sta_leave +100193f0 t .text_34 +100194c2 t .text_35 +100194ca t .text_36 +100194ce T ap_free_sta +100194ce t .text_37 +10019562 T rtw_sta_flush +10019562 t .text_38 +100195e4 T sta_info_update +100195e4 t .text_39 +10019626 T ap_sta_info_defer_update +10019626 t .text_40 +10019642 T start_ap_mode +10019642 t .text_41 +10019682 T stop_ap_mode +10019682 t .text_42 +100196c6 t .text_43 +100196d0 t .text_44 +100196dc T rtw_generate_bcn_ie +100196dc t .text_45 +10019948 t .text_46 +10019952 t .text_47 +10019958 t .text_49 +1001995c t .text_50 +10019960 t .text_51 +10019964 t .text_52 +10019968 t .text_53 +1001996c t .text_54 +10019970 t .text_55 +10019974 t ?_2 +10019978 t ?_3 +10019980 t ?_4 +10019988 t ?_5 +10019990 t ?_6 +10019998 t ?Veneer (6) for rtw_get_wpa_ie +100199a0 t ?Veneer (6) for rtw_get_wpa2_ie +100199a8 t ?Veneer (6) for rtw_ieee802_11_parse_elems +100199b0 t ?Veneer (6) for rtw_get_wps_attr_content +100199b8 t ?Veneer (6) for rtw_set_fixed_ie +100199c0 t get_da +100199da t .text_7 +100199da t check_fwstate +100199e8 T rtw_is_channel_set_contains_channel +100199e8 t .text_8 +10019a0c T init_hw_mlme_ext +10019a0c t .text_9 +10019a20 t .text_10 +10019a20 t init_mlme_ext_priv_value +10019ae4 t ?_14 +10019af4 t ?_15 +10019b04 T init_channel_set +10019b04 t .text_13 +10019bb8 t RTW_ChannelPlanMap +10019c6c t RTW_ChannelPlan2G +10019cc8 T init_mlme_ext_priv +10019cc8 t .text_16 +10019cfa T free_mlme_ext_priv +10019cfa t .text_17 +10019d22 t .text_18 +10019d22 t _mgt_dispatcher +10019d64 t ?_16 +10019d6c T mgt_dispatcher +10019d6c t .text_20 +10019df4 t ?_17 +10019dfc t .text_22 +10019e02 T OnProbeReq +10019e02 t .text_23 +10019ebc t .text_24 +10019ec2 T OnProbeRsp +10019ec2 t .text_25 +10019ed4 T OnBeacon +10019ed4 t .text_26 +10019fd4 t ?_19 +1001a008 T OnAuth +1001a008 t .text_28 +1001a238 t .text_29 +1001a23c t ?_20 +1001a278 t ?_21 +1001a2c0 t .text_32 +1001a2cc T OnAuthClient +1001a2cc t .text_33 +1001a394 t ?_22 +1001a3c4 t .text_35 +1001a3cc T OnAssocReq +1001a3cc t .text_36 +1001a9b0 t ?_23 +1001a9d0 T WMM_INFO_OUI +1001a9d0 t .text_38 +1001a9d8 t .text_39 +1001a9e0 t .text_40 +1001a9ec t .text_41 +1001a9f4 T OnAssocRsp +1001a9f4 t .text_42 +1001aaf8 t .text_43 +1001aafc t ?_24 +1001ab2c T OnDeAuth +1001ab2c t .text_45 +1001abd0 t ?_25 +1001ac24 t ?_26 +1001ac7c t .text_48 +1001ac96 t .text_49 +1001aca0 t .text_50 +1001acaa t .text_51 +1001acb0 t .text_52 +1001acb8 T OnDisassoc +1001acb8 t .text_53 +1001ad58 t .text_54 +1001ad60 t ?_28 +1001adb8 t ?_29 +1001ae10 t .text_57 +1001ae1a t .text_58 +1001ae26 t .text_59 +1001ae30 t .text_60 +1001ae3c t .text_61 +1001ae54 t .text_62 +1001ae62 t .text_63 +1001ae6c t .text_64 +1001ae70 t .text_65 +1001ae74 t .text_66 +1001ae78 t .text_67 +1001ae80 t .text_68 +1001ae86 t .text_69 +1001ae9c t .text_70 +1001aeac t .text_71 +1001aeb8 T OnAction_back +1001aeb8 t .text_72 +1001af96 T OnAction +1001af96 t .text_75 +1001afaa T DoReserved +1001afaa t .text_76 +1001afae T alloc_mgtxmitframe +1001afae t .text_77 +1001afe2 T update_mgnt_tx_rate +1001afe2 t .text_78 +1001afe8 T update_mgntframe_attrib +1001afe8 t .text_79 +1001b03e T dump_mgntframe +1001b03e t .text_80 +1001b056 T update_hidden_ssid +1001b056 t .text_81 +1001b0a0 T issue_beacon +1001b0a0 t .text_82 +1001b2a8 t .text_83 +1001b2b0 t ?_30 +1001b2b8 t .text_85 +1001b2c0 t .text_86 +1001b2d0 T issue_probersp +1001b2d0 t .text_87 +1001b51c t .text_88 +1001b528 t .text_89 +1001b534 t .text_90 +1001b53c t .text_91 +1001b546 t .text_92 +1001b556 T issue_probereq +1001b556 t .text_93 +1001b6c0 t ?_32 +1001b6c8 t .text_95 +1001b6e4 t .text_96 +1001b6ec t .text_97 +1001b6f4 T issue_auth +1001b6f4 t .text_98 +1001b8bc t .text_99 +1001b8c4 t .text_100 +1001b8ce t .text_101 +1001b8dc t .text_102 +1001b8e4 t .text_103 +1001b8ec t .text_104 +1001b8f4 t .text_105 +1001b900 t .text_106 +1001b90c T issue_asocrsp +1001b90c t .text_107 +1001bb30 t .text_108 +1001bb34 T WMM_PARA_OUI +1001bb34 t .text_109 +1001bb3c t .text_110 +1001bb48 t .text_111 +1001bb54 t .text_112 +1001bb66 t .text_113 +1001bb72 t .text_114 +1001bb78 T issue_assocreq +1001bb78 t .text_115 +1001be94 T MCS_rate_1R +1001be94 t .text_116 +1001bea4 T MCS_rate_2R +1001bea4 t .text_117 +1001beb4 T WPS_OUI +1001beb4 t .text_118 +1001beb8 T RTW_WPA_OUI +1001beb8 t .text_119 +1001bebc t .text_120 +1001bec4 t .text_121 +1001bece t .text_122 +1001bed8 t ?_31 +1001beec t .text_124 +1001bef4 t .text_125 +1001bef8 t .text_126 +1001befc t .text_127 +1001bf00 t .text_128 +1001bf06 t .text_129 +1001bf10 t .text_130 +1001bf1c t .text_131 +1001bf24 T issue_nulldata +1001bf24 t .text_132 +1001bfd8 t .text_133 +1001bfe2 T issue_qos_nulldata +1001bfe2 t .text_134 +1001c0f6 t .text_135 +1001c106 t .text_136 +1001c110 t .text_137 +1001c118 T issue_deauth +1001c118 t .text_138 +1001c1aa t .text_139 +1001c1b2 t .text_140 +1001c1ba t .text_141 +1001c1c6 t .text_142 +1001c1d6 T issue_action_BA +1001c1d6 t .text_143 +1001c3e4 t .text_144 +1001c3ea t .text_145 +1001c3f6 t .text_146 +1001c414 t .text_147 +1001c41c t .text_148 +1001c428 t .text_149 +1001c430 t .text_150 +1001c43e t .text_151 +1001c43e t issue_action_BSSCoexistPacket +1001c610 t .text_152 +1001c618 t .text_153 +1001c628 t .text_154 +1001c634 t .text_155 +1001c644 T site_survey +1001c644 t .text_157 +1001c846 t .text_158 +1001c850 T collect_bss_info +1001c850 t .text_159 +1001ca3e t .text_160 +1001ca46 t .text_161 +1001ca4c T start_clnt_join +1001ca4c t .text_162 +1001cb1e T start_clnt_auth +1001cb1e t .text_163 +1001cb88 t ?_34 +1001cbc8 T start_clnt_assoc +1001cbc8 t .text_165 +1001cbf0 t .text_166 +1001cbf8 t .text_167 +1001cc04 T receive_disconnect +1001cc04 t .text_168 +1001cc56 T report_scan_result_one +1001cc56 t .text_169 +1001cdce t .text_170 +1001cdda T add_site_survey +1001cdda t .text_171 +1001cf54 t .text_172 +1001cf5e T report_survey_event +1001cf5e t .text_173 +1001d0ac t .text_174 +1001d0b8 T report_surveydone_event +1001d0b8 t .text_175 +1001d104 t .text_176 +1001d10c T report_join_res +1001d10c t .text_177 +1001d174 t .text_178 +1001d182 t .text_179 +1001d19a T report_del_sta_event +1001d19a t .text_180 +1001d22e t .text_181 +1001d234 t .text_182 +1001d23e T report_add_sta_event +1001d23e t .text_183 +1001d2c0 T rtw_port_switch_chk +1001d2c0 t .text_184 +1001d34e T update_sta_info +1001d34e t .text_185 +1001d3be T mlmeext_joinbss_event_callback +1001d3be t .text_186 +1001d4d6 T mlmeext_sta_del_event_callback +1001d4d6 t .text_187 +1001d526 t .text_188 +1001d532 t .text_189 +1001d53a t .text_190 +1001d548 T null_addr +1001d548 t .text_191 +1001d550 t .text_192 +1001d55c t .text_193 +1001d562 T _linked_rx_signal_strehgth_display +1001d562 t .text_194 +1001d59a T linked_status_chk +1001d59a t .text_195 +1001d782 t .text_196 +1001d78e T survey_timer_hdl +1001d78e t .text_197 +1001d820 t .text_198 +1001d824 t .text_199 +1001d828 t .text_200 +1001d82c t .text_201 +1001d830 t .text_202 +1001d838 t .text_203 +1001d840 t .text_204 +1001d84a T link_timer_hdl +1001d84a t .text_205 +1001d8ba T addba_timer_hdl +1001d8ba t .text_206 +1001d8d6 T NULL_hdl +1001d8d6 t .text_207 +1001d8da T setopmode_hdl +1001d8da t .text_208 +1001d916 T join_cmd_hdl +1001d916 t .text_209 +1001da6a T disconnect_hdl +1001da6a t .text_210 +1001daf2 t .text_211 +1001dafa t .text_212 +1001db00 t .text_213 +1001db0a t .text_214 +1001db12 T sitesurvey_cmd_hdl +1001db12 t .text_215 +1001dbfa T setauth_hdl +1001dbfa t .text_216 +1001dc08 T setkey_hdl +1001dc08 t .text_217 +1001dc54 T set_stakey_hdl +1001dc54 t .text_218 +1001dd2c t .text_219 +1001dd30 t .text_220 +1001dd34 T set_tx_beacon_cmd +1001dd34 t .text_221 +1001dda2 t .text_222 +1001ddb0 T mlme_evt_hdl +1001ddb0 t .text_223 +1001de00 T tx_beacon_hdl +1001de00 t .text_224 +1001deb6 T check_buddy_mlmeinfo_state +1001deb6 t .text_225 +1001ded8 T concurrent_chk_start_clnt_join +1001ded8 t .text_226 +1001df68 t .text_227 +1001df70 t .text_228 +1001df7a T concurrent_chk_joinbss_done +1001df7a t .text_229 +1001e104 t .text_230 +1001e114 t .text_231 +1001e120 T set_chplan_hdl +1001e120 t .text_232 +1001e13c T _survey_timer_hdl +1001e13c t .text_233 +1001e140 T _link_timer_hdl +1001e140 t .text_234 +1001e144 T init_mlme_ext_timer +1001e144 t .text_235 +1001e190 t .text_236 +1001e194 t .text_237 +1001e198 t .text_238 +1001e19c t .text_239 +1001e1a0 T issue_EAPOL_start +1001e1a0 t .text_240 +1001e200 t __iar_annotation$$tailcall +1001e204 t ?_27 +1001e21c t ?_35 +1001e260 t ?_37 +1001e2b8 t ?_38 +1001e30c t ?_39 +1001e374 t ?_40 +1001e384 t ?_41 +1001e390 t ?_42 +1001e3a0 t wlanevents +1001e460 T WMM_OUI +1001e460 t .text_250 +1001e464 t get_WLAN_BSSID_EX_sz +1001e46a t .text_4 +1001e46a t check_fwstate +1001e478 t .text_5 +1001e478 t set_fwstate +1001e48a t .text_6 +1001e48a t _clr_fwstate_ +1001e49c T rtw_join_timeout_handler +1001e49c t .text_7 +1001e4d2 T _rtw_scan_timeout_handler +1001e4d2 t .text_8 +1001e4d6 T _dynamic_check_timer_handlder +1001e4d6 t .text_9 +1001e4fc T rtw_init_mlme_timer +1001e4fc t .text_10 +1001e548 t ?_0 +1001e554 t ?_1 +1001e564 t ?_2 +1001e578 T rtw_del_mlme_timer +1001e578 t .text_14 +1001e598 T reconnect_timer_hdl +1001e598 t .text_15 +1001e604 t .text_16 +1001e608 t .text_17 +1001e60c t .text_18 +1001e610 t .text_19 +1001e614 t .text_20 +1001e618 T _rtw_init_mlme_priv +1001e618 t .text_21 +1001e6b0 T rtw_mfree_mlme_priv_lock +1001e6b0 t .text_22 +1001e6cc t .text_23 +1001e6cc t rtw_free_mlme_ie_data +1001e6e4 T rtw_free_mlme_priv_ie_data +1001e6e4 t .text_24 +1001e71a T _rtw_free_mlme_priv +1001e71a t .text_25 +1001e740 T _rtw_alloc_network +1001e740 t .text_27 +1001e784 t .text_28 +1001e78e t .text_29 +1001e798 T _rtw_free_network +1001e798 t .text_30 +1001e80e T _rtw_free_network_nolock +1001e80e t .text_31 +1001e836 T _rtw_find_network +1001e836 t .text_32 +1001e872 T _rtw_free_network_queue +1001e872 t .text_33 +1001e8a4 t .text_34 +1001e8ae T rtw_if_up +1001e8ae t .text_35 +1001e8d4 T rtw_get_capability_from_ie +1001e8d4 t .text_37 +1001e8d8 T rtw_get_capability +1001e8d8 t .text_38 +1001e8ec T rtw_get_beacon_interval_from_ie +1001e8ec t .text_40 +1001e8f0 T rtw_init_mlme_priv +1001e8f0 t .text_41 +1001e908 T rtw_free_mlme_priv +1001e908 t .text_42 +1001e90a T rtw_alloc_network +1001e90a t .text_43 +1001e90c T rtw_free_network_nolock +1001e90c t .text_44 +1001e90e T rtw_free_network_queue +1001e90e t .text_45 +1001e910 T rtw_find_network +1001e910 t .text_46 +1001e912 T rtw_is_same_ibss +1001e912 t .text_47 +1001e92e T is_same_network +1001e92e t .text_48 +1001e99e T update_network +1001e99e t .text_50 +1001ea46 T rtw_update_scanned_network +1001ea46 t .text_51 +1001eb56 T rtw_add_network +1001eb56 t .text_52 +1001eb9c T rtw_survey_event_callback +1001eb9c t .text_53 +1001ec20 T rtw_surveydone_event_callback +1001ec20 t .text_54 +1001ed14 t .text_55 +1001ed1c T rtw_dummy_event_callback +1001ed1c t .text_56 +1001ed1e T rtw_free_assoc_resources +1001ed1e t .text_58 +1001edc8 t .text_59 +1001edce t .text_60 +1001edd8 t .text_61 +1001ede4 t .text_62 +1001edee t .text_63 +1001edf8 t .text_64 +1001ee00 T rtw_indicate_connect +1001ee00 t .text_65 +1001ee1c T rtw_indicate_disconnect +1001ee1c t .text_66 +1001ee40 T rtw_indicate_scan_done +1001ee40 t .text_67 +1001ee44 t .text_68 +1001ee44 t rtw_joinbss_update_stainfo +1001ef08 T rtw_joinbss_event_prehandle +1001ef08 t .text_69 +1001f070 T rtw_joinbss_event_callback +1001f070 t .text_70 +1001f08e T search_max_mac_id +1001f08e t .text_71 +1001f0da T rtw_stassoc_hw_rpt +1001f0da t .text_72 +1001f10a T rtw_stassoc_event_callback +1001f10a t .text_73 +1001f13a t .text_74 +1001f144 T rtw_stadel_event_callback +1001f144 t .text_75 +1001f1de t .text_76 +1001f1e6 T _rtw_join_timeout_handler +1001f1e6 t .text_77 +1001f264 t .text_78 +1001f26e T rtw_scan_timeout_handler +1001f26e t .text_79 +1001f286 t .text_80 +1001f290 t .text_81 +1001f29e T rtw_dynamic_check_timer_handlder +1001f29e t .text_82 +1001f35c T rtw_select_and_join_from_scanned_queue +1001f35c t .text_83 +1001f414 t .text_84 +1001f41e t .text_85 +1001f428 t .text_86 +1001f430 T rtw_set_auth +1001f430 t .text_87 +1001f47e T rtw_set_key +1001f47e t .text_88 +1001f53a T rtw_restruct_wmm_ie +1001f53a t .text_89 +1001f596 T rtw_restruct_sec_ie +1001f596 t .text_90 +1001f61c T rtw_joinbss_reset +1001f61c t .text_92 +1001f62e T rtw_restructure_ht_ie +1001f62e t .text_93 +1001f706 T rtw_update_ht_cap +1001f706 t .text_94 +1001f80c t .text_95 +1001f810 t .text_96 +1001f814 t .text_99 +1001f81e T rtw_buddy_adapter_up +1001f81e t .text_100 +1001f84e T check_buddy_fwstate +1001f84e t .text_101 +1001f874 t ?_4 +1001f898 t ?_5 +1001f8b0 t ?_6 +1001f8b8 T rtw_macaddr_cfg +1001f958 t .text_3 +1001f95c T rtw_get_cipher_info +1001f95c t .text_4 +1001f9d8 t .text_5 +1001f9e6 T rtw_get_bcn_info +1001f9e6 t .text_6 +1001fab0 T hci_dvobj_init +1001fab8 t __iar_annotation$$tailcall +1001fabe T hci_dvobj_deinit +1001fabe t .text_3 +1001fac6 t __iar_annotation$$tailcall +1001faca T hci_dvobj_request_irq +1001faca t .text_4 +1001fad2 t __iar_annotation$$tailcall +1001fad6 T hci_dvobj_free_irq +1001fad6 t .text_5 +1001fade t __iar_annotation$$tailcall +1001fae4 t .text_6 +1001fae8 t _enter_pwrlock +1001faec t .text_3 +1001faec t _exit_pwrlock +1001faf0 t .text_4 +1001faf0 t check_fwstate +1001fafe T ips_enter +1001fafe t .text_5 +1001fb88 T ips_leave +1001fb88 t .text_6 +1001fc94 T rtw_pwr_unassociated_idle +1001fc94 t .text_7 +1001fd00 T rtw_ps_processor +1001fd00 t .text_8 +1001fd48 t .text_9 +1001fd58 T pwr_state_check_handler +1001fd58 t .text_10 +1001fd5c T PS_RDY_CHECK +1001fd5c t .text_12 +1001fdd8 t .text_13 +1001fdde T rtw_set_ps_mode +1001fdde t .text_14 +1001fe48 T LPS_RF_ON_check +1001fe48 t .text_15 +1001fe98 T LPS_Enter +1001fe98 t .text_16 +1001fef2 T LPS_Leave +1001fef2 t .text_17 +1001ff22 T LeaveAllPowerSaveMode +1001ff22 t .text_18 +1001ff44 T rtw_init_pwrctrl_priv +1001ff44 t .text_19 +1001ffe0 t .text_20 +1001ffe4 t .text_21 +1001fff4 T rtw_free_pwrctrl_priv +1001fff4 t .text_22 +10020008 T _rtw_pwr_wakeup +10020008 t .text_23 +100200d2 T rtw_pm_set_lps +100200d2 t .text_24 +10020118 T rtw_pm_set_ips +10020118 t .text_25 +10020158 t ?_0 +1002016c t ??__FUNCTION__ +1002017c t low_level_output +10020198 t ??low_level_output_0 +1002019c t ??low_level_output_3 +100201b0 t ??low_level_output_2 +100201b6 t ??low_level_output_4 +100201d0 t ??low_level_output_5 +100201d2 t ??low_level_output_1 +100201d6 T ethernetif_recv +100201d6 t .text_4 +10020210 t ??ethernetif_recv_1 +1002022a t ??ethernetif_recv_2 +10020248 t ??ethernetif_recv_0 +1002024c T ethernetif_init +1002024c t .text_5 +10020268 t .text_6 +10020268 t arp_timer +1002027e T lwip_POST_SLEEP_PROCESSING +1002027e t .text_9 +10020290 t ??lwip_POST_SLEEP_PROCESSING_0 +10020294 t ??DataTable5 +10020298 t ??DataTable5_1 +1002029c t ??DataTable5_2 +100202a0 t ??DataTable5_3 +100202a4 t ?_0 +100202d0 t ?Veneer (6) for VectorIrqDisRtl8195A +100202d8 t ?Veneer (6) for VectorIrqUnRegisterRtl8195A +100202e0 t ?Veneer (6) for HalTimerDisRtl8195a +100202e8 T HalTimerIrq2To7Handle_Patch +10020306 t ??HalTimerIrq2To7Handle_Patch_0 +1002030e t ??HalTimerIrq2To7Handle_Patch_1 +1002033a t ??HalTimerIrq2To7Handle_Patch_3 +1002033e t ??HalTimerIrq2To7Handle_Patch_2 +10020348 T HalTimerIrqRegisterRtl8195a_Patch +10020348 t .text_4 +10020368 t ??HalTimerIrqRegisterRtl8195a_Patch_1 +1002036c t ??HalTimerIrqRegisterRtl8195a_Patch_0 +10020396 t ??HalTimerIrqRegisterRtl8195a_Patch_3 +100203a4 t ??HalTimerIrqRegisterRtl8195a_Patch_4 +100203ae t ??HalTimerIrqRegisterRtl8195a_Patch_2 +100203b2 T HalTimerInitRtl8195a_Patch +100203b2 t .text_5 +100203dc t ??HalTimerInitRtl8195a_Patch_1 +100203e0 t ??HalTimerInitRtl8195a_Patch_0 +10020408 t ??HalTimerInitRtl8195a_Patch_4 +10020412 t ??HalTimerInitRtl8195a_Patch_5 +10020416 t ??HalTimerInitRtl8195a_Patch_3 +1002041a t ??HalTimerInitRtl8195a_Patch_6 +10020458 t ??HalTimerInitRtl8195a_Patch_9 +10020460 t ??HalTimerInitRtl8195a_Patch_7 +1002046e t ??HalTimerInitRtl8195a_Patch_10 +10020470 t ??HalTimerInitRtl8195a_Patch_2 +10020474 t ??HalTimerInitRtl8195a_Patch_8 +10020486 t ??HalTimerInitRtl8195a_Patch_11 +1002048a T HalTimerIrqUnRegisterRtl8195a_Patch +1002048a t .text_6 +100204aa t ??HalTimerIrqUnRegisterRtl8195a_Patch_1 +100204ae t ??HalTimerIrqUnRegisterRtl8195a_Patch_0 +100204c6 t ??HalTimerIrqUnRegisterRtl8195a_Patch_3 +100204d2 t ??HalTimerIrqUnRegisterRtl8195a_Patch_4 +100204de t ??HalTimerIrqUnRegisterRtl8195a_Patch_2 +100204e8 t ??HalTimerIrqUnRegisterRtl8195a_Patch_6 +100204ee t ??HalTimerIrqUnRegisterRtl8195a_Patch_5 +100204f2 T HalTimerDeInitRtl8195a_Patch +100204f2 t .text_7 +1002050a t ??HalTimerDeInitRtl8195a_Patch_0 +1002051c T HalTimerReLoadRtl8195a_Patch +1002051c t .text_8 +10020538 t ??HalTimerReLoadRtl8195a_Patch_0 +10020542 t ??HalTimerReLoadRtl8195a_Patch_1 +10020544 t ??HalTimerReLoadRtl8195a_Patch_2 +1002055a t ??HalTimerReLoadRtl8195a_Patch_3 +10020566 T HalTimerReadCountRtl8195a_Patch +10020566 t .text_9 +10020572 t ??HalTimerReadCountRtl8195a_Patch_0 +1002057e t ??HalTimerReadCountRtl8195a_Patch_1 +10020580 T HalTimerIrqEnRtl8195a +10020580 t .text_10 +10020592 T HalTimerEnRtl8195a_Patch +10020592 t .text_12 +100205a4 T HalTimerDisRtl8195a_Patch +100205a4 t .text_13 +100205b8 t ??DataTable24 +100205bc t ??DataTable24_1 +100205c0 t ??DataTable24_2 +100205c4 t ??DataTable24_3 +100205c8 t ??DataTable24_4 +100205cc t ??DataTable24_5 +100205d0 t ??DataTable24_6 +100205d4 t ??DataTable24_7 +100205d8 t ??DataTable24_8 +100205dc t ??DataTable24_9 +100205e0 t ??DataTable24_10 +100205e4 t ??DataTable24_11 +100205e8 t ??__FUNCTION__ +10020604 t ?_0 +10020628 t ??__FUNCTION___1 +1002064c t ?_1 +10020678 t ??__FUNCTION___2 +10020694 t ?_2 +100206c4 t ?_3 +100206ec t ?_4 +10020718 t ?_5 +10020748 t ??__FUNCTION___3 +1002076c t ?_6 +10020798 t ??__FUNCTION___4 +100207b8 t ?_7 +10020804 t ?_8 +10020828 T HalTimerOpInit_Patch +10020848 t ??HalTimerOpInit_Patch_0 +10020864 t check_fwstate +10020872 T rtw_rpt_h_addr +10020872 t .text_4 +100208a8 T rtw_txrpt_read8 +100208a8 t .text_7 +100208ba t .text_8 +100208c2 T rtw_txrpt_write8 +100208c2 t .text_12 +100208d2 t .text_13 +100208dc T rtw_ratemask_read8 +100208dc t .text_16 +100208ec T rtw_ratemask_write8 +100208ec t .text_19 +100208f8 t .text_20 +100208fe T ReadRateMask8 +100208fe t .text_22 +10020908 T WriteRateMask8 +10020908 t .text_24 +1002090a T ReadTxrpt8 +1002090a t .text_25 +10020914 T WriteTxrpt8 +10020914 t .text_26 +10020916 T ResetTxrpt +10020916 t .text_27 +1002093e T PsuseTxrpt +1002093e t .text_28 +1002094c t .text_29 +10020956 T CheckMaxMacidNum +10020956 t .text_30 +10020992 T GetMediaStatusCommon +10020992 t .text_31 +100209b6 T GetTxrptStatistic +100209b6 t .text_32 +10020a42 t .text_33 +10020a42 t Init_ODM_ComInfo_8195a +10020b06 t .text_34 +10020b0c T rtl8195a_adaptivity_needed +10020b0c t .text_35 +10020b1e t .text_36 +10020b1e t Update_ODM_ComInfo_8195a +10020c08 t .text_37 +10020c0c t .text_38 +10020c10 t .text_39 +10020c14 t .text_40 +10020c18 t .text_41 +10020c1c t .text_42 +10020c22 T rtl8195a_InitHalDm +10020c22 t .text_43 +10020c5e T rtl8195a_HalDmWatchDog +10020c5e t .text_44 +10020d32 T rtl8195a_hal_dm_in_lps +10020d32 t .text_45 +10020d34 T rtl8195a_HalDmWatchDog_in_LPS +10020d34 t .text_46 +10020d36 T rtl8195a_init_dm_priv +10020d36 t .text_47 +10020d56 T rtl8195a_deinit_dm_priv +10020d56 t .text_48 +10020d58 t _RND4 +10020d68 t .text_4 +10020d68 t recvframe_put +10020d90 t .text_5 +10020d90 t check_fwstate +10020d9e t .text_6 +10020d9e t rtl8195a_init_rx_ring +10020e28 t .text_7 +10020e28 t rtl8195a_free_rx_ring +10020e58 t .text_8 +10020e58 t rtl8195a_init_tx_ring +10020ed6 t .text_9 +10020ed6 t rtl8195a_free_tx_ring +10020f64 T rtl8195a_init_desc_ring +10020f64 t .text_10 +10020fe8 T rtl8195a_free_desc_ring +10020fe8 t .text_11 +10021004 T rtl8195a_reset_desc_ring +10021004 t .text_12 +1002108e t .text_13 +1002109a t .text_14 +100210a6 T InitLxDmaRtl8195a +100210a6 t .text_15 +100211c8 t .text_16 +100211ce T get_txdesc_buf_addr +100211ce t .text_18 +10021206 T rtl8195a_check_txdesc_closed +10021206 t .text_19 +10021296 t .text_20 +10021296 t rtl8195a_tx_isr +10021378 T InterruptRecognized8195a +10021378 t .text_21 +10021424 T UpdateInterruptMask8195a +10021424 t .text_22 +1002148e T InitInterrupt8195a +1002148e t .text_23 +100214ac T EnableDMA8195a +100214ac t .text_25 +100214ca T EnableInterrupt8195a +100214ca t .text_26 +100214f6 T DisableDMA8195a +100214f6 t .text_27 +10021508 t .text_28 +10021510 T DisableInterrupt8195a +10021510 t .text_29 +1002152e t .text_30 +10021534 t .text_31 +1002153e t .text_32 +10021552 T InterruptHandle8195a +10021552 t .text_33 +1002170a t .text_34 +10021712 t .text_35 +10021712 t rtl8195a_if2_clone_recvframe +1002178e T CheckRxTgRtl8195a +1002178e t .text_36 +100217cc T rtl8192ee_check_rxdesc_remain +100217cc t .text_37 +100217fa t .text_38 +100217fa t rtl8195a_rx_mpdu +10021a1c T rtl8195a_recv_tasklet +10021a1c t .text_39 +10021a66 t .text_40 +10021a6c T rtl8195a_tx_int_handler +10021a6c t .text_41 +10021a90 t .text_42 +10021a90 t bus_read8 +10021a96 t .text_43 +10021a96 t bus_read16 +10021a9c t .text_44 +10021a9c t bus_read32 +10021aa2 t .text_45 +10021aa2 t bus_write8 +10021aaa t .text_46 +10021aaa t bus_write16 +10021ab2 t .text_47 +10021ab2 t bus_write32 +10021aba T rtl8195a_xmit_tasklet +10021aba t .text_48 +10021ae0 T lxbus_set_intf_ops +10021ae0 t .text_49 +10021b08 t .text_50 +10021b0c t .text_51 +10021b10 t .text_52 +10021b14 t .text_53 +10021b18 t .text_54 +10021b1c t .text_55 +10021b20 t .text_56 +10021b24 t .text_57 +10021b28 t .text_58 +10021b2c t ?_0 +10021b34 T ODM_InitRAInfo +10021b34 t .text_9 +10021bb6 T InitialRateUpdate +10021bb6 t .text_13 +10021c6a T RateUp_search_RateMask +10021c6a t .text_14 +10021c9a T RateDown_search_RateMask +10021c9a t .text_15 +10021ce0 T StartRateByRSSI +10021ce0 t .text_16 +10021d0e T TryDone +10021d0e t .text_19 +10021d70 t .text_20 +10021d76 t .text_21 +10021d82 T b64QamRate +10021d82 t .text_22 +10021d9e T RateUpRAM8195A +10021d9e t .text_23 +10021e1a T RateDownTrying +10021e1a t .text_25 +10021e4c t .text_26 +10021e54 T RateDownStepRAM8195A +10021e54 t .text_27 +10021ed6 t .text_28 +10021edc t .text_29 +10021ee4 T RateDecisionRAM8195A +10021ee4 t .text_30 +10021fac t .text_31 +10021fb4 T ArfrRefresh +10021fb4 t .text_32 +10022130 t .text_33 +10022134 t .text_34 +10022138 t .text_35 +1002213c t .text_36 +10022140 T H2CHDL_Set_MACID_Config +10022140 t .text_38 +100221b6 T PHY_DM_RA_SetRSSI_8195A +100221b6 t .text_39 +100221e8 T iw_ioctl +10022204 T wext_get_ssid +10022204 t .text_3 +1002220c t ??CrossCallReturnLabel_25 +1002221e t ??CrossCallReturnLabel_72 +10022230 t ??wext_get_ssid_0 +10022248 t ??wext_get_ssid_2 +1002224c t ??wext_get_ssid_1 +10022250 T wext_set_ssid +10022250 t .text_4 +10022258 t ??CrossCallReturnLabel_15 +1002225c t ??CrossCallReturnLabel_40 +1002226e t ??CrossCallReturnLabel_71 +1002227e t ??wext_set_ssid_0 +10022280 T wext_set_bssid +10022280 t .text_5 +10022288 t ??CrossCallReturnLabel_7 +100222b0 t ??wext_set_bssid_0 +100222ba t ??CrossCallReturnLabel_70 +100222ca t ??wext_set_bssid_1 +100222cc T is_broadcast_ether_addr +100222cc t .text_6 +100222ea t ??is_broadcast_ether_addr_0 +100222ee T wext_set_auth_param +100222ee t .text_7 +100222fc t ??CrossCallReturnLabel_31 +10022310 t ??CrossCallReturnLabel_69 +10022320 t ??wext_set_auth_param_0 +10022326 T wext_set_key_ext +10022326 t .text_8 +10022354 t ??CrossCallReturnLabel_35 +10022386 t ??wext_set_key_ext_1 +10022390 t ??wext_set_key_ext_2 +10022398 t ??wext_set_key_ext_3 +100223a4 t ??wext_set_key_ext_4 +100223b8 t ??wext_set_key_ext_5 +100223c4 t ??wext_set_key_ext_6 +100223da t ??wext_set_key_ext_7 +100223f8 t ??wext_set_key_ext_8 +10022414 t ??wext_set_key_ext_9 +1002241c t ??wext_set_key_ext_0 +10022422 T wext_get_enc_ext +10022422 t .text_9 +10022448 t ??CrossCallReturnLabel_34 +10022468 t ??wext_get_enc_ext_1 +10022476 t ??wext_get_enc_ext_3 +10022484 t ??wext_get_enc_ext_2 +1002248c t ??wext_get_enc_ext_0 +1002248e T wext_set_passphrase +1002248e t .text_10 +10022496 t ??CrossCallReturnLabel_14 +1002249a t ??CrossCallReturnLabel_41 +100224ac t ??CrossCallReturnLabel_68 +100224bc t .text_11 +100224bc t ??wext_set_passphrase_0 +100224bc t ?Subroutine1 +100224c2 t .text_12 +100224c2 t ?Subroutine17 +100224cc t .text_13 +100224cc t ?Subroutine9 +100224de T wext_get_passphrase +100224de t .text_14 +100224e6 t ??CrossCallReturnLabel_24 +100224f2 t ??CrossCallReturnLabel_67 +10022504 t ??wext_get_passphrase_0 +1002250c t ??wext_get_passphrase_1 +10022510 t .text_15 +10022510 t ?Subroutine12 +1002251e T wext_set_mode +1002251e t .text_20 +10022526 t ??CrossCallReturnLabel_6 +10022532 t ??CrossCallReturnLabel_66 +10022542 t .text_21 +10022542 t ??wext_set_mode_0 +10022542 t ?Subroutine3 +10022548 T wext_get_mode +10022548 t .text_22 +10022550 t ??CrossCallReturnLabel_5 +1002255a t ??CrossCallReturnLabel_65 +1002256c t ??wext_get_mode_0 +10022570 t ??wext_get_mode_1 +10022572 T wext_set_ap_ssid +10022572 t .text_23 +1002257a t ??CrossCallReturnLabel_13 +1002257e t ??CrossCallReturnLabel_42 +10022590 t ??CrossCallReturnLabel_64 +100225a0 t ??wext_set_ap_ssid_0 +100225a2 T wext_get_rssi +100225a2 t .text_25 +100225aa t ??CrossCallReturnLabel_3 +100225b4 t ??CrossCallReturnLabel_62 +100225c6 t ??wext_get_rssi_0 +100225cc t ??wext_get_rssi_1 +100225ce t .text_27 +100225ce t ??Subroutine24_0 +100225d4 t ??Subroutine24_1 +100225d8 t .text_28 +100225d8 t ?Subroutine6 +100225e8 T wext_set_pscan_channel +100225e8 t .text_29 +1002261c t ??wext_set_pscan_channel_1 +10022632 t ??wext_set_pscan_channel_0 +1002265c t ??wext_set_pscan_channel_2 +1002266a T wext_set_channel +1002266a t .text_30 +10022672 t ??CrossCallReturnLabel_2 +10022686 t ??CrossCallReturnLabel_61 +10022696 t ??wext_set_channel_0 +10022698 T wext_get_channel +10022698 t .text_31 +100226a0 t ??CrossCallReturnLabel_1 +100226aa t ??CrossCallReturnLabel_60 +100226bc t ??wext_get_channel_0 +100226c2 t ??wext_get_channel_1 +100226c4 T wext_set_scan +100226c4 t .text_36 +100226ce t ??CrossCallReturnLabel_17 +100226e2 t ??CrossCallReturnLabel_59 +100226f2 t ??wext_set_scan_0 +100226f4 T wext_get_scan +100226f4 t .text_37 +1002271a t ??wext_get_scan_0 +1002271e t ??wext_get_scan_1 +10022722 t .text_39 +10022722 t ??wext_private_command_with_retval_2 +10022722 t ?Subroutine4 +10022728 t .text_40 +10022728 t ?Subroutine14 +1002272e T wext_private_command +1002272e t .text_41 +10022742 t ??CrossCallReturnLabel_48 +1002274c t ??CrossCallReturnLabel_47 +1002274e t ??wext_private_command_0 +10022766 t ??wext_private_command_1 +1002276c t ??CrossCallReturnLabel_32 +10022778 t ??CrossCallReturnLabel_29 +10022788 t ??CrossCallReturnLabel_39 +10022796 t ??wext_private_command_3 +100227b8 t ??wext_private_command_4 +100227c0 t ??wext_private_command_2 +100227c2 t .text_42 +100227c2 t ?Subroutine20 +100227c8 T wext_wlan_indicate +100227c8 t .text_43 +100227ea t ??wext_wlan_indicate_0 +10022806 t ??wext_wlan_indicate_4 +10022810 t ??wext_wlan_indicate_2 +1002281c t ??CrossCallReturnLabel_23 +10022820 t ??CrossCallReturnLabel_55 +10022826 t ??CrossCallReturnLabel_22 +10022830 t ??wext_wlan_indicate_6 +10022838 t ??CrossCallReturnLabel_21 +1002283c t ??CrossCallReturnLabel_54 +10022842 t ??CrossCallReturnLabel_20 +1002284c t ??wext_wlan_indicate_7 +10022854 t ??CrossCallReturnLabel_19 +10022858 t ??CrossCallReturnLabel_53 +1002285e t ??CrossCallReturnLabel_18 +10022868 t ??wext_wlan_indicate_1 +10022872 t ??wext_wlan_indicate_5 +10022876 t ??wext_wlan_indicate_3 +10022878 t .text_44 +10022878 t ?Subroutine22 +10022882 t .text_45 +10022882 t ?Subroutine11 +10022888 t .text_47 +10022888 t ??wext_set_gen_ie_0 +10022888 t ?Subroutine5 +1002288a t ??Subroutine5_0 +10022890 t .text_48 +10022890 t ?Subroutine10 +100228a4 t .text_52 +100228a4 t ?Subroutine16 +100228b0 t .text_53 +100228b0 t ?Subroutine13 +100228bc t ?_0 +100228f0 t ?_1 +1002290c t ?_2 +10022928 t ?_3 +1002295c t ?_4 +10022984 t ?_5 +100229a4 t ?_6 +100229c8 t ?_7 +100229f0 t ?_9 +10022a14 t ?_10 +10022a30 t ?_11 +10022a4c t ?_13 +10022a68 t ?_14 +10022a74 t ?_15 +10022aac t ?_16 +10022ac8 t ?_17 +10022ae4 t ?_20 +10022b00 t ?_21 +10022b1c t ?_22 +10022b38 t ?_23 +10022b60 t ?_24 +10022b84 t ?_25 +10022b9c t ?_27 +10022bb4 t ?_28 +10022bcc t ?_29 +10022bf0 t check_fwstate +10022bfe t .text_3 +10022bfe t set_fwstate +10022c10 t .text_4 +10022c10 t _clr_fwstate_ +10022c22 T rtw_do_join +10022c22 t .text_5 +10022ca8 T rtw_set_802_11_bssid +10022ca8 t .text_6 +10022e28 t .text_7 +10022e2c t .text_8 +10022e34 T rtw_set_802_11_ssid +10022e34 t .text_9 +10022f52 t .text_10 +10022f58 t .text_11 +10022f60 T rtw_set_802_11_infrastructure_mode +10022f60 t .text_12 +1002301a T rtw_set_802_11_bssid_list_scan +1002301a t .text_13 +1002307c t .text_14 +10023082 T rtw_set_802_11_authentication_mode +10023082 t .text_15 +100230a4 T rtw_set_802_11_add_wep +100230a4 t .text_16 +10023108 t ?_1 +10023144 t ?_2 +10023168 t ?Veneer (6) for rt_hmac_sha1 +10023170 t ?Veneer (6) for rt_arc4_init +10023178 t ?Veneer (6) for rt_arc4_crypt +10023180 t ?Veneer (6) for AES_WRAP +10023188 t ?Veneer (6) for rt_md5_hmac +10023190 t ?Veneer (6) for AES_UnWRAP +10023198 t ?Veneer (6) for rom_psk_CalcGTK +100231a0 t ?Veneer (6) for rom_psk_CalcPTK +100231a8 t ?Veneer (6) for rom_psk_PasswordHash +100231b0 t check_fwstate +100231be t .text_6 +100231be t SubStr +100231cc t .text_7 +100231cc t Message_ReplayCounter_OC2LI +100231fc t .text_8 +100231fc t Message_SmallerEqualReplayCounter +10023226 t .text_9 +10023226 t Message_setReplayCounter +10023246 t .text_10 +10023246 t INCLargeInteger +1002326a t .text_11 +1002326a t INCOctet16_INTEGER +100232ba t .text_12 +100232ba t INCOctet32_INTEGER +1002332a t .text_13 +1002332a t SetEAPOL_KEYIV +1002338a t .text_14 +10023394 t .text_15 +100233a2 t .text_16 +100233a2 t EncGTK +100233e8 t ?_0 +100233f0 t .text_18 +100233f0 t CheckMIC +10023464 t .text_19 +10023474 t .text_20 +10023474 t CalcMIC +100234c8 t .text_21 +100234d4 T DecWPA2KeyData +100234d4 t .text_22 +10023570 t ?_1 +10023578 T DecGTK +10023578 t .text_24 +10023624 t ?_2 +1002362c t .text_26 +1002363a t .text_27 +10023644 t .text_28 +10023644 t GenNonce +100236b4 t .text_29 +100236b4 t ToDrv_SetPTK +10023774 T ToDrv_SetGTK +10023774 t .text_30 +1002380c t .text_31 +1002380c t ToDrv_SetPort +1002381e t .text_32 +1002381e t ToDrv_DisconnectSTA +100238d0 t ?_3 +100238e8 t .text_34 +100238ee T init_wpa_sta_info +100238ee t .text_35 +100239e8 t ?_4 +100239f4 t .text_37 +100239fc t .text_38 +100239fc t ResendTimeout +10023a7a t .text_39 +10023a84 T SendEAPOL +10023a84 t .text_40 +10023f38 t ?_6 +10023f58 t ?_7 +10023f78 t ?_8 +10023f80 t .text_44 +10023f90 t .text_45 +10023f9e t .text_46 +10023fd0 t .text_47 +10023fdc t .text_48 +10023fe6 t .text_49 +10023ffc t .text_50 +10024012 t .text_51 +1002401a t .text_52 +10024024 t .text_53 +10024030 t .text_54 +1002403c t .text_55 +10024048 t .text_56 +10024052 T ClientSendEAPOL +10024052 t .text_57 +10024370 t .text_58 +1002437a t .text_59 +10024386 t .text_60 +10024390 t .text_61 +1002439c t .text_62 +100243a6 t .text_63 +100243b2 t .text_64 +100243bc t .text_65 +100243c8 t .text_66 +100243d2 t .text_67 +100243de t .text_68 +100243e8 t .text_69 +100243fe t .text_70 +10024418 t .text_71 +10024442 t .text_72 +10024470 T EAPOLKeyRecvd +10024470 t .text_73 +100245f0 t .text_74 +100245f4 t .text_75 +100245f8 T ClientEAPOLKeyRecvd +100245f8 t .text_76 +10024940 t .text_77 +10024954 t .text_78 +10024966 T psk_derive +10024966 t .text_79 +100249f8 t .text_80 +100249fc T psk_init +100249fc t .text_81 +10024a82 t .text_82 +10024a8e T psk_strip_rsn_pairwise +10024a8e t .text_83 +10024af0 t .text_84 +10024af4 t .text_85 +10024af8 t .text_86 +10024afc T psk_strip_wpa_pairwise +10024afc t .text_87 +10024b62 t .text_88 +10024b68 t .text_89 +10024b74 t .text_90 +10024b80 t .text_91 +10024b8c t .text_92 +10024b9c t ?_9 +10024bb4 t ?_10 +10024bd4 t ?_11 +10024bf4 t ?_12 +10024bf8 t ?_13 +10024bfc t ?_14 +10024c00 t ?_15 +10024c08 T sscanf +10024c2c T rtw_read8 +10024c36 t __iar_annotation$$tailcall +10024c38 T rtw_read16 +10024c38 t .text_3 +10024c42 t __iar_annotation$$tailcall +10024c44 T rtw_read32 +10024c44 t .text_4 +10024c4e t __iar_annotation$$tailcall +10024c50 T rtw_write8 +10024c50 t .text_5 +10024c60 T rtw_write16 +10024c60 t .text_6 +10024c70 T rtw_write32 +10024c70 t .text_7 +10024c80 t wifi_mac_hash +10024caa t .text_3 +10024caa t check_fwstate +10024cb8 T _rtw_init_stainfo +10024cb8 t .text_4 +10024d2a t .text_5 +10024d36 T _rtw_init_sta_priv +10024d36 t .text_6 +10024e14 T _rtw_free_sta_xmit_priv_lock +10024e14 t .text_7 +10024e3a T rtw_mfree_stainfo +10024e3a t .text_8 +10024e68 T rtw_mfree_sta_priv_lock +10024e68 t .text_9 +10024e98 t .text_10 +10024ea0 T _rtw_free_sta_priv +10024ea0 t .text_11 +10024ec4 T _addba_timer_hdl +10024ec4 t .text_12 +10024ec8 T init_addba_retry_timer +10024ec8 t .text_13 +10024ee4 t .text_14 +10024ee8 T rtw_alloc_stainfo +10024ee8 t .text_15 +10024fa0 T rtw_free_stainfo +10024fa0 t .text_16 +10025132 t .text_17 +1002513c t .text_18 +10025142 t .text_19 +1002514c T rtw_free_all_stainfo +1002514c t .text_20 +100251ac T rtw_get_stainfo +100251ac t .text_21 +10025218 t .text_22 +1002521e T rtw_init_bcmc_stainfo +1002521e t .text_23 +10025238 T rtw_get_bcmc_stainfo +10025238 t .text_24 +10025248 t .text_25 +10025258 t ?_0 +1002526c t ?_1 +10025274 t ?_2 +1002527c t ?_3 +10025284 t ?Veneer (6) for HALEFUSEOneByteReadROM +1002528c t ?Veneer (6) for HALEFUSEOneByteWriteROM +10025294 T Efuse_PowerSwitch +1002529a t __iar_annotation$$tailcall +1002529c T Efuse_GetCurrentSize +1002529c t .text_3 +100252a2 t __iar_annotation$$tailcall +100252a4 T Efuse_CalculateWordCnts +100252a4 t .text_4 +100252c2 T ReadEFuseByte +100252c2 t .text_5 +1002532c T efuse_ReadEFuse +1002532c t .text_6 +10025340 T EFUSE_GetEfuseDefinition +10025340 t .text_7 +10025352 T efuse_OneByteRead +10025352 t .text_16 +100253f4 t .text_17 +10025404 t .text_18 +1002540a t .text_19 +10025412 T efuse_OneByteWrite +10025412 t .text_20 +100254c8 t .text_21 +100254d0 T efuse_WordEnableDataRead +100254d0 t .text_25 +10025502 T Efuse_WordEnableDataWrite +10025502 t .text_26 +10025514 t .text_30 +10025518 t .text_31 +1002551c t .text_32 +10025520 t .text_41 +10025528 T Efuse_ReadAllMap +10025528 t .text_60 +10025560 t .text_61 +1002556a t .text_62 +1002556e t .text_64 +1002556e t efuse_flash_map_update +100255ea t .text_65 +100255ea t rtw_flash_map_erase +1002560e t .text_66 +1002560e t rtw_flash_map_write +10025734 t .text_67 +1002573a t .text_68 +10025746 t .text_69 +10025754 t .text_74 +1002575e T rtw_config_map_write +1002575e t .text_75 +100257c0 T EFUSE_ShadowMapUpdate +100257c0 t .text_76 +10025810 T flash_map_mask +10025810 t .text_77 +1002581c T __aeabi_memclr4 +10025824 t check_fwstate +10025832 T cckrates_included +10025832 t .text_3 +1002585a T cckratesonly_included +1002585a t .text_4 +10025884 t .text_5 +1002588e T networktype_to_raid +1002588e t .text_6 +100258c8 T networktype_to_raid_ex +100258c8 t .text_7 +10025932 T judge_network_type +10025932 t .text_8 +10025984 T ratetbl_val_2wifirate +10025984 t .text_9 +100259d0 T is_basicrate +100259d0 t .text_10 +100259fe T ratetbl2rateset +100259fe t .text_11 +10025a44 T get_rate_set +10025a44 t .text_12 +10025a6c T UpdateBrateTbl +10025a6c t .text_13 +10025a9c T UpdateBrateTblForSoftAP +10025a9c t .text_14 +10025ac4 T Save_DM_Func_Flag +10025ac4 t .text_15 +10025aca T Restore_DM_Func_Flag +10025aca t .text_16 +10025ace t .text_17 +10025ad6 t .text_18 +10025adc T Switch_DM_Func +10025adc t .text_19 +10025aea T Set_MSR +10025aea t .text_20 +10025b02 T set_opmode +10025b02 t .text_21 +10025b38 T SelectChannel +10025b38 t .text_22 +10025b62 T SetBWMode +10025b62 t .text_23 +10025b92 t .text_24 +10025b98 T set_channel_bwmode +10025b98 t .text_25 +10025bea T get_my_bssid +10025bea t .text_26 +10025bee T get_beacon_interval +10025bee t .text_27 +10025c06 T is_client_associated_to_ap +10025c06 t .text_28 +10025c22 T is_client_associated_to_ibss +10025c22 t .text_29 +10025c3c T is_IBSS_empty +10025c3c t .text_30 +10025c5c T decide_wait_for_beacon_timeout +10025c5c t .text_31 +10025c78 T invalidate_cam_all +10025c78 t .text_32 +10025c80 T write_cam +10025c80 t .text_33 +10025ce6 T clear_cam_entry +10025ce6 t .text_34 +10025d10 T flush_all_cam_entry +10025d10 t .text_35 +10025d88 T WMM_param_handler +10025d88 t .text_36 +10025db0 T WMMOnAssocRsp +10025db0 t .text_37 +10025e8e t .text_38 +10025e8e t bwmode_update_check +10025f26 T HT_caps_handler +10025f26 t .text_39 +10025fe2 T HT_info_handler +10025fe2 t .text_40 +10026006 T HTOnAssocRsp +10026006 t .text_41 +1002605a T ERP_IE_handler +1002605a t .text_42 +10026070 t .text_43 +10026078 T VCS_update +10026078 t .text_44 +100260b6 T rtw_check_bcn_info +100260b6 t .text_45 +1002629c t .text_46 +100262aa t .text_47 +100262b8 T update_beacon_info +100262b8 t .text_48 +10026302 T is_ap_in_tkip +10026302 t .text_49 +10026374 T wifirate2_ratetbl_inx +10026374 t .text_50 +100263d4 T update_basic_rate +100263d4 t .text_51 +10026404 T update_supported_rate +10026404 t .text_52 +1002642e t .text_53 +10026434 T update_MCS_rate +10026434 t .text_54 +10026440 T support_short_GI +10026440 t .text_55 +10026474 T get_highest_rate_idx +10026474 t .text_56 +1002648c T Update_RA_Entry +1002648c t .text_57 +10026494 T enable_rate_adaptive +10026494 t .text_58 +10026496 T set_sta_rate +10026496 t .text_59 +10026498 T update_tx_basic_rate +10026498 t .text_60 +100264e8 t .text_61 +100264ee T check_assoc_AP +100264ee t .text_62 +100265ac t .text_63 +100265b6 T update_IOT_info +100265b6 t .text_64 +100265f2 T update_capinfo +100265f2 t .text_65 +10026678 T update_wireless_mode +10026678 t .text_66 +1002671c t .text_67 +10026720 t .text_68 +10026724 t .text_69 +10026728 t .text_70 +1002672c t .text_71 +10026730 t .text_72 +10026734 T update_bmc_sta_support_rate +10026734 t .text_73 +1002675a T update_TSF +1002675a t .text_74 +10026766 T correct_TSF +10026766 t .text_75 +10026770 T ARTHEROS_OUI1 +10026770 t .text_76 +10026774 T ARTHEROS_OUI2 +10026774 t .text_77 +10026778 T BROADCOM_OUI1 +10026778 t .text_78 +1002677c T BROADCOM_OUI2 +1002677c t .text_79 +10026780 T CISCO_OUI +10026780 t .text_80 +10026784 T MARVELL_OUI +10026784 t .text_81 +10026788 T RALINK_OUI +10026788 t .text_82 +1002678c T REALTEK_OUI +1002678c t .text_83 +10026790 T AIRGOCAP_OUI +10026790 t .text_84 +10026794 t rtw_basic_rate_cck +10026798 t rtw_basic_rate_ofdm +1002679c t rtw_basic_rate_mix +100267a4 T dump_chip_info +100268f4 t .text_3 +100268f8 t .text_4 +100268fc T hal_com_get_channel_plan +100268fc t .text_5 +1002691e T HAL_IsLegalChannel +1002691e t .text_6 +10026944 T MRateToHwRate +10026944 t .text_7 +10026ac0 T HwRateToMRate +10026ac0 t .text_8 +10026c6e T HalSetBrateCfg +10026c6e t .text_9 +10026d16 t .text_10 +10026d16 t _TwoOutPipeMapping +10026d3c t .text_11 +10026d3c t _ThreeOutPipeMapping +10026d5e T Hal_MappingOutPipe +10026d5e t .text_12 +10026daa T hal_init_macaddr +10026daa t .text_13 +10026dd0 T hw_var_port_switch +10026dd0 t .text_15 +10027004 t .text_16 +1002700a t .text_17 +10027014 T SetHwReg +10027014 t .text_18 +1002701e T GetHwReg +1002701e t .text_19 +10027020 T eqNByte +10027020 t .text_20 +1002703a T GetU1ByteIntegerFromStringInDecimal +1002703a t .text_21 +10027068 T rtw_bb_rf_gain_offset +10027068 t .text_22 +100270ac t .text_23 +100270b0 t .text_24 +100270b4 t ?_0 +100270cc t ?_1 +100270d8 t ?_2 +100270e4 t ?_3 +10027104 t ?_4 +10027124 t ?_5 +10027144 t ?_6 +10027164 t ?_7 +10027184 t ?_8 +100271a4 t ?_9 +100271c4 t ?_11 +100271d0 t ?_12 +100271dc t ?_13 +100271e4 t ?_15 +100271ec t ?_16 +100271f4 t ?_17 +100271fc t ?_18 +10027204 t ?_19 +1002720c t ?_20 +10027214 t ?_21 +1002721c t ?_22 +10027230 t ?_23 +10027238 t ?_24 +10027240 t ?_25 +10027248 t ?_26 +1002725c t ?_27 +10027268 t ?_29 +100272a0 t ?Veneer (6) for HalEFUSEPowerSwitch8195AROM +100272a8 t check_fwstate +100272b6 T rtl8195a_FirmwareDownload +100272b6 t .text_5 +100272ba T rtl8195a_InitializeFirmwareVars +100272ba t .text_6 +100272bc t .text_7 +100272bc t rtl8195a_free_hal_data +100272d6 t .text_8 +100272d6 t hal_EfuseSwitchToBank +10027310 t .text_9 +10027310 t Hal_GetEfuseDefinition +10027376 t .text_10 +10027376 t Hal_EfusePowerSwitch +10027380 t .text_11 +10027380 t hal_ReadEFuse_WiFi +100274d0 t .text_12 +100274de t .text_13 +100274de t Hal_ReadEFuse +100274f6 t .text_14 +100274f6 t hal_EfuseGetCurrentSize_WiFi +100275c6 t .text_15 +100275d0 t .text_16 +100275d0 t Hal_EfuseGetCurrentSize +100275de t .text_17 +100275de t Hal_EfuseWordEnableDataWrite +1002770c t .text_18 +10027718 t .text_19 +10027720 t .text_20 +10027720 t Hal_EfusePgPacketRead +100277f8 t .text_21 +10027804 t .text_22 +10027810 t .text_23 +10027810 t hal_EfusePgPacketWrite2ByteHeader +100278c6 t .text_24 +100278d2 t .text_25 +100278d2 t hal_EfusePgPacketWriteHeader +10027942 t .text_26 +10027942 t Hal_EfusePgPacketWrite +10027a4e t .text_27 +10027a58 t .text_28 +10027a58 t Hal_EfusePgPacketWrite_BT +10027a5c t .text_29 +10027a5c t rtl8195a_read_chip_version +10027ae6 T rtl8195a_InitBeaconParameters +10027ae6 t .text_30 +10027b6a T rtl8195a_InitBeaconMaxError +10027b6a t .text_31 +10027b6c T _InitBurstPktLen_8195AB +10027b6c t .text_32 +10027b76 t .text_33 +10027b76 t ResumeTxBeacon +10027bac t .text_34 +10027bac t StopTxBeacon +10027be6 t .text_35 +10027bf6 t .text_36 +10027bf6 t rtl8195a_SetBeaconRelatedRegisters +10027ca2 T rtl8195a_GetHalODMVar +10027ca2 t .text_37 +10027ca4 T rtl8195a_SetHalODMVar +10027ca4 t .text_38 +10027d16 T hal_notch_filter_8195a +10027d16 t .text_39 +10027d18 T UpdateHalRAMask8195A +10027d18 t .text_40 +10027e5c t .text_41 +10027e66 t .text_42 +10027e72 T HalLittleWifiMCUThreadRtl8195a +10027e72 t .text_43 +10027eb4 t ?_0 +10027ecc T HalEnter32KThreadRtl8195a +10027ecc t .text_45 +10027f06 t .text_46 +10027f18 t ?_1 +10027f30 T rtl8195a_set_hal_ops +10027f30 t .text_48 +10027fb8 t .text_49 +10027fbc t .text_50 +10027fc0 t .text_51 +10027fc4 t .text_52 +10027fc8 t .text_53 +10027fcc t .text_54 +10027fd0 t .text_55 +10027fd4 t .text_56 +10027fd8 t .text_57 +10027fdc t .text_58 +10027fe0 t .text_59 +10027fe4 t .text_60 +10027fe8 t .text_61 +10027fec t .text_62 +10027ff0 t .text_63 +10027ff4 t .text_64 +10027ff8 t .text_65 +10027ffc t .text_66 +10028000 t .text_67 +10028004 t .text_68 +10028008 t .text_69 +1002800c t .text_70 +10028010 t .text_71 +10028014 t .text_72 +10028018 t .text_73 +1002801c t .text_74 +10028020 t .text_75 +10028024 t .text_76 +10028028 t .text_77 +1002802c t .text_78 +10028030 t .text_79 +10028034 t .text_80 +10028038 t .text_81 +1002803c T rtl8195a_InitAntenna_Selection +1002803c t .text_82 +1002803e T rtl8195a_init_default_value +1002803e t .text_85 +10028040 T rtl8195a_InitLLTTable +10028040 t .text_86 +10028088 T Hal_GetChnlGroup8195A +10028088 t .text_87 +10028166 T Hal_InitPGData +10028166 t .text_88 +1002819a T Hal_EfuseParseIDCode +1002819a t .text_89 +100281b2 T Hal_ReadPowerValueFromPROM_8195A +100281b2 t .text_90 +10028362 T Hal_EfuseParseTxPowerInfo_8195A +10028362 t .text_91 +10028418 T Hal_EfuseParseEEPROMVer_8195A +10028418 t .text_93 +1002842e T Hal_EfuseParsePackageType_8195A +1002842e t .text_94 +10028476 T Hal_EfuseParseChnlPlan_8195A +10028476 t .text_95 +100284ae T Hal_EfuseParseCustomerID_8195A +100284ae t .text_96 +100284c4 T Hal_EfuseParseXtal_8195A +100284c4 t .text_98 +100284de T Hal_EfuseParseThermalMeter_8195A +100284de t .text_99 +1002850c T Hal_ReadRFGainOffset +1002850c t .text_100 +1002854c T BWMapping_8195A +1002854c t .text_101 +10028582 T SCMapping_8195A +10028582 t .text_102 +100285fc t .text_104 +100285fc t rtl8195a_fill_default_txdesc +10028898 t .text_105 +100288c2 t .text_106 +100288cc T rtl8195a_update_txdesc +100288cc t .text_107 +100288fe T rtl8195a_fill_fake_txdesc +100288fe t .text_108 +100289c4 t .text_109 +100289ce t .text_110 +100289ce t hw_var_set_opmode +10028bb2 t .text_111 +10028bb8 t .text_112 +10028bc0 t .text_113 +10028bc6 t .text_114 +10028bce t .text_115 +10028bd8 t .text_116 +10028bf4 t .text_117 +10028c12 t .text_118 +10028c12 t hw_var_set_correct_tsf +10028d42 t .text_119 +10028d4a t .text_120 +10028d50 t .text_121 +10028d5a t .text_122 +10028d64 t .text_123 +10028d6e t .text_124 +10028d7a t .text_125 +10028d86 t .text_126 +10028d86 t hw_var_set_mlme_sitesurvey +10028e72 t .text_127 +10028e7e t .text_128 +10028e86 t .text_129 +10028e8c t .text_130 +10028e96 t .text_131 +10028e9e t .text_132 +10028ea6 t .text_133 +10028ea6 t hw_var_set_mlme_join +10028fac t .text_134 +10028fb4 T c2h_id_filter_ccx_8195A +10028fb4 t .text_136 +10028fb8 T c2h_handler_8195A +10028fb8 t .text_137 +10028fbc T SetHwReg8195A +10028fbc t .text_139 +100294d2 t .text_140 +100294da t .text_141 +100294e4 T GetHwReg8195A +100294e4 t .text_142 +100295b8 T SetHalDefVar8195A +100295b8 t .text_143 +100295bc T GetHalDefVar8195A +100295bc t .text_144 +100295c0 T rtl8195a_start_thread +100295c0 t .text_145 +10029604 t .text_146 +10029608 t .text_147 +1002960c t .text_148 +10029610 t .text_149 +10029614 t .text_150 +10029618 t .text_151 +1002961c T rtl8195a_stop_thread +1002961c t .text_152 +1002963c t ?_2 +10029658 t ?_3 +10029670 t ?Veneer (6) for PHY_QueryBBReg_8195A +10029678 t ?Veneer (6) for phy_CalculateBitShift +10029680 t phy_RFSerialRead_8195A +10029734 t .text_3 +10029744 t .text_4 +10029750 T PHY_QueryRFReg_8195A +10029750 t .text_5 +10029768 T PHY_SetRFReg_8195A +10029768 t .text_6 +100297c4 T PHY_MACConfig8195A +100297c4 t .text_7 +100297e2 t .text_8 +100297e2 t phy_BB8195a_Config_ParaFile +10029888 T PHY_BBConfig8195A +10029888 t .text_9 +10029922 T PHY_RFConfig8195A +10029922 t .text_12 +10029926 T PHY_SetTxPowerIndex_8195A +10029926 t .text_15 +10029a4e t .text_16 +10029a56 t .text_17 +10029a5e t .text_18 +10029a66 T PHY_GetTxPowerIndex_8195A +10029a66 t .text_20 +10029ae4 T PHY_SetTxPowerLevel8195A +10029ae4 t .text_21 +10029aea T phy_SpurCalibration_8195A +10029aea t .text_23 +10029bf0 t .text_24 +10029bfc t .text_25 +10029c06 t .text_26 +10029c0e T phy_SetRegBW_8195A +10029c0e t .text_27 +10029c54 T phy_PostSetBwMode8195A +10029c54 t .text_29 +10029d38 t .text_30 +10029d44 t .text_31 +10029d4e t .text_32 +10029d54 t .text_33 +10029d62 T phy_SwChnl8195A +10029d62 t .text_34 +10029df0 t .text_35 +10029df4 t .text_36 +10029df8 t .text_37 +10029e02 T phy_SwChnlAndSetBwMode8195A +10029e02 t .text_38 +10029e52 T PHY_HandleSwChnlAndSetBW8195A +10029e52 t .text_39 +10029f10 T PHY_SetBWMode8195A +10029f10 t .text_40 +10029f2c T PHY_SwChnl8195A +10029f2c t .text_41 +10029f3e t .text_42 +10029f46 T PHY_SetSwChnlBWMode8195A +10029f46 t .text_43 +10029f60 T setIqkMatrix_8195A +1002a02c t .text_3 +1002a03a T DoIQK_8195A +1002a03a t .text_4 +1002a058 T ODM_TxPwrTrackSetPwr_8195A +1002a058 t .text_5 +1002a4a0 t .text_6 +1002a4b0 t .text_7 +1002a4bc t .text_8 +1002a4c2 t .text_9 +1002a4ce t .text_10 +1002a4d6 t .text_11 +1002a4e4 t .text_12 +1002a4f2 T GetDeltaSwingTable_8195A +1002a4f2 t .text_13 +1002a524 T ConfigureTxpowerTrack_8195A +1002a524 t .text_14 +1002a556 T phy_PathA_IQK_8195A +1002a556 t .text_15 +1002a688 t .text_16 +1002a696 t .text_17 +1002a6a0 t .text_18 +1002a6ac T phy_PathA_RxIQK8195A +1002a6ac t .text_19 +1002a85c t .text_20 +1002a868 t .text_21 +1002a874 t .text_22 +1002a886 t .text_23 +1002a896 t .text_24 +1002a8a8 T phy_PathB_IQK_8195A +1002a8a8 t .text_25 +1002a944 t .text_26 +1002a94a t .text_27 +1002a956 t .text_28 +1002a964 t .text_29 +1002a972 t .text_30 +1002a980 t .text_31 +1002a992 t .text_32 +1002a9a0 t .text_33 +1002a9ae t .text_34 +1002a9bc t .text_36 +1002a9c2 t .text_44 +1002a9da t .text_45 +1002a9e8 T _PHY_PathAFillIQKMatrix8195A +1002a9e8 t .text_46 +1002aaf4 t .text_47 +1002aaf8 t .text_48 +1002ab02 t .text_49 +1002ab10 T _PHY_PathBFillIQKMatrix8195A +1002ab10 t .text_50 +1002ac08 t .text_51 +1002ac0c t .text_52 +1002ac10 t .text_53 +1002ac14 t .text_54 +1002ac18 t .text_55 +1002ac24 t .text_56 +1002ac32 t .text_57 +1002ac46 t .text_58 +1002ac52 t .text_59 +1002ac5e t .text_60 +1002ac6a t .text_61 +1002ac78 T _PHY_SaveADDARegisters8195A +1002ac78 t .text_63 +1002ac98 T _PHY_SaveMACRegisters8195A +1002ac98 t .text_64 +1002acc2 T _PHY_ReloadADDARegisters8195A +1002acc2 t .text_65 +1002ace2 t .text_66 +1002acee t .text_67 +1002ad04 T _PHY_ReloadMACRegisters8195A +1002ad04 t .text_68 +1002ad30 t .text_69 +1002ad44 T _PHY_PathADDAOn8195A +1002ad44 t .text_70 +1002ad70 t .text_71 +1002ad7c T _PHY_MACSettingCalibration8195A +1002ad7c t .text_72 +1002adb8 t .text_73 +1002adc2 T _PHY_PathAStandBy8195A +1002adc2 t .text_74 +1002adec t .text_75 +1002adf0 t .text_76 +1002adfa t .text_77 +1002ae02 T _PHY_PIModeSwitch8195A +1002ae02 t .text_78 +1002ae40 t .text_79 +1002ae52 t .text_80 +1002ae5c T phy_SimularityCompare_8195A +1002ae5c t .text_81 +1002af8c t .text_82 +1002af90 t .text_83 +1002af94 t .text_84 +1002af98 t .text_85 +1002af9c t .text_86 +1002afa0 t .text_87 +1002afa4 t .text_88 +1002afa8 t .text_89 +1002afac t .text_90 +1002afb0 t .text_91 +1002afb4 t .text_92 +1002afb8 T phy_IQCalibrate_8195A +1002afb8 t .text_93 +1002b258 t .text_94 +1002b25c t .text_95 +1002b260 t .text_96 +1002b264 t .text_97 +1002b268 t .text_98 +1002b26c t .text_99 +1002b270 t .text_100 +1002b274 t .text_101 +1002b278 t .text_102 +1002b27c t .text_103 +1002b280 t .text_104 +1002b284 t .text_105 +1002b288 t .text_106 +1002b28c t .text_107 +1002b298 t .text_108 +1002b2a0 t .text_109 +1002b2ac t .text_110 +1002b2b8 t .text_111 +1002b2c2 t .text_112 +1002b2d0 t .text_113 +1002b2d6 t .text_114 +1002b2e2 t .text_115 +1002b2ee t .text_116 +1002b2fc t .text_117 +1002b30a T phy_LCCalibrate_8195A +1002b30a t .text_118 +1002b374 T PHY_IQCalibrate_8195A +1002b374 t .text_120 +1002b5d8 t .text_126 +1002b5dc t .text_127 +1002b5e0 t .text_128 +1002b5e4 t .text_129 +1002b5e8 t .text_130 +1002b5ec t .text_131 +1002b5f0 t .text_132 +1002b5f4 t .text_133 +1002b5f8 t .text_134 +1002b5fc t .text_135 +1002b608 t .text_136 +1002b614 t .text_137 +1002b61c t .text_138 +1002b624 t .text_139 +1002b630 t .text_140 +1002b63a T PHY_LCCalibrate_8195A +1002b63a t .text_141 +1002b674 t ?_0 +1002b678 t ?_1 +1002b6b8 t ?_2 +1002b6c8 t ?_3 +1002b6ec t ?_4 +1002b710 T HalPwrSeqCmdParsing +1002b7ec T init_rom_wlan_ram_map +1002b804 t ?Veneer (6) for rtw_secmicsetkey +1002b80c t ?Veneer (6) for rtw_secgetmic +1002b814 t ?Veneer (6) for rtw_secmicappend +1002b81c t IS_MCAST +1002b82a t .text_4 +1002b82a t check_fwstate +1002b838 t .text_5 +1002b838 t _init_txservq +1002b84e T _rtw_init_sta_xmit_priv +1002b84e t .text_6 +1002b894 T _rtw_init_xmit_priv +1002b894 t .text_7 +1002ba04 t .text_8 +1002ba0e T rtw_mfree_xmit_priv_lock +1002ba0e t .text_9 +1002ba5a T _rtw_free_xmit_priv +1002ba5a t .text_10 +1002bafc T qos_acm +1002bafc t .text_11 +1002bb2c t .text_12 +1002bb2c t set_qos +1002bb7c t .text_13 +1002bb7c t update_attrib +1002be9a T xmitframe_addmic +1002be9a t .text_14 +1002c022 t .text_15 +1002c028 t .text_16 +1002c032 T xmitframe_swencrypt +1002c032 t .text_17 +1002c062 T rtw_make_wlanhdr +1002c062 t .text_18 +1002c24a t .text_19 +1002c258 t .text_20 +1002c264 t .text_21 +1002c272 t .text_22 +1002c278 T rtw_txframes_pending +1002c278 t .text_23 +1002c2ae T rtw_txframes_sta_ac_pending +1002c2ae t .text_24 +1002c2da T rtw_txframes_update_attrib_vcs_info +1002c2da t .text_25 +1002c38a T rtw_put_snap +1002c38a t .text_27 +1002c3c4 T rtw_update_protection +1002c3c4 t .text_28 +1002c404 T rtw_count_tx_stats +1002c404 t .text_29 +1002c456 T rtw_alloc_xmitbuf_ext +1002c456 t .text_30 +1002c4cc T rtw_free_xmitbuf_ext +1002c4cc t .text_31 +1002c4fc t .text_32 +1002c504 T rtw_alloc_xmitbuf +1002c504 t .text_33 +1002c54c t .text_34 +1002c556 t .text_35 +1002c560 T rtw_free_xmitbuf +1002c560 t .text_36 +1002c5be T rtw_alloc_xmitframe +1002c5be t .text_37 +1002c612 t .text_38 +1002c618 T rtw_free_xmitframe +1002c618 t .text_39 +1002c66a T rtw_free_xmitframe_queue +1002c66a t .text_40 +1002c69e t .text_41 +1002c6a6 T rtw_xmitframe_enqueue +1002c6a6 t .text_42 +1002c6b2 T rtw_get_sta_pending +1002c6b2 t .text_43 +1002c6e8 T rtw_xmit_classifier +1002c6e8 t .text_44 +1002c75c T rtw_alloc_hwxmits +1002c75c t .text_45 +1002c7b4 T rtw_free_hwxmits +1002c7b4 t .text_46 +1002c7ca T rtw_init_hwxmits +1002c7ca t .text_47 +1002c7dc T rtw_get_ff_hwaddr +1002c7dc t .text_48 +1002c81e T xmitframe_enqueue_for_sleeping_sta +1002c81e t .text_49 +1002c98c t .text_50 +1002c990 t .text_51 +1002c994 t .text_52 +1002c998 t .text_53 +1002c9a4 t .text_54 +1002c9ae t .text_55 +1002c9ae t dequeue_xmitframes_to_sleeping_queue +1002ca00 T stop_sta_xmit +1002ca00 t .text_56 +1002cad8 t .text_57 +1002cade T wakeup_sta_to_xmit +1002cade t .text_58 +1002cc96 t .text_59 +1002cca2 t .text_60 +1002ccac t .text_61 +1002ccb6 T xmit_delivery_enabled_frames +1002ccb6 t .text_62 +1002cd9c t .text_63 +1002cda8 t .text_64 +1002cdb0 t .text_65 +1002cdb8 t .text_66 +1002cdbe t .text_67 +1002cdc6 T rtw_xmit_tasklet +1002cdc6 t .text_68 +1002ce0e T rtw_xmit_mgnt +1002ce0e t .text_69 +1002ce12 T rtw_xmit_data +1002ce12 t .text_70 +1002ce16 T rtw_xmit +1002ce16 t .text_71 +1002ce86 T rtw_sctx_done_err +1002ce86 t .text_73 +1002ce92 T rtw_sctx_done +1002ce92 t .text_74 +1002ce98 t ?_2 +1002ceac t ?Veneer (6) for rtw_seccalctkipmic +1002ceb4 t IS_MCAST +1002cec2 t .text_3 +1002cec2 t get_recvframe_data +1002ceca t .text_4 +1002ceca t recvframe_pull +1002ceea t .text_5 +1002ceea t recvframe_pull_tail +1002cf08 t .text_6 +1002cf12 t .text_7 +1002cf12 t check_fwstate +1002cf20 T _rtw_init_sta_recv_priv +1002cf20 t .text_8 +1002cf3e T _rtw_init_recv_priv +1002cf3e t .text_9 +1002cfb8 T rtw_mfree_recv_priv_lock +1002cfb8 t .text_10 +1002cfec T _rtw_free_recv_priv +1002cfec t .text_11 +1002d020 T _rtw_alloc_recvframe +1002d020 t .text_12 +1002d050 T rtw_alloc_recvframe +1002d050 t .text_13 +1002d060 T rtw_free_recvframe +1002d060 t .text_14 +1002d0e0 t .text_15 +1002d0e4 t ??__FUNCTION__ +1002d0f8 t ?_1 +1002d13c t .text_18 +1002d144 T _rtw_enqueue_recvframe +1002d144 t .text_19 +1002d16c T rtw_enqueue_recvframe +1002d16c t .text_20 +1002d184 T rtw_free_uc_swdec_pending_queue +1002d184 t .text_22 +1002d1a8 t .text_24 +1002d1b6 T rtw_free_buf_pending_queue +1002d1b6 t .text_25 +1002d1ba t .text_28 +1002d1c4 t .text_29 +1002d1ca t .text_31 +1002d1d8 t .text_32 +1002d1e4 T recvframe_chkmic +1002d1e4 t .text_33 +1002d2b0 T decryptor +1002d2b0 t .text_34 +1002d368 T portctrl +1002d368 t .text_35 +1002d3dc t .text_36 +1002d3e4 T recv_decache +1002d3e4 t .text_37 +1002d410 T process_pwrbit_data +1002d410 t .text_38 +1002d450 t .text_39 +1002d456 T process_wmmps_data +1002d456 t .text_40 +1002d4d6 T count_rx_stats +1002d4d6 t .text_41 +1002d564 T sta2sta_data_frame +1002d564 t .text_42 +1002d6c6 t .text_43 +1002d6ce t .text_44 +1002d6d4 T ap2sta_data_frame +1002d6d4 t .text_45 +1002d820 t ?_2 +1002d828 t .text_47 +1002d830 t .text_48 +1002d83a T sta2ap_data_frame +1002d83a t .text_49 +1002d8d0 T validate_recv_ctrl_frame +1002d8d0 t .text_50 +1002da34 T validate_recv_mgnt_frame +1002da34 t .text_51 +1002da72 T validate_recv_data_frame +1002da72 t .text_52 +1002dc80 t .text_53 +1002dc8c t .text_54 +1002dc98 T validate_recv_frame +1002dc98 t .text_55 +1002dd5a t .text_56 +1002dd62 T wlanhdr_to_ethhdr +1002dd62 t .text_57 +1002de90 t .text_58 +1002de98 T recvframe_chk_defrag +1002de98 t .text_59 +1002dedc t .text_61 +1002dee4 t .text_62 +1002deee T recv_indicatepkt_reorder +1002deee t .text_66 +1002df10 T process_recv_indicatepkts +1002df10 t .text_68 +1002df68 T recv_func_prehandle +1002df68 t .text_69 +1002df88 T recv_func_posthandle +1002df88 t .text_70 +1002dfee T recv_func +1002dfee t .text_71 +1002e08e T rtw_recv_entry +1002e08e t .text_72 +1002e0bc T rtw_recv_tasklet +1002e0bc t .text_73 +1002e108 t ?_3 +1002e11c T SNAP_ETH_TYPE_IPX +1002e11c t .text_75 +1002e120 T SNAP_ETH_TYPE_APPLETALK_AARP +1002e120 t .text_76 +1002e124 T rtw_rfc1042_header +1002e124 t .text_81 +1002e12c T rtw_bridge_tunnel_header +1002e12c t .text_82 +1002e134 t ?Veneer (6) for wep_80211_encrypt +1002e13c t ?Veneer (6) for wep_80211_decrypt +1002e144 t ?Veneer (6) for tkip_80211_encrypt +1002e14c t ?Veneer (6) for tkip_80211_decrypt +1002e154 t ?Veneer (6) for aes_80211_encrypt +1002e15c t ?Veneer (6) for aes_80211_decrypt +1002e164 t IS_MCAST +1002e172 T rtw_wep_encrypt +1002e172 t .text_3 +1002e1c0 T rtw_wep_decrypt +1002e1c0 t .text_4 +1002e202 T rtw_tkip_encrypt +1002e202 t .text_5 +1002e27c T rtw_tkip_decrypt +1002e27c t .text_6 +1002e2e6 t .text_7 +1002e2f2 t .text_8 +1002e2fe t .text_9 +1002e308 T rtw_aes_encrypt +1002e308 t .text_10 +1002e378 t .text_11 +1002e37e T rtw_aes_decrypt +1002e37e t .text_12 +1002e3ee t .text_13 +1002e3fe T rtw_init_sec_priv +1002e3fe t .text_15 +1002e466 T rtw_free_sec_priv +1002e466 t .text_16 +1002e48c T __iar_unaligned___aeabi_memcpy +1002e4ac T __iar_unaligned___aeabi_memcpy4 +1002e4ac T __iar_unaligned___aeabi_memcpy8 +1002e4ac t .text_1 +1002e504 T PHY_GetTxPowerByRateBase +1002e564 T phy_SetTxPowerByRateBase +1002e564 t .text_3 +1002e5c2 T phy_StoreTxPowerByRateBase +1002e5c2 t .text_4 +1002e6e4 t .text_5 +1002e6f0 t .text_6 +1002e6fc t .text_7 +1002e70a t .text_8 +1002e718 t .text_9 +1002e726 t .text_10 +1002e734 t .text_11 +1002e742 t .text_12 +1002e750 t .text_13 +1002e75c t .text_14 +1002e768 t .text_15 +1002e774 T PHY_GetRateValuesOfTxPowerByRate +1002e774 t .text_16 +1002ec0e t .text_17 +1002ec2e t .text_18 +1002ec34 t .text_19 +1002ec3a t .text_20 +1002ec66 T PHY_StoreTxPowerByRateNew +1002ec66 t .text_21 +1002ed00 T PHY_InitTxPowerByRate +1002ed00 t .text_22 +1002ed72 T PHY_StoreTxPowerByRate +1002ed72 t .text_23 +1002ed94 T phy_ConvertTxPowerByRateInDbmToRelativeValues +1002ed94 t .text_24 +1002eee0 t ?_2 +1002eee4 t ?_3 +1002eeec t ?_4 +1002eef4 t ?_5 +1002eefc t ?_6 +1002ef04 t ?_7 +1002ef10 t ?_8 +1002ef1c t ?_9 +1002ef28 t .text_33 +1002ef32 t .text_34 +1002ef3c t .text_35 +1002ef46 t .text_36 +1002ef5c t .text_37 +1002ef6a t .text_38 +1002ef6e t .text_39 +1002ef7a T PHY_TxPowerByRateConfiguration +1002ef7a t .text_40 +1002ef8a T PHY_SetTxPowerIndexByRateSection +1002ef8a t .text_41 +1002f030 t ?_10 +1002f034 t ?_11 +1002f03c t ?_12 +1002f044 t ?_13 +1002f04c t ?_14 +1002f054 t ?_15 +1002f05c t ?_16 +1002f068 t ?_17 +1002f074 t ?_18 +1002f080 t ?_19 +1002f08c T phy_GetChnlIndex +1002f08c t .text_52 +1002f09c T PHY_GetTxPowerIndexBase +1002f09c t .text_53 +1002f1e2 T PHY_GetTxPowerTrackingOffset +1002f1e2 t .text_54 +1002f216 T PHY_GetRateIndexOfTxPowerByRate +1002f216 t .text_55 +1002f556 T PHY_GetTxPowerByRate +1002f556 t .text_56 +1002f5b8 T PHY_SetTxPowerByRate +1002f5b8 t .text_57 +1002f5f6 t .text_58 +1002f604 T PHY_SetTxPowerLevelByPath +1002f604 t .text_59 +1002f682 t .text_60 +1002f68a T PHY_SetTxPowerIndexByRateArray +1002f68a t .text_61 +1002f6c4 T phy_GetWorldWideLimit +1002f6c4 t .text_62 +1002f6e8 T phy_GetChannelIndexOfTxPowerLimit +1002f6e8 t .text_63 +1002f722 T PHY_GetTxPowerLimit +1002f722 t .text_64 +1002f91c T PHY_ConvertTxPowerLimitToPowerIndex +1002f91c t .text_65 +1002f9f8 T PHY_InitTxPowerLimit +1002f9f8 t .text_66 +1002fa46 T PHY_SetTxPowerLimit +1002fa46 t .text_67 +1002fc1c t .text_68 +1002fc22 t .text_69 +1002fc2c t .text_70 +1002fc30 t .text_71 +1002fc34 t .text_72 +1002fc38 t .text_73 +1002fc3c t .text_74 +1002fc40 t .text_75 +1002fc44 t .text_76 +1002fc48 t .text_77 +1002fc4c t .text_78 +1002fc50 t .text_79 +1002fc54 t .text_80 +1002fc58 t .text_81 +1002fc5c t .text_82 +1002fc66 t .text_83 +1002fc70 t .text_84 +1002fc76 T PHY_GetTxPowerIndex +1002fc76 t .text_85 +1002fcc8 T PHY_SetTxPowerIndex +1002fcc8 t .text_86 +1002fd14 T Hal_ChannelPlanToRegulation +1002fd14 t .text_87 +1002fdac t ?_20 +1002fde4 t ?_24 +1002fdec t ?_25 +1002fdf4 t ?_28 +1002fdfc t ?_37 +1002fe04 t ?_38 +1002fe0c T wifi_indication +1002fe24 t ??wifi_indication_1 +1002fe3c t ??wifi_indication_2 +1002fe42 t ??wifi_indication_0 +1002fe46 T wifi_reg_event_handler +1002fe46 t .text_4 +1002fe4e t ??wifi_reg_event_handler_0 +1002fe50 t ??wifi_reg_event_handler_1 +1002fe6a t ??wifi_reg_event_handler_2 +1002fe72 T wifi_unreg_event_handler +1002fe72 t .text_5 +1002fe78 t ??wifi_unreg_event_handler_0 +1002fe84 t ??wifi_unreg_event_handler_1 +1002fe9a t ??wifi_unreg_event_handler_2 +1002fea2 T init_event_callback_list +1002fea2 t .text_6 +1002feb0 t ??DataTable3 +1002feb4 T rtw_remainder_len +1002fec0 T _rtw_open_pktfile +1002fec0 t .text_3 +1002fed4 T _rtw_pktfile_read +1002fed4 t .text_4 +1002ff04 T rtw_set_tx_chksum_offload +1002ff04 t .text_6 +1002ff06 T rtw_os_xmit_resource_alloc +1002ff06 t .text_7 +1002ff10 T rtw_os_xmit_resource_free +1002ff10 t .text_8 +1002ff12 T rtw_os_pkt_complete +1002ff12 t .text_9 +1002ff1a T rtw_os_xmit_complete +1002ff1a t .text_10 +1002ff2c T rtw_os_xmit_schedule +1002ff2c t .text_11 +1002ff68 T rtw_xmit_entry +1002ff68 t .text_12 +1002ffb0 T ODM_DMInit +1002fffe T ODM_DMWatchdog +1002fffe t .text_3 +10030072 T ODM_CmnInfoInit +10030072 t .text_4 +10030170 T ODM_CmnInfoHook +10030170 t .text_5 +10030206 T ODM_CmnInfoPtrArrayHook +10030206 t .text_6 +10030214 T ODM_CmnInfoUpdate +10030214 t .text_7 +100302ba T odm_CommonInfoSelfInit +100302ba t .text_8 +10030312 T odm_CommonInfoSelfUpdate +10030312 t .text_9 +10030366 T PhyDM_Get_Structure +10030366 t .text_14 +10030380 T odm_IQCalibrate +10030380 t .text_20 +10030382 t .text_26 +10030388 t .text_36 +1003038c t .text_37 +10030390 t .text_38 +10030394 T rtl8195ab_init_xmit_priv +100303a2 T rtl8195ab_free_xmit_priv +100303a2 t .text_3 +100303aa T GetDmaTxbdIdx +100303aa t .text_4 +100303cc T rtl8195a_enqueue_xmitbuf +100303cc t .text_5 +100303f2 T rtl8195a_dequeue_xmitbuf +100303f2 t .text_6 +10030418 t .text_7 +10030418 t GetTxBufDesc +10030462 T SetTxbdForLxDMARtl8195ab +10030462 t .text_8 +100304e0 T UpdateTxbdHostIndex +100304e0 t .text_9 +1003052e T rtw_dump_xframe +1003052e t .text_14 +100306a6 t .text_15 +100306b0 T check_tx_desc_resource +100306b0 t .text_16 +100306e4 t .text_17 +100306e4 t check_nic_enough_desc +10030750 t .text_18 +1003075c t .text_19 +1003075c t UpdateFirstTxbdtoXmitBuf +1003078e t .text_20 +1003078e t dequeue_one_xmitframe +100307b2 T rtw_dequeue_xframe +100307b2 t .text_21 +10030832 t .text_22 +10030838 T rtl8195ab_xmitframe_resume +10030838 t .text_23 +10030914 t .text_24 +10030918 T rtw_xmitframe_coalesce +10030918 t .text_25 +10030afa t .text_26 +10030b06 t .text_27 +10030b1a t .text_28 +10030b1a t pre_xmitframe +10030c00 t .text_29 +10030c08 t .text_30 +10030c10 T rtl8195ab_mgnt_xmit +10030c10 t .text_31 +10030c4c T rtl8195ab_hal_xmit +10030c4c t .text_32 +10030c4e t check_fwstate +10030c5c T translate2dbm +10030c5c t .text_3 +10030c64 t .text_4 +10030c64 t process_rssi +10030cda T rtl8195a_process_phy_info +10030cda t .text_5 +10030cdc T rtl8195a_query_rx_desc_status +10030cdc t .text_6 +10030d96 T rtl8195a_query_rx_phy_status +10030d96 t .text_7 +10030f1e t .text_8 +10030f2a t .text_9 +10030f30 T ODM_Read1Byte +10030f36 T ODM_Read4Byte +10030f36 t .text_4 +10030f3c T ODM_Write1Byte +10030f3c t .text_5 +10030f42 T ODM_Write2Byte +10030f42 t .text_6 +10030f48 T ODM_Write4Byte +10030f48 t .text_7 +10030f4e T ODM_SetMACReg +10030f4e t .text_8 +10030f50 T ODM_SetBBReg +10030f50 t .text_10 +10030f52 t .text_11 +10030f58 T ODM_GetBBReg +10030f58 t .text_12 +10030f5a t .text_13 +10030f60 T ODM_SetRFReg +10030f60 t .text_14 +10030f70 T ODM_GetRFReg +10030f70 t .text_15 +10030f76 T ODM_MoveMemory +10030f76 t .text_18 +10030f80 T ODM_delay_ms +10030f80 t .text_26 +10030f84 T ODM_delay_us +10030f84 t .text_27 +10030f88 t _GetN +10030fa2 t __iar_annotation$$tailcall +10030faa t .text_3 +10030faa t _UngetN +10030fc0 t __iar_annotation$$tailcall +10030fc4 T _ScanfSmallNoMb +10030fc4 t .text_4 +100311ac t .text_5 +100311b2 t .text_6 +100311b2 t _GetstrSmallNoMb +10031268 t .text_7 +10031268 t _GetintSmallNoMb +10031484 t .text_8 +1003148c t ?_0 +10031494 t ?_1 +1003149c t .text_6 +1003149c t flash_init +100314ca t ??flash_init_0 +100314cc t ??DataTable3_4 +100314d0 t ??DataTable3_5 +100314d4 t ??DataTable3_6 +100314d8 T flash_erase_sector +100314d8 t .text_14 +100314e8 t .text_15 +100314e8 t ?Subroutine0 +100314f0 T flash_read_word +100314f0 t .text_16 +100314f8 t ??CrossCallReturnLabel_5 +1003150a T flash_write_word +1003150a t .text_17 +10031512 t ??CrossCallReturnLabel_4 +10031524 t .text_18 +10031524 t ?Subroutine1 +1003152c t .text_19 +1003152c t ?Subroutine4 +10031534 T flash_stream_read +10031534 t .text_20 +10031568 t ??flash_stream_read_2 +1003156a t ??flash_stream_read_1 +10031578 t ??flash_stream_read_0 +10031584 t ??flash_stream_read_4 +10031592 t ??flash_stream_read_6 +100315a6 t ??flash_stream_read_7 +100315b4 t ??flash_stream_read_3 +100315b8 t ??flash_stream_read_5 +100315c4 t ??flash_stream_read_9 +100315d2 t ??flash_stream_read_8 +100315d4 T flash_stream_write +100315d4 t .text_21 +10031600 t ??flash_stream_write_1 +10031602 t ??flash_stream_write_0 +10031612 t ??flash_stream_write_2 +1003161e t ??CrossCallReturnLabel_3 +1003162a t ??flash_stream_write_4 +10031652 t ??CrossCallReturnLabel_2 +1003165a t ??flash_stream_write_6 +1003166c t ??CrossCallReturnLabel_1 +10031670 t ??flash_stream_write_3 +10031674 t ??flash_stream_write_5 +10031682 t ??flash_stream_write_7 +1003169a t .text_22 +1003169a t ??CrossCallReturnLabel_0 +1003169a t ?Subroutine2 +100316a2 t .text_23 +100316a2 t ?Subroutine3 +100316ac t ?_0 +100316c4 T __iar_Memset4_word +100316c4 T __iar_Memset8_word +100316c4 t .text_1 +100316c8 t .text_2 +100316c8 t Enter8 +100316f8 T FillH2CCmd8195A +1003171a t .text_3 +1003171a t ConstructBeacon +10031858 t .text_4 +10031862 t .text_5 +10031862 t ConstructNullFunctionData +10031934 t .text_6 +1003193e t .text_7 +1003194c t .text_8 +10031958 T CheckFwRsvdPageContent +10031958 t .text_9 +1003195a T rtl8195a_set_FwRsvdPage_cmd +1003195a t .text_10 +10031962 T rtl8195a_set_FwMediaStatusRpt_cmd +10031962 t .text_11 +10031986 T rtl8195a_set_FwMacIdConfig_cmd +10031986 t .text_12 +100319d6 T rtl8195a_set_FwPwrMode_cmd +100319d6 t .text_15 +10031a24 t .text_19 +10031a24 t rtl8195a_set_FwRsvdPagePkt +10031b36 t .text_20 +10031b40 T rtl8195a_download_rsvd_page +10031b40 t .text_21 +10031b66 T rtl8195a_set_FwJoinBssRpt_cmd +10031b66 t .text_23 +10031b70 T rtl8195a_Add_RateATid +10031b70 t .text_24 +10031bc4 t ?_0 +10031bcc t IS_MCAST +10031bda T odm_RSSIMonitorInit +10031bda t .text_3 +10031be2 T ODM_RAPostActionOnAssoc +10031be2 t .text_4 +10031bea T odm_RSSIMonitorCheck +10031bea t .text_5 +10031c00 T odm_RSSIMonitorCheckCE +10031c00 t .text_7 +10031d5c T odm_RateAdaptiveMaskInit +10031d5c t .text_9 +10031d7e T odm_RefreshRateAdaptiveMask +10031d7e t .text_10 +10031d94 T odm_RefreshRateAdaptiveMaskCE +10031d94 t .text_12 +10031df4 T ODM_RAStateCheck +10031df4 t .text_14 +10031e38 T ODM_Get_Rate_Bitmap +10031e38 t .text_16 +10031f40 t .text_17 +10031f44 t .text_18 +10031f48 t .text_19 +10031f4c t .text_20 +10031f50 t .text_21 +10031f54 t .text_22 +10031f58 t .text_23 +10031f5c t .text_24 +10031f60 t .text_25 +10031f64 t .text_26 +10031f68 t .text_27 +10031f6c t .text_28 +10031f70 t .text_29 +10031f74 t ?Veneer (6) for ROM_odm_FalseAlarmCounterStatistics +10031f7c T ODM_Write_DIG +10031f7c t .text_5 +10031fc4 T odm_DIGbyRSSI_LPS +10031fc4 t .text_7 +10032024 t .text_8 +1003202c T odm_ForbiddenIGICheck +1003202c t .text_10 +100320a4 T ODM_Write_CCK_CCA_Thres +100320a4 t .text_14 +100320ca T odm_DIGInit +100320ca t .text_15 +10032162 T odm_DigAbort +10032162 t .text_16 +10032184 T odm_FAThresholdCheck +10032184 t .text_17 +100321b0 T odm_DIG +100321b0 t .text_18 +100323aa T odm_FalseAlarmCounterStatistics +100323aa t .text_19 +100323b8 T odm_CCKPacketDetectionThresh +100323b8 t .text_20 +10032408 t ?Veneer (6) for ROM_odm_QueryRxPwrPercentage +10032410 t ?Veneer (6) for ROM_odm_EVMdbToPercentage +10032418 T odm_SignalScaleMapping_92CSeries +10032418 t .text_5 +100324ac T odm_SignalScaleMapping +100324ac t .text_6 +100324ae T odm_RxPhyStatus8195A_Parsing +100324ae t .text_9 +10032614 t .text_12 +10032622 t .text_13 +10032632 T odm_Process_RSSIForDM_8195A +10032632 t .text_17 +10032720 t .text_19 +1003272c t .text_20 +10032738 t .text_21 +10032740 t .text_22 +1003274a t .text_23 +10032758 t .text_24 +10032774 t .text_25 +10032786 T ODM_PhyStatusQuery_8195A +10032786 t .text_26 +100327aa t .text_28 +100327b4 T ODM_PhyStatusQuery +100327b4 t .text_31 +100327b6 T ODM_ConfigRFWithHeaderFile +100327b6 t .text_33 +100327d4 T ODM_ConfigRFWithTxPwrTrackHeaderFile +100327d4 t .text_34 +10032800 T ODM_ConfigBBWithHeaderFile +10032800 t .text_35 +10032828 T ODM_ConfigMACWithHeaderFile +10032828 t .text_36 +1003283c T PHY_RF6052SetBandwidth8195A +1003283c t .text_3 +100328a0 t .text_4 +100328a4 t .text_5 +100328ac t .text_6 +100328b8 t .text_7 +100328c8 t .text_8 +100328c8 t phy_RF6052_Config_ParaFile +100329c0 t .text_9 +100329c6 t .text_10 +100329cc T PHY_RF6052_Config8195A +100329cc t .text_11 +100329e4 T ConfigureTxpowerTrack +100329f4 T ODM_TXPowerTrackingCallback_ThermalMeter +100329f4 t .text_4 +10032dca t .text_5 +10032dd2 t .text_6 +10032dde t __iar_annotation$$tailcall +10032de0 t .text_7 +10032dec t __iar_annotation$$tailcall +10032dee t .text_8 +10032dfa t __iar_annotation$$tailcall +10032dfc t .text_9 +10032e08 T ODM_ResetIQKResult +10032e08 t .text_10 +10032e44 T ODM_GetRightChnlPlaceforIQK +10032e44 t .text_11 +10032e78 t ?_0 +10032eb4 t check_fwstate +10032ec2 T rtw_os_recv_resource_init +10032ec2 t .text_3 +10032ec6 T rtw_os_recv_resource_alloc +10032ec6 t .text_4 +10032ed0 T rtw_os_recv_resource_free +10032ed0 t .text_5 +10032ed2 T rtw_recv_indicatepkt +10032ed2 t .text_8 +1003308e t .text_9 +10033098 t .text_10 +100330a0 t get_hdr_bssid +100330cc t .text_4 +100330cc t get_recvframe_data +100330d4 t .text_5 +100330d4 t filter_packet +10033158 T promisc_deinit +10033158 t .text_6 +100331a2 t .text_7 +100331a8 T promisc_set_enable +100331a8 t .text_8 +10033214 t .text_9 +1003321e t .text_10 +1003321e t promisc_get_encrypt +10033272 t .text_11 +10033272 t promisc_insert +10033308 t .text_12 +10033320 t .text_13 +10033320 t promisc_info_get +100333be t .text_14 +100333be t promisc_recv_func_posthandle +10033450 t .text_15 +10033450 t promisc_validate_recv_data_frame +100335b8 t .text_16 +100335c0 t .text_17 +100335c0 t promisc_OnBeacon +10033748 t .text_18 +10033750 t .text_19 +10033750 t promisc_validate_recv_frame +100337e8 T promisc_recv_func +100337e8 t .text_20 +10033814 T promisc_set +10033814 t .text_21 +1003385c T is_promisc_enabled +1003385c t .text_22 +10033872 T promisc_get_fixed_channel +10033872 t .text_23 +10033900 t .text_24 +10033904 t .text_25 +10033908 t .text_26 +1003390c t .text_27 +10033918 T zero_bssid +10033918 t .text_28 +10033920 T Phydm_CheckAdaptivity +1003396e T Phydm_NHMCounterStatisticsInit +1003396e t .text_3 +100339dc T Phydm_NHMCounterStatistics +100339dc t .text_4 +100339f6 T Phydm_GetNHMCounterStatistics +100339f6 t .text_5 +10033a16 T Phydm_NHMCounterStatisticsReset +10033a16 t .text_6 +10033a3e t .text_7 +10033a4a T Phydm_SetEDCCAThreshold +10033a4a t .text_8 +10033a74 t .text_9 +10033a80 t .text_11 +10033a8e T Phydm_MACEDCCAState +10033a8e t .text_12 +10033abc t .text_13 +10033ac8 T Phydm_CalNHMcnt +10033ac8 t .text_14 +10033b00 T Phydm_CheckEnvironment +10033b00 t .text_15 +10033b68 t .text_16 +10033b7a T Phydm_AdaptivityInit +10033b7a t .text_18 +10033c52 t .text_19 +10033c5a T Phydm_Adaptivity +10033c5a t .text_20 +10033cc8 t ?Veneer (6) for ROM_odm_GetDefaultCrytaltalCap +10033cd0 t ?Veneer (6) for ROM_ODM_CfoTrackingReset +10033cd8 t ?Veneer (6) for ROM_odm_CfoTrackingFlow +10033ce0 T ODM_CfoTrackingInit +10033d0a T ODM_CfoTracking +10033d0a t .text_3 +10033d28 T ODM_ParsingCFO +10033d28 t .text_4 +10033d5c T odm_TXPowerTrackingInit +10033d5e T getSwingIndex +10033d5e t .text_3 +10033daa T odm_TXPowerTrackingThermalMeterInit +10033daa t .text_4 +10033e64 T ODM_TXPowerTrackingCheck +10033e64 t .text_5 +10033e72 T odm_TXPowerTrackingCheckCE +10033e72 t .text_6 +10033ef4 t .text_7 +10033ef8 t .text_8 +10033efc T OFDMSwingTable_New +10033efc t .text_11 +10033fa8 T ODM_InitDebugSetting +10033fbc T __iar_Strchr +10033fbc T strchr +10033fd2 T __iar_Stolx +10034058 T __iar_Stoulx +1003419a t .text_3 +100341a0 T __iar_Stoul +100341a0 t .text_4 +100341a4 t digits +100341cc t ndigs +100341f4 T MediaConnection +10034204 T MediaDisconnection +10034204 t .text_3 +10034212 t .text_4 +1003421e T RATaskEnable +1003421e t .text_5 +10034246 T SetMediaStatus +10034246 t .text_6 +10034280 T H2CHDL_JoinInfo +10034280 t .text_7 +100342b4 T H2CHDL_SetRsvdPage +100342b4 t .text_8 +10034318 t .text_9 +1003431c t .text_10 +10034320 t .text_11 +10034324 T H2CCmdCommon +10034324 t .text_12 +10034364 T __aeabi_llsr +10034384 t CheckPositive +1003444c T ODM_ReadAndConfig_MP_8195A_RadioA +1003444c t .text_23 +100344a6 t .text_26 +100344b6 T ODM_ReadAndConfig_MP_8195A_TxPowerTrack_QFN48 +100344b6 t .text_28 +100344c2 T ODM_ReadAndConfig_MP_8195A_TxPowerTrack_QFN56 +100344c2 t .text_29 +100344cc t .text_30 +1003454c T ODM_ReadAndConfig_MP_8195A_TxPowerTrack_TFBGA96 +1003454c t .text_31 +10034558 T ODM_ReadAndConfig_MP_8195A_TXPWR_LMT +10034558 t .text_32 +10034590 t .text_33 +10034594 t .text_34 +10034598 t .text_35 +1003459c t .text_36 +100345a0 t .text_37 +100345a4 t .text_38 +100345a8 t CheckPositive +10034670 T ODM_ReadAndConfig_MP_8195A_AGC_TAB +10034670 t .text_6 +100346d2 T ODM_ReadAndConfig_MP_8195A_PHY_REG +100346d2 t .text_8 +10034734 t .text_9 +10034744 T ODM_ReadAndConfig_MP_8195A_PHY_REG_PG +10034744 t .text_11 +1003477c t .text_12 +10034780 t .text_13 +10034784 t .text_14 +10034788 t .text_15 +1003478c t CheckPositive +10034854 T ODM_ReadAndConfig_MP_8195A_MAC_REG +10034854 t .text_4 +100348bc t .text_5 +100348c0 t .text_6 +100348c4 T __iar_Memchr +100348c4 T memchr +1003491c T odm_ConfigRFReg_8195A +10034948 t .text_3 +1003494c T odm_ConfigRF_RadioA_8195A +1003494c t .text_4 +10034954 t .text_6 +1003495a T odm_ConfigMAC_8195A +1003495a t .text_7 +1003495e T odm_ConfigBB_AGC_8195A +1003495e t .text_8 +10034966 T odm_ConfigBB_PHY_REG_PG_8195A +10034966 t .text_9 +1003498e t .text_10 +10034994 T odm_ConfigBB_PHY_8195A +10034994 t .text_11 +100349d2 t .text_12 +100349dc T odm_ConfigBB_TXPWR_LMT_8195A +100349dc t .text_13 +100349f8 t ?Veneer (6) for CmdDumpWord +10034a00 t ?Veneer (6) for CmdWriteWord +10034a08 t ?Veneer (6) for simple_strtoul +10034a10 t ?Veneer (6) for prvAtoi +10034a18 T fATSD +10034a20 t ??CrossCallReturnLabel_2 +10034a36 t ??fATSD_0 +10034a4c t ??fATSD_1 +10034a50 t ??CrossCallReturnLabel_17 +10034a62 t ??fATSD_2 +10034a66 T fATSE +10034a66 t .text_6 +10034a6e t ??CrossCallReturnLabel_1 +10034a84 t ??fATSE_0 +10034a9a t ??fATSE_1 +10034a9e t ??CrossCallReturnLabel_16 +10034aaa t ??fATSE_2 +10034aae t .text_7 +10034aae t ?Subroutine2 +10034ab6 T fATSA +10034ab6 t .text_8 +10034acc t ??CrossCallReturnLabel_3 +10034ae2 t ??fATSA_0 +10034b02 t ??fATSA_2 +10034b14 t ??fATSA_1 +10034b3e t ??fATSA_5 +10034b4e t ??fATSA_4 +10034b5e t ??fATSA_8 +10034b8c t ??fATSA_6 +10034b9e t ??fATSA_7 +10034bb6 t ??fATSA_9 +10034bbc t ??fATSA_11 +10034bc6 t ??fATSA_12 +10034bce t ??fATSA_13 +10034bf0 t ??fATSA_10 +10034bf4 t ??fATSA_3 +10034bfa T fATSG +10034bfa t .text_9 +10034c08 t ??CrossCallReturnLabel_4 +10034c26 t ??fATSG_0 +10034c38 t ??fATSG_1 +10034c46 t ??fATSG_4 +10034c4c t ??fATSG_2 +10034ca4 t ??fATSG_6 +10034ca6 t ??fATSG_5 +10034cc4 t ??fATSG_18 +10034cc6 t ??fATSG_26 +10034d02 t ??fATSG_3 +10034d08 t ??fATSG_20 +10034d0c t ??fATSG_19 +10034d10 t ??fATSG_22 +10034d14 t ??fATSG_21 +10034d18 t ??fATSG_24 +10034d1c t ??fATSG_23 +10034d20 t ??fATSG_25 +10034d24 t ??fATSG_8 +10034d40 t ??fATSG_28 +10034d42 t ??fATSG_27 +10034d46 t ??fATSG_30 +10034d4a t ??fATSG_29 +10034d4e t ??fATSG_32 +10034d52 t ??fATSG_31 +10034d56 t ??fATSG_34 +10034d5a t ??fATSG_33 +10034d5e t ??fATSG_35 +10034d62 t ??fATSG_7 +10034d84 t ??fATSG_37 +10034d86 t ??fATSG_36 +10034d8a t ??fATSG_39 +10034d8e t ??fATSG_38 +10034d92 t ??fATSG_41 +10034d96 t ??fATSG_40 +10034d9a t ??fATSG_43 +10034d9e t ??fATSG_42 +10034da2 t ??fATSG_45 +10034da6 t ??fATSG_44 +10034daa t ??fATSG_46 +10034dae t ??fATSG_10 +10034dd0 t ??fATSG_48 +10034dd2 t ??fATSG_47 +10034dd6 t ??fATSG_50 +10034dda t ??fATSG_49 +10034dde t ??fATSG_52 +10034de2 t ??fATSG_51 +10034de6 t ??fATSG_54 +10034dea t ??fATSG_53 +10034dee t ??fATSG_56 +10034df2 t ??fATSG_55 +10034df6 t ??fATSG_57 +10034dfa t ??fATSG_9 +10034e28 t ??fATSG_58 +10034e2c t ??fATSG_59 +10034e30 t ??fATSG_60 +10034e34 t ??fATSG_61 +10034e38 t ??fATSG_62 +10034e3c t ??fATSG_63 +10034e40 t ??fATSG_64 +10034e44 t ??fATSG_65 +10034e48 t ??fATSG_66 +10034e4c t ??fATSG_67 +10034e50 t ??fATSG_68 +10034e54 t ??fATSG_12 +10034e6a t ??fATSG_70 +10034e6c t ??fATSG_69 +10034e70 t ??fATSG_72 +10034e74 t ??fATSG_71 +10034e78 t ??fATSG_74 +10034e7c t ??fATSG_73 +10034e80 t ??fATSG_75 +10034e84 t ??fATSG_11 +10034ea0 t ??fATSG_77 +10034ea2 t ??fATSG_76 +10034ea6 t ??fATSG_79 +10034eaa t ??fATSG_78 +10034eae t ??fATSG_81 +10034eb2 t ??fATSG_80 +10034eb6 t ??fATSG_83 +10034eba t ??fATSG_82 +10034ebe t ??fATSG_84 +10034ec2 t ??fATSG_14 +10034ee0 t ??fATSG_85 +10034ee4 t ??fATSG_87 +10034ee8 t ??fATSG_86 +10034eec t ??fATSG_89 +10034ef0 t ??fATSG_88 +10034ef4 t ??fATSG_91 +10034ef8 t ??fATSG_90 +10034efc t ??fATSG_92 +10034f00 t ??fATSG_13 +10034f1e t ??fATSG_93 +10034f22 t ??fATSG_95 +10034f26 t ??fATSG_94 +10034f2a t ??fATSG_97 +10034f2e t ??fATSG_96 +10034f32 t ??fATSG_99 +10034f36 t ??fATSG_98 +10034f3a t ??fATSG_100 +10034f3e t ??fATSG_16 +10034f58 t ??fATSG_101 +10034f5c t ??fATSG_103 +10034f60 t ??fATSG_102 +10034f64 t ??fATSG_105 +10034f68 t ??fATSG_104 +10034f6c t ??fATSG_107 +10034f70 t ??fATSG_106 +10034f74 t ??fATSG_15 +10034f8e t ??fATSG_108 +10034f92 t ??fATSG_110 +10034f96 t ??fATSG_109 +10034f9a t ??fATSG_112 +10034f9e t ??fATSG_111 +10034fa2 t ??fATSG_114 +10034fa6 t ??fATSG_113 +10034faa t ??fATSG_17 +10034fc0 T fATSC +10034fc0 t .text_10 +10034fdc t ??fATSC_0 +10034fe4 T fATSR +10034fe4 t .text_11 +10035000 t ??fATSR_0 +10035008 T fATSP +10035008 t .text_12 +10035018 t ??CrossCallReturnLabel_5 +1003502e t ??fATSP_0 +10035044 t ??fATSP_2 +1003505a t ??fATSP_1 +10035068 t ??fATSP_5 +10035078 t ??fATSP_4 +10035082 t ??CrossCallReturnLabel_37 +100350b4 t ??fATSP_8 +100350ba t ??fATSP_7 +100350d8 t ??fATSP_9 +100350f2 t ??fATSP_6 +100350f8 t ??fATSP_10 +1003510a t ??fATSP_3 +10035110 T fATSL +10035110 t .text_13 +10035118 t ??CrossCallReturnLabel_0 +1003512c t ??fATSL_0 +1003513e t ??fATSL_1 +10035142 t ??CrossCallReturnLabel_15 +10035168 t ??fATSL_6 +10035170 t ??CrossCallReturnLabel_39 +10035176 t ??fATSL_7 +1003517e t ??CrossCallReturnLabel_38 +10035182 t ??fATSL_8 +1003518e t ??fATSL_5 +10035194 t ??fATSL_9 +100351a0 t ??CrossCallReturnLabel_8 +100351a2 t ??fATSL_4 +100351a8 t ??fATSL_3 +100351b0 t ??fATSL_2 +100351b4 t .text_14 +100351b4 t ?Subroutine6 +100351b6 t ??Subroutine6_0 +100351bc T fATSs +100351bc t .text_15 +100351c8 t ??CrossCallReturnLabel_6 +100351de t ??fATSs_0 +100351fa t ??CrossCallReturnLabel_18 +100351fc t ??fATSs_1 +1003520c T fATSc +1003520c t .text_16 +1003521a t ??CrossCallReturnLabel_7 +10035236 t ??fATSc_0 +10035252 t ??CrossCallReturnLabel_22 +1003525e t ??CrossCallReturnLabel_21 +10035264 t ??fATSc_2 +1003526c t ??CrossCallReturnLabel_20 +10035270 t ??fATSc_3 +10035278 t ??CrossCallReturnLabel_19 +1003527a t ??fATSc_1 +100352a0 t .text_17 +100352a0 t ?Subroutine3 +100352a2 t ??Subroutine3_0 +100352a8 t .text_18 +100352a8 t ?Subroutine0 +100352ac t ??Subroutine0_0 +100352b2 T fATSt +100352b2 t .text_19 +100352ba T fATSx +100352ba t .text_20 +100352d4 T fATGR +100352d4 t .text_21 +100352ec t ??CrossCallReturnLabel_14 +100352f4 t ??CrossCallReturnLabel_36 +100352fc t ??CrossCallReturnLabel_29 +10035318 t ??CrossCallReturnLabel_13 +1003531c t ??CrossCallReturnLabel_35 +10035320 t ??CrossCallReturnLabel_28 +10035334 t ??CrossCallReturnLabel_12 +10035338 t ??CrossCallReturnLabel_34 +1003533c t ??CrossCallReturnLabel_27 +10035350 t ??CrossCallReturnLabel_11 +10035354 t ??CrossCallReturnLabel_33 +10035358 t ??CrossCallReturnLabel_26 +1003536e t ??CrossCallReturnLabel_10 +10035372 t ??CrossCallReturnLabel_32 +10035376 t ??CrossCallReturnLabel_25 +1003538a t ??CrossCallReturnLabel_9 +1003538e t ??CrossCallReturnLabel_31 +10035392 t ??CrossCallReturnLabel_24 +100353a8 t ??CrossCallReturnLabel_30 +100353ac t ??CrossCallReturnLabel_23 +100353b2 t .text_22 +100353b2 t ?Subroutine5 +100353ba t .text_23 +100353ba t ?Subroutine4 +100353c2 t .text_24 +100353c2 t ?Subroutine1 +100353c4 t ??Subroutine1_0 +100353ca T at_sys_init +100353ca t .text_25 +100353d4 t ??DataTable80 +100353d8 t ??DataTable80_1 +100353dc t ??DataTable80_2 +100353e0 t ??DataTable80_3 +100353e4 t ??DataTable80_4 +100353e8 t ??DataTable80_5 +100353ec t ?_14 +10035410 t ?_15 +10035430 t ?_17 +10035454 t ?_18 +1003547c t ?_20 +1003549c t ?_21 +100354c0 t ?_22 +100354dc t ?_23 +10035510 t ?_24 +10035518 t ?_25 +10035540 t ?_26 +10035548 t ?_27 +10035560 t ?_29 +10035580 t ?_30 +100355a4 t ?_31 +100355c0 t ?_32 +100355d4 t ?_33 +10035600 t ?_34 +1003562c t ?_36 +10035654 t ?_37 +10035684 t ?_38 +1003568c t ?_39 +100356a0 t ?_40 +100356c8 t ?_42 +100356ec t ?_43 +10035714 t ?_44 +10035730 t ?_46 +10035754 t ?_47 +10035778 t ?_48 +1003579c t ?_50 +100357c4 t ?_51 +100357f0 t ?_52 +10035814 t ?_53 +10035838 t ?_54 +1003585c t ?_55 +10035878 t ?_56 +10035894 t ?_57 +100358b0 t ?_58 +100358c4 t ?_59 +100358dc t ?_60 +100358f8 t ?_61 +10035914 t ?_62 +10035930 t ?_63 +10035938 t ?_64 +10035944 t ?_65 +1003595c t ?_66 +10035970 t ?_67 +10035980 t ?_68 +10035990 t list_add +1003599c T hash_index +1003599c t .text_9 +100359a0 t ??hash_index_1 +100359aa t ??hash_index_0 +100359b8 T log_add_new_command +100359b8 t .text_10 +100359de T log_service_add_table +100359de t .text_12 +100359e8 t ??log_service_add_table_1 +100359f2 t ??log_service_add_table_0 +100359f8 T parse_param +100359f8 t .text_15 +100359fa t ??parse_param_0 +10035a02 t ??parse_param_3 +10035a04 t ??parse_param_1 +10035a1e t ??parse_param_4 +10035a30 t ??parse_param_5 +10035a42 t ??parse_param_2 +10035a46 t ??parse_param_6 +10035a4e T fAT_exit +10035a4e t .text_23 +10035a62 T at_log_init +10035a62 t .text_24 +10035a6c t ??DataTable27_3 +10035a70 t ??DataTable27_8 +10035a74 t ?_18 +10035a88 T sys_clear_ota_signature +10035a88 t .text_3 +10035a90 t ??CrossCallReturnLabel_10 +10035a94 t ??CrossCallReturnLabel_34 +10035aa0 t ??CrossCallReturnLabel_38 +10035aa8 t ??CrossCallReturnLabel_2 +10035aac t ??sys_clear_ota_signature_0 +10035ab8 t ??CrossCallReturnLabel_33 +10035abe t ??CrossCallReturnLabel_37 +10035ac2 t ??CrossCallReturnLabel_1 +10035ac6 t ??sys_clear_ota_signature_1 +10035aca t ??CrossCallReturnLabel_13 +10035adc t ??CrossCallReturnLabel_32 +10035af2 t ??CrossCallReturnLabel_0 +10035b0a t ??CrossCallReturnLabel_18 +10035b14 t ??CrossCallReturnLabel_31 +10035b28 t ??sys_clear_ota_signature_2 +10035b2c t .text_4 +10035b2c t ?Subroutine1 +10035b36 T sys_recover_ota_signature +10035b36 t .text_5 +10035b40 t ??CrossCallReturnLabel_11 +10035b44 t ??CrossCallReturnLabel_30 +10035b56 t ??CrossCallReturnLabel_36 +10035b5e t ??CrossCallReturnLabel_5 +10035b62 t ??sys_recover_ota_signature_0 +10035b6e t ??CrossCallReturnLabel_29 +10035b7a t ??CrossCallReturnLabel_35 +10035b7e t ??CrossCallReturnLabel_4 +10035b82 t ??sys_recover_ota_signature_1 +10035b86 t ??CrossCallReturnLabel_12 +10035b9a t ??CrossCallReturnLabel_28 +10035bb0 t ??CrossCallReturnLabel_3 +10035bcc t ??CrossCallReturnLabel_27 +10035bde t ??CrossCallReturnLabel_9 +10035be4 t ??CrossCallReturnLabel_20 +10035bf2 t ??CrossCallReturnLabel_26 +10035bf8 t ??CrossCallReturnLabel_7 +10035c04 t ??CrossCallReturnLabel_17 +10035c0e t ??CrossCallReturnLabel_25 +10035c2c t ??sys_recover_ota_signature_2 +10035c32 t .text_6 +10035c32 t ?Subroutine6 +10035c3c t .text_7 +10035c3c t ?Subroutine5 +10035c48 t .text_8 +10035c48 t ?Subroutine3 +10035c50 t .text_9 +10035c50 t ??Subroutine8_0 +10035c56 t .text_10 +10035c56 t ?Subroutine2 +10035c60 t .text_11 +10035c60 t ?Subroutine0 +10035c66 t ??Subroutine0_0 +10035c68 t .text_12 +10035c68 t ??Subroutine9_0 +10035c6e T sys_log_uart_on +10035c6e t .text_13 +10035c72 T sys_log_uart_off +10035c72 t .text_14 +10035c76 T sys_adc_calibration +10035c76 t .text_15 +10035c92 t ??CrossCallReturnLabel_14 +10035c96 t ??CrossCallReturnLabel_24 +10035cb2 t ??CrossCallReturnLabel_8 +10035cb8 t ??CrossCallReturnLabel_19 +10035cc6 t ??CrossCallReturnLabel_23 +10035cce t ??CrossCallReturnLabel_6 +10035cd2 t ??CrossCallReturnLabel_15 +10035cd6 t ??CrossCallReturnLabel_16 +10035ce8 t ??sys_adc_calibration_0 +10035cf4 t ??CrossCallReturnLabel_22 +10035d00 t ??CrossCallReturnLabel_21 +10035d0c t ??sys_adc_calibration_1 +10035d0e t .text_16 +10035d0e t ?Subroutine7 +10035d1a t .text_17 +10035d1a t ?Subroutine4 +10035d1e t ??Subroutine4_0 +10035d24 t ?_0 +10035d30 t ?_1 +10035d48 t ?_2 +10035d5c t ?_3 +10035d68 t ?_4 +10035d88 t ?_5 +10035dac t ?_6 +10035dd0 t ?_7 +10035df8 t ?Veneer (6) for HAL_GPIO_WritePin_8195a +10035e00 t ?Veneer (6) for HAL_GPIO_ReadPin_8195a +10035e08 T gpio_set_hal_pin_mode +10035e1a t ??gpio_set_hal_pin_mode_0 +10035e28 t ??gpio_set_hal_pin_mode_2 +10035e2a t ??gpio_set_hal_pin_mode_1 +10035e2e T gpio_set +10035e2e t .text_3 +10035e42 t ??CrossCallReturnLabel_3 +10035e54 T gpio_init +10035e54 t .text_4 +10035e74 t ??gpio_init_0 +10035e76 T gpio_mode +10035e76 t .text_5 +10035e80 t .text_6 +10035e80 t ?Subroutine0 +10035e8c T gpio_dir +10035e8c t .text_7 +10035e92 t ??CrossCallReturnLabel_4 +10035e9e t ??CrossCallReturnLabel_2 +10035eb2 T gpio_write +10035eb2 t .text_8 +10035eb8 t ??CrossCallReturnLabel_5 +10035ec4 t ??CrossCallReturnLabel_1 +10035ed2 t .text_9 +10035ed2 t ?Subroutine2 +10035ede t .text_10 +10035ede t ?Subroutine1 +10035eea T gpio_read +10035eea t .text_11 +10035f00 t ??CrossCallReturnLabel_0 +10035f0c t ??__func__ +10035f18 t ?_0 +10035f30 t ?_1 +10035f78 t ??__func___1 +10035f84 t ??__func___2 +10035f90 t ??__func___3 +10035f9c T printf +10035fc0 T HalLogUartInitSetting +1003601a T HalInitLogUart +1003601a t .text_3 +10036088 T HalDeinitLogUart +10036088 t .text_4 +100360a8 t .text_5 +100360ac t .text_6 +100360b0 t .text_7 +100360b4 t .text_8 +100360b8 T pin_function +100360ba t out +100360d2 T _PrintfTiny +100360d2 t .text_3 +1003620c T strlen +10036244 t init_wifi_struct +10036296 t .text_8 +10036296 t print_scan_result +100362ba t ??CrossCallReturnLabel_3 +100362f4 t ??print_scan_result_0 +10036344 t ??print_scan_result_1 +10036364 t ?_25 +1003636c t ?_26 +10036374 t ?_24 +1003637c t ?_28 +10036384 t ?_29 +1003638c t ?_31 +10036394 t .text_15 +10036394 t app_scan_result_handler +100363c0 t ??app_scan_result_handler_0 +100363c4 t ??app_scan_result_handler_1 +100363c8 T fATW0 +100363c8 t .text_16 +100363da t ??fATW0_0 +100363f4 t ??CrossCallReturnLabel_14 +100363f8 T fATW1 +100363f8 t .text_17 +1003640a t ??CrossCallReturnLabel_10 +10036418 t ??CrossCallReturnLabel_13 +1003642c t ??fATW1_0 +1003642e T fATW2 +1003642e t .text_18 +10036440 t ??CrossCallReturnLabel_12 +1003644e t ??fATW2_0 +1003645a t ??fATW2_1 +10036468 t .text_19 +10036468 t ?Subroutine5 +1003646e T fATW3 +1003646e t .text_20 +1003648e t ??fATW3_0 +10036496 t ??fATW3_1 +100364ac T fATW4 +100364ac t .text_21 +100364b4 t ??CrossCallReturnLabel_9 +100364be t ??CrossCallReturnLabel_11 +100364ce t .text_22 +100364ce t ?Subroutine4 +100364dc T fATW5 +100364dc t .text_23 +100364f8 T fATW6 +100364f8 t .text_24 +1003650a t ??fATW6_0 +10036538 t ??fATW6_2 +1003654a t ??fATW6_1 +10036550 t ??DataTable159 +10036554 t ?_27 +10036574 T fATWA +10036574 t .text_27 +10036590 t ??fATWA_0 +10036598 t ??fATWA_2 +100365c8 t ??fATWA_3 +100365e0 t ??fATWA_4 +100365ec t ??fATWA_5 +1003663e t ??CrossCallReturnLabel_8 +10036646 t ??fATWA_1 +1003664c t ??fATWA_8 +10036650 t ??CrossCallReturnLabel_17 +10036652 t ??fATWA_6 +1003666e t ??CrossCallReturnLabel_6 +10036670 t ??fATWA_9 +1003667c t ??fATWA_10 +10036686 t ??fATWA_7 +1003668c t ??DataTable160 +10036690 T fATWC +10036690 t .text_29 +100366c0 t ??fATWC_1 +100366d2 t ??fATWC_0 +100366de t ??fATWC_2 +1003670e t ??fATWC_4 +1003675a t ??fATWC_5 +1003677c t ??fATWC_6 +10036784 t ??fATWC_7 +100367aa t ??fATWC_3 +100367b6 T fATWD +100367b6 t .text_30 +100367f0 t ??fATWD_0 +100367f6 t ??fATWD_3 +100367fa t ??CrossCallReturnLabel_16 +100367fc t ??fATWD_1 +1003680c t ??fATWD_4 +10036814 t ??fATWD_5 +10036822 t ??fATWD_2 +10036826 t .text_31 +10036826 t ?Subroutine6 +1003682e T fATWS +1003682e t .text_32 +1003683a t ??CrossCallReturnLabel_21 +10036880 t ??fATWS_2 +10036896 t ??fATWS_5 +100368b2 t ??fATWS_4 +100368cc t ??fATWS_3 +100368d2 t ??fATWS_0 +100368e6 t ??fATWS_7 +100368ee t ??fATWS_6 +100368f4 t ??fATWS_1 +100368fa t .text_33 +100368fa t ?Subroutine8 +100368fc t ??Subroutine8_0 +10036902 T fATWR +10036902 t .text_34 +10036928 T fATWP +10036928 t .text_35 +10036952 t ??fATWP_0 +10036960 t ??fATWP_3 +10036964 t ??fATWP_2 +1003696c t ??fATWP_1 +1003696e T fATWB +1003696e t .text_36 +1003698a t ??fATWB_0 +1003699e t ??fATWB_2 +100369ca t ??CrossCallReturnLabel_7 +100369d2 t ??fATWB_1 +100369d8 t ??fATWB_5 +100369dc t ??CrossCallReturnLabel_15 +100369de t ??fATWB_3 +100369fa t ??CrossCallReturnLabel_5 +100369fc t ??fATWB_6 +10036a08 t ??fATWB_7 +10036a1c t ??fATWB_4 +10036a20 t ??DataTable166 +10036a24 t ??DataTable166_1 +10036a28 t ??DataTable166_2 +10036a2c t .text_40 +10036a2c t ?Subroutine3 +10036a40 t .text_41 +10036a40 t ?Subroutine2 +10036a4a T fATWI +10036a4a t .text_42 +10036a54 t ??CrossCallReturnLabel_22 +10036a70 t ??fATWI_0 +10036aa4 t ??fATWI_2 +10036ac2 t ??fATWI_4 +10036ad6 t ??fATWI_3 +10036ad8 t ??fATWI_5 +10036ade t ??fATWI_1 +10036ae2 T fATWM +10036ae2 t .text_43 +10036aea t ??CrossCallReturnLabel_2 +10036b04 t ??fATWM_0 +10036b08 t ??CrossCallReturnLabel_20 +10036b12 t ??fATWM_1 +10036b16 t .text_45 +10036b16 t ?Subroutine7 +10036b1e t .text_46 +10036b1e t ?Subroutine0 +10036b28 T fATWE +10036b28 t .text_47 +10036b3a T fATWQ +10036b3a t .text_48 +10036b5c t ??fATWQ_0 +10036b64 T fATWW +10036b64 t .text_49 +10036b7c t ??fATWW_0 +10036b8e T fATWw +10036b8e t .text_50 +10036b90 T fATWO +10036b90 t .text_51 +10036b98 t ??CrossCallReturnLabel_0 +10036bb0 t ??CrossCallReturnLabel_18 +10036bb4 t ??fATWO_0 +10036bbc t ??fATWO_1 +10036bc2 t ??fATWO_2 +10036bc6 T fATWx +10036bc6 t .text_52 +10036bfe t ??fATWx_0 +10036c66 t ??CrossCallReturnLabel_4 +10036cc4 t ??fATWx_1 +10036cc6 t ??fATWx_3 +10036cd4 t ??fATWx_5 +10036d02 t ??fATWx_4 +10036d0e t ??fATWx_2 +10036d1c t .text_53 +10036d1c t ?Subroutine1 +10036d2e T fATWZ +10036d2e t .text_54 +10036d3a t ??CrossCallReturnLabel_23 +10036d50 t ??fATWZ_0 +10036d60 t ??fATWZ_2 +10036d7a t ??fATWZ_3 +10036d82 t ??fATWZ_4 +10036d8c t ??fATWZ_1 +10036d90 T at_wifi_init +10036d90 t .text_56 +10036da4 t ??DataTable168 +10036da8 t ??DataTable168_1 +10036dac t ??DataTable168_2 +10036db0 t ??DataTable168_3 +10036db4 t ??DataTable168_4 +10036db8 t ??DataTable168_5 +10036dbc t ??DataTable168_6 +10036dc0 t ??DataTable168_7 +10036dc4 t ??DataTable168_8 +10036dc8 t ??DataTable168_9 +10036dcc t ??DataTable168_10 +10036dd0 t ??DataTable168_11 +10036dd4 t ??DataTable168_12 +10036dd8 t ??DataTable168_13 +10036ddc t ??DataTable168_14 +10036de0 t ?_30 +10036de8 t ?_33 +10036df4 t ?_34 +10036dfc t ?_35 +10036e08 t ?_36 +10036e14 t ?_37 +10036e20 t ?_38 +10036e28 t ?_39 +10036e30 t ?_41 +10036e38 t ?_42 +10036e54 t ?_43 +10036e78 t ?_44 +10036ea0 t ?_45 +10036ec4 t ?_46 +10036ef4 t ?_47 +10036f10 t ?_48 +10036f3c t ?_49 +10036f64 t ?_50 +10036f8c t ?_51 +10036fbc t ?_52 +10036fd8 t ?_53 +10036ffc t ?_54 +1003701c t ?_55 +10037040 t ?_56 +1003705c t ?_57 +10037070 t ?_58 +1003708c t ?_59 +10037094 t ?_60 +100370a4 t ?_61 +100370c0 t ?_63 +100370e0 t ?_64 +10037104 t ?_65 +10037140 t ?_66 +10037160 t ?_67 +1003717c t ?_68 +10037194 t ?_70 +100371b4 t ?_71 +100371cc t ?_72 +100371e0 t ?_73 +100371fc t ?_76 +10037218 t ?_77 +1003724c t ?_78 +10037280 t ?_79 +100372b4 t ?_80 +100372d4 t ?_81 +100372f4 t ?_82 +10037310 t ?_83 +10037330 t ?_86 +1003734c t ?_87 +10037364 t ?_88 +10037388 t ?_89 +100373ac t ?_90 +100373e0 t ?_91 +100373e8 t ?_94 +10037408 t ?_95 +10037438 t ?_96 +10037440 t ?_97 +1003745c t ?_98 +10037474 t ?_99 +1003747c t ?_100 +10037498 t ?_101 +100374b4 t ?_103 +100374c4 t ?_104 +100374e0 t ?_105 +10037510 t ?_110 +10037538 t ?_112 +1003755c t ?_113 +10037570 t ?_114 +10037588 t ?_115 +100375a4 t ?_116 +100375b0 t ?_118 +100375d0 t ?_119 +1003760c t ?_120 +10037614 t ?_121 +1003761c t ?_122 +10037638 t ?_123 +10037654 t ?_124 +10037678 t ?_125 +1003768c t ?_126 +100376b4 t ?_127 +100376cc t ?_128 +100376e4 t ?_129 +10037700 t ?_130 +10037714 t ?_131 +10037728 t ?_132 +10037738 t ?_134 +10037754 t ?_135 +1003777c T LoadWifiConfig +10037846 t ??LoadWifiConfig_0 +10037856 t ??LoadWifiConfig_2 +1003785e t ??LoadWifiConfig_1 +10037862 T StoreApInfo +10037862 t .text_6 +10037898 t ??StoreApInfo_0 +1003789e t ??CrossCallReturnLabel_6 +100378b0 t ??CrossCallReturnLabel_5 +100378ce t ??CrossCallReturnLabel_3 +100378e6 t ??StoreApInfo_1 +100378ea t ??CrossCallReturnLabel_8 +100378f4 t ??CrossCallReturnLabel_2 +10037904 t ??StoreApInfo_2 +10037922 t ??CrossCallReturnLabel_1 +1003792e t ??StoreApInfo_3 +10037938 t ??CrossCallReturnLabel_0 +10037950 t ??CrossCallReturnLabel_7 +10037956 t .text_7 +10037956 t ?Subroutine2 +10037960 t .text_8 +10037960 t ?Subroutine0 +10037966 T rgb_mode_handle_off +10037966 t .text_10 +1003797a T rgb_mode_handle_on +1003797a t .text_11 +10037988 t .text_12 +10037988 t _handle_post_rgb_json +100379a4 t ??CrossCallReturnLabel_12 +100379ac t ??CrossCallReturnLabel_11 +100379b6 t ??CrossCallReturnLabel_10 +100379c0 t ??CrossCallReturnLabel_9 +10037a2c t ??_handle_post_rgb_json_1 +10037a48 t ??_handle_post_rgb_json_2 +10037a60 t ??_handle_post_rgb_json_3 +10037a62 t ??_handle_post_rgb_json_4 +10037a7e t ??_handle_post_rgb_json_5 +10037a80 t ??_handle_post_rgb_json_6 +10037a8e t ??_handle_post_rgb_json_0 +10037a92 t .text_13 +10037a92 t ?Subroutine3 +10037a98 T _handle_post_rgb +10037a98 t .text_14 +10037aa4 t ??_handle_post_rgb_1 +10037ab4 t ??_handle_post_rgb_0 +10037ad0 t ??_handle_post_rgb_2 +10037ad2 T restful_api_handler +10037ad2 t .text_15 +10037b3a t ??restful_api_handler_2 +10037b4c t ??restful_api_handler_1 +10037b52 t ??restful_api_handler_0 +10037b5c T vBasicWEBServer +10037b5c t .text_16 +10037b88 t ??CrossCallReturnLabel_4 +10037bb4 t ??vBasicWEBServer_0 +10037bca t ??vBasicWEBServer_2 +10037bd8 t ??vBasicWEBServer_1 +10037bf0 t ??vBasicWEBServer_4 +10037bf6 t ??vBasicWEBServer_3 +10037c02 t .text_17 +10037c02 t ?Subroutine1 +10037c0a T start_web_server +10037c0a t .text_18 +10037c48 t ??start_web_server_0 +10037c58 t ??start_web_server_1 +10037c5c t ??DataTable44 +10037c60 t ??DataTable44_1 +10037c64 t ??DataTable44_2 +10037c68 T stop_web_server +10037c68 t .text_22 +10037c78 t ??stop_web_server_0 +10037c9e t ??stop_web_server_3 +10037ca8 t ??stop_web_server_2 +10037cb2 t ??stop_web_server_1 +10037cbe t ??stop_web_server_4 +10037ccc t ??DataTable45 +10037cd0 t ??DataTable45_1 +10037cd4 t ??DataTable45_2 +10037cd8 t ??DataTable45_3 +10037cdc t ??DataTable45_4 +10037ce0 t ??DataTable45_5 +10037ce4 t ??DataTable45_6 +10037ce8 t ??DataTable45_7 +10037cec t ??DataTable45_8 +10037cf0 t ??DataTable45_9 +10037cf4 t ??DataTable45_10 +10037cf8 t ??DataTable45_11 +10037cfc t ??DataTable45_12 +10037d00 t ??DataTable45_13 +10037d04 t ??DataTable45_14 +10037d08 t ??DataTable45_15 +10037d0c t ?_0 +10037d14 t ?_1 +10037d1c t ?_2 +10037d44 t ?_3 +10037d78 t ?_4 +10037da4 t ?_5 +10037dd4 t ?_6 +10037e08 t ?_7 +10037e38 t ?_8 +10037e78 t ?_12 +10037e80 t ?_13 +10037e88 t ?_14 +10037e90 t ?_15 +10037e98 t ?_16 +10037ea0 t ?_17 +10037eac t ?_18 +10037eb8 t ?_20 +10037ed0 t ?_22 +10037ee4 t ?_23 +10037eec t ?_24 +10037f04 t ?_25 +10037f0c t ?_26 +10037f24 t ?_27 +10037f2c t ?_28 +10037f60 t ?_29 +10037f68 t ?_30 +10037f74 t ?_31 +10037f84 t ?_32 +10037f94 t ?_33 +10037f9c t ?_34 +10037fbc t ?_35 +10037fc8 t ?_36 +10037ff0 t ?_37 +10038020 t ?_38 +10038040 t mark_ip_in_table +1003804e t ??CrossCallReturnLabel_1 +10038062 t ??mark_ip_in_table_0 +10038074 t ??mark_ip_in_table_2 +10038086 t ??mark_ip_in_table_3 +1003809c t ??mark_ip_in_table_4 +100380a4 t ??mark_ip_in_table_1 +100380b6 t .text_4 +100380b6 t add_msg_type +100380ce t .text_5 +100380ce t fill_one_option_content +100380ea t ??CrossCallReturnLabel_4 +100380ee t ??fill_one_option_content_1 +100380f2 t ??CrossCallReturnLabel_3 +100380f6 t ??fill_one_option_content_0 +100380fa t ??CrossCallReturnLabel_2 +100380fc t ??fill_one_option_content_2 +100380fe t .text_6 +100380fe t ?Subroutine1 +10038106 t .text_7 +10038106 t add_offer_options +1003816a t .text_8 +1003816a t dhcps_initialize_message +1003820c t .text_9 +1003820c t dhcps_send_offer +10038232 t ??CrossCallReturnLabel_9 +1003823c t ??dhcps_send_offer_0 +10038278 t ??dhcps_send_offer_1 +1003827a t ??dhcps_send_offer_2 +10038292 t ??CrossCallReturnLabel_0 +10038294 t ??dhcps_send_offer_4 +10038296 t ??dhcps_send_offer_5 +100382b2 t ??dhcps_send_offer_6 +100382c6 t ??CrossCallReturnLabel_8 +100382c8 t ??dhcps_send_offer_3 +100382d4 t ??dhcps_send_offer_8 +100382ec t ??CrossCallReturnLabel_10 +1003831c t ??dhcps_send_offer_7 +10038320 t ??CrossCallReturnLabel_7 +10038328 t .text_10 +10038328 t ?Subroutine4 +10038334 t .text_11 +10038334 t ?Subroutine3 +10038340 t .text_12 +10038340 t ?Subroutine0 +1003834c T dhcps_handle_state_machine_change +1003834c t .text_13 +10038364 t ??dhcps_handle_state_machine_change_0 +1003836a t ??dhcps_handle_state_machine_change_1 +10038376 t ??CrossCallReturnLabel_6 +10038380 t ??dhcps_handle_state_machine_change_6 +10038382 t ??dhcps_handle_state_machine_change_5 +1003838c t ??CrossCallReturnLabel_5 +10038392 t ??CrossCallReturnLabel_11 +10038398 t ??dhcps_handle_state_machine_change_8 +100383e6 t ??CrossCallReturnLabel_12 +100383ea t ??dhcps_handle_state_machine_change_9 +100383ee t ??dhcps_handle_state_machine_change_7 +100383f2 t ??dhcps_handle_state_machine_change_2 +100383f4 t ??dhcps_handle_state_machine_change_4 +100383f6 t ??dhcps_handle_state_machine_change_3 +100383fa t .text_14 +100383fa t ?Subroutine5 +10038406 t .text_15 +10038406 t ?Subroutine2 +10038412 t .text_16 +10038412 t dhcps_receive_udp_packet_handler +10038432 t ??dhcps_receive_udp_packet_handler_0 +10038450 t ??dhcps_receive_udp_packet_handler_2 +10038494 t ??dhcps_receive_udp_packet_handler_5 +1003849a t ??dhcps_receive_udp_packet_handler_4 +100384ae t ??dhcps_receive_udp_packet_handler_7 +100384bc t ??dhcps_receive_udp_packet_handler_6 +100384d0 t ??dhcps_receive_udp_packet_handler_8 +100384d8 t ??dhcps_receive_udp_packet_handler_9 +100384f4 t ??CrossCallReturnLabel_14 +100384fc t ??dhcps_receive_udp_packet_handler_10 +10038514 t ??CrossCallReturnLabel_13 +10038518 t ??dhcps_receive_udp_packet_handler_1 +10038524 t ??dhcps_receive_udp_packet_handler_3 +10038526 t ??dhcps_receive_udp_packet_handler_11 +1003852e t .text_17 +1003852e t ?Subroutine6 +10038540 T dhcps_init +10038540 t .text_19 +10038554 t ??dhcps_init_0 +100385a2 t ??dhcps_init_1 +100385f0 T dhcps_deinit +100385f0 t .text_20 +10038600 t ??dhcps_deinit_0 +1003860c t ??dhcps_deinit_1 +10038610 t ??DataTable14 +10038614 t ??DataTable14_1 +10038618 t ??DataTable14_2 +1003861c t ?_0 +10038644 t ?_1 +1003865c t ?_2 +10038690 t dhcp_magic_cookie +10038694 t dhcp_option_lease_time_one_day +10038698 t dhcp_option_interface_mtu_576 +1003869c t wifi_connect_local +100386b2 t ??wifi_connect_local_0 +100386ba t ??wifi_connect_local_1 +100386ee t ??wifi_connect_local_3 +100386f2 t ??CrossCallReturnLabel_25 +100386fa t ??wifi_connect_local_8 +100386fc t ??wifi_connect_local_9 +1003870a t ??wifi_connect_local_10 +1003870c t ??wifi_connect_local_2 +10038710 t ??wifi_connect_local_4 +10038716 t ??CrossCallReturnLabel_30 +1003872a t ??CrossCallReturnLabel_27 +1003872e t ??wifi_connect_local_5 +10038732 t ??CrossCallReturnLabel_32 +1003873a t ??CrossCallReturnLabel_21 +1003873c t ??wifi_connect_local_6 +10038740 t ??CrossCallReturnLabel_31 +10038748 t ??CrossCallReturnLabel_23 +10038750 t ??wifi_connect_local_11 +10038762 t ??wifi_connect_local_7 +10038770 t .text_7 +10038770 t ?Subroutine12 +10038772 t ??Subroutine12_0 +1003877a t .text_8 +1003877a t ?Subroutine11 +1003877c t ??Subroutine11_0 +10038786 t .text_9 +10038786 t wifi_connect_bssid_local +100387a4 t ??wifi_connect_bssid_local_0 +100387ae t ??wifi_connect_bssid_local_1 +100387e2 t ??wifi_connect_bssid_local_3 +100387e6 t ??CrossCallReturnLabel_26 +100387e8 t ??wifi_connect_bssid_local_8 +100387ee t ??wifi_connect_bssid_local_9 +100387f0 t ??wifi_connect_bssid_local_10 +1003881c t ??wifi_connect_bssid_local_12 +10038826 t ??wifi_connect_bssid_local_11 +10038828 t ??wifi_connect_bssid_local_2 +1003882c t ??wifi_connect_bssid_local_4 +10038832 t ??CrossCallReturnLabel_33 +1003884c t ??CrossCallReturnLabel_28 +10038852 t ??wifi_connect_bssid_local_5 +10038856 t ??CrossCallReturnLabel_35 +1003885e t ??CrossCallReturnLabel_22 +10038860 t ??wifi_connect_bssid_local_6 +10038864 t ??CrossCallReturnLabel_34 +1003886c t ??CrossCallReturnLabel_24 +10038874 t ??wifi_connect_bssid_local_13 +10038888 t ??wifi_connect_bssid_local_7 +10038898 t ?_1 +100388cc t .text_11 +100388cc t ?Subroutine13 +100388ce t ??Subroutine13_0 +100388d6 t .text_12 +100388d6 t ?Subroutine10 +100388e8 t .text_13 +100388e8 t ?Subroutine9 +100388fc t .text_14 +100388fc t ?Subroutine8 +10038910 t .text_15 +10038910 t wifi_no_network_hdl +1003891c t ??wifi_no_network_hdl_0 +1003891e t .text_16 +1003891e t wifi_connected_hdl +10038940 t ??wifi_connected_hdl_1 +1003894c t ??wifi_connected_hdl_0 +1003894e t .text_17 +1003894e t wifi_handshake_done_hdl +10038968 t .text_18 +10038968 t wifi_disconn_hdl +1003897e t ??wifi_disconn_hdl_3 +10038980 t ??wifi_disconn_hdl_4 +1003898c t ??wifi_disconn_hdl_5 +1003898e t ??wifi_disconn_hdl_1 +100389ac t ??wifi_disconn_hdl_6 +100389b8 t ??wifi_disconn_hdl_2 +100389bc t ??wifi_disconn_hdl_8 +100389be t ??wifi_disconn_hdl_7 +100389c2 t ??wifi_disconn_hdl_9 +100389c6 t ??wifi_disconn_hdl_0 +100389d4 t ?_3 +10038a14 T restore_wifi_info_to_flash +10038a14 t .text_20 +10038a4c t ??restore_wifi_info_to_flash_1 +10038a5a t ??restore_wifi_info_to_flash_2 +10038a90 t ??restore_wifi_info_to_flash_3 +10038a94 t ??CrossCallReturnLabel_37 +10038a98 t ??CrossCallReturnLabel_39 +10038a9a t ??restore_wifi_info_to_flash_4 +10038aaa t ??CrossCallReturnLabel_36 +10038aae t ??CrossCallReturnLabel_38 +10038ab8 t ??restore_wifi_info_to_flash_5 +10038b08 t ??restore_wifi_info_to_flash_0 +10038b10 t ?_4 +10038b14 t ??__func__ +10038b30 t ?_5 +10038b5c t .text_24 +10038b5c t ?Subroutine15 +10038b66 t .text_25 +10038b66 t ?Subroutine14 +10038b70 T wifi_connect +10038b70 t .text_26 +10038be6 t ??wifi_connect_1 +10038c04 t ??wifi_connect_2 +10038c08 t ??wifi_connect_4 +10038c24 t ??wifi_connect_7 +10038c3a t ??wifi_connect_5 +10038c76 t ??wifi_connect_9 +10038c8a t ??wifi_connect_8 +10038c8e t ??wifi_connect_3 +10038c9c t ??wifi_connect_0 +10038ca2 t ??wifi_connect_11 +10038cb2 t ??wifi_connect_12 +10038cb8 t ??wifi_connect_10 +10038cc6 t ??CrossCallReturnLabel_16 +10038cd0 t ??wifi_connect_14 +10038cd4 t ??wifi_connect_13 +10038cd6 t ??wifi_connect_15 +10038cf8 t ??CrossCallReturnLabel_43 +10038d16 t ??CrossCallReturnLabel_41 +10038d26 t ??CrossCallReturnLabel_10 +10038d2a t ??CrossCallReturnLabel_3 +10038d36 t ??wifi_connect_17 +10038d44 t ??CrossCallReturnLabel_9 +10038d48 t ??CrossCallReturnLabel_2 +10038d56 t ??wifi_connect_16 +10038d5a t ??wifi_connect_18 +10038d78 t ??wifi_connect_6 +10038d80 t ?_7 +10038d98 t ?_8 +10038dd0 t .text_29 +10038dd0 t ?Subroutine4 +10038dd2 t ??Subroutine4_0 +10038dd8 T wifi_connect_bssid +10038dd8 t .text_30 +10038e1a t ??wifi_connect_bssid_1 +10038e56 t ??wifi_connect_bssid_2 +10038e6a t ??wifi_connect_bssid_3 +10038e6e t ??wifi_connect_bssid_4 +10038e7c t ??wifi_connect_bssid_0 +10038e82 t ??wifi_connect_bssid_7 +10038e8a t ??wifi_connect_bssid_6 +10038e98 t ??CrossCallReturnLabel_15 +10038ea2 t ??wifi_connect_bssid_9 +10038ea6 t ??wifi_connect_bssid_8 +10038ea8 t ??wifi_connect_bssid_10 +10038eca t ??CrossCallReturnLabel_42 +10038ee8 t ??CrossCallReturnLabel_40 +10038ef8 t ??CrossCallReturnLabel_8 +10038efc t ??CrossCallReturnLabel_1 +10038f06 t ??wifi_connect_bssid_12 +10038f14 t ??CrossCallReturnLabel_7 +10038f18 t ??CrossCallReturnLabel_0 +10038f26 t ??wifi_connect_bssid_11 +10038f2a t ??wifi_connect_bssid_13 +10038f48 t ??wifi_connect_bssid_5 +10038f4c t ?_9 +10038f68 t .text_32 +10038f68 t ?Subroutine17 +10038f72 t .text_33 +10038f72 t ?Subroutine16 +10038f7e t .text_34 +10038f7e t ?Subroutine6 +10038f88 t .text_35 +10038f88 t ?Subroutine3 +10038f90 T wifi_disconnect +10038f90 t .text_36 +10038fb8 t ??wifi_disconnect_0 +10038fbc T wifi_is_up +10038fbc t .text_37 +10038fd2 T wifi_is_ready_to_transceive +10038fd2 t .text_38 +10038fe4 t ??wifi_is_ready_to_transceive_0 +1003900a t ??wifi_is_ready_to_transceive_7 +10039010 t ??wifi_is_ready_to_transceive_6 +1003901c t ??wifi_is_ready_to_transceive_2 +10039020 t ??wifi_is_ready_to_transceive_3 +10039024 t ??wifi_is_ready_to_transceive_5 +1003902a t ??wifi_is_ready_to_transceive_4 +1003902e t ??wifi_is_ready_to_transceive_1 +10039030 T wifi_get_associated_client_list +10039030 t .text_43 +10039036 t ??CrossCallReturnLabel_17 +1003904c t ??CrossCallReturnLabel_12 +10039068 t .text_44 +10039068 t ?Subroutine5 +10039070 t .text_47 +10039070 t ?Subroutine2 +10039076 T wifi_get_rssi +10039076 t .text_48 +10039080 T wifi_set_channel +10039080 t .text_49 +1003908a T wifi_on +1003908a t .text_55 +10039092 t ??CrossCallReturnLabel_19 +100390b4 t ??wifi_on_0 +100390c0 t ??wifi_on_3 +100390d0 t ??wifi_on_2 +100390d8 t ??wifi_on_6 +100390e0 t ??wifi_on_5 +100390e4 t ??wifi_on_7 +100390f2 t ??wifi_on_1 +100390f6 t ??wifi_on_4 +100390fc t ??wifi_on_8 +10039104 t ??wifi_on_9 +10039110 t .text_56 +10039110 t ?Subroutine7 +10039118 T wifi_off +10039118 t .text_57 +10039132 t ??wifi_off_0 +1003914c t ??wifi_off_2 +10039156 t ??wifi_off_1 +1003916c t ??wifi_off_3 +10039174 t ??wifi_off_4 +10039182 t .text_58 +10039182 t wifi_ap_sta_assoc_hdl +10039184 t .text_59 +10039184 t wifi_ap_sta_disassoc_hdl +10039188 t ??DataTable86 +1003918c t ??DataTable86_1 +10039190 T wifi_start_ap +10039190 t .text_63 +10039198 t ??CrossCallReturnLabel_20 +100391be t ??wifi_start_ap_0 +10039214 t ??wifi_start_ap_4 +1003923a t ??wifi_start_ap_6 +10039248 t ??wifi_start_ap_2 +10039258 t ??wifi_start_ap_1 +10039260 t ??wifi_start_ap_3 +10039266 t ??wifi_start_ap_5 +1003926c t ??DataTable87 +10039270 t .text_70 +10039270 t wifi_scan_each_report_hdl +10039280 t ??wifi_scan_each_report_hdl_1 +10039282 t ??wifi_scan_each_report_hdl_0 +100392e4 t ??wifi_scan_each_report_hdl_2 +10039324 t ??wifi_scan_each_report_hdl_3 +10039334 t ??wifi_scan_each_report_hdl_5 +1003933c t ??wifi_scan_each_report_hdl_7 +1003933e t ??wifi_scan_each_report_hdl_6 +10039356 t ??wifi_scan_each_report_hdl_8 +1003935a t ??wifi_scan_each_report_hdl_10 +10039368 t ??wifi_scan_each_report_hdl_9 +10039374 t ??wifi_scan_each_report_hdl_11 +10039380 t ??wifi_scan_each_report_hdl_12 +1003938e t ??wifi_scan_each_report_hdl_4 +10039390 t .text_71 +10039390 t wifi_scan_done_hdl +1003939c t ??wifi_scan_done_hdl_1 +100393ba t ??wifi_scan_done_hdl_0 +100393d2 t ??CrossCallReturnLabel_6 +100393d8 t ??CrossCallReturnLabel_5 +100393f4 T wifi_scan +100393f4 t .text_72 +10039422 t ??wifi_scan_1 +10039424 t ??wifi_scan_0 +1003944c t ??DataTable90 +10039450 t ??DataTable90_1 +10039454 t ??DataTable91 +10039458 t ??DataTable91_1 +1003945c t ??DataTable91_2 +10039460 t ??DataTable91_3 +10039464 T wifi_scan_networks +10039464 t .text_80 +10039474 t ??wifi_scan_networks_1 +10039484 t ??wifi_scan_networks_2 +10039498 t ??wifi_scan_networks_0 +100394e6 t ??wifi_scan_networks_3 +100394ec t ??CrossCallReturnLabel_4 +100394f0 t ??wifi_scan_networks_4 +100394f4 t ??wifi_scan_networks_5 +100394f8 t ??DataTable92 +100394fc T wifi_set_pscan_chan +100394fc t .text_82 +1003950c t ??wifi_set_pscan_chan_0 +1003950e T wifi_get_setting +1003950e t .text_83 +1003958c t ??wifi_get_setting_2 +10039590 t ??wifi_get_setting_1 +10039594 t ??wifi_get_setting_3 +10039596 t ??wifi_get_setting_0 +10039598 t ??wifi_get_setting_4 +100395b4 t ??wifi_get_setting_5 +100395b8 t ??DataTable93 +100395bc t ??DataTable93_2 +100395c0 t ??DataTable93_3 +100395c4 t ??DataTable93_4 +100395c8 T wifi_show_setting +100395c8 t .text_90 +100395f2 t ??wifi_show_setting_0 +100395f6 t ??wifi_show_setting_1 +10039626 t ??wifi_show_setting_2 +1003962c t ??wifi_show_setting_3 +10039642 t ??wifi_show_setting_4 +10039648 t ??wifi_show_setting_5 +1003964e t ??wifi_show_setting_6 +10039652 t ??wifi_show_setting_7 +10039656 t ??wifi_show_setting_8 +10039664 t .text_91 +10039664 t ?Subroutine1 +1003966c t .text_93 +1003966c t ??wifi_set_network_mode_0 +1003966c t ?Subroutine0 +10039672 T wifi_set_wps_phase +10039672 t .text_94 +10039676 T wifi_set_promisc +10039676 t .text_95 +1003967a T wifi_enter_promisc_mode +1003967a t .text_96 +10039692 t ??CrossCallReturnLabel_47 +1003969a t ??wifi_enter_promisc_mode_0 +100396b8 t ??CrossCallReturnLabel_46 +100396c8 t ??wifi_enter_promisc_mode_2 +100396d8 t ??wifi_enter_promisc_mode_1 +100396dc t ??DataTable94 +100396e0 t ??DataTable94_1 +100396e4 t ??DataTable94_2 +100396e8 T wifi_restart_ap +100396e8 t .text_100 +10039704 t ??wifi_restart_ap_0 +10039722 t ??CrossCallReturnLabel_45 +10039726 t ??wifi_restart_ap_1 +10039746 t ??CrossCallReturnLabel_44 +10039748 t ??wifi_restart_ap_2 +10039772 t ??wifi_restart_ap_3 +100397c6 t ??wifi_restart_ap_5 +100397d2 t ??wifi_restart_ap_4 +100397d8 t .text_101 +100397d8 t ?Subroutine18 +100397e0 t ??DataTable97 +100397e4 t ??DataTable97_1 +100397e8 t ??DataTable97_2 +100397ec t ??DataTable97_3 +100397f0 t ??DataTable97_4 +100397f4 t ??DataTable97_5 +100397f8 t ??DataTable97_6 +100397fc t ??DataTable97_7 +10039800 t ??DataTable97_8 +10039804 t ??DataTable97_9 +10039808 t ??DataTable97_10 +1003980c t ??DataTable97_11 +10039810 T wifi_init_packet_filter +10039810 t .text_125 +10039814 T wifi_add_packet_filter +10039814 t .text_126 +10039818 T wifi_enable_packet_filter +10039818 t .text_127 +1003981c T wifi_disable_packet_filter +1003981c t .text_128 +10039820 T wifi_remove_packet_filter +10039820 t .text_129 +10039824 t ?_0 +1003982c t ?_10 +10039834 t ?_11 +10039864 t ?_14 +1003986c t ?_15 +10039880 t ?_24 +1003989c t ?_25 +100398b4 t ?_26 +100398c8 t ?_27 +100398e4 t ?_28 +100398fc t ?_29 +10039918 t ?_30 +10039930 t ?_31 +10039950 t ?_32 +10039980 t ?_33 +100399ac t ?_49 +100399dc t ?_50 +100399f4 t ?_51 +10039a18 t ?_52 +10039a2c t ?_53 +10039a44 t ?_54 +10039a5c t ?_55 +10039a70 t ?_56 +10039a84 t ?_57 +10039a9c t ?_58 +10039ab0 t ?_59 +10039ac4 t ?_60 +10039adc t ?_61 +10039af0 t ?_62 +10039b08 t ?_63 +10039b1c t ?_64 +10039b38 t ?_65 +10039b48 t ?_66 +10039b60 t ?_67 +10039b74 t ?_68 +10039b88 W user_wifi_beacon_hdl +10039b8a T LwIP_Init +10039b8a t .text_4 +10039bb0 t ??LwIP_Init_1 +10039bb2 t ??LwIP_Init_0 +10039bba t ??LwIP_Init_2 +10039bc4 t ??LwIP_Init_3 +10039bfa t ??LwIP_Init_4 +10039c0e T LwIP_DHCP +10039c0e t .text_5 +10039c2e t ??LwIP_DHCP_0 +10039c40 t ??LwIP_DHCP_1 +10039c44 t ??CrossCallReturnLabel_4 +10039c4c t ??LwIP_DHCP_5 +10039c6a t ??LwIP_DHCP_2 +10039c98 t ??LwIP_DHCP_6 +10039caa t ??CrossCallReturnLabel_0 +10039cce t ??LwIP_DHCP_3 +10039cd2 t ??CrossCallReturnLabel_3 +10039ce4 t ??LwIP_DHCP_4 +10039ce8 t ??CrossCallReturnLabel_2 +10039cf8 t ??LwIP_DHCP_7 +10039cfc t .text_6 +10039cfc t ?Subroutine1 +10039d04 T LwIP_GetMAC +10039d04 t .text_7 +10039d08 T LwIP_GetIP +10039d08 t .text_8 +10039d0c T LwIP_GetGW +10039d0c t .text_9 +10039d10 T LwIP_UseStaticIP +10039d10 t .text_12 +10039d2a t ??LwIP_UseStaticIP_0 +10039d32 t ??LwIP_UseStaticIP_1 +10039d3e t .text_15 +10039d3e t ?Subroutine0 +10039d54 t ??DataTable11 +10039d58 t ??DataTable11_1 +10039d5c t ??DataTable11_2 +10039d60 t ??DataTable11_3 +10039d64 t ??DataTable11_4 +10039d68 t ??DataTable11_5 +10039d6c t ??DataTable11_6 +10039d70 t ?_0 +10039d8c t ?_1 +10039d9c t ?_2 +10039dc0 t ?_3 +10039dd8 t ?_4 +10039df0 T ping_test +10039e22 t ??ping_test_1 +10039e30 t ??ping_test_2 +10039e44 t ??ping_test_0 +10039e52 t ??ping_test_3 +10039e8e t ??ping_test_6 +10039e96 t ??ping_test_5 +10039f52 t ??ping_test_4 +10039f5a t ??ping_test_7 +10039f60 T do_ping_call +10039f60 t .text_4 +10039f8c t ??DataTable11 +10039f90 t ??__FUNCTION__ +10039f9c t ?_0 +10039fc4 t ?_1 +10039ff4 t ?_2 +1003a01c T promisc_init_packet_filter +1003a022 t ??promisc_init_packet_filter_0 +1003a046 T promisc_add_packet_filter +1003a046 t .text_6 +1003a052 t ??promisc_add_packet_filter_0 +1003a064 t ??promisc_add_packet_filter_1 +1003a06e t ??promisc_add_packet_filter_2 +1003a0a4 T promisc_enable_packet_filter +1003a0a4 t .text_7 +1003a0ac t ??promisc_enable_packet_filter_0 +1003a0be t ??promisc_enable_packet_filter_1 +1003a0c4 t ??promisc_enable_packet_filter_2 +1003a0d4 T promisc_disable_packet_filter +1003a0d4 t .text_8 +1003a0dc t ??promisc_disable_packet_filter_0 +1003a0ee t ??promisc_disable_packet_filter_1 +1003a0f4 t ??promisc_disable_packet_filter_2 +1003a104 t .text_9 +1003a104 t ?Subroutine1 +1003a10a t .text_10 +1003a10a t ?Subroutine0 +1003a110 T promisc_remove_packet_filter +1003a110 t .text_11 +1003a118 t ??promisc_remove_packet_filter_0 +1003a12a t ??promisc_remove_packet_filter_1 +1003a134 t ??promisc_remove_packet_filter_2 +1003a152 t ??promisc_remove_packet_filter_3 +1003a15e t ??promisc_remove_packet_filter_4 +1003a162 t .text_12 +1003a162 t promisc_callback +1003a168 t ??CrossCallReturnLabel_3 +1003a1a0 t ??promisc_callback_0 +1003a1a2 T retrieve_frame +1003a1a2 t .text_13 +1003a1c0 t ??retrieve_frame_0 +1003a1ca t .text_14 +1003a1ca t promisc_test +1003a1d2 t ??CrossCallReturnLabel_0 +1003a1f2 t ??promisc_test_0 +1003a1fe t ??CrossCallReturnLabel_5 +1003a206 t ??promisc_test_2 +1003a20e t ??promisc_test_3 +1003a214 t ??CrossCallReturnLabel_9 +1003a222 t ??promisc_test_4 +1003a22a t ??CrossCallReturnLabel_7 +1003a23e t ??promisc_test_1 +1003a260 t ??promisc_test_5 +1003a268 t .text_15 +1003a268 t promisc_callback_all +1003a26e t ??CrossCallReturnLabel_2 +1003a2ac t ??promisc_callback_all_0 +1003a2ae t .text_16 +1003a2ae t ?Subroutine5 +1003a2b8 t .text_17 +1003a2b8 t ?Subroutine2 +1003a2c2 t .text_18 +1003a2c2 t promisc_test_all +1003a2ca t ??CrossCallReturnLabel_1 +1003a2e8 t ??promisc_test_all_0 +1003a2f4 t ??CrossCallReturnLabel_4 +1003a2fc t ??promisc_test_all_2 +1003a30c t ??promisc_test_all_3 +1003a312 t ??CrossCallReturnLabel_8 +1003a320 t ??promisc_test_all_4 +1003a328 t ??CrossCallReturnLabel_6 +1003a33e t ??promisc_test_all_1 +1003a362 t ??promisc_test_all_5 +1003a368 t .text_19 +1003a368 t ?Subroutine3 +1003a374 t ??Subroutine3_1 +1003a378 t ??Subroutine3_0 +1003a384 t .text_20 +1003a384 t ?Subroutine7 +1003a386 t ??Subroutine7_0 +1003a38c t .text_21 +1003a38c t ?Subroutine6 +1003a396 t .text_22 +1003a396 t ?Subroutine4 +1003a3a4 t ??DataTable18 +1003a3a8 t ??DataTable18_1 +1003a3ac t ??DataTable18_2 +1003a3b0 t ??DataTable18_3 +1003a3b4 t ??DataTable18_4 +1003a3b8 t ??DataTable18_5 +1003a3bc T cmd_promisc +1003a3bc t .text_29 +1003a3dc t ??cmd_promisc_0 +1003a402 t ??cmd_promisc_1 +1003a410 t ?_0 +1003a42c t ?_1 +1003a434 t ?_2 +1003a43c t ?_3 +1003a444 t ?_4 +1003a450 t ?_5 +1003a460 t ?_7 +1003a46c t ?_8 +1003a494 T SC_set_ack_content +1003a4a2 t ??CrossCallReturnLabel_4 +1003a4de T SC_send_simple_config_ack +1003a4de t .text_5 +1003a526 t ??SC_send_simple_config_ack_1 +1003a528 t ??SC_send_simple_config_ack_2 +1003a552 t ??SC_send_simple_config_ack_0 +1003a556 t .text_6 +1003a556 t get_connection_info_from_profile +1003a58a t ??get_connection_info_from_profile_1 +1003a596 t ??get_connection_info_from_profile_0 +1003a59e t ??get_connection_info_from_profile_3 +1003a5aa t ??get_connection_info_from_profile_2 +1003a5ce t ??get_connection_info_from_profile_5 +1003a600 t ??get_connection_info_from_profile_8 +1003a618 t ??CrossCallReturnLabel_8 +1003a626 t ??get_connection_info_from_profile_4 +1003a62a t ??CrossCallReturnLabel_2 +1003a630 t ??CrossCallReturnLabel_1 +1003a638 t ??CrossCallReturnLabel_0 +1003a644 t ??get_connection_info_from_profile_10 +1003a652 t ??get_connection_info_from_profile_7 +1003a694 t ??get_connection_info_from_profile_12 +1003a6ac t ??CrossCallReturnLabel_7 +1003a6b8 t ??get_connection_info_from_profile_9 +1003a6ba t ??get_connection_info_from_profile_6 +1003a6f6 t ??get_connection_info_from_profile_11 +1003a6fa t .text_7 +1003a6fa t ?Subroutine2 +1003a704 t .text_8 +1003a704 t ?Subroutine0 +1003a70c T SC_connect_to_AP +1003a70c t .text_9 +1003a726 t ??SC_connect_to_AP_0 +1003a746 t ??SC_connect_to_AP_1 +1003a75a t ??SC_connect_to_AP_2 +1003a75e t ??SC_connect_to_AP_3 +1003a764 t ??SC_connect_to_AP_4 +1003a772 t ??SC_connect_to_AP_7 +1003a774 t ??SC_connect_to_AP_5 +1003a790 t ??SC_connect_to_AP_8 +1003a7ec t ??SC_connect_to_AP_9 +1003a7f2 t ??SC_connect_to_AP_6 +1003a7f6 T simple_config_callback +1003a7f6 t .text_10 +1003a81c t ??simple_config_callback_0 +1003a824 T init_test_data +1003a824 t .text_11 +1003a858 t ??init_test_data_0 +1003a86a t ??init_test_data_1 +1003a872 t ??CrossCallReturnLabel_3 +1003a886 t ??CrossCallReturnLabel_6 +1003a890 t ??init_test_data_5 +1003a894 t ??init_test_data_2 +1003a89c t ??init_test_data_3 +1003a8a2 t ??init_test_data_6 +1003a8a6 t ??CrossCallReturnLabel_5 +1003a8b0 t ??init_test_data_4 +1003a8b4 t ??init_test_data_7 +1003a8be t .text_12 +1003a8be t ?Subroutine1 +1003a8c2 t ??Subroutine1_0 +1003a8c8 T deinit_test_data +1003a8c8 t .text_13 +1003a8dc t ??deinit_test_data_0 +1003a8e8 t ??deinit_test_data_1 +1003a8ea T simple_config_test +1003a8ea t .text_14 +1003a91e t ??simple_config_test_1 +1003a934 t ??simple_config_test_0 +1003a974 t ??simple_config_test_3 +1003a990 t ??simple_config_test_4 +1003a99e t ??simple_config_test_5 +1003a9d4 t ??simple_config_test_7 +1003a9e6 t ??simple_config_test_2 +1003a9e8 t ??simple_config_test_6 +1003aa0a t ??simple_config_test_8 +1003aa0c t ??simple_config_test_10 +1003aa12 t ??simple_config_test_9 +1003aa16 T filter_add_enable +1003aa16 t .text_15 +1003aa5a T remove_filter +1003aa5a t .text_16 +1003aa6c T print_simple_config_result +1003aa6c t .text_17 +1003aa80 t ??print_simple_config_result_0 +1003aa88 t ??print_simple_config_result_2 +1003aa8e t ??print_simple_config_result_4 +1003aa94 t ??print_simple_config_result_5 +1003aa9a t ??print_simple_config_result_6 +1003aaa0 t ??print_simple_config_result_7 +1003aaa6 t ??print_simple_config_result_8 +1003aaac t ??print_simple_config_result_9 +1003aab2 t ??print_simple_config_result_1 +1003aab6 t ??print_simple_config_result_3 +1003aac0 t ??DataTable45 +1003aac4 t ??DataTable45_1 +1003aac8 t ??DataTable45_2 +1003aacc t ??DataTable45_3 +1003aad0 t ??DataTable45_4 +1003aad4 t ??DataTable45_5 +1003aad8 t ??DataTable45_6 +1003aadc t ??DataTable45_7 +1003aae0 t ??DataTable45_8 +1003aae4 T cmd_simple_config +1003aae4 t .text_27 +1003aaf6 t ??cmd_simple_config_0 +1003aafc t ??cmd_simple_config_1 +1003ab1a t ??cmd_simple_config_2 +1003ab1c t ?_0 +1003ab24 t ?_1 +1003ab58 t ?_2 +1003ab88 t ?_3 +1003abbc t ?_4 +1003abe8 t ?_5 +1003ac14 t ?_6 +1003ac40 t ?_7 +1003ac58 t ?_8 +1003ac90 t ?_9 +1003aca8 t ?_10 +1003acc4 t ?_11 +1003acd8 t ?_12 +1003acf0 t ?_13 +1003ad08 t ?_14 +1003ad34 t ?_16 +1003ad5c t ?_17 +1003ad88 t ?_18 +1003adac t ?_19 +1003adcc t ?_20 +1003ade0 t ?_22 +1003ae10 t ?_23 +1003ae34 t ?_24 +1003ae50 t ?_25 +1003ae54 t ?_26 +1003ae58 t ?_28 +1003ae98 t ?_29 +1003aedc t ?_30 +1003af0c t ?_31 +1003af2c t ?_32 +1003af5c t ?_33 +1003af88 t ?_34 +1003afa0 t ?_35 +1003afc4 t ?_36 +1003afd4 T wps_check_and_show_connection_info +1003aff8 t .text_4 +1003aff8 t wps_scan_result_handler +1003b03a t ??CrossCallReturnLabel_0 +1003b040 t ??wps_scan_result_handler_2 +1003b05a t ??CrossCallReturnLabel_1 +1003b05e t ??wps_scan_result_handler_3 +1003b064 t ??wps_scan_result_handler_0 +1003b074 t ??wps_scan_result_handler_1 +1003b078 t .text_5 +1003b078 t ?Subroutine0 +1003b084 T wps_start +1003b084 t .text_6 +1003b0be t ??wps_start_1 +1003b0c2 t ??wps_start_3 +1003b10a t ??wps_start_0 +1003b124 t ??wps_start_7 +1003b12e t ??wps_start_8 +1003b138 t ??wps_start_5 +1003b148 t ??wps_start_6 +1003b14c t ??wps_start_10 +1003b160 t ??wps_start_4 +1003b164 t ??wps_start_12 +1003b16a t ??wps_start_2 +1003b17a t ??wps_start_11 +1003b186 t ??wps_start_14 +1003b192 t ??wps_start_9 +1003b198 t ??wps_start_15 +1003b1c4 t ??wps_start_18 +1003b1c6 t ??wps_start_17 +1003b1f2 t ??wps_start_19 +1003b228 t ??CrossCallReturnLabel_2 +1003b25e t ??wps_start_23 +1003b26a t ??wps_start_22 +1003b274 t ??wps_start_25 +1003b276 t ??wps_start_24 +1003b2b6 t ??CrossCallReturnLabel_3 +1003b2e0 t ??wps_start_27 +1003b2e2 t ??wps_start_26 +1003b31a t ??wps_start_28 +1003b328 t ??wps_start_21 +1003b32c t ??wps_start_20 +1003b336 t ??wps_start_29 +1003b342 t ??wps_start_30 +1003b352 t ??wps_start_13 +1003b354 t ??wps_start_16 +1003b35a t .text_7 +1003b35a t ?Subroutine1 +1003b364 T wps_judge_staion_disconnect +1003b364 t .text_8 +1003b396 t ??wps_judge_staion_disconnect_0 +1003b3a6 t ??wps_judge_staion_disconnect_1 +1003b3aa T cmd_wps +1003b3aa t .text_9 +1003b3f2 t ??cmd_wps_0 +1003b3f4 t ??cmd_wps_2 +1003b404 t ??cmd_wps_4 +1003b40a t ??cmd_wps_3 +1003b41c t ??cmd_wps_5 +1003b422 t ??cmd_wps_1 +1003b43e t ??cmd_wps_6 +1003b444 t ??DataTable38 +1003b448 t ??DataTable38_1 +1003b44c t ??DataTable38_2 +1003b450 t ??DataTable38_3 +1003b454 t ??DataTable38_4 +1003b458 t ??DataTable38_5 +1003b45c t ??DataTable38_6 +1003b460 t ??DataTable38_7 +1003b464 t ?_0 +1003b46c t ?_1 +1003b488 t ?_2 +1003b4a0 t ?_3 +1003b4bc t ?_4 +1003b4e4 t ?_5 +1003b510 t ?_6 +1003b540 t ?_7 +1003b560 t ?_8 +1003b57c t ?_9 +1003b59c t ?_10 +1003b5d8 t ?_11 +1003b5f0 t ?_12 +1003b604 t ?_13 +1003b61c t ?_14 +1003b634 t ?_15 +1003b65c t ?_16 +1003b688 t ?_17 +1003b69c t ?_19 +1003b6b8 t ?_20 +1003b6d4 t ?_22 +1003b708 t ?_23 +1003b730 t ?_24 +1003b750 t ?_25 +1003b780 t ?_26 +1003b794 t ?_27 +1003b7a8 t ?_29 +1003b7b0 t ?_30 +1003b7d8 t ?_31 +1003b80c t ?_32 +1003b82c t ?_34 +1003b844 t ?_35 +1003b874 T ota_platform_reset +1003b896 t ??ota_platform_reset_0 +1003b8a0 t .text_5 +1003b8a0 t update_ota_local_task +1003b8ec t ??update_ota_local_task_0 +1003b904 t ??update_ota_local_task_2 +1003b930 t ??update_ota_local_task_4 +1003b944 t ??CrossCallReturnLabel_6 +1003b956 t ??CrossCallReturnLabel_5 +1003b95e t ??CrossCallReturnLabel_4 +1003b976 t ??update_ota_local_task_5 +1003b988 t ??update_ota_local_task_6 +1003b992 t ??CrossCallReturnLabel_3 +1003b9a2 t ??update_ota_local_task_7 +1003b9a6 t ??update_ota_local_task_9 +1003b9b2 t ??update_ota_local_task_8 +1003b9c2 t ??update_ota_local_task_10 +1003ba0c t ??update_ota_local_task_12 +1003ba32 t ??update_ota_local_task_14 +1003ba46 t ??update_ota_local_task_13 +1003ba4c t ??update_ota_local_task_15 +1003ba6a t ??update_ota_local_task_17 +1003baa8 t ??update_ota_local_task_19 +1003babc t ??CrossCallReturnLabel_2 +1003bb0c t ??CrossCallReturnLabel_1 +1003bb18 t ??CrossCallReturnLabel_0 +1003bb38 t ??update_ota_local_task_11 +1003bb3e t ??update_ota_local_task_1 +1003bb52 t ??update_ota_local_task_20 +1003bb76 t ??update_ota_local_task_21 +1003bb82 t ??update_ota_local_task_18 +1003bb8a t ??update_ota_local_task_3 +1003bb90 t ??update_ota_local_task_22 +1003bba6 t ??update_ota_local_task_16 +1003bbaa t ??update_ota_local_task_23 +1003bbb0 t ??update_ota_local_task_25 +1003bbbc t ??update_ota_local_task_24 +1003bbc2 t .text_6 +1003bbc2 t ?Subroutine0 +1003bbc8 T update_ota_local +1003bbc8 t .text_7 +1003bbe4 t ??update_ota_local_0 +1003bbfe t ??update_ota_local_2 +1003bc32 t ??update_ota_local_1 +1003bc36 t ??update_ota_local_4 +1003bc38 t ??update_ota_local_3 +1003bc3c t ??DataTable36 +1003bc40 t ??DataTable36_1 +1003bc44 t ??DataTable36_2 +1003bc48 t ??DataTable36_3 +1003bc4c t ??DataTable36_4 +1003bc50 t ??DataTable36_5 +1003bc54 t ??DataTable36_6 +1003bc58 t ??DataTable36_7 +1003bc5c t ??DataTable36_8 +1003bc60 T cmd_update +1003bc60 t .text_17 +1003bc78 t ??cmd_update_0 +1003bc88 t ??__FUNCTION__ +1003bca0 t ?_0 +1003bcc0 t ?_1 +1003bcdc t ?_2 +1003bcf8 t ?_3 +1003bd14 t ?_4 +1003bd34 t ?_5 +1003bd58 t ?_6 +1003bd6c t ?_7 +1003bda0 t ?_8 +1003bdbc t ?_9 +1003bddc t ?_10 +1003be04 t ?_11 +1003be28 t ?_12 +1003be40 t ?_13 +1003be60 t ?_14 +1003be74 t ?_15 +1003be8c t ?_17 +1003bea8 t ?_18 +1003bec4 t ?_19 +1003bef0 t ?_20 +1003bf18 t ?_21 +1003bf34 t ?_22 +1003bf5c t ?_23 +1003bf78 t ?_24 +1003bf90 t ?_25 +1003bfa8 t ??__FUNCTION___1 +1003bfbc t ?_26 +1003bfdc t ?_27 +1003bffc t ?_28 +1003c008 t ?_29 +1003c02c t ??__FUNCTION___2 +1003c038 t ?_30 +1003c058 T _wlan_init_done_callback +1003c088 T Ai_WS2811_sendByte +1003c088 t .text_8 +1003c08c t ??Ai_WS2811_sendByte_0 +1003c0a6 t ??Ai_WS2811_sendByte_1 +1003c0ba t ??Ai_WS2811_sendByte_2 +1003c0cc T Ai_WS2811_send +1003c0cc t .text_9 +1003c0e4 T Ai_WS2811_setColor +1003c0e4 t .text_10 +1003c10a T sendLEDs +1003c10a t .text_11 +1003c112 t ??sendLEDs_0 +1003c122 T vTaskFunction +1003c122 t .text_12 +1003c13c t ??vTaskFunction_1 +1003c152 t ??vTaskFunction_2 +1003c172 t ??vTaskFunction_4 +1003c17a t ??vTaskFunction_0 +1003c18c t ??vTaskFunction_6 +1003c190 t ??vTaskFunction_7 +1003c1a2 t ??vTaskFunction_5 +1003c1ae t ??vTaskFunction_3 +1003c1be t ??CrossCallReturnLabel_1 +1003c1c4 t ??CrossCallReturnLabel_0 +1003c1d0 t .text_13 +1003c1d0 t ?Subroutine0 +1003c1da T _init +1003c1da t .text_14 +1003c230 t ??DataTable15 +1003c234 t ??DataTable15_1 +1003c238 t ??DataTable15_2 +1003c23c t ??DataTable15_3 +1003c240 t ??DataTable15_4 +1003c244 t ??DataTable15_5 +1003c248 t ??DataTable15_6 +1003c24c t ??DataTable15_7 +1003c250 t ??DataTable15_8 +1003c254 t ??__FUNCTION__ +1003c270 t ?_0 +1003c278 t ?_1 +1003c290 t ?_2 +1003c2a0 t ??__FUNCTION___1 +1003c2b4 t ?_4 +1003c2d0 t ??__FUNCTION___2 +1003c2d8 t ?_6 +1003c2e0 t .text_4 +1003c2e0 t cJSON_strcasecmp +1003c2ec t ??cJSON_strcasecmp_0 +1003c2ee t ??cJSON_strcasecmp_2 +1003c2f2 t ??cJSON_strcasecmp_4 +1003c2f4 t ??cJSON_strcasecmp_3 +1003c314 t ??cJSON_strcasecmp_5 +1003c324 t ??cJSON_strcasecmp_1 +1003c326 T cJSON_InitHooks +1003c326 t .text_6 +1003c33a t ??cJSON_InitHooks_0 +1003c34c t ??cJSON_InitHooks_1 +1003c350 t .text_7 +1003c350 t cJSON_New_Item +1003c36a T cJSON_Delete +1003c36a t .text_8 +1003c374 t ??cJSON_Delete_1 +1003c384 t ??cJSON_Delete_2 +1003c392 t ??cJSON_Delete_3 +1003c39a t ??cJSON_Delete_4 +1003c3a2 t ??cJSON_Delete_0 +1003c3a6 t .text_9 +1003c3a6 t parse_number +1003c3dc t ??parse_number_1 +1003c3e0 t ??CrossCallReturnLabel_3 +1003c402 t ??parse_number_0 +1003c414 t ??parse_number_3 +1003c418 t ??CrossCallReturnLabel_4 +1003c44c t ??parse_number_2 +1003c468 t ??parse_number_5 +1003c46c t ??parse_number_7 +1003c47a t ??parse_number_6 +1003c484 t ??parse_number_4 +1003c4d6 t .text_10 +1003c4d6 t ?Subroutine4 +1003c4e4 t .text_11 +1003c4e4 t parse_hex4 +1003c50c t ??parse_hex4_0 +1003c534 t ??parse_hex4_2 +1003c560 t ??parse_hex4_3 +1003c574 t ??parse_hex4_5 +1003c57a t ??parse_hex4_4 +1003c592 t ??parse_hex4_1 +1003c596 t .text_12 +1003c596 t parse_string +1003c5ae t ??parse_string_1 +1003c5b0 t ??parse_string_3 +1003c5ba t ??parse_string_0 +1003c5ca t ??parse_string_4 +1003c5e4 t ??parse_string_6 +1003c5ec t ??parse_string_5 +1003c61a t ??parse_string_8 +1003c61e t ??parse_string_9 +1003c622 t ??parse_string_10 +1003c626 t ??parse_string_11 +1003c62a t ??parse_string_12 +1003c62e t ??parse_string_13 +1003c682 t ??parse_string_17 +1003c68e t ??parse_string_18 +1003c69a t ??parse_string_20 +1003c6b0 t ??parse_string_22 +1003c6b4 t ??parse_string_23 +1003c6c2 t ??parse_string_21 +1003c6d0 t ??parse_string_19 +1003c6de t ??parse_string_14 +1003c6e0 t ??parse_string_15 +1003c6e4 t ??parse_string_16 +1003c6e8 t ??parse_string_7 +1003c6fe t ??parse_string_2 +1003c704 t firstByteMark +1003c70c t .text_15 +1003c70c t skip +1003c70e t ??skip_1 +1003c710 t ??skip_0 +1003c71e t ??skip_2 +1003c720 T cJSON_ParseWithOpts +1003c720 t .text_16 +1003c758 t ??cJSON_ParseWithOpts_1 +1003c76e t ??cJSON_ParseWithOpts_2 +1003c772 t ??cJSON_ParseWithOpts_3 +1003c776 t ??cJSON_ParseWithOpts_4 +1003c778 t ??cJSON_ParseWithOpts_0 +1003c77c T cJSON_Parse +1003c77c t .text_17 +1003c782 t .text_21 +1003c782 t parse_value +1003c79e t ??parse_value_1 +1003c7b2 t ??parse_value_3 +1003c7c6 t ??parse_value_2 +1003c7ca t ??parse_value_4 +1003c7de t ??parse_value_5 +1003c7e8 t ??parse_value_6 +1003c7f2 t ??parse_value_7 +1003c830 t ??parse_value_11 +1003c85c t ??parse_value_12 +1003c860 t ??parse_value_10 +1003c864 t ??parse_value_8 +1003c872 t ??parse_value_9 +1003c874 t ??parse_value_0 +1003c87a t .text_26 +1003c87a t parse_object +1003c890 t ??CrossCallReturnLabel_8 +1003c8cc t ??CrossCallReturnLabel_7 +1003c8dc t ??parse_object_3 +1003c8f4 t ??CrossCallReturnLabel_6 +1003c916 t ??CrossCallReturnLabel_5 +1003c926 t ??parse_object_2 +1003c92a t ??parse_object_4 +1003c92e t ??parse_object_1 +1003c932 t ??parse_object_0 +1003c938 t .text_31 +1003c938 t ?Subroutine5 +1003c93c T cJSON_GetObjectItem +1003c93c t .text_37 +1003c944 t ??cJSON_GetObjectItem_1 +1003c946 t ??cJSON_GetObjectItem_0 +1003c954 t ??cJSON_GetObjectItem_2 +1003c958 t ??DataTable28 +1003c95c t ??DataTable28_1 +1003c960 t ??DataTable28_2 +1003c964 t ??DataTable28_3 +1003c968 t ??DataTable29 +1003c96c t ??DataTable29_1 +1003c970 t ?_7 +1003c978 t ?_8 +1003c980 t ?_9 +1003c988 t ?Veneer (6) for rt_md5_append +1003c990 t ?Veneer (6) for rt_md5_final +1003c998 t ?Veneer (6) for rt_md5_init +1003c9a0 T bytecopy +1003c9b4 T rtk_sc_register_pattern +1003c9b4 t .text_7 +1003c9da T rtk_sc_check_pattern +1003c9da t .text_9 +1003c9ec t __iar_annotation$$tailcall +1003c9f0 T rtk_sc_generate_key +1003c9f0 t .text_10 +1003ca02 t __iar_annotation$$tailcall +1003ca06 T rtk_sc_get_cipher_info +1003ca06 t .text_11 +1003ca18 t __iar_annotation$$tailcall +1003ca1c T rtk_sc_decode_profile +1003ca1c t .text_12 +1003ca2e t __iar_annotation$$tailcall +1003ca32 T rtk_sc_get_tlv_info +1003ca32 t .text_13 +1003ca44 t __iar_annotation$$tailcall +1003ca48 T parse_tlv_info +1003ca48 t .text_14 +1003caa6 T mcast_udp_get_cipher_info +1003caa6 t .text_15 +1003cacc T mcast_udp_generate_key +1003cacc t .text_16 +1003cbac T mcast_udp_get_pattern +1003cbac t .text_17 +1003ccc2 T mcast_udp_get_profile +1003ccc2 t .text_18 +1003cd20 T mcast_udp_decode_profile +1003cd20 t .text_19 +1003cd4c T rtk_sc_check_packet +1003cd4c t .text_21 +1003cd78 T rtk_clean_profile_value +1003cd78 t .text_22 +1003ce08 t .text_23 +1003ce10 T rtk_restart_simple_config +1003ce10 t .text_24 +1003ce24 T rtk_stop_simple_config +1003ce24 t .text_25 +1003ce32 T rtk_start_simple_config +1003ce32 t .text_26 +1003ce42 t .text_27 +1003ce50 T rtk_sc_init +1003ce50 t .text_28 +1003cf2c t .text_29 +1003cf34 t .text_30 +1003cf3e T rtk_sc_deinit +1003cf3e t .text_31 +1003cf5c t .text_32 +1003cf62 T rtk_start_parse_packet +1003cf62 t .text_33 +1003d158 t .text_34 +1003d15c t .text_35 +1003d160 t .text_36 +1003d168 t .text_37 +1003d174 t ?_0 +1003d1b4 t ?_1 +1003d1fc t sc_device_name +1003d214 t mcast_udp_buffer +1003d258 t default_pin +1003d264 t default_key_iv +1003d26c t ?Veneer (6) for os_zalloc +1003d274 T os_strdup +1003d2a2 T os_get_random +1003d2a2 t .text_3 +1003d2ac T os_xqueue_create +1003d2ac t .text_6 +1003d2b2 T os_xqueue_receive +1003d2b2 t .text_7 +1003d2c4 T os_xqueue_delete +1003d2c4 t .text_8 +1003d2c8 T os_xqueue_send +1003d2c8 t .text_9 +1003d2dc t ?Veneer (6) for rom_sha256_vector +1003d2e4 t ?Veneer (6) for rom_hmac_sha256_vector +1003d2ec t ?Veneer (6) for rom_hmac_sha256 +1003d2f4 t ?Veneer (6) for rom_aes_128_cbc_decrypt +1003d2fc T wps_kdf +1003d3a0 T wps_derive_keys +1003d3a0 t .text_3 +1003d484 T wps_derive_psk +1003d484 t .text_4 +1003d4d6 T wps_decrypt_encr_settings +1003d4d6 t .text_5 +1003d554 T wps_pin_checksum +1003d554 t .text_6 +1003d592 T wps_pin_valid +1003d592 t .text_7 +1003d5b4 T wps_generate_pin +1003d5b4 t .text_8 +1003d5f0 t .text_9 +1003d5f4 t .text_10 +1003d5f8 t .text_11 +1003d5fc T wps_build_wsc_ack +1003d5fc t .text_12 +1003d63e T wps_build_wsc_nack +1003d63e t .text_13 +1003d68c t .text_14 +1003d696 t .text_15 +1003d6a4 t ?_0 +1003d6cc T osDelay +1003d6cc t .text_16 +1003d6dc t ??osDelay_0 +1003d6e4 T init_thread +1003d70e T wlan_network +1003d70e t .text_4 +1003d744 t ??wlan_network_0 +1003d748 t ??DataTable5 +1003d74c t ??__FUNCTION__ +1003d758 t ?_0 +1003d778 t ??__FUNCTION___1 +1003d788 t ?_1 +1003d790 t ?_2 +1003d7b8 T tolower +1003d7c4 T strncmp +1003d7ee T dh5_init +1003d808 T dh5_derive_shared +1003d808 t .text_4 +1003d822 T dh5_free +1003d822 t .text_5 +1003d824 t wpabuf_put_data +1003d846 t .text_3 +1003d846 t wpabuf_put_buf +1003d850 T wpabuf_alloc +1003d850 t .text_5 +1003d868 T wpabuf_alloc_copy +1003d868 t .text_7 +1003d884 T wpabuf_dup +1003d884 t .text_8 +1003d89e T wpabuf_free +1003d89e t .text_9 +1003d8be t __iar_annotation$$tailcall +1003d8c4 t .text_10 +1003d8c8 T wpabuf_put +1003d8c8 t .text_11 +1003d8d6 T wpabuf_zeropad +1003d8d6 t .text_13 +1003d910 t ?Veneer (6) for rom_aes_128_cbc_encrypt +1003d918 t wpabuf_put_u8 +1003d928 t .text_3 +1003d928 t wpabuf_put_be16 +1003d93c t .text_4 +1003d93c t wpabuf_put_data +1003d95e t .text_5 +1003d95e t wpabuf_put_buf +1003d968 T wps_build_public_key +1003d968 t .text_6 +1003d9f6 t .text_9 +1003da0e T wps_build_config_methods +1003da0e t .text_10 +1003da1a T wps_build_uuid_e +1003da1a t .text_11 +1003da32 T wps_build_dev_password_id +1003da32 t .text_12 +1003da3c t .text_13 +1003da54 T wps_build_config_error +1003da54 t .text_14 +1003da60 T wps_build_authenticator +1003da60 t .text_15 +1003dab2 T wps_build_version +1003dab2 t .text_16 +1003dac8 T wps_build_wfa_ext +1003dac8 t .text_17 +1003dacc T wps_build_msg_type +1003dacc t .text_18 +1003dad8 T wps_build_enrollee_nonce +1003dad8 t .text_19 +1003daf6 T wps_build_registrar_nonce +1003daf6 t .text_20 +1003db14 t .text_21 +1003db1a T wps_build_auth_type_flags +1003db1a t .text_22 +1003db2e T wps_build_encr_type_flags +1003db2e t .text_23 +1003db40 t .text_24 +1003db4a t .text_25 +1003db50 t .text_26 +1003db56 T wps_build_conn_type_flags +1003db56 t .text_27 +1003db6a t .text_28 +1003db74 T wps_build_assoc_state +1003db74 t .text_29 +1003db88 T wps_build_key_wrap_auth +1003db88 t .text_30 +1003dbba T wps_build_encr_settings +1003dbba t .text_31 +1003dc30 T wps_build_mac_addr +1003dc30 t .text_33 +1003dc46 t .text_34 +1003dc54 T dh_groups_get +1003dc64 t .text_4 +1003dc68 T dh_init +1003dc68 t .text_5 +1003dcfc T dh_derive_shared +1003dcfc t .text_6 +1003dd54 t random_mix_pool +1003dddc t .text_5 +1003ddea T random_get_bytes +1003ddea t .text_6 +1003de84 t .text_7 +1003de88 t .text_8 +1003de8c t .text_9 +1003de98 t ??twist +1003deb8 t ?Veneer (6) for bignum_init +1003dec0 t ?Veneer (6) for bignum_set_unsigned_bin +1003dec8 t ?Veneer (6) for bignum_exptmod +1003ded0 t ?Veneer (6) for bignum_get_unsigned_bin +1003ded8 t ?Veneer (6) for bignum_deinit +1003dee0 T crypto_mod_exp +1003df7c T En32KCalibration +1003df8a t ??CrossCallReturnLabel_4 +1003df92 t ??CrossCallReturnLabel_3 +1003df9a t ??CrossCallReturnLabel_2 +1003dfa2 t ??CrossCallReturnLabel_1 +1003dfa4 t ??En32KCalibration_0 +1003dfac t ??CrossCallReturnLabel_0 +1003dfd0 t ??En32KCalibration_1 +1003dfd2 t .text_4 +1003dfd2 t ?Subroutine1 +1003dfdc t ??DataTable11 +1003dfe0 t ??DataTable11_1 +1003dfe4 t ??DataTable11_2 +1003dfe8 t ??DataTable11_3 +1003dfec t ??DataTable11_4 +1003dff0 t ??DataTable11_5 +1003dff4 t ?_0 +1003e00c T HalGdmaOpInit +1003e038 t ??DataTable12 +1003e03c t ??DataTable12_1 +1003e040 t ??DataTable12_2 +1003e044 t ??DataTable12_3 +1003e048 t ??DataTable12_4 +1003e04c t ??DataTable12_5 +1003e050 t ??DataTable12_6 +1003e054 t ??DataTable12_7 +1003e058 t ??DataTable12_8 +1003e05c t ??DataTable12_9 +1003e060 t ?Veneer (6) for HalI2CWrite32 +1003e068 t ?Veneer (6) for HalI2CClrAllIntrRtl8195a +1003e070 t ?Veneer (6) for HalI2CIntrCtrl8195a +1003e078 t ?Veneer (6) for HalI2CRead32 +1003e080 t ?Veneer (6) for RtkI2CSendUserAddr +1003e088 t ?Veneer (6) for I2CIsTimeout +1003e090 t ?Veneer (6) for RtkI2CDeInit +1003e098 t ?Veneer (6) for RtkI2CInit +1003e0a0 T HalI2CSendRtl8195a +1003e0d4 t ??HalI2CSendRtl8195a_0 +1003e0fc t ?_0 +1003e11c t ?_1 +1003e138 T HalI2CInit8195a +1003e138 t .text_54 +1003e198 t ??CrossCallReturnLabel_24 +1003e1de t ??CrossCallReturnLabel_23 +1003e1e8 t ??CrossCallReturnLabel_39 +1003e1f6 t ??HalI2CInit8195a_1 +1003e220 t ??CrossCallReturnLabel_22 +1003e232 t ??CrossCallReturnLabel_37 +1003e242 t ??HalI2CInit8195a_0 +1003e24a t ??CrossCallReturnLabel_21 +1003e254 t ??CrossCallReturnLabel_38 +1003e262 t ??HalI2CInit8195a_2 +1003e26e t ??CrossCallReturnLabel_20 +1003e27a t ??CrossCallReturnLabel_36 +1003e288 t ??HalI2CInit8195a_3 +1003e296 t ??CrossCallReturnLabel_19 +1003e2a2 t ??CrossCallReturnLabel_18 +1003e2ae t ??CrossCallReturnLabel_35 +1003e2bc t ??HalI2CInit8195a_4 +1003e2c6 t ??CrossCallReturnLabel_17 +1003e2d0 t ??CrossCallReturnLabel_16 +1003e2da t ??CrossCallReturnLabel_15 +1003e2e4 t ??CrossCallReturnLabel_14 +1003e2ee t ??CrossCallReturnLabel_13 +1003e2f8 t ??CrossCallReturnLabel_12 +1003e304 t ??CrossCallReturnLabel_34 +1003e31e t ??CrossCallReturnLabel_33 +1003e32c t ??HalI2CInit8195a_5 +1003e348 t ?_2 +1003e374 t ?_3 +1003e3a0 t ?_4 +1003e3cc t ?_5 +1003e3f8 t ?_6 +1003e42c t ?_7 +1003e464 t ?_8 +1003e49c T HalI2CSetCLKRtl8195a +1003e49c t .text_62 +1003e4c6 t ??HalI2CSetCLKRtl8195a_0 +1003e4e8 t ??HalI2CSetCLKRtl8195a_2 +1003e4ea t ??HalI2CSetCLKRtl8195a_1 +1003e4ee t ??CrossCallReturnLabel_67 +1003e504 t ??CrossCallReturnLabel_65 +1003e508 t ??CrossCallReturnLabel_26 +1003e514 t ??CrossCallReturnLabel_32 +1003e522 t ??HalI2CSetCLKRtl8195a_6 +1003e526 t ??CrossCallReturnLabel_84 +1003e52c t ??CrossCallReturnLabel_11 +1003e538 t ??CrossCallReturnLabel_31 +1003e544 t ??HalI2CSetCLKRtl8195a_4 +1003e548 t ??CrossCallReturnLabel_68 +1003e55e t ??CrossCallReturnLabel_66 +1003e56a t ??CrossCallReturnLabel_10 +1003e576 t ??CrossCallReturnLabel_30 +1003e584 t ??HalI2CSetCLKRtl8195a_8 +1003e588 t ??CrossCallReturnLabel_85 +1003e594 t ??CrossCallReturnLabel_9 +1003e5a0 t ??CrossCallReturnLabel_29 +1003e5ac t ??HalI2CSetCLKRtl8195a_3 +1003e5b4 t ??CrossCallReturnLabel_25 +1003e5be t ??CrossCallReturnLabel_8 +1003e5c6 t ??CrossCallReturnLabel_7 +1003e5ce t ??CrossCallReturnLabel_6 +1003e5d2 t ??CrossCallReturnLabel_69 +1003e604 t ??HalI2CSetCLKRtl8195a_9 +1003e61c t ??CrossCallReturnLabel_5 +1003e628 t ??CrossCallReturnLabel_28 +1003e636 t ??HalI2CSetCLKRtl8195a_10 +1003e63a t ??CrossCallReturnLabel_86 +1003e646 t ??CrossCallReturnLabel_4 +1003e652 t ??CrossCallReturnLabel_27 +1003e65c t ??HalI2CSetCLKRtl8195a_7 +1003e660 t ??HalI2CSetCLKRtl8195a_5 +1003e668 t ??__func__ +1003e680 t ?_9 +1003e69c t ?_10 +1003e6c4 t ?_11 +1003e6ec t ?_12 +1003e714 t ?_13 +1003e73c t ?_14 +1003e754 t ?_15 +1003e76c t ?_16 +1003e794 t ?_17 +1003e7bc t .text_73 +1003e7bc t ?Subroutine12 +1003e7ca t .text_74 +1003e7ca t ?Subroutine9 +1003e7d4 t .text_75 +1003e7d4 t ?Subroutine8 +1003e7e6 t .text_76 +1003e7e6 t ?Subroutine2 +1003e7e8 t ??Subroutine2_0 +1003e7ee t .text_77 +1003e7ee t ?Subroutine1 +1003e7f0 t ??Subroutine1_0 +1003e7f8 t ??DataTable73 +1003e7fc t ??DataTable74 +1003e800 t ??DataTable74_1 +1003e804 T RtkI2CSend +1003e804 t .text_142 +1003e852 t ??CrossCallReturnLabel_64 +1003e854 t ??RtkI2CSend_2 +1003e858 t ??CrossCallReturnLabel_138 +1003e866 t ??CrossCallReturnLabel_83 +1003e884 t ??RtkI2CSend_4 +1003e898 t ??RtkI2CSend_5 +1003e8a6 t ??RtkI2CSend_3 +1003e8b6 t ??CrossCallReturnLabel_63 +1003e8b8 t ??RtkI2CSend_7 +1003e8bc t ??CrossCallReturnLabel_137 +1003e8ca t ??CrossCallReturnLabel_82 +1003e8e8 t ??RtkI2CSend_9 +1003e908 t ??RtkI2CSend_8 +1003e926 t ??RtkI2CSend_1 +1003e94c t ??CrossCallReturnLabel_62 +1003e950 t ??RtkI2CSend_13 +1003e954 t ??CrossCallReturnLabel_46 +1003e95a t ??CrossCallReturnLabel_209 +1003e960 t ??RtkI2CSend_14 +1003e96a t ??CrossCallReturnLabel_190 +1003e96e t ??CrossCallReturnLabel_213 +1003e976 t ??CrossCallReturnLabel_193 +1003e97a t ??CrossCallReturnLabel_167 +1003e996 t ??RtkI2CSend_12 +1003e9a0 t ??CrossCallReturnLabel_163 +1003e9ae t ??CrossCallReturnLabel_81 +1003e9c0 t ??RtkI2CSend_10 +1003e9ce t ??RtkI2CSend_16 +1003e9ee t ??RtkI2CSend_15 +1003ea02 t ??CrossCallReturnLabel_61 +1003ea04 t ??RtkI2CSend_17 +1003ea08 t ??CrossCallReturnLabel_136 +1003ea14 t ??RtkI2CSend_11 +1003ea24 t ??CrossCallReturnLabel_87 +1003ea30 t ??CrossCallReturnLabel_60 +1003ea32 t ??RtkI2CSend_19 +1003ea42 t ??CrossCallReturnLabel_45 +1003ea4a t ??RtkI2CSend_18 +1003ea54 t ??CrossCallReturnLabel_80 +1003ea72 t ??RtkI2CSend_21 +1003ea92 t ??RtkI2CSend_22 +1003ea96 t ??CrossCallReturnLabel_152 +1003ea9a t ??RtkI2CSend_23 +1003eac6 t ??CrossCallReturnLabel_59 +1003eac8 t ??RtkI2CSend_20 +1003eacc t ??CrossCallReturnLabel_162 +1003eada t ??CrossCallReturnLabel_47 +1003eae0 t ??CrossCallReturnLabel_210 +1003eae6 t ??RtkI2CSend_24 +1003eaf0 t ??CrossCallReturnLabel_191 +1003eaf4 t ??CrossCallReturnLabel_214 +1003eb1e t ??CrossCallReturnLabel_197 +1003eb22 t ??RtkI2CSend_27 +1003eb2e t ??RtkI2CSend_26 +1003eb32 t ??CrossCallReturnLabel_135 +1003eb3a t ??CrossCallReturnLabel_166 +1003eb4a t ??RtkI2CSend_28 +1003eb50 t ??CrossCallReturnLabel_192 +1003eb54 t ??CrossCallReturnLabel_165 +1003eb5c t ??CrossCallReturnLabel_226 +1003eb60 t ??CrossCallReturnLabel_151 +1003eb68 t ??CrossCallReturnLabel_222 +1003eb6c t ??CrossCallReturnLabel_150 +1003eb72 t ??RtkI2CSend_29 +1003eb76 t ??CrossCallReturnLabel_134 +1003eb7e t ??CrossCallReturnLabel_225 +1003eb82 t ??CrossCallReturnLabel_149 +1003eb8a t ??CrossCallReturnLabel_221 +1003eb8c t ??RtkI2CSend_25 +1003eb8e t ??RtkI2CSend_31 +1003eb92 t ??CrossCallReturnLabel_131 +1003eb9c t ??CrossCallReturnLabel_130 +1003eba0 t ??RtkI2CSend_30 +1003ebb0 t ??CrossCallReturnLabel_204 +1003ebc2 t ??CrossCallReturnLabel_161 +1003ebca t ??CrossCallReturnLabel_203 +1003ebe6 t ??CrossCallReturnLabel_227 +1003ec08 t ??RtkI2CSend_33 +1003ec0a t ??RtkI2CSend_32 +1003ec14 t ??CrossCallReturnLabel_79 +1003ec18 t ??RtkI2CSend_34 +1003ec1c t ??RtkI2CSend_35 +1003ec24 t ??CrossCallReturnLabel_206 +1003ec28 t ??CrossCallReturnLabel_148 +1003ec30 t ??CrossCallReturnLabel_220 +1003ec34 t ??CrossCallReturnLabel_147 +1003ec3a t ??RtkI2CSend_0 +1003ec54 t ??CrossCallReturnLabel_58 +1003ec56 t ??RtkI2CSend_37 +1003ec5c t ??RtkI2CSend_39 +1003ec60 t ??CrossCallReturnLabel_133 +1003ec7a t ??CrossCallReturnLabel_43 +1003ec8a t ??RtkI2CSend_38 +1003ec9c t ??CrossCallReturnLabel_160 +1003ecaa t ??CrossCallReturnLabel_78 +1003ecc8 t ??RtkI2CSend_41 +1003ece6 t ??RtkI2CSend_6 +1003ecf6 t ??CrossCallReturnLabel_72 +1003ecfa t ??RtkI2CSend_40 +1003ecfe t ??RtkI2CSend_36 +1003ed0a t ??CrossCallReturnLabel_44 +1003ed10 t ??CrossCallReturnLabel_42 +1003ed16 t ??CrossCallReturnLabel_41 +1003ed1c t ??CrossCallReturnLabel_40 +1003ed2c t ??CrossCallReturnLabel_159 +1003ed34 t ??CrossCallReturnLabel_202 +1003ed36 t ??RtkI2CSend_42 +1003ed3c t ?_50 +1003ed68 t ?_51 +1003ed94 t ?_52 +1003edc0 t ?_53 +1003edec t .text_148 +1003edec t ?Subroutine41 +1003edf2 t __iar_annotation$$tailcall +1003edf4 t .text_149 +1003edf4 t ?Subroutine39 +1003edfc t __iar_annotation$$tailcall +1003ee00 t ??DataTable76 +1003ee04 t .text_151 +1003ee04 t ?Subroutine37 +1003ee16 t .text_152 +1003ee16 t ?Subroutine25 +1003ee1c t ??Subroutine25_0 +1003ee20 t __iar_annotation$$tailcall +1003ee22 t .text_153 +1003ee22 t ?Subroutine23 +1003ee28 t __iar_annotation$$tailcall +1003ee2a t .text_154 +1003ee2a t ?Subroutine10 +1003ee2e t ??Subroutine10_0 +1003ee36 t .text_155 +1003ee36 t ?Subroutine4 +1003ee50 t .text_156 +1003ee50 t ?Subroutine3 +1003ee54 t ??Subroutine3_0 +1003ee5a t __iar_annotation$$tailcall +1003ee5c T RtkI2CReceive +1003ee5c t .text_157 +1003eeac t ??CrossCallReturnLabel_57 +1003eeae t ??RtkI2CReceive_2 +1003eeb2 t ??CrossCallReturnLabel_146 +1003eec6 t ??CrossCallReturnLabel_77 +1003eee2 t ??RtkI2CReceive_4 +1003ef00 t ??RtkI2CReceive_3 +1003ef10 t ??CrossCallReturnLabel_56 +1003ef12 t ??RtkI2CReceive_7 +1003ef16 t ??CrossCallReturnLabel_145 +1003ef24 t ??CrossCallReturnLabel_76 +1003ef40 t ??RtkI2CReceive_9 +1003ef52 t ??RtkI2CReceive_5 +1003ef60 t ??RtkI2CReceive_8 +1003ef80 t ??RtkI2CReceive_1 +1003efb0 t ??CrossCallReturnLabel_55 +1003efb2 t ??RtkI2CReceive_11 +1003efbe t ??RtkI2CReceive_10 +1003efd0 t ??CrossCallReturnLabel_88 +1003efdc t ??CrossCallReturnLabel_54 +1003efde t ??RtkI2CReceive_14 +1003eff0 t ??CrossCallReturnLabel_176 +1003eff6 t ??CrossCallReturnLabel_174 +1003effe t ??RtkI2CReceive_16 +1003f010 t ??RtkI2CReceive_12 +1003f01a t ??CrossCallReturnLabel_168 +1003f028 t ??CrossCallReturnLabel_50 +1003f02e t ??CrossCallReturnLabel_211 +1003f036 t ??RtkI2CReceive_17 +1003f046 t ??CrossCallReturnLabel_186 +1003f054 t ??CrossCallReturnLabel_215 +1003f05a t ??CrossCallReturnLabel_195 +1003f05e t ??CrossCallReturnLabel_173 +1003f062 t ??RtkI2CReceive_18 +1003f066 t ??CrossCallReturnLabel_144 +1003f090 t ??RtkI2CReceive_19 +1003f09a t ??CrossCallReturnLabel_75 +1003f09c t ??RtkI2CReceive_21 +1003f0b6 t ??RtkI2CReceive_20 +1003f0c8 t ??RtkI2CReceive_22 +1003f0d6 t ??RtkI2CReceive_15 +1003f0f4 t ??RtkI2CReceive_24 +1003f0f8 t ??CrossCallReturnLabel_158 +1003f100 t ??CrossCallReturnLabel_48 +1003f102 t ??RtkI2CReceive_25 +1003f10e t ??CrossCallReturnLabel_53 +1003f110 t ??RtkI2CReceive_23 +1003f132 t ??CrossCallReturnLabel_196 +1003f134 t ??RtkI2CReceive_26 +1003f138 t ??CrossCallReturnLabel_143 +1003f14a t ??CrossCallReturnLabel_51 +1003f150 t ??CrossCallReturnLabel_212 +1003f158 t ??RtkI2CReceive_28 +1003f15e t ??RtkI2CReceive_27 +1003f168 t ??CrossCallReturnLabel_216 +1003f16c t ??RtkI2CReceive_30 +1003f178 t ??RtkI2CReceive_29 +1003f17c t ??CrossCallReturnLabel_142 +1003f184 t ??CrossCallReturnLabel_172 +1003f192 t ??RtkI2CReceive_31 +1003f196 t ??CrossCallReturnLabel_194 +1003f19a t ??CrossCallReturnLabel_171 +1003f1a0 t ??CrossCallReturnLabel_141 +1003f1a8 t ??CrossCallReturnLabel_224 +1003f1ac t ??CrossCallReturnLabel_157 +1003f1b4 t ??CrossCallReturnLabel_219 +1003f1b8 t ??CrossCallReturnLabel_156 +1003f1c0 t ??CrossCallReturnLabel_49 +1003f1c4 t ??RtkI2CReceive_33 +1003f1c6 t ??RtkI2CReceive_32 +1003f1ce t ??CrossCallReturnLabel_223 +1003f1d2 t ??CrossCallReturnLabel_155 +1003f1da t ??CrossCallReturnLabel_218 +1003f1dc t ??RtkI2CReceive_34 +1003f1e0 t ??CrossCallReturnLabel_140 +1003f1ec t ??CrossCallReturnLabel_187 +1003f1fa t ??RtkI2CReceive_35 +1003f1fe t ??CrossCallReturnLabel_175 +1003f20e t ??CrossCallReturnLabel_201 +1003f210 t ??RtkI2CReceive_36 +1003f21a t ??CrossCallReturnLabel_74 +1003f21e t ??RtkI2CReceive_37 +1003f222 t ??RtkI2CReceive_38 +1003f228 t ??CrossCallReturnLabel_205 +1003f22c t ??CrossCallReturnLabel_154 +1003f234 t ??CrossCallReturnLabel_217 +1003f238 t ??CrossCallReturnLabel_153 +1003f23e t ??RtkI2CReceive_0 +1003f256 t ??CrossCallReturnLabel_52 +1003f25a t ??RtkI2CReceive_41 +1003f276 t ??RtkI2CReceive_40 +1003f280 t ??CrossCallReturnLabel_139 +1003f290 t ??CrossCallReturnLabel_73 +1003f2ac t ??RtkI2CReceive_43 +1003f2c8 t ??RtkI2CReceive_6 +1003f2d6 t ??CrossCallReturnLabel_71 +1003f2da t ??RtkI2CReceive_42 +1003f2de t ??RtkI2CReceive_39 +1003f2ea t ??CrossCallReturnLabel_170 +1003f2f2 t ??CrossCallReturnLabel_200 +1003f2fe t ??CrossCallReturnLabel_169 +1003f306 t ??CrossCallReturnLabel_199 +1003f31a t ??CrossCallReturnLabel_228 +1003f346 t ??RtkI2CReceive_13 +1003f348 t ??RtkI2CReceive_44 +1003f34e t .text_158 +1003f34e t ?Subroutine48 +1003f35a t .text_159 +1003f35a t ?Subroutine47 +1003f360 t .text_160 +1003f360 t ?Subroutine46 +1003f366 t .text_161 +1003f366 t ?Subroutine45 +1003f36e t .text_162 +1003f36e t ?Subroutine44 +1003f376 t .text_163 +1003f376 t ?Subroutine42 +1003f384 t .text_164 +1003f384 t ?Subroutine40 +1003f38c t __iar_annotation$$tailcall +1003f38e t .text_165 +1003f38e t ?Subroutine38 +1003f392 t ??Subroutine38_0 +1003f39e t .text_166 +1003f39e t ?Subroutine35 +1003f3aa t .text_167 +1003f3aa t ?Subroutine30 +1003f3ac t ??Subroutine30_0 +1003f3b4 t __iar_annotation$$tailcall +1003f3b6 t .text_168 +1003f3b6 t ?Subroutine28 +1003f3bc t __iar_annotation$$tailcall +1003f3be t .text_169 +1003f3be t ?Subroutine27 +1003f3c4 t ??Subroutine27_0 +1003f3c8 t __iar_annotation$$tailcall +1003f3ca t .text_170 +1003f3ca t ?Subroutine24 +1003f3d0 t __iar_annotation$$tailcall +1003f3d2 t .text_171 +1003f3d2 t ?Subroutine22 +1003f3d8 t __iar_annotation$$tailcall +1003f3da t .text_172 +1003f3da t ?Subroutine13 +1003f3e6 t .text_173 +1003f3e6 t ?Subroutine11 +1003f3ee t .text_174 +1003f3ee t ?Subroutine7 +1003f400 t __iar_annotation$$tailcall +1003f402 t .text_175 +1003f402 t ?Subroutine6 +1003f422 t .text_176 +1003f422 t ?Subroutine5 +1003f444 t ??DataTable80 +1003f448 t ??DataTable80_1 +1003f44c t ??DataTable80_2 +1003f450 t .text_192 +1003f450 t ?Subroutine26 +1003f456 t __iar_annotation$$tailcall +1003f458 t .text_193 +1003f458 t ?Subroutine21 +1003f45a t ??Subroutine21_0 +1003f45e t __iar_annotation$$tailcall +1003f464 t ?_46 +1003f488 t ?_54 +1003f4b4 t ?_55 +1003f4e0 t ?_56 +1003f50c t ?_57 +1003f538 t ?_58 +1003f564 t ?_59 +1003f590 t ?_60 +1003f5bc t ?_61 +1003f5e8 t ?_62 +1003f614 t ?_63 +1003f640 t ?_64 +1003f66c t ?_65 +1003f698 t ?_66 +1003f6c4 t ?_67 +1003f6f4 T main +1003f700 t ??main_0 +1003f704 T HalADCInit8195a +1003f75c t ??HalADCInit8195a_0 +1003f766 t ??HalADCInit8195a_5 +1003f768 t ??HalADCInit8195a_6 +1003f7b8 t ??HalADCInit8195a_7 +1003f7cc t ??HalADCInit8195a_2 +1003f7d8 t ??HalADCInit8195a_1 +1003f7e2 t ??HalADCInit8195a_9 +1003f7e6 t ??HalADCInit8195a_3 +1003f7f2 t ??HalADCInit8195a_4 +1003f7f6 t ??HalADCInit8195a_8 +1003f83c t ??HalADCInit8195a_11 +1003f864 t ??HalADCInit8195a_12 +1003f88c t ??HalADCInit8195a_13 +1003f8b4 t ??HalADCInit8195a_14 +1003f8c8 t ??HalADCInit8195a_10 +1003f8cc T HalADCDeInit8195a +1003f8cc t .text_3 +1003f8da T HalADCEnableRtl8195a +1003f8da t .text_4 +1003f8ec T HalADCIntrCtrl8195a +1003f8ec t .text_5 +1003f8f0 t .text_6 +1003f8f0 t ?Subroutine0 +1003f8f6 T HalADCReceiveRtl8195a +1003f8f6 t .text_7 +1003f8fc T HalADCReadRegRtl8195a +1003f8fc t .text_8 +1003f904 t ??DataTable10 +1003f908 t ??DataTable10_1 +1003f90c t ??DataTable10_2 +1003f910 t ??DataTable10_3 +1003f914 t ??DataTable10_4 +1003f918 t ??DataTable10_5 +1003f91c t ??DataTable10_6 +1003f920 t ??DataTable10_7 +1003f924 t ??DataTable10_8 +1003f928 t ?_0 +1003f93c t ?_1 +1003f950 t ?_2 +1003f964 t ?_3 +1003f978 t ?_4 +1003f98c t ?_5 +1003f9a0 T SystemCoreClockUpdate +1003f9a0 t .text_6 +1003f9a4 t .text_8 +1003f9a4 t ?Subroutine0 +1003f9b0 t ??DataTable1_4 +1003f9b4 t ?Veneer (6) for HalWdgIntrHandle +1003f9bc T __iar_data_init_app +1003f9c8 t .text_58 +1003f9c8 t StartupHalInitialROMCodeGlobalVar +1003f9dc t .text_59 +1003f9dc t StartupHalLogUartInit +1003fa5e t .text_60 +1003fa5e t StartupHalInitPlatformLogUart +1003faa0 T HalNMIHandler_Patch +1003faa0 t .text_61 +1003fad0 t .text_63 +1003fad4 t .text_64 +1003fad8 t .text_65 +1003fadc t .text_66 +1003fae0 t .text_67 +1003fae4 t .text_68 +1003fae8 t .text_69 +1003faec t .text_70 +1003faf0 t .text_71 +1003faf4 t .text_72 +1003faf8 t .text_73 +1003fafc t .text_74 +1003fb00 t .text_75 +1003fb04 t .text_76 +1003fb08 t .text_77 +1003fb0c t ??__FUNCTION__ +1003fb20 t ?_5 +1003fb44 T rtw_interrupt_thread +1003fba8 t .text_4 +1003fbac t ?_0 +1003fbc4 T wpas_eap_wsc_init +1003fbd4 t __iar_annotation$$tailcall +1003fbd6 T wpas_swith_to_wps_auth +1003fbd6 t .text_8 +1003fbea T wpas_swith_to_wps_encr +1003fbea t .text_9 +1003fc0a T wpas_wps_dev_config +1003fc0a t .text_10 +1003fcda T wpas_wps_init +1003fcda t .text_11 +1003fd58 T wpas_wsc_send_packet +1003fd58 t .text_13 +1003fdbe T wpas_wsc_send_eap_rspidentity +1003fdbe t .text_14 +1003fe36 t .text_15 +1003fe46 t .text_16 +1003fe50 t .text_17 +1003fe5e t .text_18 +1003fe6a t .text_19 +1003fe6a t client_process_wsc_msg +1003fe80 T wpas_wps_notify_wps_finish +1003fe80 t .text_20 +1003feb4 T wpas_wps_notify_wps_finish_hdl +1003feb4 t .text_21 +1003feb6 T wpas_wsc_enrollee_handle_eap_fail +1003feb6 t .text_22 +1003ff00 t .text_23 +1003ff04 t .text_24 +1003ff0e T wpas_wsc_send_eapol +1003ff0e t .text_25 +1003ffda t .text_26 +1003ffe2 t .text_27 +1003ffea T wpas_wsc_enrollee_handle_recvd +1003ffea t .text_28 +10040062 T wpas_wsc_eapol_recvd +10040062 t .text_29 +100400c8 t .text_30 +100400cc t .text_31 +100400d0 t .text_32 +100400d4 t .text_34 +100400d8 T wpas_wsc_eapol_recvd_hdl +100400d8 t .text_35 +100400fc t ?_0 +10040104 t ?_2 +10040110 t ?_3 +1004011c t ?_4 +10040124 t ?_5 +1004012c t ?_7 +1004014c t g_ap_device_type +10040154 t g_sta_device_type +1004015c t wpabuf_put_u8 +1004016c t .text_4 +1004016c t wpabuf_put_data +1004018e t .text_5 +1004018e t eap_wsc_init +10040228 t .text_6 +10040228 t eap_wsc_deinit +1004024c t __iar_annotation$$tailcall +10040250 t .text_7 +10040250 t eap_wsc_build_msg +1004030a t .text_8 +1004030a t eap_wsc_process_cont +10040332 t .text_9 +10040332 t eap_wsc_process_fragment +10040366 t .text_10 +10040366 t eap_wsc_process +1004048e T eap_peer_wsc_register +1004048e t .text_11 +100404a0 t .text_12 +100404a4 t .text_13 +100404a8 t .text_14 +100404ac t .text_15 +100404b0 t .text_16 +100404b4 t .text_17 +100404b8 t .text_18 +100404bc t ?_0 +100404dc t ?_1 +100404fc T wps_init +100405d0 t .text_3 +100405dc t .text_4 +100405e8 T wps_deinit +100405e8 t .text_5 +10040640 t __iar_annotation$$tailcall +10040644 t .text_6 +10040648 T wps_process_msg +10040648 t .text_7 +1004064c T wps_get_msg +1004064c t .text_8 +10040650 t ?_1 +1004065c t wpabuf_put_u8 +1004066c T eap_hdr_len_valid +1004066c t .text_3 +10040688 T eap_hdr_validate +10040688 t .text_4 +100406f8 T eap_msg_alloc +100406f8 t .text_5 +10040774 T eap_get_id +10040774 t .text_7 +1004077a t wpabuf_put_u8 +1004078a T eap_wsc_build_frag_ack +1004078a t .text_3 +100407b8 t wpabuf_put_be16 +100407cc t .text_3 +100407cc t wpabuf_put_data +100407ee T wps_build_manufacturer +100407ee t .text_5 +10040812 T wps_build_model_name +10040812 t .text_6 +10040834 t .text_7 +10040840 T wps_build_model_number +10040840 t .text_8 +10040864 T wps_build_primary_dev_type +10040864 t .text_9 +10040888 t .text_11 +1004088e T wps_build_dev_name +1004088e t .text_13 +100408b2 T wps_build_device_attrs +100408b2 t .text_14 +10040910 T wps_build_os_version +10040910 t .text_15 +10040940 t .text_16 +10040944 T wps_build_rf_bands +10040944 t .text_18 +10040968 T wps_process_device_attrs +10040968 t .text_20 +10040a52 t .text_21 +10040a56 t __iar_annotation$$tailcall +10040a58 t .text_22 +10040a5c t __iar_annotation$$tailcall +10040a5e t .text_23 +10040a66 T wps_device_data_free +10040a66 t .text_28 +10040aac t .text_29 +10040ab0 t wpabuf_put_be16 +10040ac4 t .text_3 +10040ac4 t wpabuf_put_data +10040ae6 t .text_4 +10040ae6 t wps_build_e_hash +10040b88 t .text_5 +10040b96 t .text_6 +10040b9e T wps_build_m1 +10040b9e t .text_7 +10040c9e t .text_8 +10040c9e t wps_build_m5 +10040d20 t .text_9 +10040d26 t .text_10 +10040d26 t wps_build_ap_settings +10040e06 t .text_11 +10040e0c t .text_12 +10040e0c t wps_build_m7 +10040ea2 t .text_13 +10040ea8 t .text_14 +10040eb4 t .text_15 +10040eba t .text_16 +10040ec2 t .text_17 +10040ec8 t .text_18 +10040ed2 T wps_enrollee_get_msg +10040ed2 t .text_19 +10040ff4 t .text_20 +10040ff4 t wps_process_enrollee_nonce +1004100c t .text_21 +1004100c t wps_process_r_snonce1 +10041044 t .text_22 +10041044 t wps_process_r_snonce2 +1004107c t .text_23 +100410b4 t .text_24 +100410b4 t wps_process_cred_e +100410f6 t .text_25 +100410f6 t wps_process_creds +10041136 t .text_26 +10041136 t wps_process_m2 +100411ca t .text_27 +100411ca t wps_process_m4 +10041250 t .text_28 +10041258 t .text_29 +10041260 t .text_30 +10041260 t wps_process_m8 +100412da t .text_31 +100412e2 t .text_32 +100412f0 t .text_33 +100412fa t .text_34 +100412fa t wps_process_wsc_msg +10041448 T wps_enrollee_process_msg +10041448 t .text_35 +100414fc t .text_36 +10041506 t .text_37 +10041510 t wps_parse_vendor_ext_wfa +10041570 t .text_3 +10041570 t wps_set_attr +1004194c T wps_parse_msg +1004194c t .text_4 +100419d8 T wps_process_authenticator +10041a26 T wps_process_key_wrap_auth +10041a26 t .text_3 +10041a62 t .text_4 +10041a62 t wps_process_cred_ssid +10041a8c t .text_5 +10041a8c t wps_process_cred_auth_type +10041a9e t .text_6 +10041a9e t wps_process_cred_encr_type +10041ab0 t .text_7 +10041ab6 t .text_8 +10041ab6 t wps_process_cred_network_key_idx +10041ac2 t .text_9 +10041ac2 t wps_process_cred_network_key +10041aea t .text_10 +10041af0 t .text_11 +10041af0 t wps_process_cred_mac_addr +10041b06 t .text_12 +10041b06 t wps_workaround_cred_key +10041b2a T wps_process_cred +10041b2a t .text_13 +10041b7e t .text_14 +10041b84 t .text_16 +10041b8c t .text_17 +10041b94 t .text_18 +10041b9e t wps_validate_version +10041bb0 t .text_3 +10041bb0 t wps_validate_version2 +10041bc2 t .text_4 +10041bc8 t .text_6 +10041bc8 t valid_config_methods +10041bfc t .text_7 +10041bfc t wps_validate_config_methods +10041c1c t .text_9 +10041c1c t wps_validate_uuid_r +10041c26 t .text_10 +10041c26 t wps_validate_primary_dev_type +10041c30 t .text_11 +10041c30 t wps_validate_rf_bands +10041c48 t .text_12 +10041c48 t wps_validate_assoc_state +10041c60 t .text_13 +10041c60 t wps_validate_config_error +10041c78 t .text_14 +10041c78 t wps_validate_dev_password_id +10041c92 t .text_15 +10041c92 t wps_validate_manufacturer +10041ca8 t .text_16 +10041ca8 t wps_validate_model_name +10041cbe t .text_17 +10041cbe t wps_validate_model_number +10041cd4 t .text_18 +10041cd4 t wps_validate_serial_number +10041cea t .text_19 +10041cea t wps_validate_dev_name +10041d00 t .text_21 +10041d00 t wps_validate_msg_type +10041d14 t .text_22 +10041d14 t wps_validate_mac_addr +10041d26 t .text_23 +10041d26 t wps_validate_enrollee_nonce +10041d30 t .text_24 +10041d30 t wps_validate_registrar_nonce +10041d3a t .text_25 +10041d3a t wps_validate_public_key +10041d4a t .text_26 +10041d4a t num_bits_set +10041d5c t .text_27 +10041d5c t wps_validate_auth_type_flags +10041d78 t .text_28 +10041d78 t wps_validate_auth_type +10041da4 t .text_29 +10041da4 t wps_validate_encr_type_flags +10041dc0 t .text_30 +10041dc0 t wps_validate_encr_type +10041dec t .text_31 +10041df2 t .text_32 +10041df2 t wps_validate_conn_type_flags +10041e08 t .text_33 +10041e08 t wps_validate_os_version +10041e12 t .text_34 +10041e12 t wps_validate_authenticator +10041e1c t .text_35 +10041e1c t wps_validate_encr_settings +10041e2c t .text_36 +10041e2c t wps_validate_key_wrap_auth +10041e36 t .text_37 +10041e36 t wps_validate_ssid +10041e50 t .text_38 +10041e50 t wps_validate_network_key_index +10041e5a t .text_39 +10041e5a t wps_validate_network_key +10041e88 t .text_40 +10041e88 t wps_validate_cred +10041f0a t .text_42 +10041f10 t .text_43 +10041f16 t .text_46 +10041f1c t .text_47 +10041f22 t .text_48 +10041f28 t .text_49 +10041f2e t .text_50 +10041f34 t .text_51 +10041f3a t .text_52 +10041f40 t .text_53 +10041f46 T wps_validate_m2 +10041f46 t .text_54 +10042054 T wps_validate_m2d +10042054 t .text_55 +1004212e t .text_56 +10042136 t .text_58 +1004213c T wps_validate_m4 +1004213c t .text_59 +10042192 T wps_validate_m4_encr +10042192 t .text_60 +100421ba t .text_62 +100421c2 t .text_63 +100421c8 t .text_64 +100421d0 t .text_65 +100421d8 t .text_67 +100421de T wps_validate_m6 +100421de t .text_68 +10042228 t .text_69 +10042230 t .text_70 +10042238 t .text_71 +1004223e T wps_validate_m6_encr +1004223e t .text_72 +10042266 T wps_validate_m8 +10042266 t .text_75 +100422b0 T wps_validate_m8_encr +100422b0 t .text_76 +1004233a T wps_validate_wsc_ack +1004233a t .text_77 +10042380 T wps_validate_wsc_nack +10042380 t .text_78 +100423ce t .text_79 +100423d8 T HalCommonInit +100423e8 T ShowRamBuildInfo +100423ec T _AppStart +100423ec t .text_4 +10042408 t .text_5 +1004240c T hci_lxbus_intf_stop +10042444 T hci_lxbus_dvobj_init +10042444 t .text_3 +10042472 T hci_lxbus_dvobj_deinit +10042472 t .text_4 +100424a4 T hci_lxbus_dvobj_request_irq +100424a4 t .text_5 +100424d0 T hci_lxbus_free_irq +100424d0 t .text_6 +10042500 t .text_7 +10042510 t .text_8 +10042524 t .text_9 +10042528 t .text_10 +1004252c t .text_11 +10042530 T lextra_bus_dma_Interrupt +100425a8 t .text_4 +100425ac t .text_5 +100425b0 t ??__FUNCTION__ +100425cc t ?_0 +100425d4 t segment_holding +100425ee t .text_5 +100425ee t init_mparams +10042620 t .text_8 +10042620 t init_top +10042654 t .text_9 +10042654 t prepend_alloc +100429c2 t .text_10 +100429c2 t sys_alloc +10042d50 t .text_12 +10042d54 t .text_13 +10042d58 t .text_14 +10042d5c t .text_16 +10042d5c t tmalloc_large +100430f6 t .text_17 +100430f6 t tmalloc_small +10043306 T __iar_dlmalloc +10043306 t .text_18 +100435b0 t .text_19 +100435b6 t .text_20 +100435bc T __iar_dlfree +100435bc t .text_21 +10043acc t .text_24 +10043ad0 t .text_28 +10043ad4 T abort +10043adc T __data_GetMemChunk +10043b08 T __exit +10043b14 T __iar_data_init3 +10043b3c T __write +10043b4e t ??__write_1 +10043b5a t ??__write_0 +10043b62 t .text_4 +10043b62 t ?Subroutine0 +10043b68 T rtl8195a_InitSwLeds +10043b6a T rtl8195a_DeInitSwLeds +10043b6a t .text_3 +10043b6c T _Prout +10043b82 T putchar +10043bac T xPortPendSVHandler +10043bea T ulPortSetInterruptMask +10043bf8 T vPortClearInterruptMask +10043bfe T vPortSVCHandler +10043c1e T vPortStartFirstTask +10043c40 T _Randinit +10043c44 T _Randseed +10043c48 t _Rand_idx +10043c4c t _Rand_rv +10043ccc T __iar_Errno +10043cd0 T .ram.data$$Base +10043cd0 T .ram_image2.text$$Limit +10043cd0 t gDbgLevel +10043cd4 t gDbgFlag +10043cd8 T at_sys_items +10043da8 T at_wifi_items +10043f28 t ep +10043f2c t cJSON_malloc +10043f30 t cJSON_free +10043f34 t dhcps_allocated_client_address +10043f38 t dhcps_local_address +10043f3c t dhcps_local_gateway +10043f40 t dhcps_addr_pool_start +10043f44 t dhcps_addr_pool_end +10043f48 t client_request_ip +10043f4c t dhcps_network_id +10043f50 t dhcp_server_state_machine +10043f54 t ip_table +10043f64 t dhcps_pcb +10043f68 t dhcps_send_broadcast_address +10043f6c t dhcps_subnet_broadcast +10043f70 t dhcps_addr_pool_set +10043f74 t dhcp_message_repository +10043f78 t dhcp_message_total_options_lenth +10043f7c t dhcps_ip_table_semaphore +10043f80 t dhcps_netif +10043f84 t dhcp_recorded_xid +10043f88 t dhcps_local_mask +10043f8c t dhcp_client_ethernet_address +10043f9c t bound_client_ethernet_address +10043fac t wakelock +10043fb0 t wakeup_event +10043fb4 T at_log_items +10043fd4 t uxCriticalNesting +10043fd8 T SystemCoreClock +10043fdc t xPendingReadyList +10043ff0 t xTasksWaitingTermination +10044004 T pxCurrentTCB +10044008 t pxDelayedTaskList +1004400c t pxOverflowDelayedTaskList +10044010 t uxTasksDeleted +10044014 t xSuspendedTaskList +10044028 t uxCurrentNumberOfTasks +1004402c t xTickCount +10044030 t uxTopReadyPriority +10044034 t xSchedulerRunning +10044038 t uxPendedTicks +1004403c t xYieldPending +10044040 t xNumOfOverflows +10044044 t uxTaskNumber +10044048 t xNextTaskUnblockTime +1004404c t uxSchedulerSuspended +10044050 t xDelayedTaskList1 +10044064 t xDelayedTaskList2 +10044078 T tcp_active_pcbs_changed +10044079 t tcp_timer_ctr +1004407c T tcp_ticks +10044080 T tcp_bound_pcbs +10044084 T tcp_listen_pcbs +10044088 T tcp_active_pcbs +1004408c T tcp_tw_pcbs +10044090 T tcp_tmp_pcb +10044094 t ??iss +10044098 t udp_port +1004409c T udp_pcbs +100440a0 T BackgroudColor +10044154 T IsBlink +10044155 T IsMeteor +10044156 T Config_r +10044157 T Config_g +10044158 T Config_b +1004415a T Blink_ms +1004415c t ??blinking +10044160 T ws2812b +10044164 t ??PMKID_KDE_TYPE +1004416c t ??seed +10044170 T g_security_mode +10044174 t radom_value +10044178 t custom_pin +1004417c T simple_config_status +10044180 t sync_pkt_index +10044184 t profile_pkt_index +10044188 t fix_sa +1004418c t g_sc_pin_len +10044190 t use_ios7_mac +10044194 t g_sc_ctx +10044198 T pp +1004419c T g_bssid +100441a4 t g_ios_mac +100441ac T udp_mcast +100441e8 T udp_mcast_pin +10044224 t rtw_private_handler +10044258 T mlme_sta_tbl +10044300 t P802_1H_OUI +10044304 t RFC1042_OUI +10044308 T ARFB_table +10044348 T Noisy_State +1004434c T PER_RATE_DOWN +10044360 T PER_RATE_UP +10044374 T DROPING_NECESSARY +10044388 T TRYING_NECESSARY_idx +1004439c T rtl8195A_card_disable_flow +1004443c T rtl8195A_card_enable_flow +100444dc t dh_groups +100444f0 T Array_MP_8195A_AGC_TAB +10044b30 T Array_MP_8195A_PHY_REG +100451a8 T Array_MP_8195A_PHY_REG_PG +10045238 T Array_MP_8195A_MAC_REG +10045540 T Array_MP_8195A_RadioA +100458d8 T gDeltaSwingTableIdx_MP_2GB_N_TxPowerTrack_QFN48_8195A +100458f8 T gDeltaSwingTableIdx_MP_2GB_P_TxPowerTrack_QFN48_8195A +10045918 T gDeltaSwingTableIdx_MP_2GA_N_TxPowerTrack_QFN48_8195A +10045938 T gDeltaSwingTableIdx_MP_2GA_P_TxPowerTrack_QFN48_8195A +10045958 T gDeltaSwingTableIdx_MP_2GCCKB_N_TxPowerTrack_QFN48_8195A +10045978 T gDeltaSwingTableIdx_MP_2GCCKB_P_TxPowerTrack_QFN48_8195A +10045998 T gDeltaSwingTableIdx_MP_2GCCKA_N_TxPowerTrack_QFN48_8195A +100459b8 T gDeltaSwingTableIdx_MP_2GCCKA_P_TxPowerTrack_QFN48_8195A +100459d8 T gDeltaSwingTableIdx_MP_2GB_N_TxPowerTrack_QFN56_8195A +100459f8 T gDeltaSwingTableIdx_MP_2GB_P_TxPowerTrack_QFN56_8195A +10045a18 T gDeltaSwingTableIdx_MP_2GA_N_TxPowerTrack_QFN56_8195A +10045a38 T gDeltaSwingTableIdx_MP_2GA_P_TxPowerTrack_QFN56_8195A +10045a58 T gDeltaSwingTableIdx_MP_2GCCKB_N_TxPowerTrack_QFN56_8195A +10045a78 T gDeltaSwingTableIdx_MP_2GCCKB_P_TxPowerTrack_QFN56_8195A +10045a98 T gDeltaSwingTableIdx_MP_2GCCKA_N_TxPowerTrack_QFN56_8195A +10045ab8 T gDeltaSwingTableIdx_MP_2GCCKA_P_TxPowerTrack_QFN56_8195A +10045ad8 T gDeltaSwingTableIdx_MP_2GB_N_TxPowerTrack_TFBGA96_8195A +10045af8 T gDeltaSwingTableIdx_MP_2GB_P_TxPowerTrack_TFBGA96_8195A +10045b18 T gDeltaSwingTableIdx_MP_2GA_N_TxPowerTrack_TFBGA96_8195A +10045b38 T gDeltaSwingTableIdx_MP_2GA_P_TxPowerTrack_TFBGA96_8195A +10045b58 T gDeltaSwingTableIdx_MP_2GCCKB_N_TxPowerTrack_TFBGA96_8195A +10045b78 T gDeltaSwingTableIdx_MP_2GCCKB_P_TxPowerTrack_TFBGA96_8195A +10045b98 T gDeltaSwingTableIdx_MP_2GCCKA_N_TxPowerTrack_TFBGA96_8195A +10045bb8 T gDeltaSwingTableIdx_MP_2GCCKA_P_TxPowerTrack_TFBGA96_8195A +10045bd8 T Array_MP_8195A_TXPWR_LMT +10046e38 t log_at_sys_init +10046e3c t log_at_wifi_init +10046e40 t log_at_log_init +10046e44 t tcp_port +10046e48 T Region$$Table$$Base +10046ea8 T .ram.bss$$Base +10046ea8 T .ram.data$$Limit +10046ea8 T IMAGE2$$Limit +10046ea8 T Region$$Table$$Limit +10046ea8 t ??stat +100471e8 t wifi +10047220 t ap +10047254 t password +10047298 t ??ApNum +1004729c T dhcp_rx_options_given +100472a8 T dhcp_rx_options_val +100472d0 t ??xid +100472d4 t arp_table +1004739c T lwip_tickless_used +100473a0 T p_write_reconnect_ptr +100473a4 t ADCFullStsFlag +100473a8 t ADCDatBuf +100473b0 T SalAdcInitialFlag +100473b4 T SalAdcInitialDatKeep +100473dc T PwrAdapter +100476f8 T SYSAdapte +100476fc T current_netif +10047700 T current_header +10047704 T current_iphdr_src +10047708 T current_iphdr_dest +1004770c t ??str +1004771c t ip_reass_pbufcount +10047720 t reassdatagrams +10047724 T log_hash +10047824 T xnetif +10047894 t next_timeout +10047898 t tcpip_tcp_timer_active +1004789c t netif_num +100478a0 T netif_list +100478a4 T netif_default +100478a8 t ping_seq +100478ac t infinite_loop +100478b0 t ping_count +100478b4 t data_size +100478b8 t ping_interval +100478bc t ping_call +100478c0 t ping_ip +100478d0 t ulTimerCountsForOneTick +100478d4 t xMaximumPossibleSuppressedTicks +100478d8 t ulStoppedTimerCompensation +100478dc t raw_pcbs +100478e0 T Timer2To7HandlerData +100478f8 t sockets +100479b8 t select_cb_list +100479bc t select_cb_ctr +100479c0 t s_nextthread +100479c4 t s_timeoutlist +100479f4 t pxReadyTasksLists +10047ad0 t flags +10047ad1 t recv_flags +10047ad4 t inseg +10047ae8 t tcplen +10047aec t tcphdr +10047af0 t seqno +10047af4 t ackno +10047af8 t recv_data +10047afc T tcp_input_pcb +10047b00 t tcpip_init_done +10047b04 t tcpip_init_done_arg +10047b08 t mbox +10047b0c t pxCurrentTimerList +10047b10 t pxOverflowTimerList +10047b14 t xTimerQueue +10047b18 t ??xLastTime +10047b1c t xActiveTimerList1 +10047b30 t xActiveTimerList2 +10047b44 T TaskOTA +10047b48 T wifi_setting +10047bb8 T webs_terminate +10047bbc T memoryHook +10047bc4 T pxHTTPListener +10047bc8 T webs_task +10047bcc T webs_sema +10047bd0 t ??buf +10047ef0 t scan_result_handler_ptr +10047f14 t join_user_data +10047f18 t error_flag +10047f1c T rtw_join_status +10047f20 t wifi_mode +10047f24 t event_callback_list +10048074 t eth_buffer +1004807c T paff_array +100480f4 T is_promisc_callback_unlock +100480f8 t is_fixed_channel +100480fc T fixed_channel_num +10048100 T g_ssid_len +10048104 T simple_config_result +10048108 t ack_content +1004810c t backup_sc_ctx +10048110 t simple_config_cmd_start_time +10048114 T g_ssid +10048134 T wps_password_id +10048136 T config_method +10048138 T queue_for_credential +1004813c T wps_pin_code +1004815c T gpio_ws2811 +10048170 T __bss_start__ +10048174 T __bss_end__ +10048178 t libc_has_init +1004817c T psk_essid +100481c4 T psk_passphrase +10048248 T wpa_global_PSK +10048298 T psk_passphrase64 +100482dc T rltk_wlan_info +1004830c T timer_table +10048314 t timer_used_num +10048318 T max_timer_used_num +1004831c T rtw_initmac +10048320 T p_wlan_init_done_callback +10048324 T p_wlan_uart_adapter_callback +10048328 t drvpriv +1004833c T min_free_heap_size +10048340 t skb_pool +10048810 t wrapper_skbbuf_list +10048818 T skbbuf_used_num +1004881c T max_skbbuf_used_num +10048820 T skbdata_used_num +10048824 T max_skbdata_used_num +10048828 T pExportWlanIrqSemaphore +1004882c T promisc_callback +10048830 T promisc_callback_all +10048834 T p_wlan_autoreconnect_hdl +10048838 T g_wps_context +10048848 t ??heap_end +1004884c t ??WifiMcuCmdBitMap +10048850 t g_tcm_heap +10048854 t g_heap_inited +10048858 t tcm_lock +1004885c T wsc_eap +10048878 t pool +100488f8 t input_rotate +100488fc t pool_pos +10048900 t entropy +10048904 t dummy_key +10048918 t mparams +10048930 T __iar_gm_ +10048b08 t ??start +10048b0c t ip_id +10048b0e t etharp_cached_entry +10048b0f T pbuf_free_ooseq_pending +10048b10 t tcp_timer +10048b11 t packet_filter_enable_num +10048b12 T _r +10048b13 T _g +10048b14 T _b +10048b15 t ??pscan_retry_cnt +10048b16 t ??stop_report_count +10048b18 T SpicInitParaAllClk +10048b60 T gHAL_Gpio_Adapter +10048c8c t skb_data_pool +1004da8c t skbdata_list +1004da94 t xStart +1004da9c t pxEnd +1004daa0 t xFreeBytesRemaining +1004daa4 t xMinimumEverFreeBytesRemaining +1004daa8 t xBlockAllocatedBit +1004daac t ext_free +1004dab0 t ext_upper +1004dab4 t ext_lower +1004dab8 T .ram.bss$$Limit +1005d400 B .bf_data$$Base +1005d400 b ucHeap +10070000 B .bf_data$$Limit +1fff0000 T .ram.start.table$$Base +1fff0000 T IMAGE1_DBG$$Base +1fff0000 T TCM_overlay$$Base +1fff0000 T gRamStartFun +1fff0000 t ram +1fff0004 T gRamWakeupFun +1fff0004 t ram_end +1fff0008 T gRamPatchFun0 +1fff0008 t lfree +1fff000c T gRamPatchFun1 +1fff000c T ram_heap +1fff0010 T gRamPatchFun2 +1fff0014 T .ram.start.table$$Limit +1fff0014 T .ram_image1.data$$Base +1fff0014 T RAM_IMG1_VALID_PATTEN +1fff001c T SdrDramDev +1fff002c T SdrDramModeReg +1fff0048 T SdrDramTiming +1fff007c T SdrDramInfo +1fff0090 T rand_x +1fff0094 T AvaWds +1fff1098 t .LANCHOR1 +1fff10a0 t impure_data +1fff1420 t mem_mutex +1fff1424 t memp_tab +1fff145c t memp_memory +1fff14c8 t ??y +1fff14cc t ??z +1fff14d0 t ??c +1fff14d4 T __image2_entry_func__ +1fff14d8 T __image2_validate_code__ +1fff14dc T __image1_bss_start__ +1fff14e0 T __image1_bss_end__ +1fff14e4 T .ram_image1.bss$$Base +1fff14e4 T .ram_image1.bss$$Limit +1fff14e4 T .ram_image1.data$$Limit +1fff14e4 T .ram_image1.text$$Base +1fff14e4 t ?Veneer (6) for HalPinCtrlRtl8195A +1fff14ec t ?Veneer (6) for HalCpuClkConfig +1fff14f4 t ?Veneer (6) for RtlConsolRom +1fff14fc t ?Veneer (6) for SpicInitRtl8195A +1fff1504 t ?Veneer (6) for HalDelayUs +1fff150c t ?Veneer (6) for _memset +1fff1514 t ?Veneer (6) for DiagPrintf +1fff151c t ?Veneer (6) for SpicNVMCalLoadAll +1fff1524 t ?Veneer (6) for SpicFlashInitRtl8195A +1fff152c t ?Veneer (6) for HAL_GPIO_GetPinName +1fff1534 t ?Veneer (6) for HAL_GPIO_Init +1fff153c t ?Veneer (6) for HAL_GPIO_ReadPin_8195a +1fff1544 t ?Veneer (6) for VectorIrqRegisterRtl8195A +1fff154c t ?Veneer (6) for VectorTableInitRtl8195A +1fff1554 t ?Veneer (6) for StartupHalInitialROMCodeGlobalVar +1fff155c t ?Veneer (6) for StartupHalLogUartInit +1fff1564 t ?Veneer (6) for HalTimerInitRtl8195a +1fff156c t ?Veneer (6) for SpicWaitWipRtl8195A +1fff1574 t ?Veneer (6) for StartupHalInitPlatformLogUart +1fff157c t ?Veneer (6) for SpicOneBitCalibrationRtl8195A +1fff1584 t ?Veneer (6) for HAL_GPIO_DeInit_8195a +1fff158c t ?Veneer (6) for _strcmp +1fff1594 T __iar_data_init_boot +1fff15b0 T RtlBootToSram +1fff15b0 t .hal.ram.text_13 +1fff1732 T SYSCpuClkConfig +1fff1732 t .hal.ram.text_14 +1fff176c T IsForceLoadDefaultImg2 +1fff176c t .hal.ram.text_15 +1fff17d0 T PreProcessForVendor +1fff17d0 t .hal.ram.text_16 +1fff19fa t __iar_annotation$$tailcall +1fff19fc t .hal.ram.text_17 +1fff1a00 t .hal.ram.text_18 +1fff1a04 t .hal.ram.text_19 +1fff1a08 t .hal.ram.text_20 +1fff1a0c t .hal.ram.text_21 +1fff1a10 t .hal.ram.text_22 +1fff1a14 t .hal.ram.text_23 +1fff1a18 t .hal.ram.text_24 +1fff1a1c t .hal.ram.text_25 +1fff1a20 t .hal.ram.text_26 +1fff1a24 t .hal.ram.text_27 +1fff1a28 t .hal.ram.text_28 +1fff1a2c t .hal.ram.text_29 +1fff1a30 t .hal.ram.text_30 +1fff1a34 t .hal.ram.text_31 +1fff1a38 t .hal.ram.text_32 +1fff1a3c t .hal.ram.text_33 +1fff1a40 t .hal.ram.text_34 +1fff1a44 t .hal.ram.text_35 +1fff1a48 t .hal.ram.text_36 +1fff1a4c t .hal.ram.text_37 +1fff1a50 t .hal.ram.text_38 +1fff1a54 t .hal.ram.text_39 +1fff1a58 t .hal.ram.text_40 +1fff1a5c t .hal.ram.text_41 +1fff1a68 t ?_0 +1fff1a88 t ?_1 +1fff1aac t ?_2 +1fff1ab4 t ?_3 +1fff1ad0 t ??__func__ +1fff1ae0 t ?_4 +1fff1af8 t ?_6 +1fff1b14 t ?_7 +1fff1b2c t ?_8 +1fff1b3c t ?_9 +1fff1b50 t ?_10 +1fff1b64 t ?_11 +1fff1b98 t ?_12 +1fff1ba8 t ?_13 +1fff1bd4 t ?_14 +1fff1bfc t ?Veneer (6) for SpicWaitWipDoneRefinedRtl8195A +1fff1c04 T SdrControllerInit +1fff1c86 t ??SdrControllerInit_0 +1fff1c88 T DramInit +1fff1c88 t .hal.sdrc.text_10 +1fff1ce8 t ??DramInit_1 +1fff1cf4 t ??DramInit_2 +1fff1d28 t ??DramInit_0 +1fff1d6e t ??DramInit_5 +1fff1d8e t ??DramInit_6 +1fff1dae t ??DramInit_3 +1fff1db2 t ??DramInit_7 +1fff1dba t ??DramInit_8 +1fff1dce t ??DramInit_4 +1fff1df6 t ??DramInit_9 +1fff1e50 t ??DramInit_10 +1fff1ef0 t ??DramInit_11 +1fff1f00 T SdrCalibration +1fff1f00 t .hal.sdrc.text_11 +1fff1f84 t ??CrossCallReturnLabel_2 +1fff1f92 t ??CrossCallReturnLabel_4 +1fff1f9e t ??SdrCalibration_0 +1fff1fb4 t ??SdrCalibration_2 +1fff1fd4 t ??SdrCalibration_3 +1fff1fdc t ??SdrCalibration_4 +1fff1ffc t ??SdrCalibration_5 +1fff2020 t ??SdrCalibration_8 +1fff2030 t ??SdrCalibration_7 +1fff2064 t ??SdrCalibration_10 +1fff206a t ??SdrCalibration_9 +1fff209c t ??SdrCalibration_12 +1fff20cc t ??SdrCalibration_13 +1fff20d0 t ??CrossCallReturnLabel_3 +1fff20e0 t ??CrossCallReturnLabel_5 +1fff2102 t ??CrossCallReturnLabel_1 +1fff211a t ??CrossCallReturnLabel_0 +1fff2122 t ??SdrCalibration_6 +1fff2142 t ??SdrCalibration_11 +1fff2152 t ??SdrCalibration_15 +1fff215e t ??SdrCalibration_14 +1fff2162 t ??SdrCalibration_1 +1fff2168 t .hal.sdrc.text_12 +1fff2168 t ?Subroutine2 +1fff2174 t .hal.sdrc.text_13 +1fff2174 t ?Subroutine1 +1fff217e t .hal.sdrc.text_14 +1fff217e t ?Subroutine0 +1fff218c T Sdr_Rand2 +1fff218c t .hal.sdrc.text_16 +1fff21c8 T MemTest +1fff21c8 t .hal.sdrc.text_17 +1fff21d2 t ??MemTest_1 +1fff21d4 t ??MemTest_0 +1fff220c t ??MemTest_3 +1fff2210 t ??MemTest_2 +1fff2218 t ??DataTable16 +1fff221c t ??DataTable16_1 +1fff2220 t ??DataTable16_2 +1fff2224 t ??DataTable16_3 +1fff2228 t ??DataTable16_4 +1fff222c t ??DataTable16_5 +1fff2230 t ??DataTable16_6 +1fff2234 t ??DataTable16_7 +1fff2238 t ??DataTable16_8 +1fff223c t ??DataTable16_9 +1fff2240 t ??DataTable16_10 +1fff2244 t ??DataTable16_11 +1fff2248 t ??DataTable16_12 +1fff224c t ??DataTable16_13 +1fff2250 t ??DataTable16_14 +1fff2254 t ??DataTable16_15 +1fff2258 t ??DataTable16_16 +1fff225c t ??DataTable16_17 +1fff2260 t ??DataTable16_18 +1fff2264 t ?_0 +1fff227c t ?_1 +1fff22a0 t ?_2 +1fff22c4 t ?_3 +1fff22e0 t ?_4 +1fff2314 t ?_5 +1fff2348 t ?_6 +1fff237c t ?_7 +1fff23ac t ?_8 +1fff23c8 t ?_9 +1fff23f8 T .ram_image1.text$$Limit +1fff23f8 T IMAGE1_DBG$$Limit +1fff5210 T tcm_heap +1ffff210 T .heap$$Base +1ffff210 T end +1ffff214 T .heap$$Limit +1ffff214 T TCM_overlay$$Limit +1ffffffc A STACK_TOP +ffffffff A __as_entries_start +ffffffff A __as_table_start diff --git a/project/realtek_ameba1_va0_example/EWARM-RELEASE/Debug/Exe/application.sim b/project/realtek_ameba1_va0_example/EWARM-RELEASE/Debug/Exe/application.sim new file mode 100644 index 0000000..c927ce3 Binary files /dev/null and b/project/realtek_ameba1_va0_example/EWARM-RELEASE/Debug/Exe/application.sim differ diff --git a/project/realtek_ameba1_va0_example/EWARM-RELEASE/Debug/Exe/ota.bin b/project/realtek_ameba1_va0_example/EWARM-RELEASE/Debug/Exe/ota.bin new file mode 100644 index 0000000..52da2ef Binary files /dev/null and b/project/realtek_ameba1_va0_example/EWARM-RELEASE/Debug/Exe/ota.bin differ diff --git a/project/realtek_ameba1_va0_example/EWARM-RELEASE/Debug/Exe/ram_1.p.bin b/project/realtek_ameba1_va0_example/EWARM-RELEASE/Debug/Exe/ram_1.p.bin new file mode 100644 index 0000000..8f142f1 Binary files /dev/null and b/project/realtek_ameba1_va0_example/EWARM-RELEASE/Debug/Exe/ram_1.p.bin differ diff --git a/project/realtek_ameba1_va0_example/EWARM-RELEASE/Debug/Exe/ram_2.bin b/project/realtek_ameba1_va0_example/EWARM-RELEASE/Debug/Exe/ram_2.bin new file mode 100644 index 0000000..8310144 Binary files /dev/null and b/project/realtek_ameba1_va0_example/EWARM-RELEASE/Debug/Exe/ram_2.bin differ diff --git a/project/realtek_ameba1_va0_example/EWARM-RELEASE/Debug/Exe/ram_2.p.bin b/project/realtek_ameba1_va0_example/EWARM-RELEASE/Debug/Exe/ram_2.p.bin new file mode 100644 index 0000000..52da2ef Binary files /dev/null and b/project/realtek_ameba1_va0_example/EWARM-RELEASE/Debug/Exe/ram_2.p.bin differ diff --git a/project/realtek_ameba1_va0_example/EWARM-RELEASE/Debug/Exe/ram_all.bin b/project/realtek_ameba1_va0_example/EWARM-RELEASE/Debug/Exe/ram_all.bin new file mode 100644 index 0000000..395d89d Binary files /dev/null and b/project/realtek_ameba1_va0_example/EWARM-RELEASE/Debug/Exe/ram_all.bin differ diff --git a/project/realtek_ameba1_va0_example/EWARM-RELEASE/Project.dep b/project/realtek_ameba1_va0_example/EWARM-RELEASE/Project.dep new file mode 100644 index 0000000..2583c48 --- /dev/null +++ b/project/realtek_ameba1_va0_example/EWARM-RELEASE/Project.dep @@ -0,0 +1,3147 @@ + + + + 2 + 2350321726 + + Debug + + $PROJ_DIR$\..\..\..\component\common\api\wifi\rtw_wpa_supplicant\wpa_supplicant\wifi_wps_config.c + $PROJ_DIR$\..\..\..\component\common\network\mdns\mDNSPlatform.c + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v8.1.2\Source\queue.c + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\i2c_api.c + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\i2s_api.c + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v8.1.2\Source\timers.c + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\flash_api.c + $PROJ_DIR$\..\..\..\component\os\os_dep\mailbox.c + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\analogin_api.c + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\nfc_api.c + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\gpio_irq_api.c + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v8.1.2\Source\tasks.c + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\port\realtek\freertos\ethernetif.c + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\pinmap.c + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\port\realtek\freertos\sys_arch.c + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\dma_api.c + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v8.1.2\Source\list.c + $PROJ_DIR$\..\..\..\component\os\os_dep\osdep_api.c + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\pinmap_common.c + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v8.1.2\Source\event_groups.c + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v8.1.2\Source\portable\MemMang\heap_4.c + $PROJ_DIR$\..\..\..\component\common\drivers\wlan\realtek\src\osdep\lwip_intf.c + $PROJ_DIR$\..\..\..\component\os\freertos\cmsis_os.c + $PROJ_DIR$\..\..\..\component\common\network\dhcp\dhcps.c + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v8.1.2\Source\portable\IAR\ARM_CM3\port.c + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v8.1.2\Source\portable\IAR\ARM_CM3\portasm.s + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v8.1.2\Source\croutine.c + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\gpio_api.c + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\misc\driver\rtl_consol.c + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\cmsis\device\system_8195a.c + $PROJ_DIR$\..\..\..\component\common\api\at_cmd\atcmd_sys.c + $PROJ_DIR$\..\..\..\component\common\api\at_cmd\log_service.c + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\misc\driver\low_level_io.c + $PROJ_DIR$\..\..\..\component\common\api\at_cmd\atcmd_wifi.c + $PROJ_DIR$\Debug\Obj\port.pbi + $PROJ_DIR$\Debug\Obj\udp.pbi + $PROJ_DIR$\Debug\Obj\mDNSPlatform.pbi + $PROJ_DIR$\Debug\Obj\ethernetif.pbi + $PROJ_DIR$\Debug\Obj\heap_4.pbi + $PROJ_DIR$\Debug\Obj\croutine.pbi + $PROJ_DIR$\Debug\Obj\rtc_api.pbi + $PROJ_DIR$\Debug\Obj\sys_arch.pbi + $PROJ_DIR$\Debug\Obj\cmsis_os.pbi + $PROJ_DIR$\Debug\Obj\lwip_intf.pbi + $PROJ_DIR$\Debug\Obj\tcp_in.pbi + $PROJ_DIR$\Debug\Obj\tcp_out.pbi + $PROJ_DIR$\Debug\Obj\etharp.pbi + $PROJ_DIR$\Debug\Obj\dhcps.pbi + $PROJ_DIR$\Debug\Obj\queue.pbi + $PROJ_DIR$\Debug\Obj\timers.pbi + $PROJ_DIR$\Debug\Obj\event_groups.pbi + $PROJ_DIR$\Debug\Obj\i2c_api.pbi + $PROJ_DIR$\Debug\Obj\pwmout_api.pbi + $PROJ_DIR$\Debug\Obj\tasks.pbi + $PROJ_DIR$\Debug\Obj\spi_api.pbi + $PROJ_DIR$\Debug\Obj\sys_api.pbi + $PROJ_DIR$\Debug\Obj\serial_api.pbi + $PROJ_DIR$\Debug\Obj\us_ticker_api.pbi + $PROJ_DIR$\Debug\Obj\hal_32k.pbi + $PROJ_DIR$\Debug\Obj\pinmap.pbi + $PROJ_DIR$\Debug\Obj\nfc_api.pbi + $PROJ_DIR$\Debug\Obj\us_ticker.pbi + $PROJ_DIR$\Debug\Obj\dma_api.pbi + $PROJ_DIR$\Debug\Obj\hal_adc.pbi + $PROJ_DIR$\Debug\Obj\hal_gdma.pbi + $PROJ_DIR$\Debug\Obj\gpio_irq_api.pbi + $PROJ_DIR$\Debug\Obj\hal_gpio.pbi + $PROJ_DIR$\Debug\Obj\mailbox.pbi + $PROJ_DIR$\Debug\Obj\i2s_api.pbi + $PROJ_DIR$\Debug\Obj\gpio_api.pbi + $PROJ_DIR$\Debug\Obj\list.pbi + $PROJ_DIR$\Debug\Obj\osdep_api.pbi + $PROJ_DIR$\Debug\Obj\timer_api.pbi + $PROJ_DIR$\Debug\Obj\flash_api.pbi + $PROJ_DIR$\Debug\Obj\sleep.pbi + $PROJ_DIR$\Debug\Obj\wait_api.pbi + $PROJ_DIR$\Debug\Obj\pinmap_common.pbi + $PROJ_DIR$\Debug\Obj\analogin_api.pbi + $PROJ_DIR$\Debug\Obj\wdt_api.pbi + $PROJ_DIR$\Debug\Obj\port_api.pbi + $PROJ_DIR$\Debug\Obj\hal_i2c.pbi + $PROJ_DIR$\Debug\Obj\gpio_api.o + $PROJ_DIR$\Debug\Obj\cmsis_os.o + $PROJ_DIR$\Debug\Obj\mailbox.o + $PROJ_DIR$\Debug\Obj\hal_i2s.pbi + $PROJ_DIR$\Debug\Obj\sys_arch.o + $PROJ_DIR$\Debug\Obj\gpio_irq_api.o + $PROJ_DIR$\Debug\Obj\i2c_api.o + $PROJ_DIR$\Debug\Obj\dhcps.o + $PROJ_DIR$\Debug\Obj\event_groups.o + $PROJ_DIR$\Debug\Obj\tasks.o + $PROJ_DIR$\Debug\Obj\i2s_api.o + $PROJ_DIR$\Debug\Obj\nfc_api.o + $PROJ_DIR$\Debug\Obj\mDNSPlatform.o + $PROJ_DIR$\Debug\Obj\list.o + $PROJ_DIR$\Debug\Obj\lwip_intf.o + $PROJ_DIR$\Debug\Obj\croutine.o + $PROJ_DIR$\Debug\Obj\etharp.o + $PROJ_DIR$\Debug\Obj\hal_mii.pbi + $PROJ_DIR$\Debug\Obj\tcp_out.o + $PROJ_DIR$\Debug\Obj\tcp.o + $PROJ_DIR$\Debug\Obj\udp.o + $PROJ_DIR$\Debug\Obj\timers.o + $PROJ_DIR$\Debug\Obj\osdep_api.o + $PROJ_DIR$\Debug\Obj\ethernetif.o + $PROJ_DIR$\Debug\Obj\port.o + $PROJ_DIR$\Debug\Obj\dma_api.o + $PROJ_DIR$\Debug\Obj\queue.o + $PROJ_DIR$\Debug\Obj\heap_4.o + $PROJ_DIR$\Debug\Obj\analogin_api.o + $PROJ_DIR$\Debug\Obj\flash_api.o + $PROJ_DIR$\Debug\Obj\tcp_in.o + $PROJ_DIR$\Debug\Obj\rtl8195a_pwm.pbi + $PROJ_DIR$\Debug\Obj\asn1parse.pbi + $PROJ_DIR$\Debug\Obj\hal_soc_ps_monitor.pbi + $PROJ_DIR$\Debug\Obj\arc4.pbi + $PROJ_DIR$\Debug\Obj\aesni.pbi + $PROJ_DIR$\Debug\Obj\hal_pcm.pbi + $PROJ_DIR$\Debug\Obj\hal_pwm.pbi + $PROJ_DIR$\Debug\Obj\asn1write.pbi + $PROJ_DIR$\Debug\Obj\rtl8195a_timer.pbi + $PROJ_DIR$\Debug\Obj\hal_ssi.pbi + $PROJ_DIR$\Debug\Obj\rtl8195a_i2s.pbi + $PROJ_DIR$\Debug\Obj\base64.pbi + $PROJ_DIR$\Debug\Obj\hal_timer.pbi + $PROJ_DIR$\Debug\Obj\bignum.pbi + $PROJ_DIR$\Debug\Obj\hal_nfc.pbi + $PROJ_DIR$\Debug\Obj\hal_sdr_controller.pbi + $PROJ_DIR$\Debug\Obj\hal_uart.pbi + $PROJ_DIR$\Debug\Obj\freertos_pmu.pbi + $PROJ_DIR$\Debug\Obj\rtl8195a_adc.pbi + $PROJ_DIR$\Debug\Obj\rtl8195a_gpio.pbi + $PROJ_DIR$\Debug\Obj\rtl8195a_ssi.pbi + $PROJ_DIR$\Debug\Obj\rtl8195a_uart.pbi + $PROJ_DIR$\Debug\Obj\rtl8195a_nfc.pbi + $PROJ_DIR$\Debug\Obj\aes.pbi + $PROJ_DIR$\Debug\Obj\def.o + $PROJ_DIR$\Debug\Obj\inet_chksum.o + $PROJ_DIR$\Debug\Obj\certs.pbi + $PROJ_DIR$\Debug\Obj\camellia.pbi + $PROJ_DIR$\Debug\Obj\cipher.pbi + $PROJ_DIR$\Debug\Obj\netbuf.o + $PROJ_DIR$\Debug\Obj\blowfish.pbi + $PROJ_DIR$\Debug\Obj\ctr_drbg.pbi + $PROJ_DIR$\Debug\Obj\des.pbi + $PROJ_DIR$\Debug\Obj\icmp.o + $PROJ_DIR$\Debug\Obj\inet.o + $PROJ_DIR$\Debug\Obj\ccm.pbi + $PROJ_DIR$\Debug\Obj\ecp.pbi + $PROJ_DIR$\Debug\Obj\api_msg.o + $PROJ_DIR$\Debug\Obj\ecdh.pbi + $PROJ_DIR$\Debug\Obj\debug.pbi + $PROJ_DIR$\Debug\Obj\autoip.o + $PROJ_DIR$\Debug\Obj\err.o + $PROJ_DIR$\Debug\Obj\igmp.o + $PROJ_DIR$\Debug\Obj\ecp_curves.pbi + $PROJ_DIR$\Debug\Obj\sockets.o + $PROJ_DIR$\Debug\Obj\ip.o + $PROJ_DIR$\Debug\Obj\ecdsa.pbi + $PROJ_DIR$\Debug\Obj\tcpip.o + $PROJ_DIR$\Debug\Obj\ip_addr.o + $PROJ_DIR$\Debug\Obj\ip_frag.o + $PROJ_DIR$\Debug\Obj\dhcp.o + $PROJ_DIR$\Debug\Obj\dhm.pbi + $PROJ_DIR$\Debug\Obj\entropy.pbi + $PROJ_DIR$\Debug\Obj\dns.o + $PROJ_DIR$\Debug\Obj\asn1parse.o + $PROJ_DIR$\Debug\Obj\cipher_wrap.pbi + $PROJ_DIR$\Debug\Obj\asn1write.o + $PROJ_DIR$\Debug\Obj\cJSON.o + $PROJ_DIR$\Debug\Obj\bignum.o + $PROJ_DIR$\Debug\Obj\base64.o + $PROJ_DIR$\Debug\Obj\camellia.o + $PROJ_DIR$\Debug\Obj\debug.o + $PROJ_DIR$\Debug\Obj\blowfish.o + $PROJ_DIR$\Debug\Obj\cipher.o + $PROJ_DIR$\Debug\Obj\portasm.o + $PROJ_DIR$\Debug\Obj\example_mdns.o + $PROJ_DIR$\Debug\Obj\arc4.o + $PROJ_DIR$\Debug\Obj\init.o + $PROJ_DIR$\Debug\Obj\system_8195a.pbi + $PROJ_DIR$\Debug\Obj\certs.o + $PROJ_DIR$\Debug\Obj\ctr_drbg.o + $PROJ_DIR$\Debug\Obj\atcmd_sys.pbi + $PROJ_DIR$\Debug\Obj\raw.o + $PROJ_DIR$\Debug\Obj\stats.o + $PROJ_DIR$\Debug\Obj\ccm.o + $PROJ_DIR$\Debug\Obj\atcmd_wifi.pbi + $PROJ_DIR$\Debug\Obj\des.o + $PROJ_DIR$\Debug\Obj\sys.o + $PROJ_DIR$\Debug\Obj\lwip_timers.o + $PROJ_DIR$\Debug\Obj\us_ticker.o + $PROJ_DIR$\Debug\Obj\pinmap.o + $PROJ_DIR$\Debug\Obj\pk_wrap.o + $PROJ_DIR$\Debug\Obj\pinmap_common.o + $PROJ_DIR$\Debug\Obj\port_api.o + $PROJ_DIR$\Debug\Obj\platform.o + $PROJ_DIR$\Debug\Obj\pkparse.o + $PROJ_DIR$\Debug\Obj\pkcs5.o + $PROJ_DIR$\Debug\Obj\entropy_poll.pbi + $PROJ_DIR$\Debug\Obj\serial_api.o + $PROJ_DIR$\Debug\Obj\spi_api.o + $PROJ_DIR$\Debug\Obj\error.pbi + $PROJ_DIR$\Debug\Obj\gcm.pbi + $PROJ_DIR$\Debug\Obj\ripemd160.o + $PROJ_DIR$\Debug\Obj\sleep.o + $PROJ_DIR$\Debug\Obj\pkcs11.o + $PROJ_DIR$\Debug\Obj\sys_api.o + $PROJ_DIR$\Debug\Obj\rsa.o + $PROJ_DIR$\Debug\Obj\pkcs12.o + $PROJ_DIR$\Debug\Obj\rtc_api.o + $PROJ_DIR$\Debug\Obj\wdt_api.o + $PROJ_DIR$\Debug\Obj\pwmout_api.o + $PROJ_DIR$\Debug\Obj\pkwrite.o + $PROJ_DIR$\Debug\Obj\sha1.o + $PROJ_DIR$\Debug\Obj\hal_adc.o + $PROJ_DIR$\Debug\Obj\timer_api.o + $PROJ_DIR$\Debug\Obj\ws2812b.pbi + $PROJ_DIR$\Debug\Obj\ws2812b.o + $PROJ_DIR$\..\..\..\component\common\api\network\src\rtl8195a_it.c + $PROJ_DIR$\..\..\..\component\common\api\wifi\wifi_conf.c + $PROJ_DIR$\..\..\..\component\common\api\network\src\ping_test.c + $PROJ_DIR$\..\..\..\component\common\utilities\tcptest.c + $PROJ_DIR$\..\..\..\component\common\utilities\update.c + $PROJ_DIR$\..\..\..\component\common\api\wifi\wifi_ind.c + $PROJ_DIR$\..\..\..\component\common\utilities\ssl_client.c + $PROJ_DIR$\..\..\..\component\common\api\lwip_netconf.c + $PROJ_DIR$\..\..\..\component\common\api\wifi\wifi_util.c + $PROJ_DIR$\..\..\..\component\common\application\uart_adapter\uart_adapter.c + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\api\api_msg.c + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\api\err.c + $PROJ_DIR$\..\..\..\component\common\api\network\src\wlan_network.c + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\api\api_lib.c + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\api\netbuf.c + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\api\netdb.c + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\api\netifapi.c + $PROJ_DIR$\..\..\..\component\common\api\wifi\wifi_simple_config.c + $PROJ_DIR$\..\..\..\component\common\api\wifi_interactive_mode.c + $PROJ_DIR$\..\..\..\component\common\api\wifi\wifi_promisc.c + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\ipv4\ip.c + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\udp.c + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\netif\etharp.c + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\ipv4\ip_addr.c + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\ipv4\inet_chksum.c + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\init.c + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\sys.c + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\stats.c + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\tcp_in.c + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\api\sockets.c + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\api\tcpip.c + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\ipv4\inet.c + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\def.c + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\dhcp.c + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\dns.c + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\lwip_timers.c + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\mem.c + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\memp.c + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\raw.c + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\tcp.c + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\ipv4\autoip.c + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\ipv4\icmp.c + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\ipv4\igmp.c + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\ipv4\ip_frag.c + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\netif.c + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\pbuf.c + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\tcp_out.c + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_ssi.c + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\rtc_api.c + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\serial_api.c + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_32k.c + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_adc.c + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_soc_ps_monitor.c + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_pcm.c + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_timer.c + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_uart.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\des.c + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_gpio.c + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\sleep.c + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\spi_api.c + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\wdt_api.c + $PROJ_DIR$\..\..\..\component\common\mbed\common\wait_api.c + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\port_api.c + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\pwmout_api.c + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\sys_api.c + $PROJ_DIR$\..\..\..\component\common\mbed\common\us_ticker_api.c + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_mii.c + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_nfc.c + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_sdr_controller.c + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_i2s.c + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\timer_api.c + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\us_ticker.c + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_i2c.c + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_gdma.c + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_pwm.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\base64.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\blowfish.c + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\rtl8195a\src\rtl8195a_ssi.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\camellia.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\cipher.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ctr_drbg.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ccm.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\cipher_wrap.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\bignum.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\debug.c + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\rtl8195a\src\rtl8195a_i2s.c + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\rtl8195a\src\rtl8195a_gpio.c + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\rtl8195a\src\rtl8195a_nfc.c + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\rtl8195a\src\rtl8195a_timer.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\asn1parse.c + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_pmu.c + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\rtl8195a\src\rtl8195a_adc.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\aes.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\aesni.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\arc4.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\certs.c + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\rtl8195a\src\rtl8195a_pwm.c + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\rtl8195a\src\rtl8195a_uart.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\asn1write.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\md.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ripemd160.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\pk_wrap.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\rsa.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\md4.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ecp.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\hmac_drbg.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ecp_curves.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\net.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\padlock.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\oid.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\gcm.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\pbkdf2.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\pkcs11.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\pkcs5.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\md_wrap.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\pkparse.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ecdsa.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\entropy.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\entropy_poll.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\dhm.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ecdh.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\md5.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\havege.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\memory_buffer_alloc.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\pem.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\pk.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\pkcs12.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\error.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\pkwrite.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\md2.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\platform.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ssl_cli.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ssl_cache.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ssl_srv.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\version_features.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\threading.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\x509_crl.c + $PROJ_DIR$\..\..\..\component\common\api\platform\stdlib_patch.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\x509_crt.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\xtea.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\x509_create.c + $PROJ_DIR$\Debug\Obj\stdlib_patch.pbi + $PROJ_DIR$\Debug\Obj\xtea.pbi + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ssl_ciphersuites.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ssl_tls.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\sha256.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\timing.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\x509write_crt.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\sha512.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\version.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\x509.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\x509_csr.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\sha1.c + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\x509write_csr.c + $PROJ_DIR$\..\src\main.c + $PROJ_DIR$\Debug\Obj\pk.pbi + $PROJ_DIR$\..\src\ws2812b.c + $PROJ_DIR$\Debug\Obj\havege.pbi + $PROJ_DIR$\Debug\Obj\md2.pbi + $PROJ_DIR$\Debug\Obj\pk_wrap.pbi + $PROJ_DIR$\Debug\Obj\memory_buffer_alloc.pbi + $PROJ_DIR$\..\..\..\component\common\example\example_entry.c + $PROJ_DIR$\..\..\..\component\common\utilities\cJSON.c + $PROJ_DIR$\Debug\Obj\md_wrap.pbi + $PROJ_DIR$\Debug\Obj\pkcs11.pbi + $PROJ_DIR$\Debug\Obj\pkcs12.pbi + $PROJ_DIR$\..\..\..\component\common\utilities\webserver.c + $PROJ_DIR$\..\..\..\component\common\example\mcast\example_mcast.c + $PROJ_DIR$\Debug\Obj\pem.pbi + $PROJ_DIR$\..\..\..\component\common\example\mdns\example_mdns.c + $PROJ_DIR$\..\..\..\component\common\example\wlan_fast_connect\example_wlan_fast_connect.c + $PROJ_DIR$\Debug\Obj\md4.pbi + $PROJ_DIR$\..\..\..\component\common\example\googlenest\example_google.c + $PROJ_DIR$\Debug\Obj\md5.pbi + $PROJ_DIR$\Debug\Obj\oid.pbi + $PROJ_DIR$\Debug\Obj\md.pbi + $PROJ_DIR$\Debug\Obj\hmac_drbg.pbi + $PROJ_DIR$\Debug\Obj\net.pbi + $PROJ_DIR$\Debug\Obj\padlock.pbi + $PROJ_DIR$\Debug\Obj\pbkdf2.pbi + $PROJ_DIR$\Debug\Obj\ecdh.o + $PROJ_DIR$\Debug\Obj\pbuf.o + $PROJ_DIR$\Debug\Obj\rtl_consol.o + $PROJ_DIR$\Debug\Obj\wifi_conf.o + $PROJ_DIR$\Debug\Obj\x509write_csr.pbi + $PROJ_DIR$\Debug\Obj\x509write_crt.pbi + $PROJ_DIR$\Debug\Obj\ripemd160.pbi + $PROJ_DIR$\Debug\Obj\atcmd_sys.o + $PROJ_DIR$\Debug\Obj\low_level_io.o + $PROJ_DIR$\Debug\Obj\dhm.o + $PROJ_DIR$\Debug\Obj\system_8195a.o + $PROJ_DIR$\Debug\Obj\pkparse.pbi + $PROJ_DIR$\Debug\Obj\atcmd_wifi.o + $PROJ_DIR$\Debug\Obj\netif.o + $PROJ_DIR$\Debug\Obj\ecp_curves.o + $PROJ_DIR$\Debug\Obj\log_service.o + $PROJ_DIR$\Debug\Obj\platform.pbi + $PROJ_DIR$\Debug\Obj\rsa.pbi + $PROJ_DIR$\Debug\Obj\wifi_wps_config.o + $PROJ_DIR$\Debug\Obj\sha1.pbi + $PROJ_DIR$\Debug\Obj\mem.o + $PROJ_DIR$\Debug\Obj\ecp.o + $PROJ_DIR$\Debug\Obj\pkwrite.pbi + $PROJ_DIR$\Debug\Obj\ecdsa.o + $PROJ_DIR$\Debug\Obj\pkcs5.pbi + $PROJ_DIR$\Debug\Obj\wifi_ind.o + $PROJ_DIR$\Debug\Obj\memp.o + $PROJ_DIR$\Debug\Obj\low_level_io.pbi + $PROJ_DIR$\Debug\Obj\rtl_consol.pbi + $PROJ_DIR$\Debug\Obj\wifi_wps_config.pbi + $PROJ_DIR$\Debug\Obj\wifi_simple_config.pbi + $PROJ_DIR$\Debug\Obj\rtl8195a_it.pbi + $PROJ_DIR$\Debug\Obj\ssl_client.pbi + $PROJ_DIR$\Debug\Obj\wlan_network.pbi + $PROJ_DIR$\Debug\Obj\err.pbi + $PROJ_DIR$\Debug\Obj\netbuf.pbi + $PROJ_DIR$\Debug\Obj\netdb.pbi + $PROJ_DIR$\Debug\Obj\netifapi.pbi + $PROJ_DIR$\Debug\Obj\tcpip.pbi + $PROJ_DIR$\Debug\Obj\autoip.pbi + $PROJ_DIR$\Debug\Obj\icmp.pbi + $PROJ_DIR$\Debug\Obj\igmp.pbi + $PROJ_DIR$\Debug\Obj\wifi_interactive_mode.pbi + $PROJ_DIR$\Debug\Obj\api_msg.pbi + $PROJ_DIR$\Debug\Obj\ping_test.pbi + $PROJ_DIR$\Debug\Obj\wifi_conf.pbi + $PROJ_DIR$\Debug\Obj\wifi_util.pbi + $PROJ_DIR$\Debug\Obj\uart_adapter.pbi + $PROJ_DIR$\Debug\Obj\api_lib.pbi + $PROJ_DIR$\Debug\Obj\wifi_ind.pbi + $PROJ_DIR$\Debug\Obj\lwip_netconf.pbi + $PROJ_DIR$\Debug\Obj\sockets.pbi + $PROJ_DIR$\Debug\Obj\update.pbi + $PROJ_DIR$\Debug\Obj\wifi_promisc.pbi + $PROJ_DIR$\Debug\Obj\inet.pbi + $PROJ_DIR$\Debug\Obj\tcptest.pbi + $PROJ_DIR$\Debug\Obj\inet_chksum.pbi + $PROJ_DIR$\Debug\Obj\ip.pbi + $PROJ_DIR$\Debug\Obj\log_service.pbi + $PROJ_DIR$\Debug\Obj\main.pbi + $PROJ_DIR$\Debug\Obj\example_wlan_fast_connect.pbi + $PROJ_DIR$\Debug\Obj\cJSON.pbi + $PROJ_DIR$\Debug\Obj\Project.pbd + $PROJ_DIR$\Debug\Exe\application.axf + $PROJ_DIR$\Debug\Obj\example_entry.pbi + $PROJ_DIR$\Debug\Obj\example_mcast.pbi + $PROJ_DIR$\Debug\Obj\example_google.pbi + $PROJ_DIR$\Debug\Obj\example_mdns.pbi + $PROJ_DIR$\Debug\Obj\webserver.pbi + $PROJ_DIR$\Debug\Obj\netif.pbi + $PROJ_DIR$\Debug\Obj\ip_addr.pbi + $PROJ_DIR$\Debug\Obj\ip_frag.pbi + $PROJ_DIR$\Debug\Obj\pbuf.pbi + $PROJ_DIR$\Debug\Obj\raw.pbi + $PROJ_DIR$\Debug\Obj\ssl_srv.o + $PROJ_DIR$\Debug\Obj\dhcp.pbi + $PROJ_DIR$\Debug\Obj\sha512.o + $PROJ_DIR$\Debug\Obj\lwip_timers.pbi + $PROJ_DIR$\Debug\Obj\init.pbi + $PROJ_DIR$\Debug\Obj\tcp.pbi + $PROJ_DIR$\Debug\Obj\sha256.o + $PROJ_DIR$\Debug\Obj\ssl_tls.o + $PROJ_DIR$\Debug\Obj\stats.pbi + $PROJ_DIR$\Debug\Obj\sys.pbi + $PROJ_DIR$\Debug\Obj\ssl_cli.o + $PROJ_DIR$\Debug\Obj\def.pbi + $PROJ_DIR$\Debug\Obj\dns.pbi + $PROJ_DIR$\Debug\Obj\mem.pbi + $PROJ_DIR$\Debug\Obj\memp.pbi + $PROJ_DIR$\Debug\Obj\ssl_cache.o + $PROJ_DIR$\Debug\Obj\ssl_ciphersuites.o + $PROJ_DIR$\Debug\Obj\threading.o + $PROJ_DIR$\Debug\Obj\rtl8195a_adc.o + $PROJ_DIR$\Debug\Obj\memory_buffer_alloc.o + $PROJ_DIR$\Debug\Obj\hal_sdr_controller.o + $PROJ_DIR$\Debug\Obj\rtl8195a_nfc.o + $PROJ_DIR$\Debug\Obj\hal_mii.o + $PROJ_DIR$\Debug\Obj\rtl8195a_pwm.o + $PROJ_DIR$\Debug\Obj\rtl8195a_ssi.o + $PROJ_DIR$\Debug\Obj\hal_nfc.o + $PROJ_DIR$\Debug\Obj\hal_pcm.o + $PROJ_DIR$\Debug\Obj\hal_soc_ps_monitor.o + $PROJ_DIR$\Debug\Obj\ssl_client.o + $PROJ_DIR$\Debug\Obj\hal_uart.o + $PROJ_DIR$\Debug\Obj\update.o + $PROJ_DIR$\Debug\Obj\wifi_simple_config.o + $PROJ_DIR$\Debug\Obj\us_ticker_api.o + $PROJ_DIR$\Debug\Obj\hal_i2s.o + $PROJ_DIR$\Debug\Obj\uart_adapter.o + $PROJ_DIR$\Debug\Obj\hal_32k.o + $PROJ_DIR$\Debug\Obj\hal_ssi.o + $PROJ_DIR$\Debug\Obj\hal_i2c.o + $PROJ_DIR$\Debug\Obj\hal_gdma.o + $PROJ_DIR$\Debug\Obj\hal_timer.o + $PROJ_DIR$\Debug\Obj\api_lib.o + $PROJ_DIR$\Debug\Obj\freertos_pmu.o + $PROJ_DIR$\Debug\Obj\hal_gpio.o + $PROJ_DIR$\Debug\Obj\rtl8195a_gpio.o + $PROJ_DIR$\Debug\Obj\wait_api.o + $PROJ_DIR$\Debug\Obj\rtl8195a_i2s.o + $PROJ_DIR$\Debug\Obj\rtl8195a_timer.o + $PROJ_DIR$\Debug\Obj\rtl8195a_uart.o + $PROJ_DIR$\Debug\Obj\aesni.o + $PROJ_DIR$\Debug\Obj\wifi_promisc.o + $PROJ_DIR$\Debug\Obj\aes.o + $PROJ_DIR$\Debug\Obj\hal_pwm.o + $PROJ_DIR$\Debug\Obj\havege.o + $PROJ_DIR$\Debug\Obj\gcm.o + $PROJ_DIR$\Debug\Obj\md_wrap.o + $PROJ_DIR$\Debug\Obj\entropy.o + $PROJ_DIR$\Debug\Obj\error.o + $PROJ_DIR$\Debug\Obj\md.o + $PROJ_DIR$\Debug\Obj\md4.o + $PROJ_DIR$\Debug\Obj\md2.o + $PROJ_DIR$\Debug\Obj\entropy_poll.o + $PROJ_DIR$\Debug\Obj\hmac_drbg.o + $PROJ_DIR$\Debug\Obj\md5.o + $PROJ_DIR$\Debug\Obj\wifi_util.o + $PROJ_DIR$\Debug\Obj\wifi_interactive_mode.o + $PROJ_DIR$\Debug\Obj\lwip_netconf.o + $PROJ_DIR$\Debug\Obj\tcptest.o + $PROJ_DIR$\Debug\Obj\rtl8195a_it.o + $PROJ_DIR$\Debug\Obj\cipher_wrap.o + $PROJ_DIR$\Debug\Obj\wlan_network.o + $PROJ_DIR$\Debug\Obj\ping_test.o + $PROJ_DIR$\Debug\Obj\x509_crl.pbi + $PROJ_DIR$\Debug\Obj\netdb.o + $PROJ_DIR$\Debug\Obj\x509_csr.pbi + $PROJ_DIR$\Debug\Obj\x509_crt.pbi + $PROJ_DIR$\Debug\Obj\netifapi.o + $PROJ_DIR$\Debug\Obj\example_google.o + $PROJ_DIR$\Debug\Obj\x509_crl.o + $PROJ_DIR$\Debug\Obj\timing.o + $PROJ_DIR$\Debug\Obj\x509_csr.o + $PROJ_DIR$\Debug\Obj\version.o + $PROJ_DIR$\Debug\Obj\x509write_csr.o + $PROJ_DIR$\Debug\Obj\example_wlan_fast_connect.o + $PROJ_DIR$\Debug\Obj\example_mcast.o + $PROJ_DIR$\Debug\Obj\example_entry.o + $PROJ_DIR$\Debug\Obj\x509.o + $PROJ_DIR$\Debug\Obj\xtea.o + $PROJ_DIR$\Debug\Obj\x509_create.o + $PROJ_DIR$\Debug\Obj\main.o + $PROJ_DIR$\Debug\Obj\x509write_crt.o + $PROJ_DIR$\Debug\Obj\webserver.o + $PROJ_DIR$\Debug\Obj\stdlib_patch.o + $PROJ_DIR$\Debug\Obj\x509_crt.o + $PROJ_DIR$\Debug\Obj\version_features.o + $PROJ_DIR$\Debug\Obj\padlock.o + $PROJ_DIR$\Debug\Obj\net.o + $PROJ_DIR$\Debug\Obj\pbkdf2.o + $PROJ_DIR$\Debug\Obj\pem.o + $PROJ_DIR$\Debug\Obj\oid.o + $PROJ_DIR$\Debug\Obj\pk.o + $PROJ_DIR$\Debug\Obj\sha256.pbi + $PROJ_DIR$\Debug\Obj\ssl_cli.pbi + $PROJ_DIR$\Debug\Obj\sha512.pbi + $PROJ_DIR$\Debug\Obj\ssl_srv.pbi + $PROJ_DIR$\Debug\Obj\x509.pbi + $PROJ_DIR$\Debug\Obj\timing.pbi + $PROJ_DIR$\Debug\Obj\ssl_tls.pbi + $PROJ_DIR$\Debug\Obj\x509_create.pbi + $PROJ_DIR$\Debug\Obj\threading.pbi + $PROJ_DIR$\Debug\Obj\version.pbi + $PROJ_DIR$\Debug\Obj\ssl_ciphersuites.pbi + $PROJ_DIR$\Debug\Obj\version_features.pbi + $PROJ_DIR$\Debug\Obj\ssl_cache.pbi + + + $PROJ_DIR$\..\..\..\component\common\api\wifi\rtw_wpa_supplicant\wpa_supplicant\wifi_wps_config.c + + + ICCARM + 417 + + + BICOMP + 428 + + + + + $PROJ_DIR$\..\..\..\component\common\network\mdns\mDNSPlatform.c + + + ICCARM + 93 + + + BICOMP + 36 + + + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v8.1.2\Source\queue.c + + + ICCARM + 107 + + + BICOMP + 48 + + + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\i2c_api.c + + + ICCARM + 87 + + + BICOMP + 51 + + + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\i2s_api.c + + + ICCARM + 91 + + + BICOMP + 68 + + + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v8.1.2\Source\timers.c + + + ICCARM + 102 + + + BICOMP + 49 + + + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\flash_api.c + + + ICCARM + 110 + + + BICOMP + 73 + + + + + $PROJ_DIR$\..\..\..\component\os\os_dep\mailbox.c + + + ICCARM + 83 + + + BICOMP + 67 + + + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\analogin_api.c + + + ICCARM + 109 + + + BICOMP + 77 + + + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\nfc_api.c + + + ICCARM + 92 + + + BICOMP + 60 + + + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\gpio_irq_api.c + + + ICCARM + 86 + + + BICOMP + 65 + + + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v8.1.2\Source\tasks.c + + + ICCARM + 90 + + + BICOMP + 53 + + + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\port\realtek\freertos\ethernetif.c + + + ICCARM + 104 + + + BICOMP + 37 + + + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\pinmap.c + + + ICCARM + 192 + + + BICOMP + 59 + + + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\port\realtek\freertos\sys_arch.c + + + ICCARM + 85 + + + BICOMP + 41 + + + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\dma_api.c + + + ICCARM + 106 + + + BICOMP + 62 + + + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v8.1.2\Source\list.c + + + ICCARM + 94 + + + BICOMP + 70 + + + + + $PROJ_DIR$\..\..\..\component\os\os_dep\osdep_api.c + + + ICCARM + 103 + + + BICOMP + 71 + + + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\pinmap_common.c + + + ICCARM + 194 + + + BICOMP + 76 + + + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v8.1.2\Source\event_groups.c + + + ICCARM + 89 + + + BICOMP + 50 + + + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v8.1.2\Source\portable\MemMang\heap_4.c + + + ICCARM + 108 + + + BICOMP + 38 + + + + + $PROJ_DIR$\..\..\..\component\common\drivers\wlan\realtek\src\osdep\lwip_intf.c + + + ICCARM + 95 + + + BICOMP + 43 + + + + + $PROJ_DIR$\..\..\..\component\os\freertos\cmsis_os.c + + + ICCARM + 82 + + + BICOMP + 42 + + + + + $PROJ_DIR$\..\..\..\component\common\network\dhcp\dhcps.c + + + ICCARM + 88 + + + BICOMP + 47 + + + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v8.1.2\Source\portable\IAR\ARM_CM3\port.c + + + ICCARM + 105 + + + BICOMP + 34 + + + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v8.1.2\Source\portable\IAR\ARM_CM3\portasm.s + + + AARM + 176 + + + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v8.1.2\Source\croutine.c + + + ICCARM + 96 + + + BICOMP + 39 + + + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\gpio_api.c + + + ICCARM + 81 + + + BICOMP + 69 + + + + + [ROOT_NODE] + + + ILINK + 462 + + + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\misc\driver\rtl_consol.c + + + ICCARM + 401 + + + BICOMP + 427 + + + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\cmsis\device\system_8195a.c + + + ICCARM + 409 + + + BICOMP + 180 + + + + + $PROJ_DIR$\..\..\..\component\common\api\at_cmd\atcmd_sys.c + + + ICCARM + 406 + + + BICOMP + 183 + + + + + $PROJ_DIR$\..\..\..\component\common\api\at_cmd\log_service.c + + + ICCARM + 414 + + + BICOMP + 457 + + + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\misc\driver\low_level_io.c + + + ICCARM + 407 + + + BICOMP + 426 + + + + + $PROJ_DIR$\..\..\..\component\common\api\at_cmd\atcmd_wifi.c + + + ICCARM + 411 + + + BICOMP + 187 + + + + + $PROJ_DIR$\..\..\..\component\common\api\network\src\rtl8195a_it.c + + + ICCARM + 540 + + + BICOMP + 430 + + + + + $PROJ_DIR$\..\..\..\component\common\api\wifi\wifi_conf.c + + + ICCARM + 402 + + + BICOMP + 444 + + + + + $PROJ_DIR$\..\..\..\component\common\api\network\src\ping_test.c + + + ICCARM + 543 + + + BICOMP + 443 + + + + + $PROJ_DIR$\..\..\..\component\common\utilities\tcptest.c + + + ICCARM + 539 + + + BICOMP + 454 + + + + + $PROJ_DIR$\..\..\..\component\common\utilities\update.c + + + ICCARM + 503 + + + BICOMP + 451 + + + + + $PROJ_DIR$\..\..\..\component\common\api\wifi\wifi_ind.c + + + ICCARM + 424 + + + BICOMP + 448 + + + + + $PROJ_DIR$\..\..\..\component\common\utilities\ssl_client.c + + + ICCARM + 501 + + + BICOMP + 431 + + + + + $PROJ_DIR$\..\..\..\component\common\api\lwip_netconf.c + + + ICCARM + 538 + + + BICOMP + 449 + + + + + $PROJ_DIR$\..\..\..\component\common\api\wifi\wifi_util.c + + + ICCARM + 536 + + + BICOMP + 445 + + + + + $PROJ_DIR$\..\..\..\component\common\application\uart_adapter\uart_adapter.c + + + ICCARM + 507 + + + BICOMP + 446 + + + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\api\api_msg.c + + + ICCARM + 149 + + + BICOMP + 442 + + + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\api\err.c + + + ICCARM + 153 + + + BICOMP + 433 + + + + + $PROJ_DIR$\..\..\..\component\common\api\network\src\wlan_network.c + + + ICCARM + 542 + + + BICOMP + 432 + + + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\api\api_lib.c + + + ICCARM + 513 + + + BICOMP + 447 + + + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\api\netbuf.c + + + ICCARM + 141 + + + BICOMP + 434 + + + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\api\netdb.c + + + ICCARM + 545 + + + BICOMP + 435 + + + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\api\netifapi.c + + + ICCARM + 548 + + + BICOMP + 436 + + + + + $PROJ_DIR$\..\..\..\component\common\api\wifi\wifi_simple_config.c + + + ICCARM + 504 + + + BICOMP + 429 + + + + + $PROJ_DIR$\..\..\..\component\common\api\wifi_interactive_mode.c + + + ICCARM + 537 + + + BICOMP + 441 + + + + + $PROJ_DIR$\..\..\..\component\common\api\wifi\wifi_promisc.c + + + ICCARM + 522 + + + BICOMP + 452 + + + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\ipv4\ip.c + + + ICCARM + 157 + + + BICOMP + 456 + + + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\udp.c + + + ICCARM + 101 + + + BICOMP + 35 + + + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\netif\etharp.c + + + ICCARM + 97 + + + BICOMP + 46 + + + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\ipv4\ip_addr.c + + + ICCARM + 160 + + + BICOMP + 469 + + + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\ipv4\inet_chksum.c + + + ICCARM + 137 + + + BICOMP + 455 + + + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\init.c + + + ICCARM + 179 + + + BICOMP + 477 + + + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\sys.c + + + ICCARM + 189 + + + BICOMP + 482 + + + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\stats.c + + + ICCARM + 185 + + + BICOMP + 481 + + + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\tcp_in.c + + + ICCARM + 111 + + + BICOMP + 44 + + + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\api\sockets.c + + + ICCARM + 156 + + + BICOMP + 450 + + + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\api\tcpip.c + + + ICCARM + 159 + + + BICOMP + 437 + + + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\ipv4\inet.c + + + ICCARM + 146 + + + BICOMP + 453 + + + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\def.c + + + ICCARM + 136 + + + BICOMP + 484 + + + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\dhcp.c + + + ICCARM + 162 + + + BICOMP + 474 + + + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\dns.c + + + ICCARM + 165 + + + BICOMP + 485 + + + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\lwip_timers.c + + + ICCARM + 190 + + + BICOMP + 476 + + + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\mem.c + + + ICCARM + 419 + + + BICOMP + 486 + + + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\memp.c + + + ICCARM + 425 + + + BICOMP + 487 + + + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\raw.c + + + ICCARM + 184 + + + BICOMP + 472 + + + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\tcp.c + + + ICCARM + 100 + + + BICOMP + 478 + + + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\ipv4\autoip.c + + + ICCARM + 152 + + + BICOMP + 438 + + + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\ipv4\icmp.c + + + ICCARM + 145 + + + BICOMP + 439 + + + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\ipv4\igmp.c + + + ICCARM + 154 + + + BICOMP + 440 + + + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\ipv4\ip_frag.c + + + ICCARM + 161 + + + BICOMP + 470 + + + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\netif.c + + + ICCARM + 412 + + + BICOMP + 468 + + + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\pbuf.c + + + ICCARM + 400 + + + BICOMP + 471 + + + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\tcp_out.c + + + ICCARM + 99 + + + BICOMP + 45 + + + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_ssi.c + + + ICCARM + 509 + + + BICOMP + 121 + + + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\rtc_api.c + + + ICCARM + 210 + + + BICOMP + 40 + + + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\serial_api.c + + + ICCARM + 200 + + + BICOMP + 56 + + + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_32k.c + + + ICCARM + 508 + + + BICOMP + 58 + + + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_adc.c + + + ICCARM + 215 + + + BICOMP + 63 + + + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_soc_ps_monitor.c + + + ICCARM + 500 + + + BICOMP + 114 + + + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_pcm.c + + + ICCARM + 499 + + + BICOMP + 117 + + + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_timer.c + + + ICCARM + 512 + + + BICOMP + 124 + + + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_uart.c + + + ICCARM + 502 + + + BICOMP + 128 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\des.c + + + ICCARM + 188 + + + BICOMP + 144 + + + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_gpio.c + + + ICCARM + 515 + + + BICOMP + 66 + + + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\sleep.c + + + ICCARM + 205 + + + BICOMP + 74 + + + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\spi_api.c + + + ICCARM + 201 + + + BICOMP + 54 + + + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\wdt_api.c + + + ICCARM + 211 + + + BICOMP + 78 + + + + + $PROJ_DIR$\..\..\..\component\common\mbed\common\wait_api.c + + + ICCARM + 517 + + + BICOMP + 75 + + + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\port_api.c + + + ICCARM + 195 + + + BICOMP + 79 + + + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\pwmout_api.c + + + ICCARM + 212 + + + BICOMP + 52 + + + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\sys_api.c + + + ICCARM + 207 + + + BICOMP + 55 + + + + + $PROJ_DIR$\..\..\..\component\common\mbed\common\us_ticker_api.c + + + ICCARM + 505 + + + BICOMP + 57 + + + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_mii.c + + + ICCARM + 495 + + + BICOMP + 98 + + + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_nfc.c + + + ICCARM + 498 + + + BICOMP + 126 + + + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_sdr_controller.c + + + ICCARM + 493 + + + BICOMP + 127 + + + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_i2s.c + + + ICCARM + 506 + + + BICOMP + 84 + + + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\timer_api.c + + + ICCARM + 216 + + + BICOMP + 72 + + + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\us_ticker.c + + + ICCARM + 191 + + + BICOMP + 61 + + + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_i2c.c + + + ICCARM + 510 + + + BICOMP + 80 + + + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_gdma.c + + + ICCARM + 511 + + + BICOMP + 64 + + + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_pwm.c + + + ICCARM + 524 + + + BICOMP + 118 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\base64.c + + + ICCARM + 171 + + + BICOMP + 123 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\blowfish.c + + + ICCARM + 174 + + + BICOMP + 142 + + + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\rtl8195a\src\rtl8195a_ssi.c + + + ICCARM + 497 + + + BICOMP + 132 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\camellia.c + + + ICCARM + 172 + + + BICOMP + 139 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\cipher.c + + + ICCARM + 175 + + + BICOMP + 140 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ctr_drbg.c + + + ICCARM + 182 + + + BICOMP + 143 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ccm.c + + + ICCARM + 186 + + + BICOMP + 147 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\cipher_wrap.c + + + ICCARM + 541 + + + BICOMP + 167 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\bignum.c + + + ICCARM + 170 + + + BICOMP + 125 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\debug.c + + + ICCARM + 173 + + + BICOMP + 151 + + + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\rtl8195a\src\rtl8195a_i2s.c + + + ICCARM + 518 + + + BICOMP + 122 + + + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\rtl8195a\src\rtl8195a_gpio.c + + + ICCARM + 516 + + + BICOMP + 131 + + + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\rtl8195a\src\rtl8195a_nfc.c + + + ICCARM + 494 + + + BICOMP + 134 + + + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\rtl8195a\src\rtl8195a_timer.c + + + ICCARM + 519 + + + BICOMP + 120 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\asn1parse.c + + + ICCARM + 166 + + + BICOMP + 113 + + + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_pmu.c + + + ICCARM + 514 + + + BICOMP + 129 + + + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\rtl8195a\src\rtl8195a_adc.c + + + ICCARM + 491 + + + BICOMP + 130 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\aes.c + + + ICCARM + 523 + + + BICOMP + 135 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\aesni.c + + + ICCARM + 521 + + + BICOMP + 116 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\arc4.c + + + ICCARM + 178 + + + BICOMP + 115 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\certs.c + + + ICCARM + 181 + + + BICOMP + 138 + + + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\rtl8195a\src\rtl8195a_pwm.c + + + ICCARM + 496 + + + BICOMP + 112 + + + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\rtl8195a\src\rtl8195a_uart.c + + + ICCARM + 520 + + + BICOMP + 133 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\asn1write.c + + + ICCARM + 168 + + + BICOMP + 119 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\md.c + + + ICCARM + 530 + + + BICOMP + 394 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ripemd160.c + + + ICCARM + 204 + + + BICOMP + 405 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\pk_wrap.c + + + ICCARM + 193 + + + BICOMP + 378 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\rsa.c + + + ICCARM + 208 + + + BICOMP + 416 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\md4.c + + + ICCARM + 531 + + + BICOMP + 390 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ecp.c + + + ICCARM + 420 + + + BICOMP + 148 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\hmac_drbg.c + + + ICCARM + 534 + + + BICOMP + 395 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ecp_curves.c + + + ICCARM + 413 + + + BICOMP + 155 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\net.c + + + ICCARM + 568 + + + BICOMP + 396 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\padlock.c + + + ICCARM + 567 + + + BICOMP + 397 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\oid.c + + + ICCARM + 571 + + + BICOMP + 393 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\gcm.c + + + ICCARM + 526 + + + BICOMP + 203 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\pbkdf2.c + + + ICCARM + 569 + + + BICOMP + 398 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\pkcs11.c + + + ICCARM + 206 + + + BICOMP + 383 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\pkcs5.c + + + ICCARM + 198 + + + BICOMP + 423 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\md_wrap.c + + + ICCARM + 527 + + + BICOMP + 382 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\pkparse.c + + + ICCARM + 197 + + + BICOMP + 410 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ecdsa.c + + + ICCARM + 422 + + + BICOMP + 158 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\entropy.c + + + ICCARM + 528 + + + BICOMP + 164 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\entropy_poll.c + + + ICCARM + 533 + + + BICOMP + 199 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\dhm.c + + + ICCARM + 408 + + + BICOMP + 163 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ecdh.c + + + ICCARM + 399 + + + BICOMP + 150 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\md5.c + + + ICCARM + 535 + + + BICOMP + 392 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\havege.c + + + ICCARM + 525 + + + BICOMP + 376 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\memory_buffer_alloc.c + + + ICCARM + 492 + + + BICOMP + 379 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\pem.c + + + ICCARM + 570 + + + BICOMP + 387 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\pk.c + + + ICCARM + 572 + + + BICOMP + 374 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\pkcs12.c + + + ICCARM + 209 + + + BICOMP + 384 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\error.c + + + ICCARM + 529 + + + BICOMP + 202 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\pkwrite.c + + + ICCARM + 213 + + + BICOMP + 421 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\md2.c + + + ICCARM + 532 + + + BICOMP + 377 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\platform.c + + + ICCARM + 196 + + + BICOMP + 415 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ssl_cli.c + + + ICCARM + 483 + + + BICOMP + 574 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ssl_cache.c + + + ICCARM + 488 + + + BICOMP + 585 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ssl_srv.c + + + ICCARM + 473 + + + BICOMP + 576 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\version_features.c + + + ICCARM + 566 + + + BICOMP + 584 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\threading.c + + + ICCARM + 490 + + + BICOMP + 581 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\x509_crl.c + + + ICCARM + 550 + + + BICOMP + 544 + + + + + $PROJ_DIR$\..\..\..\component\common\api\platform\stdlib_patch.c + + + ICCARM + 564 + + + BICOMP + 360 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\x509_crt.c + + + ICCARM + 565 + + + BICOMP + 547 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\xtea.c + + + ICCARM + 559 + + + BICOMP + 361 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\x509_create.c + + + ICCARM + 560 + + + BICOMP + 580 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ssl_ciphersuites.c + + + ICCARM + 489 + + + BICOMP + 583 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ssl_tls.c + + + ICCARM + 480 + + + BICOMP + 579 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\sha256.c + + + ICCARM + 479 + + + BICOMP + 573 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\timing.c + + + ICCARM + 551 + + + BICOMP + 578 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\x509write_crt.c + + + ICCARM + 562 + + + BICOMP + 404 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\sha512.c + + + ICCARM + 475 + + + BICOMP + 575 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\version.c + + + ICCARM + 553 + + + BICOMP + 582 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\x509.c + + + ICCARM + 558 + + + BICOMP + 577 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\x509_csr.c + + + ICCARM + 552 + + + BICOMP + 546 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\sha1.c + + + ICCARM + 214 + + + BICOMP + 418 + + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\x509write_csr.c + + + ICCARM + 554 + + + BICOMP + 403 + + + + + $PROJ_DIR$\..\src\main.c + + + ICCARM + 561 + + + BICOMP + 458 + + + + + $PROJ_DIR$\..\src\ws2812b.c + + + ICCARM + 218 + + + BICOMP + 217 + + + + + $PROJ_DIR$\..\..\..\component\common\example\example_entry.c + + + ICCARM + 557 + + + BICOMP + 463 + + + + + $PROJ_DIR$\..\..\..\component\common\utilities\cJSON.c + + + ICCARM + 169 + + + BICOMP + 460 + + + + + $PROJ_DIR$\..\..\..\component\common\utilities\webserver.c + + + ICCARM + 563 + + + BICOMP + 467 + + + + + $PROJ_DIR$\..\..\..\component\common\example\mcast\example_mcast.c + + + ICCARM + 556 + + + BICOMP + 464 + + + + + $PROJ_DIR$\..\..\..\component\common\example\mdns\example_mdns.c + + + ICCARM + 177 + + + BICOMP + 466 + + + + + $PROJ_DIR$\..\..\..\component\common\example\wlan_fast_connect\example_wlan_fast_connect.c + + + ICCARM + 555 + + + BICOMP + 459 + + + + + $PROJ_DIR$\..\..\..\component\common\example\googlenest\example_google.c + + + ICCARM + 549 + + + BICOMP + 465 + + + + + + Release + + + [MULTI_TOOL] + ILINK + + + + + diff --git a/project/realtek_ameba1_va0_example/EWARM-RELEASE/Project.ewd b/project/realtek_ameba1_va0_example/EWARM-RELEASE/Project.ewd new file mode 100644 index 0000000..ac00ab6 --- /dev/null +++ b/project/realtek_ameba1_va0_example/EWARM-RELEASE/Project.ewd @@ -0,0 +1,2697 @@ + + + + 2 + + Debug + + ARM + + 1 + + C-SPY + 2 + + 26 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ARMSIM_ID + 2 + + 1 + 1 + 1 + + + + + + + + ANGEL_ID + 2 + + 0 + 1 + 1 + + + + + + + + + + + + CMSISDAP_ID + 2 + + 2 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + GDBSERVER_ID + 2 + + 0 + 1 + 1 + + + + + + + + + + + IARROM_ID + 2 + + 1 + 1 + 1 + + + + + + + + + IJET_ID + 2 + + 3 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + JLINK_ID + 2 + + 15 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + LMIFTDI_ID + 2 + + 2 + 1 + 1 + + + + + + + + + + MACRAIGOR_ID + 2 + + 3 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + PEMICRO_ID + 2 + + 1 + 1 + 1 + + + + + + + + + + + + + + + + + + + RDI_ID + 2 + + 2 + 1 + 1 + + + + + + + + + + + + + + + + STLINK_ID + 2 + + 2 + 1 + 1 + + + + + + + + + + + THIRDPARTY_ID + 2 + + 0 + 1 + 1 + + + + + + + + XDS100_ID + 2 + + 2 + 1 + 1 + + + + + + + + + + + + + $TOOLKIT_DIR$\plugins\middleware\HCCWare\HCCWare.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\AVIX\AVIX.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\CMX\CmxArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\CMX\CmxTinyArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\embOS\embOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\MQX\MQXRtosPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\OpenRTOS\OpenRTOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\SafeRTOS\SafeRTOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\ThreadX\ThreadXArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\TI-RTOS\tirtosplugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-286-KA-CSpy.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-KA-CSpy.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-III\uCOS-III-KA-CSpy.ewplugin + 0 + + + $EW_DIR$\common\plugins\CodeCoverage\CodeCoverage.ENU.ewplugin + 1 + + + $EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin + 0 + + + $EW_DIR$\common\plugins\SymList\SymList.ENU.ewplugin + 1 + + + $EW_DIR$\common\plugins\uCProbe\uCProbePlugin.ENU.ewplugin + 0 + + + + + Release + + ARM + + 0 + + C-SPY + 2 + + 26 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ARMSIM_ID + 2 + + 1 + 1 + 0 + + + + + + + + ANGEL_ID + 2 + + 0 + 1 + 0 + + + + + + + + + + + + CMSISDAP_ID + 2 + + 2 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + GDBSERVER_ID + 2 + + 0 + 1 + 0 + + + + + + + + + + + IARROM_ID + 2 + + 1 + 1 + 0 + + + + + + + + + IJET_ID + 2 + + 3 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + JLINK_ID + 2 + + 15 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + LMIFTDI_ID + 2 + + 2 + 1 + 0 + + + + + + + + + + MACRAIGOR_ID + 2 + + 3 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + PEMICRO_ID + 2 + + 1 + 1 + 0 + + + + + + + + + + + + + + + + + + + RDI_ID + 2 + + 2 + 1 + 0 + + + + + + + + + + + + + + + + STLINK_ID + 2 + + 2 + 1 + 0 + + + + + + + + + + + THIRDPARTY_ID + 2 + + 0 + 1 + 0 + + + + + + + + XDS100_ID + 2 + + 2 + 1 + 0 + + + + + + + + + + + + + $TOOLKIT_DIR$\plugins\middleware\HCCWare\HCCWare.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\AVIX\AVIX.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\CMX\CmxArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\CMX\CmxTinyArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\embOS\embOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\MQX\MQXRtosPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\OpenRTOS\OpenRTOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\SafeRTOS\SafeRTOSPlugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\ThreadX\ThreadXArmPlugin.ENU.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\TI-RTOS\tirtosplugin.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-286-KA-CSpy.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-KA-CSpy.ewplugin + 0 + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-III\uCOS-III-KA-CSpy.ewplugin + 0 + + + $EW_DIR$\common\plugins\CodeCoverage\CodeCoverage.ENU.ewplugin + 1 + + + $EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin + 0 + + + $EW_DIR$\common\plugins\SymList\SymList.ENU.ewplugin + 1 + + + $EW_DIR$\common\plugins\uCProbe\uCProbePlugin.ENU.ewplugin + 0 + + + + + + diff --git a/project/realtek_ameba1_va0_example/EWARM-RELEASE/Project.ewp b/project/realtek_ameba1_va0_example/EWARM-RELEASE/Project.ewp new file mode 100644 index 0000000..956deb2 --- /dev/null +++ b/project/realtek_ameba1_va0_example/EWARM-RELEASE/Project.ewp @@ -0,0 +1,2909 @@ + + + + 2 + + Debug + + ARM + + 1 + + General + 3 + + 22 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ICCARM + 2 + + 31 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AARM + 2 + + 9 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OBJCOPY + 0 + + 1 + 1 + 1 + + + + + + + + + CUSTOM + 3 + + + + + + + BICOMP + 0 + + + + BUILDACTION + 1 + + CSCRIPT "$PROJ_DIR$\..\..\..\component\soc\realtek\8195a\misc\iar_utility\common\prebuild.vbs" "$PROJ_DIR$" + CSCRIPT "$PROJ_DIR$\..\..\..\component\soc\realtek\8195a\misc\iar_utility\common\postbuild_img2.vbs" "$TARGET_DIR$" "$PROJ_DIR$" + + + + ILINK + 0 + + 16 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IARCHIVE + 0 + + 0 + 1 + 1 + + + + + + + BILINK + 0 + + + + + Release + + ARM + + 0 + + General + 3 + + 22 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ICCARM + 2 + + 31 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AARM + 2 + + 9 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OBJCOPY + 0 + + 1 + 1 + 0 + + + + + + + + + CUSTOM + 3 + + + + + + + BICOMP + 0 + + + + BUILDACTION + 1 + + + + + + + ILINK + 0 + + 16 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IARCHIVE + 0 + + 0 + 1 + 0 + + + + + + + BILINK + 0 + + + + + cmsis + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\cmsis\device\system_8195a.c + + + + console + + $PROJ_DIR$\..\..\..\component\common\api\at_cmd\atcmd_google.c + + Debug + + + + $PROJ_DIR$\..\..\..\component\common\api\at_cmd\atcmd_sys.c + + + $PROJ_DIR$\..\..\..\component\common\api\at_cmd\atcmd_wifi.c + + + $PROJ_DIR$\..\..\..\component\common\api\at_cmd\log_service.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\misc\driver\low_level_io.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\misc\driver\rtl_consol.c + + + + lib + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\misc\bsp\lib\va0\lib_mdns.a + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\misc\bsp\lib\va0\lib_platform.a + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\misc\bsp\lib\va0\lib_rtlstd.a + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\misc\bsp\lib\va0\lib_wlan.a + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\misc\bsp\lib\va0\lib_wps.a + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\misc\bsp\lib\va0\rom.a + + + + network + + api + + wifi + + rtw_wpa_supplicant + + $PROJ_DIR$\..\..\..\component\common\api\wifi\rtw_wpa_supplicant\wpa_supplicant\wifi_wps_config.c + + + + $PROJ_DIR$\..\..\..\component\common\api\wifi\wifi_conf.c + + + $PROJ_DIR$\..\..\..\component\common\api\wifi\wifi_ind.c + + + $PROJ_DIR$\..\..\..\component\common\api\wifi\wifi_promisc.c + + + $PROJ_DIR$\..\..\..\component\common\api\wifi\wifi_simple_config.c + + + $PROJ_DIR$\..\..\..\component\common\api\wifi\wifi_util.c + + + + $PROJ_DIR$\..\..\..\component\common\api\lwip_netconf.c + + + $PROJ_DIR$\..\..\..\component\common\api\wifi_interactive_mode.c + + + + app + + $PROJ_DIR$\..\..\..\component\common\api\network\src\ping_test.c + + + $PROJ_DIR$\..\..\..\component\common\api\network\src\rtl8195a_it.c + + + $PROJ_DIR$\..\..\..\component\common\utilities\ssl_client.c + + + $PROJ_DIR$\..\..\..\component\common\utilities\tcptest.c + + + $PROJ_DIR$\..\..\..\component\common\application\uart_adapter\uart_adapter.c + + + $PROJ_DIR$\..\..\..\component\common\utilities\update.c + + + $PROJ_DIR$\..\..\..\component\common\api\network\src\wlan_network.c + + + + lwip + + api + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\api\api_lib.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\api\api_msg.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\api\err.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\api\netbuf.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\api\netdb.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\api\netifapi.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\api\sockets.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\api\tcpip.c + + + + core + + ipv4 + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\ipv4\autoip.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\ipv4\icmp.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\ipv4\igmp.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\ipv4\inet.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\ipv4\inet_chksum.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\ipv4\ip.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\ipv4\ip_addr.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\ipv4\ip_frag.c + + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\def.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\dhcp.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\dns.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\init.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\lwip_timers.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\mem.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\memp.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\netif.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\pbuf.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\raw.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\stats.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\sys.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\tcp.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\tcp_in.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\tcp_out.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\udp.c + + + + netif + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\netif\etharp.c + + + + port + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\port\realtek\freertos\ethernetif.c + + + $PROJ_DIR$\..\..\..\component\common\drivers\wlan\realtek\src\osdep\lwip_intf.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\port\realtek\freertos\sys_arch.c + + + + $PROJ_DIR$\..\..\..\component\common\network\dhcp\dhcps.c + + + + mdns + + $PROJ_DIR$\..\..\..\component\common\network\mdns\mDNSPlatform.c + + + + + os + + freertos + + portable + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v8.1.2\Source\portable\MemMang\heap_4.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v8.1.2\Source\portable\IAR\ARM_CM3\port.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v8.1.2\Source\portable\IAR\ARM_CM3\portasm.s + + + + $PROJ_DIR$\..\..\..\component\os\freertos\cmsis_os.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v8.1.2\Source\croutine.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v8.1.2\Source\event_groups.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v8.1.2\Source\list.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v8.1.2\Source\queue.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v8.1.2\Source\tasks.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v8.1.2\Source\timers.c + + + + osdep + + $PROJ_DIR$\..\..\..\component\os\os_dep\mailbox.c + + + $PROJ_DIR$\..\..\..\component\os\os_dep\osdep_api.c + + + + + peripheral + + api + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\analogin_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\dma_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\flash_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\gpio_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\gpio_irq_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\i2c_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\i2s_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\nfc_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\pinmap.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\pinmap_common.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\port_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\pwmout_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\rtc_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\serial_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\sleep.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\spi_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\sys_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\timer_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\us_ticker.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\common\us_ticker_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\common\wait_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\wdt_api.c + + + + hal + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_32k.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_adc.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_gdma.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_gpio.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_i2c.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_i2s.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_mii.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_nfc.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_pcm.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_pwm.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_sdr_controller.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_soc_ps_monitor.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_ssi.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_timer.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_uart.c + + + + osdep + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_pmu.c + + + + rtl8195a + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\rtl8195a\src\rtl8195a_adc.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\rtl8195a\src\rtl8195a_gpio.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\rtl8195a\src\rtl8195a_i2s.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\rtl8195a\src\rtl8195a_nfc.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\rtl8195a\src\rtl8195a_pwm.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\rtl8195a\src\rtl8195a_ssi.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\rtl8195a\src\rtl8195a_timer.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\rtl8195a\src\rtl8195a_uart.c + + + + + SDRAM + + polarssl + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\aes.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\aesni.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\arc4.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\asn1parse.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\asn1write.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\base64.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\bignum.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\blowfish.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\camellia.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ccm.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\certs.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\cipher.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\cipher_wrap.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ctr_drbg.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\debug.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\des.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\dhm.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ecdh.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ecdsa.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ecp.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ecp_curves.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\entropy.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\entropy_poll.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\error.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\gcm.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\havege.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\hmac_drbg.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\md.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\md2.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\md4.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\md5.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\md_wrap.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\memory_buffer_alloc.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\net.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\oid.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\padlock.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\pbkdf2.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\pem.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\pk.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\pk_wrap.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\pkcs11.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\pkcs12.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\pkcs5.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\pkparse.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\pkwrite.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\platform.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ripemd160.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\rsa.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\sha1.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\sha256.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\sha512.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ssl_cache.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ssl_ciphersuites.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ssl_cli.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ssl_srv.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ssl_tls.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\threading.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\timing.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\version.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\version_features.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\x509.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\x509_create.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\x509_crl.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\x509_crt.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\x509_csr.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\x509write_crt.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\x509write_csr.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\xtea.c + + + + $PROJ_DIR$\..\..\..\component\common\api\platform\stdlib_patch.c + + + Debug + + ICCARM + + 31 + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + user + + $PROJ_DIR$\..\src\main.c + + + $PROJ_DIR$\..\src\ws2812b.c + + + + utilities + + example + + $PROJ_DIR$\..\..\..\component\common\example\example_entry.c + + + $PROJ_DIR$\..\..\..\component\common\example\googlenest\example_google.c + + + $PROJ_DIR$\..\..\..\component\common\example\mcast\example_mcast.c + + + $PROJ_DIR$\..\..\..\component\common\example\mdns\example_mdns.c + + + $PROJ_DIR$\..\..\..\component\common\example\wlan_fast_connect\example_wlan_fast_connect.c + + + + $PROJ_DIR$\..\..\..\component\common\utilities\cJSON.c + + + $PROJ_DIR$\..\..\..\component\common\utilities\webserver.c + + + + + diff --git a/project/realtek_ameba1_va0_example/EWARM-RELEASE/Project.ewt b/project/realtek_ameba1_va0_example/EWARM-RELEASE/Project.ewt new file mode 100644 index 0000000..922fb1f --- /dev/null +++ b/project/realtek_ameba1_va0_example/EWARM-RELEASE/Project.ewt @@ -0,0 +1,871 @@ + + + + 2 + + Debug + + ARM + + 1 + + RuntimeChecking + 0 + + 2 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + Release + + ARM + + 0 + + RuntimeChecking + 0 + + 2 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + cmsis + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\cmsis\device\system_8195a.c + + + + console + + $PROJ_DIR$\..\..\..\component\common\api\at_cmd\atcmd_google.c + + + $PROJ_DIR$\..\..\..\component\common\api\at_cmd\atcmd_sys.c + + + $PROJ_DIR$\..\..\..\component\common\api\at_cmd\atcmd_wifi.c + + + $PROJ_DIR$\..\..\..\component\common\api\at_cmd\log_service.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\misc\driver\low_level_io.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\misc\driver\rtl_consol.c + + + + lib + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\misc\bsp\lib\va0\lib_mdns.a + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\misc\bsp\lib\va0\lib_platform.a + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\misc\bsp\lib\va0\lib_rtlstd.a + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\misc\bsp\lib\va0\lib_wlan.a + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\misc\bsp\lib\va0\lib_wps.a + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\misc\bsp\lib\va0\rom.a + + + + network + + api + + wifi + + rtw_wpa_supplicant + + $PROJ_DIR$\..\..\..\component\common\api\wifi\rtw_wpa_supplicant\wpa_supplicant\wifi_wps_config.c + + + + $PROJ_DIR$\..\..\..\component\common\api\wifi\wifi_conf.c + + + $PROJ_DIR$\..\..\..\component\common\api\wifi\wifi_ind.c + + + $PROJ_DIR$\..\..\..\component\common\api\wifi\wifi_promisc.c + + + $PROJ_DIR$\..\..\..\component\common\api\wifi\wifi_simple_config.c + + + $PROJ_DIR$\..\..\..\component\common\api\wifi\wifi_util.c + + + + $PROJ_DIR$\..\..\..\component\common\api\lwip_netconf.c + + + $PROJ_DIR$\..\..\..\component\common\api\wifi_interactive_mode.c + + + + app + + $PROJ_DIR$\..\..\..\component\common\api\network\src\ping_test.c + + + $PROJ_DIR$\..\..\..\component\common\api\network\src\rtl8195a_it.c + + + $PROJ_DIR$\..\..\..\component\common\utilities\ssl_client.c + + + $PROJ_DIR$\..\..\..\component\common\utilities\tcptest.c + + + $PROJ_DIR$\..\..\..\component\common\application\uart_adapter\uart_adapter.c + + + $PROJ_DIR$\..\..\..\component\common\utilities\update.c + + + $PROJ_DIR$\..\..\..\component\common\api\network\src\wlan_network.c + + + + lwip + + api + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\api\api_lib.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\api\api_msg.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\api\err.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\api\netbuf.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\api\netdb.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\api\netifapi.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\api\sockets.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\api\tcpip.c + + + + core + + ipv4 + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\ipv4\autoip.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\ipv4\icmp.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\ipv4\igmp.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\ipv4\inet.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\ipv4\inet_chksum.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\ipv4\ip.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\ipv4\ip_addr.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\ipv4\ip_frag.c + + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\def.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\dhcp.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\dns.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\init.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\lwip_timers.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\mem.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\memp.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\netif.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\pbuf.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\raw.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\stats.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\sys.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\tcp.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\tcp_in.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\tcp_out.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\core\udp.c + + + + netif + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\src\netif\etharp.c + + + + port + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\port\realtek\freertos\ethernetif.c + + + $PROJ_DIR$\..\..\..\component\common\drivers\wlan\realtek\src\osdep\lwip_intf.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v1.4.1\port\realtek\freertos\sys_arch.c + + + + $PROJ_DIR$\..\..\..\component\common\network\dhcp\dhcps.c + + + + mdns + + $PROJ_DIR$\..\..\..\component\common\network\mdns\mDNSPlatform.c + + + + + os + + freertos + + portable + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v8.1.2\Source\portable\MemMang\heap_4.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v8.1.2\Source\portable\IAR\ARM_CM3\port.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v8.1.2\Source\portable\IAR\ARM_CM3\portasm.s + + + + $PROJ_DIR$\..\..\..\component\os\freertos\cmsis_os.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v8.1.2\Source\croutine.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v8.1.2\Source\event_groups.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v8.1.2\Source\list.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v8.1.2\Source\queue.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v8.1.2\Source\tasks.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v8.1.2\Source\timers.c + + + + osdep + + $PROJ_DIR$\..\..\..\component\os\os_dep\mailbox.c + + + $PROJ_DIR$\..\..\..\component\os\os_dep\osdep_api.c + + + + + peripheral + + api + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\analogin_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\dma_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\flash_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\gpio_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\gpio_irq_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\i2c_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\i2s_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\nfc_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\pinmap.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\pinmap_common.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\port_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\pwmout_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\rtc_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\serial_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\sleep.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\spi_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\sys_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\timer_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\us_ticker.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\common\us_ticker_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\common\wait_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8195a\wdt_api.c + + + + hal + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_32k.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_adc.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_gdma.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_gpio.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_i2c.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_i2s.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_mii.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_nfc.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_pcm.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_pwm.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_sdr_controller.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_soc_ps_monitor.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_ssi.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_timer.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\src\hal_uart.c + + + + osdep + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_pmu.c + + + + rtl8195a + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\rtl8195a\src\rtl8195a_adc.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\rtl8195a\src\rtl8195a_gpio.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\rtl8195a\src\rtl8195a_i2s.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\rtl8195a\src\rtl8195a_nfc.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\rtl8195a\src\rtl8195a_pwm.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\rtl8195a\src\rtl8195a_ssi.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\rtl8195a\src\rtl8195a_timer.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\fwlib\rtl8195a\src\rtl8195a_uart.c + + + + + SDRAM + + polarssl + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\aes.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\aesni.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\arc4.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\asn1parse.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\asn1write.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\base64.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\bignum.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\blowfish.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\camellia.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ccm.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\certs.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\cipher.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\cipher_wrap.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ctr_drbg.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\debug.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\des.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\dhm.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ecdh.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ecdsa.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ecp.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ecp_curves.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\entropy.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\entropy_poll.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\error.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\gcm.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\havege.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\hmac_drbg.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\md.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\md2.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\md4.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\md5.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\md_wrap.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\memory_buffer_alloc.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\net.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\oid.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\padlock.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\pbkdf2.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\pem.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\pk.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\pk_wrap.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\pkcs11.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\pkcs12.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\pkcs5.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\pkparse.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\pkwrite.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\platform.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ripemd160.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\rsa.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\sha1.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\sha256.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\sha512.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ssl_cache.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ssl_ciphersuites.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ssl_cli.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ssl_srv.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\ssl_tls.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\threading.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\timing.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\version.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\version_features.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\x509.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\x509_create.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\x509_crl.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\x509_crt.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\x509_csr.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\x509write_crt.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\x509write_csr.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\polarssl-1.3.8\library\xtea.c + + + + $PROJ_DIR$\..\..\..\component\common\api\platform\stdlib_patch.c + + + Debug + + + + user + + $PROJ_DIR$\..\src\main.c + + + $PROJ_DIR$\..\src\ws2812b.c + + + + utilities + + example + + $PROJ_DIR$\..\..\..\component\common\example\example_entry.c + + + $PROJ_DIR$\..\..\..\component\common\example\googlenest\example_google.c + + + $PROJ_DIR$\..\..\..\component\common\example\mcast\example_mcast.c + + + $PROJ_DIR$\..\..\..\component\common\example\mdns\example_mdns.c + + + $PROJ_DIR$\..\..\..\component\common\example\wlan_fast_connect\example_wlan_fast_connect.c + + + + $PROJ_DIR$\..\..\..\component\common\utilities\cJSON.c + + + $PROJ_DIR$\..\..\..\component\common\utilities\webserver.c + + + + + diff --git a/project/realtek_ameba1_va0_example/EWARM-RELEASE/Project.eww b/project/realtek_ameba1_va0_example/EWARM-RELEASE/Project.eww new file mode 100644 index 0000000..e0fd14b --- /dev/null +++ b/project/realtek_ameba1_va0_example/EWARM-RELEASE/Project.eww @@ -0,0 +1,10 @@ + + + + + $WS_DIR$\Project.ewp + + + + + diff --git a/project/realtek_ameba1_va0_example/EWARM-RELEASE/image2.icf b/project/realtek_ameba1_va0_example/EWARM-RELEASE/image2.icf new file mode 100644 index 0000000..ad8e046 --- /dev/null +++ b/project/realtek_ameba1_va0_example/EWARM-RELEASE/image2.icf @@ -0,0 +1,190 @@ +/*###ICF### Section handled by ICF editor, don't touch! ****/ +/*-Editor annotation file-*/ +/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */ +/*-Specials-*/ +//define symbol __ICFEDIT_intvec_start__ = 0x00000000; + +/*-Memory Regions-*/ +define symbol __ICFEDIT_region_ROM_start__ = 0x00000000; +define symbol __ICFEDIT_region_ROM_end__ = 0x000FFFFF; +define symbol __ICFEDIT_region_TCM_start__ = 0x1FFF0000; +define symbol __ICFEDIT_region_TCM_end__ = 0x1FFFFFFF; +define symbol __ICFEDIT_region_ROM_USED_RAM_start__ = 0x10000000; +define symbol __ICFEDIT_region_ROM_USED_RAM_end__ = 0x10003FFF; +//define symbol __ICFEDIT_region_RECY_RAM_start__ = 0x10002090; +//define symbol __ICFEDIT_region_RECY_RAM_end__ = 0x100037FF; +define symbol __ICFEDIT_region_BD_RAM_start__ = 0x10004000; +define symbol __ICFEDIT_region_BD_RAM_end__ = 0x1006FFFF; +define symbol __ICFEDIT_region_SDRAM_RAM_start__ = 0x30000000; +define symbol __ICFEDIT_region_SDRAM_RAM_end__ = 0x301FFFFF; + +/*-Sizes-*/ +/*define symbol __ICFEDIT_size_cstack__ = 0x400;*/ +/*define symbol __ICFEDIT_size_heap__ = 0x800;*/ +/**** End of ICF editor section. ###ICF###*/ + + +define memory mem with size = 4G; +define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__]; +define region TCM_region = mem:[from __ICFEDIT_region_TCM_start__ to __ICFEDIT_region_TCM_end__]; +define region ROM_USED_RAM_region = mem:[from __ICFEDIT_region_ROM_USED_RAM_start__ to __ICFEDIT_region_ROM_USED_RAM_end__]; +//define region RECY_RAM_region = mem:[from __ICFEDIT_region_RECY_RAM_start__ to __ICFEDIT_region_RECY_RAM_end__]; +define region BD_RAM_region = mem:[from __ICFEDIT_region_BD_RAM_start__ to __ICFEDIT_region_BD_RAM_end__]; +define region SDRAM_RAM_region = mem:[from __ICFEDIT_region_SDRAM_RAM_start__ to __ICFEDIT_region_SDRAM_RAM_end__]; + +/*define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };*/ +/*define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };*/ + +//initialize by copy { readwrite }; +//initialize by copy with packing = none { section __DLIB_PERTHREAD }; // Required in a multi-threaded application + +//do not initialize { section * }; + +//place at address mem:__ICFEDIT_intvec_start__ { readonly section .vectors_table }; + + +/*place in RAM_region { readwrite, block CSTACK, block HEAP };*/ +place in TCM_region { readwrite }; + +/**************************************** + * ROM Section config * + ****************************************/ +keep { section .rom }; +place at start of ROM_region { readonly, section .rom }; + +/**************************************** + * BD RAM Section config * + ****************************************/ +keep { section .ram_dedecated_vector_table* }; +define block .vector_table with fixed order{section .ram_dedecated_vector_table*}; + +keep { section .ram_user_define_irq_table* }; +define block .user_vector_table with fixed order{section .ram_user_define_irq_table*}; + +keep { section .ram_user_define_data_table* }; +define block .user_data_table with fixed order{section .ram_user_define_data_table*}; + +define block .rom.bss with fixed order{ section .hal.ram.bss* object hal_misc.o, + section .hal.ram.bss* object hal_pinmux.o, + section .hal.ram.bss* object diag.o, + section .hal.ram.bss* object rtl8195a_ssi_rom.o, + section .hal.ram.bss* object rtl8195a_gpio.o, + section .hal.ram.bss*, + section .timer2_7_vector_table.data*, + section .infra.ram.bss*, + section .mon.ram.bss*, + section .wlan_ram_map* object rom_wlan_ram_map.o, + section .wlan_ram_map*, + section .libc.ram.bss*, + }; + +keep { section .start.ram.data* }; +define block .ram.start.table with fixed order{ section .start.ram.data* }; + +keep { section .image1.validate.rodata* }; +keep { section .infra.ram.data* }; +keep { section .timer.ram.data* }; +keep { section .hal.ram.data* }; +define block .ram_image1.data with fixed order{ section .image1.validate.rodata*, + section .infra.ram.data*, + section .timer.ram.data*, + section .cutb.ram.data*, + section .hal.ram.data* object rom.o, // for standard libaray __impure_data_ptr + section .cutc.ram.data*, + section .hal.ram.data* + }; +define block .ram_image1.bss with fixed order{ //section .hal.flash.data*, + section .hal.sdrc.data* + }; + +define block .ram_image1.text with fixed order{ section .hal.ram.text*, + section .hal.sdrc.text*, + //section .text* object startup.o, + section .infra.ram.text*, + }; + +define block IMAGE1 with fixed order { section LOADER }; +define block IMAGE1_DBG with fixed order { block .ram.start.table, block .ram_image1.data, block .ram_image1.bss, block .ram_image1.text }; + +place at start of ROM_USED_RAM_region { readwrite, + block .vector_table, + block .user_vector_table, + block .user_data_table, + block .rom.bss, + block IMAGE1 + }; + +keep { section .image2.ram.data* }; +define block .image2.start.table1 with fixed order{ section .image2.ram.data* }; + +keep { section .image2.validate.rodata*, section .custom.validate.rodata* }; +define block .image2.start.table2 with fixed order{ section .image2.validate.rodata*, section .custom.validate.rodata* }; + +define block SHT$$PREINIT_ARRAY { preinit_array }; +define block SHT$$INIT_ARRAY { init_array }; +define block CPP_INIT with fixed order { block SHT$$PREINIT_ARRAY, + block SHT$$INIT_ARRAY }; + +define block .ram_image2.text with fixed order{ section .infra.ram.start*, + section .rodata*, + block CPP_INIT, + section .mon.ram.text*, + section .hal.flash.text*, + section .hal.gpio.text*, + section .text*, + section CODE, + section Veneer object startup.o, + section __DLIB_PERTHREAD + }; + +define block .ram.data with fixed order{ section .data*, section DATA, section .iar.init_table }; + +define block IMAGE2 with fixed order { block .image2.start.table1, block .image2.start.table2, block .ram_image2.text, block .ram.data }; + +define block .ram.bss with fixed order{ section .bss*, + section .hal.flash.data*, + section .hal.gpio.data*, + section COMMON, + section .bdsram.data*, + section .bss* object heap_4.o + }; +define block .bf_data with fixed order{ section .bfsram.data* }; +define block .heap with fixed order{ section .heap* }; +define block .stack_dummy with fixed order { section .stack }; +place at start of BD_RAM_region { readwrite, + block IMAGE2, + //block IMAGE1_DBG, + block .ram.bss, + //block .bf_data, + }; + +//place at address mem:0x10052b00 { readwrite, +place at end of BD_RAM_region { readwrite, + block .bf_data, + }; + +define block SDRAM with fixed order{ section .sdram.text*, section .sdram.data*}; +place at start of SDRAM_RAM_region { readwrite, + block SDRAM, + //block IMAGE1_DBG + }; + + +/* TCM placement */ +define overlay TCM_overlay { section .tcm.heap, + section .bss object mem.o, + section .bss object memp.o, + block .heap, + block .stack_dummy + }; +/* dummy code placement */ +define overlay TCM_overlay { block IMAGE1_DBG }; +place at start of TCM_region { readwrite, + overlay TCM_overlay + }; + +define exported symbol __rom_bss_start__ = 0x10000300; // use in rom +define exported symbol __rom_bss_end__ = 0x10000bc8; // use in rom +define exported symbol __ram_start_table_start__= 0x10000bc8; // use in rom +define exported symbol __image1_validate_code__= 0x10000bdc; // needed by ram code +define exported symbol _rtl_impure_ptr = 0x10001c60; // for standard library diff --git a/project/realtek_ameba1_va0_example/EWARM-RELEASE/settings/Project.Debug.cspy.bat b/project/realtek_ameba1_va0_example/EWARM-RELEASE/settings/Project.Debug.cspy.bat new file mode 100644 index 0000000..3c76250 --- /dev/null +++ b/project/realtek_ameba1_va0_example/EWARM-RELEASE/settings/Project.Debug.cspy.bat @@ -0,0 +1,24 @@ +@REM This batch file has been generated by the IAR Embedded Workbench +@REM C-SPY Debugger, as an aid to preparing a command line for running +@REM the cspybat command line utility using the appropriate settings. +@REM +@REM Note that this file is generated every time a new debug session +@REM is initialized, so you may want to move or rename the file before +@REM making changes. +@REM +@REM You can launch cspybat by typing the name of this batch file followed +@REM by the name of the debug file (usually an ELF/DWARF or UBROF file). +@REM +@REM Read about available command line parameters in the C-SPY Debugging +@REM Guide. Hints about additional command line parameters that may be +@REM useful in specific cases: +@REM --download_only Downloads a code image without starting a debug +@REM session afterwards. +@REM --silent Omits the sign-on message. +@REM --timeout Limits the maximum allowed execution time. +@REM + + +"C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.0\common\bin\cspybat" "C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.0\arm\bin\armproc.dll" "C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.0\arm\bin\armJET.dll" %1 --plugin "C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.0\arm\bin\armbat.dll" --macro "D:\ameba_ws2812b\project\realtek_ameba1_va0_example\EWARM-RELEASE\..\..\..\component\soc\realtek\8195a\misc\iar_utility\common\preload.mac" --flash_loader "D:\ameba_ws2812b\project\realtek_ameba1_va0_example\EWARM-RELEASE\tmp.board" --backend -B "--endian=little" "--cpu=Cortex-M3" "--fpu=None" "-p" "D:\ameba_ws2812b\project\realtek_ameba1_va0_example\EWARM-RELEASE\..\..\..\component\soc\realtek\8195a\misc\iar_utility\common\8195a.ddf" "--semihosting=none" "--multicore_nr_of_cores=1" "--jet_probe=cmsisdap" "--jet_standard_reset=4,0,0" "--reset_style="0,-,0,Disabled__no_reset_"" "--reset_style="1,-,0,Software"" "--reset_style="2,-,0,Hardware"" "--reset_style="3,-,0,Core"" "--reset_style="4,-,1,System"" "--jet_interface=SWD" "--drv_restore_breakpoints=main" "--drv_catch_exceptions=0x7f0" + + diff --git a/project/realtek_ameba1_va0_example/EWARM-RELEASE/settings/Project.crun b/project/realtek_ameba1_va0_example/EWARM-RELEASE/settings/Project.crun new file mode 100644 index 0000000..ef39dce --- /dev/null +++ b/project/realtek_ameba1_va0_example/EWARM-RELEASE/settings/Project.crun @@ -0,0 +1,16 @@ + + + + 1 + + + * + * + * + 0 + 1 + + + + + diff --git a/project/realtek_ameba1_va0_example/EWARM-RELEASE/settings/Project.dbgdt b/project/realtek_ameba1_va0_example/EWARM-RELEASE/settings/Project.dbgdt new file mode 100644 index 0000000..e068f91 --- /dev/null +++ b/project/realtek_ameba1_va0_example/EWARM-RELEASE/settings/Project.dbgdt @@ -0,0 +1,5 @@ + + + + + diff --git a/project/realtek_ameba1_va0_example/EWARM-RELEASE/settings/Project.dni b/project/realtek_ameba1_va0_example/EWARM-RELEASE/settings/Project.dni new file mode 100644 index 0000000..229eea4 --- /dev/null +++ b/project/realtek_ameba1_va0_example/EWARM-RELEASE/settings/Project.dni @@ -0,0 +1,49 @@ +[Jet] +JetConnSerialNo=64507 +JetConnFoundProbes= +DisableInterrupts=0 +MultiCoreRunAll=0 +[PlDriver] +FirstRun=0 +MemConfigValue=D:\ameba_ws2812b\project\realtek_ameba1_va0_example\EWARM-RELEASE\..\..\..\component\soc\realtek\8195a\misc\iar_utility\common\8195a.ddf +[Exceptions] +StopOnUncaught=_ 0 +StopOnThrow=_ 0 +[Stack] +FillEnabled=0 +OverflowWarningsEnabled=1 +WarningThreshold=90 +SpWarningsEnabled=1 +WarnLogOnly=1 +UseTrigger=1 +TriggerName=main +LimitSize=0 +ByteLimit=50 +[SWOManager] +SamplingDivider=8192 +OverrideClock=0 +CpuClock=1944140800 +SwoClock=4096 +DataLogMode=0 +ItmPortsEnabled=63 +ItmTermIOPorts=1 +ItmLogPorts=0 +ItmLogFile=$PROJ_DIR$\ITM.log +PowerForcePC=1 +PowerConnectPC=1 +[ArmDriver] +EnableCache=1 +[Log file] +LoggingEnabled=_ 0 +LogFile=_ "" +Category=_ 0 +[TermIOLog] +LoggingEnabled=_ 0 +LogFile=_ "" +[Disassemble mode] +mode=0 +[Breakpoints2] +Count=0 +[Aliases] +Count=0 +SuppressDialog=0 diff --git a/project/realtek_ameba1_va0_example/EWARM-RELEASE/settings/Project.wsdt b/project/realtek_ameba1_va0_example/EWARM-RELEASE/settings/Project.wsdt new file mode 100644 index 0000000..3d82570 --- /dev/null +++ b/project/realtek_ameba1_va0_example/EWARM-RELEASE/settings/Project.wsdt @@ -0,0 +1,77 @@ + + + + + + Project/Debug + + + + + + 201155 + + + + + + + 1990270 + + + + + + + 2086623157 + + + + + + + + + TabID-17985-28802 + Workspace + Workspace + + + ProjectProject/userProject/utilities + + + + 0 + + + TabID-28734-28805 + Debug Log + Debug-Log + + + + TabID-16940-28821 + Build + Build + + + + + 1 + + + + + + 0100000010000001 + + + + + + + iaridepm.enu1-2-2532246-2-2200200164745258065204283689032-2-21981216-2-212182001003295258065164745258065 + + + + diff --git a/project/realtek_ameba1_va0_example/EWARM-RELEASE/settings/Project.wspos b/project/realtek_ameba1_va0_example/EWARM-RELEASE/settings/Project.wspos new file mode 100644 index 0000000..f74a025 --- /dev/null +++ b/project/realtek_ameba1_va0_example/EWARM-RELEASE/settings/Project.wspos @@ -0,0 +1,2 @@ +[MainWindow] +WindowPlacement=_ 185 18 1415 852 1 diff --git a/project/realtek_ameba1_va0_example/EWARM-RELEASE/tmp.board b/project/realtek_ameba1_va0_example/EWARM-RELEASE/tmp.board new file mode 100644 index 0000000..83390fa --- /dev/null +++ b/project/realtek_ameba1_va0_example/EWARM-RELEASE/tmp.board @@ -0,0 +1,21 @@ + + + + + CODE 0x10000bc8 0x10003FFF + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\misc\iar_utility\common\flashloader\FlashRTL8195aMP.flash + 0x00000000 + --head + --img2_addr + 0xB000 + + + CODE 0x10004000 0x10046EA7 + $PROJ_DIR$\..\..\..\component\soc\realtek\8195a\misc\iar_utility\common\flashloader\FlashRTL8195aMP.flash + 0xB000 + + CODE 0x00000000 0x000FFFFF + CODE 0x10000000 0x10000bc7 + CODE 0x10046ea8 0x1006FFFF + CODE 0x1FFF0000 0x1FFFFFFF + diff --git a/project/realtek_ameba1_va0_example/example_sources/analogin_voltage/readme.txt b/project/realtek_ameba1_va0_example/example_sources/analogin_voltage/readme.txt new file mode 100644 index 0000000..a68f1cd --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/analogin_voltage/readme.txt @@ -0,0 +1,23 @@ +Example Description + +This example describes how to use ADC. + + +1.Prepare a DC power supply to provide a adjustable voltage. + +2.Connect anode to HDK board A3, and cathode to GND + +3.Run the main function. + +4.Will see result like below + +AD1:00008049 = 1644 mv, AD2:00002a75 = 17 mv, AD3:00002a94 = 20 mv + + +NOTE: + 1. For 8195AM EVB, A0 and A1 are hardware connected. A2 is also available. + For 8711AM EVB, A0 and A1 are not available. Only A2 is avaliable. + 2. ADC need calibration to get correct voltage value by modifing OFFSET and GAIN_DIV. + + + diff --git a/project/realtek_ameba1_va0_example/example_sources/analogin_voltage/src/main.c b/project/realtek_ameba1_va0_example/example_sources/analogin_voltage/src/main.c new file mode 100644 index 0000000..2f91bb8 --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/analogin_voltage/src/main.c @@ -0,0 +1,85 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#include "device.h" +#include "analogin_api.h" +#include + +#define ADC_CALIBRATION 0 +#define MBED_ADC_EXAMPLE_PIN_1 AD_1 // no pin out +#define MBED_ADC_EXAMPLE_PIN_2 AD_2 // HDK, A1 +#define MBED_ADC_EXAMPLE_PIN_3 AD_3 // HDK, A2 + +#if defined (__ICCARM__) +analogin_t adc0; +analogin_t adc1; +analogin_t adc2; +#else +volatile analogin_t adc0; +volatile analogin_t adc1; +volatile analogin_t adc2; +#endif + +void adc_delay(void) +{ + int i; + for(i=0;i<1600000;i++) + asm(" nop"); +} + +uint16_t adcdat0 = 0; +uint16_t adcdat1 = 0; +uint16_t adcdat2 = 0; + +int32_t v_mv0; +int32_t v_mv1; +int32_t v_mv2; + +/* + * OFFSET: value of measuring at 0.000v, value(0.000v) + * GAIN_DIV: value(1.000v)-value(0.000v) or value(2.000v)-value(1.000v) or value(3.000v)-value(2.000v) + * + * MSB 12bit of value is valid, need to truncate LSB 4bit (0xABCD -> 0xABC). OFFSET and GAIN_DIV are truncated values. + */ +#define OFFSET 0x298 +#define GAIN_DIV 0x34C +#define AD2MV(ad,offset,gain) (((ad/16)-offset)*1000/gain) + +VOID +main ( + VOID +) +{ + uint16_t offset, gain; + analogin_init(&adc0, MBED_ADC_EXAMPLE_PIN_1); // no pinout on HDK board + analogin_init(&adc1, MBED_ADC_EXAMPLE_PIN_2); + analogin_init(&adc2, MBED_ADC_EXAMPLE_PIN_3); +#if ADC_CALIBRATION + sys_adc_calibration(0, &offset, &gain); + printf("ADC:offset = 0x%x, gain = 0x%x\n", offset, gain); + if((offset==0xFFFF) || (gain==0xFFFF)) +#endif + { + offset = OFFSET; + gain = GAIN_DIV; + printf("ADC:offset = 0x%x, gain = 0x%x\n", offset, gain); + } + for (;;){ + adcdat0 = analogin_read_u16(&adc0); + adcdat1 = analogin_read_u16(&adc1); + adcdat2 = analogin_read_u16(&adc2); + + v_mv0 = AD2MV(adcdat0, offset, gain); + v_mv1 = AD2MV(adcdat1, offset, gain); + v_mv2 = AD2MV(adcdat2, offset, gain); + + printf("AD0:%x = %d mv, AD1:%x = %d mv, AD2:%x = %d mv\n", adcdat0, v_mv0, adcdat1, v_mv1, adcdat2, v_mv2); + adc_delay(); + } +} diff --git a/project/realtek_ameba1_va0_example/example_sources/crypto/readme.txt b/project/realtek_ameba1_va0_example/example_sources/crypto/readme.txt new file mode 100644 index 0000000..4641d8e --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/crypto/readme.txt @@ -0,0 +1,7 @@ +Example Description + +This example describes how to use CRYPTO function + +use Arduino board to test, and it will show at console + + diff --git a/project/realtek_ameba1_va0_example/example_sources/crypto/src/main.c b/project/realtek_ameba1_va0_example/example_sources/crypto/src/main.c new file mode 100644 index 0000000..2234ea1 --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/crypto/src/main.c @@ -0,0 +1,264 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#include "device.h" +#include "serial_api.h" +#include "hal_crypto.h" +#include "main.h" +#include "diag.h" + + +//static const u8 plaintext[] = "The quick brown fox jumps over the lazy dog"; +//static const u8 md5_digest[] = "\x9e\x10\x7d\x9d\x37\x2b\xb6\x82" +// "\x6b\xd8\x1d\x35\x42\xa4\x19\xd6"; +//static const u8 md5_key[] = "key"; + +static const char plaintext[] = "12345678901234567890123456789012345678901234567890123456789012" \ + "345678901234567890"; +static const char md5_digest[] = { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55, + 0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A }; +static const u8 md5_key[] = "key"; + +static unsigned char md5_test_buf[16][81] = +{ + { "" }, + { "a" }, + { "abc" }, + { "message digest" }, + { "abcdefghijklmnopqrstuvwxyz" }, + { "The quick brown fox jumps over the lazy dog" }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, + { "12345678901234567890123456789012345678901234567890123456789012" \ + "345678901234567890" }, + { "" }, + { "a" }, + { "abc" }, + { "message digest" }, + { "abcdefghijklmnopqrstuvwxyz" }, + { "The quick brown fox jumps over the lazy dog" }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, + { "12345678901234567890123456789012345678901234567890123456789012" \ + "345678901234567890" } +}; + +static const int md5_test_buflen[16] = +{ + 0, 1, 3, 14, 26, 43, 62, 80, 0, 1, 3, 14, 26, 43, 62, 80 +}; + +static const unsigned char md5_test_sum[16][16] = +{ + { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04, + 0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E }, + { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8, + 0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 }, + { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0, + 0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 }, + { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D, + 0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 }, + { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00, + 0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B }, + {"\x9e\x10\x7d\x9d\x37\x2b\xb6\x82" + "\x6b\xd8\x1d\x35\x42\xa4\x19\xd6"}, + { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5, + 0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F }, + { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55, + 0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A }, + { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04, + 0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E }, + { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8, + 0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 }, + { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0, + 0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 }, + { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D, + 0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 }, + { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00, + 0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B }, + {"\x9e\x10\x7d\x9d\x37\x2b\xb6\x82" + "\x6b\xd8\x1d\x35\x42\xa4\x19\xd6"}, + { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5, + 0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F }, + { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55, + 0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A } + +}; + + + + +u8 digest[64]; +u8 cipher_result[1024]; + +serial_t sobj; + +void test_md5(void) +{ + int i; + int ret; + u8 md5sum[16]; + + DiagPrintf("MD5 test\r\n"); + + ret = rtl_crypto_md5(plaintext, strlen(plaintext), (unsigned char *)&digest); // the length of MD5's digest is 16 bytes. + + if ( rtl_memcmpb(digest, md5_digest, 16) == 0 ) { + DiagPrintf("MD5 test result is correct, ret=%d\r\n", ret); + } else { + DiagPrintf("MD5 test result is WRONG!!, ret=%d\r\n", ret); + } + + for( i = 0; i < 16; i++ ) + { + DiagPrintf( " MD5 test #%d: ", i + 1 ); + ret = rtl_crypto_md5(md5_test_buf[i], md5_test_buflen[i], md5sum); // the length of MD5's digest is 16 bytes. + DiagPrintf(" MD5 ret=%d\n", ret); + if( rtl_memcmpb( md5sum, md5_test_sum[i], 16 ) != 0 ) + { + DiagPrintf( "failed\n" ); + memset(md5sum,0,16); + } + else{ + DiagPrintf( "passed\n" ); + memset(md5sum,0,16);} + } + + +} + + +// +// vector : AES CBC 128 bit : +// http://www.inconteam.com/software-development/41-encryption/55-aes-test-vectors#aes-cbc-128 +// + +#ifdef __ICCARM__ +#pragma data_alignment = 4 +#elif defined (__GNUC__) +__attribute__ ((aligned (4))) +#endif +static const unsigned char aes_test_key[16] = +{ + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c +} ; + +#ifdef __ICCARM__ +#pragma data_alignment = 4 +#elif defined (__GNUC__) +__attribute__ ((aligned (4))) +#endif +static const unsigned char aes_test_iv_1[16] = +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F +}; + + + +static const unsigned char aes_test_buf[16] = +{ + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a +}; + + + +static const unsigned char aes_test_res_128[16] = +{ + 0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, + 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d +}; + + + + +int test_aes_cbc(void) +{ + const u8 *key, *pIv; + u32 keylen= 0; + u32 ivlen = 0; + u8 *message; + u32 msglen; + u8 *pResult; + + int ret; + + DiagPrintf("AES CBC test\r\n"); + + key = aes_test_key; + keylen = 16; + pIv = aes_test_iv_1; + ivlen = 16; + + pResult = cipher_result; + + message = (unsigned char *)aes_test_buf; + msglen = sizeof(aes_test_buf); + ret = rtl_crypto_aes_cbc_init(key,keylen); + if ( ret != 0 ) { + DiagPrintf("AES CBC init failed\r\n"); + return ret; + } + + ret = rtl_crypto_aes_cbc_encrypt(message, msglen, pIv, ivlen, pResult); + if ( ret != 0 ) { + DiagPrintf("AES CBC encrypt failed\r\n"); + return ret; + } + + if ( rtl_memcmpb(aes_test_res_128, pResult, msglen) == 0 ) { + DiagPrintf("AES CBC encrypt result success\r\n"); + } else { + DiagPrintf("AES CBC encrypt result failed\r\n"); + } + + message = pResult; + + ret = rtl_crypto_aes_cbc_decrypt(message, msglen, pIv, ivlen, pResult); + if ( ret != 0 ) { + DiagPrintf("AES CBC decrypt failed, ret=%d\r\n", ret); + return ret; + } + + if ( rtl_memcmpb(aes_test_buf, pResult, msglen) == 0 ) { + DiagPrintf("AES CBC decrypt result success\r\n"); + } else { + DiagPrintf("AES CBC decrypt result failed\r\n"); + } + + return 0; +} + +void main(void) +{ + // sample text + char rc; + // + int ret; + int loop=0; + + + // + + DiagPrintf("sleep 10 sec. to wait for UART console\n"); + //RtlMsleepOS(10000); + + DiagPrintf("CRYPTO API Demo...\r\n"); + + if ( rtl_cryptoEngine_init() != 0 ) { + DiagPrintf("crypto engine init failed\r\n"); + } + + test_md5(); + test_aes_cbc(); + + for(;;); + +} + diff --git a/project/realtek_ameba1_va0_example/example_sources/flash/readme.txt b/project/realtek_ameba1_va0_example/example_sources/flash/readme.txt new file mode 100644 index 0000000..b5b9a92 --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/flash/readme.txt @@ -0,0 +1,8 @@ +Example Description + +This example read a specific flash offset, modify it and re-read again. + +Requirement Components: + None + + diff --git a/project/realtek_ameba1_va0_example/example_sources/flash/src/main.c b/project/realtek_ameba1_va0_example/example_sources/flash/src/main.c new file mode 100644 index 0000000..5486678 --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/flash/src/main.c @@ -0,0 +1,32 @@ +#include "diag.h" +#include "main.h" + +#include "objects.h" +#include "flash_api.h" + +// Decide starting flash address for storing application data +// User should pick address carefully to avoid corrupting image section +#define FLASH_APP_BASE 0x7E000 + +void main(void) +{ + flash_t flash; + uint32_t val32_to_write = 0x13572468; + uint32_t val32_to_read; + uint32_t address = FLASH_APP_BASE; + + int result = 0; + + flash_read_word(&flash, address, &val32_to_read); + flash_erase_sector(&flash, address); + flash_write_word(&flash, address, val32_to_write); + flash_read_word(&flash, address, &val32_to_read); + + DBG_8195A("Read Data 0x%x\n", val32_to_read); + + // verify result + result = (val32_to_write == val32_to_read) ? 1 : 0; + printf("\r\nResult is %s\r\n", (result) ? "success" : "fail"); + + for(;;); +} \ No newline at end of file diff --git a/project/realtek_ameba1_va0_example/example_sources/gdma/src/main.c b/project/realtek_ameba1_va0_example/example_sources/gdma/src/main.c new file mode 100644 index 0000000..d68b403 --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/gdma/src/main.c @@ -0,0 +1,60 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2015 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#include "device.h" +#include "diag.h" +#include "main.h" + +#include "dma_api.h" + +#define DMA_CPY_LEN 256 +#define DMA_SRC_OFFSET 0 +#define DMA_DST_OFFSET 0 + +gdma_t gdma; +uint8_t TestBuf1[512]; +uint8_t TestBuf2[512]; +volatile uint8_t dma_done; + + +void dma_done_handler(uint32_t id) { + DiagPrintf("DMA Copy Done!!\r\n"); + dma_done = 1; +} + +void main(void) { + int i; + int err; + + dma_memcpy_init(&gdma, dma_done_handler, (uint32_t)&gdma); + for (i=0;i< 512;i++) { + TestBuf1[i] = i; + } + _memset(TestBuf2, 0xff, 512); + + dma_done = 0; + dma_memcpy(&gdma, TestBuf2+DMA_DST_OFFSET, TestBuf1+DMA_SRC_OFFSET, DMA_CPY_LEN); + + while (dma_done == 0); + + err = 0; + for (i=0;i\n", __FUNCTION__); + gpio_led = (gpio_t *)id; + + led_ctrl = !led_ctrl; + gpio_write(gpio_led, led_ctrl); +} + +/** + * @brief Main program. + * @param None + * @retval None + */ +void main(void) +{ + gpio_irq_t gpio_btn; + + // Init LED control pin + gpio_init(&gpio_led, GPIO_LED_PIN); + gpio_dir(&gpio_led, PIN_OUTPUT); // Direction: Output + gpio_mode(&gpio_led, PullNone); // No pull + + // Initial Push Button pin as interrupt source + gpio_irq_init(&gpio_btn, GPIO_IRQ_PIN, gpio_demo_irq_handler, (uint32_t)(&gpio_led)); + gpio_irq_set(&gpio_btn, IRQ_FALL, 1); // Falling Edge Trigger + gpio_irq_enable(&gpio_btn); + + led_ctrl = 1; + gpio_write(&gpio_led, led_ctrl); + + while(1); +} + diff --git a/project/realtek_ameba1_va0_example/example_sources/gpio_port/readme.txt b/project/realtek_ameba1_va0_example/example_sources/gpio_port/readme.txt new file mode 100644 index 0000000..ddfa7b0 --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/gpio_port/readme.txt @@ -0,0 +1,9 @@ +Example Description + +This example describes how to use GPIO Port read/write by mbed api. + +Requirement Components: + 8 LEDs + 2 bords + + diff --git a/project/realtek_ameba1_va0_example/example_sources/gpio_port/src/main.c b/project/realtek_ameba1_va0_example/example_sources/gpio_port/src/main.c new file mode 100644 index 0000000..e8fa1bd --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/gpio_port/src/main.c @@ -0,0 +1,82 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#include "device.h" +#include "port_api.h" // mbed +#include "PortNames.h" // mbed +#include "main.h" + +#define PORT_OUTPUT_TEST 1 //1: output test, 0: input test + +#define LED_PATTERN_NUM 12 +port_t port0; +const uint8_t led_pattern[LED_PATTERN_NUM]={0x81, 0x42, 0x24, 0x18, 0x00, 0x88, 0x44, 0x22, 0x11, 0xff, 0x00}; + +extern void wait_ms(u32); + +/** + * @brief Main program. + * @param None + * @retval None + */ +#if PORT_OUTPUT_TEST + +void main(void) +{ + int i; + + port_mode(&port0, PullNone); + // Only PortA or PortB is available now + port_init(&port0, PortA, 0xFF, PIN_OUTPUT); + + while(1){ + for (i=0;i +#include "timer_api.h" +#include "main.h" + + +#define SW_RTC_TIMER_ID TIMER5 + +static gtimer_t sw_rtc; +static volatile struct tm rtc_timeinfo; + +const static u8 dim[14] = { + 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31, 28 }; + +static inline bool is_leap_year(unsigned int year) +{ + return (!(year % 4) && (year % 100)) || !(year % 400); +} + + +static u8 days_in_month (u8 month, u8 year) +{ + u8 ret = dim [ month - 1 ]; + if (ret == 0) + ret = is_leap_year (year) ? 29 : 28; + return ret; +} + +static void sw_rtc_tick_handler(uint32_t id) +{ + if(++rtc_timeinfo.tm_sec > 59) { // Increment seconds, check for overflow + rtc_timeinfo.tm_sec = 0; // Reset seconds + if(++rtc_timeinfo.tm_min > 59) { // Increment minutes, check for overflow + rtc_timeinfo.tm_min = 0; // Reset minutes + if(++rtc_timeinfo.tm_hour > 23) { // Increment hours, check for overflow + rtc_timeinfo.tm_hour = 0; // Reset hours + ++rtc_timeinfo.tm_yday; // Increment day of year + if(++rtc_timeinfo.tm_wday > 6) // Increment day of week, check for overflow + rtc_timeinfo.tm_wday = 0; // Reset day of week + // Increment day of month, check for overflow + if(++rtc_timeinfo.tm_mday > + days_in_month(rtc_timeinfo.tm_mon, rtc_timeinfo.tm_year)) { + rtc_timeinfo.tm_mday = 1; // Reset day of month + if(++rtc_timeinfo.tm_mon > 11) { // Increment month, check for overflow + rtc_timeinfo.tm_mon = 0; // Reset month + rtc_timeinfo.tm_yday = 0; // Reset day of year + ++rtc_timeinfo.tm_year; // Increment year + } // - year + } // - month + } // - day + } // - hour + } +} + +static void rtc_init(void) +{ + // Initial a periodical timer + gtimer_init(&sw_rtc, SW_RTC_TIMER_ID); + + // Tick every 1 sec + gtimer_start_periodical(&sw_rtc, 1000000, (void*)sw_rtc_tick_handler, (uint32_t)&sw_rtc); +} + +static void rtc_deinit(void) +{ + gtimer_stop(&sw_rtc); + gtimer_deinit(&sw_rtc); +} + +static void rtc_set_time(uint32_t year, uint8_t mon, uint8_t mday, uint8_t wday, + uint8_t hour, uint8_t min, uint8_t sec) +{ + int i; + + gtimer_stop(&sw_rtc); + rtc_timeinfo.tm_sec = sec; + rtc_timeinfo.tm_min = min; + rtc_timeinfo.tm_hour = hour; + rtc_timeinfo.tm_mday = mday-1; + rtc_timeinfo.tm_wday = wday-1; + rtc_timeinfo.tm_yday = 0; + for (i=0;i<(mon-1);i++) { + rtc_timeinfo.tm_yday += days_in_month(i,year); + } + rtc_timeinfo.tm_yday += (mday-1); + rtc_timeinfo.tm_mon = mon-1; + rtc_timeinfo.tm_year = year; + gtimer_start(&sw_rtc); +} + +static void rtc_read_time(struct tm *timeinfo) +{ + _memcpy((void*)timeinfo, (void*)&rtc_timeinfo, sizeof(struct tm)); + timeinfo->tm_mon++; + timeinfo->tm_mday++; + timeinfo->tm_wday++; + timeinfo->tm_yday++; +} + +void main(void) +{ + struct tm timeinfo; + + rtc_init(); + + // Give RTC a initial value: 2015/4/15 (Wed) 12:00:00 + rtc_set_time(2015, 4, 15, 3, 12, 0, 0); + + while (1) { + rtc_read_time(&timeinfo); + DBG_8195A("%d-%d-%d[%d] %d:%d:%d\r\n", timeinfo.tm_year, timeinfo.tm_mon, timeinfo.tm_mday, + timeinfo.tm_wday, timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec); + wait_ms(1000); + } + rtc_deinit(); +} + diff --git a/project/realtek_ameba1_va0_example/example_sources/i2c-shtc1/readme.txt b/project/realtek_ameba1_va0_example/example_sources/i2c-shtc1/readme.txt new file mode 100644 index 0000000..d86024b --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/i2c-shtc1/readme.txt @@ -0,0 +1,16 @@ +Example Description + +This example describes how to use i2c by using mbed api + +Requirement Components: + extend board + +work with arduino extended board, which has SHTC1 temperature and humidity +sensor + +Connect + - I2C3 SDA (PB_3) to extended board's SDA + - I2C3 SCL (PB_2) to extended board's SCL + + + diff --git a/project/realtek_ameba1_va0_example/example_sources/i2c-shtc1/src/main.c b/project/realtek_ameba1_va0_example/example_sources/i2c-shtc1/src/main.c new file mode 100644 index 0000000..691bed7 --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/i2c-shtc1/src/main.c @@ -0,0 +1,209 @@ + +#include "device.h" +#include "PinNames.h" + +#include "basic_types.h" +#include "diag.h" +#include "osdep_api.h" + +#include "i2c_api.h" +#include "pinmap.h" +//#include "rtl_lib.h" + +#define NO_ERROR 0x00 +#define ACK_ERROR 0x01 +#define CHECKSUM_ERROR 0x02 +#define NULL_ERROR 0x03 + +#define MBED_I2C_MTR_SDA PB_3 +#define MBED_I2C_MTR_SCL PB_2 + +#define MBED_I2C_SLAVE_ADDR0 0x70 +#define POLYNOMIAL 0x131 // P(x) = x^8 + x^5 + x^4 + 1 = 100110001 + + +#define MBED_I2C_BUS_CLK 100000 //hz +#define I2C_DATA_MAX_LENGTH 16 + +uint8_t i2cdata_write[I2C_DATA_MAX_LENGTH]; +uint8_t i2cdata_read[I2C_DATA_MAX_LENGTH]; +int i2cdata_read_pos; + +i2c_t i2cmaster; + + +// Sensor Commands +#define READ_ID 0xEFC8 // command: read ID register +#define SOFT_RESET 0x805D // soft resetSample Code for SHTC1 +#define MEAS_T_RH_POLLING 0x7866 // meas. read T first, clock stretching disabled +#define MEAS_T_RH_CLOCKSTR 0x7CA2 // meas. read T first, clock stretching enabled +#define MEAS_RH_T_POLLING 0x58E0 // meas. read RH first, clock stretching disabled +#define MEAS_RH_T_CLOCKSTR 0x5C24 // meas. read RH first, clock stretching enabled + + +static int SHTC1_GetID(uint16_t *id); +static void SHTC1_WriteCommand(uint16_t cmd); +static int SHTC1_Read2BytesAndCrc(uint16_t *data); +static int SHTC1_CheckCrc(uint8_t data[], uint8_t nbrOfBytes, uint8_t checksum); +static float SHTC1_CalcTemperature(uint16_t rawValue); +static float SHTC1_CalcHumidity(uint16_t rawValue); + + +int SHTC1_Init(uint16_t *pID) +{ + int error = NO_ERROR; + + DiagPrintf("SHTC1_Init \r\n"); + + i2c_init((i2c_t*)&i2cmaster, MBED_I2C_MTR_SDA ,MBED_I2C_MTR_SCL); + i2c_frequency((i2c_t*)&i2cmaster,MBED_I2C_BUS_CLK); + + if (pID == NULL ) return NULL_ERROR; + + + error = SHTC1_GetID(pID); + return error; +} + +static int SHTC1_GetID(uint16_t *id) +{ + int error = NO_ERROR; + uint8_t bytes[2]; + uint8_t checksum; + + SHTC1_WriteCommand(READ_ID); + + i2c_read((i2c_t*)&i2cmaster, MBED_I2C_SLAVE_ADDR0, (char*)&i2cdata_read[0], 3, 1); + i2cdata_read_pos = 0; + error = SHTC1_Read2BytesAndCrc(id); + + return error; +} + +static int SHTC1_Read2BytesAndCrc(uint16_t *data) +{ + int error; + int readed; + uint8_t bytes[2]; + uint8_t checksum; + + + + bytes[0] = i2cdata_read[i2cdata_read_pos++]; + bytes[1] = i2cdata_read[i2cdata_read_pos++]; + checksum = i2cdata_read[i2cdata_read_pos++]; + + error = SHTC1_CheckCrc(bytes, 2, checksum); + *data = (bytes[0] << 8) | bytes[1]; + + return error; +} + +static int SHTC1_CheckCrc(uint8_t data[], uint8_t nbrOfBytes, uint8_t checksum) +{ + uint8_t bit; // bit mask + uint8_t crc = 0xFF; // calculated checksum + uint8_t byteCtr; // byte counter + + // calculates 8-Bit checksum with given polynomial + for(byteCtr = 0; byteCtr < nbrOfBytes; byteCtr++) + { + crc ^= (data[byteCtr]); + for(bit = 8; bit > 0; --bit) + { + if(crc & 0x80) crc = (crc << 1) ^ POLYNOMIAL; + else crc = (crc << 1); + } + } + + // verify checksum + if(crc != checksum) return CHECKSUM_ERROR; + else return NO_ERROR; +} + + +static void SHTC1_WriteCommand(uint16_t cmd) +{ + int writebytes; + + i2cdata_write[0] = (uint8_t)(cmd >>8); + i2cdata_write[1] = (uint8_t)(cmd&0xFF); + i2c_write((i2c_t*)&i2cmaster, MBED_I2C_SLAVE_ADDR0, &i2cdata_write[0], 2, 1); +} + +static float SHTC1_CalcTemperature(uint16_t rawValue) +{ + return 175.0 * (float)rawValue / 65536.0 - 45.0; +} + +static float SHTC1_CalcHumidity(uint16_t rawValue) +{ + return 100.0 * (float)rawValue / 65536.0; +} + +int SHTC1_GetTempAndHumi(float *temp, float *humi) +{ + int error; + uint16_t rawValueTemp; + uint16_t rawValueHumi; + + SHTC1_WriteCommand(MEAS_T_RH_CLOCKSTR); + + //Wire1.requestFrom(I2C_ADR_SHTC1, 6); + i2c_read((i2c_t*)&i2cmaster, MBED_I2C_SLAVE_ADDR0, (char*)&i2cdata_read[0], 6, 1); + i2cdata_read_pos = 0; + error = NO_ERROR; + error |= SHTC1_Read2BytesAndCrc(&rawValueTemp); + error |= SHTC1_Read2BytesAndCrc(&rawValueHumi); + + //diag_printf("raw temp=0x%x, raw humidity=0x%x, error=%d\n", + // rawValueTemp, rawValueHumi, error); + + if ( error == NO_ERROR ) { + *temp = SHTC1_CalcTemperature(rawValueTemp); + *humi = SHTC1_CalcHumidity(rawValueHumi); + } + + return error; +} + + +void main(void) +{ + gpio_t gpio_led; + int led_status; + int i2clocalcnt; + int error; + uint16_t shtc1_id; + + float temperature = 1.123f; + float humidity = 2.456f; + + + DBG_8195A("sleep 10 sec. to wait for UART console\n"); + RtlMsleepOS(10000); + + + DBG_8195A("start i2c example - SHTC1\n"); + + + error = SHTC1_Init(&shtc1_id); + if ( error == NO_ERROR ) { + DiagPrintf("SHTC1 init ok, id=0x%x\r\n", shtc1_id); + } else { + DiagPrintf("SHTC1 init FAILED! \r\n"); + for(;;); + } + + + while(1){ + error = SHTC1_GetTempAndHumi(&temperature, &humidity); + + rtl_printf("temp=%f, humidity=%f, error=%d\n", + temperature, humidity, error); + + RtlMsleepOS(1000); + + } +} + diff --git a/project/realtek_ameba1_va0_example/example_sources/i2c/readme.txt b/project/realtek_ameba1_va0_example/example_sources/i2c/readme.txt new file mode 100644 index 0000000..065eb44 --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/i2c/readme.txt @@ -0,0 +1,14 @@ +Example Description + +This example describes how to use i2c by using mbed api + +1.Connect LOG-UART connector to PC + +2.Connect + - I2C3 SDA (PB_3) to I2C1 SDA (PC_4) pin, + - I2C3 SCL (PB_2) to I2C1 SCL (PC_5) pin. + +3.Run the main function. + +4.Get the Master and Slave Data. + diff --git a/project/realtek_ameba1_va0_example/example_sources/i2c/src/main.c b/project/realtek_ameba1_va0_example/example_sources/i2c/src/main.c new file mode 100644 index 0000000..db82018 --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/i2c/src/main.c @@ -0,0 +1,80 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#include "PinNames.h" +#include "basic_types.h" +#include "diag.h" +#include + +#include "i2c_api.h" +#include "pinmap.h" + +#if 1 +#define MBED_I2C_MTR_SDA PB_3 +#define MBED_I2C_MTR_SCL PB_2 + +#define MBED_I2C_SLV_SDA PC_4 +#define MBED_I2C_SLV_SCL PC_5 +#endif + +#define MBED_I2C_SLAVE_ADDR0 0xAA +#define MBED_I2C_BUS_CLK 100000 //hz + +#define I2C_DATA_LENGTH 8 +const char i2cdatasrc[I2C_DATA_LENGTH] = { 0x55, 0xAA, 0x5A, 0xA5, + 0xFF, 0x11, 0x00, 0xF1 }; +char i2cdatadst[I2C_DATA_LENGTH]; + +#if defined (__ICCARM__) +i2c_t i2cmaster; +i2c_t i2cslave; +#else +volatile i2c_t i2cmaster; +volatile i2c_t i2cslave; +#endif + +void main(void) +{ + int i2clocalcnt; + + int result = 0; + + i2c_init(&i2cmaster, MBED_I2C_MTR_SDA ,MBED_I2C_MTR_SCL); + i2c_frequency(&i2cmaster,MBED_I2C_BUS_CLK); + + i2c_init(&i2cslave, MBED_I2C_SLV_SDA ,MBED_I2C_SLV_SCL); + i2c_frequency(&i2cslave,MBED_I2C_BUS_CLK); + i2c_slave_address(&i2cslave, 0, MBED_I2C_SLAVE_ADDR0, 0xFF); + i2c_slave_mode(&i2cslave, 1); + + i2c_write(&i2cmaster, MBED_I2C_SLAVE_ADDR0, &i2cdatasrc[0], I2C_DATA_LENGTH, 1); + + DBG_8195A("master write...\n"); + + if (i2c_slave_receive(&i2cslave) == 3) { + i2c_slave_read(&i2cslave, &i2cdatadst[0], I2C_DATA_LENGTH); + } + + DBG_8195A("show slave received data\n"); + for (i2clocalcnt = 0; i2clocalcnt < I2C_DATA_LENGTH; i2clocalcnt+=2) { + DBG_8195A("i2c data: %02x \t %02x\n",i2cdatadst[i2clocalcnt],i2cdatadst[i2clocalcnt+1]); + } + + // verify result + result = 1; + for (i2clocalcnt = 0; i2clocalcnt < I2C_DATA_LENGTH; i2clocalcnt++) { + if (i2cdatasrc[i2clocalcnt] != i2cdatadst[i2clocalcnt]) { + result = 0; + break; + } + } + printf("\r\nResult is %s\r\n", (result) ? "success" : "fail"); + + while(1){;} +} diff --git a/project/realtek_ameba1_va0_example/example_sources/i2c_epl2197_heartrate/inc/HRM_2197.h b/project/realtek_ameba1_va0_example/example_sources/i2c_epl2197_heartrate/inc/HRM_2197.h new file mode 100644 index 0000000..2a44710 --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/i2c_epl2197_heartrate/inc/HRM_2197.h @@ -0,0 +1,77 @@ +/******************************************************************************* + HRM.h - Definition header + *******************************************************************************/ +#ifndef HRM_H +#define HRM_H + +#include + +//------------------------------------------------------ +#define HR_SAMPLE_RATE 25// Hz +#define HR_INTEG_MIN HR_INTEG_40 +#define HR_INTEG_BASE HR_INTEG_250 +#define HR_INTEG_MAX HR_INTEG_250 + +#define HR_TH_HIGH 63000 +#define HR_TH_LOW 30000 +//------------------------------------------------------ + +// HRM I2C address & register sub-addresses +#define HR_SLAVE_ADDRESS 0x82 + +#define HR_FILTER_1 0<<5 +#define HR_FILTER_2 1<<5 +#define HR_FILTER_4 2<<5 +#define HR_FILTER_8 3<<5 +#define HR_FILTER_16 4<<5 +#define HR_FILTER_32 5<<5 +#define HR_FILTER_64 6<<5 +#define HR_FILTER_128 7<<5 + +#define HR_MODE_HR 1<<4 +#define HR_MODE_HRS 9<<4 + +#define HR_GAIN_MID 1 +#define HR_GAIN_LOW 3 + +#define HR_INTEG_20 5 +#define HR_INTEG_25 6 +#define HR_INTEG_30 7 +#define HR_INTEG_40 8 +#define HR_INTEG_55 9 +#define HR_INTEG_70 10 +#define HR_INTEG_90 11 +#define HR_INTEG_110 12 +#define HR_INTEG_150 13 +#define HR_INTEG_200 14 +#define HR_INTEG_250 15 +#define HR_INTEG_350 16 +#define HR_INTEG_450 17 +#define HR_INTEG_550 18 + +#define HR_OSR_64 0<<2 +#define HR_OSR_256 1<<2 +#define HR_OSR_1024 2<<2 +#define HR_OSR_2048 3<<2 + +#define HR_RESETN_RESET 0<<2 +#define HR_RESETN_RUN 1<<2 + +#define HR_PDRIVE_70MA 0<<4 +#define HR_PDRIVE_35MA 1<<4 +#define HR_PDRIVE_200MA 2<<4 +#define HR_PDRIVE_100MA 3<<4 + +#define HR_INT_FRAME 1<<2 +#define HR_INT_DISABLED 2<<2 + +#define HR_IR_DISABLE 0<<7 +#define HR_IR_ENABLE 1<<7 + +//------------------------------------------------------ + +// Declarations +void init_hrm(void); +uint16_t read_hrm(void); + +#endif /* HRM_H */ diff --git a/project/realtek_ameba1_va0_example/example_sources/i2c_epl2197_heartrate/inc/heart_interface.h b/project/realtek_ameba1_va0_example/example_sources/i2c_epl2197_heartrate/inc/heart_interface.h new file mode 100644 index 0000000..52d569c --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/i2c_epl2197_heartrate/inc/heart_interface.h @@ -0,0 +1,39 @@ +/* + * heart_interface.h + * + * Created on: 2014/4/29 + * Author: 01004 + */ + +#ifndef HEART_INTERFACE_H_ +#define HEART_INTERFACE_H_ + +#define MIN_HEART_RATE 48 +#define MAX_HEART_RATE 180 + +extern int g_heartrate; + +typedef void (*hr_callback)(int); + +/* + * If there is no g-sensor, fill x, y, z in 0. + */ +void add_PPG_XYZ(int ppg, short xx, short yy, short zz); + +/* + * A callback to handle heartrate events. + */ +void register_callback(hr_callback callback); + +/* + * Ex: report_period = 25. + * it means report a heart rate every 25 samples. + */ +void start(int report_period); + +void reset(void); + +void stop(void); + + +#endif /* HEART_INTERFACE_H_ */ diff --git a/project/realtek_ameba1_va0_example/example_sources/i2c_epl2197_heartrate/readme.txt b/project/realtek_ameba1_va0_example/example_sources/i2c_epl2197_heartrate/readme.txt new file mode 100644 index 0000000..b77b22d --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/i2c_epl2197_heartrate/readme.txt @@ -0,0 +1,16 @@ +Example Description + +this example is use to measure heart rate of human + +Requirement Components: + extend board + +work with arduino extended board, which has heart rate sensor + +during the measurement, user has to lie his pulp on the sensor and do not rock the sensor + +the test code will return back the heart rate + +Build code +1. Please be sure to copy inc\heart_interface.h, inc\HRM_2197.h +2. Include hr_library.a in IAR project. Add hr_library.a into folder "lib" in IAR project. \ No newline at end of file diff --git a/project/realtek_ameba1_va0_example/example_sources/i2c_epl2197_heartrate/src/hr_library.a b/project/realtek_ameba1_va0_example/example_sources/i2c_epl2197_heartrate/src/hr_library.a new file mode 100644 index 0000000..0a35b6a Binary files /dev/null and b/project/realtek_ameba1_va0_example/example_sources/i2c_epl2197_heartrate/src/hr_library.a differ diff --git a/project/realtek_ameba1_va0_example/example_sources/i2c_epl2197_heartrate/src/main.c b/project/realtek_ameba1_va0_example/example_sources/i2c_epl2197_heartrate/src/main.c new file mode 100644 index 0000000..0504220 --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/i2c_epl2197_heartrate/src/main.c @@ -0,0 +1,162 @@ +/******************************************************************************* + * HRM.c - Eminent Heart Rate Module (HRM) routines via I2C + *******************************************************************************/ +#include "HRM_2197.h" +#include +#include +//#include +#include "heart_interface.h" +#include "device.h" +#include "PinNames.h" + +#include "basic_types.h" +#include "diag.h" +#include "osdep_api.h" + +#include "i2c_api.h" +#include "pinmap.h" +//#include "rtl_lib.h" +#include "gpio_api.h" // mbed +#include "main.h" + +#define MBED_I2C_SLAVE_ADDR0 0x41 +#define HR_MODE 0x001b +#define LED_ENABLE 0x3081 +#define FRAME_ENABLE 0x4804 +#define CHIP_RESET 0x4000 +#define CHIP_RUN 0x4004 +#define DATA_LOCK 0x4005 +#define DATA_UNLOCK 0x4004 +#define I2C_DATA_MAX_LENGTH 20 +#define CLOCK_SET 0x3800 +#define MBED_I2C_MTR_SDA PB_3 +#define MBED_I2C_MTR_SCL PB_2 +#define MBED_I2C_INTB PA_5 +#define MBED_I2C_BUS_CLK 100000 //hz + +uint8_t i2cdata_write[I2C_DATA_MAX_LENGTH]; +uint8_t i2cdata_read[I2C_DATA_MAX_LENGTH]; +uint16_t cmd; + +i2c_t i2cmaster; + +uint8_t integ_time = HR_INTEG_MIN; +int integ_time_array[] = { 4, 6, 8, 10, 15, 20, 25, 30, 40, 55, 70, 90, 110, 150, 200, 250, 350, 450, 550 }; + + + + +//Step1. define the callback to handle event of heart rate update +/******************************************************************************* + * report heart rate every 1 second + *******************************************************************************/ +void on_heartrate_update(int heartrate) { + printf("heart rate %d\n", heartrate); + //fflush(stdout); +} + +char i2cdatasrc[3] = {0x68, 0x90, 0x98}; + + +static void ePL_WriteCommand(uint16_t cmd) +{ + i2cdata_write[0] = (uint8_t)(cmd >>8); + i2cdata_write[1] = (uint8_t)(cmd&0xFF); + i2c_write(&i2cmaster, MBED_I2C_SLAVE_ADDR0, &i2cdata_write[0], 2, 1); +} + +uint16_t read_hrm(void) { + uint32_t raw, normalized_raw; + int integ_time_changed = 0; + ePL_WriteCommand(DATA_LOCK); + + i2c_write(&i2cmaster, MBED_I2C_SLAVE_ADDR0, &i2cdatasrc[1], 1, 1); + i2c_read(&i2cmaster, MBED_I2C_SLAVE_ADDR0, (char*)&i2cdata_read[1], 2, 1); + i2c_write(&i2cmaster, MBED_I2C_SLAVE_ADDR0, &i2cdatasrc[2], 1, 1); + i2c_read(&i2cmaster, MBED_I2C_SLAVE_ADDR0, (char*)&i2cdata_read[2], 2, 1); + + raw = i2cdata_read[1]; + raw |= (uint16_t) i2cdata_read[2] << 8; + + + normalized_raw = raw >> 4; + normalized_raw = normalized_raw * integ_time_array[HR_INTEG_BASE]; + normalized_raw = normalized_raw / integ_time_array[integ_time]; + + if (raw > HR_TH_HIGH && integ_time > HR_INTEG_MIN) { + integ_time -= 1; + integ_time_changed = 1; + } else if (raw < HR_TH_LOW && integ_time < HR_INTEG_MAX) { + integ_time += 1; + integ_time_changed = 1; + } + + if (integ_time_changed == 1) { + + ePL_WriteCommand(((0x01<<3)<<8) | ( HR_FILTER_4 | integ_time)); + ePL_WriteCommand(((0x08<<3)<<8) | ( HR_RESETN_RESET)); + } + + ePL_WriteCommand(((0x08<<3)<<8) | ( HR_RESETN_RUN)); + + return normalized_raw; +} + + + +/******************************************************************************* + * main function to read data, input to library, + * and calculate heart rate + *******************************************************************************/ +void main(void) { + int i, length; + int *data; + uint16_t result; + data = (int*) calloc(3000, sizeof(int)); + //load_ppg_signal(data, &length); //Load Test Data From File + i2c_init(&i2cmaster, MBED_I2C_MTR_SDA ,MBED_I2C_MTR_SCL); + i2c_frequency(&i2cmaster,MBED_I2C_BUS_CLK); +//Step2. delegate the event of heart rate update + register_callback(on_heartrate_update); + + + + +//Step3. Set the data length of heart rate calculation= 2^9 = 512 + + ePL_WriteCommand(((0x00<<3)<<8) | ( HR_MODE_HRS | HR_OSR_1024 | HR_GAIN_MID)); + ePL_WriteCommand(((0x01<<3)<<8) | ( HR_FILTER_4 | integ_time)); + ePL_WriteCommand(((0x09<<3)<<8) | ( HR_PDRIVE_70MA)); + ePL_WriteCommand(((0x06<<3)<<8) | ( HR_IR_ENABLE | HR_INT_FRAME)); + ePL_WriteCommand(((0x08<<3)<<8) | ( HR_RESETN_RESET)); + while(1) { +//Step4. Add ppg data continuously, and the Lib will return the Heart Rate 1 time/sec + result = read_hrm(); + + if(result>100) + add_PPG_XYZ(result, 0, 0, 0); + + Mdelay(40); //Simulate the ppg input time interval = 40ms + } + +//Step5. Stop + stop(); + + free(data); + +} + + + + +/******************************************************************************* + * initialize ic parameters + *******************************************************************************/ + + + + +/******************************************************************************* + * read rawdata + *******************************************************************************/ + diff --git a/project/realtek_ameba1_va0_example/example_sources/i2c_epl2590_light/readme.txt b/project/realtek_ameba1_va0_example/example_sources/i2c_epl2590_light/readme.txt new file mode 100644 index 0000000..a82de45 --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/i2c_epl2590_light/readme.txt @@ -0,0 +1,11 @@ +Example Description + +This example describes how to use proximity sensor to detect lightness + +Requirement Components: + extend board + +work with arduino extended board, which has proximity sensor + +when the proximity sensor is in ALS mode (detect lightness), it will keep polling lightness output. + diff --git a/project/realtek_ameba1_va0_example/example_sources/i2c_epl2590_light/src/main.c b/project/realtek_ameba1_va0_example/example_sources/i2c_epl2590_light/src/main.c new file mode 100644 index 0000000..594656e --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/i2c_epl2590_light/src/main.c @@ -0,0 +1,108 @@ + +#include "device.h" +#include "PinNames.h" + +#include "basic_types.h" +#include "diag.h" +#include "osdep_api.h" + +#include "i2c_api.h" +#include "pinmap.h" +//#include "rtl_lib.h" +#include "main.h" + +#define MBED_I2C_MTR_SDA PB_3 +#define MBED_I2C_MTR_SCL PB_2 +#define MBED_I2C_INTB PA_5 +#define MBED_I2C_SLAVE_ADDR0 0x49 +#define MBED_I2C_BUS_CLK 100000 //hz +#define I2C_DATA_MAX_LENGTH 20 + +uint8_t i2cdata_write[I2C_DATA_MAX_LENGTH]; +uint8_t i2cdata_read[I2C_DATA_MAX_LENGTH]; +uint16_t cmd; + +i2c_t i2cmaster; +//sensor command +#define WAKE_UP 0x1102 +#define CHIP_REFRESH1 0xFD8E +#define CHIP_REFRESH2 0xFE22 +#define CHIP_REFRESH3 0xFE02 +#define CHIP_REFRESH4 0xFD00 +#define PS_MODE 0x0002 +#define ALS_MODE 0x0001 +#define POWER_UP 0x1102 +#define CHIP_RESET 0x1100 +#define CHANGE_TIME 0x0851 +#define SETTING_1 0x0F19 +#define SETTING_2 0x0D10 +#define INT 0x3022 + +char i2cdatasrc[5] = {0x1B, 0x15, 0x16, 0x80, 0x88}; + + +static void ePL_WriteCommand(uint16_t cmd) +{ + i2cdata_write[0] = (uint8_t)(cmd >>8); + i2cdata_write[1] = (uint8_t)(cmd&0xFF); + i2c_write(&i2cmaster, MBED_I2C_SLAVE_ADDR0, &i2cdata_write[0], 2, 1); +} + + +void main(void) +{ + int result; + int i; + int light = 0; + int flag = 0; + char intertupt; + + DiagPrintf("Sensor_Init \r\n"); + i2c_init(&i2cmaster, MBED_I2C_MTR_SDA ,MBED_I2C_MTR_SCL); + i2c_frequency(&i2cmaster,MBED_I2C_BUS_CLK); + + ePL_WriteCommand(WAKE_UP); + ePL_WriteCommand(CHIP_REFRESH1); + ePL_WriteCommand(CHIP_REFRESH2); + ePL_WriteCommand(CHIP_REFRESH3); + ePL_WriteCommand(CHIP_REFRESH4); + + ePL_WriteCommand(ALS_MODE); + + //ePL_WriteCommand(SETTING_1); + //ePL_WriteCommand(SETTING_2); + + + ePL_WriteCommand(CHIP_RESET); + + ePL_WriteCommand(POWER_UP); + Mdelay(240); + while(1){ + //ePL_WriteCommand(DATA_LOCK); + i2c_write(&i2cmaster, MBED_I2C_SLAVE_ADDR0, &i2cdatasrc[0], 1, 1); + i2c_read(&i2cmaster, MBED_I2C_SLAVE_ADDR0, (char*)&i2cdata_read[0], 2, 1); + i2c_write(&i2cmaster, MBED_I2C_SLAVE_ADDR0, &i2cdatasrc[1], 1, 1); + i2c_read(&i2cmaster, MBED_I2C_SLAVE_ADDR0, (char*)&i2cdata_read[1], 2, 1); + i2c_write(&i2cmaster, MBED_I2C_SLAVE_ADDR0, &i2cdatasrc[2], 1, 1); + i2c_read(&i2cmaster, MBED_I2C_SLAVE_ADDR0, (char*)&i2cdata_read[2], 2, 1); + // printf("ALS LOW: %d\n", i2cdata_read[1]); + //printf("ALS HIGH: %d\n", i2cdata_read[2]); + light = i2cdata_read[1] + i2cdata_read[2] * 256; + printf("lightness: %d\n", light); + //flag = (i2cdata_read[0] & 8)? 1:0; + //int ret = (i2cdata_read[0] & 4)? 1:0; + //printf("flag: %d\n", flag); + //printf("ret: %d\n", ret); + + //ePL_WriteCommand(POWER_UP); + Mdelay(1000); + + } + + + + + + + +} diff --git a/project/realtek_ameba1_va0_example/example_sources/i2c_epl2590_proximity/readme.txt b/project/realtek_ameba1_va0_example/example_sources/i2c_epl2590_proximity/readme.txt new file mode 100644 index 0000000..0cafbe2 --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/i2c_epl2590_proximity/readme.txt @@ -0,0 +1,12 @@ +Example Description + +This example describes how to use proximity sensor to detect distance + +Requirement Components: + extend board + +work with arduino extended board, which has proximity sensor + +When the proximity sensor is in PS mode (detect distance), if the object is close to the sensor, a near message will print out. Otherwise a far message will print out. + + diff --git a/project/realtek_ameba1_va0_example/example_sources/i2c_epl2590_proximity/src/main.c b/project/realtek_ameba1_va0_example/example_sources/i2c_epl2590_proximity/src/main.c new file mode 100644 index 0000000..f9da2c5 --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/i2c_epl2590_proximity/src/main.c @@ -0,0 +1,115 @@ + +#include "device.h" +#include "PinNames.h" + +#include "basic_types.h" +#include "diag.h" +#include "osdep_api.h" + +#include "i2c_api.h" +#include "pinmap.h" +//#include "rtl_lib.h" +#include "main.h" + +#define MBED_I2C_MTR_SDA PB_3 +#define MBED_I2C_MTR_SCL PB_2 +#define MBED_I2C_INTB PA_5 +#define MBED_I2C_SLAVE_ADDR0 0x49 +#define MBED_I2C_BUS_CLK 100000 //hz +#define I2C_DATA_MAX_LENGTH 20 + +uint8_t i2cdata_write[I2C_DATA_MAX_LENGTH]; +uint8_t i2cdata_read[I2C_DATA_MAX_LENGTH]; +uint16_t cmd; + +i2c_t i2cmaster; +//sensor command +#define WAKE_UP 0x1102 +#define CHIP_REFRESH1 0xFD8E +#define CHIP_REFRESH2 0xFE22 +#define CHIP_REFRESH3 0xFE02 +#define CHIP_REFRESH4 0xFD00 +#define PS_MODE 0x0002 +#define ALS1_MODE 0x0072 +#define ALS2_MODE 0x503E +#define ALS3_MODE 0x583E +#define POWER_UP 0x1102 +#define CHIP_RESET 0x1100 +#define CHANGE_TIME 0x0851 +#define SETTING_1 0x0F19 +#define SETTING_2 0x0D10 +#define INT 0x3022 + +char i2cdatasrc[5] = {0x1B, 0x1E, 0x1F, 0x80, 0x88}; + + +static void ePL_WriteCommand(uint16_t cmd) +{ + i2cdata_write[0] = (uint8_t)(cmd >>8); + i2cdata_write[1] = (uint8_t)(cmd&0xFF); + i2c_write(&i2cmaster, MBED_I2C_SLAVE_ADDR0, &i2cdata_write[0], 2, 1); +} + + +void main(void) +{ + int result; + int i; + int flag = 0; + char intertupt; + + DiagPrintf("Sensor_Init \r\n"); + i2c_init(&i2cmaster, MBED_I2C_MTR_SDA ,MBED_I2C_MTR_SCL); + i2c_frequency(&i2cmaster,MBED_I2C_BUS_CLK); + + ePL_WriteCommand(WAKE_UP); + ePL_WriteCommand(CHIP_REFRESH1); + ePL_WriteCommand(CHIP_REFRESH2); + ePL_WriteCommand(CHIP_REFRESH3); + ePL_WriteCommand(CHIP_REFRESH4); + + ePL_WriteCommand(PS_MODE); + + ePL_WriteCommand(SETTING_1); + ePL_WriteCommand(SETTING_2); + + + ePL_WriteCommand(CHIP_RESET); + + ePL_WriteCommand(POWER_UP); + Mdelay(240); + while(1){ + //ePL_WriteCommand(DATA_LOCK); + i2c_write(&i2cmaster, MBED_I2C_SLAVE_ADDR0, &i2cdatasrc[0], 1, 1); + i2c_read(&i2cmaster, MBED_I2C_SLAVE_ADDR0, (char*)&i2cdata_read[0], 2, 1); + i2c_write(&i2cmaster, MBED_I2C_SLAVE_ADDR0, &i2cdatasrc[1], 1, 1); + i2c_read(&i2cmaster, MBED_I2C_SLAVE_ADDR0, (char*)&i2cdata_read[1], 2, 1); + i2c_write(&i2cmaster, MBED_I2C_SLAVE_ADDR0, &i2cdatasrc[2], 1, 1); + i2c_read(&i2cmaster, MBED_I2C_SLAVE_ADDR0, (char*)&i2cdata_read[2], 2, 1); + //printf("PS LOW: %d\n", i2cdata_read[1]); + //printf("PS HIGH: %d\n", i2cdata_read[2]); + flag = (i2cdata_read[0] & 8)? 1:0; + int ret = (i2cdata_read[0] & 4)? 1:0; + //printf("flag: %d\n", flag); + //printf("ret: %d\n", ret); + + if(flag){ + printf("the object is far\n"); + } + else + { + printf("the object is near\n"); + } + + //ePL_WriteCommand(POWER_UP); + Mdelay(1000); + + } + + + + + + + +} diff --git a/project/realtek_ameba1_va0_example/example_sources/i2s/readme.txt b/project/realtek_ameba1_va0_example/example_sources/i2s/readme.txt new file mode 100644 index 0000000..5a7ec39 --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/i2s/readme.txt @@ -0,0 +1,10 @@ +Example Description + +This example describes how to use i2s by using mbed extend api + +1.Plug ALC5651 shield to Ameba HDK + +2.Run the main function. + +3.Plug earphone to Green phone jack + diff --git a/project/realtek_ameba1_va0_example/example_sources/i2s/src/alc5651.c b/project/realtek_ameba1_va0_example/example_sources/i2s/src/alc5651.c new file mode 100644 index 0000000..1ee3447 --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/i2s/src/alc5651.c @@ -0,0 +1,183 @@ +#include +#include "PinNames.h" +#include "basic_types.h" +#include "diag.h" +#include + +#include "i2c_api.h" +#include "pinmap.h" + +//#define I2C_MTR_SDA PC_4//PB_3 +//#define I2C_MTR_SCL PC_5//PB_2 +#define I2C_MTR_SDA PB_3 +#define I2C_MTR_SCL PB_2 +#define I2C_BUS_CLK 100000 //hz + +#define I2C_ALC5651_ADDR (0x34/2) + +#define RT5651_PRIV_INDEX 0x6a +#define RT5651_PRIV_DATA 0x6c + +#if defined (__ICCARM__) +i2c_t alc5651_i2c; +#else +volatile i2c_t alc5651_i2c; +#define printf DBG_8195A +#endif + +static void alc5651_delay(void) +{ + int i; + + i=10000; + while (i) { + i--; + asm volatile ("nop\n\t"); + } +} + +void alc5651_reg_write(unsigned int reg, unsigned int value) +{ + char buf[4]; + buf[0] = (char)reg; + buf[1] = (char)(value>>8); + buf[2] = (char)(value&0xff); + + i2c_write(&alc5651_i2c, I2C_ALC5651_ADDR, &buf[0], 3, 1); + alc5651_delay(); +} + +void alc5651_reg_read(unsigned int reg, unsigned int *value) +{ + int tmp; + char *buf = (char*)&tmp; + + buf[0] = (char)reg; + i2c_write(&alc5651_i2c, I2C_ALC5651_ADDR, &buf[0], 1, 1); + alc5651_delay(); + + buf[0] = 0xaa; + buf[1] = 0xaa; + + i2c_read(&alc5651_i2c, I2C_ALC5651_ADDR, &buf[0], 2, 1); + alc5651_delay(); + + *value= ((buf[0]&0xFF)<<8)|(buf[1]&0xFF); +} + +void alc5651_index_write(unsigned int reg, unsigned int value) +{ + alc5651_reg_write(RT5651_PRIV_INDEX, reg); + alc5651_reg_write(RT5651_PRIV_DATA, value); +} + +void alc5651_index_read(unsigned int reg, unsigned int *value) +{ + alc5651_reg_write(RT5651_PRIV_INDEX, reg); + alc5651_reg_read(RT5651_PRIV_DATA, value); +} + +void alc5651_reg_dump(void) +{ + int i; + unsigned int value; + + printf("alc5651 codec reg dump\n\r"); + printf("------------------------\n\r"); + for(i=0;i<=0xff;i++){ + alc5651_reg_read(i, &value); + printf("%02x : %04x\n\r", i, (unsigned short)value); + } + printf("------------------------\n\r"); +} + +void alc5651_index_dump(void) +{ + int i; + unsigned int value; + + printf("alc5651 codec index dump\n\r"); + printf("------------------------\n\r"); + for(i=0;i<=0xff;i++){ + alc5651_index_read(i, &value); + printf("%02x : %04x\n\r", i, (unsigned short)value); + } + printf("------------------------\n\r"); +} + +void alc5651_init(void) +{ + i2c_init(&alc5651_i2c, I2C_MTR_SDA, I2C_MTR_SCL); + i2c_frequency(&alc5651_i2c, I2C_BUS_CLK); +} + +void alc5651_set_word_len(int len_idx) // interface2 +{ + // 0: 16 1: 20 2: 24 3: 8 + unsigned int val; + alc5651_reg_read(0x71,&val); + val &= (~(0x3<<2)); + val |= (len_idx<<2); + alc5651_reg_write(0x71,val); + alc5651_reg_read(0x70,&val); + val &= (~(0x3<<2)); + val |= (len_idx<<2); + alc5651_reg_write(0x70,val); + +} + +void alc5651_init_interface1(void) +{ + alc5651_reg_write(0x00,0x0021); + alc5651_reg_write(0x63,0xE8FE); + alc5651_reg_write(0x61,0x5800); + alc5651_reg_write(0x62,0x0C00); + alc5651_reg_write(0x73,0x0000); + alc5651_reg_write(0x2A,0x4242); + alc5651_reg_write(0x45,0x2000); + alc5651_reg_write(0x02,0x4848); + alc5651_reg_write(0x8E,0x0019); + alc5651_reg_write(0x8F,0x3100); + alc5651_reg_write(0x91,0x0E00); + alc5651_index_write(0x3D,0x3E00); + alc5651_reg_write(0xFA,0x0011); + alc5651_reg_write(0x83,0x0800); + alc5651_reg_write(0x84,0xA000); + alc5651_reg_write(0xFA,0x0C11); + alc5651_reg_write(0x64,0x4010); + alc5651_reg_write(0x65,0x0C00); + alc5651_reg_write(0x61,0x5806); + alc5651_reg_write(0x62,0xCC00); + alc5651_reg_write(0x3C,0x004F); + alc5651_reg_write(0x3E,0x004F); + alc5651_reg_write(0x27,0x3820); + alc5651_reg_write(0x77,0x0000); +} + +void alc5651_init_interface2(void) +{ + alc5651_reg_write(0x00,0x0021); + alc5651_reg_write(0x63,0xE8FE); + alc5651_reg_write(0x61,0x5800); + alc5651_reg_write(0x62,0x0C00); + alc5651_reg_write(0x73,0x0000); + alc5651_reg_write(0x2A,0x4242); + alc5651_reg_write(0x45,0x2000); + alc5651_reg_write(0x02,0x4848); + alc5651_reg_write(0x8E,0x0019); + alc5651_reg_write(0x8F,0x3100); + alc5651_reg_write(0x91,0x0E00); + alc5651_index_write(0x3D,0x3E00); + alc5651_reg_write(0xFA,0x0011); + alc5651_reg_write(0x83,0x0800); + alc5651_reg_write(0x84,0xA000); + alc5651_reg_write(0xFA,0x0C11); + alc5651_reg_write(0x64,0x4010); + alc5651_reg_write(0x65,0x0C00); + alc5651_reg_write(0x61,0x5806); + alc5651_reg_write(0x62,0xCC00); + alc5651_reg_write(0x3C,0x004F); + alc5651_reg_write(0x3E,0x004F); + alc5651_reg_write(0x28,0x3030); + alc5651_reg_write(0x2F,0x0080); +} \ No newline at end of file diff --git a/project/realtek_ameba1_va0_example/example_sources/i2s/src/birds_16000_2ch_16b.c b/project/realtek_ameba1_va0_example/example_sources/i2s/src/birds_16000_2ch_16b.c new file mode 100644 index 0000000..18ea03a --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/i2s/src/birds_16000_2ch_16b.c @@ -0,0 +1,11666 @@ +#include +int sample_size=46639; + +SECTION(".sdram.data") +short sample[]={ +0, 0, -1, 2, 0, -1, -1, 2, +-3, 2, 1, -1, 0, 0, 2, 0, +-2, 1, 2, -2, -1, 2, -3, 2, +1, -1, 1, -1, 4, -4, 1, -2, +2, -2, 2, -3, 1, 2, -4, 1, +2, -1, -2, 0, 1, 0, -1, 1, +-2, 2, 1, -1, -1, 1, 2, -2, +2, -3, 0, 2, -1, -2, 4, -1, +-1, -1, 3, -1, 0, -2, 2, 1, +-3, 1, 3, -2, 2, -2, 1, -1, +1, -1, -1, 0, 1, 0, -3, 2, +-1, 2, 0, -2, 1, 2, -1, 0, +1, 0, 2, -3, 3, -2, 0, -1, +2, -1, -2, 3, -3, 2, 1, 0, +0, -1, -1, 3, -1, -2, 5, -3, +-1, 0, 1, 0, -3, 3, 1, -2, +3, -3, -2, 2, 1, -2, 0, 1, +-3, 2, 1, -2, 1, 0, -2, 2, +-3, 3, -2, 1, 1, 0, -1, 1, +-1, 2, -2, 1, 0, 1, -1, 1, +0, 1, -1, 0, 3, -2, 1, 0, +1, -1, 1, 0, 1, -1, 2, -1, +0, 0, 0, 1, -2, 1, 2, -1, +-2, 2, -3, 3, -2, 1, -2, 2, +-1, 0, 1, -1, -4, 4, -3, 3, +1, -1, 0, 0, 1, -1, -1, 1, +1, -1, 1, 0, -1, 1, -1, 1, +-1, 1, 1, -1, 0, 1, 2, -3, +1, 0, -1, 1, -1, 1, -1, 1, +-2, 2, -2, 3, -4, 3, 0, 0, +0, -1, 3, -2, -2, 2, -2, 1, +-2, 2, -1, 1, -2, 2, 2, -2, +-1, 1, -2, 1, 2, -2, 1, -1, +4, -3, 0, 0, 2, -2, -1, 2, +0, 0, -1, 2, 0, 0, 1, -1, +1, 0, 0, 0, -3, 4, -2, 1, +-1, 1, -4, 4, -4, 4, -2, 2, +-3, 3, -4, 4, -2, 2, -4, 4, +1, -3, 4, -3, 1, -2, 2, -1, +1, -1, -1, 1, 0, -1, 0, 1, +-4, 5, -1, 1, 3, -2, 1, 0, +-1, 2, 2, -2, 1, 1, 0, 0, +1, 0, -1, 1, 2, -2, 0, 0, +-2, 1, 1, -1, -3, 3, -1, 0, +1, -2, 0, 0, 0, -1, 3, -3, +1, -1, -1, 1, 3, -4, 4, -3, +0, 0, 0, 0, -3, 3, -4, 3, +1, -1, 1, 0, 2, -1, 1, -1, +0, 1, -2, 2, 0, 0, -1, 2, +-1, 1, 2, -1, -1, 2, -2, 1, +1, -1, -1, 1, 1, -2, 0, 0, +-1, 0, 0, 0, -2, 2, -2, 2, +-2, 1, 1, -2, 1, -1, -4, 5, +-1, -1, 5, -5, 3, -3, 2, -1, +-4, 4, 0, 0, 3, -2, -1, 2, +3, -3, 3, -1, -1, 1, 1, -1, +0, 0, 1, -1, 1, 0, -2, 1, +1, -1, 1, -1, 1, -2, 0, 1, +-3, 2, 1, -3, 2, -2, 0, -1, +0, 0, -3, 2, 0, -2, 0, 1, +0, -1, 1, 0, -1, 1, -1, 1, +1, -2, 2, -2, 2, -1, 1, 0, +2, -1, 3, -2, 2, -1, 1, -1, +4, -4, 5, -4, 1, 0, -3, 3, +2, -2, 2, -2, 0, 0, 1, -1, +-2, 1, -1, 0, -3, 2, -1, 0, +-1, 0, -3, 3, -2, 0, -1, 1, +-1, 0, 3, -3, 3, -3, 1, -1, +-1, 2, -1, 1, 1, 0, -1, 1, +-2, 3, -2, 2, 3, -3, 3, -2, +2, -1, 2, -2, 2, -2, 2, -2, +-2, 3, -2, 1, 0, 1, -3, 3, +-1, 0, 2, -2, -2, 2, -2, 0, +2, -3, 1, -1, 0, -1, 0, 0, +-2, 2, -2, 2, 0, -1, -1, 1, +-1, 0, 1, -1, 0, 1, -1, 2, +0, 1, -2, 3, 0, 0, 1, -1, +1, 0, 0, 0, 3, -2, 1, 0, +2, -1, -2, 2, 0, 0, -1, 1, +-4, 3, 3, -3, -2, 3, 0, -1, +2, -2, -1, 1, 0, -1, -2, 2, +-3, 1, -1, 2, -3, 2, 0, 0, +0, -1, 3, -3, 1, -1, 0, 1, +-1, 1, 0, 0, -2, 3, 0, -1, +2, -1, -1, 1, -1, 2, -5, 4, +0, 0, -2, 2, 1, -1, 0, 0, +1, 0, -2, 2, -3, 2, -2, 2, +-3, 3, -2, 1, 1, -2, 2, -2, +3, -4, 3, -3, 0, 0, -1, 1, +-1, 0, 1, -1, -1, 1, -1, 1, +3, -3, 1, 0, 1, -2, 2, -1, +-3, 4, -1, 1, 2, -2, 1, -1, +1, -1, 1, -1, 1, 0, 0, 0, +-1, 1, -2, 1, 3, -3, 2, -2, +0, 1, -5, 5, -4, 4, -2, 1, +0, 0, 2, -2, -1, 1, 0, 0, +0, 0, 1, 0, -2, 1, 0, 0, +2, -3, 0, 2, -1, 0, 2, -1, +0, 0, 4, -3, 1, -1, 2, -2, +0, 1, -2, 1, 1, 0, -2, 1, +1, 0, -2, 1, 1, -1, -3, 3, +-4, 4, -2, 0, 5, -5, 2, -1, +0, 0, -2, 2, -3, 2, 2, -2, +0, 0, -2, 4, -4, 2, 3, -3, +1, -2, 4, -4, 1, -1, 0, 0, +-2, 2, -3, 3, 0, 0, 1, -1, +0, 0, 2, -2, 3, -2, 1, 0, +-4, 4, -3, 2, 2, -2, -1, 1, +0, 0, -1, 1, -2, 2, -3, 2, +0, 0, 0, 0, -1, 0, 1, -1, +-2, 1, 2, -3, -2, 3, -3, 2, +-3, 4, -3, 1, 4, -4, 0, 0, +3, -3, 1, 0, 0, -1, 1, 0, +0, -1, 2, -1, 0, 0, 0, 1, +-1, 1, 1, -1, 2, -2, 2, -1, +0, 0, 0, 1, -3, 3, 2, -4, +1, 0, -4, 3, 0, 0, 0, -1, +0, 0, -1, 0, 2, -2, 1, -1, +-1, 1, 0, 0, -1, 0, 2, -2, +-2, 2, 1, -1, -1, 1, -1, 1, +-1, 1, 1, -1, -1, 0, 2, -2, +0, 1, -1, 1, 0, 1, 0, -1, +0, 1, -2, 1, 2, -1, -3, 3, +0, -1, -1, 1, 0, -1, 3, -4, +1, -1, 2, -2, 1, 0, 0, 0, +2, -1, 0, 0, 3, -4, 3, -1, +-1, 0, 0, 0, -1, 1, -1, 2, +-3, 3, 2, -2, 2, -2, 1, 0, +0, 0, 0, 0, -2, 2, 1, 0, +-2, 3, -1, 0, 1, -2, 5, -5, +0, 1, -2, 2, -2, 2, -4, 3, +-1, 0, 2, -2, 0, 0, -1, 1, +1, -1, 0, 1, -2, 1, 0, -1, +2, -1, -1, 1, 0, 0, 0, 1, +-2, 2, 0, -1, 1, -1, 1, -2, +2, -2, 0, 0, -1, 1, -1, 2, +-3, 2, 3, -3, -1, 1, -2, 2, +-3, 2, -1, 0, 1, -1, 1, -1, +0, -1, 2, -2, 1, 0, 0, 0, +0, 1, -2, 1, -1, 1, 0, -1, +1, -1, -2, 1, 1, -1, 2, -2, +0, 0, 0, 1, 0, 0, 1, 0, +-3, 3, -1, 1, 0, 0, 1, -1, +-1, 1, 0, 0, -1, 1, 0, -1, +3, -3, 0, 0, -1, 1, 0, 0, +-2, 3, -6, 5, -2, 2, -1, 0, +1, -1, -1, 1, -1, 1, 1, -2, +4, -4, 3, -3, 2, -2, 1, -1, +2, -2, -2, 3, -4, 4, -2, 2, +-1, 1, 0, 0, 0, 0, -3, 3, +-2, 3, -2, 2, 0, 0, -1, 1, +-1, 2, -3, 3, 0, 0, 1, -1, +1, -2, 1, 0, -1, 0, 1, 0, +-1, 0, 1, 0, -3, 2, -1, 1, +-2, 2, -1, 1, -1, 2, -2, 2, +2, -3, 2, -2, 1, 0, 0, -1, +2, -2, 1, -2, 1, 0, 2, -3, +1, -1, 0, 0, 1, -1, 0, 0, +2, -2, -1, 1, 0, -1, -2, 2, +-3, 2, 1, -1, 0, 0, -2, 2, +0, 0, -2, 2, 0, -1, 4, -4, +1, -1, -1, 1, 1, -1, 2, -2, +-2, 2, 0, -1, 3, -2, 1, 0, +1, -1, 2, -2, 0, 0, 1, -1, +0, 0, 0, 0, 0, 0, 1, -1, +-2, 1, 1, -1, 0, 0, -3, 3, +-2, 1, 2, -2, 0, 0, -1, 1, +0, 0, -2, 2, -2, 1, 1, -1, +0, 0, 1, -1, 1, -1, 1, -1, +-1, 1, -1, 1, -1, 0, 2, -2, +1, -1, -1, 1, -2, 1, 0, 1, +-4, 5, -3, 2, 1, -1, 1, -1, +0, 0, 0, 0, -1, 1, 0, 0, +-3, 3, -1, 0, -1, 1, 0, -1, +3, -3, 3, -3, 3, -3, 1, -1, +2, -2, 0, 1, -4, 4, 1, -2, +2, -1, -2, 3, -3, 2, 1, -1, +-1, 1, 1, -1, 1, -1, 2, -3, +1, -1, 2, -2, 2, -2, -1, 2, +-4, 3, -2, 1, 1, -1, 2, -2, +-1, 0, 1, -1, 0, 1, 2, -3, +1, 0, -3, 3, 0, 0, -1, 1, +0, 0, -1, 1, -1, 1, 0, 0, +2, -2, 0, 0, 0, 0, -1, 1, +0, 0, 0, 1, -1, 1, 1, -1, +0, 1, -2, 2, 2, -2, 0, 1, +-3, 2, 0, 0, 1, -2, 3, -3, +0, 1, -2, 1, 2, -3, 4, -3, +-2, 2, 0, -1, 1, 0, -1, 1, +-1, 1, 3, -4, 1, 1, -2, 2, +0, 0, 0, 1, -3, 3, -2, 2, +0, 0, 2, -2, 0, 1, -2, 1, +4, -4, 2, -1, -1, 0, 2, -2, +1, -1, 1, -1, 1, -1, 0, 0, +-1, 1, 1, -1, -1, 1, -1, 1, +-3, 3, -4, 4, -1, 0, 0, 0, +-1, 2, -2, 2, 0, 0, 1, -1, +1, -1, -1, 1, 0, 0, 2, -2, +3, -3, 0, 1, 0, 0, 1, -1, +1, -2, 1, 0, -1, 1, 3, -3, +2, -2, 1, -1, 0, 0, 1, -1, +-1, 0, 3, -3, 2, -2, 3, -3, +4, -4, 1, -1, -1, 1, 1, -1, +1, -1, 2, -3, 2, -1, -3, 3, +0, -1, 0, 0, -1, 2, -1, 0, +3, -3, 2, -2, -1, 2, 0, 0, +1, 0, -4, 4, 1, -2, 1, -1, +-1, 1, -2, 2, 1, -2, 2, -2, +-2, 2, -1, 1, 2, -2, 0, 0, +1, -1, -1, 1, -1, 1, 1, -1, +-1, 1, 0, 0, 0, 0, 2, -2, +1, -1, 0, -1, 1, -1, -1, 1, +-2, 2, -2, 2, -2, 2, -1, 1, +-2, 2, -1, 0, 0, 0, 0, 0, +-2, 2, 0, -1, 4, -4, 0, 1, +-3, 2, 0, 0, -1, 1, -1, 1, +-1, 0, 0, 0, -1, 1, -2, 2, +-2, 2, 1, -1, 2, -2, 0, -1, +2, -1, 0, 0, 2, -2, -1, 2, +-1, 1, 0, 1, 0, 0, 2, -2, +2, -1, -2, 2, 2, -3, 2, -1, +-3, 3, 2, -2, 0, 0, 0, 0, +1, -1, 2, -2, 0, 1, -2, 2, +-2, 2, -1, 1, 1, -2, 2, -2, +-2, 2, 0, 0, 0, 0, 1, -1, +-1, 1, -1, 1, 1, -2, 1, -1, +-2, 2, -1, 1, 0, 0, 1, -1, +0, 1, 1, -2, 3, -3, -1, 1, +1, -1, 0, 1, -1, 0, -1, 1, +1, -2, 1, 0, -2, 1, 3, -3, +-3, 3, -1, 0, 2, -3, 1, 0, +-1, 1, -1, 1, -1, 0, 0, 0, +2, -3, 0, 1, 0, -1, 1, 0, +-2, 1, 1, -1, -4, 5, -1, -1, +2, -1, -3, 3, 0, 0, 0, 0, +-1, 2, 0, 0, -1, 2, -2, 2, +-2, 1, 1, -1, 0, 1, -3, 3, +1, -1, 3, -3, 1, -1, 0, 0, +1, -1, 1, -1, 0, 0, -2, 2, +-2, 2, -2, 2, 0, -1, 2, -2, +1, 0, -2, 2, -3, 2, 0, -1, +1, 0, -1, 1, -1, 1, -2, 2, +-2, 2, 0, -1, -1, 1, 1, -2, +2, -1, -1, 1, -2, 2, 0, -1, +2, -1, -1, 1, 0, 1, -2, 2, +-1, 1, 2, -2, 2, -1, 0, 0, +1, -1, 3, -3, 3, -2, -1, 1, +0, 0, 0, 0, 0, 0, 1, -1, +1, -1, -1, 2, -1, 1, -2, 2, +-3, 3, -1, 0, 2, -2, 0, 0, +0, 1, -3, 3, 0, 0, -1, 1, +1, -1, -1, 1, -2, 1, 1, -1, +0, 0, 4, -5, 3, -2, -1, 0, +2, -1, -1, 1, 0, 0, 0, -1, +1, -1, -1, 2, -3, 3, -2, 1, +1, -1, -1, 0, 2, -2, -1, 1, +1, -2, 0, 2, -5, 5, -1, 0, +1, -1, 1, -1, -1, 2, -3, 3, +-1, 1, -1, 0, 1, -1, 0, 0, +3, -3, 0, 1, -2, 2, 1, -1, +0, 0, 1, 0, -3, 4, -1, -1, +2, -2, -2, 2, -2, 1, 1, -2, +3, -3, 2, -2, 1, -1, 0, -1, +2, -2, 1, -1, 1, -1, 2, -3, +3, -2, -2, 2, 1, -1, 0, 0, +0, 0, 0, -1, 2, -3, 1, -1, +0, 0, 1, -1, 0, 0, 0, 0, +1, -1, 0, 1, -2, 2, 1, -1, +-3, 3, 0, -1, -1, 2, -4, 3, +1, -2, 2, -2, 2, -1, -2, 2, +0, 0, -2, 3, -3, 2, -2, 2, +-3, 2, 2, -2, -1, 1, -1, 1, +-1, 2, -1, 1, 0, 0, 0, 0, +2, -2, 1, 0, -4, 3, 2, -2, +-1, 3, -2, 0, 2, -2, 0, 1, +0, 0, 1, -1, 0, 1, 0, -1, +2, -2, -2, 2, 3, -4, 2, -1, +-5, 5, 1, -2, 2, -2, 2, -2, +0, 0, -2, 2, -1, 1, 3, -3, +1, 0, 1, -1, 0, 0, 2, -2, +1, 0, 1, -1, 0, 1, -2, 1, +1, 0, -1, 1, 1, -1, 2, -2, +1, -1, 1, -2, 3, -2, 1, -2, +4, -3, -2, 2, 2, -2, 1, 0, +3, -4, 2, -1, -2, 2, 0, 0, +0, 1, -1, 0, -1, 1, -1, 0, +3, -3, 1, -1, 1, -2, 2, -2, +1, 0, -1, 1, 1, -1, 0, 1, +1, -1, 2, -1, 0, 0, 0, 1, +-3, 2, 0, -1, 0, 0, -1, 1, +1, -1, 1, -1, -1, 0, 0, 0, +-4, 4, 0, -1, 1, -1, 1, -1, +-3, 3, -1, 0, 2, -2, -1, 1, +0, 0, -3, 4, -3, 3, -1, 1, +1, -2, 4, -3, 1, -1, 2, -2, +-2, 2, 1, -2, 3, -2, -1, 1, +-1, 1, -2, 2, -1, 1, -1, 0, +2, -3, 1, 0, -1, 1, 0, 0, +-1, 1, 1, -1, 1, -1, 0, 1, +-2, 1, 1, -1, 2, -2, -1, 1, +-1, 0, 3, -2, -2, 2, -1, 1, +-1, 1, 0, 0, -2, 2, 0, -1, +-1, 2, -2, 1, 3, -3, -1, 1, +2, -3, 4, -3, 1, -1, 4, -4, +0, 0, 2, -3, 1, 0, -2, 1, +1, -1, 2, -2, 1, -1, -1, 1, +1, -1, -1, 1, 0, -1, 2, -2, +-1, 1, -1, 0, 1, -1, 1, -1, +-1, 1, -3, 2, 0, -1, 3, -2, +0, 0, 2, -3, 3, -2, 0, 0, +-1, 1, -2, 2, 0, 0, -1, 1, +0, -1, 1, 0, 0, 0, 2, -2, +-1, 2, -2, 1, 3, -2, -1, 2, +0, -1, 1, -1, -1, 0, 4, -5, +3, -2, 0, 0, 1, -1, -1, 1, +1, -1, 2, -1, -2, 2, -1, 1, +-2, 2, 1, 0, -3, 4, -2, 1, +2, -2, 1, -1, 1, -2, 2, -2, +-1, 2, -3, 3, 1, -1, 2, -2, +3, -2, 0, 0, 0, -1, 0, 0, +1, -2, 3, -3, 0, 1, 0, 0, +-1, 1, 0, -1, 3, -2, 0, 0, +-1, 1, -3, 4, -2, 2, 0, 0, +0, 0, 0, 1, -2, 1, 1, -1, +-1, 1, 0, 0, -2, 3, 1, -3, +2, -1, -1, 1, -2, 2, -2, 1, +0, -1, 1, -1, -1, 2, 0, -2, +5, -4, 1, -1, 1, -1, 0, 0, +2, -2, -1, 1, -2, 2, -1, 1, +0, 0, 1, -1, 2, -2, -1, 1, +0, 0, -2, 2, -2, 2, -2, 3, +-5, 5, -3, 2, 2, -2, 1, -1, +2, -2, 3, -3, 2, -1, -2, 2, +2, -3, 1, 0, -1, 1, -3, 4, +-5, 4, 0, 0, -1, 2, -3, 2, +4, -5, 2, -1, -2, 1, 2, -2, +-2, 3, 0, -1, 0, 1, -1, 0, +2, -2, 1, -1, 0, 1, -2, 2, +0, 0, -1, 1, 1, -1, -2, 3, +0, -1, 4, -3, 2, -1, 0, 0, +0, 0, -1, 1, -2, 2, -2, 2, +-1, 1, -1, 1, 1, -1, -2, 3, +-4, 4, -2, 2, -1, 2, -2, 2, +0, 0, 1, -1, -1, 1, 0, 0, +2, -2, 0, 1, 0, 0, 0, 0, +2, -2, 2, -2, 2, -2, 3, -3, +3, -3, 1, -1, 0, 0, -2, 2, +1, -1, 3, -3, 3, -3, 1, -1, +1, -2, 5, -4, 0, 1, -1, 1, +0, 0, -1, 0, 0, 0, -1, 2, +-2, 2, -1, 0, 1, -1, -1, 1, +2, -2, 2, -1, -3, 3, 0, -1, +2, -2, -1, 2, 0, -1, -2, 2, +-4, 3, 2, -2, -2, 3, -4, 3, +-3, 2, 0, 0, 0, 1, 0, 0, +-1, 1, 0, 0, -1, 1, -1, 1, +2, -2, 3, -3, 0, 1, 0, 0, +0, 0, 0, 0, 1, -2, -1, 0, +0, 0, 1, 0, -3, 4, -3, 2, +-1, 0, 3, -4, 3, -1, -4, 3, +1, -1, -1, 2, -4, 4, -1, 1, +0, 1, -1, 0, 2, -2, 2, -1, +-1, 1, 0, -1, 1, -1, 0, 0, +0, 1, 2, -2, 5, -5, 0, 0, +-2, 3, -3, 4, 2, -2, 0, 0, +-3, 2, -2, 2, 0, 1, 1, -1, +-2, 1, -2, 2, -3, 3, 1, 0, +-1, 1, -1, 0, -1, 1, 0, 0, +2, 0, -3, 3, 1, -3, 2, -2, +5, -4, 2, 0, -3, 2, -3, 1, +0, -1, 4, -3, 2, -1, -2, 1, +-3, 1, -2, 2, 0, 1, 2, -1, +-4, 3, -3, 1, 1, 0, 1, 0, +0, 1, -3, 1, -1, 0, -2, 3, +1, 1, -3, 3, -4, 1, -1, 0, +2, -1, 4, -2, 0, 1, -6, 4, +-3, 2, 2, -1, -1, 3, -4, 3, +-2, -1, -2, 2, -1, 4, -3, 5, +-3, 1, -1, -1, -1, 1, 1, 1, +-1, 3, -5, 3, 0, -3, 2, -1, +2, 0, 0, 2, -4, 3, -3, 1, +-2, 4, 0, 1, 2, -1, -4, 2, +-2, 1, -1, 2, 3, -2, 3, -2, +-4, 2, -2, -1, 4, -2, 4, -1, +0, 0, -5, 2, -1, 0, 1, 2, +1, 2, -3, 2, -3, -1, 1, -1, +3, 0, 2, 0, -3, 2, -3, 0, +-3, 3, 2, 1, 2, 0, -2, 0, +-2, -1, 2, -1, 3, 0, 0, 1, +-3, 0, -3, 0, 2, -1, 4, 0, +0, 1, -3, 0, -2, -1, 4, -2, +3, 1, 0, -1, -3, 0, -3, 1, +3, 0, 5, -2, -1, 1, -4, -1, +1, -2, 4, 0, 3, 1, -4, 2, +-4, 0, -2, 2, 4, -1, 3, 1, +-3, -1, -2, -2, -1, 1, 5, -1, +4, -2, 1, -4, -4, 1, 2, -2, +6, -1, 2, -1, -2, -2, -4, 1, +2, 0, 3, 1, -1, 2, -3, -2, +-1, -1, 2, 1, 4, 0, 0, 0, +-4, -2, 1, -3, 4, 1, 0, 4, +-2, -1, -2, -2, -5, 4, 4, 0, +2, 1, -3, 0, -5, 0, 2, -2, +3, 2, 3, -1, -2, -1, -4, -1, +2, 0, 5, 0, 1, 1, -6, 2, +-5, 1, 2, -1, 8, -3, 3, -2, +-5, 0, -1, -2, 6, -2, 5, 0, +-2, 2, -5, -1, 3, -5, 4, 0, +6, -2, -1, -1, -2, -5, 1, -1, +-1, 6, 2, 1, -2, 0, -9, 3, +-2, 1, 6, 0, 3, 1, -4, 0, +-6, 1, -2, 2, 6, 0, 3, 0, +-9, 5, -8, 2, 4, -3, 6, 0, +1, 0, -7, 2, -4, 0, 5, -2, +6, 0, 0, 1, -8, 3, -7, 3, +4, -1, 9, -4, 1, -1, -8, 2, +-3, 0, 5, 0, 4, 1, -1, -1, +-4, -1, -1, 0, 5, 0, 4, 0, +-3, 0, -5, -1, 0, 1, 5, 1, +4, -1, -3, -1, -4, -1, 0, 1, +9, -3, 2, 0, -6, 1, -3, -2, +3, 0, 5, 1, -2, 2, -6, 0, +-4, 1, 1, 2, 5, 0, -2, 1, +-4, -2, -1, -1, 3, 2, 3, 2, +-3, 1, -7, 2, -3, 1, 5, 0, +5, 0, -2, -1, -3, -2, -1, 1, +5, 0, 5, -1, -4, 1, -7, 1, +2, -1, 7, -1, 2, 0, -3, -2, +-3, -2, 4, -1, 5, 1, 0, 1, +-6, 0, -3, -1, 0, 4, 4, 1, +1, -1, -4, -2, -1, -2, 3, 1, +2, 2, 0, -2, -6, 0, -1, -1, +7, -1, 2, 3, -5, 2, -4, -2, +0, -1, 8, -4, 7, -2, -2, -1, +-6, 1, -2, 1, 10, -4, 1, 2, +-5, 0, -5, 0, 1, 0, 8, -2, +-1, 4, -6, 0, -4, 0, 5, -3, +7, -1, 1, -1, -4, -1, -4, 0, +3, 0, 3, 2, -3, 2, -5, -1, +2, -4, 6, -1, 6, -2, 1, -2, +-6, 1, -3, 2, 6, -1, 5, -1, +-2, 0, -8, 3, -1, 0, 6, -2, +3, 0, -5, 1, -6, 1, -1, 1, +4, 1, -1, 3, -7, 3, -6, 3, +0, 3, 4, 2, 1, 1, -6, 1, +-3, -1, 2, 1, 3, 0, 0, -1, +-6, -1, -1, -2, 3, 0, 8, -4, +1, -1, -5, 1, -3, 2, 6, -1, +5, -1, 3, -4, -4, 1, -3, 2, +5, 0, 2, 0, -2, -2, -5, 0, +2, -3, 4, 0, 2, -1, -2, -1, +-4, 1, 1, 2, 4, 0, 4, -2, +0, -3, 3, -5, 4, 0, 3, 2, +-2, 2, -4, -2, 3, -6, 3, 0, +2, 0, -1, -1, -4, -1, 0, -1, +1, 3, 1, 2, -2, 1, -2, -1, +1, 0, 5, -1, 4, -1, -3, 0, +-3, 0, -2, 1, 3, 0, -1, 1, +-2, -2, -4, 0, 0, 0, 2, 1, +1, -1, 1, -4, -2, 1, 1, 1, +4, 1, -2, 3, -2, -1, -1, 0, +-3, 4, 5, -4, 3, -2, -6, 2, +-1, -2, 0, 1, 3, -2, -1, 0, +-2, -1, 1, 0, 4, 0, 3, 1, +-1, 1, -1, -1, 4, -3, 3, 1, +0, 1, -2, 0, -6, 2, -2, 0, +2, -1, 0, 0, -4, 1, -4, 2, +-1, 1, 3, 0, 3, 0, -2, 3, +-3, 4, 2, 1, 3, 1, 1, -1, +-2, 0, -4, 1, -1, 0, -3, 2, +-6, 2, -6, 1, -2, -1, 0, 0, +3, -2, 3, -1, 1, -1, 5, -2, +7, -2, 6, -1, 1, 1, 3, -4, +1, -1, -1, 0, -2, -1, -6, 1, +-6, 0, -3, -1, -3, 2, -2, 2, +0, 1, 1, 0, 4, 0, 4, 3, +4, 1, 3, 0, -1, 2, -1, 1, +0, 0, -6, 3, -8, 0, -4, -3, +-5, -1, 0, -3, -4, 3, -5, 4, +1, 1, 7, -1, 6, 3, 7, -1, +9, -4, 2, 2, -1, 2, 1, -1, +-5, 1, -6, -3, -10, 2, -10, 2, +-3, -2, -4, 1, -3, 1, 0, 2, +6, 1, 9, 1, 9, 0, 9, -2, +8, -2, 5, 0, -2, 3, -5, -1, +-10, 1, -11, 0, -9, 0, -10, 3, +-10, 3, -4, 0, 0, 3, 5, 2, +12, -1, 8, 3, 7, 1, 11, -2, +8, 0, 2, -1, -5, -1, -13, 2, +-13, 2, -12, 1, -7, -4, -6, -4, +-4, 0, 0, 3, 9, -1, 11, 1, +8, 3, 12, -1, 15, -2, 9, 1, +0, 2, -6, 0, -9, -1, -9, -2, +-9, -3, -14, 0, -13, -1, -4, -3, +4, -1, 8, 0, 10, 0, 13, -1, +17, -1, 16, 0, 14, -3, 5, -3, +-4, 0, -9, 0, -10, -1, -16, 1, +-19, 0, -15, -1, -6, -2, 4, -3, +8, -2, 12, -3, 17, -2, 23, -3, +19, 1, 11, 1, 3, 0, 0, -2, +-6, 1, -14, 2, -21, 3, -23, 0, +-17, 1, -12, 3, 0, -2, 2, 1, +9, 0, 15, 2, 23, -1, 22, -2, +13, 0, 4, 2, 1, 0, -4, -1, +-13, 0, -23, 1, -22, -1, -16, -1, +-12, 1, -6, 1, -2, 1, 9, 0, +21, -1, 26, -2, 21, -1, 13, 1, +8, 2, 7, -2, -2, -1, -17, 1, +-23, 0, -25, 3, -19, 1, -13, 0, +-13, 3, -2, -2, 12, -1, 20, 1, +22, 1, 20, -1, 18, -2, 15, 0, +10, -1, -3, -1, -14, -3, -22, 1, +-19, -2, -16, -2, -20, 2, -11, -3, +-2, 0, 10, 2, 17, 3, 17, 3, +18, 0, 22, -2, 18, 2, 7, 3, +-7, 1, -15, 0, -20, 1, -17, -2, +-20, 0, -23, 0, -15, -1, -2, 0, +8, 3, 14, 1, 19, -2, 22, -1, +24, 1, 20, 1, 8, 0, -4, 0, +-12, 0, -15, 0, -20, 0, -23, -2, +-23, -1, -14, -2, 1, -1, 4, 3, +11, 0, 15, 1, 25, -3, 28, -1, +20, -1, 11, -2, -3, 1, -8, 0, +-13, 1, -23, 2, -26, -2, -21, -3, +-15, 3, -6, 2, 6, -4, 11, -3, +16, 1, 25, 0, 27, -1, 18, 0, +8, 1, 0, 1, 1, -3, -13, 3, +-23, 0, -24, -2, -22, 1, -15, 3, +-8, 1, -2, 0, 7, -2, 21, -4, +27, -1, 21, 2, 15, 0, 13, -3, +5, 2, 0, 0, -10, 0, -20, -2, +-20, -2, -20, 2, -13, 0, -9, -2, +-3, -3, 6, -1, 17, -1, 22, 0, +20, -2, 18, -2, 12, 2, 8, 1, +3, -2, -12, 0, -17, -2, -18, 1, +-16, -1, -11, -3, -17, 3, -4, -3, +6, 1, 13, 1, 18, -1, 16, -1, +18, -3, 18, -1, 12, -1, 2, -1, +-11, 0, -14, 0, -16, 3, -16, 1, +-18, 1, -17, 2, -8, 3, 4, 2, +7, 4, 9, 3, 11, 2, 17, -1, +18, 1, 5, 5, -2, 0, -8, 1, +-8, -1, -8, -3, -13, -3, -16, -1, +-14, 0, -4, 0, 5, -1, 7, 0, +9, -2, 17, -3, 19, 0, 15, 0, +9, -2, 2, -1, -3, -1, -3, -2, +-10, 1, -14, -3, -15, -2, -7, -2, +-5, 3, -6, 5, -1, 3, 5, 1, +9, 3, 16, -1, 15, -1, 3, 2, +2, 0, 0, 1, -1, -4, -8, -2, +-14, 1, -14, 1, -7, -2, -1, -2, +-2, -1, 0, -1, 4, 2, 12, 0, +15, -4, 10, 0, 4, 2, 7, -4, +3, 0, -4, 4, -10, -1, -8, -5, +-6, 0, -5, -2, -2, -5, -5, 2, +0, 0, 8, -4, 12, -1, 8, 2, +6, -2, 8, -2, 10, -1, 5, -4, +0, -3, -5, 1, -9, 1, -8, 0, +-7, 5, -12, 4, -5, -3, 1, 2, +5, 1, 7, -5, 8, -1, 5, 3, +5, -1, 4, 2, 3, 2, -2, -3, +-4, -2, -1, 2, -5, 0, -6, -3, +-7, 3, -5, 1, 0, -3, 4, 2, +6, -3, 8, -8, 6, 1, 5, 5, +5, -5, 5, -4, 1, 2, 2, -6, +-1, -2, -5, 6, -8, 0, -7, -2, +-5, 7, -2, 2, 1, -5, -2, 5, +3, 2, 6, -6, 4, 4, 1, 5, +3, -7, 1, -2, 1, 6, -4, 0, +-7, 1, -5, 5, 0, -5, 1, -7, +-1, 6, -2, 1, 1, -8, 3, 3, +4, 3, 4, -7, 3, 0, 2, 5, +2, -6, 2, -1, 0, 5, -1, -4, +-6, -1, -3, 9, -1, -1, -1, -7, +-5, 8, -2, 3, 2, -8, 1, 5, +-1, 7, -2, -5, 2, 0, 6, 3, +7, -11, 2, -5, 3, 6, 0, -5, +1, -6, -3, 9, -3, 0, -2, -8, +-2, 8, -1, 4, 2, -11, 2, 2, +0, 8, 1, -7, 2, -1, 3, 8, +1, -8, 2, -5, -2, 11, -2, -1, +-4, -7, 1, 6, -1, 0, 0, -10, +-2, 7, 1, 3, 2, -13, 2, 3, +-3, 13, -1, -7, 2, -2, 0, 12, +0, -4, -2, -3, 0, 10, -1, -3, +-3, -7, -1, 8, -3, 5, -6, -10, +3, 3, -1, 6, 2, -11, 0, 1, +3, 10, 1, -10, 4, -4, 4, 9, +2, -5, 0, -8, 1, 10, 0, -3, +-1, -11, -3, 10, -3, 3, 2, -15, +0, 5, 0, 9, 1, -14, 5, -1, +2, 9, 7, -11, 0, -4, 0, 16, +-4, -3, 5, -13, 1, 9, -3, 2, +-3, -13, 0, 7, 1, 2, 0, -13, +-3, 6, 3, 6, 3, -10, 0, -1, +5, 11, 0, -8, 5, -7, 0, 12, +3, -4, -2, -12, -1, 13, -7, 3, +2, -14, -4, 7, 1, 5, -2, -12, +2, 3, 1, 11, 4, -12, 2, -2, +3, 11, 4, -6, -2, -5, 3, 11, +-3, -2, -1, -9, -8, 12, -1, 5, +-6, -12, 0, 6, -4, 9, 4, -12, +-1, 1, 2, 13, 0, -9, 7, -6, +0, 14, 0, -3, -1, -8, -2, 12, +0, -1, -1, -14, 0, 7, -8, 8, +-1, -12, -2, 3, 1, 12, -3, -10, +6, -2, 0, 11, 9, -9, 0, -5, +5, 11, 0, -6, 2, -9, -5, 11, +-2, 4, -6, -12, -3, 7, -6, 9, +1, -14, 3, 0, 0, 9, 6, -11, +4, -6, 7, 11, 0, -6, 7, -9, +-1, 9, 4, 0, -6, -9, 1, 7, +-6, 2, 0, -11, -6, 4, 2, 6, +-1, -11, 2, 0, -1, 11, 6, -7, +3, -3, 3, 9, 3, -2, -1, -8, +4, 8, -6, 4, -1, -9, -9, 7, +0, 5, -6, -9, 0, 3, -4, 6, +3, -6, 0, -4, 10, 6, 1, -3, +5, -6, 1, 9, 3, 1, -1, -8, +-3, 7, -2, 2, -3, -10, -4, 5, +-4, 4, 2, -10, -2, -4, 4, 9, +-3, -4, 9, -7, 0, 9, 8, -2, +2, -8, 7, 7, -4, 4, 2, -10, +-5, 3, -1, 4, -3, -9, -4, 0, +-1, 4, -4, -2, -1, -3, 4, 6, +4, -2, 2, -7, 7, 7, 4, -1, +6, -7, -8, 8, 2, 3, -2, -11, +0, 2, -9, 8, 1, -8, -7, -2, +1, 8, -4, 0, 0, -3, 2, 6, +6, -1, 4, -7, 5, 3, 5, 3, +-2, -7, 2, 1, -3, 6, -3, -4, +-7, -4, 1, 6, -7, -4, 5, -7, +-3, 7, 3, 1, -5, -3, 7, 5, +4, 2, 8, -11, 2, 3, -4, 12, +-3, -7, -1, -1, -3, 8, -5, -6, +-3, -3, -5, 9, 1, -2, -5, -5, +3, 8, -2, 3, 8, -9, 0, 7, +6, 4, -1, -7, -1, 5, -3, 7, +-2, -3, -5, -4, -2, 9, -7, -1, +-4, -4, -3, 8, -1, 1, 0, -7, +3, 4, 6, 4, 2, -9, 2, 6, +-1, 8, 3, -6, -3, -1, -1, 11, +-7, -5, 0, -5, -5, 8, 0, -1, +-5, -8, 3, 5, 1, 2, 4, -10, +3, 5, -1, 10, 5, -12, 4, 0, +3, 8, -2, -6, -1, -3, -5, 11, +-5, 0, -5, -9, 1, 7, -3, 0, +-1, -6, -1, 6, 4, 4, 2, -11, +5, 3, 1, 9, 0, -5, -1, 0, +1, 9, -1, -6, -3, -6, -2, 11, +-5, -2, -1, -9, -3, 8, 4, 0, +1, -12, 1, 8, 1, 5, 3, -7, +-1, 2, 4, 10, -2, -8, 3, -4, +-4, 12, 2, -8, -4, -7, -3, 9, +-2, -1, 0, -12, 2, 7, -1, 5, +2, -12, 3, 2, 8, 5, 4, -12, +1, 2, -2, 11, 1, -8, -1, -6, +-1, 11, -1, -6, -1, -10, -5, 13, +-1, 1, 0, -11, 0, 7, 2, 7, +1, -11, 4, 2, 1, 11, 3, -12, +3, -5, 1, 13, 0, -9, 3, -10, +-4, 13, -1, -3, -1, -11, 1, 9, +1, 1, 0, -12, 3, 5, 5, 5, +5, -14, -4, 7, 0, 11, 3, -12, +1, -4, -1, 12, -2, -5, -5, -8, +-1, 12, -4, 2, -3, -10, -1, 8, +3, 4, 1, -13, 2, 6, 1, 10, +1, -12, 2, -2, 1, 14, 1, -11, +-1, -5, -5, 14, 1, -7, 0, -12, +-1, 12, 0, -1, 1, -15, 1, 9, +1, 8, 3, -15, 1, 4, 2, 11, +0, -10, 2, -3, 1, 12, -3, -6, +-4, -6, -1, 15, -5, 1, -4, -9, +-2, 11, 2, 1, 0, -13, 1, 9, +1, 8, 3, -16, 2, 1, 4, 11, +0, -11, 0, -5, 1, 12, 1, -10, +0, -9, -3, 15, 0, -4, -3, -11, +-1, 14, -1, 6, 2, -16, 3, 5, +-1, 13, 0, -14, 3, 0, 1, 13, +2, -15, 3, -8, 0, 14, -1, -6, +-3, -11, -2, 17, -5, 1, 3, -15, +-3, 13, 2, 7, -1, -17, 8, 3, +2, 9, 5, -16, -3, 1, 3, 12, +0, -12, -1, -5, -3, 16, -5, -2, +-3, -11, 0, 14, 3, -2, -1, -14, +1, 12, -3, 9, 4, -16, 0, 5, +1, 14, -5, -14, 5, -2, -6, 18, +4, -14, -4, -7, 1, 15, 0, -8, +3, -13, 2, 12, -1, 4, 0, -17, +4, 9, 2, 8, -2, -14, 1, 5, +1, 11, 3, -15, 0, -4, 0, 17, +-3, -12, 3, -10, -2, 16, 4, -6, +-2, -12, 3, 11, 0, 4, -2, -14, +4, 8, -1, 8, 2, -16, -3, 5, +4, 12, -4, -14, 2, -2, -5, 15, +7, -13, -4, -8, 3, 17, -4, -4, +4, -14, 0, 12, 5, 3, -2, -16, +2, 9, 0, 7, 4, -19, -1, 6, +-3, 13, 1, -14, -2, -5, 6, 14, +-8, -5, 3, -9, -6, 17, 2, 1, +-5, -12, 9, 10, -1, 0, 6, -17, +-3, 9, 1, 12, -5, -15, 3, 1, +-3, 14, -1, -13, 1, -4, -4, 18, +1, -9, -2, -8, 3, 15, 0, -4, +4, -14, -4, 15, 0, 7, -1, -17, +3, 8, -6, 12, 1, -17, 0, 1, +-1, 13, 2, -15, -1, -5, 1, 16, +-3, -6, 4, -9, 0, 13, 1, 3, +-7, -11, 9, 8, -3, 3, 3, -13, +-7, 8, 2, 9, -6, -13, 0, 3, +-2, 10, 1, -10, -2, -4, 4, 12, +-1, -3, -2, -7, 2, 14, -1, -3, +5, -12, -5, 12, 3, 5, -7, -12, +4, 5, -2, 5, 4, -12, -6, 0, +6, 10, -5, -9, 8, -7, 0, 11, +6, -9, -1, -7, 2, 11, 3, -3, +1, -13, -2, 12, -5, 5, 1, -13, +-5, 6, 1, 8, -5, -10, 3, 0, +-4, 13, 3, -10, 1, -4, 1, 13, +3, -7, 2, -8, 3, 9, 2, -4, +3, -12, -5, 10, 0, 6, -9, -7, +1, 5, -5, 7, 1, -7, -5, 1, +6, 9, 0, -10, 6, -4, 0, 9, +2, -2, 0, -10, 3, 10, -3, 0, +-1, -8, -3, 8, -3, 3, 0, -10, +-3, 5, 0, 8, -2, -10, 5, 0, +-3, 10, 4, -6, -3, -2, 4, 10, +-2, -6, 5, -6, -4, 8, 1, 2, +-5, -8, 3, 4, -4, 4, 1, -10, +-2, 5, 1, 4, 5, -10, 0, 0, +4, 7, -3, -4, 4, -3, -3, 10, +0, -1, -4, -4, 0, 7, -3, -1, +0, -8, -2, 6, -2, 3, 0, -8, +-1, 3, -1, 8, -1, -7, 8, -4, +2, 5, 6, -8, 2, -4, 0, 10, +-3, -4, 3, -5, -5, 7, 1, -2, +-3, -6, 1, 5, -5, 5, -2, -3, +1, 1, 3, 6, 0, -7, 4, 0, +-1, 8, 2, -5, -1, 1, -3, 6, +2, -4, -6, -2, -3, 9, -5, -2, +6, -8, -4, 4, 7, -2, 1, -9, +5, 2, 1, 2, 5, -6, 0, 1, +2, 4, 0, -3, -2, 0, 0, 4, +-3, -1, 0, -5, -1, 4, 1, -3, +0, -5, 0, 2, 4, -2, 2, -6, +3, 1, 2, 3, 1, -2, -3, 4, +-2, 6, -1, -2, -1, -2, 1, 2, +-4, 0, -1, -4, 0, 3, -2, 1, +-1, -4, 3, 0, 3, 0, 0, -3, +3, 2, 0, 2, 5, -6, 1, 0, +1, 4, -1, -5, -1, 1, -5, 5, +-2, 0, -4, 0, 1, 0, 1, 0, +-3, -2, 6, -1, 0, 2, 4, -5, +0, 2, 4, 0, 3, -5, 1, 0, +-3, 6, -7, 3, -3, 0, -2, 4, +-2, -1, -2, -1, 0, 2, 1, 0, +0, -2, 2, 3, 0, 0, 7, -6, +0, 3, -1, 5, -2, -2, 2, -1, +0, 0, -3, 1, -2, -2, 1, 0, +-1, -1, -4, 2, 2, 1, 0, 0, +1, -2, 0, 3, 2, 0, 1, -1, +-1, 3, 2, -1, -2, -1, -3, 3, +1, -1, 1, -3, -2, -1, 0, 1, +1, -3, 3, -3, -1, 4, -1, 0, +2, -2, 2, 1, 3, -1, -1, -2, +2, 0, 1, 0, -2, 1, -4, 3, +1, -1, -1, -2, -1, 0, -2, 4, +-2, -1, 1, -1, -1, 4, 1, -2, +4, -4, 1, 1, 0, 1, -4, 1, +3, -1, -2, 2, 0, -3, -4, 4, +-4, 3, 1, -3, -1, 1, -1, 3, +-2, 0, 3, -3, 2, 2, 2, -3, +4, -4, -2, 4, 2, -3, 1, -2, +0, 1, 0, -1, -2, -1, 0, 0, +-3, 4, -2, -1, -1, 1, 0, 2, +0, -1, 3, -1, 0, 2, 3, -3, +1, -3, 4, -1, 0, 0, -1, -2, +2, -1, 2, -2, 0, 0, -5, 3, +0, 1, -3, 0, 2, -1, 0, 2, +3, -4, 3, -2, 0, 1, 1, 0, +-1, -1, 3, 0, -1, -2, -1, 1, +-3, 2, 2, -1, 1, -3, 1, -1, +1, 1, -2, 0, 0, 1, -2, 3, +3, -4, 3, -3, 0, 2, 3, -5, +0, -1, 0, 1, -1, 0, 1, -1, +-1, -1, 3, -2, 0, -3, 4, -2, +2, -1, 0, -1, 1, -1, 1, 0, +1, 1, -4, 1, 2, 1, -5, 2, +1, -1, -1, 1, -3, 3, -4, 1, +-1, 0, 3, -2, -2, 0, 2, 0, +-1, 0, 2, -1, 0, -2, 6, -4, +3, -3, -2, 2, 1, -1, 1, -2, +3, -2, 0, -2, 5, -3, -1, -2, +2, 1, -3, 2, 1, -1, 0, 1, +-1, 1, 2, 0, -1, -1, 3, 1, +-3, 0, 1, 2, -4, 2, 1, -1, +1, -2, -1, 1, -2, 3, -2, -1, +4, 0, -6, 3, 3, -1, -1, 0, +2, 1, 0, -3, 3, -2, -1, 1, +-2, 0, 3, 0, -3, 0, 1, 1, +-3, 0, 2, 2, -5, 3, 0, 2, +0, -1, 2, -2, 1, 1, -2, 0, +0, 2, -3, 0, 5, -3, -2, 1, +-4, 4, 0, -2, 1, -1, 0, 2, +-2, 0, 4, 0, -4, 0, 8, -3, +-3, 1, 5, -2, 0, -1, 2, 0, +1, -1, -1, 1, 2, 0, -3, 0, +2, 2, -3, 1, 4, -1, -3, 1, +0, 3, -1, 0, -2, 3, 2, 1, +-3, 3, 1, 1, 1, -2, 7, -3, +-1, -2, 4, 0, 1, -1, 0, 1, +3, -1, 1, 1, 2, 0, -1, 0, +5, 1, 0, -1, 3, 1, -1, 2, +3, -1, 2, -1, 2, 1, 4, 0, +-3, 1, 4, 3, -4, 4, 5, -2, +1, 1, 4, 2, 4, -4, 4, 0, +5, 1, 1, -2, 5, 1, 0, 1, +7, 1, -3, 1, 8, 0, -2, 2, +4, -1, 4, 0, 5, 0, 7, -3, +1, 3, 8, -1, 5, -5, 11, -4, +6, -1, 8, -4, 6, -3, 5, 1, +8, -3, 0, 2, 9, -1, 3, 1, +5, 0, 3, 2, 6, 2, 4, -2, +6, 1, 5, 3, 3, -2, 10, -2, +3, 3, 5, 2, 3, -1, 10, 1, +4, 0, 7, -1, 5, 4, 5, 0, +11, -5, 8, -1, 12, -1, 5, -2, +10, 2, 5, 2, 9, -3, 6, 2, +4, 5, 7, -1, 7, -2, 10, 4, +2, 2, 12, -3, 8, -1, 14, -3, +6, -1, 11, 1, 9, 1, 9, -2, +11, -1, 9, 1, 9, -1, 6, 2, +9, 3, 8, -1, 11, -1, 11, 2, +10, -1, 9, 0, 10, 1, 10, 2, +8, -2, 15, 1, 8, 3, 11, -1, +9, 2, 12, 1, 14, -7, 14, -3, +10, 6, 10, -1, 10, 4, 11, 0, +18, -4, 8, 0, 13, 3, 12, 0, +10, 1, 12, 4, 13, 0, 13, -2, +11, -1, 17, 0, 10, -2, 15, 1, +11, 4, 17, -4, 12, 2, 13, 2, +16, -2, 13, -4, 16, 5, 7, 5, +18, -2, 12, 4, 18, -1, 14, -3, +13, 2, 14, 3, 13, -1, 18, 0, +16, 3, 16, 0, 13, 1, 14, 4, +17, -2, 16, -4, 23, -1, 17, 1, +17, 1, 14, 3, 19, 0, 18, -7, +20, -2, 17, 3, 18, -2, 16, 6, +12, 8, 19, 0, 17, -3, 21, 1, +18, -3, 23, -5, 20, 4, 17, 4, +22, -4, 19, 0, 22, -1, 20, -7, +21, 0, 18, 4, 20, 0, 19, 2, +21, 3, 19, -2, 21, -6, 23, 0, +21, 0, 20, -1, 24, 3, 19, 4, +18, 1, 19, -1, 22, 2, 16, -2, +24, 1, 20, 6, 25, -2, 24, -1, +25, -1, 24, -4, 19, -1, 23, 2, +22, 1, 25, -2, 23, 6, 23, 0, +28, -9, 24, -3, 27, -3, 24, -3, +23, 5, 24, 5, 27, -4, 28, -3, +23, 0, 27, -4, 22, -2, 26, 5, +24, 2, 28, 0, 22, 6, 24, 0, +24, -5, 22, 1, 27, 0, 25, 0, +25, 4, 26, 6, 25, -1, 27, -4, +27, -3, 30, -5, 24, -1, 29, 5, +28, 2, 26, 1, 25, 3, 23, -1, +29, -8, 25, 0, 29, 5, 24, 2, +30, 4, 28, 2, 29, -3, 25, -4, +28, 0, 29, -3, 30, -1, 28, 9, +24, 6, 28, -5, 31, -4, 29, -5, +30, -5, 24, 4, 29, 9, 29, -1, +32, 1, 28, 1, 29, -6, 27, -2, +28, 1, 31, 3, 25, 2, 35, 5, +27, -1, 31, -5, 24, 0, 31, -2, +27, -1, 31, 2, 34, 6, 29, 0, +30, 1, 27, 1, 32, -9, 33, -5, +26, 8, 30, 8, 23, 5, 35, 5, +24, 0, 31, -6, 26, 0, 31, 1, +31, -1, 27, 9, 33, 8, 26, -1, +34, -4, 30, -4, 37, -8, 31, -2, +32, 8, 31, 5, 30, -1, 33, 3, +28, -5, 34, -9, 27, 2, 35, 2, +32, 2, 31, 6, 34, 5, 31, -9, +37, -7, 29, -2, 37, -3, 27, 3, +36, 8, 34, 1, 31, -3, 33, -1, +30, -5, 33, -5, 28, 4, 35, 8, +29, 2, 35, 4, 30, 3, 37, -14, +35, -7, 30, 4, 32, 2, 29, 7, +31, 10, 35, -2, 29, -7, 34, -2, +29, -4, 37, -5, 28, 7, 37, 9, +32, -4, 37, -1, 31, -2, 35, -10, +32, -5, 33, 7, 31, 5, 31, 3, +32, 7, 31, -2, 31, -10, 35, -3, +31, 1, 35, -2, 31, 10, 31, 10, +30, -1, 30, -3, 34, -2, 30, -8, +39, -6, 32, 8, 33, 6, 28, 0, +34, 2, 29, -3, 32, -11, 32, 2, +28, 5, 36, 0, 33, 6, 32, 8, +28, -6, 35, -9, 36, -3, 30, -3, +34, 2, 27, 14, 32, 4, 31, -5, +31, -1, 32, -6, 27, -4, 32, 5, +29, 5, 36, 2, 26, 6, 35, 2, +26, -9, 33, -5, 28, 5, 31, -1, +33, 3, 32, 8, 35, 0, 25, -7, +32, -3, 29, -4, 33, -4, 29, 9, +28, 7, 35, -1, 26, 2, 34, -1, +27, -10, 32, 0, 27, 6, 32, 1, +30, 4, 28, 9, 32, -3, 23, -8, +32, -2, 29, -4, 34, 0, 25, 12, +30, 8, 33, -8, 28, -5, 35, -6, +29, -6, 32, -2, 29, 5, 28, 5, +29, 3, 28, 3, 30, -7, 23, -6, +29, 4, 23, 3, 34, 0, 27, 10, +30, 6, 27, -12, 27, -7, 29, 2, +29, -4, 33, -2, 21, 12, 27, 4, +29, -4, 27, -2, 28, -9, 27, -3, +26, 3, 25, 1, 28, 4, 28, 10, +31, -2, 24, -12, 23, -6, 28, 5, +28, 0, 27, 2, 23, 10, 26, 2, +24, -7, 25, -5, 28, -4, 28, -3, +25, 6, 20, 3, 29, 1, 28, 5, +27, -2, 21, -10, 19, -2, 26, 2, +30, 1, 24, 6, 22, 6, 25, -6, +24, -8, 19, 1, 28, -3, 27, -4, +26, 11, 14, 8, 21, -4, 29, -4, +30, 1, 21, -5, 15, -5, 20, 3, +26, 10, 20, 14, 14, 0, 20, -5, +22, -1, 19, 1, 23, -5, 22, -1, +29, 16, 12, 6, 19, -17, 19, -1, +28, 15, 18, -2, 16, -12, 16, 2, +23, 13, 28, 2, 21, -15, 20, -4, +20, 3, 21, -4, 25, -11, 20, 7, +24, 15, 16, -2, 15, -17, 18, -4, +31, 12, 17, -1, 16, -4, 11, 4, +17, 3, 25, -2, 19, -3, 17, 0, +17, -3, 18, -4, 12, 7, 19, 8, +26, -3, 13, 1, 11, -7, 11, -1, +27, 2, 24, -1, 12, 10, 4, 3, +17, -15, 22, -1, 16, 13, 13, 0, +12, -2, 12, 3, 11, 4, 17, 0, +21, -5, 19, 2, 5, 5, 1, -6, +22, 3, 23, 14, 13, 6, 0, -6, +9, -14, 21, 0, 25, 7, 11, -3, +10, 4, 14, 7, 14, -10, 10, -7, +16, 4, 20, 5, 14, -3, 3, -15, +9, 9, 24, 16, 21, -3, 1, -9, +-3, -7, 14, -4, 29, 6, 15, 7, +-3, 11, 5, 4, 20, -20, 14, -8, +11, 6, 11, 3, 16, 4, 2, 2, +-1, -2, 20, 0, 27, 3, 7, 3, +-10, -11, 10, -24, 25, 13, 20, 28, +1, -3, 2, -10, 7, -8, 14, 1, +9, 0, 15, -10, 14, 14, 0, 19, +-1, -18, 16, -17, 27, 12, 8, 10, +-9, -10, 1, -26, 18, 10, 21, 33, +6, -1, 0, -14, -1, -6, 10, -8, +12, 2, 14, 3, 9, 9, -2, 14, +3, -18, 10, -14, 17, 13, 11, 0, +3, -4, -9, -8, 6, -8, 23, 18, +19, 15, -5, -3, -13, -16, 9, -21, +19, 8, 12, 19, -2, -3, 3, 4, +8, -3, 6, -18, 4, -1, 18, 3, +10, 10, -15, 2, -13, -24, 24, 9, +31, 33, -5, -2, -25, -27, 9, -20, +27, 7, 11, 20, -15, 1, 1, 5, +10, 8, -4, -19, -4, -10, 21, 13, +17, 8, -9, -5, -22, -20, 16, 3, +31, 32, 3, 1, -26, -19, 2, -17, +19, -6, 8, 20, -4, 16, 3, -5, +5, -3, -10, -12, 3, -5, 19, 13, +12, -3, -14, 3, -18, -1, 18, -20, +20, 19, -1, 23, -12, -10, 3, -25, +4, -22, 2, 22, 6, 35, 9, -11, +-5, -13, -20, 5, 8, -6, 24, 1, +7, 3, -20, 10, -11, -1, 13, -26, +10, 15, 5, 36, -5, -13, 3, -32, +-9, -11, 5, 12, 16, 21, 13, -6, +-14, -4, -13, 7, 8, -21, 15, -3, +0, 24, -8, 4, -2, -14, 0, -21, +1, 16, 12, 37, 13, -16, -10, -28, +-27, 0, 6, 0, 31, 13, 8, 16, +-29, -5, -6, -7, 21, -16, 14, -5, +-12, 17, -3, -4, 11, -3, -4, 1, +-18, -5, 10, 16, 30, 14, -8, -11, +-33, -27, -1, -24, 36, 32, 13, 47, +-25, -26, -14, -33, 19, 12, 15, 11, +-6, -9, -6, -15, 6, 12, -2, 25, +-8, -24, 6, -9, 13, 37, 0, 4, +-19, -34, -8, -28, 13, 25, 13, 54, +-1, -9, -12, -36, -7, 3, 6, 2, +18, 1, 5, 6, -15, -7, -15, 6, +8, 5, 18, 5, -3, 9, -9, -16, +-2, -11, 11, 2, -3, -9, -2, 15, +10, 31, 3, 1, -14, -27, -16, -28, +19, 17, 21, 44, -9, -21, -25, -36, +3, 27, 24, 26, 9, -9, -15, -28, +-6, -7, 8, 22, 3, -11, -4, 0, +-3, 39, 8, 2, -3, -29, -12, -18, +4, 8, 12, 30, 7, -4, -17, -15, +-13, 20, 4, 2, 15, -2, -3, 16, +-16, -5, -11, -20, 9, -6, 13, 27, +-3, 37, -5, -23, -7, -32, -3, 21, +2, 12, 3, -9, -3, 3, -10, 16, +-6, 20, -1, -20, 9, -21, -3, 41, +-8, 16, -9, -41, -1, -13, 1, 35, +0, 44, -1, -10, -10, -37, -16, 12, +-3, 20, 16, -7, 5, 6, -25, 9, +-18, 8, 13, 4, 17, -12, -16, 11, +-23, 14, 4, -14, 10, 3, -20, 12, +-17, 15, 16, 20, 12, -9, -31, -19, +-27, 2, 18, 13, 29, 23, -29, 4, +-45, -12, 7, 16, 29, 13, -13, 2, +-38, 4, -2, -12, 16, 7, -10, 22, +-24, 5, -2, 9, 12, 0, -15, -2, +-25, 7, -6, -12, 16, 8, -7, 39, +-24, 3, -24, -19, 7, -5, 8, 26, +-13, 29, -24, -27, -20, -23, 2, 42, +0, 37, -11, -5, -29, -17, -9, -6, +6, 34, -17, 13, -27, -32, -8, 18, +8, 53, -26, 9, -39, -35, -11, -10, +21, 65, -16, 30, -52, -61, -25, -10, +17, 74, 7, 45, -47, -37, -42, -46, +5, 46, 15, 65, -44, -38, -43, -33, +9, 68, 4, 50, -49, -44, -42, -49, +28, 61, 3, 77, -62, -60, -47, -52, +21, 83, 5, 72, -60, -38, -42, -57, +3, 52, -5, 73, -37, -55, -29, -40, +-3, 92, -23, 57, -51, -72, -22, -42, +11, 91, -24, 77, -66, -82, -36, -51, +16, 121, -18, 67, -68, -87, -31, -33, +12, 102, -39, 55, -71, -92, -7, -24, +20, 148, -60, 38, -88, -126, 4, -5, +33, 139, -60, 30, -96, -108, -9, -1, +21, 140, -50, 13, -82, -100, -9, 36, +2, 106, -70, -13, -66, -71, 6, 35, +-1, 106, -82, -1, -64, -82, 8, 28, +-10, 88, -76, 1, -52, -43, -8, 17, +-48, 78, -70, 19, -28, -41, -8, 35, +-67, 57, -74, -20, -16, -15, -8, 49, +-76, 55, -82, -4, -11, -18, -18, 43, +-77, 30, -77, -19, 2, 30, -21, 52, +-108, -10, -78, -9, 18, 45, -13, 59, +-125, -9, -83, -40, 13, 50, -17, 71, +-110, -13, -72, -12, -4, 43, -41, 37, +-93, -10, -55, -12, -12, 61, -57, 51, +-101, -34, -57, 0, -12, 69, -48, 38, +-98, -20, -64, -6, -29, 53, -55, 39, +-86, -13, -50, 29, -44, 61, -88, -10, +-76, -11, -29, 48, -41, 49, -102, 8, +-82, -10, -34, 34, -54, 41, -79, 13, +-66, 28, -60, 11, -80, -7, -63, 49, +-49, 49, -68, -14, -77, 13, -81, 61, +-71, 17, -60, -26, -39, 35, -78, 82, +-112, -12, -66, -32, -31, 71, -63, 51, +-107, -14, -81, 20, -60, 29, -55, 6, +-74, 37, -91, 53, -87, 5, -56, -11, +-58, 44, -99, 37, -77, -14, -43, 42, +-88, 60, -119, -26, -63, 11, -31, 82, +-96, 14, -118, -19, -70, 45, -49, 39, +-82, -12, -88, 34, -78, 70, -88, -13, +-79, -19, -76, 78, -75, 31, -83, -29, +-85, 58, -89, 53, -78, -40, -70, 25, +-96, 106, -93, 0, -74, -51, -87, 66, +-106, 82, -69, -28, -52, 11, -119, 81, +-119, -13, -41, -29, -46, 92, -139, 56, +-119, -49, -38, 22, -66, 92, -123, 2, +-103, -35, -50, 65, -83, 73, -110, -29, +-104, -13, -75, 78, -64, 67, -92, -9, +-119, -30, -104, 40, -55, 93, -74, 18, +-113, -50, -115, 51, -82, 103, -62, -31, +-85, -57, -102, 108, -106, 97, -68, -99, +-82, -33, -116, 177, -86, 63, -62, -129, +-113, 19, -140, 174, -51, 1, -48, -106, +-132, 77, -125, 140, -45, -42, -93, -77, +-131, 95, -54, 117, -66, -35, -165, -50, +-103, 65, 9, 88, -97, 8, -195, -29, +-67, 26, 4, 66, -134, 28, -165, -15, +-34, 26, -46, 75, -155, 32, -128, -37, +-43, 12, -56, 108, -118, 38, -127, -68, +-101, 17, -46, 121, -51, 29, -140, -70, +-147, 26, -41, 122, -30, 7, -143, -73, +-135, 64, -44, 124, -63, -22, -132, -77, +-111, 69, -49, 137, -74, -14, -121, -92, +-112, 62, -58, 132, -50, -15, -123, -64, +-142, 69, -61, 111, -25, -25, -133, -65, +-135, 97, -39, 112, -58, -57, -155, -52, +-91, 107, -7, 96, -118, -52, -160, -45, +-31, 113, -23, 83, -172, -81, -128, 1, +18, 137, -71, 29, -199, -86, -84, 30, +31, 145, -106, 13, -191, -95, -65, 59, +12, 123, -102, -24, -170, -37, -63, 74, +-8, 54, -95, -18, -161, 6, -61, 63, +-2, 32, -104, -10, -161, 28, -48, 25, +4, 13, -114, 50, -149, 10, -38, -16, +-23, 64, -127, 46, -113, -24, -27, 22, +-63, 72, -126, 2, -76, -37, -36, 81, +-87, 85, -105, -79, -58, 2, -77, 144, +-83, -26, -59, -67, -69, 127, -102, 60, +-80, -113, -34, 35, -78, 181, -100, -58, +-65, -136, -51, 182, -96, 130, -77, -198, +-35, 8, -78, 248, -109, -63, -59, -170, +-19, 164, -88, 153, -117, -152, -46, -34, +-26, 200, -102, -20, -98, -124, -10, 148, +-63, 78, -126, -148, -58, 63, 7, 163, +-92, -94, -134, -61, -26, 163, -11, 31, +-99, -131, -108, 80, -25, 155, -44, -106, +-89, -50, -86, 179, -34, -14, -34, -103, +-89, 129, -85, 50, -43, -112, -18, 66, +-77, 132, -115, -91, -41, -54, 4, 180, +-80, 12, -119, -165, -27, 132, -5, 157, +-91, -176, -112, -28, -14, 220, -7, -17, +-109, -149, -93, 105, 2, 131, -27, -113, +-113, -25, -63, 161, -9, -43, -43, -87, +-84, 146, -63, 24, -27, -112, -42, 92, +-79, 88, -53, -107, -26, 11, -55, 144, +-81, -39, -27, -92, -22, 116, -87, 67, +-63, -121, -7, 44, -45, 138, -90, -98, +-34, -44, -19, 166, -58, -19, -65, -124, +-35, 110, -34, 97, -55, -117, -54, -7, +-53, 173, -39, -40, -31, -132, -58, 150, +-74, 82, -7, -156, -15, 31, -103, 157, +-57, -60, 18, -89, -38, 108, -109, 64, +-27, -88, 8, 9, -77, 96, -81, -21, +8, -29, -21, 66, -114, -9, -19, -34, +16, 85, -84, 19, -93, -71, 21, 41, +-1, 83, -119, -32, -54, -60, 36, 72, +-36, 66, -106, -77, -24, -17, 20, 80, +-49, 21, -77, -33, -45, -33, 7, 48, +-21, 92, -98, -66, -53, -73, 27, 145, +-34, 42, -84, -151, -46, 35, 9, 159, +-27, -56, -100, -132, 0, 114, -1, 132, +-84, -160, -21, -49, -17, 199, -61, -29, +-31, -134, -8, 86, -50, 87, -50, -58, +-16, -52, -24, 65, -49, 49, -18, -58, +-29, 2, -71, 28, 2, -6, 22, 61, +-113, -37, -79, -83, 81, 137, 6, 57, +-170, -177, -45, 8, 132, 198, -45, -31, +-197, -213, 24, 80, 122, 254, -117, -156, +-146, -222, 68, 243, 61, 137, -118, -236, +-100, -59, 60, 207, 2, 58, -105, -195, +-9, -21, -5, 202, -61, -31, 12, -120, +-35, 34, -70, 49, 9, 57, -15, -55, +-40, -102, -65, 127, -2, 96, 27, -156, +-97, -51, -24, 158, 35, 22, -48, -147, +-61, 2, 4, 153, -8, -36, -47, -139, +-44, 130, -26, 53, 34, -175, -24, 111, +-130, 104, 16, -219, 119, 26, -126, 249, +-144, -132, 100, -233, 75, 237, -130, 186, +-147, -307, 114, -99, 102, 323, -181, 46, +-123, -340, 141, 2, 53, 402, -173, -127, +-77, -382, 92, 301, 50, 209, -126, -342, +-85, 8, 71, 205, 46, -82, -94, -43, +-92, 5, 68, -1, 39, 63, -91, -43, +-65, -35, 36, 29, 38, -11, -71, 83, +-87, -56, 65, -164, 29, 220, -126, 89, +-2, -315, 69, 70, -65, 277, -76, -177, +41, -189, 43, 223, -74, 80, -85, -232, +68, 46, 50, 158, -115, -126, -45, -45, +63, 101, 33, -18, -73, -75, -102, 19, +85, 97, 81, -46, -142, -137, -90, 121, +122, 125, 59, -207, -154, -35, -83, 226, +140, -87, 64, -142, -176, 127, -93, 18, +229, -77, -6, 41, -273, 15, 95, -79, +184, 44, -120, 98, -171, -140, 94, -57, +173, 191, -169, -17, -147, -178, 189, 44, +51, 163, -163, -58, -38, -187, 117, 94, +66, 182, -188, -159, -32, -143, 198, 205, +-54, 55, -145, -197, 50, 16, 97, 133, +-59, -20, -69, -117, 48, 26, 31, 104, +-28, -82, -6, -40, -33, 78, 29, -53, +52, 6, -97, 81, 10, -111, 53, -57, +-16, 196, 0, -19, -51, -236, 26, 91, +70, 225, -72, -105, -54, -264, 98, 130, +39, 337, -105, -261, -26, -328, 125, 364, +48, 229, -156, -388, -32, -184, 197, 407, +3, 122, -194, -438, 66, -5, 133, 360, +-37, -80, -71, -229, -36, 55, 127, 141, +67, -2, -182, -120, -5, -21, 206, 88, +-46, 14, -114, -39, 73, -56, 9, 3, +44, 108, 31, -31, -132, -115, 60, 47, +150, 52, -88, 1, -67, -45, 76, -90, +59, 120, -2, 79, -44, -216, -17, 20, +102, 198, 66, -158, -119, -61, -26, 166, +152, -114, 18, -37, -78, 139, 18, -101, +45, -75, 49, 95, 33, 28, -64, -77, +-12, -56, 117, 78, 48, 55, -110, -97, +-10, -46, 150, 87, 29, 26, -118, -101, +32, -3, 129, 76, -23, -44, -34, -43, +54, 64, 6, -18, 0, -119, 105, 114, +-4, 121, -124, -296, 102, -20, 189, 406, +-121, -181, -172, -391, 250, 316, 154, 278, +-244, -384, -25, -192, 235, 381, 65, 87, +-162, -350, -28, -49, 207, 270, 41, 49, +-134, -265, 56, -68, 101, 260, -18, 22, +26, -260, 53, 3, -29, 229, -14, -72, +164, -209, 7, 157, -180, 95, 135, -226, +218, 64, -167, 156, -108, -216, 266, -13, +46, 224, -166, -182, 90, -101, 114, 220, +-44, -107, 24, -98, 79, 149, -26, -94, +5, -78, 115, 149, 25, -57, -71, -142, +75, 130, 97, 5, -16, -149, 18, 121, +5, -20, 49, -156, 129, 160, -58, 19, +-96, -207, 208, 61, 105, 143, -191, -112, +44, -114, 208, 99, -57, 24, -20, -63, +111, 7, -42, -91, 49, 5, 152, 188, +-87, -144, -60, -238, 198, 241, 79, 153, +-132, -299, 6, -89, 177, 226, 46, 51, +-58, -206, -13, -97, 73, 181, 193, 44, +-48, -167, -179, -56, 199, 52, 238, 83, +-206, -31, -101, -187, 308, 49, 24, 203, +-173, -157, 145, -171, 108, 181, -73, 3, +89, -165, 57, 91, -54, 21, 106, -176, +84, 79, -53, 149, 35, -246, 111, -108, +-8, 301, 24, -64, 97, -280, -11, 105, +-26, 124, 155, -74, 85, -105, -175, -48, +100, 113, 222, 41, -115, -185, -22, -46, +156, 155, 20, -30, 34, -195, 68, 53, +-83, 125, 120, -163, 187, -55, -163, 151, +-35, -117, 289, -107, 18, 148, -188, -60, +155, -140, 184, 119, -142, -26, 23, -154, +211, 155, -64, -3, -61, -284, 208, 130, +58, 220, -125, -284, 97, -211, 173, 300, +-48, 129, -23, -405, 86, -70, 81, 371, +76, -98, -63, -295, -16, 97, 226, 105, +42, -68, -164, -57, 124, -64, 189, -20, +-112, 89, 42, -6, 158, -163, -101, -59, +70, 140, 202, 70, -121, -222, -52, -154, +278, 239, 36, 109, -189, -327, 136, -133, +210, 295, -57, 68, -72, -349, 143, -100, +106, 302, -44, 38, 47, -344, 63, -51, +29, 278, 72, -32, 28, -260, -2, -10, +100, 134, 78, 22, -48, -162, 54, -144, +155, 150, -9, 117, -40, -252, 143, -142, +25, 217, 16, 64, 106, -230, -56, -128, +62, 149, 213, 143, -126, -220, -66, -250, +340, 252, -14, 177, -199, -370, 202, -131, +169, 271, -74, 20, 11, -210, 76, -127, +52, 101, 120, 155, 14, -181, -90, -207, +140, 115, 188, 127, -81, -81, -79, -223, +185, -25, 133, 231, -32, -40, -16, -286, +15, -47, 169, 216, 186, 96, -195, -351, +-122, -226, 417, 454, 142, 117, -345, -621, +44, -20, 367, 550, 24, -187, -144, -477, +-16, 208, 185, 243, 241, -244, -148, -134, +-198, 88, 350, -29, 234, 6, -298, -23, +14, -207, 286, 84, 4, 160, -13, -269, +43, -64, 28, 177, 119, -130, 57, -59, +-6, 48, 24, -108, 79, -2, 109, 41, +-5, -99, 23, -63, 87, 53, 13, -34, +126, -122, 75, 40, -142, 34, 118, -167, +262, -26, -53, 141, -126, -128, 80, -189, +289, 128, 72, 84, -260, -195, 21, -140, +392, 153, 105, 98, -343, -263, 10, -118, +482, 205, 27, 14, -336, -206, 91, -89, +345, 123, 74, 61, -194, -189, -56, -134, +297, 136, 203, 77, -187, -207, -133, -129, +299, 142, 239, 65, -211, -198, -77, -148, +289, 165, 132, 58, -151, -230, 34, -80, +150, 130, 91, 52, 6, -211, -31, -138, +117, 225, 95, 15, 29, -312, 15, -20, +53, 250, 90, -72, 29, -344, 35, 96, +132, 257, -3, -261, -48, -210, 196, 202, +113, 46, -109, -192, 1, -76, 199, 51, +147, 25, -123, -43, -74, -142, 259, -71, +204, 173, -183, 11, -136, -331, 291, 1, +302, 325, -235, -177, -249, -349, 404, 218, +322, 174, -329, -284, -197, -109, 478, 120, +194, 14, -356, -59, 37, -127, 279, -70, +109, 139, -45, 53, -188, -309, 200, -100, +376, 391, -229, -116, -221, -479, 402, 247, +182, 286, -295, -366, 73, -192, 270, 257, +-35, 32, -45, -231, 113, -33, 69, 36, +14, 2, 91, 28, 2, -179, -2, -102, +184, 225, 7, -11, -101, -329, 215, 16, +82, 275, -164, -135, 141, -284, 220, 94, +-113, 148, -78, -78, 233, -207, 79, -56, +-38, 241, 11, -49, 12, -338, 181, 96, +119, 212, -212, -179, 12, -230, 437, 116, +-78, 179, -325, -255, 279, -145, 303, 230, +-157, -63, -193, -157, 234, 1, 242, 9, +-113, 53, -126, -120, 126, -116, 252, 104, +-42, 30, -162, -139, 117, -124, 249, 104, +-10, 106, -204, -206, 119, -164, 309, 206, +-123, 71, -121, -298, 195, -24, 103, 169, +-42, -61, -11, -109, 136, -73, 4, 68, +-7, 26, 126, -131, 0, -27, 16, -34, +81, 66, 0, -9, 36, -222, 121, 126, +-64, 42, -7, -219, 247, 126, -95, -20, +-121, -191, 293, 135, 51, 9, -189, -176, +123, -24, 160, 111, -93, 6, 52, -228, +112, 24, -96, 159, 104, -156, 135, -28, +-131, -23, 54, -93, 170, 210, -38, -143, +-32, -269, 59, 266, 104, 39, 68, -213, +-140, -51, 56, 34, 202, 162, -24, -179, +-39, -218, -44, 245, 175, 2, 167, -139, +-276, -61, 61, -92, 313, 280, -168, -37, +-47, -475, 159, 229, 1, 327, 40, -347, +14, -197, -18, 209, 45, 78, 148, -87, +-42, -198, -109, -25, 167, 309, 100, -132, +-90, -321, -66, 181, 182, 135, 123, -101, +-227, -196, 57, -21, 273, 288, -154, -121, +-23, -334, 149, 201, -88, 238, 109, -338, +55, -124, -111, 329, 129, -175, 49, -93, +-93, 118, 108, -222, 69, 269, -99, -75, +63, -443, 98, 542, -23, -81, -3, -538, +37, 511, 40, -60, 46, -364, -27, 386, +-33, -242, 141, -131, 25, 489, -92, -472, +3, -172, 127, 597, 110, -342, -180, -216, +-33, 274, 280, -149, -60, 108, -124, -46, +124, -301, -1, 312, 74, 118, 15, -390, +-180, -5, 153, 310, 243, -83, -232, -252, +-157, 84, 312, 30, 153, 67, -266, 24, +-119, -431, 341, 241, 74, 474, -303, -667, +97, -161, 217, 721, -111, -255, -74, -467, +97, 367, 40, 99, 6, -205, -26, 36, +-45, -104, 161, 82, -1, 156, -176, -316, +255, 19, -44, 296, -210, -245, 304, -164, +-57, 305, -83, -14, 93, -303, -114, 132, +189, 115, 24, -110, -202, 61, 127, -194, +54, 19, 12, 381, -7, -364, -110, -223, +157, 462, 14, -69, -67, -239, 36, 10, +-49, 15, 155, 309, -16, -192, -160, -494, +90, 498, 153, 278, -20, -549, -240, -49, +97, 317, 311, 40, -235, -179, -108, -145, +168, 129, 2, 183, 136, -132, -236, -252, +-45, 185, 370, 213, -215, -237, -64, -137, +161, 195, -168, 107, 167, -251, 79, 10, +-311, 238, 221, -246, 122, 38, -268, 141, +162, -252, 89, 221, -223, 42, 102, -343, +181, 195, -214, 215, 0, -249, 162, -184, +-60, 352, -16, 85, -87, -513, 84, 216, +204, 404, -240, -425, -165, -69, 349, 213, +25, -96, -250, 246, 44, -187, 57, -448, +106, 629, -32, 128, -190, -700, 161, 289, +76, 302, -124, -339, 63, 64, -105, 52, +94, -79, 216, 191, -377, -159, -65, -186, +468, 342, -99, 28, -400, -236, 176, -26, +213, 26, -109, 305, -9, -94, -117, -468, +-33, 366, 327, 230, -115, -363, -349, 42, +320, 98, 100, 17, -328, 19, 208, -207, +33, 124, -214, 240, 248, -294, -87, -93, +-191, 304, 272, -96, -11, -102, -211, 141, +85, -165, 71, 48, -53, 223, 74, -227, +-79, -73, -153, 191, 201, 12, 159, -95, +-282, -56, -147, 98, 361, 51, -64, -60, +-205, -23, 190, -17, -203, 78, 96, 33, +263, -83, -433, -1, 25, 47, 364, -15, +-191, 26, -152, 38, 58, -172, 126, 99, +54, 244, -231, -385, -64, 1, 260, 494, +69, -361, -297, -245, -100, 480, 317, -94, +104, -236, -426, 257, 23, -165, 412, -38, +-295, 370, -86, -373, 238, -91, -214, 497, +80, -333, 104, -193, -229, 466, 102, -124, +83, -338, -161, 312, 77, 136, -7, -360, +-86, 142, 147, 197, -57, -252, -166, 56, +101, 95, 155, -50, -107, 38, -237, -93, +169, 47, 216, 75, -246, -74, -110, 43, +168, -54, 35, -5, -95, 172, -64, -128, +51, -112, 57, 194, -61, 10, -68, -100, +32, -16, 95, 8, -114, 165, -81, -35, +174, -247, -107, 118, -73, 249, 168, -132, +-109, -261, -114, 218, 114, 255, 50, -401, +-76, -4, -59, 438, -21, -353, 105, -94, +3, 404, -132, -320, 42, -4, 8, 342, +13, -395, -34, 38, -68, 375, 161, -333, +-112, -12, -234, 279, 348, -296, 12, 38, +-348, 363, 138, -337, 40, -167, 9, 460, +19, -135, -174, -302, 50, 398, 113, -103, +-127, -362, -7, 528, 146, -51, -242, -497, +-16, 462, 301, -17, -190, -347, -155, 424, +181, -109, -63, -324, -81, 355, 165, 36, +-142, -275, -120, 191, 182, 96, -34, -335, +-99, 203, 28, 284, -29, -441, -2, 60, +68, 324, -111, -343, -43, 78, 120, 336, +-65, -411, -86, -109, 55, 552, 11, -214, +-62, -382, -22, 488, 30, -77, 10, -369, +-126, 462, 60, -83, 108, -347, -229, 404, +28, -78, 125, -269, -118, 370, 31, -80, +-53, -291, -116, 336, 201, -7, -13, -293, +-260, 296, 107, 14, 54, -295, -56, 266, +42, 54, -149, -284, -3, 174, 116, 161, +-40, -242, -67, -71, -68, 293, 48, -25, +31, -289, -76, 192, 55, 121, -75, -222, +-172, 120, 236, 71, 56, -182, -314, 110, +35, 91, 138, -154, -50, 70, -40, 78, +-82, -179, 10, 129, 88, 125, -135, -282, +-19, 124, 103, 191, -133, -282, -19, 149, +14, 165, -43, -401, 99, 196, -134, 366, +-117, -470, 193, -50, -92, 421, -89, -249, +133, -19, -196, 267, 7, -385, 164, 61, +-206, 416, 20, -328, 90, -49, -219, 189, +51, -197, 173, 187, -204, 98, -83, -260, +135, 30, -116, 104, 3, 58, 138, -61, +-248, -66, -68, 99, 241, -82, -117, 56, +-76, 111, 23, -228, -135, 120, 110, 148, +74, -332, -220, 164, -51, 324, 156, -363, +-52, -116, -152, 285, 109, 3, -19, -50, +-192, -76, 165, -44, 11, 171, -279, 23, +149, -143, 125, 16, -286, 171, -10, -128, +195, -210, -139, 394, -85, 81, 73, -509, +-152, 142, 112, 323, 124, -98, -413, -62, +79, -184, 308, 44, -288, 372, -51, -145, +48, -279, -122, 142, 192, 145, -81, 17, +-291, -122, 138, -59, 169, 153, -160, -35, +-208, -78, 136, 106, 97, 39, -207, -68, +17, -131, -11, 131, -84, 250, 167, -267, +-170, -169, -219, 244, 298, 74, 8, 12, +-365, -143, 107, -108, 133, 243, -190, 0, +61, -48, -44, 8, -209, -221, 237, 234, +-5, 254, -356, -359, 217, -51, 67, 216, +-329, -21, 175, 23, 30, -94, -240, -67, +175, 206, -72, 21, -255, -159, 245, -25, +65, 163, -342, 62, 0, -231, 181, 11, +-79, 162, -69, 20, -26, 51, -177, -273, +99, -19, 240, 502, -342, -201, -223, -405, +359, 271, -30, 215, -291, -116, 118, -126, +-52, 25, -105, 116, 236, 20, -257, -82, +-251, -59, 460, 99, -105, 90, -482, -120, +275, -35, 150, 160, -307, -29, 21, -109, +33, 118, -123, -50, 64, -58, -1, 210, +-153, -139, -22, -102, 93, 276, -123, -125, +-79, -144, 154, 216, -162, -40, -168, -132, +233, 110, -63, 81, -270, -92, 174, -14, +4, 97, -277, -60, 198, -22, 49, 87, +-379, -80, 158, 5, 174, 116, -368, -98, +81, 5, 192, 134, -418, -151, 82, -41, +334, 241, -436, -84, -116, -174, 325, 142, +-201, 100, -60, -37, 101, -66, -320, -67, +109, 100, 309, 119, -445, -105, -198, -117, +465, 129, -135, 126, -379, -132, 234, -32, +20, 80, -219, -67, 155, 96, -147, 3, +-202, -224, 344, 273, -105, 133, -409, -390, +210, 128, 137, 205, -237, -130, 9, 36, +-44, -123, -185, 12, 201, 314, 88, -114, +-414, -232, -42, 88, 316, 162, -129, 49, +-197, -174, 28, -131, -41, 211, 22, 190, +27, -185, -187, -177, -62, 157, 188, 156, +-136, -107, -204, -128, 176, 90, -27, 68, +-203, -14, 62, 33, 18, -62, -176, -5, +83, 62, 55, -29, -317, 60, 58, -50, +219, -92, -260, 201, -121, 40, 154, -223, +-101, 76, -65, 182, 54, -201, -144, -38, +-2, 272, 30, -170, -176, -114, 92, 288, +103, -115, -350, -126, -75, 189, 376, -80, +-133, -50, -384, 136, 123, -79, 114, -27, +-93, 178, -24, -79, -178, -175, -45, 216, +199, 70, -116, -252, -129, 110, -14, 110, +-126, -145, 137, 196, 86, 32, -364, -376, +-84, 200, 304, 382, -64, -379, -265, -201, +-9, 430, 68, -44, -21, -243, -26, 270, +-75, -68, -156, -256, 40, 335, 175, 1, +-157, -309, -257, 295, 97, 25, 115, -286, +-130, 304, -30, 40, -105, -318, -147, 197, +258, 83, 4, -170, -358, 139, 19, -36, +131, -59, -48, 224, -39, -200, -111, -145, +-134, 399, 132, -81, 76, -347, -242, 232, +-24, 189, 42, -170, -131, -4, 114, 49, +2, -100, -298, 127, 16, 74, 212, -214, +-97, 104, -230, 96, 19, -144, 94, 172, +-95, -2, -11, -260, -32, 148, -181, 174, +111, -93, 57, -57, -231, -84, 33, 95, +53, 321, -163, -222, -4, -406, 98, 344, +-96, 326, -164, -281, 37, -198, 58, 103, +-35, 234, -81, 35, -130, -264, 10, 27, +111, 158, -62, -105, -191, 69, 17, 85, +93, -160, -158, 36, 6, 71, 65, -15, +-242, 136, 94, -157, 89, -223, -262, 329, +98, 151, 37, -296, -193, 10, 77, 149, +-41, -56, -109, -20, 142, 49, -43, 17, +-251, -61, 54, -48, 182, 70, -131, 109, +-145, 53, 44, -171, -98, -182, -18, 283, +212, 208, -182, -314, -255, -76, 128, 210, +71, -45, 1, 9, -33, 59, -253, -117, +-57, 52, 295, 10, -22, -146, -260, 253, +24, 167, -26, -422, -57, -83, 217, 402, +-55, 26, -373, -181, 109, -69, 250, -39, +-213, 180, -53, 103, 51, -166, -132, 18, +51, 65, -11, -156, -130, 44, 133, 274, +-10, -72, -323, -315, 68, 87, 278, 273, +-145, -81, -217, -114, 49, 94, 24, -68, +-47, -92, 82, 169, 8, 84, -235, -52, +-42, -96, 236, -161, -25, 235, -143, 254, +-10, -368, -82, -76, 60, 317, 111, -203, +-139, -42, -76, 352, 26, -201, -66, -221, +58, 224, 32, -64, -190, 10, 46, 286, +56, -289, -221, -290, 46, 434, 215, 204, +-196, -355, -200, -103, 221, 205, -36, 32, +-155, -75, 211, 18, -61, 5, -251, 79, +138, 2, 135, -291, -95, 157, -47, 404, +-17, -346, -78, -221, 69, 289, 97, -57, +-137, 38, -24, 193, -16, -269, -206, -151, +229, 219, 188, 85, -446, 22, -48, -7, +231, -247, -116, -48, 98, 372, -43, 46, +-253, -282, 178, -5, 76, 34, -139, -9, +47, 171, 76, 73, -116, -196, -140, -176, +215, 180, 121, 198, -204, -106, -20, -37, +-18, -123, -41, -77, 206, 396, -20, -40, +-236, -352, 2, 219, 15, -19, 22, -160, +149, 319, -171, -77, -258, -236, 179, 201, +124, -67, -123, -75, -8, 307, -13, -115, +-101, -332, 48, 184, 180, 202, -16, -81, +-177, -50, -10, -76, 111, 17, 108, 179, +-38, -123, -158, -166, 93, 310, 130, 54, +-226, -444, -16, 98, 273, 414, -155, -160, +-179, -200, 104, 65, -57, -34, 38, 90, +97, 155, -216, -170, -124, -148, 189, 193, +85, 39, -86, -188, -81, 167, -50, 78, +97, -280, 108, 76, -36, 144, -34, -11, +-15, 53, 15, -222, 108, -19, 10, 295, +-71, -119, 26, -92, 27, 99, 7, -146, +-66, 65, -23, 260, 112, -179, -69, -290, +-135, 229, 62, 264, 8, -262, -39, -156, +61, 236, -130, 21, -110, -124, 209, 48, +49, 14, -170, -36, 53, 27, 81, 15, +-127, -26, 98, -5, 193, 30, -150, 5, +-5, 21, 86, -2, -76, -123, 150, 32, +58, 165, -146, -58, 9, -102, -15, -1, +33, 21, 120, 122, -117, -17, -192, -170, +30, 58, 155, 97, 6, -61, -123, -9, +-69, 17, -43, -3, 78, 45, 152, -9, +-79, -118, -106, 6, 107, 242, -12, -35, +-14, -349, 272, 133, -33, 332, -298, -173, +160, -221, 284, 97, -75, 164, -152, -3, +12, -173, 69, -31, 63, 150, -35, 45, +-78, -108, 34, -44, -22, 87, -118, -52, +-8, -69, 170, 184, 4, 24, -278, -230, +-25, 0, 249, 162, 55, 42, -134, -34, +-90, -138, 121, -33, 187, 199, -30, -83, +-72, -80, 60, 240, 71, -208, 43, -175, +39, 309, 17, -56, -30, 17, -38, 60, +62, -472, 71, 267, -110, 577, -54, -527, +94, -308, -45, 413, -71, -11, -22, -72, +8, 154, 54, -217, -77, -156, -50, 296, +131, 77, 7, -153, -123, 35, 88, -145, +149, -123, -55, 426, -8, 74, 139, -484, +31, 63, -65, 207, 81, -106, 128, 196, +-75, -73, -36, -392, 130, 311, -50, 242, +-83, -385, 103, 70, -44, 282, -138, -289, +72, -119, 78, 334, -77, -43, -133, -204, +-58, 134, 190, -43, 112, -88, -256, 229, +-14, -60, 224, -210, -36, 120, 27, 42, +64, -35, -96, 55, 107, -45, 182, -43, +-66, 3, 5, 39, 40, 66, -69, -84, +130, -40, 119, 44, -124, -39, -107, 77, +30, -3, 89, -101, 13, 151, -103, -89, +-136, -234, 59, 346, 151, 136, -117, -457, +-86, 76, 87, 308, -99, -223, 78, -27, +226, 194, -128, -144, -101, -51, 72, 49, +148, -61, 175, 204, -110, 41, -159, -369, +180, 76, 208, 303, -94, -202, -118, -54, +85, 241, 42, -230, -63, -176, 54, 343, +29, 44, -128, -188, -63, 50, 14, -166, +82, -32, 55, 467, -158, -120, -92, -472, +107, 224, 118, 163, -18, -96, -120, 146, +77, -167, 135, -173, -51, 236, 41, -4, +106, -33, -16, 153, -2, -216, 26, -222, +83, 349, 118, 200, -67, -374, -147, -52, +61, 232, 106, -144, 0, 30, -29, 204, +-121, -177, -66, -115, 96, 76, 65, 30, +-54, 122, -101, -40, -7, -246, 36, 77, +84, 220, 96, -74, -137, -94, -107, -40, +182, -20, 199, 215, -48, 0, -127, -311, +64, 87, 135, 237, 13, -93, -8, -77, +60, -9, -36, -70, -40, 93, 82, 176, +-9, -135, -44, -213, 3, 160, -37, 114, +25, -121, 3, 56, -71, -34, 17, -151, +29, 172, -32, 103, -35, -152, 37, -10, +82, 11, 4, -13, -44, 121, 9, -32, +92, -181, 52, 71, 10, 138, 64, -67, +-27, -24, -75, -9, 118, -62, 142, 106, +-99, 38, -88, -142, 58, 28, 26, 117, +22, -88, -25, -94, -53, 143, -7, 72, +-27, -167, 14, -32, 99, 85, -11, 2, +-168, 50, -16, -6, 181, -134, 77, 15, +-54, 155, -80, -19, -8, -121, 131, 33, +114, 24, -14, -44, -62, 83, -20, 22, +33, -114, 106, 5, 119, 42, -131, 3, +-204, 72, 123, -70, 204, -158, -47, 160, +-162, 150, -76, -183, 50, -44, 140, 79, +12, -75, -143, 69, -3, 114, 43, -133, +19, -123, 110, 74, -7, 140, -105, 14, +50, -138, 111, -100, 29, 108, -13, 169, +12, -129, 15, -144, -24, 157, 65, 29, +114, -85, -110, 24, -104, -46, 112, 78, +37, 48, -60, -200, -8, 103, -7, 151, +-20, -216, -17, 14, 4, 172, 47, -96, +-14, -82, -67, 41, 26, 81, 93, 19, +35, -156, -43, 11, -17, 182, 85, -97, +66, -137, 4, 111, 24, 52, -22, -50, +22, -14, 92, -21, -33, 18, -43, 29, +38, -4, 5, 18, -18, -32, 9, -60, +-46, 33, -78, 74, 107, 32, 55, -66, +-229, -99, 23, 27, 223, 123, -167, 24, +-95, -83, 200, -66, -28, 13, -31, 103, +43, 15, -20, -114, 175, 47, 26, 39, +-234, -171, 150, 79, 309, 233, -186, -159, +-185, -224, 210, 154, 73, 178, -101, -104, +26, -118, -23, 48, -52, 41, 73, -12, +-50, -9, -70, 18, 99, 31, -66, -75, +-148, -80, 151, 114, 109, 131, -184, -146, +-71, -161, 159, 170, 68, 121, -53, -133, +15, -61, 16, 29, 54, 59, 101, 41, +-60, -141, 22, -45, 148, 182, -67, 35, +-63, -161, 131, -69, 13, 110, -58, 94, +13, -29, -72, -85, 34, -85, 99, 68, +-147, 167, -76, -66, 110, -148, -7, 53, +-112, 26, 20, -15, 76, 105, -57, -52, +-35, -158, 42, 118, 60, 72, 28, -122, +-29, 90, 17, 3, 74, -183, 57, 139, +-45, 92, 41, -164, 138, 89, -104, 29, +-49, -186, 194, 127, 9, 138, -128, -167, +-17, -52, 28, 83, 103, 8, -19, 20, +-212, -6, 28, -83, 181, 38, -148, 81, +-118, -120, 167, 11, -24, 201, -150, -181, +105, -191, 68, 300, -69, 64, 55, -249, +-16, 34, 27, 34, 147, 2, -124, 103, +21, -126, 218, -52, -88, 157, -129, -79, +131, -79, 179, 128, -77, 15, -190, -102, +70, -43, 152, 79, -7, 85, -111, -62, +-77, -86, 47, 20, 52, 65, -45, 27, +-20, -64, 16, -40, -106, 69, -39, -5, +200, -29, 57, 58, -233, -75, -63, -55, +229, 156, 102, -18, -63, -174, -94, 69, +-20, 131, 210, -76, 56, -72, -135, 55, +45, 6, 66, -32, -38, 20, 48, 25, +43, 8, -60, -85, -21, -27, 40, 174, +-15, -13, -1, -188, 8, 47, -42, 92, +-25, -12, 9, -5, 24, -59, 0, 8, +-49, 44, -19, -44, 49, 76, 34, 0, +-53, -208, 13, 122, 55, 218, 35, -225, +-48, -104, -28, 190, 129, 15, 27, -46, +-60, -74, 15, -23, -18, 170, 85, -40, +133, -127, -183, 97, -139, -21, 283, -26, +55, 111, -253, -81, 47, -71, 100, 79, +-59, 2, 38, 22, -81, 13, -40, -92, +169, -11, -77, 87, -165, 62, 149, -74, +99, -152, -147, 94, 13, 181, 52, -113, +-24, -130, 89, 57, 12, 55, -137, 19, +80, 3, 160, -62, -130, -93, -5, 94, +155, 180, -127, -157, -27, -150, 210, 169, +-56, -3, -153, -44, 124, 99, 32, -129, +-38, -41, 54, 177, -113, -76, -24, -72, +202, 130, -93, -63, -155, -118, 99, 126, +70, 75, -41, -109, -55, -11, 0, 0, +24, -48, 48, 150, 26, 30, -109, -256, +1, 43, 151, 218, 19, -127, -115, -40, +18, 128, 89, -165, 16, -32, 13, 237, +-3, -78, -50, -113, 80, 45, 76, -63, +-90, 108, -11, 127, 70, -197, -12, -120, +-34, 176, 18, 94, -16, -147, 31, 20, +-40, 86, -82, -201, 101, 74, 41, 246, +-140, -195, -18, -111, 121, 111, -28, -28, +-52, 58, 30, 86, 22, -144, 17, -132, +-20, 170, 54, 129, 18, -157, -10, -23, +28, 34, -7, -60, 51, 119, 82, 22, +-76, -142, -45, 50, 72, 13, 66, -54, +14, 135, -122, -31, -43, -192, 124, 125, +46, 118, -114, -127, -76, -19, 39, 40, +34, 19, 74, -24, -116, -43, -111, 79, +144, -38, 71, -42, -80, 107, -80, -99, +64, -17, 147, 138, -55, -122, -119, -36, +110, 131, 122, -30, -33, -75, -101, 17, +41, 53, 151, -22, -39, 16, -89, 18, +36, -130, 31, 78, 11, 124, -2, -125, +-61, 36, -30, -44, 55, -109, 20, 275, +-94, -5, -14, -277, 50, 69, -43, 102, +25, 60, -39, -13, 0, -182, 59, 40, +-46, 130, 24, 4, 9, -20, -4, -134, +81, 36, -33, 194, -12, -139, 75, -80, +-5, 164, 31, -121, -15, -19, -2, 175, +68, -175, -49, 9, -12, 156, 53, -199, +1, 76, -100, 108, 38, -190, 69, 138, +-77, -28, -22, -172, 3, 258, 17, -46, +33, -186, -117, 163, -5, -84, 191, 15, +-130, 223, -59, -318, 105, -78, -57, 442, +136, -216, -8, -175, -203, 304, 143, -306, +162, 75, -97, 470, -19, -588, -41, -63, +21, 558, 194, -399, -65, 99, -185, 259, +83, -658, 97, 352, -90, 502, 83, -651, +-59, 95, -158, 208, 170, -352, 45, 466, +-112, -15, 0, -600, -14, 410, 2, 165, +70, -342, 0, 239, -54, 15, -70, -343, +112, 236, 84, 262, -134, -366, 60, -32, +23, 322, -30, -271, 104, -6, -60, 318, +-58, -347, 173, 16, -66, 348, -103, -402, +139, 27, -23, 425, -36, -379, 39, -83, +-51, 319, -37, -230, 125, 82, -40, 177, +-174, -383, 149, 147, 34, 299, -150, -362, +112, 18, -37, 285, -72, -252, 174, -59, +-124, 288, -75, -173, 180, -150, 1, 329, +-126, -135, -7, -253, 170, 373, -47, -42, +-98, -310, 158, 243, -82, 52, -65, -173, +248, 79, -193, 38, -84, -52, 284, -18, +-158, 70, -114, 12, 171, -156, 6, 105, +-118, 118, 51, -219, 0, 96, -96, 85, +170, -232, -35, 229, -246, 84, 206, -385, +59, 205, -193, 269, 136, -381, -21, 4, +-55, 347, 55, -274, -19, -66, 60, 321, +-55, -246, 29, -72, 50, 283, -144, -178, +176, -108, 116, 253, -337, -67, 132, -249, +180, 268, -236, 98, 185, -364, 5, 227, +-358, 109, 276, -315, 243, 266, -403, 35, +15, -313, 229, 202, -222, 119, 126, -193, +114, -4, -329, 151, 94, -65, 230, -155, +-185, 233, -20, 24, 132, -333, -162, 292, +37, 98, 219, -497, -134, 406, -74, 278, +59, -759, 13, 231, 143, 596, -66, -565, +-159, -55, 85, 393, 107, -385, -17, 118, +-65, 388, -10, -498, -55, -60, 84, 437, +88, -193, -155, -121, 5, 175, -16, -72, +-12, -121, 194, 148, -158, 158, -201, -307, +282, -24, 12, 393, -200, -353, 159, -108, +-14, 550, -86, -379, 140, -298, -76, 569, +-51, -168, 204, -270, -62, 453, -232, -340, +177, -296, 263, 823, -286, -248, -141, -755, +298, 692, -64, 208, -116, -634, 155, 302, +-124, 225, -153, -497, 363, 204, -99, 433, +-368, -559, 357, -116, 1, 703, -240, -361, +160, -449, 31, 671, -113, -89, -6, -567, +178, 574, -87, 74, -176, -703, 305, 568, +-89, 287, -235, -937, 406, 504, -114, 644, +-353, -1084, 412, 148, 76, 946, -413, -801, +215, -205, 204, 801, -347, -550, 76, -212, +289, 781, -272, -482, -146, -414, 377, 767, +-151, -193, -305, -537, 465, 597, -55, 73, +-557, -654, 484, 295, 285, 437, -680, -425, +261, -136, 402, 319, -657, -89, 245, -176, +580, 266, -718, 104, -111, -534, 698, 92, +-263, 720, -308, -458, 396, -478, -157, 644, +-291, -64, 565, -390, -54, 474, -630, -102, +374, -539, 385, 523, -497, 322, -39, -740, +419, 46, -321, 723, -140, -487, 425, -415, +-167, 803, -270, -193, 337, -699, -66, 754, +-261, 120, 372, -817, -34, 485, -392, 384, +293, -679, 185, 124, -347, 481, 140, -377, +188, -188, -304, 375, 53, -5, 294, -314, +-133, 135, -237, 254, 176, -305, 113, -66, +-177, 364, 137, -197, 6, -173, -352, 287, +329, -72, 223, -222, -521, 221, 156, 177, +264, -372, -355, -113, 160, 504, 220, -51, +-411, -474, 72, 186, 398, 249, -342, -149, +-110, -23, 391, -18, -234, -38, -145, 100, +361, 56, -177, -45, -205, -178, 386, 98, +-94, 235, -349, -257, 364, -60, 108, 279, +-384, -172, 143, -166, 238, 291, -311, 17, +36, -324, 342, 137, -379, 213, -96, -208, +500, -28, -273, 129, -301, -67, 493, -38, +-121, 90, -382, -13, 484, -113, -70, 82, +-482, 89, 518, -87, 111, -21, -651, -42, +372, 61, 355, 190, -539, -255, 80, -146, +342, 420, -314, -119, -24, -337, 344, 413, +-243, -40, -187, -478, 351, 503, -2, 207, +-367, -759, 238, 286, 250, 646, -535, -710, +169, -211, 490, 833, -555, -300, -68, -663, +532, 709, -335, 227, -184, -907, 473, 454, +-262, 630, -285, -1025, 510, 108, -34, 1035, +-503, -854, 333, -496, 300, 1183, -506, -281, +88, -967, 385, 918, -423, 290, 33, -1037, +452, 487, -490, 549, -80, -920, 643, 242, +-420, 778, -283, -851, 572, -222, -239, 940, +-260, -325, 499, -573, -222, 559, -342, 81, +500, -522, -77, 289, -320, 365, 331, -490, +-110, -178, -227, 503, 380, 7, -36, -371, +-400, 139, 278, 112, 154, -213, -327, 214, +207, 89, 92, -358, -382, 113, 224, 209, +287, -83, -415, -72, 1, -91, 424, 172, +-361, 59, -161, -307, 623, 205, -294, 207, +-502, -440, 673, 113, -20, 379, -559, -396, +517, -58, 17, 397, -572, -217, 432, -192, +278, 296, -544, -16, 53, -234, 336, 179, +-256, 73, -19, -241, 274, 138, -262, 112, +-151, -211, 376, 111, -58, 33, -241, -117, +127, 156, 48, -114, -54, -32, 13, 257, +55, -283, -86, -70, 15, 435, 53, -241, +-75, -296, 169, 395, -112, 58, -214, -412, +370, 185, -33, 345, -356, -488, 308, -50, +36, 626, -323, -434, 282, -343, 99, 723, +-430, -230, 188, -587, 371, 732, -469, 109, +-114, -893, 556, 444, -208, 687, -419, -832, +422, -236, 145, 935, -431, -332, 158, -641, +250, 797, -351, -33, 32, -836, 447, 772, +-365, 347, -296, -1111, 580, 336, -45, 895, +-479, -789, 298, -353, 215, 911, -420, -287, +59, -709, 423, 859, -306, 144, -348, -1028, +492, 551, 118, 597, -578, -911, 294, 160, +344, 697, -671, -727, 206, -137, 672, 824, +-754, -365, -217, -576, 871, 671, -334, 163, +-539, -753, 635, 354, 58, 533, -645, -739, +403, -59, 398, 746, -671, -387, 53, -398, +630, 541, -537, -56, -168, -406, 712, 401, +-519, 100, -312, -539, 813, 227, -319, 469, +-542, -441, 622, -301, 13, 544, -469, 69, +335, -549, 58, 258, -317, 337, 223, -512, +99, 15, -226, 547, 95, -296, 48, -450, +-117, 482, 134, 201, 19, -525, -141, 213, +46, 302, 26, -597, 33, 164, 81, 674, +-197, -615, -49, -349, 267, 735, -114, -137, +-115, -487, 160, 557, -130, 37, -77, -777, +244, 497, -37, 630, -256, -841, 109, -137, +184, 705, -147, -329, -100, -209, 181, 473, +-12, -262, -210, -374, 227, 550, 43, 148, +-346, -647, 303, 192, 147, 467, -441, -427, +124, -121, 367, 400, -283, -127, -168, -257, +328, 266, -124, 65, -191, -321, 291, 170, +6, 249, -327, -331, 122, -91, 233, 360, +-192, -83, -84, -263, 181, 227, -73, 125, +-207, -363, 272, 42, 181, 479, -469, -296, +-40, -379, 521, 462, -186, 77, -357, -365, +419, 201, -70, 103, -408, -351, 526, 230, +102, 318, -699, -519, 282, -47, 538, 576, +-549, -266, -152, -373, 585, 417, -292, 87, +-388, -424, 644, 222, -46, 269, -673, -483, +452, 52, 340, 510, -584, -330, 117, -328, +347, 409, -437, 59, 135, -293, 342, 191, +-419, -20, -65, -236, 375, 271, -46, 96, +-283, -283, 120, -28, 173, 243, -147, -52, +-62, -167, 88, 179, 92, -2, -156, -139, +-40, 27, 173, 104, -55, 54, -62, -174, +15, -18, 52, 147, -58, -1, -79, -107, +243, 8, -106, 173, -271, -204, 254, -76, +98, 381, -180, -196, -52, -266, 160, 343, +-136, 21, -30, -328, 348, 226, -380, 243, +-105, -530, 459, 95, -209, 611, -182, -604, +227, -137, -10, 702, -218, -484, 215, -201, +103, 605, -332, -307, 77, -265, 303, 349, +-177, 41, -259, -231, 319, -23, 30, 282, +-292, -173, 213, -183, 27, 402, -237, -181, +169, -263, 136, 347, -284, -5, 21, -171, +305, -9, -287, 43, -82, 161, 369, -181, +-173, -18, -273, 217, 285, -381, 156, 260, +-375, 354, 124, -786, 239, 320, -369, 551, +137, -845, 295, 306, -396, 564, -2, -880, +306, 233, -149, 642, -85, -775, 92, 162, +-12, 543, -62, -760, 73, 241, 36, 516, +-100, -681, -49, 191, 116, 284, 91, -392, +-288, 241, 92, -4, 287, -141, -387, 192, +28, -272, 409, 172, -424, 333, -54, -689, +483, 212, -395, 729, -8, -1013, 264, 165, +-237, 1021, 114, -1316, 30, 320, -131, 1117, +104, -1647, -16, 602, 2, 1144, 66, -1805, +-209, 651, 101, 1034, 244, -1525, -305, 554, +-101, 766, 381, -1189, -169, 435, -229, 617, +330, -917, -106, 327, -186, 445, 236, -715, +8, 295, -203, 350, 20, -526, 227, 139, +-99, 296, -233, -347, 266, 39, 43, 322, +-283, -397, 300, -1, -69, 490, -269, -490, +366, -13, -41, 464, -259, -521, 145, 204, +82, 365, -100, -678, 31, 241, -54, 487, +27, -572, 99, 27, -150, 380, 24, -389, +110, 139, -181, 303, 94, -540, 181, 157, +-386, 416, 118, -494, 367, 104, -421, 340, +50, -522, 228, 177, -335, 506, 333, -682, +-9, -11, -391, 744, 356, -650, -50, -112, +-52, 769, 79, -717, -218, -4, 194, 763, +-43, -760, -22, 12, 109, 655, -309, -551, +235, -66, 111, 465, -317, -257, 215, -196, +-21, 271, -146, 33, 180, -202, 12, 37, +-231, 152, 90, -161, 324, -19, -470, 286, +70, -295, 516, -123, -693, 453, 193, -257, +616, -172, -890, 413, 275, -289, 545, -217, +-719, 565, 335, -153, 117, -506, -404, 463, +358, 82, -2, -353, -184, 295, -3, -111, +39, -176, 209, 299, -227, -19, -132, -236, +345, 47, -197, 298, -121, -316, 358, 0, +-309, 377, -146, -532, 548, 289, -348, 295, +-314, -710, 684, 456, -367, 234, -335, -599, +753, 333, -409, 183, -420, -425, 786, 147, +-204, 333, -600, -340, 683, -206, -55, 502, +-595, -46, 671, -542, -76, 402, -624, 344, +662, -728, 2, 193, -629, 666, 525, -829, +174, 19, -613, 947, 286, -916, 329, -315, +-532, 1312, 227, -717, 290, -743, -606, 1338, +299, -559, 319, -758, -475, 1374, 170, -523, +34, -888, -160, 1065, 269, -3, -74, -665, +-180, 354, 69, 199, 29, -442, 142, 127, +-95, 509, -208, -495, 235, -324, -28, 695, +-111, -97, 200, -538, -137, 538, -126, 10, +125, -711, 119, 787, -33, 187, -257, -1138, +159, 799, 123, 391, -190, -1056, 181, 665, +-66, 254, -323, -851, 454, 551, 97, 341, +-656, -757, 455, 194, 182, 595, -621, -593, +553, -154, 9, 723, -579, -444, 472, -368, +105, 736, -359, -184, 84, -525, 242, 469, +-206, 160, -224, -526, 556, 228, -200, 477, +-564, -730, 755, -52, -104, 983, -640, -694, +745, -532, -76, 1167, -772, -487, 792, -840, +135, 1410, -871, -287, 543, -1407, 290, 1454, +-633, 301, 198, -1632, 401, 1042, -395, 641, +-186, -1588, 479, 742, -77, 1039, -468, -1631, +424, 264, 203, 1402, -721, -1402, 363, -127, +579, 1377, -888, -1015, 118, -393, 779, 1117, +-780, -426, -33, -617, 782, 690, -623, 125, +-288, -708, 834, 367, -260, 408, -689, -688, +736, 179, 167, 497, -838, -546, 469, -46, +432, 460, -794, -246, 197, -141, 676, 199, +-765, -11, -157, -91, 950, -112, -505, 359, +-646, -45, 1015, -671, -182, 672, -863, 289, +1010, -1009, -39, 595, -1020, 428, 909, -1056, +302, 620, -1126, 587, 616, -1171, 515, 332, +-995, 839, 403, -891, 551, -25, -780, 788, +28, -669, 672, -213, -354, 925, -488, -507, +633, -627, 96, 990, -748, -151, 558, -782, +255, 786, -855, -14, 519, -690, 420, 648, +-847, 109, 192, -713, 709, 434, -727, 360, +-211, -674, 1000, 153, -588, 559, -609, -581, +1077, -155, -231, 760, -841, -427, 918, -495, +64, 891, -1023, -234, 816, -793, 421, 929, +-1145, 98, 466, -1032, 694, 663, -931, 467, +42, -1000, 912, 440, -723, 626, -527, -1102, +1191, 324, -302, 910, -1033, -1009, 1087, -112, +224, 903, -1330, -493, 830, -451, 794, 751, +-1570, 1, 446, -855, 1233, 575, -1498, 567, +69, -1031, 1487, 243, -1399, 777, -308, -933, +1671, 110, -1101, 875, -633, -897, 1503, -167, +-643, 1029, -821, -659, 1205, -406, -135, 931, +-974, -471, 732, -449, 425, 858, -955, -272, +242, -597, 795, 621, -964, 106, 10, -502, +1033, 201, -930, 227, -269, -334, 1081, 83, +-551, 325, -547, -384, 867, -93, -178, 468, +-617, -187, 596, -348, 168, 417, -650, 140, +179, -639, 563, 294, -544, 617, -180, -843, +751, -44, -465, 932, -491, -780, 1022, -230, +-260, 1038, -996, -769, 1107, -372, 149, 1170, +-1306, -707, 965, -565, 540, 1267, -1464, -530, +635, -832, 925, 1172, -1406, -142, 300, -892, +1162, 845, -1354, 49, -77, -841, 1471, 615, +-1018, 391, -657, -760, 1443, -6, -581, 626, +-844, -297, 1392, -336, -388, 622, -1152, -316, +1277, -568, 227, 1043, -1315, -165, 655, -1037, +697, 941, -1140, 224, 288, -990, 952, 635, +-1195, 383, -8, -977, 1281, 433, -1037, 636, +-377, -961, 1227, 149, -658, 830, -517, -802, +955, -230, -263, 986, -671, -495, 699, -626, +155, 998, -745, -193, 393, -875, 364, 961, +-624, 76, 183, -1014, 423, 723, -463, 337, +-56, -841, 413, 308, -163, 438, -261, -489, +325, -58, -8, 409, -376, -151, 428, -291, +-36, 300, -446, 127, 543, -369, -183, 94, +-358, 246, 566, -169, -214, -79, -281, 101, +374, 54, -130, -162, -115, 40, 224, 275, +-118, -320, -141, -127, 174, 476, 80, -219, +-187, -249, 16, 377, 101, -116, -58, -220, +-6, 263, 45, 29, -16, -185, -69, -40, +59, 179, 90, 77, -165, -313, 26, 120, +197, 252, -245, -330, 24, 27, 268, 238, +-274, -169, -43, -52, 278, 116, -113, 2, +-217, -117, 198, 52, 165, 187, -318, -288, +8, -34, 354, 448, -271, -353, -204, -206, +466, 520, -146, -173, -350, -312, 376, 282, +-10, 97, -273, -205, 283, -13, -53, 198, +-251, -181, 264, -73, 84, 392, -280, -304, +4, -202, 297, 477, -161, -215, -235, -195, +370, 371, -42, -187, -400, -233, 425, 375, +59, 9, -575, -337, 491, 171, 174, 155, +-726, -232, 528, 102, 237, 138, -852, -291, +653, 92, 346, 278, -1110, -303, 595, -88, +688, 368, -1135, -168, 234, -245, 873, 362, +-966, -59, 18, -296, 947, 319, -864, -43, +-191, -229, 1021, 271, -662, -102, -452, -136, +1024, 240, -378, -108, -678, -120, 816, 232, +19, -82, -724, -186, 493, 283, 299, -69, +-694, -209, 180, 286, 579, -155, -527, -94, +-285, 330, 732, -266, -248, -89, -562, 306, +738, -177, -51, -38, -709, 182, 600, -221, +235, 7, -711, 305, 267, -262, 465, -131, +-539, 380, -89, -214, 563, -194, -298, 439, +-316, -197, 559, -323, -173, 493, -417, -112, +523, -398, 20, 485, -508, -10, 324, -491, +217, 357, -476, 248, 201, -489, 304, 114, +-487, 404, 84, -515, 426, 18, -431, 620, +-32, -568, 428, -176, -339, 685, -157, -425, +452, -228, -153, 636, -323, -356, 382, -377, +-19, 653, -368, -113, 372, -484, 132, 447, +-536, 12, 193, -384, 437, 361, -441, 75, +-140, -438, 545, 218, -292, 253, -374, -343, +703, 51, -212, 236, -603, -268, 753, 30, +-48, 257, -719, -241, 653, -43, 214, 247, +-855, -213, 469, -34, 490, 322, -880, -275, +253, -159, 669, 430, -837, -180, 4, -232, +874, 429, -722, -248, -305, -317, 951, 666, +-407, -146, -608, -620, 766, 539, 54, 155, +-664, -527, 364, 310, 312, 221, -549, -535, +117, 146, 501, 487, -566, -390, -76, -224, +679, 392, -502, -59, -290, -232, 799, 224, +-376, 113, -556, -373, 865, 14, -169, 503, +-686, -288, 786, -387, -55, 573, -769, -65, +722, -571, 211, 633, -842, 119, 393, -834, +441, 517, -655, 412, 152, -770, 494, 271, +-603, 468, -38, -693, 687, 134, -446, 605, +-393, -661, 713, -10, -105, 671, -603, -664, +510, -85, 185, 806, -526, -572, 139, -352, +403, 753, -408, -244, -152, -425, 633, 559, +-391, -136, -382, -385, 753, 460, -192, -79, +-623, -286, 678, 266, 109, -6, -737, -107, +432, -46, 381, 84, -654, 187, 84, -327, +601, 2, -569, 409, -174, -405, 781, -61, +-481, 551, -414, -466, 841, -235, -274, 708, +-617, -310, 786, -468, -14, 682, -756, -126, +597, -596, 247, 680, -742, 42, 374, -767, +361, 598, -634, 288, 179, -808, 399, 363, +-411, 492, -83, -725, 403, 69, -153, 659, +-321, -570, 406, -216, 17, 736, -455, -355, +409, -458, 120, 695, -548, -97, 350, -631, +267, 623, -487, 169, 47, -799, 365, 424, +-218, 484, -176, -731, 318, 74, -101, 600, +-261, -522, 367, -182, -9, 688, -413, -329, +342, -486, 143, 666, -398, 0, 104, -619, +303, 463, -270, 264, -156, -700, 425, 231, +-201, 601, -244, -687, 431, -113, -170, 769, +-269, -488, 381, -360, -70, 788, -266, -252, +259, -617, 0, 715, -202, 72, 189, -746, +18, 535, -216, 257, 153, -741, 136, 381, +-229, 401, -23, -697, 244, 164, -102, 536, +-181, -600, 287, -35, -97, 622, -271, -474, +388, -208, 7, 606, -445, -263, 268, -326, +242, 459, -444, -23, 190, -375, 226, 250, +-469, 192, 249, -347, 281, 23, -494, 311, +147, -237, 346, -115, -415, 322, -30, -203, +475, -161, -298, 413, -285, -193, 511, -314, +-174, 452, -307, -15, 467, -395, -115, 306, +-413, 78, 431, -345, 135, 256, -525, 131, +248, -356, 280, 107, -473, 278, 128, -226, +379, -153, -456, 335, -61, -88, 521, -295, +-351, 421, -217, -74, 483, -454, -211, 521, +-215, 57, 362, -571, -141, 352, -200, 232, +315, -415, -71, 107, -242, 237, 210, -252, +116, -57, -266, 297, -6, -101, 354, -263, +-247, 266, -276, 56, 545, -286, -178, 227, +-398, 86, 585, -372, -225, 190, -371, 328, +597, -444, -143, -76, -408, 547, 358, -387, +81, -215, -294, 657, 108, -462, 227, -262, +-295, 782, -78, -487, 409, -346, -173, 795, +-268, -386, 336, -425, -16, 732, -301, -239, +300, -498, 69, 667, -358, -76, 199, -621, +145, 557, -258, 215, 113, -675, 135, 271, +-271, 414, 44, -571, 299, 86, -214, 516, +-178, -565, 299, -108, -19, 722, -276, -444, +264, -393, 85, 732, -411, -233, 261, -478, +242, 663, -473, -122, 140, -562, 334, 556, +-388, 98, 25, -535, 307, 303, -260, 183, +-46, -420, 254, 219, -141, 231, -127, -405, +205, 83, -30, 260, -141, -204, 102, -8, +47, 94, -101, -50, -19, -54, 154, 46, +-94, 147, -104, -205, 220, -66, -164, 306, +-67, -199, 313, -89, -221, 259, -160, -204, +315, -26, -68, 195, -172, -167, 159, 33, +-9, 111, -139, -155, 134, 19, 78, 115, +-230, -58, 82, -23, 188, 30, -260, -73, +46, 50, 232, 130, -252, -169, -3, -48, +218, 184, -177, -130, -17, 6, 189, 163, +-143, -243, -116, 37, 227, 227, 15, -221, +-253, 24, 137, 154, 150, -199, -269, 44, +128, 151, 179, -147, -343, -16, 123, 122, +236, -77, -304, -53, 20, 152, 234, -60, +-172, -149, -89, 213, 195, -27, -22, -210, +-178, 229, 126, -10, 116, -178, -242, 190, +59, -100, 229, -86, -235, 269, -50, -155, +237, -161, -135, 227, -84, -33, 211, -86, +-132, 113, -111, -84, 241, -97, -63, 195, +-184, 30, 185, -252, 31, 124, -204, 142, +148, -255, 93, 157, -227, 153, 45, -408, +184, 200, -130, 337, -63, -523, 122, 65, +-59, 488, -20, -492, 97, -29, -95, 536, +-49, -519, 143, -57, -29, 627, -109, -516, +81, -174, 27, 618, -82, -361, 59, -207, +21, 501, -65, -280, 5, -243, 42, 480, +18, -110, -72, -360, 45, 316, 13, 82, +-79, -320, 133, 201, -64, 147, -126, -365, +199, 153, -50, 282, -150, -391, 196, 30, +-39, 344, -157, -303, 154, -44, 10, 293, +-108, -212, 71, -85, 5, 276, -68, -101, +63, -245, 9, 236, -25, 164, -22, -320, +-19, -7, 104, 272, -42, -138, -103, -99, +118, 199, -30, -82, -93, -189, 195, 250, +-101, 98, -161, -365, 242, 119, -36, 273, +-156, -329, 168, 66, -36, 266, -165, -395, +230, 81, 21, 388, -288, -398, 188, -71, +114, 394, -240, -231, 116, -114, 83, 268, +-190, -133, 68, -99, 141, 183, -160, -30, +-20, -152, 185, 81, -173, 138, -23, -150, +231, -53, -215, 163, -19, -87, 215, -11, +-217, 95, 47, -153, 198, 64, -262, 95, +39, -158, 206, 123, -183, -14, -29, -186, +149, 286, -78, -49, -101, -281, 159, 327, +7, -65, -202, -258, 132, 397, 117, -141, +-222, -313, 64, 439, 135, -74, -174, -325, +40, 356, 137, -53, -151, -295, -44, 327, +214, -8, -87, -279, -152, 220, 165, 17, +23, -175, -126, 164, 73, 2, 41, -164, +-101, 92, 38, 103, 71, -118, -53, -30, +-70, 124, 75, -90, 78, -28, -191, 145, +66, -117, 200, -29, -280, 116, 37, -100, +266, 18, -278, 78, -8, -84, 290, -21, +-223, 44, -136, 25, 311, -16, -61, -17, +-251, -8, 227, -6, 33, 46, -216, -4, +184, -32, 48, -5, -254, -1, 131, 58, +162, -21, -212, -40, 28, 29, 113, -49, +-124, 45, 58, 65, 71, -93, -136, -18, +36, 19, 85, 42, -60, 52, -11, -109, +0, -41, 25, 99, 12, 21, -48, -46, +48, -15, -28, 8, -45, -31, 116, 63, +-60, 65, -78, -134, 100, -27, -13, 104, +-32, 16, 36, -24, -31, -57, -49, 20, +92, 46, 30, -33, -145, 31, 66, -2, +58, -71, -93, 59, 69, 48, 1, -98, +-88, 20, 88, 115, 21, -131, -118, -74, +88, 216, 58, -34, -158, -169, 70, 110, +66, 27, -98, -77, 72, 93, -40, 1, +-36, -129, 88, 44, -63, 110, 41, -58, +5, -58, -109, 64, 115, -36, 23, -45, +-99, 149, 60, -38, -15, -193, -20, 155, +53, 90, -14, -204, -24, 118, -21, 76, +41, -242, 26, 158, -63, 135, 5, -260, +62, 87, -51, 139, -58, -179, 118, 50, +-15, 107, -142, -130, 142, 10, 17, 112, +-166, -108, 175, -31, 0, 135, -189, -88, +194, -54, 25, 118, -225, -64, 152, -42, +132, 96, -256, -23, 54, -69, 207, 12, +-221, 86, 8, -27, 212, -87, -224, 93, +-40, -5, 283, -75, -182, 92, -142, -9, +273, -66, -87, 35, -170, 3, 241, -7, +-19, 3, -233, -2, 195, -15, 86, -10, +-246, 46, 122, -9, 140, -60, -264, 35, +100, 55, 207, -53, -305, -59, 50, 92, +282, 41, -297, -139, -42, 42, 349, 103, +-245, -138, -129, 43, 350, 113, -199, -184, +-143, 42, 330, 167, -161, -185, -181, 15, +292, 155, -51, -188, -204, 22, 175, 166, +70, -153, -205, 1, 55, 84, 189, -79, +-216, 61, -43, -22, 280, -15, -199, 60, +-113, -136, 307, 111, -172, 73, -150, -201, +301, 155, -126, 16, -199, -192, 287, 197, +-8, 29, -290, -184, 207, 86, 124, 62, +-277, -107, 126, 68, 137, 96, -250, -230, +91, 36, 171, 274, -211, -234, -19, -53, +185, 250, -104, -225, -86, -54, 169, 337, +-40, -173, -157, -287, 154, 341, 54, 83, +-179, -368, 85, 217, 97, 126, -149, -368, +43, 229, 131, 175, -164, -364, -6, 141, +178, 175, -151, -262, -39, 92, 182, 162, +-119, -199, -74, -14, 134, 157, 3, -75, +-87, -54, 9, 89, 82, -52, -59, -49, +-23, 98, 94, -4, -71, -94, -74, 61, +147, 50, -2, -122, -165, 67, 110, 105, +94, -188, -159, 25, 22, 156, 136, -135, +-133, 13, -35, 101, 159, -135, -90, 19, +-100, 121, 191, -68, -39, -61, -181, 10, +205, 72, 1, 7, -205, -98, 183, 88, +32, -8, -221, -127, 172, 195, 75, 6, +-245, -268, 133, 193, 110, 139, -203, -286, +75, 111, 107, 164, -164, -282, 62, 102, +110, 225, -176, -313, 41, 20, 152, 300, +-166, -255, -13, -68, 154, 284, -122, -170, +-22, -107, 134, 236, -107, -100, -42, -132, +159, 193, -86, -41, -95, -139, 160, 158, +-27, -8, -138, -150, 129, 144, 56, 31, +-175, -189, 86, 109, 86, 117, -139, -164, +63, -15, 30, 119, -58, -32, 28, -43, +-13, 48, 33, -27, -21, -73, -46, 120, +98, 69, -55, -214, -70, 14, 131, 220, +-22, -142, -112, -73, 93, 164, 47, -118, +-126, -67, 63, 205, 83, -22, -179, -230, +84, 114, 111, 212, -174, -265, 65, -29, +90, 307, -152, -268, 66, -80, 112, 384, +-184, -303, 55, -120, 127, 484, -184, -341, +82, -253, 99, 575, -195, -185, 109, -375, +100, 425, -208, -79, 103, -295, 115, 412, +-193, -71, 44, -397, 115, 341, -101, 118, +-7, -284, 54, 106, -30, 56, -34, -122, +67, 73, 10, 100, -98, -115, 45, -119, +78, 201, -88, 39, -10, -256, 95, 160, +-68, 127, -31, -294, 67, 137, 20, 185, +-95, -290, 20, 73, 106, 214, -122, -241, +3, -25, 94, 264, -43, -147, -92, -156, +122, 234, 24, -39, -194, -180, 196, 210, +4, 6, -209, -249, 186, 176, 52, 125, +-208, -227, 114, 25, 100, 153, -179, -121, +74, -38, 53, 166, -78, -106, 31, -91, +6, 160, 2, -15, -42, -123, 72, 68, +-8, 85, -94, -168, 88, 84, 22, 134, +-77, -263, 10, 106, 95, 157, -88, -211, +-43, 30, 172, 122, -143, -100, -48, -42, +223, 164, -205, -85, -21, -156, 242, 237, +-212, -29, -20, -209, 190, 212, -120, -14, +-107, -186, 238, 189, -102, 33, -182, -192, +295, 88, -136, 118, -110, -158, 226, -8, +-110, 177, -96, -147, 168, -87, -21, 226, +-155, -100, 146, -78, 0, 159, -118, -156, +94, 56, -1, 118, -52, -167, 19, 93, +21, -22, -22, -48, -12, 123, 42, -108, +-19, 34, -49, 41, 61, -157, 70, 155, +-161, 42, 57, -199, 145, 140, -231, 1, +113, -115, 96, 174, -208, -66, 117, -110, +61, 130, -130, -16, 29, -54, 107, 40, +-76, 31, -101, -63, 168, -69, 3, 187, +-215, 11, 193, -301, 61, 216, -269, 188, +200, -450, 92, 237, -289, 321, 158, -627, +133, 278, -253, 370, 100, -664, 134, 361, +-184, 295, 5, -713, 195, 350, -155, 436, +-76, -684, 223, 152, -138, 475, -15, -635, +82, 219, -59, 453, 46, -719, -62, 260, +45, 399, 37, -615, -98, 344, 38, 145, +101, -528, -164, 505, 51, -89, 162, -349, +-242, 510, 73, -342, 197, -87, -253, 495, +14, -495, 247, 17, -210, 511, -34, -549, +190, -10, -105, 591, -59, -539, 128, -103, +-17, 612, -143, -454, 166, -189, 13, 608, +-177, -310, 121, -360, 93, 590, -182, -96, +53, -524, 156, 550, -205, 64, 67, -655, +119, 558, -173, 181, 44, -730, 142, 462, +-147, 289, -30, -670, 194, 293, -144, 411, +-52, -651, 210, 136, -132, 569, -110, -632, +246, -1, -70, 598, -181, -546, 242, -83, +-23, 613, -212, -428, 234, -291, 29, 654, +-257, -183, 175, -514, 178, 579, -313, 27, +44, -609, 366, 507, -400, 186, -10, -648, +469, 325, -441, 353, -22, -556, 467, 72, +-398, 504, -41, -454, 401, -205, -264, 637, +-132, -259, 324, -454, -40, 620, -316, -47, +323, -647, 106, 622, -448, 204, 356, -830, +102, 456, -395, 417, 310, -738, 73, 239, +-273, 466, 158, -625, 109, 31, -116, 617, +-79, -488, 236, -274, -14, 700, -341, -289, +435, -457, 10, 681, -502, -98, 547, -599, +-14, 563, -514, 172, 560, -744, -4, 478, +-517, 397, 482, -936, 109, 476, -499, 523, +316, -956, 259, 400, -449, 525, 109, -842, +382, 156, -333, 760, -111, -682, 406, -381, +-153, 1070, -246, -432, 338, -840, 54, 1243, +-342, -172, 194, -1215, 275, 1222, -337, 264, +-57, -1459, 452, 911, -205, 755, -371, -1554, +567, 438, 33, 1296, -632, -1430, 477, -276, +370, 1611, -739, -877, 207, -938, 704, 1525, +-745, -144, -138, -1463, 986, 1151, -615, 768, +-538, -1747, 1143, 370, -347, 1614, -848, -1593, +1090, -519, -7, 2160, -972, -1216, 751, -1316, +437, 2380, -953, -583, 233, -1912, 835, 2032, +-771, 280, -291, -2075, 1042, 1207, -425, 1072, +-745, -1860, 1088, 270, -39, 1595, -1057, -1365, +960, -572, 338, 1663, -1161, -579, 630, -1166, +635, 1270, -1019, 317, 214, -1455, 756, 654, +-639, 1001, -222, -1349, 761, 8, -227, 1237, +-533, -832, 632, -575, 140, 1080, -688, -87, +366, -971, 494, 639, -768, 573, 168, -992, +654, 79, -667, 918, 28, -679, 546, -478, +-327, 941, -161, -30, 363, -954, -3, 518, +-305, 752, 211, -1052, 216, -110, -388, 1254, +122, -869, 355, -688, -412, 1478, 78, -421, +385, -1182, -415, 1302, 89, 159, 360, -1332, +-453, 855, 175, 575, 253, -1191, -436, 337, +261, 802, 152, -790, -390, -168, 271, 702, +200, -223, -415, -440, 187, 350, 287, 253, +-378, -388, 48, -138, 291, 463, -219, -26, +-125, -565, 285, 431, 4, 352, -341, -805, +279, 268, 266, 640, -537, -720, 173, -153, +472, 780, -560, -285, -56, -663, 637, 779, +-458, 177, -313, -1043, 725, 649, -237, 627, +-504, -1184, 589, 271, 110, 985, -615, -1051, +317, -143, 415, 1161, -641, -808, 19, -481, +635, 1159, -475, -434, -399, -740, 819, 916, +-169, 38, -785, -826, 831, 481, 168, 448, +-994, -713, 629, 15, 489, 676, -1074, -457, +354, -356, 742, 697, -1007, -106, 120, -636, +789, 519, -722, 301, -125, -724, 677, 188, +-326, 599, -420, -638, 549, -159, 25, 823, +-627, -465, 380, -534, 270, 889, -594, -124, +179, -756, 315, 666, -391, 196, 37, -749, +236, 384, -193, 423, -120, -680, 182, 62, +-28, 622, -213, -465, 82, -335, 76, 696, +-145, -144, -31, -611, 98, 640, -98, 104, +27, -725, -53, 454, -14, 369, 94, -696, +-290, 112, 143, 605, 123, -549, -391, -185, +100, 681, 259, -363, -345, -346, -81, 583, +390, -121, -304, -406, -199, 342, 397, 131, +-204, -327, -358, 35, 368, 253, -22, -104, +-404, -215, 141, 200, 216, 131, -241, -304, +-255, 68, 411, 252, -58, -243, -567, -59, +447, 236, 166, -90, -796, -112, 328, 98, +480, 54, -877, -37, 105, -151, 685, 145, +-708, 220, -239, -475, 783, 122, -423, 545, +-627, -660, 787, -15, -79, 728, -885, -607, +578, -230, 314, 787, -921, -385, 283, -468, +560, 713, -834, -145, 51, -479, 653, 494, +-733, -51, -117, -277, 597, 213, -551, 6, +-156, -30, 388, -71, -375, -9, -38, 188, +174, -97, -297, -220, 80, 239, 55, 181, +-348, -455, 161, 119, 76, 493, -477, -580, +131, -71, 279, 728, -564, -521, -76, -350, +543, 774, -454, -182, -410, -620, 701, 511, +-276, 341, -714, -713, 714, 33, 16, 835, +-964, -644, 491, -549, 504, 1204, -1032, -293, +-2, -1134, 941, 1167, -829, 310, -524, -1389, +1104, 696, -463, 841, -946, -1260, 1001, 44, +2, 1221, -1147, -861, 584, -674, 486, 1329, +-986, -172, -32, -1254, 797, 1021, -592, 585, +-593, -1462, 827, 478, -103, 1101, -972, -1250, +531, -173, 480, 1243, -1038, -571, -54, -813, +912, 934, -718, 340, -616, -1146, 956, 328, +-204, 1022, -984, -1042, 695, -355, 322, 1344, +-1060, -573, 105, -1014, 822, 1317, -794, 132, +-627, -1451, 1124, 879, -306, 835, -1170, -1442, +1018, 181, 266, 1269, -1407, -1068, 566, -484, +802, 1377, -1336, -494, -51, -992, 1095, 1130, +-865, 200, -665, -1169, 1069, 542, -263, 715, +-1017, -913, 762, -96, 267, 909, -1097, -421, +269, -681, 674, 837, -890, 240, -270, -1041, +779, 396, -404, 803, -665, -913, 619, -192, +46, 1001, -780, -459, 315, -697, 275, 901, +-568, 159, -129, -1045, 336, 481, -163, 815, +-462, -1016, 154, -227, 233, 1231, -461, -566, +-224, -930, 520, 1230, -276, 124, -633, -1379, +599, 796, 88, 926, -949, -1465, 349, -28, +555, 1611, -955, -1100, -153, -895, 896, 1800, +-641, -437, -703, -1456, 1007, 1493, -176, 368, +-1152, -1707, 859, 769, 355, 1164, -1368, -1478, +442, -192, 829, 1526, -1239, -766, -86, -974, +1014, 1355, -783, 78, -567, -1382, 910, 808, +-208, 827, -904, -1297, 567, -4, 319, 1241, +-891, -729, 20, -755, 623, 1141, -499, 31, +-533, -1102, 633, 616, 34, 698, -888, -992, +381, -178, 529, 1146, -965, -442, -102, -1017, +900, 1144, -697, 342, -663, -1446, 984, 670, +-209, 976, -992, -1335, 702, -41, 313, 1340, +-1023, -843, 155, -777, 754, 1365, -802, -157, +-437, -1207, 906, 958, -335, 475, -840, -1166, +679, 278, 240, 915, -998, -800, 244, -414, +699, 1056, -891, -264, -261, -845, 899, 789, +-523, 285, -691, -892, 788, 279, -44, 660, +-847, -655, 402, -218, 386, 742, -754, -237, +-31, -549, 574, 539, -498, 192, -296, -606, +404, 172, -83, 409, -401, -308, 20, -246, +290, 349, -284, 213, -354, -598, 372, 123, +67, 688, -642, -728, 193, -161, 467, 895, +-700, -521, -211, -475, 773, 795, -447, -50, +-717, -735, 876, 501, -43, 428, -1002, -793, +624, 94, 444, 702, -1070, -507, 146, -392, +888, 721, -958, 5, -306, -795, 974, 526, +-479, 475, -733, -873, 782, 125, 112, 756, +-989, -614, 492, -347, 458, 832, -852, -211, +9, -693, 627, 667, -465, 267, -473, -827, +632, 243, -88, 694, -628, -731, 337, -161, +250, 831, -522, -432, -94, -483, 508, 691, +-337, 59, -402, -755, 508, 457, -90, 430, +-480, -789, 228, 220, 211, 513, -383, -513, +-159, -124, 411, 488, -187, -100, -394, -470, +327, 417, 112, 184, -487, -561, 4, 244, +545, 325, -580, -395, -280, -89, 813, 401, +-564, -79, -352, -416, 666, 351, -263, 216, +-416, -560, 296, 200, 213, 459, -546, -558, +43, -103, 441, 674, -468, -361, -149, -445, +364, 707, -102, -55, -389, -710, 232, 621, +198, 278, -443, -922, -4, 516, 338, 475, +-212, -914, -408, 412, 460, 363, 65, -602, +-713, 254, 453, 132, 284, -152, -756, 14, +213, -51, 496, 208, -629, -143, -103, -151, +590, 321, -391, -172, -312, -95, 415, 185, +22, -110, -459, 81, 93, -139, 500, 43, +-592, 253, -173, -448, 774, 195, -568, 348, +-384, -586, 814, 186, -357, 434, -548, -557, +698, 27, -111, 528, -565, -497, 438, -80, +91, 584, -402, -503, 52, -29, 250, 426, +-122, -403, -362, 192, 349, -33, 134, -131, +-639, 367, 355, -477, 329, 222, -723, 359, +216, -752, 520, 409, -740, 479, 87, -942, +615, 329, -746, 832, 109, -1257, 491, 296, +-651, 1258, 206, -1744, 255, 466, -500, 1434, +311, -2108, 8, 897, -355, 1127, 395, -2169, +-203, 1409, -196, 403, 385, -1784, -307, 1795, +-67, -512, 320, -1184, -365, 2021, 86, -1225, +211, -678, -411, 2094, 281, -1690, 54, -326, +-471, 2142, 505, -1947, -90, -114, -559, 1982, +729, -1904, -246, 139, -540, 1478, 769, -1530, +-277, 289, -457, 803, 577, -822, -96, 179, +-412, 266, 319, -210, 87, -57, -296, 183, +4, -43, 229, -186, -73, 319, -371, -256, +417, -51, 66, 464, -624, -555, 541, 58, +96, 590, -634, -643, 451, -41, 154, 727, +-551, -569, 281, -348, 290, 941, -622, -399, +333, -740, 283, 1121, -754, -189, 619, -1058, +-6, 1183, -642, 59, 765, -1330, -298, 1169, +-392, 311, 660, -1535, -342, 1172, -218, 404, +437, -1565, -236, 1117, -62, 378, 90, -1308, +45, 835, -37, 317, -217, -899, 359, 489, +-152, 287, -275, -554, 431, 184, -189, 213, +-194, -181, 296, -55, -100, 62, -125, 158, +125, -266, 42, 58, -179, 276, 114, -373, +122, 189, -368, 19, 386, -161, -59, 309, +-479, -388, 774, 182, -458, 259, -361, -535, +980, 273, -747, 344, -191, -548, 932, -91, +-734, 883, -172, -714, 796, -456, -511, 1432, +-288, -1091, 656, -386, -214, 1558, -442, -1234, +524, -176, 48, 1138, -551, -863, 403, -20, +205, 508, -545, -308, 238, -55, 317, 34, +-440, 262, 8, -258, 416, -179, -316, 569, +-159, -464, 444, -49, -188, 515, -289, -541, +421, 166, -21, 273, -459, -469, 476, 341, +35, 76, -581, -504, 610, 518, -51, 21, +-586, -639, 719, 705, -187, -66, -489, -723, +681, 864, -176, -181, -468, -620, 545, 793, +100, -348, -745, -186, 599, 460, 360, -522, +-1111, 459, 763, -152, 475, -532, -1269, 1178, +734, -920, 617, -409, -1286, 1670, 525, -1451, +858, -206, -1295, 1711, 295, -1515, 1034, -163, +-1187, 1509, 75, -1099, 988, -435, -777, 1253, +-311, -544, 922, -678, -263, 954, -811, -116, +974, -677, 52, 453, -1031, 337, 844, -503, +301, -236, -1031, 809, 545, -292, 635, -815, +-1157, 1140, 490, -153, 686, -1134, -1177, 1290, +645, -87, 329, -1205, -860, 1231, 671, -26, +-55, -1070, -441, 947, 547, 97, -250, -867, +-124, 619, 309, 250, -191, -765, 11, 415, +33, 382, 51, -739, 7, 310, -236, 411, +376, -717, -52, 332, -524, 358, 754, -710, +-210, 380, -630, 277, 953, -622, -385, 382, +-447, 146, 754, -459, -364, 331, -132, 27, +272, -214, -159, 155, 178, -90, -244, 108, +29, -35, 475, -206, -639, 344, 70, -52, +777, -483, -914, 573, 82, 176, 919, -1085, +-1001, 964, 93, 419, 809, -1718, -788, 1390, +27, 502, 558, -2035, -425, 1476, -54, 670, +293, -2055, -138, 1125, -29, 1054, 26, -1974, +0, 572, 129, 1477, -195, -1711, -49, -101, +405, 1712, -365, -1164, -166, -835, 641, 1836, +-458, -557, -204, -1564, 619, 1960, -306, -27, +-275, -2095, 407, 1968, 29, 299, -386, -2261, +192, 1853, 266, 438, -318, -2189, -86, 1611, +340, 562, -8, -1968, -484, 1249, 403, 635, +325, -1640, -878, 851, 528, 711, 452, -1298, +-1030, 363, 595, 927, 360, -1044, -851, -150, +506, 1260, 182, -945, -487, -540, 270, 1541, +83, -876, -189, -778, 43, 1630, 101, -719, +-97, -976, 1, 1581, 104, -450, -141, -1133, +46, 1419, 150, -168, -243, -1187, 81, 1160, +255, 127, -396, -1177, 126, 829, 329, 411, +-454, -1077, 61, 488, 388, 583, -334, -899, +-177, 162, 470, 708, -134, -664, -428, -173, +470, 733, 113, -392, -577, -348, 291, 612, +400, -179, -602, -372, -4, 401, 668, 41, +-505, -325, -355, 88, 873, 251, -390, -150, +-558, -268, 885, 389, -263, 45, -519, -580, +590, 502, -9, 211, -405, -748, 166, 429, +256, 405, -220, -743, -227, 167, 389, 651, +48, -718, -581, -78, 477, 836, 257, -707, +-811, -148, 529, 799, 318, -645, -817, -78, +444, 619, 346, -491, -711, -56, 306, 406, +391, -296, -650, -50, 264, 272, 299, -216, +-508, 9, 230, 172, 165, -227, -259, 179, +-11, -44, 256, -161, -102, 337, -362, -335, +570, 66, -108, 344, -690, -554, 920, 275, +-133, 331, -996, -659, 1221, 311, -123, 407, +-1253, -750, 1401, 279, -54, 592, -1405, -876, +1355, 149, 170, 813, -1442, -877, 1029, -75, +534, 920, -1348, -691, 485, -291, 936, 816, +-1134, -333, -100, -432, 1221, 465, -853, 148, +-518, -440, 1218, -46, -473, 606, -729, -342, +936, -552, 1, 940, -835, -181, 522, -933, +486, 1054, -841, 70, 52, -1179, 881, 921, +-726, 471, -404, -1344, 1140, 606, -550, 894, +-684, -1341, 1123, 205, -297, 1104, -743, -1038, +807, -200, 72, 1035, -716, -586, 369, -439, +434, 827, -598, -283, -85, -439, 718, 543, +-406, -94, -523, -256, 956, 150, -262, 74, +-834, -17, 1094, -206, -141, 204, -1022, 120, +1119, -424, 18, 309, -1185, 199, 1110, -580, +194, 358, -1320, 298, 1017, -683, 419, 358, +-1369, 361, 789, -731, 646, 360, -1284, 390, +448, -749, 845, 347, -1040, 410, -50, -759, +1096, 317, -764, 487, -612, -782, 1401, 215, +-532, 635, -1074, -835, 1547, 89, -225, 884, +-1373, -970, 1368, -101, 259, 1212, -1504, -1038, +872, -347, 862, 1428, -1518, -966, 299, -603, +1366, 1543, -1464, -753, -113, -916, 1580, 1564, +-1280, -424, -386, -1208, 1538, 1476, -932, -35, +-629, -1447, 1359, 1187, -491, 521, -840, -1559, +1083, 662, -36, 1078, -961, -1570, 743, 249, +374, 1407, -978, -1559, 362, 70, 726, 1388, +-944, -1303, 32, -21, 1000, 1037, -931, -798, +-208, -168, 1186, 722, -867, -295, -417, -509, +1289, 623, -732, 165, -611, -900, 1274, 582, +-473, 500, -823, -1112, 1110, 517, 10, 634, +-1151, -1098, 891, 404, 582, 671, -1459, -972, +618, 211, 1048, 742, -1496, -829, 144, 16, +1462, 743, -1326, -668, -421, -63, 1799, 604, +-1136, -449, -818, -92, 1909, 368, -913, -144, +-1006, -147, 1780, 89, -628, 192, -1053, -224, +1466, -131, -292, 464, -981, -307, 1011, -245, +21, 580, -775, -286, 534, -288, 186, 503, +-448, -159, 131, -305, 217, 386, -118, -48, +-161, -313, 184, 318, 125, -24, -310, -215, +95, 241, 322, -161, -381, 32, -24, 181, +496, -372, -400, 295, -166, 83, 596, -485, +-316, 529, -300, -57, 572, -580, -163, 681, +-347, -15, 415, -707, 13, 631, -341, 170, +263, -751, 140, 483, -365, 312, 232, -741, +152, 371, -355, 400, 209, -700, 146, 265, +-294, 363, 123, -504, 176, 171, -218, 161, +4, -182, 171, 38, -36, 13, -173, 77, +140, -154, 178, 60, -350, 119, 104, -223, +339, 204, -415, -108, -20, -130, 523, 392, +-428, -401, -196, -65, 678, 618, -422, -593, +-277, -164, 706, 865, -356, -657, -325, -372, +638, 1077, -198, -586, -443, -591, 581, 1103, +44, -362, -655, -740, 560, 941, 271, -52, +-826, -826, 506, 694, 417, 252, -807, -799, +292, 346, 546, 464, -663, -549, 6, -63, +667, 544, -543, -253, -189, -391, 732, 615, +-448, -57, -336, -624, 757, 608, -313, 118, +-495, -653, 755, 415, -165, 192, -612, -464, +731, 212, -98, 134, -609, -231, 696, 70, +-136, 13, -476, -3, 600, 18, -172, -171, +-331, 140, 464, 101, -114, -303, -272, 104, +329, 211, 6, -269, -226, -27, 141, 249, +160, -149, -172, -134, -45, 225, 294, -11, +-166, -206, -111, 154, 316, 116, -125, -195, +-146, 33, 257, 156, 1, -46, -229, -105, +239, 72, 58, 179, -263, -183, 230, -78, +8, 337, -149, -116, 141, -301, -61, 361, +11, 170, 26, -580, -100, 286, 72, 497, +44, -814, -136, 202, 10, 702, 207, -911, +-241, 74, -53, 838, 344, -832, -315, -147, +-65, 914, 347, -712, -237, -314, -113, 997, +280, -699, -87, -391, -143, 1063, 172, -710, +58, -374, -115, 1001, -26, -683, 265, -241, +-137, 847, -172, -670, 457, -83, -219, 708, +-187, -660, 459, 55, -182, 629, -175, -694, +337, 115, -41, 663, -201, -722, 208, 58, +58, 737, -169, -664, 102, -77, 36, 744, +-24, -506, -13, -215, -61, 666, 190, -295, +-196, -328, -79, 526, 375, -81, -439, -396, +48, 340, 415, 127, -596, -430, 199, 134, +331, 330, -565, -439, 207, -56, 259, 464, +-397, -411, 102, -157, 186, 470, -168, -382, +14, -108, 21, 374, 102, -380, -21, 44, +-188, 219, 344, -374, -40, 240, -320, 60, +475, -408, -48, 414, -386, 56, 537, -521, +-55, 435, -434, 227, 611, -603, -108, 323, +-445, 406, 639, -614, -125, 193, -452, 550, +566, -593, -43, 27, -480, 666, 489, -518, +-8, -145, -438, 686, 396, -374, -51, -289, +-272, 621, 215, -164, -50, -482, -95, 528, +2, 116, 0, -670, 40, 381, -158, 319, +25, -692, 187, 199, -295, 412, 18, -605, +331, 3, -393, 521, 26, -528, 409, -212, +-411, 638, 37, -434, 393, -367, -336, 719, +10, -372, 334, -476, -178, 831, -95, -362, +320, -542, -45, 904, -214, -338, 341, -517, +3, 820, -230, -212, 261, -455, 69, 589, +-190, 23, 88, -412, 208, 325, -220, 240, +-45, -324, 318, 77, -254, 307, -101, -121, +321, -160, -230, 274, -137, 134, 292, -417, +-194, 227, -168, 389, 283, -629, -177, 125, +-196, 565, 286, -649, -144, -35, -215, 577, +253, -509, -49, -186, -206, 492, 134, -306, +113, -303, -200, 374, -28, -101, 319, -353, +-222, 238, -159, 39, 514, -325, -272, 114, +-265, 159, 686, -266, -293, -72, -345, 352, +732, -221, -228, -284, -363, 618, 570, -270, +-57, -397, -297, 813, 258, -354, 134, -365, +-179, 824, -44, -374, 249, -265, -70, 710, +-242, -329, 270, -172, 34, 549, -371, -267, +243, -93, 142, 391, -489, -181, 220, -117, +264, 269, -568, -17, 155, -269, 375, 168, +-556, 199, 42, -394, 433, 11, -466, 363, +-52, -383, 407, -164, -308, 425, -123, -314, +354, -283, -163, 458, -186, -254, 358, -360, +-92, 452, -236, -165, 420, -365, -91, 336, +-279, -14, 497, -305, -127, 133, -275, 197, +480, -247, -81, -110, -283, 420, 383, -140, +64, -358, -386, 510, 356, 96, 101, -551, +-403, 441, 324, 385, 51, -730, -265, 329, +97, 677, 155, -870, -182, 197, -194, 829, +394, -858, -198, 123, -413, 729, 561, -737, +-144, 146, -567, 479, 564, -542, 13, 138, +-632, 203, 403, -247, 255, 38, -636, -32, +157, 15, 528, -32, -633, -170, -37, 104, +710, -10, -588, -229, -150, 80, 728, 72, +-437, -248, -216, 9, 609, 138, -218, -202, +-236, -47, 398, 198, -39, -208, -151, -37, +154, 333, 51, -382, 33, 29, -101, 512, +64, -563, 235, 101, -333, 585, 84, -618, +366, 161, -509, 538, 157, -588, 364, 184, +-599, 484, 255, -495, 262, 107, -589, 407, +302, -297, 166, -36, -528, 297, 286, -67, +122, -214, -432, 209, 191, 158, 120, -389, +-266, 113, 3, 331, 194, -484, -127, 22, +-208, 417, 330, -474, -69, -88, -326, 414, +427, -351, -11, -203, -415, 343, 438, -175, +130, -245, -542, 236, 412, -80, 309, -181, +-644, 159, 338, -93, 428, -69, -639, 162, +209, -156, 465, -13, -507, 234, 39, -212, +442, -27, -296, 341, -183, -255, 427, -68, +-111, 490, -368, -329, 376, -158, 57, 677, +-440, -377, 202, -294, 247, 785, -449, -317, +38, -413, 331, 742, -364, -170, -56, -497, +244, 607, -152, -4, -157, -536, 165, 436, +-7, 124, -210, -503, 164, 242, -6, 216, +-156, -424, 145, 50, -11, 269, -92, -331, +126, -72, -8, 247, -88, -218, 172, -106, +-49, 147, -101, -95, 265, -81, -139, 27, +-79, 16, 320, -62, -231, -47, 2, 121, +267, -84, -230, -74, 51, 188, 161, -99, +-173, -19, 63, 147, 68, -89, -141, 70, +114, 74, -41, -72, -102, 109, 160, 41, +-124, -69, -80, 112, 187, 55, -160, -80, +-116, 63, 253, 108, -194, -80, -162, -37, +332, 188, -252, -94, -140, -128, 368, 251, +-292, -124, -64, -202, 287, 295, -222, -86, +-29, -311, 131, 300, -9, 2, -100, -390, +30, 251, 194, 63, -201, -372, 5, 174, +277, 108, -242, -312, 13, 96, 251, 141, +-227, -230, 84, 21, 132, 98, -181, -59, +148, -35, 2, 8, -117, 108, 167, -83, +-65, -31, -87, 190, 163, -101, -80, -30, +-101, 194, 151, -72, -53, -14, -140, 135, +129, -46, 15, 34, -195, 56, 97, -20, +98, 55, -232, -7, 34, 8, 180, 67, +-230, -68, -32, -7, 218, 130, -174, -137, +-94, -57, 187, 207, -44, -167, -173, -116, +135, 198, 135, -91, -296, -177, 123, 108, +265, 70, -385, -241, 107, -1, 333, 238, +-382, -278, 52, -117, 365, 352, -336, -231, +-9, -213, 346, 389, -276, -135, -19, -272, +267, 374, -206, -59, -10, -273, 175, 356, +-146, -45, -4, -239, 137, 340, -152, -60, +0, -174, 160, 318, -222, -95, 39, -142, +186, 333, -287, -118, 60, -180, 204, 377, +-303, -118, 44, -248, 225, 391, -303, -90, +73, -295, 138, 345, -214, -26, 129, -315, +-62, 242, -15, 51, 124, -278, -240, 115, +174, 76, 104, -185, -325, 5, 234, 64, +139, -78, -346, -84, 159, 76, 261, -4, +-351, -163, 22, 89, 432, 65, -391, -200, +-57, 75, 467, 140, -339, -200, -101, 27, +385, 193, -163, -168, -225, -22, 320, 230, +-3, -110, -344, -85, 300, 252, 74, -74, +-366, -121, 224, 268, 110, -73, -290, -107, +94, 217, 126, -56, -154, -59, -73, 104, +151, 16, -23, -59, -201, -17, 162, 115, +67, -75, -267, -104, 155, 148, 116, -57, +-274, -130, 127, 97, 133, -2, -232, -127, +78, 7, 157, 90, -200, -154, 40, -51, +183, 188, -191, -210, 20, -48, 191, 238, +-169, -230, -30, -42, 237, 247, -164, -184, +-98, -80, 296, 257, -155, -100, -143, -157, +283, 232, -59, 43, -247, -218, 272, 140, +45, 199, -350, -262, 249, 69, 131, 318, +-375, -341, 152, 26, 241, 438, -366, -427, +34, -31, 311, 552, -310, -512, -45, -59, +243, 630, -116, -587, -188, -61, 198, 645, +69, -603, -320, -82, 193, 624, 161, -556, +-352, -113, 120, 570, 257, -459, -330, -162, +15, 476, 344, -281, -322, -245, -20, 377, +311, -74, -222, -329, -41, 274, 194, 81, +-49, -311, -99, 126, 77, 200, 119, -235, +-167, -24, -14, 306, 246, -217, -199, -83, +-99, 371, 320, -237, -185, -97, -163, 389, +334, -212, -159, -145, -170, 405, 280, -177, +-113, -221, -142, 421, 205, -112, -97, -320, +-86, 394, 135, 37, -103, -444, -7, 335, +38, 165, -31, -521, -2, 301, -50, 190, +116, -512, -119, 268, -39, 190, 215, -465, +-226, 194, -23, 206, 335, -413, -338, 157, +-48, 170, 483, -353, -438, 210, -91, 46, +590, -269, -447, 268, -179, -93, 637, -122, +-360, 231, -298, -168, 619, 30, -209, 126, +-397, -137, 505, 108, 4, 12, -492, -49, +378, 127, 180, -69, -505, 0, 213, 112, +331, -74, -480, 33, 36, 11, 467, 8, +-462, 53, -58, -140, 484, 156, -398, -3, +-110, -215, 443, 296, -311, -155, -126, -183, +370, 372, -241, -267, -92, -128, 235, 361, +-131, -268, -82, -94, 134, 275, -7, -209, +-134, -55, 104, 150, 76, -85, -187, -38, +67, -22, 195, 134, -304, -74, 97, -192, +284, 347, -414, -126, 133, -280, 335, 461, +-451, -144, 76, -326, 431, 507, -458, -104, +-38, -409, 520, 528, -413, -12, -154, -476, +510, 452, -226, 94, -333, -438, 467, 270, +2, 192, -492, -341, 397, 63, 156, 279, +-524, -232, 258, -108, 261, 299, -447, -123, +85, -193, 314, 249, -305, -57, -70, -196, +303, 185, -157, -21, -176, -151, 239, 102, +6, 18, -254, -106, 175, 16, 107, 70, +-262, -80, 131, -16, 111, 52, -187, -58, +68, 59, 95, -49, -101, -33, -23, 148, +156, -135, -120, -2, -35, 174, 165, -149, +-123, 21, -37, 141, 160, -114, -94, 14, +-56, 79, 159, -35, -68, 3, -81, 4, +110, 33, 34, 33, -157, -82, 71, 40, +155, 95, -256, -135, 88, -1, 183, 159, +-260, -146, 24, -85, 257, 264, -280, -158, +-15, -231, 298, 413, -291, -152, -4, -352, +232, 478, -190, -121, -76, -370, 252, 438, +-188, -97, -39, -328, 210, 391, -224, -117, +123, -215, -9, 309, -84, -181, 147, -25, +-108, 189, -27, -220, 123, 106, -48, 145, +-138, -263, 240, 125, -96, 203, -141, -344, +240, 171, -49, 219, -193, -398, 199, 214, +94, 189, -326, -318, 219, 65, 167, 236, +-370, -172, 193, -154, 177, 309, -321, -76, +105, -249, 209, 280, -257, -8, 3, -265, +250, 195, -196, 98, -125, -300, 361, 138, +-262, 147, -91, -291, 371, 124, -339, 101, +15, -218, 286, 105, -289, 76, -35, -182, +334, 82, -306, 99, -45, -199, 378, 92, +-391, 109, 72, -205, 256, 111, -290, 92, +42, -180, 199, 61, -158, 131, -63, -120, +219, -94, -158, 271, 0, -109, 114, -229, +-99, 405, 47, -170, -7, -229, -2, 437, +51, -212, -100, -181, 65, 379, 80, -195, +-170, -108, 91, 236, 94, -127, -207, -16, +162, 40, -4, 14, -146, -40, 190, -63, +-97, 187, -63, -200, 156, 0, -129, 230, +2, -300, 118, 114, -156, 131, 31, -257, +149, 157, -219, 43, 48, -183, 205, 106, +-294, 101, 86, -230, 244, 109, -416, 175, +231, -349, 167, 227, -428, 124, 308, -387, +75, 330, -359, 30, 292, -349, 49, 380, +-349, -52, 327, -334, 37, 460, -405, -120, +429, -410, -43, 636, -358, -225, 432, -501, +-131, 868, -215, -431, 312, -463, -104, 1020, +-136, -694, 176, -267, -25, 1025, -82, -895, +25, 11, 37, 833, 58, -961, -195, 331, +150, 467, 82, -857, -256, 587, 148, 69, +128, -648, -253, 714, 22, -252, 314, -429, +-354, 775, -5, -484, 371, -285, -354, 823, +-6, -584, 275, -230, -217, 797, -19, -566, +118, -196, 26, 694, -184, -470, 107, -170, +177, 538, -350, -262, 215, -276, 96, 456, +-240, -84, 119, -366, 93, 428, -127, -54, +-46, -335, 277, 372, -278, -13, -5, -355, +388, 321, -479, 129, 158, -506, 346, 361, +-562, 241, 283, -727, 284, 528, -578, 288, +268, -950, 365, 672, -643, 371, 247, -1106, +398, 657, -611, 535, 202, -1191, 336, 536, +-440, 740, 46, -1272, 333, 415, -271, 928, +-125, -1305, 310, 269, -81, 1031, -230, -1169, +157, 52, 204, 1010, -375, -865, 83, -218, +375, 955, -496, -545, 153, -483, 311, 924, +-425, -281, 156, -672, 154, 849, -187, -55, +19, -758, 99, 728, -32, 79, -100, -790, +227, 722, -245, 46, 95, -742, 247, 716, +-528, -16, 444, -606, 67, 558, -588, 46, +606, -518, -21, 355, -588, 259, 572, -648, +76, 305, -623, 477, 455, -854, 174, 352, +-513, 522, 178, -841, 339, 324, -390, 391, +-106, -580, 502, 174, -308, 245, -256, -210, +469, -147, -91, 233, -361, 165, 259, -554, +239, 316, -439, 387, 4, -756, 545, 356, +-494, 358, -194, -600, 771, 183, -523, 332, +-349, -305, 931, -197, -548, 484, -389, -92, +918, -535, -493, 585, -377, 77, 834, -671, +-425, 484, -405, 275, 862, -685, -503, 272, +-283, 490, 777, -704, -532, 60, -134, 749, +579, -761, -405, -109, -154, 899, 540, -724, +-375, -209, -141, 882, 434, -608, -217, -268, +-229, 800, 367, -439, -68, -376, -337, 677, +398, -110, -90, -597, -271, 505, 331, 324, +-113, -886, -121, 432, 154, 599, -50, -1074, +-42, 406, 73, 708, -64, -1023, -11, 162, +141, 856, -186, -798, 17, -250, 278, 968, +-359, -488, 81, -572, 324, 903, -380, -109, +-7, -816, 406, 685, -228, 376, -370, -1027, +685, 330, -167, 870, -653, -1000, 863, -209, +-126, 1208, -740, -644, 790, -847, 32, 1372, +-768, -153, 615, -1396, 185, 1329, -644, 402, +302, -1739, 274, 966, -291, 1062, -206, -1817, +423, 281, 37, 1701, -623, -1621, 487, -497, +306, 2119, -828, -1232, 364, -1155, 567, 2205, +-851, -600, 84, -1762, 784, 2005, -660, 239, +-349, -2279, 987, 1630, -419, 960, -724, -2434, +1084, 1096, -179, 1408, -937, -2176, 955, 384, +178, 1772, -1104, -1777, 758, -330, 464, 1973, +-1096, -1254, 448, -836, 664, 1748, -884, -548, +39, -1157, 813, 1311, -619, 130, -350, -1318, +868, 857, -246, 600, -745, -1222, 851, 292, +157, 937, -1108, -870, 845, -338, 397, 1096, +-1229, -441, 708, -734, 552, 976, -1109, -41, +328, -835, 825, 620, -990, 355, -75, -761, +1098, 109, -875, 687, -374, -470, 1211, -494, +-669, 848, -642, -5, 1205, -977, -377, 795, +-913, 410, 1190, -1196, -125, 566, -1080, 729, +1132, -1134, -40, 146, -945, 953, 842, -763, +67, -454, -650, 1035, 345, -179, 324, -1038, +-434, 984, -112, 365, 569, -1425, -276, 863, +-403, 716, 632, -1534, -67, 639, -611, 913, +613, -1360, 83, 303, -647, 915, 450, -942, +238, -10, -567, 691, 176, -400, 427, -266, +-501, 385, -15, 137, 482, -472, -358, 103, +-189, 525, 468, -492, -169, -208, -338, 678, +433, -240, -31, -534, -399, 627, 350, 136, +90, -785, -405, 456, 261, 490, 143, -892, +-354, 202, 176, 760, 161, -808, -267, -175, +57, 953, 206, -536, -206, -612, -20, 1027, +217, -193, -139, -899, -108, 880, 253, 200, +-70, -1045, -233, 571, 327, 625, -33, -1061, +-355, 161, 408, 915, 38, -809, -525, -334, +533, 992, 18, -309, -577, -787, 552, 834, +51, 288, -559, -1093, 375, 464, 281, 916, +-642, -1205, 230, -82, 488, 1426, -691, -1020, +91, -713, 611, 1661, -592, -540, -144, -1311, +699, 1606, -395, 123, -431, -1781, 763, 1286, +-163, 827, -668, -1970, 714, 706, 107, 1397, +-817, -1756, 585, -49, 333, 1711, -853, -1185, +401, -838, 443, 1747, -645, -417, 64, -1452, +477, 1440, -256, 393, -360, -1712, 505, 807, +103, 1101, -663, -1534, 362, -81, 510, 1618, +-825, -1008, 100, -1045, 854, 1864, -832, -267, +-207, -1799, 1009, 1681, -545, 593, -625, -2212, +1022, 1122, -96, 1417, -1051, -2247, 971, 334, +324, 1968, -1286, -1786, 712, -584, 713, 2140, +-1249, -946, 242, -1381, 1031, 1882, -988, 60, +-319, -1895, 1224, 1225, -551, 1113, -866, -2075, +1217, 324, -2, 1960, -1309, -1850, 1057, -610, +540, 2375, -1558, -1239, 728, -1443, 980, 2374, +-1541, -433, 359, -2018, 1136, 1984, -1200, 362, +-95, -2107, 1098, 1217, -594, 941, -636, -1664, +997, 257, -39, 1239, -978, -916, 756, -607, +436, 1162, -1087, -37, 387, -1098, 785, 577, +-990, 893, 22, -1166, 924, -316, -717, 1662, +-348, -939, 943, -1141, -374, 1993, -606, -367, +773, -1790, -14, 1759, -718, 550, 543, -2240, +277, 1114, -727, 1517, 285, -2383, 453, 354, +-622, 2173, 61, -2117, 528, -452, -494, 2405, +-54, -1409, 432, -1216, -253, 2193, -132, -454, +214, -1719, 52, 1650, -299, 448, 185, -1900, +196, 922, -401, 1184, 200, -1778, 176, 145, +-312, 1604, 138, -1342, 140, -506, -236, 1595, +117, -680, 51, -989, -109, 1321, 85, 38, +-55, -1329, 35, 945, 9, 596, -105, -1339, +172, 456, -75, 848, -147, -962, 244, -77, +-93, 857, -165, -424, 289, -556, -123, 732, +-209, 148, 360, -885, -153, 450, -210, 651, +347, -990, -153, 100, -145, 938, 226, -863, +-28, -245, -180, 1029, 133, -510, 75, -668, +-177, 980, 46, 4, 171, -1068, -195, 842, +-50, 459, 267, -1287, -190, 619, -64, 779, +219, -1281, -120, 299, -102, 989, 182, -1097, +5, -30, -215, 1018, 193, -807, 74, -244, +-288, 902, 228, -522, 69, -331, -307, 684, +245, -247, 20, -307, -216, 336, 202, 23, +-33, -197, -99, 25, 59, 166, 40, -67, +-25, -173, -83, 194, 106, 99, -5, -320, +-139, 141, 134, 253, 33, -328, -202, -14, +142, 335, 66, -235, -194, -163, 87, 418, +117, -262, -174, -165, 1, 448, 156, -333, +-103, -29, -54, 282, 88, -280, 42, 79, +-148, 129, 55, -187, 175, 31, -253, 175, +38, -172, 195, -55, -142, 266, -113, -215, +211, -59, 7, 289, -271, -215, 204, -92, +163, 282, -346, -133, 74, -147, 344, 207, +-372, -4, -79, -153, 484, 54, -294, 163, +-317, -178, 576, -72, -129, 280, -509, -155, +559, -141, 40, 211, -614, 22, 441, -200, +289, 47, -724, 227, 317, -235, 431, -77, +-717, 332, 252, -188, 369, -215, -474, 362, +16, -55, 366, -316, -301, 288, -55, 66, +255, -280, -169, 89, -4, 226, -18, -232, +142, -107, -121, 365, -71, -194, 163, -206, +-48, 329, -111, -44, 95, -249, 67, 201, +-200, 79, 158, -191, -61, 17, 38, 157, +-51, -17, -51, -289, 220, 318, -273, 61, +84, -432, 135, 373, -110, 30, -176, -295, +284, 160, 8, 128, -464, -158, 527, -100, +-115, 302, -437, -144, 515, -202, -102, 318, +-364, -80, 357, -212, -18, 207, -273, 57, +184, -262, 50, 148, -138, 138, -49, -264, +175, 77, -127, 170, -61, -165, 124, -85, +-62, 273, -73, -191, 60, -86, 48, 295, +-132, -282, 86, 91, -70, 93, 85, -166, +-120, 187, 35, -172, 108, 66, -250, 162, +227, -356, -108, 321, -38, 7, 70, -413, +-44, 558, -24, -245, -9, -313, 75, 645, +-158, -415, 147, -192, -98, 640, -65, -532, +160, -15, -161, 544, 11, -629, 78, 199, +-106, 386, -28, -633, 133, 294, -195, 381, +55, -775, 94, 422, -251, 462, 215, -1076, +-68, 733, -205, 351, 308, -1203, -205, 975, +-163, 125, 422, -1079, -355, 1020, -118, -89, +472, -819, -444, 945, -31, -294, 452, -524, +-506, 891, 64, -626, 381, -53, -561, 806, +321, -1179, 45, 764, -429, 441, 545, -1632, +-363, 1671, -166, -191, 623, -1723, -662, 2339, +49, -873, 622, -1515, -767, 2664, 122, -1429, +581, -1081, -692, 2555, -37, -1661, 712, -662, +-653, 2216, -193, -1633, 797, -399, -635, 1891, +-171, -1512, 645, -239, -454, 1576, -178, -1267, +401, -249, -161, 1337, -218, -953, 115, -398, +222, 1203, -426, -637, 43, -614, 448, 1106, +-644, -287, 260, -937, 208, 1132, -489, -14, +299, -1212, -9, 1162, -234, 169, 160, -1357, +-5, 1092, -217, 364, 180, -1433, 39, 972, +-421, 520, 430, -1440, -60, 878, -565, 570, +704, -1456, -251, 994, -538, 361, 737, -1389, +-271, 1262, -496, -115, 631, -1066, -133, 1312, +-570, -441, 596, -792, -88, 1290, -487, -568, +441, -778, -106, 1477, -207, -748, 54, -819, +116, 1675, -93, -880, -306, -848, 449, 1701, +-216, -755, -373, -970, 583, 1521, -313, -307, +-342, -1228, 593, 1203, -341, 383, -318, -1631, +624, 908, -450, 1077, -202, -2002, 553, 644, +-448, 1599, -152, -2154, 469, 302, -313, 1928, +-365, -2001, 716, -189, -402, 2162, -568, -1670, +1136, -755, -778, 2365, -494, -1331, 1370, -1160, +-1114, 2343, -263, -973, 1289, -1361, -1139, 2147, +-154, -644, 1074, -1449, -835, 1966, -406, -544, +1039, -1188, -499, 1583, -797, -569, 1233, -601, +-473, 889, -874, -387, 1221, -139, -434, 197, +-739, 18, 870, -68, -135, -188, -668, 415, +476, -286, 152, -165, -487, 542, -64, -500, +490, 73, -213, 385, -723, -519, 911, 235, +-6, 197, -1301, -418, 1242, 257, 211, 84, +-1763, -235, 1423, 106, 429, 64, -2046, -17, +1446, -135, 626, 106, -2167, 140, 1346, -253, +755, -17, -2068, 401, 1087, -323, 833, -324, +-1787, 887, 688, -600, 938, -473, -1476, 1315, +278, -978, 1007, -351, -1125, 1436, -183, -1171, +1211, -241, -974, 1359, -459, -1018, 1355, -360, +-1001, 1185, -394, -549, 1201, -691, -856, 958, +-432, 101, 1122, -1154, -736, 758, -501, 794, +1131, -1673, -725, 599, -513, 1436, 1118, -2094, +-631, 380, -692, 1952, 1297, -2257, -691, 36, +-805, 2317, 1470, -2121, -786, -480, -788, 2577, +1434, -1750, -699, -1084, -839, 2694, 1377, -1245, +-610, -1538, -820, 2455, 1237, -539, -540, -1861, +-627, 1919, 910, 323, -415, -2134, -354, 1368, +415, 994, -150, -2112, -128, 736, -129, 1386, +278, -1714, -163, -33, -389, 1645, 545, -1231, +-254, -595, -431, 1618, 565, -750, -221, -811, +-456, 1220, 582, -183, -303, -867, -260, 649, +376, 392, -282, -809, 2, 61, -66, 819, +74, -624, -89, -403, -202, 950, 282, -339, +-220, -657, -173, 835, 277, -8, -180, -806, +-262, 658, 377, 244, -229, -802, -302, 416, +448, 403, -256, -651, -311, 70, 454, 624, +-237, -582, -318, -187, 384, 853, -122, -650, +-317, -235, 161, 872, 224, -617, -523, -222, +70, 757, 505, -481, -738, -294, 106, 751, +541, -423, -711, -388, 50, 827, 473, -377, +-489, -554, -140, 932, 390, -222, -117, -935, +-515, 1237, 445, -155, 168, -1328, -890, 1633, +628, -266, 245, -1474, -1065, 1780, 717, -247, +269, -1534, -1098, 1680, 658, -28, 402, -1586, +-1203, 1422, 674, 275, 485, -1562, -1340, 975, +866, 792, 258, -1662, -1161, 496, 841, 1500, +46, -1984, -767, 170, 464, 2108, 182, -2299, +-580, 0, 103, 2444, 451, -2429, -584, -78, +-114, 2465, 668, -2292, -594, -156, -259, 2238, +738, -1910, -455, -250, -481, 1883, 780, -1452, +-227, -353, -766, 1545, 846, -996, -78, -507, +-868, 1294, 697, -629, 202, -632, -933, 1126, +416, -438, 563, -625, -1018, 1017, 190, -435, +754, -498, -855, 944, -234, -541, 1022, -311, +-661, 843, -722, -584, 1373, -213, -631, 763, +-952, -507, 1442, -293, -473, 811, -1073, -456, +1307, -461, -195, 977, -1177, -466, 1116, -596, +23, 1086, -1075, -435, 732, -670, 270, 1004, +-843, -231, 210, -745, 566, 798, -645, 70, +-228, -800, 758, 570, -428, 245, -553, -628, +826, 213, -211, 324, -732, -266, 733, -238, +19, 398, -749, 71, 430, -574, 352, 359, +-772, 442, 119, -834, 664, 176, -772, 908, +-147, -1087, 863, -50, -646, 1328, -459, -1229, +994, -291, -412, 1586, -823, -1170, 1109, -548, +-180, 1651, -1154, -883, 1233, -855, -71, 1567, +-1275, -451, 1208, -1140, -5, 1344, -1184, 40, +982, -1335, 122, 995, -1043, 560, 709, -1476, +211, 661, -808, 929, 374, -1464, 301, 357, +-550, 1075, -1, -1189, 473, -64, -456, 1152, +-138, -806, 480, -528, -375, 1209, -121, -410, +290, -927, -167, 1196, -152, -19, 141, -1267, +-43, 1158, -81, 306, -35, -1537, 44, 1127, +42, 530, -281, -1704, 241, 1155, -42, 570, +-289, -1728, 319, 1195, -193, 471, -114, -1603, +220, 1142, -237, 392, 47, -1469, 82, 1098, +-259, 292, 238, -1370, -121, 1167, -210, 85, +368, -1196, -369, 1170, 47, -103, 241, -910, +-458, 929, 323, -153, -26, -483, -382, 464, +415, -165, -129, 67, -353, -37, 396, -267, +-68, 607, -374, -357, 287, -494, 123, 1014, +-435, -440, 131, -797, 366, 1314, -568, -385, +81, -1120, 469, 1573, -573, -326, -8, -1440, +512, 1820, -443, -213, -246, -1792, 661, 1950, +-391, 120, -394, -2199, 699, 1881, -267, 606, +-475, -2494, 564, 1624, -33, 1032, -535, -2483, +383, 1163, 170, 1347, -502, -2203, 119, 538, +399, 1672, -506, -1891, -15, -101, 483, 2001, +-494, -1635, 19, -595, 295, 2180, -268, -1359, +9, -957, 26, 2178, 61, -981, -112, -1271, +-114, 2046, 303, -537, -262, -1487, -127, 1726, +415, -44, -327, -1535, -197, 1235, 545, 438, +-362, -1488, -320, 799, 719, 715, -437, -1371, +-311, 564, 684, 706, -388, -1123, -294, 401, +565, 599, -255, -815, -361, 124, 556, 626, +-163, -572, -436, -218, 486, 796, 30, -457, +-533, -437, 307, 909, 338, -452, -635, -480, +119, 974, 589, -511, -768, -523, 144, 1124, +595, -566, -815, -660, 262, 1234, 444, -445, +-670, -829, 152, 1089, 484, -72, -576, -946, +-43, 744, 632, 324, -571, -904, -138, 353, +687, 538, -525, -691, -228, -7, 734, 637, +-520, -442, -202, -344, 622, 759, -393, -253, +-196, -645, 407, 890, -119, -99, -304, -856, +291, 865, 66, 113, -335, -934, 145, 634, +251, 409, -397, -946, 44, 356, 411, 658, +-464, -942, 0, 184, 431, 773, -336, -916, +-225, 153, 513, 717, -171, -854, -440, 219, +520, 572, -54, -777, -388, 243, 266, 524, +143, -749, -306, 130, 44, 700, 247, -785, +-265, -62, -4, 928, 219, -807, -221, -184, +6, 947, 166, -711, -145, -181, -16, 728, +48, -440, 54, -249, -92, 525, -81, -115, +220, -482, -111, 523, -121, 99, 129, -717, +85, 568, -192, 234, -19, -816, 323, 517, +-376, 308, 18, -737, 443, 399, -585, 261, +127, -548, 581, 263, -809, 233, 165, -443, +764, 170, -967, 299, 140, -470, 870, 126, +-1016, 374, 140, -457, 821, 30, -898, 393, +58, -334, 763, -102, -705, 373, -132, -177, +793, -245, -581, 380, -231, -44, 716, -407, +-403, 427, -293, 63, 558, -532, -145, 409, +-453, 206, 511, -617, 60, 324, -613, 328, +455, -581, 242, 187, -700, 349, 353, -364, +361, -92, -628, 382, 169, -92, 430, -419, +-499, 468, -7, 79, 531, -626, -554, 517, +49, 166, 534, -688, -649, 466, 134, 249, +535, -640, -697, 290, 140, 365, 579, -561, +-711, 89, 132, 476, 511, -456, -587, -97, +57, 511, 485, -263, -527, -330, 40, 488, +533, 2, -647, -535, 135, 437, 520, 197, +-644, -629, 80, 358, 556, 278, -542, -602, +-89, 294, 599, 286, -460, -550, -139, 253, +528, 311, -370, -589, -113, 292, 392, 335, +-242, -709, -122, 434, 265, 305, -70, -838, +-199, 602, 184, 294, 58, -1003, -199, 711, +73, 403, 120, -1190, -137, 700, -45, 649, +208, -1383, -166, 573, -79, 989, 298, -1550, +-281, 404, 0, 1245, 298, -1585, -339, 228, +60, 1365, 268, -1503, -322, 64, 31, 1398, +323, -1362, -367, -89, 12, 1346, 399, -1083, +-429, -341, 21, 1278, 393, -697, -388, -672, +-38, 1229, 414, -373, -335, -886, -112, 1124, +414, -156, -238, -895, -213, 939, 401, -92, +-107, -702, -308, 738, 340, -148, -18, -461, +-205, 577, 82, -185, 131, -345, -73, 494, +-192, -136, 282, -345, -12, 396, -360, 35, +398, -435, 20, 282, -528, 264, 600, -581, +-69, 260, -620, 373, 804, -665, -243, 274, +-564, 386, 861, -646, -351, 220, -472, 407, +806, -561, -317, 70, -473, 447, 752, -392, +-202, -178, -607, 524, 818, -200, -164, -453, +-698, 624, 863, -71, -125, -653, -698, 703, +714, -17, 76, -731, -712, 747, 469, -30, +322, -728, -661, 731, 192, -1, 469, -731, +-509, 658, -16, 108, 447, -772, -297, 577, +-158, 248, 354, -792, -64, 423, -345, 403, +382, -737, 83, 188, -538, 528, 469, -610, +158, -18, -639, 554, 442, -439, 249, -158, +-621, 506, 305, -258, 301, -318, -450, 513, +90, -84, 277, -550, -197, 595, -62, 50, +149, -762, 43, 657, -128, 168, -5, -848, +214, 582, -180, 283, -38, -812, 247, 428, +-186, 348, -55, -694, 280, 256, -149, 361, +-182, -529, 403, 72, -151, 402, -283, -383, +478, -153, -137, 491, -292, -212, 403, -436, +-59, 586, -254, 24, 258, -774, 57, 656, +-199, 293, 68, -1086, 217, 668, -182, 568, +-87, -1289, 313, 543, -84, 843, -261, -1320, +323, 249, 122, 1112, -484, -1236, 390, -100, +220, 1315, -608, -1097, 454, -346, 183, 1343, +-565, -866, 435, -551, 145, 1218, -461, -485, +346, -799, 141, 1027, -342, -16, 206, -1057, +170, 791, -229, 484, 55, -1305, 222, 553, +-124, 903, -116, -1453, 299, 371, -41, 1095, +-270, -1429, 429, 236, -89, 1089, -305, -1248, +550, 94, -254, 1004, -200, -979, 593, -110, +-386, 937, -111, -709, 603, -310, -398, 887, +-160, -526, 649, -390, -323, 784, -294, -403, +660, -357, -159, 637, -466, -316, 659, -299, +2, 512, -576, -258, 579, -230, 162, 383, +-581, -182, 362, -188, 435, 218, -618, -27, +134, -209, 663, 87, -576, 141, -116, -260, +768, 12, -336, 229, -467, -262, 842, -35, +-97, 250, -683, -217, 782, -104, 87, 278, +-661, -179, 539, -202, 284, 351, -610, -137, +341, -324, 406, 390, -530, -28, 191, -478, +464, 369, -399, 195, -46, -649, 580, 271, +-281, 485, -256, -800, 658, 104, -195, 766, +-297, -866, 538, -85, -61, 931, -214, -810, +303, -276, 87, 1001, -156, -665, 163, -464, +153, 1031, -160, -519, 200, -611, 83, 1038, +-126, -437, 233, -629, 7, 985, -51, -430, +179, -519, 49, 844, -65, -429, 210, -381, +18, 703, -76, -423, 322, -282, -161, 644, +52, -482, 343, -181, -292, 623, 155, -535, +329, -121, -306, 572, 155, -469, 334, -179, +-285, 532, 142, -311, 326, -341, -275, 535, +174, -134, 286, -538, -293, 561, 258, 53, +201, -744, -262, 551, 282, 283, 179, -925, +-254, 428, 270, 585, 236, -1023, -338, 177, +317, 883, 263, -985, -401, -139, 335, 1069, +328, -834, -453, -413, 320, 1110, 386, -629, +-466, -576, 288, 1052, 362, -452, -324, -682, +132, 1017, 375, -346, -145, -775, -88, 1038, +458, -302, -61, -791, -223, 988, 521, -276, +-24, -700, -266, 839, 485, -242, 46, -563, +-231, 692, 304, -245, 242, -468, -228, 645, +89, -275, 469, -455, -259, 670, -56, -241, +590, -547, -236, 671, -144, -71, 603, -705, +-165, 594, -173, 174, 538, -836, -56, 462, +-221, 385, 489, -861, 47, 288, -290, 525, +478, -791, 92, 97, -269, 624, 360, -694, +207, -81, -259, 681, 243, -568, 310, -229, +-270, 632, 226, -344, 276, -345, -207, 436, +204, -15, 260, -418, -204, 136, 223, 336, +247, -421, -231, -179, 281, 580, 188, -355, +-167, -403, 243, 658, 177, -261, -116, -463, +181, 600, 196, -167, -91, -492, 164, 535, +207, -62, -91, -578, 137, 541, 249, 33, +-88, -679, 49, 539, 318, 122, 0, -694, +-160, 406, 439, 246, 103, -630, -330, 180, +461, 402, 233, -574, -391, -8, 311, 550, +467, -578, -501, -123, 240, 690, 594, -620, +-570, -231, 250, 849, 571, -657, -478, -364, +148, 980, 564, -618, -339, -488, 7, 971, +559, -477, -182, -552, -136, 858, 498, -325, +24, -551, -250, 731, 384, -259, 241, -489, +-327, 651, 235, -250, 441, -450, -361, 613, +102, -212, 541, -491, -300, 625, -42, -175, +611, -553, -235, 659, -166, -171, 663, -533, +-209, 601, -177, -129, 598, -499, -101, 454, +-202, 67, 477, -583, 72, 292, -274, 398, +382, -759, 200, 109, -276, 754, 253, -900, +312, -107, -238, 1039, 101, -905, 392, -350, +-145, 1184, -51, -750, 394, -608, 42, 1222, +-261, -516, 436, -854, 175, 1232, -425, -320, +484, -1012, 231, 1207, -474, -206, 444, -1042, +335, 1111, -551, -104, 402, -1005, 492, 927, +-697, 49, 412, -950, 588, 717, -777, 190, +402, -882, 631, 542, -766, 242, 322, -722, +682, 354, -715, 215, 214, -477, 718, 139, +-625, 191, 80, -267, 745, -25, -494, 173, +-103, -129, 792, -123, -355, 132, -274, 10, +789, -230, -184, 99, -392, 168, 687, -378, +27, 96, -452, 307, 520, -505, 214, 92, +-429, 404, 302, -549, 377, 33, -392, 483, +147, -531, 462, -73, -340, 553, 55, -473, +462, -198, -228, 591, -66, -367, 464, -322, +-135, 597, -141, -260, 448, -418, -97, 591, +-95, -206, 332, -435, -38, 566, -20, -212, +181, -386, 48, 556, -25, -244, 139, -376, +100, 588, -98, -230, 214, -485, 98, 652, +-172, -124, 257, -662, 157, 692, -283, 43, +262, -833, 290, 662, -424, 232, 295, -952, +346, 572, -447, 395, 254, -970, 380, 416, +-413, 517, 172, -859, 433, 160, -411, 630, +142, -673, 440, -145, -375, 721, 80, -449, +448, -419, -303, 716, -8, -166, 429, -656, +-179, 644, -111, 143, 350, -880, 24, 591, +-250, 370, 294, -1031, 201, 530, -351, 507, +228, -1024, 320, 358, -372, 633, 125, -895, +404, 80, -322, 772, 5, -755, 434, -180, +-192, 887, -162, -623, 482, -414, -71, 964, +-317, -454, 527, -639, -7, 982, -374, -240, +482, -805, 67, 882, -353, 8, 344, -905, +178, 699, -285, 265, 115, -945, 329, 492, +-201, 462, -105, -906, 398, 284, -57, 590, +-280, -797, 354, 80, 171, 647, -454, -652, +311, -74, 336, 619, -543, -477, 251, -165, +452, 507, -565, -302, 176, -204, 543, 386, +-564, -183, 133, -222, 532, 340, -475, -123, +64, -248, 481, 312, -348, -59, 22, -268, +369, 223, -220, 83, 29, -312, 223, 106, +-102, 254, 44, -395, 119, 33, -80, 431, +113, -513, 31, -24, -74, 600, 153, -610, +-5, -78, -75, 710, 118, -637, 96, -144, +-175, 770, 142, -634, 175, -206, -280, 833, +188, -603, 211, -317, -302, 861, 159, -435, +278, -521, -315, 828, 110, -148, 337, -734, +-296, 699, 57, 162, 326, -831, -197, 459, +-3, 427, 226, -800, -49, 219, -50, 584, +105, -741, 96, 57, -110, 683, 52, -697, +141, -89, -119, 762, 49, -567, 83, -314, +-49, 753, 20, -232, 51, -587, -32, 582, +71, 212, -36, -751, 17, 266, 131, 612, +-160, -781, 150, -48, 89, 876, -185, -750, +207, -239, 76, 961, -186, -651, 207, -352, +97, 905, -176, -474, 146, -413, 142, 740, +-145, -251, 48, -416, 189, 485, -118, -1, +-1, -399, 160, 208, -59, 239, -50, -345, +124, -52, -13, 390, -72, -229, 91, -269, +24, 436, -96, -62, 60, -423, 90, 401, +-139, 101, 40, -518, 170, 338, -150, 200, +-38, -496, 255, 227, -86, 227, -154, -369, +292, 51, 22, 282, -242, -220, 244, -150, +149, 301, -256, -18, 123, -326, 243, 210, +-213, 225, 12, -407, 244, 80, -135, 309, +-41, -298, 158, -23, -29, 180, -99, -46, +105, -96, 43, -19, -185, 196, 175, -107, +-42, -228, -130, 371, 176, -43, -98, -477, +-30, 536, 72, 52, -12, -691, -53, 615, +80, 155, 2, -767, -43, 506, 115, 304, +-43, -720, 14, 297, 103, 396, -15, -569, +-46, 97, 180, 384, -39, -352, -83, -99, +205, 383, -65, -157, -35, -306, 86, 383, +43, 57, -129, -455, 70, 249, 102, 346, +-223, -529, 95, -23, 143, 632, -262, -511, +33, -276, 238, 779, -285, -375, -41, -487, +259, 779, -98, -147, -305, -678, 373, 710, +57, 104, -505, -809, 455, 564, 113, 335, +-457, -842, 259, 379, 335, 487, -496, -762, +148, 162, 444, 568, -513, -570, 139, -133, +346, 657, -338, -336, -34, -440, 373, 698, +-253, -94, -188, -633, 418, 585, -185, 160, +-318, -668, 411, 333, -22, 352, -551, -522, +512, 51, 37, 380, -643, -273, 512, -132, +107, 295, -621, -86, 382, -201, 281, 221, +-683, 26, 353, -237, 360, 128, -689, 168, +361, -256, 320, -34, -575, 316, 267, -189, +302, -189, -443, 316, 129, -30, 307, -274, +-308, 220, -47, 90, 332, -281, -184, 154, +-225, 120, 371, -250, -144, 101, -268, 144, +313, -205, -120, 23, -204, 155, 152, -69, +15, -157, -242, 145, 95, 172, 138, -394, +-367, 138, 200, 358, 104, -490, -346, 56, +201, 439, 85, -401, -222, -85, 43, 432, +211, -265, -168, -201, -99, 420, 298, -142, +-118, -325, -202, 439, 319, -37, -44, -423, +-319, 391, 372, 109, -55, -476, -370, 297, +422, 202, -140, -469, -298, 259, 333, 162, +-120, -350, -240, 158, 177, 138, 20, -199, +-274, -15, 101, 209, 79, -125, -246, -130, +59, 274, 83, -176, -163, -72, -21, 297, +134, -310, -141, 74, -32, 234, 179, -329, +-191, 121, 25, 174, 178, -255, -227, 58, +91, 191, 115, -224, -200, -6, 93, 264, +35, -214, -62, -143, -64, 411, 70, -228, +-32, -223, -132, 457, 98, -217, -62, -191, +-105, 294, 30, -65, 11, -146, -191, 137, +78, -28, 49, -49, -268, 95, 96, -117, +77, 27, -181, 158, -76, -154, 164, -146, +-55, 355, -229, -53, 177, -413, 128, 400, +-360, 149, 130, -590, 293, 335, -428, 398, +80, -718, 277, 161, -235, 665, -172, -705, +307, -187, -55, 990, -319, -599, 192, -630, +142, 1165, -344, -263, -56, -988, 409, 1047, +-473, 209, -103, -1240, 450, 752, -383, 667, +-274, -1208, 514, 213, -262, 1037, -434, -937, +544, -401, -104, 1227, -541, -403, 396, -957, +222, 998, -683, 387, 244, -1323, 459, 512, +-641, 1056, -15, -1297, 605, -165, -507, 1412, +-158, -804, 454, -795, -222, 1338, -250, -172, +262, -1134, -31, 929, -263, 480, 172, -1185, +-86, 334, -100, 886, 53, -852, -87, -339, +-120, 1037, 120, -203, -130, -1001, -195, 847, +241, 486, -182, -1127, -241, 261, 291, 892, +-93, -774, -413, -400, 434, 977, -116, -133, +-454, -893, 458, 671, -73, 541, -444, -1103, +333, 253, 95, 970, -497, -951, 275, -191, +125, 903, -337, -395, 5, -427, 203, 502, +-168, 104, -224, -393, 234, -26, -37, 453, +-309, -159, 121, -441, 68, 513, -283, 78, +70, -545, -54, 291, -68, 324, -79, -397, +-17, -62, -92, 286, -18, 24, -2, -256, +-209, 3, 96, 386, -53, -259, -96, -299, +-50, 509, -20, 59, 3, -608, -92, 258, +-83, 600, 121, -652, -184, -323, -104, 998, +194, -271, -174, -865, -155, 787, 133, 415, +-88, -1000, -177, 162, 148, 966, -164, -767, +-172, -536, 235, 1164, -275, -161, -182, -1086, +312, 869, -250, 576, -353, -1215, 362, 122, +-87, 1201, -449, -742, 205, -842, 104, 1236, +-372, 180, -90, -1376, 333, 689, -362, 1057, +-149, -1451, 184, -167, -53, 1728, -263, -1022, +-38, -1054, 260, 1766, -332, -118, -180, -1683, +259, 1221, -42, 943, -520, -1788, 334, 165, +108, 1684, -602, -1197, 149, -941, 372, 1862, +-633, -260, -129, -1704, 620, 1350, -583, 826, +-375, -1758, 638, 294, -205, 1476, -843, -1191, +735, -600, 66, 1576, -1054, -526, 586, -1125, +362, 1413, -1042, 13, 189, -1462, 730, 1240, +-943, 555, -248, -1737, 935, 730, -573, 1293, +-765, -1621, 942, -220, -75, 1810, -1111, -973, +710, -1094, 333, 1602, -1054, 40, 235, -1410, +537, 746, -746, 735, -45, -828, 348, -175, +-497, 495, 92, 90, 115, -170, -607, -306, +276, 137, 268, 518, -844, -195, 100, -670, +578, 344, -708, 842, -283, -672, 607, -688, +-441, 886, -367, 445, 475, -1007, -365, 69, +-364, 838, 482, -667, -294, -119, -433, 886, +349, -832, -123, -405, -309, 1470, 85, -540, +-176, -1243, -26, 1272, -20, 360, -254, -1202, +41, 637, -154, 314, -75, -1013, -17, 862, +-149, 619, -157, -1622, 50, 364, -203, 1548, +-173, -1356, 211, -579, -106, 1882, -627, -916, +67, -1424, 709, 2125, -684, 244, -701, -2339, +688, 1060, 187, 1593, -982, -1932, 230, -63, +503, 1851, -850, -1308, -203, -931, 794, 1934, +-549, -313, -633, -1390, 714, 1131, -355, 232, +-577, -1180, 782, 917, -447, 730, -866, -1701, +1021, 161, -135, 1777, -1239, -1011, 703, -1184, +614, 1624, -1294, 204, -228, -1749, 1095, 812, +-479, 1507, -910, -1562, 545, -868, 174, 1846, +-677, 39, 46, -1433, 374, 580, -588, 728, +-369, -857, 667, -22, -167, 991, -895, -564, +299, -985, 675, 1149, -979, 680, -460, -1444, +1048, -22, -354, 1228, -1011, -615, 609, -396, +288, 733, -938, -495, 246, -170, 381, 873, +-835, -609, 36, -533, 502, 1138, -521, -178, +-456, -1158, 630, 883, -326, 851, -723, -1363, +824, -192, -106, 1361, -1208, -415, 678, -889, +735, 739, -1548, 275, 110, -631, 1141, 137, +-1141, 348, -460, -206, 1226, 39, -824, -79, +-940, -303, 1419, 766, -265, 177, -1539, -1355, +920, 303, 658, 1634, -1322, -934, 19, -1335, +780, 1343, -838, 751, -137, -1404, 677, -96, +-749, 1214, -391, -350, 844, -890, -260, 568, +-1053, 653, 566, -662, 692, -396, -974, 707, +-692, 210, 924, -876, 330, 291, -969, 964, +-411, -1038, 543, -653, 424, 1681, -676, 74, +-596, -1867, 425, 437, 428, 1750, -546, -647, +-523, -1532, 413, 709, 35, 1346, -367, -791, +176, -979, -301, 904, -393, 373, 487, -853, +207, 440, -749, 538, -362, -1165, 402, 141, +474, 1326, -386, -592, -1004, -1033, 338, 707, +931, 542, -631, -346, -933, -252, 813, -55, +183, 359, -1038, 94, 378, -530, 758, 225, +-1118, 714, -477, -750, 1205, -687, -266, 1229, +-1053, 518, 690, -1413, 152, -212, -1115, 1219, +742, 67, 627, -827, -1603, -102, 90, 603, +1420, 283, -1048, -851, -885, -108, 1324, 1347, +-142, -548, -1320, -1443, 618, 1247, 726, 1105, +-794, -1638, -472, -371, 460, 1619, 61, -568, +-298, -1057, 152, 1455, -135, 13, -626, -1720, +417, 1034, 753, 1290, -923, -1470, -868, -477, +1104, 1127, 507, -95, -1385, -305, -9, 234, +1013, -576, -695, 259, -571, 881, 991, -857, +-230, -387, -1290, 866, 838, -134, 1056, -454, +-1490, 447, -898, -54, 1662, -466, 538, 498, +-1899, 396, -391, -940, 1705, -109, 165, 1340, +-1632, -275, -289, -1580, 1470, 548, 217, 1993, +-1571, -945, -286, -2413, 1681, 1703, -119, 2428, +-1779, -2565, 369, -1840, 1658, 3306, -906, 703, +-1498, -3574, 1300, 747, 782, 3167, -1505, -1862, +-191, -2333, 1251, 2395, -534, 1523, -876, -2458, +834, -929, 172, 2522, -965, 208, 244, -2362, +646, 710, -586, 1668, -362, -1212, 456, -760, +-139, 1151, -79, 64, 204, -690, -574, 318, +-98, 82, 917, -392, -374, 557, -1065, 255, +792, -992, 545, -77, -1005, 1282, 58, -37, +682, -1397, -705, 75, -41, 1414, 625, -89, +-552, -1216, -337, 12, 738, 887, -195, 289, +-854, -610, 657, -690, 433, 532, -838, 1219, +-230, -873, 621, -1527, 80, 1593, -429, 1316, +-401, -2235, 354, -512, 639, 2211, -710, -276, +-865, -1471, 1064, 505, 848, 637, -1646, -191, +-705, -244, 2023, -84, 262, 281, -2322, -23, +257, -317, 2213, 412, -871, 162, -1959, -780, +1287, 171, 1541, 971, -1729, -445, -1143, -1192, +2015, 826, 517, 1455, -2212, -1419, 109, -1533, +2088, 2121, -961, 1262, -1697, -2522, 1576, -783, +934, 2455, -1932, 388, -275, -2100, 1804, -61, +-371, 1659, -1342, -340, 497, -1091, 679, 864, +-366, 220, -315, -1082, 81, 657, 69, 997, +-51, -1355, 136, -557, -122, 1638, -299, -48, +245, -1312, 293, 359, -415, 688, -347, -214, +542, -58, 261, -274, -591, -333, -359, 840, +552, 526, 422, -1333, -510, -445, -728, 1498, +640, 236, 713, -1149, -880, -179, -533, 503, +875, 431, 250, 39, -973, -708, 66, -304, +815, 755, -361, 422, -735, -547, 591, -520, +524, 266, -982, 676, -152, -229, 1172, -646, +-308, 445, -1279, 279, 579, -743, 1276, 446, +-721, 763, -1171, -1165, 438, -465, 1148, 1534, +-57, 21, -1261, -1383, -400, 374, 1494, 761, +463, -524, -1715, 76, -120, 576, 1469, -1035, +-436, -480, -997, 1911, 945, 264, 253, -2392, +-1301, -13, 251, 2199, 1572, 58, -727, -1473, +-1693, -383, 742, 401, 1737, 861, -484, 904, +-1853, -1479, -52, -2075, 1911, 2012, 619, 2922, +-1950, -2327, -1090, -3225, 1627, 2135, 1633, 3190, +-1388, -1533, -1889, -3034, 858, 912, 2129, 2644, +-434, -301, -2442, -2149, 415, -208, 2432, 1801, +-694, 333, -2071, -1498, 843, -155, 1573, 1175, +-745, 15, -1353, -1054, 450, -11, 1396, 1166, +-139, 222, -1785, -1412, 98, -737, 1807, 1675, +-12, 1571, -1503, -1973, -301, -2463, 821, 2168, +836, 3146, 80, -2208, -1729, -3274, -869, 1953, +2616, 2697, 1268, -1175, -3077, -1766, -1440, 76, +2838, 828, 1775, 986, -2316, -134, -2190, -1685, +1717, -259, 2540, 1959, -1243, 342, -2690, -1963, +986, -12, 2435, 1703, -835, -655, -1870, -1002, +669, 1102, 1079, 111, -510, -892, -125, 535, +35, 114, -612, -718, 495, 926, 975, 427, +-867, -1628, -1169, -134, 1106, 1754, 1108, 312, +-1086, -1570, -1005, -855, 976, 1258, 733, 1382, +-668, -868, -420, -1512, 335, 357, -100, 1045, +256, 333, 664, -76, -1136, -1198, -848, -1058, +1853, 2197, 932, 1705, -2536, -2875, -602, -1531, +2728, 2759, 181, 856, -2414, -1908, 158, -139, +1771, 851, -480, -395, -694, -98, 491, 864, +-400, -379, -362, -1136, 1417, 667, 121, 1208, +-2117, -996, 17, -1071, 2518, 1696, 1, 473, +-2642, -2455, 37, 529, 2206, 2638, 189, -1288, +-1418, -2025, -499, 1290, 420, 856, 880, -505, +546, 474, -1018, -630, -1286, -1513, 760, 1388, +1932, 2098, -262, -1272, -2144, -2223, -369, 182, +1955, 2074, 1028, 1319, -1260, -1647, -1609, -2540, +439, 816, 1923, 3103, 400, 267, -1847, -2979, +-983, -1075, 1554, 2090, 1121, 1228, -1002, -519, +-782, -897, 518, -1053, 18, 112, 26, 2060, +749, 931, -212, -2205, -1194, -1962, -104, 1625, +1455, 2567, 755, -619, -1386, -2497, -1346, -289, +1092, 1637, 1568, 701, -275, -55, -1376, -699, +-727, -1638, 941, 311, 1744, 2837, -246, 289, +-2523, -3111, -280, -926, 2830, 2433, 672, 1415, +-2553, -1091, -794, -1622, 1968, -381, 648, 1477, +-1098, 1490, -226, -1050, 260, -1850, -286, 395, +532, 1473, 716, 397, -922, -666, -969, -1165, +1012, -116, 1191, 1792, -929, 359, -1141, -1913, +902, -112, 869, 1610, -910, -555, -125, -894, +790, 1255, -509, -8, -595, -1580, 969, 687, +618, 1509, -1159, -1023, -616, -1114, 1112, 1017, +755, 651, -952, -938, -559, -153, 692, 904, +127, -342, -190, -814, 434, 684, -171, 513, +-966, -523, 531, -213, 1304, -60, -703, 60, +-1049, 721, 639, 8, 525, -1172, -374, -125, +236, 1209, 313, 409, -1002, -827, -392, -853, +1735, 161, 683, 1418, -2114, 424, -836, -1801, +2060, -789, 967, 1899, -1486, 717, -830, -1597, +724, -218, 533, 880, 270, -446, -235, -25, +-871, 1101, 5, -768, 1109, -1449, 288, 1326, +-969, 1247, -359, -1403, 594, -587, 542, 972, +-237, -151, -465, -394, -59, 763, 456, -118, +430, -984, -583, 332, -486, 762, 761, -253, +570, -233, -843, 154, -471, -569, 764, -245, +506, 1572, -333, 401, -623, -2460, -50, -365, +706, 2583, 576, 316, -653, -1761, -835, -433, +480, 312, 926, 656, -47, 1232, -653, -813, +-377, -2367, 120, 676, 1081, 2868, 355, -292, +-1498, -2718, -526, -116, 1626, 1982, 470, 369, +-1172, -920, -211, -377, 401, -130, 307, 190, +182, 889, -417, -56, -207, -1083, 562, 87, +-26, 700, -630, -300, 501, -61, 775, 682, +-733, -457, -975, -1152, 790, 630, 1318, 1497, +-538, -430, -1524, -1337, 256, -211, 1604, 682, +-95, 1172, -1038, 69, 13, -1932, 289, -609, +-24, 2042, 655, 810, 239, -1387, -1429, -755, +-245, 346, 1826, 446, 240, 541, -1630, 123, +-23, -1043, 1076, -764, -64, 1141, -386, 1052, +244, -850, -19, -821, -320, 230, 195, 292, +499, 349, -126, 192, -487, -458, 128, -514, +370, -62, -57, 774, -86, 746, 119, -823, +-6, -1202, -229, 528, 34, 1306, 528, -56, +47, -1022, -574, -373, -200, 519, 594, 511, +422, -3, -409, -195, -402, -427, 182, -422, +232, 663, 272, 1061, 144, -620, -707, -1524, +-292, 432, 988, 1480, 449, -35, -897, -1050, +-477, -507, 787, 609, 404, 820, -490, -341, +-48, -592, 93, 175, -107, -171, 275, 164, +257, 964, -332, -672, -302, -1285, 386, 1116, +287, 933, -221, -1197, -61, -236, 61, 922, +-101, -379, 248, -595, 205, 680, -274, 424, +-151, -735, 253, -388, 186, 599, -115, 341, +-54, -386, 51, -210, 72, 244, -62, -45, +54, -230, 243, 278, -125, 502, -260, -542, +202, -874, 315, 754, -105, 1070, -210, -729, +74, -1054, 166, 557, 29, 720, -41, -327, +35, -89, 58, 37, -24, -520, -141, 109, +223, 958, 302, -44, -227, -1259, -313, 41, +99, 1173, 480, -143, 197, -653, -415, 209, +-546, -73, 502, -90, 793, 558, -327, -110, +-728, -543, 72, 95, 672, 285, 329, 56, +-462, -55, -573, -164, 528, -41, 500, 103, +-368, 19, -80, 75, 195, 9, -196, -197, +78, -56, 343, 127, 42, 158, -237, -25, +-338, -139, 344, -171, 586, 25, -186, 438, +-621, -53, 130, -449, 529, 149, -17, 76, +4, -206, -26, 576, -472, 124, -25, -1208, +1128, -3, 240, 1680, -1480, -239, -351, -1804, +1561, 686, 595, 1284, -1189, -1090, -653, -250, +721, 1248, 671, -914, -163, -1111, -287, 1719, +-184, 840, -99, -1950, 394, -619, 590, 1660, +-202, 460, -802, -1025, -61, -338, 854, 257, +532, 232, -592, 348, -652, -116, 200, -590, +610, -72, 467, 419, -275, 332, -906, 85, +-33, -742, 1158, -577, 524, 1121, -1000, 821, +-868, -1252, 855, -856, 1066, 1162, -471, 662, +-940, -914, 321, -313, 664, 509, -132, 25, +-59, -224, 47, 166, -336, 182, 107, -381, +667, -275, -90, 572, -596, 417, 31, -739, +560, -505, 213, 836, -411, 484, -330, -863, +577, -387, 303, 862, -635, 283, 100, -1024, +570, -19, -211, 1253, -385, -527, 326, -1225, +344, 1073, -266, 809, -92, -1314, 232, -109, +-114, 1041, -82, -502, 557, -480, 28, 916, +-873, -200, 145, -1069, 1133, 858, -79, 802, +-1100, -1188, 155, -292, 857, 1070, -17, -204, +-309, -682, 19, 513, -157, 236, 20, -632, +731, 124, -10, 539, -843, -287, 52, -328, +800, 270, -21, 78, -359, -154, 125, 135, +-48, 31, -114, -256, 406, -104, 371, 473, +-554, 240, -444, -838, 590, -187, 519, 1114, +-267, -33, -438, -1184, -7, 282, 520, 1049, +192, -496, -420, -771, 39, 567, 277, 425, +-282, -431, 71, -155, 590, 74, -294, 134, +-502, 305, 355, -313, 383, -572, 16, 515, +-217, 642, -213, -573, 110, -552, 418, 291, +225, 551, -538, 92, -213, -636, 523, -404, +218, 713, -192, 522, -96, -750, -29, -304, +-26, 500, 413, 5, 190, -56, -537, 70, +-198, -256, 675, 3, 179, 273, -561, -54, +81, -168, 418, -21, -195, 237, -218, 59, +445, -652, 158, 231, -502, 1080, -20, -796, +556, -1163, -11, 1258, -377, 773, 252, -1255, +53, -48, -332, 590, 456, -499, 360, 364, +-727, 668, -172, -1037, 823, -638, 58, 1240, +-536, 566, 61, -1042, 309, -526, -55, 672, +-48, 422, 149, -304, 64, -189, -232, -35, +-52, -35, 439, 218, 102, 117, -422, -151, +10, -91, 337, -70, -126, -32, 90, 242, +296, 243, -462, -209, -276, -597, 739, 22, +399, 967, -703, 148, -444, -1106, 559, -300, +612, 941, -206, 365, -672, -551, 38, -260, +645, 20, 122, 24, -311, 466, -144, 239, +0, -669, 158, -499, 400, 503, -44, 730, +-532, -163, 41, -817, 423, -152, 151, 576, +-52, 352, -213, -51, -299, -393, 248, -654, +696, 293, -30, 1344, -883, -235, -200, -1684, +1014, 207, 427, 1498, -786, -130, -441, -946, +448, 49, 384, 175, 114, 45, -182, 570, +-513, -239, 77, -929, 740, 411, 84, 793, +-620, -436, -65, -316, 358, 321, 68, -319, +17, -57, 84, 827, -247, -292, -134, -954, +353, 553, 203, 635, -156, -570, -120, -43, +-46, 274, -86, -512, 460, 208, 370, 777, +-746, -706, -416, -599, 741, 929, 597, 112, +-476, -743, -608, 285, 144, 365, 602, -464, +343, -41, -470, 488, -705, -184, 365, -434, +1085, 363, -343, 352, -1035, -544, 306, -265, +851, 711, -39, 157, -580, -818, -174, -36, +403, 755, 472, -94, -363, -426, -434, 104, +367, -15, 238, -3, -125, 301, 24, 18, +-121, -490, -142, -85, 415, 571, 134, 40, +-452, -350, 38, 18, 322, -78, -89, -56, +-10, 446, 96, 208, -184, -733, 74, -406, +166, 889, -10, 507, -13, -827, -119, -445, +-7, 549, 238, 210, 146, -49, -344, 19, +-97, -511, 449, -108, 58, 834, -430, 81, +99, -845, 402, -45, -186, 694, -314, -70, +305, -463, 411, 288, -558, 133, -294, -469, +835, 210, 129, 450, -933, -368, 118, -276, +932, 260, -301, 154, -637, -68, 329, -118, +363, -71, -169, 171, -42, 48, -8, -265, +-104, 153, 189, 270, 153, -405, -83, -126, +-145, 526, -112, -131, 204, -425, 440, 404, +-247, 112, -632, -588, 284, 327, 756, 543, +-155, -669, -794, -257, 165, 723, 672, -205, +-73, -429, -321, 602, -39, -59, -33, -788, +255, 405, 363, 888, -424, -534, -435, -998, +499, 590, 432, 952, -386, -602, -256, -618, +144, 452, 168, 119, 218, -168, -125, 366, +-420, -222, 185, -609, 493, 558, -121, 462, +-395, -602, 53, -133, 281, 310, 134, -84, +-106, 70, -321, 78, 68, -308, 459, 61, +43, 370, -512, -249, -49, -328, 464, 422, +139, 259, -246, -568, -288, -128, 123, 534, +437, 27, 3, -308, -393, -36, -125, 59, +308, 43, 302, 144, -140, 14, -374, -284, +19, -96, 437, 284, 51, 121, -285, -52, +-36, -126, 93, -392, 5, 227, 205, 809, +56, -436, -365, -872, -75, 498, 404, 648, +201, -409, -316, -269, -248, 326, 195, -275, +293, -177, -59, 782, -206, -31, 39, -999, +99, 194, -136, 807, 193, -206, 353, -277, +-568, 8, -420, -304, 889, 257, 423, 723, +-949, -394, -293, -982, 793, 441, 215, 968, +-379, -421, -203, -661, 43, 303, 271, 202, +181, -135, -266, 261, -149, -49, 206, -536, +-20, 163, 73, 567, 187, -172, -286, -399, +-266, 84, 505, 157, 271, 22, -589, 38, +-79, -94, 546, -78, -62, 64, -480, -30, +318, 27, 400, 260, -399, -123, -393, -600, +416, 243, 626, 883, -452, -305, -799, -1055, +554, 277, 910, 1115, -667, -242, -622, -1047, +623, 243, 240, 813, -344, -231, 95, -496, +99, 213, -224, 128, 145, -146, 112, 255, +-59, -122, 121, -431, -173, 431, -202, 354, +429, -572, 199, -239, -488, 558, -42, 200, +376, -496, -58, -212, -123, 373, 166, 243, +-43, -200, -216, -263, 135, -73, 329, 349, +-111, 332, -373, -511, 130, -433, 342, 618, +-119, 377, -117, -627, 149, -163, -169, 478, +-152, -92, 562, -239, 119, 334, -803, 8, +45, -596, 770, 272, -69, 759, -473, -567, +35, -680, 103, 667, 137, 495, 290, -602, +-308, -295, -478, 440, 508, 102, 431, -190, +-499, -68, -138, 16, 325, 114, -134, 67, +-28, -187, 374, -126, -256, 298, -383, 178, +458, -411, 273, -244, -492, 515, -1, 278, +419, -527, -219, -254, -269, 365, 362, 280, +248, -114, -373, -359, -286, -92, 362, 423, +391, 198, -318, -433, -297, -142, 251, 272, +43, 44, 14, -11, 286, -12, -302, -191, +-445, 17, 469, 268, 527, -25, -385, -217, +-492, 20, 164, 65, 463, 41, 93, 101, +-342, -180, -210, -101, 213, 259, 121, -65, +117, -152, 82, 251, -513, -140, -106, -246, +758, 419, 96, 13, -797, -478, 128, 321, +514, 262, -243, -555, -86, 123, 309, 521, +-218, -362, -319, -319, 424, 288, 244, 226, +-308, -9, -192, -387, 125, -133, 102, 615, +207, 27, 6, -660, -491, 192, -47, 464, +661, -362, 160, -83, -721, 304, -138, -257, +632, -38, 123, 371, -395, -266, -90, -300, +226, 477, 35, 161, -73, -566, 111, -73, +-4, 579, -298, 68, 146, -599, 493, 25, +-364, 494, -456, -226, 587, -74, 246, 303, +-654, -552, 120, -39, 519, 1030, -382, -510, +-162, -1030, 465, 1030, -240, 562, -288, -1234, +587, 112, -5, 1077, -711, -694, 269, -686, +752, 978, -416, 291, -648, -977, 458, -50, +472, 848, -336, -118, -196, -637, 156, 264, +-74, 263, 116, -260, 288, 148, -326, 57, +-345, -412, 417, 206, 359, 508, -321, -442, +-325, -446, 126, 531, 350, 371, 83, -499, +-369, -331, -192, 484, 383, 143, 311, -322, +-434, 124, -267, -85, 455, -223, 182, 487, +-407, 176, -17, -737, 370, -111, -191, 835, +-206, 21, 356, -749, 9, 39, -383, 510, +236, 25, 205, -269, -280, -179, 47, 184, +190, 229, -258, -147, 56, -191, 346, 76, +-279, 174, -195, -30, 264, -129, 103, -35, +-168, 111, -5, 124, 67, -135, -32, -181, +-26, 181, 96, 199, 91, -155, -236, -285, +-89, 177, 375, 397, 20, -333, -353, -307, +94, 422, 191, 77, -152, -339, 69, 132, +156, 143, -300, -201, -45, 23, 411, 159, +-64, -66, -388, -88, 215, -2, 198, 62, +-272, 94, 112, -58, 199, -180, -279, 45, +-95, 301, 274, -144, 71, -318, -92, 299, +-112, 161, -175, -358, 314, 29, 335, 330, +-486, -129, -330, -323, 534, 214, 201, 304, +-381, -274, 73, -245, -48, 293, -131, 144, +397, -310, 125, 44, -522, 277, -70, -363, +434, -77, 95, 666, -154, -411, -325, -504, +69, 661, 464, 95, -107, -449, -319, 99, +95, 140, 43, -172, 118, 133, 84, 251, +-319, -489, 1, -221, 440, 893, -218, -140, +-439, -936, 580, 579, 100, 466, -636, -619, +239, 145, 452, 116, -306, -281, -297, 320, +352, 48, 55, -285, -253, 12, 143, 129, +41, 79, -14, -20, -90, -193, -50, -26, +160, 305, 121, -70, -202, -280, -235, 205, +376, 186, 79, -411, -189, 29, -126, 622, +34, -470, 195, -402, 25, 588, -101, 67, +-134, -279, 45, 5, 87, -85, 196, 156, +-179, 212, -307, -359, 322, 30, 251, 211, +-401, -244, -99, 131, 476, 269, -286, -411, +-199, -137, 375, 542, -1, -201, -279, -256, +116, 427, 77, -375, -241, -165, 366, 744, +66, -270, -543, -704, 85, 542, 560, 472, +-263, -660, -244, -155, 206, 640, -125, -175, +40, -502, 312, 431, -160, 250, -465, -459, +321, -8, 184, 277, -80, -113, 31, 16, +-160, 87, -184, -269, 143, -57, 613, 477, +-333, 82, -737, -758, 313, 20, 751, 920, +-181, -241, -598, -783, -32, 361, 289, 451, +356, -288, -125, -129, -461, 132, -48, -87, +508, -5, 37, 197, -410, -39, 111, -236, +70, 15, -47, 272, 61, -72, 58, -191, +-61, 158, -196, -31, 116, -71, 159, 130, +-112, -103, 3, 41, 102, 196, -329, -405, +28, -128, 575, 773, -242, -88, -507, -942, +206, 377, 395, 626, -49, -389, -208, 11, +-225, -130, 79, -403, 445, 704, -19, 475, +-506, -981, -17, -413, 495, 950, -116, 271, +-231, -675, 25, -67, 122, 275, 62, -195, +-243, 285, 96, 243, 170, -656, -42, -87, +-321, 565, -26, 102, 660, -332, -157, -211, +-766, 154, 384, 192, 497, 105, -403, -224, +-107, -360, 219, 478, -134, 222, -174, -527, +463, -24, -36, 429, -518, -40, 42, -391, +450, 82, 76, 357, -290, -61, -350, -441, +288, 249, 403, 350, -406, -542, -5, 74, +116, 613, -202, -554, 54, -411, 423, 820, +-333, 136, -386, -858, 403, 228, 168, 498, +-282, -329, 124, -5, -16, 54, -352, -123, +313, 107, 322, 81, -334, -133, -289, -29, +269, 209, 88, -236, -42, -125, 133, 584, +-428, -335, 9, -511, 487, 766, -113, -1, +-269, -735, -16, 426, 98, 420, -5, -452, +213, -354, -194, 559, -228, 129, 239, -485, +152, 247, -358, -74, 167, -286, 276, 718, +-599, -73, 97, -992, 650, 526, -316, 713, +-605, -593, 448, -392, 300, 639, -400, -188, +-13, -438, 280, 857, -363, -118, -41, -1164, +512, 783, -241, 967, -422, -1312, 266, -246, +316, 1397, -264, -690, -229, -997, 298, 1535, +-72, 95, -192, -1785, 207, 861, 149, 1345, +-407, -1459, -53, -382, 457, 1429, -178, -602, +-298, -928, 239, 1351, 2, 147, -111, -1669, +104, 751, -71, 1361, -112, -1381, 20, -487, +204, 1381, -111, -415, -207, -896, 108, 954, +186, 304, -156, -1138, -164, 267, 37, 839, +332, -556, -200, -261, -405, 543, 344, -446, +323, -103, -522, 826, -187, -435, 548, -742, +-38, 783, -509, 278, 231, -761, 414, 299, +-653, 417, -112, -689, 803, -23, -207, 980, +-873, -469, 448, -923, 678, 792, -539, 625, +-447, -904, 336, -160, 288, 768, -194, -352, +-212, -430, 139, 794, -95, -69, 51, -997, +37, 613, -112, 785, 86, -851, -125, -358, +-116, 738, 185, -19, 119, -509, -214, 350, +-235, 342, 49, -784, 359, -15, 89, 1115, +-567, -536, -136, -905, 387, 896, 249, 161, +-216, -554, -437, 349, 115, 64, 193, -613, +182, 225, -149, 1052, -374, -689, -77, -1329, +448, 1310, 204, 1084, -525, -1737, -143, -279, +178, 1529, 107, -637, 79, -726, -72, 1193, +-424, -227, 25, -1313, 559, 1044, -172, 1082, +-491, -1664, 182, -373, 198, 1746, -239, -483, +90, -1276, 134, 1124, -345, 516, -56, -1467, +234, 519, -23, 1175, -46, -1404, 8, -198, +-386, 1595, 33, -966, 714, -926, -307, 1666, +-872, -251, 589, -1511, 434, 1294, -606, 537, +58, -1549, 304, 626, -570, 940, -51, -1405, +936, 232, -572, 1526, -728, -1631, 681, -597, +250, 2395, -628, -1043, 151, -1784, 401, 2235, +-754, 266, 80, -2340, 817, 1158, -512, 1658, +-669, -2060, 628, -492, 132, 2134, -376, -620, +39, -1482, 45, 1198, -81, 627, -73, -1187, +26, 26, 67, 631, 138, -36, -496, -22, +-93, -508, 534, -341, 109, 1299, -640, 329, +-194, -2001, 593, 126, -57, 2032, -321, -598, +183, -1232, -225, 458, -224, 184, 545, 221, +34, 548, -769, -898, 162, -923, 605, 1352, +-508, 865, -226, -1413, 446, -323, -71, 862, +-631, -391, 360, 316, 473, 582, -498, -1293, +-427, -266, 340, 1503, 217, -152, 47, -978, +-460, 462, -406, -163, 753, -221, 284, 1148, +-986, -422, -31, -1457, 881, 1088, -555, 948, +-484, -1407, 833, 81, -36, 1217, -1170, -1178, +595, -501, 891, 1694, -1004, -293, -353, -1464, +779, 783, -295, 767, -321, -946, 518, 197, +-340, 612, -439, -785, 668, -105, -168, 839, +-663, -384, 633, -428, 407, 804, -1257, -276, +-17, -1157, 1371, 1130, -446, 1157, -1119, -1698, +425, -769, 668, 1692, -549, 134, -135, -1136, +377, 600, -322, 244, -576, -1174, 837, 588, +255, 1500, -1046, -1175, 73, -1343, 629, 1216, +-437, 900, -170, -868, 697, -213, -603, 192, +-860, -378, 1081, 444, 728, 796, -1525, -859, +-334, -1000, 1263, 1046, -239, 837, -665, -783, +424, -485, -262, 96, -269, 257, 617, 777, +-70, -414, -704, -1318, 197, 784, 280, 1312, +-236, -1171, 237, -695, -177, 1114, -800, 73, +672, -893, 829, 435, -1172, 520, -624, -546, +1108, -89, 156, 9, -844, 94, 292, 780, +-90, -621, -463, -1334, 898, 1410, 175, 1363, +-1586, -2141, 219, -911, 1605, 2616, -629, 65, +-1369, -2538, 626, 630, 750, 2196, -408, -1087, +-227, -1613, -301, 1067, -284, 1029, 1241, -632, +37, -649, -1896, 34, 86, 498, 2151, 388, +-305, -370, -2342, -513, 388, 70, 2045, 512, +-407, 209, -1746, -190, 160, -735, 1173, -121, +233, 1393, -1021, 200, -643, -1978, 815, 13, +750, 2228, -650, -251, -1059, -2291, 476, 575, +995, 2079, -410, -962, -773, -1360, 0, 1056, +266, 351, 277, -763, 385, 656, -994, 263, +-1043, -1487, 1688, 323, 1079, 2043, -2210, -1016, +-1035, -2042, 2524, 1538, 356, 1613, -2652, -1881, +504, -869, 2114, 1976, -1375, 116, -1251, -2030, +1420, 792, 402, 1748, -1321, -1568, 255, -1039, +852, 1767, -1066, 559, -109, -1936, 1161, -110, +-596, 2101, -939, -326, 731, -2083, 261, 469, +-472, 2110, 136, -468, -6, -2219, -534, 661, +196, 2161, 569, -1231, -158, -1537, -717, 1846, +-120, 485, 486, -2283, 468, 671, -487, 2497, +-766, -1775, 417, -2270, 545, 2467, -310, 1743, +-567, -2866, 441, -757, 303, 2791, -913, -454, +-171, -2255, 1357, 1397, -68, 1702, -1770, -1970, +-102, -1277, 2013, 1982, 61, 1196, -2057, -1519, +3, -1417, 1425, 623, -160, 1975, -576, 323, +33, -2566, -455, -1114, 90, 2935, 1153, 1688, +-473, -2975, -1546, -1992, 545, 2662, 1608, 2103, +-643, -2179, -1683, -1964, 566, 1534, 1366, 1784, +-223, -957, -1385, -1541, -352, 467, 1495, 1201, +726, 236, -2019, -1131, -798, -1136, 2452, 1642, +262, 1753, -2782, -2374, 378, -1971, 2831, 2951, +-1428, 1833, -2521, -3126, 2194, -1385, 1635, 2803, +-2613, 735, -699, -2050, 2415, 18, -328, 937, +-1900, -525, 864, 149, 1169, 673, -1063, -843, +-878, -727, 1032, 1377, 586, 593, -902, -1817, +-836, -195, 1054, 1940, 682, 2, -1262, -1992, +-524, -193, 1275, 2245, 192, 471, -1375, -2523, +268, -601, 960, 2338, -613, 859, -651, -1873, +885, -1140, -58, 1365, -899, 1091, 554, -704, +428, -721, -818, -59, 185, 122, 430, 926, +-761, 392, 5, -1605, 1166, -783, -767, 2026, +-1284, 994, 1285, -2119, 929, -1083, -1623, 1904, +-461, 1164, 1649, -1512, -358, -1298, -1348, 1110, +728, 1425, 935, -725, -890, -1447, -631, 241, +421, 1482, 560, 232, 68, -1469, -646, -607, +-739, 1314, 651, 758, 1280, -835, -863, -770, +-1560, 101, 824, 733, 1578, 613, -1022, -614, +-1268, -963, 1077, 220, 468, 1023, -934, 238, +193, -733, 669, -561, -941, 146, -487, 584, +1579, 625, 245, -260, -2336, -1477, -94, -132, +3032, 2012, -259, 524, -3616, -2128, 557, -619, +3751, 1542, -886, 578, -3547, -470, 1073, -441, +2801, -840, -1210, 304, -1963, 2054, 1445, -257, +782, -2796, -1811, 220, 297, 2835, 2124, -67, +-1133, -2008, -2639, -600, 1600, 778, 2935, 1693, +-1694, 378, -3234, -2711, 1554, -1237, 3043, 3095, +-1298, 2088, -2491, -3038, 727, -2673, 1601, 2679, +-34, 2682, -806, -1955, -902, -2226, 403, 1082, +1468, 1569, -258, -407, -2031, -981, 444, 169, +2330, 597, -1031, -229, -2396, -702, 1561, 487, +2190, 1364, -1903, -764, -2063, -2322, 1712, 788, +2226, 3261, -1352, -317, -2679, -4049, 804, -361, +3026, 4290, -261, 1022, -3028, -3741, -549, -1581, +2657, 2580, 1139, 1909, -1744, -1229, -1753, -1796, +355, -28, 2261, 1384, 971, 955, -2573, -1035, +-2222, -1243, 2780, 935, 2766, 858, -2718, -1035, +-2841, -98, 2341, 1103, 2467, -365, -1723, -1185, +-2122, 251, 952, 1182, 1942, 446, -428, -1030, +-1830, -1296, -68, 484, 1667, 2031, 387, 319, +-1298, -2299, -855, -996, 815, 1645, 1125, 1509, +-192, -207, -1294, -1748, -576, -1549, 1321, 1722, +1099, 2951, -1161, -1418, -1415, -3536, 810, 958, +1402, 3108, -389, -447, -1270, -1992, 34, 61, +924, 688, 185, 152, -526, 299, -388, -303, +-42, -631, 758, 573, 608, 299, -1549, -1115, +-907, 437, 2249, 1820, 1106, -1066, -2692, -2384, +-1454, 933, 2752, 2693, 1717, 119, -2194, -2798, +-2020, -1393, 1132, 2325, 2029, 2295, 256, -1157, +-1767, -2454, -1521, -325, 995, 1643, 2282, 1535, +144, 126, -2331, -2136, -1503, -2338, 1649, 1981, +2687, 4229, -529, -1189, -3404, -5122, -699, 148, +3419, 4581, 1513, 836, -2521, -2781, -2104, -1518, +1264, 358, 2175, 1844, -80, 1692, -1770, -1616, +-767, -2809, 907, 900, 1305, 2928, -83, -73, +-1505, -2143, -468, -673, 1325, 966, 639, 1138, +-953, 59, -470, -1142, 487, -662, 32, 764, +-230, 610, 778, 100, 26, -151, -1791, -1311, +46, -338, 2801, 2530, -52, 589, -3472, -3269, +-198, -614, 3593, 3152, 646, 758, -3073, -2450, +-1195, -752, 2002, 1128, 1427, 578, -437, 569, +-1199, -290, -1413, -2125, 674, -176, 2883, 3039, +169, 919, -3804, -3205, -916, -1739, 3872, 2853, +1298, 2032, -3329, -1913, -999, -1729, 2341, 755, +71, 864, -1245, 288, 1033, 187, 465, -841, +-1922, -1106, -230, 864, 2263, 1622, 488, -609, +-2084, -1585, -774, 422, 1312, 1088, 823, -644, +-207, -271, -596, 1159, -748, -380, 52, -1868, +1269, 692, 473, 2365, -1075, -575, -877, -2335, +340, 148, 990, 1753, 522, 192, -707, -711, +-1138, -248, 72, -353, 1281, -77, 662, 888, +-971, 874, -1211, -753, 368, -1795, 1341, 20, +173, 2431, -889, 979, -604, -2436, 270, -1736, +428, 1565, 589, 2009, 138, -64, -1500, -1716, +-670, -1628, 2090, 1230, 892, 2618, -2090, -690, +-878, -2447, 1649, 199, 800, 1291, -1320, 37, +-439, 336, 949, 7, 246, -1643, -824, -287, +-213, 2107, 689, 524, 485, -1460, -404, -624, +-1057, 147, 115, 394, 1382, 1133, 345, 178, +-1266, -1690, -819, -933, 530, 1287, 1187, 1480, +479, -104, -1055, -1393, -1484, -1396, 225, 669, +2304, 2431, 913, 634, -2590, -2684, -1880, -1905, +2130, 2026, 2392, 2591, -1205, -696, -2230, -2437, +209, -695, 1494, 1481, 369, 1678, -398, -234, +-416, -1869, -607, -836, 93, 1377, 1116, 1361, +327, -636, -1113, -1258, -340, 186, 631, 667, +-126, -253, 23, 4, 828, 678, -389, -134, +-1446, -1418, 261, -322, 1758, 2220, 138, 910, +-1530, -2584, -423, -1211, 663, 2175, 549, 1074, +468, -1126, -551, -570, -1106, -142, 200, -90, +1338, 1120, 74, 639, -1110, -1480, 36, -909, +522, 1235, -279, 826, -206, -626, 772, -471, +320, -52, -1304, 40, -636, 569, 1572, 165, +854, -736, -1238, -115, -822, 643, 541, -155, +420, -511, 162, 571, 492, 446, -716, -983, +-1396, -459, 832, 1199, 2006, 457, -400, -1090, +-2154, -354, -258, 608, 1883, 172, 781, 79, +-1266, 15, -830, -610, 498, -345, 517, 945, +202, 629, 9, -1010, -539, -733, -481, 770, +579, 601, 720, -288, -376, -294, -618, -351, +137, 182, 340, 662, -9, -156, 32, -525, +82, 133, -363, 90, -76, -82, 456, 398, +50, -37, -215, -642, 12, 124, -47, 605, +-120, -235, 230, -282, 363, 372, -289, -129, +-487, -600, 235, 501, 503, 907, -42, -779, +-370, -1080, -63, 786, 181, 1116, 142, -616, +-39, -944, -2, 461, 33, 462, -213, -392, +-84, 355, 511, 273, 119, -1224, -513, 36, +-126, 1614, 349, -305, 194, -1417, -75, 343, +-123, 859, -83, -207, 65, -287, 104, 145, +-27, -200, 230, -200, 143, 593, -748, 214, +-264, -763, 1306, -215, 535, 793, -1624, 183, +-624, -810, 1543, -163, 626, 964, -956, 91, +-393, -1165, 262, -47, 30, 1283, 364, 61, +569, -1134, -687, -190, -948, 604, 724, 596, +1004, -99, -338, -934, -599, -229, -19, 937, +-104, 320, 302, -548, 971, -203, -268, -28, +-1463, -107, 10, 465, 1589, 650, 404, -652, +-1199, -1258, -574, 589, 597, 1695, 537, -372, +81, -1661, -250, -16, -291, 1278, -80, 346, +173, -688, 427, -428, 231, 4, -346, 321, +-579, 520, 102, -170, 699, -668, 462, 42, +-424, 413, -868, 75, 28, -35, 1075, -91, +568, -330, -1005, 119, -767, 492, 773, -230, +700, -373, -341, 408, -280, 138, 30, -580, +-33, -30, 181, 672, 313, 182, -14, -680, +-524, -382, 76, 349, 674, 591, -193, 306, +-566, -833, 496, -813, 536, 813, -736, 865, +-286, -304, 900, -577, 97, -382, -754, 77, +223, 701, 640, 772, -477, -646, -447, -1718, +791, 441, 544, 2199, -854, -175, -665, -1963, +819, -45, 840, 1093, -306, 97, -793, 65, +-203, 41, 535, -1066, 851, -350, 103, 1632, +-1213, 656, -614, -1722, 1296, -682, 1151, 1331, +-1087, 463, -1053, -722, 791, -164, 665, 323, +-358, -195, 46, -218, 264, 448, -619, 356, +-208, -489, 1040, -599, 352, 372, -958, 716, +-251, -144, 652, -663, 165, 13, -132, 448, +95, -131, 26, -91, -256, 532, -192, -394, +522, -959, 752, 852, -468, 1134, -1204, -1054, +428, -1071, 1455, 984, -11, 822, -1276, -700, +-197, -588, 901, 428, 375, 398, -175, -225, +-284, -313, -237, 68, 118, 409, 594, -18, +201, -580, -459, 43, -371, 649, 365, -15, +556, -616, -186, -84, -358, 553, 224, 36, +237, -227, -225, -37, 22, -235, 393, 150, +66, 621, -459, -330, -40, -787, 544, 495, +201, 619, -291, -402, -198, -370, 93, 132, +285, 203, 307, 141, -200, -202, -435, -216, +297, 297, 511, 30, -249, -394, -175, 328, +233, 456, 63, -680, -159, -528, 201, 929, +320, 616, -325, -1058, -214, -564, 490, 907, +227, 355, -362, -388, -98, -157, 311, -317, +268, 85, -104, 911, -486, -93, 317, -1271, +807, 184, -403, 1287, -854, -299, 632, -1032, +901, 398, -617, 644, -547, -490, 682, -146, +131, 373, -474, -263, 659, 70, 178, 244, +-1035, -552, 294, 177, 1202, 752, -487, -574, +-724, -684, 483, 597, 333, 651, -123, -308, +38, -751, 34, -54, 2, 799, 12, 474, +-30, -744, 268, -879, 182, 642, -182, 1119, +-270, -525, 248, -1020, 323, 375, 5, 515, +34, -63, -211, 161, -317, -359, 540, -640, +746, 621, -553, 841, -789, -593, 592, -844, +657, 453, -344, 652, 8, -408, 168, -224, +-450, 501, -57, -417, 980, -554, 360, 951, +-1118, 502, -519, -1119, 1115, -346, 617, 866, +-537, 125, -269, -307, -129, 112, 36, -232, +719, -445, 507, 634, -739, 764, -877, -841, +637, -800, 1154, 707, -185, 470, -832, -199, +-56, 73, 236, -504, 473, -577, 541, 1018, +-434, 955, -947, -1166, 289, -1134, 1226, 1006, +143, 974, -972, -607, -315, -537, 643, 154, +453, -45, 4, 155, -318, 664, -275, -326, +186, -1079, 525, 394, 174, 1058, -442, -199, +-269, -896, 422, 7, 481, 753, -329, -60, +-398, -539, 576, 247, 249, 331, -520, -396, +-15, -210, 648, 420, -43, 251, -512, -443, +265, -243, 454, 453, -266, 70, -244, -411, +529, 222, 83, 272, -403, -366, 75, -194, +358, 272, 42, 341, -24, -144, -83, -478, +-119, -4, 253, 426, 297, 243, -7, -253, +-236, -514, -233, 132, 323, 634, 497, -145, +-4, -423, -486, 232, -291, -144, 569, -152, +638, 715, -272, -75, -697, -984, 72, 301, +652, 872, 468, -406, -520, -447, -581, 325, +486, -65, 587, -96, -155, 433, -388, -102, +16, -623, 400, 296, 199, 551, -390, -430, +-92, -179, 570, 344, 113, -184, -585, -194, +54, 418, 595, 134, 58, -557, -343, -146, +-48, 686, 148, 18, 181, -595, 234, 181, +-84, 259, -461, -296, 279, 161, 492, 284, +-232, -542, -86, -88, 224, 725, -242, -198, +42, -698, 495, 514, -79, 456, -237, -637, +-5, -184, 50, 472, 258, 99, 374, -120, +-310, -224, -576, -264, 366, 402, 784, 657, +-177, -586, -558, -895, 14, 692, 254, 787, +355, -483, 320, -495, -600, 29, -594, 214, +809, 346, 859, 29, -691, -415, -753, -289, +510, 223, 630, 472, -2, 116, -453, -450, +-147, -498, 257, 232, 386, 778, 80, 71, +-370, -802, -223, -376, 370, 607, 423, 542, +-138, -323, -335, -434, -105, 15, 426, 82, +432, 210, -373, 335, -449, -227, 318, -760, +546, 169, -66, 1041, -482, -222, -53, -948, +536, 320, 255, 573, -440, -371, -271, -183, +471, 403, 330, -66, -331, -392, -151, 148, +171, 273, 98, -48, 222, -103, 28, -58, +-543, -123, 134, 139, 793, 261, -210, -156, +-594, -132, 221, 8, 412, -234, -18, 259, +-26, 673, -114, -543, -228, -970, 388, 691, +419, 959, -352, -565, -403, -726, 323, 257, +389, 376, -74, 3, -131, 32, -147, -114, +-24, -413, 452, 64, 329, 723, -670, -56, +-324, -744, 804, 102, 307, 393, -583, -32, +-161, 67, 365, -190, 96, -276, -46, 331, +189, 255, -179, -372, -374, -104, 505, 371, +534, -137, -597, -282, -350, 277, 478, 178, +238, -321, -68, -27, -87, 259, -178, -149, +46, -160, 396, 301, 29, 62, -269, -264, +-17, -121, 103, 71, 55, 360, 226, 129, +76, -583, -408, -339, -143, 647, 558, 549, +308, -586, -441, -665, -378, 510, 320, 486, +489, -312, -150, -75, -403, -35, 180, -245, +280, 306, -195, 317, -67, -255, 424, -305, +-43, 18, -633, 307, 288, 59, 775, -137, +-354, 49, -698, -258, 481, -153, 462, 708, +-389, 34, -55, -765, 278, 164, -228, 234, +-17, -39, 406, 456, -135, -387, -218, -870, +132, 832, 56, 791, 127, -955, 119, -422, +-375, 728, -69, 38, 580, -361, 66, 226, +-647, 105, 80, -407, 685, 10, -231, 580, +-488, -191, 475, -554, 199, 391, -430, 263, +-39, -423, 480, 46, 134, 307, -562, -170, +-129, -211, 551, 138, 365, 160, -501, -66, +-380, -102, 367, 105, 290, -246, 50, 24, +-127, 721, -313, -549, -64, -704, 547, 851, +286, 358, -512, -707, -263, -66, 180, 341, +331, -45, 171, -24, -86, -1, -458, 13, +-193, -99, 674, -103, 437, 328, -442, 46, +-719, -317, 281, -89, 782, 137, 33, 326, +-585, -60, -266, -556, 380, 166, 384, 557, +-86, -329, -381, -299, 131, 343, 133, 129, +-143, -415, 181, -88, 272, 679, -383, 10, +-310, -909, 562, 84, 108, 917, -313, -47, +139, -764, 75, -25, -460, 404, 324, 130, +681, 76, -469, -257, -789, -503, 467, 379, +893, 709, -426, -368, -583, -695, 66, 171, +494, 665, 224, -40, -351, -521, -331, -77, +261, 372, 365, 172, -189, -280, -154, -245, +55, 316, 64, 211, 71, -405, 4, 34, +-45, 227, 6, -153, 31, 39, -77, 102, +231, -243, 57, 47, -365, 219, 43, -119, +418, -25, 4, 65, -465, -269, 173, 70, +312, 570, -170, -282, -144, -710, 264, 376, +59, 776, -474, -443, 275, -713, 513, 474, +-394, 589, -539, -545, 595, -375, 375, 585, +-581, 216, 8, -655, 271, -72, -41, 608, +-122, 7, 183, -410, 98, -110, -358, 225, +69, 157, 437, 55, -132, -273, -414, -226, +291, 333, 248, 227, -204, -279, -192, -127, +253, 130, 233, 39, -437, -20, 10, -31, +483, 103, -135, -106, -460, -213, 360, 370, +405, 61, -588, -458, -145, 192, 765, 333, +-172, -337, -635, -186, 336, 386, 463, 149, +-232, -518, -416, 10, 354, 574, 162, -260, +-333, -435, 220, 376, 318, 356, -673, -500, +-36, -253, 941, 516, -209, 261, -843, -494, +135, -390, 1014, 595, -266, 417, -867, -713, +331, -255, 720, 638, -379, 116, -338, -461, +240, -62, 142, 247, -38, 64, 0, 25, +-82, -229, 39, -165, 55, 347, 4, 201, +218, -330, -301, -241, -173, 276, 459, 184, +157, -95, -476, -68, -85, -234, 466, 74, +-29, 552, -257, -270, 141, -544, 4, 330, +-78, 383, 149, -126, 133, -339, -408, -51, +211, 238, 282, 379, -347, -250, -63, -657, +510, 368, -317, 741, -306, -512, 605, -506, +-65, 507, -561, -25, 500, -89, 220, 337, +-586, -339, 141, -394, 467, 602, -302, 328, +-251, -778, 405, 55, 0, 648, -348, -520, +355, -201, 90, 837, -547, -475, 428, -682, +356, 1040, -650, 107, -84, -1225, 767, 632, +-178, 1022, -603, -1247, 256, -467, 464, 1465, +-268, -163, -110, -1215, 61, 727, -115, 555, +150, -932, 368, 260, -401, 804, -415, -969, +649, -264, 166, 1284, -606, -434, 233, -1065, +380, 1083, -571, 391, -80, -1316, 812, 446, +-93, 1059, -910, -1025, 279, -494, 793, 1240, +-353, -96, -442, -1153, 368, 647, 19, 852, +-288, -1004, 389, -301, 103, 954, -406, -176, +-90, -511, 328, 431, 158, -57, -128, -367, +-255, 424, 46, 252, 341, -506, -127, -154, +-180, 390, 137, 107, 208, -185, -271, 64, +-194, -34, 350, -385, 305, 390, -344, 650, +-454, -587, 314, -809, 504, 670, -117, 885, +-506, -661, -100, -749, 592, 668, 71, 459, +-523, -738, 174, 157, 324, 695, -509, -786, +-8, -372, 766, 1221, -306, -161, -746, -1133, +439, 659, 640, 713, -518, -893, -411, -202, +712, 1056, -154, -394, -527, -884, 442, 990, +394, 239, -554, -1076, -212, 638, 476, 520, +-37, -1080, -139, 334, 137, 1036, -103, -1037, +-261, -496, 247, 1305, 388, -84, -275, -1135, +-408, 633, 65, 630, 482, -993, 173, 363, +-575, 843, -247, -1311, 537, -165, 221, 1869, +-476, -685, 78, -1740, 127, 1440, -322, 986, +308, -1683, 390, 252, -719, 1226, -210, -1296, +922, -170, -206, 1749, -855, -892, 763, -1482, +247, 1856, -900, 396, 316, -2038, 701, 1129, +-683, 1335, -356, -2256, 827, -5, -248, 2573, +-382, -1301, 395, -1686, -194, 1698, -174, 487, +595, -1068, -314, 416, -765, 49, 820, -573, +490, 691, -947, 417, -186, -874, 678, -37, +-163, 522, -3, -105, 87, 170, -621, -97, +162, -549, 838, 497, -415, 632, -760, -1022, +608, 12, 210, 1268, -512, -901, 183, -1000, +378, 1664, -519, 483, -301, -1777, 510, -33, +272, 1425, -335, 25, -396, -797, 43, -388, +455, 419, 75, 1028, -493, -492, 20, -1392, +162, 1082, -215, 1299, 127, -1796, 481, -482, +-676, 2248, -512, -737, 919, -1796, 222, 1871, +-974, 456, 174, -1949, 672, 1156, -691, 1057, +-293, -2118, 933, 319, -158, 2358, -1009, -1562, +527, -1614, 440, 2144, -588, 480, 84, -1854, +488, 777, -783, 971, -269, -1607, 909, 295, +81, 1739, -725, -1096, -119, -1170, -63, 1309, +273, 225, 951, -575, -881, 541, -1396, -379, +1039, -774, 1386, 1114, -1231, 602, -835, -1041, +967, -276, -232, 571, -507, -51, 1002, 193, +4, 516, -1678, -942, 324, -727, 1634, 1518, +-473, 684, -1408, -1507, 244, -300, 994, 1021, +-206, 24, -759, -294, 55, 216, 558, -201, +-193, -174, -618, 361, 157, 97, 595, -151, +-182, 266, -768, -274, -50, -601, 785, 759, +136, 1058, -961, -1149, -234, -1176, 801, 1337, +13, 1045, -564, -1077, -21, -578, -1, 607, +-18, 30, 451, 108, -443, 572, -841, -750, +854, -933, 705, 1402, -1413, 910, -394, -1556, +1445, -543, -256, 1396, -1381, 137, 866, -829, +546, 134, -1317, 368, 221, -5, 1164, -226, +-1053, -162, -912, 620, 1262, 311, 372, -1180, +-1342, -118, -90, 1691, 854, -147, -254, -1725, +-392, 444, 105, 1473, -253, -464, -23, -1097, +452, 619, -332, 830, -547, -793, 148, -602, +340, 1087, -13, 780, -330, -1426, -610, -1109, +272, 1940, 890, 1499, -640, -2173, -1063, -1728, +632, 2312, 682, 1779, -615, -2225, -511, -1333, +259, 2049, -39, 643, 184, -1750, -97, 398, +-841, 1371, 347, -1171, 996, -893, -1108, 1657, +-1153, 472, 1624, -1525, 844, 4, -2284, 1076, +-730, -461, 2435, -232, 348, 1029, -2673, -674, +-231, -1323, 2394, 1376, -140, 1639, -2262, -1644, +329, -1771, 1533, 1609, -760, 1929, -768, -1330, +648, -1726, -362, 966, -721, 1364, 1223, -536, +357, -530, -2103, 83, -380, -334, 2344, 386, +201, 1222, -2337, -515, -669, -2002, 1786, 743, +938, 2398, -1445, -669, -1467, -2494, 1018, 913, +1322, 2250, -1215, -1348, -954, -1604, 1290, 2157, +-93, 905, -1730, -3211, 977, 160, 1646, 4118, +-1980, -1234, -1437, -4240, 2095, 2253, 512, 3504, +-1860, -2799, 324, -1891, 708, 2983, -1374, -96, +455, -2515, 1504, 1911, -1627, 1759, -1382, -2748, +1837, -1072, 645, 2859, -1964, 779, 86, -2374, +1320, -653, -1002, 1842, -969, 705, 1239, -1417, +628, -631, -1533, 1499, -927, 396, 1321, -1868, +898, 272, -1018, 2319, -1401, -957, 497, -2491, +1227, 1588, -166, 2471, -1275, -1770, -385, -2226, +939, 1671, 316, 2081, -793, -1297, -378, -1877, +299, 847, -237, 1962, 237, -386, 367, -2153, +-1177, 331, -803, 2230, 2091, -187, 432, -2072, +-3179, -38, -78, 1884, 3633, 710, -849, -1808, +-3911, -1423, 1476, 1943, 3404, 2120, -2248, -1960, +-3019, -2597, 2545, 2048, 2174, 2750, -2875, -1789, +-1759, -2525, 2635, 1277, 1298, 2326, -2726, -606, +-1196, -2030, 2383, 59, 833, 1926, -2431, 381, +-621, -1996, 2137, -322, -108, 2168, -2009, 23, +516, -2130, 1552, 459, -1378, 1886, -1104, -711, +1718, -1304, 206, 835, -2105, 435, 292, -582, +2061, 813, -1106, 91, -2026, -2072, 1308, 658, +1531, 3252, -1455, -1418, -1380, -3826, 1016, 2120, +1020, 3698, -822, -2230, -1081, -2895, 420, 1826, +848, 1965, -496, -947, -869, -1134, 390, 88, +531, 698, -582, 618, -613, -491, 580, -929, +354, 511, -678, 1010, -701, -500, 585, -678, +775, 270, -709, 325, -1280, 298, 648, 92, +1409, -949, -953, -451, -1576, 1650, 927, 831, +1205, -2021, -1022, -1164, -1028, 2161, 615, 1401, +700, -1821, -405, -1402, -763, 1293, -373, 1180, +981, -612, 789, -544, -1629, 15, -1507, -233, +2171, 548, 1665, 965, -2887, -746, -1638, -1421, +2901, 742, 935, 1530, -2661, -402, -187, -1230, +1712, -46, -1086, 791, -627, 527, 1952, -187, +-655, -815, -3028, -296, 1557, 864, 3576, 783, +-2435, -546, -4020, -1074, 2538, -129, 4076, 1467, +-2717, 1079, -4105, -1855, 2554, -1757, 3495, 1939, +-2634, 2183, -2652, -1401, 2417, -2215, 1127, 387, +-2395, 1857, 488, 1076, 1843, -1113, -2086, -2387, +-1613, 159, 3019, 3099, 1305, 1179, -3579, -3027, +-1500, -2514, 3293, 2354, 1708, 3557, -2849, -1250, +-2209, -3831, 2093, 84, 1994, 3420, -1286, 925, +-1822, -2461, 422, -1390, 1030, 1411, 144, 1346, +-350, -554, -975, -936, -62, 314, 1291, 576, +-229, -740, -1770, -365, 1015, 1661, 1813, 571, +-2417, -2585, -1832, -1107, 3437, 3105, 1679, 1975, +-4235, -2965, -1765, -2753, 4075, 2168, 1747, 3376, +-3421, -974, -2059, -3543, 2130, -149, 2151, 3374, +-922, 846, -2311, -2883, -424, -889, 2177, 2342, +1269, 501, -2082, -1894, -2031, 94, 1528, 1614, +2592, -252, -1200, -1457, -3195, -263, 486, 1448, +3764, 1488, -272, -1451, -4088, -2744, -221, 1201, +3925, 3637, 340, -545, -3344, -3677, -705, -302, +2179, 2877, 919, 1067, -1218, -1316, -1142, -1307, +167, -585, 1135, 1135, 278, 2206, -1242, -485, +-463, -3083, 1140, -243, 87, 3132, -1025, 817, +-79, -2548, 863, -894, 71, 1807, -786, 508, +-623, -1225, 498, 117, 1115, 1163, -224, -621, +-1611, -1337, -395, 600, 1381, 1558, 1125, 172, +-887, -1506, -1891, -1282, -267, 935, 2151, 2270, +1418, 483, -1976, -2896, -2766, -2170, 1245, 2988, +3525, 3474, -482, -2275, -3783, -3904, -339, 1014, +3127, 3376, 726, 436, -2130, -2046, -773, -1527, +598, 480, 374, 1913, 755, 895, -84, -1367, +-1814, -1813, -415, 331, 2261, 2035, 555, 1045, +-2179, -1698, -938, -2270, 1618, 1053, 1153, 3234, +-964, -442, -1604, -3701, 229, 295, 1789, 3335, +214, -406, -1798, -2063, -614, 518, 1131, 235, +859, -370, -374, 1698, -972, 37, -709, -3176, +750, 410, 1459, 3826, -490, -746, -1874, -3384, +45, 880, 1636, 2086, -150, -826, -851, -311, +547, 891, -412, -1443, -1544, -1054, 1437, 2555, +2816, 1589, -2346, -2875, -4000, -2144, 2493, 2374, +4473, 2512, -2129, -1300, -4197, -2363, 1172, 85, +2942, 1713, -204, 831, -1225, -678, -738, -1042, +-640, -535, 1129, 670, 1959, 1564, -1108, 141, +-2853, -2194, 861, -886, 2702, 2384, -586, 1171, +-2165, -2143, 497, -653, 1156, 1404, -799, -242, +-299, -513, 1191, 1197, -295, -207, -1719, -1829, +195, 697, 2116, 1900, 110, -886, -2307, -1418, +-637, 1051, 2033, 514, 742, -1178, -1366, 428, +-607, 1441, 295, -1047, 162, -1764, 469, 1246, +436, 1915, -1041, -884, -972, -1797, 1000, 327, +1034, 1300, -574, 76, -724, -361, -287, -31, +137, -814, 887, -333, 407, 1690, -1212, 1056, +-837, -1932, 1054, -1703, 714, 1283, -650, 2128, +-313, 124, 105, -2221, -298, -1633, 87, 1943, +774, 2627, -62, -1321, -1083, -2666, -241, 543, +1165, 1905, 154, 64, -983, -628, 46, -430, +864, -286, -762, 312, -891, 590, 1387, 74, +1023, -77, -1654, -472, -1378, -841, 1221, 588, +1507, 1695, -106, -245, -1604, -2014, -1158, -328, +1159, 1614, 2061, 822, -414, -585, -2319, -901, +-448, -649, 1617, 509, 1092, 1537, -384, 374, +-1424, -1851, -872, -1331, 1132, 1575, 1704, 1967, +-529, -846, -2079, -2080, -3, 104, 1702, 1620, +417, 510, -1335, -777, -446, -997, 960, 161, +314, 1246, -1011, 54, -253, -1182, 1318, 8, +191, 956, -1384, 15, -629, -838, 1288, -176, +967, 819, -735, 548, -1237, -795, -67, -1053, +1134, 758, 712, 1461, -624, -587, -1198, -1553, +77, 179, 1115, 1536, 320, 233, -804, -1360, +-293, -531, 304, 1135, -85, 754, 13, -1035, +537, -792, -85, 1105, -782, 572, -82, -1124, +489, -67, 323, 780, 149, -360, -322, -110, +-1094, 547, 89, -645, 1796, -447, 430, 1184, +-2100, 240, -1072, -1335, 1948, -65, 1422, 1137, +-1360, 71, -1536, -739, 788, -239, 1123, 348, +-402, 497, -252, -13, 72, -813, -656, -234, +78, 1263, 1406, 266, -310, -1677, -1667, -38, +504, 1843, 1530, -313, -755, -1653, -1070, 684, +922, 1152, 518, -1026, -971, -390, 16, 1152, +793, -307, -393, -1149, -408, 883, 543, 852, +56, -1150, -668, -269, 357, 966, 591, -291, +-474, -677, -533, 806, 429, 340, 395, -985, +-135, -271, -287, 874, -188, 420, 196, -555, +394, -545, -2, 6, -519, 560, -81, 489, +437, -331, 169, -782, -194, -143, -288, 750, +52, 652, 338, -372, -14, -1026, -335, -199, +183, 1072, 296, 743, -389, -827, -245, -1020, +515, 342, 394, 934, -536, 95, -562, -570, +398, -207, 735, -138, -154, 62, -669, 938, +-34, 38, 260, -1399, 151, -67, 540, 1314, +-195, -20, -1182, -835, -29, 191, 1604, 131, +406, -367, -1448, 444, -746, 425, 747, -719, +1050, -433, 181, 703, -911, 370, -1059, -667, +649, -259, 1434, 743, -223, 47, -1079, -971, +-101, 102, 270, 1282, 148, -228, 813, -1532, +57, 288, -1528, 1452, -306, -230, 1644, -1167, +604, 85, -1176, 749, -498, 43, 333, -476, +175, -80, 536, 428, 345, -106, -1039, -562, +-721, 359, 1264, 662, 717, -543, -1032, -731, +-213, 557, 682, 630, -413, -460, -287, -438, +943, 271, 109, 216, -976, -175, -50, -86, +615, 117, 135, 38, 106, -138, -94, -91, +-699, 92, 53, 17, 1068, 91, 180, 175, +-1035, -460, -301, -555, 913, 790, 347, 972, +-723, -1026, -138, -1265, 724, 934, -11, 1132, +-722, -529, 229, -615, 708, -153, -101, -219, +-394, 717, -41, 1026, -51, -963, 261, -1731, +685, 856, -213, 1931, -992, -629, -92, -1508, +1233, 209, 565, 625, -922, 70, -814, 292, +546, -180, 843, -987, -105, -10, -273, 1192, +-35, 215, -351, -962, -120, -370, 1083, 298, +615, 404, -1257, 309, -964, -337, 1080, -755, +1229, 134, -365, 859, -961, -47, -321, -672, +552, -32, 856, 213, 188, 46, -892, 223, +-555, -264, 656, -498, 898, 505, -141, 437, +-802, -792, 97, -333, 652, 1010, -189, 127, +-320, -1268, 734, 69, 209, 1319, -1080, -365, +27, -1206, 1185, 573, 37, 804, -559, -720, +137, -393, -251, 657, -174, -16, 1344, -605, +485, 339, -1870, 317, -668, -559, 1995, -76, +1070, 560, -1442, -105, -1070, -634, 890, 108, +1077, 622, -133, -80, -683, -648, -1, -93, +360, 576, 103, 155, 55, -499, 293, -207, +-182, 241, -358, 162, 300, -3, 538, -242, +-58, -234, -288, 348, 194, 205, 147, -545, +-79, -68, 100, 527, 437, -153, -48, -395, +-430, 145, -88, 80, 682, -73, 537, 265, +-485, -227, -506, -622, 260, 476, 744, 686, +245, -626, -376, -633, -466, 500, 219, 362, +709, -337, 199, -83, -441, 130, -155, -286, +300, -101, 220, 464, 185, 147, 259, -514, +-197, -488, -471, 376, 321, 795, 1028, -251, +-114, -1099, -1068, 25, 232, 1150, 1196, 60, +-136, -1048, -826, -198, 603, 700, 639, 156, +-610, -268, -164, -203, 862, -347, 192, 291, +-532, 743, -128, -532, 457, -1026, 480, 734, +-95, 971, -433, -1036, 390, -718, 474, 1135, +-444, 236, 112, -1193, 1006, 210, -519, 890, +-955, -518, 1218, -451, 802, 390, -1168, -177, +-48, -71, 1272, 791, -638, -543, -599, -1344, +1518, 1003, 345, 1544, -1590, -1261, 240, -1528, +1564, 1052, -313, 1126, -676, -609, 587, -692, +75, 67, -530, 121, 762, 172, 980, 349, +-829, -293, -990, -672, 923, 103, 1344, 656, +-373, 65, -929, -580, 127, -125, 619, 331, +370, -214, 237, -171, -203, 660, -603, -25, +278, -1038, 1027, -122, 232, 998, -534, 509, +-261, -808, 170, -1056, 553, 363, 641, 1329, +-165, 15, -891, -1375, 76, -302, 1169, 928, +488, 236, -656, -267, -449, -123, 417, -494, +705, -124, 258, 902, -392, 246, -220, -1051, +359, -331, 366, 780, 97, 188, 22, -390, +-10, -117, 16, -130, 344, 60, 295, 410, +-226, -257, 96, -546, 565, 496, -168, 385, +-464, -872, 681, -120, 656, 1028, -639, -319, +-229, -1044, 774, 678, 136, 718, -271, -1127, +488, -198, 212, 1327, -647, -489, 323, -1375, +996, 936, -272, 1106, -638, -1181, 416, -738, +592, 954, -168, 295, 57, -604, 302, -53, +-74, 192, -81, -183, 365, -24, 397, 268, +39, -40, -336, -444, -111, -37, 644, 416, +454, 84, -274, -333, -299, -288, 198, 115, +410, 347, 470, 106, -66, -444, -486, -429, +91, 399, 720, 597, 317, -394, -300, -695, +-329, 308, 144, 422, 730, -234, 417, -44, +-668, 51, -362, -478, 877, 48, 647, 809, +-487, -205, -472, -897, 464, 133, 616, 634, +111, -47, -503, -297, -197, -127, 748, -170, +633, 216, -525, 372, -529, -296, 611, -415, +804, 218, -196, 193, -599, -210, 135, 8, +814, 186, 121, -196, -510, -383, 53, 218, +589, 493, 4, -194, -165, -540, 354, -29, +100, 326, -155, 232, 308, -38, 200, -557, +-223, -259, 241, 741, 333, 230, -357, -802, +60, -73, 777, 688, -246, -316, -502, -640, +678, 686, 472, 509, -538, -980, 69, -405, +388, 803, -41, 263, 212, -299, 198, -319, +-508, -390, 178, 347, 888, 844, -128, -418, +-651, -993, 293, 336, 549, 701, 87, -296, +78, -233, -312, 238, -317, -336, 798, -334, +754, 654, -780, 432, -702, -790, 868, -570, +808, 576, -401, 541, -451, -251, 203, -448, +336, -166, 301, 214, 77, 439, -362, -102, +-116, -588, 496, 8, 421, 495, -226, -5, +-335, -475, 216, -3, 525, 469, 38, -116, +-247, -524, -48, 160, 342, 402, 201, -146, +-77, -175, -75, -87, -10, -175, 332, 292, +327, 469, -359, -491, -301, -667, 689, 467, +453, 582, -616, -275, -232, -440, 628, 5, +239, 112, -203, 121, 21, 196, -111, -202, +40, -455, 656, 69, 104, 518, -746, 83, +34, -482, 847, -344, 101, 394, -408, 467, +-55, -433, 57, -524, 266, 501, 577, 402, +-297, -658, -816, -270, 513, 728, 1045, 79, +-432, -767, -655, 101, 364, 585, 385, -341, +5, -306, 140, 483, -165, -63, -306, -596, +416, 261, 461, 543, -267, -242, -265, -497, +248, -5, 148, 380, 28, 240, 207, -225, +-70, -473, -282, 30, 201, 546, 414, 26, +-66, -469, -238, -32, 80, 220, 190, -50, +12, -53, 117, 156, 153, -59, -209, -299, +-121, -1, 345, 349, 306, 69, -228, -327, +-217, -148, 70, 121, 341, 159, 228, 99, +-248, -184, -308, -279, 297, 164, 481, 223, +-181, -139, -366, 7, 224, -86, 321, -227, +-60, 274, -189, 252, 89, -348, 239, -188, +-39, 216, -195, 38, 276, -20, 277, 87, +-488, -232, -78, -252, 839, 453, -77, 346, +-953, -686, 425, -378, 961, 751, -581, 358, +-634, -706, 772, -374, 165, 533, -491, 264, +300, -133, 259, -287, -412, -418, 4, 532, +443, 699, 6, -854, -250, -626, -20, 911, +129, 324, 184, -666, 27, -179, -197, 350, +36, 149, 317, -251, -127, -52, -292, 78, +447, -42, 240, 109, -530, 63, -174, -281, +526, -101, 293, 386, -308, 103, -278, -407, +26, -135, 332, 231, 340, 208, -218, 53, +-399, -392, -89, -291, 486, 460, 545, 436, +-484, -385, -723, -639, 425, 392, 756, 589, +-229, -484, -471, -236, 154, 412, -35, -225, +185, -209, 469, 442, -359, -8, -707, -293, +523, -137, 877, 117, -743, 459, -587, -304, +813, -428, 287, 457, -650, 98, -129, -466, +683, 127, -30, 527, -441, -234, -84, -732, +324, 183, 366, 1089, -300, -243, -413, -1277, +142, 287, 541, 1091, -13, -121, -452, -838, +-69, -67, 211, 562, 272, 61, 81, -161, +-377, -76, -389, -252, 534, 143, 623, 546, +-634, -398, -614, -577, 615, 620, 523, 415, +-474, -716, -290, -314, 202, 736, 162, 257, +41, -669, -36, -233, -282, 365, 77, 397, +420, -80, -257, -634, -323, -83, 462, 664, +87, 303, -599, -763, 249, -337, 586, 802, +-486, 152, -474, -763, 547, 155, 432, 559, +-583, -369, -334, -379, 502, 371, 284, 401, +-473, -378, -115, -471, 339, 345, -116, 539, +-33, -366, 85, -421, -41, 243, -184, 246, +63, -23, 309, -161, -118, -193, -408, 177, +162, 325, 431, -378, -304, -173, -236, 377, +340, 41, -95, -311, -271, -40, 299, 301, +224, 45, -533, -306, -80, -41, 386, 206, +165, 166, -242, -205, -453, -307, 344, 299, +355, 281, -283, -354, -271, -199, 275, 334, +-50, 25, -204, -209, 384, 49, -88, 165, +-451, -206, 47, -112, 627, 331, -193, 114, +-713, -520, 385, -92, 495, 705, -525, -121, +-156, -614, 327, 275, -89, 309, -97, -290, +65, 40, -19, 182, -189, -327, 111, -66, +337, 523, -441, -43, -314, -682, 462, 235, +385, 658, -556, -452, -577, -298, 636, 200, +555, 203, -625, 167, -581, -487, 445, -301, +582, 751, -340, 341, -668, -969, 343, -340, +408, 1078, -266, 239, -234, -968, 157, -141, +-158, 650, 131, 40, 110, -233, -101, 142, +-405, -403, 163, -170, 541, 926, -383, -1, +-498, -1023, 344, 47, 378, 811, -394, -10, +-225, -405, 298, -44, -81, -252, -143, 405, +189, 610, -195, -772, 1, -570, 27, 869, +22, 365, -260, -872, 244, 19, 171, 748, +-614, -585, 50, -210, 605, 742, -367, -319, +-337, -438, 256, 459, 130, 135, -481, -475, +426, 143, 134, 480, -653, -578, 35, -185, +472, 882, -14, -529, -406, -471, 85, 870, +-234, -167, 262, -781, 342, 671, -437, 362, +-431, -845, 356, 200, 271, 592, -215, -646, +-153, -92, 73, 929, -348, -708, 323, -633, +330, 1238, -487, -86, -285, -1212, 412, 823, +-80, 739, -148, -1440, 285, 196, -217, 1454, +-467, -1141, 283, -722, 530, 1517, -391, -367, +-453, -1071, 163, 1073, 321, 357, -98, -1306, +-107, 292, -223, 1087, 48, -655, 289, -584, +-215, 782, -257, -228, 330, -487, -58, 1009, +-253, -229, -27, -1223, 243, 877, -102, 886, +-69, -1248, -29, -89, -168, 1139, 15, -732, +349, -752, -34, 1383, -577, 171, 26, -1584, +383, 336, 217, 1375, -369, -742, -469, -669, +231, 697, 560, -21, -210, -366, -693, 417, +277, -6, 568, -487, -539, 324, -333, 244, +682, -408, -173, 19, -518, 450, 358, -230, +158, -466, -483, 351, 268, 498, 310, -435, +-710, -432, -64, 458, 704, 241, -28, -377, +-835, 29, 307, 189, 418, -200, -562, -87, +256, 438, 415, -17, -867, -762, -119, 381, +987, 867, -91, -861, -980, -546, 284, 1045, +524, 46, -334, -745, -105, 333, 169, 74, +-262, -376, -79, 597, 560, 393, -463, -1406, +-305, -117, 625, 2065, -73, -638, -606, -1851, +195, 1278, 616, 859, -493, -1379, -304, 413, +430, 932, -179, -1344, -115, -305, 293, 1787, +-63, -298, -524, -1731, 273, 910, 248, 1151, +-190, -1554, 125, 136, -210, 1687, -421, -1510, +499, -1219, 622, 2394, -767, 445, -495, -2654, +608, 704, 48, 1912, -91, -1626, 296, -327, +-633, 1780, -604, -1324, 1256, -1089, 434, 2465, +-1517, -249, 58, -2598, 980, 1815, -371, 1539, +-302, -2735, 563, 147, -500, 2606, -381, -1536, +915, -1583, -171, 2085, -773, 45, 662, -1229, +87, 863, -826, -221, 369, -673, 871, 1118, +-915, 14, -420, -1155, 845, 635, -213, 379, +-154, -752, 305, 719, -317, 204, -373, -1441, +731, 788, 7, 1295, -622, -1412, 162, -705, +444, 1740, -583, -236, -53, -1433, 622, 963, +-97, 682, -736, -916, 59, -153, 758, 415, +-79, 6, -465, 447, -166, -558, 304, -936, +203, 1507, -118, 648, -57, -2091, -140, 197, +-259, 1897, 496, -901, 222, -1211, -610, 1366, +-286, 77, 722, -1138, -55, 1081, -564, 101, +297, -1541, 388, 1252, -503, 1085, -221, -2084, +672, -157, -126, 2032, -444, -456, 290, -1450, +75, 720, -441, 519, 335, -516, 319, 428, +-597, 13, -122, -965, 420, 497, -122, 909, +-21, -639, 364, -228, -675, 203, -391, -528, +1257, 543, 246, 1107, -1533, -1206, 85, -1193, +1274, 1432, -443, 915, -668, -1193, 584, -348, +2, 750, -863, -386, 677, -240, 774, 1116, +-975, -138, -722, -1651, 920, 518, 773, 1633, +-859, -614, -620, -1181, 641, 542, 576, 461, +-634, -178, -381, 113, 527, -162, 116, -374, +-282, 491, -247, 243, 10, -684, 528, 317, +10, 606, -860, -945, 183, -218, 797, 1368, +-302, -291, -489, -1301, 392, 687, -117, 906, +-95, -930, 493, -111, -319, 852, -624, -752, +679, -410, 348, 1406, -1053, -215, 240, -1482, +957, 714, -940, 1011, -383, -767, 1112, -127, +-305, 109, -764, -377, 770, 731, 256, 502, +-1150, -1434, 613, -177, 829, 1830, -1033, -486, +-335, -1554, 740, 934, 75, 1080, -412, -1039, +-17, -616, -46, 825, 33, 489, 360, -484, +-275, -718, -283, 474, 479, 985, -186, -819, +-375, -953, 822, 1363, 22, 676, -1532, -1993, +748, -32, 1570, 2452, -1369, -763, -1265, -2478, +1444, 1508, 696, 2100, -1195, -1929, -121, -1532, +505, 2211, -191, 794, 259, -2201, 53, -125, +-585, 2037, 211, -233, 678, -1891, -761, 534, +-414, 1522, 1332, -434, -193, -1104, -1729, 121, +461, 811, 2010, 168, -710, -438, -2003, -291, +394, -119, 2003, 461, 8, 843, -1964, -776, +-296, -1439, 1798, 1115, 544, 2098, -1705, -1757, +-486, -2260, 1429, 2354, 289, 1840, -1073, -2320, +-337, -1228, 769, 1786, 131, 653, -328, -916, +-46, -172, -252, 64, -65, -250, 765, 660, +344, 572, -1309, -1018, -514, -790, 1660, 1155, +498, 742, -1665, -943, -252, -640, 1258, 909, +-363, 242, -551, -924, 907, 379, -389, 845, +-1255, -640, 1075, -921, 1128, 731, -1476, 867, +-387, -448, 1322, -580, -614, -153, -816, 254, +1737, 700, -23, 265, -2517, -1033, 967, -822, +2447, 1263, -1706, 1022, -1831, -1075, 1962, -988, +979, 721, -2162, 895, -177, -590, 2219, -743, +-410, 1060, -2114, 235, 570, -1599, 1975, 251, +-491, 2166, -1574, -555, 199, -2644, 996, 890, +43, 2712, -306, -1081, -447, -2390, -287, 1262, +754, 1692, 352, -1221, -849, -896, -189, 989, +732, 208, -224, -393, -404, 90, 676, -284, +-100, 32, -1068, 850, 969, -308, 919, -1107, +-1693, 515, -669, 1155, 2195, -509, 278, -1098, +-2554, 492, 101, 1030, 2277, -626, -162, -824, +-1814, 903, -88, 506, 1372, -1094, 288, -191, +-876, 1096, -478, 144, 559, -1013, 574, -220, +-488, 894, -562, 263, 546, -505, 317, -409, +-606, 105, -235, 645, 481, 244, 221, -879, +-261, -398, -416, 1027, -146, 466, 838, -1046, +510, -456, -1339, 978, -696, 378, 1890, -726, +357, -158, -1940, 132, -43, 99, 1681, 683, +-320, -235, -1379, -1443, 638, 397, 777, 2312, +-669, -833, -412, -2817, 421, 1301, 401, 2868, +-227, -1384, -494, -2833, -87, 1259, 964, 2832, +21, -1042, -1224, -2775, 71, 787, 1260, 2637, +-183, -366, -1228, -2522, 179, 7, 991, 2283, +1, 339, -984, -1805, -302, -730, 1139, 1276, +612, 1037, -1634, -733, -496, -1070, 1907, 237, +322, 787, -2208, 221, 385, -240, 1833, -530, +-1020, -429, -1252, 604, 1552, 1195, 363, -531, +-1873, -1838, 475, 462, 1710, 2079, -1161, -153, +-1052, -2047, 1346, -224, 77, 1843, -961, 534, +736, -1390, 505, -802, -1528, 897, 130, 944, +1775, -459, -462, -731, -1819, -2, 446, 245, +1546, 533, -240, 400, -1227, -1036, -71, -892, +731, 1283, 382, 1136, -285, -1124, -411, -969, +-411, 548, 339, 404, 1226, 459, -218, 247, +-2142, -1337, 231, -905, 2746, 1812, -480, 1402, +-2826, -1636, 717, -1555, 2226, 761, -986, 1417, +-1134, 480, 1179, -967, -260, -1672, -1237, 351, +1396, 2290, 1394, 497, -2045, -2217, -1780, -1436, +2213, 1681, 2276, 2157, -2120, -802, -2698, -2512, +1841, -30, 2679, 2341, -1484, 775, -2420, -1900, +1202, -1194, 1738, 1454, -859, 1203, -1137, -1210, +544, -789, 708, 1253, 4, 198, -986, -1590, +-421, 281, 1662, 2216, 834, -514, -2686, -2801, +-1227, 252, 3671, 3196, 1483, 442, -4361, -3161, +-1805, -1399, 4635, 2594, 1939, 2419, -4270, -1634, +-2226, -3233, 3688, 565, 2298, 3679, -2771, 316, +-2396, -3800, 1881, -589, 2233, 3598, -913, 307, +-1994, -3282, -209, 418, 1757, 2882, 1233, -1075, +-1496, -2377, -2315, 1098, 1188, 1842, 3238, -262, +-823, -1248, -3968, -1169, 394, 463, 4264, 2724, +147, 582, -4078, -3870, -826, -1650, 3488, 4145, +1439, 2501, -2662, -3460, -1993, -2718, 1892, 1914, +2037, 2366, -1224, -160, -1786, -1448, 812, -1257, +1037, 304, -423, 1959, -114, 656, -93, -1859, +-704, -1248, 758, 1377, 1356, 1379, -1713, -1038, +-1697, -1093, 2698, 1112, 1729, 727, -3398, -1621, +-1762, -597, 3532, 2269, 1843, 869, -3141, -2579, +-1873, -1440, 2096, 2149, 1713, 2045, -554, -859, +-1422, -2402, -1011, -1008, 859, 2404, 2245, 2804, +-109, -2073, -3023, -3659, -521, 1258, 2894, 3407, +1116, -142, -2230, -2194, -1590, -1051, 1161, 615, +1890, 1960, -2, 848, -2195, -2399, -922, -1810, +2386, 2375, 1366, 2072, -2240, -1883, -1465, -1661, +1762, 948, 1100, 847, -800, 295, -532, 50, +-421, -1577, -223, -679, 1448, 2339, 1167, 1050, +-2206, -2215, -2004, -1310, 2298, 1314, 2478, 1367, +-1660, 173, -2530, -1276, 660, -1633, 1925, 949, +411, 2524, -818, -308, -1347, -2616, -226, -398, +1603, 1887, 909, 833, -1237, -447, -969, -1059, +395, -878, 276, 692, 573, 1631, 984, 426, +-1473, -1833, -2222, -1899, 1769, 1511, 3303, 3252, +-1636, -826, -3769, -4032, 1008, 49, 3591, 4008, +-199, 467, -2921, -3000, -382, -596, 1620, 1219, +741, 328, -79, 875, -927, 253, -1243, -2770, +743, -840, 2206, 3871, -463, 1271, -2582, -4003, +277, -1224, 2184, 3176, -72, 681, -1599, -1722, +301, 5, 880, 530, -816, -889, -500, 215, +1513, 1499, 603, -418, -2293, -1396, -960, 50, +2743, 742, 1164, 443, -2500, 119, -1075, -492, +1604, -834, 599, -58, -404, 1042, 166, 1079, +-674, -718, -900, -1987, 1220, -32, 1182, 2317, +-1056, 812, -949, -1811, 360, -1168, 326, 572, +271, 1000, 463, 655, -445, -111, -1182, -1366, +160, -1163, 1425, 1258, 515, 2210, -1344, -223, +-935, -2645, 881, -1409, 886, 2522, -400, 2764, +-279, -1905, 72, -3227, -578, 1091, 25, 2559, +1094, -310, 152, -1166, -1117, -169, -259, -235, +552, 219, 122, 1074, 193, 42, 360, -1109, +-679, -294, -979, 514, 443, 237, 1562, 316, +372, 150, -1719, -842, -1444, -806, 1278, 947, +2312, 1220, -484, -538, -2521, -1103, -353, -223, +1996, 535, 786, 902, -878, 272, -760, -1160, +-213, -1050, 218, 911, 992, 1646, 460, -478, +-1310, -1810, -891, 110, 1254, 1458, 850, 246, +-1081, -922, -489, -581, 1111, 530, 30, 852, +-1384, -404, 244, -989, 1667, 319, -65, 1133, +-1775, -221, -411, -1214, 1465, 38, 947, 1124, +-889, 323, -1013, -904, -47, -695, 725, 577, +784, 868, 47, 6, -1334, -954, -804, -777, +1501, 1223, 1214, 1391, -1315, -1628, -1245, -1587, +1126, 1927, 782, 1476, -983, -2020, -121, -1156, +865, 1938, -251, 503, -884, -1404, 213, 169, +937, 577, 136, -679, -785, 381, -779, 810, +540, -1118, 1257, -602, 15, 1534, -1610, 121, +-607, -1589, 1655, 449, 1120, 1365, -1370, -836, +-1507, -1030, 980, 861, 1567, 714, -524, -517, +-1295, -445, 122, 8, 710, 37, 181, 647, +77, 345, -451, -1097, -705, -703, 552, 1249, +1081, 818, -550, -959, -1066, -707, 496, 405, +740, 355, -477, 161, -243, 140, 510, -518, +-123, -637, -677, 595, 344, 892, 809, -395, +-327, -800, -745, -41, 88, 557, 629, 363, +22, -287, -319, -345, -6, 75, 17, 35, +-185, -37, 201, 380, 345, 214, -140, -700, +-473, -425, 117, 586, 172, 631, 73, -100, +248, -602, -79, -645, -687, 325, -157, 1209, +1099, 255, 356, -1287, -1205, -1062, -406, 842, +1001, 1803, 324, -60, -802, -2185, 31, -747, +734, 2054, -477, 1187, -872, -1433, 786, -987, +1166, 456, -891, 280, -1239, 582, 591, 544, +1051, -1312, -75, -1070, -645, 1518, -306, 1070, +124, -1245, 370, -529, 246, 671, -173, -219, +-93, -107, -402, 806, -257, -233, 853, -1003, +695, 318, -901, 817, -922, -410, 509, -313, +852, 534, 1, -85, -377, -862, -357, 224, +-265, 1234, 267, -3, 819, -1469, 276, -463, +-1091, 1424, -980, 858, 1038, -1006, 1418, -980, +-712, 338, -1305, 735, 288, 433, 691, -400, +39, -937, 198, 200, -264, 930, -865, -211, +346, -507, 1054, 426, -389, -40, -701, -830, +355, 593, 200, 1035, -367, -817, 150, -1012, +463, 758, -250, 736, -439, -604, 55, -268, +309, 427, 265, -105, -137, -368, -406, 167, +-61, 467, 379, 100, 77, -612, -238, -564, +135, 725, 104, 896, -410, -661, -246, -891, +717, 435, 483, 549, -761, -263, -658, 107, +433, 219, 673, -777, 33, -446, -242, 1223, +-433, 865, -580, -1296, 669, -1368, 1285, 1124, +-363, 1618, -1768, -770, -250, -1523, 1793, 436, +836, 1092, -1308, -302, -1115, -417, 621, 347, +854, -277, -20, -449, -104, 688, -281, 588, +-704, -766, 34, -679, 1382, 574, 454, 686, +-1571, -297, -931, -582, 1215, 70, 1158, 405, +-540, 22, -1023, -224, -106, 104, 625, -67, +430, -275, -80, 328, -357, 486, -370, -635, +45, -608, 605, 895, 262, 657, -627, -1128, +-337, -606, 591, 1320, -19, 422, -434, -1459, +498, -69, 353, 1479, -901, -352, -385, -1399, +1057, 761, 399, 1259, -758, -1081, -417, -1029, +196, 1139, 376, 801, 378, -965, -144, -629, +-841, 675, -46, 469, 841, -451, 317, -248, +-495, 386, -602, -51, 63, -526, 763, 418, +304, 746, -737, -720, -513, -1008, 690, 959, +482, 1088, -659, -1025, -243, -969, 668, 895, +21, 723, -820, -626, 222, -545, 893, 366, +-301, 544, -848, -272, 245, -661, 678, 329, +-208, 762, -318, -410, 287, -770, -187, 424, +-400, 581, 634, -260, 543, -244, -902, -104, +-594, -37, 940, 458, 458, 209, -742, -667, +-257, -226, 583, 598, -27, 194, -437, -371, +131, -171, 513, 51, 6, 256, -821, 194, +-115, -496, 888, -195, 485, 766, -880, -94, +-761, -880, 731, 522, 760, 804, -394, -989, +-573, -558, 203, 1332, 128, 267, -106, -1560, +320, 12, 193, 1602, -578, -227, -423, -1416, +731, 309, 415, 1095, -533, -385, -153, -605, +99, 389, -222, 22, 371, -277, 590, 491, +-712, -42, -683, -734, 767, 450, 456, 694, +-473, -866, -77, -441, 56, 1062, -205, 226, +250, -1029, 369, -160, -509, 689, -10, 259, +456, -65, -551, -515, -309, -644, 1239, 760, +36, 1204, -1571, -789, 54, -1522, 1598, 583, +-76, 1530, -1235, -298, 152, -1226, 564, 32, +-162, 782, -19, 64, 307, -381, -221, 16, +-545, 202, 213, -258, 648, -200, 89, 379, +-587, 368, -369, -292, 291, -553, 470, -78, +194, 645, -348, 510, -523, -483, -129, -825, +774, -2, 607, 958, -653, 576, -1075, -819, +541, -1059, 1058, 488, -247, 1230, -743, -122, +21, -972, 316, -222, -37, 439, 138, 350, +296, 205, -542, -252, -491, -785, 690, 11, +622, 1087, -626, 362, -633, -1219, 573, -623, +459, 1123, -463, 714, -266, -926, 462, -587, +57, 589, -328, 369, -32, -197, 129, -217, +171, -151, 120, 159, -306, 475, -426, -271, +424, -711, 644, 551, -447, 696, -515, -772, +205, -477, 220, 784, 120, 133, 290, -548, +-517, 258, -704, 74, 775, -538, 926, 400, +-790, 687, -898, -732, 686, -685, 557, 730, +-393, 644, -128, -457, 129, -625, -222, 109, +32, 572, 391, 97, -30, -358, -319, -172, +-62, 0, 93, 127, 193, 369, 113, -41, +-133, -599, -316, -65, -51, 598, 514, 156, +201, -410, -609, -195, -144, 89, 498, 227, +2, 147, -255, -266, 170, -147, 79, 245, +-432, -60, 176, -215, 514, 372, -314, 179, +-373, -668, 270, -136, 180, 695, -99, 153, +44, -416, -241, -242, -19, -135, 521, 429, +-104, 683, -676, -589, 202, -1045, 803, 617, +-304, 1175, -730, -537, 202, -1031, 567, 418, +108, 674, -461, -303, -347, -287, 381, 276, +415, -50, -283, -307, -247, 288, 197, 280, +-107, -419, -11, -79, 464, 446, -181, -328, +-706, -386, 453, 794, 694, 297, -666, -1158, +-428, -183, 690, 1183, 124, 83, -490, -844, +52, 50, 157, 193, -29, -191, 211, 499, +-183, 321, -327, -915, 329, -452, 156, 866, +-202, 536, 166, -357, -80, -578, -596, -361, +452, 505, 926, 982, -721, -332, -990, -1236, +729, 59, 681, 1042, -328, 288, -242, -607, +-229, -537, -214, 146, 718, 568, 557, 145, +-888, -383, -764, -224, 783, 74, 762, 155, +-424, 170, -671, -12, 103, -265, 487, -105, +42, 197, -234, 168, 51, -46, -58, -198, +-251, -88, 373, 259, 432, 133, -602, -427, +-436, -37, 733, 659, 239, -169, -600, -815, +-45, 366, 427, 764, -149, -430, -99, -465, +166, 299, -189, -3, 21, -40, 434, 467, +-368, -246, -377, -738, 553, 379, 283, 724, +-509, -322, -156, -462, 301, 100, 15, 35, +72, 195, 157, 366, -605, -405, -186, -633, +999, 449, 135, 714, -1132, -295, -109, -680, +1003, 39, 76, 579, -597, 204, -159, -433, +67, -431, 286, 333, 445, 581, -492, -307, +-751, -597, 541, 243, 861, 549, -522, -91, +-777, -520, 344, -76, 462, 501, 3, 215, +-229, -445, -322, -283, 41, 335, 501, 222, +70, -132, -568, -85, -50, -107, 443, -84, +21, 316, -313, 205, 108, -381, 55, -273, +-13, 256, 20, 335, -97, -82, 6, -310, +308, -115, -171, 194, -363, 306, 348, -67, +267, -422, -308, -19, -100, 434, 283, 28, +-200, -301, -46, -25, 489, 109, -166, 67, +-630, -3, 356, -95, 697, -4, -436, 79, +-585, 13, 420, -107, 511, -28, -367, 215, +-404, 48, 395, -359, 307, -70, -435, 498, +-140, -5, 518, -431, -43, 72, -601, 158, +220, -73, 769, 197, -487, 62, -829, -538, +608, -76, 870, 736, -687, 151, -732, -758, +496, -283, 501, 580, -269, 447, -157, -234, +-57, -656, -247, -195, 281, 925, 487, 464, +-328, -1072, -688, -570, 189, 1003, 596, 597, +66, -754, -478, -610, -357, 438, 245, 626, +535, -201, -137, -565, -630, 32, 138, 420, +576, 120, -344, -297, -415, -208, 510, 150, +292, 322, -633, 2, -285, -592, 671, 0, +359, 864, -622, -113, -392, -1038, 532, 278, +329, 968, -340, -370, -132, -616, 212, 290, +-115, 130, -62, -72, 447, 338, -13, -200, +-603, -602, 95, 433, 707, 580, -112, -517, +-592, -367, 269, 559, 261, 50, -173, -617, +102, 343, 114, 565, -278, -554, -67, -416, +539, 402, -3, 367, -607, -127, 120, -357, +672, -67, -233, 320, -636, 43, 357, -240, +625, 253, -439, 86, -652, -645, 447, -1, +744, 1024, -425, 37, -885, -1294, 380, -218, +860, 1443, -287, 357, -710, -1423, 4, -281, +405, 1082, 244, 36, -93, -332, -561, -8, +-278, -440, 680, 303, 464, 788, -699, -582, +-721, -766, 609, 652, 741, 636, -604, -586, +-612, -562, 412, 531, 305, 476, -193, -432, +-113, -358, -147, 228, 49, 270, 333, 60, +-157, -310, -342, -243, 207, 353, 278, 266, +-344, -341, -56, -171, 427, 279, -159, 1, +-462, -172, 347, 22, 595, 164, -486, 164, +-515, -466, 431, -292, 466, 859, 47, 225, +-649, -923, -172, -295, 790, 751, 201, 549, +-598, -632, -34, -732, 389, 609, -194, 637, +88, -554, 396, -270, -367, 256, -353, 147, +348, -145, 590, -169, -314, 497, -584, -263, +310, -546, 420, 664, -35, 317, -427, -742, +117, -165, 242, 743, -139, -55, -46, -489, +126, 81, -48, 183, -247, 90, 323, -92, +37, -21, -513, -206, 333, 69, 280, 514, +-488, -368, -228, -366, 569, 471, -29, 24, +-529, -367, 100, 334, 319, 144, -204, -532, +-256, -2, 329, 585, -91, 13, -424, -589, +240, -2, 454, 418, -509, 79, -480, -238, +628, -154, 271, 167, -579, 6, -183, 7, +410, 120, 43, -161, -370, -159, 235, 192, +212, 213, -586, -240, 28, -234, 794, 389, +-209, 170, -812, -710, 226, 100, 851, 1039, +-215, -516, -700, -1137, 171, 785, 667, 1052, +-266, -825, -346, -790, 405, 635, -67, 463, +-186, -375, 333, -43, 135, 88, -526, -359, +160, 194, 631, 536, -327, -287, -477, -615, +392, 362, 555, 442, -491, -313, -391, -224, +588, 203, 242, 127, -527, -166, -106, -115, +631, 128, -203, 172, -326, 33, 167, -422, +118, -143, 84, 710, -114, 118, -241, -806, +81, -41, 338, 745, -217, -130, -148, -473, +136, 288, -165, 117, -13, -389, 233, 243, +128, 284, -584, -372, -117, -169, 589, 409, +-23, -63, -362, -340, 33, 444, -176, -8, +-55, -624, 658, 381, -204, 556, -776, -575, +128, -394, 691, 617, -135, 184, -530, -526, +228, -67, 13, 525, -208, -168, 262, -434, +183, 498, -310, -44, -430, -361, 473, 386, +342, 35, -409, -482, -84, 145, 108, 549, +-62, -254, 235, -579, 58, 386, -313, 339, +-64, -344, 476, -25, -79, 293, -341, -359, +68, -365, 582, 900, -332, 238, -430, -1095, +510, -186, 141, 908, -185, 393, -88, -773, +103, -378, 29, 543, 21, 116, 67, -194, +75, 117, -134, 128, -212, -528, 252, -108, +484, 868, -512, -8, -255, -783, 248, -30, +433, 588, -299, -96, -289, -263, 273, 565, +98, -524, -283, -641, 87, 1173, 294, 213, +-215, -1107, -396, 159, 377, 677, 152, -372, +-134, -322, -203, 687, -114, -68, 338, -959, +-29, 647, -186, 577, -88, -829, 256, 227, +-284, 409, -66, -886, 417, 294, -110, 1079, +-482, -891, 49, -683, 461, 972, 26, 68, +-478, -684, 83, 643, -5, -17, 143, -988, +179, 713, -204, 868, -377, -1134, 354, -411, +94, 1343, -185, -550, 203, -891, -34, 1428, +-481, -70, 175, -1735, 702, 1124, -287, 1232, +-573, -1675, 178, -255, 417, 1508, -167, -689, +44, -800, 127, 1182, -512, 103, 69, -1365, +668, 542, -142, 1131, -367, -989, -29, -411, +138, 894, 52, -286, 325, -522, -114, 769, +-517, 20, 134, -804, 482, 339, -87, 391, +-232, -391, 179, 283, -200, 187, -203, -938, +494, -2, 308, 1631, -478, -397, -578, -1900, +522, 762, 451, 1713, -161, -1019, -371, -1119, +-133, 1090, 202, 282, 247, -821, -34, 374, +-125, 415, -257, -801, 100, 217, 248, 738, +-45, -820, -185, -330, 185, 1332, -124, -396, +-426, -1458, 597, 1174, 180, 959, -381, -1449, +-350, -137, 124, 1017, 486, -473, 36, -236, +-414, 714, -226, -524, 170, -674, 487, 1086, +-197, 423, -354, -1407, 75, 44, 188, 1345, +-133, -597, 163, -776, 97, 843, -448, -64, +93, -493, 308, 485, 104, 123, -466, -668, +40, 11, 509, 1116, -467, -453, -109, -1331, +447, 1010, 67, 1067, -446, -1251, -115, -495, +398, 977, 182, -63, -118, -310, -535, 409, +174, -492, 521, -372, -96, 974, -340, 215, +8, -1201, 96, 99, 51, 1023, 338, -442, +-385, -409, -368, 266, 633, 159, 105, -103, +-655, -181, 231, 79, 587, 359, -725, -194, +-54, -582, 756, 602, -543, 348, -242, -918, +804, 438, -360, 745, -969, -1540, 1191, 198, +603, 2296, -1655, -1586, 54, -2231, 1424, 2848, +-460, 1124, -954, -3017, 756, 125, 285, 2283, +-906, -1016, 583, -1209, 397, 1625, -632, -233, +-248, -1334, 397, 1215, 496, 329, -410, -1107, +-501, 610, 131, 118, 773, -1005, -108, 1306, +-953, 595, 199, -2638, 1138, 890, -636, 2668, +-1002, -2243, 1124, -1622, 560, 2824, -1427, 42, +94, -2452, 1300, 1686, -730, 819, -616, -2486, +859, 1223, -65, 2148, -756, -2828, 798, -1047, +232, 3613, -1222, -495, 558, -3138, 1032, 1772, +-1232, 1558, -311, -1996, 1348, 86, -381, 1567, +-1133, -1402, 990, -800, 429, 2150, -1049, -79, +392, -2162, 466, 843, -778, 1359, 144, -1149, +991, -23, -920, 636, -578, -888, 1180, 117, +15, 1059, -973, -656, 496, -659, 450, 933, +-845, -168, 205, -898, 953, 1034, -842, 765, +-788, -1882, 1277, -201, 392, 2103, -1418, -555, +87, -1506, 1294, 1053, -583, 547, -774, -1194, +638, 286, 346, 947, -436, -555, -52, -481, +130, 143, -231, -13, 421, 760, 300, 206, +-995, -1508, -48, -216, 1218, 1804, -356, 40, +-858, -1419, 538, 130, 60, 659, -173, -422, +527, 429, -395, 538, -653, -1314, 873, -438, +194, 1514, -810, 404, 414, -1035, 342, -498, +-998, -10, 432, 965, 1329, 1047, -1334, -1663, +-1105, -1540, 1816, 2193, 695, 1341, -2003, -2192, +-23, -763, 1725, 1704, -623, 90, -1013, -888, +804, 298, 477, 38, -750, -137, -232, 443, +579, -565, 277, -163, -345, 1206, -666, -490, +265, -1660, 1169, 1360, -555, 1613, -1236, -1959, +665, -1161, 1164, 2008, -757, 715, -1054, -1774, +1069, -202, 498, 1183, -1052, -104, -75, -484, +926, 93, -145, 67, -860, -32, 228, -9, +931, 202, -427, 97, -949, -625, 589, -124, +1124, 1214, -1077, -141, -904, -1636, 1165, 573, +839, 1863, -1075, -1106, -918, -1889, 871, 1729, +1079, 1532, -593, -2035, -1311, -910, 368, 1594, +1562, 603, -260, -700, -1735, -701, 281, -377, +1767, 1103, -283, 1362, -1571, -1677, 101, -1859, +1135, 1922, 623, 1955, -930, -1707, -1360, -1754, +712, 1121, 2244, 1274, -941, -211, -2483, -805, +1164, -674, 2280, 541, -1554, 1129, -1400, -503, +1749, -934, 307, 512, -1601, 334, 361, -511, +1451, 186, -635, 791, -1150, -618, 381, -1159, +773, 862, 360, 1352, -771, -819, -816, -1350, +940, 757, 591, 1021, -966, -899, 36, -259, +1041, 1149, -1117, -655, -894, -1442, 2095, 1431, +516, 1553, -2541, -1669, -47, -1621, 2375, 1572, +-575, 1432, -1622, -1254, 1156, -919, 631, 739, +-1611, 480, 93, -565, 2120, 31, -680, 679, +-2416, -598, 1140, -824, 2267, 1105, -1523, 719, +-1723, -1457, 2085, -157, 590, 1637, -2639, -1042, +1023, -1316, 2572, 2398, -2262, 609, -1970, -3357, +2679, -12, 1114, 3930, -2359, -427, -3, -4046, +1134, 779, -598, 3582, 182, -862, 766, -2829, +-1254, 715, -438, 2156, 1756, -580, -87, -1656, +-1620, 528, 403, 1395, 1189, -695, -248, -1173, +-760, 938, -427, 857, 700, -1031, 1293, -454, +-939, 795, -2091, 181, 1541, -271, 2203, -275, +-1877, -196, -1882, 669, 2057, 358, 1075, -1052, +-1946, -318, -55, 1316, 1589, 233, -868, -1493, +-1174, -129, 1654, 1514, 507, 172, -1815, -1505, +-100, -341, 1654, 1520, -20, 471, -1457, -1340, +13, -727, 1206, 987, 187, 1214, -1202, -695, +-263, -1688, 1185, 485, 273, 1920, -1262, -226, +-69, -1871, 1224, -140, -326, 1707, -978, 379, +699, -1332, 525, -436, -855, 600, -75, 689, +723, 42, -161, -1046, -603, -291, 354, 1132, +417, 495, -381, -1194, -447, -538, 358, 1136, +848, 517, -727, -678, -1105, -989, 1124, 315, +1206, 1848, -1457, -298, -1144, -2627, 1830, 462, +575, 3063, -1686, -579, -82, -3148, 1505, 707, +-568, 2597, -904, -592, 900, -1505, 172, -27, +-770, 457, 430, 821, 381, 330, -945, -1552, +437, -624, 992, 1821, -1275, 514, -579, -1316, +1935, -500, -215, 398, -2111, 633, 888, 662, +2157, -834, -1484, -1703, -1968, 1201, 1691, 2256, +1806, -1335, -1585, -2372, -1706, 1120, 1340, 2220, +1525, -741, -1057, -1724, -1172, 152, 786, 1182, +610, 343, -581, -622, 108, -491, 321, -119, +-795, 501, 12, 818, 1168, -352, -306, -1374, +-1170, 159, 314, 1623, 985, 11, 54, -1400, +-878, -234, -920, 798, 1372, 501, 1660, -44, +-2166, -765, -2095, -420, 2861, 618, 2194, 607, +-3327, 58, -1634, -680, 2955, -998, 854, 593, +-1930, 1933, -58, -350, 544, -2539, -412, -35, +365, 2501, 922, 687, -660, -1822, -1495, -1663, +396, 760, 2094, 2758, 364, 243, -2910, -3390, +-994, -1195, 3625, 3376, 1271, 2120, -4037, -3022, +-1078, -2515, 3902, 2223, 731, 2367, -3330, -1075, +-455, -2000, 2564, 50, 322, 1616, -1632, 521, +-547, -1454, 805, -492, 1200, 1633, -383, -3, +-1926, -2188, 207, 592, 2726, 3161, -255, -1169, +-3421, -3949, 318, 1245, 3890, 4247, -122, -545, +-4141, -4044, -408, -595, 4122, 3121, 1259, 1994, +-3823, -1728, -2201, -3329, 3189, 314, 3028, 4270, +-2322, 645, -3500, -4529, 1312, -1014, 3471, 4190, +-280, 923, -2954, -3640, -855, -573, 2305, 3276, +1895, 136, -1752, -3032, -2751, -18, 1333, 2749, +3413, 568, -1104, -2374, -3731, -1556, 806, 1702, +3692, 2458, -283, -531, -3374, -2830, -252, -1044, +2457, 2418, 1020, 2594, -1285, -1263, -1761, -3558, +99, -350, 2256, 3609, 795, 1927, -2333, -2807, +-1262, -2949, 2097, 1470, 1159, 3269, -1495, -293, +-803, -2902, 752, -321, 461, 2262, 118, 190, +-589, -1694, -914, 324, 1270, 1583, 1435, -802, +-2098, -1855, -1773, 915, 2664, 1929, 1827, -224, +-2289, -1488, -1929, -1135, 1079, 407, 1962, 2659, +709, 1132, -1784, -3710, -2651, -2749, 1489, 3897, +4065, 3965, -1060, -3313, -4535, -4164, 611, 2004, +3943, 3344, -270, -294, -2354, -2063, -186, -976, +497, 453, 539, 1660, 1265, 1055, -799, -1763, +-2691, -2031, 1117, 1142, 3491, 2652, -1447, -157, +-3426, -3090, 1392, -546, 2773, 2967, -971, 919, +-1562, -2189, 84, -1013, 149, 820, 977, 916, +1121, 827, -1676, -702, -2182, -2155, 1906, 157, +2551, 2923, -1321, 550, -2353, -2864, 273, -1157, +1662, 1845, 694, 1509, -604, -165, -1217, -1511, +-396, -1598, 1074, 1220, 874, 2672, -268, -673, +-558, -2591, -980, -74, -342, 1495, 2050, 608, +1720, 394, -2764, -941, -2969, -2280, 2920, 928, +3607, 3561, -2524, -664, -3402, -3854, 1767, 375, +2318, 3040, -697, -106, -912, -1580, -322, 164, +-374, -235, 980, -429, 1262, 1989, -1154, 559, +-1715, -2995, 927, -598, 1757, 3071, -396, 600, +-1763, -2447, 181, -467, 1487, 1437, -263, 148, +-1161, -351, 793, 256, 825, -559, -1670, -397, +-460, 752, 2410, 562, 291, -614, -2699, -497, +-373, 390, 2321, 67, 702, -193, -1446, 359, +-994, 460, 335, -768, 1146, -1026, 310, 929, +-749, 1478, -325, -529, -130, -1602, -169, -259, +1053, 1155, 849, 1134, -1483, -229, -1456, -1624, +1312, -761, 1579, 1229, -611, 1556, -1100, -90, +-297, -1745, 322, -1484, 919, 1360, 388, 2780, +-1026, -641, -625, -3124, 707, -193, 136, 2455, +-34, 840, 595, -1259, -408, -960, -1181, 77, +370, 627, 1347, 471, -126, 56, -808, -313, +-56, -763, -263, -135, -55, 1043, 1331, 512, +480, -840, -1776, -498, -1034, 457, 1278, -125, +1389, -98, -23, 1108, -1277, -106, -1359, -1799, +494, -150, 2419, 2022, 503, 602, -2605, -1657, +-1364, -901, 1929, 756, 1722, 943, -778, 250, +-1541, -660, -258, -973, 1015, 69, 740, 1397, +-502, 504, -627, -1548, 262, -815, 214, 1559, +-352, 761, 38, -1459, 645, -483, 29, 1116, +-640, 341, -629, -482, 422, -744, 1214, -131, +97, 1411, -1438, 687, -623, -2075, 1078, -1079, +798, 2472, -102, 1022, -694, -2123, -893, -792, +272, 1306, 1501, 396, 175, -268, -1477, 1, +-302, -745, 816, -69, 140, 1327, -19, -185, +272, -1358, -595, 537, -451, 1080, 520, -771, +349, -731, 80, 710, 10, 523, -678, -354, +-648, -374, 998, -259, 1193, 306, -845, 833, +-1340, -135, 215, -1201, 1121, -123, 522, 1305, +-708, 287, -915, -1099, 192, -254, 979, 706, +29, -11, -573, -210, -104, 258, 31, -165, +213, -316, 215, 322, -280, 131, -271, -317, +418, 176, 383, 358, -858, -489, -387, -526, +1074, 676, 685, 718, -1164, -610, -1072, -738, +1020, 215, 1294, 592, -618, 209, -1333, -237, +350, -373, 908, -373, -202, 329, -267, 884, +312, -180, -402, -910, -561, -94, 892, 445, +712, 248, -1029, 436, -608, -312, 683, -1297, +549, 322, -409, 1630, -275, -227, 101, -1329, +92, 189, 65, 498, -117, -300, 20, 528, +137, 521, -57, -1268, -301, -734, 190, 1322, +302, 897, -178, -698, -243, -887, 34, -370, +243, 778, 170, 1282, -392, -526, -275, -1584, +512, 85, 471, 1206, -696, 408, -510, -395, +650, -671, 439, -676, -242, 751, -352, 1554, +-237, -635, 37, -1981, 724, 360, 403, 2012, +-1020, -205, -683, -1613, 732, 187, 986, 1009, +-416, -277, -740, -411, 29, 437, 41, -113, +238, -526, 705, 495, 26, 519, -1502, -743, +-322, -580, 1600, 1107, 788, 542, -1170, -1496, +-898, -431, 271, 1659, 529, 377, 835, -1571, +86, -411, -1546, 1254, -802, 458, 1671, -815, +1228, -434, -1155, 496, -1342, 150, 439, -267, +1125, 234, 7, 149, -608, -478, -82, -255, +48, 603, -80, 404, 260, -644, 245, -355, +-220, 604, -251, 70, -2, -552, -27, 293, +265, 608, 406, -571, -401, -737, -617, 577, +344, 797, 504, -214, -207, -698, -42, -325, +-29, 403, -363, 642, 183, 173, 487, -613, +-313, -770, -165, 167, 432, 1167, -369, 489, +-669, -1185, 741, -1005, 1101, 841, -756, 1054, +-1475, -304, 320, -531, 1504, -208, 503, -361, +-1256, 539, -1043, 1082, 604, -469, 992, -1349, +295, 50, -481, 1155, -806, 358, -474, -534, +883, -654, 1265, -127, -431, 712, -1490, 493, +-352, -502, 1130, -420, 849, 65, -217, 192, +-910, 336, -704, -5, 437, -499, 1066, -64, +515, 513, -817, -44, -1520, -456, 135, 280, +2166, 303, 505, -331, -2114, -212, -877, 184, +1481, 169, 837, 49, -637, 20, -519, -303, +-33, -343, 96, 417, 435, 853, -4, -492, +-440, -1272, 259, 575, 231, 1265, -735, -556, +47, -861, 1022, 451, -115, 285, -963, -435, +46, 258, 395, 506, 239, -554, 328, -623, +-473, 442, -909, 796, 427, -105, 1299, -886, +-329, -166, -1269, 707, 178, 281, 931, -380, +-42, -122, -509, 86, -74, -321, 258, 103, +88, 766, -111, -42, -199, -983, 116, -284, +376, 892, -166, 711, -489, -522, 18, -1159, +628, 255, 217, 1267, -623, -248, -476, -889, +419, 354, 749, 331, -209, -535, -809, 134, +65, 622, 570, -299, 115, -491, -325, 99, +-57, 185, -81, 288, 111, 159, 265, -525, +-222, -496, -150, 508, 366, 724, -138, -311, +-672, -763, 717, 140, 727, 533, -1050, -62, +-680, -154, 1012, 139, 569, -253, -637, -266, +-335, 503, -42, 331, 169, -504, 692, -340, +-92, 366, -976, 128, 21, 14, 828, 116, +-6, -497, -333, -232, 77, 878, -329, 249, +-109, -1128, 694, -120, 199, 1124, -603, -83, +-343, -736, 135, 82, 410, 208, 431, 121, +-291, 299, -876, -417, 47, -645, 871, 713, +371, 682, -654, -788, -535, -560, 191, 689, +433, 365, 194, -520, -71, -103, -326, 230, +-399, -32, 208, 130, 693, -85, 32, -448, +-627, 341, -181, 734, 169, -560, 162, -1082, +329, 657, 253, 1510, -872, -689, -578, -1759, +913, 539, 884, 1733, -614, -213, -871, -1524, +119, -16, 485, 1065, 396, 66, -5, -439, +-545, 1, -451, -99, 333, -110, 658, 356, +105, 151, -465, -242, -635, -138, 134, -28, +898, -24, 236, 243, -813, 338, -423, -351, +444, -553, 378, 242, -28, 481, -86, 92, +-270, -112, -266, -503, 347, -432, 462, 802, +-173, 960, -428, -923, -92, -1180, 132, 846, +380, 883, 137, -494, -359, -211, -470, -109, +281, -427, 580, 639, -108, 851, -557, -1021, +62, -891, 387, 1147, -125, 597, -260, -947, +270, -302, 257, 612, -360, 141, -399, -236, +263, -235, 688, -45, -158, 452, -679, 175, +-239, -500, 584, -361, 521, 446, -263, 499, +-590, -321, -196, -392, 451, -46, 520, 265, +-98, 347, -576, -108, -428, -346, 547, -272, +770, 212, -459, 764, -876, -151, 544, -1053, +641, 155, -865, 1026, -93, -217, 1217, -646, +-454, 263, -1494, -15, 857, -113, 1438, 635, +-906, -159, -997, -1043, 535, 432, 479, 1152, +-57, -629, 14, -883, -369, 532, -252, 468, +548, -175, 148, -107, -293, -168, -34, -242, +-64, 454, -71, 502, 438, -628, 65, -558, +-781, 593, 231, 481, 808, -461, -482, -247, +-693, 335, 586, -154, 519, -171, -436, 467, +-362, 120, 45, -656, 334, -162, 355, 669, +-315, 170, -640, -456, 346, -136, 553, 119, +-228, 73, -281, 182, 31, 2, -46, -295, +203, -50, 210, 137, -406, 42, 2, 220, +382, 40, -451, -682, -166, -98, 917, 1044, +-127, 27, -1203, -1096, 348, 131, 1154, 924, +-411, -430, -813, -566, 265, 761, 411, 189, +-126, -1026, -6, 112, -21, 1060, -175, -284, +30, -801, 140, 314, 132, 374, -87, -353, +-302, 108, 113, 437, 356, -457, -255, -534, +-252, 502, 392, 629, 125, -308, -404, -541, +-220, -86, 371, 295, 432, 481, -180, 25, +-766, -640, -19, -376, 977, 609, 135, 489, +-864, -327, -132, -300, 439, -126, -79, -84, +314, 562, 256, 498, -935, -845, -424, -774, +1291, 912, 384, 813, -1153, -771, -162, -664, +591, 572, -98, 337, 58, -254, 382, -63, +-611, -130, -505, 11, 887, 459, 399, -43, +-869, -838, -103, 135, 701, 1251, -318, -292, +-420, -1445, 548, 325, 256, 1356, -568, -176, +-161, -1020, 357, -17, 49, 477, 15, 145, +57, 122, -247, -109, -297, -679, 341, -6, +475, 960, -106, 156, -633, -946, -274, -215, +701, 612, 573, 172, -582, -133, -625, -58, +177, -322, 628, -144, 176, 742, -441, 288, +-540, -1094, 229, -286, 862, 1370, -188, 125, +-971, -1497, 174, 88, 951, 1394, -196, -137, +-677, -1145, -25, 16, 377, 760, 372, 190, +-70, -223, -727, -493, -184, -213, 922, 607, +380, 479, -868, -437, -410, -601, 474, 147, +385, 422, 62, 214, -292, -41, -492, -550, +100, -301, 767, 585, 38, 659, -789, -435, +-40, -947, 530, 319, 51, 989, -246, -335, +-29, -745, 73, 454, 46, 304, -58, -563, +-139, 104, 186, 583, 301, -287, -391, -495, +-451, 234, 569, 350, 409, -70, -555, -133, +-186, -90, 318, -23, -110, 68, -1, 33, +439, 293, -281, -65, -725, -771, 525, 129, +785, 1103, -629, -153, -604, -1189, 593, 213, +232, 885, -453, -236, 232, -302, 273, 163, +-696, -328, -84, 54, 1028, 628, -60, -158, +-1237, -556, 183, -41, 1225, 501, -286, 337, +-967, -677, 300, -326, 486, 866, -109, -50, +-55, -696, -86, 294, -292, 308, 228, -200, +447, 23, -121, -47, -634, -279, -22, 208, +813, 595, 20, -204, -804, -1057, -12, 178, +726, 1475, -48, -213, -557, -1537, -38, 128, +601, 1267, 54, 116, -702, -833, -47, -523, +775, 570, 77, 874, -757, -671, -174, -827, +648, 859, 355, 400, -587, -686, -457, -146, +627, 365, 189, 239, -380, -280, 44, -179, +44, 211, -125, -206, 122, 224, 252, 570, +-346, -969, -144, -374, 292, 1336, 130, -171, +-189, -954, -183, 371, 232, 471, -64, -350, +58, -307, 172, 622, -464, 24, -14, -820, +559, 323, 116, 757, -832, -573, -21, -539, +864, 834, -53, 68, -572, -777, -287, 183, +602, 444, 335, 263, -376, -530, -440, -656, +-74, 621, 901, 807, 120, -241, -1064, -1145, +-221, -43, 1084, 1270, 382, 177, -1168, -971, +-148, -308, 619, 470, 369, 408, -280, -11, +-570, -408, 158, -242, 457, 241, 189, 372, +-577, -68, -231, -435, 534, 83, 226, 340, +-506, -51, -92, -428, 395, 205, -110, 583, +-103, -586, 70, -448, 77, 761, -215, 190, +-31, -732, 411, 161, -56, 501, -552, -442, +121, -189, 629, 452, -289, 98, -300, -360, +82, -109, 62, 113, 147, 210, 135, 236, +-409, -471, -54, -271, 395, 394, -60, 288, +-255, -167, 213, -299, 117, 78, -457, -42, +162, 223, 412, 374, -97, -732, -467, -204, +77, 877, 467, -231, -172, -479, -235, 321, +270, 152, -71, -299, -364, 0, 481, 354, +175, -283, -556, -191, 61, 493, 275, -98, +-46, -521, -120, 197, 79, 618, -11, -257, +-107, -629, 22, 308, 116, 337, -15, -76, +-130, -47, 197, -117, -310, -254, -44, 132, +659, 687, -412, -246, -310, -823, 168, 360, +311, 438, -80, -139, -180, 18, 54, -183, +-52, -331, 24, 356, 293, 492, -154, -376, +-456, -450, 499, 311, 156, 273, -368, -374, +-187, 261, 482, 241, 79, -825, -547, 301, +216, 693, 222, -557, -260, -206, 134, 294, +100, 155, -197, -344, -239, -33, 170, 386, +614, -36, -288, -171, -967, -416, 417, 337, +962, 623, -271, -341, -973, -596, 158, -115, +826, 918, -211, 161, -394, -886, 288, 11, +-224, 229, -156, 291, 669, 157, -39, -477, +-788, -463, 320, 643, 647, 619, -659, -959, +57, -236, 400, 826, -183, -90, -333, -450, +255, 44, 358, 335, -361, -201, -77, 107, +153, 136, -198, -836, 320, 693, 20, 805, +-418, -1316, 39, -141, 375, 1042, -218, -215, +-103, -448, 270, 166, -481, 130, 107, -289, +641, 289, -445, 306, -623, -774, 592, 110, +473, 815, -511, -662, -378, -317, 373, 847, +122, -202, 215, -798, -463, 605, -6, 550, +265, -843, 20, -9, -39, 602, -82, -465, +261, 82, -282, 449, -166, -687, 552, -10, +85, 736, -517, -234, -98, -684, 352, 537, +70, 446, 64, -984, -148, 430, -592, 797, +440, -1288, 595, 127, -387, 1376, -755, -1087, +449, -674, 413, 1439, -228, -243, -250, -1109, +107, 824, -334, 507, 453, -1129, 448, 330, +-963, 1072, -220, -1317, 1005, -429, 76, 1968, +-944, -616, 312, -1850, 488, 1540, -521, 964, +231, -1827, 491, 226, -752, 1447, -164, -1243, +1023, -690, -126, 1939, -1029, -383, 661, -1893, +547, 1398, -635, 978, -336, -1732, 805, 231, +-80, 1355, -585, -1170, 323, -562, -25, 1534, +1, -393, 142, -1105, -174, 1090, -370, -24, +340, -1016, 291, 1062, -595, 477, 145, -1632, +219, 263, -402, 1530, 69, -824, 449, -910, +-183, 1096, -727, -29, 488, -1054, 835, 1181, +-985, 300, -283, -1765, 941, 823, -103, 1283, +-591, -1438, 401, -327, 295, 1380, -616, -424, +371, -1169, 496, 1161, -643, 524, -270, -1534, +935, 561, -178, 1060, -722, -1520, 730, 158, +-130, 1750, -602, -1443, 792, -1094, 1, 1963, +-752, 160, 128, -1655, 619, 605, -536, 872, +-41, -1168, 584, 288, -966, 1205, -98, -1472, +1374, -378, -605, 1856, -1328, -926, 1216, -916, +526, 1581, -1410, -623, 602, -1102, 736, 1493, +-998, 231, -47, -1528, 915, 640, -493, 724, +-189, -1217, 855, 881, -926, 765, -248, -2266, +1444, 606, -128, 2441, -1626, -1904, 985, -1538, +1010, 2686, -1462, -249, 212, -2441, 1409, 2146, +-1202, 1066, -1040, -2999, 1786, 358, 388, 2933, +-1655, -1518, 14, -1942, 974, 2001, -143, 207, +-457, -1025, -5, 776, 118, -589, -61, -353, +110, 1468, -490, -494, 289, -1821, 713, 1616, +-1075, 1523, -427, -2652, 1266, -288, 187, 2413, +-1141, -699, 65, -1305, 871, 1156, -470, -266, +47, -1056, 407, 1985, -411, 115, -419, -2910, +1014, 1193, 110, 2565, -1165, -2041, 731, -1480, +783, 2409, -1292, -75, -92, -2136, 1572, 1589, +-546, 1098, -1143, -2126, 467, -247, 780, 2222, +-485, -707, 67, -1768, -135, 1759, -636, 450, +439, -1948, 838, 611, -571, 1547, -894, -891, +406, -1196, 404, 862, -194, 591, 364, -379, +-416, 142, -961, -597, 844, -514, 1244, 1595, +-1084, 359, -1245, -2225, 1482, 416, 574, 1924, +-1284, -1154, 72, -996, 1289, 1476, -695, -2, +-851, -1399, 1018, 761, 366, 860, -565, -884, +-66, -182, 241, 411, -338, -389, 399, 433, +565, 617, -918, -1231, -356, -429, 787, 1522, +144, 99, -341, -1195, -232, 120, -171, 414, +427, -85, 52, 596, -453, -425, 78, -1157, +268, 992, -497, 1040, 9, -1061, 612, -779, +-207, 945, -783, 311, 367, -590, 820, 78, +-737, 145, -248, -66, 520, 45, 113, -289, +-430, 232, 157, 697, 398, -783, -211, -979, +-110, 1367, -69, 1000, 421, -1775, 154, -687, +-409, 1722, -107, 403, 260, -1578, 259, -95, +-116, 1499, -215, -259, -179, -1431, 173, 414, +420, 1622, -156, -553, -714, -2042, 165, 1074, +665, 2043, -284, -1551, -506, -1780, 168, 2024, +145, 1334, -32, -2554, 29, -590, -381, 2789, +54, -152, 750, -2589, -625, 560, -848, 2162, +1198, -724, 927, -1604, -1770, 901, -860, 695, +2252, -893, 838, 376, -2302, 602, -981, -1327, +2552, 38, 984, 1840, -2376, -806, -924, -1855, +2269, 1391, 896, 1646, -2239, -1689, -316, -1514, +1866, 1946, -332, 1064, -1102, -1649, 847, -527, +113, 688, -1381, 253, 1210, 333, 1342, 141, +-2519, -1388, -883, -535, 2986, 2266, 300, 625, +-2890, -2485, 117, -469, 2041, 1983, -412, 148, +-911, -1116, 499, 436, -337, -54, -325, -775, +1035, 820, 343, 728, -1390, -642, -109, -729, +1146, -65, 124, 771, -728, 800, 117, -878, +370, -1027, -223, 987, -307, 534, 637, -1085, +552, 672, -1133, 961, -467, -2042, 1160, -487, +617, 2755, -1227, 124, -265, -2763, 844, 147, +-147, 2155, -500, -272, 491, -1308, 221, 347, +-687, 538, -427, -276, 600, -263, 887, 121, +-524, 800, -1643, -398, 556, -1478, 2053, 844, +-808, 1954, -1976, -1128, 997, -2343, 1389, 1333, +-1018, 2493, -413, -1345, 599, -2420, -415, 896, +300, 2589, 771, -396, -953, -2780, -844, -288, +1542, 3034, 845, 1120, -1735, -3631, -623, -1351, +1345, 3925, 886, 1013, -778, -3485, -1255, -627, +232, 2588, 1794, 390, -125, -1574, -2070, -385, +317, 710, 2056, 678, -998, -158, -1697, -1172, +1715, -83, 981, 1777, -2406, 10, -148, -2082, +2486, 70, -608, 1879, -2089, 217, 898, -1282, +1424, -861, -1104, 432, -395, 1721, 835, 408, +-434, -2612, -330, -841, 774, 3035, 58, 969, +-701, -2925, 120, -984, 388, 2563, 58, 738, +63, -1859, -333, -704, -171, 989, 537, 1209, +301, -401, -653, -2113, -265, 167, 802, 3059, +154, -134, -851, -3796, -267, 187, 1172, 3987, +267, -308, -1580, -3260, -281, 161, 1810, 1894, +307, 326, -2262, -403, 92, -884, 2086, -748, +-663, 1223, -1638, 1429, 1109, -1210, 1050, -1517, +-1534, 845, -531, 1132, 1562, -26, 599, -695, +-1593, -958, -1029, 410, 1792, 1813, 1444, -224, +-1844, -2553, -1479, 313, 1611, 2949, 1466, -622, +-1213, -2647, -1106, 563, 855, 2059, 468, -478, +-52, -1150, 23, 491, -800, -276, -92, -341, +1410, 1619, 111, 374, -2014, -2784, 208, -666, +1973, 3519, -271, 1014, -1702, -3509, 130, -1509, +836, 3024, 211, 1820, 399, -2240, -1140, -1489, +-1479, 1035, 1828, 876, 2322, 140, -2513, -77, +-2486, -760, 2544, -923, 2157, 993, -2135, 1904, +-1402, -877, 1291, -2422, 804, 251, -632, 2653, +-31, 531, 188, -2381, -362, -1298, -307, 1404, +914, 2411, 1030, -498, -1709, -3141, -1691, -603, +2715, 3283, 2194, 1873, -3665, -3163, -1990, -2718, +3870, 2309, 1754, 3096, -3565, -855, -1403, -3328, +2710, -579, 919, 3109, -1373, 1556, -770, -2513, +-268, -1936, 1311, 1859, 913, 1576, -1870, -1285, +-1003, -796, 2239, 1102, 559, -33, -2588, -1246, +-8, 363, 2773, 1881, -289, 45, -3028, -2666, +167, -910, 3324, 3179, 379, 2093, -3359, -3070, +-1287, -3255, 3368, 2448, 2158, 4047, -2921, -1575, +-2456, -3982, 1876, 501, 2622, 3435, -504, 284, +-2274, -2771, -953, -571, 1824, 2131, 2207, 449, +-1170, -1781, -3193, -305, 552, 1633, 3807, 478, +26, -1653, -4284, -1181, -523, 1558, 4435, 1920, +785, -1025, -4266, -2410, -1113, -46, 3573, 2327, +1293, 1355, -2561, -1433, -1440, -2670, 1157, 244, +1437, 3304, 96, 927, -1149, -2830, -1249, -1806, +762, 1791, 2028, 2197, -440, -545, -2256, -1877, +262, -581, 2193, 1555, -17, 1166, -2065, -1577, +-39, -979, 2177, 2185, 166, 159, -2220, -2848, +-416, 773, 2375, 2789, 676, -834, -1894, -2254, +-1090, 62, 917, 1140, 1409, 1021, 654, 438, +-1610, -2142, -2464, -2118, 1536, 2730, 3805, 3286, +-1087, -2753, -4653, -3645, 374, 1939, 4531, 3252, +306, -546, -3681, -2652, -1037, -729, 2175, 1919, +1759, 1566, -860, -1149, -2278, -1828, -163, 481, +2427, 1526, 825, 326, -2243, -626, -979, -1285, +1551, -224, 1017, 2006, -366, 1098, -988, -2115, +-631, -1884, 655, 1817, 1704, 2252, -124, -906, +-2179, -1982, -406, -328, 1908, 1088, 1248, 1585, +-1242, -162, -1684, -2272, 312, -531, 1708, 1838, +450, 995, -1346, -761, -776, -1304, 755, -224, +397, 881, -326, 680, 357, -58, 215, -677, +-1506, -741, -416, -119, 2290, 1495, 679, 1206, +-2470, -2177, -1237, -1971, 2080, 2329, 1819, 2491, +-1435, -2205, -2263, -2508, 653, 2031, 2567, 1887, +66, -1315, -2470, -803, -596, 347, 1912, -417, +1059, 740, -652, 1734, -1382, -1499, -806, -2708, +1541, 1742, 2195, 3265, -1248, -1422, -2899, -3101, +683, 969, 2778, 1825, -157, -417, -1716, -151, +37, 145, 115, -1282, -375, -498, 987, 1918, +1334, 1049, -1476, -1706, -2320, -1454, 875, 769, +2694, 1025, 265, 325, -2333, -13, -1326, -1007, +1022, -1033, 1761, 689, 330, 1529, -1408, 390, +-943, -1195, 141, -1469, 774, 30, 1098, 1999, +114, 1463, -1528, -1468, -1233, -2401, 1217, 329, +1682, 2208, 53, 1050, -1294, -875, -1320, -1770, +537, -847, 1741, 1428, 524, 2522, -1226, -261, +-879, -3286, -3, -1108, 386, 2830, 1519, 2231, +372, -1792, -2171, -2515, -1215, 680, 2003, 1821, +1152, 115, -1034, -908, -320, -281, -209, 87, +-835, -375, 566, 441, 1849, 1003, -134, -595, +-2172, -1273, -945, 249, 1463, 1252, 1965, -153, +-215, -731, -2286, 199, -1005, 0, 1597, -319, +1695, 543, -310, 543, -1379, -680, -1031, -420, +502, 167, 1816, 416, 509, 682, -1556, -428, +-1230, -1288, 848, 372, 1350, 1925, -18, -374, +-861, -2188, -503, 387, 465, 2227, 423, -281, +-298, -2115, -135, 91, 658, 1636, -59, 395, +-1409, -969, 25, -1145, 1756, 303, 421, 1578, +-1691, 294, -935, -1713, 1008, -818, 927, 1435, +81, 737, -525, -602, -1121, -546, -217, -402, +1582, 394, 972, 962, -1617, -374, -1164, -1195, +1137, 807, 940, 1025, -627, -1588, -455, -378, +508, 2125, -101, -49, -363, -2060, 135, 142, +453, 1413, 305, 93, -494, -247, -692, -305, +369, -720, 799, 228, -3, 1265, -510, 248, +-254, -1230, 32, -703, 237, 575, 336, 933, +64, 293, -401, -932, -410, -792, 100, 661, +388, 677, 357, -617, -83, 21, -637, 692, +-417, -947, 352, -894, 699, 1274, 388, 1182, +-714, -971, -1014, -1442, 70, 359, 1280, 1125, +842, 335, -1054, -493, -1496, -714, 522, -66, +1425, 607, 131, 255, -745, -29, -305, 177, +-144, -812, -138, -589, 949, 1240, 923, 896, +-1147, -908, -1540, -879, 883, 297, 1488, 378, +-335, 527, -602, 375, -203, -1133, -566, -901, +313, 1092, 1429, 1252, 132, -689, -1942, -1187, +-374, 33, 1493, 777, 355, 560, -549, -339, +-210, -937, -109, -175, -318, 1070, 250, 424, +795, -932, -36, -541, -794, 432, -422, 675, +378, 5, 669, -827, 128, -111, -390, 578, +-439, 75, -210, -58, 396, 106, 766, -428, +-91, -375, -745, 765, -233, 579, 228, -640, +337, -586, 431, 190, 61, 417, -806, 455, +-699, 69, 732, -1080, 961, -375, 56, 1253, +-772, 429, -995, -742, 94, -512, 1482, 154, +835, 444, -1385, 301, -1505, -425, 828, -484, +1387, 676, -76, 22, -785, -928, -206, 535, +-259, 918, 59, -606, 1014, -934, 263, 182, +-877, 890, -802, 305, 316, -674, 850, -761, +625, 499, -648, 776, -1131, -493, 176, -266, +1226, 712, 9, -457, -740, -1128, 221, 1198, +90, 1370, -577, -1430, 169, -1256, 911, 1070, +169, 993, -984, -444, -720, -513, 574, -76, +1135, 81, 146, 313, -1147, 82, -726, -184, +638, 62, 830, -59, 28, -397, -356, 198, +-605, 643, -269, -122, 587, -627, 600, -108, +-12, 147, -474, 351, -641, 550, -241, -452, +839, -1240, 1339, 369, -569, 1530, -1991, -292, +-339, -1136, 2100, -11, 1143, 364, -1266, 407, +-1532, 285, -2, -642, 1302, -603, 1082, 701, +-485, 518, -1456, -576, -440, -104, 1029, 259, +983, -260, -121, 171, -666, 496, -1054, -623, +54, -474, 1563, 1005, 713, 336, -1300, -1124, +-1232, -262, 462, 899, 1270, 473, 403, -395, +-912, -967, -948, -6, 549, 1282, 851, 201, +-417, -1235, -303, -229, 576, 903, -365, -163, +-804, -289, 802, 745, 734, -488, -748, -1136, +-338, 998, 425, 1161, -272, -1170, -167, -784, +914, 999, 108, 183, -1195, -670, -218, 339, +931, 470, 507, -576, -456, -517, -500, 494, +-154, 690, 388, 11, 432, -937, -262, -661, +-154, 1322, 51, 989, -333, -1470, 100, -900, +537, 1440, -63, 402, -475, -1289, 212, 496, +-83, 907, -599, -1262, 815, -491, 1111, 1615, +-1316, 279, -1585, -1629, 1307, -179, 1674, 1253, +-654, 214, -1443, -718, -190, -420, 891, 395, +853, 534, -197, -406, -1128, -477, -244, 535, +982, 369, 308, -820, -468, -158, -202, 894, +86, -22, -61, -595, 297, -32, -49, 119, +-267, 74, 300, 624, 141, -267, -688, -1270, +41, 599, 1000, 1422, -284, -667, -1001, -1164, +409, 450, 820, 776, -570, -57, -510, -422, +558, -354, 379, 324, -524, 610, -318, -414, +169, -637, 522, 600, 174, 467, -715, -742, +-431, -205, 786, 791, 449, -98, -694, -746, +-182, 313, 516, 583, -177, -213, -414, -697, +597, 57, 129, 828, -400, 89, -24, -707, +-232, -410, 9, 440, 1064, 693, -51, -16, +-1651, -835, 92, -410, 1610, 786, -64, 494, +-935, -303, 6, -323, -126, -478, 51, 214, +1036, 1039, -85, -84, -1417, -1244, 174, 157, +866, 1103, -96, -567, 179, -540, -154, 1078, +-1086, -153, 301, -1227, 1482, 491, -343, 944, +-1224, -302, 278, -241, 445, -253, -122, -722, +324, 993, 76, 1457, -788, -1475, -79, -1738, +730, 1511, 19, 1411, -3, -1175, -176, -525, +-724, 452, 294, -429, 1083, 288, -169, 968, +-1098, -663, -34, -1063, 815, 715, 98, 654, +-347, -443, -53, -116, -90, 127, -54, -217, +281, -116, 134, 387, -192, 302, -249, -316, +77, -547, 219, 123, -79, 734, -53, -7, +222, -665, -204, 89, -412, 203, 485, -149, +422, 412, -606, 145, -352, -923, 755, -40, +32, 1158, -857, -144, 405, -993, 791, 240, +-656, 534, -570, -195, 527, 123, 193, -120, +-25, -741, 169, 665, -554, 1048, -596, -1278, +1034, -859, 883, 1595, -1288, 279, -871, -1441, +1140, 355, 585, 962, -770, -904, -98, -349, +270, 1268, -381, -333, 65, -1252, 802, 850, +-389, 917, -935, -1010, 576, -529, 720, 960, +-631, 304, -374, -808, 570, -292, 84, 631, +-515, 512, 52, -471, 497, -799, -154, 435, +-360, 787, -4, -284, 361, -449, 68, 23, +-379, -80, -144, 257, 415, 599, 201, -406, +-527, -854, -234, 224, 497, 878, 378, 135, +-503, -676, -546, -515, 477, 275, 499, 874, +-271, -20, -414, -1021, -49, 65, 296, 682, +239, -43, -105, -320, -366, -18, -65, 147, +335, -4, 106, -48, -97, -156, -114, 185, +-322, 345, 235, -413, 586, -482, -330, 548, +-720, 546, 478, -571, 454, -441, -342, 385, +-133, 295, -23, -120, -43, -210, 344, -5, +60, 112, -640, -3, 111, 5, 665, 96, +-354, -133, -625, -129, 684, 298, 186, -73, +-718, -379, 230, 495, 356, 251, -365, -927, +-70, -39, 377, 1158, -126, -74, -519, -1192, +317, 23, 472, 1032, -189, 158, -631, -792, +-58, -377, 893, 641, 62, 391, -918, -597, +-98, -114, 964, 636, -246, -404, -809, -717, +766, 1014, 330, 697, -996, -1397, -77, -535, +943, 1382, 61, 315, -741, -1054, -142, 2, +258, 581, 230, -403, 190, -126, -259, 762, +-423, -100, -60, -984, 398, 47, 471, 1034, +-267, 226, -832, -992, 7, -414, 957, 808, +-67, 396, -671, -492, 273, -245, 2, 197, +-505, -20, 528, 100, 628, 190, -797, -379, +-586, -124, 701, 531, 194, -71, -367, -593, +381, 199, -145, 693, -785, -253, 416, -676, +716, 103, -265, 494, -394, 301, -62, -274, +-188, -770, 319, 121, 664, 950, -296, 48, +-968, -769, 24, -303, 817, 449, 274, 479, +-374, -101, -609, -523, -78, -104, 578, 405, +269, 163, -351, -255, -198, 16, -123, 39, +-42, -264, 357, 169, 303, 461, -531, -310, +-385, -557, 510, 379, 79, 529, -321, -313, +142, -522, 227, 229, -382, 510, -147, -145, +252, -469, 123, 38, 14, 396, -37, 41, +-336, -240, -182, -53, 353, -92, 536, 106, +-159, 444, -888, -69, -282, -869, 1006, 67, +736, 1211, -1004, -164, -1017, -1185, 739, 87, +982, 1000, -539, 135, -782, -859, 366, -207, +394, 667, -327, 150, -128, -422, 106, -105, +137, 273, 61, 21, -386, -168, -442, -67, +736, 252, 674, 104, -1013, -380, -778, -125, +948, 448, 649, 123, -697, -461, -360, -87, +278, 490, -55, -43, 100, -569, 273, 301, +-278, 582, -334, -372, 120, -732, 295, 344, +30, 883, -105, -242, -320, -839, -7, -26, +396, 684, -85, 285, -272, -461, 99, -273, +74, 11, -258, 212, 69, 379, 332, -198, +-281, -434, -294, 66, 281, 355, 101, -8, +-326, -282, 116, 139, 276, 271, -476, -477, +-127, -291, 538, 833, -31, 271, -643, -899, +294, -313, 523, 637, -676, 511, -252, -391, +765, -503, 113, 89, -882, 258, 47, 387, +722, -145, -227, -671, -437, 164, 390, 584, +44, -51, -611, -402, 236, -135, 735, 352, +-385, 213, -838, -375, 408, -202, 576, 462, +-288, 100, -314, -528, 173, 27, -61, 543, +-292, -254, 334, -330, 387, 437, -487, -130, +-573, -396, 418, 574, 450, 210, -174, -892, +-311, 41, -90, 976, -112, -298, 378, -794, +236, 460, -479, 452, -319, -417, 401, -181, +251, 293, -447, 68, -85, -124, 497, -121, +-146, -46, -518, 330, 104, 104, 477, -508, +205, -11, -600, 537, -537, -297, 597, -182, +746, 574, -591, -398, -851, -622, 501, 762, +803, 642, -569, -871, -630, -684, 522, 789, +300, 646, -369, -591, -37, -495, -170, 297, +-31, 277, 558, 25, 60, -132, -1002, -242, +-140, 94, 1142, 229, 165, -10, -967, -132, +-402, -193, 641, 109, 465, 423, -235, -178, +-547, -571, -110, 233, 535, 593, 181, -114, +-481, -644, -87, -50, 310, 730, -19, 77, +-274, -661, 125, -7, 147, 407, -92, 5, +-92, -182, -102, 4, 51, 67, 169, -66, +48, -26, -303, 169, -156, -17, 278, -202, +172, 23, -277, 142, -121, 63, 122, -138, +-25, -101, -22, 98, 73, 126, -73, -24, +-112, -179, -14, -108, 109, 311, 66, 225, +-156, -519, -113, -264, 135, 685, 72, 191, +-148, -682, 23, -78, 32, 511, -93, -47, +0, -193, 185, 104, -84, -92, -276, -13, +122, 2, 276, 121, -114, 280, -202, -394, +-59, -481, 71, 571, 292, 481, 44, -388, +-597, -402, -56, -106, 623, 460, 51, 452, +-499, -474, -156, -333, 328, 142, 80, -13, +-161, 454, 51, 217, -30, -860, -249, -253, +1, 828, 639, 215, -220, -428, -864, -298, +499, 118, 664, 309, -533, -143, -486, 31, +512, 179, 195, -488, -305, 0, -90, 620, +127, -211, 36, -450, -20, 325, 129, 172, +-171, -294, -320, -64, 422, 162, 366, 375, +-504, -270, -352, -699, 325, 511, 456, 699, +-250, -447, -358, -599, 126, 148, 40, 593, +134, 67, 124, -524, -223, -100, -334, 269, +250, 40, 405, 281, -284, -281, -255, -624, +60, 673, 215, 406, 44, -500, -248, -320, +96, 137, 56, 424, -111, 38, 49, -393, +199, -218, -197, 350, -319, 232, 592, -149, +43, -223, -599, -174, 94, 432, 562, 160, +-133, -425, -514, -53, 278, 149, 289, 231, +-272, -107, -49, -341, 263, 239, -192, 177, +-93, -205, 229, 64, -37, -52, -72, -65, +78, 233, -151, -91, 70, -149, 195, 148, +-140, -28, -74, -99, 68, 178, 81, -19, +-156, -284, 185, 150, 85, 302, -352, -274, +92, -184, 355, 246, -263, 11, -90, -54, +375, 114, -284, -188, -282, -245, 500, 397, +386, 400, -669, -551, -445, -478, 756, 529, +484, 448, -578, -314, -434, -327, 268, 50, +330, 4, 289, 349, -296, 281, -689, -706, +343, -275, 860, 669, -314, 211, -685, -299, +223, -361, 438, 110, -83, 478, -91, -234, +-77, -253, -77, 325, 334, -81, -97, -234, +-269, 144, 431, 326, -5, -182, -547, -610, +408, 591, 292, 435, -352, -749, -53, -57, +265, 518, -61, -208, -265, -244, 399, 577, +258, -179, -556, -922, -367, 657, 930, 961, +263, -714, -896, -950, -129, 468, 679, 922, +279, -257, -618, -481, -55, -244, 431, 188, +-55, 592, -247, -134, 351, -413, -125, -25, +-147, 109, 272, 290, -160, -100, 78, -296, +131, 326, -118, -28, -88, -383, 269, 286, +-44, 274, -219, -251, 219, -171, 226, 109, +-272, 212, -139, -316, 201, 52, 244, 566, +71, -482, -411, -530, -104, 517, 536, 576, +33, -393, -245, -691, 71, 438, 37, 504, +-171, -424, 155, -281, 505, 499, -252, 54, +-584, -684, 238, 391, 485, 464, 186, -611, +-241, 74, -593, 345, 230, -428, 809, 47, +-181, 409, -596, -193, 281, -202, 217, 131, +-218, -197, 198, 326, 212, 337, -321, -832, +10, -78, 155, 1103, -50, -366, 153, -1258, +326, 1148, -423, 980, -535, -1961, 990, -71, +270, 2119, -897, -1030, 205, -1368, 485, 1529, +-393, 390, 78, -1408, 559, 306, -609, 1077, +-192, -911, 916, -332, -282, 1291, -697, -942, +647, -874, 554, 1885, -767, -55, -163, -1956, +599, 824, 17, 1271, -127, -1080, 104, -281, +-281, 970, -68, -735, 780, -494, -105, 1476, +-796, -418, 413, -1300, 570, 1136, -512, 467, +15, -1343, 480, 450, -516, 1169, 52, -1130, +677, -621, -399, 1393, -487, -402, 654, -693, +455, 1167, -730, -528, -207, -1167, 586, 1217, +351, 915, -358, -1208, -294, -817, 24, 981, +593, 575, 220, -630, -801, 50, -10, -170, +922, -468, -289, 1026, -624, 455, 529, -1518, +432, -106, -501, 1454, -151, -184, 419, -1161, +-25, 350, 80, 889, 36, -467, -293, -659, +-22, 544, 702, 373, -200, -416, -451, -128, +272, 97, 314, 119, -300, 18, 102, 40, +368, -149, -404, -162, -167, 256, 687, 159, +-77, -184, -511, -112, 326, -31, 343, 111, +-182, 242, -332, -55, 314, -570, 336, 112, +-80, 917, -397, -393, -19, -984, 549, 634, +154, 860, -322, -799, -278, -462, 141, 586, +605, 126, -112, -216, -290, 113, -144, -185, +182, -346, 493, 749, -100, 218, -393, -1157, +-11, 271, 422, 1014, 143, -608, -264, -592, +-77, 616, 168, 363, 192, -717, -65, -17, +-126, 774, 50, -645, 462, -226, -262, 1017, +-579, -755, 845, -581, 402, 1360, -963, -298, +-34, -1194, 927, 976, -286, 542, -283, -1259, +415, 309, -260, 1179, -308, -1260, 900, -554, +208, 1867, -1271, -542, 276, -1573, 1195, 1479, +-544, 341, -455, -1548, 513, 1049, -235, 792, +-7, -1892, 664, 265, -314, 1918, -666, -1153, +762, -1133, 231, 1494, -645, -124, 348, -1221, +519, 1340, -588, 525, -511, -2042, 1109, 160, +412, 2121, -1125, -646, -203, -1545, 927, 587, +387, 890, -738, -193, -258, -589, 640, -156, +286, 665, -595, 481, 18, -1376, 666, -328, +-286, 2098, -304, -224, 391, -2151, 93, 555, +-258, 1443, 417, -290, 42, -493, -673, -413, +298, -320, 1049, 1187, -689, 678, -831, -1803, +1102, -274, 244, 1571, -862, -306, 511, -764, +547, 695, -1159, -295, 345, -789, 1300, 1444, +-819, 201, -869, -2043, 968, 668, 467, 1854, +-708, -1344, 403, -992, -13, 1398, -930, -187, +1366, -706, 863, 1019, -2214, -372, -97, -1125, +2396, 1103, -392, 783, -2042, -1503, 1297, -91, +894, 1590, -1170, -1034, 158, -1091, 923, 1804, +-634, 329, -454, -1857, 938, 89, -11, 1420, +-537, -238, 433, -819, 105, 429, -537, -90, +638, -517, 182, 953, -465, 312, 0, -1345, +512, 75, -306, 1016, -38, -451, 613, -233, +-194, 732, -721, -768, 558, -880, 749, 1654, +-527, 693, -327, -2020, 243, -321, 184, 1820, +128, -302, 386, -1100, -548, 1020, -478, 38, +863, -1762, 666, 1115, -826, 2101, -450, -1858, +837, -1978, -6, 1714, -198, 1535, 563, -742, +-367, -1199, -602, -446, 622, 828, 998, 1227, +-612, -187, -1068, -1783, 660, -345, 1168, 1812, +-496, 542, -909, -1400, 617, -557, 634, 857, +-558, 382, -239, -602, 848, -126, 69, 671, +-908, -123, 46, -1096, 1271, 357, -7, 1299, +-1191, -330, 107, -1353, 1147, 110, -29, 1186, +-837, -51, 309, -710, 730, -76, -595, 233, +-275, 97, 988, -35, 50, -109, -853, 240, +30, -227, 1007, -407, -24, 456, -708, 433, +10, -599, 970, -417, -65, 818, -1168, 10, +455, -1095, 1695, 691, -497, 1204, -2289, -1516, +746, -1182, 3102, 2058, -800, 1150, -3332, -2555, +1014, -996, 3243, 2787, -952, 615, -2361, -2776, +1030, -175, 1246, 2333, -552, -186, -2, -1660, +209, 178, -895, 863, 783, -8, 1501, -45, +-1833, -318, -1190, -949, 2904, 872, 826, 1589, +-3367, -1348, -141, -1949, 3493, 1448, -260, 2056, +-2635, -1507, 573, -1747, 1604, 1288, -290, 1228, +-571, -1229, 225, -638, 380, 1302, -190, 88, +-612, -1710, 833, 345, 1231, 2117, -1304, -722, +-1458, -2403, 1905, 965, 1431, 2336, -2079, -1449, +-426, -1750, 2225, 1921, -923, 713, -1797, -2430, +2626, 426, 1197, 2630, -3378, -1382, -245, -2485, +3379, 1741, -363, 1949, -2297, -1564, 997, -1353, +1258, 999, -1336, 798, -23, -549, 1704, -555, +-502, 488, -1549, 298, 888, -708, 1199, -221, +-676, 873, -304, 450, 519, -1296, -96, -605, +-503, 1521, 624, 370, 944, -1326, -585, -132, +-1074, 918, 361, -251, 1291, -734, 367, 743, +-878, 783, -1073, -1380, 697, -1325, 1880, 2073, +-386, 1954, -1862, -2732, 205, -2621, 1910, 2985, +140, 3195, -1388, -3129, -366, -3509, 1017, 2966, +1180, 3300, -422, -2431, -2098, -3016, 387, 1561, +3379, 2696, -357, -671, -4157, -2601, 806, -116, +4779, 2547, -1091, 461, -4561, -2471, 1572, -534, +4399, 2068, -1970, 394, -3450, -1449, 2316, -459, +2755, 701, -2108, 585, -1956, 17, 2095, -952, +1491, -777, -1666, 1368, -972, 1324, 1678, -1843, +851, -1557, -1665, 1831, -470, 1353, 2080, -1311, +482, -962, -2302, 220, -250, 339, 2775, 1047, +94, 161, -2352, -2223, 49, -676, 2104, 3086, +-1, 693, -1265, -3414, 4, -487, 909, 3030, +358, 286, -616, -2547, -359, -196, 825, 1955, +636, 166, -950, -1407, -301, -519, 1036, 893, +353, 978, -852, -617, 246, -1340, 615, 275, +-571, 1190, 62, 162, 993, -709, -270, -827, +-844, -44, 350, 1278, 836, 779, 263, -1450, +-584, -1569, -692, 1202, 735, 2111, 1166, -869, +-406, -2293, -1419, 349, 578, 1897, 1776, 164, +-564, -1338, -1542, -483, 693, 436, 1467, 348, +-331, 650, -908, -144, -89, -1726, 788, -295, +633, 2438, -151, 836, -743, -2959, -214, -1416, +696, 3074, 1003, 1578, -5, -2654, -1325, -1665, +-860, 1923, 1909, 1229, 2111, -1150, -2122, -253, +-2669, 85, 2317, -969, 3066, 582, -2070, 2348, +-2481, -1114, 1837, -3468, 1893, 1099, -1444, 3903, +-685, -678, 1494, -3698, -296, -44, -1487, 2534, +1543, 820, 1914, -879, -2249, -1588, -2254, -936, +3250, 1971, 2604, 2114, -3654, -1674, -2305, -2936, +3971, 1004, 1908, 3004, -3456, -512, -1148, -2282, +2948, -27, 858, 1262, -2349, 44, -56, -475, +1780, 470, 97, -224, -1264, -1090, -70, 308, +1099, 1243, 791, 349, -784, -1107, -1458, -1537, +710, 488, 2452, 2681, -30, 331, -3095, -3519, +-783, -1333, 4025, 3789, 2024, 1961, -4495, -3608, +-2696, -2081, 4646, 2721, 3552, 1791, -4218, -1565, +-3552, -1701, 3507, 665, 3578, 1623, -2328, -221, +-2959, -1840, 1240, -116, 2523, 2527, 189, 64, +-1878, -3453, -1189, -57, 1506, 4043, 2396, 187, +-918, -3963, -3035, -884, 510, 3072, 3638, 1726, +343, -1741, -3616, -2261, -895, -46, 3416, 2102, +1579, 1599, -2514, -1303, -1687, -2592, 1586, -77, +1854, 2719, -426, 1330, -1584, -2209, -73, -2128, +1368, 1186, 777, 2354, -1220, -545, -917, -2270, +1630, 584, 1194, 1992, -1794, -1382, -1350, -1942, +2040, 2230, 1863, 2300, -1541, -2723, -2078, -3123, +756, 2575, 2303, 3546, 545, -1742, -1647, -3142, +-1594, 232, 688, 1680, 2498, 1381, 923, 207, +-2512, -2530, -2307, -2143, 2243, 2714, 3539, 3589, +-1313, -2276, -4060, -4313, 792, 1515, 4034, 3960, +15, -717, -3474, -2994, -267, -135, 2877, 1825, +649, 658, -1886, -774, -820, -1014, 1267, -127, +934, 955, -274, 807, -607, -518, -413, -1499, +217, -270, 1103, 1877, 628, 1140, -1079, -1921, +-1258, -1826, 734, 1305, 1886, 1975, 156, -267, +-1728, -1700, -813, -686, 1208, 758, 1307, 1076, +-25, 480, -1032, -922, -999, -1572, 692, 212, +1597, 1848, 277, 879, -1538, -1615, -736, -1890, +1161, 1113, 938, 1931, -200, -395, -581, -1203, +-394, -459, -40, 9, 1128, 1138, 950, 1109, +-1461, -1680, -1499, -1976, 1714, 2006, 2125, 2242, +-1414, -2066, -2536, -2164, 1235, 1670, 2786, 1785, +-496, -1121, -2513, -1055, -166, 363, 1964, -112, +833, 348, -574, 1298, -1211, -780, -462, -2169, +1001, 589, 1559, 2289, -312, 37, -1644, -1735, +-304, -710, 1118, 647, 830, 809, -158, 506, +-304, -457, -600, -1131, -508, -132, 738, 655, +1690, 566, 121, 571, -2231, -691, -1267, -1762, +2126, 254, 2406, 2034, -1251, 414, -2402, -1225, +324, -832, 1508, -415, 382, 479, 49, 1979, +-9, 510, -1236, -2615, -1040, -1723, 1895, 1734, +2176, 2499, -1241, 202, -2465, -2460, -106, -2324, +2077, 1488, 1509, 3511, -808, -48, -2093, -3415, +-144, -1189, 1700, 2114, 557, 1611, -435, -362, +51, -1328, -574, -1009, -1130, 685, 1087, 1359, +2019, -223, -492, -879, -1804, 270, -522, 24, +608, -990, 1480, 718, 1359, 1724, -1547, -870, +-2807, -2122, 714, 296, 3325, 1998, 774, 391, +-2391, -1300, -1975, -851, 787, 169, 2470, 938, +828, 748, -1786, -690, -1445, -1104, 496, 38, +1157, 934, 933, 649, -194, -629, -1472, -1046, +-768, 263, 1476, 1029, 1101, 36, -892, -854, +-391, -239, 255, 520, -429, 390, -74, -99, +1178, -714, 441, -437, -1091, 1269, -879, 885, +349, -1913, 1108, -1067, 839, 2160, -652, 962, +-1755, -1854, -53, -741, 2019, 1118, 822, 440, +-1314, -332, -1248, -214, 386, -187, 1250, 103, +290, 229, -560, -170, -477, 76, -53, 262, +172, -382, 475, -316, 411, 316, -414, 227, +-779, 101, 290, 87, 817, -703, -382, -703, +-141, 1195, 639, 1353, -507, -1376, -955, -1686, +857, 1095, 1297, 1566, -748, -678, -1222, -990, +424, 466, 831, 188, -168, -739, -36, 561, +123, 1238, -567, -961, -110, -1480, 645, 775, +171, 1181, -130, -267, -69, -345, -366, -117, +-285, -784, 599, 70, 729, 1638, -162, 372, +-850, -1713, -712, -1055, 530, 1008, 1606, 1471, +319, 234, -2004, -1553, -1110, -1334, 1655, 1343, +1496, 1591, -621, -972, -1217, -913, -367, 594, +415, -274, 817, -404, 611, 1320, -564, 435, +-1145, -1877, -136, -391, 993, 1715, 851, 80, +-273, -1044, -980, 505, -574, 168, 681, -1065, +843, 464, 97, 1293, -458, -686, -739, -1021, +-234, 516, 788, 321, 1074, -150, -489, 531, +-1355, -329, 141, -1180, 1072, 846, -131, 1330, +-359, -1171, 496, -1191, -206, 1272, -964, 1044, +288, -1163, 1257, -948, -144, 727, -735, 869, +-93, 123, -302, -891, -52, -985, 1440, 839, +739, 1428, -2110, -537, -1476, -1264, 1713, -6, +2031, 670, -563, 564, -1797, -67, -821, -814, +897, -316, 1683, 711, 282, 418, -1536, -538, +-1151, -205, 634, 422, 1266, -155, 335, -344, +-334, 336, -918, 333, -967, -366, 701, -284, +1997, 479, 209, 65, -2325, -818, -1127, 295, +1786, 1273, 1677, -429, -1004, -1775, -1263, 164, +237, 2127, 330, 400, -11, -2109, 753, -982, +270, 1755, -1494, 1151, -571, -1237, 1489, -663, +848, 733, -1227, -195, -620, -536, 824, 1009, +210, 685, -627, -1433, 116, -844, 593, 1225, +89, 694, -684, -534, -681, -112, 662, -255, +1279, -578, -284, 555, -1617, 1020, -50, -124, +1228, -976, 270, -797, -358, 542, -48, 1526, +-643, 150, -426, -1660, 1150, -684, 824, 1178, +-682, 661, -1075, -220, -257, -157, 711, -688, +1230, -516, 229, 1135, -1795, 995, -1154, -950, +1446, -1114, 1751, 376, -455, 938, -1626, 160, +-737, -633, 962, -250, 1366, 222, 47, 8, +-1216, 118, -820, 315, 394, -263, 1102, -584, +458, 336, -700, 669, -865, -419, -147, -494, +675, 374, 869, 333, 96, -146, -1232, -385, +-864, -148, 997, 428, 1346, 670, -504, -411, +-1193, -1246, -127, 286, 802, 1538, 390, 63, +-276, -1412, -417, -480, -14, 934, 427, 631, +-136, -154, -544, -494, 572, -557, 682, 218, +-778, 816, -940, 75, 634, -568, 1134, -172, +-282, 43, -1029, -7, -144, 444, 772, 421, +112, -762, -125, -696, -80, 797, -160, 604, +-298, -610, 291, -22, 521, 316, -295, -841, +-361, 65, 234, 1518, -47, -311, -440, -1718, +568, 387, 758, 1464, -772, -397, -1160, -840, +583, 522, 1179, 69, 72, -710, -861, 655, +-788, 883, 169, -1115, 1211, -829, 606, 1264, +-1264, 530, -1097, -1049, 955, -115, 1032, 733, +-475, -177, -614, -488, 75, 253, 148, 480, +31, -43, 23, -670, 141, -221, 16, 882, +-244, 525, -331, -971, 186, -695, 560, 947, +33, 669, -490, -680, -364, -485, 164, 292, +482, 337, 382, 93, -549, -200, -697, -328, +406, 174, 707, 486, -197, -246, -583, -509, +109, 413, 559, 491, -254, -448, -715, -501, +456, 321, 995, 740, -443, -127, -1290, -914, +99, -76, 1492, 990, 364, 261, -1375, -845, +-701, -283, 914, 563, 845, 306, -391, -265, +-798, -263, 187, 113, 599, 364, -327, -49, +-412, -627, 635, 121, 511, 1066, -872, -194, +-827, -1303, 877, 118, 1164, 1370, -612, 195, +-1124, -1243, 198, -381, 703, 1021, 133, 326, +42, -630, -204, 26, -618, 269, -12, -309, +832, -14, 389, 317, -505, 60, -557, 197, +-179, -316, 520, -908, 864, 601, -218, 1646, +-1147, -559, -17, -1991, 856, 281, 135, 1781, +-19, 250, -54, -887, -767, -847, -131, -177, +1176, 1432, 494, 1012, -1139, -1668, -614, -1205, +802, 1636, 465, 892, -212, -1329, -119, -275, +-184, 1092, -150, -195, 314, -878, 315, 388, +-100, 764, -226, -118, -172, -533, 95, -375, +371, 340, 157, 863, -389, -84, -275, -901, +443, -155, 206, 661, -367, 418, -6, -254, +410, -386, -193, -30, -386, 192, 298, 242, +453, 167, -306, -185, -406, -458, 362, 82, +233, 735, -295, 162, -67, -882, 285, -302, +28, 1036, -215, 475, -168, -992, 147, -569, +455, 853, 8, 814, -770, -501, -176, -992, +999, 175, 313, 1092, -999, 242, -395, -924, +831, -488, 383, 666, -611, 628, -262, -239, +288, -447, 186, -137, -37, 268, -289, 503, +-100, -71, 372, -605, 193, 92, -519, 602, +-286, -108, 426, -385, 326, 128, -151, 268, +-493, 133, -308, -151, 463, -484, 786, 231, +-564, 977, -1209, -281, 615, -1258, 1211, 496, +-842, 1303, -1059, -645, 960, -871, 644, 862, +-1166, 285, -537, -832, 1146, 314, 430, 780, +-1068, -496, -730, -559, 589, 441, 920, 419, +-201, -97, -1231, -127, -384, -197, 1173, -64, +491, 530, -1128, 293, -578, -591, 666, -390, +310, 685, -576, 471, -195, -591, 260, -368, +-183, 610, -244, 305, 84, -558, -82, -38, +-173, 611, 79, -180, -134, -477, -309, 483, +-93, 366, 231, -552, -111, -112, -328, 610, +-50, 5, -179, -446, -162, 150, 260, 309, +53, -62, -637, -16, -418, -87, 365, -75, +325, 415, -345, 194, -581, -617, -247, -56, +344, 722, 171, 29, -424, -496, -393, 69, +-8, 257, -122, -102, -27, 253, 178, 268, +-468, -705, -508, -188, 199, 1052, 183, 97, +-387, -832, -194, 123, -72, 391, -532, -248, +187, 366, 567, 473, -915, -920, -965, -530, +938, 1341, 598, 541, -1304, -1240, -700, -266, +729, 909, 246, 14, -552, -281, -418, 329, +-331, -156, -14, -406, 517, 495, -191, 433, +-1082, -409, -240, -266, 721, 261, 51, 340, +-829, -16, -463, -427, 338, 10, 67, 832, +-522, -73, -304, -1129, 253, 380, -126, 1403, +-689, -630, -144, -1109, 372, 882, -103, 492, +-556, -752, -310, 459, -105, 575, 77, -1207, +145, -227, -312, 1755, -810, 71, -147, -1730, +645, 143, -85, 1360, -791, -111, -265, -576, +146, 69, -139, -55, -139, 166, 87, 541, +-416, -185, -678, -638, 189, 268, 618, 681, +-575, -137, -906, -573, 275, 206, 438, 542, +-579, -155, -512, -364, 442, 247, -225, 281, +-639, -259, 273, 54, 212, 369, -945, -316, +-147, -334, 981, 706, -460, 397, -1438, -828, +266, -359, 1318, 917, -431, 487, -1415, -691, +-263, -549, 846, 549, 498, 682, -654, -265, +-1006, -606, -89, 189, 774, 488, 169, -40, +-665, -140, -506, 70, -45, -73, 195, -30, +181, 392, -196, 94, -556, -476, -144, 68, +265, 533, -98, -184, -292, -279, 59, 378, +39, 159, -445, -412, -405, 77, 447, 465, +350, -151, -417, -262, -704, 401, -193, -62, +602, -432, 470, 574, -569, 471, -971, -806, +64, -285, 929, 891, 89, 93, -926, -516, +-293, 295, 323, 58, 118, -602, -35, 590, +-62, 909, -432, -907, -232, -909, 397, 1009, +249, 869, -514, -662, -430, -631, 398, 341, +284, 480, -612, 66, -280, -293, 679, -104, +-25, 282, -914, 23, 125, -176, 921, 303, +-498, 148, -939, -478, 575, 105, 715, 588, +-745, -292, -616, -389, 545, 665, 319, 113, +-300, -818, -242, 323, -164, 939, -57, -533, +436, -787, 257, 672, -745, 705, -568, -588, +700, -449, 650, 537, -715, 289, -566, -337, +462, -18, 194, 227, -450, -94, 146, -4, +481, 277, -663, -69, -615, -360, 779, 300, +646, 497, -825, -454, -626, -428, 526, 717, +403, 359, -437, -775, -151, -129, 343, 817, +-224, -18, -502, -535, 335, 224, 566, 181, +-404, -215, -552, 374, 75, 151, 322, -667, +63, 55, 43, 853, -317, -114, -570, -751, +392, 280, 682, 622, -405, -268, -699, -442, +223, 378, 393, 480, -265, -382, -97, -533, +237, 513, -320, 658, -309, -559, 409, -488, +243, 658, -524, 159, -290, -599, 491, 426, +125, 639, -654, -900, -118, -585, 658, 1248, +59, 619, -763, -1117, -281, -543, 557, 720, +416, 578, -401, -95, -625, -538, -40, -298, +562, 580, 228, 515, -538, -566, -413, -332, +265, 623, 219, 136, -254, -548, -36, 82, +67, 463, -259, -22, -156, -133, 179, -111, +43, -233, -116, 394, -87, 690, -193, -519, +-215, -862, 287, 596, 245, 788, -386, -481, +-344, -259, 21, 360, 105, -349, 190, -166, +80, 926, -598, 113, -459, -1123, 560, -21, +529, 1045, -578, -16, -656, -580, 268, 130, +373, 94, -206, -79, -267, 339, 5, -11, +-56, -427, -157, 268, 57, 364, 128, -468, +-245, -134, -318, 659, 189, -2, 129, -592, +-335, 124, -144, 409, 242, -115, -170, -25, +-320, 160, 205, -258, 57, -137, -404, 416, +-64, 182, 317, -228, -187, -107, -388, -97, +-26, 47, 262, 485, 53, 160, -351, -629, +-380, -347, 108, 608, 465, 460, -88, -272, +-678, -353, -209, -140, 462, 212, 249, 544, +-396, -18, -476, -638, 67, -67, 316, 521, +-67, 166, -261, -205, -141, -138, -93, -62, +58, 153, 88, 262, -110, -88, -299, -254, +-116, 56, 241, 198, 43, 52, -413, -39, +-176, -127, 277, -25, 119, 271, -452, 21, +-231, -284, 306, 109, 81, 219, -287, -141, +-143, -30, -141, 105, 21, -109, 417, 146, +-214, 198, -832, -460, 161, -133, 920, 827, +-389, 84, -954, -1085, 321, -38, 567, 1203, +-389, 118, -230, -979, 86, -313, -303, 563, +92, 626, 497, -31, -497, -759, -693, -421, +566, 684, 556, 774, -717, -352, -504, -866, +520, -9, 236, 732, -409, 327, -246, -382, +154, -436, 131, 50, -161, 406, -301, 130, +146, -195, 283, -42, -313, 20, -558, -220, +369, 16, 618, 722, -493, 121, -789, -1240, +259, -300, 828, 1605, -140, 560, -956, -1624, +-105, -816, 760, 1359, 228, 1027, -686, -772, +-401, -1078, 396, 46, 317, 1016, -155, 681, +-400, -752, -160, -1159, 263, 339, 313, 1375, +-248, 213, -484, -1307, 40, -703, 410, 1058, +141, 1084, -420, -663, -476, -1296, 321, 282, +624, 1442, -335, 45, -850, -1430, 328, -340, +783, 1371, -405, 730, -704, -1239, 244, -1086, +533, 976, -143, 1432, -427, -480, -125, -1659, +265, -95, 246, 1660, -218, 684, -323, -1296, +129, -1171, 86, 777, -87, 1419, 145, -172, +55, -1331, -534, -387, -10, 1101, 553, 815, +33, -814, -419, -1004, -215, 575, 110, 1044, +257, -328, 258, -989, -375, 80, -479, 937, +306, 208, 477, -870, -270, -471, -190, 758, +-3, 732, -132, -575, 220, -913, 307, 415, +-393, 978, -326, -286, 451, -913, 143, 209, +-443, 867, -12, -168, 447, -860, -127, 159, +-354, 918, -52, -54, 247, -940, 440, -154, +-217, 834, -862, 518, 203, -509, 1109, -911, +-203, 2, -1165, 1208, 300, 650, 1008, -1271, +-554, -1261, -692, 1087, 828, 1734, 405, -690, +-946, -1942, -358, 220, 883, 1898, 455, 260, +-445, -1616, -694, -664, -168, 1232, 813, 1001, +841, -827, -669, -1208, -1334, 456, 435, 1401, +1200, -195, 101, -1570, -599, 142, -551, 1671, +-347, -186, 855, -1640, 1277, 203, -829, 1513, +-1852, -72, 613, -1231, 1976, -229, -424, 829, +-1463, 663, 215, -313, 854, -1049, -68, -208, +-464, 1278, 69, 647, 453, -1183, 43, -923, +-775, 816, -273, 1061, 1284, -276, 700, -1106, +-1630, -214, -1129, 1055, 1761, 622, 1377, -919, +-1399, -897, -1490, 743, 913, 1056, 1411, -464, +-243, -1063, -1235, 120, -401, 890, 1124, 330, +1063, -552, -943, -744, -1755, 159, 810, 994, +2373, 241, -451, -926, -2759, -584, -106, 728, +2754, 753, 1004, -470, -2375, -608, -1793, 212, +1520, 327, 2515, 19, -427, -57, -2859, -97, +-578, -87, 2754, 86, 1476, 166, -2342, -56, +-1901, -160, 1618, 82, 2183, 165, -893, -122, +-2110, -176, 165, 119, 2013, 197, 580, 17, +-1941, -138, -1105, -277, 1718, -1, 1809, 587, +-1507, 281, -2356, -818, 1184, -630, 2832, 901, +-556, 918, -3232, -755, -61, -1013, 3380, 414, +844, 884, -3246, 104, -1569, -634, 2871, -584, +2235, 378, -2186, 904, -2669, -122, 1287, -1038, +2911, -59, -174, 1055, -2863, 158, -918, -977, +2599, -215, 1986, 871, -2170, 327, -2675, -804, +1567, -475, 3169, 795, -905, 641, -3218, -783, +162, -774, 3095, 673, 693, 910, -2800, -397, +-1462, -1056, 2376, 38, 2309, 1149, -1901, 368, +-2840, -1072, 1252, -776, 3219, 841, -437, 1168, +-3162, -493, -513, -1434, 2797, 23, 1661, 1652, +-2163, 572, -2652, -1882, 1341, -1141, 3586, 2080, +-541, 1659, -4001, -2097, -200, -2070, 4075, 1890, +870, 2315, -3691, -1413, -1321, -2349, 3044, 753, +1795, 2234, -2224, -50, -2140, -2002, 1393, -615, +2668, 1758, -565, 1222, -3084, -1502, -189, -1799, +3454, 1214, 1103, 2345, -3476, -783, -1965, -2772, +3133, 135, 2948, 3008, -2289, 688, -3618, -2931, +1116, -1542, 4158, 2527, 232, 2263, -4183, -1821, +-1326, -2751, 3814, 991, 2331, 2933, -3017, -152, +-2798, -2818, 1979, -717, 3193, 2525, -771, 1623, +-3210, -2165, -342, -2517, 3228, 1785, 1466, 3313, +-3051, -1344, -2173, -3898, 2727, 836, 2923, 4163, +-2181, -253, -3194, -4057, 1415, -420, 3546, 3600, +-437, 1188, -3486, -2910, -490, -1987, 3317, 2109, +1595, 2707, -2876, -1299, -2244, -3241, 2255, 526, +3001, 3526, -1494, 160, -3305, -3584, 817, -782, +3662, 3494, -72, 1431, -3704, -3320, -468, -2126, +3694, 3027, 1280, 2894, -3372, -2522, -1882, -3649, +2809, 1759, 2755, 4218, -1821, -765, -3315, -4435, +769, -316, 3798, 4232, 447, 1333, -3706, -3690, +-1320, -2116, 3387, 2895, 2160, 2664, -2682, -2007, +-2472, -3074, 1932, 1139, 2857, 3420, -1006, -341, +-2945, -3751, 245, -375, 3152, 3957, 733, 1103, +-3178, -3959, -1360, -1883, 3091, 3679, 2147, 2657, +-2598, -3112, -2541, -3351, 1989, 2308, 2843, 3913, +-932, -1425, -2795, -4242, 29, 534, 2691, 4267, +1041, 420, -2376, -4055, -1758, -1469, 2178, 3674, +2520, 2508, -1806, -3139, -2935, -3450, 1494, 2381, +3335, 4173, -790, -1454, -3346, -4600, -48, 409, +3275, 4674, 1201, 646, -2813, -4390, -2112, -1683, +2196, 3879, 2973, 2620, -1378, -3285, -3221, -3392, +638, 2667, 3280, 3878, 120, -2001, -2942, -4058, +-606, 1176, 2613, 3988, 1133, -274, -2155, -3726, +-1470, -626, 1812, 3286, 1942, 1426, -1377, -2753, +-2232, -2188, 949, 2261, 2603, 2908, -331, -1894, +-2808, -3571, -209, 1530, 2921, 4039, 929, -997, +-2775, -4236, -1604, 171, 2550, 4092, 2250, 799, +-1959, -3607, -2734, -1689, 1232, 2793, 3173, 2266, +-371, -1827, -3287, -2512, -459, 914, 3229, 2421, +1263, -225, -2876, -2108, -1881, -294, 2393, 1684, +2371, 749, -1742, -1311, -2675, -1218, 1034, 957, +2974, 1735, -320, -612, -3178, -2221, -296, 131, +3294, 2460, 937, 530, -3222, -2383, -1572, -1310, +2953, 1932, 2197, 2010, -2358, -1281, -2816, -2430, +1611, 537, 3203, 2548, -676, 102, -3379, -2442, +-226, -644, 3305, 2222, 930, 1129, -2935, -2028, +-1475, -1619, 2498, 1784, 1699, 2082, -1926, -1409, +-1915, -2488, 1430, 828, 2176, 2766, -1096, -145, +-2480, -2915, 741, -577, 2953, 2986, -562, 1214, +-3186, -3076, 128, -1738, 3276, 3199, 358, 2103, +-3045, -3298, -885, -2355, 2493, 3203, 1337, 2545, +-1887, -2821, -1482, -2829, 1255, 2189, 1501, 3176, +-961, -1546, -1285, -3490, 782, 978, 1216, 3654, +-876, -618, -1094, -3650, 837, 421, 1062, 3485, +-652, -420, -943, -3151, 328, 423, 683, 2670, +83, -399, -373, -2115, -244, 334, -76, 1452, +392, -309, 392, -759, -347, 374, -606, -78, +406, -454, 760, 916, -577, 401, -745, -1710, +864, -138, 746, 2275, -1147, -305, -579, -2613, +1327, 816, 405, 2715, -1237, -1382, -138, -2586, +1207, 1799, -221, 2216, -958, -2004, 513, -1721, +884, 1918, -550, 1256, -732, -1634, 358, -1007, +601, 1208, 326, 1069, -320, -787, -1068, -1368, +23, 334, 1996, 1711, 288, 101, -2449, -1996, +-451, -549, 2830, 2140, 528, 923, -2837, -2223, +-376, -1234, 2940, 2271, 461, 1451, -3038, -2287, +-509, -1638, 3343, 2093, 981, 1907, -3519, -1859, +-1220, -2219, 3497, 1698, 1686, 2376, -3068, -1736, +-1665, -2282, 2474, 1790, 1698, 1995, -1531, -1696, +-1575, -1723, 952, 1312, 1758, 1502, -348, -610, +-1990, -1484, 336, -241, 2384, 1650, -131, 963, +-2443, -2047, 102, -1289, 2370, 2396, 447, 1156, +-1714, -2365, -1063, -894, 1272, 1688, 1937, 864, +-725, -613, -2303, -1281, 740, -341, 2520, 1809, +-687, 714, -2207, -2084, 958, -568, 2166, 1873, +-769, 224, -2072, -1457, 609, -71, 2352, 1148, +174, 160, -2275, -1096, -967, -417, 2377, 1038, +1956, 753, -1982, -858, -2365, -1191, 1853, 656, +2542, 1519, -1432, -784, -2080, -1437, 1333, 1237, +1961, 702, -1064, -1703, -1813, 327, 1089, 1805, +2371, -1097, -947, -1551, -2668, 1166, 1052, 1249, +2982, -779, -708, -1169, -2757, 460, 748, 1156, +2463, -536, -627, -1069, -1730, 825, 1002, 922, +1173, -1046, -1095, -1007, -463, 1111, 1345, 1266, +235, -1055, -1131, -1469, -10, 717, 1219, 1399, +76, 14, -1116, -1278, 209, -1007, 1394, 1426, +-418, 1626, -1396, -1752, 972, -1562, 1380, 1735, +-1009, 1112, -1035, -1168, 1139, -1000, 722, 413, +-822, 1376, -156, -35, 723, -1781, -146, -54, +-410, 1769, 430, 237, 455, -1515, -263, -715, +-381, 1439, 77, 1047, 664, -1620, 234, -827, +-689, 1586, -282, 216, 756, -1113, 518, 268, +-686, 462, -460, -513, 757, 1, 611, 724, +-850, -394, -346, -1003, 962, 957, 144, 968, +-658, -1558, 154, -400, 234, 1605, -133, -336, +451, -900, -65, 585, -795, -177, 415, -135, +1043, 918, -605, -597, -992, -1146, 781, 1066, +924, 1152, -723, -1218, -683, -1223, 598, 1272, +570, 1253, -357, -1348, -272, -1073, 78, 1200, +27, 853, 296, -868, 348, -894, -688, 599, +-641, 1163, 1190, -672, 806, -1309, -1585, 918, +-716, 1007, 1773, -904, 638, -437, -1643, 434, +-717, -34, 1567, 224, 891, 82, -1574, -554, +-964, 6, 1851, 447, 548, 117, -1935, -355, +45, -469, 1849, 595, -588, 761, -1605, -1093, +776, -838, 1407, 1418, -642, 830, -1348, -1349, +564, -1006, 1049, 1035, -404, 1280, -595, -784, +246, -1376, -7, 622, 57, 1141, 222, -459, +-325, -810, -48, 316, 388, 598, -429, -419, +-358, -363, 872, 578, 319, -40, -1093, -503, +-494, 438, 1212, 104, 511, -616, -1052, 287, +-473, 541, 659, -294, 336, -554, -231, -10, +-473, 743, 65, 280, 728, -897, -494, -337, +-854, 658, 1013, 409, 707, -210, -1286, -625, +-455, -26, 1009, 727, 298, -106, -422, -484, +-387, 352, -120, -20, 444, -402, 388, 374, +-468, 276, -548, -467, 449, -91, 529, 428, +-630, -150, -410, -443, 819, 546, 108, 376, +-743, -919, -33, -71, 453, 732, 291, -165, +-139, 28, -792, -74, 23, -818, 1078, 645, +-33, 1047, -1066, -956, -94, -792, 781, 610, +274, 618, -443, 54, -562, -845, 125, -476, +822, 1270, 211, 489, -1231, -1575, -289, -393, +1616, 1737, 129, 419, -1786, -1900, 200, -439, +1478, 1963, -359, 271, -890, -1670, 97, -42, +403, 982, 293, -38, -230, -196, -424, -199, +164, -359, 217, 624, 270, 513, 29, -990, +-966, -448, 73, 1089, 1624, 460, -291, -914, +-1930, -693, 306, 602, 1935, 1071, 52, -370, +-1881, -1285, -583, 255, 1907, 1165, 865, -235, +-1732, -816, -933, 298, 1486, 482, 1017, -495, +-1147, -273, -1116, 719, 1084, 154, 1235, -772, +-1115, -113, -1033, 565, 953, 140, 759, -320, +-548, -55, -465, 198, 39, -302, 300, -211, +383, 922, -53, 138, -685, -1544, -19, 177, +1063, 1730, 18, -512, -1323, -1453, 331, 579, +1469, 1063, -668, -395, -1202, -841, 701, 240, +810, 641, -231, -193, -420, -220, -581, 11, +382, -354, 1290, 450, -350, 784, -1593, -1123, +422, -745, 1686, 1635, -429, 284, -1323, -1784, +571, 381, 825, 1539, -535, -980, -220, -1096, +310, 1485, -113, 458, 113, -1738, 170, 289, +-390, 1624, -165, -879, 601, -1350, 477, 1224, +-643, 1115, -881, -1356, 850, -1093, 1390, 1463, +-1005, 1180, -1396, -1625, 1086, -1226, 1238, 1818, +-964, 1096, -920, -1931, 855, -839, 755, 1859, +-960, 620, -404, -1740, 1200, -416, -73, 1592, +-1098, 139, 661, -1344, 827, 176, -921, 983, +-289, -410, 974, -592, 81, 468, -911, 316, +116, -274, 810, -312, -157, -24, -696, 566, +301, 248, 478, -835, -308, -367, -272, 889, +318, 536, 316, -718, -208, -809, -311, 432, +230, 1074, 318, -105, -80, -1178, 47, -265, +-238, 1030, -411, 783, 765, -778, 628, -1396, +-1200, 592, -533, 1879, 1320, -434, 399, -1997, +-1126, 19, -383, 1885, 1066, 693, 692, -1706, +-1145, -1518, -876, 1451, 1385, 2211, 1115, -1043, +-1475, -2593, -1048, 412, 1179, 2616, 1000, 330, +-625, -2205, -901, -1089, 17, 1353, 728, 1842, +551, -319, -478, -2447, -833, -589, 209, 2668, +1066, 1161, 108, -2283, -963, -1524, -392, 1427, +838, 1758, 757, -491, -580, -1733, -1132, -296, +268, 1310, 1445, 838, 169, -473, -1673, -1162, +-728, -608, 1749, 1201, 1335, 1706, -1467, -925, +-1873, -2609, 1036, 412, 2194, 3069, -174, 211, +-2277, -2909, -701, -715, 2062, 2041, 1616, 989, +-1746, -652, -2207, -941, 1226, -876, 2361, 600, +-676, 1938, -2128, 135, 281, -2225, 1451, -1197, +-43, 1692, -407, 2320, -15, -562, -568, -3098, +26, -841, 1163, 3213, 220, 2221, -1281, -2633, +-643, -3193, 1017, 1439, 1031, 3541, -701, 112, +-1131, -3144, 202, -1730, 848, 2166, 355, 3034, +-378, -853, -800, -3685, 19, -550, 864, 3630, +232, 1669, -218, -3047, -492, -2097, -832, 2159, +786, 1671, 1779, -1197, -985, -668, -2169, 535, +617, -498, 1908, -411, 103, 1338, -1218, 917, +-781, -1581, 142, -1765, 1045, 1100, 1207, 2500, +-751, 9, -2490, -2620, 117, -1514, 3296, 2024, +804, 2977, -3445, -973, -1883, -3817, 2942, -185, +2892, 3767, -2243, 1108, -3616, -3026, 1478, -1579, +3888, 2098, -783, 1508, -3800, -1488, 128, -1127, +3708, 1544, 452, 730, -3635, -2162, -880, -669, +3502, 2973, 1296, 1085, -3111, -3468, -1888, -1835, +2463, 3124, 2508, 2737, -1768, -1878, -3098, -3515, +1233, 167, 3217, 3858, -770, 1292, -2976, -3352, +429, -2141, 2608, 1994, -110, 2375, -2208, -318, +-193, -2173, 2013, -894, 410, 1708, -1799, 1065, +-691, -1106, 1456, -290, 996, 614, -1041, -785, +-1173, -560, 268, 1454, 1241, 1079, 723, -1351, +-1006, -1805, -1797, 497, 574, 2055, 2674, 846, +195, -1381, -2987, -2112, -1188, -204, 2747, 2635, +2007, 2228, -1872, -1992, -2472, -3880, 657, 298, +2114, 4382, 721, 1791, -1140, -3351, -1732, -3374, +-209, 1091, 2117, 3696, 1479, 1481, -1500, -2541, +-2271, -3234, 193, 232, 2496, 3501, 1277, 2388, +-1991, -2350, -2383, -4312, 1003, 353, 2705, 4943, +167, 1580, -2378, -4224, -1038, -2724, 1566, 2621, +1414, 2777, -490, -853, -1406, -1958, -293, -472, +1133, 771, 765, 1110, -682, 260, -792, -1171, +-2, -859, 762, 952, 721, 1073, -754, -694, +-1309, -1111, 590, 414, 1626, 1112, -37, 35, +-1658, -1119, -994, -692, 1544, 1033, 2133, 1302, +-1056, -647, -2828, -1495, 232, -133, 2762, 977, +801, 1122, -1758, 190, -1707, -1797, 244, -1717, +1912, 1683, 1331, 3099, -1505, -656, -2242, -3791, +656, -866, 2018, 3448, 237, 2167, -697, -2060, +-793, -2695, -1043, 189, 827, 2239, 2393, 1370, +-173, -992, -2861, -1962, -834, -539, 2318, 1552, +1673, 1627, -1149, -529, -1790, -1704, -374, -471, +1152, 725, 1583, 873, -15, 808, -2035, -454, +-1115, -2062, 1590, -616, 1830, 2467, -299, 1755, +-2215, -1919, -920, -2351, 2042, 860, 1717, 2050, +-1601, 86, -1815, -979, 999, -479, 1348, -287, +-519, 126, -711, 1112, 495, 843, -164, -1227, +-620, -1960, 872, 678, 900, 2602, -1248, 302, +-1053, -2431, 1043, -1328, 1034, 1443, -258, 2092, +-883, -3, -792, -2425, 466, -1374, 1637, 2260, +205, 2282, -2013, -1591, -1126, -2637, 1857, 648, +1957, 2411, -1380, 263, -2297, -1543, 752, -913, +2108, 236, -370, 1112, -1427, 998, 329, -742, +774, -1618, -737, -114, -503, 1383, 1168, 976, +811, -506, -1276, -1200, -1473, -553, 680, 434, +1899, 1232, 552, 1054, -1594, -1064, -1891, -2521, +335, -27, 2695, 3147, 1414, 1637, -2410, -2508, +-2849, -2917, 990, 867, 3143, 3013, 905, 1093, +-2119, -1732, -2318, -2443, 134, -169, 2383, 2415, +1900, 1583, -1172, -947, -2908, -1737, -548, -1140, +2250, 590, 1829, 2647, -280, 1166, -1912, -2784, +-1862, -2521, 898, 1656, 2687, 2707, 651, -151, +-1784, -1563, -1679, -763, -325, -258, 1361, 651, +2297, 1614, 177, 294, -2822, -1603, -2238, -1439, +1730, 329, 3489, 2009, 328, 1312, -3087, -1575, +-2107, -2317, 1281, 440, 2495, 2207, 897, 574, +-1370, -1175, -2066, -806, -642, -63, 1564, 250, +2285, 694, 152, 542, -2455, -361, -1997, -859, +1013, -630, 2823, 361, 1162, 1492, -1993, 683, +-2774, -1402, 26, -1675, 2814, 156, 2043, 2066, +-1429, 1533, -2909, -1554, -537, -2514, 1933, 302, +2056, 2149, 133, 1124, -2312, -766, -2021, -1972, +1343, -584, 2602, 1802, 142, 1030, -1658, -884, +-1117, -402, 83, 47, 765, -764, 1165, 86, +657, 1592, -1389, 505, -2076, -1379, 506, -1387, +2514, 220, 690, 1876, -1585, 1143, -1395, -1477, +45, -1880, 964, 321, 1177, 1565, 355, 840, +-1297, -455, -1669, -1161, 443, -690, 2073, 438, +600, 980, -1208, 751, -1079, 41, -206, -1490, +435, -1883, 1252, 1207, 789, 3292, -978, 89, +-2061, -3257, -200, -1676, 2341, 1772, 1540, 2489, +-1376, 336, -2141, -1936, -222, -1861, 1483, 273, +1596, 2049, -60, 1545, -1754, -1004, -1493, -2412, +737, -528, 2202, 1832, 717, 1711, -1666, -284, +-1679, -1981, 176, -1140, 1552, 1199, 1446, 1655, +-563, 173, -2239, -1246, -649, -1325, 1851, 460, +1426, 1643, -825, 196, -1355, -1299, -92, -369, +555, 932, 350, -28, 309, -901, 18, 728, +-696, 991, -668, -1197, 516, -836, 1011, 1058, +-43, 351, -922, -479, -258, 268, 552, -16, +49, -745, -204, 148, 328, 928, 309, -121, +-703, -662, -763, 211, 507, 55, 1361, -407, +120, 517, -1596, 511, -1035, -699, 1072, -380, +1851, 547, -105, 35, -1934, -401, -1024, 309, +1110, 525, 1626, -433, 324, -832, -1347, 261, +-1643, 1030, 143, 23, 2032, -937, 1349, -178, +-1220, 681, -2347, 192, -479, -627, 2102, -173, +2115, 945, -686, 238, -2779, -1242, -1245, -556, +2000, 1098, 2566, 1093, -316, -509, -2419, -1382, +-1462, -164, 882, 934, 2090, 561, 1159, 208, +-1325, -447, -2547, -1431, -333, -83, 2389, 1968, +1576, 656, -958, -1487, -1507, -842, -778, 400, +132, 501, 1397, 409, 1584, 172, -546, -419, +-2317, -736, -1191, -77, 1400, 773, 2403, 392, +543, -244, -2109, -280, -2211, -274, 451, 123, +2306, 137, 1203, -320, -719, 555, -1556, 1006, +-1553, -963, 133, -1785, 2925, 398, 1960, 1999, +-2293, 1015, -3502, -1248, -29, -2372, 3370, -166, +2530, 2656, -1643, 1544, -3797, -1725, -811, -2098, +3137, 303, 2645, 1404, -1158, 657, -2998, 78, +-1011, -683, 1843, -1278, 2238, -83, -35, 1329, +-2109, 905, -1282, -316, 857, -940, 1371, -958, +609, -75, -148, 1550, -1479, 1625, -1732, -1096, +1105, -2709, 3179, 155, 317, 2590, -3453, 407, +-1992, -1291, 2139, -99, 2889, -142, -35, -713, +-2451, 548, -1707, 1393, 808, 322, 2016, -1368, +1022, -1605, -728, 547, -1994, 2142, -1173, 638, +1493, -1445, 2321, -1401, 50, -182, -1902, 1101, +-1349, 1751, 271, 113, 1374, -2389, 1267, -1521, +-76, 1786, -1495, 2114, -1583, -464, 353, -1598, +2138, -751, 1297, 441, -1180, 1088, -2313, 389, +-562, -350, 1925, -278, 1697, -889, -529, -637, +-1526, 1708, -921, 1772, 300, -1426, 1314, -2389, +986, 383, -393, 2153, -1608, 802, -1010, -1113, +1253, -1456, 2054, -161, -210, 1302, -2140, 1196, +-866, -488, 1414, -1565, 1576, -446, -289, 1156, +-1581, 851, -735, -370, 922, -534, 1243, -186, +-35, -376, -1051, 37, -527, 1248, 106, 547, +327, -1582, 849, -1116, 543, 1096, -1209, 1163, +-1590, -219, 551, -755, 2072, -338, 571, 245, +-1558, 223, -1209, -21, 206, 250, 910, 223, +1132, -361, 253, -478, -1645, -16, -1316, 515, +1300, 696, 1583, -94, -476, -1124, -1082, -433, +108, 1200, 361, 802, -413, -976, -3, -692, +923, 677, 88, 300, -1097, -325, -438, -16, +647, -106, 612, -120, -163, 354, -493, 168, +-8, -243, 52, -203, -130, -310, 226, -289, +278, 599, -75, 1263, -119, -165, -317, -2062, +-246, -1077, 787, 1578, 604, 2246, -784, 283, +-694, -2341, 405, -2302, 715, 1106, 123, 2927, +-622, 701, -501, -1569, 343, -1574, 672, -371, +193, 1045, -804, 1317, -971, 234, 683, -619, +1505, -650, -234, -523, -1649, -173, -480, 998, +1084, 1385, 858, -667, -82, -1852, -526, 289, +-761, 1469, -504, -478, 879, -1161, 1723, 815, +6, 1246, -2107, -711, -1334, -1481, 1447, -283, +2263, 972, 104, 1336, -1858, 163, -1509, -1655, +321, -1341, 1938, 981, 1276, 1681, -1226, -68, +-1840, -1113, -195, -398, 1091, 305, 1119, 404, +124, 348, -1128, -94, -1072, -622, 323, -126, +1041, 660, 513, 379, -259, -116, -783, -237, +-799, -601, 417, -343, 1525, 1028, 486, 1171, +-1520, -631, -1189, -1391, 846, -222, 1507, 583, +324, 628, -1161, 487, -1194, -266, 350, -807, +1265, -469, 541, -74, -319, 411, -1015, 876, +-1076, 307, 436, -721, 1842, -914, 711, -299, +-1452, 448, -1717, 685, -109, 374, 1647, 147, +1523, -324, -694, -1210, -1830, -806, -426, 1210, +953, 1948, 859, -25, 276, -1649, -299, -668, +-804, 333, -409, 197, 477, 761, 725, 931, +332, -334, -336, -1059, -632, -691, -257, -18, +295, 888, 483, 1227, 432, 128, -492, -1302, +-937, -1163, 188, 266, 1043, 981, -75, 529, +-1013, -177, -88, -595, 660, -385, 175, 132, +-267, 43, -93, -27, -208, 304, -295, -12, +426, -300, 743, 117, -179, 109, -694, -259, +-259, -338, 212, 87, 636, 868, 435, 535, +-449, -788, -561, -1004, 50, 53, 221, 1109, +69, 926, 184, -642, 384, -1071, -331, 380, +-965, 668, -153, -397, 965, -186, 475, 667, +-401, 201, -424, -730, -467, -477, -138, 571, +697, 741, 624, -368, -435, -1140, -546, -77, +10, 1364, 64, 463, 73, -1221, 494, -720, +283, 287, -532, 325, -414, 518, 165, 186, +283, -617, 167, -481, 124, -32, 33, 258, +-281, 555, -429, 204, -60, -443, 400, -468, +385, 121, 70, 618, -420, 113, -581, -681, +-76, 101, 436, 1093, 237, -75, -36, -1381, +-22, -208, -143, 1478, -421, 669, -64, -1105, +538, -638, 416, 645, -424, 204, -402, -451, +415, -24, 438, 471, -330, 345, -532, -485, +178, -946, 529, -143, 181, 808, -81, 1013, +-327, -5, -607, -1635, 88, -997, 817, 1231, +276, 1071, -552, -487, -577, -379, 36, 262, +429, -91, 227, -665, -351, -413, -300, 704, +280, 1322, 302, 395, -388, -1125, -368, -1487, +511, 24, 532, 1442, -437, 875, -691, -140, +138, -451, 971, -601, 608, -285, -1013, 88, +-1243, 253, 629, 915, 1293, 557, 236, -1117, +-463, -915, -857, 542, -717, 43, 440, -410, +1331, 984, 441, 960, -1045, -1116, -1019, -1623, +267, 155, 645, 1219, -27, 422, -73, -253, +196, -175, 32, -364, -316, -342, -384, 83, +113, 243, 505, 446, -30, 316, -193, -539, +545, -524, 90, 459, -889, 459, -519, -262, +780, -259, 976, 113, -272, 197, -683, 133, +92, 186, -78, 138, -533, -521, 478, -712, +1068, 474, -174, 1027, -1255, -132, -647, -774, +828, 68, 1088, 398, -144, -490, -963, -423, +-442, 631, 297, 328, 555, -395, 332, 43, +-165, -49, -382, -571, -327, 96, 67, 514, +491, -30, 298, -65, -38, -16, -383, -302, +-415, -27, 304, 261, 709, 158, -135, 88, +-838, -204, -193, -381, 843, 88, 695, 720, +-628, 488, -1099, -751, -66, -903, 911, 524, +647, 814, -239, -109, -639, -124, -449, 122, +-87, -350, 451, -518, 888, 107, 158, 800, +-1053, 550, -783, -649, 510, -952, 1075, 142, +216, 663, -802, 107, -486, -282, 316, -105, +360, 54, 244, -159, 18, -89, -584, 178, +-481, -131, 549, 21, 864, 602, -213, -225, +-898, -1023, -179, 158, 373, 1014, 106, 40, +193, -550, 368, 180, -311, 299, -860, -583, +-144, -387, 883, 849, 674, 670, -528, -576, +-857, -575, 181, 203, 769, 497, 194, 169, +-486, -625, -543, -506, 115, 601, 713, 601, +376, -95, -381, -184, -564, -364, -95, -493, +217, -33, 147, 322, 306, 538, 337, 506, +-529, -427, -906, -959, 250, -119, 1007, 378, +118, -45, -783, -14, -372, 508, 345, 576, +396, -215, 163, -1030, -17, -637, -603, 346, +-762, 724, 711, 708, 1427, 349, -259, -636, +-1349, -1049, -243, 28, 691, 858, 314, 147, +-55, -405, -2, 131, -27, 493, -274, 213, +-170, -400, 200, -846, 329, -239, 74, 806, +-292, 664, -377, -213, 38, -367, 498, -95, +215, -175, -363, -233, -396, 122, 53, 399, +416, 67, 79, -303, -291, -117, -34, 102, +41, 64, -34, -123, 336, -327, 216, 6, +-552, 543, -570, 376, 237, -285, 886, -752, +544, -336, -612, 826, -1143, 908, -164, -388, +935, -814, 802, -68, -125, 204, -712, 297, +-560, 601, -35, -67, 505, -920, 735, -182, +15, 854, -769, 327, -460, -538, 184, -216, +417, 187, 294, -109, -1, 8, -301, 397, +-322, 44, 129, -382, 488, -203, -223, -16, +-685, -42, 403, 61, 1055, 341, -178, 409, +-1208, -265, -351, -1014, 819, -351, 717, 944, +-179, 752, -602, -378, -220, -629, 247, -34, +160, 309, -54, 28, 97, -210, 139, 1, +-352, 322, -251, 460, 407, -153, 210, -959, +-277, -229, -176, 926, -4, 439, 304, -288, +405, 1, -390, 13, -737, -427, 159, -408, +753, 68, 174, 705, -362, 797, -124, -121, +21, -974, -318, -752, -182, 193, 628, 754, +719, 366, -437, -69, -1156, -85, -113, -337, +1305, -457, 570, 40, -1232, 442, -786, 219, +912, -234, 865, -106, -458, 348, -836, -22, +145, -643, 680, -276, -162, 471, -479, 668, +324, 263, 417, -485, -299, -797, -576, -218, +14, 460, 691, 663, 367, 437, -568, -146, +-531, -718, 329, -811, 375, 6, -213, 1183, +-222, 891, 229, -683, 281, -1129, -174, 33, +-313, 959, -81, 229, 119, -804, 228, -211, +-42, 467, -119, 17, 443, 157, 19, 441, +-969, -468, -274, -831, 944, 26, 634, 560, +-272, 537, -638, 218, -324, -435, 174, -629, +442, -111, 110, 361, -201, 355, -63, -38, +173, -196, -27, 131, -456, 158, -136, -324, +545, -436, 444, 263, -302, 545, -365, -275, +22, -331, -50, 505, -158, 159, 417, -521, +460, -268, -342, -120, -533, 152, -19, 829, +378, 395, 278, -805, -218, -840, -271, 144, +59, 686, 72, 266, 82, -299, 173, -13, +-55, 344, -379, -297, -146, -606, 346, 249, +263, 598, -165, -68, -169, -198, 86, 260, +16, -2, -184, -496, -91, -232, 290, 371, +306, 661, -304, 118, -474, -733, 259, -456, +453, 340, -113, 427, -244, 142, -171, -311, +42, -461, 349, 196, 65, 497, -267, -127, +-77, -425, 139, 5, 61, 161, -168, -148, +-52, -10, 180, 424, -33, 41, -36, -572, +184, -146, -122, 423, -288, 116, 122, -288, +147, -127, -5, 377, 33, 367, -12, -344, +-11, -380, -13, 146, -269, 61, 34, 102, +403, 316, 18, -17, -214, -229, -37, -135, +37, 43, -26, 265, -97, 63, 111, -218, +239, -137, -118, -40, -235, 169, 11, 377, +270, 126, 98, -411, -442, -786, -299, -221, +559, 1072, 482, 929, -355, -709, -577, -1181, +-127, -157, 564, 756, 545, 731, -547, -166, +-755, -709, 536, -367, 779, 122, -296, 509, +-714, 382, -86, -142, 614, -243, 310, -371, +-387, -318, -237, 591, 173, 745, 2, -389, +-154, -665, 239, 372, 449, 667, -432, -415, +-906, -824, 389, 289, 1265, 925, -75, 175, +-1262, -553, -421, -463, 886, 138, 720, 440, +-395, -117, -624, -315, 64, 363, 309, 236, +-94, -544, 11, -323, 273, 477, -4, 426, +-435, -519, -106, -658, 549, 431, 81, 676, +-481, -143, 92, -494, 325, -424, -245, 81, +-167, 799, 292, 287, 176, -828, -237, -577, +-200, 556, 145, 767, 9, -113, -181, -672, +113, -186, 366, 328, 144, 227, -334, 220, +-668, 212, -111, -375, 775, -717, 515, -1, +-322, 985, -348, 766, -173, -631, -33, -1126, +321, 10, 113, 815, -241, 264, -56, -250, +268, 50, 170, -16, -118, -497, -235, -87, +-188, 465, -70, 88, 316, -206, 411, -63, +-130, 25, -341, 108, -79, -57, 45, -326, +46, -17, 87, 372, 16, 122, -112, -231, +-47, -285, 168, -29, 182, 457, -144, 353, +-375, -399, -28, -605, 384, 0, 378, 595, +-248, 426, -700, -239, 57, -319, 887, 49, +291, -15, -663, -196, -654, 138, 104, 504, +681, 28, 287, -605, -313, -93, -141, 645, +55, 91, -284, -734, -215, -263, 485, 672, +486, 574, -417, -354, -601, -756, 190, -73, +673, 518, 29, 317, -646, 17, -320, -392, +468, -587, 502, 268, -171, 757, -466, -39, +-23, -544, 358, -273, 201, 141, -218, 476, +-355, 269, -48, -399, 318, -624, 401, -30, +79, 722, -505, 590, -488, -426, 152, -813, +471, 15, 325, 618, -58, 233, -429, -295, +-471, -239, 102, 123, 703, 130, 395, 4, +-596, 92, -791, -56, 318, -288, 981, -141, +-21, 261, -928, 488, -237, -13, 716, -617, +419, -295, -350, 315, -375, 515, 80, 245, +118, -546, -61, -771, 63, 201, 276, 877, +95, 341, -378, -419, -360, -552, 72, -237, +376, 79, 350, 410, -44, 653, -489, 21, +-314, -977, 241, -631, 313, 574, 65, 931, +86, 240, -126, -693, -577, -864, -180, -36, +749, 820, 647, 752, -458, -187, -838, -750, +36, -404, 599, -18, 130, 452, -181, 801, +-28, -58, -2, -931, -64, -286, 26, 527, +36, 367, -126, 30, -102, -199, 233, -396, +289, -193, -145, 372, -329, 685, -28, 37, +6, -876, 35, -430, 282, 599, 103, 442, +-197, -209, -134, -182, -147, 96, -7, -46, +322, -167, 145, 187, -201, 165, -88, -389, +47, -257, -69, 454, -46, 499, 221, -137, +177, -555, -191, -457, -341, 79, -16, 795, +414, 612, 305, -657, -295, -979, -517, 346, +34, 896, 394, -234, 211, -630, 29, 308, +-241, 436, -460, -339, -43, -380, 503, 253, +412, 422, -62, -22, -506, -319, -496, -196, +131, -5, 705, 136, 464, 279, -437, 290, +-732, -137, -50, -589, 557, -230, 344, 358, +-192, 258, -324, 90, -14, 163, 162, -197, +47, -510, -63, -5, -67, 308, -33, 29, +178, 240, 147, 234, -223, -710, -278, -587, +112, 810, 252, 775, 34, -541, -70, -670, +-21, 73, -78, 221, -141, 133, 93, 190, +195, 143, 40, -149, -6, -489, -144, -191, +-233, 366, 28, 283, 346, 85, 273, 61, +-197, -176, -553, -365, -116, -281, 524, 213, +384, 883, -101, 416, -459, -1018, -497, -1087, +240, 465, 941, 1263, 175, 436, -927, -665, +-567, -895, 448, -323, 648, 379, 117, 849, +-322, 586, -331, -490, -56, -1026, 156, -361, +90, 586, 64, 860, 209, 123, -41, -705, +-459, -565, -119, 147, 571, 642, 194, 384, +-643, -476, -269, -682, 689, 89, 477, 627, +-450, 382, -696, -231, -134, -642, 668, -232, +698, 593, -307, 500, -925, -387, -134, -508, +668, 335, 377, 425, -159, -394, -211, -235, +-186, 354, -258, -86, 112, -125, 587, 425, +272, -42, -439, -486, -531, 13, -31, 245, +507, 5, 387, 5, -351, 104, -428, -59, +261, -248, 359, -36, -211, 230, -309, 51, +50, -169, 261, -45, 198, 135, -77, 124, +-443, -131, -234, -229, 498, 128, 539, 137, +-295, -133, -625, 88, -44, 96, 429, -176, +293, 65, -108, 78, -279, -239, -133, -17, +79, 316, 312, 154, 195, -230, -384, -301, +-442, 65, 249, 269, 482, 81, 159, -3, +-153, 13, -464, -226, -444, -340, 312, 66, +803, 503, 198, 474, -674, -99, -522, -820, +312, -694, 552, 504, -180, 1081, -572, 18, +202, -689, 733, -13, -46, 52, -747, -511, +-205, 82, 365, 843, 285, 247, 66, -706, +-54, -539, -159, 390, -173, 559, 2, -155, +212, -455, 112, -20, -76, 352, -55, 143, +-207, -274, -100, -201, 556, 301, 341, 367, +-662, -274, -638, -626, 385, -39, 742, 671, +74, 480, -577, -271, -285, -524, 308, -233, +202, 66, -93, 275, 18, 346, -2, 233, +-216, -230, -79, -772, 353, -280, 329, 754, +-197, 653, -471, -239, -235, -609, 234, -232, +620, 307, 306, 275, -636, -174, -686, -114, +244, 329, 670, 121, 148, -481, -307, -321, +-256, 399, -156, 455, 78, -200, 436, -367, +124, 19, -472, 98, -96, 236, 298, 292, +-67, -471, -41, -623, 178, 470, -185, 663, +-157, -287, 298, -361, 130, 211, -219, -14, +-88, -268, 102, 257, 36, 334, -121, -333, +-16, -425, 189, 252, 127, 530, -122, -34, +-218, -475, -39, -106, 167, 271, 61, -46, +-62, -291, 64, 198, 32, 549, -98, 38, +-96, -591, -85, -488, 133, 161, 339, 455, +-15, 305, -432, 159, -217, -368, 297, -669, +409, 108, -100, 529, -405, 6, 111, -54, +348, 264, -276, -65, -481, -625, 303, -295, +747, 643, -61, 636, -809, -339, -168, -530, +622, 196, 186, 266, -408, -336, -245, -354, +249, 387, 470, 786, -7, -68, -661, -928, +-325, -284, 574, 549, 535, 333, -325, -141, +-532, -188, 160, 64, 399, 78, -179, -100, +-227, 9, 312, 18, 209, -197, -405, -37, +-370, 263, 269, 217, 532, -98, 122, -312, +-383, -132, -478, 45, -11, 73, 575, 345, +238, 231, -431, -493, -187, -393, 227, 291, +-82, 197, -9, 52, 376, 122, 23, -224, +-633, -260, -365, 162, 619, 301, 815, 53, +-265, -323, -896, -227, -194, 222, 536, 292, +481, 156, -79, -87, -533, -461, -156, -320, +446, 300, 206, 612, -247, 231, -175, -523, +3, -655, 101, 183, 150, 687, 16, 114, +-122, -502, -128, -341, -140, 238, 51, 366, +437, 1, 316, -48, -494, -168, -752, -540, +146, -8, 788, 792, 336, 450, -403, -453, +-450, -759, -32, -98, 230, 556, 68, 335, +15, 48, 139, -100, -29, -507, -308, -323, +-77, 514, 401, 684, 212, -77, -394, -716, +-402, -335, 237, 528, 480, 456, 81, -200, +-359, -183, -279, -85, 123, -108, 230, 247, +-65, 217, -112, -102, 181, -110, 114, -295, +-324, -150, -199, 618, 390, 485, 211, -673, +-410, -856, -187, 422, 432, 959, 263, -105, +-343, -802, -456, -278, 87, 369, 605, 505, +248, 51, -467, -495, -464, -265, 134, 152, +384, 15, 165, 206, -103, 537, -226, -185, +-151, -901, 133, -285, 182, 786, -107, 844, +20, -253, 219, -886, -276, -206, -433, 514, +436, 428, 554, -75, -365, -313, -540, -29, +211, 166, 384, 24, -88, -55, -245, -19, +47, 72, 197, 21, 71, -137, -200, 52, +-291, 160, 185, -208, 490, -148, -140, 278, +-507, 52, 113, -217, 366, -120, -153, -191, +-170, 226, 224, 630, -1, -275, -313, -879, +133, 46, 338, 668, -188, 95, -281, -261, +102, 28, 79, -76, 120, -271, 209, 178, +-257, 318, -458, -83, 168, -118, 541, -10, +78, 15, -441, 179, -253, 12, 319, -280, +224, 93, -214, 373, -158, -82, 162, -211, +165, 132, -116, 43, -242, -206, 161, 36, +276, 314, -272, -22, -283, -272, 346, 125, +308, 138, -238, -307, -381, -221, -45, 169, +343, 335, 343, 177, -29, -202, -429, -422, +-415, -394, 186, 37, 627, 650, 198, 473, +-348, -292, -346, -564, -161, -378, 164, -6, +376, 519, 162, 450, -121, -132, -230, -234, +-281, -215, -50, -283, 424, 197, 430, 514, +-260, 89, -610, -213, 43, -121, 468, -83, +40, 52, -187, 392, -45, 71, -58, -608, +94, -49, 194, 776, -77, 184, -238, -537, +-85, -327, 109, 67, 247, 275, 117, 244, +-123, 9, -138, -153, -204, -283, -145, -243, +275, 151, 538, 375, 48, 193, -616, -199, +-432, -628, 332, -287, 479, 680, 16, 620, +-249, -414, -198, -875, 62, -110, 201, 872, +-74, 422, -139, -641, 222, -421, 156, 221, +-367, 194, -389, 102, 389, 122, 741, -7, +-188, -279, -895, -260, -95, 324, 637, 542, +191, -61, -163, -423, -57, -196, -57, 145, +-158, 454, -12, 243, 222, -400, 184, -408, +-172, 139, -277, 378, 82, 185, 327, -124, +92, -245, -337, -329, -270, -115, 142, 660, +253, 521, 177, -613, 39, -743, -327, 11, +-326, 458, 124, 435, 278, -56, 184, -473, +119, -318, -306, 61, -482, 349, 146, 208, +611, -266, 102, -264, -574, 89, -269, 219, +515, 222, 346, -170, -444, -575, -358, 78, +337, 767, 327, 228, -146, -491, -287, -393, +-21, 161, 160, 387, 108, 85, -47, -108, +-21, -17, 50, 60, -127, -61, -234, -253, +172, 174, 407, 623, -84, -144, -400, -833, +-21, -106, 235, 749, 31, 465, -64, -483, +-27, -727, -21, 138, 5, 597, 94, -56, +-23, -402, -129, 10, -2, 217, 153, -8, +50, -252, -56, -107, -123, 172, -192, -42, +60, -103, 432, 316, 244, 186, -384, -402, +-556, -469, -16, 96, 525, 610, 384, 390, +-165, -263, -401, -537, -146, -167, 233, 430, +241, 434, -191, -143, -356, -310, 212, 92, +567, 223, 10, -114, -586, -176, -329, 251, +213, 289, 352, -271, 217, -388, -19, 151, +-291, 407, -311, 73, 42, -330, 311, -272, +231, 172, -98, 187, -306, -178, -161, -91, +236, 151, 344, 37, -115, -186, -454, -225, +5, 103, 473, 294, 28, -110, -461, -318, +-27, 44, 494, 283, 80, 70, -471, -285, +-245, -329, 356, 142, 386, 621, -133, 283, +-420, -570, -40, -610, 363, 179, 112, 527, +-247, 319, -106, 168, 117, -195, 28, -662, +-18, -355, 88, 521, 76, 905, -175, 256, +-291, -855, 129, -859, 494, 404, 50, 976, +-482, 58, -192, -787, 282, -318, 159, 458, +-124, 290, -5, -150, 99, -204, -40, -191, +-78, 40, -37, 240, -122, -135, 54, -259, +338, 230, 75, 261, -308, -264, -189, -368, +117, 41, 143, 281, -58, 68, -125, -151, +181, 54, 276, 229, -137, -108, -391, -428, +-205, -97, 159, 503, 452, 473, 295, -129, +-253, -403, -503, -215, -164, 84, 283, 333, +302, 261, 37, -44, -26, -172, -62, -141, +-356, -111, -206, 87, 478, 441, 547, 276, +-291, -515, -809, -733, -58, 151, 858, 928, +475, 403, -659, -742, -781, -814, 221, 172, +815, 577, 189, 114, -532, -109, -332, -83, +148, -258, 214, -210, 59, 77, -97, 238, +-31, 277, 112, -69, -59, -552, -184, -215, +97, 567, 176, 474, -116, -321, -153, -482, +114, 46, 239, 284, -79, 176, -326, 102, +15, -33, 306, -121, 24, -67, -271, -26, +-94, 34, 285, 200, 316, 299, -240, 39, +-531, -432, -18, -359, 469, 290, 296, 452, +-161, -55, -285, -247, -52, -27, 69, -53, +-51, -190, -3, 78, 241, 385, 219, -46, +-251, -601, -450, -138, 96, 560, 507, 226, +2, -503, -427, -424, -126, 274, 375, 441, +380, -109, -270, -339, -643, 11, 16, 187, +614, -21, 205, -179, -245, 71, -172, 383, +-42, 80, -96, -428, -29, -198, 237, 352, +265, 325, -45, -8, -263, -200, -278, -140, +-82, 186, 405, 265, 443, -154, -228, -318, +-547, 219, -39, 472, 405, -178, 176, -543, +-235, 19, -108, 431, 125, 188, -47, -244, +-112, -452, 155, -96, 204, 443, -176, 281, +-374, -327, 95, -425, 553, -3, 46, 241, +-543, 86, -201, -130, 288, -87, 220, 77, +9, -19, 5, -186, -73, 43, -274, 267, +-153, -52, 299, -287, 324, 120, -27, 402, +-191, 18, -245, -370, -132, -194, 251, 285, +306, 389, -8, 69, -229, -120, -195, -208, +67, -239, 146, 145, 19, 487, 81, 235, +107, -216, -243, -439, -354, -296, 28, 234, +513, 624, 447, 244, -317, -582, -739, -717, +-161, 166, 580, 722, 540, 110, -174, -542, +-569, -339, -118, 105, 336, 251, 245, 173, +-6, -88, -304, -378, -318, -356, 220, 150, +474, 619, 80, 373, -322, -420, -353, -861, +-27, -218, 276, 855, 275, 875, 53, -178, +-206, -934, -291, -538, -5, 560, 214, 989, +175, 151, 10, -749, -218, -554, -134, 355, +122, 714, 85, 88, 36, -462, 47, -259, +-153, 76, -83, 320, 148, 403, 21, -230, +-126, -728, -32, -92, 125, 572, 195, 392, +-59, -103, -285, -500, -114, -495, 63, 10, +253, 544, 304, 545, -186, -241, -544, -932, +-18, -343, 511, 685, 254, 614, -284, -192, +-332, -556, -58, -336, 101, 144, 392, 600, +361, 404, -462, -494, -704, -780, 246, 196, +637, 972, 6, 355, -390, -695, -83, -757, +246, 268, 68, 995, -180, 379, -31, -617, +-11, -738, -59, -45, 207, 771, 197, 736, +-107, -324, -184, -983, -185, -290, -49, 763, +333, 714, 299, -298, -161, -758, -382, -268, +-132, 228, 302, 464, 264, 372, -81, -296, +-197, -757, -183, -329, -42, 386, 353, 688, +270, 260, -257, -623, -383, -830, -52, 52, +312, 891, 350, 519, -107, -601, -467, -738, +-232, 203, 323, 577, 561, 198, 40, -109, +-602, -324, -449, -211, 290, 316, 612, 407, +150, -68, -451, -255, -369, -19, 88, 95, +286, 151, 273, 242, -87, -146, -449, -620, +-84, 26, 370, 975, 151, 398, -142, -917, +-148, -952, -54, 292, 117, 1190, 77, 489, +-111, -978, -37, -1066, 100, 318, 2, 1040, +-83, 165, 29, -788, 141, -453, -39, 336, +-236, 445, -103, 75, 205, -381, 240, -579, +58, 16, -174, 854, -245, 655, -126, -528, +89, -1215, 303, -357, 255, 1119, -108, 1292, +-411, -176, -265, -1464, 259, -789, 501, 972, +-4, 1253, -452, -74, -174, -911, 188, -647, +203, 266, 124, 1159, -77, 544, -274, -1100, +-124, -1157, 156, 417, 227, 1286, 81, 571, +-143, -778, -255, -1256, 31, -174, 328, 1227, +65, 1023, -379, -691, -247, -1588, 279, -378, +487, 1407, 182, 1510, -483, -438, -765, -2177, +-38, -1139, 969, 1612, 770, 2207, -515, -135, +-1213, -2080, -305, -1276, 1038, 921, 1002, 1791, +-380, 476, -1238, -1353, -420, -1445, 916, 425, +970, 1805, -142, 776, -956, -1221, -738, -1679, +320, -79, 1203, 1831, 689, 1627, -944, -802, +-1549, -2390, 19, -782, 1764, 2056, 1125, 2095, +-1159, -857, -1800, -2446, -8, -522, 1614, 1791, +1018, 1525, -703, -548, -1290, -1841, -347, -790, +770, 1241, 934, 1581, 104, -77, -841, -1600, +-818, -1232, 219, 719, 1072, 1909, 594, 555, +-785, -1720, -1199, -1737, 74, 701, 1236, 2215, +762, 652, -713, -1813, -1246, -1776, -114, 760, +1099, 2231, 800, 507, -420, -1795, -961, -1406, +-390, 788, 587, 1724, 789, 364, 87, -1340, +-568, -1066, -577, 607, -45, 1272, 546, 270, +598, -994, -99, -994, -747, 426, -403, 1430, +490, 404, 598, -1339, -25, -1241, -417, 690, +-425, 1625, -6, 189, 637, -1399, 402, -961, +-439, 753, -579, 1352, -33, -116, 419, -1518, +457, -522, -29, 1316, -573, 1103, -369, -668, +363, -1522, 655, -357, 12, 1390, -705, 1298, +-460, -698, 400, -1767, 822, -254, 234, 1648, +-792, 1176, -859, -974, 288, -1780, 1042, -126, +452, 1881, -704, 1459, -1013, -1210, 90, -2396, +1159, -50, 599, 2549, -857, 1512, -1221, -1799, +138, -2559, 1493, 487, 802, 2882, -1077, 1029, +-1516, -2320, 30, -2340, 1555, 920, 1108, 2933, +-873, 937, -1697, -2453, -205, -2626, 1529, 892, +1205, 3313, -773, 1019, -1720, -2759, -211, -2483, +1575, 1189, 1097, 2889, -853, 608, -1627, -2323, +-142, -1980, 1585, 1065, 1054, 2538, -907, 454, +-1556, -2228, -170, -1806, 1411, 1195, 1171, 2619, +-625, 251, -1629, -2545, -492, -1589, 1370, 1689, +1471, 2407, -537, -436, -1821, -2307, -502, -638, +1328, 1440, 1270, 1254, -260, -243, -1288, -1271, +-757, -750, 571, 855, 1077, 1244, 383, -193, +-626, -1142, -932, -465, -183, 568, 715, 766, +788, 140, 58, -569, -795, -663, -827, 10, +167, 726, 982, 413, 717, -452, -334, -532, +-1201, 0, -740, 294, 954, 311, 1579, 242, +-104, -279, -1797, -919, -931, -318, 1386, 1230, +1752, 1377, -449, -672, -2091, -2194, -789, -693, +1755, 2161, 1871, 2276, -810, -1156, -2421, -3211, +-339, -406, 2288, 3209, 1367, 2154, -1662, -2191, +-2117, -3584, 695, 318, 2464, 4201, 498, 2074, +-2271, -3431, -1672, -4228, 1472, 1302, 2480, 5292, +-165, 1473, -2661, -4755, -1325, -4024, 2090, 2633, +2565, 5489, -746, 452, -3121, -5347, -978, -3578, +2637, 3447, 2510, 5522, -1301, -422, -3294, -5602, +-408, -2672, 3140, 3911, 2094, 4712, -2148, -1309, +-3389, -5205, 429, -1401, 3868, 4210, 1731, 3554, +-3099, -2195, -3547, -4581, 1117, -210, 4237, 4289, +1270, 2272, -3507, -2925, -3051, -3300, 1734, 1152, +3775, 3361, 326, 490, -3438, -2788, -2064, -1680, +2282, 1872, 3100, 2553, -655, -677, -3203, -2968, +-1025, -611, 2486, 2685, 2283, 1795, -1285, -1748, +-2810, -2557, -39, 528, 2638, 2715, 1169, 588, +-1945, -2438, -1879, -1483, 983, 1808, 2068, 2072, +17, -910, -1767, -2393, -898, -242, 1149, 2282, +1558, 1300, -388, -1742, -1835, -2054, -430, 806, +1636, 2354, 1196, 260, -954, -2173, -1665, -1258, +-39, 1529, 1659, 1894, 948, -704, -1052, -1918, +-1450, 138, 140, 1580, 1352, 52, 679, -1334, +-803, -124, -1146, 1363, 212, 580, 1208, -1245, +292, -1265, -1051, 738, -652, 1760, 609, -32, +822, -1787, 141, -420, -644, 1561, -826, 692, +-7, -1321, 1065, -1083, 761, 942, -669, 1546, +-1197, -276, -120, -1853, 1212, -549, 916, 1757, +-742, 1198, -1612, -1411, -116, -1785, 1861, 903, +1252, 2327, -1290, -173, -2199, -2664, -61, -968, +2274, 2363, 1624, 2242, -1355, -1327, -2542, -3118, +-70, -164, 2491, 3166, 1350, 1583, -1729, -2459, +-2051, -2508, 706, 1393, 2134, 2932, 301, -266, +-1760, -2959, -1062, -692, 1113, 2664, 1463, 1581, +-401, -1957, -1489, -2370, -172, 1002, 1299, 2992, +571, 124, -1168, -3243, -934, -1327, 1147, 3012, +1376, 2521, -950, -2146, -1854, -3493, 345, 659, +2085, 3874, 578, 1012, -1909, -3495, -1467, -2420, +1329, 2415, 2063, 3270, -434, -971, -2276, -3637, +-712, -686, 2020, 3377, 1916, 2230, -1228, -2471, +-2638, -3328, -35, 1063, 2607, 3638, 1215, 464, +-1852, -3257, -1899, -1777, 811, 2489, 2014, 2722, +58, -1411, -1646, -3169, -696, 137, 1216, 3072, +1064, 1147, -845, -2399, -1303, -2115, 457, 1433, +1604, 2707, 84, -288, -1693, -2790, -988, -868, +1314, 2293, 1853, 1840, -327, -1188, -2102, -2215, +-948, -148, 1620, 1811, 1821, 1148, -645, -957, +-2059, -1481, -339, 95, 1754, 1140, 1128, 436, +-1080, -515, -1657, -662, 166, -181, 1740, 531, +789, 642, -1221, -184, -1393, -749, 278, -265, +1310, 470, 532, 527, -658, -61, -782, -551, +-44, -211, 481, 498, 369, 296, -15, -486, +-298, -359, -286, 510, 37, 622, 385, -323, +238, -898, -363, -86, -466, 1091, 200, 655, +631, -1043, 29, -1090, -577, 850, -273, 1495, +268, -506, 380, -1882, 143, 15, -202, 2224, +-476, 766, -240, -2345, 441, -1761, 835, 2054, +1, 2678, -1268, -1299, -685, -3318, 1171, 110, +1383, 3458, -525, 1225, -1768, -3145, -495, -2581, +1746, 2358, 1506, 3638, -1320, -1276, -2199, -4236, +492, -99, 2525, 4264, 533, 1586, -2370, -3824, +-1592, -2985, 1727, 2894, 2412, 4098, -720, -1442, +-2746, -4575, -517, -242, 2612, 4222, 1603, 1753, +-2028, -3177, -2385, -2526, 1155, 2072, 2849, 2638, +-156, -1178, -2981, -2457, -935, 552, 2753, 2326, +1978, 92, -2021, -1979, -2801, -667, 750, 1316, +3205, 845, 778, -536, -2977, -473, -2172, 12, +2139, -174, 3103, 42, -931, 686, -3397, 97, +-308, -1004, 3123, -224, 1236, 1092, -2544, 207, +-1742, -1139, 1984, -164, 1992, 1233, -1720, 12, +-2261, -1578, 1678, 84, 2697, 2129, -1535, -7, +-3245, -2809, 1086, -334, 3677, 3306, -168, 863, +-3861, -3347, -1111, -1351, 3422, 2884, 2562, 1549, +-2127, -1877, -3630, -1198, 91, 629, 3803, 519, +2116, 532, -3015, 265, -3726, -1275, 1506, -809, +4482, 1694, 195, 1177, -4277, -1718, -1706, -1440, +3156, 1377, 2750, 1585, -1510, -768, -3008, -1463, +-214, 130, 2734, 1206, 1368, 314, -2258, -1152, +-1845, -578, 1749, 1284, 1914, 682, -1401, -1524, +-1682, -739, 1164, 1657, 1512, 732, -1196, -1712, +-1622, -1061, 1355, 1450, 1990, 1751, -1205, -793, +-2442, -2493, 810, -237, 2565, 2749, -335, 1177, +-2393, -2403, -74, -1579, 2120, 1711, 503, 1509, +-1704, -857, -1146, -1233, 1063, -19, 1821, 988, +-86, 1007, -2187, -717, -1067, -1794, 1959, 610, +2096, 2157, -1101, -656, -2659, -1991, -76, 830, +2697, 1706, 1049, -707, -2504, -1603, -1538, -36, +2479, 1901, 1753, 1316, -2672, -2544, -2029, -2737, +2656, 3041, 2556, 3863, -2072, -2829, -3166, -4561, +912, 1496, 3550, 4586, 478, 491, -3510, -4046, +-1665, -2360, 3068, 3094, 2445, 3360, -2464, -2168, +-2852, -3716, 1847, 1332, 3126, 3807, -1215, -529, +-3291, -3743, 368, -388, 3333, 3304, 581, 1385, +-3180, -2478, -1402, -2309, 2886, 1636, 2053, 3213, +-2524, -941, -2559, -3823, 1849, 459, 3062, 3883, +-861, 79, -3378, -3199, -288, -515, 3373, 2292, +1329, 868, -3083, -1529, -2058, -1100, 2544, 1017, +2447, 1241, -1918, -471, -2409, -1044, 1393, -153, +1929, 394, -1005, 474, -1300, 407, 722, -308, +715, -1090, -395, -198, -240, 1345, 126, 595, +-207, -1307, -193, -983, 678, 949, 655, 1345, +-1054, -443, -1294, -1694, 1242, -200, 1832, 1712, +-1243, 658, -2091, -1300, 1012, -763, 2148, 636, +-708, 649, -2010, -126, 387, -441, 1794, 45, +-165, 307, -1539, -141, -20, -184, 1322, 311, +223, 220, -1163, -347, -403, -382, 971, 370, +533, 797, -672, -283, -528, -1089, 212, 188, +368, 937, 369, -74, -139, -291, -843, 53, +-158, -436, 1131, -112, 464, 852, -1214, 40, +-694, -1004, 1054, 48, 863, 980, -720, -47, +-807, -969, 220, -316, 579, 685, 330, 814, +-394, -212, -655, -1354, 257, -347, 794, 1677, +-263, 742, -686, -1792, 259, -1099, 419, 1635, +-150, 1511, -251, -1122, 105, -1913, 134, 364, +-25, 2174, -58, 438, -68, -2033, -173, -1007, +138, 1691, 624, 1432, -133, -1249, -988, -1639, +-11, 870, 1055, 1765, 255, -372, -892, -1650, +-522, -208, 725, 1311, 761, 888, -662, -773, +-888, -1498, 719, 173, 788, 1813, -740, 342, +-588, -1828, 652, -767, 528, 1590, -527, 999, +-519, -1280, 222, -1222, 489, 745, 154, 1332, +-197, -73, -567, -1336, -347, -725, 1006, 1048, +807, 1262, -1122, -638, -1193, -1395, 858, 194, +1423, 1215, -247, 189, -1483, -1020, -519, -517, +1475, 987, 1025, 882, -1242, -997, -1311, -1159, +863, 1001, 1509, 1370, -516, -743, -1610, -1390, +116, 292, 1658, 1331, 296, 400, -1442, -1037, +-831, -995, 975, 633, 1384, 1252, -500, -195, +-1578, -1036, 126, -98, 1295, 628, 65, 257, +-703, -317, -153, -397, 76, 137, 273, 463, +261, -79, -256, -503, -349, -29, 75, 481, +246, 108, 173, -606, -53, -304, -327, 705, +-156, 542, 323, -615, 307, -823, -238, 142, +-406, 963, 197, 434, 369, -893, -149, -771, +-231, 635, 54, 747, 68, -255, 90, -485, +-1, -96, -209, 348, 19, 386, 217, -363, +-13, -398, -11, 563, -149, 146, -327, -726, +409, 359, 600, 892, -558, -809, -608, -947, +496, 1063, 324, 830, -207, -1013, 44, -459, +-229, 737, -246, -79, 634, -381, 396, 587, +-1003, 37, -654, -902, 1161, 155, 1126, 763, +-1067, -215, -1602, -305, 807, 184, 1741, -302, +-451, -356, -1551, 629, 167, 619, 1164, -549, +91, -844, -769, 153, -342, 739, 380, 103, +609, -268, -16, 28, -885, -385, -212, -494, +1153, 1040, 201, 1110, -1362, -1582, -17, -1623, +1366, 2064, -80, 2005, -1066, -2323, -92, -2093, +457, 2355, 480, 1958, 288, -2088, -816, -1656, +-976, 1725, 926, 1488, 1448, -1410, -772, -1483, +-1620, 1291, 417, 1510, 1482, -1312, 26, -1397, +-971, 1349, -562, 1127, 248, -1340, 1025, -919, +514, 1178, -1214, 936, -1106, -997, 958, -1204, +1345, 780, -245, 1322, -1312, -585, -540, -1205, +1134, 429, 1007, 935, -993, -466, -1111, -878, +1009, 496, 975, 1153, -935, -311, -932, -1466, +664, -167, 984, 1361, -301, 790, -937, -695, +-79, -1163, 823, -176, 237, 1148, -513, 1007, +-290, -724, 71, -1595, 192, 116, 386, 1981, +209, 684, -789, -1997, -747, -1470, 886, 1563, +1222, 2084, -756, -607, -1396, -2279, 568, -579, +1217, 1965, -330, 1621, -941, -1233, 128, -2251, +588, 337, 89, 2279, -221, 392, -204, -1744, +-131, -867, 118, 724, 368, 932, 190, 455, +-400, -626, -661, -1463, 167, -72, 1159, 1872, +225, 955, -1410, -1648, -686, -1765, 1260, 986, +1095, 2179, -784, -158, -1419, -2057, 143, -652, +1631, 1363, 500, 1364, -1541, -112, -1026, -1780, +973, -1372, 1219, 1632, -69, 2672, -871, -674, +-745, -3199, 81, -735, 1052, 2683, 786, 2039, +-850, -1216, -1368, -2622, 355, -534, 1600, 2372, +158, 1965, -1515, -1514, -645, -2719, 1183, 429, +965, 2772, -545, 675, -981, -2219, -313, -1703, +659, 1146, 1119, 2299, -111, 118, -1628, -2171, +-402, -1096, 1690, 1334, 750, 1253, -1451, -364, +-1001, -677, 1096, -173, 1236, -140, -704, 102, +-1446, 649, 241, 185, 1503, -751, 214, -355, +-1328, 606, -539, 369, 1038, -319, 594, -221, +-697, -43, -455, -158, 238, 289, 226, 797, +430, 18, 146, -1268, -1221, -933, -705, 1084, +1776, 2077, 1465, 0, -1899, -2734, -2253, -1602, +1628, 2551, 2908, 3154, -1118, -1498, -3283, -4113, +437, -170, 3248, 4181, 397, 2025, -2802, -3274, +-1213, -3482, 2090, 1655, 1756, 3933, -1420, -11, +-1775, -3259, 977, -1004, 1398, 1810, -877, 1007, +-936, -387, 992, -231, 861, -372, -1100, -825, +-1358, 79, 980, 1445, 2152, 1063, -468, -1161, +-2830, -2413, -307, -122, 3018, 3181, 1125, 1974, +-2658, -2903, -1750, -3638, 1844, 1632, 1984, 4453, +-711, 235, -1773, -4035, -477, -2006, 1150, 2533, +1392, 3036, -292, -455, -1809, -2875, -508, -1410, +1675, 1644, 1154, 2535, -1241, 104, -1509, -2765, +686, -1620, 1569, 2294, -176, 2501, -1348, -1372, +-260, -2656, 908, 297, 629, 2256, -344, 627, +-850, -1645, -301, -1209, 802, 1089, 901, 1492, +-396, -659, -1332, -1734, -260, 103, 1458, 1864, +986, 732, -1223, -1551, -1623, -1733, 607, 516, +1978, 2399, 336, 910, -1887, -2322, -1252, -2085, +1182, 1413, 1756, 2491, -85, 38, -1531, -2052, +-1031, -1519, 661, 1022, 1673, 2435, 529, 291, +-1497, -2239, -1638, -1440, 426, 1016, 2192, 2003, +1147, 574, -1863, -1661, -2438, -1576, 730, 648, +2705, 1538, 673, 506, -1869, -636, -1681, -1099, +472, -472, 1841, 703, 789, 1199, -1099, 588, +-1446, -1130, -274, -2086, 1314, 178, 1682, 2875, +-479, 1244, -2414, -2434, -698, -2448, 2142, 954, +1668, 2754, -1129, 789, -2004, -2102, -51, -2120, +1720, 879, 920, 2689, -1087, 286, -1363, -2562, +465, -1030, 1433, 1925, -121, 1228, -1142, -1049, +59, -1010, 633, 195, -195, 584, -14, 378, +391, -78, -514, -588, -612, -466, 819, 517, +912, 969, -825, -219, -1183, -1150, 488, -234, +1232, 775, 51, 647, -802, 261, -574, -580, +-34, -1605, 651, -255, 980, 2650, -122, 1760, +-1441, -2712, -876, -3282, 1162, 1540, 1661, 3903, +-302, 406, -1624, -3036, -539, -2074, 736, 969, +692, 2383, 432, 1096, -63, -1077, -980, -1930, +-1008, -1102, 491, 1085, 1836, 2766, 780, 741, +-1827, -2971, -2058, -2393, 864, 1666, 2476, 2877, +669, 269, -1698, -1894, -1961, -1700, 13, -68, +2311, 1854, 1771, 1951, -1531, -751, -2814, -2654, +86, -752, 2646, 1826, 1186, 1590, -1379, -100, +-1518, -1224, -226, -1295, 688, 152, 1175, 1566, +708, 723, -820, -780, -1686, -804, -507, -228, +1483, 240, 1757, 672, -200, 493, -1944, -299, +-1305, -857, 777, -527, 2050, 577, 1042, 1175, +-1476, 192, -2485, -1209, -95, -942, 2795, 637, +1667, 1138, -1934, -20, -2364, -756, 570, -128, +1924, 176, 570, -228, -867, 106, -1087, 571, +-135, 12, 941, -485, 726, -253, -350, -25, +-815, 189, -344, 609, 482, 362, 727, -897, +58, -1181, -514, 655, -485, 1801, -79, 136, +535, -1788, 637, -1081, -204, 1132, -899, 1671, +-296, -189, 856, -1588, 736, -408, -586, 1072, +-937, 386, 174, -594, 786, 11, 292, 515, +-423, -249, -586, -767, 86, 63, 576, 965, +89, 351, -377, -796, -85, -611, 89, 289, +57, 418, 61, 139, 71, 124, -93, -168, +-297, -667, -40, -147, 544, 820, 266, 360, +-577, -630, -459, -267, 289, 408, 532, 30, +99, -404, -467, 29, -316, 520, 396, 242, +220, -512, -384, -679, -104, 293, 450, 983, +230, 180, -337, -802, -598, -740, -170, 33, +773, 991, 969, 1153, -280, -386, -1639, -2023, +-806, -1046, 1583, 1755, 1928, 2504, -632, -63, +-2313, -2861, -808, -2225, 1610, 1610, 1942, 3648, +-158, 602, -2040, -3248, -1240, -2439, 1047, 1314, +1894, 2789, 351, 746, -1575, -1738, -1284, -1731, +787, 303, 1331, 1383, -223, 382, -818, -522, +176, -147, 489, 80, -379, -383, -683, -378, +220, 463, 1076, 861, 567, 121, -991, -820, +-1526, -977, 50, 69, 1898, 1425, 1352, 918, +-1187, -1060, -2303, -1396, -363, 201, 2103, 990, +1812, 458, -734, 79, -2286, -288, -981, -1034, +1511, -610, 1942, 1156, 26, 1557, -1607, -291, +-1278, -1645, 201, -867, 1499, 569, 1285, 1330, +-595, 1010, -1907, -637, -741, -1850, 1390, -720, +1615, 1154, -215, 1603, -1621, 589, -904, -1196, +985, -2016, 1535, -319, -153, 1994, -1661, 1762, +-598, -622, 1272, -2061, 1181, -995, -383, 1142, +-1420, 1636, -786, 99, 1040, -1042, 1679, -701, +-87, -57, -1724, 350, -939, 698, 862, 536, +1329, -404, 294, -1209, -751, -560, -840, 1087, +-393, 1566, 294, -91, 1106, -1868, 1004, -1188, +-644, 1151, -1941, 1930, -823, 270, 1581, -1603, +2100, -1485, 24, 430, -2045, 1745, -1665, 854, +563, -914, 2002, -1506, 1165, -436, -697, 1216, +-1686, 1490, -1240, -296, 513, -1697, 2287, -651, +1467, 1072, -1665, 1100, -2765, -194, -145, -969, +2569, -340, 1837, 432, -1128, 286, -2390, 87, +-493, 62, 1682, -284, 1360, -322, -384, 134, +-1285, 282, -643, 106, 668, -74, 1056, -182, +-21, -59, -1021, 117, -522, -22, 782, -36, +998, 291, -355, 113, -1240, -589, -300, -367, +947, 743, 881, 717, -92, -611, -881, -874, +-865, 215, 189, 703, 1253, 282, 770, -279, +-844, -579, -1379, -127, -31, 491, 1249, 366, +849, -54, -511, -396, -1142, -456, -362, 126, +781, 690, 854, 404, -82, -461, -756, -922, +-439, -123, 358, 992, 469, 620, -79, -467, +-244, -630, 56, -381, 205, 102, -113, 1003, +-405, 579, -51, -1094, 586, -1025, 378, 805, +-427, 1147, -614, -494, -1, -1070, 570, 285, +276, 823, -403, -44, -137, -275, 399, -137, +-105, -389, -568, -18, -71, 613, 504, 541, +572, 2, 110, -830, -693, -1003, -896, 348, +-39, 1416, 1102, 701, 1115, -679, -406, -1378, +-1676, -694, -685, 1010, 1331, 1566, 1389, 137, +-404, -1284, -1317, -1015, -364, 293, 578, 737, +450, 210, 299, 387, 94, 415, -588, -1031, +-742, -1500, 82, 239, 786, 1668, 683, 1279, +-103, -404, -890, -1892, -664, -1288, 288, 845, +743, 1871, 542, 831, 45, -924, -832, -1560, +-1054, -416, 331, 871, 1373, 775, 533, 158, +-679, 16, -867, -286, -515, -835, 241, -505, +1248, 750, 802, 1165, -900, -25, -1356, -975, +-62, -423, 893, 439, 705, 337, 192, -301, +-527, -225, -999, 472, -229, 419, 949, -311, +839, -610, -61, -242, -776, 491, -982, 572, +-15, -294, 1345, -410, 1101, 372, -847, 122, +-1687, -534, -164, -126, 1515, 275, 971, 215, +-835, 411, -1249, 47, 44, -843, 1049, -659, +612, 425, -409, 959, -943, 492, -563, -487, +636, -828, 1432, -234, 253, 151, -1444, 111, +-1118, 537, 451, 994, 1164, 54, 753, -1697, +-267, -1586, -1067, 788, -873, 2250, 211, 994, +1283, -1006, 1062, -1547, -629, -871, -1720, 131, +-451, 1227, 1302, 1578, 1095, 304, -312, -1485, +-884, -1772, -424, -381, 174, 1297, 494, 1961, +337, 708, -181, -1661, -272, -2163, -20, 59, +-118, 1819, -61, 1033, 328, -510, 193, -849, +-181, -280, -144, 222, -59, 188, -58, -113, +118, 35, 213, 391, -84, 30, -237, -404, +101, -54, 259, 166, -144, -215, -350, -219, +154, 379, 386, 618, -101, -44, -359, -748, +29, -489, 377, 334, 20, 652, -400, 199, +-132, -380, 382, -337, 234, 193, -196, 196, +-368, -319, -126, -201, 447, 405, 575, 390, +-190, -111, -975, -397, -461, -335, 791, 72, +1158, 441, 92, 257, -1144, -234, -1007, -273, +232, 146, 1057, 175, 726, -361, -174, -359, +-759, 424, -646, 766, -116, 48, 488, -851, +865, -819, 446, 306, -633, 1185, -1112, 490, +-292, -843, 813, -794, 924, 159, 42, 313, +-702, 132, -503, 448, 37, 288, 264, -641, +350, -868, 103, 38, -243, 784, -201, 639, +71, -42, 139, -553, 76, -366, -195, 26, +-355, -107, 93, -132, 621, 635, 389, 1002, +-420, -119, -728, -1346, -158, -1008, 388, 257, +304, 1186, 295, 1189, 254, -27, -352, -1303, +-755, -927, -357, 152, 383, 372, 981, 514, +542, 851, -869, 139, -1090, -1030, 397, -934, +952, 14, -182, 473, -563, 640, 209, 766, +297, 57, -171, -1224, 9, -1193, 95, 400, +-389, 1328, -277, 556, 426, -455, 654, -481, +137, -131, -634, -362, -902, -337, 15, 812, +1058, 1170, 723, -343, -423, -1291, -888, -405, +-301, 601, 367, 686, 454, 127, 99, -464, +-83, -294, 28, 244, -75, 58, -489, -321, +-352, 36, 597, 469, 905, 254, -62, -303, +-943, -640, -592, -309, 414, 666, 773, 1017, +98, -227, -476, -1346, -88, -315, 213, 1084, +-271, 529, -346, -521, 415, -403, 701, 62, +-126, 254, -697, 122, -262, -286, 204, -189, +144, 439, 255, 326, 453, -439, -99, -576, +-779, 90, -582, 778, 316, 570, 888, -642, +575, -1136, -317, 161, -910, 1249, -664, 318, +180, -996, 1103, -525, 943, 770, -544, 680, +-1475, -556, -364, -965, 1084, 35, 794, 1049, +-429, 645, -674, -634, 106, -903, 560, 157, +96, 711, -616, -68, -524, -657, 326, 65, +854, 725, 338, 158, -438, -330, -649, 6, +-355, -268, 105, -955, 568, -36, 596, 1577, +21, 1173, -577, -767, -599, -1569, 47, -561, +554, 598, 290, 657, -258, 377, -290, 329, +57, -217, 290, -754, 155, -212, -273, 322, +-447, -73, -43, -186, 412, 433, 401, 603, +58, -38, -266, -546, -406, -375, -211, -72, +215, -82, 397, 138, 97, 615, -166, 486, +-99, -183, -40, -533, -1, -480, 86, -320, +-39, 126, -169, 762, 24, 740, 237, -157, +121, -776, -48, -412, -187, 83, -216, 186, +-35, 151, 321, 146, 338, 244, -202, 112, +-502, -415, -16, -498, 439, -3, 166, 292, +-82, 447, -117, 397, -309, -381, -260, -889, +372, -134, 670, 755, 25, 612, -690, -203, +-520, -667, 287, -169, 668, 473, 209, 111, +-496, -461, -528, -58, 170, 633, 678, 331, +276, -561, -566, -644, -708, 146, 124, 629, +829, 363, 310, -379, -596, -830, -433, 54, +352, 1157, 303, 357, -287, -1053, -159, -678, +438, 507, 126, 667, -705, -27, -381, -452, +797, -48, 787, 321, -433, -155, -859, -244, +-80, 416, 495, 209, 205, -634, -138, -419, +-33, 524, 186, 816, -45, 78, -385, -896, +-171, -827, 380, 411, 388, 1174, -36, 382, +-275, -868, -331, -986, -217, -28, 307, 902, +624, 1023, 85, -56, -450, -1322, -292, -844, +-59, 756, -117, 1014, 153, 3, 578, -600, +379, -374, -356, 190, -766, 453, -371, 165, +396, -221, 674, -586, 225, -539, -217, 580, +-309, 1412, -275, 220, -109, -1425, 252, -1177, +329, 383, 20, 1179, -66, 696, 30, -136, +-208, -743, -435, -874, 47, -82, 667, 859, +429, 715, -399, -129, -702, -555, -96, -250, +561, 218, 323, -55, -290, -509, -178, 289, +239, 1159, -4, 220, -405, -1203, -122, -980, +448, 351, 452, 1069, -152, 474, -578, -452, +-210, -487, 402, 114, 306, 150, -227, -461, +-305, -405, 84, 663, 413, 940, 231, -133, +-366, -683, -592, -310, 126, -170, 613, -117, +-34, 286, -510, 665, 184, 654, 551, -272, +-198, -1351, -604, -740, -72, 906, 437, 1209, +388, 175, -50, -789, -583, -900, -311, 76, +528, 1054, 471, 410, -423, -962, -372, -747, +399, 769, 328, 1041, -327, -274, -396, -1000, +23, -318, 293, 483, 267, 497, -79, -2, +-235, -278, 36, -46, 204, 119, -167, 37, +-400, -39, -16, -210, 575, -231, 561, 187, +-261, 359, -959, 101, -440, -11, 722, -77, +890, -284, -78, -325, -732, -177, -311, 353, +323, 960, 312, 416, -79, -1049, -242, -1349, +-69, 152, 187, 1549, 239, 878, -84, -858, +-343, -1109, 1, 17, 439, 612, 95, 369, +-472, -166, -329, -487, 217, 46, 397, 634, +238, 140, -88, -575, -349, -399, -216, 184, +83, 336, 99, 22, 54, 21, 150, 258, +91, -122, -80, -525, -209, -120, -235, 225, +51, 293, 471, 379, 202, -132, -449, -668, +-321, -103, 289, 487, 245, 157, -164, -295, +-105, -178, 107, 339, 40, 385, -42, -365, +-61, -622, -55, 182, 79, 662, 163, 110, +-85, -626, -212, -457, 33, 475, 282, 749, +115, -49, -251, -616, -306, -400, 83, 92, +290, 404, 40, 231, -65, -161, 67, -155, +-12, 31, -217, 85, -70, 67, 159, -53, +110, -190, -122, -126, -55, 102, 134, 271, +57, 43, -80, -238, 56, 81, -16, 275, +-272, -176, -57, -283, 352, 18, 127, -110, +-292, -45, -71, 527, 288, 493, 63, -320, +-318, -768, -127, -342, 230, 462, 179, 700, +-99, 79, -177, -542, -49, -377, 155, 233, +169, 389, -89, -147, -226, -399, 62, 235, +290, 603, -15, -182, -415, -770, -174, -63, +394, 661, 383, 222, -158, -395, -397, -243, +-124, 95, 283, 293, 341, 384, -158, -156, +-529, -863, 19, -328, 621, 790, 167, 704, +-547, -214, -356, -507, 263, -154, 424, 79, +96, -2, -299, 51, -238, 307, 183, 100, +214, -458, -228, -257, -282, 400, 168, 227, +362, -265, 100, 16, -147, 283, -209, -295, +-101, -527, 81, 312, 19, 734, -168, -71, +76, -642, 473, -178, 205, 294, -474, 248, +-561, 162, 74, -33, 556, -449, 246, -438, +-341, 249, -317, 784, 194, 380, 372, -527, +-33, -778, -443, -91, -287, 508, 294, 362, +468, -14, 47, -138, -262, -94, -123, 0, +-73, -45, -156, -220, 75, -19, 423, 373, +222, 155, -385, -225, -582, -45, 121, 132, +824, -73, 318, -210, -825, -127, -764, 114, +465, 342, 921, 211, 10, -171, -769, -394, +-286, -240, 594, 292, 464, 551, -454, -50, +-649, -606, 99, -290, 604, 293, 319, 532, +-130, 314, -364, -345, -352, -683, 16, -153, +423, 443, 213, 413, -292, 133, -216, -141, +275, -460, 291, -448, -175, 254, -401, 919, +-143, 389, 183, -816, 307, -940, 245, 193, +-89, 843, -468, 250, -237, -372, 431, -56, +464, 311, -266, -201, -637, -670, -72, -15, +612, 723, 464, 357, -302, -342, -617, -303, +-111, 109, 476, 93, 365, -239, -169, -106, +-386, 376, -141, 238, 170, -389, 326, -335, +160, 376, -285, 486, -410, -271, 61, -658, +456, 20, 219, 653, -269, 217, -416, -466, +-56, -317, 426, 264, 374, 342, -272, -159, +-560, -332, 22, 115, 570, 293, 233, -48, +-373, -175, -385, -143, 124, -58, 412, 344, +2, 367, -481, -322, -109, -436, 573, 112, +265, 129, -460, -79, -244, 264, 266, 372, +-52, -379, -288, -794, 283, 145, 467, 1077, +-180, 323, -496, -991, -154, -839, 237, 467, +442, 1106, 180, 277, -501, -912, -567, -731, +224, 407, 704, 659, 293, 17, -405, -266, +-743, -165, -244, -77, 782, 50, 861, 225, +-342, 161, -1022, -223, -240, -388, 706, 112, +616, 542, -183, 190, -744, -415, -374, -561, +563, -87, 809, 582, -15, 586, -787, -69, +-557, -495, 249, -511, 661, -146, 308, 542, +-276, 652, -432, -104, -113, -537, 129, -280, +129, 61, 175, 300, 187, 387, -123, 10, +-439, -584, -223, -580, 314, 377, 453, 1038, +30, 260, -333, -862, -202, -845, 80, 15, +106, 822, 19, 764, 29, -260, 38, -816, +-23, -220, -88, 316, -74, 252, 3, 107, +128, -51, 183, -115, -35, -93, -346, -171, +-154, 48, 408, 490, 369, 202, -397, -540, +-596, -560, 283, 225, 782, 749, -45, 226, +-802, -647, -181, -441, 605, 429, 199, 438, +-352, -296, 4, -445, 234, 151, -253, 538, +-327, 120, 312, -473, 513, -373, -95, 187, +-594, 301, -267, 8, 492, 16, 573, 166, +-264, -145, -681, -476, 35, -105, 574, 397, +87, 363, -365, 93, -71, -225, 215, -527, +43, -161, -173, 572, -131, 468, 146, -348, +316, -548, -40, 20, -514, 424, -166, 222, +599, -102, 461, -230, -417, -184, -678, 96, +-23, 299, 550, -70, 369, -383, -192, 87, +-344, 506, 30, 102, 201, -390, -166, -338, +-292, -9, 236, 268, 489, 251, -72, 19, +-488, -121, -55, -161, 400, -158, 52, 75, +-417, 280, -125, 133, 445, -181, 303, -331, +-296, -186, -386, 287, 76, 580, 296, 167, +70, -535, -156, -646, -157, -88, -9, 549, +213, 716, 249, 152, -91, -694, -426, -767, +-254, 36, 263, 660, 509, 571, 204, 41, +-355, -514, -519, -580, -58, -85, 458, 372, +321, 515, -179, 315, -339, -291, -75, -718, +136, -280, 137, 469, 110, 630, 125, 131, +-81, -449, -457, -543, -359, -95, 401, 377, +742, 538, 34, 234, -646, -433, -336, -719, +283, -61, 289, 609, -72, 374, -172, -133, +76, -241, 164, -202, -100, -59, -270, 236, +57, 252, 384, -29, 124, -307, -391, -408, +-345, 84, 211, 835, 405, 442, -6, -773, +-238, -842, 20, 243, 109, 710, -220, 178, +-257, -327, 214, -247, 496, 119, 169, 328, +-362, 89, -562, -509, -149, -582, 513, 386, +563, 1015, -146, 158, -593, -905, -138, -661, +429, 363, 252, 796, -328, 158, -327, -644, +249, -450, 450, 363, -89, 551, -492, -74, +-187, -532, 353, -122, 396, 429, -25, 98, +-316, -300, -177, 151, 16, 261, 56, -461, +133, -468, 182, 471, -15, 772, -199, -27, +-132, -754, 3, -435, 113, 394, 183, 462, +14, -138, -302, -309, -171, 116, 355, 442, +389, 93, -276, -659, -603, -592, 22, 459, +660, 921, 281, 92, -495, -786, -447, -588, +215, 399, 387, 863, 13, 97, -205, -837, +-114, -638, -1, 348, 134, 875, 197, 391, +-38, -480, -373, -757, -191, -232, 408, 448, +475, 578, -250, 110, -635, -324, -26, -360, +587, -153, 291, 213, -345, 421, -433, 34, +3, -396, 373, -147, 247, 262, -178, 175, +-299, -172, 45, -245, 257, 69, 10, 314, +-233, 75, -84, -180, 145, -140, 176, -147, +27, -75, -156, 387, -144, 512, 60, -202, +79, -847, -39, -407, 121, 663, 262, 1005, +-211, 54, -678, -1067, -22, -834, 969, 531, +521, 1072, -847, 133, -913, -658, 363, -370, +894, 50, 146, 106, -520, 259, -410, 286, +43, -145, 364, -440, 277, -107, -156, 286, +-316, 212, -25, -72, 186, -140, 91, -49, +-11, 76, -99, 135, -130, -7, 33, -206, +157, -132, -1, 90, -86, 215, 58, 204, +81, -42, -46, -320, -121, -138, -142, 94, +-35, -89, 288, 7, 361, 536, -124, 374, +-545, -497, -206, -833, 400, -218, 432, 700, +-38, 903, -367, -2, -321, -900, 23, -560, +408, 337, 371, 553, -134, 127, -472, -194, +-217, -205, 218, -65, 310, 95, 77, 124, +-99, -91, -99, -153, -112, 129, -136, 224, +57, -59, 333, -171, 158, -52, -286, 8, +-269, 12, 131, 33, 203, 106, -35, 157, +-108, -93, -45, -371, 59, -49, 148, 421, +25, 201, -246, -371, -135, -323, 213, 265, +224, 447, -70, -46, -202, -405, -78, -266, +49, 148, 89, 471, 107, 223, -25, -491, +-173, -532, 8, 322, 259, 752, -12, 14, +-358, -778, -92, -405, 296, 560, 178, 577, +-68, -244, -96, -453, -167, 115, -71, 347, +292, -121, 207, -457, -395, -18, -328, 602, +438, 338, 475, -479, -304, -644, -576, 99, +43, 748, 495, 412, 179, -580, -317, -811, +-230, 76, 172, 845, 141, 516, -95, -378, +-87, -739, 70, -203, 92, 436, 4, 449, +-162, 6, -149, -312, 155, -232, 294, 76, +-3, 235, -315, 169, -127, -99, 187, -398, +131, -170, -117, 405, -105, 424, 115, -86, +219, -343, -22, -310, -348, -96, -184, 308, +341, 508, 359, 124, -182, -461, -445, -574, +-35, 26, 392, 588, 253, 379, -203, -250, +-301, -435, -36, -98, 127, 280, 133, 242, +115, -67, -30, -242, -281, -168, -158, 94, +295, 375, 348, 193, -199, -336, -445, -392, +26, 38, 390, 244, 155, 157, -198, 137, +-212, -7, -12, -346, 153, -322, 89, 246, +-75, 446, -45, -9, 39, -334, 24, -171, +-7, 85, 38, 327, -86, 223, -198, -372, +65, -582, 442, 164, 169, 768, -522, 287, +-496, -610, 284, -663, 637, 147, 107, 671, +-398, 268, -252, -339, 56, -356, 29, -28, +-15, 131, 168, 124, 210, 154, -43, 76, +-221, -200, -174, -336, -5, -55, 119, 340, +141, 428, 103, 18, 14, -523, -204, -529, +-247, 144, 72, 698, 284, 512, 104, -265, +-106, -792, -154, -423, -136, 413, 98, 637, +365, 185, 43, -254, -552, -356, -320, -192, +596, 117, 642, 246, -335, 42, -783, -148, +-40, 25, 624, 242, 247, -36, -359, -419, +-191, -146, 238, 396, 16, 274, -299, -188, +29, -204, 423, 87, 111, 60, -365, -158, +-301, -96, 137, 171, 350, 190, 152, 53, +-220, -81, -332, -273, -50, -268, 299, 170, +238, 486, -40, 190, -119, -343, -135, -408, +-242, 51, -29, 358, 445, 127, 343, -172, +-347, -216, -529, -76, 151, 271, 569, 373, +61, -150, -528, -534, -325, -131, 305, 355, +521, 323, 128, 19, -444, -204, -555, -275, +-12, -126, 644, 245, 596, 447, -220, -1, +-787, -529, -392, -336, 406, 239, 580, 462, +184, 268, -223, -203, -376, -515, -291, -248, +108, 279, 473, 454, 292, 107, -236, -316, +-445, -252, -147, 74, 251, 137, 382, 130, +95, 54, -331, -274, -332, -286, 68, 229, +296, 443, 232, 82, 40, -361, -298, -390, +-484, 86, 42, 407, 667, 107, 347, -184, +-516, -81, -574, 41, 146, -16, 538, -59, +202, 38, -269, 120, -312, -46, -54, -106, +132, 131, 137, 82, 146, -252, 14, -141, +-265, 276, -194, 263, 221, -193, 302, -350, +-119, 129, -258, 379, -7, -119, 83, -449, +-57, -17, 109, 481, 351, 396, -16, -282, +-611, -690, -378, -90, 502, 609, 643, 285, +-80, -294, -494, -226, -184, 98, 106, 143, +83, -23, 102, -161, 127, -94, -21, 97, +-173, 235, -144, 85, 51, -258, 250, -163, +120, 239, -323, 108, -308, -282, 249, -101, +460, 276, -33, 216, -427, -115, -229, -264, +202, -41, 356, 202, 76, 41, -298, -183, +-277, -16, 109, 264, 256, 139, 47, -288, +-36, -309, -34, 192, -212, 333, -173, -75, +307, -225, 401, 15, -163, 152, -512, 69, +-104, -158, 409, -201, 281, 91, -160, 238, +-281, 84, 12, -20, 153, -133, 29, -294, +-88, -131, -27, 349, 41, 530, 62, 5, +14, -645, -82, -437, -40, 357, 136, 529, +50, 24, -259, -283, -86, -174, 396, 38, +202, 132, -407, 26, -321, -88, 303, -22, +362, 90, -158, 28, -359, -55, 45, 49, +375, 54, 119, -256, -310, -197, -275, 390, +127, 423, 272, -310, 62, -538, -114, 55, +-66, 485, -20, 236, 0, -286, 11, -448, +5, -55, 17, 417, 72, 409, -1, -77, +-102, -473, -41, -289, 87, 181, 8, 273, +-83, 58, 17, 32, 131, 123, -7, -95, +-160, -461, -49, -263, 133, 436, 50, 588, +-163, -80, -93, -477, 178, -174, 240, 133, +-62, 157, -308, 68, -210, -144, 81, -144, +255, 221, 235, 281, -2, -210, -280, -372, +-305, 52, -28, 230, 261, -36, 335, 22, +32, 287, -381, -51, -355, -558, 210, -236, +530, 500, 58, 566, -598, -122, -414, -659, +432, -310, 759, 455, 30, 539, -793, -106, +-575, -460, 401, -156, 798, 165, 153, 88, +-545, 57, -441, 252, 146, 80, 376, -453, +107, -448, -179, 142, -94, 560, 94, 462, +94, -145, -69, -788, -107, -464, 11, 581, +140, 788, 92, -121, 2, -708, -54, -247, +-110, 362, -69, 351, 159, 76, 252, -156, +-28, -372, -294, -229, -134, 296, 225, 427, +316, 43, 17, -185, -334, -196, -280, -229, +203, -91, 487, 338, 100, 500, -450, -20, +-370, -608, 215, -317, 445, 395, 64, 395, +-316, -198, -159, -342, 174, 143, 128, 378, +-109, -85, -66, -404, 32, -81, -55, 210, +-31, 229, 185, 201, 102, -182, -229, -537, +-259, -35, 65, 579, 217, 276, 84, -329, +-75, -379, -135, -27, -120, 274, -3, 265, +103, 41, 26, -204, -75, -348, -3, -168, +76, 338, -85, 531, -190, 48, 38, -522, +210, -450, -74, 100, -273, 446, 73, 332, +311, -58, -68, -421, -342, -270, -27, 228, +209, 255, -15, -112, -107, -79, 111, 199, +110, 120, -208, -230, -246, -365, 97, 37, +288, 485, 97, 228, -112, -309, -129, -275, +-124, 55, -99, 130, 155, 10, 381, -18, +123, 81, -348, 50, -325, -192, 119, -129, +328, 229, 153, 215, -94, -184, -190, -297, +-69, 36, 183, 310, 214, 119, -47, -200, +-190, -168, 27, 44, 191, 106, 39, 35, +-80, -66, 57, -46, 69, 82, -143, 56, +-73, -58, 318, -83, 294, -39, -249, 93, +-439, 157, 8, -101, 421, -234, 339, 114, +-72, 331, -411, -72, -287, -424, 226, -101, +459, 408, 109, 274, -281, -187, -287, -248, +-66, -75, 190, 23, 300, 182, 54, 135, +-275, -132, -235, -51, 26, 126, 145, -126, +176, -242, 51, 131, -287, 306, -307, 62, +195, -168, 381, -215, -128, -110, -428, 155, +-34, 281, 293, 45, 72, -222, -192, -127, +-138, 47, -5, 35, 7, 36, -32, 65, +-17, -31, 65, -17, 95, 82, -88, -31, +-307, -204, -164, -130, 214, 140, 290, 370, +4, 210, -201, -296, -231, -515, -184, -163, +77, 380, 425, 582, 247, 122, -367, -565, +-467, -511, 26, 202, 288, 485, 161, 111, +120, -178, 5, -158, -340, -117, -318, -20, +257, 240, 508, 224, 16, -152, -441, -285, +-170, -38, 344, 149, 291, 190, -213, 53, +-268, -254, 238, -175, 364, 270, -195, 192, +-392, -277, 192, -193, 515, 224, -11, 197, +-454, -92, -116, -131, 386, -11, 333, 24, +-78, -3, -287, 2, -162, 36, 127, 81, +345, 5, 265, -134, -176, -19, -448, 124, +-105, -112, 426, -203, 412, 252, -62, 417, +-365, -132, -245, -508, 56, -230, 305, 255, +272, 464, -42, 181, -298, -331, -183, -405, +69, 22, 161, 287, 106, 110, 10, -43, +-117, 39, -192, -50, -61, -275, 178, -56, +187, 358, -126, 216, -271, -238, -5, -296, +187, 28, -20, 276, -199, 161, -53, -216, +123, -292, 52, 114, -84, 370, -130, 66, +-95, -336, -23, -273, 108, 126, 114, 343, +-66, 144, -241, -217, -142, -283, 100, 40, +199, 205, 42, 0, -167, -38, -218, 105, +-60, -57, 147, -204, 174, 27, -43, 197, +-205, 105, -65, -27, 119, -216, 41, -264, +-108, 156, -21, 520, 171, 114, 97, -570, +-196, -429, -216, 404, 103, 594, 286, -156, +75, -572, -137, -97, -114, 399, 33, 301, +84, -93, 61, -336, -7, -217, -9, 122, +61, 312, 93, 156, -27, -117, -88, -224, +49, -116, 142, 71, 24, 144, -48, 32, +47, -44, 115, 23, -25, 19, -169, -54, +-1, -38, 351, -82, 276, -54, -266, 227, +-489, 236, 1, -210, 562, -301, 400, 59, +-229, 170, -506, 81, -115, 33, 311, -122, +270, -210, -5, 53, -72, 301, -69, 139, +-173, -246, -111, -363, 226, -2, 306, 413, +-30, 280, -317, -216, -231, -372, 53, -49, +287, 217, 172, 164, -203, -5, -312, -127, +16, -135, 236, 48, 55, 220, -208, 82, +-203, -256, 49, -311, 231, 121, 94, 491, +-213, 172, -277, -394, -68, -355, 107, 72, +162, 200, 161, 112, -47, 130, -368, 64, +-340, -238, 104, -369, 393, 20, 223, 432, +-175, 272, -364, -172, -196, -316, 104, -147, +231, 104, 187, 247, -27, 124, -296, -129, +-265, -166, 144, -10, 330, 85, 32, 30, +-205, -29, -61, 9, 59, 16, 7, -41, +35, 50, 62, 149, -79, -116, -63, -371, +178, 3, 136, 542, -163, 284, -148, -436, +154, -498, 196, 137, -37, 457, -111, 73, +56, -289, 94, -81, -57, 216, -48, 24, +197, -235, 218, -22, -112, 214, -316, 46, +-34, -125, 325, -37, 274, 33, -27, 27, +-167, 29, -152, -40, -39, -78, 145, 38, +219, 80, 93, -25, -40, 7, -137, 88, +-174, -91, -4, -243, 254, 22, 203, 307, +-102, 139, -196, -171, -19, -172, 52, 7, +-8, 47, 49, -30, 108, 0, -52, 164, +-195, 152, -56, -167, 159, -329, 140, 8, +-104, 318, -217, 90, -40, -211, 144, -53, +54, 191, -95, 61, -119, -211, -52, -199, +63, 94, 131, 309, -83, 126, -303, -216, +-78, -224, 315, 11, 167, 100, -307, 90, +-303, 86, 130, -14, 216, -127, -96, -95, +-216, -12, 45, 110, 225, 221, -15, -9, +-377, -367, -256, -142, 288, 388, 468, 278, +-12, -264, -500, -331, -340, 69, 223, 263, +433, 66, 32, -163, -304, -59, -117, 175, +162, 29, 35, -314, -141, -134, 43, 363, +272, 332, 23, -175, -314, -391, -145, -128, +310, 199, 299, 276, -137, 61, -319, -208, +52, -158, 357, 92, 100, 71, -273, -104, +-138, 35, 240, 194, 275, -58, -11, -233, +-214, 71, -128, 209, 88, -126, 202, -247, +185, 99, 89, 346, -108, 160, -278, -273, +-157, -530, 243, -119, 478, 636, 183, 621, +-378, -297, -471, -809, 72, -236, 562, 554, +290, 575, -364, -88, -449, -585, 140, -286, +446, 361, 127, 467, -238, -13, -264, -409, +-107, -350, 175, 90, 366, 501, 149, 321, +-324, -297, -451, -485, -45, -99, 390, 240, +333, 299, -109, 191, -425, -167, -229, -443, +247, -81, 329, 443, -127, 245, -419, -333, +-91, -352, 300, 167, 214, 457, -166, 143, +-311, -404, -139, -493, 100, 45, 203, 567, +114, 414, -178, -238, -362, -563, -85, -208, +305, 311, 232, 366, -153, 63, -334, -212, +-176, -264, 104, -62, 338, 224, 257, 274, +-253, 0, -668, -336, -230, -306, 642, 161, +682, 485, -245, 183, -806, -321, -270, -409, +522, -91, 511, 321, -134, 423, -459, -58, +-140, -516, 267, -131, 284, 498, 13, 252, +-192, -437, -181, -424, -40, 177, 142, 527, +327, 304, 271, -252, -203, -635, -596, -344, +-248, 443, 602, 805, 828, 173, -28, -747, +-887, -730, -526, 279, 542, 903, 863, 259, +119, -714, -657, -640, -510, 285, 290, 769, +703, 265, 220, -535, -477, -724, -492, -23, +171, 797, 617, 594, 240, -452, -408, -828, +-415, -42, 148, 645, 456, 361, 141, -258, +-265, -432, -241, -107, 61, 345, 202, 375, +119, -170, -63, -525, -146, -60, -55, 531, +50, 297, 56, -384, 88, -443, 50, 117, +-193, 430, -276, 168, 95, -211, 393, -319, +81, -143, -408, 197, -334, 463, 175, 222, +363, -479, 9, -737, -314, 60, -166, 983, +140, 654, 75, -679, -194, -1273, -62, -159, +271, 1370, 95, 1136, -415, -777, -363, -1706, +246, -229, 510, 1519, -4, 1112, -603, -686, +-392, -1424, 394, -332, 632, 1088, -45, 1088, +-709, -324, -497, -1343, 323, -602, 790, 991, +319, 1352, -631, -60, -933, -1513, -51, -1092, +974, 833, 760, 1842, -428, 449, -1032, -1655, +-387, -1656, 683, 559, 964, 2097, 79, 890, +-972, -1544, -813, -1939, 455, 288, 1186, 2088, +400, 1037, -885, -1287, -1029, -1772, 124, -56, +1135, 1557, 774, 1253, -521, -515, -1162, -1720, +-295, -822, 986, 1259, 1020, 1797, -246, -120, +-1158, -1961, -531, -1164, 850, 1223, 1146, 1981, +-70, 105, -1163, -1908, -670, -1410, 714, 912, +1171, 2038, 143, 528, -1015, -1678, -832, -1672, +400, 579, 1107, 2000, 431, 667, -717, -1486, +-901, -1509, 21, 451, 859, 1688, 653, 669, +-298, -1200, -875, -1479, -371, 283, 586, 1713, +759, 706, -24, -1329, -670, -1398, -414, 536, +293, 1629, 496, 393, 22, -1391, -374, -1208, +-196, 769, 149, 1682, 184, 125, 14, -1597, +-74, -973, -160, 933, -225, 1378, 25, 1, +451, -1175, 306, -716, -437, 613, -752, 988, +-78, -84, 774, -949, 695, -271, -316, 818, +-1032, 576, -511, -613, 635, -922, 1020, 183, +167, 1164, -951, 489, -966, -1056, 223, -1195, +1171, 469, 620, 1632, -816, 466, -1225, -1524, +33, -1426, 1258, 791, 707, 2004, -841, 381, +-1220, -1861, 81, -1535, 1260, 952, 720, 2151, +-807, 414, -1260, -1919, -53, -1700, 1246, 890, +920, 2386, -677, 573, -1407, -2160, -162, -1890, +1369, 1090, 950, 2530, -868, 398, -1421, -2255, +181, -1722, 1556, 1214, 597, 2416, -1265, 182, +-1257, -2290, 639, -1449, 1687, 1429, 320, 2168, +-1539, -137, -1209, -2087, 818, -1090, 1692, 1260, +349, 1776, -1359, -77, -1299, -1704, 410, -949, +1587, 1047, 749, 1453, -961, -174, -1356, -1381, +-31, -550, 1167, 921, 787, 947, -385, -309, +-794, -984, -316, -231, 291, 736, 573, 553, +359, -374, -223, -646, -680, 25, -379, 541, +504, 226, 886, -316, 94, -284, -911, 98, +-789, 127, 350, -61, 1191, 116, 597, 311, +-982, -191, -1508, -734, 103, -128, 1894, 1032, +1089, 836, -1485, -866, -2131, -1637, 281, 46, +2409, 2045, 1231, 1290, -1679, -1575, -2448, -2570, +114, 132, 2621, 3057, 1532, 1757, -1731, -2343, +-2584, -3246, 190, 655, 2628, 3720, 1284, 1337, +-1938, -3049, -2334, -3024, 724, 1434, 2704, 3948, +632, 774, -2424, -3751, -1855, -3005, 1472, 2295, +2537, 4489, -256, 80, -2603, -4624, -962, -2603, +2131, 3330, 1941, 4467, -1312, -998, -2682, -5121, +88, -1716, 2898, 4310, 1428, 4025, -2338, -2157, +-2805, -5116, 956, -661, 3484, 4532, 872, 3084, +-3195, -2624, -2566, -4267, 1928, 291, 3690, 4095, +19, 1645, -3766, -3017, -2056, -2857, 2652, 1498, +3512, 3343, -668, 142, -3753, -3105, -1441, -1561, +2847, 2264, 2956, 2439, -1171, -1197, -3375, -2713, +-600, 239, 2876, 2623, 1993, 580, -1638, -2348, +-2676, -1418, 172, 1750, 2619, 2200, 1160, -707, +-1803, -2553, -1919, -555, 712, 2241, 2038, 1583, +274, -1439, -1637, -2111, -882, 480, 1105, 2179, +1193, 470, -526, -1861, -1272, -1312, -15, 1204, +1246, 1898, 513, -361, -1054, -2044, -986, -435, +705, 1771, 1391, 1000, -64, -1238, -1481, -1257, +-797, 629, 1040, 1247, 1403, -140, -105, -1087, +-1353, -126, -805, 966, 644, 263, 1096, -1023, +256, -517, -743, 1104, -837, 1034, 22, -878, +849, -1635, 590, 175, -489, 1933, -873, 810, +-128, -1728, 757, -1654, 722, 1106, -386, 2088, +-1169, -328, -256, -2126, 1274, -428, 922, 1902, +-976, 1111, -1513, -1517, 208, -1716, 1742, 986, +703, 2183, -1442, -264, -1579, -2413, 570, -627, +1973, 2253, 565, 1595, -1710, -1610, -1611, -2456, +857, 500, 2047, 2899, 273, 892, -1859, -2704, +-1279, -2183, 1191, 1829, 1827, 2972, -342, -534, +-1907, -3059, -429, -725, 1581, 2580, 1017, 1672, +-1031, -1831, -1422, -2323, 396, 982, 1580, 2750, +330, 39, -1381, -2899, -893, -1209, 924, 2556, +1141, 2281, -445, -1712, -1099, -2975, 211, 591, +1106, 3193, 5, 611, -1163, -2986, -466, -1768, +1164, 2339, 1199, 2726, -729, -1236, -1781, -3235, +-90, -99, 1931, 3128, 1062, 1346, -1410, -2495, +-1763, -2273, 538, 1559, 2021, 2804, 473, -424, +-1721, -2911, -1353, -794, 1069, 2453, 1951, 1861, +-115, -1435, -2046, -2433, -838, 183, 1669, 2375, +1531, 918, -901, -1864, -1880, -1659, 67, 1119, +1884, 2008, 714, -221, -1497, -1952, -1298, -702, +839, 1417, 1518, 1374, -107, -527, -1483, -1534, +-501, -382, 1292, 1126, 959, 995, -901, -365, +-1353, -1117, 209, -438, 1386, 730, 586, 990, +-1021, -15, -1143, -1087, 349, -707, 1178, 770, +271, 1190, -934, -254, -723, -1388, 472, -315, +895, 1412, -2, 925, -809, -1245, -461, -1573, +363, 789, 628, 2085, 185, -65, -438, -2245, +-613, -733, -96, 2058, 590, 1397, 587, -1688, +-239, -1946, -719, 1183, -229, 2435, 416, -511, +448, -2770, 63, -330, -364, 2809, -527, 1159, +-3, -2587, 724, -1865, 584, 2219, -571, 2542, +-1123, -1672, 1, -3206, 1279, 750, 754, 3633, +-919, 521, -1269, -3542, 156, -1795, 1432, 2860, +738, 2731, -1085, -1803, -1485, -3179, 274, 623, +1854, 3168, 781, 513, -1525, -2782, -1630, -1404, +781, 2111, 2021, 1913, 161, -1347, -1924, -2069, +-1003, 626, 1587, 1938, 1770, 44, -930, -1546, +-2354, -587, 32, 853, 2657, 797, 1145, 4, +-2430, -525, -2278, -693, 1755, -165, 3147, 1009, +-713, 995, -3565, -981, -373, -1739, 3617, 753, +1513, 2344, -3279, -381, -2534, -2742, 2578, -157, +3316, 2846, -1553, 766, -3644, -2656, 455, -1186, +3461, 2300, 592, 1293, -2899, -1991, -1371, -1125, +2028, 1833, 1773, 831, -1115, -1749, -1819, -558, +318, 1616, 1599, 353, 358, -1253, -1403, -160, +-1004, 542, 1216, -134, 1680, 425, -1017, 623, +-2396, -1399, 643, -1235, 2960, 2070, 32, 1791, +-3282, -2264, -974, -2148, 3072, 1969, 1996, 2225, +-2350, -1272, -2922, -2065, 1047, 399, 3436, 1751, +582, 384, -3501, -1393, -2235, -927, 2887, 1076, +3392, 1231, -1900, -766, -3828, -1385, 688, 397, +3443, 1414, 338, 23, -2521, -1291, -874, -445, +1377, 1080, 776, 805, -556, -906, -235, -1086, +280, 832, -257, 1287, -358, -796, 421, -1330, +468, 674, -280, 1180, -359, -408, -89, -948, +29, -60, 620, 739, 580, 821, -1171, -624, +-1422, -1869, 1405, 580, 2225, 2894, -1074, -524, +-2788, -3403, 247, 361, 3039, 3096, 836, 90, +-3062, -2221, -1755, -959, 3039, 1446, 2419, 2118, +-2804, -1248, -2766, -3161, 2323, 1526, 3033, 3682, +-1384, -1713, -3063, -3675, 334, 1299, 2968, 3496, +630, -281, -2713, -3404, -1412, -980, 2405, 3278, +2081, 2134, -1975, -2770, -2638, -3059, 1442, 1764, +2917, 3763, -891, -549, -2967, -4071, 248, -519, +2876, 3751, 502, 1393, -2665, -2821, -1245, -2245, +2403, 1677, 1886, 3062, -2004, -801, -2287, -3476, +1433, 373, 2642, 3104, -618, -227, -2760, -2154, +-245, 160, 2632, 1292, 880, -109, -2300, -974, +-1213, 114, 1895, 1034, 1247, -192, -1738, -970, +-1194, 273, 1676, 648, 920, -321, -1702, -341, +-583, 393, 1478, 262, 101, -567, -1079, -298, +315, 825, 674, 281, -709, -1009, -555, -341, +1122, 905, 940, 774, -1489, -513, -1561, -1481, +1626, 25, 2124, 1957, -1372, 368, -2252, -1788, +862, -664, 1966, 1054, -363, 987, -1608, -200, +-9, -1280, 1196, -414, 146, 1255, -858, 673, +-204, -743, 429, -606, 16, 23, -156, 294, +184, 391, 99, 119, -339, -218, -117, -449, +350, -265, 23, 561, -216, 573, 370, -442, +288, -413, -709, 263, -483, -139, 875, -207, +839, 776, -701, 360, -964, -1187, 490, -580, +788, 1201, -395, 640, -364, -861, 328, -515, +-148, 358, -254, 431, 393, 124, 70, -627, +-383, -534, 53, 1044, 94, 911, -54, -1324, +131, -1254, -29, 1217, -107, 1515, 176, -782, +65, -1653, -204, 232, 39, 1667, 335, 317, +109, -1547, -555, -861, -262, 1249, 1015, 1389, +435, -760, -1366, -1760, -638, 107, 1464, 1840, +882, 614, -1318, -1592, -1264, -1287, 938, 1051, +1431, 1744, -725, -356, -1296, -1859, 513, -324, +804, 1709, -415, 857, -307, -1506, 265, -1235, +11, 1367, -90, 1486, 187, -1162, 49, -1594, +-352, 655, 54, 1480, 765, 189, -201, -1165, +-1191, -1092, 473, 757, 1543, 1703, -628, -347, +-1673, -1904, 502, -132, 1620, 1820, -226, 731, +-1647, -1623, -312, -1316, 1546, 1372, 763, 1676, +-1308, -1004, -1287, -1749, 727, 479, 1620, 1636, +-99, 96, -1673, -1411, -391, -512, 1421, 1076, +636, 619, -861, -628, -647, -479, 464, 226, +767, 288, -284, 8, -810, -213, 332, -117, +855, 243, -269, 229, -661, -264, -34, -391, +264, 151, 337, 492, 62, 165, -467, -416, +-337, -626, 154, 202, 376, 1008, 202, 6, +-275, -1033, -487, -94, 29, 667, 443, 48, +376, -214, -246, 37, -675, 140, 150, -64, +909, -525, -67, -19, -750, 976, 37, 209, +517, -1038, 171, -509, -125, 641, -396, 931, +-200, -165, 426, -1399, 485, 11, -184, 1643, +-781, -254, -274, -1449, 938, 705, 470, 846, +-1031, -1115, -492, -136, 873, 1370, 325, -391, +-458, -1457, -267, 716, -158, 1358, 278, -931, +791, -992, -76, 1055, -1201, 308, -166, -1023, +1485, 523, 605, 846, -1707, -1167, -913, -700, +1944, 1411, 1165, 755, -1942, -1417, -1249, -987, +1558, 1448, 1070, 1216, -1085, -1572, -742, -1171, +525, 1594, 309, 728, -110, -1375, 44, 17, +-496, 1035, -433, -819, 1117, -739, 737, 1392, +-1460, 415, -898, -1602, 1370, 115, 883, 1520, +-836, -788, -715, -1296, 193, 1221, 704, 1108, +452, -1062, -709, -1133, -910, 378, 782, 1384, +1193, 430, -921, -1635, -1274, -945, 967, 1470, +1220, 1058, -915, -705, -1103, -939, 415, -366, +856, 785, 274, 1184, -596, -617, -953, -1447, +296, 308, 1202, 1296, 67, 200, -946, -1095, +-453, -717, 314, 1014, 875, 967, 578, -931, +-1017, -954, -1335, 715, 791, 975, 1915, -274, +-264, -1262, -2128, -338, -274, 1610, 2106, 1048, +697, -1570, -1969, -1700, -1038, 965, 1590, 2098, +1200, -8, -1091, -2031, -1162, -922, 581, 1435, +779, 1546, -189, -476, -405, -1750, -110, -482, +156, 1477, 509, 1092, 34, -774, -937, -1271, +-207, -132, 1183, 1097, 600, 950, -1098, -620, +-975, -1470, 771, -196, 1305, 1637, -204, 1271, +-1430, -1516, -476, -2225, 1224, 1212, 1118, 2593, +-777, -807, -1533, -2219, 248, 345, 1478, 1351, +149, 166, -1188, -365, -421, -580, 735, -491, +571, 619, -270, 1059, -496, -169, -99, -1176, +46, -494, 226, 770, 637, 868, 45, -11, +-1062, -671, -422, -709, 934, 48, 656, 1017, +-427, 629, -415, -783, -140, -1070, -56, 144, +389, 1129, 540, 616, -409, -747, -838, -1149, +213, -44, 814, 1237, 89, 947, -625, -876, +-404, -1515, 343, 257, 502, 1463, -125, 385, +-391, -893, 129, -933, 127, 209, -159, 1301, +-44, 223, 193, -1407, 229, -283, -98, 1248, +-477, 101, -130, -954, 497, 53, 431, 727, +65, 81, -725, -615, -1155, -589, 704, 384, +2430, 1270, -133, 200, -3350, -1773, -1015, -1145, +3552, 1723, 2279, 2097, -2986, -1083, -3162, -2619, +1956, 139, 3320, 2489, -846, 642, -2854, -1898, +43, -939, 2177, 1238, 345, 814, -1588, -836, +-467, -595, 1226, 721, 640, 600, -949, -683, +-949, -851, 665, 448, 1323, 1023, -343, 41, +-1513, -803, -2, -573, 1325, 123, 341, 803, +-861, 713, -513, -527, 332, -1201, 364, -144, +-66, 941, 22, 793, 225, 76, -273, -910, +-616, -1353, -12, 297, 821, 2156, 878, 772, +-483, -1993, -1767, -1671, -438, 967, 2212, 1852, +1615, 329, -1958, -1197, -2639, -1275, 1248, 68, +3187, 1578, -460, 907, -3075, -1341, -169, -1268, +2441, 906, 438, 1050, -1583, -637, -493, -737, +844, 682, 492, 817, -212, -823, -632, -1294, +-428, 623, 737, 1587, 1210, 117, -526, -1124, +-1814, -999, -186, -70, 1927, 1234, 1212, 1309, +-1396, -388, -2052, -1789, 357, -1103, 2258, 1191, +801, 2214, -1635, 180, -1639, -2118, 357, -1640, +1706, 839, 947, 2469, -902, 870, -1645, -2210, +-438, -2085, 1394, 941, 1520, 2310, -417, 707, +-1885, -1693, -634, -1844, 1469, 779, 1318, 2053, +-781, -79, -1443, -1664, 178, -244, 1238, 1358, +219, 407, -872, -1408, -513, -744, 481, 1385, +741, 1304, -3, -694, -814, -1743, -636, -648, +617, 1572, 1234, 1879, -91, -643, -1550, -2195, +-504, -634, 1232, 1454, 930, 1524, -568, -325, +-929, -1524, 33, -293, 586, 799, -93, -24, +-195, -158, 655, 893, 157, 369, -1089, -1415, +-551, -1400, 775, 872, 1143, 2350, 279, 657, +-1309, -2188, -1452, -2312, 851, 786, 1931, 3103, +-110, 964, -1535, -2660, -152, -1854, 784, 1497, +-468, 1437, -517, -533, 1515, -300, 1030, 351, +-2041, -520, -1874, -802, 1446, 459, 2227, 1197, +-164, 193, -1650, -911, -935, -596, 560, -23, +1156, 193, 394, 951, -686, 773, -570, -1145, +171, -1517, 126, 460, -148, 1358, 379, 511, +621, -297, -302, -901, -1128, -981, -423, 337, +1190, 1632, 1240, 684, -797, -1286, -1411, -1183, +313, 340, 753, 604, -285, 311, 150, 582, +768, -13, -475, -1310, -1425, -1032, -67, 962, +1682, 1998, 992, 85, -1406, -2165, -1434, -941, +872, 1464, 1170, 1063, -491, -429, -581, -576, +351, -325, 289, -49, -123, 494, -445, 407, +-359, -224, 577, -279, 957, -14, -328, -230, +-1266, -241, -264, 728, 1013, 1069, 698, -672, +-479, -2017, -624, -129, 67, 2420, 206, 1249, +-104, -1921, 13, -1950, 371, 770, 330, 1793, +-373, 359, -988, -982, -235, -882, 1325, 98, +1262, 672, -738, 371, -1960, -92, -593, -402, +1677, -383, 1851, 284, -424, 522, -2176, -284, +-952, -383, 1385, 481, 1452, 163, -165, -780, +-820, -46, -547, 971, -309, 104, 382, -835, +897, -259, 240, 284, -580, 294, -566, 438, +-155, -25, 203, -913, 522, -438, 491, 907, +-140, 788, -964, -570, -495, -774, 904, 264, +820, 443, -591, -233, -517, -86, 442, 421, +23, -9, -606, -609, 227, -246, 766, 556, +-91, 670, -622, -158, -153, -947, 262, -467, +190, 866, -12, 992, -126, -506, 68, -1122, +123, 144, -116, 822, -295, 29, -188, -334, +401, 13, 849, -40, -186, -213, -1344, 130, +-335, 551, 1162, 32, 796, -941, -287, -316, +-651, 1145, -541, 576, -221, -962, 536, -734, +1176, 400, 447, 749, -1335, 309, -1543, -542, +313, -842, 1700, 40, 1133, 1000, -633, 608, +-1789, -784, -859, -1047, 1108, 394, 1571, 969, +315, -101, -1144, -453, -1270, 99, 118, -55, +1270, -323, 514, 156, -725, 500, -483, 131, +441, -340, 171, -346, -564, -133, -201, 91, +576, 474, 596, 566, 39, -184, -870, -1034, +-1057, -772, 491, 747, 1710, 1772, 458, 263, +-1380, -2054, -1323, -1380, 280, 1361, 1395, 1883, +753, -161, -633, -1479, -951, -765, -249, 464, +363, 889, 462, 468, 293, -358, 56, -766, +-282, -116, -582, 456, -364, -135, 310, -173, +918, 988, 752, 543, -669, -1497, -1774, -1399, +-451, 869, 1834, 1824, 1689, 577, -778, -1115, +-2139, -1601, -591, -393, 1533, 1334, 1350, 1512, +-384, -247, -1154, -1429, -505, -397, 493, 473, +816, -84, 42, 261, -724, 1050, -235, -55, +578, -1282, 242, -731, -421, 313, -235, 1068, +154, 1060, 160, -377, 92, -1540, 17, -788, +-114, 698, -70, 1347, -315, 628, -229, -895, +801, -1239, 913, 140, -830, 878, -1557, -15, +184, -373, 1645, 567, 802, 605, -1059, -910, +-1380, -1476, 218, 218, 1293, 1987, 337, 1202, +-783, -1303, -408, -2156, 390, -274, 312, 1734, +-364, 1519, -486, -309, 408, -1490, 1044, -811, +-175, 493, -1609, 693, -466, 263, 1619, 247, +1076, 29, -886, -782, -1201, -932, -230, 238, +627, 1365, 1002, 840, 353, -771, -936, -1381, +-1073, -322, 122, 944, 1070, 1003, 767, -38, +-301, -856, -985, -580, -591, 203, 437, 630, +884, 343, 359, -397, -404, -451, -663, 278, +-433, 239, 211, -363, 871, -56, 576, 473, +-602, 103, -1083, -430, -123, -287, 853, 252, +679, 377, -112, -62, -688, -283, -605, -84, +335, 91, 889, 254, -54, 67, -750, -408, +103, -103, 557, 401, -241, -47, -510, -207, +234, 352, 608, 74, -47, -570, -656, -204, +-165, 419, 590, 428, 257, 84, -428, -329, +-478, -510, 210, -131, 859, 492, 137, 485, +-1282, -211, -625, -318, 1231, 186, 1071, -149, +-567, -597, -1164, 268, -227, 967, 849, 176, +466, -760, -429, -619, 51, 123, 344, 384, +-643, 190, -521, 357, 611, 276, 543, -631, +11, -945, -46, -114, -459, 785, -633, 1052, +174, 340, 838, -814, 424, -1243, -377, -716, +-564, 776, -282, 2015, -36, 678, 349, -1659, +671, -1513, 212, 95, -534, 833, -785, 889, +-282, 527, 594, -336, 873, -1071, 266, -810, +-386, 468, -888, 978, -760, 175, 585, -5, +1453, 144, 434, -804, -958, -1028, -1131, 410, +-208, 1204, 890, 543, 925, -317, -11, -604, +-734, -504, -715, -511, 40, 111, 776, 1490, +422, 1115, -488, -1148, -450, -1703, 313, -67, +405, 982, -444, 735, -610, 147, 490, -301, +910, -436, -101, -364, -793, -161, -499, 269, +199, 650, 780, 387, 462, -441, -511, -648, +-601, 65, 79, 182, 230, -271, -11, 276, +240, 899, 402, 18, -414, -1160, -889, -832, +268, 702, 1037, 1350, -107, -38, -885, -1189, +106, -253, 737, 713, -145, 226, -834, -420, +32, -293, 966, 359, 220, 558, -846, -307, +-320, -710, 515, 230, 93, 554, -216, -274, +320, -321, 274, 416, -530, 274, -562, -401, +201, -315, 666, 127, 493, 263, -288, 220, +-950, -195, -349, -462, 764, 345, 612, 704, +-259, -583, -439, -1018, 13, 456, 315, 1207, +-70, 180, -647, -980, -54, -837, 1036, 432, +559, 932, -857, -67, -949, -551, 116, 177, +691, 394, 489, -355, 79, -780, -307, -14, +-594, 1079, -458, 772, 271, -565, 1030, -960, +601, -407, -832, 81, -1129, 634, 124, 997, +810, 288, 343, -976, -82, -1227, -292, -188, +-279, 864, 61, 1103, 95, 563, -25, -638, +165, -1427, 85, -689, -109, 688, 83, 1313, +-113, 770, -475, -632, 171, -1272, 769, -298, +73, 449, -685, 151, -348, 317, 298, 877, +417, 264, 23, -1346, -305, -1648, -108, 457, +274, 2202, 45, 947, -349, -1242, -68, -1409, +389, -172, 204, 616, -297, 565, -420, 302, +118, 209, 667, -187, 211, -874, -701, -798, +-650, 350, 219, 1394, 815, 893, 578, -769, +-444, -1398, -927, -427, -193, 557, 570, 942, +454, 676, -38, -486, -298, -1111, 74, -115, +238, 691, -492, 135, -558, -275, 526, 175, +828, 314, 120, -186, -522, -358, -822, -108, +-218, -55, 837, 143, 657, 592, -210, 266, +-419, -566, -264, -550, 11, -21, 122, 247, +-189, 479, 75, 296, 797, -438, 311, -430, +-837, 320, -967, 251, -122, -450, 884, -339, +1101, 416, 84, 653, -952, 208, -875, -438, +-99, -916, 621, -510, 756, 792, 147, 1227, +-350, 68, -289, -767, -331, -476, -385, -376, +297, -291, 955, 763, 283, 1384, -623, 73, +-517, -1425, -131, -980, 14, 365, 398, 803, +407, 532, 12, 64, -46, -463, -336, -455, +-769, 5, 47, 166, 1110, 45, 469, -47, +-679, 133, -623, 462, 47, 15, 362, -769, +293, -349, -48, 470, -338, 325, -146, -6, +290, 7, 249, 17, -118, -10, -251, -362, +-130, -498, 92, 414, 265, 919, 78, 7, +-107, -689, -45, -416, -209, 44, -205, 412, +354, 378, 399, -151, -181, -382, -357, -56, +-120, 269, 126, 219, 297, -159, 20, -446, +-204, -192, 21, 488, 14, 693, -169, -103, +49, -734, 243, -300, 87, 144, -162, 169, +-303, 370, 33, 290, 387, -187, 103, -343, +-197, -313, -119, -146, -156, 296, -20, 420, +372, 283, 145, 22, -332, -702, -89, -685, +308, 518, -61, 847, -525, -23, -105, -516, +647, -399, 557, 212, -220, 726, -721, -88, +-475, -982, 269, -142, 719, 920, 348, 441, +-317, -502, -500, -482, -59, 147, 318, 225, +-52, -184, -257, -50, 360, 328, 444, 51, +-387, -286, -554, 39, -1, 304, 438, -161, +534, -541, -213, -36, -920, 488, -76, 362, +905, 214, 326, -175, -399, -929, -373, -509, +-273, 781, 103, 856, 584, 26, 225, -470, +-390, -534, -183, -21, 145, 416, -205, 23, +-322, -156, 424, 172, 793, 104, -46, -55, +-848, -73, -558, -235, 236, -71, 607, 238, +363, 93, -14, -11, -173, 117, -375, 44, +-514, -252, -69, -432, 657, 8, 753, 631, +58, 364, -730, -292, -716, -354, -10, -221, +501, -31, 468, 337, 230, 252, -79, -34, +-471, 52, -523, -133, -53, -591, 520, -235, +570, 699, 139, 799, -369, -150, -554, -836, +-201, -470, 242, 235, 257, 402, 195, 205, +235, 128, -46, 56, -415, -121, -426, -275, +-156, -493, 348, -356, 778, 648, 246, 1119, +-758, -96, -638, -843, 399, 30, 523, 109, +-255, -860, -344, -352, 271, 1183, 392, 1262, +-65, -157, -439, -1326, -271, -982, 329, 482, +464, 1012, -95, -60, -396, -646, -204, 320, +114, 880, 421, -238, 237, -1258, -351, -464, +-329, 944, 53, 925, 68, -205, 41, -693, +86, -211, 102, 148, 252, 153, -50, 257, +-742, 106, -379, -346, 738, -260, 770, 150, +-246, 116, -699, 80, -215, 188, 286, -74, +269, -216, 111, -3, -44, -103, -213, -133, +-115, 315, 128, 385, 6, -40, -139, -417, +77, -610, 346, -10, 188, 1159, -454, 816, +-627, -966, 239, -1326, 716, 33, -28, 723, +-374, 501, 98, 556, 110, 225, -250, -923, +-157, -1235, 188, -54, 258, 1029, -34, 915, +-267, 81, 33, -583, 280, -592, -2, -186, +-252, 169, -174, 378, 60, 303, 296, -116, +131, -402, -253, -117, -75, 445, 204, 351, +-68, -528, -251, -699, 22, 343, 190, 878, +197, 218, 119, -548, -273, -777, -523, -236, +25, 717, 687, 742, 420, -52, -336, -281, +-599, -231, -306, -679, 232, -591, 627, 744, +277, 1614, -380, 399, -292, -1396, 151, -1317, +-17, 136, -404, 922, -53, 599, 639, -19, +520, -256, -279, -162, -524, -185, -358, -245, +-228, -34, 465, 394, 993, 586, -27, -135, +-1038, -990, -366, -198, 473, 1146, 404, 573, +127, -891, -237, -973, -443, 116, 47, 1038, +473, 746, 91, -525, -364, -1012, -212, -148, +239, 601, 342, 394, -70, -95, -381, -171, +-79, 1, 243, -54, 27, -218, -184, -97, +146, 223, 392, 394, -7, 205, -513, -240, +-479, -593, 113, -445, 715, 425, 495, 952, +-356, 14, -642, -814, -131, -124, 373, 429, +315, 1, -202, -276, -381, -220, 230, 150, +536, 738, -97, 262, -567, -854, -244, -702, +255, 338, 426, 745, 200, 261, -243, -434, +-474, -383, -165, 187, 450, 148, 519, -185, +-219, -98, -602, 138, -3, 354, 472, 193, +29, -464, -418, -466, 38, 231, 560, 334, +13, -49, -611, -208, -134, 22, 395, 561, +193, 325, -73, -890, -258, -1032, -184, 378, +389, 1265, 397, 629, -386, -583, -503, -1015, +121, -262, 388, 500, 148, 439, -267, 74, +-242, -145, 364, -32, 370, 145, -543, -290, +-671, -599, 426, 241, 926, 914, -25, 181, +-843, -668, -349, -406, 440, 209, 496, 195, +96, -42, -476, 51, -569, 68, 367, 0, +842, 141, -233, -125, -852, -538, 96, 40, +686, 660, 16, 127, -490, -439, -97, -194, +340, 227, 200, 283, -220, -101, -353, -441, +6, -171, 452, 332, 307, 445, -301, 104, +-464, -300, -29, -244, 303, -76, 202, -246, +-52, -16, -79, 666, 49, 560, -45, -354, +-222, -793, -50, -219, 245, 507, 251, 353, +-83, -252, -407, -238, -136, 184, 509, 326, +358, 64, -482, -395, -573, -401, 202, 123, +601, 408, 192, 297, -362, -114, -386, -612, +79, -163, 339, 713, 68, 263, -183, -506, +-71, -113, 83, 116, 17, -294, -98, -8, +-43, 576, 238, 279, 237, -370, -250, -437, +-484, -35, -39, 174, 414, 102, 452, 201, +22, 183, -588, -324, -474, -439, 328, 171, +546, 418, 67, 107, -230, -103, -268, -298, +-148, -388, 139, 137, 271, 670, 153, 333, +-110, -401, -260, -625, -51, -207, 144, 350, +-24, 509, -33, 130, 100, -292, 14, -220, +84, 73, 172, -16, -262, -268, -546, -33, +-15, 466, 638, 437, 560, -165, -241, -611, +-826, -376, -315, 294, 663, 633, 625, 141, +-389, -585, -729, -432, 189, 400, 723, 628, +-49, -55, -634, -677, -61, -367, 582, 508, +231, 521, -580, -383, -531, -348, 425, 483, +694, 113, -53, -665, -442, -68, -222, 689, +-21, 295, 197, -407, 226, -642, -151, -205, +-258, 650, 141, 798, 401, -106, 79, -799, +-539, -456, -523, 251, 308, 423, 739, 138, +98, -23, -582, -35, -330, -94, 379, -168, +352, -170, -310, 126, -338, 454, 242, 61, +227, -552, -212, -263, -77, 441, 304, 477, +87, -171, -366, -591, -222, -35, 196, 573, +95, -24, -59, -610, 222, 129, 184, 712, +-355, 37, -336, -637, 166, -277, 218, 393, +-64, 226, -30, -409, 145, -76, 45, 745, +-207, 225, -164, -878, 98, -537, 148, 519, +-28, 515, -50, -32, 69, -53, -5, -132, +-191, -517, -74, -115, 244, 782, 179, 547, +-148, -452, -199, -686, -103, -313, -105, 157, +174, 779, 557, 699, 83, -453, -767, -1108, +-458, -249, 555, 838, 461, 628, -342, -352, +-229, -505, 337, 88, 120, 128, -338, -173, +-239, 117, 47, 509, 238, 148, 297, -640, +-63, -798, -399, 130, -130, 1042, 187, 624, +142, -495, 95, -772, -102, -149, -374, 270, +-5, 137, 492, 121, 113, 322, -457, 33, +-236, -535, 259, -416, 228, 244, -97, 528, +-165, 226, 41, -190, 91, -351, -93, -360, +-224, -149, 29, 549, 478, 895, 252, -77, +-583, -1135, -660, -654, 251, 571, 696, 908, +262, 218, -304, -491, -498, -489, -176, -48, +266, 196, 208, 121, -46, -23, 81, 167, +124, 451, -285, -172, -482, -1108, 74, -406, +633, 1193, 307, 1088, -469, -460, -588, -1171, +69, -462, 540, 558, 136, 809, -340, 182, +-88, -397, 165, -446, -121, -290, -118, 130, +105, 655, -46, 373, -10, -493, 351, -575, +65, 100, -634, 337, -475, 82, 517, 75, +837, 112, -173, -274, -899, -468, -134, 76, +628, 603, 136, 363, -417, -331, -57, -686, +328, -144, -38, 688, -410, 454, 20, -473, +446, -443, 4, 302, -402, 350, -151, -245, +127, -468, 235, 81, 224, 716, -215, 340, +-501, -673, -42, -741, 398, 184, 239, 756, +-100, 358, -228, -460, -202, -578, -43, 264, +122, 586, 186, -268, 124, -576, -76, 257, +-335, 498, -242, -193, 224, -342, 343, 155, +-24, 282, -172, -59, -135, -367, -112, -242, +94, 347, 160, 566, -122, -95, -74, -608, +148, -223, -67, 341, -179, 383, 115, 7, +130, -317, -277, -149, -263, 150, 362, -24, +515, -161, -295, 222, -689, 417, -38, -61, +400, -552, 220, -372, 79, 240, -141, 552, +-434, 286, -190, -223, 284, -496, 310, -239, +31, 267, -182, 381, -221, 132, -113, -101, +24, -369, 83, -399, 172, 234, 241, 769, +-100, 249, -600, -662, -366, -697, 462, 97, +641, 620, 17, 410, -548, -18, -438, -358, +131, -530, 368, -158, 52, 508, -152, 578, +-56, 18, 13, -465, 22, -521, -108, -70, +-204, 539, 120, 517, 277, -125, -82, -475, +-246, -210, -33, 97, 84, 115, 47, 85, +-61, 174, -116, 150, 71, -178, 52, -458, +-164, -173, -48, 463, 228, 548, 65, -149, +-308, -671, -266, -268, 154, 499, 360, 494, +85, -201, -311, -362, -397, 78, 43, 55, +531, -256, 219, 4, -542, 389, -541, 223, +229, -166, 619, -330, 138, -135, -471, 220, +-319, 162, 161, -194, 35, -88, -181, 290, +127, 177, 409, -217, 77, -241, -475, -17, +-530, 67, 113, 68, 537, 99, 141, 81, +-263, 2, -118, -144, 86, -200, -51, 44, +-277, 227, -110, 13, 371, -92, 310, 74, +-262, -53, -363, -211, -21, 71, 135, 260, +95, 88, 19, -115, -48, -321, -102, -198, +-103, 427, -9, 487, 68, -341, -2, -575, +46, 195, 108, 490, -136, -87, -309, -351, +-98, 1, 200, 192, 290, 54, 111, -31, +-300, -45, -398, -81, 50, -11, 392, 130, +18, 100, -442, -165, -34, -213, 501, 182, +66, 287, -502, -136, -196, -213, 202, 104, +72, 51, 14, -156, 90, -77, -36, 135, +-196, 374, -65, 179, 95, -602, -27, -651, +-146, 395, 38, 791, 215, 96, 72, -335, +-176, -291, -365, -299, -131, -26, 396, 506, +342, 416, -275, -245, -348, -433, 85, 23, +141, 231, -120, -84, -140, -240, 137, 101, +308, 391, -42, 142, -508, -276, -285, -299, +379, -75, 428, 29, -134, 123, -312, 300, +-3, 297, -23, -86, -240, -610, 132, -549, +472, 282, 18, 847, -487, 403, -315, -435, +54, -760, 327, -228, 414, 575, -33, 504, +-607, -199, -457, -284, 230, -27, 557, -94, +251, 88, -225, 334, -401, -54, -244, -333, +18, -66, 279, 90, 312, 150, -20, 229, +-346, -51, -226, -345, 107, -174, 181, 156, +42, 294, -132, 98, -157, -192, 11, -159, +172, -44, 84, 10, -63, 290, -182, 231, +-246, -416, 32, -435, 372, 303, 132, 453, +-265, -58, -120, -219, -5, 2, -178, -64, +47, -245, 414, 107, 117, 470, -446, 31, +-411, -415, 169, -112, 515, 175, 134, 83, +-410, 4, -298, -81, 96, -115, 180, 62, +61, 216, -53, 151, -124, -235, -15, -505, +98, 107, 41, 758, -101, 109, -227, -790, +-36, -340, 340, 630, 151, 542, -348, -333, +-101, -591, 296, -10, -151, 360, -435, 253, +211, 43, 517, -301, -59, -341, -382, 188, +-139, 328, -26, -61, 90, -88, 302, 90, +98, -58, -389, -271, -343, -159, 227, 312, +490, 539, -14, -15, -513, -583, -144, -379, +341, 141, 80, 428, -163, 291, 100, -145, +63, -282, -254, -80, -106, -32, 273, 19, +178, 200, -255, 169, -273, -90, 151, -299, +196, -162, -74, 268, 21, 329, 100, -88, +-240, -293, -242, -173, 159, -2, 259, 237, +103, 346, -62, 14, -305, -497, -215, -452, +314, 345, 384, 713, -225, -45, -455, -631, +165, -224, 451, 275, -124, 273, -362, -26, +169, -196, 249, 55, -295, 118, -252, -272, +395, -143, 348, 362, -383, 117, -429, -349, +250, -87, 365, 319, -100, 173, -176, -276, +46, -386, -46, 40, -143, 354, 141, 200, +339, -5, 24, -200, -360, -394, -158, -124, +181, 415, 121, 393, 76, -168, 113, -464, +-164, -166, -220, 320, 182, 401, 180, -116, +-200, -584, -129, -137, 164, 588, 154, 227, +49, -441, -74, -122, -281, 139, -146, -223, +316, 51, 385, 504, -72, -61, -335, -522, +-113, -113, 121, 93, 206, 45, 170, 350, +-68, 287, -236, -464, 29, -667, 267, 124, +68, 625, -205, 113, -109, -392, 191, -124, +250, 238, -32, 6, -281, -384, -115, -175, +233, 399, 222, 407, -75, -162, -120, -489, +64, -328, 20, 134, -111, 554, 83, 246, +279, -464, 88, -424, -190, 117, -177, 188, +57, -15, 242, -18, 152, 98, 39, 38, +34, -270, -79, -288, -254, 165, -128, 266, +328, -41, 592, -40, 201, -35, -599, -274, +-747, -170, 178, 180, 920, 263, 393, 78, +-432, -250, -400, -352, 7, 20, 108, 252, +160, -16, 267, -179, 161, 61, -87, 215, +-232, -131, -139, -483, 264, -129, 383, 400, +18, 270, -109, -86, 24, -218, -101, -335, +-30, -161, 371, 316, 193, 265, -306, -261, +-84, -258, 356, 213, 42, 163, -277, -343, +85, -319, 313, 148, 9, 181, -94, -8, +140, 71, 61, -6, -180, -309, 30, -330, +382, -41, 293, 304, -107, 370, -273, -13, +-54, -414, 220, -441, 351, -143, 313, 364, +-88, 445, -429, -189, -93, -422, 397, 3, +366, -2, 21, -212, -155, 92, -116, 266, +72, -97, 179, -381, 117, -194, 53, 302, +-26, 399, -6, -298, 251, -754, 191, -129, +-218, 619, -87, 470, 398, -214, 255, -627, +-177, -407, -38, 140, 343, 379, 171, 170, +-202, -92, -90, -199, 245, -276, 320, -248, +108, 54, -90, 265, -126, 99, 22, -88, +180, -190, 190, -316, 105, -101, 45, 282, +5, 85, -18, -324, -16, -133, 138, 194, +356, 56, 199, -198, -156, -230, -127, -161, +151, -8, 292, 214, 224, 205, 98, -137, +7, -368, -116, -264, -103, -101, 289, 140, +606, 411, 130, 97, -510, -579, -236, -495, +459, 238, 370, 392, -157, -162, -33, -424, +433, -2, 149, 329, -400, -8, -118, -423, +366, -329, 322, 64, 244, 367, 150, 206, +-181, -386, -207, -533, 179, 23, 360, 314, +287, 24, 153, -158, -88, -115, -111, -115, +151, -98, 209, -76, 82, -29, 182, 155, +134, 112, -135, -388, -68, -522, 317, 128, +304, 566, -73, 125, -110, -505, 135, -602, +223, -128, 132, 465, 31, 453, 66, -165, +197, -523, 181, -315, 55, -61, -27, 32, +38, 185, 340, 380, 402, 111, -150, -741, +-392, -971, 308, 189, 738, 1156, 48, 422, +-502, -817, -115, -884, 409, -79, 365, 490, +79, 390, 73, -122, 22, -410, -280, -207, +-75, 13, 591, -40, 504, -39, -160, 85, +-212, 23, 141, -176, 117, -276, 71, -170, +354, 184, 362, 379, -46, -154, -244, -744, +8, -313, 356, 532, 361, 528, 133, -180, +-58, -627, -115, -419, -10, 95, 242, 320, +353, 140, 84, -93, -139, -196, 106, -190, +244, -168, -104, -224, -89, -63, 415, 443, +419, 459, -115, -436, -203, -976, 192, -215, +289, 704, 97, 518, 88, -278, 118, -603, +45, -289, 186, 169, 393, 260, -16, -71, +-484, -262, 36, -2, 755, 125, 444, -226, +-246, -386, -345, 46, -52, 417, 287, 90, +422, -494, 189, -471, -115, 131, -32, 443, +148, 72, 67, -408, 44, -375, 232, 33, +275, 221, 58, 6, -71, -190, 103, -73, +248, 54, 113, -130, -15, -299, 134, -31, +240, 295, 68, 53, -57, -342, 113, -184, +191, 114, 49, -33, 18, -184, 137, 23, +207, 103, 52, -121, -154, -190, -9, -53, +357, 11, 333, 33, -13, -6, -130, -214, +6, -252, 99, 117, 232, 292, 374, -93, +169, -384, -180, -159, -159, 94, 173, 45, +325, -1, 172, 22, 62, -113, 50, -226, +19, -74, 11, 34, 61, -57, 183, 28, +215, 159, 41, -147, -111, -438, 23, -92, +230, 336, 208, 163, 58, -269, -17, -333, +-38, -25, 50, 204, 286, 60, 367, -156, +93, -127, -284, -89, -270, -143, 273, 29, +650, 241, 290, 30, -292, -289, -298, -275, +100, -97, 294, 105, 278, 271, 179, 61, +-46, -340, -178, -289, -50, 43, 174, 90, +320, 14, 168, 22, -86, -78, -31, -157, +141, -69, 60, -57, 10, -26, 184, 137, +179, 19, 60, -275, 96, -143, 3, 121, +-117, 28, 145, -92, 399, -78, 185, -78, +-94, 40, -114, 106, -82, -203, 91, -376, +424, 82, 374, 506, -201, 128, -464, -593, +-19, -585, 515, 215, 447, 664, -84, 113, +-280, -515, 31, -307, 171, 123, -5, -13, +91, -156, 366, 203, 163, 301, -233, -197, +-128, -467, 222, -162, 280, 198, 80, 232, +-62, -45, 18, -255, 152, -17, 128, 180, +22, -159, -42, -364, -21, 39, 94, 346, +233, 86, 159, -225, -43, -219, -30, -94, +52, 25, -52, 114, -35, 33, 262, -128, +364, -86, 93, 70, -192, 25, -270, -198, +-66, -263, 417, 55, 626, 441, 85, 216, +-520, -461, -391, -613, 217, -19, 595, 544, +329, 442, -190, -232, -316, -657, 33, -237, +259, 360, 113, 277, 6, -82, 62, -121, +75, -107, 9, -192, 27, -52, 31, 184, +-53, 115, 77, -98, 359, -107, 204, -79, +-275, -133, -230, -6, 234, 189, 303, 60, +31, -200, -47, -148, 22, 48, 52, 55, +140, -48, 80, -95, -160, -72, -24, 57, +422, 143, 284, -74, -323, -266, -399, -38, +134, 135, 481, -79, 273, -82, -122, 189, +-283, 75, -41, -268, 233, -266, 221, -13, +72, 205, -10, 238, 25, -8, -34, -291, +-150, -287, 34, -62, 462, 216, 357, 319, +-318, 1, -438, -392, 187, -292, 513, 127, +58, 255, -312, 6, -38, -157, 337, -41, +166, 14, -301, -162, -195, -123, 377, 239, +438, 212, -195, -302, -382, -348, 190, 227, +385, 318, -101, -232, -266, -344, 152, 108, +315, 267, 48, -12, -136, -206, -23, -158, +111, 1, 107, 126, 26, 76, -14, -76, +69, -98, 66, 1, -22, -15, -71, -99, +40, -55, 173, 73, 162, 139, -1, 66, +-199, -199, -41, -345, 250, -1, 167, 317, +-154, 101, -69, -114, 186, -18, 18, -101, +-95, -261, 130, -33, 218, 230, -58, 175, +-118, 41, 110, -131, 102, -356, -74, -224, +-43, 239, 171, 362, 142, 38, -67, -186, +-113, -194, 53, -200, 133, -62, 67, 215, +59, 285, 24, 67, -127, -219, -155, -385, +143, -219, 306, 250, 99, 464, -141, 76, +-163, -372, -48, -298, 156, 6, 334, 122, +104, 150, -253, 77, -245, -139, 73, -134, +267, 47, 140, -43, -47, -156, -59, 112, +79, 258, -32, -93, -150, -313, 122, -18, +337, 222, 8, 7, -368, -197, -113, -5, +275, 155, 265, -12, -51, -156, -218, -85, +-3, 60, 257, 167, 130, 44, -253, -254, +-193, -226, 194, 168, 318, 298, 75, 5, +-230, -247, -300, -214, 62, 10, 473, 213, +216, 134, -307, -126, -271, -136, 156, 36, +180, 26, -114, -80, -114, -68, 227, 42, +319, 168, -176, 90, -488, -222, -47, -237, +544, 127, 359, 167, -252, -108, -414, -37, +-105, 186, 247, 12, 247, -243, 35, -148, +-93, 57, -11, 146, -36, 174, -148, 36, +49, -227, 274, -215, 174, 70, -187, 152, +-359, -4, -110, -14, 372, 85, 441, 22, +-164, -141, -502, -186, -52, -26, 419, 240, +169, 260, -267, -102, -184, -348, 168, -85, +157, 264, -142, 160, -126, -170, 166, -169, +192, 132, -134, 199, -246, -138, 28, -265, +281, 154, 166, 349, -232, -112, -377, -406, +-2, -27, 430, 365, 258, 237, -199, -192, +-338, -365, -92, -12, 225, 304, 232, 95, +-35, -149, -222, -14, -41, 79, 83, -47, +-59, -108, -52, -18, 166, 162, 203, 203, +-156, -114, -360, -324, -37, 28, 374, 362, +195, 79, -275, -298, -241, -154, 84, 195, +145, 214, -13, -6, -16, -170, 7, -130, +-22, 94, -9, 164, -41, -27, -55, -93, +6, 74, 91, 75, 27, -90, -51, -66, +-124, 65, -112, 63, 159, 2, 277, -5, +-103, 8, -389, 44, -48, 49, 242, -81, +119, -173, -42, 53, -102, 329, -183, 126, +-46, -229, 241, -201, 114, -6, -148, 114, +-126, 222, 20, 134, -57, -170, -52, -218, +145, 27, 104, 166, -131, 104, -179, 32, +19, -37, 46, -169, 38, -61, 91, 230, +-5, 222, -241, -94, -180, -191, 151, -34, +212, 9, -11, 124, -195, 297, -123, 31, +24, -372, 100, -190, 80, 277, -67, 253, +-173, -69, -18, -105, 120, 91, -12, 62, +-183, -136, -47, -112, 211, 117, 134, 284, +-228, 92, -327, -214, 37, -188, 317, 56, +156, 243, -234, 134, -338, -138, -86, -156, +232, 90, 261, 224, -46, 61, -336, -169, +-259, -141, 188, 82, 331, 228, -39, 148, +-368, -100, -169, -219, 214, -28, 189, 231, +-137, 161, -228, -105, 45, -83, 129, 106, +-30, 68, -185, -74, -91, -59, 133, 147, +116, 186, -153, -61, -267, -199, 65, 7, +169, 240, -83, 90, -115, -93, 38, 20, +-17, 10, -189, -120, -20, 101, 164, 313, +-20, 0, -212, -268, -105, -96, 133, 154, +96, 285, -130, 126, -240, -252, -28, -213, +244, 196, 74, 240, -259, -42, -284, -73, +51, 80, 264, 82, 40, -76, -296, -104, +-235, 137, 174, 233, 172, -24, -166, -156, +-236, 22, 12, 133, 163, 3, -45, 0, +-283, 87, -91, -6, 183, -5, 100, 143, +-168, 70, -239, -192, -45, -71, 149, 264, +66, 206, -263, -111, -126, -132, 137, 87, +15, 64, -190, 12, -127, 88, 51, 66, +32, -37, -84, -3, -120, 86, -14, -8, +-3, 22, -140, 88, -104, -2, 31, 13, +73, 97, -120, 14, -205, -67, -39, 102, +42, 106, 58, -66, -32, -3, -220, 116, +-280, 84, 39, -59, 312, -33, 81, 150, +-344, 138, -512, -146, -21, -121, 459, 201, +204, 268, -328, 57, -407, -257, -147, -219, +34, 169, 169, 348, 119, 208, -99, -59, +-317, -287, -349, -225, -58, 212, 379, 458, +282, 129, -401, -244, -589, -177, -45, 84, +401, 155, 123, 82, -351, 34, -309, 84, +99, 84, 66, -101, -227, -197, -155, 103, +104, 475, 85, 162, -225, -458, -360, -266, +-105, 377, 275, 407, 105, 9, -313, -298, +-366, -157, -48, 230, 234, 291, -19, 6, +-298, -191, -231, 57, 91, 254, 58, 27, +-172, -253, -254, -61, -87, 345, 99, 310, +-52, -41, -92, -289, -188, -143, -176, 172, +-121, 312, 8, 201, 45, -160, -93, -208, +-128, 139, -228, 261, -176, -85, -51, -196, +94, 207, 4, 273, -279, -8, -137, -138, +-35, 39, -158, 132, -213, -36, 70, -114, +41, 124, -198, 393, -136, 202, -84, -252, +-170, -465, -182, -38, -9, 498, 25, 495, +-23, 98, -190, -386, -347, -400, -136, 21, +181, 377, 19, 427, -345, 89, -251, -216, +-21, -241, 87, -30, -27, 204, -234, 306, +-415, 146, -175, -159, 232, -186, 97, 65, +-166, 288, -321, 151, -258, -69, -140, -124, +-15, -22, 62, 154, -10, 184, -133, 157, +-287, 19, -286, -180, -176, -160, 2, 27, +270, 409, -1, 468, -518, -217, -460, -542, +53, 17, 207, 487, -87, 225, -200, -168, +-257, -30, -137, 174, -120, -14, -85, -139, +-62, 50, -44, 309, -99, 214, -308, -173, +-197, -207, -80, 116, 39, 269, -50, 107, +-174, -42, -263, -55, -204, -27, 11, 77, +-47, 305, -192, 91, -124, -261, -43, -24, +-255, 203, -209, 78, 41, 190, -100, 123, +-258, -426, -102, -76, 45, 662, -155, 121, +-362, -385, -242, -21, 217, 176, 98, 191, +-453, 119, -387, -150, 143, -72, 65, 233, +-333, 47, -239, -36, 23, 205, 54, 22, +-234, -181, -307, 121, -166, 276, -99, -106, +27, -146, -7, 268, -126, 322, -305, -208, +-331, -255, -176, 214, 104, 132, 199, 143, +-172, 117, -438, -98, -362, 79, 20, -102, +79, -147, -66, 399, -192, 336, -114, -227, +-182, -202, -299, 199, -113, 84, 136, -54, +77, 183, -466, 185, -417, -211, 90, -25, +173, 358, -151, -57, -236, -198, -228, 282, +-372, 107, -71, -253, 348, 184, 98, 326, +-506, -38, -549, -190, -61, -159, 125, 162, +78, 417, 13, 165, -289, -132, -411, -311, +-147, -99, -36, 417, -32, 214, 87, -107, +-35, 198, -347, -105, -364, -326, -234, 343, +106, 124, 418, -61, -314, 400, -598, -188, +-56, -331, 23, 407, -122, -20, 9, -206, +15, 571, -409, 79, -171, -596, -4, 266, +-222, 277, -2, -264, -7, 288, 44, 226, +-384, -228, -421, -119, 3, 137, 162, 268, +128, -20, -326, -151, -307, 214, -239, -11, +63, -77, -62, 350, -59, -162, 53, -121, +-287, 348, -349, -165, -159, 16, 188, 334, +10, -123, -236, -96, -136, 129, -194, 66, +-288, 60, 46, -56, 218, 78, -244, 298, +-249, -130, -153, -96, -191, 9, 7, -117, +141, 477, -203, 283, -213, -395, -153, -109, +-181, 57, 33, -16, 23, 478, -188, 156, +-114, -371, -228, -75, -44, 45, -100, 230, +-35, 266, -42, -201, -192, -125, -155, 188, +-48, 77, -146, 26, -143, 52, 198, -48, +-182, -32, -426, 146, 26, 188, 27, -82, +-92, -124, 23, 261, -193, 14, -340, -305, +-82, 182, 159, 402, 36, 70, -252, -219, +-302, -342, -14, 136, 89, 461, -259, 97, +-187, -164, 201, -101, 117, 118, -478, 22, +-596, -120, 339, 175, 375, 283, -113, -14, +-517, -156, -335, -141, 155, 59, 222, 362, +-258, 37, -309, -205, 247, 61, -51, 86, +-403, 80, -156, -5, 57, -143, 68, 171, +16, 218, -325, -123, -189, -56, 106, 77, +-155, 95, -100, 8, 17, -40, -269, 99, +23, -62, 171, 164, -339, 181, -263, -285, +113, -68, -89, 151, -51, 282, -21, 58, +-114, -268, -247, -140, 140, 321, -163, 254, +-212, -266, -132, -100, 154, 115, 200, 252, +-410, 90, -354, -306, -44, -67, 214, 352, +58, 97, -166, -101, -461, -118, -8, -18, +282, 356, -154, 15, -201, -201, -365, 11, +231, -38, 152, 409, -269, -26, -382, -406, +77, 256, 276, 238, -294, -136, -178, -53, +-259, -8, 189, 50, 119, 366, -229, -97, +-125, -331, -258, 26, 51, 310, -7, 187, +19, -253, -229, -57, -9, 146, -45, 87, +-169, 100, -81, -146, -192, -205, 165, 188, +22, 416, -225, -100, -129, -211, -72, -75, +-120, 9, 13, 273, 12, 41, -142, -114, +-63, 125, -57, 95, -99, -131, -98, -99, +-149, -88, -86, 182, 203, 492, -92, -65, +-152, -376, -212, -167, -189, 137, 45, 259, +101, 70, 47, -28, -161, 102, -419, -25, +66, -244, 78, -86, -61, 217, -188, 332, +20, -98, -127, -26, 7, 58, -30, -255, +-238, -30, -231, 126, 135, 155, 335, 503, +-354, -320, -303, -641, -191, 360, 339, 282, +34, 28, -351, -18, -90, -216, -145, 149, +166, 118, 165, 20, -484, -182, -192, 6, +169, 195, 57, 61, -265, -38, 19, -106, +-73, 230, 22, -76, -116, -153, -476, 96, +284, -14, 185, 302, -204, 40, -252, -208, +-111, -162, 109, 92, -201, 118, 110, 130, +-197, 194, 70, -265, -179, -118, -218, -28, +310, 292, -366, 187, 113, -355, -312, 51, +106, 170, 60, -128, -53, 110, -254, 169, +-157, -326, 26, 35, 3, 353, 122, -149, +-292, 30, -74, -137, -9, 68, -90, 221, +-81, -150, -17, -19, 180, -2, -428, 190, +-81, -40, 47, -119, 230, 97, -247, 40, +-205, -54, -175, 170, 26, -94, 119, -129, +91, 312, -173, -91, -358, -54, 56, -8, +-110, -57, -49, 267, 265, -24, 62, -120, +-514, -99, -159, 148, 60, 287, 48, -326, +103, -22, -89, 73, -64, 68, -386, 252, +172, -202, -233, -204, 181, 151, 61, 164, +-125, 34, -246, -279, -225, 131, 391, 307, +-343, -46, 92, -429, -115, -13, 122, 438, +-201, 334, -379, -476, 243, -385, 79, 542, +154, 50, -507, -72, -207, 20, 244, -248, +74, 254, 36, 122, -400, -197, 63, 108, +-161, -7, 249, -137, -214, 281, -107, -163, +128, 78, -178, -27, 20, 64, -284, 170, +190, -366, -23, 126, -92, 17, -24, 182, +-128, 238, -99, -467, -52, 143, 95, 26, +113, -284, -329, 526, 56, -33, -113, -12, +-148, -106, 240, -382, -46, 387, -180, 41, +-65, 109, -101, 119, 300, -391, -400, -46, +58, 298, 69, -24, -97, -52, 51, 174, +-247, -246, 45, 237, -121, -146, 341, -148, +-302, 337, -157, -28, 106, -61, -71, -114, +67, -34, -6, 269, -311, 86, 67, -231, +211, -110, -158, 107, -155, 110, -67, 187, +42, -157, 135, -291, 75, 396, -329, -127, +-345, -217, 380, 434, 191, -111, -70, -97, +-341, 64, -183, -133, 336, -68, -168, 157, +204, 326, -295, 27, 159, -435, -191, -333, +-97, 336, 115, 392, -60, 217, 348, -374, +-432, -323, -118, -123, -4, 219, 43, 691, +429, -246, -410, -452, 19, 108, -207, 33, +-15, -69, 268, 265, -168, -60, 165, 137, +-186, -73, -6, -386, -173, 22, -46, 377, +219, 195, 260, -256, -381, -84, -143, -255, +-17, 407, 136, 246, 229, -712, -238, 382, +-195, 181, 68, -316, 231, 454, -233, -463, +75, -368, -52, 957, 9, -279, -50, -360, +-111, 392, 140, -523, 114, 386, -73, 318, +-291, -624, 159, 180, -43, 242, 214, -273, +-170, 176, -135, 45, 166, -266, 27, 224, +-283, -79, 319, -176, -155, 519, -137, -284, +232, -430, -260, 742, 419, -673, -190, 247, +-402, 641, 395, -1114, -348, 743, 515, -162, +-31, -513, -411, 1061, -18, -849, 145, 39, +140, 529, 18, -520, -189, 299, -128, -150, +271, -257, 174, 489, -380, 87, -166, -597, +427, 261, -129, 129, 158, -362, -208, 544, +-79, -278, 159, -281, -44, 514, 29, -506, +149, 67, -339, 512, 346, -518, -37, 45, +-374, 323, 409, -589, -194, 294, 149, 331, +74, -388, -231, 260, -28, -385, 249, -242, +-70, 751, -17, -159, 48, -111, -264, -83, +343, -555, 137, 650, -384, 56, 164, 51, +10, -315, -5, -341, 34, 681, 61, -636, +20, 542, 94, 123, -246, -907, -149, 664, +425, 2, -37, -326, 20, 336, -101, -292, +-28, 17, 208, 392, -330, -659, 198, 154, +323, 611, -461, -662, 539, 53, -374, 185, +-65, -253, 200, 321, -31, -280, 445, -21, +-607, 361, 306, -685, 24, 638, -225, -287, +666, -528, -573, 1083, -53, -720, 487, -121, +-245, 639, 19, -758, 235, -91, -107, 936, +-173, -510, 323, -605, -265, 939, 257, -479, +105, -391, 30, 780, -256, -647, 96, 98, +-21, 461, 312, -463, 87, 24, -310, -168, +342, 84, -300, 269, 88, -296, 308, 183, +-145, -42, 70, -551, 173, 402, -173, 212, +-188, -351, 570, 242, -336, -162, 226, -261, +102, 244, -382, -89, 521, 92, -321, 39, +443, -231, -270, 27, -161, -126, 462, -53, +16, 713, -26, -858, -94, 126, 72, 319, +14, -645, 201, 789, 141, -412, -277, -397, +170, 495, 320, -113, -274, 47, 105, -256, +-23, -248, 50, 268, 513, 229, -171, 21, +-325, -368, 311, -322, -148, 226, 540, 282, +-156, -143, -343, -28, 735, -43, -412, -255, +83, 55, 355, 160, -461, -126, 413, -69, +488, 178, -658, -29, 124, -392, 348, 111, +-103, 71, 254, 133, 141, -167, -276, -247, +-11, 364, 457, -380, -195, 203, 226, -30, +292, -323, -544, 540, 410, -656, 172, 244, +-286, 424, 363, -969, 292, 679, -176, 94, +-87, -838, 99, 633, 25, -105, 432, -239, +52, 223, 21, -18, -224, -398, 95, 119, +291, 226, 64, -392, 213, 279, 185, 9, +-272, -270, -210, -82, 544, -41, 256, 389, +-181, -394, 383, -142, -349, 537, -48, -558, +773, -198, -393, 700, 181, -506, 377, -205, +-363, 375, 240, -374, 221, 197, -33, 203, +377, -491, -123, -14, -148, 56, 293, 80, +152, 48, 250, -372, 268, 429, -581, -85, +124, -717, 808, 513, -471, 4, 334, -317, +271, 479, -357, -130, 542, -575, -63, 55, +-174, 415, 275, -355, 316, 121, 316, 94, +-217, -292, -46, 26, 49, -109, 373, 133, +65, -364, 410, 312, -100, 361, -340, -754, +573, -172, 38, 566, 143, -76, 83, -471, +78, 375, 237, -337, -39, 23, 253, 415, +-101, -613, 380, 220, 144, -59, -204, -189, +227, 52, 358, 100, 114, 169, -32, -501, +-6, 132, 12, -5, 519, -274, 129, 140, +222, 330, -261, -226, -41, -264, 436, 18, +171, -247, 121, 189, 433, 337, -247, -291, +-291, -239, 623, 106, 139, -160, 112, -31, +380, 288, -398, -271, 290, -92, 301, 191, +-159, -278, 507, 44, 11, 84, -76, -369, +353, 314, -47, 66, 238, -446, 189, 258, +194, -307, -44, 324, -76, -116, 538, -446, +-126, 538, 502, -462, 25, 247, -263, 156, +312, -783, 117, 457, 296, 5, 233, -57, +150, 60, -72, -256, -191, -173, 345, 96, +580, 409, -75, -458, 255, -61, -287, 213, +131, -485, 327, 211, 447, 279, 130, -250, +-521, -55, 764, -265, -172, 121, -171, -20, +1053, -17, -367, 390, -15, -404, 388, -557, +-188, 316, 283, 362, 484, -207, -75, 65, +-25, -366, 310, -231, -97, 460, 457, -236, +-8, 204, 40, -130, 523, -231, -372, 49, +437, -357, 134, 602, -135, -264, 563, -70, +-38, 140, 133, -601, 92, 282, 61, 44, +366, 135, -125, -137, 451, -302, 66, 250, +26, -270, 342, -28, -467, 380, 592, -525, +331, 218, 196, 177, -87, -482, -360, 108, +832, -83, -191, -34, 428, 361, 216, -94, +-508, -535, 622, -92, 187, 523, 47, -216, +126, -64, 10, 20, 290, -265, 140, 85, +168, 170, 150, -91, -166, -489, 521, 538, +169, -209, -196, -264, 238, 455, 262, -429, +198, -13, 40, 39, 163, -110, -54, 173, +176, 41, 522, -235, 19, -196, -145, 84, +171, -58, 336, 375, -70, -171, 415, -693, +267, 666, -377, -128, 386, -342, 11, 414, +189, -601, 408, 346, 112, 320, 124, -621, +-448, 163, 585, -286, 91, 169, 186, 421, +660, -458, -600, -122, 90, 74, 443, -178, +-18, 292, 457, 22, 112, -668, -182, 521, +221, 120, 129, -474, 306, 214, 4, -232, +135, -46, 405, 360, -246, -239, 360, -123, +-125, 164, 296, -165, 432, -305, -80, 249, +93, 265, -108, -418, 331, 177, 496, -50, +-99, -391, -107, 218, 345, -65, 104, 282, +156, -132, 276, -261, -94, 158, 124, -579, +320, 582, 62, 246, 94, -697, 165, 264, +165, 141, 157, -619, 63, 339, 242, 496, +-1, -790, 27, 80, 432, 289, 211, -299, +85, 336, -297, -283, 389, -259, 86, 181, +396, 97, 317, 131, -614, -433, 685, 23, +92, 288, -254, -335, 598, 24, -92, 251, +246, -428, 331, 173, -201, 246, 50, -488, +158, 137, 557, 108, -88, -297, 157, 171, +192, 130, -167, -235, 214, -1, 392, -86, +7, -8, 311, 18, 10, 109, -80, -51, +210, -184, 126, 57, 626, -118, -295, 61, +-33, 87, 566, -121, -230, -96, 372, 6, +158, 158, -58, -172, 105, -79, 395, -62, +160, 73, -147, 231, 386, -298, -121, -90, +135, 162, 318, -181, 374, 63, -225, 23, +155, -65, 242, 167, -92, -311, 445, -37, +-69, 163, 326, -205, 156, 275, -42, 1, +186, -534, -74, 322, 352, 86, 318, -343, +-24, 382, 150, -223, 141, -175, -125, 308, +288, -323, 332, 16, 96, 217, 106, -156, +65, 30, 12, -161, 207, 23, 228, -14, +218, 149, 92, -7, -100, -319, 410, 79, +-6, 72, 18, 6, 413, 66, 46, -142, +-22, -199, 267, 134, 266, 110, -225, -176, +500, 277, -106, -319, 59, -231, 482, 457, +10, -292, -68, -3, 290, 273, 219, -73, +-211, -489, 420, 46, 159, 506, 100, -384, +121, 171, 42, 147, 79, -675, 205, 301, +276, 222, 100, -220, -50, 38, 196, 166, +223, -270, 37, -152, 151, 306, 107, -349, +157, 388, 141, 69, 258, -505, -113, 113, +29, -8, 559, 146, -243, 59, 395, -297, +138, 286, -347, -379, 543, 25, -4, 483, +277, -510, 231, 110, -222, 93, 4, -213, +506, 94, 52, 42, 199, -52, -25, -16, +62, -105, 147, 5, 235, 282, 126, -448, +-46, -29, 466, 591, -145, -547, -45, 96, +386, 13, 26, -212, 235, 420, 97, -279, +7, 36, 53, 19, 192, -298, 185, 244, +128, 240, 52, -382, 121, -47, 118, 264, +43, -340, 283, 207, -177, 147, 419, -407, +127, 319, -233, -179, 456, -196, -117, 347, +151, -157, 330, 79, -182, -112, 201, -228, +227, 318, 115, -191, -167, 109, 149, 7, +407, -186, -115, 261, 264, -282, -83, -128, +-20, 290, 385, 118, 5, -282, -11, -37, +437, 107, -150, -65, -70, 11, 138, -122, +326, 141, 177, 39, -33, -114, -37, 58, +38, -186, 115, -10, 311, 146, 181, -72, +-185, 118, 171, -31, 107, -146, -169, -165, +358, 55, 216, 240, -68, -62, 201, 50, +-189, -89, -56, -385, 482, 221, 127, 198, +2, -85, -61, 58, 29, -137, 39, -198, +275, 162, 193, 76, -51, -160, -38, 210, +23, -165, 177, -185, 109, 429, 113, -428, +77, 24, -18, 330, -105, -371, 189, 262, +273, -62, -2, -297, 42, 204, -116, 125, +-27, -206, 365, -6, 56, 95, 168, -15, +-217, -99, -50, -39, 192, 44, 175, -14, +129, 78, 29, -4, -145, -220, -97, -69, +472, 376, -83, -84, -188, -295, 497, 70, +-285, 42, 41, 7, 207, 234, -181, -157, +223, -507, 131, 334, -155, 314, 178, -210, +-80, -115, 4, -63, 220, 10, -52, 111, +159, -16, -191, -20, 3, -63, 238, -56, +47, 139, -69, -108, 84, -170, -197, 251, +286, 193, 49, -439, -223, -128, 373, 316, +-195, -24, -46, 116, 86, -149, 111, -352, +16, 385, -108, -50, 258, -165, -230, 322, +-47, -356, 213, 153, -25, 88, 50, -342, +99, 171, -251, -1, -104, 126, 393, 164, +-52, -337, -124, -307, 104, 188, -40, 244, +-67, 190, 81, -160, -81, -381, 111, -12, +177, 264, -165, 49, -196, -171, -68, 93, +329, 157, 161, -317, -246, -60, -191, 99, +107, 28, -30, 174, 116, -98, 193, -165, +-301, 70, -96, -102, 200, 7, -196, 68, +195, 133, -2, -45, -203, -362, 306, 352, +-330, -39, -130, -437, 238, 440, 157, 96, +-123, -285, -237, 79, 20, -117, 55, 46, +79, 92, -100, -81, -12, -80, -6, 137, +-80, 77, 103, -199, -218, -48, -42, -115, +246, 252, -14, 197, -266, -286, -91, -207, +183, 287, -80, 4, -59, -298, -7, 217, +101, 83, -207, -73, -118, 18, 153, -197, +-47, 21, -68, 67, 16, -17, -87, 291, +-10, -214, -53, -282, -134, 89, 152, 121, +-56, 209, -100, -198, -99, -207, 75, 179, +-103, 131, -41, -179, 15, -157, -82, 252, +-49, -39, 74, 47, -117, -28, -174, -364, +-28, 297, 229, 170, -89, -248, -277, 174, +60, -247, -76, -32, -106, 390, 273, -351, +-162, 84, -222, 141, -67, -302, -28, 239, +175, 12, -49, -271, -172, 210, -132, 13, +-31, -7, 72, -34, -96, -194, 2, 122, +50, 213, -292, -151, -52, -145, 44, 21, +40, 212, -67, -18, -18, -268, -229, 74, +-139, 68, 237, 104, -138, 87, -21, -362, +91, 11, -574, 274, 182, -149, 333, 42, +-443, 88, 223, -120, -312, -72, -195, -20, +364, 21, -245, 235, 34, 0, -31, -217, +-356, -178, 56, 80, 161, 328, -67, 4, +-182, -110, -126, -292, 22, -73, -51, 390, +26, 260, -150, -301, -118, -449, 98, 234, +42, 442, -348, -152, -101, -352, 187, 24, +1, 393, -68, -52, -311, -348, -27, -12, +210, 300, -230, 146, 27, -400, -204, -60, +83, 361, -25, 24, -265, -394, 194, 65, +-111, 360, -336, -207, 234, -218, 63, 380, +-312, 77, -25, -681, -139, 203, 227, 695, +-243, -271, -140, -541, 284, 134, -354, 471, +-147, -234, 168, -167, 3, 301, -306, -211, +57, -193, 107, 449, -346, -59, 44, -375, +45, 219, -120, 144, -4, -183, -236, -24, +-11, 82, 255, 74, -420, -21, -1, -96, +147, -27, -377, 58, 106, 43, 113, 101, +-275, -135, -2, -80, -85, 112, -73, -44, +9, 171, -89, -140, -1, -232, -118, 247, +-19, 250, -181, -59, 3, -505, 38, -42, +-150, 677, 40, -126, -157, -299, -48, 283, +-93, -414, -127, -119, 227, 854, -147, -216, +-206, -782, -36, 689, -285, -60, 447, -425, +-24, 694, -671, -326, 297, -441, -6, 522, +-282, 149, 216, -301, -119, -153, -180, 164, +-130, 261, 78, -223, -85, -2, -94, -28, +68, -252, -26, 634, -380, 170, -147, -1036, +331, 183, 96, 874, -302, -363, -402, -296, +183, 128, 109, 23, -196, 92, 79, -32, +-207, -77, -197, 1, 106, 259, 22, -233, +-162, -238, -97, 457, -79, 133, -57, -482, +193, -216, -293, 785, -253, -158, 227, -632, +-153, 540, -25, 103, 73, -354, -369, 39, +29, 119, 23, 135, -54, -71, -209, -331, +122, 232, 147, 497, -574, -400, -309, -738, +630, 661, 278, 861, -947, -924, -201, -400, +707, 751, -196, -79, -506, -378, 92, 135, +34, 405, 120, 61, -248, -684, -355, -15, +259, 684, -140, -57, -8, -554, -99, 293, +-51, 437, -113, -562, -151, -238, 91, 719, +-284, -74, 187, -665, 22, 633, -298, 155, +-262, -693, 191, 196, 95, 625, -524, -518, +316, -354, 304, 818, -960, -225, -45, -425, +618, 328, -95, 58, -482, -85, -105, -147, +177, 89, 48, 600, -517, -597, 39, -550, +403, 852, -211, 129, -526, -211, 96, -420, +252, 22, -390, 683, 12, -480, 350, 82, +-594, 409, -231, -902, 436, 264, -218, 745, +-77, -382, -24, -145, -338, -77, 67, -32, +272, 448, -460, -283, -144, -274, 275, 688, +-190, -222, -234, -640, 128, 723, -154, -22, +-152, -726, 127, 803, -208, 268, -88, -1013, +226, 406, -436, 499, -307, -887, 705, 464, +-253, 835, -771, -1116, 563, -390, -128, 1421, +-267, -504, 215, -825, -286, 1141, -350, -558, +497, -503, 16, 1491, -716, -807, 100, -1062, +226, 1309, -112, 64, -68, -569, -162, 287, +-322, -185, 280, -148, -6, 579, -200, -104, +-73, -652, -231, 368, 125, 417, 205, -272, +-574, -201, -85, 50, 550, 290, -308, -250, +-626, -164, 315, 459, 352, 94, -377, -425, +-397, -163, 103, 292, 203, 172, 70, -104, +-533, 73, -252, -195, 593, -124, -92, 425, +-617, -194, 68, -295, 504, 528, -443, 116, +-554, -724, 652, 108, -51, 700, -485, -414, +212, -123, -460, 199, 346, -155, 103, 122, +-415, 163, -89, -311, 26, 7, 126, 391, +-354, -313, 31, -89, 215, 312, -406, -74, +-47, -49, 193, -121, -226, 99, -235, 107, +301, -173, -105, 178, -272, 71, 54, -150, +-110, -180, -53, 66, -97, 362, 235, -124, +-161, -37, -250, -141, -193, -105, 113, 410, +170, -175, 72, -230, -510, 434, -207, -6, +516, -538, -378, 407, 6, 90, 19, -427, +-119, 375, -100, 200, -33, -348, 33, 90, +-152, -76, -133, -296, 156, 594, 175, 185, +-717, -422, 68, -308, 696, 355, -618, 210, +-374, -612, 590, 478, -111, 470, -541, -742, +321, -100, 144, 328, -624, -53, 143, 201, +446, -40, -343, -232, -322, 167, 24, -109, +193, -99, -4, 259, -287, 47, -31, -138, +216, 91, -101, -95, -583, -219, 312, 160, +486, 404, -689, -126, 60, -423, 191, 254, +-475, -16, 255, -198, 87, 475, -332, -65, +356, -455, -353, 403, -361, -179, 387, -244, +210, 614, -456, -83, -72, -473, 322, 99, +-510, 374, 118, -263, 302, 67, -313, 123, +-176, -403, 12, 366, 296, 200, -241, -356, +-445, -143, 507, 194, -40, 262, -373, -123, +117, -175, -17, -25, -14, -8, -136, 332, +107, -33, -15, -385, -500, 199, 510, 33, +4, -27, -412, 245, 85, -251, -151, -160, +209, 363, 42, -200, -241, -61, -170, 299, +197, -119, -10, -62, -223, -121, 95, -35, +68, 292, -234, 48, 59, -33, -41, -304, +-159, 1, 222, 414, -54, -369, -311, 74, +138, 455, 156, -486, -313, -127, 49, 445, +-29, -362, 108, 12, -141, 491, -54, -309, +94, -41, -337, -67, 288, -302, -42, 629, +-47, 99, -230, -397, -45, -91, 427, 123, +-385, 126, -181, -218, 293, 292, -45, 18, +-173, -327, 55, 222, -150, -185, 126, 10, +-76, 623, 98, -744, -141, -46, -252, 807, +420, -719, -488, 21, 545, 445, -280, -252, +-586, -75, 663, 147, 61, -107, -371, 75, +-261, 120, 507, -343, -200, 233, -155, 202, +187, -368, -280, 44, 79, 179, 200, 80, +-216, -153, -96, -194, 217, 235, -544, 74, +586, -126, 117, 63, -797, -6, 343, -157, +302, 198, -561, 21, 309, -355, 268, 506, +-691, 77, 179, -851, 395, 696, -283, 84, +-197, -557, 138, 557, 36, -217, -121, -159, +304, 537, -493, -619, 51, -229, 264, 1109, +-207, -510, 149, -751, -106, 1086, -187, -287, +169, -813, 3, 1062, -248, -203, 247, -754, +139, 916, -360, -134, -236, -689, 561, 610, +-239, 63, -344, -634, 816, 552, -708, 422, +-288, -930, 817, -34, -328, 974, -337, -671, +360, -202, -39, 860, -335, -877, 275, 242, +76, 516, -284, -761, -28, 270, 443, 244, +-416, -126, -112, 2, 249, -277, -99, 332, +120, 75, -105, -433, -115, 379, -74, 60, +166, -505, 173, 421, -451, 323, 330, -819, +49, 256, -662, 635, 614, -681, -68, 3, +-64, 670, -64, -683, -150, -165, 226, 840, +-76, -325, -119, -487, 86, 404, 77, 47, +-92, -124, -119, 143, 102, -21, 89, -340, +-383, 249, 339, 249, 66, -363, -320, 237, +319, -2, -469, -295, 227, 126, 246, 248, +-276, -116, -21, -65, 32, -3, 212, -48, +-517, 116, 336, -23, 233, 194, -613, -492, +312, 179, 362, 587, -656, -726, 150, 98, +491, 459, -617, -471, 150, 54, 235, 163, +-154, 7, 83, 135, -78, -395, -215, 34, +-24, 440, 469, -386, 12, -184, -622, 763, +471, -124, -203, -1010, -364, 549, 908, 623, +-551, -714, -142, 224, 488, 372, -563, -675, +-56, 44, 623, 684, -242, -566, -377, -188, +690, 866, -634, -422, -269, -729, 1106, 794, +-678, 257, -506, -1053, 1164, 704, -622, 586, +-544, -1233, 1002, 386, -615, 787, -201, -1076, +901, 162, -467, 995, -605, -749, 595, -487, +101, 905, -426, -199, 495, -893, -110, 1323, +-697, -170, 619, -1336, 227, 1207, -552, 189, +274, -1043, 178, 638, -600, 261, 276, -617, +526, 283, -589, 230, -8, -423, 278, 135, +-224, 278, 72, -224, 194, -181, -252, 166, +-49, 287, 216, -491, -4, 259, -194, 324, +-22, -911, 291, 584, -39, 468, -404, -900, +220, 436, 273, 430, -215, -971, -208, 393, +270, 528, -84, -604, -6, 283, 40, 58, +-65, -420, 110, 306, -225, 40, 172, -76, +-31, 18, 14, 32, 177, 33, -410, -196, +133, -22, 243, 291, -236, -44, 52, -191, +224, 161, -389, -126, 48, -40, 404, 199, +-333, -4, -164, -85, 317, -386, 206, 629, +-525, 274, 22, -1229, 445, 678, -378, 573, +157, -912, 132, 464, -343, -23, 114, -189, +225, 388, -267, -468, 37, -7, 144, 748, +-137, -617, 139, -509, -102, 1252, -134, -495, +114, -938, 236, 1226, -189, -159, -204, -740, +141, 567, 227, 211, -205, -575, -83, 141, +179, 519, -166, -724, 79, 152, 271, 780, +-445, -827, -58, -82, 566, 721, -278, -655, +-290, -11, 418, 872, -293, -872, 96, -119, +416, 1016, -657, -978, 18, -124, 520, 1092, +-196, -770, -184, 62, 183, 243, -53, -452, +-239, 294, 455, 73, -264, 37, -175, -214, +640, 122, -669, 14, -39, -272, 722, 442, +-564, -234, -153, -193, 594, 594, -234, -477, +-522, -207, 674, 624, -4, -338, -584, -213, +345, 398, 227, -2, -314, -458, 80, 450, +82, 114, -270, -769, 284, 668, -14, 173, +-163, -790, 157, 684, -28, 88, -114, -867, +38, 686, -2, 112, 131, -554, -28, 533, +-44, -187, -29, -223, -195, 269, 227, -158, +217, 32, -225, 199, -153, 36, 70, -593, +111, 366, -54, 530, 22, -694, 53, -34, +-210, 424, 168, -150, 71, 55, -279, -38, +95, -360, 242, 481, -2, -40, -414, -298, +157, 330, 275, -134, -200, -194, -118, 183, +289, 105, -155, -238, -143, 235, 242, 44, +-154, -473, -66, 469, 286, -147, -188, -275, +-36, 741, 51, -393, -62, -492, -156, 491, +524, 21, -185, -26, -594, -68, 672, -119, +-115, 444, -400, -503, 385, -157, 197, 809, +-478, -535, -1, -221, 438, 665, -476, -347, +263, -310, 156, 295, -429, 165, 238, -81, +37, -283, -97, 220, -38, 128, 233, -247, +-163, 83, -146, 2, 132, -39, 58, 112, +62, 75, -182, -106, -3, -217, -18, 125, +134, 188, 52, -74, -100, 49, -54, -175, +-110, -138, 285, 402, -171, -115, 42, -281, +85, 370, -244, -55, 218, -312, -151, 257, +51, 8, 153, -162, -226, 235, 46, -15, +83, -247, -150, 58, 112, 216, 13, -120, +-63, 6, -21, 27, -46, -147, 200, 190, +-215, 84, 142, -400, -129, 161, -71, 373, +529, -347, -701, -52, 139, 238, 466, -279, +-476, 76, 138, 354, 223, -167, -448, -467, +101, 261, 318, 549, -111, -528, -156, -156, +-4, 457, 50, -317, -50, -22, 216, 398, +-227, -339, -115, -68, 412, 363, -273, -269, +-228, -190, 427, 373, -182, -113, -83, -71, +227, 336, -281, -415, 82, -234, 165, 517, +-274, 99, 96, -353, 234, 60, -195, 181, +-288, -212, 416, -152, 56, 325, -547, 96, +488, -289, 109, 194, -655, -105, 365, -352, +339, 573, -439, -15, -45, -372, 395, 303, +-418, -197, -45, -124, 606, 300, -331, 2, +-451, -139, 536, 28, -95, 55, -319, -253, +531, 143, -265, 327, -224, -330, 177, 6, +119, 178, -76, -308, -298, 98, 477, 267, +-167, -127, -211, -110, 220, -21, -181, 105, +78, -5, 196, -69, -241, 83, -79, -47, +252, -57, -172, 215, 16, -198, 112, -70, +-220, 223, 102, -177, 93, 207, -60, -173, +-35, -98, -185, 374, 257, -354, 35, 132, +-247, 126, 138, -355, -57, 244, 139, 97, +-148, 11, -39, -206, 63, -160, -47, 339, +205, 40, -189, -210, -18, 112, -63, -23, +33, -147, 202, 206, -224, -44, 161, -33, +-105, 69, -328, -197, 525, 236, -1, -86, +-467, -190, 237, 481, 179, -468, -310, -63, +109, 675, 341, -624, -661, -135, 145, 676, +642, -403, -529, -181, -54, 548, 191, -431, +-282, -356, 244, 775, 263, -8, -469, -666, +133, 366, 91, 98, -366, -297, 429, 261, +133, 123, -550, -424, 212, 212, 299, 305, +-450, -567, 79, 190, 337, 293, -255, -370, +34, 257, -25, 5, -186, -367, 395, 340, +-74, 194, -465, -547, 291, 93, 303, 501, +-262, -280, -89, -34, -45, -46, -35, -265, +180, 411, 235, 123, -48, -166, -705, -131, +285, -196, 509, 313, -407, 139, 51, -230, +105, 8, -104, 88, -74, -29, 27, -107, +-62, -10, 125, 55, 218, 269, -169, -74, +-319, -425, 116, 165, 101, 162, 72, -79, +110, 190, -287, -56, 74, -261, 9, -13, +-182, 263, 340, -74, -130, -20, -201, 132, +336, -255, -111, 121, -341, 67, 257, -216, +99, 236, -228, -4, 268, -74, -84, -9, +-286, -21, 115, 3, 277, 12, -371, 124, +219, -93, 253, -102, -761, 77, 499, 72, +244, -22, -648, -65, 389, 62, 181, -119, +-443, 3, 69, 337, 452, -223, -588, -258, +42, 297, 695, 62, -688, -245, 20, 69, +356, 173, -382, -202, 239, 135, 140, 104, +-403, -413, 165, 100, 172, 456, -281, -308, +154, -90, 107, 198, -298, -184, 124, -58, +225, 244, -352, 50, 115, -269, 120, 130, +-195, 56, 174, -284, -18, 212, -188, 291, +112, -377, 116, -66, -305, 325, 261, -318, +46, 171, -226, 126, 132, -311, -169, 206, +165, 25, -48, -58, 72, -103, 25, 28, +-295, 73, 239, 99, -43, 11, -126, -315, +289, 130, -82, 145, -344, -51, 285, -70, +44, 36, -247, 58, 206, -39, 97, -22, +-232, -148, -64, 170, 207, 119, -58, -162, +-36, -8, 24, 32, 56, 0, -162, -47, +75, 51, -32, 99, 10, -170, 228, 45, +-421, 209, 227, -238, 107, -164, -280, 277, +67, 149, 255, -329, -53, 110, -456, 172, +364, -404, 176, 333, -494, 140, 313, -578, +121, 493, -323, 166, 132, -674, 76, 380, +-184, 307, 64, -581, 214, 257, -210, 307, +-18, -623, 87, 388, -162, 221, 171, -595, +76, 298, -191, 259, -51, -354, 259, -16, +-127, 326, -229, -295, 214, -73, 186, 496, +-227, -357, -122, -269, 226, 391, -154, 87, +117, -262, 32, 26, -282, 177, 307, -291, +-43, 176, -149, 249, 57, -432, 47, -11, +-47, 382, 14, -123, 132, -196, -245, 123, +68, -29, 152, 48, -119, 19, -43, -104, +43, 90, 55, -56, -43, 100, -26, 20, +-47, -280, 64, 166, 74, 150, -66, -40, +-168, -110, 122, -90, 174, 217, -150, -51, +-85, -129, 15, 145, 96, -90, -49, 55, +64, 82, -20, -192, -157, 94, 162, 28, +-11, -90, -146, 47, 110, 166, 144, -149, +-246, -128, 119, 261, 66, -232, -371, 13, +416, 178, -22, -60, -194, 87, 222, -188, +-305, -147, 71, 294, 164, 77, -23, -314, +-5, 243, -66, 44, -27, -302, -57, 223, +70, -96, 161, -23, -105, 314, -85, -292, +54, -73, -65, 274, -25, -284, 199, -24, +23, 491, -314, -310, 175, -261, 37, 375, +-90, -224, 142, 14, -135, 306, 40, -333, +74, 7, -113, 212, -4, -223, 85, 91, +-61, 148, 63, -223, 48, 18, -167, 222, +-40, -211, 204, -154, -31, 441, -101, -146, +122, -301, -120, 322, -36, -124, 69, -145, +99, 331, -27, -54, -86, -219, -26, 86, +-135, -114, 401, 127, -117, 301, -306, -413, +296, 81, -104, 169, -120, -429, 243, 307, +88, 280, -470, -364, 222, 54, 325, 46, +-501, -101, 153, 78, 278, -57, -288, 241, +9, -127, 189, -213, -251, 246, 48, -153, +265, -31, -143, 215, -109, -60, 44, -81, +-88, 27, 178, -53, 67, 42, -275, -10, +193, 119, -7, 5, -281, -340, 375, 339, +-55, 71, -272, -452, 347, 363, -130, 111, +-290, -360, 358, 150, 63, 29, -331, 11, +233, 89, 5, -195, -327, -23, 355, 187, +166, 7, -528, -192, 201, 96, 322, 155, +-537, -192, 338, -120, 154, 288, -520, 27, +382, -316, 83, 203, -311, 43, 17, -217, +271, 208, -147, 57, -34, -107, 127, -28, +-280, -187, 145, 170, 198, 321, -195, -214, +-11, -141, 81, -96, -54, 80, 5, 302, +-53, -231, -43, -21, 308, 200, -132, -171, +-306, -140, 248, 158, 26, -13, -189, 19, +347, 224, -126, -237, -402, -226, 491, 229, +-22, 90, -425, -184, 358, 149, 105, 133, +-389, -330, 267, -5, 170, 289, -570, -113, +302, -167, 371, 205, -469, -43, 103, -107, +110, 140, -149, -58, 62, -29, 137, 32, +-156, -120, -189, 27, 526, 291, -219, -24, +-409, -454, 372, 112, 133, 372, -263, -201, +8, -238, 311, 428, -377, -54, -12, -499, +311, 482, -139, 36, -58, -506, 73, 408, +-6, 169, -145, -403, 172, 157, -1, 61, +-95, -212, 108, 215, -42, 4, -197, -195, +234, 159, 95, 122, -244, -210, 59, -126, +100, 189, -102, 119, -22, -190, 122, 47, +-20, 150, -131, -260, 70, 63, 48, 250, +-18, -326, -95, 24, 98, 333, 57, -214, +-122, -54, 65, 51, -87, -194, 70, 234, +124, 147, -196, -235, 75, -26, 28, 29, +-115, 35, 162, -13, -59, -5, -112, 124, +188, -116, -157, 14, 30, -24, 173, -205, +-290, 389, 127, 6, 136, -296, -116, 173, +-77, -199, 117, 83, -37, 261, -65, -261, +194, 125, -190, -16, -36, -312, 272, 339, +-182, 87, -128, -298, 142, 162, 96, 90, +-54, -246, -111, 40, -32, 259, 113, -252, +72, 72, -40, 209, -167, -461, 90, 199, +140, 325, -140, -394, -12, 121, 45, 114, +-4, -257, 22, 176, 13, 5, -68, -62, +47, 120, -79, -137, 98, -37, 76, 100, +-175, 36, 112, -60, -135, -13, 92, 68, +82, -99, -190, 44, 216, 80, -114, -104, +-57, 28, 51, -9, -73, 23, 169, 49, +19, -66, -189, 20, 40, -58, 6, -52, +15, 308, 135, -128, -176, -350, 15, 337, +206, 84, -272, -295, -27, 169, 309, 152, +-208, -352, 0, 27, 178, 426, -182, -338, +-126, -85, 195, 419, 127, -448, -204, -54, +60, 545, 2, -389, -138, -53, 234, 421, +-60, -430, -192, -121, 231, 385, -33, -56, +-157, -34, 147, 45, -3, -151, -234, -136, +272, 266, 148, 141, -422, -327, 186, 119, +116, 69, -242, -201, 165, 239, 41, -80, +-72, -176, 90, 265, -97, -91, -221, -172, +350, 254, 51, 12, -314, -308, 237, 150, +-10, 215, -223, -314, 34, 107, 268, 242, +-139, -336, 6, 86, 64, 120, -360, -175, +359, 152, 43, -7, -319, -141, 286, 98, +26, 181, -228, -273, 49, -106, 131, 351, +-207, -197, 136, -40, 254, 319, -315, -238, +-120, -227, 259, 241, -109, -11, -57, -21, +298, 168, -209, -126, -98, -128, 181, -14, +-181, 131, 22, 122, 145, -197, 45, 20, +-59, 138, -104, -183, -76, 77, 95, 107, +84, -281, -26, 182, 125, 254, -174, -375, +-115, 34, 93, 230, 26, -240, 113, 3, +-3, 236, -74, -92, -41, -168, -93, 159, +136, -14, 26, -148, -12, 191, 31, -17, +-81, -118, 33, 162, -59, -117, -57, -172, +197, 284, -27, 81, -96, -250, 118, 50, +-172, 36, 12, -122, 117, 176, -35, 88, +5, -175, 28, -5, 16, -27, -143, -2, +0, 126, 159, 45, 10, -87, -110, -164, +21, 114, 87, 105, -121, -70, -39, -45, +153, 68, -40, 33, -92, -150, 255, 63, +-227, 61, -188, -12, 360, -8, -50, -45, +-142, 48, 72, -52, 35, -30, -34, 141, +-42, -16, 41, -157, -6, 56, 60, 109, +-21, -117, -59, 9, 74, 109, -85, -87, +-39, -57, 216, 41, -57, 92, -179, -66, +187, -81, -79, 158, -62, -82, 80, -77, +13, 144, 34, -78, -10, -20, -60, 96, +-126, -95, 185, -58, 69, 117, -108, 47, +43, -104, -57, 65, -66, -49, 118, -191, +-24, 284, -9, 89, 97, -227, -119, 88, +-14, -97, 5, -120, 66, 292, 83, 99, +-167, -333, 53, 48, 130, 191, -235, -291, +167, 124, 49, 236, -237, -233, 205, 73, +11, -48, -66, -174, 53, 308, -81, 19, +-60, -201, 77, 50, 64, 4, 6, 4, +24, 30, -138, -34, -11, 33, 100, 93, +-11, -260, 79, 38, -71, 318, 27, -271, +-59, 37, -172, 150, 213, -214, 65, 95, +-10, 22, -77, -30, -95, 56, 76, -46, +114, 16, -121, 12, -3, -51, 149, -80, +-180, 92, 94, 146, 27, -108, -150, -105, +145, 95, 44, -52, -74, -113, 47, 278, +-73, -30, -27, -216, 62, 212, 15, -154, +6, -172, 1, 362, -4, -20, -16, -163, +-18, 68, 36, -138, 46, 65, -19, 185, +-54, -137, 13, -83, -17, 114, -1, 9, +113, -84, -35, 46, -50, -55, 44, 19, +-79, 66, 184, 21, -118, -14, -92, -274, +157, 232, -105, 199, 115, -332, -75, 151, +-76, 85, 161, -271, -86, 120, 50, 170, +10, -124, -71, 1, 51, 63, -56, -110, +-109, -85, 211, 172, 41, 88, -109, -84, +34, -21, -50, -181, 0, 29, -10, 266, +195, -75, -22, -76, -230, -4, 70, -68, +93, 58, -99, 24, 52, -37, 153, 63, +-67, 31, -41, -82, -47, -103, -95, 75, +148, 144, 119, -111, -173, -43, -8, 91, +175, -73, -170, 34, -26, 40, 116, -118, +14, -24, 84, 170, -112, 12, 6, -136, +-62, 86, -98, -177, 225, -12, 39, 382, +-81, -175, 38, -137, -96, 77, 68, -140, +-21, 126, -41, 140, 191, -145, -88, -54, +-115, 115, 13, -11, 77, -194, -14, 129, +75, 192, 7, -175, -118, -29, 100, 64, +-51, -90, -90, 15, 149, 148, 27, -42, +-168, -124, 161, 53, -45, -13, -79, 61, +124, -5, 60, -70, -140, 89, -1, -76, +118, 44, -196, 64, 93, -237, 126, 158, +-120, 216, 14, -290, 83, 4, -95, 156, +5, -200, 176, 89, -225, 221, 110, -214, +70, -73, -229, 125, 176, -132, -15, 76, +-29, 197, 91, -156, -20, -100, 15, 80, +-117, -54, 16, 41, 134, 146, -115, -99, +13, -147, 64, 132, -5, 69, 0, -188, +-108, 90, 102, 55, 116, -96, -65, 197, +-2, -104, -188, -260, 63, 193, 204, 149, +-106, -91, -56, 22, 61, -82, 46, -85, +-58, 130, 12, -17, 128, 61, -158, 33, +-41, -244, 223, 108, -221, 193, -64, -283, +384, 112, -190, 178, -128, -327, 241, 201, +-197, 70, 26, -300, 262, 235, -268, 58, +-20, -138, 150, 33, -135, -3, 16, -62, +214, 7, -164, 278, 26, -191, 162, -253, +-281, 337, 72, -193, 192, 27, -248, 352, +84, -451, 268, 21, -311, 319, -88, -362, +278, 70, 61, 407, -207, -311, 95, -241, +38, 345, -151, -64, 126, -161, -89, 237, +24, -67, 92, -112, -23, 75, 2, -54, +-15, 63, -4, 25, -23, -78, 105, 78, +-26, -89, -131, -43, 86, 221, 39, -119, +-50, -93, -24, 107, 141, -99, -19, 70, +-144, 91, 225, -76, -45, -56, -326, -67, +241, 171, 182, 8, -306, -182, 81, 164, +220, -22, -266, -100, 137, 146, 216, -54, +-453, -157, 108, 69, 378, 253, -325, -130, +-78, -211, 266, 174, -203, -73, 16, 47, +328, 194, -240, -221, -197, -116, 251, 127, +42, 130, -165, -45, 12, -150, 98, 110, +-26, 31, -38, -130, 26, 113, 6, -21, +48, -87, 119, 140, -163, -85, -107, -84, +125, 185, 34, -94, 29, -83, -28, 205, +-66, -109, -36, -129, 170, 113, 38, 39, +-186, -45, 107, 39, 6, 78, -49, -273, +48, 56, -19, 306, -120, -244, 141, 39, +105, 80, -200, -221, 169, 131, -21, 87, +-159, -17, 151, -11, -46, -97, -75, -10, +80, 51, 100, 156, -129, -122, -97, -187, +224, 233, -44, -9, -24, -58, 66, 58, +-135, -135, -42, 32, 100, 104, 38, 61, +10, -75, -98, -202, -27, 68, 218, 192, +-41, -5, -96, -53, 4, -56, -85, -108, +100, 111, 108, 104, -158, -90, 7, 56, +141, -63, -159, -122, 63, 124, 160, 60, +-156, -10, 17, -4, 29, -51, -173, -125, +137, 122, 155, 193, -188, -250, 93, -23, +-45, 124, -105, -66, 213, 112, 49, -82, +-123, -45, -154, 79, 87, -103, 113, 137, +-36, -18, 18, -185, -68, 165, 38, -18, +13, -71, -35, 126, 119, -13, -30, -40, +-77, -101, -14, -49, 4, 185, 36, 126, +33, -186, -76, -148, 41, 110, 99, 32, +-49, 144, -3, 77, -3, -369, -50, -63, +-51, 254, 155, 12, -24, 40, -185, -35, +167, -207, 29, 162, -34, 218, 89, -352, +-104, -58, -27, 379, 52, -184, -83, -123, +56, 264, 38, -164, -93, -143, 85, 299, +67, -87, -91, -151, 48, 219, 46, -258, +-134, 2, 31, 383, 55, -226, -57, -76, +42, 89, -15, -233, -39, 177, 70, 316, +60, -279, -13, -195, -45, 129, -24, -1, +-54, 166, 78, 65, -35, -258, 28, -51, +-27, 26, -27, 204, 188, 144, -140, -368, +-47, -63, 180, 345, -108, -21, -51, -266, +-7, -31, -23, 148, 120, 109, 67, 88, +-150, -141, -55, -233, 204, 39, -1, 229, +-180, 118, 95, -218, 17, -183, -139, 107, +171, 205, 56, 137, -162, -184, -84, -225, +104, 64, 129, 106, -82, 125, -12, -107, +56, -194, -97, 140, 74, 180, 10, 96, +-136, -185, 1, -270, -18, 108, 50, 121, +269, 31, -42, 57, -218, -44, 44, -59, +-32, 71, -122, -75, 114, -111, 180, 220, +-41, 8, -215, -199, 12, 1, 220, 33, +70, 216, -80, 67, -125, -280, -202, -68, +175, 25, 210, 112, -144, 110, -3, -87, +-15, -50, -5, -20, 152, 97, -59, 14, +-170, -150, 26, 35, 52, 44, 112, -35, +15, 37, -197, 108, 127, -1, 23, -126, +-107, -64, 105, -55, -56, 96, -30, 118, +60, -73, 75, 16, 6, 47, -56, 1, +-87, -25, -65, -174, 84, -119, 42, 157, +54, 260, 73, -1, -147, -109, -52, -14, +120, -151, 3, 17, -52, 207, -150, -166, +109, -176, 74, 170, -37, 205, 209, 97, +-110, -116, -226, -229, 75, -153, 89, 157, +20, 184, -52, -104, -76, 2, 74, 81, +134, 35, -52, -18, -48, -153, -96, -112, +-24, 110, 149, 95, 7, -4, 19, 155, +-138, -132, -25, -248, 187, 217, -22, 121, +-42, -214, -188, -138, 54, 199, 314, 191, +-83, -13, -147, -92, -32, -322, 52, -19, +-14, 330, 21, 5, 54, -10, -78, 46, +52, -189, 147, -8, -131, 213, -97, -156, +26, -239, -159, 152, 341, 241, 86, 155, +-477, -207, 320, -294, 98, 91, -286, 89, +151, 50, 64, 125, -261, -140, 73, -113, +248, 247, -123, -73, -7, -205, -125, 134, +-91, -111, 429, 148, -81, 367, -354, -374, +118, -220, 26, 204, -52, -106, 241, 103, +2, 77, -316, -153, 98, 255, 180, 115, +-145, -309, -41, -263, 58, 74, -64, 179, +199, 69, 60, 229, -405, -67, 104, -315, +228, 111, -232, -63, 57, -183, 157, 263, +-132, 98, 85, 8, 53, 129, -279, -316, +-3, -247, 220, 306, 62, 88, -159, -127, +-196, 140, 202, 17, 264, -71, -78, -53, +-298, -232, -54, 111, 158, 332, 102, -69, +-112, -186, -114, 7, 148, 117, 30, -5, +5, -176, -50, 10, -38, 110, 46, 37, +-162, 120, 32, -137, 90, -268, -20, 266, +16, 197, -5, -192, -23, -15, 12, -63, +15, -109, -133, 79, -45, 183, 133, 130, +89, -129, -17, -101, -210, -70, 34, -149, +96, 168, -108, 208, -15, -136, 113, 0, +174, 250, -255, -179, -142, -393, 170, 118, +-80, 187, -9, 59, 51, 226, 39, -99, +89, -210, -148, -79, -169, -274, 108, 196, +99, 472, -89, -1, 12, -129, 136, -177, +-53, -194, -259, 43, -58, 69, 75, 93, +182, 203, 177, 33, -138, -157, -259, -172, +55, -31, 42, 25, -159, -54, 146, 281, +52, 272, -134, -304, 84, -283, 85, -4, +-92, 149, -133, 156, -131, -63, -25, 23, +466, 133, -5, -67, -420, -252, -42, -188, +-84, 147, 200, 306, 232, 137, -134, -125, +-15, -107, -35, -40, -256, -243, -125, -82, +284, 331, 133, 318, -169, -71, 77, -309, +48, -62, -257, 157, -189, -186, 136, -50, +223, 430, 53, -37, -110, -256, -145, 139, +-65, -22, -78, -239, 34, 6, 154, 193, +102, 173, -149, 74, -79, -243, 36, -225, +-221, 172, 58, 100, 157, -155, -52, 51, +-15, 231, 13, -63, -98, -156, -166, 54, +76, -89, 72, -45, 40, 192, 66, -31, +-106, -39, -220, 72, -9, -54, 69, -20, +-47, -80, 63, -104, 204, 292, -101, 186, +-262, -316, -95, -61, -28, 45, 237, -135, +94, 174, -184, 114, -1, -79, -25, 58, +-192, -45, 5, -87, 219, -55, -89, -139, +-86, 136, 150, 338, -70, -50, -237, -263, +-87, 28, 207, 51, 1, -185, -161, 88, +171, 282, 11, -110, -285, -176, -4, 105, +127, 43, -24, -83, -56, -44, -64, 33, +-65, 99, 21, -2, 68, -93, -30, 70, +-39, 66, -35, -242, 10, 40, -131, 292, +-154, -248, 105, -141, 106, 369, 99, 3, +-45, -318, -295, 84, -24, 170, 132, -200, +-255, -1, 49, 157, 341, -125, -165, 85, +-201, 151, 120, -192, -178, -66, -144, 36, +218, -62, 23, 78, -100, 134, 20, -71, +-139, -40, -170, 32, 246, -110, 97, 45, +-266, 134, -37, -38, 10, -146, -173, -21, +27, 113, 245, 55, -58, 63, -98, -99, +-89, -123, -139, 88, 44, -30, -156, -29, +65, 164, 289, -10, -87, -105, -248, 2, +23, -18, -118, -29, -225, -62, 353, 222, +149, 151, -307, -326, -119, 11, -23, 136, +6, -209, 45, 40, -19, 171, -13, 43, +77, 59, -190, -123, -329, -124, 171, -83, +147, 22, -50, 221, 142, 38, -121, 11, +-287, -52, -46, -116, -62, -63, 44, -136, +194, 176, 78, 238, -36, -37, -200, 71, +-289, -150, -211, -378, 174, 96, 386, 159, +114, -28, -209, 367, -350, 196, -92, -465, +-5, -242, 3, 1, 106, -154, 137, 292, +72, 512, -318, 103, -158, -411, -12, -525, +-75, 123, 51, 219, 228, -58, 26, 395, +-352, 226, -33, -468, -65, -295, -17, -52, +210, 141, -90, 366, -97, 69, -151, -83, +-122, -82, 194, -254, 107, -100, -250, 197, +-89, 97, 160, 83, -128, 241, -224, -223, +63, -449, 97, 172, -62, 215, 122, -205, +-47, 287, -349, 364, -93, -559, 21, -384, +186, 389, 167, 151, -238, -158, -159, 218, +4, 205, -111, -451, -5, -298, 151, 375, +-68, 88, -76, -92, 43, 213, -291, -140, +-113, -217, 298, 208, 47, -17, -137, -241, +-123, 254, -134, 241, 126, -270, -169, -149, +-145, 6, 393, 33, -52, 198, -286, 67, +-17, -38, -55, -111, -131, -334, 104, 71, +146, 473, -143, -68, -2, -226, -164, 171, +-193, -77, 211, -278, 25, 87, -188, 176, +72, 142, 149, 125, -325, -273, -210, -331, +134, 91, 98, 185, 136, 174, -155, 36, +-185, -50, -37, 30, -120, -439, -25, -177, +212, 540, 72, 88, -265, -118, 16, 234, +63, -120, -384, -562, -80, -58, 296, 441, +191, 219, -126, 86, -333, 7, -42, -335, +52, -408, -218, 31, 152, 397, 368, 274, +-193, 60, -348, -62, -125, -275, -66, -342, +146, -66, 162, 392, -46, 268, 38, -84, +-159, 170, -351, -159, -100, -602, 182, 54, +258, 501, -24, 51, -178, -117, -90, 170, +-185, -48, -122, -462, 165, -156, 202, 564, +-71, 221, -215, -368, -125, 125, 31, 94, +-5, -450, -145, -96, 157, 400, 144, 250, +-208, -85, -157, -217, -103, -64, -81, -46, +118, -109, 236, 224, 14, 282, -334, -70, +-191, -215, 84, -132, 4, -40, -105, 109, +90, 121, 161, 56, -22, 122, -267, -43, +-295, -280, 68, -237, 184, 188, 29, 322, +9, -52, -44, 20, -188, 127, -152, -393, +-25, -306, 44, 330, 244, 295, 98, 147, +-415, -195, -219, -383, 173, 97, 58, 34, +-55, 26, -5, 317, 71, -15, -67, -221, +-246, -13, -159, -144, 166, -135, 298, 394, +-148, 242, -378, -364, 89, -73, 239, 276, +-290, -217, -281, -315, 394, 344, 217, 391, +-390, -319, -123, -239, 69, 265, -150, -115, +-5, -257, 178, 317, 106, 318, -141, -288, +-282, -224, -56, 209, 133, -123, -62, -179, +18, 411, 231, 129, -171, -403, -329, 60, +83, 144, 64, -165, -202, 30, 140, 22, +221, 52, -148, 146, -198, -54, -186, -149, +-35, -108, 219, 29, 79, 69, -66, 73, +48, 265, -178, -25, -360, -524, 123, -140, +272, 431, -28, 212, -18, -171, -119, -114, +-218, 8, 65, -36, 91, 74, -62, 206, +-32, -223, -90, -423, 61, 402, 163, 655, +-245, -395, -280, -792, 151, 169, 195, 734, +1, 180, -139, -488, -157, -479, -6, 269, +78, 539, -77, -144, -6, -584, 155, -13, +-64, 918, -147, 206, -116, -1280, -143, -373, +206, 1254, 251, 357, -216, -918, -155, -101, +50, 628, -24, -119, -171, -601, 57, 55, +229, 735, -245, 39, -74, -729, 363, 68, +-174, 577, -515, -267, 94, -526, 538, 359, +53, 507, -580, -326, -224, -394, 535, 316, +162, 260, -459, -420, -158, -238, 332, 522, +68, 306, -305, -593, -76, -285, 116, 640, +126, 33, -47, -523, -110, 296, -104, 212, +-44, -386, 181, 11, -93, 258, -160, -7, +253, -247, 47, 38, -416, 310, 14, -211, +397, -198, -214, 340, -402, -115, 373, -346, +371, 562, -593, 243, -323, -967, 613, -65, +133, 1159, -583, -193, -11, -1070, 623, 549, +-263, 757, -799, -860, 477, -429, 796, 1017, +-654, 148, -642, -1003, 669, 208, 359, 873, +-715, -589, -249, -762, 605, 915, 165, 622, +-377, -1019, -71, -238, -46, 772, -76, -311, +215, -389, 154, 704, -261, 172, -145, -739, +314, -26, -202, 506, -404, -281, 433, -168, +339, 531, -449, -60, -93, -392, 262, 129, +-396, -30, -111, -244, 618, 430, 84, 356, +-610, -459, -108, -319, 416, 170, -37, 304, +-305, -79, 70, -394, 247, 222, 54, 532, +-275, -225, -164, -602, 189, 216, 14, 420, +-182, -573, 100, -107, 355, 1122, -103, 1, +-537, -1304, -108, -54, 415, 847, 281, -80, +-125, -34, -417, 298, -196, -632, 500, -188, +399, 1030, -616, -285, -601, -1440, 516, 846, +647, 1721, -69, -1081, -633, -1424, -622, 698, +579, 706, 1135, 37, -589, -128, -1484, -645, +701, -28, 1609, 955, -969, -159, -1497, -1030, +1057, 414, 1133, 985, -833, -529, -784, -819, +456, 440, 515, 430, -250, -192, -391, 34, +66, -86, 359, -190, 123, 323, -438, -60, +-249, -574, 463, 452, 175, 805, -509, -750, +-55, -781, 599, 939, -116, 360, -650, -1019, +169, 237, 530, 835, -136, -617, -353, -291, +52, 609, 225, -385, -36, -317, -377, 750, +151, -198, 567, -513, -323, 841, -654, -236, +488, -1176, 468, 957, -729, 862, -51, -1158, +793, -145, -395, 924, -600, -604, 633, -501, +188, 1062, -612, -76, 174, -843, 339, 448, +-307, 96, -30, -287, 196, 351, -131, -137, +-71, -210, 47, 330, 53, -116, 180, -88, +-206, 168, -353, -448, 317, 112, 248, 830, +-275, -452, -17, -870, 205, 823, -268, 643, +-202, -1347, 459, -169, 86, 1669, -504, -451, +151, -1348, 352, 978, -444, 608, -54, -1315, +583, -52, -241, 1490, -682, -269, 490, -1338, +648, 553, -723, 889, -426, -756, 800, -526, +73, 874, -755, 289, 199, -833, 572, -87, +-346, 665, -326, 13, 344, -567, 53, 53, +-355, 517, 93, -187, 341, -376, -77, 344, +-415, 128, 39, -528, 612, 274, -327, 650, +-719, -743, 674, -521, 639, 1010, -918, 60, +-364, -790, 911, 466, -112, 187, -621, -632, +391, 277, 273, 316, -368, -177, -68, 162, +221, -500, -127, -75, -158, 1038, 256, -777, +203, -705, -325, 1581, -167, -308, 300, -1542, +-61, 1256, -329, 639, 270, -1502, 409, 471, +-501, 885, -227, -1042, 666, 175, -220, 849, +-751, -1059, 570, -268, 692, 1332, -793, -122, +-307, -1091, 747, 256, -302, 693, -409, -399, +741, -221, -168, 405, -871, -268, 856, -28, +680, 613, -1346, -558, -405, -645, 1396, 989, +62, 233, -967, -1104, 326, 523, 289, 926, +-586, -1208, 150, -384, 613, 1337, -388, -483, +-372, -911, 595, 1320, 8, 382, -740, -1703, +217, 125, 724, 1383, -330, -718, -622, -542, +445, 1062, 527, -209, -497, -707, -452, 519, +347, -165, 404, -581, -173, 883, -318, 544, +210, -1071, 97, -279, -320, 882, 100, -55, +310, -702, -188, 97, -147, 740, 238, 56, +6, -725, -344, -28, 14, 333, 475, -170, +19, 262, -524, 123, 75, -609, 413, 421, +-210, 434, -197, -1130, 253, 255, -7, 1229, +-116, -1094, 217, -353, -206, 1402, -228, -899, +411, -806, 106, 1495, -362, -223, 123, -1006, +205, 789, -399, 43, 35, -510, 465, 424, +-172, -203, -216, -77, 254, 634, -110, -613, +-290, -405, 408, 929, 202, -237, -490, -630, +142, 633, 257, 95, -492, -512, 278, 326, +517, 184, -764, -674, -20, 63, 905, 1048, +-645, -301, -577, -1313, 1017, 797, 63, 1221, +-864, -1579, 459, -700, 471, 2246, -716, -116, +-129, -2281, 725, 938, 24, 1649, -612, -1544, +162, -823, 578, 1886, -519, 61, -462, -1750, +938, 532, 164, 1028, -1006, -726, 334, -175, +720, 454, -668, -223, -322, 146, 747, 3, +166, -644, -623, 504, -143, 529, 639, -741, +150, 146, -833, 549, 105, -760, 1071, -164, +-568, 851, -916, -238, 1110, -523, 468, 679, +-1431, 135, 213, -1131, 1425, 246, -764, 1338, +-909, -720, 1007, -1098, 279, 1228, -819, 494, +177, -1488, 449, 166, -68, 1297, -63, -494, +-402, -856, 131, 415, 756, 562, -553, -122, +-520, -651, 1136, -47, -45, 1062, -1262, -267, +673, -1316, 793, 1003, -924, 997, 116, -1629, +769, -131, -714, 1649, -137, -890, 795, -962, +-389, 1504, -508, -52, 734, -1443, 315, 827, +-770, 896, -89, -1106, 756, -252, -157, 1051, +-582, -311, 636, -824, 366, 730, -949, 367, +64, -799, 946, 75, -450, 531, -443, -115, +768, -404, -71, -56, -697, 687, 536, -141, +367, -949, -781, 744, 298, 559, 834, -1116, +-617, 404, -501, 643, 581, -1101, 218, 435, +-390, 833, 60, -1276, 484, 108, -86, 1425, +-691, -834, 304, -1158, 825, 985, -716, 876, +-370, -1003, 1283, -485, -334, 1267, -1364, -198, +1050, -1480, 894, 895, -1078, 1163, -169, -1149, +760, -466, -32, 906, -359, 90, -43, -627, +227, -281, 255, 649, -93, 486, -113, -844, +142, -231, -86, 993, -143, -395, 286, -1003, +325, 965, -213, 698, -365, -1141, 306, -87, +432, 981, -492, -527, -297, -824, 895, 956, +153, 616, -922, -1276, 162, 48, 793, 1412, +-429, -1134, -452, -1004, 826, 1900, 164, -72, +-739, -1684, 188, 1277, 305, 606, -154, -1783, +322, 611, -191, 1230, -266, -1275, 826, -132, +-204, 1204, -1029, -612, 737, -715, 925, 627, +-877, 246, -375, -359, 1013, -14, -45, 443, +-898, -167, 319, -683, 667, 434, -251, 339, +-228, -379, 481, 410, 37, -169, -848, -628, +273, 633, 1263, 168, -639, -597, -1197, 230, +1375, 389, 873, -165, -1899, -439, -53, 112, +1928, 537, -690, -481, -1112, -236, 1222, 886, +265, -351, -1181, -766, 455, 750, 941, 166, +-680, -815, -355, 430, 797, 747, -64, -798, +-589, -581, 248, 1047, 546, 119, -2, -1146, +-529, 543, 173, 894, 607, -947, -584, -256, +-346, 736, 1140, -344, 24, -137, -1118, 357, +454, -144, 846, 115, -620, -102, -464, -435, +851, 427, 370, 312, -865, -613, -133, 153, +972, 767, -143, -800, -809, -677, 632, 1394, +643, -62, -748, -1488, -226, 1192, 710, 810, +-16, -1767, -450, 199, 313, 1291, 572, -791, +-500, -348, -528, 665, 834, -171, 256, -167, +-796, 23, 479, -193, 615, 386, -886, 158, +-110, -650, 880, 287, -271, 605, -279, -811, +631, -306, -74, 1011, -517, -92, 188, -879, +385, 539, -49, 538, -173, -905, 328, -77, +168, 846, -479, -317, 158, -307, 301, 480, +-412, -343, 340, -427, 632, 798, -526, 63, +-406, -951, 576, 681, 26, 594, -494, -1370, +687, 263, 490, 1304, -1046, -1035, 49, -530, +1042, 1253, -661, -210, -503, -1220, 1238, 649, +1, 1319, -1187, -1303, 673, -1165, 877, 2249, +-1042, 206, -335, -2601, 1244, 1091, 121, 1774, +-997, -1698, 146, -539, 877, 1414, -354, -28, +-788, -985, 867, -58, 962, 892, -1319, -14, +-590, -887, 1710, 559, -130, 617, -1562, -1076, +1007, -199, 1353, 1069, -1404, -50, -730, -739, +1589, 153, -19, 528, -1475, -358, 1066, -367, +1254, 615, -1653, -87, -428, -575, 1725, 691, +-361, 155, -1322, -858, 988, 159, 1207, 529, +-1111, 74, -1015, -473, 1348, -487, 684, 1159, +-1474, 219, 61, -1914, 1492, 896, -456, 1691, +-957, -1876, 605, -514, 361, 1765, -343, -516, +262, -803, -6, 670, -303, -72, 667, -155, +40, 278, -1030, -436, 495, 90, 1111, 668, +-694, -493, -719, -407, 827, 526, 481, -143, +-856, -178, -186, 543, 1092, -302, 14, -488, +-987, 742, 319, 81, 815, -1111, -534, 414, +-431, 1234, 940, -881, 221, -889, -1201, 1247, +261, 124, 1420, -1253, -857, 609, -1033, 642, +1594, -793, 285, 229, -1641, 482, 703, -666, +1182, -173, -1135, 472, -395, 80, 1220, -117, +-88, -84, -767, 153, 449, 11, 337, -571, +-368, 65, 46, 872, 280, 2, -68, -917, +-34, -27, 123, 955, -9, -330, 30, -1006, +32, 954, 52, 799, 126, -1262, -169, -341, +-33, 988, 478, -38, -4, -528, -533, 130, +218, 239, 599, 124, -330, -204, -592, -620, +621, 567, 816, 816, -727, -1291, -842, -101, +942, 1706, 687, -1233, -1061, -1013, -39, 1986, +1011, -449, -305, -1432, -525, 1413, 332, 288, +241, -1320, -43, 415, -83, 709, -56, -613, +345, -181, 109, 718, -516, -195, 18, -698, +731, 541, -24, 204, -778, -729, 297, 664, +859, 465, -481, -1249, -702, 366, 685, 908, +561, -1334, -512, 286, -396, 1525, 479, -1383, +515, -622, -618, 1502, -314, -499, 924, -967, +-105, 864, -690, 741, 673, -701, 179, -937, +-760, 898, 416, 738, 554, -1479, -511, 140, +-29, 1629, 392, -974, -199, -1059, -69, 1166, +197, 232, 12, -933, 152, 296, 113, 610, +-372, -320, -68, -361, 571, -5, -73, 336, +-439, 112, 471, -455, 422, 372, -793, 222, +-241, -970, 1142, 650, -181, 791, -964, -1656, +851, 347, 493, 1973, -995, -1695, 220, -1313, +593, 2447, -560, 41, 215, -2412, 543, 1246, +-521, 1851, -178, -2078, 453, -977, -117, 2228, +-76, -98, 378, -1747, -25, 1023, -289, 1011, +22, -1455, 180, -360, 96, 1419, 18, -219, +-59, -1190, 58, 768, 169, 951, -179, -1068, +-135, -676, 182, 965, 165, 399, 239, -679, +-194, -240, -487, 613, 532, 196, 420, -788, +-832, -93, 67, 866, 1011, -242, -366, -633, +-718, 675, 568, 155, 307, -740, -568, 291, +114, 194, 556, -407, -204, 497, -147, 123, +246, -525, -415, 169, -139, -185, 980, 91, +37, 739, -1188, -847, 453, -399, 1256, 1471, +-1041, -574, -1022, -1468, 1555, 1433, 691, 785, +-1608, -1684, -26, 192, 1438, 1278, -531, -870, +-1094, -524, 953, 901, 774, -163, -1019, -469, +-79, 613, 790, -78, -412, -815, -373, 710, +458, 506, 340, -1231, -75, 459, -475, 1093, +-37, -1481, 722, -113, -276, 1704, -677, -1029, +864, -943, 488, 1516, -1030, -114, -102, -1287, +903, 891, -271, 808, -667, -1432, 877, -154, +507, 1867, -1302, -877, -53, -1896, 1436, 2033, +-498, 1213, -1146, -2618, 1045, -122, 914, 2362, +-1272, -713, -609, -1838, 1446, 1058, 287, 1627, +-1586, -1284, 265, -1559, 1860, 1736, -838, 1140, +-1775, -2189, 1502, -431, 1262, 2270, -1954, -140, +-291, -2043, 2207, 639, -631, 1685, -1929, -1388, +1431, -1058, 1262, 2059, -1807, 75, -358, -1924, +1981, 908, -246, 957, -1944, -1402, 737, -26, +1807, 1383, -1037, -287, -1450, -1235, 1436, 392, +1153, 1098, -1811, -811, -667, -810, 2051, 1223, +173, 406, -1877, -1001, 430, -253, 1561, 300, +-898, 510, -918, 85, 1062, -914, 329, 281, +-750, 997, 104, -1021, 468, -495, -156, 1391, +-297, -301, 64, -1111, 376, 788, 58, 596, +-217, -785, -36, -223, 14, 575, 97, -176, +114, -327, -89, 665, 94, 28, 189, -943, +-364, 187, -96, 921, 563, -303, -73, -872, +-418, 635, 320, 749, 236, -1279, -305, -135, +-56, 1668, 137, -962, 151, -1257, 149, 1900, +-312, 275, -155, -2203, 505, 640, 33, 2019, +-507, -1292, 251, -1601, 427, 1922, -423, 822, +-108, -2503, 595, 450, -219, 2538, -567, -1799, +453, -1703, 545, 2416, -312, 516, -556, -2024, +236, 64, 673, 1416, -327, 154, -635, -1453, +723, -285, 435, 1951, -941, -323, 0, -2072, +929, 1289, -353, 1517, -706, -1890, 780, -657, +463, 1942, -1040, -103, 60, -1691, 1051, 588, +-592, 1373, -656, -852, 1004, -1027, 237, 1030, +-932, 582, 80, -1138, 686, -146, -93, 1099, +-542, -76, 218, -912, 652, 69, -344, 692, +-640, 51, 482, -601, 540, -206, -501, 721, +-293, 281, 688, -911, 242, -74, -994, 877, +-170, -444, 1440, -606, -19, 1002, -1627, 323, +588, -1355, 1639, -25, -1273, 1416, -1307, -538, +1811, -1122, 789, 1294, -1788, 475, -159, -1626, +1497, 317, -212, 1216, -1120, -854, 322, -520, +1031, 940, -235, 123, -886, -623, 285, -96, +690, 55, -356, 212, -376, 535, 514, -453, +198, -872, -497, 955, -45, 759, 555, -1525, +-172, -329, -490, 1704, 594, -27, 323, -1408, +-750, 23, 23, 1122, 628, 189, -348, -1259, +-199, -246, 528, 1636, 36, 79, -518, -1764, +-109, 71, 707, 1503, 101, -24, -847, -1106, +251, -176, 871, 863, -615, 343, -522, -708, +747, -382, 145, 399, -424, 474, -52, -10, +347, -750, 242, -154, -574, 1102, -207, -31, +929, -1358, -125, 483, -758, 1485, 526, -1081, +246, -1418, -360, 1693, 192, 1003, -146, -2079, +-242, -218, 808, 2018, 58, -707, -1019, -1428, +234, 1280, 806, 474, -304, -1152, -465, 380, +358, 551, 296, -754, -308, -19, -153, 673, +218, -218, -53, -436, 42, 382, 328, 224, +-309, -645, -178, 75, 343, 782, -259, -549, +63, -499, 587, 1056, -564, -95, -250, -1316, +842, 669, -317, 1100, -631, -1034, 599, -406, +437, 1109, -445, -417, -236, -853, 306, 916, +109, 315, -229, -902, 44, 282, 299, 507, +-107, -552, -185, 84, 147, 176, 68, -552, +-287, 692, 117, 552, 627, -1351, -358, -70, +-845, 1331, 789, -499, 724, -838, -1259, 727, +-170, 421, 1574, -528, -557, -435, -1382, 171, +1238, 836, 731, -83, -1587, -1398, 132, 429, +1621, 1867, -725, -959, -1446, -2136, 1137, 1317, +1264, 2207, -1522, -1394, -873, -2077, 1917, 1319, +413, 1733, -1970, -1082, 20, -1326, 1858, 607, +-271, 1166, -1663, -46, 594, -1340, 1616, -250, +-1028, 1511, -1370, 181, 1568, -1336, 793, -27, +-1811, 930, 25, 87, 1688, -648, -711, -279, +-1142, 563, 1014, 372, 417, -432, -882, -283, +210, 68, 571, 223, -539, 355, -237, -380, +564, -508, -109, 607, -348, 412, 525, -537, +-60, -495, -830, 143, 625, 1015, 922, 132, +-1102, -1612, -914, 20, 1506, 1771, 1052, -349, +-1756, -1471, -1314, 432, 2028, 1107, 1618, -189, +-2311, -874, -1599, -173, 2597, 685, 1315, 557, +-2641, -502, -877, -1020, 2489, 537, 494, 1456, +-2000, -861, -250, -1609, 1406, 1171, 186, 1473, +-869, -1174, -357, -1313, 574, 1023, 784, 1379, +-578, -1095, -1276, -1599, 846, 1534, 1577, 1694, +-1312, -2134, -1523, -1460, 1810, 2582, 1095, 926, +-2086, -2661, -432, -405, 1909, 2343, -110, 295, +-1329, -1813, 303, -713, 764, 1332, -204, 1317, +-411, -1007, 52, -1676, 371, 727, 105, 1675, +-428, -378, -61, -1521, 411, -17, -32, 1324, +-317, 292, 62, -998, 494, -263, -18, 430, +-969, -40, 211, 305, 1392, 374, -750, -962, +-1403, -541, 1375, 1408, 1023, 550, -1769, -1748, +-405, -455, 1712, 2100, -367, 152, -1203, -2371, +1048, 483, 372, 2321, -1314, -1286, 402, -1933, +1055, 1821, -705, 1461, -655, -1924, 476, -1104, +634, 1861, -22, 795, -1060, -1889, -345, -373, +1637, 1870, 630, -62, -1990, -1580, -855, 226, +2159, 1131, 1124, 58, -2314, -917, -1395, -676, +2515, 1189, 1634, 1330, -2605, -1821, -1702, -1641, +2319, 2381, 1779, 1483, -1847, -2419, -2074, -1117, +1417, 1872, 2486, 1006, -1283, -1154, -2730, -1274, +1283, 739, 2510, 1556, -1090, -627, -2169, -1559, +582, 448, 1869, 1365, 40, -19, -1804, -1208, +-493, -490, 1879, 1231, 639, 806, -1954, -1486, +-571, -883, 2129, 1968, 102, 806, -2179, -2531, +811, -636, 1882, 2941, -1667, 378, -1176, -3038, +2061, -125, 484, 2862, -1901, 70, -203, -2524, +1630, -284, 281, 2055, -1464, 572, -396, -1453, +1441, -671, 314, 804, -1596, 528, -40, -224, +1667, -275, -358, -282, -1688, -20, 699, 726, +1554, 413, -1008, -1058, -1424, -873, 1109, 1171, +1057, 1260, -1156, -1050, -488, -1423, 842, 856, +13, 1433, -321, -728, -12, -1475, 23, 689, +191, 1628, -211, -719, -175, -1771, 812, 848, +-96, 1782, -1291, -1167, 296, -1633, 1717, 1609, +-146, 1401, -2205, -1931, -82, -1211, 2795, 1937, +328, 1233, -3237, -1776, -611, -1544, 3457, 1735, +1173, 2041, -3595, -1835, -1976, -2555, 3675, 1828, +2544, 3009, -3698, -1540, -2754, -3308, 3390, 1080, +2545, 3358, -2863, -656, -2213, -3168, 2060, 329, +1525, 2808, -1292, -35, -558, -2278, 380, -328, +-689, 1515, 695, 781, 1723, -618, -2005, -1207, +-2284, -131, 3208, 1404, 2229, 572, -3842, -1297, +-1796, -856, 3800, 1012, 1510, 1202, -3230, -774, +-1491, -1617, 2564, 726, 1798, 1932, -1933, -902, +-2129, -2001, 1581, 1180, 2370, 1765, -1314, -1275, +-2374, -1239, 1061, 794, 2157, 603, -651, 438, +-1976, -240, 42, -1997, 1925, 337, 470, 3066, +-1924, -602, -908, -3154, 1608, 528, 1038, 2550, +-1152, -20, -1232, -1875, 662, -516, 1277, 1429, +-614, 653, -1121, -991, 794, -338, 436, 343, +-1077, -236, 542, 292, 1099, 921, -1415, -559, +-860, -1711, 1757, 503, 715, 2497, -1563, -434, +-765, -3051, 1121, 418, 1049, 3255, -531, -103, +-1314, -3288, 89, -624, 1611, 3411, 315, 1336, +-1921, -3698, -421, -1549, 2159, 3995, 321, 1344, +-2214, -4134, -66, -1209, 2086, 4152, -243, 1371, +-1999, -4201, 390, -1523, 1907, 4342, -434, 1376, +-2016, -4326, 253, -1010, 1845, 3806, 19, 761, +-1578, -2640, -423, -806, 950, 1210, 622, 1053, +-209, -69, -720, -1193, -724, -602, 529, 1008, +1698, 1124, -226, -529, -2487, -1766, -244, 48, +2956, 2369, 786, 292, -3066, -2562, -1201, -608, +2897, 2356, 1584, 1101, -2461, -2073, -1739, -1653, +1786, 1948, 1907, 1963, -929, -1796, -2038, -1941, +122, 1455, 2217, 1887, 343, -1072, -2234, -1976, +-507, 1000, 1911, 2057, 534, -1201, -1558, -1851, +-816, 1351, 1535, 1548, 793, -1082, -2123, -1556, +-439, 522, 2833, 2057, -390, 90, -3364, -2648, +913, -674, 3300, 2881, -972, 1407, -3036, -2626, +580, -2213, 2514, 2131, -160, 2807, -1984, -1532, +-85, -2832, 1214, 854, 175, 2355, -385, -14, +-127, -1609, -341, -811, -87, 854, 927, 1418, +416, -111, -1332, -1646, -766, -544, 1760, 1642, +952, 1059, -2166, -1534, -995, -1299, 2512, 1421, +871, 1266, -2781, -1141, -694, -973, 2828, 672, +441, 573, -2901, -53, -319, -191, 2873, -523, +111, 93, -2908, 1057, -38, -402, 2509, -1480, +173, 1184, -2066, 1763, -774, -2209, 1461, -1694, +1344, 3158, -992, 1385, -1785, -3490, 305, -1101, +1834, 3111, 399, 1174, -1758, -2242, -1010, -1413, +1414, 1381, 1181, 1534, -893, -620, -1026, -1264, +207, -79, 538, 731, 441, 822, 111, -14, +-1000, -1328, -890, -759, 1165, 1469, 1720, 1696, +-1137, -1224, -2633, -2657, 953, 847, 3348, 3545, +-1019, -392, -3690, -4049, 1040, -48, 3310, 4061, +-1078, 526, -2565, -3551, 748, -915, 1435, 2856, +-264, 1166, -620, -2028, -363, -1125, -65, 1101, +641, 984, 188, -110, -783, -789, 60, -440, +404, 687, -645, 321, -17, -578, 1113, 440, +-544, 493, -1324, -1289, 657, -332, 1144, 1893, +-453, 346, -1009, -2001, -71, -602, 695, 1705, +589, 1123, -402, -987, -1197, -1485, -24, 157, +1478, 1421, 274, 583, -1658, -750, -416, -866, +1286, -182, 354, 656, -871, 1286, -321, 26, +43, -2328, 130, -738, 679, 3139, -276, 1330, +-1259, -3278, 358, -1625, 1159, 2811, -730, 1723, +-795, -1912, 915, -1416, 5, 966, -1205, 830, +614, -2, 1267, -133, -1270, -722, -1352, -199, +1334, 1129, 1045, 131, -1120, -965, -731, 371, +473, 515, 106, -1018, 34, 87, 422, 1769, +-563, -595, -1193, -2301, 778, 1013, 1704, 2594, +-1099, -1119, -2104, -2576, 1085, 1149, 1858, 2463, +-1006, -1206, -1502, -2117, 513, 1490, 774, 1642, +-323, -1637, -167, -1010, 119, 1592, -748, 542, +-390, -1295, 1548, -207, 492, 1129, -2581, 80, +-787, -1048, 3141, 78, 827, 1084, -3595, -163, +-1092, -1028, 3495, 381, 1076, 1029, -3429, -646, +-1036, -831, 2857, 1032, 470, 421, -2268, -1221, +3, 289, 1416, 1274, -540, -817, -1027, -1132, +450, 914, 769, 1147, -325, -400, -1033, -1310, +-82, -106, 1008, 1591, 302, 350, -1257, -1453, +-773, -254, 1117, 945, 887, 318, -1171, -105, +-1101, -458, 938, -557, 700, 600, -1104, 927, +-232, -343, 1037, -759, -791, -82, -1117, 306, +1434, 620, 765, 460, -2198, -1003, -561, -1221, +2294, 1378, 319, 2080, -2418, -1479, -642, -2911, +1959, 1390, 932, 3757, -1471, -930, -1623, -4169, +507, 277, 1851, 4197, 309, 648, -1931, -3709, +-1433, -1442, 1137, 2894, 2118, 2078, -280, -1525, +-2808, -2318, -802, 25, 2702, 2470, 1104, 1268, +-2473, -2431, -1077, -1617, 1486, 2274, 229, 1165, +-658, -1627, 389, -164, -247, 809, -1253, -749, +315, -23, 1519, 1553, -234, -223, -1824, -1971, +-476, 58, 1561, 2125, 723, 450, -1259, -1856, +-1064, -784, 374, 1377, 712, 998, 470, -555, +-560, -941, -1619, -329, 93, 824, 2086, 1324, +217, -505, -2507, -2003, -936, 320, 2265, 2290, +1247, -63, -1990, -1956, -1741, -224, 1204, 1413, +1691, 877, -678, -734, -1898, -1565, 52, 303, +1629, 2035, -135, 15, -1422, -1712, 111, -64, +590, 892, -538, 26, -105, 192, 582, 251, +-285, -871, -1166, -419, -109, 959, 1412, 604, +425, -189, -1868, -665, -1152, -935, 1642, 713, +1500, 2162, -1464, -346, -2089, -2958, 807, -265, +2047, 3266, -512, 1029, -1906, -2743, 21, -1330, +1121, 1605, -130, 1211, -483, 58, 76, -716, +-329, -1408, -417, 287, 375, 2023, 598, 294, +-238, -1556, -1345, -895, -388, 514, 1593, 1581, +709, 800, -1645, -1900, -1324, -1699, 789, 1850, +1401, 2070, -13, -1284, -1407, -1693, -1173, 735, +779, 993, 1739, -353, -479, -191, -2183, 438, +46, -96, 1658, -679, -167, -99, -1114, 1008, +100, 819, 256, -1024, -540, -1532, -14, 898, +665, 2043, -158, -474, -982, -1963, -270, 9, +663, 1539, 588, 510, -346, -707, -1284, -692, +-386, -189, 1519, 722, 730, 1095, -1661, -484, +-1270, -1627, 1156, 257, 1498, 1989, -896, 31, +-1882, -2097, 330, -113, 1888, 2192, -135, 195, +-2197, -2107, -246, -174, 2082, 2049, 354, 426, +-2185, -1889, -885, -875, 1717, 1850, 1230, 1543, +-1350, -1630, -1843, -1882, 468, 1271, 1936, 1825, +67, -575, -2150, -1250, -533, -34, 1761, 629, +183, 374, -1346, 19, 216, -15, 436, -507, +-926, -689, 31, 942, 1182, 1484, -261, -866, +-1604, -1900, -76, 315, 1486, 1985, 384, 674, +-1493, -1514, -905, -1559, 1114, 702, 1111, 2292, +-792, 439, -1760, -2661, 147, -1424, 2217, 2844, +201, 2154, -2601, -2550, -749, -2369, 2044, 1785, +1017, 2348, -1094, -418, -1601, -2062, -416, -1040, +1804, 1750, 1520, 2277, -1905, -1233, -2459, -2793, +1192, 616, 2552, 2748, -284, 218, -2438, -2217, +-815, -918, 1576, 1557, 1245, 1467, -705, -724, +-1319, -1656, -457, 49, 779, 1700, 1026, 374, +-299, -1524, -1265, -286, -274, 1393, 736, -66, +255, -1281, -18, 602, -108, 1429, -903, -990, +-470, -1678, 1230, 1206, 957, 2108, -1252, -986, +-1650, -2518, 710, 486, 1937, 2910, -260, 255, +-2057, -2912, -445, -890, 1585, 2557, 845, 1430, +-1028, -1836, -1327, -1646, 128, 1096, 1357, 1590, +485, -330, -1288, -1073, -1145, -261, 754, 260, +1201, 735, -210, 755, -1115, -876, -550, -1437, +659, 765, 773, 1577, -355, -382, -825, -1029, +120, 141, 232, 205, -309, -242, 308, 662, +617, 842, -821, -1162, -1303, -1518, 685, 1191, +1834, 1997, -264, -578, -2328, -1985, -474, -300, +2198, 1697, 1010, 1069, -1982, -1189, -1465, -1261, +1439, 681, 1586, 1067, -1048, -183, -1808, -769, +510, -62, 1733, 720, -153, 92, -1602, -734, +-420, 75, 979, 674, 841, -169, -236, -289, +-1330, 233, -833, -282, 1260, -278, 1636, 948, +-778, 564, -2093, -1337, -567, -1084, 1795, 1273, +2051, 1827, -1154, -587, -3390, -2444, 181, -396, +3753, 2751, 488, 1354, -3245, -2618, -1001, -1873, +1898, 2308, 1067, 1966, -607, -1940, -987, -1672, +-444, 1680, 624, 1215, 651, -1396, -239, -641, +-574, 1125, -190, 184, 263, -792, 196, -29, +-275, 498, 59, 405, 330, -250, -730, -1147, +-523, 105, 1207, 1986, 592, 90, -1643, -2512, +-765, -376, 1632, 2510, 835, 803, -1491, -1850, +-1069, -1137, 1062, 836, 1081, 1238, -684, 80, +-1066, -977, 150, -478, 869, 530, 200, 481, +-817, -135, -566, -363, 620, 93, 735, 407, +-409, -341, -1029, -592, -4, 683, 1204, 887, +230, -786, -1357, -1138, -399, 553, 1186, 1235, +230, -33, -849, -1080, -58, -461, 327, 771, +-202, 623, -174, -424, 246, -336, 365, 251, +-228, -125, -1114, -406, -28, 401, 1911, 967, +264, -171, -2680, -1705, -602, -587, 2884, 2282, +805, 1693, -2574, -2325, -1158, -2701, 1647, 1675, +1426, 3197, -470, -346, -1731, -2957, -833, -1352, +1556, 2031, 1893, 2893, -892, -570, -2651, -3754, +-332, -1147, 2663, 3685, 1615, 2638, -2041, -2751, +-2699, -3319, 840, 1288, 3054, 2923, 389, 187, +-2799, -1720, -1273, -1101, 1812, 331, 1390, 1210, +-584, 666, -999, -733, -544, -975, 321, 146, +825, 675, 190, 197, -328, -81, -519, -145, +-642, -456, 373, -337, 1367, 692, 86, 1065, +-1637, -545, -741, -1584, 1130, 29, 1212, 1458, +-210, 687, -1348, -717, -906, -1321, 942, -179, +1724, 1604, -362, 752, -2151, -1491, -153, -882, +2028, 1153, 311, 661, -1654, -831, -302, -297, +1098, 629, 351, -23, -801, -539, -551, 115, +580, 385, 618, 31, -217, -21, -568, -272, +-455, -520, 163, 369, 1172, 941, 371, -209, +-1613, -968, -974, -139, 1464, 621, 1312, 407, +-991, -275, -1106, -302, 323, 248, 268, -305, +91, -590, 835, 1101, -19, 1011, -1830, -1612, +-531, -1278, 2117, 1557, 1323, 1300, -1851, -1082, +-1852, -1234, 1109, 414, 1899, 1147, -284, 216, +-1628, -927, -292, -722, 1015, 330, 474, 1006, +-276, 522, -285, -1028, -493, -1239, -88, 753, +990, 1450, 305, -319, -1017, -1258, -402, -79, +857, 894, 172, 159, -532, -528, 59, 68, +218, 134, -112, -407, -66, 114, 38, 536, +-10, -68, 74, -375, 107, -204, -149, -3, +-355, 321, 249, 334, 604, -108, -254, -409, +-749, -338, 209, 134, 739, 633, -232, 219, +-593, -547, 527, -338, 250, 75, -890, 59, +236, 481, 959, 396, -430, -866, -662, -779, +203, 843, 247, 847, 320, -453, 140, -607, +-760, -157, -419, 37, 937, 609, 765, 709, +-840, -646, -1183, -1430, 667, 228, 1547, 1816, +-382, 279, -1641, -1798, 86, -577, 1458, 1408, +311, 609, -1114, -851, -598, -662, 719, 213, +761, 830, -156, 406, -686, -1062, -436, -984, +453, 1195, 954, 1439, -240, -1226, -978, -1771, +346, 1185, 605, 1882, -711, -1216, -172, -1803, +1440, 1307, 197, 1573, -2155, -1460, -678, -1470, +2711, 1485, 1323, 1550, -2594, -1287, -1637, -1639, +1802, 789, 1630, 1296, -617, -216, -1182, -414, +-167, -181, 380, -725, 357, 80, 650, 1497, +79, 503, -1402, -1581, -602, -1231, 1593, 992, +1024, 1461, -1125, -148, -981, -972, 468, -559, +657, 21, -14, 801, -43, 748, 108, -642, +-442, -1033, -430, 251, 764, 884, 703, 15, +-647, -730, -508, -6, 341, 826, 5, -242, +20, -1278, 802, 313, 72, 1778, -1422, 67, +-455, -1956, 1513, -897, 1075, 1484, -780, 1624, +-1204, -562, -279, -1726, 728, -469, 1131, 1033, +458, 1113, -1170, -34, -1503, -1181, 447, -850, +2053, 609, 773, 1325, -1549, 247, -1775, -1408, +275, -1076, 2321, 1037, 1393, 1622, -2064, -424, +-2525, -2006, 1313, -178, 2796, 2235, -162, 459, +-2143, -2312, -783, -589, 1321, 2076, 1380, 786, +-534, -1656, -1343, -1238, -14, 1028, 1148, 1649, +760, -243, -873, -1849, -1435, -759, 776, 1641, +2104, 1652, -578, -1175, -2289, -2235, 485, 535, +2203, 2236, -267, 23, -1722, -1773, 152, -514, +1256, 955, 60, 790, -501, -153, -132, -909, +-181, -496, 153, 759, 878, 809, 158, -510, +-1117, -971, -369, 130, 1030, 992, 609, 285, +-640, -955, -579, -856, 569, 651, 531, 1291, +-563, -155, -330, -1391, 790, -511, 197, 946, +-688, 977, -47, -294, 647, -1189, 146, -407, +-455, 1064, -88, 914, 315, -840, 142, -1292, +32, 449, -15, 1335, -219, 24, -8, -1069, +499, -585, 241, 502, -502, 851, -520, -106, +638, -761, 1009, 66, -403, 323, -1319, -489, +191, -34, 1491, 910, 210, -57, -1016, -1095, +-360, -32, 388, 803, 460, -11, 368, -371, +-150, 19, -593, -136, -209, -34, 646, 520, +892, -27, -492, -920, -1274, -181, 503, 1004, +1593, 587, -200, -681, -1445, -1125, -126, -199, +1197, 1224, 769, 1133, -500, -822, -1125, -1840, +-101, -116, 1338, 1931, 881, 988, -998, -1642, +-1163, -1507, 489, 1017, 1265, 1323, 423, -458, +-779, -759, -1026, -4, 265, -34, 1513, 142, +382, 599, -1474, -201, -443, -921, 1533, 73, +372, 825, -1380, 59, -18, -592, 1301, -373, +160, 168, -701, 610, -258, 169, 108, -782, +422, -582, 614, 579, -59, 869, -645, -209, +-140, -1059, 360, -357, 383, 725, 352, 739, +-35, -21, -545, -947, -237, -926, 404, 629, +757, 1408, 416, -6, -792, -1319, -1007, -805, +702, 612, 1483, 1079, 108, 51, -1138, -761, +-835, -510, 553, -50, 1610, 488, 421, 587, +-1542, -412, -762, -758, 1118, 357, 832, 575, +-75, -582, -283, -623, -511, 632, 32, 730, +912, -513, 278, -818, -470, 130, -76, 384, +68, -46, -39, 188, 592, 213, 583, -595, +-617, -682, -803, 267, 573, 888, 1078, 441, +-3, -835, -721, -1307, -266, 344, 675, 1778, +654, 192, -513, -2040, -496, -791, 725, 1850, +685, 1043, -428, -1383, -590, -1066, 157, 468, +850, 570, 630, 303, -663, 83, -1053, -839, +688, -805, 1639, 838, -145, 995, -1609, -732, +-296, -839, 1565, 495, 1252, 393, -820, -471, +-1656, -257, 273, 362, 1891, 305, 598, -307, +-1353, -618, -643, -83, 1029, 648, 567, 485, +-374, -451, 70, -859, 239, -147, -206, 649, +138, 541, 562, -116, 77, -647, -432, -658, +-122, 143, 588, 963, 659, 445, -52, -814, +-690, -1043, -350, 61, 830, 1166, 1102, 645, +-158, -1011, -1136, -1186, -237, 373, 1203, 1121, +843, 233, -654, -860, -633, -759, 597, 408, +494, 732, -260, -224, 38, -538, 558, 61, +66, 160, -446, -141, -46, -40, 610, 107, +656, -114, -179, -162, -732, 109, 76, -7, +978, -292, 397, 108, -467, 352, -264, -425, +235, -485, 412, 667, 454, 399, -24, -1014, +-633, -540, 120, 934, 1172, 718, 129, -487, +-1030, -1019, 54, -464, 1080, 749, 398, 1152, +-578, -76, -500, -1413, 577, -850, 997, 947, +-191, 1176, -789, -369, 255, -1105, 746, -320, +206, 671, -39, 777, -168, -388, -226, -1266, +456, -146, 724, 1286, -135, 741, -461, -899, +275, -1413, 471, -65, -72, 1380, 26, 817, +492, -755, -110, -1238, -436, -418, 656, 971, +861, 1266, -612, -553, -818, -1714, 688, -69, +1174, 1450, 79, 493, -812, -967, -378, -930, +515, 224, 828, 944, 348, 306, -369, -769, +-398, -791, 214, 260, 548, 830, 86, -24, +21, -704, 331, -38, -3, 256, -167, -263, +243, -58, 223, 345, 2, 20, 239, -393, +269, -359, 30, 229, 43, 572, -138, -281, +-145, -892, 613, 202, 979, 1107, -260, -131, +-1352, -1501, 93, -346, 1779, 1563, 628, 870, +-1333, -1348, -772, -1490, 1113, 610, 1184, 1585, +-430, 26, -997, -1348, 344, -531, 1169, 692, +9, 564, -807, -261, 126, -599, 811, -76, +314, 518, -285, 116, -424, -579, 143, -271, +901, 339, 379, 204, -609, -151, -288, -48, +452, 48, 412, -531, 160, -538, 128, 1023, +-147, 1121, -272, -1389, 238, -1614, 717, 1195, +324, 1486, -431, -879, -647, -1098, 285, 450, +1279, 406, 447, -301, -1122, 122, -765, 102, +944, -581, 1124, -90, -49, 528, -640, 76, +-401, -279, 341, -354, 874, -214, 288, 462, +-555, 436, -247, -467, 351, -629, 443, 83, +291, 619, -244, 229, -372, -723, 396, -523, +566, 578, -69, 466, -119, -375, 87, -389, +-100, -55, 311, 127, 524, 193, -270, -66, +-314, -144, 562, 50, 354, -249, -428, -350, +-148, 390, 558, 562, 453, -330, -201, -791, +-300, -83, 149, 705, 227, 246, 176, -613, +282, -251, -17, 370, -201, -7, 125, -301, +95, 65, 28, 116, 492, -168, 227, -40, +-525, 248, -131, -138, 447, -610, 283, 103, +137, 859, 18, -56, -350, -1035, -22, -174, +626, 814, 332, 271, -404, -474, -356, -458, +445, -115, 668, 463, -80, 583, -636, -415, +-116, -1013, 802, 6, 584, 1059, -423, 435, +-655, -920, 180, -868, 795, 463, 312, 859, +-423, -26, -387, -632, 254, -477, 504, 143, +214, 697, -232, 204, -367, -725, 222, -506, +696, 353, 41, 476, -673, -2, 47, -286, +675, -275, 67, -215, -172, 125, 139, 627, +-155, 195, -242, -903, 533, -712, 711, 739, +-281, 1062, -907, -446, -34, -1283, 1034, 22, +618, 1101, -531, 229, -724, -692, 121, -546, +694, -17, 369, 753, -318, 554, -327, -856, +329, -726, 292, 490, -290, 156, -30, -46, +476, 695, 91, -103, -355, -1390, 16, -516, +378, 1272, 109, 1331, -247, -553, -16, -1753, +321, -431, 119, 1289, 1, 935, -147, -459, +-240, -900, 446, -255, 610, 431, -613, 358, +-641, -118, 1024, -95, 681, 19, -1109, -340, +-460, -172, 1045, 461, 400, 235, -576, -291, +-99, -290, 317, -190, 33, 200, -193, 576, +39, -84, 502, -789, 140, -223, -463, 592, +-236, 460, 324, -198, 425, -497, 76, -294, +-333, 48, -192, 504, 369, 597, 244, -503, +-232, -1206, -115, 361, 278, 1445, 165, -373, +-169, -1420, -88, 374, 168, 1085, 126, -301, +-58, -558, 102, 85, 70, -187, -219, -87, +76, 707, 395, 272, -60, -750, -278, -423, +55, 256, 169, 54, 234, 182, 122, 624, +-454, -195, -237, -1166, 637, -268, 442, 1063, +-407, 616, -409, -563, 27, -608, 239, 15, +572, 290, 354, 309, -802, -90, -1025, -665, +673, -39, 1628, 1020, -11, 261, -1600, -1113, +-660, -692, 1148, 565, 1161, 926, -415, 274, +-1099, -698, -87, -812, 869, 97, 525, 667, +-570, 309, -850, -350, 489, -330, 1346, 418, +-367, 139, -1572, -957, 186, -202, 1549, 1378, +144, 535, -1091, -1327, -259, -917, 625, 874, +288, 963, -261, -456, -128, -670, 153, 163, +177, 186, -19, 37, -324, 155, -18, -257, +525, -224, 143, 380, -607, -26, -95, -374, +728, 382, 99, 252, -813, -662, -206, -195, +1030, 637, 437, 209, -967, -321, -539, -236, +703, -151, 463, 161, -341, 455, -91, -79, +137, -453, -82, 67, -6, 221, 19, -183, +-199, -69, 266, 250, 663, 85, -345, -169, +-981, -166, 118, -49, 912, 121, 369, 176, +-352, 8, -675, -122, -251, -134, 632, -39, +651, 208, -237, 95, -661, -246, -191, 8, +449, 176, 452, -222, -99, 3, -307, 486, +-192, -134, -204, -772, 273, -57, 935, 957, +-9, 572, -1408, -859, -546, -1003, 1343, 443, +1137, 894, -782, 8, -1391, -248, 100, -129, +1211, -434, 373, -163, -733, 614, -533, 585, +194, -253, 470, -790, 206, -204, -180, 686, +-423, 359, -286, -445, 435, -210, 703, 240, +-184, -18, -870, -113, -88, 193, 551, 30, +150, -344, 79, 18, 78, 522, -617, -14, +-572, -703, 834, -7, 964, 828, -712, -13, +-1078, -834, 453, 66, 881, 659, -357, -137, +-517, -331, 377, 210, 183, 21, -520, -230, +-17, 180, 496, 154, -68, -323, -217, -12, +67, 517, -298, -42, -227, -698, 801, -47, +461, 689, -1063, 124, -812, -453, 881, 1, +1037, 198, -496, -257, -1031, -105, 47, 397, +665, 153, 130, -284, -267, -155, -54, 84, +13, 64, -239, -16, -193, -16, 407, 116, +527, 156, -361, -189, -794, -403, -36, 89, +624, 531, 400, 127, -212, -338, -552, -202, +-323, -52, 267, 20, 552, 309, 49, 302, +-538, -121, -343, -420, 338, -363, 293, 206, +-243, 706, -202, 181, 99, -569, 92, -449, +-107, 124, -107, 529, 66, 200, 15, -479, +-257, -116, 22, 378, 443, -244, -103, -235, +-605, 560, -81, 149, 434, -596, 237, -232, +-188, 372, -376, 440, -122, -43, 226, -531, +39, -189, 3, 375, 146, 220, -273, -106, +-453, -71, 241, -25, 409, -103, -198, 37, +-196, 246, 52, -51, -187, -340, -253, 110, +406, 430, 404, 0, -594, -403, -574, -351, +514, 169, 525, 731, -498, 185, -512, -778, +241, -315, 434, 458, -113, 50, -500, -78, +-17, 404, 399, -52, -128, -555, -450, 83, +141, 258, 403, -304, -60, 161, -444, 724, +-387, -237, 138, -889, 677, 6, 170, 525, +-742, 150, -483, 150, 227, 47, 280, -590, +276, -298, 102, 648, -688, 280, -645, -576, +552, -3, 802, 710, -289, -77, -830, -892, +-136, -190, 494, 788, 207, 541, -194, -217, +-183, -446, -191, -411, -191, -113, 234, 661, +372, 709, -166, -441, -550, -787, -93, 261, +403, 411, 46, -444, -392, -72, 11, 814, +299, 230, -246, -750, -366, -599, 135, 185, +294, 677, -71, 417, -399, -242, -170, -483, +326, -227, 234, 160, -276, 352, -336, 155, +-218, -123, 21, -198, 625, -70, 363, 224, +-819, 166, -889, -259, 363, -219, 809, 123, +96, 298, -374, 382, -389, -168, -396, -840, +76, -171, 777, 833, 170, 576, -942, -277, +-379, -747, 732, -283, 195, 738, -550, 540, +-227, -588, 98, -455, 193, 474, 231, 315, +-242, -323, -604, -113, -66, 254, 461, -76, +298, -237, -217, 253, -492, 352, -210, -219, +170, -413, 277, 97, 115, 404, -224, 17, +-371, -224, -166, 0, 84, 12, 314, 103, +279, 300, -367, -325, -722, -599, -10, 578, +624, 867, 256, -479, -318, -819, -426, 129, +-305, 448, 116, 212, 601, 183, 216, -160, +-771, -610, -634, -125, 499, 679, 637, 397, +-275, -374, -547, -314, -6, 154, 92, 86, +-75, -184, 65, 110, 210, 472, -68, -4, +-496, -488, -418, -109, 352, 66, 735, 3, +-139, 674, -825, 537, -270, -996, 345, -1012, +234, 658, 65, 1054, -72, 168, -381, -474, +-432, -752, 186, -177, 741, 969, 70, 626, +-1072, -905, -565, -763, 960, 927, 751, 930, +-717, -830, -796, -949, 163, 661, 293, 796, +26, -415, 207, -402, -66, 403, -647, 216, +-258, -376, 472, -177, 294, 287, -165, 147, +-260, -5, -347, 229, -52, -107, 449, -612, +185, 154, -450, 830, -409, -163, 36, -709, +366, 360, 277, 647, -374, -395, -585, -573, +45, 243, 433, 503, 103, 150, -249, -171, +-272, -326, -67, -105, 35, 327, -10, 304, +132, -73, 40, -244, -412, -71, -240, 214, +332, 155, 218, -116, -260, -1, -306, 88, +-100, -158, 118, 58, 179, 416, 19, -65, +-194, -516, -392, 21, -119, 619, 416, 218, +178, -534, -410, -325, -216, 408, 112, 361, +-46, -37, -35, -87, 72, -241, -178, -264, +-202, 361, 200, 689, 146, -60, -363, -743, +-292, -189, 244, 538, 171, 216, -269, -102, +-162, 158, 166, -69, 50, -350, -284, 165, +-306, 293, 49, -206, 412, 7, 184, 447, +-472, 2, -520, -439, 35, -144, 301, 172, +262, 317, 91, 395, -499, -176, -738, -752, +222, 68, 952, 1017, 5, 82, -1053, -1048, +-374, -126, 673, 1044, 342, 321, -332, -689, +-243, -281, -206, 329, -288, 119, 250, -70, +633, 231, -111, 266, -890, -301, -412, -455, +540, 271, 527, 493, -211, -83, -426, -56, +-162, 105, -171, -434, -25, -151, 529, 865, +270, 417, -791, -794, -769, -571, 532, 470, +881, 653, -328, 35, -947, -361, -58, -154, +556, 125, 72, 129, -274, 52, -136, -4, +-144, 15, -142, 151, 137, 130, 231, -110, +-117, -261, -479, -95, -217, 343, 346, 476, +268, -8, -281, -379, -319, -238, -79, -33, +-20, 279, 148, 583, 93, 76, -288, -593, +-200, -255, 139, 306, -70, 358, -285, 162, +57, -326, 269, -288, -51, 546, -408, 326, +-275, -617, 124, -189, 226, 501, 44, 184, +-172, 33, -278, -21, -221, -410, 0, -124, +269, 563, 251, 469, -392, -221, -673, -669, +223, -175, 622, 812, -330, 635, -568, -509, +249, -705, 187, 33, -341, 514, -99, 557, +82, 75, -112, -651, 53, -492, 24, 469, +-403, 675, -208, -111, 363, -407, 206, 165, +-348, 242, -412, -398, 28, -148, 320, 767, +-30, 278, -439, -834, -65, -210, 385, 846, +-142, 160, -608, -610, 83, 52, 514, 410, +-219, -118, -516, -67, 150, 257, 232, -105, +-357, -227, -230, 311, 325, 305, 93, -265, +-513, -316, -215, 169, 442, 442, 93, 163, +-530, -267, -230, -261, 285, 28, 138, 198, +-181, 270, -252, 147, -130, -193, 73, -206, +74, 128, -73, 125, -143, -103, -128, 105, +-35, 355, -7, -30, -67, -363, -6, -3, +-12, 259, -254, 45, -108, 6, 220, 98, +-46, -37, -280, 10, 12, 189, -9, -129, +-248, -362, 60, 291, 265, 663, -216, -87, +-479, -540, 25, -131, 421, 147, -45, 337, +-551, 447, -78, -177, 429, -631, -100, -6, +-466, 566, 92, 248, 147, -237, -317, -194, +-6, 115, 302, 136, -256, 49, -427, 78, +99, -104, 160, -168, -58, 227, 21, 367, +-118, -2, -393, -377, -87, -358, 339, 338, +144, 814, -256, -36, -304, -853, -99, -193, +83, 665, 101, 393, 26, -229, -134, -284, +-314, -16, -122, 166, 299, 206, 97, 72, +-404, -169, -196, -104, 235, 218, 21, 149, +-229, -187, -22, -20, 10, 296, -239, -42, +-66, -290, 323, 256, 55, 383, -537, -341, +-383, -361, 386, 426, 480, 414, -293, -288, +-598, -298, 32, 265, 330, 276, -114, -263, +-242, -228, 115, 421, 96, 322, -264, -404, +-238, -204, 75, 395, 168, 32, -32, -275, +-204, 251, -141, 238, 49, -298, 46, 15, +-122, 373, -142, -272, -16, -441, 73, 522, +77, 706, -149, -401, -354, -771, -78, 179, +331, 641, 201, 101, -271, -179, -447, -124, +-104, -231, 382, 118, 228, 591, -381, 24, +-357, -647, 171, -51, 185, 620, -138, 99, +-176, -431, -48, 8, 35, 340, 35, -31, +-73, -192, -161, 134, -89, 183, 36, -143, +97, -179, -18, 226, -167, 376, -172, -138, +-93, -508, 132, 9, 271, 615, -183, 222, +-514, -482, 92, -210, 426, 360, -251, 67, +-376, -232, 280, 211, 176, 304, -379, -247, +-146, -304, 189, 152, -87, 273, -103, 69, +220, -91, -49, -95, -461, 56, -29, 90, +404, -54, -68, -20, -387, 92, 104, 56, +287, 109, -277, 45, -463, -319, 183, -161, +504, 470, -88, 305, -560, -366, -157, -217, +364, 303, 177, 110, -303, -300, -243, -38, +208, 408, 102, 175, -255, -337, -22, -256, +138, 176, -241, 279, -182, 75, 339, -131, +200, -137, -390, 46, -426, 128, 102, 49, +467, 11, 104, -53, -422, -82, -294, 137, +117, 167, 156, -209, 31, -166, -37, 336, +-148, 185, -110, -271, 9, -49, -1, 81, +-9, -187, 70, 197, 34, 571, -226, -224, +-252, -789, 190, 37, 321, 782, -220, 264, +-328, -523, 173, -351, 97, 299, -281, 290, +45, -131, 284, -118, -193, 44, -306, 57, +162, 122, 115, -21, -208, -260, 62, 19, +177, 350, -307, 79, -252, -226, 343, -154, +193, 45, -355, 203, -158, 114, 186, -85, +-15, -7, -128, -30, 95, -269, 72, 74, +-215, 579, -179, 97, 126, -595, 201, -311, +-9, 375, -233, 471, -222, -40, 109, -417, +281, -134, -73, 244, -260, 174, 39, -2, +41, -97, -171, -121, 102, 59, 246, 132, +-208, -27, -333, -15, 119, 36, 200, -78, +-42, -10, 12, 147, -41, 33, -329, -150, +-101, -121, 460, 144, 283, 318, -422, -59, +-465, -416, 130, -26, 374, 291, 52, 43, +-145, 77, -91, 131, -141, -356, -134, -320, +140, 333, 324, 350, -9, 0, -407, -75, +-208, -279, 236, -281, 200, 291, -54, 473, +-37, -21, -149, -351, -270, -230, 176, 109, +454, 293, -117, 86, -549, -127, -94, -121, +394, -70, 266, 122, -162, 248, -411, -137, +-145, -350, 348, 220, 309, 443, -245, -287, +-369, -464, 112, 331, 258, 405, -81, -286, +-151, -266, 14, 165, 27, 121, 59, 39, +27, 11, -227, -215, -98, -67, 305, 325, +93, 79, -304, -359, -101, -39, 150, 409, +48, 29, 43, -454, -32, -68, -295, 435, +-11, 150, 466, -282, 51, -209, -582, 101, +-139, 271, 512, 1, 127, -332, -338, 26, +-54, 407, 93, -62, -131, -376, 47, 49, +260, 225, -132, -7, -291, -42, 137, 63, +188, 6, -200, -210, -98, -153, 255, 391, +14, 382, -285, -481, -5, -492, 201, 442, +0, 423, -83, -295, -34, -231, -88, 143, +88, 56, 214, -42, -207, 43, -312, 30, +292, -55, 361, -97, -318, 41, -391, 191, +220, -49, 305, -229, -76, 122, -154, 230, +-20, -211, -78, -222, -26, 212, 246, 246, +124, -56, -275, -250, -211, -160, 156, 184, +169, 300, -24, -64, -41, -318, -45, -34, +-84, 276, -2, 74, 118, -224, 65, -53, +-120, 174, -105, 11, 116, -129, 131, 8, +-163, 162, -198, 40, 205, -262, 257, -128, +-202, 321, -298, 149, 132, -222, 286, 2, +-34, 56, -283, -234, -125, 9, 284, 346, +292, 115, -275, -185, -420, -272, 185, -138, +440, 262, -84, 405, -336, -47, 36, -454, +155, -203, -74, 310, -4, 310, 133, -104, +-77, -253, -114, -47, 121, 138, 12, 82, +-158, -85, 41, -17, 177, 127, 21, -52, +-110, -182, -127, 38, -64, 154, 131, 92, +253, -33, 17, -262, -316, -97, -185, 387, +208, 146, 191, -399, 2, -92, -17, 295, +-158, -3, -147, -135, 188, 62, 185, -14, +-129, -75, -83, 86, 82, 81, -6, -74, +-49, -127, -11, 15, 37, 222, 66, 53, +-25, -284, -73, -62, 40, 284, 61, 13, +-81, -248, -74, -1, 158, 214, 178, 112, +-209, -160, -342, -254, 249, 55, 491, 241, +-201, 50, -528, 4, 83, -35, 461, -281, +54, -125, -245, 284, -106, 325, -13, 62, +77, -402, 215, -488, 17, 302, -277, 677, +-16, -112, 268, -534, -51, -61, -233, 217, +127, 164, 268, 87, -106, -161, -270, -327, +43, 34, 254, 506, 51, 182, -190, -585, +-101, -353, 117, 501, 167, 380, 12, -253, +-189, -237, -139, -24, 155, 36, 252, 196, +-32, 114, -231, -214, -32, -167, 149, 148, +61, 151, -41, -93, -32, -126, 25, 75, +87, 139, 5, -42, -150, -182, -60, -36, +183, 209, 216, 152, -56, -166, -345, -243, +-93, 34, 423, 259, 257, 144, -342, -192, +-330, -278, 186, 70, 413, 278, 79, 45, +-392, -157, -255, -101, 323, -35, 311, 74, +-155, 213, -171, 31, 96, -316, 37, -190, +-85, 289, 64, 358, 134, -139, -41, -495, +-69, -103, 107, 564, 6, 374, -188, -543, +55, -611, 301, 357, 64, 705, -248, -19, +-176, -581, 165, -365, 289, 228, -21, 568, +-274, 183, -23, -481, 275, -433, 122, 172, +-152, 375, -157, 97, 19, -122, 138, -157, +186, -109, 107, 35, -223, 161, -318, 115, +128, -54, 392, -225, 79, -131, -97, 293, +-53, 348, -275, -325, -157, -598, 544, 222, +558, 779, -452, 36, -768, -777, 254, -297, +774, 551, -36, 323, -492, -264, 55, -81, +209, 91, -133, -243, 93, -71, 288, 410, +-203, 82, -321, -373, 241, -50, 377, 217, +-75, -13, -268, -86, -90, 4, 156, -37, +300, 112, 68, 164, -325, -318, -192, -316, +349, 506, 308, 460, -288, -580, -287, -561, +318, 465, 344, 563, -252, -231, -313, -473, +207, -8, 309, 326, -37, 142, -141, -218, +3, -227, 32, 121, 51, 286, 120, -23, +27, -322, -96, -132, -21, 234, 105, 270, +93, -25, -2, -343, -44, -241, -26, 297, +53, 376, 143, -202, 89, -321, -134, 120, +-152, 103, 172, -149, 262, 88, -93, 262, +-221, -152, 150, -383, 278, 77, -160, 359, +-287, -19, 266, -201, 424, 51, -213, -22, +-404, -159, 190, 171, 354, 222, -30, -233, +-140, -229, 10, 201, 57, 217, 61, -125, +47, -261, -22, -36, 44, 269, 118, 247, +-51, -188, -157, -444, 133, -18, 315, 485, +-59, 176, -292, -370, 60, -167, 275, 164, +19, -20, -105, -50, 91, 184, 103, 37, +-126, -209, -100, -83, 251, 70, 257, 85, +-223, 61, -251, -93, 289, -111, 299, 133, +-242, 64, -235, -227, 295, -27, 318, 264, +-167, -9, -254, -236, 87, 11, 255, 127, +124, -8, -104, -60, -177, -48, 106, 57, +290, 103, -56, -138, -222, -124, 152, 217, +208, 42, -122, -284, -11, 89, 230, 276, +-41, -246, -231, -247, 119, 305, 315, 185, +20, -281, -168, -123, -22, 205, 84, 26, +84, -213, 66, 4, 4, 252, 54, 43, +111, -229, -119, -150, -188, 21, 269, 165, +379, 224, -205, -101, -331, -342, 242, 17, +336, 231, -152, -34, -240, -32, 133, 67, +312, -143, 138, -74, -177, 211, -294, 13, +32, -254, 432, -7, 341, 226, -212, 9, +-489, -193, 11, 32, 577, 158, 257, -183, +-358, -204, -218, 291, 206, 230, 205, -289, +53, -172, -27, 154, -116, -27, -20, -31, +262, 245, 179, -10, -220, -439, -140, -87, +307, 502, 163, 213, -250, -475, -7, -313, +303, 315, 62, 257, -117, -146, -58, -135, +-16, -7, 194, 20, 284, 87, -96, -23, +-292, -178, 75, 23, 306, 248, 60, 45, +-144, -275, 10, -223, 173, 143, 80, 347, +-32, 47, -96, -356, -67, -248, 243, 202, +365, 323, -111, 0, -388, -286, 14, -207, +285, 100, 177, 274, 105, 122, -19, -207, +-230, -296, -131, 18, 246, 272, 317, 102, +30, -116, -117, -89, -81, -99, -57, -71, +119, 216, 262, 173, 5, -271, -120, -128, +106, 320, 11, -63, -139, -448, 188, 200, +245, 549, -161, -215, -94, -555, 276, 95, +39, 405, -265, -24, 110, -244, 368, -2, +-63, 113, -248, 2, 174, -44, 198, -60, +-157, -71, -36, 97, 211, 162, 84, -87, +2, -156, -15, 25, -171, -24, 35, -69, +463, 227, 163, 218, -491, -357, -244, -445, +539, 323, 391, 584, -380, -233, -276, -582, +352, 130, 213, 372, -214, -117, 4, -67, +227, 193, -14, -238, -108, -352, 64, 375, +139, 426, 107, -401, -2, -399, -146, 347, +-49, 251, 249, -295, 278, -111, -107, 182, +-348, -32, 19, -59, 452, 144, 183, -34, +-295, -252, -142, -4, 220, 275, 120, 81, +-88, -234, 32, -135, 177, 135, 65, 97, +-119, -56, -142, -35, 65, -61, 361, -96, +254, 134, -317, 204, -414, -170, 256, -267, +511, 138, -15, 198, -273, -142, -49, -97, +66, 150, 161, 17, 242, -146, -94, -8, +-329, 49, 100, -44, 466, 9, 56, 115, +-421, 13, -89, -153, 465, -94, 192, 75, +-418, 64, -129, -5, 542, 64, 225, 31, +-533, -207, -279, -206, 511, 210, 445, 340, +-189, -132, -339, -336, -76, 45, 168, 151, +321, -59, 158, 35, -230, 81, -192, -97, +125, -68, 120, -61, 86, -79, 156, 288, +-104, 245, -243, -445, 193, -340, 333, 388, +-164, 247, -258, -211, 198, -51, 263, 23, +-80, -139, -105, 72, 74, 213, 9, -132, +-29, -226, 124, 149, 126, 209, -19, -136, +-41, -192, -61, 57, -66, 89, 166, -11, +300, 53, -9, 18, -305, -185, -127, -74, +248, 197, 284, 77, -53, -129, -230, -37, +11, 30, 245, 24, 68, 48, -238, -135, +-85, -158, 354, 287, 233, 278, -315, -338, +-276, -353, 259, 207, 306, 292, -73, -27, +-199, -132, 13, -64, 206, -35, 75, 25, +-184, 112, -88, 1, 248, -140, 203, 62, +-161, 135, -217, -203, 89, -114, 238, 304, +58, 25, -75, -368, -63, 44, -43, 354, +111, -54, 217, -299, -34, -39, -256, 146, +31, 74, 308, 30, 51, 29, -224, -170, +-57, -252, 171, 168, 95, 430, -27, -45, +-40, -450, -45, -121, 65, 269, 178, 194, +-32, -40, -224, -168, 83, -116, 313, 73, +-54, 99, -293, -29, 68, 1, 297, 25, +-21, -94, -175, -8, 47, 107, 97, -124, +-19, -122, 9, 286, 57, 171, -19, -349, +-43, -196, 6, 280, 82, 114, 101, -205, +-38, 30, -144, 195, -13, -140, 188, -196, +127, 169, -117, 97, -162, -174, 55, 69, +182, 187, 44, -184, -80, -193, -68, 169, +9, 131, 115, -110, 88, -49, -87, 81, +-126, -17, 97, -94, 192, 60, -47, 101, +-210, -151, 37, -122, 249, 246, 32, 185, +-199, -255, -87, -303, 128, 102, 204, 366, +21, 152, -256, -325, -127, -367, 281, 186, +218, 417, -214, -52, -214, -314, 147, 16, +223, 123, -38, -102, -153, 8, -31, 205, +93, -41, 84, -243, 22, -13, -47, 184, +-71, 73, 2, -82, 62, -97, 53, -20, +19, 59, -9, 124, -57, 11, -38, -243, +51, -69, 73, 328, 11, 62, -26, -343, +-11, 8, 2, 262, -8, -87, 21, -136, +12, 98, 4, -20, 45, -47, 44, 174, +-71, 7, -96, -299, 24, -45, 99, 310, +160, 107, 25, -197, -296, -122, -220, 18, +316, 62, 356, 146, -184, 10, -315, -236, +12, -38, 169, 251, 115, 20, 12, -228, +-131, -11, -119, 167, 128, 18, 154, -87, +-120, -32, -137, -13, 154, 28, 122, 107, +-193, -8, -102, -167, 179, -11, 126, 175, +-106, 15, -119, -162, 15, -24, 95, 121, +69, 24, -10, -79, -95, -26, -128, 19, +116, 37, 271, 91, -158, -68, -371, -237, +218, 102, 430, 353, -229, -134, -412, -375, +172, 122, 325, 266, -63, -82, -184, -87, +12, 35, 6, -63, -38, 6, 128, 95, +119, -78, -145, -27, -147, 190, 50, -63, +57, -315, 70, 100, 85, 359, -84, -52, +-172, -263, -25, -68, 124, 42, 149, 175, +26, 195, -161, -204, -171, -337, 53, 109, +219, 340, 89, 44, -223, -253, -144, -178, +210, 170, 107, 273, -227, -108, -88, -331, +217, 23, 112, 362, -148, 108, -200, -305, +69, -217, 266, 138, -42, 188, -284, 38, +77, -37, 273, -111, -141, -133, -234, 32, +201, 205, 165, 79, -260, -228, -104, -116, +330, 296, 41, 77, -359, -405, -31, -29, +258, 448, 21, 3, -62, -356, 38, 37, +-162, 206, -134, -109, 243, -94, 195, 148, +-186, 18, -183, -83, 82, 116, 76, -40, +-45, -334, 58, 109, 59, 507, -174, -100, +-76, -496, 257, 90, 6, 319, -319, -161, +93, -141, 339, 280, -167, 59, -311, -348, +194, -39, 191, 311, -216, -12, -72, -214, +251, 119, -21, 139, -262, -220, 43, -117, +141, 262, -69, 125, 66, -242, 136, -110, +-270, 202, -251, 53, 320, -163, 309, 1, +-226, 128, -287, 1, 99, -69, 174, -54, +-90, -29, -60, 75, 176, 117, 6, -6, +-298, -128, 5, -105, 298, 53, -19, 115, +-185, 32, 62, 5, 34, -63, -143, -171, +58, 26, 209, 222, -62, 31, -254, -113, +-20, -75, 201, -71, 108, 103, -68, 247, +-190, -97, -143, -343, 210, 41, 321, 317, +-182, 49, -434, -190, 114, -76, 414, 48, +-31, -20, -326, -17, -24, 170, 210, 120, +-17, -293, -118, -277, 122, 364, 50, 381, +-298, -401, -37, -394, 423, 397, 57, 342, +-463, -295, -132, -261, 360, 111, 178, 178, +-189, 64, -148, -119, -7, -140, 7, 98, +95, 123, 157, -88, -99, -63, -268, 68, +43, -11, 238, -40, 12, 78, -151, 14, +-60, -147, 30, 12, 101, 210, 57, -38, +-145, -248, -156, 23, 129, 219, 216, 65, +-75, -90, -230, -158, 1, -93, 128, 165, +0, 223, -14, -64, 42, -213, -64, -38, +-99, 117, 20, 48, 64, -35, 73, 21, +-8, 30, -151, -76, -63, -50, 142, 77, +48, 49, -85, -44, -4, -13, -7, 18, +-54, -72, 72, -31, 79, 184, -125, 102, +-114, -246, 105, -210, 83, 175, -57, 288, +-5, 63, -12, -247, -147, -334, 3, 81, +247, 467, 52, 112, -218, -388, -154, -217, +33, 178, 156, 205, 171, 52, -92, -109, +-299, -194, -43, 17, 243, 232, 116, -4, +-114, -175, -99, 116, -24, 106, -23, -306, +51, -108, 111, 462, -19, 194, -135, -459, +-31, -263, 53, 315, -24, 205, 40, -156, +127, -2, -93, 88, -285, -220, 58, -96, +367, 325, 18, 103, -372, -255, -139, -59, +259, 43, 212, -10, -82, 219, -263, 83, +-125, -420, 223, -139, 257, 490, -166, 159, +-310, -418, 80, -111, 249, 278, -50, 27, +-164, -132, 24, 52, 61, 24, -43, -113, +12, 34, 44, 190, -82, -6, -104, -267, +93, -95, 169, 293, -85, 179, -225, -219, +20, -130, 204, 100, -8, -43, -143, -15, +19, 212, 70, 5, -71, -265, -61, -35, +71, 208, 80, 72, -46, -100, -126, -120, +-36, -15, 131, 168, 98, 141, -115, -168, +-167, -248, 47, 97, 184, 264, 11, -6, +-164, -174, -98, -24, 87, 80, 99, 4, +-20, -71, -87, 7, 1, 139, 49, 36, +-49, -207, -67, -95, 48, 206, 96, 130, +-23, -118, -114, -138, -60, -17, 83, 137, +74, 194, -100, -129, -74, -346, 139, 112, +63, 436, -203, -70, -149, -420, 189, 18, +231, 312, -94, 35, -293, -166, -36, -63, +233, 47, 73, 52, -131, 5, -43, 11, +20, 31, -86, -96, 32, -111, 173, 177, +-56, 189, -238, -228, 33, -232, 230, 257, +-31, 244, -216, -253, -13, -206, 150, 236, +59, 146, -116, -214, -126, -78, 53, 209, +149, 64, -57, -186, -162, -101, 82, 111, +132, 152, -123, 32, -163, -163, 116, -214, +195, 117, -45, 371, -249, -49, -78, -449, +240, -6, 141, 413, -215, 35, -162, -267, +177, -31, 127, 80, -201, -4, -141, 68, +180, 71, 177, -98, -136, -130, -225, 37, +10, 164, 179, 54, 91, -139, -139, -93, +-132, 79, 41, 89, 89, 2, 4, -40, +-22, -57, -66, -13, -99, 70, 83, 52, +169, -11, -67, -43, -202, -86, -7, 2, +133, 170, 8, 33, -57, -200, 40, -2, +16, 185, -134, -97, -59, -142, 136, 207, +40, 62, -43, -246, 28, 77, -75, 204, +-189, -256, 123, -113, 290, 398, -145, 22, +-303, -447, 133, 56, 239, 397, -172, -102, +-173, -284, 166, 104, 77, 155, -128, -71, +-2, -30, 48, 39, -114, -28, -34, -25, +173, 23, 38, 31, -161, 21, -125, -48, +97, -72, 178, 84, -29, 133, -242, -120, +-62, -228, 254, 121, 120, 343, -216, -52, +-214, -420, 136, -51, 238, 430, -78, 128, +-265, -380, 25, -141, 273, 316, -12, 117, +-313, -224, -46, -89, 286, 87, 108, 67, +-212, 93, -140, -27, 30, -249, 72, -15, +93, 311, 51, 37, -119, -240, -208, -11, +19, 97, 200, -47, 102, 31, -102, 131, +-127, -54, -91, -175, -44, -13, 182, 140, +266, 93, -124, -11, -429, -77, -60, -140, +359, -57, 170, 214, -129, 229, -153, -180, +-111, -338, -6, 84, 210, 335, 117, -7, +-241, -251, -103, -8, 207, 174, -5, -6, +-257, -148, 92, 18, 264, 203, -136, 16, +-246, -295, 125, -87, 182, 352, -159, 136, +-145, -287, 145, -73, 88, 144, -114, -101, +-38, -12, 44, 287, -72, -11, -27, -307, +136, -40, 15, 131, -139, 55, -30, 114, +85, 27, -46, -238, -42, -119, 94, 194, +15, 136, -146, -57, -47, -50, 161, -27, +38, -32, -184, 26, -90, 58, 188, 46, +127, -9, -204, -124, -157, -78, 182, 169, +118, 177, -186, -147, -69, -242, 175, 52, +-3, 248, -149, 82, -8, -171, 81, -162, +-3, 77, -10, 159, 2, -38, -56, -109, +-4, 59, 33, 71, -22, -81, -16, -39, +63, 65, -45, -23, -127, -22, 90, 107, +156, 22, -127, -163, -205, -76, 97, 145, +205, 159, -47, -53, -161, -217, -40, -41, +51, 245, 25, 102, 78, -251, 42, -121, +-176, 237, -138, 112, 174, -214, 190, -84, +-156, 169, -168, 48, 81, -114, 103, -7, +-21, 66, -44, -33, -62, -46, -43, 61, +142, 71, 105, -72, -216, -121, -160, 58, +242, 152, 178, -26, -263, -143, -150, -25, +237, 96, 85, 77, -215, -37, -50, -97, +185, -7, -7, 62, -131, 21, 16, 29, +49, 3, -70, -129, 33, -45, 134, 182, +-111, 79, -186, -152, 88, -70, 168, 44, +-46, 16, -58, 84, 34, 67, -107, -184, +-96, -153, 169, 219, 173, 199, -129, -186, +-198, -168, 38, 133, 96, 82, 5, -115, +-10, 9, 23, 154, -47, -43, -73, -190, +27, 30, 76, 166, -2, -10, -98, -95, +0, 1, 111, 18, 22, 26, -138, 43, +-105, -93, 102, -96, 190, 162, -11, 148, +-275, -176, -119, -140, 288, 172, 184, 87, +-281, -176, -238, -32, 287, 202, 235, 49, +-307, -193, -256, -99, 283, 153, 263, 140, +-252, -114, -244, -131, 151, 117, 198, 106, +-55, -102, -124, -63, -58, 17, -3, -29, +151, 127, 124, 183, -205, -221, -234, -327, +201, 197, 278, 372, -187, -85, -259, -281, +114, -13, 191, 134, -57, 76, -104, 6, +2, -92, -29, -110, 25, 74, 125, 188, +0, -3, -207, -217, -59, -82, 209, 202, +93, 140, -162, -171, -104, -136, 105, 167, +50, 93, -71, -168, 28, -45, 55, 118, +-108, -6, -71, -3, 158, 79, 66, -129, +-148, -143, -44, 214, 74, 138, -4, -248, +0, -63, 92, 270, -76, -16, -162, -289, +85, 44, 159, 280, -78, 0, -104, -195, +108, -39, -18, 66, -181, 4, 105, 50, +270, 108, -116, -86, -335, -224, 44, 49, +292, 254, 76, 12, -143, -174, -162, -47, +-59, 21, 134, 56, 230, 131, -55, -69, +-263, -223, -16, 117, 181, 228, 2, -197, +-74, -157, 100, 261, -5, 44, -172, -283, +25, 60, 166, 250, -50, -108, -106, -175, +113, 85, 56, 71, -162, -36, -60, 14, +163, 24, 75, -46, -124, -82, -38, 17, +84, 166, -5, 15, -94, -236, 34, 2, +120, 266, -27, -88, -106, -265, 3, 194, +72, 238, -26, -265, -19, -181, 86, 264, +-4, 83, -139, -207, -13, 28, 170, 121, +35, -117, -151, -26, -59, 151, 109, -65, +73, -128, -71, 132, -54, 83, 27, -172, +30, -54, 10, 177, 5, 55, -37, -147, +-55, -62, 66, 88, 67, 47, -68, -12, +-55, 23, 66, -53, 26, -139, -77, 75, +17, 244, 76, -41, -29, -275, -66, -11, +27, 214, 31, 25, -38, -108, 54, 4, +68, 24, -100, -60, -123, -5, 92, 85, +165, 34, -23, -72, -127, -64, -70, 45, +46, 54, 93, -35, 54, 1, -53, 63, +-104, -75, 20, -109, 92, 115, -4, 121, +-73, -102, 43, -95, 77, 56, -69, 43, +-89, -3, 36, -18, 101, -36, 16, 42, +-73, 70, -45, -86, 28, -83, 26, 102, +-18, 48, 44, -69, 59, 48, -83, 25, +-155, -173, 55, -8, 250, 272, 27, 37, +-260, -292, -117, -93, 210, 228, 147, 135, +-126, -134, -90, -143, 74, 65, 17, 115, +-98, -39, 49, -72, 156, 37, -60, 19, +-190, -37, 25, 42, 190, 44, 12, -84, +-136, -66, -49, 79, 85, 86, 93, -27, +-47, -90, -103, -51, 19, 89, 110, 128, +-24, -91, -107, -204, 54, 87, 132, 274, +-41, -56, -170, -326, 3, -25, 181, 301, +71, 104, -133, -199, -127, -98, 48, 106, +101, 19, 39, -68, -9, 55, -57, 74, +-100, -65, 33, -58, 170, 33, -7, -9, +-158, 4, 5, 80, 110, -29, -47, -102, +-58, 72, 96, 106, 21, -104, -99, -97, +-25, 81, 65, 56, 42, 4, 10, 41, +-32, -74, -90, -150, 23, 57, 125, 184, +-5, 31, -126, -100, -15, -80, 101, -10, +38, 67, -27, 54, -86, -33, -66, -41, +136, 17, 202, 35, -129, -3, -332, -69, +75, -45, 392, 90, 28, 83, -341, -77, +-89, -48, 225, 53, 80, -64, -85, -69, +-25, 154, 10, 89, -26, -157, 27, -47, +51, 102, -53, -57, -26, -82, 77, 123, +20, 117, -93, -61, -22, -156, 83, -115, +38, 137, -14, 282, -33, -81, -44, -363, +2, 27, 74, 345, 41, 8, -49, -271, +-45, -28, -14, 175, 23, 34, 60, -87, +36, -2, -73, 43, -88, -69, 75, -56, +131, 126, -33, 87, -153, -161, -6, -110, +156, 153, 88, 93, -106, -117, -165, -82, +33, 42, 194, 99, 60, 63, -146, -141, +-102, -170, 72, 176, 75, 218, 1, -190, +-3, -176, -17, 189, -52, 53, 29, -189, +92, 77, -55, 166, -94, -169, 89, -122, +109, 210, -96, 70, -110, -205, 51, -36, +86, 167, 29, 46, -30, -108, -62, -87, +-33, 48, 41, 113, 74, -4, 3, -83, +-49, -16, -35, 6, 23, -6, 42, 80, +8, 37, -18, -128, -23, -66, 27, 89, +40, 62, -23, 13, -89, -20, 22, -124, +170, -31, 16, 166, -221, 32, -59, -134, +224, 47, 47, 80, -160, -143, 23, -15, +84, 181, -117, -48, -48, -143, 193, 129, +58, 96, -183, -192, -76, -102, 128, 161, +108, 138, -46, -58, -109, -156, -29, -56, +118, 143, 80, 121, -119, -113, -112, -125, +102, 91, 131, 116, -51, -66, -99, -110, +-12, 23, 47, 85, 69, 8, 10, -38, +-85, 1, -26, -6, 95, -21, 9, 8, +-102, -28, 44, -5, 134, 167, -70, 51, +-170, -325, 80, -149, 180, 386, -51, 221, +-130, -306, 33, -209, 57, 132, -29, 92, +36, 41, 38, 61, -81, -155, -57, -162, +84, 186, 84, 184, -30, -145, -94, -131, +-54, 48, 87, 39, 150, 62, -43, 50, +-195, -139, -6, -99, 184, 157, 29, 94, +-118, -129, 4, -62, 55, 95, -39, 42, +-29, -61, 56, -68, 34, 21, -12, 115, +-21, 35, -54, -117, -37, -84, 91, 61, +133, 100, -59, 19, -191, -95, -6, -67, +181, 102, 56, 69, -105, -132, -42, -37, +11, 178, -22, 9, 53, -179, 99, 11, +-63, 114, -141, -32, 60, -3, 123, 71, +-56, -106, -81, -95, 69, 184, 40, 104, +-85, -214, -12, -102, 91, 215, 9, 103, +-74, -187, -8, -112, 61, 127, 12, 114, +-37, -53, -13, -75, -2, -8, 12, 14, +54, 53, 7, 37, -91, -92, -43, -40, +113, 121, 84, 12, -75, -155, -86, 8, +13, 145, 66, -6, 55, -81, -23, -7, +-87, -16, -1, 11, 103, 80, 7, -7, +-93, -88, -1, 11, 90, 47, 6, -15, +-77, 3, -33, 6, 49, -30, 84, 20, +4, 48, -111, -45, -66, -52, 100, 30, +129, 29, -33, 32, -153, 15, -55, -103, +143, -61, 123, 143, -103, 74, -126, -134, +78, -46, 81, 78, -73, -8, 1, -6, +85, 55, -72, -42, -100, -65, 139, 44, +119, 30, -165, -14, -120, 18, 162, -12, +105, -38, -130, 10, -54, 22, 91, 26, +-20, 20, -66, -66, 108, -41, 80, 91, +-181, 18, -97, -101, 213, 55, 114, 93, +-190, -128, -103, -67, 136, 157, 65, 17, +-42, -128, 4, 45, -34, 48, -63, -121, +105, 32, 111, 172, -135, -86, -119, -177, +150, 85, 111, 137, -141, -52, -85, -73, +132, 2, 71, 8, -89, 11, -52, 36, +42, 28, 25, -50, 1, -101, 11, 43, +-34, 182, -35, -3, 65, -198, 46, -59, +-92, 88, -18, 101, 141, 108, -6, -90, +-178, -289, 14, 28, 194, 342, -2, 25, +-141, -256, 7, -27, 75, 96, -18, -27, +-11, 15, 49, 49, 0, -47, -42, 20, +-36, 51, -10, -163, 75, -73, 112, 278, +-53, 109, -197, -295, -8, -133, 231, 203, +83, 118, -188, -72, -109, -71, 124, -44, +79, 17, -63, 108, 2, 32, 41, -119, +-74, -94, -31, 90, 140, 136, 28, -34, +-169, -139, -33, 2, 169, 86, 61, -6, +-119, -2, -99, 32, 30, -68, 131, -42, +82, 106, -104, 4, -153, -131, 44, 44, +159, 153, 37, -60, -94, -162, -92, 26, +34, 138, 120, 36, 3, -104, -139, -93, +7, 89, 173, 138, -18, -84, -195, -174, +-5, 60, 187, 168, 63, 7, -99, -97, +-109, -93, -30, -24, 110, 146, 150, 130, +-46, -151, -196, -161, -18, 118, 170, 121, +56, -74, -97, -69, -42, 8, 54, 32, +9, 76, -22, -8, 15, -147, 19, -44, +-7, 146, -10, 106, -20, -62, 6, -132, +90, -39, 12, 77, -161, 59, -36, -1, +252, 18, 80, -32, -294, -141, -114, 2, +275, 210, 125, 51, -214, -191, -82, -64, +161, 121, 36, 17, -134, -49, -24, 41, +144, -10, 69, -70, -122, 62, -134, 62, +67, -118, 187, -49, 13, 155, -172, 45, +-79, -148, 141, -42, 108, 110, -107, 6, +-84, -85, 112, 54, 69, 75, -142, -116, +-38, -69, 167, 162, 12, 26, -160, -189, +25, 57, 136, 207, -65, -134, -88, -194, +93, 160, 47, 129, -98, -150, -5, -27, +104, 139, -12, -56, -94, -134, -18, 75, +71, 106, 82, -44, -2, -22, -117, 24, +-98, -77, 92, -63, 175, 121, 21, 130, +-173, -81, -145, -160, 87, 4, 222, 124, +57, 32, -214, -71, -161, -14, 139, 55, +210, -16, -47, -74, -207, 19, 3, 78, +181, 0, 35, -72, -137, -15, -46, 62, +89, 2, 55, -66, -17, 14, -56, 62, +-28, -24, 34, -8, 47, 37, -22, -73, +-17, -67, 34, 136, -27, 103, -57, -124, +35, -110, 88, 34, 6, 76, -64, 76, +-67, -22, -16, -156, 114, -19, 107, 189, +-91, 22, -149, -179, 44, -3, 131, 122, +-3, -37, -53, -53, 10, 88, 12, 1, +-62, -128, -24, -13, 113, 121, 99, 67, +-100, -62, -162, -118, 59, -27, 155, 105, +-17, 85, -88, -16, 17, -69, 10, -90, +-53, 7, 53, 156, 80, 35, -64, -171, +-76, -26, 66, 150, 65, -20, -56, -118, +-39, 35, 42, 53, 27, -7, -12, 35, +-3, -19, -20, -127, -25, 13, 40, 173, +55, 7, -30, -157, -64, -13, 21, 118, +37, 2, -37, -78, 13, 5, 71, 52, +-46, 8, -97, -16, 69, -31, 94, -57, +-67, 23, -53, 146, 64, 17, 7, -219, +-53, -76, 33, 254, 27, 114, -52, -236, +5, -108, 55, 175, -30, 78, -40, -96, +44, -38, 11, 18, -45, 12, 18, 45, +36, 16, -42, -57, -36, -46, 58, 29, +45, 78, -59, 15, -53, -103, 43, -31, +57, 120, -30, 11, -35, -120, 11, 37, +0, 111, 3, -78, 39, -84, 5, 75, +-57, 37, 0, -42, 57, 5, 2, -19, +-46, -37, -2, 89, 37, 55, 9, -125, +-36, -53, -43, 113, 41, 31, 85, -45, +-33, 24, -120, -29, -1, -75, 116, 61, +33, 112, -65, -36, -50, -102, -15, -16, +42, 66, 84, 67, -4, -43, -121, -88, +-42, 46, 115, 97, 79, -52, -67, -92, +-82, 24, 11, 49, 60, 18, 40, 25, +-3, -41, -71, -92, -65, 22, 80, 103, +139, 10, -63, -58, -186, -20, 30, -10, +191, -13, 21, 62, -157, 82, -72, -80, +57, -149, 131, 69, 73, 205, -147, -56, +-189, -234, 113, 34, 246, 202, -46, -9, +-192, -102, -28, -2, 71, -54, 63, -11, +62, 200, -67, 26, -136, -277, 67, -4, +151, 253, -74, -72, -130, -170, 87, 166, +99, 67, -78, -221, -58, 22, 68, 203, +6, -88, -62, -156, 42, 120, 74, 106, +-49, -99, -90, -59, 27, 42, 64, 1, +11, -5, -10, 63, -9, 11, -35, -92, +-1, -64, 53, 49, -1, 79, -29, 35, +12, -12, 8, -93, -42, -88, 8, 94, +43, 148, -20, -66, -19, -119, 33, 65, +4, 25, -52, -97, 2, 73, 38, 128, +8, -142, -5, -127, 1, 169, -24, 106, +-20, -151, 19, -86, 8, 87, 20, 77, +23, 17, -43, -60, -65, -101, 39, 28, +65, 123, -29, 15, -37, -67, 26, -19, +5, 8, -50, -7, -10, 1, 61, 37, +65, 46, -60, -47, -119, -109, 42, 46, +156, 132, -34, -56, -169, -113, 33, 76, +156, 83, -17, -63, -132, -51, -13, -1, +75, 8, 55, 83, -5, 43, -72, -123, +-47, -69, 43, 106, 70, 33, -7, -62, +-51, 45, -24, 43, 26, -92, 14, -52, +-5, 62, 22, 57, -4, 20, -55, -47, +0, -103, 97, 36, 15, 137, -96, -63, +-55, -157, 69, 103, 89, 199, -7, -113, +-110, -239, -54, 57, 112, 228, 70, 16, +-95, -149, -42, -41, 74, 45, -15, -4, +-48, 37, 65, 77, 12, -90, -96, -133, +37, 117, 136, 145, -68, -143, -164, -135, +50, 140, 164, 110, -3, -99, -106, -60, +-45, 39, 20, -10, 57, 5, 45, 56, +-22, -21, -72, -45, 1, 20, 50, -13, +14, -31, -19, 52, -18, 37, -5, -51, +34, -11, 51, 16, -48, -59, -108, -9, +22, 110, 177, 43, 49, -104, -197, -81, +-136, 34, 143, 73, 183, 48, -62, 9, +-164, -71, -32, -113, 110, 42, 91, 182, +-58, -2, -122, -196, 31, 7, 126, 170, +-42, -51, -105, -113, 55, 113, 53, 50, +-86, -155, 20, 20, 109, 166, -71, -69, +-139, -130, 78, 65, 151, 43, -43, -21, +-133, 79, -11, -27, 97, -189, 34, 42, +-47, 216, -27, -31, 5, -146, -5, 26, +14, 39, 25, -43, -30, 38, -19, 69, +19, -47, -3, -77, -17, 20, 30, 64, +-3, 3, -41, -51, 30, -28, 35, 22, +-37, 48, -22, 30, 31, -81, -19, -123, +10, 94, 58, 216, -46, -85, -107, -257, +45, 65, 125, 210, -23, -50, -99, -98, +-23, 48, 19, -18, 21, -35, 68, 105, +7, 0, -121, -159, -51, 36, 115, 171, +62, -55, -96, -147, -48, 61, 66, 103, +16, -59, -69, -68, -8, 66, 52, 69, +3, -76, -34, -97, -1, 74, 7, 125, +-36, -61, -16, -127, 36, 44, 45, 115, +-23, -5, -83, -93, -51, -57, 75, 59, +109, 120, -47, -17, -132, -151, 4, -39, +105, 111, -20, 79, -78, -21, 29, -86, +70, -75, -35, 70, -93, 114, -22, -54, +85, -107, 87, 55, -86, 78, -129, -57, +38, -38, 106, 30, -26, 0, -64, 12, +12, 40, -7, -48, -16, -75, 24, 58, +10, 75, -50, -46, -24, -47, 37, 24, +31, 4, -38, -12, -70, 31, 8, 0, +64, -47, -6, 18, -67, 57, -4, -40, +22, -68, -21, 51, -15, 76, 18, -49, +-11, -67, -33, 40, -9, 46, 3, -32, +4, -23, -6, 14, -24, 16, -21, 21, +8, -22, -8, -63, -31, 41, -3, 114, +18, -55, -29, -127, -52, 56, 27, 105, +46, -51, -37, -51, -78, 33, 12, -36, +58, -12, -10, 119, -52, -13, -30, -184, +-5, 29, 14, 201, 29, -36, -43, -158, +-80, 42, 8, 92, 69, -45, -12, -39, +-82, 38, -38, 31, 26, -1, 31, -46, +-13, -58, -50, 54, -33, 111, 14, -36, +5, -131, -39, 1, 2, 109, 31, 27, +-48, -73, -89, -29, 39, 30, 85, -1, +-59, 2, -110, 54, 18, -15, 60, -104, +-30, 15, -64, 133, -35, 2, 27, -111, +45, -6, -34, 39, -115, -5, -27, 51, +82, 41, 42, -118, -51, -81, -85, 134, +-46, 82, 29, -117, 61, -63, -9, 97, +-77, 46, -55, -85, -7, -45, 12, 68, +16, 54, -1, -35, -35, -46, -62, -11, +-45, -4, 33, 42, 58, 66, -43, -55, +-101, -107, -11, 52, 56, 94, -21, -47, +-77, -34, -24, 59, 28, -28, 10, -73, +-32, 70, -68, 74, -46, -85, 27, -63, +51, 74, -13, 42, -91, -42, -80, -19, +4, -1, 71, -20, 24, 37, -62, 68, +-102, -38, -55, -116, 43, 3, 75, 134, +-12, 35, -109, -99, -91, -36, 5, 29, +76, -20, 41, 32, -87, 104, -144, -56, +2, -168, 133, 45, -3, 164, -181, -22, +-61, -98, 141, 10, 31, 13, -176, -10, +-90, 61, 103, 8, 68, -97, -96, 9, +-117, 105, -13, -33, 73, -99, 20, 57, +-103, 91, -89, -74, 42, -80, 40, 82, +-66, 82, -75, -72, 4, -99, 20, 44, +-20, 104, -39, -8, -57, -89, -33, -33, +21, 52, 20, 63, -59, 4, -81, -71, +-9, -56, 30, 59, -27, 86, -59, -30, +-7, -82, 0, 5, -63, 51, -51, 0, +36, -21, 18, 23, -81, 15, -88, -43, +10, -46, 60, 44, -21, 75, -111, -23, +-61, -76, 55, -7, 39, 41, -86, 21, +-87, 6, 12, -29, 36, -44, -46, 42, +-62, 50, -12, -72, 0, -36, -40, 108, +-42, 9, -12, -132, -1, 16, -23, 128, +-58, -30, -56, -91, 7, 33, 28, 31, +-61, -19, -92, 52, 15, 17, 46, -125, +-84, -37, -93, 152, 46, 62, 55, -127, +-83, -68, -113, 69, -19, 13, 55, -21, +28, 88, -73, 31, -148, -174, -31, -75, +126, 210, 20, 127, -184, -179, -89, -134, +108, 113, 27, 94, -130, -44, -61, -27, +47, -10, -9, -32, -62, 46, -36, 63, +-22, -75, -26, -74, 2, 98, -26, 84, +-79, -102, -36, -102, 41, 91, -11, 119, +-101, -60, -55, -118, 47, 28, 17, 84, +-90, -5, -82, -28, 12, -1, 22, -28, +-34, 7, -50, 76, -57, -9, -42, -98, +17, 11, 17, 93, -58, -8, -61, -44, +-37, 3, -39, -39, 11, -14, 69, 121, +-74, 53, -189, -164, -11, -95, 149, 153, +-3, 114, -157, -97, -68, -103, 34, 29, +4, 60, -27, 18, -27, -19, -55, -43, +-53, -7, -11, 61, 10, 17, -16, -80, +-50, -23, -69, 99, -21, 37, 19, -104, +-9, -57, -60, 94, -52, 80, -31, -66, +-13, -92, 25, 19, -10, 94, -122, 29, +-91, -72, 85, -57, 83, 44, -125, 57, +-151, -32, 45, -40, 91, 28, -64, 18, +-115, -39, -8, -3, 31, 43, -24, 2, +-73, -38, -41, -21, 5, 29, 15, 56, +-41, -7, -86, -97, -30, -37, 41, 117, +-8, 83, -87, -88, -44, -103, 15, 29, +-30, 81, -44, 26, 11, -25, -17, -55, +-90, -31, -37, 48, 61, 57, -5, -28, +-102, -63, -59, 17, 31, 50, 6, -15, +-47, -31, -45, 27, -40, 17, -29, -53, +26, -7, -1, 83, -100, 11, -72, -88, +57, -17, 28, 67, -96, 13, -55, -31, +25, 12, -29, -1, -60, -46, 21, -1, +6, 69, -83, 28, -62, -61, 16, -54, +6, 28, -15, 60, -25, 3, -66, -48, +-76, -16, 21, 31, 71, 22, -41, -22, +-121, -42, -40, 19, 49, 74, 4, 2, +-57, -110, -38, -39, -23, 119, -16, 77, +3, -77, -33, -92, -73, -4, -18, 72, +63, 83, -15, -6, -119, -128, -67, -69, +62, 116, 48, 127, -65, -63, -94, -143, +-21, 21, 18, 129, -12, -6, -25, -102, +-3, 23, -29, 74, -80, -60, -18, -56, +63, 99, -7, 39, -113, -122, -34, -36, +67, 121, -10, 30, -102, -86, -27, -29, +55, 26, -4, 13, -74, 32, -49, 25, +-3, -63, 4, -52, -9, 59, -18, 62, +-30, -46, -37, -50, -34, 38, -12, 31, +18, -38, 9, -11, -49, 41, -81, -3, +-28, -30, 54, 6, 40, 6, -67, -6, +-90, 23, -14, 1, 35, -54, 7, 10, +-24, 79, -61, -17, -47, -84, 19, 29, +32, 67, -53, -42, -57, -37, 27, 55, +9, -1, -60, -67, -27, 30, 21, 70, +-27, -47, -28, -69, 30, 44, -25, 55, +-84, -43, 6, -42, 66, 32, -33, 21, +-75, -29, 4, -8, 3, 30, -42, 15, +-9, -26, 34, -40, -36, 10, -54, 69, +-6, 23, -1, -85, -23, -62, 10, 75, +15, 91, -71, -27, -75, -81, 32, -33, +79, 29, -16, 73, -96, 49, -63, -75, +26, -113, 65, 43, 2, 140, -90, 15, +-77, -114, 40, -60, 80, 56, -27, 73, +-104, 2, -49, -60, 65, -31, 50, 51, +-40, 24, -88, -52, -27, -12, 56, 60, +36, 8, -46, -59, -72, -9, -1, 44, +26, 8, -2, -17, -17, 4, -9, 5, +-37, -24, -29, -23, 40, 31, 36, 55, +-62, -18, -77, -82, 17, -10, 59, 87, +5, 44, -37, -58, -66, -72, -31, -12, +58, 71, 77, 86, -58, -30, -122, -140, +4, -28, 76, 153, 11, 79, -38, -131, +-22, -93, -36, 92, -9, 75, 39, -65, +16, -55, -48, 51, -26, 41, 19, -29, +-4, -37, -22, -16, 3, 22, -3, 60, +-11, 14, -6, -67, -16, -45, -38, 36, +11, 52, 54, 21, -8, -30, -73, -71, +-31, -17, 52, 93, 26, 56, -23, -82, +-36, -71, -15, 47, 8, 55, 28, -13, +1, -26, -51, -14, -5, -20, 58, 12, +-2, 50, -89, 11, -21, -59, 89, -46, +31, 42, -62, 68, -55, -13, -6, -65, +24, -16, 62, 41, 23, 26, -102, -13, +-81, -13, 67, -9, 115, -16, -40, 9, +-99, 41, -14, 11, 59, -56, 26, -38, +-34, 54, -26, 55, 12, -46, 30, -64, +-21, 29, -40, 66, -3, -1, 44, -61, +21, -28, -35, 36, -29, 46, -8, -3, +22, -50, 24, -23, 0, 27, -22, 24, +-25, 0, 7, -6, 5, -14, 12, -20, +5, 4, 6, 30, -26, 21, -28, -16, +-4, -37, 26, -19, 45, 49, -8, 71, +-71, -32, -64, -111, 65, -8, 107, 132, +-26, 68, -112, -122, -21, -117, 71, 69, +39, 131, -16, -4, -24, -104, -37, -41, +-5, 46, 63, 46, 38, 5, -79, -28, +-60, -29, 71, 8, 79, 38, -58, 9, +-94, -39, 22, -22, 89, 36, 22, 56, +-80, -14, -57, -86, 42, -21, 76, 100, +-11, 59, -68, -88, 3, -86, 47, 60, +-18, 86, -28, -27, 36, -63, 34, -6, +-50, 26, -31, 23, 32, 15, 25, -20, +-16, -41, -1, 6, 4, 46, -30, 10, +-3, -23, 28, -6, 9, 9, -31, -9, +14, -8, 16, 19, -41, 29, -27, -1, +63, -42, 52, -38, -65, 29, -62, 74, +31, 13, 52, -79, 5, -51, -21, 54, +-22, 58, -35, -12, 28, -20, 59, 3, +-12, -31, -76, -30, 0, 59, 69, 87, +-3, -27, -39, -124, -13, -37, 16, 112, +6, 97, 34, -49, -15, -106, -63, -33, +5, 56, 88, 86, 24, 15, -86, -104, +-45, -75, 57, 91, 63, 109, -26, -74, +-54, -113, 2, 61, 35, 94, 14, -58, +-18, -67, -8, 60, 5, 38, 6, -63, +2, -23, -5, 52, -7, 26, 0, -29, +27, -25, -5, -7, -32, 18, -12, 34, +39, -5, 29, -46, -18, -4, -39, 44, +0, -16, 42, -38, 14, 31, -25, 35, +-22, -34, 18, -18, 24, 27, -13, -21, +-27, -33, 13, 69, 35, 60, 4, -97, +-45, -91, -21, 83, 36, 100, 48, -42, +-11, -79, -50, 4, -26, 29, 40, 14, +48, 23, -14, -15, -54, -51, -4, -7, +60, 57, 6, 23, -45, -53, 0, -32, +43, 34, 0, 25, -34, -23, 12, -21, +31, 9, -15, 15, -18, -2, 18, -12, +4, 2, -37, 21, 8, 16, 32, -18, +-1, -28, -38, 17, -5, 30, 33, -15, +17, -15, -5, 19, -42, -2, -20, -29, +49, 18, 66, 45, -54, -24, -91, -57, +36, 24, 100, 57, -5, -11, -89, -34, +-12, -1, 43, 4, 27, 2, 8, 40, +-20, 9, -45, -71, -13, -22, 78, 84, +41, 34, -63, -86, -63, -41, 40, 72, +73, 42, 1, -50, -49, -46, -45, 11, +26, 50, 62, 39, 20, -42, -67, -84, +-39, 17, 51, 100, 47, 8, -20, -83, +-33, -26, 3, 31, 12, 9, 21, 20, +20, 18, -24, -67, -34, -68, 19, 83, +41, 109, -6, -74, -28, -126, -6, 39, +13, 104, 31, -15, 11, -53, -34, 8, +-35, -1, 41, -15, 44, 45, -28, 34, +-48, -47, 18, -27, 39, 37, -6, 10, +-16, -11, 2, 33, -6, 1, -5, -62, +23, 8, 22, 72, -21, -7, -20, -66, +16, 2, 15, 28, 5, -3, -2, 23, +-11, 5, -24, -79, 26, -31, 41, 107, +-17, 39, -52, -126, 15, -57, 56, 107, +-2, 45, -52, -83, -16, -30, 46, 50, +40, -4, -23, -32, -63, 33, 4, 22, +82, -47, 23, -24, -74, 47, -37, 35, +59, -16, 48, -23, -28, -4, -34, 19, +-8, 41, 23, 22, 24, -30, 8, -39, +-25, 18, -17, 68, 16, 18, 25, -63, +6, -42, -9, 49, -17, 62, -13, -24, +27, -65, 31, -15, -13, 41, -34, 32, +6, -31, 28, -67, 7, -10, 0, 52, +5, -4, -11, -59, -19, 1, 19, 23, +33, -37, -7, -18, -22, 54, -10, -9, +21, -82, 28, 13, 11, 82, -31, -19, +-19, -54, 25, 51, 16, 44, -19, -50, +-10, 1, 23, 89, -10, 20, -23, -58, +16, 4, 31, 54, -18, 18, -20, 3, +23, 10, 11, -21, -20, -15, 11, 45, +32, 28, -20, -48, -37, -34, 31, 34, +51, 18, -17, -34, -45, -36, 8, -19, +41, -6, 21, 29, -13, 11, -27, -89, +-14, -80, 29, 58, 55, 84, -11, -49, +-59, -105, -10, -4, 59, 51, 33, 10, +-23, 1, -34, 17, -1, -33, 21, -49, +20, 56, -2, 109, -13, -2, -3, -86, +10, -7, 4, 83, 1, 54, 21, -2, +3, -4, -26, -9, -5, -5, 35, 48, +16, 47, -20, -26, -7, -38, 16, 24, +-6, 24, -9, -24, 27, -14, 18, 11, +-40, -16, -20, -38, 54, -15, 40, -11, +-41, -28, -35, -16, 30, -3, 34, -23, +-5, -36, -19, -6, -11, -4, 8, -25, +36, -3, 16, 22, -30, -16, -28, -45, +32, 13, 37, 56, 5, 14, -20, -16, +-20, 5, -7, 9, 39, 19, 46, 76, +-32, 56, -66, -53, 19, -52, 81, 76, +10, 105, -63, 0, -20, -61, 37, -16, +35, 37, 11, 46, -21, 9, -34, -54, +9, -39, 59, 34, 13, 21, -50, -57, +-23, -47, 45, 16, 27, -3, -10, -55, +-12, -41, 10, -17, 7, -12, 1, 1, +5, -18, 9, -58, 15, -24, -3, 40, +-17, 2, 4, -48, 35, 11, 12, 51, +-30, -13, -23, -28, 20, 50, 31, 65, +11, -6, -8, -30, -24, 29, -9, 58, +39, 37, 38, 8, -16, 3, -50, 20, +-10, 24, 48, 4, 55, 14, -10, 30, +-62, -12, -24, -38, 58, 8, 58, 28, +-25, -23, -50, -38, -1, -10, 35, -20, +27, -30, 10, -3, -22, -30, -28, -69, +16, -6, 59, 41, 6, -44, -47, -99, +-15, -1, 39, 64, 29, 0, -6, -47, +-23, -22, -20, 0, 24, 19, 57, 48, +5, 24, -68, -27, -20, -10, 70, 40, +44, 46, -46, 42, -48, 38, 14, -11, +45, -41, 30, 41, -11, 106, -44, 14, +-7, -79, 56, -14, 36, 75, -48, 32, +-33, -45, 36, -35, 38, 9, -16, 18, +-11, -19, 10, -59, 0, -41, 11, 35, +20, 26, -1, -93, -26, -98, 17, 49, +35, 80, -12, -71, -34, -124, 20, 18, +47, 98, -6, 0, -44, -94, -5, -49, +51, 66, 36, 106, -38, 0, -56, -113, +23, -29, 81, 144, 10, 107, -65, -74, +-27, -74, 45, 63, 37, 75, -1, 21, +-9, 34, -27, -4, -13, -78, 42, 12, +56, 132, -21, 21, -55, -109, 3, -26, +53, 47, 20, -12, -17, -4, 0, 28, +-3, -57, -13, -95, 28, 30, 49, 68, +-10, -58, -52, -82, 2, 11, 56, 19, +28, -31, -17, -18, -32, 1, -2, -16, +39, 6, 40, 18, -10, -33, -35, -17, +5, 56, 49, 23, 19, -49, -15, 9, +-16, 89, 3, 5, 25, -70, 31, 35, +-2, 100, -38, -2, -1, -63, 62, 22, +19, 62, -47, -11, -6, -20, 58, 25, +17, 6, -43, -32, 8, -8, 48, 14, +7, 1, -26, -1, 12, -21, 19, -57, +1, -16, 12, 72, 18, 16, -8, -115, +-4, -68, 29, 87, 14, 61, -13, -77, +11, -68, 34, 28, -2, 35, -19, 0, +30, -13, 35, -24, -8, 4, -11, 64, +18, 11, 17, -80, 13, 3, 29, 124, +-2, 16, -27, -118, 13, -1, 66, 123, +16, 24, -48, -75, -17, -7, 52, 48, +49, 13, -10, -5, -27, -16, 6, -36, +51, 6, 40, 58, -16, -10, -36, -97, +22, -28, 74, 82, 31, 40, -52, -77, +-37, -81, 53, 20, 83, 63, -3, 18, +-65, -39, -7, -53, 69, -15, 51, 39, +-14, 57, -27, -6, 11, -66, 28, -19, +28, 58, 20, 51, -5, -11, -9, -39, +16, -11, 33, 44, 13, 65, 6, -9, +5, -76, 6, -3, 23, 96, 36, 32, +14, -95, -14, -36, 4, 82, 36, 33, +22, -62, 13, -23, 13, 37, -7, -11, +-6, -32, 47, 25, 59, 15, -19, -47, +-46, -26, 38, 26, 79, 7, 12, -17, +-31, -2, 1, -10, 26, -16, 35, 21, +41, 29, -4, -23, -36, -29, 22, 32, +77, 35, 16, -23, -40, -16, 13, 35, +58, 27, 20, -23, -2, -18, 17, 22, +14, 31, 15, 16, 46, -17, 21, -41, +-34, 3, 12, 79, 80, 35, 29, -97, +-37, -77, 6, 91, 56, 93, 21, -67, +1, -99, 33, 20, 13, 61, -13, 7, +35, -26, 59, -40, -2, -35, -16, 36, +38, 60, 39, -36, -5, -74, 19, 21, +46, 58, 9, -22, -9, -30, 41, 21, +50, 5, -8, -20, -5, 22, 42, 31, +45, -21, 3, -15, -3, 36, 22, 15, +43, -21, 36, 6, 7, 29, -18, 6, +21, -13, 70, 1, 36, 10, -25, 9, +-3, 4, 60, -14, 50, -19, 6, 12, +0, 24, 20, -20, 30, -45, 51, 6, +35, 53, -17, -9, -12, -83, 67, -21, +76, 79, -3, 29, -34, -77, 26, -50, +65, 35, 43, 35, 19, -3, -2, -14, +-5, -40, 43, -26, 83, 58, 21, 55, +-43, -52, 3, -48, 76, 53, 48, 33, +-6, -30, 10, 11, 35, 34, 14, -35, +24, -18, 52, 69, 34, 14, -9, -73, +6, -2, 56, 72, 57, 4, 12, -45, +-11, -6, 19, 8, 55, 10, 49, 38, +5, -9, -10, -78, 26, -4, 63, 92, +38, 7, -1, -96, 7, -24, 50, 60, +43, 13, 11, -39, 14, -14, 45, 3, +37, 0, 2, 12, 8, 1, 47, -27, +56, -3, 18, 30, 2, -5, 15, -35, +50, 1, 55, 42, 23, 12, -12, -34, +13, -19, 61, 24, 60, 30, 2, 10, +-9, -11, 30, -26, 56, -11, 41, 46, +14, 56, -1, -34, 19, -78, 64, 20, +58, 84, -9, 3, -19, -64, 64, -15, +79, 25, 4, 10, -20, 12, 46, 1, +59, -49, 18, -22, 10, 64, 39, 28, +24, -68, 20, -38, 47, 46, 27, 28, +-2, -30, 41, -16, 71, 1, 4, -10, +-21, 10, 52, 30, 76, -9, 3, -36, +-8, 4, 39, 30, 46, 3, 25, -4, +41, 5, 24, -23, -10, -21, 30, 49, +89, 56, 30, -45, -39, -76, 20, 32, +86, 88, 38, 5, -4, -68, 26, -22, +33, 31, 27, 29, 41, 16, 45, -21, +8, -43, 12, 13, 46, 49, 42, -19, +22, -49, 41, 32, 28, 35, 2, -61, +27, -31, 75, 70, 39, 15, -16, -70, +4, 1, 56, 47, 62, -28, 28, -27, +2, 42, -5, 1, 40, -49, 82, 15, +41, 38, -32, -34, 8, -26, 70, 44, +56, 2, 12, -41, 20, 12, 23, 23, +10, -22, 44, 4, 74, 35, 22, -31, +-21, -41, 21, 43, 72, 39, 48, -29, +12, -17, 4, 20, 14, -8, 43, 5, +57, 43, 28, -2, -16, -42, 17, 7, +62, 28, 49, -12, 10, 4, 13, 33, +27, -27, 32, -60, 43, 19, 38, 72, +10, 14, 3, -55, 36, -59, 52, 4, +34, 77, 10, 48, 9, -71, 27, -89, +48, 35, 44, 79, 20, -6, 0, -52, +30, -27, 44, 11, 29, 39, 16, 27, +24, -41, 23, -49, 27, 38, 39, 62, +32, -27, 8, -52, 19, 13, 44, 42, +32, 10, 16, -4, 23, -11, 37, -24, +18, 15, 20, 52, 40, 10, 33, -41, +7, -19, 23, 23, 44, 24, 33, 1, +14, -10, 31, -17, 40, -9, 9, 13, +7, 16, 49, 0, 60, -12, 0, -14, +-15, -18, 41, 4, 71, 29, 25, 5, +-10, -36, 17, -34, 39, 14, 39, 21, +49, -8, 29, -18, -15, -14, -1, -11, +75, 8, 79, 23, -14, -3, -41, -32, +49, -9, 87, 30, 22, 13, -16, -13, +13, -2, 35, 9, 35, -2, 46, 6, +21, 19, -14, 0, 12, -9, 65, 11, +43, 5, -6, -7, 8, 19, 38, 19, +32, -38, 21, -28, 35, 44, 16, 43, +2, -38, 22, -39, 47, 12, 24, 23, +7, 3, 32, -13, 28, -29, 0, -19, +20, 25, 59, 27, 23, -14, -20, -43, +11, -17, 56, 20, 51, 29, 9, 5, +-6, -51, 4, -41, 41, 42, 68, 65, +24, -20, -35, -71, -7, -8, 77, 58, +69, 42, -13, -20, -36, -46, 26, -8, +69, 51, 42, 47, -6, -22, -22, -46, +19, 7, 65, 47, 45, 19, -18, -20, +-15, -25, 42, 5, 52, 23, 12, 7, +-2, -16, 22, -11, 18, 16, 12, 2, +38, -26, 32, -8, -4, 20, -4, 5, +41, -25, 39, -18, 6, 5, 7, 4, +29, -5, 13, 2, 4, 0, 38, -21, +43, -13, -5, 22, -18, 19, 33, -15, +57, -14, 13, 17, -21, 4, 10, -9, +40, 20, 33, 25, 6, -23, 16, -30, +18, 32, 12, 35, 22, -23, 39, -22, +16, 23, -6, 16, 12, -5, 31, -4, +26, -12, 14, -4, 27, 27, 8, 13, +-11, -44, 18, -31, 71, 30, 33, 31, +-40, -15, -28, -30, 50, -25, 77, -5, +17, 49, -41, 32, -30, -66, 35, -63, +84, 49, 36, 70, -55, -32, -42, -59, +54, 6, 90, 26, 14, 9, -49, 4, +-17, -18, 49, -24, 59, 28, 22, 34, +-20, -33, -18, -38, 28, 43, 55, 47, +25, -28, -19, -42, -7, 16, 25, 43, +31, 14, 11, -21, 5, -24, 8, 17, +4, 37, 7, -6, 22, -36, 32, 8, +10, 32, -11, -16, 4, -38, 36, 7, +30, 26, 1, -6, -10, -15, 10, -12, +28, -12, 18, 9, 13, 20, 4, -14, +1, -29, 11, 4, 37, 13, 21, -12, +-20, 3, -13, 22, 40, -8, 42, -22, +-14, 13, -25, 20, 23, -6, 49, 1, +3, 17, -16, -14, 9, -18, 26, 30, +8, 30, 16, -20, 20, -21, -7, 11, +-15, 7, 31, 11, 50, 20, -5, -22, +-36, -43, 10, 25, 51, 59, 12, -19, +-6, -66, 9, 0, 12, 37, -5, 2, +27, -11, 42, -9, -7, -35, -36, -10, +18, 58, 57, 21, 11, -71, -24, -38, +0, 50, 26, 32, 11, -22, 17, -14, +10, -4, -8, -19, -6, 22, 23, 57, +22, -14, 0, -61, 0, 4, 14, 48, +7, 11, 5, -15, 24, -5, 17, -16, +-10, 3, -13, 42, 25, 8, 30, -43, +9, -11, -9, 36, -6, 7, 10, -23, +28, 2, 26, 6, -6, -15, -21, 2, +1, 14, 39, -11, 28, -10, -8, 12, +-27, -9, 8, -22, 36, 22, 26, 26, +-10, -36, -14, -42, 14, 27, 20, 45, +11, -8, 0, -31, 4, -12, -8, 14, +5, 25, 33, 14, 20, -12, -25, -26, +-16, -4, 33, 26, 31, 34, -16, 12, +-19, -30, 25, -40, 17, 18, -7, 59, +6, 25, 23, -33, -12, -50, -13, -15, +34, 55, 36, 74, -26, -28, -31, -108, +35, -17, 41, 112, -13, 48, -16, -88, +22, -67, 18, 34, -5, 58, 6, 6, +27, -41, -1, -48, -9, 7, 15, 61, +22, 16, 5, -70, 6, -37, 10, 52, +-3, 36, 0, -26, 23, -22, 28, 5, +-11, 3, -20, 10, 10, 13, 39, -12, +19, -10, -8, 21, -24, 5, 7, -37, +42, 12, 23, 63, -20, -4, -23, -71, +26, -12, 31, 57, 9, 23, -6, -20, +1, -16, -4, -21, 11, -11, 30, 40, +19, 35, -16, -44, -9, -57, 18, 28, +16, 44, 10, -15, 2, -16, 4, 11, +-13, -10, 5, -25, 28, 25, 25, 35, +-11, -24, -21, -35, 2, 14, 30, 23, +35, -6, -2, 1, -32, 3, -8, -21, +46, -2, 35, 39, -19, 16, -34, -34, +18, -15, 32, 36, 2, 31, -9, -9, +13, -30, 0, -7, -13, 32, 23, 40, +32, -10, -9, -60, -26, -14, 21, 66, +28, 46, -6, -45, -10, -57, 23, 14, +9, 50, -17, 17, 8, -25, 30, -27, +-5, 6, -27, 33, 18, 13, 34, -27, +-5, -18, -27, 32, 20, 25, 29, -28, +-5, -27, -19, 33, 9, 37, 22, -20, +10, -30, -2, 20, -15, 32, -2, -8, +23, -10, 29, 18, -9, 10, -30, -12, +0, 1, 38, 21, 29, 6, -16, 0, +-41, 9, -5, 0, 48, -4, 32, 25, +-34, 25, -49, -18, 23, -20, 52, 31, +2, 26, -35, -30, -3, -13, 23, 39, +11, 18, -10, -30, -3, -11, 4, 37, +3, 27, 2, -11, -9, -18, -3, 0, +16, 24, 15, 36, -23, 0, -22, -36, +11, 2, 40, 46, 4, 24, -32, -25, +-23, -11, 10, 31, 33, 22, 9, 8, +-36, 8, -35, -2, 19, -2, 46, 24, +-3, 29, -49, -11, -9, -12, 29, 32, +11, 18, -19, -20, -9, 16, 0, 49, +-10, -10, 2, -48, 14, 30, -10, 72, +-33, 2, -8, -36, 14, 10, 5, 25, +-16, 11, -14, 31, -11, 21, -9, -33, +4, -19, 11, 59, -19, 56, -40, -22, +-8, -30, 30, 21, 7, 36, -40, 15, +-30, 9, 9, 1, 18, -4, -15, 23, +-37, 42, -17, 7, 12, -17, 6, 12, +-24, 34, -29, 20, -9, 7, 5, 6, +-9, 6, -17, 15, -21, 30, -17, 18, +-8, 0, -3, 13, -20, 24, -33, 9, +-13, 10, 6, 35, -16, 24, -38, -22, +-11, -13, 5, 53, -19, 54, -42, -11, +-14, -31, 9, 18, -13, 44, -45, 26, +-35, 17, 0, 6, 2, -7, -27, 7, +-46, 46, -29, 39, -4, 0, -4, -1, +-33, 20, -48, 13, -22, 12, 3, 50, +-14, 36, -42, -32, -41, -31, -13, 55, +-5, 81, -23, 7, -43, -44, -42, -4, +-15, 53, -3, 63, -33, 22, -60, -33, +-34, -17, 0, 61, -19, 77, -54, -10, +-45, -44, -20, 31, -19, 73, -35, 23, +-36, -20, -33, 1, -43, 34, -30, 38, +-15, 25, -34, 2, -60, -6, -37, 26, +-16, 52, -33, 18, -56, -7, -42, 22, +-28, 41, -44, 13, -46, 2, -30, 35, +-38, 42, -55, 2, -46, -2, -31, 30, +-40, 43, -54, 27, -54, 21, -45, 7, +-37, 4, -40, 33, -52, 52, -56, 18, +-38, -12, -36, 17, -61, 40, -60, 23, +-36, 25, -36, 37, -67, 9, -66, -14, +-40, 35, -36, 71, -59, 23, -68, -21, +-58, 12, -56, 55, -44, 34, -41, 13, +-66, 19, -85, 14, -54, 10, -25, 41, +-47, 51, -95, 12, -82, -14, -36, 25, +-35, 60, -72, 32, -84, -2, -69, 16, +-54, 35, -52, 31, -67, 31, -78, 28, +-76, 13, -60, 14, -58, 38, -70, 45, +-79, 23, -68, 4, -60, 12, -69, 37, +-75, 48, -70, 26, -66, -5, -72, 11, +-78, 57, -79, 49, -69, 0, -68, 8, +-76, 48, -88, 32, -81, 7, -63, 38, +-68, 54, -86, -5, -86, -13, -69, 56, +-73, 69, -86, 4, -79, -8, -70, 36, +-89, 33, -95, 18, -71, 52, -61, 46, +-97, -19, -109, -12, -77, 78, -64, 83, +-87, -9, -99, -27, -89, 46, -84, 61, +-82, 16, -83, 18, -88, 42, -105, 24, +-95, 2, -72, 31, -80, 61, -111, 39, +-108, 4, -79, 9, -72, 33, -97, 49, +-117, 42, -96, 18, -72, 7, -76, 19, +-115, 47, -119, 47, -79, 23, -66, 6, +-100, 11, -127, 47, -99, 58, -72, 24, +-91, -7, -112, 19, -109, 66, -96, 44, +-85, -1, -88, 11, -110, 48, -123, 32, +-94, 19, -67, 42, -95, 35, -140, -9, +-112, 6, -61, 75, -79, 65, -134, -12, +-130, -20, -78, 44, -72, 66, -113, 36, +-131, 19, -106, 12, -86, 3, -88, 34, +-111, 79, -127, 46, -112, -25, -82, -4, +-82, 64, -122, 63, -134, 12, -96, 8, +-78, 38, -104, 26, -123, 19, -113, 40, +-95, 40, -97, 16, -107, 24, -119, 39, +-111, 19, -96, 21, -101, 58, -124, 48, +-118, -7, -85, -1, -94, 58, -128, 58, +-123, 12, -87, 9, -92, 31, -131, 40, +-126, 35, -88, 31, -89, 13, -115, 10, +-122, 44, -108, 52, -103, 18, -98, 2, +-104, 34, -124, 48, -121, 31, -89, 16, +-82, 15, -125, 25, -139, 47, -94, 43, +-70, 7, -110, 0, -139, 40, -110, 54, +-77, 17, -93, 10, -129, 36, -127, 30, +-93, 9, -73, 35, -111, 57, -137, 6, +-114, -7, -77, 48, -84, 58, -132, 10, +-135, 8, -93, 48, -70, 28, -106, 0, +-135, 39, -124, 67, -90, 9, -69, -25, +-98, 43, -146, 75, -128, 10, -66, -11, +-59, 36, -130, 49, -159, 16, -90, 19, +-48, 38, -96, 17, -148, 8, -117, 41, +-75, 49, -79, 6, -105, -6, -119, 39, +-113, 53, -85, 16, -78, 2, -104, 24, +-128, 42, -100, 26, -68, 14, -93, 23, +-125, 33, -109, 24, -75, 14, -83, 25, +-111, 40, -117, 26, -99, 11, -80, 22, +-88, 43, -112, 28, -116, 8, -85, 22, +-73, 37, -100, 19, -119, 14, -92, 37, +-73, 32, -93, -1, -110, 10, -97, 56, +-87, 42, -92, -8, -94, 7, -92, 49, +-99, 31, -97, 2, -80, 33, -87, 50, +-107, -3, -94, -19, -73, 55, -85, 73, +-106, 0, -97, -26, -74, 27, -84, 57, +-104, 33, -91, 18, -78, 14, -85, -4, +-96, 16, -92, 66, -80, 48, -78, -19, +-92, -16, -96, 43, -81, 55, -68, 19, +-81, 1, -102, 10, -97, 27, -72, 39, +-68, 34, -90, 7, -97, 1, -83, 27, +-72, 38, -70, 18, -79, 11, -94, 16, +-91, 18, -67, 23, -52, 27, -88, 18, +-111, 3, -74, 21, -46, 39, -73, 16, +-107, 2, -82, 23, -54, 30, -66, 6, +-88, 12, -83, 37, -75, 25, -73, -1, +-65, 14, -71, 36, -89, 18, -83, 8, +-58, 33, -61, 25, -87, -6, -93, 15, +-63, 50, -51, 29, -72, -12, -86, -3, +-76, 33, -58, 36, -58, 22, -72, 10, +-81, -3, -71, 6, -58, 39, -64, 46, +-75, 4, -69, -18, -61, 12, -67, 44, +-69, 27, -55, -1, -61, 3, -76, 16, +-70, 22, -49, 21, -57, 18, -80, 7, +-65, 4, -51, 27, -62, 28, -74, 5, +-60, 2, -52, 25, -61, 23, -64, 2, +-57, 5, -54, 22, -62, 20, -61, 8, +-56, 11, -56, 15, -62, 16, -58, 14, +-51, 11, -56, 10, -65, 16, -61, 22, +-55, 17, -50, 6, -57, 13, -64, 19, +-57, 15, -44, 13, -47, 14, -64, 6, +-61, 8, -50, 32, -51, 28, -60, -6, +-51, -9, -46, 32, -57, 34, -57, -6, +-39, -8, -42, 25, -62, 18, -55, -4, +-34, 14, -45, 30, -64, -2, -49, -9, +-34, 27, -50, 32, -69, -1, -46, -4, +-23, 23, -49, 20, -71, -5, -44, 7, +-23, 32, -41, 8, -65, -15, -54, 10, +-33, 41, -36, 18, -47, -18, -53, -2, +-47, 32, -38, 27, -37, -1, -40, -8, +-41, 9, -46, 20, -47, 12, -38, 10, +-33, 15, -47, 9, -58, -1, -39, 13, +-20, 28, -38, 12, -62, -11, -42, 0, +-16, 25, -36, 21, -57, -1, -42, 5, +-26, 15, -35, 1, -46, 7, -38, 30, +-30, 14, -38, -23, -39, -6, -29, 43, +-32, 35, -46, -21, -40, -25, -24, 27, +-25, 42, -37, 0, -42, -19, -30, 0, +-26, 20, -29, 18, -31, 13, -36, 4, +-32, -17, -26, -2, -25, 38, -30, 34, +-40, -13, -40, -24, -22, 19, -12, 39, +-31, 8, -55, -12, -32, 1, 3, 14, +-11, 7, -50, 1, -43, 4, -6, 8, +-10, 10, -40, 8, -44, 7, -16, 3, +-13, 6, -24, 7, -25, 9, -24, 3, +-31, -2, -27, 8, -6, 20, -18, 15, +-43, -10, -42, -1, -5, 24, 2, 23, +-33, -8, -47, -15, -15, 12, 11, 22, +-17, 9, -49, -4, -32, 1, 2, 11, +-2, 16, -31, 9, -32, -7, -10, -6, +-7, 14, -20, 23, -18, 1, -13, -10, +-20, 2, -20, 15, -11, 14, -9, 9, +-25, 4, -28, -2, -7, -1, 1, 16, +-18, 17, -20, -8, -7, -9, -9, 15, +-16, 15, -15, 0, -8, 5, -16, 19, +-20, 6, -8, -10, 3, 3, -13, 24, +-24, 9, -10, -6, 3, 5, -6, 11, +-24, 4, -17, 6, 4, 18, 1, 11, +-18, -13, -20, -6, -6, 29, 0, 31, +-4, -10, -11, -21, -10, 12, -10, 34, +-5, 8, 5, -11, 2, 0, -17, 11, +-20, 6, 10, 10, 20, 17, -15, 0, +-34, -17, 3, 9, 29, 41, -2, 12, +-30, -33, -6, -12, 19, 41, 9, 27, +-15, -15, -7, -18, 11, 12, 4, 16, +-1, 2, 3, 11, 7, 10, -7, -12, +-6, -10, 12, 31, 14, 37, -4, -15, +-9, -34, 5, 16, 20, 40, 8, 6, +-8, -16, -2, 3, 12, 13, 13, 0, +4, 10, 7, 19, 10, -4, 0, -19, +4, 7, 20, 33, 17, 7, -2, -21, +-7, 0, 17, 22, 26, 9, 5, -4, +-7, 6, 8, 13, 21, -2, 16, -6, +8, 13, 3, 25, 3, 2, 16, -19, +25, 3, 12, 29, -7, 17, 3, -11, +27, -6, 27, 12, 4, 13, -4, 7, +19, 4, 30, 0, 14, -4, 0, 11, +8, 25, 26, 3, 19, -16, 8, 1, +9, 29, 20, 14, 19, -15, 15, -10, +19, 17, 19, 19, 10, 0, 9, -5, +27, 1, 34, 5, 11, 9, 3, 6, +21, 0, 37, -5, 19, 10, -3, 20, +16, -1, 36, -10, 22, 9, 8, 17, +15, 5, 22, -3, 20, 4, 15, 14, +21, 12, 20, 4, 18, -8, 21, -3, +33, 9, 24, 21, 9, 4, 20, -19, +29, -2, 32, 18, 18, 20, 10, -3, +26, -17, 34, 2, 27, 15, 16, 10, +14, 2, 25, -2, 31, 0, 28, 3, +17, 12, 12, 11, 24, -2, 36, -7, +30, 3, 11, 16, 12, 8, 30, -3, +35, 1, 20, 12, 14, 6, 21, -1, +33, 0, 32, 10, 19, 5, 21, -5, +23, 8, 28, 8, 31, -4, 29, -3, +24, 13, 17, 11, 25, -9, 37, -4, +36, 12, 19, 7, 12, -5, 30, 1, +42, 15, 25, 3, 15, -16, 26, 1, +38, 20, 33, 6, 15, -11, 19, -2, +34, 12, 31, 9, 24, -3, 26, 1, +31, 0, 28, -5, 25, 0, 33, 12, +30, 9, 27, -12, 20, -10, 31, 6, +39, 17, 29, 4, 16, -11, 25, -7, +38, 12, 31, 14, 21, 0, 23, -5, +39, -6, 33, 2, 28, 6, 25, 10, +31, -6, 32, -12, 29, 5, 27, 19, +29, 0, 38, -22, 32, -7, 26, 14, +30, 10, 36, -10, 35, -13, 22, 4, +25, 8, 37, 0, 36, 0, 22, 0, +21, -7, 36, -5, 39, 13, 28, 5, +23, -14, 30, -7, 38, 10, 32, 5, +25, -7, 28, -1, 39, 0, 33, -3, +27, -4, 29, 4, 36, 1, 35, -3, +23, 0, 29, -1, 38, 3, 36, -2, +24, -3, 24, 3, 43, 0, 38, -6, +20, -4, 20, 9, 41, 5, 41, -7, +24, -9, 22, 2, 37, 6, 45, -3, +30, -9, 22, -8, 34, 3, 44, 5, +28, -2, 17, -7, 34, 0, 46, 3, +31, -3, 22, -9, 34, -2, 43, 0, +33, 2, 16, 3, 31, -10, 49, -7, +38, 8, 16, 3, 25, -13, 44, 0, +41, 10, 22, -2, 24, -13, 46, -5, +46, 1, 29, -2, 22, 0, 35, -3, +43, -7, 31, -1, 26, 4, 34, 1, +41, -6, 32, -8, 29, -7, 40, 5, +36, 10, 25, -9, 24, -13, 43, 1, +48, 6, 26, -3, 15, -3, 35, -4, +55, -10, 39, -4, 16, 7, 25, -1, +52, -13, 43, -3, 18, 2, 23, 1, +47, -2, 47, -8, 28, -11, 23, 2, +41, 3, 49, -9, 36, -8, 26, -1, +35, -5, 46, -8, 40, 2, 25, 1, +38, -15, 44, -2, 30, 6, 25, -3, +40, -6, 49, -2, 30, -4, 20, -3, +39, 0, 57, -7, 35, -4, 14, 3, +32, -2, 55, -8, 41, 3, 18, 1, +28, -10, 49, -5, 49, -1, 28, -7, +30, -9, 45, 2, 45, -6, 35, -16, +33, -3, 45, 3, 44, -6, 29, -7, +28, -2, 44, -4, 53, -4, 31, 3, +19, -7, 43, -11, 55, 4, 33, 5, +21, -8, 41, -7, 55, -5, 37, -7, +25, 1, 40, 2, 50, -10, 39, -11, +26, 6, 33, 2, 47, -8, 42, -3, +35, -5, 35, -10, 43, -2, 42, 2, +36, -9, 38, -9, 45, 1, 37, -1, +26, -5, 35, 0, 49, -2, 46, -10, +26, -3, 27, -3, 51, -8, 55, -2, +28, 0, 19, -9, 46, -7, 58, 4, +36, -7, 23, -10, 36, 4, 53, -4, +44, -14, 29, 1, 31, 6, 47, -14, +45, -8, 34, 5, 32, -1, 40, -9, +46, -5, 38, -5, 35, -6, 44, 0, +40, -1, 32, -14, 40, -4, 44, 8, +41, -8, 28, -6, 32, 4, 50, -7, +45, -10, 24, 7, 30, 1, 52, -17, +50, -9, 31, 4, 25, 0, 43, -7, +48, -4, 34, -3, 31, -4, 37, 3, +39, -4, 39, -7, 34, 6, 35, -2, +42, -14, 40, -1, 39, -1, 39, -10, +41, -5, 46, -5, 35, -9, 37, -7, +44, 8, 39, -2, 29, -14, 38, -2, +47, 7, 40, -7, 31, -9, 36, -2, +47, -4, 40, 0, 32, 1, 39, -15, +44, -10, 41, 7, 36, 4, 38, -15, +41, -9, 40, 0, 40, -4, 36, -1, +41, -3, 38, -10, 39, -10, 40, 4, +42, -1, 44, -12, 32, -1, 32, -2, +43, -5, 49, -1, 35, -2, 26, -12, +44, -7, 52, 5, 39, -8, 28, -12, +39, 1, 50, -3, 41, -10, 30, 0, +34, 2, 44, -11, 45, -8, 39, 2, +36, -7, 39, -9, 42, 0, 41, -3, +39, -10, 41, -2, 37, 1, 38, -11, +42, -6, 42, 2, 39, -5, 32, -2, +33, 1, 46, -10, 45, -6, 33, 5, +35, -6, 48, -14, 46, -3, 34, 1, +32, -6, 48, -5, 42, 0, 32, -11, +33, 0, 42, 8, 44, -9, 31, -11, +32, 5, 42, 4, 39, -7, 34, -3, +32, 3, 39, -6, 39, 2, 36, 6, +36, -10, 41, -14, 43, 3, 40, 2, +39, -12, 39, -4, 44, -5, 41, -7, +29, 6, 38, 4, 45, -8, 39, -9, +31, 3, 36, 3, 44, -3, 43, -2, +33, -5, 36, -9, 44, 1, 42, 3, +38, -7, 38, -5, 39, -2, 40, -8, +44, -4, 43, 4, 37, -7, 38, -16, +41, 2, 41, 5, 43, -11, 40, -7, +37, -2, 36, -5, 45, -5, 47, 3, +32, -5, 29, -9, 37, 6, 53, 0, +40, -6, 24, -2, 32, 2, 51, -6, +49, -3, 34, -2, 32, -6, 37, -1, +50, -2, 43, -4, 35, -6, 36, 2, +42, -3, 44, -9, 41, -2, 40, 0, +35, 0, 37, -1, 43, -4, 43, -6, +40, -1, 35, 5, 39, -9, 48, -12, +45, 4, 33, 5, 29, -7, 47, -7, +51, 1, 39, -8, 34, -6, 39, 6, +49, -11, 44, -13, 32, 11, 39, 4, +43, -14, 42, -12, 41, 5, 43, 2, +42, -6, 34, -3, 37, -5, 43, 0, +43, 7, 37, 1, 29, -8, 40, -6, +50, 5, 49, -1, 38, -11, 37, -13, +49, -4, 54, 4, 44, -6, 36, -18, +39, -3, 45, 11, 48, -3, 42, -12, +34, -2, 37, 0, 49, -3, 48, 3, +42, -8, 33, -15, 39, 0, 51, 12, +48, -6, 33, -15, 30, 4, 41, 11, +52, -9, 49, -12, 34, 0, 32, -1, +41, 2, 54, 1, 46, -9, 31, -12, +32, 7, 46, 12, 53, -11, 41, -18, +36, -2, 43, 9, 50, -4, 45, -13, +40, -6, 40, 6, 43, -1, 48, -13, +44, -5, 42, 0, 44, -5, 40, 1, +40, 3, 45, -12, 49, -11, 43, 11, +41, 2, 40, -21, 43, -5, 45, 20, +41, 2, 35, -19, 39, -4, 50, 8, +50, -5, 45, -11, 39, -2, 40, -6, +43, -1, 46, 12, 45, -1, 36, -20, +37, -7, 51, 15, 54, 4, 38, -18, +27, -7, 41, 11, 57, 4, 48, -10, +37, -11, 36, 1, 44, 1, 50, 2, +45, 1, 38, -9, 38, -13, 48, 6, +50, 12, 46, -15, 34, -17, 45, 6, +50, 11, 48, -18, 39, -10, 35, 17, +40, 4, 44, -13, 42, 4, 40, 8, +38, -8, 43, -5, 47, 9, 43, -5, +37, -13, 41, 9, 42, 15, 43, -17, +44, -18, 46, 10, 47, 9, 39, -13, +41, -12, 45, 10, 49, 1, 44, -12, +40, -4, 41, 4, 47, -7, 52, -6, +40, 11, 33, -2, 38, -15, 50, 4, +50, 21, 35, -7, 30, -22, 42, 9, +57, 17, 49, -12, 32, -16, 34, 8, +50, 3, 57, -13, 44, 2, 29, 10, +33, -10, 52, -11, 56, 15, +}; \ No newline at end of file diff --git a/project/realtek_ameba1_va0_example/example_sources/i2s/src/birds_22050_2ch_16b.c b/project/realtek_ameba1_va0_example/example_sources/i2s/src/birds_22050_2ch_16b.c new file mode 100644 index 0000000..ec5e9b5 --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/i2s/src/birds_22050_2ch_16b.c @@ -0,0 +1,16075 @@ +#include +int sample_size=64274; + +SECTION(".sdram.data") +short sample[]={ +-1, 1, 0, 0, -1, 2, 0, -1, +1, 1, -4, 4, -1, 0, 2, -1, +-1, 1, 1, -2, 1, 1, -3, 1, +1, -2, 2, -1, -2, 2, -4, 3, +1, -1, 0, -1, 0, -1, 5, -4, +1, -3, 2, -2, 1, 0, 2, -5, +2, -1, 0, 2, -3, 1, -1, 0, +3, -1, -2, 1, -2, 1, 4, -2, +-5, 3, -1, 0, 1, 1, -2, -1, +0, 1, 2, -1, 3, -4, 1, 0, +1, 2, -3, 0, 4, -3, 4, -1, +-2, 0, 2, -2, 3, 0, -1, -2, +3, -1, -1, 3, -2, -1, 3, -2, +4, -2, -1, -1, 2, -1, 1, 1, +-1, -2, 1, 1, 0, 0, -2, 0, +-2, 4, 0, 0, 1, -3, 0, 2, +0, 0, -1, 0, 0, 1, 3, -3, +0, -3, 5, -2, 1, 0, 0, -2, +3, 0, -2, 3, -5, 2, 1, 1, +0, 0, 1, -2, -1, 3, -2, 2, +-1, -1, 5, -4, 2, 0, -2, 0, +2, 0, -2, 3, -4, 2, 3, -2, +3, -3, -1, 0, -1, 2, 1, -3, +1, -1, -2, 3, -2, 1, 0, -1, +3, -2, -1, 1, -3, 2, -2, 3, +-4, 2, 0, 0, 1, 0, 0, 0, +-2, 2, -1, 2, -2, 2, -1, 0, +1, 1, -1, 1, 0, 0, 0, 1, +-1, -1, 3, -3, 2, 0, 0, -1, +2, -1, 1, -1, 0, 0, 2, -2, +3, -2, -1, 0, 1, -1, -1, 1, +-2, 1, 1, -1, 1, -1, -3, 2, +-2, 2, -3, 2, -1, 1, -2, 3, +-2, 1, 1, -2, 1, 0, -4, 4, +-5, 4, -1, 1, 1, -1, 0, 0, +1, -1, 0, 0, -1, 1, 1, 0, +1, -2, 1, 0, -2, 3, 0, -1, +-1, 2, -1, 1, 2, -2, 0, 1, +0, 0, 4, -4, 0, 1, 0, -1, +-1, 1, -3, 2, 2, -1, -3, 3, +-2, 2, -1, 2, -5, 4, -3, 2, +1, -1, -1, 0, 2, -3, 2, -1, +-2, 2, -3, 2, -1, 1, -3, 2, +-1, 1, -1, 2, -2, 1, 2, -2, +1, 0, -3, 3, -1, 0, 3, -2, +0, 0, 2, -3, 4, -3, 0, 0, +1, 0, 2, -1, -1, 1, -1, 2, +1, -1, -3, 3, 0, -1, 1, -1, +-1, 0, 2, -1, 0, 0, -2, 3, +-3, 4, -3, 2, -1, 0, -1, 2, +-5, 5, -4, 3, -3, 4, -3, 2, +-3, 3, -5, 5, -3, 1, -2, 2, +-4, 4, -1, -1, 4, -4, 3, -3, +2, -3, 1, -1, 2, -2, 1, 0, +-1, 1, 0, 1, 0, -1, 1, 0, +-3, 5, -4, 3, -1, 0, 2, -2, +3, -3, 1, 1, -2, 2, 1, -2, +2, -1, 0, 1, 0, 0, 0, 0, +0, 0, -1, 1, 1, -1, 2, -1, +-1, 1, -2, 2, 1, -1, 0, 1, +-4, 3, 0, 0, -1, 0, 2, -2, +0, 0, -1, -1, 3, -3, 2, -2, +1, -2, -1, 1, 0, -1, 4, -5, +5, -4, 1, 0, 1, -1, -1, 1, +-2, 2, -3, 4, -4, 3, 3, -2, +0, 1, 1, -1, 2, -1, 1, -1, +1, 0, -1, 2, -2, 2, -1, 1, +0, 1, -1, 2, -2, 1, 1, -2, +1, 0, -1, 2, -3, 3, 0, -1, +1, 0, -2, 2, 1, -2, 2, -2, +-1, 1, 0, 0, 0, 0, -1, 1, +-3, 2, -2, 1, -2, 2, -2, 0, +1, -2, 1, -2, 0, 2, -6, 5, +-2, 0, 3, -4, 5, -5, 2, -2, +3, -2, -1, 3, -4, 4, 0, 0, +3, -3, 2, 0, -2, 2, 3, -3, +3, -3, 1, 0, -1, 1, 1, -1, +1, 0, 0, 0, 1, 0, 1, -1, +0, 2, -2, 1, 1, -1, 1, -1, +2, -2, 1, -1, 1, -1, -3, 3, +-3, 1, 2, -2, 2, -3, 2, -2, +0, 0, 1, -1, -1, 2, -3, 2, +1, -2, 0, 1, -1, 0, 1, -2, +1, 0, 0, 0, -1, 1, -2, 2, +1, -2, 2, -2, 2, -1, 2, -2, +1, 0, 0, 0, 3, -2, 2, -2, +3, -2, 2, -1, 1, -1, 4, -4, +5, -4, 4, -4, 2, 0, -2, 3, +-2, 1, 2, -3, 3, -2, 0, 0, +0, 0, 2, -2, -2, 2, -1, 0, +0, 1, -4, 3, 0, 0, 0, 0, +-1, 0, -2, 2, -4, 2, 0, -1, +-1, 2, -2, 1, 1, -2, 3, -3, +4, -4, 2, -1, 0, 0, 0, 1, +-3, 3, 1, -1, 0, 1, -1, 1, +0, 2, -3, 4, -1, 0, 3, -2, +3, -3, 4, -2, 0, 0, 3, -3, +1, 0, 2, -2, 3, -2, -2, 2, +-2, 2, -1, 1, 0, 0, -2, 3, +-3, 3, -1, 0, 2, -2, 0, 0, +-2, 2, -2, 1, 1, -3, 3, -2, +-1, 0, 1, -2, 0, 1, 0, 0, +-2, 2, -3, 3, 0, 0, 0, -1, +-1, 2, -1, 1, 0, 0, 0, 0, +2, -1, -3, 3, 0, 0, 0, 1, +-3, 3, -1, 2, 0, 0, 1, -1, +1, 0, 0, 0, 0, 0, 2, -1, +3, -2, -1, 1, 3, -2, -1, 2, +-2, 1, 1, 0, -1, 1, -4, 4, +-2, 0, 4, -5, -2, 3, -2, 1, +2, -3, 1, -2, 1, 0, -2, 1, +0, -1, -1, 2, -4, 3, -1, 0, +-1, 2, -3, 2, -1, 0, 0, 1, +0, -2, 3, -3, 3, -2, 2, -1, +-1, 2, 0, 0, -1, 1, 0, 0, +-1, 3, -3, 2, 1, -1, 3, -2, +0, 1, -1, 1, 0, 2, -5, 6, +-2, 1, 1, 0, -4, 4, 1, -2, +3, -1, -2, 1, 3, -2, -2, 3, +-4, 2, -1, 2, -3, 3, -2, 1, +-3, 4, -3, 1, 2, -3, 1, -1, +2, -3, 3, -3, 3, -3, 1, -2, +0, 0, -2, 2, 0, -1, -1, 1, +2, -2, 0, 1, -2, 1, 1, -1, +1, -2, 3, -2, 0, 0, 1, -2, +3, -2, -1, 2, -3, 3, -1, 1, +2, -2, 2, -2, 1, -1, 1, -1, +1, -1, 1, 0, 1, -1, 0, -1, +0, 1, -1, 1, -2, 1, 1, -2, +3, -4, 2, -2, 0, 1, -2, 3, +-7, 6, -4, 3, -1, 1, -2, 1, +1, -1, 2, -2, 0, 0, -1, 2, +0, -1, -1, 0, 0, 0, 1, -1, +-3, 2, 0, 0, 2, -2, 1, -2, +2, 0, -3, 3, 1, -3, 3, 0, +-1, 0, 2, -3, 3, -2, 1, -1, +1, -1, 2, -1, 0, 1, -3, 2, +1, 0, 0, 1, -2, 1, 1, -1, +1, 0, -3, 2, 3, -3, -2, 3, +-5, 4, -1, 3, -4, 2, 3, -5, +5, -4, 2, -2, -1, 1, 1, 0, +-3, 3, -4, 2, 2, -2, 1, -1, +-1, 0, -1, 2, -6, 5, -2, 0, +5, -4, 0, -1, 3, -4, 4, -3, +0, -1, 1, -1, -1, 2, -3, 2, +-2, 3, -2, 2, 2, -2, 1, 0, +0, 0, 1, -1, 1, -2, 4, -3, +1, -1, 0, 1, -4, 5, -3, 2, +0, 0, 2, -2, -1, 2, -1, 0, +0, 0, -2, 2, -2, 2, -3, 2, +-2, 2, 0, 0, 1, -1, -1, 2, +0, -1, 1, -1, -2, 1, 0, -1, +2, -2, -1, 2, -4, 3, -2, 1, +-3, 4, -4, 3, 1, -3, 5, -3, +-1, 1, 2, -4, 4, -2, 0, 0, +0, 0, 1, -1, 1, 0, 0, -1, +3, -2, 1, 0, 0, -1, 0, 1, +-1, 1, -1, 0, 2, -2, 1, -1, +2, -2, 2, 0, -1, 0, 0, -1, +-1, 3, -3, 2, 2, -4, 4, -2, +-2, 3, -3, 2, 0, 1, 0, 0, +1, -1, 0, 1, -1, -1, 1, -1, +1, 0, 2, -2, -1, 2, -1, 1, +2, -2, -3, 3, 2, -3, 2, -1, +-3, 3, 1, -1, 1, 0, -3, 2, +0, 0, -2, 2, -1, 0, 2, -1, +-1, 1, 0, -1, 3, -2, 0, 1, +-3, 2, 1, 0, -2, 1, 0, -1, +1, 0, -1, 1, -2, 1, 2, -2, +0, 1, -4, 3, 1, -2, 0, 1, +-1, 0, 1, -1, 2, -4, 3, -2, +0, 0, 2, -3, 1, 0, 0, 0, +0, -1, 1, -1, 1, 0, 0, -1, +3, -4, 4, -3, -1, 2, 0, -1, +1, 0, -2, 2, 0, 0, -2, 3, +-3, 3, -1, -1, 4, -3, 1, 0, +2, -3, -1, 2, -1, -1, 2, 0, +-3, 3, 0, -1, 0, 0, -2, 3, +-2, 1, 1, -1, 1, -1, 5, -6, +4, -2, -2, 2, -2, 1, -2, 2, +-4, 4, -3, 2, -2, 2, 1, -2, +3, -2, -1, 1, 0, -1, 0, 1, +0, -2, 1, 0, -3, 3, 0, -1, +0, 0, 2, -2, 0, 1, -2, 2, +0, 0, 1, -1, -3, 3, -1, 1, +0, 0, 0, -1, 2, -1, 1, -2, +2, -2, 1, -1, 0, 1, -1, 1, +0, 1, -3, 3, -2, 1, 3, -3, +2, -1, -3, 3, -1, 1, -3, 3, +-2, 1, 1, -1, 0, -1, 1, -1, +0, 0, 0, -1, 1, -2, 2, -1, +-1, 0, 0, 0, 0, 1, -2, 1, +-2, 1, -1, 1, -1, 0, 1, -1, +2, -1, -2, 2, 0, -1, 3, -1, +1, -2, 1, -1, 0, 1, 0, 0, +0, 0, 0, 0, 0, 1, -4, 5, +-1, 0, 0, 0, -1, 0, 2, -1, +0, 1, -2, 1, 1, -1, -2, 2, +-1, 0, 2, -2, 2, -3, 0, 0, +0, 0, 0, 1, -1, 0, 0, 1, +-6, 6, -5, 4, -1, 1, -2, 1, +0, -1, 1, -1, -1, 1, -2, 1, +0, 0, 0, -1, 4, -5, 3, -2, +2, -2, 3, -3, 1, 0, 2, -2, +3, -2, -2, 3, -3, 3, -4, 4, +-3, 2, 0, 1, -1, 1, 0, 0, +0, 0, -2, 2, -3, 3, -2, 2, +-3, 2, -1, 1, 0, 0, -1, 0, +-1, 2, -2, 2, -3, 2, -1, 0, +2, -2, 1, -1, 1, -2, 3, -2, +-2, 2, 1, -2, 1, 1, -1, 0, +1, -1, -1, 1, -2, 1, -2, 2, +0, 0, -2, 3, -3, 2, 0, 1, +-3, 3, -1, 1, 1, -1, 3, -3, +3, -1, 0, 0, 1, -2, 0, 0, +2, -3, 2, -1, 0, -1, 2, -2, +1, -2, 3, -3, 0, 1, -1, -1, +2, -2, 0, 1, 0, -1, 2, -2, +0, 0, -1, 1, 1, -1, -1, 3, +-4, 2, 0, 0, 0, 0, 2, -2, +-2, 3, -1, 1, 0, 0, -2, 2, +-1, 1, 1, -2, 3, -4, 3, -2, +0, 0, 0, 0, 0, 0, 2, -2, +2, -1, -1, 3, -2, 1, 3, -3, +1, 0, 2, -2, 0, 1, 1, -2, +4, -2, -1, 1, 2, -2, 1, 0, +-1, 0, 1, -1, 0, 0, 0, -1, +1, -1, 0, 1, -2, 1, 2, -2, +0, 1, -1, 1, -2, 3, -3, 2, +2, -3, 2, -1, -1, 1, 0, -1, +-1, 2, 0, 0, -1, 2, -4, 3, +1, -1, 0, 0, 1, -1, 1, 0, +1, -2, 1, -1, 2, -2, 0, 1, +-1, 1, 0, 1, -3, 2, 2, -2, +2, -1, 1, -2, 0, 1, -1, 2, +-2, 1, 0, 0, -2, 3, -5, 5, +-3, 2, 0, 0, 1, -2, 1, 0, +0, 0, 0, -1, -1, 1, 0, 0, +0, 0, -1, 2, -3, 3, -1, 0, +0, 1, -2, 1, 1, -2, 2, -3, +4, -4, 3, -3, 2, -2, 2, -1, +0, -1, 3, -3, 0, 1, -4, 4, +-3, 2, 2, -3, 3, -2, -2, 2, +-2, 3, -4, 3, 1, -2, 1, 0, +-3, 2, 2, -2, 0, 1, 1, -2, +4, -3, 0, 0, 2, -3, 2, -2, +2, -2, 0, 0, -4, 4, -3, 3, +-2, 1, 0, 0, 1, -2, 2, -2, +-1, 1, 0, -1, 1, 0, 0, 0, +1, -1, 3, -3, 1, 1, -4, 3, +-1, 0, 0, 1, -1, 1, 0, 0, +-1, 1, -1, 0, -1, 2, -2, 1, +2, -2, 2, -1, 1, -1, 0, 0, +-1, 1, -1, 1, -1, 0, 2, -1, +-2, 2, -1, 0, 1, 0, 1, -2, +0, 1, -3, 3, 1, -2, 1, -1, +0, 0, -3, 4, -2, 1, 2, -1, +0, 0, 4, -5, 2, 0, -2, 1, +0, 1, -1, 0, 4, -5, 3, -2, +-1, 2, -1, 1, 0, 0, 2, -1, +-1, 1, -1, 0, -1, 1, 2, -4, +5, -3, -3, 3, -1, 0, -1, 1, +1, -1, -1, 1, -3, 3, -3, 3, +-1, 0, 0, 1, 1, -2, 2, -2, +-3, 3, -1, 1, 2, -3, 4, -4, +2, -1, -1, 1, 1, -2, 2, -2, +1, -1, 1, -1, 1, 0, 0, -1, +1, -1, -2, 2, 0, -1, 1, 0, +-1, 1, 0, 0, -2, 2, -3, 3, +-5, 4, -3, 3, 0, -1, 0, 0, +-1, 1, -1, 2, -3, 2, 1, 0, +-1, 1, 2, -2, 1, 0, -1, 0, +0, 1, 0, 0, 3, -3, 3, -3, +2, -2, -1, 1, 0, 0, 1, -1, +0, -1, 2, -2, 2, -1, -1, 1, +-2, 1, 3, -4, 2, -2, 2, -3, +2, -1, -1, 1, 2, -2, 0, 1, +-1, 0, 2, -2, 3, -3, 2, -1, +2, -2, 5, -5, 2, -2, 2, -1, +-1, 2, -1, 0, 2, -2, 1, 0, +1, -2, 4, -4, 1, 1, -4, 3, +-1, 1, 0, 0, 1, -1, -2, 3, +-1, 0, 1, -1, 2, -3, 5, -4, +-1, 1, -1, 1, 0, 0, 0, -1, +0, 1, -4, 4, -1, 0, 4, -3, +-1, 1, -1, 1, -1, 2, -2, 1, +2, -3, 3, -2, -1, 1, -2, 2, +-2, 1, 1, -2, 2, -1, 0, 1, +0, -1, 2, -1, -3, 3, 0, -1, +1, 0, -1, 0, 0, 0, 0, 0, +0, 0, 0, -1, 2, -2, 2, -2, +0, 0, 1, -1, 2, -1, -1, 1, +-1, 1, -2, 3, -2, 1, -1, 2, +-3, 2, 0, 0, -2, 3, -1, 0, +0, 0, 0, 0, 0, 0, 0, 1, +-3, 3, 0, -2, 3, -3, 2, -2, +1, 0, -4, 4, -1, -1, 1, 0, +-2, 2, 0, 0, -2, 2, 0, -1, +1, 0, -1, 1, -1, 1, -2, 3, +-2, 2, -1, 0, 1, -2, 2, -2, +0, 0, 1, -1, 2, -1, 0, 0, +1, -2, 3, -2, -2, 3, -1, 0, +0, 1, -2, 1, 1, -1, 1, -1, +2, -3, 1, 0, -2, 1, 0, 0, +4, -5, 2, 0, -5, 4, 1, -2, +1, -1, 1, -1, -1, 1, 1, -2, +2, -1, 1, -2, 1, -1, -2, 2, +-2, 2, -2, 2, -2, 2, 0, 0, +1, -1, 2, -2, 1, 0, -3, 3, +-1, 0, 1, -1, -1, 0, 2, -2, +0, 0, -2, 2, -1, 0, 2, -2, +1, -1, 1, 0, -3, 3, -2, 0, +0, 0, -1, 0, 2, -1, -1, 2, +0, -1, 1, -2, 4, -4, 0, 1, +-1, 0, 1, -1, 1, -1, -1, 2, +0, 0, 0, 1, -1, 0, 3, -3, +0, 1, -3, 2, 3, -3, 1, 0, +-3, 3, -2, 1, 1, -2, 2, -2, +1, -1, -1, 1, -1, 0, -1, 1, +-2, 1, 0, -1, 1, 0, 2, -3, +2, -1, -2, 2, 2, -3, 1, 0, +-2, 2, 0, -1, 0, 0, -3, 4, +-4, 3, 2, -3, 2, -1, -3, 3, +-3, 2, 1, -1, 0, 0, -1, 1, +-2, 2, 1, -1, -1, 2, -2, 2, +-1, 2, -3, 2, 2, -2, 1, 0, +-1, 1, -3, 3, -1, 0, 3, -3, +2, -3, 2, -2, 0, 0, 0, -1, +1, -1, 1, -1, 1, -1, 0, 1, +-2, 2, -1, 1, -2, 3, -3, 2, +0, -1, 1, -1, 2, -2, 1, 0, +-2, 2, -2, 2, -2, 2, -1, 0, +2, -2, -1, 2, -1, 0, 0, 1, +-3, 2, 0, 1, -4, 3, 0, -2, +0, 1, -2, 1, 1, -1, 2, -2, +1, 0, -2, 2, -2, 2, -2, 2, +1, -2, 2, -1, -1, 1, 0, -1, +0, 2, -3, 3, -1, 1, -1, 1, +2, -3, 2, -2, 0, 0, 0, 0, +1, -2, 1, -2, 4, -4, 2, -1, +-1, 1, -1, 1, 0, -1, 0, 0, +0, 0, 1, -1, 0, 0, 3, -3, +-1, 2, -2, 1, 0, 0, -4, 3, +-1, 1, -3, 4, -1, -1, 3, -2, +0, 0, 0, 0, 0, 0, -2, 3, +-4, 2, 2, -1, -3, 3, 0, -1, +0, 1, -1, 1, -2, 2, 0, 0, +1, -1, -1, 0, 3, -3, 4, -5, +4, -2, -2, 2, 2, -3, 1, 0, +-2, 1, 0, 0, 0, 0, 0, -1, +1, -1, 0, 1, -3, 3, -2, 3, +-4, 3, 1, -2, 0, 1, -1, 0, +2, -2, 1, -1, 0, 1, 0, -1, +2, -2, -2, 4, -6, 5, -1, 0, +1, 0, 1, -2, 1, -1, -1, 2, +-2, 2, -3, 4, -2, 1, 1, 0, +-2, 1, 2, -3, 1, 1, 0, -1, +4, -4, 0, 2, -3, 3, 0, 0, +1, -1, 0, 0, 1, -1, 0, 1, +-3, 4, -2, 1, 1, -2, 2, -1, +-1, 3, -3, 2, 0, 0, 1, -2, +4, -4, 1, -1, 2, -2, 1, -1, +1, 0, 0, -1, 3, -3, 0, 0, +2, -2, 2, -1, 1, -2, 4, -4, +-1, 2, -2, 1, 1, -1, 0, 0, +1, 0, -1, 0, 1, -1, 1, -2, +3, -3, 1, -1, 0, 0, 0, 0, +1, -1, 1, 0, -1, 1, 1, -2, +0, 0, 1, -1, -1, 3, -3, 1, +3, -2, -4, 5, -2, 0, 2, -1, +-2, 2, -3, 3, -3, 2, 2, -3, +3, -2, 1, -2, 1, -1, -2, 3, +-1, 0, 1, 0, -3, 4, -3, 2, +-2, 2, -3, 2, -2, 2, 0, -1, +2, -1, -2, 2, 0, 0, -1, 2, +-2, 1, -1, 1, 0, 0, 0, 0, +0, -1, 2, -2, 0, 0, -1, 2, +-3, 3, 1, -3, 2, 0, -5, 5, +1, -2, 2, -1, -1, 0, 1, -1, +-2, 2, 2, -2, 0, 1, -2, 1, +1, -1, 1, -2, 1, 0, -2, 2, +2, -3, 5, -5, 0, 3, -6, 5, +0, -1, 2, -2, 3, -3, 2, -1, +1, -1, 0, 1, -3, 3, -1, 1, +0, -1, 3, -3, 1, 0, -1, 0, +2, -2, -1, 1, 2, -3, 2, -1, +-1, 1, 2, -2, 0, 1, -2, 2, +-2, 1, 2, -1, -2, 3, 0, -2, +2, -1, 0, -1, 4, -3, -1, 2, +2, -3, 4, -3, 1, -1, 3, -4, +4, -3, -1, 2, -2, 1, 2, -3, +1, 0, 1, -2, 4, -4, 2, -1, +-2, 2, 0, 0, 0, 0, -1, 0, +0, 0, -2, 1, 0, -1, -2, 2, +1, -3, 4, -3, 0, 0, 1, -2, +2, -2, 2, -2, 2, 0, -1, 1, +0, 0, 0, 0, 1, 0, -1, 1, +2, -2, 2, -1, 0, 0, 1, 0, +-1, 1, -2, 2, -1, 1, 1, -1, +0, 1, -1, 0, 0, 0, 0, -1, +2, -2, -1, 2, 0, -1, 0, 1, +-4, 4, -2, 1, 1, -2, 1, -1, +1, -1, 0, 1, -3, 3, -1, 0, +3, -3, 0, 1, -1, 0, 0, 1, +-2, 2, -3, 4, -4, 3, 0, 0, +-2, 1, 3, -4, 4, -3, 1, -1, +2, -2, 1, -1, -1, 2, -2, 1, +3, -4, 3, -2, -1, 1, 0, 0, +-1, 2, -2, 2, 0, 0, -1, 1, +0, -1, 2, -2, 2, -2, 0, 1, +-1, 1, 0, 0, 0, 1, -1, 1, +1, -2, 0, 0, 0, -1, 1, 0, +-3, 3, 0, -1, 2, -2, 1, -1, +1, -1, -2, 3, -1, -1, 4, -3, +-1, 2, -2, 1, 0, 0, -2, 2, +0, -1, 0, 1, -3, 2, 1, -1, +0, 0, -1, 2, -3, 2, 2, -3, +2, -1, 0, 1, 0, -1, 5, -5, +2, -1, 1, -1, 4, -4, 3, -3, +0, 0, 1, -2, 4, -3, -1, 2, +-2, 1, 0, 0, 1, -1, 3, -3, +1, 0, -1, 1, -1, 1, 0, 0, +0, 1, -2, 1, 3, -3, 2, -1, +0, 0, -1, 2, -1, 0, 1, -1, +0, -1, 1, -1, -2, 2, -3, 2, +-1, 1, 1, -2, 3, -3, 1, 0, +0, -1, 3, -3, 3, -3, 2, -1, +-1, 1, 0, 1, -3, 3, -1, 0, +1, 0, -2, 2, 0, -1, 1, -1, +-1, 0, 1, -1, -1, 0, 2, -3, +-1, 3, -4, 2, 3, -3, 1, 0, +0, 0, -1, 1, 1, -2, 2, -1, +-2, 2, 2, -4, 5, -4, 3, -2, +1, 0, 0, 0, 1, -1, -1, 2, +-1, 0, 2, -2, 2, -1, -2, 2, +-2, 1, 0, 1, -3, 3, 1, -1, +0, 2, -4, 4, -1, 0, 1, -1, +2, -2, 0, 0, 1, -2, 2, -2, +0, -1, 0, 1, -5, 5, -1, -1, +1, -1, 1, -2, 4, -3, 2, -1, +0, 0, 1, -1, 0, 0, -1, 0, +2, -2, 2, -2, 3, -2, -1, 2, +-1, 0, 1, 0, -2, 2, 0, -2, +4, -3, 0, 1, 1, -1, -1, 3, +-4, 3, -2, 2, -4, 3, 1, -1, +-1, 2, 0, 0, 1, 0, -2, 2, +0, -1, 2, -1, -1, 2, -1, 0, +0, 1, -3, 3, 1, -2, 4, -3, +0, 1, -1, 1, -1, 1, -4, 4, +0, -1, 1, 0, 0, -1, 2, -1, +-3, 3, 0, -1, 5, -4, 3, -2, +1, -1, 1, -1, 1, -1, 0, 1, +1, -2, 2, 0, -3, 3, -1, 1, +-2, 2, -1, 0, 1, -1, 0, 0, +2, -3, 2, 0, -2, 2, 0, -1, +0, 1, -3, 3, -2, 1, -1, 2, +-5, 5, -4, 3, -3, 3, 0, -2, +3, -2, -1, 1, 3, -4, 3, -3, +2, -3, 3, -1, -3, 3, -1, -1, +4, -3, 0, 0, -1, 1, -1, 1, +-4, 5, -5, 4, -1, 1, 0, 0, +-1, 2, -3, 3, 0, -2, 6, -6, +2, -1, -2, 2, 0, -1, 3, -2, +-2, 3, -2, 1, 2, -2, 0, 1, +-1, 1, 2, -2, 1, -1, 1, -1, +1, 0, -2, 2, -2, 1, 0, 0, +-1, 1, 0, 0, 0, 0, 0, 1, +-4, 3, 2, -4, 4, -3, 2, -2, +2, -1, -1, 1, 0, -1, 0, 1, +-2, 2, -1, 1, -3, 3, -2, 2, +0, 1, -2, 2, 1, -2, 1, 0, +-4, 4, -4, 4, -4, 3, -2, 1, +-1, 2, -2, 2, -1, 1, 0, 0, +1, -1, -1, 1, -1, 1, 0, 0, +2, -2, 2, -1, -1, 1, 0, -1, +0, 1, 0, 0, 3, -3, 1, -1, +1, -2, 2, -2, 2, -2, 4, -4, +2, -1, 1, -1, 0, 1, -2, 2, +-2, 1, 1, -2, 3, -3, 2, -3, +4, -4, 0, 0, 0, -1, 3, -3, +5, -4, 1, 1, -2, 1, 0, 0, +0, 0, 0, 0, -1, 0, 1, 0, +-1, 2, -2, 2, -1, 1, -1, 1, +1, -2, 0, 2, -2, 0, 3, -3, +2, -2, 0, 1, -3, 3, 0, -1, +2, -2, 1, 0, -2, 2, 0, -1, +0, 1, -3, 3, -4, 4, 0, -2, +2, 0, -4, 5, -3, 2, -3, 4, +-2, 1, 1, -1, -2, 2, 1, -1, +0, 0, -1, 1, 0, 0, 0, 0, +-1, 2, -1, 1, 1, -1, 2, -3, +4, -4, 0, 0, -2, 1, 1, -1, +0, 1, 0, 0, 1, -1, 1, -1, +0, 0, -1, 1, 1, -1, 0, 1, +-2, 3, -4, 4, -3, 1, 0, 0, +1, -1, 5, -5, 2, 1, -5, 4, +0, -2, 0, 0, -2, 2, -3, 3, +-3, 4, 0, 0, 1, 0, -3, 2, +1, -3, 2, -1, 2, -1, 1, 1, +-2, 2, 0, -2, 2, -2, -1, 1, +1, 0, -1, 2, 0, -1, 4, -4, +4, -4, 1, -1, -2, 2, -2, 3, +-3, 4, 0, -1, 3, -3, -2, 2, +-2, 1, -2, 2, -2, 2, 1, 0, +1, -1, 0, 0, -3, 2, -2, 1, +-3, 4, -1, 1, 2, 0, -1, 1, +-1, 0, -2, 0, 1, -1, -2, 3, +2, -2, 1, 2, -5, 4, 1, -4, +1, -2, 2, -3, 5, -4, 3, -1, +0, 2, -2, 2, -3, 2, -2, 0, +2, -2, 3, -2, 4, -2, 0, 1, +-2, 1, -3, 2, -2, 1, -1, 3, +0, 1, 2, -1, -1, 1, -4, 3, +-4, 2, 1, -2, 1, 1, 1, 0, +2, 0, -3, 2, -2, -1, -1, 1, +-4, 4, 0, 1, 0, 2, -3, 3, +-3, 2, -3, 1, -1, 0, 2, -1, +2, -1, 4, -3, -1, 2, -5, 3, +-5, 4, -3, 1, 4, -2, 0, 3, +-1, 3, -5, 4, -2, -2, -1, 1, +-2, 2, -1, 3, -3, 5, -3, 3, +-3, 0, -1, -2, -1, 0, 1, 0, +1, 1, 0, 2, -4, 4, -4, 1, +0, -3, 3, -2, 1, 1, 4, -1, +-1, 3, -3, 1, -4, 3, -4, 2, +-1, 3, -3, 4, 2, -1, 2, -1, +-3, 1, -4, 1, -2, 1, -1, 2, +2, 0, 5, -3, 2, -2, -3, 1, +-5, 2, 1, -3, 4, -2, 5, -2, +3, -1, -1, 0, -4, 2, -4, 1, +1, 0, 1, 2, 1, 2, -1, 2, +-3, 2, -4, 0, 1, -3, 1, 1, +3, -1, 3, 0, -1, 1, -4, 1, +-3, 0, -3, 3, -2, 3, 3, 0, +1, 1, -1, 0, -3, -1, -1, -1, +1, -2, 4, -1, 2, 1, 1, 0, +-3, 1, -3, -1, -3, 1, 1, -1, +4, 0, 2, 0, 0, 0, -4, 0, +-2, -2, -2, 0, 4, -3, 5, 0, +1, 1, 1, -2, -4, 0, -4, 0, +-1, 1, 3, -1, 6, -1, 2, -1, +-2, 1, -5, 1, 1, -4, 2, 0, +4, 0, 5, -1, -3, 4, -5, 0, +-4, 1, -4, 2, 3, 0, 4, 0, +4, 0, -2, 1, -3, -2, -1, -2, +-1, 1, 2, 0, 6, -2, 2, -1, +3, -6, -2, -1, -4, 1, 2, -1, +7, -3, 5, 0, 1, -2, 0, -2, +-5, 1, -2, 0, 2, 1, 4, 1, +1, 2, -2, 1, -4, -1, -2, -2, +-1, 1, 3, 0, 5, 0, 2, 0, +-1, -1, -5, -1, 0, -4, 3, -1, +3, 2, 1, 4, -3, 2, -1, -3, +-3, -1, -4, 2, -2, 3, 6, -2, +3, 2, -3, 1, -2, -2, -6, 2, +1, -3, 5, 1, 1, 3, 4, -3, +-1, -1, -5, 0, -3, -1, 2, 0, +4, 1, 5, -1, -1, 2, -6, 2, +-6, 0, -4, 2, 3, -2, 9, -4, +5, -2, 2, -3, -5, 1, -4, -2, +2, -3, 6, -2, 6, 0, 2, 1, +-4, 2, -6, -1, 2, -6, 4, -2, +4, 1, 6, -2, 2, -1, -3, -1, +-1, -6, 1, -3, -1, 4, 0, 5, +2, 2, 0, -1, -6, 2, -9, 3, +-2, 1, 4, 0, 6, 0, 3, 0, +-3, 1, -5, -1, -5, 2, -2, 2, +5, 0, 5, 0, 2, 0, -8, 5, +-11, 4, -4, 0, 5, -3, 7, 0, +4, 0, 0, -1, -8, 3, -6, 0, +0, -1, 5, -2, 8, -1, 1, 1, +-2, 0, -9, 4, -8, 3, -2, 2, +7, -3, 10, -4, 4, -2, -3, 0, +-9, 3, -3, -1, 3, 1, 4, 1, +5, 0, -1, 0, -2, -3, -5, 0, +-1, 0, 4, 0, 5, 1, 4, -1, +-3, 2, -5, -2, -3, 0, -2, 1, +5, 0, 4, 1, 4, -3, -3, 0, +-5, -2, -2, 0, -1, 2, 8, -4, +7, -1, -2, 1, -6, 0, -5, -1, +0, -2, 4, 0, 5, 1, 3, 1, +-5, 3, -6, -1, -5, 1, -2, 2, +4, 1, 5, 1, 2, 0, -5, 1, +-4, -3, -1, -1, 0, 1, 5, 2, +1, 3, -1, 0, -6, 2, -7, 1, +-3, 1, 3, 0, 5, 1, 4, -1, +-1, 0, -4, -3, -2, -2, -1, 2, +4, 1, 6, -1, 3, -1, -4, 1, +-6, 0, -5, 1, 3, -2, 8, -1, +4, 1, 1, -1, -2, -2, -4, -1, +0, -3, 6, -1, 4, 2, 4, 0, +-3, 3, -6, -1, -3, -2, -2, 3, +1, 3, 5, 0, 2, 0, -2, -2, +-4, -1, -2, -2, 4, -1, 2, 3, +3, 2, 1, -1, -3, -1, -6, 1, +-1, -1, 5, -2, 7, 0, 0, 4, +-5, 3, -5, -1, -2, -2, 0, 0, +6, -3, 10, -4, 5, -2, -3, 0, +-4, -2, -6, 3, 0, -1, 10, -4, +5, 0, -1, 2, -6, 1, -5, -1, +-3, 1, 4, -1, 8, -2, 3, 2, +-5, 4, -5, 0, -5, 1, 0, -1, +7, -3, 7, -1, 2, 1, -1, -3, +-4, 0, -6, 1, 2, -1, 3, 3, +2, 2, -1, 1, -7, 2, -3, -4, +3, -4, 4, -1, 8, -2, 4, -1, +1, -3, -4, 0, -7, 2, -2, 1, +5, 0, 6, -1, 3, -1, -2, 1, +-8, 3, -7, 2, 1, 0, 6, -1, +6, -1, 0, 1, -5, 1, -7, 1, +-3, 1, 1, 2, 4, 1, 2, 3, +-4, 3, -7, 3, -7, 3, -2, 3, +1, 3, 4, 1, 2, 1, -3, 0, +-6, 1, -4, -1, 2, -1, 2, 2, +3, 0, 2, -1, -5, 1, -5, -2, +0, -2, 1, 1, 7, -3, 8, -4, +1, -1, -3, -1, -5, 2, -3, 1, +6, -1, 5, 0, 5, -3, 2, -4, +-1, -2, -6, 4, -1, 1, 5, 0, +3, 0, 1, -1, -4, -1, -4, -1, +-3, 0, 5, -4, 4, 1, 2, -1, +2, -3, -4, 1, -4, 0, -1, 1, +2, 2, 5, 0, 5, -2, 1, -2, +1, -5, 3, -5, 3, -1, 4, 1, +2, 2, -1, 1, -4, 0, -3, -3, +4, -7, 3, -1, 2, 1, 3, 0, +-1, 0, -3, -1, -4, 0, 1, -1, +2, 3, 1, 3, 1, 2, -2, 1, +-3, 1, 0, -2, 2, 0, 3, 0, +7, -3, 0, 2, -3, -1, -3, -1, +-4, 1, 0, 1, 3, 0, 0, 2, +-2, -1, -1, -2, -6, 2, 0, -2, +1, 2, 1, 1, 3, -1, 0, -1, +2, -5, -2, 2, -1, 1, 5, -1, +3, 2, -2, 4, -3, 0, -1, -2, +-1, 0, -2, 4, -1, 2, 7, -6, +3, -2, -6, 2, -4, -1, 0, -1, +0, 1, 3, -1, 3, -2, -1, 0, +-2, -1, -1, -1, 1, 0, 4, 0, +4, 0, 1, 2, -2, 1, 0, -1, +1, -1, 5, -3, 3, 2, 0, 2, +0, 0, -4, 1, -5, 1, -4, 1, +0, -1, 2, -1, 1, -1, -3, 1, +-4, 0, -3, 1, -3, 2, 2, -1, +3, 0, 3, -1, 1, 1, -5, 5, +-2, 2, 1, 2, 4, 0, 3, 1, +1, 0, 0, -1, -4, 2, -3, 0, +-2, 1, -1, 1, -4, 3, -7, 2, +-5, 0, -6, 1, 0, -3, 1, 1, +1, 0, 5, -3, 1, 1, 1, -1, +4, -3, 6, -2, 7, -2, 8, -2, +2, 2, 0, -1, 3, -4, 1, -1, +0, -1, -2, 1, -2, -1, -4, 0, +-7, 1, -6, 0, -4, -1, -2, 1, +-3, 3, -2, 2, -1, 1, 0, 1, +2, 0, 3, 1, 5, 1, 4, 4, +4, 1, 5, 0, 0, 2, 0, 2, +-2, 3, 0, -2, -2, 2, -7, 2, +-7, 1, -7, -2, -2, -4, -6, 1, +-1, -4, 0, 0, -5, 4, -4, 4, +-2, 2, 3, 0, 7, -1, 7, 2, +4, 3, 9, -4, 9, -3, 4, 0, +1, 3, -1, 2, 1, -1, -3, 1, +-6, 0, -6, -3, -8, 0, -13, 5, +-8, -1, -3, -1, -4, 0, -3, 0, +-3, 2, 1, 1, 3, 2, 9, 0, +8, 2, 8, 0, 10, -1, 8, -1, +8, -3, 7, -1, 2, 2, -3, 3, +-5, 0, -7, 0, -12, 1, -10, 0, +-9, 0, -10, 2, -10, 3, -10, 3, +-7, 1, -1, 0, 0, 3, 5, 2, +10, 0, 13, -1, 8, 4, 7, 2, +10, -1, 10, -2, 9, -1, 3, 0, +0, -2, -5, -1, -12, 3, -14, 2, +-12, 1, -13, 3, -9, -4, -5, -5, +-7, -2, -3, -2, -3, 4, 3, 1, +11, -1, 11, 0, 10, 2, 7, 3, +14, -2, 13, 0, 14, -2, 7, 3, +0, 1, -3, 0, -9, 0, -7, -3, +-11, 0, -9, -4, -10, -2, -15, 1, +-14, -1, -10, -1, -3, -3, 4, -2, +6, 1, 10, -1, 10, 1, 12, -1, +16, -1, 16, 0, 17, -1, 14, -1, +11, -4, 4, -2, -3, -1, -8, 1, +-9, -1, -10, -1, -15, 1, -18, 1, +-18, -1, -15, -1, -10, -1, -1, -3, +4, -2, 7, -2, 10, -2, 13, -2, +18, -3, 21, -3, 23, -2, 17, 2, +10, 2, 7, -1, 0, 0, -1, -3, +-4, -1, -12, 3, -15, 1, -21, 3, +-25, 3, -19, -2, -16, 3, -14, 4, +-2, -2, 0, 1, 2, 0, 8, 0, +11, 2, 18, 1, 22, 0, 24, -2, +19, -1, 11, 0, 5, 1, 1, 1, +1, -2, -4, -1, -11, 0, -18, 0, +-24, 1, -23, -1, -17, -2, -14, 1, +-11, 1, -6, 0, -5, 3, 2, -1, +9, 1, 18, -2, 25, -1, 25, -2, +22, -1, 16, 0, 10, 2, 8, 1, +7, 0, 4, -3, -6, 1, -18, 1, +-20, -1, -27, 4, -23, 1, -20, 3, +-15, -1, -12, 2, -14, 3, -3, -1, +6, -1, 16, -1, 19, 2, 23, -1, +21, 1, 19, -1, 20, -3, 15, 1, +14, -2, 9, 0, -1, -1, -8, -3, +-18, -1, -21, 0, -22, 0, -16, -4, +-17, 0, -20, 2, -16, -2, -7, -3, +-3, 2, 8, 0, 15, 3, 16, 3, +19, 2, 16, 3, 21, -2, 23, -1, +18, 2, 12, 2, 2, 3, -7, 1, +-13, -1, -19, 1, -20, 0, -17, -2, +-18, -2, -23, 1, -23, 0, -16, -1, +-8, -1, 2, 1, 8, 3, 13, 2, +17, -1, 19, -2, 22, -1, 24, 0, +22, 2, 20, 0, 10, 1, 1, -1, +-7, 0, -13, 0, -13, 0, -18, 1, +-20, -1, -24, -1, -24, -2, -21, -1, +-13, -2, -1, -3, 3, 2, 5, 2, +12, 0, 13, 1, 20, -1, 26, -2, +29, -2, 23, 2, 17, -2, 11, -3, +-2, 2, -5, 0, -9, 2, -13, 0, +-18, 2, -27, 2, -24, -4, -21, -2, +-18, 0, -11, 3, -7, 3, 5, -5, +9, -4, 11, -2, 16, 1, 21, 1, +27, -1, 27, -2, 20, 1, 12, -1, +7, 1, -2, 3, 3, -5, -5, 1, +-17, 3, -22, 0, -24, -2, -23, -2, +-21, 2, -17, 3, -11, 2, -7, 1, +-2, -1, 4, -1, 13, -3, 23, -4, +27, -1, 24, 1, 19, 2, 14, -1, +15, -4, 9, 1, 4, 2, 0, 0, +-7, -1, -16, 0, -21, -2, -20, -3, +-20, 1, -19, 3, -12, -2, -10, -1, +-6, -4, 0, -3, 5, 0, 16, -2, +20, 1, 22, -1, 21, -1, 19, -3, +16, -1, 12, 2, 9, 2, 7, -1, +0, -2, -11, 0, -18, -1, -16, -3, +-19, 2, -16, -1, -12, -4, -14, 0, +-16, 3, -9, -2, 3, -3, 6, 3, +14, 0, 18, 0, 17, -1, 16, -1, +17, -2, 20, -3, 16, 0, 12, -1, +5, -1, -5, -1, -11, 1, -15, 0, +-14, 1, -18, 4, -15, 0, -18, 2, +-19, 1, -14, 2, -9, 4, 1, 1, +7, 2, 7, 5, 9, 2, 10, 3, +12, 2, 18, -2, 18, 0, 12, 3, +3, 5, -3, 0, -5, 0, -10, 1, +-8, -2, -8, -3, -12, -2, -14, -3, +-16, 0, -16, 0, -9, -1, -1, 0, +4, 0, 8, -1, 6, 1, 9, -3, +17, -4, 18, -1, 18, -1, 14, 0, +10, -1, 5, -2, 1, -1, -4, 1, +-2, -4, -4, 0, -12, 1, -12, -4, +-15, -2, -14, -2, -7, -3, -5, 2, +-6, 4, -5, 5, -2, 4, 4, 0, +7, 3, 9, 3, 16, -1, 16, -1, +13, -1, 2, 3, 2, -1, 2, 2, +-1, 1, -1, -3, -4, -4, -11, 0, +-14, 1, -14, 1, -12, -1, -4, -3, +0, -2, -3, 0, 0, -3, 0, 0, +3, 2, 10, 1, 13, -1, 15, -4, +12, -1, 5, 3, 5, -1, 7, -3, +5, -2, 0, 2, -6, 5, -9, -2, +-10, -3, -7, -4, -5, -1, -7, 0, +-2, -6, -3, -3, -6, 3, -3, 1, +3, -2, 8, -3, 14, -3, 8, 4, +7, -1, 6, -2, 6, -2, 11, -2, +9, -1, 6, -5, 1, -3, -2, -2, +-5, 0, -9, 2, -8, -2, -8, 2, +-8, 5, -10, 4, -11, 1, -2, -4, +1, 1, 2, 3, 8, -3, 6, -4, +8, -2, 7, 2, 3, 4, 5, -2, +6, 1, 2, 4, 4, -1, -1, -1, +-5, -4, -2, -1, -2, 3, -5, 0, +-6, -2, -6, -2, -7, 3, -5, 3, +-4, -2, 1, -3, 4, 2, 5, 0, +7, -5, 8, -9, 6, -1, 5, 6, +6, 2, 4, -3, 6, -7, 3, 1, +0, 1, 2, -6, 1, -5, -2, 1, +-6, 7, -6, 2, -9, -3, -7, 0, +-4, 7, -5, 6, 0, -2, 1, -5, +-2, 4, 0, 6, 5, -3, 5, -5, +5, 0, 3, 8, 1, 3, 5, -8, +1, -3, 1, 1, 2, 5, -4, 3, +-6, -4, -7, 5, -5, 4, 0, -2, +0, -7, 1, -6, -1, 6, -3, 7, +0, -6, 0, -5, 3, -1, 4, 6, +3, 0, 5, -8, 2, -2, 3, 4, +3, 4, 1, -4, 3, -8, 1, 5, +-1, 4, 1, -3, -5, -4, -6, 0, +-4, 10, -2, 3, -1, -8, -1, -4, +-5, 6, -4, 9, 0, -2, 2, -8, +1, 2, 1, 9, -1, 5, -2, -5, +1, -4, 4, 5, 5, 2, 8, -9, +3, -10, 1, -2, 3, 7, 1, -2, +0, -9, 1, -3, -3, 8, -5, 8, +0, -8, -4, -6, -2, 6, -1, 10, +-2, -1, 4, -12, 2, -3, 0, 9, +1, 5, 1, -5, 2, -7, 3, 5, +2, 8, 1, -6, 1, -8, 2, 0, +-2, 11, -2, 6, -2, -9, -5, -4, +1, 5, 2, 3, -4, -3, 2, -11, +-2, 5, -3, 11, 4, -4, 1, -12, +2, -4, 1, 12, -4, 12, -2, -6, +4, -9, 0, 6, 0, 11, 1, 1, +-3, -9, -1, 1, 0, 11, -2, 1, +-1, -6, -3, -6, -3, 5, 0, 11, +-6, -2, -6, -9, 2, -2, 1, 9, +-1, 3, 2, -12, 1, -5, 0, 9, +4, 7, 1, -6, 1, -12, 6, 3, +3, 9, 2, -2, 2, -9, -1, -6, +0, 10, 2, 7, -1, -13, -1, -8, +-1, 7, -5, 10, 0, -2, 3, -17, +0, -2, 0, 13, 0, 4, 0, -12, +5, -11, 4, 8, 1, 9, 7, -8, +4, -11, -2, 2, 2, 16, -3, 6, +-2, -14, 7, -8, 2, 6, -4, 10, +-1, -5, -3, -15, -2, 4, 4, 8, +-1, -4, -1, -12, 1, -2, -5, 13, +5, 2, 4, -8, -3, -7, 4, 4, +6, 12, -2, -3, 4, -15, 4, 1, +-2, 10, 4, 4, 1, -11, -3, -12, +0, 13, -5, 11, -6, -5, 2, -12, +-1, -1, -5, 14, 4, -1, -2, -12, +-3, -4, 7, 8, -1, 11, 1, -10, +9, -13, -2, 7, 3, 8, 8, 1, +-4, -10, 0, -3, 4, 13, -3, 3, +-2, -7, 0, -8, -10, 9, -2, 14, +-1, -3, -9, -12, 1, 0, -2, 11, +-5, 6, 5, -12, 3, -9, -3, 11, +5, 11, 0, -3, 2, -15, 9, 1, +1, 15, -3, 4, 4, -9, -3, -6, +-5, 10, 3, 10, -3, -11, -2, -12, +5, 1, -9, 12, -7, 5, 2, -14, +-6, -4, 1, 12, 3, 7, -8, -5, +6, -13, 5, 6, -2, 11, 11, -6, +5, -10, -2, -2, 6, 10, 3, 3, +-2, -13, 4, -6, -4, 9, -7, 9, +1, 0, -7, -13, -6, 0, -1, 16, +-8, 2, -1, -11, 9, -10, -3, 7, +0, 9, 9, -10, 1, -11, 7, 0, +9, 10, -2, 2, 6, -14, 7, -4, +-3, 8, 5, 5, 1, -4, -8, -11, +2, 5, -3, 9, -7, -5, 0, -8, +-2, -4, -8, 11, 6, 4, -1, -11, +-4, -6, 7, 6, -3, 11, 2, -3, +11, -11, -2, 3, 2, 8, 8, 3, +-5, -5, 1, -8, 7, 8, -7, 10, +-3, -4, -1, -6, -10, 0, -4, 13, +1, 1, -7, -11, -1, 0, 0, 5, +-6, 6, 3, -3, 2, -10, 0, 2, +12, 6, 5, 0, -3, -6, 8, -5, +2, 9, -2, 7, 8, -7, -4, -4, +-5, 3, 2, 10, -6, -4, -4, -10, +0, 2, -9, 7, -2, 2, 6, -9, +-7, -9, 4, 2, 4, 9, -5, -1, +7, -8, 8, -4, -2, 10, 6, 2, +8, -9, -2, -4, 9, 2, 0, 11, +-6, -4, 4, -10, -3, 1, -7, 6, +3, 1, -3, -9, -9, -4, 3, 5, +-4, 3, -5, -1, 1, -3, -3, -1, +4, 8, 8, 1, -1, -9, 4, -2, +9, 4, 0, 6, 8, -8, 6, -6, +-10, 8, 0, 7, 3, -1, -5, -11, +2, -4, -4, 11, -11, 3, 3, -7, +-3, -6, -8, 2, 4, 10, -3, 1, +-7, -3, 5, 1, 1, 5, 2, 4, +10, -7, 1, -6, 4, 3, 10, 4, +-2, -1, -2, -7, 5, -3, -5, 8, +-2, 2, -2, -2, -11, -6, 0, 1, +1, 7, -8, -5, 2, -9, 5, -2, +-5, 7, 4, 4, 0, -5, -6, -1, +9, 6, 7, 3, 1, -3, 11, -11, +4, 0, -7, 15, 1, 4, -4, -5, +-4, -5, 4, 5, -8, 8, -5, -8, +1, -6, -8, 3, -4, 8, 3, 2, +-6, -8, -1, 0, 4, 8, -3, 5, +3, -3, 9, -10, -2, 7, 4, 10, +7, -4, -4, -4, 0, 2, -1, 9, +-5, 6, -1, -5, -5, -4, -6, 2, +1, 8, -8, 2, -8, -8, -1, 3, +-4, 8, -3, 2, 3, -4, -2, -6, +3, 5, 9, 7, 1, -5, 3, -7, +4, 3, -3, 11, 2, 3, 3, -8, +-5, -3, -1, 7, -2, 9, -8, -4, +-1, -10, -1, 3, -6, 7, 0, 0, +-3, -6, -5, -6, 5, 7, 3, 5, +-1, -7, 6, -7, 3, 3, -3, 13, +4, 1, 5, -14, 3, -2, 5, 8, +1, 4, -4, -5, 1, -8, -4, 6, +-6, 10, -3, 1, -7, -8, -1, -5, +2, 10, -4, 1, -2, -7, -1, -1, +-2, 5, 3, 9, 5, -5, 0, -12, +5, 2, 5, 10, -2, 4, 1, -5, +0, -4, -3, 8, 3, 7, -2, -6, +-4, -10, -1, 4, -3, 10, -7, 1, +0, -12, -2, -2, -5, 9, 6, 4, +1, -10, 1, -10, 2, 9, -2, 9, +4, -3, 3, -6, -2, 0, 4, 11, +2, 6, -3, -9, 3, -9, 0, 8, +-6, 11, 3, -8, 0, -10, -7, 2, +0, 9, -1, 3, -4, -12, 4, -8, +1, 10, -2, 7, 2, -5, 2, -11, +3, 1, 8, 8, 6, -3, 3, -12, +3, -2, -3, 12, 1, 6, 1, -8, +-1, -10, -1, 5, -1, 10, -1, -5, +-1, -14, -2, -1, -5, 15, -2, 4, +2, -10, -2, -8, 0, 7, 2, 12, +1, -5, 2, -10, 5, 0, 1, 13, +1, 4, 4, -15, 3, -9, 2, 8, +1, 9, -1, -9, 3, -16, 0, 3, +-5, 13, -2, 0, 0, -13, -2, -5, +1, 10, 3, 5, -2, -9, 2, -10, +2, 5, 4, 9, 7, -4, 3, -14, +-2, 3, -3, 17, 2, 1, 4, -12, +1, -8, 1, 5, -2, 13, -2, -5, +-4, -12, -5, 3, 0, 12, -4, 5, +-6, -7, -1, -7, -2, 10, 2, 9, +5, -9, -1, -11, 3, 5, 2, 13, +-2, 2, 2, -13, 2, -7, 0, 13, +3, 8, 0, -11, 0, -11, -3, 8, +-5, 13, 0, -5, 3, -17, -2, -2, +0, 12, 0, 4, -1, -13, 3, -11, +1, 10, -1, 13, 4, -5, 2, -14, +1, 1, 3, 15, 1, 3, -1, -11, +2, -7, 1, 9, 1, 10, -2, -6, +-6, -11, -1, 5, -2, 15, -6, 3, +-5, -10, -3, -4, -2, 12, 3, 5, +1, -10, -1, -10, 2, 8, 0, 14, +3, -5, 3, -15, 3, -3, 3, 13, +3, 5, 0, -12, -2, -9, 2, 7, +0, 11, 0, -9, 2, -16, -4, 4, +-1, 14, -1, 1, -1, -15, -3, -4, +-1, 14, 0, 12, -1, -8, 2, -14, +4, 3, -2, 18, -1, 2, 2, -15, +1, -5, 4, 14, 0, 6, 1, -15, +5, -15, 0, 6, -1, 14, 1, -4, +-5, -15, -2, 0, -1, 18, -7, 8, +0, -15, 4, -9, -5, 14, 1, 13, +2, -7, -3, -17, 9, 0, 5, 14, +0, -2, 6, -15, -1, -6, -4, 14, +6, 7, 1, -13, -6, -10, 5, 6, +-6, 17, -7, 1, 1, -14, -6, -2, +0, 15, 6, 5, -3, -14, 1, -9, +3, 11, -6, 16, 2, -4, 4, -16, +-3, 1, 4, 18, -1, 6, -7, -15, +7, -10, -1, 14, -7, 15, 6, -13, +0, -17, -7, 8, 5, 12, 0, -3, +-1, -17, 6, -7, 0, 12, -1, 11, +0, -10, 0, -15, 3, 8, 5, 14, +-1, -3, -2, -13, 2, -1, -2, 15, +2, 3, 3, -15, -1, -12, 2, 10, +-2, 15, -3, -10, 1, -18, 2, 2, +-2, 15, 2, 0, 3, -16, -3, -6, +2, 11, 6, 10, -5, -7, 0, -13, +7, 4, -3, 16, 2, -2, 4, -17, +-6, -2, 3, 15, 4, 6, -7, -13, +3, -11, -1, 11, -8, 13, 9, -10, +1, -17, -7, 2, 6, 17, -2, 3, +-6, -15, 10, -9, -1, 11, -1, 11, +10, -9, -5, -15, -1, 4, 9, 16, +-6, -3, 6, -20, 5, -1, -11, 15, +2, 9, 3, -12, -9, -14, 6, 6, +6, 12, -11, 0, 2, -14, 2, -2, +-10, 19, 5, 8, -3, -11, -6, -9, +13, 8, 1, 11, -1, -11, 10, -16, +-4, 3, -2, 17, 3, 6, -6, -16, +0, -7, 5, 12, -7, 11, -2, -9, +4, -15, -4, 7, -4, 18, 3, -4, +-4, -15, 0, -2, 4, 15, -2, 6, +4, -15, 3, -9, -3, 11, -2, 18, +0, -4, 0, -17, 2, 1, 0, 18, +-7, 5, 0, -16, 4, -9, -5, 13, +0, 10, 5, -11, -3, -16, 1, 5, +3, 15, -7, 1, 3, -14, 4, -3, +-4, 11, 6, 10, -4, -5, -8, -11, +11, 5, 3, 11, -4, -5, 4, -11, +-3, -1, -7, 16, 6, 4, -5, -12, +-7, -6, 7, 11, -5, 9, -2, -8, +6, -11, -7, 2, 4, 11, 8, 4, +-12, -11, 3, -3, 4, 14, -7, 7, +6, -10, 6, -13, -10, 9, 5, 14, +0, -2, -12, -11, 7, -3, 0, 11, +-4, 2, 8, -13, -6, -7, -4, 7, +10, 9, -6, -3, 0, -16, 12, -1, +-3, 12, 5, -2, 7, -12, -3, -6, +1, 12, 7, 5, -2, -9, 3, -12, +2, 6, -8, 15, -1, -1, 1, -13, +-5, -1, -1, 12, 0, 6, -5, -9, +-1, -8, 3, 7, -4, 13, -1, -3, +6, -14, -1, 1, -1, 13, 6, 1, +-1, -12, 3, -6, 6, 7, -1, 5, +4, -9, 6, -12, -8, 5, 0, 12, +-1, 3, -11, -8, -1, 0, 1, 9, +-7, 5, 1, -4, -1, -7, -6, 5, +8, 9, 2, -5, -2, -12, 9, 0, +0, 8, -2, 4, 6, -7, -1, -10, +0, 7, 6, 9, -8, -5, -1, -9, +3, 4, -9, 9, 0, 2, 3, -10, +-8, -4, 1, 11, 1, 7, -8, -7, +7, -9, 3, 4, -7, 10, 8, -1, +-1, -8, -4, -1, 7, 11, -1, 1, +-1, -9, 7, -6, -4, 6, -3, 8, +3, -2, -8, -8, 0, -1, 4, 8, +-7, 2, 0, -9, 3, -4, -5, 8, +2, 3, 8, -9, -2, -7, 3, 2, +4, 9, -2, 0, 0, -5, 3, -2, +-2, 9, -3, 7, 1, -6, -5, -3, +-1, 4, 1, 7, -4, -3, -1, -9, +1, 0, -5, 9, -3, 2, 3, -7, +-4, -4, 2, 6, 0, 10, -4, -4, +5, -9, 8, -1, 2, 3, 4, 0, +7, -12, 0, -3, 1, 9, -1, 4, +-4, -6, 5, -6, -3, 5, -5, 7, +4, -4, -3, -7, -4, 0, 4, 7, +-7, 5, -4, -2, 3, -2, -2, 2, +2, 6, 4, -2, -2, -8, 5, 3, +2, 8, -6, 0, 6, -6, -1, 0, +-9, 7, 6, 2, -1, -5, -8, -2, +1, 5, -7, 8, -6, -3, 9, -10, +-3, 0, -2, 4, 8, -1, 2, -9, +2, -5, 6, 4, -1, 3, 3, -4, +6, -5, -2, 1, 2, 6, 3, 0, +-3, -4, -2, 1, 1, 2, -3, 4, +-2, -2, -1, -6, -1, 1, -1, 4, +1, -4, 1, -5, -1, -1, 1, 3, +4, -2, 4, -6, 1, -3, 5, 1, +1, 5, 2, -3, -1, 0, -4, 4, +-1, 6, -2, 3, -1, -4, -1, -2, +1, 1, 0, 2, -5, 0, -2, -4, +1, -1, -1, 5, -3, 1, 0, -4, +-1, -1, 4, -1, 4, 2, 0, -4, +2, -2, 3, 3, 0, 2, 2, -2, +6, -6, 0, -2, -1, 7, 2, -2, +-2, -4, -2, 0, -1, 4, -8, 5, +-1, -1, -3, 0, -4, 1, 4, 0, +2, 1, -7, -1, 5, -3, 4, 1, +0, 1, 3, -2, 4, -5, -1, 4, +4, 1, 3, -4, 2, -4, 3, -1, +-3, 5, -5, 6, -6, 2, -5, 0, +1, 2, -4, 3, -2, -1, -2, -1, +-2, 1, 0, 2, 3, -1, -3, -1, +3, -2, 2, 4, -2, 1, 5, -6, +6, -3, -1, 1, -1, 6, -2, 2, +-2, -4, 1, 0, 2, -1, -2, 0, +-4, 3, -1, -4, -1, 1, 1, 0, +0, -2, -6, 3, 0, 1, 2, 1, +0, 1, 2, -4, 1, 1, -1, 3, +2, 1, 2, -2, 0, 0, -1, 3, +2, 1, 1, -2, -1, 0, -5, 3, +1, 1, 0, -2, 1, -3, -1, -1, +-2, 1, 1, 0, 2, -3, 1, -5, +4, 1, -3, 4, 0, 0, 2, -2, +2, -2, 2, 2, 4, -1, 1, -1, +-2, 0, 3, -3, 1, 3, 0, -2, +-2, 1, -6, 4, 1, -1, 0, 0, +-1, -2, -1, -1, -1, 4, -2, 3, +0, 0, -1, -1, 1, 1, -1, 5, +-1, -1, 5, -5, 3, -2, 0, 0, +3, 2, -4, 1, -2, -1, 2, 1, +1, 0, -3, 2, 1, -4, -3, 3, +-7, 8, 0, -1, 0, -1, 0, -2, +0, 2, -1, 3, -1, 0, 1, -2, +3, -1, 2, 1, 2, -1, 5, -7, +2, -1, -2, 4, 0, 0, 4, -4, +0, -2, -1, 2, 2, -1, -1, -1, +-3, 1, 2, -3, -4, 5, -2, 3, +-2, -1, -3, 1, 1, 1, -1, 2, +-1, 0, 3, -3, 1, 1, 0, 2, +3, -3, 2, -2, 1, -4, 4, 0, +2, -1, -1, -1, -2, -1, 4, -4, +0, 0, 3, -3, 0, -1, -5, 5, +-2, 1, 1, 1, -5, 2, 1, -4, +2, 3, -1, 1, 2, -4, 4, -2, +1, -2, 0, 3, 2, 0, 0, -2, +-2, 1, 4, -1, 0, 0, -1, -1, +-2, 1, -3, 4, -2, 0, 4, -2, +0, -2, 1, -3, 3, 2, 0, 0, +-1, -1, 0, 3, -1, 0, -1, 4, +1, -3, 6, -6, 1, 0, 0, 1, +2, -2, 4, -5, -2, 0, 1, 2, +0, -2, -1, 1, 1, -2, 1, -1, +-1, 0, 6, -4, -1, -2, 1, -2, +6, -3, 1, 1, -1, -3, 3, 0, +-1, 0, 3, -2, 1, 3, -1, -1, +-4, 2, 3, 2, -3, 0, -5, 3, +1, -1, 2, -2, -5, 6, 0, 0, +-4, 2, -4, 2, 4, -3, 2, 0, +-3, -1, 3, 0, 0, 2, 0, -2, +2, 0, 0, 0, 1, -4, 6, -2, +4, -5, 1, -1, -4, 3, 3, -2, +-1, -1, 2, -3, 4, -2, 0, -2, +2, -3, 6, -3, -2, -3, 2, 0, +1, 3, -4, 0, -1, 1, 4, -2, +-4, 3, 0, 1, 2, -1, -2, 0, +1, -1, 2, 0, -2, 1, -2, -1, +1, 3, -4, 3, -1, -1, 2, 1, +1, -4, -1, 1, -1, 4, -2, 1, +-3, 1, 3, -2, 2, 1, -7, 4, +2, -2, 3, 0, -4, 0, 3, 0, +2, -1, -1, -4, 5, 0, 1, 0, +-6, 2, 3, -1, 2, -1, -5, 1, +3, -1, -2, 2, -2, -1, 2, 1, +-1, 3, -5, 2, -2, 2, 1, 0, +-1, -2, 3, -2, 3, 1, -3, 0, +1, 1, -1, 2, -3, 1, 0, -2, +5, -3, 0, 1, -5, 4, -2, 3, +2, -2, -1, -3, 3, 3, 0, 0, +-3, 1, 5, 0, 1, -1, -5, 0, +9, -4, 2, -1, -4, 2, 6, -4, +3, -1, -4, 1, 6, -2, 0, 1, +-3, -1, 4, 2, 0, 2, -3, -3, +1, 5, -1, 0, -2, 1, 2, 1, +3, -2, -4, 3, 0, 3, 1, -1, +-2, 3, -3, 2, 5, 1, -3, 2, +-1, 2, 0, 3, 0, -4, 4, -2, +7, -2, -1, -3, 1, 2, 5, -1, +1, -1, -2, 2, 5, -1, 1, 0, +2, 0, 3, 1, 0, 0, 0, -1, +6, 2, 1, -2, 1, -1, 3, 2, +1, 1, -1, 2, 5, -2, 2, -1, +1, 1, 4, 0, 4, 0, -4, 1, +1, 1, 3, 4, -5, 4, 1, -1, +8, -2, -3, 2, 4, 3, 7, -3, +0, -3, 5, 1, 8, 0, -2, 0, +5, -2, 6, 1, -3, 3, 6, -2, +5, 3, -5, 0, 6, -1, 6, 3, +-3, 0, 1, 1, 9, -2, 1, 0, +6, 1, 8, -5, 2, 0, 2, 4, +8, -2, 5, -3, 7, -5, 11, -4, +6, 0, 6, -4, 9, -3, 6, -4, +4, 2, 7, 0, 7, -4, -1, 3, +6, 0, 9, -2, 2, 2, 3, 0, +6, 1, 1, 4, 6, 1, 6, 0, +1, -2, 9, 2, 6, 4, 1, -1, +7, -2, 11, -3, 3, 3, 5, 3, +5, 0, 2, 0, 10, -1, 8, 2, +3, 0, 6, -3, 7, 4, 3, 3, +5, -1, 10, -3, 10, -6, 8, 1, +12, -1, 8, -4, 4, 1, 11, 1, +7, 2, 3, 0, 12, -4, 5, 4, +1, 5, 10, 3, 5, -2, 6, -3, +13, 3, 6, 4, 1, 2, 13, -4, +8, -2, 10, 0, 14, -3, 7, -3, +7, 1, 13, 0, 9, 2, 6, 0, +12, -4, 9, 2, 10, 0, 10, 1, +6, -1, 7, 2, 7, 5, 11, 0, +6, 0, 11, -2, 10, 2, 11, 1, +9, -1, 10, -1, 8, 2, 10, 1, +11, 3, 7, 0, 11, -3, 16, 3, +7, 3, 9, 0, 11, 0, 8, 2, +10, 3, 15, -4, 13, -6, 14, -4, +14, 4, 7, 5, 11, -4, 11, 5, +7, 4, 16, -4, 16, -1, 11, -3, +8, 2, 14, 3, 13, -1, 8, 2, +13, 2, 11, 4, 12, 2, 16, -2, +11, -1, 12, -1, 17, -1, 14, -1, +10, -3, 14, 1, 15, 4, 11, 2, +18, -4, 16, 0, 7, 4, 18, 0, +16, -2, 12, -4, 17, -2, 14, 7, +7, 6, 15, -3, 18, 1, 11, 5, +16, 1, 19, -2, 11, -3, 14, 2, +14, 4, 12, 1, 14, -1, 17, -1, +16, 3, 17, 2, 15, 1, 15, -1, +12, 4, 14, 3, 19, -3, 14, -4, +20, -3, 23, -1, 17, 1, 17, 1, +17, 1, 13, 4, 18, 0, 20, -4, +17, -6, 20, -4, 19, 4, 15, 0, +19, -3, 16, 6, 13, 7, 15, 7, +18, 1, 18, -5, 18, 0, 22, 0, +19, -2, 18, -5, 25, -3, 19, 6, +15, 4, 22, -1, 20, -4, 20, -2, +22, 2, 21, -6, 19, -6, 23, -1, +18, 3, 18, 3, 21, 0, 18, 1, +21, 4, 21, 2, 19, -1, 21, -5, +23, -5, 21, 3, 23, -1, 19, -1, +21, 1, 26, 1, 18, 5, 19, 2, +19, 0, 17, 0, 23, 0, 19, 2, +15, -2, 26, -1, 22, 7, 18, 3, +27, -2, 24, -1, 23, -2, 27, 0, +22, -5, 21, -3, 19, 2, 24, 1, +22, 4, 23, -2, 26, 0, 23, 7, +21, 2, 27, -6, 28, -8, 23, -4, +26, -2, 26, -4, 24, -3, 22, 4, +23, 8, 25, 2, 26, -4, 30, -5, +25, 0, 22, -1, 29, -4, 22, -4, +23, 0, 26, 6, 24, 2, 24, 0, +29, 1, 21, 6, 22, 3, 27, -4, +22, -5, 21, 0, 27, 1, 25, -1, +26, 0, 26, 3, 25, 6, 27, 5, +25, -1, 24, -4, 30, -2, 27, -5, +29, -5, 30, -4, 21, 2, 29, 4, +32, 3, 21, 0, 29, 2, 26, 2, +20, 1, 29, -4, 28, -8, 22, -1, +32, 4, 26, 4, 24, 2, 31, 3, +28, 4, 28, 1, 30, -4, 24, -4, +27, -3, 29, 1, 27, -2, 32, -5, +29, 3, 27, 9, 26, 9, 24, 0, +30, -6, 33, -3, 27, -4, 31, -7, +29, -4, 25, 1, 27, 10, 29, 6, +29, -1, 31, 0, 32, 3, 28, 0, +28, -6, 30, -4, 25, 0, 27, 1, +33, 4, 26, 2, 26, 3, 36, 6, +29, 2, 26, -4, 35, -5, 22, 1, +27, -2, 34, -2, 24, -1, 30, 1, +36, 5, 31, 4, 31, 1, 30, -2, +28, 3, 29, 0, 30, -8, 33, -9, +32, 0, 23, 8, 31, 9, 27, 6, +23, 4, 34, 6, 32, 1, 20, -2, +34, -6, 28, -2, 22, 3, 38, 0, +30, -1, 23, 8, 36, 10, 30, 5, +25, 1, 35, -6, 29, -2, 31, -4, +38, -9, 31, -5, 32, 0, 31, 9, +31, 8, 32, -1, 29, 1, 34, 2, +30, 0, 28, -8, 36, -9, 28, 1, +27, 4, 40, 0, 31, 4, 27, 4, +37, 7, 30, 5, 31, -10, 37, -9, +33, -5, 31, -4, 35, -2, 34, -2, +26, 6, 34, 8, 40, 3, 27, -1, +32, -4, 35, 0, 26, -3, 34, -7, +33, -4, 25, 1, 34, 9, 35, 7, +26, 2, 35, 2, 33, 5, 28, 1, +38, -12, 36, -14, 32, -1, 32, 4, +29, 2, 32, 4, 30, 7, 26, 11, +39, 3, 31, -6, 27, -6, 37, -3, +28, -2, 29, -5, 41, -5, 26, 4, +32, 10, 39, 8, 29, -3, 36, -4, +37, 2, 28, -4, 35, -8, 35, -10, +28, -1, 35, 7, 31, 7, 28, 3, +35, 4, 30, 6, 32, 3, 32, -6, +30, -11, 35, -4, 33, 0, 30, 0, +35, -1, 34, 4, 27, 15, 34, 7, +29, 1, 28, -4, 33, -2, 33, -3, +31, -7, 34, -9, 40, -3, 32, 9, +32, 7, 33, 4, 28, -1, 32, 2, +35, -1, 26, -6, 31, -11, 37, -1, +24, 7, 32, 3, 37, 0, 31, 3, +35, 8, 32, 8, 25, -4, 36, -11, +33, -5, 35, -4, 34, -3, 28, -2, +35, 3, 30, 15, 24, 10, 38, -2, +28, -4, 28, -2, 38, -2, 28, -8, +25, -3, 36, 3, 25, 7, 31, 4, +39, 2, 25, 4, 30, 7, 36, 0, +26, -7, 30, -9, 35, -2, 26, 5, +30, 1, 32, -1, 32, 4, 33, 8, +34, 4, 32, -3, 26, -6, 27, -5, +36, -2, 27, -4, 32, -6, 35, 6, +23, 11, 30, 5, 39, 0, 24, 0, +31, 2, 34, 0, 27, -10, 30, -7, +31, 2, 26, 6, 29, 3, 33, 1, +29, 6, 28, 8, 32, 4, 29, -7, +23, -9, 28, -1, 34, -4, 28, -3, +34, -1, 32, 7, 20, 15, 33, 6, +35, -8, 25, -6, 33, -5, 35, -5, +28, -6, 34, -6, 29, 0, 30, 4, +28, 6, 27, 3, 30, 3, 28, 4, +28, -2, 31, -8, 21, -7, 27, 2, +29, 4, 21, 1, 32, 0, 37, 5, +20, 13, 34, 4, 31, -9, 21, -13, +32, -4, 29, 1, 24, 0, 38, -6, +29, 0, 20, 12, 27, 9, 26, 0, +30, -4, 30, -2, 24, -4, 31, -9, +28, -4, 23, 3, 30, 2, 23, 2, +26, 3, 32, 8, 25, 9, 32, -4, +29, -11, 17, -11, 28, -4, 26, 6, +26, 2, 32, -2, 24, 4, 23, 9, +27, 7, 23, -2, 25, -7, 24, -6, +26, -4, 30, -4, 27, -4, 26, 4, +24, 7, 19, 1, 27, 1, 32, 3, +25, 6, 28, -1, 24, -9, 16, -7, +23, -1, 24, 2, 30, 0, 30, 3, +21, 6, 24, 7, 23, 1, 24, -9, +25, -8, 19, -2, 21, 1, 31, -5, +25, -5, 27, 5, 24, 14, 12, 6, +18, -2, 28, -6, 28, -3, 31, 2, +26, -3, 15, -6, 18, -5, 18, 3, +23, 6, 29, 12, 16, 14, 16, 3, +16, -5, 19, -4, 25, -2, 18, 2, +20, 0, 26, -7, 18, -2, 29, 9, +27, 17, 8, 6, 18, -15, 21, -14, +17, 5, 30, 15, 23, 6, 13, -8, +20, -12, 14, 0, 17, 10, 30, 11, +24, 3, 25, -14, 21, -12, 17, -1, +23, 2, 18, 1, 22, -9, 28, -10, +17, 3, 23, 14, 25, 12, 13, -2, +17, -15, 16, -16, 18, 0, 33, 12, +23, 7, 12, -5, 19, -4, 10, 4, +13, 4, 21, 2, 24, -3, 22, -3, +19, -2, 15, 1, 18, -3, 18, -5, +15, -1, 16, 5, 12, 11, 27, 0, +24, -3, 10, 2, 15, -5, 9, -6, +10, 0, 30, 2, 24, 0, 21, 1, +13, 11, 1, 7, 10, -8, 20, -14, +20, -4, 21, 12, 12, 10, 13, -2, +14, -1, 11, 0, 13, 4, 12, 5, +13, 1, 22, -1, 21, -5, 18, 0, +14, 7, -1, -1, 0, -5, 22, -1, +23, 11, 20, 14, 16, 5, -2, -2, +4, -12, 13, -13, 17, -2, 30, 7, +20, 3, 9, -3, 12, 1, 10, 9, +15, 3, 16, -9, 8, -11, 13, 0, +17, 5, 18, 5, 20, 3, 8, -9, +2, -14, 9, 2, 14, 18, 26, 12, +24, -1, 4, -10, -1, -7, -3, -6, +11, -6, 27, 3, 27, 6, 13, 8, +2, 9, -5, 11, 10, -2, 21, -19, +14, -16, 14, 1, 11, 6, 9, 3, +17, 4, 13, 3, 2, 3, -3, -2, +6, -2, 24, 0, 29, 2, 14, 3, +0, 0, -12, -12, 5, -26, 23, -7, +23, 24, 22, 28, 6, 6, -5, -12, +6, -9, 6, -8, 10, -4, 16, 5, +8, -2, 10, -10, 21, -1, 7, 20, +0, 19, 0, -7, 1, -26, 22, -12, +29, 10, 14, 14, 5, 4, -12, -11, +-4, -27, 13, -12, 17, 21, 22, 33, +14, 11, -2, -12, 2, -12, 0, -6, +1, -7, 16, -6, 12, 3, 10, 4, +18, 2, 3, 12, -2, 15, 4, -7, +3, -24, 12, -11, 19, 10, 11, 9, +13, -4, 2, -3, -9, -6, -3, -11, +9, -3, 23, 16, 24, 20, 9, 8, +-5, -5, -15, -13, -4, -22, 17, -17, +17, 9, 15, 22, 7, 8, -5, -4, +4, 2, 8, 5, 5, -12, 9, -17, +1, -3, 11, 2, 22, 4, 8, 10, +-8, 8, -18, -12, -10, -24, 22, 3, +34, 32, 20, 24, -5, -4, -26, -24, +-13, -28, 20, -15, 23, 7, 21, 19, +-1, 15, -17, -2, -1, 3, 10, 13, +4, -1, -1, -19, -9, -16, 8, 4, +25, 15, 17, 8, 0, 1, -17, -12, +-23, -20, 11, -4, 32, 26, 23, 28, +4, 0, -23, -18, -22, -18, 13, -17, +17, -7, 11, 12, 6, 23, -7, 15, +2, -4, 11, -5, -4, -3, -7, -14, +-4, -10, 13, 7, 21, 12, 12, -2, +-3, -2, -20, 7, -18, -4, 14, -20, +25, -3, 13, 28, 2, 23, -14, -1, +-7, -19, 7, -25, 2, -24, 2, 2, +3, 35, 5, 32, 11, -1, 5, -21, +-13, -6, -18, 5, -5, -3, 20, -5, +25, 2, 8, 3, -8, 5, -24, 12, +-12, -2, 14, -26, 10, -11, 10, 26, +9, 37, -8, 5, 1, -29, 2, -30, +-10, -15, -2, 3, 10, 17, 13, 21, +19, 1, 0, -12, -19, 1, -12, 7, +-1, -12, 13, -21, 17, 1, -1, 24, +-4, 14, -7, -2, -4, -14, 3, -21, +-3, -9, 2, 25, 14, 39, 12, 5, +9, -30, -11, -25, -30, -3, -11, 2, +17, 0, 28, 14, 23, 19, -15, 7, +-29, -8, -8, -6, 12, -12, 23, -17, +13, -3, -10, 16, -12, 10, 3, -9, +10, -3, 4, 3, -14, -4, -17, -2, +7, 13, 27, 20, 24, 6, -10, -13, +-34, -24, -20, -31, 10, -15, 34, 29, +29, 56, -10, 19, -25, -34, -18, -37, +5, -4, 25, 17, 14, 11, -5, -5, +-5, -14, -5, -13, 5, 10, 5, 29, +-9, 8, -8, -27, 8, -19, 7, 27, +15, 32, 0, 3, -19, -28, -14, -37, +-6, -20, 11, 19, 20, 54, 4, 39, +-1, -18, -9, -39, -15, -14, 0, 7, +6, 2, 13, -2, 20, 6, -2, 4, +-15, -7, -14, 0, -12, 10, 11, 4, +22, 3, 3, 11, -4, 3, -9, -14, +-8, -18, 8, -1, 8, 1, -1, -10, +-5, 3, 2, 26, 12, 30, 5, 10, +-6, -18, -17, -30, -17, -29, 8, 0, +28, 39, 16, 39, -6, -11, -21, -46, +-23, -16, 6, 28, 23, 33, 18, 8, +6, -16, -15, -27, -14, -20, 5, 11, +6, 20, 4, -5, 0, -17, -8, 17, +-2, 38, 8, 16, 3, -19, -3, -30, +-15, -19, -2, -4, 9, 21, 10, 28, +11, 4, -6, -20, -22, -5, -11, 21, +0, 10, 10, -7, 16, 3, -1, 15, +-16, 6, -13, -14, -12, -20, 6, -10, +17, 10, 6, 35, -2, 37, -5, -5, +-7, -41, -6, -23, -5, 16, 1, 24, +3, 1, 2, -9, 0, 0, -8, 10, +-11, 20, -3, 20, -5, -5, 5, -34, +10, -11, -3, 35, -8, 39, -8, -7, +-10, -43, -3, -23, 2, 14, -2, 41, +3, 45, -1, 12, -5, -33, -10, -32, +-18, 4, -10, 26, 5, 11, 14, -7, +13, 1, -12, 12, -27, 6, -18, 9, +1, 8, 20, -5, 15, -11, -13, 5, +-25, 21, -18, 5, 5, -15, 14, -1, +-3, 10, -25, 12, -18, 14, 4, 22, +21, 13, 10, -13, -27, -20, -36, -9, +-15, 7, 16, 13, 37, 20, 6, 21, +-38, -3, -47, -12, -15, 5, 22, 20, +28, 12, -3, 0, -34, 6, -32, -1, +-5, -11, 18, -3, 8, 19, -16, 21, +-20, 5, -18, 7, 9, 9, 13, -1, +-12, -4, -22, 5, -23, 4, -10, -11, +17, -5, 9, 27, -10, 37, -22, 11, +-28, -17, -17, -16, 9, -4, 11, 18, +-3, 38, -16, 19, -23, -24, -26, -35, +-9, 1, 2, 48, 2, 42, -6, 10, +-17, -10, -28, -18, -19, -12, 4, 13, +4, 37, -17, 19, -25, -25, -23, -22, +-8, 26, 12, 53, -11, 36, -35, -8, +-37, -35, -25, -26, 12, 27, 19, 71, +-11, 39, -44, -38, -49, -61, -21, -1, +13, 65, 19, 73, -5, 23, -48, -37, +-52, -56, -21, -11, 11, 60, 18, 72, +-17, 1, -59, -56, -39, -28, 3, 52, +12, 78, -4, 27, -48, -41, -58, -64, +-8, -9, 31, 75, 11, 88, -40, -4, +-70, -85, -44, -45, 10, 58, 27, 102, +-12, 48, -55, -34, -60, -66, -18, -23, +6, 66, -4, 83, -22, -1, -43, -74, +-29, -38, -1, 69, -12, 103, -27, 27, +-52, -65, -40, -77, 0, 12, 8, 99, +-14, 97, -53, -14, -67, -105, -34, -47, +7, 85, 11, 133, -30, 32, -67, -80, +-53, -77, -7, 23, 10, 109, -26, 79, +-68, -34, -61, -103, -8, -27, 26, 119, +-10, 136, -73, 0, -93, -121, -35, -79, +32, 66, 27, 138, -38, 68, -98, -65, +-81, -106, -11, -5, 27, 120, -4, 118, +-62, -19, -84, -101, -45, -33, 12, 83, +-2, 103, -59, 16, -79, -63, -54, -58, +5, 30, 17, 103, -38, 78, -85, -17, +-76, -87, -17, -29, 17, 65, -15, 85, +-63, 28, -78, -38, -39, -34, -6, 11, +-32, 67, -63, 71, -68, 6, -36, -40, +-6, -9, -22, 57, -66, 57, -85, -3, +-46, -31, -9, -5, -6, 46, -47, 63, +-97, 36, -74, -8, -20, -26, -4, 17, +-31, 51, -78, 30, -88, -13, -42, -8, +9, 43, -11, 53, -85, 15, -113, -22, +-69, -6, 1, 38, 27, 58, -45, 51, +-126, -9, -109, -46, -35, -6, 18, 59, +-4, 81, -84, 17, -113, -27, -66, -7, +-13, 32, -10, 53, -57, 23, -94, -7, +-72, -23, -31, 14, -11, 71, -48, 58, +-94, -4, -93, -41, -57, 4, -14, 62, +-21, 63, -64, 25, -95, -21, -85, -18, +-40, 18, -32, 55, -48, 50, -75, -1, +-86, -8, -45, 29, -38, 64, -68, 33, +-88, -24, -83, -13, -41, 30, -24, 57, +-47, 45, -95, 16, -104, -10, -63, -2, +-35, 36, -44, 46, -71, 26, -79, 14, +-69, 25, -57, 26, -68, -4, -81, -4, +-68, 39, -51, 62, -52, 34, -68, -16, +-76, -5, -78, 43, -81, 58, -71, 27, +-65, -22, -53, -15, -39, 41, -65, 83, +-107, 46, -105, -38, -67, -32, -36, 42, +-37, 83, -70, 40, -107, -15, -97, 3, +-68, 29, -64, 30, -52, 7, -62, 15, +-83, 49, -84, 50, -96, 28, -73, -15, +-52, -6, -58, 38, -79, 51, -106, 21, +-73, -18, -43, 23, -60, 71, -97, 41, +-122, -20, -88, -22, -36, 52, -37, 80, +-82, 28, -122, -20, -107, -6, -68, 47, +-51, 50, -59, 9, -89, -11, -90, 26, +-77, 74, -84, 46, -86, -19, -82, -31, +-76, 38, -76, 86, -75, 28, -80, -26, +-86, 0, -85, 71, -89, 63, -85, -17, +-71, -35, -70, 32, -92, 106, -100, 66, +-86, -33, -76, -49, -77, 25, -102, 102, +-103, 65, -74, -18, -50, -26, -66, 47, +-126, 82, -130, 10, -77, -46, -33, -4, +-41, 88, -113, 93, -153, -2, -103, -48, +-47, 3, -41, 82, -89, 79, -124, -5, +-115, -40, -73, 7, -47, 82, -82, 78, +-107, 1, -106, -42, -107, -4, -77, 69, +-65, 86, -72, 45, -89, -8, -119, -36, +-117, -2, -95, 56, -57, 93, -57, 58, +-94, -26, -113, -43, -118, 24, -100, 108, +-71, 78, -63, -34, -78, -73, -95, 9, +-104, 132, -108, 110, -82, -36, -62, -118, +-85, -17, -115, 156, -105, 158, -75, -3, +-63, -129, -90, -54, -141, 124, -132, 162, +-58, 31, -33, -107, -76, -63, -134, 92, +-141, 151, -75, 59, -44, -80, -88, -80, +-138, 44, -102, 134, -45, 105, -58, -22, +-127, -68, -172, -17, -98, 68, 3, 99, +-24, 50, -132, -5, -195, -33, -127, 5, +-4, 51, -11, 63, -109, 40, -181, -8, +-133, -9, -27, 28, -26, 68, -104, 69, +-162, 11, -135, -31, -64, -24, -36, 58, +-61, 113, -111, 56, -131, -33, -120, -67, +-103, 20, -59, 110, -34, 98, -65, 5, +-132, -72, -164, -24, -112, 77, -34, 120, +-17, 40, -91, -69, -160, -46, -135, 59, +-64, 134, -36, 74, -77, -50, -126, -78, +-132, -1, -85, 119, -48, 134, -63, 21, +-103, -82, -126, -74, -112, 61, -76, 138, +-43, 81, -55, -33, -117, -77, -146, 15, +-122, 102, -59, 108, -14, 11, -76, -81, +-153, -32, -136, 85, -68, 142, -24, 45, +-72, -74, -147, -66, -141, 40, -50, 135, +-5, 89, -85, -20, -166, -77, -139, -20, +-43, 110, 7, 121, -84, 13, -180, -87, +-153, -30, -31, 105, 22, 124, -76, 30, +-184, -79, -173, -57, -49, 67, 33, 141, +-40, 85, -164, -57, -185, -89, -92, 26, +0, 128, -3, 94, -102, -27, -173, -55, +-132, 16, -44, 80, -6, 66, -51, -4, +-134, -17, -158, 9, -88, 55, -6, 62, +-18, 11, -102, -7, -161, 13, -129, 37, +-26, 21, 10, 8, -63, 41, -146, 45, +-146, 8, -63, -23, -4, 20, -48, 79, +-123, 44, -136, -8, -71, -20, -23, 32, +-51, 75, -111, 38, -122, -23, -71, -37, +-38, 50, -55, 119, -97, 49, -109, -71, +-69, -63, -57, 88, -83, 137, -85, 8, +-69, -95, -56, -14, -71, 134, -93, 104, +-103, -44, -68, -111, -32, 13, -60, 176, +-94, 120, -99, -84, -72, -163, -48, 33, +-61, 235, -96, 125, -92, -139, -48, -178, +-38, 83, -72, 252, -105, 82, -101, -168, +-51, -153, -19, 106, -46, 232, -106, 68, +-119, -147, -67, -121, -23, 111, -35, 193, +-91, 14, -122, -143, -62, -46, -8, 164, +-42, 132, -109, -79, -122, -132, -59, 51, +0, 190, -17, 61, -109, -118, -144, -90, +-66, 96, -8, 166, -13, 15, -77, -125, +-126, -58, -87, 134, -28, 165, -27, -27, +-67, -144, -93, -14, -89, 168, -60, 109, +-23, -91, -35, -96, -80, 80, -93, 145, +-79, -2, -46, -112, -18, -16, -33, 135, +-85, 116, -119, -57, -81, -127, -17, 25, +4, 179, -51, 97, -120, -127, -106, -136, +-37, 105, 5, 223, -32, 30, -99, -190, +-118, -92, -65, 160, 7, 194, -6, -13, +-86, -164, -122, -54, -78, 142, -3, 149, +2, -30, -64, -136, -114, -4, -82, 153, +-20, 86, -13, -97, -41, -93, -75, 94, +-86, 145, -53, -16, -31, -118, -29, 0, +-55, 138, -82, 77, -61, -81, -34, -89, +-29, 64, -54, 146, -80, 34, -67, -105, +-19, -71, -13, 91, -65, 137, -91, -9, +-59, -121, -18, -20, -10, 144, -63, 99, +-91, -86, -55, -114, -19, 64, -21, 165, +-53, 25, -68, -133, -58, -70, -36, 115, +-29, 140, -47, -17, -55, -129, -55, -26, +-54, 144, -49, 135, -40, -69, -28, -156, +-44, 22, -67, 186, -74, 83, -29, -127, +12, -115, -33, 78, -99, 167, -89, 28, +-23, -113, 20, -77, -19, 77, -91, 127, +-100, 13, -31, -86, 19, -40, -28, 73, +-86, 86, -88, -4, -25, -57, 20, 13, +-28, 65, -106, 17, -86, -51, 11, -7, +16, 83, -54, 63, -106, -41, -83, -65, +9, 23, 37, 91, -49, 55, -119, -38, +-84, -73, 7, -1, 34, 94, -30, 72, +-99, -40, -88, -83, -11, 2, 22, 75, +-15, 57, -68, -2, -76, -34, -58, -37, +-17, -7, 12, 71, -17, 95, -78, 0, +-99, -112, -42, -53, 23, 118, 5, 140, +-59, -37, -83, -151, -63, -38, -15, 137, +11, 138, -18, -35, -90, -150, -79, -61, +9, 135, 17, 165, -62, -31, -77, -190, +-21, -53, -7, 174, -40, 140, -60, -75, +-38, -147, -6, 3, -19, 124, -55, 78, +-52, -37, -34, -78, -12, -27, -21, 61, +-50, 79, -38, -8, -15, -57, -24, -14, +-61, 40, -61, 7, 8, -4, 37, 50, +-44, 39, -130, -72, -86, -90, 41, 72, +87, 160, -19, 22, -162, -168, -133, -113, +30, 100, 132, 198, 23, 49, -164, -170, +-174, -188, 5, 54, 139, 268, 46, 135, +-140, -199, -170, -274, -21, 54, 98, 295, +60, 133, -80, -181, -144, -217, -70, 9, +52, 200, 52, 155, -57, -60, -102, -199, +-33, -85, 22, 155, -32, 170, -61, -27, +-7, -142, 11, -45, -52, 46, -75, 51, +-17, 55, 13, 39, -19, -68, -37, -122, +-54, 14, -61, 159, -8, 106, 47, -106, +-30, -161, -105, -9, -36, 148, 32, 113, +15, -60, -53, -145, -70, -51, -26, 114, +11, 137, -6, -25, -39, -157, -49, -43, +-42, 154, -33, 96, 11, -135, 37, -126, +-31, 124, -121, 167, -90, -86, 65, -221, +123, 0, -29, 248, -195, 142, -116, -180, +73, -271, 125, 28, 18, 316, -133, 178, +-180, -220, -31, -313, 149, 11, 122, 312, +-95, 217, -215, -152, -94, -340, 107, -104, +149, 314, -27, 341, -171, -129, -131, -439, +17, -98, 102, 381, 64, 269, -68, -218, +-147, -308, -72, 53, 54, 229, 80, 44, +14, -109, -92, -45, -122, 12, -18, -14, +79, 12, 56, 62, -53, 10, -100, -71, +-63, -25, 22, 29, 52, 2, 18, 3, +-65, 79, -110, 28, -25, -165, 77, -124, +51, 171, -84, 252, -118, -89, 8, -316, +81, -59, 4, 279, -81, 205, -84, -157, +7, -273, 63, -15, 32, 248, -58, 139, +-106, -157, -46, -203, 70, 58, 86, 191, +-44, 16, -121, -148, -56, -63, 41, 88, +65, 69, 25, -28, -55, -81, -114, -32, +-67, 53, 91, 96, 118, 11, -28, -132, +-160, -106, -110, 94, 63, 196, 139, -4, +39, -219, -128, -110, -159, 173, -19, 184, +141, -85, 120, -192, -51, -8, -196, 141, +-123, 38, 130, -75, 232, -45, -45, 49, +-276, 36, -116, -48, 175, -70, 193, 38, +-35, 125, -190, 1, -145, -156, 57, -100, +203, 137, 84, 166, -186, -31, -208, -182, +47, -93, 207, 104, 64, 162, -130, 38, +-145, -163, -9, -163, 103, 40, 122, 222, +-8, 90, -197, -165, -114, -208, 137, 45, +174, 227, -37, 78, -162, -161, -80, -157, +69, 55, 110, 128, 11, 70, -90, -77, +-66, -111, 23, -29, 61, 104, 16, 78, +-29, -69, -10, -94, -14, 28, -30, 77, +4, -37, 77, -51, 11, 44, -99, 86, +-38, -60, 66, -142, 33, -9, -11, 187, +-3, 117, -15, -152, -51, -225, -2, 9, +81, 238, 39, 164, -67, -94, -91, -277, +21, -144, 104, 205, 61, 363, -68, 11, +-106, -419, -14, -293, 103, 240, 124, 442, +-4, 67, -155, -377, -110, -348, 92, 96, +194, 435, 54, 217, -173, -299, -143, -401, +77, 20, 160, 367, 39, 183, -51, -168, +-73, -241, -60, -38, 21, 127, 140, 132, +106, 24, -102, -90, -182, -113, 3, -17, +198, 81, 120, 63, -95, 0, -131, -42, +31, -45, 68, -57, 3, 21, 25, 100, +77, 61, -25, -84, -132, -116, -18, 7, +159, 75, 117, 41, -73, -2, -112, -13, +-4, -83, 80, -79, 72, 75, 24, 170, +-17, -12, -40, -213, -42, -99, 37, 178, +113, 159, 82, -127, -57, -177, -132, 65, +-9, 161, 139, -56, 111, -150, -28, 41, +-77, 140, -18, -20, 46, -150, 41, -40, +46, 84, 55, 76, 2, -13, -70, -82, +-38, -72, 61, 7, 124, 98, 58, 60, +-78, -57, -103, -107, 16, -25, 142, 75, +112, 79, -36, -23, -119, -103, -19, -41, +115, 62, 111, 63, -15, -39, -57, -66, +8, 0, 58, 71, 16, 8, -17, -106, +29, -81, 103, 114, 55, 192, -101, -89, +-101, -315, 77, -81, 212, 359, 103, 281, +-149, -245, -216, -453, 57, -20, 306, 433, +158, 280, -179, -235, -219, -439, 44, -72, +228, 350, 165, 301, -36, -130, -166, -349, +-87, -149, 132, 180, 202, 262, 49, 57, +-122, -203, -78, -258, 84, 5, 117, 238, +12, 184, -18, -120, 31, -258, 54, -84, +24, 175, -49, 203, -20, -61, 121, -231, +156, -84, -38, 198, -183, 142, -32, -141, +233, -200, 206, 82, -82, 202, -230, -37, +-19, -236, 258, -46, 179, 234, -102, 90, +-150, -210, 48, -175, 155, 159, 61, 165, +-46, -110, -9, -171, 75, 67, 66, 132, +-23, -74, -27, -146, 53, 30, 118, 152, +55, -6, -59, -167, -47, -77, 74, 133, +120, 85, 36, -123, -19, -118, 12, 103, +23, 96, -4, -132, 63, -137, 129, 108, +57, 165, -110, -80, -100, -206, 126, -37, +243, 159, 43, 111, -182, -84, -94, -166, +153, -35, 202, 103, -4, 64, -99, -56, +35, -43, 115, 4, 1, -49, -45, -104, +78, 46, 164, 192, 22, 32, -137, -252, +-47, -229, 157, 145, 192, 307, 15, 41, +-127, -292, -75, -221, 106, 80, 172, 232, +78, 95, -42, -121, -50, -221, -11, -91, +40, 141, 148, 166, 181, -11, -24, -172, +-204, -105, -61, -8, 233, 62, 286, 80, +-13, 48, -265, -91, -98, -191, 253, -42, +252, 183, -55, 166, -188, -126, 28, -249, +197, -31, 84, 194, -67, 67, -4, -154, +119, -115, 60, 88, -55, 94, 2, -110, +129, -159, 96, 39, -14, 203, -51, 24, +48, -265, 115, -201, 55, 166, -24, 285, +18, -51, 98, -303, 61, -136, -25, 147, +-39, 148, 79, -12, 185, -97, 70, -107, +-152, -68, -95, 29, 181, 136, 238, 47, +-24, -132, -143, -181, 18, -6, 151, 146, +90, 87, -6, -115, 35, -196, 91, -19, +-17, 149, -78, 80, 101, -158, 234, -145, +55, 65, -183, 143, -100, -67, 198, -191, +272, -9, 9, 143, -197, 29, -60, -172, +212, -88, 207, 99, -51, 85, -150, -136, +57, -132, 219, 107, 81, 156, -118, -123, +-65, -287, 160, -12, 197, 279, 5, 152, +-129, -248, -8, -338, 170, -22, 164, 320, +-13, 236, -75, -207, 17, -414, 82, -91, +85, 339, 84, 240, 63, -179, -45, -324, +-84, -52, 74, 162, 235, 91, 110, -44, +-113, -79, -136, -47, 113, -68, 238, -45, +56, 29, -125, 95, -4, 19, 181, -119, +78, -161, -103, -53, -12, 109, 211, 149, +144, 16, -99, -215, -153, -237, 111, 4, +281, 265, 105, 175, -166, -179, -130, -346, +148, -128, 240, 234, 89, 273, -95, -33, +-82, -338, 72, -261, 176, 97, 83, 307, +-32, 128, -13, -237, 72, -328, 65, -52, +23, 252, 56, 195, 68, -107, 38, -265, +-8, -125, 27, 81, 105, 127, 105, 60, +-8, -85, -44, -185, 52, -151, 150, 70, +109, 207, -39, 60, -55, -220, 89, -267, +137, 9, 14, 218, -14, 144, 99, -128, +75, -237, -50, -142, -18, 77, 177, 200, +187, 103, -77, -168, -196, -333, 96, -100, +344, 261, 109, 290, -211, -142, -128, -392, +189, -166, 242, 213, 49, 228, -82, -29, +-14, -195, 77, -194, 58, -59, 56, 99, +105, 194, 102, 5, -29, -231, -93, -229, +41, 18, 218, 167, 163, 107, -40, -40, +-135, -192, -9, -202, 190, -28, 180, 210, +35, 161, -38, -114, -17, -287, -5, -169, +57, 76, 184, 222, 220, 160, -4, -153, +-261, -410, -127, -235, 305, 305, 421, 478, +26, -45, -333, -594, -179, -391, 232, 316, +363, 528, 104, 8, -120, -517, -125, -339, +-22, 190, 122, 347, 255, 14, 210, -277, +-98, -171, -279, 41, -37, 73, 373, -40, +346, -15, -88, 33, -309, -76, -8, -208, +284, -49, 185, 212, -18, 106, -36, -223, +49, -246, 24, 82, 34, 168, 99, -58, +115, -165, 30, -5, -4, 54, 12, -70, +37, -96, 93, 12, 109, 60, 57, -48, +-31, -110, 31, -64, 86, 38, 51, 40, +16, -67, 115, -123, 142, -32, -30, 87, +-138, 11, 45, -142, 275, -142, 192, 54, +-50, 141, -149, -35, -48, -225, 124, -145, +281, 108, 216, 157, -88, -20, -258, -210, +-77, -182, 273, 19, 389, 193, 114, 106, +-267, -181, -299, -279, 118, -56, 472, 197, +289, 131, -185, -87, -326, -211, -26, -135, +299, 34, 313, 141, 87, 73, -142, -127, +-195, -215, -4, -101, 260, 113, 317, 154, +72, -16, -199, -215, -199, -188, 81, 25, +354, 159, 262, 82, -91, -127, -249, -231, +-18, -117, 252, 134, 270, 170, 16, -48, +-151, -234, -37, -149, 132, 48, 141, 137, +91, 72, 50, -130, -38, -246, -19, -106, +100, 192, 127, 189, 70, -117, 30, -312, +16, -142, 21, 168, 70, 228, 85, -22, +62, -327, 10, -245, 41, 137, 129, 305, +84, -16, -46, -336, -54, -216, 138, 125, +214, 204, 70, -14, -102, -181, -73, -150, +80, -11, 204, 49, 191, 39, 0, -8, +-154, -65, -89, -140, 178, -128, 301, 42, +158, 183, -146, 64, -236, -244, 0, -304, +301, 28, 371, 327, 46, 139, -319, -300, +-282, -365, 218, 36, 500, 324, 249, 108, +-262, -247, -386, -254, 25, 2, 484, 120, +372, 46, -175, -30, -331, -72, -7, -123, +279, -119, 217, 13, 97, 152, -17, 102, +-157, -166, -139, -339, 206, -93, 431, 329, +121, 282, -309, -268, -271, -500, 219, -45, +448, 422, 123, 228, -268, -282, -168, -392, +200, -36, 268, 258, 50, 145, -97, -140, +-11, -223, 102, -55, 110, 46, 31, 10, +18, 5, 81, 41, 69, -68, -28, -214, +-10, -109, 152, 159, 155, 206, -37, -86, +-118, -321, 87, -183, 252, 173, 58, 265, +-159, -24, -48, -305, 215, -215, 223, 82, +-3, 183, -180, 61, -30, -107, 212, -199, +187, -167, 7, 57, -40, 242, 15, 73, +-7, -278, 42, -291, 168, 69, 196, 259, +-21, 73, -227, -218, -75, -255, 333, -51, +381, 201, -95, 174, -376, -153, -63, -312, +362, -49, 331, 229, -6, 76, -247, -164, +-164, -143, 167, -9, 326, 1, 144, 27, +-116, 54, -157, -62, -30, -171, 174, -78, +261, 97, 92, 87, -143, -34, -149, -151, +57, -146, 233, -15, 217, 150, -6, 108, +-196, -119, -115, -260, 184, -111, 329, 180, +63, 203, -214, -83, -102, -305, 164, -116, +178, 151, 65, 126, -42, -54, -46, -116, +63, -96, 135, -62, 34, 51, -56, 87, +60, -43, 118, -132, 38, -51, -30, -16, +46, -32, 79, 60, 32, 70, -14, -138, +53, -208, 125, 71, 32, 180, -102, -91, +-3, -215, 235, 41, 135, 152, -165, -103, +-152, -200, 193, 29, 283, 161, 2, -29, +-194, -172, -43, -110, 198, 25, 154, 113, +-44, 64, -81, -124, 102, -227, 121, -10, +-39, 189, -75, 48, 130, -170, 176, -74, +-37, 41, -126, -83, 48, -92, 189, 148, +81, 152, -56, -235, -47, -307, 37, 93, +71, 290, 108, 5, 97, -217, -52, -126, +-142, -32, 46, 34, 219, 147, 108, 80, +-42, -242, -43, -264, -46, 102, -8, 245, +189, -17, 238, -162, -86, -61, -285, -92, +32, -96, 346, 161, 131, 291, -201, -138, +-106, -487, 142, -129, 115, 410, -4, 310, +25, -225, 46, -393, -3, -88, -15, 205, +8, 154, 97, -2, 145, -100, 5, -184, +-148, -166, -31, 103, 169, 313, 154, 30, +-7, -346, -102, -244, -82, 153, 91, 221, +232, 29, 87, -114, -192, -186, -156, -159, +188, 91, 274, 293, -42, 39, -197, -324, +48, -277, 162, 152, -24, 341, -63, 41, +127, -363, 108, -252, -89, 226, -68, 259, +127, -160, 117, -232, -54, 113, -76, 57, +84, -217, 137, 33, -12, 334, -96, -128, +14, -530, 126, 73, 65, 594, -22, -24, +-18, -655, 17, -90, 38, 556, 42, 95, +44, -486, 35, -92, -29, 395, -62, -41, +64, -426, 145, 82, 40, 509, -87, -118, +-62, -633, 14, -23, 111, 610, 159, 124, +33, -512, -185, -193, -131, 270, 176, 78, +256, -167, -25, 84, -191, 120, 0, -247, +121, -263, 26, 219, 2, 357, 109, -81, +10, -388, -168, -168, -81, 229, 223, 277, +267, -33, -56, -282, -312, -139, -115, 100, +253, 63, 315, -5, 30, 114, -264, 33, +-233, -363, 110, -289, 363, 397, 139, 552, +-245, -257, -230, -764, 130, -67, 252, 696, +43, 346, -147, -488, -84, -489, 71, 171, +88, 400, 32, 8, 2, -218, 5, -40, +-56, 23, -36, -107, 115, -7, 160, 225, +-93, 53, -184, -304, 124, -183, 260, 246, +-119, 255, -266, -176, 139, -318, 284, 4, +-72, 314, -159, 119, 82, -249, 40, -250, +-110, 101, 63, 216, 232, -31, -30, -89, +-219, 39, -14, -32, 155, -249, 56, 34, +-9, 392, 43, 106, -41, -473, -121, -294, +63, 333, 172, 371, -12, -123, -94, -288, +30, -53, 1, -4, -47, 20, 99, 242, +147, 229, -73, -340, -172, -538, -6, 107, +144, 654, 145, 199, 39, -479, -176, -407, +-215, 126, 82, 316, 348, 143, 105, -82, +-285, -188, -173, -172, 152, 20, 102, 190, +4, 175, 129, -51, 0, -268, -301, -183, +-77, 161, 364, 307, 174, 10, -265, -255, +-141, -196, 183, 94, 45, 215, -166, 107, +52, -202, 263, -214, -50, 116, -316, 257, +9, -101, 333, -256, 52, 104, -274, 197, +-51, -155, 233, -183, 85, 234, -203, 193, +-122, -249, 172, -289, 205, 157, -97, 313, +-223, 39, 41, -279, 186, -250, 18, 120, +-64, 406, -16, 84, -66, -455, -60, -317, +137, 371, 226, 464, -65, -171, -323, -455, +-127, -10, 298, 252, 274, -6, -111, -46, +-259, 236, -29, 64, 81, -511, 53, -308, +97, 525, 74, 596, -139, -335, -175, -674, +81, 47, 212, 542, -14, 96, -127, -341, +25, -91, 24, 158, -115, 14, 26, -115, +291, 124, 36, 140, -384, -168, -248, -286, +322, 121, 414, 351, -48, 63, -434, -238, +-208, -153, 234, -12, 264, -1, -18, 196, +-104, 290, -8, -102, -67, -521, -155, -110, +50, 467, 329, 298, 112, -280, -326, -270, +-309, 79, 227, 132, 357, 7, -106, 44, +-327, 19, 61, -177, 271, -126, -75, 202, +-234, 279, 101, -123, 243, -334, -143, -52, +-249, 307, 95, 124, 278, -170, -8, -121, +-224, 149, -97, 14, 123, -178, 85, -12, +-34, 264, -22, 80, 77, -247, -19, -153, +-190, 119, -80, 181, 189, 3, 248, -62, +-32, -117, -314, -16, -221, 62, 228, 123, +323, -18, -91, -49, -282, -37, 60, -19, +154, -2, -192, 69, -109, 84, 320, -43, +183, -67, -377, -36, -308, 65, 254, 12, +356, 4, -72, -18, -266, 85, -87, -16, +50, -154, 102, -69, 137, 270, 27, 190, +-207, -304, -198, -342, 43, 260, 273, 498, +157, -129, -122, -525, -323, -75, -132, 479, +201, 190, 335, -296, 50, -197, -377, 236, +-314, 89, 234, -252, 422, -50, -112, 386, +-363, 93, 23, -454, 273, -192, -83, 451, +-196, 294, 106, -391, 182, -344, -142, 266, +-187, 427, 89, -116, 168, -403, -68, -80, +-155, 378, 62, 208, 72, -258, -72, -284, +-90, 178, 133, 285, 82, -93, -112, -236, +-186, 34, 27, 162, 158, -14, 140, -32, +-63, 35, -250, -36, -145, -91, 175, 57, +296, 110, -36, -28, -272, -59, -146, 34, +138, 7, 131, -94, 31, 30, -104, 173, +-79, 33, -45, -197, 61, -106, 69, 154, +6, 153, -79, -36, -71, -113, -8, -25, +70, -24, 97, 26, -83, 143, -157, 120, +3, -142, 182, -245, -13, -5, -179, 257, +-13, 206, 178, -97, 5, -286, -167, -143, +-101, 265, 91, 330, 115, -112, 5, -446, +-71, -14, -76, 460, -40, 145, -14, -435, +101, -193, 78, 381, -69, 210, -138, -349, +21, -183, 46, 364, -6, 186, 12, -379, +4, -233, -88, 360, -40, 291, 145, -263, +70, -292, -245, 210, -219, 256, 248, -187, +326, -282, -144, 201, -368, 377, -2, -98, +177, -452, 11, -63, -17, 437, 74, 222, +-61, -336, -173, -291, -22, 286, 137, 321, +74, -272, -118, -411, -104, 276, 112, 525, +120, -169, -180, -577, -239, 64, 154, 519, +298, -25, -51, -446, -292, 46, -69, 444, +170, -31, 67, -432, -148, -61, -53, 377, +157, 160, 44, -253, -216, -184, -119, 182, +139, 230, 133, -168, -78, -309, -110, 120, +-3, 436, 20, 5, -28, -453, -32, -124, +67, 390, 33, 165, -99, -339, -117, -152, +72, 346, 101, 256, -33, -342, -124, -412, +-31, 206, 56, 546, 37, 19, -42, -539, +-58, -172, -26, 465, 14, 255, 43, -421, +-13, -263, -107, 387, -76, 318, 153, -348, +86, -321, -169, 282, -187, 327, 113, -237, +134, -304, -67, 217, -92, 329, 45, -158, +-13, -357, -159, 98, -22, 358, 192, -11, +116, -349, -224, -15, -205, 332, 71, 79, +152, -326, -50, -105, -30, 290, 36, 167, +-48, -246, -168, -198, 3, 171, 125, 251, +44, -43, -51, -269, -72, -108, -68, 198, +-49, 277, 70, -79, 42, -296, -35, -77, +-72, 284, 67, 119, -7, -181, -175, -129, +-134, 172, 203, 110, 228, -145, -124, -119, +-314, 120, -59, 157, 169, -85, 82, -126, +-37, 45, -61, 158, -35, -75, -99, -159, +-3, 60, 88, 248, 40, -40, -150, -279, +-78, -16, 99, 299, 60, 75, -124, -281, +-96, -54, 49, 304, -10, 95, -51, -380, +52, -170, 77, 403, -149, 358, -177, -316, +61, -457, 192, 130, -72, 445, -172, -15, +44, -324, 119, 52, -148, 318, -178, -109, +129, -414, 158, 66, -129, 478, -187, 84, +94, -386, 105, -112, -132, 239, -200, 25, +92, -200, 204, 100, -30, 266, -242, -40, +-89, -264, 132, -67, 42, 110, -136, 94, +-40, 62, 170, 2, 16, -103, -255, -57, +-179, 96, 185, 18, 183, -96, -101, 42, +-157, 175, 30, -58, -8, -224, -134, 50, +-14, 274, 164, -44, 66, -329, -192, -11, +-182, 419, 11, 175, 165, -336, 36, -318, +-140, 140, -136, 267, 84, 51, 99, -72, +-118, -35, -190, -79, 81, -86, 197, 79, +-92, 171, -285, 49, -24, -131, 255, -104, +70, 31, -248, 183, -215, 42, 122, -221, +184, -219, -43, 264, -200, 416, -22, -81, +76, -514, -79, -163, -132, 358, 150, 279, +204, -46, -223, -112, -392, -57, 68, -197, +392, -76, 19, 258, -312, 350, -107, -95, +114, -334, -64, -142, -105, 169, 139, 165, +147, 77, -207, -15, -295, -119, 7, -117, +231, 53, 129, 157, -129, -11, -246, -107, +-119, -20, 158, 122, 159, 54, -94, -6, +-201, -104, 10, -122, 53, 0, -100, 273, +-52, 197, 157, -197, 31, -334, -286, 2, +-204, 249, 210, 125, 279, 24, -128, -6, +-370, -118, -86, -205, 238, 67, 79, 237, +-172, 68, -85, -112, 111, 20, -55, -1, +-237, -201, -16, -84, 277, 329, 47, 300, +-351, -202, -189, -352, 257, -3, 179, 239, +-270, 67, -235, -26, 169, 17, 173, -35, +-203, -149, -180, -11, 143, 193, 116, 137, +-240, -81, -224, -159, 160, -60, 273, 80, +-84, 187, -344, 62, -138, -175, 152, -196, +161, 72, -66, 174, -103, 50, -34, 38, +-26, 42, -169, -198, -96, -287, 194, 167, +255, 501, -157, 93, -445, -471, -122, -319, +322, 201, 232, 341, -220, 86, -272, -123, +32, -144, 131, -62, -138, 62, -115, 113, +174, 68, 138, -35, -333, -84, -342, -77, +229, 30, 438, 130, -122, 86, -546, -76, +-132, -134, 350, 21, 210, 154, -253, 73, +-222, -119, 41, -84, 86, 89, -113, 80, +-77, -120, 61, -54, 52, 184, -96, 108, +-152, -202, -39, -145, 83, 213, 48, 196, +-150, -158, -117, -217, 78, 108, 135, 195, +-176, -27, -233, -174, 20, -15, 257, 123, +-17, 107, -288, -46, -142, -97, 193, -2, +111, 98, -248, 31, -190, -90, 172, -21, +225, 80, -234, 35, -337, -103, 59, -15, +340, 110, -56, 67, -358, -112, -86, -49, +310, 122, 42, 89, -406, -139, -189, -151, +357, 126, 262, 226, -365, -15, -401, -233, +110, -68, 334, 139, -93, 151, -243, 8, +24, -40, 135, -68, -226, -79, -265, -19, +182, 119, 370, 143, -110, -8, -543, -142, +-178, -121, 387, 71, 319, 180, -293, 83, +-399, -124, 26, -108, 292, 48, -45, 72, +-234, -55, -9, -10, 165, 136, -148, 2, +-302, -227, 82, -56, 347, 345, -17, 196, +-451, -291, -214, -301, 231, 173, 242, 274, +-141, -31, -206, -109, -4, 31, 39, -44, +-171, -163, -145, 89, 153, 314, 248, 103, +-111, -245, -423, -212, -186, 23, 248, 164, +259, 147, -114, 57, -249, -106, -87, -216, +39, -88, -38, 166, -23, 277, 52, 70, +23, -186, -147, -242, -191, 2, 16, 190, +187, 175, 16, -28, -263, -159, -156, -109, +135, 63, 136, 117, -138, 22, -199, -7, +-4, 22, 104, 9, -34, -85, -178, -5, +-37, 57, 161, 33, 16, -38, -295, 53, +-188, 32, 191, -100, 223, -95, -153, 135, +-295, 208, -44, -37, 158, -213, 10, -86, +-153, 203, -41, 146, 62, -123, -50, -232, +-158, 107, 4, 261, 66, -6, -77, -288, +-175, -19, 58, 280, 189, 89, -51, -222, +-366, -107, -204, 181, 247, 74, 334, -118, +-109, -75, -424, 140, -191, 55, 170, -89, +154, -72, -58, 144, -68, 136, -33, -89, +-128, -217, -194, 14, 50, 261, 192, 90, +17, -212, -206, -168, -91, 163, -11, 149, +-97, -90, -87, -94, 148, 215, 170, 150, +-156, -240, -382, -339, -130, 150, 257, 475, +223, 111, -108, -427, -284, -330, -126, 256, +36, 390, 81, -41, -15, -319, -20, 21, +-36, 280, -58, -2, -150, -336, -118, -36, +65, 352, 187, 140, 31, -316, -248, -177, +-253, 293, -13, 210, 188, -246, 59, -219, +-107, 262, -104, 269, 5, -183, -132, -304, +-182, 99, 62, 256, 292, -33, 15, -176, +-330, 57, -248, 139, 73, -84, 153, -95, +1, 168, -51, 153, -50, -225, -70, -257, +-174, 196, -76, 383, 107, -44, 173, -399, +-91, -129, -240, 279, -77, 250, 92, -72, +-35, -164, -132, 3, 53, 80, 140, -49, +-78, -83, -304, 112, -128, 165, 152, -76, +204, -210, -50, 43, -219, 194, -190, -9, +30, -149, 114, 95, 1, 186, -102, -90, +-31, -273, 32, -16, -130, 245, -159, 144, +41, -65, 184, -96, -63, -44, -220, -91, +-74, 10, 128, 249, -2, 293, -153, -162, +-95, -476, 67, -185, 95, 393, -56, 426, +-170, -35, -132, -331, 43, -206, 70, 34, +21, 175, -54, 241, -60, 70, -137, -185, +-97, -241, 15, 63, 114, 178, 50, 15, +-119, -115, -186, 64, -80, 139, 117, -39, +51, -160, -120, -4, -135, 119, 108, 7, +41, -1, -199, 110, -153, 63, 180, -251, +109, -234, -215, 152, -171, 396, 132, 70, +103, -269, -177, -182, -120, 118, 67, 145, +45, -19, -158, -65, -43, -5, 117, 54, +90, 29, -185, -2, -230, -76, -22, -52, +204, 9, 111, 100, -134, 103, -186, 87, +-40, -35, 47, -209, -88, -207, -103, 105, +97, 372, 213, 158, -97, -245, -321, -294, +-159, 62, 132, 203, 116, 38, 14, -86, +5, 48, -13, 71, -177, -70, -260, -95, +-23, 64, 261, 63, 212, -132, -143, -83, +-257, 234, -69, 312, 67, -121, -58, -438, +-81, -183, 127, 311, 209, 344, -78, 7, +-372, -189, -196, -116, 221, -65, 272, -47, +-95, 107, -230, 213, -12, 65, 79, -156, +-92, -93, -100, 79, 53, 64, 45, -127, +-118, -119, -94, 119, 120, 277, 112, 93, +-176, -237, -321, -295, -18, 0, 281, 284, +192, 191, -153, -78, -258, -165, -87, 11, +72, 88, 38, -44, -51, -145, -5, 11, +85, 178, 57, 124, -152, -16, -231, -58, +-53, -91, 215, -181, 162, -30, -71, 301, +-162, 307, -34, -167, -30, -401, -79, -27, +9, 331, 146, 75, 53, -276, -137, -58, +-128, 334, -4, 183, 20, -279, -68, -276, +-8, 109, 90, 197, 27, -86, -180, -76, +-109, 233, 100, 214, 75, -263, -178, -436, +-171, 26, 96, 475, 237, 303, -3, -201, +-288, -354, -185, -90, 157, 184, 184, 153, +-130, -12, -167, -81, 113, -7, 199, 21, +-123, 6, -267, 59, -47, 95, 210, -104, +125, -291, -55, -24, -101, 423, -27, 298, +-12, -296, -72, -420, -45, 47, 81, 287, +131, 10, -51, -104, -141, 144, -33, 195, +45, -149, -154, -326, -164, -64, 167, 206, +357, 166, -76, 27, -454, 29, -190, 19, +236, -137, 141, -264, -117, -57, 12, 302, +129, 325, -106, -44, -283, -282, 18, -135, +224, 61, 61, 26, -145, -30, -51, 88, +74, 182, 86, 85, -51, -126, -177, -240, +-105, -139, 173, 135, 250, 268, -21, 93, +-200, -111, -84, -70, 43, -28, -61, -168, +-44, -100, 139, 284, 192, 353, -74, -132, +-239, -390, -114, -14, 47, 261, 12, -30, +-12, -234, 115, 105, 118, 318, -135, -27, +-323, -312, -96, -46, 203, 206, 182, 11, +-61, -189, -110, 62, -13, 306, 20, 55, +-75, -336, -91, -263, 28, 144, 162, 283, +148, 80, -45, -91, -170, -61, -115, -50, +45, -80, 105, 12, 122, 172, 64, 91, +-72, -177, -163, -204, -30, 147, 175, 342, +107, 8, -167, -415, -217, -268, 111, 274, +272, 422, 4, 22, -277, -288, -119, -148, +90, 54, 28, 17, -80, -37, 52, 103, +131, 184, -60, 5, -248, -221, -144, -163, +125, 107, 191, 206, 62, -10, -84, -198, +-81, -7, -86, 233, -40, 66, 52, -258, +144, -161, 74, 148, -27, 161, -51, -2, +-17, 30, -17, 37, 0, -179, 79, -208, +100, 133, 14, 293, -81, 0, -23, -206, +31, -27, 35, 109, 8, -68, -6, -141, +-78, 102, -47, 280, 73, 58, 93, -287, +-67, -293, -162, 78, -42, 362, 72, 183, +30, -222, -62, -297, 11, 20, 54, 241, +-78, 94, -194, -119, -22, -86, 203, 45, +150, 46, -95, -28, -159, -28, 22, 20, +127, 32, 1, -2, -130, -27, 20, -13, +227, 15, 122, 32, -145, 4, -100, 10, +96, 30, 62, -18, -79, -117, 41, -69, +186, 109, 44, 163, -136, -1, -85, -123, +31, -78, -13, -2, -12, 6, 96, 60, +109, 126, -77, 24, -207, -151, -145, -129, +35, 63, 151, 125, 109, 12, -32, -70, +-123, -14, -90, 22, -58, 3, -35, -1, +42, 41, 162, 33, 103, -43, -74, -119, +-149, -59, 7, 138, 112, 241, 11, 14, +-78, -313, 103, -252, 275, 182, 70, 372, +-269, 78, -226, -260, 155, -225, 324, 17, +140, 164, -121, 149, -160, 24, -55, -132, +52, -163, 63, -14, 74, 132, 22, 127, +-61, -2, -82, -105, 5, -89, 39, 28, +-44, 85, -112, -26, -82, -115, 64, 12, +168, 190, 85, 103, -182, -150, -266, -216, +-54, -15, 218, 151, 207, 128, 25, 26, +-124, -22, -134, -93, -38, -148, 126, -25, +206, 180, 93, 114, -63, -146, -84, -106, +25, 194, 75, 143, 73, -260, 40, -261, +45, 174, 31, 271, 22, -60, -21, -81, +-42, 159, -30, -45, 54, -464, 96, -133, +10, 597, -118, 508, -94, -352, 61, -644, +73, -40, -39, 412, -92, 154, -34, -156, +-26, -11, 3, 162, 51, -52, 26, -296, +-89, -122, -79, 239, 57, 267, 136, -29, +15, -154, -124, -12, -55, 13, 117, -184, +169, -177, 20, 235, -78, 451, -1, 31, +127, -456, 110, -293, -6, 193, -68, 224, +21, -67, 138, -21, 108, 220, -48, 18, +-103, -391, 36, -235, 128, 331, 11, 390, +-124, -142, -38, -378, 96, 25, 41, 345, +-127, 70, -121, -326, 39, -211, 118, 215, +32, 299, -79, -51, -126, -246, -125, -32, +-16, 149, 171, -17, 211, -152, -44, 47, +-265, 233, -99, 24, 199, -237, 170, -127, +-36, 120, -26, 101, 92, -36, 32, -15, +-94, 54, -1, 1, 187, -67, 170, -38, +-31, 2, -70, 10, 46, 59, 43, 68, +-63, -41, -9, -104, 159, -13, 144, 47, +-42, -16, -155, -21, -95, 84, -3, 46, +82, -108, 77, -51, 22, 147, -73, 50, +-132, -251, -127, -176, 26, 275, 165, 380, +84, -118, -123, -457, -141, -109, 45, 346, +60, 201, -87, -201, -43, -183, 213, 151, +191, 162, -73, -98, -185, -159, -24, 25, +66, 46, 129, -65, 189, 42, 141, 237, +-87, 81, -209, -297, -40, -294, 202, 139, +247, 342, 36, 24, -140, -259, -123, -53, +47, 244, 97, 71, 19, -299, -70, -225, +7, 210, 76, 332, 19, -1, -115, -205, +-115, -45, -35, 42, 13, -162, 57, -168, +103, 247, 25, 456, -144, -19, -157, -506, +-18, -271, 119, 255, 124, 259, 68, -62, +-65, -42, -118, 144, -5, -27, 156, -285, +107, -103, -34, 213, -31, 148, 93, -89, +102, -18, 5, 156, -24, 12, 7, -293, +26, -243, 53, 179, 119, 423, 104, 116, +-32, -331, -157, -292, -98, 121, 65, 226, +125, -63, 47, -154, -9, 115, -25, 218, +-90, -50, -131, -230, -49, -82, 81, 69, +102, 47, 31, 46, -55, 123, -105, 42, +-65, -187, 8, -221, 39, 40, 51, 244, +118, 125, 81, -93, -93, -114, -183, -40, +-28, -53, 177, -21, 237, 160, 97, 203, +-83, -83, -138, -312, -16, -113, 117, 228, +130, 218, 40, -37, -26, -135, 16, -40, +57, -7, 7, -66, -75, -28, -15, 126, +72, 190, 50, 12, -49, -228, -36, -199, +-2, 84, -14, 219, -37, 38, 25, -121, +29, -12, -43, 82, -67, -74, 2, -167, +45, 28, 7, 224, -31, 90, -43, -126, +-4, -112, 51, 22, 88, 14, 32, -30, +-22, 42, -47, 125, -1, 12, 60, -166, +98, -135, 48, 75, 8, 167, 37, 35, +62, -81, -16, -36, -90, 17, -18, -52, +135, -51, 169, 75, 9, 121, -134, -33, +-91, -140, 37, -41, 53, 114, 20, 93, +21, -70, 4, -138, -51, -12, -47, 155, +-15, 120, -10, -82, -30, -170, 12, -35, +85, 83, 81, 49, -45, -1, -161, 43, +-114, 45, 75, -64, 182, -134, 115, -36, +-5, 123, -66, 136, -81, -9, -43, -128, +52, -66, 142, 47, 128, 42, 36, -43, +-40, -12, -63, 86, -32, 64, 5, -74, +47, -104, 98, -4, 145, 55, 40, 15, +-158, 9, -232, 69, -25, 23, 195, -136, +203, -155, 16, 75, -133, 238, -155, 79, +-86, -171, 7, -142, 94, 53, 141, 67, +48, -62, -104, -30, -131, 122, 3, 114, +49, -73, 19, -176, 29, -88, 110, 59, +59, 139, -69, 115, -102, -3, 19, -119, +109, -147, 95, -55, 30, 104, -12, 195, +-4, 60, 13, -170, 23, -174, -21, 67, +-7, 165, 69, 14, 134, -96, 7, -16, +-146, 17, -115, -46, 70, 17, 112, 128, +15, 3, -60, -195, -32, -66, 2, 204, +-9, 135, -19, -168, -20, -173, -14, 97, +-2, 181, 44, -15, 32, -136, -23, -61, +-71, 28, -22, 70, 57, 80, 97, 16, +53, -130, -4, -128, -52, 76, -21, 188, +55, 16, 96, -177, 58, -112, 6, 84, +17, 117, 18, 3, -21, -48, -9, -24, +80, -14, 76, -20, -19, 13, -68, 37, +-3, 14, 36, -4, 18, 16, -20, 1, +-11, -51, 10, -62, -20, 7, -85, 63, +-57, 72, 86, 39, 137, -26, -63, -95, +-234, -94, -65, -6, 214, 99, 153, 115, +-158, 28, -198, -64, 84, -88, 191, -57, +3, -1, -81, 78, 21, 100, 40, 5, +-30, -108, 70, -56, 193, 84, 44, 49, +-213, -136, -138, -126, 211, 130, 344, 253, +29, 24, -279, -254, -172, -214, 151, 71, +208, 237, 8, 120, -104, -89, -16, -156, +36, -46, -37, 57, -66, 54, 30, 1, +68, -13, -58, -9, -98, 8, 23, 36, +98, 19, -46, -66, -174, -108, -54, -17, +177, 130, 152, 157, -74, -13, -201, -202, +-72, -162, 124, 89, 153, 218, 34, 68, +-50, -123, -18, -114, 30, -16, 14, 34, +32, 47, 109, 76, 65, -1, -55, -139, +-42, -115, 118, 80, 128, 185, -40, 65, +-118, -112, 16, -163, 133, -56, 56, 82, +-61, 130, -38, 65, 16, -25, -49, -74, +-61, -94, 60, -75, 116, 41, -48, 165, +-178, 119, -65, -78, 95, -168, 77, -49, +-45, 75, -112, 33, -40, -31, 77, 39, +61, 104, -41, -10, -67, -170, -6, -91, +42, 123, 60, 134, 52, -65, 16, -102, +-29, 75, -7, 97, 44, -119, 78, -167, +67, 82, -1, 199, -51, -12, 41, -166, +151, 9, 41, 142, -135, -34, -74, -192, +143, -11, 169, 209, -11, 111, -136, -134, +-68, -153, 1, 9, 25, 84, 89, 28, +89, 0, -65, 25, -205, 3, -110, -67, +140, -65, 171, 51, -82, 100, -212, -24, +-33, -136, 164, 2, 73, 200, -136, 85, +-126, -236, 79, -241, 133, 138, -2, 322, +-67, 37, 30, -245, 50, -129, -40, 78, +18, 42, 155, -27, 54, 68, -145, 88, +-34, -93, 210, -151, 148, 47, -94, 155, +-165, -11, -6, -145, 172, -25, 189, 123, +21, 80, -164, -53, -178, -102, 25, -61, +166, 26, 110, 102, -7, 84, -95, -24, +-118, -100, -52, -68, 39, 11, 67, 61, +21, 58, -55, 20, -31, -49, 19, -76, +-7, -5, -109, 69, -89, 29, 76, -44, +217, -11, 88, 58, -158, -8, -233, -115, +-34, -37, 196, 134, 209, 115, 42, -93, +-66, -177, -80, -16, -99, 149, 19, 103, +194, -54, 170, -110, -51, -21, -124, 57, +-11, 26, 108, -31, 27, -21, -36, 18, +13, 28, 72, 23, 25, -1, -47, -71, +-59, -90, 11, 48, 40, 177, -4, 62, +-17, -153, 4, -160, 15, 33, -33, 119, +-38, 38, -26, -12, 11, -5, 14, -34, +26, -59, -2, 10, -39, 58, -48, -10, +-2, -35, 43, 65, 56, 79, -1, -113, +-58, -200, -4, 44, 52, 277, 48, 105, +36, -226, -18, -207, -78, 84, 9, 182, +117, 35, 93, -51, -30, -42, -59, -79, +8, -58, 4, 106, -16, 155, 84, -35, +162, -161, 14, -18, -221, 105, -183, 2, +153, -75, 296, 44, 22, 106, -246, -33, +-132, -129, 113, -22, 104, 79, -36, 31, +-31, -11, 41, 32, -55, 25, -118, -61, +52, -88, 173, -5, -8, 76, -184, 87, +-111, 43, 133, -67, 184, -157, -36, -84, +-147, 129, -18, 203, 76, 15, 14, -167, +-20, -125, 55, 24, 99, 76, -38, 44, +-137, 19, -23, 12, 170, -15, 134, -70, +-88, -100, -134, -13, 91, 158, 153, 179, +-57, -61, -153, -243, 37, -80, 210, 155, +74, 102, -156, -80, -136, -24, 90, 101, +124, -7, -23, -163, -36, -46, 51, 166, +-6, 95, -127, -114, -62, -97, 168, 89, +149, 100, -122, -80, -189, -147, -6, 12, +117, 154, 76, 81, -17, -78, -62, -93, +-44, 9, -12, 12, 24, -59, 26, 4, +49, 158, 49, 102, -49, -159, -115, -240, +-7, 23, 130, 241, 125, 90, -7, -155, +-114, -86, -57, 124, 65, 57, 88, -171, +27, -123, 11, 164, 13, 206, 0, -56, +-44, -170, -21, -18, 96, 37, 104, -53, +-40, -2, -90, 168, -5, 122, 60, -127, +51, -230, -33, -57, -38, 162, 11, 174, +7, -17, -18, -151, 28, -32, 11, 128, +-71, 5, -85, -201, 54, -57, 123, 251, +0, 186, -133, -160, -95, -224, 59, 14, +117, 106, 12, -5, -83, -17, -19, 95, +26, 89, 26, -78, 21, -193, 15, -91, +-27, 138, 25, 215, 61, 16, 11, -162, +-16, -74, 19, 56, 20, -1, -6, -62, +23, 60, 82, 137, 74, -18, -65, -145, +-89, -39, 3, 82, 73, 7, 70, -74, +56, 45, -19, 141, -113, -11, -106, -201, +42, -92, 131, 156, 66, 158, -52, -56, +-134, -124, -70, -16, 21, 45, 40, 24, +38, 17, 81, -17, -31, -63, -175, 9, +-85, 78, 120, -3, 137, -94, 23, 19, +-79, 107, -101, -37, -21, -129, 89, 38, +154, 146, 37, -25, -122, -153, -110, -12, +80, 132, 147, 58, 92, -65, -37, -76, +-98, -12, -65, 49, 75, 44, 155, -14, +50, -19, -95, 46, -82, 8, 21, -117, +43, -65, 27, 140, 5, 133, 13, -81, +-31, -94, -61, 58, -46, -9, 32, -162, +58, 15, 17, 283, -80, 119, -79, -242, +16, -220, 57, 53, -26, 135, -30, 63, +35, 62, -30, 17, -45, -145, 41, -151, +57, 48, -33, 148, -24, 58, 32, -2, +20, -17, -27, -99, 41, -120, 79, 73, +-13, 209, -56, 24, 30, -196, 73, -76, +14, 154, -2, 60, 34, -156, -4, -53, +-38, 185, 47, 62, 60, -192, -30, -71, +-54, 190, 19, 57, 49, -196, 30, -51, +-55, 202, -98, 37, 17, -192, 104, -3, +6, 178, -80, -62, -37, -219, 1, 78, +2, 263, 17, -31, 43, -249, -18, -5, +-134, 162, -42, -45, 173, -120, 116, 157, +-144, 207, -129, -203, 90, -363, 67, 111, +-60, 448, 68, 36, 151, -384, -59, -77, +-215, 313, -19, -23, 216, -372, 155, 112, +-64, 556, -85, -36, -2, -675, -35, -144, +-42, 596, 116, 208, 191, -449, -18, -66, +-191, 463, -127, -67, 89, -660, 140, -19, +-16, 768, -85, 244, 76, -618, 46, -315, +-166, 388, -131, 120, 129, -366, 163, 59, +-34, 552, -111, -18, -31, -649, 15, -183, +-26, 510, 0, 256, 51, -321, 64, -168, +-13, 262, -42, 145, -78, -302, -40, -246, +104, 221, 150, 386, -47, -40, -126, -395, +40, -117, 82, 325, -30, 158, -25, -297, +99, -154, 41, 314, -95, 192, -72, -334, +137, -229, 124, 322, -105, 270, -142, -337, +86, -320, 114, 306, -28, 406, -61, -220, +21, -421, 30, 97, -50, 335, -63, -73, +25, -235, 137, 157, 0, 243, -178, -208, +-102, -347, 163, 173, 109, 396, -115, -50, +-114, -391, 101, -27, 67, 322, -126, 99, +-40, -286, 167, -151, 45, 231, -190, 210, +-68, -172, 151, -270, 136, 137, -49, 309, +-112, -64, -91, -377, 90, 5, 162, 379, +17, 110, -153, -352, -17, -170, 155, 235, +21, 185, -171, -131, 1, -145, 258, 64, +6, 84, -278, -4, -54, -61, 297, -21, +77, 15, -221, 92, -131, 9, 136, -129, +135, -98, -25, 155, -125, 156, -27, -131, +86, -182, -16, 112, -109, 174, 29, -157, +195, -169, -22, 198, -257, 270, -96, -206, +250, -353, 123, 92, -180, 420, -106, 47, +142, -388, 54, -175, -112, 313, -4, 258, +51, -248, -5, -268, 5, 192, 64, 292, +-41, -165, -45, -287, 76, 106, 48, 281, +-130, -51, -46, -265, 240, -12, 152, 243, +-240, 109, -266, -226, 193, -218, 256, 177, +-126, 326, -184, -96, 190, -365, 157, 36, +-265, 350, -302, -14, 208, -334, 424, 38, +-33, 333, -406, -18, -136, -336, 286, -59, +100, 273, -213, 126, -38, -150, 264, -157, +22, 42, -315, 149, -140, 55, 245, -155, +212, -140, -123, 156, -180, 250, 65, -123, +138, -338, -81, 68, -162, 411, 95, -27, +238, -509, 13, -49, -181, 613, -65, 236, +64, -662, 15, -481, 39, 503, 140, 650, +42, -253, -169, -601, -131, 79, 48, 448, +138, -79, 67, -412, -12, 146, -77, 489, +-27, -45, -21, -557, -47, -133, 5, 433, +145, 238, 64, -233, -143, -207, -90, 127, +34, 124, -5, -60, -75, -162, 133, -7, +155, 189, -98, 186, -312, -141, -3, -349, +287, 49, 121, 403, -212, 58, -116, -482, +163, -112, 75, 513, -112, 260, -57, -515, +150, -409, 21, 382, -118, 458, -50, -214, +202, -423, 108, 228, -141, 377, -245, -290, +30, -580, 318, 291, 196, 813, -217, -23, +-341, -906, 73, -327, 282, 741, 62, 504, +-211, -431, -20, -534, 137, 272, 21, 442, +-248, -154, -87, -494, 316, 57, 231, 564, +-322, 145, -363, -562, 236, -420, 324, 493, +-125, 589, -271, -257, 67, -716, 156, 57, +17, 691, -119, 138, -73, -634, 54, -293, +179, 594, 27, 400, -241, -513, -84, -585, +275, 469, 166, 729, -305, -336, -171, -914, +331, 149, 276, 1054, -325, 122, -355, -1070, +236, -469, 436, 941, -65, 708, -427, -654, +-64, -804, 360, 408, 164, 754, -305, -269, +-219, -745, 216, 186, 303, 782, -114, -21, +-354, -819, -51, -187, 361, 718, 159, 375, +-361, -566, -269, -494, 343, 422, 404, 572, +-302, -199, -569, -682, 117, -51, 694, 567, +109, 341, -642, -358, -290, -401, 567, 91, +362, 309, -521, 45, -448, -253, 517, -75, +638, 223, -351, 295, -772, -203, 53, -531, +718, -107, 222, 673, -466, 497, -302, -480, +312, -711, 263, 149, -290, 666, -358, 24, +338, -507, 538, -53, -162, 504, -678, 91, +-138, -567, 573, -319, 380, 527, -323, 587, +-482, -259, 133, -758, 437, -88, -19, 717, +-447, 413, -66, -574, 398, -636, 201, 373, +-322, 771, -279, -154, 212, -867, 298, -70, +-175, 849, -310, 321, 165, -751, 378, -506, +-78, 550, -437, 627, -62, -320, 383, -640, +220, 74, -283, 586, -229, 126, 212, -436, +254, -290, -166, 240, -283, 346, 81, -36, +310, -309, 120, -159, -219, 252, -250, 261, +41, -123, 245, -366, 65, 31, -176, 363, +-27, 94, 194, -316, -2, -168, -358, 249, +-104, 180, 447, -150, 283, -254, -380, 75, +-407, 301, 247, 131, 357, -305, -163, -371, +-319, 113, 169, 502, 340, 193, -115, -405, +-423, -394, -5, 117, 445, 366, 165, 64, +-382, -147, -258, -72, 303, 31, 286, -54, +-215, -36, -322, 73, 184, 97, 320, 48, +-90, -39, -366, -133, 44, -159, 386, 143, +74, 264, -395, -5, -208, -315, 363, -74, +304, 269, -191, 132, -375, -222, 78, -230, +324, 159, 64, 287, -329, 0, -120, -329, +341, -145, 217, 233, -346, 234, -363, -112, +286, -204, 452, 10, -126, 149, -524, 6, +0, -83, 482, -41, 145, 77, -490, 73, +-199, -61, 445, -101, 292, -18, -440, 162, +-408, 38, 390, -45, 529, -89, -226, 10, +-672, -52, 80, -1, 626, 188, 165, 124, +-532, -194, -249, -344, 346, 143, 290, 398, +-220, 54, -311, -438, 177, -138, 330, 410, +-47, 221, -389, -424, -61, -371, 314, 415, +240, 577, -230, -260, -344, -747, 83, -20, +444, 808, 30, 338, -532, -691, -173, -605, +553, 422, 362, 805, -485, -140, -459, -812, +278, -265, 528, 773, -155, 541, -475, -586, +31, -772, 481, 362, 37, 982, -494, -164, +-156, -1042, 442, -224, 363, 1101, -337, 554, +-475, -900, 105, -919, 548, 559, 95, 1148, +-490, -169, -235, -1140, 395, -292, 314, 1062, +-342, 585, -346, -782, 308, -797, 441, 516, +-263, 870, -566, -309, 169, -901, 660, 81, +14, 984, -650, 178, -166, -925, 542, -537, +239, 706, -439, 760, -262, -323, 408, -767, +320, -8, -377, 623, -413, 182, 277, -473, +460, -335, -148, 362, -411, 476, 92, -121, +320, -563, -87, -193, -345, 408, 81, 407, +392, -110, 58, -391, -405, -81, -228, 244, +323, 81, 276, -203, -191, -47, -277, 296, +200, 103, 254, -305, -193, -237, -355, 181, +122, 253, 444, -12, 38, -76, -419, -92, +-202, -81, 383, -9, 302, 233, -314, 75, +-435, -262, 276, -179, 595, 260, -97, 316, +-715, -266, -132, -381, 683, 109, 320, 488, +-556, -16, -387, -446, 478, -118, 391, 376, +-396, 232, -527, -287, 281, -260, 582, 128, +-19, 298, -546, -24, -194, -261, 369, -57, +224, 219, -204, 119, -234, -202, 201, -160, +236, 178, -151, 171, -357, -113, 32, -186, +376, 124, 121, 114, -256, -106, -190, -70, +110, 134, 118, 54, -14, -214, -52, 27, +-7, 248, 54, 30, 36, -371, -92, -88, +-39, 409, 76, 225, 34, -322, -95, -392, +84, 196, 157, 401, -140, 32, -280, -404, +91, -205, 409, 346, -13, 360, -384, -238, +-122, -547, 366, 109, 131, 645, -314, 93, +-175, -663, 288, -311, 269, 614, -275, 474, +-372, -499, 118, -638, 499, 328, 45, 829, +-514, -95, -270, -880, 416, -309, 454, 820, +-227, 668, -526, -519, -21, -895, 493, 79, +218, 956, -357, 255, -304, -768, 221, -538, +328, 637, -116, 667, -376, -493, 34, -832, +459, 305, 165, 1035, -487, -15, -387, -1075, +362, -444, 527, 913, -115, 793, -536, -502, +-87, -944, 410, 97, 235, 905, -311, 230, +-353, -837, 190, -499, 440, 720, 36, 793, +-500, -494, -292, -1003, 339, 154, 520, 1008, +-137, 195, -583, -908, -56, -377, 573, 722, +204, 547, -622, -591, -360, -689, 599, 354, +645, 813, -470, -23, -845, -785, 147, -318, +879, 626, 176, 573, -728, -387, -400, -708, +515, 127, 553, 793, -322, 124, -627, -733, +87, -442, 700, 595, 152, 603, -630, -285, +-399, -659, 502, 32, 560, 563, -353, 107, +-640, -437, 225, -234, 718, 425, -139, 310, +-790, -309, -30, -503, 799, 139, 251, 582, +-709, 165, -443, -485, 479, -461, 522, 235, +-273, 565, -481, 90, 138, -522, 381, -304, +-55, 391, -348, 420, 15, -262, 294, -506, +67, 73, -218, 577, -95, 181, 157, -468, +47, -489, -112, 239, -32, 574, 158, 53, +58, -506, -134, -206, -88, 467, 45, 236, +58, -450, -11, -468, 68, 468, 86, 694, +-105, -186, -222, -818, 0, -187, 280, 709, +74, 374, -194, -432, -113, -492, 148, 370, +60, 563, -187, -237, -89, -791, 164, -62, +223, 914, -99, 454, -259, -656, -85, -774, +197, 318, 188, 686, -83, -31, -178, -530, +-63, -26, 192, 481, 98, 76, -135, -490, +-198, -314, 147, 435, 275, 543, -149, -148, +-330, -659, 78, -126, 449, 540, -18, 343, +-410, -375, -192, -394, 354, 160, 330, 389, +-160, 15, -373, -345, -9, -115, 343, 233, +44, 251, -271, -211, -131, -270, 274, 76, +200, 365, -163, 55, -330, -355, 5, -210, +290, 205, 142, 351, -180, -80, -189, -295, +71, -91, 170, 275, -9, 196, -245, -223, +-84, -336, 275, 49, 319, 507, -193, 174, +-483, -443, -105, -427, 475, 236, 347, 495, +-273, -39, -445, -360, 130, -95, 441, 315, +-88, 84, -493, -317, 15, -171, 612, 344, +191, 389, -590, -295, -500, -522, 403, 34, +647, 606, -81, 183, -654, -457, -147, -375, +539, 249, 315, 445, -445, -71, -486, -416, +361, -99, 618, 429, -131, 198, -747, -386, +-117, -379, 626, 300, 369, 515, -444, -62, +-454, -529, 276, -203, 406, 364, -191, 321, +-423, -167, 205, -277, 432, 98, -81, 210, +-460, -153, -95, -241, 347, 120, 256, 321, +-108, 16, -308, -268, -63, -185, 210, 92, +171, 254, -108, 32, -143, -184, -23, -113, +82, 186, 121, 99, 6, -111, -175, -121, +-95, -3, 149, 92, 121, 96, -56, 73, +-88, -159, -14, -133, 21, 24, 53, 159, +3, 58, -119, -64, -48, -91, 210, -58, +146, 177, -255, 84, -268, -183, 140, -234, +283, 231, 18, 342, -169, -135, -137, -388, +50, -34, 157, 375, -59, 130, -215, -269, +138, -249, 351, 217, -155, 389, -480, -139, +56, -545, 474, -52, 75, 678, -336, 254, +-148, -655, 190, -426, 171, 562, -109, 520, +-221, -458, 63, -536, 306, 330, 8, 547, +-316, -185, -157, -497, 237, 6, 292, 349, +-53, 151, -341, -151, -147, -231, 313, -35, +227, 231, -217, 197, -248, -260, 148, -250, +224, 229, -136, 348, -220, -206, 52, -389, +270, 108, 31, 332, -266, 51, -172, -220, +232, -72, 274, -20, -204, 29, -324, 143, +121, 96, 374, -174, -6, -166, -353, 237, +-176, 102, 239, -339, 336, -136, -98, 571, +-375, 242, -8, -697, 356, -420, 65, 673, +-381, 579, -75, -642, 379, -598, 186, 550, +-358, 713, -281, -511, 242, -781, 265, 356, +-53, 825, -213, -195, 4, -808, 80, 137, +35, 743, -56, -82, -59, -791, 72, 54, +69, 771, -5, 46, -116, -688, -63, -95, +23, 541, 146, 39, 115, -387, -211, 23, +-234, 304, 165, -86, 357, -200, -146, 157, +-414, 71, 71, -269, 449, -42, 44, 490, +-524, 112, -107, -654, 497, -327, 184, 768, +-453, 571, -151, -823, 348, -792, 78, 833, +-237, 997, 9, -867, 169, -1144, -36, 894, +-146, 1285, 39, -936, 101, -1436, -34, 937, +-28, 1576, 85, -840, 8, -1650, -232, 648, +-18, 1614, 262, -449, 180, -1472, -275, 281, +-302, 1317, 151, -136, 359, -1189, -8, 1, +-400, 1056, -30, 113, 307, -903, 98, -203, +-294, 803, -102, 183, 215, -661, 151, -265, +-103, 617, -210, 264, -40, -445, 166, -313, +205, 308, -88, 334, -284, -232, -36, -294, +300, 109, 129, 399, -281, -139, -131, -432, +319, 22, 106, 560, -352, 23, -122, -578, +353, -77, 185, 554, -262, 61, -200, -554, +77, 15, 198, 612, -20, -18, -88, -672, +-7, -115, 26, 681, -73, 253, 4, -532, +146, -344, -21, 367, -136, 321, -51, -327, +166, -237, 9, 341, -165, 320, -50, -425, +270, -390, 78, 329, -365, 495, -189, -254, +383, -460, 312, 187, -329, 450, -324, -193, +241, -518, 247, 166, -298, 649, -106, -24, +391, -756, 114, -179, -478, 761, -105, 355, +355, -717, 95, -444, -208, 683, 59, 502, +93, -694, -211, -519, -58, 677, 207, 602, +27, -643, -162, -598, 125, 491, 80, 627, +-274, -359, -119, -542, 337, 178, 149, 480, +-315, -16, -123, -397, 246, -100, 55, 219, +-207, 226, -37, -115, 197, -174, 69, -64, +-122, 172, -238, 95, 60, -139, 375, -157, +55, 170, -518, 268, -132, -207, 621, -370, +171, 114, -684, 464, -260, -48, 810, -422, +306, -15, -811, 424, -429, 18, 816, -463, +380, -137, -639, 515, -295, 330, 545, -417, +117, -513, -468, 233, -29, 517, 366, -95, +93, -376, -262, 76, -55, 304, -40, -179, +39, -250, 142, 132, 174, 293, -232, -18, +-277, -221, 160, -170, 308, 113, -104, 328, +-339, -57, 143, -389, 328, 42, -126, 477, +-460, -143, 99, -516, 545, 231, 21, 605, +-626, -304, -144, -648, 651, 273, 230, 660, +-674, -197, -279, -587, 680, 109, 359, 482, +-647, -3, -505, -439, 566, -90, 620, 347, +-352, 291, -743, -260, 211, -423, 726, 38, +-86, 505, -718, 210, 15, -476, 756, -416, +21, 307, -725, 635, -173, -149, 736, -732, +246, -85, -640, 808, -360, 291, 515, -840, +489, -481, -386, 815, -526, 730, 164, -760, +578, -1021, -70, 565, -526, 1254, 8, -215, +547, -1383, -10, -51, -601, 1320, -65, 246, +607, -1308, 135, -347, -461, 1316, -135, 521, +286, -1176, -2, -775, -228, 861, 125, 813, +231, -375, -30, -703, -260, 87, -26, 471, +52, 96, 47, -431, 81, -218, 131, 390, +-106, 495, -278, -265, 52, -686, 233, -40, +11, 672, -195, 331, 59, -537, 193, -418, +-86, 391, -207, 532, -41, -431, 143, -679, +113, 402, 93, 971, -100, -262, -270, -1174, +-4, 44, 249, 1173, 92, 151, -219, -1078, +25, -207, 194, 945, -54, 231, -389, -838, +7, -328, 530, 752, 206, 443, -597, -531, +-372, -630, 537, 330, 420, 683, -514, -37, +-405, -733, 562, -156, 371, 683, -508, 343, +-469, -610, 436, -514, 385, 513, -148, 589, +-372, -242, 1, -670, 243, 51, 168, 534, +-173, 203, -388, -457, 178, -353, 527, 388, +15, 544, -780, -250, -91, -853, 753, 72, +285, 978, -759, 321, -335, -1017, 704, -617, +451, 895, -693, 834, -626, -751, 613, -1110, +788, 686, -426, 1362, -859, -367, 214, -1680, +751, -32, 11, 1715, -652, 512, -142, -1544, +455, -865, 347, 1305, -314, 1066, -439, -1047, +62, -1304, 475, 796, 173, 1523, -458, -406, +-330, -1690, 331, -1, 542, 1667, -278, 412, +-697, -1544, 87, -670, 849, 1299, 170, 871, +-905, -1005, -373, -1000, 787, 665, 567, 978, +-685, -228, -633, -929, 548, -89, 710, 717, +-354, 388, -807, -532, 121, -578, 829, 360, +202, 641, -762, -149, -521, -716, 628, 44, +697, 642, -367, 143, -828, -575, 158, -277, +812, 419, 73, 321, -769, -206, -315, -315, +740, 100, 498, 169, -596, 26, -767, -72, +412, -123, 929, -97, -84, 238, -1001, 380, +-272, -307, 990, -682, 498, 159, -878, 941, +-692, 48, 826, -997, 823, -266, -668, 961, +-1002, 392, 460, -964, 1114, -500, -147, 933, +-1144, 741, -127, -829, 1067, -938, 301, 542, +-918, 1030, -452, -210, 806, -984, 514, 1, +-540, 851, -685, 201, 299, -843, 678, -345, +100, 758, -648, 637, -403, -649, 475, -871, +620, 391, -271, 983, -768, -111, 150, -982, +804, -48, -13, 850, -873, 200, -121, -799, +844, -248, 318, 674, -741, 427, -540, -598, +535, -521, 739, 379, -312, 655, -891, -200, +56, -674, 1007, -8, 223, 651, -1016, 249, +-518, -646, 881, -405, 763, 477, -656, 679, +-903, -389, 436, -779, 988, 149, -191, 914, +-1109, 56, -27, -997, 1118, -270, 369, 923, +-1043, 617, -629, -846, 827, -796, 772, 529, +-505, 953, -926, -292, 280, -991, 948, 129, +119, 1009, -1061, 79, -497, -1132, 955, -260, +870, 1086, -702, 583, -1166, -916, 410, -785, +1249, 577, 16, 829, -1356, -221, -381, -812, +1318, -74, 817, 745, -1203, 409, -1186, -631, +946, -739, 1425, 408, -628, 976, -1569, -96, +310, -1048, 1672, -181, 36, 996, -1729, 350, +-381, -912, 1627, -485, 757, 845, -1449, 675, +-952, -739, 1093, -859, 1144, 499, -781, 1003, +-1198, -268, 429, -995, 1191, 44, -11, 932, +-1140, 100, -301, -885, 845, -214, 675, 790, +-617, 415, -835, -681, 297, -543, 988, 404, +-81, 618, -1096, -144, -111, -510, 1101, -63, +383, 367, -1098, 165, -578, -304, 845, -197, +813, 258, -599, 334, -859, -240, 275, -416, +865, 68, -53, 480, -784, 108, -150, -412, +641, -284, 388, 297, -474, 474, -538, -158, +150, -630, 691, -92, 71, 765, -635, 388, +-326, -742, 637, -685, 496, 614, -574, 855, +-722, -449, 442, -973, 1027, 333, -250, 1034, +-1173, -161, -145, -1142, 1294, 9, 421, 1164, +-1197, 215, -774, -1178, 1097, -433, 1031, 1156, +-865, 646, -1278, -978, 531, -928, 1420, 785, +-225, 1011, -1430, -429, -110, -1039, 1462, 215, +376, 948, -1401, -33, -752, -906, 1245, -194, +1119, 824, -895, 454, -1342, -535, 472, -674, +1416, 154, -175, 642, -1381, 182, -51, -534, +1396, -298, 343, 478, -1398, 429, -683, -604, +1141, -642, 1084, 597, -767, 997, -1214, -404, +268, -1184, 1210, 75, 88, 1136, -1157, 221, +-323, -1006, 1088, -369, 633, 845, -1101, 549, +-878, -750, 882, -714, 1185, 577, -643, 873, +-1267, -369, 311, -966, 1232, 131, -37, 980, +-1106, 140, -178, -940, 910, -427, 409, 815, +-732, 691, -584, -604, 470, -895, 741, 372, +-229, 996, -741, -122, -26, -1082, 702, -93, +171, 1061, -576, 366, -298, -1006, 487, -558, +381, 780, -327, 702, -432, -524, 136, -729, +422, 261, 54, 630, -336, 22, -197, -547, +271, -154, 275, 325, -243, 331, -361, -193, +251, -345, 438, -17, -262, 367, -493, 170, +286, -295, 485, -272, -304, 147, -503, 305, +307, -26, 482, -189, -221, -85, -453, 84, +133, 99, 345, 25, -77, -157, -254, -101, +75, 206, 217, 245, -53, -206, -209, -406, +-56, 120, 174, 467, 157, 37, -71, -449, +-190, -104, -10, 352, 122, 156, 42, -294, +-65, -184, -23, 215, 31, 206, 44, -55, +-20, -202, -62, -79, -40, 37, 89, 216, +104, 112, -70, -203, -174, -270, 47, 155, +239, 341, -37, -94, -261, -332, -21, -11, +333, 298, 33, 52, -289, -182, -141, -100, +259, 92, 189, 99, -129, -9, -251, -96, +-45, -93, 281, 133, 172, 185, -178, -107, +-329, -361, 109, 75, 354, 455, 58, 59, +-411, -512, -187, -186, 387, 467, 314, 296, +-304, -304, -395, -369, 180, 143, 377, 289, +-85, 69, -320, -201, 54, -140, 309, 76, +-62, 201, -307, -56, -12, -276, 301, 53, +134, 391, -214, 25, -237, -485, 29, -118, +315, 448, 99, 200, -270, -366, -257, -210, +252, 317, 332, 214, -163, -276, -451, -299, +109, 203, 511, 371, -5, -36, -610, -351, +-94, -113, 650, 265, 221, 163, -676, -164, +-350, -173, 689, 172, 422, 177, -675, -157, +-576, -274, 739, 129, 718, 330, -653, -6, +-973, -361, 497, -126, 1119, 327, -194, 225, +-1155, -225, -105, -339, 1091, 183, 326, 334, +-986, -56, -506, -388, 899, 35, 667, 337, +-771, 6, -812, -303, 584, -24, 939, 300, +-356, -37, -1016, -225, 125, -23, 1015, 268, +150, -11, -961, -204, -374, -51, 735, 224, +576, 99, -517, -235, -656, -133, 265, 212, +698, 220, -55, -233, -700, -197, -175, 197, +599, 195, 451, -243, -440, -156, -624, 288, +159, 181, 747, -295, 41, -230, -745, 253, +-244, 212, 722, -155, 413, -182, -639, 159, +-559, 129, 449, -176, 696, -195, -247, 191, +-684, 295, -30, -137, 655, -350, 226, 23, +-510, 400, -408, 10, 334, -373, 523, -107, +-163, 424, -545, 178, 0, -418, 575, -291, +94, 364, -547, 395, -219, -332, 488, -416, +362, 221, -365, 514, -449, -144, 180, -521, +487, -49, -63, 503, -474, 239, -41, -402, +469, -349, 141, 274, -462, 464, -257, -237, +395, -545, 373, 127, -322, 689, -403, 5, +216, -727, 439, -174, -142, 657, -439, 304, +-19, -587, 453, -329, 156, 495, -376, 444, +-274, -446, 283, -554, 339, 288, -239, 629, +-352, -76, 133, -617, 492, -45, -39, 478, +-508, 143, -215, -435, 467, -152, 397, 383, +-292, 246, -486, -321, 87, -368, 563, 207, +43, 376, -582, -26, -227, -370, 639, -23, +392, 288, -626, 83, -553, -280, 523, -109, +676, 272, -394, 157, -756, -207, 208, -225, +824, 182, 19, 198, -853, -132, -250, -253, +809, 159, 455, 311, -707, -106, -618, -398, +566, -6, 750, 436, -406, 98, -864, -374, +181, -170, 967, 405, 32, 170, -943, -449, +-307, -325, 872, 513, 528, 524, -660, -382, +-715, -676, 373, 132, 790, 667, -78, 38, +-690, -519, -185, -163, 563, 481, 309, 220, +-393, -420, -455, -398, 302, 305, 554, 541, +-163, -64, -670, -505, 20, -183, 705, 365, +155, 230, -698, -176, -336, -253, 665, 104, +520, 280, -575, 36, -712, -337, 437, -277, +822, 284, -250, 477, -860, -44, 105, -597, +857, -146, 35, 534, -874, 336, -217, -519, +826, -463, 456, 485, -683, 648, -611, -354, +419, -836, 686, 156, -223, 830, -641, 109, +59, -777, 642, -215, 68, 649, -656, 346, +-251, -595, 605, -471, 483, 515, -470, 584, +-632, -373, 224, -691, 725, 294, 12, 706, +-691, -179, -229, -803, 571, 72, 376, 849, +-366, 137, -443, -800, 131, -369, 476, 644, +76, 480, -497, -427, -261, -526, 511, 305, +434, 505, -474, -216, -592, -498, 358, 124, +715, 473, -153, -67, -777, -380, -68, -12, +763, 283, 296, 36, -672, -128, -466, -71, +490, -45, 591, 26, -259, 212, -654, 100, +30, -320, 672, -224, 184, 308, -673, 354, +-366, -315, 630, -417, 552, 268, -533, 543, +-693, -212, 363, -650, 807, 49, -182, 703, +-837, 157, -38, -680, 846, -324, 244, 578, +-758, 467, -443, -509, 615, -576, 585, 407, +-445, 705, -643, -264, 266, -809, 668, 84, +-133, 829, -624, 138, -33, -785, 555, -319, +153, 668, -399, 491, -295, -506, 260, -636, +354, 331, -66, 696, -432, -89, -62, -760, +433, -86, 192, 696, -415, 314, -302, -631, +404, -474, 385, 476, -328, 597, -493, -302, +251, -717, 522, 159, -64, 748, -494, 98, +-123, -805, 354, -298, 267, 672, -203, 540, +-306, -497, 77, -640, 327, 268, -22, 659, +-337, -50, -70, -681, 381, -110, 180, 631, +-376, 353, -295, -576, 307, -530, 371, 380, +-179, 651, -381, -157, 5, -679, 344, -24, +163, 632, -275, 247, -315, -612, 223, -447, +379, 477, -129, 666, -437, -288, 100, -783, +413, 59, -12, 783, -432, 182, -50, -755, +383, -331, 120, 632, -304, 553, -188, -517, +251, -691, 165, 291, -149, 784, -192, -57, +144, -803, 180, -113, -93, 721, -217, 292, +31, -685, 248, -388, 63, 549, -203, 532, +-178, -432, 128, -612, 230, 254, 2, 655, +-263, -78, -59, -688, 276, -62, 113, 640, +-330, 240, -182, -595, 336, -343, 304, 461, +-253, 454, -432, -313, 88, -475, 455, 151, +55, 462, -447, 24, -96, -414, 419, -150, +116, 300, -448, 279, -159, -193, 458, -331, +252, 42, -401, 340, -334, 75, 324, -314, +381, -148, -206, 262, -437, 206, 72, -272, +487, -250, 112, 249, -475, 355, -282, -205, +420, -445, 336, 92, -329, 472, -373, 69, +288, -439, 406, -155, -199, 336, -484, 219, +44, -300, 533, -229, 129, 249, -470, 293, +-301, -174, 393, -338, 345, 51, -281, 324, +-418, 129, 201, -264, 466, -233, -80, 146, +-517, 336, -92, -78, 527, -377, 217, 19, +-447, 453, -336, 53, 364, -531, 354, -157, +-253, 548, -342, 310, 168, -484, 333, -425, +-119, 316, -314, 459, 55, -142, 325, -400, +9, 11, -293, 326, -107, 75, 218, -261, +207, -171, -111, 190, -271, 267, -47, -65, +334, -326, 200, -59, -322, 294, -385, 153, +276, -256, 511, -178, -204, 236, -561, 227, +150, -220, 584, -337, -137, 138, -592, 436, +69, 51, 608, -491, 49, -238, -521, 438, +-192, 402, 364, -396, 248, -483, -186, 358, +-263, 579, 59, -344, 291, -671, 54, 294, +-318, 750, -207, -194, 294, -806, 337, 80, +-160, 785, -382, 71, 29, -775, 360, -187, +60, 685, -327, 322, -128, -615, 326, -429, +213, 518, -279, 529, -274, -385, 175, -652, +287, 218, -98, 694, -241, 34, 50, -673, +235, -227, -12, 554, -280, 371, -78, -433, +272, -460, 230, 342, -197, 543, -297, -230, +46, -666, 312, 68, 67, 735, -282, 156, +-151, -715, 273, -358, 246, 608, -268, 480, +-348, -480, 203, -549, 444, 385, -110, 604, +-466, -259, -24, -664, 464, 96, 107, 643, +-382, 87, -188, -543, 317, -212, 216, 417, +-229, 251, -223, -326, 139, -293, 247, 286, +-72, 336, -224, -191, -26, -386, 211, 82, +70, 333, -149, 25, -104, -218, 83, -49, +110, 123, -24, 31, -98, -49, -65, -62, +106, -21, 130, 91, -82, 155, -187, -89, +80, -264, 205, 21, -107, 312, -236, 41, +127, -300, 308, -54, -93, 266, -336, 49, +-21, -256, 319, -49, 99, 223, -213, 44, +-129, -181, 135, -22, 117, 166, -102, 11, +-128, -152, 59, -54, 195, 124, -12, 80, +-217, -47, -87, -63, 234, 22, 137, 22, +-213, -65, -188, -34, 196, 105, 228, 137, +-158, -106, -241, -187, 93, 20, 240, 199, +-54, -17, -201, -164, 19, 43, 204, 196, +26, -68, -206, -263, -113, 40, 158, 273, +217, 21, -69, -249, -255, -15, -46, 200, +249, 24, 114, -212, -235, -32, -144, 187, +249, 75, 192, -142, -261, -102, -247, 98, +216, 97, 292, -48, -148, -120, -296, 37, +54, 147, 265, 20, 32, -192, -221, -68, +-101, 205, 149, 119, 160, -200, -70, -166, +-187, 193, -22, 179, 201, -150, 100, -167, +-193, 142, -179, 119, 162, -175, 249, -112, +-101, 226, -268, 166, 12, -210, 243, -219, +50, 115, -207, 209, -75, -44, 192, -129, +97, 39, -196, 103, -141, -66, 174, -152, +193, 17, -105, 209, -220, 98, 29, -192, +215, -199, 31, 125, -208, 235, -74, -94, +199, -237, 124, 100, -156, 306, -194, -102, +82, -407, 205, 30, 21, 491, -171, 106, +-67, -521, 112, -247, 59, 475, -79, 366, +-44, -412, 92, -436, 48, 362, -103, 491, +-95, -317, 82, -572, 132, 271, -22, 636, +-128, -154, -32, -678, 95, 23, 51, 633, +-72, 94, -50, -546, 65, -160, 52, 482, +-46, 198, -57, -423, 4, -290, 31, 360, +48, 373, 3, -209, -68, -422, -24, 54, +76, 377, 8, 61, -96, -315, 28, -124, +138, 291, -40, 185, -187, -269, 17, -279, +203, 232, 22, 358, -204, -140, -44, -406, +195, 38, 74, 401, -188, 46, -96, -352, +137, -104, 113, 299, -84, 138, -98, -242, +49, -175, 66, 189, -31, 234, -76, -98, +40, -291, 59, -51, -4, 294, -33, 211, +-6, -188, -42, -311, -11, 36, 93, 288, +60, 77, -92, -203, -110, -110, 69, 160, +108, 136, -68, -137, -122, -221, 112, 79, +168, 307, -124, 68, -228, -331, 83, -216, +241, 260, -17, 292, -204, -183, -12, -309, +179, 165, 19, 322, -201, -160, -54, -402, +239, 117, 144, 462, -228, 2, -226, -462, +157, -125, 253, 389, -93, 194, -226, -279, +53, -211, 193, 210, -29, 189, -193, -134, +-19, -184, 173, 83, 92, 175, -149, -7, +-132, -156, 113, -93, 171, 111, -114, 157, +-195, -12, 111, -192, 232, -47, -98, 150, +-249, 76, 80, -118, 232, -39, -69, 122, +-233, -2, 93, -152, 247, -11, -70, 178, +-273, -1, 31, -151, 256, 20, 26, 166, +-203, -87, -70, -214, 139, 120, 93, 293, +-88, -86, -139, -349, 43, 59, 176, 344, +19, -30, -197, -367, -100, 54, 176, 403, +160, -19, -129, -452, -197, -50, 82, 452, +190, 127, -50, -387, -174, -186, 23, 345, +170, 190, 25, -302, -167, -235, -99, 271, +161, 260, 172, -198, -96, -267, -205, 113, +18, 238, 178, -86, 47, -182, -127, 57, +-63, 182, 89, -41, 71, -171, -66, -37, +-86, 143, 43, 102, 86, -75, 16, -124, +-71, 11, -71, 135, 6, -6, 125, -123, +56, -11, -160, 159, -130, 10, 177, -147, +206, -35, -175, 129, -260, 24, 137, -116, +301, 0, -92, 97, -307, 25, 33, -96, +317, -38, 46, 22, -301, 48, -150, 23, +239, -2, 245, -25, -142, -16, -286, -2, +50, -21, 264, 20, 11, 38, -240, 22, +-26, -41, 227, -18, 71, -8, -231, -7, +-150, 23, 182, 58, 210, -2, -96, -65, +-206, -2, 45, 21, 149, -25, -24, -40, +-122, 82, 44, 67, 123, -51, -29, -92, +-138, -5, -4, 23, 116, 13, 34, 69, +-59, 43, -32, -65, 7, -126, -3, 4, +22, 91, 33, 66, -22, -19, -44, -45, +34, -23, 36, 5, -65, 2, -44, -38, +93, 32, 74, 96, -95, 39, -98, -129, +61, -102, 84, 45, -21, 103, -50, 33, +20, -12, 28, -32, -28, -61, -63, -8, +4, 50, 107, 41, 55, -39, -110, 6, +-112, 36, 85, -4, 94, -77, -51, -16, +-75, 85, 67, 51, 56, -64, -72, -91, +-70, 55, 65, 121, 97, -12, -52, -182, +-113, -57, 28, 181, 142, 156, -7, -112, +-155, -179, -33, 29, 139, 130, 33, 4, +-98, -93, -5, 29, 80, 98, -45, 2, +-78, -130, 62, -68, 65, 81, -54, 115, +-23, 7, 79, -99, -20, -36, -118, 46, +8, 41, 140, -79, 23, -37, -110, 107, +-24, 126, 66, -101, 0, -207, -53, 19, +24, 214, 49, 64, -2, -201, -25, -67, +-25, 180, -20, 90, 18, -223, 59, -119, +7, 216, -57, 187, -40, -174, 43, -212, +58, 118, -21, 194, -91, -62, -17, -175, +115, 45, 66, 147, -122, -2, -116, -140, +113, -22, 141, 122, -98, 52, -159, -114, +106, -88, 182, 99, -96, 106, -199, -75, +78, -122, 223, 51, -34, 108, -233, -33, +-37, -102, 236, 18, 120, 97, -204, 13, +-191, -68, 149, -60, 228, 7, -100, 70, +-230, 71, 59, -48, 244, -101, -33, 18, +-267, 102, -36, -4, 281, -98, 117, 13, +-256, 92, -182, 12, 189, -85, 220, -20, +-132, 34, -221, 16, 78, -13, 253, -2, +-17, 5, -259, -6, -62, 0, 239, -23, +137, -11, -196, 26, -174, 46, 149, -19, +213, -62, -119, -20, -250, 57, 86, 57, +291, -20, -33, -81, -323, -41, -30, 77, +327, 101, 112, -33, -318, -141, -187, -18, +279, 136, 267, 48, -220, -133, -310, -58, +162, 146, 322, 73, -105, -158, -332, -122, +72, 155, 321, 157, -4, -122, -323, -168, +-59, 96, 286, 173, 124, -97, -205, -183, +-176, 63, 136, 200, 186, -34, -34, -163, +-210, 4, -46, 116, 203, -18, 126, -70, +-184, 54, -212, 37, 164, -64, 251, -2, +-98, 84, -299, -72, 60, -111, 303, 107, +-4, 165, -310, -116, -49, -169, 297, 120, +90, 164, -267, -137, -167, -173, 233, 138, +232, 195, -147, -72, -300, -190, 56, 7, +297, 134, 39, 26, -274, -103, -81, -31, +243, 134, 106, 80, -214, -180, -149, -190, +191, 159, 179, 285, -119, -80, -212, -288, +37, 28, 194, 270, 29, -19, -161, -287, +-78, -30, 144, 326, 116, 158, -106, -291, +-169, -313, 56, 158, 191, 390, 11, -9, +-178, -372, -59, -86, 153, 341, 87, 107, +-113, -341, -112, -163, 104, 335, 142, 224, +-70, -278, -181, -260, 34, 197, 193, 253, +5, -138, -192, -229, -38, 90, 183, 234, +68, -34, -157, -206, -100, -52, 97, 159, +112, 88, -11, -89, -85, -88, -54, 51, +46, 76, 82, -55, -13, -79, -86, 25, +7, 106, 97, 11, 6, -87, -114, -61, +-63, 72, 119, 82, 124, -64, -74, -108, +-172, 52, 19, 163, 172, -39, 51, -192, +-145, -28, -98, 186, 114, 62, 123, -140, +-73, -56, -160, 125, 43, 50, 156, -133, +11, -66, -166, 108, -62, 106, 169, -48, +123, -90, -150, -34, -178, 11, 136, 58, +197, 70, -89, -28, -222, -104, 57, 22, +221, 108, -20, -38, -229, -150, -28, 53, +244, 224, 64, 0, -223, -273, -123, -99, +201, 265, 138, 178, -145, -201, -153, -224, +105, 160, 153, 229, -76, -127, -149, -267, +56, 100, 169, 307, -44, -38, -176, -332, +-1, -54, 192, 331, 41, 127, -176, -276, +-85, -189, 144, 228, 104, 208, -123, -156, +-96, -225, 90, 102, 119, 223, -85, -51, +-125, -211, 52, -8, 161, 201, -21, 38, +-166, -169, -23, -77, 151, 156, 76, 92, +-139, -129, -106, -122, 90, 107, 160, 156, +-54, -87, -167, -180, -1, 20, 175, 201, +13, 43, -137, -154, -19, -107, 101, 80, +9, 110, -69, -9, 7, -67, 14, -12, +-2, 49, 5, 6, 44, -78, -54, -49, +-49, 106, 60, 145, 81, -55, -79, -219, +-97, -63, 62, 210, 124, 147, -18, -140, +-134, -163, -21, 95, 111, 138, 72, -89, +-97, -160, -89, 58, 74, 209, 132, 49, +-94, -192, -159, -188, 75, 109, 184, 269, +-52, 11, -166, -303, 28, -96, 153, 291, +-8, 165, -157, -298, 1, -224, 165, 291, +40, 287, -185, -276, -61, -358, 171, 271, +83, 432, -172, -211, -77, -538, 171, 99, +83, 573, -172, 67, -95, -521, 175, -187, +120, 411, -162, 201, -142, -345, 148, -218, +161, 355, -107, 282, -172, -312, 53, -386, +150, 182, -2, 399, -111, -26, -17, -289, +60, -41, 23, 173, -34, 22, -46, -124, +24, -27, 75, 114, 13, 101, -97, -58, +-50, -169, 73, -74, 85, 188, -30, 173, +-102, -124, 9, -246, 101, 67, 13, 274, +-91, -24, -29, -289, 51, -40, 65, 306, +-2, 88, -85, -265, -61, -148, 91, 235, +99, 183, -92, -170, -102, -233, 55, 100, +99, 270, -5, -3, -84, -256, -79, -96, +94, 218, 142, 135, -102, -164, -186, -169, +117, 145, 209, 202, -110, -101, -214, -259, +62, 27, 228, 264, -7, 65, -207, -208, +-55, -137, 193, 129, 85, 141, -154, -54, +-97, -157, 120, 35, 69, 162, -76, 12, +-35, -179, 37, -56, 7, 148, 8, 94, +-12, -77, -44, -126, 40, 15, 78, 127, +-48, 43, -104, -164, 34, -59, 94, 200, +13, 94, -81, -232, -41, -140, 43, 223, +100, 153, -28, -153, -134, -165, 10, 88, +178, 132, -1, -19, -209, -130, -8, -23, +226, 151, 28, 82, -262, -164, -33, -166, +266, 153, 60, 216, -249, -103, -69, -241, +187, 69, 111, 225, -136, -38, -163, -224, +94, 13, 236, 216, -81, 51, -286, -185, +67, -107, 287, 125, -58, 147, -258, -60, +56, -173, 220, 8, -22, 183, -187, 47, +-24, -202, 158, -107, 92, 178, -141, 155, +-128, -142, 109, -132, 134, 131, -94, 87, +-110, -158, 57, -52, 81, 193, -28, 40, +-58, -165, 0, -12, 27, 122, 20, -51, +-20, -85, -22, 98, 0, 74, 49, -109, +0, -40, -46, 112, -42, -12, 53, -162, +101, 23, -8, 206, -169, 7, -23, -211, +212, -29, 33, 177, -227, 3, -33, -151, +233, 25, 14, 181, -207, -32, -30, -167, +176, -13, 39, 136, -122, 24, -70, -73, +70, -28, 110, 37, -8, 45, -139, -3, +-70, -74, 147, -93, 138, 89, -120, 205, +-209, -6, 96, -301, 251, -108, -61, 323, +-278, 222, 32, -334, 287, -328, 19, 352, +-285, 443, -79, -344, 263, -550, 121, 313, +-223, 598, -142, -280, 175, -606, 153, 274, +-109, 624, -175, -240, 43, -693, 207, 125, +24, 721, -218, 66, -75, -689, 219, -209, +79, 609, -171, 268, -51, -592, 126, -292, +-3, 620, -53, 342, 44, -619, -10, -408, +-63, 569, 45, 404, 75, -493, -45, -350, +-90, 494, 12, 269, 128, -517, 17, -222, +-173, 543, -38, 165, 219, -528, 56, -81, +-238, 511, -84, -23, 242, -514, 133, 87, +-217, 543, -191, -111, 183, -565, 229, 81, +-119, 596, -231, -23, 73, -635, 198, -65, +-20, 640, -140, 187, -30, -631, 118, -281, +83, 556, -93, 376, -146, -489, 106, -439, +173, 377, -66, 525, -190, -243, 23, -584, +173, 75, 60, 609, -158, 100, -119, -596, +162, -248, 147, 555, -142, 394, -158, -529, +147, -500, 133, 459, -102, 628, -151, -380, +80, -672, 161, 225, -11, 702, -180, -90, +-32, -669, 196, -58, 68, 635, -182, 220, +-97, -618, 189, -345, 123, 533, -150, 515, +-182, -475, 127, -563, 228, 329, -56, 623, +-251, -248, 23, -623, 253, 122, 40, 638, +-247, 42, -74, -649, 247, -208, 140, 558, +-212, 425, -199, -459, 166, -530, 269, 282, +-37, 623, -338, -161, -51, -654, 388, 19, +170, 669, -425, 136, -237, -629, 438, -279, +313, 508, -400, 413, -355, -371, 374, -484, +391, 192, -289, 568, -393, -27, 229, -594, +389, -182, -104, 570, -351, 372, -8, -469, +319, -512, 157, 320, -241, 624, -286, -191, +215, -713, 398, 14, -150, 800, -450, 193, +128, -779, 469, -405, -76, 667, -413, 539, +47, -505, 389, -587, 8, 342, -286, 618, +-57, -200, 220, -655, 106, 16, -71, 663, +-139, 207, -42, -622, 213, -400, 189, 499, +-227, 550, -323, -373, 294, -633, 445, 230, +-255, 690, -528, -50, 263, -704, 581, -137, +-202, 652, -583, 348, 161, -605, 621, -516, +-70, 536, -587, 696, -33, -479, 582, -843, +158, 390, -480, 923, -247, -255, 398, -939, +375, 139, -257, 889, -402, 23, 130, -855, +459, -239, 37, 766, -400, 543, -163, -590, +341, -844, 284, 353, -228, 1052, -309, -56, +111, -1197, 376, -216, 37, 1249, -323, 532, +-170, -1217, 300, -860, 317, 1065, -155, 1155, +-368, -773, 6, -1378, 444, 428, 195, 1498, +-399, -17, -385, -1554, 363, -429, 565, 1477, +-174, 901, -667, -1227, 2, -1310, 718, 809, +282, 1542, -642, -288, -474, -1611, 551, -224, +728, 1495, -346, 746, -872, -1268, 153, -1204, +999, 841, 171, 1581, -1027, -267, -417, -1772, +959, -383, 747, 1712, -819, 1040, -905, -1498, +612, -1563, 1074, 1103, -302, 2020, -1062, -641, +11, -2301, 1010, 65, 385, 2402, -828, 562, +-630, -2275, 572, -1132, 906, 1871, -266, 1620, +-965, -1327, -84, -1882, 1018, 649, 428, 1977, +-881, 24, -718, -1878, 749, -632, 1003, 1592, +-488, 1160, -1121, -1184, 230, -1486, 1245, 630, +88, 1624, -1134, -55, -388, -1541, 1052, -511, +624, 1267, -775, 988, -772, -873, 525, -1318, +839, 396, -173, 1467, -770, 88, -123, -1409, +729, -519, 390, 1182, -505, 835, -565, -791, +365, -1051, 680, 344, -68, 1089, -693, 140, +-166, -976, 696, -574, 413, 741, -600, 848, +-582, -369, 532, -1020, 687, 20, -351, 987, +-653, 352, 215, -839, 605, -687, 8, 555, +-426, 887, -132, -90, 309, -987, 281, -382, +-137, 833, -311, 825, 11, -546, 354, -1140, +143, 194, -348, 1288, -225, 216, 341, -1341, +347, -624, -283, 1225, -354, 1010, 259, -942, +418, -1309, -180, 565, -418, 1431, 193, -137, +448, -1399, -160, -247, -434, 1254, 183, 549, +426, -990, -182, -802, -390, 689, 188, 903, +386, -305, -154, -875, -372, -38, 136, 709, +417, 289, -8, -433, -420, -459, -53, 163, +427, 453, 162, 149, -342, -358, -229, -351, +268, 113, 249, 472, -110, 167, -296, -481, +9, -421, 274, 391, 167, 653, -228, -270, +-311, -791, 196, 60, 454, 845, -20, 193, +-569, -754, -59, -463, 559, 534, 273, 676, +-539, -206, -421, -839, 432, -102, 553, 874, +-269, 444, -705, -852, 134, -748, 705, 715, +113, 992, -678, -431, -275, -1188, 547, 135, +467, 1198, -326, 233, -587, -1172, 137, -516, +640, 1028, 90, 770, -653, -827, -306, -971, +541, 583, 505, 1061, -381, -250, -706, -1083, +120, -50, 848, 956, 139, 365, -875, -759, +-414, -578, 827, 474, 664, 713, -673, -168, +-848, -746, 439, -121, 997, 669, -240, 383, +-1056, -538, -82, -552, 1056, 323, 271, 681, +-992, -76, -473, -714, 809, -194, 605, 636, +-624, 447, -618, -487, 317, -620, 675, 265, +-93, 716, -619, -23, -191, -770, 528, -212, +376, 740, -447, 478, -542, -646, 214, -713, +606, 460, -120, 847, -575, -183, -83, -888, +490, -65, 131, 804, -374, 282, -193, -666, +241, -457, 198, 524, -152, 570, -218, -316, +-21, -674, 191, 93, 63, 683, -178, 167, +-187, -611, 78, -427, 119, 476, -9, 595, +-157, -270, -73, -723, 92, 99, 49, 751, +-93, 104, -37, -730, 63, -298, -104, 628, +-28, 469, 130, -438, -50, -629, -293, 229, +20, 681, 305, 18, -63, -698, -385, -200, +-102, 626, 312, 360, 176, -518, -292, -462, +-331, 369, 178, 495, 380, -174, -149, -503, +-449, 10, 7, 400, 390, 161, 58, -275, +-450, -246, -259, 107, 304, 259, 291, 76, +-272, -217, -389, -196, 18, 100, 276, 284, +138, 12, -219, -300, -367, -121, 18, 255, +444, 207, 92, -192, -557, -241, -343, 95, +473, 229, 441, 8, -475, -185, -720, -49, +226, 81, 763, 94, -113, 17, -905, -51, +-186, -141, 793, -60, 326, 279, -714, 197, +-599, -315, 447, -429, 704, 348, -285, 597, +-905, -257, -62, -726, 826, 112, 242, 812, +-851, 32, -601, -771, 565, -258, 688, 727, +-423, 431, -888, -585, 120, -580, 810, 395, +41, 656, -867, -250, -292, -601, 729, 102, +341, 511, -695, -24, -569, -379, 486, -12, +460, 210, -426, 49, -562, -64, 195, -13, +379, -77, -263, -64, -342, 140, 97, 150, +207, -65, -216, -271, -227, -55, 143, 283, +114, 262, -252, -247, -286, -444, 204, 167, +195, 569, -272, 6, -443, -699, 69, -142, +430, 693, -79, 373, -583, -644, -268, -554, +489, 476, 348, 677, -464, -189, -645, -747, +212, -100, 713, 630, -168, 440, -873, -456, +-205, -681, 788, 178, 312, 866, -825, 170, +-720, -979, 482, -545, 833, 918, -308, 943, +-1066, -705, -208, -1263, 963, 348, 462, 1405, +-946, 104, -874, -1376, 602, -528, 990, 1175, +-421, 874, -1235, -836, -55, -1158, 1098, 437, +277, 1290, -1116, 54, -705, -1294, 667, -542, +785, 1113, -425, 977, -1008, -741, -82, -1303, +803, 288, 368, 1428, -781, 216, -746, -1392, +367, -665, 830, 1193, -169, 1017, -1045, -838, +-318, -1242, 760, 384, 586, 1265, -703, 140, +-976, -1095, 171, -622, 968, 740, 93, 974, +-1077, -253, -548, -1157, 706, -223, 765, 1118, +-601, 696, -1033, -925, 101, -1058, 948, 585, +148, 1288, -1001, -115, -637, -1417, 532, -348, +843, 1309, -348, 852, -1150, -1061, -271, -1239, +1063, 664, 562, 1425, -1072, -126, -1031, -1500, +648, -334, 1175, 1315, -426, 784, -1392, -1034, +-176, -1129, 1252, 687, 434, 1268, -1215, -184, +-949, -1364, 730, -237, 1023, 1193, -448, 653, +-1258, -868, -149, -974, 1059, 516, 392, 1016, +-999, -32, -824, -995, 579, -318, 862, 802, +-357, 630, -1101, -466, -149, -906, 869, 128, +351, 957, -849, 336, -753, -879, 384, -733, +723, 644, -177, 938, -889, -232, -262, -1064, +626, -128, 393, 971, -605, 471, -649, -735, +242, -813, 526, 481, -130, 952, -589, -29, +-250, -1051, 237, -388, 276, 936, -167, 774, +-500, -593, -217, -1132, 249, 230, 280, 1212, +-230, 304, -547, -1194, -140, -758, 468, 965, +268, 1113, -580, -551, -625, -1408, 275, 87, +707, 1439, -191, 517, -953, -1328, -287, -1081, +760, 1006, 457, 1508, -746, -477, -883, -1783, +304, -50, 907, 1779, -90, 609, -1096, -1587, +-436, -1094, 907, 1243, 643, 1442, -847, -695, +-1104, -1684, 441, 94, 1138, 1668, -214, 536, +-1355, -1407, -362, -1077, 1154, 975, 541, 1382, +-1052, -388, -990, -1498, 607, -186, 980, 1397, +-358, 692, -1107, -1092, -188, -1126, 907, 678, +369, 1336, -789, -146, -797, -1344, 351, -413, +784, 1167, -156, 831, -880, -748, -364, -1146, +576, 286, 472, 1206, -407, 199, -774, -1063, +-76, -647, 689, 787, 276, 922, -709, -335, +-706, -1088, 375, -183, 801, 1053, -229, 696, +-1023, -783, -294, -1147, 861, 378, 500, 1389, +-821, 119, -937, -1388, 371, -628, 990, 1226, +-183, 997, -1117, -837, -315, -1290, 863, 387, +507, 1406, -737, 128, -873, -1332, 257, -651, +881, 1136, -5, 1015, -1012, -738, -490, -1256, +704, 305, 660, 1269, -576, 157, -951, -1120, +87, -557, 849, 824, 188, 866, -926, -436, +-601, -1032, 566, 14, 777, 1042, -441, 385, +-1014, -885, -25, -679, 882, 585, 270, 870, +-937, -247, -624, -878, 516, -130, 726, 802, +-385, 416, -874, -580, -72, -638, 676, 320, +278, 718, -671, -14, -563, -682, 314, -269, +579, 552, -218, 457, -665, -318, -94, -575, +380, 96, 177, 502, -294, 162, -390, -352, +-78, -330, 251, 87, 224, 427, -306, 232, +-442, -449, -44, -504, 433, 336, 174, 766, +-526, -187, -482, -893, 230, -31, 636, 896, +-191, 299, -787, -804, -255, -504, 666, 557, +490, 691, -697, -259, -819, -793, 291, -44, +964, 749, -160, 381, -1070, -666, -269, -586, +856, 410, 550, 728, -804, -95, -885, -763, +383, -208, 1019, 608, -183, 571, -1184, -448, +-210, -772, 908, 160, 475, 870, -792, 160, +-801, -867, 348, -407, 863, 650, -66, 664, +-1036, -411, -261, -808, 797, 118, 449, 810, +-676, 230, -692, -788, 283, -463, 634, 573, +3, 697, -757, -280, -350, -837, 514, -16, +463, 799, -409, 376, -643, -744, 91, -576, +491, 552, 115, 712, -491, -272, -406, -796, +240, 8, 482, 699, -115, 341, -643, -609, +-123, -591, 486, 435, 224, 727, -455, -222, +-396, -795, 152, 59, 353, 693, 11, 145, +-412, -532, -286, -326, 207, 323, 391, 435, +-169, -48, -481, -531, -104, -152, 384, 498, +201, 324, -315, -419, -466, -434, 29, 291, +587, 442, 82, -68, -748, -446, -384, -115, +721, 313, 435, 329, -707, -171, -566, -454, +460, -14, 520, 485, -289, 209, -529, -489, +-64, -352, 367, 389, 278, 514, -357, -241, +-507, -634, 142, 30, 523, 667, -82, 231, +-553, -627, -126, -441, 304, 503, 260, 616, +-240, -300, -380, -773, -57, 110, 396, 837, +140, 146, -401, -887, -297, -356, 140, 863, +370, 490, -36, -742, -425, -567, -322, 634, +380, 503, 473, -454, -388, -408, -662, 296, +157, 268, 723, -142, -73, -88, -746, 8, +-205, -60, 603, 54, 370, 210, -554, -72, +-534, -297, 276, 59, 581, 311, -153, -26, +-606, -291, -81, 36, 378, 188, 267, -42, +-273, -70, -433, 90, -57, -82, 526, -172, +261, 235, -637, 226, -481, -320, 508, -334, +653, 393, -487, 407, -787, -384, 253, -475, +778, 291, -68, 562, -856, -198, -120, -577, +680, 32, 274, 594, -610, 96, -404, -609, +396, -172, 366, 568, -189, 272, -406, -575, +-31, -251, 230, 495, 196, 178, -106, -389, +-411, -52, -87, 319, 420, -176, 258, -189, +-524, 336, -447, 123, 442, -501, 514, -48, +-341, 648, -702, 4, 206, -738, 687, -88, +-38, 836, -798, 239, -116, -877, 771, -461, +150, 889, -751, 754, -273, -933, 699, -1037, +171, 964, -616, 1342, -215, -965, 526, -1636, +114, 1008, -510, 1788, -63, -981, 405, -1915, +-2, 1050, -463, 1919, 76, -1102, 383, -1839, +-146, 1157, -404, 1718, 145, -1290, 360, -1474, +-205, 1388, -354, 1286, 165, -1556, 315, -1134, +-219, 1710, -335, 1027, 249, -1793, 248, -1032, +-293, 1899, -272, 1051, 348, -1960, 225, -1138, +-455, 1976, -242, 1287, 476, -1948, 305, -1390, +-640, 1821, -339, 1427, 654, -1639, 373, -1409, +-701, 1456, -456, 1249, 689, -1180, 400, -1088, +-546, 905, -507, 845, 423, -611, 455, -557, +-251, 313, -450, 360, 36, -132, 411, -182, +16, -52, -256, 151, -203, 153, 99, -155, +223, -202, 84, 227, -287, 196, -334, -335, +334, -186, 444, 477, -313, 186, -606, -572, +269, -267, 660, 629, -234, 358, -635, -595, +66, -492, 613, 507, 5, 652, -553, -377, +-153, -789, 469, 136, 300, 962, -553, 79, +-330, -1014, 519, -382, 405, 1058, -656, 639, +-393, -1005, 744, -874, 264, 869, -735, 1136, +-270, -725, 807, -1311, 116, 484, -723, 1486, +-125, -266, 637, -1599, 141, 67, -599, 1630, +-98, 120, 420, -1611, 118, -301, -316, 1529, +-77, 390, 146, -1280, -10, -532, 99, 1074, +-23, 538, -234, -799, -43, -536, 373, 539, +46, 558, -466, -377, -33, -434, 397, 135, +97, 362, -404, -27, -79, -180, 284, -67, +95, -5, -182, 135, -127, 143, 109, -177, +113, -247, -8, 206, -178, 320, -41, -266, +261, -243, 27, 243, -349, 136, -19, -281, +514, 50, -109, 316, -631, -260, 217, -294, +739, 346, -321, 342, -866, -434, 449, -342, +881, 359, -434, 457, -943, -195, 423, -628, +923, -68, -325, 816, -874, 399, 146, -1022, +855, -657, -26, 1180, -723, 846, -176, -1297, +618, -967, 329, 1324, -478, 1011, -435, -1221, +301, -979, 543, 997, -142, 859, -591, -743, +23, -645, 550, 461, 152, 458, -544, -235, +-221, -234, 415, 0, 326, 25, -266, 219, +-439, 149, 178, -349, 405, -304, 33, 467, +-465, 341, -105, -507, 417, -333, 207, 531, +-319, 292, -337, -528, 269, -207, 400, 487, +-142, 135, -497, -461, 52, -67, 609, 489, +-37, 32, -632, -539, -31, -55, 703, 624, +53, 113, -752, -712, -25, -156, 728, 775, +95, 222, -752, -849, -76, -276, 691, 879, +146, 314, -569, -840, -308, -310, 515, 768, +459, 210, -370, -660, -712, -43, 313, 542, +943, -180, -233, -431, -1101, 458, 122, 302, +1243, -794, 23, -183, -1276, 1141, -190, 141, +1239, -1480, 443, -140, -1180, 1733, -650, 189, +1050, -1850, 887, -285, -874, 1874, -1095, 402, +713, -1760, 1194, -567, -459, 1527, -1229, 779, +227, -1218, 1145, -936, 64, 826, -946, 1054, +-384, -469, 766, -1070, 673, 158, -487, 965, +-950, 127, 289, -793, 1105, -331, -47, 480, +-1128, 500, -172, -112, 1071, -591, 396, -291, +-888, 583, -650, 672, 764, -517, 864, -982, +-602, 384, -1041, 1213, 554, -218, 1107, -1371, +-503, 49, -1056, 1435, 500, 131, 933, -1422, +-473, -304, -761, 1350, 468, 422, 593, -1156, +-438, -566, -435, 969, 428, 614, 323, -717, +-387, -678, -192, 502, 308, 718, 140, -323, +-220, -724, -38, 139, 76, 761, 7, -11, +45, -730, 86, -118, -166, 712, -191, 182, +331, -686, 305, -235, -408, 674, -485, 257, +573, -642, 590, -313, -617, 625, -676, 305, +666, -552, 704, -311, -635, 494, -625, 287, +533, -435, 531, -236, -410, 344, -355, 204, +289, -263, 140, -107, -154, 155, 81, -12, +108, -72, -299, 138, -110, 31, 520, -250, +173, -55, -638, 361, -348, 142, 804, -428, +477, -351, -829, 506, -639, 648, 850, -555, +756, -1001, -800, 562, -787, 1393, 651, -553, +804, -1700, -500, 470, -716, 1958, 304, -310, +611, -2101, -131, 62, -469, 2119, 21, 280, +328, -2027, 39, -673, -163, 1835, -39, 1065, +63, -1544, -37, -1435, 42, 1173, 127, 1705, +-42, -704, -264, -1829, -4, 164, 412, 1825, +76, 369, -499, -1654, -216, -911, 618, 1421, +274, 1389, -579, -1096, -363, -1820, 524, 705, +413, 2149, -360, -297, -413, -2331, 142, -140, +428, 2405, 49, 494, -359, -2338, -227, -816, +272, 2199, 337, 1084, -132, -2003, -335, -1299, +-74, 1721, 297, 1475, 281, -1407, -174, -1564, +-478, 1072, -3, 1577, 706, -738, 134, -1534, +-819, 416, -307, 1441, 919, -91, 419, -1294, +-943, -254, -464, 1144, 849, 568, 516, -934, +-760, -896, -465, 740, 606, 1168, 398, -529, +-423, -1382, -325, 275, 287, 1555, 213, -54, +-118, -1587, -167, -230, 18, 1604, 129, 472, +29, -1503, -98, -750, -58, 1357, 127, 982, +38, -1147, -135, -1165, -56, 894, 171, 1284, +101, -626, -221, -1336, -142, 331, 266, 1324, +220, -41, -303, -1252, -296, -248, 333, 1122, +340, 478, -276, -924, -414, -666, 193, 729, +429, 757, -39, -471, -435, -844, -150, 248, +415, 840, 300, 21, -314, -789, -472, -257, +215, 684, 540, 402, -19, -506, -578, -520, +-180, 377, 537, 519, 371, -202, -423, -505, +-561, 53, 262, 433, 689, 88, -38, -305, +-781, -214, -189, 134, 804, 274, 406, 60, +-791, -262, -536, -270, 680, 228, 629, 440, +-543, -154, -597, -602, 309, 50, 556, 714, +-97, 74, -440, -728, -113, -252, 267, 697, +270, 410, -96, -560, -328, -580, -143, 398, +342, 736, 355, -230, -304, -830, -549, 37, +217, 909, 724, 87, -139, -891, -814, -202, +39, 841, 846, 251, 69, -766, -827, -264, +-162, 642, 725, 296, 279, -527, -646, -291, +-365, 391, 547, 263, 440, -262, -468, -262, +-476, 213, 414, 218, 428, -155, -336, -198, +-386, 157, 259, 170, 299, -204, -129, -73, +-246, 220, -28, 8, 192, -288, 229, 112, +-190, 316, -416, -240, 157, -308, 640, 323, +-141, 345, -827, -436, 55, -353, 1021, 470, +59, 413, -1194, -459, -202, -504, 1298, 436, +423, 577, -1416, -358, -589, -699, 1382, 272, +829, 829, -1328, -150, -1035, -912, 1162, -54, +1201, 977, -873, 246, -1355, -944, 560, -453, +1390, 826, -153, 634, -1348, -678, -250, -715, +1211, 425, 632, 750, -977, -180, -947, -673, +690, -69, 1173, 469, -386, 318, -1249, -240, +53, -441, 1224, -89, 227, 532, -1060, 397, +-481, -518, 811, -686, 693, 417, -533, 956, +-794, -280, 169, -1110, 864, 48, 160, 1208, +-811, 217, -483, -1219, 670, -492, 781, 1095, +-481, 830, -993, -935, 226, -1087, 1138, 661, +25, 1288, -1170, -329, -248, -1395, 1079, 17, +458, 1312, -905, 324, -583, -1148, 636, -581, +692, 888, -339, 721, -719, -577, 46, -814, +660, 355, 253, 772, -554, -146, -473, -692, +353, -2, 698, 561, -135, 67, -834, -351, +-110, -128, 956, 153, 335, 105, -983, 44, +-551, -47, 971, -215, 742, 0, -883, 316, +-922, 73, 768, -402, 1083, -150, -608, 476, +-1216, 216, 422, -482, 1346, -347, -232, 509, +-1380, 433, -33, -463, 1410, -527, 280, 410, +-1323, 612, -536, -370, 1192, -642, 764, 275, +-988, 717, -927, -227, 714, -718, 1060, 120, +-390, 752, -1097, -46, 4, -761, 1137, -60, +370, 765, -1077, 196, -766, -754, 1007, -337, +1101, 718, -824, 496, -1384, -671, 595, -673, +1568, 617, -257, 870, -1643, -523, -108, -1085, +1587, 363, 520, 1281, -1383, -171, -903, -1385, +1079, -98, 1247, 1456, -679, 335, -1493, -1421, +283, -625, 1640, 1337, 132, 906, -1673, -1178, +-470, -1155, 1602, 930, 763, 1384, -1419, -648, +-999, -1522, 1184, 321, 1167, 1606, -875, 42, +-1257, -1582, 537, -453, 1304, 1447, -198, 851, +-1238, -1156, -132, -1215, 1115, 820, 436, 1465, +-923, -433, -665, -1637, 681, 98, 848, 1728, +-395, 181, -945, -1698, 102, -434, 992, 1593, +201, 578, -973, -1343, -457, -680, 928, 1056, +700, 687, -831, -726, -907, -674, 719, 419, +1063, 675, -526, -111, -1191, -664, 335, -212, +1286, 640, -106, 509, -1282, -565, -130, -786, +1254, 446, 389, 972, -1109, -288, -636, -1099, +901, 129, 916, 1123, -598, 40, -1153, -1104, +272, -186, 1345, 1017, 117, 347, -1426, -910, +-475, -501, 1387, 777, 856, 634, -1199, -612, +-1177, -733, 904, 456, 1492, 757, -525, -308, +-1686, -735, 133, 174, 1833, 657, 254, -59, +-1824, -545, -606, -27, 1763, 384, 894, 120, +-1569, -215, -1116, -151, 1335, 19, 1295, 168, +-1054, 171, -1344, -165, 731, -318, 1367, 114, +-417, 470, -1247, -82, 109, -542, 1105, 3, +120, 579, -857, 87, -287, -548, 622, -160, +354, 466, -368, 238, -321, -372, 134, -289, +285, 278, 40, 323, -150, -201, -186, -337, +66, 126, 248, 338, 85, -107, -286, -263, +-180, 92, 264, 206, 322, -169, -212, -120, +-420, 261, 161, 60, 515, -359, -33, -33, +-566, 458, -59, -14, 572, -530, 226, 42, +-534, 612, -300, -37, 442, -703, 414, -20, +-320, 755, -413, 156, 192, -752, 418, -321, +-39, 700, -372, 457, -54, -564, 352, -584, +165, 455, -323, 647, -192, -310, 308, -697, +247, 192, -281, 731, -237, -69, 234, -694, +260, -45, -156, 638, -263, 96, 102, -494, +263, -112, -14, 350, -226, 83, -54, -189, +167, -39, 125, 41, -44, 15, -169, 78, +-79, -16, 223, -170, 202, 25, -214, 219, +-315, -80, 195, -197, 399, 139, -100, 153, +-474, -256, -3, -123, 539, 379, 163, 101, +-562, -501, -298, -169, 571, 610, 424, 275, +-524, -681, -491, -435, 465, 679, 568, 629, +-348, -656, -589, -816, 253, 542, 603, 981, +-64, -375, -615, -1090, -70, 177, 612, 1098, +292, 73, -561, -1050, -464, -288, 538, 925, +649, 497, -416, -741, -757, -662, 328, 547, +829, 766, -125, -285, -812, -788, -31, 51, +751, 707, 262, 204, -643, -532, -411, -367, +527, 335, 566, 503, -390, -112, -652, -574, +276, -63, 712, 630, -115, 259, -754, -619, +-11, -419, 740, 558, 195, 538, -721, -412, +-341, -587, 657, 257, 481, 545, -572, -128, +-589, -455, 479, 21, 658, 348, -404, 7, +-677, -229, 338, -44, 660, 110, -269, -7, +-628, -24, 244, 58, 560, -49, -171, -167, +-501, 23, 119, 241, 461, 6, -35, -294, +-389, -112, -31, 261, 345, 174, 115, -206, +-222, -244, -158, 111, 145, 246, 205, -14, +26, -252, -210, -59, -91, 201, 235, 150, +208, -147, -199, -192, -217, 76, 199, 227, +266, 22, -105, -195, -247, -71, 61, 142, +261, 138, 72, -25, -237, -107, -110, -75, +254, 85, 190, 198, -222, 24, -178, -238, +209, -107, 176, 278, -168, 243, -103, -189, +126, -352, 45, 74, -86, 461, 10, 146, +72, -502, -77, -352, -71, 520, 54, 570, +99, -478, -40, -740, -136, 384, -50, 868, +194, -287, 119, -961, -238, 88, -222, 981, +263, 89, 266, -973, -266, -315, -312, 875, +207, 472, 324, -831, -142, -643, -300, 721, +35, 751, 288, -687, 40, -886, -206, 570, +-90, 937, 157, -510, 143, -994, -23, 380, +-115, 958, -80, -322, 155, -927, 248, 250, +-125, 860, -310, -213, 164, -824, 443, 185, +-109, 776, -426, -138, 123, -748, 445, 144, +-4, 758, -363, -77, -17, -757, 330, 41, +140, 814, -214, 96, -156, -792, 166, -178, +206, 799, -67, 360, -166, -697, 43, -438, +126, 614, -5, 568, -28, -436, 14, -590, +-67, 310, -37, 626, 175, -108, 45, -583, +-306, -16, -61, 523, 387, 175, 44, -426, +-514, -276, -47, 296, 552, 351, 2, -161, +-611, -425, -29, -8, 581, 419, 15, 140, +-563, -442, -82, -304, 467, 351, 112, 374, +-386, -331, -152, -475, 258, 212, 156, 444, +-147, -220, -95, -465, 44, 136, 24, 387, +56, -194, 121, -373, -80, 168, -219, 285, +145, -242, 366, -273, -89, 282, -399, 224, +109, -346, 512, -276, -10, 393, -492, 354, +8, -366, 575, -445, 112, 304, -553, 573, +-98, -153, 621, -596, 210, 39, -591, 656, +-196, 155, 612, -600, 301, -235, -523, 603, +-344, 435, 482, -473, 415, -498, -353, 423, +-474, 648, 296, -226, 486, -658, -226, 138, +-475, 696, 154, 62, 400, -619, -135, -173, +-338, 572, 59, 340, 200, -439, -50, -478, +-136, 288, -20, 603, -5, -119, -9, -677, +56, -97, -28, 655, -158, 209, -59, -624, +215, -384, 78, 463, -286, 430, -187, -406, +311, -556, 242, 189, -338, 571, -306, -108, +322, -682, 377, -126, -286, 620, -371, 214, +258, -662, 406, -404, -148, 561, -353, 479, +122, -563, 359, -633, 31, 480, -254, 710, +-75, -440, 281, -810, 224, 353, -160, 860, +-241, -256, 200, -836, 333, 157, -80, 823, +-269, 6, 71, -678, 299, -91, 47, 596, +-173, 280, -106, -384, 163, -297, 220, 276, +-69, 425, -276, -45, 19, -324, 337, -28, +28, 323, -346, 207, -92, -124, 311, -221, +122, 33, -314, 325, -182, 185, 231, -300, +186, -324, -238, 311, -261, 514, 162, -229, +229, -644, -166, 118, -322, 700, 89, 12, +268, -722, -76, -181, -326, 615, -24, 247, +266, -557, 43, -401, -221, 359, -139, 378, +133, -284, 172, -477, -27, 58, -219, 381, +-90, -10, 269, -404, 215, -175, -249, 259, +-310, 165, 295, -246, 453, -267, -228, 90, +-512, 246, 236, -31, 673, -287, -111, -148, +-651, 258, 82, 278, 734, -248, 94, -439, +-607, 238, -119, 598, 549, -184, 266, -686, +-331, 202, -238, 798, 202, -94, 268, -771, +23, 118, -186, 822, -121, 9, 129, -693, +242, 15, -29, 722, -292, 103, -62, -545, +292, -65, 156, 559, -317, 153, -260, -396, +235, -92, 325, 386, -249, 178, -454, -257, +131, -159, 472, 184, -92, 241, -579, -56, +-57, -275, 526, -89, 126, 277, -548, 206, +-280, -266, 441, -369, 314, 141, -395, 393, +-398, -76, 256, -496, 384, -107, -173, 410, +-377, 137, 47, -470, 363, -313, 33, 346, +-316, 306, -107, -374, 334, -460, 194, 224, +-283, 405, -205, -202, 318, -472, 328, 30, +-273, 362, -308, 19, 318, -315, 422, -165, +-239, 182, -376, 235, 254, -57, 444, -311, +-104, -97, -369, 362, 51, 280, 430, -296, +120, -400, -372, 243, -174, 568, 416, -21, +256, -564, -368, -98, -237, 670, 323, 373, +241, -570, -230, -506, -203, 607, 60, 778, +192, -419, 63, -847, -210, 369, -277, 996, +173, -150, 377, -930, -186, 104, -559, 917, +57, 24, 593, -786, -6, -22, -678, 689, +-199, 53, 608, -548, 271, -64, -565, 388, +-458, 29, 378, -243, 515, -50, -232, 60, +-632, -52, 1, -3, 646, 41, 178, -116, +-666, -162, -357, 44, 628, 127, 501, -96, +-538, -230, -578, -43, 448, 168, 648, 21, +-266, -225, -607, -164, 174, 123, 599, 126, +26, -130, -453, -217, -64, 45, 391, 204, +170, -52, -198, -276, -113, 34, 135, 361, +116, -43, 30, -461, 35, 43, -60, 594, +-101, 19, 144, -629, 259, -20, -142, 720, +-351, 129, 172, -655, 449, -102, -154, 698, +-521, 214, 155, -585, 545, -184, -164, 611, +-584, 310, 133, -448, 552, -277, -165, 403, +-570, 362, 90, -202, 503, -284, -111, 110, +-534, 301, 16, 67, 437, -210, -16, -172, +-446, 156, -83, 303, 303, -54, 90, -397, +-243, -67, -179, 418, 87, 155, 192, -470, +16, -287, -269, 386, -142, 328, 283, -386, +230, -445, -291, 213, -309, 397, 295, -167, +395, -477, -208, -22, -439, 334, 153, 59, +549, -352, -7, -178, -541, 200, -101, 134, +636, -200, 278, -177, -553, 119, -356, 92, +549, -145, 516, -95, -415, 143, -517, 77, +318, -183, 597, -87, -156, 213, -522, 146, +42, -211, 493, -184, 136, 257, -385, 273, +-243, -188, 287, -320, 366, 249, -176, 463, +-445, -147, 49, -504, 433, 149, 74, 688, +-424, 1, -238, -671, 307, -72, 307, 770, +-232, 262, -448, -665, 106, -328, 392, 625, +-42, 491, -411, -465, -79, -524, 264, 348, +89, 593, -184, -175, -199, -596, 58, 49, +178, 544, -21, 82, -235, -502, -30, -205, +199, 378, 12, 247, -185, -297, -32, -361, +157, 142, 35, 317, -125, -96, -17, -376, +119, -54, 66, 268, -117, 40, -33, -266, +160, -140, 82, 133, -161, 73, -64, -115, +253, -103, 98, -6, -235, 35, -83, 11, +322, -31, 103, -94, -287, -10, -58, 117, +311, 22, 83, -153, -248, -49, -38, 185, +221, 59, 58, -145, -168, -26, -43, 167, +157, 34, 11, -94, -146, 45, 15, 130, +126, -4, -58, -69, -155, 74, 85, 125, +124, -15, -107, -69, -179, 55, 95, 135, +163, 23, -110, -81, -239, -9, 43, 108, +259, 105, -72, -42, -329, -111, -13, 24, +339, 189, -18, 37, -398, -211, -29, -70, +375, 229, 19, 111, -386, -264, -39, -182, +326, 220, 27, 228, -248, -219, -60, -334, +147, 113, 69, 338, -16, -85, -92, -417, +-76, -50, 124, 342, 188, 52, -94, -367, +-238, -167, 127, 255, 287, 150, -60, -241, +-279, -234, 71, 143, 297, 201, -40, -110, +-231, -216, 83, 20, 221, 135, -74, 4, +-154, -59, 123, -40, 132, -18, -113, 52, +-100, 107, 143, -34, 95, -132, -134, 58, +-89, 189, 124, 0, 111, -159, -131, 29, +-123, 198, 80, 45, 137, -114, -75, -1, +-166, 145, 2, 42, 149, -59, 34, 30, +-189, 78, -109, 9, 135, -19, 139, 56, +-133, 25, -218, -20, 51, 9, 221, 73, +-23, 11, -265, -89, -56, -16, 219, 122, +90, 58, -205, -167, -157, -111, 130, 162, +154, 141, -47, -176, -189, -208, -56, 93, +193, 179, 164, -64, -190, -215, -253, -78, +194, 131, 339, 110, -143, -120, -383, -253, +110, 5, 433, 258, -24, 37, -409, -339, +-30, -181, 426, 294, 124, 222, -362, -278, +-162, -329, 345, 198, 214, 354, -277, -123, +-192, -384, 225, 48, 212, 392, -173, 25, +-175, -358, 133, -49, 160, 369, -97, 112, +-141, -319, 75, -88, 136, 330, -63, 148, +-176, -264, 61, -92, 184, 296, -84, 148, +-228, -234, 57, -121, 250, 293, -79, 196, +-297, -234, 34, -210, 280, 269, -16, 298, +-320, -206, -47, -321, 289, 184, 62, 376, +-311, -116, -82, -379, 261, 41, 20, 371, +-210, 26, 6, -357, 141, -112, -98, 272, +-76, 144, 167, -234, 4, -204, -236, 121, +20, 153, 303, -87, -25, -181, -327, -8, +-6, 77, 352, 19, 84, -89, -337, -103, +-141, 7, 299, 89, 262, 3, -213, -163, +-348, -76, 167, 124, 463, 98, -66, -146, +-495, -159, 26, 102, 496, 185, 71, -60, +-433, -209, -128, 17, 373, 223, 204, 46, +-235, -194, -279, -75, 137, 205, 341, 155, +-42, -125, -379, -158, -40, 134, 375, 236, +105, -59, -353, -203, -176, 69, 281, 273, +195, -10, -227, -204, -215, 28, 104, 217, +185, 26, -36, -133, -169, -4, -90, 98, +99, 58, 145, -23, -69, -62, -208, -37, +-21, 75, 230, 98, 57, -84, -250, -147, +-123, 36, 228, 149, 156, -34, -214, -168, +-188, -36, 165, 100, 206, 41, -132, -109, +-202, -104, 79, 2, 211, 105, -18, -1, +-216, -186, -2, -83, 226, 168, 47, 89, +-199, -239, -69, -144, 206, 210, 109, 148, +-159, -222, -148, -194, 162, 184, 198, 201, +-104, -136, -249, -226, 90, 85, 299, 255, +-45, -4, -278, -231, -17, -65, 279, 230, +109, 163, -247, -126, -192, -200, 210, 78, +282, 286, -181, 41, -332, -264, 97, -87, +358, 344, -20, 196, -388, -315, -67, -244, +331, 356, 171, 373, -312, -319, -269, -430, +241, 305, 304, 541, -188, -256, -322, -602, +88, 224, 235, 662, 35, -163, -219, -710, +-165, 99, 149, 712, 230, -37, -85, -728, +-320, -76, 17, 685, 347, 119, 34, -661, +-340, -238, -128, 572, 309, 263, 204, -521, +-241, -351, -299, 363, 214, 357, 348, -278, +-155, -405, -349, 100, 97, 379, 346, 7, +-39, -380, -262, -139, -9, 296, 198, 206, +85, -226, -98, -255, -97, 113, 12, 270, +143, 11, 86, -266, -136, -87, -158, 267, +127, 198, 243, -244, -96, -221, -281, 265, +37, 292, 322, -206, 24, -296, -334, 210, +-77, 355, 317, -112, 121, -348, -301, 87, +-144, 405, 233, 11, 162, -388, -198, -65, +-170, 410, 150, 170, 140, -365, -132, -249, +-135, 307, 97, 365, 87, -216, -104, -436, +-68, 109, 64, 491, 16, -30, -43, -527, +19, -58, -45, 494, -37, 99, 104, -504, +28, -169, -172, 428, -48, 195, 231, -406, +39, -274, -265, 310, -91, 273, 326, -281, +161, -326, -381, 210, -225, 286, 418, -216, +324, -280, -422, 194, -401, 232, 402, -230, +502, -200, -323, 231, -567, 145, 254, -237, +609, -94, -97, 234, -622, 42, -24, -198, +627, 9, 149, 190, -530, -23, -276, -128, +434, 78, 389, 110, -301, -59, -476, -42, +167, 118, 522, 52, -49, -97, -497, -16, +-106, 125, 463, 38, 240, -82, -406, 10, +-365, 58, 319, -23, 462, 13, -256, 78, +-511, -57, 161, -123, 506, 135, -81, 155, +-510, -190, -8, -174, 460, 244, 70, 165, +-428, -315, -126, -178, 368, 326, 131, 169, +-303, -364, -158, -200, 230, 324, 122, 193, +-153, -306, -128, -221, 63, 233, 131, 181, +0, -203, -140, -181, -54, 118, 142, 120, +99, -74, -115, -70, -162, -29, 85, -15, +255, 99, -79, 108, -323, -176, 80, -207, +382, 226, -35, 290, -432, -230, 13, -362, +465, 243, 68, 419, -468, -185, -143, -452, +459, 149, 268, 520, -422, -51, -371, -527, +383, -25, 447, 571, -284, 158, -494, -515, +159, -230, 507, 466, 0, 329, -483, -338, +-168, -345, 431, 222, 328, 370, -360, -77, +-440, -343, 261, -40, 493, 306, -144, 161, +-517, -237, -1, -235, 488, 154, 98, 274, +-433, -73, -204, -292, 316, -3, 269, 254, +-215, 41, -314, -245, 96, -92, 313, 184, +-16, 87, -275, -155, -100, -115, 210, 88, +183, 89, -160, -51, -242, -104, 86, -19, +257, 80, -25, 37, -257, -74, -25, -69, +240, 52, 51, 33, -197, -56, -44, 6, +125, 62, 80, -58, -56, -83, -125, 110, +47, 106, 156, -122, -17, -117, -173, 145, +17, 144, 174, -118, 4, -117, -160, 120, +-29, 135, 161, -73, 60, -99, -136, 60, +-73, 83, 128, -8, 109, -33, -99, 9, +-106, 6, 41, 9, 124, 50, 26, 29, +-126, -60, -109, -64, 134, 81, 190, 104, +-155, -60, -222, -146, 141, 31, 240, 170, +-96, 13, -266, -202, 24, -88, 287, 224, +40, 161, -328, -253, -92, -281, 337, 233, +99, 372, -313, -223, -123, -462, 244, 154, +138, 479, -180, -98, -191, -499, 128, 23, +230, 457, -136, 17, -231, -449, 151, -59, +189, 399, -180, 60, -105, -363, 177, -51, +14, 312, -164, -2, 72, -260, 129, 53, +-90, 226, -100, -94, 43, -197, 113, 126, +32, 222, -175, -102, -67, -253, 242, 95, +78, 311, -244, -53, -75, -344, 214, 47, +129, 402, -149, -25, -198, -397, 105, 16, +267, 392, -23, 45, -324, -311, -31, -119, +373, 214, 94, 215, -360, -105, -124, -271, +327, -8, 163, 307, -251, 101, -221, -302, +199, -156, 251, 253, -133, 193, -257, -196, +53, -241, 257, 108, 52, 266, -284, -48, +-136, -301, 318, -29, 180, 284, -355, 55, +-179, -283, 363, -89, 164, 236, -365, 68, +-151, -209, 330, -84, 148, 165, -271, 84, +-220, -146, 229, -122, 286, 127, -224, 139, +-344, -128, 239, -159, 358, 108, -264, 177, +-328, -98, 240, -182, 287, 92, -191, 187, +-238, -66, 103, -172, 217, 17, 3, 159, +-211, 68, -56, -126, 225, -160, 59, 111, +-199, 266, -25, -61, 162, -345, -5, 52, +-84, 412, 17, -27, 48, -423, -27, 22, +-11, 438, 76, 10, -30, -403, -101, -32, +45, 383, 140, 53, -37, -317, -162, -52, +16, 245, 195, 42, -14, -157, -219, -19, +57, 65, 198, 2, -87, 21, -167, -19, +103, -117, 149, 49, -117, 185, -133, -118, +122, -231, 107, 151, -127, 236, -92, -187, +126, -239, 71, 197, -123, 194, -114, -201, +141, -165, 142, 178, -170, 127, -176, -144, +164, -141, 212, 91, -163, 176, -270, -58, +169, -232, 326, 32, -229, 294, -351, -25, +267, -348, 344, 40, -278, 393, -334, -65, +262, -398, 326, 81, -237, 407, -319, -72, +208, -395, 314, 77, -172, 421, -337, -69, +147, -434, 398, 75, -141, 480, -441, -28, +160, -559, 460, 4, -141, 658, -448, 50, +146, -768, 415, -67, -127, 867, -357, 99, +112, -943, 296, -110, -64, 1020, -216, 99, +-2, -1066, 180, -81, 37, 1092, -119, 58, +-40, -1077, 28, -38, 12, 1052, 85, -28, +23, -995, -188, 92, -41, 913, 251, -191, +46, -827, -255, 258, -83, 741, 223, -335, +132, -686, -160, 401, -244, 615, 101, -459, +354, -593, -77, 500, -420, 579, 39, -537, +429, -623, -1, 544, -394, 659, -52, -517, +325, -690, 74, 440, -241, 713, -75, -356, +121, -720, 89, 272, 26, 687, -142, -185, +-139, -619, 205, 78, 221, 542, -263, 68, +-224, -467, 271, -195, 199, 398, -211, 302, +-157, -315, 127, -364, 131, 270, 0, 389, +-158, -214, -81, -384, 234, 170, 154, 376, +-324, -79, -164, -388, 415, -27, 177, 431, +-471, 136, -171, -457, 517, -254, 179, 505, +-545, 362, -166, -553, 545, -495, 206, 623, +-520, 606, -287, -650, 493, -743, 393, 621, +-455, 882, -496, -541, 433, -1015, 513, 391, +-352, 1118, -517, -227, 255, -1177, 480, -10, +-137, 1229, -441, 210, 5, -1241, 388, -442, +102, 1219, -315, 637, -210, -1135, 215, -830, +258, 985, -96, 982, -270, -796, -56, -1054, +219, 537, 236, 1080, -206, -277, -371, -1038, +180, -3, 474, 982, -193, 235, -476, -872, +165, -459, 464, 743, -128, 644, -402, -588, +95, -772, 305, 420, -42, 851, -188, -228, +-4, -855, 70, 43, 100, 875, -31, 84, +-151, -856, 81, -176, 207, 857, -203, 224, +-192, -813, 350, -266, 181, 764, -494, 312, +-134, -677, 607, -325, 102, 539, -666, 380, +-90, -399, 683, -433, 138, 241, -640, 539, +-253, -123, 616, -649, 354, -8, -529, 758, +-454, 128, 428, -845, 471, -220, -266, 849, +-476, 303, 63, -797, 443, -328, 126, 651, +-405, 352, -308, -511, 345, -321, 417, 321, +-259, 276, -477, -117, 121, -230, 463, -115, +43, 156, -405, 361, -207, -98, 267, -543, +361, -23, -114, 698, -470, 107, -79, -741, +549, -180, 251, 699, -583, 227, -413, -568, +569, -264, 580, 369, -526, 341, -720, -167, +464, -388, 842, -75, -388, 454, -882, 289, +296, -456, 886, -474, -170, 402, -850, 609, +62, -289, 838, -669, 50, 116, -822, 709, +-135, 57, 840, -667, 188, -243, -836, 615, +-180, 417, 810, -528, 158, -606, -693, 429, +-168, 783, 574, -319, 238, -894, -494, 166, +-306, 959, 462, -20, 344, -951, -420, -126, +-345, 907, 317, 243, 339, -822, -177, -348, +-362, 708, 34, 460, 395, -583, 46, -545, +-404, 389, -121, 619, 408, -142, 127, -665, +-380, -136, -131, 668, 329, 423, 92, -664, +-243, -655, -69, 610, 142, 846, 61, -548, +-89, -973, -43, 430, 67, 1031, 31, -235, +-91, -1051, -26, -11, 133, 991, 57, 313, +-210, -894, -83, -569, 287, 704, 140, 771, +-360, -471, -161, -893, 384, 211, 213, 925, +-344, 86, -271, -895, 239, -377, 383, 760, +-45, 686, -528, -570, -117, -948, 665, 277, +320, 1101, -750, 79, -440, -1131, 746, -477, +587, 1001, -666, 867, -677, -758, 530, -1193, +761, 416, -357, 1435, -799, -14, 184, -1567, +773, -409, -4, 1551, -672, 847, -130, -1383, +469, -1269, 253, 1068, -209, 1614, -332, -596, +-105, -1855, 405, 53, 344, 1928, -385, 556, +-569, -1860, 294, -1106, 716, 1647, -136, 1572, +-826, -1280, -73, -1941, 860, 837, 268, 2144, +-791, -234, -508, -2253, 647, -376, 693, 2175, +-411, 1025, -874, -1964, 144, -1592, 979, 1629, +150, 1995, -1039, -1166, -399, -2260, 1000, 670, +634, 2292, -864, -96, -824, -2231, 651, -456, +1000, 2016, -376, 979, -1128, -1725, 147, -1429, +1152, 1342, 119, 1698, -1079, -862, -345, -1822, +911, 370, 575, 1732, -684, 137, -731, -1544, +439, -578, 833, 1259, -153, 928, -872, -920, +-127, -1158, 821, 561, 428, 1254, -702, -163, +-691, -1229, 513, -229, 958, 1066, -319, 602, +-1135, -793, 107, -888, 1234, 470, 96, 1056, +-1231, -123, -301, -1081, 1127, -178, 504, 994, +-944, 430, -717, -780, 688, -623, 920, 534, +-438, 743, -1087, -201, 155, -767, 1180, -127, +94, 684, -1181, 455, -363, -469, 1116, -741, +608, 184, -991, 905, -825, 177, 798, -979, +1004, -490, -571, 913, -1153, 784, 316, -775, +1271, -1002, -88, 540, -1302, 1122, -96, -240, +1259, -1172, 230, -89, -1100, 1056, -343, 451, +896, -848, 414, -769, -616, 503, -457, 1012, +320, -114, 490, -1157, -23, -302, -476, 1181, +-238, 683, 447, -1127, 433, -1009, -328, 982, +-561, 1234, 180, -770, 661, -1392, 4, 498, +-701, 1441, -157, -206, 696, -1374, 292, -90, +-614, 1225, -387, 299, 474, -954, 473, -454, +-294, 671, -526, 505, 104, -349, 556, -474, +68, 30, -546, 420, -193, 230, 477, -262, +291, -466, -368, 127, -375, 583, 213, 106, +449, -612, -94, -309, -474, 536, -30, 503, +454, -335, 136, -667, -414, 132, -234, 720, +346, 161, 305, -751, -272, -391, -343, 662, +191, 624, 355, -527, -116, -814, -345, 341, +52, 900, 317, -68, 16, -966, -261, -205, +-92, 877, 218, 524, 157, -768, -169, -792, +-188, 556, 131, 960, 207, -296, -63, -1079, +-209, 20, -16, 1035, 246, 294, 109, -970, +-265, -590, -167, 787, 274, 834, 253, -539, +-260, -1026, -337, 249, 239, 1054, 452, 105, +-192, -998, -555, -445, 181, 804, 622, 723, +-135, -491, -665, -943, 95, 167, 631, 1005, +28, 262, -585, -984, -189, -648, 512, 844, +360, 1022, -442, -539, -531, -1329, 365, 210, +621, 1471, -237, 283, -713, -1511, 95, -700, +719, 1351, 85, 1155, -695, -1061, -274, -1506, +611, 670, 450, 1745, -479, -145, -631, -1895, +325, -342, 753, 1805, -137, 908, -815, -1626, +-75, -1336, 811, 1232, 296, 1665, -754, -737, +-485, -1859, 662, 195, 640, 1804, -523, 421, +-720, -1673, 340, -935, 744, 1312, -141, 1369, +-650, -851, -77, -1678, 494, 332, 299, 1716, +-281, 272, -473, -1665, 75, -784, 588, 1344, +158, 1220, -585, -874, -417, -1553, 508, 328, +651, 1647, -337, 366, -857, -1667, 152, -954, +975, 1407, 92, 1526, -999, -1013, -351, -1933, +914, 496, 612, 2123, -707, 180, -853, -2196, +428, -763, 1042, 1979, -107, 1415, -1173, -1658, +-217, -1847, 1196, 1125, 536, 2140, -1096, -456, +-832, -2236, 884, -200, 1062, 2059, -590, 911, +-1196, -1756, 213, -1395, 1233, 1207, 170, 1804, +-1159, -567, -564, -1984, 985, -148, 896, 1947, +-697, 891, -1147, -1735, 322, -1516, 1321, 1285, +71, 2030, -1365, -736, -494, -2315, 1323, 73, +870, 2377, -1138, 606, -1196, -2243, 860, -1242, +1434, 1902, -543, 1770, -1523, -1435, 210, -2133, +1492, 834, 118, 2272, -1301, -218, -435, -2194, +1010, -367, 741, 1860, -651, 846, -933, -1400, +267, -1162, 1051, 796, 98, 1318, -1038, -190, +-418, -1279, 896, -364, 723, 1025, -682, 826, +-938, -619, 409, -1084, 1067, 53, -131, 1163, +-1069, 560, -142, -1041, 974, -1123, 420, 737, +-826, 1615, -644, -336, 615, -1890, 796, -180, +-366, 1986, -863, 764, 105, -1842, 813, -1302, +154, 1461, -748, 1833, -359, -930, 616, -2168, +521, 242, -444, 2374, -637, 447, 269, -2352, +647, -1091, -62, 2130, -667, 1667, -80, -1726, +595, -2077, 217, 1143, -522, 2330, -293, -484, +412, -2353, 288, -219, -223, 2161, -278, 843, +70, -1789, 211, -1355, 116, 1295, -216, 1696, +-238, -717, 210, -1873, 329, 100, -189, 1866, +-367, 493, 173, -1706, 330, -1003, -90, 1371, +-301, 1368, 51, -944, 272, -1564, -15, 443, +-233, 1591, 4, 46, 199, -1467, -33, -507, +-112, 1219, 42, 930, 53, -920, -60, -1198, +-3, 523, 85, 1378, -67, -153, -91, -1337, +95, -210, 159, 1153, -163, 532, -170, -896, +145, -679, 202, 498, -125, 832, -241, -165, +133, -806, 263, -221, -100, 710, -339, 576, +112, -553, 336, -779, -52, 226, -376, 1002, +39, 30, 353, -1016, -30, -341, -287, 959, +-24, 603, 232, -839, 72, -769, -136, 559, +-170, 962, 101, -280, 181, -1023, -48, -88, +-170, 995, -30, 484, 172, -935, 116, -782, +-174, 730, -203, 1072, 166, -527, 239, -1235, +-135, 263, -218, 1286, 69, 62, 227, -1318, +-37, -309, -192, 1163, -32, 615, 168, -1033, +129, -769, -146, 768, -187, 896, 106, -538, +275, -938, -114, 327, -270, 874, 69, -79, +315, -843, -56, -18, -326, 648, 45, 206, +294, -519, -22, -223, -273, 285, 57, 233, +190, -72, -20, -221, -147, -28, -3, 101, +62, 179, 41, -59, 16, -178, -69, -83, +-75, 216, 70, 199, 109, -205, -79, -263, +-139, 100, 50, 374, 167, -35, -19, -340, +-210, -107, -21, 319, 216, 211, 36, -278, +-181, -272, -88, 200, 147, 392, 127, -252, +-102, -380, -172, 215, 47, 406, 174, -233, +-2, -357, -126, 238, -54, 233, 73, -161, +93, -243, -2, 216, -130, 112, -84, -99, +201, -171, 127, 70, -208, 204, -180, -30, +170, -190, 192, -99, -77, 322, -176, 27, +-74, -228, 213, -145, 150, 297, -165, 139, +-257, -261, 117, -162, 315, 170, -7, 261, +-330, -172, -147, -195, 371, 20, 228, 232, +-297, 18, -378, -148, 248, -97, 463, 60, +-117, 196, -526, -9, -81, -221, 591, -96, +205, 266, -533, 143, -382, -219, 480, -179, +476, 111, -369, 216, -574, -12, 182, -172, +685, -141, -51, 148, -693, 231, -165, -83, +721, -301, 245, 3, -681, 345, -295, 66, +537, -314, 342, -203, -397, 289, -346, 281, +167, -204, 388, -336, -72, 107, -386, 338, +40, -15, 294, -275, -29, -114, -174, 203, +21, 219, -32, -116, 53, -307, 146, 15, +-108, 378, -169, 46, 65, -348, 167, -152, +-32, 301, -95, 202, -92, -185, 98, -245, +151, 83, -130, 259, -149, -12, 120, -179, +97, -90, -140, 106, 82, 139, 11, 73, +-177, -256, 83, -186, 231, 304, -176, 304, +-218, -332, 170, -347, 146, 319, -23, 310, +-169, -201, -157, -290, 165, 105, 351, 193, +-236, 74, -478, -154, 261, -199, 516, 115, +-291, 286, -535, -48, 235, -350, 483, 19, +-150, 310, -450, 60, 23, -270, 394, -125, +20, 203, -331, 171, -75, -116, 209, -259, +88, 83, -88, 265, -139, -21, -50, -269, +165, -35, 71, 219, -172, 97, -100, -130, +145, -210, 38, 111, -67, 252, -79, -84, +-20, -308, 101, 117, 50, 301, -132, -177, +-38, -219, 100, 171, -72, 156, 8, -207, +83, 0, -140, 175, -73, -103, 244, -159, +-60, 193, -253, 182, 131, -323, 165, -129, +-169, 389, -77, 136, 114, -513, -10, -60, +-31, 580, -15, 8, -55, -608, 37, 5, +88, 658, -135, -36, -60, -648, 169, 17, +-42, 673, -206, -31, 95, -670, 140, 66, +-116, 661, -124, -108, 69, -648, 73, 141, +-37, 625, -140, -145, 15, -624, 147, 118, +-62, 662, -201, -47, 63, -782, 196, -2, +-175, 923, -177, 34, 179, -1074, 150, -53, +-280, 1194, -133, 38, 280, -1242, 100, -72, +-341, 1259, -160, 78, 400, -1231, 145, -85, +-464, 1137, -214, 118, 483, -1082, 177, -79, +-499, 969, -215, 70, 461, -918, 232, -10, +-511, 905, -257, -142, 488, -869, 203, 316, +-542, 942, -123, -631, 528, -965, -64, 969, +-527, 1004, 178, -1298, 494, -1066, -347, 1650, +-499, 1063, 429, -1869, 487, -1138, -533, 2107, +-562, 1179, 569, -2261, 546, -1217, -567, 2340, +-614, 1268, 475, -2367, 611, -1253, -376, 2267, +-711, 1285, 167, -2130, 772, -1292, -53, 1954, +-852, 1307, -124, -1747, 833, -1353, 168, 1571, +-812, 1354, -246, -1369, 647, -1360, 270, 1143, +-543, 1354, -317, -921, 314, -1323, 292, 629, +-171, 1317, -286, -383, -51, -1279, 169, 109, +247, 1225, -193, 134, -471, -1118, 154, -405, +572, 988, -259, 655, -603, -828, 281, -940, +462, 686, -318, 1139, -388, -499, 246, -1306, +240, 301, -220, 1415, -200, -101, 105, -1430, +155, -174, -117, 1460, -207, 377, 36, -1361, +273, -636, -78, 1301, -455, 804, 87, -1149, +509, -963, -132, 1039, -704, 1074, 165, -934, +713, -1158, -195, 923, -799, 1177, 115, -939, +753, -1143, -109, 1001, -706, 1062, -107, -1036, +669, -943, 155, 994, -640, 908, -333, -985, +563, -866, 348, 884, -550, 983, -349, -898, +363, -1067, 257, 845, -292, 1254, -184, -853, +33, -1381, 62, 776, 136, 1518, -64, -671, +-368, -1617, -23, 487, 476, 1648, -24, -211, +-609, -1662, -19, -78, 568, 1506, 31, 483, +-655, -1362, -91, -822, 562, 1020, 131, 1250, +-642, -722, -196, -1564, 601, 301, 154, 1843, +-644, 113, -225, -2005, 587, -532, 136, 2027, +-528, 995, -267, -1972, 411, -1341, 294, 1702, +-370, 1737, -530, -1411, 300, -1965, 684, 932, +-365, 2213, -938, -480, 362, -2321, 1081, -36, +-485, 2361, -1273, 517, 479, -2295, 1319, -895, +-547, 2068, -1409, 1269, 459, -1835, 1336, -1475, +-422, 1463, -1314, 1728, 190, -1202, 1183, -1801, +-42, 892, -1086, 1852, -351, -699, 953, -1718, +551, 541, -877, 1474, -913, -393, 776, -1191, +1029, 330, -779, 792, -1148, -173, 581, -518, +1112, 126, -512, 164, -1029, 42, 163, 21, +899, -129, -19, -227, -780, 263, -256, 319, +542, -381, 317, -338, -340, 444, -444, 340, +-68, -519, 411, -250, 367, 498, -438, 208, +-798, -500, 307, -150, 1063, 454, -213, 124, +-1416, -418, -50, -101, 1563, 348, 276, 101, +-1793, -258, -627, -77, 1779, 124, 869, 77, +-1806, 19, -1237, -72, 1653, -118, 1410, 9, +-1497, 243, -1736, 20, 1247, -226, 1768, -189, +-990, 240, -1913, 374, 631, -200, 1805, -600, +-349, 116, -1761, 922, -76, -153, 1584, -1100, +294, 66, -1435, 1350, -627, -89, 1126, -1450, +779, 52, -909, 1493, -1042, 56, 541, -1547, +1191, -123, -371, 1408, -1403, 358, 137, -1312, +1386, -516, -80, 1039, -1425, 742, -88, -731, +1244, -912, 161, 347, -1180, 1036, -431, 83, +1057, -1115, 486, -535, -1018, 1120, -713, 1000, +920, -1074, 716, -1425, -904, 893, -837, 1867, +651, -701, 964, -2146, -654, 311, -1106, 2426, +378, 47, 1284, -2498, -412, -520, -1455, 2481, +241, 1014, 1438, -2342, -152, -1459, -1561, 2009, +-29, 1960, 1407, -1663, 192, -2276, -1445, 1138, +-444, 2551, 1309, -623, 511, -2605, -1259, 67, +-707, 2478, 1074, 528, 660, -2224, -966, -1057, +-693, 1796, 678, 1564, 611, -1354, -612, -1904, +-490, 815, 278, 2129, 300, -321, -173, -2095, +-163, -234, -110, 1948, -109, 696, 293, -1601, +95, -1151, -429, 1208, -332, 1464, 520, -796, +240, -1604, -516, 354, -428, 1635, 420, -20, +414, -1431, -456, -336, -502, 1178, 305, 579, +495, -821, -441, -755, -410, 409, 278, 846, +238, -25, -300, -798, -109, -369, 59, 692, +-106, 662, 59, -474, 71, -873, -248, 244, +-167, 935, 261, 32, 85, -935, -333, -246, +-169, 803, 204, 498, 185, -682, -277, -651, +-324, 508, 201, 753, 312, -293, -264, -806, +-474, 148, 225, 700, 368, 138, -194, -672, +-517, -285, 102, 505, 438, 538, -102, -434, +-507, -695, -55, 347, 418, 825, 9, -257, +-313, -909, -270, 193, 164, 893, 294, -92, +-34, -841, -581, -31, -113, 790, 615, 122, +148, -706, -751, -273, -291, 683, 675, 376, +281, -663, -651, -473, -436, 584, 487, 639, +378, -562, -366, -722, -482, 369, 104, 953, +380, -253, 97, -1130, -444, 38, -418, 1375, +345, 149, 591, -1602, -413, -283, -841, 1719, +292, 484, 919, -1811, -319, -627, -1065, 1743, +141, 871, 1041, -1643, -92, -1075, -1128, 1448, +-136, 1297, 1034, -1187, 269, -1467, -1139, 903, +-497, 1536, 1085, -508, 565, -1609, -1185, 126, +-688, 1547, 1131, 398, 585, -1562, -1108, -862, +-626, 1473, 915, 1376, 469, -1366, -731, -1849, +-539, 1234, 425, 2196, 469, -955, -233, -2569, +-583, 753, -43, 2704, 523, -385, 183, -2854, +-609, 118, -419, 2791, 507, 225, 512, -2677, +-509, -525, -698, 2447, 347, 770, 678, -2139, +-207, -990, -828, 1829, -45, 1102, 764, -1467, +244, -1216, -876, 1148, -492, 1237, 753, -777, +594, -1284, -727, 500, -766, 1227, 456, -183, +795, -1215, -265, -9, -924, 1117, -96, 189, +914, -1041, 269, -296, -951, 986, -548, 328, +760, -892, 665, -386, -612, 899, -890, 343, +220, -825, 1045, -365, -11, 801, -1231, 365, +-379, -746, 1313, -392, 521, 645, -1346, 495, +-820, -589, 1190, -555, 931, 459, -1063, 720, +-1149, -408, 742, -814, 1229, 277, -570, 971, +-1343, -196, 237, -1033, 1264, 49, -76, 1094, +-1190, 92, -227, -1078, 926, -240, 361, 953, +-694, 447, -626, -854, 378, -556, 648, 594, +-108, 751, -807, -446, -183, -770, 688, 209, +387, 763, -674, -25, -655, -655, 491, -109, +729, 398, -358, 300, -902, -210, 155, -342, +800, -96, 28, 413, -792, 296, -294, -364, +589, -504, 458, 234, -478, 716, -717, -69, +250, -844, 775, -218, -91, 1013, -918, 471, +-171, -1050, 846, -796, 363, 1068, -849, 1058, +-643, -954, 659, -1336, 821, 804, -537, 1506, +-1067, -546, 258, -1634, 1184, 253, -84, 1668, +-1367, 80, -190, -1586, 1371, -461, 333, 1483, +-1422, 749, -547, -1203, 1261, -1077, 636, 958, +-1168, 1236, -781, -560, 885, -1390, 839, 175, +-755, 1439, -893, 212, 455, -1396, 850, -603, +-334, 1335, -789, 845, 62, -1114, 614, -1096, +93, 903, -541, 1174, -310, -537, 320, -1257, +449, 205, -335, 1220, -509, 172, 158, -1155, +502, -519, -181, 1019, -439, 793, 18, -777, +304, -1086, 13, 568, -262, 1233, -106, -228, +98, -1417, 105, -29, -119, 1467, -63, 341, +-44, -1495, -22, -640, 62, 1491, 91, 850, +-234, -1388, -168, -1101, 272, 1357, 115, 1203, +-362, -1214, -122, -1328, 321, 1123, 12, 1366, +-323, -970, -25, -1384, 248, 797, -76, 1418, +-234, -659, 57, -1398, 189, 492, -202, 1437, +-163, -432, 193, -1402, 140, 340, -377, 1418, +-87, -324, 351, -1335, -5, 240, -449, 1293, +72, -198, 406, -1145, -255, 99, -349, 963, +240, -28, 329, -742, -412, 36, -265, 421, +309, -28, 289, -216, -370, 226, -343, -84, +270, -341, 327, 161, -203, 621, -428, -247, +85, -819, 351, 168, 74, 1014, -410, -13, +-247, -1214, 343, -159, 368, 1290, -361, 443, +-526, -1400, 296, -672, 536, 1411, -245, 968, +-598, -1421, 84, -1244, 558, 1357, 58, 1544, +-598, -1217, -266, -1838, 544, 959, 412, 2139, +-590, -615, -514, -2345, 429, 153, 590, 2495, +-360, 314, -610, -2483, 108, -796, 606, 2345, +20, 1232, -600, -2090, -179, -1548, 440, 1663, +316, 1849, -382, -1238, -394, -1972, 117, 674, +519, 2121, -70, -182, -554, -2115, -106, -355, +573, 2069, 93, 831, -533, -1953, -140, -1208, +390, 1692, 100, 1592, -280, -1468, -69, -1778, +58, 1036, 30, 2019, 33, -696, 27, -2067, +-241, 235, -37, 2079, 261, 181, 95, -1978, +-412, -555, -101, 1708, 377, 928, 178, -1432, +-453, -1147, -271, 1003, 412, 1357, 373, -638, +-434, -1427, -548, 278, 446, 1427, 567, 8, +-383, -1380, -686, -193, 371, 1231, 581, 341, +-232, -1078, -625, -417, 121, 887, 552, 501, +-17, -677, -572, -563, -123, 437, 571, 663, +162, -235, -495, -711, -337, -31, 433, 811, +380, 187, -268, -790, -537, -375, 95, 800, +556, 485, 113, -790, -620, -539, -315, 712, +598, 699, 450, -765, -625, -732, -574, 654, +629, 963, 542, -656, -600, -1044, -591, 474, +568, 1188, 492, -285, -412, -1207, -586, 8, +309, 1127, 551, 306, -108, -1002, -673, -538, +-31, 741, 691, 750, 123, -505, -683, -807, +-282, 201, 673, 820, 326, 17, -574, -712, +-514, -260, 576, 590, 512, 440, -488, -429, +-587, -616, 430, 265, 508, 751, -297, -81, +-479, -864, 118, -102, 395, 927, 34, 313, +-368, -931, -171, -485, 280, 832, 244, 663, +-202, -666, -309, -803, 77, 440, 335, 896, +59, -185, -428, -948, -147, -56, 420, 943, +261, 271, -465, -906, -288, -458, 346, 861, +370, 562, -238, -760, -457, -652, 58, 702, +504, 666, 114, -616, -579, -651, -223, 544, +484, 670, 294, -510, -382, -616, -322, 379, +188, 703, 308, -326, -5, -732, -325, 142, +-94, 844, 254, 19, 172, -912, -247, -209, +-191, 932, 184, 417, 185, -931, -160, -534, +-197, 830, 129, 617, 160, -710, -79, -627, +-139, 539, 20, 589, 49, -335, 43, -561, +42, 129, -118, 526, -124, 78, 112, -511, +203, -292, -118, 516, -181, 450, 8, -479, +147, -618, 97, 424, -70, 715, -235, -314, +8, -793, 361, 195, -15, 798, -434, -65, +-41, -749, 550, -13, 5, 649, -614, 93, +-89, -548, 745, -142, 143, 449, -832, 197, +-272, -377, 889, -271, 424, 340, -921, 328, +-552, -282, 868, -421, 695, 254, -847, 448, +-743, -147, 716, -486, 802, 63, -605, 440, +-796, 69, 401, -413, 837, -151, -242, 322, +-822, 241, 25, -233, 846, -330, 96, 154, +-788, 380, -230, -24, 698, -492, 307, -23, +-564, 473, -373, 192, 366, -538, 484, -256, +-255, 456, -514, 412, 42, -411, 627, -510, +54, 320, -608, 547, -242, -171, 587, -588, +380, 98, -543, 480, -493, 95, 408, -399, +593, -208, -328, 224, -558, 360, 115, -59, +578, -489, 13, -76, -539, 532, -166, 246, +562, -587, 233, -352, -586, 557, -265, 457, +613, -501, 281, -546, -623, 425, -319, 572, +596, -262, 404, -617, -601, 131, -463, 592, +534, 39, 572, -569, -527, -187, -556, 512, +387, 311, 592, -407, -326, -414, -552, 290, +183, 475, 557, -115, -87, -506, -611, -85, +67, 495, 635, 263, -21, -436, -715, -429, +23, 366, 692, 527, 60, -249, -676, -606, +-161, 143, 610, 616, 305, -59, -536, -594, +-424, -42, 450, 583, 487, 83, -363, -515, +-516, -188, 273, 537, 489, 218, -186, -502, +-473, -316, 134, 548, 385, 360, -38, -575, +-350, -417, -20, 605, 248, 497, 117, -669, +-191, -538, -190, 660, 122, 679, 197, -692, +-19, -789, -225, 624, -5, 964, 130, -543, +113, -1111, -125, 374, -140, 1263, 65, -158, +203, -1381, -46, -123, -274, 1478, 63, 403, +296, -1485, -62, -696, -354, 1438, 101, 949, +342, -1318, -90, -1152, -355, 1124, 75, 1341, +343, -948, -28, -1429, -358, 686, -13, 1532, +351, -483, 111, -1528, -424, 215, -130, 1483, +408, 53, 219, -1383, -447, -330, -230, 1201, +389, 634, 272, -1025, -322, -857, -349, 785, +281, 1043, 360, -558, -168, -1145, -444, 322, +136, 1165, 402, -111, -11, -1124, -404, -47, +-100, 1015, 379, 144, 194, -895, -319, -179, +-290, 762, 272, 185, 257, -664, -136, -167, +-222, 558, 21, 183, 121, -515, 121, -210, +-21, 447, -241, 258, -48, -381, 281, -322, +162, 284, -348, 368, -227, -138, 351, -448, +353, -4, -412, 487, -435, 151, 457, -541, +528, -259, -510, 541, -600, 352, 567, -552, +630, -407, -564, 490, -665, 471, 565, -446, +668, -503, -503, 330, -695, 544, 447, -229, +694, -558, -319, 83, -730, 517, 215, 85, +745, -487, -47, -244, -816, 374, -64, 429, +850, -299, 194, -562, -884, 162, -287, 680, +866, -59, 375, -758, -739, -81, -511, 803, +632, 163, 581, -809, -399, -274, -696, 809, +236, 322, 687, -763, 10, -422, -661, 709, +-186, 488, 575, -639, 324, -573, -418, 503, +-418, 673, 312, -424, 413, -727, -136, 253, +-397, 797, 3, -128, 350, -794, 144, -59, +-297, 757, -296, 224, 294, -679, 414, -392, +-232, 543, -540, 498, 224, -407, 611, -581, +-116, 246, -652, 579, 17, -99, 667, -569, +105, -39, -606, 508, -207, 153, 527, -443, +278, -316, -355, 379, -321, 431, 226, -289, +295, -605, -46, 200, -238, 699, -18, -91, +130, -821, 121, -50, -15, 853, -119, 170, +-95, -840, 153, -333, 183, 766, -149, 435, +-193, -655, 134, -553, 243, 528, -119, 572, +-214, -383, 57, -613, 297, 236, 4, 561, +-290, -106, -100, -536, 384, -54, 185, 477, +-379, 157, -240, -399, 395, -338, 315, 309, +-328, 424, -310, -158, 255, -584, 351, -8, +-159, 641, -298, 221, 73, -717, 293, -470, +29, 713, -183, 675, -115, -664, 143, -939, +226, 563, -37, 1089, -256, -377, -31, -1278, +309, 153, 144, 1315, -216, 126, -265, -1340, +185, -429, 401, 1231, -47, 719, -493, -1115, +3, -1001, 614, 906, 81, 1173, -593, -698, +-130, -1324, 659, 450, 158, 1334, -548, -189, +-196, -1338, 559, -94, 239, 1191, -431, 370, +-232, -1062, 386, -653, 302, 804, -274, 864, +-236, -553, 181, -1072, 301, 216, -71, 1167, +-215, 118, -5, -1269, 245, -469, 124, 1227, +-140, 761, -181, -1182, 124, -1014, 308, 1015, +-16, 1167, -345, -871, 27, -1286, 457, 642, +44, 1291, -463, -456, 14, -1291, 557, 211, +3, 1198, -522, -13, 57, -1127, 618, -216, +-39, 963, -543, 392, 28, -859, 639, -557, +72, 670, -561, 649, -135, -572, 617, -713, +310, 397, -510, 694, -356, -308, 460, -691, +552, 180, -297, 609, -565, -111, 199, -601, +719, 30, -13, 505, -665, 7, -60, -484, +676, -61, 276, 377, -522, 75, -349, -327, +441, -142, 590, 192, -217, 138, -633, -115, +123, -213, 767, -16, 144, 196, -691, 82, +-247, -239, 642, -178, 555, 180, -434, 209, +-649, -184, 300, -261, 872, 103, -53, 259, +-842, -76, -51, -288, 864, -24, 290, 276, +-670, 63, -338, -317, 581, -170, 534, 288, +-346, 230, -530, -299, 294, -343, 633, 200, +-64, 401, -540, -155, 41, -507, 577, -31, +202, 531, -409, 152, -277, -564, 430, -396, +477, 524, -196, 537, -532, -454, 223, -775, +634, 306, 6, 880, -537, -168, 13, -1008, +541, -54, 157, 1006, -301, 200, -118, -1000, +296, -448, 224, 900, -56, 569, -151, -800, +102, -782, 253, 644, 39, 849, -159, -502, +76, -1002, 272, 341, -6, 994, -144, -219, +126, -1054, 222, 98, -17, 981, -93, -40, +101, -955, 177, -61, 59, 854, -80, 47, +40, -788, 230, -157, 71, 711, -157, 117, +90, -674, 322, -213, -43, 638, -219, 171, +220, -659, 359, -236, -139, 621, -258, 225, +264, -639, 385, -293, -95, 536, -299, 323, +193, -509, 419, -409, -10, 341, -299, 451, +102, -265, 423, -539, 54, 60, -278, 559, +46, 39, 434, -612, 59, -254, -279, 576, +57, 386, 434, -583, 41, -588, -260, 447, +59, 729, 393, -371, 111, -884, -244, 106, +-31, 963, 393, 72, 243, -1018, -293, -391, +-137, 947, 424, 603, 352, -863, -306, -861, +-239, 633, 387, 1001, 487, -477, -220, -1120, +-381, 174, 297, 1125, 595, -20, -99, -1114, +-448, -247, 180, 1022, 554, 357, 69, -967, +-337, -567, -1, 838, 374, 658, 293, -805, +-140, -819, -215, 655, 183, 882, 470, -618, +31, -954, -340, 431, 29, 942, 535, -382, +190, -935, -360, 205, -95, 841, 469, -159, +301, -812, -216, 40, -174, 702, 233, -25, +381, -719, 78, -62, -227, 646, -83, 73, +412, -703, 371, -185, -205, 639, -326, 254, +329, -669, 553, -418, -75, 541, -432, 527, +156, -477, 604, -692, 92, 262, -399, 749, +-10, -127, 536, -852, 241, -105, -279, 788, +-170, 254, 410, -797, 408, -441, -174, 627, +-295, 540, 295, -555, 497, -676, -63, 351, +-288, 700, 117, -234, 453, -792, 148, 40, +-220, 728, -95, 86, 388, -745, 325, -254, +-178, 575, -165, 334, 315, -479, 343, -441, +-103, 228, -143, 415, 224, -57, 348, -424, +-30, -205, -186, 274, 193, 360, 386, -185, +-26, -531, -211, -42, 199, 574, 376, 155, +-5, -621, -153, -370, 132, 548, 322, 408, +80, -500, -110, -528, 45, 368, 278, 513, +157, -304, -82, -591, 15, 140, 236, 583, +211, -94, -57, -652, -37, -84, 194, 649, +277, 138, 11, -689, -112, -309, 89, 623, +303, 359, 213, -581, -132, -493, -148, 404, +273, 514, 481, -298, -64, -594, -353, 67, +155, 563, 572, 41, 163, -604, -374, -245, +-123, 540, 502, 329, 496, -563, -307, -499, +-415, 477, 432, 578, 703, -478, -226, -739, +-533, 346, 334, 820, 711, -297, -38, -971, +-509, 114, 113, 983, 639, 1, 210, -1052, +-407, -201, -119, 929, 507, 321, 395, -902, +-210, -472, -278, 710, 260, 527, 489, -638, +67, -618, -299, 474, -28, 582, 445, -421, +328, -644, -165, 311, -284, 583, 262, -276, +538, -650, 39, 165, -404, 604, 24, -111, +590, -685, 251, -19, -345, 647, -209, 74, +491, -720, 474, -197, -231, 659, -399, 226, +358, -672, 616, -319, -121, 555, -427, 319, +197, -495, 607, -440, 50, 331, -339, 444, +-19, -196, 485, -596, 282, -23, -223, 604, +-202, 212, 318, -694, 430, -489, -61, 635, +-256, 676, 109, -601, 443, -945, 156, 432, +-220, 1055, -103, -277, 354, -1216, 336, 12, +-84, 1196, -211, 198, 135, -1209, 396, -495, +183, 1071, -236, 687, -158, -977, 408, -947, +442, 780, -224, 1061, -370, -639, 356, -1227, +586, 428, -114, 1233, -469, -287, 192, -1294, +661, 75, 95, 1213, -547, 59, -52, -1182, +752, -278, 344, 1029, -617, 388, -310, -924, +796, -574, 558, 738, -584, 622, -511, -618, +700, -731, 726, 433, -422, 685, -658, -323, +478, -684, 857, 149, -190, 550, -721, -74, +196, -475, 896, -70, 71, 319, -680, 96, +-95, -244, 809, -188, 357, 116, -541, 156, +-375, -65, 610, -198, 633, -49, -328, 127, +-572, 94, 324, -130, 778, -224, -38, 48, +-593, 256, -9, -17, 719, -395, 282, -79, +-453, 399, -280, 128, 504, -497, 485, -238, +-189, 450, -396, 291, 182, -465, 552, -417, +104, 375, -395, 451, -89, -322, 522, -571, +294, 197, -299, 565, -239, -102, 386, -648, +396, -43, -117, 581, -316, 152, 171, -599, +457, -292, 65, 491, -330, 374, 7, -468, +447, -489, 151, 358, -249, 497, -43, -315, +330, -581, 155, 235, -101, 521, -26, -201, +169, -587, 140, 153, 20, 535, -29, -124, +64, -605, 180, 40, 77, 596, -97, 14, +37, -660, 267, -191, 105, 653, -174, 285, +-23, -656, 311, -502, 213, 589, -191, 607, +-201, -504, 309, -793, 415, 354, -166, 854, +-388, -216, 267, -964, 547, 14, -86, 945, +-432, 125, 122, -940, 558, -336, 82, 825, +-410, 439, -69, -695, 540, -618, 241, 490, +-387, 667, -186, -292, 473, -772, 350, 45, +-302, 735, -274, 149, 330, -717, 444, -386, +-149, 572, -337, 524, 155, -437, 447, -710, +43, 216, -294, 785, -46, -32, 316, -896, +256, -195, -129, 897, -249, 354, 134, -920, +413, -551, 70, 815, -353, 660, -53, -725, +425, -798, 265, 513, -307, 846, -247, -319, +332, -919, 407, 68, -147, 890, -354, 139, +150, -893, 439, -366, 95, 796, -349, 529, +-101, -719, 404, -728, 348, 552, -281, 840, +-333, -400, 332, -981, 498, 181, -155, 1000, +-440, 18, 182, -1021, 521, -254, 27, 923, +-403, 432, -13, -829, 425, -641, 206, 639, +-222, 751, -204, -477, 191, -880, 352, 253, +45, 889, -301, -80, -81, -910, 348, -134, +276, 828, -189, 283, -302, -756, 139, -452, +453, 612, 75, 533, -435, -497, -139, -616, +530, 329, 319, 608, -434, -205, -350, -603, +451, 59, 516, 520, -294, 24, -519, -467, +290, -123, 672, 366, -138, 155, -582, -328, +123, -224, 667, 260, 37, 240, -513, -227, +-54, -300, 550, 164, 200, 289, -380, -103, +-144, -317, 377, -1, 241, 272, -226, 98, +-113, -264, 205, -220, 188, 196, -91, 299, +-55, -164, 117, -425, 112, 97, -65, 488, +-14, -26, 150, -609, 39, -68, -100, 645, +26, 164, 166, -710, 17, -280, -82, 690, +-31, 376, 129, -675, 141, -501, -58, 610, +-170, 571, 118, -558, 284, -689, -54, 471, +-274, 750, 90, -369, 361, -841, 15, 207, +-298, 853, -19, -19, 378, -865, 153, -215, +-289, 788, -157, 424, 358, -686, 274, -628, +-219, 499, -238, 743, 242, -295, 324, -833, +-82, 53, -216, 805, 80, 162, 240, -769, +46, -350, -89, 665, -45, 487, 88, -575, +130, -612, 47, 454, -108, 692, -39, -339, +166, -785, 97, 184, -104, 800, -56, -5, +119, -803, 63, -215, -30, 686, -35, 421, +46, -516, 51, -615, -16, 262, -6, 703, +78, 20, -7, -735, -76, -307, 116, 643, +114, 565, -122, -533, -73, -775, 228, 356, +102, 908, -173, -198, -62, -990, 243, 21, +137, 986, -158, 138, -104, -955, 215, -293, +203, 842, -118, 420, -130, -727, 117, -502, +222, 545, 4, 549, -141, -381, -22, -542, +211, 183, 109, 489, -120, -8, -78, -424, +128, -158, 136, 296, -45, 287, -94, -181, +19, -362, 137, 6, 16, 397, -81, 121, +-39, -376, 99, -279, 62, 310, -48, 373, +-92, -212, 40, -462, 130, 86, 4, 506, +-141, 21, -33, -518, 187, -153, 97, 500, +-134, 215, -152, -424, 149, -298, 232, 342, +-20, 297, -244, -216, 9, -334, 294, 89, +148, 318, -223, 44, -165, -288, 229, -180, +279, 225, -69, 253, -257, -81, 57, -354, +300, -47, 112, 336, -233, 214, -94, -330, +212, -301, 191, 234, -124, 339, -137, -141, +80, -305, 155, 43, 3, 190, -109, 52, +-50, -86, 100, -85, 125, -75, -131, 112, +-137, 179, 142, -59, 134, -311, -198, -5, +-81, 392, 165, 124, 45, -485, -135, -263, +-28, 537, 75, 405, 35, -545, -21, -550, +-62, 513, 28, 641, 92, -393, -8, -731, +-77, 254, 76, 734, 91, -62, -40, -729, +-34, -88, 83, 637, 92, 219, 5, -528, +-74, -308, 26, 385, 184, 340, 44, -223, +-164, -387, 7, 89, 211, 372, 26, 83, +-114, -387, -6, -213, 84, 312, 72, 351, +-2, -208, -136, -452, -12, 55, 186, 493, +14, 170, -226, -512, -44, -368, 210, 423, +89, 570, -217, -336, -197, -704, 194, 175, +230, 773, -180, 8, -290, -794, 77, -194, +256, 735, 69, 399, -263, -662, -267, -563, +256, 521, 423, 713, -240, -360, -511, -804, +220, 162, 534, 845, -80, 32, -467, -833, +-52, -215, 460, 765, 271, 370, -395, -659, +-361, -485, 430, 488, 455, 585, -344, -308, +-404, -627, 292, 63, 401, 675, -130, 141, +-362, -628, 13, -372, 375, 565, 120, 536, +-384, -427, -208, -647, 343, 233, 273, 715, +-295, -58, -376, -660, 151, -173, 448, 597, +-68, 285, -603, -410, -65, -398, 631, 250, +105, 395, -692, -78, -219, -351, 594, -62, +283, 296, -533, 120, -426, -198, 415, -205, +514, 158, -336, 209, -624, -60, 270, -252, +671, -13, -191, 231, -671, 128, 154, -206, +654, -240, -45, 135, -571, 310, -17, -27, +534, -340, 122, -70, -425, 293, -177, 184, +366, -230, 247, -235, -225, 126, -297, 288, +129, -75, 328, -273, 0, 0, -362, 272, +-111, 27, 347, -243, 157, -75, -356, 209, +-224, 123, 271, -180, 163, -134, -231, 92, +-220, 173, 90, -15, 147, -130, -32, -146, +-240, 103, -96, 275, 224, -28, 108, -400, +-327, -68, -176, 480, 325, 148, 129, -462, +-330, -273, -162, 426, 256, 343, 139, -306, +-156, -405, -191, 195, 61, 426, 223, -91, +60, -419, -236, -34, -123, 417, 234, 133, +215, -390, -178, -249, -264, 366, 135, 339, +322, -300, -52, -415, -386, 206, 12, 461, +408, -77, 27, -487, -474, -29, -46, 482, +433, 106, 33, -453, -453, -152, -80, 414, +336, 151, 50, -320, -296, -175, -175, 236, +161, 164, 148, -109, -128, -201, -278, 20, +24, 206, 196, 75, -35, -207, -251, -143, +-47, 231, 148, 146, 37, -233, -148, -159, +-126, 306, 79, 107, 119, -318, -71, -99, +-185, 350, 75, 70, 179, -328, -79, -69, +-210, 275, 104, 109, 203, -242, -92, -127, +-210, 177, 108, 190, 203, -164, -116, -208, +-162, 101, 77, 277, 108, -40, -46, -324, +-49, -61, -78, 391, 6, 150, 86, -420, +-34, -199, -170, 406, 4, 233, 96, -344, +-51, -228, -121, 214, -62, 226, 48, -117, +29, -170, -112, 24, -181, 149, 90, -37, +137, -94, -162, 59, -241, 73, 68, -111, +161, -72, -41, 129, -185, 135, -122, -77, +79, -260, 160, -4, -46, 346, -261, 178, +-68, -384, 225, -312, 179, 317, -233, 460, +-308, -225, 173, -575, 403, 88, -148, 668, +-431, 91, 69, -718, 349, -275, 50, 672, +-278, 512, -214, -567, 135, -739, 323, 397, +-99, 970, -367, -152, -56, -1124, 253, -146, +154, 1141, -200, 475, -376, -1029, 41, -771, +458, 818, -87, 1043, -580, -534, -64, -1227, +488, 208, 77, 1269, -487, 181, -336, -1169, +357, -557, 400, 965, -386, 876, -567, -652, +226, -1125, 532, 270, -131, 1230, -587, 179, +-164, -1133, 524, -639, 311, 882, -514, 1027, +-536, -475, 377, -1312, 582, 48, -210, 1405, +-675, 422, -33, -1286, 668, -884, 150, 1002, +-616, 1208, -273, -550, 433, -1386, 254, 123, +-253, 1362, -334, 335, 56, -1193, 279, -711, +-8, 896, -321, 1011, -50, -487, 183, -1154, +-47, 87, -172, 1108, -13, 331, 50, -918, +-57, -683, -130, 577, -88, 982, 126, -125, +5, -1113, -270, -346, -136, 1033, 235, 742, +55, -738, -320, -974, -211, 343, 198, 1048, +248, 99, -262, -974, -439, -492, 178, 730, +452, 808, -254, -335, -548, -975, 140, -73, +469, 983, -102, 504, -493, -875, -105, -830, +419, 671, 167, 1063, -449, -358, -294, -1088, +348, 20, 245, 925, -257, 272, -271, -651, +-2, -421, 201, 346, 94, 478, -243, -46, +-272, -375, 126, -248, 217, 217, -83, 441, +-309, 29, -123, -531, 203, -221, 89, 514, +-279, 368, -146, -370, 102, -480, -31, 198, +-110, 503, -37, 44, -84, -413, -55, -199, +8, 222, -141, 249, -22, 35, 75, -195, +-157, -245, -181, 92, 82, 394, 45, 72, +-116, -449, -74, -251, -69, 370, -36, 485, +-6, -177, 1, -620, -54, -114, -120, 622, +-64, 494, 117, -485, -3, -800, -272, 195, +-78, 1007, 189, 195, 44, -951, -224, -587, +-179, 697, 71, 887, 113, -290, -133, -1002, +-207, -163, 30, 994, 134, 591, -170, -783, +-273, -946, 89, 438, 199, 1168, -223, 32, +-372, -1173, 82, -501, 299, 1013, -114, 906, +-482, -625, -153, -1175, 350, 99, 168, 1268, +-426, 500, -368, -1028, 162, -1023, 252, 592, +-90, 1326, -380, -8, -224, -1357, 253, -568, +235, 1219, -354, 1097, -353, -836, 125, -1528, +151, 323, -43, 1778, -153, 298, -299, -1717, +-11, -894, 313, 1420, -44, 1397, -398, -876, +-185, -1734, 153, 217, 254, 1859, -129, 502, +-549, -1612, -85, -1170, 504, 1146, 60, 1626, +-578, -469, -328, -1840, 314, -234, 405, 1810, +-299, 915, -729, -1466, 31, -1485, 686, 913, +-32, 1777, -774, -148, -337, -1771, 487, -533, +487, 1484, -485, 1083, -908, -1013, 171, -1400, +922, 516, -149, 1551, -1097, 8, -244, -1533, +863, -412, 369, 1404, -864, 822, -768, -1223, +491, -1158, 834, 1005, -377, 1478, -1080, -608, +-92, -1712, 933, 97, 308, 1767, -937, 551, +-791, -1575, 567, -1173, 909, 1222, -408, 1596, +-1194, -611, -38, -1770, 1008, -44, 206, 1649, +-965, 671, -614, -1235, 574, -1076, 574, 687, +-458, 1138, -716, -54, 139, -876, 417, -335, +-226, 392, -471, 422, 130, 66, 282, -125, +-375, -264, -529, -274, 207, 98, 547, 505, +-274, 347, -848, -325, -140, -676, 709, -230, +210, 702, -709, 838, -613, -286, 365, -1046, +506, -374, -360, 805, -658, 907, 82, -234, +468, -1029, -206, -259, -600, 887, -83, 469, +498, -658, -1, -560, -614, 665, -262, 697, +322, -657, 146, -1073, -329, 520, -266, 1456, +44, -11, -6, -1529, -214, -645, -40, 1270, +83, 1029, -210, -721, -214, -1076, 32, 462, +-52, 888, -189, -393, -60, -973, 11, 402, +-109, 1351, -152, -66, -168, -1585, -7, -628, +28, 1513, -262, 1229, -231, -1029, 125, -1604, +191, 556, -161, 1871, -527, -71, -507, -2057, +363, -634, 756, 2055, -211, 1499, -1016, -1427, +-515, -2152, 529, 431, 713, 2333, -308, 413, +-1000, -1964, -157, -999, 729, 1586, 215, 1427, +-794, -1123, -679, -1775, 386, 456, 756, 1970, +-287, 246, -997, -1628, -157, -700, 715, 1147, +72, 843, -850, -848, -286, -965, 733, 725, +258, 1381, -1031, -336, -705, -1746, 790, -438, +830, 1650, -749, 1273, -1248, -991, 141, -1718, +1129, 209, 272, 1771, -1193, 527, -1011, -1525, +554, -1226, 1036, 1056, -80, 1800, -1100, -82, +-568, -1959, 520, -951, 519, 1418, -364, 1554, +-654, -400, -52, -1509, 407, -315, 149, 1044, +-654, 639, -589, -647, 293, -751, 645, 383, +-108, 1008, -884, 61, -553, -1149, 468, -772, +818, 904, -314, 1384, -1191, -130, -379, -1464, +911, -625, 655, 1058, -760, 951, -1053, -495, +75, -876, 859, 307, 90, 665, -901, -288, +-443, -668, 591, 302, 354, 881, -666, -170, +-656, -1015, 290, -163, 539, 1104, -151, 583, +-734, -933, -338, -1030, 517, 488, 376, 1419, +-720, 178, -745, -1362, 545, -858, 751, 904, +-459, 1229, -1232, -221, -193, -1119, 1223, -325, +556, 826, -1321, 531, -1146, -428, 809, -524, +1135, 111, -514, 445, -1394, 77, -64, -231, +1248, -3, 191, 95, -1426, -276, -780, -266, +1132, 553, 1068, 837, -954, -321, -1573, -1328, +131, -522, 1403, 1322, 298, 1449, -1214, -558, +-846, -1804, 625, -492, 734, 1420, -547, 1257, +-856, -568, 239, -1431, 717, -233, -285, 1165, +-956, 762, -191, -547, 791, -996, 443, -89, +-750, 865, -1028, 619, 109, -395, 1041, -808, +366, -131, -906, 654, -1069, 605, -50, -330, +1020, -880, 597, -17, -600, 1067, -960, 511, +-411, -1036, 352, -1199, 675, 633, 254, 1735, +-623, 353, -807, -1631, -234, -1405, 490, 707, +547, 1844, -102, 666, -697, -1266, -544, -1534, +231, -2, 413, 1457, -89, 1077, -419, -562, +20, -1360, 145, -313, -365, 992, -488, 684, +70, -501, 593, -739, 218, 399, -533, 882, +-774, -292, -222, -1208, 351, -156, 526, 1282, +307, 878, -441, -677, -1048, -1258, -488, -136, +696, 913, 931, 586, -29, -177, -1137, -376, +-748, -212, 643, -118, 820, 214, -405, 386, +-1024, 64, -67, -453, 960, -358, 439, 485, +-1050, 749, -1092, -197, 417, -1112, 1184, -485, +101, 1004, -1152, 1266, -617, -171, 696, -1435, +630, -765, -785, 754, -928, 1157, 560, 205, +1203, -732, -341, -668, -1665, -24, -414, 555, +1355, 571, 957, -10, -1063, -847, -1399, -606, +313, 824, 1367, 1249, 113, -281, -1340, -1637, +-782, -674, 737, 1436, 981, 1528, -191, -516, +-902, -1809, -514, -421, 313, 1449, 420, 1019, +-45, -939, -325, -1298, -21, 651, 196, 1523, +-200, -169, -606, -1776, -269, -580, 716, 1609, +793, 1370, -393, -786, -1289, -1610, -622, -112, +898, 1109, 1209, 526, -253, -399, -1399, -294, +-547, 265, 919, -145, 750, -615, -594, 171, +-996, 1014, 183, 272, 1010, -1008, 114, -626, +-1252, 569, -871, 741, 901, -150, 1410, -600, +-151, 31, -1775, 477, -1073, 28, 977, -522, +1772, -166, 237, 580, -1708, 564, -1531, -400, +423, -1030, 1726, -90, 823, 1200, -939, 930, +-1624, -697, -516, -1620, 1101, -491, 1366, 1480, +14, 1909, -1415, -212, -1277, -2485, 389, -1688, +1701, 1641, 697, 3099, -1283, 336, -1634, -3094, +39, -2362, 1661, 1737, 1059, 3499, -1083, 296, +-1824, -3357, -28, -2122, 1639, 2098, 849, 3247, +-1047, -191, -1421, -3188, 194, -1694, 1262, 1918, +365, 2820, -1047, 14, -799, -2513, 544, -1812, +865, 1223, -220, 2555, -985, 416, -254, -2155, +687, -1586, 539, 1182, -454, 1878, -699, -16, +-18, -1605, 452, -690, 59, 943, -307, 898, +65, -256, 232, -737, -324, -13, -628, 451, +52, -27, 875, -422, 444, 78, -869, 730, +-1059, 220, 315, -779, 1128, -881, 175, 275, +-952, 1275, -564, 680, 601, -770, 596, -1393, +-513, -316, -671, 1109, 369, 1250, 615, -67, +-227, -1190, -736, -820, -123, 248, 700, 884, +382, 623, -694, -57, -800, -653, 377, -781, +898, -175, 35, 893, -813, 1236, -589, -77, +280, -1722, 619, -1175, 179, 1217, -317, 2212, +-451, 42, -404, -2324, 157, -1360, 712, 1440, +421, 2011, -646, -147, -1139, -1604, -130, -745, +1231, 702, 1152, 753, -750, 59, -1863, -257, +-604, -246, 1643, -147, 1792, 108, -540, 301, +-2301, 8, -1040, -336, 1631, -94, 2036, 479, +-260, 325, -2225, -513, -1187, -709, 1339, 197, +2028, 990, 0, 485, -2099, -763, -1367, -1261, +1148, -35, 2136, 1527, 142, 1275, -2048, -887, +-1465, -2224, 1086, -591, 2099, 2114, 54, 2178, +-2060, -729, -1207, -2707, 1332, -1174, 1841, 1713, +-296, 2321, -1984, 81, -924, -1964, 1341, -1440, +1543, 709, -312, 1652, -1504, 431, -602, -1167, +699, -838, 789, 694, -26, 892, -490, -483, +-276, -1044, 20, 181, 128, 1345, 18, 495, +-39, -1299, 58, -1283, 137, 641, -208, 1643, +-321, 303, 3, -1237, 367, -932, 269, 426, +-248, 846, -568, 169, -165, -269, 536, -56, +489, -128, -118, -432, -627, -252, -503, 696, +237, 987, 635, -36, 424, -1374, -296, -979, +-797, 734, -554, 1504, 538, 404, 1031, -967, +76, -950, -959, -53, -770, 477, 370, 480, +946, 380, 254, 38, -848, -561, -726, -723, +350, -78, 833, 678, 171, 755, -759, 1, +-645, -573, 326, -620, 911, -129, 98, 469, +-973, 682, -653, 110, 669, -642, 1136, -515, +-105, 326, -1251, 622, -858, -183, 719, -742, +1436, 91, 332, 1028, -1119, 337, -1192, -1126, +-87, -1081, 976, 611, 1079, 1541, 146, 371, +-945, -1266, -1254, -995, -289, 455, 1181, 957, +1481, 36, -177, -583, -1695, 3, -967, 699, +914, 20, 1368, -1190, -70, -796, -1273, 1115, +-419, 1961, 981, 132, 721, -2115, -774, -1821, +-1221, 787, 75, 2189, 1533, 1045, 989, -896, +-1024, -1446, -1850, -602, -452, 186, 1370, 505, +1722, 852, 249, 1122, -1540, 9, -1698, -1952, +-271, -2229, 1457, 338, 1876, 3244, 356, 2578, +-1676, -1333, -1957, -3956, -341, -2007, 1615, 2122, +2069, 3706, 381, 1336, -1807, -2281, -2047, -3190, +-256, -796, 1674, 2149, 2082, 2541, 259, 401, +-2027, -1749, -2122, -1964, 332, -262, 2394, 1502, +1513, 1576, -1257, -74, -2212, -1448, -417, -963, +1571, 525, 1492, 1162, -238, 401, -1465, -772, +-1054, -973, 384, -85, 1348, 977, 1030, 1046, +-441, -37, -1768, -1266, -1026, -1393, 960, 19, +1795, 1723, 581, 2028, -1070, -40, -1435, -2591, +-395, -2618, 613, 494, 891, 3510, 807, 2712, +301, -1352, -983, -3931, -1959, -1976, -785, 2078, +1882, 3215, 2881, 906, 316, -1702, -2901, -1861, +-2786, -529, 397, 500, 3032, 863, 2396, 1002, +-649, 599, -2876, -685, -2190, -1687, 674, -955, +2805, 1013, 2078, 1995, -860, 636, -2867, -1500, +-1721, -1726, 1314, 240, 2630, 1748, 906, 667, +-1584, -1186, -1894, -1044, -85, 675, 1324, 1083, +835, -228, -407, -931, -479, -60, 131, 750, +1, 3, -615, -781, -199, 33, 806, 1163, +1013, 526, -226, -1267, -1433, -1434, -916, 248, +837, 1705, 1584, 1202, 399, -453, -1128, -1603, +-1353, -1251, 50, 235, 1182, 1555, 817, 1456, +-340, -87, -773, -1532, -305, -1353, 295, 66, +167, 1046, -184, 859, 279, 311, 805, 55, +-99, -520, -1401, -1413, -1008, -1209, 1038, 1043, +2152, 2864, 551, 1238, -2177, -2284, -2269, -3143, +728, -49, 2713, 2762, 1283, 1899, -1586, -941, +-2273, -1849, -160, -362, 1775, 901, 1128, 431, +-654, -443, -914, -345, 127, 632, 428, 726, +-386, -349, -683, -1230, 488, -508, 1502, 982, +434, 1305, -1645, -54, -1879, -1552, 281, -887, +2351, 1235, 1780, 1796, -1009, -494, -2649, -2459, +-1120, -841, 1483, 2211, 2106, 2317, 539, -765, +-1127, -2593, -1295, -933, -437, 1376, 296, 1326, +658, -189, 936, -362, 604, 459, -527, 1, +-1415, -1390, -1136, -1322, 427, 942, 1821, 2468, +1566, 1246, -370, -1384, -2005, -2428, -1671, -1210, +246, 706, 1906, 2048, 1682, 1892, 84, 293, +-1444, -1977, -1729, -2701, -643, -965, 1126, 1913, +1913, 3111, 1028, 1332, -825, -1663, -2000, -3060, +-1172, -1378, 806, 1322, 1842, 2221, 921, 1011, +-733, -320, -1227, -810, -368, -958, 529, -1055, +260, -408, -219, 1117, 201, 2169, 732, 1210, +325, -1162, -722, -2691, -1182, -1745, -468, 930, +889, 2767, 1531, 2002, 798, -559, -820, -2379, +-1804, -1926, -1032, 200, 827, 1571, 1801, 1249, +1038, 297, -367, -50, -1304, -490, -1232, -1319, +-381, -1524, 880, 188, 1739, 2437, 1272, 2433, +-683, -342, -2414, -2944, -1769, -2430, 1034, 404, +2846, 2490, 1597, 1990, -1336, 35, -2620, -1393, +-997, -1654, 1426, -934, 1896, 391, 337, 1623, +-1016, 1711, -787, 134, 114, -1678, 242, -1827, +-209, -230, -81, 1259, 755, 1351, 784, 517, +-335, -384, -1290, -914, -802, -1168, 670, -448, +1551, 1125, 664, 1817, -934, 348, -1422, -1637, +-255, -1540, 1169, 412, 1001, 1654, -381, 425, +-989, -1207, 35, -729, 824, 1007, 187, 1050, +-771, -691, -622, -1595, 571, -147, 1186, 1606, +316, 1207, -1031, -769, -1167, -1585, 48, -356, +1165, 1090, 1049, 986, -199, -334, -1129, -992, +-596, -209, 464, 822, 637, 573, -6, -550, +-235, -927, 212, 85, 439, 916, -244, 453, +-949, -405, -460, -474, 951, -114, 1361, -55, +4, -67, -1251, 338, -870, 747, 444, 219, +868, -852, 159, -1110, -375, -58, 9, 1044, +514, 1070, 87, 93, -948, -778, -945, -976, +501, -572, 1839, 313, 1135, 1310, -1113, 1225, +-2273, -293, -799, -1812, 1568, -1451, 2092, 659, +413, 2036, -1369, 982, -1423, -1121, -110, -1461, +767, -15, 633, 924, 333, 223, 211, -643, +-221, -23, -817, 1025, -663, 585, 248, -1174, +1071, -1585, 821, 219, -272, 1889, -1001, 1075, +-586, -1058, 239, -1440, 673, -27, 568, 981, +-7, 304, -457, -582, -419, -209, -119, 681, +249, 503, 576, -646, 389, -947, -369, -13, +-787, 836, -211, 560, 724, -212, 868, -406, +-29, 42, -945, 98, -656, -448, 383, -687, +834, 331, 490, 1607, -170, 1076, -568, -1277, +-577, -2523, -90, -606, 493, 2098, 818, 2225, +468, -94, -457, -1712, -1023, -1181, -510, -37, +507, 325, 978, 451, 561, 1106, -246, 1063, +-663, -579, -489, -2294, -251, -1692, 206, 1087, +955, 2873, 1018, 1599, -233, -1411, -1486, -2712, +-1138, -1112, 662, 1310, 1686, 1903, 720, 588, +-894, -719, -1009, -825, -127, -336, 400, -118, +331, -85, 307, 422, 201, 877, -269, 409, +-477, -737, -85, -1014, 536, -104, 363, 742, +-384, 411, -605, -345, 205, -258, 946, 472, +486, 591, -678, -415, -1186, -1196, -344, -636, +1018, 941, 1420, 1551, 352, 527, -1140, -1036, +-1479, -1302, -319, -506, 1295, 294, 1439, 843, +12, 1151, -1036, 707, -698, -879, 123, -1991, +340, -1060, 27, 1203, 94, 2127, 667, 735, +592, -1074, -676, -1381, -1494, -465, -425, 316, +1394, 446, 1674, 477, -65, 531, -1564, 288, +-1019, -551, 558, -1208, 1075, -750, 276, 661, +-424, 1527, -290, 700, 225, -702, 174, -1137, +-215, -368, -304, 263, 77, 322, 460, 282, +416, 368, -116, 209, -514, -304, -260, -575, +214, -462, 407, -137, 101, 446, -132, 966, +-79, 670, 109, -481, 86, -1353, -70, -886, +-221, 464, -127, 1351, 301, 874, 530, -284, +149, -1004, -413, -762, -569, -29, -158, 544, +457, 593, 676, 244, 232, -77, -387, -194, +-515, -322, -163, -531, 228, -341, 258, 486, +194, 1150, 334, 712, 109, -676, -518, -1601, +-770, -788, 13, 876, 937, 1522, 872, 578, +-149, -618, -972, -1057, -659, -671, 309, 140, +904, 828, 374, 811, -371, -11, -397, -704, +55, -443, 125, 150, -111, 33, 1, -262, +312, 282, 311, 961, -40, 325, -452, -1197, +-287, -1287, 204, 447, 496, 1595, 166, 527, +-179, -1097, -195, -928, 47, 425, 50, 905, +-105, -87, 42, -807, 325, -297, 210, 671, +-159, 706, -317, -136, -73, -805, 209, -518, +289, 305, 70, 667, -133, 291, -69, -272, +-8, -433, 85, -59, 54, 232, 3, 107, +-90, -208, 113, -192, 240, 191, 72, 544, +-246, 292, -248, -592, 81, -1012, 359, -176, +236, 1060, -76, 1128, -242, -93, -117, -1211, +116, -897, 158, 314, 110, 960, -19, 382, +-37, -334, 16, -251, 51, 128, 61, -79, +-23, -508, -123, -260, -66, 544, 263, 958, +368, 247, -6, -940, -306, -1147, -321, 41, +-33, 1145, 317, 734, 495, -384, 239, -717, +-189, -54, -573, 251, -509, -116, 277, -210, +902, 349, 559, 514, -314, -96, -756, -567, +-477, -308, 233, 180, 652, 307, 550, 130, +79, 18, -509, -71, -677, -141, -51, -149, +723, 26, 508, 92, -163, 52, -403, 18, +29, 82, 195, 47, -32, -153, -215, -174, +98, -61, 372, 114, 186, 150, 0, 145, +-236, -19, -372, -126, -140, -142, 434, -180, +639, -32, 184, 311, -415, 407, -622, -80, +-112, -469, 492, -194, 444, 219, 11, 133, +-73, -252, 74, 46, -78, 630, -413, 352, +-405, -769, 329, -1190, 1145, 32, 718, 1501, +-734, 1226, -1523, -791, -552, -1857, 1094, -409, +1573, 1458, 395, 1117, -987, -764, -1203, -1150, +-218, 410, 688, 1250, 869, -149, 259, -1637, +-234, -662, -306, 1493, -203, 1783, -171, -313, +-102, -2021, 310, -1193, 579, 895, 497, 1675, +-183, 520, -758, -826, -616, -898, 99, -199, +800, 258, 831, 216, 163, 284, -627, 346, +-783, 33, -213, -441, 338, -569, 616, -90, +563, 328, 241, 426, -400, 305, -896, 157, +-570, -363, 412, -921, 1197, -530, 824, 755, +-256, 1384, -1179, 398, -955, -1174, 298, -1358, +1234, -12, 945, 1287, -232, 921, -1005, -393, +-668, -975, 339, -290, 772, 445, 270, 364, +-200, -80, -90, -245, 101, 18, -106, 261, +-338, 145, -49, -295, 548, -470, 579, -58, +-97, 571, -581, 629, -406, -111, 176, -855, +537, -620, 442, 406, -42, 978, -430, 380, +-445, -689, 146, -885, 698, -9, 323, 844, +-494, 677, -494, -413, 268, -1044, 603, -262, +128, 1077, -404, 935, -367, -665, 191, -1421, +478, -125, 206, 1420, -261, 889, -234, -875, +117, -1233, 205, 202, -40, 1096, -237, 203, +139, -815, 564, -438, 285, 750, -556, 683, +-841, -611, 70, -1117, 1020, 157, 877, 1314, +-283, 555, -1115, -1002, -535, -1060, 564, 324, +864, 1075, 204, 216, -286, -753, -254, -480, +0, 443, -32, 569, -237, -218, 113, -622, +667, -74, 518, 566, -367, 359, -854, -295, +-280, -443, 560, -24, 757, 306, 69, 125, +-417, -159, -162, -56, 124, 140, 35, 99, +-187, -159, 7, -269, 384, -108, 520, 307, +-16, 574, -667, 43, -520, -741, 218, -732, +749, 411, 462, 1115, -127, 370, -454, -925, +-378, -1028, -22, 226, 402, 1124, 521, 519, +74, -697, -396, -888, -242, 64, 235, 751, +261, 379, -184, -325, -262, -402, 258, -45, +611, 70, 53, 76, -589, 245, -409, 276, +257, -190, 487, -649, 270, -320, -4, 541, +-161, 815, -268, 55, -167, -725, 94, -592, +324, 21, 452, 494, 146, 520, -446, 227, +-537, -369, 61, -708, 529, -392, 360, 441, +-26, 906, -209, 262, -114, -677, -11, -688, +-67, 130, -2, 497, 342, 110, 436, -138, +-27, 22, -538, 76, -420, -186, 249, -236, +716, 99, 295, 267, -443, 105, -443, -158, +131, -154, 464, -61, 123, 102, -307, 287, +-233, 63, 281, -497, 486, -544, 24, 494, +-470, 1121, -339, 126, 264, -1363, 552, -1057, +174, 784, -345, 1581, -283, 172, 247, -1221, +236, -680, -220, 591, -280, 443, 331, -420, +648, -212, -24, 734, -722, 632, -493, -678, +494, -1258, 792, -207, 125, 1188, -497, 1099, +-379, -192, 140, -1106, 328, -734, 112, 267, +-119, 765, -39, 404, 116, -182, 149, -341, +13, -122, -218, -36, -205, -65, 167, 51, +451, 233, 219, 170, -266, -64, -404, -160, +17, -92, 349, -58, 148, -85, -164, 5, +29, 222, 363, 300, 63, 124, -502, -256, +-445, -573, 324, -422, 817, 328, 433, 964, +-470, 579, -791, -552, -282, -1125, 467, -482, +750, 621, 375, 951, -253, 287, -669, -451, +-430, -514, 279, -134, 637, 19, 356, -19, +-148, 182, -308, 509, -180, 342, -32, -340, +20, -777, 178, -466, 373, 296, 288, 772, +-210, 609, -540, -108, -208, -737, 291, -687, +417, -27, 190, 530, 23, 530, -102, 210, +-210, -55, -322, -298, -123, -582, 406, -595, +694, 188, 340, 1193, -455, 1062, -894, -489, +-428, -1682, 600, -908, 1064, 866, 415, 1499, +-571, 409, -834, -821, -246, -823, 395, -36, +506, 288, 251, 24, 100, 88, -94, 520, +-435, 336, -454, -588, 68, -938, 652, -42, +616, 881, -105, 629, -602, -329, -373, -590, +182, 16, 350, 305, 136, -160, -18, -428, +53, 241, 96, 824, -148, 211, -297, -877, +-59, -815, 316, 362, 345, 935, 59, 188, +-162, -590, -156, -280, -47, 348, -70, 94, +-95, -491, 244, -206, 619, 691, 241, 664, +-629, -490, -791, -1026, -26, -65, 768, 956, +771, 484, 81, -558, -629, -628, -644, 220, +-111, 555, 378, -4, 620, -489, 438, -187, +-105, 400, -657, 385, -692, -196, -9, -506, +943, -101, 948, 478, -189, 409, -1095, -259, +-647, -642, 429, -168, 892, 612, 440, 623, +-284, -189, -588, -825, -328, -390, 93, 505, +476, 701, 518, 15, -18, -488, -571, -229, +-375, 117, 243, 47, 437, -96, 96, 92, +-118, 293, -31, 177, 25, -250, -167, -500, +-187, -190, 216, 425, 450, 511, 107, -1, +-430, -367, -282, -164, 174, 51, 339, -67, +33, -143, -143, 149, 36, 485, 119, 311, +-92, -374, -168, -846, 93, -352, 197, 652, +58, 988, -15, 189, -9, -782, -86, -785, +-119, 45, 32, 578, 201, 312, 263, -50, +9, 13, -359, 12, -245, -386, 230, -521, +453, 122, 111, 810, -352, 531, -339, -422, +174, -835, 438, -267, 103, 546, -312, 597, +-313, -70, 113, -516, 520, -153, 275, 376, +-478, 201, -639, -358, 187, -355, 861, 285, +399, 531, -625, 9, -862, -474, 92, -283, +947, 158, 517, 282, -494, 106, -704, -53, +-34, -111, 497, -114, 327, -68, -101, 132, +-170, 183, 14, -54, -1, -266, -123, -30, +4, 340, 218, 185, 185, -328, -6, -417, +-117, 174, -146, 519, -137, 94, 6, -479, +299, -268, 449, 367, 56, 395, -566, -303, +-566, -555, 115, 145, 738, 730, 591, 191, +-187, -687, -789, -558, -472, 391, 398, 671, +691, -121, 208, -611, -283, -2, -296, 640, +-74, 158, -14, -694, -5, -597, 252, 423, +451, 985, 32, 350, -537, -798, -490, -1057, +170, -62, 665, 1045, 356, 849, -279, -337, +-442, -921, -117, -296, 148, 447, 159, 329, +205, -160, 195, -92, -65, 343, -404, 148, +-292, -541, 236, -563, 526, 325, 222, 792, +-272, 159, -393, -595, -112, -399, 223, 199, +273, 274, 149, -55, 14, -55, -210, 153, +-325, 56, -53, -259, 333, -227, 442, 206, +75, 379, -415, -17, -450, -436, 64, -244, +441, 331, 338, 506, -7, -30, -258, -580, +-314, -352, -141, 327, 236, 502, 438, 74, +209, -294, -218, -226, -394, -9, -198, 65, +148, 34, 364, 68, 302, 147, -19, 81, +-317, -142, -343, -300, -32, -131, 364, 195, +382, 283, -9, 91, -277, -48, -178, -55, +31, -212, 100, -390, 8, -54, 67, 671, +235, 709, 99, -285, -259, -1007, -349, -455, +-30, 584, 348, 788, 395, 60, 52, -531, +-306, -289, -342, 269, -54, 162, 248, -371, +308, -280, 105, 502, -170, 750, -194, -124, +-23, -975, 128, -569, 45, 526, -132, 829, +15, 113, 401, -415, 262, -208, -444, 26, +-738, -203, 6, -251, 918, 296, 742, 754, +-385, 315, -1004, -682, -376, -1010, 595, -128, +734, 950, 91, 856, -344, -208, -325, -828, +-120, -375, 45, 313, 226, 342, 296, -65, +97, -80, -237, 237, -288, 182, 41, -334, +199, -513, 27, -4, -43, 557, 156, 426, +194, -177, -157, -452, -406, -185, -144, 143, +440, 170, 556, 54, -116, 21, -600, 39, +-265, -67, 395, -126, 485, -33, -41, 68, +-508, 1, -203, -45, 439, 65, 460, 253, +-110, 120, -534, -371, -348, -588, 233, -15, +705, 786, 447, 732, -420, -254, -907, -1059, +-338, -674, 742, 516, 1024, 1144, -13, 456, +-962, -734, -556, -1026, 440, -110, 632, 795, +27, 651, -338, -183, -93, -586, 229, -220, +29, 269, -212, 198, -53, -129, 226, -48, +101, 265, -77, 55, 51, -429, 99, -309, +-143, 377, -300, 578, 31, -40, 467, -613, +329, -388, -281, 301, -477, 581, -28, 195, +359, -386, 228, -490, -136, -78, -148, 344, +102, 373, 143, 69, -72, -228, -226, -275, +-68, -185, 244, 22, 331, 343, 45, 451, +-314, -20, -337, -614, 71, -517, 370, 255, +206, 754, -145, 294, -176, -502, 70, -578, +125, 94, -165, 475, -266, 132, 160, -304, +601, -160, 270, 285, -601, 287, -704, -281, +114, -588, 769, -8, 445, 774, -273, 547, +-489, -511, -123, -920, 140, -122, 80, 775, +111, 632, 282, -222, 185, -693, -336, -259, +-581, 357, -25, 373, 642, -11, 496, -189, +-279, -115, -519, -30, -42, 26, 326, 103, +101, 119, -220, 3, -15, -191, 353, -200, +178, 82, -398, 338, -424, 221, 180, -230, +569, -482, 192, -175, -431, 418, -367, 554, +230, 27, 414, -526, -23, -439, -391, 87, +-169, 402, 321, 308, 408, 40, 19, -242, +-408, -356, -369, -191, 52, 214, 480, 465, +390, 209, -109, -304, -466, -435, -198, -33, +222, 259, 185, 163, -46, -23, 28, -1, +291, 9, 68, -112, -460, -193, -461, 9, +180, 238, 683, 204, 420, -87, -278, -217, +-605, -96, -301, 78, 187, 59, 457, 25, +348, 100, -33, 60, -330, -160, -318, -217, +-29, 92, 239, 250, 157, 14, 54, -233, +175, -14, 72, 251, -396, 19, -504, -350, +116, -113, 728, 388, 512, 299, -400, -315, +-777, -437, -91, 168, 588, 518, 310, -21, +-253, -557, -215, -167, 166, 517, 284, 400, +-157, -292, -446, -502, -49, -56, 464, 309, +350, 267, -105, 108, -345, -99, -201, -384, +73, -326, 136, 262, 103, 628, 192, 151, +171, -573, -201, -493, -500, 261, -217, 555, +408, 15, 666, -434, 198, -105, -567, 318, +-660, 93, 33, -302, 601, -127, 438, 331, +-127, 238, -399, -299, -197, -418, 130, 119, +216, 539, 52, 201, -88, -428, -4, -517, +129, 50, 35, 546, -211, 412, -262, -216, +170, -602, 531, -211, 155, 427, -525, 394, +-510, -185, 274, -285, 690, 207, 116, 248, +-611, -425, -376, -554, 416, 417, 505, 1031, +-159, 32, -501, -1198, 27, -713, 456, 895, +97, 1173, -466, -290, -207, -1247, 495, -296, +467, 1056, -322, 727, -714, -680, -89, -1037, +713, 159, 635, 1064, -298, 466, -805, -713, +-290, -878, 520, 65, 597, 828, 9, 485, +-419, -409, -199, -649, 118, -13, 84, 459, +-91, 153, 62, -248, 324, -65, 133, 249, +-361, 18, -447, -381, 46, -217, 518, 399, +385, 526, -140, -122, -427, -668, -273, -318, +68, 429, 310, 621, 319, 79, 68, -515, +-298, -501, -384, 128, -65, 528, 355, 191, +454, -294, 25, -182, -490, 158, -377, -4, +213, -302, 491, -37, 168, 495, -322, 404, +-351, -348, 129, -755, 380, -214, 38, 667, +-334, 720, -149, -111, 297, -737, 291, -428, +-188, 296, -383, 505, 45, 183, 387, -171, +89, -275, -266, -200, -136, 38, 194, 279, +156, 202, -183, -83, -228, -231, 231, -136, +353, 74, -107, 182, -376, 107, -104, -67, +236, -128, 232, -83, -22, 12, -177, 123, +-48, 144, 70, 10, 45, -191, -32, -191, +-40, 71, 13, 259, 113, 163, 120, -116, +-106, -288, -278, -201, -60, 204, 310, 451, +314, 72, -130, -451, -354, -346, -90, 252, +245, 426, 137, -16, -114, -343, -100, -107, +176, 241, 150, 127, -217, -158, -294, -149, +84, 85, 412, 172, 173, 6, -297, -106, +-363, -82, 120, -9, 347, 29, 30, 81, +-274, 101, -36, -14, 280, -134, 109, -173, +-250, 11, -254, 270, 90, 213, 276, -193, +133, -376, -63, 14, -86, 377, -112, 170, +-197, -285, -16, -286, 396, 132, 401, 340, +-195, 86, -604, -284, -268, -306, 412, 96, +536, 388, -14, 180, -393, -266, -74, -352, +142, -2, -120, 329, -165, 216, 203, -200, +438, -281, 83, 76, -443, 317, -436, -15, +119, -446, 440, -126, 220, 596, -22, 392, +-191, -562, -308, -654, -195, 296, 284, 670, +449, 65, 71, -460, -345, -217, -239, 183, +80, 166, 98, -114, 21, -129, 138, 193, +143, 295, -183, -134, -317, -615, 11, -201, +413, 732, 251, 698, -379, -476, -494, -980, +255, -4, 649, 886, -20, 329, -645, -559, +-240, -322, 451, 324, 451, 119, -102, -313, +-469, -15, -174, 357, 312, 112, 281, -259, +-155, -210, -238, 36, 88, 127, 145, 109, +0, 60, -26, -14, -32, -153, -136, -190, +-12, 46, 161, 290, 146, 152, 61, -235, +-229, -266, -320, 105, 107, 314, 408, 52, +98, -401, -183, -257, -146, 441, -132, 553, +5, -310, 173, -726, 160, 0, 11, 590, +-65, 269, -154, -245, -100, -220, 40, -6, +73, -36, 132, -65, 190, 204, -94, 279, +-386, -159, -139, -361, 334, 50, 370, 279, +-81, -45, -449, -239, -167, 82, 422, 359, +281, 26, -352, -449, -334, -288, 243, 376, +330, 452, -5, -206, -261, -424, -165, 165, +191, 388, 126, -303, -239, -489, -71, 284, +410, 737, 211, -4, -377, -788, -484, -439, +62, 521, 583, 733, 268, -103, -371, -709, +-319, -290, 150, 508, 119, 502, -141, -243, +-39, -591, 242, -26, 267, 548, -129, 277, +-518, -345, -174, -385, 396, 88, 262, 301, +-88, 34, -10, -146, 29, 31, -139, 134, +-176, -103, -167, -293, 102, -84, 586, 350, +376, 474, -480, -46, -803, -704, -176, -523, +587, 456, 749, 913, 90, 138, -569, -787, +-511, -608, -64, 289, 203, 623, 364, 128, +330, -320, -27, -205, -391, 92, -422, 90, +-33, -90, 423, -71, 431, 126, -120, 186, +-428, -11, -80, -212, 189, -191, 44, 50, +-64, 268, 29, 139, 63, -176, 56, -197, +5, 93, -173, 139, -157, -83, 69, -90, +225, 93, 50, 84, -117, -121, -53, -31, +128, 216, 13, 89, -312, -396, -218, -378, +405, 351, 522, 772, -126, 106, -579, -872, +-305, -659, 239, 447, 435, 801, 189, 14, +-134, -410, -200, -18, -230, 73, -163, -414, +144, -299, 449, 552, 248, 875, -231, -14, +-506, -1010, -217, -759, 370, 399, 425, 999, +-65, 342, -319, -512, -83, -587, 23, 40, +104, 311, 158, -30, -59, -163, -237, 292, +-25, 430, 221, -260, 122, -673, -24, -175, +-218, 478, -350, 475, 64, 42, 617, -297, +392, -328, -502, -105, -750, 153, 12, 212, +718, 157, 326, 70, -372, -169, -318, -441, +93, -111, 201, 534, -36, 390, -279, -295, +-29, -508, 478, -27, 220, 380, -392, 321, +-478, -146, -23, -408, 353, -136, 421, 238, +36, 354, -256, 70, -345, -358, -283, -367, +249, 222, 575, 511, 6, -63, -439, -567, +-63, -93, 169, 636, -2, 333, -192, -606, +-84, -647, 340, 289, 350, 877, -296, 212, +-562, -741, -21, -607, 426, 382, 269, 604, +-176, -70, -241, -332, 150, 8, 112, 114, +-292, -86, -275, -89, 274, 86, 453, 144, +72, -14, -376, -139, -373, -83, 64, 161, +300, 142, 89, -232, -91, -308, 110, 304, +61, 548, -386, -229, -315, -740, 330, -17, +467, 802, -14, 293, -276, -690, -217, -512, +-32, 416, 124, 615, 24, -7, 13, -521, +216, -433, 28, 243, -343, 633, -179, 49, +165, -510, 280, -118, 31, 316, -354, -59, +-109, -400, 450, 136, 142, 766, -572, 146, +-329, -938, 432, -658, 621, 612, -31, 903, +-724, 15, -396, -719, 414, -463, 524, 448, +-66, 521, -403, -344, -122, -581, 296, 418, +133, 859, -395, -185, -232, -1186, 373, -452, +429, 1182, -178, 1081, -524, -681, -173, -1412, +331, 59, 366, 1388, -4, 481, -359, -1265, +-234, -978, 234, 1058, 216, 1478, -164, -531, +-222, -1812, 92, -324, 251, 1693, 120, 1114, +-332, -1091, -387, -1470, 196, 412, 445, 1427, +37, 111, -385, -1309, -199, -552, 191, 1199, +197, 1114, -144, -873, -91, -1611, 111, 137, +10, 1738, -95, 725, -109, -1349, -49, -1221, +127, 687, 210, 1309, -92, -155, -228, -1163, +-115, -295, 105, 1003, 242, 729, 4, -727, +-200, -1019, -169, 190, -40, 992, 171, 285, +333, -664, -85, -426, -519, 418, -162, 358, +344, -491, 451, -394, -92, 578, -609, 701, +-250, -342, 452, -961, 429, -153, -143, 877, +-494, 524, -215, -570, 486, -594, 399, 333, +-449, 594, -660, -153, 172, -742, 775, -156, +329, 890, -710, 649, -805, -639, 198, -1078, +881, 14, 353, 1054, -535, 622, -638, -615, +-45, -890, 411, 142, 307, 777, -10, 151, +-297, -658, -183, -337, 115, 649, 53, 640, +-133, -515, 55, -1008, 111, 70, -99, 1097, +-73, 525, 79, -719, -19, -857, -180, 166, +-99, 742, 130, 218, 225, -466, 32, -379, +-204, 325, -271, 552, -142, -155, 101, -847, +339, -234, 301, 942, -151, 824, -576, -620, +-324, -1166, 231, 76, 391, 1004, 259, 243, +-23, -595, -419, -209, -388, 407, 40, 191, +234, -442, 159, -535, 196, 253, -36, 1079, +-340, 452, -334, -1097, -116, -1436, 283, 363, +505, 1857, 127, 780, -497, -1459, -386, -1499, +-1, 606, 182, 1514, 130, 43, 85, -1260, +71, -309, -40, 1122, -329, 643, -396, -1044, +116, -1194, 541, 564, 279, 1700, -400, 337, +-483, -1657, -17, -1206, 335, 1006, 107, 1634, +-224, -184, -97, -1537, 208, -521, 115, 1238, +-306, 991, -275, -865, 66, -1319, 233, 443, +73, 1534, -100, 48, -11, -1554, 24, -587, +-221, 1423, -413, 1042, 98, -1092, 677, -1434, +385, 659, -617, 1659, -911, -97, 109, -1716, +862, -484, 262, 1530, -577, 941, -330, -1136, +294, -1216, 278, 716, -373, 1332, -615, -357, +283, -1471, 943, 33, 75, 1707, -1041, 481, +-551, -1881, 542, -1206, 662, 1706, -89, 1955, +-635, -1113, -157, -2407, 552, 255, 194, 2469, +-721, 629, -447, -2146, 617, -1481, 734, 1511, +-233, 2112, -936, -544, -304, -2332, 627, -502, +441, 1967, -299, 1301, -309, -1143, 17, -1663, +69, 277, 9, 1522, -81, 445, -117, -1068, +21, -791, 14, 409, 56, 635, 200, 111, +-110, -75, -554, -38, -195, -431, 418, -661, +479, 194, 66, 1342, -513, 890, -644, -1191, +101, -1925, 584, -22, 212, 1993, -309, 1238, +-268, -962, 147, -1399, 50, -123, -375, 594, +-222, 131, 476, 101, 442, 542, -197, 365, +-752, -814, -322, -1310, 631, -43, 491, 1515, +-383, 1216, -556, -669, 76, -1467, 410, -286, +192, 897, -507, 290, -550, -463, 307, 179, +644, 900, 101, -155, -561, -1374, -523, -672, +18, 1047, 431, 1345, 203, -165, 58, -1121, +-66, -298, -601, 554, -476, -57, 389, -539, +844, 375, 149, 1145, -838, 70, -789, -1493, +422, -984, 916, 1070, -145, 1494, -849, -279, +-255, -1468, 753, -219, 602, 1311, -661, 540, +-1148, -1284, 154, -1052, 1236, 1021, 426, 1562, +-961, -204, -857, -1581, 373, -664, 724, 1035, +-130, 1002, -611, -492, 70, -863, 485, 278, +-45, 802, -701, -156, -160, -852, 646, -197, +289, 785, -639, 512, -563, -562, 483, -559, +812, 389, -115, 787, -1296, -353, -602, -1250, +1067, -258, 1171, 1531, -305, 1336, -1241, -902, +-609, -1915, 543, -462, 847, 1541, -105, 1228, +-634, -576, -96, -1127, 348, 128, 166, 910, +-490, -166, -629, -1123, 299, -357, 1038, 1395, +67, 1369, -1015, -701, -575, -1852, 383, -692, +648, 1226, -124, 1341, -631, -32, 64, -945, +716, -343, 21, 292, -1033, -82, -733, -349, +682, 189, 1430, 903, 103, 506, -1525, -820, +-1017, -1325, 672, -135, 1205, 1235, -18, 1027, +-856, -283, -263, -887, 444, -463, -24, 88, +-557, 88, 11, 408, 579, 785, 309, 151, +-517, -1099, -644, -1182, 47, 435, 472, 1631, +42, 620, -242, -1245, 142, -1173, 215, 456, +-408, 1092, -805, 213, 26, -870, 1174, -519, +621, 582, -949, 685, -1263, -223, -5, -542, +1106, -64, 638, 59, -630, -73, -722, 238, +251, 784, 259, 115, -477, -1312, -339, -1165, +657, 899, 946, 2125, -469, 405, -1602, -2126, +-534, -1906, 1313, 1084, 1384, 2664, -363, 491, +-1575, -2249, -756, -1883, 779, 941, 917, 2382, +47, 657, -468, -1772, -268, -1646, -130, 385, +-523, 1497, -81, 761, 1133, -494, 954, -861, +-903, -389, -1878, 67, -582, 403, 1572, 588, +1978, 206, -180, -345, -2243, -565, -1597, -326, +858, 162, 2105, 511, 841, 376, -1233, 77, +-1716, -200, -358, -644, 978, -682, 1061, 257, +336, 1348, -724, 974, -1117, -914, -480, -1996, +662, -509, 1018, 1789, 389, 1911, -682, -341, +-1182, -2242, -438, -1365, 765, 1288, 1056, 2172, +107, 194, -786, -1736, -697, -1126, -140, 772, +262, 1101, 221, -202, 299, -773, 436, 262, +-68, 899, -1258, -121, -1229, -1433, 756, -765, +2082, 1415, 803, 1932, -1756, -286, -2343, -2361, +61, -1270, 2520, 1494, 1563, 2250, -1583, 2, +-2489, -2170, 2, -1211, 2327, 1259, 1110, 1888, +-1562, -124, -1759, -1989, 390, -977, 1541, 1560, +480, 1837, -1101, -663, -987, -2035, 568, -585, +1009, 1569, -386, 1588, -1182, -495, 24, -1941, +1151, -875, 482, 1506, -970, 1893, -1015, -149, +298, -2033, 856, -1397, 72, 873, -465, 2161, +-147, 941, 218, -1435, -6, -2184, -516, -265, +-306, 2085, 392, 1706, 583, -1012, 131, -2180, +-452, -166, -727, 2021, -262, 1078, 318, -1607, +528, -1969, 465, 711, -164, 2745, -895, 833, +-574, -2482, 345, -2556, 658, 882, 283, 3194, +-381, 1292, -659, -2314, -45, -2712, 620, 680, +293, 2776, -650, 844, -907, -2084, 143, -1846, +1338, 1016, 780, 2407, -921, 415, -1756, -2141, +-671, -1868, 1362, 664, 1920, 2250, 148, 1264, +-1877, -887, -1518, -1892, 396, -1146, 1485, 359, +566, 1691, -592, 1822, -510, 142, -36, -2158, +-131, -2528, -529, -113, 45, 2838, 1020, 2847, +802, -397, -789, -3293, -1618, -2551, -506, 959, +1224, 3263, 1574, 1972, 15, -1365, -1655, -2842, +-1357, -1248, 425, 1381, 1471, 2226, 870, 786, +-429, -1221, -1326, -1704, -1082, -445, 281, 922, +1503, 1199, 1272, 551, -666, -415, -2238, -1336, +-1078, -1251, 1692, 555, 2350, 2393, -205, 1404, +-2618, -1693, -1714, -3165, 1679, -607, 2820, 2946, +-20, 2992, -2984, -730, -1824, -3432, 1811, -1847, +2824, 1761, -96, 2805, -2761, 380, -1507, -1914, +1558, -1302, 2179, 635, -241, 963, -2091, -210, +-832, -521, 1212, 372, 1350, 743, -253, -194, +-1405, -1186, -768, -588, 745, 990, 1163, 1547, +156, -135, -828, -1759, -1142, -1135, -99, 1105, +1245, 1880, 929, 411, -654, -1565, -1370, -1826, +-409, -36, 981, 1946, 1194, 1952, -354, -376, +-1407, -2468, -400, -1744, 886, 924, 836, 2413, +-371, 1297, -1015, -943, -155, -2104, 922, -1067, +376, 890, -812, 1667, -668, 700, 420, -613, +827, -935, -191, -406, -823, -24, -58, 43, +658, 553, 67, 1033, -768, 374, -405, -1176, +777, -1752, 1057, -228, -560, 1855, -1641, 1970, +-406, -321, 1450, -2220, 1307, -1632, -591, 746, +-1787, 2174, -520, 1163, 1486, -869, 1097, -1928, +-776, -894, -1431, 847, -144, 1760, 1215, 763, +834, -852, -621, -1550, -1058, -723, -308, 716, +388, 1484, 612, 828, 407, -674, -39, -1516, +-570, -875, -853, 724, -436, 1445, 741, 680, +1413, -608, 376, -986, -1331, -615, -1628, 99, +-16, 545, 1592, 848, 1377, 486, -654, -426, +-1755, -1064, -507, -681, 1108, 256, 919, 973, +-484, 811, -863, -32, 73, -703, 844, -730, +103, -294, -1070, 212, -782, 549, 839, 659, +1662, 503, 184, -281, -1970, -1313, -1971, -1243, +769, 406, 2974, 1917, 1569, 1530, -2178, -715, +-3530, -2180, -517, -1156, 3257, 932, 3089, 1516, +-872, 589, -3678, -338, -1947, -485, 1922, -463, +2959, -834, 442, -423, -2236, 1137, -1762, 2052, +891, 475, 1830, -2129, -73, -2534, -1803, 115, +-711, 2691, 1648, 2012, 1896, -620, -643, -2017, +-2837, -1291, -1606, -73, 1868, 856, 3300, 1570, +865, 1465, -2700, -386, -3320, -2660, -152, -2346, +3135, 716, 2626, 3398, -711, 2642, -2766, -1056, +-1663, -3858, 850, -2482, 1786, 1577, 800, 3713, +-293, 1738, -780, -1746, -980, -2850, -570, -925, +627, 1362, 1456, 1749, 800, 464, -1050, -835, +-2029, -970, -483, -137, 1969, 563, 1984, 502, +-724, -161, -2675, -691, -1199, -450, 1940, 673, +2594, 1397, -45, 497, -2630, -1540, -2018, -2337, +712, -340, 2666, 2509, 1735, 3060, -1013, 177, +-2814, -3340, -1811, -3595, 1155, 184, 3049, 3924, +1747, 3455, -1386, -580, -3025, -3730, -1661, -2829, +1213, 575, 2771, 2844, 1499, 2222, -893, -134, +-2077, -1814, -1664, -1736, -175, -422, 1587, 847, +2310, 1496, 1060, 999, -1563, -429, -3254, -1537, +-1617, -987, 2206, 674, 3842, 1366, 1093, 166, +-2903, -1069, -3597, -544, -227, 825, 3048, 941, +2647, -257, -492, -1222, -2555, -763, -1804, 464, +487, 1151, 2056, 924, 1422, 4, -509, -1065, +-1790, -1448, -1281, -611, 449, 936, 1651, 2014, +1083, 1286, -434, -919, -1358, -2390, -1070, -1445, +88, 682, 1134, 1929, 1123, 1494, 189, 255, +-810, -981, -1355, -1936, -712, -1690, 711, 353, +1615, 2834, 920, 2725, -757, -442, -1768, -3489, +-897, -2766, 787, 927, 1565, 3245, 729, 1838, +-688, -1041, -1308, -2087, -585, -775, 543, 573, +896, 656, 421, 195, -323, 215, -535, 268, +-400, -298, -176, -701, 250, -215, 866, 730, +776, 462, -695, -735, -1872, -986, -759, 586, +1758, 1887, 2385, 709, 175, -1807, -2591, -2451, +-2571, -300, 472, 2196, 3003, 2549, 2223, 650, +-782, -1941, -2711, -2898, -1937, -1265, 444, 1600, +2015, 2975, 1789, 1673, 410, -958, -1239, -2494, +-2028, -1865, -1316, -21, 596, 1474, 2093, 1796, +1992, 1232, 84, 86, -1952, -1557, -2381, -2791, +-984, -1784, 1427, 1582, 2823, 4281, 1888, 2938, +-962, -1883, -3208, -5109, -2639, -3045, 722, 2081, +3419, 4569, 2618, 2351, -589, -1426, -2828, -2833, +-2368, -1728, 36, -250, 2074, 900, 2050, 1933, +466, 2016, -1299, 117, -1734, -2398, -816, -2846, +528, -395, 1259, 2440, 1217, 2708, 139, 360, +-1175, -1821, -1442, -1914, -336, -542, 1070, 736, +1341, 1228, 179, 989, -947, 94, -786, -859, +19, -1220, 521, -431, 150, 613, -333, 898, +57, 342, 809, 111, 442, -10, -1068, -709, +-1780, -1425, -163, -477, 2348, 1800, 2361, 2550, +-654, 0, -3345, -3015, -2307, -2528, 1418, 927, +3588, 3166, 1887, 1813, -1678, -1252, -3137, -2480, +-1459, -968, 1190, 838, 2258, 1028, 1199, 531, +-207, 538, -927, 373, -1350, -895, -1430, -2131, +-98, -1138, 2029, 1658, 2823, 3122, 606, 1311, +-2859, -2038, -3671, -3499, -383, -1336, 3391, 2228, +3443, 3270, -234, 921, -3324, -1878, -2280, -2282, +1040, -535, 2311, 974, 429, 948, -1330, 394, +-582, 295, 1130, 146, 981, -588, -1073, -1266, +-1912, -769, -352, 786, 1881, 1790, 2017, 857, +-5, -938, -1947, -1671, -1722, -526, 102, 1013, +1347, 1028, 1086, -289, 221, -881, -336, 175, +-576, 1123, -761, 432, -577, -1372, 233, -1747, +1173, 183, 1102, 2248, -104, 1822, -1089, -699, +-1087, -2347, -310, -1456, 567, 763, 981, 1766, +792, 861, 104, -406, -857, -698, -1166, -289, +-617, -261, 541, -368, 1279, -78, 1009, 666, +-113, 1098, -1206, 652, -1248, -573, -319, -1726, +971, -1429, 1315, 268, 450, 2209, -561, 2203, +-934, -21, -608, -2439, 54, -2437, 452, -183, +406, 1908, 568, 2161, 529, 761, -451, -753, +-1562, -1795, -1144, -1872, 936, -358, 2299, 1988, +973, 2657, -1515, 503, -2110, -2062, -413, -2229, +1482, -173, 1571, 1358, -43, 875, -1369, 11, +-849, 163, 505, 491, 938, -421, 313, -1598, +-621, -1134, -785, 984, -50, 2139, 652, 926, +645, -1001, 290, -1399, -452, -593, -1050, 97, +-682, 189, 486, 562, 1371, 1104, 923, 778, +-417, -685, -1353, -1773, -982, -1238, -48, 412, +848, 1637, 1182, 1463, 792, 319, -244, -808, +-1299, -1534, -1510, -1473, -606, -229, 1191, 1596, +2352, 2430, 1471, 1205, -1186, -1396, -3003, -3033, +-1852, -1900, 1124, 1052, 3003, 2946, 1846, 2158, +-865, -362, -2434, -2259, -1517, -2095, 395, -496, +1492, 1187, 1040, 1881, 21, 1345, -365, -201, +-426, -1624, -486, -1747, -606, -486, -29, 1216, +837, 1709, 1093, 774, 225, -768, -954, -1339, +-987, -620, 29, 501, 641, 694, 144, -12, +-289, -336, 168, 129, 812, 661, 343, 386, +-979, -635, -1407, -1427, -303, -865, 1337, 1109, +1651, 2384, 267, 1099, -1280, -1719, -1344, -2772, +-214, -705, 612, 1881, 629, 2090, 526, 195, +475, -1137, -240, -851, -1046, -174, -956, -198, +65, -142, 1173, 704, 1126, 1298, -139, 421, +-1099, -1218, -611, -1614, 370, -236, 519, 1252, +-76, 1194, -431, 46, -45, -731, 717, -521, +746, -127, -312, -44, -1374, 74, -1003, 485, +688, 548, 1760, -147, 872, -718, -819, -448, +-1388, 394, -559, 590, 451, -22, 630, -609, +217, -193, 185, 630, 505, 659, 60, -346, +-1109, -1123, -1426, -505, 12, 845, 1765, 1231, +1828, 170, -2, -1010, -1892, -879, -1857, 99, +-120, 628, 1651, 281, 1725, 40, 213, 112, +-1211, 38, -1237, -421, -203, -698, 590, -186, +557, 784, 307, 1090, 157, 86, -8, -1033, +-392, -1036, -691, 70, -280, 908, 501, 672, +891, -86, 320, -358, -463, -278, -698, -364, +-193, -149, 291, 419, 332, 669, 80, 98, +-66, -496, 82, -441, 106, 93, -222, 220, +-382, -67, -10, -45, 431, 337, 312, 316, +-94, -292, -214, -642, -44, -173, 27, 521, +-68, 525, -150, -158, 85, -445, 347, -11, +336, 383, -130, 49, -559, -551, -337, -442, +219, 465, 525, 1061, 328, 288, -138, -1011, +-377, -1211, -213, 26, 57, 1214, 170, 1051, +194, -246, 26, -1120, -52, -662, 0, 422, +43, 693, -41, 9, -246, -382, -150, 201, +306, 638, 534, -255, 75, -1239, -443, -527, +-430, 1189, 23, 1444, 330, -153, 307, -1462, +54, -868, -86, 539, -122, 959, -116, 231, +-47, -372, 72, -282, 115, 97, 37, 59, +-19, -286, 201, -247, 311, 350, -192, 658, +-794, 89, -507, -662, 703, -674, 1420, 146, +530, 793, -1217, 499, -1652, -395, -133, -826, +1444, -293, 1302, 699, -123, 909, -978, -51, +-618, -1086, 131, -836, 209, 456, 49, 1275, +179, 620, 611, -732, 445, -1083, -526, -339, +-1168, 431, -452, 654, 819, 582, 1152, 108, +334, -642, -572, -924, -612, -281, -145, 722, +-3, 898, -98, 137, 168, -513, 865, -416, +785, -66, -355, -40, -1407, -128, -1016, 107, +520, 608, 1568, 690, 1046, -154, -437, -1156, +-1232, -1149, -787, 248, 231, 1617, 696, 1324, +526, -454, 180, -1655, -97, -1092, -283, 405, +-317, 1269, -135, 830, -20, -191, 233, -713, +381, -514, 411, -154, 64, 89, -337, 321, +-613, 537, -348, 303, 265, -339, 680, -686, +636, -272, 192, 296, -514, 395, -884, 142, +-515, -34, 376, -24, 1070, -89, 910, -295, +-167, -237, -1155, 245, -904, 511, 262, 98, +991, -445, 630, -323, -191, 274, -452, 462, +-162, -104, 39, -571, -42, -309, 43, 373, +205, 676, 331, 302, 170, -421, -212, -729, +-534, -337, -151, 229, 558, 518, 564, 594, +-137, 342, -647, -460, -206, -1109, 617, -633, +671, 617, -262, 1138, -860, 492, -224, -335, +742, -590, 762, -497, -226, -319, -744, 46, +-221, 501, 621, 861, 555, 686, -307, -339, +-722, -1573, -92, -1403, 812, 497, 807, 2137, +-143, 1470, -1002, -790, -763, -1980, 344, -926, +1073, 718, 747, 1050, -119, 261, -710, -93, +-728, 183, -191, 45, 358, -807, 756, -1106, +815, 42, 241, 1508, -828, 1470, -1302, -354, +-454, -1776, 966, -1163, 1641, 662, 626, 1366, +-1067, 498, -1416, -562, -207, -633, 949, -22, +788, 330, -72, 50, -377, -331, 92, -184, +356, 331, -190, 544, -711, 183, -252, -466, +765, -715, 1038, -253, 123, 502, -891, 756, +-746, 273, 164, -427, 656, -661, 329, -193, +-92, 371, -93, 377, 91, -102, 89, -252, +-85, 221, -279, 519, -251, -167, 174, -1036, +731, -565, 724, 894, -66, 1414, -1098, 128, +-1027, -1348, 267, -1198, 1419, 353, 1094, 1289, +-204, 657, -1226, -510, -902, -881, 264, -287, +911, 431, 575, 531, 64, 87, -220, -292, +-291, -324, -255, -112, -178, 247, 182, 402, +543, 123, 503, -419, -3, -536, -465, 31, +-473, 607, -92, 474, 483, -174, 595, -596, +118, -409, -371, 231, -327, 548, 105, 196, +360, -238, 112, -153, -219, -44, -128, -177, +243, -190, 385, 269, 149, 625, -316, 189, +-441, -696, -6, -757, 501, 210, 450, 822, +75, 398, -287, -374, -287, -509, -59, -132, +109, 160, 270, 212, 338, 177, 220, 78, +-241, -226, -456, -284, -162, 40, 450, 337, +554, 73, -20, -365, -351, -215, -122, 414, +213, 569, 184, -182, -24, -862, -166, -509, +70, 595, 381, 1135, 218, 279, -273, -959, +-404, -1063, 76, 101, 518, 943, 353, 573, +-174, -214, -365, -360, -112, -152, 252, -257, +335, -286, 223, 257, -39, 894, -441, 508, +-338, -698, 393, -1261, 875, -238, 273, 1108, +-710, 1074, -862, -262, 121, -1108, 1103, -526, +698, 598, -468, 739, -862, -98, -99, -585, +705, -92, 416, 398, -446, 59, -271, -309, +619, 32, 606, 375, -504, -124, -1013, -563, +23, -10, 1181, 781, 837, 447, -562, -628, +-925, -872, -62, -42, 577, 763, 369, 688, +-41, 22, -105, -605, 56, -732, 67, -204, +-30, 509, 35, 862, 13, 448, -64, -447, +108, -1059, 301, -667, 199, 530, -52, 1236, +-281, 646, -243, -701, 154, -1123, 406, -284, +214, 628, 4, 509, 32, 6, -34, 13, +-270, 151, -354, -268, 162, -748, 814, -278, +682, 712, -301, 989, -955, 111, -498, -866, +577, -862, 870, 75, 154, 792, -391, 504, +-70, -310, 265, -515, -49, 127, -465, 491, +-257, -154, 540, -801, 1053, -224, 399, 915, +-774, 945, -1190, -294, -262, -1188, 987, -564, +1102, 591, 140, 794, -557, 72, -378, -333, +-121, -85, -147, 123, 10, -199, 513, -524, +818, -108, 374, 763, -558, 908, -1089, -150, +-500, -1128, 671, -763, 1253, 418, 612, 855, +-452, 255, -857, -189, -352, -17, 163, -3, +228, -605, 413, -707, 633, 265, 344, 1325, +-446, 935, -973, -638, -555, -1601, 588, -776, +1234, 868, 685, 1337, -400, 374, -991, -698, +-542, -669, 332, -79, 683, 174, 460, -47, +116, -6, -155, 477, -349, 608, -304, -155, +-8, -1066, 342, -742, 541, 515, 288, 1124, +-182, 504, -498, -521, -283, -889, 229, -385, +582, 509, 386, 704, -217, 86, -576, -541, +-87, -347, 612, 282, 450, 443, -251, -61, +-519, -469, -53, -230, 546, 256, 521, 484, +-172, 156, -562, -365, -83, -486, 447, 18, +435, 457, -78, 257, -451, -290, -69, -351, +514, 184, 355, 402, -226, 5, -379, -405, +-28, -260, 329, 87, 303, 352, 29, 337, +-37, 12, -10, -388, -124, -445, -134, -53, +118, 338, 331, 425, 279, 198, 46, -155, +-149, -482, -274, -432, -234, 137, 144, 619, +523, 394, 434, -300, 51, -466, -337, 31, +-536, 236, -238, -197, 424, -282, 766, 383, +455, 704, -244, -31, -721, -952, -450, -607, +215, 527, 616, 954, 647, 106, 194, -649, +-576, -398, -735, 242, -11, 235, 627, -188, +610, -109, 87, 329, -376, 358, -342, -233, +-55, -640, 279, -179, 424, 576, 180, 527, +-301, -252, -385, -501, 96, 7, 536, 345, +417, 31, -276, -331, -584, -124, -86, 358, +497, 394, 518, -109, 43, -566, -319, -366, +-258, 340, 41, 694, 120, 103, 181, -571, +203, -376, 226, 252, 14, 344, -393, -114, +-358, -276, 281, 163, 605, 403, 131, -109, +-279, -600, -139, -187, 203, 583, 105, 572, +-274, -305, -101, -782, 424, -95, 404, 720, +-82, 478, -260, -433, -138, -625, 19, -34, +46, 476, 142, 282, 357, -25, 364, -124, +-150, -185, -604, -306, -429, -171, 334, 386, +829, 734, 472, 264, -324, -782, -586, -996, +-227, 19, 143, 1018, 266, 730, 307, -254, +431, -669, 173, -366, -550, 21, -836, 156, +-52, 290, 940, 337, 998, 105, -21, -271, +-986, -447, -718, -274, 258, 95, 737, 415, +519, 444, 52, 155, -378, -277, -417, -568, +-82, -446, 204, 78, 364, 666, 358, 701, +71, 59, -292, -673, -384, -771, -134, -184, +336, 553, 508, 723, 237, 234, -182, -383, +-336, -491, -255, -174, 21, 74, 424, 82, +545, 139, 99, 325, -479, 286, -497, -134, +15, -685, 515, -610, 519, 272, 86, 1033, +-383, 573, -447, -613, -70, -956, 413, -111, +552, 701, 129, 436, -373, -284, -482, -429, +-10, 80, 494, 407, 459, 89, -49, -353, +-384, -319, -162, 134, 119, 317, 157, 142, +94, -75, 202, -114, 205, -57, -181, -83, +-545, -117, -147, 40, 660, 292, 681, 185, +-139, -133, -661, -208, -317, -28, 297, -7, +461, -221, 148, -73, -65, 503, -27, 665, +-46, -153, -243, -1057, -151, -738, 335, 556, +562, 1201, 137, 417, -404, -672, -481, -845, +-13, -170, 454, 413, 388, 375, 25, 73, +-147, -20, -115, 44, -158, -85, -108, -345, +126, -357, 472, 131, 475, 689, -233, 474, +-772, -360, -349, -753, 586, -197, 803, 401, +123, 326, -545, -8, -451, 1, 102, 58, +362, -221, 186, -340, -53, 29, 3, 416, +195, 275, -2, -220, -388, -399, -300, -7, +387, 375, 745, 130, 191, -300, -636, -256, +-558, 151, 165, 367, 500, 40, 269, -304, +-23, -210, -73, 183, -106, 225, -156, -73, +-126, -268, 194, -15, 400, 313, 160, 178, +-188, -156, -251, -260, -33, -132, 97, -9, +81, 184, 58, 374, 199, 230, 226, -297, +-74, -659, -408, -329, -311, 418, 217, 811, +611, 364, 369, -492, -210, -861, -542, -268, +-327, 584, 191, 627, 541, -26, 364, -342, +-140, -78, -439, 39, -190, -197, 266, -197, +316, 242, -29, 450, -257, 107, -20, -276, +356, -342, 338, -157, -277, 110, -641, 311, +-87, 176, 713, -88, 674, -119, -185, 46, +-817, -83, -374, -356, 534, -114, 629, 578, +-43, 612, -425, -278, -82, -775, 278, -182, +114, 400, -276, 151, -111, -73, 348, 297, +304, 373, -155, -419, -284, -1008, -14, -137, +137, 1098, 79, 894, 48, -483, 204, -1076, +69, -243, -312, 661, -353, 496, 182, -232, +571, -350, 312, 83, -381, 303, -630, -9, +-11, -394, 654, -255, 455, 316, -316, 569, +-593, 3, 58, -605, 571, -348, 208, 391, +-367, 460, -340, -137, 73, -419, 447, -30, +404, 341, -181, 158, -571, -193, -289, -264, +297, -15, 601, 180, 389, 172, -273, -7, +-637, -124, -246, -72, 309, 99, 403, -52, +187, -328, 40, 79, -78, 721, -243, 241, +-316, -848, -79, -753, 377, 451, 601, 960, +171, 157, -461, -667, -472, -457, -84, 192, +183, 335, 324, 28, 289, -85, 115, 2, +-71, -1, -332, 2, -501, 4, -93, -123, +598, -150, 679, 164, 198, 346, -468, 28, +-764, -288, -367, -249, 513, -29, 786, 110, +363, 294, -283, 271, -596, -131, -386, -544, +140, -284, 456, 422, 374, 558, 77, -90, +-321, -507, -327, -165, 73, 309, 255, 308, +-25, -89, -139, -439, 114, -234, 308, 402, +164, 674, -378, 37, -501, -815, 128, -678, +599, 321, 197, 919, -284, 457, -198, -451, +161, -749, 179, -234, -271, 348, -411, 345, +282, 142, 797, 84, 259, 0, -622, -330, +-835, -535, -156, -66, 860, 666, 859, 684, +-148, -110, -721, -729, -435, -559, 23, 113, +406, 648, 499, 481, 126, -149, -274, -522, +-440, -325, -181, 102, 277, 373, 442, 286, +87, -76, -242, -326, -177, -266, 17, 110, +64, 431, 65, 130, 75, -360, 39, -264, +-18, 203, -42, 213, -22, -77, 49, -137, +3, 98, -79, 128, 94, -152, 282, -220, +9, 86, -358, 256, -206, 20, 186, -144, +420, -28, 200, 94, -313, -76, -422, -285, +88, -17, 416, 517, 122, 404, -179, -361, +-204, -769, 75, -231, 299, 632, 100, 804, +-443, -41, -267, -819, 404, -568, 571, 326, +-7, 790, -613, 238, -503, -588, 356, -573, +778, 193, 72, 636, -564, 263, -268, -472, +255, -616, 232, 81, 0, 602, -137, 332, +-54, -204, 186, -405, 208, -227, -183, 108, +-353, 234, 38, 160, 405, 104, 308, -47, +-217, -310, -456, -288, -39, 106, 416, 400, +232, 222, -125, -189, -254, -296, -134, -48, +207, 126, 387, 80, -48, 11, -457, -25, +-135, -42, 403, 45, 393, 99, -126, -105, +-507, -274, -163, 36, 494, 418, 476, 145, +-263, -405, -664, -308, -42, 238, 709, 421, +451, -42, -475, -403, -646, -209, 53, 278, +562, 401, 372, 34, -147, -471, -485, -373, +-208, 356, 401, 547, 311, -51, -218, -544, +-267, -269, 193, 345, 444, 522, -73, -8, +-732, -570, -262, -352, 814, 269, 728, 562, +-279, 233, -832, -351, -529, -609, 438, -199, +1039, 553, 292, 688, -803, -75, -750, -769, +114, -432, 791, 400, 479, 613, -426, 96, +-497, -410, 33, -359, 246, 53, 148, 247, +39, 130, -79, 33, 15, 22, -38, -183, +-110, -287, 137, -21, 45, 351, -62, 318, +177, -60, 168, -383, -278, -277, -329, 107, +76, 339, 464, 146, 327, -75, -293, -77, +-470, -97, -83, -230, 378, -107, 365, 394, +-125, 490, -319, -132, 48, -675, 149, -252, +-43, 372, -45, 445, -18, 135, 207, -237, +182, -336, -344, -168, -274, 93, 341, 264, +328, 399, -143, 100, -358, -527, -58, -624, +498, 73, 236, 814, -532, 529, -327, -452, +424, -767, 505, -11, -188, 531, -618, 89, +6, -242, 681, 105, 175, 343, -548, -151, +-325, -552, 295, -221, 493, 549, -6, 657, +-482, -190, -164, -800, 370, -176, 275, 662, +-194, 387, -325, -532, 121, -515, 493, 470, +-120, 762, -583, -329, 47, -1007, 636, -11, +249, 1104, -518, 485, -583, -960, 255, -978, +795, 620, 149, 1352, -577, -8, -490, -1433, +142, -714, 573, 1054, 222, 1259, -312, -324, +-200, -1351, 84, -258, -17, 1024, -97, 604, +21, -704, 317, -710, 323, 521, -293, 921, +-655, -281, -32, -1174, 672, -123, 404, 1191, +-384, 711, -538, -906, 190, -1133, 560, 462, +-49, 1312, -615, 66, -236, -1292, 586, -541, +734, 1045, -148, 1003, -913, -582, -477, -1268, +555, 4, 830, 1205, 54, 625, -625, -860, +-342, -1049, 296, 326, 303, 1222, -179, 302, +-282, -1035, 225, -739, 445, 545, -70, 881, +-392, -58, -253, -674, 89, -121, 346, 456, +234, 113, -49, -431, -161, -173, -246, 422, +-123, 439, 302, -149, 284, -541, -95, -229, +-222, 286, -86, 358, 153, 75, 263, -175, +-41, -90, -347, 119, -192, -27, 206, -366, +437, -178, 233, 552, -284, 706, -538, -43, +-240, -917, 349, -738, 575, 338, 206, 1112, +-256, 571, -501, -615, -323, -994, 251, -159, +616, 783, 187, 629, -424, -400, -399, -691, +195, 221, 458, 822, -134, -6, -550, -961, +-74, -482, 695, 925, 505, 1025, -454, -432, +-843, -1221, -94, -184, 703, 1029, 602, 665, +-208, -586, -779, -936, -140, 184, 695, 1053, +307, 300, -552, -980, -437, -727, 297, 738, +605, 1020, 146, -375, -576, -1080, -451, 114, +242, 1068, 447, 149, 8, -1034, -198, -463, +-19, 1006, 133, 902, -12, -680, -292, -1268, +-156, 146, 231, 1298, 459, 541, 130, -913, +-364, -984, -442, 447, -131, 1062, 244, -36, +475, -1024, 345, -65, -296, 1107, -611, 355, +-263, -1264, 348, -985, 584, 1106, 86, 1756, +-464, -240, -228, -2021, 253, -856, 86, 1569, +-295, 1579, -102, -686, 454, -1658, 444, 110, +-410, 1500, -811, 224, 2, -1448, 870, -608, +493, 1458, -678, 1295, -825, -980, 387, -1930, +949, 191, -159, 2121, -895, 656, -212, -1849, +744, -1228, 595, 1500, -479, 1778, -854, -937, +117, -2360, 843, 48, 97, 2619, -593, 1144, +-202, -1957, 388, -1932, 98, 758, -383, 1842, +-90, 222, 536, -1087, 309, -336, -668, 628, +-768, 48, 390, -656, 1071, -47, 175, 813, +-878, 571, -698, -554, 298, -816, 665, 58, +12, 595, -290, 134, 168, -117, 108, 184, +-527, 73, -453, -398, 348, -487, 855, 332, +228, 927, -835, 78, -699, -1072, 387, -468, +666, 1071, -69, 962, -504, -792, -112, -1511, +449, 160, 289, 1829, -426, 878, -585, -1230, +3, -1619, 531, 84, 396, 1377, -44, 928, +-413, -312, -412, -801, -125, -556, 247, -149, +457, 556, 202, 1039, -362, 401, -439, -1075, +49, -1374, 216, 366, -45, 1855, -213, 738, +64, -1643, 511, -1617, 177, 987, -794, 2184, +-737, 11, 417, -2244, 962, -836, 224, 1861, +-834, 1474, -709, -1287, 453, -1678, 766, 838, +-248, 1912, -831, -303, -164, -2158, 807, -526, +658, 2238, -624, 1667, -1031, -1492, 81, -2423, +832, 256, 213, 2322, -522, 900, -355, -1529, +427, -1341, 451, 970, -555, 1415, -861, -611, +136, -1620, 904, 204, 467, 1841, -411, 771, +-705, -1423, -228, -1484, 67, 555, -138, 1360, +321, 125, 1008, -682, 247, 48, -1306, 542, +-1461, -290, 182, -997, 1701, -75, 1134, 1267, +-913, 883, -1549, -579, -95, -1026, 963, -254, +211, 534, -771, 346, -187, -140, 919, 126, +732, 636, -922, 47, -1641, -1058, -161, -1020, +1550, 626, 1248, 1713, -507, 684, -1464, -1211, +-819, -1324, 577, 114, 1022, 991, 303, 524, +-597, -331, -723, -234, -140, 186, 489, 51, +452, -294, -189, -191, -633, 278, -367, 322, +306, 42, 615, -208, 197, 154, -501, 223, +-763, -355, -268, -666, 498, -24, 792, 1099, +161, 1079, -750, -429, -898, -1713, -17, -819, +782, 1093, 466, 1630, -329, 296, -546, -1143, +-154, -918, 104, 231, -68, 585, -43, 51, +376, -69, 283, 417, -632, 507, -931, -516, +84, -1280, 1177, -299, 669, 1483, -1070, 1410, +-1402, -459, 168, -1693, 1416, -721, 614, 1068, +-1135, 1202, -1236, -60, 503, -879, 1276, -318, +-207, 334, -1294, 354, -401, 101, 1108, -150, +895, -225, -890, -223, -1477, 339, 14, 757, +1344, 170, 732, -1004, -801, -1025, -1305, 583, +-95, 1670, 902, 664, 398, -1321, -395, -1553, +-423, 183, -44, 1529, 88, 962, -293, -621, +-178, -1225, 389, -271, 338, 958, -344, 851, +-584, -356, -310, -1060, 246, -348, 385, 932, +90, 1274, -82, 73, -361, -1526, -624, -1536, +-305, 452, 570, 2363, 896, 1601, -37, -1134, +-1193, -2774, -892, -1204, 455, 1867, 949, 2838, +282, 453, -650, -2334, -703, -2064, -26, 602, +268, 2233, -39, 837, 49, -1413, 257, -1322, +-229, 741, -823, 1557, -369, -53, 811, -1584, +972, -849, -510, 1216, -1723, 1648, -625, -118, +1465, -1489, 1711, -798, -480, 766, -2423, 989, +-1345, -186, 1424, -746, 2437, 260, 319, 1051, +-2289, -60, -2200, -1454, 524, -977, 2380, 1108, +1184, 2179, -1363, 539, -2217, -1840, -311, -2188, +1595, 32, 1056, 2186, -747, 1967, -1113, -397, +-8, -2150, 666, -1323, -179, 669, -975, 1693, +-115, 725, 1320, -601, 861, -744, -1174, -20, +-2128, -6, -523, -337, 1941, 31, 1999, 906, +-346, 1155, -2227, -169, -1758, -1857, 303, -1505, +1850, 919, 1406, 2483, -343, 1225, -1732, -1456, +-1569, -2574, 199, -443, 1653, 2201, 1058, 1942, +-892, -811, -1607, -2324, -185, -487, 1335, 2208, +559, 1917, -1346, -1539, -1460, -3229, 743, -273, +2133, 3699, 350, 2969, -2253, -2014, -1969, -4550, +834, -1043, 2266, 3814, 467, 3451, -1698, -1321, +-1186, -3730, 763, -776, 866, 2827, -860, 1788, +-1192, -1874, 712, -2289, 1755, 1075, -116, 2935, +-2146, 466, -1404, -2730, 1145, -2257, 1996, 1109, +53, 2971, -1911, 1209, -1073, -1646, 1023, -2300, +1211, -403, -529, 1581, -1522, 1680, -409, 64, +1213, -1399, 1187, -1191, -425, 400, -1651, 1613, +-1199, 730, 567, -1321, 1576, -1668, 772, 459, +-637, 2345, -1529, 1095, -1107, -1824, 400, -2587, +1348, 138, 728, 2828, -345, 2040, -1219, -1204, +-1027, -2881, 177, -1132, 958, 1800, 572, 2503, +-290, 509, -870, -1835, -463, -1974, 272, -126, +104, 1695, -264, 1850, 116, 100, 540, -1842, +0, -1824, -1184, 414, -1317, 2164, 633, 1471, +2316, -796, 748, -2093, -2393, -1029, -2868, 965, +465, 1906, 3548, 1114, 1956, -763, -2508, -2150, +-3897, -1426, -323, 1061, 3559, 2737, 2714, 1552, +-1720, -1559, -3896, -3227, -1169, -1162, 2857, 2363, +2967, 3226, -758, 438, -3373, -2634, -1843, -2563, +1685, 133, 2912, 2390, 605, 2007, -2496, -222, +-2500, -1962, 249, -1597, 2463, 231, 1604, 1764, +-1223, 1566, -2492, -333, -797, -1983, 1778, -1255, +1701, 1050, -586, 2182, -2041, 483, -813, -1775, +1377, -1727, 1465, 621, -691, 2006, -1984, 793, +-393, -1204, 1645, -1402, 1189, 215, -1083, 1099, +-2087, 205, -242, -587, 1932, 101, 1462, 1063, +-1195, -9, -2385, -1804, -530, -1455, 1787, 1591, +1697, 3312, -497, 715, -1965, -3367, -1161, -3504, +717, 998, 1394, 4333, 554, 2285, -840, -2235, +-1272, -3672, -444, -661, 653, 2314, 899, 2231, +64, -63, -888, -1367, -809, -1050, 181, -102, +702, 494, 272, 759, -558, 628, -824, -118, +-76, -938, 697, -770, 445, 315, -329, 1150, +-847, 567, -654, -574, 307, -846, 990, -110, +471, 349, -664, 339, -1348, 270, -727, 312, +1004, -30, 1520, -830, 110, -1004, -1580, 256, +-1496, 1722, 330, 1351, 1643, -710, 714, -2303, +-942, -1299, -1348, 1271, -360, 2535, 740, 951, +855, -1466, -9, -2160, -588, -539, -760, 1357, +-581, 1515, 249, 238, 1189, -791, 883, -594, +-788, -54, -2161, -72, -1195, -222, 1646, 355, +2793, 1050, 326, 625, -2914, -770, -2725, -1564, +820, -607, 3143, 1162, 1322, 1595, -1948, 376, +-2363, -1001, 163, -1176, 1841, -308, 325, 576, +-1563, 791, -631, 539, 1590, 26, 1443, -525, +-1409, -850, -3108, -384, -681, 459, 3275, 1056, +3334, 706, -1133, -290, -4570, -1003, -2782, -980, +2398, -139, 4808, 1022, 1520, 1746, -3626, 694, +-4549, -1543, -204, -2449, 4058, -638, 3256, 2124, +-1431, 2613, -3890, 441, -1434, -2041, 2272, -2263, +2375, -514, -817, 1305, -2394, 1862, -78, 1283, +2140, -108, 812, -1810, -2197, -2358, -2442, -728, +850, 1990, 3410, 3149, 1596, 1433, -2406, -1858, +-3723, -3626, -872, -2039, 2864, 1616, 3269, 3938, +210, 2518, -2872, -1350, -3030, -3868, -84, -2518, +2586, 1080, 2188, 3369, -220, 2329, -1960, -687, +-1671, -2555, 35, -1882, 1131, 341, 780, 1734, +131, 1362, -171, -98, -708, -1011, -961, -767, +-213, 175, 983, 763, 1137, 138, -454, -807, +-1806, -677, -640, 808, 1788, 1818, 1861, 630, +-1191, -1908, -3251, -2699, -986, -394, 3006, 2789, +3529, 3256, -604, 287, -4388, -3199, -3073, -3402, +1831, -281, 4359, 3055, 1948, 3461, -2292, 587, +-3740, -2727, -1418, -3385, 1751, -797, 2738, 2506, +1275, 3235, -1045, 636, -2318, -2446, -1689, -2588, +250, 58, 2079, 2270, 2092, 1610, -123, -905, +-2369, -1837, -2321, -373, -109, 1446, 2408, 1277, +2563, -311, -130, -1410, -2828, -1107, -2843, 135, +113, 1326, 3324, 1843, 3042, 613, -959, -1802, +-3951, -2907, -2683, -970, 1464, 2493, 3927, 3610, +1874, 947, -2144, -2771, -3209, -3464, -1083, -721, +1544, 2264, 2188, 2712, 667, 779, -975, -1072, +-1414, -1495, -858, -1164, 137, -577, 1039, 521, +971, 1976, -9, 2003, -1137, -57, -1111, -2604, +255, -2716, 1182, 104, 419, 2832, -714, 2589, +-955, -272, -135, -2517, 773, -1856, 685, 572, +-115, 1894, -719, 796, -819, -835, -347, -1094, +583, 232, 1124, 1204, 648, 460, -648, -1051, +-1630, -1379, -1012, -112, 475, 1304, 1462, 1472, +1331, 467, 10, -956, -1450, -1684, -1869, -1248, +-861, 359, 1051, 1898, 2361, 2161, 1598, 701, +-870, -1909, -2829, -3385, -2552, -1687, 495, 2214, +3299, 4338, 2885, 2063, -586, -2336, -3498, -4349, +-2928, -1917, 725, 1930, 3027, 3422, 2087, 1782, +-719, -842, -2162, -2094, -1216, -1795, 311, -491, +565, 1028, 339, 1909, 711, 1432, 601, -179, +-408, -1615, -1708, -1943, -1449, -600, 785, 1151, +2308, 2062, 1188, 1464, -1212, -401, -2270, -2204, +-1014, -2328, 1101, -108, 1813, 2541, 846, 3057, +-746, 185, -1655, -3205, -1233, -3041, 403, 614, +1659, 3350, 1362, 1869, -417, -1333, -1794, -2144, +-1251, -216, 285, 869, 1208, 12, 1003, -519, +124, 886, -681, 1816, -952, -135, -895, -2886, +-92, -2250, 1079, 1686, 1514, 3833, 312, 1307, +-1350, -2774, -1823, -3099, -373, 161, 1363, 2419, +1365, 1277, -205, -874, -1004, -821, -155, 676, +625, 622, -264, -1269, -1535, -1856, -851, 377, +1837, 2725, 3083, 2263, 399, -1090, -3742, -3398, +-3993, -2144, 568, 1336, 4705, 3217, 3676, 1932, +-1500, -968, -4655, -2561, -2590, -1651, 1589, 292, +3164, 1611, 1380, 1487, -836, 389, -1245, -678, +-765, -1035, -806, -917, -474, -385, 894, 532, +2069, 1375, 1262, 1417, -1322, -55, -3035, -1864, +-1285, -2127, 1811, 21, 2740, 2298, 627, 2153, +-1864, -501, -1961, -2275, 141, -1054, 1433, 1027, +529, 1143, -835, -339, -702, -780, 677, 455, +1142, 1232, -196, -65, -1579, -1745, -1304, -1175, +561, 1087, 2050, 2040, 1390, 454, -903, -1580, +-2319, -1339, -1371, 514, 922, 1344, 2145, 9, +923, -1149, -945, -394, -1346, 1232, -437, 1298, +215, -562, 280, -2056, 151, -1075, 471, 1271, +635, 2229, -215, 732, -1223, -1316, -1120, -1911, +341, -519, 1355, 1000, 912, 1242, -335, 339, +-889, -401, -537, -218, -340, -41, 8, -549, +466, -951, 953, 14, 545, 1531, -654, 1774, +-1440, 27, -685, -2089, 749, -2124, 1240, -122, +311, 1810, -648, 2138, -538, 926, 3, -1056, +42, -2372, -227, -1934, -241, 467, 403, 2795, +791, 2506, 206, -409, -716, -2731, -1063, -2140, +-352, 373, 938, 1996, 1032, 1265, -99, -159, +-935, -622, -590, -505, 514, -401, 849, -281, +-297, 161, -1311, 549, -439, 531, 1271, 99, +1609, -89, -41, -103, -1844, -594, -1714, -857, +187, -243, 1623, 1150, 1488, 1676, 363, 473, +-933, -1445, -1712, -1938, -1304, -527, 317, 1181, +1846, 1627, 1956, 647, 172, -418, -1929, -850, +-2094, -894, -468, -646, 1303, 113, 1649, 1135, +853, 1522, -276, 588, -1114, -1153, -1496, -2116, +-742, -1134, 776, 1060, 1771, 2316, 1357, 1419, +-466, -815, -2030, -2110, -1484, -1407, 424, 521, +1662, 1606, 1191, 1106, -321, -3, -1385, -832, +-809, -1058, 466, -557, 988, 536, 380, 1252, +-730, 610, -1010, -675, 8, -1182, 1246, -189, +956, 790, -479, 817, -1389, -38, -1024, -778, +398, -662, 1486, 74, 1056, 801, -258, 801, +-1099, 62, -1210, -939, -296, -1179, 789, -117, +1166, 1251, 692, 1459, -282, -7, -1121, -1423, +-1068, -1358, -35, 12, 942, 1344, 1009, 1318, +179, 20, -723, -1256, -685, -1165, -34, -20, +325, 1152, 10, 1109, -145, -104, 115, -1220, +518, -931, 301, 494, -484, 1316, -764, 398, +-261, -983, 336, -846, 487, 381, 335, 785, +171, -33, 54, -531, -491, 83, -1056, 579, +-662, -112, 866, -916, 1803, -325, 975, 959, +-1088, 1084, -2274, -304, -1161, -1326, 1218, -669, +2290, 712, 1020, 1096, -1071, 249, -1937, -591, +-850, -682, 877, -189, 1351, 238, 300, 494, +-549, 445, -291, 26, 135, -616, -219, -826, +-682, -27, -163, 1134, 1074, 1080, 1244, -502, +-427, -1689, -1670, -728, -894, 1283, 1013, 1701, +1595, -131, 117, -1676, -1381, -990, -859, 956, +675, 1358, 1079, -116, -15, -1271, -978, -343, +-430, 1000, 680, 771, 658, -690, -329, -1218, +-610, 76, -34, 1357, 575, 663, 271, -935, +-538, -1041, -532, 263, 379, 959, 708, 182, +144, -813, -600, -467, -617, 703, 101, 826, +576, -249, 344, -1007, -56, -548, -245, 470, +-296, 917, -190, 454, 75, -356, 327, -658, +392, -488, 54, -59, -366, 369, -506, 637, +-26, 466, 394, -152, 363, -667, 68, -740, +-176, -171, -314, 523, -183, 869, 107, 545, +335, -216, 202, -900, -189, -936, -327, -138, +30, 855, 374, 1173, 193, 436, -393, -760, +-399, -1197, 51, -560, 572, 505, 504, 940, +-149, 569, -701, -217, -535, -563, 132, -334, +731, -79, 640, -177, -90, 15, -623, 688, +-523, 905, 44, -166, 274, -1307, 149, -979, +233, 532, 555, 1316, 144, 484, -804, -690, +-1153, -718, -218, 103, 1214, 361, 1533, -169, +229, -327, -1297, 241, -1325, 702, -342, 112, +740, -689, 1114, -727, 765, 134, -17, 774, +-784, 488, -1244, -347, -625, -738, 775, -176, +1506, 620, 737, 626, -635, -305, -1093, -967, +-447, -420, 221, 815, 228, 1243, 118, 68, +534, -1354, 842, -1227, -26, 409, -1339, 1466, +-1303, 821, 249, -652, 1600, -1187, 1267, -408, +-308, 556, -1219, 711, -707, 172, 164, -358, +307, -447, 174, -61, 417, 381, 638, 294, +101, -276, -952, -586, -1185, -34, 83, 690, +1372, 576, 1023, -330, -447, -922, -1084, -407, +-189, 557, 672, 824, 282, 99, -575, -565, +-398, -503, 631, 62, 911, 355, -41, 178, +-925, -132, -643, -184, 263, -13, 635, 113, +252, 88, 65, -51, 110, -150, -19, -111, +-548, 41, -630, 94, 147, 9, 1001, 44, +815, 208, -199, 71, -1038, -434, -708, -711, +341, -66, 956, 969, 500, 1114, -421, -176, +-732, -1492, -76, -1178, 668, 466, 507, 1466, +-264, 765, -738, -476, -177, -779, 643, -348, +629, -150, 24, -259, -398, 219, -304, 1032, +-29, 1000, -24, -411, -11, -1778, 413, -1387, +693, 663, 201, 2086, -662, 1139, -981, -914, +-332, -1625, 790, -587, 1288, 570, 537, 609, +-638, 157, -1108, 114, -602, 316, 454, -100, +960, -839, 520, -845, -174, 144, -316, 1121, +-94, 897, -77, -236, -348, -964, -333, -636, +430, 27, 1185, 332, 790, 406, -653, 386, +-1506, 152, -816, -407, 709, -759, 1547, -427, +850, 441, -332, 866, -949, 309, -783, -486, +-176, -637, 474, -107, 829, 221, 752, 140, +123, 48, -732, 202, -944, 89, -264, -443, +614, -505, 987, 163, 570, 739, -311, 271, +-810, -670, -388, -806, 431, 173, 638, 1030, +42, 539, -479, -791, -116, -1208, 695, -70, +643, 1247, -452, 889, -1076, -603, -281, -1308, +986, -277, 1007, 973, 10, 774, -609, -409, +-219, -870, 170, -115, -184, 625, -464, 382, +409, -419, 1419, -568, 875, 179, -1006, 557, +-1999, 41, -643, -567, 1501, -324, 2092, 344, +555, 526, -1277, -10, -1615, -594, -313, -474, +993, 190, 1206, 620, 469, 355, -406, -327, +-693, -635, -238, -350, 280, 298, 322, 581, +151, 250, 0, -335, 152, -504, 296, -162, +-42, 187, -424, 250, -222, 113, 275, 3, +563, -157, 356, -322, -152, -167, -325, 279, +11, 423, 263, -72, 116, -555, -35, -284, +-65, 379, 203, 462, 439, -120, 182, -449, +-299, -190, -417, 188, -175, 133, 353, -94, +815, 31, 512, 261, -289, -10, -649, -603, +-375, -480, 190, 392, 697, 866, 646, 231, +150, -747, -281, -759, -535, 30, -326, 651, +221, 339, 687, -218, 560, -328, 62, 11, +-429, 149, -354, -139, 76, -334, 299, -44, +258, 406, 161, 414, 219, -58, 260, -502, +-17, -605, -440, -158, -402, 523, 209, 829, +911, 260, 857, -704, -249, -1089, -1063, -315, +-575, 840, 647, 1076, 1198, 94, 410, -904, +-756, -888, -687, 12, 446, 671, 918, 479, +211, -87, -654, -259, -418, -203, 489, -290, +873, -302, 223, 254, -426, 777, -461, 378, +-52, -731, 419, -1122, 541, -93, 356, 1165, +-122, 921, -456, -616, -127, -1332, 566, -273, +513, 1076, -194, 866, -468, -572, 280, -1166, +994, -102, 374, 966, -1018, 542, -935, -537, +729, -677, 1513, 70, 348, 368, -1081, -104, +-815, -342, 787, 363, 1199, 769, -262, -185, +-1157, -1392, 52, -914, 1508, 1013, 1025, 1852, +-849, 396, -1548, -1653, -18, -1704, 1523, 143, +1077, 1506, -454, 1002, -852, -349, 73, -897, +663, -479, 95, 52, -562, 172, -103, 70, +960, 232, 1111, 354, -105, 41, -1221, -547, +-898, -656, 510, -96, 1511, 504, 1023, 624, +-309, 84, -1015, -469, -550, -520, 268, -12, +609, 337, 499, 57, 299, -345, 236, -150, +-54, 549, -511, 548, -532, -334, 232, -1037, +921, -587, 876, 455, 87, 1030, -503, 681, +-438, -271, -129, -1069, 184, -1037, 460, -68, +677, 1066, 553, 1235, -81, 164, -795, -1133, +-718, -1232, 239, -112, 1090, 862, 998, 695, +93, -33, -645, -255, -657, -135, -13, -247, +512, -543, 723, -209, 485, 614, -4, 915, +-426, 115, -315, -930, 125, -912, 421, 63, +381, 781, 143, 471, 58, -205, 5, -367, +8, -154, -33, -76, 108, -147, 365, 98, +372, 406, 1, 166, -260, -451, 84, -574, +523, 173, 385, 717, -313, 200, -522, -778, +177, -715, 927, 445, 602, 1012, -427, 114, +-700, -1048, 68, -777, 768, 604, 457, 1080, +-199, -75, -222, -1233, 413, -503, 521, 1017, +-122, 1080, -650, -574, -47, -1537, 929, -393, +834, 1319, -199, 1226, -730, -505, -297, -1451, +523, -514, 674, 814, 129, 836, -231, -100, +73, -600, 321, -259, 142, 203, -124, 121, +-105, -160, 200, -154, 465, 127, 365, 268, +109, 52, -178, -321, -375, -425, -117, -36, +483, 369, 712, 338, 315, 0, -204, -317, +-412, -356, -123, -172, 228, 151, 382, 334, +473, 279, 412, -19, -55, -443, -465, -534, +-329, -125, 214, 525, 696, 640, 588, 60, +62, -685, -325, -653, -349, 82, -171, 578, +326, 247, 708, -210, 655, -192, -36, 114, +-748, -21, -534, -426, 466, -351, 995, 408, +600, 805, -239, 134, -716, -781, -268, -774, +428, 61, 659, 651, 472, 416, 36, -114, +-455, -324, -473, -166, 91, -145, 749, -162, +836, 74, 78, 414, -668, 274, -598, -241, +225, -512, 862, -186, 747, 255, -18, 272, +-588, -87, -462, -204, 116, 4, 757, 199, +647, 57, -66, -276, -514, -402, -227, -56, +319, 437, 594, 461, 162, -36, -273, -507, +2, -461, 339, -38, 243, 285, -95, 311, +-111, 207, 240, 7, 393, -365, -20, -615, +-224, -195, 134, 600, 407, 715, 198, -92, +-341, -796, -248, -453, 521, 429, 739, 638, +-105, -144, -645, -788, -159, -268, 703, 724, +724, 789, -167, -323, -541, -1076, 34, -492, +429, 586, 199, 750, -50, 151, 144, -275, +338, -301, -14, -363, -528, -383, -125, 90, +732, 780, 780, 705, -40, -308, -664, -1070, +-392, -585, 402, 464, 604, 797, 243, 135, +67, -438, 75, -228, -174, 213, -466, 57, +-165, -449, 706, -388, 1044, 309, 219, 805, +-879, 327, -904, -619, 171, -908, 1091, -262, +821, 583, -126, 683, -591, 193, -355, -350, +156, -459, 345, -287, 318, -54, 285, 254, +185, 430, -209, 262, -369, -306, -134, -581, +338, -250, 589, 327, 336, 479, -164, 78, +-390, -372, -195, -428, 239, 45, 545, 447, +328, 278, -83, -296, -239, -536, -155, -101, +124, 399, 361, 351, 267, -84, -25, -242, +-70, -106, -80, -98, -60, -179, 155, -27, +376, 425, 362, 486, -114, -112, -520, -785, +-197, -567, 562, 301, 779, 737, 111, 356, +-620, -298, -495, -483, 294, -249, 636, 71, +305, 118, -143, 83, -151, 184, 37, 175, +-65, -105, -147, -431, 227, -376, 666, 65, +375, 478, -390, 418, -742, -46, -97, -442, +732, -502, 707, -105, 26, 444, -401, 558, +-250, 20, 11, -604, 70, -541, 133, 212, +483, 692, 532, 239, -167, -585, -828, -630, +-523, 134, 604, 752, 1154, 340, 370, -529, +-711, -698, -680, 56, 91, 635, 516, 260, +325, -442, 21, -406, 64, 243, 133, 474, +-194, -108, -376, -608, 28, -268, 528, 446, +489, 573, -30, 23, -414, -455, -192, -471, +197, -90, 258, 272, 67, 392, 35, 232, +173, -100, 154, -415, -165, -436, -294, -23, +1, 459, 371, 465, 387, -55, 31, -463, +-260, -286, -164, 105, 85, 220, 195, 26, +117, -112, 4, -13, 78, 157, 226, 61, +17, -184, -230, -297, -177, -89, 123, 241, +417, 341, 321, 75, -109, -263, -301, -312, +-164, -90, 24, 105, 264, 158, 363, 152, +202, 90, -156, -116, -373, -308, -205, -196, +282, 141, 539, 305, 247, 40, -270, -147, +-403, -22, -33, 25, 361, -193, 296, -216, +28, 157, -182, 393, -154, 120, 70, -329, +247, -343, 161, 37, -90, 213, -196, 82, +15, -52, 416, 33, 254, 84, -346, -129, +-494, -357, 163, -134, 821, 410, 436, 559, +-641, -57, -905, -745, 153, -564, 1053, 351, +614, 825, -588, 345, -910, -505, 106, -765, +841, -168, 279, 495, -482, 471, -246, 55, +338, -144, 390, -236, -183, -447, -417, -264, +-3, 523, 428, 899, 300, 44, -76, -1028, +-249, -776, -137, 460, 71, 981, 124, 221, +182, -596, 141, -526, -43, 8, -211, 344, +-57, 276, 189, -62, 310, -264, -47, -92, +-385, 90, -63, 23, 468, -35, 407, 63, +-224, 150, -559, -17, -218, -270, 387, -244, +545, 138, 205, 401, -245, 190, -381, -262, +-167, -408, 27, -113, 263, 186, 419, 243, +250, 193, -192, 67, -408, -234, -318, -486, +-37, -205, 400, 351, 667, 601, 311, 223, +-499, -396, -844, -709, -245, -250, 631, 594, +780, 637, 166, -133, -508, -612, -419, -141, +92, 401, 121, 133, -84, -361, 192, -226, +504, 367, 177, 337, -507, -114, -765, -298, +-21, -196, 927, -78, 788, 140, -445, 479, +-1034, 146, -176, -497, 809, -447, 616, 265, +-243, 483, -662, -54, -266, -443, 519, -214, +586, 394, -90, 506, -465, -29, -263, -634, +-3, -644, 307, 135, 467, 994, 98, 799, +-367, -527, -446, -1301, -133, -515, 347, 802, +534, 1075, 174, 202, -353, -665, -402, -775, +-110, -123, 173, 494, 236, 443, 275, -10, +135, -177, -181, -70, -476, -136, -367, -242, +269, -33, 827, 464, 412, 458, -574, -326, +-841, -756, -164, -139, 701, 700, 678, 588, +-109, -293, -552, -797, -286, -314, 126, 567, +227, 716, 139, 45, 35, -633, 24, -528, +-136, 66, -280, 377, -53, 424, 394, 220, +307, -282, -255, -632, -443, -342, 28, 335, +522, 679, 194, 427, -493, -426, -447, -853, +325, -238, 670, 662, 75, 707, -674, -191, +-492, -756, 282, -242, 691, 570, 302, 454, +-499, -274, -632, -534, -3, -149, 517, 402, +425, 499, -128, 25, -530, -506, -154, -498, +337, 69, 166, 581, -143, 464, -74, -241, +82, -588, 53, -196, -36, 253, -178, 299, +-122, 110, 152, -61, 312, -162, 76, -199, +-310, -110, -392, 225, 47, 394, 460, -80, +266, -456, -308, -167, -393, 323, 114, 293, +335, -49, -50, -311, -325, -196, -85, 137, +332, 298, 345, 131, -250, -202, -552, -295, +-83, -39, 366, 175, 303, 214, 121, 127, +-186, -151, -503, -385, -228, -122, 393, 344, +463, 356, -15, -57, -365, -429, -272, -218, +130, 256, 282, 281, -143, -47, -284, -215, +249, -75, 326, 135, -131, 158, -437, -123, +-299, -275, 239, 20, 633, 312, 189, 277, +-633, -170, -610, -552, 212, -236, 710, 527, +164, 604, -556, -167, -352, -666, 219, -221, +278, 406, -84, 359, -134, -177, -34, -254, +84, 104, 5, 219, -146, -110, -151, -379, +104, -46, 397, 450, 13, 408, -546, -245, +-380, -685, 262, -206, 542, 620, 322, 591, +-375, -294, -838, -578, -240, -71, 632, 184, +760, 199, 18, 241, -751, 88, -677, -439, +111, -551, 648, 93, 508, 787, -96, 592, +-757, -472, -463, -1037, 356, -370, 517, 821, +101, 1016, -309, -48, -311, -926, 90, -641, +106, 290, -201, 627, 57, 236, 227, -273, +17, -122, -79, 145, -315, -187, -357, -534, +322, 0, 610, 872, -32, 613, -534, -508, +-483, -1027, 134, -283, 581, 644, 198, 714, +-398, 60, -354, -451, 16, -223, 288, -51, +58, -236, -313, -11, 36, 671, 209, 588, +-164, -462, -140, -989, 62, -275, -16, 821, +77, 800, -77, -242, -300, -882, 170, -249, +395, 729, -120, 466, -583, -595, -267, -570, +499, 470, 529, 649, -321, -224, -528, -621, +-47, -92, 242, 500, 249, 287, -277, -310, +-409, -432, 423, 152, 494, 538, -470, 83, +-570, -697, -25, -349, 336, 740, 459, 584, +-61, -631, -504, -745, -47, 422, 44, 821, +-265, -116, 77, -885, 456, -241, 216, 825, +-312, 544, -615, -583, -195, -703, 434, 269, +324, 731, 13, -46, -245, -754, -209, -171, +112, 877, -98, 474, -365, -923, 209, -878, +567, 665, 6, 1203, -466, -172, -446, -1283, +101, -385, 438, 1160, -29, 890, -322, -955, +136, -1297, 262, 530, -148, 1583, -423, 90, +-367, -1583, 287, -679, 676, 1267, 71, 1045, +-493, -843, -467, -1185, -91, 402, 336, 1256, +317, 155, -95, -1241, -91, -724, -128, 843, +-248, 1082, -49, -175, 228, -1013, 232, -297, +-133, 713, -398, 399, -33, -693, 375, -373, +25, 856, -245, 700, -198, -756, -54, -1237, +211, 178, 170, 1428, -176, 537, -97, -1125, +48, -937, -141, 669, -144, 1067, -36, -249, +168, -1281, 390, -220, -13, 1355, -540, 933, +-402, -903, 122, -1515, 355, -29, 363, 1438, +44, 853, -387, -818, -536, -1012, -173, 220, +386, 665, 569, 64, 129, -461, -571, -61, +-627, 464, 79, 138, 709, -463, 262, -322, +-543, 368, -590, 368, 277, -112, 669, -425, +-82, -51, -642, 452, -180, 258, 412, -294, +267, -528, -285, -58, -419, 542, 262, 492, +546, -181, -268, -653, -726, -257, -158, 385, +549, 492, 622, -56, -128, -395, -844, -63, +-363, 210, 600, 108, 406, -199, -399, -203, +-389, 170, 410, 456, 547, 103, -471, -645, +-907, -564, 5, 474, 916, 1024, 649, 15, +-478, -1113, -981, -591, -205, 746, 707, 929, +370, -199, -270, -796, -297, -111, 53, 475, +151, 22, -131, -421, -357, 41, 113, 767, +606, 457, -103, -908, -676, -1448, -153, 299, +588, 2032, 353, 915, -352, -1600, -612, -1794, +-64, 552, 619, 1792, 436, 243, -395, -1356, +-642, -476, 144, 1154, 406, 700, -89, -1052, +-266, -1320, 30, 540, 295, 1793, 110, 520, +-384, -1504, -471, -1451, 213, 682, 444, 1688, +-22, 84, -166, -1643, 87, -490, 34, 1671, +-360, 1049, -405, -1465, 160, -2005, 847, 606, +406, 2566, -650, 911, -878, -2132, -13, -2095, +629, 1052, 220, 2251, -209, 13, 45, -1959, +333, -407, -316, 1743, -919, 772, -361, -1720, +1065, -1529, 1267, 1471, -461, 2331, -1512, -503, +-460, -2789, 944, -675, 719, 2590, -290, 1712, +-601, -1850, 195, -2464, 543, 841, -343, 2762, +-767, 405, 116, -2423, 926, -1463, 231, 1589, +-800, 1742, -542, -663, 613, -1321, 570, 325, +-520, 843, -754, -449, 112, -850, 986, 440, +449, 1176, -914, -12, -928, -1232, 527, -410, +729, 865, -170, 512, -312, -645, 78, -374, +288, 840, -144, 568, -604, -1046, -69, -1180, +763, 807, 345, 1678, -503, 44, -509, -1639, +31, -993, 554, 1183, 122, 1535, -637, -474, +-307, -1633, 549, -171, 487, 1286, -82, 698, +-613, -615, -633, -866, 288, 75, 799, 432, +254, 95, -286, 107, -452, 464, -309, -215, +152, -1190, 331, -443, 183, 1417, 8, 1507, +-183, -818, -26, -2103, -78, -285, -341, 1843, +-59, 1268, 543, -1027, 388, -1605, -251, 183, +-650, 1523, -377, 210, 527, -1248, 634, -340, +-220, 1234, -610, 511, -86, -1353, 466, -1023, +369, 1333, -278, 1730, -642, -690, 41, -2177, +661, -424, 254, 1831, -436, 1441, -388, -750, +192, -1631, 335, -245, -146, 1027, -449, 509, +89, -465, 557, -173, 146, 537, -572, 146, +-434, -853, 195, -653, 400, 638, 1, 1097, +-245, 9, 177, -761, 359, -253, -326, 303, +-913, -187, -87, -497, 1152, 354, 1011, 1271, +-577, 493, -1543, -1357, -435, -1575, 1141, 258, +1001, 1716, -404, 966, -900, -737, -89, -1232, +644, -62, 197, 771, -795, 137, -534, -621, +738, -175, 1077, 947, -199, 868, -1128, -678, +-802, -1682, 438, -409, 1221, 1467, 542, 1441, +-654, -246, -1042, -1413, -167, -686, 634, 578, +783, 685, -26, -9, -769, -128, -445, 88, +342, 17, 498, -354, 25, -322, -239, 346, +-296, 624, -214, -135, 43, -681, 389, -51, +514, 774, -237, 351, -861, -837, -335, -880, +641, 614, 737, 1346, -79, 149, -656, -1285, +-243, -920, 403, 667, 118, 1243, -344, 3, +79, -1038, 473, -296, 103, 837, -634, 414, +-559, -825, 415, -803, 895, 804, -120, 1337, +-1046, -153, -344, -1535, 924, -738, 774, 1023, +-774, 1182, -1029, -197, 319, -856, 1127, -26, +84, 219, -911, -293, -448, -224, 707, 689, +780, 896, -589, -345, -1063, -1530, 276, -579, +1291, 1452, 147, 1489, -1048, -619, -693, -1728, +377, -460, 729, 1335, 132, 1191, -401, -460, +-274, -1251, 19, -416, -34, 706, -64, 819, +160, 202, 349, -518, -42, -769, -518, -312, +-93, 757, 465, 1044, 163, -105, -483, -1306, +-264, -758, 633, 1019, 790, 1580, -606, -185, +-1553, -2008, -78, -1022, 1752, 1647, 1164, 2257, +-1127, -340, -1895, -2658, -250, -1374, 1579, 1809, +1119, 2576, -598, -83, -1161, -2487, -150, -1594, +578, 1386, 160, 2391, -200, 138, 188, -2098, +328, -1403, -268, 1005, -573, 2015, -36, 468, +695, -1636, 438, -1557, -701, 428, -916, 1681, +509, 803, 1351, -668, 124, -1175, -1481, -450, +-1390, 502, 593, 801, 2077, 376, 968, -238, +-1373, -438, -2036, -325, -560, -151, 1392, 8, +1962, 567, 437, 922, -1507, 61, -1805, -1284, +-232, -1414, 1534, 353, 1634, 2219, -27, 1580, +-1629, -1458, -1301, -3012, 511, -551, 1444, 2673, +622, 2441, -702, -735, -1058, -2691, -326, -1190, +613, 1318, 674, 1729, -80, 201, -316, -871, +-130, -573, -69, 109, -274, 21, -171, -285, +394, 156, 853, 874, 381, 555, -965, -575, +-1364, -1311, -120, -478, 1553, 1019, 1375, 1248, +-459, 107, -1716, -1036, -738, -857, 903, 202, +1072, 1058, -308, 281, -891, -847, 226, -536, +890, 570, -99, 959, -1360, -13, -673, -990, +1181, -888, 1546, 394, -304, 1132, -1671, 562, +-483, -377, 1152, -715, 836, -359, -907, -130, +-1069, 190, 811, 561, 1828, 696, -152, 235, +-2455, -754, -1334, -1264, 1823, -454, 2585, 1192, +-226, 1483, -2656, 175, -1424, -1210, 1537, -1207, +2146, 17, -129, 1011, -2176, 885, -1151, -201, +1525, -1008, 2010, -446, -90, 946, -2090, 987, +-1435, -734, 857, -1554, 2087, -316, 833, 1765, +-1151, 1853, -1562, -528, -377, -2671, 874, -1509, +882, 1615, 144, 2824, -289, 619, -314, -2295, +-454, -2203, -442, 537, 300, 2257, 857, 954, +367, -1155, -598, -1447, -836, 118, 48, 1046, +715, 367, 286, -386, -556, -225, -314, 108, +487, -198, 600, -297, -511, 270, -1100, 863, +215, 233, 1538, -953, 560, -960, -1457, 221, +-1658, 1271, 388, 743, 2237, -569, 1190, -1211, +-1680, -443, -2371, 841, -155, 1053, 2133, 0, +1670, -1094, -529, -641, -1821, 701, -1059, 1035, +561, -35, 1380, -1135, 712, -612, -457, 630, +-896, 1082, -552, 262, 215, -792, 782, -924, +461, -97, -300, 854, -764, 687, -272, -26, +536, -496, 591, -512, -235, -189, -609, 206, +-333, 626, 302, 548, 504, -185, 174, -927, +-214, -655, -356, 472, -411, 1128, -186, 479, +608, -719, 959, -1126, 245, -151, -1167, 872, +-1454, 874, 312, -133, 1951, -738, 1020, -334, +-1274, 129, -1807, 96, -157, 46, 1563, 600, +1170, 522, -698, -479, -1468, -1418, -246, -734, +1054, 1381, 722, 2268, -449, 188, -765, -2632, +-178, -2268, 372, 1084, 534, 3149, 152, 1519, +-292, -1944, -487, -3046, -376, -735, 240, 2404, +979, 2772, 485, 60, -878, -2620, -1115, -2357, +-63, 531, 1093, 2603, 998, 1879, -407, -778, +-1287, -2503, -545, -1512, 591, 993, 958, 2304, +418, 1094, -650, -951, -986, -1857, -386, -922, +641, 721, 1337, 1485, 431, 923, -1393, -465, +-1529, -1187, 331, -813, 1857, 251, 1232, 773, +-1219, 602, -2152, 112, 18, -207, 1958, -427, +1021, -576, -1196, -403, -1612, 379, 276, 1107, +1816, 1010, 439, -495, -1683, -1793, -1245, -1206, +903, 910, 1856, 2118, 100, 1008, -1769, -1074, +-909, -2063, 1088, -838, 1081, 1151, -423, 1826, +-954, 651, 89, -1007, 1156, -1449, 206, -583, +-1433, 721, -966, 1206, 988, 539, 1747, -488, +258, -847, -1613, -350, -1566, 86, 307, 236, +1573, 421, 1020, 607, -444, 314, -1269, -844, +-692, -1324, 321, -312, 700, 1327, 567, 1521, +35, 37, -368, -1356, -399, -1116, -426, 183, +-298, 631, 501, 375, 1152, 389, 795, 547, +-964, -127, -2113, -1349, -862, -1384, 1971, 327, +2531, 2101, -13, 1649, -2682, -626, -2040, -2106, +1063, -1386, 2442, 356, 645, 1412, -1560, 1245, +-1164, 527, 728, -551, 1037, -1493, -654, -1558, +-1394, 24, 319, 1900, 1943, 2085, 1248, 318, +-1384, -1853, -2703, -2331, -890, -740, 2100, 1601, +2948, 2477, 601, 1141, -2617, -1229, -3065, -2563, +-77, -1380, 2854, 1024, 2552, 2367, -478, 1419, +-2783, -748, -1785, -2113, 1039, -1330, 2152, 719, +721, 1839, -1055, 922, -1349, -912, -103, -1479, +787, -50, 704, 1256, 186, 765, -441, -947, +-1114, -1528, -547, 51, 1056, 2005, 1857, 1669, +511, -940, -2215, -2763, -2845, -1636, 319, 1495, +3691, 3191, 2904, 1626, -1571, -1638, -4705, -3288, +-2456, -1752, 2925, 1349, 4889, 3203, 1305, 2137, +-3502, -832, -4381, -3202, -489, -2646, 3675, 506, +3517, 3371, -160, 2939, -3188, -608, -2785, -3673, +354, -2604, 2665, 1386, 2073, 3636, -314, 1423, +-1887, -2316, -1775, -2983, -259, 269, 1323, 2950, +1920, 1598, 907, -1652, -1147, -2605, -2529, -374, +-1528, 1889, 1389, 1757, 3329, 192, 1760, -955, +-2008, -1291, -4001, -1213, -1583, -274, 2741, 1553, +4166, 2777, 1043, 1251, -3073, -2388, -3818, -4110, +-672, -1453, 2961, 3098, 3249, 4572, 472, 1167, +-2499, -3192, -2872, -3898, -491, -806, 2205, 2232, +2369, 2625, 218, 985, -1857, -765, -1773, -1421, +161, -1446, 1407, -694, 723, 703, -368, 1919, +-350, 1487, 55, -394, -153, -1973, -702, -1639, +-170, 258, 1283, 1766, 1355, 1380, -779, -391, +-2534, -1566, -1036, -735, 2343, 937, 3091, 1328, +-208, -148, -3602, -1712, -2738, -1151, 1382, 1150, +3959, 2426, 1950, 953, -2046, -1820, -3499, -2790, +-1185, -866, 1799, 1857, 2391, 2622, 917, 1181, +-664, -1016, -1330, -2309, -1395, -2061, -695, -286, +778, 2274, 2095, 3374, 1775, 1122, -648, -2718, +-2891, -3927, -2179, -1070, 902, 2671, 2915, 3350, +1956, 828, -796, -1674, -2492, -2109, -1737, -1151, +341, 60, 1774, 1255, 1809, 2008, 388, 1256, +-1472, -1078, -2277, -2862, -872, -1744, 1767, 1460, +2614, 3076, 629, 1327, -2089, -1668, -2335, -2365, +-146, -553, 1934, 1069, 1488, 1016, -205, 388, +-873, 324, -535, 42, -365, -1147, -500, -1740, +15, -101, 1253, 2182, 1834, 2119, 5, -291, +-2380, -2336, -2566, -1818, 301, 288, 2983, 1592, +2551, 1373, -516, 556, -2724, -445, -2162, -1480, +273, -1748, 1946, -278, 1514, 1902, 318, 2485, +-613, 471, -1218, -1981, -1268, -2471, -279, -493, +1161, 1526, 1729, 1763, 584, 558, -1049, -315, +-1418, -852, -453, -1152, 411, -834, 391, 298, +216, 1381, 805, 1558, 1026, 536, -467, -1160, +-2415, -2314, -1877, -1613, 1057, 909, 3539, 3198, +2272, 2539, -1804, -987, -4014, -3856, -1932, -2863, +2057, 1302, 3630, 3962, 1521, 2302, -1889, -1492, +-2830, -2985, -975, -1172, 1176, 894, 1540, 1068, +733, 291, 75, 635, -399, 1039, -1102, -279, +-1315, -2600, -169, -2380, 1615, 1188, 2133, 4003, +257, 2353, -2205, -2163, -2221, -4144, 282, -1286, +2084, 2582, 1537, 2741, -549, 10, -1648, -1723, +-575, -829, 888, 546, 792, 470, -511, -725, +-1057, -684, 4, 762, 1480, 1502, 1331, 338, +-782, -1242, -2441, -1242, -1438, -167, 1580, 682, +2957, 663, 929, 429, -2002, 214, -2440, -168, +-272, -621, 1568, -857, 1190, -401, -87, 431, +-353, 1131, 125, 1197, -139, 181, -1016, -1341, +-868, -2003, 725, -706, 1700, 1381, 714, 2379, +-931, 1004, -1344, -1202, -333, -1945, 412, -953, +386, 366, 207, 969, 365, 948, 462, 629, +-117, 173, -984, -716, -1095, -1524, 29, -1273, +1168, 300, 1354, 2030, 335, 2085, -1102, 361, +-1506, -1856, -391, -2733, 851, -1433, 1139, 1511, +277, 3442, -520, 2129, -351, -1420, 100, -3619, +-136, -1989, -615, 1401, -201, 2790, 716, 1137, +1087, -868, 179, -1182, -941, -407, -952, -77, +-69, -264, 576, 97, 289, 885, 68, 961, +202, -81, 422, -989, -59, -915, -943, 27, +-988, 498, -96, 347, 1083, 195, 1566, 351, +654, 229, -989, -413, -1983, -1051, -1364, -764, +599, 536, 2295, 1454, 1956, 898, -291, -427, +-2287, -1177, -2086, -797, 37, -132, 1879, 462, +1627, 795, 141, 870, -885, 232, -911, -835, +-457, -1432, -144, -728, 171, 752, 740, 1744, +1068, 1078, 269, -726, -1055, -1856, -1496, -969, +-276, 730, 1265, 1469, 1284, 691, -132, -443, +-1230, -979, -636, -652, 700, 110, 1074, 832, +-148, 802, -1342, -133, -807, -959, 854, -800, +1659, 323, 664, 1093, -1107, 771, -1781, -531, +-635, -1215, 920, -609, 1592, 573, 853, 1142, +-604, 587, -1211, -391, -792, -1039, -87, -707, +542, 187, 866, 906, 712, 790, 201, 122, +-799, -582, -1531, -1137, -694, -691, 1081, 728, +1812, 1838, 712, 832, -1231, -1483, -1721, -2247, +-263, -178, 1309, 2217, 1023, 1888, -400, -701, +-1035, -2400, -69, -1063, 858, 1488, 460, 1811, +-512, -120, -892, -1404, -292, -533, 702, 709, +896, 443, 318, -582, -442, -357, -911, 820, +-790, 790, 165, -650, 1076, -1373, 1173, -141, +182, 1450, -1202, 1057, -1618, -880, -390, -1528, +1376, -48, 1796, 1456, 485, 909, -1370, -810, +-1848, -1376, -491, -144, 1335, 1043, 1672, 811, +347, -107, -1117, -680, -1243, -394, -182, -21, +653, -14, 614, 143, 178, 634, 99, 642, +-55, -300, -565, -1202, -764, -919, -42, 570, +962, 1482, 1033, 702, -121, -670, -1198, -1125, +-762, -410, 424, 374, 929, 482, 253, 196, +-578, 186, -379, 171, 341, -194, 439, -709, +-159, -604, -674, 261, -330, 1025, 593, 673, +865, -320, 63, -847, -657, -567, -687, 51, +-103, 519, 574, 539, 526, 178, -15, -291, +-282, -426, -230, -125, 56, 111, 47, 50, +-179, -66, -94, 86, 258, 411, 357, 340, +133, -319, -287, -806, -506, -407, -37, 344, +254, 768, 115, 529, 62, -39, 220, -455, +185, -692, -106, -613, -622, 70, -621, 968, +220, 1143, 1075, 288, 834, -937, -476, -1483, +-1251, -821, -619, 612, 648, 1725, 1003, 1480, +234, -239, -688, -1955, -610, -1934, 367, 20, +742, 1998, -19, 1912, -923, -56, -719, -1595, +531, -1208, 1414, 48, 620, 514, -979, 280, +-1442, 405, -385, 838, 899, 207, 1091, -1219, +315, -1592, -439, -29, -630, 1706, -394, 1405, +-23, -452, 211, -1395, 371, -472, 336, 587, +23, 368, -210, -365, -74, -202, -251, 662, +-513, 621, -144, -390, 675, -1044, 1044, -397, +285, 684, -912, 822, -1172, -102, -244, -626, +669, -122, 915, 515, 331, 286, -250, -478, +-360, -866, -366, -74, -347, 1004, -168, 1107, +264, 27, 712, -1242, 777, -1353, 51, -111, +-976, 1318, -1306, 1397, -400, 178, 1177, -1078, +1617, -1195, 400, -254, -1146, 535, -1320, 743, +-231, 566, 737, 155, 599, -553, 61, -950, +117, -409, 166, 649, -296, 909, -878, 85, +-437, -625, 689, -298, 1086, 381, 139, 327, +-821, -552, -567, -765, 230, 336, 455, 1231, +-50, 561, -362, -869, -42, -1248, 448, -176, +373, 1000, -215, 809, -488, -244, -268, -704, +96, -148, 307, 395, 301, 225, 203, -293, +-158, -361, -385, 10, -317, 382, 52, 446, +357, 161, 277, -383, -127, -745, -224, -488, +69, 484, 214, 1125, -26, 537, -402, -655, +-424, -1073, 186, -320, 823, 588, 577, 637, +-334, -46, -941, -268, -594, 163, 255, 316, +712, -292, 542, -907, 66, -487, -249, 801, +-244, 1447, -512, 560, -628, -1069, 58, -1772, +1113, -655, 1233, 1257, 121, 1848, -1357, 511, +-1693, -1245, -336, -1566, 1367, -254, 1806, 1075, +510, 946, -1103, -113, -1542, -637, -575, -114, +667, 348, 993, -46, 396, -596, -118, -241, +-104, 631, -146, 855, -499, 63, -689, -873, +-189, -830, 922, 70, 1428, 778, 401, 675, +-1206, -47, -1675, -593, -500, -504, 1102, 38, +1510, 353, 534, 342, -667, -39, -1081, -238, +-585, -48, 165, 138, 641, -77, 535, -289, +201, -77, -156, 449, -342, 538, -400, -179, +-278, -905, 89, -493, 552, 639, 559, 1118, +19, 204, -616, -1120, -592, -1085, 153, 361, +619, 1412, 91, 682, -475, -994, -174, -1369, +537, 86, 564, 1447, -352, 815, -1006, -893, +-437, -1430, 751, -18, 1068, 1470, 173, 998, +-681, -814, -701, -1526, -164, -325, 201, 1205, +362, 1156, 405, -187, 319, -1116, -86, -696, +-730, 345, -708, 804, 115, 354, 812, -373, +651, -485, 47, -7, -508, 378, -675, 167, +-330, -439, 222, -426, 752, 333, 618, 875, +-142, 297, -794, -868, -661, -1177, 177, 30, +860, 1352, 472, 1079, -457, -522, -677, -1416, +-39, -643, 644, 781, 433, 1094, -433, 174, +-804, -684, -54, -677, 847, -45, 685, 537, +-275, 536, -913, 12, -454, -620, 427, -562, +718, 190, 164, 830, -427, 457, -261, -499, +207, -862, 184, -204, -373, 650, -417, 600, +320, -60, 850, -359, 363, -199, -773, -104, +-1026, -113, -49, 102, 993, 478, 739, 379, +-276, -292, -785, -716, -324, -273, 467, 450, +465, 556, -132, 109, -467, -360, -142, -295, +312, -82, 507, 55, 230, 202, -499, 316, +-815, 77, -205, -470, 684, -478, 899, 258, +367, 781, -702, 151, -1116, -817, -329, -619, +750, 538, 937, 1036, 236, -17, -551, -1185, +-634, -716, -22, 849, 282, 1342, 97, 36, +-129, -1438, 101, -1092, 400, 725, 185, 1594, +-379, 475, -708, -1165, -238, -1248, 648, 81, +772, 1174, -20, 670, -550, -488, -278, -744, +96, -20, 17, 448, -216, 41, 94, -354, +688, 48, 451, 544, -586, 88, -976, -667, +-203, -492, 815, 527, 711, 880, -177, -111, +-470, -1040, -83, -513, 95, 775, -84, 999, +-172, 0, 122, -988, 529, -709, 88, 265, +-537, 679, -240, 401, 427, 46, 295, -112, +-481, -496, -684, -747, 375, -234, 1305, 943, +384, 1338, -1218, 177, -1379, -1322, 98, -1505, +1505, -33, 1116, 1440, -533, 1313, -1266, -149, +-397, -1200, 543, -901, 511, 178, -71, 791, +-216, 461, 140, -151, 301, -386, -24, -115, +-499, 183, -464, 166, 111, -240, 640, -318, +518, 6, 17, 409, -486, 448, -624, 28, +-170, -431, 291, -560, 453, -265, 414, 255, +118, 716, -322, 589, -493, -101, -469, -726, +-95, -810, 640, -232, 889, 580, 327, 1030, +-581, 600, -1205, -392, -540, -1187, 792, -906, +1126, 266, 317, 1206, -567, 958, -743, -211, +-171, -940, 322, -716, 228, 1, -16, 421, +13, 421, 290, 284, 242, 167, -407, -126, +-764, -684, -125, -686, 711, 46, 804, 936, +45, 1008, -806, -1, -702, -1158, 213, -1130, +747, 130, 344, 1212, -335, 960, -547, -302, +-7, -1090, 473, -573, 232, 396, -219, 634, +-304, 252, -62, -184, 103, -243, 147, -184, +165, -149, 166, 79, -80, 408, -430, 393, +-411, -271, 123, -771, 746, -266, 501, 749, +-349, 811, -684, -269, -237, -958, 221, -376, +283, 642, 93, 677, 189, -178, 288, -561, +-185, 10, -858, 390, -536, -68, 606, -538, +1173, -99, 445, 731, -876, 636, -1127, -431, +-57, -1037, 867, -355, 600, 683, -190, 885, +-415, 186, -58, -565, 162, -668, -98, -241, +-230, 341, 53, 572, 372, 262, 256, -210, +-140, -356, -330, -191, -156, -29, 25, 24, +94, 162, 196, 348, 169, 247, 54, -270, +-139, -603, -292, -281, -274, 334, 74, 612, +479, 208, 458, -291, -152, -401, -645, -159, +-291, 60, 319, 165, 469, 252, -14, 142, +-272, -162, -89, -315, 227, -60, 123, 237, +-302, 116, -369, -211, 260, -179, 574, 252, +94, 462, -452, -75, -387, -659, 113, -443, +349, 350, 108, 695, -104, 259, 12, -308, +-12, -394, -257, -233, -148, -161, 342, 63, +492, 615, -76, 690, -637, -106, -458, -1071, +363, -898, 846, 368, 237, 1299, -635, 752, +-709, -609, -18, -1168, 515, -366, 520, 657, +134, 719, -304, -17, -537, -463, -269, -206, +283, 228, 547, 199, 216, -228, -291, -296, +-362, 130, 27, 434, 193, 151, -86, -402, +-156, -328, 226, 230, 454, 426, 2, -173, +-674, -599, -505, -71, 462, 798, 877, 672, +75, -507, -808, -1200, -532, -353, 405, 930, +686, 1028, 30, -59, -495, -845, -235, -447, +156, 246, 171, 202, -39, -192, 88, 43, +191, 593, -90, 435, -444, -507, -91, -1023, +353, -351, 256, 692, -107, 907, -161, 282, +154, -340, 128, -566, -422, -546, -545, -273, +283, 369, 1018, 984, 529, 723, -802, -416, +-1211, -1241, -120, -765, 953, 423, 724, 1042, +-94, 642, -400, -157, -209, -655, -189, -606, +-334, -157, 12, 341, 753, 572, 786, 307, +-152, -181, -1065, -399, -843, -253, 296, 3, +1057, 118, 634, 162, -262, 174, -725, 100, +-511, -101, 110, -266, 504, -189, 313, 63, +-44, 215, -235, 185, -78, 32, 109, -119, +-92, -200, -301, -138, 59, 107, 513, 305, +424, 134, -295, -309, -818, -416, -211, 129, +678, 649, 613, 295, -165, -584, -591, -778, +-252, 79, 377, 860, 330, 515, -153, -406, +-196, -651, 79, -70, 137, 322, -144, 63, +-184, -166, 233, 168, 443, 467, -186, -4, +-591, -709, -150, -574, 522, 331, 533, 831, +-121, 341, -525, -434, -276, -529, 244, -81, +225, 134, 25, 32, -9, 102, 218, 378, +35, 266, -565, -351, -564, -740, 396, -279, +1025, 568, 379, 789, -768, 179, -1091, -546, +-62, -671, 922, -191, 730, 405, -162, 565, +-595, 258, -350, -244, -21, -543, 89, -375, +195, 185, 502, 635, 266, 407, -493, -316, +-875, -661, -247, -276, 753, 387, 927, 569, +34, 191, -883, -326, -688, -523, 138, -202, +592, 289, 325, 532, 9, 219, -168, -297, +-306, -502, -304, -185, -12, 301, 372, 349, +477, 79, 28, -147, -538, -102, -406, -68, +138, -135, 436, -87, 216, 183, -208, 393, +-302, 113, 80, -324, 142, -421, -20, -101, +1, 276, 34, 374, -52, 154, -94, -171, +-12, -315, 238, -199, 245, 3, -273, 231, +-421, 318, 65, 139, 440, -216, 246, -430, +-189, -171, -348, 277, 31, 418, 297, 74, +-26, -280, -271, -219, 16, -8, 476, 124, +248, 71, -428, 68, -629, -14, 39, -79, +746, -74, 545, 16, -337, 90, -756, 36, +-235, -18, 486, -125, 603, -58, 52, 114, +-521, 230, -413, 53, 202, -284, 516, -337, +177, 38, -373, 494, -421, 286, 173, -258, +522, -424, 140, -34, -474, 217, -510, 82, +170, -71, 821, 89, 364, 262, -689, -38, +-908, -498, -19, -415, 959, 262, 822, 748, +-358, 391, -1040, -417, -432, -788, 446, -318, +666, 373, 174, 663, -324, 361, -221, -135, +14, -552, -172, -632, -236, -168, 129, 719, +500, 992, 387, 115, -264, -1012, -744, -1025, +-416, 123, 291, 1081, 604, 810, 364, -261, +-134, -899, -488, -596, -451, 193, -97, 698, +348, 508, 561, -124, 171, -577, -439, -400, +-603, 87, -54, 417, 575, 308, 400, -10, +-341, -296, -578, -291, 24, -35, 589, 191, +376, 327, -346, 195, -708, -238, -198, -610, +548, -216, 690, 608, 98, 797, -615, -77, +-620, -995, 58, -670, 591, 531, 414, 1031, +-141, 208, -381, -693, -93, -571, 192, 144, +94, 357, -188, -2, -80, -74, 344, 240, +392, 268, -128, -336, -606, -639, -304, -64, +404, 697, 702, 546, 156, -301, -558, -667, +-456, -148, 218, 544, 427, 378, 9, -370, +-168, -574, 58, 154, 178, 739, 11, 246, +-283, -566, -220, -609, 289, 33, 544, 469, +54, 397, -516, 46, -479, -270, 234, -356, +686, -136, 278, 183, -508, 328, -633, 38, +59, -253, 687, -51, 495, 314, -348, 158, +-781, -458, -320, -609, 534, 109, 826, 948, +205, 758, -725, -445, -890, -1275, -46, -776, +847, 704, 738, 1478, -156, 604, -734, -984, +-528, -1371, 62, -132, 373, 1006, 365, 713, +174, -240, -81, -342, -433, -2, -603, -200, +-133, -426, 581, 138, 762, 851, 87, 452, +-731, -640, -893, -956, -90, -55, 833, 845, +783, 681, -181, -224, -869, -804, -485, -441, +311, 404, 499, 704, 112, 188, -196, -447, +-155, -487, -95, -39, -153, 284, 12, 278, +321, 149, 209, -73, -222, -342, -373, -314, +-64, 104, 328, 435, 284, 258, -222, -215, +-361, -389, 93, -58, 423, 271, 128, 152, +-395, -125, -436, -162, 184, -13, 679, 100, +368, 201, -472, 166, -714, -268, -45, -610, +505, -96, 493, 797, 246, 706, -196, -297, +-683, -941, -391, -533, 465, 348, 785, 835, +234, 586, -480, -302, -512, -909, 114, -580, +407, 462, 38, 911, -242, 211, 126, -575, +446, -460, 46, 118, -488, 249, -374, 155, +128, -19, 566, -279, 517, -78, -139, 448, +-721, 239, -312, -597, 337, -500, 460, 420, +245, 763, -157, 43, -441, -715, -111, -546, +300, 332, 190, 734, -103, 127, -129, -500, +14, -342, 129, 92, 45, 193, -233, 152, +-163, 53, 267, -86, 319, -56, -306, -47, +-484, -219, 182, -64, 517, 469, 28, 357, +-471, -368, -435, -549, 200, 80, 591, 498, +74, 109, -529, -381, -345, -166, 144, 376, +339, 293, 101, -318, -336, -510, -266, -17, +224, 515, 271, 471, -206, -139, -440, -580, +-78, -323, 453, 242, 429, 414, -308, 165, +-737, -110, -217, -268, 608, -165, 560, 103, +-180, 151, -603, -25, -285, -23, 256, 129, +393, 48, 22, -171, -379, -205, -137, 3, +359, 254, 243, 224, -388, -83, -553, -348, +180, -172, 795, 313, 363, 436, -577, -129, +-788, -720, -114, -276, 739, 808, 743, 892, +-128, -364, -734, -1310, -448, -519, 271, 956, +688, 1247, 249, 7, -502, -1131, -338, -771, +314, 331, 287, 801, -174, 271, -203, -335, +136, -272, 417, 136, 53, 56, -463, -344, +-330, -162, 442, 389, 631, 538, -29, 3, +-589, -620, -367, -510, 308, 260, 666, 616, +260, 156, -553, -335, -573, -312, 204, 27, +642, 244, 264, 136, -364, -106, -528, -183, +41, -91, 638, 113, 225, 176, -440, 152, +-286, 19, 112, -329, 157, -449, 116, 72, +89, 707, -49, 465, -181, -379, -243, -800, +12, -247, 336, 633, 209, 591, -225, -159, +-261, -550, 78, -110, 96, 368, -161, 168, +-113, -334, 108, -243, 239, 329, 204, 360, +-278, -123, -647, -424, -94, -166, 556, 329, +375, 322, -139, -208, -384, -384, -109, 196, +64, 479, -215, -110, -191, -642, 453, -181, +587, 632, -217, 561, -771, -300, -492, -733, +312, -205, 711, 564, 260, 521, -445, -166, +-488, -529, 93, -228, 276, 353, -134, 473, +-231, -140, 167, -566, 296, -9, 121, 546, +-229, 67, -537, -442, -180, -111, 526, 402, +497, 210, -133, -349, -406, -429, -126, 117, +147, 554, 12, 320, -67, -381, 222, -637, +215, -36, -111, 562, -285, 313, -218, -271, +274, -278, 464, 86, -43, 312, -379, -83, +-200, -586, 128, -230, 553, 748, 254, 860, +-651, -308, -406, -1087, 426, -576, 389, 493, +61, 941, -158, 476, -205, -435, 35, -875, +124, -243, -19, 467, 81, 428, -4, -64, +49, -182, 142, 8, -39, 225, -180, 36, +-176, -485, -35, -466, 481, 346, 483, 876, +-427, 253, -516, -618, -64, -700, 203, -44, +473, 539, 213, 406, -440, -222, -343, -356, +152, 368, 236, 413, 114, -611, -249, -912, +-220, 400, 263, 1265, 281, 280, -50, -986, +-376, -779, -335, 370, 259, 744, 472, 63, +-105, -563, -115, -277, -103, 530, -340, 597, +51, -432, 370, -980, 48, 33, -88, 1050, +-178, 363, -204, -773, 249, -402, 135, 559, +-320, 393, -191, -713, 249, -646, 366, 688, +-20, 1139, -499, -172, -350, -1284, 158, -455, +389, 820, 361, 755, -194, -373, -516, -689, +-34, 322, 146, 716, -77, -351, 153, -1040, +237, 1, 29, 1171, -203, 711, -434, -826, +-32, -1249, 479, 258, 87, 1350, -266, 174, +71, -1289, 171, -502, 17, 1286, -330, 1011, +-458, -1099, 268, -1660, 774, 470, 206, 1952, +-461, 442, -584, -1629, -100, -1141, 455, 970, +347, 1362, -145, -392, -112, -1300, 174, -61, +81, 1225, -380, 585, -444, -977, 329, -1185, +704, 422, 114, 1440, -352, 250, -318, -1126, +-110, -672, 146, 627, 103, 722, 27, -326, +313, -734, 210, 179, -269, 838, -521, 95, +-148, -756, 389, -493, 462, 466, 4, 520, +-296, -177, -88, -325, 157, 302, -24, 410, +-374, -420, -74, -959, 479, -192, 474, 1345, +35, 1317, -527, -702, -702, -1981, 18, -698, +702, 1480, 420, 1706, -22, -219, -284, -1695, +-392, -698, -157, 974, 115, 915, 229, -347, +259, -793, 19, 94, -131, 736, -122, 69, +-266, -817, -79, -249, 303, 777, 185, 542, +-26, -644, -137, -946, -141, 407, 204, 1322, +82, 206, -528, -1502, -205, -1001, 603, 1089, +425, 1563, -144, -211, -380, -1541, -406, -448, +-106, 956, 321, 652, 451, -514, 217, -537, +-267, 463, -438, 582, -211, -420, -7, -990, +367, 44, 476, 1184, -92, 745, -434, -871, +-213, -1346, 78, 110, 196, 1366, 74, 616, +-179, -947, 140, -881, 282, 446, -210, 789, +-421, -207, -24, -617, 299, 130, 279, 525, +111, 133, -350, -549, -422, -584, 228, 278, +555, 1123, -122, 373, -565, -1178, -7, -1203, +411, 528, 324, 1632, -102, 423, -426, -1227, +-332, -1059, 219, 424, 391, 944, 199, 80, +51, -475, -320, 0, -513, 415, -54, -257, +563, -759, 378, 3, -68, 936, -332, 722, +-256, -580, 80, -1182, 112, -182, -8, 1036, +181, 648, 328, -517, -177, -566, -622, 10, +-122, 302, 599, 159, 466, -8, -365, -186, +-616, -164, 38, 40, 719, 263, 227, 333, +-747, -246, -448, -634, 655, -104, 571, 789, +-484, 438, -605, -690, 295, -674, 788, 615, +-46, 1019, -1121, -667, -471, -1608, 1209, 242, +1212, 2322, -745, 969, -1622, -2336, -215, -2542, +1403, 1198, 917, 3353, -625, 611, -1132, -2778, +-8, -1968, 954, 1296, 300, 2275, -847, 45, +-416, -1938, 793, -663, 542, 1499, -442, 944, +-583, -1189, -194, -1204, 242, 810, 634, 1294, +310, -276, -429, -1160, -543, 102, -309, 853, +252, -195, 783, -1060, 399, 223, -550, 1791, +-932, 371, -182, -2324, 961, -1662, 946, 2060, +-569, 2763, -1308, -689, -148, -3113, 1295, -962, +845, 2534, -845, 2039, -1353, -1476, 168, -2403, +1430, 724, 390, 2332, -1021, -188, -701, -2476, +532, -491, 787, 2665, -250, 1661, -850, -2208, +84, -3016, 1026, 779, 172, 3620, -1113, 1148, +-681, -2924, 951, -2471, 1170, 1420, -536, 2630, +-1401, -113, -54, -2029, 1308, -581, 657, 1614, +-928, 940, -1140, -1412, 436, -1554, 1266, 839, +26, 2201, -1069, 272, -249, -2004, 771, -1465, +330, 1096, -605, 1731, -615, -185, 597, -1216, +1022, -86, -342, 862, -1279, -98, -218, -942, +1107, -99, 736, 1037, -571, 652, -961, -761, +165, -948, 868, 318, 56, 945, -818, -103, +-341, -1025, 855, -218, 779, 1246, -555, 1066, +-1321, -994, -60, -1954, 1320, -50, 873, 2048, +-750, 1142, -1401, -1184, -34, -1586, 1293, 241, +733, 1435, -812, 221, -927, -1114, 121, -609, +752, 815, 347, 918, -377, -215, -326, -786, +30, -316, 183, 185, -196, -54, -78, 216, +486, 831, 482, 462, -504, -882, -1054, -1552, +15, -179, 1095, 1560, 784, 1416, -713, -461, +-940, -1441, 125, -548, 593, 607, -19, 609, +-289, -320, 320, -211, 430, 762, -359, 539, +-876, -878, 37, -1395, 977, -15, 387, 1408, +-726, 1168, -516, -309, 491, -1060, 575, -633, +-487, -229, -968, 150, 373, 939, 1510, 1340, +383, 82, -1666, -2011, -1384, -1879, 794, 805, +2065, 2666, 514, 1146, -1706, -1685, -1560, -2142, +725, 20, 1764, 1704, 238, 848, -1276, -690, +-815, -774, 646, 155, 897, 362, 50, -191, +-790, -116, -482, 424, 292, 85, 574, -744, +339, -254, -159, 967, -531, 917, -656, -774, +41, -1798, 1018, -188, 910, 2079, -575, 1579, +-1429, -1192, -425, -2343, 968, -466, 1230, 1849, +38, 1753, -1306, -532, -909, -1782, 801, -684, +1179, 956, -72, 979, -1017, -104, -570, -563, +622, -211, 887, 150, -44, 67, -770, -4, +-649, -33, 318, -16, 1003, 178, 345, 224, +-796, -48, -921, -627, 3, -484, 1205, 572, +908, 1229, -851, 147, -1470, -1433, -126, -1247, +1201, 736, 1163, 1998, -162, 638, -1337, -1796, +-973, -1967, 374, 570, 1228, 2484, 933, 1041, +-323, -1723, -1361, -2011, -950, 119, 452, 1634, +1507, 1014, 1011, -210, -812, -779, -1783, -710, +-581, -553, 1210, 45, 1687, 1314, 176, 1575, +-1493, -234, -1238, -2345, 162, -1797, 1005, 1021, +1075, 2721, 395, 1309, -877, -1501, -1431, -2338, +-868, -675, 984, 1325, 2318, 1465, 899, 414, +-1961, -479, -2461, -797, 32, -811, 2435, -234, +1828, 791, -1267, 1173, -2250, 222, -80, -1011, +1833, -832, 865, 278, -1130, 692, -1408, 40, +310, -505, 1588, -147, 658, 647, -903, 697, +-1275, -430, -197, -1303, 694, -631, 761, 984, +481, 1565, -136, 316, -1016, -1238, -874, -1408, +475, 82, 1160, 1310, 337, 778, -853, -712, +-710, -939, 662, 429, 1006, 1116, -581, -58, +-1648, -1589, -214, -989, 2009, 1304, 1651, 2106, +-1111, 306, -2546, -1957, -675, -1944, 2001, 253, +1891, 2082, -671, 1379, -1927, -767, -299, -1522, +1452, -542, 815, 667, -1127, 813, -1471, -12, +449, -582, 2082, -183, 1026, 633, -1713, 443, +-2396, -591, 23, -1079, 2464, 29, 1758, 1335, +-1211, 892, -2459, -847, -320, -1495, 2281, 116, +1344, 1626, -1777, 545, -2279, -1754, 964, -1330, +3068, 1542, 587, 2549, -2816, -245, -2413, -3228, +1227, -2090, 3012, 1995, 815, 3912, -2131, 889, +-1615, -3321, 745, -3474, 1146, 606, -176, 3679, +-629, 2140, 439, -1555, 871, -2982, -409, -929, +-1542, 1770, -266, 2070, 1555, 117, 1254, -1655, +-727, -1307, -1632, 404, -418, 1528, 1165, 720, +1026, -973, -42, -1323, -718, 25, -703, 1328, +-418, 781, 378, -689, 1264, -1124, 1035, -81, +-729, 775, -2294, 498, -1013, -114, 1950, -269, +2589, -257, -99, -321, -2568, 13, -1851, 675, +1221, 660, 2458, -389, 299, -1127, -1859, -472, +-1161, 922, 1033, 1285, 1468, 6, -315, -1366, +-1754, -1108, -372, 525, 1636, 1509, 1291, 774, +-887, -814, -1812, -1529, -368, -559, 1370, 1049, +1384, 1514, -201, 294, -1435, -1139, -904, -1318, +494, -283, 1206, 959, 656, 1409, -550, 547, +-1253, -1013, -468, -1759, 827, -592, 1142, 1315, +180, 1891, -1114, 386, -995, -1456, 430, -1732, +1254, -236, 274, 1409, -928, 1530, -840, 40, +492, -1251, 991, -1021, -32, 7, -860, 629, +-400, 696, 527, 526, 635, -252, -82, -994, +-675, -803, -279, 416, 456, 1164, 489, 758, +-37, -593, -531, -1320, -422, -503, 98, 896, +786, 1095, 688, 249, -585, -627, -1390, -997, +-360, -743, 1318, 548, 1468, 1770, -242, 1135, +-1883, -1286, -1162, -2641, 1279, -745, 1860, 2316, +0, 2821, -1629, -118, -1022, -2986, 842, -2270, +1443, 1084, -58, 2788, -1347, 1043, -341, -1248, +869, -1525, 606, -409, -465, 314, -696, 486, +264, 787, 781, 759, -196, -294, -966, -1650, +37, -1115, 1163, 869, 546, 1915, -1199, 569, +-1342, -1026, 772, -1212, 1950, -299, 234, 333, +-1938, 548, -1516, 709, 1031, 639, 2450, -380, +544, -1676, -2163, -1330, -2071, 1035, 527, 2561, +2459, 1060, 1430, -1761, -1145, -2604, -2313, -522, +-823, 2020, 1395, 2164, 1914, 36, 286, -1732, +-1406, -1454, -1270, 25, 185, 1052, 1074, 1044, +448, 175, -490, -509, -382, -677, 392, -343, +296, -145, -564, 326, -742, 783, 347, 706, +1186, -196, 404, -1260, -922, -1077, -1108, 340, +3, 1614, 944, 1003, 819, -568, 66, -1413, +-662, -698, -1106, 418, -702, 808, 1120, 553, +2185, 185, 510, -303, -2412, -797, -2697, -613, +482, 193, 3579, 723, 2320, 619, -2011, 236, +-3762, -231, -748, -794, 2676, -1047, 2411, -253, +-529, 1307, -1918, 1897, -622, 403, 734, -1938, +237, -2346, -377, -214, -25, 2161, 794, 2174, +842, 305, -392, -1640, -1498, -2047, -1127, -1103, +495, 872, 1902, 2595, 1768, 2126, -427, -706, +-2821, -3343, -2359, -2577, 1070, 798, 3828, 3645, +2175, 2796, -2310, -992, -4159, -3702, -959, -2463, +3268, 1213, 3354, 3072, -414, 1772, -3257, -832, +-2062, -2156, 1221, -1386, 2534, 244, 923, 1546, +-1191, 1316, -1534, -107, -545, -1448, 501, -1113, +1157, 713, 1083, 1655, -167, 309, -1658, -1816, +-1627, -1773, 503, 949, 2570, 3159, 1819, 1538, +-1508, -2603, -3432, -3963, -1287, -676, 2581, 3547, +3761, 3892, 578, 174, -3364, -3514, -3688, -3508, +-19, -262, 3652, 2677, 3592, 3137, -196, 1166, +-3716, -1591, -3530, -3353, 176, -2402, 3635, 1075, +3527, 4101, -112, 3046, -3513, -1513, -3379, -4582, +79, -2500, 3225, 2270, 3012, 4251, -49, 1237, +-2598, -2813, -2599, -3303, -411, 134, 1976, 3090, +2650, 2187, 930, -1360, -1824, -3013, -3069, -1120, +-1170, 1854, 2233, 2676, 3494, 820, 889, -1645, +-2949, -2577, -3537, -1253, -156, 1192, 3265, 2682, +3115, 1859, -309, -537, -3202, -2593, -2476, -2483, +531, -401, 2395, 2188, 1860, 3116, 110, 1458, +-1442, -1597, -1839, -3574, -1011, -2368, 800, 936, +2259, 3607, 1633, 3025, -789, -268, -2517, -3299, +-1632, -3241, 1060, -339, 2378, 2722, 949, 3175, +-1175, 636, -1524, -2255, -325, -2685, 727, -438, +684, 1932, 214, 1860, 98, -279, -446, -1709, +-1098, -738, -366, 1084, 1364, 1565, 1852, -153, +-254, -1878, -2627, -1438, -1964, 775, 1440, 2081, +3215, 1209, 1286, -500, -1885, -1433, -2713, -1408, +-1021, -817, 1170, 476, 1990, 2257, 1544, 2656, +273, 133, -1621, -3457, -2882, -4129, -1528, -238, +2031, 4419, 4223, 4730, 1801, -92, -2843, -4685, +-4506, -4118, -1187, 472, 3230, 3614, 3511, 2802, +175, 14, -2373, -1863, -1668, -1858, -46, -819, +558, 197, 358, 1179, 774, 1790, 1286, 1059, +74, -992, -2169, -2462, -2426, -1618, 585, 798, +3501, 2588, 2331, 2088, -1880, -455, -3746, -2873, +-1169, -2417, 2432, 627, 2818, 2950, 164, 2019, +-1900, -780, -1254, -2289, -44, -1308, 200, 349, +251, 945, 1066, 921, 1341, 896, -87, 301, +-2279, -1243, -2294, -2143, 575, -960, 2966, 1671, +2174, 2950, -849, 1118, -2520, -1888, -1738, -2905, +393, -1021, 1606, 1408, 1336, 2047, 409, 1173, +-554, -92, -1127, -1092, -1098, -1847, -194, -1394, +889, 673, 1240, 2668, 495, 2044, -282, -762, +-514, -2603, -724, -1700, -1026, 478, -476, 1515, +1217, 939, 2534, 437, 1387, 360, -1999, -548, +-3948, -2100, -1569, -1830, 2936, 914, 4407, 3497, +1014, 2319, -3369, -1677, -3738, -3915, -94, -1668, +2811, 2087, 2057, 2911, -196, 661, -1240, -1534, +-628, -1204, -338, 155, -448, 125, 57, -698, +1226, -132, 1388, 1802, -111, 1809, -1800, -904, +-1616, -3065, 354, -1567, 1832, 1839, 1394, 3030, +-289, 776, -1696, -2045, -1270, -2083, 567, -25, +1502, 1395, 641, 862, -863, -286, -1135, -319, +301, 230, 1356, -48, 284, -704, -1597, -461, +-1394, 464, 975, 867, 2448, 445, 920, -475, +-1963, -791, -2524, -161, -252, 387, 2016, 228, +2008, -173, 106, -128, -1377, 319, -1371, 574, +-482, 107, 462, -916, 1096, -1166, 903, -35, +-137, 1387, -717, 1494, -537, 40, -85, -1307, +-200, -1528, -206, -399, 539, 771, 1354, 1335, +668, 1042, -1087, 122, -1980, -1172, -814, -1651, +1298, -760, 1935, 708, 601, 1709, -848, 1347, +-1166, 152, -601, -1270, -64, -1935, 362, -1372, +835, 700, 870, 2673, 8, 2304, -988, -510, +-1012, -2968, 71, -2370, 734, 415, 286, 2369, +-231, 1847, 282, -39, 557, -1307, -60, -1171, +-1054, -407, -1013, 260, 289, 607, 1333, 603, +925, 275, -348, 16, -836, -234, -371, -643, +21, -717, -280, -95, -293, 846, 674, 1059, +1419, 185, 630, -791, -1187, -823, -1932, -23, +-772, 459, 1023, 46, 1639, -411, 1048, 315, +-49, 1097, -1025, 477, -1524, -1186, -1155, -1749, +289, -385, 2010, 1554, 2242, 1937, 130, 323, +-2271, -1435, -2530, -1592, -397, -385, 1934, 772, +2197, 1002, 588, 709, -1104, 74, -1569, -564, +-874, -1003, 306, -757, 1074, 193, 891, 1240, +110, 1287, -728, -92, -637, -1507, 41, -1417, +393, 334, 110, 1710, -300, 1043, -269, -825, +338, -1519, 646, -352, 214, 975, -380, 921, +-705, 67, -657, -480, 15, -669, 923, -703, +1174, 91, 344, 1259, -971, 1409, -1491, -181, +-533, -2160, 811, -1800, 1183, 904, 570, 2698, +-57, 1232, -512, -1458, -873, -2117, -842, -450, +26, 1190, 1170, 1025, 1410, -3, 117, -259, +-1301, 23, -1210, -314, 73, -796, 800, -223, +455, 1098, -82, 1075, 27, -415, 307, -1413, +-142, -490, -768, 1041, -442, 1066, 353, -285, +549, -1147, 280, -439, 73, 604, 87, 817, +-177, 145, -729, -382, -824, -414, 181, -299, +1330, -195, 1201, 297, -222, 811, -1445, 574, +-1147, -365, 33, -1183, 955, -779, 1061, 523, +463, 1326, -513, 656, -993, -632, -735, -1099, +134, -303, 939, 609, 718, 523, -135, -129, +-594, -259, -296, 128, -22, 220, 45, -197, +144, -385, 298, -2, 125, 398, -265, 150, +-370, -257, -27, -207, 492, 248, 499, 426, +-346, -108, -1009, -668, -331, -510, 828, 399, +1164, 952, 356, 493, -1064, -549, -1487, -893, +-279, -396, 1189, 306, 1441, 589, 333, 439, +-1115, 48, -1334, -238, -121, -348, 909, -415, +748, -304, -104, 240, -456, 849, 21, 659, +320, -317, -242, -901, -723, -577, -246, 162, +874, 443, 1081, 289, -138, 304, -1162, 426, +-734, -160, 281, -1154, 845, -1021, 462, 497, +-236, 1630, -529, 913, -101, -770, 87, -1360, +86, -303, 113, 615, 41, 374, -127, -290, +-43, 73, 74, 796, 126, 462, 39, -959, +-258, -1423, -247, -219, 178, 1269, 366, 1339, +106, 166, -206, -819, -289, -920, -71, -640, +110, -85, 240, 824, 249, 1380, -85, 592, +-487, -960, -288, -1616, 245, -622, 674, 791, +377, 1171, -549, 600, -856, -152, -128, -490, +657, -678, 616, -772, 76, -184, -319, 1093, +-349, 1614, -279, 334, -189, -1525, 106, -1894, +603, -200, 792, 1754, 11, 1696, -1031, -208, +-988, -1602, -17, -1017, 908, 537, 1044, 1058, +180, 240, -803, -576, -684, -334, -46, 336, +64, 327, 52, -360, 236, -539, 583, 179, +669, 750, -257, 352, -1415, -624, -1151, -933, +515, -36, 1622, 1190, 1188, 925, -325, -657, +-1376, -1596, -932, -528, 13, 1276, 421, 1546, +573, 15, 812, -1477, 608, -1208, -474, 282, +-1577, 1283, -1286, 803, 532, -316, 1916, -877, +1342, -500, -462, 294, -1599, 507, -1182, 64, +182, -292, 1094, 4, 917, 321, -40, 131, +-588, -348, -416, -533, 20, -76, 53, 557, +-77, 651, 10, -10, 295, -704, 303, -528, +-24, 293, -295, 610, -241, 71, -57, -541, +12, -276, -16, 461, 213, 673, 484, -107, +173, -877, -471, -642, -691, 324, -145, 953, +532, 561, 534, -202, -82, -655, -218, -627, +7, -199, 10, 322, -296, 660, -278, 525, +229, 150, 556, -490, 86, -818, -414, -633, +-206, 127, 391, 980, 217, 1131, -508, 242, +-750, -1026, 90, -1404, 1147, -437, 1032, 910, +-277, 1241, -1490, 364, -1216, -496, 228, -553, +1355, -240, 1340, -284, 258, -323, -1064, 343, +-1466, 1123, -535, 761, 642, -527, 1047, -1360, +707, -869, 130, 422, -460, 1148, -737, 755, +-791, -80, -375, -573, 659, -686, 1386, -436, +917, 132, -458, 717, -1429, 696, -1185, -3, +-1, -603, 1059, -455, 1152, -68, 439, 131, +-293, 202, -833, 330, -954, 231, -440, -176, +432, -500, 1008, -275, 955, 290, 324, 502, +-683, 37, -1463, -444, -1231, -281, 334, 346, +1979, 396, 1792, -67, -347, -387, -2074, -217, +-1634, 93, 347, 231, 1614, 149, 1018, 39, +-191, 70, -770, -73, -481, -311, -93, -413, +31, -22, 155, 612, 443, 887, 236, 50, +-324, -1104, -381, -1154, 145, 282, 449, 1385, +-84, 812, -760, -626, -308, -1041, 774, -192, +904, 586, 2, 350, -921, -340, -697, -283, +180, 348, 429, 606, 225, -89, 316, -748, +317, -617, -220, 180, -850, 776, -791, 698, +298, -7, 1283, -766, 896, -770, -524, -56, +-1313, 651, -615, 601, 596, 51, 930, -387, +266, -255, -415, 70, -461, 33, -130, -303, +200, -184, 236, 427, 72, 770, -92, 198, +-169, -688, -173, -969, 103, -302, 394, 640, +201, 1014, -275, 549, -474, -374, -280, -1119, +295, -896, 639, 385, 380, 1283, -260, 667, +-704, -643, -512, -898, 159, -50, 686, 625, +688, 172, -41, -486, -772, -300, -633, 459, +128, 601, 533, -70, 439, -580, -39, -369, +-325, 88, -161, 186, -9, 205, -93, 298, +45, 231, 308, -231, 135, -658, -232, -465, +-248, 236, 127, 838, 381, 542, -63, -200, +-697, -816, -291, -488, 867, 225, 940, 584, +-331, 207, -1247, -170, -672, -157, 679, 108, +1134, 35, 278, -341, -587, -318, -558, 252, +-143, 602, -52, 256, 91, -382, 505, -589, +648, -117, -74, 364, -912, 264, -717, -24, +263, 62, 819, 143, 416, -248, -293, -591, +-314, -159, 70, 727, -98, 836, -389, -171, +-137, -1120, 534, -658, 662, 650, 47, 1089, +-571, 107, -534, -729, -159, -525, 140, 130, +373, 242, 480, 108, 328, 174, -224, 303, +-858, -95, -641, -742, 216, -509, 825, 519, +730, 1020, 34, 219, -684, -813, -680, -827, +-149, 133, 282, 775, 439, 442, 306, -346, +72, -487, -101, -28, -263, 252, -455, 56, +-287, -20, 243, 128, 625, 49, 547, -351, +-170, -386, -639, 258, -373, 796, -8, 394, +179, -708, 171, -1163, 205, -306, 396, 1174, +267, 1507, -577, 65, -1051, -1637, -300, -1526, +791, 270, 1148, 1703, 426, 1291, -734, -403, +-974, -1503, -343, -958, 282, 474, 495, 1056, +444, 454, 265, -354, -88, -377, -506, -46, +-601, 14, -216, -180, 364, -91, 694, 288, +420, 351, -41, 30, -461, -243, -645, -192, +-450, -74, 296, -23, 869, -36, 661, 97, +-149, 347, -842, 320, -638, -161, 87, -617, +511, -417, 393, 191, 96, 528, -103, 331, +-81, 56, -221, -76, -373, -314, -103, -596, +362, -421, 516, 474, 205, 1183, -287, 684, +-456, -792, -196, -1479, -2, -471, 148, 997, +372, 1092, 312, 6, -12, -583, -344, -204, +-537, -6, -199, -367, 433, -327, 592, 514, +200, 1089, -373, 268, -539, -1147, -108, -1196, +400, 305, 273, 1329, -114, 619, -303, -673, +-68, -925, 338, -74, 326, 582, -159, 414, +-463, -68, -355, -237, 59, -236, 652, -200, +571, 83, -141, 439, -621, 368, -590, -146, +-134, -553, 520, -423, 693, 104, 270, 625, +-276, 460, -599, -154, -463, -483, -38, -311, +415, -58, 605, 154, 312, 375, -187, 301, +-530, -31, -599, -304, -196, -343, 587, -267, +878, 40, 259, 574, -695, 717, -931, -51, +8, -962, 917, -792, 488, 331, -698, 1055, +-784, 456, 466, -566, 1214, -636, 181, 72, +-1376, 304, -1237, -137, 641, -164, 1736, 439, +653, 569, -1061, -290, -1236, -1057, -64, -445, +686, 893, 494, 1161, 13, -89, -40, -1124, +-5, -657, -316, 425, -465, 696, 68, 182, +567, -181, 303, -156, -195, -66, -264, -245, +-29, -243, -25, 207, -117, 674, -26, 364, +399, -511, 390, -822, -306, -179, -779, 643, +-108, 641, 826, -37, 581, -547, -413, -284, +-885, 261, -192, 223, 700, -227, 650, -244, +-124, 251, -519, 492, -347, 98, -41, -557, +200, -587, 377, 63, 374, 662, -37, 450, +-588, -165, -585, -467, 181, -211, 678, 75, +326, 106, -231, 72, -354, 160, -103, 156, +44, -74, -46, -292, 64, -181, 316, 71, +161, 136, -345, 36, -325, 122, 226, 251, +369, 38, -194, -523, -601, -665, 74, 168, +888, 1005, 493, 647, -736, -589, -1172, -1068, +-56, -221, 1152, 864, 867, 698, -386, -411, +-940, -798, -370, 46, 388, 846, 465, 367, +38, -755, -157, -901, 14, 225, 25, 1077, +-147, 521, -142, -615, 20, -819, 123, -41, +154, 564, 110, 261, -34, -311, -275, -206, +-235, 340, 138, 427, 391, -244, 96, -705, +-361, -341, -283, 455, 229, 764, 415, 289, +45, -400, -369, -582, -379, -283, -54, 34, +384, 306, 503, 481, 183, 350, -328, -131, +-758, -607, -454, -618, 505, 8, 978, 677, +368, 608, -587, -16, -821, -410, -131, -304, +463, -122, 188, -158, -87, -6, 248, 502, +489, 725, -178, 55, -986, -929, -727, -995, +633, 155, 1374, 1157, 406, 825, -955, -374, +-952, -1033, 79, -441, 605, 474, 190, 624, +-212, 37, 108, -255, 438, -102, -70, -63, +-789, -146, -548, -10, 550, 374, 984, 402, +175, -202, -814, -805, -616, -487, 329, 693, +692, 1230, -50, 220, -639, -1246, -190, -1233, +525, 217, 503, 1352, -142, 917, -590, -399, +-300, -1051, 284, -517, 289, 278, 39, 462, +-1, 233, 54, 78, 33, 132, -233, -67, +-365, -558, -97, -602, 417, 136, 509, 904, +190, 716, -294, -269, -643, -951, -475, -542, +205, 336, 801, 594, 647, 229, -184, -108, +-812, -95, -533, -74, 16, -254, 519, -377, +600, 104, 173, 728, -313, 631, -559, -424, +-475, -1158, 105, -486, 814, 961, 648, 1302, +-300, -63, -958, -1404, -556, -984, 550, 663, +963, 1403, 210, 457, -621, -852, -594, -1074, +-126, -161, 294, 674, 405, 642, 362, 151, +75, -158, -457, -371, -753, -511, -228, -244, +677, 388, 936, 717, 194, 374, -777, -329, +-814, -687, -36, -407, 468, 173, 473, 440, +215, 314, -8, 185, -266, -26, -490, -390, +-367, -606, 217, -193, 729, 463, 526, 793, +-327, 424, -789, -467, -316, -993, 387, -496, +486, 606, 98, 1022, -221, 220, -189, -768, +-16, -653, 90, 269, 39, 631, 46, -10, +-60, -558, -161, -193, -17, 516, 241, 490, +336, -203, -95, -588, -590, -259, -382, 278, +395, 408, 721, 108, 119, -121, -535, -139, +-440, -90, 179, -81, 269, -1, -48, 72, +-175, 23, 212, 100, 427, 303, -48, 103, +-732, -536, -531, -726, 484, 83, 964, 1002, +236, 823, -775, -417, -738, -1207, 186, -519, +688, 696, 179, 849, -419, 23, -210, -490, +378, -145, 327, 170, -453, -160, -707, -351, +109, 167, 967, 647, 659, 250, -603, -397, +-1249, -549, -303, -207, 996, 264, 1072, 548, +-150, 389, -1051, -341, -548, -819, 407, -169, +575, 781, 95, 583, -143, -443, -64, -686, +-20, 26, -231, 503, -253, 180, 169, -185, +488, -93, 292, 80, -190, -82, -580, -282, +-487, -91, 299, 379, 819, 605, 354, 123, +-486, -730, -787, -1015, -146, -39, 630, 1280, +581, 1190, -126, -384, -540, -1534, -380, -894, +159, 620, 607, 1280, 339, 568, -382, -443, +-695, -855, -186, -624, 579, 105, 723, 867, +8, 840, -689, -308, -601, -1132, 48, -460, +639, 807, 584, 832, -52, -220, -650, -684, +-595, -264, 245, 234, 697, 389, 148, 228, +-372, -174, -196, -350, 105, -66, 44, 222, +-80, -58, -101, -211, 176, 330, 293, 678, +-80, -262, -419, -1186, -128, -335, 251, 1155, +243, 944, 99, -549, -193, -1016, -246, -91, +-25, 627, 249, 393, 6, -211, -120, -524, +190, -45, 169, 615, -333, 381, -427, -571, +152, -734, 526, 179, 425, 868, -274, 373, +-843, -667, -337, -749, 714, 283, 725, 889, +-41, 98, -497, -764, -565, -446, -156, 314, +526, 451, 624, 359, 24, 89, -387, -588, +-442, -804, -382, -15, 189, 823, 851, 822, +622, 163, -569, -759, -1067, -1130, -406, -296, +650, 977, 1159, 1153, 311, 115, -1007, -880, +-914, -803, 168, -73, 622, 444, 464, 501, +193, 255, -378, -62, -628, -380, -159, -387, +320, -102, 430, 257, 369, 388, -229, 225, +-622, -185, -291, -446, 340, -147, 568, 277, +135, 323, -433, 33, -429, -321, 140, -376, +403, 208, 24, 677, -201, 102, -50, -729, +57, -562, 100, 427, -4, 796, -225, 79, +-152, -696, 306, -404, 363, 433, -46, 508, +-494, -205, -405, -535, 283, -34, 676, 414, +88, 342, -478, -134, -238, -347, 32, -210, +82, 68, 79, 122, 128, 188, 204, 329, +-71, -43, -455, -532, -161, -369, 368, 205, +273, 432, -71, 270, -271, -57, -78, -331, +306, -225, 161, 76, -394, 22, -301, -39, +247, 298, 450, 457, 140, -263, -251, -851, +-483, -162, -111, 827, 408, 493, 378, -456, +-119, -529, -355, 111, -8, 379, 280, 88, +47, -254, -395, -244, -173, 188, 483, 344, +436, -88, -321, -434, -517, -33, 10, 484, +298, 221, 172, -384, -70, -501, -143, 41, +-5, 569, 95, 494, -13, -253, -111, -710, +-54, -246, 35, 417, 124, 389, 65, 16, +-109, -80, -104, -57, 155, -75, 32, -216, +-420, -227, -83, 107, 657, 635, 295, 467, +-546, -446, -382, -879, 64, -146, 200, 599, +334, 404, 43, -96, -275, -78, -77, 19, +58, -160, -51, -376, -22, -115, 47, 446, +252, 566, 189, -11, -413, -546, -453, -425, +350, 137, 501, 472, -22, 105, -337, -359, +-339, -70, 70, 526, 533, 86, 229, -751, +-461, -421, -382, 710, 199, 672, 381, -325, +-104, -590, -235, -48, 109, 291, 197, 241, +-38, 1, -210, -391, -244, -152, -111, 331, +386, 296, 585, -41, 98, -122, -839, -313, +-838, -380, 254, 244, 1051, 729, 610, 315, +-371, -407, -972, -600, -560, -459, 538, 176, +822, 888, 123, 633, -503, -545, -277, -833, +241, -78, 102, 246, -401, 217, -128, 287, +639, 273, 444, -197, -309, -553, -781, -499, +-179, 267, 808, 948, 475, 409, -582, -826, +-431, -851, 382, 303, 351, 814, -53, 174, +-330, -450, -282, -366, 229, 10, 494, 329, +27, 179, -375, -252, -170, -12, 161, 387, +63, -245, -227, -826, 180, 165, 377, 1291, +-168, 337, -415, -1226, -148, -916, 222, 658, +360, 979, -76, -5, -384, -559, 137, -275, +285, 170, -368, 224, -384, -104, 311, -282, +638, 226, 62, 526, -775, -129, -562, -789, +449, -206, 729, 830, 195, 509, -461, -639, +-620, -715, 54, 405, 402, 804, 111, -31, +201, -851, 87, -437, -531, 703, -200, 786, +366, -295, 112, -880, 35, -40, 60, 672, +-200, 165, 20, -524, 266, -83, -44, 596, +-377, 74, -117, -709, 417, -317, 521, 595, +-139, 619, -536, -180, -259, -738, 127, -314, +337, 696, 178, 631, -68, -567, 120, -866, +-125, 493, -698, 1115, -126, -332, 617, -1350, +598, -65, 20, 1477, -726, 578, -710, -1282, +307, -1074, 656, 860, 138, 1301, -170, -275, +-354, -1278, -40, -263, 98, 1053, -333, 658, +-5, -774, 806, -955, 300, 546, -845, 1263, +-782, -207, 176, -1604, 1010, -450, 562, 1710, +-676, 1334, -840, -1221, 190, -2023, 685, 244, +93, 2098, -522, 693, -57, -1582, 704, -1251, +180, 978, -756, 1482, -543, -452, 499, -1689, +999, -200, 136, 1836, -1059, 1050, -601, -1500, +768, -1791, 777, 707, -162, 1981, -704, 170, +-399, -1689, 550, -775, 742, 1307, -305, 1090, +-672, -863, 61, -1407, 292, 333, -21, 1534, +-80, 274, 135, -1345, 104, -657, -150, 1021, +-391, 735, -172, -862, 420, -846, 431, 766, +-344, 1270, -529, -317, 168, -1649, 373, -493, +-177, 1413, -376, 1222, 10, -664, 408, -1351, +346, -86, -304, 1174, -729, 373, -232, -1083, +872, -568, 822, 1182, -542, 1027, -1113, -1083, +78, -1586, 959, 512, 361, 1811, -452, 248, +-553, -1548, 185, -808, 642, 963, -21, 1196, +-648, -396, 34, -1381, 687, -243, 317, 1399, +-523, 824, -703, -1143, 247, -1188, 954, 705, +187, 1438, -850, -441, -370, -1583, 669, -1, +413, 1917, -711, 610, -427, -1778, 717, -1496, +548, 1055, -420, 1972, -747, -29, -121, -1630, +565, -792, 473, 1081, -504, 951, -491, -692, +547, -1056, 407, 606, -758, 1403, -903, -354, +598, -1759, 1357, -294, 69, 1786, -1529, 866, +-899, -1439, 1082, -1116, 1295, 1127, -538, 1197, +-1369, -925, 196, -1409, 1233, 503, 148, 1633, +-1025, 195, -474, -1456, 664, -815, 772, 1037, +-327, 899, -744, -837, 506, -855, 770, 1103, +-622, 1265, -1057, -1222, 403, -2154, 1408, 578, +611, 2724, -1206, 769, -1456, -2449, 707, -1979, +1689, 1547, -42, 2549, -1494, -608, -347, -2754, +1350, -172, 988, 2764, -1134, 1204, -1702, -2381, +363, -2401, 1890, 1149, 762, 3073, -1250, 565, +-1424, -2652, 128, -1721, 1037, 1443, 463, 1786, +-366, -525, -418, -1092, -213, 414, 164, 541, +85, -792, -97, -651, 120, 1023, -41, 1252, +-495, -581, -72, -2002, 884, -431, 359, 2221, +-955, 1776, -1053, -1612, 425, -2632, 1312, 273, +470, 2445, -800, 936, -1033, -1470, 85, -1280, +957, 724, 280, 1031, -604, -787, -27, -1197, +517, 1000, 88, 2147, -442, -343, -558, -2880, +338, -1230, 1159, 2391, 133, 2586, -1234, -863, +-428, -2808, 1001, -692, 907, 2229, -575, 1567, +-1419, -1560, 123, -1968, 1629, 874, 624, 2230, +-1037, 108, -1117, -2112, -73, -1275, 938, 1302, +633, 2111, -465, -243, -265, -2203, 233, -633, +-205, 1867, -692, 1222, -145, -1356, 641, -1675, +900, 494, -65, 1788, -1046, 648, -710, -1162, +242, -1389, 628, 74, 134, 1127, -173, 533, +203, -340, 289, -129, -761, 132, -1008, -542, +200, -875, 1364, 316, 1061, 1721, -684, 847, +-1802, -1566, -429, -1960, 1539, 499, 1154, 2154, +-616, 578, -1238, -1562, -124, -1190, 1257, 885, +769, 1414, -897, -288, -1126, -1477, 353, -339, +1102, 1202, 350, 857, -450, -582, -477, -850, +85, 59, 262, 462, -167, -169, -259, -307, +481, 530, 764, 837, -300, -421, -1030, -1392, +-374, -472, 630, 1236, 657, 1280, 14, -286, +-372, -1208, -227, -496, -258, 491, -159, 348, +355, -74, 372, 235, -129, 609, -484, -381, +-101, -1291, 271, -408, 197, 1268, -412, 1224, +-438, -272, 404, -1352, 561, -692, 49, 691, +-663, 937, -660, -20, 258, -609, 1034, -146, +193, 210, -856, 123, -396, -88, 341, 36, +490, -24, 90, -303, -360, 0, -306, 661, +351, 534, 418, -694, -63, -1279, -211, -183, +-121, 1566, -65, 1386, 145, -735, 516, -1973, +128, -644, -355, 1363, -317, 1566, -40, -95, +244, -1558, 325, -937, 134, 779, -161, 1480, +-183, 185, -241, -1290, -107, -1156, 168, 401, +417, 1607, 261, 997, -289, -1046, -742, -2132, +-273, -380, 527, 2099, 613, 1859, -53, -827, +-619, -2478, -334, -920, 153, 1954, 229, 2281, +17, -577, -17, -2727, 43, -1141, -200, 2044, +-417, 2460, 122, -394, 749, -2615, 243, -1365, +-963, 1355, -901, 2223, 569, 336, 1574, -1677, +609, -1361, -1495, 611, -1876, 1274, 245, 34, +2313, -887, 1605, -82, -979, 959, -2452, 187, +-1252, -1258, 1711, -869, 2654, 1171, 519, 1719, +-2102, -241, -2159, -2101, 172, -1102, 2279, 1458, +1779, 2119, -968, 114, -2264, -2120, -630, -1724, +1638, 863, 1366, 2337, -571, 726, -1297, -1431, +8, -1381, 1045, -3, 104, 693, -1320, 398, +-586, 167, 1698, 400, 1631, 236, -1280, -829, +-2818, -1581, -483, -274, 2612, 1883, 2358, 2114, +-949, -436, -2930, -2459, -1076, -1502, 1588, 1042, +1824, 1947, -98, 459, -1214, -1065, -371, -711, +560, 521, -107, 258, -649, -752, 30, -503, +976, 775, 876, 1054, -537, 92, -1436, -726, +-401, -811, 978, -343, 938, 177, 96, 808, +-686, 973, -471, 54, 343, -1169, 400, -1128, +-90, 406, -310, 1237, -256, 289, 434, -1040, +981, -376, -8, 1259, -1158, 913, -852, -1454, +414, -2103, 1268, 404, 786, 2660, -786, 1647, +-1234, -1556, -28, -2679, 805, -581, 417, 1938, +-417, 1721, -514, -289, 252, -1405, 623, -646, +-4, 592, -637, 599, -647, -58, -115, -339, +706, -247, 957, 0, 285, 561, -986, 742, +-1669, -397, -324, -1484, 1749, -771, 1805, 1296, +-436, 2084, -2150, 272, -1172, -2132, 1177, -2213, +1753, 469, -3, 2752, -1196, 1785, -472, -1232, +565, -2725, 240, -1253, -494, 1388, 119, 2662, +921, 1169, 310, -1609, -1044, -2764, -1152, -1159, +342, 1714, 1824, 3188, 985, 1351, -1187, -2474, +-1744, -3811, -279, -543, 1158, 3562, 1390, 3224, +384, -862, -850, -3516, -1286, -1801, -772, 1565, +677, 2480, 1817, 632, 849, -1339, -1248, -1331, +-2019, -204, -246, 616, 1888, 802, 1527, 512, +-1044, -165, -2156, -1028, -94, -1005, 2042, 366, +1302, 1726, -1575, 1070, -2305, -1145, 251, -2034, +2493, -523, 1183, 1518, -1517, 1676, -2098, 229, +-30, -1077, 1810, -1272, 999, -674, -909, 268, +-1126, 1380, 360, 1677, 766, 186, -143, -2230, +-712, -2449, 2, 333, 785, 2999, 410, 2229, +-435, -1113, -674, -3031, 27, -1532, 424, 1652, +270, 2541, 37, 537, 97, -1616, -117, -1620, +-392, -208, -195, 936, 348, 1327, 616, 770, +159, -727, -539, -2046, -677, -1307, 166, 1444, +799, 3055, 452, 1103, -462, -2640, -892, -3571, +-337, -201, 782, 3608, 1219, 3023, -16, -978, +-1448, -3321, -1234, -1646, 502, 1177, 1822, 1870, +1056, 764, -1248, -203, -2243, -447, -176, -841, +1973, -1040, 1402, -105, -988, 1383, -1813, 1696, +-235, 24, 1615, -1721, 1068, -1515, -1071, 247, +-1550, 1368, -85, 905, 1490, 99, 1303, -515, +-263, -855, -1698, -935, -1428, 22, 525, 1448, +2165, 1639, 1529, -158, -1056, -2315, -2310, -1905, +-1015, 1020, 1346, 2999, 2076, 1188, 550, -1975, +-1317, -2555, -1465, -233, 53, 1950, 981, 1667, +524, -386, -71, -1415, 68, -384, -41, 550, +-760, -87, -626, -716, 475, 290, 1436, 1662, +694, 1067, -1276, -1459, -1919, -2906, 28, -924, +1924, 2638, 1342, 3402, -593, 348, -1723, -3184, +-859, -3171, 678, 39, 834, 3105, 213, 2714, +396, -371, 249, -2568, -1042, -1683, -1779, 418, +-498, 1239, 2177, 799, 2762, 177, -274, 59, +-3426, -240, -2400, -738, 1344, -1098, 3376, -222, +1365, 1396, -1920, 1976, -2316, 387, -200, -1952, +1356, -2300, 1118, -441, -146, 2004, -665, 2520, +-43, 584, 327, -1911, -137, -2362, -373, -843, +-357, 1133, 304, 2442, 1356, 1816, 878, -781, +-1147, -2993, -2416, -2386, -778, 494, 2585, 3258, +3388, 2986, -441, -340, -4097, -3622, -2701, -3188, +2008, 382, 4248, 3290, 1454, 2977, -2867, 114, +-3466, -2655, -140, -3155, 2597, -778, 2023, 2319, +-427, 3206, -1410, 981, -847, -2076, -530, -2954, +105, -721, 1367, 1937, 1397, 2134, -532, 40, +-2122, -1532, -1201, -946, 1382, 705, 2365, 1020, +51, -275, -2409, -1245, -1731, -587, 1206, 1017, +2796, 1873, 869, 844, -2205, -1516, -2835, -2751, +-214, -1234, 2775, 1960, 2924, 3640, -111, 1635, +-3029, -2258, -2991, -4201, 105, -1959, 3338, 2427, +3303, 4529, -330, 1933, -3374, -2543, -2795, -4126, +336, -1537, 2765, 2170, 2493, 3393, 109, 1187, +-1799, -1902, -2222, -2659, -1003, -660, 1066, 1734, +2505, 1897, 1860, -39, -690, -1703, -3033, -1243, +-2503, 560, 854, 1660, 3674, 949, 2612, -756, +-1357, -1858, -4286, -1254, -2466, 704, 2218, 2247, +4452, 1620, 1709, -592, -2955, -2320, -4161, -1986, +-859, 93, 2999, 2026, 3271, 2275, 237, 771, +-2474, -1253, -2283, -2693, -254, -1967, 1323, 750, +1545, 3144, 759, 2575, -362, -428, -1143, -2865, +-1425, -2548, -511, -8, 1248, 2238, 2066, 2322, +699, 487, -1564, -1414, -2176, -1818, -348, -960, +1850, 709, 1903, 1827, -26, 1158, -1868, -926, +-1596, -1973, 552, -360, 2155, 2013, 1289, 1638, +-1000, -1480, -2227, -2775, -1075, -185, 1459, 2740, +2386, 2125, 723, -767, -1462, -2403, -1916, -1390, +-754, 415, 748, 1121, 1434, 1059, 1241, 979, +590, 338, -1087, -1589, -2599, -2871, -1879, -1173, +1400, 2575, 3857, 4114, 2425, 968, -1988, -3446, +-4721, -4100, -2344, -357, 2474, 3176, 4505, 3132, +1718, 401, -2466, -2135, -3575, -2502, -1246, -895, +1493, 1284, 2420, 2211, 1506, 1288, -471, -767, +-2054, -2035, -1997, -1262, -55, 526, 2061, 1576, +2249, 1045, 63, 65, -2155, -559, -1877, -1142, +190, -1178, 1689, 19, 1209, 1778, 214, 2005, +-670, 191, -946, -2143, -871, -2480, -89, -205, +928, 2312, 1699, 2429, 897, 259, -1219, -1729, +-2158, -1922, -939, -653, 1110, 533, 2043, 1338, +1300, 1594, -640, 570, -1811, -1391, -1467, -2272, +77, -853, 1453, 1264, 1564, 1874, 279, 865, +-1121, -488, -1366, -1228, -347, -1193, 747, -237, +693, 667, -70, 938, -274, 575, 229, 42, +572, -491, -340, -753, -1569, -735, -996, -348, +1200, 655, 2395, 1758, 818, 1321, -1756, -1128, +-2604, -2872, -742, -1474, 1716, 1779, 2531, 3328, +884, 1158, -1540, -2307, -2477, -3206, -1107, -231, +1360, 2568, 2562, 2087, 1296, -483, -1358, -1597, +-2436, -579, -1144, 343, 1183, -86, 1980, -385, +1023, 783, -298, 1872, -1117, 576, -1387, -2183, +-961, -2874, 668, -67, 2242, 3179, 1996, 2970, +-493, -473, -2906, -3311, -2249, -2243, 676, 984, +2762, 2169, 1837, 740, -750, -596, -1794, -249, +-620, 297, 358, -305, 34, -1362, -401, -922, +169, 942, 1378, 2108, 1355, 1096, -541, -1050, +-2446, -2085, -1980, -1119, 450, 589, 2493, 1184, +2281, 767, 23, 288, -2023, 112, -2257, -487, +-718, -1180, 944, -1096, 1778, 128, 1401, 1281, +8, 1461, -1257, 639, -1408, -660, -514, -1448, +159, -1459, 628, -430, 1053, 1110, 996, 2200, +213, 1561, -1068, -465, -1771, -2331, -1004, -2218, +898, -159, 1872, 1801, 1283, 2115, 11, 990, +-1044, -431, -1546, -1513, -1068, -1724, 385, -985, +1589, 599, 1538, 2186, 294, 2420, -1019, 426, +-1319, -2394, -533, -3244, -1, -1070, 193, 2036, +921, 3281, 1595, 1560, 578, -1463, -1412, -2923, +-2375, -1514, -948, 933, 1582, 1906, 2164, 1031, +365, -334, -1007, -911, -672, -537, 2, 43, +-376, 4, -817, -333, -230, -73, 1286, 880, +1810, 945, 467, -218, -1528, -1255, -2158, -1046, +-1031, 185, 838, 1227, 2011, 835, 1790, -371, +152, -817, -1765, -119, -2254, 274, -877, -23, +1150, -361, 2040, 32, 1340, 722, -251, 582, +-1192, -340, -1401, -806, -876, -292, 202, 123, +1523, 268, 1689, 568, 449, 666, -1210, -51, +-1760, -1092, -843, -1142, 731, 194, 1482, 1771, +907, 1440, -169, -731, -810, -2221, -794, -1081, +-225, 1305, 474, 2210, 574, 632, 50, -1664, +-363, -1916, -178, -161, 403, 1463, 682, 1387, +-237, 234, -1317, -797, -968, -1245, 678, -910, +1760, 302, 1059, 1429, -708, 1329, -1801, -125, +-1150, -1590, 444, -1572, 1206, 101, 877, 1513, +204, 1072, -217, -156, -709, -665, -1126, -554, +-685, -462, 624, -173, 1726, 563, 1213, 986, +-675, 331, -1971, -927, -1021, -1141, 775, 287, +1390, 1503, 575, 430, -583, -1506, -764, -1313, +75, 1030, 501, 2102, 28, 428, -418, -1733, +-219, -1720, 153, 271, 398, 1440, 480, 839, +165, -117, -454, -267, -772, -178, -383, -543, +515, -678, 832, -23, 395, 1027, -232, 1169, +-518, 221, -348, -1002, -95, -1240, 79, -426, +202, 507, 359, 915, 267, 821, 12, 172, +-305, -757, -534, -1125, -265, -407, 98, 649, +331, 927, 431, 28, 302, -689, -23, -119, +-477, 744, -667, 243, -383, -1067, 251, -1176, +582, 283, 701, 1599, 417, 1189, -407, -347, +-1026, -1559, -915, -1232, -95, 140, 914, 1103, +1391, 929, 723, 280, -641, -351, -1665, -719, +-1140, -627, 443, -89, 1458, 472, 1012, 591, +-79, 158, -709, -59, -576, 190, -137, -32, +-162, -859, -238, -888, 338, 376, 1147, 1425, +990, 991, -429, -411, -1723, -1191, -1352, -731, +545, 168, 1668, 462, 1014, 338, -371, 541, +-744, 573, -276, -314, -269, -1336, -573, -1004, +-147, 442, 874, 1500, 1435, 1111, 531, -386, +-1286, -1288, -1914, -910, -339, 54, 1317, 663, +1194, 805, 72, 416, -528, -252, -397, -832, +-72, -844, -143, -43, -314, 929, -114, 1001, +475, -20, 803, -914, 291, -827, -501, -42, +-810, 517, -480, 701, 58, 358, 602, -359, +638, -849, 274, -339, -199, 412, -439, 525, +-449, 82, -300, -96, -7, 50, 500, 79, +796, -353, 344, -590, -425, -17, -742, 799, +-397, 805, 78, -92, 255, -770, 337, -620, +416, -24, 373, 354, -44, 419, -701, 446, +-953, 370, -335, -292, 816, -1095, 1038, -791, +572, 599, -141, 1300, -734, 520, -1040, -494, +-729, -790, 277, -440, 1345, 70, 1451, 364, +207, 462, -1414, 279, -1812, -194, -487, -684, +1180, -279, 1471, 617, 449, 524, -493, -560, +-790, -875, -302, 216, -120, 1110, -307, 557, +25, -601, 911, -1049, 858, -507, 25, 385, +-784, 878, -1028, 646, -453, -67, 429, -726, +764, -868, 871, -179, 386, 790, -642, 785, +-1186, -141, -719, -686, 429, -61, 1218, 681, +692, 235, -517, -1006, -691, -1051, 26, 644, +355, 1897, -106, 752, -581, -1335, -199, -1789, +639, -217, 883, 1241, 337, 1169, -587, 65, +-1107, -640, -681, -488, 305, -142, 995, -1, +1070, 135, 231, 307, -858, 218, -1202, -86, +-574, -167, 463, 16, 957, 85, 622, -198, +-15, -404, -256, -13, -516, 550, -594, 566, +-334, -41, 325, -601, 728, -482, 550, -66, +89, 156, -301, 184, -544, 487, -664, 533, +-400, -69, 182, -1041, 1035, -1118, 1415, 151, +314, 1476, -1377, 1098, -1948, -466, -870, -1204, +1197, -567, 2249, 200, 1175, 366, -729, 367, +-1670, 446, -1377, 176, -203, -548, 971, -855, +1388, -171, 1025, 750, -115, 745, -1234, -165, +-1366, -609, -485, -129, 660, 294, 1254, 40, +846, -283, -22, 67, -476, 550, -822, 224, +-1073, -671, -330, -738, 978, 352, 1602, 1095, +824, 431, -756, -843, -1616, -1051, -1041, -52, +220, 833, 1126, 786, 1181, 208, 342, -415, +-642, -926, -1167, -729, -717, 350, 451, 1258, +1038, 818, 378, -540, -508, -1250, -447, -522, +305, 667, 513, 756, -378, -168, -971, -519, +-103, 328, 1003, 694, 847, -312, -308, -1302, +-869, -494, -223, 1159, 413, 1454, 126, -157, +-434, -1458, -149, -795, 667, 690, 881, 939, +-203, -84, -1173, -693, -775, -110, 312, 607, +943, 408, 723, -396, -89, -755, -537, -279, +-526, 475, -252, 753, 40, 470, 469, -137, +493, -835, -22, -1059, -324, -60, -151, 1411, +101, 1387, -165, -333, -332, -1726, 70, -1001, +514, 900, 379, 1497, -164, 59, -500, -1271, +-110, -483, 317, 1051, -116, 856, -663, -857, +-49, -1389, 1125, 61, 1172, 1566, -398, 1101, +-2000, -753, -1306, -1631, 887, -548, 2030, 948, +1088, 1135, -699, 186, -1505, -609, -977, -697, +107, -271, 818, 330, 1021, 652, 548, 228, +-340, -478, -1038, -595, -903, 86, 219, 688, +991, 360, 610, -565, -173, -828, -462, 136, +-282, 875, 81, 453, 24, -401, -68, -572, +253, -152, 234, 149, -217, 70, -264, 53, +147, 513, 370, 497, 23, -544, -641, -1297, +-483, -348, 551, 1275, 990, 1342, 65, -189, +-935, -1343, -798, -834, 348, 392, 989, 904, +279, 429, -716, -135, -616, -417, 174, -425, +677, -217, 352, 369, -387, 669, -569, 192, +-167, -630, 128, -674, 435, 191, 523, 836, +60, 308, -630, -628, -740, -681, -78, 214, +808, 785, 741, 255, -222, -651, -737, -624, +-241, 251, 393, 657, 401, 342, -273, -310, +-526, -683, 192, -426, 665, 385, 110, 831, +-398, 377, -214, -382, -33, -735, -173, -481, +-268, 149, 439, 640, 1082, 669, 364, 162, +-1229, -531, -1497, -886, 60, -420, 1524, 519, +1126, 883, -392, 327, -983, -272, -331, -325, +112, -373, -165, -476, -112, -19, 649, 806, +1018, 953, -25, -30, -1305, -1127, -1006, -928, +466, 461, 923, 1149, 241, 215, -150, -963, +209, -437, 70, 862, -773, 835, -1004, -636, +202, -1258, 1434, -142, 994, 1014, -621, 820, +-1307, -176, -392, -432, 569, -106, 427, -274, +-90, -757, 40, -136, 393, 1417, 128, 1541, +-581, -388, -735, -2233, 66, -1432, 736, 1040, +379, 2117, -117, 589, 15, -1191, -28, -982, +-535, 236, -659, 334, 165, -380, 1038, -204, +798, 796, -312, 880, -1102, -307, -667, -1292, +327, -636, 823, 701, 374, 949, -260, 41, +-285, -478, -112, -174, 3, 129, -164, 36, +-4, -250, 213, -178, 291, 147, 30, 466, +-189, 293, -260, -114, -162, -522, 149, -500, +228, 16, 43, 612, -133, 639, -34, -74, +191, -659, 112, -365, -362, 246, -423, 223, +183, -135, 686, 24, 281, 473, -494, 280, +-685, -578, 35, -919, 779, 35, 366, 1080, +-644, 764, -734, -528, 326, -1002, 947, -249, +281, 617, -781, 438, -740, -129, 176, -110, +562, 216, 181, -143, -65, -739, 123, -282, +109, 984, -499, 1161, -810, -463, -71, -1675, +1172, -595, 1153, 1357, -372, 1353, -1556, -475, +-866, -1445, 747, -284, 1247, 1093, 282, 686, +-743, -771, -492, -964, 222, 433, 224, 1260, +-288, 141, -329, -1303, 347, -842, 807, 820, +94, 1287, -953, 19, -765, -1155, 422, -716, +956, 554, 284, 988, -692, 213, -597, -697, +242, -717, 585, -37, 96, 624, -416, 668, +-421, 151, 179, -604, 527, -866, 138, -140, +-314, 773, -351, 755, -104, -53, 211, -546, +377, -329, 87, 6, -285, -11, -373, -68, +-74, 353, 352, 630, 436, 122, -47, -722, +-540, -835, -402, -99, 157, 718, 564, 821, +428, 205, -205, -485, -701, -733, -458, -446, +321, 120, 690, 731, 273, 788, -276, -26, +-445, -952, -279, -708, 31, 321, 284, 702, +302, 243, 132, -241, -130, -309, -366, -83, +-260, 123, 65, 128, 346, -21, 202, -16, +-24, -114, -112, -143, -76, 135, -294, 397, +-231, 149, 297, -472, 625, -588, 201, 28, +-573, 724, -738, 570, 89, -278, 752, -727, +296, -308, -310, 328, -255, 429, -67, 148, +-16, -136, -72, -223, 128, -124, 386, 44, +116, 116, -553, 35, -488, -23, 264, 13, +679, 111, 187, -20, -666, -193, -606, -123, +435, 230, 751, 247, -132, -232, -711, -392, +-173, 167, 512, 667, 265, 98, -295, -830, +-328, -702, 132, 469, 367, 1162, 81, 404, +-452, -858, -438, -1114, 260, -117, 567, 896, +257, 875, -265, 34, -577, -711, -509, -733, +289, -84, 894, 646, 434, 622, -537, -115, +-911, -650, -247, -222, 766, 528, 789, 442, +-393, -505, -935, -882, 11, 164, 952, 1272, +366, 740, -798, -931, -845, -1485, 166, -149, +927, 1282, 566, 1060, -358, -368, -735, -1041, +-318, -337, 170, 583, 245, 393, 240, -373, +226, -418, 52, 357, -332, 758, -433, 91, +-244, -824, 89, -843, 415, 114, 522, 948, +195, 840, -478, -98, -819, -962, -428, -819, +543, 168, 945, 860, 153, 547, -672, -205, +-447, -541, 303, -233, 203, 164, -396, 121, +-404, -43, 449, 67, 861, 260, 107, -9, +-883, -412, -804, -254, 249, 337, 758, 500, +185, -86, -383, -576, -58, -355, 440, 384, +-34, 714, -778, 177, -476, -585, 514, -641, +829, -47, 176, 402, -405, 492, -413, 297, +-101, -61, -101, -594, -184, -727, 244, -34, +677, 829, 455, 797, -382, -43, -953, -698, +-621, -661, 345, -93, 823, 443, 493, 545, +-19, 288, -447, -205, -621, -507, -370, -364, +179, 120, 595, 406, 419, 278, -106, -104, +-380, -254, -213, -1, -98, 124, -150, -129, +8, -250, 304, 72, 435, 462, 89, 312, +-546, -333, -597, -654, 146, -138, 529, 524, +130, 567, -299, -14, -193, -539, 183, -469, +302, 92, -136, 535, -441, 366, -127, -136, +207, -496, 215, -284, 103, 150, 7, 390, +4, 232, -126, -138, -355, -226, -279, -89, +144, -40, 432, -99, 551, 106, 122, 404, +-611, 342, -873, -237, -412, -842, 568, -521, +1194, 664, 628, 1196, -708, 231, -1344, -1000, +-641, -1025, 703, 47, 1198, 925, 371, 798, +-719, -69, -865, -815, -87, -644, 571, 191, +361, 680, -242, 330, -317, -238, -29, -415, +90, -137, 135, 229, 138, 221, 17, -28, +-306, -156, -578, -144, -155, 24, 771, 258, +945, 217, -187, -182, -1191, -393, -882, -168, +456, 310, 1166, 454, 464, 33, -561, -423, +-714, -361, -69, 138, 259, 484, 67, 202, +-111, -456, 197, -483, 301, 223, -89, 670, +-391, 291, -297, -462, 28, -787, 304, -249, +229, 668, 35, 876, -75, 133, -194, -713, +-336, -771, -59, -125, 340, 527, 298, 674, +-132, 213, -302, -370, -82, -468, 157, -158, +81, 12, -198, 112, -212, 365, 164, 324, +351, -121, -8, -453, -422, -313, -261, 102, +201, 350, 295, 228, -29, -126, -330, -281, +-87, -37, 330, 316, 194, 201, -405, -387, +-446, -582, 174, 90, 539, 859, 182, 572, +-477, -445, -556, -936, 215, -360, 729, 401, +20, 742, -742, 415, -426, -267, 457, -616, +765, -331, 85, 112, -791, 219, -644, 345, +324, 353, 739, -82, 156, -626, -506, -482, +-364, 275, 280, 614, 400, 267, -242, -213, +-613, -405, -72, -252, 664, 107, 625, 397, +-261, 256, -931, -189, -463, -439, 495, -147, +703, 389, 68, 418, -392, -131, -323, -523, +66, -232, 184, 401, -151, 486, -323, -158, +65, -511, 504, -24, 317, 452, -271, 61, +-757, -479, -361, -194, 421, 549, 551, 545, +195, -381, -242, -899, -333, -165, -158, 859, +-82, 742, -118, -382, 255, -897, 490, -205, +32, 651, -446, 484, -478, -208, -36, -466, +467, -93, 354, 264, -239, 222, -449, -37, +-69, -121, 451, -119, 317, -122, -322, 18, +-553, 315, -103, 292, 288, -185, 492, -515, +312, -171, -269, 470, -723, 385, -526, -305, +293, -403, 916, 316, 554, 510, -494, -295, +-1002, -816, -434, -152, 614, 856, 930, 846, +91, -220, -829, -1075, -618, -684, 252, 438, +638, 1008, 150, 432, -369, -504, -186, -721, +8, -185, -197, 330, -144, 331, 350, 120, +551, -9, 95, -130, -785, -246, -942, -144, +155, 155, 1095, 243, 756, 83, -349, -64, +-971, -136, -662, -202, 234, -92, 715, 217, +490, 436, -31, 81, -430, -478, -548, -519, +-196, 101, 327, 608, 554, 435, 157, -138, +-413, -611, -398, -493, 58, 183, 305, 706, +137, 450, -184, -366, -262, -639, 62, -152, +231, 367, 50, 329, -92, -8, -88, -177, +-111, -118, -86, 43, 45, 74, 136, -23, +169, -84, 18, -5, -263, 145, -306, 128, +-19, -114, 275, -203, 271, -41, -49, 99, +-315, 148, -151, 72, 89, -63, 81, -175, +-26, -76, -53, 61, 57, 141, 48, 105, +-62, -30, -139, -136, -62, -204, 2, -48, +87, 258, 136, 391, -23, -28, -162, -549, +-144, -438, 10, 288, 168, 741, 87, 225, +-127, -543, -102, -588, 52, 66, 40, 507, +-52, 243, -90, -211, -1, -179, 182, 84, +102, 29, -172, -118, -281, -14, -34, 23, +259, -6, 259, 166, -73, 306, -215, -46, +-161, -580, -54, -460, 24, 327, 190, 760, +297, 285, 94, -355, -438, -467, -573, -307, +73, -58, 586, 359, 413, 624, -176, 205, +-504, -478, -312, -505, 131, -9, 336, 124, +118, -18, -138, 238, -108, 563, 71, 113, +12, -724, -174, -793, -247, 139, -13, 824, +539, 502, 478, -188, -453, -440, -927, -330, +-69, -63, 825, 262, 585, 293, -309, -65, +-757, -163, -230, 146, 511, 199, 416, -326, +-125, -475, -288, 162, -142, 631, 75, 203, +134, -462, 22, -421, -39, 185, 76, 399, +108, 30, -148, -305, -378, -152, -74, 28, +504, 199, 473, 375, -200, 122, -584, -561, +-335, -681, 183, 188, 505, 884, 352, 479, +-203, -385, -467, -708, -134, -346, 139, 235, +66, 580, 45, 406, 188, -182, 108, -521, +-119, -278, -355, 178, -266, 236, 190, 46, +500, 181, 160, 239, -329, -381, -311, -726, +-62, 71, 117, 848, 209, 397, 150, -356, +-151, -513, -220, -243, 59, 87, 152, 385, +-48, 357, -106, -9, 11, -339, 155, -397, +164, -65, -176, 336, -446, 361, 81, 16, +649, -164, 173, -214, -533, -260, -452, 3, +142, 456, 548, 328, 333, -254, -351, -396, +-533, -63, 37, 116, 432, 193, 211, 221, +-225, -31, -249, -361, 125, -196, 258, 258, +-84, 282, -265, -83, 20, -184, 228, 53, +69, 45, -109, -142, -53, -22, 87, 227, +-51, 92, -153, -183, 69, -145, 253, 106, +12, 115, -163, -78, -77, -117, 14, 99, +107, 183, 71, -70, -153, -279, -24, -109, +280, 288, 65, 300, -297, -128, -241, -364, +201, -84, 380, 237, -19, 138, -367, -78, +-27, -36, 390, 109, 72, 1, -413, -279, +-293, -250, 302, 203, 627, 561, 239, 276, +-579, -464, -770, -710, -4, -128, 804, 570, +673, 581, -117, 15, -690, -396, -456, -352, +111, -15, 355, 52, 315, 9, 320, 290, +17, 476, -545, -33, -670, -732, 47, -532, +834, 339, 697, 666, -255, 258, -780, -208, +-352, -355, 314, -340, 481, 2, 135, 463, +-164, 326, -83, -251, -37, -383, -151, 100, +4, 314, 334, -36, 131, -292, -312, -92, +-201, 180, 342, 322, 377, 157, -294, -431, +-542, -604, 137, 239, 598, 867, 118, 152, +-346, -709, -200, -466, 88, 318, 282, 491, +33, -56, -297, -431, -126, -9, 399, 584, +428, 196, -121, -759, -638, -787, -464, 474, +482, 1218, 1031, 421, 126, -812, -829, -1087, +-638, -272, 145, 771, 659, 953, 559, 85, +-201, -527, -638, -429, -164, -263, 383, -68, +322, 428, -73, 568, -308, 65, 64, -426, +374, -327, -94, -46, -326, 88, 153, 174, +238, 296, -151, -14, -53, -362, 147, -111, +115, 340, -45, 151, -186, -357, -10, -270, +271, 227, 125, 434, -220, 17, -161, -266, +129, -213, 341, -16, 80, 189, -279, 207, +-246, -181, 75, -342, 208, 254, 256, 584, +180, -53, -115, -750, -429, -425, -241, 353, +350, 736, 501, 361, 35, -398, -278, -775, +-93, -268, 98, 625, 48, 550, -99, -105, +-161, -552, 219, -205, 515, 384, 196, 474, +-463, -240, -597, -700, -14, 11, 473, 723, +451, 276, 213, -563, -28, -350, -437, 362, +-580, 321, -16, -352, 727, -318, 671, 225, +-128, 427, -674, -3, -269, -321, 379, -142, +278, 138, -121, -65, -160, -167, 227, 368, +294, 517, -82, -300, -342, -893, -14, -158, +205, 932, 37, 828, -44, -639, 112, -1371, +307, -22, 217, 1671, -445, 899, -752, -1462, +230, -1771, 1090, 714, 417, 2184, -781, 257, +-621, -1900, 317, -1085, 595, 1232, -54, 1421, +-441, -377, 91, -1413, 618, -329, 94, 1125, +-748, 788, -324, -745, 743, -1034, 688, 560, +-409, 1235, -825, -425, 16, -1628, 848, -35, +582, 1866, -499, 949, -777, -1487, 72, -1717, +589, 488, 288, 1734, -141, 416, -102, -1165, +84, -687, -26, 714, -369, 745, -97, -682, +645, -1027, 618, 567, -309, 1462, -837, -61, +-155, -1532, 722, -580, 523, 1213, -353, 979, +-465, -784, 260, -1219, 506, 334, -223, 1413, +-555, 309, 222, -1321, 729, -959, 98, 880, +-634, 1202, -451, -480, 395, -1063, 835, 439, +194, 1111, -714, -368, -550, -1452, 217, -312, +580, 1397, 478, 1226, -91, -418, -443, -1421, +-277, -792, -62, 614, 246, 1146, 677, 268, +312, -614, -585, -278, -712, 207, 117, -274, +901, -572, 451, 308, -640, 1223, -645, 474, +297, -1201, 656, -1321, 283, 341, -412, 1461, +-514, 631, 213, -830, 405, -1115, 23, -8, +-18, 968, 139, 623, -5, -444, -155, -831, +-340, -155, 102, 651, 724, 495, 260, -232, +-497, -403, -398, -94, 135, 63, 404, 132, +209, 96, -302, 22, -160, 25, 414, 11, +262, -193, -318, -200, -433, 105, 135, 291, +700, 156, 232, -144, -561, -182, -346, -88, +305, -21, 418, 25, 169, 208, -225, 229, +-417, 18, 59, -383, 417, -562, 303, 158, +67, 885, -301, 505, -383, -714, -69, -1027, +425, -6, 508, 1070, 99, 732, -303, -582, +-324, -936, -210, -61, 125, 578, 600, 334, +368, -148, -242, -174, -309, 86, -153, 38, +-123, -398, 253, -281, 504, 556, 224, 812, +-242, -259, -395, -1162, -176, -332, 245, 977, +418, 843, 208, -473, -162, -878, -269, -169, +-43, 671, 126, 563, 215, -281, 152, -747, +-60, -85, -141, 815, -86, 276, 117, -770, +417, -482, 234, 856, -637, 664, -507, -834, +550, -996, 976, 622, 26, 1328, -947, -180, +-552, -1366, 586, -418, 885, 1161, -117, 846, +-553, -777, 21, -1125, 421, 364, -56, 1387, +-498, 92, -89, -1555, 817, -761, 809, 1441, +-601, 1457, -1242, -896, -97, -1850, 1191, 194, +834, 1762, -566, 316, -762, -1548, 186, -597, +467, 1442, -184, 1035, -282, -1257, 359, -1692, +627, 581, -36, 2075, -834, 423, -323, -1731, +758, -1152, 624, 1020, -399, 1314, -554, -610, +218, -1333, 693, 344, 167, 1704, -637, 287, +-742, -1821, 380, -1435, 1256, 1024, 458, 2157, +-877, 361, -999, -1620, 53, -1295, 843, 370, +822, 1068, -63, 561, -754, -237, -498, -600, +305, -432, 680, 8, 324, 634, -390, 793, +-565, -253, 171, -1511, 719, -731, 140, 1469, +-473, 1894, -269, -353, 267, -2175, 391, -1129, +-53, 1121, -280, 1513, 182, 240, 497, -581, +-107, -451, -638, -373, -312, -524, 706, 32, +1054, 1205, -162, 1201, -1242, -653, -456, -1901, +1030, -524, 862, 1386, -429, 1121, -812, -494, +210, -945, 964, 138, 19, 719, -1145, -283, +-379, -1058, 1306, 215, 1004, 1603, -616, 526, +-1265, -1703, -203, -1543, 1041, 930, 802, 2123, +-435, 232, -572, -1826, 409, -1040, 376, 1021, +-700, 1115, -742, -535, 1072, -857, 1778, 505, +-345, 950, -2298, -523, -898, -1307, 1730, -51, +2146, 1428, -217, 866, -2232, -999, -850, -1443, +1615, 304, 1296, 1674, -780, 235, -950, -1667, +207, -981, 976, 1351, 322, 1702, -931, -397, +-541, -1854, 715, -817, 772, 1014, -204, 1335, +-524, 60, -72, -928, 591, -474, 114, 446, +-658, 229, 35, -604, 739, -268, 234, 854, +-368, 916, -371, -516, 42, -1346, 549, -314, +132, 1005, -467, 691, -18, -456, 603, -548, +329, 415, -355, 627, -748, -588, -57, -1327, +990, 8, 626, 1799, -371, 1208, -580, -1044, +-135, -2070, 204, -358, 311, 1636, 38, 1247, +194, -713, 437, -1251, -146, 288, -761, 1167, +-399, -111, 626, -1775, 1053, -668, 319, 1891, +-806, 2192, -836, -639, 244, -2748, 836, -1485, +167, 1351, -410, 2208, 136, 721, 559, -809, +-88, -1238, -751, -928, -375, -182, 552, 791, +1111, 1262, 513, 881, -841, -458, -1179, -1696, +-137, -1342, 1088, 507, 1132, 1828, -24, 1127, +-1082, -642, -635, -1460, 532, -675, 888, 543, +148, 889, -607, 262, -455, -529, 519, -514, +838, 188, 27, 662, -778, 249, -723, -786, +377, -1003, 1254, 175, 694, 1306, -700, 883, +-1164, -504, -217, -1354, 915, -785, 1023, 618, +-15, 1194, -856, 380, -440, -574, 501, -630, +812, -173, -89, 224, -792, 189, -186, 83, +913, 10, 706, -132, -319, -40, -827, 247, +-400, -1, 627, -486, 992, -295, 129, 360, +-637, 625, -561, 124, 38, -641, 884, -646, +737, 301, -507, 871, -1178, 72, -230, -1003, +1244, -655, 1636, 981, -71, 1413, -2052, -365, +-1798, -1983, 889, -1075, 3104, 1433, 1781, 2373, +-1853, 310, -3422, -2435, -795, -2239, 2722, 824, +2999, 2876, -193, 1339, -2639, -1885, -1513, -2599, +1089, -98, 1627, 2217, 249, 1532, -641, -779, +-84, -1700, 401, -586, -259, 759, -898, 785, +317, 128, 1812, -144, 749, -3, -1837, -311, +-2057, -956, 868, -403, 3139, 1259, 1333, 1747, +-2433, -162, -3076, -2127, 310, -1779, 3367, 759, +2140, 2523, -1492, 1289, -2648, -1459, -501, -2267, +1628, -411, 1351, 1571, -83, 1481, -751, -404, +-282, -1494, 263, -488, 391, 1073, 197, 1101, +-410, -527, -612, -1697, 242, -648, 1423, 1585, +971, 1956, -943, -229, -2038, -2343, -472, -1738, +2005, 1153, 2104, 2604, -533, 685, -2290, -2117, +-623, -1902, 1913, 890, 1519, 2251, -1398, 217, +-2188, -2286, 796, -1418, 3160, 1706, 1064, 2592, +-2764, -199, -2833, -2852, 896, -1816, 3425, 1479, +1360, 2658, -1902, 572, -2061, -1771, 390, -1724, +1906, 113, 419, 1246, -1296, 782, -810, -255, +1262, -777, 1497, -379, -221, 407, -1681, 594, +-863, -125, 1100, -746, 1439, -412, 106, 425, +-858, 986, -290, 460, 405, -869, 401, -1453, +-262, -195, -525, 1412, 81, 1193, 1001, -444, +868, -1345, -250, -507, -1116, 684, -865, 795, +346, -217, 1182, -845, 1093, -217, 156, 943, +-769, 935, -1178, -467, -721, -1840, 821, -1206, +1914, 1333, 1055, 2862, -1034, 1026, -1839, -2544, +-735, -3588, 1278, -468, 1849, 3526, 511, 3769, +-1079, -420, -1274, -4377, -316, -3347, 753, 1498, +1316, 4414, 967, 2222, -243, -2111, -1845, -3747, +-1699, -1379, 863, 1983, 3281, 2922, 2050, 1016, +-2070, -1641, -4131, -2585, -1105, -1069, 3802, 1535, +4284, 2542, -445, 772, -4566, -1836, -2998, -2327, +2205, -199, 4762, 1910, 1363, 1564, -3463, -350, +-3441, -1427, 746, -931, 3628, 241, 2031, 740, +-1723, 630, -2898, 278, -483, -299, 2292, -1013, +2033, -1009, -351, 275, -1963, 1777, -1037, 1358, +1095, -925, 1857, -2459, 407, -1037, -1482, 1526, +-1467, 2155, 577, 354, 2139, -1374, 1155, -1292, +-1262, -176, -2324, 268, -434, 324, 2337, 825, +2293, 1049, -484, -179, -2328, -2013, -1299, -1985, +1033, 691, 2123, 3153, 674, 1850, -1093, -1906, +-1057, -3393, -106, -799, 752, 2496, 872, 2585, +231, -238, -555, -2442, -610, -1682, -57, 832, +834, 1925, 961, 841, -210, -905, -1057, -1384, +-396, -635, 698, 467, 1055, 1158, 196, 870, +-795, -299, -463, -1330, 629, -1059, 593, 286, +-325, 1175, -549, 854, 305, -63, 1025, -651, +336, -881, -746, -648, -782, 25, 122, 1137, +759, 1307, 788, 285, 246, -1449, -334, -1919, +-817, -504, -551, 1601, 567, 2269, 1292, 467, +768, -1821, -523, -2241, -1421, -304, -719, 1587, +1208, 1717, 1804, 224, 278, -1108, -1413, -1217, +-1364, -276, 358, 402, 1620, 380, 973, 412, +-402, 656, -953, 214, -578, -1080, 133, -1751, +773, -453, 810, 1808, 311, 2463, -208, 313, +-751, -2587, -560, -2917, 96, 98, 696, 3145, +1041, 2571, 682, -747, -313, -2976, -1292, -1909, +-1296, 930, 27, 2273, 2183, 951, 2512, -1008, +-153, -893, -3000, 94, -2629, 78, 922, -806, +3758, -678, 2283, 1128, -1683, 2364, -3250, 653, +-970, -2748, 2107, -3250, 2368, -38, -56, 3595, +-1784, 3199, -699, -591, 1213, -3641, 1107, -2568, +-714, 702, -1644, 2496, 237, 1737, 2351, 42, +1713, -924, -1437, -1507, -3245, -1555, -1074, -350, +3137, 1926, 3905, 2630, -206, 689, -4145, -2197, +-3005, -3102, 1866, -904, 4490, 2339, 1588, 2901, +-2824, 433, -3189, -2053, 44, -1969, 2869, -150, +2172, 1191, -944, 928, -2348, -135, -550, -546, +1535, 108, 1459, 509, 74, -286, -1209, -1079, +-916, -615, 319, 681, 1031, 1222, 1078, 803, +274, -231, -961, -1251, -1573, -1601, -452, -699, +1480, 1363, 2449, 2678, 980, 1404, -1884, -1835, +-3136, -3677, -1155, -1762, 2609, 2350, 4428, 4180, +1392, 1382, -3668, -2918, -4883, -3852, -645, -559, +4639, 2691, 5059, 2658, -66, 77, -5002, -1846, +-4133, -1877, 1124, -254, 4663, 1326, 3237, 1578, +-1306, 242, -3706, -1361, -1968, -1753, 1134, -198, +2663, 2103, 1749, 2181, -250, -701, -1764, -3323, +-1803, -2183, -384, 1903, 1647, 4043, 2606, 1505, +1030, -2704, -1799, -3835, -3088, -1075, -995, 2292, +2396, 3167, 3564, 1221, 1071, -1377, -2597, -2507, +-3500, -1724, -683, 46, 2830, 1780, 3322, 2266, +555, 1073, -2384, -1134, -2556, -2599, -291, -1973, +1824, 366, 2063, 2486, 624, 2509, -1027, 212, +-1595, -2268, -571, -2604, 800, -661, 1435, 1763, +885, 2420, -539, 718, -1588, -1721, -671, -2145, +1288, -54, 1920, 2049, 414, 1333, -1836, -1391, +-1968, -2476, 239, -155, 2407, 2785, 2093, 2606, +-312, -849, -2295, -3854, -1912, -2769, 179, 1508, +1984, 4233, 2128, 2401, 572, -1675, -1190, -3487, +-1945, -1809, -1337, 711, 375, 1654, 2120, 1532, +2380, 1187, 684, 39, -1861, -1986, -3206, -3086, +-1346, -1148, 2077, 2557, 3919, 4240, 1959, 1508, +-2103, -3098, -4171, -4605, -1734, -1211, 2634, 3250, +3941, 3840, 1309, 508, -2465, -2661, -3279, -2630, +-520, -300, 2470, 1574, 2452, 1622, 222, 412, +-1731, -620, -1663, -1068, -68, -844, 1309, -94, +1204, 770, 288, 1073, -408, 594, -626, -400, +-495, -1365, -252, -1298, 319, -38, 1013, 1653, +1074, 1947, 171, 292, -1098, -1948, -1474, -2331, +-478, -403, 1134, 1742, 1897, 2067, 1028, 657, +-739, -1068, -1791, -1694, -1144, -995, 370, 221, +1473, 931, 1344, 1107, 317, 707, -511, -51, +-1154, -1182, -1079, -1607, -49, -674, 1261, 1000, +1554, 1875, 690, 1268, -836, -420, -1649, -2064, +-787, -1930, 758, 152, 1328, 2025, 763, 1670, +-74, -118, -566, -1203, -514, -999, -398, -409, +-174, -132, 493, 508, 1335, 1371, 1028, 1190, +-707, -731, -1999, -2459, -1186, -1585, 1299, 1467, +2610, 3036, 1211, 979, -1530, -2167, -2809, -2768, +-1002, -257, 2033, 2166, 2870, 1938, 808, -269, +-1780, -1560, -2418, -866, -731, 280, 1488, 201, +1871, -205, 782, 375, -260, 1277, -1004, 673, +-1195, -1332, -550, -2224, 480, -644, 1430, 1695, +1489, 2211, 121, 559, -1403, -1301, -1469, -1663, +-291, -723, 840, 402, 1243, 831, 612, 772, +-90, 562, -300, -21, -361, -855, -624, -1104, +-630, -398, 62, 452, 1101, 659, 1701, 559, +845, 632, -1084, 224, -2362, -979, -1576, -1792, +835, -816, 2824, 1161, 2243, 2027, -447, 933, +-2495, -706, -1933, -1250, 220, -867, 1520, -490, +1110, -228, 253, 730, 23, 1864, 137, 1602, +-298, -606, -1304, -2688, -1386, -2354, 306, 50, +2385, 2240, 2316, 2554, -100, 1144, -2214, -982, +-2339, -2657, -545, -2628, 1410, -357, 2221, 2613, +1444, 3493, -181, 1154, -1767, -2190, -1952, -3427, +-334, -1466, 1385, 1306, 1541, 2365, 371, 1396, +-412, -68, -188, -1054, 62, -1379, -583, -1005, +-1240, 184, -354, 1323, 1525, 1168, 2131, -44, +549, -951, -1315, -516, -1774, 336, -820, 252, +196, -724, 814, -821, 1470, 696, 1682, 1849, +318, 837, -2075, -1329, -2892, -2198, -1014, -854, +2146, 1218, 3273, 1994, 1601, 861, -1215, -716, +-2635, -1378, -2041, -871, -102, -119, 1827, 525, +2446, 1017, 1181, 849, -934, -69, -2068, -1058, +-1352, -1059, 128, -270, 1010, 618, 1145, 975, +980, 701, 254, -202, -796, -1024, -1550, -948, +-1010, 33, 578, 942, 1805, 859, 1016, 0, +-564, -776, -950, -709, -128, -21, 267, 494, +-190, 510, -508, 220, 59, -166, 1061, -628, +1066, -781, -96, -6, -1087, 1291, -1111, 1372, +-323, -457, 557, -2187, 1087, -1319, 1062, 1246, +430, 2366, -833, 628, -1722, -1565, -1173, -1719, +706, -52, 1993, 1110, 1474, 789, -309, -61, +-1478, -337, -1352, -229, -286, -197, 900, -125, +1242, 122, 526, 278, -264, 3, -626, -190, +-472, 65, -183, 315, 81, 20, 190, -456, +449, -386, 536, 119, 192, 363, -466, 221, +-819, 74, -369, 167, 579, -36, 851, -671, +-8, -942, -569, -34, 27, 1421, 642, 1575, +119, -199, -913, -1965, -901, -1603, 356, 449, +1512, 1851, 942, 1171, -627, -577, -1413, -1228, +-648, -421, 581, 580, 935, 352, 229, -509, +-286, -597, -12, 606, 193, 1385, -204, 370, +-615, -1366, -185, -1572, 508, -54, 579, 1327, +95, 1054, -120, -60, -77, -521, -117, -178, +-367, -137, -412, -612, 89, -718, 715, 439, +796, 1571, 177, 1190, -450, -542, -894, -1769, +-818, -1408, -161, 111, 924, 1341, 1602, 1472, +973, 720, -846, -593, -2140, -1723, -1408, -1550, +737, 298, 2029, 1916, 1377, 1463, -227, -495, +-1199, -1432, -1081, -466, -395, 594, 218, 137, +618, -663, 855, -187, 682, 1144, -10, 1275, +-932, -469, -1128, -1910, -443, -1041, 520, 1025, +1091, 1651, 905, 201, 97, -1062, -654, -535, +-997, 653, -725, 395, 169, -792, 906, -868, +830, 521, 269, 1418, -187, 480, -552, -1028, +-744, -1106, -497, 64, 136, 695, 887, 213, +1153, -173, 367, 230, -997, 535, -1321, -351, +-388, -1239, 874, -466, 951, 1227, -11, 1465, +-539, -258, -5, -1672, 531, -1019, -3, 920, +-789, 1616, -835, 463, 274, -1165, 1249, -1310, +800, -149, -388, 886, -780, 921, -297, 433, +-55, -191, -347, -976, -224, -1127, 713, -164, +1616, 1265, 825, 1455, -1407, 117, -2442, -1185, +-1007, -1147, 1364, -161, 2446, 533, 1292, 688, +-696, 546, -1752, 123, -1488, -523, -447, -834, +825, -369, 1664, 467, 1330, 787, 31, 282, +-1416, -453, -1582, -521, -649, 79, 704, 425, +1288, 29, 909, -406, 123, -220, -305, 287, +-682, 479, -1128, 54, -845, -410, 360, -388, +1715, 192, 1816, 524, 170, 61, -1930, -742, +-2284, -538, -518, 630, 1598, 1291, 2217, 400, +708, -1241, -1179, -1716, -1487, -359, -349, 1600, +406, 2023, 343, 404, -15, -1664, 241, -2121, +859, -450, 439, 1575, -985, 1863, -1560, 204, +-365, -1318, 1179, -1021, 1608, 325, 230, 672, +-1178, -157, -1122, -717, 203, 87, 843, 1158, +363, 916, -459, -731, -539, -1637, 192, -723, +598, 930, 392, 1306, -77, 300, -661, -521, +-862, -316, -208, 11, 855, -370, 1308, -608, +581, -19, -950, 911, -1609, 993, -566, 189, +882, -669, 1149, -1026, 353, -838, -336, 0, +-217, 1144, -69, 1484, -511, 492, -806, -1097, +44, -1710, 1183, -623, 1117, 874, 85, 1227, +-892, 382, -1096, -180, -607, -188, 117, -267, +823, -744, 1175, -710, 965, 406, -387, 1396, +-1808, 990, -1668, -475, 61, -1359, 1751, -901, +1890, 270, 406, 897, -1131, 786, -1613, 55, +-1028, -555, 201, -556, 1268, -66, 1376, 234, +508, 66, -631, -6, -1282, 170, -946, 330, +-44, 32, 719, -495, 1108, -568, 720, 123, +-237, 711, -831, 487, -871, -397, -444, -669, +261, -97, 751, 435, 867, 385, 577, 43, +-382, -267, -1271, -384, -1145, -242, 44, 120, +1299, 554, 1420, 684, 127, 67, -1072, -971, +-1098, -1175, -345, -32, 560, 1317, 809, 1338, +364, -3, -168, -1257, -390, -1228, -391, -114, +-62, 879, 381, 916, 306, 260, -218, -190, +-587, -455, -28, -605, 862, -417, 661, 224, +-413, 790, -1133, 596, -712, -111, 472, -572, +1268, -360, 713, -23, -429, 36, -995, -27, +-723, 189, 209, 560, 800, 427, 333, -421, +-123, -1037, -81, -452, -91, 666, -124, 973, +-203, 103, -306, -638, 123, -251, 611, 419, +337, 63, -285, -836, -439, -486, -131, 946, +297, 1456, 41, 21, -453, -1600, -204, -1293, +622, 520, 906, 1562, 66, 649, -1077, -764, +-1214, -891, -9, 161, 1118, 627, 1078, -118, +262, -731, -579, -56, -959, 1052, -760, 836, +-114, -686, 753, -1440, 1292, -365, 683, 1200, +-680, 1129, -1594, -293, -872, -1060, 662, -373, +1383, 616, 581, 575, -492, -196, -732, -562, +-277, -164, 155, 367, 157, 498, 49, 198, +29, -323, 24, -685, 117, -411, 139, 460, +-86, 976, -230, 537, -344, -625, -194, -1183, +329, -397, 557, 826, 291, 1071, -203, 127, +-501, -730, -453, -642, -69, -5, 264, 370, +482, 340, 494, 172, 49, -34, -699, -234, +-756, -358, -53, -66, 677, 364, 682, 480, +10, -59, -556, -567, -479, -337, 72, 369, +547, 659, 351, 99, -410, -535, -753, -567, +-130, -46, 840, 564, 965, 729, -28, 156, +-1146, -682, -1133, -863, -22, -154, 1255, 784, +1360, 929, 86, 81, -1217, -773, -1312, -701, +-139, 53, 919, 561, 1060, 464, 264, -17, +-591, -313, -821, -282, -231, -30, 544, 254, +537, 360, -166, 68, -590, -454, -144, -584, +633, 135, 755, 980, -127, 751, -1038, -550, +-927, -1305, 231, -601, 1299, 798, 1057, 1355, +-267, 558, -1220, -794, -839, -1243, 162, -407, +755, 786, 451, 970, 85, 86, 23, -609, +-18, -328, -411, 269, -610, 234, -216, -227, +518, -277, 864, 133, 418, 326, -308, 115, +-620, 87, -519, 197, -239, -190, 204, -859, +753, -641, 833, 706, 132, 1691, -911, 840, +-1043, -1180, -104, -2012, 805, -667, 636, 1292, +61, 1702, -65, 538, 86, -629, -275, -925, +-776, -843, -458, -453, 625, 598, 1226, 1631, +619, 1154, -721, -834, -1249, -2073, -429, -887, +665, 1312, 812, 1764, 195, 98, -216, -1339, +-159, -815, -109, 659, -209, 1011, -181, -43, +150, -937, 410, -499, 269, 490, -21, 845, +-222, 305, -214, -308, -171, -537, -12, -456, +264, -141, 368, 509, 207, 862, -198, 413, +-474, -526, -229, -895, 346, -373, 462, 379, +20, 707, -365, 421, -194, -67, 269, -414, +377, -337, -95, -79, -476, 140, -177, 214, +320, 248, 520, 198, 117, 26, -460, -290, +-430, -460, 156, -171, 454, 433, 142, 742, +-250, 317, -258, -549, 96, -923, 287, -247, +113, 830, -127, 1044, -227, 128, -178, -949, +13, -952, 311, 37, 450, 949, 140, 946, +-515, 96, -777, -821, -155, -984, 822, -204, +936, 797, -1, 1052, -949, 362, -837, -649, +170, -967, 868, -364, 578, 507, -274, 846, +-655, 385, -258, -232, 216, -482, 281, -321, +152, -71, -13, 223, -219, 493, -287, 389, +-69, -139, 314, -590, 392, -355, 6, 334, +-505, 614, -497, 131, 97, -362, 452, -333, +385, 78, 24, 283, -287, 219, -513, 131, +-396, -72, 43, -376, 647, -443, 814, 204, +-48, 906, -1134, 690, -1067, -545, 344, -1296, +1380, -410, 686, 1098, -928, 1259, -1338, -174, +-34, -1200, 1197, -494, 732, 807, -709, 773, +-1281, -383, -294, -792, 1007, 84, 1046, 879, +-121, 463, -1085, -528, -981, -734, -91, -44, +788, 539, 954, 460, 275, 37, -713, -153, +-1259, -123, -649, -170, 619, -211, 1258, 101, +484, 536, -852, 475, -1161, -141, -297, -672, +607, -473, 627, 339, -88, 828, -594, 368, +-348, -440, 182, -684, 193, -85, -189, 603, +-296, 555, -88, -171, 101, -574, -47, -153, +-210, 523, -83, 465, 95, -253, -78, -559, +-266, 0, -293, 632, -102, 381, 173, -348, +176, -563, -192, 45, -352, 596, -131, 354, +-58, -262, -183, -433, -219, -8, 49, 366, +307, 217, 84, -51, -465, -57, -693, -1, +-312, -112, 275, -118, 481, 213, 129, 478, +-371, 169, -574, -493, -486, -548, -123, 195, +330, 718, 332, 363, -84, -311, -459, -471, +-447, -47, -148, 311, 17, 138, -128, -105, +-117, 113, 155, 421, 110, 109, -424, -650, +-634, -630, -254, 399, 246, 1073, 263, 372, +-160, -644, -431, -710, -192, 134, -5, 490, +-314, 56, -517, -250, 76, 277, 674, 681, +155, 17, -1018, -987, -1207, -847, 65, 575, +1180, 1474, 638, 583, -885, -937, -1413, -1136, +-410, 16, 645, 899, 627, 482, -110, -285, +-571, -243, -470, 255, -345, 215, -306, -333, +-52, -424, 447, 208, 383, 674, -355, 317, +-1056, -344, -769, -441, 194, -83, 725, 273, +310, 369, -491, 206, -865, -130, -511, -411, +142, -270, 382, 422, -30, 835, -470, 175, +-500, -926, -119, -929, 263, 429, 65, 1462, +-502, 652, -661, -1034, -205, -1206, 294, 248, +292, 1133, -175, 310, -542, -705, -454, -276, +-234, 813, -100, 564, 11, -832, 167, -1228, +91, 247, -237, 1700, -720, 1071, -723, -924, +-48, -1704, 598, -345, 410, 1206, -375, 1116, +-789, -87, -485, -671, 21, -259, 126, 105, +-105, -38, -211, -14, -34, 365, 86, 530, +-274, 23, -691, -596, -552, -509, 165, 239, +656, 714, 255, 421, -766, -271, -986, -589, +-212, -193, 522, 468, 400, 518, -353, 13, +-791, -387, -276, -274, 443, 228, 124, 390, +-597, 41, -553, -282, 133, -35, 476, 359, +-147, 228, -971, -332, -550, -491, 658, 173, +873, 823, -334, 464, -1399, -488, -1029, -911, +503, -205, 1374, 794, 509, 907, -958, 109, +-1408, -694, -664, -752, 387, -34, 906, 687, +575, 736, -246, 95, -947, -537, -961, -570, +-319, 20, 522, 514, 755, 364, 176, -31, +-524, -184, -699, -23, -418, 62, -95, -33, +143, -141, 217, 137, 165, 400, -86, 225, +-458, -284, -529, -454, -152, 41, 213, 544, +183, 292, -167, -284, -317, -336, -82, 146, +126, 441, 16, 121, -335, -358, -565, -289, +-236, 260, 424, 466, 531, 85, 14, -347, +-484, -190, -710, 353, -506, 285, 91, -330, +620, -411, 607, 325, 14, 797, -775, 194, +-996, -752, -372, -723, 546, 327, 918, 900, +321, 297, -666, -473, -892, -340, -260, 304, +248, 287, 288, -419, 61, -503, -40, 473, +-16, 1126, -176, 312, -466, -1046, -326, -1150, +148, 185, 464, 1280, 243, 855, -315, -307, +-660, -903, -280, -459, 335, 271, 485, 542, +-31, 351, -660, 34, -471, -255, 340, -272, +684, 17, -11, 290, -816, 140, -678, -139, +366, -134, 965, 245, 175, 365, -943, -128, +-871, -475, 248, -104, 976, 528, 402, 462, +-711, -253, -901, -574, -68, 70, 610, 730, +419, 285, -121, -640, -342, -651, -228, 390, +-167, 1027, -156, 319, 29, -823, 417, -827, +457, 196, -134, 976, -828, 561, -710, -437, +181, -749, 907, -119, 625, 554, -416, 462, +-928, -88, -322, -345, 419, -64, 435, 243, +-130, 113, -442, -114, -37, -57, 566, 193, +224, 254, -673, -70, -844, -381, 30, -129, +925, 424, 772, 550, -363, -92, -1016, -659, +-518, -346, 364, 554, 660, 789, 161, -5, +-427, -763, -364, -497, 186, 459, 310, 791, +-151, 114, -526, -547, -307, -318, 397, 258, +664, 298, 82, -135, -573, -133, -556, 358, +-125, 388, 270, -284, 301, -674, 88, -98, +29, 711, 8, 710, -353, -184, -622, -783, +-175, -331, 608, 509, 705, 638, -17, 41, +-736, -512, -608, -367, 86, 270, 504, 598, +189, 263, -271, -411, -233, -637, 171, -84, +174, 697, -285, 713, -453, -156, -22, -786, +451, -368, 355, 547, -231, 603, -601, -188, +-273, -603, 345, 89, 500, 819, -65, 410, +-627, -804, -461, -1048, 273, 147, 659, 1330, +254, 946, -506, -496, -768, -1209, -281, -559, +388, 498, 636, 807, 295, 467, -332, -31, +-655, -420, -487, -561, 24, -239, 484, 416, +533, 759, 7, 254, -530, -552, -552, -591, +-118, 160, 330, 656, 277, 258, -123, -419, +-256, -459, -8, 135, 96, 481, -98, 244, +-290, -109, -179, -137, 118, -79, 171, -196, +8, -200, -113, 272, -94, 759, -105, 420, +-194, -572, -262, -994, 0, -221, 371, 847, +277, 846, -211, -114, -469, -629, -295, -144, +-27, 364, 102, 19, 112, -493, 189, -144, +181, 747, -228, 834, -688, -237, -514, -1098, +220, -627, 748, 606, 442, 1020, -410, 227, +-829, -559, -419, -425, 268, 137, 466, 193, +106, -75, -273, -20, -289, 316, -76, 234, +26, -266, -69, -405, -166, 109, -67, 511, +118, 158, 128, -459, -117, -392, -373, 324, +-256, 651, 143, 127, 258, -539, -47, -436, +-351, 169, -239, 462, 116, 136, 216, -175, +-147, -35, -396, 175, -94, 18, 240, -307, +126, -202, -276, 235, -389, 446, -40, 150, +318, -180, 128, -208, -306, -74, -394, -96, +-160, -59, 118, 240, 278, 502, 108, 276, +-203, -351, -410, -693, -376, -328, -45, 431, +372, 709, 424, 300, -34, -237, -562, -397, +-632, -273, -111, -118, 400, 139, 451, 458, +67, 493, -401, -29, -542, -576, -253, -502, +164, 103, 320, 502, 109, 374, -204, -35, +-257, -203, -149, -166, -128, -90, -55, -31, +56, 153, 104, 280, 21, 143, -149, -153, +-297, -262, -233, -87, 26, 159, 246, 189, +146, 84, -245, 0, -430, -66, -184, -116, +175, -106, 307, 127, 38, 274, -410, 87, +-438, -244, -11, -212, 318, 140, 178, 256, +-153, 36, -292, -178, -158, -39, -96, 117, +-164, 16, 93, -113, 410, 87, 170, 293, +-516, 13, -824, -475, -189, -353, 773, 424, +787, 847, -299, 182, -1029, -874, -548, -945, +447, 169, 673, 1155, -7, 812, -495, -358, +-215, -981, 103, -586, -100, 175, -309, 642, +21, 652, 509, 263, 246, -356, -603, -784, +-815, -581, -18, 203, 779, 870, 557, 772, +-410, -7, -890, -773, -295, -787, 466, -127, +487, 583, -49, 706, -418, 265, -345, -275, +13, -513, 184, -335, 134, 34, -60, 362, +-283, 358, -266, 52, 87, -177, 336, -143, +128, 35, -345, -4, -611, -161, -178, -223, +596, 201, 629, 703, -118, 516, -818, -540, +-699, -1288, 94, -584, 783, 1021, 655, 1658, +-197, 456, -900, -1289, -715, -1663, 180, -287, +745, 1278, 528, 1469, -186, 281, -735, -915, +-530, -1160, 129, -510, 465, 421, 305, 1018, +-35, 923, -331, 27, -387, -981, -190, -1218, +128, -283, 355, 937, 283, 1359, -144, 526, +-485, -793, -389, -1387, 46, -699, 368, 657, +364, 1384, 38, 840, -374, -512, -566, -1339, +-255, -923, 394, 460, 676, 1398, 202, 966, +-612, -514, -854, -1418, -96, -883, 799, 560, +648, 1463, -281, 924, -793, -560, -438, -1541, +295, -966, 604, 556, 196, 1588, -273, 1100, +-430, -407, -253, -1584, 58, -1284, 304, 250, +272, 1565, -9, 1400, -334, -34, -318, -1344, +48, -1448, 191, -240, 9, 1133, -77, 1456, +44, 452, 206, -855, -13, -1324, -490, -626, +-388, 587, 282, 1257, 546, 773, 199, -441, +-250, -1218, -429, -747, -251, 470, 45, 1149, +157, 631, 272, -489, 315, -1014, -70, -520, +-522, 458, -467, 932, 80, 527, 553, -389, +365, -935, -226, -562, -335, 358, -35, 972, +-27, 635, -140, -329, 26, -1017, 311, -649, +313, 397, -182, 1048, -556, 534, -187, -512, +421, -950, 372, -312, -108, 620, -460, 843, +-164, 105, 354, -740, 376, -735, -118, 127, +-375, 869, -236, 671, -12, -266, 210, -917, +423, -627, 333, 270, -268, 847, -848, 700, +-514, -6, 559, -694, 1116, -927, 372, -402, +-863, 576, -1092, 1273, 40, 863, 1056, -507, +646, -1610, -616, -1201, -913, 512, 77, 1855, +982, 1389, 486, -521, -628, -1939, -973, -1382, +-191, 537, 777, 1861, 839, 1273, 139, -469, +-455, -1638, -687, -1133, -561, 333, 19, 1410, +769, 1107, 997, -190, 428, -1268, -845, -1101, +-1423, 106, -504, 1279, 907, 1174, 1182, -182, +462, -1485, -358, -1111, -615, 580, -556, 1679, +-492, 775, -45, -1046, 969, -1592, 1415, -293, +339, 1281, -1397, 1310, -1863, -35, -304, -1136, +1716, -986, 1767, 13, -100, 747, -1514, 884, +-1016, 367, 305, -362, 917, -1004, 431, -832, +-259, 185, -481, 1263, -121, 1109, 289, -173, +458, -1326, 141, -1101, -491, 138, -824, 1145, +-223, 1017, 1015, 73, 1390, -878, 193, -1051, +-1532, -299, -1780, 760, 64, 1127, 1966, 453, +1723, -733, -312, -1203, -1828, -465, -1454, 788, +333, 1201, 1569, 425, 1145, -754, -119, -1092, +-1072, -374, -1140, 579, -230, 876, 934, 491, +1366, -204, 635, -703, -960, -746, -1895, -153, +-862, 672, 1369, 991, 2407, 355, 939, -601, +-1749, -1018, -2723, -475, -844, 511, 1864, 1001, +2761, 453, 1043, -454, -1634, -747, -2747, -240, +-1280, 295, 1189, 362, 2633, 112, 1852, -21, +-685, -68, -2714, -76, -2202, -120, 416, -50, +2693, 76, 2444, 176, -278, 100, -2648, -97, +-2238, -166, 250, -33, 2335, 151, 2083, 167, +-147, -65, -2043, -199, -1795, -136, 38, 121, +1697, 200, 1862, 149, 192, -21, -1713, -103, +-1941, -244, -223, -255, 1777, 16, 2212, 479, +351, 610, -2098, 59, -2482, -760, -173, -934, +2399, -64, 2675, 1035, 173, 1077, -2685, 6, +-2874, -1098, 15, -990, 2958, 32, 2933, 856, +-105, 788, -3070, 182, -2911, -430, 234, -738, +3096, -523, 2829, 178, -217, 838, -2938, 767, +-2687, -121, 128, -944, 2641, -819, 2647, 221, +239, 1021, -2308, 703, -2711, -386, -619, -986, +2071, -489, 2993, 500, 1031, 898, -2095, 356, +-3202, -553, -1081, -894, 2173, -281, 3345, 679, +1032, 955, -2307, 189, -3152, -848, -823, -965, +2198, -55, 3003, 917, 875, 939, -2078, 62, +-2899, -871, -942, -1000, 1950, -175, 3073, 863, +1147, 1118, -2045, 310, -3212, -831, -1106, -1203, +2124, -459, 3279, 754, 1136, 1333, -2095, 648, +-3103, -702, -1142, -1455, 1721, -826, 3004, 648, +1599, 1660, -1305, 1135, -3062, -709, -2112, -2091, +986, -1353, 3501, 1061, 2653, 2582, -1104, 1332, +-3901, -1528, -2638, -2852, 1431, -1081, 4090, 1901, +2371, 2810, -1763, 750, -3815, -1966, -1789, -2485, +1847, -544, 3342, 1750, 1466, 2159, -1630, 530, +-2857, -1440, -1352, -1962, 1349, -649, 2793, 1233, +1668, 1997, -1235, 817, -3047, -1227, -1863, -2196, +1408, -971, 3509, 1412, 2101, 2510, -1625, 1054, +-3813, -1645, -2122, -2778, 1771, -1133, 4005, 1800, +2336, 3002, -1641, 1241, -3980, -1829, -2511, -3138, +1369, -1357, 4046, 1772, 2950, 3172, -1117, 1455, +-4107, -1622, -3015, -3110, 1085, -1541, 4067, 1474, +3043, 3010, -981, 1534, -3776, -1327, -2691, -2835, +845, -1583, 3360, 1096, 2658, 2767, -442, 1834, +-2983, -914, -2632, -3004, 140, -2193, 2882, 1003, +3034, 3499, 67, 2416, -3074, -1380, -3096, -3996, +124, -2325, 3313, 1915, 3239, 4218, -298, 1923, +-3421, -2325, -2929, -4041, 493, -1439, 3347, 2368, +2965, 3601, -394, 1211, -3239, -2070, -2760, -3251, +316, -1327, 3104, 1722, 3002, 3192, -102, 1593, +-3054, -1581, -2897, -3363, 106, -1748, 3026, 1694, +3087, 3541, -2, 1673, -3056, -1974, -2981, -3616, +186, -1407, 3238, 2263, 3090, 3636, -368, 1142, +-3446, -2540, -2816, -3701, 788, -932, 3620, 2829, +2771, 3834, -953, 827, -3604, -3094, -2490, -4021, +1064, -787, 3497, 3307, 2662, 4163, -721, 762, +-3326, -3404, -2804, -4170, 461, -701, 3394, 3346, +3214, 4017, -192, 641, -3389, -3183, -3182, -3748, +265, -554, 3413, 2932, 3168, 3416, -254, 546, +-3198, -2696, -2739, -3248, 391, -587, 2981, 2631, +2629, 3304, -231, 587, -2735, -2870, -2480, -3507, +249, -377, 2775, 3297, 2745, 3620, -99, 36, +-2972, -3682, -2804, -3617, 401, 277, 3262, 3915, +2877, 3517, -466, -484, -3272, -3995, -2623, -3429, +715, 590, 3121, 4006, 2428, 3400, -442, -704, +-2683, -4098, -2238, -3273, 266, 896, 2411, 4097, +2412, 3069, 152, -1006, -2284, -3992, -2549, -3015, +-161, 957, 2578, 3998, 2851, 3123, 110, -928, +-2889, -4165, -2827, -3283, 335, 972, 3240, 4346, +2793, 3384, -500, -1093, -3190, -4497, -2567, -3356, +514, 1218, 3065, 4538, 2741, 3213, -144, -1326, +-2873, -4415, -2836, -3070, -106, 1332, 2837, 4321, +3151, 3005, 326, -1400, -2808, -4389, -3019, -2922, +-204, 1660, 2788, 4501, 2895, 2603, 98, -2042, +-2602, -4381, -2469, -2154, 148, 2205, 2472, 4048, +2238, 1789, -216, -2157, -2294, -3687, -1951, -1589, +337, 1986, 2334, 3387, 1962, 1505, -388, -1828, +-2366, -3269, -1893, -1573, 551, 1830, 2520, 3484, +2012, 1595, -591, -2225, -2685, -3869, -2004, -1396, +807, 2841, 2898, 4076, 2056, 955, -878, -3254, +-2988, -4000, -2073, -622, 1038, 3276, 3167, 3755, +2076, 532, -1044, -3047, -3124, -3475, -2077, -582, +1007, 2651, 3195, 3125, 2225, 637, -957, -2213, +-3204, -2765, -2242, -689, 979, 1848, 3269, 2392, +2259, 587, -1009, -1562, -3209, -2010, -2136, -463, +1080, 1266, 3149, 1678, 2009, 504, -1099, -1046, +-2995, -1641, -1885, -675, 1070, 964, 3016, 1876, +1907, 902, -1131, -1133, -3167, -2253, -1868, -1042, +1413, 1320, 3372, 2478, 1757, 1138, -1702, -1337, +-3477, -2566, -1600, -1322, 1951, 1138, 3487, 2559, +1467, 1574, -1952, -939, -3439, -2557, -1522, -1705, +1926, 791, 3407, 2504, 1549, 1702, -1777, -801, +-3392, -2423, -1620, -1581, 1769, 832, 3365, 2359, +1453, 1490, -1776, -938, -3160, -2448, -1239, -1465, +1857, 1098, 2847, 2602, 837, 1435, -1817, -1266, +-2468, -2718, -652, -1447, 1799, 1331, 2397, 2794, +429, 1488, -2025, -1386, -2423, -2920, -253, -1536, +2449, 1521, 2647, 3149, -299, 1482, -2946, -1943, +-2468, -3446, 695, -1166, 3128, 2612, 2288, 3628, +-1066, 458, -3033, -3357, -1875, -3429, 1033, 401, +2672, 3788, 1613, 2887, -980, -1086, -2261, -3767, +-1233, -2440, 829, 1362, 1893, 3644, 924, 2197, +-971, -1549, -1567, -3696, -398, -1952, 1060, 1884, +1334, 3730, -35, 1470, -1390, -2434, -952, -3546, +504, -677, 1281, 2886, 728, 3027, -640, -331, +-1133, -3069, -397, -2097, 482, 1107, 679, 2743, +409, 1102, -180, -1498, -359, -2050, -280, -295, +-185, 1399, 17, 1149, 379, -230, 492, -931, +128, -263, -444, 443, -662, 59, -80, -550, +708, -100, 741, 962, -257, 826, -977, -809, +-447, -1777, 781, -314, 1138, 1908, -34, 1826, +-1274, -815, -861, -2629, 687, -1121, 1412, 2039, +335, 2663, -1023, -186, -1049, -2899, 284, -1911, +1193, 1492, 490, 2949, -865, 657, -831, -2307, +222, -2214, 1038, 463, 548, 2331, -541, 1216, +-939, -1062, -181, -1856, 452, -565, 634, 1085, +434, 1434, 177, 461, -432, -940, -961, -1446, +-845, -647, 685, 896, 1968, 1700, 1205, 841, +-1265, -1091, -2474, -2034, -900, -865, 2013, 1349, +2730, 2288, 219, 679, -2555, -1755, -2223, -2386, +728, -325, 2916, 2204, 1770, 2316, -1480, -239, +-3084, -2580, -1097, -2024, 2276, 713, 3354, 2690, +718, 1728, -2903, -1031, -3350, -2837, 100, -1463, +3349, 1496, 3080, 2903, -516, 897, -3317, -2178, +-2294, -2642, 1106, 65, 2816, 2558, 1615, 1887, +-895, -875, -2102, -2445, -1110, -1094, 806, 1135, +1837, 1899, 1206, 720, -644, -804, -1991, -1495, +-1066, -1010, 1283, 377, 2366, 1645, 850, 1543, +-1734, -503, -2279, -2329, -235, -1599, 2066, 1340, +2024, 2669, 178, 811, -1500, -2037, -1719, -2156, +-482, 6, 1275, 1712, 2092, 1297, 1054, 129, +-1274, -796, -2372, -1253, -723, -975, 1922, 474, +2421, 1882, 103, 1284, -2185, -1039, -1675, -2173, +879, -649, 2357, 1526, 1159, 1586, -1246, -184, +-2151, -1451, -707, -819, 1591, 519, 2322, 1177, +861, 472, -1379, -606, -2349, -1159, -1113, -455, +1491, 657, 2877, 1219, 1495, 533, -1478, -621, +-3004, -1381, -1228, -751, 2000, 723, 2996, 1633, +713, 625, -2086, -1299, -2201, -1518, 170, 351, +2194, 1679, 1717, 334, -608, -1542, -2050, -1046, +-1180, 1248, 1155, 1765, 2516, -270, 1183, -1980, +-1701, -1076, -2748, 1011, -569, 1638, 2479, 523, +2791, -950, 112, -1276, -2608, -387, -2160, 905, +758, 1143, 2595, 23, 1335, -1182, -1173, -809, +-1860, 645, -73, 1295, 1619, 238, 993, -1154, +-780, -1271, -1204, 106, 121, 1486, 1326, 1285, +841, -363, -654, -1692, -1079, -1203, -217, 479, +948, 1472, 1113, 1053, -54, -96, -1076, -1075, +-663, -1447, 660, -545, 1411, 1345, 359, 2114, +-1290, 299, -1193, -2088, 662, -1928, 1709, 581, +712, 2081, -1104, 991, -1382, -820, 119, -1373, +1349, -736, 820, 351, -507, 1223, -802, 1155, +7, -360, 720, -1701, 338, -1161, -417, 771, +-391, 1771, 248, 821, 589, -849, 328, -1558, +-209, -872, -469, 794, -202, 1754, 105, 791, +623, -1291, 595, -1760, -78, 18, -703, 1611, +-505, 844, 221, -769, 857, -987, 619, 139, +-323, 685, -824, 53, -356, -541, 560, -194, +962, 550, 232, 621, -852, -401, -743, -1105, +400, -310, 968, 1256, 308, 1175, -585, -733, +-457, -1725, 184, -171, 369, 1513, -106, 889, +-11, -841, 434, -949, 261, 308, -555, 481, +-721, -314, 202, -306, 1106, 727, 658, 671, +-712, -693, -1154, -1363, -167, -95, 1083, 1407, +978, 1262, -239, -527, -1013, -1674, -520, -961, +462, 961, 788, 1789, 284, 481, -385, -1421, +-387, -1494, -27, 117, 73, 1436, 20, 927, +179, -353, 412, -1163, 276, -756, -486, 334, +-1016, 1226, -124, 802, 1196, -690, 1263, -1525, +-388, -364, -1778, 1246, -945, 1125, 1163, -325, +1810, -1089, 381, -264, -1403, 382, -1585, 223, +-10, -84, 1571, 240, 1426, 242, -287, -277, +-1797, -562, -1214, -51, 989, 368, 2013, 407, +273, 60, -1757, -249, -1343, -543, 819, -290, +1878, 557, 326, 1017, -1580, -7, -1362, -1260, +518, -1098, 1560, 686, 894, 1622, -777, 723, +-1485, -1032, -486, -1542, 955, -574, 1069, 996, +56, 1513, -739, 563, -497, -1059, 213, -1497, +162, -278, -77, 1115, 51, 1100, 307, -85, +-88, -923, -332, -603, -122, 238, 401, 718, +139, 234, -494, -504, -544, -507, 448, 283, +943, 566, 282, -62, -837, -564, -1135, -95, +-133, 554, 1167, 165, 1041, -521, -200, -424, +-1108, 408, -700, 608, 285, 92, 718, -464, +313, -547, -100, -232, -398, 408, -438, 754, +-55, 423, 686, -596, 448, -920, -592, -225, +-1058, 559, 149, 642, 1254, 254, 778, -215, +-920, -554, -1281, -533, -148, 168, 983, 713, +711, 340, -39, -427, -458, -454, -388, 227, +-313, 345, 18, -235, 428, -403, 522, 123, +58, 522, -563, 159, -634, -423, 41, -380, +662, 175, 485, 404, -381, 67, -818, -503, +-99, -259, 809, 476, 520, 707, -411, -233, +-715, -958, -182, -303, 377, 673, 426, 506, +282, -168, 24, -142, -522, 212, -781, -293, +-80, -839, 917, -12, 886, 1196, -223, 876, +-1038, -662, -681, -1274, 267, -301, 813, 593, +453, 734, -78, 380, -535, -86, -585, -801, +-189, -859, 456, 152, 824, 1397, 466, 832, +-676, -800, -1304, -1667, -299, -387, 1315, 1372, +1400, 1624, -346, -83, -1776, -1782, -865, -1474, +1072, 677, 1401, 1975, 49, 877, -974, -1158, +-678, -1545, 92, -71, 374, 961, 392, 626, +242, -155, -154, -247, -478, -74, -250, -359, +180, -317, 259, 382, 183, 869, 302, 172, +84, -942, -751, -934, -872, 341, 372, 1108, +1569, 706, 893, -488, -1184, -1035, -1887, -653, +-422, 288, 1533, 1050, 1778, 925, 227, -294, +-1532, -1224, -1762, -918, -274, 482, 1669, 1220, +1847, 474, -40, -611, -1740, -820, -1495, -3, +332, 630, 1696, 300, 1170, -424, -478, -561, +-1510, 149, -936, 768, 685, 343, 1684, -488, +627, -745, -1114, -120, -1416, 521, -77, 437, +1118, 52, 916, -325, -202, -212, -656, 102, +-421, 189, -51, -202, 217, -420, 325, 28, +400, 948, 136, 636, -387, -799, -691, -1519, +-173, -176, 794, 1622, 990, 1231, -112, -645, +-1246, -1621, -792, -494, 865, 954, 1529, 1112, +79, 46, -1349, -784, -966, -784, 445, 111, +1121, 676, 423, 414, -270, -195, -367, -362, +-557, 56, -497, -127, 309, -303, 1208, 14, +933, 883, -642, 625, -1624, -843, -688, -1449, +1130, 88, 1680, 1620, 214, 1022, -1320, -1116, +-1044, -1687, 431, 217, 1098, 1617, 265, 802, +-590, -1218, -397, -1440, 258, 499, 195, 1654, +-95, 467, -25, -1511, 269, -1259, 72, 844, +-355, 1691, -377, 162, 133, -1546, 635, -1231, +605, 844, -73, 1673, -923, 484, -842, -1320, +218, -1608, 1537, 81, 1110, 1705, -744, 1416, +-1754, -618, -621, -2061, 1198, -1035, 1562, 1339, +44, 2086, -1260, 297, -954, -1899, 359, -1663, +1178, 558, 518, 1944, -811, 989, -992, -1088, +245, -1762, 1230, -249, 396, 1378, -981, 1251, +-822, -403, 540, -1372, 1184, -460, 79, 826, +-1060, 866, -469, -178, 608, -841, 929, -227, +53, 475, -886, 462, -576, -7, 403, -346, +796, -301, 299, -172, -585, 194, -629, 623, +124, 381, 620, -413, 250, -919, -307, -358, +-391, 675, 22, 944, 375, 312, 360, -645, +-36, -980, -320, -425, -297, 539, 145, 1112, +377, 582, 225, -514, -108, -1199, 21, -655, +-1, 408, -319, 1134, -485, 875, 294, -126, +1007, -1275, 536, -1308, -946, 60, -1269, 1700, +39, 1582, 1294, -389, 948, -1903, -440, -1475, +-1187, 470, -538, 1789, 575, 1517, 1230, -171, +601, -1790, -801, -1892, -1448, -106, -339, 2030, +1261, 2274, 1696, 149, -17, -2265, -1665, -2385, +-1327, -134, 395, 2241, 1436, 2297, 964, 207, +-320, -1910, -978, -2078, -753, -527, -52, 1231, +590, 2011, 757, 1233, 489, -647, -338, -2328, +-854, -1918, -637, 552, 231, 2702, 1006, 2025, +810, -726, -178, -2525, -957, -1741, -728, 520, +64, 1969, 942, 1620, 895, -86, 48, -1487, +-888, -1586, -1137, -259, -249, 1015, 1061, 1379, +1381, 560, 378, -323, -1171, -1053, -1750, -1115, +-508, -509, 1382, 844, 2033, 1871, 653, 1239, +-1414, -832, -2217, -2627, -784, -1734, 1506, 1064, +2235, 3046, 1013, 1836, -1175, -1258, -2296, -2951, +-1307, -1472, 928, 1096, 2307, 2099, 1748, 1084, +-749, -355, -2581, -815, -1838, -1003, 756, -894, +2515, -233, 1670, 1287, -848, 1890, -2196, 819, +-1177, -1330, 839, -2311, 1486, -1345, 481, 822, +-432, 2392, -353, 2111, 15, 9, -330, -2478, +-593, -2934, 68, -757, 1024, 2511, 971, 3545, +-126, 1321, -1274, -2355, -1080, -3823, 17, -1662, +1121, 1889, 1230, 3662, 76, 2027, -1053, -1117, +-1133, -3178, -174, -2512, 680, 46, 825, 2747, +395, 3140, -81, 896, -651, -2450, -754, -3630, +-237, -1494, 655, 2181, 810, 3813, 231, 1701, +-166, -2008, -271, -3531, -597, -1361, -868, 1860, +-43, 2526, 1481, 545, 1711, -1292, -317, -1022, +-2204, 225, -1695, 436, 534, -485, 1938, -717, +1337, 338, -207, 1481, -1169, 1168, -1083, -625, +-486, -2067, 190, -1659, 862, 382, 1319, 2315, +964, 2194, -638, 190, -2287, -2108, -1975, -2655, +682, -1116, 3135, 1569, 2531, 3184, -751, 2189, +-3510, -1167, -2863, -3672, 623, -2744, 3512, 974, +3117, 3718, -421, 2631, -3714, -856, -3243, -3185, +542, -2174, 3778, 767, 3083, 2467, -911, 1466, +-3702, -859, -2590, -1906, 1149, -597, 3690, 1390, +2247, 1569, -1569, -480, -3658, -2282, -1854, -1307, +2074, 1629, 3619, 3150, 1284, 1127, -2223, -2605, +-3414, -3646, -1113, -948, 2139, 2785, 3210, 3707, +1209, 1209, -2083, -2177, -3378, -3666, -1151, -2039, +2334, 1423, 3250, 3859, 663, 2657, -2453, -1018, +-2721, -3675, -90, -2543, 2403, 524, 2075, 2701, +-317, 2241, -2106, 319, -1589, -1570, 554, -2179, +1984, -1002, 1256, 1084, -754, 1934, -1888, 729, +-964, -953, 713, -964, 1675, 258, 927, 580, +-671, -432, -1403, -1081, -926, -137, 179, 1385, +1075, 1574, 1204, 154, 587, -1585, -747, -1959, +-1775, -646, -1398, 1213, 624, 2056, 2550, 1355, +2015, -253, -641, -1714, -2849, -2141, -2464, -1148, +506, 970, 2951, 2807, 2508, 2650, -179, 77, +-2564, -3084, -2482, -3863, -218, -1229, 1754, 2756, +1998, 4440, 933, 2277, -567, -1759, -1532, -4137, +-1713, -3096, -637, 195, 1168, 3056, 2347, 3548, +1523, 1542, -712, -1539, -2265, -3445, -2074, -2894, +-126, -225, 1889, 2585, 2548, 3725, 1054, 2134, +-1358, -1334, -2835, -4160, -1717, -3718, 838, 153, +2725, 4203, 1981, 4532, -330, 596, -2232, -3778, +-2047, -4325, -48, -902, 1622, 2791, 1707, 3315, +495, 969, -853, -1450, -1425, -1976, -802, -1051, +385, 158, 1209, 849, 947, 1131, -123, 779, +-913, -208, -764, -1210, -203, -1141, 369, -17, +900, 1237, 742, 1124, -153, -52, -1264, -1171, +-1212, -992, 239, 129, 1509, 1074, 1361, 908, +-48, 51, -1429, -949, -1661, -1150, -592, -406, +1312, 881, 2456, 1561, 1211, 691, -1356, -809, +-2889, -1545, -1597, -904, 1302, 300, 2747, 951, +1652, 1166, -548, 899, -1974, -135, -1809, -1602, +-603, -2219, 972, -768, 1976, 1969, 1665, 3223, +-41, 1610, -2109, -1850, -2274, -3787, -314, -2266, +1703, 1319, 1877, 3699, 501, 2622, -611, -543, +-632, -2811, -861, -2612, -1083, -510, -390, 1555, +1427, 2287, 2409, 1462, 1000, -261, -1680, -1698, +-2867, -1876, -1350, -861, 1314, 804, 2580, 1872, +1584, 1584, -553, 32, -1861, -1428, -1569, -1589, +-478, -588, 691, 491, 1537, 823, 1496, 900, +352, 836, -1349, 323, -2149, -1080, -1080, -2037, +1021, -1364, 2118, 1000, 1517, 2740, -75, 1981, +-1791, -674, -2186, -2705, -604, -2125, 1616, 293, +2472, 2016, 871, 1695, -1603, 72, -2262, -917, +-556, -803, 1340, -410, 1473, -287, 152, -131, +-879, 470, -657, 1173, 386, 1070, 368, -168, +-478, -1697, -618, -2001, 386, -272, 1267, 1933, +640, 2517, -1070, 706, -1556, -1709, -318, -2510, +1109, -1155, 1262, 939, 336, 2162, -481, 1798, +-859, 100, -943, -1882, -397, -2556, 695, -881, +1599, 1838, 1132, 2992, -656, 1188, -2036, -1751, +-1677, -2869, 401, -1290, 2264, 1419, 2083, 2402, +-228, 1214, -2351, -766, -2039, -1561, 214, -1104, +2101, -208, 1618, 516, -468, 1136, -1501, 1199, +-720, 275, 638, -1080, 853, -1671, -228, -768, +-1006, 584, -301, 1465, 920, 1148, 1349, 171, +259, -843, -1311, -1212, -1702, -787, -635, -107, +1089, 613, 1898, 1172, 1271, 1336, -270, 475, +-1727, -1273, -2060, -2535, -900, -1607, 1070, 981, +2723, 3172, 2209, 2568, -285, -260, -2844, -2942, +-3097, -3184, -630, -701, 2197, 2040, 3131, 2997, +1576, 1716, -848, -532, -2518, -2147, -2329, -2479, +-768, -1106, 1310, 1187, 2515, 2516, 2136, 1891, +208, -22, -2151, -1461, -2859, -1700, -1343, -1377, +1170, -432, 2431, 1138, 1929, 2599, 394, 2162, +-1043, -502, -2040, -3117, -2049, -2905, -467, -148, +1799, 2586, 2697, 2638, 1338, 603, -725, -1238, +-2014, -1477, -1719, -833, -834, -361, 286, -61, +1553, 825, 2320, 1573, 1479, 1151, -824, -351, +-2835, -1622, -2867, -1699, -515, -707, 2396, 688, +3578, 1968, 1809, 1900, -1220, 349, -3235, -1821, +-2580, -2497, -244, -1037, 1956, 1244, 2488, 2179, +1513, 1278, -167, -488, -1672, -1205, -2078, -924, +-1383, -264, 146, 64, 1706, 262, 2360, 636, +1467, 728, -625, 365, -2433, -363, -2509, -770, +-829, -866, 1462, -508, 2798, 183, 2177, 1174, +95, 1507, -2126, 562, -2965, -1004, -1636, -1884, +842, -1375, 2772, 69, 2714, 1601, 718, 2268, +-1848, 1203, -2986, -1145, -1779, -2651, 410, -1898, +1995, 435, 2226, 2013, 1335, 1879, -467, 742, +-2180, -662, -2617, -1780, -816, -1767, 1688, -292, +2724, 1605, 1410, 1773, -649, 348, -1658, -897, +-1399, -697, -526, 46, 275, -84, 717, -751, +1058, -441, 1173, 761, 490, 1660, -992, 829, +-2204, -659, -1603, -1610, 506, -1371, 2330, -329, +2086, 1138, 164, 1946, -1480, 1374, -1699, -571, +-943, -2025, 178, -1761, 841, -138, 1159, 1275, +1090, 1510, 392, 868, -864, -106, -1734, -878, +-1480, -1178, 124, -785, 1808, -9, 1862, 745, +436, 973, -942, 833, -1390, 484, -851, -282, +-216, -1412, 193, -2137, 816, -919, 1307, 1737, +935, 3324, -186, 1867, -1543, -1353, -2043, -3302, +-866, -2403, 1302, 158, 2521, 2258, 1640, 2534, +-432, 1206, -2142, -725, -1975, -2093, -562, -2035, +913, -752, 1714, 969, 1577, 2066, 441, 1924, +-1012, 438, -1899, -1516, -1592, -2420, -127, -1462, +1578, 562, 2187, 1941, 1131, 1920, -763, 698, +-1967, -903, -1686, -1989, -318, -1643, 928, -12, +1680, 1479, 1537, 1733, 310, 789, -1402, -427, +-2265, -1317, -1145, -1474, 914, -503, 2056, 984, +1480, 1645, -271, 786, -1368, -688, -1209, -1324, +-241, -541, 481, 629, 502, 857, 339, -141, +316, -952, 222, -211, -134, 1107, -691, 1035, +-822, -583, -236, -1537, 688, -500, 1044, 928, +495, 916, -474, -126, -907, -455, -522, 94, +294, 351, 543, -258, 67, -747, -238, -272, +-8, 654, 358, 875, 431, 93, -298, -709, +-878, -405, -768, 202, 200, 247, 1067, -323, +1324, -309, 230, 469, -1187, 743, -1686, 23, +-829, -763, 735, -563, 1866, 282, 1506, 536, +-155, 15, -1671, -399, -1868, -169, -588, 480, +957, 531, 1711, -14, 1289, -775, 143, -769, +-1073, 5, -1815, 887, -1290, 903, 104, 39, +1709, -851, 2098, -753, 955, 23, -978, 659, +-2266, 513, -2005, -168, -237, -634, 1701, -399, +2555, 517, 1586, 993, -640, 265, -2456, -943, +-2603, -1256, -706, -275, 1659, 958, 2867, 1356, +1837, 650, -519, -607, -2218, -1382, -2266, -946, +-930, 223, 793, 919, 1947, 754, 1951, 358, +877, 172, -967, -297, -2454, -1159, -2164, -1339, +-211, 40, 1992, 1691, 2475, 1781, 1012, 46, +-882, -1430, -1530, -1306, -1301, -237, -649, 466, +-51, 522, 857, 433, 1674, 382, 1561, 158, +112, -257, -1667, -664, -2332, -684, -1367, -159, +537, 582, 2088, 773, 2348, 311, 1005, -190, +-1055, -291, -2497, -284, -2203, -274, -361, -12, +1626, 261, 2314, 33, 1392, -320, -117, 89, +-1126, 964, -1608, 924, -1617, -525, -953, -1827, +912, -1413, 2913, 366, 2783, 1794, 134, 1863, +-2834, 661, -3646, -982, -1692, -2280, 1433, -1993, +3461, 69, 3096, 2294, 504, 2647, -2569, 736, +-3827, -1653, -2124, -2417, 1128, -1203, 3376, 630, +3044, 1401, 372, 1030, -2130, 411, -2994, 64, +-1702, -473, 589, -1123, 2200, -1188, 2276, -160, +906, 1024, -1157, 1385, -2140, 749, -1588, -160, +30, -765, 1255, -1003, 1348, -954, 803, -393, +282, 704, -390, 1800, -1363, 1710, -1998, 15, +-930, -2170, 1483, -2605, 3143, -495, 2132, 2049, +-1029, 2353, -3464, 373, -2915, -1225, 35, -846, +2642, 63, 3014, -52, 1208, -704, -1206, -411, +-2520, 682, -2063, 1396, -354, 992, 1348, -143, +2043, -1363, 1413, -1798, 287, -856, -1033, 977, +-1925, 2122, -1799, 1496, -327, -229, 1685, -1518, +2429, -1574, 1376, -787, -642, 129, -1866, 1081, +-1745, 1723, -649, 1377, 482, -319, 1300, -2194, +1478, -2401, 928, -426, -169, 1906, -1246, 2440, +-1789, 862, -1299, -952, 261, -1604, 1783, -1123, +2151, -241, 985, 569, -825, 1078, -2199, 821, +-2033, 43, -475, -335, 1492, -297, 2246, -464, +1259, -1033, -391, -731, -1434, 902, -1404, 2259, +-806, 1492, 97, -912, 977, -2549, 1392, -1807, +953, 445, 8, 2017, -1078, 1814, -1689, 360, +-1132, -993, 420, -1561, 1904, -1119, 1960, 19, +294, 1104, -1598, 1514, -2104, 816, -865, -482, +913, -1475, 1826, -1309, 1341, -102, -90, 1063, +-1333, 1204, -1501, 385, -619, -430, 670, -595, +1328, -303, 1014, -197, 10, -365, -930, -243, +-962, 611, -377, 1317, 46, 777, 251, -869, +454, -1827, 891, -987, 756, 714, -296, 1489, +-1548, 834, -1629, -154, -241, -744, 1485, -635, +2039, -262, 905, 203, -896, 312, -1744, 114, +-1131, -19, -98, 163, 667, 347, 968, 100, +1162, -319, 713, -542, -514, -317, -1779, 42, +-1626, 448, 234, 706, 1758, 569, 1559, -118, +20, -973, -1079, -1062, -930, -80, 53, 1121, +453, 1252, 81, 88, -457, -1088, -185, -906, +643, 174, 890, 782, 68, 273, -914, -257, +-1028, -233, -183, 25, 587, -76, 746, -212, +383, 62, -246, 369, -499, 264, -270, -108, +90, -259, 55, -209, -131, -241, -16, -392, +288, -192, 301, 468, 51, 1186, -128, 1037, +-118, -332, -251, -1829, -414, -1972, -40, -429, +763, 1523, 898, 2354, -22, 1667, -881, -130, +-829, -2092, 10, -2809, 617, -1420, 709, 1297, +302, 2908, -298, 2143, -701, 23, -523, -1516, +66, -1766, 583, -1174, 663, -178, 281, 877, +-340, 1414, -1070, 1071, -925, 192, 206, -496, +1402, -706, 1316, -610, -87, -536, -1436, -368, +-1473, 199, -245, 1132, 916, 1501, 1182, 418, +561, -1311, -90, -1855, -444, -411, -652, 1276, +-779, 1261, -565, -291, 285, -1323, 1424, -569, +1669, 991, 462, 1413, -1352, 258, -2255, -1152, +-1329, -1497, 687, -682, 2253, 337, 2045, 1124, +371, 1357, -1344, 793, -2005, -532, -1403, -1738, +-77, -1642, 1315, -159, 2065, 1444, 1313, 1693, +-509, 549, -1879, -789, -1670, -1059, -417, -544, +732, 139, 1234, 364, 1083, 410, 415, 379, +-590, 183, -1261, -245, -1133, -624, -126, -394, +789, 273, 1016, 688, 641, 467, 15, 26, +-434, -165, -809, -241, -882, -516, -355, -643, +771, -99, 1497, 953, 1096, 1407, -393, 566, +-1632, -836, -1453, -1435, 12, -828, 1251, 144, +1499, 578, 744, 638, -482, 609, -1304, 387, +-1270, -194, -266, -730, 910, -748, 1238, -419, +727, -136, 21, 153, -519, 590, -1006, 868, +-1218, 585, -549, -219, 785, -814, 1792, -957, +1446, -567, -153, -17, -1550, 492, -1856, 701, +-1006, 541, 432, 295, 1606, 153, 1859, -119, +663, -726, -1038, -1287, -1853, -958, -1142, 380, +180, 1772, 1000, 1881, 947, 523, 569, -1179, +138, -1601, -278, -733, -699, 204, -779, 301, +-283, 210, 397, 660, 703, 1056, 665, 622, +303, -398, -195, -1017, -565, -948, -594, -561, +-303, -57, 162, 587, 399, 1172, 489, 1162, +495, 374, -18, -812, -793, -1454, -919, -1156, +-163, -68, 776, 763, 998, 976, 9, 565, +-895, 61, -817, -395, 36, -604, 645, -467, +470, -65, -9, 182, -274, 37, -145, -74, +-77, 145, -271, 305, -314, 45, 104, -301, +689, -176, 700, 139, 25, 178, -616, -120, +-624, -300, -268, -354, 89, -90, 416, 451, +669, 932, 512, 650, -128, -312, -624, -1055, +-527, -955, -67, -211, 229, 692, 170, 1215, +89, 960, 88, -142, 335, -1131, 333, -907, +-188, 184, -872, 847, -845, 317, -82, -423, +806, -381, 949, 332, 193, 697, -374, 244, +-451, -507, -425, -805, -473, -350, -214, 440, +336, 853, 863, 492, 576, -414, -191, -1097, +-679, -852, -411, 310, -31, 1324, 116, 1048, +9, -331, 111, -1287, 435, -918, 515, -27, +36, 361, -539, 319, -552, 461, -109, 503, +228, 4, 281, -566, 219, -648, 130, -280, +123, -5, 74, 192, -133, 465, -359, 537, +-422, 204, -217, -294, 197, -564, 428, -383, +401, 38, 217, 519, -94, 569, -459, 38, +-596, -615, -384, -476, 98, 461, 435, 1106, +350, 443, 72, -842, -38, -1369, -28, -457, +-62, 1028, -236, 1507, -440, 560, -196, -848, +300, -1194, 569, -251, 474, 611, -195, 501, +-581, -184, -301, -455, 329, -101, 562, 314, +240, 515, -370, 329, -588, -276, -226, -847, +321, -874, 544, -205, 310, 564, 58, 986, +-121, 979, -244, 234, -577, -1033, -500, -1787, +102, -943, 749, 765, 694, 1567, 86, 721, +-518, -395, -664, -625, -393, -55, 120, 275, +382, 11, 405, -446, 67, -723, -355, -396, +-407, 373, -26, 1147, 343, 1277, 346, 522, +-122, -606, -546, -1467, -298, -1432, 357, -341, +700, 982, 326, 1476, -438, 898, -746, 63, +-421, -319, 323, -487, 894, -604, 976, -460, +92, -124, -1101, 103, -1428, 184, -354, 560, +1007, 1027, 1330, 584, 564, -645, -121, -1388, +-535, -690, -817, 443, -891, 464, -441, -300, +512, -377, 1258, 650, 1110, 1345, 63, 569, +-991, -1030, -1245, -1775, -535, -1061, 399, 413, +701, 1183, 247, 896, -127, 104, -80, -256, +179, -191, 155, -229, -32, -408, -297, -365, +-422, -52, -257, 176, 197, 259, 482, 399, +306, 493, -217, 96, -185, -548, 393, -677, +542, -78, -140, 587, -830, 498, -849, -26, +-47, -374, 868, -219, 1088, 56, 353, 199, +-556, 179, -681, 135, -120, 156, 207, 219, +-221, 73, -542, -448, -30, -804, 885, -412, +1029, 574, 151, 1075, -914, 535, -1265, -442, +-681, -781, 421, -239, 1182, 387, 958, 321, +25, -401, -793, -659, -926, -68, -377, 665, +163, 529, 488, -167, 554, -370, 342, 22, +-9, 115, -307, -341, -382, -552, -353, -43, +-141, 510, 238, 372, 495, -42, 387, -116, +114, 23, -93, -71, -372, -306, -485, -171, +-202, 138, 403, 262, 724, 175, 350, 121, +-460, 37, -831, -213, -464, -391, 350, -234, +944, 228, 770, 686, -145, 728, -1002, 65, +-1049, -849, -301, -1044, 592, -152, 969, 812, +644, 811, -9, 120, -512, -271, -641, -36, +-472, 126, -240, -132, 82, -509, 497, -489, +866, -56, 677, 537, -203, 857, -1033, 567, +-1053, -288, -226, -1010, 670, -821, 1101, -8, +669, 639, -205, 534, -833, 68, -649, -251, +-25, -242, 406, -31, 359, 51, 265, -80, +208, -203, -63, -40, -508, 173, -682, 37, +-191, -209, 585, 62, 942, 537, 427, 393, +-473, -525, -903, -1036, -500, -361, 164, 709, +363, 983, 152, 224, 74, -489, 300, -414, +363, 207, -85, 401, -700, -96, -811, -709, +-240, -440, 625, 445, 972, 1045, 585, 537, +-346, -411, -910, -769, -654, -359, 195, 209, +742, 478, 600, 429, 43, 39, -443, -568, +-617, -737, -364, -111, 179, 664, 670, 718, +639, 178, 178, -171, -380, -181, -594, -282, +-402, -481, -7, -456, 207, -87, 183, 227, +152, 386, 335, 558, 390, 578, -25, 107, +-760, -678, -921, -968, -177, -437, 753, 237, +970, 347, 281, 8, -565, -131, -775, 150, +-334, 529, 232, 632, 456, 275, 336, -460, +176, -1011, 59, -898, -195, -226, -690, 449, +-847, 698, -26, 739, 1172, 660, 1414, 322, +239, -373, -1073, -1024, -1255, -925, -346, -60, +546, 745, 644, 728, 243, 31, -23, -406, +-55, -161, 24, 296, -28, 502, -222, 323, +-291, -46, -100, -523, 173, -846, 327, -585, +276, 191, 36, 858, -237, 793, -390, 162, +-319, -355, 40, -359, 420, -161, 478, -74, +96, -219, -311, -238, -470, -48, -268, 267, +95, 403, 383, 160, 331, -178, -70, -309, +-291, -120, -129, 68, 54, 105, 20, 48, +-48, -96, 165, -276, 416, -296, 178, 46, +-409, 461, -705, 567, -421, 232, 193, -250, +768, -674, 884, -717, 413, -197, -447, 684, +-1106, 1111, -977, 559, -102, -432, 757, -873, +1038, -478, 630, 59, -75, 210, -596, 209, +-732, 459, -509, 582, -116, 112, 270, -690, +651, -880, 715, -147, 291, 702, -470, 804, +-791, 98, -507, -507, -20, -436, 333, 20, +417, 180, 327, -53, 150, -146, -95, 150, +-308, 394, -350, 205, -185, -217, 247, -389, +489, -230, 141, -52, -542, -16, -654, -43, +145, 22, 970, 206, 893, 398, -157, 423, +-1091, -6, -1035, -676, -112, -1027, 730, -500, +924, 532, 431, 1089, -230, 686, -587, -169, +-479, -668, -74, -521, 232, -57, 249, 276, +26, 248, -39, -34, 51, -201, 200, -125, +8, 109, -367, 335, -381, 469, 126, 277, +440, -389, 256, -941, -187, -651, -286, 354, +-149, 958, -29, 596, 142, -112, 411, -267, +395, 8, -158, 89, -726, -209, -625, -478, +78, -423, 693, -135, 631, 319, 87, 755, +-333, 859, -283, 368, -36, -435, 32, -980, +-240, -913, -363, -351, -59, 363, 563, 745, +855, 576, 393, 159, -558, -91, -1137, -69, +-802, -188, 351, -420, 1301, -457, 1027, -139, +-322, 288, -1365, 445, -955, 267, 360, -87, +1149, -286, 791, -68, -206, 295, -863, 275, +-680, -213, 124, -642, 672, -484, 432, 71, +-303, 539, -529, 686, -8, 481, 493, 37, +387, -525, -133, -809, -555, -586, -506, -36, +-18, 440, 532, 646, 722, 623, 234, 375, +-456, -50, -720, -515, -278, -814, 356, -807, +465, -269, 80, 635, -283, 1298, -246, 967, +86, -160, 325, -1090, 251, -1055, -107, -198, +-328, 724, -248, 916, -94, 210, 88, -664, +186, -716, 212, 4, -6, 461, -196, 211, +77, -63, 476, 207, 196, 490, -621, 21, +-984, -711, -274, -832, 724, -245, 995, 373, +468, 572, -202, 554, -578, 387, -604, 0, +-271, -478, 80, -661, 365, -404, 428, 46, +109, 351, -161, 415, -174, 205, -26, -97, +154, -209, 136, -15, -211, 212, -458, 140, +-273, -218, 244, -486, 618, -328, 475, 234, +-96, 601, -447, 268, -305, -376, -22, -417, +48, 207, -135, 566, -156, 117, 274, -447, +591, -466, 310, -199, -298, -116, -588, -25, +-363, 449, 47, 859, 342, 560, 394, -337, +144, -989, -231, -821, -321, -113, -109, 518, +98, 676, 71, 312, 59, -163, 128, -302, +169, 52, 10, 350, -274, 76, -381, -506, +-147, -602, 248, -22, 395, 578, 188, 512, +-139, 0, -227, -282, -75, -21, 103, 276, +51, 108, -108, -330, -193, -505, -103, -239, +189, 205, 382, 570, 238, 637, -230, 220, +-544, -478, -272, -795, 302, -396, 512, 214, +168, 476, -212, 372, -234, 149, -199, -155, +-117, -477, 97, -400, 334, 92, 250, 512, +-91, 352, -270, -156, -140, -446, 52, -241, +160, 90, 61, 177, -101, -59, -178, -178, +-22, 52, 191, 392, 70, 322, -85, -206, +-24, -573, 152, -334, 113, 217, -220, 427, +-298, 149, -20, -197, 203, -301, 123, -74, +4, 298, 12, 495, 32, 186, -13, -348, +-25, -483, 18, -104, -51, 179, -255, 80, +-169, 20, 255, 221, 387, 307, 109, 62, +-171, -189, -196, -218, -27, -131, 28, -28, +26, 169, -54, 264, -85, 103, -17, -151, +221, -222, 220, -122, -38, -63, -247, 45, +-185, 243, -6, 376, 223, 250, 272, -93, +12, -492, -375, -774, -511, -599, -12, 210, +585, 1122, 618, 1156, 46, 123, -484, -998, +-585, -1204, -316, -538, 157, 295, 637, 817, +623, 801, -48, 250, -817, -437, -725, -708, +224, -491, 904, -114, 598, 213, -242, 499, +-704, 505, -564, 170, 20, -181, 555, -247, +573, -277, 74, -432, -393, -308, -355, 340, +6, 874, 188, 578, 20, -304, -148, -770, +-71, -344, 298, 467, 481, 744, 74, 139, +-719, -690, -903, -825, -66, -74, 1028, 766, +1173, 866, 105, 275, -1040, -373, -1175, -610, +-286, -426, 689, 9, 1043, 404, 422, 362, +-365, -107, -702, -380, -360, -48, 159, 436, +341, 317, 49, -293, -133, -612, 29, -277, +261, 342, 191, 609, -123, 240, -428, -490, +-316, -792, 237, -259, 557, 564, 199, 737, +-379, 202, -399, -334, 133, -498, 369, -458, +58, -259, -319, 267, -193, 785, 182, 615, +323, -209, 123, -897, -181, -713, -306, 94, +-77, 769, 144, 753, 86, 141, -130, -510, +-160, -643, 89, -241, 322, 225, 337, 336, +98, 207, -247, 202, -584, 272, -621, 101, +-105, -384, 616, -717, 815, -514, 361, 209, +-280, 924, -426, 1043, -249, 312, -176, -743, +-81, -1181, 174, -625, 345, 348, 109, 813, +-181, 502, -224, -67, 7, -243, 251, 14, +259, 113, 61, -206, -128, -507, -231, -244, +-221, 301, -164, 444, -86, 105, 188, -186, +446, -162, 356, -42, -58, 13, -345, 82, +-269, 100, -74, -78, 47, -295, 35, -254, +59, 109, 82, 368, 61, 251, -54, -44, +-104, -261, -88, -289, 94, -186, 201, 121, +181, 471, -48, 464, -313, 5, -352, -523, +-56, -622, 274, -253, 449, 282, 337, 619, +-117, 517, -625, 34, -602, -350, 77, -314, +777, -31, 788, 91, 68, -74, -614, -193, +-769, -41, -433, 331, 191, 496, 637, 179, +579, -416, 79, -584, -305, -102, -258, 542, +27, 559, 15, -95, -246, -696, -349, -593, +15, 109, 517, 712, 603, 689, 20, 114, +-587, -561, -601, -758, -91, -340, 523, 277, +643, 528, 135, 360, -473, 123, -652, -87, +-279, -421, 326, -628, 625, -250, 363, 499, +-136, 766, -469, 268, -342, -363, 54, -542, +339, -323, 317, -38, 82, 274, -237, 479, +-368, 383, -241, -49, 41, -518, 299, -630, +422, -300, 318, 309, 19, 769, -430, 689, +-619, 43, -315, -682, 163, -804, 440, -246, +449, 423, 259, 607, -26, 283, -316, -160, +-504, -348, -447, -204, -23, 72, 496, 184, +731, 77, 395, 4, -337, 72, -872, 70, +-653, -111, 182, -276, 940, -246, 771, -6, +-135, 290, -868, 492, -730, 315, 77, -223, +712, -608, 621, -477, 49, 4, -418, 379, +-415, 508, -80, 428, 152, 5, 112, -592, +-50, -837, -29, -359, 121, 463, 273, 875, +212, 595, -116, -23, -416, -482, -400, -571, +-112, -386, 201, -123, 377, 89, 398, 326, +184, 586, -153, 608, -482, 81, -454, -736, +-79, -1039, 283, -491, 343, 420, 156, 934, +41, 803, 91, 217, -19, -500, -384, -915, +-583, -758, -248, -110, 478, 597, 885, 926, +557, 682, -278, -18, -852, -628, -673, -715, +43, -399, 571, -104, 455, 155, 20, 567, +-174, 807, -99, 385, 14, -508, -9, -933, +-64, -485, -29, 261, 58, 568, 25, 368, +-66, 104, -174, -64, -52, -246, 196, -385, +338, -331, 169, -18, -175, 414, -350, 684, +-182, 473, 20, -233, 9, -871, -17, -717, +155, 68, 286, 667, 155, 524, -121, 0, +-202, -283, -130, -165, -131, 59, -135, 80, +85, -112, 309, -174, 265, 61, -27, 276, +-218, 105, -119, -328, 26, -440, 25, -38, +-74, 471, -82, 579, 76, 219, 259, -268, +193, -545, -66, -539, -298, -303, -326, 166, +-99, 705, 269, 870, 450, 299, 297, -684, +-129, -1084, -510, -465, -452, 603, -16, 930, +340, 231, 364, -590, 188, -573, 53, 141, +-85, 568, -343, 241, -456, -338, -219, -479, +253, -106, 535, 338, 453, 444, 121, 168, +-231, -176, -532, -323, -554, -238, -213, -84, +319, 31, 696, 133, 644, 243, 91, 312, +-559, 266, -752, -76, -387, -472, 225, -569, +568, -192, 445, 288, 56, 375, -274, 193, +-332, 85, -124, 160, 105, 81, 150, -272, +78, -516, -41, -277, -66, 182, -68, 299, +-53, 85, 54, 50, 222, 322, 153, 269, +-96, -395, -315, -897, -245, -446, 50, 628, +259, 1071, 199, 391, 31, -559, -67, -795, +-52, -304, -14, 168, -72, 222, -145, 151, +-82, 145, 122, 194, 206, 170, 110, 11, +14, -263, -5, -490, -91, -346, -223, 111, +-209, 400, -8, 311, 255, 123, 378, 81, +246, 50, -97, -117, -448, -314, -533, -366, +-117, -288, 392, 19, 567, 552, 300, 915, +-46, 549, -342, -494, -532, -1293, -475, -1013, +32, 120, 726, 1100, 906, 1183, 211, 471, +-697, -387, -971, -891, -413, -848, 346, -414, +693, 109, 517, 569, 88, 863, -261, 733, +-374, 93, -287, -715, -71, -1033, 119, -661, +152, 43, 78, 677, 48, 886, 159, 525, +198, -185, -60, -720, -397, -686, -414, -236, +44, 284, 546, 630, 470, 575, -192, 68, +-670, -551, -425, -737, 333, -302, 782, 317, +469, 630, -238, 501, -680, 116, -642, -351, +-205, -626, 413, -491, 817, 96, 638, 638, +-93, 608, -807, 25, -836, -553, -134, -510, +541, 93, 658, 554, 264, 305, -121, -332, +-240, -456, -177, 40, -197, 357, -259, 38, +-139, -261, 270, 32, 576, 421, 461, 195, +-58, -354, -505, -453, -562, -58, -267, 240, +174, 183, 519, -9, 500, -20, 17, 80, +-472, 85, -441, -40, 34, -226, 434, -210, +300, 15, -147, 213, -352, 176, -215, -51, +57, -166, 248, -98, 248, 60, 166, 151, +-57, 134, -344, -31, -466, -227, -155, -202, +391, 66, 673, 223, 333, 31, -307, -130, +-651, 5, -412, 172, 88, 35, 414, -175, +401, -55, 142, 151, -136, 41, -282, -204, +-217, -191, -77, 104, 79, 320, 256, 236, +339, -19, 101, -284, -324, -316, -547, -93, +-227, 189, 299, 265, 502, 126, 327, 0, +79, 13, -156, 13, -372, -137, -541, -332, +-368, -307, 212, 2, 731, 376, 712, 551, +136, 459, -541, 55, -758, -504, -330, -905, +283, -723, 595, 92, 328, 942, -297, 1013, +-600, 201, -189, -601, 482, -554, 725, 15, +215, 162, -546, -292, -709, -495, -254, 18, +257, 721, 388, 761, 259, 111, 87, -610, +-3, -779, -91, -269, -160, 410, -187, 631, +-111, 260, 49, -292, 211, -459, 179, -212, +21, 171, -79, 362, -60, 211, -110, -113, +-248, -322, -101, -198, 406, 169, 631, 435, +164, 285, -587, -210, -832, -600, -298, -512, +466, 42, 763, 583, 465, 699, -157, 290, +-573, -269, -460, -524, 29, -432, 336, -172, +252, 38, -33, 202, -82, 325, 25, 338, +38, 281, -130, 46, -224, -395, -96, -766, +239, -565, 428, 207, 271, 830, -134, 741, +-425, 112, -439, -451, -219, -605, 130, -360, +460, 72, 641, 364, 339, 294, -350, -45, +-834, -246, -591, -53, 105, 282, 626, 320, +580, -82, 125, -493, -252, -446, -319, 29, +-227, 501, -167, 481, -31, 29, 233, -370, +450, -336, 231, -32, -284, 103, -471, 102, +-84, 238, 284, 358, 164, -1, -119, -610, +-72, -676, 165, 53, 86, 750, -218, 590, +-224, -127, 121, -503, 326, -190, 135, 209, +-168, 126, -209, -225, -41, -214, 91, 195, +91, 436, -27, 123, -129, -374, -56, -491, +107, -100, 205, 406, 131, 535, -49, 177, +-200, -307, -203, -469, -72, -175, 112, 198, +170, 230, 46, -73, -58, -299, -12, -114, +87, 348, 34, 547, -67, 271, -109, -273, +-92, -630, -95, -548, 12, -120, 231, 329, +341, 451, 106, 343, -270, 248, -444, 87, +-247, -327, 144, -690, 415, -453, 379, 211, +-2, 552, -378, 256, -312, -104, 120, -46, +388, 216, 107, 209, -400, -199, -504, -603, +-28, -538, 601, 62, 719, 710, 136, 741, +-615, 111, -764, -531, -167, -529, 517, 2, +556, 370, 41, 170, -382, -286, -381, -463, +-72, -138, 282, 451, 480, 801, 297, 464, +-206, -383, -659, -927, -546, -592, 101, 185, +651, 578, 608, 396, 10, 4, -528, -210, +-504, -176, 2, 11, 415, 128, 301, 25, +-165, -96, -320, -47, 1, 58, 359, -9, +270, -184, -170, -155, -501, 77, -351, 269, +132, 259, 484, 78, 490, -173, 156, -310, +-257, -222, -477, -29, -450, 48, -121, 56, +399, 213, 586, 400, 213, 215, -321, -333, +-438, -607, -64, -242, 234, 266, 44, 304, +-149, 83, 41, 66, 343, 135, 286, -42, +-190, -307, -639, -257, -549, 56, 82, 282, +758, 280, 860, 87, 196, -209, -657, -366, +-876, -188, -373, 152, 280, 319, 601, 254, +484, 159, 100, 9, -338, -269, -544, -487, +-227, -372, 284, 60, 463, 474, 164, 610, +-190, 359, -270, -167, -112, -657, -6, -664, +75, -115, 137, 530, 144, 659, 35, 216, +-79, -329, -136, -540, -128, -313, -137, 121, +-94, 396, 144, 297, 427, 14, 445, -75, +29, -30, -594, -229, -803, -517, -297, -364, +446, 300, 786, 805, 525, 628, -74, 4, +-480, -598, -468, -770, -182, -394, 114, 237, +233, 575, 103, 402, -9, 126, 59, 23, +141, -107, 40, -410, -177, -553, -323, -173, +-113, 451, 269, 761, 432, 465, 152, -160, +-297, -666, -521, -642, -251, -83, 236, 525, +491, 598, 350, 132, -10, -256, -339, -204, +-373, -78, -143, -121, 147, -92, 252, 175, +90, 322, -126, 119, -117, -97, 100, -115, +229, -157, 48, -324, -277, -216, -363, 328, +16, 742, 405, 432, 334, -432, -148, -999, +-456, -629, -212, 368, 291, 1000, 474, 629, +182, -271, -275, -792, -501, -581, -337, -36, +114, 385, 544, 527, 550, 348, 73, -97, +-437, -481, -567, -427, -250, -44, 199, 157, +387, 45, 282, 34, 80, 361, -107, 534, +-218, 77, -212, -651, -110, -887, 111, -367, +230, 466, 71, 978, -125, 769, -30, -40, +190, -775, 146, -797, -276, -204, -522, 396, +-82, 567, 569, 347, 604, -26, -18, -297, +-582, -248, -501, -2, 77, 166, 431, 104, +279, -12, -77, -56, -265, -34, -141, 15, +99, 85, 193, 36, 143, -97, -9, -116, +-220, 71, -316, 187, -99, -15, 322, -267, +499, -162, 109, 189, -425, 268, -459, -13, +18, -216, 392, -151, 233, -136, -177, -188, +-243, 70, 60, 553, 235, 533, 27, -214, +-286, -867, -208, -627, 207, 187, 368, 667, +54, 410, -305, -106, -271, -256, 25, -44, +147, 59, 51, -151, 107, -282, 237, -7, +78, 329, -316, 285, -484, -25, -170, -164, +363, -70, 543, -11, 239, -8, -207, 93, +-474, 187, -302, 47, 152, -230, 381, -220, +181, 145, -155, 386, -258, 168, -69, -195, +166, -213, 199, 51, 60, 164, -164, -14, +-258, -198, -25, -110, 296, 180, 245, 312, +-155, 79, -414, -238, -134, -213, 334, 117, +421, 222, 67, -63, -293, -341, -398, -262, +-211, 23, 100, 259, 359, 332, 378, 244, +189, -13, -139, -276, -414, -418, -490, -433, +-221, -279, 281, 127, 616, 593, 461, 673, +-14, 242, -362, -316, -375, -561, -267, -496, +-106, -320, 142, -37, 353, 365, 331, 600, +127, 390, -92, -58, -193, -258, -255, -201, +-278, -218, -152, -304, 181, -120, 486, 312, +456, 522, 25, 280, -508, -83, -583, -213, +-103, -145, 395, -84, 406, -77, 39, 52, +-188, 322, -122, 372, -35, -74, -60, -578, +11, -418, 169, 349, 184, 781, -16, 379, +-205, -308, -222, -556, -89, -334, 57, -29, +182, 179, 251, 290, 148, 262, -55, 104, +-144, -59, -138, -162, -183, -255, -221, -311, +-68, -172, 255, 137, 525, 356, 426, 334, +-65, 152, -562, -139, -630, -485, -198, -646, +361, -245, 525, 491, 269, 843, -76, 423, +-243, -359, -244, -859, -112, -701, 99, 36, +207, 790, 74, 814, -155, 54, -134, -654, +141, -593, 278, -50, 65, 263, -336, 207, +-489, 109, -149, 115, 472, 117, 780, 32, +332, -159, -509, -331, -893, -257, -407, 148, +387, 543, 624, 472, 247, 1, -110, -375, +-144, -383, -48, -166, -40, 78, -123, 334, +-149, 474, -17, 248, 177, -237, 245, -520, +144, -329, -131, 83, -311, 349, -178, 346, +107, 166, 309, -73, 269, -208, -27, -262, +-329, -327, -356, -258, -93, 199, 182, 738, +264, 629, 199, -178, 156, -822, 27, -716, +-253, -156, -410, 299, -234, 491, 95, 450, +292, 133, 229, -281, 180, -483, 150, -367, +-96, -97, -438, 170, -471, 354, -47, 297, +476, -32, 582, -322, 156, -285, -418, -20, +-588, 167, -182, 224, 430, 237, 572, 67, +109, -347, -449, -573, -496, -179, -16, 520, +414, 756, 353, 302, 17, -309, -257, -552, +-279, -348, -74, 63, 111, 364, 162, 337, +111, 87, -9, -93, -70, -82, 3, 2, +56, 60, -43, 15, -199, -152, -225, -249, +64, 35, 395, 523, 332, 542, -74, -118, +-377, -769, -301, -665, 55, 67, 241, 699, +120, 714, -23, 164, -63, -531, -39, -787, +-13, -360, -24, 350, -1, 605, 80, 199, +74, -318, -52, -370, -123, -58, -81, 199, +62, 177, 157, -22, 88, -216, -22, -242, +-62, -28, -119, 168, -190, 70, -138, -143, +108, -64, 397, 261, 416, 349, 66, 10, +-396, -409, -588, -528, -365, -249, 124, 229, +503, 593, 515, 557, 187, 150, -215, -319, +-397, -536, -307, -403, -32, 9, 236, 432, +292, 517, 74, 190, -269, -228, -375, -329, +-47, -72, 432, 206, 554, 207, 161, -42, +-386, -229, -605, -86, -337, 242, 87, 366, +326, 67, 340, -348, 244, -418, 75, -82, +-109, 311, -309, 401, -342, 169, -155, -163, +135, -372, 306, -283, 293, 42, 108, 265, +-144, 138, -300, -145, -260, -191, -49, 10, +256, 155, 374, 85, 163, -79, -237, -223, +-453, -229, -221, -34, 280, 248, 461, 269, +139, -35, -348, -313, -421, -245, -11, 54, +443, 270, 400, 226, -70, -5, -451, -265, +-414, -374, -5, -199, 400, 208, 434, 582, +117, 554, -271, 38, -421, -576, -187, -720, +208, -274, 365, 307, 153, 527, -162, 408, +-251, 252, -82, 153, 105, -98, 89, -495, +-2, -678, -18, -363, 54, 280, 117, 802, +44, 872, -142, 367, -302, -473, -204, -1050, +174, -793, 472, 129, 359, 907, -130, 855, +-479, 91, -352, -654, 54, -738, 305, -174, +203, 405, -51, 463, -123, 114, 5, -161, +105, -207, 38, -203, -67, -167, -79, 23, +-40, 235, -66, 140, -124, -193, 1, -293, +268, 12, 316, 333, 60, 246, -251, -142, +-316, -406, -116, -304, 105, 14, 169, 253, +80, 240, -82, 33, -141, -146, 22, -73, +268, 139, 270, 231, -12, 12, -315, -314, +-385, -418, -228, -148, 21, 322, 295, 593, +463, 429, 362, -23, 8, -354, -383, -382, +-499, -213, -300, -3, 67, 219, 324, 347, +321, 287, 134, 66, -22, -119, -19, -174, +-33, -145, -212, -131, -393, -87, -221, 81, +290, 351, 638, 479, 456, 170, -172, -421, +-750, -793, -684, -529, 10, 218, 739, 850, +852, 832, 203, 123, -621, -711, -914, -957, +-424, -449, 360, 296, 811, 593, 555, 334, +-109, -16, -543, -108, -441, -73, -72, -157, +209, -285, 214, -223, 120, -13, -12, 158, +-106, 250, -59, 289, 80, 138, 91, -240, +-63, -559, -193, -388, -82, 190, 155, 645, +189, 521, -15, -55, -180, -503, -133, -444, +62, -47, 236, 247, 189, 267, -82, 174, +-312, 124, -233, 50, 105, -59, 301, -122, +175, -92, -121, -48, -276, -23, -159, 15, +118, 112, 347, 248, 321, 296, -53, 159, +-467, -181, -493, -475, -91, -411, 344, 38, +486, 443, 268, 435, -83, 53, -282, -236, +-247, -203, -63, -35, 73, -4, 24, -137, +-64, -179, -22, 20, 138, 322, 291, 335, +203, -81, -134, -546, -441, -498, -382, 60, +60, 548, 472, 445, 390, -104, -86, -549, +-415, -499, -316, -21, 36, 422, 384, 433, +456, 37, 105, -312, -406, -296, -655, -14, +-292, 179, 350, 135, 611, -49, 312, -181, +-113, -84, -268, 186, -165, 387, -62, 219, +-50, -200, -107, -454, -46, -246, 145, 193, +293, 420, 249, 298, 18, 47, -197, -135, +-279, -217, -278, -139, -175, 86, 125, 294, +469, 214, 483, -99, 52, -349, -434, -185, +-536, 263, -172, 501, 268, 199, 406, -360, +190, -543, -151, -198, -253, 283, -55, 424, +121, 242, 45, -82, -108, -354, -106, -452, +92, -217, 243, 215, 141, 488, -159, 302, +-373, -152, -261, -455, 191, -391, 536, -59, +363, 187, -206, 231, -552, 73, -338, -94, +87, -147, 321, -47, 235, 71, 56, 48, +-8, -110, 6, -184, -47, -12, -193, 223, +-296, 228, -141, -64, 191, -288, 397, -154, +262, 219, -5, 407, -154, 203, -219, -174, +-245, -379, -177, -264, 71, 74, 327, 378, +305, 384, 80, 169, -128, -54, -249, -130, +-210, -198, -35, -263, 137, -150, 135, 186, +42, 464, 19, 418, 116, 113, 116, -210, +-134, -402, -356, -435, -320, -226, -33, 158, +350, 546, 585, 590, 413, 197, -136, -421, +-656, -804, -678, -567, -198, 126, 413, 681, +673, 575, 466, -14, -70, -508, -517, -500, +-493, -187, -94, 124, 283, 236, 344, 238, +185, 129, 17, -73, -212, -295, -379, -430, +-270, -313, 122, 51, 467, 483, 395, 628, +68, 361, -247, -218, -395, -735, -303, -825, +-58, -297, 200, 540, 315, 1033, 255, 800, +101, 18, -99, -716, -261, -947, -288, -528, +-108, 267, 143, 924, 212, 910, 186, 260, +91, -520, -86, -816, -225, -487, -179, 185, +19, 689, 149, 614, 81, 104, 32, -390, +61, -438, 23, -196, -132, 51, -167, 220, +19, 401, 150, 383, 67, -55, -84, -612, +-122, -668, -37, -115, 81, 452, 177, 588, +183, 317, -14, -35, -243, -373, -259, -555, +-103, -482, 32, -125, 145, 310, 299, 609, +314, 565, 13, 69, -415, -617, -524, -942, +-132, -492, 379, 320, 505, 813, 240, 588, +-178, -2, -389, -460, -275, -544, -72, -363, +42, -35, 198, 350, 419, 622, 429, 505, +-58, -85, -670, -700, -700, -781, -27, -116, +594, 696, 561, 963, 72, 445, -341, -377, +-334, -873, -40, -696, 219, 53, 207, 807, +-28, 958, -178, 378, -92, -390, 25, -810, +-36, -654, -72, -141, 99, 512, 264, 899, +176, 681, -53, -87, -184, -826, -174, -926, +-191, -319, -123, 521, 114, 914, 368, 594, +342, -182, 21, -713, -283, -663, -376, -230, +-229, 147, 117, 369, 347, 489, 276, 385, +19, -47, -163, -582, -196, -744, -185, -431, +-139, 118, 75, 540, 365, 691, 361, 425, +4, -173, -333, -765, -392, -854, -189, -310, +110, 468, 340, 924, 375, 659, 137, -135, +-268, -808, -467, -721, -338, -48, 18, 522, +422, 527, 572, 234, 287, -25, -241, -194, +-635, -338, -541, -273, -48, 77, 454, 416, +614, 412, 331, 62, -170, -220, -493, -234, +-411, -38, -62, 77, 187, 103, 297, 162, +293, 246, 130, 112, -216, -316, -454, -619, +-250, -285, 177, 541, 372, 1001, 206, 548, +-78, -478, -159, -1121, -142, -901, -93, -2, +50, 908, 128, 1179, 85, 537, -63, -584, +-126, -1262, -1, -923, 90, 129, 64, 945, +-44, 903, -81, 101, -10, -662, 110, -779, +130, -258, -27, 309, -201, 488, -220, 327, +-74, 15, 177, -313, 264, -571, 195, -487, +57, 38, -125, 709, -240, 925, -228, 463, +-141, -446, 8, -1131, 183, -1068, 315, -197, +288, 921, 77, 1453, -223, 997, -413, -197, +-352, -1268, -45, -1427, 353, -460, 512, 838, +236, 1421, -235, 846, -455, -191, -261, -852, +65, -873, 218, -454, 205, 253, 152, 1000, +55, 1127, -121, 275, -268, -965, -221, -1415, +-19, -689, 171, 529, 231, 1241, 173, 1080, +24, 237, -136, -746, -253, -1278, -186, -963, +97, 71, 318, 1108, 233, 1361, -101, 537, +-390, -778, -340, -1575, 23, -1198, 371, 70, +484, 1352, 341, 1737, -77, 890, -563, -749, +-779, -2065, -460, -1950, 321, -303, 988, 1690, +959, 2394, 194, 1278, -772, -709, -1215, -2034, +-762, -1837, 284, -427, 1125, 1125, 1128, 1812, +289, 1254, -777, -118, -1239, -1367, -757, -1661, +262, -703, 1067, 822, 1022, 1780, 294, 1393, +-539, -6, -987, -1357, -849, -1768, -221, -990, +636, 522, 1206, 1828, 994, 1971, -7, 678, +-1192, -1250, -1595, -2361, -749, -1736, 772, 299, +1821, 2199, 1463, 2406, -83, 676, -1585, -1574, +-1817, -2454, -663, -1329, 891, 677, 1678, 1945, +1195, 1692, -62, 319, -1095, -1187, -1266, -1848, +-625, -1189, 304, 309, 909, 1543, 950, 1613, +434, 547, -345, -861, -912, -1677, -893, -1410, +-276, -151, 587, 1309, 1078, 1904, 838, 1071, +-77, -668, -1023, -1993, -1226, -1821, -457, -203, +678, 1619, 1270, 2184, 941, 1048, -75, -903, +-1054, -2155, -1233, -1737, -495, 58, 584, 1825, +1181, 2123, 871, 709, 0, -1194, -761, -2019, +-952, -1213, -542, 421, 172, 1607, 766, 1535, +783, 356, 313, -1015, -267, -1507, -627, -798, +-601, 462, -277, 1247, 190, 1056, 581, 148, +652, -816, 289, -1209, -322, -716, -745, 404, +-610, 1323, 2, 1224, 591, 97, 635, -1203, +233, -1581, -209, -679, -433, 817, -444, 1640, +-281, 1098, 170, -304, 623, -1374, 600, -1322, +34, -265, -519, 964, -618, 1400, -279, 651, +146, -737, 434, -1529, 490, -946, 277, 518, +-183, 1494, -559, 1169, -529, -78, -88, -1238, +443, -1481, 675, -625, 368, 753, -261, 1634, +-715, 1254, -613, -163, -57, -1520, 553, -1643, +826, -414, 540, 1178, -180, 1798, -867, 977, +-957, -633, -281, -1747, 621, -1512, 1042, -103, +717, 1505, -101, 2075, -862, 1051, -1051, -982, +-414, -2377, 602, -1882, 1180, 256, 830, 2279, +-216, 2497, -1125, 658, -1227, -1782, -354, -2801, +897, -1499, 1548, 1101, 966, 2817, -398, 2187, +-1496, -252, -1454, -2473, -362, -2695, 988, -796, +1667, 1730, 1145, 2929, -268, 1893, -1516, -636, +-1598, -2771, -461, -2853, 1000, -710, 1698, 2095, +1121, 3311, -323, 1867, -1550, -1122, -1563, -3168, +-307, -2595, 1187, -20, 1688, 2379, 868, 2782, +-591, 1082, -1588, -1344, -1367, -2654, -65, -1895, +1323, 310, 1653, 2229, 657, 2350, -795, 652, +-1601, -1554, -1190, -2516, 50, -1534, 1248, 711, +1551, 2455, 721, 2270, -660, 186, -1565, -2092, +-1342, -2626, -96, -991, 1252, 1474, 1743, 2648, +865, 1603, -754, -758, -1779, -2242, -1364, -1716, +99, 79, 1323, 1439, 1501, 1518, 652, 623, +-541, -504, -1243, -1223, -1133, -1155, -287, -197, +654, 950, 1091, 1361, 809, 579, 116, -573, +-616, -1147, -957, -776, -713, 36, -9, 666, +636, 800, 884, 437, 603, -126, 1, -603, +-649, -707, -965, -399, -656, 232, 129, 707, +823, 640, 1012, 27, 596, -528, -177, -574, +-950, -232, -1237, 148, -686, 288, 558, 321, +1553, 293, 1375, 187, 19, -244, -1450, -777, +-1797, -883, -655, -140, 1078, 1025, 1992, 1616, +1258, 934, -510, -742, -1927, -2047, -1833, -1871, +-253, -88, 1618, 1993, 2242, 2740, 1033, 1213, +-1109, -1540, -2402, -3204, -1647, -2147, 590, 833, +2287, 3219, 2000, 2968, -55, 206, -2048, -2832, +-2248, -3710, -486, -1505, 1707, 2130, 2436, 4300, +1081, 2942, -1218, -987, -2530, -4371, -1689, -4253, +573, -575, 2420, 3837, 2242, 5206, 201, 2194, +-2029, -2789, -2697, -5545, -1092, -3652, 1470, 1220, +2927, 5155, 1982, 4846, -634, 683, -2822, -4157, +-2751, -5681, -382, -2664, 2296, 2629, 3183, 5800, +1461, 4205, -1485, -780, -3293, -5073, -2323, -5119, +569, -1166, 3066, 3698, 2998, 5390, 443, 2742, +-2603, -2170, -3567, -5105, -1557, -3776, 1867, 590, +3898, 4320, 2750, 4401, -738, 954, -3723, -3270, +-3727, -4624, -686, -2218, 2901, 2056, 4220, 4399, +2079, 3054, -1730, -852, -4081, -3741, -2993, -3259, +451, -93, 3404, 2842, 3465, 3131, 739, 856, +-2523, -1999, -3598, -2926, -1692, -1393, 1588, 1330, +3447, 2804, 2357, 1962, -629, -677, -2963, -2749, +-2735, -2441, -356, 87, 2242, 2492, 2939, 2688, +1177, 586, -1529, -1973, -2899, -2760, -1707, -1220, +879, 1423, 2621, 2682, 2014, 1616, -300, -998, +-2214, -2575, -2104, -1848, -204, 628, 1746, 2390, +2003, 1961, 602, -212, -1179, -2133, -1792, -2151, +-983, -395, 563, 1779, 1639, 2338, 1398, 939, +-53, -1429, -1546, -2410, -1681, -1364, -342, 947, +1307, 2311, 1791, 1694, 774, -415, -843, -2111, +-1718, -1949, -1230, -157, 215, 1786, 1530, 2070, +1563, 576, 364, -1445, -1101, -1873, -1566, -558, +-854, 1206, 508, 1451, 1320, 242, 1100, -1137, +121, -1135, -930, 70, -1216, 1240, -535, 1222, +657, 45, 1190, -1241, 711, -1538, -447, -455, +-1122, 1079, -772, 1805, 207, 852, 835, -891, +785, -1811, 309, -871, -321, 864, -759, 1643, +-854, 722, -308, -862, 501, -1578, 1164, -804, +866, 732, -101, 1632, -1035, 1135, -1173, -432, +-431, -1714, 661, -1553, 1347, 87, 939, 1711, +-185, 1750, -1349, 115, -1543, -1687, -415, -1959, +1240, -342, 2019, 1742, 1148, 2294, -709, 619, +-2151, -1791, -1938, -2677, -210, -1140, 1731, 1452, +2453, 2898, 1308, 1898, -910, -749, -2512, -2934, +-2099, -2649, 13, -54, 2140, 2699, 2435, 3076, +729, 740, -1563, -2256, -2418, -3138, -1160, -1193, +995, 1785, 2152, 3047, 1384, 1516, -436, -1391, +-1779, -2966, -1511, -1690, -36, 1164, 1397, 2860, +1541, 1854, 379, -776, -1063, -2670, -1453, -2170, +-537, 281, 820, 2636, 1340, 2658, 585, 172, +-759, -2690, -1424, -3112, -630, -558, 946, 2692, +1693, 3484, 710, 1039, -1115, -2439, -1953, -3743, +-954, -1736, 1007, 1867, 2074, 3863, 1329, 2429, +-618, -1218, -2097, -3779, -1711, -2905, 193, 560, +1995, 3408, 1979, 3134, 249, 116, -1734, -2963, +-2212, -3410, -836, -918, 1284, 2456, 2475, 3660, +1606, 1687, -760, -1896, -2560, -3756, -2178, -2325, +90, 1255, 2267, 3535, 2457, 2681, 516, -565, +-1717, -3137, -2328, -2903, -978, -57, 1112, 2820, +2059, 3085, 1150, 554, -657, -2481, -1644, -3126, +-1167, -1008, 293, 2016, 1400, 3056, 1187, 1479, +-178, -1389, -1311, -2863, -1213, -1863, 84, 814, +1380, 2708, 1434, 2212, 83, -284, -1386, -2490, +-1724, -2442, -619, -231, 1110, 2094, 2028, 2517, +1295, 832, -540, -1389, -1937, -2304, -1884, -1358, +-258, 516, 1562, 1789, 2156, 1621, 887, 227, +-1019, -1196, -2080, -1571, -1281, -618, 521, 626, +1815, 1148, 1488, 670, -1, -124, -1467, -625, +-1684, -672, -540, -377, 1032, 118, 1782, 606, +1036, 691, -466, 214, -1577, -460, -1320, -753, +-182, -436, 1039, 127, 1250, 573, 626, 525, +-353, 189, -853, -341, -722, -539, -169, -338, +339, 257, 499, 555, 370, 284, 72, -328, +-166, -590, -333, -193, -290, 446, -110, 744, +202, 325, 388, -417, 325, -903, -102, -596, +-476, 293, -465, 1092, -17, 989, 513, -135, +586, -1239, 121, -1212, -464, 99, -548, 1394, +-233, 1419, 198, -39, 382, -1595, 345, -1684, +142, -25, -94, 1868, -355, 2082, -485, 230, +-291, -2113, 155, -2589, 667, -551, 816, 2273, +290, 3025, -769, 884, -1341, -2263, -742, -3335, +656, -1321, 1580, 2003, 1199, 3498, -251, 1800, +-1532, -1653, -1631, -3699, -379, -2393, 1333, 1246, +2098, 3914, 967, 2890, -1182, -975, -2370, -4079, +-1401, -3238, 910, 638, 2454, 4031, 1818, 3540, +-541, -208, -2393, -3954, -2198, -3910, 20, -241, +2206, 3834, 2550, 4262, 499, 769, -1899, -3499, +-2737, -4414, -1073, -1266, 1489, 2916, 2881, 4256, +1532, 1684, -1146, -2184, -2862, -3777, -1878, -1708, +823, 1731, 2809, 3189, 2176, 1412, -537, -1488, +-2766, -2632, -2477, -1074, 207, 1401, 2724, 2326, +2771, 962, 190, -1185, -2504, -1975, -2994, -926, +-803, 782, 2025, 1440, 3216, 741, 1567, -347, +-1452, -687, -3345, -302, -2240, -2, 868, -78, +3305, -218, 2701, 172, -354, 621, -3073, 548, +-2897, -374, -57, -995, 2745, -587, 2847, 633, +229, 1083, -2429, 301, -2621, -916, -150, -1017, +2290, 81, 2341, 1173, -151, 826, -2507, -684, +-2180, -1573, 704, -583, 2963, 1446, 2081, 2031, +-1261, 250, -3441, -2326, -2012, -2481, 1672, 179, +3719, 3077, 2053, 2667, -1699, -633, -3880, -3400, +-2337, -2443, 1360, 979, 3775, 3150, 2854, 1841, +-482, -983, -3361, -2124, -3453, -980, -771, 464, +2582, 697, 3960, 448, 2133, 519, -1739, 519, +-4235, -422, -3105, -1428, 956, -1023, 4192, 869, +3674, 2021, -314, 970, -3878, -1266, -3756, -2144, +-281, -739, 3093, 1329, 3534, 1946, 967, 624, +-2059, -1070, -3099, -1540, -1614, -594, 1035, 681, +2794, 1206, 2065, 643, -668, -552, -2656, -1257, +-1959, -647, 716, 820, 2493, 1452, 1527, 364, +-1014, -1331, -2176, -1533, -859, 133, 1267, 1697, +1821, 1289, 266, -667, -1664, -1887, -1727, -1193, +328, 707, 2176, 1977, 1736, 1553, -678, -340, +-2538, -2181, -1779, -2218, 894, -157, 2640, 2319, +1518, 2631, -1012, 393, -2435, -2266, -1175, -2450, +1092, -243, 2151, 1917, 934, 1829, -938, 119, +-1877, -1227, -1117, -1241, 480, -352, 1750, 496, +1647, 1115, 145, 1055, -1645, 85, -2252, -1446, +-789, -1696, 1457, -18, 2610, 2008, 1417, 1715, +-1062, -605, -2653, -2152, -1926, -973, 544, 1274, +2562, 1837, 2245, 295, -321, -1365, -2626, -1545, +-2211, -476, 687, 1093, 2950, 2100, 1862, 1420, +-1505, -1361, -3315, -3523, -1389, -2128, 2194, 2350, +3445, 4745, 1203, 2058, -2293, -3165, -3471, -5054, +-1466, -1929, 1933, 2844, 3528, 4617, 1989, 2296, +-1538, -1788, -3647, -4250, -2313, -3003, 1329, 915, +3680, 4064, 2297, 3224, -1359, -789, -3607, -3939, +-2035, -3010, 1531, 976, 3508, 3800, 1784, 2704, +-1707, -1150, -3416, -3665, -1647, -2473, 1658, 1071, +3327, 3307, 1759, 2367, -1603, -619, -3313, -2861, +-1775, -2515, 1629, 101, 3376, 2873, 1683, 3018, +-1856, 54, -3369, -3351, -1554, -3250, 1872, 412, +3318, 3693, 1704, 2813, -1656, -795, -3350, -3194, +-1984, -1955, 1381, 821, 3435, 2348, 2201, 1392, +-1293, -605, -3488, -1725, -2159, -1156, 1349, 462, +3372, 1462, 1846, 1042, -1426, -279, -3040, -1067, +-1248, -824, 1556, -88, 2294, 323, 457, 466, +-1457, 469, -1367, 431, 161, -15, 1052, -716, +553, -1108, -306, -407, -440, 829, -60, 1443, +119, 498, -97, -957, -334, -1514, -44, -598, +630, 861, 886, 1496, 89, 816, -1244, -698, +-1492, -1656, 46, -1154, 1840, 543, 1826, 1705, +-424, 1213, -2255, -468, -1672, -1400, 773, -886, +2286, 257, 1372, 813, -1060, 591, -2058, -7, +-957, -395, 1130, -383, 1778, 66, 546, 307, +-1159, 154, -1426, -223, -239, -206, 1102, 125, +1166, 404, 81, 150, -1043, -224, -1012, -499, +20, -234, 967, 362, 846, 791, -52, 521, +-775, -554, -590, -1076, -49, -482, 348, 690, +345, 901, 402, 156, 198, -380, -354, -169, +-828, 60, -558, -272, 490, -486, 1170, 27, +704, 825, -676, 569, -1343, -429, -620, -1010, +743, -320, 1284, 755, 528, 878, -670, 39, +-989, -836, -415, -880, 334, -149, 558, 545, +505, 928, 144, 594, -413, -233, -710, -1210, +-315, -1198, 473, 113, 812, 1605, 197, 1480, +-655, -344, -613, -1903, 105, -1520, 518, 571, +253, 1973, -124, 1530, -335, -460, -54, -1904, +121, -1672, 163, 112, 11, 1864, -39, 1946, +-75, 161, -32, -1763, -159, -1967, -132, -234, +113, 1675, 575, 1911, 466, 267, -360, -1572, +-964, -1806, -572, -144, 505, 1551, 1073, 1712, +518, 130, -453, -1393, -965, -1483, -561, -280, +399, 1047, 969, 1356, 604, 692, -482, -576, +-1118, -1469, -416, -1195, 776, 309, 1019, 1656, +-8, 1474, -931, -304, -626, -1769, 315, -1481, +820, 328, 405, 1739, -420, 1269, -692, -411, +-286, -1623, 222, -1162, 518, 289, 343, 1337, +87, 1145, -192, 53, -432, -1097, -634, -1314, +-241, -578, 826, 832, 1230, 1476, 278, 849, +-1136, -687, -1486, -1459, -291, -826, 1186, 554, +1471, 1192, 470, 738, -918, -399, -1473, -1042, +-871, -748, 691, 342, 1675, 1216, 1055, 880, +-722, -484, -1655, -1461, -1031, -881, 662, 823, +1650, 1616, 968, 761, -682, -915, -1640, -1488, +-945, -635, 710, 738, 1640, 1326, 952, 824, +-675, -282, -1498, -1178, -1014, -1091, 281, -85, +1399, 1120, 1306, 1188, 3, 193, -1416, -879, +-1363, -936, 34, -125, 1235, 507, 946, 596, +-116, 142, -736, -234, -388, -469, -37, -254, +91, 140, 197, 489, 371, 254, 140, -217, +-203, -511, -422, -255, -198, 247, 137, 483, +218, 223, 239, -352, 118, -665, -63, -280, +-274, 496, -320, 835, -77, 343, 333, -559, +343, -910, 189, -544, -351, 249, -391, 917, +-154, 836, 377, 83, 340, -922, 17, -998, +-313, -138, -134, 811, -21, 809, 148, 103, +6, -475, 131, -452, 29, -188, -151, 149, +-177, 436, -3, 387, 221, -127, 141, -568, +-56, -272, -3, 510, -45, 511, -275, -266, +-297, -724, 205, 32, 729, 964, 377, 594, +-529, -760, -811, -1256, -123, -142, 574, 1275, +426, 1016, -106, -375, -165, -1176, 70, -358, +-148, 611, -351, 533, -111, -349, 624, -376, +678, 288, -176, 641, -1100, -141, -874, -902, +438, -431, 1478, 520, 1043, 767, -458, 24, +-1825, -459, -1216, -167, 614, 180, 1850, -76, +1116, -470, -716, -293, -1612, 491, -741, 843, +674, 303, 1169, -525, 461, -973, -478, -417, +-753, 314, -430, 771, 173, 389, 528, -141, +596, -261, 166, 14, -588, -113, -887, -528, +-240, -522, 926, 569, 1054, 1505, -135, 741, +-1344, -1289, -791, -2270, 697, -444, 1388, 2275, +279, 2553, -856, -258, -965, -2972, -87, -2186, +378, 1190, 483, 3049, 466, 1382, 388, -1741, +-351, -2539, -1092, -486, -927, 1829, 474, 1961, +1612, -31, 1072, -1809, -664, -1574, -1737, 429, +-983, 1925, 725, 1222, 1501, -974, 791, -1925, +-477, -590, -971, 1423, -716, 1585, -198, -188, +441, -1564, 1012, -1049, 878, 596, -126, 1463, +-1375, 714, -1317, -696, 65, -1511, 1354, -699, +1333, 787, 207, 1517, -941, 520, -1307, -902, +-666, -1287, 599, -198, 1431, 906, 827, 844, +-641, -189, -1498, -990, -587, -583, 1022, 475, +1308, 1208, 97, 678, -1143, -644, -1047, -1459, +90, -875, 1012, 535, 933, 1401, -38, 1037, +-839, -21, -823, -976, -111, -1150, 690, -597, +746, 489, 57, 1239, -471, 1149, -453, 2, +-148, -1244, 95, -1581, 159, -386, 287, 1315, +413, 2008, 242, 781, -482, -1336, -1010, -2304, +-590, -1090, 691, 1205, 1408, 2392, 744, 1406, +-841, -717, -1565, -2209, -529, -1780, 942, 45, +1265, 1891, 232, 2137, -826, 591, -877, -1554, +-33, -2358, 548, -1029, 498, 1240, 58, 2294, +-168, 1081, -248, -895, -178, -1835, -147, -967, +6, 277, 250, 973, 364, 888, 260, 571, +-107, -57, -578, -1001, -625, -1445, -190, -676, +774, 1026, 1147, 1944, 395, 1185, -969, -797, +-1483, -2125, -512, -1600, 989, 429, 1509, 2112, +671, 1810, -793, -112, -1455, -1848, -959, -1777, +512, -249, 1559, 1226, 1258, 1609, -319, 961, +-1602, -234, -1375, -1519, 80, -1978, 1252, -770, +1254, 1538, 337, 2875, -527, 1613, -907, -1252, +-800, -3173, -324, -2194, 443, 589, 1075, 2773, +1012, 2563, 17, 427, -1165, -1806, -1406, -2664, +-326, -1472, 1123, 775, 1556, 2591, 493, 2276, +-1068, 38, -1508, -2394, -606, -2660, 867, -532, +1386, 2056, 668, 2684, -478, 881, -981, -1474, +-822, -2513, -197, -1413, 503, 679, 1060, 2228, +969, 1948, -149, 80, -1415, -1840, -1432, -2098, +68, -602, 1624, 1204, 1445, 1630, -161, 629, +-1556, -441, -1308, -774, 190, -340, 1436, -151, +1221, -112, -104, -56, -1386, 405, -1283, 649, +41, 304, 1266, -498, 1359, -791, 10, -267, +-1138, 459, -1226, 679, -68, 124, 1017, -272, +960, -348, -64, -66, -757, -74, -572, -149, +64, 14, 269, 553, 232, 767, 356, 330, +472, -743, -148, -1375, -1173, -993, -1227, 390, +319, 1815, 2001, 1966, 1766, 433, -473, -1848, +-2617, -2933, -2144, -1459, 649, 1638, 3003, 3633, +2363, 2462, -848, -1212, -3266, -3953, -2316, -3216, +997, 511, 3185, 3854, 2156, 3797, -886, 373, +-2808, -3324, -2030, -4171, 530, -1267, 2412, 2583, +1931, 4009, -330, 1796, -2114, -1805, -1569, -3245, +538, -1662, 1710, 930, 861, 1921, -889, 997, +-1286, -174, -11, -425, 1171, -183, 1007, -320, +-377, -741, -1559, -706, -1223, 236, 462, 1235, +2035, 1560, 1821, 585, -444, -1129, -2534, -2349, +-2335, -1865, 407, 503, 2847, 2950, 2500, 3149, +-372, 405, -2742, -3162, -2434, -4115, 286, -1269, +2258, 2907, 2098, 4477, 95, 2027, -1509, -2126, +-1675, -4133, -737, -2592, 596, 897, 1437, 3313, +1339, 2906, 225, 483, -1313, -2133, -1776, -2833, +-627, -1597, 1124, 761, 1889, 2383, 873, 2418, +-929, 587, -1819, -1801, -964, -2979, 744, -1505, +1645, 1419, 915, 3147, -580, 1854, -1351, -1104, +-794, -2823, 331, -1802, 926, 647, 786, 2197, +64, 1679, -559, -141, -851, -1655, -561, -1637, +244, -149, 923, 1393, 968, 1599, 162, 220, +-919, -1379, -1299, -1668, -621, -373, 810, 1340, +1614, 1855, 991, 745, -608, -991, -1802, -2022, +-1388, -1455, 373, 207, 1752, 1984, 1748, 2310, +140, 690, -1612, -1801, -1945, -2826, -700, -1332, +1149, 1337, 1896, 2636, 1141, 1690, -404, -396, +-1446, -1918, -1460, -2061, -523, -807, 739, 1159, +1622, 2420, 1360, 1726, 37, -449, -1429, -2192, +-1888, -2046, -977, -431, 768, 1272, 2045, 2016, +2009, 1423, 239, -181, -1945, -1702, -2712, -1906, +-1151, -533, 1435, 1023, 2737, 1568, 1625, 944, +-480, 3, -2017, -719, -1919, -1102, -497, -875, +1016, -122, 1897, 704, 1217, 1192, -152, 1041, +-1330, 344, -1483, -985, -805, -2044, 344, -1628, +1419, 519, 1812, 2612, 752, 2605, -1258, 139, +-2373, -2401, -1555, -2959, 816, -1060, 2329, 1525, +1896, 2745, -99, 1864, -1810, -342, -1948, -2259, +-509, -2402, 1097, -729, 1801, 1666, 952, 2698, +-576, 1322, -1508, -1272, -1190, -2648, 231, -1415, +1374, 1044, 1112, 2146, -237, 1089, -1134, -686, +-692, -1365, 386, -706, 634, 151, 66, 556, +-318, 551, 108, 305, 401, 26, -43, -438, +-785, -626, -548, -463, 472, 283, 1194, 907, +606, 857, -741, -155, -1365, -1017, -621, -987, +668, -50, 1292, 686, 659, 806, -342, 516, +-781, 267, -715, -304, -311, -1171, 85, -1603, +591, -460, 1001, 1793, 737, 2978, -307, 1372, +-1281, -2006, -1448, -3896, -322, -2234, 1150, 1569, +1833, 3908, 934, 2804, -698, -435, -1611, -2906, +-1120, -2872, 34, -1014, 800, 1197, 731, 2337, +550, 1952, 354, 526, -54, -1081, -730, -1843, +-1191, -1781, -851, -803, 288, 788, 1503, 2437, +1805, 2540, 617, 505, -1344, -2413, -2449, -3383, +-1521, -1502, 766, 1557, 2377, 3035, 2029, 2029, +276, -176, -1483, -1739, -2166, -2035, -1516, -1264, +138, 18, 1936, 1489, 2528, 2281, 1155, 1530, +-1391, -593, -2876, -2424, -2031, -2296, 572, -356, +2513, 1605, 2211, 2016, 306, 1118, -1440, -168, +-1704, -1010, -926, -1445, 26, -1102, 617, 9, +1100, 1288, 1117, 1512, 615, 529, -589, -606, +-1493, -982, -1577, -611, -478, -249, 1040, 137, +1918, 451, 1535, 713, -16, 538, -1509, 5, +-2032, -569, -1110, -880, 359, -650, 1726, 15, +1997, 880, 1079, 1150, -793, 631, -2285, -545, +-2327, -1304, -438, -1068, 1980, 34, 2967, 1038, +1415, 1095, -1305, 257, -2773, -590, -1765, -692, +478, -145, 1914, 206, 1486, 4, 354, -254, +-802, 36, -1117, 469, -902, 509, -56, -53, +784, -438, 1017, -416, 498, -192, -306, -9, +-786, 66, -714, 385, -223, 625, 355, 482, +779, -338, 566, -1217, 36, -1140, -435, 123, +-567, 1543, -422, 1649, -109, 300, 327, -1376, +699, -1844, 578, -852, -47, 820, -700, 1795, +-891, 1281, -253, -212, 610, -1478, 1019, -1303, +542, -15, -522, 1011, -999, 862, -625, -154, +282, -565, 803, -195, 555, 474, 129, 381, +-464, -236, -601, -765, -384, -521, 261, 269, +535, 945, 389, 750, -185, -120, -360, -828, +-171, -783, 72, -71, 60, 392, 89, 439, +23, 192, 96, 111, 50, 120, -65, -108, +-238, -530, -286, -641, -9, -78, 465, 684, +537, 811, 72, 47, -574, -583, -616, -545, +-138, 119, 349, 417, 570, 109, 314, -302, +-99, -365, -473, 62, -458, 472, 77, 464, +454, 111, 259, -493, -247, -750, -394, -391, +-18, 429, 403, 980, 424, 663, 51, -190, +-343, -809, -590, -850, -489, -430, -1, 243, +721, 913, 1062, 1295, 637, 741, -445, -605, +-1530, -1866, -1504, -1887, -151, -272, 1581, 1760, +2214, 2674, 923, 1624, -1122, -690, -2299, -2712, +-1659, -2960, 168, -1023, 1725, 1943, 2127, 3656, +978, 2521, -808, -620, -2035, -3239, -1746, -3177, +-225, -825, 1342, 1830, 1937, 2821, 1141, 1801, +-415, -255, -1652, -1831, -1562, -1972, -235, -755, +1166, 769, 1378, 1382, 266, 808, -707, -159, +-750, -529, 56, -224, 544, 99, 279, -42, +-438, -394, -715, -484, -350, 13, 491, 629, +1061, 889, 892, 423, -7, -285, -1194, -915, +-1560, -1013, -832, -515, 750, 553, 1906, 1446, +1781, 1268, 160, -46, -1628, -1344, -2347, -1461, +-1271, -386, 751, 718, 2231, 965, 2094, 570, +449, 181, -1414, 19, -2290, -291, -1565, -881, +245, -1071, 1827, -322, 2013, 1020, 840, 1724, +-749, 1040, -1678, -494, -1439, -1553, -556, -1443, +656, -452, 1464, 563, 1581, 1202, 540, 1364, +-934, 795, -1875, -431, -1469, -1630, 88, -1717, +1470, -561, 1805, 850, 767, 1613, -722, 1459, +-1595, 626, -1347, -661, -94, -1804, 1228, -1921, +1581, -621, 702, 1246, -848, 2280, -1696, 1658, +-983, -75, 445, -1644, 1483, -2021, 1236, -1090, +110, 545, -929, 1639, -1466, 1521, -975, 340, +285, -760, 1471, -1055, 1667, -678, 453, -175, +-1136, 144, -1755, 447, -1037, 670, 303, 701, +1309, 219, 1222, -521, 530, -1163, -410, -1050, +-885, -83, -808, 1102, -557, 1674, -80, 977, +448, -523, 1062, -1810, 1228, -1738, 527, -350, +-851, 1358, -1841, 1987, -1658, 1219, -140, -347, +1580, -1615, 2263, -1743, 1371, -734, -439, 796, +-1946, 1712, -2108, 1404, -980, 206, 768, -1033, +1874, -1524, 1832, -1112, 674, 17, -659, 1184, +-1550, 1663, -1668, 873, -1030, -632, 261, -1659, +1778, -1303, 2389, 9, 1306, 1147, -1010, 1244, +-2748, 496, -2391, -496, -272, -974, 2010, -627, +2738, 59, 1453, 473, -749, 329, -2279, 119, +-2074, 91, -344, 66, 1334, -216, 1875, -372, +982, -249, -286, 109, -1171, 308, -1188, 196, +-495, 109, 506, -68, 1074, -150, 860, -167, +-63, -64, -895, 105, -969, 86, -269, -73, +702, -32, 1152, 167, 572, 337, -489, 44, +-1245, -500, -878, -648, 120, -55, 950, 729, +1040, 938, 467, 119, -278, -803, -832, -910, +-999, -237, -583, 561, 316, 674, 1127, 385, +1241, -15, 355, -421, -819, -573, -1445, -321, +-950, 191, 272, 539, 1172, 400, 1206, 93, +400, -163, -601, -438, -1123, -475, -893, -229, +-29, 312, 740, 692, 1000, 577, 492, 59, +-210, -572, -741, -949, -661, -563, -192, 297, +407, 1020, 514, 851, 223, -3, -192, -578, +-239, -653, -59, -456, 165, -248, 195, 203, +-60, 918, -329, 1013, -385, 64, -15, -1124, +456, -1303, 648, -157, 193, 1097, -372, 1196, +-657, 123, -457, -1010, 117, -979, 492, 51, +544, 824, 47, 640, -419, -67, -289, -311, +189, -154, 379, -185, -20, -368, -541, -257, +-451, 267, 0, 640, 408, 596, 647, 292, +460, -206, 137, -836, -488, -1099, -925, -551, +-806, 646, -153, 1382, 711, 1136, 1326, 221, +1021, -794, -38, -1307, -1267, -1230, -1682, -288, +-708, 985, 827, 1629, 1678, 1119, 1199, -142, +-220, -1212, -1180, -1309, -1159, -616, -296, 359, +503, 785, 563, 451, 405, 175, 290, 360, +218, 566, -162, -60, -667, -1243, -799, -1589, +-306, -604, 368, 836, 793, 1704, 796, 1511, +334, 549, -292, -816, -879, -1855, -869, -1761, +-298, -478, 380, 1062, 731, 1870, 672, 1468, +427, 293, 28, -947, -596, -1593, -1144, -1175, +-865, -99, 181, 821, 1237, 950, 1229, 522, +397, 107, -534, 45, -907, -102, -785, -442, +-515, -841, -32, -726, 770, 41, 1301, 942, +950, 1202, -308, 525, -1300, -526, -1294, -972, +-364, -614, 628, 112, 909, 528, 716, 333, +359, -135, -107, -402, -639, -130, -1002, 426, +-683, 558, 249, 195, 973, -354, 987, -614, +381, -485, -272, -76, -740, 462, -1034, 700, +-723, 228, 211, -382, 1210, -485, 1483, 75, +575, 470, -976, 64, -1675, -458, -1185, -432, +338, 0, 1474, 300, 1391, 198, 259, 286, +-1025, 424, -1318, 154, -592, -502, 460, -949, +1076, -642, 810, 179, 119, 795, -586, 939, +-926, 569, -819, -191, -143, -720, 749, -817, +1444, -344, 993, 76, -318, 130, -1449, 124, +-1427, 361, -386, 840, 683, 954, 1157, 196, +990, -1141, 436, -1981, -391, -1444, -952, 319, +-1126, 1901, -630, 2151, 200, 1013, 1054, -544, +1411, -1462, 848, -1482, -442, -972, -1537, -258, +-1544, 510, -297, 1298, 1078, 1632, 1447, 1090, +781, -171, -280, -1464, -878, -1894, -722, -1318, +-363, -109, 137, 1129, 407, 1885, 492, 1782, +334, 586, -91, -1189, -315, -2320, -189, -1809, +-58, -69, -27, 1538, -176, 1758, -22, 808, +323, -336, 287, -896, 90, -696, -201, -272, +-190, 151, -51, 280, -93, 110, -43, -90, +42, -90, 184, 209, 207, 404, -24, 115, +-256, -288, -139, -375, 70, -46, 310, 186, +97, 15, -235, -284, -347, -232, -86, 128, +354, 585, 355, 580, -6, 111, -321, -499, +-300, -804, 11, -473, 373, 112, 262, 578, +-59, 632, -396, 245, -311, -194, 82, -458, +401, -314, 306, 120, 2, 286, -292, 79, +-342, -309, -276, -345, 138, 89, 508, 458, +608, 422, 201, 108, -549, -270, -968, -388, +-703, -380, 213, -171, 998, 204, 1177, 425, +526, 378, -506, 59, -1240, -300, -1097, -290, +-326, -37, 603, 228, 1085, 179, 858, -263, +316, -471, -361, -232, -765, 380, -714, 780, +-500, 581, -17, -82, 399, -743, 748, -1000, +869, -558, 407, 344, -365, 1074, -997, 1074, +-1070, 183, -357, -768, 490, -1011, 991, -424, +893, 226, 189, 351, -450, 158, -741, 187, +-513, 451, -65, 435, 167, -112, 276, -782, +381, -905, 206, -353, -31, 394, -249, 805, +-270, 728, -14, 297, 91, -227, 140, -544, +124, -493, -37, -148, -236, 40, -364, -79, +-154, -205, 336, 55, 621, 698, 512, 1047, +-11, 566, -598, -496, -721, -1330, -384, -1283, +127, -489, 435, 427, 300, 1110, 276, 1338, +324, 904, 233, -97, -186, -1132, -650, -1339, +-731, -650, -383, 106, 138, 389, 666, 366, +1031, 563, 659, 855, -239, 585, -1194, -261, +-1045, -1050, 4, -1100, 931, -473, 800, 171, +-104, 451, -635, 585, -291, 715, 271, 748, +356, 249, 7, -711, -206, -1420, 28, -1176, +142, -63, -117, 1058, -445, 1285, -323, 656, +180, -171, 599, -597, 642, -431, 257, -170, +-282, -189, -803, -449, -899, -345, -339, 450, +589, 1230, 1110, 994, 822, -149, -5, -1177, +-713, -1133, -881, -299, -455, 458, 101, 762, +452, 588, 454, 134, 223, -326, -41, -514, +-65, -203, 9, 220, 21, 204, -205, -93, +-503, -336, -483, -89, 113, 327, 769, 468, +942, 277, 300, -119, -515, -516, -987, -618, +-698, -426, 3, 253, 645, 923, 766, 993, +305, 166, -293, -975, -458, -1319, -132, -407, +220, 779, 69, 1096, -327, 389, -406, -451, +51, -547, 613, -271, 698, 81, 129, 227, +-527, 239, -670, 54, -318, -265, 108, -321, +222, 42, 126, 486, 217, 416, 410, -93, +393, -585, -110, -570, -649, -135, -827, 459, +-435, 825, 209, 653, 792, -163, 862, -1010, +518, -1085, -130, -175, -738, 959, -922, 1192, +-662, 338, -130, -736, 659, -1046, 1155, -300, +1062, 671, 95, 919, -1041, 313, -1469, -640, +-718, -1009, 513, -560, 1207, 335, 816, 1050, +-76, 926, -711, 108, -608, -760, 13, -983, +464, -322, 514, 479, 60, 692, -504, 185, +-694, -523, -373, -592, 271, 16, 802, 627, +750, 627, 231, 51, -343, -334, -650, -141, +-587, 25, -350, -273, -12, -881, 340, -768, +634, 350, 605, 1495, 274, 1605, -258, 470, +-603, -957, -655, -1566, -288, -1165, 257, -152, +551, 606, 425, 725, 18, 498, -322, 365, +-306, 338, -78, 62, 172, -503, 292, -752, +220, -360, -80, 178, -357, 297, -459, -79, +-194, -249, 202, 54, 439, 525, 430, 631, +200, 256, -71, -284, -279, -554, -401, -445, +-358, -187, -98, -49, 185, -82, 414, 10, +301, 367, 40, 644, -150, 550, -149, 92, +-69, -365, -28, -533, -35, -503, 67, -424, +77, -241, -37, 86, -144, 591, -134, 879, +58, 652, 246, -5, 174, -640, 80, -753, +-60, -381, -162, -8, -212, 172, -210, 189, +-45, 137, 201, 156, 402, 162, 301, 258, +-105, 172, -467, -185, -421, -520, -17, -488, +403, -148, 369, 192, 89, 313, -73, 430, +-94, 501, -178, 166, -316, -457, -328, -895, +54, -602, 540, 172, 663, 755, 276, 748, +-373, 284, -731, -352, -579, -654, -28, -453, +521, 117, 658, 493, 345, 245, -190, -271, +-600, -456, -534, -79, -61, 498, 468, 654, +684, 184, 366, -465, -262, -765, -734, -427, +-676, 206, -107, 575, 607, 588, 818, 212, +347, -355, -377, -788, -691, -648, -327, 258, +281, 1100, 446, 915, 118, -166, -307, -1079, +-276, -937, 173, -26, 472, 637, 177, 697, +-490, 234, -770, -300, -240, -426, 636, -157, +1030, 261, 457, 257, -454, -185, -898, -319, +-566, 67, 94, 475, 492, 284, 364, -407, +26, -715, -132, -319, -97, 358, 137, 838, +164, 693, -46, 63, -327, -666, -374, -1071, +-69, -649, 342, 293, 472, 1041, 244, 1079, +-66, 248, -251, -678, -313, -1109, -334, -806, +-214, -39, 120, 695, 545, 1078, 585, 941, +170, 101, -323, -956, -455, -1391, -281, -766, +-58, 487, -102, 1122, -90, 823, 130, 36, +493, -517, 582, -582, 306, -300, -282, 122, +-670, 417, -738, 412, -330, 133, 239, -124, +631, -421, 625, -631, 256, -580, -125, 143, +-274, 1084, -315, 1382, -286, 498, -199, -881, +-17, -1575, 265, -1155, 365, 15, 183, 942, +-23, 1159, -74, 759, 10, 127, -1, -402, +-262, -780, -431, -924, -253, -526, 264, 245, +673, 849, 586, 890, 49, 315, -517, -259, +-728, -536, -374, -451, 201, -17, 579, 216, +441, 53, -61, -377, -344, -458, -177, 300, +155, 1058, 231, 954, -99, -46, -396, -1129, +-297, -1283, 80, -532, 480, 410, 519, 1063, +162, 876, -303, 205, -577, -412, -405, -617, +107, -222, 430, 187, 365, 167, -22, -174, +-345, -610, -270, -359, -31, 439, 293, 985, +437, 787, 234, -92, -157, -664, -562, -547, +-558, -282, 17, -163, 533, -160, 510, -52, +-53, 335, -529, 577, -250, 741, 353, 558, +560, -213, 122, -1089, -499, -1365, -568, -562, +-182, 699, 269, 1309, 490, 969, 376, 174, +88, -628, -321, -955, -633, -798, -366, -29, +274, 847, 646, 1019, 419, 271, -302, -781, +-573, -1118, -148, -356, 395, 773, 452, 1172, +32, 539, -410, -511, -421, -1004, -132, -665, +138, 21, 316, 516, 291, 560, 109, 241, +-164, -116, -241, -277, -56, -146, 154, 77, +189, 111, -119, 42, -379, 4, -334, -93, +29, -221, 456, -256, 706, -67, 403, 306, +-220, 346, -834, 192, -918, 29, -277, -23, +607, -50, 981, -199, 672, -336, -135, -306, +-682, -243, -619, 22, -156, 534, 303, 924, +401, 785, 145, -168, -103, -1196, -252, -1420, +-172, -644, 20, 708, 184, 1571, 263, 1222, +131, 28, -182, -1091, -323, -1163, -197, -382, +225, 353, 446, 618, 199, 456, -273, 60, +-511, -288, -334, -499, 92, -174, 364, 428, +368, 606, 285, 233, 18, -393, -194, -626, +-361, -342, -274, 89, -31, 337, 118, 290, +91, 10, 62, -33, 78, 164, 164, 230, +113, -35, -32, -470, -113, -458, -225, -72, +-251, 182, -123, 258, 154, 337, 476, 362, +375, 119, -107, -469, -495, -653, -379, -203, +52, 342, 398, 467, 201, 142, -87, -260, +-195, -288, -58, -87, 120, 309, 70, 502, +-9, 101, -33, -440, -73, -666, -60, -231, +-25, 452, 70, 650, 190, 298, 62, -274, +-148, -721, -198, -479, -97, 149, 170, 716, +291, 725, 154, 78, -84, -459, -326, -612, +-308, -412, -20, -14, 232, 274, 268, 403, +78, 287, -100, -72, 10, -199, 54, -129, +28, -20, -133, 107, -233, 63, -66, 71, +130, 7, 149, -151, 101, -179, -122, -145, +-128, -7, 45, 207, 119, 254, 100, 123, +-33, -150, -86, -227, 70, 81, 48, 298, +-160, 107, -255, -223, -133, -326, 245, -70, +363, 29, 85, -133, -228, -109, -271, 233, +43, 615, 289, 518, 181, -48, -118, -607, +-337, -751, -186, -451, 128, 152, 251, 634, +174, 686, -32, 274, -193, -298, -140, -584, +-75, -396, 93, 25, 208, 397, 135, 353, +-34, -56, -217, -394, -181, -286, 70, 246, +285, 632, 193, 328, -95, -378, -419, -760, +-331, -438, 54, 333, 425, 655, 448, 361, +94, -190, -285, -433, -391, -238, -236, 27, +74, 178, 335, 339, 358, 390, 71, 125, +-361, -455, -530, -898, -130, -518, 428, 324, +610, 915, 185, 727, -416, 24, -578, -454, +-257, -468, 203, -213, 439, 50, 350, 63, +60, -13, -224, 25, -362, 176, -128, 335, +163, 120, 274, -333, 55, -484, -290, -171, +-312, 347, -22, 424, 276, 16, 372, -259, +169, -108, -51, 242, -161, 220, -227, -261, +-143, -589, -23, -258, 84, 410, 62, 778, +-124, 343, -153, -347, 103, -635, 391, -353, +469, 122, 55, 316, -439, 249, -620, 193, +-383, 115, 156, -69, 535, -385, 455, -542, +80, -290, -354, 261, -404, 710, -76, 731, +254, 209, 395, -459, 160, -807, -242, -612, +-426, -8, -393, 451, 35, 502, 419, 259, +446, -15, 216, -130, -160, -121, -270, -90, +-119, 2, -82, -1, -99, -116, -145, -215, +-29, -111, 320, 227, 421, 392, 232, 155, +-183, -146, -595, -217, -513, 2, 1, 147, +630, 14, 831, -134, 246, -211, -618, -170, +-1003, -8, -543, 171, 429, 337, 942, 310, +653, 44, -123, -202, -752, -386, -611, -365, +20, -90, 597, 298, 633, 572, 7, 347, +-595, -231, -659, -583, -214, -484, 406, -44, +601, 349, 388, 509, 61, 483, -234, 150, +-363, -364, -377, -668, -241, -531, 131, -4, +397, 424, 369, 469, 12, 323, -326, 102, +-277, -91, 59, -312, 352, -525, 291, -446, +-39, 14, -345, 632, -377, 937, -191, 495, +92, -406, 240, -1042, 313, -888, 276, -52, +100, 705, -200, 778, -469, 273, -386, -277, +61, -343, 495, 46, 521, 305, 42, 85, +-483, -439, -630, -673, -248, -220, 345, 466, +661, 728, 490, 401, -59, -189, -544, -421, +-578, -240, -216, 54, 296, 182, 530, -15, +338, -258, -44, -179, -346, 133, -368, 428, +-149, 279, 68, -223, 260, -474, 333, -269, +198, 263, -74, 596, -399, 291, -402, -279, +-81, -661, 301, -454, 468, 225, 253, 626, +-121, 475, -372, -84, -411, -507, -142, -394, +248, 23, 472, 349, 389, 359, -95, -27, +-512, -329, -497, -270, -69, 50, 469, 328, +543, 185, 171, -79, -277, -165, -481, -163, +-279, -137, 129, -55, 376, 203, 326, 476, +-109, 278, -471, -255, -342, -510, 148, -270, +598, 141, 426, 187, -188, -38, -496, -34, +-264, 248, 164, 430, 247, 138, -148, -508, +-307, -818, 20, -353, 434, 551, 463, 1090, +-21, 631, -448, -431, -444, -1107, -186, -897, +129, 32, 355, 895, 433, 1070, 267, 471, +-221, -495, -640, -1052, -542, -690, -2, 142, +569, 704, 687, 563, 328, 48, -168, -231, +-613, -242, -739, -160, -379, -79, 339, -25, +968, 101, 859, 240, -1, 199, -825, 17, +-975, -295, -346, -414, 469, -103, 792, 324, +563, 545, -17, 311, -590, -181, -733, -503, +-383, -563, 305, -282, 837, 255, 712, 636, +100, 631, -585, 205, -837, -286, -496, -500, +88, -526, 553, -400, 653, 45, 306, 505, +-113, 744, -417, 387, -414, -238, -146, -512, +61, -435, 142, -158, 139, 89, 139, 238, +224, 390, 140, 354, -111, 17, -368, -397, +-433, -715, -156, -500, 260, 234, 457, 897, +377, 955, 6, 217, -296, -685, -311, -997, +-143, -711, 67, -46, 137, 621, 53, 925, +23, 689, 24, -80, 35, -743, 35, -713, +-28, -212, -80, 243, -86, 341, -66, 206, +-6, 124, 86, 9, 165, -107, 177, -102, +28, -92, -237, -142, -359, -153, -151, 39, +263, 410, 523, 483, 254, 59, -319, -478, +-670, -679, -362, -337, 359, 301, 800, 714, +455, 598, -324, -19, -803, -653, -477, -623, +273, -49, 611, 509, 297, 508, -237, -21, +-318, -457, 42, -413, 255, -10, 21, 449, +-348, 509, -351, 131, 110, -318, 504, -546, +460, -303, 14, 139, -482, 315, -578, 232, +-234, -3, 327, -37, 685, 142, 433, 127, +-218, -116, -669, -416, -505, -432, 154, -11, +564, 347, 368, 425, -105, 305, -373, 68, +-184, -127, 129, -396, 202, -545, 67, -192, +-120, 347, -198, 666, -103, 412, 88, -239, +288, -580, 281, -423, -55, 1, -427, 404, +-485, 373, -15, 150, 557, -61, 644, -230, +167, -218, -482, -169, -717, 13, -384, 282, +180, 242, 544, -66, 501, -351, 111, -276, +-258, 207, -359, 509, -144, 305, 160, -82, +184, -425, -73, -381, -321, -167, -205, 57, +218, 275, 506, 292, 320, 148, -175, 5, +-483, -125, -305, -143, 152, -164, 408, -169, +179, 21, -245, 208, -420, 271, -163, 162, +315, -101, 492, -265, 225, -328, -211, -241, +-456, 77, -267, 429, 97, 571, 280, 341, +230, -208, 7, -625, -160, -654, -160, -337, +-129, 198, 19, 592, 191, 733, 259, 494, +202, -119, -104, -697, -381, -858, -401, -450, +-182, 199, 231, 645, 487, 657, 443, 425, +170, -28, -272, -434, -533, -629, -426, -491, +-86, -82, 381, 279, 483, 462, 225, 521, +-112, 349, -362, -34, -271, -505, -35, -724, +86, -423, 179, 151, 114, 574, 101, 646, +151, 313, 56, -151, -132, -493, -411, -582, +-519, -299, -126, 87, 437, 383, 753, 555, +498, 435, -207, 94, -628, -393, -517, -748, +-69, -528, 353, 60, 308, 557, 78, 585, +-140, 178, -184, -139, 23, -239, 167, -233, +117, -182, -63, -71, -278, 131, -192, 314, +124, 210, 345, 26, 328, -190, -46, -385, +-407, -388, -412, -119, -113, 495, 308, 887, +427, 514, 148, -376, -142, -1005, -232, -763, +-45, 60, 149, 649, 29, 626, -222, 185, +-299, -258, -87, -345, 306, -194, 505, 82, +331, 299, -16, 292, -398, 54, -579, -399, +-399, -688, 21, -402, 503, 363, 662, 979, +286, 801, -257, -61, -589, -834, -405, -923, +114, -330, 441, 424, 341, 793, -40, 579, +-431, -80, -327, -629, 67, -627, 413, -112, +429, 453, -15, 584, -410, 226, -449, -291, +-182, -537, 268, -275, 457, 225, 310, 431, +20, 139, -286, -269, -298, -188, -133, 220, +-22, 309, 65, -127, 65, -614, 122, -446, +214, 239, 92, 770, -60, 677, -183, 47, +-201, -605, -52, -755, 5, -351, 85, 279, +190, 574, 144, 299, 22, -134, -231, -344, +-343, -154, -62, 214, 306, 427, 471, 314, +211, -190, -359, -706, -604, -702, -354, -64, +238, 705, 678, 930, 472, 398, -98, -382, +-551, -836, -521, -669, -12, 11, 357, 683, +363, 846, 114, 328, -167, -484, -194, -908, +-108, -658, -52, 41, 67, 690, 152, 865, +190, 489, 116, -149, -183, -675, -378, -744, +-279, -390, 94, 140, 517, 545, 493, 587, +3, 291, -507, -110, -613, -344, -150, -385, +431, -250, 580, -61, 275, 227, -217, 425, +-489, 293, -356, -85, -35, -386, 289, -305, +397, 56, 192, 275, -108, 220, -314, -19, +-236, -249, 58, -235, 246, -33, 180, 225, +-50, 315, -237, 95, -166, -126, 15, -178, +153, -146, 192, -127, 108, -156, -32, 14, +-147, 401, -187, 553, -49, 273, 84, -350, +84, -843, -2, -685, -28, -48, 143, 730, +279, 1059, 78, 613, -380, -278, -678, -1051, +-338, -1091, 493, -272, 1015, 716, 658, 1089, +-343, 617, -1101, -258, -847, -659, 76, -481, +827, -121, 800, 102, 177, 91, -392, 196, +-553, 332, -360, 236, -13, -64, 265, -392, +388, -401, 269, -76, -59, 223, -304, 306, +-272, 158, -55, -72, 164, -137, 170, -112, +67, -44, 13, 70, -68, 119, -121, 118, +-122, -4, -32, -186, 132, -199, 143, -90, +7, 67, -79, 199, -50, 219, 70, 194, +105, 24, -2, -241, -66, -314, -118, -133, +-154, 63, -107, 52, 4, -126, 254, -34, +418, 368, 218, 594, -163, 317, -514, -330, +-468, -816, -17, -737, 390, -237, 488, 463, +269, 939, -135, 811, -339, 133, -378, -660, +-243, -943, 66, -492, 340, 177, 462, 558, +286, 493, -131, 130, -418, -128, -431, -221, +-159, -205, 192, -70, 309, 26, 262, 128, +70, 129, -93, -48, -95, -166, -101, -103, +-119, 98, -122, 264, -112, 121, 106, -99, +318, -159, 283, -128, 35, -11, -303, 13, +-339, -7, -60, 40, 169, 30, 226, 96, +45, 177, -103, 84, -89, -127, -68, -350, +8, -288, 102, 141, 135, 411, 96, 328, +-112, -69, -278, -449, -145, -346, 89, 51, +275, 407, 212, 444, -31, 47, -169, -304, +-186, -396, -90, -290, 43, 38, 57, 329, +97, 466, 122, 306, 28, -251, -83, -630, +-173, -480, -68, 113, 197, 706, 234, 661, +-1, 24, -294, -607, -333, -799, -9, -249, +276, 479, 266, 711, 93, 348, -83, -286, +-96, -515, -113, -175, -188, 215, -80, 360, +192, 75, 337, -352, 152, -428, -328, -121, +-499, 393, -90, 658, 447, 292, 582, -297, +122, -685, -456, -558, -578, 60, -221, 610, +304, 741, 503, 327, 252, -454, -129, -870, +-371, -620, -228, 77, 104, 757, 212, 821, +89, 341, -68, -294, -143, -742, -12, -613, +76, -119, 91, 340, 68, 548, -47, 343, +-163, -7, -178, -237, -46, -346, 223, -176, +294, 61, 141, 180, -138, 256, -331, 150, +-192, -46, 75, -262, 201, -430, 145, -172, +-58, 270, -162, 491, -63, 377, 77, -33, +216, -308, 183, -323, -58, -326, -291, -153, +-350, 113, -66, 373, 336, 533, 429, 289, +163, -145, -248, -495, -467, -630, -245, -263, +137, 266, 392, 574, 349, 522, 11, 45, +-268, -354, -302, -417, -143, -269, 68, 98, +129, 304, 128, 255, 139, 94, 85, -160, +-38, -250, -222, -182, -308, -92, -63, 177, +268, 372, 401, 301, 193, 19, -264, -390, +-470, -439, -215, -142, 162, 114, 403, 258, +260, 188, -44, 117, -214, 155, -234, 5, +-91, -233, 71, -393, 146, -310, 129, 148, +-14, 458, -96, 347, -32, 21, 10, -313, +51, -304, 18, -108, -19, 31, 34, 264, +21, 355, -109, 177, -184, -216, -124, -620, +179, -470, 444, 155, 328, 658, -130, 714, +-586, 146, -566, -543, -39, -756, 492, -469, +628, 191, 276, 654, -232, 538, -406, 125, +-273, -318, -19, -439, 92, -201, 6, -9, +-25, 120, 88, 152, 207, 101, 210, 172, +30, 119, -169, -64, -217, -232, -187, -356, +-69, -189, 65, 128, 116, 347, 145, 465, +129, 248, 75, -167, 24, -508, -149, -621, +-280, -266, -193, 304, 24, 652, 268, 692, +248, 257, 74, -354, -74, -732, -147, -725, +-163, -192, -121, 425, -14, 643, 268, 497, +361, 89, 93, -239, -354, -330, -612, -344, +-265, -168, 453, 72, 777, 206, 456, 236, +-309, 48, -804, -140, -546, -94, 98, 57, +597, 236, 510, 150, -11, -222, -367, -407, +-287, -267, 61, 157, 265, 460, 26, 278, +-260, -65, -228, -254, 91, -186, 413, 71, +320, 119, -80, -25, -362, -144, -375, -159, +-98, 45, 229, 214, 339, 176, 260, 117, +9, -3, -267, -108, -330, -227, -215, -342, +68, -168, 315, 191, 283, 438, 105, 438, +-70, 72, -133, -321, -100, -442, -186, -289, +-246, 108, -88, 355, 237, 259, 512, 43, +345, -178, -172, -233, -542, -161, -454, -41, +63, 240, 545, 420, 456, 223, 4, -186, +-453, -527, -545, -401, -145, 43, 290, 338, +518, 385, 428, 204, 15, -43, -386, -171, +-587, -275, -451, -259, 56, -93, 525, 144, +745, 422, 449, 403, -200, 7, -700, -405, +-731, -555, -291, -259, 342, 187, 596, 414, +485, 447, 177, 255, -168, -100, -316, -402, +-381, -514, -314, -281, -33, 136, 284, 399, +485, 443, 367, 187, -31, -189, -344, -341, +-445, -252, -257, 5, 74, 151, 295, 118, +389, 133, 243, 119, -97, -71, -348, -291, +-374, -337, -128, -25, 180, 368, 288, 430, +267, 214, 162, -141, -18, -422, -262, -397, +-477, -126, -387, 268, 123, 411, 598, 178, +627, -95, 124, -184, -523, -94, -667, 42, +-288, 20, 258, -30, 538, -52, 390, -25, +9, 93, -278, 119, -352, -13, -179, -111, +5, -69, 130, 124, 145, 163, 137, -82, +139, -268, 55, -184, -178, 117, -293, 353, +-175, 238, 123, -88, 354, -349, 223, -294, +-102, 111, -272, 388, -176, 230, 23, -188, +98, -459, -12, -262, -49, 179, 118, 480, +334, 489, 257, 109, -159, -440, -589, -681, +-580, -394, -40, 264, 577, 633, 702, 382, +270, -92, -281, -343, -488, -227, -306, 41, +7, 152, 112, 121, 85, 0, 87, -141, +119, -154, 124, -80, 18, 56, -129, 202, +-176, 225, -150, 86, -14, -175, 163, -302, +253, -85, 160, 214, -164, 230, -411, -46, +-268, -299, 133, -181, 452, 137, 396, 301, +-35, 226, -363, -16, -404, -230, -173, -244, +172, -83, 340, 142, 303, 199, 62, 17, +-254, -159, -341, -144, -201, 58, 82, 264, +285, 230, 168, -37, 24, -326, -28, -354, +-35, -24, -63, 316, -218, 318, -248, 33, +67, -223, 376, -188, 421, 3, 64, 129, +-399, 145, -487, 47, -203, -127, 235, -227, +459, -137, 261, 96, -59, 243, -270, 176, +-262, 54, 4, -13, 142, -84, 111, -200, +31, -300, -94, -194, -69, 132, 12, 456, +22, 530, 76, 205, 49, -349, -14, -685, +-58, -497, -96, 75, 27, 537, 154, 497, +81, 129, -117, -200, -282, -288, -109, -174, +317, -18, 401, 101, 103, 130, -342, 42, +-495, -63, -90, -81, 330, -18, 404, 81, +136, 79, -285, -6, -364, -50, -93, 1, +213, 92, 396, 26, 173, -222, -179, -309, +-345, -26, -274, 410, 37, 512, 273, 83, +222, -451, 92, -545, -85, -178, -125, 303, +-35, 491, -39, 300, -8, -71, 20, -399, +-12, -446, 28, -179, -2, 199, 15, 467, +97, 432, 16, 109, -42, -273, -94, -484, +-88, -363, 66, -4, 82, 257, -9, 270, +-48, 118, -83, 1, 57, 60, 142, 124, +44, 22, -65, -239, -164, -481, -103, -358, +93, 119, 122, 564, 53, 596, -101, 135, +-204, -360, -29, -454, 151, -224, 245, 55, +192, 170, -110, 145, -281, 103, -281, -38, +-169, -189, 96, -140, 218, 98, 258, 330, +235, 236, 17, -158, -182, -390, -313, -268, +-321, 70, -78, 257, 123, 97, 297, -71, +361, 16, 142, 230, -146, 246, -403, -138, +-426, -531, -27, -470, 371, -4, 514, 521, +257, 645, -342, 269, -637, -277, -443, -650, +118, -532, 709, 15, 712, 506, 178, 595, +-494, 208, -882, -291, -552, -452, 164, -270, +706, 33, 758, 187, 217, 92, -379, 33, +-587, 131, -411, 254, 57, 161, 356, -224, +318, -540, 125, -438, -138, -42, -192, 389, +-37, 587, 64, 486, 127, 138, 51, -425, +-99, -812, -97, -613, -64, 88, 44, 770, +157, 801, 105, 177, 52, -493, 1, -698, +-65, -339, -73, 194, -123, 418, -68, 337, +125, 137, 234, -53, 221, -206, -5, -369, +-268, -340, -263, -10, -87, 348, 170, 452, +355, 222, 235, -76, 5, -182, -263, -194, +-398, -218, -178, -215, 170, -116, 452, 190, +426, 481, 9, 462, -392, 99, -489, -429, +-231, -633, 245, -288, 449, 242, 309, 518, +-27, 297, -315, -170, -268, -374, -4, -201, +175, 192, 178, 404, -24, 162, -138, -233, +-48, -399, 9, -210, 12, 108, -66, 221, +-60, 222, 128, 244, 204, 102, 67, -225, +-157, -520, -323, -379, -184, 188, 69, 573, +195, 441, 194, -14, 47, -392, -68, -399, +-108, -172, -152, 90, -111, 293, -28, 289, +57, 156, 111, -12, 30, -207, -69, -322, +-50, -323, 5, -112, 81, 283, 11, 531, +-164, 434, -173, 22, -35, -445, 168, -574, +192, -341, -63, 65, -268, 398, -175, 441, +119, 291, 327, 15, 136, -315, -215, -438, +-329, -255, -143, 115, 154, 339, 193, 177, +-7, -96, -114, -144, -39, 32, 125, 218, +154, 163, -78, -80, -265, -305, -238, -368, +-13, -111, 248, 307, 270, 490, 116, 280, +-49, -153, -144, -381, -124, -237, -115, 1, +-140, 134, -46, 111, 151, 2, 349, -23, +342, 22, 26, 87, -310, 77, -410, -110, +-190, -230, 156, -97, 320, 158, 265, 302, +91, 128, -95, -183, -180, -310, -164, -194, +-38, 96, 164, 309, 243, 233, 145, 2, +-57, -208, -199, -215, -106, -43, 92, 69, +185, 105, 114, 74, -46, -22, -73, -66, +39, -58, 100, 25, 11, 108, -148, 43, +-139, -36, 122, -76, 370, -87, 312, -38, +-52, 41, -419, 142, -405, 151, -82, -56, +292, -238, 454, -162, 329, 112, 45, 343, +-268, 199, -432, -185, -316, -407, 41, -295, +378, 127, 452, 435, 188, 335, -141, 9, +-322, -258, -289, -253, -130, -105, 49, -37, +229, 48, 304, 175, 181, 188, -83, 44, +-286, -145, -279, -106, -86, 97, 71, 87, +145, -117, 175, -263, 152, -121, 5, 201, +-251, 310, -377, 175, -167, -26, 228, -185, +407, -214, 171, -180, -266, -63, -427, 154, +-196, 277, 162, 216, 295, 3, 115, -212, +-117, -202, -205, -52, -132, 41, -25, 55, +14, 17, -4, 46, -27, 74, -33, -3, +10, -49, 81, 0, 95, 70, 22, 53, +-174, -98, -313, -210, -232, -166, 15, -21, +269, 204, 304, 366, 108, 317, -96, 36, +-211, -347, -236, -524, -211, -367, -145, -12, +82, 387, 363, 591, 428, 443, 147, -11, +-322, -525, -532, -651, -309, -268, 64, 253, +281, 499, 239, 324, 124, -6, 128, -173, +66, -178, -146, -137, -375, -105, -360, -47, +19, 144, 432, 294, 487, 196, 157, -65, +-297, -289, -446, -244, -177, -41, 214, 107, +416, 184, 229, 186, -167, 81, -332, -134, +-131, -300, 257, -156, 423, 194, 108, 322, +-311, 85, -399, -262, -41, -304, 433, 0, +485, 248, 83, 232, -346, 22, -432, -145, +-99, -123, 314, -38, 424, 16, 266, 25, +-55, -6, -267, -4, -258, 16, -144, 35, +81, 82, 279, 59, 352, -46, 267, -130, +-46, -79, -380, 84, -415, 108, -162, -91, +271, -234, 512, -76, 363, 297, 39, 455, +-285, 158, -374, -290, -234, -507, -39, -358, +187, 3, 337, 318, 272, 464, 109, 346, +-168, -11, -313, -357, -210, -443, -59, -208, +118, 134, 168, 286, 112, 185, 83, 13, +-11, -43, -114, 32, -161, 25, -190, -142, +-44, -275, 147, -151, 209, 190, 149, 388, +-117, 229, -287, -111, -176, -331, 27, -266, +186, -18, 111, 204, -127, 287, -184, 149, +-108, -135, 46, -321, 146, -232, 47, 84, +-45, 351, -103, 303, -147, 11, -87, -295, +-66, -370, 4, -162, 127, 133, 119, 325, +48, 300, -101, 65, -254, -192, -194, -313, +-53, -191, 109, 80, 221, 207, 121, 108, +-22, -45, -153, -42, -250, 87, -149, 72, +-21, -109, 118, -203, 220, -87, 97, 122, +-63, 200, -180, 124, -187, 41, 15, -70, +118, -217, 69, -288, -14, -136, -132, 247, +-42, 515, 127, 355, 165, -142, 96, -596, +-141, -551, -279, 1, -135, 549, 78, 609, +272, 111, 249, -452, 10, -541, -106, -185, +-151, 256, -82, 438, 59, 279, 65, -2, +81, -250, 59, -348, -22, -225, -6, 8, +16, 233, 54, 317, 123, 189, 16, -7, +-62, -173, -72, -229, -18, -151, 140, -28, +127, 99, 20, 152, -22, 75, -42, -13, +60, -40, 136, 4, 32, 47, -64, -9, +-169, -55, -100, -39, 200, -51, 367, -93, +310, -66, -44, 113, -448, 303, -457, 205, +-122, -133, 345, -339, 623, -224, 389, 59, +-54, 181, -420, 123, -501, 77, -156, 40, +193, -52, 339, -177, 270, -208, 28, -18, +-71, 225, -50, 296, -87, 153, -126, -137, +-192, -358, -82, -330, 206, -69, 319, 292, +229, 445, -41, 251, -303, -109, -301, -371, +-175, -328, 26, -59, 259, 161, 276, 232, +130, 144, -142, 12, -349, -78, -224, -150, +27, -134, 211, -2, 204, 151, -24, 223, +-196, 103, -232, -154, -135, -331, 91, -283, +220, 30, 186, 401, 14, 468, -223, 162, +-299, -281, -184, -474, -35, -270, 106, 42, +150, 199, 165, 172, 161, 103, 4, 124, +-238, 129, -406, -9, -347, -232, -27, -386, +291, -249, 387, 121, 264, 406, -33, 404, +-287, 110, -354, -203, -258, -314, -26, -252, +163, -84, 220, 105, 225, 222, 113, 233, +-78, 83, -264, -112, -343, -180, -149, -127, +177, 1, 324, 83, 226, 65, -59, 13, +-209, -30, -117, -12, 7, 30, 59, 5, +20, -37, -4, -9, 67, 100, 58, 149, +-52, -28, -102, -297, -25, -345, 171, -35, +205, 420, 7, 555, -180, 196, -180, -346, +22, -592, 217, -344, 189, 156, 19, 449, +-103, 334, -97, -32, 48, -284, 115, -204, +35, 67, -62, 220, -77, 85, 80, -165, +254, -222, 207, -17, -6, 188, -255, 177, +-307, -2, -66, -124, 224, -83, 357, 2, +259, 33, 17, 27, -128, 31, -168, 19, +-161, -38, -74, -86, 38, -37, 165, 57, +233, 85, 143, 17, 44, -42, -42, 19, +-130, 87, -162, 26, -159, -152, -18, -246, +205, -91, 273, 180, 168, 312, -60, 181, +-215, -68, -143, -212, -11, -163, 48, -30, +31, 52, -17, 34, 42, -30, 119, -27, +56, 60, -75, 182, -187, 177, -155, -18, +30, -261, 158, -326, 168, -105, 44, 214, +-165, 312, -213, 116, -118, -147, 40, -207, +165, -15, 71, 173, -42, 160, -104, -21, +-134, -217, -62, -237, -7, -79, 81, 152, +145, 307, 16, 237, -197, -15, -294, -231, +-165, -256, 175, -95, 347, 60, 154, 94, +-178, 95, -399, 91, -244, 76, 109, 4, +232, -102, 133, -130, -110, -88, -252, -32, +-79, 45, 108, 150, 217, 219, 122, 106, +-222, -197, -384, -379, -299, -201, 47, 207, +452, 451, 439, 248, 122, -163, -297, -381, +-550, -261, -345, 56, 51, 253, 373, 211, +427, 33, 91, -150, -224, -147, -283, 33, +-121, 172, 138, 111, 148, -166, -33, -337, +-124, -157, -62, 219, 161, 439, 288, 288, +66, -102, -196, -364, -324, -348, -152, -126, +234, 141, 376, 268, 225, 257, -88, 87, +-342, -140, -215, -233, 101, -135, 328, 54, +293, 132, -38, 11, -277, -107, -213, -28, +32, 140, 286, 182, 297, -25, 91, -230, +-97, -159, -222, 99, -173, 228, 6, 57, +118, -209, 203, -251, 210, -18, 136, 250, +77, 347, -83, 200, -244, -101, -265, -404, +-146, -531, 151, -264, 430, 297, 443, 737, +210, 641, -219, 17, -518, -644, -409, -782, +-26, -354, 430, 286, 577, 670, 246, 550, +-223, 87, -519, -413, -359, -593, 119, -316, +418, 174, 369, 494, 79, 433, -215, 66, +-282, -288, -223, -438, -116, -349, 116, -32, +293, 325, 354, 523, 198, 361, -194, -96, +-425, -453, -429, -459, -150, -185, 262, 134, +414, 277, 334, 294, 30, 250, -321, 46, +-415, -242, -272, -437, 79, -292, 362, 159, +297, 455, -28, 339, -349, -85, -396, -421, +-89, -354, 230, 13, 316, 356, 167, 452, +-134, 197, -308, -218, -262, -506, -138, -480, +68, -87, 175, 374, 192, 599, 131, 433, +-87, -40, -299, -459, -342, -546, -153, -280, +194, 136, 340, 394, 207, 349, -56, 144, +-304, -97, -318, -248, -179, -264, -5, -153, +233, 65, 343, 249, 297, 289, 4, 144, +-445, -116, -661, -345, -421, -359, 219, -112, +757, 268, 714, 484, 106, 343, -584, -30, +-795, -358, -411, -429, 234, -261, 623, 35, +500, 324, 46, 455, -379, 258, -433, -184, +-181, -502, 152, -368, 330, 154, 259, 519, +72, 363, -128, -154, -208, -529, -180, -426, +-87, 8, 40, 397, 175, 529, 313, 352, +343, -40, 142, -429, -248, -645, -562, -462, +-520, 67, -43, 607, 590, 812, 880, 446, +562, -272, -206, -823, -838, -801, -824, -166, +-174, 614, 592, 891, 901, 486, 571, -303, +-115, -823, -634, -657, -673, -26, -197, 604, +394, 755, 693, 369, 517, -233, -40, -691, +-490, -717, -564, -234, -217, 442, 337, 863, +603, 647, 448, -112, -41, -746, -459, -784, +-462, -201, -115, 465, 299, 649, 458, 348, +258, -122, -89, -420, -294, -396, -263, -140, +-46, 200, 156, 442, 186, 333, 161, -58, +10, -451, -107, -480, -133, -49, -109, 424, +19, 543, 51, 174, 49, -335, 84, -528, +83, -268, 43, 160, -140, 421, -299, 344, +-209, 52, 86, -201, 358, -327, 333, -268, +-11, -96, -377, 156, -438, 396, -180, 457, +206, 181, 382, -329, 213, -735, -92, -635, +-314, 29, -259, 782, -13, 1037, 153, 489, +111, -510, -104, -1228, -215, -1085, -38, -78, +216, 1117, 268, 1550, -19, 778, -400, -676, +-470, -1679, -137, -1347, 312, 49, 528, 1362, +283, 1581, -231, 595, -606, -733, -534, -1427, +-16, -1073, 520, 4, 650, 1028, 248, 1288, +-366, 645, -738, -495, -592, -1288, -55, -1133, +531, -150, 797, 1010, 519, 1454, -121, 848, +-767, -399, -967, -1446, -459, -1504, 390, -449, +1016, 995, 916, 1835, 133, 1354, -702, -186, +-1027, -1637, -676, -1954, 125, -810, 809, 965, +988, 2050, 526, 1656, -358, 11, -1012, -1676, +-958, -2114, -216, -957, 773, 921, 1177, 2082, +765, 1622, -186, 3, -1021, -1533, -1088, -1863, +-417, -870, 551, 606, 1164, 1601, 968, 1496, +148, 429, -785, -924, -1169, -1707, -700, -1342, +289, 35, 1082, 1474, 1121, 1889, 349, 874, +-661, -873, -1153, -1980, -823, -1606, 172, 2, +1058, 1616, 1167, 2018, 448, 924, -641, -858, +-1190, -2001, -847, -1675, 115, -130, 1022, 1489, +1156, 2035, 494, 1105, -494, -624, -1116, -1910, +-892, -1782, -67, -307, 804, 1381, 1105, 1993, +626, 1054, -246, -635, -899, -1778, -908, -1507, +-278, -138, 489, 1255, 906, 1672, 726, 844, +71, -575, -600, -1571, -873, -1396, -550, -137, +176, 1284, 735, 1693, 766, 748, 257, -830, +-402, -1706, -684, -1161, -486, 290, 26, 1480, +457, 1440, 478, 268, 146, -1112, -236, -1622, +-390, -818, -201, 701, 61, 1670, 205, 1275, +172, -185, 27, -1486, -46, -1520, -91, -373, +-172, 1001, -221, 1482, -155, 816, 122, -347, +443, -1154, 441, -1042, 38, -189, -517, 742, +-779, 1037, -452, 483, 215, -471, 783, -947, +836, -561, 265, 327, -530, 909, -1012, 638, +-837, -206, -63, -914, 727, -861, 1044, -53, +673, 877, -196, 1157, -953, 484, -1106, -697, +-515, -1393, 477, -981, 1135, 290, 1001, 1446, +116, 1473, -923, 283, -1290, -1239, -685, -1837, +450, -948, 1260, 764, 1049, 1941, 14, 1592, +-1027, -49, -1279, -1709, -530, -2034, 618, -782, +1278, 1119, 978, 2152, -84, 1542, -1087, -246, +-1266, -1879, -536, -2110, 613, -737, 1326, 1277, +1057, 2371, 0, 1648, -1115, -437, -1396, -2238, +-550, -2289, 733, -501, 1488, 1708, 1022, 2545, +-300, 1367, -1364, -881, -1315, -2402, -121, -2027, +1222, -57, 1505, 1945, 539, 2391, -896, 928, +-1602, -1280, -935, -2428, 500, -1612, 1593, 495, +1419, 2139, 70, 2024, -1337, 329, -1683, -1532, +-688, -2108, 849, -1059, 1695, 716, 1274, 1852, +-24, 1560, -1271, 109, -1575, -1335, -767, -1724, +574, -770, 1519, 730, 1365, 1583, 270, 1141, +-943, -165, -1466, -1236, -890, -1241, 250, -265, +1100, 807, 1123, 1167, 367, 561, -454, -399, +-794, -969, -619, -729, -136, 71, 271, 719, +539, 745, 548, 160, 278, -483, -142, -680, +-559, -289, -689, 267, -327, 548, 306, 349, +835, -92, 804, -363, 133, -308, -666, 1, +-1034, 163, -672, 102, 177, -48, 976, -11, +1176, 224, 552, 304, -628, -16, -1496, -548, +-1319, -712, -40, -202, 1502, 715, 1942, 1188, +814, 687, -1110, -587, -2290, -1595, -1646, -1366, +348, 94, 2116, 1715, 2301, 2110, 654, 788, +-1478, -1371, -2598, -2653, -1790, -1920, 458, 515, +2386, 2764, 2508, 2958, 661, 663, -1739, -2352, +-2778, -3564, -1610, -1846, 799, 1479, 2537, 3646, +2232, 2805, 88, -376, -2121, -3268, -2604, -3507, +-913, -849, 1561, 2543, 2694, 3955, 1576, 2161, +-905, -1494, -2658, -4092, -2115, -3418, 151, 137, +2312, 3770, 2455, 4377, 479, 1358, -1853, -2904, +-2588, -4842, -1070, -2779, 1355, 1628, 2599, 4771, +1569, 3967, -871, -123, -2655, -4236, -2152, -4827, +261, -1443, 2551, 3257, 2748, 5231, 595, 2902, +-2188, -1831, -3229, -5009, -1597, -4034, 1474, 139, +3426, 4101, 2525, 4591, -520, 1458, -3266, -2776, +-3273, -4529, -511, -2575, 2704, 1426, 3768, 4015, +1692, 3130, -1846, -323, -3868, -3311, -2736, -3308, +669, -548, 3514, 2557, 3488, 3316, 648, 1305, +-2653, -1787, -3731, -3200, -1819, -1891, 1503, 1040, +3569, 2939, 2693, 2214, -347, -495, -2979, -2624, +-3051, -2251, -646, 199, 2209, 2374, 3110, 2196, +1416, -11, -1273, -2189, -2839, -2272, -1983, -321, +423, 1925, 2392, 2451, 2341, 891, 361, -1467, +-1744, -2546, -2289, -1481, -944, 848, 1104, 2413, +2054, 1878, 1228, -258, -532, -2100, -1673, -2029, +-1274, -203, 196, 1743, 1358, 2044, 1246, 618, +57, -1347, -1087, -2032, -1199, -1031, -260, 879, +892, 2019, 1261, 1420, 445, -453, -745, -1927, +-1313, -1615, -698, 130, 600, 1724, 1420, 1591, +1011, 92, -280, -1410, -1375, -1444, -1366, -222, +-262, 1053, 1058, 1235, 1545, 300, 817, -806, +-432, -1035, -1318, -243, -1198, 728, -265, 935, +756, 115, 1121, -875, 748, -1022, -65, -68, +-734, 1102, -931, 1316, -526, 250, 207, -1177, +801, -1691, 842, -700, 230, 1000, -558, 1960, +-907, 1264, -565, -628, 124, -2075, 753, -1688, +862, 252, 327, 1998, -579, 1879, -1157, 25, +-813, -1802, 320, -1912, 1318, -261, 1214, 1595, +-39, 1946, -1316, 492, -1540, -1426, -473, -2091, +1059, -738, 1769, 1339, 975, 2266, -648, 1022, +-1800, -1239, -1528, -2426, 10, -1339, 1554, 1010, +1912, 2489, 693, 1744, -1084, -577, -2068, -2444, +-1380, -2264, 448, -66, 1929, 2307, 1760, 2772, +222, 811, -1499, -2016, -1996, -3148, -818, -1484, +1020, 1553, 1988, 3203, 1216, 2000, -595, -962, +-1866, -2954, -1379, -2278, 239, 394, 1606, 2589, +1425, 2377, 68, 50, -1289, -2276, -1514, -2482, +-375, -397, 1061, 2108, 1561, 2662, 712, 795, +-752, -1949, -1507, -2943, -911, -1265, 449, 1668, +1329, 3138, 955, 1739, -270, -1281, -1104, -3155, +-806, -2121, 314, 870, 1093, 3067, 722, 2411, +-386, -453, -1142, -2927, -888, -2728, 254, 12, +1324, 2741, 1322, 3004, 161, 547, -1341, -2428, +-1753, -3172, -648, -1109, 1135, 1985, 2035, 3172, +1173, 1567, -687, -1492, -1940, -3048, -1580, -1903, +150, 1025, 1747, 2909, 1830, 2144, 407, -533, +-1344, -2712, -1942, -2395, -920, -20, 911, 2339, +2012, 2555, 1420, 669, -420, -1758, -1902, -2543, +-1770, -1243, -49, 1087, 1679, 2377, 1918, 1617, +460, -507, -1284, -2134, -1943, -1831, -837, 100, +971, 1860, 1905, 1904, 1134, 286, -635, -1484, +-1741, -1901, -1322, -705, 256, 935, 1465, 1758, +1376, 1102, 88, -313, -1164, -1415, -1441, -1340, +-334, -247, 1017, 912, 1471, 1304, 507, 693, +-843, -316, -1494, -1062, -819, -959, 478, -271, +1341, 624, 1126, 1051, 19, 764, -1071, -79, +-1319, -951, -450, -1105, 667, -406, 1198, 720, +673, 1280, -286, 757, -1033, -490, -820, -1356, +-54, -997, 776, 288, 866, 1468, 286, 1270, +-525, -109, -823, -1594, -512, -1639, 109, -129, +573, 1671, 590, 1999, 306, 412, -216, -1631, +-530, -2222, -637, -659, -254, 1516, 240, 2319, +681, 809, 612, -1472, 101, -2397, -537, -947, +-704, 1473, -358, 2567, 168, 1134, 505, -1479, +436, -2774, 190, -1367, -141, 1441, -427, 2921, +-537, 1522, -277, -1432, 291, -3025, 756, -1572, +711, 1507, 26, 3177, -849, 1669, -1138, -1593, +-440, -3414, 674, -1922, 1341, 1501, 921, 3599, +-306, 2323, -1265, -1191, -1223, -3629, -222, -2672, +991, 771, 1459, 3453, 807, 2837, -567, -356, +-1530, -3138, -1354, -2851, -11, 2, 1427, 2742, +1854, 2809, 649, 334, -1050, -2339, -2016, -2738, +-1210, -566, 636, 1959, 1969, 2554, 1580, 653, +-177, -1641, -1750, -2277, -1817, -651, -194, 1364, +1613, 1932, 2101, 659, 628, -1002, -1466, -1533, +-2389, -723, -1111, 500, 1313, 997, 2735, 735, +1679, 123, -966, -331, -2953, -616, -2261, -691, +646, -402, 3084, 367, 2757, 1166, -280, 1092, +-3156, -165, -3048, -1621, 74, -1630, 3224, 160, +3311, 2103, 123, 1993, -3234, -339, -3503, -2523, +-304, -2145, 3193, 531, 3608, 2734, 505, 2133, +-3004, -670, -3532, -2739, -613, -1902, 2704, 891, +3231, 2572, 738, 1394, -2264, -1225, -2882, -2267, +-819, -647, 1733, 1609, 2411, 1778, 902, -176, +-1257, -1804, -1965, -1132, -921, 817, 829, 1643, +1592, 466, 959, -1028, -464, -1044, -1510, 30, +-1236, 588, 272, 109, 1707, -117, 1641, 432, +-250, 847, -2210, -279, -2081, -1694, 399, -1419, +2692, 1007, 2394, 2674, -472, 1416, -3078, -1705, +-2648, -3026, 382, -1028, 3108, 2010, 2849, 2750, +-73, 641, -2909, -1763, -3103, -2184, -570, -573, +2467, 1207, 3364, 1735, 1425, 747, -2000, -731, +-3827, -1555, -2255, -920, 1564, 551, 4077, 1531, +2712, 959, -1349, -563, -4014, -1497, -2694, -924, +1082, 549, 3402, 1417, 2305, 894, -737, -460, +-2488, -1270, -1715, -910, 362, 317, 1467, 1174, +960, 974, -172, -252, -630, -1253, -196, -1027, +286, 409, 56, 1453, -370, 935, -380, -717, +164, -1542, 616, -608, 372, 903, -197, 1304, +-422, 278, -274, -779, -68, -947, -37, -282, +270, 368, 743, 865, 639, 831, -524, 40, +-1693, -1397, -1191, -1788, 919, 1, 2490, 2454, +1498, 2460, -1129, -639, -2849, -3291, -1775, -2242, +1047, 1347, 2980, 3101, 2159, 1501, -844, -1238, +-3238, -2204, -2454, -1358, 1063, 403, 3656, 1944, +2430, 2131, -1550, -91, -3793, -2865, -1990, -2730, +1916, 983, 3628, 3927, 1687, 2243, -1728, -2173, +-3214, -4008, -1602, -1344, 1359, 2502, 2989, 3522, +1699, 1105, -1114, -2161, -2893, -3414, -1801, -1482, +1093, 1939, 2972, 3694, 1864, 1838, -1156, -1862, +-3099, -3836, -1891, -2118, 1304, 1597, 3136, 3873, +1695, 2526, -1496, -1355, -3027, -3987, -1453, -2671, +1536, 1315, 2862, 3793, 1388, 2433, -1439, -1046, +-2798, -3181, -1440, -2402, 1422, 370, 2884, 2862, +1474, 2813, -1522, -39, -2870, -3118, -1337, -2857, +1533, 501, 2843, 3080, 1399, 1940, -1376, -1003, +-2756, -2210, -1511, -784, 1199, 965, 2690, 1228, +1460, 170, -1189, -827, -2511, -837, -1181, 136, +1265, 981, 2210, 684, 673, -501, -1544, -993, +-1958, -265, -62, 658, 1807, 578, 1391, -153, +-719, -523, -1846, -141, -600, 391, 1190, 416, +1233, -102, -274, -662, -1100, -382, -331, 451, +728, 911, 611, 163, -459, -857, -954, -916, +-152, 32, 1061, 886, 1368, 966, -53, 329, +-1750, -754, -1814, -1447, 301, -908, 2360, 888, +2007, 1957, -573, 995, -2493, -1040, -1717, -1801, +721, -774, 2100, 692, 1224, 1215, -693, 883, +-1628, 2, -879, -979, 598, -1254, 1177, -362, +532, 995, -543, 1293, -832, 308, -272, -680, +347, -816, 341, -317, -36, 62, -191, 266, +42, 377, 234, 361, 79, 95, -230, -124, +-376, -356, 28, -457, 318, -318, 224, 262, +-169, 749, -177, 494, 245, -286, 523, -621, +19, -197, -705, 268, -733, 48, 124, -355, +1037, -52, 939, 690, -115, 793, -1061, -233, +-887, -1250, 198, -905, 940, 484, 520, 1342, +-375, 666, -558, -549, 22, -953, 326, -332, +-62, 276, -384, 495, -11, 341, 390, 115, +247, -480, -302, -805, -301, -230, 4, 998, +199, 1301, -57, 22, 5, -1547, 84, -1480, +106, 205, -123, 1708, -86, 1458, 109, -234, +204, -1583, -25, -1437, -192, 122, -93, 1455, +191, 1450, 350, 29, 174, -1379, -266, -1511, +-652, -215, -237, 1276, 769, 1650, 1066, 486, +63, -1179, -1302, -1784, -1245, -766, 242, 1020, +1572, 1850, 1199, 1012, -408, -761, -1644, -1827, +-1245, -1294, 335, 446, 1576, 1739, 1175, 1534, +-551, -129, -1466, -1630, -742, -1620, 634, -113, +972, 1485, 99, 1668, -549, 198, -313, -1469, +174, -1715, 230, -106, -47, 1663, -118, 1676, +103, -125, 200, -1753, 26, -1487, -303, 175, +-282, 1441, 275, 1266, 778, 269, 255, -877, +-838, -1346, -1117, -930, 171, 499, 1528, 1665, +1084, 1315, -749, -489, -1772, -1824, -797, -1362, +1018, 472, 1649, 1791, 536, 1395, -1080, -287, +-1610, -1801, -666, -1594, 996, 243, 1606, 1897, +717, 1627, -902, -328, -1664, -1860, -948, -1416, +587, 303, 1613, 1578, 1216, 1286, -371, -155, +-1578, -1288, -1276, -1205, 263, 40, 1451, 1085, +1038, 938, -170, -55, -977, -706, -721, -566, +71, 51, 751, 302, 698, 286, -25, 53, +-817, -129, -606, -238, 328, -99, 898, 121, +465, 346, -455, 143, -713, -210, -237, -420, +79, -281, 304, 235, 327, 441, 248, 416, +-58, 4, -475, -393, -462, -659, -91, -396, +174, 378, 396, 1003, 318, 590, 38, -504, +-257, -1019, -553, -420, -248, 520, 145, 572, +453, 99, 426, -242, 226, -112, -406, 64, +-623, 135, -377, 81, 552, -222, 887, -532, +267, -265, -621, 573, -649, 988, -39, 309, +496, -778, 414, -1040, 134, -359, -92, 476, +-279, 985, -424, 721, -192, -155, 300, -1298, +537, -1065, 425, 476, -139, 1655, -646, 684, +-745, -1116, -177, -1362, 797, 326, 981, 1282, +-19, 274, -983, -1106, -924, -738, 292, 882, +918, 1263, 423, -149, -279, -1480, -465, -923, +-246, 911, -156, 1560, -41, 195, 494, -1308, +787, -1054, 302, 612, -668, 1148, -1258, -23, +-342, -1020, 994, -269, 1540, 1025, 472, 752, +-1339, -805, -1872, -1399, -143, -138, 1817, 1346, +1976, 1343, -263, -262, -2171, -1549, -1560, -1261, +552, 522, 1883, 1826, 969, 1127, -746, -1032, +-1241, -1977, -426, -541, 501, 1512, 511, 1485, +50, -380, -99, -1377, 46, -353, -186, 1042, +-659, 619, -415, -860, 767, -1119, 1349, 360, +303, 1557, -1356, 573, -1521, -1192, 62, -1396, +1478, 425, 1179, 1569, -207, 463, -1013, -1399, +-694, -1263, -41, 573, 496, 1705, 740, 704, +505, -923, -236, -1396, -1039, -664, -816, 526, +446, 1301, 1375, 1161, 783, -137, -904, -1640, +-1574, -1506, -336, 227, 1229, 1651, 1383, 1251, +-94, -148, -1368, -968, -980, -898, 115, -542, +830, 181, 792, 1065, 267, 1187, -306, 71, +-898, -1361, -893, -1274, 125, 33, 1048, 1193, +1030, 1099, -16, 133, -864, -920, -828, -1153, +-251, -377, 259, 959, 758, 1317, 904, 194, +441, -1069, -791, -1160, -1555, 63, -838, 1010, +858, 955, 1948, 75, 1194, -896, -900, -1274, +-2080, -441, -1274, 1035, 919, 1843, 2161, 771, +1167, -1202, -1058, -2132, -2118, -1065, -1038, 1007, +1108, 2147, 1856, 1404, 776, -548, -930, -1959, +-1524, -1679, -518, 40, 700, 1554, 879, 1761, +260, 533, -370, -1009, -397, -1759, -187, -1045, +-8, 524, 222, 1623, 500, 1251, 347, -114, +-350, -1175, -969, -1242, -505, -403, 668, 589, +1245, 1253, 651, 951, -675, -85, -1370, -1239, +-744, -1389, 579, -443, 1359, 1041, 984, 1860, +-327, 1162, -1323, -896, -1202, -2454, -41, -1683, +1176, 1068, 1428, 2782, 416, 1496, -1010, -1277, +-1606, -2351, -664, -848, 883, 1031, 1474, 1318, +591, 458, -709, -223, -1207, -400, -494, -553, +462, -655, 834, -115, 475, 738, -145, 1124, +-525, 479, -401, -597, -76, -1184, 16, -794, +97, 149, 308, 924, 617, 899, 429, 333, +-452, -329, -1106, -700, -646, -760, 416, -384, +1055, 353, 671, 1026, -228, 902, -543, -13, +-341, -965, -164, -1128, -91, -382, 48, 619, +434, 1147, 603, 832, 122, -121, -680, -1009, +-816, -1144, -189, -482, 686, 626, 743, 1310, +212, 1106, -445, -143, -650, -1363, -383, -1472, +229, -194, 521, 1165, 414, 1371, -111, 444, +-417, -617, -210, -1064, 199, -837, 148, 14, +-62, 1030, -177, 1224, -24, 131, 142, -1216, +253, -1200, 188, 204, -73, 1238, -405, 674, +-435, -550, -53, -934, 454, -132, 529, 618, +325, 634, 72, 49, -507, -485, -1115, -726, +-970, -453, 495, 286, 2229, 1118, 1960, 1134, +-582, -30, -3102, -1536, -2797, -1879, 447, -382, +3597, 1751, 3298, 2431, -197, 854, -3618, -1688, +-3467, -2665, 58, -1173, 3264, 1386, 3100, 2481, +21, 1234, -2650, -1045, -2404, -2001, 12, -962, +1974, 782, 1763, 1440, -151, 490, -1501, -693, +-1198, -980, 264, -94, 1276, 766, 929, 787, +-258, -72, -1146, -899, -993, -873, 154, 20, +1218, 905, 1194, 945, -63, 209, -1373, -610, +-1249, -808, 113, -563, 1218, -25, 1071, 485, +-42, 895, -831, 746, -761, -80, -145, -993, +421, -1154, 383, -349, 114, 621, -118, 1019, +24, 765, 251, 280, 37, -383, -401, -1109, +-615, -1377, -311, -489, 355, 1251, 888, 2171, +942, 1232, 284, -977, -1016, -2307, -1778, -1645, +-1024, 321, 863, 1745, 2510, 1702, 1800, 470, +-680, -774, -2832, -1421, -2413, -1200, 443, -240, +3054, 1021, 2590, 1685, -430, 913, -2932, -802, +-2271, -1744, 539, -930, 2408, 721, 1540, 1379, +-577, 460, -1611, -717, -834, -922, 380, 11, +926, 920, 472, 850, -12, -317, -435, -1336, +-666, -1128, -501, 386, 218, 1532, 1097, 1278, +1178, 7, -53, -986, -1502, -1188, -1658, -842, +-317, -121, 1509, 865, 2005, 1517, 909, 1141, +-1088, -99, -2208, -1425, -1521, -1811, 473, -1037, +2096, 640, 1916, 2067, 212, 1991, -1565, 355, +-1934, -1599, -984, -2288, 638, -1410, 1600, 445, +1533, 2061, 413, 2379, -948, 783, -1638, -1566, +-1279, -2727, -65, -1564, 1319, 712, 1738, 2220, +952, 1969, -633, 459, -1831, -1369, -1485, -2203, +24, -1275, 1462, 788, 1669, 2091, 402, 1353, +-1097, -559, -1489, -1643, -555, -1014, 808, 522, +1202, 1398, 520, 745, -529, -685, -903, -1566, +-541, -751, 241, 860, 712, 1735, 703, 1029, +78, -470, -552, -1585, -903, -1598, -592, -521, +356, 1160, 1131, 2154, 1093, 1430, -31, -541, +-1304, -2079, -1432, -1824, -189, -290, 1084, 1279, +1329, 1785, 455, 1066, -629, -438, -999, -1450, +-525, -1154, 264, 114, 583, 794, 200, 326, +-342, -306, -82, -46, 563, 783, 590, 879, +-258, -183, -1136, -1447, -831, -1676, 135, -446, +943, 1366, 1168, 2343, 707, 1560, -338, -526, +-1418, -2397, -1660, -2547, -284, -814, 1479, 1785, +1917, 3085, 578, 1944, -1120, -966, -1460, -2935, +-293, -2120, 712, 460, 492, 1988, -596, 1259, +-742, -287, 591, -695, 1796, 7, 1052, 334, +-1258, -189, -2619, -883, -1362, -652, 1117, 302, +2451, 1126, 1581, 1005, -378, 100, -1517, -812, +-1501, -877, -565, -417, 542, -34, 1119, 115, +966, 432, 223, 1085, -619, 891, -771, -327, +-298, -1607, 170, -1455, 240, 7, -109, 1208, +-86, 1240, 361, 571, 652, -105, 372, -535, +-469, -969, -1092, -1063, -906, -331, 63, 849, +1246, 1663, 1473, 1112, 343, -372, -1184, -1490, +-1451, -1264, -333, -126, 818, 656, 630, 532, +-160, 336, -259, 439, 461, 577, 782, -46, +-76, -1038, -1127, -1476, -1364, -707, -218, 778, +1235, 1955, 1772, 1597, 789, -205, -1046, -1948, +-1901, -1968, -835, -134, 850, 1441, 1429, 1458, +426, 291, -694, -560, -644, -604, 54, -386, +460, -281, 252, 10, -57, 391, -297, 573, +-495, 262, -378, -241, 275, -312, 929, -161, +842, 0, -122, -189, -1139, -357, -1110, 9, +-152, 796, 807, 1158, 1114, 395, 382, -1208, +-433, -2004, -728, -1030, -355, 1166, 138, 2528, +251, 1638, -20, -772, -104, -2396, 16, -1878, +299, 163, 445, 1665, 212, 1606, -318, 473, +-884, -703, -895, -1098, -37, -791, 1132, -61, +1602, 558, 769, 638, -776, 364, -1911, 12, +-1568, -270, -147, -422, 1600, -426, 2099, 25, +1191, 518, -709, 451, -2060, -110, -1854, -563, +-220, -128, 1376, 472, 1737, 417, 705, -368, +-380, -795, -835, -178, -650, 787, -475, 848, +-261, -11, 199, -782, 805, -656, 812, -27, +261, 266, -423, 302, -665, 346, -522, 438, +-172, 68, 46, -640, 329, -962, 555, -345, +505, 688, 281, 1099, -399, 496, -944, -559, +-813, -890, 106, -389, 1042, 401, 949, 492, +-56, 18, -816, -312, -451, -55, 286, 366, +442, 330, -230, -197, -577, -594, -180, -466, +660, 88, 683, 643, 82, 700, -557, 285, +-536, -488, -144, -948, 227, -717, 251, 180, +165, 1063, -16, 1047, -101, 52, -97, -985, +107, -1062, 133, -90, 1, 749, -183, 675, +-298, 21, -258, -353, 31, -183, 541, 59, +856, -33, 362, -181, -785, -161, -1336, 185, +-662, 521, 640, 413, 1261, -270, 799, -933, +-42, -706, -531, 447, -669, 1223, -544, 736, +-387, -491, -13, -1134, 622, -636, 1096, 200, +1043, 709, -17, 702, -1273, 317, -1787, -278, +-859, -822, 619, -762, 1627, -115, 1585, 732, +604, 1051, -749, 539, -1660, -493, -1623, -1184, +-363, -803, 1029, 338, 1667, 1018, 1182, 615, +101, -236, -1010, -505, -1421, -98, -962, 140, +189, -66, 1146, -332, 1125, -154, 195, 289, +-692, 493, -725, 318, -92, -98, 503, -358, +291, -382, -336, -210, -571, -90, -197, 112, +433, 357, 700, 620, 499, 470, 116, -93, +-551, -825, -1131, -1093, -952, -681, 125, 459, +1434, 1535, 1603, 1637, 437, 251, -989, -1595, +-1645, -2224, -1105, -908, 137, 1130, 1135, 2115, +1385, 1283, 637, -328, -427, -1406, -958, -1280, +-843, -421, -254, 451, 247, 866, 444, 789, +458, 345, 315, -262, 142, -729, -19, -646, +-333, -62, -529, 442, -556, 237, -234, -282, +303, -207, 755, 661, 1001, 1126, 628, 287, +-464, -1297, -1521, -1823, -1651, -763, -347, 970, +1453, 1835, 2144, 1386, 1274, 174, -662, -1049, +-2013, -1636, -1807, -1294, -296, -162, 1337, 1120, +1747, 1736, 862, 1098, -423, -287, -1122, -1359, +-971, -1134, -273, -92, 409, 466, 858, 144, +607, -159, -61, 379, -673, 1027, -603, 645, +50, -533, 590, -1290, 419, -996, -109, -223, +-476, 475, -258, 1017, 48, 1226, 185, 670, +166, -529, 84, -1462, 78, -1345, -26, -379, +-118, 680, -76, 1304, -124, 1188, -384, 398, +-264, -760, 342, -1356, 1105, -875, 799, 245, +-400, 886, -1572, 519, -1283, -256, 124, -375, +1415, 250, 1565, 824, 529, 441, -883, -719, +-1521, -1522, -999, -1130, 313, 341, 1248, 1757, +983, 1964, 18, 661, -779, -1189, -663, -2234, +-14, -1615, 412, 49, 411, 1561, -102, 1908, +-503, 1025, -465, -367, 132, -1373, 884, -1368, +968, -514, -87, 438, -1288, 761, -1543, 524, +-175, 229, 1396, 240, 1689, 210, 479, -176, +-901, -793, -1329, -1036, -775, -497, -53, 512, +578, 1332, 959, 1233, 888, 263, 257, -899, +-762, -1413, -1221, -947, -820, 93, 107, 927, +930, 1149, 1087, 593, 596, -233, -174, -821, +-862, -803, -954, -305, -530, 259, 242, 585, +815, 591, 816, 144, 381, -370, -210, -569, +-596, -146, -653, 353, -472, 307, -104, -188, +498, -369, 870, -28, 755, 439, 5, 377, +-850, -55, -1085, -415, -527, -414, 392, -62, +894, 309, 769, 400, 213, 148, -329, -194, +-714, -280, -692, -136, -230, 7, 571, 130, +891, 248, 370, 195, -509, -141, -708, -433, +-80, -200, 567, 274, 376, 357, -248, -62, +-574, -274, -211, 64, 386, 399, 614, 123, +268, -413, -385, -570, -636, -110, -340, 335, +355, 507, 615, 342, 244, 86, -275, -227, +-551, -460, -412, -495, 144, -176, 707, 278, +796, 608, 28, 439, -1129, -85, -1246, -403, +-112, -186, 1208, 181, 1392, 55, 357, -468, +-784, -540, -1167, 137, -737, 859, 254, 845, +858, 94, 676, -644, -97, -814, -455, -465, +34, 117, 427, 377, -25, 306, -742, 186, +-650, 316, 214, 424, 758, 36, 500, -681, +98, -985, -49, -625, -73, 125, -447, 750, +-680, 1058, -399, 891, 302, 188, 797, -670, +729, -1180, 147, -1190, -379, -674, -596, 333, +-441, 1581, -218, 1981, -69, 845, 211, -1017, +504, -1961, 686, -1346, 321, -142, -229, 642, +-676, 885, -780, 892, -493, 670, 151, 178, +697, -523, 910, -1026, 530, -1064, -6, -397, +-421, 581, -823, 1014, -968, 591, -483, 4, +557, -9, 1413, 199, 1185, -176, 157, -981, +-844, -1088, -1246, -219, -886, 884, -121, 1187, +708, 739, 1104, 43, 723, -450, 14, -608, +-571, -526, -848, -510, -620, -482, -85, -38, +566, 989, 814, 1682, 357, 1012, -320, -669, +-633, -1813, -288, -1424, 288, -144, 506, 821, +107, 982, -542, 661, -696, 223, -6, -145, +780, -379, 897, -436, 192, -388, -593, -292, +-775, -86, -548, 239, -49, 563, 488, 652, +789, 300, 598, -313, -112, -710, -684, -484, +-580, 80, -94, 262, 255, -71, 185, -263, +-14, 199, 102, 818, 382, 741, 364, -122, +-223, -1029, -873, -1208, -696, -458, 257, 700, +1035, 1384, 680, 914, -363, -362, -892, -1167, +-377, -773, 501, 235, 724, 723, 66, 387, +-655, -193, -767, -463, 10, -305, 847, 162, +825, 570, 16, 482, -797, -192, -711, -732, +75, -489, 505, 298, 261, 615, -202, 167, +-131, -420, 311, -339, 410, 217, -51, 510, +-599, 171, -647, -336, -106, -460, 401, -155, +667, 133, 613, 256, 135, 265, -465, 167, +-951, -163, -700, -481, 170, -245, 811, 462, +738, 777, 79, 57, -416, -940, -425, -999, +-123, 37, 223, 1059, 303, 1110, -28, 284, +-513, -681, -596, -1109, 64, -742, 943, 217, +986, 921, 162, 751, -863, -77, -1117, -578, +-473, -278, 277, 303, 678, 425, 628, -36, +325, -621, 56, -761, -238, -235, -498, 654, +-605, 1178, -465, 786, 10, -212, 685, -912, +1054, -907, 736, -467, -298, -91, -1155, 244, +-1080, 681, -156, 983, 656, 782, 766, -33, +356, -948, 9, -1314, -178, -891, -314, 0, +-307, 775, -74, 1101, 125, 1018, 85, 510, +-21, -343, 45, -1192, 204, -1393, 88, -755, +-84, 283, -53, 1070, 94, 1310, -36, 924, +-409, -20, -388, -996, 202, -1268, 737, -601, +561, 216, -137, 439, -678, 170, -557, 151, +-64, 577, 331, 887, 456, 471, 220, -644, +-111, -1677, -292, -1637, -228, -219, 118, 1554, +284, 2205, 82, 1136, -254, -596, -336, -1585, +-14, -1319, 345, -403, 369, 377, 66, 663, +-286, 571, -468, 351, -227, 259, 222, 177, +670, -123, 496, -638, -134, -989, -738, -737, +-764, 72, -217, 1024, 431, 1442, 799, 927, +763, -286, 182, -1267, -604, -1329, -927, -573, +-586, 245, 134, 739, 597, 950, 522, 817, +222, 152, -147, -758, -300, -1124, -88, -528, +251, 374, 173, 681, -375, 250, -735, -233, +-255, -183, 554, 189, 894, 366, 521, 90, +-39, -276, -492, -370, -787, -185, -720, -63, +-83, -49, 721, 74, 925, 434, 379, 609, +-215, 249, -433, -397, -358, -694, -216, -447, +-21, -52, 152, 170, 16, 338, -208, 488, +-40, 392, 528, -116, 824, -556, 312, -433, +-588, 144, -1051, 440, -868, 130, -227, -404, +562, -512, 1087, -75, 1071, 462, 329, 677, +-572, 465, -1047, 47, -875, -428, -360, -832, +272, -889, 678, -333, 793, 649, 433, 1276, +-96, 955, -344, -27, -335, -698, -249, -693, +-393, -384, -380, -382, 4, -398, 683, 45, +949, 943, 425, 1405, -355, 801, -685, -539, +-509, -1445, -179, -1251, -64, -271, 68, 563, +394, 804, 477, 651, 239, 366, -3, -6, +-66, -404, -118, -549, -529, -327, -769, 18, +-264, 166, 681, 120, 1137, 17, 560, -47, +-388, 27, -800, 283, -564, 467, -53, 156, +290, -501, 365, -795, 294, -340, 66, 330, +-236, 512, -327, 240, -196, 4, 163, -11, +347, 16, 222, 17, -63, 12, -222, -158, +-246, -473, -125, -506, 21, 100, 195, 815, +261, 843, 114, 131, -85, -558, -83, -666, +-48, -385, -164, -41, -277, 254, -104, 461, +344, 388, 496, 19, 151, -328, -236, -359, +-376, -108, -228, 172, -28, 302, 126, 203, +295, -62, 216, -351, -84, -445, -191, -217, +-72, 266, 79, 692, -12, 635, -171, 43, +-78, -597, 146, -695, 233, -271, 157, 87, +-50, 170, -197, 186, -317, 362, -126, 384, +221, 112, 396, -231, 160, -340, -102, -327, +-214, -296, -104, -141, -140, 187, -154, 418, +64, 396, 352, 292, 316, 168, -73, -216, +-342, -761, -186, -806, 200, -63, 282, 776, +-58, 846, -466, 238, -452, -346, 39, -525, +601, -435, 711, -70, 315, 484, -282, 712, +-675, 167, -685, -730, -309, -927, 255, -174, +665, 745, 652, 892, 243, 276, -257, -432, +-512, -616, -399, -283, -40, 179, 316, 277, +185, 8, -162, -227, -268, -63, 134, 254, +553, 301, 354, -25, -284, -275, -621, -155, +-405, 184, 15, 300, 368, -12, 543, -441, +463, -502, -159, -77, -823, 390, -765, 492, +89, 333, 847, 232, 734, 74, 20, -416, +-395, -936, -413, -775, -323, 142, -236, 929, +61, 901, 472, 317, 568, -224, 146, -489, +-335, -567, -367, -308, -47, 161, 144, 420, +-67, 167, -380, -157, -224, -106, 337, 150, +804, 184, 599, 16, -137, -52, -777, -62, +-813, -155, -361, -249, 230, -70, 573, 182, +551, 226, 298, 51, 17, -16, -134, 69, +-211, 130, -407, 25, -508, -179, -376, -399, +122, -391, 638, -15, 823, 498, 531, 649, +-74, 256, -657, -232, -845, -396, -522, -302, +29, -215, 429, -100, 544, 163, 417, 377, +240, 265, 40, 25, -241, -30, -519, 60, +-532, -65, -319, -440, 153, -598, 536, -211, +602, 498, 414, 913, 17, 658, -339, -78, +-544, -712, -480, -811, -143, -383, 202, 137, +284, 415, 234, 348, 190, 208, 238, 131, +163, 113, -139, 25, -389, -105, -462, -220, +-359, -346, -112, -509, 236, -449, 646, 120, +762, 922, 242, 1120, -524, 338, -901, -662, +-478, -764, 305, -75, 655, 301, 265, -238, +-294, -896, -419, -615, -31, 504, 384, 1396, +395, 1287, 91, 321, -262, -782, -465, -1385, +-317, -1115, 83, -112, 470, 856, 446, 983, +41, 230, -332, -569, -371, -520, -226, 265, +13, 890, 257, 581, 432, -441, 314, -1212, +-136, -1000, -432, 23, -314, 980, -19, 1084, +109, 403, 43, -410, 41, -700, 79, -415, +82, -8, 113, 155, 240, 154, 174, 201, +-263, 269, -757, 98, -603, -252, 170, -397, +870, -175, 823, 133, 133, 171, -553, 63, +-670, 97, -344, 188, 128, 83, 320, -160, +274, -219, 142, -50, 59, 1, -90, -142, +-193, -155, -201, 133, -11, 429, 136, 357, +53, 50, -114, -255, -107, -498, 63, -609, +297, -303, 352, 534, 103, 1254, -372, 972, +-699, -282, -414, -1354, 302, -1275, 728, -272, +419, 567, -214, 697, -387, 509, -42, 512, +192, 543, 60, 92, -211, -775, -274, -1314, +-31, -972, 195, 6, 273, 880, 156, 1112, +-121, 766, -269, 126, -100, -427, 180, -665, +277, -557, 56, -249, -195, 34, -245, 246, +-179, 384, -1, 356, 189, 132, 309, -209, +157, -396, -150, -285, -269, 112, -25, 476, +191, 451, 101, -124, -168, -712, -248, -700, +-70, 30, 143, 757, 189, 820, 199, 303, +177, -319, 9, -704, -314, -762, -525, -402, +-327, 310, 250, 858, 684, 746, 589, 168, +84, -260, -434, -258, -602, -209, -458, -486, +-144, -785, 277, -535, 589, 421, 546, 1414, +104, 1505, -379, 459, -399, -972, -82, -1648, +175, -1132, 41, -48, -299, 763, -393, 909, +-5, 564, 508, 104, 731, -204, 351, -246, +-251, -164, -525, -159, -462, -226, -340, -236, +-273, -85, 99, 209, 734, 510, 989, 581, +326, 124, -690, -667, -1028, -983, -438, -301, +290, 822, 528, 1196, 370, 393, 173, -703, +-59, -1157, -348, -718, -441, 133, -127, 880, +329, 1089, 462, 536, 137, -427, -257, -1017, +-377, -801, -177, -44, 172, 538, 366, 581, +264, 252, -59, -95, -363, -198, -302, -87, +0, 9, 232, -30, 160, -180, -94, -214, +-184, -74, 66, 157, 335, 354, 356, 381, +3, 213, -402, -98, -579, -425, -414, -616, +17, -499, 548, 20, 744, 735, 467, 931, +-188, 304, -620, -584, -574, -766, -153, -166, +254, 387, 436, 309, 252, -60, -123, -271, +-410, -260, -252, -157, 259, 172, 561, 651, +293, 686, -251, 5, -571, -812, -406, -929, +-32, -300, 298, 437, 425, 749, 342, 549, +75, 32, -250, -443, -460, -488, -399, -100, +-46, 248, 408, 172, 609, -100, 294, -199, +-295, -77, -616, 102, -347, 262, 203, 380, +471, 188, 213, -292, -263, -607, -398, -354, +-38, 173, 467, 402, 485, 199, -60, -71, +-574, -206, -462, -144, 56, 159, 402, 552, +284, 542, 60, -181, -105, -1042, -240, -1115, +-281, -239, -16, 841, 419, 1267, 496, 857, +4, -12, -520, -801, -513, -1024, -82, -566, +319, 136, 372, 541, 198, 481, -102, 215, +-351, -17, -212, -154, 220, -84, 519, 99, +211, 107, -503, -256, -806, -613, -295, -382, +551, 382, 966, 900, 483, 627, -384, -156, +-841, -678, -569, -556, 91, -73, 521, 267, +501, 213, 274, 8, -124, -37, -528, 66, +-625, 85, -133, 5, 652, 31, 840, 142, +117, 9, -720, -387, -769, -513, -6, -44, +640, 557, 535, 578, -60, 55, -467, -398, +-360, -381, 65, -67, 336, 224, 289, 316, +19, 154, -282, -183, -359, -432, -179, -342, +188, 17, 465, 355, 402, 467, -15, 307, +-406, -13, -471, -295, -185, -311, 163, -135, +313, -89, 230, -225, 41, -206, -96, 212, +-77, 691, 37, 686, 30, 125, -90, -538, +-221, -799, -148, -479, 91, 132, 266, 548, +269, 430, 96, -30, -223, -335, -405, -225, +-265, 90, 192, 307, 584, 301, 396, 91, +-215, -251, -658, -490, -512, -351, 67, 33, +546, 346, 535, 406, 193, 291, -257, 28, +-458, -393, -316, -627, 37, -239, 310, 490, +290, 724, 23, 166, -158, -454, -157, -390, +-18, 42, 92, 113, 42, -195, -38, -296, +-107, 125, -64, 545, 129, 498, 307, 25, +202, -400, -132, -481, -470, -237, -417, 53, +-50, 178, 318, 118, 483, 117, 420, 227, +90, 211, -379, -99, -669, -464, -435, -416, +163, 34, 568, 393, 459, 372, 89, 118, +-183, -57, -257, -166, -269, -333, -172, -406, +12, -144, 218, 359, 262, 682, 205, 480, +28, -43, -164, -512, -263, -637, -149, -385, +62, 26, 143, 401, 6, 524, -76, 338, +23, -25, 96, -293, 43, -292, 8, -56, +121, 88, 186, 9, -71, -210, -447, -256, +-528, 26, -147, 394, 402, 548, 708, 303, +557, -172, 7, -543, -611, -597, -819, -264, +-404, 231, 351, 597, 819, 547, 557, 75, +-193, -494, -750, -640, -575, -234, 177, 390, +715, 679, 490, 393, -203, -186, -637, -651, +-371, -607, 226, -68, 591, 548, 389, 636, +-226, 58, -681, -520, -551, -368, 120, 282, +709, 521, 619, -37, 49, -631, -381, -454, +-410, 265, -204, 697, -59, 460, 74, -91, +248, -507, 231, -646, -16, -426, -263, 141, +-234, 732, 80, 856, 345, 345, 372, -412, +61, -798, -407, -622, -663, -87, -388, 345, +241, 431, 725, 248, 584, 42, 6, -25, +-530, -32, -555, -62, -123, -116, 387, -167, +460, -192, 50, -73, -398, 207, -367, 450, +37, 293, 349, -215, 184, -569, -158, -386, +-222, 153, 41, 540, 303, 479, 217, 40, +-157, -456, -383, -564, -274, -128, 75, 457, +230, 495, 67, -90, -62, -602, 64, -341, +273, 373, 203, 714, -211, 322, -455, -350, +-261, -649, 110, -364, 277, 179, 127, 457, +-83, 189, -55, -310, 63, -404, 160, 147, +51, 728, -138, 562, -242, -302, -127, -931, +61, -683, 173, 149, 98, 653, -31, 498, +-70, 62, 14, -101, 77, -32, 5, -109, +-142, -422, -197, -495, -35, -6, 206, 682, +272, 833, 81, 250, -152, -464, -218, -720, +-143, -532, -102, -232, -107, 113, 23, 572, +357, 896, 562, 619, 232, -227, -444, -991, +-836, -1007, -456, -246, 327, 630, 700, 929, +312, 462, -283, -274, -408, -592, 8, -309, +355, 124, 217, 181, -169, -68, -367, -164, +-247, 106, -20, 451, 131, 456, 266, 27, +310, -561, 120, -869, -222, -587, -401, 209, +-223, 930, 80, 1012, 200, 353, 142, -461, +111, -820, 47, -562, -146, -57, -367, 256, +-240, 219, 205, 91, 495, 129, 270, 294, +-236, 269, -482, -108, -263, -514, 131, -554, +321, -167, 192, 317, -57, 523, -179, 407, +-120, 85, 51, -197, 106, -334, 19, -362, +-137, -351, -220, -176, -119, 270, 227, 808, +492, 852, 364, 156, -218, -798, -737, -1173, +-654, -642, -13, 279, 587, 885, 663, 838, +316, 295, -121, -294, -434, -580, -490, -459, +-264, -130, 92, 130, 309, 198, 215, 127, +-11, -4, -24, 8, 110, 233, 147, 448, +-101, 200, -425, -568, -469, -1125, -79, -708, +438, 498, 646, 1385, 326, 1121, -256, 15, +-643, -952, -520, -1143, -32, -592, 446, 192, +499, 755, 98, 796, -290, 354, -287, -171, +7, -450, 174, -449, -17, -356, -196, -167, +-75, 208, 87, 610, 51, 621, -92, 108, +-4, -516, 293, -661, 327, -266, -93, 213, +-598, 347, -674, 167, -119, 34, 615, 92, +884, 130, 373, -65, -514, -398, -897, -464, +-425, -112, 349, 392, 627, 619, 202, 413, +-316, -82, -372, -539, -3, -679, 310, -301, +208, 371, -198, 761, -403, 462, -168, -257, +302, -624, 425, -323, 71, 241, -332, 452, +-367, 163, -122, -287, 91, -487, 191, -259, +254, 282, 231, 712, -54, 575, -416, -109, +-479, -778, -111, -805, 284, -215, 407, 469, +221, 759, -45, 514, -187, -75, -233, -587, +-210, -597, -99, -37, 33, 559, 133, 516, +192, -134, 158, -628, 82, -376, -86, 291, +-290, 560, -356, 189, -153, -312, 195, -359, +384, -12, 217, 283, -63, 256, -170, 5, +-147, -268, -136, -389, -109, -233, 28, 185, +181, 564, 116, 490, -103, -30, -152, -528, +38, -552, 148, -159, -15, 274, -188, 434, +-121, 306, 117, 4, 186, -267, -44, -304, +-331, -81, -299, 142, 112, 83, 538, -123, +474, -149, -112, 133, -658, 406, -585, 349, +-49, -51, 355, -465, 357, -562, 185, -286, +87, 175, -17, 500, -267, 519, -439, 255, +-286, -121, 79, -419, 340, -485, 321, -255, +115, 127, -70, 384, -202, 354, -227, 170, +-164, -12, -68, -180, 27, -380, 80, -449, +106, -151, 208, 409, 244, 765, 61, 528, +-328, -151, -625, -731, -467, -762, 124, -276, +624, 331, 633, 623, 202, 506, -314, 200, +-588, -95, -467, -335, -69, -513, 297, -464, +357, -87, 114, 419, -110, 651, -139, 457, +-57, 10, 3, -372, 25, -550, 9, -477, +-86, -124, -214, 350, -126, 636, 155, 472, +295, 4, 112, -403, -173, -446, -248, -216, +-99, 41, 45, 133, 85, 104, 55, 82, +-15, 133, -99, 196, -112, 136, 32, -95, +115, -369, -9, -452, -159, -186, -124, 283, +85, 615, 245, 477, 109, -43, -184, -559, +-351, -640, -253, -227, 58, 363, 321, 633, +330, 354, 107, -171, -203, -416, -400, -192, +-372, 116, -40, 101, 381, -167, 543, -244, +191, 20, -387, 338, -685, 376, -404, 137, +172, -145, 597, -311, 512, -298, 55, -93, +-409, 178, -491, 258, -158, 57, 169, -201, +113, -170, -114, 109, -160, 319, 87, 206, +372, -96, 354, -282, 21, -222, -392, -52, +-605, 52, -402, 66, 109, 68, 509, 90, +432, 101, 39, 69, -246, 14, -221, -86, +-16, -189, 88, -192, -5, -18, -187, 186, +-289, 204, -118, 18, 247, -105, 447, -20, +232, 81, -204, -19, -411, -200, -259, -153, +-5, 89, 128, 260, 125, 192, 76, 38, +26, -108, -34, -264, -67, -344, -109, -131, +-109, 347, -54, 601, 28, 272, 64, -375, +25, -638, -15, -246, 81, 354, 115, 500, +-40, 137, -238, -289, -303, -328, -153, -62, +99, 164, 244, 169, 292, 49, 190, -22, +-84, -36, -360, -52, -415, -81, -143, -52, +243, 45, 386, 139, 124, 126, -309, -37, +-422, -225, -30, -214, 436, 67, 415, 313, +-72, 232, -486, -97, -386, -267, -2, -96, +213, 116, 105, 98, 7, -88, 37, -160, +90, -81, 21, 68, -126, 248, -201, 391, +-85, 240, 58, -296, 86, -774, -42, -605, +-143, 167, -82, 776, 101, 680, 215, 117, +141, -278, -33, -334, -209, -286, -357, -302, +-296, -199, 51, 156, 408, 521, 434, 517, +38, 91, -372, -357, -361, -447, -46, -143, +172, 180, 118, 212, -90, -29, -178, -237, +-75, -177, 146, 114, 306, 366, 207, 332, +-161, 48, -492, -259, -453, -341, -25, -215, +428, -57, 487, 21, 120, 66, -256, 173, +-310, 300, -86, 334, 61, 164, -76, -190, +-246, -578, -56, -677, 322, -300, 464, 363, +143, 818, -328, 716, -503, 174, -314, -431, +-43, -753, 188, -622, 364, -75, 424, 513, +202, 670, -272, 256, -624, -233, -557, -329, +-105, -123, 373, -18, 559, -96, 385, -12, +37, 245, -281, 317, -399, 9, -331, -299, +-162, -280, 34, -48, 230, 79, 343, 105, +263, 182, -5, 230, -276, 76, -359, -214, +-179, -348, 70, -219, 188, 29, 150, 230, +37, 291, -99, 173, -170, -68, -134, -213, +-1, -170, 138, -63, 169, -38, 63, 32, +-46, 242, -125, 355, -219, 63, -248, -426, +-66, -540, 226, -104, 381, 413, 174, 476, +-180, 131, -264, -195, -93, -202, 4, -31, +-102, 19, -179, -135, 47, -246, 364, -37, +365, 341, 12, 454, -410, 94, -515, -330, +-234, -378, 219, -73, 495, 156, 401, 145, +-41, 54, -402, 4, -398, -49, -112, -120, +134, -98, 187, 35, 111, 177, 21, 224, +-59, 136, -122, -131, -88, -453, 24, -443, +98, 72, 71, 667, -9, 646, -126, -52, +-219, -735, -168, -687, 100, 5, 347, 655, +261, 678, -136, 116, -373, -480, -133, -607, +247, -231, 202, 210, -226, 364, -460, 280, +-125, 144, 411, -50, 508, -309, 112, -398, +-304, -119, -362, 283, -154, 341, -39, 74, +-10, -141, 117, -64, 282, 76, 254, 48, +-39, -135, -397, -269, -429, -233, -101, 34, +322, 400, 499, 550, 240, 258, -270, -286, +-511, -595, -269, -467, 193, -91, 337, 249, +88, 427, -162, 377, -67, 103, 130, -202, +98, -294, -159, -157, -268, -40, -80, -31, +220, -11, 300, 119, 75, 221, -243, 174, +-341, -2, -103, -203, 200, -305, 220, -205, +19, 97, -92, 360, 32, 313, 126, 12, +-52, -248, -301, -282, -252, -181, 32, -61, +259, 85, 240, 270, 130, 350, 11, 211, +-131, -156, -313, -506, -292, -548, 28, -115, +402, 510, 400, 728, 10, 283, -427, -381, +-417, -629, 47, -329, 451, 114, 339, 320, +-130, 273, -399, 58, -149, -152, 256, -176, +278, 28, -104, 169, -395, -14, -202, -296, +295, -228, 508, 174, 166, 387, -382, 120, +-529, -278, -140, -318, 337, 3, 398, 298, +69, 295, -195, 15, -159, -300, 12, -417, +46, -198, -102, 162, -146, 351, 39, 277, +271, 95, 327, -27, 84, -170, -262, -348, +-357, -371, -136, -93, 139, 318, 191, 508, +86, 280, 76, -142, 126, -438, 30, -404, +-204, -93, -251, 261, 11, 448, 260, 290, +165, -143, -127, -535, -242, -491, -55, 53, +154, 571, 187, 470, 108, -106, 38, -457, +-46, -215, -200, 136, -298, 45, -138, -224, +208, -105, 431, 356, 322, 471, -34, 2, +-308, -475, -287, -427, -84, -67, 95, 99, +178, 37, 213, 100, 171, 353, 8, 391, +-182, -22, -225, -582, -4, -700, 226, -219, +239, 410, 41, 619, -172, 255, -209, -242, +-27, -388, 185, -134, 273, 185, 158, 209, +-90, -72, -270, -360, -230, -342, 12, 24, +248, 427, 263, 471, 69, 138, -124, -290, +-123, -486, 11, -415, 88, -165, -7, 213, +-110, 528, -30, 476, 175, 3, 278, -485, +159, -517, -72, -140, -219, 185, -181, 199, +-32, 39, 158, -44, 245, -5, 178, 83, +66, 105, 38, -46, 31, -275, -35, -344, +-175, -89, -266, 241, -149, 281, 159, 54, +486, -86, 584, -28, 317, -10, -256, -174, +-755, -299, -741, -164, -124, 98, 650, 262, +916, 244, 476, 101, -203, -127, -526, -343, +-365, -333, -50, -65, 96, 212, 108, 215, +159, -12, 250, -181, 250, -101, 125, 108, +-67, 223, -193, 50, -238, -302, -118, -481, +177, -255, 408, 202, 314, 434, 28, 280, +-120, -2, -49, -157, 29, -237, -83, -323, +-125, -295, 104, -3, 384, 334, 298, 343, +-99, -2, -333, -337, -110, -272, 280, 76, +314, 289, -29, 104, -279, -285, -112, -426, +213, -175, 314, 158, 91, 223, -105, 65, +-52, -10, 127, 66, 142, 63, -58, -124, +-184, -332, -31, -355, 258, -186, 413, 63, +287, 311, -5, 397, -240, 234, -253, -109, +-82, -394, 140, -474, 279, -364, 361, -100, +339, 280, 138, 514, -226, 314, -431, -186, +-240, -458, 164, -244, 434, 51, 394, 27, +147, -182, -70, -156, -158, 124, -139, 281, +-26, 110, 120, -203, 176, -380, 144, -298, +84, 13, 45, 363, -17, 437, -46, 27, +67, -549, 264, -746, 257, -329, -32, 334, +-258, 669, -104, 493, 277, 4, 439, -452, +182, -635, -139, -468, -177, -82, 106, 272, +343, 377, 271, 240, -55, 25, -219, -130, +-109, -192, 144, -253, 323, -292, 301, -225, +150, -2, -24, 222, -118, 246, -127, 94, +-24, -56, 109, -132, 195, -220, 194, -313, +135, -233, 80, 72, 36, 292, 18, 164, +-17, -186, -16, -340, -19, -127, 76, 143, +258, 184, 363, 3, 229, -185, -44, -239, +-205, -208, -105, -156, 103, -44, 250, 114, +295, 248, 224, 209, 128, -28, 62, -278, +-15, -371, -101, -283, -147, -160, -12, -40, +324, 163, 592, 383, 460, 344, -65, -74, +-499, -566, -425, -634, 88, -195, 509, 317, +433, 430, 22, 84, -210, -322, -9, -417, +363, -131, 411, 241, -10, 303, -385, 20, +-297, -334, 124, -449, 389, -286, 344, 3, +254, 272, 241, 385, 141, 189, -102, -241, +-263, -566, -147, -456, 156, -14, 340, 293, +344, 242, 276, -12, 183, -155, 22, -134, +-140, -111, -104, -115, 77, -105, 226, -86, +186, -73, 82, -37, 133, 80, 209, 203, +110, 75, -96, -288, -160, -569, 24, -404, +322, 126, 367, 529, 136, 460, -116, 4, +-128, -461, 44, -639, 192, -491, 223, -81, +153, 377, 73, 560, 20, 332, 66, -150, +161, -487, 218, -477, 160, -270, 73, -78, +-6, 0, -32, 65, 52, 200, 264, 352, +452, 339, 315, -58, -124, -707, -423, -1052, +-185, -627, 417, 384, 755, 1117, 416, 909, +-212, -12, -503, -848, -262, -988, 188, -523, +453, 89, 381, 477, 157, 493, 41, 207, +83, -177, 55, -404, -157, -333, -304, -117, +-68, 11, 454, -9, 681, -72, 382, -13, +-122, 79, -286, 69, -74, -45, 163, -197, +141, -269, 49, -249, 131, -96, 350, 186, +424, 386, 189, 224, -109, -292, -248, -727, +-126, -594, 151, 19, 370, 569, 390, 617, +246, 171, 76, -348, -58, -626, -112, -540, +-94, -193, 27, 160, 209, 319, 357, 241, +297, 48, 62, -101, -128, -184, -60, -206, +184, -175, 251, -171, 12, -205, -187, -210, +-30, -5, 358, 382, 518, 573, 268, 242, +-139, -477, -244, -969, -20, -729, 259, 37, +296, 677, 155, 707, 63, 200, 99, -354, +121, -603, 74, -476, 51, -136, 194, 173, +380, 292, 285, 128, -153, -143, -478, -263, +-250, -123, 379, 105, 776, 107, 564, -159, +17, -385, -343, -315, -339, 49, -150, 380, +116, 349, 333, -23, 425, -458, 311, -578, +56, -277, -127, 177, -72, 443, 91, 307, +146, -79, 71, -402, 18, -447, 123, -205, +254, 95, 291, 220, 151, 120, -15, -93, +-69, -190, 53, -115, 212, 21, 235, 40, +122, -125, -5, -284, 24, -237, 162, 29, +249, 284, 152, 216, 5, -106, -58, -346, +64, -268, 193, 7, 164, 120, 57, -24, +7, -172, 55, -133, 156, 55, 207, 118, +144, -22, -25, -170, -158, -191, -82, -85, +179, -6, 398, 10, 352, 36, 101, 24, +-100, -74, -123, -233, -19, -283, 68, -67, +123, 221, 233, 288, 363, 39, 323, -295, +100, -371, -163, -189, -220, 37, -49, 106, +202, 32, 323, -4, 264, 23, 121, -1, +67, -108, 51, -222, 38, -185, 15, -34, +9, 31, 33, -18, 100, -63, 190, 42, +228, 164, 140, 46, -10, -256, -115, -439, +-39, -250, 125, 144, 247, 349, 219, 213, +120, -115, 16, -351, -12, -318, -42, -105, +-15, 131, 101, 207, 272, 66, 385, -106, +288, -172, 40, -115, -245, -81, -351, -135, +-138, -119, 297, 39, 621, 219, 560, 195, +149, -56, -272, -277, -368, -313, -155, -213, +145, -71, 280, 65, 296, 227, 262, 259, +173, 49, 17, -258, -139, -391, -175, -223, +-61, 26, 91, 107, 252, 55, 321, 13, +214, 21, 9, -11, -107, -120, -33, -155, +117, -95, 130, -49, 36, -58, 2, -41, +115, 85, 223, 146, 163, -10, 74, -237, +70, -266, 94, -56, 9, 121, -116, 79, +-46, -45, 208, -93, 389, -81, 316, -79, +65, -59, -105, 53, -115, 121, -105, -20, +-59, -287, 81, -384, 327, -104, 489, 325, +308, 505, -120, 222, -449, -336, -383, -705, +11, -558, 430, 10, 573, 562, 345, 616, +-60, 154, -286, -381, -186, -535, 70, -238, +184, 89, 67, 103, -21, -100, 100, -154, +322, 99, 347, 340, 63, 227, -214, -155, +-226, -448, 15, -400, 246, -112, 298, 151, +176, 268, 25, 175, -65, -49, -19, -235, +91, -199, 160, 53, 137, 185, 58, -1, +-9, -295, -44, -353, -33, -57, 31, 275, +136, 318, 232, 94, 210, -172, 59, -255, +-58, -197, -43, -111, 38, -17, 35, 63, +-63, 116, -67, 67, 108, -64, 325, -141, +369, -89, 193, 29, -46, 89, -220, -6, +-273, -171, -188, -275, 73, -205, 444, 84, +642, 385, 432, 427, -90, 69, -507, -438, +-515, -660, -162, -431, 293, 78, 580, 498, +512, 575, 158, 271, -198, -258, -344, -628, +-175, -544, 114, -88, 256, 342, 183, 379, +45, 119, 10, -101, 48, -133, 86, -92, +57, -133, 8, -194, 15, -113, 45, 75, +16, 199, -50, 135, -7, -39, 192, -126, +373, -101, 273, -76, -70, -109, -343, -128, +-228, -4, 116, 156, 339, 176, 262, 11, +56, -187, -52, -206, -22, -72, 25, 56, +43, 71, 95, -2, 152, -68, 87, -93, +-104, -92, -172, -26, 45, 80, 382, 148, +442, 44, 79, -175, -347, -262, -453, -110, +-159, 102, 263, 109, 478, -72, 382, -134, +107, 38, -169, 203, -282, 122, -182, -148, +72, -314, 237, -255, 243, -80, 153, 112, +41, 231, -9, 243, 14, 100, 20, -143, +-50, -306, -141, -308, -101, -172, 168, 23, +463, 219, 471, 330, 43, 218, -419, -96, +-460, -372, -61, -394, 405, -136, 497, 163, +162, 265, -222, 142, -291, -70, -37, -157, +276, -83, 335, 15, 83, -6, -276, -145, +-325, -196, 7, 3, 409, 258, 503, 274, +122, -55, -334, -399, -386, -350, 8, 55, +381, 383, 338, 248, -50, -176, -289, -396, +-159, -215, 181, 136, 330, 284, 196, 143, +-19, -81, -136, -204, -80, -192, 54, -95, +112, 21, 117, 121, 63, 118, -3, 26, +-10, -79, 47, -114, 87, -45, 51, 12, +-23, -13, -60, -76, -53, -103, 65, -39, +163, 56, 180, 121, 134, 138, -8, 60, +-176, -126, -168, -317, 21, -316, 245, -31, +244, 263, 35, 285, -168, 66, -123, -109, +115, -69, 178, -6, 10, -106, -99, -245, +-17, -204, 175, 35, 232, 222, 50, 218, +-131, 126, -101, 28, 71, -90, 154, -265, +46, -376, -65, -224, -89, 113, 57, 366, +194, 328, 157, 74, 8, -136, -109, -198, +-111, -197, 21, -198, 119, -161, 120, 7, +71, 211, 50, 296, 64, 222, 3, 20, +-106, -187, -183, -343, -86, -380, 164, -196, +306, 144, 228, 429, 37, 425, -139, 98, +-178, -274, -121, -405, -33, -260, 128, -25, +286, 94, 314, 134, 90, 150, -195, 113, +-300, -27, -192, -169, 49, -145, 249, 2, +238, 50, 120, -66, -24, -163, -90, -38, +-12, 206, 74, 252, 28, 21, -131, -261, +-124, -290, 96, -47, 310, 184, 276, 186, +-40, -24, -348, -193, -292, -123, 14, 65, +274, 155, 313, 54, 134, -107, -102, -154, +-223, -99, -113, 4, 110, 112, 263, 165, +193, 95, -88, -122, -300, -298, -195, -227, +86, 46, 299, 292, 300, 271, 112, 43, +-124, -175, -294, -271, -290, -203, -47, -43, +324, 131, 482, 231, 235, 140, -178, -55, +-379, -171, -216, -117, 108, 23, 244, 55, +85, -12, -121, -80, -156, -85, 39, -20, +295, 73, 331, 162, 20, 156, -379, -30, +-473, -251, -151, -269, 347, -36, 587, 203, +344, 158, -121, -51, -403, -131, -380, 16, +-134, 184, 152, 113, 295, -113, 228, -247, +73, -187, -60, -20, -87, 92, -10, 144, +-2, 178, -111, 138, -135, -13, 22, -206, +217, -272, 285, -116, 145, 88, -114, 164, +-333, 74, -331, -34, -115, -12, 238, 64, +500, 82, 372, -2, -91, -129, -466, -191, +-421, -154, -8, -12, 375, 196, 370, 300, +43, 198, -261, -90, -267, -325, -26, -291, +196, -22, 189, 239, -33, 261, -189, 45, +-113, -180, 103, -211, 239, -26, 135, 187, +-123, 205, -257, -10, -169, -259, 77, -236, +260, 85, 268, 352, 56, 260, -246, -130, +-390, -401, -248, -281, 107, 81, 421, 355, +384, 338, 72, 77, -233, -231, -349, -378, +-232, -210, 13, 122, 227, 301, 268, 189, +123, -63, -89, -149, -221, -29, -136, 76, +46, 46, 75, -59, -33, -112, -89, -72, +-7, 24, 169, 161, 235, 228, 73, 92, +-222, -176, -366, -331, -205, -152, 136, 197, +386, 360, 286, 174, -83, -167, -324, -314, +-247, -161, -5, 108, 162, 256, 120, 185, +5, 20, -38, -121, 2, -187, 9, -119, +-26, 46, -11, 168, -11, 137, -44, -23, +-52, -105, -45, -33, 20, 89, 89, 97, +64, -33, -1, -109, -54, -59, -105, 37, +-145, 87, -75, 45, 144, 4, 290, -5, +175, -4, -159, 13, -388, 38, -248, 56, +87, 30, 237, -90, 175, -170, 25, -108, +-56, 121, -97, 326, -158, 248, -177, -30, +-12, -244, 211, -235, 228, -83, 26, 30, +-149, 115, -158, 201, -51, 219, 26, 88, +-43, -145, -97, -252, 23, -140, 153, 44, +134, 160, -16, 146, -178, 78, -182, 34, +-34, -8, 59, -98, 37, -175, 33, -92, +79, 132, 80, 274, -16, 209, -201, -27, +-271, -198, -102, -156, 142, -40, 234, 6, +138, 33, -50, 152, -182, 295, -181, 198, +-69, -129, 28, -373, 87, -293, 109, 70, +53, 328, -55, 263, -163, 32, -142, -138, +13, -82, 116, 69, 69, 113, -76, 3, +-185, -142, -113, -146, 99, -12, 227, 163, +155, 285, -101, 199, -329, -47, -302, -227, +-38, -218, 242, -60, 316, 128, 152, 240, +-139, 200, -338, -3, -311, -166, -113, -170, +127, -9, 294, 172, 242, 220, 19, 108, +-224, -79, -368, -195, -259, -140, 57, 15, +326, 168, 297, 234, 7, 166, -289, 0, +-362, -172, -143, -218, 166, -83, 256, 125, +120, 254, -126, 168, -257, -41, -124, -140, +81, -55, 133, 91, 51, 116, -97, 13, +-185, -75, -138, -86, 33, 36, 159, 189, +121, 190, -53, 30, -254, -154, -242, -193, +10, -34, 196, 176, 98, 235, -88, 82, +-137, -81, -40, -56, 54, 43, -5, 19, +-155, -99, -166, -81, 12, 142, 160, 312, +94, 186, -99, -124, -210, -264, -161, -168, +16, 32, 158, 192, 107, 280, -47, 229, +-197, -19, -238, -276, -85, -264, 156, 15, +243, 264, 78, 241, -188, 30, -321, -104, +-243, -43, 7, 64, 240, 110, 225, 34, +9, -91, -240, -119, -343, 5, -133, 195, +170, 241, 230, 58, 31, -120, -207, -143, +-251, -9, -97, 131, 91, 97, 165, -2, +20, -18, -203, 56, -275, 86, -110, -7, +135, -31, 190, 60, 63, 150, -128, 104, +-259, -102, -190, -210, -35, -59, 114, 209, +164, 296, -7, 137, -254, -92, -231, -182, +16, -36, 138, 99, 54, 79, -122, 17, +-205, 27, -124, 91, 23, 88, 63, 10, +14, -41, -79, -16, -126, 75, -89, 67, +-6, -21, 14, 8, -84, 79, -154, 70, +-105, 1, 1, -12, 69, 64, 59, 95, +-98, 29, -219, -67, -149, -23, -32, 113, +38, 135, 56, 1, 47, -79, -29, 2, +-165, 86, -285, 127, -251, 66, -11, -56, +264, -64, 284, 21, 53, 160, -259, 176, +-499, -10, -453, -185, -42, -131, 382, 109, +435, 276, 124, 246, -274, 101, -450, -144, +-325, -306, -142, -200, 3, 77, 109, 309, +180, 336, 129, 219, -24, 33, -194, -169, +-335, -298, -367, -267, -216, 10, 81, 340, +384, 455, 391, 247, -38, -96, -511, -265, +-601, -195, -276, 4, 194, 140, 407, 150, +206, 94, -177, 46, -405, 38, -306, 84, +6, 106, 164, 10, 2, -137, -211, -202, +-225, -52, -57, 277, 120, 481, 120, 278, +-75, -222, -296, -506, -359, -271, -215, 230, +93, 484, 295, 349, 149, 54, -181, -218, +-381, -310, -353, -129, -132, 167, 153, 316, +217, 244, -7, 13, -253, -175, -307, -128, +-193, 108, 57, 256, 140, 152, -36, -88, +-178, -258, -243, -150, -219, 174, -13, 382, +103, 322, -6, 78, -79, -177, -99, -295, +-175, -182, -203, 50, -152, 238, -120, 316, +-34, 253, 70, 38, 9, -221, -82, -220, +-116, 19, -167, 239, -228, 245, -203, -22, +-96, -233, -12, -97, 92, 212, 76, 312, +-158, 148, -291, -55, -147, -139, -42, -46, +-66, 114, -168, 121, -237, -3, -71, -107, +125, -86, 38, 128, -161, 350, -190, 370, +-124, 127, -75, -213, -135, -444, -198, -392, +-172, 21, -43, 426, 38, 561, 10, 428, +-20, 98, -121, -259, -291, -477, -339, -349, +-176, -24, 86, 254, 196, 446, -7, 414, +-299, 173, -352, -95, -185, -249, -35, -245, +79, -109, 65, 75, -59, 228, -199, 305, +-367, 247, -399, 46, -154, -170, 175, -212, +230, -80, 23, 129, -150, 285, -286, 234, +-331, 41, -231, -79, -163, -126, -74, -90, +27, 43, 59, 147, 15, 196, -61, 169, +-166, 143, -282, 40, -306, -137, -246, -190, +-171, -156, -31, -14, 162, 226, 274, 493, +0, 477, -429, -17, -566, -483, -384, -485, +-1, -57, 249, 404, 98, 462, -106, 180, +-179, -122, -253, -162, -232, 57, -143, 177, +-106, 53, -125, -98, -70, -133, -61, 19, +-61, 234, -37, 325, -105, 198, -292, -105, +-282, -263, -149, -135, -97, 101, 17, 263, +38, 230, -85, 66, -157, -24, -223, -61, +-288, -55, -178, -11, -37, 22, 27, 211, +-90, 314, -193, 104, -163, -189, -69, -237, +-54, 31, -222, 202, -296, 130, -113, 79, +45, 192, -43, 211, -209, -156, -246, -464, +-125, -136, 37, 519, 2, 597, -194, 19, +-334, -376, -360, -220, -120, 79, 230, 181, +207, 179, -178, 192, -502, 73, -430, -138, +-21, -157, 211, 58, 27, 239, -295, 110, +-334, -77, -163, 38, 18, 203, 91, 114, +-64, -121, -275, -158, -315, 73, -215, 298, +-140, 173, -90, -141, 0, -180, 45, 52, +-45, 350, -118, 335, -250, -55, -355, -332, +-311, -195, -196, 184, -27, 220, 197, 75, +185, 165, -83, 158, -341, -34, -456, -69, +-374, 62, -98, 14, 110, -216, 51, -93, +-40, 344, -152, 470, -191, 160, -113, -238, +-125, -287, -291, 28, -268, 221, -127, 102, +49, -59, 196, 20, 22, 204, -397, 229, +-546, -49, -264, -255, 91, -4, 218, 320, +26, 240, -199, -155, -239, -228, -206, 139, +-289, 316, -371, 60, -160, -252, 215, -73, +351, 316, 101, 315, -366, 60, -630, -137, +-472, -204, -109, -164, 114, 7, 109, 302, +70, 416, 52, 230, -136, -10, -363, -190, +-406, -311, -242, -222, -53, 148, -40, 451, +-48, 270, 54, -68, 89, -29, -67, 208, +-275, 25, -419, -364, -324, -190, -235, 326, +-59, 307, 337, -97, 369, 13, -199, 382, +-639, 152, -446, -395, -34, -308, 53, 304, +-72, 342, -112, -184, -11, -230, 90, 357, +-164, 581, -425, -60, -248, -610, 28, -171, +-91, 463, -225, 252, -53, -234, 23, -65, +-8, 376, 54, 266, -191, -138, -523, -228, +-375, -99, -36, 97, 89, 253, 197, 222, +140, -19, -244, -187, -367, 16, -278, 238, +-267, 30, -44, -174, 99, 121, -98, 345, +-103, -40, 80, -315, -33, 70, -282, 342, +-355, 2, -310, -236, -90, 115, 166, 367, +140, 38, -112, -187, -244, -71, -153, 96, +-127, 129, -253, 39, -269, 66, -108, -4, +207, -84, 194, 154, -226, 298, -298, 64, +-180, -203, -180, -92, -171, 57, -129, -126, +50, -33, 186, 467, -116, 486, -270, -67, +-164, -397, -181, -196, -174, 86, -123, 1, +7, -28, 105, 394, -120, 470, -208, -28, +-64, -339, -240, -229, -177, 25, -6, 64, +-112, 149, -81, 375, 2, 118, -60, -208, +-153, -186, -203, 24, -133, 226, -48, 82, +-88, 1, -198, 77, -117, 19, 171, -16, +86, -67, -340, 0, -425, 154, -89, 207, +102, 91, -14, -131, -91, -142, -17, 121, +2, 285, -219, -30, -359, -328, -213, -77, +-20, 289, 170, 411, 111, 192, -111, -92, +-260, -233, -336, -366, -144, -118, 94, 348, +49, 430, -161, 209, -323, -87, -100, -180, +224, -99, 176, 49, -75, 142, -551, -23, +-691, -124, -30, 24, 501, 264, 335, 279, +14, 53, -342, -111, -555, -168, -353, -135, +16, -48, 248, 205, 190, 380, -172, 95, +-429, -176, -128, -139, 253, 47, 94, 131, +-303, 42, -380, 92, -187, 23, 16, -164, +77, -39, 57, 194, 53, 252, -159, 33, +-388, -175, -165, -42, 79, 63, 3, 75, +-157, 108, -163, 14, 61, -64, -74, 30, +-316, 87, -22, -31, 185, -7, 50, 243, +-290, 195, -429, -200, -16, -272, 126, 6, +-113, 122, -64, 244, -21, 276, -59, 13, +-29, -221, -258, -262, -193, -48, 175, 320, +-41, 368, -285, 5, -147, -286, -172, -153, +-2, 74, 283, 139, 152, 265, -277, 183, +-490, -162, -279, -299, -47, -105, 138, 273, +218, 335, 25, 27, -152, -86, -326, -95, +-453, -146, 7, 9, 359, 292, 21, 285, +-179, -84, -161, -227, -401, -13, -179, -27, +292, -16, 211, 356, -107, 321, -341, -267, +-377, -402, -96, 97, 309, 364, 189, 160, +-282, -119, -253, -127, -162, 10, -278, -22, +96, 4, 310, 262, -56, 325, -212, -88, +-131, -375, -201, -165, -236, 66, 28, 294, +59, 325, -38, -12, 32, -238, -175, -153, +-224, 111, 101, 145, -53, 62, -221, 140, +-41, 5, -146, -182, -199, -216, 41, -18, +170, 350, 20, 391, -207, 38, -215, -264, +-71, -162, -97, -56, -106, -88, -68, 175, +-12, 249, 86, 94, -129, -89, -155, -104, +7, 186, -125, 105, -37, -33, -81, -103, +-179, -174, -26, -15, -215, -82, -89, 223, +293, 563, -22, 163, -135, -184, -88, -381, +-286, -274, -163, 30, -148, 142, -51, 280, +219, 165, 14, -31, 13, 7, 13, 72, +-500, 78, -278, -95, 108, -251, 29, -164, +102, 63, -134, 255, -209, 348, -2, 96, +-43, -205, -109, 32, -42, 101, 33, -173, +-56, -197, -288, -86, -218, 154, -131, 106, +174, 164, 442, 561, -141, 98, -440, -650, +-238, -554, -279, 133, 61, 516, 439, 157, +-2, 3, -309, 82, -224, -179, -136, -181, +-81, 117, -51, 174, 269, 74, 183, 24, +-427, -146, -444, -169, -42, 109, 113, 174, +184, 111, -103, 44, -296, -93, 17, -85, +2, 62, -114, 235, 50, -61, -10, -276, +-399, 83, -372, 45, 209, -37, 401, 243, +-68, 245, -192, 21, -234, -204, -265, -213, +38, -88, 78, 71, -143, 169, -88, 65, +92, 164, -124, 237, -158, -130, 153, -285, +-194, -91, -427, -33, 295, 82, 169, 387, +-454, 188, 59, -292, 23, -238, -425, 108, +131, 211, 176, -45, -110, -130, 56, 165, +-266, 204, -299, -96, 1, -338, -53, -11, +16, 422, 107, 107, 34, -155, -194, -1, +-280, -18, 20, -162, 35, 75, -179, 302, +-6, -24, -85, -152, -119, 0, 309, -45, +-90, 93, -503, 187, -63, 8, -14, -152, +79, -55, 295, 112, -169, 67, -330, -35, +-113, -14, -220, 138, -72, 94, 139, -252, +88, -72, 86, 318, 40, 103, -336, -152, +-344, -43, -4, 17, 8, -81, -121, 1, +-87, 248, 172, 147, 301, -141, -22, -111, +-435, -75, -426, -59, -49, 280, 117, 302, +-46, -221, 144, -288, 101, 60, -171, 81, +53, 5, -234, 189, -397, 214, 132, -83, +27, -320, -272, -115, 168, 180, 260, 148, +-178, 143, -96, 11, -135, -313, -491, -72, +118, 290, 404, 257, -301, 89, -163, -300, +131, -437, -117, 2, -10, 325, 159, 471, +-303, 288, -474, -399, 102, -632, 206, -30, +68, 521, 210, 272, -157, -189, -566, -1, +-251, 78, 202, -284, 181, -75, 67, 319, +80, 149, -246, -103, -357, -139, 74, 63, +-40, 160, -132, -224, 329, -53, -108, 335, +-463, -51, 265, -154, 62, 133, -311, -7, +170, -56, -180, 167, -318, 173, 206, -283, +47, -251, -27, 226, -49, 30, -141, -9, +49, 389, -160, 137, -178, -387, 41, -253, +-116, 266, 96, 60, 247, -386, -188, 101, +-281, 547, 11, 52, 34, -187, -220, 126, +-115, -163, 195, -462, 155, 72, -116, 383, +-213, 84, -40, -30, -127, 237, -65, 65, +318, -406, -69, -238, -470, 128, 104, 261, +228, 127, -214, -187, 17, 45, 103, 217, +-299, -197, -71, -111, 49, 279, -197, -43, +228, -349, 252, 93, -339, 326, -295, 53, +95, -69, 51, -74, -87, -101, 55, -97, +50, 72, -36, 299, -241, 146, -261, -143, +264, -223, 211, -122, -156, 79, -102, 122, +-193, 107, -92, 200, 77, 27, -4, -330, +178, -235, 141, 305, -182, 283, -377, -334, +-345, -219, 154, 366, 484, 263, 108, -176, +-130, -152, -95, 91, -485, -12, -154, -148, +436, -77, -44, 12, -108, 236, 247, 329, +-191, 149, -215, -170, 232, -489, -117, -387, +-333, 86, 132, 430, 92, 400, -161, 249, +295, -18, 211, -481, -422, -354, -305, -88, +46, -135, -47, 338, -15, 736, 389, 185, +224, -462, -398, -429, -215, -9, 155, 162, +-326, -12, -132, -127, 472, 229, -69, 195, +-151, -126, 251, 134, -139, 115, -141, -251, +43, -345, -210, -152, -98, 265, -8, 380, +153, 232, 401, -134, -9, -264, -399, -45, +-225, -253, 2, -35, -29, 631, 130, 207, +299, -617, 6, -363, -279, 528, -208, 305, +-49, -390, 179, 4, 218, 437, -165, -193, +-170, -792, 149, 52, -27, 975, -136, 197, +143, -674, -121, -170, -193, 428, 173, -195, +78, -489, 92, 505, 96, 536, -368, -370, +-177, -504, 212, 105, -55, 419, 52, -54, +259, -272, -170, 128, -226, 215, 18, -118, +103, -281, 171, 147, -213, 205, -257, -232, +377, -169, 76, 330, -373, 419, 16, -415, +209, -632, -92, 489, -143, 492, 402, -692, +156, -303, -629, 1019, -175, 208, 424, -1151, +-153, 36, -198, 927, 595, -399, 219, -776, +-571, 699, -172, 743, -43, -855, 16, -563, +327, 800, 8, 215, 26, -510, 4, 19, +-363, 288, -41, -189, 261, -371, 207, 177, +111, 554, -356, 77, -453, -529, 299, -350, +371, 389, -158, 246, 79, -417, 116, -40, +-270, 549, -130, -6, 101, -614, 122, 23, +-30, 534, -50, -206, 153, -546, 87, 252, +-301, 597, -58, -167, 497, -548, -85, 113, +-551, 431, 197, -202, 318, -552, -186, 199, +-19, 642, 240, -160, 23, -344, -239, 251, +-134, -29, 67, -546, 246, -209, 64, 640, +-196, 492, 87, -350, 83, -156, -288, 143, +-44, -475, 370, -440, 249, 492, -249, 531, +-328, -142, 190, 46, 142, -22, -147, -701, +91, -37, 27, 712, -11, -212, 135, -540, +-27, 676, 74, 504, 33, -911, -396, -505, +-148, 658, 408, 351, 227, -385, -73, -214, +22, 330, -27, 27, -160, -430, 35, 116, +189, 480, -37, -205, -342, -664, 132, 88, +579, 801, -207, 15, -372, -713, 479, -80, +168, 391, -598, -100, -7, -219, 375, 254, +-192, 125, 188, -397, 505, -55, -423, 475, +-409, -132, 441, -643, 141, 409, -391, 599, +148, -892, 627, -460, -207, 1085, -721, 279, +248, -897, 575, -221, -157, 697, -190, 164, +102, -859, 138, -366, 194, 813, -251, 659, +-248, -521, 427, -911, -8, 269, -303, 926, +317, -342, 178, -894, 20, 352, 84, 689, +-286, -438, -109, -554, 179, 457, -55, 470, +151, -346, 442, -329, -90, 92, -376, -149, +240, -143, 182, 319, -348, 188, -37, -219, +350, -133, 178, 254, -117, 26, -77, -620, +216, -189, 133, 532, -146, 262, -287, -243, +71, -214, 567, 238, -70, 61, -412, -469, +507, -65, 170, 257, -613, -23, 211, -63, +439, 133, -301, 60, 85, -157, 468, -185, +-348, 11, -380, 5, 364, -289, 348, 154, +42, 784, 1, -335, -104, -962, -55, 427, +56, 503, 32, -613, 45, -205, 211, 760, +213, 66, -91, -848, -260, -105, 96, 529, +453, 40, 48, -98, -293, 52, 44, -187, +138, -363, -120, -102, 64, 269, 483, 295, +299, 120, -308, -25, -374, -329, 162, -459, +221, -103, -162, 250, 359, 320, 529, 74, +-554, -217, -351, -9, 705, 37, 265, -222, +-472, -191, -55, -10, 509, 186, 22, 99, +-464, -172, 154, -103, 776, 91, 162, 160, +-651, 14, -243, -379, 461, -242, 248, 178, +-108, 102, 106, 31, 299, 174, 111, -215, +-193, -380, -281, 210, 150, 241, 491, -346, +-11, -124, -198, 394, 330, -169, 406, -454, +-334, 387, -413, 294, 457, -695, 408, -183, +-274, 825, -147, 6, 318, -955, 415, 12, +101, 936, -204, -111, -148, -978, 84, 79, +72, 683, -10, -161, 392, -361, 340, 81, +-49, 180, 51, 50, -104, -321, -266, -345, +196, 214, 316, 318, 99, -228, 115, -287, +212, 266, 198, 226, 67, -271, -367, -216, +-295, -67, 364, -149, 542, 161, 212, 382, +-171, -223, 76, -524, 392, 155, -325, 546, +-460, -211, 625, -725, 627, 31, -316, 717, +-219, 39, 449, -704, 331, -148, -283, 464, +-179, -81, 367, -358, 277, 181, -127, 355, +211, -134, 352, -498, -53, -117, -244, 176, +-15, -47, 323, 110, 205, 160, 100, -290, +358, -248, 270, 374, -326, 322, -547, -577, +240, -633, 967, 376, -18, 476, -488, -311, +401, -293, 494, 361, -261, 355, -180, -316, +457, -578, 333, -237, -327, 329, -131, 371, +295, -251, 235, -277, 370, 318, 351, 83, +-157, -334, -192, -71, 22, -23, -26, -103, +322, 88, 319, -3, 18, -368, 361, 80, +324, 662, -356, 22, -344, -762, 415, -456, +462, 260, -55, 555, 120, 65, 202, -569, +-37, -162, 146, 395, 225, -148, 77, -446, +3, 328, 228, 415, 66, -406, -90, -428, +485, 300, 283, 102, -308, -394, 11, 24, +220, 50, 304, -41, 365, 357, -3, -44, +-70, -507, 104, -82, -123, 209, 46, -61, +589, -295, 242, -67, 111, 268, 287, 318, +-201, -55, -282, -410, 129, -140, 369, 6, +364, -181, 31, -159, 160, 224, 453, 429, +127, -44, -424, -372, -294, -221, 477, 43, +552, 60, 9, -223, 71, -76, 436, 293, +104, 103, -420, -274, 88, -232, 576, 203, +38, 92, -147, -312, 370, -78, 424, 190, +-97, -25, -132, -342, 289, -40, 244, 468, +-49, -4, 130, -517, 323, -1, 141, 209, +153, -304, 165, 20, -265, 476, 39, -341, +588, -559, 77, 364, -49, 290, 535, -471, +274, -59, -381, 585, -93, -191, 339, -814, +123, 80, 183, 534, 332, -116, 196, -145, +232, 187, 100, -113, -132, -261, -133, -141, +-65, -178, 487, 255, 666, 452, 13, -216, +22, -485, 271, 43, -215, 268, -234, -232, +365, -444, 288, 220, 341, 455, 560, -104, +-154, -211, -536, -50, 347, -224, 726, -172, +-290, 145, -462, 65, 813, -164, 815, 151, +-379, 394, -329, -134, 417, -678, 273, -424, +-187, 240, 50, 504, 461, 121, 438, -212, +78, 0, -238, -27, 149, -508, 326, -263, +-70, 452, 112, 163, 464, -249, 125, 132, +-245, 176, 370, -348, 507, -198, -299, 132, +-95, -303, 593, -183, 152, 590, -269, 158, +250, -531, 533, 94, 46, 274, -66, -530, +254, -369, 40, 319, 9, 127, 294, 7, +274, 177, -98, -125, 172, -378, 542, -45, +-46, 239, -112, -162, 479, -340, 17, 242, +-457, 368, 307, -359, 711, -399, 194, 422, +149, 249, 224, -460, -457, -249, -239, 105, +766, -7, 382, -146, -301, 63, 422, 410, +608, 65, -475, -385, -309, -497, 588, -205, +422, 448, 48, 365, 61, -289, 125, -172, +63, 146, 31, -120, 296, -275, 243, 15, +42, 129, 236, 171, 186, -6, -150, -511, +16, -199, 546, 580, 357, 79, -201, -607, +-86, 52, 230, 480, 264, -235, 270, -386, +152, 68, 59, 73, 105, -119, 140, -25, +-61, 175, 38, 118, 469, -126, 446, -259, +45, -212, -159, 28, -63, 49, 234, -53, +351, 305, 88, 299, -42, -559, 430, -668, +491, 419, -245, 580, -245, -397, 333, -412, +251, 385, -91, 57, 230, -621, 510, 84, +123, 741, 162, -122, 169, -618, -476, 12, +-45, 71, 710, -340, 142, 76, -114, 572, +606, 66, 551, -490, -429, -232, -473, 106, +376, -26, 456, -160, 0, 111, 157, 387, +514, -153, 150, -714, -180, 27, -31, 707, +187, -2, 213, -520, 152, -50, 293, 183, +90, -205, -142, -245, 484, 254, 310, 311, +-305, -178, 186, -289, 298, 33, -151, 170, +105, -91, 583, -305, 271, -224, -102, 204, +99, 441, -8, -89, -101, -425, 274, 102, +515, 227, 372, -305, -124, -352, -214, 109, +186, 147, 328, -67, 130, 233, 62, 193, +272, -429, 247, -172, -62, 246, -42, -389, +228, -414, 339, 623, 99, 584, 43, -447, +133, -586, 135, 183, 191, 405, 162, -239, +134, -615, 97, 107, 115, 768, 262, 96, +0, -784, -101, -309, 298, 486, 410, 119, +226, -322, 171, 145, -85, 267, -280, -346, +236, -384, 426, 92, -42, 146, 373, 93, +657, 196, -365, -117, -472, -456, 571, -75, +581, 365, -284, 71, -195, -355, 526, -117, +336, 299, -174, 96, 200, -402, 509, -160, +8, 468, -204, 116, 54, -499, 59, -156, +293, 267, 594, 66, 45, -250, -152, -152, +327, 266, 173, 175, -124, -226, -46, -136, +238, 7, 430, -80, 170, -55, -8, 10, +332, 20, 194, 82, -241, 93, 56, -117, +232, -198, 12, 6, 412, 22, 576, -131, +-124, 8, -409, 153, 264, 9, 594, -123, +-103, -100, -102, -81, 493, 51, 206, 171, +-114, -46, 53, -213, 107, -56, 306, -35, +451, -78, -41, 191, -182, 230, 364, -166, +197, -323, -177, -6, 121, 181, 269, -68, +359, -175, 365, 93, -112, 85, -215, -117, +336, 26, 275, 167, -177, -159, 214, -340, +421, 53, -44, 215, 92, -144, 421, -106, +116, 299, -88, 173, 145, -421, 131, -414, +-81, 268, 185, 381, 463, -291, 244, -268, +7, 350, 36, 141, 199, -407, 149, -127, +-120, 296, 9, 32, 392, -357, 330, -61, +145, 324, 106, 15, 83, -168, 94, 48, +15, -88, 31, -159, 235, 47, 232, -2, +204, 14, 235, 195, 102, 21, -100, -294, +59, -203, 419, 99, 148, 116, -205, -12, +207, 37, 437, 67, 105, -72, -1, -223, +2, -158, 195, 96, 436, 218, 4, -55, +-213, -150, 397, 203, 359, 124, -280, -500, +36, -261, 548, 446, 237, 168, -29, -350, +-30, -73, 32, 270, 444, 186, 199, -85, +-295, -450, 167, -372, 439, 282, 148, 518, +95, -135, 129, -372, 95, 293, 72, 295, +29, -544, 117, -473, 222, 326, 257, 392, +239, -112, 35, -201, -57, 42, 111, 152, +253, 56, 208, -298, 47, -301, 76, 299, +187, 134, 82, -388, 144, 173, 172, 517, +123, -188, 287, -494, 64, -86, -244, 133, +148, 3, 549, 61, 136, 234, -242, -103, +359, -313, 488, 183, -384, 135, -205, -497, +579, -91, 198, 611, -58, 75, 386, -516, +249, -60, -33, 294, -204, -64, -86, -216, +510, 26, 364, 109, -48, 21, 242, -46, +105, -44, -121, -8, 137, -123, 132, -75, +137, 251, 305, 161, 117, -416, -105, -376, +218, 469, 429, 482, -23, -456, -291, -364, +191, 337, 400, -38, 46, -348, 107, 255, +262, 319, 92, -260, 14, -161, 26, 183, +52, -58, 186, -308, 206, -23, 164, 357, +126, 235, 72, -278, 55, -368, 142, 109, +144, 283, -4, -174, 172, -282, 264, 285, +-130, 287, 22, -344, 573, -238, 110, 322, +-357, 58, 201, -421, 408, -35, -79, 359, +-63, 9, 348, -159, 277, 103, -116, -10, +-69, -328, 291, -59, 262, 323, 81, -25, +58, -218, -177, 202, 0, 80, 560, -297, +155, 52, -158, 236, 292, -169, 104, -333, +-171, 8, 29, 292, 251, 224, 346, -81, +-45, -287, -145, -107, 432, 153, 289, 22, +-209, -73, -100, 34, 48, -85, 155, -94, +364, 138, 238, 130, 60, -87, -11, -83, +-84, 45, 31, -58, 60, -212, 93, -2, +300, 186, 304, 3, 83, -58, -159, 119, +-29, 54, 297, -115, 47, -137, -216, -171, +146, -93, 412, 171, 195, 225, -42, 15, +40, -71, 191, 79, -124, -43, -291, -384, +246, -219, 489, 274, 161, 273, 57, -35, +-28, -47, -73, 58, 28, -60, 14, -226, +65, -150, 263, 125, 272, 209, 98, -84, +-74, -138, -33, 158, -18, 120, 47, -299, +201, -202, 126, 379, 80, 160, 155, -518, +43, -117, 47, 494, -45, -1, -155, -357, +168, 131, 281, 263, 191, -226, 60, -308, +-50, 75, 54, 251, -124, 83, -154, -194, +349, -139, 275, 84, 24, 89, 193, -5, +10, -36, -284, -123, -49, -45, 163, 53, +159, 3, 214, -7, 115, 71, 70, 59, +21, -69, -189, -216, -157, -182, 197, 200, +455, 362, 23, -32, -409, -347, 191, -142, +479, 84, -175, 67, -284, -17, 235, 66, +208, 228, -178, 41, -11, -466, 260, -420, +162, 276, -100, 479, -90, 69, 203, -209, +18, -163, -196, -57, 159, -58, 221, -4, +-41, 121, 55, 59, 144, -32, -158, -15, +-177, -39, 177, -82, 205, -49, 104, 118, +-37, 75, -69, -197, 118, -169, -132, 123, +-117, 330, 377, 117, 157, -384, -345, -406, +53, 123, 354, 306, -60, 34, -242, -3, +39, 139, 90, -128, 73, -420, 135, -60, +-21, 407, -153, 99, 158, -354, 194, 88, +-259, 315, -181, -233, 197, -263, 153, 282, +-16, 143, 11, -350, 86, -151, 88, 200, +-185, 32, -310, -5, 94, 224, 404, 133, +81, -188, -185, -447, -62, -219, 87, 174, +45, 251, -94, 227, -63, 185, 94, -84, +-11, -354, -81, -322, 116, -17, 217, 235, +32, 218, -207, -6, -197, -182, -135, -30, +33, 185, 378, 132, 236, -237, -104, -304, +-249, 70, -229, 100, 57, -16, 110, 146, +-83, 137, 99, -56, 255, -189, 23, -101, +-295, 87, -229, -51, 164, -125, 134, 75, +-205, 68, 22, 67, 288, 177, -113, -130, +-243, -401, 177, 58, 194, 411, -336, -81, +-318, -494, 190, -25, 206, 517, 147, 154, +58, -319, -308, -110, -172, 77, 6, -91, +-4, -72, 128, 101, 48, 103, -68, -63, +-66, -103, -17, -39, 26, 93, -97, 195, +-9, -74, 104, -208, -150, -44, -247, -100, +103, -70, 261, 269, 38, 289, -118, -40, +-282, -327, -165, -244, 202, 126, 76, 313, +-90, -43, -55, -344, -64, -12, 48, 264, +97, 79, -104, -73, -259, -14, -63, -7, +167, -170, 33, -135, -93, 125, -46, 50, +-9, -66, -12, 194, -93, 241, -35, -192, +28, -379, -148, -84, -117, 96, 164, 114, +54, 206, -132, 123, -54, -208, -141, -292, +-21, 19, 119, 212, -148, 130, -83, -55, +48, -266, -55, -108, -20, 242, -106, 122, +-25, -96, 121, 61, -97, 72, -172, -280, +-142, -295, -73, 256, 186, 373, 189, -108, +-152, -205, -296, 115, -79, 41, 79, -346, +-80, -42, -163, 459, 89, 34, 272, -388, +-111, 32, -328, 281, -86, -100, -90, -278, +-73, 128, 144, 278, 126, -163, -39, -275, +-157, 105, -173, 208, -118, -43, -37, -21, +44, 44, 40, -144, -91, -169, -80, 37, +130, 241, -40, 157, -313, -162, -127, -186, +19, -61, 40, 30, 57, 212, -37, 144, +-57, -170, -30, -252, -145, -6, -304, 132, +-22, 39, 259, 96, -22, 166, -189, -112, +48, -369, 120, -95, -307, 304, -554, 146, +223, -161, 533, -35, -224, 138, -345, 36, +187, -113, -4, -105, -502, -39, -97, -22, +402, 3, -3, 146, -269, 233, 53, -4, +69, -214, -258, -193, -314, -161, 9, 36, +204, 325, 83, 235, -105, -31, -143, -81, +-197, -211, -82, -306, 49, -64, -62, 290, +-17, 420, 39, 184, -159, -257, -160, -495, +-35, -268, 91, 280, 116, 506, -189, 137, +-369, -262, -108, -356, 177, -130, 104, 249, +-2, 379, -58, 24, -227, -331, -290, -271, +-12, 9, 256, 257, -26, 305, -256, 20, +47, -401, -94, -261, -230, 206, 179, 345, +45, 101, -328, -282, -76, -362, 177, 99, +13, 400, -310, 99, -265, -289, 199, -242, +276, 191, -210, 446, -287, -46, -23, -654, +-124, -332, -63, 524, 250, 699, -80, -24, +-394, -567, 31, -436, 285, 51, -127, 505, +-410, 268, -101, -312, 175, -248, 99, 181, +-88, 232, -292, -202, -129, -342, 256, 162, +-3, 456, -361, 16, -108, -413, 123, -182, +4, 250, -87, 220, -78, -78, -22, -190, +-210, -14, -208, 67, 266, 76, 170, 84, +-399, -27, -263, -70, 185, -87, 118, -34, +-329, 71, -229, 32, 242, 59, 110, 114, +-222, -63, -189, -173, 9, -46, -36, 125, +-153, -1, 0, -12, 6, 190, -104, -29, +-12, -312, -40, -124, -95, 230, -68, 295, +-47, 160, -177, -111, -88, -481, 158, -381, +-84, 267, -162, 663, 65, 164, -80, -465, +-153, -134, -49, 297, -57, -142, -142, -531, +-103, 11, 190, 798, 119, 490, -280, -646, +-211, -768, 28, 365, -241, 690, -206, -337, +408, -521, 352, 465, -457, 523, -601, -442, +103, -585, 376, 168, -228, 549, -309, 170, +188, -270, 92, -260, -161, -113, -174, 122, +-174, 320, -59, 99, 90, -234, -37, -104, +-152, 124, -37, -153, 66, -284, 28, 391, +-157, 711, -421, -65, -219, -982, 226, -562, +301, 726, 85, 821, -220, -128, -446, -522, +-294, -158, 149, 138, 260, 47, -109, 35, +-169, 102, 66, -16, -45, -80, -280, -66, +-194, 6, 71, 228, 106, 122, -34, -351, +-138, -298, -160, 320, -51, 436, -76, 48, +-122, -383, 155, -547, 124, 137, -326, 791, +-350, 228, 35, -693, 198, -434, -96, 485, +-199, 447, 133, -236, 42, -310, -370, -31, +-188, 118, 112, 130, 0, 123, -29, 33, +-113, -247, -219, -301, 79, 160, 288, 551, +-126, 262, -591, -472, -470, -825, 226, -116, +722, 989, 313, 887, -712, -469, -899, -1092, +47, -117, 695, 727, 261, 347, -477, -334, +-493, -364, 22, 33, 104, 324, 22, 389, +128, 106, -69, -544, -442, -600, -263, 151, +217, 687, 95, 343, -211, -345, -7, -527, +12, 23, -208, 630, 17, 217, -61, -529, +-305, -523, 76, 214, 55, 741, -324, 146, +0, -713, 234, -337, -19, 648, -209, 496, +-355, -474, -209, -613, 195, 121, 232, 660, +-195, 307, -487, -620, 67, -587, 671, 509, +-104, 706, -1011, -239, -385, -583, 466, 5, +517, 325, 40, 123, -507, -108, -378, -76, +-35, -142, 86, -57, 242, 522, -118, 426, +-544, -582, -183, -869, 336, 187, 341, 888, +-122, 242, -530, -235, -380, -182, 132, -471, +344, -191, -117, 606, -423, 465, 0, -441, +400, -329, -1, 552, -660, 222, -404, -833, +388, -464, 275, 744, -270, 701, -136, -226, +38, -383, -126, -54, -296, -81, -177, -115, +302, 177, 220, 459, -414, -146, -411, -559, +88, 117, 242, 661, -29, 146, -342, -737, +-153, -414, 144, 685, -34, 506, -247, -610, +-93, -605, 96, 575, -4, 900, -272, -282, +-106, -1010, 270, -76, -33, 882, -549, 185, +-361, -865, 417, -245, 637, 1012, -394, 689, +-928, -834, 48, -1202, 592, 284, -126, 1410, +-434, 273, 87, -1293, 150, -416, -214, 1087, +-459, 350, -102, -1099, 547, -319, 263, 1369, +-604, 677, -569, -1407, 72, -1128, 310, 891, +48, 1139, -117, -219, -93, -635, -68, 26, +-252, 273, -341, -224, 187, -295, 291, 315, +-184, 550, -159, -39, -81, -691, -173, -311, +-179, 480, 17, 513, 324, -61, -3, -312, +-620, -197, -324, -15, 421, 211, 422, 249, +-208, -216, -727, -365, -320, 171, 434, 442, +416, 215, -89, -268, -456, -446, -432, -142, +27, 220, 195, 300, 170, 109, 139, -101, +-346, -8, -608, 73, -138, -252, 508, -218, +406, 278, -393, 346, -604, -183, -166, -428, +381, 87, 459, 603, -352, 202, -800, -550, +-55, -600, 644, 177, 232, 798, -556, 121, +-302, -559, 267, -102, -319, 231, -323, -1, +520, -125, 207, 56, -437, 246, -230, 20, +-120, -344, -39, -133, 215, 350, -31, 265, +-328, -281, -156, -313, 216, 211, 165, 274, +-350, -43, -348, -79, 178, -64, 169, -108, +-161, 6, -281, 207, -160, 24, 281, -194, +177, 73, -378, 207, -190, 36, 65, -140, +-85, -172, -82, -160, -37, 80, -161, 361, +98, 173, 231, -189, -154, -55, -272, -14, +-208, -261, -201, -35, 63, 390, 214, 179, +120, -359, 91, -186, -335, 271, -617, 423, +18, -173, 535, -600, -51, 73, -439, 521, +80, -8, 108, -453, -185, -31, -37, 494, +-111, 204, -127, -301, 109, -198, -32, 118, +-165, 22, -88, -391, -154, -32, 221, 668, +303, 335, -382, -226, -675, -430, -13, -348, +778, 156, 233, 499, -791, 54, -487, -599, +359, -105, 487, 789, -106, 404, -651, -607, +-124, -600, 469, 120, 124, 331, -439, 36, +-506, -3, 256, 206, 577, 74, -105, -310, +-411, -86, -284, 188, -114, -47, 198, -176, +177, -18, -39, 225, -135, 218, -336, -125, +37, -112, 264, 89, 19, 1, -209, -142, +-598, -241, -76, 43, 796, 354, 184, 358, +-651, -71, -315, -442, 301, -226, 138, 303, +-450, 122, -188, -322, 418, 24, 89, 456, +-402, 202, 24, -426, 347, -348, -268, 346, +-569, 235, -42, -480, 391, -151, 344, 561, +-197, 356, -476, -275, -116, -487, 403, -114, +-39, 353, -560, 303, 22, -207, 438, -205, +44, 267, -304, 66, -239, -382, -91, -93, +102, 490, 274, 238, 38, -298, -530, -294, +-336, -114, 430, 148, 377, 326, -337, 135, +-334, -121, 46, -206, 76, -94, -13, -8, +-36, -32, -86, 227, -92, 327, 112, -127, +130, -418, -478, -47, -283, 257, 540, 17, +295, -92, -437, 170, -289, 183, 93, -186, +-109, -367, -54, 136, 227, 340, 127, -90, +-182, -283, -234, 109, -179, 320, 99, -42, +233, -138, -124, -40, -230, -115, -3, -132, +119, 121, 63, 270, -203, 138, -162, -52, +156, -62, -49, -275, -229, -255, 57, 383, +211, 304, 3, -309, -285, -262, -220, 365, +164, 420, 260, -307, -162, -549, -295, 141, +71, 457, 4, -127, -6, -416, 116, 152, +-81, 534, -220, 6, 95, -374, 98, -17, +-360, 63, -47, -357, 347, -135, -42, 621, +-122, 424, 1, -265, -308, -354, -136, -148, +389, 39, 237, 181, -396, 113, -361, -183, +165, -54, 253, 373, -3, 76, -210, -390, +-73, -75, 60, 213, -139, -81, -29, -276, +137, 290, -50, 630, -57, -365, 192, -869, +-276, 325, -362, 889, 419, -256, 87, -757, +-499, 174, 338, 492, 492, 35, -714, -283, +-601, -113, 526, 188, 478, 19, -41, -120, +-314, 47, -477, 199, 73, -64, 516, -330, +-30, 41, -370, 465, 2, -35, 215, -353, +-190, -97, -242, 139, 200, 205, 178, 65, +-27, -30, -261, -217, -125, -205, 325, 185, +-211, 237, -540, -29, 616, -104, 577, -16, +-597, 89, -610, -26, 103, -187, 594, 35, +7, 267, -638, -23, 77, -356, 592, -18, +-30, 618, -644, 189, -247, -835, 487, -389, +337, 844, -238, 333, -310, -654, -75, -181, +112, 525, 148, 113, -140, -500, -55, 58, +338, 575, -177, -168, -575, -822, 201, -58, +354, 1050, -149, 500, -83, -996, 123, -744, +7, 781, -219, 843, -125, -636, 108, -957, +198, 511, -185, 1035, -247, -394, 205, -944, +259, 236, 22, 958, -326, -118, -451, -838, +207, -104, 542, 674, -91, 242, -621, -630, +134, -336, 827, 610, -317, 672, -1016, -379, +221, -971, 808, -104, 33, 979, -523, 427, +-253, -819, 317, -492, 263, 860, -263, 386, +-340, -929, 200, -229, 258, 880, -19, 129, +-274, -755, -212, -137, 254, 496, 402, 146, +-273, -117, -496, -16, 169, -82, 253, -262, +-131, 115, 68, 471, 85, -140, -114, -467, +-93, 126, -128, 440, -77, -39, 156, -499, +237, -115, -2, 654, -409, 315, -44, -674, +601, -568, -218, 522, -780, 713, 288, -274, +576, -714, -194, 105, -87, 781, 25, -39, +-164, -854, -130, -144, 144, 743, 170, 505, +-134, -513, -145, -599, 38, 193, 89, 372, +87, 33, -65, -174, -146, 36, -68, 163, +77, -21, 189, -296, -152, -198, -371, 340, +239, 355, 423, -262, -268, -235, -274, 259, +290, 147, -31, -272, -502, -240, 172, 141, +488, 229, -118, 167, -255, -169, 0, -118, +-78, 74, 160, -97, 230, -21, -451, 124, +-269, -1, 528, 46, 297, 178, -506, -208, +-388, -531, 410, 338, 507, 749, -315, -291, +-619, -687, 135, 89, 692, 602, -116, -16, +-647, -523, 104, 14, 381, 265, -6, 0, +-112, 66, 22, 135, 67, -123, -161, -446, +-200, 45, -133, 480, 199, 101, 522, -441, +83, -339, -556, 566, -341, 682, 500, -264, +143, -994, -754, -398, 78, 913, 940, 667, +-99, -541, -741, -478, 73, 360, 557, 499, +-186, -354, -628, -688, 25, 151, 599, 722, +307, 118, -444, -713, -445, -299, 529, 819, +394, 499, -820, -608, -553, -842, 932, 162, +727, 989, -722, 189, -906, -1015, 557, -419, +1071, 1043, -494, 707, -1112, -905, 387, -955, +914, 645, -349, 988, -802, -405, 323, -1097, +904, 211, -63, 1142, -871, 207, -363, -940, +548, -620, 471, 599, -297, 802, -355, -389, +348, -1052, 439, 320, -472, 1484, -719, -193, +315, -1601, 724, -122, 6, 1326, -566, 465, +-89, -1031, 463, -581, 99, 770, -559, 516, +-285, -464, 526, -446, 565, 233, -357, 451, +-578, -167, 198, -405, 278, 54, -76, 362, +-173, 115, 39, -263, 303, -206, -73, -39, +-303, 257, -10, 331, 135, -323, 197, -389, +-48, 405, -211, 508, -106, -634, 73, -697, +298, 688, 116, 796, -351, -467, -312, -766, +174, 306, 397, 848, 40, -307, -224, -967, +-276, 146, 88, 863, 302, 81, -156, -616, +-64, 29, 118, 437, -50, -150, -50, -439, +98, 73, -19, 352, -211, -26, 70, -107, +211, 35, -165, -20, 25, 44, 277, 77, +-169, -101, -376, -188, 53, -60, 359, 212, +39, 270, -250, -107, -42, -230, 263, 50, +88, 118, -384, -96, -216, -162, 410, 135, +284, 198, -256, -28, -368, 11, 47, -228, +329, -391, 306, 400, -192, 851, -562, -248, +-17, -1206, 547, -95, 52, 1239, -391, 245, +60, -947, 327, -104, -95, 596, -352, -96, +5, -334, 277, 271, 118, 245, -235, -411, +-172, -393, 221, 502, 111, 698, -195, -429, +87, -962, 105, 132, -135, 1236, -129, 201, +-55, -1390, 168, -425, 279, 1195, -68, 556, +-260, -765, -178, -619, 92, 414, 251, 617, +143, -135, -219, -546, -205, -181, 154, 592, +96, 313, -117, -651, -107, -461, 244, 732, +261, 682, -371, -639, -422, -755, 231, 373, +542, 699, 33, -259, -541, -776, -123, 299, +422, 972, 17, -240, -380, -1041, 173, 47, +543, 1097, -218, 42, -672, -1201, -22, -193, +574, 1198, 235, 307, -285, -877, -202, -131, +57, 543, 186, -169, -56, -419, -345, 174, +174, 272, 434, 18, -230, 36, -464, -115, +357, -203, 553, 201, -508, 108, -655, -350, +471, -18, 696, 437, -316, 1, -634, -474, +109, 34, 594, 617, 140, -58, -575, -696, +-422, -39, 546, 636, 571, 130, -405, -499, +-574, -197, 160, 339, 440, 305, 92, -133, +-281, -484, -160, 65, 241, 649, 44, -53, +-341, -795, 81, -62, 301, 881, -39, 161, +-179, -821, -19, -203, 166, 828, 21, 264, +-170, -866, -25, -421, 34, 792, -13, 400, +76, -584, 127, -263, -34, 504, -73, 168, +12, -479, -78, -88, -186, 305, 11, -43, +337, -145, 202, 54, -195, 162, -214, 223, +-106, -146, 50, -580, 164, -84, 10, 786, +-51, 337, 5, -629, 81, -466, -34, 268, +-198, 411, 24, -43, 290, -160, -62, 137, +-312, -5, -2, -402, 185, -60, 210, 535, +128, 115, -370, -434, -322, -41, 211, 315, +302, 23, 60, -282, -234, -123, -196, 177, +260, 197, 192, -59, -236, -231, -177, 126, +126, 342, 179, -235, -121, -463, -230, 244, +207, 443, 255, -354, -203, -374, -129, 565, +53, 516, 14, -504, 4, -665, -195, 169, +-33, 476, 547, 30, 186, -109, -694, 63, +-376, -133, 587, -180, 399, 342, -469, 263, +-351, -576, 297, -435, 399, 618, 31, 612, +-462, -509, -318, -603, 427, 393, 308, 574, +-421, -203, -181, -553, 482, -43, 104, 313, +-458, 198, -91, 69, 294, -156, 39, -308, +-98, 56, -72, 309, -36, 57, 239, -246, +72, -77, -295, 136, -111, -18, 121, -65, +65, 53, 89, 114, 66, 85, -127, -30, +-148, -190, 16, -204, -13, 70, 36, 239, +171, 97, 49, -62, -113, -9, -38, 36, +-93, -254, -124, -182, 179, 298, 210, 307, +-206, -160, -89, -376, 265, 123, -99, 395, +-257, -81, 169, -350, 98, -59, -197, 285, +22, 82, 210, -235, 0, 1, -218, 246, +-56, 63, 180, -200, -8, -210, -164, 47, +53, 242, 117, 83, -23, -154, -61, -23, +-23, 98, -49, -85, -32, -119, 177, 96, +39, 255, -247, -46, 114, -415, 134, -89, +-389, 429, 97, 269, 603, -258, -249, -332, +-709, 164, 196, 227, 641, -204, -123, -215, +-453, 203, 89, 370, 368, 37, -87, -379, +-455, -429, -42, 100, 412, 655, 159, 269, +-116, -552, -151, -416, -123, 334, 37, 352, +83, -266, -95, -300, 75, 293, 216, 348, +-147, -227, -321, -369, 100, 154, 402, 370, +-30, -101, -477, -388, -72, -65, 436, 358, +84, 146, -308, -269, -27, -14, 259, 365, +-63, -27, -286, -530, 66, -245, 277, 393, +-94, 463, -259, -19, 37, -358, 277, -144, +111, 199, -213, 150, -364, -128, 68, -279, +494, -42, 84, 329, -551, 252, -194, -154, +587, -251, 277, 122, -584, 192, -430, -363, +417, -303, 500, 414, -136, 493, -446, -231, +-107, -428, 411, 199, 144, 195, -516, -270, +-180, -186, 525, 185, 412, 275, -334, -14, +-632, -152, 88, -60, 578, 49, -36, 81, +-484, -174, 91, -216, 510, 224, -80, 383, +-482, -66, -11, -365, 185, 22, 85, 251, +139, -93, -185, -292, -355, 25, 274, 343, +413, 112, -257, -160, -317, -105, 156, -85, +124, 26, -175, 108, -50, 35, 226, -53, +137, -67, -203, 90, -249, 33, 109, -122, +249, -12, -106, 175, -172, 79, 119, -286, +120, -97, -177, 281, -129, -5, 141, -145, +133, 161, -56, 92, -28, -323, -41, -62, +-200, 416, 10, -4, 308, -380, 66, 106, +-277, 303, -80, -184, 157, -325, -48, 188, +25, 254, 153, -9, -190, 42, -127, -138, +126, -308, -17, -16, -56, 299, 191, 235, +70, -149, -206, -196, -70, 86, 34, 96, +-119, -108, 48, -154, 246, 149, -24, 168, +-217, -120, 129, -43, 136, 111, -370, -72, +-239, -168, 406, 144, 433, 221, -253, -270, +-504, -196, 90, 438, 335, 163, 67, -584, +-257, -210, -202, 696, 390, 294, 273, -709, +-537, -387, -482, 544, 478, 489, 681, -365, +-282, -496, -532, 334, 95, 480, 230, -324, +-172, -641, -199, 78, 278, 788, 391, 314, +-189, -633, -452, -477, 100, 353, 310, 334, +-273, -217, -278, -233, 332, 182, 446, 326, +-167, -101, -568, -434, -2, 6, 487, 496, +92, 79, -416, -540, -220, -197, 356, 492, +279, 186, -225, -378, -149, -38, 105, 337, +-21, -23, -257, -383, 105, -90, 423, 450, +-19, 251, -489, -398, -229, -458, 349, 190, +400, 563, -78, 59, -273, -355, -92, -16, +-5, 69, -102, -283, 21, -151, 158, 358, +224, 356, 229, -84, -138, -155, -637, -102, +-380, -239, 589, -81, 543, 300, -309, 290, +-276, -99, 126, -229, 109, -2, -21, 78, +-138, 66, -64, -34, 34, -121, -26, -49, +-56, 0, 127, 47, 237, 224, 94, 221, +-228, -168, -348, -447, -65, -100, 192, 285, +83, 138, 39, -84, 163, 54, 21, 201, +-280, -40, -105, -261, 198, -181, -74, 12, +-215, 275, 162, 114, 304, -177, -136, 25, +-331, 153, 138, -79, 327, -228, -83, 60, +-373, 236, -143, -150, 294, -190, 212, 207, +-221, 160, -114, -87, 296, -68, 59, -3, +-295, -37, -205, -1, 40, 2, 348, -17, +66, 74, -419, 113, 47, -44, 541, -152, +-120, -55, -752, 92, 61, 70, 785, 46, +-27, -36, -679, -91, -14, 49, 535, 24, +109, -139, -402, -63, -288, 238, 266, 281, +476, -208, -286, -395, -658, 38, 305, 309, +768, 117, -198, -185, -731, -197, 86, 81, +507, 241, -156, -59, -318, -200, 211, 136, +321, 216, -169, -155, -388, -399, 68, -45, +338, 506, -31, 246, -286, -336, 39, -231, +263, 173, -23, 126, -272, -166, -101, -169, +312, 92, 168, 250, -335, 119, -161, -202, +242, -209, 110, 138, -197, 172, -37, -192, +208, -242, 6, 175, -199, 387, -95, 50, +134, -411, 177, -215, -169, 334, -251, 154, +268, -313, 254, -48, -264, 357, -130, -7, +148, -341, -109, 42, -85, 228, 180, -11, +19, -58, -86, -68, 158, -108, 31, 32, +-309, 91, -79, 49, 274, 120, 17, 57, +-226, -262, 49, -228, 290, 162, 46, 200, +-339, -1, -231, -47, 259, -79, 265, -14, +-232, 90, -189, 35, 179, -45, 194, 1, +-11, -75, -235, -151, -172, 92, 158, 241, +165, 26, -51, -152, -71, -78, 0, 37, +24, 33, 74, -6, -76, -16, -153, -50, +87, 56, 58, 137, -143, -47, 121, -171, +261, 10, -263, 238, -322, 72, 309, -289, +239, -216, -279, 103, -162, 318, 56, 156, +206, -268, 256, -236, -215, 226, -471, 220, +48, -297, 489, -261, 111, 406, -499, 322, +-135, -448, 462, -401, 113, 480, -331, 509, +-120, -428, 157, -586, 118, 264, -119, 599, +-176, -101, 108, -578, 245, 16, -17, 584, +-226, 8, -46, -626, 150, -4, -54, 652, +-165, 13, 157, -598, 186, -112, -56, 470, +-165, 228, -148, -295, 154, -286, 255, 128, +-135, 330, -275, -61, -53, -417, 238, 59, +250, 513, -81, 50, -274, -515, -107, -249, +204, 321, 81, 331, -189, -25, 85, -250, +212, -137, -225, 188, -226, 134, 248, -254, +212, -142, -176, 356, -140, 231, 35, -321, +54, -366, 41, 123, -33, 402, -67, 81, +121, -260, 106, -156, -206, 93, -161, 72, +185, -52, 146, 41, -79, 88, -102, -102, +-33, -65, 42, 83, 67, 4, 21, -48, +-47, 112, -32, 102, -32, -220, -44, -216, +67, 162, 99, 228, 10, 25, -78, -42, +-181, -92, -28, -161, 225, 31, 148, 220, +-101, 37, -152, -183, -60, -53, 21, 146, +78, -2, 57, -113, -55, 105, 22, 120, +102, -137, -126, -137, -161, 105, 133, 85, +121, -74, -77, -74, -131, 41, -23, 153, +219, 92, 102, -183, -237, -212, -97, 195, +228, 171, 43, -255, -362, -119, -64, 214, +493, 101, 61, -48, -372, 41, 106, 39, +179, -222, -272, -212, -157, 134, 169, 311, +162, 89, 10, -304, -28, -128, -6, 332, +-59, 96, -58, -317, -14, -114, -65, 231, +26, 10, 180, -210, 97, 139, -97, 317, +-133, -116, -3, -360, 55, 42, -54, 300, +-85, -71, 62, -338, 201, 24, 110, 491, +-220, 173, -261, -486, 162, -274, 194, 306, +-149, 193, -29, -279, 159, -90, -50, 363, +-123, 102, 58, -348, 92, -140, -23, 246, +-118, 116, -29, -220, 117, -69, 10, 228, +-66, 91, 53, -193, 84, -156, -9, 144, +-174, 216, -118, -90, 131, -324, 179, -15, +0, 434, -147, 160, -1, -403, 131, -218, +-89, 275, -132, 163, 31, -254, 65, -144, +85, 277, 83, 236, -66, -152, -110, -237, +18, 11, -118, 56, -114, -124, 348, 18, +264, 375, -322, 125, -308, -420, 204, -159, +209, 339, -186, 26, -146, -424, 130, -45, +269, 495, 61, 221, -435, -319, -252, -214, +437, 143, 342, 57, -368, -130, -368, 7, +285, 67, 325, -65, -119, 115, -276, 235, +14, -165, 261, -308, -64, 103, -272, 206, +42, -139, 275, -159, 124, 144, -181, 189, +-151, -15, 42, -128, -11, -31, -76, 33, +87, -50, 243, -15, -48, 50, -288, -7, +29, 42, 246, 168, -74, -54, -328, -358, +100, -3, 416, 453, -89, 45, -356, -471, +69, -107, 340, 440, -56, 194, -408, -356, +-29, -191, 385, 182, 178, 80, -269, -55, +-238, 74, 242, 89, 187, -134, -299, -188, +-229, 44, 284, 179, 414, 109, -155, -94, +-537, -196, 6, 29, 527, 211, 41, 71, +-518, -188, -19, -206, 572, 73, -31, 306, +-576, 103, 55, -300, 463, -185, 15, 233, +-283, 148, -199, -198, 115, -135, 292, 195, +-11, 178, -220, -87, 37, -80, 162, -23, +-163, -141, -230, -136, 167, 179, 279, 395, +-44, 41, -197, -263, -29, -148, 101, -81, +18, -87, -54, 126, -12, 334, 7, 9, +-96, -302, -38, 14, 258, 218, 210, 24, +-265, -197, -331, -184, 92, 102, 269, 143, +-26, -45, -226, -22, 114, 193, 366, 149, +-133, -243, -516, -325, 39, 20, 528, 248, +74, 131, -477, -146, -167, -118, 398, 182, +252, 207, -302, -159, -286, -338, 253, 1, +373, 280, -263, 156, -541, -169, 185, -216, +613, 114, -16, 186, -451, -74, -69, -143, +274, 52, 0, 126, -174, -48, 29, -89, +98, 47, 121, 8, -73, -113, -355, -71, +91, 128, 528, 294, 24, 112, -551, -335, +-229, -403, 368, 75, 289, 416, -77, 174, +-264, -267, -85, -300, 318, 173, 141, 456, +-387, -86, -223, -575, 322, -34, 226, 564, +-153, 110, -86, -534, -14, -203, 68, 477, +68, 310, -181, -304, -56, -297, 190, 154, +57, 199, -89, -178, -66, -154, 94, 202, +71, 154, -163, -147, -175, -172, 157, 94, +285, 224, -64, 24, -230, -213, -46, -193, +139, 24, 82, 215, -115, 154, -70, -110, +47, -177, 104, 83, 55, 188, -150, -82, +-80, -267, 72, 41, 63, 330, 29, -12, +-41, -355, -90, -56, -5, 345, 145, 176, +50, -229, -140, -160, -8, 118, 56, -40, +-84, -200, -25, 87, 171, 310, 81, 84, +-184, -222, -78, -147, 143, 38, 15, 20, +-140, 26, 30, 41, 173, -44, -47, -8, +-174, 116, 45, 47, 162, -128, -72, -36, +-190, 92, 183, -149, 178, -193, -260, 255, +-149, 377, 202, -146, 151, -334, -52, 85, +-134, 94, -59, -231, 91, -20, 91, 330, +-112, 102, -68, -258, 189, -33, 51, 231, +-232, -145, -88, -334, 255, 108, 155, 391, +-218, 42, -193, -322, 67, -69, 138, 235, +109, 87, -13, -186, -106, -203, -99, 119, +-47, 285, 55, -60, 138, -277, 58, 109, +-18, 322, -110, -219, -155, -428, 72, 176, +220, 467, -22, -30, -141, -404, -23, 27, +31, 297, 39, -105, 1, -231, -10, 81, +59, 181, -19, -60, -83, -94, 43, 132, +-4, 24, -76, -156, 55, -65, 165, 67, +-31, 98, -182, 29, 62, -40, 59, -66, +-184, 16, 75, 77, 206, -49, -119, -92, +-151, 71, 178, 107, 98, -50, -193, -93, +-53, 35, 92, 15, -64, -29, -29, 53, +151, 51, 127, -38, -95, -48, -185, 21, +-8, -19, 82, -127, -35, 49, 5, 307, +166, 77, -3, -387, -200, -251, -20, 286, +214, 314, 76, -143, -293, -282, -170, 66, +298, 285, 192, 16, -187, -344, -151, -194, +170, 335, 149, 361, -168, -249, -198, -394, +-22, 228, 194, 392, 219, -268, -101, -491, +-187, 199, 56, 571, 82, -93, -120, -497, +-101, 96, 196, 457, 160, -73, -207, -513, +-178, -101, 173, 392, 176, 187, -111, -112, +-172, -41, 59, 54, 167, -15, -54, -172, +-243, -174, 6, 85, 375, 328, 140, 132, +-385, -278, -219, -198, 287, 203, 162, 112, +-226, -220, -113, -39, 186, 250, 101, 21, +-88, -266, -23, -39, 93, 268, -13, 58, +-231, -252, -149, -89, 294, 225, 326, 191, +-217, -168, -293, -302, 179, 41, 190, 320, +-120, 72, -212, -313, -86, -98, 200, 331, +241, 143, -97, -305, -158, -166, 145, 231, +31, 93, -361, -184, -49, -8, 445, 170, +86, 10, -390, -157, -46, -62, 316, 137, +81, 197, -185, -56, -182, -358, 55, -75, +191, 347, -69, 121, -201, -264, 112, -85, +327, 320, 38, 150, -356, -304, -205, -285, +189, 84, 194, 242, -109, -17, -166, -100, +191, 147, 256, 116, -180, -103, -256, -165, +101, -84, 154, 5, -139, 93, -136, 190, +108, 31, 144, -200, 65, -88, 7, 164, +-78, 82, -109, -173, -86, -73, -38, 188, +105, 67, 132, -249, -35, -129, 22, 328, +135, 262, -85, -262, -229, -313, -56, 130, +83, 275, 50, -99, 46, -249, 109, 42, +46, 237, -82, 101, -56, -165, -32, -182, +-110, 85, -8, 160, 159, -70, 48, -168, +-45, 66, 36, 202, 17, -36, -68, -164, +-38, 59, 44, 143, -50, -92, -115, -249, +72, 16, 189, 314, 34, 152, -151, -189, +-14, -198, 133, 56, -118, 99, -164, -99, +93, -80, 116, 158, -2, 190, -24, -55, +2, -172, 26, -36, 43, 20, -29, -51, +-144, -4, -67, 118, 109, 101, 154, 21, +22, -66, -91, -181, -81, -84, 22, 137, +120, 137, -32, -10, -152, -82, -18, -41, +107, 30, 122, 94, -78, 1, -148, -159, +198, -33, 167, 116, -272, 40, -292, -7, +174, 2, 341, -29, -43, -41, -200, 22, +-12, 34, 62, -72, 56, -53, -12, 99, +-55, 125, -30, -29, 22, -159, 30, -76, +-7, 108, 54, 117, 40, -62, -87, -115, +-35, 43, 74, 119, -3, -6, -122, -114, +-24, -49, 181, 23, 149, 74, -133, 83, +-212, -55, 114, -134, 151, 36, -128, 153, +-88, -27, 58, -165, 54, 20, 20, 145, +26, -19, 23, -108, -23, 25, -46, 101, +-136, -24, -45, -127, 219, -37, 126, 99, +-99, 114, -57, -10, 36, -103, -13, 6, +-99, 91, -34, -114, 104, -213, 69, 112, +-80, 329, 5, 47, 128, -237, -40, -63, +-121, 110, -9, -97, 8, -191, 10, 73, +87, 312, 101, 163, -82, -232, -164, -295, +80, 84, 184, 256, -102, -98, -204, -281, +146, 98, 212, 338, -188, -6, -186, -236, +168, 29, 157, 100, -77, -177, -60, -155, +57, 225, -9, 274, -96, -94, -66, -213, +34, -10, 103, 59, 45, -7, 8, -3, +32, 30, -21, 16, -131, -35, -88, -7, +104, 111, 72, 40, -19, -243, 70, -173, +32, 271, -75, 271, -5, -197, 44, -223, +-139, 184, -179, 146, 136, -183, 216, -105, +9, 130, -6, 47, -24, -67, -130, 30, +-74, 49, 47, -40, 122, -20, 75, 25, +-114, 14, -111, -30, 158, -83, 98, -58, +-176, 59, -45, 181, 159, 69, -3, -126, +-162, -133, -1, 11, 173, 101, 53, -41, +-84, -169, -14, 61, 45, 293, -54, 45, +-88, -271, 32, -61, 54, 214, 21, -26, +19, -312, -13, -33, 16, 359, -7, 167, +-16, -191, 1, -118, -43, 60, 24, -42, +51, -141, 28, 74, 23, 225, -70, 22, +-38, -166, 18, -98, -9, 70, -21, 113, +8, -17, 106, -88, 61, -7, -84, 43, +-48, -57, 57, -32, -33, 89, -60, 39, +182, 18, 56, 47, -243, -140, -26, -261, +156, 109, -8, 395, -71, -4, 93, -331, +51, -13, -191, 263, -11, -10, 183, -275, +-23, -60, -70, 226, 60, 148, 43, -91, +-67, -103, -46, 54, 53, 63, -2, -60, +-126, -140, -75, -54, 182, 151, 188, 178, +-84, -6, -88, -76, 18, -27, -6, -90, +-43, -188, -13, 5, -2, 272, 43, 147, +215, -110, 48, -96, -252, 1, -126, -32, +62, -67, 125, 29, 5, 73, -128, -3, +52, -41, 174, 32, 55, 74, -61, 17, +-74, -66, -7, -114, -79, -73, -102, 84, +92, 164, 197, 31, 58, -136, -159, -68, +-127, 97, 125, 31, 153, -82, -116, 9, +-177, 77, 72, -7, 115, -119, 8, -78, +70, 84, 56, 172, -96, 45, -73, -145, +44, -55, -83, 89, -146, -110, 106, -218, +225, 152, 43, 389, -92, 1, -20, -290, +34, -62, -90, 87, -28, -81, 110, -99, +-44, 143, -92, 196, 134, -36, 150, -158, +-75, -60, -154, 81, -50, 109, 24, -53, +77, -197, 31, -42, -19, 231, 81, 177, +66, -118, -116, -164, -77, 27, 103, 76, +26, -62, -126, -78, -50, 43, 108, 139, +148, 78, -70, -116, -181, -121, 105, 32, +142, 31, -121, -13, -86, 52, 86, 55, +114, -74, 51, -53, -112, 83, -137, 14, +102, -95, 112, 46, -151, 127, -119, -116, +146, -217, 159, 111, -73, 320, -108, 11, +43, -303, 79, -96, 4, 203, -116, 53, +-15, -199, 220, -45, -11, 250, -240, 160, +67, -180, 210, -211, -112, 61, -212, 114, +112, -97, 155, -91, -89, 164, -28, 201, +97, -57, 28, -204, -10, -61, 9, 85, +-54, -1, -123, -60, 27, 52, 162, 155, +-4, 47, -123, -153, -2, -153, 95, 46, +10, 175, 3, 25, 15, -180, -89, -66, +-68, 161, 104, 43, 160, -124, 3, 64, +-70, 192, 14, -71, -131, -307, -176, -97, +129, 228, 218, 199, 22, -33, -130, -75, +-62, 22, 56, -30, 60, -142, 34, -37, +-51, 127, -53, 51, 96, -41, 108, 84, +-99, 80, -194, -164, 85, -208, 225, 104, +-92, 273, -285, -50, 44, -291, 395, 50, +74, 310, -336, -59, -60, -320, 232, 73, +31, 307, -229, -110, -8, -305, 325, 90, +30, 271, -308, -11, -66, -155, 173, -12, +51, 34, -138, -7, -60, -44, 184, -79, +157, 89, -149, 274, -132, 24, 209, -385, +100, -160, -266, 321, -137, 90, 205, -294, +173, 59, -170, 427, -204, -59, 213, -495, +291, -27, -151, 402, -342, 32, -18, -383, +262, -62, 204, 431, -52, 237, -207, -326, +-7, -381, 179, 108, -47, 343, -167, -21, +66, -255, 84, 30, -107, 235, -24, 7, +126, -181, 40, -32, -21, 75, 6, -27, +-20, -31, -2, 85, -3, 45, -39, -86, +29, -18, 99, 78, 28, -42, -135, -141, +-92, 50, 97, 226, 71, 0, -18, -208, +-44, -30, -48, 110, 90, -27, 142, -90, +-46, 86, -168, 128, 43, -23, 252, -74, +-30, -56, -347, -84, -125, 19, 297, 189, +258, 64, -187, -196, -272, -79, 115, 173, +276, 60, -46, -145, -271, -35, 100, 143, +358, 42, -104, -146, -461, -139, -22, 22, +448, 227, 176, 193, -336, -146, -237, -280, +211, 16, 200, 169, -181, -53, -166, -77, +237, 191, 292, 158, -139, -168, -359, -240, +-34, -19, 257, 127, 131, 145, -99, 74, +-154, -91, -12, -159, 111, 12, 53, 147, +-35, 4, -42, -142, -6, -1, 33, 133, +9, -20, 9, -129, 119, 40, 88, 132, +-135, -50, -197, -165, 4, 39, 126, 184, +56, -20, 17, -184, 27, 15, -26, 206, +-65, 11, -66, -205, -12, -81, 141, 98, +169, 91, -90, -2, -185, -45, 59, 4, +111, 111, -47, 12, -44, -266, 24, -143, +43, 294, -37, 243, -126, -194, 3, -175, +210, 162, 94, 66, -194, -219, -52, -73, +216, 176, -2, 100, -206, -19, -10, 4, +144, -23, 8, -97, -124, -53, -25, 8, +91, 54, 104, 146, 26, 80, -173, -193, +-131, -216, 170, 125, 170, 218, -71, -45, +-63, -94, 82, 62, 10, 4, -133, -136, +-96, -34, 45, 104, 102, 94, 44, 66, +15, 1, -10, -155, -111, -193, -74, 2, +142, 192, 193, 152, -31, 0, -141, -65, +-15, -35, -10, -70, -91, -118, 15, 10, +149, 167, 95, 84, -114, -72, -145, -36, +93, 72, 146, -52, -87, -165, -139, -6, +112, 133, 197, 81, -59, -1, -154, -8, +31, -3, 75, -34, -110, -101, -145, -106, +114, 103, 242, 257, -22, 13, -179, -270, +37, -94, 111, 160, -149, 40, -102, -64, +189, 80, 158, 65, 12, -123, -109, -66, +-190, 98, -63, -6, 98, -97, 139, 94, +16, 138, -44, -132, 32, -181, -50, 92, +-55, 152, 73, -72, 20, -94, -58, 96, +32, 93, 117, -24, 9, -41, -92, -61, +-52, -115, -20, -53, 3, 131, 15, 211, +38, 78, 47, -158, -47, -229, -65, -39, +52, 115, 118, 52, 16, 50, -63, 185, +5, 89, 2, -274, -24, -344, -47, 22, +-77, 258, 83, 112, 162, -19, -50, 45, +-204, 18, -16, -169, 199, -165, 42, 138, +-80, 309, 59, -16, 66, -387, -78, -161, +-101, 322, 27, 266, 52, -199, -66, -244, +-46, 154, 86, 222, 56, -132, -89, -265, +-42, 72, 108, 299, 83, 7, -36, -263, +-81, 0, 40, 219, 106, -121, -77, -304, +-125, 151, 25, 402, 73, -11, 8, -295, +-53, -32, 10, 132, 59, -130, -58, -198, +-41, 175, 62, 389, 62, 57, 59, -339, +0, -240, -60, 72, -19, 97, -30, -2, +-67, 116, 24, 202, 75, -45, -37, -258, +-14, -131, 57, 16, -61, 31, -54, 174, +157, 264, 113, -41, -150, -378, -133, -201, +144, 238, 135, 312, -104, -3, -104, -251, +4, -204, -19, 9, -36, 143, 66, 128, +135, 105, 55, 85, -102, -72, -168, -244, +14, -191, 208, 22, 101, 191, -119, 230, +-164, 81, 46, -177, 136, -264, -85, -92, +-137, 110, 107, 197, 183, 201, -5, 88, +-158, -157, -132, -282, -21, -111, 126, 80, +148, 107, 7, 122, -95, 95, -23, -107, +85, -235, -29, -44, -100, 176, 71, 187, +76, 134, -76, 25, -122, -212, -36, -308, +25, -68, -33, 162, 39, 123, 249, 34, +191, 50, -110, 49, -230, -31, -53, -81, +70, -14, -46, 74, -138, -22, -14, -165, +162, -32, 183, 215, 42, 133, -144, -149, +-212, -178, -31, -20, 184, 26, 194, 72, +67, 222, -65, 161, -97, -163, -145, -270, +-214, -81, 20, 23, 302, 36, 151, 129, +-117, 135, -94, -23, 29, -95, -13, -49, +-47, -28, 98, 26, 140, 112, -41, 31, +-180, -134, -104, -101, 41, 53, 57, 62, +67, -20, 130, -25, 11, 37, -191, 100, +-80, 85, 168, -38, 55, -125, -140, -89, +-7, -57, 99, -50, -18, 58, -83, 160, +6, 62, 63, -73, 68, -25, 65, 58, +-14, 35, -60, 2, -57, 0, -112, -71, +-49, -183, 65, -156, 77, 19, 32, 215, +49, 263, 97, 94, -12, -99, -166, -92, +-85, -13, 93, -91, 95, -155, -5, 38, +-33, 218, -115, 49, -131, -234, 102, -193, +152, 83, -41, 221, 1, 194, 193, 120, +80, -23, -221, -172, -221, -229, 21, -194, +115, -19, 73, 212, 23, 201, -25, -34, +-76, -108, -70, 26, 48, 84, 145, 51, +86, 29, -48, -21, -74, -122, -39, -170, +-112, -72, -51, 95, 141, 142, 100, 29, +-1, 6, 27, 141, -56, 64, -159, -242, +-24, -249, 175, 107, 111, 266, -45, 51, +-43, -195, -117, -219, -191, -21, 95, 218, +333, 231, 118, 59, -151, -27, -145, -89, +-65, -271, 10, -284, 58, 72, -11, 333, +-16, 153, 61, -64, 41, 1, -54, 73, +-54, -82, 105, -199, 157, -21, -44, 204, +-182, 108, -61, -209, 42, -276, -123, 2, +-71, 219, 363, 237, 280, 196, -358, 5, +-371, -284, 283, -309, 337, -24, -196, 148, +-240, 70, 91, 36, 184, 122, -49, 75, +-274, -147, -55, -188, 269, 93, 169, 243, +-99, -33, -88, -266, 19, -51, -153, 137, +-170, -66, 260, -82, 394, 311, -79, 363, +-411, -182, -127, -476, 157, -93, 44, 208, +-78, 4, 45, -105, 249, 130, 108, 144, +-268, -128, -247, -78, 90, 252, 233, 239, +31, -110, -171, -333, -65, -289, 73, -65, +-1, 167, -53, 169, 128, 67, 245, 151, +-88, 220, -409, -47, -110, -335, 304, -151, +152, 143, -205, -6, -129, -243, 174, -39, +143, 273, -100, 180, -74, -27, 141, 62, +69, 137, -217, -152, -233, -417, 45, -171, +225, 260, 145, 268, -6, -43, -157, -122, +-242, 87, -24, 139, 274, -35, 269, -76, +56, -23, -204, -136, -300, -226, -106, 25, +102, 332, 161, 245, 102, -71, -51, -208, +-174, -103, -64, 41, 142, 112, 97, 72, +-11, -94, 11, -174, -29, -38, -84, 109, +8, 84, 50, 36, -121, 106, -133, 64, +86, -206, 96, -294, -2, 55, -2, 360, +4, 162, 11, -166, -21, -127, -28, 15, +22, -60, 24, -134, -41, -30, -143, 102, +-78, 175, 97, 186, 128, 47, 87, -139, +22, -134, -139, -43, -194, -106, 16, -154, +149, 48, -15, 265, -108, 166, -30, -104, +50, -130, 167, 121, 166, 245, -149, -36, +-324, -400, -29, -313, 173, 89, 0, 243, +-96, 94, 7, 74, 61, 220, 24, 96, +62, -207, 93, -205, -80, -66, -224, -189, +-113, -248, 84, 142, 152, 495, 20, 319, +-101, -37, -17, -136, 109, -128, 113, -211, +-50, -192, -241, -18, -208, 90, -10, 58, +68, 80, 124, 183, 228, 175, 155, 13, +-73, -135, -258, -184, -209, -151, 50, -32, +119, 39, -103, -30, -131, -30, 117, 233, +157, 390, -52, 76, -132, -325, 36, -342, +137, -120, 35, 36, -81, 145, -138, 190, +-128, 65, -127, -77, -80, -6, 295, 130, +464, 89, -53, -77, -433, -225, -220, -264, +-27, -127, -78, 128, 61, 297, 312, 269, +185, 102, -106, -92, -104, -162, 26, -57, +-41, -43, -217, -202, -257, -236, -42, 6, +263, 310, 271, 386, -43, 189, -158, -112, +27, -301, 131, -224, -40, 46, -263, 157, +-249, -82, -38, -248, 175, 65, 236, 420, +119, 212, -13, -235, -117, -228, -158, 89, +-94, 126, -62, -117, -80, -238, -12, -88, +103, 127, 159, 195, 119, 176, -51, 137, +-187, -22, -60, -260, 62, -285, -119, -5, +-207, 213, 43, 108, 202, -114, 49, -123, +-63, 102, -17, 237, 5, 83, -1, -154, +-101, -146, -194, 26, -44, 21, 107, -126, +73, -59, 31, 160, 66, 139, 52, -60, +-71, -66, -211, 64, -182, 38, -1, -55, +87, -37, 1, -20, -46, -111, 51, -119, +188, 151, 140, 364, -147, 122, -279, -275, +-151, -248, -87, 45, -20, 40, 171, -134, +250, -19, 21, 215, -188, 141, -77, -64, +40, -32, -48, 61, -176, -13, -139, -102, +103, -66, 219, -54, 13, -134, -171, -68, +-34, 206, 151, 347, 41, 134, -162, -192, +-233, -253, -148, -35, 96, 111, 214, -20, +8, -184, -184, -40, -27, 251, 197, 246, +60, -61, -229, -231, -239, -76, 13, 112, +145, 85, 43, -47, -41, -82, -54, -46, +-64, 4, -64, 71, -62, 96, 5, 20, +75, -82, 38, -65, -28, 78, -48, 113, +-35, -101, -27, -250, 5, 7, -54, 315, +-200, 114, -126, -294, 80, -229, 126, 222, +96, 351, 100, -12, 21, -315, -194, -175, +-289, 162, -58, 193, 166, -97, -6, -205, +-274, 41, -55, 180, 330, -13, 234, -126, +-159, 85, -283, 208, -12, -22, 115, -210, +-149, -92, -251, 46, 20, -8, 220, -61, +89, 41, -100, 149, -67, 91, 21, -68, +-70, -85, -218, 29, -117, 11, 206, -104, +258, -47, -81, 115, -262, 127, -103, 1, +49, -116, -37, -138, -175, -29, -76, 100, +174, 92, 222, 52, -7, 67, -148, -10, +-54, -153, -92, -113, -174, 60, -15, 64, +22, -65, -150, -39, -74, 128, 230, 135, +265, -39, -25, -117, -249, -32, -185, 4, +27, -19, -25, -19, -276, -62, -127, -31, +324, 197, 338, 279, -94, -70, -310, -334, +-161, -77, -34, 196, -23, 23, 6, -209, +44, -65, 25, 171, -34, 142, -19, 46, +62, 64, 29, 11, -221, -136, -369, -145, +-72, -79, 252, -85, 146, 19, -48, 202, +36, 165, 140, 11, -76, 6, -302, 2, +-204, -104, -40, -111, -44, -55, -48, -122, +100, -98, 199, 167, 117, 293, 29, 97, +-54, -40, -185, 56, -265, 10, -291, -293, +-200, -367, 77, -20, 347, 233, 354, 85, +131, -34, -117, 226, -306, 434, -336, 99, +-137, -410, 9, -437, -27, -96, 7, -2, +96, -154, 113, -5, 149, 405, 93, 522, +-206, 271, -339, -99, -114, -460, -2, -571, +-75, -189, -46, 265, 51, 212, 188, -53, +221, 107, -78, 460, -350, 285, -171, -291, +32, -498, -87, -257, -72, -69, 175, 16, +151, 235, -87, 366, -128, 175, -80, -54, +-176, -75, -149, -70, 95, -198, 223, -256, +83, -70, -199, 162, -251, 186, 23, 55, +156, 76, -22, 240, -230, 114, -198, -317, +35, -479, 138, -95, 24, 313, -56, 185, +72, -171, 127, -52, -159, 430, -350, 389, +-187, -297, -18, -683, 35, -261, 149, 335, +253, 355, 40, -17, -253, -152, -215, 112, +-39, 334, -10, 76, -105, -423, -81, -487, +96, 18, 137, 397, -24, 174, -134, -131, +-13, 16, 49, 212, -216, -13, -316, -292, +7, -131, 278, 192, 190, 138, -76, -183, +-139, -215, -103, 162, -176, 379, -58, 81, +125, -269, -44, -231, -293, -31, -36, 1, +385, 21, 190, 154, -246, 186, -260, 51, +-60, -39, 3, -42, -91, -180, -137, -333, +23, -117, 191, 350, 98, 437, -125, 3, +-89, -290, 18, -77, -190, 179, -256, 21, +54, -270, 217, -214, 43, 76, -177, 195, +-125, 138, 128, 152, 172, 150, -127, -93, +-389, -373, -195, -315, 115, 6, 110, 187, +109, 175, 151, 176, -54, 108, -229, -48, +-154, -30, -49, 50, -73, -216, -127, -509, +-22, -150, 177, 459, 208, 431, -13, -37, +-253, -136, -143, 150, 146, 199, 14, -192, +-349, -548, -299, -376, 72, 156, 298, 440, +249, 305, 58, 112, -188, 87, -339, 28, +-178, -209, 67, -423, 25, -387, -192, -67, +-106, 288, 298, 404, 372, 278, -33, 104, +-348, 9, -317, -91, -141, -255, -81, -352, +-24, -289, 170, -31, 196, 319, 25, 430, +-38, 144, 30, -87, -51, 91, -300, 154, +-335, -272, -134, -606, 76, -292, 250, 311, +249, 492, 48, 173, -148, -133, -165, -55, +-88, 166, -144, 88, -208, -255, -83, -474, +128, -253, 238, 318, 132, 607, -79, 189, +-211, -331, -188, -198, -87, 221, 15, 128, +54, -330, -92, -423, -138, -17, 113, 365, +229, 375, 30, 146, -203, -91, -209, -214, +-94, -165, -113, -36, -96, -33, 52, -128, +176, -16, 238, 257, 83, 317, -218, 94, +-341, -145, -198, -215, 41, -161, 90, -89, +-35, -19, -102, 95, -7, 148, 158, 81, +153, 59, 17, 118, -146, 70, -320, -116, +-297, -276, -43, -293, 174, -81, 170, 255, +37, 345, 5, 89, 10, -102, -58, 39, +-156, 165, -208, -113, -115, -478, -24, -327, +5, 178, 127, 393, 258, 264, 157, 162, +-233, -4, -457, -339, -193, -369, 132, -2, +151, 154, 19, -23, -52, 8, -37, 271, +39, 250, 70, -70, -38, -232, -187, -97, +-255, -5, -156, -151, 83, -205, 290, 111, +248, 454, -103, 285, -399, -212, -240, -370, +139, -9, 272, 285, -24, 53, -405, -348, +-275, -310, 245, 165, 459, 514, 88, 277, +-368, -267, -301, -407, 33, -2, 47, 268, +-122, -6, -116, -317, 61, -132, 181, 313, +148, 420, 9, 51, -181, -347, -287, -279, +-174, 109, 49, 172, 126, -156, -13, -253, +-93, 144, 99, 457, 240, 151, -20, -343, +-331, -287, -283, 135, 30, 187, 166, -96, +-62, -133, -198, 39, 38, 49, 277, -4, +145, 92, -141, 151, -208, 17, -184, -117, +-189, -149, -67, -121, 136, -33, 220, 63, +79, 67, -79, 49, 2, 169, 41, 268, +-161, 13, -360, -420, -235, -490, 180, -56, +315, 386, 69, 394, -39, 71, -22, -173, +-72, -159, -196, -34, -199, 5, 48, -33, +141, 2, 6, 158, -52, 193, -43, -118, +-59, -459, -80, -273, 54, 398, 196, 750, +8, 258, -305, -568, -313, -830, -1, -258, +229, 502, 178, 725, 40, 337, -82, -223, +-162, -568, -155, -491, -64, 26, 63, 524, +64, 476, -61, -51, -80, -511, 74, -515, +155, 47, -6, 791, -153, 830, -124, -207, +-120, -1254, -160, -940, -37, 474, 251, 1293, +303, 601, -45, -612, -268, -854, -142, -52, +28, 611, 40, 366, -61, -311, -168, -606, +-72, -252, 205, 423, 194, 734, -179, 220, +-276, -564, 113, -632, 364, 92, 18, 602, +-462, 259, -450, -431, 34, -562, 481, 26, +456, 588, -29, 443, -521, -191, -524, -527, +24, -211, 536, 319, 375, 389, -214, -67, +-464, -479, -218, -303, 209, 284, 337, 602, +15, 236, -280, -466, -224, -636, -6, 4, +121, 636, 135, 349, 70, -403, -73, -440, +-120, 201, -85, 436, -118, -65, -33, -388, +171, -110, 90, 226, -176, 221, -165, 4, +137, -208, 281, -202, -38, 109, -403, 329, +-250, 35, 225, -333, 390, -174, -37, 276, +-472, 236, -263, -273, 331, -372, 545, 265, +-12, 695, -665, 72, -468, -877, 322, -734, +629, 486, 106, 1153, -509, 300, -458, -967, +193, -864, 626, 430, 170, 1041, -688, 135, +-722, -960, 227, -679, 963, 537, 453, 1036, +-671, 131, -884, -918, 11, -663, 771, 498, +467, 928, -439, 4, -744, -974, -147, -644, +529, 644, 507, 1149, -52, 123, -380, -1013, +-181, -693, 19, 461, -84, 694, -91, -180, +111, -637, 252, 26, 136, 736, -191, 415, +-312, -459, 2, -704, 307, -56, 37, 520, +-459, 232, -310, -370, 347, -271, 555, 367, +50, 464, -462, -106, -268, -432, 243, -133, +153, 184, -384, -11, -346, -278, 266, -24, +625, 504, 228, 457, -446, -175, -569, -531, +-80, -304, 379, 82, 284, 284, -170, 274, +-301, -46, -85, -381, 196, -242, 245, 309, +92, 566, -135, 172, -317, -455, -160, -598, +145, -38, 158, 524, -44, 259, -183, -511, +-48, -534, 254, 477, 344, 1128, 14, 355, +-427, -990, -501, -1180, -112, -56, 334, 837, +423, 507, 215, -204, -83, -103, -347, 343, +-413, 25, -156, -679, 384, -457, 620, 639, +163, 959, -596, -240, -793, -1451, -128, -755, +639, 1259, 702, 1875, 221, 100, -285, -1715, +-658, -1311, -723, 335, -114, 1005, 884, 484, +1162, 50, 83, -45, -1321, -343, -1330, -665, +337, -203, 1748, 733, 994, 825, -1070, -229, +-1800, -1057, -274, -486, 1420, 750, 1227, 1027, +-273, 17, -1129, -946, -636, -694, 310, 277, +673, 652, 301, 189, -267, -196, -439, -47, +-197, 71, 154, -165, 355, -210, 273, 162, +-98, 335, -470, -153, -359, -590, 193, -137, +515, 766, 169, 803, -398, -311, -459, -1144, +119, -487, 588, 833, 274, 919, -468, -323, +-620, -1016, -19, -113, 531, 927, 405, 511, +-125, -603, -393, -636, -189, 305, 105, 542, +229, -255, 114, -636, -197, 141, -367, 757, +-31, 106, 528, -703, 442, -189, -295, 823, +-741, 378, -253, -1026, 625, -988, 607, 682, +-353, 1420, -753, 111, 19, -1195, 787, -600, +347, 744, -657, 716, -652, -527, 312, -904, +705, 261, 28, 1086, -596, 213, -264, -892, +406, -492, 319, 474, -211, 339, -276, -301, +73, -156, 202, 337, -14, 121, -182, -335, +-39, -141, 52, 305, 15, 150, 112, -226, +173, -85, -63, 208, -393, -105, -265, -486, +272, 9, 413, 785, 5, 533, -279, -586, +-110, -1012, 197, 0, 118, 1112, -259, 662, +-348, -942, 136, -1321, 487, 306, 174, 1660, +-402, 648, -394, -1271, 210, -1227, 450, 553, +-98, 1315, -495, 19, -82, -1301, 535, -732, +370, 927, -401, 1419, -736, 32, -46, -1343, +802, -885, 582, 658, -456, 1098, -894, 38, +-81, -952, 784, -587, 487, 549, -454, 917, +-716, 90, 29, -787, 650, -567, 322, 276, +-367, 665, -467, 240, 57, -402, 376, -522, +91, -8, -312, 510, -251, 321, 156, -272, +357, -441, 150, 39, -233, 434, -402, 112, +-172, -466, 432, -317, 559, 491, -240, 708, +-832, -229, -282, -1011, 778, -356, 859, 863, +-298, 797, -1049, -408, -364, -791, 756, 125, +678, 650, -362, -46, -672, -638, 29, -134, +541, 505, 204, 257, -299, -180, -314, 34, +72, 91, 226, -477, -16, -475, -223, 658, +-101, 919, 207, -522, 333, -1307, 13, 205, +-337, 1610, -279, 371, 138, -1590, 292, -1023, +-39, 1174, -348, 1397, -146, -613, 363, -1440, +468, 118, -116, 1291, -638, 186, -179, -1057, +597, -334, 405, 987, -488, 481, -781, -988, +71, -921, 951, 636, 519, 1307, -622, 196, +-832, -1021, 160, -822, 748, 288, 35, 814, +-674, 176, -152, -513, 706, -297, 375, 347, +-725, 226, -774, -325, 559, -184, 1226, 505, +58, 436, -1353, -573, -982, -908, 686, 147, +1383, 1101, 257, 414, -939, -923, -610, -776, +429, 688, 453, 1168, -306, -274, -546, -1402, +132, -420, 678, 1190, 231, 837, -517, -829, +-466, -1078, 307, 554, 607, 1511, -79, 188, +-729, -1540, -378, -1167, 489, 780, 743, 1409, +36, -44, -682, -1149, -504, -240, 312, 1006, +719, 536, 209, -696, -536, -653, -588, 333, +-24, 434, 443, -448, 431, -622, 12, 421, +-336, 1111, -270, 318, 141, -950, 274, -909, +-84, 245, -323, 885, -37, 269, 305, -573, +243, -617, -167, 24, -259, 655, 38, 621, +247, -65, 76, -701, -239, -456, -329, 222, +25, 328, 428, -88, 371, -80, -131, 366, +-518, 185, -241, -480, 354, -420, 371, 545, +-104, 655, -330, -558, -58, -1105, 255, 239, +122, 1404, -161, 272, -54, -1325, 216, -624, +13, 1198, -350, 895, -178, -1075, 318, -1240, +397, 698, -84, 1439, -359, -169, -67, -1237, +299, -188, 120, 882, -363, 235, -275, -613, +308, -167, 438, 433, -13, 6, -349, -412, +-85, 189, 248, 655, 79, -164, -315, -891, +-220, -189, 322, 888, 472, 450, -92, -659, +-486, -588, -78, 417, 421, 626, 73, -167, +-485, -526, -112, 24, 636, 487, 391, 67, +-625, -610, -658, -473, 479, 491, 896, 1048, +-209, 211, -1034, -1139, -224, -1096, 962, 611, +673, 1618, -567, 230, -801, -1754, 218, -1247, +786, 1309, 107, 2164, -723, -125, -455, -2293, +424, -1176, 694, 1512, 137, 1850, -540, -449, +-464, -1954, 248, -561, 640, 1641, 63, 1439, +-735, -755, -483, -1773, 633, -252, 940, 1272, +-133, 753, -1009, -606, -343, -659, 774, 249, +658, 418, -440, -114, -777, -169, 6, 269, +733, 27, 495, -602, -286, -324, -628, 673, +-261, 683, 400, -374, 665, -693, 89, 205, +-717, 704, -633, -130, 482, -861, 1091, -243, +106, 742, -1142, 592, -705, -401, 871, -629, +1217, 200, -281, 792, -1435, 88, -451, -1001, +1287, -793, 1134, 688, -607, 1377, -1327, 137, +-101, -1369, 1086, -886, 574, 917, -614, 1358, +-660, -268, 178, -1487, 552, -515, 158, 1133, +-88, 1086, -54, -332, -272, -1058, -390, -407, +240, 498, 786, 631, 176, 223, -847, -314, +-534, -645, 817, -379, 1021, 578, -431, 1047, +-1315, -34, -188, -1339, 1166, -740, 657, 1163, +-716, 1411, -719, -554, 543, -1740, 798, -216, +-330, 1614, -809, 846, 106, -1240, 807, -1242, +190, 776, -706, 1477, -446, -198, 524, -1539, +794, -448, -3, 1222, -746, 988, -489, -639, +430, -1150, 721, 15, 27, 1038, -663, 449, +-277, -773, 670, -787, 669, 392, -425, 923, +-943, 15, -60, -772, 957, -365, 525, 470, +-588, 468, -625, -7, 379, -350, 752, -382, +-96, -43, -765, 565, -190, 557, 702, -449, +474, -987, -547, 47, -628, 1141, 445, 357, +957, -1009, 50, -578, -829, 871, -506, 649, +385, -842, 596, -777, 68, 795, -386, 999, +-186, -659, 284, -1263, 484, 316, 86, 1513, +-539, 395, -596, -1305, 278, -1192, 937, 413, +252, 1361, -898, 590, -568, -843, 861, -1090, +1134, 242, -499, 1284, -1510, 354, -251, -1326, +1440, -1138, 971, 803, -686, 1593, -1023, 140, +62, -1288, 765, -728, 368, 607, -267, 815, +-337, 44, -137, -563, 116, -572, 260, -93, +267, 604, 35, 767, -187, -65, -67, -919, +120, -478, 61, 709, -165, 831, -146, -441, +192, -1182, 383, -138, 255, 1223, -176, 839, +-422, -700, -165, -1105, 372, 124, 515, 1007, +-63, 291, -638, -909, -299, -824, 680, 516, +846, 1233, -152, 241, -898, -1202, -416, -830, +650, 937, 726, 1320, -178, -597, -753, -1801, +-103, -145, 819, 1885, 572, 954, -463, -1458, +-666, -1352, 68, 972, 467, 1585, 68, -558, +-145, -1759, 242, -71, 224, 1643, -393, 606, +-292, -1226, 602, -886, 690, 859, -460, 1054, +-1104, -368, -77, -1069, 1169, -222, 854, 661, +-554, 440, -1016, -164, 46, -358, 990, -39, +508, 362, -662, 354, -817, -307, 112, -718, +780, -109, 408, 662, -268, 305, -364, -369, +153, -39, 519, 467, 116, -79, -695, -745, +-670, -175, 466, 715, 1317, 370, 400, -471, +-1185, -456, -1195, 246, 736, 469, 1801, 141, +279, -256, -1794, -437, -1248, -192, 1179, 423, +1835, 483, -132, -277, -1571, -670, -461, 171, +1213, 885, 883, 148, -726, -918, -1072, -531, +244, 635, 1157, 698, 403, -386, -753, -790, +-625, 122, 430, 922, 757, 431, -37, -775, +-628, -955, -288, 213, 362, 1107, 564, 380, +280, -989, -248, -819, -526, 648, -69, 1142, +623, -103, 412, -1085, -539, -334, -719, 709, +367, 372, 1178, -442, 314, -264, -995, 320, +-814, 225, 524, -166, 1014, 29, 141, 153, +-801, -256, -544, -444, 509, 94, 936, 627, +192, 180, -750, -541, -724, -390, 344, 532, +966, 752, 283, -341, -767, -1226, -621, -234, +519, 1299, 965, 901, 68, -1073, -800, -1357, +-458, 717, 466, 1698, 656, -74, -35, -1779, +-459, -639, -197, 1271, 464, 999, 614, -649, +-49, -868, -774, 218, -434, 655, 640, -12, +841, -335, -154, -37, -809, 15, 9, -182, +909, -17, 377, 468, -785, 264, -712, -478, +448, -516, 858, 362, 1, 760, -566, -126, +-18, -962, 640, -361, 249, 804, -434, 817, +-453, -325, 84, -941, 436, -112, 260, 852, +-60, 478, -216, -689, 47, -811, 405, 293, +206, 865, -367, 112, -359, -586, 254, -184, +402, 462, -210, 131, -339, -594, 360, -399, +769, 566, 86, 774, -651, -293, -496, -972, +348, -9, 562, 1126, -94, 372, -536, -1217, +74, -884, 931, 966, 471, 1296, -782, -444, +-909, -1359, 431, -81, 1078, 1217, 48, 590, +-1043, -914, -330, -1146, 1067, 216, 944, 1485, +-574, 812, -1201, -1272, 54, -1826, 1239, 491, +567, 2407, -900, 717, -993, -2293, 391, -1815, +1256, 1360, 505, 2266, -728, -213, -892, -1942, +116, -630, 869, 1215, 521, 1054, -567, -293, +-874, -986, 124, -572, 1272, 377, 874, 886, +-875, 339, -1546, -726, 82, -712, 1675, 493, +839, 955, -1232, -129, -1366, -1157, 573, -472, +1859, 818, 526, 913, -1463, -97, -1303, -754, +656, -405, 1618, 354, 159, 545, -1463, -16, +-764, -585, 1335, -265, 1617, 538, -552, 428, +-1842, -427, -397, -571, 1575, 397, 1107, 777, +-837, -153, -1428, -863, 115, -295, 1531, 480, +1038, 500, -738, 148, -1562, -185, -385, -622, +1345, -509, 1278, 744, -512, 1273, -1513, -285, +-199, -1916, 1382, -552, 1042, 1941, -612, 1467, +-1145, -1334, -88, -1939, 768, 424, 387, 1776, +-288, 297, -156, -1189, 336, -516, 77, 589, +-371, 387, -21, -332, 701, -104, 367, 306, +-757, -73, -876, -481, 409, 37, 1292, 706, +435, 280, -863, -617, -906, -554, 279, 298, +991, 442, 420, -158, -638, -357, -840, 304, +188, 482, 1076, -231, 584, -683, -629, 4, +-934, 807, 64, 339, 921, -855, 483, -917, +-557, 454, -694, 1376, 285, 372, 1027, -1215, +354, -1033, -928, 670, -1000, 1277, 500, -114, +1497, -1301, 362, -367, -1398, 997, -1022, 638, +1046, -598, 1620, -568, -287, 465, -1664, 568, +-384, -334, 1431, -697, 1015, -87, -802, 453, +-1224, 310, 213, -20, 1206, -112, 475, -112, +-736, -2, -609, 188, 328, 66, 609, -400, +13, -535, -369, 146, -92, 826, 284, 602, +208, -323, -61, -911, -91, -474, 57, 589, +125, 896, -2, -72, -8, -1122, 54, -511, +28, 1032, 22, 1186, 133, -376, 73, -1362, +-142, -455, -185, 840, 221, 745, 481, -186, +126, -571, -446, -156, -422, 253, 251, 228, +648, 145, 235, 47, -511, -348, -643, -623, +168, 4, 954, 1047, 708, 629, -477, -1017, +-1145, -1212, -383, 783, 946, 1689, 1091, -310, +-273, -2018, -1104, -310, -226, 1896, 967, 903, +657, -1522, -414, -1222, -640, 1043, -17, 1374, +417, -436, 240, -1333, -4, -154, -57, 934, +-98, 497, -78, -537, 193, -569, 384, 246, +69, 723, -473, 80, -373, -733, 258, -456, +732, 507, 341, 578, -529, -417, -719, -639, +112, 467, 908, 986, 532, -235, -547, -1256, +-878, -191, 1, 1225, 863, 392, 604, -1280, +-240, -675, -639, 1392, -291, 1266, 363, -1032, +701, -1612, 199, 344, -643, 1499, -609, 116, +441, -1249, 908, -601, 1, 789, -811, 1043, +-193, 207, 758, -842, 414, -1066, -604, 16, +-567, 1272, 440, 704, 752, -1112, -22, -1261, +-545, 724, -124, 1698, 432, 68, 176, -1599, +-222, -839, -154, 934, 153, 1038, 160, -301, +12, -943, 80, -105, 226, 706, 26, 470, +-333, -260, -322, -453, 237, -235, 565, 26, +132, 275, -479, 354, -250, -91, 439, -453, +652, 44, -122, 632, -883, -18, -431, -950, +817, -233, 995, 1205, -293, 654, -1109, -1339, +-80, -1263, 1090, 1193, 567, 2033, -771, -454, +-754, -2495, 441, -721, 710, 2188, -196, 1778, +-543, -1355, 280, -2344, 661, 221, 4, 2508, +-615, 1039, -231, -1910, 389, -2100, 303, 692, +-180, 2242, -159, 488, 267, -1725, 333, -1131, +-40, 1077, -288, 1500, -181, -326, 95, -1583, +172, -552, 133, 1145, 72, 1129, -7, -457, +-30, -1283, -51, -230, 141, 1199, 157, 938, +-70, -601, -259, -1314, -59, -323, 163, 884, +185, 853, 176, -109, 250, -698, -81, -422, +-488, 303, -329, 656, 543, 212, 678, -604, +-203, -733, -878, 158, -114, 844, 931, 359, +709, -673, -466, -549, -865, 439, -38, 735, +717, -226, 336, -728, -430, -91, -452, 539, +274, 32, 578, -429, 135, 104, -348, 606, +-115, 76, 257, -551, -26, -177, -523, 203, +-185, -150, 721, -216, 917, 564, -216, 627, +-1172, -595, -495, -1099, 1062, 368, 1215, 1465, +-444, 171, -1620, -1644, -497, -998, 1448, 1289, +1479, 1607, -429, -443, -1641, -1706, -492, -287, +1271, 1359, 1078, 769, -535, -894, -1338, -951, +-187, 366, 1201, 872, 932, -49, -562, -643, +-1006, -52, 81, 653, 847, 179, 185, -754, +-614, -557, -376, 709, 302, 927, 502, -456, +281, -1217, -46, 192, -338, 1438, -483, 213, +44, -1571, 684, -753, 379, 1428, -587, 1285, +-710, -965, 428, -1561, 1087, 344, 209, 1558, +-945, 221, -744, -1329, 450, -730, 881, 995, +64, 1192, -785, -465, -397, -1552, 839, -277, +971, 1655, -357, 1235, -1357, -1361, -394, -2163, +1213, 363, 1104, 2642, -575, 1054, -1383, -2124, +-115, -2169, 1339, 828, 1036, 2393, -658, 575, +-1486, -1811, -318, -1609, 1259, 590, 1225, 1971, +-476, 936, -1596, -1343, -478, -2005, 1496, -40, +1613, 2112, -577, 1410, -2103, -1332, -709, -2224, +1746, -40, 1755, 2137, -760, 1436, -2087, -1090, +-308, -2042, 2041, -291, 1396, 1753, -1248, 1308, +-2095, -1124, 129, -1907, 2094, 240, 1019, 2110, +-1443, 835, -1654, -1681, 510, -1444, 1987, 850, +720, 1515, -1509, -268, -1751, -1467, 365, -316, +1998, 1230, 1042, 1046, -1191, -407, -1799, -1286, +16, -586, 1848, 824, 1241, 1120, -1065, -154, +-2008, -1294, -176, -526, 1914, 1062, 1430, 1111, +-858, -228, -1857, -1015, -302, -493, 1585, 137, +1155, 334, -772, 508, -1391, 378, -23, -411, +1151, -905, 581, -22, -542, 1117, -616, 501, +112, -1059, 542, -1010, 173, 695, -242, 1327, +-308, -120, -90, -1297, 230, -435, 377, 903, +139, 854, -165, -340, -189, -813, -32, -236, +12, 535, 31, 341, 123, -322, 122, -401, +-21, 363, -89, 695, 130, -109, 229, -904, +-92, -535, -440, 580, -92, 914, 471, 144, +424, -835, -219, -717, -460, 446, 35, 1126, +447, 46, 180, -1347, -235, -692, -263, 1271, +43, 1350, 141, -875, 113, -1834, 213, 191, +87, 2055, -252, 757, -354, -1790, 84, -1743, +534, 834, 210, 2230, -365, 570, -441, -1909, +223, -1725, 542, 920, 93, 2302, -490, 290, +-231, -2345, 433, -1461, 494, 1806, -255, 2467, +-664, -675, -105, -2853, 603, -758, 584, 2295, +-20, 1797, -538, -974, -514, -1982, 83, -381, +647, 1207, 505, 1237, -350, 140, -770, -1196, +-48, -1360, 885, 265, 563, 1900, -624, 966, +-870, -1573, 159, -1911, 940, 624, 385, 2260, +-713, 570, -694, -1879, 374, -1547, 1019, 929, +154, 1890, -979, 241, -640, -1619, 701, -1157, +998, 787, -234, 1537, -1048, 307, -222, -1282, +1003, -1045, 706, 491, -474, 1282, -919, 266, +-62, -1050, 641, -837, 521, 478, -146, 1094, +-551, 287, -264, -754, 442, -799, 662, 30, +35, 638, -693, 548, -534, -85, 340, -551, +749, -514, 217, 104, -528, 753, -493, 536, +246, -401, 763, -950, 302, -161, -673, 813, +-1010, 533, 75, -614, 1346, -771, 980, 359, +-765, 1157, -1629, 268, -179, -1125, 1686, -1112, +1221, 442, -1032, 1449, -1977, 343, -70, -1243, +1971, -942, 1299, 945, -981, 1448, -1760, -358, +-152, -1605, 1420, -466, 964, 1276, -569, 914, +-1160, -697, -322, -1043, 829, 158, 972, 950, +80, 405, -860, -499, -680, -526, 255, -118, +794, 82, 272, 43, -475, 292, -470, 550, +237, 72, 571, -862, 143, -791, -428, 543, +-402, 1378, 165, 171, 562, -1489, 143, -1109, +-512, 837, -386, 1695, 478, 300, 695, -1222, +-104, -1153, -766, 106, -268, 1045, 551, 890, +495, -209, -322, -1210, -436, -922, 189, 734, +521, 1642, 171, 502, -390, -1376, -491, -1547, +-98, 156, 586, 1451, 639, 999, -178, -409, +-842, -1104, -299, -634, 777, 335, 767, 891, +-360, 533, -928, -346, -87, -769, 753, -374, +430, 248, -277, 522, -383, 415, -107, 68, +237, -550, 401, -753, 193, -23, -449, 988, +-622, 821, 159, -597, 938, -1358, 344, -239, +-729, 1392, -592, 1238, 419, -801, 591, -1909, +-107, -411, -353, 1844, 114, 1603, 146, -908, +-300, -2157, -258, -307, 534, 1868, 815, 1260, +-214, -1168, -1015, -1645, -420, 307, 671, 1527, +761, 357, -33, -1113, -633, -554, -266, 687, +320, 623, 442, -487, 38, -696, -365, 154, +-200, 698, 118, 223, 187, -455, -54, -411, +-75, 192, 295, 524, 231, -4, -252, -603, +-402, -375, 145, 585, 308, 701, -159, -310, +-276, -900, 345, 4, 591, 1073, -258, 454, +-757, -1035, 54, -1128, 830, 488, 248, 1420, +-744, 330, -523, -1160, 419, -754, 741, 721, +162, 955, -446, -429, -401, -1079, 73, -56, +316, 1073, 170, 474, -177, -700, -178, -687, +57, 397, 325, 661, 118, -147, -208, -563, +-171, 68, 42, 369, 205, -275, -3, -478, +-261, 507, -163, 1046, 392, -181, 608, -1373, +-58, -612, -894, 1069, -586, 1090, 744, -426, +1116, -1105, -152, -158, -1374, 833, -498, 571, +1236, -249, 1267, -596, -686, -414, -1630, -10, +-140, 577, 1558, 824, 893, 6, -1140, -1187, +-1381, -1089, 489, 805, 1670, 1905, 514, 589, +-1401, -1867, -1401, -2087, 469, 351, 1800, 2486, +751, 1675, -1356, -1138, -1692, -2518, 368, -935, +2003, 1608, 963, 2031, -1332, 165, -1816, -1555, +17, -1322, 1787, 128, 1220, 1112, -778, 1069, +-1680, 86, -495, -1012, 1474, -1300, 1461, -41, +-465, 1352, -1865, 1171, -669, -430, 1555, -1344, +1541, -548, -647, 636, -1840, 893, -325, 192, +1575, -457, 1144, -676, -876, -188, -1442, 396, +72, 671, 1187, 136, 485, -413, -735, -417, +-623, -96, 403, 100, 666, 176, -139, 386, +-639, 195, -210, -411, 525, -654, 344, 58, +-284, 732, -394, 464, 299, -310, 526, -638, +-228, -432, -865, 7, -138, 720, 1042, 1019, +889, 79, -645, -1405, -1481, -1266, -458, 608, +1398, 1791, 1689, 611, -53, -1224, -1948, -1351, +-1714, 85, 601, 1157, 2548, 829, 1561, -207, +-1403, -842, -2871, -676, -794, 28, 2382, 639, +2561, 739, -380, 239, -2778, -609, -1610, -1068, +1404, -384, 2496, 1054, 509, 1466, -1714, -73, +-1619, -1747, 199, -1275, 1391, 898, 838, 1920, +-372, 609, -864, -1324, -543, -1595, 153, -123, +748, 1450, 790, 1408, -51, -282, -1203, -1866, +-1098, -1261, 528, 1159, 1819, 2371, 823, 514, +-1456, -2286, -1974, -2203, 204, 838, 2193, 2856, +1242, 1110, -1397, -1997, -2052, -2429, 42, 157, +1865, 2256, 1040, 1543, -862, -640, -1307, -1835, +-120, -1182, 831, 372, 592, 1576, -162, 1411, +-454, -181, -265, -1686, 114, -1528, 349, 333, +299, 1695, -65, 1277, -448, -434, -229, -1500, +263, -1048, 371, 388, 34, 1287, -321, 890, +-220, -368, 116, -1014, 445, -477, 397, 296, +-367, 355, -950, -52, -350, 121, 1097, 540, +1211, 196, -481, -869, -1727, -1036, -533, 189, +1553, 1495, 1479, 990, -657, -882, -1918, -1831, +-461, -533, 1515, 1692, 1170, 1835, -772, -428, +-1341, -2363, 186, -1085, 1346, 1718, 186, 2222, +-1199, -418, -737, -2494, 880, -1131, 1100, 1714, +-201, 2241, -1001, -76, -486, -2145, 365, -1499, +700, 899, 488, 2057, -42, 666, -909, -1530, +-1022, -1706, 110, 354, 1583, 1841, 1394, 901, +-571, -1102, -2104, -1478, -1314, -115, 1110, 1091, +2388, 898, 1059, 46, -1665, -767, -2623, -1011, +-592, -395, 2318, 1050, 2700, 1769, -74, 275, +-2863, -2087, -2287, -2125, 734, 697, 2784, 2870, +1761, 1460, -996, -1700, -2595, -2540, -1588, -446, +1109, 1749, 2739, 1723, 1475, 126, -1645, -1251, +-2974, -1480, -845, -293, 2230, 1236, 2532, 1571, +7, 118, -2217, -1485, -1844, -1347, 236, 203, +1834, 1348, 1463, 1058, -112, -148, -1631, -1083, +-1550, -1098, 208, -54, 1859, 1203, 1412, 1273, +-653, -184, -2076, -1679, -961, -1195, 1402, 984, +2034, 2215, -81, 616, -2137, -2054, -1106, -2365, +1574, 403, 1984, 2903, -546, 1806, -2283, -1521, +-703, -3039, 1805, -791, 1745, 2242, -569, 2539, +-1900, -79, -866, -2326, 1019, -1918, 1596, 438, +432, 2015, -1111, 1403, -1399, -424, -146, -1527, +1290, -932, 1207, 299, -416, 921, -1600, 503, +-734, -86, 1146, -308, 1534, -269, -118, -265, +-1681, -217, -1086, 273, 950, 754, 1743, 615, +264, -407, -1527, -1276, -1463, -887, 465, 634, +1600, 1633, 685, 941, -1023, -821, -1116, -1741, +187, -714, 846, 981, 221, 1636, -332, 400, +-236, -1209, -17, -1503, 10, -62, 94, 1518, +191, 1435, -152, -395, -367, -1847, 159, -1162, +843, 1010, 279, 2007, -972, 454, -1152, -1742, +194, -1727, 1582, 621, 1321, 2232, -554, 974, +-2116, -1599, -1476, -2170, 1139, -122, 2791, 1994, +1385, 1822, -1934, -349, -3228, -2124, -920, -1673, +2601, 628, 3398, 2540, 545, 1683, -3111, -1203, +-3680, -3085, -233, -1513, 3751, 1915, 3730, 3405, +-570, 1178, -4331, -2408, -3183, -3437, 1545, -768, +4191, 2695, 2024, 3183, -2158, 231, -3492, -2821, +-927, -2650, 2036, 340, 2263, 2698, -18, 1978, +-1404, -721, -781, -2247, 407, -1362, -7, 622, +-692, 1528, 200, 1052, 1818, -6, 1084, -892, +-1945, -1201, -3099, -625, 39, 687, 3756, 1457, +2857, 799, -1902, -724, -4316, -1468, -1399, -743, +3105, 664, 3657, 1452, 116, 849, -3169, -702, +-2692, -1715, 469, -908, 2807, 1114, 2221, 2046, +-531, 486, -2583, -1792, -2019, -1917, 727, 383, +2708, 2195, 1770, 1165, -1148, -1141, -2648, -1755, +-1266, -303, 1490, 894, 2320, 716, 689, 367, +-1419, 470, -1961, -308, -629, -1755, 1245, -1514, +1930, 1205, 636, 3091, -1304, 1148, -2040, -2325, +-600, -2993, 1336, -233, 1718, 2354, 398, 2102, +-1174, -43, -1491, -1708, -434, -1575, 976, -71, +1343, 1345, 189, 1261, -1202, -86, -991, -1045, +480, -560, 1048, 220, -109, 252, -1067, -257, +-145, 9, 1332, 758, 738, 809, -1176, -322, +-1657, -1613, 188, -1309, 1823, 744, 1239, 2426, +-731, 1523, -1657, -1507, -844, -3059, 707, -1052, +1358, 2290, 872, 3109, -329, 501, -1249, -2611, +-1065, -3040, 189, -371, 1467, 2861, 1337, 3296, +-298, 34, -1887, -3568, -1346, -3194, 934, 1100, +2190, 4234, 816, 2221, -1587, -2473, -2051, -4248, +76, -973, 1967, 3388, 1360, 3923, -891, -49, +-2051, -4024, -651, -3455, 1429, 1210, 1793, 4550, +73, 2438, -1813, -2561, -1661, -4362, 303, -901, +1789, 3244, 1283, 3197, -462, -229, -1539, -2575, +-1084, -1825, 279, 216, 964, 1257, 775, 1188, +146, 516, -396, -461, -703, -1162, -831, -1008, +-327, 200, 844, 1157, 1686, 1219, 862, 210, +-1327, -1198, -2495, -1729, -1000, -552, 1852, 1637, +2986, 2296, 886, 371, -2337, -2121, -3055, -2293, +-457, -27, 2593, 2197, 2872, 2105, 86, -36, +-2600, -2186, -2349, -2188, 169, 206, 2247, 2466, +1986, 2096, -21, -702, -1809, -2559, -1889, -1547, +-301, 1047, 1720, 2312, 2079, 1095, 191, -1182, +-1932, -2192, -1908, -749, 210, 1636, 1879, 2156, +1322, -18, -489, -2128, -1639, -1564, -1133, 909, +626, 2079, 1806, 791, 723, -1108, -1607, -1773, +-2071, -723, 422, 986, 2786, 2051, 1379, 1169, +-2250, -1220, -3227, -2705, -29, -1341, 3163, 1637, +2545, 3078, -991, 1392, -3180, -1750, -1740, -3211, +1288, -1534, 2552, 1765, 1111, 3358, -1262, 1488, +-1924, -1870, -581, -3103, 980, -1069, 1070, 1720, +187, 2367, -358, 792, -286, -1021, -107, -1622, +-321, -973, -331, 231, 270, 1266, 954, 1377, +727, 322, -565, -1130, -1506, -1646, -845, -621, +1106, 1125, 2026, 1850, 487, 704, -1913, -1270, +-2134, -1914, 290, -439, 2578, 1515, 1776, 1668, +-1367, -8, -2875, -1414, -913, -1051, 2152, 251, +2607, 862, -147, 469, -2754, -7, -2027, -121, +1044, -298, 2880, -511, 1230, -213, -1970, 740, +-2742, 969, -332, -245, 2198, -1524, 2050, -774, +-198, 1511, -1937, 2096, -1703, -383, -36, -2893, +1451, -1643, 1712, 2160, 321, 3455, -1358, 280, +-1864, -3285, -607, -2809, 1138, 889, 1835, 3195, +827, 1909, -951, -1045, -1917, -2461, -1036, -1448, +874, 733, 1734, 1894, 861, 1237, -741, -411, +-1275, -1345, -600, -920, 274, -9, 543, 655, +480, 841, 414, 736, 137, 7, -667, -1012, +-1252, -1429, -654, -443, 913, 1214, 1922, 2060, +1071, 952, -1334, -1401, -2746, -2764, -1277, -1359, +1980, 1895, 3387, 3564, 831, 1392, -3052, -2600, +-3352, -3948, 201, -916, 3378, 3149, 2333, 3719, +-1251, 301, -2852, -3107, -1067, -3040, 1276, 163, +1518, 2736, 249, 2319, -600, -373, -577, -2145, +-404, -1511, -245, 330, 138, 1327, 636, 950, +488, 166, -428, -515, -754, -824, -31, -517, +523, 342, 22, 798, -684, 205, -307, -562, +869, -163, 914, 720, -557, 496, -1463, -882, +-553, -1367, 955, 180, 1244, 1783, 165, 1380, +-879, -758, -964, -2033, -297, -1121, 437, 859, +761, 1858, 587, 1164, -33, -426, -907, -1521, +-1167, -1318, -225, -90, 1086, 1178, 1422, 1334, +135, 498, -1474, -545, -1390, -981, 141, -725, +1273, -222, 855, 390, -334, 1010, -884, 1263, +-451, 345, 48, -1561, -22, -2417, 173, -562, +613, 2521, 436, 3162, -628, 170, -1281, -3138, +-353, -2959, 1067, 410, 1001, 3042, -427, 2257, +-1217, -615, -234, -2294, 943, -1343, 471, 529, +-880, 1228, -1054, 598, 450, 25, 1510, -66, +448, -323, -1487, -759, -1681, -430, 215, 683, +1687, 1127, 1032, 107, -687, -919, -1308, -531, +-439, 622, 428, 624, 345, -567, -64, -1027, +85, 304, 417, 1718, 69, 929, -928, -1463, +-1196, -2312, 56, -182, 1660, 2436, 1428, 2239, +-740, -668, -2346, -2762, -1242, -1626, 1298, 1418, +2137, 2723, 446, 778, -1516, -1981, -1549, -2197, +-65, 390, 958, 2321, 612, 1181, -215, -1318, +-405, -1896, 46, 0, 107, 1645, -568, 1053, +-865, -646, 14, -1301, 1498, -304, 1332, 942, +-935, 943, -2708, -132, -1396, -1026, 1896, -608, +3234, 589, 661, 1068, -2984, 266, -3319, -864, +95, -887, 3359, 277, 2719, 1111, -1109, 531, +-3541, -831, -1844, -1026, 1731, 267, 2803, 1229, +404, 394, -2049, -1037, -1636, -867, 572, 721, +1465, 1332, 261, 37, -1091, -1384, -922, -972, +203, 582, 858, 1387, 563, 802, -334, -395, +-969, -1235, -813, -1040, 196, 256, 944, 1536, +808, 1157, -304, -497, -1310, -1474, -1099, -646, +307, 647, 1338, 884, 926, 341, -595, -45, +-1585, -205, -795, -532, 737, -621, 1197, 79, +38, 928, -1152, 890, -657, -66, 742, -757, +847, -647, -722, -100, -1471, 219, -112, 420, +1640, 658, 1164, 569, -1238, -329, -2310, -1381, +-380, -1172, 1942, 706, 1925, 2314, -488, 1561, +-2379, -1239, -1658, -3147, 664, -1666, 2024, 1966, +1320, 3898, -580, 1638, -1819, -2578, -1599, -4147, +-106, -1296, 1448, 2916, 1787, 4055, 469, 1091, +-1282, -2764, -2189, -3655, -1187, -941, 689, 2401, +2079, 3169, 1765, 1050, -289, -1512, -2458, -2518, +-2506, -1475, -54, 547, 2519, 2360, 2383, 2258, +-450, -111, -2556, -2601, -1718, -2280, 696, 711, +1459, 2581, 286, 1236, -737, -1209, -195, -1404, +450, 200, -83, 902, -1092, -179, -999, -881, +460, 98, 1528, 1467, 871, 1005, -800, -879, +-1806, -1979, -1183, -862, 575, 1274, 1642, 2106, +987, 840, -595, -1219, -1484, -1900, -1009, -673, +105, 1044, 698, 1534, 663, 632, 507, -490, +-103, -970, -1171, -773, -1565, -212, -334, 642, +1594, 1348, 1953, 1004, 109, -566, -2096, -1961, +-2373, -1292, -169, 988, 2144, 2303, 2138, 1054, +-88, -1190, -2173, -1927, -2130, -620, -33, 937, +1705, 1468, 1708, 857, -3, -280, -1606, -1377, +-1759, -1424, -170, 57, 1418, 1789, 1293, 1675, +-333, -242, -1472, -1682, -714, -1056, 467, 444, +617, 889, -282, 270, -598, -91, 98, 308, +582, 315, 160, -459, -684, -997, -1197, -310, +-456, 786, 865, 980, 1431, 360, 511, -170, +-1333, -508, -2078, -891, -718, -843, 1346, 422, +2098, 1947, 616, 1780, -1600, -552, -2344, -2756, +-810, -2250, 1430, 825, 2113, 3193, 461, 2361, +-1517, -875, -1790, -2872, -323, -1823, 1025, 703, +871, 1803, -192, 1180, -552, 232, -172, -246, +85, -957, -299, -1404, -522, -562, -144, 1271, +454, 1999, 635, 718, 242, -1045, -616, -1578, +-1356, -877, -886, 169, 691, 1095, 1706, 1653, +893, 963, -945, -969, -1942, -2419, -1131, -1422, +445, 1271, 1426, 2681, 1152, 1249, 6, -1282, +-1172, -2058, -1517, -611, -946, 1010, 564, 1117, +1758, 58, 1236, -488, -699, -139, -2142, 409, +-1394, 266, 818, -304, 1642, -688, 518, -377, +-921, 399, -1005, 1123, -52, 938, 461, -225, +-74, -1544, -538, -1441, -231, 270, 464, 1986, +627, 1683, -138, -359, -850, -1913, -867, -1425, +-98, 354, 586, 1503, 744, 1124, 366, 26, +-391, -741, -1171, -757, -1138, -487, 75, -21, +1445, 657, 1395, 1180, -326, 656, -1791, -712, +-1572, -1654, 151, -841, 1622, 1047, 1455, 1970, +-220, 814, -1809, -1378, -1635, -2018, 134, -369, +1707, 1793, 1499, 1913, -433, -143, -2132, -2005, +-1515, -1455, 630, 687, 2095, 2071, 1164, 1151, +-1099, -875, -2276, -1988, -1125, -1117, 948, 978, +1991, 2256, 1046, 1323, -926, -1071, -2033, -2410, +-1418, -1167, 427, 1232, 1848, 2139, 1477, 842, +-432, -887, -2029, -1314, -1636, -544, 554, 322, +1780, 630, 708, 469, -977, 146, -1183, -4, +165, -8, 736, -292, -257, -764, -942, -551, +-207, 692, 983, 1670, 968, 914, -345, -981, +-1568, -2005, -1103, -1028, 417, 895, 1468, 1978, +1006, 1359, -500, -297, -1596, -1684, -1153, -1732, +329, -393, 1426, 1439, 1073, 2284, -313, 1211, +-1524, -1272, -1643, -2882, -11, -1683, 1818, 1558, +1972, 3464, -207, 1663, -2404, -1899, -2110, -3350, +285, -1205, 2056, 1810, 1587, 2713, -91, 1162, +-1322, -888, -1624, -2040, -1049, -1700, 414, -90, +1929, 1967, 1922, 2553, -281, 601, -2579, -2135, +-2472, -2820, 79, -550, 2437, 2141, 2263, 2593, +81, 582, -2020, -1671, -2281, -2177, -590, -717, +1256, 1188, 1772, 1909, 787, 1015, -659, -691, +-1368, -1652, -1023, -1191, -299, 415, 659, 1635, +1149, 1236, 694, -444, -374, -1541, -1212, -798, +-972, 872, 78, 1318, 738, 30, 456, -1237, +68, -776, -26, 909, -36, 1546, -564, 177, +-1013, -1662, -412, -1608, 897, 440, 1461, 2249, +558, 1664, -1143, -776, -1892, -2532, -918, -1760, +1016, 957, 1967, 2831, 998, 1944, -1091, -1000, +-2050, -2921, -1083, -1858, 731, 1049, 1684, 2754, +995, 1684, -468, -868, -1370, -2300, -1258, -1415, +-186, 667, 1004, 1812, 1337, 1164, 484, -339, +-882, -1092, -1576, -768, -851, -126, 588, 233, +1328, 518, 807, 901, -328, 683, -1066, -515, +-956, -1550, -262, -1054, 663, 733, 910, 1717, +339, 862, -515, -666, -873, -1102, -297, -316, +355, 356, 188, 169, -278, -250, -99, 101, +490, 893, 656, 895, -294, -489, -1349, -1759, +-1136, -1261, 382, 824, 1712, 2183, 1495, 1385, +-398, -705, -2156, -1957, -1866, -1433, 259, 247, +2127, 1645, 1872, 1604, -315, 157, -2166, -1380, +-1823, -1453, 281, -146, 1912, 1066, 1553, 1042, +-397, 149, -1870, -643, -1503, -707, 313, -142, +1710, 565, 1259, 661, -395, -33, -1560, -702, +-1166, -436, 76, 384, 1000, 686, 991, 72, +426, -403, -474, -183, -1279, 234, -1273, -22, +-136, -459, 1407, -210, 1849, 764, 477, 1066, +-1401, 77, -2078, -1324, -1230, -1495, 558, -86, +2048, 1582, 2212, 1939, 340, 534, -2402, -1530, +-3341, -2440, -897, -1104, 2708, 1522, 3565, 2940, +650, 1468, -2694, -1631, -2917, -3106, -412, -1283, +1729, 1896, 1749, 2896, 430, 688, -666, -2071, +-986, -2239, -822, 120, -220, 2049, 604, 1329, +796, -756, 310, -1566, -326, -342, -595, 1026, +-384, 833, -43, -293, 285, -796, 267, -264, +-44, 337, -304, 508, 15, 421, 399, 69, +3, -681, -834, -1155, -732, -260, 510, 1432, +1385, 1891, 576, 36, -1231, -2188, -1719, -2107, +-262, 377, 1536, 2419, 1523, 1885, -106, -430, +-1612, -1926, -1383, -1485, 159, 34, 1368, 1140, +1084, 1243, -209, 482, -1143, -530, -919, -1008, +25, -593, 745, 236, 788, 639, 106, 449, +-677, -30, -889, -331, -278, -310, 589, 80, +897, 419, 298, 182, -585, -473, -1028, -665, +-594, 123, 537, 1010, 1215, 834, 616, -425, +-745, -1292, -1406, -853, -479, 496, 908, 1265, +1075, 864, -1, -250, -825, -1022, -503, -910, +218, -30, 317, 796, -100, 816, -273, 73, +-105, -535, 244, -376, 366, 136, 254, 209, +-368, -195, -1028, -443, -845, -31, 694, 682, +1906, 967, 1083, 262, -1453, -1040, -2731, -1768, +-952, -777, 2132, 1383, 2773, 2701, 382, 1340, +-2272, -1667, -2363, -3357, -236, -1700, 1665, 1683, +1754, 3409, 622, 1930, -796, -1070, -1696, -2891, +-1440, -2360, -15, -136, 1719, 2258, 2121, 3079, +614, 1450, -1662, -1730, -2647, -3739, -1347, -2499, +1260, 1233, 2818, 4040, 1952, 3133, -667, -769, +-2838, -3795, -2558, -3117, -34, 316, 2550, 2853, +2807, 2495, 546, 290, -2215, -1437, -2750, -1685, +-765, -908, 1560, 158, 2003, 979, 707, 1220, +-653, 596, -1019, -434, -825, -1099, -387, -777, +276, 79, 789, 659, 665, 533, 96, 138, +-302, -77, -412, -89, -610, -227, -638, -459, +27, -463, 1031, 89, 1307, 903, 245, 1104, +-1264, 154, -1624, -1230, -516, -1516, 886, -349, +1463, 1093, 873, 1424, -213, 679, -1174, -385, +-1369, -1156, -639, -1255, 794, -358, 1740, 1123, +1265, 1680, -626, 547, -2072, -1209, -1483, -1598, +683, -272, 2024, 1141, 1100, 1082, -895, -135, +-1638, -899, -533, -432, 823, 438, 1037, 556, +247, -96, -627, -548, -902, -265, -260, 277, +562, 388, 747, 131, 295, -32, -335, -24, +-552, -213, -532, -526, -342, -347, 216, 426, +1027, 976, 1086, 500, -109, -519, -1568, -974, +-1549, -495, 57, 277, 1667, 642, 1547, 490, +-65, -2, -1385, -403, -1056, -279, 59, 161, +497, 150, 134, -513, 78, -636, 598, 464, +825, 1526, -261, 758, -1674, -1255, -1553, -2002, +357, -449, 2132, 1595, 1944, 1751, -204, 132, +-2240, -1355, -2008, -1326, 48, -187, 1846, 890, +1785, 1117, 161, 465, -1362, -527, -1461, -1014, +-318, -735, 862, 47, 938, 718, 286, 1038, +-214, 624, -341, -424, -295, -1413, -510, -1131, +-297, 326, 590, 1504, 1017, 1142, 335, -287, +-752, -1228, -1032, -926, -156, 168, 799, 865, +634, 598, -222, -212, -518, -513, -92, -102, +265, 281, 135, -27, -98, -395, -127, -151, +11, 423, 29, 499, -5, 18, 18, -332, +120, -350, 83, -183, -45, -73, -330, 164, +-294, 364, 212, 353, 617, 53, 370, -271, +-373, -417, -787, -376, -297, -114, 520, 321, +731, 641, 69, 412, -638, -202, -428, -603, +458, -370, 619, -13, -306, 85, -891, 65, +-63, 396, 964, 614, 671, 94, -435, -869, +-811, -1055, -237, -30, 287, 1020, 248, 954, +256, -31, 362, -672, 74, -577, -617, -207, +-821, -70, -68, 147, 943, 597, 1020, 834, +113, 246, -1054, -904, -1288, -1456, -148, -643, +1267, 1006, 1489, 1816, 147, 816, -1427, -1068, +-1422, -1831, 4, -652, 1315, 1032, 1216, 1405, +52, 342, -1037, -744, -1022, -915, -152, -380, +775, 244, 871, 753, 339, 800, -354, 116, +-662, -1007, -618, -1323, -114, -195, 560, 1430, +994, 1651, 412, -18, -676, -1845, -971, -1731, +-20, 432, 784, 2121, 363, 1429, -647, -1032, +-670, -2186, 575, -752, 1473, 1595, 630, 1884, +-1372, -131, -2216, -1970, -647, -1450, 2067, 783, +2852, 2086, 487, 1102, -2362, -1087, -2659, -1991, +-247, -849, 1986, 986, 1940, 1436, 370, 488, +-998, -474, -1204, -401, -462, -151, 198, -416, +374, -745, 366, -81, 513, 1122, 653, 1480, +-24, 343, -1203, -1281, -1371, -1790, -9, -724, +1558, 954, 1556, 1626, 23, 867, -1312, -379, +-1107, -968, -74, -770, 729, -385, 625, 67, +105, 631, -132, 990, 41, 485, 94, -576, +-203, -1154, -634, -596, -307, 421, 628, 903, +980, 484, 308, -332, -692, -725, -710, -297, +8, 573, 363, 752, 30, -123, -124, -1195, +339, -928, 832, 574, 330, 1754, -938, 1128, +-1449, -714, -408, -1969, 1146, -1448, 1668, 310, +726, 1755, -677, 1733, -1265, 283, -940, -1284, +-179, -1698, 594, -781, 1045, 475, 1072, 1223, +474, 1103, -750, 358, -1618, -662, -1294, -1250, +217, -958, 1721, 50, 1949, 1038, 560, 1304, +-1184, 581, -2021, -740, -1410, -1578, 236, -1114, +1907, 428, 2401, 1645, 914, 1436, -1710, -128, +-3010, -1719, -1468, -1775, 1540, 10, 2959, 1992, +1536, 1869, -919, -391, -2134, -2291, -1456, -1552, +204, 815, 1490, 2161, 1526, 1135, 321, -861, +-1060, -1899, -1322, -1144, -393, 525, 709, 1708, +1212, 1384, 825, -111, -301, -1565, -1403, -1755, +-1289, -467, 338, 1347, 2028, 2110, 1623, 954, +-656, -1241, -2322, -2394, -1329, -1190, 1154, 1157, +2247, 2270, 815, 1038, -1250, -995, -1646, -1765, +-236, -849, 1101, 489, 1069, 1053, 37, 793, +-509, 106, -321, -569, -119, -954, -162, -584, +-82, 326, 458, 1002, 900, 726, 420, -258, +-673, -983, -1134, -786, -407, 115, 782, 890, +1076, 864, 395, 61, -538, -859, -821, -1118, +-203, -418, 637, 755, 679, 1343, -59, 718, +-685, -603, -381, -1385, 566, -962, 777, 191, +-8, 1056, -642, 1078, -450, 271, 277, -709, +663, -1202, 313, -712, -239, 392, -457, 1236, +-121, 973, 269, -262, 275, -1333, 116, -1158, +38, 172, 19, 1255, -68, 1109, -224, -47, +-126, -932, 279, -1017, 523, -345, 286, 427, +-270, 894, -656, 596, -441, -240, 436, -765, +1096, -395, 720, 310, -413, 313, -1310, -313, +-863, -511, 590, 215, 1490, 882, 854, 501, +-420, -642, -1045, -1068, -536, -320, 146, 658, +444, 684, 465, -6, 420, -403, 190, -188, +-254, 44, -593, -114, -441, -172, 82, 179, +686, 539, 994, 178, 297, -614, -891, -912, +-1281, -211, -182, 772, 1324, 1038, 1476, 403, +62, -555, -1261, -1106, -1229, -964, -24, -115, +1063, 975, 1165, 1468, 492, 782, -437, -740, +-1109, -1809, -876, -1417, 114, 238, 1218, 1776, +1367, 1803, 309, 121, -1062, -1704, -1358, -1899, +-420, -269, 805, 1381, 1276, 1400, 810, 107, +-76, -843, -888, -672, -1083, -87, -450, 64, +780, -81, 1507, 164, 905, 557, -686, 388, +-1543, -443, -622, -931, 1075, -398, 1496, 525, +132, 809, -1282, 236, -944, -412, 578, -603, +1285, -365, 607, 2, -448, 429, -671, 610, +-315, 259, 14, -487, 194, -895, 462, -501, +625, 369, 359, 932, -294, 681, -652, -183, +-342, -962, 143, -922, 386, -160, 386, 653, +377, 860, 277, 539, -65, -87, -498, -774, +-487, -1152, -73, -651, 380, 576, 697, 1411, +739, 1018, 273, -282, -626, -1236, -1197, -1225, +-585, -356, 789, 663, 1525, 1130, 962, 680, +-268, -224, -1114, -743, -1091, -665, -358, -315, +742, 5, 1567, 406, 1225, 686, -287, 363, +-1559, -436, -1233, -852, 291, -288, 1256, 547, +898, 634, 153, -187, -194, -828, -307, -521, +-488, 446, -360, 930, 345, 431, 926, -529, +559, -909, -204, -427, -456, 275, -134, 419, +122, 64, -35, -31, 0, 210, 449, 307, +796, -217, 304, -731, -596, -710, -973, -6, +-263, 628, 781, 911, 1127, 529, 476, -319, +-372, -1201, -734, -1266, -423, -93, 236, 1364, +819, 1689, 680, 257, -178, -1607, -752, -2005, +-335, -332, 605, 1645, 924, 1847, 340, 149, +-488, -1453, -653, -1377, -272, -199, 357, 634, +826, 576, 854, 354, 158, 264, -812, 8, +-1156, -718, -175, -1071, 1248, -372, 1624, 888, +414, 1224, -1142, 175, -1565, -975, -419, -912, +1083, 106, 1768, 678, 1055, 298, -473, -399, +-1650, -474, -1317, -62, 313, 374, 1728, 396, +1616, 40, 142, -413, -1273, -633, -1219, -343, +105, 216, 1084, 700, 786, 578, -97, 14, +-366, -685, 72, -848, 308, -424, 11, 292, +-218, 699, 77, 589, 488, 145, 493, -346, +9, -660, -380, -735, -376, -303, 66, 392, +570, 978, 750, 732, 398, -105, -173, -962, +-658, -1089, -631, -477, 16, 527, 890, 1190, +1197, 919, 570, -210, -498, -1279, -1140, -1208, +-692, -170, 451, 922, 1289, 1056, 1017, 423, +-93, -510, -886, -985, -590, -727, 358, 131, +776, 788, 291, 570, -237, -158, -169, -598, +315, -320, 556, 111, 195, 204, -342, -43, +-399, -149, -34, -46, 466, 116, 761, 23, +538, -157, -107, -175, -670, 18, -579, 143, +198, -55, 932, -270, 800, -163, 107, 280, +-479, 338, -402, -172, 2, -678, 284, -302, +399, 578, 476, 768, 355, -150, -86, -1075, +-586, -800, -436, 340, 507, 1089, 1155, 719, +633, -149, -621, -857, -975, -999, -148, -574, +907, 278, 984, 1064, 337, 1114, -447, 271, +-692, -913, -305, -1484, 558, -904, 1040, 446, +636, 1345, -386, 1014, -835, -166, -230, -1024, +560, -969, 739, -262, 337, 489, 18, 885, +-55, 614, -142, -328, -296, -1153, -7, -1063, +546, 106, 772, 1157, 285, 1242, -368, 235, +-466, -925, 104, -1487, 493, -929, 390, 309, +-44, 1341, -128, 1242, 266, 189, 489, -877, +29, -1267, -472, -898, -224, -35, 671, 990, +1031, 1403, 236, 609, -831, -953, -899, -1727, +119, -881, 1097, 726, 1120, 1456, 322, 806, +-542, -430, -826, -1115, -379, -944, 292, -124, +757, 692, 792, 923, 437, 432, -149, -433, +-476, -930, -363, -746, 65, 30, 507, 728, +473, 730, 106, 5, -63, -653, 208, -524, +305, 80, 77, 293, -215, -75, -38, -306, +253, -27, 285, 316, 63, 249, 27, -95, +224, -387, 321, -428, 160, -173, 12, 320, +54, 595, -41, 182, -195, -615, -144, -880, +413, -161, 943, 860, 861, 1020, -171, -19, +-1196, -1250, -1103, -1372, 383, -84, 1657, 1383, +1470, 1543, -58, 212, -1355, -1382, -1169, -1746, +170, -613, 1329, 1005, 1268, 1603, 170, 757, +-896, -701, -924, -1360, 48, -784, 1053, 258, +999, 801, 15, 565, -785, -46, -514, -516, +324, -564, 816, -152, 565, 381, 75, 499, +-326, 52, -432, -505, -230, -545, 392, -79, +885, 334, 688, 312, -142, 17, -653, -165, +-384, -84, 234, 86, 523, -92, 395, -562, +185, -699, 144, 186, 96, 1322, -139, 1191, +-298, -595, -123, -2019, 334, -1302, 693, 853, +597, 1902, 59, 779, -443, -951, -696, -1340, +-323, -291, 587, 626, 1258, 451, 933, -177, +-255, -231, -1217, 182, -974, 198, 262, -363, +1226, -572, 1116, -74, 228, 490, -443, 386, +-656, -34, -432, -274, 47, -325, 638, -364, +862, -163, 467, 355, -285, 614, -584, 205, +-245, -471, 245, -710, 433, -346, 437, 221, +318, 602, -26, 495, -400, -129, -342, -777, +259, -682, 632, 104, 429, 715, -71, 474, +-182, -186, 15, -493, 74, -330, -100, -84, +74, 67, 506, 173, 491, 190, -102, -5, +-482, -167, -115, -95, 546, 56, 578, -119, +-46, -397, -457, -276, -243, 286, 322, 661, +641, 331, 422, -378, -72, -790, -355, -556, +-220, 161, 136, 683, 257, 538, 169, -179, +200, -643, 277, -372, 160, 214, -136, 344, +-196, -25, 46, -309, 187, -155, 39, 131, +13, 131, 336, -89, 537, -184, 134, 0, +-461, 233, -447, 125, 110, -339, 439, -609, +368, -184, 171, 603, 140, 816, 36, 67, +-231, -868, -359, -909, 59, -46, 556, 749, +592, 667, 122, 7, -401, -467, -485, -522, +-17, -323, 560, -37, 693, 410, 270, 666, +-379, 333, -626, -506, -303, -1022, 428, -634, +885, 369, 614, 1048, -162, 797, -658, -201, +-593, -1033, 67, -984, 676, -68, 740, 780, +266, 831, -303, 196, -531, -441, -251, -651, +230, -495, 496, -88, 433, 440, 148, 705, +-169, 337, -395, -412, -252, -810, 253, -474, +672, 185, 506, 535, -183, 393, -669, 28, +-317, -240, 451, -296, 642, -270, 192, -233, +-206, -77, -67, 299, 135, 628, -27, 431, +-327, -361, -123, -1017, 464, -789, 815, 217, +418, 1117, -388, 968, -906, -141, -580, -1172, +341, -1098, 1035, 30, 882, 1001, 67, 888, +-664, -7, -766, -654, -236, -680, 422, -383, +698, 38, 489, 623, -16, 873, -421, 217, +-336, -840, 154, -1008, 448, -120, 199, 557, +-251, 245, -251, -154, 207, 217, 473, 711, +234, 216, -230, -930, -329, -1404, -9, -577, +340, 809, 321, 1593, 48, 1146, -227, -276, +-185, -1545, 140, -1579, 319, -335, 186, 1039, +23, 1386, -6, 626, -133, -396, -283, -912, +-42, -718, 543, -154, 691, 373, -38, 484, +-888, 214, -606, -131, 662, -149, 1255, 17, +290, -32, -1040, -315, -993, -345, 257, 101, +1092, 488, 614, 336, -295, -115, -574, -331, +-80, -293, 287, -218, 233, -74, -38, 313, +-178, 577, -119, 266, 243, -443, 510, -792, +274, -403, -261, 300, -484, 657, -244, 465, +193, -16, 442, -409, 389, -483, 122, -333, +-203, -84, -376, 185, -153, 542, 282, 660, +415, 153, 111, -837, -227, -1217, -214, -270, +69, 1142, 307, 1332, 204, -78, -63, -1398, +-198, -1017, -70, 475, 122, 1190, 196, 446, +77, -542, -63, -583, 34, -54, 154, 70, +23, -238, -194, -180, -132, 424, 242, 753, +389, 234, 82, -591, -268, -770, -222, -233, +33, 241, 163, 170, 179, -9, 243, 251, +186, 612, -208, 330, -530, -587, -222, -1169, +458, -660, 725, 490, 271, 1131, -356, 715, +-527, -217, -226, -740, 48, -550, 201, -89, +414, 223, 619, 305, 357, 314, -469, 78, +-1157, -407, -833, -670, 476, -160, 1575, 750, +1289, 996, -187, 136, -1465, -950, -1398, -1128, +-154, -359, 1126, 546, 1399, 943, 544, 742, +-637, 114, -1131, -602, -589, -933, 330, -562, +891, 149, 704, 632, -28, 574, -775, 147, +-864, -330, -47, -455, 1109, -30, 1248, 482, +-53, 275, -1435, -595, -1265, -988, 278, -129, +1493, 1153, 1100, 1312, -278, 76, -1081, -1266, +-674, -1349, 218, -184, 643, 1016, 394, 1109, +-95, 148, -285, -723, -126, -656, 114, -11, +184, 293, 163, 122, 5, 27, -250, 155, +-304, 50, 49, -297, 477, -313, 447, 164, +-107, 386, -611, -27, -362, -415, 397, -77, +728, 482, 206, 333, -595, -405, -797, -687, +-92, -101, 884, 567, 988, 534, 15, 12, +-962, -320, -861, -281, 76, -189, 791, -130, +562, 111, -124, 417, -366, 361, -51, -130, +142, -459, 27, -240, -102, 193, -11, 225, +58, -70, -88, -227, -193, -5, 170, 230, +647, 203, 470, -19, -407, -174, -1003, -183, +-572, -115, 417, -15, 903, 114, 633, 186, +38, 125, -413, -16, -669, -114, -535, -135, +22, -128, 655, -29, 764, 151, 261, 233, +-403, 6, -668, -236, -410, -138, 77, 155, +497, 146, 505, -166, 156, -219, -224, 199, +-302, 484, -217, 119, -195, -557, -178, -743, +201, -157, 804, 684, 816, 1026, -169, 455, +-1271, -620, -1258, -1218, 10, -679, 1335, 430, +1471, 975, 320, 534, -1050, -109, -1449, -269, +-587, -119, 676, -219, 1214, -446, 645, -296, +-327, 271, -810, 716, -548, 597, -4, 25, +391, -590, 453, -775, 262, -330, -48, 423, +-271, 732, -436, 314, -369, -339, 37, -453, +596, -65, 712, 239, 181, 103, -614, -134, +-841, -78, -252, 160, 448, 181, 477, -122, +138, -342, 38, -140, 158, 349, -29, 502, +-572, 47, -788, -589, -81, -599, 971, 131, +1114, 801, 55, 523, -1082, -391, -1059, -832, +34, -259, 950, 552, 697, 566, -265, -65, +-685, -423, -173, -115, 425, 230, 315, 109, +-289, -210, -513, -151, -18, 176, 483, 255, +304, -93, -164, -340, -243, -82, 9, 412, +7, 447, -332, -118, -355, -659, 326, -497, +929, 225, 484, 690, -686, 383, -1271, -241, +-567, -440, 717, -68, 1271, 238, 591, 59, +-583, -274, -1092, -212, -568, 203, 313, 414, +665, 175, 351, -201, -121, -290, -263, -113, +-91, 70, 42, 91, -56, 39, -245, -24, +-265, -22, 73, 31, 523, 154, 552, 161, +-27, -44, -681, -342, -755, -380, -182, -14, +443, 429, 643, 494, 386, 107, -62, -276, +-437, -331, -554, -146, -355, -61, 53, -23, +457, 112, 534, 337, 174, 342, -342, 82, +-575, -234, -338, -423, 179, -423, 453, -164, +187, 343, -211, 694, -287, 488, -85, -155, +115, -592, 119, -535, -20, -146, -136, 264, +-106, 532, 18, 381, 95, -147, -30, -509, +-244, -204, -169, 321, 227, 246, 440, -287, +69, -361, -485, 230, -556, 601, -102, 180, +351, -473, 422, -558, 176, -130, -145, 323, +-343, 484, -344, 335, -102, -75, 191, -476, +183, -469, -19, -28, -4, 361, 146, 339, +36, 53, -337, -118, -494, -91, -91, -17, +420, -51, 395, -103, -68, -25, -303, 173, +-121, 233, 49, -20, -69, -315, -296, -240, +-206, 179, 291, 433, 592, 246, 142, -160, +-606, -402, -743, -411, -77, -165, 652, 305, +594, 717, -163, 529, -674, -242, -448, -807, +116, -496, 459, 232, 335, 442, -108, 54, +-478, -159, -370, 169, 101, 411, 403, 36, +139, -502, -346, -417, -433, 134, 6, 334, +391, -77, 329, -312, -46, 138, -374, 702, +-475, 462, -337, -430, 55, -908, 538, -433, +650, 316, 112, 516, -614, 232, -771, 79, +-290, 188, 209, 65, 315, -410, 246, -650, +286, -157, 174, 562, -351, 628, -846, -64, +-607, -583, 266, -249, 906, 493, 626, 663, +-220, -4, -806, -767, -656, -784, -31, -46, +465, 700, 408, 800, 55, 298, -198, -224, +-206, -440, -162, -431, -206, -394, -215, -154, +68, 381, 367, 850, 347, 627, -58, -227, +-460, -864, -510, -558, -86, 262, 339, 550, +340, -2, -72, -504, -378, -170, -221, 599, +217, 789, 275, 131, -130, -631, -429, -814, +-256, -413, 126, 172, 316, 604, 174, 656, +-146, 318, -383, -179, -333, -463, 14, -434, +344, -202, 319, 82, -44, 305, -343, 336, +-341, 167, -241, -56, -173, -178, 100, -194, +562, -100, 646, 109, 1, 271, -862, 150, +-1041, -179, -309, -319, 594, -143, 829, 112, +359, 247, -167, 362, -392, 357, -388, -36, +-408, -663, -331, -793, 92, -138, 683, 679, +682, 869, -100, 407, -906, -223, -779, -664, +150, -701, 765, -175, 368, 608, -349, 845, +-542, 215, -218, -598, 49, -650, 143, 15, +215, 553, 244, 372, -15, -153, -458, -353, +-592, -64, -204, 237, 295, 137, 481, -188, +301, -240, -66, 101, -406, 404, -477, 285, +-258, -160, 53, -438, 237, -287, 278, 140, +166, 403, -56, 256, -293, -97, -376, -225, +-244, -72, -56, 46, 119, -1, 289, 69, +363, 283, 121, 189, -406, -369, -738, -683, +-460, -93, 204, 826, 617, 903, 456, -24, +-19, -857, -357, -725, -432, -2, -374, 445, +-219, 377, 137, 207, 531, 191, 559, 87, +6, -286, -725, -603, -870, -401, -202, 245, +596, 715, 717, 518, 146, -89, -482, -461, +-539, -306, -147, 62, 134, 203, 44, 19, +-64, -179, -19, -60, 153, 301, 200, 468, +16, 127, -332, -368, -546, -451, -417, -109, +103, 90, 674, -20, 660, 70, -29, 605, +-708, 816, -744, 43, -206, -1089, 292, -1220, +339, -137, 174, 953, 69, 1067, -15, 442, +-194, -163, -423, -543, -463, -745, -117, -545, +448, 235, 741, 1007, 325, 877, -603, -188, +-1149, -1102, -619, -814, 560, 431, 1168, 1267, +557, 724, -558, -615, -998, -1242, -498, -476, +192, 711, 352, 975, 116, 184, 42, -565, +196, -445, 123, 192, -348, 474, -662, 131, +-381, -323, 229, -364, 524, -9, 282, 292, +-89, 227, -230, 11, -278, 33, -345, 218, +-224, 109, 173, -379, 466, -599, 291, -50, +-206, 718, -522, 689, -409, -168, -80, -758, +210, -313, 395, 544, 319, 703, -121, 0, +-559, -639, -555, -523, -99, 94, 355, 500, +398, 436, 106, 155, -176, -93, -301, -267, +-248, -320, -89, -153, 26, 184, 15, 388, +-4, 285, 90, 2, 163, -206, -72, -230, +-402, -80, -386, 144, 27, 248, 370, 114, +276, -98, -95, -92, -329, 71, -299, 80, +-151, -114, 13, -137, 154, 174, 184, 416, +81, 168, -62, -342, -223, -500, -382, -100, +-311, 457, 66, 610, 424, 194, 321, -405, +-154, -581, -445, -164, -246, 374, 58, 479, +85, 181, -66, -56, -60, -87, 60, -143, +30, -300, -183, -261, -254, 165, -24, 637, +251, 622, 179, 27, -194, -615, -441, -679, +-247, -98, 167, 476, 309, 467, 41, 65, +-267, -105, -252, 93, 10, 147, 186, -153, +78, -362, -167, -76, -346, 327, -289, 262, +-40, -128, 275, -214, 429, 162, 200, 447, +-298, 206, -605, -273, -454, -431, -31, -201, +257, 86, 297, 218, 259, 327, 162, 414, +-168, 200, -638, -374, -753, -753, -170, -331, +682, 602, 921, 1009, 206, 302, -773, -773, +-1034, -977, -322, -67, 524, 915, 676, 906, +160, 32, -312, -667, -328, -540, -168, 37, +-232, 343, -309, 183, -48, -57, 445, -12, +632, 236, 159, 327, -591, 34, -900, -403, +-488, -485, 257, -17, 687, 490, 463, 451, +-90, 9, -432, -178, -362, 49, -163, 104, +-142, -285, -181, -497, 69, 40, 488, 805, +523, 799, -99, -66, -854, -844, -914, -740, +-117, 13, 802, 631, 890, 660, 80, 237, +-800, -213, -882, -361, -189, -195, 468, 46, +471, 153, 33, 124, -259, 67, -218, 20, +-114, -10, -139, 10, -177, 109, -44, 178, +175, 102, 245, -73, 64, -232, -266, -246, +-484, -82, -339, 243, 92, 490, 402, 411, +292, 24, -117, -320, -382, -363, -288, -210, +-97, -59, -50, 111, 22, 413, 150, 578, +154, 283, -90, -330, -329, -607, -230, -305, +69, 166, 119, 373, -108, 346, -289, 218, +-143, -96, 174, -424, 266, -284, 67, 344, +-249, 658, -427, 131, -310, -572, -3, -509, +201, 162, 222, 504, 86, 272, -81, 29, +-213, 56, -277, -18, -258, -320, -137, -407, +44, 1, 244, 515, 330, 616, 84, 260, +-438, -270, -724, -635, -292, -550, 455, 83, +634, 791, -1, 863, -634, 155, -469, -633, +163, -755, 365, -287, -28, 249, -347, 523, +-198, 586, 71, 390, 38, -103, -105, -629, +-35, -681, 123, -120, -30, 567, -358, 731, +-397, 252, -13, -317, 371, -399, 325, 13, +-86, 341, -414, 123, -428, -365, -148, -396, +205, 251, 312, 804, 58, 474, -323, -466, +-418, -863, -59, -189, 354, 706, 242, 729, +-292, -75, -613, -604, -254, -276, 386, 327, +483, 378, -65, -28, -532, -205, -387, 58, +150, 258, 327, 35, -42, -266, -406, -158, +-285, 264, 157, 419, 362, 112, 41, -298, +-438, -368, -489, -80, -19, 284, 440, 442, +300, 293, -245, -45, -547, -303, -307, -286, +143, -86, 308, 104, 116, 203, -132, 263, +-243, 247, -243, 73, -136, -181, 18, -264, +107, -71, 57, 158, -54, 155, -127, -34, +-144, -96, -128, 123, -57, 343, -4, 237, +-19, -149, -67, -362, -39, -170, 24, 169, +-34, 248, -223, 82, -248, -22, 22, 44, +219, 101, 64, 0, -227, -61, -250, 56, +-11, 189, 72, 37, -134, -299, -243, -333, +-19, 143, 255, 645, 185, 533, -216, -87, +-494, -529, -311, -401, 137, -52, 420, 134, +212, 245, -301, 427, -552, 428, -222, -20, +296, -543, 383, -557, -86, -19, -482, 491, +-267, 517, 168, 154, 193, -205, -179, -274, +-316, -88, 34, 130, 319, 157, 68, 74, +-385, 54, -439, 80, -62, -26, 217, -189, +120, -132, -47, 171, -23, 387, 23, 282, +-132, -21, -366, -313, -322, -443, 41, -258, +327, 293, 272, 786, -37, 618, -284, -189, +-321, -820, -195, -621, -34, 142, 88, 673, +108, 548, 71, 53, 6, -291, -122, -298, +-268, -112, -305, 72, -72, 177, 251, 208, +288, 158, -71, 1, -405, -171, -323, -164, +53, 50, 246, 251, 59, 176, -200, -89, +-184, -203, 0, 20, 36, 277, -129, 187, +-258, -176, -69, -292, 254, 71, 303, 449, +-54, 294, -490, -272, -569, -507, -123, -103, +426, 467, 555, 514, 117, 35, -469, -386, +-605, -311, -192, 111, 272, 376, 291, 210, +-51, -208, -283, -361, -136, -26, 127, 446, +154, 446, -93, -73, -308, -470, -249, -236, +-19, 282, 152, 357, 158, -50, 2, -297, +-158, 4, -207, 363, -138, 221, 9, -215, +87, -266, 7, 153, -108, 381, -163, 4, +-99, -505, -1, -364, 61, 360, 95, 837, +37, 449, -153, -418, -340, -838, -283, -401, +13, 364, 315, 651, 319, 332, 29, -83, +-308, -174, -453, -119, -318, -191, 48, -204, +381, 115, 355, 537, -57, 471, -443, -145, +-400, -633, -9, -397, 259, 287, 160, 621, +-86, 265, -201, -296, -144, -394, -51, -6, +18, 329, 47, 227, 25, -95, -57, -208, +-142, -6, -155, 213, -81, 168, 11, -72, +82, -234, 89, -105, -13, 207, -134, 405, +-184, 223, -165, -228, -111, -505, 21, -296, +215, 264, 263, 620, -33, 401, -454, -192, +-447, -519, 47, -250, 446, 244, 223, 343, +-331, -1, -442, -240, 15, -24, 364, 335, +165, 294, -287, -110, -377, -383, -36, -224, +189, 122, 33, 289, -164, 208, -75, 48, +191, -73, 163, -118, -214, -60, -458, 54, +-215, 111, 266, 23, 377, -67, -6, -33, +-377, 67, -269, 89, 151, 53, 324, 91, +24, 124, -413, -41, -469, -316, -32, -296, +439, 133, 457, 521, -2, 376, -475, -153, +-508, -431, -114, -180, 302, 238, 359, 298, +49, -16, -292, -296, -338, -188, -46, 195, +245, 422, 152, 245, -158, -170, -244, -388, +-3, -239, 161, 92, -30, 283, -300, 247, +-206, 88, 200, -80, 392, -163, 127, -122, +-320, 21, -509, 118, -296, 112, 120, 46, +435, 15, 383, -7, -32, -75, -402, -87, +-410, 46, -124, 209, 145, 135, 176, -148, +73, -286, 16, -21, -39, 339, -125, 308, +-156, -77, -87, -282, 5, -83, 15, 112, +-17, -25, -2, -191, 54, 75, 82, 520, +-22, 461, -225, -216, -302, -775, -84, -548, +262, 226, 348, 763, 8, 580, -366, -64, +-299, -549, 86, -464, 240, 18, -22, 378, +-279, 301, -112, -30, 241, -187, 243, -86, +-129, 36, -366, 52, -169, 75, 182, 123, +190, 40, -97, -176, -195, -251, 42, 1, +226, 301, 3, 303, -358, 20, -317, -207, +122, -215, 408, -97, 172, 55, -273, 177, +-355, 201, -55, 61, 184, -79, 86, -57, +-112, 31, -109, -59, 58, -252, 140, -168, +-10, 271, -222, 583, -229, 305, -38, -305, +168, -624, 212, -364, 76, 165, -100, 504, +-249, 440, -251, 66, -60, -317, 199, -401, +284, -134, 49, 180, -235, 259, -222, 137, +4, 11, 110, -64, -60, -123, -171, -113, +25, 16, 259, 141, 167, 97, -200, -24, +-382, -43, -155, 29, 174, 24, 224, -68, +33, -70, -57, 57, 21, 150, 3, 75, +-200, -76, -347, -168, -119, -127, 323, 48, +508, 261, 191, 303, -348, 14, -565, -347, +-298, -364, 152, -1, 385, 281, 247, 193, +-25, 3, -141, 66, -113, 180, -90, -34, +-155, -402, -150, -396, -2, 74, 234, 430, +323, 342, 114, 63, -248, -53, -418, -95, +-245, -260, 115, -356, 291, -99, 168, 350, +-25, 502, -70, 234, -31, -164, -153, -351, +-286, -295, -124, -85, 279, 170, 462, 293, +160, 193, -370, -17, -537, -132, -220, -131, +233, -97, 419, -40, 270, 120, -41, 258, +-316, 130, -410, -215, -194, -372, 183, -45, +420, 413, 281, 416, -135, -118, -413, -548, +-277, -305, 97, 309, 290, 525, 130, 109, +-121, -346, -167, -320, -43, 30, 35, 201, +24, 112, 46, 37, 74, 51, -22, -33, +-216, -209, -213, -179, 95, 118, 318, 340, +164, 155, -190, -235, -307, -348, -86, -20, +127, 364, 118, 322, 32, -110, 35, -449, +36, -281, -147, 189, -302, 444, -100, 236, +320, -144, 453, -309, 42, -209, -498, 24, +-509, 215, 25, 260, 495, 37, 363, -269, +-124, -284, -333, 80, -135, 402, 105, 227, +35, -223, -132, -378, -48, -90, 201, 205, +230, 198, -80, 12, -328, -63, -161, -2, +160, 66, 239, 37, -23, -107, -247, -243, +-103, -164, 188, 226, 229, 528, -57, 276, +-282, -385, -158, -677, 112, -193, 197, 478, +53, 546, -82, 24, -66, -367, -36, -250, +-74, 68, -57, 153, 127, 28, 233, -43, +-1, 3, -327, 58, -301, 26, 146, -34, +464, -88, 237, -87, -281, 27, -488, 174, +-166, 143, 278, -92, 340, -238, 88, -67, +-148, 228, -151, 223, -43, -98, -24, -316, +-96, -143, -42, 186, 163, 296, 270, 146, +84, -88, -223, -231, -317, -244, -105, -77, +156, 185, 208, 321, 73, 174, -42, -142, +-43, -316, -33, -188, -64, 118, -84, 278, +-25, 148, 70, -127, 128, -225, 66, -58, +-72, 145, -154, 142, -73, -32, 91, -125, +175, -69, 46, 77, -179, 163, -239, 95, +-7, -129, 282, -290, 265, -143, -54, 213, +-330, 348, -256, 75, 75, -204, 294, -137, +215, 87, -50, 43, -259, -193, -255, -191, +-43, 116, 270, 344, 370, 232, 95, -29, +-339, -207, -462, -270, -104, -234, 353, -33, +433, 272, 73, 428, -308, 243, -286, -165, +9, -443, 177, -362, 75, 12, -92, 342, +-38, 356, 112, 83, 95, -193, -74, -252, +-155, -116, 4, 62, 138, 146, 30, 99, +-132, -39, -121, -95, 64, 1, 181, 119, +107, 68, -24, -122, -113, -182, -127, -37, +-114, 126, -41, 148, 109, 101, 238, 31, +215, -113, -10, -271, -274, -184, -316, 186, +-84, 417, 203, 165, 246, -300, 89, -373, +-3, -1, -16, 288, -84, 159, -200, -109, +-135, -124, 121, 27, 258, 65, 113, -54, +-117, -77, -147, 34, 13, 117, 80, 64, +13, -55, -50, -125, -39, -107, -9, 26, +23, 188, 63, 207, 56, -35, -18, -273, +-78, -203, -39, 119, 54, 287, 73, 82, +-16, -197, -109, -217, -71, 6, 96, 188, +224, 202, 126, 63, -174, -137, -383, -270, +-181, -174, 311, 91, 531, 242, 165, 155, +-386, 5, -531, 7, -124, 6, 359, -150, +431, -296, 109, -167, -200, 157, -222, 346, +-91, 316, -24, 131, 20, -172, 119, -502, +215, -496, 118, 26, -148, 618, -277, 611, +-70, -4, 223, -505, 215, -428, -79, -28, +-247, 200, -84, 200, 213, 151, 274, 91, +29, -66, -239, -274, -249, -310, -7, -43, +218, 366, 225, 512, 40, 152, -161, -452, +-186, -640, -48, -155, 103, 468, 181, 552, +122, 98, -14, -289, -167, -277, -207, -86, +-59, -6, 160, 39, 268, 159, 150, 211, +-102, 51, -228, -199, -132, -241, 68, -46, +150, 170, 85, 178, -9, 16, -49, -137, +-31, -126, 7, 21, 56, 136, 92, 122, +16, -23, -105, -157, -154, -165, -42, -12, +147, 175, 239, 231, 170, 77, -47, -164, +-301, -264, -314, -149, -3, 89, 387, 248, +426, 232, 43, 35, -366, -211, -399, -303, +-72, -128, 291, 161, 413, 277, 230, 143, +-151, -76, -421, -159, -316, -114, 106, -55, +416, -14, 290, 82, -67, 200, -239, 172, +-110, -52, 91, -309, 92, -297, -40, 1, +-77, 334, 34, 391, 141, 106, 95, -303, +-46, -496, -93, -262, 20, 255, 118, 625, +24, 422, -159, -241, -145, -742, 96, -532, +292, 193, 216, 716, -46, 567, -251, -30, +-235, -507, -26, -567, 220, -262, 298, 175, +122, 516, -157, 514, -273, 119, -96, -389, +182, -574, 276, -281, 126, 166, -97, 388, +-190, 275, -134, 45, 0, -109, 107, -158, +156, -148, 189, -104, 145, 3, -51, 114, +-294, 170, -327, 117, -28, 3, 314, -136, +373, -237, 128, -164, -85, 115, -71, 397, +-58, 324, -222, -153, -311, -607, -20, -482, +519, 177, 700, 738, 196, 609, -575, -115, +-826, -729, -241, -647, 567, 22, 763, 563, +205, 473, -415, -26, -423, -290, 17, -106, +262, 107, 64, -22, -146, -269, 25, -149, +292, 256, 190, 409, -212, 70, -384, -327, +-78, -295, 330, 44, 397, 220, 97, 85, +-209, -83, -260, -79, -131, 1, 44, -18, +220, -25, 298, 112, 173, 207, -130, -20, +-356, -393, -232, -367, 161, 196, 441, 672, +267, 390, -186, -399, -408, -787, -148, -314, +310, 449, 438, 683, 96, 237, -321, -333, +-354, -492, 4, -223, 321, 157, 293, 328, +37, 216, -145, -58, -111, -266, -1, -234, +36, 2, 28, 244, 62, 267, 116, 35, +89, -249, -27, -314, -96, -116, -52, 167, +51, 306, 117, 224, 98, -4, 26, -263, +-25, -375, -47, -188, -32, 220, 12, 451, +84, 232, 145, -216, 124, -376, -12, -113, +-168, 173, -168, 126, 51, -103, 266, -113, +240, 126, -26, 278, -239, 77, -146, -282, +152, -382, 312, -78, 112, 295, -239, 324, +-310, 25, 38, -211, 432, -120, 392, 64, +-86, 25, -444, -148, -286, -105, 186, 166, +394, 284, 196, 32, -78, -286, -151, -265, +-46, 47, 42, 275, 56, 199, 59, -57, +64, -244, 29, -234, -19, -45, 3, 193, +100, 320, 105, 202, -20, -125, -157, -414, +-102, -377, 155, 15, 322, 425, 175, 438, +-160, 22, -297, -357, -83, -307, 210, 20, +259, 163, 67, 19, -108, -99, -56, 27, +94, 188, 136, 110, -6, -116, -157, -212, +-114, -97, 129, 39, 332, 82, 218, 86, +-152, 73, -343, -16, -114, -131, 296, -110, +385, 74, 46, 168, -306, 0, -268, -215, +113, -161, 401, 125, 280, 262, -85, 67, +-296, -196, -178, -201, 86, 11, 243, 133, +223, 74, 86, -28, -84, -58, -187, -59, +-114, -24, 132, 67, 300, 118, 147, -5, +-152, -188, -227, -129, 28, 136, 261, 229, +159, -30, -94, -279, -120, -120, 103, 243, +231, 257, 46, -129, -208, -373, -183, -120, +98, 291, 319, 314, 226, -39, -25, -304, +-168, -178, -101, 115, 31, 202, 84, 14, +85, -194, 82, -156, 52, 80, 8, 250, +19, 154, 97, -94, 103, -239, -78, -177, +-224, -46, -91, 61, 280, 168, 438, 239, +134, 117, -303, -186, -357, -344, 31, -152, +386, 169, 295, 216, -69, 12, -288, -88, +-155, 20, 136, 68, 301, -84, 269, -177, +84, -15, -151, 200, -296, 143, -227, -122, +73, -254, 381, -79, 460, 169, 225, 206, +-206, 16, -484, -178, -355, -134, 130, 80, +552, 172, 486, -31, 11, -272, -376, -180, +-309, 196, 35, 376, 246, 98, 210, -277, +92, -288, 16, 11, -38, 155, -109, 6, +-97, -96, 71, 68, 270, 249, 250, 103, +-31, -278, -265, -440, -159, -123, 184, 371, +350, 510, 98, 121, -221, -407, -185, -509, +131, -106, 305, 324, 146, 344, -71, 40, +-109, -182, -64, -146, -37, -35, 41, 3, +220, 27, 305, 81, 105, 58, -209, -85, +-291, -178, -45, -61, 244, 166, 289, 242, +87, 79, -109, -186, -124, -310, 33, -197, +162, 69, 144, 310, 43, 313, -34, 52, +-76, -277, -112, -382, -32, -179, 206, 160, +390, 344, 252, 241, -151, -25, -397, -256, +-222, -288, 123, -141, 287, 94, 217, 252, +137, 249, 96, 77, 7, -172, -158, -312, +-248, -227, -114, 39, 170, 250, 344, 230, +266, 33, 44, -110, -104, -111, -103, -75, +-81, -106, -62, -95, 21, 90, 193, 271, +262, 160, 86, -183, -118, -310, -79, -12, +91, 313, 98, 154, -96, -312, -122, -421, +128, 62, 305, 553, 141, 399, -168, -227, +-179, -590, 113, -305, 284, 221, 80, 416, +-228, 159, -191, -176, 161, -232, 377, -53, +182, 104, -188, 90, -250, 5, 54, -44, +278, -43, 135, -68, -133, -79, -147, 21, +87, 156, 210, 153, 125, -34, 11, -174, +8, -114, -12, 24, -135, 18, -153, -83, +111, -38, 436, 188, 390, 311, -88, 53, +-508, -388, -390, -518, 191, -99, 624, 490, +415, 597, -175, 65, -485, -531, -183, -525, +294, 23, 379, 411, 41, 234, -218, -130, +-92, -147, 179, 124, 199, 154, 2, -208, +-120, -434, -52, -104, 85, 450, 135, 505, +128, -47, 85, -546, -5, -384, -122, 192, +-140, 444, 5, 127, 233, -276, 322, -252, +164, 52, -151, 179, -349, 13, -208, -107, +177, 5, 454, 145, 322, 50, -80, -177, +-320, -240, -179, -42, 123, 219, 243, 258, +93, 52, -69, -201, -60, -235, 87, -56, +179, 133, 115, 143, -21, 12, -139, -60, +-151, -42, -38, -32, 171, -93, 376, -89, +329, 75, -30, 233, -421, 139, -429, -158, +32, -309, 482, -119, 464, 189, 63, 226, +-255, -11, -221, -190, -38, -82, 54, 119, +98, 129, 195, -39, 249, -148, 50, -65, +-257, 44, -308, 41, 12, -36, 392, -35, +420, 50, 34, 116, -363, 57, -364, -83, +51, -162, 448, -108, 388, 30, -81, 95, +-444, 54, -242, -3, 308, 24, 577, 80, +216, 27, -392, -142, -571, -269, -119, -146, +461, 171, 596, 377, 209, 206, -230, -176, +-358, -356, -211, -154, -2, 132, 166, 151, +295, -14, 303, -59, 91, 67, -201, 92, +-273, -36, -75, -115, 140, -61, 141, -44, +73, -109, 112, -16, 158, 278, 3, 363, +-233, -46, -205, -509, 131, -419, 377, 142, +201, 463, -190, 215, -309, -159, -36, -185, +271, 8, 276, 28, 20, -109, -147, -103, +-79, 116, 60, 227, 62, 36, -28, -226, +-26, -219, 89, 60, 158, 254, 98, 149, +-14, -117, -46, -230, -37, -99, -70, 78, +-79, 104, 43, 19, 242, -6, 299, 53, +97, 57, -192, -87, -309, -198, -157, -98, +133, 127, 317, 204, 263, 48, 12, -113, +-204, -104, -196, -1, 9, 30, 216, 18, +218, 46, 3, 33, -217, -112, -214, -215, +83, -25, 373, 317, 316, 355, -71, -49, +-390, -434, -284, -362, 118, 56, 368, 333, +256, 248, -34, 7, -202, -129, -149, -112, +27, -61, 191, -39, 179, -16, 6, 52, +-178, 111, -168, 60, 61, -85, 275, -133, +240, 25, -16, 169, -233, 45, -208, -215, +13, -200, 210, 129, 219, 317, 69, 57, +-53, -317, -76, -285, -62, 116, -51, 362, +27, 164, 169, -187, 215, -297, 53, -121, +-188, 88, -239, 145, 0, 82, 268, 30, +263, 41, 10, 18, -208, -125, -175, -274, +27, -175, 172, 171, 137, 433, 24, 282, +-34, -162, -40, -445, -49, -302, -24, 63, +78, 281, 178, 234, 104, 63, -116, -88, +-224, -168, -42, -152, 253, -35, 288, 97, +-3, 109, -275, 14, -218, -41, 98, 7, +303, 37, 168, -38, -104, -102, -177, -14, +-26, 107, 110, 37, 80, -158, -8, -158, +-22, 129, 36, 342, 57, 145, -1, -262, +-44, -382, -35, -70, 3, 269, 56, 238, +107, -61, 90, -205, -11, -24, -124, 195, +-130, 124, -6, -151, 154, -244, 201, -19, +77, 210, -102, 118, -186, -126, -94, -135, +82, 107, 181, 214, 125, -10, -7, -256, +-82, -190, -76, 91, -43, 218, 32, 78, +109, -99, 120, -104, 32, 16, -102, 81, +-143, 12, -19, -88, 154, -69, 192, 59, +39, 127, -165, 1, -193, -184, 1, -150, +217, 118, 213, 301, 9, 155, -179, -176, +-175, -360, -29, -223, 124, 91, 203, 333, +161, 334, -28, 82, -235, -276, -243, -442, +13, -217, 296, 217, 288, 438, -11, 224, +-272, -170, -224, -320, 37, -107, 235, 129, +199, 96, -1, -79, -143, -92, -129, 101, +-26, 203, 75, 45, 104, -194, 71, -222, +25, -32, -21, 152, -71, 170, -65, 49, +-12, -64, 44, -110, 66, -77, 54, -20, +25, 40, 8, 95, -16, 123, -57, 32, +-55, -174, -7, -248, 58, -25, 79, 291, +42, 274, -6, -96, -25, -344, -20, -137, +0, 213, -1, 225, -9, -51, 8, -191, +26, -38, 9, 102, 0, 21, 26, -89, +53, 12, 46, 171, -33, 106, -109, -164, +-81, -301, 14, -97, 71, 224, 125, 303, +161, 81, 79, -160, -146, -198, -336, -77, +-235, 18, 156, 42, 440, 101, 293, 146, +-117, 47, -349, -166, -226, -230, 25, -19, +161, 223, 153, 194, 96, -66, 19, -227, +-86, -115, -162, 103, -94, 159, 90, 51, +200, -70, 81, -78, -127, -29, -174, -16, +-3, -2, 191, 45, 143, 107, -106, 57, +-219, -90, -69, -166, 149, -56, 196, 128, +58, 161, -108, 15, -141, -146, -57, -129, +35, 16, 93, 119, 89, 77, 41, -29, +-16, -80, -78, -42, -136, 9, -92, 18, +112, 38, 285, 83, 135, 59, -243, -116, +-394, -238, -49, -80, 408, 258, 402, 341, +-81, -9, -461, -369, -298, -292, 159, 109, +364, 307, 178, 124, -112, -115, -197, -109, +-65, 16, 42, 12, -1, -64, -49, -33, +36, 87, 156, 68, 129, -70, -66, -90, +-197, 84, -121, 191, 31, -3, 73, -280, +47, -247, 74, 120, 96, 369, 20, 203, +-123, -145, -175, -266, -87, -140, 45, -10, +132, 54, 157, 144, 96, 241, -31, 108, +-162, -209, -198, -373, -81, -162, 100, 197, +216, 343, 173, 184, -31, -99, -241, -261, +-200, -222, 71, 6, 242, 246, 107, 275, +-161, 17, -235, -275, -22, -304, 203, -29, +196, 295, 14, 337, -162, 72, -216, -253, +-88, -328, 154, -125, 267, 134, 86, 212, +-211, 122, -263, 23, 22, -32, 281, -76, +173, -136, -166, -126, -282, -17, -17, 142, +264, 209, 179, 90, -153, -147, -290, -260, +-34, -54, 303, 259, 251, 268, -141, -116, +-360, -408, -147, -188, 181, 299, 237, 423, +38, 39, -84, -330, -4, -256, 30, 94, +-127, 225, -215, 33, -26, -164, 248, -89, +266, 112, 5, 130, -229, -28, -199, -93, +0, 52, 122, 123, 60, -80, -39, -325, +-6, -176, 90, 296, 59, 506, -119, 125, +-197, -414, -8, -439, 243, 24, 174, 357, +-173, 169, -311, -192, -17, -209, 329, 115, +253, 303, -158, 64, -370, -286, -103, -299, +251, 52, 231, 305, -88, 165, -245, -149, +-44, -204, 224, 46, 177, 211, -125, 56, +-265, -213, -70, -216, 150, 63, 113, 284, +-52, 173, -34, -126, 143, -265, 124, -93, +-175, 163, -368, 185, -135, -18, 297, -162, +413, -77, 95, 87, -274, 122, -321, 23, +-68, -59, 180, -64, 169, -55, -32, -40, +-134, 14, -5, 97, 167, 120, 121, 46, +-148, -63, -299, -135, -77, -120, 245, -23, +252, 93, -23, 113, -198, 56, -84, 10, +94, 2, 53, -51, -114, -153, -109, -139, +85, 54, 215, 216, 97, 149, -151, -33, +-254, -114, -111, -84, 114, -75, 205, -59, +128, 75, -8, 239, -116, 179, -195, -132, +-182, -346, 22, -194, 292, 159, 325, 318, +1, 160, -391, -94, -390, -194, 31, -98, +400, 23, 319, 40, -60, -25, -318, -39, +-222, 72, 68, 198, 213, 133, 77, -161, +-110, -387, -97, -210, 91, 279, 152, 521, +-72, 160, -302, -424, -164, -517, 249, 2, +422, 492, 99, 378, -363, -118, -434, -378, +-57, -218, 321, 68, 332, 186, 49, 153, +-193, 62, -189, -73, -64, -170, 1, -105, +6, 81, 50, 160, 141, 44, 147, -100, +-37, -89, -252, 29, -218, 65, 43, -10, +233, -55, 166, 14, -36, 86, -150, 33, +-105, -109, -20, -134, 33, 38, 91, 200, +105, 127, 10, -131, -140, -249, -193, -84, +-48, 157, 171, 211, 229, 89, 59, -43, +-171, -120, -225, -159, -60, -129, 111, 33, +107, 215, 6, 229, -32, 37, 22, -170, +35, -202, -43, -71, -116, 82, -64, 114, +25, 43, 59, -29, 72, -19, 68, 37, +-2, 33, -114, -43, -156, -92, -34, -33, +125, 64, 126, 84, -13, 16, -84, -45, +-29, -31, 16, 17, -23, 6, -57, -66, +19, -76, 111, 51, 62, 199, -94, 148, +-163, -100, -54, -296, 106, -208, 120, 78, +3, 280, -61, 266, -12, 89, 17, -137, +-65, -328, -149, -317, -54, -26, 171, 358, +240, 448, 56, 118, -171, -298, -227, -398, +-122, -142, 15, 150, 117, 237, 181, 156, +163, 41, -20, -76, -249, -179, -275, -171, +-54, 7, 193, 209, 238, 180, 74, -55, +-97, -185, -130, -20, -67, 186, -24, 88, +-23, -233, 0, -320, 76, 39, 113, 447, +38, 390, -87, -113, -133, -492, -55, -348, +44, 118, 35, 368, -25, 191, 6, -105, +109, -139, 107, 56, -70, 98, -269, -117, +-212, -259, 113, -44, 361, 286, 235, 286, +-135, -40, -374, -256, -252, -136, 80, 40, +289, 23, 230, -16, 26, 128, -175, 254, +-267, 35, -174, -358, 66, -396, 286, 68, +260, 488, -38, 348, -311, -172, -266, -430, +35, -170, 255, 206, 172, 244, -74, 0, +-176, -140, -73, -41, 60, 78, 64, 28, +-20, -94, -41, -85, 29, 71, 52, 189, +-29, 109, -113, -114, -99, -272, 43, -174, +176, 125, 131, 327, -74, 195, -224, -123, +-159, -253, 62, -87, 205, 92, 108, 39, +-88, -82, -139, -7, -28, 184, 80, 170, +47, -80, -67, -261, -89, -156, -7, 103, +80, 207, 91, 108, 14, -44, -82, -120, +-127, -119, -73, -54, 48, 75, 147, 190, +112, 157, -42, -53, -168, -255, -154, -228, +1, 29, 162, 252, 162, 218, 9, -6, +-135, -167, -165, -127, -65, 8, 74, 79, +121, 42, 59, -33, -28, -73, -86, -19, +-56, 89, 32, 143, 48, 41, -18, -155, +-77, -216, -55, -42, 32, 187, 102, 208, +67, 37, -32, -126, -105, -154, -105, -81, +-27, 17, 81, 131, 103, 210, 3, 103, +-115, -191, -100, -354, 65, -134, 160, 294, +49, 430, -154, 84, -236, -345, -80, -375, +175, -10, 273, 289, 122, 243, -137, -8, +-291, -161, -192, -125, 80, -20, 235, 50, +139, 59, -53, 30, -135, -1, -55, 9, +30, 36, -22, -2, -88, -111, -4, -134, +147, 38, 142, 238, -57, 187, -235, -120, +-155, -325, 99, -152, 233, 220, 95, 346, +-143, 64, -212, -282, -63, -273, 107, 54, +147, 281, 61, 151, -73, -145, -151, -222, +-104, -17, 34, 196, 142, 168, 109, -44, +-77, -191, -176, -144, -50, 21, 133, 141, +135, 154, -41, 80, -194, -48, -133, -188, +83, -229, 211, -51, 137, 252, -59, 366, +-231, 89, -214, -336, 6, -417, 230, -36, +230, 365, -13, 332, -241, -35, -201, -265, +49, -156, 221, 42, 117, 78, -137, 7, +-240, 12, -72, 88, 166, 78, 229, -39, +66, -140, -166, -118, -240, 5, -107, 132, +81, 157, 178, 51, 142, -103, -24, -155, +-164, -57, -143, 68, -16, 108, 78, 56, +87, -5, 18, -35, -20, -52, -23, -55, +-67, -13, -110, 52, -36, 77, 117, 40, +178, -8, 41, -29, -153, -61, -197, -85, +-56, -32, 101, 108, 120, 173, 12, 40, +-64, -164, -18, -168, 50, 52, 29, 188, +-80, 42, -148, -182, -45, -125, 113, 149, +119, 217, 1, -41, -45, -245, 13, -69, +14, 225, -101, 155, -197, -203, -46, -290, +240, 84, 282, 403, -29, 184, -314, -309, +-239, -411, 108, 14, 289, 395, 91, 254, +-209, -165, -215, -311, 41, -72, 195, 181, +72, 150, -108, -29, -96, -85, 31, -4, +55, 41, -61, -3, -128, -41, -10, -19, +158, 18, 137, 31, -33, 31, -160, 21, +-160, -25, -33, -79, 135, -55, 184, 68, +68, 152, -127, 66, -246, -144, -129, -245, +141, -79, 268, 226, 124, 345, -135, 106, +-274, -281, -171, -411, 101, -121, 257, 312, +159, 422, -101, 86, -266, -319, -160, -356, +122, -1, 271, 309, 119, 241, -189, -69, +-311, -232, -103, -124, 201, 47, 284, 90, +91, 65, -166, 88, -225, 69, -90, -88, +24, -245, 63, -147, 83, 163, 93, 310, +64, 104, -34, -186, -174, -208, -207, -2, +-50, 110, 137, 24, 201, -55, 117, 18, +-43, 128, -137, 85, -121, -79, -92, -178, +-83, -105, 6, 47, 185, 140, 288, 121, +133, 40, -217, -25, -430, -71, -251, -123, +141, -137, 368, -37, 238, 166, -26, 288, +-156, 144, -152, -178, -126, -360, -80, -196, +28, 167, 190, 340, 219, 161, -21, -145, +-252, -249, -175, -75, 101, 134, 205, 155, +7, 0, -240, -137, -166, -109, 161, 57, +282, 197, 43, 137, -243, -108, -234, -301, +40, -185, 236, 174, 110, 373, -145, 156, +-210, -205, -18, -274, 164, -18, 120, 149, +-53, 14, -122, -140, -29, 0, 43, 256, +0, 212, -91, -113, -38, -309, 102, -160, +125, 74, -12, 126, -130, 64, -104, 75, +23, 125, 85, 22, -5, -189, -84, -245, +-11, -51, 90, 179, 66, 202, -52, 49, +-153, -64, -88, -60, 93, -28, 163, -31, +37, -32, -143, 8, -190, 49, -40, 58, +170, 48, 206, 21, 8, -49, -222, -130, +-207, -111, 35, 52, 221, 212, 122, 181, +-120, -48, -198, -248, -18, -213, 168, 12, +104, 213, -89, 228, -146, 64, -45, -131, +60, -208, 73, -115, -2, 70, -23, 171, +10, 95, -7, -66, -54, -120, -34, -15, +17, 96, 32, 65, -6, -53, -38, -92, +5, -7, 62, 66, 12, 16, -110, -52, +-113, -6, 51, 94, 182, 94, 91, -44, +-135, -166, -232, -125, -81, 38, 154, 170, +213, 168, 51, 34, -129, -141, -153, -217, +-67, -94, 29, 144, 48, 260, 26, 99, +55, -183, 96, -266, 6, -46, -162, 218, +-199, 222, -34, -29, 195, -223, 231, -142, +3, 87, -212, 173, -167, 51, 17, -94, +129, -92, 84, 20, -12, 69, -45, 9, +-44, -56, -64, -42, -65, 40, 49, 89, +172, 44, 112, -68, -126, -134, -269, -63, +-104, 87, 202, 158, 290, 62, 29, -89, +-274, -142, -238, -61, 83, 50, 254, 105, +103, 80, -155, 3, -206, -78, -7, -93, +179, -24, 107, 49, -81, 55, -128, 20, +-23, 20, 63, 37, 26, -23, -65, -122, +-34, -111, 111, 55, 118, 191, -63, 121, +-211, -76, -123, -161, 90, -66, 190, 32, +74, 34, -74, 17, -69, 77, 23, 106, +2, -15, -121, -202, -126, -199, 48, 52, +214, 276, 173, 200, -44, -90, -216, -253, +-167, -114, 16, 113, 109, 150, 63, -3, +0, -119, -15, -38, 10, 123, 19, 132, +-46, -35, -85, -186, -33, -127, 40, 74, +77, 169, 45, 77, -47, -68, -98, -92, +-34, -20, 76, 25, 108, 13, 30, 24, +-99, 52, -156, 0, -82, -111, 73, -118, +187, 53, 156, 211, -24, 138, -234, -110, +-268, -228, -26, -71, 273, 160, 293, 171, +-5, -39, -316, -182, -296, -79, 67, 137, +369, 197, 224, 44, -191, -156, -391, -194, +-156, -48, 248, 139, 373, 188, 66, 51, +-285, -133, -296, -160, -17, 8, 214, 154, +200, 106, 9, -59, -121, -120, -112, -38, +-63, 18, -33, -21, 45, -2, 162, 145, +162, 212, -43, -3, -268, -319, -239, -331, +68, 28, 327, 374, 221, 323, -137, -29, +-319, -278, -142, -216, 132, 7, 216, 127, +71, 113, -103, 59, -106, 7, -19, -58, +0, -125, -32, -93, 9, 43, 100, 176, +114, 156, -9, -16, -183, -191, -184, -198, +13, -11, 204, 191, 173, 212, -25, 12, +-176, -195, -135, -173, 32, 52, 122, 200, +44, 85, -60, -129, -44, -157, 54, 8, +61, 117, -51, 48, -136, -40, -47, 12, +131, 83, 158, -12, -12, -186, -149, -140, +-94, 128, 36, 266, 69, 60, 6, -231, +-28, -203, 46, 101, 89, 273, -30, 68, +-172, -232, -114, -250, 84, 40, 178, 274, +70, 194, -114, -57, -121, -196, 42, -118, +114, 22, -40, 65, -181, 15, -74, 7, +193, 78, 272, 109, 32, -7, -286, -187, +-306, -206, -16, 2, 259, 226, 254, 212, +60, -4, -112, -167, -173, -128, -147, -15, +-66, 21, 65, 32, 208, 99, 214, 124, +-1, -26, -233, -215, -224, -159, -5, 131, +170, 270, 125, 34, -44, -256, -82, -183, +50, 156, 105, 266, -35, -13, -168, -276, +-95, -144, 101, 182, 165, 246, 18, -7, +-131, -215, -68, -128, 97, 71, 124, 112, +-40, 16, -170, -36, -102, 0, 82, 35, +176, 8, 77, -46, -93, -80, -119, -59, +-7, 49, 81, 159, 47, 115, -53, -99, +-94, -239, 0, -81, 110, 207, 98, 226, +-24, -79, -106, -294, -73, -102, 24, 259, +74, 278, 20, -81, -50, -334, -12, -154, +73, 205, 67, 255, -45, -19, -139, -207, +-79, -75, 85, 129, 173, 93, 69, -93, +-102, -118, -151, 61, -51, 149, 82, 2, +122, -157, 38, -78, -65, 118, -80, 154, +-15, -34, 33, -184, 31, -94, 18, 105, +8, 182, 3, 48, -19, -117, -64, -141, +-37, -24, 56, 83, 95, 78, 14, 13, +-75, -11, -72, 20, 18, 1, 78, -93, +25, -140, -65, -4, -55, 198, 41, 224, +79, -3, 16, -245, -62, -226, -61, 20, +10, 207, 51, 144, 9, -38, -38, -109, +17, -33, 92, 37, 45, 12, -82, -56, +-148, -45, -66, 37, 106, 85, 180, 56, +78, -27, -64, -85, -127, -66, -98, 12, +-21, 69, 59, 42, 93, -27, 79, -34, +25, 35, -57, 60, -111, -33, -54, -136, +50, -68, 93, 105, 38, 163, -50, 31, +-67, -121, 22, -114, 94, 2, 38, 72, +-73, 40, -103, 3, -36, -7, 62, -25, +102, -37, 57, 6, -29, 76, -75, 59, +-57, -57, 0, -127, 38, -27, 25, 101, +-13, 90, -2, -30, 60, -62, 65, 37, +-24, 73, -134, -56, -148, -179, 0, -69, +201, 183, 230, 266, 31, 38, -214, -241, +-253, -268, -57, -24, 188, 211, 227, 218, +42, 35, -137, -147, -122, -167, 10, -38, +84, 105, 21, 117, -84, 11, -66, -83, +83, -58, 161, 29, 48, 44, -140, -9, +-185, -37, -40, 22, 150, 68, 173, 18, +24, -80, -119, -96, -120, -6, -30, 91, +70, 98, 113, 19, 57, -55, -53, -92, +-107, -71, -59, 11, 52, 116, 110, 134, +38, -2, -86, -178, -98, -190, 23, 29, +131, 252, 102, 223, -46, -65, -163, -309, +-121, -243, 54, 63, 177, 294, 138, 223, +-13, -36, -145, -210, -149, -140, -30, 40, +81, 111, 101, 18, 58, -69, 14, -24, +-16, 75, -50, 84, -95, -16, -78, -86, +50, -51, 165, 26, 108, 21, -71, -20, +-159, 2, -60, 70, 86, 57, 97, -55, +-28, -107, -92, -9, -3, 123, 101, 95, +56, -62, -61, -146, -97, -52, -29, 77, +49, 84, 66, 18, 35, 8, 11, 42, +-5, -8, -60, -123, -88, -147, -18, -2, +100, 158, 112, 168, 6, 43, -110, -77, +-106, -103, 6, -73, 97, -22, 76, 38, +13, 77, -29, 52, -70, -14, -100, -50, +-35, -32, 120, 14, 224, 35, 114, 27, +-172, -10, -342, -60, -159, -76, 220, -10, +393, 92, 170, 109, -202, 10, -340, -94, +-128, -60, 159, 36, 217, 32, 58, -77, +-75, -93, -67, 53, -3, 180, 9, 94, +-18, -113, -18, -153, 41, -8, 58, 103, +-15, 20, -66, -105, -18, -71, 64, 86, +71, 160, -14, 76, -93, -55, -61, -140, +37, -159, 84, -92, 48, 98, -1, 278, +-20, 213, -34, -104, -47, -357, -27, -231, +19, 147, 74, 346, 66, 160, 0, -164, +-55, -264, -49, -79, -27, 136, -4, 157, +24, 28, 56, -80, 59, -60, 19, 20, +-66, 47, -109, -27, -34, -95, 93, -38, +138, 101, 56, 150, -89, 16, -152, -163, +-63, -166, 92, 25, 161, 174, 101, 112, +-37, -61, -158, -134, -155, -69, -14, 24, +152, 81, 186, 103, 61, 65, -105, -80, +-163, -206, -72, -128, 61, 140, 95, 282, +46, 86, -2, -212, -6, -235, -2, 37, +-30, 216, -52, 61, -7, -167, 77, -118, +83, 124, -37, 190, -112, -37, -43, -224, +97, -102, 134, 160, 7, 210, -129, -18, +-115, -201, 3, -127, 87, 81, 80, 167, +38, 74, -7, -62, -45, -121, -63, -82, +-44, 12, 0, 104, 55, 99, 76, 5, +31, -76, -27, -67, -50, -7, -41, 10, +-3, -12, 37, 13, 42, 82, 16, 71, +-5, -49, -22, -140, -26, -79, 7, 50, +41, 98, 37, 55, -8, 15, -71, 7, +-81, -50, 23, -123, 151, -87, 141, 80, +-38, 170, -210, 56, -173, -110, 71, -99, +228, 65, 110, 108, -111, -49, -139, -156, +18, -19, 110, 164, -3, 120, -134, -95, +-76, -158, 123, 20, 197, 178, 38, 79, +-157, -150, -169, -202, -18, -30, 124, 155, +139, 179, 44, 57, -64, -81, -110, -155, +-77, -120, 19, 9, 123, 149, 113, 157, +-21, 5, -145, -148, -120, -133, 33, 22, +153, 139, 112, 99, -24, -42, -108, -120, +-76, -81, -11, 28, 37, 85, 63, 58, +66, -10, 17, -38, -61, -13, -87, 7, +-10, -10, 85, -24, 73, -2, -38, 4, +-103, -27, -11, -33, 122, 74, 112, 182, +-48, 80, -179, -209, -104, -355, 104, -99, +195, 315, 67, 409, -104, 63, -131, -303, +-15, -305, 76, -29, 39, 152, -26, 106, +-1, 35, 59, 62, 30, 54, -61, -106, +-95, -223, -23, -87, 82, 177, 105, 247, +36, 39, -44, -174, -91, -153, -84, -5, +-14, 59, 93, 38, 158, 47, 78, 82, +-100, 13, -196, -131, -94, -157, 104, 12, +182, 175, 65, 126, -93, -55, -99, -145, +8, -55, 63, 73, 10, 93, -51, 16, +-35, -57, 34, -77, 62, -45, 26, 36, +-8, 107, -16, 95, -29, -16, -54, -118, +-54, -112, 15, -15, 115, 82, 140, 101, +26, 58, -140, -27, -186, -102, -55, -88, +128, 26, 176, 125, 54, 70, -80, -91, +-99, -138, -24, 11, 15, 169, -17, 116, +-9, -95, 62, -175, 106, -39, 32, 109, +-110, 86, -143, -30, -7, -38, 129, 55, +103, 57, -34, -84, -107, -151, -32, -4, +75, 195, 66, 165, -37, -80, -87, -238, +-19, -115, 77, 143, 76, 231, -9, 56, +-72, -164, -48, -191, 25, -30, 60, 133, +31, 144, -23, 28, -36, -74, -15, -78, +-2, -27, -1, 4, 16, 18, 51, 44, +43, 64, -26, 1, -92, -96, -74, -77, +36, 51, 129, 126, 94, 30, -27, -126, +-102, -130, -78, 34, -3, 145, 52, 79, +68, -50, 55, -82, 3, -24, -65, 0, +-83, -21, -15, 4, 83, 67, 92, 67, +-7, -18, -88, -88, -61, -47, 34, 39, +91, 46, 42, 0, -46, -17, -77, 9, +-42, 9, 18, -21, 71, -24, 82, 25, +30, 54, -65, 5, -120, -62, -70, -55, +52, 11, 141, 39, 114, 27, -8, 28, +-126, 36, -147, -18, -44, -108, 106, -95, +175, 46, 78, 163, -94, 85, -156, -88, +-49, -136, 97, -21, 101, 76, -22, 39, +-78, -30, 6, -4, 87, 54, 28, 21, +-106, -62, -109, -72, 55, 11, 187, 57, +90, 23, -128, -14, -198, 3, -36, 19, +165, -14, 161, -40, -21, -20, -143, 17, +-72, 24, 65, 19, 74, 33, -34, 14, +-79, -51, 22, -79, 138, -3, 82, 90, +-119, 65, -207, -61, -40, -92, 193, 34, +210, 125, -7, 21, -199, -140, -156, -111, +48, 73, 148, 160, 68, 23, -29, -124, +-30, -71, 8, 68, -23, 67, -76, -73, +-22, -111, 114, 47, 142, 180, -12, 68, +-170, -147, -130, -182, 76, -5, 189, 157, +77, 115, -115, -29, -156, -92, -8, -46, +135, 2, 112, 11, -23, 5, -98, 15, +-59, 35, 20, 38, 47, 5, 19, -61, +1, -104, 11, -42, 3, 106, -35, 181, +-49, 70, 9, -130, 78, -195, 55, -76, +-52, 58, -99, 97, 2, 103, 130, 115, +98, 33, -77, -173, -177, -289, -66, -102, +137, 233, 183, 329, 24, 72, -129, -217, +-107, -213, 19, -5, 81, 103, 28, 29, +-31, -37, -13, 14, 42, 60, 38, 6, +-11, -52, -40, 5, -41, 75, -32, -11, +-7, -172, 54, -137, 115, 130, 90, 301, +-44, 125, -182, -208, -158, -304, 37, -75, +216, 180, 191, 197, -20, 43, -194, -76, +-159, -81, 22, -53, 144, -39, 88, 11, +-35, 90, -59, 101, 16, 11, 47, -101, +-22, -136, -91, -44, -27, 94, 113, 149, +129, 71, -24, -73, -165, -140, -115, -63, +66, 62, 174, 80, 97, 10, -57, -24, +-133, 17, -98, 32, -7, -39, 88, -88, +136, -11, 96, 99, -35, 74, -153, -71, +-143, -128, 0, -2, 140, 145, 143, 119, +39, -58, -67, -169, -111, -97, -78, 60, +18, 138, 107, 91, 104, -19, -11, -109, +-127, -115, -100, -5, 69, 127, 174, 142, +68, -5, -129, -166, -188, -153, -42, 26, +146, 166, 176, 131, 52, -2, -76, -87, +-120, -100, -98, -87, -35, -31, 64, 92, +153, 183, 137, 101, -10, -113, -168, -218, +-173, -79, -10, 125, 151, 156, 145, 19, +14, -94, -93, -75, -80, -9, 7, 18, +57, 36, 20, 73, -21, 51, -13, -58, +15, -147, 24, -95, 6, 60, -10, 158, +-11, 119, -13, -5, -22, -106, 14, -131, +80, -64, 76, 35, -41, 85, -161, 59, +-110, 8, 113, 2, 267, 19, 120, -19, +-190, -116, -305, -126, -81, 23, 228, 190, +269, 174, 21, -29, -211, -189, -168, -135, +53, 44, 166, 121, 63, 37, -94, -52, +-127, -22, -12, 44, 123, 15, 139, -63, +22, -52, -116, 56, -159, 95, -66, -15, +96, -130, 188, -78, 111, 91, -64, 160, +-175, 36, -125, -126, 38, -131, 165, 3, +119, 108, -45, 63, -139, -56, -62, -79, +87, 29, 132, 104, 0, 25, -144, -119, +-98, -118, 86, 56, 166, 172, 33, 49, +-137, -157, -124, -145, 50, 93, 146, 223, +38, 44, -109, -214, -87, -193, 52, 72, +111, 219, 14, 74, -93, -136, -65, -119, +54, 68, 103, 133, 18, -6, -79, -146, +-84, -92, -21, 72, 52, 130, 87, 39, +75, -56, 12, -33, -79, 26, -132, -3, +-90, -81, 50, -88, 166, 30, 155, 151, +29, 134, -126, -12, -198, -148, -117, -148, +54, -22, 198, 100, 203, 113, 43, 26, +-168, -61, -241, -60, -99, 9, 126, 55, +230, 19, 131, -57, -84, -68, -208, -1, +-116, 72, 85, 65, 182, -4, 90, -64, +-71, -62, -140, 7, -60, 61, 61, 36, +90, -36, 48, -65, -7, -4, -45, 61, +-55, 43, -28, -24, 20, -27, 50, 30, +39, 25, -17, -61, -35, -104, 9, 3, +33, 149, -11, 137, -60, -30, -41, -151, +33, -111, 89, 0, 62, 65, -10, 77, +-61, 79, -70, 32, -58, -81, -10, -157, +91, -72, 142, 121, 67, 184, -86, 31, +-165, -155, -83, -142, 73, 35, 136, 126, +59, 37, -41, -76, -51, -46, -3, 67, +25, 78, -2, -43, -60, -127, -57, -69, +35, 58, 123, 127, 117, 82, -9, -10, +-153, -92, -156, -118, -4, -59, 149, 45, +131, 118, -5, 90, -91, 15, -54, -42, +27, -74, 22, -90, -40, -57, -37, 61, +55, 156, 97, 97, 16, -87, -83, -174, +-86, -46, 18, 123, 93, 119, 53, -41, +-38, -128, -69, -39, -12, 62, 42, 54, +39, 0, 5, 6, -14, 40, -4, -7, +-8, -104, -30, -109, -21, 32, 27, 164, +62, 119, 40, -58, -28, -156, -69, -77, +-34, 72, 33, 114, 44, 20, -14, -70, +-38, -61, 19, 11, 73, 52, 27, 34, +-77, -3, -100, -15, 11, -23, 117, -46, +74, -54, -48, 3, -90, 112, -8, 139, +66, 6, 34, -185, -43, -208, -41, 6, +29, 244, 48, 223, -11, -50, -53, -249, +-10, -159, 51, 87, 39, 187, -32, 73, +-54, -74, 4, -90, 48, -17, 18, 17, +-39, 11, -31, 22, 26, 47, 43, 28, +-7, -28, -55, -65, -35, -47, 35, 8, +74, 59, 26, 78, -51, 25, -73, -69, +-20, -106, 50, -16, 65, 106, 12, 95, +-44, -43, -36, -121, 3, -25, 11, 110, +-3, 90, 1, -58, 26, -122, 39, -25, +-1, 80, -51, 60, -41, -20, 23, -38, +56, 4, 27, 0, -28, -44, -45, -24, +-10, 74, 29, 105, 34, -8, 6, -129, +-27, -96, -49, 50, -33, 117, 37, 38, +87, -42, 54, -21, -52, 28, -121, -13, +-69, -79, 51, -46, 115, 66, 68, 122, +-31, 54, -68, -67, -52, -103, -29, -52, +3, 21, 48, 71, 84, 75, 53, 13, +-47, -74, -123, -88, -81, 4, 40, 100, +128, 77, 89, -37, -20, -107, -93, -52, +-76, 32, -6, 54, 48, 28, 59, 18, +40, 26, 12, -14, -32, -81, -80, -83, +-73, 6, 18, 94, 127, 85, 133, 1, +-11, -54, -170, -44, -157, -10, 23, -9, +178, -20, 149, 12, -17, 74, -151, 92, +-127, -4, -22, -132, 60, -143, 121, 8, +128, 183, 28, 176, -137, -42, -219, -228, +-91, -161, 156, 78, 258, 207, 98, 99, +-134, -72, -189, -100, -74, -18, 42, -9, +72, -69, 63, -22, 69, 145, 32, 195, +-89, -19, -144, -262, -39, -184, 127, 123, +149, 252, -9, 33, -150, -202, -95, -114, +71, 147, 134, 172, 32, -76, -89, -222, +-78, -46, 23, 188, 72, 151, 6, -87, +-64, -192, -26, -35, 62, 151, 79, 125, +3, -38, -86, -116, -85, -48, 4, 35, +67, 30, 50, -11, 14, -8, -10, 49, +-8, 60, -12, -8, -33, -85, -26, -93, +25, -27, 53, 55, 15, 83, -27, 57, +-22, 27, 11, -11, 18, -66, -16, -114, +-42, -71, -5, 69, 46, 164, 25, 96, +-22, -75, -27, -141, 8, -27, 37, 86, +9, 34, -45, -83, -41, -58, 11, 99, +38, 149, 24, -23, -1, -191, -4, -122, +-1, 111, -7, 200, -28, 48, -26, -140, +13, -147, 18, -5, 7, 94, 16, 88, +30, 40, 9, 1, -43, -62, -74, -105, +-25, -59, 57, 58, 69, 125, 6, 68, +-49, -32, -31, -67, 18, -31, 26, 4, +-12, 4, -51, -6, -30, -6, 26, 16, +67, 43, 73, 49, -3, 0, -104, -87, +-112, -105, -2, 4, 133, 126, 136, 103, +-28, -49, -165, -134, -110, -39, 67, 97, +160, 99, 70, -13, -81, -79, -130, -47, +-49, -5, 50, -1, 76, 21, 55, 80, +20, 80, -38, -28, -76, -134, -54, -95, +3, 49, 65, 113, 69, 28, 13, -61, +-38, -22, -50, 64, -28, 50, 13, -54, +29, -104, 10, -37, -7, 51, 10, 70, +24, 46, -6, 20, -46, -25, -47, -87, +22, -93, 96, 19, 63, 136, -39, 89, +-97, -86, -75, -170, 14, -39, 93, 173, +87, 201, 28, -14, -60, -229, -117, -209, +-68, 21, 58, 214, 130, 184, 58, -5, +-74, -140, -98, -113, -1, -4, 72, 46, +27, 11, -59, -4, -33, 52, 57, 84, +58, -11, -37, -142, -94, -125, -10, 60, +127, 190, 108, 87, -59, -133, -171, -190, +-99, -17, 84, 161, 168, 137, 80, -29, +-57, -117, -106, -56, -65, 31, -8, 23, +29, -20, 56, 1, 57, 50, 22, 39, +-30, -32, -73, -51, -42, -4, 30, 21, +48, -13, 27, -40, -5, 5, -23, 62, +-18, 44, -10, -29, 3, -50, 42, -4, +55, 24, 7, -27, -79, -65, -111, -9, +-26, 88, 109, 108, 180, 13, 75, -94, +-128, -112, -218, -39, -116, 41, 93, 72, +217, 64, 130, 38, -59, 10, -163, -44, +-125, -107, -4, -101, 102, 17, 118, 158, +50, 155, -69, -20, -127, -186, -61, -132, +74, 77, 129, 172, 22, 33, -106, -130, +-87, -87, 33, 89, 89, 127, 3, -36, +-90, -155, -21, -46, 99, 143, 83, 136, +-58, -55, -157, -157, -71, -52, 107, 79, +161, 62, 50, -19, -96, 4, -133, 81, +-49, 27, 57, -137, 97, -173, 43, 18, +-33, 209, -46, 152, -23, -61, 1, -156, +4, -56, -7, 57, 14, 39, 33, -35, +-2, -21, -34, 57, -22, 75, 8, -2, +21, -79, -9, -70, -20, 0, 10, 61, +31, 53, 0, 4, -45, -43, -15, -50, +41, -18, 40, 17, -12, 42, -45, 48, +-20, 26, 30, -55, 11, -131, -28, -90, +11, 86, 56, 225, 29, 126, -65, -139, +-114, -267, -30, -92, 100, 168, 120, 203, +17, 9, -89, -125, -89, -62, -26, 45, +13, 22, 19, -55, 25, -17, 62, 92, +57, 83, -42, -73, -123, -158, -86, -33, +38, 150, 130, 144, 73, -38, -59, -162, +-103, -80, -33, 82, 56, 118, 60, 10, +-20, -86, -67, -67, -33, 34, 33, 95, +51, 45, 8, -66, -29, -117, -26, -45, +1, 90, 13, 138, -19, 35, -41, -107, +-15, -127, 22, -10, 49, 107, 40, 101, +-17, 10, -67, -74, -84, -94, -45, -49, +51, 34, 120, 112, 82, 104, -42, -14, +-132, -134, -92, -130, 32, -9, 104, 103, +46, 110, -66, 44, -74, -27, 5, -75, +67, -97, 57, -50, -31, 65, -93, 128, +-72, 57, -9, -76, 72, -117, 114, -18, +39, 93, -91, 72, -146, -31, -58, -72, +74, -17, 107, 30, 26, 13, -67, -6, +-57, 18, 7, 43, 10, 0, -18, -76, +-14, -73, 13, 22, 30, 95, -1, 53, +-50, -39, -42, -66, 1, -15, 40, 26, +38, 13, -5, -17, -57, 0, -69, 31, +-20, 18, 49, -32, 59, -42, 2, 9, +-57, 60, -57, 32, 4, -49, 26, -76, +-3, -11, -25, 77, -16, 77, 12, -12, +15, -83, -20, -51, -34, 31, -17, 62, +-5, 19, 4, -35, 5, -33, 0, 2, +-10, 16, -24, 15, -27, 24, -7, 10, +9, -31, -2, -64, -27, -18, -28, 88, +1, 110, 17, -8, 3, -130, -42, -99, +-56, 47, 0, 123, 50, 47, 38, -66, +-22, -65, -77, 12, -61, 25, 15, -38, +60, -40, 32, 64, -25, 119, -52, 5, +-40, -161, -19, -143, -2, 64, 10, 203, +28, 97, 19, -111, -45, -156, -84, -16, +-47, 105, 26, 70, 71, -37, 30, -62, +-53, -4, -79, 40, -53, 38, 0, 13, +37, -12, 28, -45, 3, -67, -34, -20, +-54, 77, -34, 114, -4, 37, 20, -94, +4, -128, -38, -33, -25, 78, 17, 106, +30, 30, -15, -57, -86, -69, -78, -17, +22, 28, 93, 17, 51, -12, -69, 7, +-118, 47, -53, 39, 44, -46, 63, -104, +-1, -42, -55, 87, -63, 129, -41, 29, +-2, -92, 44, -94, 42, -1, -8, 44, +-84, 12, -114, -2, -34, 45, 60, 69, +81, -19, 33, -130, -39, -109, -80, 50, +-80, 158, -45, 77, 8, -80, 57, -129, +54, -27, -2, 91, -61, 90, -79, -11, +-48, -91, -15, -65, 6, 25, 15, 80, +15, 55, 9, -16, -17, -52, -41, -39, +-59, -14, -62, -4, -19, 4, 39, 49, +62, 73, 16, 13, -73, -87, -100, -110, +-44, 0, 32, 105, 54, 75, -10, -32, +-72, -67, -64, 7, -22, 60, 24, 0, +26, -79, 0, -49, -30, 66, -59, 103, +-70, 6, -36, -98, 19, -80, 51, 28, +40, 85, -18, 37, -79, -31, -98, -40, +-66, -9, 0, 0, 58, -18, 67, -8, +12, 46, -51, 73, -93, 19, -99, -76, +-53, -115, 21, -42, 72, 87, 66, 133, +-1, 47, -88, -70, -114, -96, -84, -23, +-14, 29, 57, 4, 76, -23, 41, 32, +-50, 104, -136, 56, -130, -96, -16, -173, +110, -54, 115, 127, -24, 157, -166, 18, +-152, -98, 4, -74, 141, 9, 96, 27, +-82, -11, -184, -1, -113, 55, 45, 51, +121, -40, 58, -97, -68, -26, -130, 86, +-97, 89, -17, -29, 58, -108, 70, -46, +2, 79, -93, 103, -117, -6, -48, -107, +46, -74, 60, 50, -19, 115, -78, 50, +-78, -64, -23, -116, 26, -50, 13, 63, +-13, 107, -33, 52, -44, -48, -59, -88, +-42, -56, -6, 13, 27, 62, 27, 64, +-33, 30, -79, -29, -77, -75, -22, -69, +25, 7, 21, 83, -28, 85, -62, 5, +-38, -75, 1, -73, 3, -2, -40, 47, +-75, 39, -43, -5, 24, -24, 46, 2, +-9, 30, -78, 15, -103, -27, -49, -57, +28, -36, 58, 36, 24, 80, -63, 50, +-114, -31, -81, -78, 3, -47, 69, 13, +43, 40, -54, 29, -108, 13, -72, 3, +-2, -23, 46, -50, 13, -23, -51, 47, +-66, 65, -38, -12, -3, -86, 0, -42, +-26, 78, -49, 101, -37, -19, -15, -128, +-2, -73, -3, 80, -26, 126, -50, 15, +-66, -94, -45, -70, 1, 28, 36, 52, +1, -1, -74, -15, -95, 39, -42, 60, +45, -29, 45, -126, -52, -86, -116, 69, +-70, 161, 37, 79, 78, -79, 8, -136, +-97, -52, -118, 56, -69, 59, 9, -15, +57, -20, 42, 60, -9, 97, -95, -6, +-147, -162, -96, -161, 39, 39, 131, 221, +61, 180, -107, -52, -194, -213, -93, -137, +73, 56, 108, 145, -4, 68, -123, -34, +-112, -49, -12, -9, 50, -13, 8, -35, +-48, -1, -59, 66, -40, 66, -19, -31, +-28, -107, -22, -54, -1, 80, -4, 125, +-48, 27, -79, -108, -54, -130, 8, -8, +46, 122, -8, 125, -81, 3, -101, -114, +-40, -107, 37, 6, 50, 85, -16, 63, +-94, -7, -95, -34, -39, -10, 25, -4, +26, -27, -19, -18, -42, 41, -52, 76, +-55, 14, -55, -79, -27, -85, 16, 12, +29, 93, -18, 57, -68, -27, -62, -46, +-42, -9, -38, -2, -36, -45, -6, -32, +58, 63, 52, 134, -73, 55, -186, -116, +-138, -182, 29, -53, 147, 136, 83, 171, +-81, 38, -157, -106, -99, -122, 1, -31, +36, 50, 7, 62, -25, 31, -25, 3, +-29, -25, -53, -42, -59, -30, -41, 18, +-9, 63, 10, 39, 0, -41, -25, -84, +-49, -29, -68, 71, -59, 101, -10, 16, +15, -92, 10, -103, -26, -8, -62, 98, +-58, 104, -39, 8, -30, -87, -16, -96, +16, -23, 25, 62, -20, 94, -106, 46, +-136, -36, -40, -83, 86, -56, 112, 19, +-9, 69, -156, 43, -161, -27, -27, -52, +95, -15, 80, 31, -32, 28, -123, -19, +-90, -41, -9, -2, 33, 38, 14, 33, +-38, -7, -70, -38, -63, -32, -20, -7, +6, 33, 17, 57, -5, 34, -63, -33, +-84, -96, -56, -75, 8, 35, 43, 129, +4, 99, -68, -25, -86, -119, -38, -98, +8, 1, 5, 74, -45, 74, -46, 29, +-2, -13, 12, -39, -28, -57, -85, -39, +-78, 16, 2, 63, 64, 55, 21, -7, +-65, -62, -105, -52, -67, 11, 12, 54, +33, 30, -1, -23, -44, -34, -48, 0, +-43, 37, -42, 16, -34, -43, -8, -49, +35, 15, 5, 82, -73, 55, -108, -41, +-62, -87, 40, -39, 69, 46, -12, 63, +-97, 12, -80, -30, -8, -15, 25, 18, +-20, 4, -67, -36, -34, -41, 26, 6, +20, 63, -46, 62, -92, 3, -63, -61, +0, -68, 23, -20, -1, 39, -13, 63, +-18, 30, -36, -20, -68, -49, -83, -27, +-35, 13, 47, 35, 73, 23, 0, -8, +-90, -37, -119, -39, -56, 9, 27, 63, +48, 65, 0, -3, -50, -96, -53, -103, +-33, 2, -21, 114, -24, 117, -5, 11, +4, -90, -27, -99, -61, -45, -69, 23, +-16, 75, 56, 87, 43, 55, -42, -36, +-117, -121, -102, -118, -16, 5, 71, 129, +63, 143, -19, 30, -84, -113, -96, -141, +-42, -34, 9, 102, 15, 119, -10, 9, +-25, -94, -18, -74, -3, 37, -16, 83, +-67, 7, -75, -85, -19, -58, 51, 65, +53, 109, -30, 6, -109, -114, -83, -99, +16, 34, 66, 124, 18, 64, -76, -52, +-98, -84, -30, -31, 44, 19, 44, 23, +-19, 12, -70, 27, -69, 41, -31, -2, +-1, -67, 5, -68, -1, 5, -13, 74, +-17, 67, -26, -14, -33, -69, -38, -38, +-34, 27, -24, 51, -3, 8, 22, -40, +12, -25, -12, 21, -64, 41, -82, 0, +-50, -32, 4, -16, 61, 8, 52, 10, +-22, -6, -88, 0, -88, 24, -38, 16, +21, -32, 35, -52, 8, 2, -11, 69, +-39, 61, -64, -31, -55, -87, -13, -32, +33, 59, 31, 67, -27, -14, -77, -64, +-41, -19, 21, 51, 30, 37, -18, -40, +-62, -65, -42, 6, 10, 76, 15, 49, +-28, -45, -38, -83, 1, -23, 30, 58, +-11, 63, -81, -6, -65, -61, 13, -38, +68, 20, 28, 39, -58, 7, -78, -28, +-19, -22, 18, 12, -7, 31, -36, 19, +-36, -8, 15, -37, 33, -38, -17, -6, +-60, 45, -44, 70, -7, 28, 3, -55, +-10, -99, -24, -47, 3, 56, 28, 110, +-7, 59, -74, -29, -87, -81, -30, -65, +52, -20, 83, 24, 24, 62, -58, 76, +-97, 40, -78, -53, -12, -122, 45, -83, +64, 44, 28, 137, -47, 104, -97, -19, +-85, -109, -5, -99, 73, -14, 77, 63, +-5, 79, -83, 41, -102, -19, -51, -60, +40, -50, 78, 9, 35, 57, -33, 33, +-77, -31, -83, -52, -19, -7, 47, 54, +56, 48, 19, -16, -44, -58, -79, -34, +-46, 23, 9, 43, 25, 15, 12, -15, +-11, -12, -18, 5, -8, 9, -19, -8, +-45, -29, -28, -25, 16, 12, 55, 50, +26, 50, -50, -2, -89, -69, -53, -74, +19, -6, 61, 72, 38, 86, -9, 20, +-32, -53, -60, -78, -64, -55, -22, -4, +45, 60, 85, 94, 52, 64, -61, -31, +-129, -129, -73, -117, 28, 13, 76, 145, +42, 140, -17, -6, -39, -140, -21, -123, +-30, 18, -36, 113, -8, 76, 29, -32, +40, -87, 5, -36, -45, 43, -45, 61, +-4, 14, 18, -32, 6, -41, -21, -26, +-17, -10, 3, 20, 3, 55, -11, 52, +-9, 0, -7, -61, -9, -69, -24, -15, +-38, 39, -5, 55, 44, 39, 49, 11, +-7, -27, -57, -65, -74, -63, -17, -2, +47, 84, 47, 95, 8, 10, -26, -84, +-35, -94, -30, -9, -9, 62, 7, 57, +22, 9, 27, -28, -7, -23, -49, -14, +-35, -19, 18, -15, 60, 14, 25, 45, +-55, 42, -89, -4, -30, -56, 63, -63, +88, -17, 19, 51, -55, 72, -66, 30, +-44, -37, -5, -64, 17, -36, 39, 17, +66, 44, 34, 30, -63, -1, -118, -17, +-68, -12, 35, -7, 124, -15, 85, -13, +-37, 7, -104, 36, -68, 38, 0, -1, +55, -51, 53, -60, -2, -8, -35, 59, +-30, 66, -9, 5, 21, -64, 33, -67, +-7, -1, -35, 58, -39, 62, -9, 10, +29, -46, 46, -60, 17, -25, -26, 25, +-39, 49, -25, 39, -7, 0, 10, -40, +32, -50, 20, -16, 3, 22, -12, 32, +-27, 17, -26, -1, 2, -6, 8, -8, +4, -16, 13, -21, 7, -7, 6, 16, +3, 31, -17, 24, -39, 2, -17, -25, +-5, -36, 14, -30, 45, 8, 38, 61, +-3, 74, -49, 15, -84, -76, -57, -109, +42, -38, 110, 82, 85, 139, -25, 71, +-107, -76, -88, -156, 1, -89, 66, 49, +64, 137, 13, 99, -17, -15, -22, -97, +-32, -86, -35, -14, -7, 45, 47, 54, +68, 29, 24, -1, -69, -25, -92, -34, +-16, -20, 75, 11, 94, 34, 16, 33, +-84, -5, -97, -38, -17, -35, 62, 0, +88, 43, 38, 58, -47, 25, -89, -45, +-52, -86, 17, -50, 77, 45, 64, 110, +-5, 66, -63, -43, -52, -115, 14, -73, +48, 39, 17, 100, -36, 59, -24, -29, +18, -67, 52, -40, 19, 4, -45, 25, +-55, 26, -1, 21, 35, 13, 29, -12, +4, -39, -21, -34, 1, 6, 11, 42, +-15, 37, -31, 1, -4, -23, 17, -15, +30, 2, 6, 9, -32, -5, -12, -15, +24, 0, 16, 18, -26, 29, -49, 22, +-16, -10, 56, -37, 75, -47, 15, -21, +-71, 35, -75, 71, -14, 56, 47, -12, +53, -76, 21, -76, -10, -6, -24, 64, +-18, 64, -36, 16, -22, -25, 30, -18, +65, 1, 30, -8, -31, -39, -75, -34, +-41, 27, 47, 87, 65, 80, 9, -4, +-34, -101, -34, -118, -16, -33, 17, 84, +9, 132, 9, 72, 33, -39, 15, -105, +-48, -87, -59, -23, -12, 44, 58, 83, +91, 77, 21, 16, -68, -79, -85, -118, +-26, -48, 49, 77, 79, 136, 32, 53, +-31, -89, -59, -128, -28, -27, 17, 96, +34, 96, 25, -16, -4, -92, -18, -48, +-13, 50, 5, 70, 4, -3, 6, -65, +5, -43, -4, 27, -5, 54, -6, 29, +-7, -17, 13, -34, 28, -22, -1, -9, +-25, 5, -31, 28, -9, 33, 28, 7, +46, -31, 17, -45, -15, -7, -37, 40, +-32, 28, 8, -24, 42, -43, 30, 1, +0, 44, -24, 33, -32, -19, 0, -42, +22, -3, 25, 27, 2, 1, -26, -40, +-25, -27, 7, 53, 30, 92, 32, 19, +5, -99, -38, -119, -43, -12, -9, 106, +31, 110, 53, 7, 33, -75, -18, -75, +-47, -10, -44, 30, -9, 23, 39, 15, +57, 22, 22, 14, -24, -25, -51, -50, +-37, -33, 30, 20, 58, 59, 23, 38, +-33, -22, -40, -59, -4, -33, 41, 17, +32, 42, -10, 17, -33, -19, -13, -29, +29, -11, 29, 10, -5, 16, -28, 8, +-7, -6, 13, -11, 19, -6, -20, 13, +-36, 21, 0, 19, 32, -2, 26, -28, +-5, -26, -29, 4, -36, 34, 10, 22, +31, -12, 24, -24, 10, 1, -9, 19, +-40, 5, -38, -25, 0, -22, 48, 20, +78, 47, 17, 21, -75, -40, -96, -59, +-14, -11, 78, 52, 97, 52, 20, 1, +-71, -35, -80, -27, -12, -2, 39, 7, +38, -2, 23, 7, 10, 38, -8, 35, +-31, -24, -45, -73, -28, -44, 40, 44, +85, 90, 44, 37, -41, -62, -77, -91, +-52, -19, 28, 63, 79, 74, 52, 6, +-3, -52, -42, -55, -55, -18, -35, 24, +27, 48, 56, 52, 56, 10, 7, -53, +-60, -89, -69, -36, -8, 58, 54, 99, +56, 41, 16, -55, -32, -81, -35, -31, +-6, 23, 8, 28, 13, 6, 20, 16, +24, 30, 12, -3, -26, -68, -39, -86, +-12, -3, 30, 109, 42, 116, 15, -5, +-23, -126, -27, -116, -8, 9, 3, 105, +20, 80, 30, -17, 21, -60, -10, -24, +-39, 14, -40, 2, 13, -19, 58, 2, +38, 49, -15, 47, -51, -15, -37, -54, +18, -29, 45, 27, 19, 35, -10, 2, +-19, -13, -4, 17, 3, 36, -7, -5, +-9, -57, 11, -42, 27, 36, 22, 72, +-7, 27, -32, -48, -13, -62, 13, -9, +18, 32, 10, 16, 7, -4, -3, 16, +-4, 28, -14, -14, -27, -75, 8, -70, +43, 33, 36, 114, -6, 63, -48, -71, +-41, -136, 19, -50, 58, 80, 34, 109, +-16, 10, -52, -79, -37, -66, 12, 13, +50, 50, 46, 9, 9, -35, -43, -17, +-63, 35, -21, 35, 51, -13, 82, -52, +34, -31, -52, 29, -77, 53, -27, 31, +43, -8, 72, -27, 25, -17, -30, -4, +-36, 10, -24, 32, -2, 41, 22, 27, +27, -11, 21, -41, 6, -36, -19, 3, +-30, 53, -6, 66, 15, 19, 25, -46, +20, -68, 2, -30, -9, 41, -12, 72, +-19, 39, -15, -28, 23, -67, 34, -46, +25, 0, -11, 41, -35, 43, -22, 10, +11, -39, 29, -66, 16, -44, 4, 18, +-2, 51, 7, 18, -3, -44, -13, -54, +-20, -3, 4, 30, 34, 1, 30, -41, +0, -29, -21, 30, -19, 52, -12, -11, +15, -79, 27, -53, 27, 38, 13, 83, +-16, 26, -37, -56, -14, -46, 21, 34, +26, 71, 8, 16, -20, -50, -19, -29, +9, 54, 24, 89, -8, 31, -25, -44, +-14, -50, 20, 11, 34, 54, 9, 38, +-28, 10, -21, 1, 16, 12, 22, -1, +10, -27, -23, -18, -5, 22, 25, 54, +31, 23, -7, -35, -41, -57, -25, -17, +26, 33, 61, 33, 23, -7, -23, -39, +-50, -38, -17, -25, 25, -16, 41, -4, +28, 20, 3, 35, -18, -9, -28, -85, +-18, -104, -3, -29, 37, 73, 57, 94, +25, 14, -36, -85, -57, -104, -30, -33, +29, 38, 64, 47, 35, 13, -6, -4, +-34, 11, -31, 15, -8, -22, 17, -57, +22, -28, 20, 57, 5, 113, -12, 72, +-12, -27, -2, -86, 4, -48, 13, 35, +1, 87, -2, 65, 15, 18, 20, -7, +3, -4, -21, -4, -24, -13, 2, 1, +35, 43, 28, 60, 2, 23, -21, -29, +-13, -46, 9, -6, 14, 33, -5, 25, +-15, -13, 6, -28, 31, -9, 24, 11, +-18, -2, -46, -28, -17, -37, 42, -22, +61, -7, 23, -15, -38, -29, -50, -23, +-7, -8, 36, -5, 36, -18, 13, -37, +-14, -29, -21, -5, -10, 0, -7, -16, +17, -25, 35, -7, 28, 20, -4, 13, +-31, -23, -37, -46, 8, -21, 43, 34, +34, 55, 17, 29, -11, -8, -21, -13, +-22, 2, -12, 12, 4, 7, 45, 23, +52, 68, 5, 81, -48, 28, -71, -51, +-7, -73, 59, 4, 80, 93, 20, 111, +-47, 45, -58, -35, -17, -59, 34, -30, +37, 18, 33, 42, 9, 47, -10, 25, +-33, -20, -29, -60, 0, -46, 48, 9, +55, 43, 6, 18, -39, -45, -51, -67, +-5, -30, 44, 14, 43, 13, 6, -30, +-10, -57, -15, -45, 2, -23, 14, -15, +6, -12, 1, -2, 5, -1, 4, -28, +7, -58, 17, -45, 7, 7, -3, 42, +-19, 15, -9, -39, 14, -40, 37, 13, +23, 52, -12, 28, -32, -26, -29, -32, +9, 21, 27, 70, 33, 59, 12, 8, +2, -33, -14, -17, -24, 30, -17, 56, +11, 53, 48, 31, 37, 10, 10, 1, +-38, 9, -47, 22, -23, 25, 26, 14, +57, 1, 55, 14, 14, 30, -44, 17, +-60, -19, -33, -41, 30, -12, 72, 23, +55, 26, -11, -11, -49, -41, -42, -31, +-5, -11, 34, -13, 32, -29, 26, -28, +14, -5, -10, -9, -29, -50, -26, -68, +1, -26, 46, 31, 56, 34, 10, -40, +-38, -98, -43, -72, -7, 13, 33, 65, +44, 34, 16, -22, -7, -47, -19, -30, +-27, -8, -14, 2, 21, 17, 50, 41, +50, 47, -6, 18, -63, -22, -56, -27, +10, 6, 70, 40, 63, 49, 0, 42, +-56, 43, -51, 40, -8, 11, 30, -31, +47, -39, 33, 22, 11, 92, -23, 95, +-45, 15, -23, -68, 24, -66, 62, 5, +44, 71, -19, 64, -59, -2, -26, -47, +24, -42, 48, -11, 27, 17, -17, 18, +-19, -5, 1, -39, 12, -61, -3, -47, +8, 5, 13, 49, 20, 20, 9, -67, +-22, -124, -18, -69, 11, 42, 43, 96, +15, 29, -15, -92, -39, -130, -7, -52, +39, 62, 43, 97, 13, 32, -36, -60, +-39, -96, -12, -55, 40, 29, 53, 97, +31, 101, -28, 24, -62, -80, -39, -112, +23, -27, 79, 111, 59, 162, -8, 71, +-67, -62, -48, -104, 2, -22, 49, 72, +46, 83, 10, 41, -3, 18, -10, 34, +-23, 17, -27, -47, -4, -77, 34, -5, +66, 107, 32, 119, -26, 5, -58, -100, +-30, -84, 21, 6, 53, 49, 37, 5, +-4, -23, -16, 6, -3, 29, 4, -13, +-12, -89, -10, -90, 13, -1, 52, 78, +39, 45, -7, -54, -47, -95, -41, -45, +15, 20, 51, 25, 50, -14, 9, -34, +-15, -17, -36, 2, -21, -7, 9, -17, +36, 5, 48, 22, 22, 0, -15, -36, +-37, -28, -17, 30, 20, 61, 51, 20, +29, -39, -3, -40, -15, 32, -20, 89, +-3, 48, 11, -41, 28, -68, 31, 11, +18, 94, -15, 83, -39, -2, -17, -63, +33, -34, 64, 40, 27, 65, -34, 18, +-42, -28, 0, -16, 53, 19, 50, 25, +-5, -7, -44, -31, -13, -21, 36, 8, +44, 13, 16, 1, -25, 0, -16, -5, +14, -23, 23, -53, 7, -50, 2, 9, +11, 71, 18, 53, 11, -47, -12, -122, +-7, -87, 19, 33, 30, 105, 13, 55, +-10, -53, -7, -96, 20, -45, 35, 24, +11, 44, -16, 18, -14, -2, 21, -12, +46, -21, 20, -21, -9, 5, -14, 55, +1, 58, 23, -15, 17, -77, 10, -46, +22, 64, 28, 127, 4, 46, -21, -83, +-23, -108, 14, 1, 59, 112, 56, 98, +1, -5, -48, -74, -35, -43, 7, 27, +58, 47, 56, 21, 15, -2, -19, -7, +-29, -16, -5, -34, 27, -26, 57, 18, +41, 57, 9, 29, -33, -51, -34, -98, +8, -54, 56, 43, 75, 87, 32, 43, +-32, -47, -63, -99, -24, -68, 41, 7, +87, 60, 63, 54, -8, 14, -63, -28, +-48, -55, 15, -47, 66, -17, 69, 23, +20, 56, -18, 52, -31, 6, -5, -51, +20, -63, 29, -16, 27, 45, 29, 67, +14, 40, -3, -8, -11, -36, -3, -34, +21, -5, 33, 35, 24, 66, 6, 52, +8, -12, 3, -70, 6, -59, 7, 23, +22, 92, 35, 76, 31, -25, 12, -99, +-13, -60, -8, 43, 12, 87, 39, 32, +25, -45, 16, -62, 13, -5, 14, 35, +3, 15, -14, -30, -1, -29, 32, 16, +70, 33, 42, -1, -16, -48, -52, -41, +-18, 1, 54, 28, 79, 13, 46, -15, +-14, -13, -28, -3, -10, -5, 20, -19, +27, -10, 34, 19, 44, 35, 27, 10, +-11, -30, -37, -33, -10, 6, 48, 44, +76, 32, 38, -12, -26, -31, -35, -5, +7, 35, 54, 37, 50, 7, 12, -27, +-1, -24, 7, 8, 21, 26, 12, 32, +11, 21, 29, 3, 47, -24, 27, -41, +-25, -21, -28, 35, 20, 83, 76, 52, +65, -42, 3, -115, -37, -76, -13, 51, +39, 125, 55, 67, 26, -54, -2, -113, +14, -63, 33, 30, 21, 64, -8, 34, +-7, -5, 35, -26, 62, -36, 38, -44, +-13, -26, -18, 26, 17, 68, 48, 34, +36, -44, 0, -79, -2, -33, 32, 44, +45, 60, 23, 1, -7, -41, -5, -21, +33, 16, 60, 21, 32, -9, -9, -19, +-13, 11, 20, 38, 49, 21, 47, -20, +17, -26, -7, 8, 1, 38, 17, 22, +37, -13, 45, -18, 35, 8, 16, 28, +-10, 22, -15, -2, 15, -13, 63, -6, +65, 8, 28, 9, -18, 9, -27, 9, +19, -1, 61, -13, 59, -21, 28, -8, +1, 19, -3, 26, 16, -2, 23, -37, +32, -44, 48, -6, 50, 42, 21, 47, +-17, -8, -24, -73, 21, -73, 78, 1, +80, 74, 28, 66, -26, -14, -31, -82, +10, -65, 58, 0, 62, 45, 43, 36, +26, 4, 9, -8, -6, -17, -5, -37, +17, -42, 64, -1, 84, 62, 37, 70, +-19, 0, -44, -67, 0, -52, 61, 27, +77, 64, 37, 21, -1, -28, -5, -14, +21, 29, 38, 32, 16, -17, 14, -49, +31, 6, 51, 67, 46, 49, 15, -31, +-11, -74, -2, -20, 38, 57, 61, 63, +57, 1, 24, -43, -6, -31, -8, 2, +16, 9, 45, 4, 60, 23, 45, 38, +13, 5, -11, -57, -4, -74, 26, -3, +58, 81, 60, 74, 28, -19, 2, -93, +-3, -67, 22, 19, 52, 60, 50, 28, +22, -25, 9, -38, 13, -14, 37, 2, +51, 1, 30, 1, 5, 11, 0, 11, +21, -11, 48, -26, 62, -14, 36, 20, +9, 28, 4, -4, 5, -31, 31, -28, +53, 10, 57, 39, 39, 32, 10, -7, +-13, -34, 2, -27, 41, 3, 65, 30, +63, 29, 22, 18, -14, 2, -4, -14, +24, -24, 48, -24, 56, 5, 40, 47, +18, 65, 7, 19, -3, -53, 16, -81, +52, -22, 69, 62, 53, 81, 4, 21, +-32, -48, 2, -60, 65, -14, 86, 22, +50, 20, -8, 8, -25, 12, 23, 11, +62, -16, 55, -52, 27, -37, 5, 32, +19, 69, 39, 31, 32, -49, 15, -73, +25, -20, 47, 39, 40, 49, 12, 3, +0, -32, 26, -22, 72, -3, 59, 0, +5, -10, -24, 0, 3, 24, 63, 28, +80, -2, 33, -34, -12, -28, -6, 7, +28, 30, 51, 19, 40, -2, 25, -5, +34, 7, 42, -4, 18, -27, -9, -26, +5, 17, 53, 66, 89, 53, 54, -20, +-18, -79, -36, -61, 15, 24, 72, 88, +81, 66, 28, -8, -5, -64, 13, -53, +30, 0, 32, 32, 28, 31, 30, 25, +44, 11, 49, -18, 19, -42, 3, -31, +16, 20, 39, 52, 52, 18, 34, -38, +20, -49, 37, 6, 42, 57, 22, 17, +4, -54, 9, -63, 48, 11, 75, 73, +53, 37, 3, -46, -18, -64, 3, -1, +41, 51, 68, 20, 58, -39, 30, -33, +12, 21, -5, 43, -5, -4, 29, -49, +67, -25, 80, 32, 46, 39, -20, -10, +-30, -48, 21, -16, 64, 41, 71, 31, +41, -22, 9, -40, 16, -3, 26, 32, +18, 12, 11, -21, 28, -13, 64, 26, +71, 32, 34, -20, -14, -55, -15, -18, +22, 44, 64, 52, 70, 2, 39, -35, +12, -20, 7, 13, 4, 15, 15, -12, +41, -3, 51, 34, 57, 37, 28, -1, +-11, -41, -8, -28, 27, 19, 61, 28, +59, 3, 34, -17, 8, 8, 9, 34, +24, 8, 26, -45, 33, -61, 41, -9, +43, 56, 35, 69, 13, 24, 0, -36, +13, -63, 38, -57, 52, -12, 46, 49, +28, 82, 10, 52, 8, -37, 14, -101, +30, -76, 47, 19, 49, 82, 38, 58, +20, -10, 0, -49, 11, -44, 38, -19, +44, 10, 34, 32, 24, 42, 14, 22, +23, -33, 27, -61, 19, -28, 29, 41, +38, 70, 38, 24, 28, -44, 9, -54, +8, -11, 35, 32, 43, 42, 35, 14, +22, -1, 14, -5, 23, -11, 37, -24, +30, -13, 15, 26, 19, 52, 35, 32, +42, -14, 31, -43, 10, -28, 9, 8, +32, 28, 44, 23, 38, 8, 23, -6, +14, -12, 27, -15, 45, -17, 29, 1, +7, 14, 5, 16, 23, 10, 61, -6, +62, -11, 17, -12, -16, -18, -11, -16, +33, -1, 69, 23, 61, 28, 21, 1, +-7, -29, -2, -43, 26, -25, 39, 14, +36, 26, 44, 8, 47, -10, 35, -18, +0, -16, -20, -13, 1, -11, 58, 2, +95, 20, 62, 20, -8, 0, -49, -26, +-12, -31, 59, -3, 91, 27, 53, 27, +3, 3, -16, -13, 2, -7, 30, 6, +34, 8, 35, -2, 43, 1, 41, 14, +18, 17, -12, 6, -8, -11, 29, -5, +64, 12, 58, 9, 16, -4, -9, -4, +5, 15, 29, 29, 41, 0, 32, -42, +19, -37, 30, 10, 34, 56, 15, 44, +3, -17, 7, -53, 27, -30, 47, 7, +39, 24, 12, 19, 8, 1, 28, -10, +34, -21, 24, -31, -1, -20, 8, 12, +41, 34, 59, 22, 32, -8, -11, -37, +-18, -40, 13, -15, 49, 14, 61, 28, +42, 28, 11, 7, -6, -34, -3, -61, +7, -32, 34, 30, 63, 71, 62, 48, +22, -23, -25, -70, -36, -51, 9, 10, +74, 56, 84, 57, 40, 19, -20, -25, +-40, -46, -6, -32, 45, 10, 69, 50, +55, 58, 18, 18, -12, -33, -23, -46, +-1, -18, 40, 29, 66, 48, 55, 26, +9, -5, -27, -25, -14, -26, 26, -4, +57, 17, 47, 22, 15, 10, -2, -8, +4, -19, 24, -9, 21, 12, 10, 14, +17, -6, 38, -26, 38, -18, 17, 7, +-8, 20, -7, 9, 23, -16, 50, -27, +37, -17, 11, 2, 1, 7, 13, 1, +27, -4, 25, -2, 0, 6, 8, -4, +34, -19, 47, -22, 34, -3, -8, 23, +-23, 25, 5, 1, 43, -19, 58, -16, +34, 9, -8, 18, -20, 1, 4, -11, +30, 6, 42, 26, 33, 25, 10, -10, +7, -38, 19, -20, 19, 27, 11, 45, +16, 14, 22, -28, 38, -28, 32, 4, +6, 27, -7, 17, 6, -3, 21, -4, +32, -5, 29, -10, 14, -11, 18, 7, +27, 29, 14, 22, -8, -19, -7, -51, +15, -31, 61, 14, 69, 41, 18, 25, +-33, -11, -45, -28, -5, -30, 56, -25, +78, -13, 55, 21, -3, 57, -38, 34, +-43, -37, -7, -85, 46, -50, 81, 35, +69, 82, 4, 43, -58, -36, -55, -65, +3, -29, 71, 17, 94, 26, 43, 15, +-19, 5, -50, 4, -27, -14, 25, -30, +59, -11, 59, 29, 35, 42, -2, 5, +-22, -44, -22, -41, 12, 14, 43, 60, +52, 41, 36, -18, -6, -47, -21, -30, +-6, 17, 16, 43, 35, 33, 28, 7, +12, -18, 6, -30, 6, -12, 8, 20, +5, 37, 1, 21, 12, -22, 20, -35, +33, -9, 26, 28, 3, 27, -8, -10, +-9, -40, 18, -27, 35, 11, 37, 27, +13, 12, -4, -12, -10, -15, 1, -11, +20, -14, 31, -10, 17, 5, 16, 21, +10, 13, 3, -16, 2, -31, 3, -14, +16, 11, 38, 14, 30, -3, 4, -14, +-22, 8, -21, 22, 20, 7, 47, -16, +44, -23, -2, 4, -29, 24, -16, 13, +18, -4, 50, -7, 38, 10, -6, 17, +-14, -8, -7, -25, 18, -6, 26, 30, +12, 38, 7, 7, 20, -26, 20, -23, +5, 2, -16, 13, -11, 7, 19, 8, +53, 21, 41, 12, -7, -20, -32, -47, +-25, -20, 21, 38, 53, 61, 29, 18, +1, -49, -4, -64, 3, -16, 17, 32, +6, 31, -5, 3, 13, -13, 43, -6, +37, -12, -1, -32, -34, -32, -24, 15, +18, 61, 61, 40, 36, -32, 0, -77, +-24, -42, -15, 29, 18, 57, 24, 24, +13, -17, 13, -23, 18, -7, 9, -3, +-4, -20, -12, -6, 1, 34, 20, 58, +30, 17, 11, -46, -2, -58, 0, -10, +7, 41, 16, 42, 7, 10, -1, -14, +18, -10, 22, -6, 21, -15, -1, -10, +-17, 21, -10, 43, 20, 19, 33, -26, +26, -45, 6, -9, -2, 29, -12, 31, +-4, -1, 11, -25, 18, -8, 34, 9, +25, 3, -3, -11, -15, -13, -20, 10, +-1, 14, 34, -4, 37, -15, 26, -8, +-8, 11, -22, 4, -22, -20, 11, -21, +34, 13, 34, 35, 19, 14, -9, -34, +-21, -53, 0, -15, 14, 35, 21, 49, +16, 16, 5, -23, 0, -30, 4, -18, +-1, 2, -9, 18, 2, 25, 28, 20, +33, 5, 15, -15, -17, -27, -34, -16, +3, 6, 32, 27, 38, 35, 11, 27, +-25, 4, -22, -26, 14, -45, 26, -23, +16, 24, -6, 57, -3, 49, 14, 7, +22, -33, 0, -52, -24, -40, -5, -3, +31, 49, 42, 81, 21, 48, -33, -39, +-38, -105, 6, -78, 44, 24, 44, 112, +0, 87, -23, -23, -10, -97, 18, -77, +27, -2, 8, 55, -6, 56, 2, 18, +18, -23, 27, -48, -2, -48, -12, -16, +1, 37, 16, 61, 24, 27, 14, -42, +0, -77, 9, -31, 9, 37, 5, 59, +-6, 21, 0, -26, 15, -30, 30, -9, +26, 7, -6, 4, -23, 5, -11, 15, +10, 12, 35, -5, 37, -19, 8, -3, +-5, 19, -21, 19, -20, -16, 14, -37, +40, -2, 35, 54, 13, 54, -22, -4, +-28, -65, -2, -57, 33, 7, 31, 55, +18, 43, 2, 2, -7, -22, 1, -17, +0, -16, -5, -23, 13, -11, 26, 26, +30, 51, 15, 24, -14, -36, -18, -68, +2, -31, 19, 33, 17, 51, 13, 12, +9, -24, 1, -16, 5, 7, -2, 8, +-17, -16, 4, -27, 22, 1, 29, 40, +26, 32, -4, -10, -23, -40, -15, -25, +-1, 13, 24, 28, 36, 11, 34, -8, +3, -1, -24, 8, -31, -4, -8, -21, +39, -13, 51, 22, 23, 40, -14, 19, +-40, -23, -18, -36, 26, -10, 32, 31, +17, 41, -6, 20, -9, -10, 9, -29, +13, -24, -5, 0, -15, 30, 9, 44, +35, 28, 27, -16, 2, -57, -29, -48, +-16, 12, 23, 66, 31, 65, 13, 4, +-10, -55, -14, -62, 15, -13, 22, 36, +9, 48, -18, 28, -8, -11, 19, -29, +29, -27, 11, -6, -24, 21, -25, 33, +15, 17, 34, -13, 24, -33, -6, -16, +-32, 24, -4, 38, 28, 13, 29, -26, +7, -37, -16, -3, -18, 40, 5, 41, +22, 4, 20, -32, 8, -29, 3, 9, +-11, 35, -14, 25, -2, -5, 15, -18, +29, 4, 27, 19, -4, 14, -26, -5, +-26, -13, 1, 2, 32, 19, 40, 17, +23, 2, -15, 1, -37, 6, -34, 8, +1, -2, 44, -6, 49, 11, 14, 32, +-31, 25, -59, -7, -17, -29, 34, -12, +53, 27, 27, 39, -21, 5, -32, -34, +-12, -21, 17, 18, 24, 44, 9, 18, +-3, -22, -13, -30, 1, -4, 6, 34, +0, 38, 6, 12, 2, -12, -9, -20, +-5, -10, -1, 6, 16, 22, 22, 37, +-3, 26, -25, -7, -26, -36, -4, -20, +23, 21, 40, 46, 16, 34, -21, -5, +-34, -29, -22, -14, -5, 22, 26, 33, +32, 19, 13, 9, -16, 8, -46, 7, +-34, -4, 7, -4, 38, 9, 45, 28, +-1, 32, -42, 2, -41, -21, -4, -6, +29, 26, 24, 34, 0, 4, -18, -22, +-17, 3, 1, 40, -2, 45, -12, -2, +-1, -49, 6, -27, 16, 38, -4, 75, +-29, 41, -30, -19, -9, -36, 11, -4, +14, 25, 0, 22, -14, 11, -17, 21, +-11, 36, -11, 17, -11, -24, -2, -39, +7, 0, 11, 58, -6, 70, -36, 23, +-36, -32, -15, -33, 20, 1, 31, 33, +2, 35, -31, 18, -44, 11, -21, 8, +9, 1, 20, -5, 8, 4, -20, 28, +-38, 43, -27, 26, -9, -6, 14, -16, +11, 2, -9, 28, -28, 33, -29, 20, +-17, 10, 0, 6, 4, 7, -6, 6, +-15, 9, -18, 21, -20, 30, -21, 24, +-11, 6, -7, 1, -3, 12, -11, 23, +-30, 21, -31, 7, -18, 7, 0, 24, +7, 37, -18, 25, -36, -11, -30, -28, +-4, -3, 5, 49, -8, 66, -30, 33, +-43, -15, -21, -34, 4, -8, 5, 29, +-11, 45, -39, 32, -46, 20, -29, 17, +-3, 6, 6, -3, -7, -7, -28, 9, +-46, 41, -40, 50, -23, 30, -4, 0, +-2, -5, -13, 9, -38, 20, -48, 17, +-36, 6, -11, 23, 3, 52, -7, 47, +-32, 3, -43, -43, -43, -32, -21, 25, +-6, 80, -7, 76, -19, 19, -36, -33, +-47, -40, -41, -2, -24, 44, -3, 64, +-8, 60, -29, 25, -56, -17, -56, -39, +-28, -9, -4, 47, -2, 86, -32, 58, +-53, -12, -52, -48, -31, -17, -18, 46, +-18, 73, -30, 46, -37, 1, -36, -20, +-31, -6, -39, 21, -42, 38, -30, 38, +-16, 30, -20, 16, -38, -2, -60, -7, +-50, 10, -25, 40, -17, 53, -27, 28, +-48, -3, -57, -3, -42, 20, -28, 42, +-34, 33, -45, 8, -47, 2, -36, 20, +-29, 43, -39, 42, -54, 9, -52, -6, +-43, 4, -30, 28, -35, 43, -46, 38, +-55, 26, -53, 21, -51, 15, -39, 1, +-38, 6, -38, 24, -44, 47, -56, 50, +-54, 20, -47, -7, -33, -7, -37, 23, +-60, 40, -64, 31, -55, 20, -36, 24, +-32, 38, -50, 28, -71, 2, -68, -15, +-47, 12, -36, 57, -37, 69, -55, 35, +-67, -9, -66, -20, -56, 12, -58, 49, +-50, 53, -43, 28, -40, 13, -55, 17, +-75, 18, -86, 14, -62, 8, -34, 24, +-27, 50, -46, 50, -84, 27, -100, -6, +-73, -13, -40, 19, -29, 53, -45, 56, +-75, 30, -86, 1, -76, 2, -66, 24, +-55, 34, -49, 34, -59, 30, -67, 32, +-79, 30, -79, 19, -73, 10, -59, 14, +-59, 33, -61, 46, -74, 42, -78, 24, +-75, 8, -61, 4, -60, 15, -68, 34, +-73, 45, -76, 45, -70, 25, -65, 0, +-68, -5, -74, 21, -77, 54, -82, 61, +-74, 29, -69, -2, -67, 2, -71, 33, +-80, 50, -88, 32, -85, 8, -72, 15, +-61, 46, -67, 56, -80, 20, -90, -21, +-84, -8, -73, 44, -66, 76, -80, 57, +-84, 3, -85, -12, -71, 11, -72, 40, +-87, 36, -96, 17, -89, 27, -68, 54, +-60, 55, -76, 11, -106, -28, -110, -14, +-87, 51, -67, 99, -66, 72, -83, 2, +-99, -37, -96, -6, -88, 48, -85, 68, +-83, 37, -81, 11, -85, 18, -82, 36, +-97, 42, -105, 19, -99, 2, -80, 15, +-71, 43, -80, 62, -106, 49, -114, 18, +-104, 3, -79, 6, -71, 26, -78, 41, +-99, 48, -118, 46, -108, 27, -87, 13, +-73, 7, -70, 13, -92, 33, -121, 50, +-120, 48, -94, 32, -67, 14, -68, 6, +-91, 7, -122, 30, -124, 55, -99, 58, +-75, 36, -75, 6, -96, -7, -111, 13, +-112, 53, -106, 67, -95, 41, -87, 4, +-83, -3, -93, 23, -108, 47, -124, 42, +-114, 20, -87, 22, -68, 40, -76, 43, +-114, 23, -140, -12, -125, -5, -81, 42, +-58, 83, -77, 68, -119, 11, -143, -29, +-123, -13, -85, 37, -65, 65, -84, 59, +-115, 34, -131, 21, -123, 17, -98, 8, +-87, 3, -85, 17, -95, 56, -114, 81, +-127, 57, -121, 0, -105, -31, -81, -3, +-78, 51, -98, 74, -129, 54, -135, 15, +-112, 1, -83, 21, -80, 39, -98, 30, +-119, 18, -123, 24, -113, 40, -98, 44, +-93, 28, -99, 14, -106, 22, -116, 38, +-120, 34, -109, 17, -99, 17, -95, 39, +-106, 63, -124, 49, -124, 7, -104, -15, +-82, 7, -91, 53, -116, 68, -133, 42, +-121, 10, -94, 6, -80, 20, -102, 36, +-130, 40, -135, 36, -109, 34, -85, 30, +-85, 15, -107, 6, -120, 18, -123, 46, +-112, 54, -104, 37, -104, 12, -97, 0, +-100, 23, -112, 45, -126, 47, -124, 34, +-104, 21, -81, 13, -83, 16, -113, 22, +-140, 35, -134, 50, -98, 44, -70, 20, +-81, -2, -115, 2, -139, 32, -127, 56, +-98, 46, -76, 17, -85, 7, -110, 22, +-133, 39, -129, 33, -106, 12, -81, 14, +-74, 38, -100, 58, -134, 36, -133, -8, +-115, -6, -86, 33, -70, 62, -92, 53, +-128, 14, -142, -1, -123, 23, -90, 49, +-70, 37, -84, 7, -116, 4, -136, 39, +-130, 66, -112, 51, -84, -2, -69, -27, +-81, 11, -115, 65, -148, 73, -140, 26, +-94, -14, -57, -3, -57, 34, -103, 52, +-156, 38, -155, 12, -101, 15, -56, 34, +-55, 35, -98, 16, -144, 6, -141, 20, +-105, 49, -78, 50, -71, 21, -89, -6, +-108, -4, -117, 31, -119, 57, -105, 44, +-84, 15, -76, 2, -88, 9, -111, 29, +-127, 43, -116, 33, -83, 18, -68, 14, +-86, 19, -115, 31, -127, 33, -109, 23, +-82, 15, -72, 17, -89, 28, -108, 40, +-119, 34, -111, 18, -98, 11, -82, 17, +-80, 36, -95, 44, -110, 27, -119, 12, +-105, 10, -80, 26, -73, 37, -87, 28, +-110, 12, -120, 15, -100, 32, -77, 41, +-76, 25, -90, -2, -109, 1, -107, 30, +-94, 59, -88, 50, -89, 8, -94, -11, +-93, 9, -92, 42, -95, 49, -101, 21, +-98, 2, -86, 20, -78, 47, -91, 47, +-105, 7, -104, -27, -86, -1, -73, 56, +-78, 80, -98, 43, -106, -14, -99, -28, +-80, 5, -73, 46, -87, 56, -103, 39, +-99, 21, -85, 18, -78, 13, -81, 0, +-91, -3, -97, 25, -92, 63, -85, 65, +-78, 23, -78, -23, -89, -24, -96, 15, +-94, 53, -81, 56, -70, 30, -70, 7, +-85, 0, -101, 8, -103, 20, -88, 32, +-71, 39, -64, 38, -80, 20, -93, 2, +-98, 0, -88, 18, -78, 36, -71, 36, +-71, 21, -73, 9, -86, 14, -93, 16, +-95, 18, -81, 20, -61, 24, -53, 28, +-72, 22, -105, 11, -110, 3, -81, 16, +-53, 36, -49, 35, -74, 15, -104, 1, +-101, 10, -74, 27, -56, 32, -58, 13, +-76, 3, -89, 15, -84, 34, -77, 36, +-74, 16, -75, -2, -65, 7, -66, 28, +-73, 35, -89, 22, -90, 4, -72, 16, +-58, 34, -56, 30, -76, 7, -91, -8, +-93, 15, -74, 45, -50, 48, -54, 22, +-69, -11, -83, -12, -87, 10, -73, 35, +-63, 38, -54, 27, -63, 20, -70, 8, +-82, 1, -77, -4, -68, 10, -59, 35, +-59, 49, -68, 37, -76, 1, -69, -18, +-67, -6, -59, 21, -68, 45, -70, 36, +-63, 13, -55, -2, -58, 2, -73, 11, +-76, 19, -69, 23, -53, 21, -46, 21, +-64, 15, -79, 8, -74, 1, -56, 11, +-52, 30, -60, 30, -70, 15, -73, 0, +-59, 2, -51, 19, -57, 29, -61, 18, +-64, 3, -62, 1, -52, 10, -57, 24, +-60, 21, -63, 13, -59, 7, -56, 11, +-56, 15, -57, 15, -65, 17, -57, 13, +-53, 13, -51, 10, -56, 10, -64, 15, +-63, 19, -60, 23, -54, 16, -51, 8, +-52, 7, -58, 15, -66, 19, -59, 16, +-55, 14, -42, 12, -45, 14, -57, 11, +-65, 4, -63, 7, -52, 26, -49, 36, +-52, 24, -59, -1, -58, -16, -45, 3, +-48, 33, -53, 39, -60, 14, -55, -11, +-38, -11, -38, 16, -51, 29, -62, 14, +-59, -2, -40, 1, -34, 22, -45, 30, +-63, 7, -60, -13, -45, -3, -33, 25, +-41, 38, -61, 20, -67, -4, -53, -7, +-28, 11, -26, 27, -51, 19, -68, 0, +-65, -5, -36, 12, -23, 32, -32, 22, +-50, -5, -67, -14, -58, 3, -41, 31, +-32, 41, -36, 19, -45, -12, -49, -17, +-55, 5, -46, 30, -42, 35, -38, 17, +-36, -3, -42, -9, -39, -2, -43, 15, +-46, 20, -46, 15, -47, 10, -33, 10, +-36, 16, -37, 12, -53, 5, -59, -1, +-44, 8, -28, 24, -19, 26, -37, 14, +-58, -7, -58, -12, -39, 4, -15, 22, +-25, 27, -45, 14, -57, -2, -48, 2, +-31, 13, -26, 13, -33, 3, -44, 0, +-45, 18, -37, 31, -30, 20, -33, -9, +-42, -27, -38, -5, -32, 34, -27, 48, +-34, 26, -47, -18, -42, -34, -36, -7, +-22, 31, -24, 46, -33, 21, -38, -9, +-43, -20, -34, -5, -26, 9, -27, 23, +-29, 20, -29, 12, -33, 14, -37, 1, +-33, -14, -29, -14, -26, 6, -24, 38, +-30, 42, -33, 15, -42, -19, -42, -27, +-29, -1, -18, 32, -11, 38, -25, 16, +-48, -6, -53, -11, -36, 1, -2, 11, +2, 13, -15, 5, -46, 2, -54, 2, +-30, 6, -7, 7, -2, 11, -27, 9, +-43, 6, -45, 9, -27, 3, -8, 4, +-17, 6, -21, 7, -26, 8, -25, 8, +-22, 3, -30, -2, -31, 2, -23, 10, +-7, 19, -8, 20, -31, 6, -42, -13, +-47, -5, -22, 14, 4, 27, 1, 24, +-21, 1, -47, -17, -43, -10, -20, 9, +7, 22, 8, 19, -22, 8, -44, -2, +-47, -3, -21, 4, 2, 11, 3, 16, +-14, 15, -36, 6, -32, -5, -19, -10, +-6, 0, -7, 16, -18, 24, -21, 15, +-17, -6, -12, -10, -19, -3, -21, 8, +-18, 17, -14, 15, -5, 11, -14, 8, +-25, 4, -29, -1, -21, -3, -1, 2, +-1, 15, -11, 21, -22, 7, -20, -10, +-7, -12, -9, 5, -11, 19, -16, 13, +-17, 4, -10, -1, -9, 8, -14, 20, +-22, 13, -16, -2, -7, -10, 2, -1, +-1, 17, -22, 24, -21, 7, -16, -3, +-3, -3, 6, 7, -9, 13, -15, 4, +-27, 4, -15, 7, 2, 16, 5, 19, +-2, 4, -19, -13, -20, -12, -15, 9, +-3, 34, 1, 34, -3, 5, -5, -20, +-15, -20, -8, 2, -10, 30, -11, 30, +-3, 9, -1, -8, 9, -10, -2, 3, +-15, 10, -22, 8, -15, 6, 14, 10, +20, 18, 6, 12, -23, -7, -36, -17, +-11, -4, 18, 25, 29, 42, 4, 19, +-23, -18, -27, -35, -5, -11, 17, 33, +17, 43, 4, 18, -13, -14, -15, -22, +5, -7, 9, 15, 8, 19, -1, 6, +-1, 3, 4, 11, 6, 13, 4, 0, +-11, -14, -6, -12, 6, 15, 13, 42, +15, 33, -4, -4, -8, -36, -8, -25, +4, 16, 19, 40, 16, 29, 7, -1, +-10, -15, -5, -8, 3, 11, 11, 12, +17, 1, 4, 3, 6, 14, 5, 20, +10, 4, 7, -15, -3, -17, 4, 3, +13, 27, 22, 31, 16, 4, 1, -18, +-7, -15, -4, 7, 18, 22, 26, 16, +20, 1, 2, -4, -7, 4, 1, 14, +13, 9, 21, -2, 18, -9, 11, 2, +8, 18, 2, 23, 2, 14, 6, -12, +19, -18, 25, -2, 20, 20, 7, 31, +-9, 16, -1, -6, 15, -12, 29, -2, +30, 11, 10, 14, 0, 10, -4, 6, +14, 5, 30, 2, 26, -2, 16, -4, +1, 5, 1, 21, 12, 24, 24, 5, +26, -12, 11, -15, 10, 3, 6, 27, +16, 26, 22, 5, 18, -16, 16, -14, +15, 1, 20, 21, 19, 21, 14, 7, +8, -3, 8, -5, 24, 0, 34, 3, +29, 6, 13, 8, 0, 8, 11, 3, +23, -1, 36, -5, 32, 1, 7, 18, +-2, 19, 8, 4, 31, -10, 35, -7, +23, 8, 10, 18, 8, 13, 17, 3, +20, -2, 22, -2, 18, 9, 13, 15, +23, 13, 19, 10, 22, 0, 16, -6, +20, -8, 26, 2, 32, 10, 30, 19, +10, 17, 12, -6, 20, -18, 26, -9, +33, 9, 28, 20, 23, 20, 8, 8, +16, -13, 28, -16, 32, -2, 33, 11, +23, 16, 17, 9, 12, 5, 17, -1, +29, -2, 29, 0, 31, 1, 24, 5, +16, 13, 12, 13, 16, 4, 30, -4, +34, -7, 35, -2, 21, 11, 8, 16, +12, 10, 21, 0, 36, -3, 33, 2, +24, 11, 15, 11, 14, 3, 21, 1, +28, -2, 36, 4, 30, 10, 19, 7, +20, -2, 21, -3, 26, 9, 25, 10, +32, 1, 30, -5, 28, -5, 28, 9, +19, 14, 18, 9, 23, -6, 31, -10, +40, 2, 33, 12, 25, 11, 11, 0, +14, -5, 30, 0, 39, 12, 40, 14, +23, 0, 15, -14, 21, -12, 28, 9, +40, 20, 36, 11, 24, -2, 14, -12, +18, -3, 29, 8, 35, 13, 30, 8, +25, -2, 24, -2, 29, 1, 29, 2, +32, -7, 24, -2, 26, 2, 34, 9, +31, 16, 30, 0, 27, -12, 21, -12, +24, -3, 35, 11, 40, 15, 33, 11, +23, -5, 16, -12, 23, -8, 35, 3, +39, 17, 29, 13, 23, 2, 19, -3, +25, -6, 40, -7, 36, 0, 29, 4, +29, 5, 24, 12, 29, 1, 32, -11, +32, -11, 31, -2, 28, 16, 27, 17, +28, 3, 37, -18, 37, -20, 32, -4, +26, 11, 27, 15, 33, 6, 35, -10, +38, -15, 28, -7, 22, 7, 24, 9, +33, 3, 39, 0, 35, -1, 23, 3, +21, -5, 23, -6, 37, -5, 40, 9, +33, 15, 27, 0, 22, -13, 27, -12, +32, 0, 39, 9, 33, 9, 26, -4, +27, -6, 25, 0, 39, -1, 37, 1, +32, -5, 28, -4, 26, 1, 32, 4, +36, 2, 37, -5, 29, -1, 20, -1, +31, -1, 34, 2, 40, 0, 34, -1, +26, -6, 22, 3, 28, 3, 46, -2, +41, -2, 29, -9, 19, 1, 17, 8, +36, 9, 44, 0, 39, -9, 27, -8, +19, -5, 27, 6, 35, 7, 47, -3, +39, -4, 26, -12, 24, -7, 26, -1, +41, 5, 43, 6, 32, -1, 20, -5, +18, -7, 35, 0, 45, 3, 42, 0, +28, -3, 21, -10, 29, -4, 38, -1, +44, 2, 37, -1, 22, 4, 15, 1, +31, -11, 46, -9, 48, -1, 35, 9, +16, 6, 19, -11, 31, -10, 45, 0, +44, 11, 31, 4, 20, -5, 22, -14, +41, -9, 48, 0, 45, 0, 31, 0, +21, -3, 26, 1, 34, -3, 44, -8, +38, -3, 27, -1, 28, 5, 29, 2, +39, -1, 40, -7, 32, -9, 30, -7, +30, -6, 42, 7, 38, 11, 31, 1, +25, -11, 21, -15, 37, -1, 48, 2, +46, 7, 32, -3, 15, -4, 20, -1, +34, -5, 53, -8, 52, -10, 32, -1, +21, 5, 13, 5, 38, -7, 53, -14, +46, -3, 31, -1, 12, 4, 25, 0, +40, -1, 51, -2, 47, -11, 27, -10, +25, -6, 26, 5, 43, 3, 51, -9, +41, -9, 34, -9, 26, 0, 30, -2, +42, -9, 44, -4, 44, -3, 28, 6, +26, -5, 40, -15, 44, -5, 38, 5, +27, 6, 26, -4, 34, -4, 46, -5, +50, -2, 32, -1, 23, -7, 23, 1, +39, -2, 57, -5, 48, -7, 30, -3, +14, 4, 22, -2, 44, -4, 54, -9, +47, 2, 24, 6, 18, -4, 30, -8, +43, -9, 55, -1, 45, -2, 29, -6, +27, -11, 35, -6, 48, 4, 46, -5, +40, -13, 33, -15, 32, -4, 42, 6, +46, -4, 42, -5, 30, -8, 25, -4, +33, -1, 44, -6, 55, -4, 44, 0, +24, 2, 21, -8, 32, -12, 54, -5, +53, 4, 35, 8, 23, -6, 24, -8, +43, -8, 55, -5, 47, -5, 34, -7, +24, 1, 34, 3, 46, -2, 49, -11, +42, -13, 29, 0, 27, 6, 32, 4, +46, -10, 46, -4, 39, -3, 38, -6, +32, -7, 39, -11, 45, 1, 40, 2, +42, -5, 32, -9, 40, -11, 44, 2, +42, -1, 36, -1, 24, -5, 31, -2, +41, 1, 48, -4, 51, -9, 33, -8, +24, -1, 27, -3, 44, -8, 60, -5, +49, -2, 33, 3, 15, -6, 27, -10, +49, -5, 57, 2, 50, 1, 28, -11, +24, -11, 31, 2, 44, 3, 57, -6, +43, -16, 35, -5, 27, 5, 31, 7, +46, -11, 48, -15, 42, -3, 35, 3, +31, 4, 35, -6, 41, -9, 46, -4, +43, -6, 35, -4, 36, -8, 41, 1, +45, 1, 37, -3, 31, -13, 38, -12, +41, 5, 44, 5, 43, -5, 33, -11, +28, -2, 31, 6, 49, -6, 51, -10, +40, -9, 27, 8, 22, 7, 41, -8, +52, -16, 52, -13, 41, 1, 24, 4, +27, 0, 36, -6, 50, -8, 46, -1, +34, -5, 32, -3, 32, -3, 37, 3, +40, -2, 39, -9, 40, -3, 32, 5, +34, 4, 38, -10, 41, -13, 43, -2, +37, 1, 41, -3, 39, -12, 39, -4, +46, -4, 44, -7, 36, -6, 33, -12, +41, 2, 44, 8, 40, 0, 33, -11, +28, -13, 39, 0, 47, 5, 43, 4, +40, -12, 29, -9, 32, -2, 42, -3, +46, -2, 43, -2, 33, 3, 33, -3, +38, -15, 44, -14, 43, 0, 39, 9, +38, 4, 33, -9, 42, -19, 41, -6, +39, 1, 43, -4, 37, -1, 37, -3, +40, 0, 39, -7, 39, -12, 37, -9, +40, -3, 40, 7, 41, -3, 46, -12, +36, -6, 30, -2, 32, 0, 39, -8, +49, -2, 47, -1, 38, -1, 26, -7, +30, -15, 47, -4, 51, 5, 48, 0, +34, -10, 27, -14, 35, -1, 44, 1, +52, -3, 43, -12, 32, -4, 31, 3, +33, 1, 43, -8, 45, -12, 44, -5, +40, 2, 35, -4, 39, -9, 37, -9, +43, 1, 42, -2, 39, -6, 39, -9, +40, -6, 40, 4, 37, -2, 38, -10, +41, -9, 42, -2, 42, 3, 40, -5, +35, -3, 32, -1, 32, 4, 45, -10, +48, -9, 41, -4, 36, 3, 29, 2, +42, -14, 48, -12, 46, -5, 42, 0, +30, 1, 32, -7, 44, -6, 49, -2, +40, 1, 32, -11, 33, -7, 34, 7, +44, 6, 46, -4, 36, -15, 31, -7, +30, 7, 42, 4, 42, 2, 37, -10, +37, -3, 30, 3, 34, 0, 40, -7, +38, -1, 38, 7, 36, 3, 35, -8, +40, -16, 42, -8, 44, 7, 40, 1, +39, -5, 38, -14, 40, -4, 41, -2, +46, -11, 38, -3, 29, 3, 34, 8, +42, 0, 44, -10, 41, -9, 33, -3, +31, 6, 37, 1, 42, -1, 47, -4, +40, -2, 34, -4, 34, -10, 39, -6, +45, 1, 42, 4, 39, -3, 38, -9, +37, -4, 40, -3, 39, -4, 40, -9, +45, -6, 43, 4, 42, 1, 37, -8, +37, -17, 41, -8, 39, 7, 42, 5, +41, -6, 43, -13, 39, -4, 37, -3, +37, -3, 36, -6, 48, -5, 48, 3, +40, 0, 30, -7, 28, -11, 34, 3, +44, 7, 54, -3, 43, -4, 26, -5, +26, 1, 32, 1, 48, -4, 54, -7, +44, -1, 36, -1, 32, -6, 32, -3, +40, -1, 48, -2, 49, -4, 38, -5, +36, -5, 36, 0, 37, 3, 44, -5, +44, -10, 42, -3, 40, -2, 40, 1, +36, 0, 35, -1, 39, -1, 43, -5, +45, -7, 40, -4, 39, 0, 36, 6, +35, -2, 44, -14, 49, -11, 45, 3, +40, 5, 29, 4, 29, -8, 43, -9, +50, -1, 51, -2, 40, -6, 35, -10, +36, 0, 38, 6, 49, -8, 48, -16, +41, -8, 32, 12, 35, 8, 44, -4, +40, -15, 43, -15, 41, 0, 41, 7, +45, 1, 41, -5, 38, -5, 33, -3, +36, -5, 42, -2, 43, 3, 43, 8, +38, 1, 30, -4, 32, -10, 40, -5, +49, 4, 50, 3, 47, -3, 38, -11, +34, -14, 42, -11, 50, -3, 54, 5, +50, -1, 39, -10, 38, -18, 37, -9, +42, 7, 46, 9, 47, 0, 46, -13, +37, -9, 34, -1, 35, 0, 43, -2, +52, -4, 46, 5, 45, -5, 38, -13, +32, -13, 39, -3, 46, 12, 52, 7, +46, -8, 36, -16, 30, -7, 32, 10, +41, 10, 49, -2, 54, -15, 46, -9, +35, -1, 31, 0, 34, -1, 41, 3, +52, 2, 53, -4, 43, -12, 31, -11, +31, -1, 36, 15, 49, 8, 54, -7, +46, -19, 38, -14, 35, -1, 41, 8, +47, 5, 51, -9, 45, -12, 41, -11, +40, -1, 40, 7, 43, 1, 47, -9, +48, -12, 43, -4, 44, 0, 41, -2, +45, -6, 39, 1, 40, 3, 42, -2, +45, -14, 50, -14, 45, 2, 42, 13, +42, 1, 40, -17, 41, -19, 44, 0, +45, 21, 43, 11, 39, -9, 34, -19, +38, -9, 45, 7, 51, 5, 49, -4, +47, -12, 42, -8, 39, -1, 39, -6, +43, -6, 43, 5, 46, 11, 47, 4, +40, -14, 35, -21, 36, -8, 46, 11, +55, 15, 52, 0, 41, -18, 29, -15, +28, 1, 44, 10, 55, 8, 56, -5, +45, -11, 36, -11, 36, -3, 37, 3, +46, 0, 50, 1, 46, 3, 44, -2, +37, -8, 36, -14, 43, -6, 49, 9, +51, 14, 48, -7, 42, -21, 32, -14, +43, 1, 50, 15, 49, 4, 49, -19, +42, -16, 35, 5, 37, 17, 39, 6, +43, -10, 45, -10, 41, 7, 41, 8, +39, -1, 38, -11, 43, -5, 47, 7, +46, 6, 41, -9, 39, -14, 37, 0, +43, 16, 42, 14, 41, -10, 46, -26, +42, -9, 47, 9, 48, 13, 42, -1, +38, -16, 41, -14, 43, 4, 46, 10, +48, 1, 46, -11, 40, -9, 40, -2, +41, 5, 44, -3, 52, -11, 50, -4, +42, 10, 34, 8, 34, -9, 40, -15, +45, 0, 55, 15, 46, 20, 36, -6, +31, -24, 31, -12, 46, 12, 55, 20, +56, 1, 43, -18, 31, -15, 32, 3, +41, 11, 52, -1, 58, -13, 49, -5, +38, 9, 28, 8, 31, -6, 43, -16, +56, -3, 54, 15, +}; \ No newline at end of file diff --git a/project/realtek_ameba1_va0_example/example_sources/i2s/src/birds_24000_2ch_16b.c b/project/realtek_ameba1_va0_example/example_sources/i2s/src/birds_24000_2ch_16b.c new file mode 100644 index 0000000..6bb37b0 --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/i2s/src/birds_24000_2ch_16b.c @@ -0,0 +1,17496 @@ +#include +int sample_size=69958; + +SECTION(".sdram.data") +short sample[]={ +-1, 1, 0, 0, -1, 2, -1, 0, +2, 0, -3, 4, -4, 3, 1, -1, +2, 0, -1, 0, 2, -2, 1, 1, +-3, 1, 1, -1, 2, -1, -1, 2, +-4, 3, -1, 1, 2, -2, -1, 0, +3, -2, 4, -4, 1, -3, 3, -2, +1, 0, 3, -5, 2, -1, 0, 2, +-2, 1, -3, 1, 2, -1, 1, -1, +-3, 1, 0, 0, 3, -1, -6, 4, +0, 0, 1, 1, -2, -1, 0, 0, +1, 1, 4, -5, 1, -1, 3, 1, +-2, 2, -2, -2, 5, -3, 2, 0, +-2, 0, 2, -2, 4, -1, -2, -1, +3, -2, 0, 3, -3, 1, 0, -2, +4, -2, 2, -2, -2, -1, 3, -1, +0, 1, -1, -2, 1, 1, 0, 1, +-1, -1, -3, 4, 0, 2, 0, -2, +1, -1, -1, 3, 0, -1, -2, 1, +1, 0, 3, -3, 0, -3, 4, -3, +2, 1, -1, -2, 3, -2, 1, 2, +-4, 3, -3, 1, 2, 1, -1, -1, +2, -2, -1, 4, -2, 1, -1, -1, +4, -4, 4, -1, -3, 1, 1, -1, +1, 1, -4, 3, -2, 0, 4, -3, +2, -3, -1, 1, -1, 2, 1, -3, +1, -1, -2, 3, -3, 2, -1, -1, +1, -1, 3, -1, -3, 2, -2, 2, +-2, 4, -4, 2, 0, 0, 1, 0, +0, 0, -2, 2, -1, 2, -2, 2, +-2, 1, 1, 0, 0, 1, -1, 1, +0, 0, 0, 1, 0, -1, 3, -2, +2, -1, 0, -1, 1, -2, 2, -1, +1, -1, 0, -1, 3, -2, 1, -1, +-1, 0, 1, -1, -1, 2, -2, 1, +0, -1, 2, -1, -3, 2, -2, 2, +-2, 3, -3, 1, -1, 1, -2, 3, +-1, 0, 1, -2, 1, 1, -4, 4, +-5, 4, -2, 1, 1, -2, 0, 0, +0, 0, 1, 0, -1, 1, 0, 1, +1, 0, 1, -2, 1, 1, -3, 3, +1, -1, -1, 2, -1, 1, 2, -2, +1, 0, -1, 2, 2, -3, 4, -3, +-1, 2, 1, -1, -2, 3, -3, 1, +2, -1, -3, 3, -2, 2, -1, 2, +-3, 3, -5, 4, 0, 0, 0, 0, +-1, -1, 3, -3, 1, 0, -2, 2, +-3, 2, -1, 1, -3, 2, -1, 1, +0, 1, -3, 2, 0, -1, 3, -2, +0, 1, -3, 2, 1, -1, 2, -2, +0, 0, 2, -3, 4, -3, 0, 0, +1, 0, 2, -1, 1, 0, -2, 3, +0, 0, 1, 0, -3, 3, 1, -2, +1, 0, 0, -1, 2, 0, 0, 0, +-1, 2, -3, 4, -3, 3, -3, 1, +0, 0, -3, 4, -6, 4, -3, 3, +-3, 4, -3, 1, -2, 3, -5, 5, +-3, 2, -2, 1, -3, 4, -3, 2, +1, -3, 4, -4, 3, -2, 2, -3, +1, -1, 2, -2, 1, 0, -1, 1, +0, 1, -1, 0, 1, -1, -2, 4, +-4, 5, -3, 2, 1, -1, 2, -2, +3, -2, 0, 2, -2, 2, 1, -2, +2, -2, 0, 1, 0, 0, 0, 0, +0, 0, 0, 1, -1, 0, 2, -2, +2, -1, -1, 1, -2, 2, 1, -1, +1, 0, -4, 4, -1, 0, -1, 0, +0, -2, 2, -1, -1, 1, 0, -2, +3, -4, 2, -2, 1, -2, -1, 2, +0, -1, 3, -4, 5, -5, 3, -1, +0, 0, 1, 0, -2, 2, -1, 2, +-4, 5, -3, 2, 3, -2, 0, 1, +1, -1, 3, -1, 1, -1, 1, -1, +0, 1, -1, 2, -2, 2, 0, 0, +0, 1, -1, 2, -2, 1, 2, -2, +1, 0, -1, 2, -2, 3, -2, 0, +2, -2, -2, 2, -1, 0, 1, -2, +2, -1, -1, 1, 0, -1, 0, 0, +-1, 0, -3, 3, -3, 1, -2, 2, +-3, 2, 0, -1, 1, -2, 1, -1, +-2, 3, -6, 5, 0, -1, 3, -4, +6, -5, 2, -2, 3, -3, 1, 2, +-5, 4, -2, 1, 1, -2, 4, -3, +-1, 2, -1, 1, 3, -4, 3, -2, +1, 0, -1, 1, 0, -1, 1, 0, +0, 0, 1, 0, 1, -1, 1, 0, +-2, 2, -1, 0, 2, -1, 1, -1, +2, -2, 1, 0, 1, -2, -2, 3, +-4, 3, 1, -2, 1, -2, 3, -3, +1, 0, 0, -1, 0, -1, -2, 3, +-3, 1, 1, -3, 0, 0, -1, 1, +1, -2, 1, -1, 0, 0, 0, 0, +-1, 2, -1, 1, 2, -2, 2, -2, +2, -1, 2, -2, 1, 0, 0, 0, +3, -2, 2, -2, 3, -2, 2, -1, +1, -1, 1, -1, 5, -4, 5, -4, +4, -4, 1, 1, -2, 3, -2, 2, +1, -2, 4, -3, 1, 0, -1, 0, +1, -2, 1, 0, -3, 2, 0, -1, +-1, 1, -3, 2, -1, 0, 0, 0, +-2, 1, -1, 1, -4, 3, -2, 0, +0, 0, -2, 2, -1, 0, 1, -2, +3, -3, 4, -4, 2, -1, 0, 0, +0, 0, -3, 3, 0, 0, 2, 0, +-1, 1, 0, 1, -1, 3, -3, 3, +0, -1, 3, -2, 3, -3, 4, -3, +0, 1, 3, -3, 3, -1, 1, -1, +4, -3, 1, 1, -2, 3, -1, 2, +-1, 0, 0, 0, -2, 3, -3, 3, +-1, 0, 2, -2, 0, 0, -1, 1, +-2, 2, -1, -1, 3, -3, 1, -1, +-1, 0, 1, -2, -1, 1, 0, -1, +-1, 2, -4, 3, -1, 0, 0, -1, +0, 0, -2, 2, 0, -1, 0, 0, +1, -1, 1, 0, -3, 3, 0, 0, +0, 1, -3, 3, -1, 2, -1, 1, +1, -1, 1, 0, 1, 0, 0, 0, +1, 0, 2, -2, 3, -2, -1, 1, +3, -3, 0, 2, -3, 2, 1, 0, +0, 0, -2, 2, -4, 4, 2, -4, +3, -2, -4, 4, -1, 0, 1, -2, +1, -2, 1, 0, -2, 1, -1, -1, +1, 0, -3, 4, -3, 1, 0, 1, +-2, 3, -3, 1, 0, 0, 0, 1, +0, -1, 3, -4, 3, -1, 2, -2, +-1, 2, -1, 1, 1, 0, -2, 1, +1, 1, -3, 3, -1, 0, 1, -1, +3, -2, -1, 1, -1, 1, 0, 1, +-4, 5, -5, 3, 2, -1, -1, 3, +-3, 2, 3, -3, 1, 0, -2, 0, +3, -2, -2, 3, -3, 2, -2, 2, +-2, 2, -3, 2, -2, 2, -4, 4, +-1, -2, 2, -2, 1, -2, 2, -3, +3, -3, 4, -3, 1, -2, 0, -1, +-2, 2, 0, 0, 0, 1, -1, 0, +3, -2, -2, 2, -1, 0, 1, 0, +2, -3, 3, -2, 0, 0, 1, -2, +3, -2, 1, 1, -4, 4, -2, 2, +1, 0, 3, -3, 1, -1, 2, -1, +1, -1, 1, -2, 1, 0, 1, -1, +0, -1, 0, 0, 0, 1, -2, 1, +-1, 0, 3, -3, 3, -3, 1, -1, +0, 1, -2, 3, -7, 6, -4, 3, +-1, 2, -3, 1, 0, -1, 2, -2, +1, -2, -1, 1, -1, 1, 0, -1, +-1, 0, 1, 0, 1, 0, -2, 2, +-1, 1, 2, -2, 0, -1, 3, -2, +-1, 3, -3, 0, 3, -3, 1, 1, +-1, -1, 2, -3, 4, -2, 1, -1, +1, -2, 1, 0, 1, 0, -3, 3, +0, 0, 1, 0, -2, 1, -1, 1, +2, -1, 0, 1, -3, 1, 3, -2, +-1, 2, -6, 5, -1, 2, -4, 4, +0, -3, 6, -5, 3, -3, 1, -1, +-1, 1, 1, 0, -4, 4, -4, 2, +2, -2, 1, -1, -1, 0, 0, 1, +-4, 5, -5, 3, 2, -4, 4, -2, +0, -1, 4, -5, 4, -2, 0, -1, +1, -1, 0, 1, -3, 3, -2, 2, +-3, 3, 0, -1, 2, -1, 0, 1, +0, 0, 1, -1, 2, -2, 4, -3, +1, 0, 0, 1, -4, 5, -4, 3, +0, 1, 1, -2, 1, 0, -3, 2, +1, -1, -1, 1, -2, 2, -2, 2, +-3, 2, -2, 2, -1, 0, 1, -1, +-1, 1, -1, 0, 1, -2, -1, 1, +-1, 1, 1, -2, 2, -2, -1, 3, +-4, 3, -2, 1, -3, 4, -4, 4, +-1, -1, 4, -4, 2, 0, -1, -1, +4, -4, 2, 0, 0, -1, -1, 0, +1, -1, 1, 0, -1, -1, 3, -2, +1, 0, 0, 0, 1, 0, 0, 2, +-2, 1, 0, -1, 3, -2, 1, -1, +2, -3, 1, 0, -1, 0, 0, -1, +-1, 2, -3, 3, 0, -3, 5, -4, +1, 1, -3, 3, -3, 1, 0, 1, +-1, -1, 1, -2, -1, 2, 0, -1, +0, -1, 1, -1, 1, -1, 1, -2, +-3, 4, 1, -2, 1, 1, -3, 2, +4, -3, 1, 0, -3, 2, 0, 0, +2, -1, -3, 3, 0, 1, 0, 2, +-2, 1, 1, -1, 1, 0, -1, 1, +1, -2, 3, -2, 0, 1, -3, 2, +1, -1, -1, 2, -1, -1, 1, -1, +0, 0, -2, 2, -1, 0, 3, -2, +-2, 3, -3, 2, 1, -1, 0, 1, +-2, 1, 1, -1, 2, -3, 3, -4, +1, 0, 1, -1, 3, -3, 0, 1, +0, 0, 0, -1, 1, -1, 1, 0, +-1, -1, 3, -4, 4, -3, 2, 0, +-3, 2, 2, -2, -1, 3, -1, 0, +0, 1, -2, 3, -3, 3, -1, -1, +4, -4, 1, 0, 1, -2, 2, 0, +-3, 2, 2, -3, -1, 2, -2, 1, +1, -1, 0, 1, -2, 3, -2, 1, +1, -2, 0, -1, 4, -5, 5, -4, +0, 1, -2, 2, -1, 1, -3, 3, +-4, 3, -2, 2, -2, 1, 1, -2, +3, -2, -1, 1, -1, 0, 0, 0, +0, 0, 2, -2, -1, 3, -2, 1, +1, -1, 0, -1, 3, -2, -1, 1, +-1, 1, 0, 0, 2, -1, -2, 3, +-2, 2, 1, 0, 0, 0, 1, -1, +1, -1, 1, -2, 2, -2, 1, -1, +0, 1, -2, 1, 0, 0, -2, 3, +-3, 2, 1, -1, 3, -3, -1, 1, +-3, 3, -1, 2, -4, 3, -2, 1, +1, -1, 0, -1, 1, -2, 1, 0, +0, -1, 1, -2, 2, -2, 1, 0, +-1, 0, 0, 0, 0, 1, -2, 1, +-2, 1, -1, 1, -1, 0, 1, -1, +2, -1, 0, 1, -2, 1, 3, -2, +1, -1, 2, -2, 1, 0, 0, 1, +-1, 0, 1, -1, 0, 1, 0, 0, +-4, 5, -3, 1, 1, 0, -1, 1, +1, -1, 1, -1, -1, 1, -1, 1, +1, -1, -2, 2, -1, 0, 2, -2, +2, -3, 1, -1, -1, 1, 0, 0, +-2, 1, 0, -1, -1, 3, -6, 6, +-4, 3, -1, 1, -2, 1, 0, -1, +1, -1, -1, 1, -2, 2, -1, 0, +0, 0, 1, -2, 5, -5, 2, -1, +3, -3, 3, -3, 1, -1, 1, -2, +3, -3, -1, 3, -3, 3, -3, 4, +-4, 4, -1, 1, -1, 1, -1, 1, +0, 0, 0, 0, -2, 2, -3, 3, +-2, 2, -3, 3, -2, 1, 0, 1, +0, 0, -1, 1, -2, 2, -2, 2, +-3, 2, -1, 0, 2, -2, 1, -1, +0, -1, 3, -3, -1, 2, -1, -1, +2, -1, -1, 2, 0, -1, 1, 0, +-1, 1, -2, 2, -2, 2, 0, 0, +-2, 2, -3, 2, 0, 0, -2, 3, +-3, 2, 0, 0, 1, -2, 3, -4, +2, 0, 0, 0, 1, -1, 0, 0, +2, -3, 2, -2, 0, 0, 2, -2, +1, -1, 2, -3, 2, -1, -1, 1, +0, -2, 2, -1, -1, 1, 0, -2, +3, -2, 0, 0, -1, 1, 0, -1, +1, 1, -4, 4, -2, 0, 0, 1, +1, -2, 2, -1, -2, 3, -1, 1, +0, 0, -1, 2, -2, 2, 1, -1, +3, -3, 4, -4, 1, 0, 0, 0, +0, 1, 0, -1, 2, -3, 1, 0, +-1, 2, -2, 1, 2, -3, 2, 0, +1, -2, 2, -1, -1, 1, 4, -4, +1, 0, -1, 0, 2, -2, 1, 0, +-1, 0, 1, -1, 0, 1, 0, -1, +1, -1, 1, 0, -2, 2, -1, -1, +2, -2, -1, 1, -1, 1, -3, 3, +-3, 1, 2, -3, 2, -1, -1, 1, +0, 0, 0, 1, -2, 1, 1, -1, +-3, 4, -2, 1, 2, -1, -1, 0, +1, -1, 1, 0, 1, -2, 1, -1, +1, -2, 2, -1, -2, 2, 1, -1, +-2, 3, -2, 0, 3, -2, 1, -1, +2, -2, 0, 1, -1, 1, -2, 2, +0, -1, -1, 2, -5, 5, -5, 4, +-1, 1, 1, -1, 1, -2, 1, 0, +0, 0, 1, -1, -1, 1, 0, 0, +-1, 0, -1, 1, -3, 3, -2, 1, +0, 0, -1, 2, -1, 0, 1, -2, +3, -3, 4, -4, 3, -3, 2, -3, +2, -1, 0, 0, 2, -3, 2, -1, +-2, 3, -4, 3, -1, 1, 3, -4, +2, -1, -2, 2, -2, 3, -4, 4, +0, -1, 2, -1, -2, 2, 0, -1, +2, -1, -1, 1, 3, -4, 3, -1, +0, -1, 2, -3, 2, -2, 1, -2, +1, 0, -3, 4, -4, 3, -2, 2, +-1, 0, 1, -1, 2, -2, 2, -1, +-1, 1, 1, -1, 1, 0, 0, 0, +1, -1, 2, -3, 2, -1, -3, 4, +-2, 1, 0, 0, -1, 1, -1, 1, +0, 0, -1, 2, -1, 0, -1, 2, +-2, 1, 2, -2, 2, -1, 2, -1, +0, 0, 0, 0, -1, 1, -1, 1, +-1, 0, 2, -1, -2, 3, -1, -1, +1, 0, 0, -1, 2, 0, -4, 4, +0, -1, 1, -1, 1, -1, -1, 2, +-3, 3, -1, 0, 2, -2, -1, 0, +4, -6, 2, 0, -2, 1, 0, 0, +-2, 2, 2, -4, 5, -5, 1, 0, +-2, 2, -1, 0, 0, 0, 2, -1, +-1, 1, -1, 0, 0, 1, 0, -2, +6, -5, 0, 3, -2, 1, -1, 1, +-1, 1, 1, -1, -1, 2, -2, 3, +-3, 3, -1, 0, 0, 1, 0, -1, +3, -3, -1, 2, -3, 2, 0, -1, +3, -4, 4, -4, 1, 0, -1, 1, +1, -2, 2, -2, 1, -1, 2, -1, +1, 0, 0, -1, 1, -1, 0, 1, +-3, 2, 2, -3, 0, 2, -1, 0, +0, 1, -2, 2, -2, 3, -5, 4, +-3, 3, -2, 0, 1, -1, -2, 2, +0, 0, -2, 3, -2, 1, 1, 0, +-1, 0, 2, -3, 1, 0, -1, 0, +0, 1, -1, 0, 2, -2, 3, -3, +3, -3, 1, 0, -1, 1, 0, -1, +1, -1, 0, -1, 2, -2, 1, -1, +0, 1, -2, 2, 2, -3, 4, -3, +1, -1, 3, -3, 0, 1, -1, 0, +2, -1, -1, 1, -1, 0, 2, -2, +3, -3, 2, -2, 1, -1, 4, -5, +4, -3, 1, -1, 2, -1, -2, 2, +0, -1, 2, -1, 1, -1, 1, -1, +4, -4, 2, 0, -3, 3, -2, 1, +0, 0, 1, -1, 0, 1, -2, 3, +-1, 0, 1, -1, 2, -3, 5, -4, +0, 1, -2, 1, 0, 0, -1, 0, +1, -1, -2, 4, -4, 3, 1, -2, +4, -2, -1, 2, -1, 0, -1, 2, +-2, 1, 1, -2, 3, -3, 1, 1, +-2, 2, -1, 2, -1, 0, 3, -3, +0, 0, 0, 0, 0, -1, 2, -2, +-3, 4, -1, -1, 1, 0, -1, 0, +0, 0, -1, 0, 0, 0, -1, 0, +1, -2, 1, -2, 2, -2, 0, 0, +1, -1, 1, -1, 0, 0, -2, 2, +-1, 1, -3, 3, -1, 0, -2, 3, +-2, 1, 0, 0, -3, 3, 0, 0, +0, 0, 1, -1, 0, 1, 0, 0, +-2, 3, -2, 1, 3, -3, 2, -2, +3, -2, -1, 2, -4, 3, 0, -1, +1, 0, -3, 2, 0, 0, -1, 2, +-1, 0, 1, -1, -1, 1, -1, 0, +-2, 2, -2, 2, -3, 2, 0, 0, +1, -1, 2, -2, 1, 0, 1, -1, +2, -1, 1, 0, 0, 0, 2, -3, +2, 0, -4, 3, 0, -1, -1, 1, +-1, 1, 1, -1, 1, -1, 2, -2, +2, -1, -1, 2, -1, 0, 1, -2, +5, -5, -1, 3, -4, 2, 2, -2, +0, -1, 2, -1, -1, 2, 1, -2, +1, -1, 1, -2, 2, -2, 0, 0, +-2, 3, -2, 1, -3, 3, -2, 1, +0, 0, 1, -1, 3, -2, 1, -1, +-2, 3, -2, 1, 2, -1, -1, 1, +1, -1, 1, -1, -1, 1, -2, 2, +0, -1, 2, -2, 1, -1, 1, -1, +-2, 3, -3, 2, 1, -1, -1, 1, +1, -2, 1, 1, -2, 1, 1, -1, +1, -2, 5, -4, -1, 2, -1, 0, +1, -1, 1, -1, -1, 1, -2, 1, +1, 0, -2, 2, 1, -2, 3, -3, +-1, 2, -3, 2, 3, -4, 1, 0, +-3, 3, -2, 2, 0, -2, 3, -2, +1, -1, 1, 0, -2, 2, 0, 0, +-1, 2, -1, 0, 0, 0, 1, -1, +1, -2, 3, -2, -2, 3, 0, -2, +3, -2, -2, 2, -1, 0, 0, -1, +0, 1, -4, 5, -4, 2, 2, -3, +2, -1, -2, 3, -3, 3, 0, -1, +1, -1, -1, 1, -1, 2, -1, 1, +1, -1, -2, 3, -2, 1, -2, 2, +-2, 2, 1, -2, 2, -1, -1, 1, +-1, 2, -3, 2, 1, -2, 3, -2, +3, -3, 2, -1, 0, 0, 1, -1, +1, -2, 1, -1, 1, -1, 1, 0, +-2, 2, -1, 1, -1, 2, -3, 3, +-2, 1, 0, -1, 1, -1, 2, -3, +1, 0, -2, 2, -2, 2, -3, 3, +-1, 1, 1, -1, 2, -1, -2, 2, +1, -1, -1, 2, -2, 1, 0, 1, +-4, 3, 0, -1, 1, 0, -2, 1, +0, -1, 1, -2, 2, -2, -1, 2, +-2, 1, -2, 2, -2, 1, 2, -2, +2, -1, 0, 1, -1, 0, 1, 0, +-3, 4, -1, 0, -1, 2, 0, -2, +3, -3, 1, -1, 0, 1, 0, 0, +2, -2, 1, -1, 4, -4, 3, -2, +0, 0, -1, 1, -1, 0, 1, -1, +0, 1, 0, -1, 0, 0, 0, -1, +2, -2, -1, 2, -3, 2, 1, 0, +-3, 4, -2, 1, -2, 3, -4, 2, +2, -3, 2, -1, 0, 0, 0, 0, +0, 0, -2, 3, -4, 3, 2, -2, +-2, 3, -1, -1, 1, 0, -1, 1, +-1, 1, -2, 2, 1, -2, 1, 0, +-1, 0, 3, -3, 4, -4, 4, -3, +-2, 3, 0, -2, 3, -2, -1, 2, +0, 0, 0, 0, 0, 0, 1, -1, +1, -1, 0, 2, -3, 3, -2, 2, +-4, 4, 0, -2, 2, 0, -1, 1, +1, -1, 1, -1, 1, 0, -1, 1, +1, -1, 2, -1, -2, 4, -6, 5, +-2, 0, 1, 0, 1, -1, 2, -2, +-1, 1, -1, 2, -3, 3, -3, 3, +-2, 1, 1, 0, -2, 2, 2, -3, +1, 1, -1, 0, 4, -4, 1, 0, +-2, 3, -2, 2, 1, -1, 0, 0, +0, 0, 1, -1, 0, 1, -3, 4, +-3, 1, 1, -2, 2, -2, 0, 1, +-4, 4, -1, 0, 0, 0, 2, -4, +4, -3, 1, -1, 3, -2, 0, -1, +2, -1, -1, 0, 4, -4, 1, 0, +1, -1, 2, -2, 1, -1, 3, -3, +4, -3, -2, 3, -1, 0, 1, -1, +0, 0, 1, -1, -1, 1, 1, -1, +1, -1, 3, -3, 2, -1, 0, -1, +1, 0, 0, -1, 1, -1, 0, 0, +-1, 1, 1, -1, 1, 0, 0, -1, +1, 1, -5, 4, 1, -3, 1, 2, +-5, 5, 0, -1, 1, 0, -2, 2, +-3, 3, -2, 2, 1, -2, 3, -3, +1, -1, 2, -2, -1, 2, -2, 2, +0, -1, 0, 1, -4, 4, -2, 1, +-2, 3, -3, 2, -2, 2, -1, 0, +3, -2, -1, 2, -2, 1, 0, 0, +-2, 2, -1, 1, -1, 1, 0, -1, +0, 1, 0, -1, 2, -2, 1, 0, +-1, 1, -3, 3, -2, 0, 3, -3, +-1, 4, -5, 3, 2, -3, 1, 0, +0, -1, 1, 0, -2, 2, 1, -2, +2, -1, -2, 2, 0, -1, 1, -1, +2, -2, 0, 1, -1, 1, 3, -4, +5, -4, -1, 3, -6, 5, -1, -1, +2, -2, 2, -3, 2, -2, 1, -1, +1, -1, -2, 3, -2, 2, -1, 1, +1, -1, 3, -3, 1, 0, -1, 0, +2, -2, 0, 1, 0, -1, 4, -3, +0, 1, 0, -1, 2, -1, -1, 2, +-2, 2, -2, 1, 2, -2, -2, 3, +-1, -1, 3, -2, 0, 0, 3, -4, +2, 0, -1, 0, 4, -4, 2, -1, +1, -1, 3, -4, 4, -3, -1, 2, +-2, 1, 2, -2, 2, -1, 0, -1, +3, -4, 4, -2, 0, 1, -2, 2, +0, -1, 0, 1, -1, 0, 0, 0, +-2, 2, 0, -1, -1, 2, -1, 0, +4, -4, 1, 0, 0, -1, 2, -2, +2, -2, 2, -2, 1, 0, -2, 2, +0, 0, 0, 0, 1, -1, -1, 1, +0, -1, 3, -2, 0, 0, 1, -1, +0, 0, -1, 2, -3, 3, -1, 0, +1, -1, 1, 0, -1, 1, 1, -1, +0, 0, 2, -2, 1, 0, -2, 1, +2, -2, -1, 2, -4, 3, -2, 1, +1, -2, 1, -1, 1, -1, 1, 0, +-3, 4, -3, 2, 1, -2, 3, -2, +-1, 2, 0, -1, -1, 2, -2, 2, +-3, 4, -4, 3, 0, 0, -2, 2, +1, -2, 5, -4, 2, -1, 1, -2, +2, -2, 0, 0, -1, 2, -1, 1, +3, -4, 4, -2, -1, 1, 0, 0, +-1, 1, -2, 2, -2, 1, 0, 0, +-2, 2, 1, -2, 2, -2, 2, -2, +0, 1, -1, 1, 0, 0, 0, 0, +-1, 1, 0, -1, 2, -1, -1, 1, +1, -2, -1, 2, -3, 2, 1, -1, +2, -2, 1, -1, 1, -1, -1, 2, +-3, 1, 4, -4, 1, 1, -2, 2, +-1, 1, 0, 0, -2, 2, 1, -2, +0, 2, -3, 2, 1, -1, -1, 1, +0, 1, -3, 3, 0, -2, 2, -2, +1, -1, -1, 1, 1, -2, 5, -5, +1, 0, 1, -2, 3, -4, 3, -3, +1, 0, 0, -1, 3, -4, 1, 0, +-2, 2, -1, 0, 0, 0, 1, -2, +3, -3, 1, 0, -1, 1, -1, 1, +0, 0, 1, 0, -2, 2, 0, -2, +3, -3, 0, 0, 0, 0, -2, 2, +0, -1, 1, -1, 0, -1, 2, -1, +-1, 2, -3, 3, -2, 1, 0, -1, +3, -3, 2, -2, 0, 0, 1, -2, +3, -3, 3, -2, 2, -1, -1, 1, +0, 0, -2, 3, -3, 1, 1, -1, +-1, 2, -1, 1, 1, -2, 1, 0, +-1, 0, 1, -1, -1, 1, 2, -3, +-1, 3, -4, 3, 1, -2, 2, -1, +0, 0, -1, 1, -1, 1, 2, -3, +1, 1, -2, 1, 3, -4, 5, -4, +3, -2, 1, 0, 0, 0, 1, -1, +0, 1, -2, 2, 1, -2, 2, -2, +1, -1, -2, 3, -2, 1, 0, 1, +-3, 3, 0, -1, 1, 0, -4, 4, +-3, 2, 0, -1, 1, -2, 2, -1, +0, 0, 2, -3, 2, -1, 0, -1, +0, 1, -5, 6, -2, 0, 2, -1, +0, 0, 3, -4, 3, -2, 1, -1, +0, 0, 1, -1, 0, 1, 0, 0, +2, -2, 2, -2, 3, -3, 0, 1, +-2, 1, 1, -1, -1, 2, -2, 1, +2, -3, 3, -2, -1, 1, 1, -1, +-1, 3, -4, 4, -1, 2, -4, 4, +0, -1, 1, 1, -2, 1, 1, -1, +-1, 2, -2, 2, 0, -1, 2, -1, +-2, 2, -1, 0, 0, 1, -3, 3, +-1, -1, 4, -4, 2, -1, -1, 2, +-1, 1, -1, 2, -4, 3, 0, -1, +0, 0, 0, -1, 3, -2, -2, 3, +-2, 0, 3, -4, 4, -3, 1, -1, +1, -1, 1, 0, 1, -1, -1, 1, +2, -3, 2, 0, -3, 3, -1, 1, +-2, 2, -1, 1, 1, -1, 0, 0, +0, -1, 3, -3, 0, 1, -2, 1, +1, -1, -1, 1, -3, 3, -2, 1, +-1, 1, -4, 5, -5, 4, -3, 3, +-3, 1, 3, -4, 2, -1, -1, 0, +3, -4, 3, -2, 2, -3, 3, -2, +-2, 3, -2, 1, 3, -4, 2, -1, +-1, 1, -1, 1, -1, 2, -5, 6, +-4, 3, -1, 1, 0, 0, -1, 2, +-3, 3, -1, 0, 5, -6, 5, -3, +0, 1, -2, 2, 1, -2, 2, -1, +-3, 3, -1, 0, 1, -1, 0, 0, +-2, 2, 1, -2, 2, -1, 1, -1, +1, -1, 0, 1, -2, 2, -1, 0, +0, 0, -1, 1, 1, -1, 0, 0, +0, 0, -3, 4, 0, -2, 4, -4, +2, -2, 2, -3, 1, 0, -1, 1, +1, -1, 0, 1, -2, 2, -1, 1, +-2, 3, -3, 2, 0, 0, -2, 2, +-1, 0, 2, -2, -1, 2, -4, 4, +-4, 4, -3, 3, -1, 1, -1, 2, +-3, 2, -1, 1, -1, 0, 1, -1, +1, 0, -1, 1, 0, 0, 0, -1, +2, -3, 1, 0, -1, 1, 0, -1, +0, 1, -1, 0, 3, -3, 2, -1, +1, -1, 3, -3, 2, -2, 3, -3, +3, -3, 1, -1, 1, -1, 0, 1, +-2, 2, -1, 1, 0, -1, 4, -3, +2, -2, 4, -4, 2, -1, -1, 0, +1, -2, 3, -4, 4, -4, 0, 1, +-2, 1, 0, 0, 0, 0, 0, 0, +-1, 1, 1, -1, 0, 1, -2, 2, +-2, 2, -1, 0, -1, 0, 2, -2, +0, 2, -2, 1, 3, -3, 2, -2, +1, -1, -3, 3, -2, 0, 1, -1, +2, -2, 0, 1, -2, 1, 1, -1, +-1, 1, -3, 3, -5, 4, -1, -1, +3, -2, -3, 4, -4, 3, -2, 2, +-4, 4, 0, -1, 1, 0, -2, 2, +1, -1, 0, 0, -1, 1, 0, 0, +0, 0, -1, 1, -2, 2, 0, 0, +1, -2, 3, -4, 3, -3, -1, 1, +-1, 1, 1, -1, 0, 1, -1, 1, +1, -2, 1, -1, 1, -1, -1, 1, +0, -1, 1, 0, -1, 2, -3, 3, +-4, 4, -2, 1, -1, 0, 1, -1, +4, -4, 5, -2, -4, 6, -2, 0, +1, -1, -1, 1, -2, 3, -3, 4, +-3, 3, 0, -1, 1, 0, -3, 3, +1, -2, 2, -1, 1, -1, 2, 0, +-1, 2, -1, 1, 1, -3, 1, -1, +-1, 0, 1, 0, -1, 2, 0, -1, +4, -4, 4, -4, 2, -2, -2, 2, +-3, 3, -3, 4, -2, 3, 2, -3, +2, -2, -2, 2, -2, 1, -2, 2, +-2, 2, 0, 0, 1, -1, 0, 0, +-2, 1, -3, 1, -1, 2, -4, 4, +1, -1, 1, 1, -2, 1, -1, 0, +-2, 1, 1, -1, -1, 3, 0, -1, +3, -1, -3, 5, -3, 0, 3, -4, +0, -1, 3, -4, 5, -3, 3, -1, +0, 2, -2, 2, -3, 2, -3, 1, +1, -2, 3, -2, 4, -3, 3, -1, +-1, 1, -2, 1, -3, 2, -2, 1, +-1, 3, -1, 2, 2, -1, 0, 0, +-3, 3, -5, 3, -2, -1, 2, -1, +0, 2, 1, 0, 1, 0, -3, 2, +-2, -1, -1, 0, -4, 4, -1, 1, +1, 1, -2, 3, -3, 2, -4, 2, +-2, 0, 0, -1, 2, -1, 2, -1, +4, -3, 0, 2, -6, 3, -4, 3, +-5, 3, 3, -2, 2, 2, -1, 3, +-2, 3, -5, 2, -1, -2, -2, 2, +-2, 2, 0, 3, -3, 6, -3, 4, +-4, 2, -1, -2, -1, 0, -1, 0, +1, 1, 1, 1, -1, 3, -5, 4, +-3, 0, 0, -3, 3, -3, 1, 1, +3, -2, 2, 2, -4, 3, -2, 1, +-6, 3, -2, 1, -2, 4, -2, 3, +2, -1, 2, -1, -2, 2, -4, 1, +-2, 1, -1, 2, 0, 1, 4, -2, +4, -2, 0, -1, -4, 2, -5, 1, +2, -3, 4, -2, 5, -2, 4, -1, +0, 0, -3, 1, -5, 2, -1, -1, +1, 1, 1, 2, 1, 2, -1, 2, +-4, 2, -4, 0, 1, -3, 1, 1, +3, -1, 4, 0, 0, 1, -3, 1, +-4, 1, -2, 1, -3, 4, 0, 1, +3, 0, 1, 1, -1, 0, -3, -1, +-1, -2, 0, -1, 4, -2, 3, 1, +1, 0, 0, 1, -4, 1, -3, -1, +-3, 1, 2, -1, 4, 0, 2, 0, +1, 0, -3, 1, -3, -2, -2, 0, +1, -2, 6, -2, 3, 2, 1, 0, +0, -1, -4, 0, -4, 0, -1, 1, +2, 0, 6, -2, 3, -1, 1, -1, +-6, 2, -2, -3, 2, -3, 2, 0, +4, -1, 4, 0, -3, 4, -5, 0, +-3, 0, -5, 2, 2, -1, 3, 1, +5, -1, 0, 2, -3, -1, -2, -2, +-1, -1, 0, 1, 3, 0, 6, -2, +3, -1, 3, -6, 0, -2, -5, 2, +0, -1, 4, -2, 8, -2, 2, 1, +2, -4, -1, -1, -5, 1, -2, 0, +1, 1, 4, 0, 2, 2, -1, 1, +-4, 0, -2, -3, -1, 0, 1, 1, +4, 0, 4, 0, 1, 0, -2, -1, +-5, 0, 0, -4, 3, -2, 3, 1, +2, 4, -2, 4, -2, -2, -1, -3, +-4, 0, -4, 3, -1, 3, 6, -2, +2, 3, -3, 1, -2, -2, -6, 2, +-2, -1, 6, -3, 2, 4, 2, 0, +3, -2, -3, 0, -5, 0, -2, -2, +2, 0, 3, 1, 6, -1, 1, 2, +-5, 2, -7, 1, -4, 1, -2, 1, +6, -4, 8, -3, 4, -2, 1, -2, +-5, 1, -4, -2, 2, -3, 5, -2, +7, -1, 3, 1, -1, 1, -6, 2, +-3, -4, 4, -6, 4, -1, 5, 0, +6, -2, 2, -1, -3, -1, -1, -5, +1, -4, 0, 2, 0, 5, 2, 3, +1, 0, -2, 0, -8, 3, -8, 3, +-1, 0, 4, 0, 6, 0, 3, 0, +-2, 1, -5, 0, -4, 0, -5, 4, +2, 0, 6, 1, 4, -1, 0, 1, +-9, 6, -10, 4, -4, 0, 4, -3, +7, -1, 4, 1, 2, -1, -4, 2, +-9, 2, -3, -2, 1, 0, 7, -3, +7, 0, 1, 1, -2, 0, -9, 4, +-8, 3, -3, 2, 4, -1, 10, -4, +8, -3, 1, -2, -6, 2, -9, 3, +-2, -1, 3, 1, 4, 1, 5, 0, +-1, 1, -2, -3, -5, -1, -3, 0, +2, 0, 5, 0, 5, 0, 3, -1, +-5, 2, -5, -2, -3, 1, -2, 1, +5, 0, 4, 2, 5, -2, 0, -1, +-5, -1, -3, -2, -2, 2, 2, 0, +10, -4, 6, 0, -2, 1, -6, 1, +-5, -1, -1, -1, 4, -1, 5, 1, +4, 1, -1, 3, -7, 2, -5, -1, +-5, 2, -1, 1, 4, 1, 5, 0, +2, 1, -4, 1, -5, -2, -1, -3, +-1, 2, 4, 1, 3, 4, 0, 2, +-2, 0, -8, 2, -6, 1, -3, 1, +3, 0, 5, 1, 5, -1, 1, 0, +-4, -1, -3, -3, -2, 1, 0, 1, +5, 1, 6, -1, 2, 0, -5, 1, +-6, 0, -6, 1, 2, -1, 7, -2, +6, 1, 1, 0, 0, -3, -4, -2, +-3, -2, 2, -3, 6, -1, 4, 2, +4, -1, -3, 3, -7, 0, -3, -2, +-2, 1, 0, 4, 3, 1, 5, 0, +0, 0, -2, -3, -5, -1, -1, -3, +4, -1, 2, 4, 3, 2, 1, 0, +-1, -2, -6, 1, -4, -1, 2, -1, +6, -1, 5, 2, -2, 4, -5, 2, +-6, -1, -2, -2, 0, 0, 5, -2, +10, -4, 7, -3, 0, 0, -4, -2, +-4, 0, -6, 4, 4, -3, 10, -3, +5, 0, -1, 2, -6, 1, -5, -1, +-4, 1, 2, -1, 7, -2, 7, 0, +-1, 4, -6, 2, -5, 0, -5, 1, +1, -2, 7, -2, 8, -1, 2, 1, +-1, -2, -3, -1, -6, 2, -1, -1, +4, 0, 2, 4, 2, 1, -3, 2, +-7, 1, -3, -4, 3, -4, 3, 0, +7, -2, 6, 0, 2, -2, -1, -1, +-7, 2, -5, 2, 0, 1, 6, -1, +6, 0, 3, -1, -3, 1, -7, 2, +-8, 3, -1, 0, 4, -1, 6, -2, +3, 0, -3, 1, -6, 1, -6, 1, +-2, 1, 1, 2, 5, 0, 2, 3, +-4, 3, -6, 3, -7, 3, -4, 2, +0, 3, 3, 2, 4, 1, 0, 1, +-3, 0, -6, 2, -4, -1, 3, -1, +2, 2, 3, 0, 2, -1, -2, 0, +-7, 0, -2, -3, 0, 0, 2, 0, +8, -4, 7, -4, 0, -1, -3, -1, +-5, 2, -4, 2, 4, -1, 6, 1, +5, -2, 4, -3, 0, -4, -2, 0, +-6, 4, 1, 0, 4, 0, 3, 0, +1, -1, -3, -1, -4, -2, -4, 0, +1, -3, 7, -2, 1, 2, 3, -3, +0, -1, -5, 1, -4, 1, -1, 1, +2, 2, 4, 0, 6, -2, 2, -2, +0, -4, 2, -6, 3, -3, 3, 0, +4, 1, 1, 2, -2, 1, -4, 1, +-3, -3, 3, -7, 4, -2, 2, 1, +3, -1, 0, 0, -3, -1, -3, -1, +-3, -1, 2, -1, 1, 3, 1, 2, +0, 2, -2, 1, -3, 1, -2, -2, +2, -1, 2, 1, 6, -2, 5, -1, +-3, 2, -2, -2, -3, 0, -3, 1, +0, 1, 3, 0, 1, 2, -3, 1, +0, -4, -5, 1, -3, -1, 2, 0, +0, 3, 2, 0, 2, -1, 0, -2, +2, -5, -2, 2, -2, 2, 5, -1, +3, 2, 0, 3, -4, 2, -1, -2, +-1, -1, -1, 1, -2, 5, 1, 0, +7, -7, 3, -2, -6, 2, -5, 0, +0, -2, 0, 1, 1, 0, 4, -2, +1, -1, -2, 0, -2, -1, 0, -1, +2, 0, 4, 0, 4, 0, 2, 2, +-2, 1, 0, -1, 0, -1, 3, -3, +6, -2, 1, 3, 0, 0, -1, 0, +-5, 1, -5, 1, -4, 1, 0, -1, +1, -1, 1, -1, -2, 0, -5, 1, +-4, 0, -4, 3, -2, 1, 3, -1, +3, 0, 3, -1, 0, 2, -5, 5, +-2, 3, 1, 2, 3, 0, 4, 0, +1, 1, 1, -1, -1, 0, -4, 2, +-2, 0, -2, 1, -1, 1, -4, 3, +-7, 3, -5, 0, -6, 2, -3, -1, +2, -2, -1, 2, 3, -3, 4, -2, +0, 1, 1, -1, 4, -3, 6, -2, +6, -2, 8, -2, 4, 1, 0, 1, +2, -3, 2, -3, 0, -1, 0, 0, +-2, 1, -1, -1, -4, 1, -7, 1, +-6, 0, -4, -1, -2, 0, -3, 2, +-2, 2, -1, 1, 0, 1, 0, 1, +3, 0, 3, 1, 6, 1, 3, 4, +4, 1, 5, 0, 1, 2, -1, 2, +-1, 2, -2, 1, 1, -2, -5, 4, +-7, 1, -7, 1, -6, -3, -1, -4, +-7, 2, -1, -4, 0, -1, -4, 3, +-5, 4, -3, 3, 0, 2, 5, -1, +7, 0, 6, 3, 4, 3, 9, -4, +9, -3, 4, 0, 2, 3, -2, 3, +1, -1, -1, 0, -5, 1, -7, -1, +-5, -3, -10, 2, -13, 4, -7, -1, +-3, -2, -5, 0, -3, 0, -4, 2, +0, 0, 1, 3, 6, 0, 9, 1, +8, 2, 9, -1, 9, -1, 8, -1, +8, -3, 7, -1, 2, 1, -2, 3, +-5, 1, -6, -1, -10, 1, -12, 1, +-9, -1, -9, 1, -9, 2, -10, 3, +-10, 3, -7, 1, -2, 0, 0, 3, +3, 3, 8, 1, 12, -2, 11, 1, +6, 4, 8, 0, 10, -1, 10, -2, +8, -1, 3, 0, 0, -2, -5, -1, +-10, 2, -15, 3, -12, 0, -13, 3, +-12, 0, -6, -6, -6, -4, -7, -3, +-2, -2, -3, 4, 3, 1, 10, -1, +11, 0, 11, 1, 7, 4, 10, 0, +15, -2, 13, 0, 14, -2, 4, 4, +0, 0, -4, 1, -9, 0, -7, -3, +-10, 0, -9, -3, -9, -4, -13, 0, +-16, 1, -12, -1, -8, -1, -1, -3, +5, -1, 6, 1, 10, -1, 10, 1, +11, -1, 16, -2, 16, 0, 18, -1, +16, 0, 13, -3, 9, -4, 1, -1, +-4, -1, -9, 1, -9, -1, -10, -1, +-14, 0, -18, 1, -19, 0, -16, -1, +-12, -1, -6, -2, 2, -3, 5, -2, +8, -2, 10, -2, 13, -3, 18, -3, +21, -3, 23, -2, 19, 1, 12, 3, +8, 0, 4, 0, -2, -1, 0, -4, +-6, 1, -13, 2, -16, 1, -21, 2, +-25, 3, -20, -2, -16, 1, -16, 5, +-6, 0, 1, -1, 0, 1, 4, 0, +9, 1, 13, 2, 19, 1, 22, 0, +24, -2, 20, -1, 13, 0, 7, 1, +2, 2, 1, 0, 0, -2, -7, 0, +-13, -1, -20, 0, -24, 1, -23, -1, +-17, -2, -14, 1, -12, 2, -7, 0, +-5, 2, -3, 1, 7, -1, 11, 1, +22, -3, 24, 0, 25, -3, 22, 0, +15, 0, 11, 2, 7, 2, 8, 0, +4, -2, 0, -3, -15, 3, -19, -2, +-23, 1, -27, 3, -22, 2, -20, 3, +-15, -1, -12, 1, -15, 4, -6, -1, +3, -1, 13, -2, 18, 2, 21, 1, +24, 0, 19, 1, 20, -2, 19, -2, +15, 1, 14, -2, 10, -1, 0, 0, +-6, -3, -15, -1, -20, -1, -23, 1, +-20, -2, -15, -4, -18, 1, -20, 2, +-15, -2, -7, -3, -3, 2, 5, 1, +14, 2, 15, 4, 19, 2, 17, 4, +17, 1, 22, -3, 22, 0, 17, 2, +11, 2, 2, 3, -7, 1, -12, -1, +-17, 1, -21, 1, -18, -2, -17, -2, +-20, -1, -24, 1, -21, -1, -15, -1, +-6, -1, 3, 1, 7, 3, 12, 2, +16, -1, 19, -2, 21, -1, 23, 0, +24, 1, 22, 1, 18, 0, 7, 1, +0, -1, -7, 0, -13, 0, -13, -1, +-17, 2, -19, -1, -22, 0, -25, -1, +-23, -1, -18, -1, -9, -3, 1, -2, +3, 3, 6, 1, 12, 0, 13, 1, +19, -1, 24, -1, 29, -3, 27, 0, +19, 1, 16, -4, 6, 0, -4, 2, +-5, 0, -10, 2, -13, 0, -18, 2, +-26, 3, -25, -3, -22, -4, -20, 0, +-14, 1, -10, 4, -3, 0, 7, -5, +9, -3, 12, -2, 16, 1, 21, 1, +27, 0, 27, -2, 23, 0, 13, 1, +10, -2, 1, 4, -1, -1, 3, -5, +-9, 3, -17, 2, -22, 0, -24, -2, +-23, -2, -21, 1, -18, 3, -13, 2, +-9, 2, -4, 0, 0, -1, 7, -2, +16, -4, 25, -4, 27, -1, 24, 1, +19, 2, 14, 0, 15, -4, 11, -1, +5, 2, 2, 1, -3, -1, -10, -1, +-18, -1, -21, -3, -20, -3, -20, 2, +-19, 3, -13, -1, -9, -1, -9, -2, +-1, -5, 2, 1, 10, -2, 18, -1, +20, 1, 23, -1, 20, -1, 19, -3, +16, -1, 12, 2, 9, 2, 7, 0, +4, -3, -7, -1, -16, 0, -18, -3, +-17, -2, -20, 3, -15, -3, -12, -3, +-14, 0, -16, 3, -11, -1, 2, -4, +5, 2, 11, 1, 17, 0, 17, 0, +17, -1, 16, -1, 17, -2, 20, -3, +16, 0, 12, -1, 6, -1, -4, 0, +-9, 0, -15, 1, -14, -1, -16, 4, +-17, 2, -15, 0, -19, 2, -18, 1, +-14, 2, -9, 4, 0, 2, 7, 2, +7, 5, 8, 3, 10, 2, 11, 3, +15, 0, 20, -2, 17, 1, 11, 4, +2, 5, -3, 0, -5, 0, -9, 1, +-9, -1, -7, -3, -10, -2, -13, -3, +-15, -2, -16, 0, -14, 0, -7, -1, +-1, 0, 4, -1, 8, -1, 7, 1, +8, -2, 15, -5, 18, -1, 18, -1, +17, 0, 12, 0, 9, -2, 4, -1, +0, -1, -5, 1, -2, -4, -4, 0, +-11, 1, -12, -3, -14, -2, -15, -1, +-11, -3, -4, -1, -6, 4, -5, 4, +-5, 5, -1, 4, 4, 1, 8, 2, +8, 4, 15, -1, 16, 0, 15, -2, +8, 2, 0, 1, 4, -1, 0, 2, +0, -1, -1, -3, -4, -4, -12, 0, +-14, 1, -14, 1, -13, -1, -7, -2, +-1, -3, -2, 0, -2, -1, 1, -3, +-1, 2, 5, 2, 10, 2, 13, -1, +15, -4, 13, -2, 7, 3, 4, 1, +7, -3, 6, -3, 4, -1, -2, 4, +-7, 3, -9, -2, -10, -3, -7, -4, +-5, -2, -7, 1, -3, -5, -2, -5, +-5, 1, -5, 3, 0, -2, 5, -2, +10, -4, 14, -2, 7, 5, 8, -1, +6, -2, 6, -2, 11, -3, 10, 0, +7, -3, 4, -5, -1, -2, -3, -2, +-7, 2, -9, 2, -8, -2, -8, 2, +-8, 5, -10, 4, -12, 2, -5, -4, +1, -2, 1, 4, 6, 0, 8, -4, +6, -3, 8, -2, 6, 3, 3, 3, +5, -2, 6, 0, 2, 5, 4, 0, +1, -1, -5, -3, -4, -3, -2, 1, +-3, 2, -5, -1, -6, -2, -6, -2, +-7, 3, -5, 3, -3, -1, -1, -4, +4, 1, 3, 2, 7, -3, 6, -7, +8, -8, 5, 3, 5, 5, 6, 2, +4, -4, 6, -7, 4, 0, 0, 3, +2, -5, 1, -6, -1, -2, -4, 5, +-6, 6, -7, 0, -9, -3, -6, 1, +-4, 7, -4, 6, 0, -2, 1, -6, +-2, 2, -1, 7, 3, 0, 6, -5, +5, -4, 5, 2, 1, 9, 1, 1, +4, -9, 2, -3, 0, 1, 3, 5, +-3, 5, -6, -3, -6, 1, -7, 6, +-2, 1, 0, -4, 1, -8, 0, -4, +-1, 7, -3, 6, -1, -6, 0, -6, +2, -2, 5, 4, 2, 5, 6, -7, +3, -6, 2, 0, 3, 5, 3, 3, +1, -5, 4, -8, 1, 5, -1, 5, +1, -2, -4, -3, -6, -3, -5, 7, +-2, 9, -2, -2, -1, -8, -2, -1, +-5, 8, -4, 8, 0, -2, 2, -9, +1, 0, 1, 8, 0, 7, -2, -2, +-1, -6, 2, 0, 4, 6, 6, -2, +8, -11, 2, -9, 2, -2, 3, 7, +1, -1, 0, -9, 0, -5, 0, 4, +-5, 11, -2, 1, -1, -10, -4, -3, +-1, 7, -1, 9, -1, -3, 4, -12, +2, -4, 0, 8, 0, 7, 1, -2, +1, -8, 3, -2, 3, 9, 2, 4, +1, -9, 1, -7, 2, 1, -2, 11, +-2, 7, -1, -7, -5, -7, -1, 4, +3, 4, -2, 1, -2, -8, 3, -9, +-5, 10, -1, 8, 3, -5, 1, -12, +2, -5, 2, 10, -3, 14, -4, -1, +3, -11, 2, -1, -1, 10, 1, 9, +0, -3, -4, -9, -1, 4, 0, 11, +-2, 2, -1, -6, -3, -6, -4, 2, +0, 12, -2, 5, -8, -7, -2, -8, +4, 2, 0, 9, -1, 0, 2, -12, +2, -6, -1, 9, 4, 8, 2, -2, +0, -13, 5, -4, 5, 9, 2, 5, +2, -6, 1, -9, -1, -4, 1, 12, +1, 6, -1, -12, -2, -10, 0, 4, +-5, 11, -3, 4, 2, -12, 2, -14, +-1, 6, 0, 12, 0, 0, 1, -13, +5, -10, 4, 7, 1, 10, 5, -5, +7, -12, -2, -3, 1, 11, 0, 16, +-5, -4, 1, -15, 8, -5, 0, 8, +-4, 9, -1, -5, -3, -15, -3, 1, +3, 10, 2, 0, -3, -9, 2, -10, +-3, 7, -3, 12, 7, -2, 2, -9, +-3, -6, 4, 5, 6, 12, -1, 1, +2, -15, 7, -5, -1, 8, 2, 8, +4, -1, -2, -15, -2, -5, -1, 16, +-6, 9, -6, -6, 2, -12, 1, -4, +-6, 13, 2, 5, 2, -11, -6, -9, +3, 2, 5, 12, -3, 6, 5, -14, +7, -10, -3, 8, 3, 9, 9, 1, +-3, -8, -2, -8, 4, 10, 0, 9, +-4, -3, 1, -10, -3, -4, -10, 13, +0, 12, -2, -5, -9, -12, 0, -1, +0, 11, -6, 9, 2, -6, 6, -14, +-2, 3, 0, 13, 5, 7, -2, -7, +4, -14, 8, 4, 0, 15, -4, 5, +3, -9, 0, -8, -7, 6, 2, 14, +1, -2, -4, -15, 2, -7, 2, 5, +-11, 13, -5, 1, 2, -14, -5, -5, +0, 12, 4, 9, -7, -1, 0, -12, +9, -4, -2, 14, 3, 4, 12, -9, +2, -9, -1, 0, 6, 11, 3, 3, +-2, -12, 3, -8, -1, 7, -8, 10, +-1, 5, -3, -8, -9, -11, -3, 9, +-3, 15, -8, -2, 1, -12, 9, -10, +-2, 7, -1, 11, 9, -6, 3, -13, +3, -4, 11, 6, 3, 10, -2, -6, +9, -14, 3, 0, -3, 8, 5, 5, +2, -4, -9, -11, 1, 1, 0, 12, +-7, -1, -3, -7, 1, -8, -7, 2, +-4, 12, 7, -1, -3, -11, -3, -6, +6, 6, -2, 11, -1, 0, 11, -12, +2, -2, -2, 8, 8, 6, 4, 0, +-6, -8, 5, -6, 5, 10, -8, 8, +-2, -4, 0, -7, -10, -2, -7, 11, +1, 7, -4, -10, -6, -6, 2, 3, +-4, 6, -4, 4, 5, -5, 1, -9, +0, 3, 12, 5, 7, 0, -3, -5, +6, -7, 6, 4, -4, 11, 3, -1, +6, -7, -8, -2, -2, 5, 2, 9, +-6, -5, -4, -10, 0, 1, -8, 7, +-6, 5, 7, -6, -3, -11, -4, -4, +9, 7, -1, 7, -3, -4, 9, -8, +7, -3, -2, 11, 5, 4, 10, -9, +-2, -5, 6, -1, 7, 10, -7, 5, +-1, -10, 4, -6, -6, 3, -5, 6, +3, 0, -3, -10, -9, -4, 2, 4, +-1, 4, -7, -1, 0, -2, -1, -4, +-1, 3, 8, 7, 5, -4, -1, -8, +5, -1, 9, 5, 0, 6, 7, -7, +9, -8, -8, 6, -5, 9, 4, 3, +-2, -7, -3, -11, 3, 2, -8, 11, +-9, 0, 3, -7, -4, -6, -8, 1, +2, 10, 0, 4, -9, -3, 1, -1, +5, 3, -1, 5, 6, 0, 9, -8, +-1, -4, 6, 3, 10, 4, -1, -1, +-3, -6, 5, -5, -2, 7, -5, 5, +2, -1, -8, -3, -8, -6, 3, 5, +-2, 5, -8, -6, 2, -8, 5, -2, +-5, 7, 2, 6, 4, -3, -7, -4, +2, 4, 11, 5, 2, 1, 4, -6, +12, -11, 1, 4, -7, 15, 0, 4, +-3, -5, -6, -5, 4, 2, -4, 10, +-9, -3, 0, -9, -3, -2, -9, 5, +-1, 8, 2, -1, -7, -8, -1, 0, +3, 9, -2, 5, 1, 0, 9, -10, +2, -1, -2, 13, 9, 2, 2, -6, +-5, -3, 1, 4, -2, 10, -5, 5, +-1, -5, -4, -5, -7, 1, 0, 7, +-5, 7, -9, -7, -4, -4, -1, 7, +-5, 6, -1, 1, 3, -5, -2, -6, +3, 5, 9, 8, 2, -3, 2, -8, +5, 0, -1, 9, -2, 9, 5, -3, +0, -8, -5, 0, 0, 8, -3, 8, +-8, -5, -1, -11, -1, 2, -6, 8, +-2, 2, 0, -4, -6, -8, 0, -1, +6, 9, 1, 1, 0, -8, 7, -6, +2, 4, -3, 13, 3, 4, 6, -14, +3, -7, 4, 7, 4, 7, -3, 0, +-2, -8, 1, -4, -5, 9, -5, 9, +-3, 0, -7, -8, -2, -6, 3, 8, +-3, 5, -3, -7, -1, -3, -2, 1, +0, 8, 5, 6, 3, -9, 1, -10, +6, 4, 5, 10, -2, 4, 1, -4, +1, -5, -3, 5, 1, 9, 2, 0, +-5, -10, -2, -6, -1, 8, -4, 9, +-7, -1, 1, -12, -2, -3, -6, 8, +5, 6, 3, -6, 0, -13, 3, 2, +0, 12, 0, 4, 5, -5, 1, -6, +-2, 2, 4, 11, 3, 6, -3, -8, +1, -11, 3, 4, -6, 13, -1, 0, +4, -13, -5, -5, -5, 5, 1, 9, +-2, 0, -3, -12, 4, -8, 1, 9, +-2, 9, 2, -2, 1, -11, 2, -6, +5, 8, 9, 4, 4, -7, 4, -12, +2, 2, -3, 12, 1, 6, 1, -7, +-1, -11, -1, 2, -1, 12, -1, 2, +-1, -12, -1, -10, -3, 7, -6, 14, +-1, 0, 2, -11, -2, -7, 0, 6, +1, 13, 1, -2, 1, -10, 4, -5, +3, 9, 0, 11, 3, -5, 4, -16, +2, -5, 2, 10, 0, 9, 0, -9, +3, -16, 1, -1, -5, 13, -3, 5, +0, -9, -1, -11, -2, 3, 3, 10, +2, 1, -2, -11, 3, -9, 2, 5, +4, 9, 7, -2, 5, -14, -1, -4, +-3, 15, -1, 11, 4, -8, 2, -11, +1, -5, 1, 8, -2, 12, -2, -6, +-4, -12, -5, 1, 0, 12, -2, 8, +-6, -4, -3, -10, 0, 0, -2, 14, +4, 3, 3, -11, -1, -9, 4, 6, +2, 13, -1, 3, 1, -11, 4, -11, +0, 8, 2, 13, 2, -2, -1, -15, +0, -4, -4, 12, -4, 11, 1, -7, +3, -17, -2, -3, 0, 11, 1, 8, +-2, -9, 1, -15, 3, 0, -1, 15, +0, 8, 4, -10, 1, -12, 1, 3, +2, 15, 1, 3, -1, -10, 2, -9, +2, 5, 0, 12, 1, 1, -6, -11, +-5, -7, 0, 11, -3, 14, -6, 1, +-5, -10, -3, -4, -2, 12, 2, 8, +2, -7, -2, -12, 2, -1, 1, 15, +0, 7, 3, -11, 2, -14, 3, 1, +3, 14, 3, 4, 0, -11, -2, -11, +1, 3, 2, 12, -1, 1, 3, -17, +-1, -8, -4, 10, -1, 13, -1, -3, +0, -15, -3, -3, -1, 13, 0, 14, +-1, -4, 1, -15, 4, -5, 2, 14, +-3, 14, 1, -8, 1, -14, 2, 0, +3, 15, 0, 4, 1, -15, 5, -16, +2, 3, -2, 15, 2, 3, -2, -13, +-5, -10, 0, 9, -3, 18, -7, 2, +3, -16, 3, -7, -5, 14, 1, 14, +3, -4, -3, -17, 5, -7, 9, 12, +0, 8, 3, -10, 5, -14, -4, 0, +-3, 15, 7, 4, 0, -13, -7, -11, +5, 3, -3, 17, -10, 7, 0, -11, +-3, -10, -5, 8, 4, 15, 4, -2, +-4, -15, 2, -7, 3, 12, -7, 16, +1, -2, 5, -15, -2, -6, 1, 15, +4, 14, -7, -6, -1, -17, 7, -2, +-4, 17, -5, 11, 6, -15, 1, -17, +-8, 6, 4, 13, 2, 2, -3, -15, +5, -14, 4, 4, -2, 15, 0, 4, +0, -14, 0, -12, 4, 11, 5, 14, +-1, -2, -3, -13, 2, -5, 0, 12, +0, 11, 4, -8, 0, -17, 0, -5, +1, 16, -3, 11, -2, -13, 1, -18, +2, 2, -2, 15, 1, 4, 4, -14, +-1, -12, -2, 5, 6, 14, 2, 4, +-7, -11, 3, -10, 6, 8, -3, 15, +2, -2, 5, -17, -6, -5, 0, 13, +7, 12, -4, -7, -3, -16, 5, -2, +-6, 16, -4, 7, 10, -13, -1, -16, +-6, 2, 5, 17, 1, 6, -8, -12, +7, -14, 5, 4, -6, 15, 7, 3, +5, -14, -8, -11, 3, 9, 8, 15, +-7, -4, 6, -21, 7, -4, -10, 14, +-3, 13, 6, -5, -6, -18, -4, -5, +11, 11, -1, 10, -11, -4, 4, -14, +1, 0, -10, 19, 4, 10, 0, -9, +-10, -11, 9, 2, 8, 13, -4, 1, +6, -17, 7, -11, -6, 9, 1, 17, +1, 3, -6, -16, -2, -8, 6, 10, +-5, 14, -6, -3, 4, -16, 1, -6, +-6, 18, 0, 12, 2, -10, -5, -14, +2, 1, 3, 15, -2, 7, 3, -13, +5, -13, -3, 6, -3, 18, -1, 8, +0, -15, 0, -12, 3, 8, -2, 18, +-7, 1, 0, -16, 5, -10, -4, 12, +-2, 12, 5, -6, 0, -18, -2, -4, +4, 14, -2, 11, -6, -6, 7, -14, +1, 0, -3, 12, 5, 10, -3, -4, +-10, -12, 8, 0, 8, 13, -5, 2, +1, -11, 3, -8, -7, 6, -4, 17, +7, -1, -7, -12, -7, -5, 7, 10, +-4, 10, -4, -5, 6, -12, -2, -4, +-5, 10, 12, 9, -2, -2, -10, -13, +7, 2, 2, 14, -7, 6, 6, -9, +8, -14, -9, 5, 0, 15, 6, 4, +-11, -9, -4, -8, 8, 4, -6, 11, +0, -3, 8, -13, -7, -6, -4, 7, +10, 9, -4, 0, -5, -15, 12, -9, +2, 11, -2, 6, 9, -8, 3, -12, +-4, -1, 2, 13, 7, 3, -2, -9, +2, -13, 3, 4, -8, 16, -4, 5, +2, -11, -2, -9, -5, 7, 1, 11, +-2, 1, -4, -11, 0, -7, 3, 7, +-4, 14, -2, -2, 6, -14, 2, -5, +-3, 12, 5, 8, 4, -7, -2, -12, +6, -2, 4, 9, -1, 3, 4, -10, +6, -13, -7, 4, -2, 12, 2, 6, +-10, -6, -6, -5, 2, 7, -3, 8, +-6, 3, 3, -7, -4, -5, -5, 6, +8, 9, 3, -4, -4, -12, 8, -3, +4, 8, -4, 7, 4, -1, 5, -12, +-4, -4, 3, 11, 4, 7, -9, -6, +0, -9, 3, 4, -9, 9, -3, 4, +4, -7, -5, -9, -5, 6, 5, 11, +-5, 2, -4, -10, 9, -7, 1, 6, +-7, 10, 8, -1, 0, -7, -5, -4, +5, 10, 3, 6, -4, -6, 4, -9, +4, -1, -7, 9, 0, 6, 1, -4, +-8, -8, 0, -1, 5, 8, -6, 4, +-3, -8, 5, -7, -3, 5, -4, 8, +7, -3, 5, -10, -2, -5, 5, 4, +3, 8, -2, -1, 0, -5, 3, -3, +0, 7, -4, 10, 1, -2, -3, -6, +-5, 1, 1, 6, -1, 5, -4, -6, +0, -8, 1, 1, -4, 9, -4, 3, +4, -6, -3, -5, 0, 1, 2, 11, +-3, 3, -1, -8, 8, -7, 6, 1, +1, 3, 5, -1, 7, -13, 1, -3, +0, 8, 1, 7, -5, -3, 2, -8, +2, -1, -7, 7, -1, 3, 4, -6, +-5, -6, -3, 1, 4, 7, -7, 6, +-6, -2, 3, -2, -1, 0, 0, 5, +5, 3, 1, -7, -1, -5, 7, 6, +-1, 7, -5, -1, 6, -6, 0, 0, +-10, 7, 4, 4, 3, -4, -8, -4, +-2, 3, -1, 8, -10, 5, 0, -8, +9, -8, -5, 1, 0, 3, 8, -1, +2, -9, 1, -6, 6, 2, 2, 4, +-1, -2, 8, -6, 2, -3, -2, 3, +3, 5, 2, -2, -3, -4, -2, 1, +1, 2, -3, 4, -2, 0, -1, -6, +0, -2, -1, 4, 0, 1, 1, -6, +1, -4, -1, 0, 2, 3, 4, -2, +4, -6, 1, -3, 4, -1, 2, 6, +0, -1, 3, -3, -4, 3, -1, 4, +-2, 6, -1, 1, -1, -5, -1, -2, +1, 2, 0, 1, -4, 1, -4, -3, +1, -3, 0, 3, -2, 4, -3, -2, +1, -3, -1, -1, 5, -1, 3, 3, +-1, -4, 2, -2, 2, 3, 2, 2, +0, -1, 7, -5, 2, -5, 0, 3, +0, 5, 2, -4, -3, -3, -1, 0, +-1, 5, -8, 5, -1, 0, -3, 0, +-4, 0, 0, 0, 6, -1, -5, 1, +-3, -2, 7, -2, 2, 1, 1, 1, +3, -2, 5, -6, -2, 3, 4, 2, +4, -4, 1, -4, 3, -3, 0, 2, +-4, 6, -5, 5, -6, 1, -5, 0, +2, 2, -4, 3, -1, -1, -2, -1, +-2, 0, -1, 2, 3, 0, 0, -1, +-2, -1, 5, -1, -1, 6, 0, -1, +5, -6, 6, -3, -1, 1, 0, 6, +-1, 3, -3, -3, 1, -2, 2, 1, +1, -2, -4, 3, -3, 1, -1, -4, +0, 2, 1, -1, 1, -2, -6, 2, +-1, 2, 2, 0, 0, 2, 0, -2, +2, -2, 0, 3, 0, 2, 3, 1, +1, -3, 0, 1, -2, 2, 2, 1, +0, -2, 0, -1, -5, 3, -1, 1, +2, 0, 0, -3, 1, -2, -3, 0, +-1, 1, 1, 0, 3, -3, 0, -5, +4, 0, -2, 5, -3, 1, 2, -1, +1, -2, 3, -1, 1, 2, 5, -3, +-1, 0, 0, -1, 3, -3, 1, 3, +0, -2, -1, 0, -5, 5, -3, 0, +2, -1, -3, 0, 1, -3, -3, 1, +0, 4, -4, 3, 1, -1, -2, -1, +1, 0, -1, 6, -2, 1, 4, -4, +4, -4, 2, 0, 0, 0, 3, 2, +-6, 0, 0, 0, 1, 1, 1, 0, +-3, 3, 0, -4, 0, 0, -9, 8, +-2, 2, -1, -2, 1, -1, -1, -1, +0, 4, -2, 2, -1, 0, 1, -2, +3, -1, 2, 1, 0, 1, 5, -6, +3, -4, 1, 3, -3, 3, 3, -2, +2, -4, 0, -1, -1, 2, 2, -1, +-1, -1, -3, 1, 2, -3, -3, 3, +-2, 6, -1, -1, -2, 0, -2, 1, +2, 2, -2, 2, 0, -1, 3, -3, +1, 1, 0, 2, 2, -3, 4, -1, +0, -4, 5, -2, 2, 1, 2, -2, +-3, 0, 1, -2, 3, -3, -1, 1, +4, -4, -1, -1, -3, 4, -4, 2, +3, 0, -4, 3, -2, -2, 2, -2, +1, 5, -1, -2, 2, -3, 5, -2, +0, -2, 1, 3, 1, 0, 2, -2, +-3, 0, 3, 0, 1, -1, -1, 0, +-1, -1, -2, 3, -3, 3, -1, -1, +4, -2, -1, -2, 1, -3, 2, 1, +1, 2, -2, -2, 1, 3, -1, 1, +-1, 2, -1, 3, 3, -6, 5, -4, +0, 1, 1, 2, 1, -2, 5, -4, +-2, -2, 0, 3, 0, -1, -1, 0, +0, 1, 1, -3, 0, 0, 0, -1, +6, -5, -2, -2, 2, -2, 6, -4, +3, 1, -2, -2, 3, -2, 0, 2, +0, -3, 4, 1, -1, 2, -1, -2, +-4, 3, 5, 1, -4, 0, -4, 3, +-1, 0, 3, -3, -4, 5, -3, 3, +0, 0, -7, 4, 1, -1, 3, -3, +2, 0, -4, -1, 4, 0, -1, 2, +0, -2, 2, -1, 1, 1, 0, -3, +4, -3, 7, -2, 2, -5, 0, 2, +-4, 2, 5, -2, -2, 0, 3, -3, +4, -2, 0, -2, 1, -2, 5, -3, +3, -3, -4, -2, 5, 2, -3, 2, +-2, 0, -1, 1, 4, -2, -5, 3, +-1, 1, 3, -1, -2, 1, 1, -1, +1, 0, 2, 1, -6, 0, 1, -1, +-1, 4, -3, 2, -1, -1, 2, 1, +1, -4, -2, 0, 0, 4, -3, 2, +-2, 1, -2, 0, 6, -2, -4, 4, +-5, 3, 3, -2, 2, 1, -4, 0, +3, 0, 4, -1, -3, -4, 5, -1, +2, 0, -3, 1, -4, 1, 7, -2, +-3, 1, -2, 0, 3, 0, -3, 2, +-2, -1, 1, 0, 1, 3, -6, 2, +-2, 2, -1, 2, 2, -1, -2, -2, +6, -1, -1, 2, -2, 0, 1, 2, +-2, 2, -3, 2, -2, -2, 7, -3, +1, 0, -2, 3, -7, 4, 3, 1, +-1, -3, 1, -2, 2, 3, -1, -1, +-3, 2, 4, -1, 3, -1, -7, 0, +7, -2, 5, -3, -2, 2, -1, -1, +9, -4, -1, 1, -2, -1, 6, -1, +-1, 1, -3, 0, 2, 1, 2, 3, +-5, -3, 2, 3, -1, 3, 0, -1, +-2, 3, 4, -1, 1, 0, -4, 4, +1, 3, 1, -1, -1, 2, -5, 3, +6, 1, -2, 3, -3, 1, 1, 3, +0, 0, 2, -4, 6, -1, 7, -3, +-2, -3, 2, 2, 4, -1, 2, -1, +-3, 2, 4, -1, 3, -1, 0, 1, +4, 0, 1, 1, -1, -1, 1, 0, +6, 1, 0, -2, 1, -1, 2, 2, +2, 1, -2, 2, 3, 0, 4, -3, +-1, 1, 3, 0, 4, 0, 3, 0, +-5, 2, 3, 1, 2, 4, -4, 4, +-1, 0, 9, -2, 0, 0, -1, 3, +8, 0, 3, -5, 1, -1, 6, 1, +7, 0, -3, 0, 6, -2, 5, 0, +-2, 3, 4, -2, 8, 1, -3, 2, +0, -2, 9, 2, 2, 2, -3, 1, +3, 0, 9, -2, 0, 1, 6, 1, +8, -5, 3, -2, 1, 4, 6, 0, +8, -3, 4, -4, 10, -6, 9, -2, +6, -1, 6, -4, 9, -3, 6, -4, +4, 2, 6, 1, 8, -4, 1, 1, +1, 3, 10, -2, 5, 1, 2, 2, +4, -1, 6, 2, 0, 3, 6, 1, +7, 0, 1, -1, 8, 0, 7, 5, +3, 0, 2, -1, 12, -3, 7, -1, +3, 4, 5, 2, 4, 0, 2, 0, +10, -1, 9, 2, 3, 1, 6, -3, +7, 2, 6, 5, 2, 0, 8, -1, +10, -5, 10, -4, 8, 2, 13, -1, +8, -4, 4, 1, 10, 1, 8, 1, +3, 2, 8, -4, 12, -1, 0, 5, +6, 4, 9, 2, 4, -3, 7, -3, +13, 3, 7, 3, -1, 3, 12, -3, +10, -3, 8, -1, 13, -1, 12, -3, +5, -2, 9, 2, 13, 0, 8, 2, +7, -1, 11, -4, 11, 1, 8, 0, +12, 0, 6, 1, 8, -2, 5, 5, +10, 2, 9, 0, 7, -1, 12, -2, +10, 3, 12, 1, 8, 0, 10, -2, +8, 1, 10, 1, 12, 2, 9, 2, +7, -2, 14, -1, 14, 3, 6, 3, +10, -1, 11, 0, 9, 2, 9, 3, +14, -2, 13, -7, 13, -5, 15, -1, +10, 7, 8, 1, 12, -2, 9, 6, +8, 3, 16, -4, 16, -1, 11, -3, +8, 0, 12, 5, 15, -1, 9, 1, +10, 1, 13, 3, 11, 4, 13, 1, +16, -2, 10, 0, 12, -1, 17, -1, +15, 0, 11, -4, 12, -1, 16, 3, +12, 3, 13, -1, 19, -4, 13, 2, +8, 4, 19, -1, 15, -2, 12, -4, +16, -3, 17, 5, 7, 8, 11, 0, +19, -2, 14, 3, 11, 4, 18, -1, +18, -3, 10, -3, 14, 3, 14, 4, +13, 1, 13, -1, 17, -1, 16, 2, +17, 3, 16, 1, 14, 0, 15, 0, +11, 5, 15, 2, 19, -3, 14, -3, +19, -3, 23, -1, 19, 0, 16, 2, +18, 0, 14, 3, 14, 3, 20, -1, +19, -5, 17, -6, 21, -3, 19, 4, +15, 1, 19, -4, 18, 4, 13, 7, +14, 7, 16, 5, 18, -3, 17, -3, +19, 1, 22, 0, 19, -3, 18, -4, +26, -4, 20, 6, 15, 5, 20, 0, +22, -3, 18, -4, 22, 1, 21, 0, +21, -8, 19, -4, 23, 0, 18, 4, +18, 3, 22, 1, 18, 0, 21, 4, +20, 4, 21, -1, 18, -2, 24, -7, +21, -2, 22, 3, 22, -2, 19, -1, +21, 1, 26, 1, 19, 5, 17, 4, +21, 0, 16, 1, 21, -1, 23, 1, +17, 0, 16, -3, 28, 0, 20, 7, +19, 3, 26, -2, 25, -1, 22, -2, +27, 0, 24, -2, 21, -6, 20, 1, +20, 1, 24, 2, 21, 3, 24, -3, +25, 0, 23, 7, 20, 3, 26, -5, +28, -9, 24, -5, 24, -3, 27, -2, +25, -4, 23, -1, 22, 6, 23, 7, +25, 2, 26, -3, 30, -6, 26, -1, +21, 1, 28, -4, 25, -4, 20, -3, +26, 4, 25, 5, 25, 1, 24, 0, +29, 1, 20, 6, 23, 3, 26, -3, +24, -5, 20, -1, 26, 1, 27, 0, +25, 0, 26, 1, 25, 4, 25, 6, +27, 4, 26, -2, 23, -4, 30, -2, +27, -4, 28, -5, 30, -5, 26, -1, +21, 5, 35, 4, 27, 2, 22, -1, +30, 3, 25, 2, 20, 2, 27, -3, +31, -9, 21, -3, 30, 3, 29, 5, +24, 2, 26, 2, 32, 3, 26, 4, +30, 0, 29, -4, 25, -4, 26, -3, +29, 0, 27, 0, 30, -5, 31, 0, +26, 6, 28, 10, 24, 6, 25, -2, +31, -6, 33, -3, 27, -4, 32, -7, +29, -4, 25, 0, 25, 7, 28, 10, +29, 1, 30, -2, 32, 1, 31, 3, +27, -2, 29, -6, 30, -4, 25, -1, +27, 1, 33, 3, 29, 3, 23, 1, +34, 5, 34, 4, 26, 0, 29, -5, +34, -3, 19, 1, 30, -3, 34, -2, +25, -2, 28, 0, 36, 5, 33, 5, +30, 3, 31, -1, 29, 0, 28, 4, +29, -3, 31, -9, 33, -9, 33, 1, +22, 8, 31, 9, 28, 7, 23, 3, +29, 6, 37, 4, 24, 0, 24, -3, +36, -6, 24, 0, 24, 3, 38, -1, +31, -1, 22, 7, 35, 11, 32, 6, +25, 4, 31, -4, 35, -5, 26, -1, +36, -7, 36, -8, 31, -5, 32, 1, +31, 9, 31, 8, 32, 0, 30, 0, +31, 2, 35, 1, 25, -4, 33, -10, +34, -6, 27, 3, 28, 3, 41, 0, +30, 4, 27, 4, 37, 6, 32, 8, +29, -7, 36, -11, 35, -6, 31, -4, +32, -3, 35, -2, 33, -1, 25, 7, +36, 7, 39, 3, 29, 0, 29, -4, +38, -1, 27, -1, 30, -6, 35, -6, +30, -3, 25, 4, 37, 9, 33, 6, +27, 2, 35, 2, 33, 5, 28, 3, +35, -9, 40, -16, 31, -7, 34, 3, +29, 2, 31, 3, 31, 4, 30, 8, +26, 11, 40, 3, 32, -5, 26, -6, +37, -4, 31, -2, 26, -4, 38, -6, +37, -2, 23, 7, 38, 10, 36, 6, +30, -5, 36, -4, 38, 2, 27, -3, +34, -7, 37, -10, 30, -5, 31, 4, +36, 8, 28, 5, 31, 3, 34, 5, +29, 6, 33, 3, 31, -6, 30, -11, +34, -6, 35, 0, 29, -1, 34, 0, +35, -1, 31, 10, 27, 13, 36, 4, +26, 1, 30, -4, 32, -1, 33, -2, +31, -6, 32, -9, 40, -7, 35, 6, +31, 9, 33, 6, 31, 2, 28, -1, +34, 3, 34, -2, 27, -6, 29, -12, +39, -3, 24, 7, 29, 5, 36, 1, +34, 1, 31, 6, 37, 9, 28, 5, +27, -7, 37, -10, 32, -5, 36, -4, +34, -3, 30, -2, 31, 1, 37, 12, +20, 15, 34, 2, 35, -3, 26, -5, +30, -1, 38, -3, 27, -8, 24, -3, +37, 2, 26, 7, 29, 5, 39, 3, +32, 3, 23, 6, 37, 5, 32, -3, +26, -8, 31, -9, 35, 0, 24, 5, +31, 1, 32, -1, 33, 2, 32, 8, +34, 5, 33, 1, 29, -6, 25, -5, +30, -4, 36, -2, 25, -5, 34, -5, +34, 6, 26, 11, 25, 7, 41, 0, +27, 0, 27, 0, 34, 3, 32, -5, +26, -11, 31, -4, 31, 3, 26, 6, +30, 3, 33, 1, 31, 4, 26, 8, +32, 5, 30, -2, 27, -10, 22, -5, +33, -1, 31, -5, 29, -2, 33, -1, +33, 7, 19, 15, 31, 8, 37, -6, +27, -8, 28, -4, 37, -6, 31, -5, +29, -7, 35, -4, 27, 1, 32, 5, +26, 6, 29, 3, 27, 3, 31, 4, +25, 0, 33, -7, 24, -8, 23, -4, +29, 5, 27, 3, 22, 1, 34, 0, +37, 6, 19, 13, 34, 5, 32, -6, +22, -14, 26, -6, 35, -1, 22, 1, +31, -3, 37, -6, 26, 3, 20, 13, +28, 8, 25, 0, 29, -4, 31, -2, +24, -3, 29, -9, 30, -7, 24, 1, +26, 3, 29, 1, 21, 2, 30, 3, +30, 9, 26, 9, 31, -3, 32, -10, +16, -11, 26, -7, 28, 4, 25, 5, +29, -1, 30, 0, 22, 6, 25, 9, +26, 6, 22, -2, 26, -7, 23, -6, +26, -4, 28, -4, 30, -4, 25, -1, +27, 7, 20, 4, 21, 1, 29, 1, +31, 3, 25, 5, 28, -1, 26, -9, +15, -7, 22, -3, 23, 2, 28, 1, +31, 1, 27, 5, 20, 7, 26, 6, +21, -1, 26, -10, 24, -7, 21, -3, +19, 2, 31, -4, 28, -6, 25, 0, +28, 12, 17, 12, 13, 2, 22, -3, +29, -6, 27, -2, 32, 2, 25, -3, +16, -6, 16, -5, 20, 1, 19, 5, +30, 8, 22, 15, 15, 10, 16, -1, +16, -5, 20, -4, 25, -2, 18, 1, +18, 1, 27, -6, 18, -4, 25, 5, +31, 16, 17, 14, 9, -3, 23, -18, +17, -9, 20, 8, 30, 15, 23, 6, +13, -8, 19, -12, 17, -3, 13, 9, +28, 11, 27, 9, 24, -6, 24, -16, +20, -9, 17, 0, 24, 2, 16, 0, +23, -8, 28, -11, 19, 1, 19, 12, +28, 15, 17, 5, 14, -9, 17, -17, +15, -12, 22, 5, 33, 12, 22, 6, +12, -5, 20, -5, 10, 4, 11, 3, +18, 4, 25, -1, 22, -3, 22, -3, +16, -1, 17, 1, 18, -5, 18, -5, +15, 0, 17, 4, 11, 12, 23, 3, +29, -4, 13, 1, 12, -1, 14, -8, +7, -3, 15, 1, 32, 2, 22, 0, +23, 1, 12, 12, 2, 8, 6, -4, +19, -14, 19, -9, 21, 6, 18, 14, +10, 4, 15, -3, 12, 0, 12, 0, +12, 5, 13, 5, 11, 1, 22, -1, +21, -4, 19, -3, 16, 6, 7, 4, +-5, -4, 8, -5, 25, 2, 22, 13, +21, 14, 16, 5, -1, -2, 2, -10, +12, -14, 14, -6, 26, 5, 27, 7, +13, -1, 9, -3, 13, 4, 9, 9, +16, 2, 15, -9, 8, -11, 12, -2, +18, 5, 17, 5, 21, 5, 15, -3, +3, -14, 4, -10, 10, 9, 17, 18, +28, 10, 23, -1, 4, -10, 0, -8, +-4, -6, 7, -7, 22, 0, 30, 6, +20, 6, 8, 9, -1, 10, -3, 10, +14, -6, 20, -20, 15, -16, 13, 0, +12, 6, 8, 3, 16, 3, 15, 3, +8, 3, -3, 1, 0, -3, 10, -1, +27, 1, 28, 3, 14, 3, 1, 0, +-12, -10, 0, -25, 19, -16, 24, 14, +22, 30, 17, 19, -1, -3, -2, -13, +7, -8, 6, -8, 10, -4, 16, 5, +9, -1, 8, -10, 21, -5, 13, 14, +0, 23, 2, 8, -2, -18, 6, -24, +26, -6, 27, 13, 12, 13, 5, 4, +-11, -9, -8, -26, 11, -18, 16, 10, +21, 33, 20, 25, 7, -1, -3, -15, +4, -10, -3, -6, 3, -8, 15, -6, +13, 2, 8, 4, 18, 1, 9, 9, +-4, 16, 3, 6, 2, -19, 6, -22, +15, -4, 18, 13, 10, 7, 13, -5, +2, -4, -8, -5, -4, -11, 5, -7, +19, 10, 25, 21, 19, 15, 1, 2, +-8, -8, -16, -15, 1, -23, 17, -15, +17, 8, 15, 22, 9, 11, -3, -3, +-1, -1, 10, 6, 4, -2, 8, -18, +7, -12, 1, -1, 14, 2, 21, 5, +8, 10, -8, 9, -17, -9, -16, -24, +13, -8, 33, 25, 29, 32, 9, 12, +-15, -14, -27, -27, -5, -26, 23, -12, +22, 8, 22, 19, 1, 17, -17, 1, +-7, -1, 9, 12, 7, 7, 2, -11, +-5, -21, -7, -10, 15, 8, 25, 15, +17, 7, -1, 1, -14, -11, -25, -20, +1, -10, 30, 17, 29, 33, 15, 15, +-7, -11, -28, -19, -14, -18, 17, -17, +16, -6, 12, 13, 6, 23, -5, 17, +-3, 0, 12, -7, 2, -2, -7, -9, +-6, -14, 0, -4, 18, 11, 20, 10, +10, -3, -4, -2, -20, 7, -20, -2, +7, -19, 26, -12, 17, 20, 8, 29, +-6, 12, -15, -10, -1, -22, 7, -26, +2, -22, 2, 5, 4, 35, 4, 34, +11, 5, 7, -19, -6, -13, -19, 3, +-13, 1, 4, -6, 27, -3, 21, 4, +5, 3, -10, 6, -24, 12, -13, 0, +11, -24, 13, -18, 6, 15, 14, 38, +-3, 24, -6, -14, 4, -32, -1, -27, +-10, -11, 0, 5, 11, 17, 12, 22, +21, 4, 5, -12, -15, -4, -17, 9, +-4, -2, 4, -20, 19, -16, 12, 10, +-3, 24, -4, 12, -8, -2, -4, -14, +2, -21, -1, -14, -2, 16, 12, 39, +13, 23, 12, -17, 3, -33, -20, -17, +-29, 1, -6, 1, 18, 1, 27, 14, +25, 19, -9, 10, -30, -6, -15, -7, +5, -7, 20, -17, 22, -13, 5, 5, +-14, 17, -9, 6, 4, -9, 10, -2, +4, 3, -12, -3, -19, -4, -2, 9, +22, 19, 29, 15, 11, -3, -24, -18, +-32, -27, -15, -30, 14, -11, 34, 32, +30, 56, -6, 26, -24, -27, -21, -42, +-5, -17, 19, 12, 22, 17, 5, 4, +-7, -9, -4, -15, -5, -11, 7, 12, +4, 30, -8, 10, -11, -22, 6, -27, +8, 14, 11, 37, 13, 20, -13, -11, +-17, -35, -13, -34, -2, -15, 12, 24, +20, 55, 5, 41, -1, -10, -6, -39, +-17, -23, -5, 2, 3, 7, 9, -2, +17, 1, 17, 7, -8, 2, -15, -8, +-14, 1, -13, 9, 8, 5, 23, 2, +8, 10, -4, 8, -5, -7, -12, -19, +-1, -12, 10, 3, 6, -2, -2, -10, +-5, 5, 2, 26, 11, 30, 8, 15, +-4, -12, -12, -27, -21, -32, -6, -18, +19, 18, 28, 45, 10, 30, -9, -21, +-22, -46, -23, -15, 5, 26, 21, 35, +20, 15, 10, -10, -7, -24, -20, -27, +-4, -8, 7, 19, 6, 15, 4, -10, +-1, -15, -7, 19, -3, 38, 8, 20, +3, -13, 0, -30, -12, -24, -10, -11, +6, 7, 9, 28, 12, 23, 8, -3, +-9, -21, -23, -3, -11, 20, -2, 12, +8, -6, 16, -1, 6, 13, -13, 13, +-16, -4, -12, -19, -9, -18, 12, -6, +15, 15, 6, 37, -2, 37, -5, -1, +-7, -39, -6, -31, -5, 6, -2, 26, +4, 13, 2, -7, 2, -7, -2, 3, +-9, 12, -11, 20, -3, 20, -5, -3, +2, -32, 12, -20, 0, 24, -6, 44, +-8, 18, -8, -31, -9, -40, 1, -12, +1, 21, -2, 44, 3, 44, -2, 13, +-4, -30, -10, -35, -16, -6, -16, 23, +0, 21, 9, 0, 17, -7, 6, 6, +-19, 11, -27, 6, -17, 9, 2, 8, +19, -3, 19, -12, -7, 0, -22, 18, +-23, 15, -6, -9, 12, -12, 10, 5, +-11, 10, -26, 12, -15, 15, 4, 22, +21, 14, 13, -10, -19, -20, -38, -14, +-24, 2, 0, 11, 31, 15, 31, 23, +-9, 15, -44, -7, -44, -11, -13, 6, +21, 20, 30, 14, 3, 1, -27, 4, +-37, 4, -17, -9, 9, -10, 19, 6, +-2, 24, -19, 16, -20, 4, -17, 7, +9, 8, 14, 0, -8, -5, -22, 3, +-23, 7, -19, -5, 6, -13, 18, 9, +0, 35, -13, 33, -24, 4, -27, -19, +-17, -15, 8, -5, 12, 14, 1, 35, +-13, 30, -21, -9, -25, -36, -21, -23, +-2, 22, 1, 53, 2, 35, -8, 7, +-17, -11, -28, -17, -21, -13, 1, 7, +7, 33, -9, 31, -25, -8, -23, -33, +-21, -5, 2, 39, 10, 53, -16, 29, +-36, -11, -36, -35, -28, -28, 6, 15, +22, 66, 0, 58, -32, -6, -52, -62, +-40, -42, -9, 25, 18, 74, 16, 67, +-9, 16, -49, -37, -53, -57, -26, -20, +5, 46, 20, 79, 1, 33, -43, -37, +-59, -55, -21, 1, 8, 69, 12, 72, +-9, 18, -50, -44, -59, -65, -15, -18, +28, 61, 21, 96, -21, 36, -63, -61, +-64, -81, -23, -5, 22, 82, 22, 97, +-20, 35, -57, -39, -60, -66, -22, -30, +5, 52, 0, 91, -15, 33, -35, -53, +-42, -71, -14, 6, -1, 94, -17, 91, +-30, 9, -54, -71, -38, -76, -3, 5, +10, 90, -8, 108, -40, 28, -68, -84, +-54, -93, -14, 11, 15, 120, 3, 117, +-40, 4, -68, -86, -52, -75, -8, 18, +11, 103, -15, 95, -60, 0, -70, -91, +-35, -80, 16, 46, 19, 148, -29, 105, +-84, -36, -89, -126, -30, -71, 31, 63, +31, 138, -24, 89, -88, -33, -97, -109, +-41, -60, 16, 64, 22, 140, -24, 81, +-72, -52, -82, -99, -39, -23, 12, 84, +3, 106, -52, 32, -78, -51, -68, -70, +-18, -11, 21, 78, -2, 104, -60, 49, +-89, -45, -67, -86, -10, -17, 17, 67, +-12, 86, -57, 38, -80, -28, -53, -42, +-13, -9, -14, 43, -50, 80, -68, 50, +-63, -14, -26, -40, -6, 0, -23, 60, +-66, 58, -86, 3, -55, -30, -16, -16, +-2, 29, -25, 62, -76, 54, -98, 18, +-55, -19, -12, -20, -5, 26, -36, 51, +-78, 30, -90, -10, -52, -14, 0, 31, +6, 57, -55, 33, -109, -8, -101, -23, +-44, 10, 16, 46, 20, 60, -56, 47, +-127, -10, -112, -47, -46, -14, 11, 46, +11, 84, -53, 47, -112, -16, -97, -22, +-43, 6, -5, 42, -18, 50, -64, 18, +-95, -8, -73, -23, -35, 7, -12, 64, +-33, 69, -82, 20, -99, -33, -80, -29, +-36, 32, -10, 68, -30, 57, -70, 17, +-96, -23, -86, -19, -42, 15, -31, 50, +-43, 58, -66, 15, -88, -13, -68, 8, +-33, 47, -49, 63, -74, 15, -90, -27, +-80, -9, -40, 30, -24, 56, -41, 49, +-84, 23, -109, -3, -80, -11, -44, 18, +-34, 46, -54, 41, -76, 19, -77, 15, +-68, 27, -57, 25, -67, -3, -80, -7, +-72, 30, -55, 61, -49, 50, -61, 4, +-74, -20, -77, 15, -80, 52, -80, 55, +-69, 19, -65, -24, -53, -16, -39, 35, +-57, 80, -99, 65, -111, -14, -85, -49, +-49, 4, -32, 68, -45, 78, -82, 21, +-109, -16, -93, 6, -68, 29, -64, 31, +-54, 10, -55, 8, -80, 41, -82, 53, +-92, 42, -91, 8, -62, -21, -52, 8, +-61, 44, -83, 50, -106, 18, -75, -17, +-44, 14, -55, 67, -85, 56, -118, 1, +-111, -34, -60, 9, -29, 75, -48, 70, +-94, 14, -124, -22, -104, -3, -69, 46, +-51, 53, -56, 17, -81, -10, -95, 8, +-79, 59, -80, 71, -85, 17, -86, -32, +-80, -21, -75, 52, -76, 85, -75, 28, +-80, -25, -86, -9, -85, 56, -87, 79, +-89, 14, -77, -38, -68, -14, -76, 65, +-98, 109, -98, 46, -85, -41, -75, -47, +-77, 19, -98, 98, -107, 82, -83, 1, +-58, -34, -50, 8, -94, 78, -137, 62, +-117, -14, -66, -46, -30, 8, -44, 92, +-111, 95, -154, 8, -115, -48, -59, -17, +-35, 58, -65, 96, -111, 39, -125, -30, +-104, -33, -62, 27, -49, 90, -86, 73, +-108, 2, -106, -42, -108, -14, -85, 54, +-64, 90, -69, 65, -77, 17, -103, -27, +-122, -31, -113, 13, -89, 65, -53, 94, +-58, 56, -92, -22, -111, -47, -118, 5, +-108, 89, -81, 107, -64, 17, -67, -66, +-85, -56, -98, 50, -106, 143, -107, 95, +-80, -43, -63, -117, -80, -37, -112, 131, +-111, 179, -86, 62, -64, -92, -71, -120, +-110, 21, -149, 158, -116, 142, -49, 5, +-33, -112, -76, -63, -129, 79, -147, 153, +-93, 92, -46, -40, -63, -103, -120, -21, +-135, 92, -77, 140, -41, 75, -67, -40, +-135, -66, -171, -15, -105, 63, -5, 101, +-7, 63, -98, 11, -183, -29, -177, -19, +-65, 29, 12, 59, -36, 61, -129, 30, +-183, -11, -128, -8, -30, 26, -20, 64, +-87, 75, -153, 29, -155, -20, -95, -35, +-42, 8, -42, 92, -75, 105, -120, 35, +-130, -44, -120, -65, -103, 19, -63, 106, +-35, 108, -52, 33, -109, -58, -160, -59, +-147, 29, -77, 107, -18, 107, -29, 7, +-108, -76, -162, -38, -134, 60, -68, 132, +-35, 92, -63, -26, -114, -83, -137, -41, +-112, 65, -62, 146, -49, 101, -72, -15, +-111, -92, -126, -63, -111, 66, -78, 137, +-46, 94, -47, -11, -98, -80, -143, -27, +-138, 72, -97, 116, -32, 82, -22, -27, +-97, -82, -157, -16, -132, 92, -71, 143, +-24, 60, -59, -60, -131, -81, -156, -2, +-92, 106, -13, 131, -26, 42, -120, -47, +-169, -76, -125, 3, -35, 118, 8, 121, +-76, 23, -171, -79, -172, -59, -71, 68, +19, 134, -15, 85, -133, -25, -196, -91, +-146, -26, -23, 89, 32, 142, -44, 81, +-159, -51, -191, -96, -116, -4, -20, 109, +12, 125, -51, 27, -146, -58, -170, -34, +-105, 40, -29, 86, -7, 57, -56, -7, +-132, -17, -161, 5, -105, 46, -23, 69, +0, 28, -65, -5, -138, -1, -162, 25, +-97, 37, -7, 14, 4, 11, -71, 44, +-146, 45, -150, 11, -80, -21, -9, 2, +-26, 68, -94, 67, -142, 14, -113, -20, +-48, -8, -23, 50, -63, 74, -115, 31, +-122, -24, -75, -39, -39, 35, -48, 114, +-84, 82, -113, -31, -90, -91, -57, 0, +-66, 131, -87, 111, -81, -24, -67, -96, +-55, -6, -71, 131, -91, 117, -103, -16, +-82, -109, -38, -52, -42, 122, -79, 181, +-100, 43, -93, -136, -65, -139, -47, 75, +-63, 239, -96, 126, -95, -120, -55, -198, +-36, 7, -59, 233, -94, 184, -110, -61, +-83, -205, -34, -75, -21, 167, -56, 220, +-112, 43, -118, -149, -71, -131, -26, 77, +-28, 203, -72, 82, -120, -105, -99, -125, +-28, 58, -12, 190, -61, 74, -120, -111, +-116, -119, -57, 60, -1, 190, -11, 86, +-89, -94, -149, -122, -99, 26, -26, 166, +-2, 113, -33, -57, -99, -129, -125, -15, +-77, 155, -26, 157, -27, -24, -62, -143, +-91, -50, -91, 136, -73, 161, -35, -16, +-21, -128, -54, -29, -90, 128, -90, 121, +-75, -33, -42, -112, -18, -13, -30, 129, +-76, 133, -117, -16, -99, -131, -40, -53, +3, 126, -12, 176, -81, 14, -126, -163, +-94, -99, -29, 133, 5, 221, -29, 42, +-92, -177, -120, -138, -85, 97, -15, 218, +14, 95, -43, -112, -108, -150, -117, 12, +-61, 166, 4, 131, -1, -42, -62, -136, +-113, -23, -93, 137, -34, 126, -8, -42, +-28, -129, -57, -4, -86, 147, -77, 106, +-45, -59, -30, -112, -30, 16, -54, 138, +-82, 88, -66, -61, -39, -107, -27, 10, +-41, 137, -70, 107, -81, -39, -52, -116, +-10, -30, -21, 116, -70, 128, -91, -15, +-60, -120, -23, -43, -5, 120, -45, 139, +-90, -21, -76, -134, -35, -45, -14, 130, +-30, 144, -59, -19, -67, -139, -57, -60, +-36, 111, -28, 148, -43, 17, -55, -118, +-55, -84, -55, 81, -52, 171, -46, 63, +-35, -128, -29, -131, -49, 59, -68, 188, +-74, 83, -34, -116, 11, -135, -15, 29, +-83, 166, -104, 102, -57, -62, 2, -120, +16, -27, -40, 110, -99, 114, -95, -1, +-28, -87, 18, -46, -18, 62, -77, 94, +-94, 28, -55, -52, 10, -28, 8, 48, +-60, 57, -115, -7, -65, -53, 19, 6, +14, 84, -51, 65, -103, -30, -95, -72, +-17, -5, 42, 77, -3, 84, -94, 10, +-117, -64, -56, -60, 24, 25, 28, 101, +-36, 64, -98, -39, -93, -86, -23, -16, +21, 65, 3, 71, -50, 23, -77, -24, +-70, -37, -47, -34, -6, 12, 11, 83, +-22, 91, -79, -2, -100, -109, -53, -74, +14, 84, 21, 160, -36, 43, -78, -124, +-78, -124, -47, 34, -3, 162, 10, 111, +-25, -57, -93, -151, -82, -69, 0, 116, +25, 180, -39, 36, -86, -159, -45, -149, +-7, 72, -17, 198, -51, 78, -58, -114, +-33, -135, -5, 15, -19, 123, -53, 88, +-55, -19, -39, -78, -19, -51, -10, 25, +-39, 87, -50, 48, -29, -35, -13, -54, +-30, -2, -64, 41, -61, 6, 2, -6, +40, 43, -19, 52, -113, -34, -122, -110, +-18, -15, 78, 136, 65, 135, -66, -41, +-173, -181, -117, -90, 36, 107, 132, 199, +46, 78, -134, -135, -195, -212, -72, -56, +102, 204, 122, 251, -30, 7, -173, -269, +-147, -225, 4, 108, 100, 295, 63, 140, +-67, -158, -143, -238, -100, -58, 16, 154, +73, 207, 0, 55, -90, -138, -88, -193, +-10, -22, 19, 179, -38, 157, -61, -28, +-12, -143, 16, -66, -36, 35, -79, 52, +-44, 53, 9, 54, 3, 3, -30, -107, +-40, -100, -58, 49, -58, 165, -6, 101, +47, -97, -14, -168, -103, -50, -63, 116, +14, 153, 34, 20, -17, -120, -69, -130, +-61, 1, -15, 137, 12, 123, -8, -36, +-39, -157, -48, -66, -43, 129, -36, 143, +-9, -62, 37, -176, 13, -8, -71, 187, +-131, 102, -57, -147, 87, -208, 118, 26, +-29, 248, -189, 164, -145, -131, 33, -290, +128, -95, 75, 236, -63, 304, -175, 5, +-148, -309, 27, -254, 163, 84, 104, 323, +-100, 210, -216, -132, -120, -338, 68, -188, +164, 204, 53, 403, -124, 119, -175, -339, +-79, -382, 55, 71, 103, 417, 51, 211, +-76, -237, -147, -315, -87, 10, 35, 230, +84, 112, 45, -82, -45, -89, -125, -3, +-91, 4, 22, -15, 85, 28, 42, 62, +-62, 3, -98, -71, -70, -32, 10, 26, +52, 12, 34, -8, -26, 48, -104, 83, +-85, -57, 16, -193, 87, -56, 30, 217, +-95, 233, -116, -96, -2, -316, 82, -115, +26, 227, -60, 279, -98, -19, -40, -272, +43, -189, 61, 109, 10, 259, -75, 77, +-104, -182, -41, -196, 65, 47, 95, 194, +-16, 63, -113, -123, -93, -120, 5, 36, +61, 100, 56, 32, 2, -54, -73, -79, +-116, -19, -58, 57, 90, 96, 125, 25, +2, -115, -138, -134, -152, 19, -8, 188, +121, 126, 118, -120, -21, -222, -154, -36, +-145, 204, -1, 165, 143, -89, 127, -195, +-21, -45, -177, 130, -174, 87, 26, -46, +229, -76, 146, 0, -168, 61, -266, 12, +-55, -60, 197, -64, 187, 43, -25, 126, +-181, 23, -172, -134, -6, -146, 172, 53, +174, 195, -48, 84, -240, -108, -145, -184, +104, -46, 204, 123, 48, 159, -127, 43, +-152, -150, -37, -181, 83, -25, 127, 185, +71, 186, -118, -48, -204, -219, -30, -151, +177, 119, 149, 222, -56, 55, -161, -161, +-91, -172, 49, 28, 115, 123, 51, 104, +-59, -20, -95, -116, -26, -84, 45, 17, +56, 124, 3, 48, -30, -79, -9, -92, +-14, 20, -28, 85, -11, -15, 63, -62, +55, 2, -63, 89, -92, 35, 12, -117, +70, -120, 18, 37, -11, 200, -3, 103, +-14, -146, -48, -233, -20, -50, 69, 204, +67, 220, -22, 27, -98, -213, -55, -264, +60, -40, 105, 280, 44, 341, -77, -33, +-106, -418, -24, -328, 86, 157, 134, 453, +48, 229, -105, -232, -165, -435, -26, -181, +150, 256, 182, 438, 7, 121, -186, -339, +-137, -394, 65, -10, 164, 351, 70, 258, +-36, -79, -67, -257, -74, -148, -32, 58, +68, 144, 156, 110, 68, -5, -126, -99, +-178, -111, -6, -22, 189, 77, 154, 71, +-41, 19, -152, -35, -42, -42, 75, -54, +40, -39, -2, 57, 42, 102, 73, 43, +-37, -95, -132, -117, -34, -3, 138, 71, +154, 56, -16, 5, -121, -3, -66, -45, +43, -101, 86, -38, 61, 118, 15, 158, +-20, -40, -40, -214, -44, -115, 22, 147, +104, 201, 104, -43, 4, -205, -121, -62, +-95, 153, 56, 102, 153, -117, 83, -125, +-42, 67, -75, 137, -22, -12, 43, -147, +44, -73, 41, 62, 57, 92, 33, 32, +-37, -55, -73, -86, -7, -55, 81, 32, +125, 103, 49, 53, -77, -56, -107, -109, +-12, -46, 122, 57, 141, 90, 31, 29, +-99, -79, -97, -92, 34, -3, 130, 76, +94, 49, -27, -47, -56, -65, 1, -6, +56, 65, 30, 36, -15, -80, 4, -112, +72, 7, 106, 192, -4, 121, -124, -183, +-74, -309, 101, -26, 213, 370, 112, 298, +-120, -181, -232, -466, -43, -188, 251, 321, +275, 426, -9, 45, -246, -385, -154, -374, +104, 43, 233, 378, 155, 281, -33, -122, +-159, -348, -120, -205, 78, 103, 206, 276, +133, 163, -52, -78, -134, -268, -23, -195, +111, 82, 104, 251, 4, 164, -18, -122, +29, -261, 52, -122, 39, 121, -31, 237, +-49, 55, 49, -182, 165, -208, 106, 27, +-99, 227, -178, 89, 0, -165, 238, -195, +217, 67, -44, 213, -226, 25, -112, -207, +183, -165, 264, 145, 46, 219, -163, -36, +-102, -249, 89, -109, 151, 191, 53, 150, +-45, -103, -18, -183, 63, 18, 80, 154, +7, 1, -42, -148, 9, -82, 86, 112, +115, 124, 22, -59, -66, -171, -40, -60, +74, 134, 123, 99, 52, -95, -14, -149, +-3, 33, 28, 146, 4, -25, 13, -177, +96, -63, 125, 161, 27, 133, -123, -106, +-95, -205, 112, -52, 246, 145, 106, 142, +-141, -25, -164, -162, 42, -114, 217, 44, +139, 110, -59, 26, -83, -67, 55, -33, +114, 3, 4, -47, -50, -105, 48, 2, +159, 179, 96, 120, -92, -137, -124, -303, +38, -93, 198, 244, 163, 276, -17, -21, +-129, -304, -77, -222, 93, 55, 174, 227, +112, 150, -11, -59, -60, -198, -29, -190, +4, 20, 73, 177, 173, 134, 161, -51, +-51, -176, -205, -102, -78, -14, 196, 55, +311, 82, 98, 64, -206, -23, -231, -173, +74, -149, 308, 47, 176, 216, -111, 117, +-176, -161, 41, -245, 196, -43, 107, 184, +-49, 116, -43, -110, 90, -162, 107, 0, +-4, 132, -58, 18, 49, -154, 138, -130, +79, 76, -20, 202, -52, 29, 37, -247, +114, -245, 78, 71, -4, 304, -17, 120, +69, -226, 95, -277, 33, -28, -41, 180, +-27, 121, 94, -24, 184, -96, 87, -109, +-130, -75, -139, -2, 96, 117, 265, 106, +115, -51, -120, -180, -103, -139, 71, 54, +154, 151, 75, 68, -7, -122, 30, -200, +92, -45, 14, 127, -86, 131, 18, -79, +206, -194, 186, -48, -58, 126, -198, 105, +-37, -123, 232, -179, 263, 6, 15, 141, +-190, 54, -107, -153, 154, -133, 253, 45, +64, 128, -142, -21, -89, -182, 138, -57, +210, 150, 40, 128, -125, -152, -64, -287, +147, -40, 210, 254, 59, 225, -112, -128, +-81, -363, 97, -205, 197, 152, 109, 355, +-54, 127, -62, -282, 28, -403, 83, -75, +86, 328, 82, 284, 77, -95, -12, -332, +-89, -180, -21, 104, 173, 152, 221, 36, +37, -69, -142, -72, -115, -47, 129, -70, +238, -46, 83, 19, -109, 90, -65, 54, +143, -78, 154, -159, -25, -128, -108, 20, +71, 138, 228, 134, 106, -22, -115, -228, +-154, -236, 86, -22, 278, 238, 172, 238, +-94, -66, -196, -321, 14, -280, 223, 43, +208, 297, 31, 215, -111, -104, -69, -352, +75, -254, 176, 77, 103, 299, -17, 199, +-30, -138, 41, -343, 86, -211, 35, 112, +32, 281, 64, 113, 65, -163, 31, -262, +-9, -114, 25, 78, 97, 127, 117, 82, +24, -44, -50, -161, 0, -189, 108, -61, +156, 157, 62, 188, -62, -5, -38, -252, +99, -254, 137, 8, 26, 208, -25, 179, +73, -63, 106, -230, -5, -199, -63, -40, +59, 158, 220, 187, 132, 47, -123, -221, +-184, -327, 104, -92, 343, 242, 163, 323, +-164, -34, -202, -369, 76, -298, 264, 51, +166, 282, -19, 136, -81, -89, 12, -211, +80, -181, 57, -51, 56, 91, 99, 198, +115, 59, 13, -180, -92, -265, -39, -105, +138, 123, 231, 158, 100, 69, -77, -82, +-132, -205, 6, -196, 189, -32, 190, 196, +61, 195, -33, -41, -26, -257, -10, -252, +14, -42, 108, 154, 217, 232, 188, 98, +-62, -214, -268, -416, -124, -230, 280, 270, +441, 501, 142, 113, -266, -477, -301, -576, +43, -17, 346, 514, 298, 400, 18, -182, +-134, -544, -117, -277, -18, 206, 117, 352, +241, 68, 247, -251, -2, -229, -253, -27, +-198, 90, 174, 18, 435, -52, 231, 12, +-179, 22, -295, -100, 19, -209, 283, -55, +206, 198, 11, 155, -53, -144, 29, -296, +43, -63, 15, 180, 62, 90, 113, -126, +102, -141, 15, 24, -3, 46, 13, -71, +32, -100, 88, -7, 106, 66, 87, -8, +-9, -100, -14, -97, 68, -20, 80, 58, +36, 14, 22, -86, 131, -121, 137, -27, +-20, 85, -139, 31, -15, -116, 234, -166, +259, -29, 59, 138, -126, 82, -126, -124, +0, -237, 164, -90, 290, 132, 203, 151, +-81, -13, -257, -198, -134, -206, 184, -41, +395, 149, 270, 185, -87, -34, -343, -260, +-197, -237, 235, 22, 483, 210, 253, 114, +-185, -86, -334, -208, -90, -159, 243, -5, +345, 118, 193, 128, -43, -30, -194, -188, +-153, -199, 73, -42, 294, 141, 304, 143, +64, -21, -190, -208, -217, -209, 4, -22, +301, 137, 345, 139, 79, -31, -214, -197, +-197, -216, 77, -44, 281, 171, 250, 151, +0, -61, -149, -232, -59, -170, 109, 16, +154, 124, 103, 118, 75, -37, 7, -210, +-50, -225, 17, -9, 119, 232, 119, 151, +67, -140, 29, -311, 17, -170, 17, 128, +57, 243, 88, 89, 73, -228, 38, -345, +4, -93, 78, 246, 131, 262, 63, -96, +-56, -344, -53, -211, 126, 107, 218, 218, +115, 41, -63, -148, -112, -186, 7, -74, +143, 30, 224, 50, 147, 29, -42, -20, +-160, -74, -81, -143, 168, -132, 301, 18, +204, 170, -60, 129, -252, -137, -126, -331, +148, -180, 377, 184, 303, 326, -53, 36, +-346, -345, -260, -349, 214, 30, 495, 318, +326, 173, -141, -177, -419, -298, -185, -110, +286, 93, 533, 100, 189, 15, -272, -42, +-299, -80, 30, -127, 281, -119, 225, 1, +113, 139, 13, 137, -117, -71, -184, -311, +13, -263, 364, 110, 373, 392, -17, 151, +-351, -368, -227, -477, 237, -22, 450, 414, +182, 286, -216, -192, -252, -420, 79, -194, +287, 170, 182, 252, -34, 32, -90, -199, +21, -199, 109, -29, 107, 45, 32, 12, +14, 1, 71, 40, 84, -21, 5, -183, +-44, -188, 69, 24, 186, 227, 101, 134, +-81, -169, -101, -326, 111, -155, 253, 175, +79, 273, -143, 33, -104, -265, 144, -287, +261, -31, 117, 170, -105, 147, -169, -2, +52, -142, 229, -205, 170, -151, 3, 66, +-43, 241, 13, 114, -4, -214, 15, -343, +120, -76, 210, 221, 121, 212, -125, -48, +-225, -264, 8, -224, 376, -14, 363, 210, +-81, 180, -376, -117, -152, -314, 279, -150, +399, 174, 146, 187, -152, -64, -260, -188, +-65, -96, 236, 7, 316, -2, 121, 32, +-117, 54, -161, -50, -59, -162, 125, -122, +260, 55, 186, 113, -41, 31, -183, -92, +-88, -167, 115, -120, 248, 19, 201, 160, +-12, 103, -192, -106, -143, -255, 114, -170, +329, 106, 199, 239, -122, 72, -211, -225, +9, -279, 199, -19, 155, 172, 51, 105, +-47, -61, -48, -116, 50, -97, 131, -75, +79, 18, -52, 95, 0, 26, 107, -109, +99, -112, 4, -25, -23, -24, 60, -24, +76, 67, 33, 70, -13, -117, 35, -225, +122, -9, 78, 197, -58, 39, -93, -207, +112, -134, 249, 128, 53, 105, -196, -148, +-126, -188, 198, 34, 293, 164, 47, 6, +-176, -161, -124, -142, 130, -29, 210, 87, +66, 110, -92, 7, -38, -180, 131, -206, +104, 27, -44, 190, -80, 58, 104, -158, +197, -114, 25, 37, -125, -28, -53, -126, +146, 9, 168, 211, 29, 48, -69, -305, +-34, -265, 41, 120, 70, 292, 106, 40, +108, -206, -4, -162, -141, -54, -57, -1, +163, 92, 202, 159, 43, -19, -53, -300, +-39, -213, -48, 134, -5, 244, 174, 5, +257, -166, 4, -81, -276, -67, -138, -121, +249, 14, 311, 277, -16, 191, -221, -290, +-49, -471, 156, -56, 109, 421, -1, 330, +16, -166, 52, -406, 9, -200, -15, 132, +-9, 213, 43, 73, 132, -43, 121, -129, +-41, -195, -150, -144, -16, 125, 166, 314, +166, 74, 21, -303, -88, -324, -105, 29, +1, 248, 187, 131, 208, -40, -11, -144, +-228, -193, -106, -134, 214, 118, 272, 294, +-15, 69, -206, -284, -20, -337, 168, 8, +63, 329, -88, 231, 16, -160, 160, -404, +53, -120, -109, 283, -49, 223, 132, -171, +123, -244, -34, 77, -93, 115, 33, -170, +147, -126, 67, 267, -74, 207, -72, -373, +61, -444, 126, 258, 50, 573, -24, -78, +-18, -652, 13, -190, 37, 515, 41, 300, +43, -370, 42, -371, 12, 239, -58, 311, +-36, -246, 100, -374, 139, 198, 28, 497, +-88, -120, -67, -633, 1, -171, 85, 545, +160, 387, 105, -350, -85, -450, -215, 65, +-26, 272, 234, -26, 225, -150, -60, 115, +-190, 112, -12, -228, 118, -301, 56, 109, +-18, 394, 79, 112, 87, -303, -85, -349, +-176, -3, 3, 290, 270, 232, 239, -81, +-74, -285, -311, -147, -157, 85, 196, 88, +339, -9, 156, 68, -163, 121, -297, -152, +-120, -437, 228, -95, 354, 526, 72, 474, +-262, -326, -232, -766, 100, -155, 263, 630, +106, 537, -105, -257, -142, -620, 7, -166, +94, 365, 72, 304, 18, -98, 2, -203, +3, -21, -59, 22, -40, -103, 90, -40, +179, 192, -1, 159, -205, -196, -44, -313, +248, 16, 162, 325, -229, 148, -208, -250, +188, -296, 276, 22, -58, 311, -180, 166, +46, -196, 85, -296, -78, -39, -56, 233, +190, 106, 168, -92, -130, -53, -198, 52, +26, -69, 156, -252, 56, 31, -10, 379, +36, 204, -2, -361, -123, -465, -34, 103, +156, 447, 117, 190, -74, -256, -68, -234, +42, -27, -10, -8, -45, 25, 86, 221, +162, 279, -16, -202, -176, -571, -88, -216, +91, 498, 160, 565, 120, -94, -15, -545, +-211, -311, -193, 179, 95, 311, 347, 156, +159, -60, -234, -175, -258, -193, 57, -67, +172, 137, 21, 205, 48, 113, 133, -140, +-77, -277, -312, -143, -45, 181, 361, 312, +220, 43, -213, -224, -232, -250, 110, -1, +156, 193, -97, 191, -126, -12, 166, -267, +230, -140, -124, 165, -310, 246, 12, -104, +329, -270, 124, 48, -242, 224, -167, -26, +161, -264, 208, 42, -60, 298, -227, 44, +-39, -329, 209, -220, 183, 203, -107, 306, +-229, 62, 2, -255, 185, -289, 82, -9, +-65, 352, -29, 310, -31, -200, -83, -509, +-18, -123, 184, 478, 207, 399, -88, -205, +-318, -459, -173, -69, 239, 256, 336, 73, +27, -89, -254, 118, -168, 249, 52, -186, +67, -569, 61, -112, 101, 619, 65, 545, +-141, -336, -186, -698, 36, -91, 213, 506, +84, 316, -133, -254, -49, -263, 52, 56, +-24, 149, -121, -53, 91, -90, 294, 150, +22, 132, -367, -146, -313, -305, 213, 14, +462, 347, 160, 205, -312, -131, -409, -248, +-20, -72, 293, -15, 215, 25, -50, 227, +-100, 281, -8, -81, -54, -512, -151, -242, +-41, 363, 269, 451, 271, -47, -116, -376, +-402, -113, -163, 129, 331, 108, 305, -4, +-141, 51, -328, 23, 17, -170, 287, -154, +23, 107, -239, 328, -73, 55, 256, -284, +104, -271, -247, 107, -182, 314, 157, 53, +270, -179, -19, -122, -218, 144, -133, 55, +90, -166, 124, -92, -2, 177, -43, 244, +22, -112, 79, -252, -86, -80, -190, 163, +-49, 165, 199, -7, 254, -53, 7, -123, +-274, -37, -302, 41, 66, 113, 361, 66, +155, -70, -237, -23, -209, -51, 136, -2, +113, -5, -209, 78, -114, 89, 293, -44, +263, -55, -255, -70, -432, 56, 30, 32, +394, 10, 206, -13, -199, 8, -235, 93, +-54, -57, 57, -151, 105, -71, 133, 253, +64, 248, -169, -206, -230, -407, -72, -19, +194, 518, 265, 271, 57, -355, -196, -480, +-324, 71, -86, 494, 208, 164, 337, -280, +110, -249, -318, 175, -394, 198, 9, -172, +451, -211, 209, 183, -292, 389, -293, -122, +128, -471, 251, -98, -109, 473, -197, 310, +75, -349, 206, -411, -49, 98, -238, 482, +-22, 139, 165, -334, 102, -335, -149, 100, +-107, 408, 86, 122, 58, -281, -67, -286, +-107, 147, 110, 314, 121, 0, -55, -244, +-184, -98, -104, 156, 123, 92, 153, -48, +115, -8, -122, 33, -250, -49, -136, -89, +154, 48, 320, 119, 36, 1, -226, -70, +-247, -1, 36, 46, 163, -54, 97, -75, +-10, 91, -118, 168, -65, -4, -48, -202, +63, -113, 73, 136, 17, 175, -52, 17, +-98, -113, -22, -65, 12, -11, 115, -24, +45, 69, -118, 156, -147, 92, 22, -165, +186, -246, 7, -28, -172, 225, -79, 261, +151, -3, 109, -232, -115, -270, -161, 36, +-39, 351, 127, 249, 93, -211, -5, -439, +-71, 6, -81, 448, -38, 234, -33, -356, +74, -359, 106, 212, 7, 398, -129, -71, +-94, -401, 57, 1, 26, 401, -3, 110, +11, -395, 6, -251, -78, 313, -73, 370, +109, -123, 135, -380, -103, -10, -315, 328, +-42, 93, 347, -289, 244, -201, -217, 276, +-358, 358, -2, -94, 179, -449, 43, -171, +-37, 367, 59, 370, 21, -126, -150, -428, +-132, -46, 47, 396, 146, 194, 39, -365, +-130, -369, -101, 291, 101, 541, 142, -46, +-107, -584, -283, -194, -14, 465, 302, 312, +176, -318, -189, -349, -268, 236, 1, 407, +175, -113, 58, -431, -146, -82, -81, 354, +132, 251, 111, -172, -142, -269, -216, 20, +21, 277, 174, 96, 75, -275, -114, -249, +-93, 199, 2, 431, 19, 13, -19, -440, +-47, -228, 50, 308, 60, 329, -40, -176, +-142, -343, -46, 81, 115, 405, 70, 117, +-55, -419, -126, -372, -27, 214, 53, 549, +44, 138, -21, -483, -68, -372, -32, 266, +-14, 488, 41, -80, 27, -489, -36, -71, +-121, 454, -53, 249, 160, -367, 93, -341, +-140, 217, -219, 392, 26, -74, 183, -387, +11, -23, -103, 362, -48, 179, 67, -297, +-61, -292, -156, 171, -5, 350, 186, 1, +151, -347, -182, -106, -248, 291, -28, 227, +168, -198, 56, -303, -82, 98, 12, 311, +22, 66, -69, -287, -170, -166, 7, 174, +128, 256, 55, 21, -22, -258, -88, -181, +-49, 69, -87, 305, 16, 146, 71, -200, +24, -278, -51, 2, -66, 301, 76, 102, +-3, -169, -154, -161, -176, 118, 101, 183, +289, -77, 43, -163, -255, -24, -267, 189, +50, 87, 165, -118, 65, -111, -41, 54, +-65, 165, -27, -50, -99, -168, -36, -17, +66, 222, 86, 137, -54, -222, -169, -214, +-2, 110, 107, 308, 36, -4, -136, -285, +-97, -53, 47, 286, 3, 177, -49, -307, +3, -321, 107, 192, -34, 499, -205, 83, +-110, -477, 126, -335, 169, 240, -106, 429, +-166, -32, 30, -327, 132, -18, -80, 318, +-231, 68, 21, -393, 196, -222, 46, 334, +-212, 419, -112, -107, 132, -388, 79, -45, +-140, 240, -207, 38, 59, -203, 215, 23, +51, 276, -197, 95, -202, -215, 50, -208, +128, 37, -22, 113, -147, 88, 1, 54, +174, -5, 16, -102, -237, -73, -227, 85, +106, 54, 242, -76, 10, -47, -173, 149, +-85, 111, 59, -157, -58, -189, -128, 117, +7, 268, 164, -55, 85, -326, -171, -89, +-202, 367, -62, 321, 136, -170, 124, -412, +-56, -123, -167, 256, -86, 214, 122, 13, +74, -75, -125, -33, -195, -74, 42, -100, +216, 48, 2, 158, -256, 123, -194, -74, +160, -137, 228, -62, -38, 89, -286, 185, +-171, -4, 142, -229, 183, -227, -14, 218, +-201, 447, -82, 74, 78, -428, -2, -411, +-144, 164, -42, 384, 235, 174, 118, -103, +-293, -93, -372, -62, 74, -204, 395, -88, +96, 201, -281, 389, -213, 61, 76, -301, +49, -269, -134, 6, -24, 216, 186, 124, +94, 72, -245, -35, -288, -119, -6, -119, +217, 21, 179, 170, -64, 36, -223, -85, +-214, -90, 20, 69, 204, 112, 92, 28, +-145, -20, -187, -120, 26, -114, 53, -8, +-87, 253, -84, 251, 116, -101, 127, -337, +-176, -186, -310, 188, -42, 213, 303, 83, +201, 11, -198, -14, -364, -131, -85, -208, +232, 47, 124, 231, -133, 132, -152, -89, +62, -51, 68, 58, -173, -102, -203, -209, +87, 20, 282, 383, -7, 251, -356, -216, +-210, -358, 213, -62, 257, 231, -160, 131, +-324, -19, -10, -3, 252, 12, 32, -87, +-260, -142, -109, 47, 168, 201, 101, 127, +-233, -76, -254, -163, 93, -81, 293, 36, +74, 170, -293, 145, -283, -58, -6, -227, +197, -125, 111, 130, -92, 159, -95, 43, +-38, 38, -17, 50, -149, -150, -148, -318, +105, -16, 282, 442, 91, 376, -355, -199, +-386, -511, 14, -176, 360, 267, 187, 327, +-230, 78, -280, -117, -15, -147, 156, -89, +-59, 30, -181, 104, 46, 101, 227, 21, +-20, -62, -426, -88, -239, -63, 295, 48, +426, 132, -97, 89, -547, -57, -247, -144, +259, -30, 343, 124, -78, 140, -310, -30, +-107, -141, 86, -26, 52, 111, -137, 54, +-60, -130, 59, -55, 57, 171, -63, 147, +-168, -133, -72, -229, 27, 81, 111, 269, +-50, 55, -167, -241, -74, -146, 111, 156, +120, 179, -187, -29, -236, -177, -30, -44, +239, 106, 113, 128, -238, 22, -247, -103, +7, -58, 246, 37, -11, 105, -274, -5, +-153, -91, 183, -14, 241, 75, -189, 56, +-360, -92, -83, -56, 314, 77, 176, 114, +-272, -22, -306, -129, 60, 18, 324, 135, +-49, 64, -414, -153, -194, -154, 315, 104, +353, 231, -234, 72, -473, -203, -129, -167, +319, 52, 194, 172, -216, 108, -189, -20, +67, -39, 121, -74, -233, -78, -285, -27, +117, 97, 377, 161, 102, 42, -467, -97, +-426, -162, 97, -41, 470, 130, 155, 176, +-379, 41, -360, -139, 38, -102, 301, 41, +4, 81, -235, -31, -96, -52, 146, 103, +42, 99, -304, -125, -185, -225, 206, 81, +325, 375, -104, 126, -457, -311, -220, -308, +195, 130, 289, 304, -50, 46, -234, -122, +-93, -27, 56, 35, -35, -126, -214, -115, +-75, 174, 192, 310, 236, 70, -114, -248, +-418, -227, -250, -11, 161, 144, 325, 167, +34, 96, -232, -15, -199, -181, -18, -194, +30, -23, -51, 209, -11, 270, 51, 58, +30, -173, -124, -257, -207, -58, -57, 157, +149, 203, 142, 80, -140, -119, -273, -153, +-64, -69, 172, 99, 105, 105, -151, 17, +-202, -4, -26, 13, 102, 29, 21, -77, +-154, -43, -130, 41, 82, 57, 152, -1, +-97, -28, -321, 77, -128, 5, 212, -104, +223, -95, -122, 112, -308, 230, -117, 23, +122, -173, 109, -189, -111, 88, -125, 224, +10, 60, 54, -188, -84, -199, -154, 150, +12, 254, 64, 19, -47, -276, -183, -119, +-30, 247, 185, 199, 95, -94, -217, -245, +-381, 35, -64, 184, 309, 26, 303, -128, +-136, -68, -424, 142, -232, 71, 114, -67, +209, -103, -5, 65, -79, 189, -49, 28, +-47, -163, -177, -191, -159, 104, 95, 258, +186, 66, 24, -208, -204, -197, -120, 125, +-9, 186, -67, -10, -118, -150, 16, 63, +217, 260, 74, 19, -241, -315, -378, -291, +-83, 210, 262, 473, 234, 147, -53, -370, +-285, -429, -184, 93, -20, 419, 83, 203, +41, -242, -32, -245, -15, 143, -45, 262, +-62, -58, -156, -340, -123, -54, 44, 332, +174, 228, 113, -217, -173, -318, -282, 117, +-165, 338, 101, 30, 177, -321, 10, -114, +-117, 309, -100, 244, 10, -176, -118, -323, +-195, 24, -20, 271, 253, 82, 194, -168, +-207, -84, -340, 143, -152, 74, 138, -123, +127, -58, -8, 188, -49, 149, -55, -202, +-52, -294, -165, 83, -124, 397, 35, 169, +177, -297, 88, -348, -191, 46, -211, 322, +-36, 193, 96, -104, -44, -160, -136, -5, +30, 82, 142, -15, 15, -106, -264, 35, +-246, 180, 15, 77, 212, -174, 148, -162, +-110, 108, -223, 181, -183, -24, 27, -152, +119, 67, 23, 204, -81, -5, -83, -253, +43, -171, -44, 158, -170, 236, -115, 72, +103, -96, 168, -83, -92, -45, -216, -94, +-95, -1, 115, 209, 55, 331, -134, 11, +-131, -417, -20, -395, 117, 77, 43, 501, +-92, 313, -181, -116, -115, -339, 49, -199, +68, 28, 35, 153, -47, 251, -55, 133, +-105, -88, -141, -271, -38, -117, 52, 154, +125, 144, 8, -27, -135, -111, -184, 80, +-89, 140, 111, -18, 75, -153, -72, -72, +-171, 117, 5, 55, 135, -15, -74, 35, +-222, 134, -85, -5, 217, -286, 78, -208, +-215, 148, -187, 401, 83, 146, 168, -224, +-119, -251, -173, -1, -24, 187, 105, 65, +-38, -46, -163, -60, 1, 14, 120, 55, +92, 26, -176, 5, -243, -73, -76, -61, +150, -15, 199, 68, -43, 114, -177, 93, +-157, 65, 17, -96, 25, -227, -103, -186, +-96, 125, 85, 372, 227, 198, -27, -175, +-294, -341, -257, -69, 25, 190, 166, 144, +60, -39, 8, -64, 3, 80, -26, 50, +-194, -77, -261, -97, -50, 50, 225, 88, +270, -93, -28, -138, -258, 93, -181, 345, +19, 166, 46, -281, -94, -427, -52, -90, +146, 344, 208, 338, -53, 29, -354, -180, +-274, -144, 104, -64, 324, -70, 89, 25, +-213, 175, -169, 192, 48, -13, 55, -169, +-111, -69, -93, 83, 49, 70, 58, -108, +-87, -147, -135, 46, 49, 250, 159, 220, +-7, -77, -282, -304, -266, -234, 76, 87, +293, 296, 173, 172, -150, -74, -265, -173, +-121, -23, 41, 93, 75, 13, -33, -127, +-37, -97, 30, 105, 102, 180, 11, 89, +-184, -34, -223, -57, -53, -92, 207, -180, +188, -72, -19, 231, -163, 370, -92, 42, +-2, -370, -68, -289, -58, 152, 49, 322, +155, -21, 25, -282, -140, -41, -130, 324, +-23, 237, 38, -205, -56, -339, -41, -35, +50, 226, 95, 72, -59, -143, -198, 15, +-55, 276, 113, 164, 66, -293, -176, -439, +-188, -34, 45, 430, 231, 411, 119, -43, +-205, -351, -286, -257, -49, 51, 228, 207, +112, 113, -167, -34, -148, -80, 112, -5, +214, 22, -71, 5, -270, 40, -143, 101, +135, 5, 210, -241, 30, -234, -83, 154, +-93, 468, -10, 192, -19, -348, -73, -411, +-45, 20, 57, 293, 149, 81, 4, -121, +-129, 40, -103, 229, 35, 62, -10, -271, +-203, -281, -107, 12, 214, 219, 352, 158, +-63, 29, -445, 25, -274, 31, 150, -83, +244, -247, -50, -190, -86, 131, 88, 371, +91, 230, -186, -136, -261, -280, 50, -114, +220, 61, 87, 36, -134, -34, -89, 52, +46, 168, 95, 148, 34, -23, -125, -197, +-176, -232, -45, -74, 220, 182, 231, 262, +-29, 87, -196, -106, -115, -85, 41, -18, +-26, -124, -78, -177, 48, 98, 202, 396, +119, 209, -158, -273, -228, -351, -90, 49, +52, 257, 15, -16, -21, -242, 93, 21, +141, 317, -22, 136, -287, -250, -257, -237, +44, 103, 238, 184, 129, -62, -89, -180, +-103, 91, -15, 306, 24, 92, -57, -289, +-106, -337, -17, 15, 110, 277, 187, 205, +73, -20, -104, -94, -174, -49, -87, -58, +58, -77, 105, 14, 123, 168, 79, 121, +-41, -121, -149, -244, -113, -10, 100, 312, +183, 248, 14, -179, -226, -446, -169, -163, +154, 327, 266, 413, 20, 41, -265, -277, +-176, -198, 59, 18, 73, 53, -50, -34, +-47, 12, 120, 162, 89, 153, -114, -57, +-256, -235, -127, -148, 125, 104, 191, 211, +97, 42, -65, -182, -86, -106, -84, 165, +-73, 206, -4, -91, 88, -283, 147, -75, +48, 176, -29, 147, -53, -4, -20, 24, +-12, 54, -15, -127, 60, -245, 98, -22, +72, 282, -46, 196, -71, -117, -2, -187, +34, 23, 34, 101, 6, -77, -2, -144, +-71, 63, -67, 274, 43, 156, 105, -179, +22, -349, -144, -145, -130, 230, 3, 358, +79, 92, 13, -263, -63, -285, 10, 13, +57, 236, -44, 140, -186, -82, -111, -124, +132, -3, 215, 65, 54, 14, -154, -39, +-125, -16, 53, 26, 125, 30, 0, -1, +-130, -28, -17, -15, 196, 7, 197, 33, +-56, 15, -169, 1, -2, 23, 116, 23, +16, -46, -81, -125, 67, -50, 186, 113, +55, 167, -122, 25, -115, -113, 13, -101, +12, -25, -31, 9, 33, 16, 125, 98, +68, 113, -121, -16, -208, -165, -137, -120, +30, 60, 147, 127, 125, 41, 11, -66, +-111, -39, -110, 14, -72, 17, -50, -6, +-20, 11, 74, 47, 170, 24, 88, -50, +-71, -120, -154, -69, -25, 102, 108, 244, +57, 121, -63, -202, -20, -350, 215, -79, +244, 306, -28, 330, -302, 0, -193, -277, +165, -220, 323, 4, 182, 154, -81, 164, +-169, 69, -103, -77, 13, -175, 66, -109, +64, 52, 72, 149, 0, 105, -66, -20, +-81, -107, 2, -91, 44, 14, -28, 88, +-97, 15, -113, -103, -2, -69, 126, 115, +167, 194, 6, 23, -232, -193, -248, -198, +-33, 3, 219, 150, 218, 136, 57, 41, +-96, -14, -148, -62, -83, -141, 37, -110, +187, 70, 181, 202, 51, 44, -82, -171, +-76, -80, 28, 197, 72, 164, 78, -212, +43, -316, 44, 37, 38, 312, 26, 100, +8, -135, -36, 16, -39, 164, -22, -147, +68, -477, 94, -99, 14, 577, -105, 580, +-120, -183, 27, -675, 87, -306, 18, 297, +-85, 358, -71, -13, -25, -153, -26, 50, +13, 155, 50, -75, 29, -295, -82, -155, +-94, 188, 21, 305, 126, 76, 90, -145, +-77, -96, -118, 34, 0, -44, 152, -221, +153, -127, 4, 277, -77, 449, -11, 73, +115, -414, 128, -391, 31, 65, -59, 282, +-38, 65, 84, -108, 147, 84, 71, 220, +-76, -73, -93, -412, 42, -216, 128, 312, +34, 427, -112, -23, -81, -387, 61, -164, +93, 265, -42, 282, -155, -115, -77, -355, +70, -118, 115, 260, 24, 287, -78, -45, +-123, -247, -132, -88, -56, 135, 108, 65, +231, -131, 113, -87, -169, 158, -255, 207, +-15, -62, 222, -246, 152, -104, -37, 121, +-34, 111, 81, -22, 65, -34, -69, 42, +-67, 36, 107, -45, 214, -63, 103, -20, +-70, 5, -50, 15, 55, 66, 40, 66, +-58, -34, -31, -105, 134, -39, 171, 46, +36, 12, -129, -37, -139, 25, -60, 99, +26, -5, 92, -120, 69, -23, 19, 152, +-72, 58, -128, -229, -137, -230, -29, 152, +140, 427, 142, 133, -14, -358, -173, -389, +-82, 77, 72, 372, 39, 131, -94, -219, +-45, -185, 200, 131, 217, 189, -5, -37, +-187, -179, -100, -54, 41, 73, 84, -12, +160, -58, 188, 103, 112, 244, -114, 40, +-207, -303, -52, -310, 172, 76, 268, 348, +105, 150, -87, -200, -163, -204, -46, 118, +87, 240, 82, -49, -4, -334, -72, -175, +16, 228, 73, 337, 32, 42, -93, -198, +-134, -106, -56, 50, -10, -58, 38, -225, +74, -31, 103, 376, -20, 400, -159, -124, +-150, -514, -21, -274, 115, 223, 126, 302, +92, 2, -21, -95, -115, 89, -80, 110, +74, -170, 169, -275, 64, -6, -45, 235, +-22, 122, 96, -92, 107, -31, 16, 144, +-24, 76, -6, -217, 25, -323, 32, -36, +86, 348, 127, 370, 75, -32, -66, -372, +-161, -249, -91, 137, 59, 231, 128, -27, +65, -173, 0, 29, -17, 232, -54, 92, +-122, -177, -113, -200, -6, -16, 99, 74, +94, 40, 25, 50, -53, 123, -105, 59, +-76, -151, -10, -245, 37, -66, 39, 194, +84, 220, 125, 23, 29, -127, -134, -93, +-174, -36, -5, -56, 178, -19, 240, 146, +127, 220, -49, -2, -138, -279, -82, -240, +70, 88, 135, 277, 109, 130, 9, -91, +-23, -124, 24, -28, 56, -9, 14, -64, +-74, -42, -33, 93, 52, 194, 77, 103, +-10, -136, -58, -259, -16, -101, -3, 161, +-19, 200, -36, 3, 31, -121, 29, -16, +-36, 86, -68, -38, -24, -169, 46, -64, +23, 171, -10, 197, -45, -16, -32, -149, +7, -79, 61, 35, 88, 7, 30, -29, +-16, 33, -49, 121, -16, 58, 42, -124, +90, -177, 83, -35, 18, 149, 15, 135, +46, -8, 58, -84, -30, -26, -89, 17, +-24, -49, 115, -59, 183, 45, 63, 131, +-95, 37, -137, -115, -24, -117, 57, 26, +43, 132, 18, 61, 21, -89, 3, -135, +-51, -17, -49, 144, -22, 146, -6, -26, +-27, -168, -16, -110, 51, 41, 98, 83, +51, 26, -83, 2, -165, 51, -103, 39, +76, -64, 180, -133, 134, -63, 22, 92, +-55, 152, -77, 62, -73, -89, -5, -121, +88, -21, 153, 59, 112, 27, 26, -49, +-41, -8, -65, 81, -35, 78, -6, -45, +37, -115, 73, -46, 135, 41, 119, 45, +-34, -1, -204, 27, -210, 72, 13, 5, +200, -142, 207, -159, 41, 45, -116, 229, +-157, 151, -122, -102, -28, -194, 44, -45, +129, 91, 124, 25, 13, -76, -122, -6, +-125, 130, 5, 115, 48, -56, 26, -172, +15, -124, 88, 15, 102, 117, -11, 142, +-100, 71, -76, -48, 58, -137, 110, -139, +91, -40, 29, 106, -13, 196, -3, 91, +4, -127, 31, -210, -7, -33, -21, 157, +19, 113, 105, -47, 120, -88, -35, 5, +-152, 9, -111, -46, 66, 12, 117, 124, +36, 49, -46, -161, -55, -154, -1, 102, +-6, 227, -10, 12, -24, -216, -16, -119, +-14, 131, 0, 174, 45, -12, 33, -135, +-10, -79, -68, 10, -47, 60, 26, 80, +86, 63, 87, -45, 31, -158, -16, -87, +-56, 112, -13, 183, 55, 12, 95, -170, +70, -137, 10, 44, 13, 133, 20, 49, +2, -37, -32, -42, 24, -15, 92, -17, +61, -17, -29, 18, -69, 36, -5, 16, +34, -6, 26, 13, -12, 11, -20, -31, +5, -68, 3, -36, -45, 35, -93, 69, +-29, 69, 104, 30, 132, -31, -58, -95, +-231, -98, -117, -25, 159, 76, 225, 125, +-31, 71, -233, -22, -97, -84, 162, -80, +158, -46, -28, 12, -76, 83, 21, 100, +46, 15, -28, -98, 32, -85, 174, 47, +140, 93, -108, -49, -234, -172, -22, -48, +290, 194, 314, 233, -20, -14, -281, -259, +-187, -224, 116, 32, 228, 227, 71, 176, +-86, -17, -72, -152, 30, -118, 13, 4, +-57, 66, -54, 43, 46, -4, 65, -13, +-56, -9, -101, 4, -7, 33, 101, 30, +19, -31, -141, -106, -149, -78, 49, 44, +207, 161, 103, 131, -107, -49, -201, -209, +-71, -162, 112, 69, 162, 216, 68, 123, +-37, -79, -40, -139, 11, -63, 31, 14, +7, 38, 54, 55, 114, 74, 52, -18, +-56, -140, -49, -123, 99, 51, 148, 183, +14, 117, -114, -52, -65, -162, 91, -127, +123, 0, 15, 109, -70, 124, -27, 52, +16, -28, -47, -73, -68, -93, 33, -86, +123, 1, 27, 132, -148, 167, -149, 29, +11, -141, 112, -148, 50, -10, -62, 80, +-112, 26, -41, -31, 71, 30, 74, 103, +-17, 35, -73, -134, -34, -158, 22, 23, +53, 164, 60, 73, 45, -104, 6, -77, +-31, 89, -6, 95, 41, -105, 74, -184, +76, 20, 23, 201, -42, 94, -22, -134, +109, -116, 137, 90, -18, 118, -147, -84, +-49, -188, 151, 2, 173, 205, 14, 139, +-128, -95, -98, -177, -13, -52, 11, 71, +53, 65, 105, 6, 56, 8, -110, 26, +-208, -6, -94, -71, 137, -66, 185, 40, +-35, 104, -209, 19, -119, -120, 108, -86, +155, 122, -22, 200, -167, -25, -80, -285, +108, -191, 125, 173, -4, 321, -70, 64, +14, -226, 62, -184, -16, 34, -30, 81, +103, -13, 147, 2, -33, 101, -152, 49, +21, -126, 222, -137, 139, 55, -85, 157, +-172, 17, -49, -138, 132, -78, 207, 85, +113, 123, -78, 16, -197, -86, -133, -96, +75, -44, 167, 40, 104, 105, -5, 85, +-90, -12, -117, -95, -80, -84, 16, -17, +61, 46, 57, 65, -17, 47, -58, -1, +-16, -64, 21, -70, -13, 4, -112, 69, +-95, 35, 44, -38, 202, -29, 159, 44, +-69, 37, -228, -77, -176, -106, 67, 28, +222, 156, 187, 81, 22, -114, -68, -175, +-76, -27, -105, 138, -14, 129, 148, -9, +218, -111, 49, -71, -113, 26, -97, 58, +36, 5, 109, -35, 8, -15, -33, 19, +9, 28, 71, 23, 41, 8, -34, -50, +-61, -100, -29, -28, 44, 131, 19, 161, +-10, -14, -17, -181, 10, -136, 13, 48, +-36, 119, -35, 45, -33, -10, 7, -7, +13, -19, 22, -59, 19, -32, -22, 44, +-45, 44, -43, -30, 11, -22, 44, 75, +57, 76, 3, -101, -58, -208, -20, -27, +41, 240, 55, 219, 40, -92, 22, -274, +-52, -105, -67, 148, 38, 162, 123, 15, +88, -51, -27, -42, -63, -74, -3, -76, +15, 58, -20, 168, 27, 66, 141, -128, +131, -128, -69, 43, -247, 97, -142, -21, +177, -72, 297, 43, 54, 110, -224, -3, +-194, -125, 50, -72, 141, 56, 28, 67, +-58, 2, 3, -1, 33, 41, -81, 12, +-109, -69, 55, -88, 175, -12, 28, 69, +-164, 89, -161, 64, 37, -19, 207, -127, +97, -150, -106, -11, -128, 177, 15, 181, +74, -15, 10, -170, -19, -130, 41, 9, +107, 76, 9, 55, -122, 25, -99, 16, +79, 4, 193, -35, 68, -87, -126, -93, +-113, 11, 107, 168, 154, 180, -36, -33, +-158, -235, -30, -148, 182, 97, 164, 163, +-53, -2, -190, -90, -63, 33, 128, 97, +102, -42, -33, -165, -36, -43, 49, 159, +13, 125, -108, -76, -111, -134, 81, 19, +210, 130, 31, 28, -185, -132, -152, -119, +32, 52, 120, 157, 73, 74, -13, -73, +-62, -102, -49, -9, -23, 26, 14, -38, +28, -48, 31, 83, 60, 173, 27, 29, +-74, -207, -111, -219, 4, 43, 129, 241, +132, 118, 22, -127, -100, -137, -93, 69, +17, 126, 95, -65, 64, -200, 14, -32, +12, 212, 12, 173, -2, -78, -44, -170, +-28, -30, 80, 43, 119, -34, 10, -44, +-95, 108, -49, 184, 29, 19, 69, -196, +30, -205, -44, -8, -32, 176, 10, 170, +11, -6, -20, -147, 18, -74, 28, 101, +-42, 86, -95, -131, -35, -186, 107, 74, +98, 284, -35, 115, -140, -196, -88, -215, +57, 8, 117, 110, 42, 17, -77, -34, +-48, 57, 15, 117, 28, 18, 24, -144, +21, -185, 7, -38, -29, 169, 33, 207, +60, 16, 15, -157, -16, -101, 7, 39, +31, 34, -4, -58, 6, -16, 44, 120, +99, 103, 41, -70, -84, -142, -81, -20, +4, 82, 73, 15, 71, -75, 61, 9, +12, 134, -84, 73, -126, -136, -51, -192, +97, 9, 122, 191, 44, 120, -67, -80, +-136, -120, -71, -20, 12, 44, 44, 29, +31, 17, 71, 3, 43, -53, -121, -42, +-168, 49, -18, 69, 149, -35, 120, -90, +14, 32, -78, 107, -106, -20, -35, -133, +56, -17, 153, 143, 101, 67, -51, -121, +-149, -119, -50, 56, 117, 132, 141, 31, +84, -72, -41, -75, -96, -17, -75, 43, +37, 52, 154, 4, 103, -30, -31, 16, +-119, 50, -37, -41, 33, -130, 42, -24, +24, 157, 3, 125, 16, -74, -28, -108, +-56, 36, -59, 39, 3, -129, 57, -108, +45, 171, -17, 278, -100, -6, -57, -280, +27, -182, 56, 67, -25, 135, -38, 68, +35, 58, -11, 45, -54, -91, -1, -182, +71, -60, 19, 118, -45, 130, -7, 32, +35, -2, 16, -22, -28, -99, 35, -126, +83, 36, 11, 205, -57, 107, -13, -137, +72, -178, 49, 48, 0, 162, 7, -11, +36, -168, -14, -21, -37, 189, 44, 74, +66, -174, -10, -129, -63, 141, -9, 154, +43, -112, 46, -181, 4, 74, -83, 200, +-83, -37, 37, -190, 104, 16, 8, 178, +-78, -28, -48, -228, -3, -22, 2, 256, +7, 132, 32, -194, 34, -189, -62, 93, +-138, 134, -3, -84, 183, -106, 116, 158, +-130, 223, -156, -133, 47, -388, 108, -79, +-31, 397, -22, 308, 140, -217, 100, -353, +-128, 73, -204, 307, 16, -88, 219, -369, +164, 75, -40, 553, -103, 155, -15, -588, +-15, -465, -54, 353, 14, 559, 179, -114, +149, -448, -72, 101, -196, 455, -118, -117, +86, -659, 145, -131, 19, 705, -95, 500, +15, -405, 104, -597, -67, 96, -193, 405, +-54, -97, 174, -348, 135, 179, -47, 547, +-110, -18, -41, -636, 20, -316, -21, 404, +-14, 445, 29, -145, 70, -337, 35, 44, +-32, 301, -46, 20, -85, -345, -25, -203, +106, 231, 154, 395, -13, 36, -141, -368, +-9, -255, 89, 195, 29, 328, -60, -82, +28, -329, 105, -7, 10, 357, -104, 124, +-66, -352, 134, -242, 141, 271, -63, 354, +-168, -186, 1, -439, 146, 29, 39, 473, +-56, 193, -45, -385, 40, -333, 17, 178, +-55, 322, -61, -70, 9, -252, 136, 89, +50, 283, -134, -36, -177, -389, 42, -118, +194, 358, 22, 295, -142, -191, -84, -374, +118, 28, 62, 322, -120, 126, -68, -251, +134, -234, 129, 142, -135, 275, -161, 25, +42, -298, 183, -146, 84, 241, -75, 269, +-111, -125, -90, -378, 86, -13, 165, 363, +57, 210, -124, -264, -106, -316, 117, 94, +119, 270, -68, 65, -171, -189, 87, -94, +253, 81, -24, 78, -273, 1, -98, -65, +273, -24, 174, -2, -157, 75, -214, 66, +10, -71, 181, -146, 78, -26, -57, 202, +-128, 110, -9, -151, 86, -180, -8, 89, +-103, 204, -29, -87, 181, -222, 97, 42, +-178, 320, -242, 88, 46, -343, 275, -264, +48, 193, -192, 415, -98, 23, 136, -381, +85, -232, -104, 231, -44, 356, 49, -75, +24, -349, -19, -68, 38, 317, 48, 180, +-64, -252, -26, -248, 80, 130, 51, 285, +-116, -10, -94, -264, 186, -104, 235, 189, +-71, 217, -341, -67, -90, -286, 291, -107, +173, 266, -175, 287, -162, -141, 193, -365, +181, -4, -207, 345, -353, 113, 22, -304, +434, -168, 232, 269, -255, 238, -386, -184, +12, -315, 301, 28, 52, 281, -214, 115, +-59, -139, 251, -176, 111, 1, -258, 137, +-264, 115, 88, -64, 301, -195, 83, -41, +-184, 231, -141, 200, 96, -183, 131, -331, +-75, 54, -171, 408, 36, 102, 241, -457, +114, -307, -130, 403, -157, 582, 12, -166, +57, -764, 7, -252, 57, 617, 141, 602, +44, -254, -162, -622, -152, -49, 4, 450, +130, 147, 106, -391, 23, -193, -44, 399, +-76, 380, -9, -241, -32, -551, -44, -54, +7, 438, 137, 265, 99, -185, -122, -267, +-121, 47, -11, 168, 46, 26, -69, -129, +-15, -134, 180, 64, 114, 208, -135, 162, +-314, -161, -15, -354, 278, -9, 178, 376, +-134, 225, -222, -358, 85, -391, 151, 252, +-2, 535, -138, 7, 3, -609, 155, -291, +0, 425, -111, 458, -74, -149, 175, -472, +167, 59, -70, 443, -229, 28, -161, -578, +202, -311, 314, 618, 109, 700, -288, -236, +-316, -923, 84, -305, 276, 708, 120, 615, +-191, -243, -105, -648, 110, -48, 107, 503, +-105, 209, -267, -362, 49, -422, 348, 220, +178, 560, -343, 112, -381, -542, 177, -504, +365, 332, 14, 691, -301, 88, -90, -655, +160, -466, 109, 436, -32, 625, -130, -76, +-51, -673, 62, -228, 179, 589, 57, 467, +-219, -368, -163, -714, 169, 91, 302, 826, +-94, 273, -346, -755, 9, -712, 395, 514, +187, 1016, -370, -20, -349, -1074, 197, -570, +457, 798, 83, 937, -395, -257, -267, -983, +209, -206, 360, 778, -27, 463, -352, -545, +-135, -645, 253, 320, 297, 774, -94, 30, +-355, -787, -146, -417, 279, 560, 322, 645, +-161, -175, -418, -720, -46, -141, 469, 594, +279, 449, -398, -320, -548, -676, 97, -65, +688, 539, 277, 443, -524, -192, -544, -500, +256, -110, 642, 247, -26, 261, -649, -98, +-236, -245, 641, -23, 577, 242, -357, 299, +-788, -164, -118, -522, 669, -277, 467, 465, +-254, 735, -504, -15, -10, -735, 397, -488, +121, 405, -368, 611, -308, -71, 362, -505, +552, -95, -50, 483, -647, 244, -390, -430, +391, -544, 577, 160, 62, 707, -502, 317, +-338, -509, 263, -707, 411, 55, -53, 733, +-450, 435, -129, -485, 351, -741, 320, 89, +-163, 791, -397, 354, -37, -668, 328, -697, +180, 324, -279, 866, -255, 127, 204, -796, +377, -503, -26, 479, -433, 719, -195, -84, +283, -677, 373, -276, -60, 446, -353, 488, +-73, -127, 284, -468, 195, -197, -208, 282, +-276, 342, 58, -17, 303, -287, 191, -238, +-133, 149, -288, 320, -113, 79, 174, -297, +219, -283, -28, 186, -179, 348, 12, 34, +196, -326, 10, -183, -336, 223, -211, 227, +338, -58, 442, -274, -99, -96, -526, 229, +-160, 280, 384, 2, 257, -383, -234, -319, +-299, 154, 167, 502, 355, 247, -23, -333, +-407, -465, -209, -66, 333, 341, 389, 249, +-92, -70, -444, -140, -104, -37, 359, 31, +244, -65, -221, -32, -343, 70, 114, 95, +350, 70, 60, -19, -329, -85, -219, -186, +279, -46, 331, 240, -78, 216, -431, -84, +-133, -323, 380, -52, 314, 265, -127, 166, +-403, -155, -68, -293, 300, 22, 227, 282, +-148, 196, -343, -166, 55, -332, 372, -47, +145, 263, -376, 219, -372, -110, 235, -213, +482, -32, 63, 139, -495, 75, -293, -77, +324, -63, 440, -5, -101, 110, -530, 34, +-62, -74, 469, -99, 286, -21, -396, 164, +-498, 59, 228, -32, 594, -84, 136, -39, +-613, 13, -435, -85, 388, 93, 584, 190, +3, 84, -564, -239, -219, -339, 330, 125, +331, 395, -110, 171, -379, -351, -1, -346, +329, 220, 207, 426, -240, -29, -352, -530, +52, -214, 330, 504, 222, 547, -225, -240, +-361, -759, -12, -207, 401, 677, 266, 661, +-379, -323, -467, -824, 155, -222, 635, 705, +145, 658, -566, -326, -404, -809, 278, -261, +552, 722, -35, 687, -489, -353, -176, -873, +378, -186, 362, 916, -284, 620, -461, -633, +24, -985, 503, 72, 297, 1159, -357, 503, +-487, -847, 10, -1029, 522, 216, 305, 1214, +-345, 428, -458, -888, 80, -967, 486, 322, +121, 1149, -428, 266, -274, -892, 340, -746, +450, 485, -180, 929, -599, -65, -78, -903, +615, -387, 397, 770, -417, 780, -588, -375, +127, -986, 569, -235, 116, 836, -466, 691, +-262, -323, 370, -783, 402, -172, -221, 569, +-521, 410, -14, -261, 495, -527, 245, -33, +-341, 508, -321, 357, 189, -245, 297, -565, +-99, -174, -351, 384, 2, 451, 383, 12, +205, -374, -265, -244, -416, 140, 51, 229, +393, -52, 148, -210, -266, 37, -234, 310, +223, 80, 262, -299, -143, -270, -376, 103, +-48, 296, 418, 70, 274, -69, -229, -82, +-432, -93, -1, -71, 446, 41, 217, 252, +-351, 43, -440, -262, 209, -202, 619, 177, +131, 394, -615, -78, -511, -425, 380, -181, +681, 349, -9, 406, -651, -200, -229, -431, +529, -65, 375, 381, -350, 264, -586, -238, +86, -313, 613, 1, 265, 297, -376, 162, +-503, -181, 70, -229, 397, 40, 136, 238, +-240, 76, -223, -208, 191, -174, 262, 151, +-65, 205, -355, -30, -162, -216, 296, -24, +312, 190, -49, 9, -297, -123, -114, -29, +133, 152, 109, 34, -11, -217, -56, -4, +-14, 235, 36, 131, 64, -273, -45, -308, +-94, 221, 21, 414, 83, 47, -5, -421, +-92, -313, 109, 247, 155, 397, -120, 69, +-286, -365, -36, -317, 390, 202, 207, 443, +-273, 89, -347, -488, 84, -395, 391, 341, +15, 621, -328, -18, -161, -675, 271, -349, +318, 530, -174, 621, -416, -240, -103, -750, +409, -170, 382, 737, -234, 598, -531, -449, +-121, -868, 485, -142, 422, 863, -214, 687, +-535, -415, -149, -933, 422, -265, 396, 813, +-146, 713, -435, -337, -91, -863, 333, -165, +249, 822, -196, 501, -366, -580, 39, -829, +448, 198, 260, 1048, -363, 329, -536, -879, +67, -907, 574, 332, 302, 1103, -354, 362, +-486, -779, 42, -833, 427, 244, 218, 904, +-287, 291, -398, -751, 74, -712, 432, 405, +254, 973, -309, 159, -510, -967, -50, -684, +474, 547, 437, 969, -247, 4, -576, -931, +-76, -403, 539, 641, 360, 704, -465, -310, +-598, -847, 203, -127, 814, 740, 249, 595, +-766, -376, -687, -781, 335, -160, 876, 674, +176, 575, -696, -317, -529, -739, 319, -143, +693, 717, 48, 519, -620, -401, -406, -778, +395, -75, 667, 748, -31, 457, -661, -368, +-382, -654, 462, -22, 634, 560, -149, 248, +-696, -318, -174, -428, 659, 159, 445, 492, +-524, 83, -696, -445, 215, -427, 811, 243, +196, 576, -693, 188, -537, -431, 334, -542, +634, 38, 22, 538, -534, 381, -215, -264, +333, -552, 289, -77, -175, 487, -329, 340, +52, -313, 293, -502, 98, 1, -191, 554, +-167, 345, 107, -289, 127, -591, -55, -165, +-110, 502, 42, 460, 168, -131, 13, -530, +-139, -131, -86, 476, 40, 272, 66, -363, +-4, -573, 31, 164, 109, 784, -4, 283, +-187, -583, -183, -741, 106, 143, 280, 745, +27, 269, -197, -455, -123, -514, 126, 269, +114, 632, -146, 20, -159, -700, 51, -549, +243, 523, 123, 908, -193, 97, -240, -820, +-44, -654, 210, 389, 193, 689, -64, 48, +-174, -510, -119, -228, 123, 413, 188, 323, +-32, -248, -192, -541, -129, -63, 247, 558, +220, 460, -188, -222, -326, -662, 32, -182, +451, 484, 127, 469, -351, -168, -346, -515, +103, -97, 455, 325, 152, 321, -263, -139, +-350, -337, 57, -68, 344, 238, 59, 269, +-247, -163, -208, -306, 186, -38, 291, 302, +1, 277, -292, -198, -255, -354, 140, -96, +284, 289, 101, 315, -196, -111, -194, -291, +52, -129, 165, 226, 72, 276, -203, -89, +-195, -346, 91, -205, 369, 289, 187, 496, +-322, -1, -462, -497, -52, -387, 479, 240, +383, 513, -183, 55, -481, -338, -95, -233, +430, 195, 228, 283, -351, -137, -415, -332, +241, -42, 615, 420, 95, 336, -604, -319, +-534, -526, 292, -70, 698, 553, 178, 399, +-542, -283, -503, -506, 252, -114, 564, 435, +98, 326, -559, -187, -396, -414, 407, -67, +621, 427, -23, 253, -724, -294, -374, -474, +458, 50, 605, 542, -37, 287, -603, -322, +-226, -514, 395, -41, 340, 405, -240, 291, +-425, -169, 152, -292, 459, 33, 71, 238, +-409, -21, -320, -281, 192, -75, 362, 259, +144, 265, -202, -96, -291, -274, -25, -162, +211, 99, 186, 257, -78, 72, -159, -154, +-58, -175, 43, 84, 121, 203, 87, -27, +-67, -126, -192, -104, -38, 33, 163, 91, +113, 96, -52, 80, -94, -140, -27, -160, +14, -17, 43, 121, 43, 140, -62, -31, +-126, -65, 32, -109, 243, -5, 90, 195, +-278, 59, -269, -175, 104, -258, 298, 148, +94, 391, -133, 37, -173, -351, -55, -278, +128, 198, 115, 360, -134, 7, -187, -305, +185, -218, 348, 227, -115, 401, -489, -43, +-106, -520, 435, -295, 294, 475, -207, 619, +-317, -216, -2, -739, 227, -144, 124, 683, +-143, 412, -215, -490, 47, -557, 305, 229, +97, 608, -267, 41, -268, -499, 71, -265, +330, 244, 181, 317, -172, 46, -349, -193, +-75, -219, 330, -12, 232, 224, -185, 229, +-286, -190, 44, -324, 272, 67, 20, 387, +-239, 118, -130, -401, 158, -247, 255, 216, +-39, 314, -274, 12, -169, -220, 206, -85, +317, -15, -95, -1, -360, 123, -88, 137, +337, -26, 259, -254, -179, -13, -356, 272, +-95, 10, 278, -366, 327, -106, -74, 547, +-380, 366, -114, -572, 304, -642, 248, 291, +-241, 869, -332, -12, 151, -847, 394, -273, +64, 737, -404, 588, -250, -583, 236, -792, +285, 237, 9, 863, -215, 147, -85, -796, +84, -365, 53, 609, 12, 539, -88, -449, +-21, -711, 79, 259, 66, 754, -6, 45, +-113, -684, -78, -241, 3, 487, 103, 283, +174, -329, -48, -234, -289, 227, -117, 218, +273, -195, 307, -137, -214, 178, -409, 60, +43, -260, 433, -113, 196, 421, -438, 335, +-366, -435, 296, -650, 477, 197, -107, 936, +-476, 164, 3, -1010, 351, -613, 54, 911, +-239, 1029, -28, -678, 176, -1334, 29, 318, +-141, 1552, -63, 107, 115, -1644, 42, -618, +-51, 1561, -3, 1141, 94, -1211, -11, -1542, +-235, 646, -45, 1678, 236, -58, 243, -1522, +-121, -431, -392, 1228, -70, 761, 291, -845, +303, -976, -167, 440, -382, 1019, 28, -48, +304, -901, 127, -285, -268, 757, -188, 420, +159, -512, 210, -561, 23, 275, -195, 639, +-163, -81, 22, -485, 200, -200, 182, 371, +-105, 315, -284, -230, -82, -301, 262, -9, +234, 416, -167, 89, -285, -394, 116, -294, +334, 305, -75, 519, -369, -198, -35, -561, +366, -21, 192, 559, -244, 136, -237, -526, +8, -207, 198, 528, 89, 367, -100, -478, +-46, -566, 7, 222, 15, 707, -88, 76, +27, -562, 149, -328, -14, 325, -122, 408, +-103, -227, 129, -348, 106, 115, -114, 474, +-152, -15, 69, -554, 297, -196, -35, 439, +-381, 442, -167, -294, 365, -467, 378, 102, +-230, 479, -410, 34, 31, -536, 375, -203, +-35, 507, -337, 517, 84, -348, 409, -741, +13, -13, -495, 786, -108, 373, 341, -658, +173, -603, -179, 436, -72, 784, 171, -245, +-92, -846, -200, -6, 51, 872, 213, 303, +-36, -782, -150, -501, 131, 495, 98, 672, +-233, -216, -219, -630, 235, -47, 313, 454, +-136, 297, -321, -283, 51, -332, 247, 6, +-20, 254, -207, 198, -28, -132, 197, -171, +93, -91, -84, 133, -230, 163, -104, -74, +296, -178, 304, -47, -196, 298, -540, 146, +82, -297, 641, -335, 106, 152, -669, 470, +-379, 16, 701, -410, 593, -177, -518, 350, +-824, 282, 258, -297, 893, -426, -51, 99, +-681, 580, -139, 204, 573, -462, 112, -511, +-472, 172, -114, 554, 310, 65, 264, -375, +-209, -156, -165, 303, -23, 125, -34, -297, +77, -153, 155, 192, 159, 282, -253, -32, +-289, -218, 107, -185, 321, 27, 61, 328, +-356, 131, -105, -303, 312, -287, 213, 303, +-296, 386, -409, -316, 205, -464, 538, 279, +45, 616, -601, -191, -317, -711, 523, -5, +523, 685, -359, 252, -682, -566, 181, -360, +744, 322, 103, 431, -734, -113, -431, -439, +570, -88, 667, 323, -183, 346, -788, -121, +-170, -459, 700, -187, 406, 322, -488, 500, +-609, -61, 320, -551, 722, -311, -98, 384, +-726, 631, -234, -96, 673, -718, 471, -314, +-471, 637, -601, 676, 127, -401, 684, -910, +167, 23, -545, 1008, -419, 458, 260, -918, +574, -974, -49, 514, -523, 1296, -147, 159, +489, -1289, 297, -748, -465, 975, -460, 1077, +284, -530, 590, -1316, -73, 155, -463, 1372, +-91, 378, 283, -1163, 48, -916, -253, 663, +40, 1005, 238, 14, 115, -756, -202, -351, +-194, 365, 44, 399, 36, -58, 60, -470, +81, -150, 133, 393, -84, 519, -292, -133, +-32, -702, 218, -298, 137, 463, -152, 659, +-119, -116, 162, -629, 138, -206, -143, 522, +-197, 453, -31, -477, 138, -694, 125, 246, +90, 1010, -8, 193, -269, -1076, -147, -693, +141, 799, 253, 1003, -36, -377, -212, -1065, +83, 30, 181, 963, -40, 241, -388, -784, +-108, -537, 457, 574, 418, 702, -291, -152, +-678, -754, 50, -282, 648, 597, 199, 565, +-617, -197, -319, -745, 575, -141, 416, 660, +-391, 461, -616, -413, 191, -731, 546, 147, +80, 712, -296, 273, -308, -527, 135, -553, +228, 220, 152, 526, -186, 185, -410, -441, +113, -424, 494, 251, 282, 600, -612, 126, +-567, -742, 429, -577, 730, 559, -61, 951, +-842, -1, -148, -1109, 724, -524, 476, 878, +-600, 932, -786, -451, 318, -1291, 921, 6, +165, 1402, -891, 704, -489, -1190, 532, -1438, +665, 593, -161, 1719, -653, 308, -133, -1551, +427, -1023, 420, 1061, -164, 1398, -499, -392, +-162, -1601, 325, -297, 455, 1480, -88, 1039, +-513, -1007, -220, -1572, 400, 278, 530, 1671, +-229, 532, -721, -1412, -135, -1093, 730, 874, +605, 1360, -544, -199, -868, -1355, 121, -386, +918, 988, 303, 781, -795, -398, -575, -922, +521, -116, 774, 684, -140, 524, -838, -299, +-289, -738, 673, -52, 669, 644, -250, 413, +-857, -454, -255, -633, 756, 208, 630, 636, +-364, 145, -852, -545, -46, -399, 795, 308, +405, 435, -522, 10, -730, -361, 205, -145, +838, 183, 217, 128, -746, 7, -686, -81, +443, -123, 948, -105, 97, 177, -912, 425, +-665, -58, 632, -672, 976, -354, -185, 665, +-1069, 798, -269, -375, 1031, -996, 656, -76, +-728, 986, -1027, 437, 274, -873, 1169, -749, +285, 613, -976, 1071, -801, -152, 646, -1186, +971, -397, -164, 908, -995, 844, -238, -431, +857, -966, 510, -2, -454, 828, -776, 404, +44, -683, 687, -689, 407, 380, -321, 899, +-715, 139, -81, -962, 610, -601, 527, 606, +-378, 941, -761, -134, 78, -993, 795, -231, +269, 755, -761, 559, -570, -550, 519, -685, +800, 251, -131, 743, -846, 140, -333, -723, +638, -410, 715, 405, -271, 671, -903, -74, +-215, -696, 883, -241, 696, 479, -592, 597, +-1031, -252, 74, -700, 1077, -140, 465, 634, +-817, 582, -848, -468, 423, -781, 1016, 39, +81, 874, -1052, 421, -563, -816, 828, -755, +969, 406, -298, 1047, -1174, 120, -229, -1048, +962, -590, 673, 634, -512, 948, -971, -186, +81, -1024, 929, -199, 508, 894, -704, 651, +-1035, -739, 219, -998, 1159, 342, 503, 1161, +-980, 279, -1052, -1023, 477, -738, 1252, 526, +251, 892, -1232, 25, -885, -789, 837, -448, +1380, 473, -149, 752, -1587, 3, -596, -827, +1312, -549, 1235, 578, -764, 951, -1585, -66, +76, -1030, 1634, -444, 687, 817, -1420, 780, +-1290, -492, 817, -949, 1673, 105, -60, 1025, +-1651, 344, -601, -906, 1208, -771, 1136, 506, +-642, 1039, -1330, -27, 23, -1003, 1164, -393, +646, 749, -813, 693, -971, -485, 192, -823, +957, 129, 467, 843, -740, 292, -808, -707, +234, -579, 987, 292, 265, 678, -1004, 112, +-646, -497, 687, -313, 1054, 181, -290, 381, +-1184, 0, -243, -339, 956, -139, 758, 277, +-574, 346, -921, -182, 43, -445, 856, -93, +384, 403, -646, 363, -590, -208, 234, -438, +701, -121, 171, 421, -560, 412, -496, -220, +143, -627, 694, -175, 223, 686, -540, 609, +-545, -412, 262, -936, 790, -43, 16, 962, +-783, 486, -508, -773, 681, -833, 967, 493, +-297, 1020, -1159, -68, -395, -1127, 1136, -374, +914, 1024, -716, 779, -1288, -673, 92, -1158, +1435, 279, 511, 1259, -1161, 295, -1135, -1110, +631, -867, 1439, 748, 6, 1098, -1382, -128, +-674, -1082, 1139, -341, 1162, 867, -645, 606, +-1485, -515, -88, -857, 1495, 120, 846, 863, +-1017, 380, -1351, -525, 295, -721, 1449, 10, +353, 598, -1257, 433, -829, -309, 904, -551, +1261, 45, -385, 611, -1489, 199, -327, -747, +1246, -545, 1063, 615, -661, 1035, -1312, -160, +-108, -1210, 1113, -425, 735, 920, -789, 876, +-1012, -489, 274, -989, 1215, 37, 275, 940, +-1230, 397, -806, -793, 817, -746, 1300, 428, +-251, 973, -1379, 29, -356, -964, 1083, -484, +840, 716, -680, 828, -986, -292, 149, -981, +948, -232, 327, 869, -729, 700, -652, -487, +286, -992, 826, 6, 144, 991, -683, 490, +-495, -798, 383, -883, 666, 435, -83, 1067, +-603, 100, -231, -1065, 499, -540, 420, 720, +-239, 821, -485, -241, -68, -875, 406, -130, +272, 585, -152, 455, -365, -276, -61, -519, +326, -28, 229, 347, -259, 328, -380, -180, +175, -356, 481, -106, -22, 286, -565, 332, +-100, -130, 536, -345, 233, -140, -505, 267, +-363, 248, 408, -68, 452, -188, -206, -91, +-478, 76, 16, 102, 376, 59, 83, -98, +-249, -175, -127, 50, 202, 283, 146, 135, +-117, -323, -205, -356, -33, 174, 175, 466, +168, 88, -31, -421, -192, -247, -83, 269, +98, 304, 98, -99, -15, -341, -68, -18, +1, 256, 32, 164, 45, -82, -25, -205, +-60, -81, -48, 14, 56, 190, 133, 183, +-4, -91, -148, -297, -120, -119, 172, 315, +192, 244, -114, -189, -256, -319, 0, 16, +337, 297, 80, 91, -261, -165, -225, -143, +133, 31, 301, 129, 11, 41, -197, -42, +-235, -119, 56, -51, 295, 167, 145, 169, +-173, -103, -347, -365, 30, -27, 345, 433, +204, 255, -255, -334, -412, -483, 99, 158, +450, 504, 173, 140, -399, -381, -345, -329, +190, 159, 390, 288, -10, 116, -332, -166, +-85, -190, 277, -6, 169, 172, -255, 137, +-232, -196, 102, -225, 315, 152, 83, 392, +-228, -10, -233, -480, -23, -196, 303, 387, +190, 350, -147, -211, -348, -384, -25, 72, +380, 373, 205, 54, -283, -345, -422, -240, +171, 237, 507, 373, 67, 4, -567, -329, +-328, -222, 510, 182, 532, 260, -279, -8, +-750, -233, 55, -64, 778, 229, 229, 124, +-745, -185, -561, -273, 679, 100, 843, 341, +-343, 92, -1109, -289, -157, -302, 1111, 163, +666, 351, -731, 73, -1052, -330, 244, -264, +1104, 246, 262, 320, -961, -34, -668, -384, +694, -91, 941, 339, -276, 150, -1075, -201, +-176, -263, 955, 183, 645, 236, -666, -119, +-936, -214, 226, -3, 1011, 275, 289, 22, +-873, -201, -665, -109, 444, 139, 834, 231, +31, -110, -770, -240, -387, -28, 476, 278, +643, 152, -151, -263, -701, -189, -233, 171, +517, 242, 596, -156, -176, -268, -693, 144, +-283, 318, 540, -36, 635, -369, -269, -88, +-749, 300, -121, 170, 741, -164, 458, -193, +-547, 123, -690, 180, 154, -101, 788, -239, +227, -10, -603, 330, -525, 151, 246, -255, +667, -316, 95, 103, -528, 400, -422, 19, +265, -360, 572, -200, 42, 322, -516, 374, +-322, -221, 380, -457, 500, -38, -185, 504, +-561, 232, -90, -420, 522, -375, 358, 221, +-321, 533, -500, -21, 15, -519, 488, -255, +222, 339, -376, 488, -368, -79, 195, -480, +472, -204, 2, 382, -489, 419, -235, -263, +366, -553, 439, 8, -188, 662, -484, 310, +-34, -583, 450, -564, 227, 286, -353, 691, +-364, -3, 109, -652, 469, -210, 119, 523, +-370, 461, -313, -360, 176, -642, 428, 54, +-48, 633, -390, 318, -167, -474, 363, -482, +406, 200, -214, 474, -507, 34, -167, -453, +470, -150, 442, 361, -195, 313, -510, -187, +-163, -460, 481, -27, 393, 378, -293, 252, +-593, -203, 27, -340, 709, 72, 288, 285, +-643, 75, -599, -269, 388, -170, 787, 226, +-49, 237, -808, -70, -323, -299, 648, -42, +664, 259, -331, 111, -857, -193, -88, -227, +832, 184, 492, 317, -612, -53, -768, -383, +249, -180, 896, 364, 150, 318, -830, -169, +-570, -398, 576, 37, 891, 444, -190, 62, +-951, -473, -317, -331, 810, 450, 710, 621, +-421, -159, -865, -711, -126, -285, 789, 557, +497, 493, -389, -232, -665, -515, -17, -28, +590, 507, 293, 204, -354, -391, -515, -458, +122, 137, 600, 585, 175, 210, -554, -375, +-493, -455, 388, 58, 664, 403, -50, 139, +-740, -208, -290, -247, 642, 90, 612, 286, +-365, 103, -859, -241, -7, -388, 857, 31, +420, 461, -678, 348, -684, -277, 386, -591, +827, -18, -51, 551, -876, 347, -326, -454, +711, -580, 706, 260, -359, 745, -838, 142, +-106, -799, 701, -529, 457, 520, -452, 766, +-573, -94, 139, -795, 645, -198, 134, 618, +-611, 468, -435, -413, 381, -681, 700, 157, +-23, 722, -702, 216, -388, -664, 471, -491, +669, 487, -110, 650, -694, -216, -271, -811, +512, -82, 503, 807, -181, 456, -524, -560, +-155, -751, 373, 170, 405, 752, -134, 206, +-532, -560, -156, -436, 546, 352, 445, 514, +-389, -141, -681, -524, 91, -79, 750, 470, +302, 215, -609, -318, -623, -281, 294, 138, +780, 262, 115, -19, -714, -124, -461, -70, +433, -48, 660, 9, -38, 167, -658, 203, +-325, -176, 464, -357, 605, -1, -175, 431, +-734, 202, -170, -420, 697, -360, 528, 287, +-488, 560, -763, -91, 116, -661, 845, -225, +279, 565, -716, 556, -607, -320, 405, -698, +835, -35, -26, 677, -805, 349, -387, -551, +593, -592, 668, 301, -272, 767, -726, 45, +-103, -787, 672, -420, 353, 601, -458, 702, +-528, -241, 172, -817, 557, -138, 91, 709, +-393, 488, -336, -431, 184, -724, 395, 88, +95, 718, -338, 320, -344, -566, 222, -618, +429, 283, 32, 710, -481, 136, -230, -691, +417, -452, 410, 436, -226, 650, -565, -68, +13, -759, 540, -239, 266, 608, -350, 599, +-434, -327, 54, -820, 386, -55, 218, 729, +-227, 503, -308, -471, 22, -701, 327, 90, +112, 662, -285, 295, -251, -539, 177, -528, +406, 253, -17, 677, -432, 134, -214, -666, +342, -473, 375, 373, -136, 678, -390, 12, +-127, -667, 290, -321, 289, 456, -55, 576, +-385, -154, -156, -713, 339, -215, 319, 601, +-184, 610, -438, -307, 63, -800, 418, -97, +120, 715, -367, 501, -288, -501, 266, -707, +328, 151, -53, 770, -349, 283, -88, -686, +275, -600, 149, 333, -136, 789, -217, 89, +79, -772, 223, -403, 7, 517, -199, 659, +-143, -242, 163, -752, 222, -71, -5, 661, +-226, 420, -162, -491, 128, -618, 232, 170, +63, 669, -230, 181, -178, -618, 170, -432, +270, 382, -90, 620, -373, -84, -41, -660, +385, -193, 264, 505, -259, 449, -449, -266, +-4, -522, 430, -4, 253, 447, -326, 263, +-363, -281, 194, -372, 412, 35, -77, 359, +-473, 202, -75, -242, 469, -323, 279, 21, +-341, 330, -430, 172, 150, -246, 471, -272, +78, 95, -412, 323, -302, 23, 263, -350, +471, -149, 14, 306, -491, 336, -296, -193, +371, -465, 427, -25, -172, 440, -472, 285, +-8, -297, 478, -392, 186, 84, -374, 379, +-420, 91, 167, -349, 535, -187, 121, 249, +-439, 312, -396, -95, 260, -368, 467, -89, +-32, 258, -464, 286, -197, -64, 402, -314, +368, -145, -207, 217, -516, 320, -68, -97, +515, -377, 306, -59, -343, 414, -475, 257, +119, -393, 493, -448, 70, 220, -382, 600, +-221, 57, 270, -573, 292, -335, -144, 349, +-318, 470, 5, -77, 318, -412, 132, -131, +-241, 279, -234, 237, 67, -122, 270, -283, +116, -58, -180, 253, -261, 233, -15, -96, +336, -328, 234, -95, -245, 263, -449, 236, +31, -142, 554, -294, 201, 50, -487, 305, +-403, 93, 374, -320, 517, -277, -231, 195, +-586, 432, 16, 90, 602, -454, 230, -364, +-436, 261, -407, 548, 154, -14, 406, -600, +71, -204, -257, 553, -221, 447, 111, -468, +289, -645, 68, 261, -292, 775, -279, 44, +166, -800, 410, -335, 77, 632, -348, 594, +-273, -381, 191, -746, 340, 80, -16, 718, +-336, 252, -130, -612, 300, -502, 281, 391, +-174, 651, -355, -64, -13, -715, 310, -275, +151, 558, -211, 571, -187, -216, 107, -686, +230, -134, -19, 560, -278, 414, -129, -335, +209, -563, 305, 93, -30, 605, -324, 195, +-171, -565, 184, -503, 297, 348, -25, 719, +-295, 24, -133, -730, 259, -394, 291, 527, +-175, 619, -402, -230, -29, -695, 448, -51, +237, 664, -337, 325, -401, -511, 131, -568, +469, 236, 60, 637, -377, 98, -236, -518, +253, -334, 314, 310, -106, 401, -292, -106, +-54, -424, 250, -55, 162, 400, -149, 223, +-209, -273, 0, -365, 215, 89, 87, 338, +-130, 84, -137, -197, 27, -135, 131, 94, +41, 88, -67, -14, -103, -61, -25, -56, +134, -5, 112, 106, -90, 153, -190, -76, +37, -266, 225, -65, -5, 275, -248, 200, +-74, -202, 292, -251, 195, 112, -222, 257, +-307, -44, 46, -259, 324, -25, 106, 222, +-198, 76, -170, -166, 75, -93, 170, 136, +-19, 109, -146, -98, -70, -140, 132, 13, +174, 139, -63, 54, -217, -53, -89, -62, +222, 14, 184, 36, -145, -55, -254, -56, +38, 40, 295, 162, 66, 45, -247, -175, +-174, -150, 158, 70, 223, 197, -64, -28, +-205, -166, -18, 7, 191, 193, 111, 45, +-149, -254, -195, -132, 11, 196, 227, 231, +155, -99, -136, -237, -249, 33, -26, 198, +244, 34, 152, -205, -189, -90, -223, 160, +125, 143, 302, -58, -34, -169, -342, -11, +-108, 122, 297, 69, 240, -71, -181, -116, +-296, 38, 22, 145, 262, 57, 116, -158, +-175, -153, -190, 119, 39, 215, 195, -22, +92, -253, -128, -73, -175, 233, 6, 147, +204, -156, 115, -181, -162, 106, -221, 168, +54, -102, 282, -195, 82, 79, -235, 274, +-201, 21, 115, -268, 235, -160, 7, 152, +-212, 202, -83, -38, 174, -136, 149, 2, +-133, 113, -214, 6, 41, -147, 242, -94, +86, 112, -183, 215, -185, 28, 77, -221, +214, -182, 32, 122, -198, 248, -123, -32, +154, -251, 191, -41, -44, 291, -228, 156, +-93, -308, 164, -330, 178, 199, -24, 490, +-176, 31, -62, -525, 107, -292, 79, 401, +-56, 487, -79, -188, 50, -577, 96, -23, +-24, 573, -129, 243, -51, -518, 112, -457, +121, 381, -30, 620, -128, -118, -50, -682, +80, -176, 82, 576, -35, 386, -83, -352, +9, -494, 81, 158, 21, 500, -59, 36, +-50, -465, 8, -250, 31, 356, 48, 408, +18, -106, -57, -444, -53, -145, 41, 321, +69, 277, -56, -137, -77, -323, 74, -2, +127, 320, -64, 146, -186, -273, -3, -302, +197, 157, 90, 398, -166, 41, -150, -388, +111, -234, 189, 276, -36, 343, -207, -108, +-42, -356, 149, -45, 107, 304, -75, 155, +-113, -211, 27, -232, 75, 93, 13, 278, +-80, 68, -29, -237, 69, -245, 39, 73, +-14, 323, -33, 161, -3, -209, -42, -314, +-20, -7, 81, 278, 85, 164, -37, -136, +-137, -200, -26, 37, 116, 198, 63, 54, +-110, -193, -97, -192, 134, 111, 166, 306, +-100, 101, -246, -289, -3, -303, 242, 123, +115, 364, -159, 65, -156, -331, 85, -173, +170, 279, -36, 263, -206, -219, -44, -396, +230, 84, 184, 465, -160, 141, -287, -393, +10, -338, 279, 214, 118, 390, -205, -8, +-165, -332, 114, -119, 179, 245, -44, 171, +-194, -127, -44, -200, 152, 30, 146, 189, +-75, 66, -184, -108, -18, -158, 182, -8, +101, 152, -179, 132, -160, -50, 136, -196, +232, -45, -66, 142, -266, 105, -12, -82, +238, -103, 85, 86, -219, 86, -127, -86, +205, -141, 193, 62, -139, 172, -263, -30, +41, -149, 256, 5, 71, 169, -180, -11, +-142, -234, 83, -29, 145, 277, 12, 175, +-136, -258, -103, -282, 88, 166, 173, 328, +5, -56, -193, -370, -129, -14, 134, 396, +206, 149, -24, -372, -221, -322, -82, 270, +175, 414, 135, -72, -108, -417, -159, -94, +41, 364, 172, 192, 43, -271, -146, -299, +-148, 158, 83, 352, 214, -17, 48, -309, +-187, -129, -153, 222, 85, 174, 173, -137, +26, -166, -128, 60, -74, 187, 76, -2, +90, -170, -23, -93, -106, 84, -19, 159, +80, 16, 70, -111, -12, -104, -80, 51, +-65, 131, 11, -16, 122, -120, 79, -37, +-126, 146, -176, 79, 60, -122, 265, -109, +38, 57, -278, 127, -165, -45, 226, -106, +268, 23, -123, 97, -308, 28, -11, -93, +306, -54, 155, 13, -225, 41, -277, 41, +58, 3, 310, -7, 133, -32, -227, -5, +-253, -8, 87, -20, 263, 22, 37, 36, +-230, 31, -106, -31, 186, -33, 178, -4, +-106, -14, -258, 7, -25, 36, 234, 56, +164, -24, -130, -62, -202, 2, 35, 20, +154, -15, 21, -52, -125, 49, -32, 98, +122, -1, 67, -85, -92, -70, -121, 21, +40, 14, 113, 21, 28, 71, -59, 44, +-38, -51, 6, -130, -1, -38, 10, 78, +36, 85, 12, 29, -44, -45, -25, -36, +50, -19, 21, 11, -71, -2, -44, -39, +86, 27, 92, 90, -58, 71, -127, -82, +0, -144, 99, -21, 41, 85, -47, 91, +-34, 9, 30, -11, 24, -37, -31, -61, +-62, -10, -13, 42, 96, 56, 87, -24, +-47, -22, -151, 35, -21, 23, 123, -32, +53, -80, -74, 15, -61, 87, 74, 47, +59, -61, -63, -100, -83, 27, 24, 121, +115, 56, 16, -131, -105, -162, -77, 52, +88, 211, 127, 100, -43, -149, -155, -167, +-33, 29, 135, 131, 63, 33, -86, -92, +-52, -22, 69, 93, 32, 64, -93, -64, +-31, -136, 83, -22, 45, 97, -62, 110, +-20, 4, 78, -100, 3, -48, -114, 30, +-48, 61, 113, -37, 104, -86, -61, 34, +-98, 137, 16, 83, 63, -155, -13, -190, +-51, 33, 21, 211, 53, 101, 7, -177, +-21, -138, -26, 112, -23, 185, -8, -74, +42, -250, 52, 0, -13, 252, -60, 142, +-36, -197, 44, -213, 61, 92, -4, 211, +-83, 13, -60, -185, 71, -59, 119, 133, +-13, 104, -157, -69, -63, -134, 144, 15, +124, 124, -101, 50, -168, -107, 66, -109, +204, 62, 0, 132, -213, -1, -75, -135, +195, -55, 161, 102, -124, 78, -223, -62, +4, -95, 242, 25, 131, 98, -174, 26, +-232, -58, 52, -70, 261, -20, 64, 46, +-222, 84, -147, 35, 159, -85, 217, -84, +-90, 39, -265, 100, -42, -1, 267, -101, +182, -11, -186, 86, -267, 54, 39, -61, +275, -68, 85, 16, -218, 30, -166, 10, +134, -16, 246, 1, -22, 5, -255, -7, +-113, 2, 192, -20, 221, -18, -81, 9, +-245, 45, -37, 26, 228, -45, 142, -57, +-183, -6, -229, 64, 100, 54, 294, -16, +24, -77, -307, -61, -161, 46, 245, 111, +281, 42, -117, -107, -353, -119, -37, 43, +336, 140, 211, 18, -246, -138, -316, -63, +115, 134, 345, 110, 32, -109, -334, -178, +-140, 39, 268, 214, 239, 46, -152, -181, +-313, -118, 20, 137, 293, 159, 122, -99, +-188, -190, -213, 16, 70, 204, 212, 60, +68, -157, -154, -94, -183, 79, 64, 91, +219, -60, 73, -49, -211, 62, -206, 33, +149, -60, 270, -22, -9, 88, -299, -17, +-115, -134, 263, -5, 209, 183, -162, 78, +-295, -184, 56, -116, 303, 152, 66, 153, +-261, -130, -206, -195, 174, 84, 285, 222, +-4, 34, -302, -187, -167, -113, 213, 86, +258, 120, -59, -15, -282, -108, -48, -16, +243, 134, 131, 97, -174, -143, -214, -230, +97, 34, 240, 302, 32, 131, -208, -234, +-149, -223, 109, 135, 184, 251, 2, -63, +-162, -287, -90, -54, 123, 299, 149, 244, +-40, -175, -183, -380, -70, -87, 159, 344, +151, 295, -62, -162, -181, -367, -25, -15, +158, 347, 92, 123, -93, -313, -139, -251, +47, 227, 165, 356, 36, -80, -162, -360, +-125, -85, 118, 289, 175, 174, -39, -187, +-194, -213, -40, 87, 174, 242, 108, 19, +-118, -196, -153, -129, 26, 93, 133, 163, +65, 1, -49, -111, -87, -58, -38, 72, +55, 66, 82, -58, -6, -80, -84, 4, +-26, 104, 89, 51, 56, -61, -68, -91, +-120, -5, 5, 104, 149, 45, 92, -89, +-98, -97, -169, 60, 9, 166, 169, -8, +90, -185, -101, -100, -154, 135, 28, 160, +152, -60, 59, -140, -131, 8, -131, 138, +77, 16, 153, -138, 15, -68, -157, 96, +-103, 123, 126, -10, 177, -96, -33, -58, +-224, -11, -58, 31, 209, 70, 141, 56, +-138, -52, -211, -100, 61, 24, 226, 110, +26, -7, -209, -150, -134, -35, 179, 198, +200, 149, -88, -153, -242, -269, -26, 16, +231, 295, 102, 134, -150, -210, -162, -237, +74, 116, 176, 262, -9, -15, -159, -279, +-56, -103, 151, 270, 111, 218, -115, -170, +-159, -321, 36, 17, 194, 338, 46, 134, +-166, -249, -122, -250, 94, 135, 162, 284, +-40, -5, -148, -252, -19, -115, 129, 197, +81, 174, -116, -99, -112, -207, 52, -6, +162, 198, 21, 79, -162, -141, -84, -140, +95, 77, 156, 172, -32, -17, -159, -160, +-57, -71, 123, 146, 148, 138, -63, -95, +-167, -181, -34, -18, 161, 191, 89, 113, +-119, -101, -89, -161, 52, -19, 93, 120, +-36, 79, -57, -32, 15, -65, 10, -7, +2, 49, -4, 14, 50, -65, -26, -75, +-72, 51, 15, 158, 91, 69, 30, -150, +-121, -204, -59, 11, 82, 230, 121, 125, +-17, -140, -136, -176, -44, 53, 85, 166, +114, -14, -38, -169, -121, -72, -28, 159, +125, 182, 92, -22, -137, -218, -141, -166, +79, 118, 190, 271, -13, 66, -175, -268, +-41, -214, 135, 178, 97, 302, -111, -55, +-126, -367, 67, -73, 165, 356, 6, 229, +-191, -301, -68, -370, 154, 200, 129, 479, +-120, -5, -160, -537, 86, -256, 177, 441, +-29, 466, -197, -178, -24, -533, 195, -72, +101, 428, -160, 204, -162, -313, 107, -300, +196, 239, -14, 405, -195, -72, -70, -460, +129, -175, 116, 344, -49, 325, -105, -110, +-5, -283, 60, -35, 26, 171, -27, 55, +-51, -113, -3, -75, 66, 71, 57, 130, +-43, 39, -103, -116, -11, -166, 87, -25, +76, 212, -36, 161, -104, -111, -8, -257, +96, -15, 53, 271, -70, 119, -72, -220, +18, -235, 64, 136, 54, 302, -26, -14, +-90, -281, -55, -126, 90, 234, 111, 209, +-62, -115, -127, -263, 3, -31, 104, 260, +56, 167, -48, -143, -94, -253, -51, -3, +128, 239, 125, 107, -104, -166, -195, -184, +64, 99, 239, 234, -5, 3, -227, -245, +-95, -153, 186, 184, 176, 231, -91, -25, +-203, -228, -22, -105, 200, 136, 94, 145, +-133, -26, -138, -162, 74, -36, 123, 150, +-29, 105, -77, -96, 2, -176, 37, 26, +0, 157, 11, 72, -16, -85, -45, -129, +30, 0, 84, 115, -6, 91, -113, -110, +-32, -152, 86, 88, 72, 214, -24, -22, +-87, -264, -23, -77, 46, 241, 104, 149, +-16, -134, -132, -192, -42, 33, 150, 152, +114, 47, -152, -93, -163, -115, 104, 53, +219, 161, -46, 40, -267, -186, -16, -159, +257, 139, 116, 235, -223, -26, -158, -255, +120, -72, 188, 214, -8, 133, -188, -150, +-105, -192, 154, 86, 218, 210, -104, 37, +-288, -184, 18, -130, 293, 90, 63, 169, +-257, 24, -109, -162, 195, -110, 151, 103, +-109, 177, -173, -23, 17, -217, 161, -83, +94, 177, -129, 173, -152, -100, 52, -178, +169, 59, -1, 155, -146, -51, -37, -171, +89, 58, 57, 192, -43, -15, -56, -165, +5, -6, 21, 125, 30, -24, -19, -107, +-18, 46, -20, 122, 36, -36, 35, -117, +-23, 36, -52, 106, -29, -60, 67, -156, +99, 35, -2, 210, -160, 37, -80, -189, +181, -119, 139, 152, -147, 105, -195, -100, +116, -121, 210, 112, -66, 155, -202, -71, +-9, -164, 177, -13, 57, 131, -109, 56, +-100, -70, 27, -45, 115, 8, 65, 58, +-75, 22, -144, -19, -14, -96, 173, -72, +116, 110, -122, 203, -221, 18, 48, -282, +257, -196, 66, 215, -257, 353, -159, -78, +202, -450, 242, -102, -101, 494, -287, 318, +-28, -433, 270, -531, 134, 282, -196, 637, +-198, -78, 103, -669, 211, -93, 6, 643, +-182, 297, -111, -574, 122, -536, 196, 354, +-24, 696, -222, -4, -81, -688, 207, -298, +132, 527, -136, 474, -128, -366, 83, -597, +89, 225, -61, 689, -14, -9, 44, -718, +-26, -235, -60, 623, 48, 390, 80, -446, +-27, -464, -93, 350, -33, 481, 99, -269, +103, -528, -86, 183, -171, 559, 50, -92, +228, -534, 11, 20, -240, 513, -101, 13, +219, -514, 194, -88, -131, 527, -265, 213, +14, -500, 276, -357, 110, 388, -205, 515, +-185, -230, 117, -626, 192, -3, -17, 632, +-137, 284, -64, -550, 95, -485, 115, 324, +-11, 615, -160, -76, -63, -630, 175, -181, +126, 520, -105, 436, -184, -312, 25, -583, +173, 13, 87, 585, -109, 302, -183, -460, +64, -515, 204, 208, 31, 654, -210, 64, +-78, -667, 181, -340, 107, 546, -106, 611, +-159, -330, 49, -724, 171, 9, 52, 695, +-138, 305, -147, -560, 106, -488, 187, 275, +-16, 649, -202, 4, -56, -660, 200, -295, +126, 511, -122, 591, -212, -307, 40, -685, +245, 3, 92, 655, -200, 281, -188, -571, +142, -446, 236, 319, -16, 620, -255, -37, +-74, -651, 236, -271, 184, 464, -133, 577, +-271, -194, 23, -655, 270, -150, 181, 567, +-184, 443, -322, -403, 49, -598, 404, 117, +156, 672, -404, 191, -323, -581, 327, -440, +461, 314, -146, 592, -525, -17, -18, -555, +510, -277, 212, 388, -396, 515, -332, -138, +256, -597, 398, -208, -45, 515, -354, 504, +-138, -267, 254, -635, 282, -79, -36, 623, +-336, 381, -160, -473, 326, -643, 349, 185, +-197, 808, -452, 199, 64, -734, 484, -569, +96, 452, -396, 763, -202, -95, 309, -735, +290, -229, -154, 586, -264, 468, 7, -357, +229, -634, 100, 35, -63, 649, -134, 336, +-89, -495, 145, -601, 252, 173, -7, 696, +-372, 175, -137, -629, 443, -452, 341, 414, +-342, 654, -514, -93, 232, -704, 613, -247, +-18, 554, -603, 562, -180, -299, 565, -746, +387, -31, -387, 796, -513, 405, 164, -726, +588, -724, 103, 479, -477, 929, -303, -120, +307, -962, 474, -220, -46, 823, -447, 522, +-178, -557, 350, -775, 387, 166, -118, 849, +-410, 370, -113, -680, 343, -837, 314, 259, +-164, 1062, -348, 314, -43, -1022, 341, -842, +256, 716, -170, 1238, -330, -166, -43, -1409, +363, -495, 273, 1224, -173, 1102, -368, -688, +-68, -1466, 403, -13, 333, 1460, -194, 756, +-520, -1112, -59, -1356, 571, 442, 404, 1627, +-360, 429, -642, -1428, 67, -1215, 712, 773, +375, 1603, -518, 128, -660, -1518, 215, -934, +834, 971, 282, 1463, -758, -133, -657, -1584, +473, -764, 979, 1141, 45, 1507, -1035, -281, +-516, -1755, 799, -749, 999, 1373, -347, 1623, +-1165, -545, -153, -2022, 1072, -508, 718, 1862, +-699, 1547, -964, -1233, 172, -2211, 1013, 168, +457, 2377, -732, 999, -800, -1916, 214, -1901, +994, 907, 360, 2288, -779, 288, -786, -2028, +328, -1287, 1063, 1194, 227, 1879, -920, -132, +-747, -1866, 602, -886, 1139, 1302, -56, 1603, +-1138, -408, -515, -1766, 974, -568, 985, 1365, +-453, 1301, -1142, -586, -126, -1543, 1110, -351, +619, 1268, -687, 1104, -906, -590, 210, -1453, +942, -267, 285, 1318, -619, 999, -630, -759, +253, -1381, 767, 6, 217, 1313, -566, 672, +-555, -821, 319, -1096, 709, 133, 140, 1084, +-606, 540, -497, -667, 374, -982, 739, 50, +28, 996, -764, 561, -380, -626, 649, -972, +649, 94, -318, 980, -699, 488, 31, -664, +618, -913, 273, 127, -327, 929, -354, 527, +72, -570, 364, -968, 196, -71, -196, 945, +-303, 754, 9, -536, 339, -1176, 223, -97, +-256, 1190, -354, 788, 119, -871, 460, -1302, +98, 229, -424, 1479, -216, 540, 350, -1210, +384, -1190, -193, 603, -433, 1458, 93, 158, +481, -1312, 63, -804, -453, 863, -159, 1158, +420, -230, 251, -1183, -339, -398, -309, 903, +260, 791, 373, -357, -132, -880, -393, -177, +15, 657, 415, 488, 199, -208, -308, -570, +-340, -183, 197, 354, 424, 412, 29, 26, +-375, -404, -199, -326, 267, 106, 272, 459, +-45, 276, -293, -351, -134, -551, 213, 18, +258, 690, 27, 351, -339, -587, -209, -683, +283, 263, 440, 849, -25, 175, -567, -716, +-180, -594, 480, 336, 466, 769, -245, 205, +-654, -676, -27, -672, 601, 340, 390, 921, +-449, 190, -661, -949, 176, -707, 700, 664, +237, 1067, -590, -83, -511, -1205, 309, -493, +635, 937, 122, 976, -561, -432, -432, -1230, +320, -128, 624, 1134, 34, 684, -651, -799, +-385, -1071, 419, 305, 637, 1143, -65, 298, +-716, -960, -402, -739, 544, 514, 775, 934, +-178, 49, -920, -847, -305, -494, 830, 478, +745, 743, -491, -3, -979, -721, -22, -412, +1013, 433, 486, 681, -805, -42, -881, -695, +330, -348, 1074, 475, 91, 644, -1006, -108, +-536, -708, 686, -314, 816, 515, -322, 634, +-805, -148, -124, -729, 628, -265, 476, 569, +-355, 600, -589, -252, -91, -777, 555, -151, +394, 727, -377, 574, -604, -459, -25, -870, +610, 28, 267, 885, -468, 448, -460, -632, +155, -764, 500, 232, 13, 817, -379, 194, +-196, -665, 217, -526, 248, 393, -86, 685, +-228, -11, -129, -675, 120, -372, 174, 469, +-29, 612, -213, -75, -150, -672, 104, -343, +113, 496, 3, 619, -146, -133, -116, -740, +63, -228, 84, 645, -27, 535, -108, -368, +33, -735, 25, 14, -121, 707, 3, 363, +129, -473, -38, -647, -289, 125, -76, 683, +294, 278, 114, -548, -305, -565, -320, 277, +101, 670, 337, 72, 69, -629, -344, -344, +-305, 416, 175, 496, 397, -107, -39, -518, +-454, -151, -189, 341, 304, 321, 306, -82, +-201, -339, -478, -126, -105, 176, 363, 251, +247, 43, -283, -220, -402, -207, -46, 52, +252, 279, 218, 134, -78, -223, -354, -266, +-256, 65, 226, 307, 434, 98, -61, -247, +-591, -211, -311, 111, 450, 229, 512, 45, +-292, -175, -794, -106, -183, 53, 699, 97, +478, 68, -559, -17, -839, -72, 105, -155, +827, -14, 249, 296, -705, 199, -673, -264, +275, -486, 781, 122, 114, 667, -815, 158, +-627, -641, 433, -506, 801, 483, -77, 736, +-931, -170, -502, -779, 578, -248, 731, 691, +-242, 565, -933, -392, -272, -736, 707, -9, +551, 719, -475, 315, -845, -526, 57, -466, +784, 253, 210, 488, -716, -51, -610, -381, +383, -69, 587, 206, -190, 109, -654, -48, +-179, -38, 437, -23, 150, -106, -386, -4, +-255, 168, 148, 129, 194, -81, -210, -272, +-257, -91, 93, 238, 169, 320, -119, -44, +-362, -471, -51, -199, 300, 428, 49, 486, +-365, -225, -403, -707, 129, -45, 429, 690, +-26, 444, -548, -518, -425, -723, 288, 168, +552, 755, -80, 301, -677, -573, -428, -626, +474, 157, 630, 674, -296, 360, -871, -484, +-266, -698, 722, 38, 540, 815, -558, 517, +-952, -651, -94, -986, 862, 153, 503, 1199, +-675, 527, -1009, -1021, -12, -1139, 990, 455, +494, 1408, -832, 314, -1049, -1243, 204, -977, +1103, 704, 294, 1309, -1062, 40, -942, -1255, +467, -758, 1086, 827, 11, 1210, -1163, -90, +-707, -1295, 583, -677, 884, 916, -97, 1228, +-1006, -163, -565, -1373, 490, -645, 795, 1025, +-51, 1250, -942, -326, -570, -1464, 474, -462, +821, 1223, -90, 1095, -1020, -600, -575, -1383, +512, -169, 851, 1179, -91, 837, -1059, -568, +-633, -1133, 528, -220, 926, 937, -104, 872, +-1096, -322, -583, -1158, 592, -397, 905, 953, +-203, 1020, -1111, -379, -483, -1306, 664, -343, +828, 1123, -312, 1022, -1063, -559, -466, -1415, +603, -199, 849, 1303, -224, 988, -1129, -773, +-619, -1473, 727, -7, 1055, 1418, -327, 839, +-1345, -942, -528, -1376, 1017, 208, 994, 1403, +-606, 616, -1385, -1059, -296, -1205, 1161, 433, +805, 1349, -826, 376, -1336, -1135, -58, -1021, +1159, 583, 575, 1227, -854, 218, -1171, -1074, +58, -831, 1073, 576, 445, 1030, -881, 131, +-1024, -913, 208, -660, 980, 500, 272, 881, +-908, 148, -890, -819, 279, -698, 895, 416, +165, 958, -900, 252, -764, -870, 288, -827, +766, 420, 118, 1043, -789, 236, -656, -897, +259, -792, 698, 477, 59, 979, -758, 158, +-517, -876, 313, -726, 523, 497, -77, 975, +-575, 167, -373, -918, 115, -794, 331, 522, +77, 1068, -375, 229, -465, -1013, -70, -887, +302, 548, 242, 1200, -251, 245, -550, -1156, +-218, -943, 375, 666, 444, 1310, -291, 148, +-760, -1320, -257, -914, 590, 813, 547, 1404, +-452, 73, -944, -1473, -213, -974, 749, 972, +559, 1591, -557, -39, -1013, -1728, -158, -895, +854, 1285, 559, 1572, -636, -423, -1080, -1811, +-63, -523, 1013, 1505, 529, 1307, -853, -705, +-1164, -1718, 172, -277, 1187, 1516, 336, 1151, +-1103, -769, -1100, -1604, 447, -193, 1211, 1440, +71, 1022, -1220, -753, -847, -1467, 651, -120, +1017, 1362, -166, 911, -1088, -782, -588, -1384, +640, -46, 816, 1349, -222, 808, -978, -792, +-512, -1291, 577, -13, 712, 1262, -219, 750, +-876, -711, -469, -1210, 451, -35, 623, 1155, +-94, 706, -746, -644, -542, -1110, 324, -45, +698, 1044, 28, 684, -808, -544, -640, -1077, +373, -180, 831, 994, -19, 882, -957, -440, +-677, -1262, 489, -371, 913, 1160, -90, 1074, +-1072, -551, -665, -1442, 614, -259, 937, 1336, +-222, 959, -1108, -745, -503, -1380, 698, -52, +794, 1356, -300, 800, -1019, -824, -430, -1330, +655, 72, 756, 1376, -285, 690, -1042, -931, +-430, -1219, 679, 252, 748, 1269, -331, 476, +-1030, -910, -349, -973, 657, 285, 710, 1076, +-334, 416, -1012, -806, -327, -902, 699, 237, +724, 1056, -432, 397, -1042, -819, -236, -830, +758, 277, 659, 981, -548, 276, -990, -737, +-130, -698, 762, 268, 514, 849, -586, 224, +-834, -642, -54, -628, 655, 259, 413, 745, +-516, 195, -728, -564, -34, -564, 610, 228, +294, 645, -509, 195, -572, -497, 51, -489, +390, 191, 156, 497, -279, 186, -409, -312, +-150, -383, 171, -37, 308, 336, -56, 414, +-464, -92, -322, -600, 123, -301, 467, 537, +60, 702, -553, -273, -487, -893, 153, -152, +654, 826, 88, 589, -722, -525, -581, -826, +233, 58, 806, 779, 93, 442, -882, -508, +-683, -741, 406, 56, 963, 752, -56, 447, +-1046, -542, -557, -745, 592, 110, 896, 746, +-187, 398, -1080, -527, -494, -678, 719, 52, +912, 696, -379, 483, -1180, -486, -277, -789, +841, 18, 692, 825, -472, 497, -1015, -608, +-190, -803, 751, 138, 660, 828, -485, 393, +-1013, -629, -65, -732, 821, 187, 468, 806, +-586, 340, -811, -669, 39, -694, 631, 261, +369, 805, -460, 293, -746, -675, -28, -680, +613, 258, 345, 827, -478, 281, -641, -749, +34, -647, 482, 404, 260, 807, -337, 90, +-549, -759, -81, -480, 446, 419, 349, 694, +-332, 86, -623, -728, -27, -495, 489, 462, +259, 748, -390, -70, -485, -804, 6, -269, +338, 599, 228, 500, -231, -239, -433, -569, +-154, -124, 302, 411, 353, 395, -210, -82, +-477, -529, -168, -229, 330, 420, 321, 464, +-155, -170, -467, -579, -308, -82, 332, 462, +550, 316, -159, -206, -791, -442, -298, -67, +725, 308, 519, 353, -568, -76, -752, -456, +159, -208, 669, 336, 114, 465, -510, -126, +-409, -566, 82, -163, 401, 491, 226, 462, +-369, -260, -529, -645, 44, -93, 517, 601, +175, 476, -499, -361, -379, -694, 108, -9, +360, 707, 132, 402, -324, -492, -354, -731, +-36, 174, 390, 829, 210, 284, -342, -771, +-377, -677, -30, 529, 346, 886, 230, -155, +-235, -908, -458, -177, -195, 777, 481, 343, +421, -490, -377, -419, -695, 257, -12, 328, +702, -67, 295, -151, -618, 4, -586, -34, +186, -39, 685, 128, 116, 187, -642, -152, +-474, -278, 296, 61, 590, 321, -14, 34, +-613, -278, -279, -104, 252, 209, 403, 60, +30, -87, -406, -17, -371, 95, 68, -151, +563, -129, 224, 243, -617, 246, -567, -265, +318, -410, 784, 186, -39, 558, -878, -39, +-358, -569, 616, -222, 637, 502, -341, 443, +-841, -317, -38, -562, 674, 21, 358, 582, +-500, 249, -587, -511, 182, -442, 488, 337, +101, 570, -366, -119, -316, -640, 70, -2, +241, 513, 179, 117, -110, -396, -409, -92, +-169, 322, 335, -39, 412, -304, -226, 168, +-663, 342, -47, -193, 615, -502, 323, 236, +-505, 621, -650, -119, 250, -742, 690, -141, +94, 790, -733, 477, -453, -645, 593, -836, +587, 333, -367, 1108, -759, 150, 96, -1277, +725, -665, 13, 1205, -625, 1254, -232, -921, +489, -1757, 275, 480, -452, 2031, -290, 88, +285, -2086, 315, -676, -291, 2033, -371, 1098, +239, -1724, 333, -1484, -197, 1402, -403, 1702, +96, -1085, 396, -1773, -63, 773, -403, 1838, +-68, -495, 353, -1955, 114, 214, -365, 2019, +-203, 192, 330, -2026, 190, -693, -303, 1951, +-295, 1198, 279, -1694, 352, -1710, -308, 1240, +-444, 2144, 174, -608, 572, -2352, -73, -104, +-736, 2244, -96, 769, 713, -1894, 313, -1264, +-678, 1402, -575, 1469, 548, -820, 626, -1444, +-267, 263, -693, 1241, -63, 62, 615, -803, +221, -268, -363, 433, -413, 279, 88, -155, +415, -181, 50, -65, -233, 118, -249, 193, +-2, -52, 213, -250, 177, -6, -53, 331, +-396, -2, -190, -387, 438, -67, 388, 518, +-330, 156, -628, -541, 128, -387, 708, 489, +80, 593, -642, -283, -333, -718, 428, -52, +507, 744, -251, 409, -533, -579, -63, -728, +486, 193, 327, 967, -489, 236, -474, -906, +327, -737, 613, 633, -200, 1135, -800, -213, +145, -1253, 789, -372, -23, 1179, -779, 924, +-180, -859, 811, -1315, 226, 296, -684, 1524, +-363, 319, 479, -1475, 508, -888, -361, 1172, +-505, 1325, 157, -708, 414, -1560, 13, 134, +-322, 1566, -71, 341, 152, -1231, -2, -779, +70, 834, 57, 950, -188, -414, -189, -860, +164, -41, 375, 743, -168, 297, -445, -494, +49, -366, 397, 147, 123, 380, -383, 13, +-192, -180, 246, -101, 199, -25, -76, 60, +-214, 185, -17, 38, 131, -261, 97, -172, +-38, 273, -179, 293, -50, -258, 253, -288, +103, 190, -294, 223, -224, -173, 381, -198, +344, 318, -483, 102, -457, -381, 477, -156, +650, 432, -443, 280, -862, -440, 353, -385, +958, 274, -88, 511, -1024, 52, -208, -568, +973, -444, 456, 369, -718, 888, -703, -15, +394, -1159, 823, -455, -73, 1227, -717, 926, +-293, -1089, 516, -1329, 535, 760, -231, 1561, +-586, -300, -114, -1540, 519, -178, 398, 1272, +-315, 497, -565, -873, 81, -575, 544, 446, +229, 516, -467, -136, -412, -310, 269, -37, +444, -2, 67, 116, -463, 251, -269, 7, +305, -439, 372, -187, -11, 510, -475, 338, +-148, -464, 373, -448, 319, 371, -171, 526, +-431, -277, -42, -517, 440, 167, 244, 494, +-297, -84, -469, -465, 154, 17, 603, 493, +16, 71, -625, -516, -229, -233, 587, 512, +460, 449, -546, -441, -569, -640, 381, 289, +683, 788, -157, -59, -755, -889, -10, -198, +688, 866, 240, 452, -489, -716, -489, -623, +265, 517, 632, 651, 81, -353, -647, -568, +-511, 273, 620, 459, 848, -317, -350, -378, +-1107, 455, -21, 387, 1209, -683, 480, -522, +-1077, 864, -879, 861, 732, -917, 1184, -1287, +-210, 744, -1307, 1672, -314, -341, 1152, -1865, +852, -214, -785, 1838, -1235, 780, 309, -1522, +1338, -1245, 265, 945, -1180, 1514, -733, -242, +810, -1451, 981, -425, -243, 1073, -964, 911, +-325, -542, 744, -1088, 761, -5, -255, 939, +-996, 472, -276, -604, 995, -676, 724, 117, +-650, 599, -1049, 342, 230, -269, 1094, -604, +291, -235, -884, 580, -747, 726, 553, -292, +1046, -1059, -83, -173, -1147, 1134, -359, 701, +1122, -971, 669, -1134, -879, 589, -877, 1400, +659, -93, 909, -1418, -382, -446, -862, 1256, +200, 817, 763, -825, -57, -1079, -635, 360, +-33, 1093, 553, 81, 97, -894, -439, -467, +-112, 619, 311, 691, 162, -289, -209, -746, +-93, -90, 79, 733, 25, 372, 16, -543, +82, -596, 23, 306, -247, 703, -91, -73, +390, -711, 263, -168, -393, 676, -549, 343, +398, -539, 769, -536, -218, 385, -901, 619, +-34, -194, 971, -608, 261, -16, -827, 572, +-440, 143, 608, -463, 523, -228, -367, 319, +-438, 278, 178, -196, 277, -215, -113, 101, +-55, 101, 159, -89, -23, 0, -353, 158, +34, -36, 544, -257, 138, -40, -612, 352, +-475, 209, 623, -335, 775, -477, -411, 166, +-991, 784, 59, 165, 1123, -959, 286, -685, +-1003, 960, -608, 1255, 718, -701, 827, -1715, +-389, 187, -807, 1971, 21, 512, 674, -1920, +220, -1207, -418, 1469, -327, 1794, 198, -738, +291, -2049, -19, -184, -162, 1935, -39, 1045, +66, -1395, -25, -1710, 3, 573, 128, 1957, +49, 384, -180, -1709, -230, -1217, 190, 1031, +404, 1724, -57, -124, -520, -1729, -195, -847, +601, 1336, 387, 1595, -453, -561, -560, -2001, +226, -432, 640, 1970, 24, 1370, -486, -1462, +-279, -2091, 261, 632, 408, 2426, 19, 290, +-352, -2311, -272, -1169, 190, 1847, 391, 1837, +47, -1139, -319, -2186, -244, 273, 86, 2186, +357, 564, 192, -1843, -252, -1212, -474, 1251, +-3, 1577, 684, -545, 314, -1641, -679, -140, +-654, 1423, 506, 709, 948, -965, -269, -1078, +-1023, 354, -72, 1213, 952, 270, 375, -1031, +-778, -867, -527, 647, 512, 1271, 559, -108, +-228, -1395, -495, -558, 39, 1290, 352, 1105, +64, -883, -160, -1479, -145, 277, 47, 1649, +127, 349, 31, -1470, -83, -979, -94, 1053, +96, 1410, 97, -459, -73, -1549, -140, -223, +45, 1428, 194, 785, 29, -1028, -252, -1189, +-112, 474, 262, 1328, 255, 121, -224, -1189, +-387, -668, 131, 838, 463, 985, 33, -320, +-440, -1079, -255, -181, 343, 935, 374, 567, +-91, -576, -440, -835, -185, 169, 360, 857, +397, 267, -127, -644, -524, -630, -162, 341, +488, 718, 401, 58, -227, -652, -590, -361, +-73, 465, 552, 495, 392, -172, -331, -524, +-641, -86, 11, 407, 656, 265, 406, -174, +-517, -326, -704, -76, 172, 212, 873, 255, +218, 7, -837, -275, -548, -276, 590, 177, +773, 465, -271, 43, -768, -556, -64, -338, +569, 509, 345, 592, -314, -282, -388, -739, +-42, -64, 293, 738, 265, 397, -70, -510, +-314, -664, -231, 157, 201, 797, 448, 227, +45, -713, -542, -597, -355, 486, 467, 848, +652, -190, -280, -897, -807, -156, -16, 826, +826, 403, 329, -654, -710, -551, -556, 408, +443, 615, 689, -152, -136, -584, -719, -49, +-146, 445, 617, 185, 391, -283, -454, -271, +-541, 175, 275, 267, 552, -68, -87, -243, +-505, -8, -70, 253, 391, 3, 153, -232, +-194, 24, -232, 223, 3, -29, 185, -288, +248, 68, -113, 351, -431, -101, -90, -395, +564, 58, 377, 486, -603, 13, -671, -570, +424, -124, 1003, 558, -137, 333, -1199, -483, +-295, -534, 1201, 318, 823, 673, -1040, -61, +-1257, -741, 637, -267, 1518, 720, -24, 589, +-1624, -511, -562, -857, 1353, 138, 1116, 988, +-825, 283, -1455, -881, 169, -674, 1437, 550, +533, 931, -1087, -142, -1057, -937, 487, -280, +1276, 696, 226, 595, -1134, -339, -844, -655, +688, -67, 1228, 446, -89, 391, -1255, -114, +-517, -439, 968, -294, 953, 246, -489, 623, +-1072, 95, -102, -695, 935, -553, 580, 548, +-559, 941, -819, -189, 11, -1120, 821, -313, +494, 1042, -543, 832, -817, -731, 44, -1173, +922, 174, 481, 1278, -729, 488, -916, -1105, +305, -1025, 1139, 608, 218, 1346, -1085, 64, +-679, -1358, 764, -669, 981, 985, -294, 1094, +-1021, -397, -170, -1220, 794, -198, 568, 1003, +-411, 634, -721, -567, -34, -871, 618, 147, +447, 830, -338, 212, -645, -617, -80, -455, +633, 366, 523, 474, -418, -101, -806, -350, +13, -91, 969, 156, 418, 110, -859, 51, +-835, -12, 576, -181, 1129, -140, -149, 214, +-1213, 283, -363, -127, 1128, -431, 822, -2, +-811, 503, -1179, 185, 344, -465, 1388, -423, +175, 358, -1300, 604, -741, -163, 1014, -660, +1177, -132, -523, 683, -1357, 354, -90, -557, +1307, -556, 648, 342, -973, 725, -1035, -124, +440, -741, 1203, -160, 157, 684, -1036, 424, +-709, -566, 626, -607, 1111, 305, -57, 770, +-1183, -13, -634, -780, 1035, -326, 1175, 671, +-523, 636, -1534, -437, -126, -870, 1550, 82, +828, 1016, -1177, 340, -1385, -962, 554, -829, +1600, 703, 263, 1221, -1420, -249, -979, -1377, +876, -363, 1442, 1320, -70, 902, -1527, -969, +-713, -1332, 1213, 399, 1369, 1552, -611, 260, +-1683, -1447, -115, -910, 1656, 1041, 802, 1409, +-1272, -431, -1317, -1593, 689, -295, 1541, 1480, +2, 966, -1435, -1019, -628, -1446, 1059, 295, +1083, 1584, -502, 512, -1217, -1272, -125, -1209, +1081, 669, 655, 1569, -690, 111, -960, -1556, +167, -866, 1008, 1273, 376, 1397, -780, -711, +-778, -1683, 362, 61, 990, 1653, 157, 503, +-945, -1292, -627, -915, 700, 803, 999, 1037, +-283, -278, -1176, -926, -212, -176, 1149, 682, +688, 498, -854, -296, -1086, -663, 441, -164, +1294, 629, 96, 585, -1228, -364, -618, -906, +974, -44, 1023, 983, -471, 499, -1198, -841, +-112, -881, 1107, 523, 723, 1076, -712, -94, +-1156, -1105, 129, -316, 1313, 932, 591, 664, +-1127, -606, -1168, -907, 615, 222, 1532, 945, +116, 218, -1499, -832, -852, -552, 1094, 565, +1472, 742, -399, -242, -1704, -777, -432, -59, +1625, 655, 1186, 291, -1133, -454, -1707, -387, +441, 206, 1918, 361, 325, 29, -1731, -230, +-1002, -141, 1273, 14, 1489, 152, -645, 200, +-1602, -59, -59, -328, 1471, -131, 640, 370, +-1045, 349, -972, -323, 493, -490, 1069, 128, +9, 584, -856, 92, -377, -530, 524, -281, +540, 364, -196, 419, -426, -164, -101, -436, +271, -52, 216, 392, -22, 205, -171, -280, +-177, -307, 78, 131, 240, 354, 138, -41, +-225, -284, -279, -35, 102, 239, 377, 19, +125, -242, -391, 43, -305, 276, 294, -44, +490, -370, -63, -3, -571, 455, -148, 80, +498, -505, 435, -205, -325, 527, -545, 375, +81, -482, 561, -584, 206, 320, -441, 740, +-337, -13, 225, -772, 424, -336, 12, 641, +-360, 605, -180, -337, 260, -752, 326, 2, +-105, 754, -369, 297, -10, -584, 365, -563, +165, 376, -317, 702, -228, -82, 206, -689, +300, -200, -60, 586, -297, 356, -60, -363, +249, -394, 173, 168, -129, 323, -212, -37, +4, -181, 174, -19, 122, 42, -39, 11, +-157, 76, -128, 20, 147, -147, 271, -90, +-12, 188, -349, 119, -157, -195, 339, -115, +330, 198, -185, 103, -472, -273, -15, -133, +518, 352, 298, 216, -424, -398, -531, -409, +245, 340, 676, 623, 30, -161, -684, -782, +-272, -160, 583, 796, 507, 541, -348, -664, +-627, -874, 119, 320, 620, 1073, 217, 139, +-513, -1058, -446, -590, 305, 799, 629, 919, +48, -350, -652, -1059, -370, -118, 566, 940, +679, 556, -268, -617, -834, -835, -40, 209, +835, 882, 415, 256, -605, -698, -660, -575, +306, 352, 748, 686, 129, 84, -674, -553, +-429, -381, 446, 269, 664, 542, -118, 92, +-737, -509, -177, -389, 650, 350, 488, 630, +-446, -56, -687, -705, 169, -268, 741, 612, +201, 538, -689, -342, -490, -653, 466, 36, +713, 591, -168, 185, -786, -411, -159, -310, +731, 210, 429, 305, -576, -73, -608, -223, +364, -39, 684, 110, -127, 14, -681, -44, +-57, 51, 607, 8, 212, -132, -448, -126, +-343, 143, 318, 217, 400, -76, -111, -301, +-388, -94, -49, 258, 334, 205, 190, -136, +-156, -295, -234, -18, 21, 239, 215, 157, +152, -148, -56, -235, -229, 19, -34, 215, +246, 134, 213, -147, -168, -205, -262, 27, +102, 221, 309, 121, 67, -142, -248, -168, +-142, 32, 168, 172, 247, 100, 9, -50, +-252, -109, -101, -73, 236, 72, 237, 199, +-145, 85, -262, -178, 75, -221, 265, 114, +14, 335, -210, 100, -17, -293, 132, -305, +23, 146, -86, 462, 2, 173, 83, -449, +-52, -472, -93, 285, 7, 727, 102, 23, +48, -813, -99, -384, -128, 714, -2, 710, +221, -488, 92, -935, -231, 68, -254, 971, +182, 338, 350, -837, -97, -715, -387, 478, +-75, 920, 359, -119, 188, -1001, -238, -311, +-267, 880, 72, 647, 290, -704, 63, -945, +-189, 346, -145, 1065, 95, -8, 187, -1082, +52, -371, -73, 897, -126, 623, -28, -687, +203, -790, 226, 407, -142, 843, -317, -151, +90, -854, 456, -73, 97, 772, -426, 302, +-178, -662, 372, -456, 338, 544, -178, 623, +-337, -325, 57, -729, 333, 118, 149, 810, +-193, 217, -201, -725, 90, -469, 241, 572, +60, 734, -165, -226, -96, -797, 103, -70, +102, 747, -23, 423, -23, -507, 14, -587, +-61, 244, -60, 659, 132, 108, 145, -551, +-201, -325, -269, 355, 183, 474, 371, -75, +-156, -477, -514, -164, 51, 339, 552, 340, +49, -132, -594, -435, -225, -128, 514, 346, +331, 335, -414, -216, -451, -495, 206, -54, +451, 466, -33, 248, -399, -414, -123, -449, +253, 192, 189, 475, -109, -82, -142, -505, +18, -108, 38, 398, 26, 155, 94, -390, +93, -225, -152, 272, -188, 224, 180, -280, +367, -273, -41, 248, -406, 292, -61, -224, +476, -412, 287, 136, -360, 512, -382, 53, +281, -521, 556, -284, -50, 433, -566, 532, +-74, -174, 603, -603, 332, -85, -486, 602, +-447, 411, 388, -399, 598, -555, -116, 195, +-614, 697, -91, 175, 573, -595, 325, -403, +-382, 465, -492, 661, 211, -113, 544, -684, +-12, -142, -512, 633, -166, 448, 399, -368, +226, -577, -283, 115, -273, 620, 118, 222, +189, -481, -51, -480, -138, 216, -42, 632, +8, 113, -25, -607, 41, -452, 32, 375, +-91, 626, -163, -135, 17, -682, 233, -233, +38, 518, -289, 418, -212, -362, 251, -606, +338, -3, -182, 574, -427, 236, 18, -530, +480, -560, 152, 222, -414, 638, -269, 11, +327, -710, 389, -364, -125, 534, -376, 568, +14, -372, 359, -787, 185, 59, -175, 829, +-225, 233, 80, -802, 324, -542, 142, 619, +-205, 769, -224, -344, 196, -840, 352, 40, +-1, 819, -276, 298, -78, -592, 270, -445, +205, 341, -75, 591, -184, 21, -45, -448, +202, -205, 203, 318, -72, 425, -278, -11, +-49, -319, 311, -132, 181, 254, -257, 306, +-287, 26, 127, -211, 321, -163, -18, 134, +-345, 341, -130, 134, 240, -315, 200, -341, +-190, 227, -315, 561, 46, 28, 275, -631, +36, -323, -318, 531, -201, 561, 209, -301, +220, -715, -134, -34, -324, 631, -33, 263, +261, -505, 105, -515, -178, 189, -210, 490, +26, 8, 193, -494, 107, -303, -107, 238, +-227, 340, -32, -104, 291, -410, 211, -171, +-214, 237, -358, 222, 140, -167, 516, -317, +84, -68, -511, 234, -270, 158, 525, -151, +551, -295, -298, -75, -626, 292, 114, 266, +732, -218, 226, -471, -549, 63, -359, 615, +384, 192, 510, -623, -54, -399, -389, 594, +-99, 653, 258, -346, 244, -734, 8, 189, +-184, 823, -141, 133, 81, -666, 246, -272, +102, 613, -226, 495, -238, -330, 109, -471, +316, 205, 43, 558, -363, 28, -222, -403, +230, -92, 351, 367, -148, 257, -492, -189, +-96, -245, 437, 54, 270, 270, -405, 136, +-497, -166, 159, -267, 531, -17, 42, 300, +-556, 194, -319, -239, 369, -403, 437, 16, +-210, 397, -518, 161, -57, -381, 436, -412, +204, 142, -308, 420, -324, -4, 114, -508, +363, -281, 47, 330, -301, 360, -189, -250, +240, -545, 332, -34, -105, 453, -335, 154, +-5, -413, 422, -368, 202, 166, -341, 345, +-273, -18, 315, -314, 455, -194, -125, 134, +-444, 262, 33, 60, 478, -244, 209, -271, +-311, 114, -277, 422, 191, 143, 431, -378, +59, -360, -375, 256, -208, 578, 354, 93, +380, -513, -220, -345, -394, 446, 85, 671, +395, -71, 49, -728, -283, -223, -147, 783, +84, 672, 196, -469, 68, -870, -175, 201, +-308, 1028, 20, 266, 399, -860, 120, -506, +-467, 689, -420, 724, 320, -362, 547, -736, +-146, 151, -685, 684, -213, 65, 572, -538, +411, -196, -399, 358, -632, 197, 33, -196, +595, -178, 251, 36, -469, 27, -557, -61, +161, 18, 653, 32, 168, -119, -634, -168, +-490, 8, 446, 142, 707, -15, -143, -212, +-766, -165, -147, 80, 694, 157, 445, -62, +-434, -243, -557, -135, 208, 133, 603, 132, +123, -98, -425, -230, -238, -50, 290, 196, +342, 97, -39, -201, -222, -222, -25, 187, +156, 333, 98, -133, 29, -458, 35, 28, +-46, 585, -116, 187, 65, -562, 276, -351, +71, 529, -337, 585, -195, -300, 356, -623, +363, 162, -276, 715, -498, 126, 161, -587, +559, -252, -24, 539, -597, 484, -161, -264, +534, -477, 260, 106, -480, 505, -418, 163, +299, -298, 448, -224, -198, 152, -532, 301, +-19, 82, 431, -186, 127, -214, -400, 52, +-284, 304, 192, 159, 269, -270, -65, -353, +-268, 115, -123, 437, 117, 64, 188, -489, +26, -303, -253, 333, -205, 417, 182, -202, +335, -553, -69, -78, -409, 412, -86, 222, +433, -356, 280, -416, -300, 69, -417, 334, +153, 61, 555, -338, 121, -241, -485, 134, +-347, 212, 408, -75, 614, -254, -135, -43, +-630, 160, -121, 26, 656, -166, 430, -70, +-433, 147, -548, 90, 201, -158, 645, -146, +109, 143, -515, 229, -280, -49, 328, -279, +450, -26, -55, 335, -416, 192, -181, -242, +309, -306, 375, 230, -108, 489, -457, -7, +-130, -501, 379, -172, 303, 590, -210, 477, +-449, -377, -52, -619, 375, 187, 242, 792, +-270, 179, -452, -661, 52, -411, 400, 509, +103, 657, -359, -168, -282, -674, 160, -104, +235, 601, -16, 397, -223, -385, -164, -542, +84, 132, 176, 543, -1, 129, -228, -462, +-105, -344, 169, 251, 121, 391, -130, -50, +-154, -424, 63, -201, 153, 262, -11, 264, +-127, -156, -8, -374, 115, -72, 86, 257, +-90, 117, -91, -215, 113, -234, 152, 35, +-38, 151, -189, -13, 53, -134, 267, -80, +39, 5, -243, 35, -90, 12, 304, -26, +186, -87, -234, -51, -198, 95, 203, 86, +275, -76, -107, -157, -230, 49, 53, 191, +224, 12, 29, -148, -169, -24, -60, 165, +144, 66, 72, -90, -134, -14, -69, 126, +108, 75, 72, -61, -135, -31, -107, 111, +127, 106, 101, -32, -112, -67, -187, 48, +58, 137, 189, 55, -26, -67, -233, -53, +-128, 63, 208, 127, 178, 59, -198, -84, +-306, -96, 59, 53, 340, 192, -9, 43, +-390, -201, -137, -123, 334, 170, 211, 215, +-290, -127, -295, -299, 179, -13, 288, 292, +-82, 135, -241, -284, -36, -310, 150, 115, +78, 346, -6, 3, -72, -400, -107, -222, +39, 251, 197, 270, 98, -179, -203, -372, +-172, -34, 201, 286, 265, 104, -71, -248, +-285, -249, 12, 99, 301, 234, 87, -16, +-227, -226, -92, -107, 214, 116, 131, 95, +-149, -29, -107, -58, 152, -37, 120, -16, +-109, 49, -118, 109, 103, 3, 152, -135, +-75, -28, -143, 170, 14, 128, 167, -100, +31, -130, -161, 94, -95, 192, 94, 27, +137, -116, -56, -15, -174, 134, -49, 86, +121, -53, 117, -13, -99, 70, -199, 59, +-19, -18, 171, -1, 100, 61, -161, 17, +-213, -19, 31, 5, 224, 68, 53, 38, +-232, -74, -182, -62, 129, 65, 211, 131, +-31, -32, -239, -193, -96, -54, 154, 184, +147, 129, -40, -168, -186, -227, -102, 33, +137, 199, 224, 35, -24, -183, -300, -180, +-102, 18, 315, 156, 263, 66, -225, -157, +-367, -248, 106, 3, 438, 252, 83, 105, +-382, -274, -221, -308, 304, 124, 368, 350, +-132, 12, -379, -382, -16, -218, 385, 283, +163, 324, -283, -131, -213, -391, 176, -35, +272, 376, -67, 191, -241, -276, -7, -273, +199, 193, 75, 356, -150, -44, -104, -334, +98, -23, 133, 335, -54, 166, -181, -237, +-1, -175, 196, 224, 33, 267, -216, -89, +-132, -263, 190, 58, 191, 336, -173, 97, +-276, -273, 63, -185, 281, 264, 24, 329, +-302, -120, -164, -366, 229, -11, 219, 397, +-162, 170, -300, -309, 83, -296, 247, 179, +-44, 354, -207, -23, 11, -359, 147, -144, +-62, 240, -125, 221, 115, -134, 121, -282, +-165, -27, -182, 188, 171, 77, 270, -145, +-123, -160, -319, 13, 11, 76, 348, 23, +146, -76, -288, -116, -260, -26, 165, 68, +357, 72, 55, -91, -351, -163, -237, -10, +294, 147, 433, 69, -111, -160, -495, -161, +-50, 74, 478, 201, 243, 16, -329, -199, +-354, -114, 176, 159, 385, 191, 49, -54, +-299, -204, -230, -23, 177, 216, 338, 155, +0, -109, -370, -179, -166, 55, 299, 258, +294, 77, -179, -186, -364, -122, 7, 189, +326, 235, 114, -81, -257, -193, -204, 36, +88, 218, 199, 62, 17, -127, -155, -55, +-138, 79, 9, 89, 159, 19, 80, -45, +-135, -63, -197, -19, 24, 90, 232, 93, +67, -80, -235, -153, -181, -7, 149, 149, +250, 51, -72, -144, -269, -127, -51, 37, +239, 103, 138, 3, -177, -123, -185, -95, +77, 0, 218, 103, 30, 32, -198, -159, +-111, -152, 179, 79, 175, 189, -82, -63, +-206, -273, 19, -42, 221, 241, 78, 113, +-161, -229, -164, -210, 126, 141, 228, 244, +-2, -33, -250, -250, -109, -82, 257, 217, +212, 195, -160, -102, -259, -229, 36, -22, +282, 238, 121, 171, -219, -98, -245, -213, +100, -22, 333, 263, 46, 190, -345, -136, +-197, -267, 237, 67, 322, 378, -107, 116, +-387, -340, -70, -246, 314, 309, 240, 444, +-209, -149, -371, -516, 36, -32, 366, 575, +121, 271, -320, -515, -235, -464, 151, 390, +224, 627, 32, -183, -210, -718, -197, -61, +80, 697, 252, 285, 67, -596, -268, -527, +-231, 387, 195, 625, 319, -174, -72, -681, +-347, -120, -110, 587, 302, 293, 246, -462, +-160, -471, -354, 192, 6, 478, 399, 6, +134, -448, -312, -239, -259, 250, 214, 345, +315, -76, -69, -383, -263, -147, -39, 273, +185, 264, 135, -126, -50, -315, -121, -48, +-47, 245, 69, 203, 159, -113, 29, -267, +-161, -19, -144, 285, 134, 195, 249, -220, +-32, -272, -289, 163, -94, 366, 262, 0, +235, -356, -191, -96, -309, 349, 59, 260, +335, -209, 63, -326, -309, 108, -161, 406, +201, 83, 222, -357, -110, -223, -244, 291, +15, 373, 206, -113, 35, -420, -177, -80, +-86, 388, 117, 308, 76, -255, -103, -438, +-82, 39, 49, 487, 44, 168, -42, -452, +-6, -355, 5, 298, -72, 447, 14, -156, +113, -517, -8, -45, -178, 445, -47, 192, +224, -378, 95, -352, -222, 196, -205, 378, +186, -64, 342, -414, -100, -107, -436, 334, +-46, 169, 486, -290, 249, -238, -439, 206, +-432, 249, 307, -178, 585, -271, -61, 128, +-634, 256, -173, -89, 567, -252, 422, 67, +-346, 231, -583, -37, 105, -195, 630, 29, +171, 190, -494, 9, -394, -142, 275, 22, +526, 136, -1, 14, -504, -90, -276, 31, +384, 127, 447, 7, -165, -102, -496, -1, +-107, 125, 439, 51, 333, -76, -277, -24, +-486, 66, 33, 6, 526, -24, 202, 55, +-470, 54, -385, -106, 293, -92, 481, 160, +-100, 148, -512, -172, -109, -215, 428, 164, +255, 271, -306, -158, -365, -346, 157, 79, +368, 369, -26, -2, -327, -407, -103, -124, +241, 335, 130, 210, -133, -269, -156, -292, +12, 128, 132, 278, 74, -53, -84, -259, +-138, -58, 16, 165, 160, 72, 69, -88, +-128, -64, -163, -29, 58, -20, 259, 77, +37, 135, -313, -70, -139, -270, 312, -3, +280, 344, -239, 143, -393, -346, 138, -287, +462, 302, 56, 412, -456, -142, -238, -474, +370, -22, 424, 512, -175, 241, -541, -405, +-35, -411, 539, 271, 271, 559, -411, -12, +-444, -543, 191, -196, 510, 449, 85, 398, +-444, -230, -328, -435, 251, 14, 494, 401, +4, 192, -517, -246, -260, -300, 402, 65, +435, 318, -193, 135, -519, -233, -70, -259, +460, 87, 265, 296, -319, 70, -391, -263, +86, -192, 387, 151, 114, 230, -303, -54, +-264, -254, 135, -60, 314, 186, 11, 105, +-263, -130, -171, -153, 131, 34, 251, 119, +8, 15, -257, -92, -150, -86, 179, 16, +229, 84, -68, 24, -257, -77, -42, -72, +230, 39, 120, 54, -161, -44, -136, -30, +79, 55, 121, 22, 34, -103, -97, -32, +-105, 139, 79, 78, 151, -132, -9, -121, +-175, 123, -31, 175, 163, -55, 89, -165, +-122, 23, -128, 170, 68, 55, 165, -117, +1, -62, -146, 78, -55, 78, 128, -10, +123, -34, -74, 2, -127, 12, -7, -1, +109, 37, 96, 50, -50, -6, -148, -82, +-59, -31, 179, 105, 164, 91, -165, -64, +-234, -150, 94, 1, 265, 162, 19, 85, +-261, -145, -146, -189, 191, 66, 256, 267, +-99, 44, -337, -316, -19, -231, 344, 262, +113, 379, -295, -151, -197, -496, 175, -44, +234, 475, -62, 219, -236, -404, -84, -371, +221, 243, 165, 422, -191, -94, -210, -451, +150, -58, 213, 390, -135, 155, -174, -318, +118, -219, 131, 238, -129, 214, -92, -181, +145, -197, 73, 151, -114, 190, -88, -129, +47, -193, 111, 109, 56, 239, -139, -18, +-150, -266, 152, -70, 222, 278, -105, 201, +-241, -226, 32, -293, 230, 167, 95, 389, +-159, -57, -204, -398, 67, -52, 271, 375, +90, 188, -266, -245, -233, -256, 219, 59, +347, 269, -87, 129, -375, -176, -40, -258, +341, 23, 163, 306, -222, 141, -272, -261, +102, -247, 302, 142, 38, 292, -265, -9, +-152, -281, 162, -142, 242, 194, -16, 238, +-300, -89, -126, -301, 298, -57, 250, 269, +-267, 146, -327, -219, 197, -228, 368, 126, +-115, 220, -388, -61, 17, -217, 354, -22, +88, 176, -281, 74, -233, -140, 180, -143, +336, 80, -70, 179, -403, -31, -50, -197, +426, -44, 137, 186, -393, 110, -212, -156, +301, -154, 261, 110, -187, 189, -260, -40, +46, -180, 226, -42, 98, 136, -152, 131, +-185, -30, 87, -176, 228, -95, -34, 189, +-197, 239, 1, -102, 163, -348, 9, 13, +-90, 405, -6, 125, 52, -387, 7, -226, +-44, 329, 41, 336, 58, -216, -70, -367, +-85, 84, 66, 387, 140, 28, -29, -310, +-160, -110, -40, 227, 177, 131, 102, -124, +-177, -106, -135, 52, 175, 40, 131, -1, +-142, 25, -142, -36, 121, -117, 150, 44, +-90, 192, -166, -49, 63, -264, 157, 6, +-35, 283, -159, 47, 7, -300, 147, -105, +18, 263, -141, 132, -100, -224, 144, -162, +158, 159, -127, 167, -221, -96, 54, -176, +262, -12, 34, 181, -284, 97, -153, -152, +288, -206, 255, 113, -289, 286, -338, -39, +238, -349, 393, -37, -151, 384, -424, 124, +39, -373, 413, -201, 82, 327, -374, 296, +-183, -246, 298, -347, 267, 162, -198, 412, +-344, -49, 88, -443, 413, -52, 47, 450, +-452, 237, -155, -437, 429, -409, 284, 368, +-345, 606, -358, -220, 249, -768, 394, 38, +-129, 867, -368, 212, 21, -878, 325, -468, +61, 828, -206, 699, -136, -695, 112, -891, +161, 500, -23, 1026, -119, -264, -27, -1065, +29, 0, 9, 1052, 76, 195, 60, -959, +-140, -370, -154, 837, 154, 466, 221, -717, +-102, -540, -255, 581, -6, 594, 239, -478, +117, -654, -151, 368, -257, 683, 13, -253, +347, -738, 134, 105, -361, 774, -277, 60, +279, -791, 367, -295, -146, 745, -385, 510, +-12, -589, 325, -695, 113, 342, -222, 794, +-145, -65, 85, -786, 116, -204, 60, 678, +-31, 396, -190, -472, -63, -513, 254, 227, +186, 529, -272, 58, -250, -457, 219, -278, +276, 297, -107, 428, -246, -86, 16, -460, +161, -104, 90, 433, -48, 245, -173, -318, +-43, -341, 241, 194, 171, 384, -284, -17, +-267, -373, 293, -189, 383, 330, -238, 361, +-472, -179, 154, -510, 543, -6, -23, 589, +-571, 238, -107, -599, 543, -505, 275, 531, +-433, 751, -460, -347, 275, -941, 580, 13, +-23, 1035, -650, 365, -208, -936, 592, -774, +388, 656, -419, 1066, -511, -251, 201, -1177, +521, -278, 19, 1116, -432, 739, -230, -850, +285, -1125, 328, 411, -77, 1333, -350, 95, +-127, -1298, 250, -632, 246, 1034, -75, 1040, +-278, -597, -111, -1216, 146, 51, 291, 1152, +21, 444, -376, -867, -216, -792, 363, 422, +388, 971, -300, 32, -453, -893, 152, -485, +480, 657, 6, 796, -434, -280, -94, -919, +296, -139, 171, 856, -172, 509, -129, -595, +23, -749, 80, 253, 96, 874, -31, 74, +-154, -834, 30, -372, 231, 724, -55, 603, +-310, -534, 106, -727, 405, 272, -82, 805, +-537, -18, 53, -728, 617, -216, 73, 552, +-657, 417, -229, -321, 616, -511, 409, 27, +-442, 541, -587, 264, 206, -486, 685, -531, +69, 300, -624, 754, -351, -42, 469, -861, +483, -248, -194, 790, -507, 533, -115, -613, +391, -669, 329, 321, -155, 685, -479, -47, +-103, -590, 450, -141, 339, 366, -313, 247, +-475, -117, 65, -234, 463, -140, 189, 71, +-318, 352, -361, 160, 49, -414, 382, -439, +244, 300, -265, 689, -453, -112, -6, -750, +560, -155, 293, 681, -498, 361, -569, -475, +297, -452, 768, 172, 12, 455, -837, 118, +-348, -311, 762, -349, 670, 44, -557, 490, +-849, 257, 250, -438, 919, -531, 84, 225, +-826, 701, -383, 63, 671, -658, 620, -389, +-427, 482, -776, 618, 170, -178, 857, -682, +89, -174, -834, 612, -294, 486, 742, -389, +445, -723, -544, 51, -522, 842, 300, 321, +569, -764, -50, -668, -560, 511, -165, 902, +505, -164, 334, -951, -390, -214, -418, 847, +187, 522, 432, -615, 21, -717, -348, 289, +-242, 800, 228, 56, 366, -728, -77, -374, +-414, 483, -96, 599, 401, -106, 198, -660, +-326, -305, -274, 497, 218, 679, 281, -198, +-126, -886, -218, -203, 18, 901, 151, 604, +31, -742, -91, -919, -46, 414, 62, 1066, +50, 43, -67, -1030, -76, -493, 80, 738, +134, 855, -58, -271, -236, -1001, 27, -240, +308, 844, 97, 687, -366, -487, -200, -924, +334, 12, 321, 897, -195, 471, -405, -639, +10, -816, 368, 177, 293, 928, -226, 384, +-530, -786, -13, -864, 678, 329, 367, 1105, +-660, 275, -647, -1003, 464, -856, 866, 533, +-119, 1210, -920, 144, -233, -1202, 782, -844, +578, 817, -515, 1371, -768, -151, 163, -1558, +780, -633, 195, 1333, -618, 1324, -405, -707, +300, -1744, 451, -155, 41, 1699, -293, 1063, +-308, -1173, -31, -1728, 441, 289, 336, 1932, +-328, 752, -624, -1614, 54, -1637, 733, 881, +298, 2104, -637, 158, -665, -2101, 368, -1156, +857, 1566, 27, 1911, -840, -582, -480, -2258, +608, -535, 775, 2006, -159, 1590, -907, -1232, +-345, -2295, 767, 175, 791, 2399, -408, 964, +-1075, -1970, -50, -1849, 1082, 1112, 557, 2246, +-837, -10, -934, -2181, 388, -1017, 1113, 1608, +193, 1759, -1060, -687, -680, -2112, 765, -323, +1014, 1896, -277, 1208, -1101, -1248, -223, -1733, +910, 371, 665, 1740, -513, 515, -890, -1340, +48, -1161, 864, 653, 433, 1426, -620, 136, +-757, -1308, 195, -788, 865, 859, 314, 1181, +-727, -206, -729, -1227, 335, -447, 1029, 895, +154, 938, -1056, -310, -662, -1089, 844, -341, +1051, 905, -442, 846, -1229, -438, -65, -1067, +1150, -103, 553, 981, -838, 570, -916, -611, +323, -838, 1074, 138, 234, 845, -991, 351, +-757, -558, 652, -678, 1107, 113, -182, 729, +-1197, 394, -375, -460, 1044, -776, 850, -8, +-670, 839, -1149, 572, 136, -609, 1211, -982, +417, 152, -1021, 1117, -908, 420, 625, -991, +1233, -893, -128, 568, -1291, 1152, -378, 6, +1143, -1145, 746, -561, -776, 777, -943, 950, +347, -192, 928, -1037, 64, -446, -695, 730, +-362, 952, 343, -182, 502, -1147, 48, -493, +-423, 981, -390, 1074, 223, -535, 572, -1425, +98, -93, -552, 1454, -399, 711, 372, -1167, +631, -1218, -64, 639, -699, 1449, -252, -12, +614, -1350, 519, -575, -380, 1001, -646, 914, +75, -486, 621, -958, 239, -23, -448, 781, +-460, 352, 174, -403, 555, -466, 124, -15, +-506, 403, -353, 311, 323, -97, 484, -479, +-81, -223, -482, 425, -187, 512, 355, -133, +391, -654, -174, -206, -470, 559, -59, 524, +430, -221, 262, -710, -308, -148, -394, 619, +104, 548, 443, -336, 85, -801, -381, -46, +-251, 787, 262, 496, 337, -592, -105, -828, +-357, 218, -38, 918, 306, 283, 158, -818, +-192, -704, -227, 438, 52, 936, 253, 103, +77, -966, -204, -606, -169, 661, 135, 955, +216, -178, -14, -1093, -208, -335, -104, 872, +164, 789, 242, -467, -72, -1051, -304, -86, +-48, 1000, 327, 623, 205, -681, -271, -1010, +-357, 175, 162, 1052, 483, 405, 48, -803, +-556, -852, -236, 305, 530, 985, 439, 303, +-412, -792, -589, -804, 229, 354, 622, 1004, +51, 297, -562, -897, -332, -869, 380, 484, +529, 1202, -90, 239, -655, -1217, -208, -907, +590, 825, 479, 1404, -389, -64, -690, -1568, +95, -697, 716, 1234, 245, 1393, -588, -525, +-547, -1744, 318, -322, 691, 1586, 60, 1216, +-691, -1026, -435, -1798, 502, 170, 709, 1874, +-163, 852, -817, -1530, -232, -1598, 708, 715, +602, 1920, -437, 305, -814, -1778, 54, -1169, +867, 1084, 328, 1695, -704, -113, -623, -1773, +393, -825, 755, 1261, -24, 1518, -651, -395, +-290, -1787, 363, -540, 477, 1432, 16, 1327, +-439, -684, -370, -1737, 250, -231, 587, 1521, +96, 1099, -580, -858, -481, -1622, 366, -51, +747, 1541, 42, 1049, -825, -1001, -487, -1732, +675, 99, 846, 1831, -282, 1004, -1027, -1446, +-207, -1803, 926, 552, 681, 2120, -543, 626, +-989, -1929, -4, -1587, 1015, 1122, 595, 2210, +-772, 39, -1054, -2285, 286, -1107, 1261, 1642, +319, 1970, -1137, -592, -885, -2248, 708, -551, +1232, 1818, -95, 1594, -1251, -957, -549, -2038, +923, -172, 1035, 1860, -363, 1264, -1213, -1153, +-328, -1891, 1053, 40, 911, 1935, -558, 1129, +-1231, -1387, -141, -1944, 1223, 316, 810, 2230, +-838, 877, -1307, -1858, 196, -1866, 1494, 915, +531, 2375, -1268, 288, -1179, -2259, 722, -1441, +1553, 1532, -16, 2221, -1539, -434, -662, -2426, +1194, -765, 1140, 1979, -594, 1694, -1281, -1082, +-93, -2111, 1086, -13, 698, 1883, -601, 953, +-998, -1213, -27, -1449, 995, 257, 611, 1418, +-678, 619, -977, -923, 151, -1135, 1055, 132, +442, 1155, -842, 650, -882, -699, 379, -1091, +1096, -96, 153, 1059, -996, 901, -619, -539, +647, -1389, 918, -319, -150, 1425, -979, 1217, +-346, -952, 767, -1825, 729, 68, -375, 1987, +-884, 973, -88, -1572, 770, -1772, 476, 622, +-480, 2185, -733, 548, 120, -1937, 740, -1624, +285, 1098, -591, 2329, -568, 55, 298, -2385, +656, -1249, 64, 1823, -630, 2183, -347, -800, +446, -2533, 511, -457, -169, 2263, -585, 1551, +-48, -1414, 467, -2186, 216, 224, -241, 2196, +-288, 913, 40, -1604, 203, -1723, 168, 633, +-92, 1987, -311, 446, -34, -1687, 339, -1348, +208, 923, -315, 1822, -305, 71, 213, -1782, +329, -1002, -51, 1223, -311, 1604, -59, -379, +263, -1731, 136, -504, -179, 1365, -176, 1177, +118, -689, 166, -1451, -78, -141, -99, 1313, +45, 892, 58, -831, -48, -1319, -36, 107, +86, 1381, 1, 613, -116, -1070, -17, -1042, +159, 434, 92, 1206, -220, 188, -129, -982, +156, -626, 207, 465, -79, 872, -274, 70, +27, -767, 273, -525, 105, 340, -299, 853, +-213, 132, 259, -783, 281, -621, -128, 415, +-374, 997, 37, 34, 358, -982, 51, -564, +-272, 718, -153, 961, 178, -307, 184, -1063, +-29, -236, -177, 899, -123, 748, 151, -533, +161, -991, -48, -66, -173, 966, -61, 665, +140, -677, 170, -1065, -59, 143, -256, 1191, +-52, 487, 262, -1075, 152, -953, -199, 618, +-190, 1249, 79, -17, 232, -1312, 2, -517, +-195, 985, -90, 998, 104, -519, 195, -1207, +-2, 3, -207, 1064, -121, 533, 183, -827, +248, -805, -147, 414, -269, 871, 28, 50, +311, -838, 83, -303, -321, 548, -145, 501, +230, -218, 223, -538, -171, 15, -225, 305, +119, 197, 175, -104, -18, -222, -153, -35, +-25, 75, 60, 192, 46, 26, 33, -164, +-27, -151, -92, 34, -33, 286, 107, 88, +83, -257, -101, -237, -134, 115, 39, 379, +170, 32, 36, -325, -185, -215, -133, 180, +149, 360, 177, -40, -77, -351, -184, -157, +-36, 307, 168, 340, 113, -294, -97, -387, +-181, 157, 0, 438, 174, -32, 74, -465, +-100, 14, -109, 320, 2, 85, 96, -265, +76, -144, -24, 257, -138, 80, -82, -99, +183, -168, 176, 4, -148, 240, -240, 24, +26, -113, 255, -232, 67, 126, -132, 295, +-175, -91, -21, -229, 231, -115, 141, 312, +-152, 164, -270, -244, 13, -199, 329, 47, +137, 326, -208, 14, -339, -241, 75, -126, +414, 101, 115, 228, -350, -30, -357, -143, +231, -101, 490, 36, 7, 198, -482, 64, +-339, -168, 385, -209, 540, 99, -142, 293, +-611, 9, -187, -254, 574, -135, 421, 129, +-372, 219, -595, 6, 24, -156, 683, -174, +268, 42, -550, 260, -565, 92, 290, -220, +744, -258, -69, 137, -717, 339, -195, 14, +547, -315, 385, -229, -329, 237, -426, 344, +14, -57, 378, -369, 206, -133, -314, 292, +-279, 248, 176, -132, 261, -273, -78, -72, +-166, 214, 17, 226, -20, -75, 11, -305, +164, -118, -9, 310, -191, 268, -73, -204, +149, -337, 118, 1, -68, 348, -93, 134, +-87, -202, 95, -245, 170, 44, -92, 276, +-178, 59, 23, -147, 181, -162, -66, 24, +-79, 134, 127, 136, -72, 6, -155, -301, +115, -140, 229, 310, -148, 327, -264, -239, +109, -455, 188, 148, 43, 412, -108, 47, +-196, -339, -71, -150, 273, 173, 290, 175, +-326, 52, -455, -163, 225, -206, 562, 75, +-117, 287, -603, 89, -74, -313, 518, -202, +226, 226, -369, 261, -361, -66, 160, -287, +381, -69, -18, 216, -331, 171, -112, -83, +187, -274, 147, -24, -49, 264, -124, 133, +-125, -191, 49, -226, 180, 89, -2, 216, +-186, 57, -78, -148, 150, -212, 49, 89, +-63, 263, -74, 18, -59, -305, 69, -101, +97, 323, -29, 111, -150, -283, 35, -113, +75, 218, -83, 115, 18, -215, 84, -17, +-109, 189, -138, -45, 196, -189, 114, 41, +-260, 297, -92, -75, 222, -356, 63, 56, +-199, 419, -34, 32, 113, -528, -10, -76, +-33, 567, -14, 173, -46, -547, -17, -324, +108, 524, -16, 447, -166, -421, 43, -550, +157, 264, -96, 650, -196, -130, 100, -664, +152, -19, -82, 667, -154, 140, 12, -626, +102, -271, 14, 562, -88, 383, -128, -445, +89, -519, 122, 305, -87, 635, -201, -74, +46, -783, 216, -167, -95, 847, -245, 465, +57, -850, 240, -767, -50, 735, -329, 1026, +27, -528, 291, -1186, 41, 192, -358, 1264, +-173, 127, 366, -1205, 261, -425, -348, 1007, +-422, 682, 238, -779, 485, -833, -160, 547, +-523, 858, -32, -274, 507, -906, 169, 115, +-511, 902, -320, -20, 411, -894, 383, -61, +-375, 1003, -446, 130, 331, -1204, 400, -194, +-351, 1379, -422, 452, 330, -1584, 442, -802, +-368, 1695, -533, 1213, 310, -1578, 612, -1721, +-229, 1314, -769, 2201, 47, -892, 794, -2502, +136, 258, -758, 2670, -419, 419, 589, -2571, +572, -1066, -342, 2202, -747, 1655, -44, -1662, +740, -2039, 363, 995, -657, 2211, -676, -279, +375, -2167, 810, -413, -144, 1941, -829, 957, +-163, -1511, 646, -1369, 348, 949, -458, 1592, +-472, -374, 152, -1556, 390, -254, 63, 1340, +-293, 748, -215, -956, 9, -1080, 205, 430, +228, 1213, -205, 99, -478, -1091, 29, -613, +592, 762, 62, 987, -662, -293, -176, -1164, +541, -302, 203, 1160, -467, 782, -265, -836, +296, -1222, 222, 391, -208, 1429, -232, 143, +56, -1344, 179, -754, -1, 1108, -224, 1174, +-112, -623, 155, -1416, 246, 24, -224, 1483, +-425, 495, 137, -1221, 511, -992, -43, 887, +-702, 1296, -143, -440, 716, -1444, 277, -2, +-665, 1504, -567, 344, 502, -1389, 629, -674, +-286, 1273, -697, 896, -96, -1064, 651, -1035, +302, 734, -536, 1225, -550, -474, 245, -1246, +657, 54, -112, 1282, -621, 368, -134, -1261, +431, -748, 186, 1033, -304, 1214, -195, -764, +19, -1512, 56, 298, 120, 1655, 60, 294, +-276, -1651, -301, -817, 233, 1278, 438, 1336, +-220, -752, -597, -1603, 42, 75, 562, 1487, +127, 699, -612, -1162, -334, -1204, 447, 435, +433, 1482, -311, 408, -646, -1426, 158, -1157, +603, 879, -2, 1794, -670, -141, -220, -2013, +568, -737, 264, 1770, -433, 1639, -457, -1233, +183, -2132, 476, 288, 6, 2311, -532, 713, +-383, -2029, 482, -1547, 620, 1252, -400, 2184, +-960, -309, 144, -2331, 1140, -733, 87, 1994, +-1307, 1697, -493, -1368, 1237, -2189, 803, 388, +-1116, 2346, -1155, 567, 732, -2072, 1298, -1325, +-381, 1396, -1342, 1919, -179, -655, 1162, -2096, +525, -130, -828, 1932, -933, 844, 255, -1625, +1065, -1150, 193, 1050, -1023, 1306, -818, -557, +774, -1198, 1127, 216, -503, 846, -1303, 95, +-55, -578, 1257, -131, 351, 243, -1009, 70, +-717, 55, 501, -18, 838, -157, -158, -213, +-772, 282, -315, 347, 482, -304, 452, -440, +-182, 212, -473, 569, -288, -182, 176, -561, +486, 75, 190, 548, -617, 27, -727, -525, +379, -110, 1068, 446, 0, 201, -1364, -368, +-633, -262, 1236, 258, 1198, 279, -936, -117, +-1777, -247, 275, 24, 1937, 121, 428, 69, +-1913, 14, -1260, -73, 1472, -114, 1750, -35, +-812, 215, -2180, 137, -34, -162, 2097, -243, +729, -50, -1748, 381, -1467, 264, 1118, -317, +1691, -584, -390, 134, -1774, 930, -429, 71, +1445, -1053, 938, -476, -985, 1096, -1329, 893, +272, -1020, 1307, -1160, 293, 663, -1127, 1435, +-901, -240, 613, -1555, 1208, -197, -129, 1341, +-1415, 750, -451, -1026, 1219, -1085, 833, 493, +-1013, 1157, -1159, 175, 519, -1021, 1201, -674, +-119, 528, -1195, 1025, -459, 105, 984, -1069, +742, -767, -731, 734, -1076, 1382, 274, -197, +1174, -1649, -6, -635, -1140, 1626, -501, 1452, +859, -1208, 876, -2054, -688, 345, -1139, 2425, +99, 599, 1307, -2265, 289, -1554, -1412, 1620, +-757, 2352, 1059, -703, 1150, -2627, -791, -474, +-1457, 2425, 232, 1615, 1409, -1783, 287, -2358, +-1361, 679, -849, 2691, 984, 516, 1121, -2448, +-610, -1513, -1351, 1627, 54, 2214, 1255, -543, +265, -2342, -1079, -618, -606, 1896, 654, 1620, +714, -1105, -441, -2108, -677, -6, 74, 2150, +386, 988, 74, -1619, -259, -1693, -89, 716, +-153, 1983, -50, 239, 318, -1693, 78, -1140, +-381, 1054, -443, 1667, 370, -245, 473, -1685, +-278, -623, -598, 1389, -88, 1163, 604, -761, +173, -1359, -557, 36, -433, 1229, 322, 533, +537, -778, -347, -855, -520, 156, 104, 882, +374, 380, -89, -554, -312, -764, 37, 56, +-8, 854, -89, 455, 80, -613, 60, -847, +-242, 213, -210, 941, 211, 277, 195, -802, +-225, -664, -319, 474, 42, 835, 255, 30, +64, -896, -368, -382, -253, 645, 238, 701, +308, -284, -204, -847, -527, -14, 51, 656, +433, 436, 63, -444, -457, -621, -344, 96, +345, 637, 340, 348, -219, -612, -499, -615, +-45, 367, 432, 848, 66, -67, -258, -936, +-346, -224, 0, 827, 295, 508, 201, -623, +-263, -677, -591, 308, 106, 776, 618, -30, +106, -717, -741, -299, -418, 604, 576, 572, +511, -459, -370, -699, -728, 113, 63, 848, +591, 184, 146, -803, -484, -523, -415, 544, +150, 928, 374, -248, 147, -1134, -374, -259, +-509, 1212, 63, 850, 655, -1151, 170, -1306, +-801, 778, -566, 1717, 614, -258, 812, -1897, +-474, -349, -1054, 1762, 39, 1025, 1038, -1391, +278, -1542, -1014, 793, -704, 1800, 651, -5, +946, -1798, -351, -686, -1210, 1423, -133, 1251, +1173, -781, 485, -1589, -1138, 45, -902, 1505, +887, 801, 1008, -1154, -617, -1511, -1172, 535, +219, 1873, 1013, 421, 26, -2015, -827, -1296, +-404, 1658, 476, 2074, 470, -897, -163, -2669, +-586, 40, -244, 2713, 418, 1011, 433, -2415, +-235, -1909, -713, 1790, -91, 2423, 633, -796, +377, -2692, -596, -144, -691, 2455, 282, 999, +714, -1884, 56, -1646, -787, 1194, -469, 1857, +498, -349, 713, -1849, -206, -346, -976, 1515, +-221, 894, 827, -975, 561, -1252, -686, 425, +-866, 1272, 212, 188, 867, -1136, 209, -646, +-815, 846, -677, 889, 389, -409, 931, -1057, +-66, 79, -1008, 1018, -471, 239, 741, -881, +766, -521, -410, 758, -969, 676, -258, -551, +894, -771, 725, 284, -667, 872, -1208, -81, +105, -810, 1407, -211, 330, 696, -1345, 495, +-959, -535, 948, -653, 1281, 211, -495, 821, +-1455, 108, -236, -846, 1319, -437, 713, 690, +-1026, 821, -1174, -498, 447, -987, 1262, 94, +5, 1084, -1150, 319, -566, -997, 754, -632, +733, 620, -274, 935, -851, -248, -264, -959, +592, -206, 542, 760, -237, 643, -816, -516, +-207, -779, 639, 93, 539, 761, -409, 277, +-873, -592, 1, -413, 800, 197, 387, 441, +-716, 140, -746, -295, 350, -319, 782, -64, +29, 416, -768, 341, -453, -273, 440, -548, +628, -78, -77, 678, -787, 421, -373, -505, +575, -814, 662, 160, -321, 1090, -917, 298, +-136, -1064, 818, -888, 523, 856, -648, 1316, +-903, -345, 181, -1571, 989, -305, 286, 1546, +-972, 907, -812, -1148, 590, -1440, 1139, 572, +-178, 1658, -1366, 145, -410, -1508, 1220, -889, +878, 1142, -1008, 1327, -1263, -440, 464, -1517, +1368, -304, -9, 1377, -1330, 892, -518, -826, +961, -1348, 853, 159, -641, 1436, -1027, 530, +115, -1135, 935, -1185, 231, 688, -795, 1452, +-487, -17, 346, -1453, 580, -630, -66, 1173, +-558, 1043, -294, -562, 275, -1290, 511, -61, +-159, 1183, -577, 642, -137, -778, 465, -1108, +278, 267, -417, 1193, -322, 384, 99, -1029, +308, -952, -11, 647, -263, 1245, -125, 7, +51, -1371, 156, -619, -66, 1178, -103, 1137, +-42, -686, -44, -1560, -1, 122, 85, 1654, +65, 509, -257, -1478, -171, -1135, 247, 1182, +191, 1502, -272, -647, -304, -1719, 215, 66, +237, 1752, -184, 443, -290, -1491, 94, -953, +227, 1142, -118, 1297, -223, -691, 21, -1442, +223, 145, -122, 1517, -243, 276, 67, -1377, +250, -689, -92, 1158, -409, 1020, 112, -884, +326, -1166, -71, 465, -451, 1281, 30, -111, +451, -1177, -135, -218, -406, 892, -14, 495, +452, -656, -27, -447, -501, 301, -60, 342, +367, -140, 224, -171, -410, 248, -348, -87, +223, -341, 369, 23, -37, 605, -461, 170, +-158, -788, 286, -448, 298, 657, -103, 903, +-453, -452, -147, -1192, 378, 3, 366, 1289, +-303, 597, -592, -1232, 94, -1103, 593, 861, +123, 1572, -583, -323, -369, -1833, 345, -361, +511, 1817, -100, 1121, -623, -1491, -232, -1782, +505, 803, 520, 2247, -417, 112, -691, -2284, +85, -1125, 689, 1870, 208, 2011, -631, -1087, +-432, -2476, 268, 8, 598, 2506, -33, 1044, +-604, -2044, -241, -1818, 342, 1133, 468, 2284, +-184, -133, -479, -2205, -186, -869, 358, 1682, +436, 1709, -274, -923, -528, -2065, -51, -112, +581, 2064, 167, 1082, -507, -1675, -288, -1748, +266, 828, 333, 2218, -195, 25, -207, -2160, +-9, -931, 66, 1682, 20, 1716, 35, -1020, +34, -2040, -248, 62, -75, 2034, 210, 839, +222, -1664, -262, -1451, -363, 866, 191, 1810, +376, -46, 7, -1707, -529, -720, -167, 1213, +429, 1296, 386, -574, -331, -1489, -666, -128, +195, 1358, 680, 733, 91, -1047, -742, -1079, +-325, 564, 617, 1204, 419, -86, -347, -1130, +-613, -299, 121, 877, 561, 608, 108, -539, +-494, -733, -399, 115, 396, 738, 479, 276, +-161, -584, -564, -582, -139, 244, 515, 831, +316, 59, -271, -798, -553, -436, -22, 661, +535, 754, 321, -508, -376, -832, -646, 118, +154, 996, 699, 172, 177, -995, -779, -474, +-438, 789, 670, 937, 566, -609, -469, -1126, +-765, 137, 299, 1217, 698, 407, -18, -1101, +-656, -784, -296, 595, 535, 1102, 432, -80, +-217, -1054, -679, -450, -45, 723, 686, 839, +271, -308, -527, -881, -605, -210, 388, 741, +653, 538, -66, -406, -728, -685, -261, -21, +702, 664, 416, 361, -485, -431, -643, -651, +297, 116, 624, 755, -60, 279, -524, -703, +-213, -644, 349, 476, 299, 915, -95, -89, +-397, -1014, -106, -318, 288, 858, 254, 711, +-138, -522, -357, -938, -30, 65, 267, 930, +278, 416, -230, -730, -412, -766, 45, 355, +474, 952, 162, 69, -495, -935, -295, -484, +295, 773, 431, 768, -67, -477, -485, -915, +-206, 133, 343, 975, 464, 124, -166, -832, +-604, -396, -81, 698, 508, 593, 292, -524, +-348, -654, -388, 209, 85, 782, 324, 45, +158, -756, -219, -368, -291, 578, 59, 731, +281, -352, 103, -899, -282, -63, -174, 949, +167, 488, 215, -822, -88, -783, -249, 498, +14, 952, 200, -153, 58, -918, -144, -183, +-95, 733, 41, 407, 48, -433, 41, -539, +49, 108, -106, 530, -141, 200, 35, -395, +227, -494, 37, 194, -212, 650, -104, 96, +59, -686, 160, -423, 70, 580, -85, 661, +-232, -309, -37, -821, 355, -3, 120, 796, +-356, 310, -312, -631, 354, -507, 452, 409, +-307, 567, -585, -140, 99, -556, 768, -59, +110, 455, -813, 227, -430, -316, 705, -378, +789, 185, -519, 435, -977, 19, 122, -471, +1092, -211, 247, 418, -1032, 357, -565, -227, +762, -483, 843, 45, -471, 438, -911, 177, +48, -326, 886, -340, 323, 175, -720, 346, +-599, 78, 383, -355, 826, -237, -113, 225, +-789, 366, -240, -10, 655, -497, 473, -132, +-430, 400, -542, 388, 60, -282, 575, -559, +202, 102, -450, 540, -428, 247, 182, -543, +634, -438, 30, 332, -591, 562, -351, -36, +435, -615, 607, -147, -241, 432, -668, 346, +-125, -176, 652, -415, 371, -67, -480, 279, +-500, 346, 142, -90, 586, -484, 107, -162, +-493, 458, -357, 437, 349, -331, 553, -637, +-233, 118, -613, 684, 33, 178, 684, -650, +123, -424, -650, 480, -325, 576, 527, -175, +559, -651, -403, -102, -669, 557, 120, 356, +769, -346, 133, -540, -736, 96, -326, 560, +505, 190, 548, -454, -346, -406, -575, 244, +64, 510, 556, 46, 199, -467, -549, -331, +-353, 276, 435, 512, 534, -1, -315, -543, +-677, -301, 157, 447, 686, 509, 110, -214, +-649, -624, -349, -61, 470, 617, 550, 259, +-192, -463, -657, -461, -83, 300, 600, 540, +328, -103, -462, -526, -484, -146, 262, 537, +516, 291, -44, -413, -508, -475, -106, 275, +386, 642, 217, -154, -227, -681, -305, -96, +95, 757, 242, 311, 97, -736, -194, -525, +-210, 574, 84, 823, 204, -391, 80, -993, +-191, 22, -143, 1085, 89, 413, 133, -1011, +73, -836, -171, 693, -112, 1210, 67, -221, +202, -1377, 13, -391, -285, 1305, -53, 998, +257, -978, 177, -1430, -294, 382, -232, 1684, +244, 241, 291, -1577, -159, -884, -353, 1225, +70, 1383, 337, -719, 82, -1603, -344, 53, +-177, 1613, 240, 563, 326, -1382, -141, -1030, +-441, 869, 38, 1361, 430, -297, 173, -1387, +-450, -332, -287, 1137, 334, 879, 361, -703, +-120, -1183, -480, 125, -11, 1223, 408, 450, +222, -1031, -321, -880, -383, 622, 204, 1117, +395, -155, 21, -1124, -383, -268, -225, 935, +292, 563, 339, -670, -90, -701, -419, 386, +-78, 718, 353, -144, 173, -677, -171, -37, +-216, 565, 15, 210, 120, -474, 121, -348, +48, 327, -196, 429, -182, -123, 131, -482, +311, -74, 1, 394, -407, 281, -134, -223, +376, -444, 362, -3, -353, 464, -529, 275, +244, -427, 670, -478, -51, 256, -799, 618, +-124, -52, 800, -674, 358, -167, -726, 584, +-571, 400, 588, -463, 712, -538, -337, 217, +-822, 599, 87, 51, 805, -582, 208, -265, +-684, 364, -487, 458, 508, -130, 663, -508, +-180, -165, -822, 389, -110, 452, 817, -216, +429, -592, -680, -103, -730, 630, 499, 387, +834, -524, -110, -648, -867, 283, -243, 805, +733, -29, 520, -824, -380, -292, -739, 756, +54, 526, 697, -580, 311, -713, -476, 281, +-575, 843, 214, -25, 606, -794, 136, -333, +-503, 652, -360, 602, 317, -440, 438, -752, +-52, 74, -398, 816, -168, 245, 280, -696, +297, -540, -53, 413, -388, 729, -155, -88, +390, -731, 364, -285, -255, 568, -554, 526, +110, -304, 637, -653, 148, -20, -578, 602, +-409, 267, 452, -426, 571, -469, -176, 203, +-624, 502, -81, 55, 547, -460, 285, -331, +-305, 326, -397, 493, 101, -74, 344, -631, +111, -224, -189, 602, -185, 495, 66, -444, +129, -771, 114, 167, -34, 860, -118, 161, +-102, -803, 102, -517, 238, 593, -59, 712, +-219, -266, -59, -817, 265, -77, 127, 730, +-191, 338, -181, -529, 93, -552, 303, 261, +18, 578, -267, -8, -192, -514, 273, -273, +366, 370, -165, 387, -423, -126, 1, -482, +490, -161, 172, 413, -379, 370, -283, -194, +239, -586, 386, -104, -68, 590, -324, 435, +-81, -429, 263, -799, 201, 140, -93, 915, +-186, 302, -64, -930, 183, -768, 214, 684, +-38, 1085, -251, -227, -99, -1303, 264, -317, +247, 1177, -82, 838, -307, -819, -110, -1259, +337, 265, 333, 1349, -164, 384, -492, -1243, +23, -961, 612, 813, 198, 1305, -514, -256, +-398, -1454, 466, -335, 541, 1245, -260, 840, +-541, -864, 53, -1185, 609, 298, 124, 1204, +-440, 292, -252, -1041, 332, -797, 399, 570, +-154, 1054, -324, -8, -7, -1101, 315, -587, +179, 786, -172, 1043, -183, -304, 37, -1312, +257, -329, 122, 1219, -122, 910, -198, -920, +25, -1345, 310, 373, 156, 1491, -229, 197, +-287, -1437, 249, -735, 421, 1076, -78, 1093, +-466, -644, 28, -1280, 560, 96, 117, 1198, +-484, 376, -221, -988, 541, -758, 370, 558, +-389, 937, -437, -134, 276, -975, 624, -300, +-49, 764, -561, 612, -169, -536, 564, -791, +472, 174, -342, 779, -541, 107, 97, -717, +668, -347, 255, 492, -507, 473, -453, -312, +334, -567, 709, 89, -2, 502, -657, 81, +-228, -464, 572, -228, 537, 307, -253, 272, +-579, -176, -20, -322, 615, -2, 442, 216, +-365, 97, -608, -135, 141, -215, 753, -31, +310, 175, -598, 148, -506, -158, 342, -263, +769, 11, 138, 265, -678, 85, -453, -268, +504, -206, 840, 144, -105, 254, -836, -58, +-209, -292, 780, -100, 592, 222, -416, 210, +-658, -189, 132, -320, 721, 9, 289, 359, +-497, 117, -448, -353, 345, -318, 640, 187, +20, 426, -530, -37, -181, -488, 496, -273, +446, 373, -134, 466, -481, -185, -44, -640, +537, -186, 390, 635, -252, 466, -538, -455, +160, -809, 646, 103, 206, 909, -465, 261, +-317, -849, 407, -717, 446, 585, -44, 920, +-328, -207, -20, -1057, 314, -286, 214, 928, +-41, 623, -164, -646, 39, -974, 246, 241, +151, 1023, -112, 178, -97, -987, 201, -625, +225, 749, -75, 840, -123, -418, 142, -1042, +225, 58, 11, 988, -109, 226, 46, -863, +177, -545, 126, 660, -24, 617, -70, -419, +122, -745, 227, 129, 20, 720, -156, 25, +89, -670, 329, -296, 32, 566, -242, 407, +50, -493, 403, -556, 130, 273, -292, 641, +-108, -149, 378, -675, 317, -122, -143, 579, +-296, 304, 162, -481, 436, -486, 104, 188, +-277, 538, -116, 33, 366, -537, 309, -335, +-121, 329, -255, 515, 167, -149, 429, -627, +27, -213, -275, 559, -8, 478, 418, -428, +200, -730, -236, 51, -123, 816, 262, 279, +364, -763, -55, -692, -238, 410, 37, 945, +411, -43, 250, -1013, -271, -511, -210, 788, +297, 893, 496, -437, -61, -1122, -398, -156, +23, 1076, 526, 596, 349, -839, -338, -996, +-329, 333, 304, 1127, 612, 80, 24, -1066, +-478, -582, -47, 776, 508, 856, 377, -469, +-208, -1036, -273, -30, 136, 1031, 400, 368, +250, -926, -161, -769, -216, 601, 119, 988, +470, -321, 203, -1090, -286, -132, -210, 987, +322, 425, 520, -843, -39, -684, -370, 484, +-5, 780, 490, -249, 308, -813, -188, -67, +-220, 685, 124, 254, 397, -628, 231, -460, +-100, 411, -243, 559, 88, -276, 479, -700, +286, -3, -252, 661, -321, 246, 280, -635, +591, -539, 92, 352, -418, 691, -157, -69, +514, -781, 459, -334, -156, 585, -382, 617, +136, -359, 547, -837, 217, -59, -265, 771, +-226, 399, 304, -660, 505, -701, 40, 286, +-347, 782, -62, 37, 489, -801, 364, -408, +-178, 548, -256, 624, 146, -300, 457, -799, +192, -68, -180, 692, -185, 361, 233, -575, +459, -615, 58, 236, -259, 623, -22, 53, +398, -583, 276, -336, -132, 273, -138, 413, +191, -11, 375, -409, 67, -294, -198, 123, +3, 420, 379, 115, 246, -417, -166, -452, +-136, 179, 282, 586, 352, 53, -18, -630, +-158, -415, 87, 460, 317, 556, 180, -263, +-85, -676, -54, -61, 166, 614, 289, 236, +61, -501, -87, -498, 46, 260, 243, 570, +220, -72, -40, -641, -64, -261, 127, 547, +293, 450, 146, -423, -98, -674, -53, 116, +172, 709, 320, 113, 162, -659, -153, -433, +-148, 405, 234, 554, 499, -164, 106, -625, +-366, -204, -99, 474, 443, 402, 500, -312, +-87, -606, -384, -10, -8, 602, 548, 238, +485, -578, -270, -540, -474, 354, 230, 693, +775, -143, 181, -842, -585, -226, -194, 767, +614, 531, 577, -664, -225, -860, -477, 302, +154, 976, 636, 52, 296, -1024, -344, -477, +-286, 750, 330, 739, 556, -475, 98, -938, +-341, 63, -135, 841, 373, 266, 459, -759, +23, -547, -296, 469, -76, 634, 396, -248, +418, -746, -6, -23, -323, 643, -57, 214, +482, -597, 427, -454, -127, 391, -398, 540, +101, -201, 592, -689, 292, -78, -288, 618, +-322, 294, 293, -577, 616, -557, 104, 362, +-431, 634, -188, -161, 563, -729, 506, -109, +-211, 599, -414, 282, 163, -470, 620, -514, +189, 199, -302, 510, -202, 76, 304, -527, +495, -425, 52, 302, -285, 604, -109, -6, +389, -767, 407, -420, -56, 624, -261, 747, +16, -369, 417, -1063, 302, -101, -98, 1051, +-238, 547, 92, -902, 429, -1007, 235, 459, +-139, 1179, -197, 32, 142, -1215, 392, -609, +241, 916, -155, 985, -268, -510, 191, -1274, +541, -63, 180, 1232, -406, 546, -209, -1055, +486, -1019, 537, 643, -143, 1209, -478, -202, +86, -1307, 649, -318, 334, 1115, -404, 679, +-421, -829, 409, -1013, 760, 369, 17, 1054, +-697, 47, -150, -1001, 838, -496, 573, 724, +-491, 715, -664, -415, 410, -886, 931, 22, +73, 792, -750, 238, -271, -646, 801, -483, +669, 358, -371, 494, -690, -138, 201, -474, +905, -115, 248, 300, -607, 186, -412, -164, +551, -266, 754, -25, -106, 182, -629, 90, +-129, -124, 744, -190, 539, -23, -351, 130, +-592, 100, 183, -95, 812, -240, 253, -49, +-507, 219, -398, 172, 425, -241, 692, -364, +13, 105, -505, 414, -186, 36, 540, -516, +495, -255, -122, 405, -424, 398, -15, -281, +527, -583, 359, 47, -193, 553, -389, 183, +152, -534, 555, -441, 190, 326, -324, 541, +-244, -98, 351, -651, 447, -187, 13, 511, +-331, 399, -76, -362, 414, -599, 341, 92, +-117, 581, -324, 168, 128, -579, 448, -414, +139, 377, -238, 519, -107, -190, 291, -648, +249, -33, -34, 555, -101, 198, 76, -518, +188, -399, 101, 386, 3, 453, -27, -228, +73, -602, 179, 12, 99, 593, -79, 182, +-35, -554, 216, -501, 226, 376, -57, 643, +-175, -123, 99, -778, 338, -261, 155, 706, +-213, 539, -204, -493, 266, -842, 458, 137, +-2, 901, -425, 226, -55, -844, 546, -646, +337, 586, -302, 840, -357, -236, 252, -972, +550, -201, 66, 837, -399, 504, -167, -568, +457, -785, 436, 167, -204, 783, -399, 210, +131, -666, 559, -588, 153, 347, -372, 712, +-211, 21, 350, -734, 460, -421, -81, 489, +-365, 641, -13, -159, 427, -780, 277, -266, +-184, 640, -255, 607, 88, -408, 349, -882, +205, 6, -150, 923, -253, 371, 91, -846, +404, -758, 208, 530, -270, 950, -265, -164, +235, -1028, 448, -289, 73, 832, -386, 634, +-150, -531, 372, -883, 402, 84, -103, 882, +-385, 328, 22, -755, 412, -706, 297, 425, +-196, 881, -328, -36, 104, -949, 467, -411, +245, 755, -343, 747, -313, -449, 304, -998, +532, -3, 2, 979, -472, 429, -89, -805, +477, -809, 363, 420, -218, 955, -361, 12, +125, -959, 433, -472, 177, 699, -217, 766, +-231, -352, 120, -948, 356, -100, 192, 861, +-200, 462, -269, -659, 122, -763, 394, 286, +172, 843, -253, 81, -278, -796, 140, -445, +453, 554, 171, 648, -364, -271, -331, -745, +310, -73, 564, 647, -35, 317, -541, -476, +-145, -496, 559, 213, 449, 506, -320, 1, +-535, -461, 162, -205, 711, 310, 149, 285, +-560, -179, -291, -367, 503, 13, 539, 338, +-220, 112, -487, -302, 50, -255, 562, 189, +218, 293, -353, -55, -239, -321, 269, -116, +386, 226, -68, 220, -244, -88, 33, -323, +247, -91, 125, 272, -118, 256, -35, -208, +114, -426, 122, 44, -39, 479, -62, 169, +126, -517, 104, -412, -48, 397, -85, 593, +107, -200, 144, -753, -15, -69, -82, 731, +-30, 352, 124, -634, 152, -625, -6, 405, +-175, 763, -25, -126, 274, -856, 168, -206, +-194, 784, -220, 499, 192, -598, 346, -771, +-11, 270, -295, 856, -77, 122, 343, -804, +272, -523, -165, 533, -308, 773, 108, -143, +426, -870, 112, -297, -285, 698, -181, 636, +275, -378, 324, -835, -47, -50, -231, 769, +-9, 430, 238, -561, 142, -702, -46, 224, +-90, 781, 0, 129, 113, -745, 123, -453, +32, 544, -110, 680, -54, -268, 150, -823, +135, -85, -53, 766, -116, 424, 57, -564, +119, -701, 19, 190, -40, 747, -24, 233, +56, -598, 47, -590, -13, 229, -14, 711, +66, 219, 39, -616, -88, -601, 23, 266, +163, 793, 23, 169, -157, -786, -3, -589, +247, 532, 76, 878, -169, -179, -90, -998, +206, -232, 212, 890, -85, 598, -174, -657, +49, -837, 284, 279, 89, 904, -160, 96, +-97, -817, 140, -405, 222, 553, 20, 595, +-134, -252, -73, -624, 155, -54, 198, 475, +-36, 294, -135, -270, -8, -394, 165, -18, +101, 346, -61, 245, -90, -199, 8, -365, +139, -61, 47, 361, -65, 266, -73, -232, +41, -417, 112, -12, 10, 447, -67, 221, +-83, -330, 69, -427, 125, 130, 8, 509, +-133, 91, -79, -470, 155, -340, 158, 348, +-38, 455, -194, -143, -43, -491, 225, -83, +188, 424, -71, 211, -247, -247, 15, -334, +286, 51, 197, 325, -145, 128, -258, -201, +91, -301, 310, 52, 161, 292, -198, 165, +-203, -192, 130, -342, 299, 12, 105, 337, +-231, 240, -131, -272, 160, -381, 247, 88, +-10, 382, -189, 112, -32, -316, 132, -185, +132, 122, -40, 179, -107, 26, -43, -91, +94, -81, 143, -88, -89, 76, -176, 189, +42, 54, 207, -244, -38, -238, -222, 209, +30, 384, 163, -30, 9, -533, -140, -198, +-27, 537, 75, 462, 40, -404, -1, -705, +-66, 178, -15, 783, 74, 159, 71, -731, +-59, -472, -47, 516, 99, 657, 79, -170, +-43, -732, -39, -145, 68, 599, 104, 391, +32, -363, -51, -528, -53, 111, 122, 472, +167, 144, -33, -350, -165, -320, 49, 157, +210, 367, 34, 103, -112, -358, -36, -303, +73, 190, 81, 420, 44, 72, -75, -433, +-130, -304, 75, 246, 180, 496, -34, 57, +-230, -542, -45, -370, 200, 357, 135, 638, +-150, -81, -265, -743, 30, -266, 293, 628, +71, 591, -285, -379, -220, -772, 143, 10, +249, 770, 65, 382, -246, -617, -307, -673, +128, 289, 471, 829, 65, 108, -530, -796, +-244, -475, 463, 558, 416, 751, -219, -223, +-454, -841, -24, -162, 451, 744, 335, 495, +-279, -516, -490, -676, 148, 152, 607, 722, +83, 193, -515, -572, -204, -487, 404, 265, +339, 674, -162, 73, -366, -622, -32, -444, +345, 422, 248, 693, -255, -115, -383, -709, +93, -289, 417, 597, 90, 548, -392, -295, +-310, -650, 204, -91, 446, 606, -14, 333, +-582, -333, -270, -482, 512, 39, 456, 456, +-417, 159, -644, -250, 143, -316, 636, 80, +108, 299, -584, 78, -402, -202, 387, -222, +568, 123, -143, 232, -689, 31, -114, -223, +665, -166, 360, 143, -533, 227, -517, 38, +368, -265, 611, -197, -103, 158, -570, 310, +-103, 25, 506, -331, 296, -176, -300, 197, +-386, 306, 134, -35, 409, -300, 86, -132, +-299, 209, -249, 259, 168, -116, 327, -269, +35, -30, -334, 258, -230, 125, 250, -208, +317, -177, -132, 84, -409, 240, -22, -3, +311, -204, 83, -93, -256, 112, -213, 173, +79, -8, 157, -119, 18, -160, -198, 6, +-204, 264, 103, 158, 242, -240, -62, -378, +-376, 145, -49, 489, 348, 51, 98, -477, +-323, -291, -213, 373, 212, 434, 215, -146, +-69, -473, -219, -96, -89, 423, 164, 263, +203, -264, -16, -386, -259, 64, -91, 425, +232, 131, 236, -362, -113, -329, -305, 237, +-7, 456, 310, -40, 188, -477, -265, -188, +-323, 397, 172, 370, 395, -200, -42, -480, +-479, -11, -84, 477, 417, 196, 174, -381, +-377, -339, -313, 269, 233, 371, 263, -110, +-111, -345, -317, -40, -97, 271, 186, 124, +134, -117, -113, -205, -290, -14, -45, 197, +193, 135, 76, -110, -196, -248, -200, 56, +71, 268, 134, 22, -7, -279, -165, -89, +-114, 326, 81, 107, 121, -300, -25, -181, +-198, 281, -26, 248, 187, -241, 74, -255, +-188, 109, -136, 288, 184, -4, 162, -260, +-119, -94, -208, 177, 85, 209, 229, -120, +-51, -240, -193, -6, -21, 259, 143, 161, +29, -226, -60, -286, -51, 83, -78, 420, +27, 66, 82, -430, -25, -220, -168, 356, +-47, 347, 110, -231, 1, -350, -102, 33, +-113, 298, -9, 92, 57, -179, 5, -133, +-136, 53, -175, 149, 91, -38, 151, -101, +-106, 34, -269, 93, -47, -45, 179, -139, +68, 46, -117, 154, -193, 91, -72, -152, +107, -247, 153, 36, -49, 346, -259, 214, +-116, -319, 175, -409, 246, 124, -61, 515, +-361, 159, -127, -511, 336, -418, 313, 324, +-276, 653, -398, -33, 90, -726, 350, -318, +106, 590, -241, 666, -269, -268, -12, -869, +308, -185, 180, 868, -279, 696, -313, -600, +35, -1071, 266, 92, 136, 1165, -196, 505, +-378, -928, -78, -983, 434, 428, 179, 1233, +-478, 218, -430, -1162, 253, -808, 451, 760, +-103, 1180, -518, -114, -288, -1204, 362, -549, +437, 885, -265, 1032, -636, -287, -60, -1212, +559, -407, 241, 999, -420, 978, -536, -405, +56, -1204, 573, -350, 224, 1003, -532, 997, +-567, -392, 261, -1328, 652, -367, 52, 1215, +-617, 1039, -445, -630, 404, -1440, 609, -162, +-139, 1342, -647, 915, -159, -789, 452, -1357, +263, 75, -208, 1334, -367, 659, -63, -912, +260, -1142, 164, 259, -210, 1226, -279, 490, +83, -922, 151, -982, -87, 339, -167, 1112, +-13, 331, 56, -858, -42, -835, -115, 279, +-131, 1031, 48, 446, 125, -797, -140, -1000, +-278, 200, -32, 1171, 262, 480, 1, -853, +-320, -956, -232, 264, 146, 1056, 299, 397, +-94, -774, -471, -868, -167, 213, 439, 969, +252, 452, -453, -663, -456, -900, 237, 106, +457, 1001, -81, 544, -489, -752, -224, -1010, +326, 256, 358, 1177, -222, 367, -500, -964, +-20, -787, 425, 444, 113, 902, -297, 91, +-253, -680, -6, -422, 197, 288, 133, 524, +-157, 93, -334, -315, -41, -356, 239, -29, +113, 382, -193, 366, -303, -145, -55, -559, +216, -141, 83, 522, -266, 405, -196, -274, +82, -552, 28, -26, -108, 487, -70, 321, +-42, -222, -100, -413, -18, -58, -15, 261, +-148, 231, -11, 23, 79, -185, -129, -262, +-212, 5, 13, 356, 109, 264, -74, -266, +-103, -461, -66, -2, -65, 494, -25, 385, +-5, -291, 2, -613, -55, -125, -114, 576, +-90, 604, 82, -228, 86, -856, -193, -323, +-234, 760, 72, 858, 183, -281, -33, -1024, +-246, -375, -156, 789, 72, 879, 123, -202, +-93, -990, -226, -469, -55, 743, 140, 965, +8, -150, -291, -1100, -164, -538, 175, 817, +147, 1070, -278, -161, -361, -1186, 59, -566, +311, 874, 0, 1108, -437, -179, -348, -1205, +172, -625, 369, 826, -74, 1204, -507, -7, +-252, -1214, 215, -850, 236, 694, -79, 1333, +-372, 175, -285, -1239, 131, -988, 348, 696, +-114, 1479, -465, 201, -151, -1440, 202, -1126, +94, 890, -60, 1730, -167, 81, -301, -1724, +-44, -1054, 301, 1133, 88, 1707, -351, -123, +-314, -1758, 1, -955, 246, 1228, 173, 1704, +-286, -183, -540, -1774, 11, -946, 503, 1209, +104, 1676, -540, -146, -447, -1789, 145, -948, +477, 1281, 81, 1721, -626, -257, -559, -1885, +337, -869, 636, 1366, -181, 1635, -781, -281, +-360, -1766, 422, -771, 581, 1233, -193, 1469, +-938, -298, -414, -1606, 742, -590, 664, 1229, +-615, 1286, -1041, -525, -15, -1539, 893, -237, +368, 1402, -793, 970, -904, -954, 186, -1467, +927, 295, 206, 1679, -950, 555, -810, -1431, +384, -1340, 942, 745, 47, 1761, -1005, 300, +-767, -1605, 498, -1280, 982, 928, -68, 1812, +-1162, 129, -639, -1674, 729, -1104, 837, 988, +-321, 1585, -1053, 52, -355, -1432, 669, -877, +533, 764, -427, 1151, -762, 110, -37, -838, +469, -564, 29, 191, -485, 500, -235, 250, +326, -33, 105, -167, -502, -291, -453, -242, +262, 138, 558, 500, -195, 394, -826, -213, +-423, -653, 555, -472, 559, 329, -308, 951, +-840, 454, -298, -689, 540, -998, 387, -150, +-443, 883, -647, 896, 21, -155, 497, -999, +-28, -555, -575, 653, -370, 826, 319, -183, +405, -831, -313, -134, -603, 886, -121, 466, +354, -809, 119, -1039, -316, 445, -303, 1488, +0, 385, 51, -1273, -166, -1273, -162, 555, +77, 1484, -12, 366, -271, -1099, -151, -805, +44, 667, -67, 835, -188, -377, -77, -1004, +18, 80, -78, 1343, -147, 589, -167, -1147, +-115, -1462, 63, 363, -63, 1782, -304, 707, +-175, -1346, 150, -1489, 191, 588, -136, 1888, +-477, 350, -590, -1850, 43, -1432, 779, 1181, +351, 2290, -696, 208, -985, -2121, -209, -1666, +668, 1042, 643, 2296, -354, 299, -1002, -1921, +-313, -1296, 646, 1157, 492, 1871, -486, -188, +-915, -1907, -206, -942, 699, 1380, 551, 1738, +-565, -332, -958, -1673, -81, -572, 712, 1127, +191, 984, -774, -587, -567, -1173, 479, 89, +685, 1415, -447, 730, -1163, -1165, -208, -1615, +1012, 170, 623, 1801, -878, 1112, -1241, -1009, +13, -1763, 1097, -181, 611, 1640, -809, 1176, +-1358, -842, -209, -1762, 998, -275, 762, 1651, +-462, 1482, -1125, -563, -434, -2010, 542, -878, +548, 1337, -248, 1698, -695, 59, -256, -1436, +297, -945, 377, 586, -229, 1086, -792, 132, +-343, -866, 451, -554, 605, 535, -171, 1002, +-874, 93, -639, -1071, 278, -993, 878, 457, +184, 1485, -995, 664, -986, -972, 220, -1403, +1050, -12, 333, 1243, -933, 747, -992, -591, +68, -882, 860, 214, 284, 723, -753, -26, +-761, -712, 254, -183, 661, 793, -102, 577, +-840, -623, -423, -943, 424, 115, 499, 1160, +-174, 541, -721, -863, -453, -1143, 373, 111, +570, 1353, -301, 859, -980, -816, -183, -1419, +846, -203, 474, 1243, -728, 1005, -1206, -421, +-104, -1115, 1200, -371, 749, 755, -1030, 698, +-1490, -208, 137, -618, 1326, -191, 444, 363, +-1115, 359, -1173, -76, 384, -212, 1243, 41, +48, 81, -1426, -276, -926, -302, 866, 396, +1367, 913, -275, 160, -1649, -1075, -882, -1171, +923, 285, 1261, 1675, -190, 1040, -1310, -933, +-708, -1787, 644, -448, 790, 1342, -373, 1434, +-945, -147, -144, -1397, 735, -873, 285, 663, +-751, 1223, -816, 270, 155, -812, 853, -907, +302, 72, -787, 878, -1054, 652, -52, -280, +962, -825, 709, -386, -515, 428, -1171, 763, +-691, 220, 468, -686, 1076, -752, 314, 296, +-727, 1113, -943, 408, -424, -1015, 297, -1292, +660, 268, 444, 1685, -353, 1042, -851, -939, +-578, -1878, 92, -593, 618, 1326, 419, 1747, +-231, 305, -720, -1387, -542, -1523, 193, -133, +435, 1331, 59, 1343, -406, -43, -197, -1258, +198, -1001, -61, 393, -496, 1082, -384, 359, +212, -673, 603, -655, 187, 445, -503, 902, +-793, -106, -373, -1161, 233, -633, 494, 903, +477, 1305, 1, 169, -754, -1123, -1025, -1044, +-212, 184, 812, 953, 901, 530, -2, -162, +-1074, -388, -950, -233, 314, -156, 977, 78, +174, 376, -908, 277, -779, -157, 376, -537, +997, -176, 201, 606, -1146, 711, -1083, -206, +298, -1085, 1191, -690, 476, 690, -901, 1400, +-1047, 525, 120, -1008, 915, -1385, 167, -196, +-1051, 1023, -705, 1052, 723, 68, 1183, -746, +-230, -690, -1641, -120, -831, 469, 969, 632, +1432, 271, -156, -499, -1563, -952, -866, -99, +830, 1153, 1276, 1056, -154, -554, -1367, -1643, +-815, -733, 599, 1269, 1092, 1728, 148, 101, +-778, -1634, -801, -1302, -84, 672, 475, 1588, +287, 421, -151, -1290, -317, -1076, 17, 810, +196, 1524, -157, 17, -569, -1675, -450, -1117, +415, 1050, 948, 1832, 271, 312, -924, -1469, +-1245, -1258, -218, 366, 1104, 1125, 1120, 403, +-300, -407, -1381, -331, -767, 233, 693, 19, +1001, -588, -76, -252, -1038, 758, -576, 887, +662, -292, 917, -1103, -221, -357, -1331, 668, +-799, 716, 856, -121, 1465, -614, 253, -124, +-1502, 442, -1608, 268, 95, -358, 1639, -471, +1402, 158, -497, 695, -1898, 397, -1294, -568, +575, -1016, 1727, -98, 968, 1130, -673, 1111, +-1624, -266, -1043, -1521, 515, -1185, 1468, 556, +934, 1968, -575, 1424, -1564, -959, -1054, -2615, +577, -1420, 1710, 1702, 813, 3136, -1048, 910, +-1768, -2565, -593, -3130, 1214, 88, 1662, 3297, +123, 2547, -1664, -1379, -1508, -3579, 447, -1300, +1684, 2515, 764, 3171, -982, -25, -1515, -3050, +-174, -2313, 1151, 987, 881, 3010, -530, 1516, +-1182, -1491, -275, -2656, 826, -967, 697, 1841, +-404, 2416, -986, 208, -260, -2140, 626, -1792, +666, 741, -213, 2022, -759, 754, -346, -1179, +310, -1454, 380, 116, -144, 1129, -261, 651, +140, -444, 206, -698, -332, -10, -641, 460, +-92, 67, 751, -397, 751, -167, -380, 566, +-1201, 616, -560, -260, 810, -967, 1003, -658, +-107, 558, -1001, 1292, -520, 632, 562, -712, +690, -1410, -294, -639, -805, 785, -30, 1393, +691, 641, 276, -754, -537, -1208, -661, -511, +105, 463, 739, 895, 321, 590, -677, -48, +-868, -602, 150, -817, 916, -394, 420, 519, +-556, 1287, -842, 762, -243, -860, 497, -1870, +558, -632, 82, 1566, -346, 2149, -446, 17, +-426, -2239, 44, -1733, 637, 843, 623, 2219, +-185, 849, -1082, -1190, -852, -1462, 411, -161, +1416, 883, 886, 620, -982, 2, -1847, -260, +-725, -252, 1415, -161, 2021, 31, 255, 298, +-1930, 153, -1996, -212, 265, -323, 2180, 152, +1534, 535, -849, 169, -2279, -613, -1049, -677, +1285, 165, 2100, 962, 504, 675, -1749, -436, +-1966, -1264, 51, -752, 2004, 850, 1613, 1705, +-752, 707, -2196, -1433, -1113, -2153, 1278, -368, +2095, 2120, 285, 2310, -1883, -193, -1696, -2531, +561, -2005, 2037, 639, 920, 2451, -1281, 1577, +-1936, -843, -283, -2091, 1600, -1089, 1403, 920, +-359, 1634, -1497, 547, -807, -1038, 497, -1088, +897, 266, 320, 1076, -388, 215, -433, -973, +-158, -741, 81, 650, 116, 1351, -1, 255, +-32, -1363, 44, -1317, 159, 405, -139, 1652, +-340, 816, -144, -840, 238, -1312, 396, -269, +81, 771, -401, 692, -549, 2, -40, -270, +559, -28, 501, -144, -72, -393, -557, -369, +-631, 468, -2, 1032, 535, 526, 616, -811, +143, -1485, -528, -418, -822, 1100, -403, 1433, +650, 236, 1022, -982, 160, -986, -870, -191, +-934, 433, 5, 486, 874, 447, 714, 229, +-291, -212, -1000, -731, -436, -592, 531, 91, +813, 742, 122, 735, -737, 30, -722, -531, +115, -655, 871, -308, 535, 280, -608, 659, +-1020, 516, -166, -248, 1000, -710, 969, -357, +-342, 445, -1274, 592, -877, -169, 574, -745, +1452, -131, 732, 912, -720, 753, -1372, -569, +-702, -1390, 419, -454, 1153, 1132, 911, 1427, +-62, 37, -1016, -1343, -1257, -974, -378, 360, +978, 996, 1613, 298, 459, -524, -1293, -332, +-1614, 468, -100, 596, 1329, -489, 1103, -1293, +-422, -479, -1283, 1329, -356, 1942, 941, 243, +865, -1926, -483, -2152, -1289, -3, -545, 1993, +1018, 1797, 1587, 87, 239, -1350, -1507, -1256, +-1704, -392, -155, 263, 1447, 512, 1729, 851, +458, 1130, -1312, 342, -1834, -1505, -887, -2450, +806, -1043, 1896, 2026, 1464, 3508, -396, 1475, +-1955, -2319, -1794, -3951, -147, -1667, 1613, 2151, +2129, 3726, 727, 1903, -1372, -1553, -2275, -3317, +-1081, -2022, 822, 897, 2141, 2729, 1638, 1955, +-436, -298, -2285, -1974, -1937, -1845, 420, -196, +2350, 1444, 1803, 1689, -699, 340, -2271, -1211, +-1280, -1356, 829, -153, 1840, 1007, 913, 1005, +-743, 27, -1523, -934, -881, -898, 457, -20, +1348, 957, 1116, 1108, -100, 208, -1573, -985, +-1530, -1548, 103, -719, 1635, 913, 1497, 2113, +-15, 1594, -1312, -751, -1340, -2818, -286, -2474, +608, 507, 892, 3361, 834, 3162, 496, -303, +-506, -3533, -1740, -3295, -1670, 191, 341, 3102, +2592, 2661, 2515, 92, -393, -1960, -3079, -1731, +-2738, -511, 198, 474, 2830, 827, 2833, 993, +332, 823, -2312, -137, -2894, -1370, -1004, -1604, +1726, -252, 2914, 1503, 1562, 1899, -1256, 336, +-2884, -1573, -1806, -1756, 995, -28, 2634, 1647, +1593, 1178, -819, -647, -2126, -1424, -1137, -238, +653, 1116, 1381, 757, 514, -531, -517, -885, +-432, 37, 120, 743, 63, 117, -564, -761, +-405, -282, 492, 895, 1105, 1065, 525, -430, +-879, -1630, -1474, -983, -503, 751, 1117, 1775, +1538, 1054, 370, -480, -1060, -1573, -1435, -1395, +-336, -134, 995, 1250, 1108, 1712, 220, 736, +-703, -859, -643, -1694, -131, -995, 366, 347, +85, 1086, -166, 832, 239, 327, 806, 85, +191, -354, -1146, -1195, -1398, -1520, 42, -140, +1878, 2217, 1820, 2667, -333, 136, -2563, -2863, +-1932, -2880, 938, 225, 2714, 2731, 1532, 2144, +-1153, -514, -2422, -1888, -1040, -1009, 1212, 586, +1776, 827, 330, 18, -973, -559, -694, -122, +281, 760, 383, 654, -398, -357, -709, -1219, +253, -710, 1423, 680, 989, 1400, -890, 631, +-2132, -996, -1105, -1579, 1202, -135, 2519, 1670, +1313, 1533, -1334, -843, -2649, -2464, -1237, -978, +1226, 1920, 2195, 2643, 1114, 218, -650, -2335, +-1411, -2007, -946, 317, -93, 1687, 424, 872, +734, -401, 945, -249, 549, 485, -500, 22, +-1374, -1274, -1288, -1531, -62, 262, 1494, 2234, +1903, 2073, 756, -53, -1243, -2147, -2111, -2195, +-1304, -748, 618, 1009, 1965, 2099, 1674, 1884, +226, 460, -1277, -1667, -1785, -2762, -1129, -1741, +445, 785, 1738, 2916, 1717, 2638, 409, 270, +-1297, -2326, -2005, -2958, -970, -1061, 862, 1383, +1838, 2243, 1129, 1217, -428, -101, -1255, -739, +-782, -898, 221, -1049, 551, -892, -3, 114, +-176, 1570, 352, 2154, 744, 926, 275, -1297, +-703, -2673, -1179, -1974, -693, 422, 549, 2480, +1444, 2591, 1288, 594, 33, -1665, -1383, -2500, +-1762, -1311, -607, 689, 1091, 1615, 1801, 1184, +1037, 284, -260, -21, -1211, -391, -1347, -1109, +-710, -1634, 341, -729, 1454, 1473, 1721, 2817, +733, 1697, -1297, -1235, -2497, -3109, -1551, -2199, +1117, 483, 2816, 2432, 1933, 2200, -716, 466, +-2570, -1079, -1863, -1692, 394, -1364, 1989, -379, +1430, 921, -171, 1812, -1110, 1503, -665, -141, +148, -1736, 242, -1851, -152, -452, -208, 1079, +558, 1446, 915, 876, 253, -42, -939, -664, +-1269, -1079, -387, -1073, 1008, -111, 1526, 1352, +548, 1774, -930, 373, -1447, -1536, -535, -1718, +918, -145, 1260, 1514, 220, 1161, -906, -553, +-689, -1311, 452, -116, 775, 1265, -10, 802, +-823, -860, -604, -1595, 493, -274, 1191, 1447, +613, 1516, -678, -163, -1322, -1539, -608, -1107, +650, 409, 1296, 1267, 759, 660, -473, -584, +-1147, -961, -545, -159, 433, 805, 678, 674, +130, -332, -263, -975, 23, -379, 428, 699, +221, 829, -616, 85, -942, -536, -170, -383, +1132, -86, 1313, -60, 23, -65, -1189, 277, +-1061, 737, 138, 439, 878, -499, 531, -1190, +-222, -684, -301, 478, 226, 1204, 518, 876, +-93, -97, -1014, -825, -934, -976, 379, -615, +1736, 153, 1509, 1127, -397, 1430, -2104, 413, +-1798, -1222, 338, -1952, 2050, -782, 1789, 1236, +-24, 2025, -1475, 730, -1394, -1180, -169, -1494, +722, -220, 703, 871, 397, 541, 257, -450, +41, -487, -545, 561, -871, 1084, -438, 97, +481, -1485, 1116, -1425, 764, 356, -247, 1877, +-981, 1271, -726, -739, 44, -1572, 581, -596, +684, 750, 315, 813, -247, -161, -494, -607, +-356, 35, -61, 752, 284, 425, 576, -659, +431, -970, -246, -203, -769, 730, -492, 755, +392, 80, 940, -426, 574, -236, -438, 154, +-1001, -21, -473, -553, 485, -644, 826, 383, +527, 1569, -95, 1286, -511, -745, -627, -2470, +-318, -1632, 249, 1031, 689, 2571, 793, 1487, +207, -796, -639, -1751, -1030, -1018, -444, 13, +473, 319, 982, 416, 682, 973, -27, 1244, +-607, 120, -594, -1708, -373, -2385, -116, -672, +446, 1933, 1081, 2855, 899, 1147, -370, -1626, +-1475, -2705, -1252, -1323, 368, 998, 1606, 1978, +1228, 1123, -336, -313, -1176, -914, -649, -622, +133, -209, 424, -119, 304, -37, 315, 499, +192, 872, -245, 469, -479, -599, -223, -1079, +396, -438, 547, 519, -38, 719, -606, 10, +-402, -427, 512, -70, 951, 597, 352, 509, +-734, -477, -1187, -1183, -494, -781, 789, 651, +1464, 1560, 864, 1037, -546, -409, -1510, -1389, +-1161, -1017, 228, -245, 1526, 461, 1273, 899, +-99, 1162, -1038, 712, -767, -727, 9, -1922, +357, -1499, 140, 466, -31, 2048, 384, 1637, +782, -133, 256, -1385, -1036, -1201, -1436, -282, +-243, 357, 1422, 442, 1727, 474, 239, 531, +-1381, 392, -1395, -250, -23, -1061, 1040, -1116, +808, -180, -67, 1154, -465, 1446, -188, 399, +267, -832, 152, -1124, -197, -402, -324, 224, +-20, 332, 387, 282, 490, 332, 164, 345, +-383, -28, -475, -461, -112, -572, 303, -404, +386, -66, 74, 490, -130, 967, -94, 738, +81, -251, 120, -1243, -22, -1190, -158, -135, +-235, 1057, 42, 1309, 425, 497, 498, -544, +34, -1032, -444, -699, -573, -23, -196, 521, +373, 619, 687, 337, 426, 2, -175, -166, +-532, -240, -397, -425, 4, -538, 275, -157, +235, 669, 201, 1169, 342, 666, 125, -603, +-433, -1581, -804, -1075, -289, 416, 670, 1499, +1053, 1128, 460, -36, -568, -899, -1002, -1011, +-459, -510, 437, 263, 913, 850, 380, 824, +-313, 82, -459, -636, -51, -602, 164, 0, +-21, 172, -115, -171, 140, -151, 361, 580, +244, 953, -111, 79, -480, -1293, -265, -1283, +147, 307, 511, 1547, 261, 954, -89, -719, +-243, -1228, -67, -252, 93, 850, -14, 653, +-104, -391, 106, -799, 337, -186, 200, 693, +-142, 732, -320, -12, -147, -725, 146, -708, +286, 13, 206, 591, -63, 574, -123, 48, +-47, -369, 8, -396, 96, 12, 43, 227, +15, 119, -98, -184, 64, -233, 239, 76, +154, 451, -107, 513, -319, -119, -120, -885, +184, -880, 382, 159, 177, 1176, -94, 1066, +-241, -92, -143, -1167, 101, -1045, 145, 16, +153, 885, 15, 728, -31, -66, -29, -389, +43, -104, 48, 152, 62, -183, -40, -515, +-123, -250, -74, 504, 207, 957, 407, 494, +111, -629, -209, -1247, -367, -629, -205, 686, +95, 1171, 408, 402, 472, -553, 187, -672, +-211, -12, -563, 247, -558, -62, 98, -260, +812, 182, 791, 562, 65, 219, -618, -400, +-723, -545, -269, -134, 384, 246, 664, 297, +526, 109, 84, 28, -468, -72, -698, -122, +-276, -171, 545, -33, 718, 87, 153, 75, +-348, 31, -309, 29, 145, 96, 156, 16, +-49, -170, -222, -166, 71, -78, 370, 102, +233, 145, 64, 158, -149, 60, -330, -103, +-335, -125, 66, -167, 558, -159, 594, 25, +99, 355, -430, 391, -634, -51, -192, -464, +406, -279, 534, 127, 153, 245, -92, -119, +5, -215, 63, 314, -186, 669, -464, 130, +-338, -923, 390, -1154, 1152, 9, 806, 1415, +-455, 1441, -1499, -232, -1031, -1781, 433, -1250, +1578, 678, 1215, 1645, -130, 504, -1188, -1099, +-1088, -963, -110, 565, 693, 1247, 887, -11, +373, -1540, -174, -1108, -301, 901, -264, 2008, +-151, 858, -191, -1325, 34, -2009, 411, -621, +600, 1224, 449, 1616, -218, 463, -741, -792, +-678, -955, -67, -349, 641, 185, 921, 259, +518, 211, -237, 360, -798, 258, -654, -107, +-69, -527, 396, -527, 621, -54, 571, 322, +282, 431, -262, 329, -840, 212, -771, -130, +-57, -755, 913, -876, 1184, -51, 502, 1131, +-539, 1271, -1243, 131, -870, -1279, 305, -1341, +1201, -147, 1075, 1179, 62, 1159, -869, 14, +-933, -899, -157, -738, 664, 125, 662, 492, +95, 256, -221, -154, -57, -228, 100, 29, +-88, 253, -332, 190, -158, -206, 391, -472, +676, -279, 250, 313, -396, 702, -587, 422, +-251, -391, 297, -905, 545, -503, 429, 460, +-35, 983, -399, 481, -486, -509, -61, -975, +590, -365, 597, 543, -95, 935, -646, 271, +-265, -732, 418, -994, 580, -26, 64, 1140, +-395, 935, -403, -530, 101, -1445, 462, -572, +343, 1069, -92, 1392, -334, -44, -72, -1302, +184, -851, 171, 607, -105, 1043, -224, 60, +153, -822, 553, -501, 373, 624, -374, 852, +-884, -207, -377, -1136, 678, -597, 1110, 874, +517, 1248, -642, 78, -1108, -1200, -384, -914, +600, 386, 882, 1084, 280, 355, -228, -647, +-311, -674, -76, 133, 31, 676, -153, 227, +-184, -487, 323, -538, 712, 123, 415, 593, +-438, 315, -852, -293, -359, -459, 444, -109, +803, 268, 347, 233, -319, -77, -342, -150, +-6, 43, 139, 160, -36, 41, -190, -198, +47, -267, 389, -97, 529, 268, 98, 589, +-576, 212, -652, -527, -99, -899, 589, -192, +711, 889, 237, 997, -257, -22, -473, -1089, +-341, -920, -7, 287, 392, 1114, 534, 662, +197, -500, -316, -978, -369, -345, 34, 577, +337, 680, 99, 82, -282, -443, -179, -321, +347, -9, 605, 70, 62, 77, -559, 222, +-499, 312, 93, -43, 489, -544, 374, -580, +137, 120, -96, 777, -190, 657, -283, -207, +-114, -767, 112, -543, 328, 26, 456, 480, +219, 535, -315, 329, -611, -176, -203, -647, +366, -625, 534, -57, 201, 720, -94, 828, +-219, 54, -86, -743, -18, -666, -60, 95, +-31, 503, 267, 211, 472, -121, 186, -55, +-348, 95, -585, -27, -187, -266, 451, -151, +708, 167, 176, 261, -472, 87, -445, -154, +62, -166, 465, -73, 246, 39, -187, 255, +-351, 216, 13, -202, 440, -649, 398, -287, +-137, 773, -495, 1063, -298, -12, 268, -1374, +556, -1154, 260, 493, -250, 1606, -391, 775, +48, -861, 341, -1166, 39, -68, -322, 752, +-160, 169, 457, -479, 619, -121, -58, 761, +-697, 675, -596, -504, 299, -1274, 826, -647, +435, 769, -287, 1364, -535, 557, -186, -661, +253, -1132, 301, -519, 74, 378, -128, 771, +-40, 414, 101, -128, 156, -357, 66, -184, +-144, -39, -262, -60, -51, -30, 328, 134, +435, 250, 101, 113, -327, -91, -386, -162, +15, -88, 346, -61, 201, -78, -111, -40, +-103, 158, 286, 293, 285, 246, -196, -28, +-592, -391, -275, -597, 469, -317, 817, 420, +418, 968, -433, 631, -795, -400, -448, -1102, +271, -783, 719, 235, 619, 942, 84, 733, +-453, -41, -684, -546, -288, -447, 358, -90, +639, 16, 371, -18, -102, 143, -311, 465, +-225, 460, -76, -81, 4, -664, 68, -722, +275, -173, 385, 508, 203, 793, -298, 527, +-538, -172, -208, -730, 252, -728, 438, -150, +245, 435, 74, 592, -59, 347, -150, 64, +-271, -153, -304, -395, 0, -637, 496, -517, +690, 301, 328, 1204, -406, 1119, -883, -229, +-608, -1565, 283, -1343, 1022, 202, 827, 1445, +-54, 1157, -792, -133, -722, -962, -93, -683, +445, 50, 497, 282, 262, 36, 111, 45, +-34, 454, -350, 488, -511, -231, -216, -947, +387, -623, 735, 410, 439, 946, -280, 417, +-608, -437, -339, -568, 176, 9, 361, 313, +174, -53, 8, -448, 0, -58, 122, 694, +-14, 667, -241, -286, -268, -1039, 53, -560, +349, 551, 331, 915, 51, 174, -150, -569, +-172, -383, -65, 256, -47, 276, -112, -319, +32, -475, 461, 196, 588, 860, -1, 392, +-751, -705, -735, -981, 8, -16, 746, 943, +820, 609, 249, -384, -468, -746, -741, -112, +-367, 538, 135, 358, 515, -260, 611, -484, +341, -40, -195, 446, -682, 359, -694, -184, +-110, -509, 810, -212, 1080, 360, 268, 532, +-848, 45, -1037, -537, -195, -551, 688, 117, +853, 712, 311, 527, -332, -272, -590, -825, +-356, -457, 27, 392, 398, 746, 570, 285, +247, -390, -362, -413, -593, -47, -150, 145, +359, -18, 401, -81, 53, 122, -119, 294, +-35, 195, 26, -194, -109, -484, -244, -344, +56, 214, 394, 571, 374, 310, -138, -200, +-466, -358, -178, -89, 219, 48, 337, -75, +37, -147, -142, 106, -8, 448, 130, 421, +-2, -108, -186, -735, -57, -732, 177, 62, +163, 883, 26, 884, -15, 2, -10, -825, +-88, -787, -121, -26, -3, 549, 169, 424, +261, 23, 162, -47, -214, 64, -379, -132, +-94, -510, 343, -418, 426, 287, 57, 833, +-361, 513, -355, -375, 96, -837, 440, -455, +239, 351, -181, 692, -381, 279, -151, -363, +300, -465, 538, 35, 125, 411, -555, 126, +-618, -375, 155, -372, 838, 215, 569, 550, +-363, 197, -936, -371, -414, -441, 619, -56, +937, 258, 178, 244, -644, 57, -640, -65, +27, -115, 492, -112, 367, -80, -47, 97, +-191, 202, -45, 42, 43, -212, -81, -211, +-102, 162, 88, 357, 240, 59, 152, -398, +-22, -383, -117, 190, -146, 515, -142, 195, +-46, -403, 208, -420, 435, 140, 317, 502, +-253, 117, -664, -515, -418, -424, 279, 323, +769, 729, 564, 148, -153, -667, -759, -637, +-610, 203, 165, 730, 699, 216, 473, -521, +-69, -435, -348, 345, -226, 612, -42, -64, +-18, -758, 3, -548, 249, 413, 454, 979, +144, 537, -431, -538, -591, -1128, -146, -583, +502, 583, 628, 1160, 133, 480, -386, -596, +-405, -888, -83, -206, 150, 452, 159, 359, +194, -103, 219, -177, 40, 238, -290, 325, +-428, -219, -69, -694, 397, -295, 501, 563, +112, 739, -310, 50, -388, -610, -131, -421, +198, 138, 281, 316, 193, 31, 63, -110, +-92, 76, -311, 156, -255, -66, 69, -310, +396, -145, 416, 262, 42, 370, -408, -6, +-478, -418, -43, -325, 390, 184, 417, 534, +147, 257, -158, -363, -301, -594, -290, -126, +-53, 442, 293, 458, 437, 29, 205, -295, +-189, -242, -396, -36, -267, 61, 38, 46, +309, 39, 367, 119, 186, 141, -149, 15, +-354, -208, -311, -295, 20, -95, 370, 203, +395, 286, 48, 122, -253, -36, -232, -48, +-42, -129, 97, -340, 61, -320, -1, 225, +125, 803, 240, 554, 53, -438, -275, -1011, +-353, -480, -75, 495, 293, 843, 428, 291, +199, -404, -178, -493, -372, 16, -252, 329, +60, -16, 288, -436, 290, -178, 82, 562, +-173, 749, -200, -29, -57, -908, 108, -784, +99, 191, -76, 863, -114, 525, 192, -206, +445, -406, 96, -110, -563, 14, -707, -235, +34, -243, 887, 257, 845, 735, -124, 492, +-953, -396, -728, -1031, 192, -655, 799, 440, +531, 1086, -91, 587, -369, -421, -303, -825, +-109, -334, 40, 297, 205, 378, 304, 2, +174, -133, -121, 132, -331, 283, -144, -47, +149, -493, 169, -408, -19, 158, -22, 593, +171, 386, 195, -174, -119, -452, -398, -254, +-255, 88, 247, 187, 623, 104, 268, 17, +-407, 39, -574, 13, -84, -97, 473, -117, +449, -21, -49, 71, -502, 6, -289, -47, +321, 26, 545, 207, 134, 234, -396, -131, +-529, -544, -152, -471, 404, 247, 730, 867, +352, 647, -454, -302, -909, -1049, -454, -781, +547, 272, 1089, 1101, 464, 831, -680, -235, +-930, -1051, -148, -760, 627, 243, 526, 867, +-65, 543, -337, -235, -102, -585, 224, -275, +85, 215, -180, 270, -151, -40, 140, -147, +215, 131, -9, 261, -56, -128, 89, -477, +75, -208, -170, 435, -300, 574, -3, 13, +425, -569, 427, -514, -93, 97, -493, 553, +-286, 448, 196, -86, 371, -498, 122, -410, +-178, 24, -122, 372, 109, 365, 147, 86, +-39, -205, -219, -282, -142, -220, 132, -73, +343, 197, 231, 452, -108, 336, -373, -233, +-271, -670, 136, -432, 373, 305, 213, 755, +-118, 372, -203, -384, 6, -660, 149, -159, +-20, 405, -282, 375, -139, -90, 344, -329, +611, -46, 130, 332, -659, 253, -697, -285, +38, -596, 729, -144, 596, 643, -66, 762, +-493, -80, -335, -883, 43, -683, 135, 269, +67, 854, 140, 490, 295, -312, 172, -694, +-306, -292, -597, 300, -188, 425, 498, 101, +671, -164, 78, -162, -506, -69, -384, -9, +118, 47, 326, 116, 41, 112, -222, -9, +-27, -186, 333, -218, 260, 21, -256, 292, +-519, 318, -103, -26, 443, -409, 512, -427, +-42, 21, -494, 517, -285, 504, 271, -29, +417, -526, 16, -472, -359, 1, -284, 366, +190, 372, 431, 155, 259, -110, -206, -325, +-449, -330, -285, -99, 150, 291, 500, 463, +380, 195, -78, -275, -450, -462, -303, -130, +136, 208, 249, 240, 52, 40, -69, -31, +145, 18, 291, -16, -45, -142, -505, -186, +-440, 27, 156, 230, 661, 228, 529, -31, +-91, -213, -567, -156, -491, 12, -56, 99, +333, 23, 466, 50, 269, 106, -93, 36, +-342, -176, -320, -219, -59, 65, 214, 249, +205, 102, 56, -195, 122, -152, 178, 163, +-108, 216, -520, -137, -394, -360, 256, -10, +753, 411, 498, 295, -344, -284, -797, -473, +-298, 8, 465, 506, 522, 263, -37, -394, +-316, -495, -82, 124, 251, 587, 232, 270, +-225, -363, -440, -491, -73, -78, 429, 291, +423, 293, 15, 155, -298, -12, -310, -262, +-54, -434, 123, -130, 125, 446, 109, 594, +211, 28, 153, -600, -192, -500, -495, 193, +-307, 575, 253, 193, 657, -361, 474, -320, +-207, 166, -730, 301, -476, -69, 227, -323, +629, -41, 390, 354, -133, 233, -396, -266, +-248, -450, 68, -33, 221, 479, 135, 418, +-48, -154, -73, -565, 54, -361, 133, 234, +-13, 574, -234, 355, -256, -241, 146, -601, +522, -295, 287, 327, -359, 494, -639, 28, +-110, -346, 584, -73, 571, 329, -159, 80, +-656, -554, -267, -465, 454, 486, 511, 1035, +-84, 184, -511, -1070, -157, -1027, 392, 366, +332, 1334, -227, 550, -486, -880, 47, -1131, +581, 114, 368, 1140, -392, 617, -714, -686, +-155, -1078, 623, -64, 764, 976, 18, 800, +-724, -288, -644, -981, 100, -537, 659, 429, +468, 851, -109, 314, -429, -485, -182, -639, +106, -53, 109, 446, -70, 258, -24, -174, +260, -203, 285, 155, -94, 208, -478, -158, +-337, -412, 174, -91, 544, 465, 357, 505, +-126, -99, -420, -651, -327, -441, -22, 248, +245, 655, 350, 368, 224, -253, -83, -604, +-378, -335, -333, 285, 5, 519, 383, 145, +452, -294, 75, -212, -436, 128, -475, 80, +20, -244, 452, -222, 388, 264, -65, 565, +-405, 177, -252, -538, 220, -723, 367, -117, +26, 682, -326, 748, -207, 17, 220, -669, +360, -615, 12, 47, -379, 493, -237, 399, +232, 27, 362, -226, -16, -272, -273, -179, +-123, 53, 191, 275, 181, 229, -118, -32, +-279, -212, 50, -196, 395, -15, 160, 146, +-276, 175, -339, 51, -3, -96, 258, -125, +220, -78, -20, 12, -176, 114, -78, 151, +54, 56, 65, -132, -3, -231, -48, -75, +-22, 180, 42, 258, 137, 98, 91, -164, +-130, -291, -281, -198, -80, 176, 264, 452, +367, 201, 17, -330, -330, -482, -258, -33, +90, 425, 263, 305, 49, -157, -135, -339, +-76, -54, 188, 247, 160, 138, -180, -135, +-317, -178, -54, 18, 351, 177, 341, 94, +-59, -69, -403, -107, -245, -61, 227, 6, +324, 33, 2, 86, -275, 101, -76, -1, +257, -116, 191, -179, -142, -77, -318, 180, +-90, 298, 206, 63, 260, -316, 69, -321, +-76, 105, -86, 382, -112, 167, -197, -266, +-67, -321, 309, 27, 478, 332, 73, 224, +-490, -123, -543, -360, -15, -187, 535, 215, +458, 389, -85, 127, -396, -277, -92, -361, +147, -55, -58, 286, -206, 303, 46, -54, +392, -312, 342, -144, -147, 221, -517, 277, +-340, -140, 199, -455, 441, -83, 222, 591, +1, 464, -167, -404, -283, -775, -286, -50, +68, 659, 448, 439, 335, -225, -92, -460, +-379, -91, -175, 208, 92, 148, 99, -118, +21, -143, 110, 142, 182, 316, -72, 52, +-317, -487, -196, -535, 222, 231, 438, 890, +93, 436, -475, -690, -442, -928, 281, 33, +657, 877, 102, 464, -591, -441, -448, -508, +241, 143, 552, 324, 223, -143, -305, -281, +-447, 142, -53, 354, 347, 49, 260, -268, +-142, -218, -262, 16, 35, 121, 164, 120, +49, 77, -36, 27, -11, -79, -78, -196, +-129, -141, 46, 124, 167, 299, 144, 123, +60, -234, -200, -285, -347, 42, -18, 301, +372, 189, 279, -246, -104, -435, -175, 31, +-142, 606, -112, 382, 43, -475, 180, -692, +161, 24, 13, 580, -51, 352, -143, -172, +-135, -276, -7, -70, 70, 8, 85, -81, +175, 11, 147, 280, -182, 216, -387, -220, +-114, -352, 322, 35, 398, 284, 20, 36, +-394, -242, -353, -68, 203, 294, 474, 275, +19, -204, -452, -483, -207, -145, 306, 456, +310, 416, -1, -202, -251, -444, -211, 47, +114, 439, 218, -44, -114, -559, -243, -155, +159, 601, 443, 603, 49, -284, -445, -811, +-456, -352, 75, 536, 573, 760, 359, 35, +-260, -652, -428, -519, -5, 245, 207, 638, +-18, 200, -152, -478, 46, -503, 279, 135, +239, 563, -151, 250, -516, -329, -250, -418, +323, -11, 369, 302, -3, 156, -83, -112, +48, -91, -35, 112, -168, 86, -175, -170, +-154, -290, 136, -55, 583, 343, 437, 491, +-334, 81, -822, -580, -455, -713, 311, 23, +771, 833, 554, 714, -196, -244, -618, -861, +-446, -469, -23, 362, 202, 621, 356, 172, +361, -286, 66, -273, -294, 19, -472, 132, +-250, -8, 186, -119, 507, -3, 307, 167, +-230, 164, -416, -43, -61, -215, 188, -198, +70, 14, -61, 244, -5, 214, 68, -71, +52, -244, 53, -70, -64, 164, -202, 75, +-114, -115, 100, -66, 229, 99, 49, 89, +-105, -110, -85, -73, 94, 167, 99, 195, +-188, -193, -351, -501, 14, -120, 556, 584, +397, 709, -239, -82, -587, -916, -300, -651, +205, 368, 436, 844, 275, 231, -56, -390, +-196, -208, -209, 128, -231, -123, -75, -500, +248, -91, 460, 694, 194, 833, -243, -54, +-502, -985, -292, -867, 271, 143, 482, 963, +145, 688, -287, -182, -228, -666, -16, -385, +35, 206, 132, 263, 142, -78, -74, -152, +-239, 279, -59, 463, 199, -112, 171, -652, +18, -427, -114, 252, -329, 564, -250, 317, +275, -97, 659, -334, 265, -306, -563, -81, +-750, 152, -66, 216, 664, 165, 516, 102, +-213, -71, -422, -362, -106, -374, 201, 206, +138, 597, -116, 216, -283, -394, 29, -483, +489, -11, 247, 367, -318, 361, -529, -33, +-170, -392, 235, -278, 446, 79, 284, 339, +-118, 290, -282, -63, -362, -414, -237, -316, +280, 256, 577, 513, 98, 28, -432, -540, +-195, -306, 145, 442, 100, 624, -114, -144, +-198, -781, 38, -405, 413, 516, 276, 856, +-345, 126, -561, -735, -83, -673, 397, 227, +351, 673, -30, 166, -303, -324, -41, -187, +216, 119, -25, 48, -354, -114, -197, -62, +326, 100, 446, 145, 107, -6, -331, -127, +-426, -120, -80, 90, 267, 206, 226, -43, +-37, -351, -46, -138, 157, 479, -23, 449, +-422, -341, -293, -735, 309, -57, 498, 760, +86, 496, -246, -486, -258, -735, -125, 17, +65, 654, 111, 416, -15, -214, 60, -563, +223, -358, -1, 293, -342, 636, -213, 126, +118, -476, 278, -285, 163, 254, -231, 171, +-331, -314, 161, -279, 473, 422, -71, 744, +-613, -69, -260, -988, 440, -643, 636, 535, +103, 963, -634, 251, -611, -570, 127, -701, +596, 27, 297, 648, -262, 248, -376, -543, +-26, -451, 318, 543, 113, 844, -381, -127, +-298, -1131, 269, -763, 498, 798, 78, 1398, +-463, 169, -420, -1315, 40, -1030, 410, 628, +298, 1389, -63, 208, -371, -1327, -242, -1009, +200, 873, 265, 1627, -71, 86, -263, -1669, +-52, -1237, 209, 853, 235, 1831, -6, 387, +-425, -1456, -311, -1252, 244, 586, 443, 1424, +84, 254, -359, -1204, -285, -929, 83, 728, +265, 1468, 14, 156, -188, -1535, 8, -1187, +106, 739, -20, 1767, -99, 474, -111, -1389, +-52, -1291, 97, 444, 228, 1394, 11, 363, +-225, -1000, -175, -881, -33, 398, 199, 1137, +199, 314, -59, -956, -209, -909, -162, 264, +-44, 992, 144, 407, 334, -557, 83, -610, +-448, 158, -391, 549, 116, -63, 453, -632, +344, -91, -272, 737, -612, 586, -191, -434, +453, -960, 464, -254, -54, 778, -449, 751, +-394, -265, 229, -763, 589, -140, 53, 601, +-658, 399, -507, -382, 350, -734, 775, -33, +311, 903, -667, 707, -877, -471, -49, -1128, +791, -410, 681, 797, -181, 1008, -697, 53, +-464, -909, 145, -666, 427, 372, 271, 759, +-27, 102, -293, -648, -217, -433, 75, 487, +109, 800, -97, -70, -63, -991, 144, -633, +20, 620, -120, 1092, -36, 216, 89, -844, +-38, -805, -177, 158, -117, 742, 93, 350, +229, -342, 118, -514, -121, 26, -263, 560, +-238, 341, -65, -476, 170, -831, 363, -2, +271, 1008, -161, 806, -567, -531, -401, -1216, +129, -274, 387, 896, 328, 683, 132, -338, +-208, -547, -488, 72, -271, 440, 109, 60, +234, -500, 156, -514, 197, 207, 11, 1043, +-309, 700, -352, -681, -230, -1581, 107, -607, +433, 1322, 445, 1746, -101, 46, -546, -1754, +-321, -1246, 15, 740, 185, 1519, 137, 231, +87, -1188, 82, -719, 12, 773, -190, 1120, +-440, -228, -227, -1405, 309, -722, 549, 1035, +166, 1642, -449, 120, -473, -1672, -59, -1324, +320, 693, 198, 1756, -157, 503, -200, -1260, +81, -1269, 238, 355, -40, 1458, -363, 510, +-209, -1153, 99, -1195, 233, 517, 87, 1545, +-98, 316, -33, -1390, 33, -1131, -95, 819, +-393, 1596, -254, 42, 380, -1587, 701, -937, +185, 1120, -739, 1544, -881, -244, 88, -1709, +844, -715, 448, 1306, -443, 1369, -527, -488, +69, -1559, 390, -313, 48, 1285, -568, 944, +-479, -837, 471, -1387, 926, 234, 70, 1707, +-1007, 672, -721, -1639, 338, -1712, 751, 833, +260, 2399, -479, 506, -544, -2194, 150, -1787, +586, 1163, 3, 2424, -769, 257, -418, -2187, +578, -1606, 795, 1161, 11, 2332, -855, 369, +-674, -2048, 287, -1723, 697, 881, 136, 2125, +-399, 579, -225, -1519, 36, -1494, 70, 400, +7, 1518, -67, 635, -129, -889, -14, -1048, +37, 33, 2, 695, 152, 392, 141, -34, +-290, -46, -555, -91, -76, -511, 442, -638, +481, 197, 111, 1281, -430, 1124, -695, -679, +-198, -2000, 513, -1014, 454, 1234, -33, 2050, +-389, 436, -146, -1324, 179, -1229, 7, 15, +-381, 595, -258, 157, 404, 54, 528, 464, +15, 534, -602, -306, -681, -1312, 169, -894, +737, 624, 245, 1691, -515, 861, -497, -885, +108, -1446, 405, -344, 248, 856, -374, 496, +-670, -374, -9, -189, 619, 747, 463, 603, +-211, -799, -637, -1372, -416, -271, 106, 1243, +440, 1275, 201, -156, 58, -1109, -7, -518, +-480, 479, -640, 248, 11, -495, 742, -214, +681, 869, -239, 985, -960, -412, -627, -1599, +542, -801, 910, 1101, -73, 1551, -823, 17, +-486, -1402, 510, -806, 845, 922, -26, 1197, +-1102, -345, -824, -1548, 613, -503, 1221, 1349, +233, 1435, -996, -296, -895, -1571, 241, -868, +775, 772, 157, 1246, -585, 52, -311, -950, +394, -399, 362, 673, -300, 614, -708, -419, +5, -833, 659, -122, 299, 780, -567, 599, +-695, -410, 235, -701, 831, 54, 420, 786, +-831, 374, -1277, -927, -2, -1113, 1303, 212, +976, 1718, -445, 1164, -1248, -924, -678, -1931, +383, -794, 919, 1212, 239, 1616, -575, 112, +-424, -1127, 176, -711, 350, 622, 12, 747, +-608, -445, -558, -1133, 334, -294, 1047, 1334, +249, 1531, -907, -251, -825, -1752, 60, -1353, +668, 464, 372, 1570, -451, 875, -523, -440, +283, -937, 705, -193, -56, 288, -1023, -69, +-832, -357, 409, 40, 1419, 783, 755, 801, +-1010, -239, -1563, -1283, -319, -999, 1062, 414, +1017, 1356, -258, 839, -849, -389, -258, -880, +425, -520, 115, 44, -540, 99, -233, 237, +421, 722, 565, 592, -59, -400, -688, -1364, +-499, -843, 186, 776, 463, 1641, 20, 554, +-246, -1178, 83, -1324, 269, 119, -191, 1091, +-768, 657, -508, -471, 659, -925, 1210, -63, +142, 752, -1179, 539, -1157, -345, 76, -517, +1102, -82, 750, 76, -419, -69, -884, 96, +-58, 651, 421, 610, -109, -640, -587, -1533, +-41, -626, 854, 1415, 828, 2039, -621, 178, +-1597, -2125, -690, -2065, 1083, 568, 1594, 2629, +273, 1502, -1295, -1384, -1397, -2516, -21, -775, +1022, 1799, 719, 2181, -107, 145, -472, -1920, +-264, -1598, -112, 266, -489, 1465, -292, 1031, +809, -171, 1294, -853, 26, -658, -1611, -144, +-1634, 186, 76, 501, 1882, 552, 1817, 130, +-318, -367, -2211, -564, -1812, -373, 389, 67, +2014, 453, 1525, 479, -408, 189, -1746, -33, +-1314, -376, 168, -739, 1115, -549, 978, 462, +271, 1385, -731, 984, -1114, -737, -660, -1985, +408, -1082, 1030, 1149, 734, 2227, -141, 934, +-1041, -1381, -1047, -2294, -118, -705, 928, 1670, +997, 2082, 94, 143, -766, -1677, -750, -1366, +-277, 403, 192, 1245, 262, 357, 219, -731, +398, -427, 354, 671, -383, 756, -1436, -446, +-1053, -1492, 847, -679, 2078, 1341, 1077, 2035, +-1300, 277, -2517, -2027, -1038, -2045, 1702, 319, +2562, 2260, 336, 1633, -2269, -897, -2145, -2244, +483, -848, 2367, 1392, 1145, 1897, -1378, 122, +-1960, -1839, -209, -1509, 1432, 769, 1110, 2172, +-388, 724, -1346, -1585, -492, -1807, 864, 28, +869, 1777, -542, 1452, -1172, -529, -93, -1904, +1086, -1205, 783, 1038, -578, 2086, -1241, 824, +-365, -1368, 740, -2087, 666, -630, -176, 1440, +-449, 2121, -89, 664, 221, -1505, 20, -2212, +-481, -603, -417, 1748, 201, 2165, 612, 41, +376, -2075, -147, -1525, -630, 898, -659, 2116, +-104, 474, 365, -1873, 536, -1870, 468, 649, +-74, 2703, -819, 1435, -771, -1779, 55, -3041, +628, -775, 536, 2489, 16, 2888, -558, 44, +-583, -2868, 104, -2305, 635, 995, 289, 2775, +-587, 1088, -956, -1767, -195, -2257, 1079, 58, +1251, 2257, -101, 1711, -1482, -898, -1597, -2433, +-106, -1276, 1652, 1141, 1819, 2265, 80, 1199, +-1832, -787, -1694, -1877, -29, -1400, 1380, -111, +1080, 1280, -191, 1970, -691, 1259, -303, -802, +11, -2564, -230, -2210, -533, 348, 115, 2936, +995, 2903, 918, 2, -476, -2961, -1588, -3159, +-1069, -338, 538, 2641, 1661, 3093, 1109, 636, +-639, -2195, -1803, -2695, -1111, -813, 561, 1546, +1474, 2224, 961, 955, -220, -950, -1191, -1792, +-1311, -948, -347, 451, 1023, 1229, 1632, 981, +740, 238, -1260, -693, -2250, -1439, -806, -1127, +1753, 597, 2410, 2371, 243, 1701, -2315, -978, +-2378, -3157, 354, -1948, 2854, 1490, 1858, 3580, +-1393, 1833, -3160, -1863, -1062, -3463, 2163, -1387, +2770, 1905, 9, 2832, -2627, 735, -2035, -1675, +810, -1733, 2391, 3, 1013, 1113, -1461, 431, +-1926, -524, -80, -306, 1451, 580, 1178, 661, +-388, -278, -1403, -1199, -883, -689, 510, 720, +1239, 1633, 546, 581, -473, -1296, -1120, -1754, +-868, -233, 452, 1684, 1360, 1638, 681, 47, +-797, -1718, -1368, -1790, -496, -191, 812, 1748, +1324, 2186, 213, 477, -1239, -1906, -1066, -2472, +287, -603, 1047, 1754, 558, 2339, -618, 846, +-980, -1181, -98, -2111, 905, -1130, 527, 678, +-652, 1673, -854, 1083, 5, -205, 840, -944, +450, -728, -606, -196, -700, -2, 186, 105, +652, 663, 0, 1028, -772, 394, -481, -1041, +562, -1801, 1194, -778, 89, 1263, -1442, 2268, +-1281, 1003, 478, -1356, 1690, -2313, 905, -1109, +-925, 1145, -1779, 2186, -492, 1124, 1404, -716, +1323, -1930, -374, -1243, -1452, 304, -813, 1617, +732, 1437, 1273, 7, 331, -1261, -923, -1468, +-951, -431, -214, 860, 411, 1485, 609, 893, +451, -507, 67, -1434, -425, -1236, -803, 157, +-739, 1299, 69, 1254, 1158, 142, 1281, -846, +-29, -940, -1497, -534, -1576, 153, -52, 524, +1493, 846, 1586, 610, -64, -179, -1668, -928, +-1231, -982, 404, -212, 1308, 597, 458, 1057, +-721, 610, -778, -161, 181, -744, 839, -721, +206, -334, -956, 136, -1013, 500, 279, 633, +1589, 632, 1146, 172, -852, -762, -2330, -1492, +-1411, -903, 1374, 779, 3018, 1985, 1465, 1486, +-2001, -601, -3632, -2119, -1392, -1558, 2379, 386, +3772, 1545, 1118, 1095, -2612, 90, -3574, -489, +-751, -438, 2499, -532, 2781, -857, 251, -357, +-2195, 1092, -1980, 2063, 417, 943, 1896, -1524, +786, -2781, -1332, -1279, -1622, 1658, 296, 2839, +2082, 1204, 1463, -1163, -1133, -2021, -2881, -1182, +-1608, -78, 1607, 791, 3339, 1479, 1731, 1633, +-1697, 396, -3587, -1896, -2023, -2936, 1553, -1223, +3460, 1893, 1848, 3597, -1309, 2081, -2789, -1469, +-1611, -3886, 736, -2665, 1794, 1026, 1097, 3601, +-44, 2681, -631, -524, -935, -2780, -896, -2230, +-186, 63, 987, 1706, 1448, 1572, 604, 253, +-1145, -869, -2033, -990, -762, -240, 1590, 475, +2338, 602, 364, 101, -2158, -522, -2406, -701, +106, -68, 2560, 1033, 2188, 1344, -561, 213, +-2715, -1677, -2023, -2344, 453, -593, 2516, 2107, +2236, 3268, -76, 1409, -2341, -2092, -2691, -4039, +-626, -2341, 2077, 1762, 3040, 4273, 1211, 2894, +-1658, -1023, -3034, -3746, -1813, -3002, 811, 83, +2663, 2566, 2141, 2706, -19, 818, -1737, -1222, +-2064, -1997, -1207, -1328, 354, -8, 1865, 1037, +2273, 1515, 956, 942, -1453, -364, -3212, -1482, +-2212, -1236, 1135, 210, 3769, 1342, 2744, 869, +-954, -585, -3749, -1076, -2846, -108, 721, 1021, +3260, 804, 2476, -341, -443, -1224, -2495, -858, +-2090, 260, -142, 1061, 1761, 1099, 1930, 443, +512, -556, -1239, -1361, -1813, -1297, -907, -244, +760, 1198, 1671, 2039, 1070, 1260, -335, -757, +-1295, -2314, -1237, -1853, -320, 34, 815, 1629, +1278, 1890, 777, 962, -207, -195, -1026, -1311, +-1352, -2015, -541, -1540, 741, 453, 1627, 2762, +1069, 2936, -387, 345, -1665, -2883, -1406, -3554, +47, -834, 1345, 2423, 1411, 3118, 279, 920, +-929, -1502, -1287, -2016, -506, -662, 523, 562, +907, 683, 548, 277, -150, 137, -538, 344, +-458, -40, -316, -553, -22, -646, 444, 144, +970, 810, 608, 280, -850, -817, -1866, -992, +-937, 453, 1424, 1804, 2508, 1236, 1112, -1083, +-1664, -2546, -3048, -1602, -1462, 962, 1653, 2605, +3141, 2223, 1723, 123, -1109, -2162, -2731, -2888, +-2025, -1397, 115, 1253, 1853, 2908, 1992, 2294, +1036, 26, -548, -2052, -1745, -2449, -1967, -1219, +-796, 525, 1004, 1648, 2201, 1758, 1916, 1184, +156, 120, -1810, -1371, -2429, -2679, -1538, -2341, +603, 272, 2450, 3463, 2695, 4226, 845, 1176, +-1894, -3388, -3377, -5108, -2235, -2287, 1031, 2456, +3413, 4562, 2817, 2658, -47, -903, -2516, -2792, +-2802, -2220, -1053, -810, 1291, 365, 2322, 1369, +1614, 2154, -60, 1693, -1514, -387, -1682, -2586, +-789, -2814, 466, -582, 1205, 2163, 1300, 2921, +569, 1208, -762, -1207, -1476, -2123, -1098, -1387, +269, 28, 1291, 952, 1206, 1243, -26, 904, +-965, 34, -807, -821, -77, -1254, 494, -630, +311, 353, -223, 936, -240, 608, 477, 157, +846, 110, 24, -171, -1403, -927, -1682, -1429, +29, -317, 2343, 1779, 2502, 2625, -43, 592, +-2942, -2485, -3112, -3158, -181, -617, 2947, 2467, +3322, 3000, 657, 771, -2381, -1870, -3033, -2361, +-1185, -755, 1222, 860, 2273, 1054, 1412, 579, +65, 505, -777, 521, -1182, -284, -1514, -1720, +-1026, -2023, 696, -178, 2494, 2361, 2627, 3015, +154, 904, -2966, -2158, -3729, -3518, -898, -1735, +2840, 1596, 3902, 3385, 1319, 2013, -2360, -804, +-3353, -2448, -998, -1721, 1819, 62, 2079, 1106, +63, 852, -1368, 377, -595, 292, 1003, 185, +1215, -430, -542, -1170, -1906, -1098, -1242, 85, +872, 1483, 2290, 1634, 1475, 237, -602, -1285, +-2106, -1599, -1572, -360, 111, 1028, 1322, 1078, +1188, -68, 419, -924, -216, -235, -490, 878, +-689, 1010, -752, -377, -349, -1784, 529, -1394, +1273, 691, 996, 2355, -150, 1752, -1070, -584, +-1134, -2276, -513, -1824, 357, 141, 886, 1654, +961, 1424, 511, 207, -258, -665, -1077, -585, +-1087, -235, -496, -285, 631, -366, 1261, -85, +1087, 582, 126, 1090, -1000, 844, -1358, -78, +-814, -1361, 353, -1786, 1284, -864, 1125, 985, +163, 2461, -673, 1942, -936, -260, -597, -2452, +-4, -2539, 440, -585, 407, 1535, 499, 2321, +628, 1412, 140, -70, -1034, -1283, -1642, -1974, +-682, -1622, 1357, 93, 2286, 2197, 897, 2628, +-1413, 652, -2197, -1825, -867, -2440, 1036, -863, +1816, 1017, 783, 1289, -813, 385, -1410, -46, +-415, 320, 698, 420, 908, -629, 260, -1613, +-609, -1187, -810, 764, -233, 2096, 543, 1441, +695, -425, 491, -1457, -38, -1060, -764, -250, +-1060, 179, -434, 207, 678, 682, 1398, 1106, +915, 792, -297, -564, -1289, -1687, -1170, -1522, +-355, -155, 505, 1283, 1132, 1725, 1080, 1027, +510, -113, -586, -1046, -1404, -1604, -1478, -1395, +-565, -188, 1087, 1504, 2293, 2428, 1865, 1645, +-328, -591, -2604, -2686, -2760, -2779, -551, -620, +2110, 2034, 2988, 2992, 1291, 1698, -1175, -697, +-2455, -2302, -1568, -2127, 198, -708, 1388, 917, +1309, 1813, 321, 1676, -254, 550, -425, -995, +-418, -1858, -557, -1471, -541, -65, 110, 1410, +892, 1673, 1087, 792, 350, -657, -823, -1346, +-1096, -880, -366, 163, 553, 789, 459, 354, +-109, -237, -246, -259, 394, 317, 818, 677, +239, 310, -1013, -654, -1416, -1413, -544, -1044, +1029, 610, 1763, 2245, 934, 1885, -665, -375, +-1532, -2620, -984, -2275, 104, 128, 671, 2183, +604, 1912, 529, 111, 485, -1117, -121, -946, +-943, -253, -1084, -151, -386, -239, 765, 250, +1336, 1133, 719, 1129, -565, -91, -1109, -1490, +-455, -1491, 415, -118, 525, 1244, -17, 1268, +-417, 255, -213, -621, 483, -681, 883, -241, +311, -75, -848, -12, -1455, 178, -635, 584, +979, 462, 1767, -222, 846, -716, -716, -505, +-1415, 293, -814, 622, 190, 231, 681, -472, +416, -514, 124, 202, 310, 776, 499, 454, +-156, -580, -1224, -1122, -1401, -467, -79, 805, +1616, 1260, 1988, 474, 650, -782, -1359, -1080, +-2141, -369, -1177, 476, 679, 553, 1894, 157, +1475, 46, -39, 120, -1261, 21, -1248, -412, +-318, -703, 511, -334, 619, 537, 379, 1138, +215, 628, 88, -555, -134, -1200, -541, -748, +-661, 368, -151, 938, 558, 613, 896, -89, +380, -364, -363, -273, -714, -357, -407, -264, +161, 172, 348, 653, 257, 493, -24, -164, +-30, -553, 100, -355, 93, 146, -241, 209, +-383, -51, -81, -82, 369, 262, 412, 400, +39, -39, -201, -573, -160, -518, 21, 125, +-3, 619, -84, 408, -152, -246, 118, -436, +330, -23, 369, 366, -27, 171, -491, -437, +-490, -581, -16, 11, 422, 903, 507, 900, +179, -153, -230, -1214, -377, -1082, -187, 147, +55, 1215, 167, 1121, 197, -17, 82, -1026, +-61, -938, -12, -1, 14, 727, 45, 448, +-127, -222, -258, -312, -85, 353, 354, 606, +535, -290, 103, -1215, -386, -740, -498, 867, +-109, 1604, 240, 573, 369, -1057, 190, -1415, +-15, -322, -104, 813, -123, 867, -110, 116, +-45, -380, 74, -297, 108, 68, 69, 108, +-36, -200, 109, -338, 314, 56, 152, 602, +-491, 518, -825, -181, -273, -756, 892, -585, +1416, 216, 531, 792, -1070, 561, -1758, -245, +-589, -812, 1030, -560, 1629, 301, 594, 978, +-611, 596, -994, -471, -388, -1183, 195, -634, +190, 580, 53, 1279, 148, 702, 572, -573, +559, -1123, -182, -628, -1065, 198, -942, 601, +146, 655, 1106, 464, 999, -104, 112, -766, +-630, -892, -599, -240, -152, 697, -8, 934, +-74, 324, 11, -406, 642, -518, 969, -206, +336, -3, -875, -95, -1467, -97, -713, 213, +750, 669, 1586, 662, 1060, -143, -301, -1085, +-1194, -1265, -989, -187, -112, 1282, 620, 1693, +641, 514, 400, -1151, 59, -1649, -141, -740, +-311, 643, -306, 1279, -126, 817, -42, -124, +206, -695, 346, -590, 438, -263, 234, 13, +-162, 194, -485, 447, -606, 517, -168, 143, +362, -460, 713, -674, 615, -247, 228, 279, +-434, 411, -863, 200, -694, -8, 22, -36, +838, -34, 1119, -186, 578, -330, -555, -118, +-1217, 355, -770, 490, 339, 59, 983, -440, +708, -368, -64, 170, -459, 493, -282, 140, +-5, -453, 12, -527, -46, -41, 109, 554, +234, 635, 341, 193, 132, -481, -207, -725, +-531, -382, -262, 153, 431, 478, 654, 584, +194, 513, -507, -29, -559, -829, 97, -1094, +755, -305, 536, 814, -372, 1114, -862, 462, +-275, -305, 648, -587, 868, -524, 95, -387, +-690, -112, -550, 294, 192, 695, 761, 890, +310, 461, -461, -637, -706, -1671, -28, -1328, +793, 437, 863, 2055, 70, 1782, -858, -175, +-983, -1824, -175, -1599, 829, -43, 1050, 1053, +489, 846, -318, 87, -746, -67, -709, 202, +-184, 40, 315, -727, 706, -1168, 853, -325, +501, 1101, -379, 1764, -1235, 643, -1074, -1153, +34, -1813, 1285, -694, 1578, 935, 444, 1330, +-1100, 470, -1447, -526, -414, -683, 790, -163, +973, 292, 244, 215, -349, -198, -222, -338, +282, -3, 262, 453, -345, 510, -716, 105, +-204, -495, 739, -718, 1072, -331, 361, 368, +-699, 772, -941, 500, -249, -134, 509, -638, +600, -533, 161, 11, -127, 439, -70, 316, +106, -134, 82, -253, -58, 169, -263, 531, +-283, 84, -18, -838, 540, -960, 822, 164, +479, 1332, -456, 1142, -1234, -343, -846, -1462, +403, -1087, 1445, 387, 1137, 1276, 16, 820, +-1109, -281, -1135, -892, -210, -584, 751, 137, +837, 574, 371, 397, -44, -49, -249, -328, +-290, -306, -253, -99, -184, 234, 124, 407, +500, 209, 558, -270, 224, -590, -320, -268, +-511, 351, -377, 661, 100, 285, 566, -309, +554, -612, 77, -373, -371, 225, -350, 546, +18, 293, 349, -174, 231, -221, -106, -55, +-241, -96, 29, -225, 330, -85, 360, 413, +73, 609, -354, 111, -435, -704, -51, -798, +457, 54, 507, 768, 203, 626, -166, -111, +-345, -541, -182, -367, 5, 5, 158, 192, +293, 209, 336, 170, 210, 72, -223, -215, +-457, -302, -261, -41, 277, 288, 629, 244, +259, -216, -242, -377, -321, 4, 6, 568, +237, 454, 159, -311, -38, -878, -167, -524, +32, 485, 350, 1136, 312, 616, -107, -607, +-433, -1205, -215, -580, 309, 595, 538, 930, +226, 372, -243, -303, -357, -339, -109, -150, +228, -248, 346, -306, 251, 69, 80, 771, +-306, 803, -480, -83, -67, -1128, 662, -1054, +815, 188, 72, 1239, -788, 967, -842, -311, +51, -1092, 1045, -676, 895, 408, -140, 832, +-872, 261, -539, -493, 355, -441, 747, 166, +137, 380, -529, -70, -155, -297, 655, 58, +623, 381, -375, -48, -1046, -550, -352, -241, +887, 574, 1209, 766, 154, -95, -915, -879, +-711, -686, 162, 209, 596, 813, 330, 648, +-41, 22, -112, -569, 30, -757, 90, -378, +-16, 298, 0, 789, 47, 757, -35, 71, +-36, -728, 180, -1077, 304, -469, 177, 652, +-61, 1235, -268, 719, -279, -543, 62, -1153, +372, -619, 329, 374, 63, 689, 8, 248, +30, -56, -92, 80, -318, 116, -327, -353, +207, -752, 792, -305, 763, 613, -105, 1037, +-862, 425, -799, -594, 130, -1011, 870, -475, +659, 463, -103, 807, -382, 322, 16, -411, +257, -484, -38, 119, -457, 503, -333, -1, +307, -728, 1005, -556, 791, 496, -203, 1134, +-1116, 502, -999, -736, 101, -1170, 1118, -339, +1037, 666, 117, 788, -537, 119, -441, -324, +-136, -165, -147, 106, -85, -18, 241, -439, +736, -435, 733, 209, 136, 937, -744, 764, +-1074, -310, -456, -1146, 631, -798, 1249, 287, +815, 874, -182, 465, -828, -110, -649, -134, +-42, 69, 214, -198, 255, -759, 482, -557, +631, 453, 301, 1360, -437, 950, -956, -490, +-705, -1545, 288, -1154, 1144, 372, 1042, 1342, +140, 982, -756, -166, -954, -816, -310, -527, +444, 4, 681, 168, 455, -52, 138, -27, +-117, 403, -319, 654, -350, 165, -144, -793, +181, -1086, 467, -207, 508, 879, 153, 1055, +-264, 294, -510, -617, -261, -879, 203, -428, +563, 421, 478, 744, -39, 309, -517, -375, +-418, -548, 310, -37, 659, 427, 253, 345, +-383, -201, -486, -469, -14, -203, 540, 248, +561, 485, -33, 249, -547, -245, -312, -519, +278, -248, 511, 303, 270, 449, -269, 82, +-421, -384, 42, -280, 542, 226, 347, 402, +-187, 46, -398, -373, -133, -337, 246, -15, +364, 259, 161, 398, -39, 214, -13, -131, +-34, -463, -143, -388, -117, -5, 128, 349, +327, 428, 298, 239, 103, -75, -107, -406, +-227, -519, -298, -164, -88, 423, 315, 626, +557, 197, 355, -413, 0, -421, -360, 61, +-533, 237, -297, -140, 303, -345, 739, 189, +628, 695, 75, 407, -553, -574, -702, -987, +-240, -252, 351, 746, 644, 891, 632, 13, +193, -645, -522, -452, -782, 164, -225, 312, +486, -74, 693, -219, 382, 117, -165, 431, +-414, 195, -278, -404, 10, -623, 306, -89, +425, 586, 201, 561, -239, -151, -431, -530, +-71, -175, 407, 291, 568, 239, 126, -184, +-489, -323, -504, 20, 65, 423, 533, 349, +508, -138, 52, -560, -290, -426, -312, 201, +-23, 684, 107, 402, 151, -361, 200, -583, +211, -124, 204, 375, -89, 252, -429, -175, +-328, -261, 279, 159, 612, 417, 236, 5, +-228, -538, -237, -431, 81, 316, 231, 707, +-74, 263, -300, -599, 45, -692, 473, 86, +371, 753, -99, 465, -248, -390, -177, -656, +7, -200, 30, 390, 96, 420, 243, 87, +426, -82, 217, -146, -320, -213, -629, -320, +-357, -115, 371, 410, 822, 733, 558, 370, +-183, -593, -595, -1082, -390, -433, 6, 683, +230, 1058, 274, 335, 346, -473, 428, -649, +78, -295, -595, 37, -840, 152, -156, 280, +812, 342, 1100, 195, 400, -155, -695, -409, +-1013, -406, -320, -124, 515, 216, 728, 461, +449, 410, 2, 118, -377, -282, -436, -562, +-132, -490, 145, -73, 332, 519, 384, 775, +246, 428, -112, -308, -360, -801, -351, -660, +-45, -25, 384, 615, 501, 712, 261, 265, +-144, -327, -324, -517, -300, -278, -102, 13, +243, 96, 549, 83, 430, 213, -100, 351, +-547, 223, -445, -218, 54, -707, 506, -621, +548, 169, 174, 963, -276, 825, -496, -233, +-254, -975, 169, -640, 550, 323, 451, 731, +-6, 252, -434, -368, -458, -401, -9, 83, +473, 407, 504, 167, 88, -276, -340, -397, +-296, -56, 11, 294, 163, 260, 132, 60, +103, -112, 230, -99, 178, -58, -195, -84, +-540, -118, -249, 4, 523, 259, 789, 257, +208, -20, -534, -222, -585, -133, -72, 18, +416, -64, 414, -242, 102, -4, -67, 531, +-30, 674, -30, -35, -213, -954, -226, -966, +151, 85, 544, 1101, 419, 959, -112, -80, +-495, -854, -407, -729, 83, -44, 471, 432, +387, 376, 54, 92, -143, -22, -120, 33, +-140, -11, -153, -249, -8, -404, 273, -207, +550, 368, 340, 726, -386, 339, -773, -442, +-329, -749, 544, -241, 840, 357, 306, 390, +-402, 75, -588, -49, -149, 75, 276, -47, +341, -317, 94, -277, -64, 136, 26, 432, +203, 253, 6, -203, -353, -414, -378, -104, +180, 314, 720, 292, 529, -156, -249, -339, +-751, -118, -334, 277, 297, 328, 497, -31, +241, -313, -23, -215, -69, 158, -102, 250, +-139, 12, -167, -245, 41, -171, 349, 191, +345, 313, 26, 59, -239, -215, -227, -246, +-8, -118, 93, -6, 88, 169, 48, 362, +163, 302, 252, -115, 71, -588, -279, -569, +-436, -5, -142, 647, 372, 766, 619, 192, +298, -581, -230, -858, -543, -299, -375, 506, +84, 706, 488, 161, 490, -306, 89, -233, +-338, 42, -407, -43, -34, -245, 325, -124, +280, 310, -54, 441, -258, 112, -57, -249, +304, -358, 405, -212, -33, 10, -596, 261, +-459, 282, 284, 58, 831, -137, 494, -78, +-343, 56, -826, -115, -364, -354, 490, -156, +678, 488, 134, 709, -399, 34, -264, -716, +150, -559, 280, 166, -51, 387, -299, 33, +-16, -35, 381, 347, 286, 356, -132, -374, +-306, -1007, -66, -418, 113, 837, 123, 1175, +29, 168, 123, -965, 206, -868, -47, 99, +-369, 731, -308, 392, 225, -263, 565, -356, +372, 38, -262, 304, -653, 110, -291, -299, +444, -392, 678, 11, 149, 508, -511, 462, +-500, -196, 196, -631, 568, -285, 208, 392, +-344, 493, -382, -48, -34, -410, 351, -210, +498, 264, 135, 292, -426, 3, -542, -273, +-130, -208, 390, 34, 605, 189, 371, 171, +-235, -3, -641, -111, -365, -107, 168, 67, +439, 51, 281, -240, 116, -248, -10, 383, +-115, 723, -283, -9, -298, -933, -62, -702, +371, 423, 602, 975, 299, 364, -333, -536, +-546, -635, -257, -69, 70, 352, 252, 223, +337, -47, 252, -67, 85, 8, -86, -2, +-336, -2, -498, 13, -209, -105, 469, -166, +728, 30, 442, 343, -154, 216, -670, -135, +-708, -321, -146, -187, 646, 2, 754, 125, +357, 303, -257, 277, -582, -53, -472, -499, +-24, -438, 393, 158, 442, 623, 267, 308, +-85, -328, -380, -475, -261, -44, 127, 340, +246, 294, -9, -73, -158, -424, 67, -321, +268, 220, 283, 676, -138, 411, -536, -429, +-314, -917, 358, -397, 573, 543, 96, 915, +-296, 391, -204, -447, 139, -759, 213, -355, +-142, 251, -464, 401, -65, 212, 652, 98, +689, 69, -71, -86, -764, -428, -775, -502, +-52, 9, 874, 678, 900, 710, 3, 24, +-680, -658, -575, -684, -142, -175, 236, 465, +512, 665, 398, 268, -5, -312, -331, -523, +-436, -275, -158, 119, 257, 369, 457, 316, +177, 1, -186, -286, -238, -325, -59, -88, +58, 315, 59, 391, 72, -50, 69, -402, +33, -198, -24, 225, -39, 216, -29, -55, +41, -151, 29, 27, -69, 176, -12, -37, +226, -231, 227, -127, -147, 198, -372, 217, +-140, -24, 220, -145, 417, -26, 236, 97, +-251, -38, -453, -260, -113, -168, 379, 340, +298, 569, -34, 98, -228, -609, -148, -705, +142, -52, 297, 706, 91, 789, -438, 5, +-329, -771, 272, -702, 617, 63, 255, 732, +-390, 595, -680, -197, -216, -713, 600, -374, +699, 355, -63, 632, -569, 216, -283, -457, +227, -653, 267, -62, 57, 533, -107, 504, +-124, -3, 66, -350, 244, -376, 112, -110, +-282, 164, -316, 231, 81, 152, 404, 103, +338, -27, -135, -279, -459, -332, -224, -42, +294, 335, 394, 360, 52, 42, -193, -286, +-253, -243, -75, 0, 243, 131, 386, 77, +-20, 12, -441, -17, -254, -49, 278, 15, +480, 97, 138, 23, -364, -230, -471, -209, +52, 182, 569, 425, 402, 62, -306, -424, +-668, -315, -138, 179, 622, 449, 636, 107, +-170, -332, -720, -359, -351, 32, 334, 399, +573, 321, 252, -96, -224, -518, -492, -324, +-206, 356, 365, 568, 386, 68, -112, -487, +-323, -436, -22, 111, 406, 525, 308, 365, +-355, -260, -748, -594, -45, -241, 877, 325, +710, 561, -225, 265, -807, -281, -665, -601, +117, -396, 949, 290, 789, 747, -281, 420, +-944, -421, -528, -782, 301, -255, 820, 479, +435, 601, -405, 113, -540, -372, -62, -420, +233, -54, 194, 217, 86, 208, -26, 56, +-69, 41, 41, -24, -88, -236, -79, -268, +148, 7, 43, 354, -65, 336, 128, 16, +233, -335, -136, -362, -386, -57, -151, 270, +271, 303, 499, 42, 178, -87, -381, -74, +-447, -106, -77, -232, 361, -131, 405, 327, +-6, 538, -336, 106, -114, -555, 174, -561, +54, 84, -62, 457, -39, 387, 6, 48, +239, -267, 162, -332, -325, -180, -336, 70, +243, 227, 412, 386, 28, 275, -320, -259, +-283, -684, 181, -422, 544, 357, 41, 860, +-581, 396, -275, -512, 414, -765, 543, -108, +-52, 527, -597, 235, -304, -199, 515, -106, +561, 320, -201, 193, -583, -344, -160, -544, +373, -93, 475, 606, -15, 649, -473, -119, +-252, -784, 283, -405, 383, 485, -20, 642, +-331, -116, -190, -707, 335, -191, 414, 689, +-287, 634, -556, -485, 79, -993, 630, -80, +343, 1044, -389, 754, -672, -607, -111, -1220, +694, -176, 604, 1234, -204, 1013, -639, -573, +-374, -1485, 236, -455, 577, 1132, 231, 1274, +-278, -138, -268, -1328, 51, -682, 37, 730, +-83, 1001, -67, -75, 136, -944, 385, -342, +215, 769, -409, 813, -637, -415, -28, -1172, +650, -248, 506, 1078, -213, 1003, -609, -420, +-145, -1329, 511, -400, 377, 1083, -325, 1067, +-611, -430, -75, -1328, 652, -349, 722, 1074, +-95, 1059, -871, -369, -666, -1303, 278, -489, +871, 926, 487, 1111, -357, -83, -626, -1175, +-133, -726, 368, 639, 250, 1205, -205, 212, +-283, -1016, 156, -852, 480, 327, 83, 949, +-335, 333, -358, -554, -91, -511, 219, 199, +359, 441, 157, -54, -76, -451, -170, -123, +-243, 423, -153, 464, 246, -37, 347, -515, +22, -386, -213, 98, -172, 398, 12, 247, +227, -27, 221, -196, -122, -40, -353, 126, +-183, -40, 184, -346, 428, -265, 316, 416, +-126, 751, -508, 334, -438, -596, 24, -989, +513, -391, 510, 661, 99, 1116, -303, 416, +-506, -657, -333, -1009, 177, -280, 606, 655, +367, 811, -249, -33, -509, -736, -141, -342, +398, 608, 342, 697, -303, -303, -527, -995, +-18, -388, 698, 919, 565, 1101, -293, -167, +-859, -1195, -428, -678, 464, 674, 765, 1047, +313, 143, -507, -890, -726, -743, 52, 424, +720, 1054, 287, 273, -516, -928, -523, -885, +146, 430, 585, 1159, 414, 248, -288, -1001, +-652, -701, -199, 642, 382, 982, 390, -167, +-50, -1071, -192, -401, -29, 969, 127, 1029, +45, -361, -239, -1323, -259, -508, 57, 1006, +387, 1144, 401, -63, -49, -1161, -424, -717, +-415, 646, -105, 1032, 244, -15, 456, -1010, +421, -337, -130, 953, -580, 825, -477, -664, +51, -1477, 526, -158, 491, 1630, -100, 1446, +-481, -688, -177, -2043, 259, -831, 113, 1452, +-260, 1785, -208, -137, 298, -1680, 565, -783, +49, 1141, -740, 1213, -623, -537, 311, -1508, +915, -171, 363, 1600, -711, 1230, -856, -877, +221, -1995, 987, -392, 241, 1859, -806, 1565, +-639, -919, 292, -2045, 866, -166, 290, 2001, +-674, 1319, -786, -1336, 195, -2315, 845, -18, +202, 2518, -546, 1690, -384, -1305, 256, -2406, +327, -438, -206, 1698, -360, 1372, 136, -408, +597, -1072, 158, -107, -734, 636, -764, 46, +290, -652, 1075, -198, 479, 669, -641, 804, +-933, -108, -194, -879, 607, -500, 501, 364, +-170, 541, -226, 25, 205, -95, 96, 193, +-509, 89, -515, -334, 157, -549, 809, 35, +591, 843, -407, 635, -978, -568, -296, -1091, +610, 24, 557, 1245, -177, 777, -500, -891, +-128, -1521, 411, -87, 391, 1686, -248, 1377, +-633, -568, -304, -1768, 328, -933, 552, 812, +260, 1396, -149, 645, -447, -478, -392, -789, +-127, -559, 217, -194, 451, 436, 309, 989, +-184, 766, -514, -493, -197, -1494, 189, -809, +153, 1092, -125, 1830, -195, 282, 113, -1807, +519, -1574, 222, 841, -683, 2224, -889, 682, +58, -1879, 908, -1787, 696, 789, -320, 2186, +-974, 473, -403, -1817, 651, -1264, 684, 1149, +-304, 1876, -831, -222, -283, -2101, 668, -1087, +859, 1672, -146, 2356, -1080, -95, -596, -2459, +538, -1629, 755, 1227, -15, 2280, -559, 477, +-309, -1634, 426, -1353, 504, 789, -381, 1571, +-930, -43, -266, -1610, 725, -782, 811, 1319, +79, 1698, -613, -19, -630, -1749, -128, -1179, +57, 737, -142, 1350, 271, 223, 969, -683, +564, -167, -893, 520, -1649, 155, -731, -838, +1037, -766, 1772, 499, 590, 1383, -1249, 585, +-1446, -714, -19, -1010, 952, -297, 372, 493, +-688, 441, -484, -42, 581, -80, 1056, 493, +18, 510, -1463, -419, -1373, -1236, 323, -745, +1655, 899, 1154, 1702, -492, 716, -1436, -1084, +-1038, -1471, 256, -274, 1031, 841, 691, 862, +-196, 29, -772, -414, -570, -61, 41, 210, +550, -18, 404, -306, -196, -192, -622, 259, +-453, 341, 161, 125, 589, -179, 443, -44, +-192, 313, -696, -16, -671, -532, -37, -607, +608, 221, 773, 1175, 120, 1050, -718, -353, +-942, -1649, -250, -1179, 657, 607, 695, 1670, +16, 1064, -545, -525, -420, -1264, -38, -579, +101, 422, -102, 537, -17, 17, 365, -70, +343, 360, -460, 580, -994, -186, -361, -1176, +821, -936, 1188, 649, -41, 1778, -1439, 873, +-1125, -914, 470, -1695, 1437, -551, 601, 1075, +-1029, 1258, -1389, 160, 60, -818, 1296, -590, +545, 152, -1018, 401, -1101, 261, 178, -6, +1304, -183, 587, -236, -1057, -199, -1459, 370, +-83, 749, 1276, 311, 997, -788, -366, -1226, +-1346, -104, -773, 1393, 533, 1465, 861, -126, +111, -1666, -471, -1273, -375, 446, -31, 1550, +101, 1001, -265, -475, -257, -1235, 253, -641, +468, 628, -45, 1091, -553, 316, -511, -798, +-150, -969, 359, -36, 334, 1093, 82, 1220, +-92, 85, -322, -1447, -618, -1676, -445, -159, +268, 1962, 921, 2267, 540, 279, -611, -2169, +-1306, -2588, -543, -375, 648, 2301, 922, 2726, +261, 370, -619, -2241, -753, -2305, -187, -20, +277, 2043, 78, 1674, -65, -519, 197, -1743, +161, -629, -453, 1247, -834, 1369, -225, -326, +859, -1609, 994, -904, -303, 1011, -1640, 1783, +-1148, 455, 805, -1207, 1946, -1340, 861, 3, +-1503, 1087, -2437, 690, -709, -454, 1772, -674, +2381, 358, 333, 1053, -2134, 89, -2457, -1314, +-240, -1305, 2086, 370, 2000, 2051, -127, 1635, +-2085, -569, -1797, -2283, 344, -1793, 1688, 527, +893, 2286, -781, 1937, -1141, -227, -195, -2059, +650, -1685, 190, 61, -827, 1535, -718, 1369, +614, 38, 1454, -812, 322, -567, -1536, 84, +-2074, -73, -406, -326, 1876, -6, 2160, 814, +187, 1217, -1903, 344, -2203, -1371, -680, -2004, +1229, -470, 1927, 1817, 918, 2388, -750, 629, +-1823, -1796, -1495, -2529, 185, -483, 1577, 2049, +1335, 2232, -423, -44, -1610, -2192, -981, -1577, +776, 1008, 1307, 2608, -105, 916, -1639, -2355, +-1188, -3026, 969, 155, 2131, 3727, 548, 3209, +-1982, -1240, -2360, -4504, -93, -2644, 2095, 2252, +1629, 4447, -703, 1514, -1856, -2800, -632, -3353, +1005, 120, 703, 2990, -914, 1658, -1239, -1742, +444, -2517, 1775, 311, 637, 2843, -1649, 1765, +-2099, -1571, -249, -3052, 1860, -1082, 1603, 2038, +-505, 2858, -2002, 775, -923, -1775, 981, -2317, +1318, -644, -187, 1329, -1468, 1866, -972, 716, +622, -931, 1477, -1528, 609, -630, -962, 957, +-1719, 1608, -946, 398, 710, -1463, 1588, -1652, +858, 249, -413, 2233, -1428, 1667, -1388, -946, +-265, -2739, 1096, -1476, 1217, 1609, 348, 2988, +-629, 1252, -1294, -1782, -919, -2831, 213, -1051, +947, 1696, 673, 2584, -112, 1072, -768, -1297, +-747, -2239, 18, -1091, 296, 835, -79, 2008, +-242, 1480, 267, -396, 518, -1985, -46, -1754, +-1173, 365, -1391, 2067, 154, 1800, 2134, -188, +1657, -1878, -1115, -1758, -3168, -6, -1830, 1525, +1768, 1851, 3661, 691, 1272, -1057, -2802, -2195, +-3898, -1418, -718, 844, 3177, 2636, 3412, 2113, +-217, -524, -3621, -2947, -2988, -2611, 744, 453, +3511, 3109, 2158, 2769, -1475, -267, -3422, -2792, +-1753, -2527, 1507, -30, 2977, 2205, 1318, 2330, +-1746, 492, -2972, -1484, -1154, -2059, 1511, -820, +2561, 910, 805, 1948, -1706, 1238, -2444, -594, +-645, -2040, 1712, -1285, 1886, 766, -133, 2208, +-1857, 1141, -1559, -1112, 562, -2133, 1753, -718, +777, 1477, -1403, 1859, -1816, 293, -26, -1413, +1735, -1300, 1182, 180, -871, 1132, -2137, 383, +-878, -477, 1404, -311, 2048, 853, 194, 766, +-2087, -847, -2018, -2051, 180, -821, 1994, 2158, +1536, 3236, -543, 652, -1933, -3201, -1403, -3818, +340, -199, 1374, 3853, 1011, 3639, -209, -158, +-1227, -3534, -1062, -2896, -114, 410, 811, 2564, +836, 2021, 21, -180, -868, -1330, -887, -1163, +-21, -268, 657, 364, 518, 695, -200, 759, +-809, 339, -628, -490, 238, -1028, 734, -562, +339, 486, -381, 1165, -840, 579, -717, -492, +124, -883, 908, -343, 781, 299, -198, 334, +-1109, 330, -1293, 249, -173, 307, 1342, -251, +1377, -921, -61, -959, -1605, 279, -1560, 1674, +6, 1529, 1534, -149, 1198, -2054, -361, -1989, +-1367, 5, -1025, 2179, 107, 2235, 890, 233, +741, -1807, -128, -2062, -582, -466, -774, 1316, +-621, 1586, 16, 559, 1003, -633, 1184, -763, +67, -273, -1620, 29, -2120, -189, -399, -119, +2193, 544, 2639, 1081, 101, 552, -2877, -744, +-2944, -1554, 111, -905, 2910, 757, 2353, 1668, +-709, 1024, -2645, -397, -1506, -1246, 1020, -957, +1735, -50, -96, 667, -1606, 777, -618, 542, +1468, 65, 1701, -440, -660, -828, -2956, -620, +-2124, 133, 1555, 828, 3991, 1058, 2059, 351, +-2460, -525, -4656, -1077, -2279, -915, 2551, -106, +4832, 962, 2184, 1734, -2694, 1079, -4950, -899, +-2168, -2418, 2519, -1760, 4442, 729, 1613, 2698, +-2648, 2154, -3733, -170, -865, -2251, 2400, -2187, +2428, -577, -458, 1166, -2425, 1860, -925, 1521, +1697, 467, 1814, -1125, -724, -2312, -2823, -1961, +-1611, 161, 1736, 2506, 3447, 3062, 1271, 1194, +-2390, -1866, -3803, -3592, -1506, -2521, 2119, 718, +3640, 3523, 1657, 3570, -1576, 605, -3412, -2808, +-2225, -3860, 829, -1608, 2765, 1692, 1988, 3433, +-296, 2260, -1888, -521, -1862, -2441, -322, -2238, +922, -337, 1081, 1403, 333, 1743, 32, 737, +-382, -577, -823, -1049, -921, -598, -28, 296, +1007, 771, 1177, 156, -240, -715, -1699, -849, +-1218, 361, 1008, 1641, 2298, 1458, 606, -612, +-2422, -2580, -3002, -2270, 13, 432, 3418, 3105, +3354, 3141, -575, 305, -4225, -2974, -3676, -3674, +586, -1204, 4089, 2126, 3423, 3788, -275, 2258, +-3442, -950, -3251, -3379, -532, -2943, 2158, -160, +2669, 2744, 1246, 3213, -921, 847, -2245, -2114, +-1985, -2899, -410, -849, 1498, 1647, 2395, 2340, +1296, 475, -1117, -1544, -2626, -1621, -2007, 78, +252, 1552, 2467, 1225, 2636, -251, 237, -1347, +-2419, -1275, -3211, -244, -1160, 937, 2100, 1760, +3807, 1517, 1689, -325, -2232, -2405, -4067, -2744, +-2151, -457, 1742, 2683, 3920, 3621, 2235, 1310, +-1553, -2246, -3327, -3688, -1995, -1862, 556, 1210, +2215, 2880, 1704, 2066, 33, 29, -1220, -1315, +-1367, -1457, -776, -1129, 144, -558, 1010, 413, +1041, 1807, 280, 2194, -857, 757, -1311, -1729, +-488, -3108, 859, -1690, 1068, 1291, 62, 3131, +-856, 2138, -899, -631, -104, -2560, 766, -1929, +734, 257, 83, 1842, -625, 1273, -810, -316, +-672, -1215, 105, -588, 860, 781, 1122, 1148, +380, 128, -826, -1219, -1660, -1323, -1024, -160, +325, 1223, 1358, 1529, 1494, 828, 552, -507, +-900, -1494, -1835, -1639, -1613, -683, -281, 956, +1521, 2109, 2381, 2042, 1449, 494, -916, -1920, +-2706, -3376, -2836, -2163, -332, 1271, 2637, 4109, +3538, 3454, 1271, -238, -2156, -3744, -3765, -3931, +-2097, -797, 1428, 2468, 3052, 3381, 2036, 1693, +-600, -726, -2119, -2037, -1548, -1955, -63, -947, +645, 500, 357, 1628, 497, 1892, 766, 879, +396, -675, -727, -1815, -1797, -1852, -1375, -494, +740, 1114, 2246, 2025, 1598, 1707, -627, 149, +-2139, -1668, -1824, -2589, 96, -1461, 1610, 1063, +1659, 3059, 453, 2639, -960, -460, -1680, -3356, +-1229, -3043, 252, 279, 1554, 3169, 1587, 2572, +257, -404, -1454, -2238, -1724, -1317, -623, 557, +750, 684, 1242, -256, 875, -408, 22, 1091, +-703, 1795, -930, 36, -957, -2621, -309, -2800, +725, 452, 1541, 3512, 1030, 3017, -494, -750, +-1741, -3476, -1577, -2344, 70, 883, 1472, 2452, +1327, 1158, -173, -825, -989, -962, -408, 440, +568, 875, 209, -532, -1088, -1985, -1551, -1017, +128, 1494, 2582, 2974, 2803, 1631, -286, -1639, +-3951, -3422, -4011, -2172, 89, 1047, 4295, 3128, +4483, 2498, 332, 4, -3973, -2230, -4171, -2341, +-774, -854, 2589, 893, 2924, 1711, 918, 1340, +-970, 258, -1239, -685, -777, -1038, -796, -946, +-634, -557, 393, 245, 1782, 1083, 1930, 1574, +216, 917, -2253, -790, -2898, -2170, -609, -1863, +2084, 378, 2717, 2346, 724, 2219, -1649, -144, +-2185, -2171, -512, -1615, 1231, 371, 1130, 1430, +-207, 453, -1016, -727, -313, -528, 939, 788, +1041, 1160, -320, -203, -1566, -1728, -1416, -1354, +191, 722, 1835, 2024, 1874, 1230, 119, -924, +-1883, -1767, -2194, -635, -647, 1050, 1442, 1154, +2094, -290, 730, -1161, -958, -379, -1379, 1151, +-588, 1436, 128, -53, 302, -1803, 186, -1767, +249, 173, 658, 1992, 420, 1931, -533, 84, +-1334, -1576, -988, -1852, 388, -434, 1356, 945, +1016, 1295, -59, 567, -892, -292, -656, -345, +-436, -57, -190, -195, 164, -816, 641, -806, +976, 369, 383, 1687, -708, 1711, -1465, 83, +-791, -1955, 487, -2298, 1296, -753, 699, 1302, +-318, 2201, -749, 1712, -271, 119, 63, -1627, +-4, -2461, -272, -1644, -208, 719, 414, 2803, +785, 2642, 361, 110, -541, -2420, -1031, -2632, +-794, -708, 375, 1508, 1179, 1908, 709, 721, +-429, -407, -958, -606, -489, -497, 551, -395, +867, -295, -98, 89, -1228, 504, -884, 575, +690, 295, 1718, -89, 1036, -37, -861, -263, +-2047, -730, -1397, -816, 472, -76, 1646, 1225, +1516, 1677, 496, 675, -703, -1139, -1599, -2021, +-1607, -1160, -475, 532, 1177, 1608, 2111, 1345, +1564, 240, -417, -576, -2122, -875, -2001, -891, +-484, -638, 1222, 19, 1673, 1003, 1129, 1516, +57, 1061, -798, -466, -1417, -1821, -1322, -1968, +-238, -379, 1146, 1555, 1815, 2331, 1218, 1202, +-518, -864, -1991, -2089, -1683, -1615, -2, 101, +1457, 1461, 1561, 1435, 420, 515, -959, -447, +-1369, -990, -415, -997, 659, -348, 979, 671, +318, 1268, -695, 631, -1056, -525, -253, -1225, +990, -535, 1284, 532, 158, 934, -1040, 478, +-1418, -422, -634, -828, 751, -534, 1521, 217, +982, 822, -272, 815, -1025, 135, -1293, -775, +-562, -1265, 452, -556, 1148, 726, 991, 1601, +334, 965, -648, -597, -1199, -1577, -949, -1172, +95, 166, 947, 1365, 1036, 1358, 335, 252, +-587, -1065, -796, -1347, -307, -527, 251, 679, +230, 1335, -107, 732, -100, -490, 199, -1311, +544, -776, 271, 547, -459, 1322, -774, 575, +-405, -786, 213, -1067, 474, -65, 431, 795, +232, 474, 149, -358, -64, -433, -658, 274, +-1076, 548, -589, -184, 852, -916, 1781, -435, +1249, 769, -542, 1231, -2112, 242, -1890, -1079, +16, -1193, 1964, -70, 2075, 1011, 482, 959, +-1364, 62, -1907, -628, -833, -687, 784, -216, +1397, 177, 603, 462, -409, 495, -486, 239, +-5, -316, 77, -811, -450, -653, -657, 327, +71, 1268, 1183, 946, 1222, -559, -360, -1690, +-1597, -941, -1233, 899, 513, 1873, 1632, 665, +971, -1186, -774, -1658, -1421, -225, -396, 1335, +926, 1129, 981, -357, -92, -1286, -981, -363, +-533, 911, 519, 954, 818, -303, 3, -1260, +-632, -623, -383, 874, 266, 1334, 607, 93, +50, -1151, -609, -877, -486, 380, 399, 955, +709, 276, 277, -725, -466, -684, -717, 361, +-220, 974, 437, 330, 544, -705, 184, -982, +-126, -266, -267, 622, -290, 911, -188, 425, +66, -317, 294, -662, 416, -539, 180, -213, +-222, 240, -507, 527, -350, 651, 199, 238, +411, -323, 328, -744, 7, -690, -167, -132, +-334, 509, -189, 862, 31, 653, 316, 3, +281, -704, -3, -1032, -331, -626, -216, 292, +170, 1070, 393, 1082, 105, 249, -428, -847, +-393, -1185, 2, -656, 511, 367, 596, 904, +84, 775, -531, 91, -725, -482, -262, -510, +368, -215, 804, -76, 523, -195, -167, 81, +-626, 695, -553, 936, -22, 25, 261, -1146, +200, -1261, 138, -74, 442, 1159, 488, 1094, +-206, -15, -1019, -851, -1059, -562, -29, 188, +1275, 352, 1539, -158, 441, -347, -1105, 98, +-1458, 663, -751, 428, 316, -407, 1031, -821, +1040, -469, 550, 444, -220, 770, -882, 389, +-1249, -417, -631, -732, 659, -253, 1477, 515, +1061, 738, -236, 43, -1051, -809, -868, -852, +-79, 107, 275, 1122, 185, 1081, 141, -246, +599, -1419, 835, -1216, 59, 310, -1193, 1411, +-1484, 1100, -293, -225, 1215, -1165, 1670, -876, +595, 77, -802, 733, -1201, 590, -502, 48, +227, -405, 297, -431, 177, -89, 367, 357, +645, 355, 333, -92, -574, -571, -1280, -363, +-717, 358, 705, 780, 1470, 332, 714, -536, +-638, -922, -1063, -335, -207, 542, 646, 853, +420, 255, -395, -457, -626, -605, 212, -193, +931, 285, 628, 314, -442, 77, -962, -188, +-497, -153, 332, -3, 641, 120, 270, 89, +80, -25, 86, -141, 81, -138, -337, -25, +-701, 97, -369, 56, 515, 0, 1080, 86, +644, 224, -325, 17, -1054, -446, -743, -723, +213, -186, 906, 781, 737, 1233, -113, 414, +-704, -1031, -532, -1585, 289, -609, 717, 938, +365, 1439, -378, 582, -735, -540, -192, -772, +585, -406, 704, -131, 185, -268, -299, -19, +-409, 707, -143, 1201, 0, 541, -45, -971, +54, -1883, 500, -1117, 682, 855, 193, 2086, +-600, 1282, -1004, -634, -549, -1645, 428, -1027, +1249, 212, 1016, 727, 10, 398, -935, 80, +-1045, 178, -428, 304, 572, -191, 946, -851, +567, -873, -114, -17, -332, 990, -162, 1102, +-35, 217, -215, -760, -423, -922, -121, -366, +720, 162, 1219, 358, 630, 409, -734, 381, +-1503, 160, -950, -340, 422, -745, 1476, -581, +1227, 114, 147, 818, -731, 678, -968, -32, +-608, -644, -13, -534, 563, -27, 836, 232, +756, 134, 191, 52, -614, 168, -985, 182, +-553, -283, 290, -574, 893, -230, 906, 502, +274, 701, -517, 7, -803, -785, -301, -749, +447, 210, 651, 1004, 148, 699, -430, -528, +-317, -1248, 413, -649, 840, 770, 200, 1321, +-829, 362, -983, -970, 10, -1223, 1087, -69, +962, 996, 52, 809, -602, -289, -333, -886, +128, -394, 10, 457, -451, 608, -180, -2, +913, -618, 1455, -380, 488, 349, -1285, 525, +-1979, -13, -655, -568, 1347, -375, 2159, 244, +1066, 556, -782, 221, -1702, -411, -1096, -635, +359, -219, 1184, 405, 1094, 617, 283, 244, +-463, -389, -691, -631, -284, -386, 245, 209, +328, 579, 230, 398, 17, -113, 61, -516, +242, -375, 242, -19, -200, 246, -424, 223, +-170, 100, 299, -3, 559, -149, 406, -310, +-54, -237, -343, 159, -135, 439, 197, 213, +231, -374, 32, -539, -50, -79, -45, 482, +270, 395, 426, -159, 198, -449, -273, -230, +-422, 146, -269, 188, 151, -40, 680, -71, +776, 178, 179, 226, -492, -220, -625, -673, +-291, -357, 252, 476, 695, 859, 678, 310, +219, -650, -184, -848, -500, -258, -462, 505, +-64, 587, 476, 59, 716, -319, 434, -265, +-46, 85, -464, 123, -333, -145, 53, -341, +292, -97, 278, 330, 180, 477, 180, 140, +269, -331, 174, -607, -195, -499, -500, 59, +-303, 641, 320, 812, 939, 192, 870, -680, +-123, -1108, -1004, -519, -822, 577, 229, 1154, +1125, 606, 952, -491, -127, -1035, -917, -652, +-443, 254, 617, 687, 888, 440, 216, -97, +-631, -255, -516, -209, 266, -255, 881, -345, +553, -33, -179, 609, -516, 729, -348, 15, +90, -983, 480, -1013, 527, 68, 353, 1188, +-103, 978, -437, -417, -262, -1330, 398, -723, +654, 692, 141, 1189, -435, 248, -289, -1011, +583, -974, 984, 205, 191, 1007, -1076, 479, +-962, -517, 548, -721, 1523, -79, 796, 390, +-711, 91, -1177, -337, -72, -95, 1237, 683, +839, 582, -634, -524, -1098, -1473, 204, -778, +1508, 1010, 1140, 1872, -545, 752, -1615, -1266, +-655, -1968, 1069, -702, 1566, 1052, 398, 1501, +-786, 530, -684, -618, 266, -867, 648, -414, +76, 61, -552, 177, -231, 73, 753, 179, +1230, 355, 456, 216, -838, -281, -1269, -700, +-432, -493, 922, 102, 1535, 586, 869, 584, +-375, 50, -1006, -459, -650, -544, 142, -134, +564, 312, 578, 202, 364, -196, 271, -363, +162, 136, -205, 667, -580, 391, -460, -489, +304, -1049, 915, -590, 917, 367, 240, 997, +-428, 849, -502, 68, -272, -808, 43, -1183, +296, -714, 558, 363, 685, 1240, 479, 1118, +-168, 21, -796, -1149, -762, -1271, 88, -301, +954, 728, 1152, 864, 474, 229, -368, -233, +-755, -201, -462, -133, 180, -341, 573, -550, +728, -110, 459, 642, 20, 926, -397, 253, +-386, -780, 9, -1046, 335, -337, 456, 579, +252, 747, 102, 187, 35, -328, 4, -327, +5, -127, -34, -80, 108, -147, 343, 59, +404, 385, 113, 282, -229, -243, -125, -646, +349, -261, 552, 500, 180, 666, -463, -66, +-449, -877, 264, -631, 929, 456, 669, 1027, +-300, 307, -734, -855, -249, -1059, 609, 61, +705, 1064, 152, 725, -322, -633, -64, -1235, +510, -177, 468, 1126, -144, 1049, -655, -503, +-170, -1527, 775, -767, 1008, 934, 198, 1535, +-618, 335, -625, -1181, 26, -1273, 683, -44, +575, 958, 54, 726, -240, -154, 74, -601, +311, -312, 198, 149, -72, 195, -153, -87, +54, -196, 360, -36, 473, 234, 277, 225, +48, -34, -232, -374, -371, -407, -116, -31, +441, 347, 724, 377, 441, 82, -54, -227, +-390, -389, -308, -268, 55, -52, 299, 261, +410, 327, 483, 251, 378, -71, -70, -456, +-461, -533, -369, -219, 73, 423, 611, 670, +694, 358, 328, -405, -171, -785, -360, -421, +-323, 308, -87, 568, 401, 166, 712, -217, +670, -207, 52, 101, -661, 38, -706, -326, +101, -476, 890, 46, 893, 723, 279, 645, +-484, -204, -683, -890, -146, -666, 470, 126, +656, 659, 501, 447, 115, -28, -352, -330, +-550, -215, -176, -134, 449, -169, 902, -101, +638, 212, -168, 439, -730, 187, -534, -289, +247, -514, 846, -212, 809, 210, 174, 315, +-496, 25, -573, -215, -200, -107, 455, 112, +826, 199, 462, -47, -209, -326, -520, -390, +-195, -26, 298, 426, 600, 489, 284, 82, +-222, -422, -152, -536, 234, -245, 348, 160, +107, 319, -156, 289, -44, 168, 294, -38, +379, -397, -15, -615, -239, -259, 67, 482, +367, 794, 340, 226, -143, -597, -413, -765, +50, -63, 725, 618, 590, 509, -278, -320, +-630, -790, -155, -248, 675, 673, 785, 875, +60, -42, -567, -974, -222, -863, 315, 128, +393, 808, 57, 562, -28, -15, 205, -305, +328, -295, -36, -372, -531, -386, -211, 4, +580, 674, 899, 842, 282, 113, -462, -858, +-667, -993, -67, -158, 554, 686, 546, 713, +190, 7, 68, -442, 77, -240, -142, 195, +-438, 129, -324, -336, 410, -509, 1037, -12, +758, 642, -301, 736, -1043, -8, -700, -782, +388, -856, 1118, -172, 815, 591, -71, 700, +-567, 285, -460, -252, 12, -476, 319, -362, +334, -179, 306, 84, 267, 344, 105, 429, +-290, 170, -347, -372, -128, -575, 324, -277, +582, 268, 423, 502, -23, 223, -366, -231, +-317, -475, -15, -251, 412, 252, 526, 460, +237, 166, -132, -371, -232, -527, -167, -112, +101, 366, 329, 410, 336, 23, 55, -236, +-75, -174, -65, -70, -91, -143, -6, -165, +219, 69, 398, 489, 338, 452, -116, -115, +-514, -755, -293, -676, 388, 107, 824, 677, +442, 604, -325, -22, -702, -438, -229, -442, +463, -143, 614, 100, 246, 113, -151, 82, +-162, 180, 26, 192, -24, -28, -161, -357, +35, -458, 519, -161, 639, 288, 91, 526, +-577, 298, -688, -151, 42, -474, 754, -493, +722, -117, 101, 393, -371, 594, -324, 204, +-66, -427, 71, -684, 67, -210, 256, 499, +574, 647, 422, 27, -312, -669, -841, -584, +-529, 128, 519, 742, 1150, 464, 662, -339, +-443, -768, -841, -308, -301, 455, 359, 583, +503, -11, 226, -530, 2, -302, 80, 304, +134, 468, -176, -65, -380, -586, -103, -404, +423, 252, 572, 635, 246, 312, -274, -238, +-392, -522, -65, -385, 243, 2, 242, 301, +55, 394, 38, 237, 151, -55, 194, -372, +-77, -471, -293, -213, -173, 284, 206, 537, +428, 300, 303, -239, -65, -471, -270, -223, +-144, 125, 80, 224, 199, 42, 132, -99, +31, -64, 17, 124, 199, 132, 157, -59, +-110, -266, -252, -260, -112, 0, 185, 285, +434, 328, 310, 70, -79, -251, -306, -322, +-199, -154, -44, 68, 177, 143, 344, 165, +326, 130, 79, 37, -250, -193, -371, -312, +-158, -160, 308, 152, 534, 313, 310, 73, +-185, -130, -421, -81, -207, 54, 229, -94, +385, -250, 191, -107, -49, 284, -204, 368, +-125, 52, 86, -351, 247, -346, 182, 4, +-51, 207, -192, 135, -101, -33, 272, -19, +435, 83, 2, 27, -480, -232, -395, -352, +319, -46, 833, 453, 429, 555, -581, 0, +-958, -682, -156, -699, 901, 51, 940, 758, +-12, 669, -932, -40, -633, -712, 420, -661, +825, -9, 166, 534, -498, 458, -264, 68, +272, -128, 455, -212, -12, -385, -414, -428, +-244, 148, 249, 822, 445, 712, 183, -359, +-141, -1105, -247, -629, -127, 534, 72, 982, +116, 328, 176, -507, 167, -624, 32, -175, +-165, 246, -178, 363, 57, 148, 249, -163, +280, -254, -144, -45, -376, 90, -65, 25, +444, -39, 469, 44, -68, 143, -525, 69, +-426, -190, 114, -302, 534, -111, 463, 284, +74, 383, -306, 113, -369, -311, -157, -396, +13, -139, 234, 168, 404, 239, 343, 219, +-26, 124, -359, -68, -390, -398, -236, -443, +88, -41, 488, 452, 664, 585, 269, 189, +-478, -382, -855, -707, -410, -398, 432, 403, +841, 751, 483, 236, -208, -474, -589, -519, +-237, 97, 152, 409, 84, 40, -84, -380, +189, -227, 506, 331, 261, 396, -332, -17, +-797, -275, -412, -260, 520, -123, 1059, -23, +405, 284, -736, 474, -970, 12, -40, -533, +818, -437, 658, 229, -134, 509, -637, 85, +-465, -386, 244, -375, 693, 115, 306, 550, +-307, 350, -448, -225, -197, -709, 27, -578, +327, 185, 468, 976, 158, 899, -299, -255, +-470, -1234, -277, -951, 139, 284, 507, 1111, +445, 813, -6, -134, -425, -766, -360, -717, +-92, -58, 179, 489, 229, 476, 275, 61, +196, -179, -73, -99, -370, -84, -504, -208, +-134, -208, 511, 134, 840, 547, 227, 356, +-641, -410, -841, -750, -218, -204, 607, 625, +788, 707, 139, -2, -466, -717, -480, -648, +-71, 101, 196, 750, 214, 573, 113, -121, +29, -675, 25, -503, -131, 46, -274, 358, +-137, 431, 293, 310, 425, -79, 0, -542, +-433, -575, -318, -85, 227, 508, 533, 672, +80, 334, -519, -491, -455, -849, 251, -329, +684, 539, 287, 815, -481, 147, -707, -638, +-100, -622, 524, 150, 663, 658, 87, 278, +-589, -373, -597, -519, 6, -143, 502, 374, +473, 526, 22, 166, -480, -377, -379, -584, +163, -240, 340, 346, 20, 628, -156, 298, +-38, -375, 92, -569, 45, -177, -26, 243, +-168, 311, -156, 153, 67, -20, 291, -131, +231, -191, -119, -184, -396, -4, -309, 330, +178, 339, 468, -171, 240, -451, -304, -184, +-417, 298, 12, 332, 349, 49, 114, -252, +-269, -296, -261, -29, 97, 235, 410, 282, +235, 45, -354, -242, -535, -286, -80, -35, +351, 164, 333, 216, 162, 163, -58, -45, +-423, -332, -444, -317, 52, 105, 515, 415, +353, 269, -106, -151, -381, -441, -261, -201, +109, 237, 299, 311, -32, 21, -337, -199, +37, -155, 397, 51, 131, 181, -287, 80, +-450, -214, -203, -241, 317, 73, 636, 317, +208, 289, -568, -118, -702, -514, -27, -407, +642, 285, 512, 702, -265, 282, -588, -474, +-149, -610, 294, -41, 233, 454, -111, 322, +-127, -176, -49, -274, 75, 50, 45, 232, +-110, 34, -168, -335, -63, -273, 277, 191, +348, 522, -170, 270, -582, -376, -318, -679, +273, -188, 546, 591, 375, 661, -188, -91, +-812, -626, -559, -270, 264, 113, 827, 203, +545, 205, -247, 244, -826, -10, -593, -495, +150, -535, 641, 67, 555, 739, 43, 722, +-621, -161, -712, -975, 46, -794, 523, 225, +401, 1091, -68, 758, -345, -330, -272, -963, +122, -579, 103, 288, -190, 629, -13, 336, +240, -190, 86, -244, -47, 98, -168, 37, +-417, -393, -178, -470, 493, 266, 545, 932, +-112, 517, -528, -524, -516, -1038, 41, -434, +536, 488, 401, 800, -228, 350, -447, -290, +-201, -423, 151, -94, 283, -102, -44, -242, +-311, 64, 58, 693, 219, 618, -132, -339, +-180, -977, 27, -587, 27, 495, 2, 985, +87, 359, -240, -626, -200, -812, 281, 12, +361, 791, -168, 398, -580, -586, -329, -637, +380, 298, 645, 750, -30, 91, -579, -581, +-300, -437, 110, 216, 285, 528, 164, 128, +-379, -380, -352, -406, 427, 165, 546, 534, +-348, 202, -651, -566, -187, -625, 214, 371, +458, 872, 306, 61, -311, -894, -442, -461, +49, 616, -3, 765, -262, -159, 50, -882, +444, -381, 305, 670, -158, 796, -569, -208, +-477, -830, 155, -307, 479, 603, 212, 589, +-41, -272, -274, -758, -187, -98, 110, 867, +-56, 593, -369, -711, -1, -1106, 573, 115, +290, 1233, -278, 680, -529, -826, -307, -1199, +249, 45, 407, 1289, -82, 755, -322, -964, +100, -1368, 292, 207, -43, 1563, -366, 769, +-449, -1140, -89, -1446, 581, 267, 540, 1521, +-137, 557, -528, -1107, -440, -1066, -73, 454, +317, 1264, 362, 371, -29, -1054, -128, -1101, +-71, 315, -229, 1209, -185, 602, 62, -665, +275, -937, 173, -34, -190, 768, -396, 339, +-50, -678, 370, -489, 117, 675, -221, 937, +-222, -233, -141, -1278, 82, -713, 253, 873, +61, 1381, -216, 85, -46, -1259, 34, -829, +-135, 672, -157, 1109, -49, 19, 93, -1197, +366, -770, 226, 861, -338, 1435, -569, 169, +-223, -1375, 227, -1271, 363, 332, 354, 1488, +27, 812, -365, -742, -544, -1114, -294, -48, +242, 682, 562, 345, 414, -299, -219, -396, +-696, 212, -478, 450, 262, 0, 720, -504, +216, -290, -524, 355, -640, 404, 84, -12, +702, -393, 242, -261, -504, 296, -536, 443, +129, 44, 439, -437, 154, -474, -361, 51, +-390, 568, 259, 493, 568, -113, -97, -632, +-733, -420, -401, 206, 286, 539, 710, 265, +367, -291, -439, -327, -861, 40, -159, 219, +641, 80, 392, -203, -361, -218, -464, 110, +234, 429, 650, 296, -17, -388, -898, -759, +-599, -153, 421, 829, 985, 881, 442, -291, +-604, -1149, -971, -534, -250, 705, 657, 1002, +517, 47, -146, -771, -352, -448, -116, 338, +168, 357, 60, -236, -232, -371, -327, 232, +233, 813, 595, 381, -92, -888, -669, -1497, +-301, -117, 461, 1804, 550, 1617, -82, -629, +-562, -2138, -486, -939, 229, 1271, 659, 1619, +320, -151, -472, -1379, -632, -460, 84, 1097, +443, 910, 25, -681, -272, -1516, -119, -316, +213, 1478, 271, 1510, -57, -297, -492, -1776, +-373, -1116, 290, 929, 435, 1669, -6, 187, +-176, -1555, 31, -958, 114, 1228, -227, 1661, +-452, -339, -219, -2165, 487, -1236, 859, 1498, +163, 2514, -758, 447, -847, -2250, -37, -2144, +623, 750, 328, 2329, -149, 781, -116, -1616, +304, -1452, 109, 920, -661, 1744, -880, -88, +-33, -2056, 1255, -1111, 1166, 1702, -468, 2320, +-1515, -233, -711, -2694, 714, -1521, 977, 1834, +78, 2649, -581, -166, -360, -2728, 498, -1533, +357, 1756, -506, 2600, -734, 0, 159, -2457, +918, -1607, 386, 1274, -651, 2047, -783, 39, +214, -1449, 816, -513, 67, 877, -770, 430, +-575, -768, 354, -670, 1019, 641, 369, 1151, +-881, 37, -1035, -1193, 275, -688, 874, 642, +113, 830, -362, -202, -142, -765, 224, 162, +216, 981, -301, 217, -597, -1247, 15, -1066, +760, 804, 427, 1716, -419, 399, -572, -1390, +-185, -1491, 415, 324, 467, 1752, -269, 806, +-669, -1153, -56, -1456, 628, 216, 425, 1320, +-87, 659, -599, -547, -681, -941, 43, -128, +793, 432, 508, 241, -72, 8, -412, 310, +-429, 370, -202, -583, 244, -1205, 313, -216, +177, 1491, 18, 1546, -183, -525, -59, -2109, +-21, -995, -269, 1306, -279, 1891, 269, 168, +594, -1613, 191, -1192, -382, 665, -664, 1499, +-321, 41, 524, -1235, 678, -503, -69, 1079, +-612, 936, -317, -852, 298, -1523, 506, 121, +132, 1960, -498, 1051, -555, -1322, 211, -2100, +664, -134, 241, 1843, -408, 1549, -450, -442, +71, -1671, 370, -789, 82, 709, -401, 962, +-290, -30, 345, -508, 525, 68, -14, 571, +-621, 18, -402, -882, 170, -684, 414, 482, +104, 1156, -251, 382, -12, -637, 377, -588, +124, 111, -670, 220, -814, -398, 243, -387, +1243, 531, 939, 1286, -560, 517, -1536, -1222, +-746, -1714, 850, -306, 1273, 1448, 199, 1520, +-863, 89, -648, -1184, 239, -956, 659, 277, +9, 751, -842, 41, -520, -623, 658, -246, +1146, 812, 158, 1054, -988, -132, -1051, -1514, +-230, -1281, 970, 548, 1104, 1724, 211, 1061, +-842, -600, -990, -1423, -120, -633, 599, 537, +830, 749, 180, 114, -641, -168, -688, 23, +18, 97, 526, -144, 344, -440, -101, -148, +-256, 482, -297, 577, -205, -202, 45, -674, +342, -158, 563, 695, 5, 596, -747, -460, +-702, -1099, 194, -229, 822, 1154, 527, 1117, +-298, -281, -656, -1382, -171, -794, 397, 672, +179, 1271, -342, 260, -54, -950, 402, -679, +360, 484, -323, 856, -737, -178, -276, -1025, +683, -463, 794, 1098, -267, 1235, -1058, -208, +-401, -1504, 794, -976, 989, 746, -334, 1328, +-1196, 410, -370, -821, 893, -515, 917, 194, +-351, 100, -920, -375, -302, -126, 754, 742, +813, 899, -459, -156, -1108, -1451, -210, -1038, +1193, 805, 810, 1861, -580, 538, -1097, -1337, +-334, -1553, 556, 56, 689, 1467, 62, 1095, +-393, -472, -309, -1241, -1, -634, -6, 516, +-80, 886, 44, 508, 301, -201, 260, -700, +-267, -701, -497, -52, 49, 925, 477, 973, +145, -136, -459, -1281, -363, -944, 452, 641, +898, 1671, 60, 683, -1389, -1391, -1130, -1958, +749, -16, 1890, 2178, 713, 1918, -1373, -767, +-1860, -2686, -325, -1465, 1467, 1500, 1387, 2747, +-160, 824, -1176, -1931, -700, -2415, 363, -188, +492, 2226, -18, 1925, -170, -549, 270, -2206, +293, -1242, -257, 992, -588, 2031, -165, 862, +558, -1247, 679, -1876, -230, -475, -1033, 1322, +-439, 1522, 1014, 257, 1199, -926, -210, -1125, +-1572, -337, -1367, 508, 453, 814, 2003, 460, +1434, -116, -726, -434, -2076, -378, -1437, -235, +382, -88, 1840, 150, 1714, 762, -20, 843, +-1654, -111, -1775, -1324, -304, -1453, 1382, 93, +1788, 1965, 533, 2107, -1201, -294, -1729, -2769, +-488, -2288, 1093, 949, 1344, 3040, 294, 1860, +-837, -1226, -1037, -2683, -337, -1230, 545, 1146, +755, 1850, 109, 643, -326, -669, -206, -827, +-73, -187, -131, 181, -315, -131, -46, -247, +500, 294, 857, 908, 378, 538, -898, -492, +-1395, -1282, -545, -813, 1158, 629, 1713, 1352, +507, 765, -1245, -515, -1605, -1130, -221, -608, +1088, 438, 966, 1065, -367, 226, -906, -824, +56, -644, 891, 344, 314, 1007, -1029, 434, +-1272, -639, 228, -1117, 1605, -473, 1155, 772, +-791, 1089, -1644, 429, -359, -427, 1133, -716, +973, -397, -623, -162, -1288, 81, 85, 455, +1714, 679, 1187, 571, -1356, -160, -2509, -1027, +-575, -1203, 2232, -188, 2443, 1305, -237, 1471, +-2600, 306, -1824, -1066, 905, -1355, 2359, -424, +952, 725, -1442, 1100, -2162, 475, -156, -598, +1972, -1008, 1749, -181, -380, 1051, -2122, 963, +-1519, -660, 550, -1552, 2038, -739, 1401, 1245, +-502, 2169, -1630, 743, -1133, -1777, 186, -2679, +1026, -585, 733, 2146, 59, 2711, -303, 434, +-308, -2255, -435, -2374, -495, -38, 54, 2109, +770, 1657, 697, -338, -117, -1620, -842, -908, +-637, 598, 300, 998, 710, 198, 226, -403, +-571, -227, -361, 103, 365, -125, 699, -349, +-80, 45, -1084, 689, -608, 742, 963, -358, +1489, -1110, -22, -740, -1679, 496, -1539, 1294, +469, 710, 2172, -495, 1547, -1210, -1142, -705, +-2504, 500, -1233, 1160, 1327, 582, 2281, -596, +907, -1150, -1104, -231, -1818, 887, -854, 974, +630, -119, 1381, -1109, 840, -758, -264, 437, +-868, 1064, -742, 694, -143, -435, 566, -959, +770, -718, 214, 295, -447, 904, -778, 600, +-179, -90, 502, -479, 665, -545, -123, -236, +-565, 83, -503, 524, 56, 657, 483, 248, +409, -573, 18, -973, -271, -398, -368, 663, +-412, 1133, -173, 440, 553, -630, 983, -1188, +482, -408, -724, 610, -1630, 1053, -665, 369, +1233, -518, 1967, -693, 328, -143, -1579, 146, +-1705, 82, -55, 52, 1523, 582, 1341, 601, +-335, -260, -1472, -1224, -840, -1265, 632, 451, +1104, 2087, 256, 1823, -688, -864, -670, -2884, +-78, -1905, 397, 1343, 538, 3126, 199, 1820, +-229, -1403, -461, -3138, -461, -1771, -84, 1219, +673, 3099, 977, 1840, 15, -1000, -1097, -2922, +-996, -1944, 60, 801, 1106, 2621, 1054, 2009, +-169, -357, -1236, -2331, -899, -2092, 197, -7, +905, 1986, 823, 2032, 41, 319, -871, -1376, +-913, -1810, -286, -728, 685, 777, 1331, 1469, +640, 1075, -1072, -201, -1761, -1086, -451, -1078, +1355, -236, 1890, 614, 360, 754, -1838, 482, +-1876, -6, 415, -213, 1989, -468, 1058, -546, +-1008, -477, -1752, 241, -321, 939, 1538, 1218, +1380, 252, -816, -1300, -1837, -1815, -606, -584, +1382, 1405, 1717, 2081, -108, 838, -1784, -1090, +-1047, -2059, 842, -1152, 1323, 752, 35, 1809, +-934, 1312, -573, -303, 721, -1374, 1063, -1273, +-312, -203, -1555, 902, -769, 1185, 1042, 505, +1763, -447, 543, -855, -1333, -492, -1819, 14, +-492, 174, 1238, 341, 1492, 507, 514, 611, +-851, 16, -1227, -1071, -569, -1264, 386, -227, +675, 1301, 624, 1598, 128, 371, -288, -1099, +-423, -1414, -388, -362, -439, 555, -35, 544, +786, 327, 1178, 452, 603, 509, -1138, -217, +-2092, -1361, -1077, -1437, 1573, -44, 2739, 1834, +1006, 2063, -1830, 386, -2876, -1661, -739, -2020, +1895, -811, 2237, 772, 119, 1454, -1645, 1185, +-1137, 510, 654, -496, 1135, -1384, -227, -1685, +-1466, -585, -500, 1300, 1391, 2276, 1967, 1463, +353, -575, -2066, -2231, -2560, -2139, -493, -433, +2213, 1695, 2980, 2489, 965, 1368, -2094, -768, +-3371, -2439, -1343, -2050, 1825, -33, 3202, 1930, +1485, 2248, -1451, 765, -2885, -1214, -1354, -2147, +1199, -1186, 2170, 695, 885, 1835, -816, 1182, +-1467, -474, -578, -1556, 560, -772, 826, 773, +517, 1294, -27, 209, -624, -1301, -1165, -1382, +-377, 274, 1053, 2030, 1895, 1772, 810, -523, +-1606, -2586, -3118, -2295, -1187, 232, 2393, 2792, +4002, 2848, 1440, 469, -2834, -2424, -4744, -3207, +-1813, -1400, 3114, 1476, 4932, 3186, 1914, 2399, +-2731, -188, -4685, -2767, -2261, -3233, 2191, -1069, +4217, 2124, 2288, 3682, -1378, 2040, -3424, -1524, +-2434, -3824, 595, -2372, 2640, 1332, 2252, 3613, +103, 2071, -1644, -1511, -1992, -3259, -1011, -1387, +632, 2051, 1709, 2837, 1795, 518, 394, -2266, +-1466, -2365, -2577, -123, -1478, 1920, 1163, 1823, +3244, 444, 2429, -782, -817, -1236, -3683, -1306, +-3256, -865, 412, 483, 3780, 2185, 3688, 2688, +122, 586, -3386, -2773, -3760, -4095, -860, -1640, +2649, 2600, 3504, 4701, 1441, 2496, -1594, -1833, +-3111, -4166, -1993, -2735, 699, 606, 2598, 2649, +2007, 2372, -138, 699, -1934, -849, -1794, -1400, +-48, -1490, 1332, -875, 1036, 286, -84, 1634, +-490, 1908, -109, 650, 58, -1197, -351, -2111, +-725, -1242, 69, 589, 1370, 1828, 1356, 1359, +-593, -236, -2426, -1521, -1710, -1075, 1346, 438, +3324, 1433, 1738, 715, -2022, -967, -3863, -1824, +-1753, -584, 2154, 1560, 3970, 2403, 1821, 871, +-1866, -1704, -3558, -2833, -1868, -1461, 1081, 1180, +2508, 2631, 1711, 2046, 107, 142, -1032, -1673, +-1390, -2402, -1333, -1796, -520, 53, 866, 2401, +2073, 3385, 1930, 1505, -118, -2080, -2484, -4034, +-2839, -2407, -495, 1253, 2195, 3507, 2893, 2563, +1120, -152, -1402, -1974, -2532, -2015, -1595, -1047, +350, 53, 1694, 1171, 1923, 1951, 819, 1629, +-898, -248, -2185, -2383, -1835, -2712, 271, -414, +2410, 2375, 2304, 2916, 86, 743, -2284, -1895, +-2290, -2339, -302, -680, 1768, 946, 1808, 1138, +237, 538, -757, 294, -772, 289, -354, -431, +-457, -1568, -426, -1493, 229, 444, 1417, 2353, +1812, 2030, 71, -193, -2160, -2230, -2813, -2101, +-649, -317, 2296, 1335, 3177, 1591, 1230, 1018, +-1705, 169, -2829, -787, -1689, -1661, 666, -1643, +1976, -102, 1517, 1876, 429, 2564, -498, 909, +-1075, -1465, -1379, -2630, -779, -1490, 447, 697, +1610, 1864, 1499, 1440, 123, 233, -1240, -392, +-1372, -924, -415, -1133, 359, -896, 465, 118, +162, 1195, 610, 1624, 1069, 1072, 483, -361, +-1514, -1820, -2566, -2330, -1208, -1006, 1745, 1486, +3615, 3326, 2133, 2422, -1662, -836, -3969, -3679, +-2642, -3415, 1016, 56, 3515, 3457, 2821, 3537, +-176, 485, -2698, -2539, -2435, -2668, -418, -593, +1375, 1051, 1498, 1018, 739, 296, 136, 558, +-328, 1073, -883, 231, -1418, -1884, -764, -2998, +705, -799, 2142, 2723, 1708, 4023, -421, 1254, +-2466, -2823, -2044, -4068, 312, -1237, 2029, 2416, +1770, 2970, -62, 711, -1537, -1497, -1200, -1385, +318, -15, 1068, 747, 375, 48, -826, -915, +-956, -453, 194, 931, 1514, 1489, 1392, 423, +-487, -1119, -2264, -1369, -2046, -510, 448, 467, +2752, 754, 2364, 535, -326, 365, -2488, 108, +-2102, -264, 87, -686, 1617, -848, 1204, -417, +28, 350, -419, 1029, 42, 1282, 55, 638, +-642, -706, -1185, -1878, -284, -1696, 1217, 6, +1643, 1792, 406, 2330, -1019, 786, -1357, -1197, +-406, -1973, 345, -1162, 442, 94, 232, 868, +270, 1004, 472, 804, 300, 456, -448, -86, +-1129, -999, -966, -1576, 196, -1157, 1180, 361, +1383, 1976, 517, 2193, -833, 831, -1562, -1270, +-927, -2644, 375, -2301, 1123, -165, 927, 2550, +-59, 3406, -546, 1448, -292, -1893, 120, -3634, +-130, -2063, -589, 1072, -355, 2799, 485, 1755, +1080, -311, 715, -1266, -466, -834, -1088, -167, +-729, -131, 167, -258, 581, 229, 251, 923, +74, 973, 175, 7, 417, -887, 140, -1048, +-700, -295, -1105, 422, -616, 445, 429, 263, +1384, 211, 1461, 393, 356, 123, -1143, -480, +-1996, -1070, -1436, -807, 288, 337, 2064, 1367, +2303, 1212, 691, 70, -1569, -961, -2499, -1126, +-1434, -519, 732, 29, 2009, 584, 1462, 797, +71, 883, -874, 242, -940, -704, -555, -1414, +-199, -1045, 17, 214, 485, 1454, 978, 1663, +910, 386, -181, -1237, -1275, -1848, -1419, -682, +-140, 817, 1263, 1482, 1345, 790, 162, -281, +-1118, -918, -978, -855, 151, -204, 1120, 493, +681, 976, -664, 525, -1404, -391, -525, -1029, +996, -714, 1659, 348, 771, 1066, -885, 905, +-1787, -233, -1137, -1147, 399, -969, 1408, 21, +1463, 969, 283, 1046, -887, 312, -1203, -575, +-696, -1059, -61, -671, 519, 151, 863, 853, +759, 890, 407, 312, -412, -312, -1323, -968, +-1371, -1078, 20, -207, 1484, 1205, 1720, 1829, +424, 501, -1341, -1612, -1718, -2257, -458, -448, +1153, 1947, 1266, 2268, 95, 261, -979, -2018, +-689, -2085, 448, 73, 865, 1956, 214, 1426, +-647, -469, -872, -1409, -285, -518, 655, 672, +929, 566, 488, -377, -216, -636, -783, 415, +-943, 1016, -454, 251, 574, -1141, 1188, -1183, +1074, 221, 1, 1544, -1235, 994, -1638, -804, +-614, -1575, 1077, -462, 1865, 1198, 1131, 1347, +-603, -34, -1843, -1338, -1498, -1036, 116, 320, +1589, 1124, 1557, 683, 241, -152, -1098, -686, +-1306, -439, -394, -60, 510, -2, 721, 39, +342, 419, 97, 763, 86, 336, -203, -669, +-681, -1275, -706, -719, 49, 698, 973, 1492, +1065, 789, 117, -468, -1070, -1165, -1044, -685, +-51, 99, 848, 543, 740, 335, -100, 170, +-647, 196, -233, 137, 393, -257, 428, -721, +-120, -625, -650, 118, -476, 946, 322, 885, +917, 57, 497, -719, -343, -792, -752, -345, +-564, 228, 67, 564, 623, 506, 497, 154, +3, -287, -279, -430, -253, -204, -33, 90, +123, 82, -119, -19, -168, -50, 21, 239, +356, 444, 308, 232, 88, -450, -328, -798, +-509, -415, -75, 297, 234, 733, 175, 652, +31, 132, 172, -301, 224, -609, 106, -708, +-290, -453, -704, 335, -518, 1075, 332, 1098, +1085, 260, 885, -882, -284, -1469, -1204, -1073, +-931, 174, 185, 1398, 1025, 1821, 730, 808, +-144, -980, -820, -2189, -421, -1637, 470, 332, +736, 2050, 9, 1958, -855, 183, -871, -1422, +154, -1503, 1247, -351, 1185, 427, -191, 441, +-1362, 227, -1239, 585, -31, 810, 1013, 2, +1057, -1310, 322, -1595, -398, -213, -630, 1518, +-485, 1702, -132, 186, 125, -1248, 304, -1094, +392, 92, 252, 658, -71, 158, -202, -425, +-68, -128, -253, 680, -520, 655, -226, -224, +473, -1007, 1061, -710, 678, 313, -366, 927, +-1228, 471, -898, -425, 54, -557, 793, 32, +878, 552, 297, 247, -236, -440, -362, -884, +-359, -305, -368, 762, -256, 1217, 41, 620, +505, -653, 803, -1463, 645, -1085, -205, 273, +-1085, 1433, -1287, 1351, -419, 187, 1052, -984, +1673, -1292, 820, -511, -712, 320, -1461, 734, +-850, 671, 267, 441, 822, -71, 436, -717, +26, -928, 141, -318, 155, 665, -240, 925, +-843, 250, -637, -555, 342, -484, 1101, 140, +707, 499, -397, -34, -871, -785, -338, -559, +342, 604, 426, 1232, -76, 518, -357, -827, +-112, -1282, 377, -478, 470, 772, 12, 1046, +-442, 243, -424, -602, -128, -571, 187, 77, +319, 416, 291, 158, 194, -322, -158, -358, +-370, -40, -358, 337, -58, 460, 287, 301, +365, -143, 91, -616, -241, -734, -138, -222, +130, 735, 207, 1112, -67, 437, -397, -658, +-451, -1093, 68, -475, 722, 415, 772, 749, +43, 232, -738, -265, -918, -120, -286, 302, +434, 212, 733, -450, 488, -919, 58, -462, +-249, 750, -238, 1433, -431, 877, -672, -631, +-284, -1688, 654, -1396, 1359, 283, 907, 1708, +-329, 1627, -1592, 76, -1582, -1394, -237, -1530, +1334, -298, 1852, 996, 832, 1075, -736, 186, +-1573, -596, -1111, -410, 86, 194, 945, 289, +859, -277, 226, -607, -147, -102, -91, 683, +-154, 861, -459, 143, -706, -757, -376, -963, +535, -241, 1408, 558, 1060, 847, -314, 388, +-1578, -288, -1484, -641, -186, -417, 1228, 93, +1495, 351, 609, 360, -532, 14, -1083, -231, +-792, -129, -115, 103, 485, 68, 658, -218, +410, -258, 102, 58, -225, 545, -343, 471, +-411, -212, -274, -911, 25, -584, 489, 414, +615, 1133, 259, 654, -377, -605, -720, -1348, +-340, -586, 389, 828, 578, 1417, -38, 427, +-479, -1093, -184, -1367, 493, -87, 634, 1346, +-80, 1144, -912, -339, -811, -1475, 174, -881, +1066, 753, 844, 1573, -105, 553, -754, -1083, +-655, -1483, -161, -292, 196, 1144, 333, 1276, +422, 141, 346, -963, 145, -1005, -469, -131, +-828, 666, -477, 731, 391, 125, 839, -459, +594, -451, 12, 24, -485, 364, -692, 238, +-419, -346, 50, -518, 601, 10, 786, 747, +292, 743, -453, -166, -858, -1120, -502, -1019, +311, 283, 878, 1384, 478, 1107, -381, -384, +-718, -1366, -244, -988, 473, 364, 656, 1147, +8, 727, -706, -275, -669, -775, 235, -557, +904, 85, 617, 563, -288, 532, -904, 61, +-578, -554, 245, -655, 729, -80, 450, 661, +-214, 777, -450, 26, -75, -742, 271, -771, +94, -3, -428, 702, -401, 577, 287, -27, +824, -364, 562, -231, -477, -121, -1096, -106, +-595, -50, 538, 306, 1069, 513, 439, 220, +-465, -456, -776, -696, -274, -232, 464, 447, +497, 573, -9, 213, -456, -276, -296, -376, +132, -148, 458, -25, 458, 126, 18, 241, +-665, 315, -764, -19, -131, -499, 696, -476, +903, 192, 503, 770, -452, 390, -1130, -576, +-744, -881, 272, -40, 988, 927, 740, 820, +1, -433, -647, -1239, -583, -563, 1, 891, +273, 1369, 148, 260, -123, -1218, 3, -1438, +318, 34, 365, 1431, -76, 1297, -558, -235, +-672, -1393, -31, -1032, 724, 286, 750, 1197, +-1, 692, -534, -382, -365, -802, 30, -241, +97, 380, -148, 298, -152, -237, 363, -274, +742, 260, 226, 535, -730, -59, -951, -695, +-202, -493, 759, 444, 823, 929, 20, 196, +-472, -854, -275, -921, 82, 186, 25, 1058, +-135, 745, -144, -335, 223, -1046, 531, -613, +65, 287, -518, 674, -337, 465, 327, 94, +435, -51, -172, -328, -748, -693, -321, -632, +863, 184, 1242, 1217, 9, 1202, -1345, -36, +-1338, -1377, 40, -1523, 1422, -247, 1339, 1260, +-70, 1522, -1224, 436, -890, -907, 142, -1202, +656, -510, 332, 489, -168, 773, -178, 370, +166, -191, 303, -387, 17, -145, -436, 143, +-542, 221, -104, -103, 470, -356, 673, -179, +308, 184, -154, 490, -590, 363, -569, -60, +-119, -467, 301, -555, 447, -293, 434, 174, +210, 645, -201, 708, -464, 197, -497, -479, +-371, -847, 174, -665, 793, 8, 834, 720, +216, 1032, -613, 560, -1208, -351, -681, -1135, +557, -1066, 1184, -85, 675, 956, -227, 1250, +-766, 426, -573, -601, 36, -971, 346, -560, +188, 94, -29, 431, 16, 423, 258, 294, +312, 192, -231, -16, -733, -503, -507, -802, +364, -374, 847, 438, 641, 1107, -228, 820, +-861, -222, -645, -1229, 231, -1117, 737, 31, +448, 1115, -199, 1155, -563, 108, -284, -914, +328, -974, 440, -97, 55, 579, -293, 571, +-268, 145, -32, -209, 105, -244, 148, -181, +159, -166, 181, 21, 18, 317, -318, 482, +-489, 76, -212, -595, 401, -706, 797, 58, +311, 888, -438, 702, -686, -343, -238, -955, +183, -480, 310, 499, 128, 796, 119, 132, +297, -527, 131, -353, -503, 270, -906, 306, +-270, -228, 771, -543, 1168, -16, 432, 729, +-789, 694, -1204, -257, -356, -1005, 675, -686, +851, 324, 160, 921, -377, 656, -332, -131, +56, -663, 134, -617, -129, -175, -228, 356, +34, 573, 348, 326, 320, -126, -26, -356, +-305, -270, -266, -86, -50, -1, 51, 59, +125, 226, 205, 363, 155, 195, 47, -301, +-136, -603, -281, -338, -299, 223, -50, 606, +368, 404, 538, -112, 220, -399, -436, -330, +-616, -66, -129, 85, 383, 186, 456, 250, +-26, 145, -259, -140, -149, -314, 178, -155, +212, 179, -127, 214, -429, -59, -151, -268, +472, -47, 498, 359, -24, 422, -486, -162, +-371, -658, 81, -483, 353, 248, 178, 693, +-75, 444, -53, -129, 51, -420, -133, -315, +-278, -202, -22, -126, 431, 159, 452, 681, +-112, 661, -628, -65, -521, -1005, 192, -1043, +814, -18, 559, 1104, -312, 1181, -794, 90, +-485, -995, 215, -1040, 551, -76, 491, 738, +87, 685, -289, -15, -546, -453, -338, -283, +140, 143, 531, 279, 406, -53, -57, -340, +-401, -149, -250, 284, 117, 419, 165, 48, +-115, -437, -152, -314, 199, 192, 457, 454, +161, -3, -515, -564, -706, -374, -20, 429, +802, 927, 693, 287, -244, -824, -860, -1156, +-423, -168, 440, 961, 693, 1055, 132, 87, +-460, -783, -356, -648, 43, 46, 219, 327, +61, -17, -39, -192, 162, 231, 150, 647, +-147, 324, -457, -573, -90, -1024, 328, -452, +308, 546, -18, 957, -208, 536, 24, -124, +216, -497, -67, -579, -576, -492, -399, -141, +456, 500, 1035, 1011, 513, 709, -719, -326, +-1260, -1196, -446, -979, 734, 53, 963, 929, +275, 930, -316, 290, -358, -399, -161, -693, +-228, -540, -327, -93, 37, 356, 727, 571, +848, 366, 78, -94, -877, -374, -1089, -343, +-244, -98, 768, 72, 1038, 141, 340, 168, +-406, 170, -750, 75, -465, -112, 85, -268, +504, -205, 366, 13, 51, 200, -210, 207, +-177, 112, 45, -58, 76, -155, -203, -208, +-263, -83, 152, 148, 532, 311, 422, 129, +-231, -279, -802, -444, -443, -40, 465, 556, +770, 549, 234, -166, -447, -817, -546, -555, +-71, 362, 444, 892, 275, 412, -164, -425, +-202, -668, 39, -156, 169, 295, -64, 182, +-223, -143, 2, -37, 428, 371, 274, 385, +-393, -250, -557, -771, -49, -477, 542, 383, +552, 830, -59, 426, -484, -320, -417, -590, +108, -241, 291, 94, 120, 100, -21, 13, +50, 197, 244, 404, -61, 191, -598, -406, +-565, -738, 304, -347, 1013, 452, 625, 823, +-413, 436, -1143, -297, -671, -702, 467, -516, +998, 36, 507, 506, -303, 534, -594, 211, +-340, -258, -35, -534, 85, -430, 148, 51, +423, 552, 460, 587, -138, 27, -761, -564, +-766, -591, 77, -75, 882, 485, 862, 542, +-22, 165, -874, -311, -754, -530, -29, -290, +556, 159, 460, 503, 125, 417, -84, -43, +-229, -434, -330, -457, -261, -57, 51, 345, +396, 333, 476, 82, 90, -139, -483, -119, +-503, -60, -45, -116, 375, -131, 381, 25, +29, 315, -302, 352, -229, -13, 140, -374, +118, -406, -16, -92, -7, 257, 39, 383, +-28, 222, -97, -78, -57, -294, 103, -276, +320, -110, 79, 86, -391, 284, -357, 299, +136, 104, 442, -235, 263, -426, -144, -228, +-359, 205, -111, 422, 277, 247, 158, -176, +-196, -286, -222, -144, 183, 56, 506, 121, +146, 64, -459, 70, -639, -16, -37, -74, +665, -81, 701, -14, -36, 81, -695, 65, +-590, 11, 106, -61, 610, -133, 512, -10, +-73, 138, -546, 232, -404, 48, 156, -267, +519, -354, 291, -86, -213, 401, -507, 452, +-137, -11, 406, -406, 464, -327, -52, 88, +-543, 205, -461, 62, 202, -77, 812, 81, +483, 260, -502, 62, -975, -396, -433, -535, +601, -77, 1072, 571, 424, 714, -697, 147, +-1000, -562, -288, -774, 479, -264, 676, 353, +231, 672, -264, 437, -308, 0, -15, -436, +-69, -653, -253, -480, -129, 187, 286, 939, +526, 862, 309, -91, -330, -1079, -743, -1014, +-465, 17, 192, 1008, 586, 980, 485, 97, +73, -763, -361, -838, -518, -273, -354, 447, +30, 710, 418, 407, 554, -199, 145, -581, +-409, -420, -629, 22, -210, 382, 443, 378, +579, 115, -1, -183, -565, -343, -419, -203, +250, 40, 613, 231, 292, 332, -385, 173, +-709, -219, -282, -606, 438, -345, 732, 399, +366, 864, -356, 391, -731, -616, -389, -1044, +291, -302, 616, 770, 329, 975, -178, 114, +-383, -694, -123, -615, 166, 32, 156, 389, +-115, 114, -190, -105, 141, 66, 442, 338, +258, 99, -298, -494, -618, -593, -228, 29, +415, 708, 712, 584, 264, -190, -446, -666, +-591, -375, -35, 340, 431, 583, 270, 40, +-126, -560, -119, -435, 107, 343, 168, 736, +3, 201, -286, -547, -244, -655, 166, -98, +565, 400, 272, 472, -297, 211, -613, -126, +-228, -340, 450, -316, 671, -57, 151, 222, +-549, 326, -636, 37, -14, -242, 627, -118, +630, 252, -55, 286, -714, -199, -640, -648, +43, -388, 744, 446, 735, 1030, 36, 586, +-796, -572, -877, -1275, -117, -853, 766, 495, +864, 1440, 133, 1028, -600, -411, -713, -1429, +-265, -941, 228, 409, 393, 1075, 339, 513, +144, -316, -94, -326, -417, -7, -616, -154, +-266, -430, 397, -99, 804, 677, 460, 786, +-339, -70, -908, -924, -733, -772, 166, 212, +900, 894, 741, 635, -171, -215, -845, -785, +-619, -570, 140, 206, 524, 703, 303, 476, +-87, -176, -210, -548, -116, -363, -109, 78, +-148, 302, 42, 267, 326, 151, 230, -59, +-159, -304, -387, -370, -191, -37, 195, 342, +387, 419, 76, 40, -356, -330, -269, -345, +193, 38, 425, 275, 104, 146, -373, -121, +-479, -169, 37, -48, 600, 76, 588, 160, +-97, 226, -719, 4, -523, -463, 187, -557, +537, 122, 472, 867, 219, 658, -178, -276, +-665, -924, -508, -671, 244, 128, 788, 742, +540, 791, -156, 187, -606, -648, -336, -908, +255, -356, 378, 625, -2, 882, -246, 211, +90, -546, 436, -535, 197, 1, -373, 261, +-497, 190, -129, 92, 349, -151, 628, -283, +381, 74, -288, 492, -737, 154, -278, -619, +307, -530, 478, 299, 302, 793, -21, 318, +-396, -508, -329, -755, 126, -166, 318, 606, +91, 635, -134, -56, -118, -524, 29, -317, +119, 85, 80, 194, -202, 161, -222, 91, +101, -49, 408, -89, 40, -25, -493, -112, +-325, -235, 347, 62, 479, 519, -24, 307, +-469, -369, -468, -570, 85, -45, 572, 477, +322, 292, -363, -233, -524, -375, -125, 99, +261, 438, 316, 151, 17, -416, -364, -480, +-256, -3, 202, 498, 305, 520, -90, 10, +-438, -512, -267, -498, 228, -4, 552, 391, +196, 348, -517, 75, -703, -155, -98, -274, +631, -151, 580, 95, -100, 163, -573, 6, +-438, -53, 98, 85, 390, 121, 277, -65, +-194, -216, -370, -161, -14, 72, 403, 273, +197, 207, -378, -80, -585, -338, 29, -237, +721, 198, 624, 472, -219, 171, -817, -504, +-579, -683, 209, 103, 857, 984, 621, 733, +-218, -505, -738, -1315, -486, -606, 169, 779, +656, 1341, 476, 476, -270, -834, -551, -1123, +-17, -271, 406, 626, 155, 731, -231, 110, +-168, -364, 149, -258, 421, 127, 122, 99, +-393, -290, -454, -284, 148, 200, 694, 557, +360, 354, -303, -288, -624, -686, -209, -361, +386, 367, 674, 607, 263, 162, -489, -305, +-657, -356, -4, -59, 583, 198, 506, 224, +-76, 1, -513, -157, -414, -174, 249, -38, +644, 136, 148, 176, -443, 150, -318, 39, +75, -277, 165, -472, 125, -153, 107, 521, +31, 708, -119, 104, -214, -627, -218, -742, +101, -54, 341, 694, 203, 565, -218, -122, +-283, -553, 9, -240, 148, 286, -82, 320, +-179, -132, -7, -399, 173, -20, 256, 424, +140, 271, -370, -191, -636, -424, -114, -177, +528, 295, 455, 374, -10, -56, -358, -425, +-270, -92, 45, 445, -28, 316, -282, -361, +-67, -625, 552, -29, 541, 672, -221, 558, +-759, -235, -584, -731, 116, -396, 683, 368, +517, 663, -132, 178, -585, -404, -300, -492, +217, -64, 224, 431, -177, 437, -225, -168, +153, -563, 297, -124, 180, 515, -117, 280, +-460, -336, -452, -353, 185, 176, 625, 424, +333, 36, -253, -427, -389, -383, -106, 154, +146, 550, 39, 377, -91, -249, 146, -663, +276, -305, 32, 377, -225, 554, -296, 44, +-100, -346, 398, -202, 407, 145, -81, 308, +-388, -85, -214, -566, 54, -358, 479, 527, +473, 997, -325, 235, -721, -863, 12, -1005, +510, -203, 292, 710, 18, 914, -182, 387, +-193, -452, 8, -887, 151, -359, -19, 356, +60, 530, 41, 109, -12, -187, 122, -114, +96, 103, -100, 233, -184, -76, -173, -527, +-14, -446, 460, 323, 554, 867, -270, 448, +-606, -442, -203, -769, 85, -391, 355, 314, +459, 569, -4, 234, -515, -349, -253, -273, +167, 416, 243, 416, 128, -517, -180, -992, +-311, 3, 131, 1181, 336, 857, 137, -474, +-211, -1106, -423, -397, -220, 592, 367, 676, +435, -24, -117, -565, -126, -324, -70, 433, +-326, 692, -123, -62, 332, -956, 235, -583, +-66, 633, -89, 1004, -235, -40, -128, -833, +286, -270, 112, 580, -311, 430, -236, -606, +169, -809, 390, 304, 163, 1194, -323, 557, +-528, -901, -137, -1167, 260, 13, 412, 949, +314, 619, -243, -444, -514, -693, -90, 217, +174, 771, -51, -14, 42, -990, 264, -599, +135, 729, -53, 1196, -309, 224, -406, -1133, +92, -1087, 481, 423, 80, 1355, -271, 299, +15, -1178, 188, -891, 75, 837, -164, 1454, +-498, -57, -210, -1727, 557, -1088, 710, 1134, +35, 1874, -499, 146, -584, -1669, -123, -1215, +409, 734, 432, 1523, -28, 165, -200, -1226, +72, -809, 188, 719, -73, 1211, -495, 98, +-317, -1209, 441, -1032, 691, 534, 125, 1442, +-329, 430, -347, -993, -173, -958, 69, 229, +171, 896, 15, 239, 132, -659, 354, -541, +96, 454, -337, 800, -520, -5, -138, -753, +354, -559, 497, 346, 130, 620, -261, 40, +-210, -385, 71, -37, 142, 495, -178, 169, +-370, -652, 46, -930, 515, -21, 459, 1378, +70, 1381, -469, -411, -724, -1910, -276, -1305, +566, 768, 623, 1942, 197, 967, -142, -1008, +-337, -1650, -375, -273, -107, 1087, 122, 859, +226, -318, 268, -823, 73, -112, -120, 682, +-114, 429, -199, -550, -249, -734, 112, 246, +317, 865, 119, 288, -45, -809, -147, -883, +-139, 405, 175, 1323, 168, 498, -423, -1199, +-438, -1479, 335, 275, 652, 1661, 144, 976, +-250, -910, -417, -1456, -369, -114, -66, 1014, +336, 622, 447, -460, 277, -637, -171, 268, +-442, 695, -313, 24, -98, -908, 134, -683, +495, 588, 353, 1242, -217, 445, -425, -1058, +-204, -1301, 82, 43, 178, 1323, 140, 896, +-162, -591, -14, -1159, 307, -125, 86, 817, +-385, 477, -331, -503, 80, -490, 318, 243, +267, 522, 118, 137, -315, -501, -469, -651, +39, 9, 562, 951, 234, 913, -482, -484, +-401, -1449, 207, -734, 422, 1008, 272, 1569, +-155, 229, -423, -1242, -358, -1133, 140, 227, +416, 976, 242, 407, 135, -400, -136, -301, +-461, 281, -430, 288, 165, -520, 596, -684, +313, 137, -77, 963, -335, 752, -278, -417, +11, -1200, 155, -575, 0, 710, 72, 1049, +295, 34, 217, -691, -401, -392, -578, 117, +-3, 304, 630, 141, 470, -3, -291, -173, +-651, -192, -179, -10, 570, 177, 601, 371, +-340, 104, -811, -503, -71, -557, 807, 145, +394, 854, -550, 330, -603, -700, 232, -724, +791, 401, 248, 1145, -903, -45, -973, -1543, +460, -932, 1532, 1418, 608, 2291, -1240, 26, +-1479, -2761, 12, -2237, 1442, 1347, 967, 3367, +-447, 1125, -1180, -2340, -427, -2660, 768, 142, +771, 2301, -313, 1489, -926, -1005, 14, -1895, +883, -86, 403, 1622, -489, 816, -583, -1157, +-240, -1345, 160, 465, 568, 1430, 527, 349, +-153, -1054, -571, -711, -463, 660, -175, 634, +435, -525, 788, -1013, 327, 410, -557, 1799, +-942, 566, -360, -2006, 734, -2274, 1154, 924, +106, 3105, -1203, 1242, -978, -2229, 459, -2840, +1413, 127, 528, 2845, -989, 1695, -1341, -1567, +76, -2479, 1386, 251, 757, 2388, -750, 786, +-1024, -1999, -15, -1931, 852, 1256, 476, 2860, +-568, 570, -765, -2846, 272, -2682, 1029, 1019, +211, 3618, -1037, 1608, -912, -2378, 537, -3143, +1382, 62, 288, 2714, -1237, 1548, -1057, -1269, +538, -1880, 1347, 52, 395, 1747, -1012, 757, +-1153, -1416, 310, -1657, 1266, 392, 459, 2188, +-932, 1142, -739, -1299, 392, -2149, 773, -389, +-49, 1700, -721, 1350, -470, -547, 741, -1177, +995, -50, -244, 864, -1268, 93, -578, -897, +855, -486, 1070, 715, 41, 1059, -968, 0, +-643, -1065, 512, -651, 808, 578, -108, 890, +-819, -174, -390, -1022, 768, -380, 917, 1021, +-138, 1370, -1265, -201, -808, -1873, 772, -1330, +1371, 1018, 400, 2114, -1080, 573, -1299, -1427, +105, -1507, 1287, 230, 858, 1428, -601, 532, +-1077, -936, -235, -965, 597, 257, 677, 1127, +-18, 458, -446, -520, -232, -759, 82, -170, +171, 175, -210, -50, -104, 165, 418, 791, +571, 647, -137, -427, -1041, -1526, -617, -1026, +612, 718, 1181, 1794, 396, 959, -941, -823, +-827, -1410, 161, -493, 602, 584, 74, 678, +-336, -145, 146, -420, 502, 469, 68, 839, +-759, -76, -660, -1326, 434, -1109, 990, 390, +189, 1502, -753, 1081, -544, -284, 436, -1060, +640, -729, -148, -309, -1037, -14, -313, 571, +1129, 1289, 1350, 1038, -400, -666, -1877, -2296, +-1071, -1521, 999, 1074, 2061, 2668, 692, 1344, +-1487, -1353, -1844, -2321, -57, -795, 1726, 1334, +1138, 1509, -588, 88, -1372, -935, -378, -528, +816, 286, 841, 315, 3, -208, -764, -138, +-590, 385, 177, 245, 531, -570, 500, -633, +43, 482, -331, 1171, -654, 397, -528, -1321, +275, -1648, 1106, 174, 840, 2166, -536, 1606, +-1442, -910, -686, -2398, 658, -1133, 1328, 1207, +667, 2184, -733, 710, -1419, -1332, -358, -1636, +1098, -218, 1037, 1104, -192, 895, -1021, -103, +-644, -572, 453, -280, 969, 94, 296, 134, +-570, -13, -822, 7, -301, -66, 688, 59, +947, 206, 116, 208, -886, -109, -896, -642, +-68, -515, 1097, 413, 1154, 1218, -333, 627, +-1501, -953, -892, -1623, 626, -442, 1356, 1468, +875, 1864, -511, 81, -1381, -2012, -914, -1881, +341, 502, 1192, 2413, 1071, 1555, 70, -1124, +-1137, -2270, -1304, -939, -322, 1132, 1011, 1578, +1544, 601, 634, -433, -1097, -792, -1761, -698, +-580, -555, 1092, -34, 1752, 1110, 672, 1716, +-1111, 517, -1584, -1650, -535, -2506, 642, -661, +1099, 1893, 980, 2662, 171, 768, -992, -1719, +-1428, -2324, -937, -806, 687, 1135, 2231, 1600, +1609, 750, -934, -195, -2709, -719, -1528, -826, +1117, -703, 2660, 76, 1241, 954, -1601, 1129, +-2201, 152, -162, -997, 1741, -914, 1254, 54, +-691, 730, -1562, 308, -605, -332, 1197, -471, +1420, 206, 140, 775, -1159, 530, -1163, -649, +-112, -1301, 699, -643, 767, 851, 554, 1617, +54, 726, -746, -796, -1149, -1588, -224, -764, +933, 759, 1037, 1344, -28, 389, -951, -898, +-609, -852, 690, 459, 1048, 1126, -304, 196, +-1608, -1360, -889, -1463, 1292, 415, 2259, 2075, +507, 1548, -1987, -648, -2320, -2253, -43, -1604, +2180, 563, 1812, 2110, -575, 1453, -1945, -546, +-759, -1539, 1152, -918, 1331, 307, -298, 910, +-1620, 479, -894, -336, 1148, -558, 2106, 12, +646, 701, -1869, 376, -2406, -569, -272, -1106, +2212, -248, 2276, 1120, -194, 1265, -2363, -93, +-1722, -1462, 992, -1025, 2445, 809, 555, 1626, +-2161, 120, -2098, -1875, 1009, -1305, 3076, 1359, +1158, 2647, -2243, 636, -3058, -2630, -281, -3079, +2671, -33, 2437, 3427, -443, 3309, -2406, -440, +-1133, -3784, 930, -3142, 1113, 778, -114, 3634, +-687, 2550, 198, -859, 918, -2960, 215, -1976, +-1265, 730, -1228, 2278, 574, 1476, 1730, -575, +881, -1778, -997, -1100, -1598, 510, -465, 1523, +1078, 881, 1170, -716, 233, -1423, -564, -556, +-777, 939, -579, 1302, -184, 156, 741, -1010, +1332, -969, 847, 138, -930, 786, -2288, 499, +-1220, -81, 1551, -275, 2789, -241, 957, -325, +-1877, -183, -2634, 360, -598, 822, 2095, 353, +2105, -687, -245, -1123, -1942, -313, -1096, 945, +945, 1327, 1563, 208, 156, -1151, -1578, -1411, +-1186, -105, 908, 1235, 1813, 1391, 546, 156, +-1445, -1169, -1636, -1473, -106, -314, 1447, 1099, +1388, 1547, 13, 448, -1348, -918, -1181, -1441, +-7, -703, 1072, 444, 1058, 1351, 209, 1192, +-920, 69, -1184, -1344, -259, -1700, 916, -426, +1126, 1296, 310, 1956, -979, 685, -1179, -1062, +-87, -1912, 1136, -937, 922, 674, -342, 1743, +-1076, 1091, -554, -384, 727, -1354, 926, -904, +-56, 16, -851, 623, -524, 697, 364, 600, +714, 45, 243, -805, -496, -1020, -616, -341, +30, 868, 557, 1122, 401, 565, -114, -808, +-547, -1275, -429, -580, 22, 800, 671, 1156, +860, 530, -76, -361, -1223, -905, -1121, -974, +381, -352, 1590, 1060, 1198, 1816, -580, 844, +-1921, -1481, -1182, -2634, 1096, -1022, 1979, 1897, +562, 3058, -1285, 1093, -1557, -2121, -67, -3124, +1363, -955, 1113, 2075, -560, 2588, -1327, 571, +-170, -1397, 866, -1491, 673, -505, -338, 291, +-763, 416, -91, 721, 766, 834, 386, 369, +-717, -1030, -786, -1716, 475, -605, 1191, 1243, +353, 1879, -1264, 465, -1387, -966, 495, -1291, +1943, -479, 940, 205, -1355, 497, -2075, 631, +-418, 753, 1938, 366, 2180, -847, -170, -1797, +-2378, -1076, -1940, 1220, 485, 2547, 2398, 1322, +1801, -1342, -509, -2681, -2219, -1467, -1708, 1143, +384, 2454, 1897, 1440, 1551, -757, -259, -1841, +-1524, -1251, -1170, 182, 208, 1034, 1060, 1105, +610, 297, -340, -379, -545, -701, 109, -486, +507, -223, -80, 0, -770, 549, -543, 813, +614, 607, 1172, -351, 359, -1280, -886, -1113, +-1166, 122, -277, 1482, 784, 1361, 969, 4, +443, -1206, -311, -1254, -871, -205, -1127, 611, +-392, 807, 1405, 481, 2149, 179, 585, -310, +-2202, -749, -2926, -730, -568, -11, 2867, 598, +3463, 743, 239, 423, -3336, 74, -3177, -428, +306, -906, 2920, -1007, 2222, -129, -564, 1321, +-1905, 1910, -933, 773, 588, -1482, 520, -2513, +-240, -1293, -301, 1215, 333, 2492, 972, 1638, +596, -306, -674, -1865, -1538, -1990, -1096, -1061, +415, 764, 1769, 2463, 1989, 2453, 363, 280, +-2103, -2639, -3050, -3400, -970, -1166, 2446, 2137, +3873, 3864, 1244, 2082, -2820, -1509, -4118, -3757, +-1067, -2534, 2946, 838, 3740, 2986, 724, 2358, +-2657, 55, -3063, -1860, -447, -1986, 2150, -750, +2252, 759, 342, 1664, -1402, 1124, -1465, -227, +-567, -1458, 455, -1212, 1055, 403, 1240, 1630, +311, 964, -1104, -1060, -1958, -2194, -867, -807, +1370, 2002, 2742, 3156, 1280, 815, -1834, -2968, +-3456, -3929, -1467, -940, 2087, 3115, 3929, 4257, +1830, 1501, -2083, -2397, -4155, -4069, -2319, -2223, +1607, 1045, 4115, 3105, 3005, 2887, -776, 799, +-3807, -1703, -3603, -3350, -316, -2644, 3184, 289, +3978, 3580, 1418, 3962, -2356, 661, -3946, -3531, +-2272, -4361, 1348, -1015, 3493, 3171, 2685, 4080, +-330, 884, -2562, -2777, -2728, -3472, -841, -542, +1467, 2636, 2704, 2954, 1884, 138, -484, -2664, +-2683, -2556, -2770, -40, -275, 2372, 2713, 2492, +3408, 564, 806, -1682, -2757, -2588, -3756, -1554, +-1086, 646, 2480, 2447, 3688, 2447, 1500, 673, +-1931, -1634, -3396, -2852, -1679, -2026, 1087, 147, +2462, 2444, 1784, 3091, 195, 1558, -1322, -1229, +-1850, -3408, -1374, -3018, 90, -347, 1781, 2698, +2277, 3808, 780, 1897, -1533, -1391, -2567, -3629, +-1281, -2924, 1232, -107, 2379, 2695, 1159, 3287, +-884, 1190, -1647, -1648, -788, -2922, 387, -1556, +849, 908, 449, 2288, 164, 1224, 22, -803, +-590, -1731, -1109, -541, -339, 1083, 1248, 1622, +1954, 179, 393, -1632, -2091, -1832, -2687, -176, +-285, 1757, 2687, 1894, 2874, 609, 361, -903, +-2327, -1467, -2589, -1381, -955, -775, 1112, 400, +1965, 2055, 1709, 2811, 724, 1107, -904, -2243, +-2521, -4424, -2652, -2743, -251, 1790, 3044, 5141, +4116, 3983, 1137, -933, -3079, -4817, -4515, -4186, +-1690, -10, 2660, 3343, 3895, 3326, 1505, 1005, +-1690, -1310, -2334, -2051, -954, -1497, 304, -442, +524, 422, 366, 1345, 835, 1786, 1300, 1047, +210, -815, -1842, -2384, -2717, -2005, -571, -43, +2637, 2116, 3524, 2619, 545, 1167, -3044, -1516, +-3422, -3084, -390, -1963, 2687, 1002, 2754, 2970, +335, 2138, -1807, -425, -1522, -2188, -330, -1785, +222, -193, 141, 816, 572, 945, 1333, 922, +1097, 818, -587, 25, -2473, -1463, -2196, -2125, +498, -1028, 2833, 1411, 2588, 2930, -33, 1878, +-2233, -935, -2330, -2835, -747, -2277, 1112, 100, +1623, 1833, 1160, 1934, 229, 966, -613, -189, +-1125, -1082, -1141, -1827, -370, -1575, 648, 58, +1267, 2223, 874, 2670, 33, 710, -434, -1861, +-555, -2577, -826, -1132, -1016, 814, -342, 1512, +1268, 915, 2504, 449, 1731, 390, -1230, -239, +-3757, -1701, -2977, -2278, 928, -550, 4228, 2350, +3605, 3603, -437, 1234, -3889, -2437, -3406, -3888, +99, -1460, 2794, 1996, 2261, 3009, 229, 1217, +-1179, -1148, -902, -1585, -359, -375, -414, 368, +-355, -248, 404, -733, 1434, 283, 1233, 2029, +-246, 1662, -1804, -871, -1720, -3012, -19, -2061, +1630, 1053, 1738, 3047, 467, 2017, -1147, -858, +-1787, -2460, -687, -1473, 981, 505, 1465, 1440, +491, 733, -888, -295, -1173, -356, 45, 186, +1291, 94, 813, -553, -961, -694, -1872, 30, +-431, 754, 1784, 798, 2333, 202, 306, -635, +-2216, -744, -2468, -133, -366, 384, 1854, 272, +2199, -111, 725, -201, -1033, 146, -1509, 523, +-1030, 463, -60, -289, 683, -1140, 1171, -1015, +762, 209, -195, 1440, -720, 1520, -574, 181, +-143, -1118, -118, -1629, -300, -858, 168, 347, +1016, 1137, 1326, 1327, 67, 774, -1436, -183, +-1961, -1370, -590, -1608, 1296, -749, 1985, 607, +848, 1644, -587, 1531, -1203, 582, -864, -742, +-284, -1763, 113, -1854, 545, -782, 915, 1399, +776, 2814, -143, 2082, -993, -643, -1063, -2907, +-53, -2623, 671, -190, 518, 2042, -165, 2305, +-19, 841, 520, -800, 413, -1404, -373, -951, +-1190, -242, -869, 337, 369, 612, 1336, 613, +1019, 307, -122, 52, -844, -148, -563, -508, +-87, -762, -47, -496, -424, 310, -33, 1043, +933, 924, 1423, -13, 478, -835, -1192, -825, +-1949, -81, -1046, 437, 653, 211, 1613, -369, +1375, -99, 509, 844, -530, 1020, -1261, -77, +-1541, -1551, -942, -1600, 487, -173, 2057, 1615, +2285, 1959, 496, 608, -1888, -1172, -2735, -1726, +-1386, -922, 1042, 345, 2354, 982, 1729, 930, +-4, 551, -1320, -81, -1537, -639, -807, -1012, +271, -779, 1042, 84, 982, 1066, 357, 1452, +-492, 468, -820, -984, -298, -1734, 241, -809, +378, 929, -24, 1761, -320, 756, -251, -950, +349, -1518, 645, -488, 317, 842, -252, 1053, +-638, 356, -731, -331, -401, -582, 443, -739, +1111, -537, 1067, 426, 85, 1402, -1071, 1322, +-1502, -238, -596, -2090, 645, -2035, 1230, 256, +779, 2467, 166, 2141, -324, -316, -684, -2107, +-949, -1676, -668, 163, 281, 1311, 1280, 898, +1380, -41, 169, -269, -1198, 14, -1364, -202, +-300, -725, 687, -586, 688, 558, 160, 1346, +-135, 557, 166, -885, 265, -1374, -254, -221, +-791, 1111, -440, 1066, 294, -145, 570, -1128, +355, -703, 116, 303, 73, 874, 23, 524, +-420, -142, -850, -439, -677, -378, 446, -290, +1372, -165, 1200, 305, -136, 804, -1333, 653, +-1360, -112, -320, -1035, 653, -1091, 1145, -127, +837, 1042, 141, 1243, -765, 278, -966, -830, +-679, -1063, 195, -249, 915, 585, 800, 592, +37, -20, -557, -296, -444, -27, -108, 262, +21, 47, 69, -337, 200, -317, 297, 123, +68, 407, -290, 113, -365, -250, -84, -239, +429, 168, 569, 446, 18, 131, -881, -496, +-813, -697, 174, -187, 1082, 699, 1049, 916, +128, 338, -1182, -644, -1474, -875, -394, -458, +1021, 225, 1525, 566, 776, 521, -599, 215, +-1464, -138, -886, -289, 354, -386, 993, -407, +593, -239, -191, 332, -450, 855, -7, 694, +334, -193, -89, -858, -663, -744, -544, -106, +372, 412, 1182, 373, 711, 265, -557, 354, +-1204, 384, -574, -312, 317, -1198, 863, -1027, +511, 305, -104, 1572, -542, 1242, -272, -182, +72, -1379, 67, -927, 117, 171, 90, 679, +15, 171, -153, -314, -11, 149, 59, 791, +137, 548, 60, -750, -181, -1480, -323, -724, +6, 766, 331, 1535, 297, 887, -28, -262, +-251, -937, -272, -868, -38, -605, 111, -56, +233, 776, 271, 1368, 3, 883, -395, -536, +-456, -1548, 19, -1262, 458, 117, 706, 1066, +90, 1085, -685, 407, -827, -213, -54, -510, +629, -664, 672, -792, 167, -358, -235, 736, +-383, 1636, -289, 1068, -266, -630, -85, -1950, +241, -1518, 725, 350, 723, 1921, -75, 1583, +-1038, -208, -1034, -1557, -198, -1235, 732, 193, +1117, 1065, 621, 669, -403, -281, -908, -600, +-435, -83, 34, 431, 56, 220, 56, -420, +252, -536, 551, 140, 722, 709, 9, 537, +-1137, -359, -1494, -942, -304, -597, 1183, 610, +1647, 1314, 797, 527, -641, -985, -1407, -1573, +-876, -434, -20, 1234, 411, 1625, 524, 382, +768, -1201, 767, -1524, 98, -407, -1112, 917, +-1669, 1266, -827, 438, 1007, -521, 1945, -881, +1246, -443, -469, 294, -1543, 515, -1369, 167, +-153, -270, 891, -135, 1136, 233, 455, 295, +-373, -74, -592, -468, -303, -478, 71, 57, +31, 592, -74, 654, -5, 35, 256, -636, +348, -665, 80, 50, -209, 593, -319, 406, +-139, -272, -26, -557, 14, -65, -8, 573, +265, 631, 485, -160, 189, -855, -392, -734, +-725, 129, -336, 862, 312, 814, 665, 107, +237, -457, -215, -717, -155, -513, 41, -84, +-21, 396, -320, 669, -273, 521, 164, 207, +563, -388, 251, -781, -303, -758, -390, -251, +118, 600, 451, 1160, -28, 943, -646, -101, +-686, -1185, 208, -1365, 1156, -423, 1080, 844, +-33, 1275, -1322, 631, -1467, -319, -405, -602, +958, -396, 1480, -186, 1064, -370, -160, -194, +-1234, 520, -1430, 1164, -477, 719, 598, -472, +1046, -1315, 816, -1087, 295, 67, -247, 993, +-675, 1067, -764, 335, -739, -308, -78, -657, +877, -653, 1411, -378, 843, 176, -435, 710, +-1373, 733, -1335, 151, -332, -516, 758, -570, +1267, -221, 829, 58, 130, 162, -511, 238, +-905, 346, -923, 170, -359, -208, 427, -509, +997, -303, 993, 198, 533, 525, -361, 226, +-1217, -300, -1525, -459, -669, -3, 1013, 466, +2174, 283, 1476, -152, -608, -396, -2101, -204, +-1702, 81, 67, 221, 1513, 188, 1328, 44, +241, 70, -630, 14, -709, -179, -303, -389, +-36, -353, 45, 119, 192, 682, 449, 882, +255, 73, -287, -1005, -412, -1280, -37, -175, +450, 1175, 213, 1248, -462, 111, -767, -1006, +84, -835, 909, 46, 821, 632, -97, 288, +-918, -340, -758, -317, 54, 237, 451, 638, +271, 197, 251, -558, 369, -788, 149, -319, +-476, 461, -926, 817, -662, 612, 448, -105, +1280, -776, 970, -792, -340, -178, -1253, 550, +-965, 696, 193, 280, 916, -237, 716, -400, +-56, -111, -486, 103, -413, -27, -77, -333, +209, -157, 238, 407, 96, 769, -71, 377, +-149, -488, -195, -959, -52, -711, 280, 205, +383, 862, 50, 973, -362, 329, -467, -505, +-252, -1154, 298, -899, 627, 264, 468, 1220, +-98, 964, -612, -267, -677, -963, -193, -548, +429, 351, 761, 586, 563, -44, -213, -523, +-798, -236, -627, 473, 88, 620, 508, 44, +498, -526, 129, -498, -286, -63, -260, 183, +-73, 178, -16, 241, -107, 311, 122, 164, +307, -294, 122, -678, -223, -463, -274, 114, +44, 806, 358, 676, 188, 111, -489, -638, +-665, -769, 161, -202, 1086, 400, 709, 563, +-527, 114, -1267, -166, -678, -174, 558, 101, +1176, 75, 554, -247, -372, -410, -680, -10, +-327, 503, -71, 538, -38, 34, 183, -498, +572, -549, 622, -56, -90, 365, -876, 287, +-824, -1, 33, 15, 746, 164, 672, -50, +5, -494, -411, -508, -160, 168, 93, 886, +-183, 701, -386, -316, -123, -1138, 515, -703, +691, 496, 207, 1135, -446, 463, -626, -542, +-325, -723, -13, -213, 245, 269, 419, 176, +479, 118, 271, 188, -268, 307, -853, -85, +-708, -705, 61, -630, 718, 228, 855, 1005, +367, 671, -361, -351, -800, -984, -513, -561, +-29, 372, 337, 781, 432, 384, 307, -360, +88, -493, -81, -121, -214, 249, -414, 127, +-413, -23, -29, 46, 455, 154, 664, -88, +403, -423, -321, -311, -637, 353, -357, 790, +-30, 451, 178, -581, 167, -1163, 191, -691, +305, 662, 432, 1586, -83, 1015, -873, -686, +-951, -1846, -36, -1219, 896, 537, 1134, 1734, +462, 1323, -647, -218, -1008, -1415, -560, -1256, +120, -15, 434, 983, 505, 857, 371, 86, +188, -470, -212, -279, -537, -24, -602, 14, +-200, -189, 302, -111, 697, 232, 513, 382, +118, 154, -313, -169, -589, -247, -626, -133, +-237, -49, 512, -23, 890, -32, 597, 126, +-170, 350, -826, 336, -714, -80, -74, -560, +450, -550, 479, -42, 237, 439, -24, 490, +-108, 206, -90, 15, -275, -113, -363, -356, +-80, -602, 348, -441, 528, 360, 288, 1116, +-154, 965, -466, -252, -323, -1386, -85, -1170, +51, 177, 218, 1228, 400, 877, 267, -151, +-36, -583, -342, -206, -538, 8, -293, -307, +290, -418, 621, 182, 400, 992, -90, 845, +-535, -372, -431, -1397, 39, -884, 445, 586, +218, 1341, -107, 588, -312, -606, -119, -981, +261, -296, 397, 467, 49, 560, -380, 145, +-450, -194, -245, -233, 240, -243, 716, -160, +497, 127, -170, 455, -615, 373, -616, -68, +-256, -519, 352, -503, 718, -125, 498, 449, +5, 643, -451, 229, -604, -315, -382, -477, +37, -270, 436, -40, 611, 144, 348, 371, +-96, 331, -474, 72, -605, -248, -447, -338, +204, -328, 809, -170, 767, 205, 1, 689, +-812, 641, -891, -148, 26, -971, 890, -845, +639, 150, -456, 995, -950, 768, -84, -227, +1044, -750, 969, -350, -461, 267, -1564, 205, +-949, -205, 872, -114, 1730, 461, 734, 586, +-901, -154, -1362, -988, -426, -769, 527, 436, +671, 1255, 246, 697, -66, -638, -2, -1132, +-49, -410, -368, 535, -448, 677, 50, 191, +557, -161, 386, -184, -80, -62, -311, -172, +-113, -300, 0, -65, -63, 444, -127, 683, +64, 154, 455, -627, 348, -802, -309, -172, +-779, 599, -277, 708, 683, 137, 796, -448, +-6, -486, -795, 40, -704, 327, 186, 73, +795, -307, 529, -167, -208, 306, -515, 484, +-366, 140, -76, -502, 152, -640, 334, -177, +414, 520, 202, 639, -315, 171, -687, -349, +-410, -435, 360, -127, 671, 88, 294, 108, +-222, 66, -366, 155, -155, 170, 33, 7, +-8, -247, -32, -267, 210, -53, 317, 131, +5, 106, -424, 33, -244, 153, 260, 250, +370, 37, -136, -476, -603, -714, -169, -90, +714, 821, 822, 966, -128, 23, -1111, -967, +-928, -894, 355, 118, 1224, 956, 756, 597, +-418, -434, -939, -815, -491, -107, 267, 760, +521, 646, 215, -361, -131, -1026, -93, -479, +55, 676, -24, 1059, -168, 271, -125, -716, +30, -797, 117, -68, 159, 536, 119, 383, +26, -203, -201, -326, -304, 97, -79, 493, +288, 212, 359, -467, -30, -690, -393, -228, +-253, 512, 227, 756, 424, 361, 128, -316, +-294, -587, -424, -414, -215, -74, 173, 160, +500, 418, 426, 466, 64, 263, -431, -244, +-768, -625, -443, -621, 450, -34, 974, 607, +583, 703, -336, 179, -851, -315, -534, -404, +236, -194, 440, -124, 57, -154, -59, 80, +303, 564, 488, 717, -151, 90, -916, -835, +-906, -1100, 232, -228, 1286, 914, 1021, 1148, +-338, 279, -1145, -768, -673, -971, 294, -201, +589, 553, 147, 606, -206, 37, 49, -249, +444, -138, 116, -45, -591, -130, -821, -106, +-6, 175, 878, 471, 833, 250, -134, -393, +-880, -837, -537, -397, 335, 708, 711, 1241, +90, 453, -590, -984, -421, -1447, 294, -425, +627, 966, 249, 1362, -369, 452, -587, -698, +-171, -1029, 321, -408, 281, 297, 43, 466, +0, 268, 35, 85, 70, 119, -127, 60, +-346, -340, -295, -680, 106, -388, 513, 423, +454, 964, 134, 602, -332, -333, -634, -949, +-525, -625, 69, 201, 694, 607, 805, 385, +204, -5, -584, -135, -800, -61, -335, -118, +137, -307, 590, -352, 566, 177, 179, 721, +-289, 686, -538, -243, -533, -1091, -137, -853, +588, 403, 867, 1379, 276, 848, -627, -661, +-961, -1495, -365, -697, 662, 824, 947, 1400, +269, 525, -563, -717, -655, -1151, -279, -480, +169, 444, 388, 764, 396, 418, 298, 4, +-78, -220, -559, -417, -743, -506, -168, -211, +648, 369, 970, 719, 378, 475, -558, -135, +-950, -647, -385, -582, 274, -137, 525, 358, +398, 409, 155, 286, -43, 156, -291, -48, +-487, -391, -402, -610, 112, -295, 647, 316, +695, 747, 38, 670, -676, -16, -681, -793, +-40, -943, 488, -211, 429, 773, 59, 987, +-233, 194, -187, -738, -52, -738, 95, 63, +45, 649, 51, 297, 3, -395, -124, -504, +-139, 101, 59, 612, 289, 368, 309, -288, +-118, -591, -596, -271, -428, 222, 219, 437, +762, 196, 368, -58, -279, -158, -631, -104, +-167, -93, 272, -61, 217, 21, -99, 74, +-164, 18, 217, 100, 423, 293, 89, 180, +-623, -374, -712, -776, 26, -342, 893, 624, +763, 1099, -142, 460, -912, -740, -588, -1190, +264, -392, 697, 711, 221, 881, -370, 150, +-327, -450, 224, -314, 465, 133, -62, 39, +-709, -318, -498, -235, 415, 370, 1022, 635, +527, 161, -656, -416, -1254, -555, -476, -261, +804, 175, 1208, 502, 372, 516, -819, 29, +-956, -683, -147, -693, 578, 175, 481, 866, +33, 444, -144, -500, -68, -688, -8, -53, +-195, 484, -289, 307, -6, -110, 418, -175, +443, 21, 109, 54, -356, -176, -615, -274, +-396, -20, 385, 422, 816, 602, 410, 178, +-373, -614, -805, -1051, -418, -465, 386, 848, +729, 1470, 293, 593, -347, -969, -546, -1531, +-294, -607, 229, 776, 617, 1268, 358, 625, +-287, -353, -711, -813, -385, -765, 312, -186, +791, 551, 447, 1021, -315, 472, -763, -674, +-474, -1120, 144, -264, 665, 855, 587, 849, +24, -121, -574, -681, -701, -416, -80, 95, +639, 366, 507, 347, -139, 77, -380, -289, +-99, -310, 120, -3, 29, 228, -78, -67, +-111, -219, 124, 215, 316, 699, 69, 152, +-336, -979, -347, -966, 89, 396, 274, 1339, +218, 557, 50, -770, -223, -961, -234, -55, +-52, 615, 246, 461, 79, -85, -141, -502, +64, -311, 263, 377, -47, 647, -465, 36, +-294, -767, 280, -588, 535, 316, 408, 875, +-258, 400, -821, -584, -517, -836, 477, -41, +882, 843, 284, 558, -312, -426, -578, -783, +-483, -168, 4, 407, 611, 436, 583, 349, +33, 91, -383, -536, -426, -839, -440, -271, +-43, 630, 629, 921, 900, 548, 148, -240, +-901, -1002, -968, -1025, -223, -41, 760, 1066, +1144, 1139, 404, 186, -893, -795, -1066, -914, +-158, -295, 575, 295, 547, 534, 376, 403, +-3, 146, -524, -168, -576, -416, -80, -360, +338, -86, 420, 250, 410, 386, -99, 281, +-583, -62, -479, -411, 74, -337, 535, 86, +459, 348, -69, 256, -501, -56, -362, -361, +186, -355, 399, 204, 71, 673, -208, 260, +-85, -582, 22, -754, 101, 3, 65, 770, +-92, 582, -265, -250, -40, -743, 363, -246, +337, 488, -57, 499, -473, -155, -470, -553, +118, -172, 648, 321, 412, 441, -322, 98, +-428, -289, -111, -322, 65, -135, 78, 108, +83, 116, 130, 197, 207, 335, -18, 19, +-416, -462, -317, -502, 226, 19, 391, 381, +100, 399, -173, 141, -268, -154, 27, -355, +324, -171, 132, 83, -396, 25, -339, -49, +157, 220, 454, 495, 280, 50, -101, -731, +-404, -657, -419, 334, 111, 888, 449, 228, +322, -547, -172, -487, -350, 123, -38, 379, +262, 151, 153, -197, -299, -300, -357, -4, +185, 357, 601, 196, 178, -268, -474, -403, +-444, 106, 74, 496, 297, 199, 184, -361, +-45, -532, -150, -94, -53, 457, 79, 617, +57, 124, -82, -575, -98, -624, -31, -9, +60, 480, 125, 338, 59, -5, -111, -70, +-114, -71, 106, -48, 139, -193, -311, -241, +-346, -98, 332, 403, 684, 683, -41, 208, +-600, -657, -296, -825, 90, -56, 194, 598, +340, 448, 110, -49, -242, -116, -176, 16, +53, -61, -1, -300, -55, -339, 0, 92, +86, 547, 288, 500, 136, -92, -429, -556, +-479, -439, 249, 50, 566, 468, 126, 257, +-250, -228, -389, -324, -193, 274, 281, 497, +548, -202, 60, -814, -505, -267, -355, 748, +187, 699, 400, -241, 0, -616, -282, -225, +-3, 248, 203, 270, 111, 173, -141, -190, +-220, -396, -245, -17, -48, 369, 429, 270, +577, -42, 175, -120, -721, -264, -967, -430, +-151, -3, 860, 621, 966, 625, 185, -31, +-655, -538, -984, -586, -359, -389, 621, 271, +821, 894, 160, 684, -446, -390, -410, -911, +148, -303, 225, 196, -174, 236, -438, 228, +215, 323, 689, 175, 304, -310, -407, -564, +-780, -490, -211, 247, 738, 912, 663, 622, +-358, -534, -651, -1049, 72, -226, 488, 710, +175, 654, -149, -94, -370, -484, -220, -317, +266, 42, 496, 325, 83, 219, -355, -210, +-255, -141, 71, 335, 179, 135, -137, -692, +-131, -586, 348, 684, 271, 1265, -261, -4, +-404, -1292, -142, -897, 203, 579, 370, 1050, +61, 230, -386, -491, -111, -452, 350, -7, +18, 250, -510, 134, -204, -209, 433, -227, +621, 305, 17, 514, -753, -93, -659, -764, +266, -422, 764, 621, 431, 813, -186, -161, +-648, -883, -417, -328, 264, 690, 349, 684, +93, -189, 210, -871, 101, -450, -505, 619, +-325, 883, 295, 15, 247, -848, -5, -504, +104, 458, -63, 583, -190, -132, 124, -535, +246, 81, -85, 600, -382, 63, -148, -687, +343, -450, 575, 430, 104, 734, -482, 172, +-433, -571, -83, -681, 239, 56, 329, 852, +113, 425, -66, -686, 125, -841, -92, 426, +-680, 1167, -316, 42, 473, -1276, 687, -760, +333, 992, -354, 1376, -867, -226, -452, -1512, +504, -691, 600, 1084, 112, 1237, -168, -238, +-348, -1273, -132, -550, 154, 830, -210, 1003, +-278, -183, 449, -1133, 812, -435, -137, 1007, +-959, 1071, -659, -547, 273, -1613, 1012, -438, +644, 1605, -511, 1611, -953, -619, -167, -2151, +639, -878, 464, 1542, -256, 1858, -498, -251, +214, -1812, 715, -868, 58, 1183, -771, 1446, +-583, -338, 362, -1680, 999, -694, 514, 1426, +-720, 1735, -1059, -386, 86, -2086, 979, -1002, +517, 1413, -340, 1797, -716, -178, -358, -1716, +533, -834, 791, 1160, -84, 1341, -740, -346, +-201, -1526, 295, -567, 159, 1196, -108, 1279, +-7, -386, 157, -1421, 73, -360, -174, 1095, +-392, 731, -211, -755, 334, -1019, 527, 379, +-78, 1349, -603, 499, -201, -1254, 381, -1438, +217, 261, -303, 1632, -333, 917, 63, -839, +409, -1336, 375, -187, -211, 1104, -694, 712, +-498, -774, 485, -1041, 1075, 417, 256, 1485, +-966, 291, -901, -1536, 384, -1294, 947, 825, +316, 1788, -437, 331, -588, -1464, 11, -1121, +631, 542, 304, 1378, -499, 406, -464, -1115, +420, -1152, 654, 371, 139, 1519, -638, 524, +-655, -1250, 234, -1183, 951, 516, 398, 1543, +-698, 116, -696, -1495, 319, -925, 750, 1213, +-92, 1796, -842, -353, -97, -2016, 809, -1127, +457, 1295, -430, 1953, -766, 121, -233, -1533, +446, -1184, 632, 615, -118, 1308, -724, 85, +-8, -1145, 698, -588, 97, 1088, -935, 1206, +-781, -632, 671, -1756, 1366, -391, 294, 1661, +-1329, 1297, -1343, -925, 431, -1633, 1530, 172, +542, 1587, -1178, 422, -1050, -1400, 607, -1094, +1187, 804, 37, 1620, -1021, 211, -583, -1367, +510, -1113, 882, 658, 103, 1245, -811, -123, +-204, -1215, 889, -89, 378, 1532, -928, 766, +-900, -1634, 558, -2029, 1414, 620, 708, 2702, +-941, 1274, -1689, -1892, -26, -2649, 1645, 142, +1013, 2673, -967, 1466, -1339, -1853, 216, -2453, +1487, 616, 785, 2837, -1214, 1073, -1731, -2271, +37, -2667, 1802, 360, 1291, 2970, -587, 1896, +-1677, -1525, -751, -2801, 645, -442, 1003, 1983, +227, 1356, -414, -800, -410, -1024, -219, 389, +135, 632, 142, -578, -101, -927, 47, 463, +104, 1464, -294, 497, -478, -1409, 292, -1845, +932, 321, 127, 2432, -1030, 1551, -1049, -1638, +299, -2719, 1303, -275, 764, 2246, -437, 1743, +-1141, -705, -541, -1747, 607, -437, 896, 1183, +-62, 612, -596, -1075, 75, -1058, 516, 1090, +118, 2166, -386, 128, -601, -2638, -22, -2137, +1020, 1165, 821, 3139, -659, 1158, -1204, -2040, +90, -2558, 1124, 73, 771, 2400, -675, 1410, +-1421, -1489, -117, -2148, 1527, 318, 1091, 2219, +-576, 1129, -1296, -1459, -670, -2080, 409, -267, +1029, 1934, 346, 1753, -547, -711, -194, -2219, +218, -627, -130, 1745, -691, 1570, -337, -805, +408, -1948, 915, -489, 547, 1458, -622, 1544, +-1066, -46, -469, -1435, 391, -1199, 606, 248, +116, 1129, -171, 598, 126, -281, 383, -240, +-413, 145, -1133, -212, -449, -891, 826, -500, +1481, 962, 626, 1767, -1056, 349, -1779, -1802, +-305, -1882, 1500, 398, 1322, 2149, -304, 1038, +-1257, -1124, -666, -1680, 778, 5, 1311, 1456, +85, 912, -1210, -895, -864, -1388, 583, -51, +1083, 1256, 356, 866, -405, -483, -534, -916, +-58, -198, 289, 479, 38, 130, -325, -385, +-7, -15, 722, 796, 586, 632, -525, -700, +-1017, -1387, -359, -439, 592, 1153, 717, 1423, +163, 78, -317, -1087, -313, -937, -191, 146, +-298, 545, 36, 155, 430, -74, 298, 365, +-201, 572, -481, -454, -123, -1273, 252, -615, +253, 1018, -217, 1453, -594, 319, 44, -1035, +595, -1267, 415, -97, -185, 927, -759, 790, +-565, -179, 333, -602, 1034, -151, 330, 194, +-784, 166, -603, -61, 137, -28, 515, 65, +330, -194, -121, -266, -428, 233, -163, 747, +438, 377, 377, -821, -68, -1259, -211, -324, +-139, 1388, -71, 1652, 31, -1, 419, -1787, +412, -1536, -153, 340, -383, 1715, -258, 1218, +28, -480, 266, -1614, 320, -868, 154, 701, +-146, 1514, -178, 554, -230, -992, -188, -1416, +43, -395, 300, 1146, 429, 1598, 108, 460, +-416, -1494, -755, -2044, -204, -214, 505, 2079, +654, 2027, 88, -295, -539, -2341, -515, -1775, +-12, 825, 240, 2611, 159, 1326, -38, -1596, +20, -2689, 17, -593, -224, 2248, -424, 2435, +67, -122, 701, -2505, 486, -1907, -625, 528, +-1160, 2267, -209, 1458, 1181, -712, 1486, -1888, +28, -859, -1777, 914, -1742, 1202, 334, -11, +2256, -886, 1873, -253, -439, 845, -2254, 612, +-2042, -835, 364, -1342, 2588, 18, 2101, 1730, +-369, 1305, -2404, -765, -1923, -2173, 319, -956, +2250, 1399, 1988, 2195, -452, 614, -2218, -1701, +-1456, -2217, 829, -344, 1892, 1941, 588, 1999, +-1028, -112, -1138, -1644, 293, -1191, 1024, 103, +119, 686, -1271, 444, -879, 155, 1199, 348, +2083, 381, 9, -311, -2512, -1405, -2228, -1278, +787, 529, 2952, 2232, 1875, 1804, -1305, -758, +-2937, -2466, -1230, -1629, 1305, 721, 2048, 2000, +518, 1031, -1019, -638, -951, -1137, 223, -75, +458, 636, -383, -67, -592, -843, 169, -356, +1002, 829, 909, 1067, -366, 219, -1397, -625, +-848, -858, 626, -541, 1110, -45, 583, 464, +-283, 999, -747, 780, -277, -258, 422, -1287, +368, -1047, -87, 397, -302, 1236, -297, 545, +203, -826, 941, -851, 561, 688, -723, 1433, +-1215, -5, -461, -2077, 733, -1659, 1290, 955, +661, 2723, -818, 1605, -1265, -1389, -231, -2731, +731, -1242, 636, 1374, -120, 2162, -612, 687, +-217, -1014, 506, -1319, 520, -234, -172, 709, +-675, 524, -630, -82, -152, -337, 630, -266, +971, -70, 570, 381, -517, 815, -1546, 238, +-1303, -1062, 591, -1453, 2054, -175, 1437, 1699, +-823, 1957, -2165, 94, -1206, -2115, 991, -2344, +1866, -93, 525, 2423, -1017, 2489, -947, 52, +154, -2352, 608, -2415, -80, -360, -480, 1935, +322, 2601, 919, 919, 308, -1642, -988, -2771, +-1240, -1548, -105, 1083, 1540, 3022, 1623, 2495, +-194, -677, -1744, -3618, -1359, -3088, 219, 807, +1304, 3936, 1337, 2853, 322, -1024, -797, -3483, +-1295, -2216, -948, 990, 186, 2551, 1594, 1515, +1547, -648, -137, -1574, -1833, -938, -1713, 125, +330, 698, 2025, 797, 1407, 470, -997, -134, +-2203, -975, -601, -1104, 1694, -96, 1928, 1422, +-330, 1636, -2444, 21, -1485, -1832, 1233, -1735, +2541, 36, 679, 1724, -1663, 1582, -2106, 218, +-221, -1002, 1684, -1333, 1395, -824, -362, -104, +-1356, 997, -383, 1679, 769, 1297, 512, -742, +-401, -2605, -669, -2106, 125, 726, 793, 3035, +445, 2350, -331, -657, -724, -2920, -207, -2268, +366, 487, 372, 2628, 147, 1788, 26, -386, +100, -1922, -217, -1315, -384, -51, -175, 1009, +333, 1305, 630, 896, 273, -415, -354, -1818, +-765, -1874, -253, 164, 574, 2604, 781, 2690, +165, -117, -644, -3295, -871, -3251, -251, 147, +776, 3634, 1254, 3229, 254, -277, -1199, -3156, +-1530, -2501, -280, 140, 1366, 1890, 1785, 1465, +308, 362, -1778, -336, -2068, -469, 133, -911, +1989, -1021, 1511, -190, -675, 1204, -1888, 1817, +-844, 653, 1046, -1207, 1724, -1903, 37, -774, +-1512, 843, -1283, 1374, 338, 706, 1571, 24, +1254, -555, -214, -831, -1592, -976, -1654, -242, +-79, 1108, 1759, 1797, 2155, 837, 353, -1352, +-1883, -2556, -2127, -1126, -471, 1735, 1641, 2974, +2013, 939, 572, -1965, -1205, -2636, -1597, -732, +-364, 1618, 847, 2024, 823, 544, 144, -1229, +-77, -1109, 126, 48, -215, 548, -842, -300, +-534, -677, 485, 314, 1428, 1613, 909, 1323, +-838, -869, -2020, -2761, -930, -2111, 1275, 1084, +1970, 3497, 662, 2626, -1080, -837, -1710, -3540, +-648, -2884, 720, 195, 855, 3048, 259, 2956, +310, 296, 439, -2231, -535, -2328, -1634, -439, +-1465, 1004, 546, 1172, 2756, 562, 2323, 116, +-864, 46, -3525, -279, -2421, -723, 983, -1106, +3321, -476, 2182, 1015, -973, 1989, -2612, 1313, +-1363, -901, 644, -2411, 1474, -1870, 825, 228, +-333, 2292, -641, 2423, -34, 554, 334, -1783, +-55, -2464, -363, -1271, -377, 518, -91, 2107, +946, 2394, 1393, 835, 244, -1814, -1712, -3131, +-2343, -1940, -402, 893, 2685, 3312, 3467, 3081, +165, 149, -3671, -3148, -3656, -3784, 251, -1045, +3851, 2264, 3478, 3610, -370, 2011, -3594, -842, +-2932, -3039, 397, -2959, 2666, -577, 2056, 2274, +-194, 3270, -1420, 1542, -994, -1378, -625, -3029, +-259, -1949, 714, 779, 1666, 2379, 888, 1593, +-1064, -525, -2177, -1578, -995, -813, 1392, 709, +2414, 1081, 549, -59, -2059, -1117, -2300, -1002, +-51, 406, 2451, 1614, 2324, 1712, -294, 18, +-2736, -2048, -2531, -2706, 179, -887, 2827, 2033, +3017, 3659, 359, 2065, -2589, -1449, -3380, -4044, +-1280, -3248, 2099, 431, 3853, 3933, 2200, 4057, +-1548, 548, -3550, -3258, -2481, -3984, 551, -1320, +2704, 2099, 2684, 3433, 572, 1792, -1411, -1213, +-2264, -2745, -1712, -1768, -9, 671, 1810, 2126, +2578, 1416, 1342, -580, -1140, -1781, -3144, -1124, +-2481, 563, 520, 1632, 3450, 1178, 3238, -342, +52, -1646, -3533, -1731, -3994, -322, -477, 1541, +3503, 2317, 4185, 1091, 805, -1008, -3321, -2400, +-4117, -1950, -1124, -34, 2640, 1826, 3562, 2412, +1322, 1321, -1738, -472, -2720, -2210, -1449, -2684, +493, -1090, 1515, 1622, 1451, 3324, 609, 2258, +-410, -584, -1124, -2827, -1440, -2733, -795, -557, +774, 1781, 1999, 2584, 1551, 1413, -448, -537, +-2112, -1790, -1813, -1637, 258, -629, 2036, 980, +1800, 1840, -1, 1165, -1786, -726, -1801, -2006, +-65, -932, 1870, 1333, 1928, 2311, 167, 114, +-1788, -2469, -2090, -2275, -452, 799, 1839, 2903, +2311, 1897, 681, -831, -1357, -2373, -1991, -1658, +-1071, 80, 303, 1029, 1336, 1111, 1358, 1015, +1065, 841, 64, -261, -1625, -2163, -2695, -2794, +-1573, -753, 1560, 2724, 3821, 4142, 2818, 1521, +-1066, -2739, -4415, -4451, -3761, -1997, 397, 1969, +4026, 3615, 3910, 2244, 293, -559, -3080, -2427, +-3401, -2368, -1025, -742, 1461, 1262, 2426, 2201, +1767, 1572, 71, -230, -1664, -1815, -2262, -1815, +-1210, -376, 962, 1139, 2404, 1556, 1874, 770, +-416, -62, -2263, -611, -1834, -1154, 3, -1202, +1632, -250, 1393, 1446, 552, 2170, -392, 1097, +-872, -1136, -966, -2650, -679, -1884, 214, 624, +1112, 2570, 1727, 2260, 821, 157, -1132, -1664, +-2160, -2016, -1337, -943, 580, 237, 1880, 1078, +1853, 1594, 432, 1299, -1277, -163, -1852, -1886, +-1207, -2131, 336, -542, 1492, 1379, 1583, 1856, +441, 1035, -936, -310, -1430, -1064, -807, -1354, +400, -678, 857, 247, 407, 888, -260, 851, +-175, 457, 320, -60, 556, -522, -347, -759, +-1529, -741, -1218, -450, 629, 371, 2323, 1479, +1709, 1788, -559, 182, -2485, -2182, -2181, -2760, +-12, -618, 2053, 2311, 2461, 3278, 805, 1033, +-1440, -2151, -2484, -3347, -1569, -1033, 671, 2045, +2371, 2643, 2182, 749, 65, -1366, -2078, -1323, +-2254, -224, -656, 385, 1445, -218, 1944, -332, +1069, 722, -179, 1862, -1013, 1004, -1354, -1484, +-1247, -3060, -141, -1593, 1564, 1751, 2436, 3620, +1379, 2058, -1225, -1391, -3053, -3434, -2046, -2001, +660, 987, 2711, 2187, 2164, 1058, -133, -434, +-1769, -482, -1218, 170, 36, 148, 347, -827, +-196, -1441, -352, -488, 378, 1283, 1483, 2110, +1311, 1046, -390, -940, -2306, -2063, -2301, -1468, +-366, 133, 1921, 1130, 2699, 1016, 1403, 516, +-905, 204, -2297, 15, -2052, -677, -460, -1215, +1000, -1070, 1771, 89, 1514, 1196, 297, 1501, +-974, 965, -1532, -228, -935, -1181, -137, -1578, +350, -1160, 777, 45, 1110, 1456, 908, 2238, +145, 1435, -1084, -446, -1733, -2226, -1279, -2416, +455, -747, 1717, 1279, 1694, 2225, 635, 1639, +-473, 384, -1309, -875, -1521, -1663, -867, -1657, +552, -865, 1592, 640, 1588, 2104, 509, 2528, +-786, 1032, -1365, -1610, -903, -3292, -140, -2389, +42, 399, 408, 2822, 1175, 3071, 1574, 946, +313, -1783, -1464, -2918, -2401, -1608, -1214, 691, +1130, 1873, 2318, 1411, 1130, 104, -612, -776, +-1013, -834, -337, -263, 4, 101, -545, -76, +-793, -353, -158, -20, 1280, 872, 1838, 1003, +805, 22, -1071, -1082, -2180, -1274, -1652, -386, +-117, 820, 1500, 1267, 2084, 421, 1505, -592, +-227, -767, -1887, -32, -2244, 261, -1025, 17, +901, -348, 1961, -130, 1734, 560, 356, 762, +-855, 140, -1364, -690, -1301, -682, -609, -131, +457, 160, 1654, 288, 1636, 588, 550, 667, +-1062, 93, -1756, -933, -1246, -1263, 182, -442, +1306, 1190, 1356, 1921, 477, 716, -428, -1402, +-868, -2197, -735, -750, -186, 1433, 473, 2211, +592, 880, 170, -1349, -314, -2098, -299, -877, +130, 938, 657, 1643, 443, 959, -679, -156, +-1390, -973, -752, -1247, 835, -841, 1751, 318, +1178, 1368, -442, 1457, -1674, 281, -1551, -1222, +-171, -1820, 997, -826, 1164, 896, 628, 1567, +65, 726, -295, -330, -770, -667, -1135, -553, +-723, -459, 419, -250, 1605, 407, 1546, 943, +107, 722, -1621, -387, -1791, -1236, -297, -750, +1130, 812, 1313, 1476, 399, 142, -622, -1571, +-784, -1358, -12, 780, 492, 2125, 212, 1063, +-342, -1125, -357, -2067, -33, -842, 273, 985, +447, 1387, 451, 578, 73, -207, -503, -249, +-766, -179, -452, -510, 390, -702, 833, -259, +594, 724, 2, 1274, -438, 775, -489, -337, +-246, -1255, -46, -1074, 108, -247, 214, 594, +365, 905, 277, 849, 48, 286, -226, -565, +-512, -1126, -412, -789, -53, 200, 218, 921, +389, 700, 420, -295, 244, -665, -73, 12, +-505, 763, -658, 280, -451, -950, 143, -1298, +523, -207, 678, 1292, 624, 1582, 51, 505, +-723, -956, -1078, -1646, -775, -938, 73, 341, +969, 1140, 1403, 919, 811, 352, -388, -267, +-1529, -654, -1495, -725, -238, -337, 1120, 218, +1436, 604, 635, 478, -310, 44, -743, -29, +-528, 202, -135, -39, -145, -823, -264, -968, +158, 26, 940, 1250, 1232, 1325, 328, 287, +-1133, -938, -1830, -1124, -886, -483, 920, 315, +1668, 434, 965, 351, -336, 519, -766, 622, +-366, -81, -198, -1131, -500, -1321, -458, -238, +326, 1074, 1210, 1547, 1339, 690, 117, -704, +-1499, -1302, -1881, -857, -355, 51, 1219, 618, +1345, 825, 348, 553, -420, -15, -515, -629, +-212, -939, -46, -595, -224, 325, -307, 1062, +-28, 889, 525, -144, 814, -903, 328, -884, +-377, -143, -829, 406, -598, 706, -192, 544, +396, 13, 677, -671, 548, -777, 127, -91, +-264, 490, -457, 498, -438, 57, -318, -89, +-45, 21, 376, 113, 792, -202, 576, -591, +-80, -360, -677, 398, -656, 944, -244, 581, +152, -301, 261, -800, 343, -588, 419, -34, +380, 333, 78, 418, -558, 433, -928, 442, +-738, 68, 277, -753, 1047, -1153, 920, -384, +415, 913, -269, 1254, -763, 418, -1051, -498, +-772, -796, 87, -517, 1145, -40, 1569, 299, +835, 443, -692, 414, -1811, 97, -1504, -399, +31, -698, 1366, -85, 1410, 668, 398, 504, +-441, -510, -820, -930, -411, -66, -108, 972, +-250, 928, -235, -110, 440, -929, 1066, -950, +618, -225, -148, 537, -885, 898, -997, 608, +-491, -43, 367, -675, 728, -899, 865, -439, +665, 505, -210, 951, -1006, 375, -1134, -481, +-367, -604, 691, 184, 1239, 696, 593, 152, +-518, -1016, -722, -1118, -101, 314, 365, 1790, +89, 1362, -447, -565, -516, -1867, 188, -1273, +813, 434, 811, 1369, 168, 1012, -674, -60, +-1109, -637, -730, -514, 174, -175, 887, -23, +1135, 82, 647, 256, -405, 303, -1136, 81, +-1070, -162, -267, -124, 641, 50, 950, 73, +601, -225, -14, -394, -223, -96, -476, 485, +-598, 615, -479, 240, 12, -444, 601, -604, +708, -332, 422, 52, -24, 154, -343, 213, +-558, 516, -670, 525, -428, 22, 51, -913, +830, -1229, 1412, -380, 958, 1066, -609, 1532, +-1801, 461, -1772, -893, -348, -1137, 1517, -395, +2241, 240, 1132, 369, -618, 359, -1628, 448, +-1524, 284, -630, -311, 602, -857, 1278, -587, +1340, 285, 664, 902, -483, 523, -1366, -336, +-1296, -587, -435, -103, 620, 295, 1240, 87, +990, -253, 213, -104, -375, 446, -630, 477, +-1026, -192, -906, -880, 70, -460, 1229, 608, +1574, 1094, 728, 342, -738, -832, -1598, -1093, +-1224, -267, -105, 696, 902, 888, 1276, 481, +847, -115, -107, -655, -883, -982, -1172, -505, +-525, 558, 543, 1287, 1043, 803, 444, -453, +-418, -1229, -557, -802, 64, 366, 573, 886, +130, 319, -795, -497, -808, -290, 272, 563, +1094, 583, 736, -469, -347, -1317, -879, -555, +-330, 979, 342, 1583, 301, 400, -293, -1179, +-393, -1319, 227, -61, 889, 1002, 669, 688, +-514, -310, -1192, -679, -725, -48, 305, 596, +904, 475, 838, -258, 117, -743, -447, -519, +-571, 179, -410, 694, -130, 690, 165, 296, +551, -317, 421, -928, -67, -1028, -319, -47, +-186, 1326, 105, 1538, -87, 133, -326, -1457, +-157, -1566, 363, 12, 520, 1424, 218, 1168, +-318, -454, -474, -1286, -43, -297, 319, 1080, +-77, 922, -644, -645, -277, -1467, 824, -487, +1366, 1159, 461, 1597, -1296, 274, -2064, -1310, +-671, -1485, 1287, -172, 2026, 1067, 986, 1101, +-660, 214, -1487, -562, -1155, -722, -170, -427, +626, 135, 1006, 574, 877, 553, 202, -96, +-616, -596, -1107, -499, -772, 232, 322, 692, +985, 366, 680, -498, -75, -880, -439, -153, +-385, 758, -46, 742, 115, -11, -71, -592, +25, -447, 311, -43, 161, 165, -253, 47, +-258, 63, 126, 484, 366, 571, 155, -278, +-475, -1212, -692, -914, 44, 606, 915, 1569, +774, 869, -308, -661, -1006, -1378, -698, -667, +421, 427, 975, 926, 421, 480, -600, -21, +-747, -396, -129, -417, 550, -376, 619, 58, +53, 556, -540, 612, -497, -17, -105, -709, +142, -631, 441, 181, 528, 828, 182, 460, +-491, -432, -790, -807, -433, -197, 418, 623, +942, 688, 448, -90, -450, -764, -711, -498, +-165, 337, 401, 647, 422, 387, -160, -230, +-577, -637, -64, -590, 589, 56, 475, 728, +-223, 723, -369, 84, -143, -543, -31, -730, +-206, -415, -260, 180, 410, 625, 1054, 701, +639, 289, -827, -341, -1648, -839, -770, -729, +919, 26, 1609, 784, 673, 782, -669, 153, +-932, -311, -285, -321, 122, -370, -147, -485, +-168, -144, 413, 609, 1050, 1042, 545, 478, +-760, -661, -1431, -1251, -524, -516, 737, 783, +848, 1086, 176, 87, -155, -981, 192, -510, +150, 698, -570, 1030, -1089, -155, -400, -1238, +989, -820, 1474, 494, 446, 1108, -992, 556, +-1220, -321, -246, -396, 587, -101, 448, -254, +-49, -723, -43, -404, 335, 1020, 308, 1763, +-260, 655, -786, -1466, -502, -2280, 353, -709, +740, 1495, 284, 2043, -130, 444, 21, -1169, +-8, -1089, -424, 53, -737, 457, -177, -169, +736, -436, 1102, 279, 365, 1030, -655, 567, +-1127, -637, -491, -1317, 395, -506, 822, 702, +438, 985, -213, 203, -299, -458, -191, -298, +9, 34, -94, 147, -139, -115, 91, -266, +248, -108, 275, 225, -15, 477, -185, 279, +-261, -91, -193, -481, 90, -560, 238, -159, +133, 407, -80, 747, -120, 354, 56, -361, +220, -677, 25, -207, -416, 283, -401, 206, +163, -131, 669, -25, 422, 419, -316, 416, +-717, -253, -371, -932, 500, -577, 758, 552, +34, 1156, -801, 477, -609, -705, 415, -968, +947, -261, 373, 593, -655, 517, -880, -13, +-123, -203, 522, 128, 416, 132, 7, -452, +-21, -739, 166, 46, 38, 1156, -577, 1061, +-796, -516, -147, -1658, 1043, -867, 1317, 1024, +156, 1630, -1283, 278, -1423, -1260, -104, -1125, +1132, 364, 1078, 1178, 5, 394, -791, -916, +-451, -913, 204, 377, 267, 1271, -198, 463, +-403, -1029, 64, -1262, 717, 117, 613, 1289, +-395, 927, -1059, -483, -524, -1199, 592, -533, +934, 637, 299, 985, -644, 310, -694, -593, +33, -803, 578, -296, 359, 399, -213, 740, +-490, 494, -271, -99, 352, -767, 489, -793, +93, -45, -328, 794, -350, 778, -156, 82, +150, -518, 358, -429, 256, -109, -148, 56, +-354, -92, -320, 51, 71, 483, 398, 599, +415, 7, -84, -743, -525, -854, -456, -203, +42, 586, 492, 892, 550, 466, 109, -202, +-509, -683, -703, -665, -239, -295, 482, 274, +661, 792, 240, 756, -282, -8, -432, -907, +-340, -842, -32, 66, 197, 699, 349, 482, +209, -35, 54, -326, -247, -247, -364, -20, +-218, 141, 99, 117, 353, -25, 211, -14, +14, -93, -122, -164, -62, 27, -197, 330, +-337, 349, -21, -130, 476, -610, 591, -473, +38, 192, -635, 764, -730, 545, 51, -241, +723, -720, 461, -447, -208, 183, -323, 459, +-141, 293, -21, -1, -40, -197, -52, -208, +209, -87, 383, 64, 84, 115, -551, 35, +-534, -19, 119, -5, 653, 97, 450, 54, +-342, -142, -808, -195, -217, 3, 702, 316, +599, 142, -296, -298, -705, -375, -169, 175, +490, 658, 353, 253, -192, -668, -389, -895, +-72, -46, 325, 994, 294, 990, -106, -74, +-543, -1074, -327, -993, 332, 23, 562, 914, +287, 900, -208, 161, -528, -604, -601, -808, +-71, -382, 737, 363, 802, 757, 69, 384, +-760, -345, -842, -645, -103, -105, 805, 550, +811, 460, -265, -400, -952, -925, -340, -210, +765, 1009, 797, 1207, -255, -67, -999, -1398, +-575, -1212, 425, 288, 949, 1372, 496, 972, +-361, -375, -735, -1038, -421, -516, 95, 435, +244, 583, 241, -89, 238, -531, 186, -132, +-77, 609, -405, 671, -408, -100, -219, -883, +101, -828, 400, 50, 528, 883, 312, 950, +-279, 232, -763, -719, -711, -1029, -7, -419, +833, 530, 813, 866, -77, 392, -705, -286, +-416, -539, 293, -247, 258, 136, -297, 161, +-503, -22, 100, -1, 838, 198, 602, 205, +-330, -212, -1025, -429, -583, -135, 392, 420, +754, 472, 185, -78, -362, -561, -167, -442, +383, 193, 230, 708, -548, 477, -779, -243, +-60, -729, 753, -465, 719, 104, 35, 445, +-432, 482, -407, 292, -119, -33, -71, -520, +-211, -774, 79, -310, 553, 545, 669, 966, +107, 452, -669, -341, -963, -770, -440, -565, +451, -18, 825, 462, 509, 545, 44, 336, +-379, -103, -606, -468, -516, -463, -73, -117, +423, 321, 609, 388, 256, 183, -204, -191, +-382, -223, -194, 9, -99, 132, -152, -105, +-34, -260, 225, -42, 438, 364, 293, 463, +-232, 7, -693, -557, -388, -566, 324, 65, +502, 581, 80, 537, -306, -27, -208, -516, +121, -524, 334, -52, 28, 450, -389, 505, +-336, 109, 67, -340, 233, -494, 193, -149, +75, 212, 5, 400, 3, 215, -117, -125, +-334, -232, -335, -123, 19, -29, 351, -95, +528, -22, 443, 263, -184, 443, -755, 212, +-840, -403, -286, -871, 627, -462, 1192, 643, +741, 1212, -477, 484, -1304, -758, -1018, -1180, +149, -473, 1127, 587, 980, 994, -34, 563, +-870, -311, -777, -857, -6, -588, 570, 198, +409, 671, -174, 426, -351, -130, -123, -409, +74, -294, 103, 85, 157, 274, 105, 142, +-43, -87, -388, -157, -570, -138, -131, 35, +730, 248, 1009, 249, 107, -91, -1006, -380, +-1168, -294, -196, 85, 967, 461, 1029, 335, +124, -125, -693, -468, -653, -304, -30, 166, +253, 482, 105, 265, -118, -354, 94, -571, +336, -54, 104, 573, -277, 578, -403, -15, +-199, -650, 107, -734, 325, -99, 205, 724, +42, 876, -74, 213, -163, -613, -326, -846, +-200, -367, 215, 298, 381, 687, 137, 531, +-258, -12, -258, -460, -34, -423, 172, -127, +73, 13, -187, 102, -233, 333, 63, 381, +366, 25, 163, -370, -261, -440, -445, -126, +-66, 229, 270, 357, 261, 157, -90, -163, +-328, -282, -103, -44, 301, 284, 279, 283, +-253, -229, -537, -603, -124, -298, 432, 542, +476, 890, -33, 273, -581, -654, -475, -907, +277, -295, 737, 396, 102, 736, -671, 516, +-610, -108, 186, -564, 751, -520, 531, -67, +-353, 181, -882, 250, -424, 378, 481, 309, +714, -144, 143, -632, -485, -517, -437, 167, +147, 611, 460, 415, 51, -44, -551, -364, +-460, -370, 233, -136, 763, 217, 485, 409, +-380, 208, -941, -207, -494, -439, 398, -206, +754, 299, 271, 488, -289, 93, -410, -417, +-152, -473, 181, 26, 105, 520, -229, 380, +-299, -261, 102, -497, 505, -37, 355, 445, +-153, 175, -694, -395, -600, -394, 135, 263, +581, 694, 432, 213, 39, -677, -312, -822, +-307, 43, -144, 907, -84, 737, -121, -312, +171, -898, 514, -442, 203, 467, -284, 674, +-544, 112, -313, -408, 164, -384, 527, 46, +240, 281, -294, 201, -441, -51, -101, -115, +419, -122, 399, -124, -126, -48, -577, 211, +-334, 373, 105, 96, 394, -369, 489, -488, +207, -16, -362, 520, -727, 347, -545, -292, +213, -445, 851, 181, 768, 576, -146, 33, +-902, -724, -855, -621, 18, 312, 842, 1005, +817, 641, -108, -418, -859, -1097, -614, -675, +191, 355, 642, 999, 314, 647, -270, -243, +-324, -753, -24, -493, -65, 88, -239, 389, +-32, 272, 438, 90, 530, -21, 73, -136, +-747, -241, -1004, -179, -127, 100, 932, 247, +1034, 159, 166, -15, -752, -96, -956, -169, +-423, -194, 415, -36, 708, 262, 475, 437, +-28, 91, -390, -428, -565, -575, -326, -94, +154, 497, 520, 589, 437, 173, -111, -372, +-485, -654, -304, -359, 126, 301, 307, 718, +134, 453, -158, -308, -287, -657, -25, -308, +221, 245, 146, 414, -50, 153, -95, -110, +-92, -181, -115, -73, -67, 62, 59, 68, +136, -27, 171, -82, 53, -26, -209, 119, +-333, 161, -153, -12, 163, -206, 318, -141, +178, 21, -159, 125, -315, 142, -111, 55, +94, -69, 85, -176, -16, -95, -60, 41, +25, 123, 76, 140, -16, 26, -107, -80, +-130, -178, -25, -182, 8, 20, 110, 302, +129, 381, -24, -25, -151, -521, -166, -512, +-27, 86, 119, 691, 169, 537, -45, -209, +-141, -677, -54, -406, 76, 243, 18, 506, +-57, 194, -89, -217, -17, -195, 173, 60, +139, 68, -78, -95, -291, -75, -174, 37, +110, -10, 312, 39, 178, 228, -132, 285, +-210, -125, -162, -590, -52, -482, 7, 229, +155, 750, 288, 481, 216, -167, -189, -483, +-610, -397, -376, -231, 295, 62, 607, 452, +337, 614, -214, 151, -505, -469, -345, -539, +52, -89, 333, 145, 216, 7, -50, 76, +-169, 454, -20, 488, 81, -191, -33, -846, +-201, -688, -240, 245, -10, 817, 510, 556, +557, -110, -215, -421, -922, -390, -522, -180, +515, 114, 856, 338, 283, 183, -526, -148, +-723, -115, -125, 175, 520, 196, 447, -313, +-82, -495, -275, -10, -217, 595, 20, 435, +117, -195, 110, -568, -40, -192, -2, 318, +90, 356, 98, -40, -177, -311, -373, -152, +-132, 10, 421, 166, 570, 344, 46, 287, +-500, -274, -527, -752, -124, -407, 329, 517, +518, 882, 274, 335, -249, -446, -467, -707, +-166, -387, 122, 148, 98, 539, 22, 521, +138, 70, 184, -433, 12, -472, -207, -111, +-384, 255, -191, 191, 242, 45, 500, 185, +193, 255, -297, -283, -341, -748, -146, -245, +76, 675, 161, 741, 228, -8, 37, -482, +-212, -465, -181, -162, 98, 126, 143, 401, +-42, 361, -111, 34, -17, -290, 122, -423, +192, -211, 12, 184, -379, 415, -326, 236, +338, -77, 632, -172, 32, -229, -558, -252, +-452, 1, 91, 432, 520, 402, 448, -125, +-125, -424, -580, -214, -279, 69, 274, 137, +422, 230, 83, 177, -271, -98, -220, -380, +133, -180, 267, 236, -31, 316, -268, -4, +-94, -207, 199, -39, 168, 99, -30, -54, +-120, -143, 0, 65, 85, 237, -83, 50, +-143, -190, 53, -151, 260, 82, 69, 143, +-144, -31, -123, -132, -17, -16, 54, 191, +128, 102, -1, -159, -169, -282, 34, -45, +285, 308, 69, 303, -280, -88, -283, -362, +79, -185, 397, 167, 184, 226, -251, 7, +-312, -92, 177, 20, 373, 116, -32, -51, +-433, -296, -288, -245, 270, 170, 612, 542, +399, 401, -352, -240, -816, -727, -451, -471, +437, 228, 877, 678, 476, 442, -279, -100, +-711, -418, -426, -340, 87, -26, 355, 64, +316, -7, 331, 191, 180, 467, -303, 284, +-703, -424, -475, -784, 349, -280, 899, 501, +589, 632, -326, 225, -774, -208, -423, -347, +225, -360, 495, -123, 284, 345, -87, 474, +-153, 39, -34, -402, -75, -255, -151, 216, +68, 281, 347, -76, 122, -292, -290, -115, +-265, 149, 228, 300, 463, 267, -1, -187, +-554, -643, -312, -327, 406, 596, 538, 787, +-14, -69, -360, -745, -183, -437, 67, 288, +286, 523, 108, 74, -229, -393, -267, -252, +176, 388, 507, 546, 254, -186, -312, -926, +-682, -579, -358, 664, 541, 1210, 1039, 444, +251, -712, -733, -1140, -786, -543, -130, 446, +508, 1047, 695, 580, 303, -260, -455, -551, +-579, -371, -55, -245, 409, -37, 317, 437, +-41, 576, -305, 174, -72, -366, 365, -403, +142, -151, -317, 47, -158, 113, 286, 234, +127, 265, -178, -110, -22, -365, 149, -93, +119, 324, -17, 223, -178, -288, -93, -358, +189, 26, 259, 429, -61, 282, -250, -142, +-82, -272, 192, -180, 342, 16, 49, 197, +-267, 212, -277, -129, 23, -378, 192, 63, +239, 574, 246, 318, 52, -483, -259, -743, +-451, -169, -97, 504, 417, 726, 486, 306, +30, -403, -271, -766, -142, -420, 77, 469, +81, 686, -34, 172, -168, -404, -50, -506, +382, 33, 486, 469, 82, 404, -520, -339, +-588, -692, -51, -46, 432, 681, 497, 472, +274, -387, 86, -561, -245, 63, -572, 478, +-453, 72, 238, -455, 797, -200, 597, 274, +-175, 429, -665, 4, -357, -306, 305, -207, +369, 93, 6, 60, -212, -213, 9, 56, +331, 539, 196, 340, -175, -530, -333, -866, +23, -64, 204, 923, 52, 912, -43, -375, +49, -1376, 267, -657, 303, 1146, -50, 1657, +-729, -123, -522, -1945, 546, -1294, 1094, 1194, +281, 2131, -793, 201, -670, -1836, 197, -1385, +629, 798, 190, 1678, -408, 378, -235, -1169, +407, -1157, 566, 328, -206, 1236, -780, 506, +-193, -902, 780, -990, 709, 493, -271, 1294, +-868, -2, -279, -1550, 628, -874, 869, 1263, +73, 1814, -774, -40, -583, -1922, 277, -1320, +577, 819, 259, 1716, -144, 446, -117, -1100, +63, -898, 41, 401, -270, 976, -330, -56, +304, -1132, 769, -503, 367, 1117, -549, 1265, +-794, -427, -57, -1551, 727, -557, 577, 1134, +-246, 1172, -539, -395, 8, -1344, 552, -396, +178, 1143, -509, 1164, -365, -380, 472, -1477, +676, -621, -8, 1047, -650, 1166, -475, -409, +283, -1129, 833, 76, 467, 1174, -450, 307, +-781, -1204, -174, -1169, 414, 454, 603, 1592, +380, 912, -176, -644, -443, -1431, -284, -814, +-78, 485, 165, 1170, 602, 577, 558, -424, +-233, -553, -790, 65, -451, 99, 453, -477, +924, -455, 261, 518, -700, 1236, -642, 464, +234, -1100, 661, -1460, 414, -101, -193, 1299, +-615, 1167, -156, -195, 415, -1150, 281, -837, +-42, 363, 20, 1002, 138, 520, -12, -478, +-147, -837, -330, -281, -67, 535, 636, 657, +543, 16, -207, -416, -578, -279, -180, 2, +245, 76, 416, 148, 136, 74, -317, 29, +-174, 17, 374, 27, 357, -155, -184, -240, +-471, -10, -180, 245, 496, 267, 643, 27, +-74, -193, -617, -157, -231, -76, 338, -17, +417, 26, 197, 189, -160, 254, -426, 73, +-146, -222, 352, -597, 378, -273, 225, 545, +-65, 912, -365, 195, -350, -889, -19, -965, +437, 23, 516, 1043, 171, 869, -247, -310, +-348, -1006, -259, -447, -80, 387, 377, 561, +620, 126, 173, -209, -309, -126, -287, 111, +-147, 19, -133, -385, 204, -347, 497, 394, +342, 875, -88, 229, -386, -943, -323, -963, +-20, 268, 355, 1136, 388, 570, 160, -643, +-190, -843, -266, -183, -66, 628, 107, 660, +200, -65, 198, -693, 27, -497, -128, 483, +-125, 772, -43, -137, 205, -868, 437, -256, +171, 944, -659, 639, -549, -758, 397, -1109, +1003, 208, 422, 1389, -705, 538, -901, -1028, +-50, -1197, 880, 262, 670, 1309, -314, 540, +-514, -939, 49, -1085, 424, 293, 28, 1385, +-474, 490, -283, -1263, 494, -1369, 1033, 529, +209, 1870, -1066, 637, -1041, -1520, 279, -1587, +1257, 580, 753, 1749, -558, 353, -812, -1479, +17, -952, 524, 1050, 50, 1524, -374, -304, +15, -1891, 570, -926, 503, 1378, -295, 1932, +-858, -48, -211, -1807, 764, -1134, 682, 903, +-266, 1456, -639, -125, -46, -1420, 607, -467, +534, 1311, -234, 1426, -789, -635, -546, -2005, +664, -1041, 1240, 1311, 408, 2130, -832, 473, +-1081, -1476, -173, -1556, 679, -82, 952, 984, +391, 886, -484, 166, -768, -449, -269, -594, +458, -349, 666, 86, 287, 676, -381, 792, +-593, -93, 5, -1392, 677, -1167, 434, 741, +-311, 2101, -452, 981, -53, -1372, 391, -2150, +307, -540, -128, 1368, -267, 1433, 185, 238, +509, -567, 16, -486, -576, -357, -519, -496, +277, -327, 1081, 666, 667, 1448, -695, 691, +-1221, -1209, -139, -1825, 1118, -274, 826, 1422, +-373, 1183, -852, -300, -69, -1018, 907, -235, +534, 690, -758, 313, -1072, -842, 337, -799, +1486, 785, 666, 1602, -795, 209, -1250, -1783, +-241, -1590, 967, 665, 965, 2136, -114, 957, +-745, -1374, 6, -1712, 585, 19, -22, 1413, +-943, 613, -408, -816, 1361, -706, 1697, 618, +-343, 946, -2251, -382, -1324, -1335, 1205, -474, +2350, 1085, 966, 1393, -1591, -117, -2033, -1474, +126, -1024, 1884, 876, 908, 1612, -917, -18, +-930, -1685, 146, -1098, 928, 1077, 608, 1899, +-670, 327, -899, -1569, 170, -1570, 962, 100, +421, 1366, -403, 1071, -476, -252, 22, -942, +607, -431, 144, 434, -636, 315, -178, -491, +667, -510, 508, 487, -176, 1106, -431, 331, +-254, -1066, 239, -1182, 554, 60, -1, 1088, +-470, 603, -22, -450, 576, -597, 436, 243, +-198, 741, -686, -122, -508, -1226, 587, -905, +1014, 924, 267, 1915, -531, 668, -520, -1403, +-88, -2014, 203, -312, 324, 1573, 67, 1451, +108, -279, 435, -1382, 160, -391, -557, 993, +-735, 841, -37, -880, 862, -1800, 987, -119, +174, 2099, -843, 2137, -857, -530, 102, -2654, +830, -1982, 428, 624, -324, 2253, -206, 1522, +461, -111, 405, -1115, -368, -1186, -761, -800, +-247, -34, 615, 848, 1104, 1258, 632, 966, +-639, -187, -1239, -1481, -595, -1687, 664, -342, +1293, 1375, 746, 1781, -485, 544, -1127, -1005, +-427, -1424, 612, -552, 888, 552, 213, 904, +-540, 390, -586, -386, 194, -633, 888, -105, +477, 510, -382, 612, -900, -122, -484, -989, +622, -860, 1273, 351, 646, 1326, -647, 926, +-1194, -324, -482, -1292, 660, -1082, 1138, 94, +539, 1136, -542, 923, -833, -49, -150, -702, +662, -535, 753, -111, -168, 244, -781, 187, +-306, 90, 777, 34, 907, -108, 17, -105, +-709, 135, -745, 229, 17, -254, 881, -499, +870, -157, -56, 465, -659, 599, -558, 129, +-27, -606, 786, -717, 906, 38, -77, 832, +-1092, 525, -861, -573, 455, -1085, 1582, -120, +1370, 1333, -541, 1202, -2156, -611, -1746, -2004, +727, -1175, 2991, 1118, 2359, 2440, -773, 1146, +-3349, -1577, -2387, -2828, 1011, -970, 3347, 1937, +2268, 2806, -964, 624, -2690, -2203, -1379, -2522, +1053, -182, 1683, 2102, 555, 1872, -570, -181, +-365, -1654, 308, -1222, 210, 172, -659, 947, +-720, 570, 794, 13, 1846, -139, 550, 4, +-1836, -312, -2185, -931, 310, -602, 2893, 854, +2374, 1868, -1029, 809, -3353, -1361, -1946, -2317, +1714, -1042, 3489, 1466, 1500, 2519, -1808, 1019, +-2615, -1521, -669, -2303, 1470, -745, 1589, 1267, +333, 1770, -651, 379, -589, -1246, 23, -1252, +345, 164, 378, 1298, 93, 846, -488, -762, +-588, -1701, 194, -714, 1348, 1374, 1219, 2122, +-384, 509, -1904, -1803, -1475, -2408, 846, -441, +2437, 2120, 1460, 2313, -1210, -57, -2237, -2351, +-415, -1734, 1907, 869, 1701, 2273, -918, 729, +-2399, -1890, -421, -2124, 2628, 419, 2645, 2674, +-708, 1710, -3379, -1376, -2058, -2982, 1606, -1260, +3425, 1750, 1295, 2646, -1776, 747, -2244, -1546, +-245, -1969, 1784, -483, 1226, 1004, -676, 1158, +-1400, 304, -71, -542, 1640, -756, 1212, -212, +-446, 477, -1717, 581, -925, -92, 914, -718, +1543, -546, 556, 184, -699, 870, -660, 852, +105, -152, 499, -1283, 237, -1250, -407, 250, +-476, 1519, 138, 1105, 1001, -422, 936, -1341, +-41, -733, -971, 444, -1108, 917, -188, 268, +866, -680, 1267, -719, 841, 186, -118, 1118, +-882, 748, -1180, -611, -711, -1865, 710, -1316, +1851, 914, 1442, 2784, -410, 1942, -1776, -1190, +-1454, -3641, 156, -2610, 1772, 1143, 1588, 4119, +170, 3194, -1211, -1021, -1237, -4445, -376, -3506, +641, 874, 1267, 4217, 1159, 3301, 303, -611, +-1183, -3539, -2125, -3031, -905, 44, 1793, 2610, +3406, 2696, 1533, 616, -2308, -1773, -4140, -2584, +-1598, -1319, 3088, 1115, 4778, 2540, 1486, 1646, +-3344, -853, -4553, -2445, -953, -1684, 3634, 687, +4438, 2065, 421, 1298, -3687, -519, -3444, -1412, +429, -1025, 3429, 93, 2806, 689, -636, 707, +-2898, 436, -1979, 16, 972, -628, 2584, -1153, +1476, -766, -814, 601, -1985, 1876, -979, 1279, +1008, -768, 1884, -2449, 855, -1515, -1056, 825, +-1758, 2298, -504, 1318, 1562, -588, 2058, -1591, +476, -958, -1717, -4, -2226, 273, -274, 344, +2298, 798, 2467, 1102, 90, 135, -2112, -1570, +-1934, -2364, 32, -646, 1864, 2157, 1793, 3185, +-33, 640, -1252, -2601, -923, -3248, -32, -460, +763, 2469, 882, 2746, 384, 260, -422, -2123, +-668, -2271, -347, -174, 403, 1693, 1064, 1666, +649, 197, -554, -1211, -1047, -1292, -264, -542, +709, 515, 1079, 1115, 353, 1004, -650, -40, +-729, -1084, 266, -1382, 799, -344, 185, 798, +-552, 1215, -379, 575, 527, -219, 1024, -698, +270, -894, -720, -640, -845, -110, -68, 978, +653, 1371, 838, 794, 542, -717, -69, -1937, +-529, -1531, -879, 173, -306, 1977, 724, 2130, +1309, 275, 770, -1804, -409, -2322, -1345, -704, +-1090, 1248, 599, 1894, 1835, 951, 1228, -593, +-580, -1295, -1624, -990, -1028, 12, 706, 400, +1633, 402, 951, 383, -329, 685, -949, 311, +-701, -736, -109, -1764, 581, -1147, 875, 749, +626, 2477, 106, 1922, -363, -568, -808, -2976, +-470, -2672, 115, 252, 678, 3090, 1035, 2847, +806, -51, 18, -2642, -1020, -2671, -1437, -315, +-852, 1890, 890, 2036, 2619, 234, 2111, -1190, +-665, -732, -3106, 132, -2653, 86, 535, -729, +3530, -853, 3071, 608, -380, 2185, -3112, 1782, +-2464, -1130, 465, -3496, 2612, -2466, 1889, 1033, +-509, 3911, -1802, 2909, -676, -623, 1134, -3558, +1268, -2977, -247, -11, -1643, 2196, -763, 2314, +1576, 776, 2471, -450, 732, -1183, -2292, -1589, +-3114, -1446, -615, -103, 3281, 2007, 3977, 2645, +444, 1052, -3658, -1686, -3913, -3157, -6, -2026, +3941, 1010, 3744, 3078, -341, 2169, -3467, -484, +-2657, -2297, 580, -1749, 2937, -42, 2226, 1186, +-651, 1015, -2348, 43, -1225, -549, 1028, -193, +1735, 493, 858, 215, -568, -699, -1314, -1096, +-623, -301, 498, 853, 1052, 1215, 1088, 803, +345, -150, -760, -1114, -1577, -1617, -974, -1141, +718, 477, 2221, 2303, 2130, 2467, -36, 349, +-2498, -2647, -3014, -3608, -755, -1337, 2706, 2455, +4458, 4222, 2020, 1918, -2727, -2111, -5160, -4142, +-2684, -2032, 2514, 1474, 5669, 3163, 3539, 1785, +-1898, -668, -5392, -2023, -3548, -1732, 1429, -141, +4618, 1294, 3630, 1636, -480, 572, -3477, -1009, +-2948, -1808, -119, -1113, 2159, 1028, 2575, 2522, +1101, 1495, -686, -1551, -1904, -3427, -1723, -1922, +-388, 1911, 1488, 4040, 2622, 2170, 1609, -1813, +-888, -3969, -2950, -2499, -2388, 819, 525, 3067, +3205, 2732, 3221, 473, 344, -1736, -2877, -2511, +-3469, -1682, -902, -68, 2466, 1593, 3553, 2309, +1578, 1586, -1480, -262, -2890, -2144, -1680, -2583, +653, -1228, 2114, 1125, 1861, 2696, 380, 2326, +-1080, 61, -1616, -2210, -723, -2701, 561, -1149, +1376, 1190, 1212, 2478, 139, 1695, -1210, -535, +-1485, -2251, -33, -1667, 1619, 563, 1823, 2172, +235, 1148, -1822, -1365, -2080, -2533, -201, -704, +2015, 2230, 2542, 3121, 760, 790, -1504, -2720, +-2480, -3971, -1252, -1454, 723, 2575, 2184, 4242, +2012, 2020, 554, -1744, -1117, -3483, -1906, -2194, +-1602, 249, -210, 1537, 1531, 1626, 2526, 1385, +1811, 824, -237, -671, -2490, -2506, -3099, -2970, +-929, -702, 2203, 2692, 3921, 4261, 2372, 2025, +-1319, -2281, -4002, -4698, -3111, -2878, 829, 1534, +3804, 4147, 3281, 2824, 52, -723, -3030, -2958, +-3035, -2371, -279, -122, 2448, 1554, 2591, 1696, +649, 644, -1364, -415, -1956, -978, -783, -1032, +723, -500, 1489, 276, 877, 976, 106, 1007, +-513, 453, -598, -505, -513, -1381, -261, -1331, +199, -305, 889, 1337, 1154, 2067, 631, 1143, +-531, -980, -1436, -2446, -1254, -1827, -32, 294, +1404, 1984, 1872, 1965, 979, 593, -675, -1012, +-1736, -1693, -1414, -1222, -50, -109, 1155, 750, +1596, 1080, 872, 1000, -28, 434, -739, -353, +-1226, -1415, -980, -1529, 30, -597, 1253, 982, +1573, 1851, 926, 1473, -438, 95, -1545, -1632, +-1337, -2261, 8, -1068, 1167, 1126, 1224, 2163, +550, 1284, -193, -409, -582, -1214, -508, -1011, +-411, -426, -228, -191, 285, 313, 1123, 1131, +1361, 1483, 221, 347, -1462, -1689, -1983, -2506, +-583, -846, 1746, 2012, 2575, 2982, 1141, 865, +-1408, -2031, -2810, -2920, -1606, -899, 1235, 1650, +2951, 2386, 1992, 790, -500, -1110, -2336, -1494, +-2103, -459, -205, 379, 1688, 118, 1822, -197, +820, 342, -171, 1233, -886, 935, -1231, -776, +-849, -2198, 20, -1570, 989, 575, 1620, 2224, +1179, 1835, -318, 43, -1531, -1488, -1406, -1615, +-289, -729, 768, 336, 1248, 809, 832, 802, +70, 657, -244, 271, -335, -458, -437, -1087, +-715, -940, -491, -140, 234, 551, 1216, 642, +1691, 567, 942, 622, -820, 349, -2225, -704, +-2049, -1679, -162, -1429, 2113, 283, 2943, 1774, +1343, 1835, -1233, 391, -2620, -921, -1676, -1241, +310, -839, 1519, -493, 1199, -289, 394, 498, +10, 1611, 123, 1954, -7, 507, -774, -1797, +-1546, -2903, -1016, -1711, 858, 670, 2566, 2437, +2198, 2489, -92, 1164, -2085, -803, -2492, -2452, +-1078, -2861, 840, -1304, 2080, 1477, 2001, 3472, +800, 2826, -780, -54, -2014, -2817, -1761, -3285, +-131, -1162, 1403, 1336, 1590, 2376, 547, 1601, +-324, 237, -334, -819, 60, -1334, -190, -1276, +-979, -560, -1138, 700, 184, 1429, 1818, 972, +2040, -208, 457, -963, -1274, -548, -1793, 263, +-1090, 373, -1, -447, 561, -999, 1217, -91, +1658, 1448, 1407, 1722, -460, 165, -2467, -1718, +-2788, -2126, -803, -709, 2118, 1198, 3292, 2006, +2053, 1156, -543, -377, -2400, -1282, -2498, -1202, +-1181, -447, 808, 125, 2215, 756, 2313, 1033, +798, 749, -1083, -183, -2095, -1066, -1420, -1087, +-104, -422, 914, 455, 1122, 921, 1109, 900, +659, 273, -193, -631, -1158, -1128, -1556, -733, +-735, 259, 770, 992, 1828, 836, 1076, 43, +-400, -714, -1005, -801, -402, -228, 258, 354, +54, 565, -405, 387, -420, 86, 400, -309, +1172, -710, 967, -738, -200, 76, -1050, 1269, +-1185, 1462, -461, -46, 313, -1914, 998, -1949, +1105, 157, 873, 2139, -75, 1947, -1214, -238, +-1759, -1816, -908, -1535, 875, 121, 1986, 1099, +1590, 855, -42, 49, -1305, -339, -1535, -253, +-770, -215, 368, -163, 1207, -50, 1065, 231, +277, 228, -369, -57, -636, -185, -458, 76, +-202, 317, 56, 81, 169, -376, 352, -487, +570, -64, 381, 301, -75, 336, -702, 133, +-749, 93, -194, 168, 703, -108, 813, -704, +27, -950, -575, -180, -134, 1187, 565, 1750, +434, 557, -513, -1377, -1099, -2101, -487, -853, +833, 1088, 1564, 1878, 693, 906, -728, -701, +-1424, -1218, -742, -529, 410, 490, 969, 515, +515, -247, -187, -730, -199, -83, 135, 1135, +122, 1217, -365, -106, -601, -1588, -105, -1450, +522, -28, 592, 1306, 169, 1164, -123, 181, +-75, -508, -97, -328, -215, -73, -474, -324, +-256, -765, 271, -504, 813, 762, 735, 1613, +145, 1133, -432, -489, -865, -1707, -879, -1593, +-398, -358, 523, 1034, 1430, 1526, 1485, 1221, +329, 218, -1426, -1011, -2160, -1850, -1123, -1347, +893, 463, 2029, 1903, 1489, 1603, 50, -178, +-1085, -1385, -1193, -933, -727, 314, -24, 529, +378, -281, 750, -677, 839, 153, 609, 1315, +-111, 1167, -943, -505, -1144, -1885, -581, -1294, +325, 594, 978, 1726, 1083, 894, 504, -654, +-274, -1041, -842, -42, -988, 771, -583, 155, +296, -895, 916, -827, 850, 457, 333, 1415, +-106, 773, -456, -668, -715, -1312, -666, -475, +-230, 496, 439, 615, 1063, -5, 1066, -120, +173, 302, -1078, 529, -1315, -347, -520, -1207, +707, -728, 1079, 839, 335, 1656, -443, 584, +-380, -1160, 323, -1672, 459, -388, -231, 1299, +-868, 1517, -782, 307, 300, -1185, 1214, -1356, +961, -346, -145, 714, -784, 1024, -526, 619, +-79, 158, -166, -572, -397, -1132, -33, -981, +952, 144, 1628, 1373, 768, 1432, -1332, 184, +-2428, -1079, -1489, -1275, 764, -457, 2263, 350, +2091, 666, 283, 652, -1222, 420, -1837, -65, +-1263, -649, -295, -815, 917, -319, 1649, 454, +1418, 796, 317, 416, -1116, -292, -1694, -604, +-1130, -203, 20, 336, 1106, 336, 1223, -164, +742, -421, -4, -136, -315, 318, -692, 490, +-1113, 82, -947, -344, -1, -472, 1373, 2, +1974, 460, 1164, 398, -851, -338, -2319, -824, +-1974, -267, -54, 852, 1756, 1268, 2210, 354, +807, -1175, -992, -1762, -1586, -767, -731, 1096, +252, 2137, 427, 1325, 185, -629, -46, -2112, +471, -1797, 879, 50, 278, 1746, -1055, 1816, +-1584, 248, -518, -1224, 907, -1223, 1708, -4, +819, 725, -682, 269, -1383, -567, -635, -547, +562, 507, 798, 1249, 233, 721, -512, -878, +-534, -1624, 128, -860, 582, 708, 477, 1387, +93, 682, -426, -293, -861, -532, -677, -94, +162, -67, 1083, -493, 1254, -562, 452, 78, +-1004, 938, -1597, 1004, -804, 340, 660, -535, +1191, -955, 743, -1001, -136, -448, -335, 523, +-129, 1441, -125, 1304, -649, 171, -751, -1277, +100, -1688, 1167, -673, 1189, 738, 309, 1288, +-676, 644, -1132, -65, -864, -216, -280, -177, +427, -432, 978, -852, 1196, -522, 837, 616, +-524, 1415, -1796, 1007, -1763, -359, -280, -1289, +1432, -1143, 2058, -96, 1139, 730, -478, 934, +-1471, 522, -1528, -212, -733, -616, 426, -490, +1337, -19, 1362, 242, 584, 67, -484, 3, +-1211, 98, -1152, 335, -401, 186, 394, -241, +962, -643, 1070, -364, 465, 341, -415, 745, +-857, 394, -870, -434, -460, -673, 170, -186, +695, 376, 856, 446, 763, 177, 100, -147, +-882, -353, -1372, -359, -855, -149, 375, 223, +1416, 605, 1365, 670, 153, 77, -1017, -885, +-1156, -1249, -596, -408, 305, 943, 799, 1548, +652, 757, 104, -626, -268, -1417, -417, -1003, +-357, 103, -17, 927, 383, 913, 334, 302, +-137, -141, -553, -399, -322, -583, 597, -545, +909, -125, 237, 541, -790, 814, -1125, 420, +-514, -247, 618, -580, 1272, -343, 759, -33, +-300, 42, -952, -24, -880, 86, -176, 450, +670, 581, 669, 92, 90, -771, -139, -985, +-69, -199, -96, 787, -133, 947, -188, 122, +-330, -609, 28, -392, 519, 311, 541, 317, +-68, -505, -413, -888, -375, 85, 49, 1306, +304, 1266, -53, -324, -474, -1658, -195, -1289, +559, 382, 944, 1530, 337, 996, -759, -394, +-1349, -1042, -691, -394, 592, 533, 1245, 454, +891, -371, 88, -710, -658, 86, -951, 1069, +-796, 893, -201, -482, 549, -1435, 1246, -830, +1035, 710, -16, 1428, -1263, 511, -1515, -745, +-415, -993, 932, -113, 1363, 677, 501, 548, +-462, -185, -760, -555, -374, -283, 70, 263, +204, 495, 74, 382, 44, -59, 13, -506, +50, -694, 138, -219, 119, 590, -107, 981, +-229, 537, -336, -531, -259, -1186, 209, -685, +535, 475, 455, 1148, 30, 672, -366, -334, +-531, -809, -373, -487, 12, 101, 283, 383, +496, 334, 491, 186, 156, -10, -572, -186, +-835, -355, -375, -225, 396, 182, 790, 480, +476, 352, -207, -269, -592, -579, -432, -259, +114, 399, 525, 673, 432, 172, -282, -431, +-729, -647, -474, -246, 480, 297, 1031, 753, +693, 560, -464, -106, -1252, -829, -1029, -787, +96, -92, 1239, 788, 1427, 959, 339, 262, +-963, -625, -1459, -841, -697, -276, 491, 380, +1102, 592, 873, 316, -7, -133, -678, -323, +-808, -271, -206, -18, 504, 232, 604, 372, +2, 163, -542, -296, -411, -631, 296, -290, +814, 578, 523, 1063, -449, 435, -1115, -810, +-826, -1291, 288, -549, 1285, 758, 1154, 1359, +33, 807, -1089, -447, -1099, -1246, -297, -895, +558, 200, 714, 1035, 299, 753, 55, -134, +21, -635, -27, -279, -410, 263, -615, 268, +-322, -154, 328, -331, 843, -11, 675, 300, +48, 248, -518, 47, -603, 152, -473, 152, +-164, -308, 245, -898, 767, -628, 847, 602, +285, 1639, -705, 1212, -1152, -566, -537, -1947, +456, -1530, 881, 280, 387, 1680, -10, 1474, +-54, 257, 100, -711, -316, -922, -752, -852, +-566, -536, 401, 339, 1166, 1427, 980, 1568, +-111, 131, -1160, -1665, -1045, -1899, -62, -180, +811, 1633, 741, 1622, 159, -33, -213, -1323, +-177, -953, -94, 434, -193, 1079, -211, 408, +-32, -701, 339, -871, 378, -81, 189, 717, +-101, 774, -222, 179, -220, -339, -160, -542, +-42, -464, 237, -218, 356, 349, 301, 830, +-32, 686, -380, -68, -447, -819, -18, -778, +445, -163, 409, 495, -42, 701, -367, 404, +-217, -37, 218, -398, 404, -375, 82, -164, +-408, 78, -380, 190, 66, 234, 452, 243, +465, 159, -28, -31, -500, -336, -407, -453, +141, -189, 455, 374, 226, 731, -169, 505, +-312, -251, -71, -879, 240, -716, 248, 218, +26, 1039, -166, 903, -231, -71, -165, -1001, +8, -951, 294, -57, 446, 850, 269, 1046, +-308, 423, -762, -497, -568, -1035, 298, -735, +1004, 174, 759, 970, -219, 980, -998, 257, +-820, -674, 112, -972, 824, -486, 723, 341, +-24, 831, -612, 631, -508, 20, 0, -397, +284, -464, 251, -238, 121, -23, -40, 271, +-226, 497, -292, 400, -104, -67, 243, -549, +428, -488, 176, 81, -296, 599, -608, 441, +-280, -110, 259, -417, 471, -250, 341, 135, +-4, 285, -287, 215, -498, 147, -452, -33, +-77, -293, 434, -496, 876, -130, 473, 621, +-552, 965, -1307, 335, -772, -870, 616, -1255, +1396, -255, 659, 1118, -846, 1309, -1398, 62, +-412, -1109, 971, -872, 1112, 380, -26, 1008, +-1168, 284, -1063, -703, 129, -635, 1148, 313, +944, 896, -182, 425, -1060, -503, -1058, -764, +-284, -215, 575, 445, 1016, 550, 641, 234, +-184, -110, -1042, -137, -1193, -134, -374, -184, +788, -199, 1252, 139, 497, 530, -746, 510, +-1221, -14, -564, -592, 361, -631, 757, -32, +296, 696, -366, 736, -604, 86, -191, -585, +224, -631, 172, -5, -201, 604, -295, 591, +-133, -60, 86, -551, 26, -359, -176, 298, +-175, 616, 20, 170, 76, -463, -155, -475, +-276, 160, -290, 657, -86, 354, 161, -318, +201, -588, -107, -117, -363, 509, -217, 528, +-58, 6, -103, -433, -230, -312, -164, 146, +127, 378, 311, 169, 53, -59, -455, -58, +-698, -2, -416, -82, 139, -156, 475, 81, +333, 408, -139, 415, -496, -117, -574, -615, +-420, -413, -42, 332, 357, 720, 327, 358, +-46, -268, -423, -499, -486, -166, -252, 242, +-7, 267, -39, -36, -174, -59, -23, 249, +196, 418, 34, -33, -486, -712, -622, -601, +-289, 330, 204, 1076, 306, 592, -18, -392, +-389, -845, -346, -274, -49, 419, -77, 382, +-432, -101, -456, -201, 193, 376, 678, 673, +183, 42, -911, -907, -1303, -1006, -349, 159, +934, 1336, 1091, 1176, -109, -230, -1304, -1228, +-1210, -853, -88, 329, 721, 915, 581, 412, +-107, -286, -564, -278, -496, 192, -367, 297, +-317, -155, -209, -494, 220, -149, 524, 491, +174, 641, -586, 125, -1099, -419, -672, -413, +209, -75, 728, 261, 405, 372, -325, 260, +-832, -19, -717, -334, -151, -410, 337, 1, +285, 678, -192, 752, -510, -69, -476, -1019, +-88, -886, 251, 381, 127, 1424, -410, 952, +-678, -638, -421, -1397, 127, -468, 358, 882, +147, 969, -343, -101, -552, -751, -422, -95, +-218, 858, -101, 571, -2, -718, 149, -1304, +139, -231, -105, 1393, -525, 1605, -830, 80, +-482, -1536, 217, -1420, 656, 148, 276, 1330, +-439, 1018, -794, -108, -516, -670, -36, -343, +145, 75, -24, 27, -210, -83, -137, 175, +56, 503, 15, 421, -431, -195, -710, -644, +-495, -444, 210, 278, 639, 706, 366, 492, +-589, -139, -1049, -573, -552, -405, 271, 199, +585, 601, 131, 341, -569, -143, -759, -419, +-142, -206, 460, 257, 133, 391, -552, 86, +-627, -262, -55, -145, 461, 261, 216, 362, +-635, -40, -988, -499, -133, -339, 857, 392, +746, 846, -477, 378, -1399, -494, -1109, -924, +263, -360, 1328, 607, 926, 1000, -425, 478, +-1380, -370, -1174, -835, -273, -552, 618, 208, +901, 761, 493, 688, -279, 67, -929, -521, +-1000, -603, -489, -131, 305, 439, 780, 476, +502, 145, -187, -156, -670, -138, -638, 25, +-342, 53, -53, -53, 153, -142, 216, 136, +177, 386, -22, 297, -372, -152, -559, -476, +-349, -226, 68, 350, 251, 541, 86, 83, +-248, -361, -293, -280, -58, 191, 128, 443, +34, 157, -275, -301, -549, -378, -410, 90, +179, 456, 585, 327, 344, -150, -190, -368, +-575, -46, -712, 418, -451, 218, 109, -339, +607, -436, 642, 219, 179, 776, -568, 471, +-1018, -455, -741, -903, 67, -294, 792, 688, +837, 815, 98, 96, -762, -520, -872, -306, +-277, 294, 217, 333, 309, -285, 127, -613, +-36, 82, -15, 986, -65, 916, -300, -295, +-494, -1267, -211, -919, 212, 437, 478, 1303, +236, 854, -263, -217, -650, -883, -431, -634, +167, 63, 498, 502, 299, 481, -360, 214, +-702, -74, -280, -302, 479, -229, 653, 49, +-34, 299, -792, 152, -763, -106, 112, -176, +929, 119, 607, 400, -498, 143, -1103, -360, +-502, -419, 564, 99, 967, 595, 251, 387, +-750, -287, -914, -579, -181, -33, 546, 674, +541, 513, 61, -351, -305, -814, -302, -212, +-185, 785, -170, 938, -134, 24, 81, -926, +444, -767, 454, 184, -61, 953, -752, 708, +-834, -211, -151, -765, 696, -455, 910, 292, +208, 612, -714, 287, -861, -211, -155, -326, +452, -24, 435, 246, -100, 129, -431, -95, +-191, -97, 445, 116, 487, 277, -272, 117, +-893, -252, -613, -364, 348, 33, 995, 504, +668, 510, -418, -131, -1008, -649, -624, -433, +213, 384, 665, 850, 404, 345, -217, -509, +-495, -789, -158, -128, 305, 677, 236, 708, +-229, -24, -533, -557, -315, -330, 334, 223, +685, 337, 282, -20, -408, -229, -648, 161, +-355, 468, 61, 164, 334, -518, 246, -604, +65, 56, 29, 760, 9, 701, -323, -115, +-619, -759, -341, -514, 391, 283, 792, 705, +382, 370, -393, -257, -811, -557, -422, -201, +206, 379, 514, 596, 159, 236, -250, -382, +-275, -658, 99, -241, 241, 503, -106, 846, +-455, 279, -308, -550, 201, -758, 494, -73, +247, 667, -316, 515, -603, -234, -282, -613, +289, -1, 535, 745, 122, 650, -491, -405, +-637, -1150, -118, -575, 524, 746, 603, 1408, +69, 611, -611, -705, -743, -1201, -287, -555, +359, 441, 623, 810, 438, 583, -157, 118, +-569, -280, -641, -543, -271, -479, 202, -22, +563, 579, 462, 727, -63, 159, -541, -570, +-565, -613, -187, 50, 262, 623, 357, 452, +21, -203, -250, -548, -169, -218, 81, 343, +52, 455, -147, 159, -301, -139, -160, -126, +111, -84, 181, -174, 43, -237, -96, 111, +-108, 644, -87, 695, -142, -52, -238, -878, +-224, -862, 109, 74, 393, 940, 246, 790, +-211, -116, -468, -627, -337, -264, -87, 310, +83, 211, 106, -349, 143, -442, 218, 248, +87, 929, -381, 625, -714, -467, -453, -1115, +239, -601, 739, 546, 533, 1046, -225, 454, +-797, -406, -649, -580, -32, -106, 450, 249, +368, 84, -24, -104, -314, 42, -263, 348, +-70, 209, 29, -247, -56, -431, -157, -12, +-116, 465, 62, 364, 155, -226, 37, -545, +-244, -134, -385, 518, -169, 592, 193, 4, +247, -564, -46, -438, -334, 118, -293, 458, +39, 254, 229, -126, 48, -129, -349, 92, +-309, 167, 43, -113, 266, -330, 54, -134, +-306, 275, -387, 447, -70, 175, 296, -147, +215, -228, -189, -108, -416, -68, -286, -112, +-33, 55, 205, 365, 264, 502, 43, 159, +-237, -423, -414, -693, -385, -354, -93, 352, +298, 716, 473, 460, 166, -72, -350, -379, +-682, -352, -472, -213, 81, -56, 459, 219, +415, 489, 33, 478, -397, -24, -549, -541, +-325, -571, 70, -61, 310, 426, 233, 484, +-63, 174, -265, -155, -220, -192, -134, -156, +-126, -71, -42, -29, 54, 163, 106, 274, +40, 183, -106, -89, -265, -264, -291, -178, +-107, 50, 143, 210, 260, 147, 47, 63, +-314, -20, -420, -67, -171, -123, 164, -105, +309, 85, 128, 278, -303, 161, -496, -125, +-232, -305, 194, -38, 316, 220, 76, 225, +-210, -38, -285, -176, -147, -24, -95, 114, +-167, 40, 21, -116, 365, 15, 326, 254, +-211, 205, -774, -262, -669, -524, 155, -139, +905, 616, 655, 807, -403, 89, -1026, -881, +-622, -986, 320, -42, 720, 1020, 254, 1071, +-397, 116, -415, -812, -25, -912, 84, -310, +-194, 344, -289, 682, 85, 623, 514, 249, +284, -329, -506, -752, -861, -692, -321, -48, +573, 681, 794, 932, 143, 457, -722, -342, +-802, -879, -98, -675, 518, -21, 470, 613, +-42, 711, -390, 323, -402, -183, -71, -500, +147, -425, 183, -142, 47, 225, -154, 404, +-323, 284, -199, -33, 148, -180, 338, -140, +129, 46, -309, -4, -604, -124, -356, -250, +383, 19, 738, 542, 301, 729, -483, 131, +-886, -925, -523, -1249, 257, -309, 816, 1173, +641, 1643, -146, 564, -843, -1101, -846, -1747, +-99, -820, 618, 792, 720, 1586, 229, 1040, +-453, -253, -762, -1091, -399, -1086, 203, -388, +468, 466, 314, 1001, 5, 989, -287, 226, +-402, -730, -280, -1286, -17, -790, 267, 334, +368, 1258, 180, 1211, -261, 215, -495, -966, +-371, -1371, 50, -717, 347, 557, 394, 1333, +138, 1104, -246, -67, -535, -1121, -479, -1301, +16, -384, 567, 907, 623, 1425, 54, 746, +-673, -667, -853, -1411, -155, -964, 709, 358, +798, 1368, -1, 1246, -685, 39, -711, -1236, +-92, -1484, 481, -435, 557, 960, 67, 1627, +-299, 939, -438, -475, -258, -1559, 18, -1413, +271, -81, 317, 1293, 105, 1675, -198, 658, +-399, -736, -177, -1580, 131, -1164, 172, 107, +-25, 1275, -67, 1422, 35, 469, 206, -752, +58, -1335, -388, -887, -522, 179, -4, 1109, +508, 1151, 448, 302, 36, -820, -331, -1215, +-420, -561, -224, 581, 50, 1144, 151, 704, +251, -337, 335, -983, 92, -769, -385, 81, +-569, 817, -263, 851, 302, 217, 575, -622, +253, -934, -279, -465, -324, 388, -47, 969, +-8, 720, -136, -111, -49, -916, 215, -904, +374, -98, 127, 824, -396, 985, -520, 210, +-36, -691, 469, -927, 341, -241, -92, 596, +-454, 880, -258, 271, 246, -562, 442, -870, +119, -284, -320, 569, -333, 925, -175, 394, +55, -493, 239, -938, 443, -563, 323, 280, +-206, 820, -805, 780, -690, 173, 204, -497, +1036, -924, 879, -740, -203, 1, -1116, 908, +-884, 1290, 311, 643, 1083, -668, 617, -1630, +-568, -1255, -960, 256, -189, 1704, 830, 1722, +837, 271, -157, -1500, -924, -1929, -795, -725, +157, 1095, 872, 1900, 783, 1064, 84, -560, +-433, -1637, -689, -1245, -608, 36, -188, 1243, +542, 1368, 984, 427, 833, -829, -53, -1369, +-1195, -780, -1314, 444, -274, 1377, 1000, 1091, +1166, -173, 551, -1435, -265, -1296, -597, 138, +-582, 1511, -527, 1378, -349, -201, 361, -1520, +1271, -1311, 1271, 207, 14, 1422, -1545, 1221, +-1837, -88, -441, -1086, 1526, -1102, 1962, -192, +548, 565, -1192, 932, -1450, 650, -413, 52, +676, -649, 862, -1065, 265, -663, -318, 339, +-481, 1306, -129, 1120, 246, 8, 461, -1199, +277, -1302, -263, -350, -763, 816, -671, 1233, +268, 689, 1298, -265, 1235, -1018, -87, -977, +-1628, -229, -1783, 767, -146, 1125, 1764, 641, +2012, -466, 433, -1174, -1406, -903, -1877, 196, +-784, 1120, 934, 1045, 1601, 107, 945, -911, +-243, -1052, -1087, -363, -1156, 540, -419, 877, +729, 625, 1323, 8, 1090, -555, -205, -795, +-1547, -558, -1781, 171, -229, 839, 1741, 944, +2373, 222, 821, -626, -1657, -1028, -2769, -576, +-1383, 321, 1196, 963, 2745, 757, 2078, -88, +-281, -697, -2363, -624, -2544, -23, -704, 342, +1502, 347, 2663, 84, 1874, -10, -428, -74, +-2504, -68, -2611, -113, -558, -91, 1940, 30, +2966, 128, 1477, 182, -1280, 23, -2844, -124, +-1886, -165, 500, -5, 2346, 144, 2189, 183, +222, -34, -1749, -183, -2132, -182, -740, 14, +1010, 202, 2029, 175, 1412, 111, -411, -73, +-1936, -104, -1820, -276, -136, -237, 1702, -10, +2298, 428, 864, 640, -1493, 271, -2705, -473, +-1431, -999, 1187, -621, 2865, 400, 2149, 1210, +-570, 892, -2916, -171, -2779, -1145, -39, -995, +2751, -84, 3225, 766, 832, 890, -2282, 403, +-3456, -180, -1560, -649, 1656, -707, 3419, -341, +2232, 388, -796, 883, -3050, 722, -2682, -131, +-105, -907, 2372, -913, 2922, -63, 1146, 876, +-1437, 961, -2875, 175, -2022, -791, 398, -910, +2588, -232, 2831, 662, 677, 870, -2171, 335, +-3232, -516, -1490, -907, 1550, -469, 3369, 417, +2229, 989, -918, 632, -3135, -325, -2557, -1054, +168, -757, 2630, 184, 2868, 997, 698, 901, +-2018, 92, -2959, -797, -1457, -1063, 1235, -454, +3023, 534, 2305, 1159, -457, 820, -2917, -167, +-2840, -1087, -293, -1105, 2521, -272, 3223, 840, +1132, 1336, -1875, 737, -3171, -478, -1802, -1403, +850, -1158, 2798, 8, 2594, 1328, 390, 1632, +-2181, 590, -3082, -1231, -1644, -2126, 1342, -1152, +3531, 1126, 2796, 2564, -528, 1656, -3603, -915, +-3438, -2785, -227, -2057, 3334, 580, 3835, 2730, +875, 2298, -2767, -115, -3693, -2333, -1323, -2330, +2002, -424, 3346, 1703, 1804, 2234, -1100, 934, +-2808, -975, -2143, -2016, 179, -1386, 2330, 285, +2654, 1763, 835, 1812, -1890, 345, -3058, -1504, +-1674, -2172, 1401, -997, 3440, 1236, 2594, 2480, +-685, 1652, -3473, -811, -3275, -2619, -188, -2281, +3125, 146, 3877, 2523, 1367, 2815, -2298, 690, +-4004, -2083, -2459, -3130, 1132, -1545, 3853, 1369, +3560, 3118, 224, 2275, -3340, -481, -4074, -2746, +-1325, -2778, 2541, -415, 4217, 2158, 2352, 2967, +-1495, 1174, -3808, -1424, -2798, -2835, 411, -1855, +3085, 573, 3187, 2509, 797, 2503, -2131, 361, +-3213, -2127, -1721, -3117, 1140, -1302, 3212, 1744, +2760, 3629, -199, 2180, -3038, -1307, -3272, -3931, +-543, -2907, 2703, 826, 3740, 3911, 1416, 3402, +-2200, -283, -3698, -3528, -1968, -3613, 1439, -357, +3536, 2803, 2756, 3554, -453, 1131, -3127, -1854, +-3059, -3306, -485, -1964, 2449, 814, 3474, 2949, +1605, 2718, -1669, 195, -3412, -2524, -2253, -3282, +815, -1073, 3209, 2031, 3028, 3572, 155, 1786, +-2802, -1522, -3308, -3621, -891, -2337, 2373, 972, +3642, 3508, 1738, 2863, -1876, -371, -3682, -3292, +-2176, -3398, 1356, -326, 3673, 2973, 2837, 3888, +-568, 1211, -3366, -2479, -3148, -4241, -209, -2212, +2796, 1746, 3523, 4317, 1424, 3157, -1850, -777, +-3509, -4016, -2404, -3845, 799, -275, 3390, 3333, +3373, 4162, 433, 1283, -2863, -2433, -3684, -4075, +-1334, -2089, 2209, 1459, 3782, 3634, 2198, 2668, +-1316, -467, -3383, -3070, -2492, -3094, 513, -461, +2901, 2490, 2865, 3449, 462, 1336, -2224, -1987, +-2942, -3775, -1173, -2126, 1636, 1516, 3122, 3962, +2134, 2840, -878, -934, -3152, -3951, -2701, -3476, +320, 162, 3073, 3679, 3241, 3949, 557, 744, +-2601, -3111, -3367, -4249, -1142, -1687, 2016, 2303, +3232, 4325, 1855, 2598, -943, -1428, -2744, -4214, +-2250, -3266, 51, 518, 2171, 3837, 2659, 3712, +1040, 430, -1451, -3184, -2781, -4007, -1771, -1489, +933, 2357, 2965, 4179, 2533, 2522, -271, -1392, +-2931, -4205, -2933, -3437, -182, 304, 2832, 3944, +3323, 4137, 910, 823, -2270, -3419, -3344, -4536, +-1559, -1884, 1460, 2596, 3274, 4634, 2464, 2747, +-305, -1574, -2831, -4372, -2992, -3437, -763, 426, +2203, 3900, 3435, 3951, 1843, 694, -1402, -3342, +-3321, -4316, -2367, -1658, 635, 2730, 3041, 4478, +2758, 2337, 128, -2050, -2471, -4334, -2699, -2817, +-627, 1194, 1944, 3910, 2661, 3130, 1171, -252, +-1343, -3296, -2453, -3292, -1488, -683, 813, 2529, +2415, 3288, 1929, 1497, -214, -1695, -2221, -3209, +-2214, -2244, -300, 847, 2006, 3203, 2574, 2934, +1003, -137, -1609, -3266, -2791, -3562, -1533, -519, +1175, 3257, 2935, 3995, 2125, 1157, -488, -2907, +-2802, -4191, -2617, -1881, -202, 2156, 2594, 4034, +3020, 2592, 964, -1125, -1978, -3564, -3156, -3064, +-1690, 1, 1221, 2778, 3194, 3146, 2433, 941, +-349, -1840, -2917, -2889, -2908, -1614, -491, 947, +2480, 2422, 3247, 1881, 1282, -265, -1824, -1851, +-3262, -1892, -1882, -235, 1110, 1242, 3121, 1743, +2346, 711, -334, -701, -2742, -1647, -2621, -1190, +-445, 171, 2277, 1561, 2944, 1745, 1160, 352, +-1735, -1485, -3200, -2256, -1752, -932, 1251, 1190, +3336, 2508, 2324, 1542, -697, -607, -3246, -2432, +-2832, -2114, 67, -223, 2971, 1962, 3196, 2489, +704, 1092, -2352, -1303, -3422, -2572, -1573, -1743, +1600, 525, 3419, 2373, 2270, 2138, -635, 125, +-3126, -2025, -2876, -2286, -254, -679, 2673, 1584, +3176, 2346, 911, 1160, -2009, -1169, -3164, -2428, +-1460, -1641, 1432, 715, 2925, 2451, 1691, 2099, +-870, -190, -2506, -2317, -1903, -2497, 282, -484, +2231, 1968, 2192, 2759, 109, 1198, -2056, -1474, +-2502, -2904, -593, -1877, 1942, 890, 3028, 2977, +953, 2484, -1976, -399, -3214, -3069, -1399, -2998, +1648, 13, 3266, 3189, 1915, 3414, -1272, 206, +-2986, -3289, -2172, -3655, 547, -445, 2430, 3211, +2330, 3730, 90, 737, -1852, -2807, -2129, -3724, +-539, -1293, 1216, 2200, 1899, 3668, 756, 1938, +-959, -1553, -1601, -3657, -656, -2476, 774, 977, +1428, 3560, 674, 2830, -906, -628, -1417, -3440, +-479, -2904, 848, 413, 1259, 3252, 623, 2786, +-700, -426, -1112, -3007, -571, -2438, 375, 408, +649, 2602, 595, 2035, 64, -408, -314, -2099, +-344, -1571, -250, 336, -156, 1520, 52, 991, +407, -291, 476, -936, 214, -373, -373, 380, +-637, 257, -409, -413, 455, -446, 815, 438, +474, 1137, -642, 394, -926, -1197, -298, -1719, +875, -124, 1138, 1889, 92, 1973, -1127, -322, +-1173, -2446, 215, -1982, 1270, 811, 1108, 2866, +-403, 1732, -1152, -1369, -852, -3056, 606, -1344, +1138, 1780, 517, 2949, -852, 857, -898, -2003, +-60, -2565, 908, -427, 889, 1900, -56, 2099, +-854, 117, -774, -1587, 96, -1681, 479, -158, +671, 1203, 377, 1418, 237, 520, -393, -813, +-847, -1433, -1037, -1013, 35, 359, 1579, 1502, +1903, 1526, 317, 93, -1936, -1574, -2326, -1957, +-500, -538, 2196, 1471, 2720, 2301, 551, 901, +-2249, -1389, -2644, -2502, -380, -1238, 2326, 1307, +2783, 2661, 461, 1458, -2378, -1238, -2904, -2753, +-489, -1626, 2513, 971, 3354, 2711, 970, 1865, +-2464, -589, -3670, -2675, -1191, -2209, 2380, 353, +3721, 2602, 1732, 2419, -1895, -340, -3410, -2657, +-1712, -2308, 1495, 470, 2789, 2591, 1738, 1980, +-623, -517, -2031, -2374, -1579, -1697, 119, 383, +1564, 1830, 1745, 1513, 575, 78, -1226, -1132, +-1992, -1484, -775, -864, 1436, 496, 2340, 1598, +1136, 1690, -1381, -102, -2385, -1984, -1172, -2251, +1314, 76, 2344, 2376, 1400, 2254, -510, -228, +-1692, -2411, -1610, -1853, -323, 178, 1284, 1758, +2083, 1334, 1353, 348, -737, -657, -2294, -1124, +-1688, -1256, 756, -311, 2519, 1201, 1844, 1980, +-708, 705, -2319, -1441, -1460, -2118, 979, -592, +2323, 1483, 1469, 1682, -807, 286, -2116, -1320, +-1498, -1182, 626, -128, 2202, 1024, 1996, 1010, +162, 155, -1752, -809, -2311, -1147, -991, -368, +1441, 598, 2838, 1256, 1969, 690, -709, -273, +-2791, -1271, -2398, -1169, 432, -83, 2803, 1276, +2566, 1521, -98, 149, -2313, -1511, -2089, -1420, +185, 351, 2094, 1662, 1990, 700, -26, -1250, +-1807, -1500, -1811, 289, -29, 1943, 2010, 1035, +2367, -1044, 443, -2037, -2148, -656, -2634, 1162, +-518, 1628, 2391, 623, 2923, -813, 880, -1299, +-2070, -780, -2722, 490, -732, 1199, 1975, 780, +2428, -548, 606, -1253, -1570, -539, -1721, 817, +33, 1282, 1599, 280, 1176, -1032, -492, -1394, +-1282, -350, -481, 1109, 979, 1618, 1296, 577, +271, -1041, -998, -1762, -929, -833, -51, 711, +1032, 1497, 1102, 1046, 79, 23, -993, -960, +-901, -1422, 210, -1039, 1269, 585, 1114, 1997, +-439, 1658, -1512, -673, -808, -2342, 996, -1587, +1694, 840, 675, 2085, -1001, 1095, -1508, -587, +-245, -1415, 1087, -965, 1277, -133, 22, 938, +-767, 1306, -630, 792, 327, -930, 701, -1709, +259, -1007, -453, 892, -400, 1740, 171, 1030, +566, -564, 460, -1498, -29, -1273, -408, 7, +-400, 1469, -59, 1592, 224, 176, 729, -1665, +491, -1562, -110, 127, -713, 1650, -554, 949, +90, -497, 729, -1160, 849, -229, 52, 576, +-653, 505, -772, -324, -17, -493, 720, -24, +942, 655, 101, 560, -848, -424, -803, -1081, +224, -552, 960, 986, 599, 1434, -293, 127, +-677, -1594, -141, -1253, 314, 584, 294, 1619, +-192, 507, 72, -944, 427, -944, 292, 298, +-452, 509, -809, -122, -102, -501, 843, 386, +1097, 897, -22, 116, -1032, -1172, -1008, -1151, +184, 325, 1152, 1485, 937, 1227, -230, -552, +-979, -1564, -697, -1313, 244, 555, 773, 1651, +581, 1354, -98, -657, -473, -1654, -272, -1133, +38, 609, 51, 1463, 39, 808, 159, -317, +429, -1212, 306, -793, -229, -60, -1017, 1168, +-594, 1022, 586, 213, 1490, -1395, 790, -1203, +-894, 49, -1821, 1472, -720, 935, 1224, -335, +1819, -1102, 661, -428, -1138, 374, -1717, 251, +-760, 72, 1031, -70, 1719, 465, 924, -59, +-898, -304, -1856, -624, -979, 139, 1121, 288, +2015, 485, 543, 45, -1520, -155, -1720, -507, +34, -462, 1726, 163, 1392, 915, -611, 787, +-1770, -519, -988, -1359, 820, -924, 1545, 879, +914, 1569, -666, 904, -1486, -831, -849, -1541, +566, -1042, 1230, 412, 596, 1450, -374, 1264, +-787, -8, -288, -1371, 280, -1353, 108, -123, +-52, 1157, 0, 1120, 341, 119, -7, -865, +-284, -769, -281, -115, 195, 626, 406, 582, +-128, -58, -590, -626, -424, -362, 612, 368, +902, 560, 345, -46, -755, -543, -1162, -258, +-528, 462, 808, 407, 1305, -271, 492, -605, +-675, -119, -1137, 602, -444, 502, 380, 17, +748, -517, 273, -517, -21, -307, -410, 332, +-406, 693, -301, 655, 462, -180, 699, -911, +57, -707, -913, 88, -893, 663, 461, 580, +1234, 222, 823, -243, -916, -515, -1255, -605, +-569, 5, 860, 602, 861, 618, 388, -125, +-375, -546, -397, -248, -413, 384, -245, 238, +66, -296, 428, -383, 564, 79, 79, 544, +-387, 240, -792, -247, -153, -543, 350, -21, +801, 302, 81, 385, -536, -170, -822, -516, +125, -166, 795, 519, 551, 722, -339, -139, +-745, -904, -339, -603, 209, 458, 494, 695, +317, 161, 245, -289, -175, 30, -622, 167, +-758, -439, 46, -820, 905, -9, 948, 1172, +-49, 1010, -937, -268, -913, -1333, -101, -733, +651, 221, 754, 778, 226, 608, -195, 280, +-614, -219, -536, -879, -185, -812, 439, 52, +807, 1355, 613, 1060, -309, -290, -1258, -1597, +-921, -1169, 498, 525, 1634, 1716, 973, 1271, +-775, -576, -1821, -1866, -724, -1400, 1028, 662, +1483, 1923, 319, 1254, -821, -725, -911, -1657, +-199, -825, 293, 651, 393, 924, 373, 379, +157, -285, -222, -187, -493, -84, -234, -374, +141, -320, 290, 215, 164, 893, 280, 458, +241, -494, -305, -1203, -1007, -390, -522, 707, +774, 1138, 1638, 491, 671, -606, -1228, -1021, +-1921, -712, -683, 186, 1190, 906, 1956, 1129, +914, 191, -807, -897, -1913, -1282, -1327, -429, +327, 848, 1949, 1169, 1654, 308, -152, -655, +-1721, -826, -1626, -117, -34, 596, 1476, 450, +1585, -170, 232, -643, -1125, -263, -1501, 467, +-433, 768, 1041, 113, 1677, -575, 459, -728, +-1104, -126, -1468, 510, -348, 462, 953, 185, +1119, -266, 286, -290, -606, -69, -552, 213, +-335, 76, 77, -301, 215, -400, 357, 125, +388, 960, 163, 702, -310, -608, -690, -1505, +-407, -789, 432, 1122, 1082, 1702, 596, 434, +-628, -1249, -1322, -1472, -472, -129, 1055, 1057, +1502, 1088, 144, 75, -1280, -724, -1156, -863, +36, -179, 1077, 598, 810, 584, 22, 146, +-362, -383, -385, -223, -616, 78, -403, -187, +378, -288, 1211, -3, 1022, 832, -354, 792, +-1542, -470, -1197, -1468, 421, -756, 1670, 1085, +1247, 1627, -449, 370, -1439, -1580, -811, -1432, +560, 403, 1104, 1649, 322, 887, -505, -941, +-549, -1677, 122, -127, 286, 1432, 26, 1323, +-129, -555, 103, -1743, 274, -733, -21, 1221, +-391, 1609, -361, 61, 104, -1492, 605, -1425, +655, 457, 184, 1655, -681, 1100, -1018, -595, +-441, -1735, 798, -1111, 1673, 723, 707, 1830, +-977, 1196, -1773, -780, -615, -2044, 1034, -1242, +1688, 974, 493, 2151, -958, 1110, -1292, -1152, +-319, -2158, 834, -817, 1134, 1242, 162, 1929, +-966, 623, -912, -1228, 246, -1779, 1242, -358, +586, 1184, -711, 1505, -1115, 119, 23, -1168, +1035, -1124, 920, 240, -524, 973, -1021, 668, +-261, -421, 719, -815, 905, -193, 113, 447, +-829, 521, -740, 68, 140, -252, 758, -388, +621, -189, -138, -94, -752, 443, -426, 598, +282, 258, 632, -549, 195, -907, -285, -378, +-424, 583, -55, 991, 304, 514, 420, -304, +153, -996, -218, -753, -346, -80, -201, 857, +274, 1059, 341, 425, 235, -609, -154, -1207, +53, -713, -16, 226, -187, 1058, -552, 1043, +-77, 355, 747, -791, 993, -1474, 35, -958, +-1243, 574, -1086, 1856, 193, 1435, 1347, -476, +960, -1843, -208, -1680, -1207, 66, -773, 1527, +108, 1843, 1106, 685, 1060, -1019, 124, -2073, +-1182, -1514, -1326, 408, -111, 2220, 1324, 2204, +1730, 223, 197, -2088, -1463, -2583, -1645, -867, +-214, 1574, 1151, 2629, 1396, 1421, 445, -773, +-642, -2238, -990, -1786, -663, -233, 16, 1354, +581, 2003, 773, 1356, 555, -314, -93, -2040, +-804, -2350, -771, -570, -295, 1877, 689, 2825, +1023, 1137, 626, -1409, -406, -2578, -961, -1541, +-726, 596, 19, 1898, 848, 1820, 1011, 269, +328, -1120, -550, -1796, -1175, -928, -843, 370, +254, 1317, 1319, 1217, 1253, 348, 184, -418, +-1232, -1093, -1775, -1106, -692, -634, 1027, 566, +2099, 1708, 1289, 1685, -517, 169, -2102, -1891, +-1853, -2659, -59, -906, 1919, 1699, 2114, 3109, +907, 1618, -1204, -1238, -2241, -2916, -1645, -1920, +403, 573, 2010, 1963, 2273, 1739, 608, 210, +-1787, -600, -2623, -924, -1262, -988, 1237, -848, +2536, -103, 1652, 1314, -718, 1902, -2132, 1068, +-1594, -850, 289, -2255, 1470, -1889, 1074, -289, +-54, 1758, -494, 2480, -233, 1706, 21, -586, +-411, -2660, -576, -2906, 27, -867, 939, 2171, +1099, 3627, 225, 2203, -928, -1057, -1388, -3662, +-561, -3146, 450, -269, 1354, 2781, 1007, 3571, +-102, 1563, -1118, -1288, -1128, -3212, -285, -2625, +581, -534, 856, 2250, 569, 3282, 115, 2152, +-360, -873, -800, -3329, -622, -3261, -36, -561, +785, 2708, 756, 3763, 230, 1668, -150, -1800, +-264, -3525, -472, -2137, -885, 1034, -496, 2638, +750, 1701, 1895, -499, 1152, -1412, -990, -692, +-2327, 408, -1471, 349, 613, -514, 1920, -735, +1500, 160, 103, 1334, -1003, 1440, -1215, 128, +-775, -1607, -174, -2120, 457, -1006, 1045, 1101, +1335, 2503, 813, 1983, -775, 51, -2251, -2101, +-2152, -2675, 137, -1554, 2679, 894, 3177, 2854, +763, 2994, -2372, 670, -3758, -2512, -1848, -3786, +1519, -1972, 3729, 1630, 2898, 3782, -450, 2617, +-3556, -591, -3628, -3022, -441, -2703, 3023, -175, +3959, 2089, 1128, 2263, -2498, 448, -3799, -1484, +-1661, -1764, 1846, -173, 3748, 1527, 2146, 1539, +-1399, -360, -3573, -2170, -2573, -1770, 1003, 753, +3496, 2949, 2756, 2480, -460, -656, -3060, -3498, +-3068, -3147, -326, -90, 2442, 3152, 3188, 3637, +1283, 1294, -1773, -1856, -3401, -3636, -2043, -2732, +1246, 139, 3318, 3170, 2326, 3746, -790, 1286, +-2924, -2176, -2275, -3776, 428, -2059, 2494, 734, +2073, 2732, -102, 2336, -1963, 677, -1922, -1189, +-201, -2178, 1647, -1670, 1862, 66, 441, 1728, +-1369, 1687, -1820, 243, -648, -1145, 861, -824, +1693, 247, 994, 648, -456, -314, -1377, -1011, +-1148, -628, -287, 936, 761, 1658, 1212, 1132, +1081, -613, 236, -1843, -1033, -1833, -1824, -377, +-1332, 1281, 552, 2049, 2421, 1515, 2351, 52, +156, -1347, -2267, -2189, -3034, -1710, -1210, -260, +1746, 1895, 3147, 2989, 2000, 2267, -649, -482, +-2651, -3239, -2499, -3877, -435, -1566, 1524, 2160, +2102, 4369, 1370, 3379, 47, -119, -1166, -3331, +-1705, -4124, -1516, -2074, -163, 1077, 1459, 3364, +2376, 3435, 1490, 1499, -586, -1367, -2114, -3304, +-2322, -3247, -799, -1168, 1184, 1619, 2504, 3479, +2108, 3368, 168, 944, -1956, -2324, -2853, -4414, +-1397, -3367, 912, 343, 2734, 4113, 2164, 4739, +184, 1596, -1869, -2813, -2389, -4678, -1041, -2733, +914, 1099, 1849, 3448, 1430, 2776, 143, 316, +-995, -1676, -1430, -1924, -808, -1095, 271, 97, +1131, 723, 1128, 1145, 260, 940, -677, 301, +-953, -817, -524, -1314, -27, -870, 536, 363, +931, 1342, 688, 1026, -172, -43, -1202, -1158, +-1341, -1071, -136, -194, 1217, 910, 1628, 1070, +694, 532, -735, -443, -1688, -1139, -1469, -1029, +-259, -167, 1538, 1021, 2455, 1559, 1306, 751, +-1037, -637, -2779, -1506, -2252, -1207, 247, -117, +2421, 742, 2499, 1085, 817, 1151, -1136, 654, +-2069, -444, -1686, -1800, -500, -2172, 931, -842, +1947, 1748, 1807, 3167, 547, 2337, -1533, -672, +-2500, -3327, -1494, -3474, 673, -849, 1986, 2390, +1629, 3780, 238, 2143, -647, -813, -625, -2810, +-837, -2729, -1083, -864, -680, 1128, 807, 2263, +2279, 1920, 1958, 647, -157, -1033, -2417, -1894, +-2679, -1721, -860, -545, 1582, 969, 2563, 1889, +1694, 1634, -296, 266, -1708, -1202, -1800, -1697, +-907, -1037, 157, 63, 1167, 737, 1642, 839, +1268, 924, -14, 764, -1553, 196, -2130, -1182, +-1145, -2016, 836, -1536, 2021, 505, 1846, 2503, +508, 2517, -1073, 602, -2281, -1953, -1700, -2770, +109, -1464, 2050, 900, 2356, 2076, 671, 1615, +-1598, 51, -2327, -870, -895, -873, 966, -485, +1690, -302, 716, -240, -467, 126, -986, 806, +-274, 1275, 527, 828, 221, -468, -537, -1820, +-624, -1975, 343, -414, 1182, 1699, 966, 2585, +-622, 1461, -1573, -916, -1069, -2389, 460, -2146, +1314, -314, 1079, 1403, 99, 2254, -535, 1612, +-877, 12, -951, -1839, -483, -2593, 447, -1360, +1463, 1129, 1475, 2913, 222, 2290, -1510, -281, +-2108, -2537, -1173, -2618, 982, -658, 2371, 1761, +1993, 2349, -231, 1255, -2231, -646, -2288, -1514, +-407, -1310, 1666, -488, 2144, 230, 585, 856, +-1142, 1273, -1401, 987, -348, -83, 803, -1281, +778, -1645, -241, -742, -1010, 508, -463, 1393, +667, 1332, 1372, 465, 838, -447, -642, -1198, +-1685, -1046, -1452, -586, -153, 136, 1390, 720, +1871, 1243, 1244, 1312, -238, 535, -1559, -1056, +-2158, -2421, -1306, -2108, 273, -33, 2191, 2416, +2776, 3307, 1403, 1570, -1215, -1207, -3156, -3299, +-2883, -2932, -398, -495, 2153, 2011, 3173, 3019, +1961, 2048, -239, 53, -2126, -1751, -2646, -2498, +-1649, -2035, 84, -118, 1904, 1793, 2549, 2573, +1922, 1581, -42, -184, -2163, -1485, -2893, -1699, +-1680, -1459, 621, -720, 2257, 611, 2289, 2128, +1195, 2718, -317, 1144, -1442, -1602, -2202, -3433, +-1846, -2461, -203, 208, 1865, 2674, 2721, 2671, +1570, 911, -302, -984, -1818, -1556, -1956, -1086, +-1257, -528, -344, -240, 780, 190, 1892, 1158, +2298, 1570, 1213, 1011, -989, -487, -2795, -1572, +-3003, -1786, -1034, -895, 1688, 264, 3515, 1650, +2853, 2111, 324, 1309, -2298, -585, -3334, -2299, +-2059, -2296, 164, -667, 2104, 1424, 2464, 2155, +1639, 1422, 95, -264, -1376, -1145, -2100, -1086, +-1762, -527, -680, -28, 907, 116, 2065, 401, +2297, 699, 1110, 698, -870, 293, -2462, -387, +-2567, -755, -1092, -875, 967, -624, 2631, -46, +2593, 788, 1199, 1535, -1054, 1186, -2640, 0, +-2820, -1423, -1102, -1866, 1155, -1235, 2840, 179, +2746, 1552, 972, 2284, -1384, 1531, -2957, -484, +-2368, -2363, -584, -2494, 1375, -843, 2211, 1303, +2079, 2113, 940, 1685, -776, 495, -2279, -748, +-2629, -1804, -1008, -1803, 1315, -632, 2711, 1249, +2022, 1952, 142, 1017, -1356, -427, -1662, -993, +-1132, -393, -276, 107, 380, -195, 750, -804, +1073, -393, 1171, 661, 659, 1647, -658, 1120, +-1948, -230, -2114, -1360, -520, -1640, 1461, -945, +2566, 179, 1573, 1530, -236, 1918, -1621, 1212, +-1659, -704, -985, -1982, 60, -1891, 770, -488, +1066, 997, 1219, 1547, 738, 1234, -132, 392, +-1370, -447, -1744, -1048, -1256, -1137, 479, -685, +1846, 63, 1893, 730, 564, 991, -754, 845, +-1385, 631, -1101, -7, -424, -891, -26, -1963, +439, -1874, 1032, -81, 1316, 2386, 766, 3291, +-318, 1581, -1564, -1410, -2065, -3265, -1121, -2681, +806, -453, 2379, 1776, 2185, 2660, 613, 1970, +-1372, 346, -2311, -1358, -1635, -2233, -234, -1850, +1058, -539, 1733, 1033, 1594, 2051, 627, 2006, +-762, 832, -1725, -1025, -1890, -2276, -846, -2127, +700, -506, 2044, 1236, 1991, 2104, 741, 1710, +-1043, 469, -1982, -1010, -1706, -1979, -458, -1748, +756, -332, 1527, 1189, 1744, 1807, 900, 1280, +-514, 157, -2000, -851, -2073, -1486, -654, -1327, +1243, -251, 2058, 1109, 1477, 1634, -161, 895, +-1285, -505, -1339, -1287, -584, -927, 302, 251, +536, 887, 439, 551, 299, -595, 328, -879, +158, 53, -182, 1214, -719, 989, -825, -508, +-345, -1520, 511, -846, 1045, 642, 777, 1088, +-34, 385, -802, -470, -825, -253, -303, 224, +458, 307, 476, -395, 60, -726, -264, -302, +-19, 584, 271, 919, 508, 355, -12, -519, +-700, -673, -930, -42, -451, 286, 561, 116, +1183, -450, 1274, -180, 55, 516, -1157, 747, +-1727, 100, -1010, -702, 335, -691, 1647, -1, +1842, 582, 741, 284, -936, -201, -1918, -422, +-1640, 22, -259, 550, 1095, 490, 1706, -29, +1354, -760, 277, -814, -789, -208, -1750, 686, +-1588, 1025, -645, 500, 928, -439, 2037, -956, +1908, -539, 551, 187, -1225, 705, -2290, 470, +-2043, -141, -449, -619, 1377, -503, 2500, 247, +2122, 962, 386, 704, -1685, -344, -2754, -1246, +-2189, -1043, -74, 49, 1948, 1101, 2892, 1334, +1823, 653, -319, -509, -2048, -1329, -2411, -1163, +-1457, -160, 107, 749, 1513, 914, 2089, 567, +1696, 275, 422, 107, -1311, -455, -2539, -1227, +-2109, -1335, -374, -53, 1785, 1512, 2532, 1960, +1621, 651, -278, -1032, -1376, -1555, -1508, -852, +-1075, 121, -465, 524, 94, 506, 1006, 422, +1679, 383, 1604, 162, 303, -199, -1354, -608, +-2331, -730, -1859, -405, -347, 282, 1417, 775, +2365, 638, 2095, 124, 513, -251, -1341, -286, +-2553, -286, -2208, -277, -549, -39, 1340, 235, +2325, 147, 1810, -265, 511, -181, -739, 543, +-1354, 1143, -1696, 535, -1503, -964, -730, -1899, +1160, -1276, 2926, 408, 2878, 1730, 609, 1957, +-2298, 989, -3694, -462, -2734, -1903, -1, -2379, +2567, -1226, 3654, 993, 2508, 2651, -147, 2402, +-2888, 420, -3794, -1742, -2252, -2412, 770, -1437, +3079, 332, 3457, 1306, 1452, 1266, -1168, 637, +-2794, 248, -2730, -117, -991, -683, 1054, -1225, +2331, -1099, 2211, -61, 942, 1003, -993, 1409, +-2086, 895, -1855, 67, -574, -617, 900, -928, +1401, -1031, 1180, -788, 583, -75, 172, 1027, +-571, 1903, -1434, 1609, -2015, -6, -1055, -2059, +1106, -2708, 2948, -1146, 2776, 1410, 301, 2572, +-2580, 1472, -3643, -564, -1984, -1281, 910, -552, +2932, 139, 2880, -127, 1132, -726, -1132, -434, +-2429, 523, -2318, 1354, -876, 1193, 766, 341, +1929, -872, 1851, -1702, 1019, -1615, -120, -318, +-1293, 1346, -1983, 2151, -1745, 1404, -367, -198, +1515, -1435, 2436, -1660, 1798, -1014, 58, -200, +-1533, 691, -1942, 1467, -1390, 1749, -215, 940, +692, -847, 1412, -2385, 1435, -2309, 940, -404, +-90, 1766, -1098, 2528, -1733, 1337, -1598, -462, +-433, -1508, 1133, -1454, 2138, -745, 1887, 64, +502, 758, -1161, 1098, -2268, 743, -2008, 20, +-560, -330, 1244, -305, 2279, -382, 1640, -877, +264, -1037, -1142, 71, -1484, 1690, -1262, 2272, +-524, 835, 280, -1412, 1089, -2602, 1385, -1699, +968, 390, 134, 1923, -905, 1992, -1595, 784, +-1502, -580, -287, -1443, 1208, -1460, 2190, -709, +1536, 419, -199, 1281, -1818, 1483, -2053, 716, +-867, -481, 782, -1426, 1780, -1434, 1567, -428, +432, 747, -945, 1315, -1552, 832, -1242, -6, +-147, -585, 931, -524, 1347, -262, 927, -205, +-15, -366, -899, -278, -1013, 481, -511, 1229, +-47, 1112, 186, -219, 338, -1576, 641, -1664, +970, -339, 513, 1090, -577, 1456, -1659, 687, +-1588, -184, -292, -748, 1311, -662, 2092, -348, +1323, 84, -252, 339, -1603, 198, -1550, 38, +-740, 0, 217, 269, 752, 315, 1017, 44, +1151, -353, 727, -539, -397, -350, -1612, -19, +-1874, 344, -455, 661, 1293, 680, 1897, 295, +975, -521, -488, -1123, -1155, -897, -789, 164, +149, 1200, 442, 1236, 121, 186, -407, -993, +-343, -1062, 419, -178, 899, 688, 584, 603, +-463, -34, -1057, -301, -881, -160, 44, 46, +619, -110, 753, -211, 400, 57, -181, 334, +-488, 342, -377, -35, -7, -213, 117, -266, +-45, -170, -135, -333, 86, -364, 325, -90, +275, 600, 28, 1211, -120, 1046, -128, -167, +-198, -1642, -419, -2097, -227, -1104, 415, 795, +1001, 2110, 578, 2261, -367, 1131, -977, -651, +-712, -2361, 92, -2760, 615, -1400, 727, 1120, +377, 2817, -153, 2501, -633, 718, -660, -1080, +-241, -1771, 337, -1593, 668, -826, 598, 117, +168, 1060, -424, 1408, -1093, 1052, -952, 226, +36, -434, 1216, -697, 1525, -650, 494, -550, +-917, -486, -1673, -156, -1071, 537, 165, 1375, +1071, 1381, 1135, 173, 506, -1400, -71, -1864, +-430, -609, -604, 1061, -780, 1464, -683, 306, +-174, -1084, 895, -1156, 1681, 87, 1429, 1332, +-4, 1235, -1598, -6, -2257, -1235, -1314, -1501, +530, -753, 2100, 179, 2279, 983, 968, 1352, +-725, 1134, -1871, 159, -1860, -1146, -992, -1900, +337, -1329, 1530, 185, 2072, 1568, 1262, 1662, +-417, 637, -1772, -672, -1857, -1085, -800, -744, +341, -89, 1118, 325, 1211, 373, 909, 430, +108, 325, -776, 123, -1305, -327, -1093, -620, +-154, -418, 720, 211, 1029, 648, 783, 587, +233, 153, -270, -105, -615, -202, -911, -317, +-773, -619, -132, -571, 965, 48, 1493, 1037, +1112, 1403, -270, 675, -1503, -628, -1651, -1417, +-525, -1113, 866, -230, 1494, 459, 1300, 607, +304, 652, -754, 566, -1385, 314, -1194, -271, +-243, -735, 868, -757, 1247, -476, 886, -176, +212, 34, -322, 435, -791, 771, -1171, 842, +-1092, 297, -183, -431, 1060, -889, 1843, -934, +1386, -538, -100, -37, -1437, 445, -1898, 694, +-1329, 607, -97, 375, 1175, 205, 1881, 65, +1554, -332, 84, -943, -1337, -1321, -1854, -795, +-1034, 493, 163, 1772, 968, 1935, 1001, 821, +659, -818, 299, -1656, -128, -1165, -476, -199, +-830, 362, -638, 211, -121, 296, 511, 752, +692, 1067, 677, 598, 321, -331, -119, -979, +-508, -1004, -626, -695, -444, -268, -61, 271, +319, 885, 420, 1266, 526, 1003, 433, 145, +-112, -952, -823, -1446, -928, -1201, -284, -191, +620, 636, 1058, 989, 464, 760, -616, 267, +-966, -152, -552, -537, 325, -580, 647, -406, +417, 11, -48, 169, -269, 52, -163, -89, +-70, 103, -207, 291, -356, 182, -113, -199, +410, -296, 808, -34, 511, 196, -165, 124, +-677, -176, -587, -299, -273, -365, 75, -109, +359, 351, 640, 871, 617, 838, 158, 97, +-458, -788, -648, -1120, -380, -733, 56, 47, +238, 845, 155, 1230, 92, 932, 77, -83, +308, -1066, 376, -1054, 7, -154, -654, 740, +-982, 669, -538, -90, 281, -517, 973, -199, +827, 484, 71, 675, -378, 199, -469, -494, +-400, -812, -502, -473, -292, 236, 97, 798, +719, 733, 820, 81, 280, -781, -424, -1130, +-678, -631, -325, 539, -20, 1353, 129, 1049, +2, -226, 85, -1219, 349, -1108, 558, -283, +274, 284, -295, 351, -636, 343, -410, 531, +8, 413, 259, -125, 277, -599, 213, -652, +140, -283, 110, -50, 114, 166, -79, 361, +-264, 585, -444, 370, -343, -1, -89, -471, +322, -532, 420, -319, 400, 117, 192, 535, +-78, 574, -428, 120, -600, -536, -468, -609, +-92, 87, 351, 962, 427, 942, 251, -85, +-5, -1153, -23, -1276, -42, -210, -56, 1120, +-248, 1507, -424, 675, -281, -656, 202, -1256, +501, -628, 590, 361, 166, 675, -449, 220, +-546, -367, -146, -400, 428, -13, 545, 347, +228, 518, -335, 348, -608, -175, -322, -762, +148, -935, 546, -529, 425, 255, 202, 788, +-35, 1059, -141, 838, -302, -13, -615, -1189, +-463, -1794, 58, -978, 725, 570, 741, 1568, +300, 1043, -363, -50, -640, -672, -597, -382, +-177, 146, 234, 247, 409, -102, 382, -505, +24, -729, -343, -394, -436, 294, -89, 1045, +258, 1333, 418, 847, 94, -137, -378, -1116, +-545, -1592, -71, -1154, 497, 34, 687, 1155, +264, 1460, -470, 881, -719, 104, -539, -289, +193, -447, 713, -588, 1081, -550, 580, -288, +-447, 8, -1406, 130, -1223, 246, -56, 682, +1129, 1035, 1312, 543, 594, -602, -54, -1363, +-470, -935, -745, 206, -913, 596, -716, 57, +-25, -510, 885, -42, 1319, 979, 935, 1306, +-129, 344, -1031, -1131, -1258, -1763, -618, -1195, +254, 185, 719, 1082, 435, 1102, -23, 422, +-148, -153, 26, -250, 223, -173, 97, -277, +-56, -423, -339, -346, -401, -46, -301, 165, +147, 249, 431, 356, 437, 499, -37, 319, +-298, -262, 49, -702, 550, -527, 413, 148, +-311, 640, -870, 441, -841, -43, -82, -370, +768, -259, 1137, 15, 623, 164, -266, 213, +-756, 132, -444, 153, 77, 166, 152, 229, +-358, -32, -510, -518, 14, -811, 882, -423, +1060, 476, 361, 1064, -680, 760, -1253, -128, +-1030, -763, -156, -586, 830, 64, 1222, 464, +765, 172, -149, -511, -828, -630, -937, -69, +-412, 636, 79, 612, 446, -12, 550, -393, +470, -157, 150, 160, -144, -56, -372, -487, +-368, -479, -341, 98, -98, 528, 251, 362, +482, -29, 434, -125, 146, -2, -6, -5, +-291, -243, -450, -284, -433, -20, 35, 214, +543, 252, 715, 150, 243, 122, -500, 21, +-826, -201, -541, -392, 203, -286, 832, 81, +947, 558, 289, 781, -617, 496, -1149, -338, +-859, -1026, -76, -915, 707, 43, 962, 851, +646, 809, 45, 183, -457, -267, -640, -108, +-550, 108, -329, 28, -101, -359, 263, -553, +640, -382, 900, 109, 548, 626, -312, 862, +-1038, 548, -1093, -232, -344, -957, 478, -941, +1074, -270, 906, 460, 229, 679, -582, 316, +-851, -73, -485, -293, 103, -195, 427, -13, +344, 53, 275, -76, 210, -200, 25, -91, +-405, 139, -670, 129, -501, -135, 212, -154, +795, 279, 891, 588, 196, 222, -575, -670, +-910, -1027, -501, -362, 120, 623, 363, 1035, +225, 447, 45, -311, 208, -560, 371, -100, +247, 378, -328, 296, -787, -287, -761, -746, +-151, -357, 637, 454, 972, 1044, 686, 666, +-129, -225, -827, -747, -842, -587, -241, -23, +542, 361, 745, 508, 480, 343, -93, -73, +-469, -639, -629, -716, -370, -151, 100, 605, +607, 771, 706, 347, 372, -103, -144, -186, +-550, -205, -547, -363, -297, -513, 82, -393, +202, -24, 188, 239, 143, 387, 320, 540, +407, 606, 131, 277, -519, -421, -983, -957, +-624, -776, 238, -121, 947, 354, 854, 277, +123, -44, -625, -122, -768, 157, -379, 507, +166, 646, 440, 400, 395, -214, 228, -861, +119, -1039, -24, -646, -358, 56, -808, 560, +-766, 714, 128, 738, 1197, 655, 1449, 341, +414, -270, -852, -938, -1362, -1045, -729, -434, +201, 461, 714, 849, 490, 502, 145, -180, +-55, -397, -44, -98, 30, 321, -35, 502, +-187, 351, -320, 32, -141, -397, 55, -781, +316, -783, 297, -232, 224, 521, -87, 934, +-270, 659, -410, 54, -294, -381, 49, -353, +383, -179, 525, -69, 179, -178, -167, -266, +-483, -135, -368, 101, -147, 384, 249, 341, +386, 70, 292, -235, -132, -295, -278, -117, +-148, 67, 43, 102, 44, 72, -53, -49, +58, -208, 329, -330, 388, -174, -46, 219, +-545, 538, -696, 528, -342, 164, 225, -273, +762, -670, 897, -736, 543, -338, -204, 450, +-944, 1069, -1144, 903, -609, 70, 299, -723, +919, -814, 1002, -329, 514, 112, -123, 208, +-601, 208, -732, 435, -566, 597, -212, 282, +143, -445, 508, -931, 747, -582, 588, 263, +40, 852, -637, 666, -764, -53, -463, -533, +-7, -428, 323, -4, 412, 189, 366, 6, +198, -161, 18, 7, -240, 327, -335, 360, +-332, 50, -66, -312, 327, -372, 486, -204, +104, -45, -519, -17, -697, -41, -46, -3, +802, 150, 1056, 336, 370, 453, -700, 278, +-1201, -277, -803, -850, 135, -994, 804, -343, +910, 596, 437, 1092, -185, 751, -549, -31, +-559, -603, -202, -632, 120, -250, 297, 144, +150, 316, -18, 158, -29, -98, 79, -207, +210, -104, -11, 112, -334, 326, -435, 458, +16, 369, 383, -159, 395, -794, 2, -916, +-282, -231, -243, 682, -112, 942, -1, 445, +170, -175, 426, -256, 399, -6, -66, 105, +-662, -136, -723, -431, -221, -478, 494, -285, +744, 64, 452, 510, -92, 839, -357, 801, +-250, 253, -21, -487, 35, -975, -212, -948, +-371, -466, -178, 185, 346, 688, 822, 693, +711, 380, 21, 5, -848, -90, -1135, -79, +-655, -227, 480, -437, 1297, -454, 1097, -170, +-103, 235, -1230, 441, -1243, 351, -169, 56, +909, -236, 1123, -238, 453, 77, -463, 345, +-893, 205, -610, -280, 162, -650, 655, -500, +512, -5, -167, 469, -551, 678, -253, 595, +330, 255, 518, -223, 212, -698, -299, -786, +-588, -483, -459, 50, 22, 459, 521, 644, +734, 638, 361, 431, -298, 79, -702, -371, +-546, -710, 75, -868, 474, -651, 378, 11, +-40, 855, -303, 1327, -227, 883, 91, -160, +315, -1056, 287, -1120, -13, -449, -299, 486, +-297, 950, -175, 643, -11, -226, 133, -801, +203, -563, 193, 148, -41, 461, -196, 198, +56, -60, 445, 146, 332, 486, -388, 226, +-954, -467, -726, -886, 246, -613, 923, 24, +914, 479, 295, 574, -261, 547, -599, 366, +-602, 17, -319, -439, 26, -658, 291, -511, +459, -105, 269, 246, -52, 416, -195, 359, +-139, 101, 23, -149, 168, -198, 126, 10, +-222, 210, -438, 162, -351, -155, 129, -450, +521, -436, 626, -15, 180, 495, -291, 542, +-458, 32, -212, -476, 6, -328, 39, 274, +-135, 564, -180, 156, 221, -399, 543, -504, +483, -276, -101, -117, -490, -108, -568, 154, +-179, 651, 126, 860, 399, 397, 361, -458, +136, -998, -226, -842, -333, -193, -151, 417, +47, 700, 117, 474, 24, 34, 115, -301, +130, -198, 170, 186, -78, 342, -293, -13, +-387, -540, -144, -600, 218, -91, 394, 519, +272, 589, -51, 182, -220, -235, -178, -199, +23, 141, 108, 277, 13, -3, -135, -394, +-191, -495, -102, -233, 173, 180, 369, 526, +307, 665, -75, 394, -480, -206, -472, -741, +-11, -684, 451, -162, 456, 341, 73, 472, +-236, 351, -227, 134, -205, -137, -129, -455, +41, -455, 288, -68, 327, 410, 65, 500, +-216, 116, -248, -320, -74, -434, 86, -150, +162, 118, 46, 175, -96, -61, -180, -178, +-66, -11, 161, 324, 143, 414, -46, 36, +-77, -450, 47, -551, 184, -145, 38, 319, +-267, 410, -280, 108, -21, -195, 204, -310, +140, -119, 27, 210, -7, 481, 40, 365, +5, -107, -22, -485, -16, -383, 23, 15, +-93, 182, -269, 61, -154, 23, 234, 212, +406, 315, 171, 128, -99, -139, -234, -230, +-92, -174, 7, -88, 38, 37, 7, 226, +-71, 246, -78, 67, -14, -164, 228, -224, +224, -131, 27, -74, -227, 7, -220, 169, +-99, 345, 116, 349, 276, 127, 220, -227, +-87, -583, -427, -788, -495, -551, -7, 216, +557, 1073, 657, 1234, 215, 424, -369, -707, +-582, -1256, -498, -923, -108, -158, 329, 532, +720, 872, 522, 729, -135, 169, -840, -455, +-752, -707, 86, -538, 834, -190, 787, 119, +66, 407, -568, 554, -711, 376, -374, 17, +211, -234, 614, -238, 524, -298, 47, -436, +-396, -319, -369, 259, -79, 827, 198, 744, +79, 16, -75, -681, -171, -656, 77, -14, +393, 658, 452, 663, -56, -3, -766, -738, +-905, -824, -160, -154, 888, 666, 1265, 923, +536, 506, -661, -141, -1259, -557, -881, -571, +104, -294, 855, 138, 1009, 437, 312, 326, +-365, -120, -713, -380, -429, -122, 62, 362, +336, 433, 199, -53, -114, -540, -72, -534, +111, -41, 299, 478, 119, 583, -155, 152, +-447, -524, -322, -793, 168, -353, 545, 434, +358, 779, -209, 433, -479, -141, -174, -455, +312, -494, 304, -422, -42, -164, -347, 366, +-158, 803, 175, 617, 328, -127, 174, -832, +-115, -844, -296, -195, -212, 551, 78, 862, +140, 535, 27, -108, -181, -612, -121, -596, +112, -190, 327, 232, 345, 341, 140, 222, +-161, 189, -500, 259, -662, 215, -418, -140, +246, -584, 771, -714, 742, -345, 218, 381, +-333, 980, -420, 1030, -255, 350, -179, -633, +-114, -1175, 93, -865, 321, 12, 259, 707, +-56, 745, -226, 265, -182, -182, 81, -207, +265, 55, 252, 102, 65, -200, -118, -497, +-214, -333, -243, 181, -169, 459, -146, 281, +40, -85, 310, -201, 474, -123, 259, -18, +-123, 18, -359, 91, -260, 98, -93, -62, +44, -271, 36, -300, 47, -17, 78, 306, +79, 350, 20, 122, -91, -139, -99, -290, +-74, -276, 126, -164, 193, 137, 191, 460, +-12, 492, -272, 125, -371, -400, -200, -647, +153, -463, 366, 2, 463, 452, 215, 642, +-232, 428, -678, -39, -567, -361, 54, -317, +735, -60, 850, 96, 293, -21, -433, -176, +-767, -144, -659, 136, -188, 451, 381, 444, +675, 36, 517, -496, 30, -561, -302, -101, +-279, 509, -7, 613, 54, 85, -162, -557, +-352, -738, -220, -258, 260, 422, 612, 791, +508, 565, -134, -22, -614, -620, -597, -750, +-120, -372, 457, 207, 680, 521, 325, 428, +-275, 209, -640, 10, -541, -220, -45, -552, +468, -579, 615, -97, 295, 586, -159, 753, +-469, 287, -373, -312, -24, -550, 292, -396, +357, -141, 201, 141, -74, 401, -330, 485, +-345, 272, -187, -178, 96, -568, 308, -618, +429, -300, 329, 259, 86, 724, -327, 768, +-611, 296, -487, -427, -62, -845, 318, -622, +470, 12, 416, 534, 207, 575, -54, 234, +-328, -169, -491, -349, -485, -236, -129, 14, +344, 183, 708, 126, 616, 22, 87, 21, +-605, 97, -892, 28, -510, -154, 303, -286, +963, -239, 784, -13, -15, 255, -791, 476, +-853, 409, -247, -14, 517, -497, 752, -608, +425, -304, -144, 155, -457, 425, -381, 515, +-49, 408, 145, 11, 130, -547, -34, -843, +-51, -541, 65, 204, 220, 787, 284, 811, +90, 339, -237, -215, -453, -542, -355, -551, +-86, -360, 216, -120, 357, 79, 423, 283, +233, 542, -26, 642, -391, 362, -512, -376, +-321, -968, 87, -933, 327, -224, 322, 572, +127, 955, 42, 783, 92, 243, 6, -420, +-299, -878, -583, -857, -425, -386, 133, 316, +768, 811, 828, 908, 337, 487, -478, -185, +-863, -681, -644, -699, 39, -405, 545, -126, +515, 101, 128, 454, -154, 785, -141, 650, +-42, -52, 32, -797, -45, -861, -53, -292, +-24, 364, 72, 561, 13, 368, -49, 115, +-173, -38, -99, -204, 119, -353, 309, -385, +293, -194, 14, 172, -270, 549, -338, 683, +-124, 362, 25, -327, 9, -884, -22, -740, +129, -40, 279, 599, 218, 635, -23, 191, +-205, -208, -164, -267, -123, -67, -140, 93, +-111, 49, 131, -139, 313, -166, 269, 56, +7, 267, -211, 170, -156, -223, -20, -464, +55, -257, -32, 239, -89, 580, -52, 500, +135, 93, 268, -336, 173, -552, -64, -541, +-292, -324, -331, 75, -182, 598, 164, 881, +407, 625, 421, -226, 125, -975, -286, -976, +-553, -165, -380, 754, 31, 892, 350, 203, +367, -567, 214, -628, 74, -26, -30, 527, +-242, 430, -444, -89, -389, -485, -50, -374, +379, 39, 541, 402, 423, 422, 94, 146, +-216, -167, -514, -323, -575, -260, -338, -129, +134, 1, 572, 81, 737, 195, 469, 272, +-141, 324, -660, 208, -727, -147, -339, -494, +223, -571, 562, -234, 487, 228, 163, 395, +-196, 256, -340, 106, -255, 111, -2, 171, +137, -29, 143, -365, 55, -515, -50, -225, +-63, 190, -71, 305, -54, 117, 14, 20, +188, 242, 211, 367, 29, -39, -215, -713, +-332, -848, -166, -149, 110, 819, 267, 1034, +191, 342, 34, -538, -57, -814, -68, -423, +-9, 77, -50, 241, -112, 173, -149, 143, +3, 158, 166, 205, 199, 139, 86, -22, +13, -289, -5, -487, -80, -378, -203, 33, +-236, 365, -85, 370, 146, 190, 352, 84, +348, 82, 151, 6, -205, -173, -486, -338, +-520, -361, -100, -286, 364, -7, 573, 472, +385, 880, 47, 757, -225, -58, -475, -1018, +-538, -1317, -356, -646, 254, 462, 816, 1201, +875, 1126, 158, 432, -663, -359, -992, -859, +-566, -899, 157, -556, 630, -79, 652, 378, +319, 741, -69, 879, -327, 578, -365, -98, +-265, -810, -51, -1025, 113, -670, 160, -25, +87, 588, 49, 887, 105, 705, 220, 125, +95, -509, -210, -779, -460, -561, -333, -100, +147, 366, 569, 643, 469, 575, -148, 108, +-631, -469, -557, -759, 96, -481, 681, 84, +715, 542, 153, 616, -445, 384, -722, -17, +-577, -431, -139, -633, 438, -480, 808, 71, +698, 590, 80, 676, -647, 218, -930, -381, +-502, -630, 236, -255, 658, 325, 578, 566, +153, 160, -148, -395, -246, -438, -171, 27, +-195, 359, -249, 119, -205, -229, 115, -130, +489, 310, 578, 389, 282, -36, -245, -465, +-552, -376, -539, 11, -225, 250, 172, 182, +507, 1, 532, -31, 162, 58, -361, 100, +-521, 23, -227, -140, 258, -259, 451, -139, +183, 78, -216, 232, -354, 153, -202, -57, +36, -165, 245, -114, 246, 27, 212, 136, +31, 154, -205, 64, -452, -136, -392, -251, +-1, -139, 497, 127, 664, 214, 298, 16, +-288, -129, -648, -20, -486, 160, -51, 99, +345, -127, 438, -149, 301, 71, 11, 147, +-195, -45, -292, -235, -188, -154, -71, 128, +82, 322, 242, 250, 341, 30, 195, -233, +-195, -338, -501, -205, -461, 62, 27, 258, +407, 229, 495, 83, 267, -9, 63, 20, +-167, 9, -357, -122, -528, -315, -453, -337, +24, -114, 568, 249, 812, 500, 489, 546, +-130, 342, -680, -105, -708, -614, -249, -925, +308, -692, 596, 59, 381, 876, -172, 1078, +-594, 477, -395, -391, 196, -685, 694, -288, +598, 166, -40, 52, -663, -398, -661, -457, +-215, 74, 258, 721, 390, 788, 287, 248, +129, -464, 13, -804, -42, -542, -143, 101, +-166, 580, -188, 560, -62, 106, 71, -361, +229, -448, 169, -207, 36, 152, -76, 354, +-67, 272, -74, -15, -207, -270, -225, -304, +106, -42, 567, 297, 558, 444, 14, 198, +-669, -274, -812, -607, -340, -528, 405, -32, +738, 498, 617, 726, 56, 483, -426, -36, +-606, -442, -270, -519, 155, -359, 356, -113, +211, 62, -51, 214, -74, 325, 3, 338, +66, 302, -99, 127, -196, -230, -199, -654, +78, -757, 343, -281, 425, 476, 171, 880, +-198, 656, -440, 46, -439, -454, -237, -610, +71, -415, 398, -28, 610, 306, 540, 367, +-21, 128, -616, -177, -851, -218, -397, 47, +227, 325, 663, 293, 561, -102, 149, -482, +-221, -482, -330, -85, -248, 397, -194, 560, +-104, 254, 75, -192, 348, -418, 437, -246, +123, 19, -347, 105, -460, 105, -96, 233, +269, 364, 213, 101, -60, -469, -137, -755, +82, -319, 177, 472, -40, 799, -274, 369, +-154, -282, 179, -493, 324, -144, 135, 208, +-155, 151, -219, -182, -90, -265, 68, 51, +102, 399, 46, 337, -93, -113, -119, -475, +-16, -428, 138, 9, 205, 442, 126, 534, +-38, 199, -190, -250, -212, -479, -125, -291, +51, 80, 165, 272, 131, 110, -14, -193, +-55, -292, 8, -21, 96, 403, 22, 541, +-60, 285, -112, -219, -92, -592, -98, -614, +-46, -292, 135, 159, 315, 437, 291, 414, +-25, 309, -337, 223, -441, 38, -216, -367, +144, -691, 401, -495, 413, 103, 107, 535, +-285, 395, -408, 6, -102, -129, 284, 74, +358, 261, -40, 132, -460, -293, -481, -623, +-9, -529, 574, 19, 747, 647, 307, 801, +-425, 341, -805, -339, -511, -623, 192, -316, +622, 196, 437, 368, -77, 74, -406, -334, +-370, -459, -84, -154, 248, 386, 463, 778, +393, 632, -14, -69, -496, -780, -701, -875, +-313, -280, 312, 376, 709, 579, 536, 336, +-39, -20, -527, -209, -531, -188, -95, -23, +352, 118, 402, 77, 28, -63, -314, -91, +-222, 5, 148, 62, 391, -58, 201, -200, +-214, -137, -504, 82, -375, 263, 63, 273, +428, 129, 533, -98, 311, -282, -72, -289, +-391, -134, -493, 20, -392, 46, -15, 73, +451, 242, 581, 403, 235, 231, -271, -268, +-461, -604, -196, -395, 181, 117, 172, 351, +-89, 194, -116, 44, 147, 98, 375, 121, +234, -88, -228, -316, -637, -261, -585, 26, +-48, 258, 615, 301, 920, 170, 543, -84, +-262, -324, -858, -332, -760, -73, -200, 221, +372, 320, 603, 244, 484, 158, 127, 25, +-274, -225, -541, -457, -373, -453, 98, -128, +441, 300, 376, 579, 12, 563, -240, 229, +-254, -281, -88, -691, -8, -651, 75, -147, +129, 468, 151, 689, 77, 376, -48, -148, +-113, -504, -144, -478, -119, -151, -146, 239, +-52, 406, 184, 259, 442, 0, 447, -75, +88, -28, -490, -172, -823, -464, -531, -488, +144, -13, 694, 620, 741, 815, 345, 447, +-216, -166, -502, -667, -454, -756, -178, -392, +95, 195, 233, 557, 148, 475, 3, 195, +20, 52, 111, -24, 128, -225, -39, -509, +-229, -501, -323, -54, -63, 509, 273, 763, +440, 488, 204, -72, -206, -595, -500, -713, +-409, -334, 26, 286, 395, 645, 487, 457, +246, -24, -86, -279, -373, -178, -356, -79, +-160, -117, 130, -110, 245, 121, 161, 317, +-74, 218, -148, -30, -29, -121, 189, -115, +199, -207, -28, -344, -319, -148, -351, 376, +21, 742, 379, 487, 392, -288, -30, -934, +-400, -857, -385, -51, 64, 797, 422, 964, +426, 320, 49, -474, -337, -808, -506, -526, +-327, -24, 87, 369, 498, 526, 603, 414, +239, 53, -264, -374, -576, -512, -458, -267, +-80, 78, 299, 141, 375, 20, 265, 59, +62, 381, -94, 537, -220, 156, -212, -527, +-159, -903, 35, -621, 203, 105, 190, 787, +-34, 988, -124, 554, 22, -254, 210, -832, +126, -769, -276, -206, -522, 354, -202, 575, +446, 422, 677, 104, 289, -221, -371, -309, +-628, -154, -335, 80, 226, 169, 429, 79, +251, -18, -86, -59, -261, -34, -172, 3, +48, 76, 188, 66, 168, -47, 82, -134, +-112, -49, -274, 145, -296, 160, -11, -78, +362, -279, 499, -148, 128, 178, -376, 283, +-506, 52, -137, -189, 310, -190, 366, -118, +32, -177, -266, -136, -166, 223, 129, 621, +227, 455, 3, -274, -285, -863, -235, -688, +133, 46, 380, 612, 192, 567, -183, 89, +-348, -239, -149, -191, 97, 29, 134, 25, +39, -192, 124, -276, 236, 0, 100, 315, +-257, 318, -490, 47, -310, -157, 158, -115, +534, -27, 444, -11, 81, 13, -318, 133, +-476, 179, -255, 16, 168, -238, 382, -229, +220, 94, -91, 371, -268, 271, -156, -83, +69, -259, 217, -99, 152, 133, 3, 132, +-216, -67, -238, -206, -9, -93, 298, 172, +265, 317, -71, 139, -396, -172, -281, -276, +154, -27, 445, 223, 309, 138, -74, -182, +-343, -357, -390, -218, -179, 47, 93, 262, +356, 330, 382, 271, 260, 56, -38, -202, +-313, -378, -496, -442, -412, -393, -56, -163, +412, 267, 626, 651, 414, 646, -24, 224, +-360, -293, -377, -551, -303, -524, -151, -380, +30, -159, 289, 176, 364, 521, 277, 572, +46, 260, -118, -136, -206, -257, -256, -199, +-280, -216, -176, -301, 111, -185, 425, 199, +519, 497, 247, 432, -254, 84, -621, -167, +-466, -206, 39, -120, 439, -84, 381, -73, +42, 52, -184, 300, -141, 400, -45, 67, +-48, -456, -42, -590, 99, -47, 201, 629, +135, 726, -82, 184, -219, -400, -215, -550, +-83, -325, 50, -45, 164, 156, 251, 275, +195, 287, 23, 173, -128, 10, -137, -111, +-150, -195, -199, -281, -213, -303, -29, -136, +270, 150, 522, 355, 461, 344, 44, 198, +-450, -51, -674, -362, -429, -628, 86, -530, +497, 47, 468, 677, 188, 812, -122, 305, +-243, -411, -247, -860, -126, -741, 64, -112, +200, 646, 144, 913, -74, 421, -188, -374, +-31, -730, 225, -421, 254, 73, -2, 273, +-371, 194, -487, 108, -182, 113, 384, 122, +774, 60, 542, -92, -186, -282, -821, -334, +-766, -108, -100, 326, 538, 579, 577, 395, +190, -62, -118, -384, -147, -387, -57, -197, +-33, 31, -96, 261, -159, 458, -92, 396, +78, 28, 227, -401, 230, -508, 96, -238, +-177, 138, -309, 358, -183, 346, 82, 189, +286, -37, 309, -185, 90, -246, -223, -300, +-386, -330, -269, -115, 15, 409, 222, 794, +262, 522, 189, -261, 162, -826, 35, -745, +-202, -244, -412, 219, -310, 455, -44, 498, +241, 314, 278, -59, 203, -390, 177, -480, +124, -317, -140, -65, -447, 179, -479, 349, +-119, 322, 391, 47, 607, -266, 364, -338, +-185, -147, -567, 91, -495, 196, 17, 235, +521, 222, 535, 19, 71, -374, -443, -575, +-519, -243, -122, 405, 344, 770, 425, 510, +169, -71, -141, -492, -302, -511, -226, -221, +-17, 161, 128, 384, 161, 321, 111, 85, +-1, -86, -69, -93, -21, -17, 54, 48, +12, 51, -127, -63, -241, -223, -158, -200, +175, 176, 419, 582, 299, 495, -90, -142, +-369, -753, -335, -725, -23, -110, 225, 568, +184, 786, 31, 468, -53, -177, -58, -705, +-29, -727, -12, -203, -26, 426, 4, 597, +77, 215, 84, -281, -29, -398, -114, -154, +-110, 138, -6, 219, 127, 90, 146, -110, +48, -251, -38, -208, -67, 16, -127, 171, +-189, 70, -151, -132, 59, -103, 340, 185, +454, 370, 243, 186, -182, -226, -529, -508, +-555, -473, -247, -126, 216, 314, 522, 613, +511, 549, 209, 178, -167, -263, -383, -520, +-358, -476, -150, -171, 130, 262, 294, 524, +242, 436, -29, 53, -323, -283, -356, -312, +-22, -54, 419, 201, 568, 223, 265, 14, +-251, -207, -585, -173, -503, 98, -123, 352, +211, 291, 353, -78, 320, -407, 226, -387, +56, -49, -101, 310, -300, 408, -348, 222, +-223, -83, 45, -330, 256, -360, 324, -131, +232, 171, 19, 261, -198, 61, -311, -179, +-241, -177, -50, 13, 247, 154, 369, 103, +246, -40, -125, -188, -405, -250, -398, -149, +14, 100, 402, 304, 418, 203, 31, -107, +-389, -327, -409, -233, -34, 41, 412, 257, +452, 255, 81, 68, -357, -176, -482, -358, +-254, -326, 186, -59, 454, 348, 388, 621, +53, 505, -290, -8, -422, -571, -222, -735, +147, -380, 362, 179, 257, 504, -45, 479, +-243, 320, -203, 212, -3, 96, 120, -197, +72, -554, -8, -671, -18, -357, 48, 236, +114, 744, 74, 909, -78, 579, -256, -132, +-295, -856, -55, -1050, 314, -501, 489, 402, +281, 972, -191, 790, -482, 58, -366, -633, +3, -771, 282, -317, 263, 277, 38, 511, +-126, 290, -73, -46, 57, -199, 104, -203, +8, -203, -72, -150, -80, 39, -37, 233, +-62, 167, -117, -137, -60, -308, 186, -124, +335, 232, 220, 346, -83, 101, -307, -264, +-284, -415, -74, -257, 119, 41, 166, 254, +94, 248, -63, 72, -141, -124, -57, -122, +187, 53, 308, 219, 174, 172, -138, -113, +-359, -374, -370, -396, -202, -98, 30, 336, +281, 589, 456, 476, 406, 75, 133, -286, +-258, -405, -488, -302, -442, -118, -166, 82, +167, 274, 346, 351, 302, 265, 123, 52, +-21, -115, -22, -173, -19, -152, -150, -132, +-353, -115, -353, -7, 12, 207, 481, 443, +642, 430, 332, 36, -287, -511, -773, -798, +-685, -529, -56, 151, 646, 783, 905, 908, +469, 405, -313, -410, -872, -939, -783, -813, +-146, -176, 534, 440, 823, 577, 488, 292, +-120, -22, -539, -108, -474, -75, -161, -125, +156, -260, 234, -272, 168, -116, 64, 78, +-60, 198, -107, 270, -33, 279, 96, 98, +82, -260, -54, -556, -192, -434, -119, 68, +94, 565, 217, 640, 84, 218, -112, -321, +-191, -544, -77, -332, 111, 45, 248, 266, +174, 261, -81, 174, -298, 127, -276, 67, +22, -33, 267, -110, 267, -114, 22, -64, +-215, -38, -267, -12, -91, 31, 168, 137, +360, 259, 317, 295, -23, 177, -423, -129, +-534, -429, -238, -483, 198, -159, 467, 288, +425, 501, 136, 318, -164, -60, -293, -253, +-230, -184, -54, -29, 71, 0, 38, -122, +-55, -188, -48, -59, 70, 224, 240, 386, +289, 179, 88, -292, -250, -603, -470, -398, +-334, 154, 95, 563, 469, 450, 422, -49, +2, -500, -368, -566, -394, -203, -122, 271, +224, 495, 466, 294, 378, -109, -26, -346, +-481, -256, -651, 13, -281, 180, 309, 144, +615, -18, 410, -168, 5, -140, -250, 70, +-227, 323, -110, 364, -46, 76, -64, -306, +-111, -452, -25, -195, 150, 207, 292, 417, +265, 327, 74, 94, -150, -89, -259, -205, +-288, -193, -248, -49, -84, 186, 245, 305, +511, 156, 445, -148, 17, -353, -428, -192, +-548, 221, -262, 492, 176, 331, 397, -185, +322, -533, 7, -427, -231, 20, -214, 376, +10, 400, 123, 194, 31, -113, -108, -353, +-116, -456, 58, -274, 224, 111, 206, 442, +-33, 434, -297, 69, -375, -320, -124, -480, +321, -310, 548, 3, 310, 201, -223, 229, +-549, 82, -388, -77, 1, -148, 288, -89, +295, 41, 130, 77, 10, -13, -4, -166, +3, -154, -74, 42, -214, 244, -295, 217, +-149, -55, 157, -279, 380, -207, 331, 118, +76, 386, -100, 332, -196, 18, -229, -293, +-244, -376, -129, -194, 119, 133, 339, 392, +305, 382, 99, 192, -97, -28, -234, -120, +-239, -168, -118, -251, 68, -234, 158, -26, +103, 313, 24, 483, 31, 377, 126, 74, +113, -216, -117, -395, -338, -444, -353, -291, +-139, 32, 207, 418, 512, 630, 567, 455, +234, -26, -314, -585, -714, -808, -635, -492, +-168, 161, 399, 675, 668, 617, 538, 115, +95, -417, -405, -556, -562, -340, -331, -21, +88, 195, 336, 242, 320, 227, 155, 99, +5, -88, -212, -294, -373, -428, -310, -351, +7, -59, 393, 356, 473, 617, 243, 543, +-79, 138, -321, -426, -395, -810, -265, -776, +-32, -217, 205, 555, 312, 1021, 272, 880, +141, 210, -37, -526, -210, -937, -298, -795, +-233, -191, -6, 559, 185, 1002, 208, 814, +182, 157, 83, -547, -78, -817, -216, -551, +-205, 43, -41, 600, 124, 707, 129, 363, +39, -169, 46, -466, 59, -376, -3, -134, +-155, 81, -158, 231, 17, 400, 146, 403, +96, 45, -56, -491, -121, -735, -87, -386, +28, 203, 120, 573, 201, 525, 148, 226, +-58, -96, -257, -400, -257, -555, -115, -497, +16, -192, 115, 218, 251, 538, 344, 642, +192, 349, -184, -235, -514, -813, -455, -890, +-22, -335, 422, 406, 499, 819, 258, 608, +-130, 74, -377, -394, -328, -557, -143, -447, +3, -200, 95, 150, 291, 479, 458, 643, +368, 404, -160, -186, -693, -725, -708, -788, +-109, -202, 526, 573, 628, 971, 265, 696, +-213, -39, -386, -688, -235, -893, 70, -487, +242, 266, 180, 888, -52, 933, -177, 371, +-104, -336, 17, -785, -9, -732, -84, -331, +16, 255, 203, 776, 262, 885, 93, 453, +-103, -327, -191, -905, -170, -889, -193, -293, +-129, 486, 77, 902, 326, 719, 393, 54, +153, -580, -159, -752, -361, -487, -344, -59, +-143, 220, 194, 410, 350, 490, 267, 370, +24, -32, -153, -538, -195, -750, -192, -555, +-163, -73, -48, 385, 234, 656, 410, 637, +275, 253, -100, -335, -359, -826, -387, -830, +-188, -310, 86, 407, 312, 896, 392, 788, +242, 150, -103, -602, -419, -870, -441, -464, +-239, 198, 138, 581, 475, 477, 566, 204, +273, -31, -209, -185, -605, -323, -608, -319, +-213, -40, 284, 307, 601, 474, 528, 269, +153, -68, -304, -256, -507, -202, -376, -13, +-43, 79, 182, 102, 288, 152, 308, 237, +189, 186, -74, -149, -401, -539, -404, -554, +-85, 29, 287, 768, 356, 979, 164, 404, +-96, -551, -157, -1119, -143, -955, -111, -176, +16, 721, 113, 1186, 122, 905, 13, -28, +-111, -974, -100, -1267, 39, -681, 89, 321, +59, 983, -49, 895, -81, 159, -26, -585, +85, -819, 145, -458, 47, 128, -129, 453, +-235, 450, -182, 217, -7, -77, 220, -379, +257, -585, 193, -472, 62, 11, -105, 643, +-226, 936, -244, 657, -175, -100, -69, -902, +96, -1206, 240, -809, 333, 170, 249, 1119, +38, 1450, -244, 933, -412, -183, -369, -1194, +-115, -1490, 262, -783, 501, 431, 404, 1316, +-9, 1259, -373, 405, -434, -478, -170, -919, +105, -821, 223, -400, 204, 263, 155, 962, +77, 1169, -79, 548, -233, -612, -271, -1384, +-118, -1158, 70, -144, 216, 882, 220, 1282, +154, 954, 1, 114, -139, -777, -251, -1270, +-210, -1053, 34, -169, 277, 857, 308, 1398, +59, 1021, -258, -77, -424, -1202, -244, -1589, +111, -965, 407, 277, 480, 1410, 348, 1740, +-27, 1025, -486, -437, -764, -1824, -640, -2186, +-35, -1141, 706, 748, 1081, 2205, 767, 2204, +-56, 804, -903, -1017, -1210, -2080, -759, -1831, +202, -553, 1038, 921, 1215, 1759, 620, 1558, +-379, 471, -1132, -840, -1135, -1651, -419, -1448, +539, -293, 1134, 1084, 962, 1809, 267, 1360, +-502, 73, -963, -1219, -922, -1784, -449, -1326, +320, -80, 1016, 1328, 1224, 2077, 682, 1630, +-381, 103, -1381, -1610, -1549, -2385, -672, -1650, +733, 243, 1770, 2056, 1643, 2533, 394, 1275, +-1160, -856, -1909, -2327, -1387, -2119, -3, -521, +1271, 1231, 1677, 2026, 1016, 1522, -165, 188, +-1096, -1187, -1288, -1844, -766, -1376, 86, -80, +773, 1241, 1001, 1746, 751, 1170, 97, -78, +-586, -1251, -979, -1718, -811, -1236, -191, 15, +609, 1337, 1066, 1909, 918, 1263, 159, -272, +-791, -1720, -1263, -2090, -920, -1074, 81, 702, +994, 2034, 1274, 2010, 761, 653, -222, -1138, +-1089, -2176, -1241, -1777, -611, -173, 388, 1561, +1103, 2233, 1077, 1354, 407, -412, -417, -1795, +-917, -1871, -877, -720, -386, 786, 285, 1688, +792, 1476, 784, 367, 364, -919, -176, -1512, +-573, -1067, -649, 51, -439, 1031, -46, 1271, +378, 723, 653, -213, 596, -994, 187, -1188, +-381, -622, -748, 424, -635, 1291, -101, 1312, +495, 407, 686, -858, 415, -1590, -19, -1240, +-343, -7, -455, 1262, -419, 1623, -213, 845, +240, -481, 632, -1398, 615, -1346, 112, -422, +-436, 756, -644, 1395, -434, 1048, -31, -118, +304, -1259, 489, -1467, 451, -525, 190, 836, +-259, 1530, -570, 1105, -534, -63, -140, -1157, +363, -1525, 660, -927, 533, 287, 6, 1393, +-536, 1614, -753, 739, -452, -696, 105, -1699, +639, -1507, 821, -261, 536, 1196, -126, 1802, +-789, 1177, -1010, -254, -554, -1526, 291, -1773, +930, -875, 987, 666, 449, 1882, -344, 1947, +-961, 684, -1016, -1217, -380, -2394, 564, -1948, +1151, -47, 983, 1970, 107, 2668, -854, 1517, +-1309, -750, -919, -2530, 138, -2562, 1204, -745, +1528, 1637, 793, 2885, -483, 2070, -1486, -199, +-1513, -2321, -608, -2835, 662, -1435, 1558, 919, +1514, 2679, 506, 2685, -875, 942, -1698, -1491, +-1406, -3019, -204, -2627, 1103, -456, 1699, 2107, +1204, 3313, -79, 2246, -1343, -399, -1718, -2761, +-916, -3152, 528, -1388, 1575, 1188, 1529, 2798, +485, 2485, -854, 611, -1629, -1576, -1342, -2664, +-140, -1977, 1178, -7, 1709, 1940, 1046, 2531, +-268, 1443, -1374, -604, -1557, -2233, -773, -2361, +457, -930, 1414, 1204, 1497, 2559, 652, 2195, +-631, 253, -1512, -1911, -1481, -2698, -485, -1603, +833, 664, 1687, 2396, 1479, 2409, 221, 685, +-1210, -1433, -1823, -2297, -1165, -1470, 220, 227, +1328, 1440, 1524, 1554, 846, 809, -278, -253, +-1089, -1053, -1290, -1304, -755, -743, 147, 328, +887, 1222, 1081, 1256, 695, 352, 38, -670, +-638, -1151, -944, -816, -791, -73, -168, 559, +466, 825, 857, 611, 787, 147, 355, -380, +-256, -689, -794, -661, -954, -281, -573, 314, +175, 719, 802, 650, 1030, 110, 707, -460, +62, -606, -712, -385, -1193, 10, -1093, 238, +-228, 311, 953, 317, 1640, 282, 1222, 146, +-103, -289, -1444, -773, -1831, -905, -926, -322, +667, 753, 1856, 1535, 1753, 1388, 409, 133, +-1235, -1422, -2099, -2187, -1524, -1529, 106, 321, +1763, 2148, 2230, 2735, 1157, 1366, -814, -1157, +-2266, -3034, -2106, -2773, -333, -392, 1685, 2329, +2432, 3498, 1378, 2143, -734, -751, -2265, -3257, +-2121, -3592, -382, -1355, 1639, 1997, 2465, 4214, +1485, 3493, -589, 219, -2275, -3430, -2328, -4828, +-686, -2823, 1455, 1287, 2625, 4739, 1882, 4861, +-163, 1478, -2145, -3093, -2700, -5543, -1318, -4000, +1049, 305, 2753, 4473, 2577, 5480, 534, 2734, +-1912, -1916, -3134, -5371, -2131, -5109, 368, -1380, +2624, 3468, 3134, 5856, 1417, 4157, -1279, -399, +-3196, -4659, -2775, -5522, -425, -2698, 2307, 1964, +3404, 5148, 2085, 4691, -744, 1027, -3177, -3377, +-3379, -5178, -1181, -3366, 1992, 766, 3864, 4227, +3074, 4605, 39, 1867, -3086, -2229, -4152, -4579, +-2304, -3712, 1114, -224, 3803, 3373, 3909, 4367, +1254, 2313, -2221, -1431, -4127, -3810, -3035, -3302, +71, -462, 3042, 2479, 3771, 3331, 1879, 1855, +-1260, -917, -3448, -2771, -3120, -2566, -634, -503, +2296, 1894, 3465, 2824, 2146, 1786, -651, -698, +-2862, -2663, -2952, -2664, -1024, -623, 1528, 1917, +2982, 2909, 2269, 1826, -21, -649, -2281, -2512, +-2819, -2559, -1247, -720, 1154, 1677, 2644, 2675, +2096, 1733, 34, -666, -1948, -2420, -2368, -2303, +-1038, -382, 988, 1842, 2122, 2452, 1606, 1280, +37, -941, -1456, -2306, -1748, -2002, -911, -268, +525, 1749, 1583, 2364, 1545, 1344, 419, -846, +-1136, -2308, -1820, -2041, -1177, -289, 397, 1744, +1628, 2306, 1673, 1287, 509, -791, -951, -2167, +-1725, -1946, -1312, -350, -51, 1571, 1299, 2163, +1716, 1237, 950, -733, -437, -1914, -1473, -1476, +-1423, 117, -523, 1474, 748, 1291, 1333, 88, +1089, -1169, 186, -1171, -820, -125, -1232, 1052, +-839, 1390, 223, 559, 1071, -693, 1091, -1566, +311, -1255, -752, -2, -1124, 1349, -666, 1776, +255, 769, 832, -839, 806, -1796, 440, -1178, +-175, 425, -612, 1546, -899, 1318, -646, -79, +-4, -1299, 768, -1501, 1197, -445, 734, 937, +-176, 1649, -1034, 1144, -1201, -289, -596, -1568, +386, -1768, 1230, -541, 1231, 1155, 422, 1989, +-727, 1190, -1572, -578, -1357, -1959, -121, -1783, +1384, -121, 2014, 1769, 1248, 2334, -436, 952, +-1935, -1299, -2211, -2678, -981, -1967, 884, 239, +2284, 2370, 2231, 2814, 719, 1229, -1353, -1317, +-2585, -3061, -2029, -2570, -87, -176, 1965, 2460, +2552, 3249, 1358, 1583, -804, -1279, -2305, -3131, +-2047, -2492, -308, 2, 1538, 2480, 2144, 2916, +1135, 1114, -553, -1575, -1778, -2963, -1598, -1911, +-335, 664, 1116, 2675, 1670, 2467, 970, 387, +-390, -1967, -1413, -2770, -1252, -1486, -191, 998, +1009, 2849, 1314, 2510, 571, 136, -671, -2548, +-1418, -3261, -923, -1329, 452, 1809, 1605, 3599, +1364, 2511, -90, -568, -1628, -3301, -1839, -3475, +-593, -1058, 1220, 2254, 2076, 3871, 1394, 2555, +-354, -741, -1930, -3507, -2015, -3507, -614, -857, +1341, 2437, 2249, 3699, 1455, 2193, -422, -984, +-2017, -3343, -2112, -3206, -711, -707, 1248, 2415, +2441, 3673, 1917, 2260, -96, -999, -2142, -3463, +-2633, -3330, -1200, -636, 1136, 2541, 2600, 3595, +2128, 2021, 95, -1153, -1854, -3229, -2321, -2896, +-1135, -322, 827, 2516, 1996, 3290, 1623, 1597, +48, -1454, -1340, -3177, -1612, -2497, -702, 139, +693, 2577, 1471, 2932, 1079, 1187, -231, -1482, +-1274, -2835, -1310, -2137, -244, 222, 1088, 2367, +1599, 2694, 822, 997, -686, -1513, -1678, -2769, +-1537, -1954, -242, 368, 1314, 2284, 2027, 2473, +1344, 892, -354, -1197, -1746, -2268, -2093, -1779, +-923, -129, 842, 1374, 2087, 1918, 1828, 1135, +253, -285, -1401, -1420, -2092, -1490, -1139, -509, +511, 623, 1769, 1150, 1649, 789, 403, 59, +-1065, -512, -1804, -704, -1204, -553, 139, -182, +1464, 310, 1710, 682, 780, 644, -621, 137, +-1598, -467, -1354, -762, -379, -495, 839, -8, +1301, 488, 929, 592, 105, 372, -689, -45, +-849, -484, -607, -506, -25, -250, 370, 344, +503, 544, 379, 304, 98, -258, -114, -606, +-315, -334, -315, 205, -218, 717, 44, 600, +297, 54, 405, -647, 251, -896, -179, -490, +-490, 372, -465, 1085, -71, 1048, 449, 90, +618, -1037, 326, -1383, -261, -543, -577, 863, +-445, 1593, -81, 1057, 280, -527, 385, -1741, +332, -1591, 139, 16, -84, 1788, -309, 2184, +-495, 785, -366, -1510, -59, -2711, 461, -1774, +786, 810, 724, 2898, -2, 2670, -959, 215, +-1336, -2564, -693, -3305, 608, -1439, 1525, 1644, +1393, 3460, 195, 2556, -1163, -375, -1771, -3167, +-1171, -3490, 313, -1101, 1742, 2371, 2005, 4036, +669, 2419, -1324, -1249, -2354, -4078, -1595, -3468, +523, -145, 2210, 3462, 2325, 4177, 501, 1590, +-1641, -2349, -2618, -4520, -1598, -2928, 679, 906, +2425, 4281, 2466, 4039, 442, 735, -1742, -3287, +-2792, -4574, -1614, -2223, 719, 1734, 2602, 4259, +2517, 3259, 330, -67, -1960, -3203, -2916, -3503, +-1366, -1034, 1117, 2075, 2853, 3168, 2260, 1544, +-178, -1180, -2448, -2622, -2894, -1741, -898, 565, +1764, 2197, 3159, 1932, 1964, 84, -747, -1631, +-2865, -1881, -2823, -677, -608, 868, 1968, 1441, +3236, 850, 2031, -180, -658, -697, -2980, -461, +-3089, -85, -791, 2, 2108, -167, 3507, -156, +2057, 321, -906, 646, -3206, 512, -2881, -395, +-309, -972, 2430, -729, 3141, 341, 1205, 1109, +-1537, 704, -2942, -339, -1739, -1196, 878, -671, +2599, 408, 2012, 1280, -492, 661, -2537, -714, +-2281, -1575, 282, -821, 2703, 1063, 2691, 2100, +91, 1165, -2843, -1273, -3220, -2821, -701, -1700, +2644, 1187, 3652, 3361, 1599, 2300, -1901, -821, +-3873, -3381, -2648, -2722, 645, 333, 3442, 2856, +3533, 2692, 1116, 137, -2157, -1817, -3767, -1905, +-2836, -384, 105, 601, 2992, 677, 3928, 430, +2149, 516, -1451, 564, -4017, -242, -3774, -1239, +-452, -1396, 3195, 64, 4497, 1674, 2188, 1859, +-1826, 179, -4273, -1710, -3278, -2046, 149, -497, +3147, 1357, 3603, 1980, 1422, 865, -1514, -759, +-3061, -1578, -2433, -1062, -193, 128, 2056, 1057, +2863, 1111, 1362, 319, -1248, -787, -2732, -1257, +-1859, -583, 637, 774, 2409, 1474, 1929, 674, +-343, -919, -2046, -1734, -1692, -714, 237, 1032, +1758, 1826, 1514, 724, -255, -1094, -1839, -1912, +-1625, -1070, 303, 693, 2105, 1929, 1971, 1748, +18, 210, -2187, -1705, -2400, -2481, -545, -1380, +1958, 1006, 2547, 2761, 897, 2232, -1426, -141, +-2438, -2439, -1118, -2412, 947, -420, 2160, 1723, +1335, 2057, -404, 687, -1696, -840, -1673, -1407, +-409, -884, 1029, -11, 1908, 702, 1414, 1184, +-85, 974, -1707, 34, -2275, -1408, -1032, -1774, +1024, -461, 2514, 1566, 2094, 2181, 65, 487, +-2057, -1588, -2658, -2037, -1259, -202, 1142, 1594, +2688, 1724, 2125, 155, -283, -1362, -2503, -1570, +-2511, -757, -156, 739, 2493, 1845, 2747, 2033, +253, 153, -2678, -2527, -3052, -3549, -481, -1118, +2687, 3081, 3348, 4696, 1181, 2018, -2114, -2874, +-3499, -5104, -2164, -2989, 922, 1498, 3270, 4451, +3085, 3807, 517, 508, -2666, -3038, -3603, -4286, +-1701, -2352, 1771, 1411, 3687, 4113, 2434, 3351, +-900, -246, -3434, -3560, -2842, -3735, 215, -594, +3018, 2923, 3147, 3808, 424, 1336, -2547, -2247, +-3317, -3724, -1185, -2040, 1846, 1292, 3306, 3288, +2076, 2595, -1057, -47, -3123, -2489, -2696, -2943, +216, -1195, 2847, 1643, 3117, 3357, 510, 2304, +-2535, -912, -3280, -3668, -1281, -3014, 1904, 418, +3306, 3585, 2144, 3216, -877, 102, -3154, -2779, +-2856, -2857, -345, -463, 2675, 1722, 3337, 2316, +1389, 806, -1973, -899, -3494, -1768, -2079, -1108, +1173, 391, 3321, 1385, 2396, 1280, -447, 75, +-2864, -853, -2377, -1090, 113, -445, 2213, 88, +1919, 408, -46, 458, -1590, 476, -1297, 422, +120, -7, 1027, -629, 722, -1119, -125, -683, +-484, 393, -240, 1348, 85, 1158, 62, -133, +-195, -1279, -332, -1425, 67, -353, 664, 957, +903, 1490, 171, 927, -1033, -465, -1634, -1524, +-563, -1510, 1199, -183, 2179, 1303, 1009, 1715, +-1263, 675, -2357, -869, -1302, -1391, 1048, -786, +2266, 296, 1518, 790, -780, 670, -2016, 111, +-1485, -308, 376, -452, 1764, -164, 1373, 238, +-129, 281, -1462, 58, -1232, -283, -62, -154, +1163, 128, 1172, 415, 236, 189, -887, -157, +-1167, -447, -383, -416, 620, 122, 1087, 589, +498, 827, -318, 200, -847, -764, -476, -1061, +-37, -396, 368, 682, 336, 939, 395, 292, +302, -308, -170, -308, -660, 43, -843, -74, +-133, -419, 805, -407, 1186, 268, 479, 880, +-797, 478, -1344, -442, -694, -1014, 560, -480, +1293, 566, 855, 966, -232, 434, -1008, -497, +-777, -975, -139, -669, 485, 88, 533, 648, +503, 938, 107, 564, -388, -202, -703, -1103, +-460, -1350, 278, -303, 768, 1113, 601, 1863, +-290, 670, -746, -1057, -432, -2077, 270, -1088, +510, 865, 219, 2005, -108, 1560, -352, -281, +-100, -1739, 86, -1929, 172, -569, 85, 1243, +-38, 2189, -41, 1348, -82, -578, -25, -2031, +-201, -1772, -94, -28, 98, 1690, 565, 1965, +534, 581, -146, -1242, -859, -1964, -859, -944, +-16, 887, 882, 1845, 993, 1302, 236, -421, +-609, -1518, -970, -1408, -530, -217, 362, 1007, +939, 1372, 767, 907, -160, -209, -1013, -1235, +-894, -1503, 192, -582, 1026, 943, 816, 1803, +-302, 1172, -955, -585, -582, -1813, 304, -1493, +806, 107, 543, 1635, -226, 1535, -693, 241, +-506, -1314, -20, -1569, 384, -631, 515, 764, +260, 1398, 58, 1005, -229, -49, -422, -1125, +-638, -1300, -361, -796, 572, 549, 1251, 1373, +793, 1286, -498, 52, -1492, -1187, -1201, -1387, +162, -465, 1365, 783, 1403, 1171, 438, 735, +-874, -373, -1454, -981, -1111, -921, 210, 11, +1475, 969, 1541, 1232, 285, 287, -1286, -972, +-1598, -1485, -737, -538, 908, 1027, 1635, 1604, +1015, 808, -512, -769, -1585, -1502, -1271, -966, +105, 282, 1444, 1227, 1478, 1185, 335, 421, +-1122, -654, -1461, -1252, -861, -984, 409, 23, +1392, 1120, 1367, 1234, 269, 387, -1164, -673, +-1573, -1064, -616, -477, 790, 253, 1298, 625, +584, 476, -359, 10, -741, -278, -325, -488, +-35, -227, 79, 101, 192, 477, 324, 348, +292, -87, -136, -434, -292, -462, -444, 3, +15, 362, 128, 482, 262, 92, 215, -406, +106, -677, -33, -290, -297, 406, -273, 841, +-249, 546, 290, -246, 305, -869, 367, -795, +-58, -268, -414, 521, -353, 972, -97, 751, +433, 19, 302, -937, 93, -1016, -329, -344, +-165, 658, -74, 907, 103, 443, 99, -269, +3, -518, 177, -374, -68, -107, -133, 218, +-197, 439, 21, 400, 202, -113, 177, -509, +-28, -450, -43, 335, 19, 608, -181, 170, +-322, -621, -188, -556, 415, 352, 731, 1021, +279, 455, -565, -832, -822, -1238, -225, -375, +483, 1133, 562, 1224, 50, 203, -200, -1053, +-51, -907, 63, 81, -274, 737, -316, 342, +-47, -440, 692, -328, 660, 264, -59, 670, +-1000, 36, -1072, -797, -48, -725, 1166, 163, +1474, 771, 465, 543, -1000, -250, -1927, -424, +-886, -95, 743, 191, 1888, -83, 1199, -462, +-437, -356, -1577, 280, -1154, 868, 166, 558, +1096, -101, 973, -854, 73, -850, -626, -200, +-734, 439, -358, 784, 187, 349, 529, -108, +594, -291, 320, -25, -405, -23, -848, -383, +-679, -631, 351, -136, 1151, 1083, 796, 1459, +-470, 351, -1412, -1573, -672, -2230, 629, -505, +1450, 2073, 506, 2766, -607, 654, -1098, -2327, +-479, -3006, 232, -605, 428, 2355, 500, 2858, +446, 587, 344, -2118, -463, -2446, -1068, -466, +-1010, 1701, 234, 2135, 1459, 503, 1442, -1386, +67, -1974, -1422, -616, -1623, 1271, -390, 1966, +1101, 656, 1454, -1330, 661, -1875, -521, -531, +-957, 1361, -782, 1695, -311, 259, 236, -1349, +849, -1443, 1054, -193, 507, 1209, -647, 1330, +-1553, 308, -1079, -971, 276, -1507, 1397, -604, +1352, 737, 342, 1536, -760, 790, -1322, -573, +-979, -1329, 12, -797, 1161, 463, 1350, 1020, +393, 588, -981, -474, -1465, -1002, -463, -508, +1035, 470, 1338, 1197, 361, 838, -952, -306, +-1223, -1337, -439, -1270, 681, -177, 1095, 1051, +676, 1404, -337, 783, -883, -224, -788, -1051, +-82, -1124, 658, -670, 791, 363, 238, 1112, +-387, 1313, -495, 508, -321, -719, 8, -1571, +111, -1300, 197, 143, 311, 1582, 424, 1970, +213, 668, -453, -1266, -994, -2311, -754, -1465, +311, 589, 1317, 2212, 1184, 2076, 33, 416, +-1364, -1484, -1373, -2302, -165, -1417, 1107, 365, +1220, 1988, 239, 2137, -760, 775, -962, -1228, +-254, -2375, 421, -1651, 594, 307, 283, 2067, +-80, 2000, -196, 389, -256, -1304, -150, -1800, +-159, -822, 28, 286, 221, 961, 374, 926, +292, 648, 45, 199, -429, -654, -662, -1342, +-498, -1284, 130, -71, 1010, 1436, 1061, 1931, +256, 977, -1041, -885, -1473, -2105, -703, -1761, +741, -29, 1500, 1808, 1114, 2160, -161, 854, +-1265, -1099, -1385, -2058, -581, -1394, 869, 154, +1588, 1363, 1198, 1590, -306, 978, -1537, -115, +-1524, -1312, -350, -2011, 998, -1357, 1369, 538, +891, 2487, -117, 2660, -671, 717, -962, -1948, +-706, -3221, -292, -1975, 478, 629, 1027, 2679, +1100, 2772, 296, 976, -842, -1172, -1481, -2590, +-968, -2240, 358, -540, 1455, 1591, 1388, 2754, +172, 1939, -1210, -280, -1485, -2462, -677, -2700, +715, -879, 1394, 1616, 963, 2791, -75, 1733, +-874, -482, -953, -2211, -643, -2321, 51, -792, +624, 1117, 1128, 2327, 906, 1859, -102, 124, +-1343, -1698, -1541, -2218, -433, -1082, 1236, 647, +1757, 1700, 747, 1208, -871, 154, -1680, -673, +-997, -695, 459, -275, 1485, -152, 1214, -105, +10, -78, -1246, 324, -1468, 650, -420, 469, +846, -152, 1526, -793, 874, -608, -508, -17, +-1269, 616, -1104, 609, 115, 49, 1009, -260, +1017, -382, 60, -68, -669, -77, -719, -113, +-158, -121, 245, 312, 240, 716, 262, 693, +411, 46, 429, -965, -307, -1376, -1197, -949, +-1265, 359, 128, 1697, 1763, 2078, 2095, 977, +415, -1071, -1865, -2743, -2815, -2534, -1127, -264, +1587, 2549, 3197, 3665, 1935, 1976, -1119, -1530, +-3261, -3944, -2536, -3425, 466, -170, 2887, 3275, +2876, 4260, 350, 2019, -2133, -1727, -2840, -4152, +-1193, -3526, 1180, -139, 2537, 3091, 1734, 3954, +-388, 1696, -2062, -1627, -1800, -3245, 94, -2196, +1543, 228, 1424, 1815, -143, 1578, -1306, 382, +-950, -379, 451, -363, 1243, -160, 898, -380, +-477, -749, -1521, -730, -1367, 113, 109, 1072, +1697, 1581, 2195, 1085, 677, -379, -1624, -1842, +-2808, -2427, -1659, -1252, 1158, 1163, 2989, 3181, +2368, 3035, -374, 425, -2605, -2900, -2721, -4251, +-453, -2235, 1841, 1607, 2411, 4356, 1243, 3640, +-806, 268, -1667, -3235, -1562, -4027, -460, -2036, +688, 1234, 1455, 3347, 1379, 2977, 422, 939, +-977, -1707, -1857, -2808, -1177, -2318, 278, -335, +1726, 1636, 1658, 2625, 401, 2054, -1273, 77, +-1777, -2043, -918, -2989, 701, -1586, 1611, 1064, +1179, 3034, -180, 2495, -1220, -23, -1186, -2372, +-247, -2660, 659, -868, 957, 1314, 657, 2268, +-56, 1445, -584, -266, -854, -1650, -616, -1708, +95, -468, 790, 1089, 1053, 1721, 582, 941, +-405, -679, -1208, -1698, -1182, -1388, -296, 108, +1047, 1538, 1611, 1825, 976, 711, -487, -866, +-1719, -1974, -1627, -1707, -248, -386, 1377, 1368, +1919, 2416, 1231, 1793, -630, -208, -1843, -2348, +-1835, -2699, -466, -1048, 1203, 1442, 1887, 2611, +1322, 1922, -114, 25, -1216, -1597, -1611, -2191, +-1001, -1513, 44, 94, 1194, 1825, 1665, 2433, +1145, 1311, -204, -774, -1488, -2247, -1899, -2062, +-1115, -625, 438, 1019, 1825, 1939, 2196, 1782, +1188, 561, -945, -1021, -2486, -2003, -2472, -1581, +-478, -93, 1776, 1197, 2750, 1561, 1605, 928, +-329, 78, -1851, -634, -2133, -1046, -975, -1032, +407, -449, 1659, 315, 1757, 992, 761, 1206, +-536, 906, -1454, 134, -1435, -1152, -779, -2049, +285, -1707, 1301, 196, 1825, 2282, 1234, 2903, +-517, 1241, -2063, -1415, -2263, -2960, -732, -2498, +1472, -218, 2384, 1932, 1710, 2769, -246, 1743, +-1762, -266, -2038, -2133, -830, -2525, 717, -1316, +1710, 864, 1504, 2549, 180, 2290, -1057, 299, +-1576, -1980, -895, -2571, 470, -1040, 1416, 1222, +1112, 2136, -124, 1241, -1070, -447, -918, -1337, +71, -1016, 673, -142, 386, 406, -180, 607, +-250, 471, 263, 235, 357, -40, -110, -499, +-812, -598, -579, -521, 315, 201, 1128, 780, +929, 1008, -244, 271, -1230, -694, -1187, -1143, +-117, -699, 953, 240, 1269, 747, 507, 798, +-372, 484, -780, 294, -743, -231, -396, -993, +-24, -1609, 392, -1069, 875, 793, 982, 2643, +386, 2692, -680, 349, -1405, -2713, -1371, -3876, +-186, -1991, 1122, 1556, 1849, 3822, 1169, 3228, +-300, 397, -1460, -2307, -1474, -3214, -539, -2040, +447, -56, 863, 1787, 649, 2354, 546, 1760, +304, 357, -46, -1121, -704, -1795, -1150, -1878, +-1023, -1053, -102, 213, 1078, 1920, 1843, 2737, +1440, 1886, -91, -626, -1825, -2986, -2435, -3203, +-1269, -1134, 858, 1680, 2361, 3016, 2155, 2263, +690, 249, -1085, -1413, -2053, -2082, -1982, -1695, +-795, -701, 877, 606, 2330, 1864, 2372, 2260, +812, 1274, -1552, -751, -2881, -2413, -2188, -2399, +50, -764, 2256, 1221, 2503, 2063, 1259, 1598, +-767, 459, -1683, -590, -1557, -1196, -633, -1458, +136, -943, 668, 133, 1117, 1297, 1108, 1554, +770, 697, -324, -362, -1258, -1003, -1697, -759, +-1111, -438, 202, -57, 1487, 239, 1939, 556, +1310, 710, -245, 499, -1523, -31, -2070, -530, +-1250, -887, 21, -719, 1419, -236, 2045, 604, +1632, 1119, 275, 1015, -1514, 211, -2463, -875, +-2088, -1334, -39, -958, 2068, 119, 3002, 1021, +1637, 1140, -817, 442, -2635, -425, -2346, -750, +-494, -417, 1400, 110, 1939, 164, 1114, -104, +66, -247, -952, 130, -1088, 487, -916, 511, +-128, -2, 697, -422, 1007, -426, 765, -300, +-41, -29, -570, -13, -872, 205, -524, 480, +-104, 654, 495, 363, 768, -447, 566, -1238, +54, -1173, -381, -87, -574, 1311, -479, 1798, +-248, 920, 123, -671, 527, -1808, 734, -1596, +420, -381, -199, 1156, -770, 1800, -875, 1226, +-277, -181, 532, -1388, 998, -1467, 767, -382, +-160, 747, -910, 1100, -908, 379, -285, -444, +542, -504, 799, -37, 476, 546, 109, 321, +-496, -219, -569, -756, -487, -611, 134, 61, +483, 781, 515, 966, 109, 318, -350, -470, +-294, -932, -119, -612, 113, 49, 33, 416, +111, 437, 10, 202, 90, 111, 79, 129, +-43, -6, -147, -372, -326, -666, -173, -460, +142, 234, 580, 815, 449, 711, 6, -78, +-613, -584, -615, -572, -202, 54, 264, 412, +562, 229, 437, -174, 91, -405, -305, -199, +-532, 262, -330, 519, 215, 405, 457, 29, +228, -536, -245, -747, -408, -447, -95, 280, +315, 921, 482, 854, 218, 184, -152, -579, +-483, -885, -597, -756, -400, -261, 124, 366, +787, 973, 1055, 1298, 695, 802, -276, -387, +-1334, -1655, -1687, -2063, -773, -1047, 792, 871, +2107, 2376, 1924, 2526, 346, 1014, -1492, -1175, +-2314, -2873, -1604, -2911, 107, -1131, 1576, 1610, +2183, 3520, 1418, 3125, -162, 609, -1635, -2321, +-2109, -3587, -1230, -2423, 312, 73, 1598, 2259, +1900, 2776, 1050, 1681, -398, -229, -1577, -1742, +-1694, -2051, -631, -1165, 763, 324, 1494, 1263, +907, 1233, -235, 366, -833, -362, -602, -506, +208, -141, 537, 106, 280, -51, -397, -363, +-722, -522, -476, -122, 194, 440, 942, 877, +1039, 711, 604, 113, -483, -538, -1398, -1017, +-1506, -950, -676, -424, 818, 607, 1867, 1417, +1898, 1368, 558, 273, -1178, -1059, -2269, -1583, +-1972, -965, -331, 216, 1447, 915, 2402, 891, +1807, 455, 173, 156, -1518, 2, -2279, -275, +-1713, -831, -101, -1096, 1505, -613, 2144, 563, +1443, 1578, 48, 1556, -1275, 441, -1709, -959, +-1261, -1634, -365, -1323, 757, -346, 1462, 561, +1610, 1175, 770, 1374, -617, 1010, -1664, -6, +-1847, -1217, -696, -1871, 753, -1307, 1765, -39, +1624, 1155, 485, 1648, -871, 1394, -1603, 595, +-1386, -601, -295, -1683, 1011, -2033, 1598, -1107, +1173, 554, -146, 2007, -1403, 2182, -1607, 1076, +-557, -632, 726, -1840, 1551, -1969, 1171, -1005, +151, 504, -843, 1577, -1423, 1640, -1222, 712, +-184, -463, 1017, -1020, 1752, -939, 1311, -445, +-96, -65, -1411, 222, -1724, 489, -932, 681, +293, 707, 1277, 267, 1285, -389, 743, -1055, +-120, -1193, -781, -549, -881, 549, -721, 1473, +-414, 1583, 64, 605, 553, -807, 1123, -1892, +1213, -1705, 598, -460, -662, 1168, -1707, 1975, +-1861, 1571, -839, 285, 868, -1144, 2054, -1826, +2127, -1485, 858, -287, -804, 1073, -2079, 1749, +-2056, 1352, -1050, 259, 595, -933, 1737, -1489, +1971, -1325, 1174, -420, -125, 707, -1147, 1556, +-1719, 1495, -1518, 418, -799, -963, 523, -1707, +1856, -1219, 2403, -7, 1456, 1090, -589, 1297, +-2489, 735, -2749, -189, -1282, -878, 990, -884, +2571, -336, 2497, 257, 898, 484, -1121, 274, +-2338, 114, -2065, 88, -451, 76, 1127, -168, +1907, -371, 1342, -304, 196, -56, -846, 282, +-1292, 256, -993, 173, -217, 60, 688, -97, +1086, -151, 837, -171, -25, -63, -831, 81, +-1017, 121, -533, -48, 379, -65, 1053, 59, +1010, 284, 147, 284, -783, -129, -1287, -592, +-730, -604, 184, 2, 938, 722, 1085, 959, +563, 319, -54, -639, -728, -962, -935, -604, +-928, 228, -184, 686, 582, 605, 1288, 285, +1119, -86, 263, -455, -843, -568, -1433, -354, +-1089, 115, -29, 497, 988, 490, 1287, 202, +881, -35, -91, -296, -848, -489, -1153, -432, +-747, -145, 82, 386, 752, 687, 1020, 603, +564, 124, -53, -434, -650, -915, -750, -785, +-439, -117, 105, 705, 532, 1082, 438, 616, +141, -181, -245, -614, -215, -646, -75, -460, +155, -272, 210, 87, 24, 749, -251, 1102, +-405, 569, -251, -577, 197, -1372, 567, -1039, +601, 214, 76, 1209, -404, 1144, -659, 110, +-496, -950, 38, -1081, 417, -211, 593, 663, +286, 834, -246, 263, -443, -255, -121, -267, +289, -129, 349, -222, -94, -378, -545, -244, +-475, 237, -53, 621, 320, 627, 624, 409, +560, -4, 303, -543, -113, -1052, -726, -985, +-936, -234, -717, 896, -27, 1398, 750, 1099, +1324, 254, 1102, -715, 184, -1238, -952, -1343, +-1716, -692, -1249, 447, 29, 1440, 1334, 1550, +1653, 759, 913, -467, -455, -1297, -1203, -1279, +-1164, -613, -385, 284, 435, 786, 578, 555, +473, 223, 305, 233, 287, 528, 85, 420, +-339, -474, -768, -1471, -745, -1492, -234, -450, +382, 865, 781, 1688, 820, 1587, 469, 813, +-108, -401, -676, -1553, -989, -1978, -629, -1281, +-53, 129, 551, 1410, 732, 1885, 656, 1342, +410, 226, 39, -910, -507, -1576, -1099, -1326, +-1022, -420, -263, 568, 868, 993, 1377, 778, +955, 325, 77, 53, -691, 42, -902, -155, +-776, -464, -509, -848, -99, -761, 640, -120, +1225, 747, 1195, 1227, 259, 895, -917, -18, +-1426, -836, -1058, -913, -57, -446, 731, 241, +907, 523, 706, 337, 390, -119, -41, -380, +-512, -251, -949, 286, -898, 567, -226, 420, +655, -64, 1061, -497, 862, -612, 229, -422, +-342, -6, -749, 476, -1048, 714, -778, 297, +-31, -274, 1000, -543, 1477, -160, 1157, 376, +-205, 368, -1380, -193, -1663, -506, -890, -359, +574, 73, 1502, 299, 1408, 201, 382, 264, +-837, 426, -1375, 266, -896, -259, 12, -844, +883, -888, 1049, -327, 603, 445, -75, 871, +-683, 918, -927, 505, -827, -201, -186, -692, +597, -844, 1366, -480, 1265, -9, 239, 133, +-1004, 117, -1613, 182, -1114, 531, -51, 939, +834, 878, 1170, 52, 969, -1189, 478, -1968, +-302, -1598, -858, -85, -1139, 1552, -884, 2240, +-183, 1656, 609, 253, 1298, -1005, 1328, -1557, +612, -1394, -651, -881, -1563, -208, -1569, 493, +-442, 1229, 874, 1634, 1476, 1314, 1087, 317, +172, -980, -684, -1811, -873, -1765, -612, -960, +-251, 222, 216, 1301, 408, 1916, 502, 1777, +349, 709, -16, -921, -309, -2176, -239, -2161, +-106, -828, -17, 871, -88, 1842, -181, 1492, +89, 484, 347, -514, 268, -902, 84, -682, +-190, -300, -214, 113, -60, 277, -83, 185, +-72, -37, -1, -118, 102, 12, 225, 339, +157, 357, -87, 20, -265, -325, -123, -370, +61, -48, 297, 172, 178, 83, -182, -236, +-317, -286, -277, -64, 177, 376, 397, 657, +277, 462, -116, -36, -336, -586, -283, -799, +3, -474, 372, 68, 289, 519, 46, 674, +-327, 391, -393, -23, -134, -369, 261, -451, +412, -171, 233, 211, -59, 268, -311, 43, +-340, -316, -286, -362, 62, 26, 465, 399, +595, 484, 453, 234, -234, -93, -782, -379, +-987, -371, -457, -370, 404, -76, 1067, 234, +1166, 437, 548, 381, -380, 102, -1170, -244, +-1209, -343, -656, -121, 225, 106, 916, 287, +1073, 3, 695, -365, 171, -464, -464, -147, +-767, 424, -719, 779, -526, 623, -110, 42, +316, -601, 626, -984, 891, -826, 694, -121, +98, 711, -627, 1180, -1083, 911, -996, -20, +-263, -827, 505, -1011, 967, -470, 966, 160, +351, 367, -271, 220, -697, 126, -668, 334, +-315, 501, 63, 293, 187, -329, 314, -864, +371, -870, 200, -318, -28, 369, -220, 783, +-304, 778, -79, 440, 69, -45, 120, -445, +149, -568, 76, -374, -102, -50, -276, 30, +-364, -105, -120, -204, 325, 49, 617, 638, +554, 1039, 163, 770, -444, -119, -727, -1062, +-606, -1432, -161, -1004, 266, -169, 442, 632, +263, 1191, 293, 1327, 319, 896, 248, -21, +-98, -1007, -580, -1395, -739, -910, -580, -155, +-91, 325, 349, 377, 865, 402, 999, 660, +513, 864, -365, 502, -1219, -294, -1073, -1028, +-145, -1142, 804, -625, 965, 15, 238, 389, +-492, 519, -575, 655, -34, 749, 348, 678, +310, 44, -55, -840, -199, -1443, 21, -1188, +149, -191, -50, 899, -386, 1336, -428, 920, +-48, 173, 420, -471, 673, -572, 553, -335, +123, -137, -370, -231, -846, -461, -885, -346, +-417, 380, 467, 1153, 1039, 1166, 1016, 252, +331, -848, -405, -1316, -882, -796, -770, -1, +-301, 601, 192, 756, 475, 549, 438, 118, +255, -311, -38, -509, -53, -314, -39, 142, +64, 249, -99, 71, -331, -254, -577, -296, +-342, 45, 269, 387, 830, 462, 937, 253, +304, -100, -416, -493, -974, -612, -819, -527, +-278, -23, 426, 681, 769, 1057, 648, 763, +83, -230, -379, -1165, -434, -1252, -98, -298, +227, 778, 86, 1113, -254, 550, -459, -305, +-117, -585, 390, -401, 767, -86, 493, 180, +-113, 234, -641, 222, -623, -11, -271, -288, +112, -315, 235, 9, 118, 454, 198, 473, +334, 92, 476, -447, 147, -640, -366, -413, +-787, 90, -759, 606, -308, 842, 293, 581, +818, -216, 856, -989, 587, -1134, -5, -401, +-588, 693, -928, 1258, -803, 799, -452, -215, +180, -995, 873, -901, 1192, -46, 976, 771, +-10, 901, -1023, 317, -1489, -563, -902, -1018, +216, -722, 1090, 8, 1096, 843, 364, 1092, +-403, 642, -778, -232, -458, -896, 116, -927, +491, -226, 510, 486, 96, 702, -436, 292, +-699, -399, -517, -657, 3, -269, 606, 394, +858, 716, 591, 455, 54, -120, -434, -330, +-664, -102, -573, 20, -367, -248, -47, -828, +262, -883, 580, -24, 653, 1156, 456, 1725, +27, 1186, -435, -133, -647, -1263, -618, -1554, +-196, -1036, 279, -82, 559, 600, 444, 734, +105, 544, -272, 374, -342, 363, -190, 220, +59, -205, 240, -692, 295, -673, 160, -213, +-139, 242, -373, 277, -461, -87, -220, -249, +148, -18, 403, 435, 464, 653, 305, 449, +54, -37, -173, -455, -335, -551, -410, -375, +-322, -143, -58, -47, 188, -83, 417, 0, +325, 317, 97, 612, -115, 620, -168, 288, +-104, -190, -43, -478, -30, -536, -21, -480, +94, -398, 57, -199, -38, 109, -149, 586, +-139, 868, 10, 734, 221, 189, 217, -461, +112, -783, 26, -602, -123, -205, -171, 71, +-229, 191, -189, 180, -27, 135, 201, 158, +399, 158, 335, 243, 13, 227, -394, -62, +-486, -407, -249, -566, 203, -351, 447, -19, +296, 254, 45, 321, -83, 451, -91, 498, +-176, 189, -294, -365, -357, -861, -91, -756, +379, -141, 670, 561, 543, 818, 31, 619, +-532, 87, -740, -460, -521, -654, 7, -429, +514, 104, 664, 479, 435, 334, -48, -146, +-490, -452, -638, -303, -325, 220, 159, 636, +597, 561, 650, 17, 276, -547, -312, -763, +-737, -427, -697, 161, -232, 537, 466, 623, +821, 368, 613, -120, -45, -620, -586, -824, +-640, -401, -150, 546, 354, 1155, 433, 830, +104, -197, -288, -1052, -318, -1022, 70, -237, +428, 505, 371, 740, -187, 502, -702, -47, +-667, -396, 26, -386, 780, -61, 1014, 294, +407, 241, -429, -172, -885, -336, -684, -28, +-71, 397, 394, 445, 492, -101, 177, -643, +-47, -629, -158, -105, -40, 504, 156, 868, +161, 651, -51, 73, -298, -613, -404, -1047, +-157, -838, 204, -22, 485, 785, 371, 1184, +121, 799, -161, -102, -265, -852, -326, -1111, +-330, -740, -204, -24, 83, 657, 512, 1052, +605, 1028, 349, 427, -178, -586, -426, -1298, +-420, -1251, -170, -307, -52, 770, -117, 1129, +-67, 736, 134, 5, 497, -509, 574, -589, +412, -384, -131, 15, -555, 327, -765, 468, +-594, 285, -101, 32, 390, -213, 673, -485, +584, -645, 228, -559, -124, 136, -266, 1007, +-312, 1413, -301, 823, -234, -446, -113, -1412, +126, -1504, 346, -702, 326, 397, 121, 1065, +-46, 1128, -69, 701, 9, 121, 10, -372, +-220, -731, -417, -930, -352, -713, 39, -67, +529, 610, 701, 956, 429, 730, -132, 125, +-593, -336, -719, -551, -350, -438, 175, -37, +555, 212, 518, 114, 81, -246, -288, -529, +-303, -113, -9, 725, 228, 1140, 169, 723, +-194, -327, -404, -1219, -280, -1261, 70, -543, +454, 313, 543, 1003, 284, 999, -155, 449, +-496, -177, -562, -591, -201, -509, 251, -50, +453, 222, 314, 128, -59, -216, -348, -613, +-283, -407, -76, 315, 218, 905, 432, 953, +346, 283, 48, -482, -352, -674, -631, -440, +-442, -235, 147, -156, 559, -162, 500, -42, +-19, 314, -505, 559, -364, 707, 190, 690, +559, 110, 389, -705, -195, -1350, -608, -1170, +-477, -186, -80, 922, 318, 1309, 495, 930, +376, 202, 132, -568, -249, -923, -578, -903, +-547, -351, 13, 511, 501, 1055, 650, 807, +194, -85, -437, -963, -542, -1061, -100, -263, +398, 773, 466, 1181, 121, 693, -337, -269, +-464, -948, -264, -874, 21, -325, 227, 287, +337, 580, 250, 503, 62, 164, -186, -144, +-244, -277, -60, -163, 116, 60, 228, 113, +-25, 69, -293, 9, -415, -27, -183, -166, +184, -242, 571, -238, 692, 16, 326, 336, +-244, 337, -833, 201, -932, 41, -460, -19, +406, -35, 912, -133, 904, -295, 296, -336, +-416, -284, -729, -196, -529, 133, -73, 613, +323, 937, 407, 791, 164, -67, -59, -1062, +-240, -1462, -215, -999, -66, 138, 114, 1278, +229, 1570, 252, 868, 52, -317, -229, -1201, +-321, -1105, -195, -369, 201, 323, 442, 606, +290, 525, -133, 184, -468, -163, -464, -437, +-153, -436, 231, 65, 383, 536, 357, 573, +265, 155, 1, -414, -182, -629, -353, -391, +-313, 8, -96, 297, 81, 342, 123, 141, +62, -67, 72, 45, 91, 206, 183, 206, +80, -105, -30, -489, -119, -460, -208, -112, +-265, 161, -162, 236, 36, 315, 369, 363, +493, 298, 195, -117, -275, -615, -520, -580, +-311, -100, 91, 381, 404, 461, 222, 177, +-55, -221, -185, -311, -132, -167, 82, 135, +106, 486, 36, 379, -28, -106, -35, -554, +-83, -635, -51, -143, -26, 468, 62, 659, +189, 357, 103, -147, -94, -646, -206, -651, +-156, -139, 9, 439, 263, 823, 260, 562, +113, -72, -125, -506, -337, -609, -305, -419, +-62, -53, 214, 236, 265, 384, 181, 368, +-76, 81, -49, -180, 36, -174, 58, -102, +-1, 20, -166, 110, -225, 57, -71, 72, +130, 19, 141, -134, 138, -181, -57, -163, +-164, -78, -38, 108, 94, 258, 121, 222, +75, 60, -62, -199, -74, -204, 75, 91, +55, 297, -133, 150, -253, -163, -197, -335, +92, -189, 380, 41, 253, -49, -39, -156, +-290, -42, -219, 336, 89, 635, 295, 496, +187, -31, -86, -565, -315, -759, -269, -573, +37, -70, 218, 468, 244, 720, 91, 568, +-94, 81, -204, -405, -120, -586, -72, -363, +94, 21, 210, 382, 148, 392, 26, 57, +-184, -320, -216, -395, -82, -41, 201, 474, +278, 610, 135, 147, -166, -494, -437, -761, +-318, -423, 22, 295, 396, 655, 473, 459, +231, -25, -172, -411, -372, -353, -354, -115, +-123, 102, 161, 213, 368, 375, 336, 371, +50, 104, -347, -433, -543, -887, -236, -647, +290, 85, 617, 780, 431, 908, -126, 407, +-553, -226, -512, -501, -148, -424, 264, -164, +440, 61, 355, 64, 84, -10, -178, 10, +-359, 128, -238, 304, 64, 267, 244, -119, +232, -452, -84, -428, -330, -29, -279, 408, +14, 399, 280, 4, 372, -249, 215, -159, +-24, 183, -119, 283, -228, -44, -185, -508, +-98, -515, 29, -21, 92, 578, 35, 756, +-144, 248, -149, -366, 97, -640, 352, -405, +502, 37, 197, 301, -274, 282, -599, 212, +-551, 168, -195, 57, 323, -157, 551, -454, +415, -528, 49, -262, -353, 257, -417, 679, +-147, 770, 187, 380, 374, -252, 313, -718, +-61, -783, -341, -379, -450, 187, -318, 502, +125, 475, 435, 229, 445, -16, 239, -130, +-109, -122, -282, -104, -165, -27, -80, 21, +-91, -57, -115, -168, -142, -213, 65, -26, +370, 289, 412, 382, 218, 144, -156, -139, +-570, -221, -569, -61, -181, 146, 420, 71, +826, -67, 650, -188, -109, -205, -807, -135, +-981, 38, -412, 194, 483, 345, 939, 315, +713, 70, 28, -156, -645, -355, -752, -398, +-262, -237, 334, 104, 711, 441, 470, 570, +-172, 208, -651, -315, -634, -594, -213, -482, +370, -80, 606, 301, 454, 491, 171, 513, +-134, 329, -319, -125, -382, -535, -352, -681, +-158, -406, 206, 100, 407, 450, 364, 465, +35, 333, -304, 132, -314, -54, -59, -236, +281, -468, 360, -527, 163, -278, -182, 256, +-382, 779, -352, 912, -153, 380, 107, -454, +235, -1034, 311, -948, 293, -226, 161, 551, +-85, 844, -379, 526, -485, -21, -233, -385, +227, -237, 549, 139, 474, 306, -9, 47, +-480, -439, -641, -678, -336, -334, 209, 324, +609, 704, 619, 602, 235, 84, -308, -350, +-613, -393, -510, -159, -123, 98, 345, 176, +526, -21, 361, -254, 5, -206, -294, 51, +-401, 370, -239, 400, -30, 16, 162, -397, +308, -445, 315, -136, 148, 378, -117, 590, +-412, 264, -407, -263, -124, -640, 232, -549, +464, 34, 361, 548, 44, 604, -271, 236, +-413, -310, -364, -525, -42, -309, 294, 90, +480, 362, 391, 361, -47, 14, -467, -307, +-545, -309, -246, -81, 271, 261, 587, 298, +413, 64, 13, -133, -370, -163, -471, -164, +-243, -131, 138, -54, 368, 182, 356, 458, +13, 370, -413, -94, -440, -473, -118, -432, +402, -74, 615, 219, 268, 123, -300, -64, +-490, -10, -247, 262, 149, 430, 272, 199, +-65, -379, -316, -807, -137, -602, 273, 138, +517, 909, 316, 1031, -195, 320, -481, -654, +-417, -1132, -162, -853, 124, 21, 342, 836, +431, 1100, 344, 685, -34, -173, -511, -918, +-663, -981, -351, -349, 213, 389, 656, 741, +649, 476, 284, 8, -175, -233, -588, -245, +-751, -173, -502, -95, 93, -43, 778, 37, +1028, 190, 534, 243, -350, 149, -948, -63, +-905, -350, -241, -398, 492, -85, 789, 306, +618, 541, 115, 393, -451, -41, -748, -418, +-589, -567, -89, -483, 574, -82, 868, 403, +606, 672, -6, 594, -619, 169, -836, -276, +-551, -495, -13, -523, 451, -467, 680, -129, +484, 324, 92, 671, -261, 680, -459, 164, +-358, -343, -101, -523, 73, -413, 140, -158, +144, 76, 128, 215, 211, 359, 192, 403, +-2, 174, -253, -197, -435, -567, -371, -721, +-40, -327, 324, 384, 458, 943, 374, 941, +23, 267, -271, -592, -330, -989, -203, -843, +-6, -323, 132, 348, 105, 816, 29, 910, +26, 496, 23, -264, 39, -784, 31, -692, +-25, -226, -78, 209, -87, 352, -75, 242, +-32, 148, 45, 69, 129, -60, 183, -117, +151, -92, -35, -100, -273, -150, -356, -147, +-150, 40, 228, 382, 513, 511, 367, 191, +-133, -318, -587, -662, -603, -565, -58, -70, +576, 496, 793, 738, 314, 514, -397, -99, +-807, -664, -516, -642, 182, -143, 590, 421, +453, 581, -65, 209, -350, -305, -184, -497, +176, -290, 223, 138, -60, 509, -381, 476, +-335, 109, 93, -307, 478, -540, 507, -385, +161, 34, -330, 287, -602, 296, -453, 122, +-22, -61, 493, 19, 682, 164, 345, 101, +-268, -140, -666, -413, -548, -452, 38, -93, +520, 287, 487, 423, 94, 378, -295, 186, +-341, -18, -64, -207, 176, -469, 188, -519, +49, -136, -123, 354, -198, 663, -125, 484, +41, -93, 235, -538, 326, -525, 131, -220, +-241, 216, -503, 447, -401, 307, 120, 110, +601, -90, 634, -231, 193, -223, -419, -174, +-718, -45, -524, 228, -19, 298, 424, 89, +580, -226, 371, -380, -23, -152, -310, 319, +-346, 508, -122, 278, 158, -73, 195, -410, +-17, -411, -282, -221, -294, -24, 29, 198, +408, 313, 491, 240, 163, 96, -289, -30, +-489, -140, -266, -139, 156, -167, 407, -173, +237, -16, -156, 177, -409, 264, -314, 233, +93, 26, 454, -192, 436, -295, 105, -327, +-287, -192, -457, 121, -252, 441, 83, 570, +272, 395, 257, -91, 80, -540, -122, -689, +-169, -518, -150, -95, -90, 385, 81, 660, +213, 721, 263, 422, 189, -163, -96, -685, +-367, -874, -413, -549, -268, 25, 88, 546, +415, 690, 498, 572, 357, 256, 33, -184, +-371, -502, -538, -636, -403, -458, -85, -84, +355, 263, 498, 438, 300, 526, -4, 429, +-292, 141, -359, -284, -159, -657, 18, -675, +115, -273, 182, 254, 101, 601, 106, 643, +149, 334, 78, -91, -86, -439, -324, -590, +-531, -443, -359, -75, 144, 228, 603, 477, +750, 549, 359, 377, -294, 34, -637, -422, +-522, -744, -128, -580, 307, -51, 357, 449, +158, 650, -50, 366, -201, -3, -114, -204, +90, -240, 172, -227, 95, -168, -81, -57, +-278, 129, -213, 311, 74, 238, 306, 72, +374, -115, 136, -321, -266, -415, -455, -315, +-336, 67, 1, 659, 367, 877, 410, 434, +141, -398, -131, -992, -234, -845, -105, -130, +120, 538, 106, 697, -110, 423, -293, -51, +-251, -332, 20, -318, 379, -142, 501, 120, +314, 304, -1, 297, -363, 93, -567, -306, +-485, -658, -141, -574, 298, -2, 653, 730, +558, 1017, 113, 572, -369, -285, -599, -899, +-369, -898, 107, -336, 434, 369, 377, 768, +79, 689, -341, 156, -432, -452, -135, -708, +231, -450, 476, 105, 344, 542, -106, 549, +-431, 174, -445, -298, -209, -537, 210, -338, +451, 119, 376, 425, 146, 297, -161, -105, +-336, -312, -236, -36, -98, 297, 0, 259, +69, -203, 66, -624, 117, -464, 214, 150, +127, 708, -24, 769, -139, 313, -221, -356, +-134, -753, -15, -652, 16, -154, 118, 397, +192, 565, 138, 269, 25, -129, -206, -339, +-353, -214, -159, 128, 195, 381, 440, 415, +405, 95, -24, -436, -502, -784, -581, -587, +-269, 81, 298, 757, 679, 928, 505, 450, +-10, -274, -477, -781, -597, -791, -235, -290, +233, 403, 394, 838, 300, 730, 19, 98, +-193, -618, -185, -913, -105, -638, -56, 8, +50, 627, 143, 879, 178, 640, 176, 94, +-39, -478, -305, -774, -377, -643, -190, -235, +200, 254, 551, 575, 472, 576, 14, 301, +-467, -77, -640, -314, -310, -396, 260, -305, +584, -149, 470, 70, 76, 341, -353, 418, +-487, 214, -310, -153, -3, -396, 290, -304, +402, 29, 236, 260, -38, 252, -271, 71, +-308, -179, -89, -273, 168, -162, 252, 61, +125, 279, -96, 293, -245, 62, -158, -129, +4, -179, 142, -152, 193, -123, 145, -154, +19, -88, -98, 223, -183, 525, -153, 494, +5, 112, 93, -495, 78, -863, -9, -658, +-28, -68, 119, 657, 275, 1057, 167, 797, +-210, 52, -606, -774, -605, -1189, -20, -838, +737, 77, 1016, 882, 520, 1068, -426, 550, +-1104, -259, -902, -653, -86, -532, 703, -208, +901, 63, 460, 103, -154, 118, -516, 275, +-515, 325, -274, 173, 52, -134, 285, -413, +390, -395, 282, -98, -10, 194, -273, 307, +-308, 225, -149, 4, 78, -129, 198, -128, +128, -96, 50, -10, -2, 88, -78, 121, +-123, 116, -122, 1, -50, -171, 106, -211, +161, -125, 59, 7, -56, 154, -79, 220, +-8, 214, 101, 163, 85, -42, -18, -269, +-68, -310, -119, -132, -153, 50, -121, 74, +-32, -89, 156, -113, 392, 192, 354, 534, +67, 542, -302, 115, -555, -496, -403, -847, +29, -700, 398, -228, 487, 423, 324, 901, +-54, 899, -301, 378, -376, -378, -336, -908, +-112, -811, 179, -235, 396, 328, 454, 583, +241, 456, -149, 115, -412, -124, -445, -213, +-232, -223, 110, -107, 294, -7, 297, 82, +188, 154, -17, 71, -102, -103, -93, -167, +-103, -80, -120, 113, -121, 264, -120, 144, +55, -72, 287, -153, 318, -150, 166, -61, +-148, 21, -370, -5, -263, 8, 14, 43, +192, 30, 219, 109, 43, 176, -101, 97, +-90, -92, -79, -308, -18, -360, 65, -41, +132, 329, 126, 413, 46, 217, -187, -206, +-270, -470, -120, -307, 98, 67, 272, 394, +235, 468, 19, 143, -148, -233, -188, -385, +-152, -368, -15, -154, 57, 170, 61, 387, +112, 467, 113, 245, 22, -290, -83, -623, +-166, -523, -112, -8, 140, 585, 255, 772, +126, 322, -160, -313, -355, -770, -257, -691, +88, -47, 293, 560, 254, 704, 94, 341, +-78, -241, -98, -528, -102, -276, -168, 106, +-159, 349, 63, 262, 282, -130, 320, -431, +30, -376, -405, -29, -478, 446, -72, 658, +426, 319, 600, -223, 255, -637, -317, -660, +-597, -199, -429, 401, 31, 730, 440, 653, +463, 103, 168, -600, -175, -872, -376, -591, +-234, 58, 72, 705, 218, 864, 129, 496, +-13, -69, -135, -605, -96, -753, 44, -428, +79, 46, 96, 423, 51, 542, -55, 313, +-166, -7, -179, -221, -82, -345, 162, -239, +305, -1, 218, 138, 12, 231, -258, 236, +-314, 81, -122, -98, 116, -307, 201, -429, +144, -159, -48, 246, -162, 481, -92, 432, +34, 103, 171, -248, 232, -325, 87, -331, +-156, -289, -335, -73, -321, 166, -8, 409, +349, 530, 434, 304, 204, -103, -170, -432, +-449, -640, -366, -441, -23, 48, 284, 451, +422, 606, 259, 405, -73, -81, -291, -381, +-295, -414, -146, -273, 54, 68, 129, 290, +125, 282, 140, 159, 116, -54, 32, -242, +-113, -221, -277, -163, -278, -37, 6, 230, +289, 376, 404, 298, 214, 43, -198, -341, +-470, -476, -323, -238, 20, 23, 324, 214, +390, 249, 139, 145, -106, 127, -234, 147, +-222, -28, -83, -240, 66, -391, 143, -343, +141, 45, 35, 418, -91, 422, -63, 183, +-11, -159, 28, -358, 51, -241, 3, -75, +-15, 59, 37, 280, 23, 355, -97, 203, +-179, -134, -159, -549, 54, -600, 372, -123, +435, 448, 169, 752, -313, 587, -637, -54, +-502, -618, 20, -751, 497, -461, 633, 142, +356, 623, -136, 604, -391, 269, -354, -160, +-137, -442, 59, -353, 74, -114, -20, 27, +-10, 140, 104, 145, 209, 101, 215, 171, +58, 135, -137, -25, -218, -185, -202, -328, +-138, -309, 6, -32, 89, 220, 129, 404, +146, 450, 121, 190, 74, -191, 23, -505, +-123, -626, -279, -366, -223, 169, -71, 561, +189, 727, 289, 532, 184, -5, 15, -513, +-98, -774, -154, -670, -163, -131, -118, 427, +-32, 641, 226, 541, 374, 195, 209, -165, +-170, -309, -546, -349, -541, -296, -14, -72, +608, 117, 761, 225, 386, 225, -334, 41, +-797, -137, -613, -108, -47, 19, 500, 193, +617, 233, 245, -48, -228, -349, -384, -391, +-198, -163, 137, 256, 257, 461, 5, 259, +-255, -58, -247, -244, 19, -222, 354, 7, +409, 139, 99, 41, -247, -89, -403, -173, +-313, -113, -7, 104, 263, 220, 339, 169, +259, 119, 35, 5, -235, -92, -334, -192, +-270, -322, -63, -282, 223, 18, 333, 318, +226, 476, 54, 372, -94, -16, -131, -346, +-100, -444, -179, -304, -250, 48, -140, 337, +128, 307, 441, 134, 488, -88, 124, -228, +-351, -212, -569, -135, -371, 5, 143, 279, +556, 421, 467, 232, 59, -134, -376, -491, +-581, -485, -315, -120, 118, 244, 432, 387, +527, 340, 320, 116, -95, -81, -432, -188, +-590, -281, -457, -259, 12, -111, 455, 98, +732, 362, 607, 463, 79, 193, -499, -218, +-777, -517, -625, -501, -123, -134, 430, 247, +593, 425, 482, 446, 200, 274, -130, -47, +-295, -346, -368, -510, -365, -414, -186, -54, +118, 280, 378, 444, 494, 401, 295, 106, +-80, -225, -352, -340, -447, -261, -292, -25, +11, 141, 248, 132, 371, 117, 347, 147, +85, 45, -215, -165, -386, -336, -338, -297, +-78, 44, 196, 383, 286, 433, 273, 240, +188, -73, 33, -378, -172, -437, -408, -266, +-486, 74, -212, 380, 319, 361, 654, 99, +575, -127, 59, -179, -531, -96, -673, 40, +-371, 26, 147, -20, 491, -48, 499, -46, +191, 31, -138, 131, -336, 79, -323, -50, +-135, -116, 20, -52, 136, 132, 143, 167, +137, -44, 141, -252, 95, -233, -84, -11, +-277, 284, -258, 341, -81, 123, 225, -189, +354, -370, 182, -253, -121, 140, -272, 386, +-192, 263, -14, -109, 104, -429, 29, -378, +-53, -10, 7, 359, 223, 524, 351, 408, +178, -32, -244, -513, -612, -677, -577, -391, +-93, 217, 504, 617, 729, 484, 449, 50, +-84, -285, -444, -325, -447, -105, -189, 104, +64, 153, 107, 104, 85, -18, 87, -143, +119, -156, 127, -92, 50, 21, -93, 168, +-170, 234, -170, 171, -103, -30, 58, -259, +201, -271, 253, -11, 126, 238, -184, 219, +-408, -35, -303, -289, 56, -229, 390, 54, +472, 274, 169, 282, -232, 122, -412, -122, +-359, -257, -85, -219, 215, -46, 344, 157, +303, 198, 88, 38, -211, -144, -348, -165, +-262, -25, -47, 203, 224, 280, 262, 137, +105, -153, 5, -368, -33, -316, -34, 22, +-66, 320, -207, 328, -267, 80, -18, -190, +306, -226, 444, -72, 279, 87, -175, 147, +-482, 125, -436, -3, -111, -159, 284, -228, +459, -128, 271, 89, -29, 236, -239, 202, +-299, 80, -97, 10, 113, -51, 135, -132, +88, -254, -11, -294, -106, -132, -53, 191, +14, 472, 21, 532, 72, 247, 61, -257, +-3, -645, -39, -618, -93, -181, -54, 358, +99, 583, 151, 386, 37, 28, -157, -236, +-284, -283, -102, -171, 295, -27, 419, 88, +190, 133, -207, 79, -508, -31, -324, -83, +132, -63, 400, 21, 360, 96, 47, 64, +-321, -14, -358, -51, -103, -1, 176, 84, +389, 61, 270, -153, -66, -317, -297, -194, +-346, 192, -169, 514, 138, 427, 283, -55, +202, -501, 83, -531, -85, -186, -131, 266, +-45, 488, -34, 376, -26, 60, 20, -282, +1, -469, -2, -362, 32, -53, -15, 288, +35, 486, 96, 411, 14, 104, -39, -250, +-86, -470, -105, -424, 16, -120, 106, 181, +26, 295, -25, 212, -69, 61, -63, 0, +93, 82, 135, 120, 41, 15, -61, -225, +-155, -465, -136, -420, 44, -34, 134, 431, +88, 649, -4, 425, -170, -87, -173, -436, +20, -422, 168, -180, 248, 67, 196, 170, +-78, 149, -271, 115, -286, 10, -233, -152, +-15, -190, 181, -38, 233, 212, 270, 346, +195, 150, -24, -220, -195, -392, -313, -266, +-331, 44, -120, 253, 85, 152, 238, -41, +371, -49, 272, 130, 15, 282, -245, 149, +-447, -273, -377, -560, 28, -433, 379, 14, +514, 501, 321, 660, -219, 378, -606, -121, +-564, -551, -175, -659, 429, -304, 798, 233, +587, 585, 32, 546, -577, 133, -883, -311, +-568, -455, 89, -297, 632, -23, 809, 176, +451, 136, -159, 39, -531, 64, -562, 191, +-275, 259, 164, 88, 367, -294, 308, -549, +124, -437, -120, -80, -206, 330, -76, 567, +38, 548, 108, 310, 113, -137, -24, -647, +-114, -814, -86, -460, -54, 240, 62, 812, +157, 791, 110, 220, 56, -422, 17, -704, +-52, -493, -70, 10, -96, 362, -126, 407, +2, 268, 169, 77, 243, -86, 205, -228, +-21, -375, -263, -347, -277, -55, -127, 290, +93, 460, 321, 331, 318, 39, 125, -153, +-96, -187, -340, -202, -374, -221, -125, -210, +195, -101, 451, 188, 446, 465, 92, 491, +-316, 218, -495, -262, -382, -619, 11, -512, +385, -57, 427, 384, 238, 509, -96, 214, +-325, -208, -266, -375, -19, -221, 159, 134, +196, 396, 50, 273, -128, -89, -96, -366, +-15, -352, 19, -87, -4, 167, -80, 220, +-43, 226, 135, 243, 207, 111, 89, -180, +-108, -485, -302, -477, -267, -33, -34, 463, +145, 570, 211, 281, 161, -161, 9, -428, +-75, -373, -111, -154, -152, 87, -118, 281, +-42, 305, 35, 192, 104, 53, 80, -131, +-33, -276, -72, -340, -34, -281, 25, -19, +85, 348, -6, 537, -166, 431, -178, 57, +-64, -389, 126, -582, 219, -442, 56, -103, +-202, 268, -264, 453, -81, 400, 203, 228, +324, -54, 92, -345, -225, -436, -331, -269, +-179, 69, 104, 323, 218, 256, 73, -13, +-92, -155, -97, -81, 21, 121, 163, 231, +119, 117, -116, -117, -269, -316, -241, -369, +-42, -151, 213, 239, 290, 479, 175, 394, +18, 33, -112, -315, -145, -356, -113, -153, +-124, 46, -135, 142, -31, 102, 153, 1, +337, -24, 367, 13, 116, 72, -219, 98, +-409, -22, -330, -202, -33, -198, 245, -10, +322, 221, 238, 294, 68, 92, -99, -191, +-178, -310, -172, -221, -75, 28, 107, 275, +237, 291, 206, 115, 60, -109, -134, -241, +-194, -171, -63, -8, 115, 76, 185, 106, +118, 76, -31, -12, -84, -63, 7, -65, +92, -14, 70, 87, -74, 92, -175, 3, +-76, -50, 199, -84, 385, -82, 292, -32, +-52, 41, -401, 134, -435, 165, -175, 7, +181, -204, 427, -223, 418, -38, 219, 241, +-69, 342, -335, 101, -433, -248, -288, -412, +52, -287, 364, 101, 464, 417, 265, 386, +-54, 114, -274, -182, -332, -290, -219, -184, +-68, -68, 107, -23, 257, 77, 301, 185, +170, 185, -76, 50, -270, -130, -302, -138, +-143, 50, 26, 124, 120, -20, 163, -210, +176, -248, 121, -17, -51, 255, -288, 300, +-373, 161, -170, -24, 196, -176, 406, -216, +264, -192, -128, -119, -416, 64, -345, 238, +-41, 274, 249, 156, 270, -63, 69, -231, +-134, -189, -205, -49, -140, 37, -38, 59, +13, 23, 4, 28, -19, 76, -35, 41, +-21, -37, 37, -38, 94, 22, 88, 77, +5, 39, -184, -105, -311, -208, -253, -178, +-43, -57, 212, 138, 325, 327, 211, 367, +0, 211, -150, -119, -230, -437, -230, -515, +-207, -322, -135, 16, 78, 383, 343, 587, +441, 494, 250, 126, -168, -373, -501, -666, +-462, -508, -151, -39, 166, 381, 292, 492, +216, 264, 118, -30, 130, -174, 75, -180, +-108, -143, -332, -111, -408, -76, -160, 55, +262, 250, 512, 279, 402, 113, 25, -144, +-365, -305, -431, -222, -163, -35, 199, 102, +410, 177, 298, 193, -59, 124, -317, -47, +-259, -251, 46, -278, 375, -22, 370, 273, +3, 296, -350, 33, -389, -277, -51, -307, +398, -35, 518, 222, 211, 260, -223, 105, +-451, -97, -308, -153, 91, -88, 390, -15, +403, 23, 221, 22, -83, -8, -267, -4, +-262, 15, -170, 29, 24, 73, 228, 78, +339, 0, 333, -101, 156, -129, -184, -24, +-424, 116, -386, 81, -119, -116, 284, -234, +511, -92, 396, 249, 116, 460, -206, 282, +-376, -133, -314, -452, -146, -480, 43, -230, +251, 110, 339, 367, 253, 465, 97, 331, +-161, 0, -313, -329, -237, -453, -104, -295, +61, 23, 170, 255, 141, 261, 100, 110, +63, -24, -42, -32, -123, 43, -165, 16, +-190, -142, -63, -272, 126, -192, 202, 105, +192, 360, 5, 332, -241, 57, -265, -235, +-107, -342, 80, -208, 195, 30, 88, 221, +-132, 287, -185, 162, -123, -95, 8, -301, +138, -289, 97, -50, -14, 257, -68, 371, +-129, 210, -137, -89, -75, -338, -65, -355, +12, -148, 124, 125, 125, 312, 65, 324, +-49, 141, -217, -110, -245, -285, -124, -287, +5, -83, 163, 147, 213, 201, 97, 81, +-32, -51, -152, -43, -249, 78, -174, 91, +-48, -62, 63, -195, 203, -157, 179, 22, +23, 181, -107, 182, -201, 101, -162, 25, +36, -85, 118, -219, 72, -288, 4, -176, +-116, 154, -94, 471, 75, 471, 161, 113, +152, -381, 24, -654, -210, -427, -267, 134, +-109, 590, 88, 597, 267, 135, 269, -403, +55, -569, -89, -310, -137, 110, -137, 405, +-2, 393, 73, 171, 64, -87, 86, -291, +46, -343, -24, -211, -8, 5, 17, 214, +39, 320, 119, 234, 65, 59, -46, -112, +-66, -220, -69, -208, 37, -111, 159, 6, +107, 117, 14, 150, -22, 73, -43, -8, +37, -40, 137, -11, 71, 43, -29, 22, +-119, -45, -179, -50, 0, -38, 271, -62, +374, -97, 285, -53, -63, 122, -437, 298, +-480, 238, -208, -62, 210, -310, 573, -303, +551, -66, 179, 147, -210, 168, -492, 103, +-452, 71, -96, 31, 208, -60, 338, -175, +288, -215, 71, -64, -68, 172, -54, 297, +-68, 237, -106, 18, -153, -252, -189, -377, +-11, -284, 243, -8, 318, 319, 228, 444, +-17, 276, -277, -53, -323, -330, -218, -379, +-70, -173, 162, 72, 296, 213, 236, 216, +68, 105, -200, -8, -351, -88, -217, -151, +16, -138, 193, -22, 230, 121, 50, 219, +-150, 172, -229, -32, -209, -258, -55, -344, +149, -215, 223, 121, 172, 434, 0, 460, +-217, 173, -303, -239, -212, -471, -75, -352, +62, -58, 145, 156, 151, 204, 178, 138, +127, 101, -53, 134, -275, 116, -411, -26, +-347, -232, -59, -382, 254, -295, 382, 27, +330, 337, 96, 447, -182, 277, -341, -41, +-337, -268, -207, -310, 21, -228, 173, -62, +220, 108, 229, 218, 134, 240, -33, 128, +-214, -62, -336, -170, -276, -164, 8, -72, +259, 44, 322, 85, 174, 55, -94, 6, +-208, -30, -122, -13, -4, 28, 56, 14, +37, -29, -8, -30, 33, 48, 83, 146, +16, 106, -79, -119, -97, -338, 2, -319, +183, -1, 206, 418, 27, 564, -158, 283, +-204, -221, -57, -565, 155, -500, 236, -94, +119, 328, -33, 453, -118, 250, -77, -97, +63, -290, 114, -200, 42, 50, -51, 216, +-86, 136, 15, -96, 206, -237, 258, -133, +124, 93, -103, 213, -302, 134, -276, -39, +-26, -127, 235, -79, 355, -1, 283, 33, +64, 28, -102, 30, -159, 28, -173, -8, +-128, -68, -29, -80, 75, -6, 193, 72, +229, 81, 135, 10, 45, -42, -32, 9, +-118, 83, -157, 56, -168, -87, -99, -234, +100, -198, 258, 23, 253, 252, 118, 302, +-101, 139, -216, -88, -142, -213, -17, -172, +43, -49, 42, 41, -8, 50, 4, -9, +96, -40, 107, 2, 11, 106, -112, 201, +-196, 151, -138, -48, 37, -268, 155, -329, +172, -145, 83, 157, -112, 319, -220, 211, +-168, -39, -52, -212, 107, -152, 158, 57, +37, 189, -51, 142, -108, -34, -135, -215, +-69, -245, -18, -117, 53, 90, 139, 274, +95, 297, -94, 124, -257, -122, -281, -263, +-91, -229, 228, -62, 343, 67, 153, 95, +-153, 95, -385, 92, -317, 82, 8, 36, +218, -64, 201, -129, 40, -116, -194, -69, +-228, -14, -35, 64, 123, 161, 218, 219, +135, 118, -179, -155, -375, -368, -346, -290, +-117, 49, 299, 388, 504, 410, 338, 90, +2, -261, -383, -384, -549, -222, -324, 73, +42, 251, 346, 224, 451, 71, 202, -111, +-143, -177, -285, -52, -232, 117, -7, 178, +178, 36, 108, -233, -58, -331, -126, -130, +-61, 219, 139, 434, 293, 337, 139, -5, +-123, -310, -294, -384, -285, -254, 19, -1, +323, 204, 358, 278, 175, 238, -123, 62, +-345, -144, -231, -232, 60, -158, 292, 16, +344, 129, 101, 75, -200, -73, -283, -94, +-132, 35, 115, 175, 317, 156, 276, -60, +80, -234, -91, -165, -215, 70, -198, 226, +-43, 128, 89, -126, 164, -272, 227, -162, +178, 101, 122, 305, 49, 334, -113, 159, +-251, -125, -266, -402, -163, -534, 92, -338, +382, 149, 467, 635, 337, 758, 4, 369, +-388, -297, -526, -767, -327, -713, 59, -241, +465, 344, 576, 672, 274, 570, -159, 164, +-485, -317, -461, -588, -71, -470, 322, -56, +434, 358, 282, 519, -20, 347, -249, -19, +-278, -318, -220, -440, -122, -357, 86, -76, +270, 261, 347, 495, 296, 468, -18, 120, +-336, -301, -452, -500, -377, -394, -49, -105, +305, 169, 415, 280, 335, 294, 68, 259, +-276, 93, -414, -170, -348, -395, -82, -407, +254, -78, 380, 326, 204, 464, -122, 248, +-384, -163, -380, -433, -83, -351, 213, -15, +320, 316, 219, 460, -36, 310, -273, -57, +-299, -397, -217, -544, -67, -370, 116, 52, +179, 445, 193, 601, 124, 419, -75, -18, +-281, -421, -350, -561, -234, -384, 68, -16, +317, 315, 301, 405, 116, 280, -146, 70, +-330, -144, -303, -258, -168, -262, -11, -156, +212, 43, 336, 223, 325, 297, 140, 212, +-263, 1, -598, -245, -625, -385, -235, -302, +386, -21, 798, 325, 679, 486, 102, 342, +-544, 0, -806, -321, -542, -438, 30, -333, +528, -91, 617, 195, 325, 411, -132, 427, +-436, 147, -401, -267, -144, -513, 161, -355, +328, 126, 277, 499, 117, 439, -77, 8, +-195, -438, -201, -532, -144, -245, -40, 180, +79, 466, 207, 518, 327, 305, 339, -63, +151, -421, -205, -637, -523, -531, -576, -91, +-251, 438, 330, 787, 800, 703, 825, 169, +340, -494, -398, -880, -886, -733, -790, -99, +-174, 614, 542, 895, 894, 591, 704, -106, +112, -724, -469, -802, -726, -366, -516, 278, +24, 727, 512, 694, 701, 261, 468, -295, +-54, -697, -475, -731, -577, -322, -328, 301, +182, 788, 552, 817, 570, 268, 250, -455, +-235, -842, -506, -665, -412, -41, -56, 522, +314, 644, 460, 362, 293, -72, -25, -387, +-262, -432, -300, -248, -155, 50, 71, 346, +184, 447, 182, 226, 139, -163, -19, -489, +-109, -461, -133, -53, -117, 392, 0, 559, +54, 300, 44, -184, 71, -505, 89, -444, +75, -82, -1, 279, -200, 437, -301, 297, +-188, 23, 93, -204, 348, -325, 359, -285, +84, -142, -288, 74, -457, 315, -334, 463, +-2, 378, 311, 4, 364, -473, 152, -768, +-128, -577, -318, 65, -266, 759, -42, 1048, +134, 655, 147, -224, -20, -1045, -198, -1272, +-162, -687, 72, 423, 263, 1373, 232, 1475, +-82, 580, -417, -773, -473, -1673, -179, -1437, +242, -225, 511, 1100, 418, 1662, -12, 1113, +-455, -96, -645, -1141, -392, -1423, 138, -840, +582, 211, 633, 1092, 240, 1285, -326, 713, +-713, -323, -670, -1179, -246, -1287, 319, -606, +731, 497, 740, 1335, 309, 1347, -319, 531, +-859, -655, -942, -1514, -429, -1483, 352, -510, +972, 828, 1004, 1756, 399, 1636, -434, 440, +-962, -1073, -945, -1970, -390, -1664, 372, -270, +901, 1310, 963, 2092, 476, 1581, -339, 47, +-977, -1546, -1022, -2161, -465, -1384, 461, 283, +1112, 1761, 1063, 2061, 414, 1029, -520, -579, +-1118, -1758, -1020, -1771, -334, -747, 555, 614, +1146, 1560, 1049, 1588, 376, 740, -517, -514, +-1116, -1511, -1024, -1673, -294, -824, 633, 605, +1180, 1724, 1027, 1799, 231, 690, -686, -925, +-1148, -1956, -912, -1744, -65, -391, 863, 1226, +1229, 2053, 867, 1581, -65, 106, -953, -1434, +-1175, -2069, -673, -1411, 264, 118, 1053, 1556, +1165, 2040, 588, 1262, -311, -296, -1027, -1675, +-1062, -2012, -465, -1051, 393, 576, 1022, 1815, +1026, 1843, 427, 662, -382, -889, -926, -1814, +-909, -1506, -343, -266, 378, 1073, 853, 1694, +853, 1222, 366, 10, -300, -1201, -786, -1656, +-828, -1047, -375, 281, 311, 1465, 766, 1651, +758, 712, 297, -746, -328, -1668, -663, -1389, +-594, -178, -182, 1137, 293, 1632, 527, 1002, +378, -287, 27, -1390, -297, -1557, -383, -636, +-186, 773, 54, 1659, 197, 1388, 193, 132, +66, -1225, -31, -1674, -66, -971, -129, 334, +-199, 1344, -219, 1372, -109, 554, 180, -518, +457, -1180, 444, -1045, 83, -279, -429, 615, +-768, 1045, -617, 747, -75, -84, 543, -817, +887, -880, 699, -278, 55, 546, -654, 925, +-1027, 570, -827, -222, -119, -889, 635, -923, +1028, -275, 861, 630, 163, 1160, -650, 909, +-1115, -39, -968, -1062, -243, -1392, 664, -767, +1164, 467, 977, 1475, 156, 1498, -819, 465, +-1297, -969, -939, -1819, 27, -1422, 999, -17, +1300, 1474, 698, 2002, -352, 1174, -1179, -488, +-1223, -1865, -455, -1993, 605, -806, 1254, 957, +1099, 2085, 223, 1848, -816, 419, -1311, -1313, +-997, -2210, -59, -1701, 943, -52, 1355, 1702, +915, 2381, -118, 1492, -1122, -465, -1419, -2159, +-724, -2416, 444, -1023, 1369, 1092, 1352, 2457, +372, 2153, -872, 400, -1495, -1606, -1072, -2504, +183, -1725, 1326, 216, 1489, 1996, 599, 2414, +-733, 1188, -1565, -856, -1252, -2289, -47, -2133, +1211, -512, 1700, 1433, 983, 2328, -412, 1624, +-1537, -137, -1613, -1717, -596, -2086, 822, -1091, +1668, 548, 1435, 1740, 358, 1782, -916, 673, +-1590, -801, -1295, -1700, -227, -1472, 975, -271, +1596, 1043, 1227, 1603, 155, 1046, -948, -174, +-1467, -1186, -1038, -1322, -25, -541, 904, 509, +1226, 1145, 794, 950, -33, 134, -638, -677, +-794, -990, -538, -597, -81, 164, 279, 730, +533, 762, 564, 252, 353, -370, -10, -688, +-419, -487, -685, 28, -580, 448, -96, 529, +492, 218, 892, -173, 741, -377, 87, -295, +-649, -5, -1028, 158, -791, 126, -70, -13, +739, -60, 1189, 121, 971, 302, 103, 226, +-995, -193, -1562, -641, -1177, -676, 93, -135, +1504, 716, 1964, 1183, 1089, 837, -651, -250, +-2075, -1373, -2140, -1631, -699, -729, 1230, 865, +2409, 2044, 2005, 1913, 237, 399, -1664, -1579, +-2605, -2660, -1885, -2020, 122, 141, 2084, 2398, +2703, 3180, 1537, 1766, -691, -1045, -2472, -3242, +-2585, -3253, -949, -916, 1287, 2124, 2628, 3724, +2159, 2683, 167, -266, -1933, -3043, -2692, -3720, +-1547, -1775, 733, 1433, 2464, 3715, 2422, 3469, +644, 772, -1649, -2578, -2754, -4265, -1833, -3001, +340, 450, 2306, 3753, 2543, 4486, 896, 2045, +-1352, -1919, -2607, -4637, -1918, -4069, 177, -642, +2132, 3340, 2498, 4978, 992, 3113, -1307, -985, +-2720, -4495, -2120, -4793, 89, -1736, 2317, 2662, +2936, 5173, 1431, 4009, -1195, 65, -3072, -3971, +-2795, -5092, -511, -2733, 2265, 1485, 3487, 4540, +2223, 4367, -665, 1274, -3203, -2646, -3444, -4518, +-1193, -3220, 1921, 284, 3746, 3440, 2953, 3949, +10, 1664, -2965, -1753, -3863, -3671, -2068, -2857, +1208, -29, 3616, 2709, 3509, 3318, 981, 1589, +-2176, -1305, -3752, -3092, -2744, -2615, 111, -227, +2844, 2276, 3579, 2963, 1797, 1428, -1170, -1217, +-3208, -2751, -2911, -2088, -607, 234, 2048, 2290, +3161, 2381, 1969, 596, -451, -1673, -2484, -2533, +-2683, -1420, -996, 777, 1292, 2381, 2619, 2188, +2058, 424, 76, -1702, -1800, -2541, -2307, -1567, +-1190, 552, 720, 2249, 1964, 2244, 1715, 623, +277, -1453, -1229, -2331, -1707, -1472, -881, 484, +535, 1987, 1427, 1925, 1197, 497, 82, -1323, +-1008, -2042, -1272, -1317, -569, 374, 537, 1814, +1251, 1879, 980, 582, -69, -1232, -1037, -2031, +-1278, -1271, -492, 465, 703, 1794, 1424, 1579, +1083, 232, -62, -1253, -1188, -1585, -1515, -679, +-786, 619, 462, 1326, 1427, 912, 1403, -128, +486, -993, -656, -938, -1363, -127, -1174, 750, +-325, 954, 652, 254, 1110, -703, 923, -1108, +257, -514, -480, 620, -890, 1373, -850, 1031, +-313, -200, 359, -1406, 850, -1642, 822, -610, +249, 960, -482, 1929, -901, 1522, -706, -87, +-135, -1729, 523, -2110, 887, -846, 717, 1099, +47, 2207, -781, 1534, -1170, -327, -744, -1889, +321, -1914, 1267, -427, 1326, 1356, 323, 2056, +-979, 1094, -1612, -699, -1129, -2021, 211, -1718, +1456, 9, 1704, 1768, 693, 2201, -814, 787, +-1810, -1283, -1590, -2423, -228, -1605, 1276, 497, +1986, 2249, 1297, 2299, -279, 570, -1707, -1605, +-2013, -2662, -901, -1770, 845, 502, 2017, 2511, +1706, 2724, 278, 901, -1338, -1740, -2049, -3148, +-1260, -2183, 374, 486, 1772, 2804, 1815, 2970, +545, 888, -1146, -1831, -1916, -3047, -1165, -1945, +363, 610, 1609, 2584, 1499, 2496, 334, 520, +-1018, -1841, -1610, -2700, -960, -1460, 401, 993, +1439, 2661, 1406, 2254, 338, 57, -980, -2326, +-1505, -2883, -893, -1218, 369, 1501, 1269, 3102, +1152, 2273, 121, -336, -895, -2739, -1094, -2963, +-344, -880, 707, 1934, 1109, 3193, 520, 1935, +-520, -844, -1155, -2986, -916, -2786, 96, -383, +1177, 2349, 1452, 3231, 687, 1671, -726, -1261, +-1738, -3148, -1471, -2651, -101, -109, 1482, 2513, +2014, 3091, 1063, 1386, -665, -1466, -1885, -3012, +-1764, -2286, -360, 239, 1339, 2564, 2006, 2761, +1261, 949, -386, -1692, -1723, -2890, -1825, -1936, +-618, 476, 1069, 2467, 2014, 2538, 1517, 851, +-125, -1466, -1672, -2554, -2016, -1843, -842, 178, +981, 2005, 2012, 2283, 1547, 928, -85, -1109, +-1526, -2239, -1910, -1667, -768, 186, 904, 1810, +1866, 2009, 1442, 694, -148, -1066, -1465, -1952, +-1735, -1396, -622, 105, 828, 1398, 1603, 1720, +1155, 797, -127, -505, -1210, -1456, -1461, -1352, +-471, -372, 804, 730, 1494, 1318, 961, 974, +-314, 131, -1294, -775, -1387, -1119, -379, -778, +751, -47, 1400, 749, 1051, 1049, 8, 764, +-998, -8, -1379, -845, -700, -1154, 319, -705, +1125, 271, 1021, 1143, 275, 1175, -623, 357, +-1080, -825, -685, -1385, 36, -885, 803, 332, +877, 1439, 384, 1379, -361, 240, -830, -1240, +-658, -1853, -217, -937, 403, 761, 600, 2060, +555, 1671, 188, -57, -273, -1839, -539, -2187, +-649, -708, -298, 1308, 140, 2359, 596, 1380, +706, -723, 352, -2279, -219, -1954, -697, 60, +-618, 2065, -247, 2452, 255, 715, 508, -1656, +438, -2780, 215, -1565, -89, 1004, -363, 2807, +-537, 2276, -428, -237, -8, -2575, 537, -2773, +808, -516, 588, 2200, -151, 3152, -916, 1345, +-1136, -1663, -497, -3398, 527, -2307, 1274, 755, +1171, 3277, 190, 3219, -916, 509, -1390, -2626, +-928, -3707, 152, -1786, 1186, 1514, 1426, 3590, +761, 2712, -540, -240, -1455, -2951, -1508, -3174, +-436, -894, 970, 1960, 1864, 3195, 1445, 1797, +-62, -850, -1480, -2809, -2014, -2385, -932, -135, +759, 2097, 1973, 2558, 1687, 875, 146, -1329, +-1447, -2342, -2024, -1370, -983, 651, 796, 1876, +2057, 1591, 1788, 8, 53, -1263, -1758, -1485, +-2372, -591, -1061, 521, 1160, 981, 2675, 824, +2122, 239, -115, -192, -2411, -547, -2978, -665, +-1076, -642, 1742, -144, 3340, 612, 2283, 1266, +-717, 978, -3230, -225, -3114, -1591, -377, -1732, +2772, -287, 3675, 1684, 1516, 2350, -1984, 854, +-3849, -1575, -2556, -2747, 967, -1449, 3626, 1192, +3336, 2855, 222, 1976, -2969, -619, -3649, -2671, +-1276, -2240, 2045, 130, 3433, 2325, 2051, 2186, +-930, 102, -2892, -2021, -2421, -1944, -92, -26, +2026, 1854, 2345, 1646, 883, -200, -1149, -1753, +-1973, -1385, -1292, 407, 324, 1585, 1469, 1137, +1409, -469, 369, -1213, -958, -731, -1580, 325, +-1014, 534, 487, 47, 1730, -104, 1695, 386, +34, 884, -1914, 38, -2408, -1374, -670, -1821, +1884, -222, 2937, 2097, 1490, 2538, -1473, 529, +-3286, -2299, -2319, -2910, 590, -838, 3090, 1963, +3011, 2838, 564, 1120, -2368, -1240, -3379, -2349, +-1895, -1376, 1074, 376, 3176, 1642, 3020, 1529, +602, 383, -2507, -949, -3822, -1561, -2248, -910, +1286, 435, 3898, 1472, 3410, 1231, -8, -68, +-3353, -1281, -3838, -1389, -1113, -303, 2249, 997, +3437, 1410, 1777, 663, -1057, -610, -2489, -1264, +-1817, -972, 115, 166, 1369, 1054, 1243, 1172, +227, 259, -549, -908, -505, -1330, 42, -569, +296, 856, -57, 1476, -395, 750, -372, -809, +157, -1545, 588, -761, 475, 652, -67, 1377, +-390, 712, -373, -393, -149, -1001, -52, -728, +14, -45, 396, 501, 786, 915, 583, 789, +-523, 46, -1648, -1291, -1408, -1877, 341, -592, +2214, 1764, 2215, 2918, 207, 1088, -2136, -2087, +-2811, -3406, -1077, -1356, 1548, 1934, 3043, 3064, +2098, 1445, -657, -1127, -3060, -2191, -2940, -1657, +-91, -158, 3028, 1457, 3514, 2293, 720, 1415, +-2831, -1289, -3658, -3223, -1212, -2184, 2356, 1559, +3604, 3945, 1787, 2373, -1375, -1716, -3200, -4033, +-2265, -2393, 288, 1286, 2631, 3571, 2683, 2662, +636, -274, -1932, -2889, -2898, -3227, -1410, -969, +1309, 2163, 2965, 3698, 2080, 2120, -642, -1261, +-2863, -3669, -2654, -3065, -37, 49, 2582, 3116, +2926, 3776, 618, 1307, -2174, -2323, -2957, -4068, +-1178, -2333, 1599, 1387, 2844, 3747, 1766, 2838, +-859, -267, -2639, -2822, -2289, -3032, 88, -1053, +2391, 1683, 2701, 3217, 641, 2215, -2030, -778, +-2819, -3329, -1230, -2739, 1445, 341, 2828, 2971, +1877, 2418, -624, -207, -2551, -2127, -2359, -1625, +-262, 165, 2082, 1275, 2581, 990, 887, -125, +-1541, -891, -2498, -808, -1214, 136, 1065, 927, +2233, 845, 1243, -209, -895, -970, -2103, -683, +-1206, 273, 906, 763, 1954, 350, 925, -314, +-1068, -505, -1823, -83, -574, 396, 1103, 432, +1370, 1, 94, -583, -1019, -572, -776, 119, +311, 801, 853, 734, 262, -279, -718, -981, +-892, -797, 6, 170, 1083, 903, 1409, 971, +168, 459, -1463, -550, -2057, -1317, -630, -1318, +1627, 42, 2562, 1594, 1152, 1837, -1385, 371, +-2560, -1384, -1414, -1742, 868, -680, 2095, 674, +1390, 1208, -360, 989, -1561, 273, -1282, -684, +-23, -1266, 1078, -957, 1008, 236, 184, 1260, +-739, 1136, -767, 96, -211, -721, 341, -825, +383, -346, -13, 11, -149, 234, -110, 345, +256, 400, 128, 239, 9, -17, -384, -195, +-267, -416, 85, -441, 347, -288, 202, 295, +-146, 730, -213, 580, 145, -128, 502, -611, +300, -414, -427, 113, -827, 257, -499, -152, +460, -348, 1115, 99, 836, 773, -181, 754, +-1055, -188, -954, -1207, -38, -1070, 865, 73, +764, 1221, 5, 1105, -616, 53, -346, -867, +185, -820, 289, -148, -147, 335, -387, 499, +6, 337, 349, 145, 346, -366, -220, -813, +-342, -504, -148, 474, 168, 1399, 107, 866, +-96, -565, 62, -1774, 68, -1216, 120, 389, +-153, 1736, -75, 1525, 69, 10, 215, -1377, +65, -1686, -169, -532, -156, 950, 11, 1663, +301, 1027, 317, -461, 113, -1537, -346, -1410, +-644, -131, -275, 1245, 676, 1681, 1103, 813, +453, -784, -903, -1738, -1502, -1408, -627, 120, +899, 1532, 1670, 1764, 867, 617, -663, -1015, +-1679, -1839, -1256, -1313, 195, 298, 1442, 1598, +1474, 1761, 22, 498, -1276, -1143, -1291, -1849, +-121, -1108, 917, 521, 823, 1707, -86, 1503, +-553, 9, -312, -1494, 160, -1753, 246, -418, +23, 1390, -146, 1886, 15, 718, 183, -1194, +158, -1862, -98, -974, -355, 676, -202, 1509, +361, 1171, 783, 225, 291, -855, -724, -1317, +-1185, -1119, -311, 59, 1191, 1363, 1526, 1704, +281, 549, -1383, -1191, -1653, -1879, -391, -1018, +1242, 765, 1607, 1807, 570, 1425, -967, -125, +-1620, -1611, -1035, -1864, 465, -447, 1558, 1345, +1308, 2069, 62, 894, -1342, -991, -1593, -1960, +-722, -1151, 738, 464, 1612, 1579, 1292, 1370, +-105, 57, -1428, -1089, -1526, -1414, -434, -492, +1075, 680, 1436, 1201, 636, 597, -493, -299, +-1004, -749, -641, -500, 101, 73, 736, 295, +748, 302, 159, 108, -646, -92, -835, -205, +-92, -206, 678, 21, 871, 202, 160, 363, +-585, 33, -680, -232, -203, -436, 78, -286, +273, 193, 363, 422, 240, 458, 131, 173, +-376, -247, -484, -544, -373, -649, 61, -159, +196, 574, 436, 1029, 289, 500, 22, -514, +-195, -1008, -590, -590, -296, 372, -34, 633, +420, 323, 414, -148, 423, -215, -5, -42, +-516, 95, -614, 138, -310, 57, 595, -227, +882, -538, 396, -327, -478, 368, -750, 998, +-280, 649, 287, -290, 556, -1075, 271, -827, +91, -114, -160, 642, -287, 998, -434, 677, +-203, -109, 263, -1233, 501, -1229, 522, -1, +66, 1436, -445, 1366, -779, -273, -588, -1478, +128, -961, 971, 762, 875, 1209, -119, 165, +-976, -1121, -993, -836, 91, 641, 884, 1366, +660, 424, -32, -1108, -453, -1455, -385, -161, +-185, 1390, -157, 1340, 37, -148, 546, -1385, +796, -1019, 331, 522, -507, 1205, -1263, 290, +-729, -859, 519, -767, 1454, 544, 1258, 1130, +-234, 229, -1703, -1188, -1686, -1252, 183, 93, +1854, 1379, 2035, 1393, 26, -84, -1969, -1373, +-1971, -1556, -231, -158, 1540, 1429, 1704, 1786, +229, 299, -1077, -1579, -1135, -1829, -251, -186, +540, 1608, 509, 1487, 92, -204, -117, -1368, +30, -735, -57, 696, -484, 1060, -687, -171, +37, -1194, 1126, -763, 1224, 828, -6, 1542, +-1477, 384, -1491, -1206, -71, -1469, 1382, 141, +1378, 1493, 247, 1014, -865, -791, -925, -1655, +-414, -502, 193, 1186, 593, 1639, 746, 320, +428, -1044, -269, -1400, -1027, -693, -911, 380, +168, 1218, 1234, 1305, 1198, 458, -143, -1088, +-1469, -1835, -1265, -936, 220, 814, 1430, 1727, +1239, 1063, -210, -237, -1371, -961, -1059, -928, +-83, -613, 729, -57, 870, 815, 524, 1270, +-34, 781, -550, -616, -1025, -1541, -696, -997, +327, 279, 1091, 1253, 1029, 1083, 57, 217, +-784, -796, -914, -1201, -438, -707, 70, 431, +525, 1382, 900, 921, 806, -310, 173, -1268, +-1062, -979, -1524, 221, -811, 1020, 807, 988, +1878, 195, 1531, -710, -303, -1284, -1855, -875, +-1887, 363, -305, 1595, 1651, 1661, 2073, 158, +715, -1551, -1353, -2109, -2090, -940, -1096, 968, +938, 2114, 1869, 1673, 1188, -16, -381, -1630, +-1498, -2029, -1159, -924, 50, 785, 902, 1786, +756, 1573, 146, 248, -412, -1111, -382, -1762, +-214, -1147, -26, 285, 148, 1460, 436, 1555, +483, 440, 32, -740, -695, -1364, -956, -994, +-191, -131, 854, 766, 1242, 1276, 613, 920, +-610, -13, -1356, -1134, -970, -1457, 189, -813, +1196, 486, 1298, 1651, 447, 1737, -829, 487, +-1398, -1540, -1031, -2501, 163, -1391, 1216, 1237, +1439, 2766, 572, 1760, -784, -797, -1570, -2356, +-1173, -1555, 283, 338, 1326, 1407, 1296, 1010, +109, 184, -907, -305, -1190, -411, -389, -570, +451, -661, 835, -171, 576, 599, -17, 1130, +-428, 775, -537, -163, -190, -1013, -38, -1126, +55, -491, 122, 405, 378, 991, 632, 848, +408, 323, -383, -303, -1095, -665, -810, -779, +70, -548, 947, 52, 944, 763, 281, 1105, +-474, 610, -480, -321, -312, -1092, -141, -1071, +-88, -330, 29, 585, 408, 1138, 588, 943, +354, 189, -461, -774, -834, -1175, -622, -931, +215, -36, 803, 917, 648, 1356, 112, 973, +-493, -262, -635, -1348, -443, -1534, 147, -456, +478, 900, 505, 1459, 129, 908, -340, -143, +-374, -894, -71, -1061, 257, -667, 84, 208, +-58, 1107, -197, 1209, -20, 233, 110, -1087, +244, -1350, 229, -298, 48, 1017, -258, 1110, +-480, 112, -329, -852, 98, -788, 523, 73, +499, 656, 324, 625, 79, 67, -417, -431, +-1033, -713, -1128, -589, -181, -16, 1587, 779, +2437, 1291, 1147, 782, -1522, -518, -3352, -1782, +-2445, -1754, 704, -240, 3583, 1735, 3489, 2464, +530, 1263, -2980, -1085, -4010, -2631, -1625, -2041, +1952, 118, 3673, 2154, 2252, 2273, -850, 677, +-2834, -1379, -2242, -1965, 57, -949, 1883, 680, +1965, 1463, 306, 785, -1227, -375, -1530, -1027, +-471, -606, 849, 369, 1313, 880, 628, 620, +-492, -283, -1187, -946, -972, -851, 108, -36, +1115, 847, 1332, 994, 359, 493, -975, -385, +-1544, -773, -657, -756, 627, -358, 1342, 130, +848, 599, -191, 919, -859, 711, -764, -59, +-219, -927, 355, -1202, 447, -625, 197, 335, +-27, 932, -122, 961, 172, 567, 212, 95, +-53, -582, -478, -1200, -600, -1355, -317, -481, +309, 1131, 826, 2132, 987, 1634, 583, -264, +-471, -1995, -1573, -2207, -1639, -848, -432, 982, +1427, 1875, 2608, 1540, 1550, 298, -739, -794, +-2796, -1414, -2622, -1277, -278, -485, 2532, 655, +3171, 1588, 1098, 1441, -1863, 158, -3099, -1356, +-1506, -1668, 1115, -585, 2468, 910, 1411, 1362, +-512, 492, -1609, -619, -1057, -990, 86, -295, +852, 682, 754, 1031, 181, 374, -151, -843, +-578, -1421, -641, -856, -443, 662, 306, 1557, +1096, 1280, 1212, 126, 230, -900, -1256, -1172, +-1753, -1035, -1046, -416, 718, 330, 1914, 1283, +1804, 1474, 388, 903, -1408, -401, -2228, -1502, +-1478, -1821, 346, -1099, 1970, 380, 2114, 1861, +819, 2197, -1001, 1112, -1965, -774, -1628, -2123, +-402, -2120, 1050, -927, 1651, 860, 1460, 2187, +326, 2356, -904, 844, -1612, -1318, -1434, -2681, +-446, -2085, 863, -90, 1741, 1739, 1465, 2331, +399, 1446, -1160, -124, -1879, -1724, -1314, -2161, +159, -1153, 1454, 780, 1712, 2055, 690, 1603, +-807, -73, -1499, -1484, -1091, -1443, 199, -273, +1121, 1077, 1072, 1325, 233, 401, -667, -930, +-889, -1572, -536, -712, 200, 753, 671, 1717, +756, 1293, 318, 7, -356, -1267, -764, -1736, +-895, -1237, -255, 83, 609, 1580, 1224, 2158, +995, 1222, -87, -625, -1275, -2057, -1499, -1938, +-496, -646, 808, 913, 1381, 1753, 949, 1520, +-115, 393, -876, -976, -936, -1497, -333, -915, +349, 303, 584, 785, 200, 340, -306, -274, +-200, -171, 440, 601, 669, 975, 196, 379, +-808, -893, -1151, -1703, -529, -1423, 378, 35, +1034, 1620, 1147, 2362, 707, 1530, -269, -362, +-1269, -2203, -1754, -2698, -842, -1516, 861, 775, +1947, 2766, 1496, 2864, -107, 1009, -1394, -1770, +-1318, -2981, -119, -1876, 715, 563, 541, 1968, +-482, 1436, -848, -2, 120, -759, 1510, -265, +1672, 277, 34, 194, -2045, -523, -2508, -922, +-815, -477, 1420, 452, 2465, 1151, 1612, 1015, +-195, 208, -1407, -694, -1600, -948, -967, -581, +122, -175, 900, 66, 1159, 180, 756, 657, +4, 1158, -720, 735, -735, -452, -302, -1617, +149, -1526, 265, -245, -26, 1014, -166, 1355, +175, 859, 557, 205, 622, -327, 104, -671, +-696, -1072, -1130, -980, -827, -207, 97, 877, +1204, 1665, 1524, 1243, 671, -17, -800, -1302, +-1560, -1487, -940, -704, 293, 372, 931, 669, +366, 455, -253, 328, -202, 474, 507, 568, +793, -24, 39, -943, -954, -1476, -1446, -1030, +-729, 245, 661, 1555, 1667, 2033, 1556, 952, +208, -849, -1416, -2174, -1848, -1749, -696, 29, +856, 1443, 1439, 1515, 665, 501, -528, -441, +-762, -644, -260, -475, 363, -319, 406, -203, +145, 165, -132, 459, -338, 566, -503, 199, +-376, -250, 245, -312, 849, -197, 972, -4, +197, -110, -794, -331, -1319, -244, -696, 359, +216, 1033, 1018, 1061, 1021, 92, 256, -1409, +-452, -1981, -747, -1107, -393, 938, 33, 2401, +303, 2131, 53, 102, -77, -1895, -89, -2440, +137, -1126, 365, 780, 436, 1797, 139, 1472, +-363, 376, -878, -698, -939, -1099, -216, -875, +848, -269, 1601, 415, 1237, 656, 29, 535, +-1398, 202, -1968, -88, -1261, -329, 162, -433, +1757, -409, 2055, 39, 1327, 502, -468, 495, +-1838, 45, -2137, -507, -917, -383, 707, 242, +1752, 550, 1458, 183, 343, -593, -525, -739, +-851, -59, -623, 822, -497, 862, -281, 111, +66, -686, 676, -787, 891, -241, 551, 186, +-82, 297, -591, 304, -641, 387, -461, 409, +-115, -32, 48, -686, 335, -956, 540, -449, +529, 543, 370, 1069, -128, 824, -793, -168, +-967, -832, -519, -776, 496, -95, 1130, 507, +816, 432, -154, -32, -831, -310, -483, -91, +170, 328, 520, 384, -15, 0, -515, -506, +-473, -579, 211, -270, 804, 334, 528, 708, +-42, 656, -621, 206, -500, -519, -184, -935, +213, -795, 257, -29, 198, 863, 60, 1195, +-92, 571, -98, -497, -55, -1167, 175, -837, +82, 159, 1, 795, -213, 646, -282, 31, +-281, -342, -37, -239, 399, 23, 812, 30, +694, -136, -190, -196, -1152, -63, -1241, 336, +-350, 536, 824, 345, 1259, -354, 790, -926, +23, -771, -497, 257, -643, 1141, -624, 1024, +-424, 8, -273, -972, 287, -1026, 800, -327, +1178, 386, 905, 748, -173, 674, -1294, 299, +-1813, -241, -1022, -780, 297, -831, 1444, -352, +1714, 435, 1156, 1010, -38, 908, -1174, 175, +-1775, -787, -1441, -1198, -138, -672, 1075, 402, +1682, 1015, 1259, 695, 336, -91, -761, -527, +-1377, -260, -1264, 92, -453, 86, 668, -205, +1256, -328, 963, -54, 13, 353, -729, 484, +-723, 329, -159, -78, 455, -320, 412, -412, +-141, -259, -555, -143, -442, 3, 77, 213, +594, 456, 675, 644, 441, 375, 59, -153, +-569, -859, -1115, -1076, -1032, -802, -172, 191, +1102, 1267, 1730, 1772, 1084, 1051, -251, -644, +-1368, -2043, -1604, -2030, -870, -457, 301, 1336, +1164, 2132, 1397, 1311, 755, -134, -244, -1303, +-882, -1408, -952, -776, -542, 118, 32, 709, +349, 895, 473, 675, 430, 210, 292, -356, +124, -746, -9, -645, -314, -126, -503, 402, +-576, 349, -383, -132, 82, -356, 547, 184, +902, 993, 967, 985, 390, -113, -683, -1526, +-1593, -1771, -1633, -739, -470, 876, 1244, 1800, +2115, 1572, 1710, 595, 114, -636, -1546, -1452, +-2123, -1617, -1355, -929, 225, 213, 1555, 1339, +1683, 1721, 821, 1049, -398, -233, -1064, -1290, +-1084, -1284, -465, -387, 157, 375, 735, 361, +818, -82, 370, -41, -286, 636, -737, 1051, +-520, 491, 89, -610, 598, -1289, 449, -1056, +-3, -361, -439, 311, -377, 854, -56, 1206, +130, 1061, 202, 204, 130, -926, 79, -1544, +73, -1217, -47, -272, -107, 690, -93, 1285, +-82, 1252, -351, 634, -347, -406, 39, -1249, +800, -1225, 1142, -405, 411, 596, -773, 869, +-1680, 368, -1127, -324, 165, -361, 1387, 220, +1620, 784, 804, 625, -497, -385, -1442, -1317, +-1345, -1494, -455, -503, 822, 954, 1266, 1999, +818, 1777, -145, 401, -789, -1292, -683, -2232, +-70, -1738, 358, -283, 468, 1252, 106, 1943, +-390, 1519, -535, 340, -298, -872, 421, -1499, +982, -1205, 883, -340, -229, 500, -1270, 759, +-1600, 551, -444, 259, 1099, 215, 1778, 262, +1091, 12, -328, -485, -1215, -998, -1228, -919, +-546, -251, 57, 716, 653, 1375, 955, 1210, +908, 330, 375, -777, -560, -1375, -1181, -1188, +-1058, -299, -347, 594, 545, 1133, 1081, 1011, +994, 344, 437, -392, -280, -866, -891, -774, +-954, -334, -599, 223, 92, 527, 716, 652, +874, 320, 611, -153, 85, -544, -403, -456, +-650, 47, -624, 403, -428, 243, -62, -228, +500, -363, 856, -75, 814, 392, 237, 444, +-623, 96, -1078, -299, -897, -471, -116, -287, +634, 82, 922, 372, 686, 373, 145, 112, +-335, -203, -710, -280, -713, -164, -379, -15, +341, 86, 872, 217, 700, 249, -42, 74, +-713, -292, -573, -423, 82, -94, 606, 313, +340, 353, -226, -58, -569, -268, -331, -41, +253, 371, 579, 273, 507, -178, -70, -581, +-543, -430, -609, 59, -187, 399, 446, 509, +598, 313, 255, 100, -245, -212, -519, -420, +-504, -527, -55, -305, 493, 85, 853, 487, +568, 608, -383, 270, -1317, -208, -1099, -406, +23, -140, 1233, 180, 1419, 86, 544, -406, +-575, -592, -1147, -127, -986, 642, -243, 960, +639, 569, 862, -229, 506, -752, -260, -781, +-417, -394, 53, 140, 430, 373, 68, 326, +-644, 194, -774, 257, -139, 427, 634, 276, +695, -303, 332, -888, 14, -931, -44, -476, +-103, 245, -481, 774, -674, 1064, -453, 927, +177, 342, 719, -471, 818, -1061, 429, -1249, +-162, -997, -501, -309, -592, 763, -363, 1818, +-199, 1887, -48, 679, 219, -1037, 476, -1952, +697, -1506, 436, -411, -56, 472, -529, 826, +-782, 916, -700, 822, -290, 528, 341, -11, +762, -654, 909, -1056, 497, -1056, 23, -435, +-376, 469, -744, 1002, -980, 773, -745, 177, +53, -80, 1046, 120, 1474, 145, 907, -420, +-88, -1104, -956, -1007, -1238, -152, -905, 875, +-197, 1196, 562, 853, 1086, 225, 914, -324, +326, -572, -313, -590, -727, -490, -837, -532, +-496, -416, 16, 95, 617, 1089, 814, 1680, +400, 1111, -214, -394, -631, -1677, -439, -1694, +55, -690, 491, 463, 384, 972, -116, 907, +-677, 536, -610, 149, 90, -182, 800, -383, +910, -436, 314, -398, -469, -316, -781, -165, +-664, 113, -307, 423, 220, 656, 636, 566, +802, 129, 468, -440, -212, -717, -703, -456, +-583, 68, -155, 273, 227, 5, 231, -269, +43, -29, -1, 597, 255, 896, 427, 458, +238, -459, -419, -1158, -914, -1145, -635, -368, +249, 700, 1020, 1365, 800, 1075, -96, -46, +-852, -1023, -673, -1072, 81, -252, 735, 552, +552, 683, -150, 223, -743, -276, -723, -465, +38, -299, 814, 138, 893, 529, 220, 567, +-607, 34, -882, -593, -296, -715, 350, -137, +489, 516, 105, 545, -242, 24, -81, -460, +331, -312, 414, 197, 20, 511, -520, 272, +-701, -220, -337, -473, 222, -321, 546, 15, +708, 190, 488, 277, 2, 247, -566, 139, +-958, -198, -713, -478, 102, -293, 734, 340, +844, 792, 304, 390, -256, -583, -489, -1135, +-307, -646, -5, 457, 291, 1182, 264, 1007, +-73, 183, -521, -699, -615, -1099, -63, -850, +779, -5, 1102, 777, 531, 935, -398, 333, +-1138, -395, -925, -552, -257, -101, 411, 381, +684, 393, 626, -63, 332, -605, 87, -779, +-173, -387, -443, 407, -579, 1078, -577, 1077, +-270, 334, 262, -565, 871, -983, 1038, -825, +629, -398, -388, -70, -1139, 237, -1139, 644, +-339, 952, 509, 904, 804, 283, 561, -593, +141, -1235, -66, -1220, -243, -618, -322, 234, +-289, 865, -42, 1109, 122, 1017, 94, 554, +-11, -195, 6, -1037, 175, -1420, 164, -1096, +-21, -210, -98, 685, 3, 1230, 102, 1263, +-109, 775, -439, -153, -374, -1020, 170, -1279, +704, -715, 657, 84, 81, 445, -541, 287, +-694, 86, -333, 327, 111, 744, 407, 859, +430, 258, 169, -819, -126, -1714, -293, -1656, +-246, -395, 45, 1267, 289, 2216, 171, 1649, +-106, 129, -361, -1246, -228, -1605, 116, -1048, +396, -169, 331, 459, 33, 667, -284, 571, +-476, 363, -278, 267, 96, 208, 570, 5, +653, -424, 189, -874, -427, -965, -841, -495, +-645, 342, -91, 1170, 494, 1430, 805, 899, +772, -224, 295, -1184, -471, -1399, -885, -843, +-804, -21, -183, 544, 394, 879, 641, 943, +424, 683, 160, -57, -202, -854, -288, -1118, +-100, -552, 222, 298, 243, 683, -224, 417, +-668, -121, -583, -261, 185, -20, 751, 320, +865, 312, 353, -6, -99, -316, -538, -363, +-780, -182, -747, -71, -224, -46, 566, 14, +938, 314, 676, 590, 12, 494, -333, -33, +-452, -566, -299, -671, -205, -370, 18, -17, +143, 170, 38, 333, -195, 469, -121, 456, +348, 56, 793, -434, 649, -574, -109, -186, +-838, 324, -1060, 404, -759, 15, -128, -455, +603, -498, 1070, -96, 1118, 415, 505, 667, +-344, 560, -953, 201, -1018, -212, -650, -650, +-109, -910, 442, -787, 729, -114, 775, 793, +391, 1285, -98, 965, -325, 53, -365, -625, +-237, -756, -352, -466, -413, -348, -249, -424, +294, -282, 854, 329, 883, 1153, 276, 1372, +-415, 693, -685, -571, -532, -1413, -215, -1349, +-77, -510, 3, 367, 265, 775, 494, 753, +388, 529, 139, 244, -43, -130, -62, -461, +-146, -543, -555, -308, -766, 2, -369, 167, +507, 130, 1100, 55, 880, -44, -4, -18, +-666, 121, -777, 401, -405, 425, 48, 19, +316, -591, 366, -785, 290, -349, 102, 279, +-203, 529, -315, 320, -280, 64, 12, -30, +293, 15, 330, 8, 128, 27, -123, -14, +-233, -207, -243, -499, -121, -503, 9, 45, +168, 735, 269, 920, 174, 393, -15, -341, +-117, -690, -43, -563, -84, -260, -199, 49, +-283, 304, -50, 472, 350, 378, 510, 36, +197, -297, -161, -386, -378, -191, -296, 75, +-118, 274, 51, 280, 190, 117, 317, -159, +146, -395, -113, -432, -191, -193, -75, 259, +73, 661, 21, 697, -144, 225, -142, -408, +58, -746, 211, -510, 221, -94, 97, 144, +-99, 165, -214, 207, -325, 379, -116, 380, +192, 142, 396, -192, 242, -333, -43, -333, +-180, -315, -188, -240, -67, -10, -196, 299, +-91, 431, 104, 378, 385, 279, 300, 163, +-52, -192, -322, -700, -266, -870, 112, -335, +289, 515, 154, 933, -289, 604, -510, -18, +-358, -445, 188, -520, 643, -406, 705, -40, +329, 473, -224, 718, -625, 330, -727, -524, +-472, -974, 3, -589, 502, 330, 711, 918, +558, 751, 109, 82, -317, -508, -521, -601, +-396, -288, -76, 156, 282, 288, 264, 96, +-66, -190, -268, -171, -130, 108, 378, 327, +550, 215, 210, -123, -400, -279, -615, -126, +-396, 195, -13, 303, 338, 52, 508, -367, +548, -538, 122, -280, -559, 208, -922, 484, +-500, 447, 367, 288, 906, 219, 657, 28, +-17, -446, -385, -926, -426, -842, -332, -56, +-276, 777, -71, 1011, 300, 593, 585, 30, +448, -365, -34, -529, -388, -549, -333, -232, +-17, 188, 136, 425, -25, 201, -361, -125, +-302, -151, 118, 66, 679, 217, 786, 94, +327, -24, -409, -58, -848, -72, -759, -182, +-303, -246, 242, -61, 559, 166, 578, 243, +359, 88, 101, -13, -101, 25, -161, 119, +-293, 101, -466, -42, -499, -247, -305, -426, +201, -362, 649, 7, 829, 482, 584, 663, +59, 362, -519, -118, -840, -379, -716, -356, +-264, -253, 220, -186, 493, -31, 535, 230, +383, 383, 236, 248, 34, 26, -200, -33, +-496, 47, -543, 5, -429, -315, -57, -585, +376, -478, 604, 84, 562, 697, 329, 916, +-58, 550, -362, -152, -547, -714, -496, -828, +-200, -460, 136, 24, 293, 373, 247, 398, +215, 271, 190, 163, 255, 123, 80, 100, +-192, -4, -414, -115, -458, -228, -368, -334, +-151, -498, 160, -494, 529, -99, 794, 653, +539, 1151, -121, 858, -753, -98, -854, -815, +-303, -645, 395, 25, 654, 293, 272, -224, +-247, -860, -443, -751, -159, 185, 274, 1180, +446, 1468, 265, 876, -60, -160, -357, -1062, +-465, -1407, -260, -981, 121, -15, 473, 862, +465, 1007, 113, 383, -266, -438, -396, -640, +-289, -92, -120, 676, 135, 881, 323, 256, +451, -721, 234, -1257, -180, -911, -439, 57, +-325, 952, -55, 1122, 103, 590, 69, -207, +24, -668, 72, -596, 76, -208, 91, 86, +139, 162, 264, 155, 126, 214, -287, 268, +-757, 105, -653, -216, 3, -401, 737, -259, +938, 41, 470, 195, -243, 109, -684, 58, +-588, 131, -240, 189, 199, 44, 308, -175, +287, -219, 140, -65, 82, 12, -56, -107, +-168, -181, -215, -15, -128, 319, 84, 444, +124, 263, 11, -38, -136, -304, -92, -521, +68, -608, 283, -336, 369, 404, 171, 1160, +-207, 1186, -645, 253, -614, -967, -118, -1476, +549, -958, 700, 40, 294, 649, -283, 678, +-374, 502, -56, 508, 183, 559, 112, 223, +-150, -528, -284, -1215, -168, -1227, 107, -545, +232, 416, 272, 1027, 88, 1075, -155, 676, +-271, 76, -100, -422, 161, -662, 278, -591, +139, -336, -142, -44, -233, 159, -236, 337, +-104, 390, 61, 305, 237, 43, 306, -261, +123, -397, -148, -284, -284, 90, -58, 433, +152, 515, 176, 83, -82, -523, -234, -810, +-204, -430, 32, 346, 162, 854, 196, 746, +196, 222, 176, -342, 19, -696, -275, -774, +-507, -513, -435, 100, 27, 717, 543, 886, +710, 489, 418, -45, -96, -302, -512, -226, +-593, -230, -442, -512, -149, -783, 238, -594, +554, 225, 600, 1211, 284, 1615, -209, 1004, +-460, -279, -278, -1403, 26, -1590, 188, -874, +-22, 133, -322, 805, -391, 907, -45, 597, +447, 166, 717, -153, 542, -262, -52, -191, +-428, -151, -545, -183, -390, -247, -341, -209, +-223, -37, 162, 250, 759, 517, 995, 588, +449, 211, -503, -514, -1043, -987, -722, -661, +0, 342, 474, 1147, 490, 1001, 306, 29, +129, -877, -101, -1148, -361, -666, -445, 115, +-170, 822, 256, 1109, 478, 744, 281, -92, +-111, -862, -358, -1003, -330, -524, -62, 207, +243, 592, 373, 548, 238, 213, -55, -95, +-358, -199, -327, -112, -85, 2, 193, -7, +219, -111, 38, -233, -180, -159, -122, -7, +153, 230, 363, 368, 338, 376, -18, 203, +-378, -81, -584, -384, -466, -600, -142, -568, +371, -227, 709, 431, 678, 926, 239, 780, +-371, 18, -643, -708, -540, -715, -118, -127, +239, 383, 439, 340, 306, 7, -16, -242, +-343, -278, -388, -215, -12, -36, 435, 378, +541, 739, 158, 579, -321, -144, -584, -854, +-396, -931, -72, -363, 264, 335, 408, 726, +398, 659, 194, 264, -90, -248, -370, -525, +-471, -387, -332, 25, 43, 266, 447, 146, +609, -106, 324, -201, -219, -100, -591, 64, +-487, 216, 3, 351, 404, 333, 419, -22, +24, -455, -353, -600, -360, -238, 32, 224, +486, 403, 492, 207, 18, -46, -518, -191, +-554, -188, -140, 30, 307, 388, 391, 639, +184, 322, 7, -484, -144, -1160, -253, -1026, +-277, -156, -17, 837, 387, 1266, 526, 971, +162, 222, -392, -585, -585, -1017, -324, -864, +121, -258, 376, 324, 342, 568, 151, 436, +-134, 189, -353, -19, -232, -153, 153, -104, +492, 57, 378, 147, -229, -85, -760, -486, +-668, -603, 23, -127, 743, 592, 944, 912, +373, 543, -413, -190, -839, -667, -633, -602, +-40, -169, 447, 205, 549, 277, 387, 86, +112, -34, -307, -9, -599, 96, -575, 63, +-9, 2, 689, 36, 848, 142, 205, 38, +-611, -321, -854, -534, -308, -260, 449, 348, +679, 656, 312, 398, -252, -141, -484, -438, +-301, -338, 107, -35, 335, 228, 303, 316, +68, 196, -226, -103, -365, -380, -279, -425, +3, -167, 342, 182, 488, 430, 313, 445, +-112, 252, -431, -54, -468, -300, -200, -317, +127, -155, 302, -79, 274, -181, 110, -257, +-46, -17, -111, 466, -29, 765, 52, 559, +8, -36, -110, -609, -227, -795, -148, -490, +62, 73, 250, 505, 281, 515, 181, 131, +-86, -247, -346, -334, -391, -94, -140, 178, +320, 331, 601, 276, 349, 65, -215, -251, +-646, -486, -570, -393, -87, -69, 442, 277, +594, 404, 385, 368, -8, 193, -374, -107, +-445, -504, -261, -602, 80, -161, 312, 508, +300, 736, 60, 261, -138, -360, -171, -490, +-85, -100, 66, 138, 79, -3, 13, -301, +-63, -208, -111, 238, -45, 571, 141, 481, +306, 36, 226, -365, -59, -499, -403, -316, +-491, -41, -221, 155, 140, 157, 420, 99, +481, 148, 373, 247, 8, 181, -405, -133, +-678, -463, -466, -441, 55, -45, 522, 335, +536, 422, 251, 223, -83, 12, -227, -102, +-268, -218, -256, -375, -141, -386, 33, -97, +225, 371, 260, 677, 221, 536, 73, 78, +-113, -396, -242, -641, -232, -535, -45, -206, +113, 182, 125, 471, -34, 507, -65, 296, +24, -43, 101, -288, 47, -307, 9, -106, +75, 74, 197, 57, 75, -108, -260, -280, +-537, -169, -448, 144, -16, 464, 475, 533, +714, 273, 558, -170, 66, -520, -525, -615, +-823, -377, -607, 71, 39, 477, 661, 639, +804, 380, 320, -130, -383, -596, -783, -597, +-514, -177, 190, 402, 703, 680, 566, 459, +-42, -45, -572, -554, -551, -688, -51, -369, +442, 241, 592, 664, 229, 525, -349, -94, +-702, -547, -532, -343, 93, 257, 665, 540, +699, 111, 213, -519, -262, -620, -450, -65, +-314, 545, -139, 679, -21, 291, 114, -206, +264, -548, 220, -642, -14, -432, -244, 79, +-272, 650, -3, 887, 270, 576, 404, -109, +251, -676, -132, -787, -540, -462, -646, 52, +-290, 384, 298, 424, 732, 244, 608, 52, +107, -22, -442, -30, -609, -48, -327, -95, +167, -143, 496, -186, 345, -172, -93, -5, +-445, 268, -324, 460, 48, 276, 349, -189, +225, -552, -101, -466, -241, -10, -82, 443, +218, 564, 310, 306, 91, -169, -265, -549, +-382, -507, -239, -39, 102, 483, 224, 499, +94, -17, -62, -558, 14, -484, 210, 130, +289, 655, 15, 602, -362, 34, -434, -510, +-169, -630, 162, -273, 273, 218, 128, 460, +-78, 221, -68, -240, 31, -449, 145, -73, +121, 549, -54, 761, -198, 223, -233, -604, +-66, -955, 84, -545, 182, 239, 87, 654, +-21, 521, -76, 110, -7, -96, 70, -53, +47, -45, -73, -269, -192, -522, -159, -367, +41, 209, 243, 785, 259, 788, 66, 207, +-147, -451, -222, -719, -159, -583, -105, -314, +-109, -20, -62, 364, 172, 780, 485, 871, +520, 384, 78, -452, -544, -1055, -837, -970, +-455, -245, 269, 573, 692, 936, 461, 630, +-121, -53, -431, -541, -241, -505, 214, -102, +353, 198, 124, 127, -236, -111, -364, -150, +-242, 114, -33, 441, 118, 480, 230, 152, +327, -399, 210, -805, -50, -805, -355, -256, +-362, 523, -139, 1039, 134, 923, 193, 237, +141, -491, 112, -822, 58, -610, -96, -153, +-329, 209, -335, 260, -4, 137, 398, 82, +468, 194, 113, 323, -335, 206, -475, -181, +-236, -534, 131, -553, 315, -215, 233, 251, +-4, 502, -156, 480, -169, 225, -32, -72, +96, -274, 88, -351, -18, -363, -164, -339, +-217, -143, -118, 279, 206, 784, 471, 894, +438, 363, -12, -529, -589, -1139, -778, -984, +-410, -231, 254, 569, 665, 939, 619, 755, +258, 213, -135, -313, -429, -578, -497, -489, +-329, -199, -4, 76, 261, 194, 295, 172, +98, 64, -48, -29, 14, 62, 136, 296, +130, 452, -126, 158, -420, -556, -484, -1108, +-171, -860, 321, 169, 629, 1193, 522, 1379, +33, 614, -462, -459, -668, -1115, -410, -1058, +59, -456, 479, 260, 492, 758, 134, 813, +-254, 434, -324, -61, -93, -401, 150, -467, +107, -408, -130, -289, -179, -54, -19, 336, +98, 655, 34, 584, -96, 84, -13, -497, +258, -675, 363, -375, 57, 101, -433, 344, +-722, 268, -476, 77, 181, 42, 772, 118, +836, 111, 249, -113, -561, -415, -900, -465, +-498, -163, 224, 312, 633, 600, 397, 530, +-131, 144, -415, -331, -249, -650, 133, -613, +327, -139, 151, 471, -233, 765, -400, 458, +-202, -206, 240, -613, 446, -442, 216, 74, +-199, 434, -404, 349, -272, -40, -33, -403, +128, -467, 204, -170, 258, 346, 229, 718, +-38, 596, -374, -2, -510, -676, -241, -876, +157, -481, 394, 183, 350, 670, 113, 724, +-103, 358, -203, -211, -235, -625, -205, -579, +-104, -54, 21, 517, 115, 585, 185, 62, +177, -524, 120, -579, 15, -49, -176, 481, +-333, 497, -334, 50, -97, -358, 218, -340, +385, -12, 239, 269, -26, 282, -162, 75, +-159, -187, -135, -369, -133, -347, -63, -76, +91, 347, 192, 599, 77, 416, -121, -94, +-149, -536, 26, -565, 150, -224, 34, 195, +-155, 422, -178, 380, 5, 158, 189, -141, +127, -312, -139, -262, -362, -19, -260, 151, +136, 73, 531, -116, 513, -165, 21, 67, +-553, 353, -692, 417, -299, 149, 189, -272, +402, -552, 301, -510, 156, -182, 75, 242, +-30, 512, -266, 520, -435, 286, -334, -60, +-16, -359, 283, -499, 361, -378, 228, -67, +25, 270, -118, 402, -226, 313, -216, 134, +-159, -28, -64, -184, 21, -368, 75, -458, +98, -252, 168, 235, 257, 684, 172, 718, +-92, 247, -478, -406, -629, -807, -374, -693, +209, -198, 633, 354, 643, 620, 267, 535, +-225, 265, -543, -19, -562, -251, -254, -450, +121, -529, 373, -352, 295, 76, 53, 510, +-130, 647, -134, 431, -57, 16, -2, -345, +26, -534, 15, -525, -39, -268, -175, 153, +-204, 540, -17, 624, 237, 330, 274, -121, +61, -442, -193, -430, -246, -215, -114, 30, +32, 129, 81, 115, 73, 82, 13, 105, +-57, 174, -126, 191, -72, 70, 73, -178, +106, -408, -31, -440, -162, -169, -129, 261, +54, 596, 233, 546, 178, 125, -78, -399, +-304, -675, -341, -492, -146, 3, 156, 504, +350, 612, 307, 284, 92, -201, -202, -416, +-384, -227, -405, 76, -145, 144, 244, -74, +533, -257, 427, -145, -50, 168, -538, 389, +-670, 334, -311, 86, 218, -165, 602, -313, +532, -304, 138, -137, -321, 124, -520, 263, +-320, 166, 45, -97, 195, -231, 26, -85, +-151, 188, -136, 326, 128, 174, 374, -103, +366, -281, 73, -239, -309, -89, -582, 35, +-528, 65, -141, 67, 338, 75, 540, 100, +327, 95, -44, 60, -261, 3, -212, -93, +-21, -187, 86, -201, 25, -59, -139, 142, +-276, 227, -232, 110, 57, -68, 368, -91, +426, 25, 127, 78, -262, -52, -410, -207, +-260, -153, -21, 69, 115, 246, 136, 228, +89, 84, 51, -45, -9, -192, -49, -316, +-82, -315, -116, -11, -102, 427, -47, 596, +32, 258, 62, -344, 36, -640, -18, -377, +45, 200, 125, 517, 49, 346, -136, -84, +-287, -358, -280, -264, -101, -2, 127, 179, +247, 163, 293, 53, 211, -19, -23, -34, +-298, -47, -433, -72, -296, -77, 52, -8, +346, 86, 344, 153, 20, 98, -361, -69, +-406, -234, -37, -216, 413, 39, 456, 288, +74, 289, -402, 15, -483, -238, -201, -214, +134, 14, 200, 138, 65, 57, 8, -118, +41, -155, 95, -79, 25, 57, -100, 223, +-205, 370, -131, 338, 8, -66, 95, -595, +40, -803, -94, -353, -143, 392, -51, 820, +125, 621, 215, 92, 148, -270, -13, -339, +-172, -289, -327, -299, -355, -265, -128, -26, +244, 354, 471, 577, 348, 418, -78, -30, +-400, -398, -345, -437, -50, -147, 163, 160, +145, 230, -37, 46, -174, -194, -135, -235, +26, -52, 237, 247, 304, 387, 136, 279, +-237, -14, -505, -278, -452, -341, -60, -227, +377, -75, 520, 9, 260, 50, -137, 121, +-329, 247, -230, 331, -1, 301, 46, 76, +-120, -270, -248, -614, -41, -671, 307, -325, +471, 279, 242, 767, -212, 800, -482, 407, +-436, -180, -175, -628, 42, -764, 257, -485, +385, 69, 419, 573, 174, 658, -263, 268, +-603, -199, -607, -343, -239, -184, 225, -24, +532, -61, 505, -90, 254, 91, -85, 307, +-330, 271, -399, -60, -320, -309, -159, -281, +17, -63, 205, 70, 326, 97, 318, 154, +111, 226, -153, 181, -349, -52, -317, -291, +-109, -337, 108, -173, 190, 55, 147, 236, +44, 292, -84, 199, -162, -17, -158, -191, +-57, -203, 80, -108, 172, -41, 139, -30, +25, 87, -63, 287, -138, 343, -222, 35, +-251, -416, -93, -557, 171, -213, 372, 306, +284, 515, -40, 306, -267, -58, -206, -238, +-41, -150, -6, 1, -128, 5, -171, -151, +44, -247, 350, -65, 388, 285, 124, 472, +-297, 248, -520, -188, -415, -411, -37, -270, +348, 39, 511, 169, 338, 132, -93, 44, +-405, 5, -410, -46, -155, -112, 95, -115, +190, -11, 148, 130, 59, 217, -14, 204, +-89, 57, -124, -234, -67, -493, 38, -401, +99, 105, 72, 656, 3, 689, -102, 111, +-202, -600, -210, -803, -38, -337, 246, 368, +360, 755, 155, 540, -230, -44, -363, -540, +-104, -591, 248, -235, 225, 182, -147, 359, +-453, 313, -291, 189, 212, 45, 538, -185, +377, -384, -56, -343, -359, -3, -334, 328, +-132, 323, -41, 70, -11, -138, 89, -85, +258, 53, 289, 80, 104, -58, -250, -223, +-464, -278, -339, -162, 25, 142, 390, 458, +488, 540, 223, 235, -257, -266, -505, -583, +-354, -520, 77, -205, 339, 144, 229, 369, +-61, 438, -166, 288, 7, 0, 146, -249, +72, -283, -181, -145, -263, -43, -113, -28, +179, -24, 307, 82, 180, 198, -122, 215, +-332, 96, -277, -89, 15, -255, 238, -301, +193, -164, 1, 129, -95, 363, 24, 326, +123, 64, 17, -209, -249, -290, -307, -230, +-120, -115, 162, -5, 275, 154, 211, 309, +109, 343, -6, 177, -133, -173, -312, -494, +-307, -569, -61, -237, 321, 346, 454, 726, +220, 550, -221, -45, -494, -549, -304, -584, +163, -223, 472, 162, 313, 324, -120, 277, +-396, 83, -225, -123, 171, -195, 327, -56, +85, 143, -297, 116, -376, -145, -48, -328, +399, -141, 484, 237, 119, 383, -386, 116, +-539, -256, -221, -343, 247, -86, 438, 229, +218, 337, -100, 172, -215, -134, -96, -375, +42, -391, 27, -127, -119, 195, -144, 352, +27, 285, 243, 116, 342, -3, 178, -121, +-141, -286, -363, -395, -279, -277, -22, 67, +186, 414, 169, 493, 78, 224, 78, -163, +126, -434, 51, -425, -164, -161, -272, 173, +-104, 415, 185, 404, 258, 97, 49, -330, +-199, -584, -219, -392, -13, 158, 162, 590, +189, 470, 113, -58, 51, -440, -22, -315, +-142, 59, -284, 135, -249, -111, 2, -239, +319, 48, 433, 448, 269, 419, -76, -61, +-310, -481, -296, -444, -114, -113, 64, 91, +160, 59, 205, 44, 204, 232, 110, 424, +-69, 284, -217, -196, -199, -661, 36, -666, +230, -187, 244, 395, 68, 627, -140, 355, +-223, -126, -110, -389, 105, -279, 245, 39, +257, 240, 81, 142, -143, -153, -283, -383, +-215, -324, 8, 20, 235, 403, 279, 494, +126, 244, -74, -161, -151, -444, -57, -476, +59, -330, 75, -43, -47, 312, -109, 555, +-12, 444, 178, -8, 281, -465, 184, -546, +-16, -237, -198, 115, -209, 229, -117, 117, +60, -16, 205, -40, 242, 19, 151, 98, +58, 96, 39, -57, 31, -266, -21, -353, +-147, -159, -254, 165, -222, 310, 10, 167, +324, -41, 567, -77, 538, -5, 207, -33, +-351, -204, -771, -298, -747, -168, -199, 76, +535, 246, 919, 265, 687, 159, 63, -22, +-429, -251, -508, -375, -252, -264, 7, 19, +104, 237, 109, 199, 160, -14, 246, -178, +257, -126, 166, 58, -10, 212, -153, 155, +-230, -134, -211, -423, -24, -448, 263, -130, +418, 278, 284, 434, 17, 270, -117, 8, +-68, -145, 31, -219, -44, -302, -136, -332, +-31, -165, 259, 178, 405, 386, 192, 266, +-184, -97, -328, -355, -87, -255, 277, 70, +330, 285, 45, 165, -253, -190, -207, -426, +81, -317, 310, 6, 247, 226, 3, 181, +-114, 29, -24, -4, 139, 72, 140, 62, +-40, -107, -182, -307, -89, -372, 168, -252, +382, -44, 382, 202, 165, 377, -105, 368, +-270, 150, -227, -177, -60, -413, 150, -474, +270, -373, 357, -144, 354, 198, 222, 482, +-87, 443, -381, 50, -390, -372, -91, -423, +272, -138, 453, 77, 367, 0, 132, -190, +-66, -160, -154, 93, -149, 276, -65, 184, +75, -98, 166, -331, 168, -375, 119, -191, +68, 135, 35, 420, -30, 402, -40, -22, +64, -548, 255, -754, 278, -430, 54, 185, +-222, 617, -210, 620, 86, 260, 401, -215, +386, -554, 83, -624, -173, -405, -161, -38, +118, 278, 334, 380, 306, 266, 14, 72, +-201, -96, -177, -173, 21, -223, 249, -278, +336, -284, 267, -174, 109, 54, -40, 238, +-122, 241, -126, 99, -42, -43, 89, -120, +173, -191, 212, -288, 156, -301, 114, -102, +54, 193, 34, 291, 7, 88, -19, -234, +-15, -336, -22, -129, 65, 125, 224, 197, +358, 58, 298, -134, 71, -234, -155, -227, +-191, -190, -33, -125, 150, -5, 267, 144, +293, 254, 222, 207, 133, -11, 71, -248, +4, -369, -76, -321, -141, -204, -106, -102, +125, 39, 451, 254, 605, 411, 373, 285, +-137, -142, -508, -581, -439, -642, 20, -261, +459, 234, 506, 454, 178, 242, -158, -163, +-162, -418, 144, -341, 434, -2, 345, 292, +-86, 278, -394, -5, -302, -331, 85, -452, +368, -329, 372, -74, 275, 191, 244, 367, +214, 330, 47, 21, -179, -382, -263, -586, +-99, -390, 182, 26, 341, 295, 347, 255, +289, 26, 207, -142, 82, -147, -93, -115, +-148, -112, -32, -114, 146, -97, 234, -82, +162, -70, 77, -28, 139, 85, 206, 202, +136, 108, -61, -206, -163, -522, -75, -526, +200, -128, 386, 360, 299, 564, 47, 347, +-144, -114, -108, -508, 55, -639, 191, -498, +225, -129, 169, 305, 92, 552, 32, 453, +32, 62, 116, -358, 191, -520, 215, -419, +133, -213, 62, -58, -13, 5, -32, 66, +44, 188, 221, 333, 434, 371, 396, 113, +74, -447, -339, -964, -382, -969, 8, -298, +571, 654, 737, 1156, 350, 829, -231, -44, +-501, -820, -315, -1013, 96, -651, 411, -81, +440, 372, 261, 531, 78, 388, 48, 59, +93, -273, 22, -413, -191, -306, -301, -106, +-80, 9, 403, -1, 681, -67, 503, -41, +43, 56, -279, 87, -205, 26, 36, -110, +191, -232, 105, -272, 53, -235, 143, -76, +353, 186, 430, 380, 240, 281, -44, -151, +-230, -631, -205, -728, 10, -308, 265, 295, +402, 655, 363, 531, 213, 66, 60, -392, +-61, -628, -111, -553, -102, -247, -8, 94, +152, 298, 314, 293, 358, 140, 197, -31, +-24, -137, -143, -199, -9, -201, 206, -173, +249, -171, 17, -204, -176, -216, -94, -67, +258, 276, 506, 555, 423, 457, 59, -87, +-231, -741, -197, -978, 53, -573, 287, 162, +285, 704, 159, 708, 62, 254, 92, -277, +122, -576, 95, -556, 46, -283, 102, 34, +287, 256, 392, 264, 193, 55, -239, -182, +-483, -261, -241, -119, 340, 95, 754, 127, +660, -90, 185, -339, -248, -384, -378, -144, +-267, 228, -58, 417, 191, 269, 361, -120, +426, -497, 300, -573, 67, -293, -116, 126, +-102, 420, 52, 384, 142, 69, 117, -283, +27, -465, 45, -376, 168, -105, 276, 145, +281, 218, 137, 108, -13, -91, -71, -188, +21, -137, 182, -10, 243, 56, 184, -41, +45, -222, -13, -295, 64, -166, 197, 110, +245, 300, 136, 192, 4, -110, -60, -339, +37, -300, 178, -55, 186, 117, 101, 50, +15, -118, 20, -181, 86, -71, 183, 98, +201, 100, 132, -43, -34, -174, -153, -194, +-106, -100, 121, -15, 354, 6, 405, 26, +222, 40, -12, -11, -131, -134, -98, -272, +7, -256, 75, -22, 129, 234, 228, 290, +358, 74, 343, -246, 173, -383, -87, -268, +-229, -50, -157, 97, 56, 82, 266, 10, +321, 1, 244, 26, 107, -8, 72, -109, +47, -217, 46, -203, 16, -68, 12, 25, +15, 11, 66, -53, 137, -37, 218, 101, +215, 160, 112, -6, -26, -289, -119, -440, +-43, -267, 99, 95, 236, 335, 237, 283, +163, 14, 56, -273, -4, -368, -21, -250, +-46, -29, 6, 167, 120, 198, 284, 55, +382, -103, 310, -172, 90, -131, -171, -78, +-352, -115, -264, -143, 58, -57, 469, 123, +644, 242, 487, 148, 68, -101, -293, -287, +-367, -313, -182, -224, 108, -93, 260, 30, +302, 176, 277, 276, 229, 177, 109, -86, +-41, -338, -167, -371, -162, -172, -45, 45, +93, 107, 247, 58, 317, 15, 256, 18, +63, 10, -77, -79, -96, -155, 47, -133, +137, -71, 111, -48, 15, -62, 12, -30, +121, 92, 222, 147, 177, 16, 82, -201, +67, -289, 86, -143, 69, 66, -68, 127, +-114, 25, 20, -69, 273, -94, 392, -77, +303, -80, 65, -58, -98, 40, -117, 123, +-108, 34, -81, -199, 7, -387, 199, -285, +424, 85, 471, 432, 205, 476, -196, 129, +-465, -389, -376, -708, -20, -582, 383, -85, +572, 468, 450, 666, 94, 371, -220, -155, +-278, -515, -93, -463, 129, -124, 173, 120, +49, 83, -22, -108, 95, -159, 296, 61, +374, 314, 155, 299, -132, -8, -264, -351, +-126, -472, 119, -298, 285, -19, 281, 194, +152, 268, 18, 162, -67, -46, -26, -224, +71, -226, 152, -16, 153, 176, 95, 109, +19, -156, -26, -365, -48, -284, -20, 42, +46, 307, 147, 306, 232, 91, 216, -158, +85, -255, -44, -215, -58, -139, 5, -53, +57, 27, -9, 93, -82, 113, -36, 33, +157, -88, 341, -142, 367, -85, 204, 24, +-18, 89, -192, 26, -273, -126, -236, -249, +-70, -267, 249, -89, 557, 214, 626, 437, +329, 380, -166, -5, -520, -464, -520, -659, +-205, -472, 214, -19, 537, 414, 575, 594, +330, 442, -38, 18, -289, -454, -325, -655, +-97, -453, 149, -1, 260, 363, 180, 378, +54, 142, 8, -80, 37, -139, 78, -101, +77, -104, 27, -175, 4, -180, 27, -50, +46, 123, 2, 203, -54, 117, -2, -43, +179, -125, 362, -106, 321, -78, 41, -94, +-275, -134, -332, -77, -73, 78, 229, 186, +349, 143, 215, -38, 35, -204, -56, -200, +-21, -77, 20, 48, 40, 77, 75, 22, +141, -51, 135, -85, 0, -98, -164, -74, +-131, 7, 128, 104, 422, 146, 426, 27, +79, -174, -320, -265, -467, -146, -256, 60, +134, 138, 430, 5, 462, -135, 275, -81, +1, 114, -221, 209, -278, 79, -161, -176, +80, -316, 231, -262, 251, -108, 176, 74, +72, 205, -2, 255, -1, 186, 24, -8, +3, -222, -81, -323, -149, -290, -79, -148, +185, 32, 457, 214, 492, 327, 149, 260, +-325, -1, -501, -295, -277, -422, 190, -296, +497, -3, 428, 221, 55, 255, -257, 108, +-282, -83, -40, -157, 256, -93, 347, 4, +172, 14, -174, -96, -357, -202, -191, -123, +193, 124, 491, 301, 446, 217, 25, -132, +-360, -414, -384, -346, -20, 27, 347, 360, +389, 320, 79, -46, -242, -359, -259, -343, +-14, -55, 281, 229, 306, 266, 157, 97, +-47, -105, -132, -205, -89, -196, 44, -107, +104, -3, 122, 101, 89, 133, 22, 73, +-14, -27, 7, -107, 68, -100, 83, -27, +43, 14, -30, -18, -56, -74, -63, -106, +44, -54, 144, 32, 183, 105, 161, 137, +77, 116, -88, -9, -200, -197, -132, -345, +62, -283, 261, 3, 238, 265, 57, 294, +-154, 103, -156, -86, 37, -99, 195, -14, +96, -41, -55, -177, -95, -260, 37, -148, +204, 85, 221, 231, 43, 215, -130, 130, +-112, 40, 29, -61, 159, -211, 91, -358, +-17, -328, -98, -74, -47, 236, 111, 389, +202, 280, 140, 36, -4, -144, -105, -198, +-122, -196, -2, -199, 100, -180, 133, -66, +89, 135, 57, 270, 53, 287, 59, 162, +-28, -34, -120, -219, -186, -353, -84, -381, +146, -217, 298, 88, 264, 380, 100, 467, +-76, 254, -182, -111, -153, -370, -99, -379, +7, -194, 161, 10, 299, 99, 312, 137, +103, 149, -162, 124, -299, 9, -240, -139, +-52, -177, 181, -67, 266, 47, 200, 19, +76, -108, -49, -158, -88, -4, -4, 216, +71, 256, 44, 53, -107, -219, -151, -317, +4, -146, 237, 104, 333, 220, 173, 115, +-163, -98, -372, -199, -250, -94, 40, 78, +273, 155, 321, 67, 170, -87, -47, -154, +-209, -124, -181, -41, -2, 62, 195, 146, +269, 157, 132, 48, -144, -167, -304, -303, +-190, -223, 71, 29, 279, 270, 321, 302, +178, 118, -35, -101, -231, -247, -318, -257, +-228, -149, 62, 9, 387, 163, 472, 230, +214, 131, -166, -51, -376, -164, -270, -142, +23, -9, 235, 58, 178, 24, -25, -51, +-163, -90, -116, -71, 105, 2, 322, 88, +320, 167, 22, 157, -351, -8, -488, -222, +-263, -291, 189, -131, 544, 127, 519, 219, +146, 69, -252, -103, -425, -113, -349, 56, +-103, 189, 156, 111, 293, -100, 246, -239, +108, -216, -26, -71, -95, 59, -49, 122, +11, 164, -35, 176, -137, 106, -115, -54, +49, -225, 222, -270, 288, -124, 168, 68, +-57, 163, -290, 111, -359, -7, -234, -37, +45, 26, 371, 82, 510, 66, 282, -32, +-165, -144, -478, -192, -425, -154, -53, -31, +331, 163, 413, 290, 170, 260, -160, 41, +-307, -233, -181, -347, 64, -218, 221, 58, +161, 263, -56, 249, -187, 40, -128, -167, +73, -223, 221, -78, 199, 131, -26, 231, +-217, 111, -248, -134, -86, -295, 142, -164, +277, 156, 255, 363, 43, 249, -233, -113, +-389, -386, -298, -337, -7, -26, 335, 280, +449, 387, 254, 232, -60, -46, -294, -305, +-340, -367, -203, -165, 31, 141, 222, 300, +277, 211, 155, -21, -30, -153, -201, -79, +-194, 44, -44, 79, 88, 3, 41, -86, +-55, -110, -88, -58, 8, 34, 170, 162, +236, 230, 114, 126, -157, -111, -350, -313, +-305, -263, -33, 31, 272, 308, 399, 332, +194, 80, -150, -218, -331, -310, -241, -153, +-16, 96, 149, 249, 146, 214, 31, 69, +-29, -73, -26, -171, 22, -173, -12, -61, +-22, 94, -11, 175, -12, 121, -48, -32, +-50, -104, -48, -46, 2, 70, 80, 112, +80, 18, 29, -94, -31, -96, -71, -21, +-125, 63, -141, 84, -48, 35, 164, 4, +289, -6, 196, -2, -101, 7, -363, 34, +-332, 50, -46, 54, 200, -26, 225, -137, +128, -168, -11, -60, -59, 172, -107, 333, +-155, 244, -183, -14, -43, -225, 171, -257, +253, -128, 115, -6, -87, 76, -173, 156, +-127, 222, -16, 197, 21, 41, -56, -172, +-96, -251, 19, -145, 144, 23, 151, 149, +32, 160, -129, 103, -208, 49, -117, 18, +19, -39, 60, -130, 29, -175, 39, -62, +83, 149, 80, 273, -2, 224, -171, 16, +-275, -175, -179, -189, 50, -84, 214, -7, +213, 12, 76, 61, -96, 197, -192, 302, +-174, 172, -66, -135, 23, -366, 80, -328, +110, -19, 78, 283, -10, 320, -119, 146, +-177, -65, -92, -145, 55, -37, 119, 89, +53, 108, -82, -5, -184, -137, -132, -155, +56, -44, 209, 113, 206, 258, 27, 267, +-231, 89, -354, -136, -237, -246, 36, -190, +269, -31, 311, 141, 156, 238, -111, 214, +-318, 34, -338, -136, -192, -190, 29, -90, +228, 92, 305, 213, 176, 198, -44, 62, +-262, -108, -369, -199, -256, -138, 33, 2, +301, 150, 333, 230, 113, 202, -190, 71, +-364, -96, -296, -216, -22, -186, 220, -26, +242, 162, 96, 256, -137, 161, -256, -32, +-153, -139, 49, -83, 135, 54, 93, 129, +-29, 65, -153, -34, -184, -92, -95, -62, +74, 76, 163, 201, 114, 184, -49, 33, +-240, -139, -267, -202, -66, -89, 162, 111, +169, 239, -2, 179, -130, 0, -117, -94, +-9, -29, 57, 50, -18, 10, -155, -99, +-175, -92, -19, 102, 139, 293, 141, 261, +-24, -2, -173, -231, -211, -243, -106, -101, +67, 85, 165, 213, 91, 285, -51, 223, +-192, -2, -242, -254, -133, -294, 90, -81, +241, 196, 180, 287, -48, 152, -264, -44, +-318, -103, -200, -17, 48, 74, 246, 111, +229, 36, 35, -79, -196, -127, -345, -41, +-237, 132, 54, 252, 239, 170, 170, -30, +-55, -145, -240, -123, -236, 21, -81, 134, +91, 99, 168, 2, 55, -22, -154, 33, +-279, 93, -201, 34, 24, -37, 191, 0, +158, 98, 16, 157, -164, 73, -260, -124, +-187, -210, -43, -72, 95, 176, 171, 303, +66, 200, -174, -7, -288, -173, -121, -134, +87, 31, 132, 107, 18, 64, -142, 13, +-205, 29, -129, 89, 10, 94, 65, 25, +33, -33, -43, -36, -118, 35, -115, 93, +-59, 27, 16, -27, -4, 28, -99, 84, +-155, 66, -105, 1, -8, -16, 61, 51, +74, 96, -34, 61, -193, -35, -200, -68, +-96, 38, -2, 140, 47, 111, 56, -27, +44, -75, -33, 3, -154, 83, -276, 123, +-275, 93, -103, -27, 175, -75, 314, -30, +201, 83, -60, 191, -343, 137, -520, -56, +-419, -194, -18, -122, 369, 99, 454, 269, +201, 262, -169, 154, -429, -51, -401, -262, +-235, -289, -79, -99, 39, 165, 130, 335, +184, 325, 119, 208, -20, 36, -181, -153, +-312, -282, -378, -299, -284, -104, -58, 214, +250, 437, 440, 403, 288, 130, -180, -164, +-559, -267, -587, -181, -269, 7, 166, 135, +403, 155, 282, 109, -61, 56, -348, 36, +-396, 56, -174, 106, 99, 83, 146, -31, +-49, -162, -224, -197, -222, -42, -66, 263, +105, 474, 138, 356, -6, -75, -225, -458, +-356, -437, -317, -38, -108, 380, 184, 475, +293, 289, 105, 10, -200, -231, -380, -310, +-365, -158, -185, 119, 89, 297, 232, 294, +112, 119, -146, -100, -299, -190, -287, -59, +-138, 164, 94, 256, 131, 134, -37, -90, +-171, -251, -236, -190, -241, 98, -89, 341, +90, 380, 58, 205, -52, -39, -84, -244, +-115, -285, -189, -141, -198, 76, -152, 243, +-121, 315, -52, 271, 59, 94, 41, -157, +-58, -264, -102, -99, -136, 132, -192, 280, +-235, 183, -182, -87, -84, -237, -7, -80, +90, 206, 91, 316, -109, 189, -286, -10, +-213, -128, -65, -108, -46, 40, -96, 140, +-209, 89, -217, -36, -31, -114, 130, -76, +38, 129, -151, 337, -195, 385, -144, 206, +-80, -108, -100, -371, -176, -469, -199, -243, +-136, 185, -7, 491, 37, 555, 7, 400, +-21, 89, -113, -241, -269, -464, -348, -407, +-242, -120, -14, 154, 183, 377, 136, 464, +-126, 340, -348, 89, -325, -140, -162, -258, +-28, -241, 77, -113, 75, 54, -34, 205, +-156, 293, -311, 288, -416, 144, -313, -67, +-9, -215, 233, -182, 193, -36, -10, 163, +-161, 289, -284, 235, -336, 59, -247, -68, +-178, -116, -109, -121, -10, -11, 55, 99, +47, 180, -9, 190, -84, 163, -189, 133, +-289, 23, -307, -140, -248, -189, -186, -165, +-67, -58, 99, 147, 263, 396, 180, 551, +-209, 293, -521, -224, -543, -539, -315, -422, +48, 9, 249, 418, 109, 467, -93, 222, +-162, -76, -240, -186, -251, -32, -185, 156, +-111, 139, -117, -16, -115, -125, -58, -116, +-66, 54, -58, 245, -39, 325, -90, 220, +-264, -53, -312, -251, -182, -202, -121, 4, +-44, 198, 50, 277, 3, 177, -111, 33, +-165, -33, -231, -63, -290, -55, -187, -13, +-57, 10, 28, 156, -39, 318, -172, 212, +-188, -58, -127, -260, -40, -158, -91, 105, +-254, 202, -286, 117, -104, 81, 43, 186, +-22, 229, -181, -58, -254, -429, -184, -333, +-26, 241, 54, 668, -70, 408, -247, -155, +-352, -384, -345, -171, -95, 90, 225, 181, +233, 178, -101, 193, -444, 124, -509, -76, +-206, -181, 145, -71, 179, 161, -88, 230, +-340, 49, -311, -81, -147, 58, 18, 203, +95, 130, -31, -89, -232, -179, -328, -16, +-257, 233, -171, 287, -118, 24, -64, -195, +26, -136, 35, 115, -57, 370, -118, 327, +-244, -34, -347, -316, -332, -260, -231, 84, +-103, 262, 102, 118, 237, 99, 97, 194, +-170, 106, -381, -66, -457, -54, -362, 67, +-107, 20, 103, -199, 70, -157, -16, 235, +-111, 483, -195, 332, -156, -55, -95, -315, +-172, -207, -316, 106, -242, 218, -119, 86, +51, -59, 193, 5, 76, 179, -296, 249, +-556, 67, -408, -223, -72, -171, 189, 160, +177, 353, -45, 141, -222, -209, -235, -203, +-206, 150, -281, 317, -372, 113, -234, -213, +112, -184, 344, 196, 262, 369, -108, 208, +-511, -31, -625, -167, -399, -205, -66, -150, +119, 18, 110, 295, 73, 420, 62, 280, +-64, 49, -300, -130, -411, -272, -352, -307, +-148, -98, -34, 279, -48, 455, -38, 208, +61, -81, 92, -31, -53, 197, -236, 92, +-406, -298, -370, -323, -261, 133, -182, 412, +106, 123, 422, -137, 261, 126, -315, 397, +-647, 95, -438, -401, -54, -338, 65, 227, +-48, 413, -111, -29, -70, -311, 72, 52, +19, 569, -297, 419, -418, -288, -178, -602, +38, -70, -103, 472, -226, 273, -77, -202, +27, -152, -10, 286, 40, 378, -27, 26, +-390, -229, -522, -187, -263, -45, 14, 145, +98, 261, 206, 212, 142, -17, -209, -186, +-377, -40, -290, 216, -280, 140, -164, -141, +76, -76, 35, 278, -144, 272, -52, -166, +87, -285, -58, 116, -284, 343, -355, 32, +-323, -240, -159, 3, 108, 356, 188, 205, +19, -135, -206, -158, -222, -7, -128, 128, +-145, 111, -265, 36, -266, 66, -117, 3, +167, -92, 254, 92, -119, 297, -321, 182, +-225, -114, -168, -200, -185, 2, -160, 22, +-107, -156, 87, 30, 179, 491, -109, 493, +-275, -9, -176, -378, -172, -285, -184, 22, +-150, 75, -72, -69, 73, 116, 63, 505, +-183, 371, -181, -109, -66, -346, -242, -226, +-194, 10, -10, 70, -85, 98, -112, 333, +-17, 280, -15, -96, -106, -228, -177, -131, +-199, 102, -109, 222, -47, 60, -90, 2, +-194, 78, -147, 27, 120, -9, 170, -54, +-185, -48, -458, 90, -292, 194, 28, 188, +86, 22, -45, -160, -87, -120, -11, 140, +4, 285, -190, 21, -359, -314, -265, -181, +-89, 179, 99, 399, 185, 341, 15, 59, +-164, -144, -292, -272, -324, -363, -120, -78, +94, 349, 62, 438, -124, 257, -307, -24, +-220, -178, 130, -140, 238, -32, 91, 115, +-221, 108, -664, -74, -615, -112, 52, 49, +506, 269, 351, 287, 60, 85, -264, -86, +-530, -161, -472, -154, -151, -99, 149, 44, +267, 313, 107, 337, -257, 14, -423, -186, +-103, -132, 248, 41, 136, 135, -240, 54, +-400, 68, -266, 85, -64, -106, 69, -143, +64, 62, 64, 240, 25, 222, -207, -13, +-391, -178, -165, -41, 70, 59, 30, 71, +-123, 107, -194, 58, -30, -52, 63, -31, +-229, 76, -260, 57, 69, -54, 181, 32, +23, 262, -296, 187, -439, -175, -83, -298, +152, -50, -52, 100, -116, 187, -11, 298, +-53, 182, -36, -94, -70, -252, -298, -243, +-140, -2, 177, 332, -21, 375, -290, 57, +-166, -260, -162, -224, -105, 13, 184, 116, +284, 191, -9, 283, -388, 80, -472, -222, +-234, -292, -37, -80, 138, 267, 222, 354, +68, 78, -118, -82, -252, -82, -448, -134, +-293, -103, 245, 134, 291, 340, -72, 210, +-173, -144, -172, -213, -406, -11, -214, -17, +250, -48, 271, 272, -9, 416, -267, -27, +-392, -447, -295, -209, 69, 255, 349, 342, +93, 95, -313, -138, -241, -121, -161, 5, +-277, -10, -17, -27, 334, 185, 88, 356, +-188, 140, -182, -293, -127, -328, -246, -85, +-189, 115, 57, 322, 50, 311, -39, -5, +32, -231, -121, -188, -272, 44, 9, 176, +78, 72, -197, 104, -149, 116, -36, -70, +-192, -205, -169, -204, 60, 15, 172, 350, +37, 407, -180, 101, -240, -222, -108, -232, +-67, -58, -122, -99, -80, 5, -65, 249, +30, 212, 66, 62, -154, -108, -150, -97, +10, 177, -113, 136, -69, -24, -28, -64, +-187, -184, -81, -80, -78, -30, -255, -45, +62, 389, 278, 524, -74, 96, -127, -196, +-83, -379, -279, -304, -194, -13, -132, 117, +-132, 237, 137, 261, 167, 40, -57, -32, +82, 30, -106, 84, -531, 61, -236, -113, +114, -251, 22, -179, 108, 26, -62, 213, +-237, 341, -77, 248, 12, -111, -93, -153, +-93, 122, -18, 29, 35, -200, -80, -189, +-294, -82, -222, 143, -146, 132, 77, 93, +440, 487, 145, 391, -422, -371, -331, -722, +-247, -324, -239, 321, 180, 484, 427, 105, +-33, 7, -309, 89, -232, -153, -161, -215, +-75, 35, -98, 199, 122, 104, 326, 61, +-54, -36, -535, -189, -341, -119, -6, 146, +124, 166, 180, 112, -62, 56, -315, -79, +-57, -98, 57, -8, -102, 197, -44, 145, +83, -232, -134, -179, -465, 137, -285, -3, +258, -14, 402, 246, -47, 256, -194, 56, +-208, -165, -294, -237, -90, -137, 123, -13, +-28, 144, -166, 138, -21, 61, 82, 206, +-160, 210, -146, -148, 151, -288, -125, -113, +-470, -33, 77, 17, 398, 293, -297, 367, +-291, -74, 201, -341, -182, -133, -367, 169, +213, 188, 145, -63, -111, -134, 56, 140, +-194, 229, -362, -4, -68, -299, -9, -225, +-52, 274, 78, 368, 95, -44, -8, -130, +-239, 17, -261, -31, 22, -165, 52, 50, +-171, 304, -56, 72, -7, -174, -192, -41, +130, -18, 260, -17, -347, 163, -419, 153, +1, -33, -31, -158, 94, -46, 298, 108, +-98, 82, -362, -21, -145, -38, -172, 79, +-191, 168, 65, -72, 132, -277, 76, 88, +92, 317, 6, 51, -361, -157, -345, -45, +-31, 21, 32, -66, -97, -51, -125, 176, +45, 250, 287, -19, 215, -164, -178, -78, +-484, -90, -377, -21, -16, 308, 114, 302, +-38, -188, 95, -324, 181, -12, -149, 119, +-33, 3, -14, 86, -414, 246, -229, 133, +203, -176, -69, -318, -253, -71, 183, 181, +277, 155, -138, 136, -150, 77, -45, -253, +-423, -231, -270, 171, 428, 308, 149, 208, +-384, -5, -46, -383, 109, -400, -124, 28, +-20, 321, 171, 459, -192, 374, -529, -211, +-106, -658, 255, -353, 96, 315, 131, 515, +167, 84, -305, -203, -560, 54, -210, 53, +206, -284, 192, -116, 72, 291, 92, 225, +-105, -44, -408, -151, -133, -63, 115, 164, +-155, 50, -12, -276, 341, 61, -195, 318, +-454, -54, 234, -178, 158, 124, -333, 33, +47, -73, 61, 66, -411, 244, -43, -21, +216, -375, -19, -98, -11, 251, -70, -20, +-139, 15, 52, 377, -130, 207, -217, -325, +15, -362, -53, 107, -67, 274, 259, -239, +96, -289, -286, 325, -224, 502, 47, -46, +15, -165, -216, 123, -147, -113, 164, -474, +196, -99, -19, 373, -224, 229, -123, -34, +-39, 69, -168, 269, 45, -83, 324, -426, +-143, -199, -464, 135, 61, 258, 281, 170, +-155, -144, -109, -84, 167, 241, -131, 6, +-285, -262, 65, 69, -47, 267, -160, -159, +285, -324, 230, 112, -325, 335, -339, 81, +39, -58, 108, -76, -74, -85, -17, -116, +84, -39, 13, 177, -77, 304, -296, 66, +-201, -166, 292, -223, 215, -125, -141, 66, +-116, 125, -157, 102, -175, 169, 53, 157, +27, -177, 46, -364, 221, -71, 63, 399, +-230, 178, -383, -367, -348, -213, 120, 340, +475, 327, 235, -103, -132, -212, -58, 14, +-297, 85, -482, -109, 146, -127, 386, -61, +-148, 50, -48, 259, 242, 330, -165, 155, +-271, -118, 191, -451, 42, -465, -358, -108, +-92, 327, 222, 447, -69, 346, -73, 192, +377, -120, 113, -517, -440, -324, -316, -90, +33, -143, -15, 216, -74, 716, 257, 457, +412, -258, -118, -525, -444, -270, -23, 102, +93, 135, -391, -46, -58, -118, 470, 236, +-15, 219, -219, -111, 224, 53, 18, 195, +-240, -119, 23, -338, -65, -298, -219, -9, +-46, 344, -3, 360, 191, 207, 402, -150, +17, -269, -377, -58, -297, -192, -28, -206, +-17, 447, 22, 557, 248, -242, 238, -674, +-116, -85, -286, 617, -188, 175, -38, -386, +173, -31, 238, 459, -90, -42, -242, -722, +75, -417, 101, 776, -148, 748, -22, -264, +137, -670, -221, 71, -121, 388, 172, -253, +90, -499, 65, 433, 151, 646, -282, -182, +-327, -569, 124, -184, 118, 383, -108, 261, +196, -209, 176, -205, -234, 204, -196, 177, +16, -111, 105, -306, 170, 98, -89, 249, +-376, -101, 184, -292, 342, 107, -218, 466, +-300, 195, 150, -658, 158, -437, -122, 596, +-136, 447, 399, -672, 239, -451, -537, 865, +-424, 666, 349, -895, 174, -739, -356, 781, +136, 530, 651, -772, -30, -511, -579, 891, +-128, 631, -47, -839, -11, -697, 314, 683, +107, 504, -50, -427, 104, -270, -227, 270, +-305, 132, 119, -343, 259, -274, 199, 288, +82, 550, -365, 56, -481, -500, 195, -443, +461, 258, -44, 417, -88, -222, 211, -363, +-89, 325, -276, 470, -46, -266, 123, -580, +112, 141, -39, 527, -51, -177, 127, -574, +148, 58, -216, 643, -251, 156, 326, -517, +370, -314, -429, 372, -381, 292, 336, -358, +243, -506, -203, 269, -22, 644, 235, -77, +84, -414, -203, 138, -202, 176, -12, -404, +166, -494, 238, 156, -74, 767, -157, 249, +130, -399, 56, -105, -300, 146, -67, -436, +323, -532, 342, 292, -108, 674, -383, 73, +-78, -146, 296, 163, -30, -309, -95, -681, +108, 207, 12, 679, -13, -256, 144, -569, +-17, 535, 36, 741, 106, -596, -256, -906, +-379, 249, 171, 698, 421, 5, 99, -438, +-76, -77, 37, 355, -40, -21, -160, -425, +7, 32, 186, 507, 58, 20, -286, -626, +-178, -358, 491, 593, 353, 631, -444, -355, +-169, -659, 543, 67, 83, 375, -602, -102, +-74, -244, 408, 195, -81, 236, -61, -279, +560, -313, 63, 319, -631, 342, -77, -455, +500, -482, -16, 629, -380, 456, 171, -915, +636, -555, -58, 997, -757, 608, -89, -718, +648, -652, 179, 415, -297, 631, -45, -291, +116, -915, 163, -69, 162, 884, -273, 614, +-272, -500, 403, -947, 130, -12, -346, 964, +103, 202, 361, -931, -2, -377, 112, 742, +-40, 374, -303, -635, -47, -413, 187, 517, +-70, 469, 128, -296, 432, -401, 102, 41, +-424, -26, -17, -247, 350, 115, -89, 353, +-345, 27, 122, -259, 349, -57, 145, 270, +-120, 13, -95, -608, 196, -308, 177, 446, +-58, 428, -276, -94, -168, -307, 365, -11, +474, 294, -336, -138, -250, -465, 570, 23, +120, 242, -620, -2, 96, -95, 530, 123, +-150, 93, -191, -69, 466, -227, 134, -83, +-552, 46, -125, -77, 439, -300, 296, 313, +26, 757, 8, -320, -103, -1015, -73, 189, +37, 713, 52, -329, 17, -586, 123, 395, +253, 690, 131, -394, -173, -784, -235, 84, +150, 524, 452, 19, 89, -98, -298, 41, +-43, -102, 170, -364, -28, -235, -107, 108, +289, 341, 499, 222, 135, 89, -399, -78, +-315, -367, 174, -451, 244, -125, -158, 230, +207, 319, 645, 187, -153, -171, -713, -132, +254, 71, 712, -61, -42, -259, -480, -143, +67, 12, 513, 202, 28, 95, -458, -151, +-17, -143, 728, 56, 479, 146, -405, 123, +-609, -194, 137, -417, 477, -71, 129, 202, +-118, 71, 149, 37, 286, 185, 145, -191, +-166, -404, -286, 53, -47, 367, 467, -159, +278, -349, -202, 171, -47, 323, 453, -394, +294, -318, -412, 452, -386, 271, 421, -681, +494, -330, -188, 729, -254, 409, 156, -797, +445, -613, 288, 648, -35, 730, -238, -558, +-86, -869, 97, 263, 68, 660, -17, -151, +352, -389, 415, 11, 2, 190, 6, 115, +14, -144, -247, -436, -130, -131, 331, 342, +244, 212, 97, -305, 112, -247, 222, 270, +194, 256, 113, -210, -266, -285, -427, -61, +113, -145, 539, -33, 442, 330, 41, 255, +-176, -420, 177, -435, 370, 231, -364, 552, +-478, -174, 476, -722, 799, -204, -113, 649, +-379, 415, 155, -492, 549, -592, 58, 200, +-336, 396, -66, -231, 412, -306, 252, 204, +-134, 369, 172, -80, 370, -473, 80, -281, +-248, 171, -136, 34, 155, -16, 357, 193, +99, 44, 174, -373, 361, -151, 259, 403, +-351, 331, -541, -519, 34, -724, 953, 130, +401, 623, -524, -19, -70, -439, 623, -16, +236, 484, -365, 190, -49, -417, 484, -564, +329, -228, -318, 310, -195, 411, 240, -105, +274, -401, 273, 139, 451, 304, 119, -176, +-251, -292, -111, 9, 21, -69, -14, -77, +346, 86, 327, 18, 23, -360, 275, -70, +434, 597, -121, 374, -496, -528, 16, -738, +575, -158, 280, 424, -82, 512, 172, -61, +185, -581, -42, -166, 132, 387, 227, -11, +131, -498, -18, 46, 137, 556, 220, 4, +-87, -579, 72, -176, 562, 378, 142, -33, +-317, -381, 28, 28, 207, 75, 293, -83, +375, 308, 142, 164, -139, -425, 80, -357, +10, 139, -141, 142, 211, -155, 614, -291, +158, -15, 142, 276, 279, 322, -126, 11, +-344, -394, 28, -243, 296, 7, 422, -88, +206, -224, -2, -34, 291, 347, 433, 372, +42, -132, -452, -370, -294, -227, 405, 23, +630, 91, 113, -163, -23, -195, 311, 179, +390, 272, -200, -79, -356, -321, 288, -134, +546, 251, -26, 40, -139, -307, 335, -114, +471, 187, 21, 52, -215, -273, 145, -258, +337, 306, 96, 377, -51, -283, 230, -459, +298, 128, 127, 154, 157, -308, 176, -20, +-221, 497, -116, -137, 539, -669, 325, 26, +-132, 524, 228, -129, 585, -473, 20, 226, +-398, 535, -11, -358, 350, -794, 118, 59, +167, 557, 327, 2, 234, -238, 200, 137, +209, 59, -51, -253, -137, -200, -141, -153, +32, -131, 581, 354, 634, 411, 0, -214, +3, -508, 270, -44, -65, 286, -365, -31, +173, -480, 393, -150, 234, 457, 473, 286, +458, -212, -326, -167, -482, -54, 376, -232, +748, -181, -141, 108, -606, 132, 451, -148, +1066, -11, 138, 357, -573, 239, 1, -416, +475, -681, 156, -292, -207, 322, 86, 490, +448, 141, 467, -212, 154, -47, -199, 45, +-57, -350, 376, -515, 111, 148, -76, 463, +257, -46, 459, -208, 21, 198, -230, 140, +374, -349, 545, -239, -185, 133, -283, -176, +472, -366, 435, 335, -174, 552, -128, -266, +458, -428, 437, 284, -30, 144, -38, -582, +263, -349, 53, 302, -19, 185, 242, -25, +332, 163, 37, 34, -79, -321, 459, -291, +379, 131, -183, 177, 9, -264, 505, -293, +-38, 271, -454, 384, 191, -282, 741, -495, +337, 218, 81, 480, 277, -231, -64, -455, +-581, -65, 126, 117, 825, -67, 225, -132, +-292, 84, 413, 421, 674, 106, -328, -329, +-507, -499, 362, -365, 616, 195, 167, 549, +38, 64, 78, -359, 135, -44, 32, 129, +54, -150, 296, -281, 264, 7, 43, 117, +184, 169, 259, 97, -39, -331, -153, -508, +275, 229, 594, 560, 168, -211, -236, -571, +-41, 166, 240, 471, 261, -216, 275, -414, +182, -17, 69, 136, 78, -85, 145, -89, +65, 70, -102, 206, 185, 33, 512, -162, +404, -273, 11, -193, -149, 20, -93, 67, +190, -66, 352, 191, 212, 420, -67, -172, +157, -814, 579, -261, 274, 675, -368, 355, +-137, -508, 361, -347, 244, 399, -79, 108, +139, -583, 532, -189, 237, 713, 82, 312, +257, -556, -104, -396, -520, 172, 272, -77, +675, -328, 61, 160, -104, 573, 581, 102, +638, -469, -247, -322, -612, 48, 74, 71, +567, -151, 213, -70, -24, 258, 299, 331, +504, -357, 61, -679, -168, 88, -49, 715, +183, 91, 213, -511, 163, -212, 229, 199, +265, -19, -133, -320, 75, -57, 587, 363, +101, 206, -293, -244, 240, -267, 294, 32, +-134, 180, 18, -43, 521, -275, 451, -291, +-39, 6, -13, 413, 110, 282, -93, -308, +-29, -336, 351, 202, 516, 179, 364, -318, +-106, -369, -241, 55, 99, 193, 337, -46, +216, 83, 50, 332, 148, -112, 317, -472, +158, 39, -99, 174, -7, -476, 240, -371, +344, 605, 126, 663, 26, -272, 124, -688, +126, -93, 172, 439, 184, 150, 149, -505, +123, -487, 89, 350, 136, 750, 266, 5, +-6, -786, -113, -388, 229, 423, 434, 294, +277, -285, 189, -99, 84, 336, -239, 24, +-164, -474, 383, -254, 345, 141, -55, 133, +392, 94, 685, 198, -221, -48, -609, -436, +280, -249, 765, 265, 96, 292, -417, -179, +106, -345, 587, 32, 196, 318, -180, 25, +234, -414, 512, -180, 76, 430, -226, 265, +-4, -413, 75, -362, 126, 152, 513, 233, +458, -87, -139, -275, -43, -59, 358, 305, +139, 139, -120, -221, -69, -162, 190, 9, +412, -63, 302, -77, -14, -12, 152, 19, +375, 35, 7, 109, -236, 53, 141, -156, +207, -185, 16, 8, 374, 33, 622, -124, +49, -42, -435, 138, -61, 89, 594, -87, +328, -119, -262, -95, 97, -60, 511, 91, +138, 162, -114, -59, 49, -215, 100, -75, +247, -20, 467, -92, 183, 72, -251, 289, +82, 55, 417, -286, 24, -263, -152, 81, +171, 161, 268, -85, 358, -179, 388, 70, +-21, 121, -276, -91, 148, -54, 430, 152, +-15, 54, -104, -314, 385, -241, 320, 148, +-88, 179, 139, -178, 419, -92, 148, 270, +-97, 250, 89, -306, 186, -515, -28, -18, +-5, 475, 367, 97, 424, -419, 158, -85, +-10, 395, 55, 66, 202, -419, 160, -144, +-97, 266, -64, 144, 309, -311, 406, -232, +204, 207, 123, 260, 90, -145, 91, -91, +82, 45, 7, -113, 36, -154, 238, 48, +234, 10, 205, -16, 230, 169, 176, 125, +-37, -183, -80, -313, 230, -63, 419, 140, +6, 85, -179, -24, 251, 53, 437, 57, +128, -47, -5, -222, 4, -184, 89, -5, +404, 228, 277, 96, -203, -154, -42, -55, +516, 273, 222, 5, -301, -535, 55, -236, +546, 426, 296, 260, -8, -306, -29, -207, +-30, 187, 249, 268, 469, 71, -75, -222, +-234, -511, 290, -248, 415, 360, 134, 506, +92, -121, 135, -401, 93, 164, 90, 429, +28, -268, 71, -677, 171, -64, 247, 474, +257, 239, 212, -196, -6, -163, -44, 54, +106, 156, 251, 70, 226, -234, 82, -385, +35, 119, 167, 341, 142, -221, 76, -265, +187, 428, 140, 385, 149, -317, 289, -471, +55, -75, -246, 133, 66, 21, 521, 18, +330, 217, -208, 82, 6, -315, 593, -122, +182, 297, -507, -65, -1, -528, 596, 35, +167, 613, -70, 105, 355, -506, 316, -189, +22, 281, -143, 97, -222, -225, 208, -108, +583, 91, 173, 90, -20, -2, 274, -49, +71, -42, -120, -5, 117, -112, 153, -112, +104, 177, 270, 272, 242, -178, -45, -540, +-27, -39, 361, 645, 359, 252, -120, -557, +-269, -284, 200, 341, 416, 6, 83, -375, +57, 108, 249, 419, 178, -57, 18, -319, +28, 48, 20, 152, 89, -166, 203, -295, +201, 39, 162, 361, 128, 253, 77, -225, +52, -410, 110, -40, 175, 308, 48, 62, +32, -337, 274, -85, 162, 400, -181, 149, +117, -399, 582, -196, 118, 317, -361, 119, +77, -394, 457, -195, 82, 310, -168, 208, +160, -161, 397, -52, 140, 128, -166, -108, +-4, -334, 307, -7, 262, 322, 81, 11, +75, -245, -125, 111, -144, 209, 394, -216, +475, -182, -122, 228, 0, 117, 322, -268, +15, -298, -165, 61, 39, 291, 242, 238, +357, -44, 61, -269, -221, -198, 231, 95, +482, 117, 4, -63, -226, -29, -30, 25, +59, -119, 187, -65, 369, 148, 242, 132, +70, -67, 7, -110, -80, 31, -19, -1, +72, -168, 48, -162, 176, 130, 336, 142, +262, -36, 36, -42, -169, 136, -26, 44, +287, -100, 119, -144, -214, -155, -4, -153, +366, 71, 342, 239, 59, 151, -47, -55, +99, -36, 174, 91, -177, -84, -280, -387, +214, -246, 505, 231, 231, 317, 57, 49, +26, -93, -90, 38, -15, 20, 27, -127, +18, -245, 95, -89, 293, 151, 252, 205, +117, -80, -78, -156, -36, 108, -25, 187, +12, -157, 139, -357, 203, 104, 68, 427, +121, -95, 134, -544, 34, 30, 47, 490, +-45, 3, -163, -372, 107, 44, 297, 310, +210, -58, 138, -368, -37, -117, 3, 193, +26, 228, -184, 0, -84, -217, 392, -112, +257, 84, 30, 98, 169, -2, 98, -21, +-248, -105, -179, -97, 106, 27, 163, 40, +178, -15, 206, 13, 87, 82, 76, 46, +10, -77, -183, -213, -180, -206, 115, 117, +437, 379, 253, 144, -326, -270, -218, -298, +453, -19, 311, 95, -293, 49, -217, -24, +265, 85, 207, 223, -157, 82, -77, -397, +231, -517, 221, 39, 12, 509, -165, 292, +52, -88, 203, -226, -80, -123, -164, -55, +195, -55, 215, -5, -33, 119, 25, 77, +159, -24, -49, -22, -251, -22, 25, -64, +233, -85, 168, 7, 69, 146, -62, 20, +-54, -217, 129, -159, -132, 110, -149, 323, +289, 199, 327, -256, -253, -490, -203, -125, +290, 294, 243, 215, -189, -25, -192, 40, +72, 129, 81, -155, 78, -424, 128, -110, +30, 362, -169, 257, 38, -290, 262, -172, +-26, 323, -331, 120, -22, -357, 218, -126, +126, 329, -31, 89, 21, -351, 73, -186, +110, 184, -112, 90, -326, -43, -110, 144, +330, 229, 320, -2, -69, -305, -173, -447, +-27, -120, 98, 192, 35, 257, -86, 220, +-85, 206, 79, -19, 40, -296, -91, -378, +12, -168, 197, 127, 176, 264, -56, 161, +-226, -61, -187, -185, -129, -10, 23, 178, +361, 159, 296, -171, -30, -349, -216, -58, +-269, 151, -105, 9, 140, 36, 36, 179, +-78, 94, 151, -87, 245, -192, 27, -100, +-287, 82, -266, -14, 72, -146, 226, 17, +-112, 99, -157, 38, 201, 133, 208, 127, +-234, -259, -171, -362, 208, 126, 190, 410, +-319, -50, -368, -485, 103, -183, 250, 439, +138, 378, 150, -175, -123, -289, -330, 15, +-77, 41, -6, -115, 15, -49, 127, 108, +57, 107, -69, -47, -63, -110, -44, -58, +37, 33, -47, 187, -91, 100, 69, -186, +55, -156, -218, -35, -211, -115, 134, -53, +259, 274, 62, 301, -103, 25, -237, -286, +-272, -314, 94, -37, 189, 282, -26, 215, +-87, -208, -51, -308, -59, 74, 65, 260, +95, 74, -91, -72, -253, -25, -136, 9, +140, -119, 107, -197, -56, 16, -86, 142, +-21, -32, -9, -18, -20, 248, -103, 202, +-23, -214, 27, -383, -125, -120, -160, 83, +105, 105, 145, 172, -93, 203, -96, -30, +-71, -298, -149, -218, 46, 94, 92, 213, +-162, 118, -85, -52, 52, -259, -45, -165, +-29, 179, -66, 218, -104, -52, 91, -42, +52, 118, -158, -29, -157, -353, -143, -216, +-50, 302, 187, 369, 206, -83, -106, -229, +-297, 48, -169, 136, 60, -232, 16, -291, +-153, 254, -105, 408, 183, -164, 236, -353, +-172, 97, -318, 276, -98, -84, -71, -293, +-111, 30, 100, 314, 157, 14, 43, -314, +-114, -110, -169, 210, -167, 139, -95, -76, +-28, 5, 51, 33, 39, -139, -77, -182, +-107, -3, 91, 201, 73, 234, -248, -40, +-258, -221, -33, -126, 24, -36, 51, 73, +47, 231, -47, 115, -53, -170, -34, -264, +-110, -44, -298, 125, -152, 74, 208, 40, +161, 171, -162, 76, -123, -240, 108, -354, +73, 9, -373, 315, -544, 134, 186, -158, +572, -67, -62, 126, -435, 83, 19, -69, +200, -130, -297, -67, -461, -30, 129, -17, +377, 20, -82, 176, -261, 224, 49, 7, +90, -211, -201, -195, -349, -180, -115, -55, +164, 218, 173, 345, -5, 102, -133, -59, +-148, -100, -204, -239, -56, -301, 41, -59, +-46, 266, -49, 425, 64, 268, -105, -116, +-187, -450, -100, -437, 23, -39, 124, 435, +66, 448, -261, 43, -354, -288, -100, -355, +173, -146, 125, 200, 7, 396, -28, 158, +-162, -238, -291, -348, -208, -147, 140, 113, +222, 303, -115, 270, -239, -38, 66, -418, +-92, -266, -245, 159, 106, 358, 164, 189, +-261, -151, -238, -402, 94, -177, 155, 290, +-97, 357, -353, -16, -201, -316, 228, -217, +282, 191, -181, 450, -313, 77, -73, -568, +-54, -548, -165, 194, 142, 753, 186, 447, +-257, -290, -341, -587, 133, -364, 262, 114, +-136, 507, -416, 304, -157, -261, 146, -319, +145, 62, -12, 288, -210, 21, -289, -355, +44, -200, 259, 317, -116, 415, -357, -65, +-91, -416, 126, -198, 18, 220, -75, 263, +-94, 0, -26, -189, -100, -107, -287, 56, +-29, 59, 340, 94, 29, 60, -439, -39, +-224, -72, 182, -85, 150, -44, -267, 62, +-332, 48, 126, 31, 239, 114, -86, 46, +-256, -141, -115, -150, 29, 9, -69, 128, +-148, -20, 2, -9, 16, 188, -104, 23, +-32, -278, -15, -233, -85, 120, -88, 299, +-47, 253, -81, 77, -199, -220, -21, -522, +155, -315, -99, 295, -169, 664, 52, 261, +-31, -405, -170, -306, -76, 227, -44, 137, +-89, -423, -165, -422, -18, 296, 228, 859, +59, 330, -294, -704, -218, -779, 30, 258, +-183, 764, -295, -56, 205, -659, 520, 44, +-44, 698, -659, 138, -406, -645, 266, -425, +311, 288, -283, 541, -299, 163, 163, -255, +146, -278, -134, -151, -172, 36, -183, 275, +-128, 260, 19, -82, 84, -245, -101, -11, +-134, 108, -26, -199, 74, -275, 27, 361, +-118, 730, -389, 162, -335, -806, 87, -907, +319, 180, 222, 990, -32, 477, -307, -351, +-458, -483, -232, -91, 165, 140, 274, 50, +-84, 26, -188, 102, 8, 25, 52, -78, +-219, -69, -268, -54, -94, 97, 132, 256, +62, 12, -45, -404, -153, -250, -154, 320, +-63, 458, -54, 111, -142, -276, 56, -578, +219, -218, -113, 582, -417, 701, -228, -163, +126, -763, 168, -255, -133, 548, -192, 425, +120, -209, 92, -340, -311, -83, -307, 88, +55, 139, 69, 120, -34, 112, -34, -68, +-170, -309, -188, -240, 132, 241, 282, 553, +-113, 279, -561, -396, -550, -830, 17, -406, +630, 664, 613, 1144, -185, 282, -967, -926, +-655, -902, 283, 185, 701, 738, 189, 289, +-470, -340, -531, -380, -43, -41, 127, 282, +24, 385, 88, 291, 87, -233, -256, -691, +-460, -391, -121, 366, 252, 686, 50, 271, +-212, -359, -22, -537, 40, -84, -189, 563, +-75, 447, 54, -303, -265, -635, -169, -248, +168, 515, -81, 679, -319, -71, 66, -754, +227, -282, -12, 625, -188, 587, -341, -313, +-289, -698, 56, -173, 294, 507, 53, 618, +-370, -69, -416, -780, 284, -362, 643, 644, +-196, 657, -1013, -233, -478, -604, 378, -106, +563, 310, 244, 216, -336, -37, -527, -116, +-205, -69, 15, -181, 130, 79, 233, 590, +-184, 351, -541, -602, -224, -896, 288, 2, +389, 863, 47, 511, -422, -159, -525, -192, +-159, -287, 283, -495, 268, 56, -236, 682, +-400, 366, 21, -472, 405, -358, 77, 483, +-566, 411, -598, -605, 155, -812, 456, 271, +-23, 924, -303, 340, -31, -398, 11, -299, +-151, -35, -304, -90, -182, -114, 268, 133, +297, 465, -265, 70, -523, -552, -104, -243, +220, 494, 176, 577, -170, -197, -342, -807, +-87, -219, 151, 745, -40, 493, -244, -549, +-131, -715, 71, 298, 64, 994, -184, 269, +-261, -864, 99, -758, 252, 403, -210, 857, +-579, -84, -288, -891, 447, -196, 653, 984, +-235, 829, -968, -529, -291, -1327, 561, -374, +275, 1124, -425, 1153, -254, -502, 186, -1304, +81, 12, -264, 1135, -463, 244, -109, -1090, +501, -496, 410, 1172, -427, 1138, -701, -800, +-201, -1642, 276, -100, 228, 1312, -38, 735, +-120, -478, -84, -557, -73, 81, -253, 272, +-359, -185, 97, -350, 356, 166, -53, 563, +-232, 278, -75, -463, -128, -661, -182, 2, +-158, 585, 90, 423, 328, -120, -26, -309, +-602, -207, -423, -41, 306, 163, 509, 287, +67, -7, -571, -411, -661, -145, 6, 339, +525, 418, 316, 117, -152, -325, -471, -436, +-435, -155, -28, 195, 209, 306, 150, 181, +205, -54, -113, -84, -549, 77, -504, -30, +109, -327, 571, -103, 302, 333, -451, 323, +-602, -186, -208, -437, 297, -29, 538, 543, +-50, 433, -756, -288, -534, -691, 361, -341, +617, 500, -1, 738, -618, -74, -210, -558, +259, -83, -270, 228, -426, 42, 401, -133, +420, -13, -271, 199, -404, 191, -107, -188, +-149, -340, 67, 19, 198, 400, -78, 199, +-335, -301, -167, -324, 186, 158, 223, 320, +-206, 27, -463, -94, -29, -57, 255, -90, +36, -92, -230, 84, -277, 205, -107, -30, +309, -192, 179, 75, -352, 207, -263, 77, +52, -113, -28, -169, -116, -177, -31, -78, +-96, 233, -127, 355, 193, 60, 178, -205, +-186, -29, -270, -17, -210, -257, -210, -97, +-17, 322, 217, 333, 144, -202, 126, -357, +-47, 32, -523, 387, -518, 332, 192, -339, +519, -562, -89, 107, -442, 525, 12, 79, +177, -432, -156, -215, -97, 373, -41, 432, +-168, -88, -29, -332, 116, -88, -95, 148, +-151, -40, -92, -402, -154, -41, 173, 637, +365, 454, -198, -126, -675, -381, -396, -441, +481, -124, 733, 364, -176, 448, -861, -157, +-323, -612, 407, -6, 485, 793, -53, 473, +-627, -495, -322, -711, 384, -94, 339, 342, +-194, 188, -571, -41, -297, 78, 468, 220, +485, -6, -182, -328, -409, -65, -290, 185, +-147, -7, 143, -179, 230, -81, 22, 142, +-81, 277, -245, 64, -276, -188, 194, -31, +208, 92, 0, -24, -240, -145, -591, -251, +-184, 12, 726, 308, 469, 404, -483, 107, +-573, -338, 38, -417, 353, 10, -80, 352, +-489, -27, -63, -321, 431, 78, 85, 452, +-396, 251, -81, -356, 363, -455, -25, 139, +-572, 437, -345, -188, 201, -491, 433, 157, +233, 604, -305, 234, -458, -330, -103, -482, +397, -143, 69, 314, -546, 368, -207, -57, +385, -316, 287, 83, -180, 275, -306, -144, +-198, -388, -54, 58, 133, 514, 275, 205, +53, -294, -490, -307, -452, -155, 253, 74, +533, 296, -49, 260, -457, -13, -154, -172, +88, -195, 57, -50, -26, -18, -31, -22, +-91, 228, -94, 340, 66, -34, 197, -415, +-278, -207, -537, 198, 201, 178, 586, -94, +8, -13, -504, 218, -184, 135, 92, -229, +-116, -362, -68, 103, 201, 365, 189, 11, +-107, -287, -241, -87, -214, 317, -87, 175, +215, -133, 153, -103, -188, -42, -210, -128, +9, -127, 117, 115, 83, 267, -153, 181, +-233, -18, 76, -61, 104, -146, -203, -367, +-142, -13, 144, 485, 193, 150, -53, -358, +-290, -228, -231, 364, 142, 456, 276, -178, +-28, -596, -351, -129, -57, 459, 85, 215, +-45, -358, 53, -291, 96, 329, -132, 494, +-206, -62, 101, -374, 123, -42, -321, 98, +-189, -273, 320, -319, 141, 375, -169, 666, +-22, 78, -89, -373, -350, -300, -11, -106, +413, 60, 219, 186, -386, 120, -405, -152, +71, -139, 289, 300, 96, 272, -142, -252, +-193, -327, 27, 114, 8, 161, -156, -165, +14, -246, 131, 348, -43, 629, -84, -244, +187, -927, -108, -42, -489, 923, 121, 319, +440, -741, -290, -434, -340, 423, 561, 402, +312, -45, -789, -289, -592, -111, 478, 186, +555, 56, 51, -114, -230, -31, -467, 179, +-277, 108, 385, -232, 398, -275, -208, 217, +-333, 436, 55, -116, 210, -346, -172, -110, +-281, 113, 128, 218, 233, 102, 43, 11, +-151, -127, -292, -267, 93, -72, 281, 268, +-401, 178, -436, -54, 680, -101, 598, -21, +-518, 90, -692, 7, -104, -165, 522, -90, +381, 227, -444, 174, -480, -199, 383, -339, +511, 169, -169, 644, -657, 95, -242, -839, +457, -484, 416, 728, -123, 616, -356, -475, +-162, -512, 20, 280, 173, 488, 59, -191, +-185, -461, 32, 231, 341, 547, -209, -196, +-582, -827, 82, -217, 440, 894, -48, 880, +-157, -528, 45, -1143, 123, -30, -107, 1082, +-221, 452, -79, -892, 138, -820, 192, 588, +-180, 1063, -272, -240, 123, -996, 304, -160, +103, 923, -150, 477, -483, -669, -243, -657, +418, 225, 462, 696, -231, 78, -607, -661, +129, -331, 844, 541, -70, 768, -1049, -100, +-271, -922, 802, -612, 469, 581, -291, 962, +-524, -60, -80, -940, 369, -230, 214, 929, +-268, 347, -367, -897, 143, -431, 293, 776, +71, 508, -192, -583, -305, -560, -19, 270, +398, 445, 269, 9, -421, -103, -428, -11, +192, -91, 269, -264, -115, 45, 8, 478, +138, 79, -74, -478, -104, -183, -106, 383, +-128, 317, -16, -241, 206, -495, 219, 15, +-32, 682, -406, 319, -121, -611, 581, -692, +84, 258, -797, 833, -235, 172, 673, -658, +232, -484, -268, 466, 4, 700, -16, -262, +-169, -851, -130, -120, 128, 713, 202, 617, +-80, -303, -175, -735, -35, -99, 91, 392, +84, 243, 62, -90, -125, -146, -125, 90, +-63, 153, 90, -33, 190, -287, -95, -245, +-393, 242, 24, 445, 507, -40, 43, -379, +-412, 32, -33, 298, 318, 9, -211, -321, +-461, -188, 225, 162, 497, 225, -70, 188, +-281, -114, -49, -191, -31, 65, -15, -29, +325, -96, -49, 59, -540, 110, -50, -32, +585, 91, 222, 161, -518, -209, -424, -550, +293, 170, 606, 816, -49, 75, -630, -712, +-319, -350, 527, 440, 526, 489, -401, -259, +-561, -472, 193, 83, 373, 265, 6, 0, +-115, 52, -16, 137, 92, -5, -76, -391, +-214, -271, -174, 353, -54, 403, 349, -82, +492, -505, -24, -238, -573, 620, -359, 684, +447, -146, 321, -948, -633, -689, -393, 523, +797, 1039, 582, 0, -569, -694, -566, -213, +298, 509, 505, 399, -272, -431, -621, -683, +-44, 70, 566, 716, 447, 335, -217, -521, +-612, -659, 47, 355, 713, 898, -52, 85, +-965, -799, -279, -730, 1039, 305, 677, 992, +-655, 255, -1009, -922, 216, -724, 1179, 724, +190, 1090, -1151, -181, -539, -1255, 868, -381, +622, 978, -600, 773, -715, -604, 395, -1073, +911, 176, 71, 1130, -816, 480, -606, -748, +290, -905, 658, 78, 90, 922, -456, 405, +-158, -775, 482, -901, 329, 640, -539, 1448, +-726, -189, 234, -1605, 749, -467, 230, 1165, +-486, 964, -385, -558, 285, -1083, 413, 82, +-164, 898, -607, 224, -125, -554, 578, -384, +555, 245, -309, 470, -636, -75, 40, -431, +357, -108, 36, 306, -159, 291, -125, -93, +185, -288, 252, -154, -172, 6, -284, 298, +11, 316, 124, -310, 210, -437, 9, 242, +-199, 642, -158, -201, -17, -944, 195, -47, +296, 989, -41, 437, -407, -695, -248, -656, +207, 394, 399, 851, 77, -177, -199, -1005, +-285, -196, -84, 798, 323, 529, 78, -427, +-212, -460, 53, 299, 81, 340, -65, -262, +-43, -416, 106, 84, -8, 361, -204, 30, +-25, -134, 247, 12, -27, 7, -161, -10, +223, 90, 162, 22, -298, -146, -324, -180, +115, -29, 362, 220, 49, 281, -233, -62, +-123, -250, 219, -34, 209, 142, -186, 7, +-433, -173, 61, -72, 469, 214, 158, 142, +-310, -38, -356, 13, 48, -226, 308, -411, +346, 219, -34, 887, -523, 240, -341, -997, +370, -900, 451, 661, -193, 1153, -337, -196, +157, -934, 308, 19, -98, 594, -361, -41, +-60, -376, 250, 133, 211, 374, -111, -168, +-282, -540, 16, -45, 259, 755, -3, 456, +-187, -650, 134, -911, 82, 192, -116, 1221, +-149, 444, -64, -1223, 76, -950, 305, 787, +107, 1116, -200, -169, -254, -905, -111, -314, +153, 575, 248, 542, 131, -186, -219, -539, +-230, -260, 102, 494, 158, 521, -65, -372, +-146, -743, 33, 129, 360, 966, 70, 264, +-476, -849, -339, -600, 288, 456, 540, 702, +90, -182, -503, -795, -304, -49, 344, 987, +263, 363, -284, -873, -239, -757, 428, 593, +416, 1012, -387, -297, -643, -1207, 3, -138, +570, 1179, 314, 521, -214, -776, -282, -488, +-21, 475, 144, 236, 143, -445, -233, -215, +-262, 289, 310, 209, 383, 8, -272, 33, +-473, -103, 259, -229, 645, 136, -209, 211, +-817, -232, -37, -274, 796, 296, 339, 350, +-577, -217, -502, -449, 232, 178, 598, 611, +132, -59, -529, -691, -539, -203, 333, 574, +734, 393, -5, -336, -666, -449, -285, 76, +355, 397, 381, 212, 11, -231, -305, -474, +-142, 84, 219, 654, 125, 89, -329, -730, +-85, -430, 306, 679, 140, 678, -157, -412, +-138, -789, 46, 180, 171, 861, -18, 91, +-170, -888, -28, -465, 36, 714, -8, 603, +36, -405, 141, -528, 42, 244, -82, 497, +-36, -170, 9, -461, -119, 69, -177, 284, +36, -71, 339, -145, 234, 41, -145, 144, +-244, 231, -134, 32, -33, -469, 144, -466, +113, 352, -33, 816, -41, 35, 19, -692, +84, -399, -41, 280, -193, 426, -34, 23, +279, -192, 91, 55, -295, 131, -177, -259, +124, -361, 193, 216, 219, 531, 50, -52, +-421, -431, -297, -15, 193, 314, 318, 76, +119, -256, -163, -205, -278, 86, 56, 233, +337, 95, -4, -168, -273, -176, -112, 237, +163, 295, 163, -280, -113, -467, -251, 171, +127, 507, 325, -144, -68, -540, -236, 181, +7, 743, 34, 100, 22, -718, -35, -494, +-216, 299, 19, 449, 550, 28, 250, -122, +-613, 56, -571, -66, 341, -237, 655, 119, +-109, 456, -562, -114, -104, -704, 398, -152, +348, 753, -27, 501, -476, -542, -344, -635, +352, 282, 436, 646, -261, 41, -408, -546, +256, -324, 444, 200, -198, 295, -432, 153, +43, 33, 288, -195, 20, -303, -101, 51, +-65, 305, -71, 130, 183, -204, 196, -182, +-181, 92, -270, 83, 28, -73, 114, -28, +58, 76, 98, 116, 51, 78, -125, -31, +-162, -180, 4, -223, 0, -5, -2, 223, +132, 177, 144, -5, -49, -66, -101, 37, +-27, -21, -121, -297, -102, -130, 188, 307, +225, 323, -162, -95, -179, -392, 223, -66, +94, 399, -290, 176, -67, -281, 232, -289, +-22, 74, -191, 293, 69, 22, 207, -238, +8, -7, -210, 238, -113, 121, 151, -149, +96, -240, -149, -86, -79, 181, 122, 216, +76, -12, -47, -160, -55, 18, -23, 91, +-47, -86, -45, -125, 150, 50, 122, 253, +-209, 98, -86, -317, 254, -343, -127, 184, +-359, 457, 334, 131, 532, -328, -363, -294, +-695, 175, 131, 246, 676, -155, 65, -266, +-470, 70, -159, 373, 340, 233, 221, -171, +-295, -462, -410, -329, 96, 254, 417, 668, +136, 227, -109, -539, -153, -484, -136, 210, +-15, 456, 106, -57, -25, -402, -70, -27, +192, 432, 135, 185, -237, -332, -288, -317, +138, 196, 406, 371, 21, -52, -445, -385, +-250, -186, 359, 261, 303, 321, -180, -117, +-263, -244, 131, 163, 222, 344, -140, -153, +-272, -537, 72, -236, 288, 366, -35, 499, +-269, 103, -79, -307, 229, -285, 231, 72, +-35, 227, -312, 55, -305, -200, 201, -265, +488, 11, 55, 336, -544, 267, -289, -112, +484, -275, 492, -1, -328, 264, -660, -107, +-14, -473, 586, -26, 327, 552, -264, 364, +-433, -331, -67, -398, 407, 192, 211, 236, +-449, -217, -365, -260, 345, 67, 576, 297, +62, 149, -583, -115, -474, -130, 306, -33, +536, 69, -112, 68, -484, -176, 39, -235, +513, 156, 107, 405, -471, 111, -235, -333, +176, -214, 123, 202, 110, 167, 97, -198, +-274, -264, -311, 78, 297, 344, 434, 130, +-185, -149, -380, -121, 35, -88, 217, -33, +-73, 97, -171, 80, 73, 3, 249, -77, +65, -37, -241, 103, -231, 21, 96, -122, +271, -31, -45, 151, -204, 149, 15, -180, +187, -272, -36, 153, -214, 225, -36, -120, +176, -82, 100, 193, -63, 60, -28, -328, +-28, -104, -192, 387, -75, 162, 253, -366, +229, -135, -163, 316, -252, 128, 49, -331, +129, -212, -78, 263, 58, 221, 149, -13, +-179, 42, -165, -100, 101, -307, 50, -136, +-94, 217, 84, 318, 202, 69, -66, -242, +-203, -109, -23, 117, 22, 75, -126, -119, +44, -159, 242, 117, 53, 207, -226, -59, +-14, -117, 234, 82, -116, 51, -435, -157, +-28, -99, 501, 222, 349, 162, -306, -301, +-506, -197, 41, 407, 345, 283, 149, -461, +-163, -481, -312, 407, 95, 689, 491, -206, +-12, -778, -653, -109, -333, 630, 565, 417, +667, -385, -230, -524, -578, 222, -38, 562, +276, -65, -13, -653, -277, -345, 1, 497, +408, 763, 271, 0, -318, -718, -411, -371, +127, 381, 323, 348, -212, -169, -357, -285, +176, 67, 500, 341, 156, 138, -473, -340, +-431, -342, 233, 220, 465, 487, -8, -46, +-432, -551, -220, -204, 314, 463, 360, 303, +-139, -308, -233, -230, 27, 266, 97, 223, +-159, -235, -206, -359, 250, 68, 390, 489, +-79, 183, -497, -402, -259, -486, 279, 90, +459, 553, 73, 277, -262, -296, -192, -219, +-21, 110, -37, -57, -100, -323, 66, -44, +161, 395, 230, 345, 233, -76, -74, -163, +-565, -97, -572, -201, 262, -197, 758, 152, +110, 361, -428, 155, -123, -197, 155, -188, +88, 26, -28, 76, -141, 69, -75, -24, +25, -116, 1, -76, -71, -4, 36, 9, +213, 130, 206, 269, -4, 124, -299, -282, +-320, -430, -33, -50, 194, 287, 94, 159, +26, -71, 145, -3, 103, 193, -184, 88, +-266, -195, 84, -251, 152, -122, -170, 91, +-167, 292, 208, 65, 297, -177, -115, 12, +-348, 161, 23, -18, 355, -228, 92, -83, +-294, 231, -333, 90, 48, -258, 341, -67, +116, 248, -255, 119, -84, -93, 291, -71, +109, -2, -269, -33, -250, -16, -63, 13, +243, -21, 310, 19, -199, 110, -374, 79, +243, -91, 509, -147, -206, -43, -755, 94, +-27, 73, 772, 49, 252, -5, -627, -101, +-371, -9, 388, 71, 442, -52, -125, -152, +-435, 13, -202, 284, 329, 248, 465, -225, +-239, -405, -697, -27, 57, 293, 805, 209, +244, -92, -674, -237, -451, -90, 401, 188, +366, 190, -284, -136, -260, -170, 235, 153, +329, 223, -111, -112, -407, -389, -83, -202, +323, 368, 175, 471, -229, -84, -202, -385, +165, -85, 230, 215, -84, 77, -274, -180, +-102, -169, 289, 70, 244, 242, -249, 179, +-297, -102, 123, -273, 242, -34, -49, 221, +-202, 61, 59, -266, 201, -182, -26, 218, +-201, 387, -107, 78, 105, -370, 203, -328, +-45, 213, -311, 321, 11, -148, 386, -291, +42, 165, -307, 325, -40, -126, 140, -324, +-125, 67, -91, 230, 165, 15, 76, -67, +-108, -49, 75, -114, 159, -40, -167, 86, +-294, 70, 73, 59, 268, 134, -49, 14, +-221, -280, 47, -229, 285, 133, 119, 229, +-273, 37, -334, -42, 59, -66, 369, -67, +50, 44, -304, 88, -83, 6, 212, -44, +179, 4, -16, -77, -225, -157, -209, 50, +94, 240, 211, 115, 22, -119, -89, -131, +-34, -20, 10, 53, 39, 15, 66, -6, +-104, -21, -146, -50, 80, 51, 83, 140, +-127, 3, 5, -169, 300, -81, -2, 160, +-420, 224, -86, -92, 408, -320, 100, -147, +-305, 148, -141, 322, 54, 160, 189, -237, +282, -292, -65, 117, -477, 311, -228, -81, +348, -403, 432, 12, -140, 516, -517, 129, +7, -530, 468, -335, 107, 491, -324, 553, +-175, -297, 119, -673, 161, -25, -20, 613, +-200, 303, -71, -429, 204, -468, 202, 257, +-83, 558, -225, -103, -33, -628, 147, -49, +-12, 639, -191, 213, 63, -534, 234, -381, +49, 286, -124, 458, -181, -2, -84, -361, +225, -210, 216, 187, -158, 321, -278, -49, +-81, -418, 193, -69, 293, 475, 40, 291, +-231, -351, -237, -488, 38, 15, 227, 399, +-13, 251, -180, -81, 117, -255, 213, -135, +-197, 170, -276, 181, 148, -177, 305, -260, +-47, 181, -214, 399, -46, -23, 53, -422, +52, -261, 34, 219, -45, 393, -63, 65, +110, -251, 137, -192, -151, 58, -229, 105, +67, -20, 229, -28, 21, 101, -105, 21, +-89, -129, -11, -23, 47, 85, 68, -2, +22, -51, -43, 95, -38, 135, -25, -133, +-50, -288, 9, 2, 109, 254, 64, 149, +-15, -18, -109, -44, -180, -111, -3, -156, +224, 30, 167, 219, -69, 83, -161, -155, +-92, -132, -9, 97, 55, 108, 84, -93, +18, -57, -62, 152, 56, 76, 88, -155, +-130, -134, -174, 96, 100, 105, 159, -49, +-29, -91, -125, -10, -102, 112, 96, 156, +238, 3, -11, -247, -257, -142, -47, 236, +236, 150, 55, -246, -337, -166, -190, 183, +413, 161, 315, -22, -301, -17, -200, 82, +255, -56, 28, -273, -309, -143, -96, 183, +180, 308, 164, 92, 19, -283, -30, -208, +-7, 260, -36, 252, -76, -201, -24, -288, +-33, 73, -60, 220, 76, -95, 185, -180, +77, 180, -99, 314, -138, -84, -21, -369, +57, -75, -11, 292, -101, 118, -17, -285, +136, -243, 208, 238, 22, 500, -272, 16, +-224, -518, 179, -244, 206, 291, -125, 249, +-87, -218, 146, -219, 50, 250, -144, 311, +-37, -165, 96, -346, 67, 8, -55, 269, +-118, 58, -17, -229, 116, -73, 27, 217, +-74, 142, 24, -137, 88, -215, 46, 17, +-96, 234, -192, 119, -34, -210, 171, -301, +160, 81, -22, 446, -145, 152, -20, -382, +138, -294, -31, 197, -161, 271, -25, -117, +63, -282, 68, 60, 97, 333, 54, 134, +-96, -209, -96, -215, 19, 18, -109, 63, +-148, -109, 258, -50, 385, 301, -129, 312, +-419, -227, -69, -412, 304, 89, 80, 334, +-223, -114, -109, -425, 146, -1, 267, 491, +106, 281, -366, -256, -397, -305, 235, 53, +516, 148, -16, -68, -505, -104, -157, 62, +381, 32, 258, -63, -150, 142, -276, 234, +-17, -131, 260, -334, 43, -2, -273, 247, +-113, 2, 208, -220, 254, -26, 6, 205, +-218, 143, -107, -52, 49, -126, -15, -26, +-78, 35, 55, -41, 240, -36, 76, 46, +-263, 16, -159, -5, 192, 115, 175, 139, +-203, -180, -289, -344, 181, 84, 408, 456, +-75, 63, -367, -455, -31, -228, 332, 349, +136, 375, -335, -168, -298, -373, 195, 3, +386, 193, 61, 27, -311, -49, -207, 87, +243, 87, 220, -115, -238, -206, -316, -19, +121, 162, 450, 156, 182, 17, -421, -175, +-435, -145, 211, 103, 514, 208, -47, 42, +-517, -192, -69, -215, 555, 27, 175, 283, +-542, 215, -263, -175, 401, -322, 312, 26, +-157, 277, -284, 35, -151, -228, 162, -95, +285, 207, 3, 184, -224, -65, -28, -102, +182, -18, -30, -94, -279, -174, -56, -15, +282, 321, 198, 335, -116, -71, -184, -263, +-15, -137, 103, -80, 27, -93, -50, 74, +-29, 321, 16, 169, -50, -247, -110, -193, +85, 162, 310, 176, 100, -42, -330, -220, +-299, -162, 99, 107, 274, 151, 30, -23, +-228, -54, -29, 131, 345, 224, 176, -52, +-408, -352, -400, -220, 253, 117, 507, 251, +-18, 97, -486, -154, -187, -127, 353, 151, +350, 241, -175, -42, -381, -338, 0, -188, +421, 180, 173, 274, -455, 59, -442, -224, +311, -178, 598, 133, -7, 189, -448, -52, +-168, -157, 248, -4, 131, 137, -166, 34, +-83, -106, 82, -31, 103, 62, 110, -30, +-143, -120, -348, -58, 98, 132, 529, 290, +138, 168, -482, -241, -422, -454, 189, -144, +409, 320, 120, 374, -174, 2, -261, -337, +1, -233, 339, 235, 122, 452, -375, -53, +-286, -566, 238, -209, 332, 484, -54, 383, +-155, -324, -30, -508, -1, 104, 104, 535, +14, 165, -193, -355, -38, -272, 192, 146, +76, 225, -72, -117, -91, -222, 39, 97, +123, 238, -44, -3, -216, -206, -89, -100, +237, 157, 249, 209, -96, -1, -229, -214, +-65, -203, 122, -14, 122, 185, -66, 207, +-118, -3, 2, -193, 73, -84, 113, 167, +-1, 141, -167, -144, -56, -257, 73, 54, +65, 331, 35, 55, -25, -331, -84, -198, +-58, 244, 91, 326, 139, -33, -41, -275, +-135, -57, 35, 123, 38, -81, -88, -195, +-29, 79, 156, 307, 130, 152, -137, -169, +-159, -214, 74, -19, 125, 46, -83, 8, +-113, 42, 88, 24, 161, -52, -71, 2, +-173, 117, 24, 61, 168, -110, 4, -87, +-212, 89, 10, -26, 283, -245, -26, -28, +-302, 383, -38, 273, 226, -240, 129, -305, +-57, 95, -132, 111, -80, -206, 65, -114, +116, 272, -28, 253, -149, -137, 70, -230, +190, 126, -47, 174, -247, -239, -38, -303, +264, 134, 165, 392, -187, 101, -236, -296, +9, -184, 130, 174, 131, 197, 60, -58, +-64, -238, -110, -126, -91, 200, -32, 259, +61, -92, 141, -277, 65, 64, -7, 344, +-82, -55, -166, -472, -48, -111, 195, 430, +148, 322, -105, -237, -115, -356, -8, 129, +34, 277, 38, -113, 6, -242, -18, 35, +50, 198, 22, 22, -86, -135, -20, 37, +56, 135, -55, -71, -52, -151, 88, -34, +163, 78, -48, 97, -181, 32, 25, -32, +108, -68, -154, -17, -63, 75, 223, 21, +67, -102, -199, -37, -55, 110, 217, 79, +42, -70, -196, -87, -59, 35, 98, 23, +-38, -32, -67, 30, 101, 69, 170, -2, +25, -59, -170, -20, -142, 28, 38, -54, +70, -123, -44, 81, 7, 307, 163, 110, +41, -340, -185, -350, -107, 137, 149, 393, +200, 85, -100, -281, -332, -187, -28, 169, +336, 269, 142, -36, -195, -350, -162, -213, +136, 278, 198, 428, -90, -65, -226, -457, +-110, -83, 81, 435, 248, 182, 142, -444, +-163, -390, -160, 309, 68, 556, 83, -78, +-100, -509, -138, -41, 126, 456, 234, 170, +-56, -419, -271, -398, -26, 164, 228, 396, +112, 84, -149, -121, -159, -28, 61, 53, +171, -4, -6, -152, -232, -198, -118, -17, +265, 266, 348, 289, -124, -67, -424, -327, +-64, -82, 326, 238, 109, 69, -229, -224, +-132, -59, 166, 239, 147, 103, -53, -225, +-75, -179, 58, 175, 75, 233, -102, -94, +-257, -255, -67, -9, 344, 246, 302, 176, +-202, -159, -330, -314, 104, -40, 248, 289, +-21, 216, -205, -189, -175, -294, 23, 112, +267, 349, 175, 20, -143, -334, -139, -129, +145, 229, 65, 123, -329, -168, -193, -79, +353, 150, 329, 103, -239, -102, -328, -146, +142, 10, 298, 175, 15, 176, -198, -97, +-179, -360, 39, -105, 198, 321, 3, 219, +-213, -191, -36, -224, 282, 165, 252, 332, +-140, -41, -378, -358, -112, -219, 217, 129, +183, 235, -101, -7, -187, -117, 117, 106, +306, 163, -15, -33, -310, -162, -89, -136, +184, -43, 72, 28, -185, 123, -96, 187, +118, 9, 146, -199, 71, -112, 17, 137, +-56, 140, -112, -109, -93, -167, -74, 81, +18, 194, 141, -53, 96, -277, -53, -49, +44, 356, 131, 255, -65, -237, -234, -349, +-105, 26, 60, 301, 74, 67, 31, -248, +79, -145, 105, 151, 4, 229, -91, 45, +-46, -188, -34, -174, -110, 75, -30, 172, +141, -18, 104, -178, -45, -40, 3, 190, +42, 118, -16, -133, -79, -117, -11, 111, +41, 122, -58, -110, -116, -251, 50, -20, +190, 288, 92, 235, -111, -93, -114, -246, +107, -74, 56, 120, -189, 37, -103, -129, +121, -43, 105, 175, -4, 188, -24, -37, +-4, -176, 22, -72, 40, 24, 17, -24, +-103, -49, -137, 58, -1, 130, 143, 78, +137, 7, 3, -80, -93, -183, -82, -93, +4, 118, 117, 158, 32, 31, -142, -71, +-94, -68, 51, -9, 132, 60, 82, 90, +-128, -45, -116, -161, 219, -19, 171, 116, +-233, 51, -341, -7, 46, 3, 360, -15, +147, -44, -190, -16, -130, 45, 31, 3, +64, -88, 50, -30, -20, 109, -53, 124, +-36, -14, 17, -151, 34, -114, 1, 56, +18, 146, 76, 30, -24, -117, -92, -72, +2, 86, 77, 106, -22, -23, -122, -115, +-34, -54, 161, 16, 186, 62, -46, 96, +-239, 7, -54, -126, 208, -80, 36, 113, +-154, 124, -49, -78, 67, -158, 51, 34, +22, 146, 23, 2, 29, -112, -13, -20, +-34, 100, -94, 45, -137, -95, 76, -111, +237, 13, 60, 116, -112, 102, -46, -22, +35, -103, -4, -8, -94, 96, -64, -48, +67, -230, 113, -51, -18, 282, -79, 257, +73, -92, 105, -231, -76, -7, -113, 103, +-6, -103, 9, -198, 5, 28, 68, 284, +117, 255, 2, -90, -168, -334, -77, -149, +168, 214, 126, 189, -165, -180, -175, -258, +162, 122, 222, 340, -149, 45, -236, -239, +84, -60, 217, 134, 11, -53, -105, -234, +-3, -12, 56, 305, -39, 202, -99, -143, +-60, -203, 33, -11, 103, 62, 58, 1, +9, -10, 25, 21, 17, 30, -82, -11, +-142, -39, -23, 33, 127, 124, 43, -7, +-14, -261, 71, -166, 41, 249, -69, 315, +-33, -99, 54, -294, -53, 37, -212, 245, +-55, -20, 223, -212, 160, -22, -14, 140, +0, 24, -28, -67, -129, 27, -87, 56, +24, -25, 109, -38, 113, 18, -27, 22, +-161, 0, -9, -57, 196, -85, 24, -40, +-186, 83, -25, 183, 159, 70, 21, -112, +-157, -148, -64, -30, 143, 91, 132, 44, +-40, -139, -73, -113, 21, 174, 32, 277, +-74, -30, -80, -276, 32, -56, 58, 209, +21, 35, 25, -288, -8, -174, 2, 253, +14, 332, -24, -26, -1, -214, -12, -52, +-39, 63, 34, -64, 51, -139, 26, 63, +32, 226, -56, 81, -61, -139, 9, -146, +7, -4, -19, 117, -18, 73, 35, -56, +117, -80, 38, 8, -88, 40, -50, -55, +52, -44, -4, 77, -91, 63, 106, 7, +179, 51, -133, -19, -211, -234, 81, -189, +131, 230, -35, 371, -64, -53, 94, -330, +69, -49, -172, 258, -89, 85, 171, -237, +77, -192, -93, 121, -8, 237, 74, 58, +14, -126, -79, -75, -31, 66, 53, 60, +6, -53, -116, -137, -108, -88, 105, 94, +243, 204, 32, 83, -127, -65, -37, -57, +23, -28, -19, -120, -43, -183, -10, 25, +-2, 268, 29, 179, 191, -80, 141, -121, +-189, -24, -219, -3, -19, -65, 103, -37, +110, 59, -46, 61, -118, -15, 70, -39, +175, 33, 65, 74, -46, 31, -86, -48, +-20, -104, -34, -105, -120, 0, -33, 143, +155, 139, 181, -23, 14, -146, -172, -47, +-123, 97, 114, 42, 171, -80, -52, -19, +-209, 73, -23, 39, 135, -77, 58, -125, +12, -21, 92, 125, 23, 165, -105, 15, +-69, -148, 45, -62, -62, 89, -162, -56, +26, -236, 224, -14, 142, 360, -49, 257, +-81, -181, 15, -255, 15, 4, -105, 74, +-11, -95, 107, -99, -23, 122, -114, 215, +80, 27, 184, -147, 23, -116, -150, 16, +-115, 116, -19, 71, 40, -107, 79, -195, +21, -11, -18, 233, 73, 193, 87, -83, +-83, -185, -121, -33, 46, 89, 101, 7, +-64, -96, -122, -39, -5, 78, 134, 144, +133, 55, -82, -121, -186, -127, 68, 19, +179, 44, -61, -12, -138, 22, 21, 75, +117, -2, 98, -97, 9, -4, -146, 88, +-109, -9, 116, -94, 115, 44, -131, 135, +-156, -66, 87, -236, 196, -26, 27, 294, +-135, 215, -43, -166, 71, -290, 70, 6, +-20, 210, -119, 23, -14, -200, 216, -67, +49, 222, -238, 220, -57, -83, 222, -256, +65, -72, -226, 132, -113, 47, 178, -135, +107, -46, -103, 186, -19, 196, 94, -45, +43, -202, -14, -105, 11, 66, -22, 48, +-106, -57, -84, -21, 112, 106, 134, 148, +-49, -2, -118, -170, 9, -145, 97, 42, +17, 175, -4, 68, 24, -146, -51, -146, +-107, 91, 15, 147, 154, -57, 126, -97, +-39, 129, -56, 171, 12, -101, -131, -309, +-190, -124, 81, 194, 234, 240, 94, 35, +-91, -91, -121, -20, 3, 23, 65, -80, +56, -139, 22, 4, -60, 131, -50, 46, +89, -42, 121, 64, -48, 109, -206, -91, +-46, -239, 224, -63, 111, 241, -218, 194, +-237, -171, 152, -261, 394, 115, 43, 304, +-335, -46, -107, -326, 215, -24, 119, 317, +-175, 69, -168, -308, 205, -148, 281, 235, +-131, 205, -295, -79, -6, -143, 174, -1, +52, 34, -130, -5, -93, -34, 134, -83, +213, 11, -25, 230, -211, 210, 21, -187, +245, -395, -13, -6, -287, 341, -98, 33, +211, -295, 186, 26, -124, 423, -250, 99, +83, -458, 343, -278, 76, 291, -312, 316, +-258, -185, 94, -365, 277, 67, 177, 452, +-65, 210, -207, -313, -42, -411, 175, 4, +40, 348, -178, 143, -45, -221, 126, -159, +1, 163, -119, 198, 27, -65, 126, -176, +31, -17, -22, 76, 5, -18, -15, -45, +-12, 60, 9, 84, -33, -46, -16, -78, +68, 42, 95, 60, -17, -88, -149, -128, +-74, 78, 100, 225, 77, 22, -10, -205, +-39, -87, -58, 98, 24, 45, 152, -97, +75, -22, -120, 135, -142, 91, 110, -48, +245, -72, -49, -56, -344, -85, -175, -2, +233, 167, 333, 137, -25, -127, -315, -183, +-109, 66, 241, 176, 213, -24, -137, -149, +-252, -1, 136, 146, 359, 45, -45, -136, +-457, -153, -186, -31, 357, 168, 375, 254, +-117, 39, -386, -261, -77, -210, 269, 95, +141, 146, -208, -73, -160, -76, 211, 177, +327, 192, -30, -96, -353, -264, -204, -114, +170, 78, 240, 146, 41, 131, -139, 34, +-136, -121, 8, -150, 113, 21, 57, 146, +-29, 33, -44, -134, -20, -62, 25, 114, +27, 75, -5, -106, 45, -85, 139, 96, +43, 110, -161, -82, -191, -161, 0, 35, +125, 186, 73, 32, 17, -175, 28, -83, +3, 164, -53, 152, -67, -111, -60, -197, +21, -25, 164, 110, 156, 84, -92, -2, +-193, -45, 20, -11, 133, 91, -4, 81, +-67, -169, -4, -277, 39, 57, 30, 359, +-74, 124, -120, -242, 28, -138, 214, 168, +108, 81, -171, -201, -123, -137, 180, 132, +123, 158, -163, 17, -148, -17, 81, 8, +127, -50, -36, -98, -122, -41, -17, 9, +91, 53, 103, 138, 55, 116, -126, -121, +-191, -263, 42, -33, 231, 235, 65, 122, +-104, -104, -25, -57, 90, 72, -5, -10, +-132, -136, -105, -49, 23, 91, 103, 104, +66, 72, 20, 41, 11, -76, -49, -201, +-128, -146, -21, 68, 174, 204, 180, 136, +-38, -2, -142, -66, -33, -38, 9, -55, +-82, -115, -45, -61, 102, 115, 153, 159, +22, 15, -159, -85, -106, -7, 120, 72, +139, -63, -80, -166, -152, -30, 58, 122, +216, 107, 45, 20, -161, -11, -75, -3, +84, -10, 28, -52, -149, -116, -117, -88, +134, 123, 245, 257, 4, 47, -181, -249, +-33, -175, 139, 112, -39, 123, -191, -49, +35, -15, 219, 112, 115, 14, -8, -137, +-122, -46, -190, 99, -73, 6, 79, -104, +146, 43, 62, 168, -46, -19, 0, -216, +16, -69, -84, 162, -13, 98, 78, -106, +6, -73, -58, 101, 28, 98, 117, -14, +41, -42, -81, -49, -73, -100, -29, -103, +-11, 31, 12, 187, 17, 191, 47, 25, +38, -186, -54, -222, -65, -43, 39, 112, +119, 69, 51, 30, -55, 144, -29, 178, +20, -89, -17, -369, -24, -248, -65, 119, +-63, 255, 101, 92, 161, -19, -31, 39, +-202, 37, -83, -128, 166, -206, 138, 2, +-64, 280, -28, 221, 90, -190, 30, -391, +-100, -56, -89, 354, 30, 251, 56, -182, +-55, -276, -67, 76, 53, 263, 95, 10, +-32, -270, -99, -144, 24, 215, 122, 256, +57, -86, -50, -256, -78, 25, 36, 221, +113, -77, -41, -323, -141, 3, -27, 401, +73, 209, 47, -223, -25, -232, -48, 73, +37, 91, 47, -175, -66, -178, -39, 177, +58, 392, 65, 133, 60, -280, 28, -325, +-50, -35, -44, 127, -10, 41, -52, 14, +-54, 165, 45, 177, 69, -82, -42, -259, +-17, -142, 56, 8, -28, 24, -93, 117, +86, 268, 180, 143, -9, -237, -198, -378, +-51, -65, 178, 300, 105, 283, -114, -22, +-106, -248, -2, -221, -8, -32, -43, 124, +22, 142, 124, 109, 112, 105, -5, 40, +-147, -142, -145, -255, 56, -161, 213, 39, +99, 191, -103, 233, -178, 118, -14, -119, +147, -268, 19, -182, -162, 23, -43, 160, +172, 207, 148, 186, -45, 48, -163, -183, +-129, -280, -29, -125, 108, 65, 162, 107, +54, 114, -72, 124, -79, 3, 45, -201, +67, -195, -75, 37, -76, 194, 90, 180, +68, 131, -71, 31, -126, -184, -56, -317, +21, -155, -9, 110, -25, 164, 148, 69, +273, 31, 102, 60, -168, 34, -218, -44, +-36, -80, 68, -15, -29, 72, -141, 7, +-56, -146, 110, -112, 202, 134, 121, 225, +-36, 8, -194, -199, -184, -138, 13, -1, +196, 27, 192, 73, 76, 215, -51, 193, +-98, -90, -116, -282, -209, -163, -130, -2, +181, 25, 299, 62, 57, 152, -136, 110, +-76, -41, 31, -94, -10, -51, -54, -29, +65, 8, 155, 97, 38, 85, -142, -72, +-168, -150, -40, -38, 61, 77, 51, 43, +77, -26, 129, -22, 14, 37, -181, 95, +-125, 97, 127, -2, 135, -110, -91, -113, +-105, -64, 69, -60, 73, -27, -50, 95, +-77, 158, 17, 46, 61, -74, 69, -33, +67, 53, 11, 46, -60, 8, -49, 2, +-89, -23, -103, -127, -2, -195, 80, -118, +69, 61, 28, 232, 52, 259, 95, 105, +13, -84, -150, -109, -131, -25, 37, -45, +123, -151, 42, -93, -21, 137, -48, 205, +-137, -23, -109, -254, 117, -178, 153, 77, +-26, 217, -32, 203, 159, 145, 162, 34, +-105, -117, -274, -213, -124, -226, 77, -154, +110, 44, 64, 234, 19, 185, -25, -35, +-73, -113, -79, 5, 14, 83, 128, 63, +129, 36, 13, 11, -78, -63, -55, -152, +-50, -158, -122, -40, -28, 110, 144, 140, +107, 35, 3, -5, 22, 116, -14, 126, +-141, -132, -115, -309, 85, -99, 187, 218, +54, 229, -55, -13, -44, -214, -125, -213, +-194, -28, 56, 200, 321, 250, 208, 106, +-87, -12, -172, -48, -104, -171, -37, -321, +36, -198, 50, 170, -23, 331, -10, 129, +60, -64, 48, -11, -41, 77, -71, -31, +46, -191, 171, -123, 71, 117, -133, 211, +-165, -1, -12, -268, 28, -241, -141, 35, +-61, 221, 342, 238, 345, 206, -233, 64, +-476, -208, 34, -347, 440, -172, 92, 93, +-296, 134, -149, 44, 143, 49, 168, 130, +-64, 66, -273, -140, -97, -203, 232, 30, +238, 245, -22, 98, -132, -214, -15, -207, +-21, 68, -211, 101, -92, -115, 323, -35, +375, 337, -75, 365, -408, -129, -200, -480, +127, -221, 106, 170, -52, 121, -46, -104, +147, -22, 254, 187, 6, 78, -306, -156, +-218, -48, 95, 256, 235, 253, 72, -58, +-151, -308, -122, -326, 41, -166, 54, 75, +-50, 200, -9, 123, 191, 70, 215, 182, +-149, 205, -409, -63, -131, -333, 282, -194, +223, 112, -129, 76, -216, -195, 58, -183, +211, 141, 45, 287, -135, 98, -22, -33, +155, 88, 52, 129, -215, -147, -249, -411, +-7, -248, 204, 174, 193, 323, 53, 89, +-77, -135, -218, -46, -203, 140, 65, 104, +299, -60, 253, -69, 54, -24, -189, -123, +-307, -231, -165, -59, 53, 266, 154, 330, +144, 78, 43, -168, -112, -188, -171, -58, +-16, 62, 152, 114, 92, 68, -10, -87, +8, -177, -13, -77, -80, 82, -40, 111, +61, 43, -19, 61, -167, 121, -71, -5, +116, -261, 78, -267, -3, 83, -3, 358, +4, 199, 11, -128, -8, -169, -36, -14, +2, -7, 31, -117, 6, -108, -77, 19, +-150, 125, -46, 183, 106, 181, 130, 46, +88, -130, 41, -148, -99, -56, -205, -70, +-89, -160, 127, -76, 97, 167, -74, 272, +-95, 90, -14, -137, 60, -110, 171, 130, +175, 249, -101, 19, -329, -348, -141, -394, +150, -59, 100, 225, -77, 188, -68, 52, +37, 119, 55, 227, 22, 53, 67, -218, +95, -209, -56, -71, -216, -151, -162, -274, +20, -32, 148, 398, 106, 470, -48, 161, +-95, -101, 20, -130, 119, -137, 107, -217, +-50, -192, -231, -34, -232, 85, -56, 69, +60, 59, 87, 143, 188, 203, 224, 116, +85, -49, -137, -157, -270, -184, -188, -142, +57, -28, 125, 39, -72, -17, -160, -52, +42, 138, 186, 380, 52, 272, -122, -136, +-88, -382, 89, -283, 126, -77, 18, 51, +-86, 150, -137, 190, -132, 86, -121, -64, +-121, -46, 135, 95, 476, 132, 271, 15, +-280, -144, -411, -253, -147, -248, -27, -91, +-78, 146, 58, 296, 302, 279, 233, 135, +-50, -48, -141, -162, -13, -109, 19, -21, +-116, -103, -258, -243, -224, -196, 17, 67, +283, 330, 267, 385, -25, 207, -165, -71, +-24, -278, 130, -278, 50, -62, -175, 149, +-293, 81, -182, -186, 29, -205, 205, 162, +229, 429, 113, 191, -8, -224, -107, -257, +-158, 34, -118, 158, -61, -23, -78, -219, +-59, -194, 33, 5, 131, 166, 158, 193, +103, 173, -66, 131, -186, -19, -80, -242, +64, -307, -57, -90, -220, 173, -83, 187, +165, -11, 162, -156, -13, -61, -57, 159, +-10, 230, 7, 59, -3, -156, -90, -155, +-196, 4, -93, 45, 80, -88, 101, -122, +40, 65, 43, 192, 74, 67, 27, -91, +-103, -39, -220, 71, -176, 34, -10, -54, +88, -43, 22, -15, -47, -78, 1, -147, +135, 4, 202, 294, 43, 325, -223, -15, +-261, -317, -133, -207, -87, 57, -21, 44, +150, -125, 260, -63, 99, 172, -149, 205, +-155, 6, 8, -79, 20, 20, -95, 54, +-190, -44, -107, -103, 124, -60, 219, -54, +34, -130, -163, -96, -89, 136, 116, 339, +119, 255, -76, -49, -210, -264, -225, -193, +-90, 28, 140, 106, 206, -44, -2, -185, +-181, -55, -64, 222, 173, 282, 138, 36, +-137, -208, -281, -175, -134, 30, 96, 129, +129, 45, 16, -65, -45, -79, -55, -44, +-64, 3, -64, 64, -65, 99, -21, 49, +62, -54, 63, -93, 3, -1, -43, 122, +-44, 65, -34, -162, -23, -237, 6, 40, +-53, 315, -194, 148, -156, -246, 38, -302, +131, 76, 104, 371, 99, 200, 84, -186, +-45, -317, -247, -81, -268, 202, -23, 171, +167, -104, 14, -211, -259, 1, -144, 182, +246, 62, 336, -123, 20, -37, -273, 184, +-210, 152, 70, -105, 80, -207, -185, -66, +-245, 48, 10, -5, 214, -62, 132, 13, +-66, 132, -102, 133, -3, -1, 2, -104, +-140, -40, -223, 46, -46, -18, 245, -111, +242, -35, -79, 115, -263, 133, -141, 26, +31, -93, 14, -145, -136, -88, -159, 47, +31, 114, 228, 71, 178, 55, -51, 64, +-146, -25, -53, -155, -83, -123, -178, 40, +-58, 83, 46, -29, -87, -78, -159, 52, +65, 162, 293, 79, 201, -82, -89, -107, +-258, -21, -176, 3, 22, -19, 1, -18, +-241, -52, -226, -61, 174, 103, 415, 294, +148, 153, -233, -228, -287, -301, -118, 13, +-29, 198, -22, 1, 6, -208, 42, -91, +34, 146, -22, 171, -36, 65, 29, 51, +74, 58, -57, -53, -309, -161, -334, -124, +4, -77, 260, -83, 143, 22, -43, 194, +10, 187, 140, 37, 19, -6, -247, 19, +-284, -51, -116, -128, -24, -83, -58, -63, +-29, -136, 121, -76, 199, 177, 122, 296, +38, 128, -31, -35, -149, 22, -243, 67, +-286, -149, -272, -388, -110, -264, 175, 97, +376, 229, 331, 51, 115, -28, -113, 219, +-291, 435, -350, 195, -200, -304, -15, -495, +-6, -244, -29, 4, 49, -66, 107, -156, +117, 95, 154, 456, 74, 510, -207, 269, +-345, -71, -155, -410, -1, -587, -54, -353, +-73, 124, 2, 306, 106, 76, 230, -57, +170, 219, -153, 480, -353, 227, -161, -307, +31, -501, -66, -295, -107, -92, 109, -18, +208, 140, 15, 344, -138, 310, -100, 70, +-97, -81, -195, -66, -122, -81, 108, -206, +223, -257, 109, -98, -151, 129, -279, 204, +-85, 100, 142, 34, 95, 163, -122, 243, +-253, -15, -149, -404, 69, -449, 135, -52, +24, 313, -57, 214, 43, -131, 146, -140, +-46, 287, -320, 510, -294, 69, -95, -557, +6, -615, 55, -76, 179, 392, 248, 322, +31, -25, -244, -157, -238, 64, -71, 319, +1, 206, -69, -248, -120, -543, -4, -298, +141, 220, 102, 388, -61, 88, -131, -138, +-4, 30, 53, 212, -181, 28, -335, -266, +-101, -218, 218, 100, 271, 219, 58, -17, +-136, -255, -118, -122, -117, 255, -177, 362, +-40, 48, 125, -268, -15, -248, -277, -56, +-151, 7, 289, -2, 351, 97, -60, 196, +-308, 140, -191, 4, -24, -39, -7, -52, +-102, -202, -136, -333, 9, -144, 179, 291, +143, 474, -70, 159, -141, -237, -1, -224, +-47, 73, -266, 170, -188, -77, 117, -294, +210, -181, 32, 87, -172, 196, -148, 145, +81, 141, 199, 170, 6, 21, -315, -273, +-353, -397, -47, -198, 143, 92, 94, 192, +121, 172, 145, 175, -51, 110, -224, -37, +-178, -49, -65, 51, -52, -85, -115, -439, +-99, -419, 65, 136, 217, 540, 172, 318, +-65, -96, -261, -117, -139, 153, 135, 212, +65, -120, -285, -502, -371, -493, -79, -57, +227, 365, 304, 416, 189, 221, -7, 91, +-235, 88, -337, 7, -168, -219, 61, -417, +48, -409, -156, -148, -181, 202, 149, 396, +415, 354, 212, 190, -194, 59, -371, -14, +-278, -124, -122, -277, -81, -353, -26, -292, +152, -65, 213, 262, 71, 442, -39, 271, +1, -37, 24, -34, -153, 173, -350, 55, +-296, -397, -97, -600, 94, -239, 250, 314, +258, 500, 85, 237, -113, -90, -182, -119, +-111, 95, -99, 174, -188, -49, -186, -368, +-24, -463, 162, -157, 237, 378, 126, 604, +-68, 221, -203, -292, -203, -281, -118, 126, +-23, 239, 55, -125, 5, -449, -148, -305, +-82, 126, 166, 400, 217, 351, 14, 132, +-200, -86, -219, -209, -109, -186, -97, -67, +-123, -12, -15, -95, 118, -111, 215, 97, +217, 314, 10, 281, -257, 49, -338, -158, +-198, -214, 26, -168, 99, -99, -2, -40, +-96, 57, -65, 144, 85, 120, 183, 57, +109, 78, -22, 124, -183, 41, -330, -136, +-293, -279, -58, -297, 155, -125, 190, 190, +73, 361, 2, 209, 16, -53, -14, -70, +-94, 117, -183, 127, -199, -208, -98, -494, +-23, -305, 4, 164, 109, 393, 243, 296, +220, 183, -80, 82, -418, -195, -377, -421, +-37, -242, 171, 97, 123, 125, 1, -44, +-53, 26, -38, 269, 32, 270, 74, -15, +-1, -224, -142, -159, -242, -12, -229, -61, +-63, -212, 168, -135, 312, 226, 202, 469, +-144, 239, -401, -220, -261, -379, 90, -74, +279, 259, 104, 174, -291, -218, -416, -401, +-49, -124, 392, 343, 404, 510, -26, 167, +-393, -318, -287, -398, 25, -20, 63, 266, +-95, 77, -143, -269, -9, -258, 146, 125, +182, 431, 104, 316, -49, -99, -219, -381, +-285, -227, -159, 130, 46, 174, 130, -125, +17, -276, -96, 17, 12, 410, 223, 350, +153, -129, -177, -403, -360, -146, -214, 202, +80, 145, 156, -116, -65, -132, -201, 30, +-11, 59, 249, -3, 224, 51, -42, 152, +-206, 96, -191, -55, -191, -138, -171, -146, +-27, -108, 156, -20, 218, 65, 90, 68, +-73, 46, -25, 134, 56, 266, -68, 152, +-294, -239, -354, -523, -84, -365, 276, 108, +276, 430, 37, 360, -38, 49, -22, -170, +-63, -170, -173, -54, -227, 7, -46, -21, +145, -29, 79, 71, -33, 209, -51, 124, +-42, -224, -67, -476, -76, -225, 55, 401, +195, 752, 57, 381, -246, -394, -356, -845, +-141, -561, 154, 171, 234, 686, 129, 640, +5, 177, -103, -313, -165, -584, -153, -480, +-71, -5, 50, 482, 80, 540, -25, 124, +-96, -379, -8, -583, 140, -319, 116, 353, +-68, 916, -158, 682, -118, -389, -122, -1279, +-161, -967, -60, 320, 197, 1253, 339, 908, +92, -238, -217, -917, -239, -531, -58, 304, +48, 631, 24, 204, -83, -399, -170, -601, +-72, -251, 186, 370, 231, 738, -87, 409, +-308, -347, -75, -727, 308, -310, 279, 402, +-176, 574, -519, 69, -383, -520, 93, -525, +487, 44, 472, 573, 52, 507, -442, -51, +-590, -495, -226, -394, 358, 96, 556, 433, +162, 257, -347, -224, -444, -500, -165, -236, +228, 311, 340, 603, 62, 308, -249, -346, +-270, -679, -82, -285, 83, 439, 138, 623, +120, 32, 29, -527, -101, -312, -113, 289, +-87, 419, -116, -62, -50, -386, 147, -181, +145, 169, -99, 259, -218, 103, -26, -115, +248, -247, 219, -120, -160, 200, -420, 315, +-208, -13, 233, -334, 397, -200, 49, 226, +-422, 308, -395, -118, 99, -430, 540, -92, +373, 565, -303, 583, -715, -232, -318, -971, +405, -614, 621, 539, 134, 1156, -462, 462, +-532, -781, -13, -1071, 555, -66, 481, 961, +-262, 759, -851, -388, -488, -1046, 467, -423, +977, 694, 375, 1015, -657, 148, -926, -864, +-175, -809, 660, 201, 692, 951, -69, 500, +-719, -589, -573, -1025, 126, -239, 601, 915, +429, 1064, -104, -11, -380, -1021, -203, -760, +12, 309, -51, 774, -120, 128, 23, -596, +207, -390, 240, 427, 24, 748, -266, 171, +-280, -587, 53, -664, 309, -25, 60, 511, +-418, 310, -409, -280, 164, -391, 573, 138, +336, 535, -249, 228, -480, -305, -97, -395, +293, -31, 82, 186, -409, -33, -352, -278, +200, -73, 614, 427, 395, 553, -243, 54, +-611, -455, -372, -476, 156, -133, 416, 172, +180, 304, -230, 242, -287, -84, -87, -381, +183, -274, 254, 223, 138, 565, -56, 354, +-270, -222, -283, -627, -12, -414, 191, 215, +110, 550, -83, 113, -184, -570, -39, -516, +240, 421, 356, 1117, 112, 626, -320, -649, +-532, -1307, -333, -649, 124, 485, 414, 848, +383, 261, 151, -265, -123, -32, -358, 351, +-415, 44, -200, -629, 280, -597, 628, 343, +387, 1032, -278, 409, -816, -975, -594, -1443, +155, -125, 737, 1634, 639, 1721, 181, -90, +-288, -1716, -633, -1421, -751, 86, -330, 991, +580, 700, 1205, 166, 758, -6, -596, -130, +-1542, -497, -1004, -637, 704, -25, 1782, 802, +949, 812, -964, -160, -1851, -1015, -722, -725, +1056, 417, 1548, 1098, 454, 586, -832, -532, +-1078, -1004, -347, -424, 457, 442, 658, 624, +273, 160, -256, -193, -443, -77, -265, 82, +66, -90, 309, -251, 351, -26, 120, 321, +-273, 205, -505, -354, -246, -571, 276, 5, +514, 814, 172, 808, -360, -199, -501, -1094, +-58, -785, 508, 452, 497, 1102, -107, 359, +-654, -800, -460, -857, 161, 240, 569, 971, +354, 400, -130, -617, -394, -677, -234, 176, +51, 605, 212, 26, 192, -633, -45, -320, +-316, 549, -311, 651, 146, -198, 584, -721, +371, -45, -327, 843, -741, 425, -353, -891, +481, -1178, 749, 182, 15, 1408, -728, 863, +-493, -681, 418, -1194, 790, -139, 104, 901, +-748, 568, -603, -606, 302, -909, 718, 126, +189, 1063, -520, 556, -469, -643, 165, -846, +486, 60, 79, 574, -299, 94, -208, -356, +132, -59, 188, 356, -15, 112, -182, -316, +-71, -215, 57, 240, 12, 263, 66, -113, +164, -225, 115, 87, -208, 171, -415, -260, +-173, -464, 326, 114, 404, 802, 23, 568, +-265, -445, -179, -1054, 137, -387, 199, 816, +-80, 1101, -379, -80, -205, -1351, 300, -976, +473, 745, 90, 1671, -429, 519, -398, -1244, +144, -1348, 478, 227, 78, 1331, -440, 615, +-346, -916, 272, -1267, 585, -58, 135, 1317, +-566, 1206, -690, -269, 46, -1387, 802, -877, +643, 558, -299, 1150, -907, 356, -435, -752, +546, -903, 778, 9, 77, 870, -682, 726, +-578, -215, 200, -840, 663, -480, 298, 298, +-340, 668, -502, 327, -67, -291, 346, -562, +251, -249, -161, 333, -354, 520, -107, 96, +258, -396, 343, -379, 100, 122, -252, 435, +-401, 129, -220, -425, 318, -421, 631, 274, +92, 772, -690, 270, -709, -749, 175, -919, +967, 74, 652, 1013, -501, 630, -1043, -491, +-365, -794, 694, 41, 796, 654, -118, 188, +-713, -561, -313, -440, 393, 272, 479, 506, +-2, 54, -359, -179, -260, 96, 113, 48, +221, -487, 4, -518, -215, 501, -152, 1034, +113, -12, 335, -1271, 206, -711, -182, 1092, +-369, 1452, -178, -308, 219, -1736, 265, -748, +-57, 1251, -347, 1443, -194, -386, 274, -1491, +512, -436, 148, 1132, -499, 876, -542, -588, +182, -1009, 668, 167, 211, 1070, -603, 241, +-753, -1052, 63, -933, 918, 506, 685, 1327, +-366, 580, -931, -744, -314, -1081, 620, -287, +566, 661, -305, 693, -659, -59, 33, -546, +740, -235, 356, 358, -669, 256, -878, -266, +228, -300, 1220, 314, 674, 615, -823, -65, +-1452, -907, -401, -638, 1072, 527, 1277, 1106, +56, 233, -955, -959, -651, -815, 340, 514, +549, 1249, -95, 231, -576, -1205, -242, -1096, +497, 455, 610, 1349, -29, 321, -603, -1085, +-371, -918, 355, 679, 611, 1512, 6, 377, +-677, -1343, -559, -1504, 212, 126, 766, 1447, +473, 833, -337, -716, -734, -1045, -320, 162, +443, 1064, 708, 414, 198, -704, -498, -708, +-638, 206, -167, 536, 336, -160, 503, -732, +232, -151, -176, 878, -369, 991, -170, -80, +213, -1079, 247, -801, -96, 286, -329, 887, +-85, 388, 254, -448, 317, -697, -17, -254, +-286, 424, -139, 740, 152, 407, 237, -312, +-1, -734, -270, -357, -324, 252, 19, 331, +402, -48, 423, -143, 21, 275, -446, 344, +-441, -209, 72, -607, 462, -54, 226, 763, +-203, 423, -317, -761, -20, -1057, 254, 251, +145, 1390, -134, 568, -120, -1093, 161, -1122, +157, 573, -211, 1403, -353, 36, 1, -1476, +405, -799, 333, 1033, -143, 1350, -356, -233, +-92, -1235, 275, -395, 209, 791, -246, 560, +-404, -425, 42, -504, 464, 205, 302, 382, +-159, -205, -344, -354, -20, 298, 250, 650, +91, -143, -288, -868, -290, -420, 178, 702, +509, 788, 205, -247, -379, -815, -400, -201, +131, 642, 427, 472, -45, -284, -494, -514, +-111, 30, 596, 474, 523, 191, -407, -497, +-821, -629, -26, 52, 905, 931, 539, 846, +-646, -294, -971, -1333, 41, -854, 1017, 800, +645, 1613, -508, 357, -867, -1581, -33, -1624, +755, 535, 470, 2248, -423, 1193, -757, -1399, +-117, -2287, 597, -354, 633, 1867, 33, 1650, +-560, -580, -476, -1945, 158, -835, 641, 1340, +295, 1788, -512, 72, -768, -1659, 44, -1264, +934, 545, 709, 1327, -440, 415, -1008, -735, +-248, -598, 767, 242, 732, 449, -266, -31, +-821, -235, -317, 145, 523, 245, 739, -339, +165, -631, -486, 10, -593, 835, -142, 520, +454, -461, 665, -689, 141, 144, -629, 717, +-768, 127, 103, -767, 1030, -620, 737, 351, +-568, 854, -1219, 239, -270, -599, 1108, -514, +1109, 317, -363, 795, -1422, 127, -670, -908, +1035, -982, 1418, 253, 53, 1343, -1277, 882, +-906, -722, 511, -1460, 1115, -344, 279, 1224, +-718, 1213, -613, -403, 164, -1481, 562, -682, +239, 927, -69, 1294, -58, 172, -143, -939, +-405, -856, -208, 23, 512, 643, 747, 551, +-22, 136, -896, -364, -518, -642, 735, -427, +1124, 424, -43, 1068, -1250, 439, -817, -961, +678, -1317, 1190, 112, 122, 1570, -910, 994, +-510, -968, 671, -1691, 767, -131, -273, 1583, +-844, 1078, -130, -881, 730, -1560, 547, 9, +-389, 1489, -751, 888, -72, -956, 729, -1443, +689, -10, -153, 1333, -755, 904, -512, -612, +355, -1190, 744, -252, 274, 900, -521, 826, +-578, -319, 213, -987, 851, -362, 362, 734, +-676, 798, -880, -184, 50, -776, 965, -372, +599, 442, -446, 509, -759, 120, 47, -284, +764, -397, 409, -270, -518, 235, -691, 681, +96, 353, 769, -657, 371, -943, -575, 94, +-656, 1122, 287, 561, 985, -829, 397, -908, +-612, 384, -804, 1059, -75, -82, 581, -1083, +483, -363, -66, 1057, -403, 827, -153, -744, +266, -1281, 498, 105, 192, 1460, -386, 873, +-695, -829, -169, -1521, 728, -465, 823, 981, +-171, 1290, -1003, 224, -349, -999, 944, -1031, +1146, 245, -356, 1263, -1491, 629, -726, -1009, +1051, -1480, 1452, -29, 83, 1518, -1068, 1156, +-729, -514, 363, -1342, 756, -459, 296, 697, +-281, 804, -341, 93, -170, -518, 61, -612, +238, -285, 276, 357, 182, 807, -112, 495, +-166, -480, -10, -939, 141, -234, 27, 823, +-168, 787, -156, -393, 154, -1192, 373, -439, +320, 960, -1, 1214, -383, -43, -346, -1134, +33, -736, 508, 557, 419, 970, -171, 85, +-660, -959, -297, -837, 598, 404, 926, 1214, +136, 639, -766, -854, -764, -1246, 157, 35, +858, 1431, 464, 818, -413, -1132, -732, -1706, +12, 116, 824, 1898, 627, 1098, -331, -1192, +-740, -1680, -175, 263, 411, 1740, 322, 622, +-130, -1468, -24, -1383, 315, 589, 120, 1678, +-449, 325, -260, -1253, 578, -954, 751, 695, +-185, 1197, -1106, 62, -578, -1014, 719, -724, +1268, 311, 304, 695, -864, 238, -885, -255, +260, -341, 993, -2, 534, 352, -585, 391, +-887, -176, -166, -701, 667, -412, 667, 429, +35, 634, -400, -52, -235, -371, 304, 140, +501, 459, 52, -175, -715, -736, -699, -261, +248, 657, 1269, 540, 850, -242, -625, -610, +-1498, -81, -456, 432, 1390, 390, 1609, 18, +-205, -317, -1907, -430, -1167, -181, 1083, 412, +1929, 516, 362, -80, -1413, -701, -1104, -221, +598, 694, 1360, 726, 257, -366, -1044, -969, +-875, -273, 460, 749, 1154, 645, 430, -364, +-679, -819, -760, -91, 162, 819, 796, 745, +374, -280, -445, -1080, -578, -561, -66, 629, +475, 1092, 536, 125, 247, -1054, -259, -813, +-521, 543, -192, 1200, 513, 269, 601, -946, +-152, -806, -819, 325, -337, 735, 790, 34, +1116, -509, 10, -134, -1058, 348, -791, 215, +471, -161, 1033, -17, 397, 179, -620, -116, +-793, -453, 18, -227, 857, 425, 763, 574, +-135, -74, -850, -602, -625, -288, 415, 579, +958, 766, 412, -198, -634, -1175, -804, -679, +102, 898, 957, 1366, 638, -27, -387, -1573, +-830, -800, -228, 1185, 569, 1578, 625, -276, +-38, -1779, -451, -811, -279, 1063, 305, 1297, +676, -159, 276, -1033, -477, -341, -807, 565, +-46, 498, 820, -196, 728, -292, -282, -14, +-802, 11, -64, -172, 858, -81, 612, 396, +-495, 418, -942, -203, -107, -653, 816, -159, +631, 647, -278, 617, -525, -385, 91, -965, +652, -307, 272, 786, -385, 886, -503, -77, +-90, -927, 387, -519, 369, 534, 115, 868, +-170, -3, -170, -903, 144, -612, 426, 467, +164, 846, -364, 120, -393, -569, 148, -308, +461, 361, 10, 360, -413, -354, -35, -641, +646, -13, 645, 804, -172, 575, -689, -506, +-437, -948, 371, 16, 577, 1105, 18, 590, +-514, -940, -221, -1270, 696, 278, 876, 1459, +-107, 649, -1044, -1054, -609, -1154, 702, 273, +1021, 1259, -8, 522, -1037, -871, -494, -1214, +854, -128, 1186, 1278, 6, 1309, -1170, -328, +-771, -1917, 679, -1158, 1236, 1353, 213, 2358, +-1041, 219, -924, -2406, 366, -1848, 1252, 1091, +715, 2406, -457, 557, -1015, -1711, -361, -1448, +603, 441, 868, 1429, 175, 610, -784, -566, +-767, -996, 238, -483, 1297, 381, 942, 889, +-588, 480, -1637, -511, -557, -904, 1237, -7, +1586, 935, -154, 619, -1589, -637, -951, -1144, +991, -188, 1837, 908, 438, 892, -1401, -53, +-1474, -725, 245, -545, 1581, 158, 917, 578, +-949, 296, -1439, -346, 32, -588, 1757, -2, +1252, 624, -876, 319, -1824, -469, -450, -585, +1475, 295, 1368, 822, -339, 152, -1516, -754, +-684, -662, 987, 163, 1583, 574, 492, 394, +-1117, 63, -1492, -253, -221, -649, 1354, -511, +1363, 650, -211, 1320, -1482, 233, -807, -1633, +922, -1474, 1463, 910, 359, 2209, -1048, 520, +-934, -1882, 134, -1618, 802, 703, 347, 1767, +-257, 407, -231, -1119, 279, -784, 229, 363, +-265, 621, -292, -69, 352, -351, 750, 119, +29, 270, -915, -209, -765, -465, 496, 79, +1286, 712, 591, 360, -689, -471, -1048, -720, +-192, 32, 855, 497, 833, 196, -11, -367, +-869, -186, -659, 442, 377, 407, 1103, -295, +575, -687, -538, -76, -994, 737, -236, 587, +760, -512, 814, -1104, -77, -311, -787, 1046, +-429, 1237, 576, -112, 1020, -1354, 209, -894, +-944, 720, -1054, 1291, 269, 151, 1438, -1224, +907, -811, -866, 596, -1534, 1057, -114, 17, +1590, -780, 1237, -293, -757, 622, -1634, 469, +-288, -371, 1417, -706, 1160, -177, -456, 405, +-1373, 394, -357, 84, 940, -105, 1073, -106, +-106, -99, -850, 74, -413, 194, 452, 11, +579, -437, 20, -534, -366, 66, -169, 763, +224, 750, 280, 6, 38, -778, -115, -818, +-32, -34, 99, 853, 109, 735, -29, -303, +13, -1165, 39, -469, 49, 942, -7, 1312, +133, 11, 96, -1248, -34, -993, -238, 348, +-24, 983, 363, 419, 450, -395, -7, -533, +-488, -84, -397, 254, 213, 242, 659, 137, +349, 103, -297, -232, -745, -575, -238, -425, +593, 579, 1036, 1112, 364, 149, -716, -1293, +-1139, -1004, -274, 928, 919, 1692, 1171, -52, +-14, -1953, -1046, -998, -678, 1408, 588, 1732, +1017, -434, 188, -1840, -625, -467, -523, 1413, +98, 1140, 426, -605, 231, -1331, 12, -260, +-62, 861, -77, 715, -117, -263, 74, -717, +330, -166, 321, 560, -153, 623, -530, -219, +-265, -769, 330, -359, 747, 540, 362, 604, +-418, -295, -794, -725, -168, 94, 691, 1008, +884, 457, 0, -909, -807, -1089, -727, 373, +273, 1255, 887, 124, 563, -1333, -227, -706, +-638, 1227, -388, 1539, 185, -440, 676, -1777, +503, -624, -241, 1234, -799, 1159, -310, -510, +677, -1266, 839, -363, -107, 882, -810, 1027, +-277, 304, 671, -721, 624, -1119, -330, -457, +-759, 908, -68, 1249, 743, -92, 547, -1490, +-252, -822, -524, 1090, -54, 1637, 453, -14, +182, -1556, -171, -1074, -230, 646, 101, 1221, +176, 247, 90, -861, -11, -671, 171, 297, +195, 746, -48, 313, -367, -335, -305, -437, +229, -252, 553, 9, 277, 218, -388, 389, +-416, 102, 134, -370, 668, -322, 429, 375, +-445, 566, -905, -308, -242, -969, 897, -107, +992, 1209, -170, 787, -1103, -1062, -450, -1598, +856, 358, 986, 2121, -161, 1040, -1009, -1703, +-357, -2297, 664, 172, 593, 2435, -294, 1512, +-531, -1439, 226, -2381, 686, -253, 187, 2304, +-507, 1825, -496, -904, 177, -2523, 428, -977, +135, 1641, -268, 2020, -60, -95, 298, -1833, +325, -1031, -25, 1023, -287, 1593, -210, 91, +6, -1462, 198, -1130, 121, 497, 141, 1428, +6, 563, 9, -907, -62, -1186, -21, 31, +146, 1258, 163, 936, -50, -457, -245, -1335, +-142, -660, 125, 567, 179, 1051, 184, 388, +198, -451, 218, -702, -240, -236, -489, 410, +-290, 653, 583, 192, 688, -557, -39, -795, +-836, -77, -485, 737, 640, 690, 980, -235, +228, -817, -808, -188, -685, 641, 147, 630, +765, -378, 268, -696, -377, -147, -536, 537, +156, 181, 551, -394, 380, -171, -223, 486, +-302, 473, 58, -258, 262, -532, -176, -31, +-534, 184, -129, -176, 707, -227, 968, 495, +24, 730, -1048, -243, -921, -1158, 455, -403, +1415, 1173, 651, 1188, -1038, -560, -1551, -1774, +-134, -616, 1567, 1447, 1453, 1591, -272, -285, +-1622, -1689, -906, -780, 827, 1042, 1457, 1263, +236, -151, -1079, -1213, -1150, -497, 331, 646, +1269, 792, 814, -200, -639, -617, -1004, -115, +-100, 637, 819, 352, 469, -529, -414, -828, +-606, 134, -40, 1050, 455, 502, 457, -886, +214, -1069, -96, 473, -349, 1430, -492, 262, +-29, -1488, 614, -1103, 569, 950, -269, 1712, +-845, 9, -227, -1644, 872, -944, 943, 999, +-133, 1433, -1029, -127, -655, -1364, 455, -732, +901, 904, 233, 1303, -663, 6, -680, -1452, +364, -1023, 1138, 843, 490, 1879, -867, 383, +-1301, -1923, -40, -1880, 1308, 722, 1066, 2666, +-486, 1202, -1410, -1793, -486, -2538, 1034, -98, +1399, 2198, 151, 1743, -1274, -729, -1247, -2081, +232, -1055, 1424, 1069, 1067, 1963, -589, 828, +-1585, -1304, -694, -2064, 1205, -540, 1851, 1734, +323, 2033, -1767, -137, -1755, -2199, 368, -1594, +2137, 861, 1261, 2267, -1163, 1065, -2038, -1267, +-328, -2040, 1961, -495, 1694, 1547, -592, 1689, +-2235, -314, -964, -1999, 1402, -1030, 2039, 1318, +90, 2047, -1802, 86, -1366, -1911, 762, -1233, +1992, 895, 842, 1563, -1259, 21, -1958, -1405, +-371, -843, 1626, 781, 1808, 1374, -8, 436, +-1723, -897, -1464, -1238, 524, -288, 1922, 963, +1154, 1082, -1007, -97, -2038, -1254, -684, -809, +1542, 694, 1916, 1340, 192, 396, -1685, -766, +-1461, -934, 409, -227, 1748, 193, 869, 370, +-884, 507, -1398, 389, -179, -336, 1077, -905, +845, -357, -221, 865, -757, 1000, -258, -346, +367, -1325, 509, -502, 10, 1081, -256, 1174, +-317, -290, -69, -1313, 199, -516, 386, 756, +213, 1028, -94, 21, -214, -779, -110, -595, +11, 161, 5, 604, 58, 131, 137, -402, +106, -344, -19, 396, -106, 716, 116, -2, +222, -789, 57, -803, -392, 228, -312, 886, +193, 686, 565, -327, 241, -928, -341, -520, +-421, 638, 73, 1105, 455, 66, 210, -1274, +-165, -988, -322, 840, -43, 1651, 121, 169, +131, -1764, 134, -1231, 228, 1042, -8, 2056, +-291, 267, -340, -1927, 90, -1725, 531, 649, +290, 2224, -244, 1154, -517, -1276, -70, -2237, +497, -418, 412, 1894, -154, 1943, -528, -623, +-82, -2502, 477, -1118, 482, 1912, -219, 2530, +-675, -206, -261, -2745, 436, -1705, 708, 1424, +261, 2534, -288, 504, -627, -1717, -358, -1690, +228, 85, 691, 1304, 460, 1194, -331, 171, +-781, -1099, -244, -1459, 720, -296, 843, 1550, +-131, 1711, -945, -303, -534, -2167, 529, -1239, +930, 1272, 188, 2212, -771, 309, -693, -1877, +293, -1693, 1002, 560, 482, 1929, -744, 945, +-959, -1058, 32, -1713, 1082, -315, 643, 1287, +-578, 1368, -1020, -56, -58, -1367, 1025, -1007, +748, 417, -319, 1276, -958, 601, -371, -789, +475, -1105, 667, -165, 248, 962, -384, 902, +-526, -62, -132, -880, 532, -708, 639, 76, +61, 632, -646, 593, -649, 42, 106, -471, +711, -592, 545, -223, -199, 484, -630, 791, +-296, 269, 434, -622, 762, -918, 223, -54, +-665, 805, -1044, 616, -164, -453, 1131, -884, +1325, -68, -21, 997, -1465, 908, -1261, -417, +608, -1325, 1837, -805, 861, 766, -1254, 1418, +-1959, 310, -224, -1203, 1827, -1109, 1676, 522, +-314, 1609, -1792, 441, -1079, -1280, 746, -1366, +1502, 311, 523, 1426, -820, 583, -1118, -850, +-262, -1014, 810, 124, 1012, 922, 306, 597, +-686, -317, -883, -614, -173, -294, 629, 19, +703, 75, -12, 69, -552, 395, -392, 527, +291, 10, 572, -862, 192, -861, -347, 291, +-496, 1334, -23, 778, 449, -963, 480, -1595, +-209, -345, -556, 1393, -219, 1500, 634, -49, +624, -1290, -103, -1143, -769, 30, -390, 963, +415, 1033, 629, 174, 7, -914, -547, -1273, +-158, -259, 364, 1289, 505, 1503, 29, 103, +-422, -1541, -493, -1488, -115, 71, 512, 1398, +720, 1202, 89, -3, -699, -1020, -705, -933, +266, -202, 949, 671, 479, 857, -610, 362, +-882, -476, 3, -753, 734, -391, 521, 205, +-214, 505, -380, 466, -253, 220, 136, -283, +319, -762, 405, -548, -25, 351, -567, 1113, +-552, 615, 254, -719, 954, -1368, 402, -346, +-589, 1199, -790, 1513, 161, -122, 641, -1753, +291, -1421, -373, 720, -179, 2138, 175, 1001, +93, -1376, -361, -2087, -220, -202, 481, 1817, +874, 1504, 39, -711, -908, -1844, -790, -512, +238, 1256, 873, 1229, 503, -370, -289, -1162, +-637, -241, -161, 781, 337, 565, 451, -464, +88, -751, -328, -3, -288, 631, 28, 500, +198, -252, 90, -508, -130, -220, 38, 406, +347, 444, 157, -118, -285, -633, -406, -365, +106, 518, 339, 785, -40, -42, -328, -857, +49, -514, 619, 700, 302, 1028, -569, -96, +-647, -1272, 275, -903, 830, 686, 220, 1401, +-724, 436, -617, -1066, 226, -987, 764, 304, +435, 1130, -223, 265, -516, -945, -232, -844, +192, 381, 308, 1111, 134, 280, -204, -725, +-165, -720, 7, 301, 315, 716, 206, 102, +-116, -548, -238, -278, -63, 361, 122, 160, +193, -461, -96, -329, -265, 696, -140, 1003, +397, -177, 625, -1342, 89, -860, -741, 725, +-870, 1346, 210, 216, 1148, -987, 727, -848, +-729, 300, -1362, 877, -152, 431, 1354, -330, +1232, -583, -561, -447, -1673, -60, -577, 426, +1195, 866, 1492, 417, -280, -670, -1560, -1416, +-842, -490, 1073, 1340, 1582, 1823, 269, 277, +-1483, -1966, -1421, -2120, 221, 16, 1713, 2262, +1261, 2214, -678, -120, -1884, -2273, -892, -2076, +1282, 166, 1955, 2059, 424, 1727, -1597, -188, +-1732, -1605, -5, -1339, 1713, 14, 1482, 999, +-295, 1199, -1607, 459, -1213, -588, 587, -1341, +1808, -921, 900, 536, -985, 1490, -1869, 943, +-422, -590, 1574, -1345, 1633, -624, -311, 498, +-1814, 949, -995, 441, 1017, -247, 1687, -646, +250, -537, -1379, 65, -1141, 507, 425, 650, +1193, 19, 427, -403, -706, -440, -719, -126, +217, 78, 721, 140, 213, 319, -548, 358, +-518, -79, 94, -603, 615, -523, 165, 276, +-325, 752, -387, 416, 303, -296, 550, -647, +-66, -473, -789, -152, -555, 491, 657, 995, +1161, 732, 360, -613, -1153, -1609, -1349, -886, +-172, 948, 1563, 1780, 1641, 583, 134, -1131, +-1786, -1474, -1981, -282, -249, 955, 2048, 1117, +2427, 284, 306, -574, -2294, -878, -2626, -505, +-102, 178, 2618, 677, 2486, 740, -222, 257, +-2656, -486, -2123, -1074, 585, -680, 2484, 502, +1671, 1557, -736, 904, -1975, -834, -1158, -1905, +612, -831, 1402, 1170, 773, 1903, -361, 653, +-852, -1189, -646, -1693, -39, -618, 584, 1042, +867, 1658, 486, 719, -575, -1101, -1371, -1951, +-787, -745, 834, 1549, 1843, 2318, 801, 506, +-1298, -2149, -2110, -2465, -433, 22, 1797, 2591, +2008, 2208, -163, -621, -2079, -2658, -1520, -1715, +734, 950, 1913, 2336, 827, 1330, -912, -715, +-1325, -1804, -319, -1371, 746, 59, 742, 1294, +134, 1708, -433, 619, -373, -971, -159, -1902, +242, -1058, 340, 746, 282, 1747, -97, 1208, +-451, -401, -263, -1446, 161, -1253, 428, -1, +145, 1102, -165, 1225, -374, 302, -47, -780, +192, -943, 524, -261, 293, 365, -429, 328, +-950, -55, -460, 86, 908, 500, 1371, 380, +184, -529, -1482, -1168, -1393, -521, 441, 853, +1881, 1588, 987, 519, -1035, -1184, -1912, -1811, +-379, -472, 1428, 1596, 1394, 1992, -390, 165, +-1412, -2039, -551, -1968, 1077, 513, 1046, 2378, +-472, 1497, -1275, -1322, -419, -2470, 1047, -783, +1038, 1846, -138, 2249, -1004, 271, -630, -1952, +140, -1925, 678, -3, 605, 1895, 299, 1627, +-395, -257, -1080, -1926, -853, -1318, 359, 687, +1653, 1867, 1398, 911, -375, -966, -1981, -1566, +-1746, -533, 290, 838, 2155, 1120, 2027, 492, +-91, -332, -2345, -940, -2331, -938, -41, -179, +2526, 1194, 2663, 1763, 150, 418, -2624, -1811, +-2742, -2439, -237, -289, 2288, 2355, 2638, 2592, +534, -34, -1827, -2401, -2593, -2167, -1086, 126, +1428, 1868, 2743, 1686, 1585, 179, -1308, -1125, +-2977, -1563, -1732, -726, 1298, 741, 2840, 1651, +1538, 1056, -1103, -638, -2392, -1658, -1435, -1062, +551, 450, 1891, 1368, 1456, 1078, 79, -40, +-1465, -966, -1746, -1209, -511, -489, 1357, 738, +1924, 1457, 642, 796, -1341, -796, -2047, -1791, +-553, -882, 1575, 1194, 2021, 2199, 114, 821, +-1996, -1760, -1614, -2577, 801, -691, 2272, 2286, +831, 2763, -1658, 415, -2075, -2512, 106, -2715, +2048, -118, 1544, 2466, -664, 2485, -1887, 46, +-1096, -2158, 684, -2245, 1632, -269, 1002, 1657, +-488, 1945, -1466, 567, -1048, -1021, 362, -1519, +1446, -647, 1035, 443, -525, 918, -1598, 531, +-903, -69, 847, -256, 1670, -336, 578, -196, +-1199, -338, -1697, 38, -269, 456, 1458, 854, +1561, 384, -107, -570, -1595, -1329, -1480, -858, +338, 494, 1535, 1596, 1081, 1239, -574, -233, +-1328, -1612, -491, -1401, 656, 49, 719, 1414, +4, 1468, -355, 37, -202, -1313, -22, -1500, +22, -138, 56, 1359, 219, 1652, -39, 208, +-340, -1488, -190, -1774, 566, -193, 796, 1667, +-103, 1784, -1153, -84, -1044, -1918, 297, -1631, +1554, 544, 1457, 2204, -169, 1384, -1840, -955, +-2020, -2358, -64, -1166, 2250, 1055, 2613, 2291, +349, 1204, -2580, -882, -3067, -2255, -635, -1502, +2608, 595, 3484, 2501, 1168, 1995, -2367, -435, +-3998, -2809, -1962, -2553, 2053, 245, 4409, 2990, +2523, 3010, -1867, 175, -4554, -2888, -2759, -3310, +1653, -669, 4177, 2546, 2546, 3366, -1332, 1026, +-3580, -2133, -2181, -3180, 868, -1190, 2567, 1700, +1550, 2820, -665, 1251, -1387, -1237, -643, -2251, +476, -1286, -22, 590, -632, 1482, -148, 1244, +1521, 265, 1697, -596, -532, -1188, -3036, -1018, +-2260, -167, 1443, 1091, 4080, 1405, 2229, 609, +-2237, -849, -4318, -1448, -1811, -868, 2513, 448, +4013, 1363, 1507, 1211, -2148, -35, -3449, -1383, +-1469, -1620, 1519, -246, 2962, 1561, 1815, 1944, +-824, 237, -2584, -1822, -2158, -1993, 321, -12, +2458, 2015, 2406, 1750, -11, -300, -2281, -1800, +-2366, -1236, -236, 285, 2037, 961, 2125, 604, +414, 370, -1497, 468, -1970, -260, -858, -1617, +919, -1799, 1935, 326, 1293, 2784, -499, 2461, +-1893, -610, -1719, -3076, 100, -2382, 1577, 539, +1630, 2506, 253, 1995, -1136, -19, -1554, -1616, +-657, -1734, 632, -509, 1431, 976, 781, 1522, +-578, 644, -1394, -624, -502, -1042, 756, -302, +980, 268, -282, 233, -1036, -282, -288, -22, +1227, 654, 1063, 911, -591, 127, -1791, -1209, +-862, -1719, 1121, -531, 1881, 1547, 730, 2478, +-1072, 1008, -1626, -1851, -808, -3043, 666, -1200, +1332, 1943, 1061, 3262, 34, 1471, -1009, -1643, +-1304, -3289, -573, -2068, 771, 1007, 1618, 3417, +1067, 2823, -579, -575, -1936, -3697, -1372, -3241, +695, 613, 2160, 4014, 1386, 3214, -834, -912, +-2233, -4137, -1194, -3126, 1074, 1031, 2065, 4132, +854, 3255, -1235, -893, -2032, -4178, -629, -3450, +1302, 838, 1905, 4337, 586, 3424, -1346, -1053, +-2033, -4305, -730, -3068, 1139, 1230, 1856, 3782, +839, 2439, -765, -913, -1571, -2619, -1041, -1780, +208, 137, 947, 1192, 848, 1267, 371, 762, +-255, -92, -549, -914, -834, -1233, -710, -632, +-44, 583, 1126, 1241, 1679, 1152, 765, 126, +-1271, -1172, -2499, -1734, -1450, -922, 1105, 1108, +2973, 2349, 2109, 1476, -760, -1005, -3102, -2539, +-2465, -1754, 371, 651, 2899, 2352, 2722, 2001, +95, -50, -2480, -2054, -2599, -2397, -517, -477, +1779, 1921, 2394, 2648, 1054, 783, -927, -1814, +-2071, -2520, -1585, -899, 93, 1473, 1881, 2280, +2046, 1055, 339, -1080, -1736, -2182, -2140, -1255, +-521, 1015, 1473, 2292, 1845, 1233, 532, -1233, +-1083, -2246, -1670, -931, -823, 1384, 864, 2018, +1812, 694, 787, -1055, -1375, -1804, -2246, -1002, +-435, 501, 2242, 1862, 2522, 1806, -410, 106, +-3163, -2097, -2570, -2578, 960, -682, 3328, 2052, +2364, 3045, -991, 1425, -3114, -1517, -2209, -3162, +601, -2234, 2442, 713, 1977, 3076, -163, 2828, +-1842, 1, -1619, -2656, -106, -2853, 1129, -498, +994, 1897, 177, 2361, -350, 918, -314, -819, +-125, -1608, -223, -1274, -413, -245, -59, 839, +611, 1479, 1034, 1092, 413, -96, -837, -1369, +-1528, -1581, -775, -571, 1035, 1092, 2041, 1833, +960, 1091, -1344, -792, -2422, -1905, -983, -1332, +1618, 624, 2702, 1830, 879, 1290, -2000, -466, +-2783, -1458, -698, -988, 2128, 248, 2721, 847, +457, 579, -2341, 73, -2671, -99, -315, -197, +2337, -433, 2605, -479, 113, 71, -2514, 941, +-2497, 840, -36, -393, 2209, -1532, 2161, -904, +161, 1197, -1679, 2247, -2004, 622, -749, -2217, +841, -2770, 1771, 3, 1370, 3164, -214, 2926, +-1570, -592, -1825, -3474, -511, -2718, 1044, 739, +1873, 3085, 1118, 2440, -424, -254, -1778, -2219, +-1632, -2175, -170, -424, 1450, 1387, 1598, 1878, +535, 895, -947, -624, -1226, -1356, -648, -934, +234, -99, 516, 572, 517, 825, 425, 816, +324, 409, -218, -525, -1001, -1301, -1207, -1280, +-311, -13, 1176, 1434, 1922, 2065, 1073, 927, +-1166, -1219, -2679, -2714, -1905, -1952, 968, 849, +3256, 3305, 2523, 2903, -1032, -400, -3723, -3573, +-2623, -3500, 999, -39, 3508, 3436, 2224, 3668, +-1074, 507, -2868, -2812, -1616, -3398, 735, -908, +1709, 2081, 874, 2887, -266, 1215, -663, -1348, +-512, -2157, -380, -1167, -209, 578, 169, 1320, +623, 976, 562, 248, -266, -413, -777, -783, +-359, -719, 412, -39, 382, 672, -316, 682, +-723, -117, -27, -581, 1000, -13, 830, 766, +-549, 487, -1470, -759, -780, -1450, 625, -299, +1362, 1405, 665, 1847, -437, 352, -1065, -1555, +-762, -1946, -98, -609, 552, 1173, 752, 1857, +586, 1132, 7, -337, -794, -1443, -1216, -1470, +-607, -524, 632, 781, 1460, 1425, 1013, 1029, +-563, 86, -1668, -763, -1131, -968, 352, -666, +1290, -196, 889, 375, -215, 939, -860, 1290, +-636, 732, -58, -859, 36, -2340, -3, -1848, +371, 711, 655, 3154, 248, 2707, -811, -435, +-1263, -3286, -366, -2958, 984, 62, 1146, 2833, +-44, 2741, -1144, 387, -812, -1941, 504, -2064, +957, -531, 5, 976, -1114, 1133, -865, 458, +614, 4, 1520, -78, 553, -278, -1246, -745, +-1887, -571, -438, 297, 1312, 1173, 1619, 676, +227, -439, -1101, -990, -1182, -166, -190, 741, +459, 524, 332, -626, -57, -1041, 34, 89, +393, 1558, 247, 1417, -543, -604, -1282, -2301, +-742, -1607, 747, 1020, 1882, 2754, 1012, 1723, +-1072, -1145, -2381, -2775, -1258, -1681, 1080, 1176, +2204, 2715, 1023, 1533, -1002, -1229, -1806, -2504, +-878, -1122, 520, 1540, 976, 2240, 391, 564, +-312, -1659, -381, -1767, 56, 0, 125, 1627, +-447, 1239, -902, -249, -375, -1322, 952, -804, +1760, 412, 452, 1158, -1787, 594, -2716, -440, +-762, -1082, 2215, -464, 3218, 622, 825, 1071, +-2639, 429, -3620, -705, -1095, -1008, 2485, -246, +3561, 918, 1092, 982, -2485, 36, -3435, -1126, +-1056, -786, 2130, 450, 2729, 1251, 465, 413, +-1910, -939, -1934, -1046, 11, 281, 1425, 1377, +944, 726, -545, -784, -1214, -1494, -589, -452, +463, 879, 856, 1406, 520, 679, -366, -377, +-913, -1225, -939, -1130, -37, -137, 760, 1267, +1014, 1527, 293, 358, -828, -1135, -1417, -1357, +-778, -250, 584, 794, 1375, 842, 881, 324, +-502, -34, -1567, -181, -1073, -452, 308, -672, +1252, -259, 687, 596, -628, 1059, -1205, 583, +-210, -355, 918, -793, 716, -586, -832, -70, +-1462, 215, -339, 390, 1431, 630, 1565, 648, +-358, 86, -2218, -1022, -1662, -1487, 730, -572, +2247, 1414, 1496, 2367, -933, 1208, -2415, -1483, +-1660, -3146, 475, -1902, 1954, 1368, 1645, 3805, +78, 2771, -1514, -913, -1855, -3963, -1107, -3355, +554, 259, 1653, 3665, 1697, 3758, 231, 638, +-1279, -2816, -2221, -3744, -1392, -1402, 266, 1763, +1794, 3355, 2135, 2011, 797, -378, -1395, -2286, +-2825, -2285, -1970, -966, 586, 1027, 2699, 2470, +2288, 2198, -357, -26, -2449, -2416, -2103, -2625, +82, -188, 1482, 2279, 914, 2156, -357, -32, +-698, -1661, 123, -935, 411, 510, -228, 846, +-1158, -299, -989, -863, 302, -51, 1469, 1328, +1178, 1327, -228, -235, -1572, -1746, -1692, -1697, +-495, 87, 1124, 1773, 1622, 1978, 733, 440, +-745, -1356, -1483, -1915, -1071, -759, -48, 813, +645, 1606, 692, 956, 596, -63, 262, -885, +-569, -903, -1477, -639, -1376, 42, 73, 799, +1768, 1402, 1910, 941, 202, -486, -1897, -1882, +-2542, -1617, -943, 328, 1492, 2089, 2482, 1906, +1252, -80, -1085, -1734, -2419, -1703, -1787, -184, +338, 1068, 1736, 1486, 1751, 841, 161, -137, +-1387, -1254, -1914, -1540, -825, -598, 903, 1207, +1601, 2014, 716, 1005, -898, -925, -1440, -1705, +-476, -802, 535, 557, 610, 880, -214, 322, +-645, -96, -77, 196, 501, 424, 446, -119, +-305, -845, -980, -860, -1122, 150, -37, 935, +1035, 918, 1438, 251, 423, -152, -1238, -527, +-2122, -810, -1114, -981, 797, -9, 2082, 1443, +1514, 2199, -484, 833, -2149, -1565, -2096, -2979, +-269, -1687, 1653, 1296, 2087, 3234, 485, 2431, +-1358, -577, -1917, -2695, -773, -2399, 686, -86, +1139, 1565, 344, 1665, -473, 719, -463, 61, +-69, -395, 72, -1084, -356, -1385, -504, -563, +-206, 1157, 393, 2012, 629, 1168, 443, -583, +-252, -1532, -1069, -1333, -1359, -399, -365, 500, +1089, 1325, 1715, 1635, 690, 791, -986, -1031, +-1945, -2402, -1312, -1690, 122, 686, 1252, 2570, +1406, 2055, 575, -177, -580, -1984, -1442, -1674, +-1420, -42, -707, 1187, 817, 1013, 1755, -15, +1295, -463, -497, -234, -1991, 378, -1846, 340, +70, -59, 1571, -622, 1258, -595, -141, -118, +-1139, 697, -805, 1176, 89, 805, 458, -338, +-80, -1560, -526, -1500, -326, -92, 301, 1724, +692, 2020, 233, 581, -570, -1388, -959, -1938, +-666, -874, 141, 811, 647, 1531, 735, 1024, +349, 1, -346, -726, -1081, -774, -1268, -568, +-359, -177, 991, 371, 1689, 1024, 713, 1093, +-1006, 189, -1933, -1107, -1285, -1645, 400, -616, +1659, 1138, 1488, 1962, 4, 1052, -1605, -1016, +-1890, -2078, -583, -1165, 1170, 981, 1875, 2186, +859, 1260, -1126, -903, -2226, -2119, -1221, -1164, +786, 842, 2094, 2072, 1339, 1310, -743, -555, +-2173, -1868, -1750, -1635, 161, 106, 1656, 1833, +1868, 2163, 344, 537, -1328, -1614, -2076, -2390, +-1257, -919, 463, 1254, 1793, 2170, 1674, 1097, +19, -561, -1660, -1366, -2116, -900, -515, -50, +1357, 551, 1636, 597, 154, 389, -1170, 86, +-1074, -3, 223, -7, 762, -286, -135, -706, +-882, -712, -575, 316, 665, 1434, 1130, 1518, +491, 3, -988, -1557, -1596, -1941, -806, -567, +650, 1122, 1485, 2010, 1019, 1363, -345, -126, +-1510, -1516, -1402, -1877, -216, -950, 1119, 687, +1430, 2088, 561, 2061, -805, 467, -1681, -1896, +-1495, -2875, 214, -1447, 1808, 1618, 2064, 3425, +190, 2162, -2053, -1157, -2518, -3271, -752, -2408, +1463, 549, 2109, 2518, 1019, 2402, -530, 503, +-1451, -1175, -1605, -2116, -1008, -1635, 337, -192, +1792, 1747, 2114, 2653, 505, 1351, -1923, -1205, +-2882, -2926, -1475, -2011, 1208, 614, 2672, 2596, +1895, 2295, -292, 217, -2087, -1772, -2315, -2181, +-783, -926, 974, 908, 1819, 1868, 1228, 1495, +-57, 18, -1169, -1319, -1307, -1649, -815, -729, +-67, 824, 798, 1696, 1149, 1118, 685, -450, +-281, -1527, -1148, -1012, -1125, 495, -289, 1417, +606, 650, 661, -749, 259, -1304, -1, -190, +-14, 1261, -82, 1433, -657, -61, -993, -1695, +-491, -1668, 763, 121, 1433, 2026, 995, 2106, +-548, 213, -1734, -1984, -1666, -2514, -183, -838, +1474, 1751, 1922, 2880, 737, 1623, -1201, -1180, +-2041, -2895, -1266, -2114, 419, 510, 1576, 2553, +1409, 2348, 149, 246, -1017, -1839, -1460, -2199, +-989, -771, 138, 1106, 1132, 1813, 1315, 1063, +476, -351, -769, -1064, -1566, -881, -1132, -253, +119, 134, 1194, 395, 1185, 717, 343, 946, +-684, 335, -1109, -869, -863, -1609, -168, -887, +691, 762, 908, 1730, 465, 1040, -359, -349, +-844, -1169, -621, -648, 153, 104, 358, 402, +9, -58, -333, -220, 43, 253, 532, 974, +659, 857, -275, -446, -1259, -1668, -1318, -1545, +-85, 232, 1358, 1899, 1832, 2016, 723, 390, +-1259, -1386, -2321, -1992, -1477, -1080, 641, 513, +2180, 1708, 1899, 1602, -118, 321, -1957, -1199, +-2161, -1599, -457, -655, 1407, 681, 2029, 1220, +796, 709, -1046, -175, -1980, -744, -1232, -633, +502, -75, 1722, 583, 1340, 673, -152, 101, +-1412, -622, -1453, -616, -405, 66, 644, 669, +1130, 483, 796, -186, 222, -395, -694, -92, +-1320, 258, -1255, -56, -195, -442, 1259, -296, +1895, 570, 1025, 1126, -819, 544, -1950, -741, +-1873, -1651, -554, -1057, 1095, 470, 2250, 1842, +2060, 1814, 149, 407, -2363, -1517, -3411, -2438, +-1503, -1494, 1887, 861, 3769, 2745, 2165, 2434, +-1234, -75, -3268, -2616, -2221, -2838, 276, -452, +1900, 2310, 1651, 2804, 413, 653, -612, -1945, +-985, -2416, -883, -523, -474, 1694, 324, 1914, +801, 227, 648, -1390, 55, -1298, -443, 138, +-596, 1125, -329, 718, -47, -334, 295, -795, +271, -364, 52, 256, -290, 484, -151, 487, +275, 262, 339, -233, -351, -982, -945, -1037, +-524, 108, 710, 1626, 1382, 1840, 613, 81, +-1078, -2032, -1792, -2353, -770, -368, 1031, 1955, +1815, 2445, 806, 809, -836, -1273, -1782, -1975, +-1037, -1152, 412, 285, 1423, 1189, 1070, 1237, +-106, 567, -1062, -404, -1083, -955, -276, -833, +508, -60, 883, 503, 541, 640, -190, 265, +-823, -125, -822, -370, -182, -270, 614, 84, +901, 422, 417, 241, -421, -328, -967, -720, +-879, -251, 2, 676, 977, 1106, 1146, 421, +227, -800, -1003, -1305, -1367, -707, -403, 583, +897, 1245, 1113, 971, 259, -50, -743, -881, +-690, -1066, -97, -457, 406, 435, 130, 925, +-176, 625, -276, -128, -44, -560, 268, -340, +354, 142, 298, 218, -264, -110, -883, -446, +-1085, -221, -11, 393, 1486, 936, 1852, 784, +276, -173, -2059, -1351, -2618, -1731, -635, -570, +2202, 1428, 2824, 2699, 811, 1674, -1847, -1007, +-2659, -3166, -1154, -2709, 952, 132, 1949, 2835, +1393, 3213, 222, 1062, -1078, -1611, -1718, -2976, +-1411, -2256, -55, -243, 1544, 2068, 2221, 3072, +1160, 2169, -867, -607, -2511, -3150, -2264, -3616, +-369, -1118, 2003, 2384, 2819, 4223, 1627, 2633, +-876, -1075, -2843, -3782, -2668, -3341, -575, -287, +2096, 2451, 2998, 2942, 1745, 1247, -1028, -734, +-2765, -1734, -2312, -1476, -42, -647, 1787, 352, +1949, 1020, 663, 1231, -584, 643, -1027, -279, +-882, -1031, -559, -971, 15, -259, 597, 462, +830, 687, 464, 375, -49, 58, -341, -96, +-426, -87, -617, -242, -657, -451, -73, -487, +833, -70, 1385, 703, 737, 1146, -623, 718, +-1671, -556, -1291, -1527, -65, -1282, 1135, 27, +1433, 1228, 807, 1401, -196, 691, -1113, -289, +-1396, -1062, -921, -1311, 293, -779, 1484, 522, +1707, 1604, 587, 1392, -1293, -77, -2123, -1502, +-1179, -1456, 893, -117, 2023, 1157, 1221, 1130, +-616, 69, -1670, -842, -983, -673, 358, 124, +1126, 641, 735, 301, -82, -323, -807, -547, +-827, -143, -161, 314, 591, 387, 748, 139, +380, -22, -229, -24, -534, -124, -544, -436, +-470, -517, -126, -26, 527, 728, 1189, 947, +902, 274, -333, -636, -1632, -975, -1563, -502, +-137, 202, 1463, 628, 1788, 561, 541, 199, +-963, -295, -1454, -398, -561, -112, 292, 257, +474, 9, 50, -608, 129, -582, 586, 465, +858, 1508, -21, 996, -1425, -776, -1814, -2048, +-545, -1258, 1461, 707, 2322, 1987, 1354, 1264, +-913, -348, -2384, -1505, -1849, -1209, 133, -167, +1781, 871, 1923, 1128, 547, 672, -1011, -263, +-1631, -917, -911, -954, 292, -398, 1059, 340, +749, 857, 163, 1029, -265, 498, -333, -482, +-294, -1407, -492, -1229, -400, 20, 332, 1307, +1000, 1461, 736, 355, -213, -879, -1025, -1258, +-839, -603, 124, 416, 865, 883, 571, 547, +-224, -220, -523, -511, -188, -202, 233, 253, +203, 125, -8, -296, -155, -356, -62, 109, +31, 534, 20, 399, -9, -75, 28, -348, +122, -345, 88, -196, -19, -82, -265, 89, +-377, 343, 5, 366, 473, 247, 613, -142, +98, -320, -556, -450, -770, -319, -175, -77, +542, 351, 745, 637, 165, 461, -553, -69, +-592, -565, 143, -495, 718, -156, 240, 80, +-674, 54, -777, 132, 250, 492, 1011, 585, +603, 29, -433, -869, -824, -1089, -361, -255, +209, 843, 299, 1112, 208, 419, 342, -471, +296, -687, -135, -463, -773, -130, -734, -66, +26, 196, 971, 599, 1035, 839, 294, 391, +-838, -664, -1368, -1401, -714, -1139, 678, 243, +1573, 1554, 1141, 1666, -375, 268, -1591, -1369, +-1290, -1783, 70, -575, 1293, 992, 1299, 1439, +320, 629, -812, -542, -1174, -933, -584, -696, +326, -37, 952, 431, 718, 873, 204, 677, +-463, -19, -639, -1089, -648, -1318, -154, -349, +429, 1187, 961, 1817, 729, 659, -253, -1189, +-978, -2137, -693, -942, 375, 1177, 777, 2211, +206, 1051, -730, -1240, -644, -2183, 462, -911, +1447, 1307, 973, 2088, -736, 603, -2174, -1430, +-1653, -2051, 562, -501, 2744, 1469, 2432, 2051, +-155, 679, -2571, -1305, -2610, -1972, -366, -944, +1804, 820, 2149, 1474, 847, 849, -576, -233, +-1297, -531, -890, -238, -171, -193, 313, -560, +362, -705, 378, 96, 531, 1178, 647, 1489, +104, 509, -1046, -1036, -1457, -1809, -635, -1244, +1039, 285, 1770, 1472, 1066, 1461, -569, 436, +-1389, -609, -966, -981, 18, -731, 740, -388, +643, 33, 201, 538, -146, 966, -4, 748, +87, -150, 10, -998, -443, -1045, -620, -219, +-76, 629, 783, 896, 944, 391, 279, -350, +-657, -727, -780, -395, -135, 405, 323, 823, +216, 294, -160, -778, 59, -1301, 552, -415, +843, 1030, 48, 1809, -1066, 891, -1447, -802, +-436, -1967, 1001, -1581, 1693, -44, 1087, 1476, +-232, 1942, -1143, 1013, -1193, -558, -657, -1636, +89, -1511, 741, -463, 1078, 645, 1053, 1247, +472, 1102, -643, 435, -1551, -500, -1493, -1190, +-363, -1141, 1223, -421, 2033, 627, 1527, 1253, +-117, 1177, -1509, 234, -2038, -956, -1255, -1608, +274, -1075, 1832, 325, 2451, 1560, 1387, 1609, +-919, 438, -2845, -1238, -2493, -1986, -121, -1149, +2424, 884, 2779, 2228, 1026, 1516, -1197, -730, +-2132, -2326, -1507, -1607, 17, 545, 1319, 2090, +1661, 1606, 846, -174, -532, -1651, -1367, -1745, +-1047, -497, -9, 1010, 897, 1791, 1215, 1195, +759, -235, -292, -1557, -1339, -1811, -1429, -747, +-157, 912, 1607, 2081, 2116, 1623, 561, -120, +-1590, -2005, -2316, -2216, -685, -607, 1510, 1529, +2224, 2234, 758, 1011, -1141, -899, -1738, -1761, +-617, -1162, 804, 139, 1259, 938, 553, 1004, +-336, 500, -479, -154, -248, -731, -105, -950, +-176, -482, -63, 360, 430, 1000, 889, 802, +595, -38, -374, -871, -1105, -957, -856, -337, +186, 565, 1055, 980, 927, 685, 181, -180, +-650, -951, -796, -1100, -220, -436, 582, 661, +748, 1312, 155, 999, -540, -170, -651, -1175, +105, -1336, 797, -493, 586, 543, -239, 1163, +-664, 976, -399, 182, 290, -726, 660, -1190, +398, -852, -127, 137, -447, 1047, -306, 1247, +126, 369, 312, -819, 222, -1459, 78, -844, +38, 451, 11, 1308, -70, 1085, -223, -5, +-158, -848, 188, -1087, 500, -567, 427, 152, +-5, 758, -506, 857, -660, 296, -223, -476, +647, -761, 1114, -288, 658, 340, -380, 318, +-1282, -247, -1039, -553, 176, -25, 1358, 739, +1274, 812, 226, -51, -822, -978, -972, -918, +-339, -48, 220, 751, 457, 634, 461, -10, +429, -393, 242, -251, -141, 36, -524, -54, +-568, -184, -190, -45, 345, 396, 870, 499, +916, -30, 59, -741, -988, -881, -1280, -177, +-250, 731, 1160, 1064, 1618, 587, 544, -283, +-874, -981, -1446, -1114, -742, -654, 470, 324, +1209, 1216, 1062, 1430, 370, 597, -485, -825, +-1107, -1795, -939, -1538, -113, -108, 976, 1458, +1465, 2023, 880, 982, -411, -876, -1364, -2044, +-1150, -1510, -104, 217, 949, 1514, 1276, 1323, +797, 111, 20, -814, -811, -750, -1080, -219, +-780, 87, 298, -47, 1259, -9, 1453, 354, +368, 595, -1047, 199, -1518, -595, -432, -926, +1101, -372, 1533, 479, 373, 833, -1084, 396, +-1250, -253, -8, -594, 1148, -508, 1107, -203, +179, 160, -627, 531, -607, 580, -272, 176, +34, -524, 181, -895, 433, -579, 619, 194, +482, 855, -46, 858, -585, 241, -562, -631, +-140, -1056, 258, -734, 399, 60, 379, 734, +381, 848, 270, 545, -15, -28, -456, -665, +-529, -1121, -243, -932, 217, 45, 550, 1120, +775, 1407, 634, 617, 70, -613, -794, -1305, +-1189, -1174, -568, -333, 710, 608, 1497, 1117, +1185, 854, 112, 41, -882, -614, -1208, -767, +-831, -509, 29, -198, 1047, 111, 1616, 489, +1079, 688, -356, 330, -1542, -402, -1354, -859, +-37, -456, 1136, 348, 1130, 731, 468, 237, +-79, -589, -230, -824, -369, -249, -500, 645, +-292, 910, 408, 371, 917, -517, 637, -921, +-100, -542, -449, 110, -287, 471, 82, 204, +58, -26, -71, 36, 114, 303, 584, 224, +781, -336, 214, -749, -596, -716, -992, -49, +-410, 543, 562, 900, 1143, 719, 810, 43, +0, -814, -614, -1394, -692, -952, -251, 344, +372, 1566, 855, 1599, 654, 187, -136, -1550, +-731, -2072, -499, -798, 352, 1207, 925, 2026, +686, 1070, -78, -778, -657, -1617, -563, -1081, +-155, 73, 457, 666, 831, 559, 869, 362, +249, 264, -654, 102, -1178, -523, -654, -1048, +711, -803, 1614, 270, 1306, 1209, -177, 995, +-1369, -173, -1492, -1063, -256, -848, 1070, 118, +1778, 664, 1238, 410, -90, -271, -1393, -528, +-1668, -252, -542, 188, 1048, 451, 1904, 292, +1289, -82, -179, -488, -1366, -628, -1181, -322, +23, 178, 1034, 671, 933, 648, 151, 213, +-386, -447, -155, -870, 247, -700, 243, -169, +-104, 482, -194, 705, 141, 549, 501, 115, +503, -339, 65, -627, -333, -765, -421, -451, +-127, 128, 381, 794, 710, 975, 675, 424, +205, -408, -298, -1089, -711, -1020, -588, -414, +7, 534, 834, 1163, 1210, 1033, 794, 112, +-151, -1025, -991, -1389, -1049, -751, -229, 364, +831, 1100, 1340, 932, 842, 261, -214, -601, +-890, -985, -639, -757, 241, -10, 763, 728, +503, 701, -106, 153, -263, -504, 18, -521, +486, -156, 493, 198, 82, 158, -395, -68, +-380, -150, -53, -51, 414, 107, 740, 60, +651, -119, 152, -192, -482, -86, -722, 117, +-331, 93, 491, -142, 987, -282, 709, -109, +55, 314, -480, 332, -429, -106, -63, -644, +230, -482, 374, 305, 445, 835, 462, 404, +195, -638, -274, -1134, -643, -538, -303, 540, +607, 1104, 1154, 702, 706, -93, -466, -783, +-1016, -1026, -483, -751, 559, -92, 1100, 762, +723, 1194, 52, 902, -617, -81, -636, -1106, +-236, -1478, 613, -856, 1025, 400, 735, 1290, +-181, 1187, -837, 176, -517, -801, 238, -1114, +758, -668, 602, 48, 215, 674, -20, 883, +-57, 515, -154, -410, -299, -1135, -50, -1136, +451, -124, 781, 957, 512, 1347, -131, 752, +-512, -399, -279, -1252, 303, -1446, 498, -622, +339, 513, -89, 1405, -117, 1223, 231, 277, +497, -749, 184, -1257, -382, -1069, -417, -430, +208, 533, 989, 1290, 838, 1270, -83, 186, +-965, -1218, -811, -1710, 161, -826, 1069, 666, +1181, 1443, 509, 1029, -317, -91, -829, -967, +-632, -1117, -72, -615, 525, 240, 805, 833, +753, 877, 350, 312, -174, -481, -484, -926, +-380, -797, -40, -130, 435, 596, 532, 824, +283, 370, -47, -397, 26, -698, 282, -338, +271, 200, 21, 258, -226, -114, -33, -302, +239, -64, 297, 292, 127, 295, -14, 33, +156, -303, 286, -435, 294, -364, 68, -3, +27, 439, 46, 579, -61, 92, -193, -633, +-170, -893, 337, -297, 851, 679, 996, 1109, +284, 471, -810, -761, -1342, -1495, -654, -1013, +885, 420, 1745, 1561, 1328, 1433, -162, 115, +-1336, -1355, -1258, -1783, -121, -910, 1126, 618, +1428, 1567, 731, 1269, -449, 36, -1043, -1130, +-697, -1282, 347, -536, 1130, 403, 939, 805, +23, 567, -768, 3, -608, -464, 103, -598, +755, -325, 718, 188, 325, 515, -131, 363, +-394, -170, -415, -578, -142, -487, 468, -15, +886, 329, 724, 337, -24, 42, -611, -129, +-529, -153, -1, 61, 462, 28, 489, -279, +317, -717, 145, -536, 156, 454, 66, 1408, +-145, 1133, -302, -533, -157, -1949, 235, -1616, +632, 257, 691, 1790, 326, 1476, -214, -118, +-579, -1331, -671, -1100, -124, -1, 724, 672, +1279, 405, 937, -176, -142, -253, -1118, 114, +-1169, 269, -178, -166, 930, -579, 1319, -383, +772, 213, -60, 540, -537, 270, -651, -89, +-386, -291, 52, -319, 611, -371, 866, -213, +605, 231, -58, 605, -567, 430, -447, -167, +-19, -663, 367, -629, 431, -184, 436, 325, +283, 623, -45, 473, -386, -94, -395, -734, +141, -768, 573, -151, 577, 583, 130, 677, +-184, 162, -117, -378, 67, -474, 41, -269, +-111, -57, 106, 78, 499, 168, 526, 203, +12, 31, -450, -139, -314, -152, 297, 19, +677, 11, 350, -254, -247, -418, -459, -159, +-156, 389, 374, 660, 639, 325, 455, -335, +-4, -762, -322, -673, -307, -75, 3, 540, +243, 702, 222, 253, 158, -425, 230, -636, +274, -256, 130, 265, -146, 337, -201, -9, +12, -291, 183, -223, 97, 76, -26, 159, +170, 27, 483, -179, 459, -129, -76, 74, +-523, 259, -387, 65, 147, -363, 436, -615, +385, -252, 203, 472, 130, 860, 109, 404, +-124, -529, -328, -1035, -268, -618, 273, 280, +600, 820, 556, 574, 60, -52, -400, -464, +-497, -536, -123, -354, 461, -125, 699, 268, +514, 615, -99, 582, -544, -10, -587, -776, +-115, -1006, 558, -469, 893, 485, 597, 1049, +-129, 839, -617, -63, -667, -910, -159, -1112, +499, -464, 785, 467, 573, 915, 26, 640, +-415, -28, -516, -525, -182, -648, 250, -479, +494, -98, 453, 383, 207, 704, -85, 491, +-343, -143, -371, -732, -30, -721, 467, -212, +696, 360, 368, 535, -301, 343, -671, -3, +-323, -240, 408, -296, 659, -277, 338, -243, +-139, -155, -165, 130, 65, 501, 116, 632, +-152, 197, -338, -590, -20, -1053, 517, -707, +823, 245, 449, 1088, -269, 1062, -862, 136, +-762, -941, -38, -1290, 801, -557, 1075, 571, +623, 1100, -194, 661, -745, -196, -728, -686, +-200, -674, 406, -389, 690, -25, 565, 518, +129, 877, -313, 560, -449, -419, -113, -1083, +324, -729, 429, 190, 80, 561, -288, 153, +-231, -154, 209, 211, 464, 700, 310, 375, +-132, -655, -351, -1390, -174, -1053, 197, 134, +382, 1268, 240, 1587, -33, 833, -255, -557, +-156, -1613, 142, -1567, 322, -429, 212, 884, +50, 1424, -3, 932, -58, -27, -242, -762, +-235, -900, 160, -529, 673, 18, 603, 440, +-164, 462, -905, 203, -647, -127, 518, -162, +1252, -11, 695, 17, -661, -211, -1217, -396, +-470, -172, 732, 300, 1066, 501, 392, 238, +-389, -173, -567, -330, -75, -298, 259, -220, +281, -121, 17, 205, -142, 535, -185, 476, +39, -84, 399, -672, 492, -737, 142, -221, +-338, 399, -476, 664, -242, 455, 167, 25, +424, -376, 425, -484, 220, -404, -80, -177, +-330, 42, -332, 345, 9, 635, 366, 591, +382, -29, 63, -941, -236, -1203, -220, -336, +25, 1004, 285, 1443, 263, 421, 36, -1064, +-169, -1414, -164, -345, 12, 933, 161, 1085, +188, 186, 47, -616, -62, -555, 28, -62, +155, 86, 60, -184, -147, -266, -204, 199, +76, 703, 373, 598, 306, -133, -59, -749, +-299, -682, -180, -123, 49, 255, 167, 169, +173, -9, 237, 183, 224, 562, -51, 511, +-463, -192, -450, -1004, 70, -1082, 640, -268, +658, 761, 140, 1130, -404, 617, -524, -240, +-241, -736, 19, -598, 174, -191, 335, 167, +574, 282, 556, 328, 22, 244, -806, -91, +-1188, -542, -605, -630, 674, -37, 1602, 791, +1313, 1003, -8, 264, -1312, -794, -1560, -1193, +-666, -694, 657, 195, 1413, 817, 1163, 928, +138, 571, -846, -68, -1111, -694, -512, -930, +326, -560, 873, 91, 783, 590, 174, 633, +-568, 308, -946, -155, -538, -463, 473, -329, +1346, 183, 1001, 520, -358, 136, -1513, -681, +-1235, -982, 181, -203, 1407, 1013, 1327, 1418, +134, 535, -906, -848, -1001, -1507, -247, -914, +451, 338, 639, 1184, 281, 964, -138, -1, +-288, -740, -131, -677, 91, -75, 185, 275, +173, 194, 86, 16, -148, 107, -317, 147, +-212, -80, 212, -371, 520, -222, 392, 234, +-159, 377, -609, -26, -416, -405, 273, -180, +727, 385, 454, 480, -291, -89, -813, -666, +-593, -515, 270, 171, 1035, 639, 869, 453, +-101, -37, -977, -323, -896, -289, -77, -195, +708, -155, 722, 17, 133, 315, -343, 458, +-258, 166, 65, -305, 127, -450, -7, -148, +-106, 229, -1, 212, 56, -54, -62, -233, +-201, -64, 21, 185, 519, 244, 654, 89, +103, -115, -747, -189, -973, -169, -361, -92, +550, 1, 897, 123, 648, 186, 85, 135, +-343, 11, -633, -100, -634, -130, -248, -139, +365, -91, 791, 41, 642, 205, 86, 203, +-492, -50, -662, -244, -404, -134, 40, 137, +456, 179, 542, -99, 288, -255, -100, -3, +-305, 422, -264, 396, -199, -125, -200, -693, +-144, -677, 278, -57, 816, 709, 843, 1032, +-16, 565, -1097, -395, -1420, -1161, -541, -993, +823, -72, 1591, 818, 1133, 892, -137, 315, +-1255, -196, -1393, -252, -506, -114, 653, -214, +1218, -434, 804, -362, -85, 106, -739, 617, +-725, 720, -284, 349, 195, -252, 449, -718, +422, -719, 217, -208, -78, 480, -265, 730, +-436, 364, -395, -257, -94, -492, 441, -205, +744, 158, 508, 223, -179, -29, -799, -145, +-741, -21, -98, 197, 496, 156, 461, -133, +160, -338, 23, -196, 148, 256, 71, 517, +-353, 281, -791, -335, -569, -701, 346, -383, +1158, 391, 960, 832, -127, 414, -1122, -440, +-1073, -831, -103, -358, 858, 446, 878, 650, +75, 180, -634, -360, -514, -327, 119, 62, +481, 246, 182, 24, -373, -235, -495, -125, +-21, 172, 469, 272, 369, -30, -62, -316, +-281, -225, -89, 232, 60, 515, -119, 256, +-421, -356, -225, -697, 479, -385, 942, 302, +457, 692, -622, 417, -1267, -167, -814, -454, +353, -211, 1207, 175, 1036, 192, 41, -109, +-898, -316, -1030, -102, -378, 281, 404, 408, +659, 155, 371, -192, -85, -298, -262, -156, +-158, 33, 27, 100, 4, 62, -144, 10, +-296, -36, -190, -6, 184, 50, 571, 174, +526, 148, -22, -39, -639, -322, -797, -405, +-358, -129, 269, 302, 623, 536, 557, 329, +200, -83, -209, -337, -500, -293, -538, -115, +-322, -62, 63, -18, 437, 96, 554, 313, +281, 369, -192, 177, -543, -116, -501, -359, +-119, -445, 342, -366, 423, -31, 97, 445, +-242, 702, -284, 467, -91, -132, 95, -563, +142, -585, 15, -267, -97, 123, -149, 445, +-40, 527, 52, 193, 91, -308, -93, -504, +-252, -112, -155, 338, 226, 253, 441, -244, +170, -409, -369, 57, -605, 558, -328, 439, +160, -181, 432, -596, 363, -446, 91, 1, +-193, 378, -351, 480, -344, 333, -122, -44, +158, -433, 219, -518, 33, -189, -43, 250, +83, 401, 145, 224, -89, -39, -426, -122, +-458, -77, -19, -13, 430, -55, 409, -102, +-9, -42, -297, 130, -192, 251, 12, 98, +22, -204, -191, -344, -315, -92, -84, 296, +408, 430, 573, 192, 95, -184, -595, -397, +-771, -423, -232, -226, 512, 166, 724, 619, +189, 701, -500, 185, -663, -556, -266, -805, +238, -313, 473, 321, 303, 424, -108, 52, +-466, -165, -419, 102, -20, 402, 362, 216, +308, -328, -129, -554, -457, -186, -319, 281, +149, 264, 412, -169, 298, -292, -61, 157, +-361, 689, -475, 548, -388, -238, -82, -865, +369, -702, 680, 11, 469, 493, -186, 437, +-745, 147, -703, 95, -207, 195, 224, 44, +320, -396, 245, -660, 282, -293, 237, 400, +-125, 714, -697, 280, -834, -404, -294, -551, +552, -4, 925, 617, 505, 602, -286, -78, +-809, -764, -689, -821, -146, -185, 394, 557, +478, 858, 208, 534, -106, 6, -225, -361, +-183, -447, -167, -426, -215, -373, -206, -108, +86, 395, 347, 840, 385, 705, 39, -21, +-356, -757, -556, -787, -319, -112, 142, 507, +399, 415, 247, -209, -169, -507, -381, -75, +-207, 631, 212, 797, 293, 229, -34, -517, +-395, -833, -361, -600, -41, -80, 261, 414, +293, 680, 82, 581, -222, 203, -395, -248, +-317, -469, 13, -437, 325, -226, 355, 36, +58, 261, -276, 354, -372, 251, -284, 52, +-217, -127, -116, -191, 221, -185, 624, -67, +615, 131, -18, 271, -817, 169, -1082, -137, +-520, -315, 355, -225, 847, 28, 626, 191, +97, 300, -290, 389, -403, 292, -385, -166, +-414, -722, -315, -779, 64, -172, 636, 604, +748, 896, 175, 575, -688, -2, -971, -506, +-383, -745, 498, -561, 741, 76, 189, 739, +-420, 799, -534, 155, -218, -593, 30, -684, +135, -121, 192, 477, 257, 508, 135, 60, +-242, -320, -578, -276, -510, 69, -63, 251, +354, 85, 481, -212, 294, -238, -36, 73, +-370, 379, -488, 356, -350, -16, -62, -373, +170, -413, 272, -108, 256, 276, 110, 402, +-105, 188, -316, -131, -373, -222, -253, -81, +-78, 42, 82, 12, 244, 21, 358, 214, +281, 295, -114, -37, -588, -577, -724, -597, +-322, 127, 292, 911, 624, 868, 463, -4, +28, -811, -316, -821, -433, -193, -400, 353, +-307, 453, -67, 273, 316, 191, 601, 180, +471, 18, -125, -361, -772, -608, -867, -400, +-270, 194, 503, 680, 764, 625, 373, 107, +-275, -372, -596, -439, -389, -140, -10, 152, +142, 178, 8, -32, -62, -184, -19, -50, +148, 282, 206, 476, 74, 232, -226, -244, +-503, -489, -521, -284, -224, 31, 356, 66, +747, -42, 556, 161, -145, 678, -728, 799, +-753, 72, -274, -995, 231, -1309, 363, -488, +233, 653, 103, 1153, 36, 800, -76, 170, +-270, -309, -462, -610, -434, -751, -75, -500, +448, 233, 741, 971, 442, 975, -371, 114, +-1074, -908, -965, -1093, -25, -225, 960, 930, +1083, 1236, 254, 385, -718, -831, -983, -1221, +-479, -446, 164, 660, 366, 1016, 170, 400, +30, -416, 134, -595, 214, -109, -64, 404, +-521, 402, -642, -21, -259, -375, 299, -333, +522, 12, 296, 287, -57, 251, -218, 42, +-262, -2, -327, 159, -316, 219, -53, -108, +332, -543, 465, -505, 186, 155, -279, 783, +-529, 644, -410, -162, -110, -746, 169, -449, +362, 359, 389, 767, 89, 348, -375, -397, +-626, -686, -433, -333, 43, 246, 397, 517, +379, 414, 98, 148, -161, -79, -296, -249, +-272, -323, -143, -231, -3, 50, 31, 328, +-1, 377, 16, 188, 129, -75, 144, -226, +-120, -221, -409, -70, -397, 137, -28, 247, +329, 158, 349, -51, 42, -125, -259, -1, +-342, 110, -246, 13, -100, -159, 50, -87, +168, 229, 179, 417, 85, 174, -52, -301, +-188, -515, -356, -242, -370, 290, -121, 619, +283, 460, 446, -70, 180, -536, -270, -520, +-443, -60, -211, 408, 57, 476, 97, 205, +-52, -37, -77, -87, 23, -110, 75, -240, +-79, -327, -249, -112, -202, 362, 69, 698, +271, 540, 143, -61, -208, -630, -440, -693, +-291, -188, 87, 397, 317, 533, 169, 220, +-152, -88, -309, -32, -160, 158, 86, 82, +189, -231, 42, -352, -179, -47, -348, 323, +-303, 292, -96, -62, 197, -247, 412, 8, +347, 378, -37, 393, -474, 0, -604, -378, +-360, -399, 38, -147, 267, 104, 299, 218, +261, 318, 191, 412, -68, 291, -497, -175, +-787, -676, -529, -643, 220, 69, 878, 861, +807, 920, 3, 80, -851, -856, -1027, -964, +-368, -126, 439, 829, 719, 1005, 339, 322, +-180, -490, -374, -696, -242, -281, -163, 214, +-275, 333, -285, 120, 16, -71, 467, 0, +638, 229, 232, 336, -461, 113, -894, -299, +-696, -523, -69, -268, 546, 273, 666, 552, +294, 322, -212, -83, -444, -159, -346, 69, +-162, 105, -137, -248, -187, -509, -23, -152, +365, 601, 588, 930, 272, 418, -462, -478, +-983, -918, -768, -570, 79, 161, 863, 665, +877, 653, 140, 266, -714, -165, -947, -361, +-437, -266, 278, -37, 556, 125, 289, 150, +-117, 102, -274, 52, -190, 11, -110, -12, +-142, 14, -178, 105, -66, 178, 137, 127, +252, -20, 154, -187, -116, -261, -405, -190, +-474, 35, -219, 346, 194, 504, 414, 366, +270, -9, -117, -318, -372, -371, -323, -240, +-131, -92, -56, 39, -21, 281, 90, 540, +178, 516, 96, 80, -172, -461, -339, -588, +-203, -258, 74, 175, 127, 369, -70, 357, +-269, 260, -226, 20, 63, -326, 262, -430, +207, -27, -51, 548, -323, 584, -429, -38, +-277, -617, 11, -487, 196, 138, 230, 499, +120, 341, -36, 67, -171, 33, -258, 53, +-279, -153, -222, -408, -84, -327, 90, 134, +270, 563, 326, 604, 89, 266, -387, -222, +-722, -597, -465, -627, 224, -177, 671, 537, +386, 936, -330, 638, -678, -152, -313, -740, +246, -702, 349, -233, -37, 256, -335, 509, +-249, 592, 35, 462, 74, 77, -57, -452, +-107, -739, 57, -491, 107, 153, -122, 685, +-404, 676, -368, 175, 5, -331, 362, -407, +358, -50, 7, 314, -349, 238, -461, -198, +-302, -478, 29, -146, 289, 533, 269, 810, +-31, 281, -364, -583, -407, -850, -71, -207, +333, 642, 304, 808, -139, 159, -573, -516, +-483, -503, 80, 49, 526, 436, 344, 260, +-219, -116, -555, -185, -347, 87, 154, 258, +336, 61, 34, -236, -356, -230, -379, 132, +-25, 416, 326, 304, 279, -87, -145, -373, +-512, -315, -428, -6, 46, 316, 448, 443, +320, 306, -173, 3, -529, -269, -422, -317, +-15, -171, 286, 29, 248, 158, 12, 229, +-182, 270, -250, 223, -237, 38, -124, -193, +10, -265, 109, -100, 69, 128, -20, 182, +-115, 37, -135, -105, -148, -15, -99, 235, +-37, 353, 2, 155, -30, -209, -67, -360, +-39, -170, 21, 147, -11, 259, -179, 127, +-276, -7, -109, 3, 163, 91, 191, 72, +-42, -40, -273, -45, -212, 89, 10, 191, +72, 29, -122, -284, -246, -360, -90, 9, +198, 539, 262, 660, -11, 224, -390, -352, +-479, -542, -189, -297, 226, 4, 423, 147, +189, 253, -286, 422, -552, 450, -323, 92, +177, -429, 424, -630, 164, -293, -340, 271, +-464, 565, -119, 427, 227, 53, 147, -238, +-204, -266, -318, -90, -4, 118, 303, 165, +177, 93, -257, 50, -483, 75, -276, 49, +102, -106, 217, -203, 67, -68, -58, 228, +-14, 391, 22, 277, -117, 0, -340, -279, +-369, -434, -82, -359, 249, 52, 344, 605, +146, 814, -150, 362, -316, -431, -305, -853, +-174, -542, -27, 176, 85, 665, 112, 594, +78, 154, 32, -228, -72, -329, -204, -203, +-314, -16, -244, 124, 37, 194, 297, 206, +255, 141, -102, -12, -402, -170, -350, -175, +-12, 4, 233, 219, 154, 236, -113, 23, +-230, -185, -109, -145, 40, 129, 6, 293, +-162, 133, -258, -207, -62, -290, 232, 39, +328, 416, 49, 388, -369, -96, -607, -493, +-382, -360, 143, 177, 542, 565, 480, 411, +-9, -73, -517, -407, -597, -299, -216, 92, +233, 364, 328, 279, 58, -91, -239, -363, +-242, -226, 0, 216, 175, 526, 100, 319, +-160, -199, -316, -479, -240, -204, -20, 275, +138, 378, 174, 35, 47, -285, -109, -145, +-205, 252, -183, 364, -85, 38, 55, -299, +77, -186, -12, 225, -118, 372, -162, 0, +-107, -482, -13, -440, 48, 176, 90, 764, +76, 709, -47, -2, -251, -701, -355, -774, +-217, -183, 79, 471, 337, 640, 310, 317, +50, -68, -274, -180, -441, -122, -391, -161, +-101, -229, 254, -74, 429, 334, 226, 592, +-198, 323, -478, -293, -357, -648, 13, -364, +258, 272, 183, 619, -43, 371, -190, -171, +-176, -431, -89, -204, -15, 200, 36, 341, +45, 124, 10, -154, -73, -193, -146, 16, +-155, 213, -89, 181, -2, -29, 68, -218, +99, -178, 38, 76, -80, 344, -167, 379, +-182, 75, -155, -337, -94, -507, 41, -246, +219, 278, 269, 614, 26, 464, -380, -61, +-515, -483, -169, -412, 318, 30, 428, 362, +9, 241, -433, -108, -379, -232, 86, 28, +364, 345, 181, 302, -248, -61, -399, -363, +-149, -304, 159, 4, 131, 250, -81, 273, +-171, 143, 13, 4, 224, -92, 119, -115, +-244, -52, -458, 53, -254, 112, 195, 44, +405, -55, 150, -57, -264, 27, -390, 94, +-95, 70, 261, 57, 288, 108, -63, 113, +-440, -70, -466, -319, -65, -312, 390, 59, +505, 469, 166, 485, -325, 57, -561, -365, +-363, -375, 61, -12, 366, 305, 316, 254, +1, -62, -303, -300, -342, -200, -93, 150, +213, 405, 215, 336, -48, -21, -256, -336, +-151, -358, 96, -111, 138, 178, -105, 292, +-315, 229, -184, 76, 196, -79, 394, -160, +199, -140, -213, -17, -494, 97, -424, 126, +-98, 81, 284, 25, 464, 12, 304, -22, +-117, -85, -417, -80, -411, 48, -145, 204, +116, 165, 191, -79, 103, -283, 33, -167, +-8, 193, -77, 387, -147, 186, -145, -176, +-66, -268, 11, -48, 14, 113, -17, -14, +-6, -189, 40, -15, 86, 416, 32, 570, +-131, 131, -294, -550, -250, -790, 23, -335, +318, 394, 321, 784, -19, 546, -363, -50, +-326, -525, 16, -521, 247, -119, 95, 298, +-206, 387, -255, 141, 48, -133, 295, -172, +171, -49, -195, 45, -365, 51, -167, 75, +163, 123, 220, 64, -31, -124, -203, -263, +-80, -129, 181, 177, 175, 349, -137, 220, +-405, -62, -247, -225, 170, -205, 411, -93, +192, 48, -224, 164, -381, 211, -157, 113, +127, -41, 170, -87, -20, -9, -137, 26, +-69, -122, 95, -269, 132, -123, -23, 297, +-218, 582, -242, 360, -77, -195, 118, -595, +226, -511, 142, -63, -6, 374, -172, 528, +-268, 340, -222, -39, -15, -358, 215, -390, +285, -134, 76, 162, -205, 265, -255, 174, +-73, 44, 102, -36, 46, -98, -142, -132, +-131, -79, 102, 59, 273, 147, 135, 83, +-209, -25, -382, -46, -204, 21, 119, 36, +244, -41, 114, -89, -46, -10, -26, 115, +36, 142, -41, 30, -250, -102, -341, -172, +-99, -121, 311, 41, 511, 240, 287, 320, +-212, 120, -547, -240, -463, -415, -77, -216, +288, 151, 376, 289, 181, 140, -58, -7, +-141, 79, -116, 180, -85, -2, -147, -352, +-161, -452, -69, -103, 140, 334, 311, 435, +271, 222, -10, -2, -323, -58, -410, -117, +-213, -279, 124, -355, 287, -125, 200, 294, +7, 509, -70, 348, -43, -20, -67, -301, +-240, -348, -262, -233, -24, -8, 357, 210, +444, 293, 143, 184, -357, -10, -544, -126, +-310, -136, 119, -107, 397, -69, 366, 36, +133, 207, -166, 245, -368, 32, -393, -287, +-136, -352, 202, -11, 424, 409, 306, 443, +-54, -8, -382, -493, -363, -462, -67, 57, +243, 504, 255, 406, 40, -79, -160, -390, +-149, -269, -32, 60, 35, 201, 25, 121, +38, 40, 77, 48, 22, 13, -140, -148, +-263, -233, -94, -68, 206, 233, 317, 332, +93, 78, -222, -271, -306, -343, -97, -40, +111, 333, 135, 373, 50, 30, 24, -371, +51, -423, -27, -65, -236, 337, -281, 428, +-11, 147, 370, -185, 441, -311, 54, -213, +-461, 1, -558, 188, -140, 271, 386, 142, +498, -156, 123, -328, -266, -168, -302, 224, +-59, 408, 117, 155, 18, -255, -133, -377, +-62, -118, 165, 176, 261, 226, 35, 71, +-267, -56, -294, -38, -7, 32, 226, 73, +198, 4, -90, -139, -247, -250, -95, -155, +177, 203, 248, 514, 13, 381, -245, -189, +-245, -659, 0, -490, 182, 151, 164, 598, +-4, 423, -86, -98, -60, -380, -36, -233, +-73, 61, -68, 159, 87, 53, 233, -36, +117, -23, -208, 44, -375, 50, -152, 2, +300, -54, 456, -96, 163, -76, -321, 41, +-483, 173, -209, 156, 228, -51, 362, -227, +187, -156, -76, 124, -177, 277, -104, 104, +-21, -210, -41, -307, -103, -79, -22, 213, +165, 294, 275, 159, 120, -59, -159, -210, +-329, -255, -206, -163, 46, 67, 216, 274, +165, 302, 33, 84, -54, -199, -36, -318, +-37, -174, -60, 109, -87, 274, -41, 193, +44, -55, 117, -226, 110, -153, 0, 53, +-118, 176, -148, 93, -33, -68, 111, -125, +176, -60, 45, 76, -160, 161, -252, 119, +-85, -65, 205, -265, 322, -243, 122, 33, +-198, 324, -351, 287, -178, -19, 131, -220, +302, -113, 208, 89, -30, 56, -244, -165, +-272, -224, -131, 7, 157, 293, 366, 322, +290, 115, -71, -110, -424, -235, -422, -272, +-41, -219, 367, -21, 438, 262, 129, 426, +-257, 307, -336, -49, -103, -377, 137, -446, +156, -203, -2, 168, -104, 386, 2, 311, +122, 34, 87, -205, -72, -252, -158, -134, +-34, 36, 127, 136, 87, 131, -75, 20, +-156, -87, -54, -69, 123, 49, 178, 127, +83, 39, -34, -138, -115, -180, -125, -52, +-120, 110, -64, 153, 56, 118, 201, 64, +249, -33, 138, -195, -118, -281, -315, -97, +-289, 261, -46, 413, 210, 148, 250, -284, +110, -395, 5, -91, -11, 243, -49, 250, +-153, -5, -206, -153, -42, -69, 188, 60, +250, 45, 76, -70, -125, -72, -150, 31, +-2, 114, 81, 83, 35, -27, -35, -108, +-52, -130, -21, -53, 0, 97, 39, 220, +66, 168, 48, -87, -26, -282, -78, -201, +-46, 94, 41, 288, 81, 153, 19, -124, +-80, -250, -112, -113, -5, 104, 156, 213, +226, 177, 76, 25, -207, -158, -385, -271, +-200, -184, 247, 57, 535, 230, 320, 200, +-199, 50, -540, -12, -394, 24, 87, -39, +433, -208, 385, -297, 53, -126, -207, 173, +-228, 344, -100, 328, -35, 174, 8, -79, +74, -402, 191, -564, 196, -293, 20, 300, +-224, 702, -254, 496, -18, -114, 237, -520, +215, -429, -54, -58, -241, 182, -150, 211, +127, 166, 292, 122, 174, 26, -106, -161, +-278, -318, -201, -268, 46, 33, 229, 402, +223, 509, 52, 184, -139, -379, -201, -660, +-96, -351, 49, 266, 161, 601, 170, 381, +76, -88, -60, -324, -191, -240, -197, -67, +-48, -6, 154, 36, 267, 145, 189, 215, +-32, 116, -212, -120, -194, -259, -38, -166, +127, 53, 136, 201, 65, 147, -23, -13, +-47, -144, -33, -127, 5, 7, 47, 123, +90, 140, 55, 32, -61, -112, -142, -181, +-131, -117, 28, 59, 181, 207, 242, 219, +151, 53, -49, -168, -293, -264, -330, -177, +-97, 35, 289, 216, 469, 261, 258, 146, +-170, -83, -431, -272, -331, -280, 11, -67, +323, 189, 410, 276, 244, 151, -106, -54, +-390, -156, -391, -132, -59, -74, 321, -32, +413, 21, 150, 136, -152, 213, -233, 136, +-75, -95, 98, -320, 93, -298, -29, -34, +-83, 288, -2, 414, 118, 230, 135, -137, +24, -448, -86, -449, -69, -104, 57, 386, +117, 636, 7, 372, -161, -250, -156, -727, +55, -611, 266, 16, 272, 614, 62, 707, +-173, 272, -276, -284, -173, -581, 46, -509, +257, -177, 288, 225, 113, 524, -148, 523, +-274, 183, -152, -297, 112, -574, 272, -431, +217, -25, 15, 313, -153, 378, -185, 203, +-107, 1, 20, -122, 111, -158, 156, -148, +186, -111, 165, -19, 12, 88, -219, 161, +-356, 152, -210, 64, 131, -51, 373, -181, +332, -239, 79, -130, -91, 144, -71, 399, +-52, 346, -190, -65, -319, -536, -156, -598, +306, -116, 698, 526, 552, 783, -85, 388, +-728, -326, -768, -777, -146, -590, 587, 44, +773, 550, 303, 520, -322, 82, -490, -266, +-160, -207, 207, 40, 211, 93, -49, -134, +-135, -283, 95, -68, 306, 304, 171, 402, +-201, 83, -391, -301, -158, -336, 239, -51, +427, 199, 251, 167, -74, -12, -264, -103, +-227, -50, -92, 6, 75, -26, 231, -19, +299, 112, 191, 209, -76, 40, -328, -319, +-314, -443, -12, -72, 348, 508, 425, 653, +116, 130, -287, -579, -395, -759, -99, -230, +319, 464, 445, 691, 159, 322, -250, -232, +-397, -498, -154, -359, 208, -9, 354, 272, +206, 315, -35, 143, -156, -116, -95, -277, +2, -226, 37, -7, 26, 225, 54, 285, +103, 117, 115, -162, 25, -322, -72, -244, +-93, 1, -20, 235, 72, 305, 120, 195, +94, -23, 26, -262, -21, -375, -47, -242, +-37, 117, -7, 420, 54, 375, 119, 2, +151, -343, 87, -319, -57, -20, -185, 192, +-155, 104, 57, -107, 258, -122, 262, 87, +43, 271, -201, 174, -220, -153, 6, -387, +262, -286, 278, 79, 7, 347, -288, 280, +-287, -17, 58, -214, 422, -127, 426, 50, +21, 53, -389, -108, -403, -158, -27, 38, +346, 265, 348, 223, 104, -84, -120, -318, +-140, -229, -39, 71, 43, 273, 56, 218, +57, -11, 66, -211, 45, -262, -2, -139, +-22, 77, 43, 269, 120, 310, 81, 132, +-48, -187, -163, -427, -99, -374, 137, -17, +314, 380, 239, 483, -59, 174, -285, -247, +-221, -389, 63, -167, 263, 111, 222, 143, +20, -19, -115, -96, -50, 34, 88, 185, +142, 132, 33, -71, -128, -210, -158, -153, +5, -13, 251, 70, 332, 84, 117, 86, +-227, 60, -334, -34, -90, -136, 290, -112, +398, 54, 124, 170, -240, 63, -335, -159, +-66, -226, 294, -28, 404, 221, 165, 228, +-164, -9, -300, -219, -154, -188, 86, 13, +240, 131, 234, 91, 126, -9, -33, -55, +-159, -60, -178, -49, -16, 13, 217, 98, +293, 104, 87, -45, -176, -198, -224, -122, +12, 122, 248, 239, 206, 42, -28, -238, +-151, -229, -9, 89, 194, 315, 195, 134, +-45, -245, -231, -360, -155, -59, 116, 306, +317, 320, 249, 4, 20, -281, -150, -246, +-144, 21, -19, 203, 66, 135, 88, -88, +84, -213, 79, -109, 43, 120, 6, 253, +20, 153, 89, -74, 117, -231, -26, -205, +-197, -87, -187, 20, 92, 115, 402, 211, +377, 225, 7, 43, -354, -238, -330, -340, +41, -144, 377, 155, 331, 232, 13, 58, +-258, -83, -243, -35, 4, 74, 235, 13, +311, -142, 227, -156, 34, 40, -178, 211, +-298, 132, -234, -114, 34, -256, 333, -130, +469, 114, 343, 224, -13, 117, -381, -96, +-485, -193, -227, -72, 258, 124, 578, 159, +461, -54, 15, -271, -358, -204, -350, 131, +-54, 375, 207, 228, 245, -146, 150, -340, +52, -173, 0, 98, -57, 136, -117, -28, +-87, -91, 75, 72, 262, 246, 271, 147, +44, -194, -222, -439, -243, -295, 16, 154, +308, 501, 299, 418, -11, -44, -248, -477, +-154, -480, 145, -84, 305, 315, 176, 365, +-40, 107, -115, -147, -80, -181, -48, -78, +-14, -8, 105, 8, 270, 43, 285, 87, +56, 42, -224, -96, -294, -177, -74, -81, +204, 131, 309, 246, 168, 157, -43, -79, +-143, -278, -71, -289, 91, -118, 171, 142, +130, 332, 34, 298, -35, 48, -72, -259, +-112, -388, -66, -247, 121, 56, 346, 306, +363, 320, 87, 133, -284, -125, -387, -288, +-154, -271, 156, -116, 288, 103, 221, 248, +144, 258, 105, 125, 42, -104, -95, -283, +-231, -296, -215, -113, -10, 141, 247, 271, +348, 195, 239, 4, 31, -113, -104, -112, +-106, -76, -84, -97, -70, -114, -20, 12, +117, 215, 256, 263, 214, 24, 4, -270, +-135, -270, -50, 59, 100, 322, 98, 152, +-83, -281, -140, -446, 59, -86, 280, 448, +247, 548, -32, 91, -224, -459, -91, -556, +190, -156, 274, 296, 41, 406, -233, 146, +-204, -164, 113, -242, 362, -99, 278, 75, +-63, 112, -278, 43, -135, -26, 176, -46, +271, -45, 73, -76, -156, -72, -138, 30, +81, 153, 208, 165, 150, 5, 33, -154, +-1, -156, 13, -28, -68, 45, -169, -26, +-98, -93, 203, 7, 461, 226, 364, 305, +-88, 53, -491, -357, -449, -534, 33, -242, +544, 324, 576, 640, 120, 382, -379, -232, +-441, -614, -42, -407, 348, 130, 358, 419, +30, 224, -212, -116, -128, -171, 131, 66, +229, 195, 81, -49, -85, -387, -111, -352, +4, 118, 109, 542, 137, 424, 125, -133, +82, -556, -2, -399, -111, 131, -150, 444, +-49, 253, 153, -166, 314, -321, 273, -111, +48, 144, -245, 147, -346, -34, -158, -103, +207, 19, 454, 145, 349, 69, -10, -144, +-297, -249, -259, -131, 0, 126, 224, 274, +200, 193, 25, -45, -86, -237, -39, -213, +102, -34, 179, 135, 122, 148, -1, 31, +-118, -53, -162, -52, -94, -28, 63, -60, +278, -111, 399, -43, 252, 133, -122, 240, +-450, 107, -418, -170, 12, -309, 447, -156, +510, 140, 188, 252, -175, 89, -276, -141, +-131, -173, 11, 6, 67, 149, 115, 100, +212, -66, 244, -148, 53, -66, -233, 37, +-328, 51, -94, -19, 285, -49, 467, 10, +261, 93, -161, 109, -418, 11, -288, -113, +139, -163, 465, -96, 384, 31, -45, 95, +-420, 64, -339, 5, 135, 6, 541, 66, +459, 70, -66, -39, -533, -207, -497, -264, +10, -91, 506, 208, 591, 378, 230, 221, +-189, -132, -360, -351, -270, -242, -75, 47, +94, 180, 235, 78, 319, -58, 262, -29, +21, 90, -230, 79, -267, -45, -81, -115, +128, -69, 154, -37, 84, -96, 86, -78, +154, 148, 110, 378, -105, 245, -265, -230, +-141, -550, 193, -342, 379, 191, 199, 463, +-165, 247, -321, -118, -120, -214, 194, -49, +320, 51, 154, -42, -81, -138, -146, -39, +-37, 174, 75, 211, 52, 3, -30, -232, +-30, -228, 74, 20, 153, 236, 128, 209, +24, -19, -43, -212, -39, -191, -44, -23, +-81, 105, -65, 89, 70, 10, 251, -4, +301, 51, 127, 64, -145, -54, -304, -186, +-238, -158, 7, 31, 248, 198, 326, 160, +195, -17, -55, -127, -220, -88, -185, 6, +9, 30, 204, 17, 236, 40, 65, 48, +-160, -54, -254, -200, -88, -157, 235, 129, +400, 386, 234, 278, -152, -141, -401, -452, +-277, -354, 95, 31, 355, 317, 306, 290, +54, 78, -166, -98, -195, -133, -78, -86, +100, -50, 209, -34, 152, -6, -21, 63, +-184, 111, -172, 64, 30, -69, 248, -141, +279, -32, 85, 140, -160, 135, -256, -89, +-132, -258, 88, -113, 233, 206, 202, 305, +56, 25, -52, -315, -78, -309, -62, 44, +-58, 340, -9, 270, 110, -55, 217, -285, +169, -246, -34, -38, -230, 119, -213, 139, +32, 75, 272, 29, 272, 40, 53, 27, +-178, -84, -212, -245, -58, -252, 124, -7, +176, 325, 95, 431, 0, 166, -37, -248, +-40, -451, -49, -288, -26, 50, 63, 269, +167, 260, 147, 113, -34, -40, -207, -143, +-173, -173, 83, -116, 304, 12, 242, 114, +-56, 99, -283, 7, -221, -41, 67, 2, +290, 39, 230, -11, -22, -94, -182, -68, +-117, 59, 47, 106, 117, -29, 56, -188, +-17, -123, -18, 160, 37, 342, 59, 171, +9, -208, -40, -397, -42, -196, -14, 166, +30, 305, 82, 115, 113, -151, 67, -181, +-36, 30, -132, 205, -127, 115, -12, -140, +136, -252, 208, -81, 124, 170, -38, 190, +-170, -26, -162, -173, -28, -55, 127, 174, +181, 187, 108, -55, -15, -262, -82, -194, +-78, 65, -51, 217, 9, 132, 88, -52, +126, -125, 89, -50, -26, 59, -132, 71, +-127, -17, 12, -96, 165, -60, 191, 60, +56, 128, -141, 32, -209, -152, -78, -193, +148, -2, 248, 247, 137, 277, -73, 42, +-200, -255, -153, -358, -10, -191, 128, 101, +201, 326, 175, 350, 22, 152, -187, -175, +-272, -422, -129, -366, 165, -18, 336, 349, +219, 417, -85, 138, -286, -213, -212, -316, +29, -115, 225, 115, 223, 122, 58, -36, +-113, -118, -150, 8, -86, 182, 22, 166, +92, -38, 100, -228, 63, -201, 21, -14, +-21, 152, -69, 177, -71, 70, -26, -41, +28, -105, 63, -96, 62, -48, 42, 6, +16, 61, 5, 107, -25, 119, -60, 12, +-54, -179, -11, -251, 51, -70, 79, 237, +57, 329, 9, 61, -19, -277, -26, -303, +-13, 10, 3, 261, -3, 178, -8, -86, +10, -189, 25, -44, 13, 97, -3, 50, +18, -76, 44, -46, 58, 116, 14, 177, +-71, 8, -114, -240, -60, -282, 27, -44, +74, 242, 125, 303, 161, 106, 104, -131, +-83, -209, -295, -124, -321, -9, -55, 32, +318, 61, 440, 126, 194, 137, -184, 12, +-352, -184, -221, -229, 10, -37, 153, 200, +161, 230, 117, 19, 50, -194, -33, -199, +-133, -10, -156, 149, -48, 139, 127, 21, +198, -78, 72, -76, -121, -30, -182, -17, +-49, -7, 152, 27, 196, 91, 9, 98, +-195, -10, -185, -138, 5, -152, 181, -10, +184, 146, 45, 155, -106, 18, -146, -137, +-74, -146, 12, -24, 81, 98, 97, 111, +69, 22, 16, -61, -35, -76, -96, -25, +-139, 13, -79, 19, 115, 38, 281, 80, +180, 73, -157, -69, -399, -224, -234, -180, +220, 99, 481, 352, 260, 252, -229, -135, +-474, -395, -249, -253, 175, 123, 363, 307, +215, 159, -62, -81, -202, -136, -125, -23, +12, 33, 37, -27, -31, -70, -37, 4, +67, 101, 164, 49, 120, -77, -62, -92, +-193, 63, -146, 192, -5, 72, 76, -202, +54, -315, 56, -85, 88, 265, 85, 358, +-15, 115, -141, -188, -173, -261, -86, -139, +36, -17, 123, 46, 157, 116, 125, 224, +23, 196, -102, -53, -197, -320, -171, -340, +-32, -59, 131, 248, 220, 339, 168, 176, +-17, -87, -224, -250, -234, -249, -16, -73, +211, 170, 203, 299, -20, 184, -227, -111, +-194, -319, 38, -266, 217, 22, 188, 306, +20, 340, -148, 110, -219, -204, -140, -341, +70, -216, 250, 33, 214, 201, -43, 186, +-268, 86, -218, 5, 79, -38, 286, -80, +174, -137, -141, -131, -292, -40, -103, 105, +202, 207, 263, 159, 13, -27, -259, -229, +-240, -222, 71, 37, 331, 295, 219, 242, +-151, -127, -359, -403, -195, -247, 125, 203, +255, 450, 126, 219, -58, -200, -61, -357, +29, -130, 0, 171, -165, 204, -205, -1, +-12, -167, 243, -95, 281, 95, 65, 145, +-186, 20, -241, -98, -91, -24, 80, 116, +116, 73, 21, -176, -44, -336, 9, -111, +94, 328, 59, 507, -102, 176, -202, -346, +-75, -495, 179, -149, 255, 276, 4, 322, +-283, -1, -251, -249, 94, -143, 353, 176, +220, 297, -165, 57, -371, -270, -162, -327, +194, -38, 284, 266, 44, 262, -218, -10, +-189, -224, 71, -130, 253, 120, 123, 205, +-159, 20, -264, -221, -80, -222, 134, 25, +142, 263, -14, 238, -71, -20, 66, -240, +177, -217, 25, 20, -269, 202, -354, 150, +-71, -51, 321, -164, 414, -79, 136, 75, +-228, 129, -344, 53, -172, -40, 101, -68, +209, -59, 94, -52, -93, -27, -119, 35, +29, 108, 176, 117, 118, 44, -128, -56, +-300, -129, -155, -131, 164, -60, 297, 54, +120, 119, -134, 91, -186, 35, -24, 5, +107, -1, 34, -64, -118, -155, -114, -144, +58, 26, 206, 200, 155, 190, -62, 32, +-239, -97, -213, -105, -19, -74, 161, -77, +199, -41, 109, 103, -16, 245, -114, 183, +-189, -98, -197, -331, -48, -268, 210, 41, +357, 292, 201, 270, -180, 50, -450, -152, +-309, -184, 111, -74, 414, 29, 315, 40, +-29, -20, -301, -45, -273, 37, -25, 169, +190, 192, 169, -3, -18, -293, -133, -378, +-53, -88, 123, 365, 138, 510, -81, 141, +-298, -401, -205, -547, 162, -134, 425, 397, +265, 496, -171, 113, -465, -294, -324, -357, +78, -127, 360, 112, 303, 188, 32, 149, +-191, 66, -199, -59, -86, -161, -7, -141, +4, 15, 22, 152, 95, 122, 164, -24, +106, -118, -98, -63, -268, 44, -201, 61, +43, -10, 228, -56, 192, -2, 14, 77, +-133, 66, -136, -52, -59, -149, 6, -77, +52, 110, 104, 208, 95, 85, -5, -156, +-143, -247, -196, -99, -77, 131, 129, 220, +239, 134, 143, 1, -73, -91, -229, -142, +-180, -161, 0, -94, 128, 77, 94, 229, +3, 223, -34, 45, 16, -154, 39, -211, +-14, -117, -102, 37, -101, 117, -16, 87, +45, 9, 64, -36, 74, -5, 63, 42, +-10, 29, -113, -42, -159, -92, -62, -50, +94, 44, 148, 89, 48, 50, -68, -22, +-70, -47, -5, -13, 13, 23, -34, -5, +-55, -72, 21, -75, 108, 40, 79, 185, +-59, 182, -161, -16, -114, -245, 39, -288, +137, -86, 83, 174, -28, 299, -58, 238, +-4, 62, 16, -146, -61, -324, -146, -332, +-90, -103, 111, 263, 247, 468, 161, 303, +-64, -98, -217, -387, -206, -345, -89, -64, +33, 178, 123, 235, 181, 158, 171, 52, +22, -54, -201, -159, -298, -192, -166, -85, +84, 123, 242, 232, 199, 112, 22, -112, +-113, -176, -127, 4, -65, 187, -26, 106, +-22, -187, -12, -342, 51, -107, 110, 320, +88, 491, -20, 194, -117, -297, -122, -506, +-31, -265, 49, 168, 32, 369, -23, 204, +-5, -77, 91, -160, 126, -1, 11, 119, +-196, -3, -286, -219, -104, -218, 217, 69, +368, 325, 188, 251, -157, -62, -373, -255, +-278, -158, 20, 21, 260, 42, 276, -19, +119, 47, -80, 219, -233, 211, -257, -101, +-124, -419, 112, -345, 296, 117, 259, 488, +-12, 379, -285, -92, -309, -419, -70, -293, +198, 78, 250, 279, 65, 149, -138, -78, +-162, -133, -43, -10, 68, 81, 62, 25, +-17, -90, -45, -96, 12, 33, 58, 171, +8, 164, -81, -7, -124, -209, -56, -269, +94, -94, 185, 189, 109, 330, -87, 179, +-222, -115, -177, -255, 19, -131, 188, 63, +167, 81, -10, -42, -138, -76, -107, 75, +17, 214, 86, 122, 30, -123, -74, -263, +-89, -156, -15, 85, 69, 206, 99, 143, +44, 1, -44, -102, -117, -126, -115, -100, +-36, -13, 83, 111, 153, 200, 99, 141, +-47, -59, -164, -248, -166, -248, -39, -36, +124, 207, 186, 263, 89, 106, -67, -102, +-163, -174, -147, -89, -34, 32, 88, 80, +120, 39, 61, -30, -18, -72, -79, -37, +-75, 60, 3, 137, 55, 107, 22, -55, +-48, -207, -80, -183, -37, 19, 46, 208, +104, 200, 66, 38, -22, -117, -98, -159, +-112, -104, -62, -17, 41, 83, 109, 184, +73, 195, -44, 12, -128, -262, -78, -344, +82, -94, 160, 301, 61, 437, -127, 152, +-238, -271, -149, -422, 80, -171, 260, 185, +230, 311, 29, 157, -202, -72, -292, -166, +-163, -113, 92, -16, 233, 48, 161, 60, +-19, 38, -130, 5, -98, 0, 6, 27, +20, 30, -59, -42, -80, -138, 33, -110, +160, 73, 133, 245, -53, 190, -229, -89, +-187, -314, 32, -231, 218, 100, 180, 346, +-30, 244, -203, -103, -178, -329, -13, -206, +126, 114, 143, 284, 60, 148, -65, -128, +-147, -232, -127, -77, -13, 148, 111, 212, +148, 64, 36, -130, -138, -196, -160, -102, +-11, 52, 147, 148, 129, 153, -31, 85, +-185, -30, -164, -163, 19, -236, 187, -143, +193, 118, 53, 349, -138, 303, -251, -49, +-177, -399, 44, -385, 240, -6, 231, 361, +18, 357, -218, 35, -238, -239, -47, -222, +179, -31, 201, 83, 16, 51, -203, -5, +-218, 30, -31, 96, 182, 70, 229, -40, +84, -136, -135, -130, -245, -30, -163, 98, +10, 164, 149, 116, 178, -19, 96, -140, +-77, -139, -171, -31, -134, 78, -9, 108, +72, 60, 94, 1, 31, -30, -14, -48, +-22, -57, -39, -39, -97, 19, -97, 69, +8, 72, 145, 28, 171, -12, 28, -30, +-148, -61, -205, -84, -87, -50, 65, 68, +136, 171, 63, 119, -35, -67, -61, -202, +12, -110, 52, 106, 18, 184, -92, 21, +-146, -182, -60, -143, 94, 108, 135, 236, +40, 61, -44, -200, -20, -201, 29, 76, +-17, 255, -137, 66, -193, -256, -14, -268, +243, 96, 293, 398, 21, 245, -275, -214, +-305, -448, -30, -182, 251, 268, 238, 398, +-35, 96, -251, -253, -171, -284, 74, -29, +196, 187, 77, 154, -94, -11, -115, -90, +0, -30, 64, 36, 0, 23, -115, -29, +-99, -38, 49, -6, 177, 23, 113, 31, +-45, 31, -160, 21, -167, -20, -60, -72, +95, -73, 191, 23, 128, 133, -24, 133, +-202, -19, -232, -205, -66, -227, 186, -26, +262, 252, 122, 343, -122, 129, -266, -232, +-218, -420, 17, -245, 224, 158, 236, 432, +49, 311, -187, -83, -264, -379, -109, -305, +156, 51, 268, 315, 132, 251, -158, -33, +-311, -223, -190, -172, 106, -6, 282, 89, +222, 76, -23, 68, -210, 94, -206, 45, +-65, -119, 27, -248, 64, -150, 81, 135, +93, 311, 79, 181, 6, -106, -116, -240, +-217, -114, -157, 72, 19, 97, 170, -7, +194, -53, 105, 30, -46, 129, -134, 94, +-128, -53, -94, -170, -90, -143, -42, -12, +95, 109, 254, 144, 265, 93, 44, 18, +-283, -34, -431, -76, -238, -125, 124, -138, +360, -57, 287, 122, 44, 275, -129, 230, +-163, -30, -138, -300, -114, -338, -54, -89, +62, 235, 210, 335, 210, 141, -15, -140, +-241, -253, -212, -118, 29, 92, 207, 174, +118, 76, -133, -83, -262, -148, -63, -64, +225, 103, 263, 204, 14, 121, -244, -109, +-246, -295, -9, -226, 218, 85, 180, 353, +-50, 287, -216, -45, -146, -286, 65, -204, +176, 56, 88, 143, -68, -10, -123, -141, +-32, -13, 37, 234, 21, 254, -74, -10, +-76, -276, 40, -262, 136, -39, 84, 118, +-58, 110, -138, 56, -90, 84, 30, 124, +85, 27, 8, -169, -80, -255, -42, -119, +64, 114, 95, 222, 13, 137, -103, -12, +-155, -72, -46, -52, 116, -25, 160, -32, +37, -32, -131, 4, -195, 44, -91, 58, +112, 52, 221, 37, 127, -10, -106, -88, +-253, -141, -155, -78, 83, 88, 226, 220, +115, 177, -107, -33, -206, -232, -69, -242, +132, -63, 159, 153, -4, 248, -140, 168, +-120, -16, -7, -170, 71, -203, 67, -92, +-7, 78, -23, 170, 7, 111, 2, -37, +-44, -123, -51, -63, -2, 60, 29, 101, +24, 18, -23, -79, -33, -81, 15, 10, +64, 66, 11, 17, -99, -50, -128, -21, +5, 73, 155, 112, 160, 23, -26, -120, +-202, -171, -208, -75, -13, 82, 182, 181, +206, 159, 46, 30, -121, -132, -159, -218, +-91, -138, 5, 72, 51, 245, 35, 206, +30, -32, 77, -251, 87, -228, -29, 17, +-177, 237, -195, 215, -44, -19, 174, -213, +248, -180, 84, 26, -160, 170, -218, 122, +-83, -29, 78, -114, 130, -62, 61, 42, +-22, 65, -45, 4, -45, -55, -59, -47, +-74, 25, 12, 85, 141, 70, 167, -18, +1, -115, -215, -121, -249, -15, -24, 119, +240, 153, 279, 47, 23, -90, -260, -144, +-271, -78, 7, 27, 237, 96, 193, 99, +-41, 43, -216, -36, -152, -95, 61, -79, +188, -7, 84, 55, -85, 53, -132, 22, +-38, 17, 54, 37, 49, 3, -37, -91, +-70, -137, 33, -47, 143, 126, 74, 193, +-108, 80, -216, -100, -109, -160, 84, -68, +192, 26, 105, 39, -46, 15, -88, 51, +-14, 109, 36, 66, -49, -97, -144, -233, +-96, -153, 84, 102, 220, 283, 172, 198, +-26, -69, -201, -247, -199, -168, -42, 52, +92, 165, 96, 82, 31, -73, -11, -112, +-11, 9, 16, 142, 15, 120, -48, -42, +-86, -182, -43, -148, 27, 32, 71, 161, +67, 128, -3, -9, -83, -98, -86, -68, +0, 0, 93, 25, 102, 11, 25, 26, +-98, 51, -153, 10, -107, -92, 33, -135, +156, -19, 194, 162, 79, 210, -113, 43, +-277, -177, -229, -212, 26, -30, 290, 172, +293, 171, 25, -21, -280, -174, -342, -125, +-68, 73, 284, 201, 357, 139, 46, -50, +-304, -194, -371, -169, -76, -10, 277, 154, +373, 186, 86, 62, -249, -112, -331, -175, +-109, -52, 147, 117, 241, 154, 119, 32, +-55, -103, -131, -104, -101, -18, -58, 17, +-32, -23, 43, -5, 148, 127, 181, 218, +25, 83, -201, -223, -297, -379, -108, -188, +198, 197, 341, 407, 142, 253, -185, -85, +-318, -285, -144, -217, 114, -11, 218, 119, +123, 122, -61, 79, -124, 27, -63, -21, +4, -93, -14, -128, -30, -64, 24, 72, +108, 183, 111, 154, 3, -3, -164, -172, +-205, -217, -59, -81, 148, 125, 220, 233, +91, 142, -96, -80, -188, -217, -102, -136, +49, 82, 125, 201, 45, 93, -49, -109, +-62, -172, 32, -45, 73, 98, 10, 96, +-110, -6, -121, -36, 8, 44, 159, 78, +141, -40, -26, -192, -147, -143, -108, 102, +20, 266, 69, 140, 36, -154, -32, -263, +5, -64, 75, 214, 70, 241, -79, -19, +-176, -262, -101, -233, 89, 44, 176, 267, +99, 224, -81, 2, -143, -178, -29, -167, +109, -39, 67, 57, -110, 51, -178, 3, +-25, 17, 221, 87, 266, 107, 50, 1, +-260, -169, -330, -223, -119, -73, 186, 162, +289, 254, 176, 121, -20, -87, -140, -176, +-176, -101, -137, -5, -60, 21, 63, 31, +197, 91, 229, 131, 71, 29, -173, -165, +-261, -223, -130, -27, 90, 231, 179, 228, +87, -54, -67, -275, -74, -158, 50, 158, +109, 273, -6, 44, -152, -243, -140, -228, +23, 61, 165, 265, 118, 158, -48, -107, +-139, -220, -33, -88, 108, 86, 124, 110, +-32, 22, -161, -36, -133, -11, 30, 31, +161, 25, 144, -22, -8, -66, -126, -81, +-92, -35, 19, 79, 85, 165, 40, 106, +-49, -93, -98, -236, -22, -131, 86, 141, +122, 266, 31, 71, -74, -225, -108, -265, +-42, 23, 43, 309, 73, 237, 12, -113, +-50, -334, -18, -183, 62, 158, 82, 283, +-5, 83, -112, -167, -133, -173, -9, 29, +131, 149, 166, 45, 32, -117, -112, -105, +-152, 65, -57, 151, 65, 31, 127, -139, +71, -126, -32, 49, -87, 169, -55, 86, +9, -113, 36, -181, 29, -53, 16, 126, +9, 180, 3, 54, -13, -104, -59, -150, +-53, -63, 21, 56, 93, 93, 67, 48, +-29, -7, -86, -3, -56, 23, 33, -11, +77, -100, 27, -140, -61, -22, -64, 170, +16, 243, 80, 91, 49, -166, -27, -274, +-76, -135, -39, 106, 27, 215, 49, 112, +2, -53, -39, -109, 12, -40, 85, 32, +70, 25, -46, -38, -135, -63, -127, -3, +14, 66, 151, 84, 168, 34, 43, -43, +-75, -87, -130, -63, -99, 9, -33, 67, +47, 54, 89, -9, 89, -43, 53, 2, +-12, 60, -87, 36, -106, -74, -29, -138, +62, -43, 93, 115, 38, 163, -42, 48, +-74, -104, -5, -131, 81, -41, 78, 57, +-21, 64, -99, 20, -89, -2, -10, -11, +75, -29, 100, -35, 57, 7, -25, 73, +-71, 69, -68, -27, -17, -122, 26, -83, +39, 52, 6, 116, -17, 51, 13, -56, +70, -48, 58, 48, -28, 71, -130, -49, +-155, -174, -41, -111, 151, 113, 250, 273, +140, 169, -93, -109, -264, -290, -211, -214, +2, 41, 213, 227, 219, 210, 48, 39, +-128, -135, -138, -177, -25, -80, 73, 66, +63, 132, -38, 72, -97, -38, -25, -90, +120, -35, 153, 38, 34, 41, -143, -9, +-187, -38, -74, 10, 117, 65, 187, 44, +98, -44, -66, -105, -135, -65, -95, 34, +0, 104, 85, 87, 112, 9, 55, -56, +-49, -91, -104, -78, -79, -10, 22, 88, +100, 146, 89, 76, -26, -90, -107, -212, +-73, -143, 56, 89, 134, 267, 97, 213, +-43, -57, -156, -295, -143, -280, 3, -26, +151, 242, 173, 291, 73, 103, -78, -132, +-161, -214, -130, -96, -6, 62, 85, 109, +102, 18, 61, -67, 20, -38, -9, 54, +-37, 98, -78, 29, -100, -63, -33, -84, +101, -21, 170, 35, 77, 12, -86, -22, +-161, 3, -66, 67, 68, 66, 113, -30, +10, -107, -83, -61, -62, 72, 59, 135, +101, 41, 22, -102, -80, -140, -92, -32, +-25, 81, 47, 85, 68, 25, 42, 3, +16, 37, 3, 23, -30, -73, -86, -156, +-70, -105, 19, 59, 119, 176, 99, 154, +-3, 31, -111, -76, -111, -104, -15, -80, +84, -37, 95, 18, 36, 66, -8, 73, +-47, 24, -83, -33, -97, -50, -9, -25, +134, 18, 226, 35, 126, 28, -127, -2, +-333, -50, -250, -77, 73, -47, 362, 48, +334, 115, 30, 84, -280, -28, -319, -99, +-89, -47, 168, 39, 221, 35, 79, -65, +-58, -106, -83, 4, -21, 151, 9, 163, +-1, -9, -27, -158, -2, -119, 52, 30, +52, 103, -21, 10, -66, -104, -25, -82, +51, 59, 81, 158, 18, 117, -67, -2, +-94, -106, -18, -156, 60, -149, 84, -54, +36, 137, -2, 285, -22, 211, -31, -80, +-48, -339, -33, -296, 1, 28, 56, 312, +80, 290, 40, 8, -24, -238, -60, -234, +-42, -28, -27, 150, -1, 154, 19, 35, +56, -73, 58, -73, 39, -2, -35, 49, +-99, 15, -91, -70, 19, -89, 118, 2, +132, 127, 35, 141, -97, 4, -153, -161, +-78, -177, 67, -15, 155, 153, 136, 156, +25, 12, -104, -118, -177, -118, -119, -37, +31, 42, 171, 87, 180, 103, 61, 65, +-95, -67, -164, -196, -103, -170, 24, 49, +97, 264, 72, 216, 22, -56, -10, -264, +-1, -177, -7, 93, -32, 215, -54, 53, +-9, -161, 65, -142, 96, 75, 1, 206, +-98, 68, -93, -171, 24, -205, 131, 1, +110, 210, -29, 177, -137, -54, -109, -204, +-1, -132, 84, 61, 84, 167, 52, 110, +6, -18, -27, -109, -60, -111, -57, -48, +-33, 47, 15, 114, 62, 87, 75, -3, +32, -76, -24, -70, -47, -16, -48, 12, +-16, -6, 21, -6, 48, 50, 30, 93, +9, 37, -11, -84, -23, -140, -25, -66, +10, 53, 39, 98, 41, 64, 4, 19, +-52, 11, -90, -21, -37, -95, 88, -127, +171, -33, 101, 125, -84, 161, -219, 32, +-166, -115, 65, -103, 222, 48, 153, 118, +-62, 4, -157, -144, -62, -104, 88, 84, +84, 180, -55, 57, -142, -135, -48, -142, +136, 37, 197, 177, 58, 97, -134, -117, +-186, -215, -77, -101, 78, 92, 149, 191, +108, 138, 3, 5, -83, -109, -110, -157, +-69, -110, 21, 12, 119, 143, 124, 167, +14, 46, -118, -113, -152, -163, -45, -57, +100, 89, 159, 145, 74, 62, -48, -67, +-112, -121, -71, -77, -15, 25, 35, 82, +58, 69, 70, 8, 41, -37, -26, -27, +-86, 0, -67, 5, 25, -19, 94, -21, +61, 2, -47, 3, -102, -26, -25, -37, +106, 49, 131, 168, 16, 144, -144, -81, +-168, -326, -21, -294, 161, 48, 179, 385, +34, 373, -114, 21, -130, -305, -24, -317, +70, -74, 58, 133, -14, 135, -21, 53, +35, 41, 62, 76, -4, 10, -79, -157, +-90, -217, -9, -56, 84, 185, 107, 251, +46, 72, -29, -145, -82, -184, -95, -57, +-52, 46, 34, 53, 131, 33, 150, 61, +42, 79, -124, -7, -194, -138, -98, -158, +87, -10, 182, 158, 110, 160, -50, 8, +-118, -129, -50, -118, 45, 4, 55, 94, +-9, 79, -54, 0, -30, -61, 35, -76, +62, -50, 34, 22, -4, 95, -13, 111, +-23, 36, -40, -79, -62, -130, -37, -85, +43, 17, 129, 92, 134, 98, 20, 56, +-132, -22, -191, -95, -93, -101, 80, -13, +183, 101, 122, 118, -16, -4, -105, -133, +-80, -110, -9, 55, 14, 176, -19, 106, +-9, -91, 54, -178, 105, -74, 64, 82, +-63, 116, -152, 16, -92, -54, 61, -4, +140, 75, 74, 30, -55, -106, -106, -147, +-32, -4, 70, 185, 77, 189, -11, -15, +-85, -214, -57, -197, 36, 21, 92, 215, +50, 194, -32, -11, -75, -187, -41, -180, +26, -25, 59, 127, 39, 153, -14, 57, +-36, -52, -25, -88, -4, -51, -2, -8, +4, 9, 26, 24, 56, 51, 36, 62, +-30, -4, -91, -94, -82, -87, 11, 24, +114, 121, 122, 82, 28, -66, -75, -155, +-103, -75, -56, 87, 14, 144, 57, 59, +68, -57, 56, -83, 9, -29, -54, 1, +-87, -17, -46, -12, 46, 43, 104, 80, +58, 37, -44, -50, -92, -89, -46, -31, +44, 45, 91, 45, 47, 3, -36, -19, +-76, 3, -59, 15, -5, -9, 48, -29, +84, -6, 69, 44, 5, 47, -83, -10, +-119, -66, -65, -52, 48, 8, 136, 39, +129, 29, 31, 25, -91, 37, -153, 16, +-112, -65, 17, -122, 141, -60, 169, 83, +51, 166, -103, 73, -156, -86, -64, -140, +78, -46, 117, 63, 23, 63, -74, -8, +-47, -30, 51, 26, 85, 54, -8, -1, +-120, -72, -99, -67, 58, 13, 184, 56, +120, 30, -83, -10, -202, -7, -122, 19, +84, 5, 194, -30, 105, -37, -72, -8, +-143, 21, -55, 23, 68, 19, 77, 33, +-21, 19, -82, -37, -19, -81, 108, -41, +133, 56, -7, 97, -182, 19, -180, -89, +17, -73, 214, 55, 201, 124, -2, 25, +-189, -130, -182, -133, -6, 23, 138, 156, +116, 101, 11, -68, -41, -127, -15, -22, +9, 87, -34, 48, -77, -84, -21, -111, +105, 32, 151, 172, 35, 116, -134, -88, +-175, -199, -29, -106, 151, 84, 172, 167, +21, 76, -140, -51, -147, -91, -2, -43, +131, 0, 125, 12, 5, 6, -88, 10, +-85, 29, -13, 40, 41, 28, 40, -18, +9, -80, 2, -102, 11, -25, 2, 113, +-34, 182, -51, 89, -5, -97, 64, -199, +78, -130, -4, 10, -91, 88, -74, 98, +51, 110, 140, 108, 76, 5, -92, -190, +-177, -289, -83, -128, 109, 186, 194, 342, +88, 181, -83, -123, -141, -256, -54, -130, +54, 56, 76, 96, 13, 9, -33, -37, +-12, 16, 40, 60, 43, 18, 0, -47, +-36, -23, -42, 61, -37, 51, -24, -91, +11, -193, 76, -73, 119, 188, 78, 298, +-52, 109, -180, -199, -171, -313, -8, -133, +183, 127, 227, 221, 84, 117, -125, -27, +-206, -90, -109, -70, 65, -50, 146, -35, +79, 17, -34, 89, -63, 105, 3, 30, +49, -77, 9, -139, -74, -95, -77, 29, +34, 133, 141, 136, 100, 34, -56, -95, +-171, -138, -111, -61, 54, 56, 170, 85, +127, 27, -13, -23, -118, -3, -126, 36, +-60, 7, 29, -68, 109, -79, 135, 15, +84, 106, -42, 69, -150, -66, -153, -132, +-34, -36, 110, 115, 160, 153, 90, 26, +-15, -131, -95, -162, -108, -48, -61, 89, +34, 138, 110, 85, 105, -18, 2, -103, +-114, -123, -124, -41, 5, 89, 153, 157, +145, 84, -17, -84, -174, -187, -167, -117, +-6, 60, 157, 171, 175, 130, 63, 7, +-62, -80, -117, -100, -109, -93, -65, -61, +14, 28, 110, 147, 164, 177, 106, 45, +-46, -151, -179, -213, -169, -71, -19, 119, +139, 164, 160, 53, 57, -75, -65, -94, +-100, -37, -42, 9, 36, 22, 53, 47, +8, 77, -22, 39, -11, -66, 15, -147, +24, -108, 10, 32, -7, 145, -12, 147, +-11, 50, -19, -62, -15, -127, 37, -118, +89, -39, 64, 49, -54, 86, -162, 59, +-122, 11, 74, 0, 253, 17, 199, 3, +-69, -77, -293, -142, -241, -76, 41, 91, +276, 210, 237, 144, -12, -53, -215, -190, +-176, -143, 24, 22, 162, 120, 109, 72, +-42, -30, -134, -49, -87, 14, 46, 47, +144, -10, 122, -71, 1, -40, -121, 62, +-161, 96, -81, 1, 65, -118, 180, -111, +155, 32, 14, 154, -136, 119, -174, -40, +-79, -148, 79, -106, 170, 27, 108, 110, +-45, 62, -138, -48, -83, -86, 54, -2, +138, 94, 69, 75, -89, -55, -152, -146, +-38, -68, 128, 105, 156, 167, 12, 26, +-140, -160, -131, -154, 25, 58, 143, 220, +86, 124, -65, -134, -122, -247, -26, -83, +92, 160, 96, 203, -15, 22, -98, -150, +-60, -112, 51, 63, 105, 138, 41, 30, +-60, -123, -93, -135, -53, 2, 17, 122, +72, 106, 89, 1, 64, -62, -2, -22, +-86, 28, -132, -3, -99, -75, 23, -97, +147, -7, 174, 121, 91, 162, -53, 69, +-173, -80, -187, -166, -76, -123, 85, 5, +207, 107, 201, 113, 57, 32, -142, -52, +-244, -69, -161, -14, 42, 45, 207, 46, +208, -16, 57, -72, -139, -54, -206, 17, +-93, 76, 93, 62, 182, -1, 108, -59, +-42, -69, -136, -15, -103, 49, 14, 57, +89, 2, 78, -57, 30, -54, -18, 15, +-49, 65, -55, 39, -29, -23, 16, -32, +46, 22, 48, 35, 3, -29, -37, -102, +-16, -67, 27, 72, 25, 169, -27, 102, +-62, -60, -36, -154, 35, -110, 87, -7, +71, 60, 6, 76, -49, 80, -71, 61, +-65, -24, -45, -127, 24, -148, 115, -19, +138, 151, 50, 176, -91, 22, -166, -150, +-100, -157, 44, -2, 135, 120, 98, 85, +-3, -37, -58, -81, -34, -2, 10, 89, +24, 58, -11, -61, -62, -128, -58, -71, +24, 46, 112, 123, 130, 102, 45, 22, +-102, -60, -177, -116, -107, -102, 58, -27, +163, 71, 112, 120, -17, 84, -91, 15, +-60, -39, 18, -70, 32, -88, -22, -78, +-52, 8, 6, 123, 89, 152, 79, 37, +-15, -130, -93, -164, -78, -24, 21, 126, +92, 125, 63, -19, -20, -126, -71, -76, +-39, 35, 24, 70, 47, 26, 27, -8, +-4, 19, -13, 38, -3, -20, -9, -108, +-30, -111, -25, 13, 17, 150, 57, 151, +55, 7, 4, -135, -57, -137, -63, -15, +-11, 104, 43, 99, 37, 2, -18, -74, +-37, -61, 12, 5, 70, 50, 47, 43, +-45, 7, -108, -13, -55, -17, 69, -32, +120, -53, 42, -46, -65, 22, -87, 122, +-5, 138, 64, 17, 44, -164, -29, -226, +-53, -75, 2, 171, 51, 274, 27, 113, +-35, -152, -49, -254, 6, -109, 54, 113, +36, 185, -30, 78, -57, -62, -9, -98, +43, -37, 37, 12, -18, 14, -45, 12, +-10, 34, 39, 47, 36, 16, -17, -37, +-56, -65, -35, -47, 28, 3, 74, 51, +45, 79, -29, 51, -73, -31, -54, -102, +12, -82, 64, 32, 56, 119, -1, 75, +-47, -57, -35, -121, 1, -34, 13, 96, +0, 111, -3, -12, 15, -117, 39, -85, +27, 34, -22, 87, -56, 37, -31, -32, +31, -34, 56, 6, 29, 1, -23, -40, +-46, -37, -23, 45, 17, 111, 37, 55, +23, -78, -7, -138, -36, -54, -50, 79, +-25, 112, 43, 30, 87, -41, 61, -27, +-32, 25, -114, 5, -99, -63, 0, -75, +97, 8, 108, 103, 35, 112, -49, 23, +-66, -83, -51, -100, -28, -52, 1, 16, +41, 66, 80, 79, 71, 40, -3, -44, +-98, -94, -119, -58, -42, 48, 74, 107, +131, 58, 77, -51, -23, -107, -92, -56, +-82, 24, -21, 55, 37, 36, 60, 17, +51, 25, 27, 15, -2, -42, -49, -92, +-85, -69, -65, 22, 25, 96, 125, 87, +139, 9, 23, -49, -140, -51, -185, -21, +-65, -4, 117, -18, 190, -12, 103, 31, +-61, 86, -158, 83, -119, -16, -21, -133, +55, -149, 113, -22, 135, 151, 72, 206, +-71, 59, -200, -162, -190, -233, -4, -83, +209, 136, 246, 202, 70, 78, -140, -76, +-191, -103, -93, -27, 25, -1, 71, -54, +66, -61, 65, 66, 64, 199, -9, 141, +-121, -109, -134, -278, -16, -147, 134, 139, +151, 254, 12, 65, -136, -178, -129, -170, +15, 63, 129, 206, 100, 66, -27, -170, +-102, -196, -57, 22, 38, 204, 71, 135, +6, -87, -61, -194, -39, -71, 43, 120, +85, 159, 42, 29, -48, -98, -100, -100, +-59, -12, 28, 42, 69, 22, 46, -14, +13, -7, -10, 46, -9, 63, -8, 10, +-27, -67, -35, -100, -2, -63, 46, 13, +44, 74, -1, 78, -31, 51, -18, 23, +13, -14, 19, -64, -11, -112, -41, -89, +-21, 27, 34, 146, 43, 147, 0, 15, +-30, -125, -19, -119, 18, 9, 37, 89, +4, 24, -44, -82, -44, -68, 2, 72, +36, 159, 32, 50, 8, -142, -6, -189, +-1, -27, -2, 171, -11, 178, -31, 9, +-23, -151, 13, -145, 18, -14, 8, 86, +12, 97, 28, 54, 22, 17, -17, -30, +-64, -89, -66, -100, 0, -29, 67, 80, +63, 124, 3, 63, -49, -29, -36, -67, +10, -40, 30, -2, 5, 8, -38, -2, +-50, -8, -8, 0, 40, 26, 74, 47, +67, 46, -10, -6, -103, -86, -118, -109, +-27, -21, 104, 105, 158, 131, 52, 20, +-114, -113, -168, -113, -54, 13, 107, 114, +157, 83, 56, -23, -83, -79, -131, -51, +-67, -8, 33, -1, 75, 9, 66, 56, +38, 95, -3, 42, -59, -75, -75, -141, +-45, -69, 11, 64, 67, 112, 71, 34, +21, -56, -30, -39, -50, 45, -40, 71, +-5, -5, 26, -92, 25, -89, 2, -6, +-6, 62, 13, 68, 23, 44, -6, 21, +-43, -19, -52, -77, -2, -103, 78, -30, +92, 99, 13, 137, -72, 21, -99, -134, +-57, -157, 31, -1, 96, 186, 86, 200, +34, 6, -46, -206, -111, -239, -96, -61, +6, 158, 111, 229, 116, 109, 9, -70, +-97, -149, -85, -94, 11, 7, 72, 46, +32, 13, -52, -7, -49, 37, 34, 86, +73, 38, 11, -90, -78, -160, -79, -66, +36, 117, 141, 189, 90, 58, -69, -143, +-171, -192, -115, -41, 50, 140, 164, 165, +125, 31, -2, -99, -96, -100, -96, -14, +-45, 41, 3, 10, 34, -21, 57, 5, +57, 51, 26, 43, -21, -21, -67, -55, +-62, -21, 4, 19, 47, 9, 40, -32, +17, -32, -13, 24, -23, 65, -17, 38, +-9, -31, 2, -51, 36, -12, 57, 24, +28, -7, -45, -60, -110, -45, -84, 37, +24, 110, 143, 89, 174, -13, 49, -103, +-136, -110, -218, -42, -135, 34, 52, 70, +203, 69, 183, 47, 23, 24, -127, -11, +-163, -73, -92, -116, 27, -83, 111, 42, +115, 165, 50, 155, -59, -1, -126, -170, +-88, -169, 29, 7, 126, 162, 90, 124, +-43, -52, -119, -142, -59, -44, 52, 114, +87, 117, 1, -39, -89, -154, -39, -74, +80, 111, 106, 166, 2, 25, -128, -137, +-142, -129, -3, 6, 142, 91, 149, 43, +31, -24, -101, 8, -135, 80, -62, 42, +39, -107, 96, -188, 71, -69, -4, 146, +-48, 216, -38, 71, -15, -114, 5, -147, +2, -34, -6, 60, 13, 40, 33, -31, +6, -31, -30, 39, -30, 81, -5, 38, +20, -48, 12, -86, -18, -50, -15, 19, +16, 65, 31, 50, 0, 3, -44, -40, +-23, -52, 31, -26, 48, 6, 10, 34, +-36, 47, -41, 44, 1, 4, 34, -82, +0, -135, -28, -75, 13, 93, 55, 223, +38, 152, -44, -84, -112, -261, -74, -185, +47, 64, 128, 223, 89, 142, -21, -52, +-99, -125, -81, -44, -22, 48, 12, 23, +20, -51, 21, -34, 52, 67, 69, 108, +7, -1, -93, -139, -122, -130, -51, 36, +70, 171, 131, 121, 62, -55, -60, -162, +-104, -92, -48, 61, 39, 127, 71, 52, +15, -59, -55, -92, -61, -26, -10, 66, +46, 93, 45, 25, 2, -77, -30, -117, +-27, -52, -3, 74, 14, 141, -6, 77, +-39, -61, -30, -139, 3, -83, 35, 44, +51, 120, 31, 85, -25, -3, -69, -78, +-84, -94, -53, -57, 32, 17, 109, 96, +109, 121, 15, 47, -98, -82, -133, -150, +-54, -99, 59, 25, 104, 112, 36, 106, +-65, 44, -78, -21, -8, -69, 57, -95, +71, -76, 9, 17, -73, 112, -92, 114, +-53, 9, 12, -102, 86, -108, 112, -3, +36, 95, -84, 77, -146, -18, -87, -73, +41, -39, 110, 20, 74, 26, -24, 0, +-77, -2, -38, 29, 14, 40, 5, -10, +-18, -78, -15, -74, 10, 10, 29, 89, +13, 75, -37, -8, -52, -67, -22, -46, +19, 7, 46, 27, 30, 5, -13, -18, +-60, 3, -69, 31, -26, 21, 39, -24, +65, -47, 25, -12, -36, 44, -68, 58, +-33, -3, 20, -69, 21, -68, -9, 7, +-26, 82, -15, 76, 10, -5, 18, -78, +-12, -67, -34, 7, -25, 60, -9, 46, +-1, -10, 6, -42, 3, -23, -1, 7, +-11, 17, -24, 15, -27, 24, -11, 13, +8, -22, 2, -60, -18, -47, -34, 42, +-14, 117, 9, 77, 17, -56, -7, -139, +-48, -81, -54, 57, -1, 123, 47, 58, +44, -52, -4, -77, -64, -13, -78, 33, +-26, -4, 43, -55, 57, -11, 18, 90, +-33, 112, -52, -13, -40, -162, -20, -153, +-4, 30, 7, 191, 23, 154, 30, -37, +-11, -164, -71, -107, -78, 41, -28, 112, +40, 48, 70, -46, 27, -61, -50, -7, +-80, 37, -61, 41, -16, 21, 30, -3, +36, -28, 18, -61, -11, -59, -44, 9, +-52, 94, -29, 109, -2, 29, 19, -92, +9, -132, -34, -55, -34, 53, 4, 110, +31, 70, 15, -19, -46, -73, -97, -55, +-58, -2, 40, 30, 94, 14, 50, -12, +-61, 4, -119, 41, -76, 49, 17, -16, +69, -92, 34, -87, -29, 15, -64, 119, +-58, 113, -35, 2, 4, -100, 45, -92, +43, -6, 1, 44, -69, 21, -116, -5, +-75, 24, 25, 69, 79, 42, 70, -68, +10, -142, -51, -82, -83, 73, -78, 158, +-47, 81, 3, -66, 50, -133, 62, -63, +21, 59, -38, 107, -78, 46, -70, -53, +-36, -95, -8, -45, 9, 38, 15, 81, +15, 55, 9, -11, -11, -50, -36, -45, +-53, -21, -65, -6, -45, -3, 7, 19, +54, 65, 57, 65, 1, -5, -81, -96, +-99, -109, -49, -8, 23, 97, 57, 94, +15, -2, -56, -69, -75, -35, -47, 43, +-3, 49, 31, -29, 20, -83, -3, -36, +-33, 71, -58, 104, -72, 21, -45, -85, +4, -98, 44, -12, 51, 74, 18, 72, +-46, 6, -90, -41, -96, -34, -57, -5, +4, -1, 58, -18, 69, -11, 24, 37, +-37, 73, -81, 46, -102, -38, -82, -108, +-22, -98, 43, 3, 76, 112, 57, 126, +-10, 35, -90, -72, -114, -98, -91, -36, +-32, 25, 40, 16, 76, -19, 65, -4, +6, 72, -88, 104, -146, 17, -115, -125, +3, -168, 113, -46, 119, 122, -3, 165, +-147, 51, -175, -78, -60, -97, 95, -26, +146, 29, 30, 14, -130, -16, -182, 12, +-91, 60, 55, 47, 120, -39, 69, -97, +-48, -46, -124, 63, -117, 105, -52, 27, +24, -84, 74, -99, 54, -3, -23, 100, +-105, 91, -113, -18, -47, -107, 42, -81, +65, 31, 2, 111, -67, 81, -85, -21, +-54, -105, 6, -100, 27, -7, 5, 85, +-17, 104, -35, 40, -44, -51, -59, -88, +-46, -63, -14, -2, 19, 54, 34, 67, +-2, 50, -61, 3, -84, -50, -66, -81, +-6, -57, 26, 21, 20, 86, -27, 86, +-60, 14, -46, -65, -7, -84, 8, -28, +-19, 33, -63, 51, -71, 22, -20, -17, +36, -20, 42, 8, -17, 31, -78, 15, +-104, -24, -60, -54, 12, -47, 56, 11, +45, 71, -18, 74, -97, 17, -110, -56, +-62, -76, 21, -35, 71, 18, 40, 41, +-50, 30, -107, 15, -85, 6, -23, -13, +36, -44, 37, -44, -19, 8, -64, 65, +-61, 49, -30, -33, 0, -89, -1, -36, +-25, 76, -49, 106, -41, 10, -21, -112, +-6, -112, 0, 16, -12, 126, -37, 93, +-57, -29, -66, -101, -38, -55, 4, 34, +36, 52, 7, 3, -64, -18, -97, 24, +-67, 65, 13, 17, 62, -89, 8, -129, +-85, -37, -114, 108, -52, 159, 47, 62, +77, -82, 15, -138, -87, -68, -120, 39, +-89, 71, -21, 13, 42, -33, 56, 12, +27, 87, -32, 82, -113, -42, -147, -174, +-91, -155, 35, 32, 127, 209, 87, 208, +-61, 18, -183, -180, -158, -197, -6, -45, +108, 114, 83, 133, -39, 40, -132, -43, +-105, -46, -14, -10, 50, -10, 19, -34, +-36, -15, -61, 46, -49, 79, -27, 25, +-20, -75, -31, -105, -15, -21, 0, 99, +-6, 120, -49, 24, -79, -101, -60, -137, +-8, -42, 44, 90, 20, 143, -49, 68, +-100, -59, -86, -129, -16, -80, 47, 29, +45, 88, -20, 60, -93, -5, -99, -34, +-53, -16, 11, 0, 35, -20, 2, -28, +-34, 6, -46, 64, -54, 66, -55, -9, +-54, -88, -23, -80, 15, 10, 31, 90, +-7, 72, -60, -9, -68, -49, -49, -27, +-38, 4, -39, -19, -31, -51, 9, -13, +66, 82, 44, 133, -73, 53, -184, -105, +-155, -184, -13, -97, 127, 85, 130, 182, +-3, 114, -133, -36, -148, -129, -70, -102, +16, -11, 34, 55, 6, 61, -25, 32, +-26, 6, -25, -19, -47, -39, -60, -39, +-52, -7, -26, 45, 2, 64, 10, 17, +-6, -57, -28, -83, -51, -23, -66, 69, +-64, 104, -18, 37, 11, -69, 16, -114, +-8, -57, -47, 51, -66, 116, -51, 80, +-36, -20, -28, -96, -14, -92, 17, -23, +25, 57, -9, 94, -86, 63, -140, -11, +-90, -71, 31, -79, 116, -24, 83, 43, +-55, 70, -172, 30, -149, -33, -23, -52, +93, -18, 88, 28, -4, 34, -108, -4, +-115, -41, -44, -25, 18, 21, 32, 42, +0, 23, -48, -17, -71, -39, -61, -31, +-21, -7, 5, 28, 15, 56, 7, 45, +-44, -6, -80, -76, -77, -99, -31, -37, +26, 75, 41, 134, -8, 83, -71, -36, +-86, -119, -42, -104, 2, -16, 13, 62, +-30, 81, -54, 49, -23, 5, 11, -25, +4, -47, -45, -57, -90, -30, -72, 23, +5, 64, 62, 58, 33, 3, -49, -53, +-99, -63, -92, -14, -21, 40, 30, 52, +26, 8, -16, -32, -48, -30, -48, 7, +-42, 38, -42, 18, -34, -37, -16, -54, +28, -7, 26, 64, -40, 81, -99, 9, +-101, -70, -31, -82, 58, -18, 62, 54, +-19, 61, -97, 13, -85, -28, -19, -21, +24, 13, 2, 15, -56, -21, -60, -45, +-6, -27, 35, 29, 5, 70, -58, 54, +-93, -4, -61, -62, -4, -69, 24, -29, +4, 27, -11, 62, -16, 47, -25, 3, +-50, -38, -78, -46, -77, -15, -18, 20, +55, 35, 71, 21, 4, -6, -82, -34, +-121, -43, -81, -8, 3, 47, 47, 73, +32, 40, -26, -42, -55, -113, -50, -85, +-29, 21, -22, 118, -23, 118, -8, 23, +6, -77, -18, -106, -50, -66, -72, -6, +-50, 54, 18, 85, 64, 83, 25, 36, +-58, -54, -121, -126, -101, -117, -22, -5, +61, 116, 77, 152, 6, 76, -62, -65, +-101, -147, -77, -107, -20, 21, 16, 122, +11, 104, -12, -6, -25, -96, -18, -77, +-5, 23, -8, 84, -54, 37, -80, -59, +-50, -89, 18, -2, 63, 99, 34, 90, +-53, -26, -113, -122, -78, -93, 15, 31, +65, 122, 33, 84, -53, -26, -103, -87, +-64, -58, 11, -1, 56, 25, 26, 18, +-34, 13, -74, 32, -66, 40, -31, -2, +-2, -64, 4, -74, 2, -15, -10, 58, +-15, 82, -21, 29, -30, -47, -35, -67, +-38, -20, -33, 36, -23, 49, -3, 6, +22, -40, 13, -30, -4, 11, -48, 42, +-84, 19, -67, -23, -29, -29, 30, -5, +66, 11, 40, 7, -33, -7, -89, 1, +-89, 23, -45, 19, 11, -22, 38, -54, +17, -24, -3, 45, -22, 78, -52, 30, +-65, -60, -47, -83, -4, -16, 35, 64, +31, 67, -21, -6, -73, -62, -57, -37, +5, 33, 34, 55, 11, -1, -43, -63, +-62, -49, -28, 30, 17, 79, 11, 40, +-28, -48, -40, -83, -5, -35, 27, 45, +10, 71, -60, 25, -85, -43, -32, -60, +41, -15, 67, 31, 9, 36, -65, 1, +-76, -29, -21, -23, 17, 9, 0, 29, +-30, 25, -42, 2, -11, -25, 34, -43, +18, -28, -35, 9, -62, 56, -38, 68, +-6, 23, 3, -55, -7, -99, -24, -61, +-6, 30, 24, 104, 16, 89, -43, 15, +-89, -59, -74, -82, -8, -54, 64, -11, +81, 28, 23, 63, -54, 76, -95, 50, +-87, -30, -34, -110, 28, -113, 61, -20, +56, 98, 2, 140, -67, 74, -101, -45, +-78, -113, -1, -97, 71, -17, 81, 56, +15, 81, -67, 55, -101, 2, -83, -47, +-6, -63, 64, -31, 73, 29, 18, 59, +-41, 24, -79, -34, -84, -52, -26, -13, +39, 46, 59, 58, 36, 7, -17, -48, +-69, -54, -73, -9, -26, 36, 17, 39, +24, 8, 11, -17, -11, -12, -18, 4, +-9, 10, -13, -3, -40, -24, -40, -31, +-7, -9, 37, 32, 55, 55, 5, 41, +-62, -17, -89, -74, -51, -72, 16, -10, +58, 64, 48, 91, 2, 44, -24, -30, +-48, -74, -68, -72, -52, -37, -2, 16, +58, 72, 86, 94, 47, 60, -59, -29, +-128, -122, -90, -130, 2, -28, 70, 109, +64, 164, 12, 78, -33, -73, -35, -155, +-19, -94, -33, 42, -34, 114, -8, 75, +26, -24, 41, -85, 17, -55, -31, 22, +-54, 63, -24, 41, 10, -10, 17, -39, +-2, -38, -24, -23, -14, -8, 4, 22, +4, 54, -9, 55, -11, 14, -6, -45, +-9, -75, -14, -44, -36, 14, -31, 49, +10, 53, 51, 33, 44, 6, -10, -30, +-56, -64, -76, -66, -31, -18, 35, 64, +54, 104, 27, 54, -12, -41, -31, -101, +-35, -73, -26, 14, -5, 66, 8, 54, +22, 9, 27, -26, 2, -26, -43, -14, +-46, -17, -6, -19, 46, -4, 55, 30, +-3, 49, -71, 34, -86, -16, -20, -60, +65, -62, 90, -21, 32, 43, -44, 73, +-68, 49, -55, -13, -23, -59, 8, -57, +22, -16, 49, 29, 65, 44, 24, 26, +-67, -3, -119, -17, -77, -14, 13, -7, +109, -13, 116, -16, 17, -3, -82, 21, +-100, 42, -46, 29, 15, -13, 61, -56, +49, -58, -1, -9, -34, 55, -33, 70, +-15, 24, 9, -45, 36, -77, 16, -38, +-23, 29, -39, 66, -35, 52, -1, -1, +32, -50, 46, -60, 20, -28, -21, 19, +-38, 46, -31, 46, -12, 18, 0, -23, +22, -50, 32, -41, 14, -3, 1, 27, +-14, 31, -27, 16, -27, -1, -1, -6, +10, -7, 2, -13, 12, -21, 10, -15, +6, 3, 6, 24, 0, 32, -24, 20, +-39, -2, -15, -27, -6, -36, 11, -31, +41, -1, 44, 50, 13, 77, -31, 48, +-69, -32, -85, -102, -27, -96, 65, -8, +113, 99, 77, 138, -27, 69, -104, -66, +-97, -153, -20, -115, 52, 6, 73, 115, +40, 132, -7, 51, -19, -54, -25, -103, +-34, -74, -34, -5, -6, 47, 45, 54, +68, 33, 40, 5, -44, -20, -98, -33, +-58, -30, 30, -6, 95, 22, 79, 37, +-9, 28, -93, -12, -94, -39, -19, -35, +56, -4, 89, 37, 58, 58, -18, 42, +-81, -14, -79, -73, -24, -82, 39, -21, +83, 68, 54, 111, -11, 58, -63, -43, +-56, -113, 4, -87, 45, 13, 34, 91, +-20, 87, -37, 12, -7, -55, 33, -63, +52, -27, 5, 11, -49, 26, -54, 26, +-4, 21, 34, 15, 31, -5, 14, -33, +-17, -41, -13, -15, 10, 26, 4, 46, +-24, 28, -28, -7, 1, -24, 18, -14, +31, 2, 11, 9, -29, -2, -21, -14, +14, -7, 27, 11, -4, 24, -40, 30, +-46, 13, 1, -18, 65, -40, 73, -47, +15, -21, -66, 30, -81, 68, -31, 65, +30, 13, 59, -56, 37, -86, 8, -52, +-19, 24, -21, 71, -19, 57, -38, 10, +-20, -26, 27, -19, 64, 0, 43, -3, +-13, -30, -62, -44, -71, -6, 1, 59, +65, 94, 54, 61, -4, -27, -36, -109, +-33, -116, -17, -36, 15, 72, 12, 131, +5, 97, 25, 1, 31, -86, -14, -105, +-62, -65, -47, 0, 3, 56, 69, 85, +89, 74, 21, 16, -61, -72, -89, -119, +-44, -74, 26, 36, 76, 127, 62, 110, +3, -10, -45, -119, -57, -113, -18, -1, +20, 103, 34, 94, 27, -8, 0, -88, +-17, -67, -17, 23, -1, 77, 7, 37, +3, -38, 8, -68, 2, -23, -4, 37, +-5, 53, -6, 27, -7, -16, 9, -34, +30, -25, 9, -12, -19, -1, -31, 19, +-24, 34, 5, 26, 38, -5, 43, -38, +10, -43, -16, -3, -37, 39, -35, 32, +0, -15, 36, -45, 40, -19, 11, 31, +-12, 46, -32, 13, -24, -34, 9, -37, +23, 5, 25, 26, 1, 1, -24, -38, +-28, -34, -1, 33, 25, 92, 34, 59, +22, -46, -16, -127, -46, -90, -36, 26, +-1, 118, 35, 101, 53, 3, 35, -72, +-12, -80, -44, -25, -47, 25, -27, 28, +19, 16, 53, 17, 49, 23, 6, 4, +-32, -34, -53, -50, -34, -31, 29, 18, +58, 57, 34, 46, -21, -5, -44, -54, +-23, -50, 20, -8, 46, 33, 17, 38, +-18, 7, -34, -23, -9, -29, 30, -10, +30, 9, 2, 16, -27, 11, -15, -3, +6, -10, 20, -10, 7, 1, -34, 18, +-29, 21, 8, 17, 33, -5, 26, -28, +-4, -27, -25, -1, -40, 31, -4, 29, +29, 1, 28, -24, 18, -15, 4, 11, +-17, 18, -45, -1, -34, -28, 2, -21, +46, 19, 79, 46, 34, 30, -54, -25, +-102, -60, -58, -38, 37, 23, 97, 62, +82, 38, -7, -11, -78, -37, -77, -24, +-12, -2, 37, 8, 40, -1, 27, 2, +14, 28, 1, 44, -21, 9, -38, -52, +-46, -73, -13, -23, 53, 59, 85, 89, +42, 34, -37, -57, -76, -94, -62, -40, +0, 43, 71, 81, 71, 43, 28, -28, +-21, -59, -48, -48, -55, -8, -28, 28, +30, 49, 55, 53, 58, 16, 21, -40, +-45, -86, -74, -65, -41, 19, 29, 89, +61, 87, 47, 8, 3, -70, -36, -77, +-33, -26, -7, 22, 7, 29, 11, 8, +19, 10, 23, 29, 21, 17, -7, -35, +-37, -87, -33, -68, -1, 29, 35, 121, +40, 108, 14, -8, -21, -122, -30, -127, +-11, -22, -1, 87, 14, 104, 27, 30, +29, -48, 11, -52, -20, -10, -42, 15, +-36, -2, 16, -19, 58, 0, 43, 45, +-4, 54, -45, 3, -49, -46, -7, -48, +38, -1, 39, 38, 8, 26, -14, -5, +-18, -11, -3, 20, 3, 36, -6, 0, +-10, -51, 4, -54, 25, 9, 26, 67, +11, 58, -22, -5, -30, -64, -5, -52, +16, 1, 18, 33, 10, 16, 7, -4, +-2, 12, -5, 29, -8, 5, -26, -54, +-13, -85, 28, -33, 45, 74, 27, 113, +-16, 39, -51, -86, -40, -136, 16, -56, +57, 67, 42, 116, 0, 44, -44, -56, +-50, -85, -16, -31, 31, 38, 53, 43, +40, -4, 2, -37, -46, -14, -63, 34, +-28, 38, 39, -3, 81, -46, 59, -46, +-17, 4, -76, 47, -62, 48, -3, 18, +57, -16, 69, -27, 20, -16, -30, -3, +-37, 9, -27, 30, -9, 40, 16, 34, +27, 6, 25, -31, 15, -43, -2, -26, +-25, 18, -28, 60, -3, 64, 15, 17, +25, -43, 22, -69, 5, -43, -6, 21, +-12, 69, -14, 60, -22, 10, -2, -50, +30, -65, 33, -37, 22, 7, -14, 42, +-35, 43, -24, 15, 4, -31, 29, -63, +20, -58, 10, -10, -2, 42, 2, 45, +6, -3, -6, -54, -15, -48, -20, 1, +4, 30, 32, 5, 33, -37, 8, -38, +-18, 10, -20, 54, -18, 27, -1, -47, +23, -83, 27, -31, 26, 53, 10, 82, +-17, 24, -37, -53, -20, -54, 17, 17, +26, 69, 18, 45, -9, -27, -24, -53, +-10, 1, 18, 74, 20, 83, -13, 20, +-25, -47, -14, -51, 15, 4, 35, 50, +17, 46, -16, 19, -34, 2, 0, 6, +21, 12, 21, -11, 2, -28, -25, -14, +-2, 26, 24, 54, 32, 28, 2, -27, +-39, -57, -33, -35, 0, 17, 54, 39, +50, 19, 6, -21, -33, -41, -49, -36, +-12, -24, 25, -16, 41, -5, 31, 16, +8, 35, -11, 11, -28, -58, -24, -106, +-14, -81, 10, 12, 48, 90, 54, 84, +18, 0, -38, -88, -57, -106, -35, -43, +16, 28, 62, 51, 49, 26, 12, -2, +-23, 2, -36, 16, -26, 8, -2, -33, +19, -58, 21, -23, 21, 56, 7, 112, +-9, 85, -14, -1, -5, -77, 0, -73, +9, -8, 11, 65, -3, 87, 2, 52, +17, 12, 19, -8, 3, -4, -20, -4, +-24, -13, -7, -5, 29, 29, 35, 61, +15, 45, -10, -1, -23, -42, -6, -39, +12, 5, 14, 34, -6, 24, -15, -12, +2, -28, 27, -15, 31, 8, -1, 7, +-39, -17, -41, -35, 7, -34, 54, -15, +57, -7, 14, -17, -41, -29, -50, -23, +-12, -9, 31, -4, 40, -13, 21, -32, +-2, -36, -22, -16, -15, 0, -10, -4, +-4, -20, 22, -23, 35, -4, 29, 19, +-1, 16, -28, -17, -39, -43, -11, -35, +36, 13, 40, 52, 29, 48, 6, 15, +-16, -14, -21, -11, -22, 3, -12, 12, +3, 6, 39, 19, 58, 58, 20, 84, +-28, 55, -70, -17, -49, -74, 23, -53, +70, 35, 74, 104, 7, 106, -49, 40, +-59, -34, -24, -60, 29, -38, 37, 7, +37, 36, 20, 48, -1, 40, -19, 9, +-37, -36, -23, -63, 6, -39, 52, 13, +55, 43, 10, 22, -33, -35, -54, -68, +-23, -46, 28, 0, 51, 21, 27, -3, +-3, -44, -11, -57, -15, -40, 5, -21, +13, -15, 7, -12, 1, -3, 3, 0, +6, -17, 3, -50, 15, -57, 14, -24, +3, 26, -7, 40, -21, 3, -5, -44, +15, -38, 36, 11, 27, 50, -7, 37, +-26, -13, -36, -38, -7, -6, 20, 50, +31, 73, 29, 44, 6, -4, 2, -35, +-16, -14, -24, 29, -17, 55, 2, 56, +44, 37, 43, 17, 24, 2, -15, 3, +-49, 14, -41, 25, -13, 24, 35, 11, +57, 1, 55, 14, 18, 30, -38, 20, +-60, -10, -47, -39, 5, -28, 58, 9, +73, 30, 33, 16, -28, -23, -50, -42, +-39, -28, -3, -11, 33, -13, 33, -27, +27, -31, 19, -11, -1, -2, -22, -30, +-31, -66, -18, -58, 14, -6, 55, 39, +52, 27, 6, -46, -38, -98, -45, -78, +-15, -3, 24, 60, 46, 51, 29, 1, +2, -41, -12, -44, -24, -21, -26, -5, +-9, 4, 25, 19, 50, 42, 52, 47, +5, 24, -54, -14, -66, -30, -20, -10, +48, 27, 77, 47, 44, 46, -20, 41, +-60, 44, -47, 38, -7, 9, 28, -30, +47, -42, 37, 6, 17, 76, -9, 105, +-40, 58, -40, -31, -6, -79, 38, -49, +64, 24, 36, 75, -23, 61, -59, -1, +-32, -45, 17, -46, 44, -20, 41, 9, +-1, 21, -23, 9, -11, -18, 8, -49, +10, -62, -4, -41, 10, 10, 13, 50, +19, 24, 14, -52, -18, -119, -22, -98, +-5, -1, 33, 83, 36, 81, 2, -16, +-22, -114, -39, -123, 0, -39, 40, 65, +43, 97, 20, 44, -29, -43, -41, -94, +-28, -78, 18, -12, 53, 67, 48, 108, +17, 86, -41, -1, -61, -90, -37, -110, +20, -30, 77, 98, 67, 164, 13, 106, +-53, -20, -65, -103, -23, -75, 22, 23, +56, 85, 36, 76, 7, 34, -3, 19, +-10, 34, -21, 21, -30, -36, -10, -78, +19, -38, 59, 66, 56, 132, 6, 80, +-42, -41, -57, -109, -20, -69, 25, 14, +53, 49, 40, 9, 0, -24, -15, -2, +-9, 27, 5, 12, -5, -57, -14, -103, +-4, -63, 25, 29, 56, 82, 33, 33, +-9, -58, -46, -96, -47, -54, 5, 11, +44, 30, 57, 1, 27, -30, -5, -29, +-23, -7, -37, 2, -12, -12, 12, -16, +38, 7, 48, 22, 25, 3, -8, -31, +-35, -37, -27, 10, 4, 56, 39, 48, +49, -8, 15, -48, -6, -27, -18, 47, +-19, 90, -2, 47, 10, -36, 26, -71, +32, -12, 24, 76, -1, 100, -32, 42, +-35, -39, 0, -63, 47, -13, 62, 51, +19, 62, -36, 15, -43, -28, -7, -19, +45, 13, 58, 28, 18, 6, -34, -24, +-38, -31, 10, -9, 43, 13, 41, 11, +9, 0, -26, 0, -16, -5, 12, -20, +23, -49, 11, -56, 1, -16, 8, 50, +15, 75, 19, 16, 3, -81, -15, -125, +-2, -69, 21, 44, 30, 105, 15, 61, +-8, -38, -11, -96, 10, -67, 34, 0, +26, 43, -3, 35, -20, 9, -7, -5, +28, -14, 45, -22, 18, -21, -8, 3, +-14, 50, -4, 64, 19, 10, 22, -63, +11, -73, 14, 1, 27, 102, 24, 116, +-3, 15, -23, -95, -22, -105, 13, -1, +56, 106, 60, 110, 18, 24, -38, -61, +-47, -67, -16, -7, 29, 43, 67, 40, +46, 14, 9, -3, -22, -7, -29, -16, +-7, -33, 21, -30, 54, 5, 49, 50, +22, 50, -13, -11, -42, -80, -21, -93, +21, -28, 64, 58, 72, 86, 30, 41, +-29, -43, -63, -97, -36, -81, 22, -16, +76, 47, 84, 63, 31, 38, -34, -3, +-67, -38, -35, -56, 23, -43, 67, -15, +70, 21, 25, 54, -12, 55, -32, 22, +-17, -34, 11, -65, 26, -46, 28, 11, +27, 58, 28, 64, 10, 32, -4, -11, +-11, -36, -4, -35, 18, -11, 31, 25, +30, 58, 11, 65, 6, 23, 7, -41, +3, -76, 7, -42, 7, 40, 24, 95, +35, 74, 31, -19, 16, -95, -10, -77, +-11, 12, 2, 84, 30, 66, 38, -6, +18, -62, 16, -50, 12, 8, 15, 35, +2, 13, -14, -29, -3, -32, 24, 7, +64, 34, 59, 16, 8, -31, -39, -53, +-49, -25, 6, 13, 66, 29, 78, 8, +41, -16, -14, -12, -29, -4, -14, -3, +13, -17, 27, -16, 29, 6, 42, 31, +40, 30, 16, -6, -22, -36, -36, -29, +-5, 11, 50, 44, 76, 35, 47, -6, +-15, -30, -39, -17, -13, 22, 35, 41, +60, 26, 36, -7, 5, -31, 0, -18, +9, 12, 21, 27, 13, 33, 10, 23, +26, 7, 43, -16, 42, -39, -4, -34, +-34, 1, -14, 60, 40, 83, 82, 33, +57, -57, -1, -117, -37, -77, -18, 39, +31, 121, 55, 93, 39, -14, 5, -102, +1, -99, 25, -23, 33, 51, 13, 60, +-11, 26, -4, -8, 36, -27, 62, -35, +45, -44, -3, -34, -23, 7, 1, 58, +36, 61, 49, 0, 23, -65, -6, -74, +3, -17, 36, 50, 44, 59, 25, 4, +-5, -38, -8, -29, 20, 8, 56, 25, +50, 6, 10, -20, -16, -10, -6, 22, +28, 39, 51, 15, 46, -22, 17, -27, +-7, 3, -2, 36, 12, 31, 31, -2, +44, -21, 41, -8, 29, 19, 7, 29, +-14, 17, -13, -5, 19, -12, 63, -6, +67, 7, 35, 9, -8, 8, -31, 10, +-2, 4, 44, -7, 66, -18, 50, -20, +20, 0, -2, 23, -2, 24, 16, -3, +23, -35, 30, -46, 45, -17, 52, 30, +35, 53, -2, 23, -26, -42, -13, -83, +41, -57, 85, 21, 75, 79, 25, 62, +-25, -12, -32, -79, 0, -73, 48, -18, +66, 34, 51, 46, 35, 20, 19, -3, +4, -10, -7, -21, -3, -40, 21, -40, +64, -1, 86, 57, 47, 75, -7, 20, +-43, -51, -25, -69, 35, -13, 75, 54, +68, 56, 24, 4, -4, -31, -3, -10, +22, 29, 39, 34, 19, -9, 12, -49, +26, -17, 44, 50, 54, 68, 32, 16, +4, -58, -14, -67, 6, -2, 42, 63, +62, 60, 58, 3, 28, -41, -2, -37, +-11, -6, 6, 10, 33, 5, 55, 9, +57, 33, 35, 33, 5, -9, -12, -65, +-2, -72, 26, -4, 56, 77, 64, 83, +37, 7, 9, -78, -4, -90, 7, -24, +36, 46, 56, 56, 43, 13, 18, -31, +9, -36, 13, -14, 35, 2, 51, 2, +36, 0, 12, 7, -1, 13, 9, 0, +34, -21, 56, -25, 59, -5, 29, 26, +8, 25, 4, -6, 4, -30, 28, -31, +50, 2, 58, 34, 47, 40, 23, 13, +-3, -24, -14, -35, 14, -20, 48, 11, +68, 32, 61, 29, 23, 18, -13, 4, +-8, -12, 16, -21, 41, -27, 56, -10, +50, 26, 30, 61, 14, 56, 4, 0, +-3, -62, 19, -79, 53, -21, 69, 57, +58, 84, 16, 39, -26, -31, -20, -64, +37, -40, 82, 7, 79, 24, 33, 16, +-17, 7, -22, 13, 25, 10, 61, -14, +57, -49, 34, -46, 8, 12, 11, 63, +32, 57, 40, -7, 24, -69, 14, -63, +31, -5, 47, 45, 39, 47, 13, 4, +0, -31, 17, -26, 63, -7, 71, 2, +28, -7, -15, -8, -21, 10, 22, 29, +74, 23, 76, -9, 28, -36, -13, -28, +-8, 5, 23, 29, 48, 24, 46, 4, +28, -8, 27, 2, 40, 6, 37, -12, +8, -31, -10, -21, 9, 23, 54, 67, +89, 56, 63, -9, -5, -72, -39, -75, +-8, -11, 49, 68, 85, 88, 66, 41, +11, -30, -3, -68, 16, -47, 31, 3, +32, 32, 29, 32, 28, 26, 39, 16, +51, -7, 34, -35, 6, -43, 7, -13, +23, 36, 45, 49, 51, 8, 32, -41, +20, -48, 35, 0, 43, 54, 27, 34, +9, -34, 3, -70, 27, -32, 65, 47, +73, 71, 40, 15, -5, -58, -17, -60, +4, 1, 39, 49, 66, 29, 63, -30, +38, -42, 18, 0, 3, 41, -9, 28, +5, -26, 41, -49, 73, -13, 79, 37, +43, 37, -18, -8, -33, -47, 10, -27, +55, 30, 73, 43, 58, 1, 22, -39, +7, -30, 22, 12, 25, 32, 17, 6, +11, -22, 28, -13, 61, 23, 73, 36, +47, -5, -1, -51, -21, -41, 1, 16, +42, 57, 72, 39, 64, -12, 32, -36, +11, -17, 7, 14, 4, 16, 11, -8, +37, -10, 48, 25, 57, 41, 46, 20, +7, -22, -16, -43, 0, -15, 35, 26, +63, 25, 58, 3, 35, -17, 10, 4, +6, 33, 21, 21, 26, -26, 29, -62, +37, -43, 43, 19, 41, 67, 32, 63, +10, 14, 0, -39, 12, -63, 36, -59, +51, -23, 49, 34, 34, 76, 16, 74, +7, 11, 10, -72, 18, -103, 35, -55, +48, 35, 48, 83, 37, 58, 22, -6, +1, -46, 5, -48, 31, -28, 44, -1, +40, 23, 29, 38, 20, 39, 14, 8, +26, -43, 25, -60, 20, -26, 29, 38, +37, 71, 39, 38, 33, -27, 16, -59, +4, -33, 19, 11, 42, 41, 41, 35, +33, 8, 20, -2, 14, -5, 23, -11, +36, -24, 33, -18, 17, 15, 16, 47, +28, 46, 40, 9, 39, -30, 24, -43, +6, -19, 13, 13, 34, 29, 44, 23, +39, 9, 26, -4, 15, -11, 20, -13, +40, -19, 41, -9, 17, 9, 4, 15, +8, 16, 30, 7, 64, -7, 61, -11, +19, -12, -13, -17, -16, -18, 18, -7, +60, 14, 71, 30, 44, 18, 7, -11, +-9, -35, 3, -42, 29, -20, 39, 15, +36, 26, 43, 11, 48, -7, 40, -17, +15, -18, -17, -13, -14, -13, 21, -7, +77, 7, 93, 22, 52, 18, -13, -2, +-50, -26, -17, -32, 48, -9, 90, 21, +71, 31, 21, 13, -11, -8, -13, -13, +14, -2, 33, 8, 34, 7, 36, -3, +43, 2, 42, 13, 22, 18, -7, 9, +-14, -8, 13, -10, 51, 5, 68, 13, +44, 4, 5, -6, -8, -1, 8, 18, +30, 29, 41, 2, 34, -39, 19, -41, +26, -6, 36, 44, 24, 58, 7, 17, +2, -38, 12, -51, 33, -20, 48, 12, +37, 24, 12, 19, 7, 3, 25, -9, +34, -17, 29, -30, 8, -27, -3, -5, +22, 25, 50, 34, 58, 15, 23, -14, +-13, -40, -18, -39, 11, -18, 44, 11, +61, 25, 51, 30, 22, 18, 0, -14, +-7, -51, 0, -57, 12, -15, 42, 41, +65, 72, 61, 45, 24, -20, -21, -68, +-39, -59, -9, -8, 54, 44, 89, 62, +68, 42, 15, 0, -34, -35, -36, -46, +2, -27, 48, 14, 68, 50, 58, 59, +25, 27, -6, -23, -22, -47, -15, -33, +21, 6, 53, 43, 68, 44, 45, 19, +1, -10, -29, -26, -13, -26, 23, -6, +54, 15, 54, 22, 24, 15, 3, -2, +-2, -15, 14, -19, 27, 0, 17, 15, +10, 12, 19, -9, 39, -26, 39, -19, +21, 4, -4, 20, -11, 15, 10, -7, +41, -25, 49, -25, 26, -9, 6, 6, +1, 6, 16, 0, 27, -4, 26, -3, +2, 6, 4, -1, 28, -15, 43, -23, +45, -14, 13, 12, -19, 27, -17, 19, +15, -6, 48, -20, 57, -15, 33, 9, +-5, 18, -21, 5, -4, -11, 23, -1, +39, 19, 41, 30, 23, 13, 5, -25, +11, -38, 19, -12, 19, 32, 10, 45, +16, 17, 20, -24, 36, -32, 37, -6, +16, 22, -4, 26, -3, 6, 13, -5, +24, -3, 34, -6, 27, -11, 14, -11, +18, 6, 27, 28, 19, 26, -4, -6, +-10, -45, 3, -46, 36, -9, 74, 29, +55, 40, 5, 16, -40, -15, -43, -29, +-6, -29, 53, -26, 76, -16, 66, 10, +16, 50, -28, 52, -44, 0, -33, -65, +13, -83, 57, -29, 84, 49, 63, 82, +3, 42, -57, -32, -59, -66, -13, -41, +52, 6, 94, 26, 73, 21, 11, 9, +-34, 4, -51, 2, -15, -20, 30, -29, +61, -10, 58, 28, 39, 44, 4, 15, +-18, -33, -25, -51, -7, -13, 31, 41, +48, 62, 52, 23, 26, -29, -10, -48, +-21, -27, -5, 17, 13, 43, 34, 37, +31, 14, 17, -10, 7, -28, 6, -24, +6, 2, 8, 29, 3, 37, 3, 14, +13, -25, 20, -34, 31, -12, 31, 24, +6, 32, -3, 2, -13, -31, 5, -40, +27, -9, 38, 20, 33, 26, 8, 6, +-3, -14, -12, -15, 3, -11, 15, -14, +33, -12, 19, 1, 16, 16, 14, 21, +6, -1, 2, -25, 2, -29, 5, -8, +19, 14, 39, 13, 30, -3, 7, -14, +-18, 3, -27, 22, 6, 14, 38, -7, +51, -23, 28, -15, -18, 15, -27, 23, +-13, 10, 23, -6, 48, -6, 42, 9, +-3, 19, -13, -1, -12, -23, 8, -17, +26, 14, 21, 40, 7, 30, 10, -5, +22, -29, 19, -21, 5, 3, -17, 13, +-13, 8, 11, 6, 46, 18, 52, 19, +15, -4, -24, -37, -33, -45, -15, -2, +33, 48, 51, 59, 28, 13, -1, -48, +-2, -66, -1, -27, 17, 23, 10, 36, +-1, 16, -2, -8, 27, -11, 45, -5, +30, -17, -7, -34, -35, -30, -23, 15, +12, 59, 60, 48, 44, -14, 11, -71, +-17, -64, -24, -4, 0, 50, 25, 50, +20, 11, 12, -22, 13, -21, 19, -7, +8, -2, -1, -18, -13, -12, -3, 22, +12, 55, 29, 44, 23, -15, 4, -58, +-2, -49, 1, 4, 9, 44, 15, 42, +9, 11, -4, -13, 17, -12, 20, -5, +24, -12, 9, -15, -10, 3, -18, 35, +-1, 40, 25, 8, 33, -32, 25, -44, +6, -9, -2, 27, -10, 34, -10, 9, +9, -21, 13, -18, 28, 3, 33, 9, +16, -1, -8, -14, -16, -10, -19, 12, +-1, 14, 35, -3, 34, -14, 34, -12, +-1, 7, -16, 10, -27, -9, -9, -26, +23, -10, 36, 23, 32, 34, 16, 8, +-10, -36, -22, -53, -2, -21, 12, 27, +20, 50, 19, 32, 10, -9, 2, -30, +1, -27, 4, -12, -3, 6, -9, 20, +4, 25, 27, 20, 36, 6, 16, -12, +-5, -26, -38, -22, -12, -4, 19, 17, +40, 32, 31, 34, 2, 23, -29, -1, +-19, -29, 15, -45, 26, -25, 20, 18, +-3, 53, -6, 57, 7, 24, 22, -16, +15, -45, -12, -51, -23, -32, 3, 7, +34, 55, 43, 81, 21, 50, -27, -27, +-45, -98, -5, -96, 30, -17, 54, 82, +22, 116, -12, 47, -24, -55, -2, -101, +21, -67, 26, 3, 10, 55, -7, 58, +2, 26, 11, -13, 31, -42, 10, -51, +-10, -36, -9, 7, 8, 51, 18, 58, +24, 16, 11, -48, 0, -77, 8, -36, +10, 28, 6, 60, -2, 37, -6, -11, +9, -33, 20, -22, 34, -1, 18, 7, +-11, 3, -23, 5, -11, 15, 10, 12, +30, -2, 43, -18, 14, -10, 1, 12, +-15, 23, -24, 6, -10, -30, 26, -32, +40, 12, 34, 59, 10, 51, -22, -2, +-29, -61, -9, -64, 26, -11, 36, 45, +22, 55, 12, 23, -5, -12, -4, -22, +2, -15, -1, -18, -5, -23, 13, -11, +27, 23, 28, 50, 23, 35, -9, -17, +-17, -63, -12, -56, 15, -1, 17, 48, +18, 44, 10, 3, 9, -25, 0, -15, +5, 5, 1, 10, -17, -11, -3, -27, +17, -14, 27, 26, 30, 43, 18, 17, +-14, -23, -22, -41, -14, -20, 1, 14, +23, 28, 36, 13, 35, -6, 15, -5, +-19, 7, -28, 3, -27, -13, 14, -22, +46, -2, 48, 30, 16, 39, -16, 16, +-40, -23, -22, -36, 22, -16, 32, 22, +24, 42, 2, 31, -11, 5, -3, -21, +14, -30, 8, -19, -8, 6, -15, 33, +10, 44, 34, 29, 29, -9, 8, -51, +-22, -57, -29, -14, 7, 45, 30, 74, +27, 46, 5, -17, -12, -62, -13, -58, +17, -10, 22, 35, 11, 48, -13, 35, +-17, -2, 12, -25, 24, -31, 27, -19, +-5, 5, -28, 28, -19, 32, 22, 12, +33, -15, 25, -33, -3, -19, -31, 18, +-14, 39, 21, 24, 32, -11, 20, -37, +-5, -27, -19, 13, -14, 46, 10, 35, +21, 0, 20, -32, 9, -30, 4, 3, +-7, 32, -17, 31, -6, 7, 4, -16, +24, -10, 30, 13, 22, 19, -13, 11, +-26, -7, -26, -12, 0, 1, 29, 18, +40, 20, 32, 5, -2, 0, -29, 3, +-40, 8, -23, 4, 16, -5, 50, -4, +45, 15, 11, 32, -31, 25, -59, -4, +-29, -27, 25, -21, 49, 15, 45, 39, +0, 28, -30, -16, -29, -35, -4, -12, +20, 25, 23, 44, 8, 18, -2, -20, +-13, -31, -4, -12, 8, 24, 0, 42, +4, 26, 6, -1, -2, -17, -10, -18, +-3, -7, -1, 8, 18, 23, 22, 38, +1, 28, -22, 1, -29, -31, -13, -32, +11, 3, 35, 36, 36, 46, 3, 23, +-26, -12, -34, -29, -20, -12, -6, 22, +24, 33, 33, 21, 19, 10, -4, 7, +-36, 9, -46, 2, -18, -7, 19, 0, +43, 13, 42, 31, -6, 31, -41, 2, +-43, -20, -11, -11, 24, 19, 29, 35, +10, 19, -11, -14, -20, -16, -11, 18, +4, 46, -5, 40, -12, -9, 0, -50, +5, -30, 17, 29, 2, 73, -24, 57, +-32, 2, -21, -36, 3, -25, 13, 10, +12, 27, -4, 19, -14, 11, -18, 22, +-11, 36, -11, 21, -11, -18, -4, -40, +4, -20, 11, 36, 6, 72, -20, 56, +-40, 2, -31, -37, -10, -28, 23, 3, +31, 33, 5, 36, -26, 21, -45, 11, +-31, 10, -2, 5, 17, -3, 18, -3, +-1, 11, -27, 35, -38, 42, -25, 22, +-9, -7, 14, -16, 13, -1, -5, 23, +-23, 35, -31, 25, -24, 15, -10, 7, +4, 6, 1, 7, -7, 6, -16, 10, +-18, 21, -20, 30, -22, 26, -13, 9, +-8, 0, -5, 8, -4, 19, -21, 24, +-33, 16, -28, 5, -14, 10, 2, 27, +6, 37, -18, 25, -35, -8, -33, -28, +-11, -14, 6, 32, -2, 66, -17, 54, +-39, 12, -38, -27, -14, -31, 7, -1, +4, 32, -11, 44, -38, 33, -47, 20, +-35, 19, -11, 10, 6, 0, 0, -6, +-15, -3, -37, 21, -46, 47, -37, 48, +-21, 26, -3, -1, -2, -4, -11, 7, +-33, 19, -48, 19, -43, 9, -23, 11, +-1, 39, 1, 55, -13, 37, -37, -10, +-42, -46, -44, -29, -21, 24, -7, 77, +-6, 81, -15, 36, -31, -20, -44, -42, +-46, -26, -34, 19, -17, 53, 0, 65, +-12, 56, -31, 20, -57, -17, -58, -39, +-32, -16, -8, 34, 2, 79, -19, 78, +-46, 21, -56, -35, -46, -44, -26, 1, +-18, 56, -18, 73, -31, 44, -36, 2, +-37, -20, -31, -11, -36, 14, -43, 33, +-36, 39, -23, 34, -15, 26, -25, 10, +-43, -5, -62, -6, -48, 12, -26, 39, +-16, 53, -24, 35, -42, 3, -57, -6, +-51, 8, -33, 33, -29, 42, -38, 24, +-47, 3, -46, 3, -34, 22, -30, 43, +-38, 44, -53, 14, -53, -5, -47, -1, +-34, 18, -30, 39, -41, 43, -49, 33, +-57, 24, -52, 21, -52, 13, -38, 1, +-38, 5, -38, 21, -41, 43, -54, 53, +-56, 33, -51, 3, -40, -11, -31, 2, +-44, 31, -63, 40, -63, 29, -54, 20, +-36, 23, -30, 37, -46, 31, -66, 10, +-73, -13, -56, -5, -41, 35, -34, 68, +-41, 62, -60, 23, -67, -14, -66, -19, +-55, 12, -59, 47, -51, 54, -45, 35, +-39, 15, -47, 15, -66, 18, -82, 17, +-82, 11, -52, 9, -32, 30, -26, 51, +-47, 50, -82, 28, -100, -2, -82, -15, +-47, 7, -31, 43, -34, 59, -59, 47, +-82, 17, -84, -2, -74, 6, -64, 26, +-55, 33, -48, 34, -59, 30, -64, 31, +-78, 32, -78, 23, -77, 13, -65, 10, +-57, 21, -59, 39, -63, 46, -77, 40, +-77, 22, -75, 8, -62, 4, -60, 12, +-67, 30, -71, 42, -75, 48, -74, 37, +-68, 14, -65, -5, -70, -1, -74, 28, +-77, 57, -83, 61, -73, 31, -71, 1, +-66, -2, -70, 23, -76, 48, -86, 43, +-88, 19, -81, 6, -68, 24, -60, 51, +-69, 55, -79, 17, -91, -20, -84, -13, +-77, 34, -65, 71, -74, 71, -83, 26, +-85, -12, -81, -5, -67, 21, -76, 44, +-89, 32, -97, 17, -90, 27, -70, 52, +-61, 59, -68, 24, -98, -19, -112, -28, +-101, 15, -76, 78, -66, 98, -68, 55, +-87, -9, -100, -37, -95, -5, -90, 44, +-83, 69, -86, 46, -78, 15, -86, 13, +-81, 27, -89, 42, -101, 36, -105, 12, +-95, 3, -78, 18, -71, 44, -79, 61, +-104, 53, -114, 23, -109, 6, -89, 2, +-71, 16, -74, 35, -84, 44, -108, 50, +-118, 43, -105, 24, -86, 12, -72, 7, +-71, 12, -85, 28, -117, 48, -122, 51, +-109, 40, -76, 22, -66, 10, -72, 5, +-100, 11, -124, 35, -123, 56, -98, 58, +-76, 38, -74, 9, -90, -7, -109, 2, +-112, 38, -110, 66, -100, 59, -92, 26, +-85, -2, -84, 0, -95, 26, -109, 47, +-123, 43, -118, 23, -91, 18, -74, 36, +-67, 44, -97, 36, -128, 5, -142, -16, +-111, 7, -75, 54, -57, 84, -80, 65, +-117, 12, -143, -27, -130, -21, -94, 24, +-68, 59, -71, 66, -100, 47, -123, 27, +-132, 19, -116, 16, -95, 6, -87, 4, +-85, 17, -94, 54, -111, 79, -125, 68, +-125, 19, -113, -25, -92, -24, -75, 21, +-84, 64, -105, 73, -135, 47, -132, 12, +-113, 1, -83, 20, -79, 38, -93, 33, +-113, 20, -125, 19, -117, 33, -108, 44, +-93, 40, -96, 23, -100, 14, -108, 24, +-116, 39, -120, 35, -110, 19, -100, 15, +-95, 32, -100, 57, -117, 61, -127, 29, +-118, -6, -96, -13, -80, 18, -95, 59, +-117, 67, -133, 43, -123, 11, -99, 5, +-81, 16, -92, 31, -120, 40, -135, 38, +-127, 35, -97, 33, -84, 27, -86, 12, +-110, 7, -119, 19, -123, 44, -113, 55, +-104, 42, -105, 21, -99, 0, -97, 10, +-104, 35, -117, 48, -127, 44, -121, 31, +-101, 20, -79, 13, -82, 16, -109, 20, +-137, 32, -139, 47, -113, 50, -78, 31, +-70, 8, -93, -4, -125, 10, -140, 40, +-123, 57, -97, 45, -75, 17, -84, 7, +-104, 19, -130, 36, -133, 38, -117, 20, +-92, 9, -75, 22, -79, 48, -110, 57, +-137, 27, -131, -10, -115, -6, -88, 30, +-70, 60, -85, 59, -118, 25, -140, 0, +-135, 9, -109, 38, -80, 50, -70, 29, +-90, 3, -119, 6, -136, 40, -130, 65, +-116, 56, -89, 10, -71, -27, -73, -8, +-99, 42, -133, 78, -151, 58, -128, 10, +-84, -17, -54, 3, -59, 35, -102, 52, +-152, 40, -160, 15, -117, 12, -67, 28, +-49, 39, -72, 26, -120, 10, -149, 8, +-133, 27, -99, 52, -76, 48, -72, 20, +-87, -4, -107, -7, -115, 22, -121, 52, +-112, 53, -95, 29, -77, 6, -79, 3, +-92, 14, -116, 33, -128, 43, -115, 33, +-85, 19, -67, 14, -81, 17, -105, 28, +-127, 34, -118, 28, -98, 19, -74, 14, +-76, 20, -93, 31, -111, 41, -119, 33, +-111, 19, -100, 11, -85, 15, -78, 30, +-90, 45, -103, 36, -117, 19, -116, 9, +-97, 14, -75, 31, -75, 36, -88, 27, +-110, 12, -120, 14, -104, 30, -81, 41, +-74, 33, -84, 7, -100, -5, -113, 11, +-101, 42, -93, 62, -87, 43, -90, 4, +-94, -11, -93, 6, -92, 39, -93, 51, +-100, 32, -100, 5, -92, 8, -80, 33, +-81, 52, -96, 38, -106, -3, -102, -27, +-84, 1, -74, 55, -75, 80, -95, 54, +-105, -2, -103, -29, -90, -13, -73, 27, +-77, 54, -92, 53, -105, 33, -96, 20, +-85, 18, -78, 13, -80, 1, -89, -4, +-96, 15, -95, 53, -87, 70, -81, 48, +-76, 0, -82, -29, -92, -16, -96, 24, +-93, 55, -80, 56, -71, 31, -69, 10, +-81, 0, -97, 5, -104, 15, -96, 27, +-80, 36, -66, 40, -66, 34, -85, 16, +-93, 1, -99, 0, -87, 17, -80, 35, +-71, 37, -71, 26, -72, 11, -79, 12, +-91, 15, -94, 16, -93, 18, -75, 21, +-59, 25, -52, 28, -72, 22, -102, 12, +-112, 3, -90, 11, -60, 31, -47, 39, +-58, 26, -89, 7, -107, 2, -95, 14, +-69, 30, -55, 31, -58, 13, -74, 3, +-89, 12, -86, 30, -80, 39, -74, 25, +-76, 4, -70, -2, -64, 15, -68, 32, +-75, 34, -91, 19, -89, 4, -73, 15, +-59, 33, -54, 33, -70, 15, -88, -7, +-94, 1, -87, 31, -63, 49, -49, 42, +-57, 14, -71, -14, -83, -11, -88, 9, +-73, 33, -66, 40, -54, 29, -60, 23, +-66, 13, -76, 5, -83, -2, -73, -1, +-67, 17, -57, 39, -61, 50, -67, 36, +-77, 4, -69, -18, -68, -10, -60, 11, +-62, 38, -72, 44, -66, 26, -61, 6, +-53, -3, -61, 4, -73, 12, -77, 19, +-70, 23, -55, 21, -46, 22, -57, 17, +-76, 11, -78, 4, -67, 3, -51, 20, +-55, 33, -61, 28, -71, 13, -73, 0, +-60, 1, -52, 18, -55, 28, -62, 23, +-62, 6, -66, 1, -55, 4, -54, 17, +-57, 25, -61, 19, -63, 12, -59, 7, +-56, 11, -56, 15, -56, 14, -63, 17, +-61, 15, -53, 13, -53, 12, -51, 9, +-61, 12, -64, 16, -64, 20, -58, 22, +-55, 16, -50, 8, -52, 7, -55, 12, +-65, 19, -62, 17, -57, 15, -50, 12, +-40, 13, -49, 14, -58, 10, -66, 3, +-61, 8, -53, 25, -48, 36, -51, 28, +-57, 6, -60, -14, -51, -8, -44, 19, +-51, 40, -54, 34, -62, 7, -52, -12, +-38, -9, -38, 16, -50, 29, -61, 17, +-62, 1, -47, -2, -33, 13, -39, 30, +-52, 23, -66, -2, -55, -14, -43, 1, +-33, 27, -41, 37, -60, 22, -67, -2, +-59, -8, -33, 4, -24, 24, -37, 26, +-62, 11, -69, -5, -60, -2, -29, 17, +-25, 33, -32, 21, -50, -4, -66, -14, +-61, -2, -46, 23, -33, 42, -33, 32, +-40, 3, -48, -18, -50, -12, -56, 11, +-44, 32, -42, 35, -37, 17, -35, -2, +-42, -9, -39, -5, -41, 9, -45, 20, +-46, 17, -47, 13, -43, 9, -31, 12, +-37, 16, -37, 11, -54, 6, -60, -1, +-45, 6, -33, 21, -18, 27, -28, 21, +-49, 3, -62, -12, -52, -8, -32, 9, +-13, 25, -29, 27, -45, 14, -57, -2, +-50, 0, -33, 11, -27, 14, -28, 7, +-42, -1, -45, 6, -44, 26, -33, 30, +-31, 15, -34, -13, -42, -26, -38, -5, +-33, 30, -28, 49, -29, 35, -46, -3, +-44, -34, -41, -24, -29, 9, -21, 40, +-26, 43, -34, 14, -39, -11, -42, -20, +-36, -6, -25, 7, -28, 20, -27, 23, +-31, 14, -29, 13, -37, 11, -34, -6, +-33, -16, -28, -12, -26, 10, -24, 39, +-29, 42, -33, 19, -39, -13, -45, -29, +-32, -13, -25, 19, -12, 40, -16, 32, +-31, 8, -52, -9, -51, -11, -35, 2, +-2, 11, 3, 14, -11, 6, -36, 2, +-58, 1, -39, 4, -20, 7, 1, 8, +-10, 12, -32, 7, -45, 7, -45, 8, +-26, 3, -9, 3, -14, 6, -23, 7, +-22, 8, -30, 9, -19, 6, -28, 0, +-29, -2, -32, 4, -18, 11, -7, 20, +-8, 19, -30, 7, -41, -12, -47, -8, +-35, 9, 0, 24, 3, 28, -5, 14, +-34, -8, -47, -18, -41, -6, -15, 11, +7, 23, 9, 19, -18, 9, -42, -1, +-48, -5, -35, 2, -3, 8, 2, 13, +1, 16, -24, 13, -36, 4, -31, -6, +-17, -10, -6, 0, -7, 14, -15, 24, +-23, 19, -17, 0, -15, -11, -12, -7, +-23, 1, -18, 13, -20, 17, -10, 14, +-6, 11, -14, 8, -25, 5, -29, 0, +-24, -2, -7, -1, 4, 10, -8, 20, +-14, 17, -25, -1, -14, -12, -7, -10, +-8, 8, -11, 19, -16, 14, -17, 5, +-12, -1, -8, 4, -13, 17, -18, 18, +-22, 5, -11, -7, -5, -10, 4, 4, +-5, 19, -23, 24, -21, 7, -17, -3, +-5, -3, 5, 4, -2, 13, -14, 8, +-19, 3, -28, 5, -5, 9, 1, 19, +7, 17, -4, 2, -19, -13, -20, -13, +-16, 5, -6, 29, 0, 38, -1, 18, +-4, -11, -8, -23, -15, -14, -5, 11, +-13, 33, -9, 28, -3, 8, -2, -8, +9, -10, 1, 0, -10, 10, -21, 9, +-20, 7, -4, 7, 22, 13, 16, 18, +2, 8, -27, -9, -35, -17, -11, -4, +15, 22, 31, 42, 10, 28, -14, -7, +-31, -31, -16, -29, 4, 9, 21, 41, +13, 39, 2, 12, -15, -16, -16, -22, +4, -9, 8, 12, 10, 20, 0, 10, +-1, 2, 1, 7, 6, 14, 5, 10, +1, -5, -13, -15, -4, -11, 6, 17, +13, 41, 17, 36, -1, 5, -8, -30, +-9, -35, -2, -2, 12, 31, 20, 40, +14, 20, 3, -6, -11, -16, -4, -7, +4, 10, 8, 13, 19, 2, 5, 1, +6, 9, 4, 20, 9, 14, 10, -4, +5, -19, -3, -14, 6, 7, 14, 28, +22, 31, 18, 7, 2, -16, -4, -18, +-10, -1, 11, 19, 23, 21, 26, 9, +14, -3, -2, -2, -7, 6, 2, 15, +14, 8, 20, -1, 20, -9, 11, -2, +11, 14, 3, 22, 3, 22, 2, 2, +11, -17, 22, -15, 24, 3, 19, 22, +6, 31, -8, 17, -4, -4, 13, -12, +23, -7, 35, 8, 17, 14, 5, 13, +-4, 8, 0, 5, 19, 5, 30, 2, +25, -2, 16, -4, 2, 4, -1, 18, +10, 26, 18, 13, 30, -6, 17, -15, +11, -10, 8, 13, 7, 29, 18, 23, +21, 3, 19, -16, 15, -14, 16, -2, +18, 17, 21, 24, 15, 12, 12, 1, +5, -6, 14, -3, 27, 1, 35, 3, +28, 7, 12, 8, 0, 8, 8, 3, +22, 0, 31, -4, 39, -3, 16, 11, +2, 21, -2, 15, 16, -1, 33, -11, +34, -5, 23, 9, 10, 18, 9, 14, +14, 5, 22, -1, 20, -2, 23, 3, +11, 13, 19, 14, 22, 13, 19, 8, +22, -2, 15, -7, 21, -8, 25, 1, +32, 9, 32, 17, 17, 21, 7, 3, +18, -15, 21, -16, 30, -2, 32, 13, +27, 21, 22, 19, 7, 7, 15, -12, +27, -17, 32, -5, 34, 8, 28, 16, +18, 12, 16, 7, 11, 3, 22, -2, +29, -2, 29, 0, 31, 1, 24, 5, +17, 12, 13, 14, 14, 7, 25, -2, +34, -6, 35, -6, 33, 3, 14, 14, +9, 15, 13, 8, 22, -1, 37, -3, +33, 1, 26, 9, 16, 13, 13, 4, +18, 1, 25, -1, 32, -1, 36, 8, +26, 10, 19, 6, 21, -3, 20, -3, +27, 8, 23, 11, 32, 2, 31, -3, +28, -7, 28, 2, 25, 14, 17, 13, +19, 6, 24, -9, 33, -9, 41, 2, +33, 12, 28, 11, 12, 2, 12, -5, +23, -3, 37, 6, 40, 16, 35, 10, +17, -5, 16, -16, 22, -10, 29, 11, +40, 20, 37, 12, 27, 0, 14, -11, +16, -8, 24, 5, 34, 11, 33, 14, +29, 3, 23, -2, 25, -1, 29, 1, +29, 1, 33, -7, 25, -3, 23, 1, +33, 6, 32, 16, 31, 10, 29, -8, +24, -13, 20, -11, 27, 0, 35, 12, +41, 15, 32, 11, 25, -3, 15, -12, +21, -9, 30, -2, 40, 12, 34, 18, +26, 8, 21, -1, 20, -4, 28, -6, +41, -7, 36, 0, 29, 5, 30, 4, +24, 11, 27, 7, 31, -8, 32, -12, +32, -9, 30, 4, 27, 18, 27, 15, +28, 1, 37, -18, 37, -21, 32, -6, +28, 9, 25, 16, 31, 10, 33, -3, +37, -15, 36, -12, 24, -3, 22, 9, +24, 8, 34, 2, 38, 1, 37, -2, +24, 4, 21, -4, 21, -6, 30, -7, +42, 0, 37, 15, 32, 12, 25, -4, +23, -14, 27, -12, 33, 0, 39, 9, +36, 9, 26, 0, 27, -9, 24, -1, +31, -2, 42, 0, 33, -1, 33, -5, +26, -3, 28, 1, 31, 4, 37, 2, +36, -4, 33, -2, 20, 1, 26, -3, +34, 2, 36, 1, 40, 1, 31, -3, +25, -5, 21, 4, 29, 3, 44, -2, +43, -1, 30, -9, 23, -3, 14, 7, +27, 8, 42, 7, 44, -5, 35, -9, +25, -8, 18, -3, 28, 6, 34, 8, +47, -3, 42, -3, 29, -11, 24, -10, +24, -3, 33, 1, 45, 7, 39, 3, +29, -3, 19, -6, 18, -6, 36, 0, +43, 4, 45, 0, 30, -1, 23, -9, +23, -7, 36, -3, 39, 0, 45, 1, +31, 0, 21, 6, 14, -2, 34, -11, +43, -10, 51, -1, 37, 6, 22, 10, +13, -6, 27, -11, 36, -7, 49, 5, +39, 11, 29, 1, 18, -5, 24, -15, +40, -8, 48, -1, 46, 0, 36, -1, +22, -1, 23, -2, 30, 2, 39, -7, +45, -6, 34, -2, 27, 0, 27, 6, +29, 1, 37, 0, 43, -7, 32, -9, +32, -8, 27, -7, 38, -1, 41, 11, +36, 8, 28, -2, 24, -13, 21, -15, +38, 0, 48, 1, 47, 8, 36, -1, +18, -5, 16, -2, 27, -3, 43, -6, +57, -10, 46, -8, 29, 0, 21, 6, +12, 4, 38, -6, 52, -15, 49, -4, +36, -2, 18, 3, 15, 2, 35, -2, +43, 0, 53, -5, 41, -11, 26, -10, +25, -5, 26, 5, 41, 4, 52, -8, +44, -8, 36, -10, 29, -3, 25, 1, +36, -6, 44, -8, 44, -3, 43, -2, +26, 7, 27, -5, 39, -16, 44, -6, +40, 1, 31, 9, 24, -2, 29, -4, +39, -6, 50, -4, 46, -2, 28, -2, +23, -7, 23, 2, 38, -1, 57, -5, +51, -6, 36, -8, 17, 5, 15, 0, +33, -1, 50, -8, 54, -7, 43, 4, +21, 5, 18, -5, 30, -8, 41, -9, +55, -3, 49, 0, 34, -6, 25, -7, +31, -12, 39, 1, 51, 1, 42, -6, +41, -14, 31, -14, 34, -4, 40, 6, +48, -2, 42, -6, 36, -6, 23, -8, +31, 1, 36, -6, 51, -4, 53, -5, +40, 2, 21, 1, 22, -7, 31, -13, +52, -6, 55, 3, 40, 8, 27, 0, +21, -10, 32, -6, 50, -9, 54, -2, +44, -8, 32, -5, 23, 1, 34, 4, +45, -2, 49, -10, 45, -14, 34, -5, +26, 6, 30, 6, 37, -1, 50, -12, +43, 0, 39, -6, 37, -4, 32, -8, +38, -10, 45, -1, 41, 4, 41, -3, +37, -7, 32, -12, 46, -7, 40, 4, +44, -3, 32, 0, 26, -7, 29, 0, +43, 1, 45, -2, 54, -8, 37, -9, +27, -3, 23, -1, 34, -6, 51, -8, +60, -3, 44, -2, 32, 3, 13, -8, +28, -9, 46, -6, 57, 1, 54, 3, +36, -6, 23, -14, 28, -4, 34, 4, +50, 0, 55, -9, 41, -16, 35, -3, +26, 4, 31, 9, 43, -9, 49, -16, +43, -7, 39, 2, 31, 4, 33, 1, +36, -9, 43, -8, 46, -4, 42, -7, +35, -3, 36, -9, 41, 1, 44, 1, +41, -1, 31, -9, 35, -15, 39, -4, +43, 8, 44, 3, 41, -7, 31, -10, +28, -2, 29, 7, 48, -6, 51, -8, +45, -12, 31, 3, 22, 10, 28, 0, +48, -13, 52, -16, 51, -10, 38, 3, +24, 4, 27, -1, 35, -4, 49, -10, +49, 0, 38, -5, 31, -2, 32, -4, +33, 1, 39, 2, 39, -5, 39, -9, +40, -2, 32, 6, 33, 3, 39, -7, +40, -16, 44, -3, 38, -2, 39, 2, +41, -9, 38, -9, 41, -3, 46, -5, +43, -7, 35, -7, 33, -12, 41, -1, +44, 10, 41, 0, 36, -4, 29, -17, +31, -5, 44, 1, 46, 7, 42, 0, +39, -13, 29, -9, 32, -3, 41, -3, +45, -3, 45, -1, 35, 0, 32, 3, +34, -12, 42, -15, 44, -12, 43, 5, +37, 8, 39, 4, 31, -9, 43, -19, +40, -8, 41, 0, 40, -2, 42, -4, +33, 0, 41, -4, 38, 1, 40, -11, +38, -10, 38, -10, 40, -2, 40, 7, +40, -1, 46, -11, 40, -8, 30, -2, +31, -1, 33, -3, 44, -8, 49, 1, +46, -3, 35, 0, 26, -9, 28, -15, +47, -6, 49, 4, 51, 2, 39, -7, +29, -14, 29, -9, 40, 2, 46, -1, +52, -4, 39, -13, 32, -2, 30, 2, +33, 2, 42, -7, 46, -12, 44, -8, +43, 1, 36, 0, 36, -8, 39, -9, +37, -8, 45, 3, 40, -3, 41, -5, +37, -10, 42, -7, 38, 2, 40, 1, +35, -8, 42, -11, 39, -6, 44, 0, +40, 2, 40, -6, 33, -2, 34, -2, +31, 5, 44, -9, 49, -10, 42, -4, +39, 0, 30, 6, 33, -7, 47, -15, +47, -10, 46, -3, 40, 0, 30, 1, +32, -8, 44, -6, 49, -4, 43, 2, +34, -8, 32, -12, 33, 2, 37, 8, +48, 3, 42, -8, 36, -15, 30, -6, +31, 8, 40, 3, 44, 4, 36, -10, +38, -6, 31, 1, 32, 2, 37, -3, +41, -7, 37, 3, 39, 6, 35, 2, +35, -10, 40, -15, 41, -11, 44, 7, +40, 3, 40, -2, 38, -11, 39, -11, +40, 0, 43, -5, 46, -10, 35, -1, +30, 4, 33, 7, 42, 2, 44, -11, +43, -8, 36, -8, 31, 5, 34, 3, +39, 1, 44, -3, 46, -3, 38, -2, +34, -5, 33, -10, 39, -7, 45, 1, +43, 3, 40, 2, 39, -10, 37, -5, +38, -4, 40, -2, 38, -6, 42, -9, +44, -5, 44, 5, 41, 2, 38, -8, +35, -15, 42, -14, 39, 5, 42, 6, +41, 2, 43, -12, 42, -10, 38, -4, +36, -3, 38, -3, 35, -6, 48, -5, +48, 2, 43, 2, 33, -5, 27, -10, +31, -7, 37, 9, 49, 2, 54, -3, +39, -5, 25, -5, 27, 1, 30, 1, +47, -3, 53, -8, 50, -3, 36, 0, +36, -4, 29, -6, 37, -1, 40, -2, +51, -1, 47, -4, 38, -5, 35, -5, +37, -1, 36, 4, 43, -3, 45, -9, +43, -7, 41, -1, 40, -2, 39, 2, +35, -2, 36, 0, 39, -2, 43, -4, +45, -7, 42, -4, 39, -2, 39, 4, +33, 3, 40, -10, 46, -15, 49, -7, +43, 6, 40, 4, 27, 4, 30, -9, +42, -10, 50, -2, 51, -1, 45, -4, +34, -10, 37, -7, 35, 5, 43, 3, +50, -12, 47, -15, 40, -7, 31, 13, +35, 9, 43, -3, 41, -13, 42, -18, +44, -5, 38, 5, 44, 5, 43, -2, +41, -5, 37, -5, 33, -2, 36, -5, +43, -1, 43, 2, 44, 8, 40, 3, +33, -3, 30, -7, 35, -10, 43, 0, +51, 4, 50, 3, 46, -5, 38, -11, +34, -15, 42, -10, 48, -6, 54, 5, +52, 2, 44, -6, 37, -15, 38, -17, +36, -2, 45, 8, 46, 9, 48, -3, +46, -12, 38, -10, 33, -1, 35, -1, +39, 1, 50, -6, 50, 3, 45, 2, +44, -9, 34, -13, 33, -12, 40, 0, +47, 12, 52, 8, 48, -7, 37, -15, +31, -12, 29, 6, 38, 11, 44, 6, +52, -9, 52, -14, 44, -7, 34, 0, +31, 0, 34, -1, 40, 3, 51, 1, +54, -1, 47, -11, 34, -11, 30, -8, +33, 8, 40, 15, 52, 4, 53, -10, +46, -19, 38, -13, 36, -2, 40, 7, +46, 7, 50, -4, 48, -13, 41, -10, +41, -9, 39, 5, 41, 5, 43, 0, +47, -11, 48, -12, 43, -4, 44, -1, +42, 0, 44, -6, 43, -1, 37, 3, +43, 3, 41, -7, 48, -16, 48, -12, +46, 5, 41, 13, 42, 1, 39, -15, +42, -20, 42, -6, 45, 15, 44, 20, +42, -1, 36, -14, 35, -20, 40, -3, +46, 7, 52, 5, 49, -5, 48, -12, +42, -8, 40, -2, 38, -3, 43, -9, +43, 1, 45, 8, 47, 12, 45, -2, +38, -16, 35, -21, 36, -6, 46, 10, +55, 16, 53, 4, 44, -14, 34, -18, +26, -7, 35, 7, 49, 10, 56, 5, +54, -8, 42, -10, 36, -11, 36, -3, +37, 3, 44, 1, 52, 0, 46, 4, +46, 1, 40, -5, 36, -11, 37, -14, +46, -1, 49, 11, 52, 14, 46, -7, +44, -21, 32, -16, 41, -3, 49, 13, +50, 12, 49, -9, 47, -22, 38, -9, +35, 10, 37, 17, 40, 3, 44, -10, +45, -12, 42, 6, 41, 9, 40, 3, +37, -8, 42, -10, 45, 1, 48, 9, +44, 3, 41, -12, 38, -12, 38, 1, +43, 16, 43, 15, 40, -4, 46, -26, +43, -16, 44, 2, 49, 13, 46, 9, +41, -7, 38, -17, 41, -13, 43, 7, +47, 9, 48, 3, 47, -11, 41, -10, +40, -5, 41, 4, 41, 2, 48, -8, +52, -10, 49, 0, 40, 11, 33, 6, +33, -9, 40, -17, 43, -2, 54, 10, +51, 22, 38, 5, 34, -19, 29, -21, +35, -3, 50, 17, 56, 18, 55, -2, +42, -19, 32, -15, 30, 1, 39, 11, +48, 4, 58, -11, 54, -11, 44, 3, +33, 11, 27, 4, 34, -9, 45, -16, +57, -2, 54, 15, +}; \ No newline at end of file diff --git a/project/realtek_ameba1_va0_example/example_sources/i2s/src/birds_32000_2ch_16b.c b/project/realtek_ameba1_va0_example/example_sources/i2s/src/birds_32000_2ch_16b.c new file mode 100644 index 0000000..b6d66d1 --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/i2s/src/birds_32000_2ch_16b.c @@ -0,0 +1,23326 @@ +#include +int sample_size=93277; + +SECTION(".sdram.data") +short sample[]={ +-1, 1, 0, 0, 1, 1, -1, 2, +-1, -1, 2, -1, 0, 2, -4, 4, +-3, 2, -1, 0, 2, -2, 1, 1, +-1, 0, 1, -2, 2, 0, 1, 1, +-3, 1, 0, -1, 2, -2, 2, 0, +-1, 2, -4, 3, -3, 3, 0, 0, +2, -2, -1, -1, 0, -1, 4, -3, +4, -4, 1, -3, 1, -3, 3, -1, +1, 0, 2, -4, 3, -5, 1, 1, +0, 1, -1, 1, -5, 2, -1, 0, +2, 0, 2, -1, -1, 0, -4, 2, +1, 0, 5, -2, -2, 2, -6, 3, +0, 0, 2, 0, -1, 1, -1, -2, +1, 0, 0, 3, 3, -4, 3, -4, +0, -1, 3, 0, 1, 2, -3, 1, +-1, -1, 4, -3, 5, -1, 0, 0, +-2, -1, 0, -1, 4, -2, 2, 0, +-2, -1, 2, -3, 3, 1, -1, 3, +-3, 0, -1, -2, 3, -2, 4, -2, +2, -1, -2, -2, 1, -1, 3, 0, +1, 0, -2, 0, 1, -2, 1, 2, +-1, 1, 1, -2, -3, 3, -3, 3, +0, 2, -1, -1, 1, -4, 1, 1, +-1, 3, 0, -1, 0, 0, -3, 1, +1, 0, 3, -2, 1, -4, 1, -2, +4, -3, 4, 0, -2, 0, 0, -3, +2, -1, 2, 1, -2, 3, -4, 3, +-3, 2, 2, 0, 0, 1, 0, -2, +1, -2, 0, 3, -3, 3, -2, 0, +-1, -1, 2, -3, 7, -4, 2, 1, +-3, 1, 1, -1, 1, 1, 0, 1, +-3, 3, -4, 1, 2, -3, 4, -2, +2, -3, 0, 0, -2, 3, -1, 0, +2, -3, 1, -2, 0, 1, -2, 4, +-3, 2, -1, -1, -1, 0, 2, -2, +3, -1, -3, 2, -2, 2, -3, 3, +-1, 3, -5, 4, -1, -1, 0, 0, +0, 0, 0, 0, -1, 1, -2, 2, +0, 1, -2, 2, -2, 1, -1, 1, +0, 0, 0, 1, -2, 1, -1, 0, +0, 1, 0, 1, -1, 1, 0, -2, +3, -3, 3, -1, 1, 0, 0, -1, +1, -2, 2, -1, 1, 0, 1, -1, +0, 0, 2, -2, 3, -2, 0, 0, +-1, 0, 1, -1, 0, 1, -2, 2, +-2, 0, -1, 0, 2, -2, 2, 0, +-3, 2, -2, 2, -2, 2, -3, 3, +-3, 1, 0, 1, -2, 3, -2, 2, +-1, 0, 0, -2, 2, -1, 0, 2, +-4, 5, -5, 4, -3, 3, -1, 1, +2, -2, 1, 0, -1, 0, 1, -1, +1, 0, -1, 0, 0, 1, -1, 1, +1, -1, 1, -1, 1, -2, 1, 2, +-3, 4, 0, -2, 1, 0, -2, 3, +-1, 1, 1, -1, 2, -2, 0, 0, +-1, 2, 0, -2, 4, -4, 2, -1, +0, 2, -1, 0, 2, -1, -4, 4, +-2, 1, 2, -1, 0, 1, -4, 3, +-2, 2, -1, 2, -2, 3, -4, 4, +-5, 4, -1, 1, 1, -1, -1, 0, +-1, -1, 3, -3, 3, -2, 0, 1, +-2, 2, -3, 3, -2, 1, -1, 1, +-3, 2, -2, 1, 0, 0, -1, 2, +-3, 1, 0, 0, 1, -2, 3, -2, +-1, 2, -3, 2, -1, 1, 2, -1, +2, -3, 1, 0, 0, 0, 4, -4, +4, -3, 2, -1, 0, 0, 1, -1, +1, -1, 2, -2, -1, 2, -2, 2, +0, 0, 1, -1, -1, 2, -3, 3, +1, -2, 3, -1, -2, 1, 1, -2, +2, 0, 0, 0, 1, 0, -3, 3, +-3, 4, -3, 3, -2, 2, -2, 0, +1, -1, -2, 4, -5, 4, -5, 4, +-4, 3, -2, 3, -4, 3, -2, 1, +-2, 3, -5, 5, -4, 4, -3, 1, +-2, 1, -3, 4, -4, 4, -3, 0, +2, -3, 4, -4, 4, -3, 2, -3, +2, -2, 2, -2, 1, -1, 2, -2, +1, -1, -2, 1, 0, 0, -1, 1, +0, 0, 1, -1, 0, 1, -3, 5, +-4, 4, -4, 3, -1, 0, 2, -1, +2, -2, 3, -3, 1, -1, 0, 3, +-3, 2, 1, -1, 1, -2, 3, -1, +0, 1, 0, 1, 0, -1, 0, 0, +0, 0, 1, 0, -2, 2, 0, -1, +2, -1, 2, -2, 1, 0, -2, 2, +-2, 1, 0, 0, 2, -2, -1, 2, +-3, 3, -3, 2, 1, -1, -1, 1, +0, -3, 3, -2, -1, 1, 0, -1, +0, 0, 2, -4, 4, -3, 1, -2, +2, -2, -1, 1, -2, 2, 0, -3, +4, -4, 4, -5, 6, -4, 1, 1, +0, -1, 1, -1, -1, 2, -2, 2, +-1, 2, -4, 4, -4, 4, -2, 1, +3, -3, 1, 0, -1, 1, 1, -2, +3, -1, 1, -1, 2, -1, 0, 0, +0, 1, -1, 2, -1, 2, -2, 2, +1, -1, 0, 1, -1, 1, -2, 2, +-1, 1, 1, -1, 2, -2, 1, 1, +-3, 2, 0, 2, -3, 3, 0, -1, +3, -2, -1, 2, -2, 1, 0, 0, +1, -2, 3, -2, 0, 1, -1, 1, +0, -1, 1, 1, -2, 0, 1, 0, +-4, 4, -2, 1, -2, 2, -2, 2, +-2, 2, -1, 0, 2, -3, 1, -1, +1, -2, 0, 2, -5, 5, -5, 3, +0, -1, 2, -3, 4, -5, 6, -5, +3, -2, 1, -3, 4, -2, -2, 3, +-4, 4, -3, 2, 0, 0, 2, -3, +4, -3, 0, 1, -2, 2, 0, 0, +3, -4, 4, -3, 2, 0, 1, 0, +0, 2, -1, -1, 2, -1, 0, 0, +1, 0, 0, 0, 1, -1, 1, 0, +1, -1, -1, 2, -3, 2, 0, -1, +2, 0, 1, -1, 2, -1, 1, -2, +1, 0, 1, -1, 1, 0, -3, 4, +-4, 3, 0, -2, 1, -2, 1, -3, +3, -3, 1, 0, 0, -1, 0, -1, +0, -1, -1, 2, -4, 3, -2, 0, +1, -3, 1, 0, -2, 1, 0, 0, +0, -1, 2, -2, 0, 0, 0, 0, +0, 0, -1, 2, -2, 1, 0, 0, +1, -2, 3, -3, 2, -1, 2, -1, +2, -2, 1, 0, 0, 0, 0, 0, +3, -2, 2, -2, 2, -2, 3, -3, +2, -1, 1, -1, 1, -1, 1, -2, +5, -5, 5, -4, 4, -4, 4, -3, +1, 1, -2, 2, -2, 3, -2, 1, +2, -2, 3, -3, 3, -2, -1, 0, +0, 0, 0, 0, 2, -2, 0, 1, +-3, 2, -1, 0, 1, 0, -3, 2, +-3, 2, -2, 1, 1, -1, -1, 0, +-2, 0, -1, 1, -2, 2, -4, 3, +-2, -1, 1, -1, -2, 2, -1, 1, +-2, 1, 1, -2, 3, -3, 3, -3, +4, -5, 3, -2, 0, 0, 0, 0, +-1, 0, -1, 3, -4, 3, 2, -2, +1, 0, -1, 1, -1, 1, 0, 1, +-1, 3, -3, 4, -2, 1, 2, -1, +2, -2, 3, -3, 3, -3, 4, -2, +0, 1, 2, -2, 4, -3, 2, 0, +0, -1, 4, -3, 3, -2, -1, 1, +-2, 3, -2, 2, -1, 1, -1, 1, +0, 0, -1, 3, -4, 3, -2, 2, +-2, 1, 2, -3, 2, -1, -1, 1, +-1, 1, -2, 2, -3, 1, 0, -2, +3, -3, 2, -1, 0, 0, -1, -1, +1, -2, 0, 1, -1, 1, 0, -1, +-1, 2, -3, 3, -2, 2, 0, -1, +0, 0, 0, -1, 0, 2, -3, 2, +0, -1, 0, 1, 0, 0, 2, -2, +1, 0, -2, 2, -2, 2, 0, -1, +1, 1, -4, 4, -2, 2, -1, 2, +-1, 1, 2, -2, 1, 0, 1, 0, +2, 0, -1, 1, 1, -2, 1, 0, +1, -2, 4, -3, 0, 1, 0, 0, +3, -3, 1, 1, -3, 3, -2, 1, +1, -1, 0, 0, -1, 1, -2, 3, +-5, 4, 0, -2, 4, -5, 2, 0, +-4, 4, -2, 1, 1, -2, 1, -2, +2, -3, 1, 0, 0, 0, -2, 1, +-2, -1, 1, -1, -2, 3, -4, 3, +-3, 1, -1, 0, -1, 2, -3, 3, +-3, 1, -1, 0, 0, 0, 0, 0, +0, -1, 2, -4, 4, -3, 2, -1, +2, -3, 1, 0, -2, 3, 0, -1, +1, 1, -2, 1, 1, -1, 1, 2, +-3, 4, -2, 0, 0, 0, 1, -2, +3, -2, 0, 0, -2, 2, -1, 1, +0, 2, -3, 4, -5, 6, -4, 2, +2, -2, 0, 2, -4, 3, -2, 1, +2, -3, 3, -1, -1, 1, -1, 0, +3, -3, 0, 2, -5, 4, -1, 0, +-2, 3, -2, 1, -2, 3, -4, 2, +-1, 1, -4, 5, -4, 2, 1, -3, +2, -2, 1, -1, 2, -3, 2, -2, +3, -4, 4, -4, 2, -2, 2, -2, +0, 0, -1, 2, -2, 1, 0, 0, +0, 0, -2, 1, 2, -3, 2, -1, +-2, 3, -2, 1, 1, 0, 1, -1, +2, -2, 3, -3, 2, 0, 0, 0, +1, -2, 2, -2, 3, -1, 0, 2, +-4, 4, -3, 2, 0, 1, 1, -1, +3, -3, 1, -1, 1, 0, 2, -1, +1, 0, 1, -2, 3, -1, 0, 1, +2, -2, 0, 0, 0, -1, 1, 1, +-1, 2, -1, 1, -2, 1, 0, -1, +3, -3, 4, -3, 2, -3, 2, -1, +-1, 3, -1, 1, -4, 5, -8, 6, +-3, 3, -2, 2, -2, 1, -2, 1, +0, -1, 2, -1, 1, -2, 1, -1, +-2, 2, -1, 1, 0, 0, 0, -1, +-1, 1, 0, 0, 1, 0, 0, 0, +-2, 2, -2, 2, 1, -2, 2, -2, +0, -1, 2, -2, 2, 1, -3, 3, +-3, 0, 2, -3, 3, -1, 0, 2, +-1, -1, 2, -3, 3, -3, 4, -2, +0, 0, 1, -2, 2, -1, 1, -1, +1, 0, -2, 2, -3, 2, 1, -1, +2, 1, -3, 2, 0, 0, -1, 3, +2, -3, 2, 1, -5, 3, 0, -1, +2, -1, 1, 0, -4, 5, -6, 4, +-1, 2, -3, 4, -4, 1, 3, -5, +6, -5, 4, -3, 3, -3, 0, 0, +-1, 1, 1, -1, -1, 2, -5, 4, +-4, 2, 1, -2, 2, -2, 1, -1, +0, 0, -1, 1, -1, 2, -5, 6, +-5, 2, 1, -1, 4, -4, 4, -2, +-1, 0, 4, -5, 5, -3, 2, -1, +2, -2, -1, 0, 1, -1, -1, 3, +-3, 2, -1, 2, -3, 3, -2, 2, +0, -1, 2, -3, 1, 1, 0, 1, +1, -1, 0, -1, 1, -2, 2, -2, +3, -3, 3, -1, -1, 1, 0, 0, +-3, 6, -6, 4, -1, 0, -1, 1, +1, -3, 2, -1, -2, 3, -2, 1, +1, -1, -1, 1, -1, 1, -2, 2, +-2, 2, -2, 2, -3, 3, -1, 1, +-1, 0, 1, -2, 0, 0, -1, 1, +-1, 1, 1, -2, 1, -1, -2, 2, +-1, 0, 0, 0, 1, -3, 2, -1, +-2, 3, -4, 4, -3, 2, -2, 2, +-3, 4, -4, 5, -3, 2, 1, -3, +4, -4, 4, -2, -1, 2, -1, -2, +5, -5, 2, 0, 1, -1, 0, 0, +-1, 0, 1, -1, 2, -1, 0, 1, +-1, -1, 3, -2, 2, -1, 1, -1, +0, 0, 0, -1, 1, 0, -1, 2, +-2, 0, 0, 0, 0, -1, 4, -2, +0, 0, 1, -3, 3, -1, 0, 1, +0, 0, 0, -1, -1, 1, -1, 2, +-3, 4, -2, -1, 4, -5, 4, -2, +2, 0, -3, 3, -4, 3, -2, 1, +1, 0, -1, 0, 1, -2, 1, 0, +0, 1, -1, 0, 1, -2, 0, 0, +1, -2, 2, -1, 0, -2, 2, -1, +-3, 4, -1, -1, 4, -3, -2, 3, +-3, 1, 2, -2, 3, -2, 0, 1, +-3, 2, -1, 1, 2, -2, 1, 0, +-3, 3, -2, 1, 1, 1, -2, 2, +-2, 0, 0, 0, 1, -2, 2, 0, +-3, 1, 2, -2, 1, -1, 3, -2, +0, 1, -3, 2, -1, 1, 1, 0, +-1, 2, -2, 0, 1, -2, 1, 0, +1, 0, -2, 2, -2, 1, 0, -1, +2, -2, 0, 1, -5, 3, -1, 1, +1, -1, 1, -1, -2, 2, -1, 0, +2, -1, 1, -2, 3, -4, 3, -2, +1, 0, 1, -1, 1, -2, 3, -3, +0, 1, -1, 0, 1, -1, 0, 0, +1, -2, 2, -1, -1, 1, 0, -1, +4, -5, 3, -2, 3, -3, 1, 1, +-3, 2, 2, -3, 2, 1, -3, 3, +-1, 0, 0, 0, -1, 2, -2, 3, +-4, 3, -1, 0, 2, -2, 4, -4, +2, 0, -1, -1, 4, -3, 0, 3, +-3, 1, 2, -2, 2, 0, -2, 3, +-2, 2, 0, -1, 1, 0, -1, 1, +-2, 2, -3, 3, -1, -1, 2, -1, +0, 0, 3, -4, 6, -6, 4, -2, +-1, 1, -2, 2, -2, 2, -1, 1, +-2, 3, -4, 4, -2, 2, -3, 3, +-2, 0, 0, 0, 2, -3, 3, -1, +-2, 2, -1, -1, 0, 0, 0, 0, +0, 0, 1, -2, 1, 0, -2, 4, +-3, 1, 1, -2, 0, 0, 0, -1, +3, -2, 0, 1, -1, 1, -1, 2, +-1, 0, 2, -1, 0, 1, -3, 3, +-2, 2, 0, 0, 0, 0, 0, -1, +1, -1, 2, -1, 1, -2, 2, -2, +2, -2, 1, -1, 1, 0, -1, 1, +-2, 1, 0, 0, 0, 1, -3, 3, +-3, 2, -1, 0, 3, -3, 3, -2, +-1, 2, -3, 3, -2, 2, -1, 2, +-4, 3, -3, 1, 0, 0, 1, -1, +0, -1, 0, -2, 2, -1, 0, 0, +0, -1, 1, -1, 1, -2, 2, -2, +0, 0, -1, 0, 0, -1, 0, 0, +0, 1, -1, 1, -3, 2, -1, 1, +-1, 2, -1, 0, 0, 0, 1, -1, +2, -1, 0, 1, -1, 1, -2, 0, +3, -3, 2, 0, 1, -2, 3, -2, +0, 1, 0, 0, 0, 1, -1, 0, +1, -1, 1, 1, 0, 0, 1, 0, +-4, 6, -4, 2, 1, -1, -1, 1, +0, 0, 0, 0, 1, -2, 1, 0, +-2, 1, -1, 1, -1, 0, 1, 0, +-3, 3, -2, 0, 1, -1, 2, -3, +2, -3, 2, -2, -1, 1, -1, 0, +0, 0, -1, 1, -2, 1, 1, -1, +-1, 4, -6, 6, -6, 5, -4, 2, +-1, 1, -2, 2, -1, 1, 0, -2, +1, 0, 0, 0, -2, 2, -2, 1, +0, 0, 0, 0, 1, -1, 2, -3, +5, -6, 4, -1, 1, -2, 4, -5, +2, -1, 2, -2, 2, 0, 0, -2, +4, -4, 0, 3, -3, 3, -2, 3, +-4, 4, -4, 4, -3, 2, -1, 0, +0, 1, -2, 2, 0, -1, 1, 1, +-1, 0, 0, 1, -4, 4, -2, 2, +-2, 3, -3, 2, -3, 2, -1, 1, +0, 1, -1, 0, 0, 0, -2, 2, +-2, 1, -1, 2, -4, 3, -2, 2, +-1, 0, 2, -2, 2, -2, 1, 0, +0, -1, 3, -3, 1, 0, -2, 2, +-1, -1, 2, -2, 0, 1, -2, 1, +0, -1, 1, 0, 0, 1, -2, 1, +-1, 2, -3, 3, -1, 1, 0, 1, +-2, 2, -3, 3, -2, 1, 0, 0, +-1, 2, -4, 3, -1, 0, 1, 0, +1, -2, 4, -4, 3, -2, 1, 0, +0, 0, 1, -2, 1, -1, 0, 0, +2, -3, 3, -2, 0, 0, 0, -1, +2, -2, 2, -1, 1, -2, 3, -3, +2, -1, 0, 1, -1, 0, 1, -2, +2, -1, 0, 0, -1, 1, 0, -2, +3, -3, 0, 1, 0, 0, -1, 1, +-1, -1, 2, -1, -3, 4, -4, 3, +-2, 1, 1, 0, -1, 1, 1, -3, +2, -1, -2, 3, -2, 1, 0, 1, +-1, 0, 0, 1, -3, 3, -1, 0, +0, -1, 2, -3, 4, -4, 4, -3, +2, 0, -1, 0, 0, 0, -1, 1, +1, -1, 2, -3, 3, -2, 0, 0, +-1, 2, -3, 2, 0, -2, 3, -3, +2, -1, 1, -1, 2, -3, 1, 1, +-2, 1, 3, -4, 4, -2, 0, 1, +0, 0, 1, -2, 2, -1, 0, 1, +-1, 0, 1, -1, 1, -1, -1, 1, +0, -1, 1, -1, 1, -1, 0, 0, +-1, 2, -2, 1, 2, -3, 1, 0, +-1, 0, -1, 1, -2, 2, -2, 3, +-4, 2, 1, -3, 3, -2, 0, 0, +0, 0, -1, 1, 0, -1, 0, 2, +-2, 1, 1, -1, -1, 1, -3, 4, +-3, 1, 2, -2, 0, 0, -1, 0, +1, -1, 1, 0, 1, -1, 1, -2, +1, -1, 1, -1, 2, -2, 1, 0, +-2, 3, 0, 0, 1, 1, -3, 3, +-2, 0, 3, -3, 2, -1, 1, -2, +2, -1, 0, 0, -1, 1, -1, 1, +-2, 2, -1, 0, 2, 0, -3, 4, +-4, 4, -5, 5, -4, 2, 0, 0, +0, -1, 1, -2, 2, -1, 0, 1, +0, 0, 1, -1, -1, 1, -1, 1, +0, 0, 0, 0, -1, 1, -1, 1, +-2, 4, -4, 2, 0, -1, -1, 1, +-1, 1, -1, 2, -1, -1, 3, -3, +2, -2, 3, -4, 4, -4, 2, -2, +2, -3, 3, -2, 1, 0, 0, -1, +2, -3, 3, -2, 0, 1, -3, 4, +-4, 4, -2, 1, 1, -1, 3, -4, +3, -1, -2, 3, -1, 1, -2, 4, +-5, 4, -1, 0, 2, -2, 1, 0, +-2, 2, -1, 1, 2, -2, 2, 0, +-2, 1, 2, -4, 4, -3, 1, 0, +0, -1, 1, -2, 3, -3, 2, -1, +2, -2, 1, -1, -1, 2, -4, 4, +-3, 3, -3, 2, -2, 1, 0, 0, +1, -1, 1, -2, 2, -3, 1, 0, +-1, 1, 0, -1, 1, -1, 0, 0, +-1, 0, 1, -1, 1, -2, 3, -4, +2, 0, -2, 3, -3, 3, -2, 1, +0, 0, -1, 1, -1, 1, -1, 1, +0, 0, 0, 1, -2, 1, 0, 0, +-1, 2, -2, 2, 0, -1, 2, -2, +1, -1, 2, -2, 0, 1, 0, 0, +0, 1, -1, 1, 0, 1, -1, 1, +0, 0, 1, -1, 1, 0, -3, 3, +-1, 0, 2, -1, -1, 2, 1, -3, +2, 0, -4, 5, -2, 1, 1, -1, +1, -1, 2, -2, 0, 1, -3, 2, +-2, 3, -3, 2, 2, -2, 2, 0, +-1, 0, 3, -5, 5, -4, 0, 1, +-2, 1, 0, 0, -1, 2, -2, 1, +2, -4, 5, -5, 4, -3, 0, 1, +-2, 1, -1, 1, -1, 0, 0, -1, +2, -1, 0, 1, -2, 1, 0, 0, +0, 1, -1, 0, 3, -5, 6, -4, +0, 3, -3, 2, 0, 0, -2, 2, +-1, 1, 1, -1, 1, 1, -2, 3, +-2, 2, -3, 4, -3, 1, 0, 0, +-1, 0, 0, 0, 1, -2, 3, -2, +-1, 2, -3, 3, -1, 0, 1, -1, +2, -4, 5, -4, 2, -1, 1, 0, +-1, 1, 0, -1, 2, -2, 2, -2, +1, -1, 1, -2, 2, -1, 0, 0, +1, -1, 0, 0, 1, -1, 0, 2, +-3, 2, 1, -2, 2, -1, -1, 2, +-1, 0, 2, -1, -3, 3, -1, 0, +-2, 4, -5, 4, -3, 3, -4, 3, +-1, 0, 1, -1, 0, 0, -2, 2, +0, 0, -2, 2, -3, 2, -1, 0, +1, 0, 0, 1, 0, -1, 2, -2, +1, 0, -1, 1, 0, 0, 0, 1, +-1, 0, 2, -2, 2, -2, 3, -3, +3, -2, 2, -1, 0, 1, -2, 1, +1, 0, 1, -1, 1, -1, 0, 0, +2, -3, 2, 0, 0, -1, 0, 1, +-3, 3, 1, -3, 4, -3, 2, -2, +2, -1, 2, -2, 3, -2, -2, 2, +0, -1, 1, -1, 1, 0, -1, 1, +-1, 0, 2, -2, 2, -3, 4, -4, +2, -1, 1, -2, 2, -3, 4, -5, +5, -4, 1, -1, 1, -2, 1, 0, +-2, 2, -1, 0, 2, -2, 2, -1, +0, -1, 1, -1, 1, -3, 5, -5, +2, 1, -3, 3, -2, 2, -2, 2, +0, 0, 1, 0, 1, -1, 0, 1, +-2, 3, -2, 1, 1, -1, 1, 0, +1, -3, 6, -5, 2, -1, -1, 1, +-2, 2, 0, 0, 0, 1, -1, 0, +2, -1, -1, 3, -4, 4, -3, 1, +0, -1, 4, -4, 1, 0, -2, 2, +-1, 0, 0, 1, -3, 4, -1, -1, +2, -1, 2, -3, 3, -2, -1, 2, +-2, 2, -1, 1, -2, 2, 0, -1, +3, -3, 1, 0, 0, 0, 0, 0, +0, 0, 2, -2, 0, 2, -4, 4, +-1, -1, 3, -2, -1, 2, 0, -1, +1, 0, -2, 0, 1, -1, -1, 1, +0, 0, 1, -2, 1, -1, 2, -2, +2, -2, 1, 0, 0, -1, 2, -1, +1, -1, 1, 0, -1, 1, -1, 2, +-1, 1, -2, 3, -3, 2, 0, 0, +-2, 4, -4, 2, 1, -1, -1, 2, +-3, 3, -1, 1, 0, 0, 0, 0, +0, -1, 1, 0, -1, 1, 0, 0, +-2, 3, -3, 2, 1, -2, 3, -3, +2, -3, 3, -2, 2, 0, -2, 3, +-4, 4, -1, 0, 1, -1, 0, 1, +-3, 2, -1, 0, 0, 0, -2, 2, +-1, 0, 1, -1, 0, 0, -1, 1, +-1, 0, -1, 2, -3, 3, -1, 2, +-3, 3, -1, -1, 1, 0, 0, -2, +4, -3, 1, 0, 0, -1, 1, -1, +1, -2, 1, -1, 0, 0, 0, 0, +2, -3, 3, -2, -2, 3, -3, 2, +0, -1, 0, 1, -2, 1, 0, 0, +0, 0, 1, -2, 1, -1, 2, -3, +2, -1, 0, 1, -2, 1, 0, -1, +1, -2, 4, -5, 4, -2, -3, 5, +-4, 3, 1, -2, 1, 0, 0, -1, +2, -1, -1, 1, -1, 0, 1, -2, +2, -1, 0, -1, 3, -3, 0, 0, +1, -1, -2, 3, -3, 2, -1, 1, +-3, 4, -2, 1, 0, 0, 0, 0, +1, -2, 2, -2, 2, -2, 0, 0, +-2, 3, -4, 3, 0, -2, 2, -1, +-1, 1, 1, -1, 1, -1, 1, -1, +-1, 1, -2, 2, -1, 1, 0, -1, +2, -2, 1, -1, 1, -1, 1, 0, +-1, 2, -3, 3, 0, -1, 0, 1, +-1, 1, 0, -1, 2, -2, 0, 1, +-2, 2, 1, -2, 1, 0, 1, -3, +5, -5, 1, 1, -2, 1, 0, -1, +1, 0, 1, -1, 1, 0, -2, 2, +-1, 1, 1, -1, 0, 1, -2, 1, +1, -2, 3, -3, 2, -1, -2, 3, +-3, 1, 1, -2, 4, -3, 0, 1, +-3, 3, -2, 2, -2, 1, 1, -3, +3, -2, 1, -1, 2, -2, 0, 1, +-2, 2, 0, 0, -1, 1, -2, 2, +-1, 0, 0, 0, 1, -1, 1, -1, +1, -2, 3, -3, 2, 0, -3, 3, +0, -2, 3, -3, 1, 1, -2, 2, +-1, 0, 0, -1, 0, 0, -1, 2, +-4, 6, -4, 3, -1, 0, 3, -3, +3, -1, -1, 3, -3, 3, -2, 2, +0, -1, 1, -1, 1, 0, -2, 1, +0, 1, -2, 2, 0, -1, 2, 0, +-3, 4, -2, 1, -1, 2, -2, 2, +-2, 2, -1, -1, 2, -2, 1, 0, +-1, 1, -1, 2, -2, 3, -3, 2, +2, -3, 3, -2, 2, -3, 3, -3, +1, -1, 1, 0, 0, 0, 1, -1, +1, -1, 2, -2, 1, 0, 1, -2, +1, 0, -2, 2, -1, 1, -2, 2, +-1, 1, -2, 3, -4, 2, 0, 0, +0, 0, 1, -1, 1, -2, 2, -2, +1, 0, -2, 2, -2, 1, -2, 3, +-3, 3, -2, 1, 0, 0, 1, -2, +2, -1, -2, 2, -2, 0, 2, -2, +-1, 3, -3, 2, 0, 0, -2, 3, +-3, 3, -1, 0, 1, -2, 1, 1, +-2, 2, 0, -1, 0, -1, 2, -3, +2, -1, 0, 0, -2, 2, -2, 2, +-1, 2, -3, 2, 1, -2, 2, -2, +2, -1, 0, 1, -1, 1, 0, 0, +1, 0, -3, 4, -3, 2, 0, 0, +-2, 2, 0, -1, 3, -3, 3, -2, +2, -1, 1, 0, -1, 1, 0, -1, +2, -2, 1, -1, 2, -3, 4, -4, +2, -2, 0, 0, -1, 1, -1, 1, +0, 0, 1, -1, 1, 0, -1, 1, +0, -2, 1, 0, -1, 0, 2, -2, +2, -2, 0, 1, -3, 3, -2, 1, +1, -1, -2, 3, -4, 3, -1, 1, +-2, 3, -4, 4, -1, -1, 3, -3, +1, 0, 0, -1, 0, 0, 0, 0, +0, 0, -1, 2, -4, 4, -3, 2, +2, -2, 0, 3, -4, 2, 1, -2, +1, 1, -1, 0, 0, 1, -2, 2, +-1, 2, -1, 0, 2, -2, 0, 1, +-1, 0, 2, -3, 4, -4, 4, -5, +5, -4, -1, 3, -3, 1, 2, -3, +3, -1, -1, 2, -1, 1, 0, 0, +0, 0, 0, 0, 0, -1, 1, -1, +1, -1, 0, 0, -2, 3, -3, 2, +-2, 2, -4, 4, -4, 2, 2, -3, +2, 0, -1, 1, 0, 0, 1, -1, +2, -2, 1, 0, 0, 0, 0, 1, +0, -2, 2, -1, 0, 1, -4, 6, +-6, 5, -3, 2, 0, 0, 1, -1, +0, -1, 2, -3, 1, 1, -2, 1, +-1, 1, -3, 3, -3, 3, -3, 3, +-2, 1, 1, -1, 0, 1, -2, 1, +2, -3, 3, -1, -2, 2, 0, -2, +4, -4, 2, -1, 0, 1, -3, 3, +-2, 1, 1, 0, 1, -1, 1, 0, +-1, 0, 2, -1, 0, 0, -1, 2, +-3, 4, -4, 2, 0, -1, 2, -2, +2, -1, 1, 0, -2, 3, -4, 3, +-1, 0, 0, 0, 0, -1, 3, -4, +5, -4, 1, 0, 1, -3, 3, -2, +-1, 0, 2, -3, 0, 1, -1, -1, +4, -5, 2, 0, -1, 0, 2, -2, +2, -2, 1, -1, 2, -2, 3, -3, +4, -3, 0, 2, -3, 3, 0, -1, +1, 0, 0, 0, 1, -1, 1, 0, +-1, 1, 0, -1, 1, -1, 0, -1, +3, -3, 3, -2, 1, -1, 0, 0, +1, -1, 0, 0, 1, -2, 1, -1, +0, 0, 0, 1, -1, 0, 1, -2, +1, 0, 0, 0, 1, -1, 0, 2, +-5, 5, -1, -2, 3, -2, -2, 3, +-5, 5, -2, 0, 2, -1, 0, 1, +-2, 2, -3, 3, -3, 3, -2, 1, +0, -1, 3, -4, 3, -1, 0, -1, +3, -3, 0, 2, -2, 2, -2, 1, +0, -1, 1, 0, -3, 3, -4, 4, +-2, 1, -1, 2, -3, 3, -3, 2, +-1, 2, -2, 1, 2, -3, 2, 0, +-1, 1, -2, 2, 0, -1, 0, 1, +-3, 3, -1, 1, -1, 1, -1, 1, +1, -1, 0, 0, -1, 1, 1, -2, +2, -2, 1, -1, 0, 1, -2, 2, +-3, 3, -3, 2, 1, -3, 4, -2, +-2, 3, -4, 5, -2, -1, 4, -3, +0, 1, -1, -1, 1, -1, 0, 0, +-1, 1, -1, 0, 3, -3, 1, 1, +-2, 2, 0, -1, 1, -1, 1, -1, +2, -2, 1, 0, -1, 2, -1, -1, +3, -3, 4, -5, 3, -1, -3, 5, +-6, 4, -2, 1, 2, -3, 3, -2, +2, -2, 3, -3, 1, 0, 1, -1, +1, -1, -1, 2, -3, 3, -1, 1, +-1, 1, 0, 0, 3, -3, 3, -2, +1, 0, -1, 1, 1, -2, 2, -2, +1, 1, -1, 0, 3, -3, 3, -2, +0, 1, -1, 0, 2, -2, 1, -1, +-1, 2, -2, 2, -2, 2, 0, 0, +1, -2, 0, 2, -4, 2, 1, -2, +3, -2, 0, 1, 1, -3, 4, -3, +1, -1, -1, 1, 0, -3, 5, -5, +2, 0, 0, -2, 3, -2, 2, -4, +5, -4, 0, 2, -2, 2, -1, 0, +2, -2, 2, -2, 1, 0, 0, -1, +3, -4, 4, -3, 2, -1, 0, 1, +-2, 2, -1, 0, 1, -1, -1, 2, +-1, 0, 1, 0, -2, 2, 0, 0, +-1, 0, 0, 1, -2, 2, 1, -2, +4, -4, 3, -1, 0, 1, 0, -1, +2, -2, 1, -1, 3, -3, 2, -2, +2, 0, -1, 1, -1, 2, 0, -1, +1, 0, -1, 0, 2, -1, -2, 2, +0, -2, 4, -3, 0, 0, 1, -1, +0, 0, 1, 0, 0, 0, -1, 3, +-3, 2, -1, 1, -1, -1, 2, -1, +0, 0, -1, 1, 0, 0, 0, 0, +0, 0, 0, -2, 3, -2, -1, 1, +-1, 1, 0, -2, 2, 0, -3, 3, +-3, 3, -3, 2, 0, -1, 2, -2, +1, -1, 0, -1, 1, -1, 0, 1, +-4, 4, -3, 2, -2, 0, 2, -3, +2, -2, 0, 1, -2, 0, 0, 0, +-1, 1, -2, 3, -2, 2, -4, 5, +-5, 3, -1, 0, 0, 1, -2, 1, +1, -2, 4, -4, 5, -3, 1, -1, +2, -2, 2, -2, 2, -1, -1, 0, +-1, 2, -2, 1, 1, -2, 4, -4, +3, -2, 1, 0, -2, 1, 2, -1, +-2, 2, -1, 1, -2, 2, -2, 1, +0, -1, -2, 3, -1, -1, 3, -2, +1, -1, 2, -2, 2, -1, -1, 2, +-1, 0, 0, 0, 0, 0, -1, 0, +0, 2, -2, 0, 2, -2, 0, 0, +0, 1, 0, -1, 2, 0, -2, 3, +-3, 2, 0, -2, 2, -1, 1, -2, +2, -2, 0, 1, 0, -1, -1, 3, +-5, 2, 5, -5, 2, -1, 0, 1, +-2, 2, -2, 2, 0, -1, 0, 1, +-2, 2, 0, -1, 2, -1, -2, 3, +-3, 2, 0, -1, 1, 1, -2, 0, +1, 1, -4, 3, -2, 1, 1, -3, +2, -2, 1, -1, 0, 1, -1, 1, +1, -3, 5, -4, 3, -3, 2, 0, +0, -2, 4, -4, 3, -3, 4, -2, +1, 0, -1, 1, 2, -4, 4, -3, +1, 0, -1, 2, -3, 2, 0, -2, +1, 0, 0, -1, 4, -3, 1, -2, +2, 0, -2, 1, 0, 1, -1, 1, +0, 0, 0, -1, 0, 1, -2, 2, +0, -2, 4, -3, 1, -1, 1, 0, +-2, 1, 0, 1, -3, 2, 2, -2, +1, 0, 0, 0, 1, -2, 1, 0, +-2, 2, -2, 3, -3, 2, -1, 1, +0, -1, 1, -3, 4, -3, 1, -1, +1, 0, -1, -2, 3, -3, 2, -3, +4, -2, 1, -2, 2, 0, -2, 2, +0, -1, -1, 3, -4, 3, 0, 0, +1, -1, 0, 1, -3, 1, 0, 0, +0, -1, 2, -1, -1, 1, 0, 0, +1, -2, 0, 1, -1, -1, 4, -3, +-1, 4, -5, 3, -1, 0, 1, -2, +4, -2, -1, 1, 0, 0, -2, 2, +-1, 1, 0, -2, 4, -2, -1, 2, +-2, 1, 2, -3, 4, -4, 5, -4, +3, -2, 2, -1, 0, 0, 1, -1, +0, 0, 2, 0, -2, 2, -1, 1, +1, -2, 3, -1, 1, -2, 1, 0, +-3, 3, -3, 2, 0, 0, -2, 2, +-2, 3, -2, 0, 2, -1, -1, 2, +-3, 4, -5, 3, 0, -1, 0, 0, +1, -2, 2, -2, 1, 0, 0, -1, +2, -3, 3, -2, 0, 0, 1, -1, +0, 1, -3, 5, -6, 4, 1, -1, +1, -2, 1, 0, 0, -3, 5, -3, +2, -2, 2, -1, -1, 0, 0, -1, +1, 0, 0, -1, 0, 2, -1, -2, +4, -2, 0, -1, 4, -4, 1, -1, +1, 0, -2, 2, -1, 0, 1, -1, +-1, 2, -2, 1, 0, -1, 3, -4, +3, -2, 1, 1, -1, 0, 3, -1, +-2, 3, -3, 5, -4, 2, 0, 2, +-5, 5, -1, 0, 1, -1, 0, 1, +-2, 1, 1, -1, 1, 1, -2, 2, +-1, 2, -2, -1, 3, -2, 0, 0, +0, 2, -3, 1, 2, 0, -1, 1, +-2, 3, -3, 1, 2, -3, 4, -4, +2, -1, 0, 1, -3, 2, 1, 0, +-2, 2, -3, 4, -3, 1, 2, -1, +-1, 0, 0, 0, 1, -3, 3, -1, +-3, 3, -2, 2, 1, -3, 4, -4, +5, -4, 1, -1, 2, -1, 0, -1, +2, 0, -1, -1, 2, 0, -2, 1, +2, -3, 3, -2, -1, 3, -3, 2, +-1, 1, -1, 2, -3, 2, 0, 0, +0, -1, 1, -1, -1, 0, 2, -2, +2, -3, 2, 0, -3, 2, -1, 1, +0, -1, 0, 1, -2, 3, -4, 3, +-2, 1, -1, 1, -2, 4, -5, 5, +-4, 4, -4, 3, -1, 3, -4, 1, +5, -5, 2, -1, 1, 0, -1, -1, +3, -4, 4, -3, 1, -2, 3, -4, +3, -1, -1, 2, -3, 3, -1, 0, +2, -4, 5, -2, -2, 1, 0, 0, +-2, 1, 0, 1, -3, 4, -5, 5, +-5, 3, -1, 1, 0, 0, -1, 0, +0, 1, -4, 3, -1, 2, -1, -1, +6, -6, 5, -4, 3, 0, -2, 2, +-1, 2, -1, -1, 4, -3, 0, 1, +-2, 3, -2, 2, 0, -1, 2, -1, +-1, 0, 0, 2, -2, 0, 3, -3, +1, -1, 2, -1, 0, -2, 2, 0, +-1, 1, -1, 2, -2, 2, -1, -1, +1, 0, -3, 2, 1, -1, -1, 0, +1, 0, -1, 0, 0, 2, -5, 4, +1, -3, 4, -4, 3, -2, 2, -2, +2, -2, 2, -1, -1, 2, 0, 0, +0, -1, 0, 1, -2, 2, -2, 3, +-2, 1, 0, 2, -5, 4, -1, 0, +-1, 1, -1, 2, -2, 2, -1, 0, +3, -3, 0, 2, -3, 4, -4, 4, +-4, 4, -4, 3, -2, 2, -2, 0, +1, 2, -4, 3, -1, 1, -1, 1, +-1, 1, 1, -1, 1, 0, 0, 0, +-2, 2, 0, 0, 0, 1, 1, -1, +2, -3, 2, 0, -1, 1, -1, 1, +0, -1, 1, 1, -2, 1, 1, -1, +2, -3, 3, -3, 1, 0, 0, -2, +4, -3, 1, -1, 3, -3, 3, -3, +3, -3, 2, -2, 1, 0, 0, -1, +1, 1, -4, 2, 0, 0, -2, 2, +0, -2, 5, -3, 1, -2, 4, -3, +3, -3, 4, -3, -1, 1, 0, 0, +1, -2, 4, -3, 3, -4, 5, -3, +-1, 2, -2, 1, -1, 0, 0, 0, +1, -1, -1, 0, 1, 0, -2, 1, +1, -1, 0, 1, -1, 2, -3, 2, +-1, 2, -3, 1, 1, 0, -1, 0, +2, -2, 1, 0, -3, 4, 0, -2, +4, -3, 2, -2, 2, -2, 1, 1, +-3, 3, -2, 2, -1, -1, 2, -1, +1, -2, 2, 0, -3, 3, 0, 0, +1, -1, -1, 1, -1, 2, -4, 4, +-4, 4, -3, 1, 2, -2, 2, 0, +-2, 4, -6, 5, -1, 1, -4, 4, +-4, 3, -2, 0, 1, -1, 0, 1, +-2, 2, 0, -1, 1, -1, -1, 1, +-1, 0, 0, 1, -1, -1, 1, 0, +-2, 2, -1, 1, -2, 1, 1, -1, +1, -2, 2, -3, 4, -4, 3, -2, +-1, 1, -2, 1, 0, 0, 0, -1, +1, 0, -2, 1, 1, -1, 1, -1, +1, -1, 0, -1, 0, 0, -2, 1, +0, -1, 2, -1, 0, 1, -1, 1, +-3, 4, -4, 4, -4, 2, -1, 1, +-1, 0, 1, -1, 1, -2, 5, -5, +4, -2, -2, 5, -6, 4, 0, -2, +1, -1, -1, 0, -1, 2, -4, 3, +-2, 4, -4, 4, -1, 1, 0, -1, +2, 0, -4, 3, -1, 0, 1, -2, +3, -2, 0, 0, 2, -2, 1, 1, +-2, 1, 0, 1, -2, 0, 3, -4, +1, -1, -1, 1, 0, -1, 1, 1, +-1, 2, 0, 1, 1, -2, 5, -5, +3, -3, 3, -4, 0, 1, -3, 2, +-1, 2, -4, 4, -2, 3, -2, 2, +2, -3, 3, -3, 0, 1, -3, 1, +-1, 1, -3, 2, -1, 2, -1, 2, +0, 0, 2, -1, 0, 0, 0, -1, +-2, 1, -3, 1, -2, 1, -1, 3, +-4, 4, -1, 1, 2, -2, 0, 2, +-2, 1, 0, 0, -2, 1, -2, 0, +1, -2, -1, 2, -2, 2, 2, -2, +3, 0, -2, 3, -4, 4, -2, -2, +3, -4, 1, -1, 1, -2, 4, -4, +5, -3, 3, -1, 2, 0, -1, 3, +-2, 1, -2, 2, -4, 2, -1, 0, +0, -1, 3, -2, 3, -2, 5, -3, +2, 0, 0, 1, -2, 1, -2, 1, +-3, 2, -2, 1, -1, 2, -2, 3, +0, 2, 1, -1, 3, -1, -1, 1, +-3, 2, -5, 4, -4, 2, 0, -2, +2, 0, 0, 1, 1, 1, 2, -1, +2, 0, -2, 2, -3, 1, -1, -1, +-1, 0, -3, 4, -4, 3, 1, 1, +1, 1, -1, 3, -3, 3, -3, 2, +-4, 2, -2, 0, -2, 0, 0, -1, +3, -1, 2, -1, 4, -2, 3, -2, +1, 2, -6, 4, -4, 1, -5, 4, +-5, 3, 0, -2, 4, -1, 0, 3, +-1, 2, -2, 3, -5, 4, -3, 1, +-2, -2, 0, 0, -4, 3, -1, 2, +-1, 3, -3, 6, -3, 4, -3, 4, +-4, 1, -2, -1, 0, -2, -2, 1, +-1, 0, 1, 1, 1, 1, 1, 1, +-1, 3, -4, 4, -5, 3, -3, -1, +0, -3, 2, -4, 3, -1, 0, 2, +3, -2, 4, 0, -3, 5, -3, 1, +-3, 2, -5, 2, -5, 2, -2, 0, +-2, 4, -3, 4, 1, 1, 3, -1, +2, -1, -1, 1, -5, 2, -3, 0, +-3, 1, -1, 1, 0, 2, 0, 1, +5, -3, 4, -2, 3, -2, -1, 0, +-4, 2, -5, 2, -2, 0, 3, -4, +4, -1, 4, -2, 6, -2, 2, 0, +0, 0, -2, 1, -5, 2, -5, 2, +-1, -1, 1, 1, 1, 2, 2, 2, +0, 1, 0, 2, -3, 1, -4, 2, +-5, 0, 1, -4, 1, -1, 1, 1, +3, -1, 4, -1, 2, 1, -2, 2, +-2, 1, -5, 2, -3, -1, -3, 2, +-3, 4, -2, 3, 3, 0, 3, 0, +1, 1, -1, 0, -2, 0, -3, -1, +-1, -2, -1, -1, 2, -2, 4, -1, +3, 1, 2, 1, 1, 0, -1, 1, +-5, 1, -2, 0, -3, 0, -2, 1, +1, -1, 5, -1, 3, 2, 2, -1, +1, 1, -3, 1, -3, 0, -3, -2, +-1, 0, -1, -1, 5, -3, 6, -2, +3, 2, 0, 0, 1, -1, -1, -1, +-3, 0, -4, 0, -3, 1, 0, 0, +1, 1, 6, -3, 5, -1, 1, -1, +1, -2, -4, 3, -6, 0, 0, -4, +2, -2, 2, 0, 3, 0, 4, 0, +4, -1, -1, 4, -6, 2, -5, 0, +-3, -1, -6, 4, -2, 0, 3, 0, +3, 1, 4, -1, 4, 0, -2, 3, +-3, -1, -2, -2, -2, -2, -1, -1, +-1, 1, 2, 1, 5, -2, 6, -1, +3, -2, 2, -4, 3, -6, -2, 0, +-6, 1, -1, -1, 2, -1, 6, -3, +7, -2, 4, 0, 0, 0, 2, -4, +-1, 0, -6, 1, -3, 0, -2, 1, +1, 1, 4, -1, 3, 3, 1, 1, +-1, 2, -4, 0, -3, -1, -2, -3, +-1, 0, 0, 0, 3, 0, 5, -1, +4, 0, 2, 0, 0, -1, -2, -1, +-5, 0, -2, -3, 2, -4, 3, -1, +3, 1, 3, 3, -1, 5, -2, 2, +-2, -2, -1, -3, -2, -2, -4, 1, +-4, 3, -2, 4, 3, 0, 7, -2, +3, 3, -4, 3, -1, -2, -4, 0, +-5, 1, -4, 1, 2, -4, 6, 0, +2, 4, 1, 2, 4, -4, 2, 0, +-4, -1, -4, 0, -5, 0, 0, -2, +2, 0, 2, 2, 5, -2, 5, 1, +1, 1, -4, 3, -7, 2, -6, 0, +-4, 1, -3, 2, 2, -2, 8, -4, +9, -3, 5, -2, 3, -2, 0, -2, +-5, 2, -5, -2, 0, -2, 3, -3, +5, -1, 6, -2, 6, 0, 2, 1, +-1, 1, -5, 1, -7, 1, -1, -6, +4, -5, 4, -2, 4, 0, 5, 0, +6, -2, 5, -2, -2, 1, -3, -3, +-1, -5, 0, -5, 2, -1, -1, 4, +-1, 5, 2, 3, 1, 3, 1, -2, +-1, 0, -8, 3, -8, 3, -8, 3, +-1, 0, 3, 1, 4, 0, 7, -1, +3, 1, -1, 1, -4, 0, -5, 0, +-4, -1, -5, 5, -3, 1, 5, 0, +5, 0, 4, 1, 4, -2, -2, 4, +-10, 5, -10, 4, -8, 2, -1, -2, +5, -2, 6, -1, 7, -1, 2, 2, +3, -2, -3, 1, -8, 3, -8, 1, +-3, -2, 1, -1, 4, -1, 8, -3, +7, 0, 2, 2, -1, 0, -2, 0, +-9, 5, -9, 2, -6, 3, -2, 1, +4, -1, 9, -4, 10, -4, 6, -3, +1, -1, -4, 0, -8, 4, -8, 0, +-2, 0, 3, -1, 4, 3, 4, -1, +6, 0, 0, 2, -1, -2, -2, -3, +-5, 0, -4, -1, 0, 0, 3, -1, +6, 0, 5, 0, 4, 0, 2, 0, +-5, 2, -6, -1, -3, -3, -4, 3, +-2, 1, 5, 0, 5, 1, 4, 1, +4, -3, 2, -1, -4, -1, -5, -1, +-3, -3, -2, 1, -1, 2, 4, -1, +10, -5, 8, -1, 1, 1, -3, 1, +-5, 0, -7, 0, -3, -2, -1, 0, +4, -2, 5, 2, 4, 1, 4, 1, +-1, 2, -6, 3, -6, -1, -5, 0, +-5, 1, -2, 3, 2, 1, 5, 1, +4, 1, 4, -1, -2, 2, -5, -1, +-5, -1, -3, -4, 0, 0, -1, 2, +4, 0, 4, 3, 1, 4, 0, 0, +-1, 1, -7, 2, -7, 2, -6, 1, +-3, 2, 2, -2, 5, 2, 5, 0, +5, -1, 2, -1, -2, -1, -4, -2, +-3, -3, -1, -1, -3, 3, 3, 0, +5, 1, 6, -1, 5, -1, 1, 0, +-6, 2, -6, -1, -6, 2, -5, 1, +2, -2, 5, -1, 8, -2, 5, 2, +1, 0, 0, -2, -2, -3, -5, -1, +-3, -2, 0, -2, 5, -3, 5, 2, +4, 1, 3, 1, 2, 0, -5, 4, +-7, -1, -3, -2, -4, 0, -1, 2, +-1, 4, 2, 3, 5, -1, 4, 1, +0, -2, -1, -2, -4, -2, -4, -1, +-2, -2, 4, -3, 3, 3, 2, 3, +4, 2, 1, 0, 1, -2, -3, -1, +-5, 1, -7, 0, 0, -2, 3, -1, +6, -1, 7, 0, 1, 5, -2, 3, +-5, 3, -6, -1, -4, -2, -1, -3, +0, 0, 4, -2, 8, -3, 10, -5, +7, -2, 2, -2, -3, 1, -4, -3, +-4, 0, -6, 3, -3, 1, 7, -5, +10, -3, 6, 0, 2, 1, -3, 2, +-6, 1, -5, -2, -4, 1, -4, 1, +3, -1, 5, -1, 8, -3, 5, 2, +-2, 4, -5, 3, -6, 0, -4, 0, +-6, 1, 0, -1, 5, -3, 8, -1, +7, -3, 4, 2, -1, -1, 0, -2, +-3, -2, -6, 2, -5, 0, 1, -1, +4, -1, 3, 3, 2, 3, 1, 1, +-2, 2, -8, 3, -5, -2, -2, -4, +3, -5, 3, -1, 5, -1, 8, -3, +6, 0, 1, -1, 2, -4, -3, 0, +-7, 2, -5, 2, -4, 3, 3, -1, +6, 0, 6, 0, 5, -1, 2, -1, +-3, 1, -6, 1, -8, 4, -7, 2, +-1, 0, 3, -1, 6, -1, 6, -2, +3, 1, -2, 0, -5, 1, -7, 0, +-6, 2, -4, 0, 0, 2, 2, 1, +5, 1, 3, 1, -1, 4, -5, 2, +-6, 3, -8, 3, -6, 2, -3, 3, +-1, 3, 3, 3, 3, 1, 5, 1, +-1, 1, -2, 1, -5, 0, -6, 2, +-4, -1, 2, -1, 3, 1, 2, 3, +4, -1, 2, 0, 1, -3, -4, 2, +-7, -1, -4, -2, 0, -3, 0, 2, +2, -1, 7, -3, 9, -6, 6, -2, +-1, 0, -2, -2, -4, 1, -5, 3, +-3, 2, 2, 0, 7, -2, 5, 2, +4, -2, 6, -3, 1, -3, 0, -4, +-3, 0, -6, 4, -3, 2, 3, -1, +4, 1, 3, 0, 2, 0, 0, -2, +-3, 0, -4, -2, -4, 0, -3, -1, +1, -2, 6, -5, 5, 2, 0, 1, +4, -3, 1, -2, -3, 1, -4, 0, +-5, 2, -1, 0, 0, 3, 3, 1, +4, 1, 5, -2, 5, -3, 1, -1, +-1, -4, 3, -6, 2, -4, 4, -4, +3, 1, 4, 0, 3, 2, -1, 3, +-1, 0, -4, 2, -5, -2, -2, -4, +3, -8, 5, -3, 2, 0, 2, 1, +3, -1, 2, 0, -2, 0, -3, -1, +-3, -1, -4, 1, 0, -2, 2, 1, +1, 3, 1, 4, 2, 1, 0, 3, +-2, 0, -3, 1, -4, 0, 0, -2, +2, -1, 2, 1, 4, -1, 6, -2, +5, -2, -1, 3, -3, 0, -2, -2, +-3, 1, -4, 1, -1, 1, 1, 0, +3, 0, 2, 0, -2, 3, -3, -1, +0, -3, -3, 0, -6, 2, -1, -3, +1, 1, 0, 2, 2, 2, 2, -1, +3, -1, 0, -1, 0, -4, 3, -4, +-2, 3, -3, 3, 2, -1, 5, 0, +3, 2, 1, 2, -3, 4, -4, 0, +-1, -2, -2, -1, -1, 0, -1, 2, +-2, 5, -1, 2, 5, -5, 7, -6, +4, -3, -5, 3, -6, 0, -3, -1, +-2, -2, 1, 0, -1, 2, 3, -1, +4, -2, 1, 0, 0, -2, -2, 1, +-4, -1, 1, -2, -1, 1, 3, -1, +5, 0, 3, 1, 5, -1, -1, 4, +-1, -1, -1, 0, 0, -2, 1, -1, +3, -3, 6, -3, 4, 1, -1, 3, +1, 0, 0, 0, -3, 1, -5, 1, +-5, 1, -5, 2, -3, 0, 1, -1, +1, 0, 2, -2, 0, 0, -2, 0, +-4, 1, -4, 0, -3, 1, -4, 3, +-2, 1, 3, -1, 3, 1, 3, -1, +2, 0, 2, -1, -2, 5, -5, 4, +-1, 3, 0, 2, 2, 2, 3, 0, +5, 0, 2, 1, 1, 0, 1, -2, +-1, 0, -4, 1, -4, 1, -2, 0, +-2, 1, -1, 1, -3, 2, -4, 3, +-7, 3, -5, 0, -5, 1, -6, 1, +-3, -2, 1, -2, 2, 0, -1, 3, +3, -4, 6, -2, 1, 0, 1, 0, +1, -1, 4, -3, 6, -3, 5, -1, +7, -2, 7, -2, 7, -1, 1, 2, +1, 0, 1, -1, 4, -5, 2, -1, +0, -2, 1, 0, -2, 1, -1, 0, +-2, -1, -3, 0, -7, 2, -7, 1, +-6, 0, -4, -1, -3, -1, -2, 0, +-3, 3, -3, 2, -1, 2, -2, 1, +0, 1, 0, 1, 1, 0, 4, -1, +2, 3, 6, -1, 5, 4, 2, 3, +5, 1, 4, -1, 3, 1, 0, 2, +0, 2, -1, 2, -2, 2, -1, 0, +1, -2, -3, 2, -8, 4, -6, 0, +-8, 1, -7, -2, -3, -5, -2, -2, +-8, 3, -3, -4, 2, -3, -2, 0, +-3, 3, -6, 5, -4, 3, -2, 3, +0, 1, 3, 0, 8, -2, 7, 2, +7, 2, 5, 4, 5, -1, 11, -5, +9, -3, 5, -1, 4, 0, 0, 4, +-1, 2, 1, 0, 1, -1, -2, 1, +-5, 0, -7, 0, -6, -3, -5, -2, +-10, 2, -13, 5, -10, 2, -6, -1, +-3, -2, -4, 1, -4, -1, -2, 0, +-5, 3, -2, 0, 3, 2, 1, 4, +7, -1, 9, 0, 7, 3, 9, 0, +8, 1, 9, -3, 9, 0, 6, -2, +9, -3, 7, -1, 5, 0, 1, 2, +-2, 3, -4, 1, -5, -1, -7, -1, +-10, 1, -12, 1, -11, 0, -9, -1, +-9, 1, -10, 1, -9, 2, -10, 3, +-9, 3, -8, 2, -4, 0, 0, 0, +-1, 4, 2, 3, 6, 2, 9, 0, +12, -1, 12, -1, 8, 4, 5, 3, +9, 0, 10, 0, 10, -2, 10, -2, +8, -1, 4, 1, 2, -2, 0, -1, +-5, -1, -8, 1, -13, 3, -14, 2, +-12, 0, -12, 2, -14, 2, -11, -1, +-6, -6, -5, -5, -7, -3, -6, -2, +-2, -3, -3, 3, -2, 3, 5, -1, +11, -1, 10, 0, 12, 0, 10, 3, +8, 3, 9, 2, 13, -3, 16, -1, +12, 1, 14, -3, 10, 2, 2, 4, +0, 0, -2, 0, -8, 2, -8, -2, +-8, -2, -9, -1, -11, 0, -9, -5, +-8, -3, -13, -1, -14, 1, -16, 0, +-12, -2, -9, -1, -5, -2, 2, -4, +5, -1, 5, 1, 8, 0, 11, -1, +10, 1, 10, 0, 14, -2, 16, -1, +16, 0, 17, -1, 17, 0, 15, 0, +13, -3, 10, -3, 6, -3, 0, -1, +-4, -1, -7, 0, -11, 1, -8, -2, +-10, -1, -13, 0, -16, 0, -19, 2, +-18, -1, -17, 0, -14, -2, -11, 0, +-6, -2, 0, -3, 4, -3, 6, -1, +8, -3, 10, -2, 11, -2, 15, -3, +17, -3, 20, -3, 22, -3, 23, -2, +19, 1, 14, 2, 9, 3, 8, -2, +4, 0, -1, 1, -1, -4, -1, -3, +-7, 1, -11, 3, -14, 2, -17, 0, +-21, 3, -25, 3, -24, 1, -18, -2, +-16, 2, -17, 4, -12, 4, -4, -2, +1, -1, 0, 1, 3, 0, 5, 0, +9, 0, 11, 2, 15, 1, 21, 1, +21, 1, 25, -2, 22, -1, 18, -2, +13, 1, 8, 0, 5, 2, 1, 1, +1, 0, 0, -2, -3, -1, -9, 1, +-13, -1, -18, 0, -23, 1, -24, 0, +-23, -1, -19, -2, -15, -1, -15, 2, +-12, 1, -9, 1, -6, 0, -5, 3, +-3, 2, 5, -2, 9, 1, 13, 0, +22, -4, 25, 0, 24, -1, 26, -3, +21, 0, 16, 0, 14, 0, 9, 3, +7, 1, 8, 0, 6, -1, 4, -3, +0, -3, -11, 3, -19, 1, -18, -3, +-23, 2, -27, 4, -24, 2, -22, 3, +-20, 3, -17, 0, -12, -1, -13, 2, +-15, 5, -9, 0, 0, -2, 4, -1, +13, -3, 18, 0, 18, 3, 22, -1, +24, 0, 20, 1, 19, -1, 20, -3, +19, -2, 17, 0, 13, 1, 14, -3, +11, -1, 1, 1, -2, -3, -8, -3, +-15, -1, -19, -1, -22, 0, -22, 1, +-20, -2, -15, -5, -16, -1, -19, 1, +-20, 2, -17, -1, -11, -3, -6, -2, +-3, 2, 3, 1, 11, 0, 15, 3, +15, 5, 18, 2, 19, 3, 15, 4, +18, 0, 21, -2, 23, -3, 21, 1, +17, 1, 14, 2, 6, 2, 0, 3, +-7, 1, -10, -1, -15, 0, -18, 1, +-21, 2, -19, -1, -17, -2, -18, -2, +-19, -1, -24, 2, -23, 0, -19, -1, +-15, 0, -8, -1, -1, 0, 4, 2, +8, 3, 11, 3, 15, 1, 17, -1, +19, -2, 20, -1, 22, -1, 24, 0, +23, 1, 22, 1, 20, 0, 16, 0, +7, 2, 2, -1, -4, -1, -10, 1, +-12, 0, -14, -1, -14, 0, -19, 2, +-19, -1, -21, -1, -25, 0, -24, -3, +-23, -1, -20, -1, -14, -2, -6, -3, +1, -2, 4, 2, 3, 4, 8, 0, +12, 0, 12, 1, 15, 0, 20, 0, +24, -2, 28, -2, 29, -2, 25, 1, +19, 1, 16, -4, 13, -4, 2, 2, +-4, 1, -5, 0, -7, 0, -11, 3, +-13, -1, -15, 1, -24, 4, -27, 1, +-25, -3, -22, -4, -21, -2, -20, 1, +-15, 1, -10, 4, -8, 4, 0, -2, +8, -5, 8, -3, 10, -3, 13, -1, +15, 1, 20, 1, 24, 0, 28, -1, +27, -2, 25, -1, 18, 1, 12, 0, +10, -1, 4, 2, -2, 4, 1, -4, +3, -5, -5, 2, -14, 3, -18, 1, +-22, 1, -24, -2, -23, -3, -23, -1, +-21, 1, -19, 3, -16, 3, -11, 2, +-9, 2, -6, 0, -2, -1, 2, -1, +6, -2, 15, -4, 20, -3, 26, -5, +27, -1, 24, 1, 23, 1, 17, 3, +14, 0, 15, -3, 14, -3, 9, 0, +6, 2, 2, 1, 1, -1, -5, 0, +-10, -1, -16, 0, -21, -1, -21, -3, +-20, -3, -20, 0, -20, 3, -18, 2, +-13, -2, -10, -2, -10, -1, -7, -3, +-1, -6, 2, 0, 4, 0, 14, -2, +18, 0, 20, 1, 22, -1, 22, -1, +20, -1, 19, -3, 18, -3, 15, 1, +12, 1, 10, 2, 8, 2, 7, -2, +4, -2, -4, -1, -11, 0, -17, 0, +-17, -3, -17, -2, -18, 1, -20, 3, +-15, -3, -11, -4, -13, -1, -13, 0, +-17, 4, -13, 0, -4, -4, 4, -3, +5, 3, 8, 2, 15, 1, 17, -1, +18, 0, 17, -1, 17, -1, 16, -1, +17, -2, 19, -4, 19, -1, 14, 1, +12, -2, 8, -2, 1, -1, -6, 0, +-9, -1, -14, 2, -15, -1, -13, 0, +-17, 4, -17, 3, -16, 0, -15, 0, +-19, 2, -19, 1, -16, 1, -13, 3, +-9, 4, -3, 3, 5, 0, 7, 3, +6, 5, 8, 4, 10, 2, 11, 3, +10, 3, 14, 1, 17, -1, 20, -2, +17, 2, 11, 3, 8, 4, -1, 5, +-2, -1, -4, 0, -8, 1, -9, 0, +-9, -1, -7, -3, -7, -3, -12, -1, +-13, -4, -14, -1, -17, -1, -15, 0, +-16, 1, -8, -2, -4, 0, 0, 0, +4, -1, 7, -1, 8, 0, 6, 1, +7, -1, 14, -5, 18, -3, 18, -1, +19, -1, 17, 0, 15, 0, 11, 0, +9, -2, 5, -1, 1, -1, 0, -1, +-5, 2, -3, -4, -1, -3, -6, 1, +-11, 2, -12, -3, -13, -3, -15, -3, +-15, -1, -13, -3, -6, -3, -4, 1, +-6, 3, -5, 4, -5, 4, -4, 5, +-2, 4, 3, 1, 6, 1, 8, 3, +8, 4, 12, 0, 18, -1, 15, 0, +15, -3, 11, 1, 1, 4, 1, -1, +4, -1, 1, 2, 0, 1, 0, -1, +-1, -3, -3, -4, -7, -2, -13, 1, +-14, 0, -13, 1, -15, 0, -11, -1, +-8, -2, -2, -3, 0, -2, -3, 0, +-2, -1, 1, -3, 0, 0, 0, 2, +5, 2, 9, 2, 12, 1, 14, -3, +15, -4, 14, -4, 10, 1, 5, 3, +4, 2, 6, -3, 7, -3, 5, -2, +4, -1, -1, 3, -5, 5, -8, 2, +-10, -2, -9, -4, -9, -3, -6, -4, +-6, -1, -6, 1, -6, -1, -2, -7, +-2, -5, -6, 0, -4, 2, -5, 3, +0, -2, 4, -3, 6, -2, 12, -5, +14, -2, 9, 4, 6, 2, 8, -2, +6, -2, 5, -2, 8, -3, 11, -2, +10, 0, 7, -2, 6, -5, 2, -4, +-1, -2, -3, -1, -4, -1, -8, 3, +-9, 1, -8, -1, -8, -1, -8, 4, +-8, 5, -9, 5, -12, 3, -11, 1, +-5, -4, 0, -3, 0, 2, 1, 5, +6, 0, 8, -4, 6, -3, 6, -3, +8, -2, 7, 1, 4, 4, 3, 2, +6, -2, 6, -1, 5, 3, 1, 5, +4, -1, 3, -1, -3, -1, -4, -4, +-4, -2, -2, 0, -2, 3, -3, 1, +-6, -1, -5, -3, -7, -2, -6, -2, +-7, 4, -7, 4, -3, 1, -4, -2, +-1, -3, 4, -2, 4, 3, 4, 0, +7, -3, 6, -5, 7, -9, 8, -6, +4, 4, 5, 4, 7, 4, 4, 1, +5, -4, 5, -7, 6, -5, 3, 2, +0, 3, 2, -4, 2, -6, 1, -6, +-1, -2, -3, 2, -6, 7, -6, 5, +-6, -1, -9, -2, -8, -2, -5, 4, +-5, 7, -4, 7, -3, 3, 1, -4, +1, -6, -1, -1, -2, 6, -1, 7, +3, 0, 5, -4, 6, -5, 4, -2, +6, 1, 2, 9, 0, 6, 3, -2, +3, -8, 4, -6, -1, 1, 1, 2, +3, 4, -1, 7, -5, 0, -6, -3, +-7, 1, -7, 6, -5, 4, -1, -1, +0, -3, 0, -7, 1, -8, 0, -1, +-2, 7, -2, 8, -3, 1, 0, -8, +0, -5, 0, -3, 5, 0, 4, 6, +2, 6, 5, -5, 5, -7, 2, -5, +2, 0, 2, 4, 3, 5, 2, 1, +0, -5, 3, -9, 3, -1, 0, 7, +-1, 5, 1, -2, 0, -2, -5, -4, +-6, -3, -5, 5, -4, 10, -2, 7, +-2, -2, -1, -8, -1, -6, -3, 1, +-5, 7, -5, 10, -2, 3, 1, -5, +1, -9, 2, -3, 0, 6, 1, 9, +0, 7, -2, 1, -2, -6, -1, -5, +2, -1, 5, 6, 4, 3, 7, -5, +8, -11, 4, -10, 0, -6, 3, 1, +3, 7, 1, 3, 1, -7, -1, -8, +0, -6, 1, 1, -4, 9, -5, 10, +-2, 0, -1, -9, -2, -9, -4, 1, +-1, 7, 0, 10, -3, 5, 0, -6, +3, -12, 3, -8, 1, 3, 0, 9, +0, 8, 1, -1, 0, -5, 1, -9, +3, -2, 3, 8, 3, 9, 2, 0, +1, -8, 2, -10, 1, -2, 1, 2, +-1, 12, -5, 10, 1, -2, -3, -8, +-6, -7, -1, 1, 0, 7, 4, 2, +-2, 2, -4, -6, 2, -12, 1, -5, +-5, 10, -3, 11, 3, 2, 2, -8, +1, -13, 2, -8, 2, 2, 2, 13, +-3, 14, -5, 4, 0, -9, 3, -9, +2, -2, -1, 9, -1, 10, 2, 7, +-1, -3, -3, -9, -3, -4, 0, 7, +1, 11, -2, 5, -1, -4, -2, -6, +-3, -7, -4, -1, -2, 7, 1, 12, +-3, 5, -7, -5, -6, -9, -1, -5, +4, 2, 1, 9, -1, 6, 0, -3, +2, -12, 2, -9, 0, 2, 0, 10, +4, 7, 4, 2, -1, -8, 2, -14, +5, -3, 5, 7, 4, 9, 0, 3, +2, -6, 2, -9, -2, -7, 0, -2, +1, 13, 1, 10, 2, -5, -2, -14, +-2, -10, 0, 0, -3, 10, -5, 9, +-3, 5, 1, -9, 3, -16, 1, -10, +-1, 7, 0, 13, 1, 9, 0, -5, +1, -12, 4, -14, 7, -1, 2, 10, +2, 9, 3, 0, 8, -12, 5, -11, +-3, -3, 0, 6, 1, 17, -2, 12, +-5, -4, -2, -14, 5, -11, 7, -1, +0, 8, -5, 11, -1, 3, -2, -8, +-2, -16, -4, -4, 0, 8, 3, 10, +2, -1, -2, -6, -1, -12, 3, -7, +-3, 6, -5, 14, 3, 5, 7, -4, +2, -9, -3, -7, 0, -2, 6, 9, +6, 11, 1, 5, -3, -9, 5, -15, +7, -5, 0, 7, -1, 9, 3, 7, +4, -1, 0, -14, -4, -13, -1, 0, +0, 16, -6, 13, -6, 0, -5, -8, +2, -12, 2, -9, -4, 7, -5, 14, +2, 5, 4, -8, -3, -12, -5, -7, +2, 2, 7, 9, 1, 13, -3, 1, +5, -14, 9, -14, 2, 0, -2, 9, +2, 10, 10, 1, 4, -2, -5, -11, +-1, -8, 3, 6, 3, 12, -2, 6, +-4, -3, -1, -9, 1, -9, -6, 0, +-10, 13, -3, 15, 1, 5, -5, -8, +-9, -12, -2, -4, 2, 5, -3, 12, +-6, 9, 0, -2, 5, -13, 4, -12, +-2, 2, -3, 14, 5, 10, 3, 5, +-2, -9, 2, -14, 8, -8, 8, 9, +0, 14, -4, 9, -1, -3, 4, -10, +0, -9, -7, 3, -3, 11, 3, 13, +1, -2, -4, -14, -2, -12, 4, -3, +3, 5, -9, 13, -11, 9, -1, -4, +1, -14, -3, -10, -5, 6, 3, 12, +5, 9, -4, 2, -7, -8, 5, -13, +8, -4, 2, 10, -4, 14, 7, -2, +12, -8, 4, -10, -1, -5, 0, 4, +6, 11, 5, 6, -1, -5, -1, -15, +3, -7, 2, 3, -6, 11, -7, 9, +-1, 5, 0, -5, -7, -12, -8, -8, +-3, 10, -1, 15, -6, 8, -7, -6, +1, -11, 8, -12, 5, -3, -4, 10, +-2, 11, 8, -2, 6, -12, 1, -12, +3, -4, 10, 4, 10, 10, -1, 8, +-1, -6, 7, -14, 9, -9, 0, 4, +-2, 7, 2, 8, 6, 0, -1, -5, +-9, -11, -2, -4, 3, 9, -2, 11, +-7, -2, -5, -5, 0, -9, 0, -6, +-7, 1, -7, 13, 3, 6, 6, -5, +-4, -11, -5, -8, 4, 0, 6, 9, +-2, 11, -3, 5, 6, -8, 12, -12, +2, -2, -4, 6, 4, 8, 8, 5, +4, -1, -5, -6, -3, -9, 9, -3, +4, 12, -6, 10, -7, 3, -1, -7, +0, -6, -9, -4, -10, 5, -4, 12, +1, 8, -2, -8, -8, -9, -4, -4, +1, 5, -1, 4, -6, 7, -1, 2, +5, -4, 2, -10, -1, -4, 2, 6, +12, 5, 11, 2, -1, -2, -2, -7, +6, -7, 8, 1, 1, 10, -4, 10, +3, -1, 9, -8, -2, -4, -8, -1, +-2, 5, 3, 10, -2, 3, -7, -8, +-3, -11, 0, -1, -2, 4, -10, 8, +-6, 4, 5, -2, 4, -11, -6, -10, +-5, -5, 7, 5, 7, 8, -5, 6, +-3, -5, 6, -7, 10, -8, 5, 1, +-2, 10, 2, 8, 10, -6, 8, -9, +-2, -5, 3, -3, 10, 5, 2, 11, +-6, 5, -4, -7, 4, -11, 2, -3, +-6, 3, -7, 6, 0, 5, 3, -3, +-3, -9, -10, -7, -4, 1, 4, 5, +-2, 5, -7, -1, -3, -1, 1, -3, +-1, -3, -2, 0, 3, 8, 9, 4, +5, -2, -1, -10, 1, -4, 7, 0, +9, 5, 1, 7, 1, 1, 10, -10, +8, -7, -4, 2, -9, 9, -2, 8, +5, 3, 0, -4, -5, -11, 0, -10, +2, 3, -5, 11, -11, 7, -6, -2, +4, -8, -1, -6, -8, -5, -6, 5, +2, 10, 4, 6, -6, 0, -8, -4, +1, -2, 5, 3, 1, 4, 0, 6, +6, 0, 10, -6, 4, -9, -1, 0, +6, 2, 11, 6, 4, 2, -2, -2, +-4, -6, 3, -7, 4, 1, -5, 9, +-5, 4, 2, 0, -2, -2, -10, -4, +-8, -6, 1, 2, 3, 8, -5, 2, +-7, -6, -2, -9, 8, -6, 1, 1, +-5, 6, -1, 7, 6, 2, 1, -5, +-7, -3, -1, 1, 9, 7, 10, 4, +2, 2, 2, -5, 9, -10, 11, -10, +1, 5, -7, 13, -4, 12, 1, -1, +-2, -4, -8, -6, 0, -3, 4, 5, +-4, 11, -10, 1, -3, -8, 1, -8, +-3, -1, -8, 3, -6, 8, 1, 6, +3, -1, -6, -7, -5, -7, 2, 4, +3, 8, -1, 6, -3, 3, 4, -3, +9, -10, 5, -6, -3, 8, 1, 12, +9, 2, 6, -5, -3, -5, -4, -1, +2, 3, 0, 10, -5, 8, -4, 3, +-1, -5, -1, -6, -7, -2, -6, 3, +1, 6, -3, 10, -8, -1, -9, -8, +-4, -4, -1, 6, -3, 7, -5, 6, +-1, 0, 3, -3, 0, -8, -2, -4, +3, 4, 9, 9, 6, 3, 1, -5, +2, -9, 5, -3, 3, 5, -2, 10, +-2, 10, 3, 0, 4, -7, -3, -6, +-4, 0, -1, 7, 0, 10, -5, 6, +-8, -4, -3, -12, 0, -5, -2, 4, +-6, 9, -3, 3, 1, 0, -2, -6, +-6, -7, -3, -5, 5, 6, 4, 9, +1, 1, -1, -7, 3, -8, 9, -5, +1, 5, -2, 11, -1, 12, 4, -2, +6, -13, 3, -11, 3, 1, 5, 8, +5, 6, -2, 2, -4, -5, -1, -8, +1, -5, -4, 6, -7, 11, -3, 7, +-3, 0, -6, -7, -6, -9, 0, -2, +3, 8, -2, 10, -4, -3, -2, -6, +-1, -4, -2, 1, -1, 4, 1, 10, +5, 5, 5, -5, 1, -13, 2, -7, +6, 4, 6, 10, 1, 7, -2, 3, +0, -5, 3, -6, -3, -1, -2, 6, +0, 10, 3, 2, -1, -6, -6, -10, +-1, -7, -1, 6, -2, 10, -4, 7, +-7, 0, -1, -12, 2, -9, -5, 0, +-5, 8, 2, 7, 6, 0, 1, -9, +0, -14, 3, -4, 1, 10, 0, 11, +-1, 5, 4, -4, 5, -6, -2, -5, +-1, 2, 2, 9, 5, 12, 0, 1, +-3, -7, -1, -12, 4, -5, 1, 8, +-6, 13, -2, 4, 2, -8, 3, -13, +-5, -5, -7, 3, -1, 8, 0, 8, +-2, 0, -4, -10, 0, -13, 4, -4, +2, 9, -3, 12, 0, 3, 2, -4, +1, -11, 2, -9, 2, 1, 8, 9, +8, 3, 6, -4, 1, -11, 5, -10, +2, 2, -4, 12, -1, 9, 1, 4, +2, -8, -1, -12, -1, -6, -1, 6, +-1, 12, -2, 6, 0, -7, -1, -13, +-2, -11, -1, 3, -5, 14, -4, 12, +-1, 0, 2, -9, 0, -11, -3, -4, +1, 6, 1, 13, 1, 7, 1, -6, +1, -10, 3, -8, 6, 1, 2, 11, +0, 11, 3, 0, 3, -12, 5, -16, +1, -3, 3, 6, 2, 13, -1, 4, +0, -8, 2, -17, 3, -10, -1, 3, +-4, 14, -5, 8, 0, -3, -1, -11, +-1, -11, -2, -2, 0, 10, 4, 8, +2, 2, -2, -9, 1, -13, 4, -5, +1, 5, 3, 9, 6, 5, 7, -6, +5, -14, -1, -8, -2, 6, -3, 17, +-1, 11, 4, -4, 4, -11, 2, -10, +0, -5, 2, 5, -2, 13, -2, 9, +-2, -7, -3, -12, -5, -8, -4, 6, +0, 11, -1, 11, -5, 2, -7, -6, +-2, -10, -1, -3, -1, 8, -2, 14, +4, 2, 6, -9, -2, -12, 1, -6, +3, 6, 3, 13, 0, 9, -1, 1, +1, -12, 4, -13, 1, -2, 0, 12, +3, 13, 2, 2, 0, -10, -1, -15, +0, -4, -4, 9, -5, 14, -3, 7, +0, -6, 5, -18, 0, -11, -2, 1, +-1, 11, 2, 10, -1, 0, -1, -13, +1, -14, 3, -5, 1, 10, -2, 14, +1, 9, 3, -8, 4, -13, -1, -11, +2, 3, 2, 14, 1, 11, 1, -1, +-2, -10, 1, -11, 2, -4, 1, 9, +0, 12, 1, 5, -2, -6, -7, -12, +-4, -7, -2, 7, 0, 14, -5, 12, +-5, 1, -6, -9, -4, -10, -3, 1, +-3, 11, 2, 12, 2, 0, 2, -9, +-3, -12, 2, -5, 2, 8, 0, 17, +1, 6, 2, -7, 4, -15, 2, -11, +4, 0, 2, 12, 4, 11, 3, 0, +0, -12, -2, -13, -1, -5, 2, 8, +1, 11, 0, 6, -1, -10, 4, -18, +-1, -8, -4, 7, -1, 14, -2, 10, +-1, -3, -1, -14, -1, -11, -4, 1, +-1, 14, 0, 16, -1, 7, -1, -10, +1, -15, 4, -9, 4, 4, 1, 17, +-4, 14, 1, -3, 1, -14, 1, -13, +2, 0, 3, 13, 2, 13, -2, -2, +2, -14, 3, -19, 5, -8, -1, 7, +-2, 16, 1, 7, 0, -6, -3, -15, +-6, -10, 1, 4, -1, 17, -4, 15, +-8, 2, 0, -14, 6, -15, 0, -1, +-4, 13, -3, 17, 5, 6, 0, -8, +-3, -16, 2, -12, 10, 3, 7, 14, +-1, 7, 3, -5, 4, -15, 5, -12, +-5, 0, -3, 13, 2, 13, 7, -1, +1, -14, -9, -11, 1, -6, 4, 9, +-2, 16, -11, 13, -4, -4, 1, -13, +-4, -10, -5, 2, -2, 15, 7, 12, +4, -3, -2, -14, -4, -14, 5, -2, +3, 11, -5, 18, -4, 8, 3, -7, +6, -15, -2, -11, -1, 6, 2, 18, +4, 14, -5, 0, -8, -14, 4, -16, +6, -1, 0, 13, -9, 19, -2, 5, +6, -14, 4, -20, -6, -6, -6, 10, +3, 14, 5, 5, -2, -6, -2, -18, +6, -13, 3, -2, 3, 12, -4, 15, +1, 3, 1, -10, -2, -17, 3, -8, +2, 11, 7, 15, 2, 7, -1, -6, +-4, -13, 2, -10, 2, 5, -2, 14, +1, 11, 2, -4, 5, -16, -3, -15, +2, -6, 2, 12, -1, 17, -2, 5, +-3, -13, 1, -19, 2, -10, 2, 8, +-3, 15, 1, 9, 2, -6, 4, -16, +-1, -12, -4, 1, 3, 11, 5, 14, +3, 3, -7, -7, -3, -14, 6, -6, +6, 8, -1, 16, -3, 9, 5, -7, +4, -17, -3, -9, -6, 4, 4, 15, +6, 12, -1, -2, -6, -14, -1, -15, +6, -2, -4, 13, -8, 16, -1, 2, +11, -13, 2, -17, -7, -9, -3, 8, +4, 18, 5, 10, -8, -3, -5, -15, +5, -14, 10, -2, -4, 13, -4, 13, +7, 4, 7, -12, -1, -15, -9, -7, +5, 10, 9, 15, 0, 9, -7, -11, +6, -20, 11, -11, -4, 8, -10, 14, +-4, 14, 7, 0, 1, -14, -8, -16, +-4, -5, 9, 9, 7, 13, -6, 6, +-10, -3, -1, -14, 8, -10, -6, 6, +-8, 18, -1, 16, 6, -2, -3, -11, +-12, -11, 6, -3, 11, 10, 5, 12, +-5, 0, 3, -13, 10, -18, 3, -5, +-6, 8, -2, 17, 4, 13, -2, -3, +-4, -17, -5, -12, 4, 1, 5, 13, +-5, 14, -7, 2, -1, -13, 5, -15, +-1, -6, -4, 13, -6, 20, 3, 6, +2, -10, -4, -14, -2, -9, 2, 6, +5, 15, -2, 11, 1, -4, 4, -16, +5, -13, -2, 1, -3, 14, -2, 18, +-2, 9, 1, -11, -1, -17, 1, -8, +3, 8, 1, 18, -7, 12, -5, -5, +1, -16, 4, -15, 2, 2, -7, 14, +-1, 13, 4, -2, 4, -13, -2, -18, +-2, -4, 2, 11, 3, 15, -4, 8, +-8, -6, 5, -15, 5, -7, 0, 3, +-4, 12, 4, 11, 4, 4, -7, -8, +-9, -11, 2, -4, 13, 9, 3, 12, +-4, 2, -2, -9, 5, -11, 0, -6, +-8, 5, -6, 17, 2, 10, 7, -5, +-8, -13, -10, -8, 2, 2, 6, 13, +-4, 10, -7, -1, 4, -10, 5, -11, +-1, -5, -9, 8, 5, 11, 12, 8, +-2, -2, -11, -11, -2, -9, 9, 8, +0, 14, -5, 9, -3, -1, 10, -12, +9, -15, -7, 1, -8, 13, 4, 15, +7, 3, -8, -7, -10, -11, 1, -6, +9, 4, -2, 11, -7, 7, 4, -7, +7, -13, -3, -8, -10, 1, 1, 9, +8, 9, 3, 3, -10, -7, 1, -18, +13, -7, 5, 7, -2, 12, -1, 1, +11, -8, 4, -12, -1, -8, -3, 4, +2, 13, 8, 6, 2, -3, -2, -12, +1, -13, 7, -2, -5, 13, -7, 14, +-4, 5, 2, -8, 1, -13, -5, -5, +-4, 7, -1, 11, 2, 8, -4, -3, +-3, -11, -3, -9, 2, 0, 2, 10, +-5, 14, -3, 3, 2, -10, 7, -14, +1, -5, -3, 9, 0, 13, 6, 5, +4, -8, -3, -11, 3, -10, 6, 3, +5, 8, -2, 6, 1, -4, 6, -12, +6, -13, -4, 0, -8, 10, 2, 12, +1, 6, -6, -2, -11, -9, -2, -2, +1, 6, 0, 8, -6, 7, -5, 1, +5, -7, -2, -6, -6, 0, -2, 9, +9, 9, 7, -1, -3, -10, -1, -12, +8, -3, 8, 6, -3, 8, -2, 5, +2, -1, 7, -10, -1, -11, -3, 0, +3, 11, 6, 8, -3, 1, -10, -10, +1, -8, 4, 0, -2, 9, -10, 8, +-2, 4, 4, -4, 1, -11, -7, -6, +-7, 6, 6, 11, 0, 9, -6, -2, +-5, -9, 8, -10, 8, 1, -3, 7, +-6, 11, 3, 2, 10, -6, -5, -7, +-4, -5, 4, 8, 5, 12, 2, 2, +-5, -5, 2, -9, 7, -7, 1, 2, +-8, 8, -2, 8, 3, 1, -1, -6, +-7, -8, -4, -3, 7, 3, 2, 10, +-6, 3, -5, -5, 2, -9, 4, -6, +-3, 5, -5, 9, 2, 3, 8, -5, +5, -12, -2, -6, 0, -2, 7, 7, +2, 8, -1, 2, -1, -5, 1, -5, +4, -3, 1, 4, -3, 11, -4, 8, +2, -3, -2, -6, -5, -3, -4, 3, +1, 6, 2, 6, -4, 0, -3, -8, +0, -9, 1, -1, -2, 5, -4, 9, +-5, 4, 3, -7, 2, -5, -5, -5, +1, 2, 2, 9, 0, 10, -4, -1, +-1, -8, 6, -9, 9, -3, 4, 2, +0, 3, 6, 1, 4, -7, 8, -15, +0, -2, -1, 6, 3, 9, -2, 5, +-4, -3, -1, -9, 6, -5, -1, 1, +-6, 8, -5, 5, 3, -2, 2, -7, +-5, -6, -4, 0, 1, 5, 4, 7, +-8, 6, -7, 0, 0, -3, 3, -2, +0, 0, -1, 4, 4, 6, 3, 1, +2, -8, -4, -6, 5, -1, 6, 9, +-2, 6, -5, 1, 0, -4, 8, -6, +-1, 0, -9, 7, -4, 6, 6, 3, +4, -5, -7, -4, -7, -1, 0, 4, +0, 8, -9, 7, -7, -1, 4, -9, +10, -9, -3, 0, -6, 3, 4, 3, +7, -2, 5, -8, -1, -9, 3, -4, +6, 2, 5, 4, -2, 2, 2, -4, +8, -5, 4, -4, -2, 1, -2, 4, +4, 6, 2, 0, 0, -4, -4, -4, +-2, 2, 2, 1, -2, 4, -2, 3, +-3, 1, -1, -6, -1, -5, 0, -1, +-2, 5, 0, 2, 2, -3, 0, -7, +2, -4, -2, 0, 1, 1, 2, 3, +4, -2, 4, -6, 2, -4, 1, -3, +3, -1, 5, 5, -2, 5, 3, -3, +2, -3, -3, 2, -3, 3, -1, 5, +-2, 6, -2, 3, 1, -3, -2, -4, +0, -3, 1, 2, 1, 1, -1, 2, +-3, 0, -5, -2, -1, -5, 2, -1, +-1, 3, -1, 5, -3, 1, -2, -3, +0, -3, 0, 0, 1, -2, 6, 1, +4, 2, -2, -1, 2, -6, 2, 0, +2, 3, 3, 2, 0, 2, 1, -3, +8, -6, 3, -5, 1, -3, 0, 6, +-1, 5, 2, -3, 0, -4, -4, -3, +-1, 1, 0, 3, -6, 7, -7, 3, +0, 0, -2, -1, -4, 1, -4, 0, +0, 1, 6, -1, 2, 1, -7, 0, +-3, -2, 7, -3, 5, 0, 2, 1, +0, 1, 2, -2, 5, -4, 3, -5, +-2, 4, 1, 4, 7, -2, 1, -4, +1, -4, 4, -4, 1, 0, 0, 3, +-5, 6, -6, 6, -5, 2, -6, 1, +-5, 0, 2, 2, -2, 3, -4, 3, +-1, -1, -1, -2, -2, -1, -2, 1, +0, 1, 1, 2, 4, -2, -2, 0, +-3, -1, 5, -2, 2, 3, -2, 6, +0, -2, 4, -6, 7, -5, 4, -2, +-1, 0, -2, 7, 1, 5, -3, 2, +-3, -4, 0, -4, 1, 1, 2, 1, +2, -3, -4, 2, -3, 3, -2, -1, +-2, -4, 0, 1, 0, 2, 1, -2, +1, -2, -5, 2, -5, 2, 1, 1, +1, 0, 1, 1, 0, 2, 0, -5, +3, -1, 0, 2, 0, 2, 1, 2, +2, 1, 2, -3, 0, 0, 0, 1, +-3, 4, 2, 0, 2, 1, -1, -4, +1, -1, -4, 3, -6, 2, 1, 1, +1, 0, 0, -4, 1, -2, 1, -3, +-3, 0, -2, 1, 0, 1, 1, 0, +3, -3, 0, -5, 1, -4, 5, 3, +-2, 4, -4, 2, 1, 0, 2, -1, +1, -3, 2, -1, 2, 1, 2, 2, +5, -3, 2, -2, -4, 1, 2, -3, +3, -3, 0, 3, 1, 0, -1, -2, +-1, -1, -4, 5, -6, 2, -1, 0, +4, -3, -3, 2, 0, -4, 1, -2, +-4, 1, 0, 2, -2, 5, -4, 1, +2, -2, -1, 0, -2, -2, 3, 1, +-1, 6, -4, 2, 2, -2, 4, -4, +4, -4, 4, 0, -1, 1, 2, 0, +3, 3, -5, 1, -4, 0, 2, 0, +2, 1, 0, -1, 0, 3, -4, 1, +0, -3, 3, -3, -7, 6, -8, 7, +-1, 2, -1, -3, 0, -1, 1, -2, +-1, -1, 0, 3, -1, 4, -3, 0, +-1, 0, 1, -3, 1, -2, 3, 0, +2, 0, 0, 1, 2, -2, 6, -7, +2, -3, 2, 2, -2, 4, -3, 2, +3, -3, 3, -3, 0, -4, 0, 1, +-1, 2, 0, 0, 3, -2, -3, 0, +-3, 0, 2, -1, 0, -2, -4, 6, +-2, 5, -1, 1, -2, -2, -2, 1, +-2, 0, 2, 2, 1, 1, -3, 2, +0, -1, 4, -3, 0, -2, 2, 2, +0, 3, -1, -2, 5, -3, 1, -1, +0, -5, 4, -2, 3, 0, 2, 0, +1, -1, -1, -2, -3, 1, 2, -3, +4, -4, -2, 1, 2, -1, 4, -5, +-2, 0, -3, 3, -4, 5, -4, 0, +3, 0, -2, 2, -6, 2, 1, -4, +2, -1, 1, 3, 1, 3, -1, -4, +2, -2, 6, -3, 1, -2, 0, -2, +1, 4, -1, 1, 3, -1, 0, -1, +-3, 0, 1, 0, 5, -1, 0, -1, +-1, 0, 0, -2, -3, 0, -2, 4, +-3, 3, -2, 0, 3, -2, 4, -2, +-1, -2, 0, -3, 2, -3, 1, 2, +2, 1, -2, -1, -2, -1, 1, 4, +-1, 0, -2, 1, 0, 4, -2, 1, +3, -6, 6, -5, 2, -2, 0, 2, +2, 1, 0, 0, 3, -5, 4, -3, +-2, -3, 0, 3, 2, 2, -1, -2, +-1, -1, 0, 2, 0, -2, 2, -2, +-1, 0, -1, 0, 4, -2, 5, -5, +-2, -1, -1, -1, 6, -4, 5, -3, +3, 1, -1, -1, -1, -2, 4, -1, +1, 2, -3, -2, 4, -2, 2, 2, +-2, 3, 0, -2, -4, 1, -3, 3, +5, 1, -1, -1, -7, 2, -2, 2, +-1, 1, 2, -4, 2, 1, -7, 6, +-3, 3, 2, -1, -6, 3, -5, 3, +1, 0, 2, -3, 4, -1, 0, 0, +-4, -1, 3, -1, 4, 2, -3, 1, +1, -2, 2, -1, 1, 0, 1, 0, +0, -4, 2, -3, 7, -2, 5, -3, +1, -6, 2, 0, -3, 3, -3, 1, +5, -3, 0, 1, -3, -3, 5, -3, +4, -3, 0, 0, 2, -3, 0, -1, +5, -4, 6, -2, -4, -3, -1, -1, +6, 1, -1, 3, -4, 0, -1, 1, +-1, 1, 3, -2, 2, 0, -7, 4, +-1, 1, 5, -2, -2, 1, -1, 0, +1, -1, 0, -1, 3, 1, 0, 1, +-6, 1, 0, -1, 2, 2, -3, 4, +-3, 3, -2, -2, 0, 1, 2, 0, +2, -4, -3, -1, 0, 3, 0, 2, +-4, 3, -1, -1, -3, 2, 0, -2, +6, -1, 0, 1, -8, 6, -2, 0, +3, -1, 3, 0, 0, 1, -5, 0, +3, 0, 6, 0, -2, -3, -1, -5, +5, -1, 4, 0, 0, 0, -5, 1, +-4, 1, 5, 0, 5, -3, -6, 2, +-3, 0, 4, -1, -1, 1, -3, 2, +-1, -1, -1, 0, 3, 1, -1, 4, +-6, 2, -2, 2, -1, 2, -1, 2, +3, -3, -2, 0, 0, -4, 8, 0, +-2, 2, -3, 0, 1, 1, 0, 2, +-2, 2, -1, 2, -5, 1, 1, -3, +7, -3, 1, -1, 0, 1, -4, 4, +-7, 4, 0, 2, 3, -1, -3, -4, +1, -2, 4, 3, -1, 1, 0, -2, +-4, 3, 1, -1, 8, -1, -1, -1, +-7, 1, 4, -3, 9, -2, 2, -3, +-2, 3, -3, 0, 5, -3, 9, -3, +-1, 2, -5, 0, 5, -1, 4, -1, +-1, 1, -3, 0, -1, 0, 4, 2, +2, 4, -4, -3, -2, -1, 3, 4, +-1, 4, -1, -2, 0, 1, -3, 3, +5, -2, 3, -1, -5, 1, -2, 4, +1, 3, 0, 0, 1, 0, -3, 4, +-4, 2, 3, 2, 5, 1, -4, 3, +-3, 0, 1, 3, -1, 2, 1, -1, +1, -4, 4, -1, 8, -1, 4, -4, +-2, -3, 1, 2, 4, 0, 3, -1, +3, -2, -3, 2, -1, 0, 6, -1, +2, -1, 0, 1, 2, 1, 4, 0, +1, 2, 0, -1, -1, -1, 2, 1, +7, 1, 2, -1, -1, -2, 3, 0, +2, 2, 2, 2, 0, 2, -2, 1, +2, 1, 6, -4, 1, 0, 0, 1, +4, 0, 2, 0, 5, 0, 1, 0, +-5, 2, 0, 1, 5, 3, 0, 5, +-4, 4, -3, 0, 4, -1, 9, -3, +0, 1, -4, 3, 6, 2, 8, -2, +3, -4, 2, -3, 2, 1, 8, 0, +7, 0, -2, 0, 0, -1, 8, -2, +5, 0, -2, 4, -1, 1, 6, -2, +8, 1, 0, 4, -6, -1, 3, -1, +10, 2, 3, 3, -1, -1, -3, 2, +3, -1, 10, -1, 3, -1, 0, 1, +5, 1, 10, -3, 5, -5, 2, 0, +1, 4, 4, 2, 10, -3, 6, -3, +4, -4, 9, -5, 11, -5, 8, -1, +6, -1, 5, -4, 8, -3, 9, -3, +6, -4, 4, -1, 5, 4, 7, -1, +9, -5, 3, 0, -2, 3, 3, 2, +10, -2, 8, -2, 1, 3, 3, 0, +4, 0, 5, 1, 4, 3, 0, 3, +6, 1, 9, -1, 1, 1, 3, -3, +8, 1, 8, 4, 6, 4, 2, -1, +2, -1, 10, -3, 12, -3, 4, 0, +3, 5, 5, 3, 5, 1, 4, 0, +2, 0, 7, -1, 13, 0, 6, 3, +3, 0, 6, -3, 6, -2, 8, 3, +6, 5, 2, 2, 5, -1, 9, 0, +9, -6, 10, -5, 8, -1, 9, 2, +13, -1, 10, -4, 4, -2, 5, 2, +10, 1, 9, 1, 6, 2, 3, 2, +7, -5, 14, -3, 5, 4, -1, 5, +5, 4, 10, 3, 6, 0, 4, -3, +7, -3, 12, 2, 12, 3, 3, 3, +0, 3, 9, -1, 14, -5, 8, -2, +8, 0, 13, -2, 13, -1, 11, -5, +5, -1, 6, 1, 14, 1, 11, 1, +9, 2, 6, 1, 8, -4, 12, -3, +10, 2, 8, 0, 10, 1, 11, -1, +5, 2, 7, -3, 8, 2, 4, 6, +10, 3, 11, 0, 5, 1, 9, -2, +12, -1, 10, 2, 11, 2, 11, 1, +8, 0, 10, -2, 10, -1, 7, 2, +10, 1, 12, 2, 11, 3, 9, 1, +6, -2, 12, -2, 16, 2, 12, 4, +7, 3, 8, 0, 12, -1, 10, 1, +9, 1, 8, 4, 11, 1, 15, -4, +13, -7, 13, -6, 15, -3, 14, 1, +11, 7, 6, 4, 11, -4, 12, 0, +10, 6, 7, 5, 12, -2, 17, -4, +16, -2, 13, -1, 9, -4, 9, 3, +11, 5, 17, 1, 11, -1, 9, 1, +10, 1, 14, 2, 11, 4, 11, 3, +13, 1, 16, -2, 14, -2, 9, 0, +12, -1, 16, -2, 17, 1, 14, -1, +11, -3, 11, -2, 16, 2, 15, 3, +12, 4, 12, 0, 16, -3, 19, -4, +14, 2, 5, 4, 15, 1, 20, -1, +14, -1, 13, -4, 13, -3, 17, -2, +17, 5, 9, 9, 6, 4, 14, -1, +19, -2, 16, 2, 12, 5, 12, 2, +18, -1, 20, -2, 12, -3, 10, -1, +14, 2, 15, 5, 12, 2, 14, 1, +11, 0, 17, -2, 17, 0, 15, 3, +17, 3, 17, 3, 15, -1, 15, 1, +15, 0, 13, 4, 12, 6, 17, 0, +19, -3, 13, -2, 16, -5, 21, -2, +24, -1, 20, -1, 17, 1, 16, 2, +19, -1, 15, 3, 13, 4, 16, 2, +20, -1, 19, -4, 18, -6, 17, -6, +21, -4, 20, 3, 15, 5, 16, -2, +18, -3, 20, 1, 15, 7, 13, 7, +14, 6, 16, 6, 17, 1, 19, -5, +16, -3, 18, -1, 20, 1, 21, -1, +19, -3, 17, -3, 22, -6, 27, -2, +19, 7, 16, 6, 17, 2, 21, -1, +22, -3, 19, -4, 19, -1, 23, 1, +21, 0, 20, -8, 21, -7, 18, -2, +24, -1, 19, 3, 15, 4, 20, 1, +23, 1, 17, 0, 21, 2, 20, 5, +21, 3, 21, 0, 19, -2, 19, -2, +24, -8, 23, -3, 19, 1, 25, 2, +20, -1, 20, -2, 18, 2, 22, 1, +26, 1, 22, 4, 15, 5, 19, 3, +21, -2, 17, 1, 17, 0, 24, -1, +21, 2, 19, 0, 14, -1, 18, -3, +29, -1, 22, 8, 16, 6, 23, 1, +26, -1, 26, -2, 24, -1, 21, -2, +29, -1, 24, -1, 22, -5, 21, -4, +21, 1, 18, 2, 24, 1, 23, 2, +21, 3, 24, -2, 25, -3, 25, 2, +23, 7, 20, 5, 22, 0, 28, -7, +27, -8, 26, -6, 23, -3, 26, -3, +27, -2, 26, -4, 24, -4, 23, 1, +22, 5, 23, 9, 24, 4, 26, 0, +25, -3, 30, -6, 28, -4, 25, 1, +20, 1, 26, -4, 28, -3, 23, -5, +20, -2, 24, 0, 28, 7, 22, 5, +28, -1, 21, 2, 29, -1, 28, 3, +19, 7, 21, 3, 26, 1, 25, -5, +26, -6, 19, -1, 22, -1, 28, 2, +26, -1, 25, -1, 25, 1, 27, 1, +24, 5, 26, 5, 25, 6, 27, 3, +26, -2, 23, -3, 27, -4, 31, -2, +25, -4, 29, -5, 29, -4, 30, -5, +26, -2, 22, 4, 26, 5, 38, 3, +26, 3, 20, -1, 29, 1, 28, 4, +26, 1, 20, 2, 21, 0, 30, -5, +32, -9, 20, -5, 25, 0, 31, 4, +29, 5, 23, 3, 25, 2, 26, 3, +33, 3, 27, 4, 26, 3, 32, -2, +29, -3, 25, -5, 26, -3, 26, -3, +30, 0, 28, 1, 26, -4, 33, -5, +30, 0, 27, 4, 27, 9, 28, 10, +24, 6, 26, 0, 26, -6, 33, -6, +32, -3, 28, -3, 27, -6, 34, -7, +28, -4, 27, -2, 25, 3, 25, 9, +29, 10, 29, 3, 29, -2, 30, 0, +33, 0, 31, 4, 30, 2, 26, -4, +29, -6, 30, -5, 27, -2, 23, 0, +29, 1, 29, 3, 35, 3, 25, 3, +23, 1, 32, 4, 36, 6, 32, 2, +27, 0, 26, -4, 34, -6, 31, -1, +19, 1, 25, -1, 36, -3, 31, -1, +24, -2, 28, 0, 30, 3, 39, 5, +31, 6, 30, 2, 31, 2, 31, -2, +28, 0, 29, 4, 27, 1, 30, -5, +32, -9, 31, -9, 35, -5, 31, 3, +22, 9, 28, 8, 33, 9, 24, 5, +25, 4, 26, 5, 35, 5, 35, 3, +25, -1, 19, -3, 34, -5, 34, -6, +24, 0, 22, 3, 32, 2, 38, -1, +32, -1, 20, 4, 29, 10, 37, 10, +32, 5, 26, 5, 26, 0, 33, -5, +35, -5, 29, -2, 27, -3, 40, -8, +34, -8, 32, -6, 32, -3, 32, 3, +30, 8, 32, 10, 30, 4, 33, -1, +30, 0, 29, 1, 36, 2, 32, 0, +25, -4, 30, -9, 36, -10, 31, -3, +28, 3, 25, 4, 36, 1, 40, 0, +30, 4, 24, 4, 34, 4, 35, 7, +33, 8, 28, -3, 32, -12, 37, -9, +36, -6, 31, -5, 32, -3, 33, -3, +35, -2, 36, -2, 27, 2, 27, 9, +35, 7, 41, 3, 34, 2, 29, -2, +27, -4, 39, -2, 33, 0, 26, -2, +30, -6, 36, -7, 32, -4, 30, -2, +25, 4, 33, 8, 39, 9, 28, 5, +27, 2, 34, 3, 35, 3, 32, 5, +29, 3, 31, -6, 41, -14, 37, -15, +31, -7, 33, 2, 33, 4, 27, 2, +33, 3, 30, 4, 32, 6, 28, 9, +26, 11, 36, 5, 42, -2, 26, -6, +26, -6, 35, -4, 35, -3, 30, -1, +26, -4, 33, -6, 42, -5, 33, 0, +21, 7, 36, 10, 39, 9, 34, 4, +29, -4, 35, -6, 38, 1, 37, 1, +26, -3, 32, -6, 38, -9, 35, -10, +30, -5, 30, 2, 34, 6, 36, 8, +27, 6, 28, 2, 36, 4, 31, 5, +30, 6, 31, 4, 33, -2, 29, -8, +32, -11, 30, -8, 38, -3, 33, 0, +29, 0, 32, 0, 35, -1, 34, 1, +33, 10, 26, 15, 32, 8, 36, 3, +26, 1, 27, -4, 34, -4, 31, -1, +33, -3, 34, -5, 27, -8, 36, -9, +39, -6, 37, 2, 32, 9, 32, 8, +32, 6, 34, 4, 27, -1, 30, 0, +34, 3, 35, 0, 31, -4, 26, -7, +29, -12, 40, -6, 33, 4, 22, 6, +30, 5, 35, 1, 36, 1, 33, 2, +32, 6, 33, 8, 38, 8, 23, 3, +28, -8, 36, -10, 34, -8, 33, -4, +36, -4, 35, -5, 32, -1, 29, -2, +30, 1, 38, 8, 29, 16, 20, 13, +34, 2, 39, -3, 27, -4, 28, -5, +29, -1, 37, -1, 36, -7, 23, -7, +23, -2, 39, 1, 30, 5, 26, 6, +28, 5, 36, 3, 39, 2, 28, 4, +23, 6, 35, 7, 37, 1, 28, -5, +27, -9, 28, -9, 35, -5, 34, 1, +24, 6, 28, 1, 35, 0, 29, -1, +35, 1, 32, 8, 31, 7, 35, 4, +33, 2, 28, -5, 30, -6, 23, -5, +31, -5, 37, -2, 29, -2, 25, -6, +35, -6, 35, 4, 30, 10, 25, 10, +24, 8, 40, 1, 37, 0, 24, 1, +27, -1, 34, 3, 32, 0, 33, -8, +25, -11, 30, -6, 33, 0, 29, 4, +25, 6, 31, 3, 29, 2, 34, 0, +32, 5, 24, 8, 31, 7, 31, 4, +30, -2, 29, -9, 23, -9, 23, -3, +34, -1, 32, -5, 30, -4, 29, -2, +34, -1, 34, 5, 27, 12, 17, 14, +32, 8, 38, -3, 31, -9, 27, -6, +29, -4, 33, -5, 38, -6, 28, -5, +27, -7, 37, -6, 28, 0, 29, 1, +32, 5, 27, 7, 26, 4, 30, 4, +26, 3, 32, 3, 28, 3, 26, -2, +33, -8, 29, -8, 18, -7, 27, -1, +29, 5, 27, 4, 25, 1, 22, 1, +33, 0, 41, 2, 25, 12, 20, 11, +36, 5, 33, -3, 27, -13, 21, -12, +26, -6, 35, -2, 30, 1, 20, 1, +32, -3, 37, -6, 32, -3, 23, 7, +21, 13, 25, 10, 30, 2, 23, -1, +29, -5, 34, -3, 24, -1, 27, -5, +28, -8, 31, -9, 28, -2, 23, 2, +25, 3, 31, 2, 23, 1, 22, 2, +29, 3, 32, 7, 27, 11, 28, 6, +30, -3, 34, -10, 24, -11, 15, -10, +27, -8, 29, 2, 24, 6, 27, 3, +28, 0, 31, -3, 27, 4, 19, 6, +26, 9, 27, 8, 23, 1, 22, -3, +27, -7, 22, -7, 26, -5, 26, -3, +28, -4, 31, -4, 27, -4, 25, 1, +28, 8, 22, 5, 18, 2, 23, 2, +29, 0, 31, 4, 29, 4, 24, 5, +27, -1, 30, -9, 17, -9, 17, -6, +22, -3, 22, 1, 25, 2, 29, 0, +30, 1, 30, 3, 21, 6, 20, 7, +27, 6, 22, 2, 22, -6, 28, -11, +24, -7, 20, -4, 21, 0, 19, 2, +32, -5, 30, -5, 22, -4, 28, 2, +28, 12, 19, 12, 15, 8, 13, 0, +22, -3, 29, -6, 27, -5, 28, -1, +33, 2, 27, -1, 20, -5, 16, -6, +15, -5, 21, -2, 18, 4, 20, 6, +31, 8, 25, 15, 15, 14, 17, 7, +15, -1, 16, -5, 18, -4, 21, -4, +25, -2, 21, 1, 15, 2, 21, 0, +27, -7, 20, -6, 19, 0, 29, 7, +31, 16, 22, 17, 9, 6, 11, -8, +24, -18, 20, -14, 15, 1, 23, 11, +31, 14, 24, 11, 18, -3, 12, -9, +18, -12, 21, -8, 11, 5, 16, 9, +29, 11, 26, 11, 26, 2, 23, -9, +24, -16, 23, -11, 15, -3, 19, 1, +25, 3, 18, 1, 17, -4, 26, -10, +27, -12, 22, -3, 16, 7, 22, 14, +27, 15, 21, 8, 12, -3, 17, -12, +17, -17, 14, -15, 17, -5, 25, 8, +32, 12, 29, 7, 12, 1, 14, -7, +21, -5, 11, 3, 10, 3, 13, 4, +18, 4, 24, 0, 24, -2, 21, -3, +23, -3, 17, -2, 15, 1, 18, 0, +18, -5, 18, -6, 17, -2, 14, 0, +17, 4, 12, 11, 13, 9, 29, 0, +29, -4, 15, 0, 11, 1, 13, -2, +13, -8, 10, -5, 6, 0, 21, 1, +32, 2, 25, 1, 20, -1, 23, 4, +11, 12, 3, 11, 4, 2, 8, -7, +19, -15, 21, -12, 18, -2, 23, 9, +17, 15, 10, 8, 13, -1, 15, -3, +12, 0, 12, 0, 12, 1, 12, 6, +14, 4, 10, 2, 16, 0, 24, -2, +21, -3, 19, -5, 19, 1, 14, 8, +8, 4, -3, -2, -2, -5, 15, -4, +24, 2, 23, 10, 20, 16, 21, 11, +16, 5, 3, 0, -3, -6, 5, -12, +13, -15, 12, -8, 19, 0, 29, 7, +26, 7, 17, 1, 8, -3, 11, -2, +12, 4, 10, 8, 11, 7, 18, -2, +15, -9, 8, -11, 11, -8, 12, 2, +18, 4, 17, 6, 17, 5, 22, 4, +14, -3, 4, -13, 3, -14, 5, -6, +11, 9, 15, 19, 22, 15, 29, 6, +23, 0, 7, -9, 1, -9, -2, -7, +-4, -7, 2, -6, 15, -5, 25, 3, +30, 6, 25, 5, 12, 9, 7, 8, +-1, 10, -6, 12, 5, 4, 17, -11, +20, -20, 17, -18, 13, -8, 13, 3, +13, 6, 7, 4, 11, 3, 17, 4, +15, 4, 11, 3, 3, 2, -4, 1, +0, -3, 8, -2, 18, 0, 31, 1, +27, 3, 16, 4, 9, 2, -4, -1, +-12, -10, -5, -23, 11, -24, 22, -9, +24, 14, 22, 29, 22, 28, 13, 14, +-1, -3, -4, -12, 3, -10, 7, -7, +6, -8, 8, -6, 14, 1, 15, 5, +8, 0, 7, -8, 14, -10, 21, -2, +14, 14, 1, 24, 1, 18, 2, 2, +-3, -18, 3, -26, 16, -16, 29, -1, +27, 13, 15, 15, 9, 8, 2, 2, +-10, -9, -13, -23, 4, -26, 12, -12, +16, 10, 20, 30, 21, 33, 18, 18, +6, 0, -3, -14, 0, -14, 4, -9, +-3, -6, -1, -7, 11, -8, 16, -5, +13, 2, 8, 5, 13, 2, 19, 2, +9, 9, -4, 16, 0, 14, 3, 0, +2, -19, 5, -24, 9, -14, 18, 1, +18, 13, 11, 10, 11, 0, 13, -5, +2, -4, -8, -3, -7, -8, -3, -11, +4, -7, 17, 5, 23, 18, 26, 21, +19, 15, 5, 5, -4, -3, -11, -10, +-16, -15, -6, -22, 13, -23, 17, -9, +18, 8, 17, 21, 12, 20, 7, 6, +-3, -2, -4, -3, 7, 3, 8, 6, +5, -3, 6, -15, 10, -19, 4, -8, +0, -1, 11, 1, 19, 4, 20, 6, +9, 10, -5, 11, -12, 1, -18, -14, +-16, -24, 5, -16, 26, 10, 34, 29, +29, 32, 15, 19, -3, -2, -20, -19, +-27, -27, -14, -27, 12, -21, 25, -7, +21, 8, 23, 17, 15, 20, -5, 14, +-17, 1, -11, -3, 2, 6, 11, 13, +8, 8, 1, -6, 1, -19, -8, -20, +-7, -11, 9, 5, 22, 13, 24, 14, +17, 6, 4, 3, -8, -4, -17, -15, +-26, -20, -9, -15, 21, 2, 30, 24, +29, 32, 20, 22, 4, 1, -13, -15, +-28, -19, -22, -18, 5, -18, 19, -15, +15, -6, 13, 9, 10, 19, 3, 23, +-6, 18, -6, 4, 5, -6, 12, -7, +2, -2, -7, -6, -5, -14, -7, -12, +0, -5, 15, 8, 20, 13, 19, 6, +10, -2, 0, -5, -12, 4, -23, 7, +-19, -2, -1, -15, 21, -21, 25, -4, +17, 19, 10, 31, 2, 22, -9, 6, +-16, -9, -5, -21, 5, -23, 6, -27, +2, -22, 1, -3, 4, 22, 3, 39, +4, 34, 10, 13, 10, -10, 4, -21, +-6, -14, -17, 0, -19, 5, -9, -1, +4, -5, 22, -5, 28, 1, 15, 4, +5, 2, -5, 5, -19, 10, -23, 11, +-13, 0, 6, -20, 17, -27, 10, -11, +6, 15, 13, 35, 7, 36, -7, 15, +-6, -14, 3, -31, 3, -31, -4, -23, +-10, -12, -5, 2, 8, 11, 11, 20, +12, 22, 20, 9, 16, -7, -2, -11, +-14, -4, -19, 7, -11, 6, -1, -8, +4, -19, 16, -20, 19, -4, 7, 16, +-3, 25, -4, 15, -5, 4, -9, -5, +-3, -15, 0, -19, 2, -21, -2, -8, +-3, 16, 10, 36, 14, 37, 12, 14, +12, -16, 8, -33, -9, -27, -25, -12, +-29, 1, -13, 2, 9, -1, 21, 3, +28, 14, 28, 20, 12, 15, -19, 6, +-30, -6, -20, -8, -6, -5, 10, -10, +19, -16, 24, -16, 15, -4, -2, 9, +-13, 17, -13, 12, -2, -5, 7, -9, +10, -2, 8, 2, -4, 1, -16, -5, +-19, -4, -8, 5, 11, 16, 25, 20, +29, 15, 19, 1, -7, -12, -30, -20, +-32, -27, -21, -30, -1, -24, 22, -1, +34, 32, 35, 54, 14, 48, -15, 12, +-24, -27, -22, -43, -15, -33, 2, -9, +20, 12, 24, 18, 15, 11, 1, 0, +-8, -9, -4, -15, -6, -15, -3, -7, +7, 12, 7, 29, -2, 23, -10, 2, +-11, -23, 1, -31, 10, -10, 6, 24, +10, 36, 17, 26, 0, 5, -16, -19, +-17, -35, -14, -36, -9, -27, 2, -6, +12, 24, 20, 50, 14, 55, 1, 30, +-1, -10, -2, -37, -14, -35, -16, -17, +-4, 1, 1, 9, 6, 1, 10, -3, +17, 1, 20, 6, 6, 7, -13, -1, +-14, -8, -13, -2, -16, 6, -8, 9, +8, 6, 22, 1, 19, 6, 3, 12, +-3, 7, -4, -2, -9, -15, -11, -20, +-2, -12, 9, 0, 9, 3, 4, -6, +-2, -10, -6, -1, -2, 16, 4, 29, +11, 30, 10, 21, 1, 1, -6, -18, +-13, -26, -19, -32, -17, -28, 1, -11, +20, 18, 28, 42, 22, 44, 4, 18, +-9, -21, -18, -46, -26, -36, -18, -4, +6, 27, 19, 36, 23, 26, 18, 9, +9, -10, -2, -21, -16, -27, -19, -25, +-4, -7, 6, 15, 6, 22, 6, 9, +4, -10, 0, -18, -4, 0, -8, 28, +-3, 37, 7, 27, 6, 4, 3, -20, +0, -30, -9, -27, -15, -17, -5, -8, +6, 7, 9, 24, 10, 29, 12, 18, +8, -3, -4, -20, -19, -16, -22, 5, +-10, 20, -4, 17, 3, 1, 11, -7, +16, -1, 10, 11, -4, 15, -16, 10, +-16, -5, -11, -17, -13, -20, -4, -16, +12, -6, 17, 9, 10, 27, 3, 40, +-2, 38, -5, 11, -5, -24, -8, -41, +-6, -32, -4, -3, -5, 20, 0, 25, +4, 13, 2, -3, 2, -10, 2, -4, +-3, 3, -7, 9, -12, 17, -9, 21, +-3, 20, -4, 4, -4, -20, 6, -34, +12, -20, 3, 13, -5, 40, -7, 42, +-8, 18, -8, -20, -8, -43, -9, -34, +1, -13, 3, 14, -3, 35, 0, 46, +3, 44, -1, 24, -2, -11, -5, -36, +-10, -35, -14, -15, -18, 11, -13, 26, +0, 21, 7, 4, 13, -6, 17, -6, +6, 6, -14, 12, -24, 7, -26, 6, +-17, 9, -2, 10, 10, 3, 23, -7, +19, -11, 0, -5, -17, 11, -24, 21, +-23, 15, -12, -3, 5, -16, 14, -8, +9, 5, -3, 9, -23, 12, -25, 12, +-16, 15, -1, 20, 15, 21, 21, 8, +14, -10, -11, -19, -32, -19, -38, -10, +-24, 1, -7, 10, 16, 13, 36, 17, +31, 23, 1, 19, -29, 4, -48, -11, +-45, -11, -22, 2, 5, 15, 27, 20, +30, 14, 12, 3, -14, 1, -32, 5, +-38, 4, -24, -7, -3, -11, 13, -7, +19, 6, 5, 21, -14, 23, -19, 12, +-20, 4, -20, 6, -5, 9, 14, 7, +14, -1, -2, -5, -17, -3, -23, 5, +-23, 7, -20, -1, -10, -11, 13, -11, +19, 9, 5, 30, -7, 38, -16, 28, +-24, 4, -28, -16, -25, -19, -11, -13, +8, -5, 14, 8, 6, 26, -3, 37, +-12, 29, -21, 2, -23, -28, -26, -36, +-21, -23, -5, 9, 1, 44, 1, 51, +2, 36, -5, 13, -13, -3, -20, -14, +-27, -18, -27, -15, -9, -6, 4, 15, +7, 33, -3, 36, -20, 14, -25, -18, +-23, -33, -23, -15, -11, 19, 8, 46, +9, 53, -8, 38, -29, 9, -37, -19, +-36, -35, -31, -33, -14, -10, 15, 30, +23, 66, 7, 67, -14, 29, -39, -24, +-53, -62, -44, -55, -27, -8, 0, 40, +19, 75, 18, 74, 9, 44, -20, 3, +-49, -38, -57, -57, -40, -45, -18, -5, +5, 46, 19, 78, 14, 66, -9, 14, +-43, -37, -62, -58, -42, -35, -11, 22, +8, 68, 13, 79, 5, 50, -18, 1, +-50, -43, -62, -66, -42, -50, -1, 2, +27, 61, 29, 95, 2, 78, -32, 10, +-63, -60, -68, -87, -47, -50, -10, 20, +22, 82, 27, 102, 4, 72, -31, 15, +-57, -39, -64, -65, -44, -56, -11, -12, +5, 53, 3, 91, -6, 71, -20, 11, +-35, -53, -43, -77, -32, -41, -7, 32, +-1, 94, -14, 102, -21, 55, -36, -14, +-54, -70, -47, -85, -19, -43, 2, 30, +11, 89, -1, 113, -23, 79, -48, -3, +-69, -84, -61, -103, -35, -49, -4, 43, +15, 120, 11, 131, -19, 67, -49, -26, +-69, -85, -61, -88, -30, -34, 1, 45, +10, 103, -4, 107, -40, 55, -67, -28, +-70, -90, -48, -96, -6, -26, 22, 81, +20, 148, -16, 130, -58, 37, -92, -69, +-89, -126, -48, -98, 6, -4, 38, 92, +32, 137, -8, 112, -59, 30, -97, -61, +-97, -109, -58, -83, -8, 0, 22, 93, +22, 140, -11, 108, -51, 13, -79, -77, +-82, -99, -53, -50, -10, 35, 17, 101, +3, 106, -39, 56, -71, -14, -78, -64, +-69, -70, -33, -33, 9, 36, 21, 94, +-2, 104, -45, 68, -82, 2, -87, -65, +-67, -85, -25, -41, 12, 31, 12, 79, +-12, 86, -46, 55, -74, 2, -78, -38, +-53, -42, -21, -19, -6, 16, -22, 55, +-50, 80, -66, 64, -69, 17, -57, -26, +-25, -40, -7, -14, -12, 33, -31, 67, +-66, 59, -86, 17, -75, -19, -45, -31, +-15, -16, -2, 17, -9, 50, -35, 64, +-76, 54, -99, 28, -82, -2, -41, -25, +-13, -20, -2, 13, -17, 45, -47, 49, +-77, 31, -93, -1, -75, -21, -38, -5, +0, 31, 12, 56, -20, 50, -73, 22, +-109, -7, -110, -24, -75, -11, -28, 22, +17, 46, 27, 58, -10, 59, -79, 36, +-127, -10, -123, -44, -81, -37, -28, 0, +11, 46, 18, 80, -15, 76, -72, 28, +-112, -16, -107, -26, -71, -10, -31, 16, +-5, 43, -10, 53, -40, 36, -75, 10, +-95, -7, -83, -21, -52, -16, -29, 23, +-11, 63, -21, 75, -60, 48, -89, 5, +-99, -33, -88, -37, -59, -1, -26, 46, +-11, 68, -20, 63, -52, 40, -78, 4, +-96, -22, -94, -24, -64, -3, -35, 24, +-31, 50, -40, 61, -52, 41, -73, 3, +-88, -13, -78, 0, -47, 27, -31, 56, +-49, 63, -70, 31, -82, -13, -93, -27, +-79, -10, -50, 22, -28, 46, -25, 58, +-41, 49, -72, 28, -103, 10, -106, -9, +-81, -12, -51, 9, -35, 35, -37, 48, +-54, 41, -72, 24, -79, 15, -75, 17, +-68, 27, -58, 28, -59, 12, -72, -9, +-80, -7, -76, 19, -64, 49, -51, 63, +-49, 50, -57, 16, -68, -15, -76, -17, +-76, 16, -79, 46, -81, 57, -79, 50, +-68, 18, -67, -16, -61, -27, -47, -6, +-40, 36, -48, 71, -78, 83, -108, 48, +-110, -14, -94, -50, -66, -30, -42, 23, +-32, 67, -39, 83, -61, 54, -91, 5, +-110, -15, -100, -3, -79, 20, -66, 32, +-63, 31, -59, 16, -49, 2, -61, 15, +-81, 40, -82, 53, -85, 49, -95, 36, +-91, 8, -69, -19, -53, -13, -54, 19, +-61, 43, -75, 52, -99, 39, -103, 6, +-76, -16, -47, 0, -45, 46, -61, 71, +-85, 56, -112, 16, -121, -24, -100, -31, +-61, 10, -32, 62, -33, 83, -58, 58, +-93, 13, -121, -17, -120, -20, -95, 9, +-70, 47, -54, 56, -50, 37, -62, 7, +-80, -11, -95, -1, -88, 32, -76, 69, +-81, 71, -85, 33, -86, -12, -86, -36, +-80, -21, -75, 32, -77, 82, -75, 76, +-75, 28, -79, -17, -82, -27, -87, 5, +-85, 56, -85, 83, -91, 53, -86, -5, +-77, -38, -70, -28, -68, 22, -83, 84, +-98, 108, -100, 70, -91, -3, -82, -51, +-75, -47, -74, -2, -85, 64, -103, 105, +-107, 82, -91, 20, -68, -26, -54, -31, +-50, 8, -79, 65, -123, 83, -138, 44, +-117, -14, -79, -46, -43, -29, -28, 31, +-44, 91, -92, 106, -142, 55, -150, -13, +-116, -48, -70, -31, -42, 20, -37, 73, +-66, 96, -102, 59, -123, -1, -124, -38, +-104, -33, -72, 8, -48, 64, -55, 94, +-86, 73, -106, 20, -106, -28, -108, -42, +-108, -15, -93, 37, -71, 79, -64, 89, +-69, 65, -74, 29, -88, -6, -110, -34, +-122, -30, -117, 0, -103, 40, -81, 77, +-52, 94, -52, 72, -75, 16, -99, -35, +-111, -47, -118, -13, -116, 47, -101, 104, +-82, 108, -65, 43, -64, -33, -71, -74, +-84, -57, -97, 19, -101, 108, -108, 146, +-107, 95, -86, -9, -68, -96, -64, -113, +-80, -37, -107, 93, -117, 178, -105, 162, +-87, 62, -66, -60, -63, -129, -79, -97, +-109, 20, -144, 137, -144, 170, -97, 115, +-50, 6, -31, -96, -49, -109, -92, -29, +-128, 78, -150, 148, -127, 138, -75, 61, +-47, -40, -53, -103, -89, -76, -132, 10, +-134, 91, -93, 138, -53, 122, -42, 44, +-68, -40, -117, -70, -163, -45, -165, 3, +-105, 63, -24, 100, 11, 88, -25, 49, +-98, 11, -167, -23, -196, -32, -155, -9, +-65, 29, 5, 55, 1, 63, -60, 57, +-129, 30, -178, -4, -170, -16, -100, -1, +-29, 26, -14, 55, -47, 76, -107, 69, +-153, 28, -161, -10, -129, -33, -78, -31, +-42, 8, -38, 73, -55, 112, -87, 92, +-121, 36, -131, -27, -124, -67, -117, -53, +-103, 19, -74, 90, -45, 118, -35, 95, +-52, 32, -93, -40, -139, -74, -165, -41, +-147, 29, -95, 93, -42, 120, -12, 90, +-29, 7, -87, -66, -144, -71, -162, -16, +-135, 60, -83, 121, -44, 129, -37, 63, +-63, -26, -103, -78, -130, -73, -135, -19, +-113, 65, -72, 135, -49, 141, -53, 73, +-72, -15, -102, -79, -123, -95, -124, -35, +-111, 67, -87, 131, -60, 127, -42, 70, +-46, -10, -82, -73, -127, -68, -146, -1, +-137, 72, -112, 112, -64, 111, -21, 58, +-22, -27, -75, -81, -136, -61, -159, 12, +-131, 90, -86, 143, -42, 117, -23, 25, +-60, -59, -115, -87, -153, -51, -149, 26, +-92, 106, -27, 138, -7, 94, -45, 15, +-121, -47, -167, -78, -156, -51, -105, 35, +-35, 118, 9, 132, -22, 79, -105, -7, +-171, -80, -183, -78, -130, 1, -41, 97, +19, 134, 7, 106, -73, 33, -159, -51, +-196, -91, -169, -53, -87, 34, 3, 111, +31, 143, -17, 106, -105, 15, -179, -77, +-190, -95, -141, -34, -64, 58, -4, 126, +13, 124, -28, 57, -102, -27, -162, -62, +-170, -33, -125, 21, -64, 70, -17, 86, +-6, 57, -40, 6, -95, -20, -146, -12, +-161, 5, -125, 35, -62, 65, -9, 63, +-1, 29, -44, -1, -106, -6, -149, 4, +-162, 26, -121, 38, -46, 27, 5, 9, +4, 11, -48, 36, -115, 51, -154, 38, +-149, 11, -103, -16, -36, -19, -4, 19, +-26, 68, -76, 76, -125, 41, -142, 3, +-112, -21, -63, -17, -27, 18, -27, 62, +-63, 74, -105, 44, -125, 2, -115, -34, +-74, -40, -43, 10, -40, 84, -54, 118, +-84, 82, -110, -1, -106, -77, -79, -82, +-57, 0, -58, 108, -80, 144, -88, 81, +-81, -24, -71, -92, -59, -70, -56, 33, +-72, 131, -86, 137, -98, 56, -103, -49, +-82, -109, -47, -83, -32, 33, -50, 156, +-80, 180, -97, 89, -101, -55, -87, -161, +-64, -138, -49, 13, -50, 184, -72, 238, +-95, 126, -100, -63, -77, -195, -46, -170, +-36, 8, -50, 196, -77, 247, -101, 131, +-109, -61, -94, -193, -58, -172, -25, -12, +-21, 167, -44, 233, -84, 150, -121, -14, +-117, -150, -84, -160, -46, -37, -20, 128, +-28, 203, -58, 129, -99, -20, -124, -132, +-100, -125, -43, 4, -11, 151, -19, 183, +-61, 74, -109, -74, -127, -145, -104, -86, +-58, 61, -9, 177, 4, 165, -26, 37, +-88, -94, -144, -134, -136, -62, -77, 72, +-26, 166, -3, 145, -9, 28, -49, -91, +-99, -129, -126, -57, -108, 78, -60, 178, +-26, 157, -23, 27, -42, -107, -72, -139, +-92, -50, -93, 95, -85, 180, -64, 128, +-34, -16, -20, -119, -33, -101, -65, 15, +-91, 128, -93, 143, -84, 50, -68, -68, +-42, -112, -20, -50, -20, 66, -38, 147, +-76, 134, -112, 27, -116, -91, -87, -131, +-40, -53, -4, 85, 4, 178, -26, 153, +-80, 14, -122, -135, -118, -167, -78, -45, +-30, 133, 3, 225, -5, 158, -45, -24, +-91, -176, -119, -177, -110, -25, -69, 149, +-14, 217, 15, 144, -6, -16, -63, -143, +-108, -150, -120, -38, -96, 106, -41, 177, +4, 130, 7, 4, -28, -113, -79, -126, +-114, -23, -104, 106, -64, 161, -22, 91, +-8, -42, -22, -127, -42, -89, -66, 43, +-86, 146, -83, 136, -61, 24, -40, -91, +-29, -112, -28, -26, -39, 92, -64, 144, +-82, 88, -74, -26, -51, -106, -34, -90, +-27, 11, -34, 116, -57, 145, -76, 74, +-80, -39, -64, -111, -26, -93, -7, 9, +-22, 116, -57, 143, -89, 67, -87, -53, +-59, -120, -33, -78, -9, 42, -9, 145, +-45, 138, -82, 25, -90, -98, -65, -131, +-35, -45, -16, 92, -18, 167, -37, 113, +-60, -19, -67, -126, -64, -124, -53, -17, +-35, 112, -28, 158, -33, 96, -48, -24, +-54, -119, -55, -110, -55, -6, -55, 118, +-53, 171, -47, 108, -42, -40, -32, -154, +-29, -131, -43, 7, -60, 147, -72, 185, +-74, 83, -49, -75, -5, -155, 12, -105, +-16, 30, -66, 146, -103, 161, -97, 61, +-56, -62, -12, -119, 20, -90, 8, 11, +-41, 111, -86, 129, -108, 63, -82, -32, +-28, -87, 12, -68, 11, 9, -34, 81, +-78, 94, -94, 51, -83, -19, -37, -58, +10, -28, 16, 32, -22, 64, -79, 46, +-116, -6, -86, -52, -18, -34, 27, 29, +14, 85, -35, 81, -81, 20, -109, -51, +-95, -72, -40, -28, 23, 41, 40, 88, +-2, 83, -75, 34, -117, -34, -108, -71, +-57, -60, 9, -2, 37, 74, 16, 103, +-36, 64, -88, -13, -106, -77, -80, -77, +-23, -16, 17, 52, 18, 77, -8, 63, +-51, 23, -75, -16, -75, -33, -66, -39, +-47, -33, -15, -5, 8, 49, 7, 95, +-21, 90, -66, 28, -97, -65, -95, -117, +-54, -74, 1, 44, 26, 145, 11, 147, +-36, 43, -73, -93, -81, -150, -74, -93, +-47, 34, -12, 143, 8, 161, 6, 72, +-25, -57, -79, -142, -101, -132, -63, -24, +0, 116, 29, 185, 0, 129, -58, -18, +-86, -160, -59, -179, -20, -48, -5, 124, +-17, 198, -43, 125, -61, -27, -53, -142, +-34, -135, -10, -27, -5, 86, -29, 126, +-53, 89, -57, 7, -48, -60, -34, -78, +-19, -51, -9, 4, -21, 64, -46, 88, +-50, 48, -35, -18, -20, -55, -12, -45, +-30, -2, -57, 38, -70, 31, -50, -4, +3, -6, 40, 30, 20, 59, -44, 39, +-113, -34, -133, -104, -77, -84, 12, 28, +79, 135, 81, 155, 9, 60, -103, -91, +-174, -181, -145, -132, -44, 10, 72, 146, +132, 199, 85, 125, -47, -32, -166, -174, +-196, -211, -116, -115, 23, 81, 127, 246, +122, 251, 15, 85, -116, -152, -185, -298, +-147, -226, -35, 22, 67, 243, 103, 286, +64, 141, -33, -92, -120, -239, -143, -208, +-100, -60, -14, 111, 62, 208, 64, 185, +0, 55, -73, -98, -104, -192, -71, -170, +-10, -22, 21, 145, -4, 199, -52, 118, +-61, -27, -26, -133, 10, -123, 10, -35, +-36, 35, -76, 52, -68, 51, -31, 55, +9, 53, 10, 25, -16, -54, -33, -123, +-40, -100, -53, 8, -64, 122, -50, 170, +-6, 101, 41, -50, 32, -160, -41, -152, +-103, -50, -82, 79, -20, 159, 25, 132, +35, 20, 0, -93, -49, -146, -71, -107, +-62, 1, -26, 112, 5, 154, 9, 92, +-6, -37, -34, -142, -46, -140, -47, -15, +-45, 129, -37, 166, -29, 55, 3, -114, +38, -175, 27, -69, -26, 112, -93, 197, +-131, 102, -89, -89, 19, -219, 110, -170, +118, 26, 20, 215, -127, 248, -199, 98, +-145, -131, -10, -281, 101, -234, 126, -8, +76, 236, -27, 326, -130, 188, -184, -92, +-149, -310, -23, -306, 114, -98, 168, 169, +104, 323, -47, 271, -185, 47, -208, -211, +-121, -337, 22, -260, 140, -1, 154, 292, +54, 403, -87, 229, -171, -126, -161, -407, +-80, -381, 27, -62, 93, 301, 98, 418, +54, 210, -44, -139, -126, -345, -142, -254, +-88, 11, 7, 207, 74, 204, 80, 55, +46, -82, -20, -105, -94, -43, -128, 8, +-92, 5, -5, -16, 65, 0, 84, 42, +44, 62, -40, 26, -91, -45, -95, -72, +-71, -32, -11, 18, 42, 26, 50, 3, +35, -9, -5, 28, -71, 82, -110, 64, +-87, -56, -11, -179, 64, -161, 85, 15, +31, 216, -69, 269, -126, 92, -95, -184, +-4, -316, 76, -198, 67, 70, 1, 279, +-58, 279, -98, 71, -79, -180, -16, -284, +42, -189, 64, 33, 42, 224, -12, 241, +-74, 77, -108, -131, -82, -231, -15, -150, +64, 47, 104, 186, 50, 155, -49, 10, +-112, -123, -110, -144, -46, -45, 28, 67, +60, 100, 63, 55, 35, -15, -18, -68, +-73, -79, -112, -39, -104, 22, -23, 72, +89, 97, 136, 55, 74, -48, -37, -137, +-137, -134, -168, -30, -90, 119, 32, 200, +121, 126, 134, -58, 60, -207, -63, -200, +-153, -36, -163, 160, -84, 229, 42, 108, +143, -90, 149, -194, 61, -144, -65, 10, +-177, 131, -197, 116, -90, 15, 87, -66, +227, -76, 204, -24, -11, 43, -226, 58, +-264, 12, -127, -46, 90, -75, 225, -46, +185, 42, 33, 121, -121, 95, -195, -20, +-171, -134, -58, -165, 95, -63, 195, 108, +173, 195, 21, 129, -173, -16, -244, -144, +-144, -183, 43, -94, 191, 52, 183, 145, +47, 159, -93, 88, -162, -60, -133, -179, +-37, -181, 60, -76, 115, 88, 125, 215, +71, 185, -66, 16, -194, -157, -180, -228, +-30, -151, 140, 50, 198, 213, 103, 197, +-57, 56, -152, -115, -144, -206, -57, -128, +50, 28, 110, 114, 98, 124, 22, 83, +-60, -20, -96, -106, -70, -110, -4, -65, +46, 17, 58, 110, 37, 109, -12, 10, +-31, -79, -11, -102, -10, -46, -18, 52, +-27, 85, -23, 14, 26, -56, 75, -53, +55, 2, -33, 74, -100, 88, -73, -5, +12, -116, 67, -138, 51, -56, 3, 88, +-11, 201, -4, 155, -5, -26, -21, -190, +-48, -233, -39, -117, 28, 93, 80, 235, +67, 220, 5, 87, -70, -101, -100, -252, +-54, -265, 32, -115, 97, 127, 99, 335, +43, 341, -48, 86, -112, -263, -91, -449, +-24, -328, 58, 28, 127, 364, 123, 443, +48, 230, -66, -123, -160, -390, -146, -411, +-26, -180, 112, 154, 193, 404, 154, 403, +7, 120, -154, -246, -196, -435, -90, -327, +65, -11, 159, 296, 135, 363, 37, 177, +-37, -78, -60, -240, -76, -233, -68, -94, +-31, 59, 37, 136, 126, 141, 153, 86, +68, -5, -82, -82, -183, -117, -152, -98, +-6, -22, 155, 61, 205, 86, 110, 60, +-41, 19, -144, -24, -121, -45, 1, -42, +74, -54, 56, -54, 11, 7, 0, 76, +43, 101, 78, 70, 32, -26, -71, -119, +-133, -116, -74, -34, 59, 45, 162, 75, +156, 56, 30, 15, -91, -4, -118, -5, +-67, -45, 18, -95, 77, -87, 82, -2, +61, 118, 28, 172, -7, 79, -24, -100, +-41, -214, -49, -167, -19, 18, 45, 193, +105, 201, 114, 28, 64, -160, -30, -196, +-122, -61, -120, 115, -22, 169, 90, 47, +154, -118, 115, -151, 13, -35, -59, 107, +-76, 137, -40, 36, 17, -100, 48, -148, +44, -73, 39, 36, 49, 92, 57, 84, +33, 32, -18, -36, -66, -80, -66, -84, +-7, -55, 62, 7, 112, 79, 120, 101, +48, 53, -52, -30, -106, -95, -96, -103, +-10, -46, 94, 35, 149, 85, 124, 84, +30, 29, -74, -56, -119, -103, -72, -75, +36, -4, 115, 64, 130, 78, 66, 26, +-28, -48, -60, -70, -32, -40, 18, 14, +57, 66, 45, 57, -1, -22, -14, -102, +3, -111, 52, -38, 105, 110, 90, 208, +-2, 120, -107, -107, -124, -291, -35, -276, +100, -27, 202, 297, 191, 410, 57, 195, +-119, -181, -229, -444, -175, -394, 39, -55, +250, 321, 304, 454, 157, 275, -91, -80, +-245, -385, -205, -428, -24, -189, 157, 154, +232, 378, 192, 348, 64, 89, -77, -212, +-158, -348, -149, -268, -31, -53, 128, 170, +205, 276, 167, 212, 44, 46, -93, -137, +-133, -268, -62, -243, 53, -60, 126, 143, +103, 252, 27, 212, -21, 27, -10, -183, +31, -262, 48, -173, 52, -3, 27, 174, +-33, 237, -55, 121, -12, -78, 83, -214, +165, -208, 142, -47, 4, 162, -139, 223, +-179, 90, -64, -112, 136, -223, 263, -148, +218, 66, 27, 212, -165, 147, -227, -43, +-114, -207, 115, -213, 269, -16, 228, 203, +47, 219, -133, 40, -166, -172, -54, -253, +88, -110, 155, 135, 115, 222, 20, 89, +-44, -102, -36, -193, 25, -105, 77, 77, +79, 154, 31, 53, -31, -94, -37, -153, +10, -82, 67, 69, 113, 154, 104, 86, +20, -59, -53, -162, -67, -144, -18, -5, +76, 133, 123, 135, 95, 1, 31, -131, +-15, -149, -11, -24, 17, 125, 27, 125, +4, -24, 0, -161, 53, -153, 114, -3, +124, 161, 64, 171, -56, 17, -141, -155, +-93, -204, 55, -107, 206, 61, 239, 168, +105, 141, -90, 22, -191, -110, -125, -170, +41, -114, 192, 6, 211, 98, 88, 100, +-60, 27, -99, -55, -20, -64, 86, -16, +115, 3, 36, -28, -43, -85, -36, -100, +48, 2, 142, 149, 156, 185, 50, 66, +-91, -137, -140, -291, -56, -245, 87, 1, +197, 244, 194, 305, 76, 155, -57, -112, +-129, -304, -108, -275, 6, -85, 128, 116, +173, 227, 138, 192, 49, 45, -35, -104, +-60, -197, -39, -214, -12, -101, 15, 77, +73, 176, 152, 162, 193, 52, 123, -99, +-50, -176, -191, -129, -174, -52, -13, 3, +195, 54, 314, 82, 239, 76, 15, 53, +-205, -22, -264, -143, -100, -191, 158, -109, +308, 46, 240, 192, 24, 208, -157, 49, +-177, -159, -24, -255, 149, -170, 194, 27, +107, 184, -18, 164, -74, -3, -12, -146, +90, -162, 120, -51, 58, 91, -31, 126, +-58, 19, 14, -124, 111, -173, 134, -89, +80, 76, 1, 195, -49, 152, -41, -47, +37, -247, 106, -282, 107, -108, 58, 156, +-3, 303, -27, 201, 23, -67, 87, -276, +94, -277, 54, -102, -9, 105, -49, 190, +-27, 121, 59, 7, 154, -69, 182, -105, +86, -109, -81, -86, -177, -46, -93, 26, +97, 118, 247, 128, 231, 34, 44, -92, +-119, -181, -132, -169, -20, -46, 108, 95, +155, 151, 101, 102, 24, -23, -10, -163, +30, -200, 87, -96, 70, 53, -20, 148, +-86, 132, -28, -19, 123, -173, 228, -175, +186, -49, 10, 94, -165, 150, -183, 56, +-38, -122, 175, -197, 293, -97, 217, 54, +15, 140, -161, 99, -188, -59, -46, -177, +155, -133, 256, 1, 186, 110, -3, 113, +-141, -21, -129, -165, 22, -153, 182, 1, +211, 150, 92, 165, -59, 3, -136, -218, +-65, -287, 99, -125, 208, 130, 189, 285, +58, 225, -82, -30, -127, -291, -41, -358, +96, -206, 190, 62, 174, 298, 67, 338, +-54, 127, -77, -192, -16, -399, 45, -358, +83, -75, 90, 256, 79, 373, 85, 202, +78, -95, 15, -308, -60, -300, -90, -102, +-20, 104, 124, 164, 233, 101, 189, 4, +37, -69, -111, -80, -163, -52, -65, -51, +129, -70, 241, -57, 181, -17, 29, 39, +-110, 90, -104, 78, 43, -10, 173, -106, +153, -159, 24, -149, -98, -62, -84, 59, +71, 138, 213, 148, 198, 75, 48, -79, +-114, -229, -174, -259, -56, -149, 155, 49, +279, 238, 222, 274, 42, 106, -150, -148, +-194, -320, -56, -323, 143, -139, 240, 130, +208, 297, 82, 266, -60, 69, -116, -187, +-70, -351, 38, -312, 140, -96, 177, 155, +101, 299, 6, 256, -39, 40, -17, -216, +41, -342, 86, -273, 65, -54, 25, 184, +32, 280, 57, 179, 69, -33, 60, -212, +33, -261, -6, -167, 1, -5, 42, 104, +98, 127, 122, 101, 82, 27, -5, -80, +-49, -161, -23, -193, 54, -149, 131, -3, +154, 156, 98, 206, -11, 112, -72, -72, +-40, -252, 68, -289, 140, -135, 120, 75, +25, 208, -28, 212, 15, 70, 97, -124, +106, -231, 27, -219, -54, -134, -49, 15, +60, 159, 194, 198, 216, 136, 67, -13, +-121, -221, -206, -336, -70, -241, 191, -6, +344, 242, 240, 346, -13, 183, -212, -145, +-201, -370, -3, -352, 204, -139, 264, 139, +164, 282, 24, 196, -75, 12, -65, -130, +10, -210, 77, -206, 71, -117, 52, -19, +55, 91, 86, 189, 118, 160, 100, -4, +14, -180, -79, -266, -86, -214, -3, -40, +140, 122, 227, 167, 190, 122, 48, 37, +-75, -82, -137, -184, -84, -218, 59, -170, +189, -31, 209, 150, 130, 236, 29, 148, +-34, -41, -32, -217, -15, -289, -6, -210, +11, -42, 83, 114, 165, 213, 232, 221, +188, 98, 12, -133, -196, -350, -270, -412, +-124, -230, 180, 143, 421, 458, 402, 458, +143, 112, -186, -351, -345, -620, -238, -484, +44, -16, 295, 429, 373, 545, 232, 276, +20, -182, -119, -510, -138, -479, -98, -150, +-19, 206, 84, 360, 181, 249, 263, -30, +246, -252, 78, -264, -155, -130, -272, 17, +-202, 90, 71, 48, 351, -35, 428, -43, +231, 12, -86, 33, -298, -26, -246, -139, +19, -209, 249, -119, 280, 90, 155, 222, +14, 156, -60, -66, -14, -266, 42, -269, +46, -63, 14, 148, 33, 173, 76, 33, +114, -125, 113, -164, 61, -61, 1, 52, +-4, 45, 15, -42, 12, -104, 49, -85, +85, -7, 107, 59, 103, 46, 70, -38, +-11, -100, -28, -105, 30, -67, 79, 6, +79, 58, 51, 35, 15, -37, 41, -105, +133, -121, 154, -61, 71, 41, -65, 91, +-136, 30, -74, -82, 122, -162, 267, -150, +260, -29, 117, 110, -50, 142, -146, 35, +-125, -124, -37, -230, 79, -195, 207, -26, +288, 131, 253, 169, 66, 83, -144, -66, +-260, -197, -189, -226, 15, -135, 262, 10, +394, 149, 334, 202, 102, 99, -175, -104, +-342, -260, -276, -270, 13, -124, 330, 92, +485, 210, 348, 158, 26, 12, -265, -129, +-331, -208, -179, -187, 93, -85, 295, 32, +346, 118, 247, 142, 72, 64, -93, -79, +-195, -187, -184, -212, -56, -139, 139, 12, +291, 140, 331, 162, 203, 75, -8, -74, +-192, -208, -234, -232, -133, -126, 84, 28, +300, 137, 369, 157, 237, 68, -8, -82, +-211, -197, -241, -228, -66, -154, 141, 19, +283, 170, 283, 181, 138, 56, -61, -117, +-147, -232, -99, -207, 31, -76, 137, 53, +153, 125, 117, 132, 87, 57, 66, -88, +5, -210, -44, -242, -33, -144, 48, 67, +117, 231, 132, 204, 89, 10, 58, -206, +28, -310, 19, -234, 16, -16, 21, 182, +58, 242, 85, 151, 84, -67, 66, -292, +40, -344, 1, -180, 33, 92, 99, 293, +134, 262, 86, 5, 4, -264, -76, -345, +-52, -212, 78, 33, 198, 206, 209, 192, +113, 41, -21, -112, -117, -190, -89, -168, +4, -75, 114, 13, 194, 47, 225, 48, +145, 29, 7, -7, -121, -45, -161, -91, +-81, -143, 104, -149, 266, -69, 295, 64, +206, 169, 12, 165, -188, 12, -251, -208, +-123, -331, 74, -251, 285, 0, 394, 257, +305, 327, 42, 138, -226, -178, -372, -392, +-261, -349, 89, -78, 410, 217, 493, 324, +324, 173, -13, -97, -344, -283, -400, -273, +-188, -109, 170, 59, 471, 120, 501, 81, +189, 14, -187, -31, -347, -60, -237, -91, +30, -127, 249, -132, 281, -70, 191, 39, +116, 140, 38, 157, -47, 54, -150, -140, +-182, -311, -68, -312, 202, -99, 412, 211, +374, 392, 96, 262, -223, -118, -370, -454, +-228, -477, 122, -164, 404, 245, 424, 441, +179, 286, -132, -75, -301, -364, -185, -401, +76, -194, 269, 92, 265, 259, 127, 215, +-34, 32, -99, -156, -41, -233, 49, -162, +110, -29, 116, 43, 74, 32, 15, 4, +16, 1, 55, 32, 90, 32, 71, -62, +6, -183, -47, -211, -3, -101, 108, 89, +186, 226, 142, 189, 4, -14, -107, -233, +-103, -326, 50, -227, 214, 16, 238, 233, +78, 273, -104, 114, -163, -133, -49, -304, +142, -286, 261, -104, 212, 96, 61, 184, +-104, 147, -185, 39, -79, -80, 115, -165, +230, -205, 201, -181, 88, -57, -30, 127, +-41, 241, 1, 177, 14, -47, -9, -281, +16, -343, 90, -166, 176, 100, 211, 250, +121, 212, -64, 26, -213, -183, -197, -277, +6, -224, 303, -75, 439, 112, 277, 236, +-82, 180, -348, -36, -325, -253, -40, -309, +278, -150, 414, 107, 301, 234, 63, 132, +-151, -64, -261, -181, -196, -160, 13, -61, +238, 6, 323, 3, 247, 3, 51, 48, +-117, 54, -169, -17, -122, -116, -18, -172, +125, -122, 243, 12, 250, 108, 137, 100, +-42, 31, -168, -61, -163, -143, -37, -166, +113, -119, 231, -23, 250, 102, 158, 169, +-12, 103, -164, -51, -201, -200, -92, -260, +113, -170, 300, 36, 312, 209, 118, 223, +-121, 73, -225, -158, -123, -302, 74, -232, +200, -19, 178, 149, 103, 166, 24, 63, +-46, -62, -63, -115, -3, -107, 76, -94, +129, -75, 111, -10, 2, 69, -57, 93, +-2, 27, 91, -82, 116, -132, 81, -90, +3, -25, -31, -15, 17, -37, 74, -6, +75, 67, 46, 89, 6, -9, -14, -168, +35, -224, 107, -85, 120, 130, 46, 191, +-57, 39, -109, -165, -10, -219, 170, -68, +250, 128, 125, 147, -93, -23, -217, -190, +-125, -188, 119, -29, 298, 134, 253, 147, +45, 6, -138, -137, -192, -170, -66, -119, +130, -30, 218, 65, 153, 112, 19, 97, +-93, 7, -74, -137, 56, -231, 147, -164, +104, 27, -9, 176, -89, 157, -51, -4, +104, -157, 202, -152, 130, -22, -27, 42, +-123, -28, -95, -118, 52, -90, 175, 71, +168, 210, 66, 129, -34, -147, -72, -344, +-35, -264, 28, 21, 57, 264, 78, 258, +105, 40, 116, -171, 66, -213, -45, -129, +-143, -54, -102, -15, 57, 38, 198, 120, +203, 158, 87, 53, -26, -179, -53, -323, +-40, -213, -44, 52, -43, 241, 29, 206, +174, 5, 265, -153, 168, -137, -87, -60, +-275, -68, -216, -117, 62, -86, 313, 82, +311, 278, 77, 265, -166, -38, -207, -391, +-49, -471, 127, -196, 159, 225, 76, 462, +-1, 330, 3, -43, 43, -347, 47, -390, +9, -200, -13, 61, -14, 215, -3, 187, +43, 74, 113, -19, 148, -86, 90, -149, +-40, -196, -146, -176, -108, -31, 37, 200, +165, 315, 186, 167, 101, -132, -15, -355, +-87, -324, -111, -69, -69, 185, 48, 242, +187, 131, 229, -4, 119, -99, -79, -163, +-228, -192, -172, -166, 60, -27, 266, 189, +272, 293, 72, 157, -158, -123, -187, -337, +-21, -337, 147, -101, 146, 209, 12, 347, +-88, 230, -30, -53, 111, -337, 157, -382, +53, -121, -82, 214, -111, 321, -2, 135, +132, -172, 149, -280, 45, -93, -64, 134, +-93, 115, -9, -104, 110, -220, 144, -34, +67, 267, -46, 296, -97, -74, -44, -478, +61, -444, 125, 63, 100, 541, 25, 483, +-24, -78, -24, -593, -2, -543, 20, 25, +37, 515, 40, 442, 41, -59, 44, -460, +42, -371, 24, 92, -23, 395, -69, 193, +-35, -245, 67, -423, 141, -135, 122, 349, +28, 498, -69, 84, -94, -478, -50, -607, +2, -171, 59, 417, 133, 602, 161, 206, +104, -349, -29, -513, -181, -210, -198, 175, +-26, 271, 186, 64, 273, -153, 170, -100, +-61, 115, -193, 161, -120, -51, 38, -293, +117, -302, 85, -15, 0, 317, -6, 372, +78, 112, 109, -220, 7, -388, -125, -288, +-177, -2, -66, 245, 155, 306, 297, 167, +240, -81, 14, -265, -229, -253, -312, -82, +-157, 85, 116, 111, 309, 29, 321, -8, +157, 69, -90, 132, -267, 26, -281, -252, +-121, -437, 145, -243, 343, 247, 315, 602, +73, 474, -203, -106, -303, -671, -162, -700, +100, -154, 257, 490, 211, 718, 47, 366, +-104, -258, -156, -616, -76, -462, 42, -4, +94, 366, 82, 378, 47, 97, 7, -166, +2, -204, 10, -69, -27, 35, -67, -6, +-40, -103, 53, -83, 156, 80, 162, 224, +-2, 159, -182, -105, -170, -317, 37, -262, +248, 16, 233, 283, -41, 302, -283, 42, +-208, -250, 94, -328, 300, -164, 214, 117, +-58, 312, -197, 243, -76, -22, 87, -258, +84, -294, -39, -127, -110, 133, -1, 238, +191, 107, 215, -66, 21, -96, -184, -23, +-197, 52, -39, -11, 125, -196, 145, -229, +56, 30, -9, 329, 11, 367, 40, 76, +0, -362, -104, -522, -112, -215, 20, 243, +155, 445, 153, 301, 18, -61, -101, -302, +-66, -235, 25, -58, 34, -6, -32, -7, +-46, 24, 45, 161, 153, 309, 137, 204, +-15, -206, -160, -534, -157, -488, -42, -33, +90, 497, 158, 643, 147, 270, 98, -258, +-14, -546, -173, -422, -241, -48, -140, 254, +93, 310, 316, 207, 313, 45, 56, -103, +-234, -175, -299, -197, -112, -154, 124, -13, +171, 138, 58, 199, -2, 186, 86, 55, +131, -138, 2, -270, -233, -241, -300, -73, +-44, 182, 296, 321, 367, 209, 111, -41, +-215, -221, -282, -274, -62, -146, 167, 66, +155, 196, -34, 203, -165, 123, -68, -93, +165, -266, 264, -207, 76, 17, -212, 220, +-311, 247, -99, 2, 220, -261, 328, -217, +123, 50, -176, 218, -271, 144, -83, -119, +160, -264, 236, -68, 93, 231, -131, 276, +-226, 45, -110, -262, 105, -353, 235, -113, +182, 203, -29, 320, -218, 214, -195, -26, +4, -256, 164, -315, 165, -178, 32, 89, +-66, 352, -46, 379, -13, 80, -49, -326, +-80, -510, -53, -277, 80, 217, 221, 541, +208, 398, -2, -52, -237, -422, -323, -406, +-172, -70, 141, 227, 357, 207, 280, 6, +28, -91, -210, 47, -261, 238, -103, 194, +54, -188, 73, -539, 58, -445, 68, 95, +102, 616, 92, 673, -30, 133, -181, -524, +-189, -700, -26, -286, 149, 275, 213, 542, +85, 316, -104, -139, -123, -347, -7, -182, +48, 55, 12, 159, -96, 68, -100, -102, +89, -89, 285, 97, 208, 190, -86, 74, +-369, -145, -383, -307, -73, -198, 333, 127, +460, 350, 271, 273, -87, 37, -392, -197, +-410, -246, -133, -122, 177, -13, 312, -23, +215, 29, 7, 172, -109, 298, -79, 230, +-5, -79, -32, -450, -110, -475, -154, -83, +-39, 365, 195, 496, 339, 243, 191, -183, +-110, -376, -374, -204, -351, 44, -35, 145, +334, 107, 371, 18, 95, 0, -240, 73, +-322, 21, -105, -131, 222, -197, 258, -106, +26, 103, -210, 316, -209, 243, 19, -48, +259, -286, 190, -311, -99, -113, -277, 207, +-181, 314, 73, 135, 271, -89, 224, -197, +-20, -123, -197, 92, -205, 158, -80, -17, +89, -165, 146, -137, 53, 34, -17, 234, +-47, 247, -1, -20, 70, -235, 59, -229, +-89, -77, -185, 105, -150, 216, 16, 113, +194, -3, 278, -46, 151, -90, -69, -122, +-274, -35, -335, 29, -153, 71, 176, 125, +358, 69, 252, -58, -63, -50, -283, -21, +-209, -53, 60, -18, 196, 8, 31, -1, +-209, 75, -191, 120, 98, 4, 350, -47, +262, -58, -120, -75, -436, -16, -359, 78, +31, 26, 352, 8, 362, 9, 100, -23, +-201, 4, -265, 99, -142, 29, -21, -91, +57, -154, 98, -114, 117, 76, 137, 315, +62, 246, -112, -90, -235, -373, -206, -365, +-71, -20, 129, 433, 275, 507, 231, 104, +54, -352, -130, -524, -301, -257, -296, 231, +-84, 499, 145, 286, 303, -89, 320, -333, +111, -244, -229, 68, -418, 279, -334, 106, +10, -167, 385, -255, 426, -42, 63, 284, +-287, 394, -353, 36, -95, -382, 214, -439, +254, -96, -19, 364, -215, 519, -150, 140, +81, -350, 204, -465, 120, -196, -133, 243, +-237, 481, -94, 280, 100, -145, 172, -377, +106, -340, -98, -25, -180, 319, -47, 389, +85, 116, 81, -196, 1, -359, -99, -196, +-106, 142, 52, 334, 164, 182, 78, -84, +-57, -248, -156, -164, -189, 51, -39, 175, +123, 89, 155, -28, 149, -46, 75, 13, +-124, 34, -246, -23, -214, -89, -79, -69, +151, 50, 329, 121, 209, 74, -49, -34, +-224, -65, -274, -30, -127, 44, 104, 27, +161, -50, 113, -96, 59, 2, -52, 127, +-117, 173, -80, 51, -56, -121, -30, -216, +62, -110, 90, 79, 36, 194, 8, 144, +-50, 18, -108, -95, -55, -109, -15, -41, +11, -11, 94, -27, 111, 10, -2, 100, +-117, 154, -158, 132, -86, -29, 81, -216, +188, -250, 72, -90, -112, 103, -173, 269, +-80, 259, 103, 75, 182, -138, 47, -261, +-112, -274, -170, -64, -118, 229, 10, 371, +126, 246, 119, -82, 39, -408, -24, -380, +-67, 6, -94, 386, -50, 433, -40, 86, +-33, -355, 43, -443, 114, -83, 87, 323, +10, 400, -104, 73, -143, -317, -52, -363, +58, 5, 45, 354, -2, 341, 2, -39, +11, -393, 11, -363, -25, 45, -99, 396, +-73, 372, 68, 11, 153, -330, 101, -335, +-106, -11, -294, 294, -244, 274, 79, -18, +345, -288, 324, -281, 18, 34, -305, 362, +-363, 355, -96, 42, 137, -331, 165, -442, +41, -173, -36, 264, 1, 454, 79, 275, +16, -128, -111, -411, -176, -311, -91, 103, +46, 395, 141, 307, 115, -95, -8, -450, +-131, -369, -132, 119, -5, 529, 140, 455, +143, -44, -33, -525, -236, -501, -261, -1, +-11, 466, 255, 433, 298, -14, 86, -413, +-187, -346, -297, 84, -146, 429, 63, 316, +180, -111, 106, -420, -55, -318, -164, 50, +-79, 354, 88, 331, 166, 33, 54, -243, +-137, -269, -240, -68, -111, 184, 80, 280, +174, 94, 120, -199, -30, -334, -134, -157, +-90, 196, -16, 438, 19, 282, 14, -131, +-19, -445, -52, -338, -5, 52, 69, 389, +61, 324, -13, -41, -97, -352, -146, -271, +-44, 77, 91, 378, 113, 334, 42, -26, +-54, -421, -125, -457, -89, -100, 1, 352, +57, 549, 48, 302, 21, -218, -42, -543, +-69, -368, -40, 103, -23, 487, -5, 397, +44, -74, 38, -472, -2, -353, -55, 86, +-123, 461, -96, 370, 65, -74, 177, -453, +94, -333, -86, 73, -216, 402, -183, 311, +23, -67, 187, -382, 110, -260, -31, 101, +-103, 366, -78, 275, 24, -70, 62, -365, +-63, -290, -157, 54, -102, 330, 49, 304, +182, 0, 201, -304, -11, -300, -241, 16, +-246, 288, -92, 298, 92, 20, 174, -276, +56, -311, -78, -4, -39, 255, 24, 296, +26, 58, -41, -218, -136, -305, -156, -66, +8, 166, 127, 271, 96, 169, 35, -61, +-16, -266, -92, -221, -61, -71, -57, 144, +-86, 302, -22, 231, 71, -47, 57, -249, +27, -279, -27, -97, -87, 198, -32, 295, +75, 103, 40, -125, -92, -203, -173, -111, +-181, 121, 14, 211, 250, 60, 261, -128, +39, -158, -190, -81, -322, 104, -195, 195, +43, 92, 175, -90, 115, -134, 42, -86, +-44, 57, -71, 164, -38, 86, -35, -112, +-105, -166, -62, -73, 21, 111, 80, 248, +86, 138, -5, -149, -145, -279, -147, -147, +-2, 108, 98, 303, 92, 204, -7, -113, +-133, -287, -140, -142, 0, 138, 45, 320, +7, 176, -47, -198, -37, -409, 31, -217, +113, 190, 18, 484, -139, 375, -214, -88, +-102, -477, 61, -439, 203, -52, 112, 353, +-104, 430, -191, 108, -73, -255, 72, -298, +136, -15, -8, 272, -206, 276, -195, -71, +19, -389, 184, -335, 156, 68, -26, 421, +-213, 423, -175, 39, 33, -331, 150, -347, +75, -43, -79, 211, -222, 192, -159, -51, +56, -201, 212, -69, 160, 196, -14, 268, +-199, 96, -234, -154, -85, -265, 101, -149, +126, 36, 23, 114, -105, 98, -141, 85, +4, 51, 157, 16, 133, -55, -54, -113, +-237, -77, -270, 59, -74, 95, 178, 23, +247, -79, 76, -74, -108, 48, -178, 179, +-84, 108, 44, -93, 28, -225, -100, -132, +-125, 115, -40, 280, 99, 145, 174, -154, +86, -327, -117, -192, -222, 158, -175, 423, +-62, 322, 93, -46, 170, -355, 81, -386, +-58, -122, -146, 193, -165, 285, -25, 160, +119, 15, 114, -70, -27, -58, -163, -30, +-197, -73, -34, -114, 173, -34, 197, 84, +-2, 159, -207, 150, -281, 31, -115, -113, +162, -137, 254, -85, 115, 0, -115, 134, +-286, 185, -241, 59, 2, -129, 180, -262, +187, -228, 42, 89, -129, 414, -205, 398, +-79, 73, 58, -323, 65, -522, -46, -287, +-140, 165, -106, 385, 117, 308, 253, 97, +120, -103, -198, -125, -406, -39, -297, -102, +75, -203, 372, -143, 308, 49, -24, 273, +-281, 392, -271, 179, -60, -165, 113, -327, +45, -266, -103, -80, -121, 156, 39, 206, +183, 127, 157, 77, -81, 36, -296, -71, +-293, -117, -79, -126, 125, -75, 238, 77, +178, 171, -2, 81, -164, -39, -236, -98, +-217, -91, -49, 25, 144, 124, 202, 89, +93, 26, -92, 2, -207, -76, -146, -127, +29, -117, 73, -46, -18, 111, -109, 304, +-81, 247, 59, -4, 179, -258, 61, -339, +-172, -191, -316, 117, -218, 247, 60, 180, +304, 81, 272, 27, 6, -7, -282, -25, +-360, -133, -188, -220, 114, -106, 246, 118, +122, 231, -79, 179, -185, 14, -108, -115, +63, -49, 103, 53, -52, 3, -212, -153, +-207, -204, 5, -75, 230, 232, 256, 407, +-7, 255, -306, -113, -349, -346, -106, -320, +212, -58, 308, 188, 64, 225, -249, 76, +-324, -16, -113, -16, 172, 17, 239, -3, +34, -86, -223, -153, -237, -67, -28, 103, +170, 200, 155, 166, -62, 26, -293, -115, +-249, -167, -4, -103, 241, -31, 277, 76, +75, 167, -224, 177, -344, 50, -226, -109, +-2, -232, 163, -175, 198, 7, 51, 170, +-93, 155, -106, 72, -68, 19, -24, 55, +-17, 47, -110, -80, -191, -276, -95, -289, +103, -17, 266, 356, 241, 498, -16, 257, +-360, -198, -431, -499, -214, -402, 129, -49, +357, 270, 287, 349, -48, 223, -279, 9, +-284, -113, -90, -153, 113, -125, 133, -65, +-61, 34, -188, 88, -94, 117, 116, 84, +225, 25, 86, -50, -258, -78, -450, -90, +-236, -62, 172, 14, 447, 105, 345, 132, +-96, 91, -502, -17, -475, -123, -110, -132, +263, -30, 374, 94, 171, 155, -189, 113, +-307, -32, -172, -133, 8, -106, 104, 20, +54, 108, -106, 95, -132, -51, -19, -142, +60, -57, 65, 130, 15, 200, -104, 93, +-171, -135, -100, -248, -23, -104, 55, 166, +111, 267, 9, 137, -146, -118, -151, -263, +-78, -146, 64, 97, 168, 210, 54, 139, +-188, -29, -258, -167, -151, -137, 42, 5, +238, 106, 198, 131, -89, 94, -274, -21, +-245, -103, -78, -80, 172, -11, 227, 61, +-10, 106, -247, 36, -251, -74, -82, -81, +186, -15, 285, 56, 48, 90, -284, 20, +-356, -92, -185, -86, 141, 16, 347, 98, +176, 114, -185, 27, -350, -107, -244, -109, +62, 17, 312, 122, 203, 125, -179, 15, +-417, -152, -293, -192, 62, -30, 402, 157, +353, 232, -82, 137, -442, -80, -426, -233, +-134, -164, 243, -2, 342, 134, 81, 172, +-218, 112, -233, -1, -63, -34, 119, -46, +119, -71, -132, -87, -347, -54, -199, -7, +116, 101, 348, 162, 324, 117, -54, 3, +-464, -96, -508, -161, -182, -125, 228, 8, +471, 129, 295, 180, -152, 130, -435, -12, +-355, -141, -81, -128, 236, -32, 269, 71, +5, 77, -219, 6, -194, -77, -36, -14, +151, 97, 113, 134, -152, -7, -329, -173, +-184, -231, 114, -19, 330, 273, 263, 372, +-103, 120, -427, -219, -396, -391, -112, -214, +192, 126, 320, 317, 140, 196, -129, -20, +-238, -123, -139, -64, -3, 34, 64, 6, +-38, -124, -187, -157, -190, 22, 1, 234, +188, 314, 266, 152, 97, -108, -223, -285, +-418, -221, -331, -70, -48, 86, 247, 157, +323, 174, 130, 110, -135, 56, -250, -62, +-197, -175, -66, -219, 39, -118, 7, 29, +-50, 213, -31, 282, 28, 186, 54, -8, +35, -172, -84, -262, -189, -187, -192, 10, +-55, 156, 106, 206, 188, 165, 86, 28, +-139, -122, -278, -154, -195, -129, 6, -25, +173, 95, 154, 130, -28, 48, -191, 13, +-204, -9, -75, 7, 59, 31, 103, 12, +20, -81, -116, -65, -182, 7, -80, 51, +77, 55, 170, 24, 55, -39, -176, -3, +-322, 76, -211, 40, 59, -62, 259, -115, +219, -95, -22, 45, -271, 219, -284, 196, +-117, 25, 76, -138, 160, -214, 57, -145, +-111, 91, -148, 224, -56, 165, 35, -3, +56, -185, -41, -245, -152, -33, -128, 216, +16, 254, 68, 96, 25, -150, -90, -295, +-182, -119, -100, 185, 110, 274, 187, 138, +99, -96, -135, -247, -352, -143, -341, 114, +-64, 181, 241, 76, 367, -64, 221, -141, +-135, -71, -403, 110, -370, 138, -144, 31, +111, -69, 230, -106, 107, -47, -45, 123, +-78, 188, -57, 81, -37, -75, -67, -196, +-179, -190, -195, 16, -36, 234, 144, 231, +185, 68, 85, -151, -110, -260, -217, -126, +-119, 129, -16, 202, -30, 105, -85, -68, +-118, -147, -43, -22, 144, 214, 215, 233, +76, 22, -169, -252, -352, -370, -345, -197, +-82, 213, 205, 465, 296, 368, 175, 12, +-49, -369, -261, -487, -263, -197, -139, 221, +-19, 418, 66, 301, 85, -34, 12, -303, +-30, -247, -18, 52, -26, 259, -50, 218, +-63, -60, -128, -314, -174, -264, -80, 69, +42, 330, 149, 305, 185, 10, 48, -301, +-173, -320, -279, -2, -251, 294, -102, 304, +97, 29, 196, -271, 99, -295, -29, 7, +-117, 310, -124, 313, -32, 42, 4, -263, +-121, -323, -200, -84, -132, 203, 49, 257, +254, 83, 260, -130, -6, -172, -279, -20, +-340, 144, -220, 121, 6, -39, 172, -139, +128, -59, 11, 135, -29, 225, -58, 73, +-56, -203, -38, -320, -109, -145, -177, 198, +-123, 394, -7, 277, 117, -82, 187, -362, +88, -352, -133, -60, -243, 227, -173, 329, +-38, 190, 86, -36, 56, -177, -94, -125, +-136, -8, -18, 80, 105, 51, 140, -50, +11, -107, -203, -14, -309, 129, -187, 180, +14, 77, 179, -120, 222, -219, 88, -103, +-113, 111, -208, 191, -226, 102, -143, -85, +28, -149, 120, -9, 80, 185, -6, 174, +-80, 0, -103, -214, -14, -262, 48, -97, +-43, 163, -157, 245, -161, 172, -76, 18, +106, -93, 189, -107, 53, -43, -151, -61, +-214, -92, -146, -41, 23, 98, 131, 262, +58, 332, -105, 131, -150, -238, -113, -462, +-20, -395, 97, -67, 108, 345, 2, 514, +-90, 310, -167, -16, -176, -271, -69, -335, +49, -201, 73, -11, 56, 87, 17, 190, +-47, 249, -60, 182, -63, 24, -129, -143, +-141, -273, -64, -189, 6, 42, 78, 178, +125, 143, 52, 22, -76, -104, -154, -82, +-184, 81, -134, 153, 23, 73, 129, -63, +74, -150, -35, -122, -140, 44, -159, 123, +6, 58, 140, -14, 50, 2, -130, 58, +-222, 136, -152, 63, 86, -167, 235, -309, +79, -206, -169, 47, -239, 323, -135, 385, +82, 146, 197, -158, 32, -283, -169, -206, +-172, -3, -67, 174, 58, 147, 101, 27, +-39, -48, -165, -61, -96, -36, 42, 39, +118, 51, 125, 34, -31, 18, -230, -9, +-243, -77, -123, -69, 30, -40, 199, 4, +197, 65, 20, 118, -133, 98, -186, 95, +-158, 63, -27, -48, 58, -178, -10, -236, +-104, -187, -111, 32, -28, 292, 146, 367, +227, 199, 61, -85, -192, -309, -315, -309, +-258, -67, -52, 152, 140, 201, 148, 100, +61, -37, 12, -88, 5, 14, 2, 93, +-25, 52, -145, -52, -264, -106, -228, -74, +-51, 52, 164, 104, 297, 7, 217, -132, +-27, -136, -230, 14, -252, 249, -130, 349, +18, 167, 65, -179, -26, -415, -109, -383, +-51, -89, 97, 263, 212, 406, 172, 271, +-54, 29, -305, -151, -370, -188, -194, -115, +105, -64, 309, -72, 254, -40, -5, 65, +-214, 176, -211, 209, -57, 110, 80, -74, +55, -168, -77, -111, -132, 17, -59, 100, +50, 71, 75, -64, -7, -161, -120, -115, +-134, 47, -6, 211, 137, 277, 141, 161, +-6, -77, -224, -272, -332, -309, -195, -169, +75, 88, 269, 276, 276, 267, 96, 112, +-149, -75, -271, -173, -207, -118, -75, 25, +40, 91, 88, 48, 23, -65, -49, -140, +-36, -101, 11, 60, 71, 166, 103, 171, +9, 86, -143, -7, -229, -61, -201, -53, +-53, -95, 157, -165, 242, -163, 140, -2, +-19, 229, -142, 378, -156, 257, -54, -81, +-2, -371, -52, -361, -78, -78, -39, 244, +49, 322, 143, 88, 122, -207, -30, -267, +-140, -39, -144, 256, -85, 357, 6, 132, +40, -202, -35, -360, -69, -215, -19, 54, +50, 230, 96, 139, 46, -66, -117, -142, +-197, 18, -108, 228, 45, 288, 128, 59, +66, -290, -120, -465, -230, -281, -140, 99, +46, 432, 202, 472, 225, 205, 38, -155, +-205, -350, -298, -314, -199, -107, 37, 116, +227, 207, 180, 150, -46, 34, -197, -58, +-147, -82, 41, -23, 213, 18, 170, 20, +-72, 2, -252, 28, -241, 74, -77, 102, +135, 3, 226, -184, 128, -293, -10, -162, +-83, 152, -101, 435, -56, 406, 3, 50, +-19, -349, -69, -456, -66, -223, -29, 131, +56, 293, 147, 160, 99, -60, -43, -111, +-128, 40, -125, 206, -35, 195, 54, -28, +-10, -270, -172, -320, -199, -147, -36, 85, +213, 221, 367, 191, 201, 84, -200, 15, +-444, 26, -360, 38, -60, -9, 227, -129, +243, -246, 21, -237, -120, -46, -44, 214, +88, 371, 120, 303, -28, 45, -249, -205, +-263, -281, -32, -170, 173, -8, 213, 74, +87, 35, -95, -28, -147, -10, -49, 88, +45, 167, 91, 171, 84, 74, -5, -72, +-125, -199, -180, -238, -136, -180, 19, -7, +220, 181, 268, 269, 109, 197, -88, 27, +-196, -107, -158, -108, -18, -35, 44, -30, +-26, -124, -84, -191, -32, -76, 94, 193, +201, 397, 171, 305, -22, -38, -205, -353, +-227, -350, -134, -63, -5, 218, 61, 222, +14, -13, -28, -231, 28, -159, 119, 120, +142, 319, 40, 223, -167, -72, -319, -300, +-257, -235, -34, 21, 173, 199, 240, 140, +129, -61, -49, -189, -122, -79, -82, 175, +-15, 306, 25, 180, -5, -111, -82, -347, +-106, -338, -46, -84, 46, 184, 140, 290, +187, 204, 117, 32, -23, -86, -134, -83, +-174, -50, -122, -49, -7, -75, 78, -67, +106, 13, 119, 141, 115, 178, 53, 70, +-42, -121, -128, -244, -160, -168, -69, 84, +101, 311, 187, 311, 125, 54, -54, -285, +-225, -445, -223, -279, -10, 100, 216, 402, +267, 413, 105, 152, -152, -160, -282, -294, +-176, -196, 15, -27, 96, 65, 46, 32, +-49, -34, -72, -18, 38, 92, 141, 182, +89, 154, -61, 4, -206, -169, -254, -241, +-127, -148, 74, 44, 183, 190, 181, 193, +98, 41, -33, -144, -94, -190, -79, -39, +-84, 165, -84, 235, -39, 80, 14, -170, +88, -285, 147, -150, 110, 75, 20, 198, +-29, 146, -51, 24, -43, -15, -10, 48, +-11, 53, -24, -71, 20, -220, 76, -223, +98, -22, 88, 231, 18, 295, -70, 119, +-71, -117, -17, -205, 19, -95, 40, 70, +34, 103, 10, -29, 5, -144, -14, -115, +-70, 64, -84, 244, -14, 262, 67, 78, +105, -178, 60, -341, -70, -290, -161, -52, +-130, 231, -30, 364, 55, 265, 76, -8, +13, -263, -57, -320, -39, -155, 33, 92, +57, 234, -6, 191, -127, 20, -194, -114, +-112, -125, 77, -36, 205, 47, 195, 61, +54, 13, -116, -31, -175, -37, -82, -3, +53, 24, 125, 34, 83, 16, -45, -9, +-130, -30, -65, -19, 97, -5, 226, 14, +196, 33, 12, 24, -155, 0, -144, 6, +-2, 23, 107, 28, 88, 0, -24, -73, +-81, -125, 14, -84, 157, 33, 172, 143, +55, 168, -88, 70, -149, -60, -82, -124, +14, -99, 25, -45, -18, 3, -26, 7, +33, 17, 110, 74, 122, 127, 24, 90, +-121, -14, -204, -139, -188, -173, -101, -77, +31, 61, 131, 126, 152, 100, 103, 8, +12, -67, -90, -55, -124, -6, -99, 19, +-72, 17, -57, 0, -37, -8, -6, 25, +73, 46, 161, 35, 149, -8, 49, -71, +-71, -122, -151, -95, -113, 6, 23, 150, +107, 244, 83, 181, -7, -37, -78, -271, +-20, -350, 159, -179, 274, 136, 196, 356, +-27, 330, -259, 96, -305, -173, -107, -294, +165, -219, 312, -52, 285, 96, 115, 169, +-81, 165, -168, 98, -147, 0, -77, -113, +13, -174, 63, -142, 63, -29, 67, 86, +73, 149, 22, 128, -39, 45, -76, -50, +-82, -106, -25, -106, 42, -44, 31, 42, +-27, 88, -82, 47, -117, -54, -97, -113, +-3, -70, 100, 67, 163, 185, 149, 172, +7, 21, -186, -149, -274, -233, -212, -157, +-33, 2, 172, 131, 254, 158, 183, 117, +56, 39, -60, -5, -143, -31, -138, -82, +-84, -142, 0, -133, 120, -34, 206, 121, +180, 201, 89, 107, -23, -87, -98, -182, +-76, -80, 6, 137, 56, 243, 78, 82, +77, -212, 53, -342, 36, -173, 47, 139, +38, 313, 25, 184, 25, -59, -5, -131, +-36, 18, -40, 161, -37, 66, -7, -267, +69, -476, 99, -258, 63, 268, -15, 668, +-105, 580, -137, 30, -53, -530, 58, -656, +87, -304, 43, 176, -38, 414, -97, 279, +-70, -14, -29, -159, -28, -72, -19, 105, +12, 155, 44, 2, 52, -219, 6, -297, +-81, -155, -109, 108, -42, 296, 53, 272, +126, 75, 119, -112, 6, -152, -106, -57, +-118, 34, -39, -3, 83, -143, 173, -235, +153, -127, 43, 172, -55, 430, -73, 400, +-12, 74, 89, -324, 141, -484, 109, -296, +32, 66, -44, 275, -67, 207, -12, -6, +84, -108, 144, 15, 126, 200, 34, 183, +-76, -72, -109, -363, -32, -393, 76, -86, +128, 312, 73, 462, -50, 243, -125, -154, +-80, -387, 27, -266, 101, 70, 71, 324, +-42, 281, -143, -4, -138, -293, -38, -335, +70, -120, 118, 185, 81, 333, -6, 224, +-79, -47, -114, -229, -134, -205, -122, -17, +-56, 133, 64, 113, 188, -47, 229, -148, +111, -89, -101, 99, -257, 230, -218, 160, +-15, -63, 187, -229, 226, -210, 100, -39, +-37, 122, -55, 137, 27, 41, 95, -41, +65, -33, -39, 24, -96, 56, -33, 16, +108, -44, 206, -69, 185, -42, 53, -12, +-70, 7, -74, 8, 10, 39, 65, 74, +40, 68, -37, -7, -71, -82, 7, -103, +134, -38, 181, 34, 119, 43, -11, -7, +-128, -36, -154, -1, -99, 77, -41, 91, +25, -5, 85, -108, 87, -99, 59, 27, +20, 151, -49, 116, -109, -93, -134, -270, +-137, -231, -71, 39, 66, 345, 160, 409, +142, 132, 35, -257, -112, -456, -177, -300, +-82, 76, 49, 351, 78, 303, 8, 29, +-95, -219, -88, -238, 80, -27, 238, 184, +217, 189, 59, 26, -121, -138, -192, -171, +-100, -53, 19, 62, 63, 48, 100, -41, +161, -57, 187, 49, 170, 204, 65, 229, +-114, 40, -214, -233, -148, -367, 2, -238, +172, 76, 270, 323, 209, 300, 49, 54, +-86, -199, -160, -247, -127, -54, -2, 188, +88, 239, 92, 48, 48, -232, -32, -340, +-73, -176, -12, 137, 59, 342, 71, 290, +32, 41, -58, -168, -138, -187, -118, -54, +-56, 48, -22, -5, 15, -169, 48, -216, +73, -31, 105, 286, 62, 468, -65, 305, +-158, -125, -164, -471, -99, -469, 22, -145, +114, 223, 131, 337, 114, 163, 73, -59, +-21, -93, -102, 37, -115, 148, -50, 54, +74, -167, 166, -291, 133, -167, 27, 75, +-45, 236, -42, 178, 36, -3, 115, -108, +107, -29, 37, 111, -13, 153, -23, 10, +-7, -215, 21, -337, 26, -218, 39, 68, +86, 349, 124, 413, 115, 199, 46, -146, +-67, -373, -151, -324, -146, -53, -54, 205, +58, 230, 126, 48, 105, -143, 45, -150, +0, 28, -14, 210, -28, 201, -72, 22, +-122, -179, -126, -223, -67, -115, 26, 24, +99, 73, 106, 53, 61, 29, 6, 70, +-53, 122, -99, 96, -99, -42, -61, -196, +-10, -246, 29, -131, 40, 77, 42, 229, +84, 219, 126, 79, 94, -73, -12, -133, +-133, -92, -187, -42, -107, -41, 48, -59, +177, -18, 240, 100, 204, 216, 80, 190, +-50, -1, -127, -229, -131, -310, -45, -173, +70, 88, 128, 263, 133, 235, 88, 68, +9, -92, -28, -136, 0, -78, 34, -11, +56, -10, 36, -50, -39, -71, -77, -15, +-33, 92, 34, 184, 78, 175, 64, 51, +-10, -138, -59, -252, -38, -213, -8, -32, +-5, 160, -11, 220, -36, 113, -26, -47, +32, -122, 41, -56, -6, 57, -47, 75, +-68, -38, -44, -155, 20, -147, 47, -6, +24, 172, -2, 221, -28, 102, -49, -70, +-32, -146, -2, -113, 31, -8, 76, 39, +88, 9, 45, -32, 5, -6, -27, 56, +-48, 123, -31, 92, 16, -34, 53, -157, +90, -175, 95, -86, 48, 71, 11, 168, +15, 135, 38, 27, 60, -62, 46, -81, +-31, -25, -86, 19, -70, -11, 7, -62, +115, -60, 184, 14, 141, 102, 20, 129, +-95, 34, -142, -84, -94, -141, 9, -88, +56, 25, 51, 121, 28, 117, 16, 24, +20, -91, 14, -139, -28, -95, -57, 29, +-48, 142, -29, 167, -10, 71, -8, -73, +-27, -168, -26, -142, 15, -30, 67, 65, +98, 84, 74, 42, -12, 3, -114, 10, +-164, 52, -134, 53, -18, -7, 116, -91, +181, -132, 155, -96, 80, 17, -4, 120, +-56, 154, -73, 94, -81, -16, -62, -115, +-5, -120, 65, -50, 128, 31, 155, 62, +112, 28, 46, -38, -9, -44, -53, 16, +-66, 81, -42, 92, -22, 25, 5, -76, +38, -116, 61, -69, 103, 1, 145, 53, +119, 43, 12, 8, -126, 1, -229, 44, +-211, 71, -52, 36, 127, -71, 219, -166, +207, -160, 93, -16, -55, 159, -134, 238, +-156, 151, -140, -40, -73, -186, -9, -171, +43, -46, 111, 74, 144, 81, 103, -9, +12, -75, -92, -39, -150, 69, -96, 145, +6, 116, 46, -11, 40, -133, 18, -176, +16, -124, 66, -21, 116, 76, 80, 129, +-11, 144, -85, 96, -106, 13, -47, -76, +58, -136, 108, -151, 103, -98, 81, -6, +29, 107, -10, 187, -7, 170, -4, 38, +4, -127, 28, -213, 18, -148, -17, 30, +-22, 157, 7, 145, 56, 31, 126, -75, +119, -89, 10, -16, -110, 25, -158, -7, +-112, -46, 23, -15, 118, 75, 101, 131, +37, 47, -28, -115, -66, -201, -41, -101, +-2, 101, -2, 230, -9, 152, -12, -64, +-23, -217, -22, -172, -9, 13, -17, 170, +0, 174, 38, 40, 46, -97, 25, -135, +-9, -78, -58, -10, -70, 41, -29, 66, +26, 81, 73, 72, 98, 23, 74, -82, +31, -157, -4, -125, -41, 11, -55, 152, +-13, 183, 42, 69, 78, -97, 98, -185, +70, -138, 19, -1, 6, 112, 17, 125, +19, 49, 12, -23, -21, -47, -28, -35, +24, -15, 84, -12, 87, -24, 41, -8, +-29, 17, -71, 36, -42, 30, 11, 8, +34, -6, 31, 7, 9, 19, -20, 3, +-19, -31, -1, -62, 10, -63, -6, -17, +-44, 35, -89, 64, -77, 74, 3, 62, +105, 31, 145, -14, 59, -65, -119, -105, +-231, -97, -172, -49, 22, 27, 209, 95, +224, 126, 47, 89, -167, 26, -231, -44, +-98, -83, 111, -87, 202, -64, 115, -36, +-29, 13, -82, 67, -34, 103, 42, 88, +46, 16, -14, -77, -22, -113, 71, -58, +174, 47, 174, 101, 29, 39, -168, -93, +-234, -174, -99, -100, 147, 78, 335, 235, +314, 231, 77, 65, -188, -162, -292, -278, +-188, -226, 43, -37, 214, 154, 205, 239, +71, 175, -59, 34, -104, -104, -44, -159, +30, -120, 29, -24, -26, 47, -65, 68, +-55, 43, 18, 6, 79, -13, 41, -12, +-57, -8, -104, -2, -68, 20, 27, 36, +102, 31, 57, -12, -68, -74, -163, -113, +-149, -76, -13, 8, 158, 113, 202, 171, +104, 132, -58, 0, -180, -143, -188, -224, +-70, -161, 75, 7, 159, 170, 148, 215, +69, 123, -19, -33, -51, -135, -28, -127, +10, -62, 34, -1, 17, 33, 10, 40, +54, 55, 109, 77, 97, 42, 24, -52, +-57, -141, -67, -144, 18, -48, 132, 99, +146, 183, 57, 150, -66, 34, -121, -89, +-65, -163, 56, -148, 132, -68, 103, 33, +16, 109, -61, 131, -61, 94, -8, 30, +17, -29, -29, -65, -71, -84, -53, -95, +33, -86, 113, -29, 100, 70, -21, 154, +-148, 168, -171, 75, -76, -66, 49, -162, +112, -148, 76, -48, -9, 54, -82, 76, +-114, 27, -68, -28, 21, -12, 85, 54, +74, 102, 8, 69, -58, -51, -69, -162, +-35, -157, 12, -30, 40, 117, 57, 165, +61, 72, 50, -69, 30, -125, -6, -35, +-32, 88, -16, 119, 19, 5, 50, -151, +76, -185, 79, -44, 57, 136, 3, 205, +-41, 93, -41, -88, 39, -168, 135, -68, +138, 90, 28, 139, -102, 30, -147, -134, +-49, -189, 111, -63, 190, 128, 145, 216, +13, 140, -106, -40, -134, -169, -72, -159, +-14, -51, 8, 50, 24, 86, 71, 47, +103, 8, 83, 0, -21, 22, -150, 22, +-207, -4, -143, -58, 24, -83, 177, -47, +187, 41, 29, 100, -148, 81, -213, -19, +-118, -120, 56, -118, 169, 12, 122, 167, +-21, 199, -150, 54, -153, -181, -29, -301, +107, -192, 141, 83, 66, 300, -33, 288, +-71, 64, -13, -177, 55, -251, 51, -128, +-18, 32, -41, 93, 25, 33, 136, -25, +145, 2, 24, 83, -126, 103, -133, 7, +20, -127, 195, -160, 216, -51, 83, 101, +-84, 158, -173, 66, -130, -79, -2, -146, +133, -77, 201, 49, 182, 128, 66, 104, +-76, 17, -183, -69, -189, -102, -88, -88, +77, -43, 162, 17, 146, 81, 78, 108, +-4, 86, -75, 16, -109, -63, -115, -101, +-81, -84, -5, -35, 45, 19, 66, 56, +54, 65, 8, 53, -55, 27, -50, -18, +-17, -65, 15, -76, 18, -41, -37, 28, +-113, 67, -112, 55, -37, -7, 89, -45, +202, -29, 197, 28, 51, 58, -123, 14, +-227, -78, -215, -116, -62, -53, 122, 71, +223, 155, 210, 121, 113, -18, -17, -150, +-67, -174, -71, -78, -96, 71, -96, 154, +-13, 129, 108, 28, 209, -74, 196, -115, +48, -70, -90, 3, -124, 55, -70, 49, +35, 6, 113, -32, 65, -29, -13, -8, +-34, 21, -5, 28, 43, 26, 76, 22, +41, 8, -19, -33, -53, -84, -61, -97, +-29, -27, 31, 94, 45, 175, 5, 132, +-8, -15, -17, -154, -8, -188, 17, -92, +16, 46, -30, 122, -37, 88, -36, 26, +-34, -11, -4, -9, 16, -7, 11, -28, +22, -60, 27, -46, -5, 6, -27, 56, +-46, 44, -48, -13, -20, -43, 25, -1, +42, 75, 59, 95, 39, 2, -17, -149, +-58, -208, -36, -96, 13, 122, 51, 272, +54, 220, 44, -9, 35, -224, 8, -263, +-51, -103, -79, 99, -20, 191, 64, 128, +125, 15, 108, -47, 32, -46, -50, -46, +-62, -73, -21, -89, 19, -22, 4, 99, +-19, 168, 3, 111, 87, -40, 158, -153, +130, -128, -7, 0, -182, 97, -251, 77, +-143, -21, 99, -76, 284, -28, 266, 77, +51, 108, -172, 38, -257, -80, -136, -129, +48, -72, 145, 30, 96, 79, -4, 53, +-58, 1, -21, -7, 39, 21, 13, 45, +-80, 12, -124, -51, -41, -91, 102, -76, +178, -11, 82, 54, -83, 86, -185, 86, +-159, 65, -25, 6, 150, -74, 204, -147, +98, -149, -67, -60, -146, 94, -99, 201, +15, 182, 78, 40, 45, -112, -4, -180, +-20, -129, 19, -24, 85, 58, 101, 75, +7, 56, -97, 31, -135, 18, -63, 14, +77, 4, 188, -24, 155, -62, 16, -96, +-126, -94, -144, -25, -7, 93, 148, 192, +154, 180, 17, 34, -121, -159, -152, -243, +-28, -149, 140, 43, 212, 165, 117, 137, +-52, -3, -179, -91, -156, -43, -7, 67, +129, 97, 128, 4, 31, -127, -51, -158, +-36, -44, 34, 122, 50, 178, -15, 77, +-110, -75, -129, -146, -33, -71, 137, 62, +209, 130, 97, 69, -100, -62, -201, -150, +-153, -118, -12, 4, 97, 128, 116, 152, +73, 75, 8, -42, -46, -109, -63, -85, +-48, -9, -32, 29, -4, -1, 20, -53, +29, -49, 25, 43, 48, 151, 60, 160, +28, 28, -50, -157, -109, -256, -96, -169, +5, 42, 107, 220, 146, 216, 115, 54, +21, -128, -77, -164, -116, -41, -70, 111, +16, 125, 87, -5, 89, -165, 49, -185, +13, -33, 12, 170, 12, 235, 11, 118, +-4, -77, -33, -176, -52, -111, -6, 4, +81, 43, 123, -11, 81, -60, -28, -17, +-94, 109, -72, 186, -4, 127, 41, -44, +71, -195, 48, -229, -13, -119, -50, 48, +-31, 178, 1, 191, 19, 95, 2, -56, +-21, -146, 4, -113, 36, 21, 15, 124, +-42, 86, -88, -75, -85, -201, 2, -143, +106, 73, 120, 263, 35, 245, -67, 31, +-142, -196, -116, -245, -14, -110, 84, 57, +116, 109, 73, 48, -28, -29, -85, -19, +-48, 56, 5, 117, 24, 85, 28, -23, +25, -146, 18, -192, 23, -132, -7, 17, +-28, 168, 12, 223, 62, 130, 50, -43, +17, -157, -13, -134, -11, -23, 17, 56, +32, 33, 4, -41, -7, -60, 15, 17, +42, 121, 89, 127, 91, 23, 6, -108, +-85, -142, -91, -60, -45, 50, 29, 79, +70, 17, 77, -67, 64, -53, 57, 46, +12, 135, -62, 110, -116, -29, -121, -176, +-50, -193, 65, -52, 131, 123, 106, 200, +45, 119, -39, -36, -115, -128, -132, -100, +-70, -21, -6, 37, 37, 42, 42, 23, +31, 17, 57, 12, 81, -25, 7, -61, +-122, -42, -176, 27, -113, 76, 35, 51, +148, -35, 144, -94, 66, -44, -10, 68, +-78, 106, -111, 24, -77, -99, -12, -127, +54, -16, 138, 118, 150, 139, 65, 16, +-49, -122, -139, -143, -127, -37, -2, 94, +118, 133, 145, 63, 122, -29, 55, -84, +-40, -73, -94, -36, -89, 18, -61, 51, +39, 52, 139, 19, 147, -22, 72, -25, +-30, 16, -113, 53, -93, 17, -9, -72, +32, -131, 43, -68, 37, 77, 17, 176, +1, 125, 19, -27, -2, -127, -38, -77, +-57, 36, -61, 63, -38, -44, 25, -155, +58, -109, 50, 98, 24, 274, -43, 238, +-99, -6, -78, -242, -11, -276, 40, -117, +58, 67, -2, 140, -52, 103, -19, 58, +36, 58, 7, 58, -42, -11, -49, -130, +-1, -181, 62, -108, 60, 40, -5, 140, +-45, 131, -21, 55, 19, 4, 39, -3, +14, -21, -22, -79, -11, -130, 59, -105, +83, 36, 35, 182, -32, 192, -58, 47, +-14, -136, 59, -201, 72, -79, 34, 102, +0, 162, 0, 48, 25, -119, 33, -160, +-14, -22, -44, 159, 0, 174, 60, 6, +66, -175, 12, -175, -48, 6, -58, 185, +-8, 154, 36, -45, 49, -196, 41, -137, +6, 74, -64, 207, -100, 108, -61, -105, +37, -190, 104, -55, 69, 138, -23, 157, +-78, -28, -62, -211, -22, -172, 2, 66, +1, 255, 5, 202, 17, -43, 39, -238, +33, -187, -29, 27, -121, 165, -123, 87, +-4, -83, 151, -137, 189, 14, 56, 215, +-129, 222, -182, -24, -60, -317, 88, -365, +107, -79, 5, 308, -61, 445, 18, 187, +141, -217, 136, -385, -8, -176, -175, 185, +-204, 307, -55, 43, 145, -309, 229, -319, +165, 73, 9, 499, -103, 470, -83, -52, +-15, -589, -5, -601, -39, -65, -53, 507, +15, 558, 142, 80, 203, -402, 100, -371, +-73, 101, -180, 454, -186, 258, -68, -316, +85, -658, 153, -354, 96, 354, -22, 775, +-94, 500, -31, -195, 93, -650, 79, -468, +-66, 97, -184, 420, -156, 207, 10, -233, +175, -346, 172, 8, 40, 466, -78, 485, +-109, -16, -67, -556, 4, -594, 15, -125, +-22, 403, -22, 526, 7, 164, 41, -261, +69, -338, 55, -69, -7, 230, -37, 279, +-45, 19, -78, -291, -72, -342, 7, -100, +106, 232, 160, 404, 95, 268, -68, -91, +-141, -369, -53, -334, 63, -36, 85, 285, +32, 327, -52, 44, -36, -278, 62, -292, +104, -8, 42, 307, -55, 324, -115, -13, +-66, -351, 87, -336, 178, 17, 98, 359, +-63, 356, -165, -37, -113, -407, 60, -375, +144, 30, 77, 416, -23, 429, -62, 34, +-45, -385, 21, -419, 49, -79, -6, 272, +-55, 322, -63, 44, -43, -236, 46, -200, +134, 91, 94, 282, -49, 176, -164, -155, +-176, -390, -31, -241, 163, 154, 170, 406, +24, 292, -118, -63, -145, -369, -33, -310, +118, 26, 107, 295, -47, 277, -133, 26, +-67, -251, 84, -293, 182, -50, 68, 214, +-134, 275, -188, 114, -69, -166, 93, -314, +181, -146, 131, 164, -12, 315, -92, 201, +-110, -125, -110, -373, -13, -254, 126, 114, +165, 363, 96, 299, -36, -28, -149, -343, +-108, -315, 72, -10, 152, 238, 82, 246, +-69, 65, -174, -151, -80, -184, 169, -38, +252, 82, 67, 87, -187, 47, -274, -24, +-101, -65, 207, -36, 294, -11, 84, 9, +-156, 76, -234, 88, -122, -1, 74, -99, +182, -147, 115, -80, 5, 104, -85, 219, +-127, 107, -55, -94, 68, -210, 71, -131, +-6, 89, -89, 220, -97, 84, 26, -160, +181, -221, 153, -48, -47, 219, -222, 318, +-244, 89, -47, -268, 211, -379, 255, -164, +48, 192, -160, 419, -186, 277, -34, -113, +134, -381, 134, -319, -33, -4, -109, 321, +-47, 356, 39, 52, 48, -279, 9, -325, +-18, -67, 16, 252, 66, 328, 21, 67, +-65, -253, -53, -303, 35, -70, 89, 211, +52, 284, -77, 88, -148, -183, -38, -261, +192, -103, 256, 127, 117, 253, -170, 164, +-338, -65, -199, -264, 141, -248, 313, -13, +173, 267, -102, 334, -237, 100, -80, -246, +192, -366, 241, -126, -9, 223, -283, 346, +-358, 111, -104, -231, 276, -321, 450, -51, +229, 268, -145, 305, -392, 34, -326, -269, +14, -312, 281, -79, 225, 207, -40, 272, +-214, 116, -136, -90, 121, -191, 269, -146, +113, 2, -188, 116, -317, 145, -201, 85, +93, -66, 286, -183, 234, -155, 0, 32, +-184, 230, -182, 254, -22, 23, 135, -266, +132, -332, -21, -71, -157, 289, -146, 399, +36, 103, 219, -354, 214, -498, 51, -144, +-135, 404, -173, 632, -82, 287, 47, -392, +55, -764, 14, -468, 17, 230, 83, 726, +140, 603, 94, -30, -73, -572, -182, -542, +-154, -49, -36, 392, 80, 394, 137, -12, +110, -391, 35, -321, -3, 127, -66, 475, +-73, 380, -25, -74, -7, -496, -44, -488, +-45, -55, -10, 374, 65, 425, 160, 153, +99, -186, -80, -299, -151, -123, -95, 113, +-12, 167, 50, 70, -2, -59, -86, -153, +-17, -133, 152, 6, 179, 159, 63, 216, +-133, 163, -310, -64, -215, -321, 90, -310, +277, -11, 234, 315, 28, 384, -196, 91, +-227, -360, 12, -471, 165, -96, 120, 394, +-1, 536, -120, 193, -108, -369, 67, -633, +155, -289, 47, 281, -72, 556, -120, 335, +-74, -143, 111, -483, 234, -274, 102, 218, +-62, 443, -205, 189, -240, -322, -84, -621, +205, -314, 321, 416, 243, 819, 19, 531, +-290, -241, -369, -851, -124, -779, 166, -8, +275, 704, 194, 757, -58, 202, -212, -427, +-111, -651, 83, -254, 125, 324, 81, 499, +-109, 209, -267, -237, -154, -497, 151, -304, +351, 222, 266, 552, -75, 414, -435, -69, +-380, -540, 38, -617, 355, -116, 312, 512, +15, 696, -269, 291, -248, -336, -6, -727, +167, -464, 130, 226, 49, 675, -72, 503, +-129, -74, -80, -602, 5, -587, 94, 7, +180, 588, 119, 602, -96, 71, -248, -549, +-161, -716, 81, -176, 297, 581, 247, 814, +-100, 269, -336, -544, -231, -934, 140, -464, +390, 514, 306, 1052, -112, 629, -442, -364, +-349, -1073, 58, -855, 401, 151, 420, 1003, +81, 936, -316, 81, -414, -797, -155, -911, +214, -212, 371, 631, 220, 791, -154, 216, +-347, -549, -231, -754, 76, -212, 312, 541, +295, 779, 21, 279, -281, -464, -343, -832, +-145, -409, 181, 349, 386, 764, 228, 484, +-159, -170, -414, -685, -300, -551, 106, 95, +469, 589, 408, 575, -66, 86, -516, -491, +-545, -680, -113, -263, 486, 304, 684, 588, +277, 442, -361, -20, -675, -447, -381, -447, +248, -107, 663, 185, 390, 306, -238, 195, +-654, -99, -431, -258, 238, -150, 753, 44, +574, 240, -115, 337, -712, 110, -709, -295, +-118, -519, 543, -403, 702, 75, 285, 623, +-245, 739, -530, 220, -308, -457, 134, -780, +405, -486, 232, 193, -141, 655, -431, 490, +-308, -76, 193, -467, 575, -399, 454, 90, +-51, 478, -553, 388, -648, -112, -193, -536, +387, -548, 618, -51, 369, 532, -101, 695, +-510, 319, -450, -323, -31, -740, 366, -586, +411, 59, 96, 635, -323, 719, -435, 216, +-130, -481, 268, -802, 409, -404, 227, 332, +-165, 794, -401, 568, -263, -182, 78, -815, +332, -698, 265, 53, -56, 741, -345, 795, +-252, 124, 88, -648, 363, -819, 322, -261, +-23, 475, -387, 781, -385, 388, -73, -311, +287, -674, 405, -453, 197, 121, -179, 541, +-357, 490, -172, 35, 131, -377, 320, -450, +190, -198, -111, 183, -314, 383, -212, 279, +57, -26, 272, -233, 292, -322, 116, -154, +-135, 147, -280, 323, -236, 237, -38, -20, +177, -292, 238, -357, 120, -51, -99, 270, +-174, 356, -60, 132, 138, -175, 189, -353, +6, -180, -264, 143, -366, 286, -78, 168, +334, -60, 491, -247, 219, -239, -256, -5, +-524, 231, -316, 294, 167, 185, 421, -110, +259, -380, -126, -391, -351, -103, -214, 276, +174, 500, 363, 375, 219, -64, -153, -416, +-402, -478, -324, -178, 77, 166, 415, 383, +383, 239, 55, 2, -343, -145, -418, -119, +-110, -38, 292, 29, 373, -4, 142, -88, +-225, -22, -375, 44, -152, 95, 230, 89, +347, 78, 165, -6, -160, -43, -368, -115, +-215, -184, 164, -115, 393, 114, 248, 271, +-72, 216, -391, 5, -370, -246, 17, -306, +382, -52, 382, 224, 112, 259, -239, 97, +-403, -155, -194, -307, 166, -170, 321, 115, +226, 280, -40, 253, -321, 28, -284, -248, +51, -333, 345, -141, 321, 135, 21, 294, +-378, 218, -456, -28, -84, -214, 360, -181, +479, -34, 220, 113, -268, 139, -528, 32, +-298, -82, 195, -70, 471, -44, 354, 25, +-97, 108, -506, 73, -382, -39, 109, -82, +473, -94, 399, -70, -43, 99, -524, 158, +-495, 65, 31, -27, 517, -49, 548, -94, +141, -40, -473, 27, -680, -53, -230, -64, +385, 90, 625, 195, 357, 153, -183, 26, +-571, -237, -369, -383, 101, -131, 389, 231, +328, 398, 23, 270, -326, -92, -330, -432, +-2, -346, 287, 83, 325, 402, 109, 375, +-237, -41, -395, -449, -167, -496, 146, -18, +336, 499, 288, 634, 13, 211, -315, -454, +-362, -752, -120, -436, 215, 291, 446, 777, +263, 677, -229, -74, -538, -706, -355, -770, +154, -219, 590, 517, 510, 855, -74, 453, +-566, -336, -526, -773, -71, -666, 418, 8, +557, 710, 149, 846, -351, 191, -478, -579, +-172, -872, 257, -464, 485, 441, 225, 1009, +-288, 627, -492, -353, -270, -987, 179, -837, +498, 72, 430, 1020, -45, 1050, -459, 145, +-490, -853, -145, -1134, 317, -528, 554, 589, +303, 1212, -201, 762, -501, -299, -367, -1068, +83, -961, 445, -59, 397, 944, -48, 1063, +-424, 270, -391, -690, 38, -1019, 445, -483, +451, 484, 7, 982, -490, 534, -553, -357, +-77, -907, 500, -637, 641, 228, 202, 931, +-416, 780, -651, -70, -284, -839, 315, -919, +567, -232, 288, 640, -235, 950, -501, 461, +-263, -323, 236, -772, 497, -585, 282, 61, +-225, 567, -524, 535, -344, 76, 162, -394, +492, -527, 379, -204, -75, 298, -414, 542, +-322, 355, 69, -88, 327, -490, 226, -526, +-97, -177, -344, 278, -235, 493, 129, 377, +386, 12, 292, -320, -23, -371, -362, -154, +-413, 147, -97, 243, 296, 119, 378, -134, +149, -200, -181, -62, -335, 221, -127, 300, +220, 80, 318, -227, 72, -351, -235, -185, +-379, 92, -176, 306, 228, 198, 449, 21, +274, -78, -107, -71, -403, -96, -380, -89, +1, -67, 385, -16, 419, 176, 74, 239, +-348, 52, -502, -225, -165, -270, 381, -136, +619, 178, 322, 408, -288, 211, -696, -210, +-517, -433, 165, -278, 667, 76, 584, 449, +-14, 403, -567, -43, -578, -405, -4, -384, +531, -59, 503, 293, 20, 423, -496, 132, +-583, -234, -132, -348, 458, -180, 592, 97, +272, 293, -241, 246, -539, -33, -405, -221, +72, -237, 382, -36, 311, 176, 36, 230, +-244, 78, -281, -154, -22, -245, 264, -108, +259, 161, 33, 219, -247, 114, -360, -103, +-163, -212, 205, -105, 374, 127, 240, 177, +-49, 3, -272, -107, -252, -106, -35, 27, +134, 144, 132, 111, 48, -134, -32, -204, +-58, -4, -23, 202, 7, 233, 52, 43, +63, -271, -11, -376, -93, -57, -77, 325, +25, 417, 76, 171, 61, -217, -44, -468, +-91, -313, 44, 117, 189, 401, 98, 346, +-118, 68, -276, -276, -221, -434, 88, -202, +388, 200, 319, 439, -57, 335, -338, -65, +-350, -492, -48, -504, 313, -49, 352, 497, +13, 621, -287, 193, -302, -424, -60, -705, +273, -343, 373, 327, 97, 740, -286, 449, +-416, -233, -222, -727, 173, -578, 475, 82, +388, 735, -79, 769, -465, 87, -491, -655, +-121, -874, 371, -398, 563, 420, 286, 970, +-215, 685, -522, -143, -418, -810, 14, -879, +420, -260, 477, 599, 141, 961, -268, 478, +-438, -337, -216, -838, 163, -660, 366, 138, +250, 814, -84, 724, -354, -63, -312, -759, +44, -834, 381, -125, 447, 782, 113, 1009, +-362, 337, -576, -649, -297, -1085, 249, -682, +570, 344, 441, 1043, -39, 895, -462, 41, +-490, -779, -106, -957, 293, -363, 438, 523, +211, 891, -165, 556, -430, -291, -319, -873, +78, -721, 383, 115, 417, 850, 127, 886, +-307, 168, -534, -782, -330, -1026, 98, -406, +478, 559, 521, 993, 132, 623, -409, -325, +-576, -930, -249, -651, 280, 163, 593, 791, +361, 696, -274, -17, -678, -752, -455, -753, +203, -134, 752, 593, 685, 823, -35, 383, +-763, -376, -840, -788, -210, -563, 572, 74, +873, 676, 440, 713, -350, 150, -760, -509, +-531, -738, 105, -372, 634, 353, 612, 791, +45, 520, -518, -181, -635, -714, -223, -699, +394, -73, 704, 625, 396, 744, -247, 254, +-657, -371, -544, -669, 44, -429, 611, 193, +634, 554, 81, 392, -534, -60, -665, -408, +-175, -429, 511, -19, 717, 435, 216, 433, +-524, 92, -782, -347, -309, -533, 458, -300, +809, 251, 440, 562, -321, 454, -773, 29, +-538, -435, 126, -586, 612, -310, 546, 214, +23, 530, -469, 492, -473, 72, -54, -402, +332, -554, 361, -242, 67, 259, -271, 526, +-326, 349, -64, -169, 235, -499, 273, -431, +101, 0, -137, 472, -233, 550, -101, 197, +105, -297, 157, -565, 34, -480, -88, 36, +-110, 496, -9, 549, 134, 192, 154, -287, +11, -520, -118, -313, -135, 247, -55, 497, +43, 284, 69, -223, 35, -565, -14, -475, +34, 165, 101, 735, 78, 642, -53, 68, +-191, -595, -209, -803, -67, -385, 190, 394, +275, 738, 116, 459, -124, -128, -201, -563, +-127, -508, 72, 40, 174, 598, 52, 538, +-147, 26, -185, -569, -67, -782, 110, -319, +247, 520, 183, 950, -39, 591, -245, -165, +-234, -830, -109, -818, 93, -147, 245, 586, +191, 688, -3, 240, -141, -300, -180, -534, +-113, -223, 52, 290, 209, 482, 144, 187, +-36, -242, -159, -536, -211, -392, -47, 129, +250, 555, 286, 561, 16, 152, -262, -395, +-327, -664, -97, -366, 299, 202, 446, 558, +125, 471, -270, 5, -412, -438, -267, -469, +101, -92, 428, 250, 367, 388, 31, 237, +-259, -141, -377, -348, -192, -228, 181, 16, +340, 231, 163, 326, -129, 63, -274, -245, +-209, -310, 82, -120, 315, 140, 234, 355, +1, 274, -230, -79, -343, -346, -165, -317, +141, -92, 283, 194, 228, 389, 17, 220, +-188, -106, -241, -290, -65, -238, 97, -54, +163, 233, 124, 312, -71, 115, -240, -179, +-196, -349, 11, -281, 250, 21, 388, 404, +182, 493, -206, 167, -462, -310, -408, -529, +-49, -390, 382, 73, 529, 484, 258, 441, +-185, 58, -465, -286, -367, -344, 65, -142, +435, 202, 346, 318, -75, 102, -437, -235, +-424, -335, 62, -144, 528, 198, 563, 486, +95, 331, -476, -158, -694, -522, -369, -460, +295, -73, 689, 437, 527, 607, -29, 225, +-534, -276, -622, -519, -135, -369, 400, 38, +570, 440, 264, 420, -271, 68, -621, -286, +-401, -417, 226, -199, 627, 221, 533, 464, +-31, 245, -610, -159, -704, -472, -144, -400, +453, 51, 656, 479, 354, 508, -241, 133, +-599, -315, -395, -544, 134, -325, 457, 103, +341, 406, -92, 374, -439, 60, -332, -248, +158, -300, 454, -51, 324, 176, -69, 224, +-412, -28, -406, -252, -66, -231, 285, 20, +364, 258, 217, 308, -28, 105, -267, -183, +-290, -266, -101, -215, 113, -38, 237, 162, +186, 260, -13, 135, -159, -55, -137, -187, +-60, -174, 20, 6, 89, 197, 127, 163, +84, -29, -17, -120, -156, -123, -180, -81, +-37, 32, 132, 98, 169, 76, 71, 115, +-52, 76, -100, -84, -63, -193, -12, -124, +13, -22, 36, 93, 52, 158, 29, 105, +-64, -28, -127, -74, -75, -69, 94, -121, +247, 1, 164, 168, -103, 166, -331, -6, +-265, -168, 2, -284, 258, -102, 271, 269, +101, 383, -102, 164, -167, -198, -162, -381, +-55, -283, 94, 82, 153, 353, 72, 307, +-139, 6, -218, -259, -30, -314, 277, -134, +349, 237, 34, 411, -379, 243, -462, -198, +-108, -516, 347, -436, 460, 88, 166, 614, +-205, 618, -344, 30, -185, -612, 87, -680, +221, -150, 183, 548, -17, 710, -186, 183, +-222, -491, -33, -653, 206, -201, 309, 412, +91, 610, -196, 229, -321, -306, -210, -515, +80, -265, 290, 143, 312, 344, 91, 268, +-170, 42, -342, -147, -268, -240, 40, -186, +336, -9, 303, 170, 26, 283, -259, 150, +-290, -185, -48, -363, 203, -150, 255, 170, +18, 389, -210, 251, -218, -190, -69, -431, +163, -250, 268, 122, 141, 323, -128, 273, +-268, 0, -234, -187, 11, -190, 282, -40, +318, -14, 27, -24, -293, 68, -334, 137, +-92, 138, 261, 36, 376, -166, 159, -254, +-183, -2, -350, 237, -276, 208, 15, -105, +272, -373, 362, -236, 168, 239, -197, 621, +-373, 365, -227, -359, 123, -786, 353, -454, +243, 280, -114, 856, -386, 581, -239, -329, +152, -840, 386, -524, 291, 286, -72, 853, +-407, 591, -353, -314, 13, -884, 301, -608, +286, 240, 86, 832, -133, 643, -217, -142, +-86, -800, 69, -600, 74, 182, 45, 721, +12, 532, -69, -184, -83, -783, 18, -531, +74, 264, 79, 744, 38, 519, -37, -211, +-109, -683, -106, -445, -26, 196, 15, 529, +109, 292, 174, -225, 102, -382, -133, -111, +-285, 219, -205, 291, 91, 1, 332, -245, +310, -135, -69, 126, -414, 179, -330, -25, +39, -262, 382, -215, 408, 170, 35, 484, +-439, 344, -477, -250, -38, -677, 418, -521, +477, 196, 73, 867, -400, 739, -416, -187, +2, -1013, 332, -883, 255, 145, -49, 1171, +-244, 1022, -107, -216, 116, -1318, 167, -1085, +26, 316, -113, 1480, -141, 1116, -6, -471, +113, -1640, 80, -1142, -22, 607, -53, 1776, +2, 1145, 69, -672, 90, -1799, -85, -1124, +-233, 646, -127, 1709, 118, 1037, 270, -606, +241, -1522, -3, -889, -327, 547, -357, 1349, +-71, 760, 229, -504, 352, -1180, 227, -695, +-171, 440, -402, 1062, -210, 600, 131, -365, +309, -896, 207, -566, -82, 331, -315, 823, +-184, 419, 88, -327, 227, -683, 178, -402, +25, 274, -159, 676, -213, 336, -121, -253, +19, -492, 167, -310, 227, 87, 130, 455, +-108, 314, -269, -124, -230, -325, 13, -257, +261, -13, 292, 354, 46, 359, -251, -76, +-283, -387, -6, -377, 306, -31, 276, 450, +-74, 520, -357, 5, -262, -498, 93, -495, +365, -24, 292, 491, -49, 472, -294, -71, +-234, -529, -55, -376, 122, 201, 209, 602, +85, 371, -74, -293, -91, -666, -27, -420, +9, 226, 23, 684, -34, 505, -90, -150, +22, -562, 160, -453, 71, -5, -45, 442, +-125, 407, -130, -71, 5, -397, 167, -257, +104, 110, -69, 449, -161, 334, -124, -211, +70, -553, 280, -348, 196, 146, -160, 529, +-381, 446, -271, -113, 102, -509, 449, -363, +382, 104, -84, 448, -413, 360, -341, -158, +30, -534, 356, -365, 243, 178, -174, 608, +-336, 519, -54, -113, 320, -692, 377, -643, +17, -14, -438, 667, -403, 754, 56, 99, +338, -660, 257, -752, -21, -117, -213, 658, +-70, 782, 158, 66, 76, -731, -161, -746, +-201, -3, -23, 751, 175, 786, 185, -17, +-35, -782, -177, -705, -14, 18, 170, 658, +100, 672, -160, 37, -298, -584, -129, -535, +240, -52, 357, 384, 113, 466, -238, 158, +-323, -285, -61, -385, 220, -164, 207, 79, +-19, 256, -194, 253, -158, 29, 49, -180, +195, -165, 143, -120, -4, 5, -124, 183, +-228, 163, -182, -22, 106, -145, 353, -176, +303, -51, -43, 238, -464, 300, -469, 32, +78, -298, 605, -381, 483, -136, -115, 291, +-675, 468, -579, 175, 182, -268, 844, -414, +589, -177, -248, 239, -859, 428, -650, 146, +256, -300, 906, -460, 531, -225, -321, 268, +-673, 581, -358, 367, 311, -162, 573, -555, +118, -510, -428, -28, -359, 484, 12, 487, +314, 67, 333, -321, 27, -347, -273, -23, +-157, 299, -28, 241, -45, -135, -10, -313, +81, -156, 122, 120, 209, 286, 78, 235, +-250, -35, -351, -205, -92, -208, 188, -161, +320, 28, 179, 285, -201, 299, -357, 16, +-111, -300, 250, -367, 332, -11, 109, 418, +-301, 386, -460, -134, -149, -532, 362, -328, +534, 281, 230, 643, -340, 309, -637, -427, +-320, -713, 351, -244, 675, 442, 346, 689, +-359, 254, -730, -429, -337, -604, 422, -179, +740, 320, 348, 480, -399, 204, -786, -261, +-435, -435, 356, -214, 783, 151, 502, 374, +-179, 347, -739, 18, -625, -358, 103, -444, +701, -186, 586, 202, -52, 493, -639, 425, +-606, -66, 57, -489, 695, -521, 597, -153, +-100, 379, -663, 674, -617, 343, 19, -316, +671, -717, 655, -514, -25, 183, -611, 780, +-602, 677, -89, -110, 511, -835, 654, -793, +170, 24, -435, 871, -587, 946, -275, 108, +260, -919, 590, -1152, 341, -308, -240, 870, +-518, 1298, -309, 573, 214, -699, 545, -1385, +300, -747, -308, 605, -597, 1326, -307, 757, +283, -528, 618, -1341, 327, -783, -252, 627, +-462, 1369, -216, 786, 144, -500, 292, -1318, +42, -921, -229, 306, -157, 1072, 132, 824, +231, 16, 178, -662, -47, -689, -247, -139, +-200, 369, 14, 445, 49, 216, 39, -203, +58, -471, 74, -286, 114, 144, 115, 482, +-82, 518, -287, 86, -198, -527, 50, -683, +221, -298, 187, 286, -8, 694, -197, 529, +-110, -114, 96, -597, 211, -508, 68, -17, +-137, 522, -221, 592, -116, 4, 10, -651, +145, -695, 140, -42, 94, 766, 91, 970, +-12, 188, -218, -855, -269, -1138, -66, -334, +140, 799, 256, 1154, 153, 390, -124, -706, +-221, -1065, 14, -340, 171, 681, 154, 925, +-34, 236, -339, -603, -342, -859, 49, -266, +459, 573, 500, 809, 117, 314, -483, -368, +-671, -752, -196, -506, 470, 224, 627, 683, +201, 575, -467, 9, -654, -568, -68, -716, +578, -131, 558, 528, 21, 697, -552, 266, +-615, -410, -41, -782, 515, -376, 465, 386, +78, 710, -223, 452, -374, -146, -215, -646, +131, -555, 254, 35, 177, 467, 121, 492, +-193, 186, -432, -305, -194, -562, 251, -274, +491, 245, 421, 587, -152, 466, -754, -100, +-570, -747, 201, -755, 716, -32, 624, 789, +-55, 947, -776, 328, -649, -671, 132, -1158, +723, -517, 654, 588, -44, 1144, -801, 664, +-788, -439, 19, -1286, 777, -848, 852, 465, +167, 1408, -723, 1074, -892, -256, -206, -1512, +529, -1438, 743, 24, 320, 1467, -384, 1578, +-651, 303, -308, -1226, 193, -1658, 493, -510, +419, 1060, -1, 1572, -418, 637, -469, -873, +-157, -1605, 214, -801, 470, 753, 374, 1623, +-91, 1035, -472, -500, -442, -1650, -74, -1258, +403, 273, 590, 1540, 214, 1398, -429, -19, +-733, -1411, -344, -1437, 336, -106, 839, 1220, +602, 1367, -252, 266, -914, -1001, -696, -1305, +114, -382, 836, 755, 787, 1099, -12, 512, +-791, -396, -780, -928, -16, -633, 710, 153, +777, 683, 135, 648, -617, 153, -819, -504, +-287, -736, 481, -289, 833, 387, 487, 679, +-255, 415, -798, -244, -712, -710, 36, -473, +754, 206, 789, 627, 158, 475, -584, -49, +-857, -548, -328, -531, 493, -32, 818, 418, +400, 434, -304, 138, -789, -225, -569, -369, +201, -140, 802, 133, 652, 193, -45, 87, +-748, 14, -841, -69, -161, -102, 687, -131, +959, -105, 377, 81, -478, 360, -1019, 382, +-645, -62, 292, -574, 1051, -660, 762, -112, +-171, 660, -996, 926, -867, 280, 107, -660, +1037, -998, 922, -404, -53, 579, -963, 1025, +-1033, 436, -111, -614, 919, -1056, 1109, -451, +271, 614, -727, 1133, -1143, 600, -470, -533, +638, -1182, 1085, -741, 475, 347, -463, 1050, +-1002, 851, -556, -101, 433, -902, 912, -833, +506, 7, -227, 715, -762, 785, -657, 126, +47, -678, 617, -844, 640, -182, 241, 613, +-310, 896, -725, 438, -483, -507, 129, -1038, +615, -602, 634, 332, 134, 955, -602, 782, +-754, -133, -190, -930, 550, -768, 795, 71, +263, 756, -561, 740, -871, 13, -307, -739, +513, -686, 871, 12, 421, 613, -397, 699, +-847, 139, -557, -588, 186, -719, 779, -195, +718, 400, 6, 700, -723, 400, -860, -316, +-207, -695, 668, -419, 1011, 139, 407, 602, +-591, 596, -1085, -6, -606, -622, 419, -628, +1084, -142, 751, 474, -222, 776, -994, 362, +-850, -469, 88, -837, 916, -451, 903, 296, +84, 879, -873, 679, -1049, -243, -196, -973, +816, -748, 1117, 92, 417, 897, -637, 957, +-1177, 122, -594, -877, 501, -1028, 1041, -280, +665, 631, -204, 1022, -945, 498, -818, -516, +92, -1034, 816, -503, 883, 431, 227, 1000, +-702, 646, -1128, -396, -519, -1136, 569, -743, +1160, 340, 809, 1110, -266, 911, -1204, -106, +-1059, -1022, 83, -977, 1071, -94, 1163, 749, +248, 894, -961, 300, -1355, -486, -486, -825, +836, -439, 1456, 250, 805, 759, -651, 634, +-1584, 14, -1060, -701, 461, -846, 1547, -305, +1234, 589, -233, 994, -1513, 570, -1345, -398, +76, -1031, 1432, -729, 1496, 238, 124, 985, +-1417, 771, -1612, -154, -282, -948, 1255, -777, +1683, 92, 512, 933, -1119, 874, -1634, 3, +-597, -916, 859, -958, 1483, -175, 762, 788, +-641, 1036, -1388, 330, -801, -675, 431, -1000, +1154, -391, 940, 520, -109, 934, -1041, 435, +-968, -478, -121, -904, 701, -417, 965, 382, +469, 853, -485, 531, -974, -263, -607, -818, +243, -567, 895, 67, 837, 611, -108, 608, +-1006, 116, -898, -416, 22, -491, 936, -189, +1056, 177, 124, 392, -970, 238, -1086, -117, +-246, -349, 743, -216, 1081, 60, 457, 362, +-574, 338, -995, -25, -521, -407, 321, -397, +854, -97, 631, 304, -197, 483, -752, 237, +-598, -209, 29, -437, 568, -336, 665, 16, +170, 423, -438, 492, -630, 129, -372, -381, +141, -621, 630, -379, 591, 301, -7, 785, +-532, 615, -638, -144, -203, -830, 486, -838, +793, -41, 283, 820, -482, 921, -832, 172, +-504, -778, 370, -991, 1069, -235, 737, 793, +-301, 1010, -1070, 302, -996, -760, 15, -1118, +1135, -383, 1189, 781, 109, 1144, -1029, 458, +-1295, -673, -366, -1239, 966, -588, 1432, 687, +500, 1261, -823, 662, -1446, -493, -777, -1263, +625, -866, 1478, 369, 904, 1185, -458, 880, +-1382, -126, -1057, -980, 291, -919, 1385, 19, +1173, 870, -182, 810, -1332, 51, -1327, -733, +-81, -853, 1254, -188, 1481, 640, 377, 844, +-1011, 377, -1505, -321, -659, -770, 750, -590, +1442, 7, 808, 518, -602, 613, -1373, 277, +-835, -312, 507, -587, 1376, -312, 982, 226, +-391, 615, -1416, 406, -1147, -319, 147, -849, +1241, -537, 1318, 316, 253, 1029, -1022, 859, +-1319, -156, -482, -1106, 612, -1024, 1213, -49, +734, 917, -448, 1069, -1149, 235, -781, -771, +281, -996, 1119, -278, 991, 613, -177, 960, +-1223, 392, -1119, -550, 17, -987, 1115, -493, +1308, 421, 232, 990, -1073, 636, -1293, -296, +-362, -970, 827, -734, 1227, 143, 490, 902, +-687, 825, -1087, 22, -504, -795, 457, -925, +944, -227, 600, 663, -272, 992, -844, 431, +-646, -474, 28, -1027, 698, -619, 754, 330, +154, 1000, -566, 745, -713, -171, -312, -1001, +390, -882, 710, 85, 359, 948, -288, 961, +-598, 94, -402, -881, 168, -1043, 585, -188, +415, 712, -79, 944, -452, 357, -430, -511, +-74, -882, 345, -378, 401, 319, 183, 636, +-164, 451, -344, -80, -282, -533, 67, -424, +321, -28, 307, 278, -1, 411, -358, 224, +-383, -178, 16, -374, 426, -251, 414, -21, +-6, 293, -524, 383, -436, 120, 94, -231, +547, -340, 387, -231, -159, 78, -598, 320, +-350, 245, 232, 6, 568, -165, 315, -175, +-210, -99, -488, 54, -294, 95, 167, 105, +372, 50, 198, -42, -134, -178, -252, -138, +-144, 46, 157, 250, 219, 269, 88, 29, +-124, -325, -202, -416, -153, -121, 40, 302, +166, 467, 200, 230, 78, -213, -88, -454, +-188, -247, -139, 165, 30, 366, 109, 223, +105, -96, 7, -337, -50, -226, -69, 82, +16, 260, 14, 203, 53, 54, 30, -144, +-23, -203, -61, -116, -57, -33, -33, 49, +51, 189, 142, 221, 72, 56, -36, -159, +-160, -297, -144, -212, 3, 118, 236, 361, +185, 245, -35, -90, -224, -315, -234, -272, +2, 18, 294, 270, 281, 243, -37, 7, +-255, -165, -276, -170, -64, -64, 217, 74, +308, 126, 87, 74, -113, -10, -227, -57, +-235, -121, -41, -92, 225, 63, 286, 198, +145, 167, -85, -13, -319, -281, -295, -342, +25, -31, 317, 370, 319, 423, 114, 127, +-257, -339, -446, -531, -203, -215, 242, 322, +439, 500, 310, 276, -143, -151, -466, -442, +-342, -329, 58, 50, 370, 284, 333, 258, +-8, 122, -311, -110, -257, -220, 12, -154, +287, 0, 243, 126, -49, 212, -314, 59, +-227, -193, 14, -268, 248, -62, 302, 252, +84, 392, -182, 140, -259, -311, -200, -483, +-31, -199, 255, 275, 302, 470, 111, 230, +-150, -214, -329, -409, -263, -203, 115, 203, +377, 368, 296, 177, -30, -188, -386, -373, +-420, -242, -7, 123, 443, 382, 454, 313, +72, 4, -456, -279, -592, -337, -119, -129, +516, 186, 625, 283, 181, 148, -493, -87, +-747, -230, -229, -148, 558, 117, 752, 242, +227, 123, -546, -108, -876, -289, -265, -210, +670, 96, 979, 336, 319, 256, -645, -3, +-1118, -294, -519, -353, 601, -95, 1190, 267, +660, 347, -406, 173, -1123, -145, -837, -379, +249, -267, 1045, 134, 862, 360, -102, 254, +-950, -30, -931, -340, 40, -325, 910, 48, +949, 348, 79, 225, -866, -23, -998, -275, +-168, -252, 762, 53, 1018, 319, 336, 140, +-665, -113, -1042, -221, -442, -149, 537, 89, +1008, 275, 593, 121, -379, -144, -977, -190, +-671, -116, 190, 74, 787, 238, 734, 177, +24, -118, -660, -240, -727, -171, -155, 62, +466, 271, 718, 249, 309, -87, -368, -297, +-700, -191, -423, 87, 179, 274, 622, 170, +601, -155, 43, -309, -537, -79, -680, 231, +-271, 325, 341, 76, 758, -252, 454, -365, +-265, -80, -736, 236, -551, 305, 134, 75, +741, -158, 657, -235, -68, -44, -699, 183, +-695, 181, -90, -28, 585, -210, 764, -216, +226, -14, -461, 282, -689, 310, -365, 45, +241, -258, 666, -344, 466, -156, -102, 235, +-528, 394, -524, 158, -104, -229, 422, -371, +570, -203, 221, 198, -299, 457, -551, 255, +-319, -222, 211, -467, 573, -309, 367, 120, +-178, 508, -558, 384, -401, -133, 88, -493, +526, -368, 482, 51, 15, 485, -441, 458, +-500, -17, -148, -468, 317, -467, 499, -113, +219, 340, -252, 530, -480, 254, -246, -233, +192, -482, 475, -325, 309, 95, -162, 478, +-494, 419, -359, -80, 74, -521, 466, -478, +438, 5, -16, 564, -438, 633, -425, 78, +-34, -588, 378, -678, 439, -176, 73, 485, +-354, 687, -428, 240, -151, -443, 233, -637, +474, -212, 261, 386, -175, 625, -411, 289, +-310, -359, 33, -685, 399, -360, 356, 255, +-47, 634, -358, 481, -344, -99, -40, -585, +359, -480, 486, 31, 115, 433, -344, 418, +-511, 38, -298, -396, 162, -393, 561, -3, +442, 367, -41, 376, -421, 96, -492, -318, +-163, -455, 357, -178, 558, 238, 240, 393, +-291, 252, -604, -86, -380, -360, 253, -263, +708, 69, 500, 282, -218, 216, -760, -12, +-599, -274, 133, -247, 749, 41, 671, 279, +-49, 232, -720, 24, -714, -234, -64, -276, +650, -46, 789, 227, 216, 229, -568, 35, +-861, -194, -363, -266, 468, -47, 886, 275, +492, 321, -365, 52, -880, -249, -581, -403, +250, -174, 857, 247, 675, 446, -155, 200, +-827, -161, -770, -405, -8, -248, 796, 189, +895, 445, 130, 212, -724, -249, -919, -520, +-318, -335, 588, 260, 968, 681, 463, 486, +-431, -165, -863, -648, -622, -628, 160, -53, +785, 552, 690, 622, 27, 127, -535, -367, +-673, -519, -230, -200, 383, 312, 593, 515, +296, 202, -210, -268, -537, -518, -417, -357, +128, 139, 554, 544, 497, 487, -32, 43, +-545, -371, -627, -505, -70, -237, 560, 194, +668, 408, 172, 233, -478, -54, -757, -258, +-286, -247, 461, -6, 782, 240, 424, 270, +-369, 101, -865, -150, -559, -379, 289, -329, +849, 29, 662, 395, -172, 483, -821, 223, +-693, -275, 117, -604, 772, -378, 714, 167, +-54, 553, -779, 480, -765, -42, -45, -601, +718, -580, 836, 27, 229, 623, -609, 695, +-829, 142, -360, -631, 384, -854, 751, -269, +468, 519, -264, 826, -649, 426, -445, -355, +141, -796, 601, -437, 510, 288, -92, 687, +-613, 465, -569, -185, -48, -714, 560, -535, +693, 154, 223, 680, -467, 590, -715, -26, +-394, -662, 275, -669, 711, 12, 542, 643, +-119, 656, -625, 35, -607, -645, -55, -755, +515, -75, 595, 670, 189, 800, -338, 202, +-520, -557, -297, -838, 143, -356, 436, 408, +415, 753, 14, 417, -400, -236, -521, -635, +-153, -435, 407, 165, 637, 568, 261, 394, +-389, -145, -717, -503, -389, -392, 338, 102, +739, 465, 518, 354, -194, -94, -729, -368, +-627, -285, 50, 39, 669, 267, 715, 211, +109, -18, -576, -129, -743, -91, -243, -68, +435, -44, 705, -17, 386, 79, -254, 204, +-655, 208, -497, -71, 89, -334, 593, -312, +606, 1, 60, 357, -575, 426, -696, 36, +-168, -420, 535, -457, 786, -56, 296, 430, +-488, 561, -822, 125, -413, -480, 382, -644, +842, -225, 535, 403, -287, 708, -819, 379, +-609, -322, 145, -711, 783, -459, 720, 195, +-28, 676, -710, 538, -741, -129, -141, -680, +594, -590, 784, 54, 239, 679, -487, 681, +-719, 48, -340, -665, 373, -767, 705, -164, +356, 604, -295, 806, -619, 290, -396, -482, +172, -819, 553, -391, 390, 372, -61, 770, +-398, 485, -403, -201, -102, -736, 302, -593, +390, 87, 199, 652, -131, 641, -406, 98, +-347, -565, 79, -735, 412, -200, 372, 481, +38, 711, -401, 351, -471, -336, -55, -762, +419, -450, 487, 240, 134, 670, -392, 542, +-559, -64, -188, -685, 368, -638, 540, 3, +268, 610, -216, 704, -495, 200, -338, -563, +54, -821, 344, -310, 366, 423, 111, 786, +-232, 499, -332, -230, -178, -762, 128, -551, +322, 85, 221, 601, -124, 597, -318, 83, +-257, -543, 60, -637, 367, -164, 351, 432, +-15, 677, -381, 349, -403, -331, -78, -732, +345, -471, 440, 167, 139, 654, -253, 585, +-383, 16, -237, -580, 110, -617, 336, -122, +292, 461, 42, 634, -252, 283, -396, -371, +-157, -709, 248, -424, 405, 238, 225, 707, +-185, 610, -451, -48, -248, -708, 210, -712, +415, -101, 244, 584, -153, 760, -419, 278, +-294, -508, 149, -782, 381, -344, 255, 385, +-55, 765, -312, 512, -294, -254, 36, -795, +275, -603, 211, 100, 6, 687, -194, 721, +-214, 87, -11, -646, 210, -746, 186, -164, +11, 517, -169, 740, -211, 282, -78, -480, +164, -749, 249, -308, 119, 378, -66, 706, +-227, 424, -215, -286, -14, -712, 179, -467, +231, 172, 132, 626, -98, 546, -263, -48, +-177, -620, 83, -580, 282, -24, 213, 536, +-89, 615, -355, 147, -274, -489, 91, -631, +386, -195, 350, 377, 15, 596, -367, 298, +-453, -267, -142, -548, 261, -314, 455, 149, +253, 448, -198, 370, -453, -18, -248, -367, +192, -372, 432, -81, 227, 240, -230, 371, +-472, 203, -234, -144, 254, -351, 501, -263, +279, 23, -201, 284, -493, 319, -321, 64, +150, -246, 462, -316, 342, -112, -71, 192, +-412, 319, -397, 144, -28, -216, 375, -354, +474, -152, 165, 212, -288, 403, -524, 238, +-297, -193, 223, -472, 519, -303, 305, 121, +-172, 445, -469, 385, -318, -2, 162, -401, +476, -388, 322, -50, -121, 297, -452, 360, +-421, 93, -3, -281, 445, -350, 496, -72, +120, 250, -333, 347, -521, 146, -261, -209, +262, -369, 501, -189, 261, 109, -175, 305, +-467, 285, -333, 44, 134, -243, 470, -302, +370, -150, -54, 135, -446, 331, -471, 257, +-70, -102, 424, -359, 521, -285, 146, 77, +-344, 414, -522, 373, -231, -72, 281, -500, +493, -443, 219, 26, -212, 521, -403, 537, +-224, 63, 166, -485, 368, -563, 198, -167, +-142, 351, -329, 522, -197, 233, 110, -215, +320, -411, 220, -242, -74, 105, -287, 321, +-232, 236, -15, -33, 205, -251, 266, -258, +116, -60, -117, 198, -258, 292, -230, 171, +-17, -99, 275, -305, 356, -269, 132, 13, +-250, 261, -455, 289, -287, 64, 207, -228, +556, -293, 366, -57, -180, 230, -565, 293, +-404, 97, 186, -240, 593, -378, 375, -179, +-230, 198, -596, 420, -370, 334, 220, -63, +602, -454, 401, -462, -148, -69, -511, 401, +-403, 547, 5, 186, 367, -398, 360, -598, +71, -204, -205, 405, -286, 655, -159, 243, +117, -465, 278, -736, 222, -249, -25, 487, +-296, 776, -332, 311, -80, -487, 274, -819, +411, -335, 198, 444, -172, 781, -385, 392, +-276, -381, 78, -787, 341, -418, 284, 319, +-16, 717, -296, 460, -303, -228, -13, -707, +300, -504, 344, 180, 70, 657, -274, 544, +-356, -68, -122, -632, 190, -636, 322, -39, +150, 553, -141, 671, -260, 221, -120, -415, +107, -685, 234, -341, 144, 282, -106, 611, +-279, 420, -199, -156, 43, -571, 272, -464, +305, 99, 77, 547, -223, 518, -327, -16, +-169, -561, 98, -629, 300, -103, 247, 534, +-24, 720, -266, 263, -266, -443, -39, -762, +259, -396, 344, 329, 83, 729, -284, 459, +-402, -234, -165, -681, 254, -486, 475, 190, +236, 659, -216, 513, -461, -125, -305, -628, +127, -572, 461, 20, 329, 560, -84, 572, +-376, 98, -328, -421, 11, -538, 336, -175, +311, 314, 5, 451, -260, 184, -265, -241, +-51, -419, 194, -200, 269, 231, 81, 417, +-149, 225, -223, -162, -129, -404, 68, -282, +218, 89, 144, 332, -38, 248, -154, -3, +-137, -198, -21, -182, 106, -11, 121, 122, +42, 85, -47, 10, -95, -46, -95, -63, +-28, -58, 104, -20, 155, 40, 71, 139, +-90, 152, -192, -1, -113, -209, 116, -254, +221, -65, 83, 209, -166, 311, -247, 101, +-75, -199, 221, -297, 322, -83, 90, 191, +-221, 259, -334, 50, -166, -203, 150, -237, +324, -25, 192, 193, -72, 192, -229, 5, +-167, -169, 11, -139, 165, 30, 138, 164, +-17, 108, -137, -51, -128, -151, -27, -114, +131, 12, 198, 126, 70, 118, -122, 19, +-216, -52, -152, -69, 73, -31, 263, 32, +182, 38, -66, -36, -250, -69, -214, -41, +37, 41, 275, 141, 230, 144, -29, -21, +-247, -174, -234, -180, -7, -54, 217, 130, +222, 195, 16, 47, -181, -145, -182, -139, +-17, 3, 156, 171, 196, 168, 45, -40, +-149, -257, -212, -202, -113, 41, 77, 245, +227, 232, 206, -8, 12, -229, -194, -194, +-250, 37, -104, 185, 134, 154, 264, -42, +152, -202, -112, -157, -271, 58, -154, 181, +122, 146, 309, -6, 182, -143, -148, -151, +-341, -10, -211, 108, 119, 113, 341, 39, +239, -73, -80, -125, -306, -54, -244, 83, +24, 141, 234, 103, 236, -57, 37, -187, +-173, -157, -221, 53, -85, 208, 95, 184, +195, -24, 141, -224, -26, -217, -161, 18, +-177, 235, -52, 205, 124, -7, 214, -206, +116, -176, -99, 28, -239, 199, -174, 110, +51, -97, 262, -215, 232, -84, -12, 157, +-233, 275, -251, 114, -50, -159, 181, -281, +234, -160, 82, 84, -133, 227, -217, 157, +-81, -40, 123, -137, 209, -86, 89, 47, +-133, 111, -234, 53, -107, -89, 112, -154, +245, -97, 153, 61, -65, 193, -214, 196, +-187, 28, 6, -177, 187, -247, 193, -121, +32, 124, -157, 256, -211, 144, -52, -120, +151, -247, 216, -131, 90, 155, -110, 313, +-227, 158, -155, -208, 50, -407, 195, -229, +179, 198, 33, 488, -124, 336, -176, -142, +-59, -527, 77, -430, 120, 66, 47, 513, +-56, 485, -92, 6, -21, -495, 78, -516, +96, -22, 14, 492, -92, 531, -128, 43, +-53, -518, 81, -582, 141, -55, 93, 544, +-31, 621, -119, 108, -109, -509, -12, -656, +77, -175, 101, 450, 24, 615, -58, 203, +-84, -349, -21, -555, 62, -213, 75, 320, +21, 499, -45, 196, -67, -273, -37, -488, +11, -252, 23, 230, 44, 479, 43, 310, +23, -109, -46, -412, -67, -369, -36, -7, +43, 321, 78, 342, 16, 83, -83, -231, +-77, -320, 35, -115, 128, 208, 101, 323, +-67, 147, -184, -182, -124, -367, 63, -214, +195, 157, 150, 396, -54, 279, -193, -92, +-154, -389, 48, -333, 194, 28, 152, 358, +-34, 343, -194, 18, -159, -302, 23, -322, +149, -46, 136, 256, 21, 292, -113, 60, +-110, -214, -9, -270, 70, -88, 66, 173, +14, 277, -66, 148, -75, -102, 1, -277, +71, -243, 52, -24, 11, 241, -22, 320, +-37, 164, -5, -127, -17, -315, -50, -270, +-21, -5, 62, 238, 96, 271, 68, 89, +-40, -137, -128, -217, -106, -104, 19, 105, +117, 195, 95, 115, -25, -81, -135, -226, +-97, -194, 77, 27, 198, 250, 114, 294, +-96, 100, -251, -204, -159, -371, 79, -218, +242, 121, 178, 354, -34, 271, -196, -56, +-154, -331, 22, -270, 168, 72, 139, 336, +-37, 265, -189, -95, -167, -392, 34, -327, +229, 89, 238, 426, 20, 387, -231, -12, +-291, -393, -82, -424, 182, -74, 284, 325, +116, 388, -144, 117, -241, -227, -98, -327, +114, -122, 196, 186, 88, 265, -107, 99, +-192, -128, -103, -215, 72, -107, 171, 94, +148, 189, -15, 111, -166, -29, -163, -138, +-16, -158, 146, -59, 190, 90, 31, 165, +-181, 132, -201, 4, -23, -149, 199, -188, +231, -43, 27, 112, -220, 154, -237, 63, +-14, -81, 211, -130, 207, -7, 4, 114, +-222, 85, -195, -41, 53, -148, 247, -107, +193, 59, -52, 182, -261, 88, -216, -81, +42, -152, 240, -48, 204, 113, -7, 160, +-177, -10, -185, -214, -26, -180, 121, 60, +146, 279, 53, 247, -72, -38, -153, -331, +-101, -280, 38, 50, 159, 321, 155, 273, +2, -56, -157, -348, -203, -264, -67, 126, +133, 396, 223, 268, 112, -134, -90, -436, +-224, -323, -144, 127, 64, 444, 200, 329, +136, -73, -53, -386, -173, -335, -124, 51, +41, 362, 162, 296, 136, -58, -13, -336, +-141, -300, -178, 34, -46, 335, 141, 295, +215, -16, 109, -280, -82, -271, -214, -37, +-151, 226, 28, 230, 161, 12, 156, -184, +22, -163, -102, -4, -130, 161, -34, 165, +75, -3, 105, -151, 38, -157, -50, -50, +-111, 82, -48, 165, 40, 102, 88, -26, +70, -112, 11, -119, -55, -42, -83, 94, +-65, 130, -15, 30, 73, -90, 130, -117, +84, -39, -81, 112, -184, 154, -142, 22, +61, -122, 247, -134, 204, -32, -62, 94, +-276, 130, -241, 2, 34, -107, 292, -84, +265, 26, -14, 88, -281, 84, -268, -9, +-12, -93, 262, -75, 292, -13, 60, 22, +-230, 39, -304, 51, -141, 17, 154, 2, +308, -8, 213, -27, -57, -26, -282, 4, +-252, -9, -6, -23, 226, 0, 237, 28, +39, 37, -194, 36, -217, 5, -30, -44, +190, -31, 212, -5, 53, -11, -178, -11, +-256, 7, -109, 27, 135, 55, 251, 44, +163, -22, -56, -70, -222, -29, -153, 11, +31, 21, 154, -2, 107, -44, -26, -40, +-128, 48, -72, 107, 58, 52, 134, -23, +63, -89, -54, -82, -136, -25, -92, 34, +41, 11, 114, 12, 80, 49, 0, 74, +-58, 44, -55, -24, -5, -104, 2, -126, +3, -35, 1, 58, 28, 93, 35, 75, +14, 30, -37, -34, -45, -47, -9, -30, +52, -18, 40, 1, -31, 18, -77, -18, +-47, -38, 58, 5, 115, 66, 62, 95, +-58, 71, -128, -39, -83, -144, 42, -121, +95, -23, 67, 69, -11, 101, -56, 77, +-32, 5, 16, -8, 38, -19, 12, -48, +-32, -63, -60, -24, -49, 18, 11, 51, +101, 58, 101, -5, 32, -40, -86, -7, +-150, 38, -73, 26, 77, 5, 120, -54, +55, -79, -49, -17, -94, 68, -26, 84, +71, 47, 86, -31, -8, -104, -80, -78, +-83, 26, -11, 111, 87, 110, 111, 15, +11, -132, -81, -183, -117, -71, -41, 111, +89, 210, 141, 156, 56, -33, -88, -183, +-156, -168, -82, -21, 70, 105, 140, 124, +67, 32, -66, -74, -89, -81, -23, 13, +71, 95, 62, 81, -42, 9, -99, -100, +-28, -134, 61, -63, 88, 50, 13, 111, +-63, 109, -43, 42, 37, -66, 82, -98, +0, -49, -96, 14, -108, 55, -5, 50, +110, -38, 133, -92, 19, -36, -87, 67, +-100, 137, -15, 120, 60, -32, 51, -198, +-13, -189, -53, -30, -23, 145, 39, 216, +54, 102, 15, -123, -7, -208, -28, -78, +-24, 113, -25, 198, -19, 88, 1, -154, +43, -249, 56, -87, 27, 159, -32, 262, +-59, 142, -48, -122, 0, -269, 61, -146, +58, 91, 17, 216, -47, 138, -92, -53, +-61, -188, 41, -113, 113, 55, 106, 150, +-16, 103, -135, -24, -144, -131, -8, -112, +145, 16, 157, 111, 17, 109, -147, 9, +-168, -105, -5, -133, 179, -27, 178, 97, +3, 134, -189, 43, -187, -86, -1, -138, +195, -54, 205, 72, 25, 118, -183, 44, +-221, -61, -72, -105, 150, -45, 254, 56, +127, 98, -102, 51, -256, -23, -184, -68, +53, -72, 243, -33, 208, 11, -20, 63, +-226, 81, -199, 61, 3, -29, 214, -102, +217, -84, -4, 7, -224, 88, -243, 89, +-41, 0, 212, -95, 289, -72, 92, 20, +-183, 88, -295, 72, -138, -1, 125, -81, +276, -67, 165, -2, -90, 32, -246, 26, +-164, 10, 58, -12, 239, -12, 208, 7, +-24, 6, -227, -7, -230, 0, -33, -1, +191, -20, 256, -21, 85, -7, -152, 19, +-247, 44, -110, 41, 117, -14, 250, -54, +141, -58, -108, -22, -265, 32, -169, 71, +101, 54, 288, 1, 208, -49, -81, -86, +-305, -59, -248, 15, 55, 94, 305, 106, +281, 44, -3, -74, -299, -140, -321, -88, +-35, 43, 276, 136, 346, 102, 104, -30, +-247, -140, -360, -103, -126, 42, 220, 158, +344, 109, 146, -54, -197, -181, -343, -145, +-142, 39, 193, 200, 320, 167, 157, -24, +-153, -182, -325, -164, -186, 10, 122, 178, +292, 159, 197, -33, -47, -188, -232, -159, +-211, 17, -9, 181, 185, 175, 193, -11, +70, -155, -105, -133, -209, 0, -138, 104, +65, 91, 206, -25, 183, -87, 0, -15, +-211, 61, -252, 54, -43, -18, 225, -68, +267, -23, 83, 75, -188, 62, -309, -61, +-113, -135, 194, -55, 299, 105, 130, 193, +-166, 77, -310, -136, -159, -201, 158, -49, +303, 152, 155, 190, -120, 21, -294, -186, +-208, -196, 83, 7, 291, 197, 237, 198, +-1, 36, -259, -154, -296, -188, -71, -59, +213, 87, 291, 130, 123, 65, -148, -54, +-280, -108, -143, -51, 136, 64, 255, 152, +129, 95, -102, -80, -254, -230, -153, -191, +97, 32, 241, 269, 166, 273, -41, 34, +-210, -233, -194, -276, -21, -51, 157, 207, +184, 252, 59, 33, -101, -225, -168, -271, +-92, -52, 76, 232, 171, 340, 114, 155, +-41, -177, -166, -373, -160, -289, -9, 35, +160, 346, 179, 364, 55, 80, -116, -262, +-178, -367, -86, -138, 92, 220, 165, 348, +92, 125, -50, -232, -148, -366, -109, -142, +48, 224, 158, 393, 127, 171, -18, -194, +-164, -362, -163, -190, -7, 136, 164, 315, +174, 174, 27, -115, -150, -255, -183, -157, +-40, 90, 141, 240, 180, 165, 53, -56, +-118, -193, -174, -172, -72, -18, 69, 136, +133, 162, 93, 50, 3, -79, -67, -110, +-86, -60, -58, 44, 9, 96, 71, 36, +83, -59, 20, -86, -56, -49, -85, 34, +-25, 106, 68, 77, 96, -9, 26, -78, +-68, -91, -120, -36, -81, 61, 54, 108, +146, 45, 128, -61, -1, -117, -138, -69, +-169, 59, -49, 164, 113, 108, 173, -71, +90, -184, -56, -146, -159, 20, -126, 173, +30, 162, 142, -7, 128, -131, 13, -121, +-131, 10, -161, 125, -30, 106, 116, -35, +155, -138, 60, -102, -84, 16, -171, 124, +-105, 121, 74, 29, 188, -72, 143, -94, +-32, -58, -203, -20, -187, 8, 22, 43, +208, 70, 193, 68, 1, 11, -189, -81, +-212, -98, -19, -16, 188, 90, 206, 97, +25, -5, -169, -134, -221, -127, -62, 27, +181, 197, 237, 198, 68, 3, -156, -216, +-240, -269, -111, -81, 141, 198, 234, 297, +102, 134, -98, -136, -199, -284, -115, -169, +75, 118, 181, 271, 106, 158, -64, -105, +-160, -279, -103, -191, 56, 105, 175, 309, +110, 218, -64, -71, -173, -308, -126, -273, +34, 14, 182, 303, 152, 296, -16, 30, +-167, -249, -159, -301, -16, -72, 135, 217, +164, 286, 18, 83, -128, -163, -132, -258, +-19, -113, 102, 134, 140, 242, 30, 111, +-113, -100, -141, -209, -33, -139, 92, 67, +161, 196, 81, 136, -99, -45, -165, -168, +-84, -141, 51, 18, 156, 163, 129, 143, +-36, -15, -147, -148, -134, -140, -10, -22, +123, 148, 168, 173, 58, 23, -115, -139, +-167, -181, -81, -77, 73, 105, 179, 205, +89, 109, -84, -51, -131, -161, -58, -140, +54, -19, 102, 99, 37, 122, -63, 48, +-54, -30, -1, -69, 23, -41, 2, 9, +7, 52, -10, 29, 22, -27, 52, -78, +-31, -78, -77, 14, -34, 119, 37, 160, +91, 66, 68, -95, -62, -217, -124, -168, +-63, 10, 55, 197, 119, 225, 103, 52, +-17, -137, -127, -202, -109, -75, -7, 108, +84, 169, 126, 41, 52, -113, -80, -172, +-117, -73, -66, 112, 55, 206, 144, 147, +93, -25, -86, -181, -182, -234, -95, -105, +80, 117, 189, 264, 121, 211, -82, -27, +-173, -266, -92, -279, 60, -22, 153, 254, +96, 302, -62, 61, -159, -268, -84, -352, +65, -73, 167, 286, 111, 374, -53, 110, +-194, -305, -125, -429, 61, -119, 175, 337, +132, 479, -60, 163, -191, -336, -109, -555, +86, -255, 186, 292, 99, 578, -94, 332, +-198, -175, -91, -524, 110, -383, 205, 97, +101, 427, -105, 321, -210, -76, -108, -380, +110, -304, 206, 107, 114, 412, -78, 332, +-197, -74, -122, -418, 44, -398, 149, -32, +116, 344, -8, 392, -104, 116, -87, -200, +-5, -279, 55, -120, 52, 109, 12, 167, +-27, 54, -49, -84, -37, -124, 18, -38, +66, 71, 67, 129, 17, 101, -73, 2, +-101, -121, -44, -165, 50, -125, 95, 38, +77, 215, -4, 204, -90, 33, -90, -174, +-13, -256, 87, -108, 89, 170, 26, 273, +-72, 121, -88, -149, -25, -291, 34, -159, +64, 132, 63, 316, 20, 178, -49, -109, +-88, -282, -79, -202, 14, 66, 119, 281, +109, 208, -14, -37, -125, -227, -108, -245, +7, -27, 87, 212, 101, 265, 26, 93, +-47, -141, -88, -263, -91, -159, -14, 81, +129, 236, 158, 176, 16, -47, -151, -199, +-199, -187, -18, 21, 204, 215, 208, 202, +-5, 2, -199, -204, -208, -253, -16, -73, +181, 189, 220, 253, 46, 125, -146, -99, +-203, -226, -89, -166, 114, 33, 207, 164, +96, 144, -93, 26, -167, -120, -101, -153, +79, -40, 138, 124, 49, 155, -55, 62, +-78, -96, -20, -187, 35, -93, 27, 78, +0, 161, 6, 101, 9, -3, -33, -118, +-42, -128, 3, -38, 73, 68, 75, 127, +-9, 91, -95, -55, -101, -178, 10, -102, +84, 82, 87, 221, 28, 129, -48, -105, +-90, -263, -41, -164, 13, 113, 62, 259, +109, 152, 25, -77, -96, -200, -126, -159, +-45, 37, 109, 148, 180, 112, 47, 12, +-147, -94, -202, -130, -39, -44, 166, 99, +217, 156, 45, 96, -206, -87, -247, -211, +-12, -160, 219, 62, 242, 241, 29, 191, +-228, -23, -215, -231, -8, -212, 159, 13, +194, 219, 53, 183, -124, -7, -191, -200, +-108, -194, 90, 16, 238, 186, 164, 193, +-106, 34, -287, -142, -183, -201, 123, -72, +292, 86, 157, 173, -133, 120, -271, -33, +-106, -158, 141, -153, 223, 0, 90, 141, +-109, 181, -187, 41, -95, -148, 72, -217, +156, -82, 139, 125, -19, 222, -168, 119, +-147, -104, -9, -192, 145, -80, 151, 118, +-3, 153, -134, 13, -112, -152, 1, -141, +94, 60, 73, 195, 6, 115, -57, -80, +-60, -160, -4, -71, 17, 100, 21, 104, +37, -24, -11, -109, -27, -51, -11, 90, +-28, 121, 24, 13, 51, -110, 17, -90, +-21, 28, -46, 123, -55, 33, -4, -104, +64, -153, 104, -39, 66, 165, -47, 194, +-158, 36, -133, -150, 58, -201, 214, -54, +135, 158, -76, 146, -228, -5, -137, -127, +118, -128, 231, 54, 93, 182, -137, 107, +-195, -71, -83, -165, 119, -115, 173, 42, +55, 128, -77, 90, -130, -16, -73, -84, +28, -37, 102, -10, 108, 37, 34, 59, +-78, 23, -140, -13, -106, -47, 39, -115, +177, -73, 153, 71, 3, 170, -170, 196, +-229, 13, -30, -227, 191, -301, 246, -106, +70, 213, -203, 379, -272, 185, -68, -214, +200, -444, 280, -263, 93, 247, -189, 539, +-282, 319, -124, -256, 157, -629, 283, -376, +131, 283, -126, 659, -254, 368, -136, -299, +108, -676, 215, -314, 133, 360, -57, 672, +-184, 297, -150, -395, -1, -718, 171, -345, +194, 356, 47, 716, -152, 441, -223, -240, +-79, -685, 151, -493, 230, 157, 57, 626, +-134, 473, -162, -154, -23, -638, 117, -454, +88, 221, -35, 691, -64, 444, 16, -251, +39, -719, 1, -460, -63, 267, -44, 687, +52, 391, 85, -269, 35, -607, -54, -294, +-95, 355, -55, 563, 31, 139, 123, -431, +103, -527, -34, -32, -163, 510, -140, 467, +49, -95, 219, -513, 161, -358, -74, 219, +-235, 510, -180, 203, 79, -343, 254, -497, +195, -88, -47, 438, -251, 497, -228, 14, +16, -497, 243, -497, 247, 26, 22, 512, +-207, 517, -229, -14, -41, -561, 175, -546, +190, -2, 41, 542, -105, 596, -131, 65, +-70, -555, 66, -607, 125, -100, 96, 490, +-10, 617, -136, 144, -152, -460, 1, -607, +177, -181, 167, 389, 12, 606, -151, 270, +-184, -308, -40, -613, 132, -353, 168, 204, +88, 583, -58, 463, -183, -101, -149, -570, +71, -516, 194, 7, 154, 538, -44, 603, +-208, 62, -150, -559, 80, -646, 195, -119, +104, 549, -53, 718, -173, 189, -119, -544, +45, -724, 170, -228, 129, 447, 6, 708, +-141, 308, -173, -396, -34, -672, 161, -316, +187, 269, 46, 652, -134, 431, -202, -226, +-57, -661, 160, -469, 205, 124, 65, 642, +-119, 592, -227, -64, -113, -648, 116, -589, +245, 9, 159, 560, -66, 616, -240, 46, +-187, -572, 59, -583, 246, -66, 193, 472, +-15, 619, -223, 191, -222, -455, 19, -639, +238, -273, 229, 302, 40, 651, -204, 438, +-277, -193, -62, -635, 177, -497, 284, 54, +182, 569, -92, 579, -316, 29, -270, -558, +51, -598, 356, -97, 368, 492, 5, 655, +-401, 190, -431, -447, -2, -643, 446, -268, +457, 312, 38, 619, -441, 359, -470, -207, +-20, -554, 446, -416, 460, 66, 48, 501, +-398, 517, -428, 52, -40, -458, 361, -580, +398, -205, 86, 362, -262, 648, -345, 343, +-138, -268, 172, -631, 333, -453, 218, 137, +-33, 622, -291, 545, -324, -55, -37, -618, +329, -646, 407, -65, 113, 621, -332, 770, +-453, 201, -101, -570, 357, -820, 459, -343, +99, 453, -332, 817, -381, 417, -71, -341, +306, -732, 371, -445, 57, 238, -221, 668, +-269, 464, -74, -148, 154, -632, 229, -530, +94, 34, -30, 567, -108, 615, -140, 132, +-86, -497, 78, -681, 244, -265, 218, 375, +-4, 700, -313, 385, -352, -288, 17, -701, +447, -450, 445, 207, 18, 677, -482, 533, +-510, -92, 11, -641, 561, -600, 525, -24, +-16, 553, -536, 666, -519, 181, 40, -510, +562, -747, 534, -282, -11, 470, -511, 838, +-519, 407, -24, -486, 474, -939, 548, -476, +102, 479, -391, 978, -486, 522, -159, -439, +304, -962, 516, -522, 255, 407, -190, 893, +-448, 519, -303, -307, 112, -849, 420, -608, +392, 166, 19, 778, -335, 752, -387, 107, +-108, -678, 248, -944, 419, -372, 207, 559, +-164, 1066, -352, 633, -243, -424, 71, -1175, +339, -841, 331, 324, 45, 1239, -253, 1030, +-329, -171, -149, -1262, 187, -1228, 402, -15, +271, 1221, -64, 1363, -329, 266, -336, -1083, +-71, -1467, 316, -504, 455, 919, 221, 1504, +-194, 762, -499, -704, -388, -1553, 136, -1029, +572, 445, 527, 1539, 44, 1296, -525, -102, +-642, -1431, -158, -1512, 478, -282, 730, 1205, +375, 1597, -318, 638, -744, -873, -506, -1613, +217, -936, 776, 538, 703, 1509, 5, 1213, +-759, -128, -829, -1409, -122, -1452, 720, -289, +975, 1145, 385, 1651, -629, 782, -1072, -812, +-512, -1751, 501, -1222, 1132, 371, 756, 1705, +-343, 1615, -1142, 100, -831, -1617, 223, -1909, +1074, -508, 975, 1410, 3, 2164, -940, 948, +-965, -1236, -152, -2322, 729, -1300, 1015, 923, +455, 2383, -484, 1665, -964, -586, -596, -2293, +205, -1903, 913, 163, 854, 2020, 42, 2058, +-782, 288, -914, -1667, -307, -2078, 627, -680, +1065, 1187, 543, 2006, -432, 1087, -1040, -745, +-741, -1863, 244, -1365, 1106, 268, 962, 1641, +-54, 1607, -1002, 169, -1049, -1366, -135, -1700, +976, -562, 1184, 987, 314, 1665, -775, 911, +-1138, -590, -503, -1512, 633, -1163, 1169, 122, +613, 1263, -399, 1360, -1008, 309, -706, -970, +208, -1457, 898, -706, 741, 656, 28, 1457, +-626, 1003, -729, -329, -245, -1343, 475, -1182, +770, 9, 419, 1137, -216, 1239, -667, 281, +-560, -819, 91, -1200, 649, -591, 632, 486, +150, 1077, -475, 801, -690, -85, -311, -877, +375, -986, 753, -272, 492, 647, -231, 1029, +-759, 561, -600, -350, 168, -983, 792, -814, +643, 100, -65, 874, -664, 898, -594, 201, +34, -658, 557, -1007, 540, -473, 109, 413, +-332, 925, -407, 743, -162, -24, 178, -781, +364, -973, 281, -370, -10, 525, -260, 1039, +-306, 751, -92, -186, 209, -1062, 359, -1053, +227, -87, -143, 964, -390, 1258, -273, 400, +123, -870, 428, -1409, 367, -690, -63, 686, +-426, 1475, -333, 964, 80, -428, 436, -1423, +383, -1203, -36, 136, -419, 1304, -352, 1301, +88, 161, 462, -1088, 353, -1330, -104, -402, +-450, 872, -312, 1279, 185, 578, 457, -611, +258, -1173, -222, -734, -430, 337, -185, 1047, +266, 783, 415, -61, 159, -785, -258, -792, +-396, -189, -117, 537, 264, 689, 433, 331, +190, -210, -190, -549, -425, -451, -229, -31, +194, 364, 440, 434, 273, 275, -101, -116, +-373, -394, -305, -403, 61, -122, 319, 218, +274, 456, 39, 391, -200, -38, -298, -465, +-134, -559, 146, -167, 278, 409, 222, 732, +30, 346, -269, -384, -361, -793, -88, -515, +283, 268, 451, 817, 288, 643, -210, -97, +-559, -707, -363, -747, 206, -146, 550, 535, +468, 764, -38, 426, -579, -282, -573, -787, +-31, -680, 513, 69, 606, 771, 213, 865, +-460, 183, -719, -731, -316, -1062, 401, -399, +692, 678, 433, 1114, -211, 646, -696, -475, +-504, -1197, 104, -839, 586, 298, 572, 1121, +128, 974, -447, -29, -614, -1069, -273, -1093, +327, -145, 632, 959, 418, 1133, -178, 336, +-655, -802, -541, -1203, 24, -473, 563, 648, +637, 1154, 162, 615, -482, -401, -734, -1102, +-405, -721, 317, 204, 831, 912, 612, 808, +-176, 47, -846, -714, -780, -840, 5, -238, +831, 461, 923, 806, 165, 434, -753, -222, +-982, -737, -341, -574, 608, 15, 1058, 586, +484, 687, -542, 183, -1050, -457, -658, -717, +333, -334, 1045, 274, 758, 710, -275, 504, +-1003, -101, -797, -641, 106, -636, 875, -94, +813, 506, -13, 718, -751, 295, -703, -355, +-126, -741, 496, -454, 696, 182, 284, 686, +-362, 602, -608, -18, -406, -630, 87, -736, +565, -135, 520, 555, 16, 828, -522, 340, +-602, -448, -222, -910, 368, -532, 624, 323, +276, 874, -340, 692, -568, -136, -336, -780, +145, -784, 511, -31, 310, 659, -126, 770, +-386, 189, -277, -510, 13, -748, 287, -330, +241, 410, 0, 703, -197, 435, -222, -249, +-127, -660, 55, -553, 198, 70, 131, 604, +-24, 606, -185, 142, -221, -468, -90, -669, +109, -365, 130, 335, 62, 674, -32, 501, +-145, -140, -154, -676, -15, -618, 82, 13, +88, 659, 6, 657, -91, 128, -90, -584, +34, -714, 58, -251, -66, 479, -116, 712, +1, 364, 123, -279, 80, -710, -111, -500, +-293, 110, -174, 645, 145, 576, 314, 83, +106, -563, -212, -667, -391, -181, -236, 464, +102, 674, 322, 278, 259, -346, -46, -676, +-345, -331, -371, 244, -84, 586, 282, 373, +403, -101, 101, -487, -306, -420, -458, 8, +-185, 330, 204, 388, 391, 129, 205, -171, +-198, -353, -476, -197, -351, 35, 34, 224, +363, 255, 344, 107, -24, -95, -368, -264, +-409, -192, -142, -38, 129, 206, 285, 274, +212, 143, 12, -151, -245, -304, -373, -200, +-259, 53, 100, 300, 413, 237, 367, 17, +-56, -261, -522, -253, -556, -60, -135, 177, +463, 229, 592, 105, 168, -77, -501, -203, +-795, -86, -417, 4, 323, 103, 781, 84, +469, 77, -300, -2, -886, -44, -673, -88, +93, -163, 772, -73, 674, 145, -17, 341, +-701, 178, -809, -120, -230, -475, 487, -399, +792, 119, 354, 619, -409, 536, -914, -78, +-616, -630, 163, -672, 790, -16, 673, 659, +-81, 753, -808, 80, -894, -593, -221, -754, +572, -251, 833, 515, 311, 798, -500, 356, +-943, -405, -531, -743, 293, -489, 796, 255, +560, 705, -227, 524, -823, -156, -716, -624, +58, -459, 720, 69, 635, 495, -51, 389, +-716, -34, -764, -390, -130, -251, 570, 14, +576, 215, 37, 155, -538, 7, -615, -50, +-174, -51, 338, -1, 421, -80, -30, -90, +-371, -22, -358, 159, -27, 161, 197, 96, +206, -75, -115, -265, -318, -210, -174, -23, +87, 256, 197, 322, 47, 206, -199, -193, +-378, -459, -154, -346, 163, 135, 312, 531, +31, 467, -269, 16, -461, -618, -315, -613, +137, -63, 422, 594, 277, 695, -196, 235, +-534, -522, -550, -810, -73, -325, 425, 378, +563, 778, 117, 475, -452, -144, -704, -716, +-434, -613, 262, -65, 719, 509, 467, 677, +-310, 356, -817, -275, -719, -744, 18, -562, +722, 19, 720, 703, 11, 826, -782, 261, +-948, -658, -387, -1052, 485, -544, 916, 508, +507, 1209, -408, 844, -1017, -270, -865, -1273, +-11, -1122, 850, -8, 943, 1180, 169, 1303, +-836, 318, -1162, -962, -526, -1401, 552, -589, +1102, 690, 634, 1374, -465, 815, -1214, -360, +-944, -1272, 106, -1047, 991, 34, 952, 1113, +11, 1206, -992, 314, -1150, -841, -383, -1346, +582, -662, 956, 547, 492, 1338, -399, 981, +-1008, -149, -796, -1231, -9, -1256, 665, -216, +802, 1017, 228, 1417, -602, 569, -982, -744, +-565, -1475, 225, -876, 809, 476, 693, 1419, +-89, 1091, -892, -160, -973, -1243, -298, -1246, +509, -151, 892, 947, 506, 1256, -412, 499, +-1061, -561, -861, -1146, -54, -815, 756, 120, +927, 932, 236, 1039, -743, 328, -1114, -617, +-584, -1178, 330, -704, 928, 328, 739, 1143, +-204, 1020, -1024, 21, -959, -1044, -185, -1243, +667, -330, 934, 829, 344, 1348, -614, 683, +-1063, -545, -709, -1403, 90, -1016, 787, 268, +854, 1291, 104, 1282, -814, 138, -1143, -1131, +-619, -1494, 406, -466, 1132, 870, 826, 1493, +-329, 834, -1250, -528, -1151, -1448, -120, -1127, +1016, 232, 1217, 1251, 246, 1271, -960, 164, +-1388, -1037, -698, -1415, 551, -460, 1283, 822, +807, 1342, -439, 770, -1331, -485, -1141, -1287, +-66, -1052, 1005, 208, 1087, 1115, 218, 1115, +-856, 207, -1262, -833, -675, -1200, 419, -515, +1077, 597, 734, 1038, -252, 728, -1089, -212, +-1018, -889, -145, -884, 770, -71, 929, 714, +275, 874, -674, 412, -1108, -408, -649, -908, +278, -724, 871, 158, 668, 813, -134, 908, +-908, 244, -928, -645, -260, -1050, 511, -584, +766, 434, 360, 1015, -400, 795, -879, -101, +-658, -878, 29, -995, 603, -181, 629, 739, +66, 971, -637, 453, -773, -442, -320, -975, +314, -738, 570, 200, 272, 908, -243, 877, +-582, 160, -475, -700, -122, -1075, 207, -516, +331, 535, 181, 1060, -164, 800, -446, -120, +-467, -1006, -193, -1107, 157, -202, 331, 851, +245, 1202, -114, 601, -473, -541, -522, -1302, +-216, -954, 238, 279, 528, 1209, 309, 1177, +-289, 140, -733, -1060, -615, -1410, -32, -506, +593, 810, 679, 1451, 89, 926, -680, -410, +-947, -1460, -474, -1339, 338, 4, 843, 1332, +557, 1600, -277, 494, -954, -1082, -903, -1794, +-161, -896, 691, 815, 895, 1780, 287, 1226, +-637, -443, -1113, -1676, -711, -1490, 285, 73, +1016, 1497, 798, 1615, -170, 365, -1102, -1166, +-1162, -1710, -239, -816, 879, 805, 1142, 1639, +337, 1177, -819, -308, -1353, -1453, -799, -1442, +450, -187, 1215, 1175, 809, 1517, -328, 624, +-1222, -766, -1117, -1475, -96, -1012, 916, 378, +1019, 1337, 187, 1237, -778, 63, -1093, -1110, +-599, -1385, 378, -498, 924, 825, 627, 1401, +-227, 828, -886, -446, -904, -1250, -237, -1132, +578, 6, 813, 1071, 306, 1239, -464, 400, +-869, -719, -673, -1241, 22, -793, 588, 380, +635, 1130, 112, 993, -486, 6, -789, -887, +-549, -1120, 115, -397, 628, 635, 627, 1092, +20, 697, -655, -257, -887, -965, -416, -995, +364, -157, 852, 756, 527, 1161, -319, 607, +-949, -440, -887, -1197, -100, -1033, 713, 57, +928, 1148, 225, 1315, -693, 312, -1124, -921, +-659, -1453, 309, -702, 989, 677, 752, 1461, +-237, 963, -999, -336, -998, -1309, -172, -1210, +686, -43, 931, 1140, 304, 1347, -575, 397, +-1021, -819, -685, -1398, 159, -803, 802, 529, +771, 1369, 2, 1042, -789, -162, -1031, -1188, +-421, -1233, 449, -164, 899, 954, 546, 1239, +-332, 472, -981, -631, -836, -1167, -56, -732, +645, 295, 836, 997, 251, 926, -601, 80, +-1019, -792, -588, -1045, 241, -395, 832, 534, +732, 1054, -119, 697, -912, -286, -959, -959, +-222, -843, 560, -17, 904, 770, 405, 941, +-551, 268, -1025, -550, -662, -874, 152, -514, +751, 280, 722, 803, -53, 675, -761, -45, +-845, -624, -280, -754, 378, -223, 695, 473, +427, 737, -315, 412, -756, -247, -617, -641, +-31, -584, 515, 31, 588, 536, 79, 613, +-503, 186, -656, -351, -284, -619, 196, -353, +380, 209, 264, 463, -82, 426, -344, 32, +-417, -296, -228, -430, 16, -230, 233, 65, +314, 330, 67, 458, -304, 207, -488, -242, +-313, -620, -6, -438, 355, 98, 447, 703, +57, 698, -446, 14, -615, -734, -363, -835, +149, -136, 617, 639, 495, 914, -149, 312, +-733, -510, -697, -899, -218, -460, 448, 312, +811, 772, 370, 636, -486, -50, -962, -663, +-678, -758, 106, -169, 870, 479, 835, 792, +-55, 446, -927, -315, -970, -804, -278, -605, +599, 128, 959, 651, 470, 714, -507, 165, +-1092, -524, -745, -754, 126, -366, 924, 263, +918, 684, -12, 656, -975, 0, -1097, -664, +-276, -800, 655, -233, 945, 507, 451, 869, +-472, 505, -1025, -365, -717, -881, 96, -643, +745, 149, 818, 737, 139, 764, -753, 130, +-1008, -624, -385, -842, 511, -322, 847, 421, +472, 799, -342, 568, -877, -207, -655, -798, +40, -706, 557, 19, 605, 646, 189, 779, +-469, 293, -774, -476, -472, -849, 194, -490, +614, 262, 495, 774, -62, 699, -627, 2, +-638, -747, -156, -819, 341, -130, 480, 606, +271, 815, -204, 333, -524, -411, -487, -818, +-84, -479, 364, 220, 484, 667, 220, 623, +-341, 77, -638, -573, -398, -787, 158, -257, +485, 455, 388, 792, -74, 441, -497, -337, +-482, -798, -130, -509, 224, 243, 350, 671, +235, 514, -121, -71, -391, -491, -406, -526, +-151, -123, 199, 323, 415, 471, 254, 313, +-219, -85, -468, -466, -377, -488, -42, -48, +333, 409, 392, 545, 91, 183, -257, -337, +-471, -575, -407, -274, -6, 276, 464, 474, +557, 330, 63, -84, -572, -396, -787, -397, +-299, -64, 527, 243, 829, 376, 256, 298, +-575, -87, -828, -405, -372, -415, 400, -65, +661, 324, 310, 519, -258, 219, -568, -294, +-398, -562, -47, -339, 285, 216, 418, 554, +222, 478, -223, -77, -548, -551, -450, -596, +65, -84, 442, 476, 466, 662, -12, 312, +-514, -384, -465, -692, -140, -462, 211, 235, +359, 702, 234, 577, -114, -47, -387, -661, +-349, -727, -140, -113, 196, 656, 432, 777, +207, 309, -238, -567, -423, -938, -324, -400, +-20, 514, 275, 968, 363, 460, 132, -453, +-255, -905, -420, -466, -415, 407, -36, 826, +494, 319, 531, -324, 43, -591, -536, -272, +-712, 279, -228, 372, 430, 135, 713, -128, +313, -160, -463, -19, -731, 11, -433, -64, +187, -25, 647, 70, 530, 201, -134, 144, +-626, -171, -618, -286, -100, -143, 466, 148, +567, 342, 219, 124, -428, -164, -597, -271, +-289, -127, 155, 190, 381, 166, 361, 5, +33, -87, -345, -50, -431, 60, -311, 73, +82, -155, 477, -203, 530, 88, 4, 268, +-620, 272, -689, -138, -165, -448, 534, -297, +776, 174, 266, 559, -608, 354, -860, -241, +-368, -571, 425, -369, 794, 144, 443, 615, +-338, 434, -851, -138, -544, -541, 207, -492, +692, 30, 499, 506, -52, 535, -656, 45, +-587, -501, 4, -582, 420, -46, 454, 480, +96, 564, -288, 119, -409, -526, -227, -559, +60, -10, 247, 482, 210, 393, 147, -38, +-111, -407, -383, -233, -344, 202, -53, 279, +338, -15, 472, -337, 144, -104, -404, 283, +-662, 337, -278, -22, 388, -468, 625, -396, +328, 231, -307, 660, -746, 319, -473, -330, +241, -755, 697, -390, 480, 408, -130, 858, +-745, 465, -651, -367, 98, -959, 731, -626, +593, 346, -130, 1037, -707, 861, -655, -288, +110, -1275, 687, -1036, 494, 304, -228, 1487, +-627, 1256, -402, -335, 165, -1752, 563, -1405, +267, 464, -316, 1983, -502, 1398, -132, -638, +279, -2082, 391, -1372, 36, 905, -410, 2217, +-368, 1101, 92, -1166, 394, -2128, 232, -842, +-199, 1409, -428, 2056, -201, 381, 228, -1618, +405, -1785, 81, 66, -311, 1783, -372, 1480, +-74, -501, 300, -1929, 321, -1211, -27, 936, +-362, 2022, -319, 881, 91, -1186, 383, -2085, +184, -682, -200, 1484, -391, 2093, -183, 485, +284, -1703, 429, -2110, 45, -326, -440, 1848, +-431, 2136, -21, 234, 488, -1965, 505, -2109, +-79, -99, -663, 1948, -578, 1987, 185, -14, +704, -1894, 530, -1777, -215, 127, -808, 1782, +-575, 1474, 294, -273, 788, -1499, 430, -1148, +-263, 252, -688, 1243, -486, 798, 171, -287, +614, -796, 396, -487, -129, 160, -422, 483, +-424, 270, -52, -72, 328, -210, 385, -167, +34, -42, -185, 42, -265, 213, -227, 153, +22, -64, 162, -213, 234, -204, 137, 110, +-58, 345, -322, 110, -405, -240, -27, -386, +443, -75, 482, 439, 64, 466, -494, -52, +-635, -528, -105, -542, 538, 47, 665, 645, +75, 581, -545, -35, -605, -642, -150, -644, +443, -43, 579, 608, 174, 752, -417, 152, +-537, -573, -202, -815, 232, -349, 551, 467, +331, 971, -319, 543, -633, -428, -298, -1012, +312, -740, 673, 270, 283, 1142, -439, 920, +-808, -211, -180, -1155, 674, -1044, 677, 61, +-21, 1178, -685, 1214, -670, 55, 137, -1198, +814, -1310, 489, -202, -321, 1162, -750, 1442, +-332, 331, 270, -1188, 675, -1532, 317, -375, +-368, 1159, -573, 1591, -209, 384, 309, -1157, +399, -1557, 158, -429, -232, 1130, -297, 1502, +-79, 325, 147, -977, 87, -1277, -25, -400, +85, 862, 79, 1110, -48, 312, -248, -680, +-164, -870, 35, -283, 359, 435, 304, 770, +-187, 295, -441, -373, -268, -534, 199, -230, +393, 118, 240, 419, -157, 207, -425, -66, +-193, -179, 185, -133, 264, -52, 146, -10, +-74, 56, -226, 170, -124, 158, 25, -51, +139, -248, 114, -258, 38, 54, -80, 354, +-179, 277, -119, -100, 120, -412, 278, -158, +90, 185, -197, 273, -369, 39, -75, -240, +363, -220, 486, 237, -85, 318, -594, -56, +-468, -362, 254, -305, 748, 179, 452, 490, +-437, 271, -949, -274, -349, -563, 654, -227, +965, 283, 252, 504, -715, 371, -994, -131, +-207, -580, 803, -538, 928, -106, 137, 601, +-722, 882, -850, 326, -199, -717, 638, -1191, +819, -460, 206, 896, -528, 1434, -704, 449, +-282, -1068, 327, -1592, 697, -361, 350, 1206, +-212, 1572, -593, 271, -422, -1241, 60, -1395, +532, -187, 502, 1098, 64, 1138, -463, 93, +-572, -883, -107, -792, 397, -27, 538, 586, +231, 515, -321, 18, -581, -315, -250, -262, +274, -19, 457, -14, 318, 38, -90, 162, +-455, 256, -407, 106, 56, -239, 373, -470, +373, -193, 118, 390, -289, 552, -488, 161, +-141, -483, 290, -557, 408, -57, 242, 524, +-195, 526, -411, -63, -310, -550, 105, -398, +445, 179, 358, 488, -44, 299, -378, -274, +-494, -453, -30, -154, 490, 330, 535, 484, +29, 65, -555, -433, -555, -487, -5, -49, +579, 511, 632, 590, -50, 9, -696, -601, +-574, -641, 155, 9, 679, 723, 564, 659, +-161, -36, -732, -817, -506, -720, 247, 120, +686, 876, 434, 692, -169, -167, -589, -868, +-469, -621, 32, 258, 599, 783, 542, 456, +91, -367, -504, -648, -751, -187, -265, 446, +618, 453, 960, -111, 339, -531, -667, -189, +-1112, 458, -419, 540, 764, -131, 1227, -854, +479, -506, -771, 539, -1279, 1161, -512, 506, +740, -929, 1259, -1473, 648, -407, -641, 1237, +-1302, 1673, -716, 312, 530, -1459, 1298, -1719, +833, -218, -365, 1542, -1312, 1737, -974, 119, +315, -1501, 1266, -1628, 1031, -153, -184, 1345, +-1175, 1513, -1043, 282, 77, -1108, 1036, -1384, +990, -423, 79, 800, -755, 1248, -928, 592, +-326, -545, 539, -1123, 914, -682, 582, 340, +-273, 929, -909, 715, -829, -105, 67, -755, +1023, -675, 938, -90, 60, 444, -907, 601, +-1075, 344, -125, -124, 841, -502, 1035, -583, +305, -246, -690, 405, -1009, 792, -477, 564, +543, -288, 1114, -1014, 600, -800, -443, 211, +-1136, 1127, -755, 1025, 521, -164, 1220, -1236, +666, -1128, -537, 102, -1190, 1303, -529, 1195, +655, -98, 1057, -1268, 318, -1214, -661, 39, +-863, 1272, -121, 1132, 688, -33, 634, -1086, +-43, -1085, -614, -39, -443, 964, 193, 958, +540, 86, 293, -766, -265, -859, -436, -184, +-100, 613, 239, 821, 314, 236, 62, -505, +-225, -747, -142, -326, 14, 399, 86, 782, +20, 365, 7, -354, 52, -719, 82, -429, +36, 310, -201, 731, -251, 402, 43, -309, +376, -710, 391, -404, -69, 337, -518, 726, +-548, 332, 108, -345, 800, -709, 597, -343, +-223, 391, -841, 681, -669, 275, 330, -397, +973, -604, 552, -223, -363, 375, -920, 558, +-421, 152, 402, -389, 737, -435, 329, -86, +-382, 320, -529, 366, -117, 23, 256, -254, +302, -223, -46, 40, -158, 149, 31, 56, +140, -100, 77, -37, -230, 96, -346, 151, +44, -38, 479, -237, 456, -204, -62, 72, +-620, 344, -629, 323, 44, -79, 830, -426, +772, -480, -87, -51, -896, 579, -862, 764, +53, 153, 1016, -727, 922, -1089, -100, -318, +-1006, 968, -878, 1425, 94, 435, 906, -1206, +842, -1716, -86, -454, -795, 1379, -670, 1918, +18, 533, 607, -1529, 572, -2011, 8, -564, +-409, 1473, -421, 2073, -70, 670, 295, -1350, +286, -2039, 55, -857, -115, 1130, -168, 2031, +-24, 1038, 53, -855, 32, -1968, -37, -1292, +-2, 581, 111, 1882, 120, 1475, -7, -245, +-173, -1716, -267, -1611, -61, -104, 309, 1452, +391, 1739, 112, 446, -363, -1165, -520, -1750, +-201, -861, 446, 867, 667, 1840, 169, 1202, +-459, -562, -619, -1896, -249, -1573, 448, 271, +630, 1963, 218, 1874, -300, -40, -517, -1979, +-262, -2082, 126, -193, 418, 1984, 352, 2217, +8, 297, -281, -1929, -385, -2251, -177, -387, +201, 1851, 385, 2242, 275, 447, -69, -1767, +-329, -2181, -286, -499, -103, 1607, 178, 2099, +364, 566, 264, -1441, -13, -1964, -356, -611, +-476, 1256, -179, 1807, 392, 635, 726, -1054, +311, -1641, -475, -665, -852, 854, -427, 1470, +507, 705, 1015, -612, 459, -1304, -602, -786, +-1024, 345, -407, 1168, 573, 930, 979, -115, +367, -1032, -566, -1076, -864, -180, -262, 997, +520, 1265, 659, 343, 198, -934, -400, -1414, +-482, -552, -131, 913, 296, 1563, 304, 659, +78, -881, -146, -1587, -164, -787, -116, 805, +46, 1645, 141, 876, 74, -739, 11, -1601, +-82, -977, -123, 571, 5, 1605, 124, 1055, +92, -457, -21, -1500, -142, -1142, -114, 304, +53, 1426, 169, 1166, 164, -170, -59, -1298, +-250, -1191, -191, 24, 87, 1155, 315, 1199, +254, 106, -91, -984, -410, -1185, -286, -285, +111, 839, 472, 1138, 308, 401, -118, -638, +-436, -1083, -376, -516, 58, 498, 433, 998, +365, 568, 42, -318, -316, -890, -448, -666, +-176, 167, 241, 811, 470, 687, 304, 13, +-132, -639, -478, -768, -444, -169, 20, 535, +490, 731, 504, 263, 100, -356, -368, -707, +-600, -350, -258, 291, 303, 612, 601, 362, +380, -178, -130, -508, -615, -383, -555, 77, +27, 405, 537, 357, 682, 34, 184, -246, +-519, -336, -774, -149, -350, 80, 430, 254, +875, 257, 496, 82, -397, -149, -917, -311, +-554, -284, 337, 53, 878, 387, 574, 435, +-261, 32, -794, -439, -487, -594, 143, -126, +572, 502, 482, 695, -6, 204, -406, -498, +-387, -730, -138, -319, 147, 437, 329, 765, +272, 406, 6, -325, -209, -716, -338, -540, +-234, 172, 92, 724, 381, 664, 415, -45, +48, -712, -447, -756, -565, -89, -175, 713, +467, 853, 734, 119, 257, -705, -524, -840, +-800, -154, -305, 672, 531, 815, 833, 108, +330, -649, -510, -714, -829, -76, -317, 586, +445, 602, 743, 84, 361, -509, -374, -506, +-721, -64, -362, 403, 305, 383, 671, 64, +399, -292, -277, -325, -641, -67, -386, 266, +272, 260, 606, 25, 269, -202, -241, -223, +-518, -6, -225, 227, 232, 183, 397, -90, +140, -237, -115, -59, -271, 168, -178, 204, +-3, -31, 152, -270, 243, -178, 207, 194, +-114, 356, -409, 37, -337, -327, 77, -354, +561, 72, 557, 437, -133, 368, -745, -195, +-679, -566, 118, -319, 906, 284, 866, 604, +-143, 332, -1088, -295, -983, -673, 131, -352, +1213, 307, 1129, 706, -94, 394, -1364, -298, +-1253, -738, 122, -496, 1393, 276, 1309, 833, +-3, 586, -1446, -237, -1414, -869, -10, -704, +1342, 136, 1436, 903, 172, 819, -1212, -50, +-1453, -887, -341, -873, 1046, -85, 1401, 797, +536, 927, -766, 192, -1355, -704, -733, -902, +486, -269, 1251, 501, 947, 832, -197, 368, +-1118, -321, -1112, -702, -95, -404, 997, 92, +1226, 456, 344, 452, -871, 173, -1241, -248, +-528, -430, 676, -377, 1219, -57, 652, 396, +-489, 623, -1098, 302, -712, -353, 222, -776, +938, -555, 807, 260, -9, 950, -750, 766, +-813, -187, -260, -1028, 518, -932, 858, 85, +494, 1023, -295, 1096, -856, 64, -667, -1027, +27, -1176, 803, -238, 888, 902, 176, 1277, +-723, 478, -1031, -773, -408, -1366, 648, -675, +1129, 610, 591, 1350, -557, 914, -1176, -410, +-676, -1349, 436, -1046, 1126, 230, 733, 1206, +-283, 1107, -1006, 2, -736, -1024, 144, -1123, +781, -190, 756, 810, 72, 1035, -592, 326, +-720, -553, -255, -953, 368, -451, 667, 429, +435, 825, -125, 454, -626, -278, -564, -687, +-71, -457, 478, 184, 744, 553, 313, 361, +-421, -113, -812, -333, -537, -270, 328, 4, +966, 151, 702, 138, -269, 64, -1031, 52, +-836, -25, 203, -124, 1101, -231, 937, -48, +-144, 199, -1111, 333, -1012, 101, 52, -231, +1131, -447, 1108, -153, 6, 315, -1105, 509, +-1173, 187, -125, -337, 1125, -569, 1273, -263, +175, 359, -1074, 656, -1305, 292, -311, -379, +1020, -647, 1371, -358, 416, 350, -920, 735, +-1359, 350, -529, -370, 772, -714, 1367, -377, +640, 345, -633, 755, -1281, 399, -741, -374, +445, -740, 1188, -391, 846, 335, -210, 743, +-1056, 438, -920, -368, -76, -749, 902, -428, +1121, 304, 309, 776, -756, 494, -1224, -279, +-650, -782, 676, -542, 1408, 198, 843, 819, +-508, 618, -1512, -142, -1078, -843, 411, -734, +1549, 80, 1243, 903, -218, 887, -1490, -19, +-1384, -963, 13, -1046, 1382, -115, 1445, 1025, +277, 1231, -1149, 193, -1506, -1023, -545, -1331, +873, -365, 1527, 1022, 860, 1440, -557, 452, +-1525, -962, -1135, -1492, 314, -601, 1496, 868, +1367, 1551, -44, 760, -1487, -762, -1486, -1569, +-128, -896, 1405, 572, 1588, 1582, 243, 1068, +-1264, -426, -1576, -1529, -406, -1207, 1150, 243, +1526, 1479, 517, 1337, -932, -39, -1455, -1364, +-626, -1446, 722, -226, 1352, 1189, 768, 1534, +-510, 506, -1226, -919, -825, -1559, 253, -823, +1084, 665, 923, 1584, -39, 1059, -917, -415, +-951, -1553, -185, -1296, 761, 254, 976, 1588, +376, 1400, -538, -146, -995, -1543, -536, -1457, +359, 65, 958, 1481, 745, 1395, -192, -43, +-937, -1286, -861, -1238, 22, -36, 957, 1084, +986, 1029, 107, 78, -927, -794, -1109, -843, +-204, -175, 918, 547, 1189, 724, 309, 319, +-861, -301, -1222, -647, -446, -512, 839, 48, +1294, 635, 510, 703, -715, 165, -1289, -600, +-618, -912, 649, -352, 1261, 578, 735, 1038, +-483, 486, -1193, -536, -820, -1130, 267, -583, +1120, 517, 967, 1123, 26, 635, -995, -468, +-1155, -1098, -282, -662, 890, 420, 1329, 1031, +597, 668, -768, -310, -1461, -968, -814, -719, +616, 231, 1525, 896, 1052, 733, -399, -85, +-1507, -843, -1228, -756, 138, 15, 1423, 751, +1486, 743, 141, 33, -1321, -666, -1621, -698, +-446, -50, 1263, 552, 1799, 616, 648, 71, +-1123, -444, -1884, -502, -815, -78, 1035, 301, +1919, 365, 941, 126, -923, -141, -1852, -235, +-997, -143, 767, -14, 1788, 71, 1070, 194, +-654, 191, -1619, 33, -1049, -227, 462, -339, +1473, -120, 1049, 248, -303, 479, -1238, 205, +-972, -325, 119, -538, 1015, -235, 912, 302, +10, 588, -761, 284, -766, -297, -121, -551, +512, -286, 660, 231, 172, 497, -328, 308, +-427, -168, -201, -433, 104, -305, 318, 90, +200, 390, 41, 314, -115, -57, -185, -347, +-187, -301, 15, 2, 187, 326, 234, 298, +153, -44, -152, -273, -312, -203, -212, 57, +102, 240, 348, 116, 329, -171, -25, -211, +-372, 37, -425, 273, 4, 169, 406, -163, +483, -367, 136, -157, -420, 302, -547, 441, +-142, 81, 364, -415, 603, -483, 261, -8, +-315, 533, -599, 516, -281, -47, 256, -631, +561, -585, 367, 75, -157, 679, -515, 643, +-318, -13, 76, -673, 412, -712, 375, -73, +-10, 635, -284, 752, -364, 150, -53, -532, +253, -759, 366, -253, 147, 490, -218, 761, +-378, 290, -124, -399, 218, -744, 379, -360, +171, 369, -237, 754, -350, 382, -129, -305, +212, -694, 323, -406, 157, 257, -164, 647, +-292, 349, -152, -210, 122, -500, 279, -270, +164, 166, -49, 357, -224, 159, -173, -115, +4, -177, 151, -71, 173, 48, 86, 21, +-42, 21, -135, 50, -169, 86, -87, -35, +161, -136, 264, -148, 185, 60, -125, 217, +-345, 121, -261, -137, 101, -218, 419, -31, +312, 195, -27, 183, -423, -106, -416, -306, +-17, -131, 438, 254, 513, 398, 134, 62, +-434, -395, -600, -500, -199, -74, 437, 515, +688, 620, 246, 90, -409, -597, -704, -745, +-275, -159, 428, 627, 687, 861, 325, 270, +-343, -672, -683, -983, -313, -367, 319, 635, +612, 1074, 401, 493, -193, -585, -596, -1126, +-444, -585, 110, 491, 582, 1109, 555, 662, +53, -342, -545, -1043, -652, -749, -154, 226, +578, 945, 765, 778, 282, -32, -524, -827, +-825, -828, -335, -94, 518, 695, 863, 839, +406, 257, -376, -526, -823, -799, -459, -372, +310, 359, 740, 700, 545, 466, -111, -121, +-678, -549, -597, -507, 20, -53, 596, 396, +668, 542, 128, 261, -555, -260, -694, -559, +-189, -395, 515, 165, 714, 610, 283, 539, +-445, -66, -757, -614, -329, -637, 406, -21, +728, 611, 439, 669, -312, 122, -771, -527, +-484, -651, 233, -182, 753, 415, 569, 576, +-172, 185, -742, -313, -605, -453, 102, -189, +741, 209, 623, 350, -94, 125, -723, -146, +-607, -226, 115, -97, 691, 66, 554, 101, +-129, 20, -651, -58, -484, 10, 170, 53, +617, 15, 378, -107, -163, -160, -511, -78, +-351, 142, 177, 247, 465, 86, 299, -151, +-109, -306, -380, -181, -278, 104, 81, 299, +328, 192, 277, -34, -3, -282, -205, -250, +-238, -21, -54, 203, 151, 242, 219, 87, +151, -147, 6, -254, -173, -127, -219, 87, +-30, 216, 192, 182, 285, -4, 137, -197, +-169, -207, -300, -36, -96, 142, 182, 234, +316, 119, 156, -88, -123, -192, -263, -134, +-146, 35, 102, 153, 252, 162, 209, 56, +16, -44, -222, -111, -227, -94, -14, -56, +236, 79, 286, 181, 62, 176, -226, 24, +-262, -182, -22, -245, 226, -87, 235, 210, +16, 332, -195, 195, -149, -112, 50, -348, +126, -306, 69, 18, -56, 363, -78, 448, +-2, 180, 88, -321, 27, -575, -83, -335, +-92, 290, -23, 714, 66, 501, 102, -248, +55, -813, -76, -616, -126, 195, -114, 871, +-5, 706, 185, -170, 211, -920, 7, -782, +-231, 66, -295, 864, -71, 851, 293, 4, +347, -837, 36, -895, -309, -153, -365, 733, +-74, 918, 292, 215, 355, -714, 72, -980, +-237, -311, -307, 662, -118, 994, 161, 341, +290, -709, 147, -1067, -95, -389, -206, 674, +-143, 1064, 29, 372, 185, -718, 159, -1073, +54, -374, -47, 669, -114, 1005, -116, 298, +-29, -680, 146, -947, 271, -231, 155, 660, +-137, 844, -335, 158, -163, -671, 219, -784, +460, -71, 244, 666, -219, 697, -449, 38, +-174, -666, 265, -643, 450, 63, 227, 696, +-180, 621, -362, -63, -176, -701, 167, -601, +328, 114, 235, 748, -42, 663, -234, -60, +-203, -724, 15, -667, 205, 64, 226, 743, +57, 732, -127, 54, -173, -672, -40, -713, +102, -78, 124, 637, 37, 729, -41, 195, +-19, -510, 12, -690, -13, -207, -79, 433, +-62, 657, 82, 311, 192, -296, 77, -587, +-197, -322, -318, 200, -66, 528, 287, 371, +375, -71, 11, -441, -438, -399, -450, -21, +53, 342, 510, 395, 415, 136, -167, -257, +-586, -434, -419, -250, 206, 136, 573, 404, +329, 342, -248, -72, -571, -436, -308, -451, +204, -46, 470, 376, 265, 473, -176, 76, +-402, -410, -228, -532, 94, -155, 289, 340, +186, 472, -45, 105, -171, -395, -103, -467, +15, -113, 53, 326, 13, 379, 46, 0, +88, -394, 116, -332, -7, 45, -214, 333, +-181, 221, 73, -162, 338, -386, 319, -152, +-43, 247, -376, 355, -310, 58, 90, -340, +481, -411, 415, -37, -56, 422, -448, 463, +-386, 58, 105, -436, 538, -515, 463, -112, +-42, 439, -527, 594, -430, 240, 137, -368, +603, -592, 496, -289, -96, 327, -600, 649, +-445, 419, 187, -216, 630, -614, 484, -424, +-124, 195, -575, 664, -464, 547, 121, -49, +574, -598, 469, -556, -43, 30, -494, 622, +-498, 658, 18, 126, 499, -520, 465, -645, +-8, -146, -459, 508, -439, 676, 6, 260, +397, -370, 344, -626, -56, -294, -343, 312, +-272, 616, 25, 397, 220, -168, 137, -567, +-50, -485, -140, 31, -100, 520, -17, 593, +8, 109, -23, -481, -3, -661, 57, -272, +32, 381, -59, 669, -144, 323, -149, -353, +18, -679, 210, -422, 184, 187, -51, 600, +-292, 419, -282, -176, 10, -602, 337, -517, +341, -2, -39, 498, -395, 525, -364, 38, +11, -532, 428, -652, 417, -214, -21, 415, +-406, 636, -388, 236, 40, -433, 423, -740, +381, -362, 23, 341, -338, 717, -326, 382, +18, -373, 316, -809, 331, -478, 91, 341, +-178, 821, -252, 507, -98, -371, 165, -884, +328, -549, 220, 360, -44, 901, -254, 559, +-230, -349, 85, -858, 350, -516, 294, 322, +0, 818, -246, 532, -236, -215, 27, -674, +265, -443, 267, 153, 56, 583, -124, 504, +-182, 22, -105, -398, 92, -402, 233, -73, +203, 316, 9, 467, -215, 236, -264, -126, +-50, -317, 250, -223, 322, 81, 71, 304, +-256, 313, -340, 100, -97, -112, 220, -236, +324, -158, 96, 49, -232, 276, -341, 334, +-134, 132, 178, -212, 280, -421, 121, -231, +-191, 223, -340, 560, -162, 385, 138, -174, +279, -636, 127, -496, -167, 123, -346, 658, +-202, 558, 126, -66, 281, -647, 150, -630, +-137, -32, -318, 546, -230, 574, 74, 55, +258, -504, 180, -610, -56, -188, -210, 344, +-217, 489, -37, 171, 139, -303, 189, -518, +116, -304, -62, 121, -187, 372, -215, 263, +-33, -103, 235, -388, 314, -344, 117, -64, +-210, 240, -391, 279, -161, 35, 290, -246, +513, -317, 258, -156, -276, 111, -544, 256, +-269, 159, 344, -78, 699, -260, 371, -278, +-294, -74, -657, 219, -346, 351, 348, 172, +730, -217, 441, -480, -229, -283, -612, 250, +-357, 619, 218, 385, 565, -262, 407, -701, +-57, -398, -366, 372, -303, 811, 15, 450, +257, -345, 281, -777, 135, -374, -52, 459, +-185, 819, -175, 391, -37, -368, 135, -693, +250, -271, 169, 444, -72, 714, -271, 301, +-241, -335, 14, -536, 266, -178, 286, 372, +54, 562, -306, 200, -366, -271, -110, -389, +225, -91, 388, 287, 153, 398, -296, 143, +-486, -188, -251, -282, 219, -110, 480, 129, +266, 271, -244, 199, -579, -18, -370, -225, +158, -261, 517, -115, 378, 178, -151, 317, +-553, 199, -463, -132, 44, -391, 473, -346, +437, 19, -31, 348, -473, 359, -451, 24, +-66, -384, 373, -477, 411, -164, 63, 275, +-308, 416, -379, 153, -129, -315, 224, -529, +362, -283, 160, 202, -168, 452, -324, 242, +-185, -251, 131, -552, 371, -362, 251, 137, +-106, 453, -331, 294, -227, -166, 123, -472, +425, -374, 323, 41, -98, 333, -397, 291, +-278, -19, 175, -278, 492, -301, 350, -117, +-117, 134, -454, 265, -268, 192, 189, -20, +475, -243, 341, -312, -87, -107, -368, 221, +-274, 426, 65, 263, 383, -139, 390, -446, +58, -360, -307, 87, -378, 515, -77, 524, +359, 92, 454, -408, 101, -553, -340, -165, +-398, 445, -52, 719, 312, 380, 364, -303, +51, -726, -253, -461, -249, 333, -86, 901, +80, 669, 195, -173, 154, -873, 14, -703, +-173, 198, -312, 964, -201, 819, 147, -63, +396, -869, 256, -741, -201, 119, -541, 864, +-421, 717, 130, -76, 568, -740, 434, -588, +-149, 149, -629, 671, -576, 471, 16, -146, +572, -538, 552, -356, 12, 142, -554, 386, +-629, 199, -177, -129, 406, -239, 597, -124, +248, 37, -312, 52, -635, -33, -431, -56, +166, 20, 609, 46, 528, -31, -59, -157, +-633, -163, -643, -51, -33, 107, 625, 128, +707, -13, 119, -182, -590, -222, -719, -115, +-149, 83, 560, 171, 723, 67, 228, -125, +-434, -244, -639, -190, -219, 6, 396, 171, +595, 129, 302, -33, -218, -199, -453, -211, +-237, -56, 177, 164, 402, 190, 261, 27, +-38, -201, -217, -268, -155, -41, 44, 281, +151, 332, 131, 13, 44, -379, 32, -412, +37, 30, -20, 513, -97, 513, -100, -27, +67, -561, 250, -517, 233, 103, -40, 662, +-336, 589, -303, -71, 96, -616, 431, -503, +366, 164, -106, 680, -512, 539, -387, -109, +156, -582, 558, -438, 357, 188, -226, 629, +-596, 487, -355, -83, 256, -493, 572, -379, +260, 107, -333, 474, -586, 410, -253, 19, +296, -297, 513, -294, 163, -36, -351, 224, +-537, 302, -188, 157, 286, -70, 422, -219, +131, -217, -307, -28, -441, 207, -157, 315, +185, 156, 307, -166, 123, -393, -154, -272, +-260, 116, -190, 413, 10, 334, 156, -101, +185, -490, 92, -428, -124, 26, -290, 434, +-199, 418, 77, -26, 329, -478, 280, -501, +-72, -74, -376, 340, -327, 409, 61, 82, +441, -358, 383, -475, -11, -192, -401, 178, +-419, 336, -16, 166, 442, -170, 521, -372, +122, -239, -382, 48, -533, 233, -177, 161, +402, -73, 678, -250, 298, -182, -337, 31, +-627, 159, -330, 86, 328, -96, 723, -170, +421, -72, -233, 108, -640, 163, -408, 31, +207, -162, 617, -182, 482, -15, -97, 205, +-519, 227, -403, 38, 32, -206, 433, -266, +449, -25, 92, 280, -301, 332, -412, 87, +-181, -241, 202, -358, 426, -77, 287, 363, +-106, 490, -429, 159, -371, -321, 19, -507, +379, -175, 385, 441, 62, 684, -328, 285, +-442, -378, -198, -670, 220, -301, 396, 425, +239, 792, -133, 419, -461, -320, -369, -722, +53, -408, 372, 298, 322, 743, -32, 503, +-358, -166, -363, -650, -56, -497, 230, 120, +233, 598, 53, 543, -140, 2, -240, -519, +-163, -546, 24, -56, 164, 433, 154, 511, +1, 129, -195, -359, -217, -509, -26, -205, +167, 253, 172, 424, -12, 211, -165, -182, +-156, -421, 6, -313, 144, 57, 127, 319, +-9, 263, -124, -39, -86, -334, 33, -334, +115, -78, 111, 215, 4, 243, -124, 30, +-89, -216, 64, -266, 168, -112, 120, 96, +-36, 150, -183, 37, -111, -95, 139, -137, +266, -75, 126, -18, -133, 33, -257, 29, +-89, 13, 228, -15, 332, -57, 71, -93, +-233, -53, -262, 65, -1, 118, 276, 55, +276, -78, -8, -159, -235, -85, -181, 114, +52, 192, 217, 68, 162, -89, -44, -151, +-165, -19, -114, 135, 58, 153, 161, 13, +67, -88, -93, -53, -145, 70, -16, 135, +107, 74, 106, -34, -31, -76, -164, 9, +-109, 106, 83, 133, 154, 33, 52, -54, +-111, -68, -201, 12, -91, 112, 128, 131, +185, 55, 48, -45, -157, -80, -244, -28, +-125, 64, 129, 121, 270, 111, 89, 24, +-197, -87, -325, -108, -169, -37, 174, 102, +342, 190, 116, 110, -251, -102, -396, -218, +-132, -122, 247, 98, 367, 253, 86, 150, +-291, -126, -362, -303, -66, -197, 266, 85, +291, 294, 14, 219, -217, -82, -213, -349, +-37, -309, 128, -2, 137, 297, 46, 310, +-4, 2, -51, -339, -111, -391, -82, -99, +33, 250, 178, 329, 187, 63, 25, -278, +-202, -371, -233, -147, 12, 175, 271, 289, +255, 104, 37, -178, -239, -309, -256, -177, +19, 97, 261, 247, 260, 133, -17, -88, +-228, -226, -163, -165, 79, 23, 242, 136, +131, 95, -98, -3, -177, -58, -44, -52, +151, -38, 168, -24, -5, 10, -141, 70, +-114, 110, 37, 44, 183, -84, 100, -134, +-74, -28, -150, 134, -87, 188, 69, 74, +167, -98, 89, -158, -87, -28, -171, 144, +-94, 192, 51, 80, 147, -68, 108, -116, +-60, -11, -164, 106, -137, 140, 2, 48, +118, -55, 145, -36, 21, 37, -150, 76, +-197, 60, -81, 0, 98, -30, 183, 23, +100, 60, -98, 34, -236, -8, -167, -20, +29, 6, 205, 55, 186, 71, -34, 12, +-227, -77, -238, -78, -27, -5, 186, 95, +210, 135, 45, 21, -168, -136, -239, -191, +-95, -53, 108, 141, 186, 205, 109, 62, +-40, -168, -165, -254, -177, -112, -47, 97, +138, 202, 230, 96, 140, -92, -118, -206, +-296, -179, -201, -40, 128, 115, 364, 152, +260, 66, -97, -99, -389, -244, -286, -212, +104, 3, 418, 217, 332, 235, -60, 10, +-385, -272, -320, -355, 47, -120, 388, 232, +371, 346, 0, 136, -330, -230, -339, -401, +-16, -219, 330, 172, 354, 393, 36, 232, +-286, -129, -283, -382, -18, -278, 246, 101, +272, 375, 32, 291, -216, -56, -204, -342, +-13, -272, 179, 76, 175, 351, 7, 297, +-145, -45, -150, -316, 8, -239, 124, 99, +137, 332, 1, 262, -151, -60, -159, -278, +-7, -177, 181, 136, 153, 316, -41, 195, +-215, -85, -193, -272, 34, -144, 238, 162, +192, 335, -82, 198, -290, -119, -220, -305, +64, -185, 270, 158, 203, 382, -80, 243, +-300, -119, -248, -360, 46, -250, 283, 123, +214, 398, -59, 284, -303, -95, -239, -365, +86, -300, 261, 60, 123, 343, -114, 297, +-211, -22, -61, -321, 129, -318, 113, -30, +-59, 235, -149, 276, -15, 51, 160, -209, +120, -284, -97, -107, -234, 115, -112, 191, +169, 75, 304, -98, 101, -188, -220, -126, +-317, 17, -104, 74, 229, 58, 352, 1, +147, -77, -202, -119, -353, -80, -168, 1, +165, 70, 356, 83, 260, 8, -66, -135, +-349, -162, -329, -58, 24, 81, 396, 159, +432, 67, 58, -111, -395, -202, -456, -113, +-47, 73, 398, 200, 464, 139, 90, -52, +-330, -197, -418, -168, -114, 26, 294, 205, +383, 187, 155, 18, -154, -167, -332, -188, +-232, -21, 80, 175, 314, 230, 299, 93, +-1, -110, -320, -195, -342, -86, -46, 126, +301, 261, 358, 150, 72, -79, -278, -207, +-367, -123, -110, 113, 219, 276, 323, 170, +115, -78, -192, -208, -291, -100, -131, 103, +85, 219, 204, 125, 132, -61, -44, -130, +-150, -55, -162, 52, -72, 105, 51, 69, +162, 24, 122, -36, -30, -58, -173, -60, +-200, -17, -48, 62, 162, 119, 226, 59, +71, -82, -182, -155, -263, -103, -106, 45, +148, 149, 272, 99, 118, -61, -158, -162, +-269, -129, -131, -1, 117, 92, 259, 90, +140, 5, -117, -103, -227, -129, -135, -71, +77, -1, 218, 83, 151, 104, -36, -25, +-201, -153, -166, -183, 40, -51, 219, 139, +175, 186, -18, 22, -180, -213, -182, -258, +20, -37, 203, 196, 184, 237, 12, 22, +-158, -226, -202, -267, -29, -36, 189, 205, +223, 246, 79, 51, -155, -181, -261, -243, +-105, -85, 176, 162, 312, 256, 120, 134, +-158, -105, -277, -228, -144, -160, 127, 60, +282, 233, 195, 228, -57, 30, -271, -147, +-245, -215, 4, -97, 264, 144, 315, 286, +44, 191, -285, -55, -343, -252, -91, -227, +238, 72, 358, 342, 143, 319, -222, -10, +-392, -343, -182, -333, 158, 21, 346, 415, +243, 448, -98, 24, -364, -429, -309, -467, +34, -35, 337, 486, 306, 552, 3, 67, +-324, -515, -313, -589, -28, -57, 205, 560, +226, 625, 91, 63, -97, -586, -246, -654, +-192, -63, -1, 597, 207, 639, 238, 47, +68, -600, -198, -660, -323, -93, -136, 568, +190, 623, 352, 58, 154, -549, -178, -634, +-344, -119, -215, 481, 126, 575, 339, 94, +251, -463, -61, -562, -315, -163, -313, 337, +2, 477, 360, 165, 337, -285, 7, -461, +-310, -236, -337, 141, -26, 374, 298, 277, +316, -81, 39, -350, -228, -328, -231, -33, +-46, 276, 159, 316, 189, 84, 91, -214, +-46, -316, -127, -141, -88, 130, -23, 267, +68, 205, 155, -30, 121, -241, -29, -236, +-156, -20, -182, 233, -21, 304, 204, 99, +241, -219, 68, -320, -207, -79, -286, 267, +-88, 362, 184, 129, 326, -240, 140, -348, +-187, -98, -340, 271, -156, 388, 165, 150, +331, -207, 180, -361, -172, -146, -320, 226, +-161, 409, 124, 206, 277, -175, 152, -390, +-107, -222, -256, 172, -142, 425, 90, 279, +206, -106, 102, -410, -98, -312, -184, 57, +-87, 388, 82, 395, 132, 39, 31, -370, +-105, -436, -107, -115, -10, 327, 63, 491, +47, 166, -29, -337, -39, -517, 14, -208, +-1, 300, -55, 500, -58, 189, 54, -309, +114, -523, 36, -208, -106, 269, -187, 454, +-44, 195, 179, -266, 217, -468, 13, -232, +-227, 197, -250, 400, -34, 208, 280, -200, +343, -409, 38, -238, -339, 162, -408, 355, +-44, 174, 402, -205, 483, -345, 71, -139, +-432, 210, -540, 298, -82, 51, 464, -261, +581, -273, 158, 24, -455, 265, -610, 196, +-176, -87, 435, -266, 631, -124, 240, 153, +-340, 228, -628, 50, -310, -169, 310, -165, +627, 28, 360, 184, -220, 128, -553, -50, +-396, -147, 107, -31, 508, 110, 451, 120, +-2, 18, -432, -86, -492, -50, -113, 74, +382, 126, 523, 51, 167, -69, -307, -96, +-495, 0, -257, 108, 210, 114, 489, 10, +332, -75, -124, -53, -482, 36, -411, 65, +36, 3, 458, -26, 478, 8, 14, 73, +-469, 54, -495, -64, -55, -143, 425, -35, +479, 161, 78, 194, -395, -6, -486, -231, +-100, -216, 333, 63, 448, 296, 111, 195, +-308, -158, -419, -364, -137, -182, 279, 205, +367, 366, 94, 136, -231, -268, -319, -404, +-108, -123, 194, 259, 237, 355, 57, 97, +-130, -276, -181, -344, -76, -96, 53, 216, +132, 279, 108, 47, -10, -212, -110, -236, +-143, -62, -33, 137, 110, 154, 158, 21, +70, -90, -84, -77, -181, -41, -125, -28, +54, -20, 242, 44, 204, 133, -70, 106, +-310, -67, -242, -256, 109, -194, 366, 109, +281, 346, -105, 245, -414, -116, -305, -411, +139, -286, 449, 161, 334, 463, -103, 313, +-456, -144, -367, -461, 85, -331, 459, 153, +424, 510, -1, 387, -457, -110, -489, -489, +-34, -416, 456, 93, 519, 530, 91, 477, +-408, -8, -527, -483, -155, -476, 341, -12, +502, 445, 246, 496, -234, 97, -487, -357, +-323, -430, 97, -131, 469, 269, 428, 405, +1, 193, -437, -158, -501, -337, -87, -237, +405, 69, 508, 292, 158, 277, -346, 42, +-518, -236, -228, -300, 246, -103, 497, 170, +260, 300, -192, 157, -447, -120, -305, -293, +91, -193, 361, 72, 314, 246, -4, 183, +-306, -54, -322, -239, -77, -198, 222, 18, +317, 185, 109, 155, -165, -19, -273, -167, +-173, -151, 56, -19, 237, 107, 219, 105, +8, 16, -216, -74, -257, -103, -70, -69, +181, 21, 256, 72, 104, 74, -148, -7, +-258, -77, -122, -86, 121, -22, 246, 62, +118, 54, -106, -24, -197, -56, -82, -8, +79, 54, 130, 48, 84, -47, 5, -111, +-98, -30, -127, 107, -21, 147, 118, 24, +151, -131, 44, -157, -114, -5, -174, 171, +-27, 173, 134, 10, 159, -149, 39, -142, +-125, 27, -153, 154, -37, 143, 113, 5, +162, -122, 62, -92, -106, 14, -139, 94, +-56, 79, 84, 8, 172, -32, 68, -28, +-65, 2, -141, 17, -77, 1, 31, 6, +104, 35, 119, 55, 28, 28, -88, -26, +-143, -83, -108, -60, 64, 42, 216, 121, +161, 90, -79, -21, -265, -132, -174, -134, +98, 2, 258, 140, 186, 154, -73, 34, +-263, -148, -207, -210, 18, -84, 256, 137, +251, 271, 10, 135, -277, -161, -309, -348, +-16, -235, 297, 143, 301, 411, -4, 289, +-302, -152, -265, -481, -8, -354, 234, 130, +238, 473, 14, 357, -182, -117, -232, -483, +-81, -372, 156, 95, 262, 431, 81, 342, +-196, -97, -248, -429, -50, -330, 225, 91, +211, 392, -52, 271, -218, -113, -114, -361, +121, -220, 169, 144, -1, 311, -164, 118, +-88, -180, 97, -248, 161, -27, 11, 213, +-110, 187, -113, -46, -24, -223, 80, -137, +104, 112, 90, 243, -34, 147, -182, -103, +-142, -270, 66, -154, 255, 125, 161, 313, +-109, 201, -247, -126, -140, -341, 114, -208, +229, 167, 149, 400, -34, 223, -204, -195, +-204, -398, -11, -184, 202, 212, 268, 391, +87, 189, -191, -162, -324, -313, -136, -190, +218, 57, 380, 249, 168, 238, -209, 55, +-371, -177, -171, -274, 209, -152, 346, 119, +164, 302, -141, 231, -311, -77, -204, -314, +101, -244, 303, 38, 205, 284, -51, 246, +-271, -9, -217, -247, 16, -263, 207, -59, +252, 196, 62, 268, -185, 101, -310, -178, +-128, -299, 216, -152, 356, 139, 141, 287, +-270, 147, -391, -144, -81, -288, 303, -155, +370, 127, 32, 245, -345, 96, -330, -129, +13, -216, 325, -94, 287, 111, -32, 174, +-273, 77, -296, -98, -44, -180, 279, -99, +326, 81, 69, 184, -307, 103, -383, -98, +-42, -197, 350, -104, 391, 87, -26, 205, +-396, 110, -319, -102, 61, -201, 368, -101, +259, 111, -89, 207, -287, 89, -210, -95, +57, -184, 203, -91, 196, 62, 39, 150, +-162, 138, -200, 10, -79, -116, 162, -182, +227, -102, 47, 128, -161, 266, -173, 179, +-1, -93, 156, -347, 111, -227, -41, 150, +-85, 399, -37, 263, 39, -175, 47, -428, +8, -217, -42, 199, -16, 443, 65, 220, +56, -225, -37, -389, -105, -189, -54, 210, +62, 394, 147, 147, 79, -195, -89, -306, +-149, -118, -103, 181, 86, 231, 199, 58, +92, -120, -108, -143, -223, -16, -60, 68, +185, 36, 173, 3, -7, 12, -178, 20, +-153, -31, 75, -118, 171, -66, 109, 108, +-90, 184, -188, 47, -60, -213, 111, -236, +161, 8, 24, 250, -134, 231, -136, -65, +5, -302, 138, -198, 110, 109, -35, 287, +-137, 134, -137, -161, 13, -254, 195, -84, +148, 160, -46, 207, -227, 39, -182, -148, +62, -170, 236, -72, 207, 105, -69, 194, +-281, 93, -236, -90, 72, -230, 351, -152, +257, 112, -163, 295, -421, 165, -221, -146, +235, -352, 445, -167, 152, 231, -280, 388, +-427, 121, -115, -280, 308, -396, 387, -54, +86, 326, -304, 371, -370, 42, -50, -352, +298, -346, 334, 27, 49, 366, -294, 358, +-345, -47, -42, -422, 315, -320, 392, 100, +44, 449, -379, 374, -413, -122, 18, -525, +424, -411, 406, 168, -41, 632, -445, 474, +-347, -222, 87, -750, 440, -508, 294, 335, +-133, 865, -371, 500, -227, -422, 144, -958, +325, -463, 155, 559, -112, 1023, -216, 383, +-139, -697, 56, -1044, 177, -263, 125, 807, +-24, 1033, -114, 123, -88, -888, 1, -946, +31, -3, 6, 947, 37, 842, 90, -187, +57, -956, -82, -672, -204, 322, -88, 935, +152, 461, 251, -489, 82, -849, -182, -270, +-253, 584, -89, 750, 150, 71, 245, -667, +117, -658, -94, 99, -232, 719, -237, 519, +22, -250, 294, -754, 322, -428, 3, 370, +-363, 776, -370, 330, 0, -476, 376, -810, +364, -292, -2, 550, -354, 834, -334, 241, +-7, -591, 279, -812, 290, -232, 4, 581, +-222, 796, -195, 208, -22, -553, 117, -764, +117, -206, 69, 540, 32, 694, -73, 174, +-195, -473, -122, -613, 98, -165, 298, 382, +182, 530, -167, 215, -359, -252, -140, -489, +219, -278, 323, 168, 96, 452, -184, 345, +-254, -85, -52, -434, 121, -359, 154, 53, +95, 431, -17, 375, -119, -68, -175, -391, +-47, -337, 192, 42, 268, 396, 73, 312, +-279, -20, -364, -309, 23, -375, 379, -51, +391, 334, -64, 410, -486, 140, -361, -328, +147, -514, 535, -181, 360, 353, -231, 609, +-567, 246, -297, -443, 281, -710, 589, -289, +259, 527, -271, 867, -579, 262, -320, -613, +290, -939, 581, -337, 373, 684, -238, 1030, +-650, 365, -416, -678, 257, -1112, 656, -452, +388, 656, -241, 1151, -605, 539, -372, -627, +205, -1177, 526, -635, 337, 511, -140, 1244, +-436, 739, -330, -498, 33, -1247, 365, -865, +329, 414, 26, 1318, -251, 908, -353, -347, +-124, -1303, 185, -1000, 294, 270, 195, 1254, +-85, 1038, -259, -163, -229, -1190, -46, -1016, +148, 49, 280, 1018, 216, 1026, -98, 68, +-378, -868, -317, -963, 71, -235, 460, 698, +391, 971, -132, 344, -497, -550, -347, -930, +156, -485, 476, 402, 310, 928, -142, 592, +-456, -279, -205, -890, 141, -679, 315, 173, +181, 856, -122, 731, -192, -64, -83, -771, +21, -749, 69, -34, 103, 721, 70, 798, +-16, 73, -162, -712, -88, -780, 97, -86, +233, 727, 57, 793, -256, 32, -260, -726, +108, -727, 400, -12, 243, 710, -254, 699, +-542, -16, -163, -665, 451, -595, 579, 9, +74, 555, -550, 545, -607, 49, 26, -454, +611, -508, 572, -142, -24, 344, -588, 564, +-585, 258, -23, -315, 569, -653, 628, -372, +62, 301, -520, 752, -617, 485, -152, -325, +476, -868, 581, -513, 158, 344, -336, 884, +-502, 532, -269, -360, 191, -852, 432, -453, +327, 320, -12, 713, -396, 407, -443, -270, +-109, -584, 356, -314, 496, 181, 197, 393, +-318, 245, -517, -36, -248, -217, 210, -222, +469, -138, 307, -2, -87, 235, -386, 364, +-364, 162, -67, -286, 260, -543, 391, -299, +254, 297, -147, 707, -436, 396, -389, -366, +-18, -748, 478, -392, 550, 342, 92, 733, +-489, 360, -672, -319, -188, -587, 517, -319, +759, 174, 293, 452, -528, 336, -858, -2, +-339, -314, 525, -385, 943, -193, 399, 177, +-563, 490, -933, 397, -391, -106, 538, -548, +928, -532, 373, -1, -481, 594, -860, 632, +-380, 63, 458, -549, 839, -661, 392, -179, +-424, 482, -830, 698, -403, 273, 450, -385, +850, -676, 393, -386, -507, 281, -839, 684, +-302, 490, 569, -171, 789, -694, 181, -620, +-543, 54, -651, 736, -125, 759, 465, 26, +564, -768, 150, -835, -396, -118, -551, 761, +-158, 899, 377, 166, 558, -724, 154, -901, +-396, -218, -496, 678, -135, 880, 312, 245, +442, -620, 140, -836, -203, -262, -374, 522, +-243, 805, 110, 314, 382, -440, 289, -753, +-72, -373, -389, 299, -330, 678, 52, 467, +399, -104, 326, -592, -103, -604, -374, -95, +-281, 488, 107, 744, 340, 334, 192, -465, +-125, -882, -245, -486, -108, 421, 70, 1008, +154, 597, 74, -428, -50, -1077, -91, -670, +-48, 422, 40, 1067, 80, 710, 20, -318, +-67, -1025, -90, -780, -15, 183, 127, 900, +123, 866, 12, 46, -180, -801, -226, -940, +43, -241, 262, 650, 274, 961, -21, 432, +-377, -489, -308, -958, 90, -573, 395, 319, +330, 888, -69, 712, -380, -116, -345, -807, +8, -826, 324, -106, 377, 674, 209, 927, +-235, 380, -526, -531, -355, -1036, 179, -636, +691, 333, 556, 1042, -163, 887, -804, -104, +-654, -991, 186, -1071, 848, -202, 719, 843, +-113, 1216, -857, 523, -734, -640, 71, -1316, +773, -842, 778, 408, 25, 1365, -705, 1152, +-771, -158, -113, -1379, 618, -1403, 727, -107, +204, 1326, -491, 1600, -648, 387, -222, -1171, +300, -1755, 483, -718, 280, 973, -72, 1805, +-294, 1070, -327, -651, -213, -1821, 86, -1398, +450, 294, 433, 1741, 25, 1704, -472, 114, +-634, -1605, -168, -1960, 488, -497, 736, 1469, +301, 2101, -444, 845, -823, -1214, -458, -2220, +358, -1157, 884, 980, 544, 2180, -247, 1468, +-842, -593, -698, -2131, 86, -1777, 780, 211, +775, 2003, 119, 2037, -654, 245, -900, -1826, +-341, -2291, 534, -637, 983, 1652, 552, 2387, +-396, 974, -1079, -1385, -721, -2444, 317, -1219, +1081, 1120, 852, 2316, -181, 1411, -1040, -756, +-936, -2178, 27, -1608, 946, 394, 1024, 1978, +192, 1756, -843, -3, -1123, -1774, -325, -1933, +764, -331, 1136, 1555, 465, 1948, -617, 629, +-1105, -1257, -550, -1919, 448, -836, 999, 924, +672, 1737, -236, 1010, -880, -542, -751, -1540, +49, -1155, 764, 181, 801, 1321, 171, 1253, +-619, 140, -862, -1086, -341, -1324, 449, -384, +855, 865, 572, 1292, -267, 612, -854, -597, +-729, -1228, 28, -773, 845, 285, 959, 1077, +148, 932, -846, 41, -1109, -876, -303, -1032, +850, -353, 1201, 672, 405, 1089, -815, 583, +-1225, -435, -474, -1072, 710, -731, 1178, 241, +559, 984, -556, 813, -1103, -45, -674, -805, +322, -833, 1032, -160, 825, 638, -117, 817, +-996, 358, -981, -370, -82, -762, 938, -535, +1106, 114, 223, 652, -886, 682, -1154, 191, +-386, -464, 784, -792, 1210, -510, 509, 271, +-665, 830, -1229, 766, -637, 11, 520, -855, +1217, -982, 764, -200, -374, 786, -1201, 1113, +-892, 423, 210, -718, 1200, -1192, 1034, -589, +-132, 576, -1164, 1179, -1088, 737, 68, -385, +1147, -1139, 1045, -870, -53, 164, -997, 970, +-960, 948, 18, 151, 831, -779, 815, -1011, +64, -455, -607, 479, -645, 1025, -174, 773, +338, -194, 542, -1018, 315, -1046, -96, -107, +-413, 974, -478, 1260, -110, 367, 370, -940, +572, -1421, 280, -580, -284, 872, -604, 1504, +-402, 720, 182, -785, 630, -1516, 526, -855, +-61, 650, -626, 1477, -615, 915, -8, -489, +605, -1343, 670, -955, 75, 299, -551, 1191, +-644, 906, -150, -133, 454, -947, 607, -804, +237, -33, -307, 695, -571, 694, -336, 143, +186, -414, 513, -508, 451, -280, -76, 117, +-502, 409, -472, 372, -22, 131, 450, -217, +484, -478, 80, -365, -351, 128, -478, 512, +-185, 528, 248, 51, 455, -476, 300, -643, +-192, -203, -454, 413, -340, 667, 96, 376, +429, -224, 373, -669, -31, -560, -401, 99, +-391, 602, -43, 675, 349, 149, 416, -551, +86, -806, -310, -301, -391, 454, -143, 847, +279, 492, 371, -332, 148, -899, -212, -655, +-364, 234, -145, 844, 177, 771, 314, -34, +165, -805, -127, -897, -261, -142, -168, 663, +36, 949, 256, 397, 189, -527, 8, -1035, +-207, -617, -222, 386, -13, 995, 186, 787, +217, -192, 58, -991, -143, -921, -211, 33, +-103, 849, 95, 984, 255, 196, 190, -745, +-71, -1051, -291, -424, -227, 578, 57, 1063, +333, 626, 287, -380, -31, -1053, -355, -831, +-360, 199, 12, 945, 404, 920, 444, 70, +46, -795, -457, -1002, -539, -325, -22, 581, +529, 989, 567, 573, 36, -303, -578, -925, +-587, -821, 5, 57, 555, 825, 551, 959, +53, 285, -474, -640, -557, -1120, -161, -588, +381, 481, 580, 1176, 279, 914, -282, -181, +-654, -1206, -417, -1213, 254, -44, 668, 1148, +475, 1418, -155, 414, -707, -1003, -553, -1607, +88, -689, 653, 828, 615, 1635, 6, 1046, +-581, -534, -671, -1672, -147, -1319, 513, 261, +685, 1572, 282, 1586, -385, 132, -745, -1475, +-433, -1810, 285, -443, 761, 1278, 564, 1895, +-162, 852, -765, -1022, -659, -2000, 29, -1125, +713, 722, 753, 1869, 115, 1428, -660, -353, +-807, -1760, -235, -1611, 584, -17, 871, 1477, +322, 1705, -500, 453, -849, -1171, -400, -1804, +392, -827, 794, 830, 445, 1707, -246, 1195, +-663, -412, -440, -1652, 59, -1473, 460, 34, +479, 1419, 152, 1614, -247, 400, -488, -1152, +-368, -1742, 78, -769, 519, 833, 528, 1639, +104, 1110, -463, -376, -653, -1540, -309, -1414, +369, -36, 760, 1281, 498, 1604, -214, 584, +-831, -992, -704, -1824, 108, -1029, 860, 683, +855, 1820, 37, 1484, -820, -252, -960, -1844, +-215, -1816, 746, -104, 993, 1646, 413, 2049, +-545, 616, -1030, -1436, -616, -2238, 321, -986, +1014, 1127, 856, 2250, -98, 1453, -1009, -742, +-1057, -2271, -118, -1735, 978, 378, 1198, 2036, +322, 1986, -875, 141, -1280, -1803, -530, -2113, +711, -544, 1298, 1379, 720, 2119, -508, 1072, +-1247, -978, -886, -2058, 242, -1377, 1136, 484, +1033, 1846, 33, 1707, -994, 56, -1137, -1599, +-334, -1905, 793, -568, 1235, 1206, 594, 2024, +-556, 1141, -1234, -823, -864, -2062, 271, -1586, +1226, 333, 1102, 1989, -4, 1989, -1153, 128, +-1303, -1843, -286, -2237, 1065, -600, 1471, 1575, +533, 2373, -914, 1050, -1548, -1247, -783, -2418, +720, -1454, 1592, 855, 979, 2354, -536, 1795, +-1542, -453, -1088, -2226, 346, -2026, 1438, 21, +1124, 1975, -138, 2125, -1214, 367, -1112, -1655, +-87, -2107, 901, -698, 1109, 1228, 383, 1903, +-603, 979, -1042, -781, -632, -1654, 293, -1133, +1008, 263, 835, 1296, -20, 1248, -923, 208, +-967, -921, -196, -1258, 755, -608, 1050, 503, +444, 1132, -576, 945, -1090, -63, -624, -916, +364, -1111, 1086, -410, 782, 559, -199, 1182, +-1003, 905, -859, -157, 21, -1153, 871, -1321, +912, -300, 175, 1061, -711, 1691, -968, 742, +-333, -935, 536, -1903, 953, -1117, 495, 694, +-375, 1993, -889, 1508, -602, -372, 183, -1941, +780, -1783, 648, -37, 3, 1719, -658, 2094, +-738, 528, -128, -1468, 542, -2232, 730, -1040, +280, 1086, -406, 2382, -748, 1508, -375, -728, +292, -2390, 670, -1885, 444, 363, -148, 2289, +-633, 2201, -517, 28, 81, -2115, 549, -2339, +522, -446, 12, 1785, -474, 2440, -535, 818, +-47, -1389, 414, -2369, 413, -1211, 92, 940, +-236, 2186, -337, 1517, -126, -472, 107, -1930, +194, -1739, 210, -1, 46, 1640, -157, 1862, +-323, 428, -136, -1286, 188, -1918, 363, -834, +211, 919, -197, 1864, -418, 1196, -187, -545, +220, -1767, 349, -1470, 184, 166, -166, 1569, +-305, 1625, -157, 180, 137, -1326, 277, -1665, +141, -496, -125, 1019, -221, 1593, -121, 778, +120, -697, 201, -1471, 38, -987, -109, 326, +-102, 1293, 14, 1224, 76, 10, 36, -1127, +-53, -1340, -49, -328, 21, 921, 102, 1401, +-9, 616, -99, -736, -92, -1338, 28, -734, +163, 445, 143, 1158, -68, 911, -256, -233, +-123, -944, 96, -874, 222, -54, 161, 665, +-72, 877, -284, 343, -155, -452, 117, -810, +268, -527, 199, 119, -120, 704, -338, 811, +-217, 102, 159, -601, 352, -884, 198, -380, +-128, 387, -366, 1013, -241, 656, 177, -301, +361, -981, 148, -808, -134, 81, -306, 942, +-140, 971, 108, 41, 227, -856, 147, -1015, +-43, -203, -139, 660, -196, 1058, -60, 454, +156, -522, 189, -1038, 64, -635, -97, 241, +-172, 966, -110, 904, 49, -11, 171, -908, +166, -1095, 22, -206, -202, 802, -238, 1219, +-56, 467, 211, -738, 270, -1327, 64, -593, +-204, 617, -228, 1264, -64, 824, 138, -490, +243, -1283, 70, -916, -124, 343, -201, 1151, +-78, 1020, 46, -125, 189, -1108, 165, -1049, +1, 13, -177, 924, -209, 998, -46, 205, +172, -853, 297, -965, 62, -239, -220, 683, +-279, 843, -53, 363, 193, -537, 323, -828, +79, -312, -263, 412, -298, 639, -50, 356, +240, -211, 266, -573, 46, -289, -251, 127, +-220, 325, 36, 223, 202, 82, 134, -191, +-18, -209, -139, -89, -120, 33, 23, 98, +56, 204, 46, 83, 49, -92, 16, -173, +-24, -159, -78, -22, -92, 175, 12, 300, +101, 77, 114, -186, -5, -310, -135, -158, +-135, 96, -9, 385, 126, 251, 161, -81, +45, -331, -160, -278, -188, -31, -80, 270, +152, 365, 216, 81, 47, -245, -123, -363, +-184, -136, -98, 171, 91, 455, 180, 191, +110, -281, -36, -462, -184, -132, -144, 281, +-12, 437, 162, 142, 149, -354, 30, -408, +-107, 6, -117, 324, -64, 222, 32, 14, +103, -287, 81, -221, 44, 83, -66, 279, +-131, 68, -129, -69, 53, -140, 218, -163, +186, 6, -81, 219, -237, 173, -202, -48, +21, -86, 243, -251, 192, -94, 5, 218, +-134, 319, -174, -27, -134, -172, 58, -248, +222, -106, 209, 220, -15, 335, -205, 52, +-272, -270, -90, -204, 219, -136, 328, 173, +136, 294, -133, 164, -319, -211, -296, -200, +87, -147, 382, 46, 331, 214, -12, 177, +-352, -12, -424, -166, -97, -99, 370, -111, +489, 65, 165, 151, -288, 195, -520, -27, +-338, -140, 203, -256, 603, -69, 413, 177, +-144, 294, -559, 111, -523, -177, 37, -239, +566, -158, 567, 95, 23, 185, -523, 216, +-582, -21, -196, -109, 445, -200, 691, -132, +267, 28, -389, 251, -691, 209, -407, 16, +290, -216, 758, -310, 441, -67, -315, 208, +-724, 369, -397, 93, 235, -162, 614, -360, +381, -214, -172, 106, -487, 390, -338, 259, +15, -50, 318, -331, 383, -331, 66, 4, +-307, 274, -363, 328, -44, 46, 249, -192, +263, -287, 10, -125, -187, 64, -117, 271, +14, 214, 6, 17, -43, -228, 60, -305, +162, -118, 62, 220, -137, 379, -185, 154, +-72, -191, 99, -378, 187, -183, 54, 91, +-54, 368, -106, 221, -90, -60, -63, -245, +89, -237, 203, -67, 42, 232, -138, 239, +-181, 62, -42, -105, 142, -199, 155, -103, +-75, -5, -118, 156, 50, 107, 115, 157, +-71, -19, -179, -222, -39, -317, 186, -12, +222, 308, -25, 383, -306, 92, -183, -389, +117, -439, 188, -40, 143, 406, -17, 327, +-92, 82, -196, -316, -170, -294, 13, -60, +262, 179, 366, 191, 12, 127, -461, 1, +-444, -162, 27, -228, 511, -98, 490, 171, +-147, 263, -550, 207, -453, -160, 128, -329, +528, -218, 357, 149, -92, 298, -448, 209, +-360, -78, 27, -258, 353, -234, 320, 22, +-4, 224, -326, 195, -248, 77, -40, -173, +195, -257, 193, -139, 24, 185, -55, 241, +-148, 165, -119, -149, -67, -246, 100, -170, +194, 81, 46, 240, -112, 131, -188, 23, +-92, -157, 132, -223, 127, -104, 1, 197, +-48, 221, -91, 156, -63, -217, -37, -292, +57, -103, 131, 240, 23, 330, -58, -38, +-146, -269, -50, -207, 143, 87, 0, 228, +-72, 147, -16, -208, 63, -138, 72, 38, +-115, 210, -186, 23, 40, -166, 227, -153, +116, 29, -186, 289, -273, 172, 34, -188, +204, -384, 151, -43, -107, 261, -199, 438, +-35, 6, 117, -443, 53, -438, -29, 142, +-27, 562, -28, 364, -6, -242, -76, -617, +5, -299, 71, 308, 93, 696, -76, 211, +-174, -401, -16, -642, 139, -192, 123, 458, +-95, 664, -223, 102, -62, -524, 161, -602, +144, -30, -13, 611, -166, 523, -118, -84, +9, -640, 100, -455, 74, 186, -18, 653, +-85, 368, -136, -250, -48, -640, 148, -357, +113, 310, -35, 656, -162, 377, -196, -316, +66, -783, 212, -448, 96, 446, -173, 897, +-251, 483, -34, -573, 210, -1085, 194, -426, +-33, 725, -324, 1179, -212, 354, 155, -908, +270, -1169, 159, -259, -196, 958, -384, 1188, +-172, 110, 261, -1023, 419, -1082, 126, -3, +-357, 1003, -487, 963, -132, -85, 386, -980, +496, -854, 17, 227, -436, 935, -480, 649, +-20, -262, 425, -922, 462, -533, -25, 436, +-517, 909, -454, 301, 54, -610, 520, -866, +377, -36, -191, 852, -566, 838, -281, -310, +329, -1208, 510, -646, 27, 770, -473, 1427, +-425, 445, 138, -1206, 550, -1672, 273, -119, +-365, 1673, -620, 1728, -156, -221, 496, -2008, +617, -1725, 22, 520, -645, 2348, -684, 1670, +51, -896, 729, -2540, 616, -1501, -144, 1154, +-756, 2682, -631, 1320, 117, -1429, 727, -2678, +563, -1046, -102, 1568, -683, 2563, -664, 856, +-39, -1659, 624, -2394, 711, -660, 115, 1668, +-671, 2211, -800, 511, -202, -1633, 609, -2032, +821, -435, 145, 1610, -638, 1878, -776, 308, +-163, -1525, 526, -1716, 645, -255, 127, 1401, +-445, 1595, -581, 195, -156, -1267, 269, -1441, +387, -234, 186, 1066, -170, 1376, -300, 283, +-224, -942, -38, -1263, 108, -411, 241, 802, +233, 1205, -75, 493, -426, -648, -417, -1138, +22, -622, 535, 469, 467, 1088, -188, 779, +-650, -312, -410, -1083, 289, -944, 549, 104, +209, 1170, -353, 1080, -496, -38, -94, -1124, +284, -1219, 315, -114, -13, 1212, -260, 1273, +-240, 152, -6, -1112, 145, -1361, 166, -283, +-5, 1106, -192, 1408, -209, 351, -47, -1033, +156, -1407, 265, -475, 76, 967, -368, 1488, +-406, 482, -45, -901, 421, -1418, 465, -588, +-52, 893, -617, 1459, -583, 539, 125, -872, +724, -1448, 499, -531, -250, 1011, -759, 1458, +-593, 347, 270, -1114, 753, -1393, 439, -134, +-279, 1254, -707, 1290, -488, -149, 131, -1326, +653, -1024, 497, 278, -158, 1315, -649, 925, +-533, -473, -1, -1291, 615, -742, 540, 458, +-113, 1298, -591, 785, -477, -583, 64, -1379, +414, -741, 336, 623, -122, 1468, -328, 838, +-191, -775, -21, -1596, 52, -806, 64, 839, +117, 1644, 112, 858, -99, -891, -346, -1735, +-286, -825, 63, 861, 468, 1659, 320, 928, +-216, -751, -600, -1684, -374, -930, 255, 560, +551, 1497, 322, 1092, -304, -288, -654, -1422, +-351, -1197, 317, -11, 547, 1163, 294, 1430, +-302, 404, -700, -1081, -305, -1631, 359, -717, +603, 873, 217, 1841, -431, 1096, -671, -787, +-224, -2027, 449, -1312, 556, 620, 68, 2093, +-434, 1647, -527, -506, -180, -2181, 345, -1733, +466, 277, 169, 2093, -305, 1973, -590, -103, +-374, -2003, 254, -2045, 743, -165, 422, 1799, +-393, 2188, -971, 485, -582, -1703, 529, -2265, +1138, -723, 505, 1452, -772, 2381, -1347, 1026, +-495, -1379, 928, -2367, 1357, -1146, 340, 1140, +-1119, 2334, -1422, 1320, -250, -1013, 1100, -2248, +1307, -1325, 114, 765, -1152, 2140, -1199, 1448, +-186, -643, 962, -2088, 1119, -1416, 123, 566, +-816, 1918, -1050, 1429, -454, -543, 607, -1867, +1048, -1139, 531, 568, -493, 1540, -1170, 947, +-796, -564, 352, -1300, 1277, -574, 822, 527, +-511, 855, -1299, 334, -882, -350, 400, -563, +1251, -137, 760, 243, -487, 145, -1091, 64, +-720, 49, 206, 9, 879, -75, 666, -204, +-165, -213, -717, 139, -660, 444, -99, 213, +488, -314, 552, -484, 138, -178, -301, 387, +-484, 585, -359, 29, -78, -504, 289, -476, +494, 78, 321, 516, -194, 396, -766, -183, +-741, -511, 77, -298, 888, 250, 970, 462, +12, 196, -1188, -246, -1266, -445, -180, -105, +1252, 238, 1479, 349, 211, 85, -1400, -200, +-1785, -239, -385, -61, 1442, 129, 1841, 93, +437, 82, -1505, 24, -2061, -29, -596, -89, +1469, -115, 2047, -79, 612, 95, -1443, 239, +-2170, 142, -805, -106, 1390, -228, 2075, -226, +729, -55, -1269, 298, -2075, 419, -881, 133, +1119, -318, 1880, -589, 793, -359, -925, 421, +-1791, 924, -949, 425, 678, -639, 1583, -1083, +936, -484, -547, 763, -1482, 1349, -1027, 442, +263, -1012, 1241, -1400, 1019, -316, -146, 1071, +-1106, 1433, -1160, 313, -171, -1196, 938, -1444, +1195, -182, 335, 1105, -981, 1339, -1407, 311, +-427, -1036, 894, -1298, 1368, -339, 395, 821, +-1039, 1160, -1339, 519, -410, -533, 895, -1106, +1210, -675, 283, 252, -831, 923, -1189, 936, +-463, 97, 717, -871, 1134, -1133, 395, -452, +-727, 738, -1182, 1430, -524, 803, 654, -713, +1176, -1647, 410, -1119, -760, 563, -1149, 1927, +-489, 1459, 553, -553, 1149, -2069, 551, -1696, +-698, 344, -1213, 2220, -657, 1976, 499, -248, +1313, -2271, 755, -2112, -733, 13, -1502, 2214, +-750, 2344, 659, 204, 1455, -2153, 755, -2433, +-788, -459, -1563, 1903, -767, 2622, 701, 782, +1409, -1770, 740, -2659, -683, -1057, -1479, 1483, +-852, 2697, 586, 1366, 1379, -1259, 772, -2633, +-606, -1525, -1398, 935, -824, 2424, 504, 1731, +1247, -538, 684, -2236, -575, -1830, -1141, 106, +-597, 1883, 373, 2049, 926, 308, 458, -1661, +-444, -2099, -751, -718, -345, 1354, 259, 2213, +347, 971, 221, -1071, -171, -2111, -242, -1197, +-82, 706, -122, 1969, -165, 1388, 46, -384, +329, -1693, 179, -1524, -156, -63, -473, 1468, +-430, 1681, 123, 312, 647, -1210, 259, -1669, +-246, -618, -599, 998, -461, 1648, 161, 715, +572, -756, 405, -1436, -278, -813, -609, 465, +-436, 1227, 126, 857, 582, -192, 387, -951, +-363, -849, -596, -135, -213, 650, 214, 868, +400, 382, 39, -361, -292, -786, -250, -649, +48, 62, 31, 744, -82, 810, -60, 200, +79, -616, 108, -933, -96, -404, -276, 497, +-228, 948, 134, 543, 273, -326, 110, -913, +-231, -683, -348, 225, -164, 795, 132, 747, +255, 9, 151, -741, -163, -850, -415, -80, +-258, 648, 144, 790, 339, 303, 233, -556, +-203, -853, -542, -264, -298, 412, 208, 694, +439, 439, 198, -236, -226, -685, -519, -491, +-335, 106, 180, 546, 483, 641, 203, 103, +-218, -593, -480, -775, -372, -135, 138, 572, +434, 859, 189, 255, -141, -671, -285, -890, +-372, -233, -89, 656, 177, 867, 318, 230, +192, -636, -115, -789, -520, -241, -522, 545, +131, 774, 564, 233, 491, -490, -140, -719, +-734, -292, -646, 401, 143, 783, 676, 343, +517, -461, -143, -763, -702, -372, -605, 366, +55, 845, 574, 481, 439, -429, -18, -851, +-499, -528, -502, 272, -139, 931, 261, 752, +365, -256, 251, -1053, -114, -919, -474, 167, +-505, 1190, -132, 1204, 443, -159, 649, -1480, +179, -1294, -631, 200, -873, 1620, -301, 1442, +621, -255, 932, -1771, 256, -1455, -786, 289, +-1052, 1784, -319, 1480, 695, -207, 1027, -1774, +277, -1531, -792, 171, -1095, 1672, -382, 1564, +644, -11, 1065, -1563, 393, -1620, -693, -74, +-1223, 1410, -530, 1566, 675, 285, 1214, -1210, +488, -1595, -822, -476, -1340, 983, -493, 1553, +898, 790, 1218, -683, 249, -1703, -957, -1139, +-1169, 536, -207, 1776, 873, 1488, 880, -264, +22, -2008, -717, -1865, -773, 237, -156, 2122, +475, 2084, 565, -30, 174, -2305, -315, -2353, +-591, 36, -393, 2405, 111, 2390, 513, 93, +426, -2432, -36, -2520, -575, -70, -672, 2429, +-75, 2418, 515, 121, 648, -2258, 158, -2429, +-601, -136, -813, 2137, -235, 2212, 486, 191, +717, -1854, 296, -2135, -448, -214, -834, 1683, +-471, 1860, 282, 311, 761, -1448, 561, -1720, +-194, -353, -920, 1241, -768, 1521, 109, 431, +808, -982, 798, -1416, -80, -525, -884, 838, +-872, 1258, -82, 584, 685, -605, 820, -1218, +212, -651, -631, 546, -926, 1110, -445, 628, +382, -405, 936, -1072, 593, -649, -422, 452, +-985, 1005, -750, 566, 179, -427, 910, -965, +770, -514, -115, 481, -836, 972, -916, 388, +-245, -554, 659, -868, 1039, -323, 442, 556, +-702, 879, -1210, 226, -771, -606, 576, -765, +1415, -219, 771, 537, -630, 774, -1501, 250, +-957, -535, 503, -754, 1451, -272, 956, 440, +-501, 823, -1432, 396, -1050, -483, 221, -888, +1342, -427, 1066, 417, -207, 996, -1274, 550, +-1186, -480, 13, -1065, 1109, -542, 1115, 413, +-11, 1098, -994, 670, -1077, -466, -213, -1077, +754, -640, 898, 338, 242, 976, -496, 750, +-848, -262, -521, -922, 266, -724, 645, 95, +565, 735, -23, 842, -638, 63, -775, -719, +-206, -779, 490, -165, 734, 542, 344, 749, +-404, 284, -891, -452, -558, -634, 296, -255, +779, 202, 627, 422, -197, 363, -875, 3, +-747, -290, 69, -347, 735, -230, 678, 58, +31, 404, -652, 459, -756, 20, -236, -378, +450, -563, 671, -256, 358, 347, -308, 741, +-792, 418, -578, -285, 128, -802, 721, -688, +655, 169, -26, 981, -792, 919, -824, -104, +-145, -1039, 666, -1163, 860, -47, 241, 1191, +-634, 1323, -1010, 146, -438, -1193, 474, -1508, +993, -292, 592, 1241, -416, 1579, -1110, 409, +-810, -1168, 223, -1617, 1109, -594, 943, 1095, +-165, 1646, -1252, 676, -1145, -870, 63, -1597, +1203, -899, 1223, 704, -85, 1583, -1311, 975, +-1267, -435, -13, -1452, 1198, -1167, 1201, 207, +-5, 1382, -1185, 1217, -1164, 33, -103, -1153, +954, -1342, 1089, -330, 121, 1026, -918, 1412, +-1027, 523, -224, -782, 687, -1472, 895, -816, +238, 692, -644, 1507, -800, 893, -272, -490, +351, -1455, 607, -1057, 336, 380, -259, 1367, +-563, 1047, -394, -155, -37, -1164, 419, -1144, +505, -54, 48, 1011, -476, 1134, -543, 292, +-124, -778, 345, -1211, 508, -547, 99, 650, +-432, 1183, -403, 723, -105, -385, 178, -1209, +319, -959, 93, 247, -196, 1196, -248, 1069, +-126, 20, 3, -1180, 140, -1292, 121, -139, +-65, 1171, -127, 1394, -54, 296, -43, -1109, +-52, -1561, -1, -451, 21, 1158, 114, 1625, +70, 491, -194, -1076, -286, -1732, -73, -587, +249, 1178, 272, 1735, -49, 556, -337, -1173, +-315, -1704, 95, -566, 335, 1223, 124, 1683, +-166, 462, -332, -1195, -121, -1556, 182, -466, +229, 1157, -30, 1544, -227, 375, -185, -1114, +19, -1440, 219, -376, 101, 1087, -216, 1452, +-243, 272, -9, -1131, 191, -1350, 233, -207, +-99, 1151, -407, 1336, -210, 58, 245, -1191, +322, -1174, 60, 18, -326, 1148, -416, 1097, +19, -107, 468, -1116, 209, -876, -279, 145, +-394, 884, -171, 756, 296, -152, 429, -760, +-32, -448, -471, 170, -353, 407, 82, 256, +373, -150, 316, -243, -80, 73, -512, 251, +-341, -102, 105, -329, 355, -230, 330, 183, +-46, 609, -413, 405, -384, -390, -30, -849, +289, -445, 341, 389, 130, 998, -220, 666, +-458, -438, -278, -1223, 147, -745, 440, 397, +372, 1304, -121, 973, -572, -378, -496, -1466, +106, -1100, 543, 355, 476, 1557, -93, 1290, +-582, -319, -514, -1718, -1, -1426, 468, 282, +508, 1819, 96, 1617, -453, -221, -611, -1907, +-235, -1779, 356, 70, 648, 1949, 353, 2013, +-435, 104, -742, -1933, -367, -2198, 297, -350, +697, 1861, 422, 2398, -284, 603, -688, -1792, +-437, -2481, 107, -822, 524, 1586, 528, 2565, +-22, 1028, -573, -1433, -486, -2482, -97, -1173, +336, 1135, 539, 2360, 168, 1385, -322, -901, +-481, -2196, -295, -1472, 83, 514, 460, 2029, +436, 1712, -82, -232, -524, -1906, -449, -1814, +-62, -107, 481, 1726, 538, 2033, -75, 379, +-492, -1688, -414, -2070, -3, -589, 362, 1447, +334, 2231, -79, 784, -282, -1402, -150, -2179, +-1, -924, 43, 1122, 72, 2203, -5, 1137, +37, -1009, 76, -2139, -123, -1230, -256, 732, +-79, 2033, 163, 1437, 261, -559, 144, -1937, +-260, -1455, -440, 289, -85, 1687, 288, 1574, +371, -65, 160, -1506, -327, -1525, -530, -197, +-169, 1210, 329, 1529, 499, 449, 259, -1010, +-334, -1486, -707, -607, -320, 798, 423, 1419, +676, 742, 313, -675, -390, -1382, -794, -730, +-322, 564, 461, 1247, 662, 719, 235, -488, +-344, -1126, -650, -637, -324, 398, 326, 973, +554, 602, 275, -274, -230, -827, -565, -571, +-401, 117, 213, 663, 577, 653, 352, 27, +-170, -576, -517, -687, -468, -225, 64, 475, +519, 830, 430, 351, 30, -495, -404, -822, +-546, -436, -218, 397, 342, 948, 550, 492, +322, -516, -193, -896, -643, -457, -527, 420, +160, 996, 658, 533, 562, -570, -77, -1020, +-783, -479, -682, 507, 183, 1109, 782, 651, +571, -615, -209, -1212, -816, -604, -575, 501, +299, 1222, 744, 791, 398, -469, -226, -1227, +-652, -772, -502, 247, 189, 1075, 601, 926, +435, -76, -41, -957, -537, -921, -631, -142, +-50, 716, 611, 976, 594, 320, 65, -575, +-523, -872, -717, -472, -154, 343, 591, 820, +647, 546, 149, -199, -472, -671, -745, -592, +-268, -24, 557, 573, 712, 634, 202, 166, +-492, -429, -726, -699, -236, -354, 511, 357, +621, 744, 134, 510, -373, -259, -522, -819, +-212, -658, 250, 202, 405, 867, 211, 787, +-92, -95, -365, -913, -324, -855, 17, 12, +297, 868, 288, 892, 101, 132, -252, -780, +-356, -934, -126, -251, 137, 629, 313, 941, +278, 415, -86, -488, -424, -954, -335, -537, +48, 348, 406, 948, 441, 655, -33, -256, +-495, -933, -423, -744, 18, 180, 388, 945, +436, 773, 85, -171, -347, -888, -477, -774, +-210, 148, 224, 898, 496, 736, 360, -214, +-156, -827, -598, -628, -425, 182, 111, 840, +498, 599, 440, -285, -63, -765, -429, -483, +-388, 192, -42, 773, 269, 533, 311, -215, +156, -767, -122, -558, -336, 115, -217, 740, +57, 736, 258, -48, 249, -808, -1, -794, +-285, -65, -251, 786, 13, 946, 213, 145, +218, -824, 1, -962, -228, -184, -208, 768, +12, 956, 186, 182, 161, -710, -3, -859, +-145, -184, -129, 599, -15, 727, 51, 183, +52, -432, 31, -606, 60, -259, 25, 277, +-109, 530, -157, 333, -70, -106, 94, -502, +225, -488, 127, -17, -139, 536, -203, 602, +-107, 91, 20, -544, 132, -729, 148, -177, +78, 582, -51, 770, -166, 234, -235, -550, +-35, -818, 291, -290, 330, 525, -24, 796, +-344, 310, -408, -449, -1, -748, 485, -287, +449, 409, -106, 639, -575, 257, -489, -314, +99, -562, 698, -230, 604, 269, -180, 470, +-822, 226, -640, -197, 137, -444, 898, -274, +789, 188, -180, 442, -970, 286, -812, -131, +125, -471, 985, -360, 900, 146, -154, 479, +-1032, 361, -844, -79, 132, -448, 963, -414, +841, 50, -127, 402, -920, 373, -750, 51, +44, -327, 781, -412, 787, -90, 24, 270, +-728, 347, -740, 175, -152, -156, 613, -397, +828, -242, 184, 137, -603, 337, -749, 336, +-244, -17, 484, -432, 751, -421, 234, 37, +-421, 394, -614, 461, -284, 105, 237, -454, +570, -553, 380, -95, -178, 410, -519, 534, +-420, 254, -14, -374, 523, -662, 568, -238, +33, 325, -513, 584, -573, 355, -178, -252, +437, -613, 686, -329, 234, 202, -440, 483, +-668, 339, -327, -36, 318, -378, 715, -372, +369, -58, -313, 203, -615, 371, -372, 278, +140, -84, 555, -452, 446, -400, -85, -12, +-494, 469, -465, 529, -30, 91, 500, -505, +555, -639, -12, -117, -558, 518, -531, 656, +33, 174, 612, -492, 552, -718, -127, -185, +-658, 472, -490, 664, 103, 247, 671, -371, +552, -650, -157, -309, -703, 304, -539, 596, +123, 352, 700, -171, 614, -569, -153, -428, +-740, 90, -524, 524, 128, 464, 616, 17, +561, -456, -126, -505, -618, -93, -451, 377, +61, 513, 491, 203, 508, -262, -20, -504, +-541, -331, -509, 123, 51, 491, 571, 441, +525, -1, -64, -462, -668, -536, -545, -121, +162, 450, 654, 594, 513, 185, -123, -389, +-653, -626, -524, -273, 88, 368, 588, 624, +551, 270, 21, -336, -542, -572, -600, -322, +-85, 307, 500, 588, 593, 262, 129, -268, +-461, -522, -590, -321, -126, 252, 409, 583, +517, 288, 135, -262, -365, -567, -485, -336, +-106, 269, 319, 679, 379, 322, 102, -370, +-221, -690, -351, -316, -121, 397, 180, 806, +234, 310, 158, -553, -48, -813, -244, -278, +-210, 575, 18, 929, 170, 305, 202, -693, +76, -991, -135, -323, -219, 689, -85, 1111, +98, 405, 125, -732, 128, -1192, 22, -501, +-177, 693, -158, 1287, -10, 650, 102, -650, +202, -1383, 111, -809, -196, 561, -263, 1477, +-60, 1010, 205, -516, 286, -1538, 70, -1121, +-294, 375, -324, 1604, 21, 1257, 312, -344, +290, -1569, -31, -1311, -343, 213, -291, 1548, +83, 1388, 304, -169, 282, -1498, -47, -1384, +-342, 64, -276, 1416, 51, 1422, 303, 6, +328, -1386, 10, -1366, -391, -83, -374, 1216, +38, 1367, 385, 196, 391, -1107, 11, -1287, +-448, -347, -427, 889, 59, 1267, 410, 528, +354, -706, 34, -1260, -389, -666, -433, 521, +-7, 1221, 358, 808, 380, -372, 106, -1202, +-330, -874, -450, 243, -109, 1120, 320, 921, +395, -160, 143, -1039, -222, -898, -404, 104, +-232, 935, 188, 815, 394, -89, 259, -842, +-87, -702, -393, 117, -324, 731, 63, 578, +357, -147, 259, -659, -18, -461, -216, 182, +-219, 564, -45, 375, 99, -171, 114, -545, +129, -347, 80, 179, -68, 486, -232, 326, +-187, -116, 54, -474, 261, -342, 285, 68, +6, 402, -363, 360, -348, 45, 1, -334, +379, -445, 443, -152, 46, 284, -512, 490, +-525, 276, 24, -262, 584, -597, 593, -322, +-53, 248, -723, 630, -631, 379, 179, -273, +792, -687, 609, -361, -241, 258, -846, 655, +-570, 401, 319, -276, 864, -645, 502, -395, +-340, 229, -834, 580, -495, 430, 375, -165, +808, -577, 436, -426, -288, 86, -781, 453, +-481, 457, 284, 50, 743, -419, 521, -474, +-188, -163, -762, 260, -633, 535, 192, 328, +818, -221, 646, -570, -137, -451, -856, 111, +-732, 630, 191, 560, 877, -79, 669, -673, +-107, -648, -788, 13, -725, 709, 56, 701, +733, -27, 681, -734, 82, -724, -570, 1, +-739, 748, -204, 746, 498, -58, 688, -744, +308, -713, -294, -7, -677, 736, -420, 741, +216, -34, 594, -699, 455, -714, -51, -75, +-504, 654, -485, 756, -11, 100, 422, -640, +445, -757, 81, -182, -282, 555, -395, 810, +-171, 244, 197, -537, 352, -771, 231, -337, +-50, 419, -342, 772, -358, 405, -10, -330, +388, -722, 448, -498, 84, 196, -406, 663, +-553, 533, -114, -96, 494, -603, 597, -575, +150, -12, -444, 514, -646, 560, -202, 72, +451, -422, 652, -546, 244, -173, -367, 364, +-624, 495, -282, 209, 312, -246, 573, -505, +278, -335, -173, 175, -448, 510, -304, 408, +102, -75, 342, -558, 258, -564, 31, 9, +-191, 596, -227, 644, -52, 45, 101, -638, +131, -774, 124, -127, 57, 668, -73, 808, +-118, 157, -110, -636, -35, -854, 174, -244, +239, 592, 23, 828, -179, 273, -208, -502, +-61, -821, 206, -344, 270, 440, 30, 745, +-191, 341, -211, -351, -70, -693, 173, -381, +313, 259, 106, 601, -151, 353, -294, -192, +-191, -503, 149, -414, 422, 73, 264, 455, +-167, 389, -422, 6, -284, -353, 164, -485, +491, -151, 320, 301, -152, 485, -424, 259, +-286, -196, 116, -555, 399, -453, 312, 105, +-72, 590, -312, 569, -246, 31, 13, -620, +268, -809, 258, -158, 44, 672, -137, 890, +-190, 309, -110, -682, 59, -1107, 226, -439, +211, 682, 40, 1172, -178, 568, -249, -627, +-104, -1305, 194, -724, 319, 554, 174, 1306, +-77, 835, -286, -415, -266, -1328, 1, -1003, +339, 266, 396, 1259, 112, 1100, -292, -68, +-496, -1244, -172, -1266, 411, -78, 600, 1140, +204, 1309, -387, 232, -594, -1103, -203, -1377, +460, -336, 659, 981, 147, 1334, -413, 435, +-538, -866, -156, -1323, 442, -548, 574, 679, +128, 1202, -366, 648, -434, -471, -114, -1169, +333, -794, 470, 239, 134, 1015, -257, 909, +-326, -7, -104, -950, 184, -1052, 335, -251, +178, 789, -107, 1157, -221, 488, -143, -686, +38, -1316, 223, -731, 238, 554, 52, 1370, +-125, 909, -194, -473, -134, -1465, 118, -1043, +315, 374, 227, 1426, -31, 1105, -304, -326, +-287, -1437, 104, -1131, 439, 238, 337, 1319, +-78, 1099, -434, -203, -331, -1246, 231, -1076, +555, 101, 295, 1085, -244, 1009, -520, -19, +-220, -988, 392, -988, 611, -106, 176, 806, +-391, 932, -517, 207, -125, -722, 452, -941, +626, -298, 163, 565, -408, 886, -543, 355, +-169, -540, 415, -876, 671, -378, 281, 422, +-341, 782, -587, 361, -289, -406, 297, -744, +665, -350, 449, 331, -177, 624, -590, 308, +-453, -310, 119, -613, 659, -292, 612, 264, +2, 499, -586, 248, -569, -255, -7, -487, +573, -225, 649, 205, 168, 376, -424, 175, +-577, -183, -211, -333, 355, -195, 669, 84, +438, 221, -162, 140, -625, -12, -493, -185, +148, -212, 678, -91, 669, 86, 69, 199, +-604, 150, -641, -81, -99, -263, 527, -220, +771, 8, 377, 235, -354, 232, -733, -15, +-453, -266, 261, -270, 840, -31, 698, 211, +-110, 252, -769, 44, -676, -228, 75, -279, +783, -97, 767, 150, 88, 287, -595, 125, +-660, -191, -102, -335, 533, -199, 708, 122, +289, 361, -343, 232, -615, -148, -277, -403, +344, -321, 667, 51, 402, 393, -173, 364, +-531, -37, -345, -426, 198, -472, 569, -119, +448, 371, 15, 536, -380, 183, -450, -359, +-44, -636, 450, -389, 555, 278, 254, 714, +-251, 462, -565, -222, -268, -784, 360, -684, +648, 102, 374, 833, -166, 749, -537, -44, +-316, -849, 258, -915, 537, -88, 343, 832, +-44, 923, -310, 128, -235, -788, 97, -1022, +313, -287, 268, 723, 87, 994, -94, 321, +-167, -643, -30, -1065, 170, -476, 252, 575, +153, 1018, -57, 504, -160, -503, -29, -1077, +199, -627, 266, 453, 81, 1034, -130, 589, +-122, -417, 71, -1055, 232, -646, 187, 413, +10, 992, -106, 527, -55, -409, 99, -950, +173, -546, 156, 411, 52, 856, -57, 380, +-68, -420, 60, -788, 215, -408, 200, 388, +19, 717, -143, 269, -85, -423, 184, -686, +331, -296, 137, 397, -161, 662, -220, 185, +47, -493, 364, -658, 344, -182, -4, 464, +-287, 645, -219, 97, 161, -551, 432, -618, +315, -124, -30, 464, -296, 590, -228, 90, +162, -477, 435, -578, 315, -179, -11, 350, +-276, 534, -223, 217, 152, -321, 416, -566, +308, -334, -14, 169, -264, 537, -188, 408, +167, -150, 430, -588, 283, -520, -95, -13, +-276, 560, -116, 619, 239, 37, 439, -605, +203, -731, -176, -210, -239, 548, -36, 812, +261, 281, 403, -561, 178, -913, -147, -463, +-240, 408, -58, 958, 247, 595, 440, -379, +252, -1012, -173, -771, -332, 154, -97, 998, +293, 892, 523, -79, 278, -976, -217, -1022, +-396, -155, -124, 880, 317, 1083, 567, 233, +350, -839, -191, -1139, -461, -418, -190, 674, +302, 1129, 616, 457, 412, -642, -179, -1111, +-474, -581, -211, 473, 278, 1075, 560, 582, +371, -471, -74, -1048, -338, -686, -190, 328, +143, 1031, 358, 686, 391, -360, 146, -1064, +-163, -771, -246, 258, -84, 1044, 232, 764, +469, -318, 333, -1073, -83, -771, -331, 226, +-206, 986, 175, 731, 528, -295, 428, -968, +-42, -684, -354, 201, -258, 837, 144, 598, +489, -248, 424, -809, 31, -552, -248, 187, +-216, 687, 19, 466, 308, -243, 395, -714, +228, -459, -20, 211, -218, 637, -210, 408, +92, -276, 419, -711, 464, -446, 160, 227, +-260, 657, -374, 453, -66, -243, 430, -733, +594, -538, 256, 128, -224, 663, -437, 587, +-160, -70, 382, -695, 607, -699, 319, -93, +-155, 588, -401, 731, -189, 184, 297, -592, +549, -840, 344, -322, -52, 452, -322, 810, +-227, 399, 170, -432, 491, -872, 439, -493, +39, 280, -307, 781, -286, 531, 87, -238, +489, -798, 476, -622, 73, 105, -256, 688, +-253, 623, 19, -40, 366, -701, 439, -714, +191, -63, -108, 580, -245, 677, -109, 127, +233, -576, 465, -730, 310, -215, -63, 417, +-261, 627, -124, 252, 215, -342, 432, -609, +280, -337, -60, 145, -190, 425, -76, 345, +188, -7, 382, -358, 260, -408, -31, -206, +-194, 121, -92, 394, 220, 342, 407, -29, +244, -416, -82, -515, -230, -190, -42, 354, +279, 583, 398, 251, 176, -351, -92, -683, +-159, -414, 6, 257, 238, 671, 317, 393, +183, -266, -39, -667, -111, -475, -3, 168, +164, 615, 288, 416, 211, -174, -11, -592, +-86, -501, 2, 58, 144, 547, 275, 474, +219, -72, 15, -572, -89, -577, -30, -43, +127, 545, 273, 592, 261, 24, 73, -593, +-99, -672, -92, -133, 53, 543, 227, 664, +320, 112, 231, -536, -6, -685, -196, -234, +-147, 408, 121, 622, 430, 244, 462, -349, +109, -625, -308, -376, -320, 177, 47, 548, +438, 403, 563, -130, 244, -571, -230, -527, +-381, -11, -145, 521, 290, 551, 624, 21, +483, -576, -80, -666, -507, -123, -358, 548, +229, 691, 731, 130, 611, -627, -70, -810, +-585, -227, -390, 588, 255, 849, 711, 255, +576, -665, -21, -976, -490, -356, -371, 597, +154, 978, 583, 389, 566, -619, 118, -1057, +-345, -475, -381, 503, 10, 960, 454, 488, +559, -473, 243, -987, -176, -542, -358, 356, +-132, 838, 263, 525, 494, -316, 386, -854, +18, -547, -259, 242, -252, 717, 43, 475, +399, -247, 470, -744, 229, -491, -117, 217, +-322, 642, -183, 412, 242, -241, 542, -680, +424, -455, 22, 199, -351, 608, -340, 407, +106, -199, 531, -666, 537, -497, 137, 155, +-292, 616, -385, 473, -57, -161, 448, -702, +619, -557, 276, 135, -226, 651, -457, 509, +-192, -163, 407, -694, 681, -539, 337, 128, +-209, 600, -447, 448, -193, -120, 343, -577, +619, -516, 351, 13, -117, 462, -334, 454, +-201, 79, 170, -412, 493, -599, 422, -263, +54, 303, -246, 609, -261, 404, 9, -246, +389, -763, 475, -628, 180, 118, -147, 793, +-263, 747, -90, -44, 250, -898, 446, -967, +300, -101, -5, 881, -225, 1028, -197, 190, +94, -905, 386, -1180, 394, -348, 132, 804, +-139, 1177, -226, 436, -57, -750, 237, -1256, +392, -610, 311, 593, 52, 1224, -237, 686, +-269, -509, 52, -1274, 434, -861, 522, 370, +180, 1233, -305, 898, -428, -312, -38, -1268, +488, -1021, 615, 221, 234, 1207, -305, 990, +-479, -202, -106, -1210, 446, -1049, 659, 122, +335, 1112, -247, 981, -552, -107, -256, -1064, +409, -1014, 787, -12, 481, 936, -226, 927, +-701, 47, -400, -854, 420, -956, 916, -174, +576, 728, -252, 868, -763, 193, -471, -665, +411, -884, 951, -276, 608, 549, -202, 771, +-752, 240, -518, -491, 324, -722, 918, -279, +667, 356, -117, 564, -701, 209, -551, -286, +198, -474, 851, -246, 718, 140, -20, 325, +-607, 183, -571, -83, 55, -265, 731, -230, +756, -24, 129, 155, -478, 171, -602, 35, +-130, -123, 582, -199, 815, -124, 315, 27, +-345, 131, -638, 124, -297, 18, 429, -151, +807, -242, 476, -121, -195, 103, -580, 249, +-393, 171, 210, -130, 707, -388, 578, -283, +11, 105, -441, 395, -457, 307, 6, -129, +540, -517, 599, -403, 190, 104, -249, 490, +-424, 396, -176, -94, 317, -555, 556, -492, +358, 48, -56, 502, -386, 472, -308, -7, +152, -535, 527, -569, 449, -60, 38, 467, +-323, 541, -339, 107, 47, -472, 455, -631, +444, -187, 134, 391, -204, 575, -337, 235, +-75, -361, 330, -648, 454, -312, 243, 281, +-117, 579, -337, 350, -154, -250, 262, -652, +448, -413, 252, 198, -87, 577, -264, 396, +-106, -188, 214, -636, 338, -439, 176, 178, +-35, 557, -111, 363, -32, -193, 127, -599, +186, -401, 131, 215, 47, 553, -15, 320, +-25, -227, 36, -599, 143, -395, 178, 227, +100, 591, -42, 362, -100, -221, 25, -648, +215, -501, 261, 152, 97, 664, -121, 518, +-176, -122, 11, -702, 260, -674, 333, 11, +156, 708, -137, 708, -280, 40, -115, -702, +270, -844, 473, -172, 288, 674, -153, 861, +-425, 225, -217, -643, 300, -958, 583, -363, +338, 586, -167, 937, -438, 385, -239, -528, +250, -971, 561, -508, 369, 429, -88, 898, +-402, 502, -292, -321, 159, -858, 543, -616, +437, 167, -48, 742, -403, 619, -319, -36, +131, -666, 524, -727, 444, -143, -12, 542, +-376, 714, -312, 253, 67, -438, 451, -774, +463, -421, 66, 292, -305, 708, -327, 504, +-15, -158, 356, -721, 437, -657, 155, -17, +-181, 639, -290, 741, -109, 147, 184, -647, +346, -878, 280, -302, 23, 592, -215, 937, +-254, 371, -21, -601, 296, -1032, 405, -477, +211, 529, -170, 1014, -360, 508, -157, -492, +234, -1030, 453, -592, 322, 360, -72, 934, +-382, 635, -280, -248, 144, -898, 436, -731, +402, 85, 46, 791, -338, 772, -329, 33, +21, -754, 352, -866, 428, -179, 185, 672, +-194, 878, -363, 273, -149, -619, 228, -965, +466, -410, 366, 518, -67, 958, -419, 506, +-316, -450, 153, -1017, 513, -638, 461, 331, +1, 978, -425, 709, -376, -240, 82, -967, +477, -813, 462, 99, 79, 882, -329, 830, +-357, 11, -20, -823, 353, -912, 413, -164, +176, 699, -136, 898, -292, 272, -157, -628, +116, -944, 334, -405, 324, 496, 96, 903, +-198, 465, -307, -418, -102, -904, 228, -561, +391, 287, 272, 833, -56, 588, -315, -201, +-274, -796, 14, -653, 356, 79, 441, 705, +171, 646, -254, -15, -454, -657, -199, -664, +310, -74, 589, 547, 335, 619, -220, 106, +-543, -476, -317, -591, 248, -168, 633, 367, +451, 507, -135, 164, -555, -297, -425, -469, +163, -204, 667, 211, 553, 385, -82, 184, +-559, -178, -451, -380, 120, -226, 624, 136, +539, 332, -29, 219, -471, -123, -409, -346, +50, -257, 499, 82, 496, 318, 43, 228, +-352, -52, -334, -295, 15, -272, 362, -22, +386, 232, 57, 251, -235, 94, -197, -178, +33, -323, 219, -184, 232, 109, 54, 320, +-121, 252, -76, -73, 50, -410, 135, -355, +118, 39, 12, 429, -97, 424, -16, -12, +129, -515, 129, -548, 32, -10, -79, 543, +-85, 596, 54, 41, 169, -611, 105, -689, +-12, -69, -79, 620, -72, 697, 5, 105, +121, -639, 171, -765, 84, -141, -54, 618, +-177, 765, -99, 154, 150, -626, 292, -826, +171, -205, -115, 615, -277, 831, -139, 233, +191, -597, 366, -876, 205, -320, -117, 533, +-292, 852, -179, 395, 158, -432, 386, -869, +271, -523, -59, 290, -307, 826, -247, 618, +108, -138, 405, -802, 331, -732, -13, -23, +-281, 701, -267, 778, 54, 166, 347, -603, +323, -838, 52, -315, -193, 458, -205, 807, +-11, 430, 206, -339, 226, -805, 90, -531, +-49, 225, -89, 752, -63, 584, 38, -137, +109, -747, 132, -646, 92, 59, -9, 708, +-104, 677, -101, 8, 60, -703, 173, -742, +133, -87, -1, 642, -123, 756, -82, 179, +53, -564, 129, -794, 72, -311, -4, 414, +-36, 751, -41, 436, 20, -222, 64, -706, +46, -590, 0, 9, -25, 577, -1, 679, +71, 217, 61, -447, -34, -758, -86, -427, +17, 267, 159, 757, 117, 620, -32, -110, +-156, -782, -80, -776, 162, -44, 241, 754, +77, 878, -131, 154, -176, -757, -21, -949, +209, -231, 253, 696, 71, 960, -142, 298, +-173, -659, -24, -955, 197, -346, 282, 555, +87, 905, -127, 389, -159, -478, -48, -847, +140, -405, 238, 358, 134, 734, -33, 424, +-132, -253, -117, -632, 44, -413, 194, 131, +198, 468, 31, 410, -130, 1, -109, -365, +-15, -391, 137, -136, 171, 203, 51, 371, +-60, 250, -92, -98, -62, -338, 53, -332, +140, -56, 81, 280, -16, 401, -84, 150, +-66, -232, -1, -425, 103, -278, 99, 140, +4, 442, -45, 346, -96, -75, -56, -414, +68, -430, 136, -38, 74, 413, -26, 467, +-135, 95, -122, -374, 47, -514, 181, -184, +163, 349, 13, 521, -136, 186, -191, -286, +-43, -494, 179, -237, 248, 233, 135, 441, +-70, 212, -237, -154, -166, -354, 114, -273, +281, 51, 253, 306, 40, 266, -223, 45, +-253, -201, -15, -324, 253, -159, 301, 149, +165, 291, -118, 226, -273, -1, -127, -274, +128, -343, 287, -98, 250, 213, 11, 358, +-236, 245, -192, -148, 20, -422, 212, -295, +246, 94, 75, 351, -147, 319, -172, -16, +-28, -320, 96, -257, 166, -17, 93, 167, +-39, 175, -106, 76, -88, -56, -13, -94, +91, -77, 160, -99, 46, -25, -143, 125, +-179, 189, -21, 109, 155, -93, 191, -295, +-42, -239, -224, 95, -120, 367, 92, 332, +166, -29, 61, -461, -89, -486, -136, 1, +-25, 539, 66, 583, 64, 63, 29, -594, +2, -705, -57, -92, -57, 622, 12, 735, +73, 154, 85, -571, 14, -785, -86, -220, +-43, 510, 70, 745, 112, 301, 54, -392, +-49, -731, -53, -376, 15, 318, 84, 635, +109, 400, 52, -194, -13, -570, -60, -413, +-60, 110, 79, 456, 182, 370, 129, 10, +-28, -352, -166, -393, -91, -90, 122, 255, +207, 365, 95, 210, -67, -146, -113, -415, +-31, -300, 50, 64, 91, 372, 72, 386, +45, 72, -38, -345, -133, -464, -98, -174, +76, 243, 186, 497, 100, 352, -101, -114, +-237, -550, -111, -488, 98, -23, 221, 512, +131, 641, -73, 155, -260, -516, -221, -740, +27, -260, 267, 443, 242, 781, -39, 385, +-277, -375, -293, -801, -30, -478, 202, 265, +250, 769, 129, 593, -90, -145, -306, -762, +-306, -674, -9, 27, 370, 699, 444, 763, +66, 103, -437, -651, -515, -809, -50, -223, +462, 560, 517, 835, 109, 343, -347, -484, +-452, -838, -169, -420, 259, 373, 490, 815, +334, 496, -118, -288, -501, -765, -387, -521, +144, 151, 585, 674, 444, 581, -120, -38, +-512, -573, -362, -593, 147, -150, 463, 453, +340, 669, -40, 291, -332, -349, -328, -673, +-27, -443, 279, 199, 370, 718, 142, 555, +-261, -111, -416, -653, -187, -617, 223, -66, +418, 605, 221, 677, -190, 141, -436, -468, +-310, -648, 72, -299, 403, 333, 393, 641, +-12, 326, -499, -185, -555, -509, -64, -390, +508, 27, 588, 431, 37, 366, -588, 42, +-641, -248, -91, -353, 514, -146, 589, 176, +102, 305, -461, 145, -628, -67, -217, -250, +392, -222, 618, 37, 284, 231, -350, 201, +-695, 29, -337, -170, 355, -255, 707, -89, +364, 143, -351, 232, -689, 169, -327, -48, +370, -259, 664, -266, 316, -15, -300, 225, +-562, 311, -293, 134, 274, -200, 537, -336, +293, -184, -166, 123, -445, 296, -285, 266, +131, -44, 408, -272, 293, -259, -23, -53, +-306, 216, -306, 289, -53, 101, 252, -208, +333, -260, 127, -118, -168, 143, -372, 273, +-233, 126, 147, -149, 360, -242, 238, -118, +-132, 78, -405, 242, -275, 151, 107, -78, +308, -208, 180, -135, -116, 8, -290, 154, +-208, 173, 6, 41, 164, -79, 130, -135, +20, -158, -146, -65, -254, 160, -141, 278, +102, 157, 248, -133, 136, -392, -169, -296, +-383, 144, -173, 478, 202, 345, 352, -115, +96, -474, -250, -420, -346, 53, -107, 474, +214, 434, 260, 11, 77, -393, -133, -439, +-210, -99, -157, 341, 57, 437, 195, 132, +202, -263, 62, -420, -173, -203, -257, 196, +-93, 428, 169, 253, 289, -141, 170, -425, +-112, -326, -307, 83, -197, 449, 92, 379, +315, -39, 262, -423, -33, -429, -345, -25, +-327, 390, 45, 459, 360, 98, 343, -322, +-44, -487, -432, -171, -383, 301, 91, 483, +410, 197, 305, -267, -129, -467, -444, -205, +-310, 270, 110, 426, 343, 150, 177, -218, +-110, -342, -301, -154, -257, 171, -5, 267, +189, 126, 167, -68, 29, -187, -184, -185, +-293, -12, -130, 164, 111, 200, 196, 82, +79, -106, -139, -256, -251, -135, -139, 147, +69, 269, 150, 112, 73, -162, -53, -285, +-161, -99, -159, 273, -6, 291, 111, -7, +114, -309, 39, -259, -147, 51, -186, 349, +-24, 250, 154, -140, 177, -324, 1, -182, +-188, 116, -191, 279, 28, 197, 227, -111, +163, -253, -56, -164, -204, 51, -170, 222, +87, 207, 246, -28, 107, -241, -115, -200, +-192, -7, -86, 210, 98, 276, 129, 66, +34, -227, -57, -316, -52, -142, -56, 203, +-83, 420, -6, 216, 77, -243, 67, -446, +-23, -227, -145, 239, -152, 460, 19, 221, +103, -232, 44, -391, -66, -176, -113, 125, +-114, 306, -41, 171, 40, -73, 53, -199, +4, -128, -94, -1, -195, 137, -128, 121, +92, -38, 177, -114, 36, -41, -170, 68, +-272, 85, -129, 15, 107, -140, 176, -101, +69, 41, -78, 147, -175, 144, -183, 40, +-68, -144, 64, -273, 161, -127, 123, 118, +-48, 355, -234, 299, -231, -47, -43, -412, +178, -412, 260, -27, 133, 386, -162, 507, +-368, 155, -225, -375, 115, -600, 402, -247, +313, 315, -129, 672, -449, 410, -298, -273, +85, -723, 340, -521, 274, 166, 5, 722, +-238, 670, -302, -7, -158, -699, 68, -824, +316, -178, 265, 665, -58, 991, -344, 417, +-314, -601, -57, -1122, 189, -629, 269, 463, +134, 1166, -110, 826, -332, -266, -354, -1126, +-79, -985, 345, 42, 429, 1037, 0, 1140, +-480, 214, -526, -920, -112, -1253, 394, -437, +451, 757, 56, 1270, -372, 659, -528, -497, +-292, -1208, 221, -861, 513, 208, 316, 1103, +-275, 1029, -628, 91, -442, -924, 145, -1183, +564, -396, 390, 709, -109, 1241, -530, 688, +-523, -398, -146, -1161, 413, -955, 558, 24, +232, 999, -370, 1178, -698, 376, -394, -747, +251, -1333, 668, -765, 430, 525, -150, 1384, +-621, 1040, -579, -195, -37, -1286, 567, -1294, +609, -162, 76, 1105, -495, 1395, -624, 530, +-146, -797, 353, -1420, 457, -810, 134, 523, +-209, 1331, -367, 994, -270, -156, 55, -1172, +248, -1131, 238, -154, -27, 939, -273, 1190, +-287, 498, -2, -632, 181, -1197, 93, -714, +-73, 334, -193, 1068, -85, 885, 9, -2, +67, -862, -22, -980, -82, -337, -126, 564, +-135, 1031, -3, 708, 123, -194, 93, -1009, +-157, -992, -262, -167, -210, 846, 71, 1167, +264, 471, 103, -571, -195, -1129, -348, -720, +-217, 260, 28, 996, 307, 880, 235, 93, +-98, -779, -411, -991, -434, -389, 20, 484, +428, 981, 397, 677, -122, -113, -549, -862, +-463, -893, 70, -208, 458, 674, 367, 1034, +-69, 537, -467, -442, -408, -1117, -111, -782, +350, 250, 410, 1099, 107, 972, -360, -13, +-504, -961, -175, -1006, 269, -169, 427, 672, +98, 914, -220, 349, -336, -394, -189, -714, +-11, -421, 162, 126, 213, 499, 60, 472, +-144, 75, -341, -225, -230, -403, 58, -288, +239, -43, 175, 312, -41, 443, -248, 271, +-314, -137, -122, -531, 91, -439, 248, 34, +70, 542, -195, 498, -293, 94, -129, -427, +101, -550, 48, -197, -39, 291, -130, 521, +-57, 312, -44, -83, -71, -406, -94, -354, +-23, -63, 20, 218, -109, 281, -128, 187, +-25, 24, 104, -142, -20, -248, -169, -238, +-219, 13, -52, 290, 113, 383, 62, 159, +-56, -278, -136, -469, -56, -299, -80, 159, +-64, 488, -25, 486, -29, 74, 16, -449, +-12, -606, -28, -310, -95, 268, -117, 662, +-93, 618, 36, 3, 134, -643, 21, -845, +-180, -323, -288, 532, -71, 989, 112, 663, +207, -299, 16, -951, -153, -864, -258, -67, +-165, 793, 42, 995, 107, 415, 116, -498, +-117, -977, -208, -732, -178, 168, 14, 937, +137, 967, 78, 194, -158, -775, -323, -1098, +-144, -559, 86, 538, 245, 1141, 49, 879, +-278, -172, -395, -1058, -189, -1081, 178, -217, +296, 893, 135, 1207, -269, 589, -461, -562, +-363, -1188, 51, -930, 349, 120, 304, 1086, +-63, 1197, -471, 390, -440, -753, -141, -1284, +237, -861, 256, 311, 114, 1243, -178, 1183, +-369, 179, -347, -993, -102, -1371, 246, -635, +328, 707, 67, 1472, -402, 1057, -414, -287, +-162, -1443, 151, -1426, 207, -194, 25, 1349, +-51, 1704, -129, 667, -260, -1038, -284, -1814, +-34, -1060, 236, 625, 286, 1770, -41, 1406, +-361, -110, -349, -1556, -185, -1659, 93, -447, +241, 1249, 227, 1840, -13, 942, -422, -741, +-527, -1768, -188, -1382, 359, 155, 474, 1588, +115, 1661, -433, 433, -598, -1196, -312, -1837, +140, -945, 461, 770, 364, 1873, -99, 1375, +-638, -251, -670, -1694, -158, -1709, 543, -294, +621, 1366, 79, 1841, -606, 803, -761, -791, +-357, -1792, 244, -1207, 636, 283, 445, 1548, +-177, 1449, -854, 237, -845, -1198, -111, -1578, +738, -565, 861, 825, 44, 1607, -862, 899, +-1052, -500, -329, -1523, 567, -1110, 909, 258, +368, 1407, -554, 1300, -1031, 24, -717, -1311, +201, -1485, 856, -221, 743, 1213, -124, 1660, +-951, 540, -995, -1039, -245, -1733, 646, -922, +942, 757, 365, 1748, -586, 1271, -1084, -254, +-773, -1608, 180, -1628, 941, -221, 843, 1383, +-83, 1819, -982, 694, -1144, -974, -278, -1780, +735, -1114, 959, 504, 341, 1603, -629, 1346, +-1046, 51, -633, -1208, 233, -1433, 770, -466, +534, 770, -197, 1216, -736, 739, -660, -210, +-33, -838, 441, -729, 325, -166, -127, 322, +-495, 506, -364, 336, 90, 81, 356, -70, +114, -167, -391, -270, -591, -297, -298, -186, +242, 147, 613, 439, 254, 515, -424, 290, +-813, -235, -641, -575, 101, -662, 692, -311, +547, 327, -66, 882, -690, 852, -807, 176, +-295, -690, 392, -1051, 609, -668, 199, 134, +-449, 890, -697, 1019, -369, 439, 201, -442, +508, -999, 156, -798, -378, 72, -597, 843, +-366, 828, 144, 99, 515, -644, 248, -790, +-309, -124, -613, 711, -431, 896, 43, 144, +354, -803, 231, -1163, -128, -434, -362, 861, +-308, 1499, -62, 801, 67, -530, 18, -1478, +-180, -1300, -188, 93, -48, 1262, 108, 1384, +-14, 350, -234, -825, -253, -1239, -90, -431, +49, 653, -23, 989, -151, 285, -182, -671, +-72, -989, 7, -335, -7, 894, -115, 1350, +-140, 600, -166, -777, -165, -1578, -65, -1183, +54, 391, 14, 1618, -220, 1551, -308, 162, +-173, -1350, 71, -1714, 233, -595, 132, 1135, +-146, 1880, -385, 952, -610, -922, -500, -2055, +41, -1434, 671, 514, 737, 2139, 76, 2027, +-685, 194, -1032, -1716, -692, -2318, 61, -1079, +653, 1034, 771, 2319, 210, 1584, -628, -396, +-981, -1926, -606, -1741, 266, -70, 726, 1603, +486, 1897, -225, 426, -859, -1301, -822, -1933, +-203, -946, 524, 870, 808, 1946, 312, 1359, +-577, -332, -982, -1570, -635, -1374, 198, -87, +724, 1127, 414, 1230, -337, 233, -879, -918, +-561, -1158, 236, -350, 764, 917, 496, 1472, +-444, 707, -1146, -697, -854, -1730, 171, -1312, +989, 169, 930, 1562, -161, 1780, -1131, 609, +-1235, -1011, -394, -1812, 733, -1187, 1116, 363, +609, 1665, -443, 1504, -1322, 210, -1190, -1269, +-202, -1783, 780, -783, 1110, 806, 462, 1873, +-443, 1474, -1088, 5, -936, -1531, -122, -1994, +510, -866, 681, 861, 171, 1847, -437, 1406, +-685, 66, -432, -1221, 77, -1442, 359, -580, +384, 599, -30, 1106, -605, 739, -781, -185, +-332, -879, 270, -738, 656, -34, 488, 768, +-191, 1008, -750, 404, -899, -565, -437, -1201, +282, -1008, 814, 63, 715, 1143, -155, 1471, +-990, 652, -1130, -599, -468, -1438, 547, -1188, +1046, -13, 632, 1078, -344, 1203, -1123, 414, +-969, -582, -246, -991, 592, -394, 866, 467, +262, 726, -533, 217, -937, -468, -564, -722, +268, -158, 678, 588, 374, 902, -342, 297, +-852, -625, -621, -1008, 48, -535, 523, 459, +515, 1161, 12, 857, -523, -217, -726, -1067, +-478, -1167, 204, -269, 593, 861, 445, 1426, +-305, 854, -938, -405, -737, -1372, 125, -1245, +868, -210, 678, 992, -100, 1377, -988, 679, +-1196, -418, -497, -1081, 680, -895, 1289, -53, +743, 760, -585, 837, -1588, 266, -1196, -405, +122, -606, 1222, -361, 1114, 143, 15, 409, +-1110, 374, -1361, 21, -485, -208, 773, -166, +1237, 38, 485, 125, -829, -89, -1540, -332, +-900, -326, 413, 211, 1431, 741, 1103, 875, +-286, 150, -1466, -825, -1548, -1316, -414, -948, +912, 306, 1401, 1458, 642, 1647, -587, 585, +-1309, -940, -1011, -1781, 22, -1340, 828, 60, +812, 1350, -75, 1602, -830, 763, -849, -586, +-155, -1398, 628, -1159, 667, -117, 26, 965, +-764, 1223, -919, 580, -396, -342, 412, -953, +860, -912, 537, -212, -262, 577, -975, 924, +-1054, 652, -376, -36, 570, -671, 1026, -797, +721, -390, -209, 247, -990, 690, -1143, 715, +-697, 214, 170, -489, 935, -883, 1000, -570, +307, 308, -509, 1010, -974, 975, -842, 27, +-441, -1006, 137, -1406, 552, -692, 645, 775, +473, 1658, -163, 1420, -684, 71, -853, -1360, +-578, -1878, -86, -1072, 418, 450, 644, 1616, +418, 1761, -62, 758, -534, -632, -744, -1618, +-557, -1513, 30, -560, 408, 703, 380, 1503, +67, 1350, -338, 346, -393, -765, -68, -1362, +202, -1004, 47, 48, -302, 908, -546, 1028, +-374, 345, 47, -460, 481, -855, 590, -427, +170, 438, -337, 942, -733, 528, -751, -450, +-374, -1150, 116, -949, 392, 167, 530, 1159, +467, 1311, 171, 538, -378, -579, -914, -1251, +-1008, -1065, -517, -119, 394, 690, 917, 964, +917, 521, 283, -30, -613, -320, -1180, -398, +-970, -205, 1, -188, 805, -74, 913, 171, +166, 379, -711, 332, -1027, 100, -541, -295, +381, -533, 966, -340, 765, 222, -159, 747, +-1144, 694, -1289, 97, -429, -764, 614, -1117, +1205, -696, 790, 339, -273, 1233, -1086, 1316, +-1060, 534, -205, -674, 677, -1421, 873, -1199, +169, -192, -833, 801, -1128, 1214, -359, 856, +716, 78, 1249, -630, 668, -810, -719, -577, +-1628, -123, -1240, 357, 123, 606, 1268, 606, +1437, 255, 353, -275, -1087, -856, -1570, -866, +-883, -99, 452, 913, 1315, 1334, 1048, 755, +-155, -566, -1212, -1535, -1301, -1433, -473, -262, +606, 1293, 1113, 1831, 746, 1090, -162, -422, +-772, -1640, -879, -1613, -504, -362, 124, 1098, +470, 1581, 386, 862, 59, -530, -227, -1498, +-334, -1050, -70, 309, 163, 1481, 149, 1312, +-146, 8, -515, -1379, -588, -1755, -300, -598, +417, 1042, 933, 1882, 734, 1277, -25, -217, +-917, -1482, -1323, -1508, -835, -483, 129, 705, +1108, 1138, 1305, 635, 473, -61, -651, -495, +-1403, -325, -1065, 126, -4, 248, 925, -142, +1008, -609, 247, -423, -675, 243, -1084, 936, +-559, 896, 366, 33, 1001, -846, 728, -1072, +-228, -345, -1147, 483, -1331, 821, -385, 575, +836, -131, 1505, -592, 1046, -447, -229, 51, +-1487, 439, -1820, 399, -856, -66, 564, -454, +1644, -470, 1667, -44, 546, 520, -985, 695, +-1898, 403, -1631, -312, -397, -956, 1003, -898, +1731, -101, 1313, 892, 135, 1332, -1007, 858, +-1641, -273, -1317, -1309, -299, -1595, 871, -835, +1465, 572, 1203, 1729, 218, 2015, -935, 925, +-1555, -965, -1338, -2412, -286, -2418, 972, -691, +1726, 1700, 1211, 3111, -153, 2439, -1374, -33, +-1798, -2546, -999, -3417, 351, -1829, 1516, 1095, +1673, 3283, 614, 3181, -890, 695, -1864, -2279, +-1507, -3582, -85, -2210, 1315, 746, 1636, 3109, +780, 3155, -611, 983, -1477, -1892, -1332, -3250, +-179, -2308, 973, 112, 1186, 2403, 621, 2943, +-559, 1528, -1179, -811, -844, -2441, 16, -2466, +861, -984, 846, 1239, 178, 2552, -631, 2038, +-1021, 229, -495, -1742, 250, -2376, 711, -1240, +705, 735, -1, 1965, -587, 1637, -732, 212, +-362, -1155, 202, -1636, 419, -755, 299, 508, +-159, 1120, -301, 889, -69, 80, 210, -624, +212, -706, -178, -193, -575, 298, -594, 459, +-71, 49, 551, -326, 935, -376, 539, -5, +-396, 569, -1088, 725, -1093, 218, -198, -484, +814, -970, 1102, -857, 546, -83, -427, 838, +-1003, 1298, -750, 910, 42, -38, 738, -1002, +680, -1395, -13, -977, -714, 120, -714, 1037, +-19, 1396, 597, 953, 622, -94, 54, -990, +-537, -1210, -724, -750, -352, 1, 331, 651, +742, 882, 518, 731, -186, 275, -842, -213, +-886, -582, -133, -838, 660, -678, 899, -190, +448, 492, -382, 1211, -789, 1198, -775, 420, +-254, -854, 390, -1811, 586, -1521, 496, -64, +72, 1557, -282, 2275, -402, 1345, -472, -704, +-420, -2225, -116, -2158, 374, -513, 714, 1420, +620, 2231, 73, 1358, -707, -264, -1159, -1480, +-852, -1461, 62, -525, 1041, 481, 1453, 956, +897, 602, -518, 131, -1668, -165, -1727, -286, +-741, -249, 922, -182, 2057, -95, 1739, 107, +271, 311, -1503, 211, -2335, -14, -1560, -292, +253, -328, 1903, 13, 2209, 398, 991, 541, +-833, 147, -2163, -418, -1976, -807, -444, -512, +1275, 165, 2136, 823, 1556, 997, -120, 416, +-1744, -428, -2173, -1144, -1131, -1223, 669, -386, +1988, 853, 1986, 1634, 512, 1467, -1322, 174, +-2176, -1412, -1622, -2241, 113, -1500, 1720, 295, +2098, 2124, 904, 2582, -973, 1240, -2101, -909, +-1706, -2552, -46, -2416, 1574, -779, 2000, 1289, +921, 2438, -792, 2055, -1912, 371, -1704, -1353, +-286, -2072, 1280, -1548, 1791, -28, 1038, 1266, +-361, 1640, -1381, 943, -1344, -330, -470, -1234, +508, -1106, 897, -75, 697, 827, 111, 1034, +-392, 203, -472, -779, -305, -1042, -88, -483, +80, 686, 134, 1314, 55, 1011, -19, -190, +-32, -1376, 12, -1524, 124, -567, 132, 865, +-143, 1648, -339, 1199, -264, -66, -75, -1116, +252, -1309, 398, -614, 282, 372, -33, 858, +-409, 681, -567, 188, -369, -246, 148, -221, +549, -18, 595, -90, 234, -279, -222, -423, +-545, -393, -691, 236, -373, 869, 182, 996, +527, 544, 643, -472, 455, -1348, -46, -1365, +-519, -418, -804, 778, -725, 1491, -163, 1229, +650, 257, 1057, -794, 701, -1125, -136, -827, +-874, -202, -1029, 354, -542, 487, 281, 484, +877, 443, 856, 309, 268, 32, -559, -349, +-996, -735, -678, -708, 90, -267, 690, 266, +804, 745, 378, 835, -387, 397, -825, -126, +-716, -548, -149, -663, 599, -526, 899, -190, +530, 312, -310, 573, -1011, 689, -885, 370, +-173, -273, 754, -638, 1224, -658, 683, -146, +-326, 439, -1156, 659, -1260, 284, -561, -400, +566, -726, 1381, -413, 1276, 476, 366, 1007, +-706, 761, -1357, -205, -1156, -1174, -420, -1305, +405, -473, 1065, 814, 1144, 1503, 720, 1208, +-67, 41, -822, -1142, -1255, -1370, -1155, -675, +-361, 374, 647, 955, 1469, 785, 1516, 30, +435, -528, -911, -462, -1717, 47, -1371, 631, +-92, 586, 1100, -158, 1437, -1052, 796, -1248, +-426, -488, -1246, 905, -985, 1915, 4, 1705, +952, 254, 1046, -1511, 249, -2355, -803, -1799, +-1293, 2, -860, 1680, 233, 2160, 1328, 1458, +1588, 89, 702, -1127, -725, -1479, -1759, -1056, +-1689, -407, -642, 164, 764, 400, 1675, 572, +1703, 863, 930, 1104, -525, 932, -1581, -75, +-1833, -1515, -1246, -2394, -42, -2070, 1175, -337, +1900, 2034, 1733, 3448, 641, 2906, -905, 552, +-1950, -2318, -2003, -3927, -1105, -3214, 375, -718, +1579, 2163, 2195, 3670, 1649, 3163, 148, 1105, +-1316, -1585, -2296, -3154, -1874, -3003, -581, -1369, +776, 924, 1981, 2483, 2140, 2657, 1196, 1452, +-397, -312, -2015, -1682, -2413, -2171, -1477, -1522, +412, -193, 2076, 1114, 2400, 1805, 1296, 1457, +-715, 351, -2107, -917, -2061, -1504, -760, -1133, +819, -159, 1786, 807, 1574, 1165, 488, 825, +-724, 20, -1488, -753, -1341, -1070, -566, -723, +438, -19, 1250, 744, 1348, 1197, 906, 952, +-94, 206, -1299, -694, -1789, -1429, -1241, -1459, +121, -726, 1358, 495, 1808, 1662, 1209, 2167, +-48, 1616, -1047, -103, -1532, -1971, -1137, -3013, +-256, -2480, 398, -364, 861, 2164, 864, 3683, +843, 3138, 644, 751, 55, -2251, -808, -3838, +-1770, -3288, -1865, -848, -860, 2045, 989, 3266, +2592, 2686, 2846, 790, 1285, -1177, -1239, -2106, +-3082, -1731, -3133, -818, -1453, 42, 1024, 630, +2822, 813, 3118, 964, 1791, 992, -442, 656, +-2299, -144, -3008, -1089, -2192, -1703, -311, -1386, +1739, -253, 2838, 1118, 2543, 1975, 919, 1647, +-1286, 348, -2680, -1203, -2707, -1953, -1166, -1448, +1013, -39, 2436, 1392, 2457, 1703, 994, 759, +-805, -653, -2013, -1420, -1889, -1022, -655, 191, +640, 1127, 1362, 987, 1100, 127, 192, -786, +-529, -864, -523, -259, -161, 531, 208, 717, +63, 99, -443, -611, -616, -732, -220, 38, +493, 882, 1042, 1194, 980, 467, 200, -879, +-882, -1621, -1475, -1299, -1153, -166, -107, 1167, +1139, 1757, 1590, 1378, 1094, 296, -18, -835, +-1075, -1572, -1470, -1572, -1043, -844, 53, 239, +1003, 1255, 1195, 1723, 740, 1396, -48, 323, +-719, -840, -731, -1637, -391, -1512, -11, -656, +398, 337, 202, 1009, -139, 1052, -89, 689, +208, 331, 740, 131, 694, -62, -159, -562, +-1149, -1170, -1480, -1592, -884, -1050, 577, 451, +1877, 2202, 2056, 2892, 943, 1647, -1019, -688, +-2559, -2880, -2409, -3251, -571, -1520, 1604, 1063, +2716, 2729, 2078, 2592, 189, 868, -1707, -1086, +-2407, -1891, -1601, -1366, 183, -172, 1567, 836, +1767, 819, 809, 226, -523, -336, -1021, -577, +-704, -121, 59, 607, 521, 849, 197, 450, +-379, -327, -750, -1148, -377, -1111, 619, -411, +1416, 677, 1287, 1376, 121, 1166, -1347, 267, +-2150, -999, -1541, -1646, 12, -1036, 1716, 372, +2525, 1663, 1828, 1850, 15, 465, -1900, -1446, +-2641, -2470, -1802, -1623, 48, 550, 1674, 2395, +2193, 2659, 1524, 996, 192, -1304, -975, -2552, +-1412, -2018, -1136, -273, -507, 1257, 72, 1681, +438, 853, 638, -164, 891, -529, 923, -35, +531, 494, -185, 256, -1047, -611, -1451, -1527, +-1277, -1521, -481, -326, 806, 1420, 1724, 2426, +1905, 2082, 1187, 564, -264, -1257, -1627, -2386, +-2109, -2195, -1642, -1163, -418, 130, 1108, 1396, +1943, 2102, 1901, 2044, 1033, 1328, -201, -57, +-1268, -1683, -1782, -2645, -1584, -2546, -811, -1172, +462, 779, 1506, 2544, 1915, 3149, 1495, 2153, +400, 283, -899, -1773, -1861, -3017, -1902, -2646, +-966, -1083, 419, 867, 1545, 2090, 1816, 2108, +1127, 1232, -52, 156, -1006, -488, -1247, -823, +-782, -879, -9, -1024, 527, -1052, 455, -724, +5, 111, -231, 1231, 57, 2064, 494, 2013, +739, 932, 492, -750, -238, -2199, -884, -2702, +-1185, -1990, -913, -220, -106, 1610, 849, 2736, +1441, 2585, 1445, 1219, 762, -648, -361, -2043, +-1379, -2495, -1817, -1781, -1345, -256, -177, 1059, +1104, 1601, 1756, 1411, 1573, 676, 723, 161, +-283, -20, -1004, -262, -1420, -721, -1242, -1302, +-683, -1630, 3, -1139, 984, 336, 1612, 1967, +1710, 2829, 1140, 2211, -269, 312, -1742, -1927, +-2493, -3103, -2020, -2671, -285, -939, 1738, 1145, +2818, 2422, 2384, 2457, 697, 1425, -1362, -14, +-2581, -1056, -2247, -1645, -809, -1635, 951, -1149, +1994, -404, 1736, 622, 650, 1456, -533, 1879, +-1095, 1504, -886, 336, -204, -1055, 263, -1936, +213, -1848, -15, -885, -302, 403, -82, 1309, +596, 1425, 878, 1090, 736, 414, -45, -251, +-961, -638, -1280, -1016, -984, -1153, -20, -937, +1003, -111, 1535, 1022, 1211, 1781, 137, 1584, +-899, 368, -1487, -1142, -1122, -1927, -168, -1423, +911, -155, 1356, 1219, 817, 1661, -85, 737, +-930, -533, -882, -1308, -112, -926, 646, 343, +788, 1254, 232, 1097, -491, 4, -890, -1220, +-600, -1601, 195, -731, 979, 685, 1170, 1668, +610, 1524, -357, 313, -1166, -1023, -1257, -1610, +-612, -1115, 356, 42, 1108, 993, 1262, 1259, +780, 654, -189, -305, -940, -935, -1111, -856, +-562, -150, 262, 620, 643, 920, 613, 448, +132, -323, -259, -918, -141, -834, 102, -82, +454, 694, 351, 914, -193, 507, -762, -124, +-973, -533, -429, -481, 488, -192, 1349, -66, +1320, -61, 392, -73, -680, 34, -1315, 431, +-1060, 726, -172, 604, 632, 3, 894, -743, +525, -1183, -61, -932, -378, -94, -196, 725, +229, 1203, 507, 1068, 343, 388, -368, -311, +-997, -828, -1096, -1004, -388, -829, 796, -481, +1717, 165, 1780, 901, 664, 1421, -930, 1306, +-2097, 406, -2112, -832, -829, -1796, 896, -1836, +2051, -788, 2048, 783, 982, 1874, -515, 1886, +-1456, 732, -1573, -799, -845, -1589, 161, -1278, +689, -217, 799, 715, 516, 881, 358, 289, +259, -449, 115, -615, -200, -19, -714, 818, +-848, 1070, -624, 483, -2, -763, 717, -1702, +1099, -1401, 962, -178, 274, 1308, -490, 1953, +-977, 1268, -889, -248, -323, -1425, 192, -1448, +599, -609, 695, 496, 551, 985, 180, 604, +-258, -156, -465, -609, -467, -388, -285, 270, +-64, 748, 197, 621, 453, -106, 597, -871, +435, -958, -63, -457, -571, 309, -794, 862, +-486, 735, 162, 276, 757, -245, 955, -449, +549, -234, -148, 93, -874, 148, -951, -152, +-469, -540, 251, -734, 792, -243, 770, 731, +537, 1566, 75, 1554, -378, 408, -536, -1328, +-639, -2457, -450, -2117, -7, -346, 350, 1632, +701, 2559, 828, 1988, 567, 305, 2, -1220, +-642, -1747, -1020, -1299, -843, -438, -206, 161, +470, 318, 924, 357, 934, 648, 506, 1122, +-18, 1247, -506, 528, -684, -818, -516, -2054, +-388, -2395, -199, -1284, 129, 694, 616, 2400, +1088, 2851, 1063, 1782, 343, -295, -718, -2136, +-1479, -2697, -1460, -1854, -549, -116, 809, 1426, +1597, 1984, 1475, 1450, 513, 374, -716, -570, +-1150, -926, -864, -719, -229, -404, 281, -150, +402, -109, 355, -119, 277, 213, 319, 630, +205, 870, -154, 669, -394, -59, -478, -814, +-224, -1084, 259, -673, 560, 80, 472, 665, +-56, 727, -506, 210, -626, -313, -215, -395, +525, -81, 931, 466, 767, 697, 94, 310, +-746, -476, -1171, -1091, -976, -1148, -187, -477, +793, 648, 1405, 1468, 1319, 1466, 552, 715, +-555, -390, -1367, -1297, -1517, -1314, -874, -829, +228, -251, 1296, 314, 1646, 704, 946, 985, +-76, 1164, -921, 933, -1044, 66, -557, -1115, +-10, -1922, 347, -1790, 289, -619, 58, 992, +-24, 2044, 230, 1936, 663, 798, 752, -551, +257, -1394, -716, -1354, -1460, -764, -1249, -69, +-256, 360, 1069, 445, 1837, 441, 1474, 499, +246, 527, -1084, 465, -1631, 142, -1127, -480, +-17, -1054, 879, -1209, 1079, -748, 609, 156, +-90, 1161, -411, 1522, -410, 1029, -59, 61, +287, -834, 205, -1173, -16, -824, -261, -201, +-341, 229, -102, 333, 182, 306, 458, 282, +499, 330, 261, 373, -91, 204, -496, -157, +-464, -458, -211, -579, 80, -514, 410, -331, +350, -75, 182, 347, -62, 766, -161, 1010, +-60, 721, 3, 51, 154, -826, 97, -1356, +-52, -1178, -80, -465, -260, 526, -190, 1232, +58, 1312, 308, 757, 563, -52, 401, -737, +34, -1040, -334, -833, -586, -370, -509, 134, +-200, 533, 235, 628, 597, 516, 670, 242, +432, 0, -28, -137, -416, -200, -535, -279, +-403, -412, -99, -558, 185, -416, 274, 32, +254, 651, 169, 1150, 283, 1028, 346, 399, +105, -594, -262, -1467, -709, -1512, -763, -745, +-289, 404, 449, 1365, 979, 1475, 993, 872, +460, -42, -332, -747, -904, -1049, -955, -935, +-452, -501, 223, 53, 769, 628, 891, 898, +358, 835, -172, 306, -459, -353, -412, -691, +-30, -622, 152, -136, 88, 180, -60, 98, +-127, -160, 63, -245, 287, 177, 360, 751, +246, 968, -5, 386, -333, -645, -494, -1488, +-260, -1287, 48, -130, 347, 1079, 537, 1609, +251, 939, -40, -323, -155, -1213, -269, -1073, +-55, -262, 105, 664, 12, 943, -4, 402, +-130, -384, 19, -805, 293, -594, 292, 61, +234, 687, -68, 829, -285, 406, -284, -231, +-169, -711, 93, -819, 241, -374, 282, 199, +215, 579, -4, 658, -134, 326, -99, -84, +-49, -361, -14, -451, 66, -203, 91, 93, +45, 240, 22, 153, -36, -8, -100, -254, +62, -231, 234, -4, 204, 246, 118, 546, +-110, 492, -309, 103, -249, -554, -50, -982, +186, -880, 367, -161, 318, 771, 106, 1258, +-104, 1084, -206, 230, -243, -722, -75, -1262, +107, -1062, 132, -252, 167, 521, 126, 967, +17, 729, -35, 110, -28, -308, -18, -367, +36, -103, 71, 143, 30, 39, 68, -301, +-37, -512, -140, -384, -82, 107, -58, 683, +216, 956, 417, 699, 275, -37, 40, -895, +-223, -1230, -351, -908, -317, 36, -143, 944, +104, 1156, 330, 684, 497, -154, 422, -664, +186, -686, -107, -183, -410, 228, -611, 181, +-557, -42, -117, -277, 521, -101, 881, 331, +798, 559, 278, 362, -340, -109, -690, -495, +-739, -560, -411, -238, 68, 75, 497, 297, +680, 306, 569, 137, 360, 70, -70, 2, +-471, -74, -675, -109, -602, -153, -49, -164, +531, -25, 769, 70, 490, 89, -25, 67, +-327, 34, -394, 13, -78, 76, 219, 87, +136, 20, 19, -130, -167, -207, -199, -128, +64, -97, 357, 69, 319, 147, 184, 134, +85, 168, -125, 97, -220, -33, -372, -125, +-343, -113, -40, -167, 311, -172, 643, -128, +595, 5, 231, 308, -165, 408, -543, 336, +-630, -55, -344, -417, 127, -427, 508, -190, +524, 141, 269, 253, -20, 108, -102, -214, +27, -213, 51, 161, -12, 570, -272, 631, +-481, 132, -397, -688, -64, -1209, 630, -981, +1171, 9, 982, 1147, 256, 1656, -800, 1158, +-1518, -241, -1264, -1544, -364, -1800, 811, -820, +1588, 685, 1432, 1597, 595, 1296, -475, 41, +-1183, -1105, -1234, -1185, -641, -250, 143, 903, +684, 1248, 916, 431, 695, -914, 196, -1658, +-164, -1111, -303, 385, -292, 1708, -231, 1925, +-163, 864, -160, -836, -163, -1963, 165, -1809, +398, -632, 567, 849, 612, 1662, 289, 1424, +-190, 470, -681, -564, -777, -1016, -566, -850, +-80, -333, 507, 71, 837, 289, 901, 232, +512, 197, -52, 351, -562, 333, -856, 197, +-641, -108, -217, -448, 184, -594, 486, -444, +617, -49, 603, 255, 465, 406, 161, 420, +-256, 334, -731, 236, -914, 101, -635, -276, +-53, -773, 677, -909, 1211, -593, 1064, 269, +503, 1141, -259, 1359, -1020, 834, -1235, -263, +-885, -1287, -10, -1475, 871, -837, 1252, 219, +1095, 1190, 342, 1315, -482, 634, -972, -276, +-941, -898, -393, -896, 316, -298, 755, 282, +659, 494, 245, 355, -134, 29, -211, -208, +-58, -236, 90, -41, 45, 163, -169, 269, +-328, 198, -253, -103, 100, -383, 521, -469, +670, -285, 415, 163, -102, 566, -503, 711, +-578, 410, -384, -166, 38, -749, 399, -900, +537, -484, 503, 193, 217, 859, -153, 943, +-398, 471, -498, -247, -354, -895, 123, -894, +588, -372, 675, 337, 308, 855, -300, 862, +-636, 278, -446, -530, 120, -987, 514, -883, +584, -8, 235, 925, -242, 1253, -413, 643, +-426, -541, -45, -1361, 365, -1229, 439, -142, +376, 1060, 4, 1518, -271, 802, -301, -472, +-79, -1291, 153, -1139, 205, -108, 129, 869, +-113, 1042, -236, 369, -86, -499, 280, -863, +557, -504, 481, 359, 41, 936, -570, 674, +-883, -219, -596, -992, 157, -1090, 885, -237, +1104, 885, 756, 1306, -61, 813, -874, -321, +-1108, -1202, -637, -1137, 151, -286, 755, 668, +890, 1094, 461, 629, -41, -224, -269, -751, +-327, -690, -137, -80, 25, 501, -7, 659, +-145, 224, -227, -349, 15, -614, 477, -430, +708, 140, 552, 529, 30, 549, -648, 156, +-838, -291, -542, -480, 41, -324, 619, 13, +788, 251, 529, 308, -27, 55, -406, -116, +-330, -153, -93, -21, 108, 144, 125, 136, +-42, 50, -181, -146, -112, -267, 131, -245, +400, -91, 520, 151, 406, 487, -92, 571, +-580, 203, -693, -337, -446, -820, 100, -828, +584, -193, 750, 672, 523, 1107, 82, 823, +-244, -18, -460, -912, -446, -1181, -262, -679, +-20, 293, 313, 1014, 511, 1044, 495, 392, +201, -508, -215, -968, -417, -770, -296, -96, +36, 583, 303, 748, 284, 412, -14, -74, +-284, -455, -255, -398, 58, -138, 476, 23, +604, 77, 249, 64, -306, 133, -617, 265, +-499, 320, -65, 73, 353, -308, 506, -619, +365, -588, 203, -81, 13, 503, -138, 845, +-181, 650, -274, 35, -238, -594, -46, -774, +116, -536, 256, -135, 440, 309, 432, 519, +207, 539, -151, 405, -561, 108, -566, -319, +-182, -647, 212, -685, 556, -401, 467, 146, +194, 719, -15, 902, -207, 506, -191, -180, +-90, -751, -20, -775, -32, -313, -71, 269, +-29, 502, 172, 319, 430, 8, 433, -149, +202, -41, -233, 61, -535, 87, -533, -103, +-208, -265, 331, -213, 641, 5, 658, 235, +181, 245, -381, 163, -522, -58, -361, -178, +63, -165, 428, -100, 410, -21, 142, 76, +-185, 270, -367, 254, -215, 52, 139, -340, +436, -652, 473, -477, 154, 234, -267, 979, +-496, 1055, -399, 359, -26, -788, 390, -1514, +561, -1155, 370, 50, -2, 1241, -336, 1588, +-405, 782, -70, -527, 257, -1233, 310, -978, +56, -74, -291, 686, -300, 590, -34, -65, +449, -467, 692, -314, 319, 345, -245, 888, +-696, 656, -728, -162, -176, -1049, 504, -1247, +830, -644, 599, 420, 55, 1265, -413, 1258, +-536, 569, -306, -399, 61, -1033, 312, -1068, +298, -519, 139, 184, -43, 658, -147, 757, +-25, 401, 67, -5, 138, -297, 160, -347, +53, -181, -77, -51, -241, -48, -239, -61, +-52, -27, 242, 75, 439, 231, 383, 229, +109, 115, -249, -44, -414, -155, -321, -146, +12, -90, 314, -58, 313, -74, 132, -70, +-123, -53, -148, 114, 80, 242, 349, 297, +291, 256, -70, 46, -435, -201, -604, -480, +-271, -588, 299, -450, 716, 28, 798, 608, +416, 964, -232, 817, -715, 135, -758, -637, +-459, -1110, 100, -954, 562, -304, 732, 477, +639, 947, 215, 858, -196, 375, -552, -233, +-695, -535, -426, -526, 40, -261, 482, -24, +640, 4, 473, -7, 132, 19, -196, 228, +-304, 464, -266, 517, -144, 237, -47, -249, +0, -665, 48, -772, 151, -503, 332, 7, +383, 512, 279, 769, -18, 731, -424, 380, +-530, -177, -325, -631, 33, -809, 339, -629, +438, -145, 307, 321, 141, 567, 48, 569, +-65, 335, -127, 131, -202, -43, -305, -218, +-301, -382, -107, -602, 247, -648, 599, -378, +681, 299, 473, 1040, -25, 1325, -581, 888, +-877, -237, -759, -1333, -198, -1684, 518, -1034, +1024, 212, 970, 1244, 417, 1513, -279, 867, +-800, -134, -815, -851, -432, -955, 68, -489, +448, 44, 531, 292, 379, 176, 218, -13, +107, 47, 17, 349, -173, 570, -433, 362, +-501, -225, -337, -843, 74, -935, 529, -379, +728, 400, 578, 922, 88, 788, -435, 188, +-598, -437, -454, -630, -76, -309, 275, 143, +356, 318, 234, 73, 73, -305, -10, -441, +-2, -55, 102, 543, 98, 820, -83, 492, +-239, -290, -289, -946, -149, -958, 158, -285, +349, 552, 355, 942, 227, 637, -39, -68, +-142, -571, -174, -509, -147, -51, -18, 350, +-65, 275, -100, -171, -74, -504, 110, -375, +470, 200, 623, 770, 361, 785, -203, 123, +-758, -715, -832, -1028, -403, -623, 215, 304, +750, 945, 882, 798, 577, 120, 69, -586, +-469, -735, -748, -332, -597, 295, -243, 575, +139, 355, 439, -107, 605, -468, 582, -415, +335, -49, -44, 372, -477, 484, -738, 240, +-696, -172, -306, -500, 354, -417, 981, -77, +1084, 360, 536, 565, -320, 337, -1029, -112, +-1032, -544, -447, -618, 294, -272, 820, 313, +848, 710, 480, 653, -31, 162, -450, -476, +-588, -819, -443, -637, -167, -23, 125, 555, +397, 744, 567, 462, 473, -94, 98, -472, +-361, -409, -604, -139, -432, 89, 1, 138, +361, -26, 437, -95, 247, 8, -26, 173, +-124, 300, -53, 250, 1, 20, 20, -294, +-107, -483, -253, -430, -132, -89, 155, 351, +393, 572, 433, 423, 151, 44, -267, -286, +-474, -365, -276, -160, 34, 19, 283, 32, +346, -71, 119, -160, -97, -56, -126, 200, +-13, 450, 119, 477, 99, 207, -68, -280, +-180, -740, -123, -811, 78, -410, 206, 312, +152, 878, 67, 984, -17, 517, -12, -266, +0, -813, -77, -898, -111, -443, -111, 170, +-4, 549, 136, 510, 223, 209, 264, -32, +165, -52, -119, 58, -354, 12, -340, -231, +-103, -506, 256, -519, 448, -100, 360, 474, +69, 830, -295, 686, -418, 72, -270, -562, +85, -834, 418, -625, 385, -48, 142, 512, +-179, 683, -378, 444, -305, -73, -52, -458, +304, -462, 530, -119, 414, 296, -56, 399, +-553, 125, -696, -272, -296, -466, 382, -261, +837, 219, 733, 529, 121, 446, -573, 45, +-947, -371, -631, -486, 117, -267, 801, 41, +945, 262, 418, 274, -300, 152, -731, 17, +-644, -63, -153, -112, 332, -114, 509, -109, +372, -84, 48, 50, -177, 176, -160, 189, +-54, 37, 47, -152, -2, -271, -117, -135, +-93, 159, 26, 355, 188, 265, 244, -73, +147, -387, 21, -467, -84, -118, -126, 328, +-149, 507, -145, 340, -112, -134, -2, -479, +219, -423, 384, -13, 450, 396, 200, 477, +-255, 121, -609, -403, -635, -580, -253, -276, +269, 328, 709, 714, 756, 546, 411, -83, +-148, -673, -665, -738, -794, -271, -446, 420, +163, 729, 634, 415, 672, -203, 335, -602, +-66, -429, -321, 142, -325, 616, -165, 506, +-47, -62, -9, -645, -26, -792, 38, -337, +254, 409, 435, 932, 372, 877, 0, 296, +-437, -540, -605, -1084, -438, -987, 29, -311, +500, 583, 668, 1135, 430, 952, -25, 193, +-383, -594, -454, -927, -253, -619, -6, 5, +149, 453, 170, 447, 157, 122, 214, -178, +222, -181, 97, 133, -110, 368, -368, 235, +-430, -219, -184, -639, 175, -612, 480, -83, +494, 572, 241, 782, -131, 471, -369, -167, +-382, -615, -224, -532, 57, -138, 241, 243, +283, 309, 220, 123, 132, -99, 26, -75, +-89, 75, -266, 162, -340, 82, -177, -154, +60, -301, 335, -236, 464, 69, 345, 333, +50, 367, -318, 124, -514, -259, -401, -446, +-50, -327, 321, 45, 451, 422, 369, 525, +149, 259, -96, -218, -248, -565, -316, -536, +-287, -124, -138, 336, 132, 531, 351, 373, +444, 29, 291, -248, -2, -310, -256, -192, +-412, -36, -310, 52, -132, 58, 117, 42, +315, 33, 366, 101, 314, 145, 101, 123, +-146, 16, -327, -155, -364, -283, -255, -273, +21, -90, 305, 133, 430, 289, 342, 258, +40, 122, -203, -8, -277, -58, -197, -46, +-34, -131, 70, -291, 104, -385, 36, -234, +-6, 227, 87, 710, 201, 809, 231, 342, +49, -438, -203, -971, -359, -867, -316, -231, +-69, 490, 207, 858, 408, 641, 399, 95, +201, -404, -93, -548, -311, -268, -371, 142, +-255, 334, -15, 110, 192, -276, 318, -447, +286, -183, 150, 392, -57, 778, -211, 631, +-194, -28, -103, -755, 33, -997, 133, -584, +95, 194, -29, 781, -134, 813, -68, 333, +193, -209, 427, -418, 352, -285, -72, -35, +-559, 12, -763, -167, -421, -307, 287, -154, +881, 254, 972, 665, 420, 725, -394, 304, +-951, -393, -890, -953, -286, -978, 406, -412, +799, 442, 672, 1026, 197, 969, -196, 334, +-373, -420, -342, -818, -202, -661, -73, -148, +46, 294, 156, 421, 281, 207, 294, -80, +172, -131, -39, 51, -264, 257, -322, 246, +-144, -46, 96, -415, 194, -532, 135, -295, +-25, 158, -49, 535, 76, 570, 197, 255, +205, -178, -30, -424, -294, -406, -406, -160, +-260, 89, 112, 185, 493, 160, 615, 72, +265, 22, -262, 24, -579, 48, -506, -15, +-79, -98, 368, -122, 548, -84, 347, 15, +-46, 68, -431, 34, -501, -38, -124, -37, +305, 23, 564, 161, 399, 267, -24, 172, +-379, -125, -563, -474, -381, -590, -15, -341, +398, 246, 708, 781, 632, 868, 160, 460, +-450, -305, -870, -944, -802, -1048, -210, -565, +536, 275, 1059, 978, 920, 1115, 159, 601, +-665, -232, -1006, -935, -602, -1053, 91, -530, +617, 237, 654, 800, 209, 814, -168, 354, +-336, -236, -211, -565, 118, -494, 219, -143, +92, 218, -129, 306, -221, 127, -79, -106, +132, -147, 241, 48, 112, 257, -54, 207, +-53, -129, 53, -437, 118, -425, 27, -56, +-169, 439, -305, 615, -200, 348, 114, -161, +425, -570, 486, -599, 205, -238, -236, 252, +-492, 552, -389, 529, -38, 206, 285, -225, +370, -498, 210, -478, -55, -212, -201, 138, +-124, 369, 65, 403, 157, 242, 119, 5, +-39, -207, -197, -282, -210, -257, -90, -198, +138, -68, 311, 118, 332, 348, 158, 471, +-112, 335, -326, -71, -386, -516, -175, -680, +132, -432, 352, 110, 339, 620, 125, 737, +-111, 370, -225, -209, -111, -623, 61, -598, +148, -154, 55, 305, -180, 473, -291, 281, +-141, -95, 218, -315, 550, -243, 564, 69, +134, 329, -503, 332, -803, 9, -561, -419, +36, -591, 616, -328, 776, 274, 446, 767, +-69, 762, -431, 183, -490, -573, -227, -937, +41, -685, 136, 17, 107, 675, 56, 844, +149, 491, 263, -119, 287, -601, 77, -659, +-310, -290, -579, 177, -480, 439, -7, 370, +499, 98, 704, -122, 445, -190, -114, -140, +-507, -68, -473, -22, -139, 16, 220, 67, +328, 113, 133, 128, -131, 62, -218, -53, +-32, -182, 272, -242, 366, -119, 156, 97, +-252, 291, -526, 349, -369, 182, 46, -139, +446, -407, 562, -472, 283, -248, -199, 168, +-498, 516, -390, 570, -7, 275, 372, -182, +419, -527, 134, -542, -207, -254, -391, 119, +-290, 367, 75, 399, 365, 278, 421, 90, +266, -112, -93, -283, -382, -362, -440, -290, +-286, -99, 28, 192, 372, 435, 514, 430, +383, 197, 48, -163, -311, -437, -464, -418, +-309, -128, 43, 149, 249, 263, 212, 205, +56, 35, -71, -33, 5, -3, 218, 17, +288, -14, 79, -108, -305, -194, -558, -153, +-435, 28, -18, 193, 468, 262, 694, 184, +529, -33, 76, -191, -385, -207, -603, -117, +-491, 8, -173, 102, 159, 62, 399, 14, +461, 55, 351, 93, 86, 100, -173, -16, +-339, -172, -357, -247, -204, -100, 17, 143, +216, 244, 238, 172, 115, -60, 51, -228, +122, -155, 188, 93, 83, 244, -224, 155, +-521, -133, -492, -363, -98, -238, 424, 118, +752, 409, 644, 391, 96, 15, -533, -402, +-797, -469, -494, -154, 128, 315, 562, 530, +524, 258, 111, -244, -254, -557, -290, -386, +-83, 126, 183, 535, 313, 521, 139, 106, +-223, -364, -445, -526, -315, -317, 69, 36, +427, 297, 486, 314, 230, 226, -84, 122, +-296, -18, -343, -187, -195, -390, 13, -408, +116, -131, 140, 316, 102, 610, 124, 509, +218, 30, 191, -495, 8, -656, -290, -356, +-501, 193, -399, 554, -45, 459, 387, 36, +666, -362, 572, -400, 172, -79, -387, 254, +-734, 303, -605, 41, -135, -254, 381, -299, +632, -42, 496, 289, 127, 371, -236, 120, +-403, -269, -305, -461, -98, -303, 137, 119, +221, 480, 167, 497, 51, 162, -87, -302, +-67, -562, 19, -470, 108, -73, 126, 367, +-16, 572, -189, 461, -283, 73, -200, -381, +147, -600, 480, -427, 476, 24, 150, 438, +-363, 494, -648, 169, -450, -222, 81, -341, +588, -70, 662, 270, 245, 301, -344, -82, +-658, -554, -436, -595, 125, -36, 550, 722, +514, 1033, 81, 515, -372, -525, -499, -1215, +-158, -1029, 299, -32, 446, 1040, 220, 1294, +-227, 553, -501, -577, -290, -1225, 224, -920, +579, 115, 501, 1014, 1, 1066, -554, 302, +-710, -688, -356, -1129, 268, -688, 744, 262, +760, 979, 259, 964, -433, 300, -788, -553, +-641, -979, -117, -740, 470, -50, 675, 622, +467, 848, 41, 517, -346, -123, -407, -604, +-182, -640, 57, -232, 146, 268, 68, 463, +-69, 254, -73, -82, 118, -263, 309, -126, +280, 156, 31, 246, -331, 52, -499, -259, +-335, -407, 37, -231, 410, 217, 556, 539, +354, 506, -9, 89, -312, -449, -439, -672, +-321, -444, -106, 73, 128, 530, 291, 645, +348, 368, 279, -103, 83, -493, -168, -599, +-380, -335, -381, 138, -182, 484, 102, 474, +387, 141, 477, -216, 309, -329, -60, -120, +-440, 129, -528, 135, -261, -81, 155, -297, +455, -218, 451, 125, 185, 486, -183, 536, +-405, 176, -339, -376, -18, -739, 309, -632, +366, -119, 137, 519, -189, 845, -344, 612, +-214, 19, 126, -551, 348, -752, 312, -477, +18, 46, -326, 436, -376, 501, -127, 318, +229, 25, 394, -187, 200, -264, -116, -267, +-270, -174, -196, -16, 47, 183, 232, 295, +178, 228, -36, 37, -245, -146, -246, -226, +53, -199, 355, -64, 344, 78, 46, 167, +-279, 175, -369, 92, -198, -34, 88, -113, +260, -129, 250, -90, 117, -42, -86, 41, +-174, 113, -116, 152, -4, 124, 75, 10, +60, -130, 20, -230, -35, -180, -49, -11, +-18, 184, 18, 259, 95, 205, 145, 34, +92, -168, -70, -272, -235, -282, -269, -126, +-79, 178, 190, 422, 362, 397, 324, 69, +13, -329, -280, -508, -340, -309, -191, 114, +97, 424, 259, 392, 184, 74, -13, -247, +-139, -338, -112, -152, 46, 135, 234, 261, +157, 136, -99, -75, -290, -198, -293, -142, +-52, 19, 274, 155, 410, 167, 267, 46, +-62, -66, -350, -110, -398, -90, -130, -44, +229, 5, 350, 28, 191, 53, -94, 100, +-274, 102, -168, 29, 124, -60, 279, -140, +195, -180, -58, -122, -278, 46, -291, 235, +-96, 301, 156, 149, 262, -137, 234, -369, +68, -323, -62, -9, -79, 294, -94, 376, +-107, 167, -180, -174, -182, -364, 23, -252, +307, 21, 482, 293, 348, 328, -90, 144, +-489, -121, -590, -331, -334, -331, 154, -86, +538, 213, 536, 385, 211, 310, -215, 13, +-400, -272, -193, -387, 82, -239, 130, 45, +-58, 285, -206, 340, -121, 153, 143, -153, +395, -311, 403, -221, 129, 42, -278, 285, +-516, 276, -435, -13, -80, -362, 313, -430, +441, -86, 292, 463, 97, 667, -41, 275, +-167, -401, -261, -795, -311, -508, -236, 187, +66, 662, 397, 568, 446, 106, 250, -351, +-98, -461, -346, -203, -330, 103, -89, 222, +94, 154, 112, -59, 58, -182, 19, -84, +113, 135, 192, 313, 87, 239, -157, -75, +-311, -490, -273, -606, 6, -221, 315, 459, +436, 890, 232, 660, -219, -136, -548, -890, +-440, -921, 79, -268, 587, 574, 592, 900, +100, 462, -467, -259, -649, -611, -281, -372, +239, 143, 537, 369, 457, 108, 79, -235, +-302, -284, -469, 22, -298, 321, 76, 315, +349, 45, 326, -211, 67, -295, -222, -158, +-264, 18, -42, 103, 141, 136, 149, 105, +48, 81, -27, 40, -28, -18, -12, -110, +-79, -199, -138, -174, -60, -27, 95, 195, +164, 296, 157, 200, 115, -61, 12, -295, +-199, -281, -355, -57, -231, 211, 100, 309, +374, 190, 351, -131, 81, -417, -163, -374, +-172, 32, -141, 507, -145, 627, -78, 181, +42, -473, 156, -746, 196, -399, 130, 229, +6, 576, -30, 472, -98, 72, -157, -252, +-133, -273, -43, -124, 48, 2, 69, -12, +91, -77, 142, -49, 206, 159, 80, 311, +-179, 212, -379, -100, -306, -375, 4, -277, +323, 30, 427, 271, 251, 210, -103, -60, +-395, -242, -418, -151, -113, 129, 343, 338, +470, 282, 174, -80, -275, -406, -467, -459, +-206, -148, 212, 337, 377, 547, 242, 281, +2, -200, -212, -460, -275, -263, -146, 208, +113, 433, 247, 143, 73, -393, -190, -545, +-248, -154, 35, 442, 373, 747, 401, 428, +53, -283, -362, -775, -517, -687, -369, -132, +74, 535, 508, 814, 552, 464, 216, -181, +-262, -655, -461, -637, -243, -159, 95, 415, +206, 640, 55, 365, -131, -168, -126, -571, +47, -502, 234, -41, 309, 426, 165, 557, +-148, 248, -468, -208, -474, -457, -95, -344, +322, -12, 421, 265, 189, 280, -72, 74, +-78, -105, 26, -136, 33, 23, -73, 133, +-173, 89, -173, -105, -175, -267, -123, -267, +143, -52, 491, 248, 623, 476, 273, 446, +-333, 74, -775, -424, -738, -765, -270, -592, +315, 18, 707, 694, 756, 914, 397, 519, +-208, -244, -563, -803, -599, -772, -343, -268, +-19, 368, 160, 636, 280, 447, 384, 31, +362, -288, 155, -321, -119, -128, -366, 75, +-475, 131, -334, 40, -42, -91, 294, -106, +507, -7, 415, 137, 33, 193, -326, 129, +-422, -45, -169, -188, 119, -229, 177, -166, +74, 20, -48, 197, -52, 275, 23, 155, +69, -70, 51, -231, 65, -197, 27, 9, +-49, 157, -197, 134, -179, -45, -64, -123, +92, -67, 235, 62, 157, 133, -2, 41, +-109, -108, -103, -118, -10, 52, 134, 205, +97, 199, -110, -73, -311, -410, -322, -474, +19, -121, 459, 428, 585, 767, 248, 582, +-237, -81, -558, -780, -515, -946, -162, -412, +199, 362, 419, 838, 400, 634, 189, 16, +-54, -389, -183, -311, -205, 9, -212, 120, +-239, -112, -130, -472, 74, -391, 326, 104, +466, 696, 292, 903, -31, 483, -334, -338, +-502, -987, -400, -1005, -8, -422, 377, 422, +481, 956, 268, 864, -110, 248, -320, -358, +-233, -673, -45, -515, 14, -68, 47, 287, +143, 265, 147, 2, 68, -175, -144, -88, +-242, 288, -119, 486, 78, 246, 234, -294, +165, -653, 52, -553, -38, -95, -165, 396, +-333, 558, -316, 417, -22, 101, 415, -179, +667, -335, 427, -336, -150, -210, -713, -14, +-746, 151, -282, 216, 358, 195, 733, 149, +514, 103, -48, -14, -410, -214, -373, -419, +-106, -369, 154, 26, 210, 499, 89, 562, +-130, 217, -256, -264, -210, -538, 174, -389, +498, -17, 356, 311, -31, 411, -431, 298, +-528, -37, -288, -337, 58, -394, 301, -195, +455, 80, 359, 294, 77, 364, -183, 220, +-292, -60, -330, -355, -367, -438, -124, -206, +280, 267, 563, 510, 431, 352, -89, -152, +-433, -542, -297, -444, 8, 63, 175, 585, +95, 619, -61, 100, -186, -572, -174, -780, +38, -407, 343, 295, 438, 825, 137, 756, +-344, 128, -586, -580, -373, -849, 64, -489, +402, 227, 405, 668, 179, 491, -127, 0, +-308, -323, -140, -272, 142, 0, 196, 134, +-23, 50, -301, -91, -353, -116, -75, -20, +332, 95, 466, 162, 315, 76, -10, -41, +-331, -132, -453, -135, -285, -39, 25, 152, +269, 205, 273, 44, 91, -223, -76, -367, +-45, -138, 120, 345, 137, 596, -134, 282, +-426, -329, -386, -752, -11, -493, 437, 187, +490, 763, 213, 680, -126, -3, -271, -655, +-262, -741, -161, -206, -36, 420, 107, 683, +107, 408, 13, -58, -15, -450, 110, -568, +229, -356, 87, 118, -199, 564, -365, 580, +-208, 127, 41, -385, 228, -483, 277, -144, +166, 262, -132, 256, -363, -78, -245, -384, +152, -279, 481, 228, 282, 713, -261, 637, +-609, -68, -430, -846, 122, -998, 545, -364, +647, 530, 282, 989, -299, 693, -729, 14, +-608, -567, -72, -761, 448, -410, 592, 249, +291, 644, -139, 437, -401, -187, -309, -640, +-35, -447, 275, 286, 292, 876, -19, 690, +-378, -130, -396, -961, -19, -1171, 383, -417, +498, 799, 229, 1436, -234, 951, -520, -263, +-417, -1325, -87, -1293, 266, -239, 438, 983, +288, 1393, 39, 633, -247, -681, -394, -1466, +-242, -1012, 103, 394, 301, 1550, 203, 1415, +-71, 92, -258, -1381, -189, -1773, 20, -778, +214, 856, 247, 1818, 155, 1353, -114, -162, +-425, -1457, -413, -1527, -27, -390, 344, 991, +445, 1421, 210, 667, -177, -590, -398, -1342, +-279, -928, -14, 308, 227, 1339, 238, 1318, +8, 157, -172, -1243, -127, -1666, 71, -769, +98, 740, 22, 1719, -76, 1376, -105, -61, +-108, -1392, -82, -1533, 20, -496, 132, 854, +240, 1391, 85, 752, -139, -431, -234, -1135, +-175, -878, -74, 51, 75, 949, 249, 1062, +181, 325, 26, -722, -177, -1137, -201, -667, +-166, 261, -78, 934, 41, 837, 197, 146, +342, -567, 192, -692, -197, -276, -519, 349, +-380, 547, -23, 144, 337, -444, 467, -614, +352, -80, -105, 581, -539, 822, -561, 365, +-206, -427, 339, -954, 552, -730, 362, 34, +-56, 769, -381, 908, -496, 259, -281, -473, +234, -779, 576, -352, 420, 297, -163, 660, +-653, 391, -648, -184, -100, -668, 544, -669, +757, -12, 525, 713, -198, 1008, -832, 436, +-877, -457, -308, -1097, 449, -920, 863, -89, +695, 794, 26, 1096, -517, 610, -715, -228, +-460, -929, 2, -833, 346, -167, 428, 584, +257, 754, 67, 325, -196, -339, -304, -714, +-224, -421, 13, 246, 146, 809, 50, 661, +-78, -56, -132, -861, 82, -989, 128, -348, +34, 618, -118, 1124, -91, 762, -2, -80, +89, -858, 23, -930, -153, -367, -149, 387, +-151, 744, 64, 513, 169, -18, 233, -456, +117, -513, -67, -151, -207, 359, -280, 586, +-229, 341, -131, -262, 66, -792, 210, -725, +383, 0, 315, 827, 92, 1105, -285, 526, +-581, -529, -480, -1206, -161, -901, 260, 77, +363, 902, 376, 871, 236, 160, 61, -505, +-201, -549, -465, -95, -429, 335, -180, 422, +125, 45, 212, -375, 218, -616, 133, -385, +212, 198, 92, 904, -182, 1067, -331, 393, +-365, -667, -270, -1513, -89, -1334, 206, -126, +432, 1331, 492, 1855, 228, 1095, -265, -519, +-547, -1755, -415, -1604, -130, -269, 63, 1145, +202, 1503, 145, 694, 108, -653, 87, -1260, +73, -717, 51, 424, -80, 1199, -254, 890, +-448, -218, -330, -1265, 38, -1296, 427, -316, +532, 1050, 336, 1682, -189, 1107, -521, -429, +-463, -1671, -195, -1639, 186, -385, 333, 1167, +200, 1738, -79, 996, -242, -515, -137, -1451, +71, -1283, 246, -93, 142, 1121, -146, 1408, +-357, 519, -296, -829, -28, -1446, 139, -880, +244, 530, 140, 1485, -28, 1176, -105, -185, +-27, -1392, 22, -1422, 7, -221, -167, 1246, +-400, 1586, -346, 569, 39, -964, 524, -1667, +706, -944, 380, 655, -290, 1669, -892, 1233, +-888, -231, -188, -1556, 578, -1502, 859, -196, +450, 1324, -262, 1594, -618, 534, -402, -933, +66, -1573, 374, -765, 294, 618, -114, 1434, +-566, 925, -608, -374, -52, -1432, 704, -1127, +910, 238, 395, 1505, -581, 1559, -1080, 47, +-717, -1618, 84, -2024, 684, -589, 684, 1482, +275, 2399, -340, 1237, -621, -1049, -424, -2455, +156, -1796, 561, 421, 413, 2229, -239, 2159, +-769, 243, -620, -1776, 94, -2340, 752, -987, +782, 1166, 276, 2346, -505, 1660, -927, -362, +-675, -2031, 48, -2136, 626, -480, 628, 1438, +133, 2137, -330, 1132, -377, -601, -146, -1763, +50, -1510, 55, -81, 64, 1169, -24, 1498, +-67, 614, -110, -565, -116, -1200, 45, -837, +22, 45, 0, 619, 68, 639, 178, 249, +143, -29, -156, -68, -513, -21, -490, -175, +-78, -503, 353, -700, 527, -321, 409, 496, +126, 1280, -313, 1351, -623, 333, -652, -1155, +-200, -2013, 393, -1456, 581, 104, 344, 1677, +-28, 2050, -348, 969, -343, -599, -24, -1504, +165, -1213, 104, -311, -210, 478, -422, 536, +-256, 154, 241, 12, 589, 239, 421, 555, +32, 522, -481, -5, -749, -917, -546, -1364, +177, -899, 695, 223, 592, 1323, 45, 1684, +-536, 861, -569, -504, -224, -1380, 249, -1310, +392, -340, 340, 679, -23, 862, -537, 246, +-662, -370, -229, -364, 385, 300, 662, 868, +455, 607, -26, -441, -504, -1300, -641, -1235, +-405, -264, -42, 928, 345, 1529, 423, 974, +196, -143, 64, -1017, 66, -986, -96, -216, +-477, 468, -682, 439, -390, -195, 230, -536, +741, -224, 793, 617, 289, 1150, -504, 731, +-936, -406, -848, -1447, -42, -1482, 758, -309, +928, 1081, 210, 1677, -568, 930, -830, -456, +-507, -1393, 293, -1161, 811, 92, 744, 1206, +-41, 1185, -897, 128, -1197, -1166, -500, -1510, +612, -493, 1228, 970, 882, 1695, -133, 1109, +-996, -304, -1065, -1411, -362, -1463, 495, -461, +766, 779, 390, 1300, -301, 793, -618, -325, +-317, -935, 264, -670, 491, 206, 226, 789, +-291, 627, -712, -173, -455, -770, 233, -744, +675, -128, 450, 626, -119, 857, -728, 369, +-701, -410, -8, -746, 632, -412, 834, 312, +428, 756, -522, 643, -1268, -301, -1087, -1142, +-16, -1095, 1116, -232, 1349, 1102, 661, 1829, +-433, 1155, -1201, -402, -1083, -1692, -421, -1830, +379, -802, 901, 784, 703, 1709, -25, 1358, +-567, 114, -550, -960, -115, -1121, 287, -393, +333, 625, 153, 897, -312, 202, -704, -732, +-544, -1117, 61, -672, 819, 582, 1008, 1575, +242, 1536, -710, 288, -1022, -1212, -643, -1826, +58, -1360, 604, -26, 614, 1255, 199, 1533, +-472, 872, -610, -122, -157, -882, 464, -818, +721, -196, 209, 259, -617, 178, -1110, -196, +-831, -350, 57, -126, 1047, 428, 1448, 900, +739, 792, -579, 89, -1560, -868, -1373, -1358, +-312, -1006, 794, 44, 1287, 1037, 723, 1367, +-229, 838, -867, -108, -616, -771, -71, -849, +444, -515, 285, -80, -294, 158, -537, 53, +-266, 265, 320, 601, 555, 790, 491, 407, +-62, -404, -606, -1206, -684, -1346, -351, -451, +182, 752, 488, 1613, 277, 1311, -100, 90, +-230, -1189, -52, -1480, 278, -690, 197, 476, +-201, 1114, -635, 838, -828, 143, -229, -735, +642, -913, 1226, -343, 844, 439, -245, 809, +-1198, 535, -1282, -130, -643, -593, 417, -381, +1135, -130, 907, 123, 240, -21, -707, -70, +-865, 104, -309, 497, 316, 807, 365, 366, +-111, -625, -548, -1470, -445, -1297, 223, -168, +822, 1445, 1016, 2109, 190, 1364, -1003, -484, +-1586, -2130, -1093, -2369, 249, -944, 1368, 1312, +1625, 2606, 678, 2092, -588, 45, -1505, -1948, +-1405, -2498, -395, -1429, 629, 629, 1090, 2183, +695, 2167, 103, 788, -395, -1085, -438, -2097, +-285, -1599, -82, -200, -271, 1031, -571, 1528, +-252, 1016, 472, 120, 1281, -616, 1114, -891, +26, -647, -1285, -264, -1905, 39, -1305, 262, +55, 505, 1559, 579, 2146, 395, 1436, -18, +-338, -358, -1889, -559, -2349, -508, -1343, -282, +389, 73, 1770, 375, 2070, 523, 1064, 426, +-355, 178, -1619, 31, -1707, -180, -994, -489, +152, -728, 1026, -692, 1108, -108, 874, 753, +260, 1384, -502, 1246, -1034, 199, -1076, -1173, +-662, -2002, 131, -1496, 844, 2, 1024, 1626, +741, 2225, 106, 1435, -639, -237, -1167, -1841, +-1024, -2278, -426, -1299, 481, 578, 1062, 2043, +986, 2060, 385, 763, -450, -985, -806, -1813, +-800, -1356, -352, -74, -68, 1098, 288, 1120, +256, 372, 179, -546, 347, -799, 374, -128, +405, 657, -163, 884, -943, 261, -1550, -809, +-1047, -1490, 342, -1073, 1674, 329, 2077, 1731, +1041, 2038, -674, 885, -2232, -1014, -2391, -2303, +-1026, -2070, 1045, -332, 2565, 1507, 2222, 2384, +350, 1639, -1797, -262, -2631, -1876, -1624, -2155, +482, -822, 2156, 897, 2128, 1972, 498, 1619, +-1393, 124, -2064, -1497, -1276, -2027, 335, -1029, +1432, 762, 1357, 2075, 410, 1774, -751, 76, +-1347, -1578, -853, -2003, 289, -1040, 1005, 586, +900, 1758, -178, 1778, -1090, 521, -1013, -1013, +-112, -1893, 914, -1613, 1130, -102, 498, 1490, +-599, 2109, -1200, 1287, -976, -290, -25, -1767, +751, -2107, 777, -1092, 287, 410, -362, 1851, +-434, 2094, -195, 1187, 94, -466, 241, -1907, +19, -2200, -387, -1178, -543, 650, -281, 2126, +175, 2159, 609, 706, 521, -1228, 283, -2239, +-152, -1515, -550, 278, -698, 1836, -591, 1960, +-80, 475, 274, -1432, 473, -2243, 554, -1426, +471, 669, 95, 2432, -457, 2513, -938, 671, +-756, -1789, -163, -3061, 399, -2277, 700, 107, +496, 2507, 199, 3142, -308, 1733, -654, -837, +-546, -2885, -145, -2809, 498, -765, 615, 1754, +283, 2762, -342, 1772, -939, -443, -835, -2212, +-212, -2244, 793, -667, 1411, 1407, 986, 2405, +-79, 1721, -1227, -221, -1754, -1982, -1339, -2371, +-126, -1296, 1324, 589, 1988, 1966, 1540, 2188, +72, 1203, -1480, -325, -2074, -1511, -1332, -1907, +-39, -1391, 1143, -460, 1493, 596, 734, 1576, +-155, 1950, -697, 1596, -549, 337, -172, -1378, +-4, -2546, -114, -2553, -451, -1114, -478, 1113, +123, 2937, 832, 3226, 1115, 1692, 685, -877, +-485, -2965, -1454, -3425, -1512, -2025, -740, 559, +549, 2624, 1521, 3283, 1586, 2153, 753, -205, +-658, -2171, -1663, -2846, -1677, -1967, -727, -158, +580, 1536, 1362, 2273, 1388, 1768, 669, 473, +-209, -954, -1005, -1747, -1401, -1539, -1143, -592, +-370, 455, 729, 1126, 1473, 1216, 1567, 826, +743, 217, -757, -421, -2032, -1165, -2101, -1489, +-824, -1104, 1185, 24, 2478, 1700, 2049, 2453, +288, 1715, -1867, -244, -2736, -2328, -1882, -3244, +317, -1930, 2534, 621, 2796, 2896, 1124, 3559, +-1368, 1799, -3095, -981, -2516, -3112, -175, -3269, +2138, -1382, 3007, 1201, 1657, 2787, -848, 2534, +-2611, 746, -2519, -1258, -680, -2016, 1460, -1393, +2379, -6, 1594, 1039, -300, 905, -1865, 174, +-1904, -557, -648, -454, 893, 141, 1560, 716, +1155, 670, 76, -5, -1127, -825, -1368, -1245, +-901, -682, 144, 366, 1092, 1328, 1132, 1585, +583, 595, -268, -940, -849, -1723, -1177, -1586, +-866, -214, 81, 1338, 1072, 1926, 1343, 1341, +675, 51, -442, -1379, -1284, -2027, -1259, -1492, +-493, -205, 507, 1341, 1249, 2249, 1197, 1930, +205, 480, -967, -1385, -1408, -2540, -755, -2178, +279, -606, 977, 1261, 952, 2346, 269, 2130, +-604, 818, -1039, -687, -641, -1892, 215, -2035, +879, -1106, 808, 210, -130, 1391, -819, 1655, +-835, 1071, -306, 135, 567, -731, 846, -940, +452, -741, -355, -313, -868, -33, -492, -18, +177, 126, 627, 480, 465, 951, -271, 968, +-761, 396, -654, -670, -6, -1621, 825, -1707, +1205, -783, 491, 764, -777, 2026, -1607, 2156, +-1287, 1010, 4, -814, 1281, -2114, 1699, -2201, +891, -1097, -472, 586, -1593, 1957, -1659, 2084, +-481, 1110, 1033, -238, 1681, -1515, 964, -1953, +-381, -1214, -1322, -118, -1350, 1068, -437, 1760, +737, 1419, 1288, 414, 944, -729, -20, -1422, +-931, -1489, -1064, -736, -596, 227, -40, 1124, +415, 1478, 610, 1150, 542, 233, 397, -849, +51, -1410, -302, -1428, -630, -628, -872, 543, +-708, 1289, -226, 1386, 667, 787, 1326, -181, +1266, -849, 409, -965, -885, -805, -1667, -355, +-1583, 148, -522, 452, 852, 695, 1673, 865, +1590, 621, 458, 16, -1056, -578, -1769, -1032, +-1213, -1004, -36, -404, 1079, 193, 1240, 760, +444, 1095, -481, 738, -937, 263, -587, -360, +182, -750, 773, -762, 692, -568, -108, -206, +-957, 134, -1144, 422, -485, 604, 683, 632, +1590, 644, 1457, 343, 231, -273, -1361, -991, +-2332, -1506, -1896, -1193, -87, -105, 2016, 1182, +3018, 1989, 2150, 1804, -253, 532, -2712, -1122, +-3652, -2133, -2234, -1872, 559, -656, 3065, 850, +3799, 1530, 2036, 1317, -885, 589, -3212, -127, +-3591, -481, -1669, -479, 1104, -418, 2897, -628, +2789, -857, 1010, -596, -1194, 309, -2438, 1461, +-1970, 2061, -246, 1434, 1474, -275, 1839, -2052, +780, -2770, -856, -1913, -1849, 229, -1261, 2208, +290, 2846, 1789, 1794, 2154, -69, 887, -1563, +-1125, -2020, -2677, -1485, -2663, -575, -851, 133, +1604, 804, 3194, 1334, 2947, 1660, 910, 1495, +-1700, 390, -3400, -1340, -3254, -2714, -1166, -2770, +1541, -1228, 3310, 1156, 3054, 3055, 1058, 3566, +-1300, 2057, -2690, -549, -2474, -3015, -1050, -3979, +750, -2639, 1718, 52, 1595, 2667, 803, 3730, +-50, 2671, -530, 317, -794, -1945, -978, -2922, +-905, -2225, -407, -534, 365, 1074, 1251, 1852, +1431, 1560, 924, 630, -202, -418, -1580, -991, +-1993, -1000, -1286, -461, 437, 183, 2038, 552, +2326, 624, 1041, 246, -1035, -226, -2506, -626, +-2414, -706, -655, -298, 1562, 492, 2782, 1229, +2188, 1355, 201, 600, -1911, -715, -2828, -2068, +-2023, -2328, -203, -1218, 1665, 789, 2712, 2649, +2249, 3245, 550, 2160, -1305, -352, -2697, -2832, +-2680, -4040, -1283, -3115, 768, -350, 2608, 2684, +2993, 4273, 1916, 3594, -301, 1031, -2206, -1953, +-3029, -3758, -2354, -3489, -508, -1590, 1395, 878, +2689, 2566, 2491, 2895, 1124, 1937, -546, 225, +-1742, -1212, -2116, -1952, -1740, -1809, -879, -1030, +365, 26, 1550, 779, 2253, 1404, 2126, 1480, +935, 909, -813, 40, -2562, -1077, -3281, -1544, +-2201, -1245, 217, -205, 2764, 951, 3923, 1363, +2727, 886, 30, -241, -2667, -1057, -3955, -910, +-2801, -138, -248, 843, 2333, 1115, 3417, 522, +2434, -299, 361, -1129, -1765, -1197, -2620, -589, +-2073, 237, -713, 952, 944, 1160, 2009, 999, +1914, 441, 968, -302, -423, -1022, -1545, -1452, +-1799, -1295, -1253, -573, -87, 479, 1123, 1512, +1670, 2043, 1335, 1611, 396, 326, -660, -1279, +-1304, -2302, -1328, -2180, -878, -964, -11, 513, +822, 1623, 1240, 1981, 1149, 1496, 539, 677, +-212, -195, -840, -1048, -1294, -1759, -1281, -2031, +-505, -1550, 396, -142, 1309, 1709, 1662, 3090, +1031, 2942, 33, 1155, -1145, -1376, -1787, -3407, +-1390, -3551, -356, -1702, 784, 944, 1523, 2930, +1394, 3105, 625, 1624, -385, -446, -1131, -1854, +-1280, -2001, -780, -1098, 59, 103, 690, 676, +910, 673, 690, 411, 202, 96, -302, 221, +-532, 331, -504, 107, -381, -319, -266, -653, +-30, -619, 329, -149, 716, 636, 1023, 767, +609, 282, -471, -549, -1500, -1135, -1876, -742, +-921, 458, 843, 1583, 2255, 1827, 2404, 745, +1084, -1095, -952, -2377, -2724, -2381, -2913, -1041, +-1450, 983, 875, 2367, 2802, 2662, 3002, 1845, +1740, 93, -411, -1656, -2221, -2813, -2748, -2702, +-2023, -1406, -478, 609, 1171, 2314, 2036, 2987, +1968, 2287, 1393, 657, 235, -1152, -903, -2347, +-1744, -2434, -2044, -1639, -1533, -319, -357, 888, +1008, 1652, 2007, 1808, 2286, 1539, 1569, 956, +169, 134, -1406, -993, -2338, -2113, -2319, -2817, +-1557, -2345, 20, -523, 1691, 1955, 2664, 4016, +2720, 4209, 1468, 2235, -569, -1172, -2428, -4261, +-3405, -5079, -2772, -3353, -716, 136, 1825, 3393, +3438, 4533, 3222, 3441, 1548, 857, -821, -1641, +-2523, -2769, -2926, -2535, -2155, -1505, -414, -486, +1280, 355, 2234, 1139, 2171, 1811, 1220, 2228, +-41, 1672, -1252, 238, -1781, -1607, -1517, -2910, +-800, -2786, 172, -1324, 938, 926, 1272, 2597, +1307, 2914, 846, 1816, -106, -96, -1027, -1604, +-1478, -2140, -1304, -1662, -482, -699, 624, 340, +1276, 958, 1354, 1200, 685, 1191, -376, 693, +-949, 43, -933, -622, -471, -1145, 110, -1196, +505, -626, 410, 121, 37, 735, -291, 942, +-274, 605, 319, 217, 749, 125, 772, 81, +37, -175, -1115, -700, -1746, -1318, -1458, -1324, +42, -312, 1869, 1268, 2804, 2515, 2069, 2387, +-44, 589, -2374, -1825, -3490, -3263, -2583, -2772, +-199, -610, 2361, 1842, 3561, 3157, 2879, 2630, +672, 779, -1802, -1340, -3051, -2471, -2772, -2065, +-1180, -784, 704, 596, 1970, 1118, 2238, 938, +1394, 593, 360, 459, -402, 586, -936, 405, +-1157, -279, -1461, -1381, -1458, -2139, -660, -1738, +675, -187, 2137, 1815, 2881, 3041, 2223, 2727, +160, 886, -2305, -1436, -3792, -3205, -3324, -3368, +-902, -1715, 2061, 769, 3828, 2869, 3574, 3325, +1313, 2001, -1577, -108, -3320, -1904, -3032, -2486, +-975, -1705, 1260, -384, 2351, 759, 1700, 1139, +48, 857, -1189, 444, -1246, 318, -168, 276, +1004, 192, 1363, -225, 504, -861, -1049, -1242, +-1903, -1107, -1581, -287, -284, 861, 1407, 1677, +2291, 1632, 1849, 680, 502, -629, -1115, -1496, +-2121, -1606, -1860, -769, -782, 450, 518, 1186, +1332, 1067, 1309, 289, 832, -678, 222, -879, +-212, -234, -443, 641, -587, 1139, -729, 784, +-761, -378, -491, -1557, 42, -1855, 769, -989, +1280, 706, 1167, 2101, 479, 2372, -447, 1254, +-1076, -590, -1183, -2029, -899, -2323, -289, -1416, +358, 153, 798, 1412, 977, 1758, 911, 1156, +496, 194, -38, -511, -694, -755, -1213, -458, +-1040, -242, -725, -258, 33, -328, 910, -372, +1224, -55, 1218, 382, 706, 907, -215, 1123, +-973, 815, -1371, 236, -1196, -747, -539, -1601, +326, -1765, 1159, -1230, 1337, 19, 929, 1449, +168, 2468, -524, 2285, -867, 939, -918, -853, +-587, -2500, -153, -2725, 253, -1729, 492, 3, +389, 1551, 445, 2272, 627, 2058, 550, 1018, +171, -57, -743, -1016, -1510, -1729, -1534, -1998, +-712, -1628, 874, -440, 2091, 1226, 2141, 2530, +899, 2628, -892, 1306, -2109, -707, -2014, -2209, +-872, -2432, 610, -1404, 1652, 223, 1705, 1240, +791, 1304, -473, 623, -1288, 29, -1315, 24, +-391, 295, 487, 510, 910, 15, 837, -977, +237, -1587, -412, -1482, -831, -314, -719, 1273, +-240, 2076, 389, 1792, 711, 534, 641, -825, +514, -1472, 116, -1215, -410, -668, -895, -80, +-1078, 198, -654, 146, 109, 421, 929, 807, +1408, 1113, 1139, 976, 338, 197, -600, -929, +-1293, -1696, -1309, -1681, -780, -955, -142, 261, +499, 1292, 1044, 1707, 1175, 1521, 986, 724, +519, -110, -310, -825, -1073, -1420, -1500, -1612, +-1478, -1413, -892, -567, 229, 672, 1489, 1852, +2285, 2432, 2172, 2014, 916, 632, -982, -1208, +-2606, -2685, -2982, -3003, -1860, -1899, 167, 89, +2108, 2028, 3024, 2993, 2404, 2564, 635, 1151, +-1155, -705, -2341, -2068, -2258, -2407, -1113, -1879, +181, -679, 1196, 527, 1532, 1506, 1082, 1871, +333, 1672, -179, 920, -358, -253, -437, -1302, +-424, -1863, -488, -1687, -649, -846, -402, 343, +88, 1415, 731, 1747, 1115, 1318, 955, 480, +390, -685, -596, -1291, -1117, -1211, -957, -674, +-406, 193, 416, 714, 643, 683, 286, 170, +-68, -238, -321, -316, 19, -19, 590, 475, +788, 668, 510, 477, -400, -136, -1247, -897, +-1409, -1427, -862, -1253, 221, -350, 1369, 1109, +1757, 2256, 1251, 2182, 168, 919, -1035, -1050, +-1514, -2624, -1226, -2640, -435, -1175, 332, 762, +662, 2185, 648, 2222, 541, 1033, 535, -293, +485, -1119, 92, -1114, -575, -540, -1064, -184, +-1075, -143, -643, -242, 201, -104, 999, 484, +1333, 1137, 988, 1246, 65, 651, -806, -506, +-1122, -1477, -677, -1669, 22, -892, 538, 282, +521, 1242, 136, 1416, -273, 790, -435, 13, +-207, -649, 292, -721, 785, -479, 836, -154, +310, -76, -562, -44, -1291, 71, -1404, 250, +-617, 603, 576, 562, 1569, 141, 1708, -386, +811, -714, -323, -645, -1259, -113, -1367, 458, +-794, 606, -70, 402, 565, -154, 654, -566, +418, -520, 163, -2, 155, 570, 398, 786, +506, 466, 76, -329, -702, -973, -1414, -1078, +-1394, -461, -512, 503, 829, 1213, 1902, 1149, +1960, 489, 1136, -512, -401, -1112, -1735, -942, +-2122, -393, -1571, 326, -258, 623, 1097, 460, +1896, 152, 1730, 51, 769, 74, -423, 127, +-1263, 29, -1370, -307, -835, -599, -64, -696, +510, -327, 659, 308, 485, 931, 351, 1133, +191, 629, 140, -274, -4, -994, -235, -1192, +-519, -759, -721, 114, -444, 757, 19, 940, +553, 612, 900, 66, 716, -296, 187, -358, +-361, -265, -692, -330, -625, -367, -273, -172, +174, 165, 334, 567, 318, 684, 221, 335, +-58, -161, -36, -503, 37, -536, 107, -222, +117, 145, -168, 244, -359, 84, -350, -99, +-75, -81, 268, 163, 470, 403, 340, 335, +28, -36, -154, -475, -223, -645, -113, -385, +29, 118, 11, 559, -45, 603, -96, 254, +-174, -242, 45, -469, 260, -261, 333, 98, +401, 366, 88, 290, -295, -141, -529, -542, +-512, -578, -136, -203, 231, 494, 478, 1021, +515, 906, 282, 149, -44, -753, -295, -1337, +-382, -1074, -253, -194, -48, 765, 86, 1344, +174, 1097, 198, 327, 156, -627, 45, -1122, +-70, -932, -28, -268, 14, 462, 8, 759, +62, 438, -77, -72, -229, -380, -232, -196, +-101, 360, 251, 649, 518, 271, 471, -589, +111, -1213, -299, -1021, -498, 38, -442, 1203, +-113, 1612, 190, 949, 318, -286, 362, -1320, +200, -1421, -6, -646, -35, 314, -133, 961, +-134, 861, -76, 310, -139, -196, 22, -418, +66, -292, 86, -14, 138, 152, 6, 42, +-19, -191, 48, -360, 223, -194, 335, 206, +146, 600, -319, 627, -746, 188, -785, -350, +-263, -770, 597, -702, 1314, -217, 1337, 408, +508, 803, -661, 686, -1645, 189, -1635, -440, +-555, -821, 641, -691, 1549, -171, 1507, 524, +567, 992, -343, 777, -950, 96, -910, -725, +-388, -1194, 111, -871, 245, -38, 140, 849, +73, 1275, 59, 968, 371, 53, 640, -820, +543, -1116, 79, -828, -702, -189, -1148, 348, +-942, 598, -170, 663, 730, 602, 1182, 352, +1006, -97, 352, -635, -333, -924, -693, -793, +-612, -249, -239, 504, -37, 938, -25, 840, +-58, 330, -76, -272, 289, -545, 804, -457, +957, -207, 592, -23, -268, -27, -1131, -124, +-1462, -96, -1021, 112, 23, 446, 1051, 744, +1603, 660, 1299, 109, 409, -657, -603, -1230, +-1219, -1273, -1099, -544, -614, 592, 129, 1529, +631, 1697, 661, 917, 552, -368, 309, -1433, +59, -1644, -96, -1060, -233, -26, -333, 908, +-311, 1282, -159, 1004, -85, 359, -1, -334, +212, -695, 324, -654, 394, -433, 434, -182, +236, 12, -82, 149, -311, 308, -566, 509, +-605, 507, -303, 283, 100, -167, 487, -576, +701, -671, 691, -396, 436, 50, 95, 353, +-433, 413, -829, 264, -821, 79, -593, -35, +44, -30, 661, -29, 1058, -89, 1089, -235, +553, -338, -248, -201, -1023, 111, -1207, 445, +-765, 497, 51, 188, 787, -214, 985, -501, +712, -366, 129, 34, -351, 389, -456, 482, +-270, 132, -74, -332, 50, -572, -8, -449, +-71, -42, 100, 438, 150, 672, 274, 566, +359, 191, 181, -321, -7, -695, -313, -678, +-535, -380, -389, 17, 78, 368, 566, 504, +651, 592, 355, 565, -171, 302, -620, -223, +-551, -836, -99, -1119, 475, -818, 817, -7, +529, 818, -142, 1142, -726, 867, -822, 247, +-272, -312, 460, -554, 875, -584, 762, -491, +96, -383, -579, -210, -720, 98, -405, 388, +190, 701, 706, 883, 649, 770, 101, 237, +-455, -636, -732, -1496, -465, -1725, 216, -974, +793, 431, 930, 1784, 556, 2200, -194, 1391, +-864, -179, -1037, -1549, -682, -1972, 109, -1265, +834, -40, 1073, 889, 850, 1108, 278, 643, +-321, 93, -679, -101, -794, 69, -612, 234, +-186, 32, 217, -507, 504, -1077, 795, -1085, +845, -318, 638, 760, 127, 1613, -652, 1664, +-1225, 631, -1233, -750, -589, -1696, 366, -1697, +1292, -685, 1638, 594, 1161, 1329, 34, 1200, +-1114, 470, -1498, -336, -1060, -723, -60, -593, +786, -160, 1041, 217, 671, 326, 29, 119, +-333, -196, -330, -353, 42, -216, 361, 122, +248, 450, -164, 552, -623, 346, -683, -40, +-186, -493, 500, -731, 1049, -580, 982, -173, +349, 366, -450, 744, -989, 697, -816, 371, +-247, -140, 349, -557, 673, -664, 503, -427, +156, 22, -74, 365, -152, 458, -13, 208, +112, -139, 88, -272, 44, -96, -124, 304, +-258, 535, -299, 271, -205, -385, 123, -992, +520, -966, 824, -176, 723, 838, 283, 1450, +-434, 1142, -1154, 64, -1178, -1051, -582, -1521, +386, -1088, 1307, 4, 1454, 1000, 884, 1274, +39, 821, -907, -8, -1297, -707, -931, -890, +-246, -582, 595, -49, 911, 435, 722, 578, +399, 397, 14, 64, -156, -233, -273, -342, +-300, -309, -246, -165, -250, 63, -127, 307, +126, 408, 418, 292, 591, -11, 501, -392, +227, -589, -191, -406, -488, 51, -487, 473, +-385, 666, -51, 430, 392, -33, 599, -417, +561, -614, 227, -491, -207, -71, -397, 345, +-358, 548, -92, 406, 231, 31, 356, -226, +236, -227, -28, -81, -222, -47, -209, -135, +34, -223, 271, -165, 387, 149, 317, 520, +72, 608, -257, 294, -466, -315, -368, -830, +-56, -807, 354, -182, 561, 488, 436, 819, +212, 637, -81, 62, -307, -394, -317, -551, +-195, -371, -24, -66, 73, 114, 198, 218, +299, 205, 326, 177, 318, 151, 119, 1, +-224, -203, -442, -331, -406, -193, -155, 47, +282, 283, 602, 321, 521, 14, 111, -300, +-244, -383, -343, -132, -192, 316, 102, 624, +231, 465, 199, -117, 66, -661, -87, -897, +-171, -526, -44, 238, 208, 904, 384, 1142, +319, 611, 4, -318, -311, -1036, -438, -1171, +-219, -577, 195, 339, 477, 906, 513, 849, +228, 374, -159, -177, -338, -409, -339, -271, +-97, -155, 155, -206, 313, -309, 354, -269, +226, 76, 160, 606, -103, 931, -400, 643, +-465, -84, -238, -915, 317, -1300, 785, -796, +814, 182, 313, 1069, -412, 1301, -904, 684, +-836, -314, -238, -997, 628, -1036, 1142, -419, +890, 415, 137, 825, -610, 641, -901, 45, +-531, -498, 138, -537, 666, -145, 686, 284, +130, 386, -438, 62, -474, -269, 61, -244, +655, 54, 749, 354, 179, 266, -631, -231, +-1050, -542, -638, -394, 306, 154, 1090, 742, +1214, 751, 496, 178, -505, -582, -982, -937, +-717, -675, -49, -40, 481, 614, 572, 832, +341, 649, 18, 199, -108, -314, -88, -655, +24, -764, 108, -519, 28, -39, -20, 442, +-5, 803, 52, 818, 11, 485, -50, -148, +-43, -735, 124, -1048, 274, -919, 284, -177, +192, 647, -18, 1173, -158, 1138, -310, 414, +-277, -538, -38, -1115, 242, -1010, 410, -365, +316, 371, 134, 710, -6, 505, 20, 134, +40, -61, -64, 31, -188, 153, -366, 40, +-336, -349, 54, -722, 525, -634, 870, -87, +768, 616, 140, 1021, -555, 848, -939, 167, +-799, -602, -139, -986, 601, -857, 911, -236, +651, 470, 92, 796, -359, 657, -326, 120, +36, -413, 220, -544, 190, -230, -167, 283, +-473, 499, -396, 195, -87, -418, 522, -799, +1013, -550, 930, 205, 359, 959, -490, 1091, +-1113, 502, -1143, -444, -527, -1128, 427, -1054, +1104, -339, 1186, 471, 605, 865, -110, 661, +-527, 118, -534, -275, -246, -301, -120, -81, +-148, 104, -121, 60, 42, -228, 360, -513, +745, -421, 798, -6, 484, 631, -58, 1011, +-768, 752, -1066, 3, -874, -851, -200, -1174, +641, -798, 1177, 12, 1165, 714, 575, 843, +-177, 470, -742, -11, -838, -196, -502, -64, +-47, 52, 201, -55, 216, -520, 300, -810, +483, -545, 622, 146, 547, 1019, 126, 1400, +-429, 950, -886, -106, -947, -1156, -496, -1594, +275, -1165, 1015, -16, 1222, 1011, 860, 1370, +157, 988, -601, 119, -950, -615, -864, -816, +-321, -524, 320, -113, 605, 154, 676, 131, +455, -55, 190, -79, 36, 162, -200, 513, +-313, 654, -352, 360, -298, -313, -44, -982, +173, -1076, 398, -511, 560, 405, 426, 1029, +169, 1052, -171, 542, -436, -209, -483, -757, +-281, -877, 111, -600, 397, -6, 600, 588, +489, 742, 85, 464, -295, -42, -574, -494, +-428, -555, 143, -180, 564, 230, 626, 475, +263, 345, -274, -67, -498, -400, -426, -450, +-10, -200, 442, 142, 620, 414, 480, 473, +-55, 250, -466, -128, -522, -434, -180, -506, +304, -253, 474, 188, 462, 444, 145, 400, +-286, 83, -426, -304, -264, -417, 208, -166, +544, 231, 453, 409, 78, 278, -288, -83, +-399, -374, -227, -385, 73, -192, 304, 75, +372, 247, 219, 394, 42, 350, -51, 119, +-17, -112, -2, -417, -107, -487, -141, -296, +-128, -20, 59, 292, 258, 425, 331, 397, +311, 248, 148, -3, 0, -236, -153, -478, +-221, -513, -294, -295, -248, 134, 28, 539, +291, 615, 553, 361, 499, -148, 255, -487, +23, -419, -299, -66, -469, 233, -528, 174, +-295, -135, 146, -364, 571, -150, 776, 368, +615, 688, 252, 573, -273, -58, -651, -785, +-697, -988, -401, -502, 87, 285, 451, 897, +644, 895, 672, 260, 467, -411, 25, -673, +-526, -456, -797, 26, -579, 330, -31, 242, +494, -76, 690, -235, 592, -88, 252, 220, +-174, 436, -388, 305, -382, -98, -217, -524, +20, -625, 229, -272, 410, 291, 402, 666, +194, 560, -117, 41, -413, -442, -379, -494, +-72, -174, 301, 206, 553, 347, 514, 140, +125, -183, -370, -338, -592, -198, -400, 142, +71, 422, 452, 421, 588, 129, 425, -268, +45, -564, -232, -519, -341, -140, -264, 360, +-20, 692, 104, 541, 109, 23, 177, -501, +202, -586, 190, -263, 246, 157, 148, 428, +-89, 242, -356, -82, -476, -276, -187, -206, +267, 170, 601, 411, 499, 276, 79, -146, +-209, -545, -293, -537, -88, -86, 162, 487, +216, 706, 42, 443, -256, -176, -270, -745, +63, -680, 380, -146, 514, 498, 264, 792, +-123, 457, -217, -189, -246, -639, -136, -589, +28, -203, 9, 278, 63, 489, 123, 342, +234, 86, 413, -56, 375, -118, 105, -160, +-330, -212, -593, -305, -573, -279, -204, 7, +385, 407, 757, 702, 793, 658, 385, 151, +-183, -585, -552, -1074, -557, -877, -279, -154, +-5, 683, 207, 1086, 254, 782, 284, 103, +350, -480, 421, -663, 337, -512, -94, -189, +-591, 44, -858, 118, -612, 222, 115, 303, +807, 343, 1121, 259, 866, 26, 113, -237, +-696, -411, -1042, -433, -755, -293, -83, -33, +522, 215, 726, 417, 635, 483, 338, 347, +3, 119, -298, -176, -469, -465, -373, -574, +-143, -491, 101, -209, 237, 233, 366, 632, +389, 773, 288, 573, 103, 69, -217, -477, +-353, -800, -372, -757, -253, -377, 85, 156, +377, 615, 507, 752, 426, 532, 153, 115, +-141, -328, -307, -526, -327, -419, -275, -207, +-94, 21, 141, 93, 429, 77, 570, 108, +427, 204, 55, 341, -380, 325, -571, 140, +-453, -217, -75, -617, 306, -763, 567, -478, +550, 175, 283, 814, -57, 1052, -366, 609, +-499, -236, -345, -877, -46, -945, 275, -415, +556, 325, 529, 724, 231, 567, -117, 77, +-441, -373, -506, -455, -264, -190, 119, 210, +482, 404, 546, 272, 327, -70, -32, -350, +-350, -395, -346, -172, -143, 164, 72, 314, +160, 265, 154, 108, 95, -35, 128, -132, +232, -95, 221, -59, 27, -71, -318, -89, +-528, -124, -410, -46, 149, 137, 663, 295, +789, 258, 415, 55, -222, -149, -611, -230, +-601, -129, -205, -6, 200, 9, 473, -113, +420, -249, 164, -108, 4, 266, -87, 626, +-24, 683, -6, 201, -122, -547, -239, -1066, +-234, -977, 34, -221, 388, 682, 566, 1194, +426, 965, 21, 190, -344, -553, -527, -914, +-403, -731, -57, -216, 328, 249, 495, 470, +385, 376, 141, 151, -83, 12, -145, -23, +-124, 37, -123, 23, -164, -122, -132, -305, +-5, -405, 186, -300, 443, 57, 561, 510, +337, 726, -189, 502, -686, -55, -730, -596, +-333, -748, 338, -419, 820, 109, 758, 422, +310, 390, -251, 155, -591, -36, -518, -22, +-146, 73, 195, 18, 358, -199, 303, -345, +82, -277, -37, 16, -55, 339, 80, 427, +206, 256, 90, -89, -190, -375, -404, -376, +-380, -108, 2, 238, 519, 374, 745, 202, +531, -158, -37, -342, -604, -260, -724, -29, +-332, 282, 166, 370, 468, 163, 459, -117, +248, -317, 10, -281, -53, -24, -76, 218, +-106, 254, -119, 83, -174, -134, -138, -268, +37, -173, 291, 105, 397, 305, 286, 276, +24, 60, -196, -168, -266, -259, -188, -224, +1, -115, 80, -34, 97, 65, 82, 229, +43, 357, 121, 355, 240, 130, 228, -254, +74, -583, -190, -641, -413, -331, -398, 176, +-145, 640, 246, 819, 568, 537, 579, -8, +308, -575, -113, -879, -430, -657, -546, -86, +-387, 501, -16, 751, 289, 478, 559, 7, +479, -304, 204, -299, -130, -73, -423, 60, +-387, -43, -162, -215, 187, -237, 359, -29, +273, 308, 42, 469, -205, 299, -243, 18, +-55, -252, 221, -363, 413, -297, 349, -168, +-38, 15, -488, 204, -648, 315, -295, 239, +279, 57, 762, -105, 782, -142, 290, -34, +-339, 59, -781, -49, -718, -259, -135, -360, +495, -159, 706, 327, 474, 711, -45, 609, +-399, 38, -349, -593, -50, -766, 220, -384, +290, 161, 44, 416, -223, 226, -279, -39, +-19, -32, 321, 241, 397, 458, 196, 221, +-137, -370, -305, -932, -217, -891, 3, -92, +112, 829, 129, 1235, 83, 794, 18, -174, +126, -966, 221, -1014, 104, -419, -129, 333, +-372, 730, -384, 553, -57, 30, 344, -352, +573, -353, 468, -78, 79, 228, -407, 292, +-670, 113, -426, -207, 66, -414, 586, -326, +684, 8, 310, 411, -202, 586, -605, 325, +-501, -187, 22, -599, 463, -545, 548, -110, +205, 386, -241, 558, -431, 248, -320, -181, +-29, -409, 262, -313, 477, 46, 459, 325, +133, 295, -307, 75, -558, -147, -485, -302, +-117, -212, 263, -8, 560, 108, 588, 220, +364, 168, -58, 33, -528, -56, -620, -134, +-374, -106, 51, 28, 351, 98, 443, -1, +268, -245, 150, -309, 66, 17, -66, 550, +-79, 722, -273, 254, -310, -550, -257, -1011, +-80, -700, 282, 136, 525, 850, 586, 912, +303, 370, -194, -363, -516, -709, -507, -524, +-256, -72, 4, 298, 173, 346, 287, 141, +333, -44, 293, -85, 164, -22, 48, 14, +-86, -4, -270, -4, -449, 9, -481, 4, +-209, -112, 306, -169, 687, -101, 694, 109, +442, 353, 10, 287, -456, 33, -736, -202, +-698, -322, -353, -246, 294, -70, 755, 27, +741, 122, 500, 274, 41, 319, -377, 229, +-589, -53, -526, -413, -289, -556, 109, -321, +398, 158, 443, 567, 394, 566, 181, 137, +-80, -327, -333, -503, -385, -306, -168, 87, +132, 341, 249, 337, 155, 146, -88, -192, +-158, -416, 3, -403, 175, -81, 309, 374, +268, 673, 15, 561, -407, 7, -540, -618, +-308, -922, 176, -607, 598, 96, 473, 707, +108, 927, -240, 579, -318, -49, -107, -588, +125, -774, 247, -487, 72, -42, -257, 351, +-462, 404, -238, 250, 328, 153, 750, 77, +689, 72, 155, -19, -485, -262, -840, -486, +-767, -506, -300, -162, 468, 378, 990, 769, +898, 705, 263, 236, -442, -376, -714, -737, +-577, -675, -253, -344, 61, 172, 316, 571, +515, 665, 469, 409, 205, -40, -105, -412, +-321, -524, -456, -364, -331, -74, -52, 201, +249, 371, 462, 359, 354, 176, 82, -82, +-194, -294, -251, -330, -159, -252, -20, 18, +68, 313, 51, 426, 69, 217, 79, -187, +56, -391, 64, -306, -14, 42, -23, 272, +-38, 216, -47, 8, 16, -141, 42, -124, +35, 21, -49, 177, -78, 100, 49, -109, +218, -225, 278, -190, 57, 38, -237, 251, +-376, 212, -224, 36, 47, -110, 291, -144, +422, -16, 317, 78, 9, 65, -362, -100, +-444, -264, -244, -233, 167, 53, 425, 469, +298, 558, 32, 277, -142, -287, -249, -710, +-148, -711, 79, -248, 239, 357, 296, 820, +92, 791, -333, 236, -495, -439, -184, -865, +263, -684, 594, -168, 522, 472, 84, 788, +-385, 588, -670, 25, -548, -555, -4, -704, +607, -373, 763, 185, 387, 586, -272, 588, +-569, 209, -394, -294, -26, -666, 318, -563, +246, -58, 114, 426, -27, 611, -145, 396, +-111, -1, 0, -300, 181, -394, 244, -341, +122, -104, -206, 114, -361, 218, -244, 227, +76, 145, 364, 117, 417, 62, 257, -89, +-138, -281, -431, -348, -403, -228, -98, 65, +287, 337, 445, 392, 222, 230, -20, -57, +-192, -288, -268, -288, -179, -121, -12, 51, +248, 129, 398, 102, 239, 34, -158, 4, +-444, -11, -354, -57, 8, -20, 386, 35, +472, 99, 268, 67, -136, -107, -443, -265, +-472, -210, -119, 73, 377, 363, 591, 394, +412, 59, -128, -340, -589, -457, -611, -196, +-143, 169, 476, 443, 757, 341, 481, -32, +-164, -319, -674, -412, -631, -188, -166, 145, +320, 400, 592, 385, 446, 135, 136, -217, +-216, -521, -484, -447, -406, 15, -72, 485, +371, 561, 457, 243, 146, -270, -214, -529, +-316, -444, -143, -38, 226, 377, 451, 534, +297, 381, -153, -113, -678, -497, -665, -577, +-47, -228, 712, 188, 963, 514, 487, 531, +-211, 265, -743, -145, -811, -499, -534, -599, +128, -402, 791, 111, 1035, 593, 565, 752, +-287, 409, -870, -199, -861, -732, -312, -710, +293, -256, 758, 323, 757, 653, 209, 505, +-401, 119, -593, -280, -326, -468, 54, -347, +231, -55, 218, 178, 139, 241, 63, 177, +-35, 49, -63, 42, -30, 31, 58, -71, +-103, -237, -118, -292, 54, -158, 153, 97, +43, 362, -64, 375, 1, 198, 187, -80, +239, -337, -26, -397, -322, -227, -359, 26, +-164, 279, 185, 326, 421, 188, 486, -16, +176, -88, -272, -74, -483, -83, -390, -127, +-66, -236, 258, -199, 466, 85, 319, 425, +4, 543, -307, 265, -281, -255, -20, -638, +183, -570, 93, -76, -21, 335, -64, 472, +-42, 391, -12, 141, 101, -132, 282, -309, +168, -330, -230, -238, -409, -48, -239, 114, +260, 231, 437, 345, 244, 400, -73, 164, +-323, -259, -340, -623, -85, -657, 320, -244, +533, 354, 258, 809, -376, 754, -583, 163, +-270, -520, 246, -785, 611, -530, 423, 114, +-46, 530, -510, 365, -592, -28, -82, -228, +500, -113, 670, 237, 202, 358, -363, 53, +-599, -333, -291, -557, 120, -398, 467, 104, +464, 592, 149, 743, -310, 318, -489, -341, +-242, -782, 154, -603, 425, 69, 307, 626, +-25, 635, -276, 125, -341, -530, -63, -680, +328, -186, 488, 505, 107, 843, -450, 402, +-555, -479, -119, -1016, 435, -664, 639, 245, +348, 1054, -224, 978, -625, 100, -606, -896, +-118, -1220, 552, -560, 789, 635, 421, 1374, +-187, 1008, -627, -146, -549, -1247, -260, -1405, +255, -448, 540, 807, 491, 1451, 69, 1017, +-260, -136, -344, -1177, -84, -1233, 84, -312, +28, 734, -47, 1081, -115, 570, -15, -394, +118, -947, 357, -599, 369, 249, 80, 940, +-402, 793, -677, -43, -392, -1001, 162, -1076, +667, -250, 615, 821, 170, 1282, -378, 704, +-611, -405, -323, -1272, 232, -1069, 580, 12, +358, 1083, -125, 1257, -600, 399, -517, -802, +-96, -1331, 518, -719, 800, 442, 586, 1261, +-91, 1038, -758, 54, -895, -1052, -475, -1240, +288, -497, 803, 630, 797, 1245, 278, 884, +-360, -65, -641, -1028, -446, -1153, 38, -405, +354, 641, 353, 1206, 7, 875, -282, -165, +-270, -1017, 1, -1030, 412, -308, 432, 605, +83, 938, -264, 574, -396, -167, -308, -664, +-96, -494, 159, 7, 311, 446, 354, 349, +145, -37, -33, -432, -121, -352, -208, 13, +-222, 437, -228, 507, 45, 258, 318, -182, +353, -529, 104, -457, -120, -168, -235, 223, +-169, 385, -36, 327, 113, 92, 275, -79, +207, -196, -14, -113, -284, 91, -353, 102, +-169, -35, 73, -276, 360, -401, 420, -124, +330, 416, -9, 739, -354, 630, -535, 132, +-445, -609, -104, -978, 291, -803, 580, -129, +503, 652, 217, 1123, -121, 879, -375, 134, +-511, -647, -412, -1046, -104, -733, 311, -26, +619, 654, 477, 885, 65, 462, -372, -276, +-514, -740, -267, -536, 146, 148, 476, 761, +328, 694, -126, -15, -534, -783, -440, -971, +-33, -388, 567, 623, 777, 1246, 370, 859, +-285, -154, -800, -1070, -773, -1133, -196, -345, +468, 670, 758, 1106, 631, 689, 107, -152, +-506, -894, -772, -922, -425, -191, 294, 684, +720, 1060, 482, 574, -158, -394, -613, -1077, +-531, -880, -21, 57, 419, 1006, 616, 1052, +405, 262, -95, -788, -572, -1090, -612, -374, +-181, 635, 250, 1067, 498, 518, 277, -501, +-42, -1073, -201, -699, -126, 321, 20, 1166, +128, 1036, 94, 15, -94, -1004, -289, -1305, +-255, -506, -38, 707, 238, 1290, 438, 932, +396, -68, 89, -993, -284, -1160, -460, -376, +-405, 633, -216, 1107, 102, 612, 293, -338, +466, -1022, 471, -647, 196, 382, -289, 1102, +-578, 817, -547, -248, -258, -1312, 219, -1337, +501, -148, 584, 1285, 221, 1875, -251, 1010, +-475, -686, -309, -1928, 90, -1741, 281, -235, +114, 1450, -192, 1976, -303, 971, -110, -680, +294, -1672, 578, -1236, 378, 275, -138, 1390, +-774, 1210, -736, -46, -209, -1305, 546, -1358, +917, -179, 598, 1290, -198, 1753, -888, 761, +-843, -860, -119, -1970, 788, -1492, 912, 264, +261, 1853, -642, 1941, -884, 402, -427, -1475, +282, -2035, 826, -834, 711, 1150, 29, 2138, +-678, 1325, -867, -689, -394, -2235, 482, -2006, +832, -17, 443, 2120, -251, 2576, -610, 993, +-366, -1311, 92, -2455, 430, -1685, 186, 227, +-174, 1705, -424, 1680, -142, 495, 282, -755, +593, -1072, 378, -413, -350, 417, -828, 602, +-791, 43, 1, -562, 813, -574, 1064, 50, +471, 652, -393, 892, -939, 428, -828, -376, +-178, -882, 446, -682, 710, -58, 316, 520, +-156, 524, -301, 170, -4, -134, 265, -30, +78, 206, -350, 145, -658, -97, -357, -441, +136, -549, 704, -176, 849, 493, 363, 923, +-393, 632, -954, -250, -771, -1030, -18, -947, +609, 29, 662, 1052, 222, 1259, -348, 394, +-489, -890, -263, -1565, 156, -1010, 498, 433, +377, 1692, -67, 1680, -523, 466, -621, -1026, +-294, -1762, 177, -1322, 522, -9, 515, 1093, +253, 1420, -42, 889, -331, 67, -474, -664, +-382, -800, -213, -593, 46, -448, 301, -26, +443, 427, 397, 880, 75, 1045, -304, 507, +-513, -495, -330, -1345, 58, -1425, 198, -344, +170, 1078, -63, 1866, -215, 1304, -133, -321, +92, -1799, 471, -1927, 479, -454, 24, 1399, +-698, 2246, -947, 1279, -518, -702, 344, -2207, +917, -1796, 829, 131, 265, 1815, -608, 2057, +-944, 456, -666, -1430, 172, -1949, 799, -701, +673, 1140, -24, 2013, -726, 1043, -754, -865, +-317, -2090, 491, -1642, 893, 326, 716, 2150, +-149, 2369, -968, 670, -994, -1550, -340, -2585, +582, -1646, 780, 566, 465, 2132, -247, 2057, +-542, 466, -442, -1255, 39, -1860, 580, -883, +476, 794, -107, 1627, -803, 976, -865, -592, +-269, -1577, 533, -1257, 909, 345, 669, 1641, +90, 1692, -504, 539, -704, -1089, -536, -1834, +-127, -1199, 83, 311, -75, 1301, -97, 1176, +244, 238, 874, -612, 943, -543, 244, 44, +-878, 527, -1639, 354, -1357, -364, -323, -976, +1039, -760, 1789, 143, 1356, 1101, 136, 1358, +-1279, 567, -1595, -438, -815, -1028, 342, -890, +949, -315, 648, 377, -245, 559, -779, 333, +-479, -41, 301, -155, 997, 199, 916, 583, +41, 525, -1201, -160, -1665, -911, -1052, -1281, +322, -734, 1481, 473, 1623, 1524, 799, 1615, +-509, 706, -1323, -661, -1387, -1577, -776, -1231, +277, -285, 934, 634, 982, 1035, 488, 661, +-190, 55, -713, -407, -736, -289, -457, 50, +59, 213, 459, 58, 566, -175, 289, -342, +-226, -182, -524, 156, -654, 355, -298, 322, +157, 91, 516, -75, 616, -236, 293, 98, +-177, 307, -625, 110, -745, -286, -587, -621, +-4, -610, 454, -47, 784, 768, 704, 1274, +78, 1057, -494, 60, -987, -1142, -814, -1724, +-270, -1186, 485, 156, 823, 1330, 533, 1669, +50, 1075, -491, -146, -540, -1083, -334, -1206, +-29, -574, 95, 217, 26, 625, -141, 417, +-22, 17, 303, -110, 406, 112, 257, 473, +-511, 585, -930, 81, -820, -754, -87, -1269, +855, -939, 1208, 204, 770, 1417, -490, 1748, +-1436, 872, -1376, -501, -385, -1519, 849, -1584, +1442, -552, 953, 769, -251, 1373, -1287, 1065, +-1421, 165, -355, -682, 849, -841, 1298, -400, +581, 144, -757, 406, -1251, 345, -886, 199, +180, 10, 1162, -183, 1191, -188, 159, -255, +-1034, -218, -1574, 226, -908, 627, 361, 723, +1245, 331, 1268, -535, 312, -1166, -668, -1089, +-1361, -112, -1069, 1117, -57, 1650, 716, 1199, +880, -124, 330, -1434, -272, -1721, -500, -905, +-361, 448, -144, 1426, 125, 1461, 26, 674, +-273, -490, -302, -1167, -57, -1089, 409, -340, +431, 631, 152, 1116, -372, 795, -597, 55, +-485, -834, -303, -1028, 160, -598, 390, 257, +355, 1120, 111, 1299, 20, 786, -163, -308, +-310, -1468, -552, -1784, -655, -1094, -244, 376, +205, 1996, 873, 2417, 861, 1488, 278, -388, +-589, -2175, -1282, -2761, -1070, -1712, -228, 353, +664, 2318, 940, 2905, 697, 1798, 0, -394, +-603, -2248, -817, -2570, -516, -1320, -9, 622, +244, 2060, 213, 2000, -111, 661, 28, -1034, +170, -1739, 237, -1074, -92, 373, -633, 1531, +-820, 1345, -472, 172, 340, -1167, 1032, -1639, +1005, -893, 81, 535, -1068, 1677, -1770, 1613, +-1115, 454, 285, -890, 1605, -1509, 1917, -1103, +822, 16, -890, 928, -2347, 1076, -2189, 411, +-733, -463, 1250, -752, 2432, -257, 2056, 655, +371, 1044, -1699, 472, -2593, -721, -2147, -1459, +-201, -1336, 1659, -120, 2382, 1362, 1614, 2173, +-158, 1666, -1722, -8, -2296, -1595, -1341, -2413, +348, -1804, 1541, -73, 1538, 1584, 461, 2445, +-784, 1922, -1218, 393, -746, -1345, 81, -2194, +654, -1682, 430, -402, -380, 917, -935, 1689, +-725, 1367, 242, 367, 1234, -494, 1360, -872, +313, -552, -1119, -37, -2071, 115, -1851, -190, +-402, -313, 1407, -147, 2366, 364, 1814, 1028, +192, 1187, -1504, 712, -2329, -519, -1940, -1713, +-702, -1997, 839, -1025, 1780, 750, 1821, 2189, +927, 2396, -370, 1203, -1399, -619, -1902, -2264, +-1506, -2482, -264, -1224, 1010, 978, 1704, 2365, +1342, 2210, 45, 695, -1206, -1409, -1634, -2285, +-977, -1607, 344, 333, 1334, 2144, 1077, 2487, +-98, 950, -1373, -1664, -1745, -3186, -699, -2539, +947, 152, 2092, 3096, 1660, 4112, -150, 2322, +-1960, -1232, -2580, -4122, -1426, -4214, 597, -1507, +2090, 2249, 2023, 4420, 508, 3469, -1210, 366, +-1853, -2829, -1093, -3682, 316, -1888, 1166, 1094, +683, 3008, -515, 2352, -1376, -96, -958, -2316, +460, -2523, 1615, -561, 1544, 1910, 30, 2950, +-1638, 1750, -2252, -728, -1362, -2789, 355, -2806, +1871, -1114, 1933, 1373, 601, 2876, -991, 2527, +-2052, 793, -1379, -1265, 141, -2380, 1213, -2037, +1373, -666, 238, 944, -1004, 1823, -1494, 1702, +-1006, 739, 247, -599, 1237, -1397, 1408, -1443, +626, -634, -618, 591, -1497, 1495, -1672, 1458, +-963, 434, 331, -1120, 1314, -1824, 1555, -1339, +867, 229, -137, 1937, -942, 2302, -1588, 1115, +-1377, -925, -581, -2573, 414, -2463, 1349, -779, +1177, 1623, 585, 2957, -99, 2423, -912, 532, +-1252, -1818, -1134, -2853, -390, -2204, 500, -376, +931, 1727, 822, 2610, 310, 2043, -325, 500, +-758, -1316, -839, -2222, -418, -1845, 213, -645, +263, 855, 45, 1855, -234, 1949, -187, 1127, +291, -434, 523, -1693, 321, -2148, -272, -1381, +-1210, 415, -1491, 1768, -791, 2199, 664, 1459, +2197, -263, 2034, -1522, 399, -2120, -1798, -1419, +-3222, 33, -2451, 1185, -112, 1914, 2556, 1664, +3695, 698, 2168, -625, -828, -1800, -3533, -2196, +-3865, -1438, -1805, 263, 1484, 1917, 3676, 2762, +3404, 2139, 884, 179, -2281, -1895, -3882, -3216, +-2999, -2616, -260, -385, 2501, 2000, 3616, 3391, +2132, 2751, -582, 595, -2828, -1808, -3390, -2991, +-1691, -2565, 703, -697, 2627, 1259, 2871, 2448, +1263, 2384, -977, 974, -2786, -537, -2766, -1828, +-1115, -2070, 869, -1208, 2383, 44, 2396, 1283, +729, 1966, -1086, 1554, -2453, 383, -2202, -1051, +-593, -2077, 1165, -1648, 2232, -307, 1479, 1253, +-158, 2230, -1515, 1626, -2067, -31, -1105, -1533, +591, -2139, 1610, -1289, 1554, 534, 265, 1738, +-1464, 1904, -1900, 765, -1136, -694, 535, -1577, +1774, -1321, 1483, -189, 262, 804, -1395, 1135, +-2125, 338, -1397, -322, 306, -542, 1820, -95, +2017, 887, 857, 978, -1136, 27, -2328, -1252, +-2017, -2057, -462, -1412, 1334, 686, 2074, 2729, +1577, 3221, -28, 1614, -1434, -1446, -1982, -3781, +-1418, -3798, -84, -1403, 1023, 2182, 1409, 4257, +1013, 3643, 117, 944, -804, -2215, -1338, -3763, +-1028, -2944, -402, -393, 408, 1780, 953, 2655, +787, 2094, 315, 272, -506, -904, -982, -1402, +-856, -1191, -318, -450, 462, 59, 657, 499, +536, 677, 12, 784, -601, 626, -815, 139, +-662, -473, 29, -990, 588, -909, 711, -328, +335, 491, -200, 1091, -678, 1030, -866, 301, +-720, -507, -132, -855, 607, -727, 967, -128, +782, 299, 91, 345, -734, 327, -1226, 327, +-1307, 225, -566, 334, 678, 118, 1530, -460, +1366, -917, 394, -1042, -956, -512, -1772, 718, +-1562, 1680, -462, 1704, 917, 876, 1648, -727, +1213, -2036, 8, -2241, -980, -1143, -1436, 620, +-1012, 2183, -179, 2477, 581, 1359, 965, -331, +730, -1834, 100, -2197, -450, -1405, -612, 16, +-791, 1353, -712, 1656, -334, 1164, 208, 261, +1050, -692, 1247, -783, 753, -549, -315, -180, +-1669, 86, -2161, -187, -1529, -185, 265, -28, +2224, 554, 2807, 1032, 1673, 946, -768, 289, +-2867, -778, -3297, -1434, -1641, -1453, 998, -513, +2908, 758, 2847, 1576, 909, 1534, -1419, 672, +-2660, -384, -2031, -1151, -202, -1222, 1449, -757, +1764, -51, 445, 541, -1084, 793, -1602, 730, +-636, 553, 1050, 189, 1911, -192, 1330, -556, +-674, -834, -2599, -738, -2994, -279, -1393, 344, +1588, 805, 3726, 1110, 3578, 779, 1017, 121, +-2494, -529, -4502, -986, -4017, -1100, -1129, -766, +2554, -82, 4725, 655, 4050, 1482, 993, 1728, +-2695, 1064, -4855, -331, -4116, -1885, -950, -2469, +2486, -1762, 4437, 32, 3525, 1963, 451, 2821, +-2618, 2134, -3921, 503, -2619, -1407, 91, -2463, +2396, -2170, 2800, -1065, 1135, 383, -1185, 1445, +-2443, 1878, -1554, 1654, 509, 1101, 2044, 92, +1821, -1135, 3, -2098, -2043, -2408, -2898, -1547, +-1586, 156, 889, 2013, 3013, 3111, 3284, 2784, +1239, 1208, -1548, -1125, -3538, -3051, -3578, -3577, +-1469, -2537, 1267, -173, 3322, 2383, 3436, 3809, +1667, 3608, -840, 1505, -2769, -1267, -3440, -3331, +-2231, -3908, 96, -2366, 2045, 108, 2865, 2314, +1981, 3485, 254, 2764, -1226, 911, -2079, -1134, +-1858, -2490, -748, -2439, 421, -1446, 1067, 209, +1087, 1419, 534, 1759, 72, 1422, 36, 334, +-433, -558, -727, -1014, -908, -957, -879, -342, +51, 261, 764, 756, 1238, 605, 1031, -136, +-315, -664, -1419, -965, -1762, -392, -776, 800, +1042, 1578, 2201, 1748, 1830, 570, -175, -1238, +-2424, -2551, -3233, -2641, -1820, -1100, 1008, 1229, +3409, 3097, 3821, 3447, 1666, 1986, -1693, -623, +-4251, -2952, -4250, -3853, -1782, -2729, 1706, -323, +4140, 2095, 3927, 3678, 1795, 3392, -1282, 1491, +-3468, -922, -3579, -3002, -2099, -3562, 274, -2373, +2160, -179, 2750, 2165, 2147, 3396, 705, 2814, +-916, 863, -2058, -1493, -2315, -2897, -1682, -2602, +-422, -839, 1074, 1118, 2152, 2319, 2307, 2086, +1327, 458, -547, -1175, -2076, -1863, -2686, -1307, +-2022, 65, -359, 1351, 1465, 1597, 2785, 905, +2639, -225, 966, -1220, -1219, -1411, -2843, -1115, +-3228, -245, -1883, 701, 503, 1360, 2753, 1899, +3850, 1484, 2523, 242, -320, -1448, -2973, -2747, +-4107, -2721, -2907, -1238, -244, 1209, 2586, 3229, +3932, 3612, 2979, 2133, 358, -526, -2325, -2922, +-3324, -3680, -2521, -2553, -752, -297, 1151, 1843, +2199, 2873, 2023, 2475, 892, 1058, -363, -424, +-1216, -1307, -1437, -1511, -1108, -1303, -593, -1019, +165, -569, 828, 141, 1165, 1081, 900, 2091, +279, 2195, -566, 1235, -1276, -405, -1172, -2332, +-529, -3081, 585, -2279, 1191, -264, 831, 2006, +128, 3089, -749, 2666, -979, 815, -741, -1312, +-162, -2524, 681, -2361, 818, -846, 620, 756, +106, 1856, -526, 1617, -743, 424, -817, -592, +-684, -1262, -115, -861, 533, 130, 967, 992, +1148, 1174, 637, 451, -237, -593, -1069, -1421, +-1709, -1302, -1285, -533, -342, 593, 600, 1446, +1401, 1503, 1533, 1092, 1157, 197, 198, -842, +-910, -1481, -1682, -1691, -1899, -1326, -1348, -261, +-302, 927, 1108, 1931, 2160, 2254, 2297, 1781, +1489, 508, -325, -1332, -1977, -2902, -2909, -3346, +-2870, -2178, -1128, 345, 1317, 2985, 3089, 4319, +3559, 3477, 2090, 780, -550, -2219, -2776, -4184, +-3782, -3951, -2827, -1694, -294, 980, 2100, 3001, +3044, 3370, 2523, 2269, 760, 450, -1179, -1218, +-2121, -2023, -1839, -2084, -797, -1544, 205, -597, +706, 503, 367, 1401, 388, 1913, 594, 1748, +723, 884, 636, -307, -161, -1325, -1018, -1968, +-1791, -1844, -1718, -921, -380, 363, 1257, 1431, +2233, 2015, 1998, 1939, 532, 1016, -1158, -310, +-2109, -1677, -2123, -2518, -955, -2291, 618, -908, +1556, 1090, 1844, 2688, 1123, 3266, 78, 2042, +-934, -473, -1638, -2827, -1576, -3714, -944, -2379, +245, 277, 1352, 2694, 1719, 3372, 1393, 1891, +255, -388, -1123, -2037, -1792, -2089, -1563, -796, +-601, 547, 438, 848, 1149, 201, 1205, -417, +870, -414, 273, 638, -430, 1769, -770, 1538, +-946, 48, -983, -2037, -731, -3239, -66, -2189, +741, 437, 1390, 2991, 1524, 3819, 661, 2240, +-486, -739, -1506, -3131, -1914, -3382, -1237, -1573, +68, 867, 1227, 2371, 1638, 2064, 1024, 614, +-196, -825, -900, -1155, -864, -294, -119, 721, +566, 869, 449, -57, -432, -1453, -1354, -2005, +-1541, -1015, -500, 864, 1490, 2510, 2911, 2930, +2822, 1637, 711, -834, -2352, -2887, -4396, -3384, +-4033, -2184, -1134, 228, 2489, 2404, 4820, 3213, +4472, 2505, 1616, 695, -2159, -1294, -4481, -2496, +-4150, -2316, -1810, -1321, 1194, 75, 2977, 1232, +2931, 1677, 1507, 1564, -189, 811, -1189, -15, +-1246, -670, -859, -1033, -735, -993, -819, -913, +-635, -537, 63, 12, 1122, 684, 2010, 1264, +1914, 1567, 794, 1225, -1060, 110, -2705, -1216, +-2878, -2174, -1376, -2153, 910, -888, 2471, 998, +2729, 2348, 1391, 2483, -629, 1231, -1963, -831, +-2220, -2176, -1038, -1961, 529, -673, 1388, 823, +1130, 1428, 155, 815, -786, -255, -986, -825, +-283, -532, 632, 455, 1251, 1221, 774, 936, +-329, -193, -1320, -1463, -1749, -1854, -1077, -899, +167, 707, 1527, 1895, 2131, 1881, 1539, 743, +147, -927, -1500, -1787, -2310, -1356, -1934, -209, +-663, 1056, 989, 1357, 2049, 459, 1892, -599, +747, -1177, -633, -726, -1357, 454, -1252, 1363, +-599, 1464, 26, 419, 245, -1050, 307, -1994, +177, -1789, 184, -381, 462, 1240, 697, 2179, +413, 1945, -266, 607, -1012, -886, -1405, -1782, +-957, -1871, -12, -876, 1037, 402, 1387, 1091, +1004, 1328, 252, 812, -608, 44, -904, -353, +-667, -368, -449, -105, -359, -36, -107, -343, +198, -807, 450, -933, 935, -320, 911, 735, +346, 1703, -361, 1861, -1271, 1065, -1413, -455, +-774, -1989, 136, -2389, 1059, -1713, 1267, -221, +689, 1329, -80, 2084, -658, 2144, -694, 1378, +-271, 128, 42, -1246, 42, -2211, -45, -2426, +-272, -1656, -310, 78, 102, 1925, 541, 3038, +792, 2630, 552, 871, -109, -1344, -706, -2737, +-1043, -2620, -937, -1315, -296, 520, 694, 1829, +1169, 1900, 928, 1078, 163, 62, -688, -544, +-926, -604, -710, -513, 30, -459, 756, -364, +858, -293, 232, -53, -763, 356, -1311, 538, +-899, 574, 296, 420, 1359, 33, 1723, -81, +1056, -53, -406, -152, -1624, -505, -2077, -823, +-1405, -792, 19, -375, 1211, 601, 1735, 1464, +1518, 1668, 789, 1065, -112, -244, -971, -1501, +-1607, -2030, -1704, -1504, -1179, -321, -52, 896, +1166, 1628, 2006, 1507, 2047, 840, 1155, -24, +-394, -594, -1873, -799, -2272, -946, -1722, -839, +-494, -630, 895, -220, 1609, 543, 1614, 1188, +1119, 1512, 350, 1303, -445, 366, -949, -876, +-1422, -1813, -1472, -2101, -833, -1353, 76, 165, +1172, 1541, 1759, 2306, 1660, 2007, 899, 679, +-548, -851, -1745, -1929, -2074, -2078, -1358, -1244, +22, 100, 1178, 1229, 1704, 1635, 1372, 1236, +404, 520, -645, -225, -1357, -804, -1234, -1022, +-402, -1013, 432, -567, 942, 171, 901, 876, +316, 1292, -471, 880, -996, 41, -980, -766, +-233, -1237, 700, -824, 1338, 82, 1103, 676, +156, 945, -799, 682, -1369, -12, -1307, -566, +-675, -839, 462, -672, 1253, -169, 1496, 400, +1043, 813, -56, 907, -665, 517, -1149, -81, +-1345, -770, -743, -1252, -93, -1045, 690, -250, +1177, 725, 1053, 1488, 740, 1503, 105, 579, +-680, -583, -1088, -1451, -1222, -1561, -727, -866, +104, 148, 781, 1157, 1114, 1539, 913, 1155, +343, 245, -398, -772, -808, -1404, -717, -1203, +-305, -521, 145, 357, 326, 1182, 149, 1271, +-125, 740, -114, -170, 2, -1043, 311, -1303, +550, -780, 394, 214, -68, 1090, -631, 1285, +-750, 572, -561, -495, -78, -1116, 330, -911, +460, -51, 474, 667, 326, 781, 202, 262, +142, -369, 40, -502, -344, -127, -803, 442, +-1075, 549, -832, 49, 94, -632, 1179, -945, +1802, -420, 1503, 476, 470, 1168, -1046, 1119, +-2113, 231, -2130, -816, -1084, -1327, 589, -1003, +1972, -57, 2240, 816, 1416, 1142, -14, 785, +-1387, 43, -1912, -491, -1550, -752, -411, -601, +796, -205, 1368, 84, 1155, 341, 287, 496, +-401, 502, -552, 319, -264, 2, 99, -473, +63, -823, -295, -753, -658, -266, -569, 640, +82, 1265, 933, 1160, 1428, 285, 948, -969, +-381, -1690, -1408, -1293, -1630, -46, -896, 1306, +540, 1876, 1501, 1129, 1509, -344, 597, -1472, +-806, -1668, -1428, -696, -1048, 708, -40, 1467, +942, 1130, 1113, 46, 498, -1023, -369, -1223, +-995, -354, -766, 670, 30, 1124, 692, 733, +815, -309, 275, -1152, -447, -1139, -638, -261, +-357, 869, 49, 1408, 584, 851, 523, -310, +33, -1135, -448, -1115, -728, -248, -269, 639, +406, 942, 690, 555, 594, -302, 71, -838, +-456, -674, -731, 54, -548, 840, -25, 904, +426, 333, 587, -474, 384, -996, 87, -866, +-120, -267, -252, 430, -283, 876, -287, 849, +-183, 424, -3, -145, 183, -563, 357, -666, +390, -532, 301, -318, -44, 12, -313, 349, +-480, 502, -489, 674, -41, 513, 289, 63, +391, -287, 408, -695, 156, -782, -63, -579, +-132, -148, -347, 384, -279, 725, -125, 877, +4, 651, 283, 183, 339, -365, 215, -840, +16, -1038, -290, -788, -337, -196, -112, 519, +148, 1090, 397, 1145, 305, 763, -33, -33, +-428, -875, -467, -1158, -201, -1041, 115, -407, +514, 375, 651, 826, 374, 930, -72, 634, +-529, 100, -752, -398, -549, -553, -90, -447, +338, -231, 783, -47, 732, -166, 367, -166, +-152, 79, -586, 534, -627, 938, -474, 809, +-9, 33, 246, -926, 224, -1369, 198, -1074, +120, -68, 342, 945, 584, 1306, 343, 877, +-188, -15, -855, -743, -1196, -831, -869, -375, +-39, 189, 995, 400, 1612, 119, 1354, -261, +453, -359, -772, -42, -1496, 415, -1319, 704, +-758, 441, 30, -230, 798, -675, 1060, -829, +1053, -461, 724, 226, 144, 722, -373, 727, +-897, 386, -1226, -204, -1066, -712, -354, -650, +687, -262, 1349, 330, 1448, 766, 774, 616, +-250, 54, -926, -640, -1089, -978, -687, -681, +-79, 110, 254, 923, 241, 1288, 165, 845, +129, -263, 455, -1209, 832, -1533, 727, -918, +62, 324, -904, 1248, -1555, 1436, -1284, 828, +-301, -235, 888, -1032, 1650, -1170, 1512, -654, +604, 69, -516, 645, -1169, 754, -1092, 458, +-517, 64, 119, -336, 320, -475, 260, -362, +184, -110, 276, 289, 548, 417, 641, 274, +321, -85, -306, -498, -1043, -572, -1278, -196, +-704, 354, 331, 745, 1280, 671, 1404, 107, +720, -527, -334, -917, -1042, -737, -924, -96, +-226, 542, 533, 854, 664, 656, 219, 35, +-375, -461, -704, -608, -275, -476, 454, -34, +926, 287, 817, 326, 108, 237, -668, -17, +-962, -185, -681, -181, -70, -83, 483, 33, +651, 128, 369, 101, 126, 43, 86, -57, +72, -149, 115, -141, -67, -101, -493, 19, +-674, 95, -544, 79, 52, 14, 739, 6, +1056, 89, 864, 199, 155, 186, -555, -99, +-1043, -442, -952, -705, -244, -581, 413, 70, +907, 774, 896, 1213, 303, 1006, -286, 29, +-715, -1021, -665, -1586, -133, -1280, 461, -193, +716, 932, 521, 1458, -13, 1139, -528, 267, +-736, -547, -403, -792, 255, -621, 678, -307, +712, -124, 343, -234, -111, -241, -347, 156, +-423, 691, -218, 1163, -21, 1046, -21, 179, +-36, -957, -4, -1798, 244, -1725, 613, -673, +682, 851, 354, 1954, -187, 1935, -778, 826, +-1003, -633, -727, -1549, -97, -1514, 683, -701, +1262, 195, 1168, 714, 560, 613, -255, 279, +-955, 99, -1084, 99, -814, 310, -198, 234, +592, -194, 928, -712, 825, -985, 408, -724, +-121, -18, -340, 785, -246, 1203, -130, 942, +-31, 223, -132, -571, -378, -967, -389, -816, +-127, -375, 486, 71, 1101, 286, 1165, 380, +630, 410, -369, 394, -1306, 317, -1460, 41, +-954, -323, 38, -698, 1104, -740, 1519, -436, +1237, 94, 441, 720, -382, 854, -833, 525, +-978, -22, -742, -554, -301, -680, 122, -414, +575, -27, 807, 204, 825, 215, 686, 91, +180, 52, -433, 135, -872, 211, -976, 120, +-531, -294, 69, -560, 650, -468, 968, -74, +896, 514, 483, 744, -154, 425, -650, -214, +-809, -790, -479, -864, 98, -333, 567, 476, +657, 997, 309, 903, -184, 119, -486, -811, +-318, -1247, 219, -923, 729, 54, 787, 1050, +197, 1328, -614, 690, -1064, -351, -819, -1174, +2, -1239, 915, -404, 1176, 570, 777, 1077, +40, 826, -505, -27, -578, -707, -187, -860, +140, -402, 73, 296, -204, 635, -517, 517, +-173, -3, 643, -528, 1319, -609, 1381, -211, +481, 360, -876, 554, -1858, 318, -1832, -188, +-658, -571, 918, -492, 1957, -68, 2073, 378, +1063, 547, -373, 371, -1395, -115, -1718, -524, +-1082, -626, 6, -385, 892, 131, 1249, 497, +1088, 624, 520, 388, -143, -94, -584, -490, +-673, -642, -453, -482, 31, -109, 319, 342, +291, 595, 312, 467, 90, 177, -7, -247, +94, -535, 150, -422, 341, -224, 134, 78, +-196, 249, -405, 235, -367, 179, -37, 55, +284, 11, 539, -112, 535, -242, 303, -317, +-48, -247, -317, 57, -299, 341, -23, 439, +174, 211, 273, -230, 135, -556, -25, -460, +-14, -85, -103, 378, 98, 550, 361, 255, +393, -147, 326, -430, -62, -399, -353, -116, +-408, 133, -345, 226, -86, 78, 294, -90, +667, -55, 839, 95, 528, 271, -10, 157, +-488, -234, -659, -588, -481, -653, -182, -143, +260, 472, 618, 836, 747, 715, 603, 44, +205, -639, -89, -901, -356, -610, -543, -58, +-460, 509, -179, 653, 197, 338, 593, -57, +720, -332, 522, -311, 223, -98, -186, 142, +-463, 132, -411, -88, -138, -256, 130, -345, +303, -90, 286, 244, 236, 440, 160, 456, +181, 128, 254, -228, 257, -491, 105, -637, +-197, -494, -457, -102, -474, 373, -172, 737, +320, 825, 816, 393, 1039, -257, 678, -848, +-114, -1124, -873, -739, -1057, 23, -605, 809, +215, 1158, 999, 831, 1171, 61, 749, -722, +-132, -1022, -830, -833, -824, -208, -186, 454, +623, 662, 932, 572, 620, 154, -5, -192, +-647, -240, -647, -230, -131, -207, 442, -287, +899, -345, 724, -164, 139, 295, -277, 722, +-540, 720, -425, 268, -128, -532, 184, -1119, +494, -1009, 547, -263, 448, 718, 286, 1296, +-114, 979, -404, -47, -397, -1029, -154, -1328, +415, -725, 678, 367, 441, 1126, -10, 1075, +-446, 242, -423, -763, 132, -1207, 763, -733, +991, 211, 493, 909, -504, 912, -1228, 201, +-962, -517, 137, -759, 1223, -471, 1498, 110, +797, 392, -369, 204, -1153, -151, -1027, -370, +-65, -92, 1007, 517, 1304, 801, 473, 362, +-629, -520, -1153, -1344, -624, -1375, 647, -343, +1495, 1000, 1403, 1834, 373, 1556, -965, 227, +-1618, -1250, -1046, -2008, 250, -1519, 1357, -223, +1583, 1044, 755, 1562, -300, 1119, -893, 206, +-698, -616, 52, -908, 571, -670, 587, -284, +76, 60, -469, 196, -514, 107, -23, 83, +767, 178, 1213, 321, 989, 350, 135, 106, +-857, -278, -1268, -635, -995, -693, -97, -345, +940, 94, 1478, 496, 1364, 672, 558, 476, +-386, 55, -925, -360, -950, -573, -455, -472, +158, -143, 483, 245, 625, 330, 540, 103, +337, -191, 315, -376, 216, -196, 99, 323, +-184, 659, -553, 543, -570, -16, -334, -712, +297, -1038, 851, -797, 955, -112, 833, 586, +246, 984, -355, 979, -474, 493, -499, -162, +-272, -800, 4, -1182, 123, -1034, 401, -492, +548, 363, 655, 1105, 675, 1309, 320, 926, +-157, 18, -668, -928, -918, -1367, -586, -1113, +80, -296, 775, 531, 1179, 927, 1037, 746, +482, 233, -186, -182, -644, -244, -735, -175, +-474, -133, 38, -256, 416, -506, 623, -499, +747, -117, 545, 473, 245, 889, -85, 839, +-413, 269, -430, -577, -210, -1034, 108, -950, +337, -342, 452, 407, 388, 768, 187, 661, +106, 183, 55, -247, 3, -380, 13, -279, +4, -129, -37, -65, 14, -127, 166, -131, +343, 64, 421, 320, 300, 410, 3, 175, +-219, -248, -213, -592, 106, -571, 453, -59, +538, 504, 341, 700, -176, 405, -546, -326, +-443, -879, 46, -795, 670, -139, 969, 722, +670, 1014, -61, 588, -643, -308, -684, -1049, +-253, -1049, 425, -293, 796, 696, 584, 1116, +158, 724, -247, -277, -313, -1154, 113, -1095, +500, -179, 548, 883, 212, 1316, -331, 753, +-651, -512, -383, -1425, 323, -1355, 943, -370, +999, 951, 464, 1560, -292, 1105, -708, -89, +-607, -1195, -194, -1406, 431, -741, 738, 283, +554, 973, 216, 874, -188, 301, -195, -335, +74, -613, 282, -415, 300, -69, 119, 213, +-54, 203, -183, -33, -62, -164, 125, -185, +354, -40, 494, 189, 380, 265, 226, 179, +50, -30, -172, -309, -326, -440, -362, -351, +-107, -24, 300, 276, 649, 407, 710, 337, +429, 66, 77, -148, -264, -339, -418, -393, +-296, -251, -53, -130, 219, 112, 321, 315, +413, 318, 477, 287, 461, 129, 305, -182, +-79, -461, -397, -536, -481, -444, -274, -66, +60, 430, 511, 656, 721, 587, 633, 194, +331, -412, -64, -761, -312, -681, -365, -251, +-316, 310, -188, 586, 156, 404, 512, 51, +699, -220, 746, -254, 413, -51, -147, 142, +-658, 32, -791, -233, -371, -461, 345, -421, +887, 56, 972, 594, 630, 807, 85, 483, +-487, -208, -718, -788, -464, -900, 16, -483, +486, 119, 640, 597, 612, 635, 432, 318, +102, -15, -230, -299, -522, -312, -505, -163, +-175, -140, 290, -166, 730, -147, 920, -61, +637, 225, 35, 420, -512, 363, -775, 83, +-521, -302, 30, -496, 613, -422, 906, -96, +800, 218, 376, 319, -215, 214, -579, -67, +-566, -220, -333, -145, 116, -5, 606, 159, +823, 208, 615, 19, 113, -188, -335, -380, +-526, -389, -316, -145, 67, 221, 390, 494, +616, 483, 411, 221, -13, -199, -257, -496, +-166, -535, 160, -345, 334, -29, 318, 228, +105, 321, -117, 301, -150, 245, 32, 123, +301, -39, 398, -292, 228, -570, -126, -577, +-240, -264, -24, 301, 235, 748, 411, 723, +330, 227, 5, -421, -365, -806, -363, -650, +56, -63, 590, 505, 800, 679, 406, 344, +-298, -323, -607, -766, -490, -628, 47, -10, +698, 670, 831, 945, 501, 512, -162, -333, +-570, -971, -374, -1006, 93, -412, 375, 375, +398, 807, 150, 689, -59, 264, 31, -129, +199, -300, 328, -310, 224, -307, -196, -403, +-530, -390, -371, -125, 192, 329, 723, 806, +922, 843, 471, 347, -126, -398, -569, -1015, +-691, -989, -243, -406, 297, 321, 609, 789, +560, 719, 257, 187, 97, -289, 76, -451, +68, -244, -49, 120, -324, 235, -456, 31, +-328, -337, 188, -530, 818, -327, 1047, 164, +774, 647, -23, 789, -789, 448, -1054, -246, +-712, -786, 113, -904, 858, -603, 1145, 65, +808, 586, 154, 733, -410, 543, -589, 137, +-451, -250, -132, -457, 234, -449, 326, -313, +332, -178, 328, 6, 269, 234, 265, 384, +100, 424, -204, 285, -373, -109, -309, -476, +-130, -565, 203, -404, 516, 6, 570, 374, +426, 494, 104, 341, -246, -25, -384, -313, +-315, -480, -120, -354, 214, 10, 480, 341, +527, 466, 333, 278, 36, -109, -193, -466, +-223, -529, -203, -247, -60, 162, 189, 422, +313, 417, 372, 128, 217, -155, -22, -232, +-59, -188, -73, -69, -79, -94, -81, -171, +-14, -152, 166, -34, 322, 300, 418, 539, +334, 455, 28, 54, -377, -469, -519, -828, +-293, -682, 203, -94, 697, 455, 798, 723, +448, 613, -147, 136, -602, -287, -663, -467, +-230, -452, 333, -222, 608, 6, 569, 118, +238, 119, -78, 73, -205, 125, -119, 200, +31, 196, 12, 41, -113, -193, -153, -417, +37, -465, 397, -250, 671, 53, 553, 393, +87, 521, -431, 394, -744, 76, -572, -255, +50, -473, 627, -525, 842, -351, 601, 19, +94, 393, -295, 592, -408, 476, -259, 35, +-65, -421, 53, -685, 76, -535, 77, -13, +261, 495, 513, 688, 586, 413, 276, -186, +-314, -668, -776, -686, -799, -268, -316, 325, +524, 743, 1097, 623, 1027, 59, 415, -502, +-459, -777, -845, -493, -640, 114, -117, 555, +357, 596, 531, 161, 377, -339, 152, -545, +11, -307, 18, 170, 174, 476, 63, 389, +-168, -64, -366, -512, -313, -586, 40, -263, +415, 255, 592, 602, 454, 548, 117, 171, +-276, -246, -419, -478, -254, -516, 30, -288, +241, 0, 277, 240, 143, 384, 26, 370, +45, 242, 114, 20, 203, -218, 159, -431, +-87, -468, -261, -310, -278, 25, -95, 397, +213, 530, 400, 407, 409, 35, 223, -351, +-66, -467, -255, -313, -234, -35, -88, 180, +77, 228, 192, 92, 181, -46, 101, -107, +38, -68, -6, 84, 101, 163, 233, 93, +147, -56, -38, -227, -213, -300, -249, -213, +-102, 4, 96, 222, 340, 355, 446, 282, +310, 68, 17, -175, -229, -342, -314, -278, +-191, -168, -83, 27, 46, 129, 250, 136, +327, 178, 363, 137, 225, 95, -8, -2, +-247, -202, -375, -303, -304, -269, -58, -86, +312, 146, 520, 318, 470, 227, 203, -12, +-191, -112, -405, -133, -361, 14, -105, 48, +229, -104, 396, -223, 300, -229, 138, -18, +-54, 291, -183, 387, -190, 249, -82, -62, +90, -345, 219, -408, 249, -170, 130, 76, +-54, 205, -169, 182, -190, 30, -21, -41, +266, -22, 455, 62, 277, 91, -154, -32, +-466, -228, -504, -359, -69, -254, 500, 86, +836, 447, 617, 601, -63, 339, -790, -189, +-952, -684, -438, -780, 431, -386, 1045, 276, +925, 753, 285, 775, -569, 351, -995, -242, +-627, -708, 165, -760, 769, -361, 735, 164, +174, 527, -417, 546, -476, 246, -119, -2, +261, -119, 482, -205, 276, -267, -161, -439, +-405, -435, -341, -27, -2, 516, 355, 907, +435, 710, 280, -60, 2, -858, -196, -1111, +-239, -617, -180, 240, -17, 936, 104, 878, +106, 342, 166, -348, 188, -679, 140, -525, +38, -192, -125, 178, -208, 338, -132, 343, +55, 143, 216, -94, 296, -247, 226, -232, +-152, -30, -379, 66, -259, 80, 48, 0, +454, -46, 537, 21, 219, 102, -197, 142, +-537, 79, -508, -133, -168, -280, 238, -274, +546, -129, 520, 214, 284, 374, -27, 351, +-312, 111, -391, -215, -268, -420, -117, -344, +25, -144, 161, 103, 349, 245, 412, 218, +339, 232, 94, 155, -239, 36, -385, -130, +-389, -408, -298, -482, -84, -270, 184, 77, +485, 462, 676, 602, 529, 436, 101, 49, +-480, -384, -841, -673, -716, -642, -219, -218, +446, 404, 803, 755, 750, 570, 312, 44, +-207, -477, -559, -595, -492, -234, -96, 232, +145, 418, 139, 164, -36, -213, -52, -404, +171, -234, 494, 212, 434, 455, 136, 309, +-322, -15, -759, -244, -705, -290, -206, -233, +520, -117, 1024, -60, 879, 100, 99, 377, +-727, 471, -1048, 177, -597, -315, 251, -575, +799, -446, 812, 61, 265, 476, -309, 439, +-632, 101, -585, -317, -127, -443, 406, -287, +704, 110, 455, 500, -31, 520, -395, 230, +-453, -232, -263, -621, -83, -744, 97, -433, +316, 194, 489, 811, 348, 1106, 44, 677, +-292, -261, -484, -1073, -387, -1283, -210, -673, +153, 276, 440, 1009, 536, 1094, 365, 599, +-14, -131, -348, -674, -461, -824, -284, -599, +-102, -59, 127, 411, 235, 538, 222, 404, +281, 61, 242, -173, 68, -134, -151, -97, +-354, -74, -534, -173, -359, -254, 8, -145, +508, 130, 849, 473, 628, 561, -6, 190, +-642, -422, -875, -733, -615, -586, 19, 24, +586, 635, 856, 764, 513, 429, -54, -229, +-454, -714, -551, -747, -277, -321, 15, 310, +200, 755, 224, 687, 171, 252, 82, -300, +31, -674, 28, -619, -29, -215, -180, 146, +-284, 361, -189, 430, 47, 395, 394, 244, +427, -85, 118, -442, -236, -641, -486, -484, +-311, -92, 91, 387, 440, 660, 508, 626, +72, 346, -419, -285, -575, -798, -331, -773, +257, -345, 662, 347, 556, 805, 121, 715, +-497, 149, -739, -491, -459, -761, 72, -468, +540, 152, 678, 608, 461, 568, -115, 101, +-598, -381, -655, -528, -349, -391, 174, 1, +512, 376, 506, 527, 310, 417, -135, 7, +-487, -360, -453, -596, -133, -469, 277, -92, +347, 337, 89, 620, -88, 531, -165, 141, +-33, -377, 85, -596, 67, -404, 41, -64, +-32, 250, -136, 326, -187, 239, -127, 113, +80, -23, 241, -109, 312, -166, 167, -193, +-136, -195, -333, -57, -426, 152, -208, 390, +188, 347, 427, -46, 433, -369, 103, -435, +-302, -191, -455, 211, -236, 373, 132, 279, +350, 47, 221, -189, -118, -321, -292, -253, +-284, -21, 15, 175, 271, 304, 436, 238, +229, 52, -210, -189, -537, -304, -469, -243, +-72, -36, 276, 139, 393, 192, 290, 226, +158, 154, 20, 27, -244, -197, -489, -374, +-432, -317, -114, -13, 350, 306, 532, 423, +351, 271, 8, -46, -286, -334, -391, -448, +-257, -189, 10, 140, 261, 337, 264, 259, +-36, 21, -315, -170, -221, -206, 169, -108, +405, 41, 227, 181, -85, 150, -367, 21, +-446, -211, -305, -292, 46, -82, 441, 140, +636, 318, 386, 341, -207, 107, -685, -230, +-706, -519, -232, -502, 367, -91, 705, 447, +506, 713, -62, 441, -546, -106, -525, -601, +-147, -610, 218, -201, 335, 248, 148, 507, +-118, 301, -144, -45, -86, -316, -27, -204, +78, 48, 79, 217, -43, 186, -134, -73, +-162, -323, -129, -357, 110, -46, 337, 300, +349, 524, -2, 396, -462, -52, -564, -510, +-328, -675, 141, -385, 469, 242, 544, 703, +367, 652, -4, 145, -559, -480, -858, -598, +-543, -267, 36, 45, 638, 186, 836, 203, +546, 203, -44, 244, -605, 177, -857, -140, +-592, -488, -34, -599, 457, -290, 673, 262, +561, 736, 191, 824, -298, 349, -725, -422, +-736, -973, -135, -945, 350, -338, 545, 504, +413, 1093, 33, 958, -236, 225, -369, -566, +-272, -963, 29, -762, 201, -134, 11, 451, +-187, 618, -96, 464, 151, 52, 240, -267, +81, -241, -31, 18, -80, 149, -234, -62, +-420, -395, -303, -521, 164, -189, 594, 501, +556, 936, 50, 710, -378, 14, -556, -751, +-535, -1039, -113, -658, 342, 55, 566, 649, +410, 795, -80, 517, -426, -3, -404, -383, +-203, -426, 60, -175, 286, -21, 223, -176, +-34, -219, -303, -84, -188, 401, 172, 777, +216, 617, -49, -75, -211, -775, -138, -969, +34, -603, 45, 241, -10, 875, 28, 923, +96, 360, -150, -416, -321, -868, -81, -675, +280, 11, 401, 679, 152, 759, -323, 137, +-587, -582, -433, -754, -18, -217, 557, 520, +633, 743, 182, 321, -393, -333, -587, -618, +-294, -444, 35, 56, 211, 459, 307, 487, +158, 125, -243, -282, -506, -474, -178, -308, +416, 172, 656, 499, 130, 460, -530, 13, +-653, -552, -314, -756, 33, -165, 293, 597, +457, 873, 402, 360, 13, -538, -429, -922, +-446, -468, -58, 390, 123, 862, -107, 593, +-247, -148, -87, -812, 303, -775, 461, -113, +300, 667, -28, 907, -397, 354, -617, -463, +-461, -825, -35, -530, 429, 192, 428, 719, +224, 589, 6, -44, -156, -635, -309, -701, +-179, -102, 56, 705, 98, 920, -156, 312, +-375, -719, -152, -1176, 337, -629, 605, 495, +278, 1228, -155, 986, -444, -95, -538, -1084, +-289, -1206, 100, -345, 432, 800, 319, 1360, +-79, 753, -336, -561, -158, -1455, 220, -1104, +271, 199, 86, 1402, -259, 1437, -385, 297, +-472, -1141, -216, -1616, 254, -709, 674, 724, +540, 1533, 30, 967, -394, -366, -550, -1313, +-437, -1053, -179, 36, 137, 1081, 378, 1175, +361, 374, 74, -757, -151, -1335, -85, -815, +-84, 314, -181, 1121, -252, 1081, -135, 278, +74, -661, 222, -1017, 299, -557, 67, 222, +-168, 781, -401, 556, -290, -211, 98, -795, +359, -483, 240, 395, -104, 1007, -243, 752, +-214, -245, -181, -1122, -36, -1234, 139, -321, +258, 856, 135, 1460, -100, 874, -238, -327, +-13, -1272, 18, -1103, -18, -77, -187, 944, +-141, 1113, -84, 368, 3, -684, 174, -1307, +337, -745, 367, 446, -99, 1404, -406, 1258, +-604, 165, -324, -1079, 23, -1601, 288, -928, +369, 308, 363, 1374, 253, 1356, -110, 439, +-339, -756, -547, -1188, -476, -667, -158, 225, +223, 701, 545, 468, 526, 35, 324, -432, +-255, -372, -602, 30, -702, 444, -308, 380, +261, -3, 678, -410, 593, -529, -21, -100, +-495, 332, -717, 481, -344, 201, 307, -119, +695, -393, 451, -366, -196, 28, -579, 385, +-552, 451, -40, 165, 382, -211, 395, -521, +170, -451, -258, -136, -469, 381, -281, 598, +283, 498, 552, 68, 360, -451, -342, -637, +-725, -437, -548, 67, -65, 431, 450, 531, +699, 267, 536, -179, -39, -394, -609, -248, +-867, 44, -420, 202, 354, 190, 662, 2, +409, -199, -205, -256, -536, -80, -340, 212, +240, 420, 631, 404, 447, -24, -284, -544, +-909, -767, -773, -377, -115, 365, 656, 979, +977, 878, 678, 52, -109, -874, -779, -1137, +-990, -528, -489, 426, 270, 1038, 735, 852, +531, 36, -25, -648, -299, -762, -336, -225, +-118, 325, 140, 456, 140, 60, 14, -341, +-252, -371, -340, 35, -131, 609, 416, 807, +588, 401, 136, -581, -483, -1373, -669, -1359, +-290, -108, 281, 1443, 648, 2052, 414, 1172, +-74, -631, -490, -1997, -607, -1851, -355, -352, +234, 1267, 628, 1789, 566, 868, 154, -632, +-486, -1365, -701, -865, -302, 425, 228, 1260, +473, 908, 132, -268, -172, -1315, -272, -1414, +-121, -304, 139, 1119, 303, 1787, 207, 1179, +-40, -313, -422, -1553, -526, -1753, -228, -627, +291, 920, 485, 1721, 224, 1129, -86, -339, +-189, -1553, -14, -1374, 102, 159, 83, 1598, +-249, 1659, -422, 283, -401, -1492, -84, -2228, +499, -1233, 855, 830, 622, 2412, -91, 2238, +-773, 450, -908, -1727, -529, -2679, 212, -1552, +614, 744, 470, 2254, 45, 1857, -196, 133, +-114, -1627, 207, -1809, 342, -309, -86, 1391, +-651, 1741, -928, 527, -581, -1293, 300, -2150, +1266, -1102, 1375, 1042, 429, 2487, -860, 1888, +-1541, -219, -1025, -2340, 38, -2622, 934, -698, +987, 1830, 313, 2850, -328, 1524, -629, -1020, +-355, -2741, 304, -2169, 629, 125, 118, 2351, +-482, 2592, -797, 812, -394, -1507, 444, -2614, +917, -1582, 613, 575, -147, 2129, -829, 1689, +-776, 50, -68, -1301, 658, -1239, 761, -72, +44, 871, -624, 715, -820, -245, -368, -889, +337, -694, 967, 326, 859, 1095, 39, 1003, +-864, 42, -1190, -1018, -442, -1162, 569, -357, +885, 661, 330, 914, -225, 403, -354, -478, +-146, -762, 159, -149, 277, 719, 140, 951, +-322, 214, -581, -945, -409, -1471, 255, -657, +764, 788, 605, 1717, -19, 1275, -545, -114, +-574, -1372, -298, -1707, 94, -700, 542, 811, +451, 1772, -64, 1238, -572, -241, -628, -1431, +-25, -1500, 501, -212, 649, 943, 276, 1331, +-77, 640, -475, -278, -764, -893, -531, -849, +6, -95, 709, 359, 766, 398, 333, 159, +-56, 1, -359, 203, -470, 463, -374, 208, +-220, -591, 144, -1165, 362, -934, 248, 254, +201, 1471, 59, 1791, -98, 655, -192, -1101, +-39, -2098, -23, -1523, -103, 236, -344, 1667, +-266, 1915, 109, 700, 513, -881, 567, -1772, +171, -1160, -232, 170, -603, 1376, -623, 1316, +-350, 26, 352, -1077, 733, -1118, 545, -74, +-59, 1058, -573, 1234, -529, 57, -192, -1211, +331, -1517, 485, -468, 398, 1280, -24, 2011, +-518, 1053, -602, -770, -262, -2060, 442, -1832, +634, -114, 419, 1513, -117, 2007, -502, 1134, +-441, -439, -76, -1572, 294, -1438, 346, -383, +89, 696, -321, 1087, -433, 486, -164, -221, +357, -543, 561, -101, 294, 407, -150, 533, +-686, 37, -472, -744, -132, -940, 272, -446, +451, 474, 165, 1140, -66, 895, -297, 96, +15, -651, 309, -697, 351, -244, -52, 237, +-672, 213, -906, -238, -388, -544, 578, -213, +1218, 540, 1190, 1180, 242, 1146, -941, 82, +-1498, -1231, -1150, -1767, 145, -1209, 1074, 193, +1296, 1477, 542, 1645, -466, 951, -917, -357, +-661, -1161, 24, -1165, 571, -372, 586, 550, +15, 727, -703, 286, -869, -381, -228, -655, +626, -223, 1198, 538, 777, 1137, -194, 864, +-963, -137, -1173, -1250, -696, -1677, 60, -908, +959, 563, 1253, 1577, 655, 1622, -2, 675, +-886, -618, -1070, -1349, -599, -1212, 101, -292, +582, 541, 870, 793, 586, 482, -62, -30, +-613, -185, -812, 7, -337, 55, 175, 90, +525, -138, 469, -433, 63, -343, -125, -12, +-293, 474, -267, 684, -286, 197, -158, -355, +65, -709, 230, -343, 540, 300, 470, 802, +50, 593, -662, -172, -799, -922, -574, -1046, +216, -201, 756, 850, 754, 1406, 374, 814, +-325, -265, -646, -1237, -481, -1323, -9, -411, +412, 650, 303, 1282, -131, 940, -362, -140, +-38, -920, 303, -918, 485, -85, 210, 707, +-292, 843, -750, 174, -579, -776, -59, -1002, +662, -472, 965, 718, 252, 1505, -465, 892, +-1134, -159, -642, -1317, 232, -1522, 970, -547, +1006, 746, 58, 1332, -986, 1026, -1112, 54, +-372, -849, 621, -684, 1158, -119, 628, 279, +-336, 73, -909, -258, -736, -406, -11, 93, +724, 743, 988, 966, 226, 513, -754, -540, +-1100, -1452, -565, -1343, 579, -157, 1330, 1209, +789, 1898, -265, 1017, -985, -519, -1047, -1556, +-289, -1601, 365, -387, 732, 914, 607, 1550, +27, 1118, -310, -106, -413, -1030, -240, -1200, +14, -641, 14, 263, -60, 844, -76, 817, +66, 529, 199, -28, 413, -514, 90, -732, +-209, -721, -555, -264, -280, 460, 235, 1070, +432, 974, 347, 200, -246, -801, -478, -1381, +-398, -940, 250, 225, 797, 1329, 807, 1655, +87, 661, -1134, -905, -1528, -1994, -767, -1688, +788, 8, 1760, 1760, 1615, 2465, 146, 1362, +-1383, -734, -1917, -2507, -1330, -2432, 258, -782, +1421, 1501, 1643, 2765, 655, 2075, -524, 97, +-1186, -1945, -921, -2596, -156, -1520, 546, 521, +462, 2233, 117, 2310, -162, 752, -141, -1114, +334, -2241, 309, -1686, 72, -108, -387, 1415, +-621, 2058, -286, 1310, 172, -228, 707, -1604, +669, -1903, 54, -911, -748, 476, -1037, 1607, +-444, 1493, 696, 636, 1357, -422, 938, -1091, +-194, -1116, -1356, -594, -1695, 156, -1039, 613, +472, 848, 1753, 572, 2038, 161, 940, -202, +-706, -486, -1934, -357, -1993, -342, -1002, -196, +323, -54, 1656, -2, 1970, 496, 1389, 838, +39, 861, -1467, 201, -1807, -784, -1635, -1488, +-253, -1466, 1058, -410, 1727, 1148, 1704, 2195, +458, 2149, -786, 430, -1700, -1749, -1569, -2982, +-490, -2304, 804, 80, 1389, 2386, 1197, 3019, +286, 1884, -642, -465, -1029, -2372, -980, -2501, +-294, -1278, 337, 652, 767, 1805, 680, 1636, +62, 690, -240, -468, -332, -885, -144, -695, +-72, -215, -105, 200, -224, 41, -319, -201, +-41, -247, 374, 104, 717, 673, 859, 934, +372, 516, -591, -190, -1311, -1015, -1311, -1279, +-539, -843, 741, 299, 1702, 1138, 1530, 1329, +508, 766, -843, -214, -1730, -957, -1330, -1116, +-248, -577, 872, 138, 1252, 911, 664, 995, +-335, 206, -974, -629, -501, -919, 319, -416, +918, 338, 576, 935, -373, 887, -1248, 135, +-1295, -619, -208, -1102, 1056, -937, 1705, -164, +1150, 781, -290, 1117, -1512, 848, -1481, 182, +-351, -401, 851, -752, 1335, -557, 610, -338, +-597, -150, -1345, -2, -791, 266, 588, 541, +1686, 668, 1622, 661, -41, 268, -1899, -391, +-2509, -1037, -1283, -1253, 953, -845, 2641, 199, +2414, 1330, 583, 1570, -1707, 993, -2754, -48, +-1776, -1107, 168, -1375, 2004, -1026, 2248, -96, +930, 733, -872, 1081, -2180, 923, -1858, 193, +-156, -600, 1608, -997, 2194, -771, 1322, 196, +-383, 1017, -1858, 1191, -2144, 235, -1035, -1069, +535, -1513, 1829, -1118, 2024, 206, 918, 1704, +-462, 2130, -1525, 1316, -1562, -544, -809, -2275, +157, -2658, 944, -1325, 994, 921, 545, 2577, +83, 2673, -272, 1234, -330, -1127, -281, -2588, +-491, -2323, -468, -816, -341, 1350, 268, 2210, +801, 1661, 746, 208, 412, -1243, -407, -1582, +-805, -936, -801, 281, -198, 1000, 511, 857, +697, 204, 417, -337, -217, -381, -628, -139, +-398, 131, 259, -57, 568, -276, 641, -319, +-37, 42, -1026, 556, -961, 847, -310, 550, +943, -337, 1657, -1075, 799, -1004, -441, -521, +-1686, 492, -1856, 1268, -565, 1084, 938, 482, +2209, -520, 1993, -1149, 224, -1070, -1670, -464, +-2549, 524, -1730, 1105, 43, 1001, 1817, 311, +2289, -597, 1371, -1151, -124, -840, -1487, 118, +-1801, 860, -1201, 1105, -99, 508, 936, -440, +1376, -1108, 1077, -976, 275, -178, -470, 702, +-902, 1043, -782, 898, -532, 151, 75, -674, +565, -952, 767, -835, 611, -314, -29, 595, +-399, 872, -786, 730, -593, 298, 57, -282, +488, -446, 691, -560, 393, -452, -361, -118, +-564, 82, -492, 372, -381, 731, 306, 546, +457, 262, 408, -326, 344, -955, -187, -859, +-219, -411, -330, 371, -466, 1102, -335, 1002, +-190, 459, 318, -359, 933, -1070, 901, -1103, +475, -389, -327, 359, -1421, 978, -1515, 962, +-689, 385, 767, -363, 1919, -703, 1715, -601, +351, -159, -1238, 166, -1908, 79, -1411, 96, +-61, 30, 1266, 421, 1674, 766, 1015, 418, +-343, -272, -1345, -975, -1357, -1494, -485, -971, +636, 496, 1139, 1734, 778, 2338, -23, 1308, +-686, -898, -776, -2570, -375, -2850, 60, -1167, +386, 1337, 569, 2979, 397, 2819, 83, 1120, +-211, -1431, -459, -2991, -456, -2787, -437, -1097, +-80, 1234, 500, 2881, 919, 2863, 899, 1136, +-30, -964, -878, -2684, -1222, -2827, -797, -1271, +82, 747, 880, 2415, 1297, 2603, 789, 1514, +-139, -341, -1096, -2029, -1248, -2494, -622, -1709, +171, 18, 820, 1596, 954, 2324, 675, 1693, +62, 324, -717, -1037, -1011, -1800, -785, -1654, +-310, -735, 454, 453, 1111, 1249, 1299, 1485, +664, 1062, -683, 151, -1640, -768, -1613, -1170, +-449, -1052, 984, -542, 1835, 311, 1721, 685, +346, 750, -1393, 609, -2232, 198, -1442, -69, +421, -210, 1825, -415, 1799, -527, 558, -549, +-1012, -483, -1789, 15, -1240, 655, 201, 1046, +1541, 1219, 1685, 646, 358, -612, -1289, -1538, +-1854, -1816, -1032, -1073, 397, 503, 1740, 1727, +1701, 2072, 437, 1334, -1110, -229, -1908, -1405, +-998, -2099, 409, -1545, 1329, -164, 1163, 1101, +-28, 1848, -770, 1559, -932, 561, -304, -679, +749, -1383, 1137, -1384, 537, -851, -757, 151, +-1531, 873, -1180, 1229, 180, 940, 1384, 241, +1737, -427, 1041, -851, -499, -730, -1630, -360, +-1784, 30, -1011, 131, 536, 263, 1429, 368, +1491, 526, 861, 597, -236, 456, -1055, -275, +-1233, -1071, -794, -1329, -66, -897, 548, 187, +659, 1282, 664, 1718, 450, 1089, -50, -20, +-261, -1099, -408, -1506, -440, -959, -349, -89, +-481, 588, -185, 576, 387, 424, 926, 319, +1202, 446, 858, 568, -194, 229, -1533, -475, +-2113, -1403, -1490, -1540, 128, -901, 2183, 441, +2734, 1856, 1598, 2212, -372, 1378, -2436, -146, +-2849, -1695, -1460, -2107, 712, -1527, 2282, -425, +2229, 800, 745, 1383, -991, 1395, -1734, 1052, +-1155, 508, 255, -233, 1163, -988, 910, -1526, +-200, -1711, -1352, -970, -1244, 358, -7, 1679, +1378, 2297, 2037, 1800, 1406, 532, -291, -1104, +-2052, -2237, -2725, -2332, -1756, -1439, 233, 118, +2198, 1718, 3088, 2454, 2243, 2149, 194, 884, +-2079, -797, -3383, -2123, -2692, -2583, -528, -1613, +1815, -17, 3157, 1485, 2677, 2435, 743, 1936, +-1445, 803, -2792, -755, -2458, -1937, -672, -2030, +1198, -1222, 2146, 246, 1748, 1463, 414, 1819, +-851, 1211, -1387, -75, -1239, -1181, -224, -1537, +611, -800, 727, 477, 828, 1186, 332, 1181, +-51, 227, -366, -1047, -1081, -1542, -1057, -1113, +-367, 244, 650, 1783, 1700, 2155, 1798, 1361, +800, -503, -943, -2302, -2702, -2714, -2986, -1854, +-1155, 212, 1516, 2386, 3666, 3115, 3761, 2483, +1408, 463, -1813, -1850, -4326, -3123, -4469, -3007, +-1806, -1382, 2010, 795, 4619, 2568, 4602, 3268, +1904, 2377, -1693, 536, -4211, -1593, -4494, -3181, +-2252, -3205, 1153, -1808, 3696, 551, 4080, 2789, +2282, 3664, -496, 2739, -2756, 324, -3453, -2364, +-2450, -3813, -179, -3085, 1897, -566, 2766, 2171, +2263, 3609, 686, 2803, -932, 272, -1871, -2249, +-1970, -3239, -1395, -2181, -161, 440, 979, 2609, +1687, 2816, 1937, 1293, 1234, -1045, -88, -2635, +-1445, -2328, -2484, -797, -2319, 1091, -890, 2137, +1166, 1790, 2912, 837, 3281, -250, 1744, -983, +-832, -1213, -3142, -1326, -4037, -1193, -2507, -594, +414, 461, 3141, 1815, 4319, 2704, 2982, 2406, +141, 610, -2723, -2030, -4064, -3837, -3265, -3848, +-859, -1635, 1908, 1608, 3531, 4095, 3195, 4598, +1420, 2448, -834, -762, -2736, -3455, -3012, -4154, +-2018, -2721, -18, -223, 1953, 1917, 2634, 2803, +2053, 2337, 413, 1202, -1199, -202, -2093, -1083, +-1828, -1359, -494, -1565, 773, -1242, 1448, -637, +1026, 278, 165, 1359, -404, 1954, -457, 1741, +-90, 626, 63, -744, -85, -1864, -501, -2075, +-711, -1202, -267, 74, 799, 1423, 1541, 1858, +1340, 1354, 42, 217, -1763, -1047, -2504, -1585, +-1710, -1066, 482, 35, 2767, 1109, 3225, 1424, +1757, 714, -1072, -554, -3458, -1605, -3642, -1722, +-1765, -581, 1202, 1075, 3579, 2246, 3742, 2237, +1830, 887, -995, -1140, -3161, -2534, -3389, -2734, +-1892, -1468, 413, 577, 2096, 2119, 2471, 2704, +1731, 2018, 476, 682, -548, -864, -1187, -1979, +-1402, -2399, -1369, -2075, -1072, -1006, -178, 649, +873, 2403, 1808, 3381, 2301, 2804, 1525, 665, +-95, -2097, -1995, -3844, -3049, -3666, -2432, -1551, +-512, 1259, 1657, 3217, 2868, 3428, 2655, 1931, +1112, -150, -824, -1689, -2242, -2194, -2460, -1819, +-1609, -1050, -124, -218, 1164, 608, 1835, 1431, +1962, 1949, 1169, 1852, -27, 865, -1283, -863, +-2223, -2366, -2081, -2895, -953, -1828, 904, 375, +2425, 2371, 2566, 3060, 1368, 2099, -593, -20, +-2296, -1880, -2544, -2492, -1420, -1656, 281, -172, +1770, 931, 2049, 1231, 1043, 840, -100, 418, +-754, 307, -864, 306, -519, 67, -343, -741, +-449, -1571, -491, -1687, -187, -713, 509, 1051, +1399, 2349, 1921, 2343, 1164, 1053, -558, -819, +-2124, -2233, -2936, -2354, -2024, -1292, 156, 155, +2282, 1363, 3246, 1630, 2504, 1349, 453, 849, +-1686, 133, -2806, -503, -2484, -1301, -1143, -1760, +644, -1657, 1883, -594, 1857, 953, 1291, 2215, +432, 2586, -338, 1475, -768, -331, -1232, -1928, +-1364, -2624, -1012, -1984, -219, -357, 800, 1140, +1596, 1830, 1694, 1730, 887, 777, -264, 31, +-1253, -376, -1462, -825, -977, -1066, -129, -1129, +320, -900, 530, -183, 297, 713, 144, 1372, +670, 1627, 974, 1310, 978, 426, 96, -774, +-1553, -1796, -2499, -2381, -2174, -1882, -567, -433, +1771, 1470, 3405, 3079, 3315, 3262, 1291, 1746, +-1677, -834, -3713, -3185, -3733, -4025, -1859, -2773, +1046, 65, 3150, 2822, 3566, 4017, 2223, 2947, +-202, 518, -2269, -2014, -2925, -3008, -2030, -2234, +-374, -634, 996, 839, 1694, 1189, 1324, 839, +685, 312, 360, 354, -191, 954, -407, 998, +-849, 220, -1447, -1284, -1162, -2825, -496, -2730, +702, -804, 1935, 1911, 2165, 3860, 1316, 3687, +-434, 1242, -2117, -1923, -2617, -3988, -1547, -3685, +317, -1232, 1768, 1685, 2144, 3181, 1433, 2563, +-97, 711, -1290, -1103, -1605, -1774, -894, -1026, +379, -50, 961, 693, 911, 583, 62, -301, +-872, -865, -999, -751, -552, 244, 598, 1225, +1526, 1455, 1577, 846, 633, -443, -1051, -1343, +-2286, -1336, -2291, -817, -1045, 59, 1202, 607, +2785, 742, 2663, 622, 1262, 419, -1109, 321, +-2483, 131, -2382, -209, -1180, -431, 694, -794, +1604, -859, 1405, -536, 668, -90, -238, 563, +-422, 1045, -36, 1239, 98, 1141, -28, 308, +-646, -719, -1184, -1613, -878, -2082, 76, -1326, +1228, 3, 1714, 1379, 1157, 2345, 10, 2101, +-1030, 770, -1403, -737, -988, -1831, -128, -1874, +341, -1162, 442, -210, 381, 585, 162, 940, +295, 1008, 439, 875, 440, 640, 181, 350, +-459, -81, -1023, -764, -1165, -1393, -762, -1560, +198, -1186, 1026, -59, 1355, 1237, 1300, 2214, +516, 2191, -545, 1270, -1296, -180, -1559, -1775, +-943, -2610, 121, -2587, 795, -1419, 1202, 555, +948, 2535, 128, 3481, -345, 2725, -586, 649, +-283, -1891, 87, -3511, 35, -3212, -216, -1312, +-630, 1074, -472, 2627, 30, 2579, 692, 1217, +1081, -301, 914, -1187, 156, -1169, -737, -630, +-1063, -175, -918, -83, -279, -236, 353, -213, +573, 243, 368, 770, 90, 1076, 103, 822, +162, -14, 369, -712, 403, -1073, -79, -956, +-674, -265, -1104, 286, -959, 513, -377, 392, +415, 263, 1211, 203, 1566, 289, 1284, 413, +362, 98, -803, -306, -1696, -812, -2012, -1128, +-1435, -800, -192, 25, 1252, 920, 2333, 1491, +2299, 1190, 1209, 397, -456, -519, -2015, -1104, +-2488, -1123, -1854, -693, -393, -217, 1217, 151, +2026, 599, 1700, 767, 810, 851, -241, 842, +-919, 222, -911, -483, -846, -1100, -407, -1478, +-185, -1043, -110, -97, 293, 839, 568, 1685, +995, 1661, 1051, 764, 409, -423, -459, -1573, +-1303, -1841, -1510, -1070, -912, 114, 259, 1090, +1287, 1503, 1449, 1026, 865, 252, -201, -512, +-1149, -906, -1129, -945, -467, -573, 436, -7, +1159, 475, 898, 928, 37, 883, -949, 278, +-1436, -366, -847, -949, 256, -1014, 1273, -468, +1690, 335, 1088, 970, -36, 1107, -1235, 699, +-1807, -238, -1400, -1016, -419, -1186, 758, -780, +1410, 19, 1533, 805, 1039, 1118, -118, 935, +-878, 298, -1173, -367, -1087, -899, -461, -1056, +-87, -664, 355, -56, 804, 535, 819, 959, +779, 878, 545, 479, 23, -1, -641, -476, +-1318, -976, -1529, -1132, -773, -766, 431, 135, +1479, 1207, 1836, 1831, 1204, 1409, -27, -58, +-1339, -1605, -1832, -2330, -1192, -1616, -54, 224, +1170, 1948, 1429, 2439, 704, 1476, -184, -406, +-1013, -2012, -905, -2339, -84, -1158, 619, 684, +895, 1963, 434, 1772, -274, 498, -758, -875, +-885, -1396, -499, -871, 222, 185, 793, 796, +943, 537, 632, -107, 140, -709, -371, -462, +-804, 445, -930, 951, -813, 830, -209, -128, +574, -1137, 1099, -1348, 1235, -591, 896, 650, +-2, 1522, -982, 1364, -1572, 66, -1539, -1143, +-606, -1572, 695, -902, 1628, 484, 1852, 1398, +1109, 1352, -142, 392, -1373, -842, -1942, -1414, +-1466, -1048, -371, -21, 996, 874, 1749, 1112, +1537, 688, 656, 38, -537, -483, -1269, -701, +-1302, -450, -689, -90, 156, -46, 605, 28, +741, 25, 453, 282, 153, 682, 115, 711, +70, 354, -92, -414, -442, -1094, -779, -1250, +-680, -716, -214, 320, 563, 1287, 1113, 1439, +1043, 778, 451, -149, -558, -963, -1211, -1146, +-1033, -671, -337, -95, 476, 404, 942, 537, +729, 342, 130, 162, -477, 206, -628, 175, +-240, 145, 295, -113, 479, -558, 344, -726, +-117, -657, -584, -94, -643, 588, -331, 1021, +325, 912, 860, 257, 814, -352, 292, -843, +-346, -775, -710, -479, -724, -69, -435, 371, +59, 544, 546, 566, 642, 351, 377, 46, +14, -298, -255, -422, -287, -361, -212, -113, +-43, 89, 133, 111, 26, 17, -182, -21, +-147, -70, -62, 154, 200, 404, 406, 396, +287, 283, 164, -308, -95, -710, -439, -739, +-500, -461, -210, 174, 137, 538, 243, 774, +180, 667, 42, 245, 74, -87, 216, -396, +218, -614, 152, -695, -46, -658, -428, -290, +-701, 333, -634, 937, -154, 1206, 577, 950, +1088, 271, 1033, -630, 387, -1277, -613, -1471, +-1197, -1073, -1105, -175, -431, 848, 483, 1601, +1018, 1826, 900, 1186, 304, -79, -350, -1389, +-840, -2181, -607, -1976, 47, -715, 614, 846, +753, 2043, 239, 2212, -471, 1149, -975, -287, +-855, -1427, -182, -1658, 791, -959, 1381, -96, +1155, 445, 255, 474, -954, 314, -1440, 249, +-1224, 581, -424, 856, 653, 508, 1088, -303, +1048, -1327, 591, -1688, -155, -1060, -457, 259, +-628, 1522, -596, 1860, -252, 1056, -96, -251, +125, -1255, 306, -1291, 305, -512, 432, 334, +242, 657, -24, 352, -127, -219, -230, -432, +-42, -137, -160, 508, -462, 829, -476, 468, +-235, -215, 268, -882, 860, -1026, 1062, -463, +670, 311, -65, 851, -909, 852, -1268, 211, +-886, -413, -199, -615, 491, -320, 884, 219, +878, 540, 474, 402, -25, -100, -296, -601, +-363, -874, -361, -570, -361, 281, -365, 940, +-248, 1220, -55, 879, 259, -13, 625, -942, +784, -1442, 764, -1336, 282, -437, -462, 624, +-1082, 1414, -1328, 1546, -994, 795, -57, -113, +1057, -990, 1650, -1348, 1418, -964, 442, -283, +-717, 319, -1396, 686, -1310, 738, -557, 624, +259, 447, 778, 80, 720, -403, 278, -840, +34, -926, 88, -539, 199, 185, 92, 853, +-233, 897, -730, 499, -886, -227, -424, -637, +338, -470, 991, -35, 1075, 411, 436, 456, +-399, -42, -843, -650, -720, -828, -114, -328, +326, 621, 471, 1190, 234, 1023, -239, 204, +-317, -855, -238, -1280, 140, -1009, 479, -171, +442, 804, 180, 1077, -275, 742, -481, -15, +-416, -610, -223, -657, 51, -276, 238, 227, +318, 414, 307, 260, 260, -85, 131, -408, +-156, -339, -357, -140, -370, 148, -327, 427, +-58, 431, 237, 386, 339, 109, 353, -294, +82, -586, -196, -785, -228, -545, -79, 0, +133, 724, 224, 1145, 97, 858, -156, 183, +-396, -663, -487, -1102, -259, -865, 256, -256, +717, 425, 844, 753, 479, 554, -194, 77, +-724, -282, -961, -194, -681, 99, -67, 349, +422, 225, 713, -286, 673, -748, 368, -912, +66, -475, -201, 464, -275, 1209, -235, 1424, +-433, 882, -665, -244, -554, -1292, -92, -1756, +650, -1404, 1287, -193, 1262, 1150, 656, 1836, +-333, 1634, -1346, 540, -1798, -799, -1338, -1552, +-228, -1541, 978, -689, 1807, 472, 1716, 1123, +829, 1088, -361, 445, -1315, -300, -1576, -640, +-1102, -408, -235, 55, 623, 352, 1022, 178, +834, -270, 418, -604, -48, -445, -162, 109, +-57, 679, -157, 910, -246, 589, -561, -109, +-726, -753, -480, -1008, -20, -688, 833, 0, +1404, 549, 1266, 840, 456, 714, -703, 182, +-1582, -263, -1648, -612, -925, -609, 194, -267, +1254, 65, 1540, 338, 1156, 377, 317, 302, +-557, 31, -997, -233, -1053, -193, -621, -68, +-112, 72, 347, 168, 659, -125, 610, -243, +408, -240, 192, -100, -79, 371, -281, 574, +-325, 463, -423, 28, -361, -667, -213, -927, +17, -577, 391, 131, 610, 899, 579, 1128, +240, 655, -195, -277, -642, -1135, -694, -1300, +-317, -584, 185, 501, 637, 1299, 455, 1316, +-42, 425, -412, -778, -445, -1447, -5, -1168, +497, -85, 668, 1091, 378, 1492, -331, 828, +-922, -336, -925, -1315, -396, -1424, 457, -480, +1083, 743, 986, 1526, 406, 1294, -324, 83, +-778, -1055, -708, -1562, -445, -1042, -41, 143, +216, 1114, 268, 1422, 422, 781, 407, -191, +329, -955, 263, -1121, -159, -617, -604, 113, +-824, 659, -647, 801, -46, 476, 574, -65, +835, -438, 707, -539, 320, -220, -144, 143, +-468, 343, -697, 355, -601, -61, -303, -457, +37, -505, 484, -192, 769, 429, 725, 839, +287, 734, -273, 129, -733, -737, -850, -1204, +-491, -1031, 88, -99, 688, 984, 876, 1428, +476, 1144, -187, -2, -648, -1043, -672, -1365, +-242, -1032, 323, 44, 656, 904, 579, 1127, +-7, 753, -572, -55, -802, -623, -522, -769, +258, -569, 807, -80, 877, 386, 430, 589, +-302, 548, -819, 200, -859, -265, -385, -640, +251, -673, 669, -246, 683, 302, 294, 778, +-228, 793, -444, 229, -318, -390, 39, -853, +291, -769, 164, -220, -146, 404, -515, 778, +-413, 562, 128, 123, 586, -244, 876, -392, +560, -199, -219, -152, -889, -111, -1093, -85, +-593, -80, 272, 230, 933, 451, 1016, 493, +441, 221, -288, -289, -704, -682, -730, -628, +-283, -231, 341, 291, 568, 621, 398, 492, +8, 218, -415, -153, -431, -427, -193, -295, +116, -167, 422, -49, 492, 56, 394, 144, +31, 254, -535, 310, -813, 212, -654, -150, +-152, -512, 547, -533, 883, -210, 844, 389, +529, 788, -218, 548, -882, -61, -1140, -783, +-755, -874, 30, -311, 705, 504, 1032, 1042, +740, 819, 179, -90, -347, -995, -735, -1207, +-581, -571, -127, 560, 181, 1337, 276, 1210, +162, 276, -100, -932, -100, -1545, 87, -1199, +295, 26, 435, 1222, 159, 1553, -201, 1024, +-549, -239, -729, -1257, -414, -1364, 180, -772, +723, 286, 843, 1113, 413, 1074, -190, 444, +-537, -389, -455, -808, -152, -588, 87, -61, +102, 388, -89, 392, -214, 20, -61, -309, +359, -288, 723, 128, 595, 479, -14, 470, +-731, -58, -1003, -607, -663, -700, 61, -313, +756, 449, 929, 928, 451, 678, -172, -87, +-464, -853, -382, -1051, -54, -432, 105, 478, +21, 1063, -100, 932, -172, 228, -96, -583, +231, -1058, 511, -805, 386, -146, -107, 449, +-539, 679, -438, 547, -14, 269, 431, 32, +466, -46, -34, -233, -481, -533, -787, -737, +-328, -627, 617, -93, 1196, 763, 1107, 1346, +-4, 1196, -1127, 348, -1501, -791, -1126, -1565, +46, -1509, 1205, -671, 1556, 599, 1099, 1476, +-73, 1507, -1090, 807, -1189, -316, -677, -1102, +154, -1191, 630, -759, 537, 24, 226, 656, +-194, 765, -222, 509, -3, 80, 217, -300, +321, -377, 111, -230, -219, 10, -508, 200, +-548, 209, -248, 14, 207, -293, 563, -342, +682, -175, 428, 81, 60, 371, -253, 515, +-607, 345, -628, 76, -357, -300, -11, -526, +311, -543, 433, -402, 445, -61, 417, 300, +204, 637, -104, 769, -353, 489, -505, 29, +-484, -471, -435, -823, -162, -805, 366, -546, +784, 5, 894, 585, 595, 925, -4, 1016, +-601, 555, -1132, -133, -1125, -764, -361, -1259, +539, -1047, 1141, -370, 1056, 461, 430, 1152, +-215, 1237, -694, 702, -769, -124, -424, -789, +38, -952, 308, -729, 319, -212, 114, 223, +-36, 419, -3, 460, 107, 354, 326, 258, +312, 213, -67, 34, -538, -215, -761, -632, +-510, -820, 143, -507, 705, -19, 845, 669, +656, 1105, 14, 983, -654, 358, -865, -522, +-668, -1229, 7, -1274, 603, -609, 703, 352, +473, 1116, -51, 1269, -456, 716, -538, -206, +-304, -907, 208, -1074, 471, -599, 362, 151, +64, 556, -241, 647, -329, 373, -208, 31, +-39, -201, 89, -268, 130, -197, 151, -182, +163, -167, 173, -44, 148, 169, -77, 381, +-307, 487, -484, 233, -419, -288, -59, -691, +381, -717, 783, -184, 655, 549, 97, 951, +-424, 713, -706, -76, -514, -773, -101, -931, +187, -486, 293, 278, 263, 787, 72, 692, +117, 139, 292, -433, 241, -544, 41, -204, +-520, 274, -895, 377, -693, 58, -22, -350, +785, -550, 1165, -216, 930, 414, 122, 804, +-788, 708, -1233, 12, -891, -739, -62, -1030, +676, -683, 908, 58, 562, 744, -28, 920, +-382, 655, -376, 89, -167, -497, 148, -674, +122, -634, -65, -307, -204, 117, -217, 436, +55, 588, 283, 418, 384, 91, 263, -204, +-39, -371, -253, -301, -329, -175, -217, -61, +-44, 15, 32, 19, 82, 140, 152, 278, +203, 343, 181, 307, 99, -65, 19, -402, +-146, -604, -249, -464, -308, -46, -280, 341, +-29, 609, 249, 517, 522, 132, 502, -215, +216, -385, -267, -402, -647, -176, -522, -20, +-134, 71, 278, 189, 505, 200, 365, 260, +-26, 154, -248, -93, -228, -226, -87, -334, +181, -147, 258, 119, 54, 228, -218, 183, +-425, -68, -303, -252, 202, -201, 548, 46, +485, 366, 152, 466, -333, 189, -499, -335, +-371, -659, -50, -590, 292, -157, 325, 433, +193, 685, -37, 557, -103, 168, -8, -259, +41, -410, -58, -361, -252, -241, -252, -190, +-18, -124, 327, 54, 531, 421, 355, 771, +-127, 642, -525, 180, -679, -573, -386, -1145, +211, -1032, 693, -338, 836, 612, 353, 1251, +-326, 1186, -720, 410, -758, -530, -303, -1127, +225, -1044, 489, -346, 588, 412, 405, 818, +81, 680, -193, 176, -455, -318, -549, -459, +-328, -279, 10, 34, 371, 285, 570, 227, +391, -59, 72, -294, -271, -316, -425, -37, +-235, 290, 30, 419, 202, 305, 112, -104, +-122, -436, -184, -400, -2, -79, 293, 315, +459, 447, 293, 169, -180, -341, -638, -606, +-712, -363, -245, 199, 450, 797, 883, 880, +702, 274, -2, -559, -656, -1164, -850, -1014, +-432, -161, 267, 742, 665, 1171, 620, 886, +138, 84, -387, -648, -467, -836, -275, -497, +49, 57, 219, 320, 148, 201, 32, -112, +-58, -197, 117, 100, 213, 485, 76, 661, +-127, 316, -432, -342, -367, -918, 77, -975, +305, -449, 355, 315, 178, 867, -124, 917, +-186, 532, -68, 28, 163, -355, 205, -544, +-81, -568, -465, -544, -621, -352, -211, 3, +458, 486, 964, 957, 941, 967, 206, 500, +-706, -321, -1261, -1070, -995, -1226, -117, -771, +728, 58, 1027, 775, 668, 1050, 91, 801, +-328, 296, -376, -255, -263, -608, -141, -690, +-220, -544, -351, -214, -195, 145, 192, 446, +728, 561, 922, 467, 532, 133, -179, -196, +-864, -359, -1168, -400, -745, -209, 37, -54, +746, 74, 1108, 135, 737, 146, 134, 185, +-398, 159, -734, 120, -665, -21, -336, -153, +82, -277, 444, -236, 505, -108, 270, 72, +62, 200, -160, 219, -252, 170, -108, 70, +33, -49, 102, -154, -35, -170, -280, -214, +-253, -81, 27, 104, 373, 228, 576, 332, +407, 113, -29, -180, -594, -409, -819, -412, +-432, -32, 243, 438, 751, 651, 689, 424, +237, -164, -310, -730, -593, -799, -459, -367, +-77, 374, 360, 845, 458, 763, 146, 199, +-164, -436, -225, -677, -104, -483, 106, 9, +168, 293, 8, 247, -181, 16, -205, -189, +-1, -25, 345, 276, 463, 459, 109, 283, +-382, -257, -602, -706, -356, -726, 129, -294, +524, 390, 645, 802, 269, 709, -215, 252, +-463, -331, -513, -589, -156, -459, 211, -138, +281, 102, 180, 115, 26, 46, -28, 25, +54, 198, 214, 384, 177, 357, -211, 67, +-602, -410, -646, -718, -220, -629, 568, -157, +1011, 448, 807, 814, 148, 697, -683, 273, +-1133, -305, -906, -656, -98, -670, 697, -404, +993, 39, 708, 424, 70, 575, -437, 479, +-595, 213, -430, -147, -165, -439, 9, -544, +87, -435, 118, -86, 261, 327, 494, 620, +454, 589, 50, 197, -495, -310, -842, -638, +-762, -587, -187, -238, 565, 247, 958, 551, +866, 547, 251, 275, -543, -76, -937, -408, +-754, -530, -228, -383, 327, -71, 604, 265, +448, 508, 208, 480, 5, 214, -130, -168, +-215, -433, -329, -492, -316, -299, -206, 70, +48, 346, 332, 367, 478, 225, 428, 9, +94, -137, -377, -143, -575, -77, -414, -61, +-50, -125, 309, -129, 425, -88, 327, 98, +19, 319, -242, 380, -324, 208, -154, -123, +162, -382, 144, -420, 35, -298, -13, 23, +-25, 251, 53, 374, 7, 347, -48, 138, +-95, -71, -82, -258, 10, -323, 160, -232, +325, -117, 192, 34, -189, 198, -439, 306, +-360, 303, 2, 167, 356, -57, 429, -314, +271, -425, -47, -311, -303, -19, -334, 301, +-121, 417, 220, 328, 284, 39, 64, -258, +-195, -278, -262, -190, -56, -46, 302, 95, +508, 125, 292, 63, -177, 78, -562, 54, +-640, -19, -248, -59, 380, -88, 736, -76, +713, -3, 186, 49, -451, 100, -732, 44, +-599, 5, -83, -22, 433, -129, 637, -110, +511, -12, 104, 100, -383, 207, -565, 217, +-399, 45, -9, -195, 422, -354, 504, -321, +288, -85, -72, 288, -442, 519, -465, 359, +-141, -9, 295, -341, 524, -439, 367, -229, +-43, 89, -469, 213, -584, 144, -335, 23, +194, -86, 735, 24, 773, 198, 265, 256, +-507, 52, -953, -273, -813, -551, -187, -466, +604, -70, 1054, 414, 877, 759, 134, 613, +-692, 151, -1050, -405, -711, -769, -67, -697, +476, -262, 700, 214, 507, 569, 80, 668, +-258, 432, -351, 109, -164, -217, 32, -532, +-87, -646, -216, -567, -239, -210, -52, 408, +302, 940, 491, 977, 485, 462, 179, -384, +-339, -1081, -694, -1147, -687, -562, -318, 306, +203, 1018, 523, 1090, 601, 592, 394, -147, +75, -775, -265, -892, -494, -603, -493, -95, +-364, 460, -72, 696, 240, 620, 482, 268, +562, -197, 288, -540, -161, -559, -494, -315, +-644, 6, -362, 343, 147, 405, 531, 344, +599, 106, 165, -116, -337, -285, -606, -349, +-423, -193, 86, -22, 505, 143, 605, 270, +278, 333, -204, 237, -645, 1, -667, -337, +-273, -608, 259, -483, 682, 17, 692, 568, +361, 865, -163, 606, -644, -131, -704, -799, +-380, -1057, 108, -571, 554, 292, 584, 915, +321, 994, -38, 367, -372, -374, -335, -762, +-121, -613, 98, -141, 228, 302, 86, 362, +-115, 112, -200, -83, -77, -67, 253, 153, +447, 334, 337, 225, 17, -210, -442, -592, +-621, -587, -364, -179, 87, 434, 552, 766, +715, 581, 424, 20, -102, -525, -571, -658, +-583, -377, -205, 165, 261, 577, 458, 498, +259, 42, -39, -451, -188, -622, -62, -260, +113, 334, 164, 732, 121, 561, -69, -12, +-298, -541, -284, -712, -78, -416, 291, 57, +578, 402, 393, 491, -19, 370, -412, 127, +-619, -133, -387, -294, 138, -372, 558, -264, +676, -52, 339, 150, -249, 324, -633, 281, +-646, 40, -205, -205, 362, -232, 696, -32, +632, 253, 155, 336, -452, 83, -775, -343, +-630, -650, -173, -530, 456, 4, 821, 651, +728, 1031, 266, 802, -434, 25, -901, -835, +-886, -1268, -348, -1081, 365, -227, 890, 832, +868, 1433, 340, 1268, -269, 364, -713, -775, +-700, -1421, -408, -1204, 6, -274, 313, 698, +380, 1060, 377, 752, 248, 26, 86, -401, +-92, -320, -330, -69, -568, -3, -582, -257, +-270, -423, 233, -254, 673, 291, 789, 817, +471, 774, -152, 202, -676, -581, -953, -998, +-738, -772, -73, -52, 604, 654, 960, 921, +745, 633, 69, 7, -593, -583, -878, -811, +-627, -563, -34, -8, 405, 548, 519, 705, +308, 477, -15, -6, -177, -441, -205, -544, +-112, -359, -94, -38, -149, 244, -121, 307, +41, 256, 270, 207, 348, 39, 135, -115, +-157, -293, -360, -415, -351, -216, -83, 54, +186, 346, 381, 451, 296, 260, -56, -70, +-358, -330, -338, -385, -58, -183, 300, 143, +428, 264, 214, 210, -142, 6, -458, -168, +-478, -160, -129, -87, 363, 18, 663, 105, +590, 153, 110, 227, -486, 167, -746, -112, +-533, -459, 21, -607, 437, -299, 537, 353, +482, 868, 289, 811, 40, 219, -294, -498, +-683, -933, -619, -805, -154, -297, 416, 322, +810, 747, 654, 831, 212, 570, -319, -35, +-609, -651, -465, -915, -24, -732, 349, -116, +376, 630, 114, 923, -191, 617, -209, -5, +90, -553, 394, -617, 394, -269, 58, 99, +-375, 273, -527, 206, -346, 149, -11, 51, +352, -158, 594, -283, 584, -167, 227, 212, +-277, 491, -707, 321, -608, -260, -85, -717, +291, -521, 480, 78, 426, 648, 217, 772, +-8, 310, -323, -324, -454, -738, -204, -680, +105, -164, 330, 457, 237, 740, 5, 503, +-118, -56, -154, -478, -43, -480, 66, -216, +107, 90, 123, 195, -48, 170, -266, 164, +-204, 79, -10, -7, 299, -93, 403, -76, +22, -20, -394, -75, -519, -198, -168, -209, +346, 60, 534, 446, 253, 513, -158, 150, +-463, -373, -539, -597, -222, -365, 235, 116, +580, 491, 458, 387, -36, 32, -470, -329, +-531, -380, -237, -39, 92, 332, 313, 429, +317, 144, 112, -285, -191, -550, -406, -386, +-249, -1, 95, 390, 325, 606, 245, 414, +-97, 17, -386, -413, -425, -598, -151, -389, +224, -10, 520, 327, 474, 431, 2, 274, +-503, 85, -749, -111, -473, -234, 120, -267, +618, -155, 696, 46, 252, 157, -261, 146, +-567, -4, -540, -54, -171, 3, 211, 115, +383, 126, 355, -16, 54, -156, -295, -226, +-365, -161, -139, 9, 236, 191, 425, 291, +196, 204, -247, 2, -563, -232, -511, -362, +28, -230, 615, 75, 773, 395, 471, 454, +-219, 171, -758, -339, -772, -721, -431, -554, +211, 91, 774, 845, 840, 1029, 450, 473, +-221, -500, -690, -1246, -678, -1139, -359, -260, +183, 782, 578, 1327, 660, 1074, 327, 110, +-285, -824, -563, -1186, -345, -787, 136, 5, +415, 617, 254, 798, -69, 468, -261, -65, +-174, -355, 71, -336, 312, -63, 414, 191, +130, 86, -309, -195, -484, -369, -368, -194, +137, 210, 659, 501, 593, 542, 213, 209, +-305, -287, -621, -643, -479, -623, -54, -172, +383, 353, 661, 641, 561, 422, 62, 27, +-472, -304, -723, -394, -382, -217, 190, 10, +571, 211, 606, 232, 227, 142, -216, -67, +-512, -151, -506, -178, -115, -138, 410, 31, +652, 117, 324, 191, -211, 159, -477, 135, +-328, 45, 9, -195, 151, -420, 153, -444, +137, -160, 94, 368, 100, 724, -17, 609, +-114, 116, -195, -495, -242, -777, -173, -646, +107, -46, 313, 563, 315, 751, 121, 414, +-232, -129, -313, -494, -145, -501, 68, -70, +154, 271, -9, 375, -190, 129, -136, -259, +-14, -388, 131, -165, 242, 258, 240, 444, +150, 273, -221, -85, -611, -355, -551, -411, +-133, -179, 430, 197, 584, 404, 344, 305, +-8, -55, -298, -388, -385, -345, -178, 67, +42, 441, 31, 430, -175, -12, -289, -500, +-74, -628, 423, -229, 669, 378, 388, 740, +-213, 556, -701, -24, -747, -575, -448, -728, +117, -390, 603, 180, 691, 625, 374, 600, +-122, 174, -546, -287, -517, -522, -158, -432, +211, -48, 295, 314, 15, 538, -235, 319, +-229, -171, 53, -527, 289, -450, 263, 77, +198, 509, -40, 428, -294, -68, -519, -404, +-441, -363, -18, 39, 511, 387, 606, 363, +327, 55, -104, -363, -425, -472, -322, -278, +-101, 141, 85, 521, 166, 514, -34, 265, +-103, -253, 107, -637, 217, -555, 272, -152, +30, 391, -202, 584, -248, 339, -306, -84, +-100, -363, 307, -259, 469, -38, 327, 223, +-87, 311, -368, 53, -330, -372, -149, -595, +41, -363, 395, 294, 567, 895, 342, 919, +-336, 233, -737, -645, -435, -1084, 209, -872, +523, -192, 357, 511, 154, 940, -43, 820, +-187, 397, -204, -245, -119, -785, 71, -827, +156, -370, 16, 227, -17, 516, 93, 474, +39, 106, -33, -163, 74, -165, 114, -81, +118, 110, -63, 232, -165, 135, -176, -207, +-181, -513, -83, -560, 208, -96, 551, 523, +572, 858, -54, 652, -574, -23, -533, -600, +-202, -760, 24, -551, 217, -26, 413, 447, +464, 555, 154, 379, -322, -89, -530, -415, +-247, -279, 96, 262, 229, 562, 245, 236, +111, -515, -79, -1009, -322, -647, -240, 367, +134, 1180, 341, 1096, 251, 204, 77, -749, +-231, -1111, -387, -658, -392, 156, -87, 721, +365, 674, 518, 178, 145, -376, -177, -580, +-138, -328, -26, 248, -216, 688, -334, 585, +-120, -57, 244, -816, 368, -954, 144, -305, +-78, 650, -70, 1041, -155, 614, -261, -359, +-115, -836, 187, -485, 314, 197, -25, 682, +-314, 428, -285, -362, -67, -890, 278, -628, +386, 311, 243, 1090, -47, 1077, -458, 190, +-501, -893, -285, -1291, 111, -652, 304, 330, +422, 944, 370, 832, 84, 69, -392, -623, +-507, -699, -223, -52, 112, 647, 149, 694, +-59, -25, -25, -820, 196, -1012, 253, -281, +138, 733, -6, 1213, -171, 871, -373, -164, +-401, -1121, -81, -1291, 389, -406, 432, 800, +87, 1351, -249, 722, -181, -580, 109, -1291, +176, -910, 121, 413, -28, 1422, -246, 1243, +-515, -66, -341, -1446, 160, -1769, 712, -555, +685, 1135, 254, 1934, -315, 1248, -547, -449, +-583, -1657, -298, -1557, 214, -266, 444, 1128, +446, 1539, 103, 600, -214, -677, -130, -1318, +62, -812, 187, 366, 119, 1179, -198, 1059, +-498, 95, -429, -972, 27, -1356, 612, -718, +682, 541, 291, 1384, -149, 1146, -388, 10, +-321, -990, -251, -1126, -34, -411, 108, 508, +177, 897, 51, 490, 19, -282, 204, -746, +369, -546, 179, 204, -110, 792, -434, 676, +-518, -7, -271, -634, 134, -796, 430, -349, +501, 334, 253, 676, -113, 359, -281, -104, +-221, -390, 16, -193, 146, 302, 100, 495, +-183, 180, -376, -467, -217, -909, 179, -826, +534, -14, 501, 1079, 297, 1653, -51, 1048, +-489, -413, -694, -1689, -613, -1906, -55, -831, +569, 755, 695, 1856, 398, 1694, 126, 479, +-172, -1001, -275, -1718, -399, -1118, -335, 169, +-96, 1076, 73, 1077, 186, 275, 243, -561, +276, -810, 131, -383, -43, 394, -135, 718, +-115, 432, -155, -307, -278, -839, -177, -544, +96, 246, 328, 811, 233, 726, 62, 1, +-32, -809, -138, -1017, -165, -335, -87, 750, +169, 1333, 256, 845, -120, -364, -532, -1491, +-418, -1482, 100, -234, 651, 1165, 552, 1708, +147, 965, -177, -456, -362, -1483, -419, -1232, +-381, -113, -150, 857, 134, 1007, 412, 342, +439, -457, 345, -728, 84, -240, -293, 480, +-433, 699, -368, 257, -200, -492, -53, -1004, +144, -691, 403, 282, 539, 1058, 208, 1192, +-227, 446, -400, -736, -374, -1414, -109, -1072, +89, 39, 143, 1128, 213, 1353, 65, 528, +-167, -565, -95, -1210, 179, -761, 313, 204, +88, 801, -296, 696, -443, -54, -228, -627, +71, -492, 296, 80, 316, 453, 230, 506, +131, 110, -200, -340, -486, -681, -376, -567, +21, 34, 498, 720, 520, 1165, 27, 622, +-468, -468, -522, -1359, -87, -1302, 318, -325, +409, 1005, 351, 1644, 72, 1045, -258, -203, +-415, -1252, -419, -1325, -148, -509, 271, 551, +414, 959, 283, 647, 196, -69, 76, -484, +-120, -277, -408, 126, -514, 429, -317, 125, +148, -534, 580, -745, 500, -356, 207, 392, +-69, 963, -302, 929, -349, 210, -209, -697, +-4, -1214, 171, -843, 79, 87, -24, 931, +86, 1059, 234, 329, 336, -462, 96, -694, +-407, -389, -618, 5, -348, 270, 181, 280, +629, 145, 611, 21, 84, -71, -436, -222, +-654, -173, -373, -74, 252, 94, 646, 221, +631, 385, -90, 219, -736, -206, -703, -597, +-92, -561, 688, -66, 775, 572, 127, 878, +-545, 315, -694, -490, -255, -881, 472, -526, +771, 403, 495, 1125, -343, 757, -1097, -493, +-957, -1564, 25, -1302, 1201, 169, 1489, 1932, +620, 2279, -857, 805, -1641, -1566, -1211, -3050, +8, -2222, 1221, 383, 1463, 2852, 611, 3181, +-452, 1121, -1098, -1641, -1017, -3032, -54, -2121, +753, 125, 903, 2032, 305, 2249, -593, 909, +-937, -994, -291, -1983, 585, -1192, 868, 492, +448, 1605, -378, 1276, -587, -261, -536, -1435, +-248, -1334, 91, -71, 326, 1276, 675, 1259, +493, 391, 45, -829, -441, -1150, -587, -348, +-454, 655, -272, 805, 89, 99, 602, -797, +777, -1001, 506, -89, -92, 1338, -776, 1764, +-894, 557, -627, -1422, 209, -2638, 953, -1705, +1139, 933, 500, 2919, -680, 2630, -1310, 349, +-978, -2230, 67, -3105, 1115, -1613, 1384, 1010, +498, 2845, -637, 2368, -1407, 1, -1124, -2128, +84, -2491, 1206, -609, 1316, 1739, 370, 2327, +-751, 748, -1122, -1377, -583, -2545, 250, -1256, +880, 1257, 666, 2806, -52, 2162, -739, -396, +-782, -2841, -20, -3168, 789, -1036, 990, 1983, +199, 3615, -802, 2511, -1191, -508, -636, -3013, +555, -3130, 1327, -933, 1060, 1810, -169, 2765, +-1226, 1544, -1311, -627, -290, -2023, 868, -1511, +1377, 24, 731, 1529, -378, 1625, -1178, 143, +-1221, -1375, -38, -1889, 942, -791, 1235, 992, +481, 2192, -711, 1664, -1043, -126, -472, -1731, +379, -2162, 824, -996, 444, 850, -297, 1869, +-700, 1363, -659, -108, 93, -1120, 996, -1023, +977, -28, 128, 752, -895, 691, -1297, -253, +-555, -890, 551, -712, 1154, 106, 920, 942, +3, 1071, -766, 315, -1033, -629, -342, -1130, +508, -667, 856, 343, 469, 863, -411, 784, +-779, -220, -634, -916, 199, -881, 968, -47, +901, 1026, 190, 1473, -788, 767, -1357, -728, +-806, -1853, 415, -1744, 1254, -186, 1277, 1517, +399, 2104, -786, 1156, -1393, -610, -1093, -1622, +132, -1547, 1112, -241, 1279, 1051, 530, 1394, +-603, 524, -1134, -640, -713, -1194, -8, -708, +609, 254, 754, 1022, 354, 1005, -163, 104, +-476, -452, -292, -835, -77, -508, 144, -7, +175, 166, -108, 6, -286, -33, 62, 316, +380, 792, 621, 804, 333, 159, -442, -722, +-997, -1556, -907, -1328, 36, -169, 846, 1079, +1165, 1840, 750, 1299, -387, 67, -1053, -1159, +-845, -1396, -63, -806, 497, 115, 554, 740, +65, 650, -316, 112, -173, -476, 300, -259, +500, 478, 239, 864, -346, 512, -905, -400, +-617, -1375, 111, -1286, 885, -458, 917, 783, +155, 1514, -562, 1299, -836, 456, -316, -620, +456, -1033, 682, -885, 339, -465, -404, -250, +-1076, -19, -623, 411, 464, 929, 1317, 1415, +1415, 989, 83, -117, -1334, -1669, -1902, -2396, +-1083, -1479, 500, 353, 1795, 2214, 1918, 2593, +740, 1353, -1092, -737, -1944, -2187, -1545, -2125, +-111, -801, 1539, 909, 1659, 1741, 753, 1212, +-584, 90, -1376, -791, -1019, -915, -17, -271, +799, 276, 971, 388, 467, 64, -259, -283, +-709, -152, -800, 308, -154, 417, 323, 62, +466, -531, 651, -823, 205, -79, -16, 729, +-332, 1155, -626, 786, -635, -526, -409, -1589, +270, -1643, 995, -441, 1115, 1379, 582, 2312, +-530, 1584, -1394, -216, -1210, -2000, -358, -2309, +648, -1126, 1306, 643, 1121, 2017, 365, 2001, +-740, 723, -1418, -928, -1047, -1772, 19, -1365, +1144, -250, 1184, 921, 476, 1183, -469, 641, +-1064, -65, -796, -585, -146, -453, 692, -172, +1001, 69, 477, 201, -124, 7, -748, 5, +-808, 9, -485, -72, 157, -6, 910, 80, +921, 229, 386, 211, -422, 109, -1041, -242, +-863, -659, -342, -621, 530, -125, 1288, 680, +1162, 1230, 71, 909, -1056, -136, -1547, -1285, +-896, -1621, 307, -877, 1089, 549, 1401, 1800, +837, 1850, -126, 670, -1109, -1103, -1383, -2266, +-918, -1861, 24, -201, 876, 1740, 1250, 2464, +1083, 1573, 364, -474, -566, -2065, -1333, -2082, +-1290, -997, -634, 746, 344, 1595, 1304, 1406, +1496, 615, 1030, -240, -253, -691, -1442, -797, +-1735, -687, -1029, -613, 339, -371, 1370, 209, +1766, 1106, 1085, 1721, -279, 1335, -1400, -5, +-1582, -1655, -878, -2538, 132, -1877, 825, 46, +1085, 1883, 1090, 2725, 640, 2001, -103, 56, +-1006, -1706, -1412, -2399, -1288, -1773, -657, -248, +704, 1126, 1985, 1644, 2245, 1282, 1078, 451, +-925, -157, -2529, -664, -2453, -793, -911, -819, +1129, -722, 2495, -151, 2358, 550, 487, 1101, +-1586, 1115, -2361, 498, -1396, -533, 501, -1104, +1679, -907, 1667, -225, 255, 519, -1080, 719, +-1526, 301, -1051, -205, 392, -475, 1438, -408, +1426, 255, 516, 659, -595, 792, -1323, 308, +-1154, -676, -395, -1241, 362, -1136, 818, -303, +714, 844, 669, 1598, 324, 1326, -120, 360, +-740, -796, -1171, -1536, -822, -1360, 105, -380, +949, 756, 1112, 1351, 631, 1027, -369, 5, +-934, -874, -823, -1053, -2, -238, 967, 766, +1042, 1103, 113, 588, -1096, -665, -1672, -1565, +-889, -1482, 771, -134, 2052, 1434, 2098, 2188, +481, 1525, -1477, -25, -2511, -1706, -1965, -2294, +-18, -1608, 1804, -31, 2356, 1595, 1325, 2105, +-588, 1523, -1854, -118, -1583, -1241, -290, -1492, +1217, -973, 1450, 88, 664, 683, -743, 909, +-1668, 502, -1203, -211, 32, -499, 1630, -512, +2091, 7, 1192, 629, -629, 636, -2329, 187, +-2380, -572, -957, -1102, 1101, -815, 2554, 80, +2263, 1161, 523, 1359, -1507, 739, -2519, -531, +-1724, -1460, 310, -1330, 2058, -153, 2300, 1213, +541, 1614, -1654, 684, -2567, -1060, -1544, -2012, +1026, -1335, 2927, 703, 2526, 2369, 317, 2431, +-2283, 674, -3215, -1987, -1985, -3327, 611, -2587, +2690, -40, 2809, 2795, 1172, 3926, -1210, 2621, +-2372, -460, -1711, -3220, 58, -4052, 1183, -2321, +1089, 767, 257, 3265, -644, 3566, -535, 1793, +188, -879, 842, -2697, 774, -2838, -173, -1362, +-1263, 756, -1455, 2080, -424, 2171, 1019, 983, +1744, -569, 1238, -1646, -42, -1662, -1362, -708, +-1591, 494, -839, 1418, 352, 1403, 1305, 518, +1165, -740, 451, -1370, -169, -1185, -723, -162, +-765, 944, -615, 1357, -479, 883, 46, -245, +722, -968, 1270, -1149, 1262, -445, 499, 385, +-933, 796, -2130, 614, -2079, 211, -617, -189, +1600, -277, 2727, -222, 2223, -306, 213, -303, +-1913, -201, -2681, 213, -1937, 644, 172, 835, +2105, 322, 2399, -419, 1057, -1036, -836, -1086, +-1976, -223, -1483, 565, -75, 1394, 1311, 1144, +1589, 177, 586, -810, -786, -1548, -1778, -1163, +-1180, -116, 418, 979, 1593, 1506, 1730, 1195, +507, 135, -1010, -880, -1859, -1520, -1344, -1288, +-103, -333, 1142, 828, 1691, 1471, 1079, 1424, +35, 456, -1097, -680, -1524, -1249, -869, -1440, +-48, -663, 876, 175, 1259, 919, 840, 1495, +249, 1161, -667, 398, -1261, -636, -994, -1607, +-284, -1726, 663, -779, 1222, 396, 950, 1665, +339, 1968, -678, 1070, -1338, -167, -931, -1453, +-120, -1901, 898, -1303, 1310, -130, 564, 1034, +-287, 1759, -1020, 1393, -984, 349, -234, -704, +728, -1362, 1022, -1135, 503, -393, -310, 182, +-887, 622, -658, 746, -108, 611, 541, 568, +739, 39, 364, -657, -86, -968, -663, -982, +-595, -320, -147, 600, 327, 1156, 625, 1012, +368, 612, 36, -490, -368, -1255, -587, -1131, +-427, -644, -95, 514, 309, 1177, 831, 1022, +855, 546, 219, -130, -693, -746, -1385, -918, +-1106, -990, -46, -624, 1125, 365, 1678, 1332, +1184, 1840, -75, 1264, -1452, -285, -1945, -1972, +-1200, -2652, 552, -1636, 1853, 450, 1802, 2469, +548, 3052, -892, 1830, -1709, -584, -1289, -2681, +-64, -3138, 1104, -1678, 1521, 639, 726, 2574, +-531, 2555, -1358, 1174, -895, -532, 201, -1695, +847, -1398, 843, -839, 196, -4, -560, 390, +-761, 365, -318, 672, 390, 819, 843, 784, +373, 383, -485, -657, -933, -1600, -578, -1588, +497, -593, 1149, 788, 953, 1857, -56, 1671, +-1234, 437, -1650, -663, -508, -1314, 955, -1166, +1964, -450, 1447, 47, -309, 420, -1676, 501, +-2160, 664, -939, 714, 835, 678, 2259, 143, +2239, -895, 464, -1610, -1435, -1753, -2591, -559, +-1938, 1231, -146, 2415, 1627, 2262, 2540, 702, +1805, -1381, 64, -2534, -1524, -2407, -2352, -847, +-1722, 1175, -110, 2304, 1254, 2245, 2056, 904, +1540, -772, 201, -1722, -1038, -1730, -1602, -931, +-1193, 212, -96, 879, 727, 1173, 1096, 998, +622, 251, -188, -218, -507, -599, -491, -705, +131, -475, 519, -268, 265, -145, -251, 107, +-792, 577, -717, 754, 9, 815, 858, 424, +1179, -357, 665, -1109, -320, -1374, -1070, -872, +-1174, 121, -564, 1220, 319, 1666, 921, 1075, +978, -7, 600, -958, 76, -1437, -484, -1042, +-873, -190, -1105, 444, -952, 804, 17, 759, +1414, 461, 2156, 276, 1660, -38, -109, -463, +-2206, -715, -3061, -840, -2057, -404, 323, 179, +2859, 594, 3753, 758, 2154, 619, -797, 330, +-3319, 63, -3693, -260, -1557, -729, 1170, -958, +2908, -1011, 2747, -473, 824, 651, -1124, 1569, +-1888, 1918, -1363, 1245, -30, -386, 722, -1897, +523, -2546, -80, -1769, -395, -60, -172, 1728, +313, 2515, 893, 1973, 927, 743, 338, -801, +-687, -1884, -1428, -2042, -1472, -1680, -827, -645, +476, 746, 1454, 2148, 2094, 2750, 1790, 2070, +294, 312, -1453, -2033, -2968, -3402, -2803, -3093, +-925, -1156, 1575, 1350, 3676, 3365, 3561, 3766, +1218, 2072, -1866, -625, -4074, -2964, -3674, -3824, +-1075, -2518, 2112, -11, 3918, 2217, 3233, 3104, +748, 2344, -2020, 675, -3324, -1060, -2593, -2093, +-476, -1973, 1719, -1123, 2529, 16, 1882, 1089, +376, 1666, -1144, 1374, -1615, 495, -1269, -598, +-616, -1446, 282, -1467, 780, -466, 1134, 823, +1303, 1605, 567, 1367, -359, -50, -1420, -1493, +-2000, -2189, -1277, -1419, 207, 644, 1873, 2539, +2779, 3150, 1880, 1729, -257, -1226, -2475, -3566, +-3507, -3932, -2212, -1977, 331, 1275, 2793, 3743, +3983, 4281, 2644, 2449, -155, -575, -2854, -3077, +-4211, -4117, -3072, -2909, -385, -582, 2445, 1741, +4180, 3111, 3577, 3150, 1277, 2006, -1719, 134, +-3871, -1674, -3919, -3131, -2277, -3331, 696, -2064, +3232, 275, 4022, 2913, 3142, 4291, 402, 3411, +-2377, 667, -3787, -2642, -3573, -4566, -1390, -3817, +1358, -1016, 3182, 2275, 3505, 4241, 2034, 3552, +-350, 890, -2160, -2034, -2933, -3642, -2431, -2988, +-805, -561, 909, 2058, 2315, 3222, 2704, 2484, +1873, 151, 187, -2219, -1758, -2962, -2931, -2120, +-2810, -17, -1024, 1939, 1329, 2734, 3180, 2181, +3441, 534, 1648, -1180, -1069, -2368, -3349, -2524, +-3795, -1524, -1942, 37, 794, 1723, 3083, 2641, +3742, 2439, 2219, 1241, -212, -526, -2607, -2097, +-3423, -2847, -2267, -2420, -299, -1019, 1650, 757, +2477, 2440, 2055, 3179, 1061, 2511, -224, 975, +-1366, -1263, -1759, -3042, -1783, -3571, -1081, -2521, +125, -332, 1344, 2022, 2341, 3619, 2024, 3602, +802, 1887, -986, -569, -2343, -2787, -2443, -3763, +-1277, -2918, 604, -887, 2148, 1427, 2246, 3124, +1150, 3300, -381, 1855, -1573, -267, -1480, -2196, +-830, -2940, 142, -2065, 765, -331, 768, 1422, +488, 2326, 159, 1640, 153, 199, -93, -1189, +-594, -1776, -1052, -931, -929, 325, 58, 1349, +1242, 1660, 1958, 645, 1464, -826, -262, -1872, +-2101, -1842, -2803, -694, -1824, 898, 583, 2017, +2688, 1871, 3134, 1007, 1836, -191, -409, -1186, +-2358, -1427, -2737, -1466, -1921, -1152, -434, -516, +1154, 376, 1849, 1659, 1953, 2675, 1527, 2629, +720, 1109, -455, -1382, -1786, -3701, -2772, -4402, +-2639, -2748, -1057, 592, 1476, 3893, 3658, 5315, +4083, 4012, 2224, 384, -1150, -3303, -3798, -5117, +-4487, -4213, -2788, -1129, 688, 2001, 3344, 3674, +3880, 3329, 2367, 1661, -283, -270, -2143, -1674, +-2310, -2053, -1395, -1693, -187, -1005, 454, -182, +495, 421, 412, 1093, 480, 1725, 1013, 1700, +1349, 1039, 571, -260, -763, -1815, -2273, -2477, +-2771, -1982, -1269, -673, 1060, 1191, 3219, 2416, +3549, 2610, 1489, 1728, -1419, -168, -3558, -2096, +-3416, -3084, -1293, -2502, 1355, -550, 3082, 1709, +2714, 2952, 1053, 2621, -955, 889, -2004, -1011, +-1483, -2195, -610, -2080, 40, -984, 264, 121, +104, 856, 404, 920, 1006, 945, 1388, 917, +1117, 810, -71, 334, -1662, -724, -2666, -1753, +-2210, -2142, -263, -1455, 1901, 112, 3047, 1989, +2593, 2940, 713, 2349, -1370, 584, -2453, -1634, +-2323, -2822, -1261, -2633, 300, -1218, 1373, 723, +1623, 1814, 1337, 2027, 720, 1562, -9, 638, +-614, -193, -1031, -838, -1215, -1541, -1036, -1878, +-342, -1566, 381, -488, 1067, 1228, 1276, 2568, +851, 2653, 254, 1389, -288, -704, -466, -2262, +-554, -2570, -749, -1648, -967, -53, -970, 1109, +-325, 1540, 813, 1096, 2066, 596, 2530, 442, +1744, 371, -391, 36, -2780, -948, -3916, -2009, +-3000, -2288, -152, -1167, 2914, 900, 4508, 2946, +3594, 3605, 716, 2100, -2533, -682, -4178, -3131, +-3403, -3863, -871, -2388, 1797, 476, 2957, 2507, +2253, 3010, 746, 1877, -650, -148, -1269, -1435, +-896, -1610, -418, -719, -368, 184, -424, 310, +-354, -264, 124, -697, 1006, -460, 1524, 757, +1230, 2049, 208, 1992, -1151, 563, -1963, -1583, +-1734, -3009, -505, -2617, 929, -561, 1821, 1760, +1755, 3058, 836, 2548, -345, 610, -1472, -1469, +-1784, -2485, -1083, -1883, 188, -475, 1267, 895, +1465, 1449, 816, 1000, -230, 155, -1115, -416, +-1186, -368, -315, 88, 769, 241, 1383, -43, +819, -557, -536, -755, -1626, -389, -1763, 228, +-419, 786, 1325, 824, 2345, 588, 2064, -19, +314, -651, -1763, -786, -2654, -499, -2132, 45, +-373, 389, 1474, 342, 2244, 80, 2006, -176, +713, -207, -702, 41, -1410, 365, -1479, 552, +-1019, 486, -306, -72, 353, -766, 831, -1219, +1177, -1045, 963, -114, 264, 879, -373, 1606, +-729, 1546, -665, 540, -335, -520, -94, -1345, +-113, -1644, -281, -1125, -187, -249, 408, 605, +988, 1133, 1386, 1345, 880, 1146, -387, 535, +-1421, -149, -1970, -1129, -1535, -1672, -39, -1437, +1298, -790, 1933, 290, 1677, 1219, 373, 1730, +-583, 1544, -1071, 850, -1242, -48, -608, -1062, +-313, -1776, -32, -1908, 417, -1504, 567, -300, +951, 1417, 918, 2615, 315, 2761, -341, 1534, +-1015, -658, -1176, -2525, -595, -3125, 171, -2145, +696, -188, 626, 1635, 164, 2443, -234, 2060, +-33, 837, 450, -463, 541, -1249, 277, -1379, +-358, -940, -1087, -411, -1171, 60, -620, 462, +364, 589, 1212, 649, 1326, 499, 779, 193, +-129, 91, -760, -119, -801, -293, -416, -604, +-96, -771, 5, -607, -235, -152, -456, 544, +-12, 1042, 689, 1049, 1296, 514, 1359, -266, +457, -850, -799, -896, -1751, -516, -1895, 116, +-1031, 449, 249, 303, 1271, -69, 1680, -441, +1347, -102, 771, 657, -14, 1058, -775, 876, +-1234, -71, -1552, -1281, -1367, -1788, -635, -1349, +474, -193, 1730, 1264, 2436, 2023, 1990, 1741, +511, 631, -1372, -820, -2599, -1634, -2573, -1632, +-1402, -929, 462, 69, 1954, 758, 2341, 1032, +1756, 910, 433, 694, -796, 236, -1451, -234, +-1575, -632, -1018, -968, -282, -979, 507, -620, +1074, 98, 1029, 830, 751, 1402, 131, 1342, +-494, 454, -810, -640, -656, -1516, -98, -1682, +213, -802, 403, 525, 238, 1532, -168, 1695, +-287, 752, -328, -588, -9, -1423, 529, -1407, +610, -485, 450, 601, 47, 1082, -407, 954, +-606, 345, -758, -210, -631, -470, -221, -652, +433, -711, 1015, -679, 1179, -123, 926, 721, +65, 1387, -814, 1502, -1420, 683, -1417, -746, +-578, -2099, 376, -2294, 1038, -1068, 1230, 932, +766, 2474, 280, 2492, -40, 1031, -479, -949, +-655, -2090, -899, -1995, -947, -803, -432, 594, +253, 1300, 1075, 1121, 1518, 391, 1164, -187, +170, -265, -914, -43, -1498, -9, -1161, -328, +-292, -747, 493, -700, 846, -115, 540, 874, +171, 1360, -104, 848, -65, -150, 280, -1182, +257, -1363, -109, -606, -543, 536, -846, 1273, +-417, 1048, 150, 210, 461, -770, 605, -1163, +313, -699, 167, 74, 96, 664, 38, 898, +61, 508, -299, -2, -690, -325, -855, -475, +-708, -357, 130, -309, 1041, -265, 1405, -69, +1240, 296, 242, 716, -875, 845, -1408, 478, +-1418, -86, -590, -855, 241, -1229, 772, -895, +1215, -158, 929, 821, 514, 1308, -26, 1076, +-852, 292, -918, -618, -891, -1086, -547, -936, +254, -254, 754, 449, 993, 694, 650, 467, +15, -12, -445, -309, -594, -182, -351, 58, +-91, 256, -22, 168, 66, -198, 80, -366, +191, -309, 325, -29, 189, 360, 5, 370, +-306, 96, -387, -148, -243, -340, 3, -147, +459, 183, 582, 385, 376, 408, -201, -50, +-894, -501, -958, -683, -346, -565, 417, 55, +1103, 705, 1160, 926, 650, 735, -162, 87, +-1212, -652, -1550, -896, -1030, -716, -58, -302, +1052, 233, 1515, 529, 1271, 571, 476, 474, +-618, 217, -1357, -78, -1352, -220, -578, -320, +354, -393, 931, -397, 908, -381, 386, -123, +-185, 334, -466, 762, -284, 891, 134, 519, +328, -204, 78, -748, -429, -902, -712, -618, +-548, -89, 103, 308, 878, 469, 1206, 319, +710, 255, -250, 345, -1023, 389, -1165, 309, +-563, -306, 121, -1067, 645, -1253, 892, -791, +494, 292, 30, 1402, -343, 1593, -578, 947, +-269, -163, 65, -1232, 30, -1334, 109, -646, +117, 160, 66, 661, 119, 515, -74, -12, +-135, -315, -58, -34, 34, 531, 82, 832, +129, 566, 112, -413, -61, -1292, -236, -1407, +-323, -752, -117, 435, 226, 1296, 344, 1507, +295, 890, 80, -15, -199, -660, -252, -1017, +-274, -836, -130, -690, 104, -400, 93, 170, +252, 745, 295, 1313, 150, 1280, -79, 579, +-397, -544, -512, -1392, -245, -1586, 156, -987, +426, 142, 740, 900, 484, 1193, -145, 964, +-656, 398, -912, -91, -504, -385, 178, -566, +611, -652, 737, -784, 457, -694, 19, -101, +-216, 711, -380, 1521, -355, 1573, -257, 675, +-278, -608, -154, -1758, 77, -1988, 340, -1117, +723, 337, 832, 1670, 361, 2032, -307, 1187, +-1050, -191, -1167, -1363, -622, -1619, 4, -907, +754, 176, 1109, 982, 948, 996, 407, 436, +-407, -273, -905, -630, -720, -389, -296, 76, +33, 429, 93, 360, 3, -131, 109, -504, +250, -557, 455, -57, 716, 507, 639, 724, +-3, 561, -859, -128, -1498, -755, -1344, -939, +-272, -607, 845, 280, 1597, 1146, 1559, 1235, +764, 536, -254, -620, -1210, -1508, -1380, -1412, +-850, -451, -240, 884, 284, 1666, 447, 1424, +501, 397, 737, -886, 807, -1570, 680, -1348, +112, -407, -839, 644, -1528, 1257, -1601, 1147, +-837, 433, 564, -321, 1688, -796, 1898, -845, +1269, -442, -47, 135, -1169, 493, -1594, 464, +-1391, 176, -488, -205, 465, -277, 1020, -34, +1140, 232, 701, 321, -41, 156, -464, -198, +-600, -468, -422, -520, -48, -278, 60, 238, +64, 581, -81, 695, -67, 434, 70, -192, +218, -618, 407, -736, 209, -382, 8, 274, +-195, 571, -350, 522, -221, 99, -108, -443, +-30, -536, 25, -243, -17, 281, 24, 680, +276, 614, 462, 97, 405, -609, 60, -893, +-410, -742, -678, -122, -632, 590, -166, 908, +332, 833, 600, 296, 582, -235, 50, -527, +-221, -737, -157, -598, -107, -293, 109, 13, +-34, 412, -281, 638, -315, 628, -230, 462, +183, 207, 519, -230, 480, -647, 115, -802, +-310, -768, -436, -421, -173, 164, 254, 794, +451, 1159, 155, 1086, -394, 496, -714, -419, +-695, -1173, -83, -1450, 782, -990, 1233, -102, +1093, 854, 306, 1281, -745, 1046, -1503, 396, +-1460, -339, -745, -591, 308, -522, 1219, -339, +1447, -167, 1276, -323, 515, -383, -511, -28, +-1199, 504, -1520, 1072, -1053, 1119, -158, 421, +581, -459, 1012, -1180, 1002, -1375, 684, -829, +305, 57, -115, 832, -503, 1156, -711, 931, +-780, 337, -760, -187, -521, -507, 173, -700, +894, -653, 1321, -457, 1324, -154, 517, 356, +-438, 700, -1180, 784, -1540, 519, -1124, -64, +-326, -500, 489, -625, 1154, -411, 1227, -126, +809, 49, 336, 153, -236, 193, -629, 262, +-890, 358, -999, 237, -680, -11, -171, -295, +415, -524, 922, -391, 1049, -64, 918, 319, +548, 523, -135, 360, -817, -62, -1363, -392, +-1546, -444, -975, -187, 124, 324, 1414, 464, +2192, 278, 1817, -24, 506, -350, -1109, -366, +-2125, -209, -1945, 14, -925, 184, 541, 220, +1532, 189, 1479, 78, 849, 26, -53, 85, +-624, 19, -753, -146, -536, -266, -194, -435, +-44, -354, 27, -8, 102, 388, 253, 814, +450, 875, 371, 350, -39, -505, -364, -1191, +-417, -1272, -168, -559, 252, 601, 470, 1339, +224, 1238, -313, 471, -702, -569, -682, -1094, +93, -827, 801, -192, 947, 438, 687, 634, +-111, 285, -803, -220, -942, -429, -596, -203, +46, 233, 461, 604, 345, 527, 252, -14, +266, -547, 311, -807, 371, -628, -11, -121, +-488, 452, -821, 799, -958, 767, -419, 483, +462, -103, 1125, -671, 1323, -855, 688, -706, +-364, -166, -1083, 402, -1308, 705, -696, 642, +205, 267, 793, -115, 955, -390, 533, -354, +-66, -112, -413, 80, -517, 85, -338, -117, +-62, -316, 131, -283, 286, 135, 194, 534, +92, 754, -9, 586, -157, -93, -128, -645, +-214, -954, -120, -877, 135, -261, 316, 409, +407, 860, 150, 1023, -180, 716, -415, 124, +-472, -519, -341, -1022, 7, -1201, 418, -645, +636, 268, 543, 1044, 218, 1307, -240, 665, +-641, -250, -679, -897, -516, -891, -27, -300, +465, 323, 657, 654, 805, 311, 375, -216, +-225, -514, -665, -396, -876, 149, -422, 571, +73, 642, 433, 203, 586, -283, 397, -580, +155, -512, -219, -152, -342, 87, -184, 200, +-94, 185, -1, 196, -63, 312, -100, 289, +128, 163, 307, -150, 236, -552, 49, -680, +-219, -453, -326, -73, -117, 506, 130, 878, +343, 660, 330, 279, -169, -261, -612, -778, +-644, -761, -156, -363, 759, 112, 1121, 506, +690, 574, -173, 223, -1077, -63, -1227, -183, +-666, -200, 224, 62, 1055, 134, 1099, 6, +553, -235, -155, -429, -660, -266, -605, 141, +-341, 495, -101, 595, -43, 330, -28, -128, +198, -487, 473, -608, 678, -338, 524, 87, +-107, 356, -723, 360, -979, 117, -671, -23, +55, 5, 613, 154, 820, 112, 546, -167, +-19, -484, -344, -587, -369, -225, -52, 380, +103, 882, -108, 861, -316, 235, -378, -587, +-124, -1130, 369, -951, 700, -95, 613, 750, +217, 1122, -317, 757, -610, -131, -582, -667, +-323, -704, -81, -415, 115, 135, 306, 263, +411, 172, 486, 138, 416, 111, 167, 244, +-270, 306, -743, 61, -901, -420, -549, -781, +76, -634, 570, -16, 886, 700, 778, 1038, +357, 687, -163, -121, -674, -749, -789, -991, +-501, -578, -157, 196, 184, 638, 398, 774, +413, 395, 377, -238, 180, -487, 45, -449, +-74, -124, -192, 216, -290, 215, -466, 84, +-406, -29, -145, 16, 213, 115, 557, 148, +656, -108, 522, -348, 68, -450, -483, -195, +-637, 384, -436, 710, -200, 755, 50, 223, +177, -591, 172, -1097, 171, -1075, 209, -401, +301, 658, 438, 1484, 278, 1488, -312, 659, +-855, -691, -1050, -1708, -571, -1749, 242, -834, +891, 543, 1160, 1567, 903, 1737, 191, 988, +-666, -206, -999, -1238, -854, -1509, -397, -1007, +143, -25, 373, 847, 492, 1042, 506, 690, +345, 102, 264, -421, 15, -430, -342, -189, +-501, -42, -651, 52, -446, -92, -49, -212, +272, -108, 659, 147, 675, 351, 397, 360, +137, 153, -213, -107, -495, -239, -599, -232, +-648, -132, -377, -60, 139, -34, 651, -22, +910, -31, 707, 61, 263, 260, -387, 374, +-822, 332, -815, 69, -421, -373, 97, -601, +441, -553, 524, -203, 360, 261, 171, 471, +-19, 511, -121, 274, -74, 81, -121, 2, +-283, -129, -358, -273, -280, -504, 38, -617, +352, -443, 505, 124, 478, 809, 161, 1184, +-143, 970, -422, 103, -463, -926, -230, -1487, +-100, -1163, 20, -202, 134, 841, 259, 1285, +406, 865, 339, 101, 96, -496, -89, -539, +-356, -198, -518, 5, -472, -108, -174, -394, +303, -417, 580, -24, 579, 628, 279, 1089, +-80, 838, -461, -20, -572, -1011, -306, -1442, +11, -877, 409, 223, 402, 1137, 102, 1287, +-86, 588, -289, -358, -288, -928, 6, -892, +240, -307, 407, 356, 295, 570, -110, 508, +-349, 143, -484, -161, -372, -206, -145, -254, +227, -238, 657, -188, 695, -58, 349, 233, +-175, 458, -540, 427, -670, 190, -558, -201, +-252, -531, 191, -535, 608, -360, 717, 13, +488, 462, 147, 643, -250, 505, -534, 75, +-583, -319, -493, -473, -158, -405, 135, -203, +428, -33, 627, 80, 505, 277, 257, 392, +-102, 327, -401, 156, -566, -103, -602, -297, +-449, -336, 14, -336, 562, -281, 870, -94, +770, 209, 232, 575, -454, 787, -931, 485, +-878, -147, -278, -810, 576, -1077, 939, -629, +628, 149, -147, 845, -902, 1062, -824, 523, +-85, -217, 812, -704, 1237, -661, 681, -150, +-463, 252, -1405, 296, -1515, -19, -517, -252, +867, -112, 1691, 320, 1439, 631, 290, 475, +-881, -158, -1428, -841, -983, -1045, -140, -529, +525, 451, 718, 1151, 478, 1156, 144, 387, +-77, -664, -22, -1111, 11, -901, -110, -135, +-374, 546, -478, 706, -259, 487, 211, 50, +565, -154, 474, -196, 160, -134, -185, -42, +-302, -181, -188, -300, -14, -216, -5, 30, +-81, 459, -93, 685, -112, 502, 185, -46, +456, -638, 424, -832, 79, -570, -503, 52, +-774, 596, -486, 762, 220, 474, 837, -39, +792, -443, 225, -549, -451, -249, -890, 161, +-697, 335, -54, 160, 582, -133, 814, -343, +533, -169, -44, 209, -436, 438, -505, 459, +-371, 140, -142, -369, 45, -653, 202, -576, +334, -177, 416, 371, 349, 679, 97, 561, +-319, 162, -641, -231, -637, -475, -247, -373, +377, -119, 657, 39, 546, 135, 157, 84, +-231, 64, -363, 138, -294, 172, -85, 156, +30, 1, 15, -190, -44, -299, 1, -226, +216, -51, 328, 99, 202, 146, -106, 76, +-437, 33, -347, 110, 27, 227, 331, 234, +385, 36, 20, -340, -445, -684, -581, -640, +-181, -88, 536, 626, 911, 1043, 662, 807, +-121, 34, -951, -806, -1193, -1075, -673, -702, +354, 113, 1135, 850, 1134, 918, 490, 363, +-425, -444, -919, -826, -789, -562, -314, 144, +276, 767, 528, 784, 396, 190, 123, -609, +-136, -1034, -143, -712, 20, 104, 39, 893, +-17, 1060, -137, 533, -191, -272, -69, -856, +17, -786, 105, -283, 148, 307, 151, 578, +123, 378, 58, -65, -76, -359, -254, -252, +-305, 98, -159, 436, 112, 454, 346, 44, +367, -473, 80, -694, -246, -538, -416, -44, +-258, 524, 120, 751, 378, 626, 400, 206, +124, -340, -207, -552, -401, -543, -406, -350, +-208, -37, 65, 66, 371, 316, 524, 457, +429, 448, 163, 368, -164, 12, -559, -361, +-765, -625, -594, -675, -29, -391, 665, 159, +969, 604, 758, 743, 138, 500, -537, 12, +-858, -310, -670, -415, -163, -326, 382, -134, +444, -132, 138, -164, -45, -71, -19, 180, +307, 567, 523, 754, 241, 483, -366, -145, +-914, -828, -1029, -1155, -430, -770, 569, 86, +1284, 902, 1233, 1229, 387, 791, -653, -5, +-1151, -762, -873, -1047, -185, -641, 470, 20, +591, 555, 269, 676, -71, 342, -217, -85, +57, -253, 395, -170, 373, -79, -54, -48, +-593, -131, -857, -145, -522, 20, 272, 257, +873, 474, 951, 371, 417, -67, -398, -538, +-888, -842, -699, -610, -114, 155, 518, 931, +719, 1247, 289, 767, -306, -294, -652, -1236, +-412, -1451, 116, -778, 549, 329, 596, 1188, +242, 1366, -224, 757, -563, -179, -532, -882, +-174, -1022, 241, -630, 363, 14, 218, 379, +40, 468, -2, 342, 16, 134, 46, 93, +75, 112, -61, 105, -257, -101, -368, -464, +-287, -679, -28, -526, 356, -12, 547, 621, +443, 968, 241, 767, -96, 159, -445, -549, +-618, -962, -615, -769, -269, -231, 259, 380, +672, 608, 868, 468, 566, 193, -12, -83, +-567, -131, -848, -75, -593, -69, -208, -157, +130, -305, 505, -390, 655, -150, 481, 353, +180, 710, -173, 784, -466, 311, -545, -530, +-537, -1084, -291, -1032, 237, -302, 724, 746, +863, 1382, 504, 1115, -215, 129, -778, -999, +-960, -1506, -605, -1010, 184, 66, 826, 1115, +951, 1408, 497, 814, -201, -116, -670, -946, +-647, -1151, -396, -707, -42, 7, 254, 606, +387, 765, 402, 527, 369, 200, 236, -76, +-83, -215, -445, -367, -723, -499, -680, -470, +-159, -213, 467, 223, 898, 607, 924, 717, +361, 469, -338, 35, -865, -443, -899, -693, +-374, -577, 149, -269, 435, 132, 542, 430, +388, 401, 205, 311, 75, 240, -122, 102, +-275, -42, -460, -291, -502, -562, -296, -575, +97, -297, 556, 157, 746, 588, 596, 779, +37, 667, -553, 206, -774, -460, -572, -898, +-30, -945, 402, -467, 529, 334, 346, 918, +62, 987, -190, 466, -248, -354, -144, -831, +-60, -746, 72, -162, 95, 457, 24, 642, +51, 304, 42, -256, -82, -549, -132, -407, +-137, 107, -24, 540, 212, 589, 306, 207, +308, -285, 44, -578, -432, -495, -607, -132, +-427, 211, 21, 436, 584, 355, 747, 107, +366, -48, -132, -154, -519, -146, -605, -81, +-159, -104, 225, -74, 269, -14, 173, 28, +-108, 89, -209, 23, 18, 28, 302, 156, +413, 289, 251, 256, -293, -59, -733, -529, +-700, -773, -230, -532, 535, 129, 977, 836, +751, 1090, 123, 724, -619, -156, -955, -963, +-573, -1194, 53, -673, 577, 214, 667, 866, +214, 884, -277, 360, -417, -226, -240, -485, +243, -317, 474, 51, 269, 171, -236, -68, +-730, -307, -634, -328, -77, 45, 638, 509, +1022, 630, 758, 326, -56, -164, -911, -499, +-1246, -556, -794, -357, 221, -46, 1011, 281, +1207, 494, 683, 563, -298, 330, -968, -153, +-963, -685, -382, -794, 292, -315, 637, 410, +477, 873, 134, 645, -100, -51, -140, -653, +-68, -684, -4, -248, -74, 293, -255, 504, +-282, 307, -112, -27, 226, -197, 472, -133, +449, 17, 199, 81, -107, -50, -466, -231, +-616, -271, -494, -116, -69, 201, 598, 517, +802, 593, 566, 349, 43, -216, -564, -793, +-796, -1039, -580, -734, -26, 191, 555, 1121, +730, 1465, 439, 945, -35, -219, -463, -1255, +-545, -1524, -377, -946, -70, 126, 376, 1025, +619, 1253, 471, 876, 58, 99, -441, -531, +-724, -801, -513, -838, -54, -528, 475, 11, +806, 536, 591, 983, 73, 894, -475, 179, +-777, -661, -590, -1140, -174, -825, 289, 60, +682, 856, 660, 974, 335, 414, -126, -355, +-595, -678, -720, -527, -484, -164, 143, 207, +642, 358, 616, 376, 195, 246, -273, -25, +-370, -288, -195, -344, 54, -180, 119, 85, +26, 230, -57, 37, -108, -225, -90, -148, +133, 208, 302, 638, 238, 593, -26, -152, +-353, -978, -388, -1123, -154, -382, 180, 764, +280, 1338, 226, 879, 171, -160, -27, -969, +-227, -956, -249, -316, -167, 382, 17, 644, +265, 463, 146, 57, -70, -343, -125, -520, +59, -318, 259, 211, 161, 616, -161, 567, +-485, 44, -377, -635, -26, -819, 397, -391, +542, 318, 458, 818, 169, 769, -486, 153, +-807, -589, -675, -878, -70, -539, 713, 231, +870, 849, 466, 739, -43, 68, -419, -617, +-578, -781, -535, -370, -295, 194, 171, 453, +625, 430, 645, 384, 343, 252, -103, -27, +-401, -547, -400, -840, -468, -647, -383, -46, +-44, 640, 463, 919, 876, 795, 796, 388, +168, -244, -721, -852, -1064, -1143, -836, -860, +-231, -46, 545, 864, 1067, 1256, 1076, 968, +393, 196, -598, -629, -1204, -958, -868, -818, +-171, -290, 458, 187, 652, 443, 467, 551, +399, 391, 122, 211, -296, 9, -586, -261, +-580, -411, -233, -398, 190, -248, 373, 4, +411, 254, 460, 369, 206, 368, -266, 218, +-563, -72, -586, -332, -211, -457, 215, -235, +526, 87, 554, 306, 202, 356, -199, 179, +-500, -52, -468, -296, -85, -428, 293, -257, +390, 205, 194, 619, -133, 587, -204, 41, +-71, -582, -15, -808, 76, -459, 110, 247, +48, 771, -19, 720, -220, 191, -249, -447, +-34, -741, 273, -449, 431, 182, 248, 561, +-53, 512, -386, 18, -555, -445, -368, -519, +131, -175, 550, 232, 659, 428, 226, 406, +-330, 87, -459, -213, -288, -353, -33, -284, +54, -141, 88, 68, 72, 134, 90, 112, +133, 195, 194, 334, 157, 235, -132, -109, +-417, -465, -399, -552, -61, -282, 334, 154, +392, 384, 176, 406, -41, 322, -230, 32, +-264, -133, -75, -333, 215, -329, 333, -63, +130, 62, -281, 69, -477, -38, -217, -27, +157, 229, 413, 470, 434, 373, 178, -154, +-101, -736, -334, -791, -482, -206, -334, 567, +133, 894, 388, 464, 457, -239, 219, -612, +-188, -490, -341, -34, -253, 344, 83, 334, +241, 166, 244, -125, -76, -302, -380, -251, +-348, -12, 12, 304, 481, 350, 573, 85, +178, -278, -355, -414, -557, -226, -336, 273, +86, 494, 270, 310, 280, -71, 115, -476, +-26, -532, -165, -225, -105, 185, -17, 563, +66, 616, 106, 288, -44, -242, -77, -685, +-114, -618, -42, -182, 7, 295, 90, 506, +115, 343, 101, 47, -30, -55, -148, -73, +-91, -77, 17, -36, 208, -109, 49, -229, +-323, -233, -400, -168, -72, 117, 517, 537, +680, 678, 195, 392, -439, -231, -579, -811, +-302, -824, 28, -280, 161, 346, 210, 643, +364, 450, 194, 45, -96, -136, -263, -82, +-186, 12, 22, -8, 60, -192, -43, -333, +-41, -348, -25, -43, 32, 361, 140, 591, +274, 500, 252, 82, -161, -396, -516, -574, +-482, -439, 47, -95, 532, 320, 499, 472, +114, 265, -165, -132, -363, -344, -372, -248, +-187, 298, 140, 527, 508, 219, 479, -401, +73, -837, -431, -494, -513, 289, -234, 862, +190, 713, 410, -21, 247, -552, -116, -556, +-289, -245, -88, 184, 136, 292, 208, 252, +106, 171, -79, -69, -212, -383, -223, -327, +-240, -28, -151, 310, 207, 392, 506, 171, +573, -25, 351, -127, -279, -150, -874, -336, +-985, -426, -400, -168, 396, 348, 996, 700, +985, 621, 383, 162, -234, -358, -830, -577, +-978, -584, -588, -480, 156, -107, 777, 465, +831, 895, 341, 840, -187, 194, -512, -641, +-419, -908, 31, -498, 270, 21, 147, 234, +-166, 235, -450, 219, -211, 275, 430, 326, +674, 178, 462, -194, -49, -480, -559, -581, +-792, -490, -419, 8, 290, 682, 861, 931, +676, 624, -133, -216, -644, -999, -542, -919, +74, -233, 484, 536, 355, 841, 97, 478, +-160, -100, -329, -428, -359, -474, -111, -215, +266, 42, 497, 261, 358, 362, -71, 97, +-341, -206, -338, -220, -71, 99, 115, 391, +196, 137, -57, -519, -230, -822, -8, -332, +332, 678, 383, 1310, -11, 794, -349, -425, +-397, -1285, -235, -1171, 39, -157, 281, 850, +352, 1055, 208, 473, -229, -206, -390, -557, +-104, -453, 273, -111, 306, 153, -165, 271, +-506, 122, -351, -120, 134, -296, 538, -137, +632, 321, 217, 527, -416, 299, -834, -303, +-669, -772, 36, -609, 623, 97, 746, 802, +430, 818, -30, 119, -469, -647, -669, -866, +-423, -337, 124, 505, 402, 840, 277, 508, +95, -179, 158, -795, 245, -802, -38, -192, +-513, 615, -465, 951, 33, 533, 344, -259, +258, -843, 13, -723, 36, 24, 109, 586, +-66, 587, -208, 76, -58, -463, 201, -450, +237, 71, 37, 571, -297, 440, -367, -158, +-146, -694, 212, -606, 546, -17, 506, 603, +121, 727, -397, 371, -528, -238, -350, -679, +-90, -681, 179, -184, 321, 539, 300, 885, +115, 426, -60, -446, 9, -952, 151, -633, +-97, 436, -579, 1157, -645, 787, -97, -375, +473, -1267, 690, -1101, 574, 138, 177, 1290, +-356, 1379, -793, 266, -809, -1094, -197, -1498, +501, -701, 675, 712, 359, 1455, 12, 945, +-158, -238, -331, -1153, -299, -1133, -24, -172, +150, 835, -80, 1100, -373, 531, -133, -539, +441, -1133, 839, -743, 474, 312, -454, 1232, +-943, 1067, -822, -94, -239, -1297, 529, -1547, +1005, -433, 851, 1192, 86, 1967, -753, 1188, +-949, -625, -422, -2001, 313, -1855, 713, -233, +446, 1527, -70, 2092, -495, 938, -404, -809, +229, -1817, 682, -1319, 513, 224, -196, 1482, +-776, 1463, -728, 159, -148, -1213, 597, -1687, +996, -678, 754, 952, -106, 1941, -944, 1372, +-1071, -398, -255, -1874, 689, -1904, 967, -380, +537, 1411, -182, 1990, -579, 956, -725, -723, +-343, -1718, 309, -1265, 822, 220, 646, 1460, +-75, 1330, -701, 134, -571, -1148, -9, -1509, +281, -542, 244, 813, -9, 1550, -118, 946, +-8, -385, 141, -1348, 136, -1124, 34, 99, +-187, 1076, -347, 1032, -379, -49, -80, -983, +327, -1042, 560, -13, 297, 1054, -272, 1304, +-599, 515, -377, -886, 158, -1640, 408, -1129, +228, 266, -205, 1444, -396, 1559, -250, 456, +53, -819, 358, -1408, 452, -895, 272, 207, +-203, 1099, -642, 1004, -681, -58, -324, -1014, +488, -1050, 1064, -15, 805, 1168, -74, 1412, +-962, 279, -1099, -1192, -283, -1746, 656, -871, +930, 862, 559, 1758, -135, 1310, -533, -211, +-577, -1481, -219, -1400, 435, -317, 624, 895, +309, 1389, -314, 775, -669, -426, -244, -1310, +407, -1162, 692, -53, 462, 1127, -64, 1503, +-628, 508, -780, -897, -245, -1519, 458, -839, +967, 524, 654, 1481, -212, 1121, -824, -454, +-703, -1461, 49, -1302, 711, 96, 625, 1667, +-88, 1763, -768, 323, -658, -1480, 237, -2026, +778, -1134, 675, 715, -27, 2029, -567, 1627, +-797, 134, -387, -1277, 118, -1641, 565, -784, +643, 615, 112, 1341, -538, 856, -684, -321, +19, -1141, 606, -919, 571, 279, -206, 1342, +-924, 1217, -989, -124, -112, -1465, 998, -1626, +1370, -424, 681, 1328, -577, 1825, -1553, 817, +-1352, -930, -40, -1742, 1196, -909, 1488, 704, +535, 1577, -839, 928, -1424, -647, -682, -1567, +607, -1078, 1234, 297, 749, 1524, -334, 1424, +-1005, 210, -835, -1091, -3, -1520, 703, -741, +873, 683, 400, 1293, -488, 727, -809, -549, +-209, -1207, 716, -558, 868, 898, 31, 1600, +-930, 783, -1084, -1091, -242, -2267, 898, -1568, +1435, 614, 983, 2479, -48, 2416, -1331, 489, +-1692, -1890, -574, -2852, 1007, -1532, 1733, 993, +1008, 2674, -512, 2130, -1485, -240, -1045, -2401, +203, -2471, 1326, -264, 1406, 2122, 321, 2798, +-1225, 1042, -1840, -1536, -1046, -3031, 608, -2112, +1794, 360, 1646, 2583, 363, 2955, -997, 1081, +-1677, -1517, -1151, -2864, 79, -1943, 792, 358, +1055, 1973, 445, 1794, -191, 230, -443, -1130, +-410, -1014, -302, 48, -13, 764, 161, 399, +159, -575, -63, -1044, -94, -336, 138, 827, +68, 1489, -145, 890, -500, -477, -364, -1741, +289, -1866, 895, -349, 689, 1609, -200, 2552, +-1033, 1552, -1192, -854, -479, -2682, 668, -2362, +1310, -257, 1001, 1812, 180, 2433, -711, 1181, +-1139, -730, -799, -1692, 56, -1348, 813, 76, +882, 1199, 247, 938, -527, -253, -485, -1331, +71, -1060, 485, 508, 407, 1976, -50, 1930, +-365, 138, -608, -2146, -434, -2907, 252, -1428, +1026, 1148, 1037, 3010, 125, 2584, -965, 283, +-1226, -2039, -283, -2775, 748, -1499, 1174, 869, +773, 2397, -286, 1965, -1279, -43, -1272, -2014, +-118, -2145, 1254, -414, 1603, 1577, 697, 2230, +-595, 1142, -1233, -895, -1132, -2137, -392, -1792, +415, -275, 950, 1515, 886, 2252, 13, 1242, +-518, -711, -380, -2100, 122, -1797, 169, 89, +-94, 1725, -640, 1913, -617, 483, -147, -1362, +397, -1927, 853, -1023, 868, 601, 297, 1711, +-644, 1538, -1049, 403, -878, -863, -224, -1577, +377, -1176, 653, -144, 386, 856, 5, 1130, +-184, 576, 25, -97, 331, -412, 294, -94, +-411, 121, -1085, -24, -933, -624, -148, -910, +834, -522, 1438, 589, 1243, 1583, 226, 1608, +-1069, 391, -1773, -1427, -1307, -2154, 270, -1489, +1482, 391, 1575, 1984, 568, 1896, -689, 471, +-1246, -1094, -947, -1825, 51, -982, 1051, 510, +1350, 1416, 440, 1297, -649, -38, -1335, -1199, +-858, -1388, 256, -491, 1000, 772, 1007, 1314, +333, 882, -253, -180, -559, -880, -462, -808, +-54, -197, 266, 384, 204, 438, -43, -64, +-360, -371, -138, -194, 374, 405, 804, 923, +609, 599, -269, -315, -901, -1255, -966, -1291, +-337, -427, 378, 783, 808, 1569, 590, 1164, +173, 87, -234, -902, -387, -1191, -243, -707, +-213, 165, -263, 532, -226, 406, 194, 37, +410, -68, 389, 215, 72, 596, -337, 430, +-461, -469, -268, -1182, 120, -1133, 283, -253, +250, 1045, -52, 1516, -510, 998, -527, -32, +60, -1065, 514, -1340, 590, -802, 290, 248, +-190, 925, -652, 938, -796, 324, -368, -360, +324, -649, 960, -232, 874, 26, -12, 240, +-781, 175, -759, -41, -218, -63, 275, 13, +526, 41, 404, -72, 126, -335, -244, -186, +-412, 276, -308, 595, 175, 787, 498, 66, +378, -826, 32, -1245, -197, -991, -178, 96, +-173, 1432, -42, 1738, -84, 1040, 133, -555, +410, -1807, 489, -1775, 151, -725, -278, 850, +-373, 1703, -307, 1502, -141, 443, 125, -918, +240, -1593, 345, -1224, 259, -57, 76, 1013, +-139, 1528, -198, 929, -176, -280, -247, -1246, +-197, -1397, -5, -785, 161, 442, 350, 1400, +461, 1584, 182, 907, -116, -565, -552, -1830, +-776, -2054, -380, -827, 188, 1068, 588, 2370, +702, 1999, 217, 404, -231, -1561, -626, -2474, +-523, -1776, -111, 122, 139, 2021, 260, 2594, +161, 1329, -20, -915, -21, -2542, 32, -2426, +19, -602, -143, 1697, -379, 2776, -372, 1958, +65, -96, 600, -2154, 726, -2592, 267, -1351, +-631, 506, -1167, 2047, -835, 2189, 164, 926, +1167, -697, 1603, -1794, 909, -1629, -454, -377, +-1805, 926, -1968, 1288, -861, 721, 923, -364, +2288, -882, 2180, -514, 853, 341, -1052, 976, +-2254, 609, -2300, -483, -1077, -1308, 1124, -1170, +2555, 21, 2501, 1433, 976, 1842, -1028, 855, +-2404, -766, -2286, -2010, -890, -1930, 906, -302, +2255, 1359, 2314, 2249, 902, 1651, -1084, -12, +-2212, -1693, -1880, -2342, -336, -1500, 1303, 294, +1909, 1967, 1035, 2220, -322, 1110, -1242, -701, +-1128, -1613, -125, -1466, 917, -536, 883, 364, +154, 670, -1009, 552, -1426, 251, -366, 159, +1133, 349, 2185, 440, 1329, 117, -740, -576, +-2502, -1414, -2644, -1501, -872, -497, 1549, 1055, +2980, 2218, 2403, 2201, 391, 606, -2034, -1362, +-2938, -2483, -1845, -2050, 103, -495, 1756, 1233, +2028, 2011, 1023, 1414, -414, 155, -1162, -924, +-953, -1144, -69, -397, 563, 462, 269, 552, +-377, -39, -645, -775, -300, -740, 425, -84, +1000, 842, 1046, 1144, 396, 701, -763, -17, +-1359, -632, -1161, -865, -92, -733, 898, -439, +1090, -29, 782, 320, 146, 750, -460, 1076, +-771, 740, -428, 79, 82, -875, 529, -1375, +347, -1048, 12, 12, -206, 1000, -354, 1198, +-266, 548, -8, -532, 642, -1103, 978, -546, +573, 694, -429, 1435, -1128, 969, -1133, -589, +-457, -2087, 457, -2054, 1138, -451, 1259, 1591, +649, 2726, -442, 2161, -1300, 139, -1071, -2008, +-247, -2721, 578, -1823, 828, 104, 458, 1846, +-108, 2157, -566, 1153, -525, -241, -14, -1280, +502, -1307, 607, -556, 213, 337, -346, 792, +-681, 501, -676, 63, -448, -266, 25, -346, +649, -259, 941, -136, 865, 112, 371, 536, +-552, 807, -1326, 506, -1672, -420, -954, -1310, +630, -1442, 1804, -638, 2078, 835, 920, 1981, +-808, 1958, -2046, 684, -1958, -1118, -674, -2439, +967, -2330, 1915, -811, 1354, 1334, 78, 2742, +-1021, 2471, -1134, 794, -397, -1348, 369, -2638, +606, -2392, 159, -1002, -455, 897, -348, 2327, +315, 2564, 871, 1563, 769, -445, -5, -2121, +-1001, -2743, -1314, -2102, -819, -240, 326, 1699, +1534, 2996, 1840, 2973, 831, 1066, -705, -1558, +-1723, -3610, -1674, -3664, -559, -1312, 556, 1819, +1299, 3941, 1465, 3551, 891, 968, 24, -1900, +-794, -3482, -1268, -2877, -1194, -580, -770, 1617, +218, 2546, 1280, 1987, 1855, 398, 1217, -1058, +-140, -1556, -1498, -1211, -2106, -365, -1289, 327, +306, 678, 1787, 845, 2041, 644, 885, 372, +-1000, -155, -2166, -766, -1694, -1203, 43, -942, +1691, -88, 2142, 1058, 1009, 1829, -1024, 1332, +-2447, 35, -2015, -1470, -131, -2122, 1798, -1350, +2542, 28, 1371, 1392, -696, 1977, -1951, 1220, +-2115, 254, -868, -750, 1008, -1346, 1766, -1208, +1423, -850, 126, -315, -1160, 442, -1198, 1221, +-435, 1701, 611, 1523, 829, 454, 249, -1337, +-359, -2634, -745, -2450, -339, -904, 351, 1511, +807, 3063, 593, 2755, 67, 1043, -493, -1458, +-745, -2939, -361, -2644, 109, -1076, 445, 1232, +351, 2666, 215, 2167, 53, 766, 38, -896, +107, -1985, -116, -1537, -361, -723, -370, 264, +-142, 1023, 140, 1286, 617, 1203, 555, 657, +279, -425, -168, -1536, -674, -2091, -707, -1556, +-253, 175, 383, 2116, 806, 3069, 689, 2176, +146, -69, -436, -2735, -901, -3773, -766, -2615, +-251, 105, 505, 3060, 1187, 3988, 1131, 2491, +250, -241, -879, -2740, -1584, -3282, -1340, -1864, +-276, 97, 1007, 1679, 1811, 1908, 1584, 1143, +295, 401, -1316, -245, -2291, -436, -1677, -503, +128, -939, 1725, -1080, 2047, -691, 1054, 107, +-679, 1226, -1814, 1823, -1578, 1420, -393, 192, +1063, -1215, 1769, -1911, 1110, -1521, -515, -326, +-1491, 813, -1505, 1421, -587, 1087, 799, 516, +1541, 38, 1486, -450, 606, -709, -634, -896, +-1590, -965, -1795, -555, -1040, 475, 449, 1351, +1760, 1821, 2241, 1246, 1523, -234, -320, -1821, +-1868, -2576, -2278, -1707, -1488, 306, 121, 2314, +1621, 2970, 2156, 1693, 1415, -663, 107, -2398, +-1209, -2631, -1698, -1379, -1080, 591, -8, 1938, +861, 2019, 936, 1036, 480, -467, 21, -1423, +-72, -1095, 81, -229, 65, 440, -396, 467, +-859, -327, -688, -723, -80, -293, 763, 657, +1455, 1615, 1179, 1638, 105, 331, -1261, -1461, +-2043, -2744, -1389, -2622, 210, -617, 1650, 1870, +1993, 3509, 1079, 3184, -253, 1019, -1385, -1713, +-1733, -3548, -994, -3374, 99, -1474, 907, 1027, +852, 3055, 376, 3325, 188, 1744, 404, -406, +427, -2271, -193, -2558, -1187, -1458, -1756, 1, +-1435, 1041, -137, 1203, 1874, 925, 2946, 400, +2307, 110, 101, 75, -2595, -76, -3590, -398, +-2439, -709, 103, -1067, 2493, -973, 3383, -109, +2186, 988, -207, 1885, -2144, 1895, -2550, 841, +-1346, -893, 203, -2221, 1259, -2397, 1427, -1426, +842, 188, -109, 1951, -612, 2618, -556, 2115, +-41, 577, 354, -1331, 149, -2351, -127, -2346, +-393, -1240, -376, 59, -300, 1369, 78, 2384, +987, 2361, 1398, 1392, 1015, -450, -226, -2427, +-1729, -3056, -2405, -2500, -1675, -615, 372, 1678, +2695, 3234, 3657, 3533, 2229, 1771, -969, -730, +-3669, -3132, -4108, -4040, -1998, -2649, 1393, -175, +3842, 2263, 3998, 3574, 1781, 3106, -1413, 1318, +-3618, -815, -3436, -2684, -1403, -3320, 1212, -2529, +2668, -603, 2430, 1695, 1001, 3072, -707, 3105, +-1415, 1526, -1146, -679, -760, -2479, -569, -3048, +-252, -1929, 407, 88, 1311, 1857, 1677, 2413, +877, 1580, -573, 2, -1840, -1287, -2128, -1565, +-977, -763, 817, 307, 2214, 1166, 2232, 897, +523, -115, -1536, -854, -2551, -1315, -1942, -718, +-13, 451, 1944, 1314, 2834, 1926, 1813, 1427, +-320, -13, -2258, -1543, -3082, -2713, -1990, -2439, +199, -903, 2271, 1332, 3383, 3160, 2524, 3596, +354, 2047, -1947, -539, -3404, -3033, -3055, -4242, +-1307, -3218, 1290, -627, 3374, 2429, 3732, 4384, +2232, 4035, -635, 1631, -2973, -1577, -3502, -3821, +-2524, -3958, -236, -2217, 1920, 524, 2846, 2699, +2747, 3427, 1176, 2449, -599, 264, -1658, -1822, +-2332, -2730, -1955, -2241, -942, -573, 457, 1208, +1828, 2128, 2550, 1776, 2206, 462, 778, -1037, +-1136, -1778, -2822, -1437, -3226, -319, -1840, 961, +482, 1621, 2934, 1434, 3842, 480, 2592, -746, +107, -1644, -2836, -1850, -4311, -1199, -3399, 189, +-490, 1519, 2716, 2313, 4402, 1934, 3639, 562, +830, -994, -2506, -2200, -4264, -2431, -3630, -1556, +-1164, -22, 1904, 1422, 3544, 2350, 3230, 2279, +1356, 1293, -1124, 41, -2545, -1452, -2572, -2465, +-1459, -2707, 66, -1659, 1150, 268, 1585, 2192, +1459, 3378, 858, 2734, 75, 927, -608, -1273, +-1147, -2868, -1395, -2953, -1298, -1840, -437, 107, +770, 1801, 1803, 2536, 2038, 2249, 1139, 905, +-454, -545, -1828, -1561, -2258, -1930, -1405, -1395, +276, -643, 1713, 546, 2229, 1650, 1408, 1773, +15, 1160, -1437, -159, -2110, -1667, -1436, -1936, +-104, -895, 1503, 693, 2230, 2262, 1551, 1984, +218, 110, -1420, -1965, -2221, -2865, -1804, -1656, +-489, 810, 1371, 2639, 2393, 2777, 2051, 1270, +667, -850, -896, -2185, -1939, -2274, -1860, -1234, +-1046, 85, -87, 893, 968, 1139, 1412, 1074, +1339, 1026, 1204, 920, 662, 460, -316, -714, +-1616, -2187, -2609, -2834, -2433, -2138, -928, 122, +1571, 2715, 3523, 4156, 3743, 3294, 2071, 430, +-1100, -2741, -3853, -4412, -4653, -3689, -2968, -952, +451, 1958, 3353, 3517, 4532, 3249, 3252, 1566, +246, -530, -2420, -2169, -3700, -2610, -2981, -2080, +-994, -764, 915, 856, 2194, 1884, 2384, 2204, +1759, 1592, 572, 223, -908, -1104, -1918, -2029, +-2291, -1807, -1612, -777, -156, 415, 1436, 1423, +2450, 1525, 2163, 1029, 881, 308, -1022, -223, +-2310, -599, -2072, -1037, -1044, -1295, 513, -1046, +1677, -271, 1525, 1042, 1014, 2047, 311, 2025, +-404, 1142, -794, -593, -952, -2098, -945, -2698, +-683, -1889, -31, -44, 683, 1807, 1310, 2737, +1740, 2245, 1222, 760, -185, -924, -1486, -1889, +-2220, -2018, -1654, -1296, -432, -267, 1011, 441, +1911, 1087, 1948, 1530, 1332, 1565, -65, 1046, +-1283, -150, -1804, -1562, -1705, -2241, -857, -1873, +350, -576, 1260, 1044, 1726, 1782, 1375, 1760, +449, 1052, -641, -31, -1341, -750, -1353, -1177, +-827, -1379, 128, -899, 782, -190, 786, 430, +431, 905, -149, 918, -325, 653, -51, 362, +318, -73, 562, -436, 281, -641, -719, -815, +-1529, -712, -1454, -569, -440, -131, 1175, 681, +2339, 1451, 2066, 1878, 674, 1236, -1147, -472, +-2519, -2144, -2450, -2912, -1253, -1958, 612, 172, +2051, 2279, 2548, 3379, 1871, 2455, 183, 220, +-1420, -2177, -2395, -3343, -2293, -2583, -1036, -159, +639, 2080, 2107, 2711, 2560, 1973, 1760, 80, +114, -1376, -1733, -1486, -2414, -811, -1979, 19, +-696, 420, 1055, -64, 1908, -424, 1822, -143, +1067, 686, 116, 1731, -672, 1728, -1134, 450, +-1351, -1472, -1348, -2916, -838, -2725, 290, -803, +1551, 1746, 2378, 3451, 2185, 3259, 774, 1239, +-1171, -1386, -2885, -3219, -2868, -3140, -1437, -1245, +631, 996, 2435, 2120, 2761, 1853, 1664, 597, +-114, -428, -1570, -591, -1735, -162, -851, 294, +-4, 111, 417, -508, 98, -1322, -332, -1339, +-314, -488, 78, 846, 998, 1931, 1622, 2004, +1281, 1048, 159, -453, -1476, -1709, -2549, -2069, +-2279, -1464, -968, -282, 851, 798, 2338, 1178, +2664, 1013, 1914, 649, 244, 305, -1411, 180, +-2271, 15, -2293, -478, -1337, -1017, -24, -1257, +989, -1064, 1657, -282, 1800, 771, 1264, 1308, +296, 1525, -690, 1181, -1391, 381, -1489, -494, +-912, -1196, -322, -1534, 133, -1486, 472, -921, +744, 51, 1092, 1119, 1077, 1997, 751, 2206, +186, 1427, -821, 65, -1524, -1433, -1712, -2479, +-1328, -2417, 16, -1260, 1245, 316, 1794, 1665, +1746, 2226, 902, 1884, 59, 1045, -696, 52, +-1338, -878, -1521, -1529, -1324, -1771, -556, -1524, +554, -870, 1426, 226, 1724, 1446, 1410, 2343, +517, 2527, -525, 1599, -1174, -298, -1357, -2174, +-906, -3316, -265, -2862, -15, -1077, 82, 1088, +422, 2870, 953, 3218, 1522, 2257, 1445, 222, +276, -1799, -1029, -2840, -2127, -2557, -2343, -1014, +-1192, 690, 559, 1733, 1990, 1825, 2241, 1121, +1124, 78, -282, -602, -977, -928, -926, -730, +-327, -236, 31, 27, -243, 100, -657, -180, +-803, -360, -420, -159, 555, 392, 1541, 1052, +1880, 998, 1141, 305, -85, -552, -1478, -1282, +-2233, -1246, -1831, -688, -1036, 241, 364, 1052, +1517, 1261, 1994, 719, 2008, -166, 1124, -713, +-235, -795, -1523, -210, -2315, 217, -2047, 221, +-1019, 20, 409, -272, 1649, -360, 1987, 45, +1733, 569, 794, 761, -417, 577, -983, -122, +-1371, -682, -1420, -763, -956, -428, -418, -7, +457, 157, 1453, 238, 1792, 429, 1460, 660, +552, 646, -697, 333, -1578, -445, -1727, -1121, +-1247, -1245, -222, -780, 899, 371, 1377, 1530, +1397, 1914, 721, 1187, -32, -373, -559, -1800, +-898, -2196, -798, -1275, -502, 407, -15, 1811, +475, 2222, 638, 1368, 401, -267, 54, -1747, +-328, -2110, -357, -1282, -104, 43, 256, 1287, +667, 1641, 610, 1194, -78, 422, -951, -423, +-1380, -971, -1061, -1220, 28, -1164, 1184, -598, +1738, 329, 1476, 1148, 406, 1596, -840, 1254, +-1667, 279, -1737, -875, -944, -1718, 212, -1700, +980, -844, 1227, 513, 932, 1438, 472, 1463, +62, 735, -206, -135, -506, -580, -912, -661, +-1113, -557, -940, -468, -180, -407, 726, -127, +1621, 421, 1723, 844, 920, 969, -321, 501, +-1660, -390, -1932, -1120, -1148, -1188, 111, -404, +1158, 810, 1373, 1506, 954, 1009, 105, -358, +-624, -1560, -847, -1665, -461, -382, 191, 1309, +495, 2109, 325, 1545, -67, -65, -433, -1544, +-346, -2067, -111, -1311, 109, 173, 353, 1239, +434, 1396, 476, 818, 324, 119, -79, -292, +-511, -245, -726, -152, -715, -328, -260, -577, +403, -729, 771, -413, 803, 193, 453, 954, +-7, 1279, -343, 971, -535, 265, -428, -630, +-251, -1259, -88, -1214, 36, -685, 139, -32, +209, 611, 336, 866, 370, 913, 201, 778, +72, 276, -166, -358, -381, -909, -532, -1160, +-426, -773, -117, -62, 71, 643, 290, 975, +381, 699, 421, -47, 382, -634, 138, -560, +-35, -6, -428, 672, -638, 696, -608, -29, +-497, -933, 23, -1377, 376, -877, 548, 180, +716, 1303, 643, 1662, 421, 1157, -144, 136, +-755, -958, -1006, -1602, -1042, -1449, -595, -610, +99, 322, 722, 1052, 1326, 1125, 1342, 781, +791, 356, -25, -117, -1069, -513, -1646, -693, +-1492, -725, -635, -486, 542, -26, 1301, 318, +1448, 610, 897, 579, 103, 224, -453, 2, +-766, -39, -615, 148, -306, 201, -100, -234, +-134, -820, -279, -1036, -124, -601, 336, 384, +953, 1244, 1244, 1440, 940, 897, -47, -50, +-1133, -934, -1782, -1205, -1586, -829, -417, -304, +903, 340, 1644, 469, 1461, 330, 634, 418, +-321, 484, -801, 657, -571, 402, -287, -391, +-201, -1108, -398, -1407, -601, -911, -305, 138, +332, 1068, 1005, 1538, 1448, 1293, 1148, 318, +104, -709, -1127, -1241, -1955, -1207, -1642, -632, +-341, 68, 922, 485, 1485, 796, 1165, 794, +322, 544, -267, 161, -560, -354, -455, -743, +-202, -934, -69, -762, -91, -166, -291, 574, +-295, 1032, -139, 1076, 240, 390, 646, -392, +824, -886, 498, -1001, -46, -529, -506, 25, +-863, 410, -676, 654, -397, 701, -88, 432, +429, 7, 637, -499, 648, -865, 483, -648, +110, -73, -184, 358, -366, 606, -505, 392, +-404, 41, -376, -58, -209, -84, 73, 85, +341, 107, 753, -97, 769, -416, 420, -633, +-61, -334, -583, 176, -752, 759, -556, 952, +-261, 571, 88, -78, 231, -641, 274, -811, +340, -583, 418, -175, 409, 188, 341, 387, +91, 398, -421, 448, -781, 435, -958, 409, +-739, 76, -9, -563, 765, -1050, 1104, -1093, +895, -379, 586, 634, 66, 1248, -428, 1139, +-739, 407, -1039, -314, -983, -727, -607, -777, +85, -513, 904, -153, 1491, 151, 1488, 355, +843, 444, -298, 439, -1391, 299, -1876, -21, +-1514, -407, -397, -672, 827, -527, 1498, 166, +1429, 671, 666, 622, -86, 79, -571, -774, +-839, -914, -550, -348, -177, 500, -126, 1115, +-258, 920, -271, 166, 5, -589, 662, -1024, +1092, -957, 761, -421, 264, 168, -350, 690, +-910, 898, -1004, 723, -838, 319, -276, -240, +379, -651, 672, -921, 807, -751, 873, -217, +665, 486, 43, 965, -677, 743, -1101, 153, +-1150, -473, -610, -696, 177, -251, 898, 384, +1255, 686, 845, 410, -2, -470, -682, -1183, +-725, -1132, -277, -119, 208, 1178, 362, 1911, +98, 1360, -348, -65, -561, -1398, -412, -1923, +188, -1256, 730, 2, 864, 1086, 736, 1377, +151, 1021, -485, 205, -953, -465, -1123, -647, +-712, -512, -61, -263, 577, -58, 1002, -8, +1140, 67, 837, 246, 150, 277, -650, 291, +-1150, 87, -1142, -150, -758, -143, -6, -105, +652, 51, 915, 119, 872, -80, 430, -284, +-25, -395, -169, -232, -350, 224, -524, 566, +-603, 617, -532, 382, -287, -114, 177, -551, +610, -613, 713, -400, 619, -157, 295, 134, +-10, 150, -286, 156, -459, 381, -590, 550, +-694, 526, -495, 213, -231, -450, 219, -1091, +838, -1224, 1325, -700, 1363, 367, 630, 1323, +-605, 1544, -1619, 809, -1936, -276, -1560, -1094, +-338, -1136, 1111, -602, 2074, -29, 2155, 330, +1108, 351, -211, 365, -1243, 395, -1728, 452, +-1502, 286, -917, -143, -11, -635, 861, -892, +1269, -579, 1372, 55, 1123, 679, 375, 917, +-484, 519, -1189, -149, -1503, -567, -1102, -521, +-436, -100, 342, 252, 1068, 253, 1227, -18, +997, -244, 436, -214, -175, 183, -420, 532, +-640, 469, -943, 29, -1068, -623, -742, -891, +74, -468, 985, 366, 1541, 976, 1474, 1024, +729, 352, -387, -610, -1300, -1094, -1629, -983, +-1217, -268, -403, 527, 444, 870, 1087, 849, +1254, 464, 1039, 40, 394, -396, -360, -775, +-848, -985, -1206, -707, -950, 5, -249, 812, +520, 1287, 1047, 1044, 839, 188, 211, -735, +-418, -1220, -615, -1038, -297, -206, 242, 586, +576, 896, 330, 532, -356, -149, -934, -567, +-800, -291, -41, 377, 806, 741, 1125, 381, +725, -456, -62, -1235, -765, -1147, -819, -152, +-326, 952, 217, 1621, 434, 1168, 169, -46, +-298, -1174, -444, -1461, -147, -773, 429, 281, +887, 1018, 842, 874, 128, 187, -800, -493, +-1181, -697, -934, -237, -219, 329, 530, 652, +899, 481, 915, -73, 547, -567, -99, -765, +-433, -513, -564, -5, -545, 489, -311, 757, +-151, 668, 84, 442, 379, -5, 578, -487, +429, -907, 40, -1122, -230, -645, -332, 310, +-174, 1320, 45, 1672, 87, 965, -185, -319, +-332, -1449, -220, -1744, 58, -889, 495, 465, +505, 1413, 311, 1426, -12, 400, -457, -816, +-456, -1288, -168, -669, 172, 490, 333, 1224, +-100, 927, -560, -234, -589, -1275, -46, -1370, +833, -495, 1354, 801, 1092, 1615, 41, 1395, +-1281, 287, -2097, -1020, -1570, -1607, -150, -1268, +1279, -168, 2029, 859, 1676, 1233, 574, 941, +-668, 210, -1392, -428, -1444, -706, -949, -686, +-151, -433, 451, 0, 874, 382, 1035, 630, +861, 556, 423, 86, -233, -413, -787, -626, +-1096, -511, -971, 34, -242, 559, 569, 676, +977, 367, 845, -267, 286, -840, -216, -776, +-433, -154, -437, 576, -230, 916, 37, 559, +108, 11, -14, -515, -96, -612, 117, -319, +306, -68, 249, 160, -56, 131, -313, 6, +-255, 72, 23, 363, 291, 637, 358, 437, +164, -272, -325, -1062, -688, -1260, -593, -597, +42, 594, 769, 1497, 992, 1395, 568, 505, +-321, -646, -922, -1372, -967, -1129, -487, -391, +447, 421, 942, 914, 801, 768, 191, 330, +-627, -11, -810, -330, -463, -455, 32, -385, +570, -397, 674, -83, 374, 355, -111, 611, +-540, 614, -587, 203, -271, -443, -45, -769, +134, -613, 395, -94, 499, 644, 514, 815, +168, 447, -329, -178, -712, -788, -777, -706, +-417, -195, 177, 430, 800, 824, 909, 519, +446, -85, -245, -645, -710, -794, -622, -269, +-167, 328, 296, 630, 502, 584, 312, 247, +-153, -233, -557, -571, -424, -678, 149, -495, +573, 79, 601, 583, 127, 844, -348, 596, +-354, 81, -207, -410, -55, -714, -49, -682, +-200, -428, -318, 40, 8, 433, 622, 688, +1047, 699, 884, 431, -52, -25, -1163, -493, +-1650, -834, -1126, -842, 82, -389, 1253, 239, +1604, 784, 1016, 879, -56, 477, -874, 15, +-923, -323, -471, -339, 5, -299, 108, -434, +-156, -466, -227, -295, 73, 215, 596, 796, +1058, 1023, 805, 731, -118, -101, -1020, -900, +-1442, -1246, -879, -827, 222, 185, 862, 987, +860, 1087, 360, 415, -109, -556, -86, -1050, +181, -479, 242, 401, -159, 1059, -774, 866, +-1080, -182, -701, -1065, 318, -1233, 1239, -516, +1480, 502, 807, 1070, -341, 945, -1195, 324, +-1229, -334, -522, -450, 263, -224, 646, -87, +453, -255, 37, -621, -114, -744, 39, -101, +330, 1022, 393, 1733, 48, 1444, -417, 134, +-782, -1457, -679, -2320, -58, -1724, 516, -124, +735, 1503, 462, 2131, -22, 1423, -116, -56, +29, -1187, 23, -1243, -166, -561, -551, 291, +-749, 464, -372, -10, 282, -402, 915, -348, +1108, 271, 618, 950, -176, 944, -845, 291, +-1135, -621, -730, -1301, 7, -1056, 535, -179, +836, 696, 608, 1046, 50, 662, -265, -22, +-313, -460, -222, -389, -83, -109, 16, 87, +-85, 145, -177, -20, -21, -259, 140, -226, +239, -120, 310, 128, 143, 411, -84, 445, +-176, 302, -255, -14, -255, -279, -134, -556, +89, -557, 230, -287, 210, 123, 78, 533, +-74, 752, -144, 512, -43, -16, 111, -497, +212, -683, 132, -372, -223, 106, -468, 308, +-400, 209, -13, -54, 490, -181, 679, 115, +427, 391, -133, 502, -605, 143, -694, -480, +-382, -911, 295, -803, 773, -15, 637, 800, +47, 1143, -659, 775, -873, -172, -368, -889, +397, -948, 931, -523, 778, 250, 103, 672, +-640, 505, -958, 125, -554, -191, 92, -154, +513, 140, 517, 190, 185, -120, -50, -597, +-4, -744, 105, -233, 191, 659, -93, 1292, +-589, 1062, -802, -65, -595, -1287, 144, -1651, +1048, -861, 1393, 567, 874, 1620, -246, 1424, +-1284, 277, -1557, -969, -869, -1469, 284, -790, +1127, 354, 1229, 1126, 593, 964, -275, 37, +-786, -918, -630, -1076, -67, -336, 275, 702, +270, 1287, -61, 795, -401, -327, -323, -1257, +50, -1273, 592, -288, 812, 852, 405, 1349, +-387, 935, -1001, -130, -936, -1019, -244, -1145, +589, -531, 961, 369, 704, 977, 52, 878, +-640, 312, -807, -395, -343, -831, 207, -707, +573, -303, 501, 233, 38, 655, -310, 717, +-479, 497, -411, 77, 66, -465, 451, -861, +474, -786, 242, -284, -171, 430, -375, 901, +-327, 761, -248, 289, 12, -280, 226, -579, +329, -406, 361, -197, 31, 8, -227, 58, +-327, -117, -401, -19, -122, 272, 169, 546, +381, 625, 489, 190, 185, -406, -216, -838, +-525, -875, -533, -391, -227, 212, 175, 721, +489, 907, 591, 605, 376, 138, -47, -354, +-507, -689, -726, -708, -528, -512, -69, -167, +495, 273, 687, 698, 486, 865, 115, 630, +-301, -12, -422, -733, -397, -1032, -305, -656, +-7, 75, 139, 605, 283, 697, 364, 339, +188, -34, 100, -277, -66, -344, -333, -178, +-354, -22, -261, 102, -100, 177, 206, 66, +352, -23, 253, -12, 127, -45, -45, -115, +-121, -170, -68, -43, -103, 189, -247, 376, +-344, 348, -138, 24, 244, -424, 557, -643, +593, -467, 224, -6, -342, 552, -725, 789, +-737, 547, -194, -38, 498, -569, 730, -719, +470, -446, -66, 32, -358, 395, -269, 444, +-142, 293, -52, 75, 3, -128, -64, -210, +-64, -210, 155, -126, 315, -5, 372, 90, +94, 112, -438, 64, -640, -6, -412, -23, +116, 2, 583, 60, 646, 120, 286, 2, +-337, -149, -793, -189, -624, -144, 33, 93, +704, 328, 748, 219, 160, -74, -478, -376, +-706, -383, -369, 17, 231, 477, 538, 663, +347, 248, -55, -458, -371, -923, -346, -769, +-66, -46, 238, 794, 389, 1167, 208, 781, +-107, -62, -455, -913, -563, -1183, -147, -796, +327, 21, 550, 767, 492, 1024, 149, 764, +-197, 159, -471, -449, -615, -795, -527, -749, +-83, -389, 585, 188, 886, 641, 677, 736, +70, 386, -598, -179, -920, -586, -721, -589, +-98, -100, 615, 436, 981, 618, 605, 298, +-270, -401, -889, -906, -801, -706, -44, 99, +767, 1013, 926, 1315, 332, 695, -529, -471, +-994, -1396, -785, -1433, -71, -526, 635, 664, +940, 1370, 702, 1213, 36, 317, -511, -658, +-734, -1039, -562, -724, -117, -24, 149, 592, +259, 581, 235, 91, 237, -383, 249, -526, +164, -125, 33, 459, -278, 752, -441, 550, +-391, -111, -300, -739, -53, -983, 180, -666, +390, 56, 539, 728, 453, 1026, 206, 837, +-284, 226, -690, -504, -801, -997, -608, -955, +2, -413, 672, 308, 957, 821, 650, 806, +-85, 385, -631, -125, -659, -498, -248, -509, +307, -231, 351, 38, -27, 225, -393, 103, +-515, -25, -111, -15, 545, 72, 881, 253, +603, 201, -76, -100, -781, -379, -1030, -401, +-585, -141, 175, 305, 691, 541, 684, 365, +189, -69, -303, -495, -336, -580, -42, -316, +386, 188, 378, 644, -179, 684, -671, 321, +-791, -245, -303, -670, 432, -686, 816, -319, +735, 106, 213, 382, -271, 510, -453, 439, +-419, 300, -184, 60, -41, -265, -118, -630, +-210, -778, -37, -488, 337, 117, 623, 724, +681, 965, 291, 651, -307, 24, -793, -485, +-986, -777, -616, -671, 7, -293, 614, 111, +844, 466, 597, 568, 292, 453, -74, 259, +-390, -107, -557, -417, -624, -498, -427, -415, +-66, -119, 298, 246, 594, 392, 561, 360, +251, 190, -95, -119, -352, -261, -356, -172, +-191, 5, -101, 136, -128, 47, -144, -180, +-38, -255, 163, -128, 349, 160, 448, 440, +297, 465, -90, 152, -510, -300, -708, -634, +-392, -569, 181, -109, 494, 376, 443, 629, +82, 541, -264, 132, -296, -322, -145, -559, +124, -536, 324, -188, 239, 232, -95, 508, +-389, 518, -401, 219, -141, -128, 149, -415, +228, -505, 211, -251, 146, 52, 38, 273, +12, 408, 6, 293, -41, 28, -158, -172, +-348, -239, -362, -157, -188, -54, 111, -40, +368, -89, 473, -75, 565, 117, 324, 327, +-192, 446, -637, 315, -881, -71, -757, -561, +-283, -876, 393, -657, 1010, 65, 1185, 892, +738, 1207, -154, 772, -1016, -167, -1337, -981, +-1020, -1171, -181, -736, 750, 95, 1201, 771, +982, 994, 253, 737, -553, 137, -927, -508, +-790, -858, -210, -724, 363, -219, 586, 386, +432, 663, -59, 546, -333, 144, -302, -243, +-147, -403, 70, -360, 79, -116, 113, 171, +174, 270, 104, 194, 67, 26, -120, -132, +-391, -151, -563, -151, -447, -81, 78, 105, +732, 244, 1043, 276, 687, 123, -220, -205, +-1004, -372, -1238, -347, -806, -141, 153, 213, +954, 452, 1144, 423, 635, 114, -136, -241, +-683, -464, -760, -400, -346, -70, 97, 273, +246, 477, 176, 389, -39, -50, -111, -471, +95, -567, 316, -242, 275, 317, -6, 639, +-263, 576, -421, 173, -322, -380, -120, -734, +93, -731, 316, -320, 288, 363, 155, 836, +51, 879, -59, 433, -110, -247, -196, -732, +-336, -856, -266, -525, 1, -21, 294, 430, +389, 690, 220, 622, -70, 277, -309, -151, +-263, -458, -79, -483, 67, -264, 196, -79, +78, 14, -155, 71, -219, 203, -214, 385, +71, 384, 338, 129, 307, -190, 76, -427, +-270, -448, -449, -211, -306, 57, 53, 293, +266, 361, 298, 221, 121, 1, -197, -230, +-317, -282, -202, -125, 111, 131, 364, 334, +268, 283, -97, -78, -485, -487, -490, -593, +-123, -303, 321, 331, 541, 847, 384, 805, +-29, 280, -483, -454, -640, -910, -315, -810, +268, -295, 721, 248, 541, 624, -151, 739, +-655, 516, -724, 56, -258, -390, 400, -599, +739, -526, 670, -182, 134, 108, -579, 191, +-870, 258, -621, 344, 38, 391, 646, 230, +705, -146, 327, -545, -216, -672, -552, -377, +-443, 171, 6, 560, 371, 577, 428, 312, +60, -55, -462, -299, -591, -416, -332, -327, +234, -130, 703, 117, 720, 368, 307, 391, +-382, 201, -892, -89, -827, -385, -279, -422, +402, -199, 751, 159, 586, 489, 103, 424, +-291, 93, -416, -303, -327, -538, -45, -382, +171, 31, 176, 423, -69, 563, -288, 228, +-295, -266, -35, -498, 360, -347, 519, 135, +355, 441, -7, 305, -453, -129, -759, -478, +-597, -390, -58, 76, 436, 568, 595, 669, +425, 206, 149, -476, -164, -900, -355, -676, +-298, 46, -188, 757, -90, 984, -93, 511, +-127, -308, 65, -858, 395, -777, 501, -221, +204, 471, -183, 723, -445, 434, -551, -48, +-304, -404, 44, -455, 380, -176, 542, 144, +232, 265, -190, 268, -415, 57, -411, -86, +-103, -108, 329, -129, 482, -117, 305, -124, +-123, -45, -528, 134, -528, 339, -212, 343, +100, 99, 338, -268, 482, -501, 446, -417, +224, -22, -232, 440, -595, 532, -730, 199, +-569, -291, 25, -495, 579, -186, 915, 353, +778, 571, 103, 242, -599, -402, -975, -803, +-858, -618, -241, 48, 505, 765, 931, 1020, +812, 639, 175, -142, -601, -873, -890, -1103, +-601, -665, -39, 86, 539, 789, 608, 1004, +314, 644, -132, -20, -412, -593, -227, -755, +-31, -492, -26, -48, -160, 293, -244, 396, +-34, 264, 346, 133, 539, 27, 477, -46, +71, -136, -553, -222, -1008, -242, -885, -122, +-123, 102, 727, 235, 1132, 226, 883, 115, +168, -12, -577, -89, -954, -120, -884, -192, +-425, -196, 228, -87, 660, 96, 672, 340, +486, 438, 101, 217, -254, -187, -428, -513, +-587, -582, -419, -250, -78, 236, 246, 576, +541, 594, 503, 300, 187, -101, -233, -491, +-506, -644, -376, -498, -93, -30, 204, 448, +321, 714, 179, 598, 3, 73, -224, -458, +-295, -660, -97, -438, 117, -16, 241, 339, +146, 413, -18, 238, -81, -3, -101, -143, +-86, -183, -113, -111, -108, 7, -33, 74, +56, 71, 124, -2, 162, -70, 158, -74, +60, -32, -154, 87, -297, 167, -320, 131, +-154, -3, 98, -185, 263, -199, 324, -100, +169, 18, -70, 108, -285, 145, -293, 129, +-108, 57, 62, -38, 111, -132, 64, -178, +-17, -96, -63, 20, -23, 77, 41, 146, +88, 137, 2, 57, -61, -26, -122, -112, +-135, -170, -45, -207, -4, -101, 22, 92, +110, 298, 148, 406, 57, 231, -61, -169, +-151, -520, -180, -577, -109, -268, 19, 276, +109, 686, 190, 663, 77, 182, -98, -383, +-137, -676, -87, -539, 18, -77, 86, 368, +19, 504, -56, 310, -60, -45, -100, -258, +-14, -195, 141, 5, 183, 110, 102, 20, +-79, -86, -262, -111, -273, -1, -108, 38, +111, -15, 283, 12, 293, 125, 100, 271, +-139, 286, -204, 15, -196, -402, -143, -628, +-43, -483, -16, 25, 67, 580, 206, 753, +278, 480, 270, -7, 50, -402, -324, -477, +-604, -400, -515, -278, -29, -104, 418, 157, +613, 452, 448, 626, 56, 456, -315, -26, +-524, -468, -400, -590, -167, -336, 147, 10, +351, 156, 250, 31, 100, -1, -112, 155, +-175, 446, -55, 566, 41, 197, 80, -388, +-36, -846, -172, -827, -233, -257, -226, 468, +-4, 810, 385, 691, 640, 225, 434, -248, +-229, -410, -809, -421, -887, -306, -264, -104, +523, 109, 855, 307, 668, 320, 56, 88, +-521, -148, -756, -161, -502, 24, 83, 230, +514, 198, 537, -173, 191, -505, -192, -413, +-259, -21, -251, 492, -123, 634, 96, 274, +90, -186, 135, -534, 52, -477, -83, -22, +22, 313, 66, 384, 103, 213, 80, -170, +-195, -300, -359, -206, -294, -66, -28, 49, +439, 166, 602, 301, 354, 380, -108, 185, +-507, -277, -575, -683, -348, -709, -8, -182, +330, 510, 513, 892, 445, 691, 155, 126, +-245, -443, -478, -712, -350, -593, -67, -261, +107, 148, 149, 476, 18, 587, 49, 443, +141, 73, 178, -343, 140, -518, -63, -407, +-200, -114, -351, 198, -365, 273, -67, 138, +234, 42, 470, 137, 440, 268, 31, 184, +-286, -284, -368, -712, -260, -613, -83, -8, +78, 677, 141, 837, 205, 395, 219, -187, +26, -470, -160, -519, -241, -320, -128, -84, +112, 119, 156, 353, 59, 432, -77, 292, +-117, 35, -41, -218, 45, -398, 159, -398, +187, -216, 93, 90, -191, 341, -434, 409, +-329, 237, 162, -15, 597, -149, 550, -179, +34, -231, -476, -262, -580, -169, -349, 111, +103, 435, 441, 473, 562, 161, 339, -252, +-129, -420, -522, -301, -526, -46, -120, 103, +268, 130, 438, 211, 297, 237, -32, 120, +-270, -92, -271, -341, -62, -353, 219, -60, +259, 230, 67, 342, -192, 187, -268, -96, +-86, -204, 138, -97, 233, 60, 119, 88, +-34, -53, -111, -157, -86, -55, 39, 123, +94, 240, -46, 128, -138, -105, -117, -200, +45, -155, 249, 22, 200, 158, -2, 107, +-143, -34, -145, -117, -67, -111, 1, 45, +57, 195, 113, 148, 103, -22, -64, -217, +-172, -283, -40, -132, 189, 148, 284, 352, +69, 305, -222, 19, -324, -271, -228, -361, +81, -187, 363, 96, 347, 245, 81, 185, +-260, 7, -353, -94, -101, -48, 286, 56, +383, 115, 82, 19, -262, -197, -466, -318, +-291, -242, 140, 38, 485, 408, 626, 559, +402, 401, -160, -53, -667, -567, -808, -727, +-455, -475, 226, 50, 756, 524, 855, 689, +469, 432, -90, 39, -577, -310, -706, -439, +-421, -327, -32, -120, 265, 84, 366, 27, +317, -3, 314, 120, 318, 342, 67, 493, +-295, 277, -644, -235, -691, -708, -301, -733, +356, -280, 824, 339, 862, 674, 391, 550, +-346, 232, -722, -125, -697, -315, -250, -350, +225, -363, 474, -221, 444, 120, 179, 426, +-80, 474, -179, 187, -81, -241, -29, -420, +-74, -256, -149, 108, -87, 332, 159, 206, +350, -78, 219, -265, -103, -258, -343, -26, +-264, 140, 93, 273, 429, 328, 407, 190, +-2, -186, -464, -577, -553, -606, -130, -118, +402, 610, 596, 844, 290, 445, -141, -321, +-376, -739, -235, -594, -61, -62, 127, 418, +299, 523, 180, 224, -71, -214, -281, -417, +-266, -265, 35, 242, 418, 576, 482, 438, +267, -193, -174, -805, -557, -925, -674, -299, +-363, 666, 308, 1205, 919, 958, 963, 136, +249, -706, -562, -1143, -874, -937, -674, -304, +-121, 448, 381, 981, 662, 946, 666, 348, +290, -259, -271, -535, -652, -494, -466, -313, +-64, -252, 336, -122, 439, 199, 223, 524, +-39, 576, -261, 311, -279, -120, 71, -446, +364, -385, 251, -232, -109, -25, -367, 68, +-146, 114, 206, 196, 289, 288, 24, 213, +-179, -125, -88, -331, 97, -307, 149, 43, +127, 310, 21, 323, -106, -41, -190, -367, +-93, -358, 122, -88, 275, 256, 207, 462, +-63, 284, -239, -65, -200, -230, -6, -283, +177, -164, 357, -46, 230, 121, -48, 222, +-265, 217, -313, -27, -140, -314, 87, -338, +200, 67, 213, 499, 271, 554, 215, 135, +43, -485, -161, -774, -416, -518, -415, 19, +-88, 498, 296, 742, 547, 573, 393, 147, +34, -417, -241, -722, -247, -703, -75, -207, +74, 463, 104, 740, 22, 459, -62, 18, +-177, -391, -114, -579, 153, -250, 470, 162, +479, 467, 223, 502, -231, 66, -621, -511, +-577, -693, -216, -268, 242, 392, 479, 733, +509, 471, 320, -187, 189, -614, 17, -451, +-238, 74, -522, 431, -587, 380, -320, -107, +228, -459, 737, -315, 775, 56, 453, 349, +-188, 442, -612, 129, -600, -214, -193, -298, +305, -228, 434, 43, 175, 136, -57, -16, +-222, -213, -90, -68, 223, 334, 325, 579, +209, 337, -87, -303, -316, -846, -278, -755, +21, -60, 208, 725, 139, 1102, 12, 675, +-36, -372, -4, -1266, 169, -1238, 298, -240, +306, 1152, 87, 1764, -403, 968, -814, -696, +-513, -1951, 270, -1718, 963, -91, 1025, 1704, +271, 2129, -603, 844, -897, -1033, -474, -1987, +193, -1388, 615, 257, 484, 1551, 23, 1505, +-419, 377, -355, -877, 97, -1415, 509, -865, +587, 337, 21, 1150, -617, 1066, -728, 136, +-210, -896, 604, -1169, 915, -325, 493, 851, +-256, 1298, -831, 469, -712, -953, 1, -1617, +589, -887, 938, 772, 563, 1876, -210, 1524, +-742, -43, -773, -1621, -125, -1976, 420, -808, +580, 817, 369, 1708, 32, 1293, -192, -28, +-106, -1103, 24, -1111, 87, -276, -9, 677, +-281, 985, -376, 292, -74, -733, 482, -1157, +772, -507, 541, 761, -87, 1489, -720, 940, +-797, -418, -281, -1468, 389, -1285, 807, -101, +575, 1139, -52, 1369, -503, 466, -468, -777, +5, -1350, 494, -769, 471, 442, -9, 1354, +-513, 1150, -501, 69, 43, -1133, 630, -1453, +671, -613, 205, 685, -400, 1405, -698, 846, +-470, -402, 78, -1159, 635, -682, 846, 467, +461, 1175, -233, 692, -738, -549, -710, -1372, +-154, -1184, 293, 5, 562, 1223, 588, 1585, +383, 916, -42, -274, -376, -1207, -426, -1401, +-292, -809, -110, 160, 4, 986, 278, 1126, +596, 584, 659, -224, 207, -632, -436, -423, +-793, 66, -612, 186, -19, -190, 655, -566, +930, -456, 504, 231, -272, 1014, -817, 1204, +-633, 449, 8, -728, 556, -1546, 642, -1228, +417, -105, -25, 1054, -490, 1461, -580, 883, +-159, -197, 338, -1018, 417, -1152, 194, -588, +-53, 385, -17, 932, 107, 897, 119, 270, +-13, -475, -111, -849, -248, -641, -322, -65, +-91, 531, 518, 731, 712, 369, 377, -143, +-192, -412, -588, -355, -420, -120, -60, 46, +247, 57, 405, 155, 342, 118, 0, 51, +-307, 36, -293, 10, 130, 34, 428, 1, +381, -150, -70, -266, -374, -131, -463, 46, +-184, 255, 348, 293, 677, 155, 534, -25, +-81, -215, -564, -163, -522, -125, -57, -50, +327, -28, 454, 20, 312, 84, 131, 233, +-165, 263, -402, 109, -350, -28, -19, -349, +363, -581, 407, -449, 295, 147, 189, 706, +-83, 915, -300, 470, -409, -409, -290, -1029, +-24, -965, 345, -284, 537, 623, 467, 1136, +161, 869, -152, 5, -350, -812, -329, -965, +-249, -453, -169, 233, 151, 562, 463, 499, +643, 120, 313, -168, -117, -205, -345, -70, +-289, 111, -165, 96, -142, -196, -102, -436, +220, -351, 454, 179, 474, 753, 250, 820, +-93, 230, -339, -692, -400, -1173, -259, -720, +-26, 278, 286, 1018, 419, 1056, 351, 235, +152, -636, -94, -907, -304, -575, -205, 40, +-80, 622, 75, 765, 165, 319, 209, -242, +195, -705, 90, -650, -80, -20, -136, 663, +-119, 795, -86, 120, 68, -610, 283, -865, +425, -252, 331, 721, -257, 1029, -778, 328, +-527, -791, 132, -1156, 820, -633, 979, 647, +420, 1386, -469, 906, -957, -300, -772, -1266, +-37, -1187, 704, -177, 961, 999, 429, 1261, +-319, 564, -558, -648, -284, -1241, 213, -837, +408, 287, 195, 1274, -286, 1185, -507, 34, +-264, -1271, 249, -1567, 903, -562, 961, 1040, +200, 1882, -803, 1137, -1286, -521, -774, -1821, +279, -1588, 1129, -4, 1198, 1474, 435, 1619, +-573, 342, -880, -1155, -456, -1586, 226, -439, +531, 1020, 214, 1680, -248, 779, -349, -849, +17, -1892, 464, -1407, 649, 270, 345, 1757, +-286, 1962, -823, 534, -680, -1138, 85, -1895, +739, -1131, 855, 427, 206, 1502, -450, 1189, +-633, -107, -263, -1299, 366, -1202, 642, 13, +560, 1301, -38, 1653, -581, 535, -824, -1172, +-540, -2005, 319, -1472, 1166, 93, 1127, 1797, +398, 2121, -529, 1007, -1193, -604, -877, -1741, +-192, -1548, 505, -467, 929, 559, 867, 1093, +402, 866, -289, 362, -752, -179, -680, -540, +-289, -598, 312, -413, 655, -182, 598, 253, +312, 662, -242, 852, -583, 482, -505, -455, +-6, -1375, 582, -1454, 679, -288, 244, 1215, +-301, 2118, -509, 1479, -259, -233, 44, -1799, +418, -2143, 375, -1103, 84, 577, -190, 1573, +-297, 1431, 69, 567, 411, -299, 473, -603, +4, -484, -468, -363, -649, -410, -378, -516, +274, -334, 961, 380, 1057, 1185, 361, 1429, +-698, 692, -1254, -744, -825, -1830, 233, -1574, +1137, -296, 1036, 1148, 236, 1573, -611, 831, +-854, -275, -346, -1013, 506, -753, 976, 59, +528, 680, -450, 558, -1138, -307, -862, -990, +358, -816, 1347, 363, 1315, 1440, 261, 1452, +-790, 210, -1274, -1405, -905, -2045, 138, -1138, +950, 682, 1111, 1973, 481, 1887, -377, 341, +-764, -1375, -228, -1886, 416, -969, 543, 489, +-17, 1438, -798, 969, -914, -203, -7, -952, +1371, -730, 1856, 311, 889, 1015, -987, 718, +-2238, -371, -1838, -1269, -45, -1100, 1715, -76, +2327, 1087, 1560, 1510, -400, 786, -1984, -571, +-2039, -1476, -524, -1317, 1286, -148, 1889, 1309, +920, 1589, -597, 533, -1153, -1050, -714, -1775, +168, -1108, 790, 555, 950, 1804, 331, 1688, +-698, 336, -977, -1236, -460, -1833, 469, -1271, +967, 128, 642, 1165, -50, 1420, -501, 790, +-472, -270, -147, -878, 381, -813, 604, -193, +162, 436, -554, 464, -542, -108, 56, -606, +666, -509, 664, 194, 119, 964, -258, 1023, +-461, 349, -310, -777, -50, -1359, 381, -940, +550, 57, 196, 944, -338, 1040, -447, 318, +4, -470, 443, -635, 640, -291, 281, 504, +-207, 733, -574, 170, -756, -727, -271, -1361, +591, -882, 1028, 426, 745, 1679, 14, 1807, +-531, 660, -588, -936, -314, -2004, 10, -1777, +199, -305, 323, 1244, 235, 1790, 1, 1114, +117, -294, 388, -1285, 379, -1113, 12, 26, +-579, 994, -768, 1058, -473, 83, 202, -1308, +871, -1808, 1053, -711, 665, 1130, -96, 2364, +-856, 2176, -975, 215, -422, -1875, 335, -2749, +860, -2007, 595, -38, 14, 1719, -402, 2262, +-207, 1533, 323, 265, 569, -735, 235, -1198, +-358, -1205, -758, -903, -595, -486, -27, 206, +599, 864, 1075, 1183, 986, 1248, 371, 734, +-658, -191, -1207, -1192, -1043, -1813, -310, -1451, +677, -357, 1243, 1017, 1149, 1816, 475, 1588, +-492, 545, -1094, -678, -908, -1413, -149, -1290, +615, -555, 921, 317, 625, 863, 2, 825, +-556, 409, -647, -232, -275, -601, 423, -567, +915, -103, 635, 393, 67, 647, -580, 510, +-900, -123, -682, -837, 47, -1086, 864, -620, +1293, 332, 897, 1220, -3, 1278, -880, 652, +-1238, -304, -690, -1171, 59, -1322, 902, -857, +1144, 83, 741, 994, 29, 1171, -773, 717, +-810, -48, -364, -624, 272, -694, 809, -427, +743, -122, 95, 194, -586, 260, -778, 139, +-297, 101, 529, 47, 1031, -23, 736, -148, +3, -85, -562, 44, -850, 257, -606, 156, +16, -272, 707, -480, 1039, -401, 672, -2, +-44, 468, -595, 637, -668, 408, -460, -28, +-41, -632, 619, -768, 977, -418, 757, 278, +-85, 838, -918, 722, -1163, -15, -594, -803, +458, -1085, 1384, -496, 1708, 708, 1012, 1480, +-531, 1222, -1930, -113, -2213, -1504, -1311, -2035, +748, -1167, 2625, 527, 3087, 2057, 1733, 2368, +-780, 1149, -2967, -923, -3352, -2549, -1633, -2650, +1007, -962, 3048, 1304, 3239, 2753, 1551, 2519, +-993, 623, -2527, -1646, -2365, -2779, -771, -2089, +1102, -229, 1697, 1776, 1270, 2280, 197, 1470, +-595, -178, -487, -1479, -25, -1632, 410, -906, +194, 157, -435, 902, -898, 835, -463, 404, +809, 48, 1759, -201, 1504, -6, -64, -45, +-1843, -304, -2395, -799, -1188, -974, 1099, -283, +2901, 851, 2850, 1753, 851, 1648, -1901, 239, +-3344, -1341, -2623, -2281, -191, -1957, 2541, -433, +3437, 1474, 2310, 2492, -263, 2051, -2363, 386, +-2575, -1552, -1327, -2327, 587, -1756, 1705, -180, +1597, 1272, 662, 1828, -250, 1262, -752, -99, +-588, -1264, -106, -1396, 205, -667, 409, 575, +346, 1288, 222, 1109, -192, 105, -619, -1152, +-545, -1698, -124, -1126, 850, 316, 1477, 1788, +1218, 2130, 90, 1044, -1289, -678, -2027, -2233, +-1481, -2380, 222, -1120, 1896, 970, 2463, 2476, +1442, 2306, -529, 653, -2149, -1415, -1959, -2540, +-440, -1720, 1471, 214, 2249, 1875, 1120, 2185, +-867, 712, -2375, -1343, -1785, -2430, 430, -1669, +2597, 407, 3081, 2371, 1159, 2609, -1608, 1023, +-3384, -1381, -2764, -2891, -245, -2481, 2379, -497, +3416, 1761, 2130, 2721, -451, 1935, -2179, 102, +-2226, -1557, -918, -2075, 1035, -1373, 1872, -32, +1246, 1020, -229, 1222, -1311, 822, -1212, 39, +-104, -546, 1375, -751, 1719, -605, 807, 34, +-413, 436, -1554, 650, -1622, 329, -424, -342, +886, -663, 1559, -711, 1229, -186, 138, 382, +-643, 850, -842, 984, -250, 426, 261, -481, +472, -1253, 409, -1463, -142, -578, -471, 667, +-493, 1493, -60, 1419, 600, 324, 1111, -738, +937, -1345, 226, -1025, -549, -82, -1118, 636, +-1102, 916, -474, 538, 376, -291, 1067, -788, +1235, -701, 1050, -131, 369, 772, -360, 1179, +-852, 701, -1193, -164, -1054, -1405, -416, -1935, +673, -1283, 1735, 235, 1829, 2116, 1076, 2859, +-374, 1926, -1661, -298, -1735, -2757, -1197, -3747, +157, -2589, 1533, 84, 1875, 3011, 1324, 4296, +179, 3180, -989, 184, -1378, -3166, -1073, -4653, +-387, -3502, 420, -347, 1022, 3005, 1304, 4382, +1189, 3321, 546, 433, -361, -2437, -1560, -3747, +-2144, -3029, -1380, -822, 348, 1599, 2450, 2868, +3398, 2693, 2316, 1277, -379, -713, -3100, -2145, +-4155, -2592, -2590, -1811, 781, -127, 3973, 1672, +4787, 2498, 2639, 2140, -1064, 416, -4150, -1418, +-4555, -2428, -2130, -2133, 1528, -509, 4342, 1179, +4438, 2098, 1677, 1636, -2004, 400, -4086, -878, +-3468, -1435, -624, -1180, 2300, -531, 3617, 355, +2847, 700, 251, 679, -2125, 672, -2957, 291, +-1990, 20, 215, -400, 2150, -1034, 2502, -1100, +1496, -787, -257, 178, -1688, 1422, -1887, 1898, +-1014, 1293, 559, -201, 1690, -1824, 1768, -2499, +886, -1498, -636, 237, -1652, 1795, -1602, 2303, +-517, 1312, 1105, -173, 2129, -1231, 1785, -1616, +509, -947, -1250, -152, -2318, 155, -1886, 316, +-341, 347, 1839, 613, 2761, 1098, 2034, 991, +109, 82, -1771, -1059, -2319, -2308, -1558, -2127, +42, -639, 1523, 1466, 2136, 3125, 1419, 2840, +-28, 620, -1110, -1913, -1231, -3391, -708, -2830, +-44, -416, 620, 1884, 915, 3039, 807, 2301, +382, 270, -230, -1718, -659, -2496, -617, -1928, +-337, -165, 151, 1410, 863, 1878, 1040, 1424, +674, 188, -263, -981, -984, -1391, -930, -1161, +-274, -556, 507, 289, 999, 886, 1019, 1159, +327, 1026, -425, 248, -870, -616, -535, -1242, +264, -1411, 787, -660, 593, 290, -49, 988, +-533, 1204, -550, 828, 73, 99, 720, -340, +1029, -684, 559, -933, -315, -753, -834, -578, +-845, -111, -317, 732, 373, 1297, 750, 1321, +806, 791, 713, -288, 196, -1487, -194, -2000, +-489, -1524, -912, -337, -664, 1191, -76, 2209, +715, 2144, 1288, 837, 1141, -863, 527, -2136, +-423, -2316, -1182, -1246, -1422, 377, -757, 1574, +579, 1860, 1718, 1351, 1722, 112, 851, -875, +-581, -1262, -1546, -1201, -1473, -482, -699, 226, +732, 333, 1577, 479, 1416, 332, 660, 421, +-327, 747, -930, 426, -840, -119, -621, -1052, +-93, -1783, 445, -1467, 758, -255, 906, 1223, +592, 2534, 247, 2280, -119, 795, -517, -1235, +-780, -3031, -660, -3026, -116, -1416, 216, 1108, +686, 3080, 1016, 3283, 953, 1502, 705, -789, +-13, -2673, -774, -2951, -1341, -1623, -1403, 304, +-844, 1944, 370, 2187, 1903, 1290, 2770, -262, +2103, -1212, 127, -945, -2120, -240, -3332, 207, +-2634, 127, -406, -569, 2304, -943, 3817, -630, +3056, 588, 590, 1949, -2085, 2285, -3290, 1261, +-2459, -1126, -323, -3213, 1828, -3373, 2714, -1764, +1890, 1037, 88, 3501, -1443, 3898, -1718, 2158, +-702, -639, 813, -3051, 1436, -3793, 1010, -2286, +-238, -31, -1479, 1820, -1490, 2547, -245, 2005, +1608, 779, 2481, -217, 1896, -845, 13, -1321, +-2332, -1593, -3224, -1557, -2204, -958, 326, 414, +3343, 2038, 4238, 2666, 2561, 2130, -673, 377, +-3717, -1689, -4288, -2999, -2288, -2951, 1153, -1334, +3988, 984, 4225, 2831, 1971, 2996, -1428, 1527, +-3484, -414, -3158, -2123, -1196, -2248, 1424, -1352, +2913, -90, 2700, 1069, 891, 1205, -1340, 838, +-2332, 41, -1718, -514, -66, -443, 1431, -22, +1726, 484, 1147, 436, 187, -305, -909, -831, +-1300, -1119, -883, -612, -55, 375, 725, 985, +1045, 1241, 1118, 967, 856, 353, 32, -401, +-744, -1108, -1436, -1588, -1552, -1489, -526, -874, +665, 508, 1948, 1922, 2484, 2668, 1702, 2166, +7, 300, -2019, -1920, -3089, -3575, -2691, -3306, +-758, -1319, 1884, 1506, 3982, 3849, 4295, 3995, +1989, 1895, -1566, -1109, -4480, -3631, -5038, -3973, +-2633, -2007, 1166, 643, 4671, 2709, 5647, 3073, +3532, 1789, -494, -114, -4219, -1532, -5442, -2115, +-3550, -1733, 174, -580, 3486, 672, 4781, 1505, +3625, 1639, 648, 938, -2401, -239, -3647, -1328, +-2960, -1799, -891, -1457, 1252, -142, 2429, 1584, +2571, 2501, 1620, 2031, 79, 54, -990, -2262, +-1935, -3436, -1946, -2600, -1064, -109, -44, 2793, +1552, 4032, 2507, 2950, 2349, 240, 1120, -2711, +-937, -3935, -2592, -3164, -3058, -893, -1821, 1600, +556, 3050, 2679, 3059, 3666, 1740, 2682, -178, +370, -1721, -2243, -2486, -3615, -2265, -3048, -1304, +-944, -79, 1783, 1225, 3392, 2131, 3304, 2255, +1612, 1582, -825, 276, -2476, -1317, -2816, -2421, +-1718, -2580, 160, -1722, 1499, -68, 2266, 1661, +1856, 2687, 757, 2635, -360, 1347, -1380, -607, +-1600, -2199, -1028, -2796, -76, -2129, 845, -564, +1375, 1189, 1342, 2331, 779, 2358, -225, 1196, +-1208, -517, -1581, -2008, -939, -2272, 469, -1173, +1602, 542, 1952, 1989, 1232, 1996, -359, 549, +-1787, -1367, -2283, -2496, -1307, -1977, 414, 73, +1992, 2236, 2676, 3183, 1843, 2330, 156, -125, +-1495, -2740, -2448, -3965, -2096, -3186, -749, -392, +726, 2571, 1908, 4165, 2369, 3602, 1689, 1021, +557, -1722, -710, -3346, -1713, -3171, -1888, -1561, +-1599, 251, -690, 1341, 765, 1701, 1836, 1544, +2527, 1405, 2215, 1028, 794, 193, -755, -1145, +-2518, -2517, -3245, -3080, -2239, -2167, -182, 170, +2206, 2689, 3796, 4185, 3513, 3622, 1582, 993, +-1333, -2306, -3618, -4410, -4030, -4369, -2336, -1831, +858, 1542, 3359, 3817, 3963, 3989, 2682, 1990, +26, -729, -2469, -2633, -3464, -3023, -2562, -1864, +-228, -109, 1907, 1238, 2906, 1860, 2241, 1474, +598, 660, -885, -197, -1941, -765, -1804, -1031, +-720, -1042, 298, -670, 1326, -119, 1437, 470, +831, 980, 346, 1076, -290, 772, -571, 258, +-587, -504, -558, -1237, -407, -1476, -158, -1168, +174, -309, 751, 954, 1096, 1892, 1107, 2000, +632, 1130, -227, -401, -1069, -1950, -1531, -2483, +-1222, -1827, -433, -293, 755, 1333, 1652, 2135, +1848, 1965, 1347, 1023, 141, -287, -1036, -1280, +-1725, -1696, -1651, -1444, -762, -660, 284, 120, +1163, 785, 1593, 1013, 1344, 1103, 624, 913, +-42, 405, -547, -98, -1058, -910, -1253, -1586, +-948, -1514, -323, -913, 719, 161, 1448, 1332, +1530, 1861, 1233, 1635, 233, 931, -754, -369, +-1547, -1659, -1559, -2207, -688, -1954, 324, -493, +1200, 1124, 1295, 2059, 928, 1976, 359, 828, +-196, -401, -539, -1117, -576, -1222, -469, -857, +-428, -420, -274, -248, -47, -7, 496, 516, +1119, 1125, 1421, 1505, 957, 1127, -218, -158, +-1461, -1685, -2029, -2516, -1509, -1986, -4, -118, +1748, 2000, 2600, 3055, 2088, 2227, 545, 79, +-1411, -2025, -2697, -2987, -2506, -2197, -988, -170, +1260, 1647, 2755, 2419, 2769, 1845, 1465, 195, +-547, -1090, -2001, -1554, -2518, -1114, -1744, -116, +-160, 353, 1265, 247, 2078, -98, 1555, -175, +834, 362, 88, 1053, -629, 1306, -955, 595, +-1264, -771, -1023, -1996, -400, -2174, 216, -1089, +1012, 554, 1549, 1990, 1527, 2294, 914, 1441, +-348, 67, -1329, -1238, -1636, -1724, -1190, -1445, +-290, -750, 561, 129, 1089, 642, 1227, 847, +863, 792, 181, 710, -98, 514, -287, 101, +-366, -437, -329, -1004, -646, -1116, -695, -772, +-488, -158, -9, 455, 749, 643, 1414, 616, +1676, 582, 1280, 587, 106, 593, -1281, 145, +-2178, -713, -2335, -1501, -1218, -1762, 434, -1119, +2078, 317, 3024, 1479, 2351, 2037, 721, 1580, +-1212, 374, -2533, -669, -2366, -1209, -1205, -1179, +281, -848, 1413, -527, 1472, -445, 998, -141, +429, 487, -18, 1357, 108, 1969, 98, 1759, +2, 518, -511, -1269, -1291, -2600, -1529, -2824, +-1042, -1713, 335, 84, 1870, 1706, 2716, 2638, +2191, 2489, 557, 1565, -1256, 236, -2364, -1305, +-2463, -2458, -1602, -2895, -31, -2372, 1218, -626, +2055, 1481, 2225, 3131, 1403, 3583, 480, 2192, +-788, -39, -1852, -2251, -2040, -3468, -1499, -2902, +-110, -1177, 1143, 793, 1633, 2122, 1470, 2305, +504, 1610, -185, 568, -391, -358, -289, -994, +107, -1341, -66, -1343, -578, -1011, -1129, -270, +-1128, 701, -281, 1356, 1116, 1339, 2048, 704, +2008, -197, 1017, -895, -584, -870, -1495, -337, +-1778, 255, -1411, 467, -436, 7, 141, -650, +554, -1021, 1085, -438, 1449, 729, 1718, 1679, +1417, 1746, 99, 646, -1576, -856, -2751, -2003, +-2799, -2140, -1469, -1158, 711, 276, 2648, 1561, +3305, 2009, 2531, 1475, 818, 403, -1145, -721, +-2435, -1260, -2575, -1319, -2022, -858, -703, -254, +859, 105, 1885, 600, 2537, 993, 2038, 987, +771, 762, -597, 106, -1822, -738, -2062, -1124, +-1395, -1104, -469, -639, 514, 61, 1044, 589, +1078, 950, 1187, 939, 915, 665, 487, 55, +-183, -653, -962, -1047, -1453, -1077, -1495, -487, +-720, 248, 385, 877, 1441, 1042, 1844, 659, +1068, 49, -89, -566, -832, -870, -969, -696, +-404, -221, 197, 222, 210, 529, -53, 541, +-390, 384, -537, 177, -40, -106, 615, -418, +1180, -700, 1145, -815, 424, -426, -486, 381, +-1035, 1263, -1242, 1590, -910, 872, -209, -565, +270, -1914, 886, -2186, 1129, -1059, 1054, 781, +889, 2125, 232, 2253, -711, 964, -1403, -798, +-1766, -1800, -1288, -1785, 14, -782, 1231, 525, +1993, 1081, 1867, 993, 802, 495, -419, -159, +-1314, -305, -1587, -292, -1236, -231, -501, -192, +370, -176, 1072, -91, 1269, 90, 887, 267, +287, 238, -250, 7, -551, -164, -627, -143, +-468, 55, -243, 324, -92, 231, 116, -21, +171, -371, 265, -535, 519, -295, 546, 46, +381, 295, 79, 377, -423, 217, -778, 117, +-754, 78, -380, 172, 264, 95, 841, -257, +834, -688, 217, -987, -333, -683, -591, 135, +-135, 1203, 474, 1748, 587, 1370, 275, 61, +-512, -1381, -1090, -2100, -890, -1697, -218, -347, +837, 1094, 1548, 1837, 1266, 1597, 354, 475, +-736, -700, -1379, -1218, -1230, -992, -435, -245, +388, 484, 952, 633, 825, 151, 325, -426, +-185, -731, -276, -361, -1, 570, 160, 1318, +134, 1196, -226, 332, -586, -969, -518, -1745, +-121, -1432, 406, -450, 650, 758, 495, 1440, +191, 1149, -114, 435, -95, -238, -85, -568, +-78, -299, -187, -104, -341, -146, -483, -428, +-280, -777, 180, -682, 510, 75, 916, 1065, +733, 1622, 260, 1383, -90, 391, -615, -888, +-851, -1730, -892, -1711, -759, -1111, -143, 52, +491, 1038, 1245, 1469, 1644, 1493, 1256, 1002, +368, 234, -1031, -718, -2019, -1537, -2038, -1876, +-1141, -1355, 404, -29, 1673, 1349, 2039, 2003, +1477, 1621, 449, 291, -645, -975, -1206, -1410, +-1169, -950, -914, 48, -341, 618, 101, 354, +366, -261, 682, -699, 833, -401, 817, 494, +603, 1294, 122, 1402, -583, 422, -1057, -958, +-1149, -1887, -781, -1637, -121, -380, 521, 1020, +980, 1725, 1124, 1267, 862, 47, 299, -881, +-264, -1056, -744, -355, -964, 527, -956, 722, +-568, 185, 50, -719, 702, -1038, 951, -582, +852, 448, 485, 1317, 64, 1289, -165, 409, +-477, -644, -665, -1318, -729, -1026, -612, -156, +-209, 455, 253, 718, 776, 313, 1175, -132, +1027, -87, 506, 149, -510, 522, -1276, 427, +-1290, -370, -810, -1075, 113, -1163, 937, -393, +1065, 846, 582, 1626, -122, 1318, -529, 141, +-371, -1169, 143, -1724, 527, -1205, 333, 78, +-229, 1302, -762, 1635, -937, 1023, -609, -96, +322, -1178, 1070, -1495, 1235, -884, 748, -78, +-180, 722, -692, 1056, -746, 827, -404, 535, +-56, 141, -121, -367, -304, -917, -382, -1179, +-39, -977, 694, -211, 1408, 851, 1589, 1519, +771, 1439, -806, 565, -2143, -553, -2348, -1226, +-1523, -1291, 205, -703, 1721, 19, 2346, 447, +2141, 694, 768, 655, -615, 575, -1410, 324, +-1885, -76, -1479, -505, -748, -831, -86, -734, +979, -328, 1541, 278, 1618, 716, 1276, 760, +264, 419, -766, -125, -1567, -537, -1657, -563, +-1112, -200, -304, 231, 634, 424, 1248, 237, +1219, -169, 883, -404, 395, -339, -166, -13, +-303, 315, -542, 499, -988, 347, -1109, -59, +-945, -337, -345, -484, 747, -316, 1611, 172, +1965, 457, 1549, 456, 181, 129, -1324, -578, +-2311, -802, -2278, -489, -1086, 265, 454, 1103, +1757, 1251, 2292, 684, 1671, -405, 338, -1485, +-1019, -1762, -1569, -1118, -1297, 102, -434, 1547, +273, 2113, 413, 1682, 360, 425, 89, -1146, +-60, -2087, 314, -2073, 756, -980, 842, 572, +279, 1740, -733, 1983, -1510, 1162, -1457, -214, +-505, -1227, 575, -1366, 1442, -689, 1684, 294, +794, 740, -348, 430, -1157, -143, -1381, -702, +-589, -555, 299, 243, 818, 966, 727, 1272, +209, 731, -338, -504, -663, -1430, -396, -1567, +136, -873, 510, 351, 599, 1223, 391, 1327, +87, 672, -274, -86, -699, -538, -888, -447, +-666, -95, -102, -3, 677, -273, 1226, -583, +1232, -539, 767, -165, -279, 569, -1304, 1050, +-1569, 988, -1132, 568, -60, -128, 951, -700, +1149, -939, 946, -1042, 300, -813, -314, -204, +-290, 492, -201, 1293, -77, 1541, -185, 1064, +-688, 204, -799, -978, -421, -1678, 381, -1533, +1186, -685, 1297, 433, 795, 1175, 65, 1216, +-688, 640, -1095, 61, -1053, -195, -754, -211, +-263, -165, 243, -339, 738, -670, 1076, -864, +1180, -539, 1031, 331, 251, 1121, -925, 1437, +-1784, 1026, -1930, -27, -1157, -929, 202, -1363, +1419, -1151, 2054, -373, 1774, 392, 731, 839, +-465, 929, -1331, 690, -1592, 135, -1424, -342, +-713, -632, 130, -561, 942, -265, 1474, 75, +1320, 263, 860, 105, 38, 7, -739, 24, +-1172, 82, -1294, 296, -792, 334, -193, 66, +375, -215, 884, -593, 1063, -615, 1005, -170, +466, 315, -237, 718, -684, 675, -903, 183, +-879, -417, -577, -719, -170, -465, 332, -40, +704, 387, 824, 474, 868, 325, 657, 102, +92, -154, -638, -314, -1247, -389, -1340, -316, +-847, -166, 31, 143, 996, 410, 1527, 674, +1358, 680, 528, 264, -547, -385, -1143, -1090, +-1154, -1247, -786, -700, -151, 263, 503, 1232, +787, 1532, 745, 1068, 406, 60, -47, -925, +-238, -1407, -415, -1219, -416, -466, -286, 370, +-40, 916, 333, 1014, 413, 618, 246, 159, +-127, -131, -507, -356, -525, -489, -147, -617, +613, -535, 941, -275, 647, 219, 1, 661, +-807, 828, -1142, 555, -899, 84, -278, -367, +634, -614, 1217, -393, 1125, -195, 538, 15, +-334, 67, -833, -57, -1010, 42, -766, 130, +-157, 455, 487, 625, 813, 374, 541, -74, +66, -800, -95, -1032, -134, -670, -58, 57, +-73, 791, -171, 1030, -103, 588, -245, -105, +-348, -612, -73, -545, 277, -3, 588, 393, +569, 329, 57, -280, -275, -852, -444, -760, +-384, 85, -59, 1071, 237, 1507, 264, 976, +-38, -324, -436, -1467, -417, -1692, -28, -948, +553, 385, 945, 1398, 744, 1449, 81, 675, +-765, -395, -1300, -1018, -1179, -831, -372, -139, +592, 537, 1178, 593, 1179, 44, 694, -532, +97, -716, -503, -199, -881, 667, -933, 1159, +-811, 887, -372, -82, 172, -1147, 738, -1422, +1253, -823, 1203, 302, 551, 1307, -318, 1308, +-1275, 512, -1607, -474, -1063, -1057, -65, -839, +931, -104, 1405, 537, 1026, 747, 220, 387, +-450, -205, -778, -498, -612, -514, -237, -133, +51, 264, 226, 462, 137, 494, 41, 287, +72, -55, -8, -411, 35, -652, 74, -652, +117, -213, 175, 400, -5, 869, -154, 962, +-207, 530, -343, -250, -315, -983, -190, -1174, +213, -679, 506, 181, 519, 942, 398, 1136, +18, 668, -291, -95, -467, -680, -536, -794, +-376, -482, -66, -38, 145, 299, 352, 392, +497, 330, 512, 233, 383, 89, 0, -62, +-587, -175, -838, -336, -670, -342, -209, -124, +424, 163, 734, 455, 723, 474, 326, 227, +-233, -256, -520, -590, -593, -460, -323, -117, +139, 387, 428, 711, 581, 464, 299, 9, +-310, -413, -649, -683, -716, -481, -286, -106, +505, 270, 954, 715, 984, 726, 472, 421, +-488, -85, -1132, -718, -1267, -907, -830, -658, +114, -98, 1003, 603, 1495, 1004, 1266, 844, +331, 262, -688, -431, -1341, -860, -1398, -749, +-690, -269, 233, 229, 877, 573, 1142, 552, +869, 311, 221, -13, -399, -296, -768, -309, +-814, -272, -402, -113, 199, 151, 589, 255, +621, 380, 175, 270, -336, -91, -564, -380, +-437, -642, 125, -467, 620, 161, 823, 745, +544, 1073, -218, 710, -862, -228, -1146, -1018, +-836, -1301, -8, -836, 858, 129, 1390, 1001, +1155, 1363, 345, 1048, -585, 193, -1241, -725, +-1085, -1252, -522, -1085, 148, -376, 710, 463, +700, 1052, 401, 912, 158, 316, 11, -317, +36, -651, 8, -414, -196, 26, -494, 324, +-631, 270, -418, -46, -40, -308, 510, -291, +839, -4, 778, 246, 393, 324, -129, 190, +-510, 43, -630, 109, -537, 206, -426, 76, +-163, -305, 143, -790, 491, -923, 870, -373, +846, 602, 461, 1473, -167, 1657, -936, 844, +-1152, -576, -740, -1724, -60, -2003, 670, -1142, +886, 288, 523, 1443, 153, 1804, -56, 1193, +-64, 262, 103, -531, -37, -913, -471, -892, +-743, -860, -694, -669, -154, -151, 677, 610, +1157, 1432, 1121, 1693, 527, 996, -448, -347, +-1156, -1674, -1182, -2055, -619, -1195, 223, 350, +803, 1640, 842, 1827, 466, 891, 11, -471, +-189, -1322, -233, -1200, -103, -276, -97, 722, +-223, 1080, -186, 666, -180, -182, 59, -866, +364, -880, 370, -299, 323, 357, 116, 825, +-116, 782, -189, 326, -245, -98, -208, -431, +-149, -547, -103, -482, 100, -390, 297, -96, +341, 352, 349, 742, 163, 866, -147, 529, +-357, -65, -496, -677, -275, -925, 129, -638, +430, -169, 489, 347, 194, 692, -155, 645, +-358, 409, -312, 81, 7, -260, 306, -423, +394, -376, 222, -226, -210, -33, -451, 117, +-383, 192, -60, 222, 298, 246, 490, 236, +475, 151, 121, 39, -317, -186, -531, -399, +-416, -447, 4, -299, 363, 83, 445, 507, +223, 727, -80, 626, -286, 164, -293, -456, +-55, -876, 164, -849, 299, -305, 204, 479, +12, 1037, -108, 1039, -232, 475, -223, -349, +-149, -1006, -74, -1065, 170, -563, 348, 203, +433, 851, 381, 1080, -14, 821, -449, 182, +-755, -481, -713, -986, -160, -987, 517, -537, +1004, 157, 930, 848, 288, 1073, -452, 856, +-1007, 267, -967, -486, -380, -924, 334, -914, +832, -494, 829, 151, 383, 653, -215, 852, +-614, 632, -597, 170, -258, -229, 105, -449, +286, -462, 275, -307, 187, -119, 88, 34, +-43, 268, -182, 478, -285, 478, -274, 330, +-97, -74, 149, -466, 385, -592, 408, -389, +170, 89, -170, 514, -508, 613, -597, 309, +-271, -107, 142, -387, 411, -385, 477, -156, +330, 134, 95, 281, -165, 257, -348, 197, +-488, 149, -515, 23, -280, -160, 40, -358, +422, -501, 834, -284, 789, 251, 244, 771, +-545, 967, -1216, 589, -1221, -279, -444, -1093, +607, -1251, 1334, -608, 1216, 495, 283, 1321, +-841, 1303, -1418, 453, -1059, -662, -30, -1189, +967, -875, 1236, 53, 631, 875, -371, 928, +-1159, 288, -1243, -520, -516, -836, 447, -436, +1142, 317, 1138, 836, 406, 789, -457, 190, +-1051, -515, -1169, -776, -708, -567, -62, -26, +570, 456, 990, 564, 910, 431, 461, 133, +-180, -120, -869, -139, -1242, -125, -1069, -151, +-375, -171, 525, -230, 1159, -71, 1180, 262, +486, 521, -455, 574, -1137, 294, -1152, -183, +-547, -587, 139, -692, 671, -393, 716, 174, +284, 690, -210, 817, -574, 454, -547, -108, +-195, -579, 168, -708, 247, -355, 98, 171, +-200, 606, -323, 675, -205, 299, -97, -225, +94, -557, 85, -465, -111, -55, -179, 453, +-181, 607, -46, 341, 112, -183, 17, -549, +-155, -465, -248, -36, -313, 496, -255, 652, +-82, 356, 99, -162, 235, -542, 144, -532, +-105, -119, -333, 394, -334, 609, -153, 427, +-60, 12, -82, -375, -163, -437, -249, -212, +-162, 146, 54, 370, 248, 304, 304, 102, +46, -65, -335, -70, -629, -20, -685, -14, +-409, -72, 3, -169, 354, -72, 495, 175, +325, 397, -9, 478, -355, 188, -543, -271, +-567, -619, -490, -538, -248, -54, 71, 488, +353, 734, 392, 486, 147, 44, -141, -387, +-425, -504, -515, -268, -377, 51, -189, 305, +-4, 263, 3, 34, -135, -103, -161, -4, +-19, 253, 151, 420, 194, 275, -91, -220, +-490, -717, -636, -726, -502, -188, -161, 577, +206, 1090, 332, 807, 174, 78, -121, -572, +-391, -859, -406, -482, -179, 150, -22, 468, +-68, 392, -346, 21, -534, -264, -337, -77, +185, 356, 642, 693, 552, 465, -73, -230, +-913, -879, -1336, -1140, -962, -519, 2, 522, +936, 1318, 1201, 1395, 601, 520, -476, -572, +-1306, -1230, -1368, -1073, -699, -270, 191, 573, +723, 919, 689, 602, 262, 12, -271, -360, +-567, -282, -533, 84, -423, 323, -347, 220, +-317, -150, -262, -473, -27, -397, 338, 11, +529, 492, 314, 678, -184, 436, -771, -37, +-1103, -421, -858, -464, -225, -257, 390, 20, +737, 255, 551, 378, 39, 331, -482, 205, +-841, -9, -801, -286, -460, -399, 3, -370, +332, 0, 365, 546, 58, 812, -310, 639, +-492, -83, -543, -840, -297, -1127, 22, -651, +238, 395, 232, 1263, -145, 1409, -520, 598, +-673, -646, -540, -1365, -140, -1106, 233, -95, +351, 891, 245, 1090, -95, 497, -445, -367, +-543, -756, -477, -346, -313, 451, -179, 939, +-100, 573, -37, -398, 81, -1192, 168, -1191, +136, -230, -16, 1059, -311, 1748, -625, 1350, +-838, 82, -629, -1253, -126, -1734, 361, -1101, +667, 143, 440, 1170, -107, 1349, -566, 759, +-800, -108, -637, -631, -248, -576, 40, -210, +140, 71, 52, 79, -157, -66, -213, -56, +-124, 186, -12, 427, 114, 551, -76, 299, +-449, -202, -650, -573, -702, -643, -339, -285, +224, 279, 567, 659, 626, 673, 157, 358, +-594, -141, -1028, -517, -895, -563, -346, -281, +279, 201, 578, 559, 437, 544, -48, 211, +-576, -135, -782, -392, -536, -379, 66, -80, +460, 245, 289, 416, -233, 272, -656, -23, +-621, -254, -230, -235, 265, 70, 488, 335, +214, 350, -415, 111, -952, -324, -875, -533, +-135, -322, 689, 168, 964, 740, 518, 806, +-481, 366, -1276, -259, -1404, -843, -851, -858, +268, -360, 1192, 374, 1296, 938, 643, 929, +-427, 487, -1255, -171, -1396, -689, -996, -829, +-273, -558, 445, 14, 841, 550, 866, 802, +491, 695, -83, 242, -642, -272, -1020, -592, +-997, -611, -653, -279, -107, 188, 489, 504, +780, 486, 626, 223, 182, -18, -360, -188, +-664, -148, -686, 12, -504, 39, -258, 46, +-57, -43, 115, -169, 201, -21, 218, 215, +170, 378, 56, 377, -199, 79, -449, -256, +-551, -480, -449, -347, -126, 75, 144, 449, +245, 548, 168, 230, -97, -193, -297, -392, +-288, -278, -134, 58, 66, 393, 136, 408, +23, 156, -174, -194, -452, -427, -562, -289, +-404, 88, 2, 407, 472, 457, 568, 222, +351, -151, -58, -367, -420, -262, -627, 83, +-718, 424, -557, 338, -180, -82, 248, -422, +610, -440, 692, 9, 452, 596, 16, 774, +-574, 476, -973, -209, -958, -827, -585, -821, +78, -307, 654, 481, 917, 914, 721, 666, +91, 103, -588, -422, -940, -536, -759, -138, +-281, 293, 137, 388, 308, 85, 275, -457, +141, -612, -30, -154, -29, 579, -4, 1103, +-85, 916, -202, 46, -456, -899, -467, -1325, +-195, -917, 90, 80, 404, 1021, 466, 1309, +227, 854, -121, 47, -513, -649, -657, -909, +-435, -630, 25, -107, 391, 336, 498, 542, +309, 474, -195, 294, -621, 64, -657, -142, +-293, -301, 320, -281, 681, -95, 537, 121, +-16, 300, -674, 230, -886, -7, -610, -136, +103, -175, 822, 2, 911, 332, 367, 372, +-498, 145, -1069, -235, -926, -501, -237, -304, +565, 89, 976, 511, 723, 613, -27, 206, +-745, -272, -984, -584, -610, -408, 42, 192, +542, 666, 620, 650, 309, 114, -51, -557, +-307, -811, -334, -444, -226, 314, -179, 947, +-171, 932, -148, 310, -64, -532, 172, -1017, +451, -761, 495, -72, 261, 644, -247, 1015, +-756, 701, -891, 18, -566, -571, 81, -783, +696, -444, 946, 114, 654, 537, -46, 588, +-715, 280, -922, -101, -569, -337, 48, -275, +450, -26, 498, 212, 204, 231, -238, 63, +-431, -93, -297, -124, 111, -3, 560, 173, +491, 279, -71, 188, -641, -66, -931, -322, +-622, -368, 122, -93, 742, 295, 1027, 568, +682, 510, -171, 60, -810, -466, -1007, -671, +-632, -428, 35, 156, 498, 741, 680, 802, +407, 341, -89, -306, -407, -775, -482, -700, +-156, -116, 238, 507, 325, 828, 158, 570, +-241, -39, -501, -468, -483, -551, -193, -181, +349, 230, 661, 351, 564, 203, 111, -124, +-415, -234, -645, 44, -545, 370, -248, 454, +60, 171, 297, -372, 333, -678, 187, -480, +71, 43, 21, 641, 40, 850, -36, 537, +-331, -104, -581, -682, -566, -740, -177, -338, +392, 282, 762, 678, 684, 609, 184, 218, +-381, -257, -785, -544, -707, -447, -240, -52, +184, 382, 511, 593, 403, 481, 14, 86, +-230, -388, -327, -642, -112, -539, 195, -52, +229, 504, 11, 831, -317, 678, -481, 42, +-300, -548, 67, -786, 407, -516, 485, 171, +248, 665, -179, 632, -527, 173, -576, -412, +-287, -615, 167, -210, 473, 423, 500, 829, +120, 650, -369, -105, -637, -912, -572, -1136, +-114, -570, 401, 414, 647, 1251, 518, 1333, +74, 613, -477, -413, -766, -1108, -663, -1127, +-303, -561, 233, 232, 546, 723, 612, 793, +453, 583, -13, 238, -407, -100, -615, -359, +-647, -540, -394, -546, -15, -278, 298, 122, +568, 582, 550, 768, 209, 502, -193, -32, +-543, -574, -619, -692, -389, -321, -79, 233, +258, 619, 402, 579, 195, 122, -59, -339, +-246, -542, -241, -369, -7, 103, 88, 417, +57, 449, -87, 265, -258, -34, -287, -156, +-166, -121, 55, -92, 180, -107, 161, -208, +39, -246, -67, -4, -119, 388, -101, 726, +-80, 705, -132, 170, -180, -512, -259, -980, +-229, -865, 16, -196, 283, 588, 409, 1013, +243, 796, -95, 110, -388, -474, -469, -608, +-332, -272, -150, 220, 15, 352, 105, 85, +99, -347, 130, -508, 185, -158, 214, 460, +94, 928, -258, 817, -598, 99, -715, -712, +-450, -1115, 55, -837, 554, -20, 767, 771, +526, 1047, -13, 677, -588, -22, -831, -528, +-644, -583, -205, -244, 270, 131, 482, 252, +368, 83, 78, -88, -203, -65, -334, 111, +-265, 362, -109, 289, -7, -22, 28, -329, +-55, -444, -150, -149, -147, 274, -88, 498, +64, 372, 159, -73, 107, -471, -9, -501, +-253, -139, -383, 387, -309, 657, -89, 487, +206, 7, 269, -475, 124, -595, -130, -312, +-340, 121, -337, 415, -143, 425, 119, 144, +226, -129, 131, -158, -160, -28, -403, 142, +-304, 168, -46, -26, 188, -264, 264, -319, +51, -137, -237, 182, -384, 413, -352, 414, +-68, 178, 241, -93, 311, -212, 130, -216, +-185, -105, -408, -57, -372, -108, -230, -88, +-41, 49, 170, 292, 251, 480, 243, 464, +44, 159, -187, -287, -324, -623, -447, -670, +-381, -350, -177, 174, 91, 619, 391, 699, +467, 461, 277, 59, -85, -280, -473, -389, +-679, -358, -577, -247, -206, -139, 212, -5, +454, 224, 470, 435, 248, 536, -83, 400, +-396, -30, -552, -446, -470, -628, -238, -489, +78, -57, 272, 340, 312, 507, 174, 436, +-72, 174, -230, -101, -273, -201, -191, -179, +-129, -162, -138, -87, -88, -50, -17, -7, +52, 174, 106, 263, 86, 250, 9, 134, +-104, -94, -233, -246, -302, -245, -265, -130, +-106, 47, 86, 198, 231, 192, 245, 121, +42, 70, -231, -9, -417, -43, -387, -75, +-167, -132, 85, -115, 274, -36, 296, 148, +126, 285, -191, 210, -465, 29, -461, -195, +-234, -309, 97, -131, 319, 129, 270, 237, +83, 230, -153, 41, -287, -161, -253, -146, +-159, -29, -77, 92, -142, 112, -159, -10, +32, -119, 281, -39, 428, 145, 225, 280, +-217, 214, -660, -142, -847, -458, -501, -490, +155, -144, 775, 448, 945, 829, 413, 700, +-400, 92, -959, -682, -953, -1089, -390, -824, +316, -42, 712, 810, 569, 1214, 70, 892, +-398, 111, -478, -630, -218, -992, 41, -796, +91, -309, -118, 195, -301, 571, -230, 699, +80, 620, 448, 377, 506, -38, 105, -466, +-505, -745, -858, -776, -689, -417, -90, 151, +572, 677, 836, 943, 546, 769, -92, 264, +-717, -341, -892, -804, -486, -871, 92, -531, +513, -19, 561, 479, 215, 755, -155, 637, +-384, 319, -448, -49, -250, -397, 12, -513, +137, -414, 200, -243, 128, 58, -3, 298, +-147, 390, -306, 363, -303, 111, -120, -90, +148, -170, 325, -185, 282, -33, 27, 62, +-310, -12, -563, -86, -570, -202, -189, -240, +384, 23, 725, 423, 604, 705, 111, 669, +-485, 130, -853, -687, -794, -1235, -344, -1130, +261, -309, 726, 841, 838, 1609, 476, 1499, +-147, 569, -713, -726, -958, -1627, -709, -1644, +-98, -825, 485, 413, 753, 1363, 649, 1561, +221, 1044, -288, 75, -689, -791, -735, -1154, +-388, -1091, 56, -609, 406, 71, 457, 630, +309, 999, 95, 1073, -164, 675, -327, -26, +-408, -716, -329, -1242, -153, -1168, 47, -526, +278, 321, 361, 1105, 313, 1376, 89, 1024, +-271, 222, -466, -714, -477, -1308, -287, -1293, +52, -724, 302, 240, 395, 1071, 362, 1364, +145, 1110, -170, 274, -394, -695, -574, -1250, +-488, -1298, -110, -718, 294, 324, 660, 1123, +629, 1418, 212, 1051, -303, 17, -816, -945, +-854, -1407, -369, -1203, 300, -332, 844, 678, +802, 1366, 216, 1406, -397, 720, -765, -315, +-719, -1240, -261, -1555, 231, -1080, 559, -75, +562, 968, 203, 1567, -161, 1454, -342, 603, +-445, -479, -330, -1359, -103, -1690, 72, -1145, +275, -79, 343, 996, 219, 1674, 41, 1529, +-194, 653, -395, -404, -325, -1281, -87, -1609, +117, -1158, 213, -240, 65, 763, -60, 1438, +-51, 1420, -23, 768, 147, -164, 209, -990, +50, -1337, -261, -1078, -552, -393, -435, 459, +-3, 1114, 417, 1232, 561, 814, 348, 14, +42, -829, -259, -1213, -423, -1003, -384, -289, +-233, 592, -2, 1091, 120, 1040, 162, 477, +254, -352, 334, -888, 264, -983, -23, -604, +-381, 97, -578, 671, -462, 942, -133, 741, +298, 213, 574, -424, 466, -890, 120, -873, +-280, -468, -379, 170, -165, 765, -18, 986, +-5, 723, -103, 119, -145, -565, 25, -1012, +211, -906, 355, -336, 325, 395, -11, 969, +-395, 987, -545, 447, -344, -275, 131, -837, +471, -935, 418, -456, 142, 208, -209, 737, +-454, 889, -364, 476, 1, -173, 342, -708, +438, -873, 244, -497, -136, 175, -371, 720, +-321, 924, -230, 610, -63, -84, 114, -651, +226, -943, 411, -740, 447, -128, 211, 447, +-193, 829, -697, 851, -876, 518, -506, -2, +194, -501, 897, -856, 1113, -925, 657, -592, +-199, 5, -972, 691, -1170, 1221, -631, 1225, +310, 635, 999, -311, 1002, -1284, 337, -1673, +-568, -1251, -993, -185, -672, 1096, 90, 1870, +827, 1720, 975, 727, 380, -683, -410, -1785, +-916, -1923, -937, -1142, -361, 207, 404, 1448, +859, 1902, 896, 1389, 457, 274, -91, -930, +-417, -1650, -660, -1453, -695, -663, -527, 384, +-197, 1251, 361, 1451, 836, 994, 1002, 107, +831, -835, 244, -1339, -682, -1201, -1356, -505, +-1304, 448, -621, 1229, 440, 1408, 1171, 831, +1157, -174, 743, -1195, 135, -1601, -423, -1002, +-591, 140, -584, 1246, -578, 1707, -488, 1052, +-354, -205, 116, -1286, 885, -1656, 1371, -994, +1278, 214, 424, 1211, -847, 1534, -1769, 942, +-1843, -95, -916, -905, 610, -1243, 1838, -931, +1962, -185, 1007, 415, -409, 798, -1438, 937, +-1448, 649, -716, 197, 184, -271, 837, -822, +861, -1071, 431, -815, -49, -236, -417, 641, +-484, 1311, -231, 1270, 69, 648, 321, -337, +467, -1200, 360, -1402, 35, -909, -410, -40, +-767, 810, -771, 1243, -290, 1042, 567, 468, +1304, -255, 1379, -905, 694, -1092, -512, -849, +-1634, -234, -1926, 555, -1133, 1052, 391, 1082, +1771, 642, 2147, -176, 1382, -939, -80, -1196, +-1411, -903, -1917, -123, -1495, 771, -349, 1195, +931, 1042, 1588, 405, 1386, -481, 664, -1039, +-233, -1047, -963, -600, -1205, 134, -1050, 683, +-433, 880, 487, 735, 1107, 333, 1352, -145, +1106, -565, 164, -764, -945, -751, -1744, -414, +-1795, 184, -732, 696, 836, 996, 2065, 837, +2383, 208, 1383, -430, -464, -916, -2127, -1002, +-2776, -570, -1935, 96, -80, 713, 1739, 1005, +2746, 762, 2468, 122, 988, -452, -901, -753, +-2362, -631, -2729, -166, -1786, 204, -119, 376, +1501, 349, 2533, 148, 2528, 5, 1387, -12, +-431, -77, -2111, -82, -2873, -61, -2256, -143, +-553, -84, 1380, 8, 2743, 64, 2826, 167, +1475, 177, -608, 69, -2345, -56, -2838, -154, +-1889, -162, -113, -57, 1596, 81, 2528, 172, +2196, 175, 781, 44, -872, -147, -2037, -189, +-2138, -171, -1174, -75, 165, 162, 1372, 196, +2030, 168, 1727, 161, 561, -7, -881, -81, +-1935, -104, -2039, -235, -1090, -296, 367, -192, +1699, -5, 2340, 299, 1808, 618, 283, 592, +-1492, 265, -2617, -256, -2369, -840, -813, -986, +1192, -618, 2630, 109, 2843, 919, 1589, 1243, +-578, 886, -2495, 132, -3235, -745, -2278, -1236, +-31, -987, 2201, -336, 3360, 391, 2868, 886, +822, 888, -1601, 542, -3220, 118, -3272, -323, +-1549, -650, 896, -729, 2843, -583, 3424, -179, +2223, 391, -15, 808, -2158, 899, -3251, 561, +-2674, -134, -833, -770, 1280, -1024, 2743, -769, +2918, -66, 1751, 705, -178, 1042, -1970, 830, +-2876, 180, -2446, -605, -897, -979, 1036, -792, +2590, -239, 3016, 473, 1987, 888, -67, 781, +-2173, 341, -3235, -310, -2666, -824, -756, -861, +1551, -470, 3157, 184, 3186, 807, 1528, 986, +-921, 629, -2806, -61, -3218, -791, -1998, -1082, +171, -753, 2166, -73, 3092, 662, 2505, 1078, +701, 897, -1435, 323, -2802, -374, -2791, -960, +-1458, -1052, 567, -672, 2367, 33, 3111, 764, +2301, 1148, 312, 1004, -1892, 355, -3190, -431, +-2832, -1087, -1065, -1210, 1249, -749, 2967, -1, +3218, 839, 1856, 1327, -442, 1145, -2435, 466, +-3173, -470, -2348, -1278, -499, -1422, 1467, -932, +2801, 1, 2875, 1061, 1655, 1651, -295, 1488, +-2180, 597, -3092, -793, -2622, -1896, -988, -2053, +1337, -1158, 3227, 534, 3552, 2103, 2142, 2560, +-518, 1654, -3084, -219, -3973, -2116, -2853, -2862, +-237, -2051, 2640, -153, 4076, 1899, 3353, 2893, +883, 2289, -2015, 575, -3688, -1410, -3355, -2581, +-1326, -2320, 1265, -1001, 3042, 737, 3207, 2039, +1802, 2230, -388, 1373, -2233, -36, -2864, -1369, +-2136, -2024, -476, -1675, 1406, -613, 2627, 720, +2638, 1781, 1474, 1944, -577, 1229, -2413, -138, +-3038, -1525, -2266, -2150, -195, -1823, 2124, -468, +3428, 1250, 3106, 2330, 1116, 2351, -1568, 1124, +-3469, -818, -3648, -2338, -1977, -2746, 759, -1833, +3126, 151, 4004, 2080, 2973, 2974, 419, 2494, +-2302, 687, -3860, -1487, -3636, -2907, -1646, -2979, +1138, -1552, 3387, 678, 4164, 2500, 2939, 3172, +222, 2289, -2618, 234, -4181, -1792, -3663, -3015, +-1325, -2785, 1663, -1119, 3806, 986, 4070, 2588, +2353, 2968, -535, 1808, -3038, -188, -3860, -1938, +-2798, -2831, -463, -2337, 1997, -658, 3379, 1146, +3185, 2505, 1556, 2764, -782, 1580, -2632, -291, +-3214, -2123, -2302, -3132, -325, -2518, 1812, -553, +3208, 1732, 3164, 3420, 1468, 3349, -1050, 1360, +-3032, -1294, -3530, -3527, -2179, -3963, 354, -2074, +2700, 825, 3788, 3358, 2964, 4238, 477, 2635, +-2197, -298, -3628, -2894, -3204, -4113, -1159, -3002, +1443, -337, 3251, 2149, 3532, 3600, 2110, 3201, +-461, 1117, -2675, -1195, -3463, -2853, -2603, -3263, +-477, -1954, 1824, 131, 3292, 2034, 3281, 3198, +1602, 2711, -894, 911, -2866, -1243, -3403, -3000, +-2251, -3286, 9, -1799, 2245, 514, 3453, 2660, +3023, 3587, 1022, 2486, -1525, 134, -3209, -2248, +-3303, -3638, -1712, -2966, 853, -729, 2951, 1761, +3639, 3519, 2502, 3375, -84, 1369, -2612, -1224, +-3676, -3288, -2843, -3745, -476, -2092, 2176, 598, +3666, 2958, 3356, 4021, 1308, 2909, -1477, 232, +-3359, -2461, -3508, -4130, -1907, -3695, 674, -1243, +2794, 1737, 3603, 3953, 2800, 4269, 589, 2291, +-1855, -781, -3324, -3423, -3327, -4479, -1714, -3165, +808, -261, 2924, 2582, 3787, 4241, 2861, 3740, +434, 1267, -2196, -1598, -3680, -3655, -3363, -3926, +-1343, -2075, 1415, 614, 3368, 2837, 3676, 3737, +2208, 2655, -446, 359, -2704, -1965, -3425, -3391, +-2500, -3090, -305, -1247, 1966, 1123, 3129, 2997, +2869, 3461, 1213, 2072, -1047, -343, -2616, -2676, +-2949, -3789, -1813, -2828, 279, -359, 2188, 2357, +3125, 3968, 2635, 3472, 737, 1084, -1634, -1891, +-3146, -3953, -3109, -3976, -1384, -1876, 1174, 1198, +3072, 3681, 3483, 4268, 2191, 2645, -343, -296, +-2599, -3116, -3462, -4334, -2581, -3345, -299, -695, +2020, 2310, 3169, 4145, 2847, 3924, 1201, 1680, +-953, -1426, -2475, -3818, -2806, -4243, -1783, -2468, +61, 507, 1745, 3258, 2679, 4279, 2438, 3091, +1035, 439, -859, -2444, -2371, -4065, -2753, -3637, +-1784, -1490, 230, 1446, 2177, 3708, 3118, 4071, +2546, 2515, 528, -338, -1804, -3193, -3243, -4361, +-2928, -3421, -1023, -813, 1498, 2431, 3262, 4368, +3317, 4120, 1707, 1916, -786, -1477, -2816, -4098, +-3346, -4520, -2209, -2846, -54, 361, 2114, 3506, +3278, 4616, 2904, 3535, 1214, 717, -1061, -2611, +-2836, -4362, -3209, -3988, -2100, -1766, -6, 1528, +2213, 3906, 3384, 4253, 2968, 2692, 1102, -431, +-1420, -3352, -3089, -4417, -3197, -3406, -1736, -568, +641, 2741, 2646, 4429, 3272, 3827, 2250, 1344, +139, -2069, -1997, -4148, -2930, -3968, -2340, -1987, +-644, 1209, 1416, 3576, 2611, 3890, 2454, 2494, +1192, -254, -768, -2807, -2184, -3656, -2368, -2853, +-1508, -700, 211, 1901, 1849, 3265, 2482, 3042, +1937, 1525, 405, -956, -1394, -2789, -2432, -3168, +-2215, -2264, -897, -11, 950, 2348, 2371, 3361, +2569, 2949, 1561, 827, -306, -2000, -2137, -3607, +-2786, -3573, -2040, -1551, -246, 1620, 1814, 3769, +2942, 3991, 2539, 2165, 956, -1033, -1207, -3582, +-2811, -4170, -2908, -2772, -1612, 179, 570, 2956, +2603, 4005, 3194, 3265, 2208, 836, 240, -2010, +-1986, -3543, -3139, -3469, -2681, -1759, -1043, 890, +1219, 2766, 2955, 3290, 3128, 2344, 1884, 149, +-350, -1842, -2472, -2805, -3262, -2578, -2495, -977, +-482, 963, 1843, 2188, 3251, 2461, 2970, 1414, +1278, -284, -1078, -1552, -2918, -2121, -3149, -1601, +-1879, -212, 321, 943, 2434, 1640, 3184, 1651, +2338, 688, 431, -382, -1764, -1246, -2983, -1728, +-2605, -1173, -1129, -173, 1007, 869, 2725, 1817, +2936, 1739, 1770, 759, -261, -544, -2360, -1875, +-3203, -2271, -2321, -1365, -334, 88, 1989, 1677, +3335, 2536, 2848, 1925, 924, 545, -1490, -1163, +-3245, -2457, -3255, -2380, -1541, -1285, 896, 343, +2967, 1981, 3478, 2568, 2140, 1964, -86, 554, +-2350, -1316, -3472, -2471, -2767, -2363, -832, -1294, +1600, 533, 3251, 2095, 3163, 2505, 1642, 1777, +-625, 131, -2715, -1633, -3382, -2421, -2373, -2022, +-268, -708, 2087, 1118, 3334, 2216, 2802, 2207, +922, 1189, -1366, -622, -2928, -2032, -2986, -2422, +-1465, -1647, 757, 79, 2476, 1813, 2873, 2565, +1692, 2096, -254, 498, -1899, -1467, -2592, -2544, +-1903, -2505, -300, -1155, 1385, 895, 2473, 2332, +2191, 2776, 713, 1793, -1079, -186, -2389, -1994, +-2509, -2915, -1214, -2375, 731, -557, 2427, 1562, +3044, 2974, 1705, 2903, -640, 1200, -2479, -1205, +-3234, -3060, -2112, -3359, 210, -1721, 2230, 928, +3267, 3182, 2571, 3744, 291, 2091, -1919, -796, +-2954, -3289, -2670, -3953, -859, -2364, 1187, 598, +2393, 3204, 2621, 3994, 1356, 2535, -542, -256, +-1826, -2790, -2258, -3858, -1518, -2827, -6, -387, +1197, 2187, 1870, 3623, 1580, 3148, 253, 1135, +-947, -1549, -1562, -3435, -1349, -3451, -234, -1751, +769, 987, 1340, 3183, 1298, 3631, 246, 2145, +-908, -638, -1407, -3000, -1132, -3622, -93, -2249, +854, 409, 1229, 2807, 1104, 3463, 295, 2152, +-711, -424, -1109, -2632, -934, -3112, -344, -1863, +390, 414, 636, 2284, 637, 2665, 528, 1517, +62, -409, -292, -1878, -313, -2093, -348, -1160, +-270, 337, -123, 1398, -145, 1423, 173, 695, +430, -294, 427, -900, 463, -759, 44, -154, +-384, 386, -569, 378, -653, -87, -208, -514, +467, -451, 772, 179, 764, 906, 235, 1112, +-651, 391, -975, -825, -679, -1696, -44, -1519, +871, -107, 1256, 1488, 677, 2259, -234, 1586, +-1099, -342, -1388, -2091, -514, -2594, 566, -1426, +1223, 817, 1374, 2610, 364, 2708, -724, 1017, +-1110, -1358, -1086, -2950, -172, -2587, 924, -538, +1107, 1751, 766, 3003, -136, 2222, -1095, 50, +-886, -1967, -236, -2762, 351, -1693, 1127, 256, +877, 1881, 124, 2335, -397, 1229, -1045, -418, +-744, -1591, -64, -1829, 276, -1048, 599, 271, +656, 1224, 444, 1436, 323, 1126, 131, 171, +-397, -846, -769, -1313, -987, -1417, -949, -714, +49, 389, 1275, 1236, 1927, 1756, 1710, 1257, +318, 82, -1494, -1187, -2418, -2044, -2052, -1716, +-532, -547, 1658, 996, 2820, 2169, 2389, 2124, +563, 919, -1695, -864, -2839, -2200, -2272, -2410, +-374, -1247, 1761, 704, 2960, 2249, 2400, 2621, +464, 1449, -1786, -566, -3059, -2289, -2513, -2723, +-492, -1620, 1871, 305, 3337, 2095, 3027, 2757, +976, 1871, -1708, 51, -3506, -1799, -3370, -2870, +-1196, -2212, 1617, -320, 3435, 1617, 3535, 2884, +1737, 2411, -1064, 426, -3073, -1718, -3247, -2883, +-1730, -2298, 760, -306, 2517, 1811, 2672, 2712, +1767, 1975, -21, 161, -1602, -1695, -2033, -2459, +-1608, -1690, -353, -143, 1000, 1270, 1707, 1950, +1758, 1490, 989, 467, -366, -599, -1564, -1343, +-1983, -1441, -1276, -1143, 379, -213, 1848, 849, +2320, 1561, 1659, 1867, -137, 968, -1870, -667, +-2365, -1976, -1668, -2414, 50, -1367, 1824, 827, +2327, 2385, 1758, 2495, 510, 1269, -971, -986, +-1680, -2427, -1713, -2160, -1157, -957, 164, 721, +1263, 1784, 1973, 1527, 2000, 859, 851, 102, +-711, -694, -2060, -1016, -2329, -1258, -1151, -1173, +749, -269, 2265, 808, 2526, 1788, 1293, 1880, +-718, 691, -2127, -963, -2190, -2060, -934, -1919, +1015, -606, 2167, 1099, 2161, 1847, 982, 1437, +-844, 292, -1941, -1031, -2053, -1493, -1064, -937, +634, -117, 1970, 748, 2313, 1264, 1676, 785, +157, 143, -1383, -515, -2218, -1214, -2181, -974, +-995, -365, 872, 309, 2354, 1099, 2861, 1190, +1983, 688, -17, 4, -1951, -839, -2976, -1383, +-2407, -1157, -354, -419, 1859, 629, 3022, 1509, +2574, 1510, 661, 600, -1457, -779, -2501, -1712, +-2084, -1421, -479, -136, 1364, 1207, 2266, 1654, +1979, 714, 600, -869, -1141, -1654, -1969, -1203, +-1791, 271, -646, 1756, 1168, 1783, 2276, 527, +2340, -1036, 1169, -2012, -1048, -1592, -2492, -125, +-2618, 1160, -1297, 1653, 1121, 1289, 2792, 230, +2906, -822, 1612, -1264, -711, -1176, -2536, -496, +-2701, 501, -1419, 1111, 732, 1147, 2389, 487, +2410, -537, 1184, -1229, -582, -1038, -1879, -203, +-1713, 793, -461, 1358, 955, 879, 1727, -62, +1182, -1014, -120, -1483, -1043, -971, -1245, 11, +-492, 1103, 700, 1666, 1298, 1231, 1164, 183, +272, -1036, -788, -1754, -1119, -1460, -763, -439, +-40, 687, 787, 1454, 1268, 1377, 906, 812, +66, 49, -759, -788, -1173, -1237, -650, -1445, +215, -1044, 1031, 129, 1465, 1424, 761, 2129, +-424, 1649, -1373, -4, -1431, -1789, -341, -2381, +970, -1574, 1705, 188, 1367, 1806, 231, 1995, +-976, 1067, -1586, -142, -1025, -1226, 183, -1386, +1045, -921, 1413, -439, 748, 469, -327, 1119, +-718, 1261, -777, 1102, -209, -39, 569, -1305, +665, -1673, 424, -1344, -99, -116, -568, 1321, +-393, 1713, 56, 1312, 372, 307, 618, -962, +479, -1481, 44, -1403, -191, -800, -483, 461, +-418, 1470, -82, 1685, 2, 1087, 378, -344, +742, -1697, 585, -1757, 235, -839, -295, 592, +-718, 1714, -658, 1242, -263, 199, 275, -742, +716, -1227, 921, -489, 526, 283, -191, 610, +-628, 546, -835, -139, -483, -552, 236, -385, +691, -34, 977, 490, 665, 797, -227, 336, +-820, -441, -932, -956, -375, -1050, 525, -180, +937, 1010, 782, 1455, 164, 1003, -488, -377, +-671, -1616, -313, -1530, 147, -393, 354, 993, +299, 1657, -91, 889, -193, -322, 229, -1092, +422, -985, 357, 39, 15, 588, -673, 364, +-805, -104, -310, -513, 355, -192, 1038, 656, +1109, 902, 296, 369, -615, -515, -1131, -1380, +-1039, -1170, -131, -21, 780, 967, 1198, 1616, +982, 1253, 35, -143, -705, -1197, -993, -1627, +-736, -1348, 53, 72, 575, 1319, 790, 1670, +604, 1390, 48, -100, -348, -1477, -460, -1569, +-299, -1145, 18, 75, 56, 1391, 27, 1318, +76, 784, 64, 100, 331, -1021, 456, -1156, +267, -745, 0, -404, -701, 682, -1064, 1269, +-569, 978, 259, 549, 1159, -619, 1505, -1618, +779, -1166, -484, -291, -1537, 778, -1771, 1652, +-707, 901, 809, -109, 1739, -714, 1692, -1176, +654, -426, -745, 379, -1637, 233, -1610, 273, +-759, 119, 601, -237, 1612, 335, 1622, 413, +929, -131, -406, -156, -1653, -567, -1754, -546, +-999, 204, 569, 263, 1927, 353, 1789, 511, +554, 7, -1073, -166, -1984, -199, -1373, -669, +49, -437, 1382, 44, 1934, 447, 929, 1113, +-635, 769, -1591, -235, -1684, -973, -512, -1463, +837, -924, 1455, 481, 1438, 1395, 543, 1537, +-683, 910, -1388, -414, -1360, -1399, -510, -1489, +589, -1049, 1161, -10, 1064, 1123, 333, 1474, +-398, 1275, -723, 410, -678, -839, -75, -1484, +296, -1361, 141, -512, 41, 645, -90, 1275, +-2, 1117, 302, 422, 240, -462, -121, -965, +-288, -744, -298, -319, -119, 285, 340, 741, +412, 546, 4, 143, -375, -402, -650, -672, +-432, -341, 371, 190, 902, 576, 815, 470, +355, -51, -482, -485, -1132, -496, -1060, -82, +-547, 458, 472, 537, 1282, 55, 1163, -401, +503, -602, -393, -329, -1082, 319, -1035, 655, +-436, 491, 183, 167, 670, -282, 700, -586, +247, -496, 50, -396, -195, -37, -490, 502, +-382, 676, -357, 708, -19, 370, 667, -479, +705, -893, 216, -816, -370, -386, -1107, 331, +-916, 646, 179, 628, 913, 453, 1291, 76, +856, -230, -558, -456, -1306, -623, -1113, -511, +-615, -3, 561, 515, 1118, 682, 651, 507, +429, -132, -158, -537, -607, -437, -249, -121, +-441, 393, -412, 386, 71, -100, 25, -340, +440, -377, 695, -114, 216, 428, 47, 516, +-375, 220, -861, -80, -461, -513, -28, -462, +319, -8, 821, 235, 528, 398, -146, 303, +-492, -160, -865, -528, -487, -376, 441, -30, +757, 515, 688, 809, 174, 338, -579, -360, +-724, -921, -461, -795, -93, -57, 352, 621, +493, 711, 344, 298, 300, -110, 186, -297, +-198, 35, -498, 233, -782, -114, -664, -576, +81, -837, 719, -319, 1069, 676, 793, 1279, +-76, 1011, -774, 100, -1044, -948, -783, -1349, +-75, -721, 497, 22, 793, 546, 683, 824, +194, 605, -82, 331, -409, 118, -683, -420, +-510, -896, -298, -865, 89, -527, 603, 411, +801, 1378, 708, 1268, 263, 454, -614, -675, +-1277, -1600, -1100, -1475, -322, -342, 895, 919, +1658, 1701, 1259, 1595, 172, 382, -1200, -1015, +-1835, -1848, -1135, -1743, 202, -426, 1314, 1147, +1496, 1903, 669, 1617, -349, 300, -949, -1159, +-918, -1630, -387, -1171, 113, -47, 341, 890, +390, 904, 394, 543, 295, 34, 63, -372, +-207, -182, -478, -22, -427, -278, -104, -377, +106, -316, 314, -2, 224, 660, 143, 890, +316, 443, 265, -220, 45, -984, -501, -1153, +-1030, -379, -755, 486, 104, 1016, 1073, 1097, +1651, 495, 1093, -393, -339, -891, -1542, -1019, +-1943, -727, -1135, -25, 331, 574, 1491, 1031, +1998, 1149, 1286, 484, 31, -410, -1153, -1067, +-1953, -1301, -1604, -735, -560, 266, 775, 1037, +1964, 1186, 1956, 577, 782, -238, -590, -782, +-1733, -831, -1861, -342, -879, 317, 373, 650, +1488, 439, 1746, 6, 979, -476, -139, -649, +-1126, -244, -1558, 287, -1097, 715, -54, 706, +1036, 86, 1684, -430, 1270, -737, -3, -652, +-1092, -119, -1529, 409, -1056, 561, 43, 381, +951, 218, 1189, -194, 790, -345, 18, -213, +-619, -115, -612, 201, -429, 197, -279, -35, +102, -263, 205, -468, 236, -192, 437, 335, +355, 953, 249, 938, -29, 54, -468, -895, +-671, -1521, -550, -1149, -35, 179, 668, 1458, +1076, 1713, 827, 849, 13, -467, -921, -1507, +-1306, -1465, -831, -517, 328, 565, 1337, 1207, +1479, 1065, 623, 386, -737, -432, -1404, -810, +-1125, -856, -351, -439, 714, 322, 1129, 639, +786, 591, 241, 292, -279, -170, -362, -417, +-370, -216, -591, 42, -582, 0, -251, -261, +366, -297, 1073, -103, 1285, 359, 757, 997, +-347, 797, -1368, -150, -1580, -1059, -862, -1516, +411, -758, 1501, 698, 1679, 1565, 881, 1484, +-435, 379, -1373, -1213, -1273, -1845, -498, -1025, +558, 380, 1132, 1517, 790, 1520, 85, 432, +-509, -920, -639, -1721, -223, -1123, 237, 407, +291, 1404, 86, 1543, -78, 540, -110, -1080, +94, -1714, 297, -1153, 148, 252, -118, 1579, +-381, 1593, -445, 519, -134, -808, 231, -1695, +596, -1424, 723, -50, 451, 1272, 2, 1663, +-669, 1119, -1066, -163, -782, -1336, -204, -1757, +785, -1115, 1645, 258, 1359, 1470, 306, 1843, +-976, 1189, -1766, -235, -1378, -1669, -184, -2015, +1046, -1256, 1672, 399, 1300, 1870, 55, 2043, +-977, 1143, -1288, -604, -993, -1978, 52, -1979, +841, -848, 1120, 805, 856, 1841, -228, 1761, +-975, 626, -990, -830, -501, -1745, 633, -1593, +1258, -339, 820, 884, -20, 1529, -987, 1328, +-1127, 94, -285, -966, 595, -1296, 1159, -913, +928, 269, -164, 932, -997, 870, -888, 502, +-275, -435, 508, -896, 977, -479, 746, -67, +140, 448, -660, 634, -964, 230, -512, 18, +101, -244, 691, -447, 787, -232, 456, -194, +-114, -116, -694, 349, -692, 564, -243, 566, +270, 279, 624, -378, 489, -811, 38, -865, +-283, -384, -424, 377, -304, 878, 70, 966, +315, 496, 388, -87, 373, -704, 26, -1059, +-228, -730, -299, -275, -361, 370, -79, 1043, +293, 1053, 326, 607, 329, -29, 159, -878, +-186, -1210, -7, -872, 98, -310, -98, 502, +-161, 1063, -479, 1096, -494, 806, 193, 68, +743, -786, 984, -1393, 729, -1391, -372, -631, +-1269, 572, -1201, 1654, -595, 1897, 588, 1051, +1384, -505, 1108, -1609, 476, -1981, -545, -1380, +-1239, 108, -929, 1239, -372, 1843, 359, 1717, +1139, 652, 1162, -602, 671, -1683, -186, -2130, +-1204, -1496, -1451, -131, -801, 1428, 245, 2456, +1341, 2193, 1810, 822, 1139, -1010, -289, -2472, +-1479, -2567, -1753, -1436, -1074, 372, 212, 2070, +1169, 2607, 1416, 1894, 1078, 343, 108, -1291, +-661, -2212, -920, -2093, -956, -1032, -479, 175, +39, 1351, 405, 1997, 799, 1783, 721, 1062, +533, -343, 174, -1685, -581, -2432, -832, -2111, +-751, -551, -523, 1324, 239, 2650, 850, 2640, +1004, 1145, 828, -866, 118, -2221, -630, -2535, +-946, -1562, -860, 132, -387, 1356, 241, 2055, +845, 1820, 1071, 692, 728, -486, 120, -1402, +-568, -1766, -1064, -1303, -1160, -197, -617, 628, +282, 1291, 1075, 1433, 1505, 711, 1028, 198, +167, -409, -847, -1029, -1762, -1111, -1610, -1075, +-675, -640, 554, 258, 1788, 1181, 2075, 1866, +1246, 1698, 24, 616, -1477, -846, -2258, -2315, +-1800, -2665, -654, -1490, 1080, 391, 2179, 2277, +2069, 3090, 1360, 2245, -142, 177, -1649, -1862, +-2222, -2884, -1947, -2455, -750, -643, 956, 1086, +2004, 1922, 2323, 2008, 1752, 994, -87, -125, +-1778, -555, -2577, -896, -2268, -980, -601, -957, +1228, -877, 2372, -352, 2426, 580, 1076, 1599, +-704, 1908, -1949, 1386, -2121, 199, -1172, -1344, +282, -2256, 1332, -2119, 1438, -1211, 810, 232, +-60, 1775, -477, 2450, -401, 2263, -139, 1282, +16, -609, -247, -2280, -629, -3034, -468, -2633, +38, -852, 698, 1475, 1216, 3203, 929, 3564, +212, 2197, -614, -207, -1371, -2606, -1252, -3883, +-547, -3153, 165, -1050, 996, 1334, 1412, 3302, +991, 3583, 202, 2179, -665, 183, -1268, -1964, +-1096, -3223, -544, -2945, 185, -1731, 744, 156, +825, 2266, 695, 3258, 335, 2936, -3, 1581, +-345, -902, -742, -2938, -788, -3591, -505, -2864, +-31, -524, 597, 2021, 933, 3586, 614, 3557, +212, 1651, -28, -1000, -294, -2997, -246, -3490, +-463, -2140, -868, 286, -766, 2154, -285, 2622, +756, 1712, 1753, 7, 1772, -1211, 692, -1332, +-995, -708, -2191, 202, -2149, 570, -998, 132, +614, -501, 1761, -792, 1895, -412, 1201, 498, +102, 1319, -812, 1568, -1205, 924, -1161, -333, +-764, -1603, -330, -2164, 136, -1731, 618, -539, +1043, 1112, 1316, 2311, 1207, 2483, 515, 1590, +-799, 55, -1962, -1644, -2472, -2664, -1789, -2497, +184, -1589, 2126, 242, 3301, 2089, 2838, 3033, +718, 3049, -1635, 1422, -3428, -1021, -3608, -3053, +-1816, -3831, 682, -2662, 2898, -216, 3870, 2416, +2875, 3807, 495, 3169, -2224, 1114, -3950, -1377, +-3615, -3042, -1408, -3028, 1459, -1605, 3593, 528, +3942, 2100, 2111, 2416, -873, 1551, -3098, -138, +-3781, -1484, -2513, -1868, 201, -1172, 2527, 373, +3739, 1511, 2929, 1725, 299, 792, -2111, -978, +-3571, -2140, -3211, -2119, -832, -686, 1818, 1488, +3497, 2919, 3292, 2908, 1239, 1132, -1264, -1576, +-3041, -3471, -3402, -3580, -1890, -1818, 488, 830, +2409, 3140, 3293, 3863, 2501, 2677, 526, 516, +-1749, -1861, -3285, -3435, -3069, -3497, -1307, -2156, +1234, 143, 3099, 2553, 3168, 3873, 1679, 3377, +-795, 1280, -2659, -1374, -2909, -3369, -1751, -3641, +438, -2043, 2211, 65, 2555, 1908, 1660, 2925, +-109, 2304, -1670, 1115, -2160, -224, -1650, -1624, +-180, -2155, 1297, -1914, 1975, -948, 1661, 590, +412, 1751, -967, 1818, -1834, 1116, -1660, -192, +-616, -1200, 484, -968, 1438, -337, 1682, 464, +964, 702, -75, -96, -1058, -729, -1428, -1040, +-1133, -664, -547, 580, 254, 1465, 967, 1625, +1194, 1155, 1170, -143, 773, -1413, -101, -1923, +-1009, -1854, -1728, -850, -1783, 575, -945, 1530, +528, 2061, 2092, 1801, 2696, 782, 1944, -293, +174, -1347, -1781, -2110, -2926, -2081, -2829, -1438, +-1213, -272, 1079, 1393, 2735, 2658, 3104, 2978, +1997, 2284, 31, 318, -1845, -2040, -2847, -3637, +-2504, -3877, -1020, -2404, 677, 340, 1804, 2932, +2118, 4363, 1624, 3967, 742, 1750, -286, -1032, +-1187, -3336, -1612, -4227, -1741, -3362, -1287, -1318, +-152, 1085, 1083, 2964, 2064, 3704, 2365, 3101, +1481, 1499, -73, -652, -1459, -2570, -2342, -3474, +-2302, -3256, -1305, -1833, 230, 269, 1622, 2206, +2478, 3480, 2429, 3634, 1225, 2384, -399, 124, +-1923, -2312, -2887, -4143, -2344, -4323, -820, -2605, +872, 333, 2477, 3362, 2769, 4950, 1684, 4248, +231, 1593, -1451, -1799, -2419, -4253, -2145, -4508, +-1088, -2721, 491, 119, 1580, 2670, 1820, 3532, +1470, 2763, 470, 1015, -499, -913, -1161, -1876, +-1455, -1913, -1034, -1399, -264, -446, 512, 303, +1142, 713, 1235, 1087, 743, 1124, 15, 813, +-684, 297, -973, -518, -772, -1234, -404, -1263, +-22, -855, 392, -35, 784, 1044, 950, 1354, +676, 1007, 94, 316, -720, -729, -1374, -1252, +-1325, -1045, -532, -503, 627, 430, 1428, 1063, +1621, 1045, 1048, 739, -62, 63, -1031, -688, +-1682, -1117, -1670, -1156, -919, -666, 131, 132, +1540, 1006, 2444, 1564, 2071, 1295, 810, 409, +-1044, -628, -2538, -1395, -2799, -1508, -1781, -958, +256, -137, 2063, 604, 2706, 949, 2231, 1117, +801, 1180, -714, 810, -1752, 186, -2106, -781, +-1678, -1835, -831, -2191, 201, -1750, 1270, -256, +1950, 1785, 1943, 2983, 1323, 3060, 66, 1763, +-1554, -706, -2435, -2834, -2220, -3768, -1017, -3061, +701, -824, 1799, 1668, 2003, 3425, 1340, 3660, +223, 2135, -529, -109, -679, -2001, -634, -3021, +-830, -2735, -1071, -1383, -991, 174, -409, 1527, +802, 2282, 2043, 2097, 2381, 1383, 1558, 237, +-149, -1058, -1987, -1765, -2861, -1938, -2365, -1522, +-883, -532, 1058, 608, 2327, 1549, 2487, 1952, +1713, 1631, 209, 672, -1170, -540, -1836, -1437, +-1813, -1705, -1176, -1275, -353, -480, 403, 286, +1175, 756, 1611, 812, 1544, 889, 1050, 924, +-20, 751, -1230, 420, -1993, -430, -2060, -1517, +-1130, -2011, 344, -1788, 1603, -700, 2106, 1133, +1833, 2509, 929, 2691, -325, 1786, -1426, -79, +-2284, -1971, -2059, -2758, -804, -2366, 571, -892, +2070, 918, 2538, 1935, 1620, 2033, 152, 1290, +-1622, 37, -2410, -756, -1732, -924, -451, -820, +982, -472, 1708, -302, 1303, -323, 419, -152, +-481, 111, -967, 615, -745, 1145, -26, 1241, +544, 835, 380, -88, -184, -1226, -639, -2011, +-650, -1966, 72, -946, 856, 709, 1237, 2092, +992, 2561, -195, 1957, -1307, 274, -1549, -1438, +-1080, -2362, 49, -2415, 1094, -1325, 1304, 187, +1078, 1391, 407, 2164, -375, 2129, -572, 1255, +-867, 8, -1057, -1386, -684, -2482, -351, -2451, +433, -1342, 1342, 436, 1542, 2300, 1326, 2990, +236, 2263, -1203, 497, -1919, -1672, -2068, -2756, +-1186, -2598, 487, -1341, 1812, 727, 2493, 2086, +2002, 2342, 379, 1681, -1377, 264, -2475, -995, +-2292, -1513, -963, -1432, 713, -947, 2004, -267, +2136, 227, 1089, 685, -398, 1153, -1378, 1255, +-1383, 997, -695, 244, 320, -749, 940, -1466, +758, -1649, 68, -1062, -761, -75, -1011, 769, +-436, 1384, 366, 1482, 1139, 909, 1383, 241, +815, -428, -233, -1108, -1306, -1203, -1767, -932, +-1420, -609, -578, -33, 688, 457, 1661, 832, +1824, 1272, 1540, 1351, 546, 1035, -643, 220, +-1509, -1087, -2168, -2169, -1893, -2532, -912, -1730, +215, -8, 1792, 1843, 2751, 3195, 2559, 3096, +1454, 1557, -567, -503, -2396, -2458, -3306, -3483, +-2912, -2934, -1110, -1176, 1011, 851, 2577, 2453, +3180, 3028, 2446, 2419, 851, 1116, -759, -466, +-2115, -1762, -2724, -2401, -2236, -2458, -1290, -1671, +68, -109, 1563, 1394, 2358, 2364, 2531, 2508, +1935, 1573, 504, 236, -1162, -920, -2538, -1665, +-2896, -1691, -2122, -1520, -587, -1221, 1177, -398, +2252, 612, 2407, 1738, 1856, 2693, 809, 2507, +-312, 1133, -1199, -873, -1890, -2828, -2251, -3451, +-1856, -2448, -682, -544, 846, 1638, 2272, 2948, +2730, 2664, 1968, 1415, 662, -105, -761, -1293, +-1827, -1567, -2038, -1204, -1646, -822, -1057, -415, +-329, -218, 471, -29, 1376, 708, 2096, 1335, +2295, 1548, 1637, 1298, 160, 284, -1532, -843, +-2799, -1544, -3151, -1868, -2258, -1431, -334, -591, +1688, 233, 3223, 1347, 3563, 2067, 2289, 1995, +331, 1329, -1699, -53, -3155, -1603, -3167, -2471, +-2071, -2297, -417, -1191, 1276, 453, 2351, 1782, +2473, 2136, 1906, 1743, 949, 607, -340, -635, +-1368, -1120, -1997, -1165, -2091, -857, -1507, -352, +-705, -36, 502, 81, 1620, 238, 2187, 488, +2316, 692, 1544, 750, 107, 533, -1322, 136, +-2460, -378, -2746, -723, -1928, -811, -619, -874, +956, -632, 2375, -180, 2806, 300, 2356, 1040, +1215, 1547, -510, 1352, -1990, 685, -2842, -370, +-2821, -1449, -1669, -1845, 75, -1672, 1653, -959, +2828, 227, 3013, 1204, 1939, 2063, 439, 2281, +-1383, 1480, -2786, 128, -2862, -1588, -2017, -2602, +-578, -2455, 962, -1421, 1944, 332, 2261, 1667, +2074, 2085, 1324, 1913, 85, 1126, -1189, 166, +-2280, -731, -2730, -1612, -2017, -1976, -430, -1593, +1328, -649, 2518, 804, 2639, 1869, 1590, 1806, +125, 1035, -1044, -95, -1699, -904, -1558, -901, +-1122, -396, -534, 41, 154, 69, 453, -374, +747, -816, 1036, -582, 1127, 94, 1143, 954, +671, 1656, -325, 1403, -1332, 433, -2161, -536, +-2127, -1361, -993, -1696, 483, -1353, 1887, -704, +2569, 160, 1980, 1263, 656, 1866, -651, 1835, +-1616, 1242, -1787, -215, -1330, -1527, -767, -2065, +35, -1906, 722, -920, 855, 362, 1168, 1216, +1251, 1538, 826, 1410, 442, 813, -479, 176, +-1388, -422, -1694, -984, -1673, -1120, -909, -1090, +491, -705, 1607, -79, 2055, 371, 1673, 878, +556, 996, -497, 855, -1139, 808, -1431, 490, +-1092, -8, -556, -623, -233, -1475, 98, -2105, +427, -1867, 881, -666, 1278, 1199, 1239, 2846, +777, 3287, -17, 2216, -966, 92, -1796, -2059, +-2071, -3277, -1483, -3026, -211, -1681, 1293, 164, +2388, 1793, 2405, 2574, 1495, 2506, 135, 1607, +-1395, 343, -2233, -958, -2122, -1973, -1336, -2227, +-206, -1867, 758, -920, 1494, 277, 1793, 1348, +1564, 2074, 967, 2109, -86, 1560, -1073, 394, +-1696, -1034, -1989, -2070, -1479, -2406, -474, -1831, +690, -511, 1803, 880, 2230, 1789, 1749, 2142, +745, 1714, -599, 792, -1717, -235, -1985, -1372, +-1712, -1970, -845, -1911, 261, -1188, 945, 140, +1527, 1162, 1820, 1761, 1387, 1698, 618, 984, +-521, 185, -1717, -636, -2248, -1241, -1847, -1526, +-638, -1339, 803, -576, 1853, 457, 2032, 1360, +1466, 1632, 305, 1181, -915, 208, -1357, -815, +-1334, -1274, -867, -1127, -32, -377, 387, 525, +538, 874, 506, 726, 311, 31, 328, -842, +322, -867, 208, -227, 35, 655, -327, 1378, +-711, 978, -863, -138, -648, -1132, -147, -1558, +507, -843, 988, 348, 1005, 998, 601, 1027, +-20, 383, -675, -356, -911, -457, -719, -129, +-324, 226, 314, 361, 584, 17, 367, -571, +68, -725, -217, -452, -223, 103, 90, 781, +273, 922, 454, 526, 407, -61, -251, -690, +-712, -674, -861, -177, -875, 151, -165, 319, +579, 114, 997, -353, 1426, -438, 1042, 0, +51, 513, -881, 768, -1583, 524, -1667, -144, +-1008, -696, -16, -779, 1034, -399, 1861, 206, +1829, 571, 1099, 431, -71, 5, -1322, -289, +-1901, -407, -1825, -178, -1062, 388, 159, 563, +1084, 487, 1622, 174, 1685, -465, 1100, -823, +277, -830, -507, -407, -1349, 262, -1836, 833, +-1579, 1047, -940, 679, 83, 41, 1324, -636, +2029, -976, 2053, -686, 1376, -181, 86, 347, +-1237, 726, -2099, 578, -2386, 170, -1736, -272, +-425, -643, 915, -583, 2115, -186, 2556, 457, +2101, 990, 938, 844, -728, 244, -2079, -629, +-2731, -1258, -2542, -1191, -1214, -569, 496, 366, +1931, 1092, 2839, 1377, 2599, 1086, 1310, 381, +-308, -504, -1721, -1213, -2432, -1369, -2261, -974, +-1464, -154, -299, 583, 878, 922, 1757, 858, +2077, 563, 1894, 327, 1152, 204, -7, 20, +-1285, -457, -2386, -1059, -2531, -1422, -1758, -1155, +-396, -36, 1325, 1177, 2404, 1935, 2426, 1801, +1631, 636, 201, -683, -1022, -1469, -1449, -1471, +-1503, -861, -1259, -66, -710, 385, -361, 546, +78, 522, 813, 404, 1362, 440, 1777, 334, +1616, 156, 679, -76, -517, -442, -1725, -659, +-2325, -734, -2101, -539, -1195, -66, 116, 435, +1410, 784, 2249, 726, 2384, 391, 1815, 2, +515, -249, -930, -301, -2053, -267, -2657, -298, +-2214, -285, -993, -101, 392, 100, 1742, 275, +2330, 142, 2019, -178, 1241, -314, 142, -53, +-748, 555, -1214, 1062, -1585, 1027, -1701, 189, +-1490, -970, -1034, -1778, 108, -1808, 1696, -887, +2924, 404, 3113, 1483, 1970, 2012, -152, 1799, +-2309, 1000, -3541, -96, -3521, -1215, -2160, -2159, +18, -2391, 2008, -1634, 3363, -187, 3593, 1541, +2482, 2663, 608, 2634, -1627, 1584, -3366, -195, +-3767, -1753, -2860, -2389, -796, -2124, 1506, -1000, +3059, 343, 3599, 1154, 2708, 1406, 735, 1131, +-1153, 631, -2515, 321, -3029, 97, -2392, -249, +-1002, -681, 583, -1117, 1850, -1298, 2426, -899, +2217, -61, 1349, 777, -19, 1321, -1395, 1357, +-2101, 893, -1999, 270, -1341, -309, -163, -731, +924, -934, 1330, -1010, 1386, -986, 1035, -644, +571, -66, 297, 709, -154, 1590, -794, 1942, +-1429, 1612, -1959, 511, -1785, -1112, -553, -2395, +1106, -2722, 2592, -1708, 3225, 166, 2307, 1894, +293, 2590, -1920, 1901, -3486, 433, -3439, -931, +-1981, -1291, 169, -768, 2166, -141, 3109, 181, +2876, -122, 1690, -646, -50, -696, -1586, -228, +-2411, 509, -2507, 1237, -1702, 1395, -430, 1015, +744, 362, 1747, -588, 2052, -1376, 1663, -1770, +1034, -1635, 185, -713, -746, 547, -1516, 1666, +-1991, 2159, -1915, 1715, -1178, 629, 100, -583, +1520, -1428, 2357, -1717, 2294, -1390, 1434, -814, +65, -201, -1242, 468, -1880, 1110, -1877, 1610, +-1404, 1741, -501, 1271, 290, 102, 870, -1315, +1434, -2374, 1497, -2541, 1216, -1502, 766, 188, +-115, 1759, -880, 2545, -1448, 2115, -1824, 880, +-1587, -465, -786, -1350, 335, -1606, 1492, -1310, +2139, -743, 2056, -138, 1319, 442, 61, 884, +-1169, 1104, -2065, 893, -2365, 374, -1710, -117, +-544, -331, 767, -321, 1995, -300, 2244, -470, +1627, -880, 669, -1099, -533, -637, -1333, 487, +-1477, 1695, -1357, 2296, -960, 1797, -293, 257, +271, -1414, 888, -2468, 1371, -2434, 1307, -1189, +975, 382, 391, 1649, -417, 2181, -1112, 1751, +-1593, 795, -1649, -274, -985, -1103, 91, -1528, +1203, -1465, 2068, -947, 2085, -161, 1142, 690, +-196, 1276, -1490, 1517, -2175, 1220, -1837, 409, +-872, -471, 376, -1251, 1445, -1590, 1820, -1242, +1569, -436, 789, 486, -316, 1154, -1177, 1281, +-1556, 838, -1410, 186, -749, -346, 151, -638, +941, -526, 1310, -298, 1242, -222, 717, -221, +-21, -359, -711, -384, -1093, 61, -902, 699, +-511, 1218, -156, 1285, 117, 538, 203, -618, +343, -1563, 556, -1817, 827, -1104, 974, 70, +502, 1076, -287, 1514, -1155, 1138, -1815, 452, +-1576, -181, -670, -661, 508, -780, 1654, -581, +2089, -345, 1621, -44, 592, 288, -671, 314, +-1608, 200, -1676, 81, -1178, -26, -510, 52, +228, 273, 668, 335, 872, 212, 1100, -57, +1134, -350, 908, -533, 243, -479, -749, -267, +-1594, -28, -1972, 264, -1345, 509, 47, 710, +1280, 679, 1893, 428, 1611, -67, 582, -740, +-481, -1119, -1089, -1035, -1098, -453, -560, 486, +147, 1196, 454, 1335, 322, 825, -7, -165, +-405, -993, -460, -1158, 18, -695, 600, 90, +885, 689, 773, 713, 78, 288, -697, -158, +-1042, -298, -1018, -218, -464, -34, 269, 44, +610, -106, 744, -233, 668, -99, 227, 139, +-177, 325, -431, 395, -516, 165, -270, -117, +-5, -202, 99, -270, 85, -227, -114, -162, +-133, -347, 31, -391, 201, -251, 366, 25, +269, 607, 79, 1122, -49, 1234, -147, 849, +-123, -161, -150, -1354, -331, -2018, -417, -1998, +-232, -1114, 229, 347, 782, 1562, 1002, 2277, +586, 2266, -154, 1492, -735, 292, -1012, -1134, +-720, -2359, -81, -2832, 382, -2284, 696, -826, +734, 1118, 477, 2584, 137, 2890, -295, 2158, +-643, 720, -686, -729, -506, -1555, -92, -1797, +346, -1599, 604, -1039, 702, -370, 507, 366, +167, 1066, -250, 1394, -797, 1300, -1164, 885, +-951, 213, -256, -306, 650, -603, 1427, -723, +1523, -636, 833, -574, -229, -528, -1209, -437, +-1673, -159, -1330, 334, -457, 981, 451, 1502, +1066, 1374, 1214, 561, 856, -654, 331, -1678, +-57, -1861, -374, -1040, -524, 301, -637, 1320, +-800, 1470, -725, 681, -500, -470, 42, -1263, +912, -1159, 1552, -276, 1713, 798, 1168, 1474, +-8, 1225, -1256, 349, -2093, -685, -2179, -1425, +-1320, -1494, 74, -992, 1395, -273, 2324, 395, +2289, 983, 1348, 1318, 137, 1314, -1114, 975, +-1878, 152, -1938, -840, -1537, -1636, -666, -1913, +338, -1315, 1253, -227, 1952, 962, 1991, 1752, +1269, 1655, 20, 946, -1214, -33, -1923, -909, +-1866, -1085, -1105, -839, -194, -478, 574, 98, +1125, 321, 1242, 336, 1091, 452, 772, 387, +102, 333, -590, 210, -1084, -106, -1351, -419, +-1099, -622, -393, -530, 311, -117, 870, 364, +1039, 633, 854, 672, 561, 369, 68, 60, +-272, -93, -507, -202, -816, -223, -913, -393, +-770, -614, -363, -644, 422, -324, 1184, 281, +1488, 1034, 1309, 1431, 512, 1141, -660, 379, +-1501, -627, -1727, -1337, -1238, -1365, -126, -931, +866, -228, 1397, 353, 1531, 561, 1091, 630, +308, 644, -512, 607, -1156, 467, -1418, 200, +-1197, -272, -526, -666, 348, -787, 1062, -715, +1239, -472, 1024, -235, 565, -83, 41, 116, +-308, 438, -677, 703, -1016, 859, -1202, 775, +-1105, 290, -471, -268, 453, -696, 1321, -953, +1850, -930, 1633, -659, 695, -289, -484, 89, +-1439, 450, -1884, 658, -1728, 694, -1060, 544, +-99, 379, 889, 240, 1632, 141, 1906, 9, +1566, -343, 498, -781, -712, -1207, -1562, -1294, +-1865, -791, -1330, 135, -397, 1199, 403, 1955, +969, 1936, 1076, 1179, 807, 4, 593, -1159, +302, -1663, -49, -1356, -277, -698, -587, 19, +-838, 367, -722, 256, -411, 193, 37, 387, +526, 756, 675, 1038, 695, 948, 644, 368, +308, -331, -18, -863, -308, -1079, -595, -926, +-616, -701, -501, -391, -295, 0, 70, 411, +314, 890, 399, 1223, 480, 1220, 532, 833, +432, 156, 70, -715, -498, -1299, -933, -1444, +-918, -1219, -506, -460, 184, 294, 804, 759, +1051, 990, 716, 877, -111, 492, -795, 168, +-960, -146, -721, -482, -123, -582, 499, -562, +640, -412, 498, -81, 208, 136, -157, 156, +-274, 53, -179, -77, -123, -33, -66, 172, +-196, 300, -379, 223, -251, 24, -17, -289, +402, -297, 789, -90, 717, 74, 369, 241, +-159, 111, -621, -112, -677, -246, -521, -332, +-278, -359, 3, -210, 212, 114, 435, 479, +646, 878, 657, 928, 442, 518, -6, -125, +-460, -798, -651, -1109, -557, -995, -270, -567, +53, 51, 235, 670, 201, 1106, 137, 1231, +94, 932, 59, 208, 171, -648, 367, -1180, +373, -1051, 136, -420, -306, 361, -811, 838, +-972, 665, -710, 103, -150, -383, 506, -516, +954, -190, 975, 323, 448, 678, -94, 608, +-359, 192, -494, -323, -415, -740, -410, -782, +-520, -472, -361, 46, -117, 574, 225, 852, +735, 725, 870, 293, 590, -367, 111, -947, +-427, -1118, -694, -848, -524, -79, -236, 826, +-23, 1346, 124, 1245, 78, 475, -17, -563, +89, -1214, 280, -1233, 476, -730, 556, -81, +267, 282, -159, 355, -513, 335, -642, 373, +-411, 528, -73, 508, 143, 154, 292, -263, +287, -589, 204, -710, 206, -471, 111, -200, +98, -67, 158, 130, 6, 251, -123, 419, +-247, 600, -444, 448, -407, 187, -291, -102, +-109, -482, 258, -566, 397, -421, 418, -258, +411, 126, 247, 471, 68, 584, -164, 534, +-422, 110, -599, -408, -557, -657, -397, -518, +-103, 99, 280, 789, 426, 1100, 399, 760, +261, -89, 31, -946, -34, -1368, -12, -1109, +-56, -209, -37, 844, -125, 1469, -320, 1406, +-413, 672, -363, -345, -57, -1110, 318, -1203, +493, -626, 596, 151, 467, 628, -20, 622, +-445, 216, -568, -252, -412, -467, 20, -322, +421, -10, 566, 265, 437, 470, 86, 509, +-322, 350, -611, -22, -506, -492, -212, -857, +142, -938, 492, -679, 539, -150, 361, 430, +199, 792, 33, 1006, -122, 1051, -153, 668, +-293, -18, -577, -882, -596, -1661, -357, -1717, +43, -967, 606, 161, 828, 1244, 645, 1576, +315, 1029, -214, 220, -576, -470, -636, -683, +-605, -372, -318, 37, 85, 260, 278, 202, +406, -115, 443, -406, 204, -659, -65, -715, +-338, -384, -479, 105, -273, 678, -1, 1192, +257, 1333, 427, 1022, 297, 403, -18, -414, +-388, -1115, -555, -1536, -370, -1515, 77, -888, +525, 31, 656, 920, 579, 1451, 78, 1367, +-500, 886, -662, 278, -717, -157, -398, -323, +222, -454, 577, -563, 945, -596, 1081, -507, +550, -288, -159, -50, -983, 86, -1525, 148, +-1201, 245, -390, 543, 584, 935, 1318, 996, +1301, 548, 789, -305, 250, -1107, -189, -1368, +-467, -945, -673, -56, -869, 554, -897, 512, +-719, 64, -244, -437, 451, -428, 1058, 221, +1318, 980, 1115, 1331, 445, 985, -409, -41, +-1022, -1138, -1289, -1705, -1027, -1637, -383, -885, +251, 198, 666, 930, 663, 1203, 300, 982, +-32, 412, -132, -50, -106, -251, 96, -234, +238, -170, 119, -232, 40, -374, -115, -419, +-356, -355, -390, -122, -382, 88, -230, 182, +165, 259, 383, 314, 468, 441, 381, 500, +-52, 320, -298, -107, -168, -535, 175, -726, +552, -529, 544, -30, 50, 459, -474, 659, +-866, 440, -943, 70, -502, -239, 138, -392, +764, -260, 1135, -33, 970, 89, 405, 197, +-257, 214, -720, 142, -676, 139, -298, 154, +68, 167, 208, 222, -73, 162, -476, -160, +-498, -514, -175, -780, 452, -732, 1042, -201, +1049, 464, 591, 992, -150, 1032, -910, 555, +-1248, -125, -1147, -667, -670, -785, 123, -434, +832, 67, 1189, 407, 1107, 428, 544, -14, +-159, -503, -682, -680, -988, -413, -845, 134, +-398, 627, -44, 718, 287, 306, 509, -148, +529, -395, 529, -264, 325, 57, 55, 153, +-124, -56, -350, -392, -385, -575, -357, -367, +-348, 101, -181, 466, 85, 522, 323, 251, +478, -24, 490, -136, 283, -70, 93, 26, +6, -12, -225, -173, -398, -320, -456, -231, +-445, -19, -111, 169, 328, 261, 613, 235, +725, 142, 421, 133, -159, 92, -625, -36, +-828, -184, -676, -381, -188, -371, 393, -214, +819, 74, 1006, 457, 689, 715, 55, 768, +-606, 496, -1099, -105, -1094, -759, -689, -1078, +-78, -925, 546, -229, 919, 541, 925, 915, +646, 816, 204, 353, -244, -112, -531, -279, +-638, -102, -597, 73, -437, 113, -279, -47, +-100, -365, 165, -540, 455, -507, 731, -291, +898, 112, 712, 518, 136, 787, -528, 851, +-1032, 545, -1176, -21, -773, -638, -121, -1047, +471, -941, 980, -457, 1100, 113, 753, 588, +234, 684, -393, 415, -834, 119, -787, -158, +-488, -294, -52, -234, 344, -106, 419, 27, +340, 47, 301, -28, 233, -160, 189, -197, +33, -89, -307, 86, -571, 186, -677, 68, +-512, -132, 24, -199, 553, 30, 867, 396, +903, 590, 413, 383, -238, -210, -700, -851, +-912, -1037, -673, -582, -142, 138, 211, 816, +356, 1043, 309, 642, 76, 41, 69, -442, +219, -560, 320, -255, 393, 192, 124, 417, +-337, 291, -689, -110, -870, -600, -646, -730, +-148, -353, 449, 243, 899, 828, 951, 1054, +679, 666, 118, -18, -564, -556, -894, -774, +-828, -595, -462, -149, 206, 193, 653, 420, +731, 518, 604, 395, 190, 179, -219, -219, +-456, -644, -631, -760, -549, -497, -252, 43, +86, 613, 508, 800, 728, 594, 644, 228, +380, -119, -14, -180, -385, -182, -592, -238, +-541, -356, -383, -498, -102, -492, 151, -316, +195, -18, 198, 186, 162, 318, 156, 425, +321, 536, 427, 620, 301, 500, 11, 125, +-522, -421, -945, -877, -889, -966, -442, -624, +237, -128, 839, 287, 999, 382, 716, 189, +124, -33, -484, -150, -777, -11, -711, 255, +-377, 498, 39, 651, 354, 571, 449, 272, +396, -205, 269, -739, 163, -1018, 96, -990, +-22, -653, -256, -109, -593, 345, -872, 631, +-773, 713, -142, 734, 698, 722, 1372, 599, +1458, 341, 744, -91, -270, -634, -1070, -1041, +-1371, -1037, -961, -649, -228, 35, 372, 628, +722, 847, 599, 650, 275, 148, 101, -295, +-58, -403, -82, -188, 32, 109, 10, 407, +-39, 504, -119, 401, -307, 219, -289, -74, +-136, -398, -13, -699, 204, -858, 342, -690, +290, -225, 257, 331, 97, 814, -167, 925, +-268, 652, -367, 218, -424, -224, -202, -411, +59, -351, 274, -225, 540, -101, 462, -76, +165, -179, -59, -264, -365, -222, -504, -81, +-345, 97, -232, 330, 43, 418, 344, 274, +356, 79, 363, -172, 103, -313, -237, -255, +-259, -122, -194, 30, -62, 110, 89, 88, +33, 76, -46, -6, -14, -143, 104, -232, +337, -340, 423, -247, 209, 22, -181, 306, +-546, 547, -712, 568, -567, 370, -207, 58, +220, -276, 657, -587, 891, -761, 854, -680, +542, -335, 4, 233, -611, 837, -1066, 1108, +-1135, 901, -812, 312, -152, -391, 502, -818, +909, -814, 1051, -473, 806, -67, 346, 166, +-112, 205, -521, 198, -703, 289, -718, 507, +-566, 599, -304, 403, -35, -46, 238, -634, +500, -927, 727, -740, 715, -182, 488, 471, +41, 844, -499, 793, -786, 323, -710, -222, +-462, -531, -129, -505, 199, -219, 359, 82, +409, 192, 399, 66, 283, -107, 155, -153, +26, 5, -191, 263, -307, 394, -338, 305, +-340, 54, -155, -245, 141, -384, 397, -340, +492, -206, 245, -71, -225, -18, -625, -21, +-701, -44, -268, -20, 419, 61, 939, 197, +1055, 339, 627, 434, -196, 423, -899, 166, +-1196, -279, -994, -724, -333, -1011, 340, -905, +805, -339, 948, 378, 721, 935, 280, 1088, +-189, 748, -489, 165, -602, -370, -498, -668, +-199, -633, 57, -358, 227, -40, 300, 218, +149, 317, -3, 217, -25, 27, -19, -148, +70, -205, 218, -147, 128, -2, -98, 170, +-319, 322, -480, 441, -242, 455, 141, 279, +375, -157, 438, -667, 230, -945, -108, -818, +-279, -232, -269, 496, -182, 916, -78, 876, +-1, 450, 108, -64, 308, -283, 463, -202, +390, -14, 94, 121, -396, 12, -748, -221, +-711, -425, -397, -502, 155, -395, 624, -217, +735, 64, 570, 405, 180, 696, -207, 883, +-351, 794, -300, 430, -137, -122, 27, -653, +32, -965, -139, -1017, -326, -740, -363, -308, +-174, 177, 195, 611, 626, 746, 870, 633, +698, 385, 242, 80, -439, -83, -1005, -76, +-1121, -84, -858, -172, -129, -340, 767, -472, +1291, -450, 1252, -268, 592, 41, -462, 313, +-1224, 441, -1357, 398, -807, 220, 166, -28, +903, -238, 1157, -271, 886, -106, 201, 166, +-461, 348, -843, 280, -853, -15, -429, -404, +160, -653, 584, -582, 674, -272, 371, 127, +-170, 472, -520, 651, -473, 672, -110, 533, +333, 253, 527, -94, 406, -479, 91, -774, +-296, -780, -565, -588, -563, -234, -372, 187, +20, 450, 427, 617, 664, 672, 716, 597, +358, 435, -155, 181, -533, -149, -741, -467, +-541, -713, -79, -853, 322, -816, 507, -531, +373, 25, 66, 639, -208, 1188, -320, 1313, +-226, 865, 6, 138, 233, -692, 331, -1162, +291, -1110, 74, -678, -184, 40, -322, 669, +-302, 944, -201, 798, -106, 231, 39, -432, +130, -800, 187, -695, 225, -212, 148, 291, +-36, 465, -193, 282, -121, 35, 171, -59, +436, 141, 438, 446, 12, 439, -586, 69, +-940, -463, -887, -848, -272, -829, 485, -460, +913, 13, 990, 415, 651, 552, 117, 567, +-254, 563, -531, 409, -666, 227, -531, -99, +-326, -447, -65, -625, 188, -641, 330, -418, +465, -104, 361, 169, 71, 361, -84, 422, +-204, 358, -176, 179, -44, -45, 48, -182, +175, -199, 173, -60, -37, 139, -301, 220, +-435, 163, -416, -59, -142, -335, 263, -476, +509, -437, 649, -155, 466, 274, 25, 559, +-284, 544, -450, 193, -387, -280, -123, -506, +7, -330, 30, 121, -2, 506, -197, 520, +-188, 153, 129, -286, 395, -520, 582, -460, +497, -274, 35, -142, -331, -106, -538, -89, +-582, 159, -283, 532, 3, 821, 178, 816, +415, 392, 401, -245, 246, -805, 76, -1025, +-239, -846, -351, -367, -239, 138, -111, 527, +46, 702, 139, 566, 49, 258, 35, -72, +126, -298, 113, -275, 167, -1, 144, 261, +-90, 339, -247, 127, -357, -310, -374, -611, +-135, -596, 141, -265, 327, 261, 405, 592, +267, 589, 22, 313, -158, -72, -234, -266, +-177, -207, -25, 62, 91, 260, 97, 236, +17, 8, -107, -325, -177, -483, -183, -464, +-108, -234, 103, 84, 296, 360, 380, 596, +311, 660, 38, 505, -303, 115, -531, -365, +-468, -746, -153, -758, 258, -447, 507, -23, +446, 350, 194, 468, -131, 429, -253, 305, +-224, 132, -214, -61, -176, -304, -100, -501, +46, -458, 224, -180, 358, 178, 281, 491, +57, 504, -148, 223, -286, -110, -202, -396, +-76, -439, 43, -224, 157, -8, 135, 165, +59, 176, -74, 2, -148, -152, -172, -166, +-77, -6, 131, 238, 178, 433, 105, 357, +-45, 31, -100, -340, -12, -577, 78, -485, +188, -142, 113, 222, -138, 428, -300, 362, +-280, 98, -101, -124, 126, -289, 212, -294, +134, -109, 56, 113, -8, 380, 1, 497, +46, 363, 14, 27, -13, -344, -21, -506, +-20, -385, 20, -78, -5, 146, -150, 167, +-266, 62, -219, 7, 27, 103, 323, 260, +399, 317, 253, 194, 22, -15, -154, -183, +-226, -231, -155, -191, -7, -137, 8, -59, +30, 34, 44, 183, -59, 274, -69, 207, +-69, 75, -70, -118, 124, -225, 257, -202, +215, -136, 102, -79, -123, -49, -254, 46, +-212, 166, -143, 311, 2, 379, 171, 308, +273, 132, 261, -139, 90, -407, -180, -663, +-430, -784, -518, -669, -321, -219, 164, 455, +560, 1065, 674, 1303, 507, 916, 47, 138, +-371, -705, -555, -1212, -583, -1173, -424, -755, +-103, -156, 214, 388, 554, 750, 751, 889, +513, 728, 52, 330, -515, -159, -936, -570, +-743, -704, -144, -606, 511, -374, 924, -102, +786, 117, 256, 334, -285, 522, -660, 536, +-720, 376, -472, 114, -111, -149, 356, -243, +627, -244, 563, -264, 346, -373, -107, -452, +-402, -309, -392, 75, -266, 603, 23, 878, +198, 739, 125, 240, -3, -403, -111, -748, +-171, -655, -18, -210, 264, 371, 433, 740, +453, 658, 133, 206, -458, -417, -862, -840, +-908, -818, -424, -376, 410, 299, 1063, 793, +1267, 927, 816, 654, -92, 172, -890, -272, +-1252, -565, -1076, -595, -396, -463, 333, -194, +846, 142, 1067, 390, 726, 442, 102, 231, +-356, -121, -674, -360, -658, -313, -283, 2, +55, 362, 293, 479, 338, 232, 102, -200, +-117, -540, -98, -592, 3, -323, 168, 103, +309, 484, 178, 604, -15, 430, -228, -13, +-456, -533, -401, -782, -90, -664, 289, -157, +546, 436, 469, 757, 71, 680, -323, 280, +-474, -138, -306, -411, 109, -496, 363, -484, +298, -421, 67, -256, -242, 77, -346, 511, +-158, 799, 105, 737, 281, 280, 318, -335, +181, -829, -59, -928, -216, -562, -311, 0, +-217, 550, 25, 853, 135, 757, 125, 393, +33, -110, -146, -528, -192, -670, -62, -521, +104, -188, 290, 145, 369, 335, 306, 316, +146, 224, -85, 182, -330, 221, -569, 273, +-665, 210, -520, -20, -124, -386, 424, -654, +769, -714, 800, -488, 532, 5, 47, 557, +-327, 985, -442, 1083, -339, 774, -223, 101, +-180, -631, -140, -1114, -31, -1128, 164, -670, +316, 9, 316, 591, 103, 809, -123, 659, +-221, 262, -221, -101, -63, -251, 148, -152, +264, 58, 273, 126, 176, -20, 9, -295, +-119, -497, -191, -426, -244, -81, -232, 290, +-163, 459, -161, 361, -82, 90, 117, -146, +301, -200, 465, -148, 418, -70, 154, 2, +-116, 15, -329, 68, -352, 121, -200, 67, +-101, -62, 17, -220, 66, -329, 19, -253, +49, -12, 84, 233, 66, 383, 83, 303, +24, 122, -87, -74, -84, -244, -113, -290, +-71, -281, 80, -203, 176, -38, 203, 230, +183, 461, 69, 520, -165, 357, -313, -13, +-363, -396, -288, -631, -5, -602, 216, -363, +359, 0, 475, 360, 373, 587, 116, 632, +-229, 427, -599, 79, -713, -237, -437, -389, +51, -314, 590, -127, 901, 47, 748, 93, +300, -22, -269, -151, -676, -188, -764, -97, +-667, 135, -333, 395, 121, 497, 481, 377, +678, 39, 605, -391, 277, -604, -75, -487, +-308, -100, -318, 377, -145, 655, 36, 528, +63, 79, -107, -411, -274, -741, -358, -668, +-227, -254, 140, 256, 474, 679, 637, 786, +516, 564, 37, 143, -433, -351, -652, -710, +-602, -751, -267, -498, 190, -84, 557, 329, +680, 522, 464, 471, 12, 323, -393, 155, +-645, 8, -613, -146, -317, -391, 94, -608, +471, -575, 626, -261, 497, 262, 180, 704, +-159, 747, -422, 443, -476, -33, -294, -420, +-23, -546, 227, -458, 365, -266, 331, -78, +198, 143, 8, 345, -228, 474, -357, 464, +-340, 268, -248, -53, -47, -406, 162, -615, +302, -620, 420, -409, 406, -35, 274, 398, +92, 729, -219, 800, -515, 596, -617, 116, +-486, -428, -184, -792, 162, -819, 371, -478, +471, 10, 452, 440, 316, 624, 150, 510, +-56, 235, -266, -77, -427, -302, -509, -341, +-489, -237, -243, -53, 113, 126, 452, 187, +710, 125, 692, 43, 384, 3, -79, 41, +-606, 98, -892, 62, -765, -58, -341, -202, +302, -280, 869, -277, 980, -136, 620, 57, +-8, 245, -653, 449, -924, 484, -745, 332, +-257, -8, 364, -407, 718, -604, 707, -568, +434, -306, -14, 54, -353, 317, -466, 460, +-387, 517, -132, 457, 84, 247, 153, -126, +132, -549, 10, -815, -80, -774, -23, -376, +70, 205, 166, 685, 295, 876, 254, 726, +81, 339, -134, -91, -399, -416, -447, -573, +-349, -554, -179, -413, 92, -242, 260, -66, +350, 85, 436, 217, 347, 421, 169, 592, +-20, 637, -307, 489, -505, 21, -480, -567, +-326, -964, -22, -1017, 260, -637, 330, -2, +330, 569, 186, 912, 40, 935, 65, 669, +91, 245, 38, -258, -111, -701, -397, -920, +-588, -856, -496, -542, -197, -34, 311, 473, +777, 808, 864, 933, 648, 757, 146, 324, +-487, -184, -823, -594, -823, -756, -507, -636, +44, -405, 471, -190, 586, -13, 443, 170, +131, 452, -125, 735, -161, 791, -122, 521, +-49, -49, 40, -660, -7, -927, -58, -762, +-47, -293, -47, 231, 30, 530, 79, 535, +6, 368, -29, 170, -104, 28, -194, -71, +-92, -207, 67, -324, 215, -387, 342, -366, +293, -191, 86, 72, -130, 371, -324, 618, +-337, 683, -180, 485, -34, 43, 40, -507, +8, -886, -31, -844, 37, -428, 177, 154, +278, 599, 258, 689, 105, 440, -82, 67, +-207, -205, -187, -289, -127, -179, -129, -14, +-139, 93, -132, 82, -19, -44, 206, -172, +310, -167, 296, -11, 169, 183, -80, 281, +-205, 168, -186, -117, -92, -393, 16, -455, +51, -255, -1, 108, -75, 457, -88, 600, +-52, 500, 78, 212, 232, -140, 260, -414, +176, -550, 1, -568, -194, -454, -323, -243, +-329, 73, -242, 475, -23, 792, 253, 877, +401, 624, 446, 19, 313, -675, 12, -1053, +-278, -975, -521, -426, -530, 358, -273, 875, +25, 892, 293, 426, 402, -240, 329, -661, +213, -626, 112, -211, 13, 315, -61, 567, +-240, 427, -424, 56, -440, -342, -337, -505, +-53, -373, 299, -74, 489, 249, 541, 444, +427, 424, 171, 226, -57, -18, -299, -226, +-515, -327, -588, -284, -491, -199, -238, -94, +137, 4, 481, 57, 697, 136, 718, 221, +466, 271, 23, 317, -441, 301, -728, 135, +-725, -149, -467, -419, -56, -585, 344, -522, +559, -232, 541, 124, 341, 365, 68, 377, +-196, 255, -330, 133, -320, 87, -204, 133, +-3, 173, 127, 46, 140, -203, 138, -429, +55, -519, -39, -331, -55, 4, -68, 251, +-74, 307, -53, 176, -41, 26, 54, 54, +193, 241, 221, 376, 145, 236, -36, -212, +-217, -715, -322, -896, -288, -587, -92, 105, +111, 822, 242, 1080, 265, 766, 143, 106, +35, -540, -37, -821, -82, -671, -50, -285, +-9, 76, -35, 238, -83, 210, -124, 160, +-154, 146, -46, 145, 100, 188, 183, 203, +203, 137, 120, 29, 31, -143, 14, -360, +-7, -484, -55, -441, -140, -194, -227, 144, +-239, 362, -130, 397, 22, 286, 206, 148, +359, 84, 363, 84, 275, 59, 74, -31, +-211, -172, -427, -309, -552, -365, -457, -352, +-97, -285, 267, -104, 506, 222, 566, 594, +387, 880, 116, 861, -82, 413, -297, -314, +-479, -1019, -532, -1337, -499, -1083, -241, -378, +262, 460, 702, 1089, 936, 1264, 766, 993, +151, 433, -488, -181, -907, -658, -962, -916, +-564, -899, -5, -662, 427, -322, 693, 41, +650, 379, 407, 661, 133, 854, -162, 850, +-327, 575, -362, 96, -344, -487, -209, -925, +-51, -1024, 76, -798, 162, -364, 144, 143, +88, 589, 52, 851, 60, 861, 139, 586, +219, 123, 155, -366, -51, -713, -289, -764, +-457, -558, -416, -228, -107, 149, 275, 459, +565, 640, 567, 637, 181, 376, -304, -40, +-625, -468, -650, -739, -267, -684, 277, -349, +675, 84, 778, 455, 480, 634, -18, 577, +-442, 382, -691, 99, -703, -243, -481, -506, +-144, -630, 296, -566, 677, -233, 825, 225, +701, 585, 271, 714, -314, 498, -771, 58, +-930, -375, -670, -629, -118, -509, 382, -100, +657, 321, 648, 565, 375, 436, 52, -4, +-143, -392, -246, -488, -215, -241, -158, 156, +-200, 359, -241, 216, -246, -85, -159, -256, +119, -133, 414, 210, 574, 426, 545, 315, +280, -33, -120, -396, -441, -493, -577, -282, +-541, 8, -321, 219, -22, 252, 263, 130, +510, 3, 567, -41, 384, 8, 35, 79, +-366, 101, -531, 51, -413, -51, -114, -183, +259, -261, 456, -186, 353, -30, 83, 127, +-214, 234, -362, 195, -290, 45, -150, -97, +32, -166, 219, -141, 257, -44, 239, 59, +219, 137, 82, 159, -82, 122, -270, 24, +-453, -139, -449, -241, -220, -223, 121, -81, +496, 131, 683, 223, 526, 135, 159, -38, +-284, -131, -615, -65, -616, 82, -391, 175, +-57, 98, 279, -76, 422, -178, 424, -107, +304, 73, 80, 156, -106, 72, -230, -105, +-294, -237, -227, -201, -119, -21, -44, 196, +79, 322, 216, 291, 295, 147, 342, -34, +199, -233, -106, -340, -360, -290, -542, -151, +-464, 64, -99, 230, 248, 265, 459, 201, +499, 81, 332, 1, 154, -2, 17, 28, +-170, 9, -319, -78, -437, -223, -560, -346, +-447, -337, -115, -187, 304, 61, 681, 333, +807, 500, 617, 551, 193, 485, -293, 244, +-676, -106, -766, -489, -509, -823, -105, -924, +303, -690, 578, -163, 541, 505, 264, 1005, +-168, 1076, -544, 687, -569, 18, -264, -541, +189, -685, 618, -423, 730, -19, 472, 200, +-35, 53, -557, -300, -745, -504, -572, -372, +-215, 72, 160, 594, 375, 847, 374, 695, +283, 251, 177, -303, 52, -708, -1, -791, +-35, -545, -131, -65, -154, 394, -173, 624, +-193, 562, -98, 241, 8, -160, 106, -424, +233, -447, 208, -287, 86, -27, 17, 229, +-79, 352, -89, 319, -36, 143, -114, -94, +-207, -268, -236, -325, -123, -205, 244, 51, +567, 295, 610, 439, 348, 374, -174, 83, +-673, -273, -835, -551, -644, -634, -157, -428, +412, -34, 701, 383, 728, 667, 520, 707, +48, 485, -335, 95, -552, -272, -588, -494, +-261, -520, 75, -410, 270, -239, 371, -56, +209, 60, -19, 173, -68, 286, -71, 333, +-1, 338, 85, 322, -15, 235, -132, 55, +-190, -228, -229, -565, -83, -768, 160, -694, +337, -280, 437, 297, 336, 752, 75, 883, +-199, 655, -394, 209, -476, -243, -402, -526, +-230, -611, -25, -492, 249, -228, 466, 68, +597, 306, 621, 386, 293, 273, -189, 48, +-605, -178, -866, -245, -689, -106, -228, 126, +219, 327, 596, 341, 688, 124, 458, -217, +155, -481, -143, -526, -323, -320, -307, 46, +-250, 395, -212, 569, -149, 452, -79, 138, +80, -191, 283, -399, 434, -374, 400, -169, +120, 20, -244, 96, -472, 106, -404, 117, +-95, 233, 211, 359, 294, 288, 146, -27, +-59, -470, -152, -746, -47, -623, 139, -124, +174, 471, 34, 795, -183, 658, -285, 198, +-154, -281, 103, -503, 289, -363, 308, -31, +135, 207, -98, 206, -218, -11, -201, -246, +-89, -264, 36, -49, 101, 251, 95, 434, +45, 338, -56, 8, -133, -330, -99, -508, +-13, -431, 92, -115, 202, 251, 191, 505, +123, 537, 17, 306, -136, -34, -202, -338, +-210, -482, -166, -369, -31, -103, 87, 155, +163, 272, 163, 180, 52, -49, -36, -247, +-52, -290, -20, -123, 64, 205, 96, 475, +16, 539, -40, 385, -91, 42, -117, -339, +-87, -591, -96, -646, -92, -488, -6, -177, +132, 157, 281, 398, 343, 456, 232, 383, +-24, 311, -275, 246, -422, 153, -418, -43, +-214, -368, 58, -648, 292, -665, 434, -366, +415, 103, 202, 476, -98, 533, -354, 296, +-410, 6, -204, -133, 110, -56, 342, 141, +362, 260, 86, 199, -287, -60, -506, -406, +-486, -621, -161, -599, 309, -302, 666, 196, +750, 644, 468, 826, -66, 634, -571, 165, +-808, -337, -642, -613, -171, -529, 349, -184, +622, 196, 534, 374, 186, 264, -191, -35, +-408, -333, -408, -470, -247, -355, 1, -27, +251, 385, 425, 719, 477, 787, 318, 495, +-17, -69, -381, -640, -662, -928, -663, -774, +-307, -280, 158, 244, 564, 544, 729, 551, +532, 335, 117, 58, -321, -141, -587, -224, +-526, -186, -226, -70, 155, 63, 417, 129, +396, 76, 145, -30, -183, -99, -338, -73, +-219, 5, 49, 61, 311, 24, 388, -105, +199, -198, -110, -174, -394, -35, -519, 138, +-377, 263, -48, 288, 266, 215, 486, 78, +534, -99, 387, -249, 129, -312, -168, -261, +-392, -133, -485, -9, -473, 48, -325, 42, +-13, 74, 348, 189, 580, 343, 532, 402, +235, 230, -158, -135, -427, -492, -432, -606, +-194, -393, 106, -7, 239, 294, 108, 337, +-90, 194, -140, 62, -9, 53, 224, 120, +378, 122, 303, -19, 29, -223, -355, -333, +-639, -262, -645, -51, -369, 163, 131, 286, +612, 302, 900, 215, 823, 55, 353, -155, +-257, -323, -764, -358, -905, -227, -634, 11, +-206, 218, 251, 320, 547, 290, 592, 220, +490, 160, 229, 67, -84, -88, -358, -294, +-542, -457, -467, -484, -136, -324, 202, -17, +442, 300, 441, 532, 194, 615, -67, 506, +-238, 228, -282, -148, -167, -524, -61, -733, +-9, -650, 54, -304, 108, 182, 138, 574, +150, 690, 108, 491, 8, 113, -69, -261, +-111, -508, -144, -516, -132, -341, -119, -50, +-150, 243, -92, 391, 56, 370, 252, 190, +442, 0, 484, -77, 304, -48, -44, -37, +-490, -172, -798, -398, -747, -535, -383, -413, +144, -14, 599, 485, 782, 794, 677, 768, +346, 447, -89, -11, -407, -449, -518, -739, +-452, -753, -261, -519, -24, -102, 142, 326, +231, 554, 194, 531, 55, 333, -6, 140, +24, 53, 81, 1, 147, -104, 99, -298, +-43, -509, -177, -549, -311, -317, -291, 93, +-61, 509, 199, 749, 388, 684, 427, 360, +203, -70, -112, -488, -375, -722, -527, -657, +-414, -335, -80, 133, 225, 531, 453, 646, +494, 458, 312, 97, 92, -208, -172, -274, +-381, -179, -377, -89, -277, -86, -93, -131, +138, -110, 232, 49, 227, 251, 113, 318, +-78, 221, -153, 24, -102, -101, 17, -116, +191, -118, 231, -168, 95, -292, -96, -339, +-318, -148, -396, 239, -183, 612, 123, 747, +376, 488, 445, -80, 204, -669, -144, -999, +-400, -857, -439, -289, -190, 419, 185, 923, +420, 965, 462, 527, 276, -108, -69, -613, +-338, -810, -482, -638, -476, -270, -226, 86, +89, 371, 396, 513, 627, 500, 540, 347, +235, 52, -132, -282, -477, -494, -584, -482, +-450, -269, -200, 11, 144, 151, 349, 113, +366, 23, 316, 16, 160, 203, 13, 459, +-81, 536, -211, 299, -223, -183, -200, -673, +-167, -903, -15, -748, 134, -287, 219, 301, +193, 785, 27, 998, -119, 844, -101, 367, +23, -254, 171, -742, 225, -882, 40, -662, +-280, -202, -496, 236, -447, 516, -40, 569, +451, 417, 673, 193, 556, -71, 124, -275, +-375, -306, -615, -209, -542, -36, -201, 127, +232, 166, 423, 110, 370, 25, 176, -36, +-87, -57, -250, -44, -236, -16, -128, 18, +48, 77, 176, 84, 184, 13, 155, -75, +87, -134, -67, -92, -198, 55, -301, 172, +-300, 160, -100, -3, 184, -214, 430, -275, +503, -151, 256, 102, -150, 281, -450, 245, +-513, 57, -257, -152, 114, -216, 367, -166, +369, -118, 130, -156, -155, -193, -279, -73, +-169, 221, 64, 554, 216, 632, 198, 305, +5, -275, -235, -771, -312, -885, -161, -529, +132, 48, 357, 515, 336, 676, 97, 463, +-181, 89, -345, -192, -282, -259, -75, -136, +97, 29, 144, 57, 85, -79, 36, -238, +123, -278, 232, -94, 196, 186, 28, 346, +-256, 320, -473, 124, -444, -87, -213, -163, +156, -116, 484, -43, 538, -10, 372, -13, +78, 13, -229, 101, -441, 179, -457, 159, +-253, 14, 63, -184, 323, -284, 376, -169, +214, 97, -9, 325, -216, 378, -267, 188, +-150, -86, 8, -242, 166, -218, 224, -29, +146, 132, 51, 155, -105, 48, -258, -123, +-230, -205, -86, -144, 154, 34, 342, 233, +260, 318, 23, 208, -253, -21, -428, -229, +-279, -276, 50, -110, 329, 129, 463, 236, +310, 137, 10, -98, -220, -312, -386, -346, +-394, -218, -234, -22, -55, 172, 171, 293, +359, 329, 390, 301, 339, 181, 202, -13, +-43, -201, -252, -344, -419, -424, -510, -441, +-412, -393, -157, -243, 175, 38, 508, 381, +631, 650, 487, 696, 218, 469, -137, 92, +-366, -296, -378, -519, -355, -560, -271, -497, +-143, -376, -35, -228, 169, -3, 332, 271, +359, 521, 316, 599, 173, 448, -14, 154, +-113, -137, -187, -257, -238, -228, -261, -191, +-281, -219, -224, -279, -45, -291, 194, -101, +422, 201, 535, 443, 420, 525, 135, 351, +-249, 87, -578, -125, -607, -212, -355, -186, +31, -124, 386, -81, 462, -88, 307, -55, +49, 53, -165, 234, -179, 396, -114, 357, +-50, 65, -31, -336, -67, -607, -15, -512, +105, -44, 178, 491, 203, 776, 83, 635, +-83, 182, -195, -282, -239, -539, -188, -515, +-83, -325, 19, -109, 109, 67, 189, 192, +253, 277, 223, 295, 115, 244, -20, 132, +-132, 7, -141, -83, -133, -158, -165, -215, +-197, -281, -221, -313, -152, -242, 47, -70, +268, 151, 474, 322, 550, 375, 378, 316, +43, 199, -333, 19, -623, -204, -651, -440, +-429, -628, -53, -605, 337, -283, 532, 224, +466, 674, 270, 848, 22, 618, -178, 123, +-237, -407, -257, -799, -207, -872, -74, -624, +60, -114, 178, 481, 206, 871, 91, 857, +-70, 420, -185, -191, -142, -640, 41, -706, +221, -420, 279, -35, 153, 221, -96, 270, +-369, 192, -501, 122, -381, 102, -52, 119, +380, 122, 731, 83, 737, -4, 391, -142, +-186, -281, -713, -345, -892, -257, -639, -10, +-100, 328, 424, 553, 639, 540, 500, 293, +189, -64, -65, -331, -164, -423, -127, -348, +-54, -200, -33, -22, -54, 141, -118, 320, +-161, 461, -119, 441, -15, 245, 124, -94, +229, -397, 241, -525, 182, -405, 36, -141, +-178, 134, -304, 332, -269, 371, -126, 321, +82, 189, 254, 17, 319, -125, 281, -205, +91, -246, -156, -284, -329, -327, -387, -312, +-273, -112, -48, 262, 128, 661, 254, 797, +263, 519, 200, -51, 177, -617, 146, -864, +30, -745, -131, -384, -332, 17, -423, 295, +-302, 457, -122, 507, 110, 434, 285, 236, +273, -62, 216, -323, 191, -471, 166, -460, +128, -315, -54, -131, -319, 62, -484, 232, +-478, 350, -248, 353, 158, 210, 479, -42, +608, -266, 472, -349, 93, -267, -308, -80, +-568, 88, -564, 185, -270, 214, 162, 243, +523, 222, 587, 92, 339, -166, -69, -466, +-448, -572, -550, -376, -359, 76, 5, 548, +349, 769, 444, 626, 319, 226, 91, -205, +-147, -493, -278, -543, -294, -390, -180, -127, +-13, 163, 98, 354, 160, 385, 155, 272, +109, 83, 32, -58, -52, -107, -67, -78, +-19, -16, 37, 35, 58, 62, -23, 35, +-127, -64, -220, -189, -240, -250, -87, -139, +175, 178, 384, 508, 412, 622, 210, 374, +-88, -144, -325, -642, -397, -837, -272, -605, +-27, -114, 194, 428, 232, 752, 146, 747, +35, 472, -47, -10, -58, -485, -53, -767, +-32, -726, -6, -370, -26, 140, -22, 526, +6, 595, 54, 348, 103, -62, 59, -351, +-29, -400, -99, -232, -126, 7, -91, 182, +-6, 221, 98, 132, 159, -7, 125, -158, +50, -249, -23, -240, -56, -108, -74, 74, +-129, 171, -179, 117, -187, -41, -117, -156, +61, -105, 275, 107, 431, 315, 435, 359, +240, 188, -69, -125, -384, -399, -571, -531, +-554, -475, -349, -229, -18, 96, 321, 411, +520, 615, 546, 600, 388, 389, 110, 64, +-168, -263, -349, -484, -402, -534, -317, -423, +-150, -170, 61, 156, 240, 433, 300, 536, +241, 435, 57, 164, -197, -150, -362, -318, +-354, -314, -137, -134, 220, 99, 492, 225, +568, 227, 382, 79, 1, -117, -361, -225, +-583, -175, -569, 20, -321, 248, -27, 374, +207, 292, 345, 27, 343, -272, 304, -440, +229, -388, 95, -147, -19, 148, -149, 365, +-302, 409, -356, 286, -302, 75, -168, -158, +43, -331, 224, -376, 298, -274, 322, -48, +234, 170, 68, 267, -85, 191, -247, -13, +-315, -177, -262, -204, -172, -91, 24, 62, +251, 152, 356, 134, 344, 31, 171, -75, +-128, -190, -356, -249, -445, -219, -334, -100, +19, 101, 335, 274, 458, 295, 359, 133, +29, -106, -316, -299, -450, -319, -351, -170, +-33, 40, 328, 221, 492, 285, 390, 223, +81, 64, -268, -111, -468, -288, -455, -374, +-255, -323, 78, -150, 362, 146, 467, 437, +387, 622, 154, 577, -140, 282, -345, -162, +-422, -572, -306, -745, -30, -611, 220, -240, +362, 179, 316, 460, 105, 525, -110, 442, +-242, 320, -241, 233, -102, 168, 38, 40, +121, -196, 98, -477, 20, -658, -13, -633, +-19, -359, 23, 86, 96, 518, 109, 826, +78, 911, -31, 702, -177, 258, -281, -334, +-300, -857, -137, -1071, 136, -860, 383, -280, +493, 399, 367, 896, 53, 976, -295, 638, +-486, 59, -425, -500, -197, -785, 94, -705, +286, -314, 288, 146, 166, 458, -20, 491, +-131, 287, -93, 30, -13, -152, 84, -206, +108, -204, 29, -202, -35, -191, -84, -115, +-82, 39, -41, 200, -42, 243, -77, 100, +-116, -135, -97, -298, 53, -258, 244, -36, +337, 231, 270, 358, 81, 255, -159, 10, +-309, -265, -308, -411, -196, -363, -13, -191, +120, 43, 162, 220, 148, 277, 57, 218, +-66, 70, -129, -85, -128, -156, -4, -87, +189, 53, 298, 189, 273, 234, 105, 115, +-139, -113, -323, -325, -390, -424, -342, -352, +-203, -95, -28, 230, 151, 503, 341, 598, +457, 473, 438, 190, 298, -135, 36, -336, +-259, -406, -454, -342, -500, -209, -390, -74, +-165, 85, 90, 231, 287, 333, 353, 344, +303, 265, 171, 108, 34, -47, -32, -137, +-23, -175, -9, -160, -67, -137, -202, -131, +-352, -116, -388, -44, -208, 88, 136, 272, +481, 443, 648, 470, 541, 273, 195, -102, +-288, -510, -694, -775, -812, -735, -565, -382, +-56, 150, 495, 659, 857, 927, 859, 835, +471, 407, -121, -211, -650, -743, -920, -972, +-786, -815, -325, -355, 214, 170, 659, 528, +826, 576, 614, 383, 189, 116, -258, -68, +-541, -106, -527, -82, -328, -83, -77, -157, +158, -260, 240, -290, 199, -206, 152, -68, +63, 79, -37, 177, -90, 233, -105, 287, +-34, 276, 75, 165, 106, -68, 59, -356, +-54, -555, -173, -513, -184, -208, -70, 209, +94, 566, 208, 674, 179, 473, 28, 76, +-113, -321, -185, -532, -160, -481, -26, -239, +111, 46, 222, 235, 252, 286, 113, 240, +-80, 174, -254, 136, -335, 105, -215, 43, +22, -33, 221, -96, 307, -124, 220, -101, +22, -65, -168, -42, -271, -27, -243, -4, +-90, 33, 104, 101, 281, 208, 379, 276, +316, 295, 80, 227, -238, 39, -489, -214, +-535, -429, -338, -503, -16, -363, 289, -40, +469, 286, 463, 484, 300, 457, 53, 224, +-166, -58, -277, -234, -285, -242, -191, -145, +-52, -27, 50, 8, 75, -50, 11, -153, +-56, -189, -59, -109, -3, 71, 114, 294, +240, 384, 297, 267, 221, -44, 6, -407, +-249, -601, -441, -499, -454, -136, -241, 289, +93, 563, 404, 530, 511, 221, 335, -181, +4, -500, -303, -596, -430, -423, -343, -80, +-125, 271, 142, 478, 371, 444, 482, 195, +381, -108, 88, -317, -263, -341, -565, -193, +-654, 11, -412, 159, 19, 184, 427, 111, +617, -18, 496, -142, 205, -180, -81, -102, +-252, 72, -252, 266, -164, 389, -89, 318, +-46, 75, -51, -219, -97, -429, -105, -420, +-24, -198, 103, 117, 235, 347, 305, 421, +263, 329, 133, 148, -46, -3, -191, -128, +-258, -203, -286, -210, -281, -136, -220, 5, +-85, 187, 153, 299, 409, 261, 530, 88, +445, -150, 147, -327, -234, -324, -494, -98, +-547, 222, -368, 455, -30, 476, 258, 218, +394, -185, 374, -486, 175, -537, -72, -334, +-229, 18, -248, 321, -109, 424, 61, 366, +122, 196, 67, -41, -45, -243, -128, -398, +-116, -457, 6, -347, 157, -91, 240, 210, +209, 442, 38, 478, -178, 276, -340, -37, +-378, -322, -215, -468, 98, -433, 413, -234, +549, 6, 410, 163, 53, 243, -344, 203, +-551, 83, -463, -45, -199, -125, 93, -146, +289, -91, 317, 14, 220, 73, 90, 67, +9, -13, -6, -135, 4, -191, -7, -115, +-74, 42, -179, 205, -273, 272, -283, 162, +-151, -54, 82, -245, 291, -286, 397, -139, +334, 118, 137, 343, -27, 404, -128, 269, +-199, 17, -223, -229, -241, -372, -236, -352, +-126, -194, 51, 47, 245, 288, 364, 417, +301, 381, 153, 248, -1, 76, -144, -67, +-230, -119, -252, -151, -194, -211, -70, -262, +65, -233, 154, -99, 141, 145, 80, 382, +26, 482, 15, 429, 78, 238, 142, -7, +111, -216, -46, -360, -250, -442, -363, -425, +-351, -292, -214, -61, 32, 229, 293, 498, +510, 631, 593, 534, 442, 241, 107, -170, +-314, -585, -653, -803, -736, -712, -546, -346, +-168, 160, 270, 592, 589, 721, 669, 519, +537, 116, 229, -310, -179, -547, -486, -524, +-560, -340, -420, -99, -123, 112, 178, 218, +333, 240, 346, 240, 244, 178, 113, 54, +8, -87, -151, -243, -319, -381, -377, -430, +-311, -352, -96, -151, 221, 148, 447, 448, +473, 617, 320, 595, 78, 376, -150, 1, +-321, -428, -398, -744, -349, -858, -213, -683, +-32, -216, 153, 372, 280, 853, 313, 1047, +272, 881, 181, 404, 55, -181, -83, -670, +-210, -939, -289, -883, -288, -533, -188, -3, +-6, 559, 154, 946, 211, 986, 204, 681, +181, 156, 117, -394, 3, -756, -118, -795, +-216, -550, -228, -122, -131, 359, 6, 677, +124, 705, 146, 481, 78, 94, 32, -280, +45, -466, 61, -424, 41, -259, -37, -74, +-155, 81, -183, 195, -76, 314, 59, 431, +144, 402, 129, 164, 16, -225, -83, -601, +-119, -734, -109, -518, -32, -88, 56, 328, +116, 573, 189, 574, 199, 386, 104, 146, +-56, -97, -222, -332, -286, -504, -226, -561, +-117, -498, -12, -287, 66, 15, 143, 311, +251, 538, 338, 648, 304, 547, 112, 219, +-184, -234, -458, -695, -545, -942, -371, -797, +-22, -337, 336, 233, 514, 682, 460, 825, +258, 607, -30, 213, -293, -184, -388, -470, +-327, -556, -195, -490, -54, -340, 23, -118, +93, 149, 239, 405, 390, 596, 470, 628, +371, 403, -2, -25, -468, -490, -755, -800, +-709, -789, -295, -393, 257, 204, 606, 724, +629, 972, 385, 827, 9, 351, -294, -227, +-385, -690, -295, -895, -87, -763, 137, -312, +241, 266, 215, 770, 76, 1003, -109, 834, +-176, 371, -131, -168, -42, -616, 33, -820, +-11, -730, -80, -453, -53, -53, 59, 408, +205, 775, 273, 908, 195, 735, 39, 272, +-103, -327, -183, -808, -185, -979, -170, -786, +-193, -292, -165, 306, -35, 763, 138, 914, +326, 718, 411, 242, 296, -306, 74, -672, +-159, -752, -331, -584, -378, -267, -310, 29, +-143, 220, 113, 366, 311, 473, 345, 480, +268, 370, 93, 96, -92, -304, -167, -626, +-194, -752, -201, -640, -173, -330, -152, 52, +-49, 387, 165, 607, 349, 694, 410, 572, +277, 253, -7, -181, -257, -619, -389, -884, +-387, -830, -252, -473, -49, 48, 150, 570, +311, 895, 394, 877, 345, 514, 170, -50, +-100, -601, -366, -875, -466, -729, -406, -303, +-242, 198, 38, 535, 327, 575, 525, 413, +569, 204, 376, 21, 34, -116, -324, -218, +-607, -322, -654, -349, -440, -204, -90, 48, +284, 309, 557, 464, 612, 415, 457, 181, +153, -67, -202, -228, -450, -261, -502, -155, +-376, -12, -129, 66, 96, 93, 213, 108, +287, 153, 319, 218, 261, 244, 139, 127, +-71, -148, -340, -461, -454, -618, -343, -461, +-90, 29, 215, 612, 367, 968, 321, 907, +169, 404, -44, -323, -157, -917, -145, -1149, +-147, -953, -129, -407, -51, 297, 45, 894, +113, 1187, 131, 1051, 79, 489, -24, -295, +-110, -974, -121, -1279, -33, -1070, 66, -438, +87, 321, 74, 879, 11, 1041, -73, 752, +-80, 160, -42, -436, 19, -778, 116, -779, +145, -458, 80, -7, -35, 335, -171, 480, +-236, 451, -203, 286, -114, 71, 55, -153, +222, -378, 262, -558, 231, -576, 169, -383, +60, 10, -63, 498, -175, 858, -242, 919, +-243, 658, -197, 116, -128, -534, -34, -1039, +98, -1206, 208, -975, 297, -363, 336, 439, +247, 1121, 98, 1442, -97, 1298, -310, 686, +-410, -184, -396, -986, -274, -1463, -18, -1403, +261, -783, 464, 127, 506, 963, 317, 1402, +-9, 1261, -303, 648, -452, -71, -390, -640, +-169, -919, 50, -885, 183, -641, 229, -256, +204, 262, 164, 812, 128, 1157, 44, 1094, +-81, 549, -197, -320, -277, -1102, -249, -1427, +-114, -1158, 21, -432, 156, 420, 232, 1052, +216, 1282, 178, 1096, 88, 574, -43, -124, +-137, -779, -227, -1202, -266, -1261, -158, -880, +34, -168, 224, 621, 335, 1227, 264, 1394, +58, 1021, -179, 231, -380, -687, -410, -1392, +-243, -1591, 18, -1200, 280, -382, 447, 602, +481, 1411, 400, 1754, 192, 1509, -147, 705, +-488, -438, -719, -1540, -771, -2178, -525, -2051, +-33, -1140, 530, 260, 974, 1616, 1067, 2360, +765, 2204, 179, 1243, -518, -134, -1046, -1391, +-1209, -2081, -939, -2013, -305, -1277, 448, -166, +1038, 921, 1247, 1639, 1001, 1794, 387, 1350, +-380, 470, -1001, -533, -1241, -1348, -1009, -1706, +-419, -1449, 307, -638, 919, 425, 1165, 1358, +962, 1810, 465, 1579, -133, 771, -659, -282, +-965, -1220, -976, -1736, -734, -1680, -276, -1069, +322, -80, 871, 1006, 1204, 1831, 1162, 2085, +680, 1630, -94, 549, -936, -807, -1528, -1928, +-1549, -2384, -968, -1975, 12, -784, 1068, 762, +1771, 2054, 1795, 2584, 1124, 2094, -12, 767, +-1161, -856, -1838, -2097, -1799, -2448, -1091, -1811, +-1, -521, 1012, 851, 1610, 1791, 1605, 2015, +1015, 1521, 132, 557, -700, -545, -1224, -1444, +-1289, -1845, -941, -1593, -355, -790, 293, 287, +776, 1240, 984, 1726, 940, 1579, 614, 895, +93, -76, -427, -1008, -841, -1596, -994, -1688, +-808, -1238, -378, -336, 215, 720, 777, 1579, +1064, 1909, 1014, 1535, 607, 553, -93, -686, +-790, -1721, -1213, -2133, -1202, -1735, -706, -659, +81, 701, 812, 1808, 1231, 2211, 1216, 1775, +762, 652, 35, -718, -707, -1813, -1213, -2220, +-1242, -1778, -819, -637, -128, 760, 626, 1865, +1103, 2233, 1152, 1701, 805, 505, 187, -841, +-415, -1796, -835, -1990, -972, -1404, -781, -335, +-388, 785, 114, 1561, 591, 1722, 839, 1261, +786, 368, 491, -632, 91, -1343, -297, -1493, +-575, -1068, -660, -250, -573, 609, -355, 1171, +-45, 1271, 279, 919, 546, 267, 675, -441, +597, -993, 312, -1213, -94, -991, -509, -385, +-749, 423, -709, 1137, -408, 1427, 65, 1161, +495, 407, 687, -557, 594, -1342, 307, -1609, +-19, -1240, -281, -359, -424, 690, -457, 1463, +-419, 1623, -289, 1124, -7, 191, 362, -784, +631, -1397, 669, -1454, 408, -966, -45, -116, +-437, 755, -629, 1320, -590, 1351, -333, 810, +-31, -117, 227, -1034, 427, -1515, 498, -1327, +451, -525, 281, 521, -30, 1316, -360, 1526, +-572, 1105, -579, 255, -372, -669, -13, -1333, +366, -1526, 616, -1158, 660, -355, 428, 606, +3, 1393, -416, 1670, -705, 1292, -725, 399, +-448, -694, -43, -1547, 393, -1762, 733, -1272, +818, -261, 648, 877, 240, 1651, -317, 1756, +-786, 1178, -1014, 130, -868, -977, -352, -1702, +289, -1773, 814, -1188, 1045, -133, 896, 1042, +451, 1883, -144, 2059, -702, 1465, -1039, 217, +-1016, -1218, -593, -2232, 97, -2394, 766, -1575, +1150, -47, 1104, 1544, 604, 2544, -155, 2547, +-853, 1517, -1267, -164, -1227, -1800, -694, -2729, +137, -2562, 978, -1322, 1500, 491, 1435, 2112, +794, 2885, -156, 2462, -1072, 1024, -1600, -810, +-1513, -2320, -892, -2903, 22, -2332, 954, -884, +1556, 919, 1624, 2379, 1110, 2926, 159, 2390, +-874, 943, -1586, -911, -1699, -2453, -1165, -3118, +-204, -2628, 816, -1106, 1528, 894, 1679, 2593, +1202, 3315, 278, 2715, -773, 1020, -1548, -1097, +-1716, -2763, -1213, -3279, -211, -2481, 866, -749, +1574, 1190, 1653, 2559, 1097, 2889, 144, 2125, +-854, 611, -1527, -1083, -1623, -2326, -1108, -2660, +-138, -1975, 890, -560, 1584, 1066, 1652, 2252, +1044, 2528, 71, 1850, -893, 461, -1529, -1109, +-1555, -2231, -1033, -2490, -178, -1807, 757, -410, +1412, 1205, 1569, 2364, 1177, 2609, 338, 1824, +-629, 255, -1365, -1455, -1628, -2536, -1309, -2595, +-485, -1606, 521, 79, 1358, 1697, 1753, 2580, +1478, 2411, 595, 1225, -539, -443, -1471, -1809, +-1825, -2299, -1432, -1808, -500, -643, 557, 618, +1330, 1441, 1566, 1621, 1275, 1262, 583, 549, +-281, -255, -941, -893, -1270, -1267, -1230, -1244, +-753, -742, -76, 49, 555, 841, 1005, 1335, +1081, 1255, 822, 626, 396, -195, -148, -860, +-640, -1149, -904, -967, -935, -451, -670, 106, +-165, 558, 324, 809, 703, 765, 891, 510, +786, 149, 481, -259, 67, -575, -416, -712, +-795, -663, -956, -406, -839, 13, -401, 448, +180, 721, 665, 716, 988, 423, 997, -54, +701, -462, 250, -610, -334, -532, -879, -292, +-1185, 11, -1193, 204, -746, 280, 73, 322, +948, 315, 1560, 292, 1581, 246, 944, 63, +-99, -288, -1166, -670, -1802, -909, -1713, -833, +-930, -322, 262, 480, 1383, 1225, 1967, 1606, +1758, 1387, 815, 522, -448, -685, -1557, -1720, +-2106, -2188, -1793, -1836, -786, -689, 562, 833, +1770, 2149, 2262, 2760, 1863, 2290, 710, 775, +-821, -1158, -2025, -2717, -2415, -3225, -1788, -2324, +-329, -392, 1255, 1728, 2272, 3204, 2338, 3394, +1376, 2141, -197, 12, -1663, -2173, -2406, -3599, +-2122, -3592, -907, -2095, 698, 311, 2000, 2753, +2467, 4213, 1879, 3968, 499, 2065, -1108, -764, +-2275, -3431, -2498, -4795, -1663, -4220, -137, -1899, +1455, 1286, 2494, 4109, 2497, 5304, 1434, 4282, +-161, 1477, -1732, -2018, -2676, -4776, -2515, -5530, +-1320, -4002, 449, -888, 2091, 2620, 2903, 5102, +2578, 5480, 1160, 3695, -761, 475, -2379, -3024, +-3132, -5373, -2596, -5553, -945, -3571, 1014, -139, +2619, 3470, 3245, 5640, 2490, 5487, 773, 3195, +-1271, -400, -2911, -3832, -3294, -5600, -2317, -5120, +-432, -2697, 1709, 798, 3156, 3943, 3286, 5395, +2087, 4688, 11, 2147, -2149, -1315, -3478, -4163, +-3379, -5177, -1901, -4119, 420, -1434, 2671, 1832, +3859, 4225, 3532, 4833, 1736, 3563, -841, 853, +-3083, -2227, -4153, -4284, -3569, -4544, -1498, -3025, +1112, -228, 3309, 2653, 4262, 4268, 3447, 4120, +1254, 2314, -1404, -502, -3514, -2956, -4135, -3952, +-3035, -3304, -786, -1298, 1724, 1182, 3491, 2923, +3773, 3331, 2538, 2415, 343, 499, -1987, -1545, +-3451, -2772, -3441, -2812, -2071, -1713, 145, 154, +2302, 1895, 3405, 2770, 3091, 2555, 1516, 1242, +-656, -699, -2470, -2326, -3207, -2944, -2622, -2317, +-1020, -623, 924, 1369, 2492, 2673, 3014, 2828, +2269, 1825, 617, 2, -1266, -1778, -2628, -2704, +-2820, -2559, -1780, -1321, -44, 561, 1678, 2098, +2646, 2673, 2420, 2155, 1169, 605, -539, -1249, +-1950, -2419, -2443, -2516, -1880, -1523, -535, 244, +987, 1841, 1992, 2481, 2054, 2066, 1273, 764, +37, -942, -1162, -2126, -1781, -2347, -1620, -1689, +-910, -268, 148, 1336, 1178, 2268, 1680, 2260, +1539, 1344, 797, -279, -401, -1786, -1424, -2397, +-1811, -2041, -1469, -832, -430, 832, 789, 2053, +1618, 2304, 1802, 1678, 1197, 294, 123, -1277, +-943, -2166, -1643, -2138, -1659, -1298, -1049, 181, +-54, 1570, 1014, 2165, 1670, 1881, 1620, 794, +949, -734, -77, -1780, -1069, -1871, -1567, -1161, +-1417, 115, -815, 1270, 128, 1560, 994, 1057, +1329, 89, 1213, -935, 713, -1359, -102, -966, +-815, -128, -1196, 795, -1153, 1384, -604, 1269, +220, 559, 923, -380, 1200, -1238, 956, -1614, +312, -1253, -512, -359, -1068, 718, -1069, 1586, +-665, 1773, 11, 1127, 646, -38, 858, -1189, +805, -1793, 577, -1483, 121, -401, -299, 801, +-612, 1541, -862, 1523, -851, 690, -503, -454, +-4, -1295, 574, -1573, 1082, -1104, 1161, -71, +732, 934, 68, 1566, -650, 1570, -1162, 827, +-1201, -288, -795, -1313, -132, -1859, 643, -1574, +1228, -541, 1324, 760, 899, 1756, 146, 1941, +-726, 1189, -1438, -118, -1620, -1403, -1119, -2088, +-123, -1785, 1044, -612, 1873, 890, 1942, 2090, +1252, 2336, 16, 1437, -1289, -167, -2142, -1794, +-2215, -2681, -1397, -2333, -48, -961, 1312, 845, +2286, 2372, 2409, 2910, 1603, 2226, 212, 626, +-1349, -1319, -2444, -2801, -2519, -3117, -1641, -2101, +-94, -174, 1553, 1898, 2488, 3182, 2404, 3036, +1368, 1580, -271, -561, -1729, -2476, -2419, -3211, +-2056, -2490, -803, -712, 691, 1393, 1844, 2829, +2152, 2913, 1491, 1720, 307, -247, -948, -2130, +-1783, -2962, -1775, -2379, -1048, -704, 48, 1314, +1118, 2676, 1660, 2737, 1446, 1580, 664, -252, +-390, -1969, -1256, -2773, -1483, -2358, -1047, -921, +-192, 1000, 759, 2555, 1313, 2987, 1211, 2065, +568, 135, -354, -1983, -1183, -3251, -1414, -3001, +-917, -1326, 66, 1044, 1153, 3024, 1697, 3602, +1356, 2508, 345, 278, -950, -2150, -1843, -3631, +-1833, -3472, -1009, -1834, 333, 642, 1580, 2912, +2074, 3869, 1689, 3135, 605, 1030, -835, -1601, +-1929, -3508, -2149, -3798, -1466, -2426, -117, 20, +1343, 2438, 2180, 3657, 2050, 3254, 1042, 1479, +-422, -983, -1728, -2966, -2283, -3602, -1875, -2773, +-711, -709, 776, 1737, 2022, 3366, 2484, 3571, +1919, 2260, 480, -144, -1230, -2496, -2452, -3697, +-2633, -3329, -1702, -1479, -38, 1095, 1650, 3060, +2600, 3592, 2431, 2641, 1227, 484, -478, -1878, +-1856, -3226, -2366, -3207, -1911, -1831, -656, 490, +826, 2514, 1838, 3327, 2007, 2741, 1303, 859, +47, -1453, -1083, -2968, -1629, -3135, -1487, -1970, +-702, 135, 369, 2133, 1205, 3036, 1493, 2674, +1079, 1190, 121, -865, -853, -2412, -1388, -2848, +-1313, -2142, -584, -441, 471, 1467, 1319, 2638, +1601, 2698, 1128, 1577, 75, -302, -1016, -1998, +-1683, -2773, -1687, -2346, -1001, -880, 169, 962, +1322, 2287, 1958, 2604, 1874, 1860, 967, 345, +-361, -1203, -1468, -2131, -2094, -2229, -1939, -1431, +-919, -122, 416, 1059, 1586, 1806, 2196, 1843, +1830, 1129, 689, 78, -617, -940, -1714, -1564, +-2095, -1487, -1489, -807, -328, 92, 901, 836, +1774, 1148, 1818, 945, 1104, 426, 28, -111, +-1069, -511, -1743, -697, -1651, -659, -909, -479, +142, -184, 1190, 191, 1771, 526, 1559, 721, +777, 647, -259, 287, -1244, -177, -1648, -586, +-1351, -764, -667, -599, 250, -259, 1064, 124, +1298, 487, 1068, 617, 569, 495, -140, 294, +-687, -42, -854, -415, -778, -535, -478, -470, +-29, -254, 311, 200, 453, 527, 505, 506, +384, 305, 153, -95, -1, -523, -174, -577, +-321, -333, -320, 46, -285, 515, -168, 752, +49, 597, 240, 219, 376, -306, 399, -779, +247, -894, -60, -643, -376, -97, -516, 602, +-462, 1084, -205, 1142, 212, 672, 535, -228, +616, -1038, 444, -1393, 36, -1117, -388, -186, +-572, 867, -513, 1505, -276, 1511, 21, 713, +278, -531, 385, -1535, 369, -1874, 299, -1297, +143, 17, -40, 1426, -182, 2216, -375, 1989, +-498, 787, -417, -959, -237, -2358, 55, -2678, +464, -1775, 740, 104, 812, 2081, 615, 3078, +-1, 2672, -758, 966, -1243, -1315, -1284, -2992, +-697, -3308, 294, -2109, 1152, 109, 1615, 2302, +1397, 3464, 540, 3033, -516, 1229, -1418, -1187, +-1777, -3170, -1416, -3699, -504, -2559, 725, -245, +1749, 2372, 2081, 3931, 1523, 3598, 165, 1614, +-1332, -1249, -2237, -3646, -2221, -4225, -1135, -2816, +530, -144, 1899, 2717, 2516, 4310, 2028, 3775, +496, 1584, -1180, -1375, -2325, -3879, -2573, -4457, +-1598, -2918, 111, -148, 1686, 2888, 2645, 4625, +2471, 4029, 1044, 1730, -738, -1373, -2148, -4002, +-2795, -4567, -2108, -3043, -450, -304, 1266, 2650, +2602, 4261, 2805, 3794, 1545, 1769, -288, -1000, +-1955, -3208, -2911, -3730, -2407, -2520, -742, -205, +1113, 2083, 2578, 3162, 2910, 2637, 1729, 875, +-175, -1187, -1979, -2469, -3009, -2459, -2575, -1230, +-898, 571, 1144, 1945, 2740, 2315, 3107, 1576, +1965, 80, -49, -1314, -1994, -1958, -3099, -1698, +-2825, -674, -1274, 537, 747, 1312, 2469, 1389, +3238, 850, 2548, 58, 745, -539, -1339, -696, +-2979, -462, -3338, -155, -2135, -4, -49, -23, +2104, -166, 3423, -212, 3100, 57, 1374, 436, +-903, 647, -2824, 612, -3421, 129, -2372, -629, +-311, -979, 1853, -845, 3149, -298, 2859, 645, +1204, 1124, -897, 849, -2528, 271, -2887, -643, +-1736, -1216, 223, -868, 1970, -173, 2694, 690, +2010, 1301, 200, 932, -1731, -23, -2723, -1008, +-2279, -1594, -479, -1167, 1712, 105, 2964, 1456, +2689, 2119, 913, 1579, -1562, 23, -3238, -1846, +-3216, -2839, -1536, -2200, 1090, -358, 3201, 1915, +3649, 3377, 2342, 2852, -141, 830, -2655, -1613, +-3871, -3393, -3229, -3225, -1119, -1285, 1504, 1097, +3440, 2861, 3795, 3048, 2553, 1519, 288, -497, +-2156, -1817, -3621, -2078, -3587, -1236, -2252, -8, +101, 601, 2431, 690, 3738, 582, 3765, 384, +2158, 511, -563, 651, -2986, 221, -4271, -498, +-3786, -1227, -1434, -1534, 1526, -801, 3814, 531, +4509, 1658, 3052, 2024, 169, 1179, -2682, -369, +-4283, -1692, -3848, -2178, -1690, -1435, 1037, 24, +3156, 1341, 3771, 2006, 2751, 1597, 672, 430, +-1521, -745, -2873, -1500, -3009, -1477, -1980, -774, +-189, 121, 1582, 889, 2712, 1218, 2710, 968, +1362, 323, -631, -524, -2228, -1168, -2757, -1185, +-1860, -582, -4, 425, 1736, 1309, 2529, 1403, +1933, 671, 265, -513, -1401, -1545, -2167, -1639, +-1692, -709, -292, 615, 1173, 1650, 1880, 1721, +1511, 721, 258, -678, -1205, -1699, -1984, -1855, +-1619, -1068, -270, 248, 1375, 1453, 2283, 2031, +1964, 1751, 624, 679, -1212, -790, -2484, -2059, +-2394, -2487, -1143, -1813, 769, -261, 2377, 1595, +2544, 2770, 1424, 2574, -269, 1193, -1900, -823, +-2440, -2449, -1582, -2657, -84, -1556, 1399, 175, +2163, 1733, 1701, 2184, 465, 1478, -797, 278, +-1704, -849, -1826, -1385, -1124, -1233, -41, -681, +1037, -2, 1787, 539, 1849, 985, 1099, 1222, +-97, 967, -1326, 333, -2225, -678, -2116, -1684, +-1021, -1771, 490, -894, 1950, 547, 2613, 1961, +2084, 2183, 661, 1021, -1104, -618, -2398, -1935, +-2651, -2040, -1774, -760, -65, 842, 1674, 1813, +2690, 1722, 2482, 633, 1052, -741, -948, -1540, +-2514, -1562, -2756, -1055, -1548, -33, 586, 1092, +2512, 1833, 2962, 2142, 1755, 1372, -557, -569, +-2703, -2516, -3254, -3563, -2045, -2805, 382, -40, +2713, 3080, 3465, 4677, 2555, 3880, 362, 815, +-2129, -2879, -3423, -4965, -3124, -4528, -1504, -1963, +928, 1509, 2903, 4029, 3495, 4563, 2649, 3168, +517, 495, -2003, -2277, -3502, -4058, -3377, -4093, +-1705, -2339, 921, 431, 3101, 3098, 3662, 4290, +2438, 3342, -9, 779, -2473, -2162, -3604, -3965, +-2842, -3729, -650, -1572, 1840, 1358, 3358, 3460, +3139, 3803, 1272, 2205, -1240, -556, -3000, -2898, +-3307, -3717, -1946, -2730, 433, -381, 2410, 2014, +3291, 3278, 2682, 3022, 536, 1396, -1761, -777, +-3110, -2474, -3097, -3070, -1415, -2296, 1027, -509, +2839, 1623, 3334, 3182, 2107, 3178, -366, 1629, +-2534, -890, -3350, -3250, -2605, -3808, -462, -2317, +1901, 400, 3200, 3056, 3038, 3902, 1488, 2573, +-870, 113, -2812, -2250, -3327, -3249, -2399, -2383, +-351, -467, 2054, 1293, 3390, 2278, 3051, 2105, +1394, 809, -1153, -563, -3161, -1438, -3360, -1788, +-2078, -1114, 283, 70, 2652, 943, 3330, 1513, +2393, 1291, 378, 361, -1961, -430, -3012, -1007, +-2375, -1100, -599, -614, 1410, -148, 2366, 186, +1925, 413, 494, 456, -1009, 460, -1688, 484, +-1306, 423, -237, 129, 715, -309, 1054, -785, +732, -1126, 60, -885, -393, -167, -459, 665, +-252, 1356, 42, 1348, 114, 564, 5, -464, +-182, -1286, -354, -1515, -189, -996, 225, -4, +654, 963, 927, 1454, 660, 1346, -133, 629, +-1026, -471, -1616, -1343, -1313, -1673, -102, -1298, +1192, -176, 2083, 1006, 1909, 1671, 416, 1600, +-1259, 668, -2250, -541, -2134, -1287, -722, -1338, +1044, -778, 2131, 40, 2163, 650, 1006, 805, +-775, 662, -1909, 284, -1924, -165, -1124, -355, +369, -442, 1613, -308, 1726, 107, 1091, 260, +-124, 274, -1279, 172, -1505, -176, -1010, -277, +-61, -153, 941, 35, 1336, 319, 998, 400, +230, 197, -635, -86, -1190, -305, -1049, -488, +-367, -430, 370, -8, 984, 366, 1036, 683, +473, 843, -104, 421, -669, -311, -849, -921, +-455, -1072, -139, -629, 166, 161, 429, 863, +330, 943, 334, 477, 458, -54, 169, -380, +-173, -304, -504, -25, -891, 56, -718, -163, +-123, -427, 556, -459, 1157, -148, 1087, 482, +471, 889, -459, 651, -1273, 39, -1250, -658, +-693, -1018, 214, -704, 1109, 56, 1253, 760, +862, 964, 72, 633, -760, -31, -1017, -694, +-779, -969, -325, -813, 229, -303, 544, 264, +533, 644, 517, 907, 375, 849, -41, 380, +-392, -204, -634, -875, -704, -1405, -278, -1182, +287, -297, 663, 758, 828, 1685, 397, 1745, +-295, 664, -693, -665, -694, -1715, -251, -2064, +269, -1087, 511, 438, 405, 1549, 123, 2095, +-103, 1565, -321, 178, -292, -1100, -2, -1947, +76, -1938, 145, -984, 185, 341, 16, 1623, +-30, 2195, -26, 1698, -89, 445, -53, -1057, +-27, -2033, -162, -2005, -191, -1018, -42, 478, +97, 1691, 432, 2064, 692, 1437, 377, 97, +-146, -1245, -688, -1938, -1031, -1659, -670, -493, +-23, 897, 677, 1727, 1116, 1777, 819, 936, +253, -433, -415, -1360, -908, -1601, -904, -1208, +-548, -208, 137, 773, 750, 1289, 945, 1342, +790, 904, 107, 90, -683, -775, -1067, -1399, +-921, -1508, -101, -905, 728, 177, 1052, 1264, +849, 1815, -23, 1460, -770, 357, -920, -1009, +-613, -1826, 103, -1697, 651, -818, 785, 580, +578, 1645, -55, 1694, -534, 998, -688, -180, +-534, -1318, -114, -1655, 186, -1191, 450, -294, +535, 757, 309, 1376, 163, 1274, 2, 804, +-245, -33, -366, -959, -534, -1288, -661, -1249, +-340, -814, 302, 220, 1017, 1079, 1268, 1433, +772, 1296, -135, 431, -1120, -678, -1561, -1336, +-1188, -1386, -235, -793, 879, 229, 1496, 973, +1394, 1159, 757, 941, -250, 198, -1115, -617, +-1451, -962, -1288, -1017, -552, -556, 599, 319, +1478, 949, 1645, 1265, 1064, 921, -156, -87, +-1294, -953, -1639, -1464, -1304, -1229, -358, -96, +910, 1014, 1609, 1577, 1445, 1399, 709, 404, +-515, -758, -1461, -1446, -1563, -1380, -1026, -674, +109, 273, 1220, 1078, 1619, 1332, 1296, 1036, +338, 429, -834, -397, -1446, -1064, -1380, -1255, +-864, -992, 66, -275, 1014, 640, 1482, 1258, +1364, 1241, 638, 645, -512, -166, -1394, -867, +-1567, -1068, -970, -671, 145, -84, 1026, 389, +1298, 625, 847, 562, 54, 246, -512, -88, +-740, -273, -483, -460, -88, -429, -36, -116, +77, 94, 199, 382, 208, 535, 381, 208, +296, -82, -65, -334, -208, -559, -354, -344, +-446, 1, -118, 272, 153, 497, 115, 413, +264, 93, 286, -281, 96, -610, 123, -640, +-27, -292, -294, 238, -252, 690, -304, 843, +-260, 551, 188, -47, 348, -614, 303, -923, +362, -802, 117, -410, -339, 94, -406, 706, +-329, 982, -253, 830, 241, 478, 457, -250, +273, -947, 200, -1071, -153, -764, -353, -90, +-150, 663, -83, 934, -22, 727, 157, 272, +98, -267, -26, -529, 123, -445, 152, -329, +-84, -117, -118, 169, -167, 319, -193, 479, +43, 413, 169, 5, 210, -330, 150, -560, +-43, -462, -61, 145, 19, 587, -20, 544, +-175, 176, -306, -444, -311, -766, -66, -354, +408, 356, 734, 918, 583, 942, 75, 120, +-555, -843, -873, -1229, -573, -990, -33, 24, +474, 1145, 642, 1344, 308, 793, -57, -130, +-189, -1061, -128, -1105, 69, -388, 9, 278, +-289, 738, -331, 571, -230, -157, 101, -475, +703, -323, 781, 71, 314, 591, -269, 597, +-999, 26, -1220, -623, -593, -926, 245, -535, +1157, 174, 1580, 669, 1035, 788, 137, 351, +-983, -259, -1897, -446, -1587, -287, -469, -1, +720, 196, 1751, 30, 1784, -318, 787, -483, +-417, -359, -1414, 84, -1589, 658, -820, 873, +151, 558, 940, 73, 1202, -489, 757, -967, +86, -850, -500, -358, -772, 108, -654, 593, +-373, 784, 61, 489, 403, 93, 557, -188, +603, -291, 436, -108, -23, 58, -562, -106, +-859, -386, -786, -596, -255, -534, 637, 155, +1168, 1090, 963, 1494, 256, 1088, -817, -114, +-1435, -1584, -942, -2279, -37, -1633, 930, 163, +1469, 2087, 847, 2857, -152, 2006, -766, -130, +-1110, -2342, -734, -3144, 3, -2100, 273, 220, +425, 2368, 539, 3020, 418, 1981, 476, -179, +357, -2124, -268, -2633, -806, -1633, -1143, 152, +-1025, 1701, -130, 2246, 941, 1502, 1598, -38, +1445, -1380, 485, -2003, -770, -1515, -1627, -91, +-1619, 1265, -791, 1960, 434, 1563, 1324, 106, +1449, -1328, 938, -1914, 44, -1420, -732, -6, +-952, 1364, -853, 1795, -586, 1142, -163, -219, +233, -1354, 692, -1568, 1064, -937, 970, 212, +505, 1212, -308, 1437, -1253, 907, -1556, -23, +-1079, -970, -101, -1507, 962, -1208, 1492, -253, +1359, 732, 642, 1447, -260, 1374, -952, 419, +-1334, -568, -1143, -1222, -528, -1269, 299, -462, +1175, 462, 1433, 957, 958, 952, 76, 326, +-1003, -475, -1487, -953, -1103, -886, -95, -264, +1058, 471, 1409, 1072, 938, 1200, 46, 569, +-978, -307, -1283, -1123, -892, -1511, -193, -1036, +706, -174, 1087, 758, 944, 1420, 497, 1289, +-367, 777, -829, 75, -864, -755, -711, -1114, +-60, -1118, 532, -871, 776, -159, 747, 594, +223, 1105, -291, 1352, -464, 1028, -499, 199, +-313, -715, -52, -1433, 67, -1619, 139, -1012, +194, 144, 276, 1282, 385, 1969, 415, 1800, +210, 663, -260, -814, -794, -1974, -1022, -2298, +-749, -1460, -7, 57, 912, 1543, 1408, 2383, +1177, 2070, 395, 900, -732, -573, -1550, -1852, +-1363, -2295, -514, -1764, 525, -581, 1299, 842, +1206, 1983, 523, 2275, -298, 1591, -932, 293, +-947, -1224, -472, -2265, 130, -2223, 528, -1239, +580, 306, 397, 1760, 73, 2291, -137, 1695, +-180, 385, -266, -950, -209, -1757, -131, -1666, +-170, -814, -37, 46, 151, 681, 248, 1036, +378, 916, 349, 710, 165, 495, -37, -6, +-428, -647, -673, -1213, -587, -1458, -417, -1072, +122, -76, 864, 1112, 1134, 1866, 944, 1820, +266, 979, -763, -410, -1409, -1674, -1384, -2168, +-713, -1760, 402, -552, 1263, 1007, 1506, 2064, +1116, 2158, 197, 1308, -819, -156, -1389, -1481, +-1383, -2058, -876, -1693, 138, -646, 1166, 523, +1584, 1367, 1402, 1625, 551, 1363, -722, 744, +-1538, -122, -1629, -1024, -1074, -1782, 44, -2001, +1009, -1347, 1344, -10, 1246, 1622, 658, 2760, +-142, 2650, -549, 1349, -856, -651, -975, -2485, +-672, -3215, -435, -2492, 45, -721, 701, 1268, +990, 2674, 1160, 2967, 828, 2025, -38, 414, +-808, -1170, -1418, -2365, -1400, -2666, -639, -1887, +329, -541, 1270, 1065, 1611, 2419, 1140, 2719, +193, 1935, -935, 365, -1529, -1530, -1346, -2741, +-688, -2693, 367, -1485, 1235, 422, 1351, 2101, +966, 2781, 219, 2191, -589, 644, -937, -1010, +-943, -2199, -786, -2498, -295, -1673, 212, -308, +605, 1107, 1058, 2174, 1133, 2301, 700, 1506, +-78, 129, -1101, -1323, -1624, -2176, -1354, -2068, +-457, -1082, 874, 233, 1718, 1331, 1607, 1725, +763, 1205, -493, 400, -1459, -299, -1632, -786, +-1004, -694, 91, -343, 1101, -209, 1549, -123, +1209, -104, 356, -122, -675, 94, -1446, 437, +-1453, 644, -764, 575, 253, 191, 1107, -344, +1506, -783, 1192, -749, 150, -301, -782, 138, +-1246, 601, -1287, 737, -546, 288, 423, -37, +993, -245, 1127, -429, 611, -210, -202, -37, +-662, -85, -762, -98, -505, -144, 9, -61, +249, 312, 227, 661, 265, 752, 274, 604, +397, 57, 516, -759, 118, -1257, -549, -1353, +-1177, -967, -1416, 7, -695, 1077, 588, 1914, +1737, 2096, 2235, 1355, 1443, 20, -182, -1590, +-1843, -2759, -2834, -2780, -2255, -1616, -441, 481, +1575, 2562, 3020, 3614, 2955, 3187, 1218, 1164, +-1118, -1537, -2929, -3565, -3324, -4104, -1890, -2797, +477, -172, 2439, 2566, 3271, 4181, 2409, 3974, +340, 2026, -1629, -819, -2776, -3248, -2635, -4310, +-1185, -3536, 635, -1097, 2059, 1685, 2565, 3568, +1738, 3967, 138, 2490, -1351, -53, -2235, -2249, +-1812, -3250, -378, -2684, 936, -990, 1697, 760, +1442, 1814, 255, 1803, -852, 977, -1378, 129, +-969, -376, 132, -435, 961, -210, 1273, -183, +910, -385, -118, -653, -1114, -849, -1609, -580, +-1372, 116, -334, 853, 983, 1418, 1963, 1568, +2190, 1086, 1240, 31, -540, -1172, -2068, -2102, +-2797, -2433, -2216, -1713, -262, -103, 1782, 1771, +2975, 3184, 2812, 3334, 1092, 1960, -1067, -433, +-2595, -2900, -2958, -4230, -1777, -3622, 228, -1343, +1840, 1607, 2443, 3941, 2026, 4465, 740, 2949, +-813, 271, -1586, -2514, -1687, -4076, -1405, -3717, +-451, -2038, 469, 397, 1077, 2621, 1583, 3449, +1372, 2974, 681, 1588, -196, -468, -1348, -2168, +-1858, -2803, -1427, -2586, -541, -1471, 711, 244, +1737, 1635, 1806, 2472, 1141, 2602, -20, 1620, +-1288, 77, -1798, -1537, -1472, -2803, -569, -2831, +720, -1592, 1516, 378, 1528, 2286, 919, 3157, +-194, 2501, -1063, 678, -1315, -1362, -1040, -2675, +-237, -2670, 499, -1417, 854, 285, 966, 1709, +648, 2283, 113, 1766, -336, 633, -697, -688, +-846, -1663, -728, -1821, -307, -1218, 306, -54, +779, 1098, 1048, 1682, 922, 1507, 348, 567, +-395, -689, -1071, -1549, -1321, -1722, -1025, -1103, +-303, 123, 731, 1251, 1499, 1864, 1543, 1669, +980, 702, -80, -483, -1234, -1531, -1832, -2067, +-1624, -1699, -686, -770, 649, 464, 1629, 1776, +1920, 2408, 1533, 2096, 371, 930, -1070, -817, +-1847, -2350, -1931, -2817, -1339, -2080, 18, -431, +1217, 1451, 1784, 2508, 1814, 2460, 979, 1532, +-138, 15, -946, -1287, -1577, -2015, -1529, -2167, +-975, -1505, -288, -342, 683, 981, 1399, 2161, +1633, 2423, 1420, 1717, 492, 328, -563, -1289, +-1459, -2238, -1957, -2248, -1606, -1464, -777, -169, +407, 1014, 1606, 1792, 2117, 2028, 2099, 1540, +1218, 573, -451, -643, -1827, -1659, -2672, -2027, +-2496, -1597, -1054, -486, 711, 643, 2190, 1378, +2771, 1577, 2018, 1133, 645, 485, -776, -100, +-1857, -651, -2214, -969, -1671, -1101, -613, -949, +408, -432, 1389, 117, 1928, 679, 1549, 1116, +763, 1193, -193, 1026, -1126, 596, -1514, -164, +-1434, -1144, -1009, -1924, -253, -2069, 551, -1356, +1295, 185, 1793, 1869, 1683, 2832, 881, 2706, +-508, 1254, -1800, -825, -2346, -2373, -2047, -3064, +-746, -2512, 1017, -831, 2114, 957, 2369, 2296, +1723, 2786, 260, 2124, -1138, 798, -1957, -793, +-2046, -2146, -1228, -2589, -4, -2088, 1023, -832, +1712, 870, 1707, 2274, 889, 2688, -163, 1917, +-1052, 298, -1563, -1499, -1370, -2573, -579, -2352, +459, -1042, 1295, 708, 1419, 1943, 851, 2043, +-112, 1246, -942, -33, -1124, -1080, -715, -1334, +58, -1022, 641, -368, 588, 216, 250, 464, +-169, 606, -338, 553, 21, 314, 341, 204, +349, -37, 73, -423, -516, -572, -863, -605, +-579, -531, 76, -6, 779, 556, 1204, 859, +940, 1019, 58, 549, -810, -293, -1337, -834, +-1206, -1149, -400, -925, 454, -174, 1127, 388, +1293, 749, 727, 854, 39, 619, -518, 444, +-804, 296, -755, -73, -619, -590, -291, -1192, +-4, -1613, 236, -1348, 682, -246, 944, 1323, +964, 2651, 644, 2912, -180, 1766, -896, -452, +-1396, -2722, -1515, -3859, -860, -3292, 163, -1154, +1120, 1564, 1777, 3496, 1691, 3894, 825, 2665, +-309, 386, -1233, -1758, -1651, -3032, -1290, -3096, +-519, -2036, 199, -559, 788, 931, 832, 2094, +630, 2358, 597, 1959, 430, 1182, 227, -80, +-25, -1131, -553, -1650, -975, -1965, -1181, -1739, +-1034, -1040, -379, -175, 500, 1078, 1330, 2269, +1850, 2724, 1668, 2281, 767, 776, -548, -1341, +-1827, -2978, -2452, -3391, -2050, -2397, -771, -407, +852, 1684, 2137, 2883, 2466, 2874, 1870, 1824, +695, 242, -681, -1084, -1713, -1873, -2119, -2089, +-1993, -1685, -1173, -982, 39, -90, 1281, 969, +2334, 1851, 2546, 2285, 1730, 1951, 265, 815, +-1554, -739, -2760, -2130, -2741, -2648, -1763, -2101, +49, -777, 1868, 800, 2612, 1827, 2312, 2044, +1262, 1608, -295, 754, -1426, -112, -1712, -775, +-1551, -1208, -930, -1430, -132, -1324, 235, -701, +657, 145, 1094, 1017, 1101, 1626, 1093, 1400, +792, 682, -68, -79, -815, -814, -1432, -1003, +-1723, -739, -1318, -538, -525, -242, 559, 34, +1513, 222, 1890, 493, 1792, 669, 975, 684, +-269, 519, -1236, 94, -1942, -290, -1997, -632, +-1238, -906, -305, -790, 713, -511, 1709, -69, +2043, 621, 1795, 1048, 1107, 1131, -203, 903, +-1525, 196, -2301, -633, -2516, -1202, -1695, -1332, +-21, -946, 1590, -185, 2774, 653, 2892, 1136, +1620, 1131, -199, 683, -1899, -42, -2808, -563, +-2334, -747, -1009, -558, 519, -114, 1723, 170, +1934, 164, 1358, -25, 618, -233, -229, -194, +-952, 127, -1117, 429, -1020, 549, -802, 430, +-129, 8, 561, -388, 880, -428, 1028, -420, +774, -307, 136, -62, -329, -20, -674, 15, +-889, 207, -633, 417, -304, 592, 4, 643, +518, 367, 750, -227, 694, -885, 490, -1336, +27, -1176, -289, -414, -492, 630, -608, 1569, +-451, 1806, -326, 1221, -93, 174, 257, -1062, +498, -1817, 738, -1744, 648, -1106, 255, 29, +-172, 1155, -670, 1753, -909, 1659, -766, 918, +-308, -178, 378, -1171, 813, -1597, 1012, -1275, +797, -386, 58, 526, -589, 1044, -981, 1011, +-939, 389, -435, -323, 109, -543, 694, -433, +829, -50, 511, 474, 364, 518, -53, 190, +-519, -211, -551, -661, -579, -796, -383, -458, +149, 59, 437, 612, 522, 1004, 472, 848, +111, 325, -299, -287, -347, -782, -263, -922, +-126, -619, 91, -96, 85, 278, 28, 449, +120, 444, 41, 260, 6, 120, 129, 131, +80, 112, -38, 63, -60, -170, -203, -485, +-342, -642, -208, -593, -57, -133, 258, 422, +599, 794, 512, 848, 257, 330, -134, -261, +-637, -568, -670, -651, -417, -300, -102, 217, +275, 398, 524, 315, 539, 36, 372, -274, +85, -396, -209, -294, -455, 28, -532, 361, +-329, 521, 82, 456, 403, 257, 434, -111, +232, -537, -134, -745, -397, -656, -360, -298, +-99, 279, 225, 817, 451, 980, 446, 732, +228, 182, -76, -417, -315, -799, -547, -890, +-602, -751, -463, -418, -196, 61, 304, 518, +791, 969, 1031, 1286, 974, 1157, 491, 551, +-278, -381, -1094, -1386, -1661, -2020, -1570, -1936, +-771, -1061, 384, 392, 1553, 1740, 2247, 2564, +1916, 2540, 809, 1494, -607, -68, -1852, -1686, +-2304, -2883, -1908, -3083, -817, -2210, 558, -493, +1564, 1623, 2137, 3220, 1996, 3639, 1029, 2660, +-151, 595, -1311, -1661, -2076, -3264, -1976, -3509, +-1238, -2417, -98, -594, 1066, 1312, 1762, 2570, +1907, 2776, 1361, 2063, 325, 768, -733, -700, +-1582, -1740, -1802, -2091, -1250, -1745, -291, -804, +770, 326, 1434, 1116, 1339, 1371, 632, 1078, +-241, 356, -762, -231, -813, -504, -433, -457, +215, -136, 532, 90, 450, 55, 154, -117, +-401, -362, -724, -536, -622, -373, -373, 16, +197, 442, 821, 803, 1045, 886, 1000, 580, +603, 107, -191, -365, -1012, -840, -1517, -1049, +-1503, -947, -969, -611, 40, 54, 1172, 871, +1861, 1413, 2009, 1480, 1393, 937, 86, -101, +-1174, -1049, -2083, -1564, -2354, -1408, -1630, -674, +-334, 211, 1034, 819, 2104, 977, 2397, 804, +1800, 453, 638, 204, -741, 84, -1825, -49, +-2269, -277, -1990, -678, -976, -1057, 350, -1043, +1494, -610, 2124, 220, 1932, 1186, 1122, 1669, +58, 1559, -1009, 804, -1627, -319, -1656, -1204, +-1266, -1636, -620, -1494, 203, -859, 987, -97, +1471, 556, 1628, 1065, 1344, 1325, 418, 1348, +-621, 1012, -1438, 288, -1936, -623, -1658, -1473, +-692, -1866, 403, -1558, 1364, -698, 1854, 288, +1625, 1154, 818, 1614, -217, 1584, -1140, 1251, +-1609, 595, -1516, -295, -943, -1186, 61, -1867, +1015, -2041, 1531, -1435, 1528, -315, 904, 974, +-156, 2017, -1143, 2272, -1688, 1754, -1436, 673, +-549, -637, 421, -1634, 1240, -2037, 1593, -1833, +1158, -1000, 415, 136, -355, 1135, -1063, 1709, +-1413, 1631, -1355, 1011, -794, 90, 147, -680, +1012, -1018, 1641, -1007, 1723, -720, 995, -321, +-95, -60, -1132, 131, -1749, 386, -1595, 532, +-926, 676, -43, 755, 897, 523, 1363, 117, +1282, -382, 919, -926, 329, -1215, -332, -1097, +-777, -564, -900, 284, -813, 1060, -663, 1601, +-417, 1597, -57, 904, 301, -78, 694, -1149, +1124, -1901, 1264, -1870, 984, -1177, 338, -57, +-663, 1176, -1527, 1895, -1900, 1899, -1728, 1325, +-847, 279, 471, -832, 1556, -1604, 2200, -1840, +2141, -1486, 1239, -632, 29, 425, -1187, 1333, +-2096, 1756, -2169, 1530, -1647, 864, -688, -60, +610, -935, 1543, -1422, 1951, -1494, 1890, -1167, +1167, -418, 178, 442, -660, 1185, -1364, 1663, +-1717, 1492, -1620, 741, -1231, -277, -520, -1255, +528, -1709, 1564, -1431, 2279, -663, 2322, 316, +1454, 1097, -39, 1325, -1649, 1092, -2757, 520, +-2746, -195, -1758, -753, -182, -979, 1526, -779, +2571, -335, 2663, 128, 1864, 435, 357, 461, +-1121, 270, -2136, 136, -2438, 94, -1727, 87, +-451, 78, 777, -88, 1671, -309, 1886, -372, +1341, -301, 485, -147, -357, 143, -1038, 308, +-1292, 256, -1114, 188, -664, 132, 34, 19, +682, -103, 1048, -135, 1048, -172, 661, -161, +-20, -53, -685, 38, -1007, 134, -955, 92, +-542, -54, 158, -77, 773, -11, 1130, 100, +1009, 293, 403, 323, -348, 112, -975, -250, +-1277, -605, -971, -653, -236, -365, 387, 199, +918, 727, 1171, 968, 826, 750, 421, 61, +-26, -644, -636, -946, -846, -864, -961, -424, +-956, 240, -382, 628, 216, 689, 751, 546, +1320, 275, 1243, 14, 727, -280, 21, -523, +-867, -564, -1370, -434, -1355, -147, -900, 247, +-8, 490, 784, 529, 1224, 365, 1265, 123, +870, -28, 170, -227, -533, -421, -967, -498, +-1153, -425, -923, -255, -330, 118, 271, 502, +748, 679, 1027, 672, 856, 396, 404, -21, +-49, -431, -522, -825, -791, -959, -683, -634, +-444, -129, -50, 509, 387, 1007, 544, 1023, +437, 628, 237, 1, -73, -467, -286, -643, +-210, -650, -108, -517, 16, -353, 218, -222, +202, 87, 73, 588, -88, 1003, -337, 1069, +-389, 565, -322, -285, -60, -1076, 329, -1413, +557, -1039, 637, -122, 408, 813, -97, 1301, +-395, 1151, -604, 407, -680, -480, -347, -1097, +28, -1081, 331, -473, 565, 288, 548, 783, +296, 834, -126, 444, -420, -64, -393, -292, +-129, -270, 212, -152, 379, -138, 282, -276, +-94, -379, -473, -309, -578, -39, -385, 369, +-53, 624, 237, 643, 485, 552, 662, 318, +552, -6, 371, -390, 143, -842, -278, -1099, +-718, -988, -937, -478, -874, 338, -586, 1113, +-32, 1402, 578, 1219, 1075, 745, 1371, -11, +1109, -723, 424, -1132, -351, -1369, -1231, -1260, +-1726, -679, -1452, 134, -684, 1021, 397, 1570, +1347, 1540, 1665, 1031, 1417, 151, 586, -749, +-459, -1285, -1104, -1370, -1263, -998, -1044, -390, +-380, 277, 295, 741, 564, 732, 566, 451, +473, 228, 336, 187, 287, 376, 269, 575, +84, 413, -224, -192, -572, -1038, -824, -1594, +-746, -1492, -380, -770, 76, 225, 512, 1143, +791, 1688, 831, 1692, 704, 1263, 331, 543, +-121, -401, -517, -1315, -922, -1884, -949, -1917, +-624, -1279, -213, -237, 273, 822, 647, 1636, +729, 1880, 685, 1552, 561, 825, 323, -81, +34, -907, -334, -1482, -853, -1575, -1160, -1132, +-1009, -419, -525, 341, 318, 893, 1092, 970, +1365, 785, 1141, 440, 525, 135, -143, 50, +-689, 38, -908, -85, -845, -301, -732, -561, +-505, -848, -222, -852, 228, -484, 838, 91, +1228, 738, 1261, 1196, 860, 1144, -84, 707, +-915, -8, -1359, -711, -1383, -948, -815, -842, +-63, -453, 578, 98, 912, 443, 858, 514, +712, 344, 488, -12, 169, -291, -140, -384, +-521, -262, -863, 153, -1006, 490, -787, 560, +-218, 424, 449, 76, 946, -322, 1063, -552, +854, -607, 418, -510, -104, -216, -439, 104, +-747, 476, -1018, 719, -988, 568, -622, 141, +-44, -267, 767, -534, 1346, -430, 1461, 6, +1178, 362, 180, 448, -914, 113, -1512, -328, +-1677, -498, -1192, -433, -146, -164, 871, 182, +1516, 291, 1530, 228, 972, 204, 70, 301, +-848, 438, -1335, 339, -1236, 37, -694, -412, +30, -855, 682, -936, 1098, -666, 966, -135, +589, 450, 134, 805, -445, 932, -768, 874, +-909, 498, -936, -29, -527, -484, -1, -774, +578, -837, 1247, -617, 1438, -206, 1082, 52, +242, 135, -732, 123, -1425, 121, -1595, 241, +-1117, 533, -312, 858, 431, 999, 986, 743, +1171, 49, 1042, -881, 773, -1696, 292, -1995, +-302, -1598, -749, -530, -1038, 805, -1134, 1837, +-893, 2238, -360, 1917, 195, 992, 814, -107, +1305, -1002, 1383, -1502, 1070, -1538, 318, -1288, +-649, -884, -1411, -378, -1697, 134, -1391, 680, +-439, 1228, 602, 1594, 1275, 1569, 1483, 1121, +1085, 318, 401, -668, -280, -1498, -826, -1880, +-874, -1768, -664, -1214, -484, -384, -110, 514, +216, 1305, 363, 1817, 485, 1963, 483, 1592, +351, 711, 90, -507, -207, -1662, -319, -2313, +-238, -2161, -134, -1244, -55, 53, -11, 1217, +-91, 1843, -183, 1686, -88, 1006, 183, 224, +345, -519, 309, -885, 180, -822, 24, -602, +-193, -300, -248, 30, -113, 226, -65, 279, +-70, 186, -92, 10, -38, -97, 29, -112, +87, 15, 219, 260, 212, 415, 108, 290, +-81, 17, -260, -247, -212, -411, -80, -306, +63, -47, 246, 140, 308, 171, 82, 13, +-185, -242, -292, -304, -339, -198, -199, 20, +184, 386, 384, 624, 364, 615, 206, 357, +-119, -36, -325, -464, -315, -756, -253, -767, +5, -472, 321, -66, 369, 312, 239, 602, +47, 666, -241, 498, -421, 174, -345, -116, +-133, -368, 159, -472, 403, -342, 375, -70, +237, 208, 26, 298, -224, 171, -318, -42, +-355, -306, -307, -422, -157, -176, 177, 128, +472, 389, 573, 522, 585, 363, 327, 163, +-241, -87, -679, -347, -933, -386, -944, -368, +-457, -378, 214, -168, 751, 103, 1182, 284, +1166, 445, 731, 423, 125, 253, -631, 18, +-1175, -239, -1253, -371, -1004, -234, -449, -70, +236, 103, 766, 281, 1090, 195, 1010, -105, +687, -364, 325, -472, -157, -364, -591, -6, +-758, 420, -756, 734, -637, 770, -446, 504, +-111, 42, 230, -452, 467, -844, 711, -1004, +888, -824, 798, -332, 421, 314, -80, 880, +-623, 1177, -1023, 1062, -1110, 484, -869, -263, +-268, -827, 361, -1037, 752, -811, 1037, -285, +971, 160, 515, 353, 30, 325, -402, 166, +-711, 126, -699, 271, -528, 444, -207, 495, +76, 296, 152, -163, 251, -638, 345, -927, +364, -870, 267, -488, 73, 39, -75, 508, +-214, 783, -320, 815, -210, 642, -18, 322, +63, -43, 110, -366, 146, -549, 133, -544, +89, -380, -63, -115, -191, 28, -306, 6, +-377, -104, -204, -201, 100, -138, 415, 183, +631, 634, 588, 992, 406, 1000, 19, 588, +-454, -115, -692, -864, -713, -1343, -521, -1395, +-159, -1005, 180, -383, 391, 249, 429, 803, +257, 1192, 254, 1339, 351, 1187, 285, 703, +254, -26, 37, -782, -388, -1320, -633, -1344, +-744, -903, -668, -342, -335, 148, 16, 367, +349, 377, 750, 375, 1007, 508, 935, 736, +509, 867, -119, 650, -852, 127, -1308, -501, +-1065, -1033, -406, -1184, 366, -936, 957, -452, +958, 9, 457, 335, -174, 460, -595, 550, +-570, 658, -187, 727, 213, 762, 377, 578, +307, 44, 50, -631, -197, -1204, -157, -1483, +24, -1186, 134, -469, 102, 375, -146, 1107, +-386, 1333, -453, 1072, -288, 568, 82, -21, +425, -474, 626, -591, 679, -473, 457, -271, +119, -130, -230, -188, -642, -350, -906, -488, +-882, -345, -587, 159, 7, 821, 672, 1245, +1034, 1171, 1082, 534, 748, -335, 108, -1045, +-396, -1323, -794, -987, -929, -383, -642, 170, +-307, 602, 63, 770, 400, 670, 474, 470, +434, 116, 337, -230, 75, -431, -60, -516, +-48, -312, -57, 50, 22, 240, 57, 229, +-102, 70, -275, -179, -460, -335, -592, -235, +-342, 45, 125, 322, 552, 463, 935, 435, +941, 250, 482, 1, -53, -310, -591, -558, +-978, -607, -915, -574, -569, -341, -115, 164, +429, 682, 743, 1005, 746, 1024, 556, 554, +84, -229, -325, -981, -422, -1356, -409, -1088, +-96, -298, 207, 555, 175, 1065, 32, 1046, +-260, 550, -462, -120, -332, -539, 2, -559, +389, -403, 721, -171, 714, 74, 346, 207, +-112, 234, -538, 238, -720, 136, -536, -91, +-271, -291, 14, -335, 242, -200, 197, 132, +115, 458, 179, 511, 245, 321, 391, -42, +476, -450, 268, -638, -114, -566, -489, -312, +-783, 92, -829, 497, -552, 767, -172, 836, +288, 579, 735, 8, 887, -647, 811, -1104, +596, -1133, 150, -655, -312, 162, -708, 911, +-928, 1262, -871, 997, -645, 309, -325, -460, +169, -995, 743, -1022, 1073, -520, 1202, 194, +993, 766, 255, 955, -547, 669, -1209, 105, +-1503, -560, -1123, -988, -359, -938, 479, -571, +1101, 2, 1178, 672, 781, 1062, 157, 1034, +-411, 650, -733, -14, -709, -623, -301, -971, +115, -933, 415, -436, 571, 181, 429, 588, +102, 704, -313, 452, -627, -75, -685, -517, +-525, -660, -145, -418, 321, 76, 713, 519, +865, 720, 690, 569, 339, 166, -83, -229, +-440, -328, -630, -173, -659, 2, -520, -9, +-367, -245, -143, -690, 128, -981, 329, -734, +582, -30, 679, 884, 562, 1570, 386, 1691, +27, 1188, -354, 223, -551, -788, -680, -1416, +-620, -1556, -313, -1231, 44, -565, 382, 133, +560, 604, 501, 741, 292, 659, 5, 489, +-276, 370, -357, 367, -274, 323, -143, 140, +68, -206, 205, -596, 280, -768, 291, -578, +153, -213, -59, 147, -271, 338, -417, 198, +-457, -88, -314, -244, -22, -181, 222, 88, +402, 439, 477, 634, 396, 603, 254, 343, +51, -39, -125, -373, -254, -548, -374, -524, +-402, -374, -367, -195, -204, -71, 17, -50, +180, -84, 380, -44, 424, 139, 254, 405, +105, 615, -66, 648, -181, 492, -141, 170, +-111, -195, -59, -427, -18, -531, -44, -530, +-18, -475, 71, -430, 98, -315, 26, -130, +-30, 103, -132, 468, -166, 781, -104, 867, +-4, 740, 190, 353, 249, -159, 182, -579, +125, -787, 40, -686, -39, -397, -148, -125, +-180, 75, -195, 175, -252, 197, -143, 168, +-23, 134, 120, 149, 344, 164, 397, 163, +335, 246, 127, 261, -226, 102, -440, -149, +-490, -407, -341, -563, -20, -494, 293, -268, +452, -21, 359, 205, 155, 304, 8, 338, +-93, 448, -84, 524, -117, 378, -216, 70, +-283, -361, -368, -784, -274, -890, 29, -637, +372, -144, 635, 414, 665, 758, 441, 802, +33, 620, -412, 240, -695, -217, -722, -545, +-519, -657, -145, -523, 295, -179, 589, 235, +661, 479, 529, 418, 205, 106, -174, -260, +-486, -449, -649, -388, -525, -64, -209, 357, +159, 636, 508, 632, 689, 328, 590, -144, +270, -547, -152, -754, -581, -667, -773, -275, +-687, 160, -399, 467, 131, 623, 606, 590, +810, 366, 733, 16, 303, -388, -215, -712, +-575, -822, -697, -578, -433, 53, 1, 766, +346, 1154, 468, 1003, 296, 357, -3, -463, +-286, -1052, -364, -1122, -149, -679, 179, -18, +427, 505, 439, 728, 134, 676, -350, 379, +-700, -47, -743, -347, -383, -428, 243, -335, +780, -61, 1026, 235, 811, 327, 176, 157, +-430, -170, -810, -352, -890, -216, -531, 82, +-70, 393, 291, 502, 520, 215, 428, -267, +176, -637, -1, -703, -122, -398, -154, 53, +-36, 496, 116, 833, 189, 826, 129, 524, +-58, 79, -238, -451, -383, -889, -382, -1061, +-149, -845, 114, -245, 367, 414, 509, 932, +363, 1190, 181, 968, -7, 364, -228, -318, +-257, -855, -298, -1105, -367, -995, -290, -579, +-209, -21, -25, 502, 327, 901, 564, 1092, +608, 1023, 453, 641, 81, -73, -273, -818, +-433, -1294, -434, -1355, -323, -866, -109, -3, +-41, 768, -126, 1120, -90, 1009, -42, 559, +123, 9, 438, -426, 561, -596, 560, -558, +420, -388, 11, -86, -380, 192, -618, 381, +-773, 468, -680, 359, -358, 140, 21, -17, +397, -213, 633, -432, 670, -569, 517, -669, +224, -560, -52, -81, -216, 591, -286, 1175, +-305, 1415, -318, 1066, -267, 210, -211, -746, +-119, -1416, 67, -1570, 247, -1194, 372, -420, +328, 398, 170, 955, 32, 1170, -73, 1057, +-67, 701, -8, 261, 28, -139, -21, -477, +-223, -729, -392, -907, -416, -891, -290, -577, +40, -67, 428, 458, 662, 846, 680, 955, +427, 729, 13, 284, -391, -146, -665, -407, +-721, -551, -476, -508, -78, -243, 287, 51, +560, 213, 575, 170, 322, -47, -31, -347, +-292, -527, -333, -294, -178, 317, 71, 891, +231, 1137, 214, 915, 10, 228, -283, -597, +-408, -1217, -326, -1348, -137, -950, 179, -327, +461, 310, 542, 879, 464, 1105, 175, 885, +-161, 455, -417, -32, -591, -430, -502, -621, +-197, -511, 144, -167, 404, 136, 444, 226, +313, 128, 51, -107, -251, -447, -355, -637, +-286, -407, -133, 126, 64, 655, 288, 982, +438, 955, 387, 493, 219, -143, -46, -592, +-358, -675, -586, -509, -615, -320, -310, -206, +149, -155, 492, -159, 598, -139, 403, 40, +-20, 308, -426, 521, -524, 630, -238, 737, +191, 694, 506, 294, 552, -294, 262, -901, +-196, -1351, -550, -1313, -606, -735, -388, 107, +-75, 924, 221, 1309, 453, 1172, 489, 780, +365, 201, 218, -409, -54, -796, -351, -955, +-563, -906, -629, -535, -294, 78, 165, 700, +489, 1059, 674, 943, 490, 411, 16, -339, +-430, -964, -587, -1133, -359, -745, 41, 8, +397, 772, 501, 1170, 322, 1031, 8, 475, +-341, -272, -475, -844, -379, -1000, -203, -763, +27, -325, 184, 151, 293, 489, 343, 588, +245, 505, 114, 260, -55, -12, -239, -193, +-241, -276, -107, -218, 23, -37, 166, 90, +225, 109, 65, 91, -185, 29, -335, 5, +-414, -26, -280, -129, 18, -217, 267, -249, +570, -237, 727, -79, 532, 210, 208, 361, +-243, 338, -724, 240, -948, 116, -873, 14, +-461, -19, 197, -25, 731, -72, 955, -171, +903, -297, 499, -341, -106, -309, -531, -273, +-726, -196, -637, 27, -285, 373, 24, 720, +324, 937, 442, 891, 280, 441, 117, -343, +-62, -1060, -214, -1437, -243, -1345, -195, -753, +-59, 136, 71, 1043, 178, 1566, 253, 1471, +243, 866, 131, -8, -106, -862, -274, -1271, +-313, -1103, -263, -577, -9, 22, 297, 431, +436, 607, 368, 575, 90, 374, -240, 88, +-467, -162, -499, -377, -338, -500, -48, -347, +228, 64, 373, 455, 377, 611, 343, 511, +270, 152, 67, -289, -107, -583, -219, -609, +-356, -386, -354, -92, -200, 178, -50, 335, +81, 341, 135, 208, 83, 11, 61, -71, +75, 45, 72, 182, 146, 226, 180, 169, +77, -109, -11, -422, -65, -530, -151, -392, +-204, -111, -259, 118, -242, 207, -112, 254, +34, 315, 276, 354, 499, 362, 442, 229, +195, -113, -149, -526, -469, -677, -493, -481, +-312, -106, -25, 292, 303, 478, 396, 415, +227, 180, -4, -138, -137, -317, -189, -282, +-141, -168, 44, 36, 120, 344, 83, 507, +46, 382, -26, 26, -30, -358, -40, -619, +-91, -638, -59, -306, -35, 194, -19, 565, +66, 658, 169, 468, 176, 109, 53, -280, +-92, -646, -194, -722, -199, -416, -124, 1, +6, 440, 212, 778, 304, 774, 222, 413, +114, -71, -52, -433, -260, -592, -350, -590, +-302, -421, -145, -142, 102, 106, 245, 288, +262, 382, 227, 396, 51, 255, -110, -9, +-45, -178, 29, -189, 39, -141, 65, -79, +-4, 22, -130, 100, -211, 94, -212, 47, +-71, 71, 102, 54, 142, -69, 145, -153, +139, -182, 3, -173, -148, -130, -145, -42, +-37, 107, 66, 239, 124, 258, 115, 194, +71, 62, -16, -143, -111, -253, -35, -146, +78, 92, 73, 273, -22, 268, -181, 74, +-257, -166, -218, -312, -94, -307, 193, -116, +383, 44, 306, -10, 120, -123, -120, -150, +-290, -45, -268, 231, -77, 527, 167, 643, +291, 501, 243, 115, 55, -324, -157, -651, +-310, -761, -322, -650, -119, -353, 104, 77, +214, 470, 255, 690, 188, 698, 35, 469, +-86, 77, -198, -298, -179, -551, -93, -565, +-79, -358, 40, -84, 189, 224, 194, 429, +153, 389, 68, 158, -87, -147, -210, -381, +-220, -394, -128, -160, 53, 224, 253, 569, +283, 606, 174, 304, 16, -189, -260, -612, +-443, -761, -367, -561, -175, -71, 129, 444, +398, 658, 484, 539, 390, 243, 133, -156, +-174, -412, -346, -394, -385, -242, -320, -52, +-120, 103, 96, 184, 277, 291, 394, 404, +334, 370, 135, 194, -141, -131, -438, -588, +-541, -886, -351, -774, 26, -310, 407, 284, +618, 780, 527, 946, 171, 713, -265, 237, +-554, -226, -564, -474, -350, -493, -42, -372, +269, -165, 421, 26, 425, 84, 302, 44, +82, -9, -119, -7, -285, 60, -368, 170, +-240, 303, 1, 317, 165, 97, 270, -226, +233, -449, 4, -475, -236, -263, -348, 100, +-279, 404, -67, 458, 163, 214, 324, -90, +370, -246, 277, -218, 81, 6, -59, 251, +-118, 281, -204, 68, -235, -292, -153, -574, +-101, -513, -10, -168, 87, 289, 81, 688, +34, 756, -90, 411, -203, -82, -93, -477, +103, -642, 274, -501, 480, -181, 465, 130, +191, 301, -151, 305, -481, 237, -621, 203, +-548, 171, -315, 87, 73, -28, 419, -233, +552, -458, 473, -537, 255, -440, -62, -147, +-356, 260, -439, 596, -308, 777, -63, 722, +195, 375, 338, -95, 389, -523, 243, -782, +-69, -779, -285, -517, -415, -84, -452, 300, +-312, 499, 0, 511, 327, 367, 460, 157, +442, -12, 317, -119, 61, -133, -180, -116, +-279, -108, -214, -47, -94, 11, -83, 10, +-95, -55, -95, -145, -152, -208, -113, -192, +67, -28, 303, 221, 438, 379, 376, 346, +213, 148, -36, -89, -398, -206, -616, -203, +-565, -66, -313, 123, 117, 134, 558, 31, +824, -64, 762, -165, 312, -214, -318, -190, +-806, -140, -1001, -9, -789, 124, -181, 227, +482, 347, 887, 353, 910, 197, 566, 11, +29, -155, -509, -317, -794, -400, -667, -377, +-259, -238, 188, 13, 579, 283, 716, 504, +470, 571, -7, 338, -459, -72, -699, -412, +-634, -595, -343, -550, 79, -292, 485, 24, +604, 301, 506, 466, 331, 515, 84, 495, +-133, 331, -282, -5, -369, -352, -378, -602, +-354, -685, -231, -508, 25, -157, 280, 215, +406, 452, 402, 483, 228, 407, -67, 291, +-305, 131, -342, -14, -212, -135, 29, -295, +281, -468, 373, -539, 285, -444, 85, -166, +-181, 256, -363, 671, -381, 917, -325, 843, +-150, 381, 53, -255, 181, -799, 260, -1090, +310, -948, 309, -434, 243, 190, 107, 687, +-82, 845, -314, 641, -471, 258, -455, -147, +-233, -388, 111, -314, 427, -46, 572, 213, +476, 307, 130, 148, -276, -197, -551, -540, +-645, -678, -451, -474, -63, 0, 331, 460, +611, 705, 660, 675, 461, 373, 105, -56, +-311, -351, -577, -413, -604, -300, -437, -84, +-123, 98, 243, 178, 484, 112, 512, -96, +362, -255, 98, -240, -166, -99, -339, 137, +-404, 371, -296, 435, -123, 247, 11, -107, +167, -397, 283, -470, 328, -330, 293, -14, +146, 378, -46, 593, -268, 477, -459, 138, +-403, -263, -204, -578, 45, -668, 321, -436, +462, 35, 412, 458, 222, 635, -49, 547, +-269, 237, -392, -188, -423, -479, -304, -503, +-42, -310, 223, -9, 409, 256, 491, 390, +393, 360, 78, 124, -286, -187, -523, -333, +-548, -308, -347, -162, 3, 103, 390, 311, +588, 295, 490, 132, 222, -55, -90, -155, +-373, -160, -479, -165, -390, -155, -153, -114, +138, -56, 335, 105, 392, 344, 306, 478, +13, 371, -336, 37, -480, -329, -388, -503, +-119, -433, 277, -177, 580, 113, 575, 229, +266, 124, -170, -35, -468, -73, -457, 45, +-244, 262, 47, 421, 284, 369, 213, 76, +-66, -378, -285, -751, -284, -789, -38, -452, +277, 136, 483, 756, 488, 1081, 194, 919, +-197, 323, -440, -437, -490, -983, -362, -1133, +-160, -854, 50, -221, 252, 480, 373, 961, +432, 1101, 392, 849, 188, 277, -159, -393, +-511, -919, -673, -1046, -555, -717, -221, -152, +211, 389, 584, 711, 711, 675, 582, 352, +283, 9, -60, -199, -395, -260, -663, -229, +-753, -173, -600, -114, -240, -64, 275, -31, +776, 36, 1034, 154, 867, 237, 323, 232, +-350, 149, -852, 2, -1015, -210, -785, -399, +-242, -398, 342, -182, 702, 117, 787, 388, +620, 543, 255, 468, -178, 190, -565, -150, +-748, -419, -666, -550, -375, -559, 73, -412, +578, -82, 849, 298, 796, 571, 476, 692, +-6, 594, -491, 291, -792, -71, -809, -356, +-550, -495, -151, -522, 241, -517, 537, -413, +681, -129, 568, 219, 286, 515, 2, 722, +-263, 681, -435, 317, -442, -126, -299, -418, +-101, -525, 45, -461, 111, -291, 151, -94, +141, 78, 127, 184, 162, 281, 227, 394, +193, 402, 55, 252, -125, -4, -311, -296, +-439, -565, -411, -726, -233, -596, 62, -155, +326, 382, 444, 841, 448, 1035, 310, 824, +20, 268, -219, -400, -325, -871, -317, -993, +-200, -844, -55, -483, 77, 20, 143, 492, +105, 817, 37, 931, 28, 767, 22, 322, +25, -264, 34, -709, 43, -810, 20, -595, +-24, -226, -69, 121, -87, 322, -85, 339, +-76, 242, -46, 163, 3, 118, 67, 36, +130, -59, 172, -113, 184, -109, 118, -86, +-36, -101, -219, -139, -348, -162, -331, -123, +-151, 40, 131, 300, 403, 498, 527, 471, +365, 190, 5, -195, -391, -529, -645, -687, +-605, -564, -226, -215, 284, 228, 686, 601, +794, 738, 487, 610, -58, 245, -541, -274, +-807, -664, -662, -704, -159, -430, 323, 12, +590, 421, 545, 596, 199, 446, -174, 71, +-350, -305, -264, -491, 10, -433, 227, -196, +224, 137, 26, 444, -238, 552, -419, 402, +-334, 111, -27, -211, 316, -462, 524, -541, +511, -387, 268, -70, -83, 198, -434, 307, +-605, 296, -519, 180, -266, 7, 112, -66, +495, 19, 681, 142, 576, 163, 199, 51, +-269, -139, -606, -354, -681, -483, -430, -392, +39, -95, 444, 217, 566, 379, 412, 429, +91, 380, -217, 239, -373, 79, -290, -61, +-65, -208, 137, -401, 207, -551, 165, -457, +47, -134, -83, 235, -181, 552, -192, 672, +-124, 484, -6, 61, 140, -364, 275, -578, +327, -525, 207, -312, -51, -8, -327, 314, +-503, 446, -472, 358, -174, 206, 266, 62, +602, -91, 672, -209, 464, -241, 35, -211, +-418, -173, -691, -97, -677, 91, -415, 277, +-16, 298, 333, 157, 547, -67, 561, -294, +370, -380, 75, -243, -191, 78, -347, 415, +-344, 507, -197, 354, 33, 111, 198, -170, +193, -410, 53, -445, -163, -316, -319, -177, +-294, -24, -72, 148, 234, 276, 469, 313, +489, 241, 275, 126, -76, 37, -372, -64, +-492, -142, -354, -141, -56, -145, 248, -178, +407, -173, 318, -68, 40, 90, -240, 209, +-410, 264, -375, 256, -130, 149, 204, -39, +454, -192, 480, -275, 292, -324, 2, -314, +-284, -192, -455, 33, -389, 294, -169, 498, +81, 567, 248, 474, 285, 176, 227, -225, +83, -538, -88, -684, -159, -642, -170, -430, +-148, -96, -116, 277, -14, 555, 126, 694, +212, 721, 254, 539, 255, 138, 131, -307, +-94, -685, -316, -877, -421, -764, -389, -416, +-271, 24, -13, 443, 280, 670, 456, 674, +500, 571, 413, 359, 211, 30, -64, -278, +-376, -500, -528, -632, -496, -585, -344, -373, +-84, -86, 254, 193, 483, 368, 471, 466, +296, 528, 82, 476, -165, 301, -336, 49, +-356, -285, -226, -589, -47, -719, 40, -611, +113, -273, 184, 135, 146, 455, 86, 646, +109, 645, 143, 430, 131, 122, 43, -190, +-87, -442, -257, -573, -453, -560, -535, -360, +-358, -73, 8, 159, 399, 359, 678, 522, +752, 547, 503, 437, 25, 227, -424, -78, +-637, -421, -585, -699, -348, -732, -9, -465, +308, -51, 387, 340, 260, 608, 111, 619, +-52, 364, -182, 74, -186, -123, -65, -229, +90, -239, 172, -229, 144, -210, 64, -141, +-83, -56, -242, 68, -289, 247, -151, 314, +76, 237, 258, 116, 369, -17, 349, -167, +132, -321, -169, -409, -404, -391, -450, -250, +-334, 66, -100, 521, 205, 849, 417, 825, +409, 434, 222, -183, -12, -770, -176, -1031, +-232, -844, -162, -334, 22, 252, 145, 631, +107, 696, -50, 522, -219, 189, -309, -154, +-250, -331, -64, -339, 206, -249, 443, -77, +502, 119, 375, 274, 171, 328, -95, 262, +-363, 94, -541, -194, -564, -517, -419, -686, +-140, -574, 186, -181, 506, 381, 684, 865, +558, 1017, 235, 744, -134, 155, -466, -484, +-600, -900, -458, -958, -145, -670, 222, -151, +434, 370, 419, 707, 254, 795, -26, 590, +-343, 156, -457, -319, -309, -643, -42, -690, +230, -450, 443, -39, 464, 362, 248, 590, +-106, 549, -381, 288, -471, -69, -409, -393, +-211, -539, 109, -424, 373, -119, 455, 225, +380, 427, 208, 366, -1, 106, -231, -196, +-337, -312, -273, -135, -161, 161, -72, 329, +2, 259, 55, -62, 76, -466, 64, -644, +118, -464, 201, -22, 196, 472, 85, 778, +-23, 769, -111, 464, -193, -25, -217, -497, +-134, -752, -34, -723, 2, -437, 32, -3, +118, 396, 187, 573, 174, 457, 117, 163, +23, -130, -139, -312, -317, -322, -334, -135, +-160, 129, 108, 332, 342, 436, 465, 370, +403, 95, 112, -303, -298, -660, -563, -794, +-582, -586, -378, -108, 0, 453, 434, 863, +679, 928, 597, 613, 263, 86, -144, -435, +-478, -782, -613, -841, -466, -592, -106, -117, +235, 403, 381, 772, 376, 861, 242, 610, +19, 99, -162, -464, -209, -836, -167, -895, +-103, -638, -71, -166, -12, 346, 80, 734, +144, 880, 168, 739, 193, 387, 144, -56, +-39, -480, -252, -738, -371, -758, -355, -559, +-190, -234, 93, 135, 404, 453, 583, 606, +471, 575, 142, 391, -242, 105, -554, -154, +-640, -313, -430, -392, -26, -369, 382, -266, +583, -150, 533, 4, 295, 213, -41, 387, +-354, 418, -488, 288, -426, 35, -239, -237, +-4, -396, 227, -360, 378, -147, 385, 107, +237, 262, 28, 271, -165, 181, -307, 7, +-308, -180, -157, -270, 50, -239, 210, -113, +254, 61, 168, 234, 20, 323, -149, 250, +-247, 62, -195, -96, -74, -167, 39, -178, +145, -152, 189, -125, 180, -136, 121, -156, +17, -88, -73, 130, -144, 402, -195, 553, +-151, 495, -35, 237, 65, -183, 98, -632, +77, -864, 15, -755, -39, -396, -5, 113, +118, 658, 251, 1014, 264, 1008, 91, 642, +-211, 51, -524, -585, -683, -1065, -506, -1178, +-20, -837, 567, -172, 970, 537, 961, 996, +518, 1067, -180, 735, -852, 133, -1142, -414, +-901, -652, -311, -593, 349, -379, 826, -125, +900, 63, 607, 110, 144, 92, -281, 149, +-516, 276, -541, 333, -418, 271, -192, 109, +53, -135, 236, -363, 359, -449, 385, -339, +284, -97, 68, 136, -160, 274, -307, 306, +-309, 224, -199, 60, -37, -85, 126, -136, +199, -128, 152, -108, 83, -61, 37, 18, +-2, 87, -59, 118, -108, 123, -126, 102, +-122, 1, -80, -135, 27, -212, 137, -198, +160, -125, 94, -30, -8, 85, -71, 180, +-79, 221, -33, 216, 50, 203, 115, 127, +84, -43, 6, -224, -48, -320, -79, -282, +-119, -132, -151, 16, -145, 86, -104, 48, +-33, -90, 98, -143, 286, 13, 418, 289, +355, 533, 148, 587, -111, 370, -391, -35, +-558, -494, -475, -811, -204, -824, 141, -607, +402, -229, 484, 262, 443, 707, 239, 951, +-55, 901, -262, 544, -348, 3, -384, -550, +-333, -909, -183, -896, 36, -551, 244, -77, +395, 328, 462, 555, 384, 563, 148, 378, +-149, 116, -369, -83, -456, -178, -416, -225, +-231, -224, 30, -142, 231, -47, 308, 11, +296, 84, 228, 147, 87, 133, -58, 30, +-102, -104, -94, -167, -99, -137, -105, -41, +-123, 115, -120, 247, -126, 238, -100, 85, +55, -73, 246, -144, 325, -159, 299, -137, +165, -60, -66, 11, -290, 15, -378, -9, +-260, 6, -54, 43, 120, 33, 217, 38, +215, 111, 103, 170, -57, 155, -106, 58, +-86, -93, -88, -257, -54, -374, 4, -314, +61, -40, 126, 258, 135, 408, 114, 391, +51, 217, -131, -95, -266, -388, -244, -466, +-123, -307, 44, -30, 201, 249, 285, 446, +236, 468, 76, 252, -82, -70, -166, -289, +-190, -383, -168, -391, -93, -283, 17, -75, +59, 169, 53, 350, 87, 443, 120, 451, +112, 248, 53, -158, -37, -504, -105, -640, +-163, -526, -154, -159, 9, 307, 194, 688, +252, 775, 181, 475, -12, -5, -228, -451, +-353, -771, -315, -778, -94, -405, 166, 131, +293, 560, 277, 721, 187, 574, 43, 199, +-80, -240, -101, -512, -91, -451, -117, -175, +-166, 105, -183, 309, -69, 359, 131, 179, +280, -130, 336, -383, 222, -452, -88, -309, +-403, -29, -512, 329, -319, 620, 65, 618, +425, 318, 603, -89, 491, -462, 108, -689, +-315, -660, -570, -347, -566, 116, -329, 518, +29, 730, 366, 715, 507, 433, 408, -84, +168, -600, -95, -859, -308, -792, -376, -454, +-233, 60, 1, 572, 176, 865, 215, 810, +129, 494, 20, 81, -79, -360, -148, -693, +-97, -751, 20, -538, 67, -190, 85, 156, +96, 422, 70, 546, 4, 464, -87, 227, +-166, -6, -186, -175, -147, -302, -33, -344, +162, -241, 296, -55, 279, 81, 177, 162, +14, 232, -201, 250, -324, 171, -282, 36, +-125, -100, 70, -248, 180, -405, 197, -400, +147, -156, 3, 153, -131, 393, -156, 501, +-94, 431, 1, 203, 103, -95, 198, -294, +234, -324, 139, -324, -35, -334, -210, -245, +-337, -73, -350, 105, -198, 289, 94, 461, +349, 529, 443, 393, 353, 99, 115, -194, +-172, -431, -401, -615, -463, -602, -289, -326, +-21, 47, 213, 368, 390, 569, 407, 591, +258, 405, 13, 45, -214, -280, -306, -402, +-296, -413, -195, -335, -37, -108, 85, 145, +131, 290, 125, 302, 131, 227, 143, 116, +113, -54, 59, -215, -31, -250, -161, -204, +-272, -164, -309, -85, -160, 91, 92, 289, +285, 376, 400, 333, 354, 196, 116, -51, +-194, -340, -439, -486, -448, -383, -237, -163, +16, 21, 260, 176, 405, 259, 344, 225, +143, 147, -60, 117, -182, 151, -245, 125, +-225, -30, -120, -193, -6, -322, 93, -411, +146, -340, 145, -71, 105, 265, -3, 457, +-96, 420, -73, 256, -36, 19, -2, -240, +32, -356, 46, -288, 38, -149, -12, -44, +-18, 57, 30, 226, 41, 353, 1, 332, +-94, 205, -175, -32, -177, -356, -132, -612, +52, -601, 312, -273, 440, 183, 402, 555, +170, 752, -194, 683, -515, 299, -655, -227, +-502, -619, -122, -758, 286, -658, 572, -329, +632, 142, 459, 543, 111, 676, -238, 536, +-388, 269, -382, -52, -264, -344, -71, -452, +56, -353, 86, -170, 31, -29, -38, 54, +-8, 140, 75, 162, 158, 107, 229, 113, +214, 171, 106, 160, -42, 62, -176, -67, +-216, -187, -209, -295, -183, -357, -103, -255, +3, -31, 80, 167, 107, 317, 137, 438, +148, 450, 128, 278, 100, -1, 63, -278, +19, -506, -69, -625, -224, -550, -285, -242, +-218, 170, -125, 487, 56, 671, 243, 724, +285, 530, 224, 139, 100, -279, -24, -609, +-96, -773, -144, -739, -168, -444, -153, 33, +-119, 426, -65, 618, 80, 630, 290, 470, +375, 196, 272, -90, 42, -266, -281, -319, +-546, -350, -592, -329, -333, -192, 162, -16, +610, 117, 773, 205, 636, 245, 222, 195, +-335, 41, -739, -110, -781, -145, -489, -81, +-48, 19, 389, 149, 631, 252, 558, 188, +246, -48, -128, -293, -358, -406, -362, -358, +-198, -163, 55, 151, 250, 414, 218, 441, +5, 259, -209, 15, -292, -175, -198, -260, +17, -221, 282, -60, 436, 109, 355, 128, +100, 39, -175, -56, -354, -144, -404, -175, +-314, -112, -92, 43, 150, 194, 298, 213, +341, 167, 290, 137, 165, 68, -36, -25, +-236, -90, -326, -163, -318, -261, -234, -337, +-63, -283, 158, -68, 312, 183, 321, 373, +227, 476, 97, 432, -28, 196, -116, -118, +-131, -346, -103, -440, -123, -406, -209, -229, +-250, 47, -184, 292, -24, 359, 213, 266, +439, 135, 519, -30, 346, -183, -2, -232, +-351, -212, -552, -159, -523, -77, -262, 62, +143, 278, 493, 422, 576, 356, 379, 153, +58, -132, -275, -427, -532, -544, -555, -417, +-316, -121, 16, 173, 295, 341, 481, 393, +528, 341, 398, 180, 123, 1, -196, -110, +-434, -189, -566, -263, -576, -290, -360, -231, +14, -111, 354, 41, 625, 228, 749, 417, +606, 465, 231, 286, -228, -14, -607, -310, +-777, -518, -700, -542, -410, -347, 32, -26, +429, 249, 591, 395, 555, 456, 430, 424, +201, 271, -63, 40, -228, -210, -321, -403, +-367, -509, -378, -471, -303, -250, -111, 43, +117, 279, 322, 421, 466, 453, 475, 348, +296, 109, 11, -161, -237, -309, -393, -337, +-450, -263, -352, -86, -144, 81, 79, 151, +252, 132, 347, 112, 388, 136, 303, 139, +82, 44, -147, -111, -323, -263, -399, -355, +-336, -297, -156, -59, 74, 240, 240, 425, +284, 433, 283, 303, 242, 93, 152, -159, +35, -377, -116, -450, -294, -372, -452, -196, +-486, 73, -316, 331, 48, 412, 436, 309, +656, 100, 634, -90, 366, -170, -108, -171, +-534, -97, -682, 18, -571, 51, -248, 10, +149, -18, 432, -42, 542, -56, 445, -32, +190, 30, -67, 114, -254, 129, -359, 44, +-321, -51, -184, -106, -50, -108, 54, -9, +135, 134, 152, 181, 131, 85, 143, -110, +141, -254, 113, -257, 28, -145, -145, 67, +-278, 286, -277, 357, -192, 256, -9, 48, +226, -192, 352, -346, 298, -355, 109, -172, +-121, 143, -260, 357, -252, 366, -152, 187, +-14, -110, 93, -375, 84, -457, 0, -306, +-54, -9, -23, 281, 103, 472, 278, 526, +351, 406, 248, 100, -11, -296, -360, -592, +-611, -675, -631, -507, -381, -99, 67, 359, +504, 616, 721, 563, 646, 277, 322, -56, +-84, -284, -385, -347, -490, -233, -397, -40, +-190, 103, 18, 154, 110, 137, 98, 80, +87, -17, 83, -120, 99, -165, 128, -144, +126, -93, 78, -12, -19, 97, -125, 195, +-169, 235, -174, 198, -152, 87, -66, -93, +56, -260, 175, -295, 242, -166, 242, 68, +127, 240, -102, 248, -328, 114, -415, -113, +-303, -290, -43, -274, 243, -97, 442, 124, +473, 275, 272, 298, -50, 220, -298, 63, +-414, -122, -393, -242, -243, -256, -3, -188, +217, -47, 328, 117, 344, 204, 267, 174, +86, 39, -140, -112, -311, -175, -344, -144, +-259, -26, -115, 152, 98, 271, 265, 262, +261, 138, 146, -77, 42, -287, -8, -383, +-33, -317, -36, -77, -38, 204, -91, 348, +-209, 329, -276, 159, -177, -76, 70, -222, +309, -227, 428, -119, 411, 19, 180, 110, +-177, 148, -436, 139, -503, 72, -376, -44, +-110, -160, 193, -223, 417, -201, 443, -79, +269, 90, 42, 214, -147, 241, -274, 173, +-298, 78, -166, 26, 32, -19, 133, -69, +135, -129, 105, -226, 44, -294, -42, -274, +-105, -134, -80, 106, -5, 349, 14, 512, +20, 534, 63, 349, 77, 2, 47, -377, +-3, -647, -32, -669, -62, -436, -102, -41, +-53, 359, 64, 571, 145, 524, 138, 301, +36, 27, -108, -188, -241, -286, -278, -266, +-101, -170, 205, -63, 409, 37, 389, 108, +188, 132, -100, 102, -399, 23, -515, -52, +-322, -83, 23, -73, 304, -28, 420, 46, +360, 96, 144, 80, -156, 24, -372, -30, +-356, -52, -175, -20, 38, 45, 245, 94, +387, 62, 338, -91, 101, -262, -138, -315, +-296, -195, -356, 84, -283, 389, -97, 537, +137, 427, 277, 85, 254, -318, 175, -551, +85, -531, -47, -297, -133, 51, -113, 352, +-46, 488, -28, 432, -42, 231, -12, -30, +19, -281, 10, -448, -10, -451, 8, -297, +32, -53, -2, 209, -13, 415, 64, 495, +96, 411, 36, 194, -17, -80, -50, -324, +-85, -468, -111, -466, -61, -290, 55, -33, +105, 179, 51, 288, -9, 272, -33, 173, +-69, 61, -82, 0, 8, 30, 124, 106, +134, 119, 68, 54, -10, -89, -88, -298, +-153, -465, -161, -467, -53, -260, 85, 90, +133, 431, 104, 632, 52, 595, -42, 307, +-170, -87, -200, -382, -82, -471, 66, -373, +168, -181, 235, 16, 250, 140, 144, 171, +-79, 149, -246, 124, -286, 79, -284, -33, +-231, -152, -82, -198, 104, -137, 202, 22, +233, 212, 263, 338, 256, 293, 148, 57, +-25, -219, -159, -379, -258, -363, -335, -197, +-330, 43, -187, 228, 1, 237, 119, 98, +238, -41, 354, -68, 353, 26, 214, 182, +15, 281, -184, 217, -361, -44, -467, -378, +-377, -559, -83, -501, 229, -238, 434, 148, +513, 501, 412, 664, 69, 567, -352, 260, +-606, -121, -612, -463, -408, -663, -33, -610, +429, -303, 757, 105, 760, 448, 466, 616, +34, 546, -436, 256, -798, -111, -862, -381, +-570, -455, -76, -355, 391, -164, 720, 42, +810, 177, 583, 165, 143, 76, -286, 34, +-533, 64, -581, 155, -459, 249, -164, 241, +166, 88, 344, -192, 361, -464, 271, -553, +123, -437, -60, -183, -200, 134, -184, 412, +-75, 568, 16, 574, 76, 455, 121, 218, +113, -137, 18, -535, -90, -796, -112, -772, +-84, -460, -69, 53, -7, 579, 97, 870, +156, 791, 131, 392, 74, -126, 50, -536, +18, -704, -39, -589, -66, -249, -72, 127, +-96, 361, -127, 420, -84, 351, 52, 221, +169, 77, 231, -50, 247, -155, 162, -267, +-20, -375, -218, -381, -303, -225, -246, 37, +-128, 291, 32, 443, 221, 433, 348, 261, +319, 39, 178, -122, 19, -182, -158, -188, +-342, -201, -397, -220, -272, -219, -45, -198, +197, -101, 399, 107, 497, 346, 384, 501, +91, 491, -228, 311, -441, -9, -495, -381, +-380, -620, -105, -583, 232, -307, 428, 68, +425, 384, 304, 519, 78, 406, -177, 102, +-323, -208, -307, -366, -150, -333, 40, -143, +158, 134, 201, 361, 148, 385, -8, 190, +-127, -89, -119, -319, -49, -401, -3, -301, +18, -87, 11, 120, -44, 217, -88, 216, +-41, 226, 88, 250, 199, 199, 191, 51, +87, -180, -51, -425, -219, -538, -322, -401, +-265, -33, -98, 365, 74, 575, 170, 528, +211, 281, 188, -53, 86, -335, -22, -441, +-75, -372, -101, -214, -136, -33, -151, 145, +-119, 280, -60, 319, -6, 255, 56, 158, +104, 55, 97, -86, 27, -214, -56, -299, +-71, -342, -45, -312, -10, -177, 45, 73, +85, 349, 33, 516, -95, 520, -185, 360, +-179, 56, -100, -290, 25, -531, 169, -574, +219, -441, 115, -199, -79, 92, -245, 340, +-263, 452, -141, 429, 59, 325, 264, 168, +323, -53, 174, -286, -79, -422, -278, -417, +-330, -270, -238, -19, -39, 225, 161, 340, +217, 257, 122, 53, -23, -112, -110, -155, +-96, -82, -15, 69, 99, 202, 178, 222, +119, 118, -56, -57, -213, -227, -280, -347, +-240, -370, -104, -231, 92, 43, 258, 323, +289, 479, 213, 446, 96, 236, -20, -71, +-111, -315, -148, -377, -129, -268, -109, -96, +-125, 47, -141, 129, -99, 140, 10, 76, +155, 1, 296, -25, 386, -11, 328, 27, +115, 72, -141, 102, -342, 60, -417, -72, +-330, -202, -117, -222, 124, -119, 286, 50, +321, 220, 269, 303, 160, 221, 20, 17, +-99, -190, -167, -302, -185, -288, -158, -171, +-74, 26, 59, 231, 190, 315, 245, 258, +205, 117, 106, -57, -40, -196, -169, -243, +-194, -172, -107, -44, 31, 45, 147, 86, +184, 106, 146, 91, 46, 33, -62, -31, +-84, -63, -20, -68, 58, -49, 99, 11, +70, 87, -34, 105, -142, 49, -172, -15, +-77, -50, 127, -76, 321, -90, 390, -73, +292, -32, 48, 19, -249, 88, -445, 154, +-435, 165, -256, 63, 2, -111, 262, -231, +427, -223, 442, -99, 337, 103, 150, 296, +-69, 341, -278, 186, -413, -83, -419, -314, +-289, -412, -41, -348, 226, -113, 413, 205, +465, 417, 338, 424, 100, 267, -121, 33, +-274, -182, -337, -286, -289, -254, -182, -148, +-67, -68, 61, -35, 192, 18, 281, 110, +300, 185, 221, 198, 48, 133, -134, 1, +-269, -130, -316, -161, -237, -52, -95, 91, +26, 124, 103, 27, 146, -121, 168, -242, +177, -249, 144, -92, 50, 136, -110, 291, +-289, 301, -377, 203, -307, 69, -83, -69, +197, -175, 384, -217, 379, -206, 179, -181, +-128, -119, -375, 12, -424, 163, -282, 262, +-41, 274, 194, 198, 300, 52, 230, -118, +70, -232, -91, -217, -192, -117, -196, -21, +-140, 38, -61, 60, -2, 44, 14, 16, +3, 29, -12, 68, -30, 71, -35, 20, +-19, -37, 17, -46, 73, -12, 97, 39, +88, 77, 37, 62, -83, -26, -230, -142, +-311, -208, -284, -197, -162, -126, 23, -15, +212, 137, 317, 291, 293, 370, 160, 348, +-2, 211, -118, -28, -200, -296, -236, -485, +-230, -515, -214, -389, -185, -164, -96, 111, +79, 383, 283, 562, 425, 578, 421, 426, +249, 126, -54, -253, -372, -568, -528, -671, +-462, -508, -240, -166, 22, 198, 220, 442, +291, 493, 247, 341, 155, 105, 113, -81, +130, -175, 103, -186, -6, -162, -164, -135, +-332, -111, -417, -89, -322, -28, -59, 107, +262, 249, 483, 294, 500, 215, 326, 52, +26, -144, -287, -287, -450, -290, -386, -177, +-164, -34, 114, 74, 338, 147, 414, 187, +299, 194, 35, 150, -221, 50, -334, -100, +-259, -252, -44, -298, 228, -179, 418, 64, +370, 274, 110, 321, -198, 191, -397, -54, +-389, -278, -161, -334, 188, -193, 472, 44, +518, 223, 314, 271, -12, 201, -310, 50, +-451, -98, -378, -154, -121, -127, 189, -67, +391, -14, 422, 16, 333, 28, 150, 15, +-84, -8, -243, -9, -278, 7, -248, 17, +-170, 29, -31, 62, 133, 86, 267, 64, +339, 1, 347, -79, 271, -130, 79, -115, +-184, -24, -389, 91, -438, 128, -338, 40, +-119, -116, 185, -226, 440, -199, 510, -16, +396, 250, 194, 440, -48, 421, -271, 186, +-375, -133, -345, -395, -236, -506, -99, -439, +44, -230, 201, 29, 323, 254, 328, 409, +254, 465, 146, 388, -25, 179, -221, -92, +-313, -330, -267, -448, -172, -407, -65, -222, +61, 24, 156, 216, 168, 286, 126, 232, +100, 109, 78, 2, 16, -46, -69, -14, +-122, 43, -154, 38, -187, -54, -175, -185, +-63, -272, 88, -236, 177, -59, 208, 186, +192, 361, 71, 368, -134, 214, -272, -24, +-264, -235, -155, -338, -9, -300, 120, -150, +196, 30, 138, 182, -31, 275, -163, 273, +-186, 162, -143, -29, -67, -217, 47, -322, +139, -290, 122, -124, 38, 110, -31, 313, +-70, 371, -111, 270, -149, 67, -122, -164, +-74, -337, -67, -377, -41, -271, 45, -79, +124, 125, 134, 280, 99, 344, 44, 295, +-50, 142, -179, -52, -259, -212, -221, -306, +-123, -288, -30, -146, 84, 44, 194, 181, +213, 201, 133, 119, 28, 5, -60, -66, +-152, -43, -236, 50, -235, 109, -138, 64, +-48, -61, 28, -175, 141, -198, 217, -121, +178, 22, 64, 154, -48, 201, -134, 164, +-200, 101, -194, 45, -66, -24, 75, -118, +118, -221, 85, -282, 45, -262, -25, -110, +-116, 155, -122, 412, -12, 521, 109, 409, +161, 114, 162, -264, 109, -569, -33, -647, +-209, -427, -281, -14, -201, 401, -61, 643, +88, 596, 231, 278, 302, -158, 227, -490, +56, -569, -69, -401, -113, -102, -148, 207, +-137, 404, -40, 425, 53, 295, 73, 106, +63, -87, 83, -252, 78, -340, 24, -326, +-24, -211, -18, -50, 11, 114, 18, 256, +38, 320, 103, 270, 117, 149, 30, 15, +-45, -112, -64, -203, -72, -230, -56, -188, +37, -112, 144, -24, 151, 65, 80, 136, +14, 151, -15, 97, -38, 28, -36, -21, +37, -41, 127, -24, 121, 19, 42, 47, +-29, 23, -95, -32, -166, -55, -161, -45, +1, -38, 214, -52, 346, -83, 371, -97, +286, -54, 43, 70, -275, 225, -484, 312, +-481, 238, -295, 20, -8, -211, 318, -335, +573, -303, 602, -135, 384, 62, 76, 170, +-210, 168, -441, 119, -526, 82, -379, 66, +-95, 31, 149, -34, 292, -117, 345, -198, +288, -215, 130, -118, -24, 57, -71, 219, +-53, 297, -59, 269, -88, 144, -114, -51, +-153, -252, -193, -367, -131, -356, 59, -230, +243, -9, 316, 247, 294, 418, 180, 427, +-17, 276, -225, 32, -332, -211, -301, -368, +-219, -379, -115, -239, 42, -41, 214, 117, +297, 213, 263, 229, 165, 167, 7, 75, +-200, -9, -341, -69, -312, -123, -159, -159, +16, -138, 157, -57, 237, 51, 204, 152, +49, 219, -111, 200, -201, 84, -236, -93, +-207, -259, -106, -339, 54, -310, 185, -146, +221, 121, 196, 375, 102, 490, -58, 413, +-216, 173, -301, -140, -274, -395, -176, -473, +-76, -352, 28, -131, 118, 68, 148, 184, +151, 204, 172, 157, 170, 108, 93, 106, +-54, 134, -221, 133, -363, 59, -417, -74, +-346, -232, -147, -359, 114, -377, 306, -229, +381, 28, 362, 273, 231, 426, 22, 431, +-181, 277, -317, 38, -357, -176, -315, -296, +-207, -309, -38, -258, 118, -153, 189, -14, +221, 108, 234, 197, 194, 243, 97, 225, +-33, 128, -170, -16, -289, -134, -343, -177, +-276, -164, -73, -102, 156, -9, 292, 62, +322, 86, 231, 66, 36, 30, -144, -5, +-209, -30, -154, -24, -57, 12, 17, 30, +56, 14, 49, -20, 8, -39, -7, -16, +33, 47, 79, 127, 64, 153, -12, 63, +-80, -119, -100, -299, -66, -367, 48, -265, +183, 0, 224, 324, 130, 545, -27, 531, +-157, 282, -211, -93, -151, -437, -1, -589, +153, -500, 237, -213, 195, 141, 77, 393, +-32, 453, -106, 324, -117, 76, -45, -170, +63, -291, 115, -244, 88, -82, 17, 109, +-51, 217, -86, 176, -56, 26, 63, -149, +206, -237, 266, -178, 208, -21, 72, 140, +-103, 213, -267, 169, -324, 47, -228, -74, +-27, -128, 179, -97, 317, -37, 356, 12, +283, 34, 122, 29, -36, 27, -123, 31, +-160, 28, -173, 5, -160, -39, -107, -79, +-28, -80, 47, -28, 135, 39, 216, 82, +227, 81, 164, 32, 83, -27, 28, -38, +-31, 9, -102, 70, -142, 86, -161, 28, +-169, -87, -129, -208, -10, -246, 153, -153, +259, 22, 267, 206, 202, 307, 66, 278, +-102, 139, -206, -36, -197, -171, -108, -217, +-17, -172, 34, -79, 51, 4, 31, 52, +-8, 50, -10, 7, 49, -33, 112, -36, +107, 2, 40, 76, -51, 164, -140, 204, +-197, 152, -169, 9, -54, -167, 76, -304, +156, -330, 175, -209, 146, 6, 39, 221, +-112, 319, -209, 259, -209, 91, -143, -99, +-52, -212, 68, -189, 160, -52, 136, 104, +37, 190, -37, 169, -78, 63, -122, -85, +-136, -216, -89, -255, -38, -195, -7, -70, +54, 91, 125, 239, 139, 312, 57, 270, +-95, 124, -228, -64, -290, -213, -257, -271, +-90, -229, 155, -108, 327, 18, 320, 80, +151, 95, -75, 95, -292, 94, -403, 91, +-317, 83, -77, 52, 145, -10, 231, -89, +201, -129, 92, -123, -81, -96, -233, -54, +-229, -14, -87, 41, 54, 114, 153, 182, +218, 220, 184, 164, -11, -9, -253, -225, +-375, -368, -368, -341, -264, -139, -20, 146, +298, 389, 491, 445, 456, 275, 263, -7, +3, -261, -293, -382, -515, -333, -524, -152, +-325, 73, -46, 228, 206, 258, 400, 195, +451, 70, 290, -70, 14, -167, -200, -162, +-286, -52, -261, 82, -136, 167, 57, 164, +179, 35, 144, -170, 21, -319, -87, -308, +-126, -130, -90, 133, 25, 360, 197, 441, +293, 337, 202, 89, 1, -180, -176, -352, +-293, -384, -316, -302, -161, -134, 112, 62, +323, 203, 374, 271, 287, 274, 106, 205, +-123, 63, -314, -101, -332, -207, -160, -228, +60, -159, 244, -27, 353, 89, 308, 132, +100, 76, -138, -42, -277, -106, -263, -71, +-131, 34, 49, 150, 236, 194, 333, 115, +277, -60, 129, -211, -10, -231, -128, -114, +-216, 69, -218, 209, -129, 209, -3, 70, +90, -125, 144, -259, 204, -247, 226, -102, +177, 101, 132, 269, 98, 345, 13, 309, +-112, 158, -226, -52, -275, -269, -250, -458, +-164, -533, 15, -421, 251, -117, 426, 286, +468, 635, 387, 775, 194, 622, -101, 211, +-388, -297, -525, -692, -461, -809, -241, -622, +59, -241, 376, 207, 578, 561, 531, 684, +273, 571, -52, 284, -350, -86, -520, -414, +-460, -588, -186, -536, 151, -282, 380, 58, +434, 359, 340, 510, 139, 471, -95, 265, +-249, -21, -285, -259, -252, -402, -203, -441, +-123, -356, 28, -160, 194, 96, 297, 336, +347, 494, 331, 509, 167, 325, -113, 7, +-336, -299, -438, -482, -445, -480, -316, -331, +-49, -107, 234, 115, 393, 245, 409, 286, +335, 296, 155, 276, -117, 196, -334, 31, +-414, -171, -382, -349, -238, -443, 5, -354, +255, -77, 377, 240, 325, 440, 128, 442, +-123, 247, -334, -58, -426, -337, -326, -447, +-83, -350, 154, -110, 292, 168, 315, 374, +219, 459, 35, 377, -172, 136, -302, -152, +-298, -396, -240, -535, -157, -499, -16, -279, +116, 52, 172, 364, 189, 559, 189, 589, +124, 419, -18, 100, -188, -241, -314, -486, +-351, -561, -281, -453, -99, -212, 151, 81, +317, 316, 325, 407, 224, 361, 54, 231, +-146, 69, -301, -95, -342, -219, -272, -266, +-168, -262, -57, -195, 99, -60, 260, 92, +336, 224, 338, 293, 265, 273, 52, 169, +-263, 0, -536, -187, -660, -337, -566, -388, +-235, -301, 232, -105, 646, 157, 822, 394, +679, 484, 270, 404, -242, 184, -659, -93, +-806, -320, -648, -432, -275, -409, 179, -281, +528, -93, 637, 126, 506, 319, 216, 439, +-132, 429, -391, 240, -458, -62, -350, -355, +-143, -515, 90, -435, 272, -132, 334, 247, +277, 500, 162, 495, 20, 254, -119, -118, +-195, -440, -207, -548, -180, -426, -121, -140, +-41, 182, 49, 413, 141, 526, 240, 489, +329, 304, 351, 35, 273, -252, 72, -495, +-205, -636, -460, -596, -594, -339, -530, 44, +-251, 437, 179, 733, 605, 809, 855, 604, +825, 170, 501, -341, -27, -743, -563, -898, +-886, -734, -872, -284, -528, 282, 17, 740, +542, 896, 855, 714, 865, 270, 581, -293, +113, -725, -346, -838, -648, -633, -720, -209, +-517, 278, -119, 653, 294, 776, 594, 612, +701, 261, 565, -159, 221, -532, -183, -745, +-476, -731, -583, -459, -498, -13, -213, 447, +183, 788, 491, 870, 605, 598, 521, 81, +250, -456, -119, -794, -415, -826, -514, -537, +-412, -39, -157, 415, 145, 643, 378, 605, +461, 361, 360, 36, 136, -257, -97, -427, +-263, -431, -310, -309, -245, -107, -101, 130, +71, 345, 173, 452, 186, 373, 179, 134, +139, -161, 23, -430, -82, -535, -115, -382, +-134, -54, -133, 297, -62, 526, 24, 531, +53, 301, 46, -65, 53, -385, 79, -527, +90, -445, 79, -183, 54, 115, -43, 341, +-201, 438, -296, 354, -270, 160, -130, -39, +94, -206, 301, -308, 391, -324, 314, -257, +84, -141, -205, 12, -410, 198, -452, 366, +-334, 462, -95, 430, 176, 218, 353, -116, +364, -472, 220, -732, 9, -741, -189, -447, +-318, 63, -306, 608, -158, 978, 12, 1017, +133, 656, 166, 13, 77, -677, -72, -1175, +-198, -1272, -199, -901, -54, -163, 132, 708, +262, 1373, 270, 1548, 100, 1135, -179, 250, +-417, -773, -495, -1538, -360, -1713, -75, -1197, +242, -225, 471, 810, 517, 1518, 332, 1623, +-14, 1113, -359, 223, -596, -687, -626, -1296, +-391, -1423, 1, -1052, 390, -333, 642, 470, +633, 1094, 367, 1313, -41, 1082, -455, 480, +-712, -325, -724, -1021, -493, -1341, -107, -1184, +318, -605, 659, 215, 795, 995, 668, 1427, +310, 1346, -159, 794, -619, -56, -938, -930, +-943, -1513, -598, -1589, -47, -1091, 540, -178, +973, 826, 1062, 1602, 763, 1851, 190, 1417, +-435, 441, -877, -719, -1025, -1648, -852, -2016, +-390, -1665, 190, -680, 683, 567, 967, 1609, +963, 2093, 643, 1830, 83, 893, -538, -391, +-978, -1548, -1071, -2136, -811, -1935, -251, -1015, +460, 285, 1012, 1471, 1173, 2095, 949, 1911, +415, 1027, -294, -176, -896, -1284, -1161, -1883, +-1022, -1770, -540, -1067, 114, -59, 751, 917, +1147, 1559, 1138, 1676, 765, 1250, 157, 440, +-517, -513, -1022, -1324, -1163, -1718, -891, -1550, +-293, -825, 417, 241, 981, 1258, 1213, 1860, +1027, 1800, 468, 1053, -256, -121, -858, -1277, +-1148, -1955, -1039, -1921, -542, -1172, 188, 36, +864, 1225, 1207, 1960, 1134, 1982, 674, 1275, +-65, 107, -780, -1102, -1161, -1909, -1113, -2021, +-673, -1412, 18, -297, 717, 914, 1156, 1789, +1166, 2041, 778, 1562, 152, 523, -531, -695, +-1027, -1676, -1125, -2055, -821, -1672, -259, -668, +393, 577, 914, 1597, 1111, 2004, 923, 1639, +426, 661, -188, -523, -712, -1483, -980, -1860, +-909, -1504, -518, -620, 28, 445, 530, 1324, +854, 1692, 904, 1434, 657, 667, 202, -326, +-301, -1199, -697, -1643, -873, -1476, -756, -755, +-374, 280, 141, 1239, 592, 1710, 808, 1509, +758, 713, 448, -390, -30, -1337, -449, -1714, +-662, -1390, -649, -527, -418, 529, -54, 1365, +292, 1633, 505, 1247, 496, 394, 298, -617, +28, -1391, -230, -1623, -382, -1213, -352, -290, +-187, 774, 1, 1532, 141, 1678, 211, 1141, +193, 131, 101, -937, 6, -1605, -41, -1594, +-67, -970, -109, -4, -168, 937, -211, 1452, +-217, 1371, -156, 810, 20, 5, 263, -744, +455, -1180, 486, -1154, 296, -712, -41, -45, +-427, 616, -723, 1005, -757, 984, -507, 573, +-76, -84, 402, -685, 770, -942, 893, -782, +700, -279, 238, 359, -319, 823, -791, 903, +-1028, 570, -934, -13, -514, -607, 86, -971, +636, -923, 975, -483, 1023, 182, 726, 824, +162, 1159, -463, 1049, -949, 496, -1141, -323, +-967, -1062, -464, -1399, 226, -1192, 847, -489, +1163, 467, 1091, 1293, 628, 1634, -102, 1323, +-819, 465, -1251, -625, -1223, -1526, -733, -1844, +27, -1422, 793, -420, 1268, 789, 1224, 1728, +698, 2002, -82, 1492, -836, 387, -1276, -908, +-1223, -1867, -702, -2096, 85, -1534, 829, -376, +1254, 958, 1217, 1918, 728, 2145, -52, 1579, +-815, 418, -1263, -916, -1252, -1922, -804, -2219, +-62, -1699, 729, -527, 1250, 896, 1322, 2007, +918, 2380, 160, 1855, -665, 574, -1286, -972, +-1423, -2157, -968, -2521, -156, -1892, 725, -505, +1373, 1090, 1460, 2257, 949, 2525, 53, 1816, +-875, 401, -1431, -1166, -1415, -2252, -814, -2465, +185, -1726, 1111, -311, 1550, 1215, 1354, 2260, +598, 2415, -411, 1620, -1265, 184, -1604, -1327, +-1253, -2288, -385, -2334, 627, -1454, 1436, 3, +1701, 1433, 1258, 2251, 313, 2166, -756, 1241, +-1538, -137, -1710, -1407, -1210, -2087, -242, -1949, +823, -1091, 1552, 138, 1684, 1260, 1225, 1871, +358, 1783, -626, 1027, -1365, -85, -1607, -1108, +-1296, -1700, -536, -1642, 405, -948, 1208, 85, +1596, 1044, 1409, 1566, 737, 1455, -143, 771, +-948, -174, -1422, -996, -1367, -1386, -812, -1196, +-25, -541, 711, 263, 1164, 912, 1182, 1181, +794, 949, 176, 362, -393, -305, -715, -819, +-795, -987, -636, -753, -307, -225, 20, 343, +281, 727, 483, 815, 584, 554, 530, 87, +352, -368, 92, -656, -220, -651, -507, -370, +-684, 28, -650, 368, -369, 541, 52, 482, +492, 219, 832, -88, 897, -305, 610, -386, +87, -295, -482, -77, -908, 105, -1028, 164, +-791, 127, -277, 23, 353, -64, 900, -31, +1189, 120, 1094, 275, 602, 306, -176, 151, +-994, -192, -1504, -556, -1492, -726, -930, -596, +93, -135, 1207, 512, 1895, 1035, 1867, 1179, +1089, 837, -195, 64, -1481, -872, -2246, -1544, +-2140, -1631, -1159, -1051, 290, 43, 1636, 1244, +2407, 2045, 2271, 2088, 1220, 1295, -275, -105, +-1661, -1580, -2513, -2531, -2460, -2574, -1460, -1583, +120, 141, 1681, 1919, 2613, 3046, 2570, 3031, +1539, 1768, -116, -318, -1731, -2344, -2683, -3483, +-2587, -3256, -1472, -1652, 190, 661, 1758, 2727, +2628, 3726, 2453, 3187, 1283, 1327, -413, -1061, +-1934, -3044, -2678, -3813, -2343, -3023, -1023, -1010, +735, 1433, 2166, 3343, 2695, 3946, 2111, 2980, +641, 772, -1120, -1815, -2443, -3747, -2707, -4237, +-1830, -3000, -249, -502, 1455, 2288, 2570, 4248, +2540, 4485, 1428, 2889, -255, 93, -1818, -2828, +-2605, -4636, -2271, -4539, -959, -2598, 746, 420, +2131, 3340, 2600, 4900, 1934, 4449, 429, 2209, +-1307, -985, -2535, -3849, -2683, -5119, -1671, -4294, +91, -1735, 1858, 1611, 2896, 4337, 2745, 5228, +1429, 4009, -530, 1190, -2345, -2161, -3229, -4598, +-2793, -5093, -1208, -3588, 949, -689, 2787, 2485, +3485, 4540, 2752, 4723, 875, 3103, -1424, 247, +-3202, -2646, -3651, -4341, -2554, -4252, -413, -2471, +1921, 284, 3511, 2839, 3694, 4091, 2359, 3600, +9, 1663, -2355, -936, -3752, -3039, -3654, -3719, +-2067, -2854, 376, -837, 2658, 1521, 3857, 3099, +3508, 3314, 1766, 2209, -668, 148, -2788, -1936, +-3751, -3090, -3227, -2951, -1440, -1580, 891, 481, +2843, 2277, 3643, 3008, 2959, 2444, 1085, 792, +-1171, -1219, -2886, -2564, -3377, -2693, -2472, -1612, +-604, 235, 1457, 1923, 2895, 2614, 3062, 2075, +1966, 596, 185, -1173, -1621, -2359, -2743, -2422, +-2681, -1421, -1536, 212, 173, 1761, 1769, 2515, +2618, 2188, 2374, 961, 1161, -703, -467, -2083, +-1801, -2539, -2339, -1960, -1926, -572, -732, 1089, +722, 2247, 1778, 2422, 2033, 1587, 1433, 77, +275, -1451, -913, -2281, -1640, -2099, -1609, -1038, +-880, 483, 187, 1743, 1107, 2158, 1478, 1674, +1196, 498, 402, -921, -533, -1879, -1166, -1980, +-1272, -1320, -816, -87, -11, 1227, 778, 1969, +1251, 1884, 1151, 1004, 496, -357, -347, -1573, +-1037, -2037, -1316, -1583, -996, -462, -193, 902, +703, 1798, 1329, 1766, 1397, 997, 840, -177, +-61, -1254, -953, -1642, -1492, -1237, -1418, -357, +-788, 619, 142, 1256, 1037, 1241, 1524, 684, +1406, -129, 763, -844, -101, -1095, -896, -782, +-1368, -125, -1300, 564, -801, 975, -71, 849, +656, 252, 1062, -482, 1083, -1023, 797, -1052, +255, -512, -320, 333, -731, 1105, -931, 1401, +-849, 1029, -477, 147, 29, -872, 511, -1586, +850, -1640, 891, -963, 582, 180, 64, 1302, +-482, 1926, -852, 1767, -874, 811, -585, -554, +-135, -1724, 368, -2183, 769, -1647, 895, -365, +717, 1095, 253, 2087, -388, 2091, -938, 1127, +-1170, -325, -931, -1611, -249, -2128, 600, -1651, +1268, -426, 1421, 962, 925, 1909, -15, 1961, +-981, 1093, -1551, -243, -1513, -1502, -847, -2123, +213, -1720, 1208, -481, 1743, 973, 1557, 2045, +692, 2205, -450, 1264, -1429, -270, -1886, -1709, +-1591, -2428, -625, -1984, 572, -614, 1559, 1027, +1988, 2251, 1593, 2481, 549, 1592, -685, 3, +-1710, -1605, -2080, -2572, -1600, -2457, -484, -1279, +848, 502, 1844, 2135, 2052, 2892, 1421, 2436, +274, 901, -969, -1116, -1877, -2711, -1984, -3134, +-1255, -2182, -63, -243, 1186, 1835, 1935, 3082, +1813, 2970, 946, 1558, -326, -541, -1478, -2337, +-1916, -3049, -1464, -2415, -438, -737, 750, 1240, +1610, 2588, 1662, 2722, 986, 1682, -14, -115, +-1021, -1845, -1582, -2682, -1420, -2324, -655, -892, +402, 994, 1268, 2417, 1566, 2732, 1221, 1831, +339, 59, -696, -1840, -1379, -2906, -1454, -2649, +-897, -1219, 53, 834, 915, 2572, 1347, 3125, +1155, 2273, 416, 392, -450, -1717, -1039, -3042, +-1098, -2961, -593, -1555, 205, 584, 898, 2469, +1113, 3192, 737, 2459, 5, 613, -747, -1527, +-1156, -2987, -1058, -3083, -482, -1774, 403, 366, +1176, 2351, 1481, 3247, 1194, 2727, 359, 985, +-723, -1260, -1588, -2889, -1779, -3202, -1204, -2164, +-105, -114, 1139, 2007, 1941, 3101, 1899, 2862, +1066, 1390, -229, -790, -1416, -2514, -1989, -3040, +-1767, -2287, -795, -480, 548, 1596, 1637, 2837, +2006, 2757, 1565, 1552, 487, -404, -803, -2205, +-1721, -2886, -1934, -2349, -1357, -833, -188, 1111, +1065, 2466, 1902, 2701, 1957, 1881, 1172, 253, +-120, -1468, -1371, -2450, -2035, -2414, -1851, -1420, +-848, 181, 556, 1657, 1659, 2373, 2042, 2077, +1552, 926, 356, -620, -900, -1873, -1744, -2256, +-1913, -1666, -1170, -330, 108, 1135, 1234, 2010, +1866, 2007, 1703, 1132, 698, -235, -545, -1402, +-1463, -1947, -1803, -1676, -1318, -678, -233, 481, +827, 1391, 1505, 1777, 1549, 1367, 864, 469, +-129, -500, -985, -1298, -1491, -1555, -1313, -1157, +-469, -372, 514, 476, 1265, 1132, 1490, 1314, +958, 972, 4, 364, -875, -347, -1429, -938, +-1384, -1118, -690, -906, 228, -453, 974, 169, +1397, 751, 1246, 1030, 549, 976, -261, 612, +-994, -12, -1396, -660, -1132, -1093, -451, -1113, +316, -700, 989, 0, 1200, 778, 865, 1245, +274, 1172, -402, 625, -964, -244, -1046, -1062, +-682, -1383, -166, -1097, 455, -333, 909, 669, +874, 1437, 536, 1521, 33, 902, -542, -136, +-829, -1237, -734, -1850, -472, -1555, -60, -545, +402, 759, 597, 1860, 586, 2101, 511, 1315, +188, -56, -190, -1468, -403, -2273, -605, -1953, +-648, -706, -406, 831, -83, 2055, 259, 2306, +595, 1377, 732, -185, 569, -1668, 222, -2406, +-216, -1955, -624, -515, -724, 1173, -536, 2363, +-250, 2456, 133, 1287, 440, -519, 504, -2114, +441, -2784, 286, -2072, 58, -314, -157, 1602, +-363, 2806, -519, 2655, -519, 1147, -352, -929, +-10, -2572, 415, -2991, 721, -1862, 807, 224, +590, 2195, 61, 3173, -569, 2559, -1042, 595, +-1136, -1659, -724, -3194, 16, -3229, 762, -1629, +1271, 754, 1302, 2822, 746, 3650, -110, 2723, +-908, 509, -1370, -1946, -1260, -3547, -694, -3481, +142, -1787, 994, 703, 1418, 2858, 1339, 3662, +773, 2714, -218, 567, -1091, -1776, -1554, -3301, +-1517, -3177, -780, -1591, 298, 586, 1259, 2507, +1868, 3198, 1699, 2330, 738, 519, -451, -1486, +-1478, -2814, -2030, -2722, -1647, -1376, -507, 493, +754, 2103, 1774, 2667, 2058, 1909, 1360, 299, +153, -1338, -1099, -2259, -1938, -2097, -1894, -890, +-990, 661, 358, 1692, 1567, 1940, 2153, 1277, +1796, 1, 551, -1040, -934, -1507, -2062, -1364, +-2378, -591, -1540, 303, 48, 823, 1658, 1006, +2679, 828, 2478, 376, 1105, 7, -742, -286, +-2411, -554, -3091, -649, -2266, -679, -377, -581, +1739, -138, 3168, 422, 3150, 977, 1639, 1329, +-713, 972, -2798, 112, -3557, -933, -2619, -1819, +-382, -1727, 2116, -732, 3613, 700, 3396, 2073, +1521, 2348, -1155, 1364, -3271, -339, -3827, -2095, +-2560, -2751, 34, -1948, 2596, -196, 3855, 1811, +3339, 2867, 1154, 2391, -1590, 802, -3417, -1295, +-3649, -2690, -2102, -2555, 503, -1219, 2628, 806, +3431, 2344, 2645, 2430, 581, 1311, -1594, -526, +-2893, -2037, -2778, -2181, -1363, -1118, 535, 534, +2030, 1865, 2463, 1917, 1777, 806, 366, -686, +-1153, -1756, -1932, -1684, -1778, -526, -954, 817, +328, 1582, 1309, 1419, 1557, 353, 1246, -797, +365, -1208, -674, -938, -1377, -205, -1573, 513, +-1014, 528, 98, 154, 1197, -81, 1884, -61, +1698, 393, 543, 859, -1014, 625, -2235, -319, +-2411, -1379, -1267, -1876, 659, -1275, 2358, 406, +2942, 2099, 2063, 2672, 55, 1794, -2141, -220, +-3292, -2296, -2799, -3062, -992, -2105, 1364, -110, +3097, 1958, 3294, 2915, 1996, 2188, -223, 512, +-2373, -1236, -3373, -2283, -2912, -2064, -1222, -950, +1074, 376, 2851, 1430, 3387, 1775, 2613, 1300, +606, 380, -1831, -633, -3480, -1419, -3714, -1502, +-2252, -906, 381, 72, 2872, 1080, 4116, 1542, +3414, 1227, 977, 310, -1903, -773, -3809, -1432, +-3841, -1383, -1987, -657, 699, 411, 2822, 1209, +3434, 1401, 2406, 955, 328, 6, -1621, -863, +-2482, -1252, -2160, -1154, -902, -452, 568, 457, +1362, 1045, 1383, 1236, 800, 835, -48, -69, +-545, -906, -576, -1318, -269, -1114, 180, -211, +294, 859, 46, 1435, -244, 1290, -442, 380, +-373, -811, 8, -1504, 422, -1318, 618, -410, +478, 651, 70, 1322, -282, 1197, -408, 416, +-376, -389, -210, -921, -64, -980, -59, -552, +17, -47, 280, 366, 621, 753, 821, 942, +579, 787, -186, 301, -1179, -594, -1754, -1586, +-1406, -1873, -186, -1075, 1399, 566, 2441, 2275, +2219, 2916, 812, 1795, -1048, -543, -2526, -2697, +-2821, -3406, -1665, -2130, 250, 384, 2097, 2499, +3056, 3066, 2551, 2036, 840, 107, -1388, -1595, +-3073, -2193, -3251, -1884, -1766, -1013, 797, 294, +3041, 1457, 3710, 2184, 2457, 2155, -258, 836, +-2837, -1293, -3781, -2952, -2775, -3150, -285, -1402, +2357, 1572, 3614, 3689, 2999, 3642, 1030, 1468, +-1372, -1736, -3006, -3817, -3037, -3645, -1710, -1555, +280, 1310, 2203, 3272, 3001, 3496, 2302, 2044, +648, -294, -1359, -2371, -2736, -3425, -2721, -2870, +-1420, -955, 636, 1418, 2418, 3289, 2980, 3593, +2087, 2114, 96, -388, -1979, -2762, -3069, -3832, +-2657, -3060, -819, -846, 1467, 1768, 2925, 3573, +2922, 3769, 1379, 2165, -930, -574, -2606, -3036, +-2951, -4060, -1834, -3084, 281, -495, 2114, 2215, +2835, 3741, 2259, 3380, 502, 1373, -1471, -1048, +-2629, -2816, -2605, -3240, -1264, -2224, 779, -377, +2388, 1673, 2855, 3069, 1923, 3025, -89, 1593, +-2035, -762, -2849, -2943, -2292, -3458, -568, -2102, +1450, 319, 2686, 2577, 2643, 3106, 1326, 1838, +-627, -190, -2232, -1864, -2752, -2167, -1967, -1207, +-262, 161, 1597, 1127, 2651, 1296, 2318, 747, +892, -131, -986, -766, -2323, -968, -2346, -640, +-1227, 148, 520, 791, 1910, 1014, 2165, 661, +1258, -220, -375, -878, -1732, -938, -2072, -488, +-1215, 277, 394, 748, 1684, 617, 1873, 193, +932, -317, -604, -540, -1716, -320, -1660, 37, +-580, 401, 766, 485, 1475, 242, 1147, -135, +97, -591, -856, -665, -1067, -255, -534, 302, +310, 808, 831, 863, 674, 275, 4, -524, +-712, -984, -973, -928, -529, -368, 301, 421, +1071, 906, 1473, 996, 961, 807, -286, 227, +-1451, -554, -2078, -1168, -1603, -1464, -27, -1107, +1614, 54, 2533, 1282, 2154, 1930, 500, 1626, +-1371, 353, -2485, -1024, -2261, -1779, -848, -1588, +855, -665, 1975, 371, 1963, 1075, 982, 1205, +-351, 980, -1393, 511, -1605, -227, -1014, -881, +-28, -1260, 893, -1150, 1197, -408, 838, 552, +182, 1258, -544, 1297, -906, 651, -636, -160, +-199, -720, 196, -874, 486, -613, 284, -229, +-38, 13, -92, 178, -200, 311, -33, 360, +294, 392, 146, 322, 81, 81, -46, -56, +-420, -183, -333, -394, -73, -433, 138, -433, +370, -297, 277, 145, 1, 562, -181, 760, +-222, 580, 19, 64, 389, -445, 497, -629, +303, -403, -222, -24, -743, 278, -792, 189, +-501, -166, 175, -338, 933, -213, 1101, 282, +843, 787, 129, 835, -750, 387, -1095, -498, +-967, -1212, -322, -1218, 520, -583, 920, 417, +780, 1221, 212, 1268, -391, 617, -624, -220, +-359, -871, 94, -934, 297, -483, 220, -11, +-134, 343, -419, 494, -212, 430, 110, 305, +339, 130, 424, -193, 72, -665, -317, -818, +-342, -489, -202, 166, 0, 1055, 216, 1426, +113, 855, -103, -177, -10, -1290, 76, -1847, +56, -1205, 141, -14, 0, 1138, -199, 1903, +-60, 1512, 41, 404, 128, -723, 242, -1628, +52, -1671, -142, -897, -165, 222, -148, 1265, +13, 1642, 255, 1313, 332, 322, 292, -832, +117, -1519, -232, -1579, -543, -866, -632, 260, +-277, 1238, 443, 1697, 1018, 1401, 1036, 434, +461, -785, -572, -1612, -1393, -1742, -1393, -1116, +-644, 125, 545, 1269, 1461, 1815, 1602, 1605, +884, 611, -308, -645, -1287, -1572, -1730, -1848, +-1266, -1311, -170, -135, 887, 1067, 1611, 1756, +1484, 1767, 429, 916, -738, -389, -1417, -1424, +-1301, -1861, -448, -1417, 496, -315, 1010, 891, +832, 1724, 137, 1694, -425, 850, -536, -410, +-324, -1518, 67, -1822, 270, -1266, 190, 61, +40, 1412, -143, 1903, -99, 1504, 85, 233, +167, -1201, 198, -1856, 50, -1577, -182, -586, +-349, 679, -296, 1439, 54, 1431, 512, 988, +783, 225, 507, -633, -224, -1163, -930, -1343, +-1183, -1120, -657, -301, 482, 776, 1442, 1577, +1513, 1690, 713, 978, -628, -377, -1635, -1506, +-1637, -1857, -813, -1398, 492, -119, 1501, 1146, +1599, 1791, 922, 1678, -213, 720, -1268, -556, +-1613, -1599, -1280, -1981, -363, -1308, 862, 36, +1552, 1340, 1475, 2058, 794, 1700, -343, 405, +-1341, -991, -1650, -1858, -1276, -1784, -375, -742, +738, 468, 1499, 1372, 1608, 1704, 1018, 1073, +-96, 58, -1204, -841, -1635, -1420, -1352, -1274, +-445, -491, 770, 417, 1436, 1070, 1315, 1153, +640, 589, -239, -101, -866, -593, -983, -766, +-638, -491, -97, -54, 471, 227, 805, 318, +751, 291, 344, 180, -257, -9, -786, -135, +-838, -183, -318, -256, 340, -87, 798, 72, +870, 186, 402, 374, -294, 240, -663, -68, +-683, -221, -347, -395, 10, -446, 91, -151, +282, 180, 383, 393, 276, 469, 247, 414, +121, 178, -245, -153, -506, -412, -460, -595, +-366, -655, -75, -331, 210, 221, 205, 725, +424, 1039, 438, 728, 37, -37, 46, -695, +-187, -1017, -599, -785, -432, -89, -256, 523, +-35, 640, 347, 417, 446, 89, 415, -226, +420, -220, 159, -61, -322, 3, -567, 140, +-606, 134, -472, 73, 140, -27, 763, -346, +874, -533, 582, -427, -48, -39, -636, 586, +-754, 991, -421, 830, 14, 203, 394, -536, +575, -1072, 338, -989, 163, -456, 56, 58, +-180, 641, -252, 1000, -359, 871, -450, 550, +-184, -111, 155, -1010, 404, -1416, 545, -1017, +511, 7, 221, 1144, -220, 1670, -546, 1041, +-776, -283, -709, -1301, -261, -1464, 344, -569, +973, 781, 1036, 1271, 394, 793, -357, -175, +-978, -1146, -1122, -1083, -508, -106, 363, 933, +889, 1383, 794, 788, 312, -409, -173, -1333, +-462, -1470, -429, -588, -271, 730, -170, 1555, +-146, 1350, -64, 267, 287, -904, 663, -1471, +782, -1016, 526, 131, -89, 1084, -722, 1093, +-1261, 291, -1020, -644, -58, -1025, 768, -492, +1462, 537, 1479, 1144, 570, 823, -635, -140, +-1706, -1183, -1917, -1431, -858, -648, 691, 469, +1843, 1364, 2210, 1585, 1239, 736, -612, -487, +-1954, -1352, -2176, -1680, -1246, -1004, 306, 305, +1529, 1413, 1852, 1877, 1096, 1244, -208, -246, +-1066, -1565, -1231, -1975, -775, -1181, 20, 357, +530, 1599, 581, 1733, 313, 713, -8, -625, +-110, -1369, -13, -1043, 41, 12, -139, 934, +-494, 1075, -697, 198, -447, -832, 316, -1226, +1155, -772, 1303, 417, 760, 1436, -419, 1389, +-1506, 388, -1619, -868, -921, -1602, 368, -1191, +1397, 135, 1503, 1314, 904, 1487, -88, 627, +-875, -791, -992, -1650, -691, -1261, -277, -58, +212, 1184, 505, 1716, 705, 1128, 733, -107, +409, -1023, -59, -1432, -685, -1153, -1129, -409, +-896, 358, -149, 1074, 765, 1377, 1384, 1169, +1173, 476, 280, -712, -928, -1668, -1605, -1737, +-1239, -957, -217, 400, 970, 1467, 1536, 1685, +1220, 1074, 231, 61, -971, -711, -1418, -1002, +-1049, -934, -354, -701, 400, -384, 825, 144, +867, 820, 649, 1230, 242, 1161, -160, 490, +-555, -616, -938, -1447, -1007, -1429, -462, -701, +335, 271, 942, 1107, 1210, 1307, 836, 896, +53, 226, -620, -571, -962, -1118, -818, -1149, +-447, -712, -44, 114, 303, 1028, 619, 1411, +928, 921, 854, 1, 580, -877, -90, -1344, +-1090, -980, -1513, -72, -1300, 704, -480, 1104, +827, 986, 1731, 429, 1884, -274, 1209, -904, +-321, -1287, -1606, -1081, -2042, -308, -1667, 702, +-287, 1604, 1261, 1802, 2084, 1050, 1904, -317, +706, -1554, -896, -2122, -1951, -1729, -1998, -456, +-1089, 965, 431, 1952, 1659, 2119, 1809, 1306, +1181, -4, 64, -1308, -1133, -2035, -1526, -1861, +-1156, -943, -297, 396, 629, 1420, 928, 1850, +753, 1581, 337, 626, -210, -492, -447, -1357, +-375, -1763, -266, -1425, -113, -450, 18, 631, +136, 1456, 378, 1679, 510, 1077, 416, 111, +38, -730, -529, -1304, -932, -1287, -862, -796, +-188, -133, 632, 553, 1156, 1114, 1191, 1268, +605, 918, -304, 260, -1100, -602, -1378, -1322, +-961, -1460, -129, -1037, 768, -230, 1330, 844, +1286, 1654, 742, 1827, -210, 1289, -1071, -12, +-1398, -1544, -1203, -2434, -511, -2219, 490, -804, +1231, 1244, 1448, 2613, 1171, 2559, 214, 1194, +-797, -804, -1427, -2188, -1587, -2206, -845, -1114, +296, 346, 1126, 1289, 1495, 1342, 1074, 806, +92, 175, -695, -219, -1177, -387, -1085, -436, +-378, -557, 285, -702, 694, -470, 847, 7, +580, 597, 103, 1069, -223, 1064, -512, 573, +-539, -171, -266, -839, -94, -1194, -10, -1016, +52, -488, 98, 175, 220, 787, 460, 1017, +637, 842, 517, 483, 66, -7, -609, -423, +-1106, -663, -962, -777, -401, -714, 306, -432, +964, 62, 1031, 583, 644, 1034, 94, 1053, +-494, 610, -539, -76, -351, -776, -308, -1166, +-127, -1083, -71, -540, -103, 132, 140, 777, +404, 1151, 553, 1042, 577, 629, 164, -54, +-460, -790, -798, -1126, -810, -1139, -452, -765, +205, -26, 747, 705, 782, 1224, 543, 1350, +123, 971, -392, 85, -606, -894, -623, -1493, +-446, -1535, -3, -822, 372, 292, 503, 1127, +504, 1455, 269, 1153, -153, 357, -388, -364, +-368, -885, -181, -1104, 142, -895, 265, -507, +65, 201, -16, 959, -135, 1258, -205, 1080, +2, 237, 81, -835, 164, -1374, 279, -1206, +225, -304, 93, 785, -74, 1226, -348, 941, +-490, 110, -372, -693, -170, -953, 239, -618, +534, 74, 510, 581, 440, 698, 260, 534, +78, 68, -247, -352, -769, -569, -1115, -757, +-1132, -587, -539, -167, 702, 337, 1947, 993, +2449, 1287, 1660, 992, -142, 216, -2140, -904, +-3372, -1776, -2932, -1912, -1030, -1155, 1567, 288, +3600, 1726, 3828, 2468, 2258, 2090, -413, 713, +-2984, -1074, -4101, -2436, -3151, -2603, -727, -1587, +1959, 99, 3537, 1796, 3312, 2484, 1546, 1986, +-868, 695, -2554, -949, -2856, -1924, -1760, -1813, +72, -960, 1554, 290, 2176, 1273, 1678, 1394, +294, 793, -947, -102, -1536, -817, -1398, -1024, +-462, -602, 584, 130, 1198, 725, 1265, 889, +620, 609, -243, -16, -900, -725, -1256, -981, +-967, -846, -182, -307, 653, 492, 1285, 944, +1324, 993, 687, 688, -336, 31, -1236, -537, +-1538, -775, -992, -790, 38, -602, 870, -230, +1343, 141, 1096, 463, 283, 825, -381, 916, +-867, 702, -876, 193, -473, -555, -101, -1053, +370, -1202, 497, -853, 289, -114, 174, 515, +-40, 941, -149, 1010, 31, 777, 203, 468, +226, 85, 31, -394, -271, -924, -543, -1309, +-615, -1340, -405, -826, -44, 326, 472, 1488, +841, 2118, 957, 1943, 905, 763, 356, -770, +-481, -1998, -1325, -2330, -1817, -1661, -1421, -391, +-422, 995, 919, 1773, 2270, 1840, 2545, 1301, +1540, 286, -109, -573, -1933, -1145, -3013, -1494, +-2621, -1255, -985, -726, 1215, 42, 2992, 966, +3173, 1572, 1769, 1603, -400, 912, -2450, -262, +-3101, -1355, -2078, -1738, -196, -1262, 1668, -191, +2472, 909, 1833, 1398, 440, 1035, -918, 190, +-1616, -619, -1306, -1003, -477, -748, 334, -35, +850, 685, 866, 1028, 454, 832, 75, 76, +-139, -841, -491, -1379, -668, -1291, -602, -524, +-453, 654, 73, 1472, 767, 1526, 1194, 1064, +1212, 137, 592, -748, -574, -1074, -1497, -1188, +-1748, -1050, -1354, -564, -220, -89, 1143, 569, +1907, 1301, 1954, 1500, 1253, 1275, -108, 651, +-1392, -421, -2165, -1290, -2058, -1758, -1062, -1768, +331, -1081, 1670, -23, 2266, 1167, 1890, 2119, +819, 2177, -564, 1494, -1669, 218, -1984, -1246, +-1618, -2102, -792, -2251, 394, -1659, 1289, -480, +1644, 845, 1602, 1949, 986, 2460, -25, 2128, +-893, 852, -1505, -819, -1658, -2163, -1228, -2754, +-461, -2083, 547, -611, 1420, 898, 1777, 2056, +1474, 2322, 714, 1761, -357, 718, -1491, -570, +-1877, -1717, -1539, -2205, -680, -1812, 582, -719, +1446, 778, 1745, 1900, 1384, 2023, 270, 1273, +-802, -83, -1406, -1251, -1472, -1637, -791, -1247, +195, -250, 966, 781, 1236, 1393, 903, 1180, +234, 382, -480, -583, -885, -1443, -838, -1483, +-529, -700, -9, 373, 522, 1384, 713, 1745, +740, 1286, 520, 366, -86, -691, -456, -1477, +-753, -1742, -961, -1436, -619, -670, -56, 488, +608, 1586, 1144, 2132, 1218, 1892, 799, 782, +-87, -623, -1040, -1805, -1543, -2229, -1350, -1665, +-497, -653, 531, 538, 1208, 1498, 1370, 1764, +950, 1529, 153, 751, -573, -364, -960, -1186, +-939, -1512, -521, -1155, 50, -297, 446, 520, +602, 802, 328, 482, -93, 9, -340, -343, +-224, -182, 305, 422, 635, 877, 609, 926, +216, 389, -582, -590, -1121, -1399, -1054, -1753, +-545, -1430, 174, -384, 754, 878, 1117, 1922, +1156, 2357, 855, 1891, 284, 635, -554, -869, +-1265, -2195, -1721, -2767, -1517, -2262, -398, -1030, +843, 771, 1793, 2428, 1952, 3063, 1128, 2575, +-94, 1019, -1173, -1144, -1563, -2668, -1063, -2905, +-123, -1883, 595, -40, 764, 1518, 332, 1993, +-485, 1434, -897, 364, -486, -561, 473, -720, +1516, -258, 1822, 183, 1012, 332, -507, 60, +-2059, -536, -2617, -892, -1852, -794, -238, -277, +1433, 472, 2367, 1021, 2265, 1210, 1178, 855, +-196, 195, -1199, -478, -1627, -960, -1505, -867, +-971, -586, -150, -279, 587, 1, 1003, 63, +1166, 201, 914, 491, 382, 966, -179, 1179, +-733, 706, -811, -95, -506, -1119, -216, -1761, +171, -1500, 285, -638, 122, 477, -71, 1201, +-189, 1343, 68, 1043, 405, 503, 590, 70, +642, -329, 280, -596, -316, -859, -839, -1140, +-1150, -979, -962, -427, -422, 296, 375, 1155, +1219, 1670, 1549, 1447, 1230, 681, 322, -380, +-804, -1312, -1500, -1551, -1398, -1178, -640, -435, +287, 386, 897, 676, 751, 562, 161, 420, +-249, 319, -288, 412, 105, 592, 681, 475, +790, -15, 283, -723, -468, -1310, -1165, -1455, +-1439, -1044, -1024, -101, -39, 945, 981, 1786, +1663, 2045, 1724, 1338, 988, 59, -219, -1262, +-1422, -2188, -1908, -2038, -1409, -910, -299, 457, +868, 1460, 1421, 1623, 1191, 1077, 351, 224, +-539, -453, -803, -644, -550, -570, -105, -437, +373, -306, 456, -257, 261, -47, 98, 275, +-142, 440, -298, 583, -412, 446, -532, 49, +-374, -237, 77, -331, 568, -266, 951, -146, +979, -6, 439, -48, -312, -243, -1003, -349, +-1317, -241, -937, 163, -211, 744, 431, 1122, +1000, 1051, 1166, 439, 630, -687, 71, -1692, +-428, -1965, -791, -1476, -574, -156, -291, 1459, +7, 2371, 329, 2402, 180, 1271, -8, -515, +-44, -1860, -146, -2502, 29, -1981, 203, -614, +336, 765, 491, 1674, 293, 1792, 39, 1231, +-351, 372, -799, -457, -967, -1018, -847, -1079, +-218, -863, 605, -476, 1288, 130, 1649, 515, +1243, 638, 343, 627, -670, 343, -1691, 138, +-1978, -78, -1484, -311, -666, -357, 617, -476, +1769, -400, 2082, -99, 1822, 298, 970, 565, +-489, 482, -1593, 196, -2119, -264, -2012, -567, +-887, -377, 341, 89, 1305, 464, 1872, 533, +1428, 176, 615, -412, -111, -796, -706, -627, +-831, -55, -686, 631, -560, 1003, -440, 700, +-296, 119, -36, -517, 359, -874, 788, -657, +910, -256, 644, 113, 279, 284, -253, 279, +-605, 321, -627, 351, -607, 429, -365, 363, +-107, -52, -6, -519, 183, -913, 409, -907, +532, -441, 555, 288, 468, 925, 283, 1060, +-118, 840, -667, 106, -949, -627, -919, -842, +-522, -804, 235, -295, 921, 298, 1140, 519, +814, 461, 113, 77, -610, -234, -828, -279, +-487, -117, 23, 258, 420, 416, 469, 314, +-7, 15, -469, -418, -531, -602, -379, -528, +200, -276, 772, 179, 709, 586, 413, 723, +-27, 658, -554, 364, -617, -163, -419, -668, +-204, -934, 151, -893, 272, -476, 233, 218, +210, 853, 94, 1205, -22, 994, -111, 300, +-93, -480, -83, -1094, 50, -1129, 212, -606, +63, 142, 18, 731, -62, 794, -295, 518, +-256, 40, -285, -319, -237, -313, 111, -184, +367, 20, 734, 77, 883, -80, 493, -148, +-159, -196, -976, -141, -1347, 144, -1074, 409, +-365, 537, 570, 446, 1179, 35, 1203, -543, +790, -922, 215, -902, -298, -334, -557, 553, +-637, 1134, -658, 1157, -523, 591, -385, -294, +-283, -971, 124, -1104, 584, -731, 891, -123, +1188, 390, 1073, 684, 408, 779, -464, 586, +-1294, 303, -1799, -85, -1563, -555, -692, -838, +286, -840, 1219, -508, 1714, 28, 1626, 619, +1168, 1017, 290, 995, -670, 607, -1371, -69, +-1779, -793, -1644, -1174, -843, -1053, 206, -416, +1069, 399, 1622, 949, 1592, 964, 1037, 499, +351, -72, -502, -508, -1181, -446, -1388, -148, +-1286, 77, -706, 146, 133, -66, 870, -262, +1281, -325, 1099, -162, 536, 174, -228, 414, +-741, 482, -772, 402, -505, 131, 31, -165, +454, -319, 489, -404, 166, -366, -288, -212, +-551, -137, -522, -65, -214, 133, 232, 251, +587, 454, 705, 648, 574, 544, 359, 273, +72, -154, -412, -703, -882, -1050, -1164, -1044, +-1052, -809, -425, -114, 443, 792, 1373, 1450, +1745, 1776, 1315, 1375, 474, 230, -595, -1062, +-1382, -2030, -1609, -2233, -1376, -1346, -567, 20, +311, 1319, 964, 2116, 1420, 1864, 1290, 966, +755, -120, 14, -1107, -666, -1486, -925, -1287, +-961, -791, -689, -85, -222, 467, 123, 789, +358, 899, 456, 762, 466, 459, 406, 72, +291, -347, 159, -704, 67, -745, -69, -555, +-315, -128, -477, 321, -542, 444, -573, 261, +-381, -141, -34, -363, 308, -172, 665, 396, +896, 1002, 992, 1096, 787, 544, 125, -483, +-668, -1538, -1424, -1851, -1770, -1366, -1432, -370, +-489, 891, 856, 1685, 1846, 1794, 2113, 1400, +1733, 582, 571, -343, -812, -1113, -1790, -1571, +-2153, -1607, -1636, -1179, -609, -373, 613, 516, +1583, 1331, 1745, 1749, 1349, 1477, 525, 775, +-418, -234, -952, -1119, -1155, -1415, -990, -1135, +-450, -372, 11, 249, 444, 453, 849, 277, +804, -99, 506, -120, 71, 262, -464, 799, +-728, 1059, -626, 713, -248, -54, 262, -851, +596, -1291, 538, -1188, 232, -721, -122, -184, +-445, 307, -445, 739, -198, 1059, -10, 1235, +141, 1068, 195, 457, 172, -360, 118, -1166, +68, -1544, 90, -1370, 22, -797, -80, -1, +-100, 683, -108, 1186, -65, 1360, -126, 1137, +-349, 639, -404, -128, -182, -913, 192, -1330, +792, -1225, 1185, -667, 854, 143, 150, 748, +-769, 872, -1578, 540, -1570, -12, -835, -409, +172, -373, 1127, 66, 1677, 535, 1487, 838, +793, 637, -139, -119, -1107, -898, -1504, -1458, +-1335, -1506, -767, -822, 229, 218, 1036, 1288, +1261, 2009, 1003, 1956, 355, 1195, -369, -36, +-789, -1288, -772, -2125, -405, -2159, 78, -1424, +362, -293, 459, 925, 369, 1738, -48, 1931, +-395, 1526, -511, 663, -501, -306, -140, -1099, +425, -1505, 874, -1353, 1062, -805, 682, -110, +-235, 508, -1062, 750, -1561, 687, -1472, 474, +-440, 258, 789, 198, 1549, 262, 1769, 231, +1088, 10, -15, -339, -837, -779, -1332, -1050, +-1227, -918, -710, -456, -253, 217, 225, 946, +649, 1373, 910, 1327, 986, 845, 819, 39, +382, -771, -328, -1302, -955, -1379, -1215, -1020, +-1066, -296, -552, 404, 104, 911, 732, 1188, +1085, 1003, 1062, 533, 765, -32, 254, -554, +-276, -866, -771, -842, -1011, -579, -877, -198, +-611, 230, -102, 472, 466, 612, 780, 633, +892, 308, 702, -44, 360, -355, -40, -608, +-417, -441, -604, -84, -671, 258, -590, 436, +-418, 232, -190, -122, 223, -350, 622, -332, +851, -73, 877, 294, 588, 487, 24, 380, +-621, 95, -1028, -211, -1065, -425, -747, -461, +-122, -281, 497, -18, 828, 254, 917, 408, +694, 363, 263, 204, -86, -66, -455, -251, +-716, -274, -730, -209, -612, -80, -212, 13, +332, 82, 798, 191, 886, 250, 536, 233, +-23, 70, -618, -197, -749, -417, -418, -383, +58, -82, 556, 217, 561, 411, 184, 273, +-206, -64, -544, -253, -521, -209, -189, 70, +246, 369, 543, 359, 594, 51, 409, -291, +-71, -580, -473, -538, -611, -166, -566, 153, +-183, 395, 318, 530, 592, 415, 553, 265, +257, 104, -137, -142, -415, -330, -543, -457, +-512, -533, -192, -387, 235, -112, 599, 182, +869, 493, 707, 621, 146, 483, -648, 147, +-1337, -206, -1265, -405, -593, -316, 339, -39, +1249, 173, 1495, 168, 1058, -147, 265, -515, +-581, -582, -1082, -305, -1139, 269, -852, 792, +-250, 950, 473, 736, 833, 172, 819, -406, +518, -751, -93, -817, -458, -632, -319, -255, +41, 141, 394, 348, 352, 373, -126, 290, +-637, 195, -824, 215, -532, 357, 86, 434, +633, 274, 749, -130, 523, -636, 240, -964, +14, -921, -54, -634, -32, -121, -179, 414, +-483, 764, -662, 1025, -620, 1064, -326, 807, +178, 351, 621, -273, 827, -819, 765, -1139, +432, -1253, -33, -1104, -363, -701, -549, -76, +-596, 760, -429, 1616, -257, 2014, -177, 1697, +-44, 676, 150, -633, 345, -1661, 548, -1959, +696, -1505, 550, -691, 183, 94, -174, 602, +-527, 835, -761, 894, -768, 909, -636, 760, +-296, 524, 202, 159, 575, -357, 834, -781, +916, -1048, 628, -1125, 239, -807, -72, -211, +-380, 456, -660, 959, -888, 956, -986, 642, +-744, 177, -179, -81, 555, 7, 1247, 161, +1473, 146, 1115, -226, 425, -821, -336, -1167, +-961, -1008, -1227, -414, -1136, 401, -756, 1039, +-188, 1202, 372, 965, 888, 569, 1119, 54, +907, -323, 489, -528, 0, -618, -451, -556, +-725, -493, -842, -519, -730, -514, -357, -334, +10, 96, 466, 824, 827, 1513, 731, 1650, +413, 1106, -58, 33, -494, -1167, -628, -1806, +-448, -1689, -72, -1005, 307, -58, 527, 661, +386, 962, 20, 977, -410, 730, -757, 435, +-607, 157, -98, -122, 462, -287, 924, -420, +900, -431, 500, -410, -81, -371, -631, -277, +-763, -174, -720, 38, -526, 274, -167, 487, +209, 666, 556, 621, 763, 380, 773, -10, +465, -445, -34, -694, -520, -650, -733, -327, +-577, 66, -272, 278, 65, 174, 268, -84, +235, -269, 78, -149, -3, 282, 35, 726, +249, 896, 432, 636, 365, 15, 128, -677, +-419, -1160, -872, -1226, -847, -832, -474, -105, +252, 706, 913, 1266, 1023, 1364, 623, 836, +-100, -40, -737, -853, -878, -1180, -514, -924, +85, -255, 622, 409, 769, 704, 385, 611, +-152, 223, -616, -179, -859, -410, -569, -456, +34, -307, 658, 32, 978, 345, 766, 591, +226, 569, -423, 197, -860, -301, -799, -697, +-295, -708, 228, -330, 488, 242, 440, 590, +95, 547, -191, 178, -223, -268, 11, -494, +345, -308, 430, 69, 268, 404, -114, 511, +-535, 267, -693, -104, -585, -394, -197, -472, +239, -323, 463, -58, 667, 122, 698, 215, +474, 282, 151, 259, -290, 210, -700, 82, +-947, -202, -862, -442, -324, -451, 305, -168, +720, 342, 896, 745, 625, 704, 130, 167, +-241, -582, -482, -1091, -433, -1014, -229, -391, +-9, 453, 232, 1085, 335, 1202, 199, 839, +-81, 192, -402, -521, -664, -968, -526, -1101, +-54, -858, 560, -233, 1078, 432, 1019, 892, +524, 936, -137, 530, -866, -70, -1174, -502, +-920, -552, -439, -244, 102, 179, 527, 438, +683, 390, 659, 83, 506, -358, 248, -698, +86, -771, -83, -548, -344, -3, -471, 604, +-584, 1076, -609, 1167, -447, 758, -168, 107, +270, -575, 734, -935, 1035, -960, 985, -732, +633, -393, -108, -142, -869, 70, -1193, 335, +-1152, 643, -589, 897, 156, 994, 621, 800, +811, 285, 668, -381, 320, -971, 84, -1302, +-69, -1225, -208, -797, -286, -208, -340, 438, +-280, 862, -119, 1073, 73, 1117, 130, 929, +88, 552, 25, 22, -43, -645, 52, -1189, +176, -1421, 186, -1244, 81, -692, -59, 33, +-105, 687, -21, 1132, 64, 1321, 85, 1182, +-97, 778, -398, 105, -453, -646, -283, -1144, +164, -1293, 631, -906, 740, -289, 567, 224, +77, 451, -426, 353, -675, 149, -656, 103, +-327, 325, 19, 652, 265, 869, 462, 782, +422, 262, 245, -547, 23, -1329, -196, -1820, +-285, -1661, -284, -781, -125, 443, 134, 1625, +287, 2213, 227, 1924, 41, 937, -183, -268, +-361, -1250, -301, -1621, -54, -1402, 196, -839, +396, -166, 391, 343, 177, 608, -38, 667, +-283, 574, -471, 404, -405, 305, -204, 254, +98, 207, 463, 83, 690, -193, 578, -544, +187, -875, -276, -997, -689, -792, -857, -310, +-641, 343, -241, 996, 213, 1396, 609, 1372, +805, 897, 813, 82, 597, -781, 114, -1313, +-486, -1399, -815, -1039, -915, -415, -702, 148, +-159, 543, 257, 819, 578, 947, 632, 912, +406, 689, 240, 156, -17, -489, -274, -988, +-283, -1118, -156, -759, 46, -97, 289, 448, +245, 688, -100, 532, -468, 135, -720, -208, +-595, -259, -7, -101, 519, 160, 819, 370, +885, 306, 492, 86, 98, -180, -187, -359, +-555, -368, -741, -223, -798, -116, -678, -60, +-224, -38, 394, -32, 822, 151, 930, 392, +693, 598, 148, 558, -199, 273, -370, -192, +-474, -565, -323, -691, -251, -554, -178, -270, +37, -19, 121, 134, 121, 247, -15, 375, +-203, 470, -182, 486, 84, 310, 482, -87, +793, -432, 760, -584, 310, -445, -321, -35, +-832, 323, -1069, 429, -957, 262, -624, -126, +-139, -453, 448, -535, 871, -340, 1131, 41, +1128, 415, 695, 636, 80, 660, -535, 482, +-956, 203, -1051, -106, -870, -434, -525, -744, +-108, -909, 319, -866, 622, -516, 766, 114, +769, 799, 535, 1220, 106, 1244, -169, 757, +-323, 54, -387, -503, -286, -766, -243, -698, +-351, -476, -422, -331, -358, -401, -160, -418, +300, -278, 752, 120, 943, 776, 797, 1288, +261, 1365, -267, 953, -606, 70, -691, -858, +-521, -1406, -294, -1463, -117, -982, -61, -268, +-6, 370, 194, 719, 408, 804, 495, 711, +400, 522, 182, 331, 45, 60, -65, -227, +-73, -453, -72, -565, -348, -448, -644, -227, +-760, -3, -545, 157, 62, 157, 706, 116, +1099, 53, 1026, -21, 465, -56, -220, 13, +-663, 115, -803, 335, -634, 475, -279, 355, +46, 19, 271, -443, 365, -784, 356, -721, +286, -341, 171, 119, -54, 497, -264, 491, +-300, 320, -320, 130, -162, -27, 112, -9, +275, 11, 363, 7, 242, 23, 58, 20, +-113, -11, -232, -139, -236, -366, -232, -534, +-123, -516, -10, -120, 66, 408, 220, 853, +268, 918, 202, 572, 96, 10, -66, -482, +-119, -684, -54, -631, -50, -410, -108, -187, +-196, 52, -284, 246, -214, 405, 60, 483, +339, 376, 523, 132, 399, -148, 83, -346, +-146, -392, -355, -247, -374, -63, -239, 139, +-126, 275, 11, 293, 128, 222, 218, 50, +323, -156, 224, -351, -18, -447, -131, -395, +-202, -199, -121, 143, 28, 483, 63, 718, +35, 697, -113, 377, -182, -102, -90, -536, +46, -746, 193, -612, 234, -285, 194, -17, +110, 144, -66, 175, -156, 158, -246, 249, +-330, 382, -194, 397, 48, 295, 260, 53, +389, -193, 329, -315, 70, -343, -86, -325, +-168, -317, -231, -270, -92, -145, -88, 67, +-203, 301, -131, 421, -1, 415, 171, 358, +385, 275, 372, 208, 118, 26, -130, -324, +-315, -697, -340, -890, -70, -688, 188, -119, +272, 513, 249, 897, -76, 854, -378, 443, +-498, -13, -455, -372, -98, -524, 322, -498, +645, -409, 734, -162, 560, 230, 195, 568, +-229, 722, -543, 495, -725, -91, -691, -703, +-474, -975, -126, -760, 266, -147, 595, 539, +708, 919, 627, 857, 362, 445, -22, -93, +-308, -516, -502, -616, -497, -487, -326, -174, +-76, 164, 205, 283, 343, 230, 191, 11, +-76, -185, -225, -219, -272, -38, -14, 179, +385, 323, 550, 287, 445, 37, 60, -185, +-402, -279, -614, -196, -537, 41, -312, 254, +-11, 297, 265, 152, 441, -169, 533, -445, +552, -535, 276, -388, -231, -29, -690, 305, +-934, 485, -671, 479, -70, 362, 552, 264, +917, 217, 780, 104, 324, -180, -154, -591, +-386, -917, -430, -949, -392, -503, -305, 183, +-282, 765, -146, 1041, 114, 843, 384, 451, +591, 35, 529, -299, 218, -459, -149, -556, +-388, -550, -389, -336, -178, -12, 50, 271, +130, 428, 51, 294, -207, 6, -401, -157, +-297, -153, -11, 0, 404, 181, 782, 202, +777, 94, 481, -2, -27, -54, -583, -53, +-837, -77, -824, -144, -569, -239, -154, -228, +241, -52, 505, 110, 609, 236, 540, 225, +351, 79, 176, 3, -27, -10, -121, 47, +-157, 124, -258, 118, -377, 40, -501, -87, +-493, -250, -383, -393, -83, -436, 342, -295, +645, 9, 814, 372, 771, 636, 459, 625, +59, 363, -374, -6, -748, -292, -837, -391, +-718, -360, -403, -273, 9, -220, 301, -161, +493, -31, 554, 164, 463, 337, 343, 374, +245, 251, 78, 68, -70, -26, -270, -20, +-509, 44, -543, 49, -507, -137, -370, -402, +-48, -584, 277, -554, 521, -238, 623, 253, +556, 698, 406, 913, 148, 804, -156, 386, +-359, -154, -511, -603, -568, -844, -431, -768, +-201, -461, 56, -91, 254, 229, 288, 410, +244, 402, 228, 295, 191, 221, 202, 139, +262, 125, 145, 116, -65, 50, -246, -30, +-421, -116, -463, -202, -420, -279, -335, -367, +-147, -505, 79, -520, 331, -354, 629, 65, +791, 660, 655, 1082, 238, 1118, -307, 656, +-747, -99, -903, -711, -636, -837, -114, -494, +390, 29, 659, 302, 520, 112, 130, -411, +-244, -863, -442, -867, -353, -354, -40, 467, +269, 1181, 441, 1480, 392, 1270, 182, 633, +-52, -162, -299, -869, -444, -1331, -441, -1370, +-264, -979, 26, -282, 312, 489, 521, 979, +463, 1006, 213, 591, -87, -60, -335, -570, +-393, -638, -325, -279, -214, 314, -60, 807, +133, 880, 286, 474, 399, -236, 446, -926, +232, -1257, -87, -1075, -334, -469, -459, 319, +-319, 954, -112, 1155, 33, 921, 124, 394, +63, -210, 19, -605, 56, -690, 69, -516, +79, -206, 88, 38, 98, 139, 175, 166, +260, 153, 198, 190, -59, 260, -416, 249, +-752, 105, -762, -135, -347, -346, 189, -398, +734, -253, 977, -39, 745, 157, 306, 189, +-238, 104, -644, 65, -670, 77, -523, 159, +-250, 189, 127, 95, 281, -71, 310, -210, +295, -218, 168, -108, 105, 0, 64, -3, +-58, -108, -155, -182, -187, -129, -223, 61, +-123, 322, 42, 445, 122, 379, 119, 194, +-1, -41, -101, -243, -143, -418, -61, -562, +80, -609, 214, -447, 372, -15, 341, 622, +163, 1163, -82, 1270, -458, 823, -695, -69, +-606, -971, -284, -1442, 238, -1335, 659, -714, +693, 43, 434, 551, -11, 726, -373, 628, +-373, 504, -137, 489, 84, 551, 203, 530, +113, 216, -96, -316, -233, -924, -287, -1298, +-168, -1224, 52, -764, 182, -63, 253, 624, +272, 1026, 152, 1106, -45, 928, -198, 524, +-274, 81, -168, -319, 46, -582, 202, -669, +282, -593, 201, -408, -14, -186, -182, 19, +-236, 155, -240, 299, -191, 387, -59, 378, +64, 307, 186, 124, 307, -124, 280, -312, +117, -398, -72, -341, -260, -116, -261, 191, +-46, 432, 105, 535, 198, 365, 141, -85, +-96, -517, -208, -791, -241, -715, -171, -236, +44, 340, 145, 780, 173, 882, 213, 631, +185, 226, 188, -212, 131, -559, -61, -736, +-266, -776, -470, -618, -526, -232, -345, 268, +24, 718, 434, 905, 687, 736, 676, 350, +415, -48, 42, -273, -342, -289, -562, -200, +-593, -230, -495, -429, -310, -674, -60, -798, +242, -592, 490, -23, 622, 744, 554, 1394, +282, 1617, -89, 1242, -390, 403, -449, -615, +-277, -1400, -45, -1648, 140, -1308, 175, -621, +-25, 128, -261, 699, -397, 914, -347, 864, +-45, 595, 339, 266, 620, -10, 720, -206, +555, -261, 86, -211, -281, -162, -469, -152, +-563, -181, -420, -238, -347, -244, -342, -179, +-210, -36, 30, 171, 458, 398, 886, 561, +990, 588, 651, 355, -22, -141, -712, -681, +-1042, -987, -868, -827, -366, -200, 160, 602, +477, 1143, 514, 1141, 407, 567, 258, -240, +128, -873, -30, -1160, -247, -981, -400, -479, +-452, 116, -267, 665, 53, 1046, 333, 1078, +490, 738, 356, 148, 88, -538, -193, -962, +-364, -1000, -355, -695, -227, -145, 30, 350, +236, 588, 366, 598, 340, 400, 165, 120, +-43, -91, -310, -198, -389, -167, -271, -83, +-90, 8, 135, 1, 251, -48, 181, -141, +35, -244, -127, -183, -212, -92, -50, 41, +156, 238, 309, 344, 413, 386, 262, 358, +-20, 197, -288, -4, -524, -232, -578, -457, +-465, -598, -248, -603, 111, -443, 483, -82, +713, 429, 719, 852, 509, 945, 84, 630, +-380, 22, -604, -584, -643, -808, -454, -605, +-114, -127, 162, 305, 366, 423, 441, 270, +311, 4, 58, -197, -177, -283, -402, -268, +-393, -212, -115, -107, 212, 152, 519, 491, +542, 738, 272, 684, -84, 258, -423, -348, +-587, -858, -468, -982, -233, -703, 4, -178, +277, 336, 383, 668, 417, 750, 379, 579, +177, 268, -5, -129, -242, -437, -424, -527, +-461, -388, -399, -83, -161, 196, 150, 261, +447, 146, 605, -47, 522, -187, 198, -187, +-225, -100, -526, 20, -613, 145, -383, 252, +8, 347, 324, 373, 481, 186, 341, -137, +25, -451, -282, -616, -420, -467, -282, -110, +22, 223, 406, 396, 562, 341, 399, 134, +33, -48, -429, -158, -603, -222, -478, -150, +-147, 34, 229, 284, 391, 568, 364, 618, +175, 321, 48, -259, -65, -897, -187, -1210, +-240, -1029, -301, -413, -181, 375, 85, 1012, +386, 1271, 538, 1094, 399, 637, 24, 5, +-402, -588, -573, -955, -507, -1022, -214, -734, +128, -262, 330, 206, 399, 495, 296, 566, +153, 435, -54, 247, -280, 83, -352, -67, +-237, -151, 48, -134, 356, -26, 516, 95, +382, 149, -59, 3, -547, -293, -806, -559, +-670, -603, -176, -297, 416, 250, 862, 727, +942, 913, 572, 695, -45, 177, -565, -350, +-835, -670, -753, -665, -336, -407, 96, -54, +448, 203, 569, 293, 467, 197, 347, 35, +104, -31, -201, -26, -480, 41, -638, 112, +-568, 57, -200, 8, 380, 13, 792, 53, +851, 149, 423, 96, -249, -135, -733, -400, +-861, -537, -498, -379, 104, 42, 568, 472, +679, 658, 445, 507, 18, 128, -360, -251, +-471, -441, -391, -390, -96, -196, 200, 40, +317, 232, 351, 308, 193, 286, -7, 135, +-214, -111, -371, -315, -328, -451, -238, -380, +3, -165, 278, 93, 433, 335, 493, 453, +304, 447, -1, 315, -297, 104, -478, -129, +-460, -300, -293, -336, -19, -245, 185, -116, +303, -81, 302, -146, 193, -241, 77, -238, +-57, -11, -100, 339, -88, 669, -5, 767, +65, 553, 12, 136, -30, -359, -152, -698, +-232, -794, -175, -608, -62, -212, 127, 205, +247, 504, 285, 563, 253, 348, 125, 22, +-84, -246, -299, -349, -400, -239, -359, -17, +-140, 177, 204, 308, 510, 334, 594, 230, +346, 68, -69, -168, -474, -401, -685, -495, +-568, -391, -226, -163, 197, 119, 527, 335, +597, 401, 450, 389, 214, 300, -121, 127, +-379, -103, -443, -412, -395, -622, -172, -535, +77, -164, 271, 355, 349, 715, 244, 673, +69, 257, -112, -228, -169, -512, -158, -422, +-90, -94, 41, 112, 89, 110, 65, -79, +14, -304, -45, -280, -97, 4, -106, 343, +-47, 575, 89, 547, 244, 278, 309, -82, +232, -363, 19, -501, -236, -435, -459, -248, +-501, -41, -295, 122, -46, 179, 220, 140, +436, 95, 465, 132, 463, 196, 308, 258, +-9, 182, -286, -45, -594, -313, -677, -506, +-453, -442, -100, -155, 334, 164, 573, 394, +532, 421, 339, 283, 73, 109, -143, -29, +-225, -98, -258, -186, -281, -297, -227, -402, +-149, -385, -12, -195, 139, 132, 245, 479, +271, 675, 223, 616, 176, 324, 18, -48, +-120, -394, -201, -615, -282, -626, -185, -467, +-44, -207, 72, 91, 159, 346, 85, 510, +-35, 507, -69, 365, -32, 134, 51, -124, +105, -288, 64, -322, 18, -230, 17, -44, +70, 75, 182, 73, 177, -5, -2, -165, +-256, -281, -495, -222, -548, -25, -361, 230, +-19, 469, 366, 543, 640, 443, 713, 167, +556, -170, 214, -451, -242, -610, -644, -583, +-817, -382, -718, -40, -311, 288, 216, 551, +657, 640, 835, 477, 620, 141, 146, -265, +-386, -596, -734, -649, -738, -420, -354, -36, +192, 399, 619, 667, 731, 613, 428, 353, +-37, -42, -477, -459, -651, -670, -442, -657, +-62, -366, 347, 86, 575, 504, 543, 693, +237, 521, -222, 79, -568, -389, -719, -561, +-534, -342, -74, 106, 413, 483, 743, 495, +697, 109, 353, -389, -48, -663, -346, -530, +-446, -64, -370, 427, -210, 682, -111, 627, +-22, 286, 80, -92, 189, -398, 287, -606, +215, -636, 50, -518, -136, -207, -284, 236, +-270, 646, -83, 877, 148, 801, 319, 419, +408, -104, 315, -576, 77, -790, -240, -742, +-543, -464, -661, -69, -520, 251, -149, 423, +296, 421, 666, 303, 745, 132, 498, 26, +111, -23, -324, -30, -596, -32, -567, -62, +-331, -92, 39, -132, 386, -168, 500, -190, +348, -175, 24, -59, -308, 126, -464, 332, +-323, 464, -46, 356, 224, 58, 372, -307, +220, -551, -30, -536, -198, -261, -236, 118, +-80, 441, 153, 578, 301, 468, 282, 204, +98, -171, -195, -487, -359, -585, -363, -427, +-252, -35, 32, 380, 202, 574, 204, 407, +101, -20, -45, -455, -51, -623, 60, -354, +211, 129, 294, 564, 201, 718, -94, 487, +-363, 34, -446, -401, -342, -638, -68, -578, +156, -270, 271, 100, 232, 396, 60, 444, +-68, 220, -96, -129, -16, -404, 63, -413, +134, -70, 163, 408, 26, 740, -93, 698, +-190, 220, -260, -415, -149, -874, -28, -918, +81, -548, 179, 57, 148, 520, 57, 665, +-25, 524, -66, 208, -64, -36, 25, -98, +70, -53, 54, -30, 10, -126, -125, -350, +-180, -523, -189, -452, -79, -115, 112, 376, +227, 789, 291, 849, 172, 548, 5, 26, +-139, -453, -230, -693, -189, -691, -147, -515, +-102, -317, -105, -99, -107, 160, -17, 471, +167, 785, 421, 896, 559, 699, 451, 189, +79, -455, -401, -954, -760, -1114, -809, -830, +-452, -248, 92, 397, 551, 834, 698, 920, +460, 631, 20, 119, -336, -349, -428, -586, +-243, -504, 110, -214, 345, 90, 319, 213, +125, 128, -150, -60, -349, -171, -344, -107, +-242, 112, -91, 377, 65, 508, 136, 428, +232, 155, 321, -260, 292, -643, 157, -845, +-49, -811, -295, -432, -408, 138, -312, 690, +-145, 1044, 78, 1017, 200, 623, 172, 38, +146, -492, 119, -790, 88, -775, 35, -502, +-93, -153, -285, 140, -370, 279, -284, 230, +-5, 138, 321, 83, 482, 115, 420, 241, +108, 322, -238, 264, -456, 37, -449, -290, +-232, -534, 42, -582, 261, -424, 314, -94, +237, 254, 54, 462, -100, 527, -168, 431, +-174, 225, -71, -2, 45, -192, 105, -301, +90, -355, 13, -358, -92, -364, -189, -311, +-219, -140, -159, 151, 19, 548, 297, 866, +471, 895, 476, 546, 274, -71, -178, -737, +-584, -1140, -781, -1094, -667, -653, -242, -11, +247, 570, 608, 898, 695, 914, 548, 637, +257, 214, -44, -199, -299, -489, -476, -586, +-490, -492, -396, -274, -174, -51, 80, 125, +256, 194, 319, 184, 208, 130, 45, 28, +-47, -28, -18, 21, 82, 169, 152, 358, +130, 452, -44, 284, -291, -175, -466, -738, +-482, -1108, -286, -1012, 83, -405, 426, 462, +625, 1195, 602, 1433, 297, 1087, -102, 343, +-457, -461, -666, -1013, -583, -1175, -300, -943, +55, -454, 402, 88, 549, 554, 421, 818, +139, 814, -179, 555, -341, 178, -280, -164, +-99, -406, 110, -468, 173, -444, 47, -387, +-125, -287, -199, -129, -108, 128, 25, 436, +94, 658, 71, 643, -44, 377, -102, -75, +-10, -500, 186, -677, 359, -575, 322, -255, +57, 104, -313, 313, -629, 341, -715, 218, +-479, 76, 6, 35, 514, 77, 853, 131, +837, 110, 439, -37, -167, -277, -718, -460, +-895, -466, -655, -265, -138, 74, 382, 415, +626, 601, 515, 579, 126, 370, -240, 19, +-410, -331, -335, -592, -48, -693, 207, -526, +326, -141, 235, 331, -50, 686, -303, 743, +-401, 460, -288, -43, 17, -474, 330, -624, +447, -442, 304, -60, 8, 302, -285, 456, +-404, 349, -325, 68, -153, -245, 22, -453, +124, -467, 191, -272, 234, 77, 262, 471, +236, 717, 41, 680, -214, 339, -434, -185, +-516, -677, -334, -886, -34, -738, 234, -324, +398, 185, 385, 582, 241, 756, 53, 667, +-106, 358, -184, -67, -225, -461, -235, -663, +-204, -580, -135, -213, -38, 266, 46, 593, +118, 589, 170, 224, 194, -266, 166, -601, +115, -582, 58, -207, -81, 257, -223, 543, +-329, 497, -363, 181, -234, -193, -19, -398, +216, -340, 376, -104, 342, 155, 174, 300, +-27, 282, -146, 139, -167, -59, -156, -243, +-130, -371, -140, -374, -110, -241, -27, 23, +86, 350, 190, 568, 156, 568, 27, 306, +-122, -95, -166, -453, -74, -612, 70, -503, +155, -224, 77, 98, -66, 346, -183, 432, +-180, 380, -48, 228, 111, 5, 204, -202, +126, -311, -68, -296, -271, -154, -379, 45, +-258, 150, 25, 113, 354, -23, 585, -152, +508, -164, 172, -11, -287, 227, -648, 395, +-688, 418, -429, 244, -35, -65, 274, -362, +405, -554, 340, -553, 219, -369, 135, -80, +68, 246, 15, 467, -141, 549, -326, 482, +-433, 286, -390, 27, -186, -221, 69, -414, +285, -501, 365, -429, 312, -240, 178, 25, +24, 271, -88, 394, -175, 378, -241, 272, +-214, 134, -173, 9, -123, -102, -33, -229, +18, -369, 63, -456, 93, -400, 104, -149, +166, 237, 251, 595, 235, 773, 123, 639, +-88, 248, -394, -250, -598, -663, -606, -828, +-376, -694, 57, -340, 470, 92, 672, 459, +645, 619, 387, 580, 7, 415, -321, 187, +-549, -17, -588, -197, -438, -358, -157, -485, +124, -532, 329, -422, 384, -160, 230, 197, +55, 511, -94, 647, -163, 578, -107, 336, +-60, 15, -18, -269, 25, -461, 20, -554, +17, -524, -13, -355, -109, -67, -197, 262, +-206, 539, -81, 643, 122, 514, 274, 221, +275, -120, 127, -392, -76, -477, -236, -385, +-240, -218, -160, -22, -31, 102, 58, 129, +73, 116, 88, 88, 42, 81, -2, 123, +-55, 174, -119, 195, -116, 153, -39, 15, +74, -179, 116, -360, 50, -461, -72, -399, +-162, -169, -156, 150, -49, 462, 108, 625, +234, 547, 218, 252, 60, -144, -145, -504, +-304, -677, -354, -574, -271, -270, -69, 144, +152, 505, 325, 631, 357, 490, 262, 161, +98, -200, -139, -406, -310, -359, -406, -147, +-410, 75, -230, 163, 49, 52, 333, -134, +535, -258, 499, -202, 212, 5, -184, 242, +-539, 390, -688, 373, -537, 221, -180, 18, +216, -164, 541, -290, 629, -329, 449, -276, +141, -138, -217, 62, -474, 221, -502, 260, +-319, 167, -44, -30, 169, -199, 175, -217, +21, -85, -114, 121, -181, 290, -89, 315, +132, 171, 326, -32, 413, -217, 315, -292, +71, -236, -213, -130, -475, -17, -605, 52, +-525, 62, -262, 67, 112, 69, 426, 79, +540, 102, 410, 100, 136, 78, -119, 50, +-265, 3, -243, -67, -122, -143, 21, -202, +88, -202, 50, -106, -47, 45, -185, 180, +-274, 228, -266, 154, -113, 13, 148, -94, +366, -90, 445, -7, 316, 72, 19, 62, +-261, -53, -403, -179, -367, -213, -193, -104, +-24, 69, 94, 217, 140, 264, 125, 196, +91, 84, 57, -13, 27, -114, -26, -230, +-46, -314, -72, -339, -105, -204, -114, 104, +-106, 425, -61, 598, -10, 490, 47, 109, +63, -343, 45, -617, 8, -576, -19, -241, +45, 199, 121, 485, 102, 484, 12, 248, +-135, -83, -266, -325, -299, -350, -255, -203, +-99, -3, 79, 153, 197, 194, 268, 135, +290, 56, 251, -10, 106, -30, -93, -34, +-298, -49, -422, -63, -399, -82, -223, -68, +54, -7, 292, 62, 391, 129, 287, 155, +20, 97, -283, -23, -443, -160, -344, -255, +-38, -215, 323, -38, 504, 184, 386, 317, +76, 290, -301, 96, -514, -138, -427, -259, +-204, -215, 62, -44, 219, 104, 165, 134, +66, 57, 16, -77, 9, -164, 61, -139, +97, -78, 46, 11, -30, 148, -135, 258, +-208, 370, -159, 383, -62, 171, 39, -199, +96, -596, 67, -810, -29, -653, -119, -170, +-143, 393, -87, 768, 37, 796, 160, 497, +217, 92, 175, -208, 74, -336, -56, -327, +-173, -290, -290, -292, -373, -301, -318, -227, +-129, -26, 151, 260, 396, 506, 474, 574, +348, 420, 40, 90, -285, -246, -419, -441, +-345, -437, -132, -238, 90, 29, 175, 202, +147, 230, 16, 111, -129, -89, -177, -226, +-135, -235, -25, -117, 136, 100, 277, 307, +299, 386, 206, 327, -41, 147, -329, -94, +-499, -277, -506, -345, -284, -300, 61, -187, +374, -74, 526, -7, 430, 31, 158, 62, +-136, 119, -311, 217, -309, 298, -175, 337, +-1, 302, 62, 149, -25, -89, -166, -364, +-250, -614, -124, -698, 144, -541, 372, -189, +470, 277, 340, 685, 10, 842, -307, 737, +-478, 408, -484, -39, -308, -432, -113, -698, +36, -764, 213, -590, 330, -225, 405, 215, +422, 573, 263, 688, -40, 505, -365, 138, +-605, -199, -646, -344, -455, -286, -122, -131, +227, -25, 482, -38, 562, -98, 454, -64, +256, 92, 0, 266, -232, 334, -360, 208, +-401, -62, -351, -271, -243, -328, -116, -238, +14, -61, 163, 53, 277, 84, 338, 108, +321, 154, 173, 210, -24, 231, -213, 136, +-350, -53, -350, -240, -219, -349, -54, -308, +111, -174, 185, -3, 174, 159, 132, 261, +39, 292, -50, 237, -133, 98, -171, -71, +-156, -192, -92, -215, 15, -160, 109, -85, +174, -40, 159, -37, 84, 8, -1, 138, +-62, 285, -119, 360, -181, 235, -238, -86, +-255, -414, -146, -568, 36, -438, 233, -77, +375, 305, 337, 505, 131, 453, -116, 214, +-271, -58, -242, -219, -117, -221, -19, -106, +0, 1, -97, 22, -176, -60, -139, -195, +40, -245, 292, -138, 411, 108, 346, 363, +125, 469, -194, 343, -455, 26, -520, -276, +-416, -408, -149, -338, 181, -110, 408, 95, +513, 167, 418, 151, 128, 87, -192, 27, +-406, 8, -441, -30, -298, -83, -83, -119, +95, -117, 183, -44, 179, 63, 129, 157, +57, 219, 5, 217, -52, 149, -106, -3, +-122, -236, -92, -449, -12, -504, 59, -306, +100, 105, 85, 547, 40, 760, -20, 590, +-102, 110, -183, -446, -224, -794, -185, -739, +-41, -336, 184, 199, 337, 633, 339, 756, +157, 538, -142, 114, -348, -333, -330, -602, +-104, -589, 179, -348, 301, -8, 147, 253, +-145, 358, -408, 339, -443, 252, -173, 158, +210, 44, 498, -121, 519, -303, 275, -402, +-56, -343, -309, -107, -390, 194, -286, 360, +-130, 323, -55, 142, -26, -61, 3, -148, +87, -85, 222, 26, 300, 86, 262, 60, +106, -58, -160, -191, -396, -265, -462, -270, +-342, -163, -75, 58, 225, 312, 448, 511, +489, 541, 320, 341, -13, -13, -358, -376, +-504, -584, -425, -566, -156, -381, 180, -113, +340, 146, 280, 325, 93, 428, -122, 422, +-169, 287, -38, 76, 88, -142, 154, -282, +75, -284, -126, -182, -252, -83, -244, -32, +-117, -27, 113, -34, 277, 18, 294, 116, +184, 199, -46, 223, -255, 171, -344, 51, +-279, -89, -66, -219, 158, -302, 249, -283, +193, -163, 52, 47, -77, 274, -79, 380, +23, 325, 115, 144, 99, -91, -46, -247, +-248, -290, -326, -254, -229, -172, -55, -89, +163, -5, 276, 109, 245, 242, 193, 332, +109, 342, 16, 242, -56, 14, -181, -266, +-315, -493, -327, -586, -217, -454, 35, -99, +324, 344, 455, 677, 379, 713, 118, 423, +-221, -45, -466, -459, -456, -632, -198, -518, +164, -224, 433, 82, 452, 274, 214, 329, +-121, 276, -361, 140, -370, -30, -124, -158, +169, -194, 327, -110, 250, 58, -18, 164, +-295, 115, -400, -70, -250, -273, 69, -319, +401, -140, 512, 146, 343, 363, -9, 351, +-388, 115, -550, -176, -422, -350, -104, -304, +248, -85, 435, 162, 363, 319, 135, 320, +-101, 171, -213, -55, -173, -275, -56, -404, +43, -391, 47, -212, -42, 47, -146, 253, +-144, 353, -24, 321, 138, 198, 287, 81, +343, -3, 242, -88, 22, -199, -214, -327, +-368, -393, -324, -333, -157, -124, 39, 166, +192, 412, 188, 510, 117, 392, 70, 127, +76, -163, 119, -388, 114, -470, 1, -375, +-163, -161, -268, 91, -223, 318, -26, 440, +181, 404, 273, 195, 178, -119, -24, -421, +-195, -584, -246, -487, -127, -136, 43, 298, +159, 591, 198, 556, 155, 222, 91, -187, +55, -441, -3, -392, -75, -119, -177, 118, +-289, 136, -278, -40, -144, -220, 82, -205, +321, 48, 432, 371, 382, 507, 193, 325, +-75, -61, -278, -412, -326, -523, -266, -370, +-113, -115, 32, 67, 115, 93, 179, 41, +205, 44, 206, 171, 177, 352, 67, 429, +-71, 283, -184, -58, -246, -463, -151, -717, +37, -663, 194, -337, 267, 123, 212, 500, +69, 626, -95, 462, -205, 110, -211, -225, +-112, -389, 54, -337, 190, -127, 261, 113, +258, 240, 138, 193, -39, 6, -187, -229, +-285, -383, -254, -371, -108, -178, 67, 127, +236, 403, 294, 509, 214, 402, 79, 148, +-75, -160, -155, -399, -111, -486, -31, -454, +62, -330, 87, -124, 19, 133, -72, 394, +-114, 555, -46, 510, 78, 246, 220, -139, +283, -465, 220, -570, 92, -423, -70, -137, +-199, 115, -220, 227, -170, 190, -83, 77, +63, -15, 178, -46, 236, -16, 233, 40, +150, 96, 71, 113, 45, 35, 37, -109, +28, -266, 5, -356, -84, -290, -178, -78, +-252, 165, -255, 302, -120, 267, 82, 107, +325, -41, 526, -86, 592, -41, 483, 4, +206, -33, -204, -158, -608, -277, -809, -285, +-750, -169, -375, 16, 183, 177, 677, 266, +922, 264, 798, 194, 391, 77, -88, -78, +-430, -250, -528, -366, -402, -348, -177, -203, +9, 18, 90, 205, 110, 249, 116, 155, +155, -13, 235, -157, 259, -177, 246, -87, +168, 58, 31, 188, -86, 218, -180, 99, +-230, -134, -227, -366, -142, -481, 46, -396, +266, -131, 400, 190, 388, 400, 217, 418, +14, 270, -96, 67, -116, -84, -38, -168, +35, -218, -17, -282, -103, -333, -132, -312, +-36, -167, 190, 91, 369, 319, 384, 387, +196, 268, -103, 0, -299, -265, -303, -363, +-88, -257, 205, -14, 353, 212, 283, 287, +45, 167, -202, -98, -280, -344, -143, -432, +79, -318, 274, -77, 321, 147, 188, 239, +4, 181, -105, 62, -92, -8, 20, 12, +139, 71, 161, 82, 64, -8, -93, -162, +-179, -306, -137, -376, 32, -329, 237, -205, +376, -45, 413, 142, 287, 307, 97, 395, +-102, 368, -252, 221, -268, -12, -195, -251, +-60, -413, 103, -476, 222, -442, 290, -327, +360, -144, 367, 107, 303, 368, 166, 509, +-92, 443, -325, 170, -427, -189, -343, -426, +-87, -424, 191, -220, 391, 4, 460, 83, +364, 1, 195, -152, 23, -215, -104, -107, +-148, 93, -162, 252, -116, 267, -30, 121, +69, -98, 160, -287, 170, -382, 161, -349, +122, -192, 73, 48, 59, 299, 19, 454, +-31, 403, -44, 110, -7, -301, 110, -643, +257, -755, 297, -556, 190, -128, -22, 325, +-224, 617, -248, 660, -82, 472, 174, 141, +403, -216, 429, -490, 246, -627, 6, -594, +-173, -405, -197, -133, -36, 138, 190, 328, +331, 379, 344, 307, 178, 172, -63, 23, +-199, -95, -203, -161, -94, -195, 84, -239, +248, -278, 330, -289, 319, -249, 230, -122, +110, 54, -8, 206, -92, 266, -128, 213, +-129, 100, -69, -14, 23, -89, 117, -133, +175, -192, 206, -266, 198, -315, 135, -273, +117, -101, 72, 126, 29, 281, 39, 267, +6, 88, -21, -161, -8, -329, -22, -306, +-24, -128, 41, 72, 132, 191, 271, 179, +360, 57, 327, -90, 204, -200, 2, -240, +-155, -225, -201, -201, -131, -164, 19, -100, +151, -5, 240, 106, 299, 212, 279, 260, +221, 208, 159, 52, 93, -138, 61, -292, +4, -371, -60, -344, -106, -263, -154, -178, +-102, -102, 51, -5, 287, 141, 521, 308, +602, 410, 470, 351, 131, 95, -261, -266, +-507, -580, -501, -677, -241, -490, 154, -133, +458, 235, 537, 441, 373, 394, 76, 144, +-158, -163, -196, -383, -35, -423, 236, -272, +434, -3, 408, 244, 151, 326, -197, 226, +-391, -5, -363, -262, -126, -424, 184, -442, +365, -328, 391, -144, 323, 64, 258, 248, +244, 367, 233, 366, 147, 203, -10, -82, +-179, -381, -266, -570, -207, -538, -31, -290, +182, 25, 320, 256, 357, 312, 334, 205, +293, 27, 225, -116, 156, -160, 41, -137, +-100, -114, -144, -113, -112, -112, 14, -113, +149, -97, 221, -84, 221, -80, 128, -61, +77, -30, 116, 49, 182, 158, 204, 203, +138, 109, -15, -117, -133, -383, -158, -562, +-78, -527, 128, -252, 323, 131, 389, 448, +299, 565, 114, 434, -73, 128, -157, -230, +-108, -509, 11, -632, 135, -600, 208, -424, +227, -128, 186, 203, 132, 467, 74, 562, +31, 452, 26, 178, 64, -167, 143, -428, +188, -519, 218, -462, 186, -318, 106, -166, +65, -57, 8, -7, -40, 30, -17, 90, +44, 188, 162, 300, 345, 377, 453, 341, +395, 112, 178, -292, -150, -743, -400, -1027, +-379, -969, -121, -518, 296, 188, 676, 848, +732, 1156, 483, 982, 56, 424, -349, -273, +-498, -819, -394, -1028, -122, -880, 201, -514, +409, -81, 458, 283, 369, 491, 203, 522, +81, 387, 42, 150, 72, -120, 93, -332, +22, -413, -136, -351, -276, -204, -282, -66, +-82, 9, 284, 12, 592, -36, 681, -73, +501, -40, 163, 33, -159, 84, -302, 80, +-198, 26, -29, -72, 139, -180, 195, -250, +98, -272, 55, -254, 82, -173, 183, -15, +358, 185, 437, 353, 356, 375, 176, 199, +-49, -152, -200, -532, -243, -747, -169, -666, +13, -308, 205, 152, 355, 527, 409, 672, +362, 531, 254, 194, 134, -180, 26, -478, +-62, -628, -104, -600, -115, -418, -85, -157, +-11, 94, 113, 267, 238, 321, 339, 264, +366, 140, 242, 7, 88, -92, -71, -155, +-149, -200, -55, -206, 102, -184, 242, -171, +252, -170, 85, -195, -106, -221, -183, -198, +-97, -68, 162, 183, 421, 447, 514, 573, +425, 458, 163, 79, -125, -435, -251, -855, +-194, -980, -24, -724, 196, -213, 309, 333, +282, 705, 198, 760, 94, 517, 61, 114, +93, -279, 118, -529, 116, -607, 81, -505, +45, -282, 73, -41, 187, 164, 332, 283, +390, 264, 276, 118, -16, -73, -336, -222, +-480, -260, -350, -171, 37, -4, 479, 127, +754, 127, 732, -20, 446, -229, 58, -375, +-250, -384, -371, -228, -345, 46, -218, 303, +-58, 416, 128, 337, 296, 90, 383, -227, +429, -497, 351, -591, 180, -466, 16, -192, +-118, 126, -129, 372, -22, 447, 80, 323, +143, 68, 137, -204, 65, -405, 21, -469, +42, -376, 135, -179, 230, 35, 288, 183, +283, 216, 180, 150, 54, 8, -39, -133, +-69, -187, -19, -160, 108, -77, 210, 20, +239, 56, 215, -4, 111, -131, 20, -259, +-14, -294, 33, -217, 134, -37, 220, 179, +247, 299, 172, 247, 65, 49, -21, -185, +-59, -339, -3, -337, 121, -188, 193, 8, +184, 116, 131, 87, 47, -37, 8, -149, +23, -181, 61, -114, 139, 22, 199, 119, +197, 100, 163, -3, 54, -117, -77, -193, +-149, -193, -141, -128, -7, -50, 188, -4, +352, 5, 419, 20, 334, 38, 158, 34, +-10, -10, -118, -98, -131, -209, -73, -289, +5, -257, 63, -92, 98, 119, 149, 273, +229, 290, 331, 148, 378, -92, 311, -306, +172, -384, -18, -312, -190, -161, -228, 0, +-152, 98, -14, 96, 183, 44, 293, 0, +316, 1, 284, 23, 162, 18, 91, -27, +76, -109, 47, -197, 48, -230, 43, -176, +12, -68, 14, 12, 12, 29, 19, -4, +69, -54, 116, -54, 179, 25, 230, 132, +216, 161, 141, 53, 47, -145, -59, -350, +-122, -441, -69, -338, 23, -92, 138, 177, +237, 336, 248, 321, 204, 166, 138, -66, +58, -273, -1, -367, -6, -329, -31, -200, +-48, -28, -11, 128, 52, 209, 160, 174, +285, 54, 370, -69, 371, -152, 265, -171, +88, -131, -106, -84, -285, -87, -360, -130, +-263, -143, -39, -90, 268, 27, 548, 167, +643, 242, 554, 192, 302, 30, -48, -162, +-292, -287, -372, -319, -308, -280, -104, -191, +107, -93, 233, -2, 294, 100, 298, 212, +278, 276, 246, 222, 177, 56, 73, -158, +-43, -338, -140, -391, -188, -288, -138, -112, +-41, 46, 50, 107, 177, 86, 275, 46, +316, 14, 290, 15, 165, 22, 17, -6, +-76, -77, -106, -146, -40, -155, 89, -118, +133, -72, 126, -47, 69, -55, -7, -62, +15, -29, 91, 58, 178, 142, 229, 131, +178, 15, 94, -148, 73, -275, 68, -272, +83, -142, 93, 19, 0, 125, -94, 111, +-112, 24, -35, -50, 149, -91, 322, -91, +391, -76, 344, -80, 193, -77, 6, -40, +-95, 39, -120, 116, -113, 103, -104, -15, +-84, -199, -21, -360, 88, -380, 261, -208, +423, 84, 488, 365, 375, 504, 103, 423, +-194, 129, -425, -263, -471, -594, -299, -723, +-22, -580, 290, -231, 522, 212, 565, 565, +452, 665, 195, 482, -94, 112, -256, -275, +-279, -514, -157, -515, 35, -307, 157, -40, +173, 120, 89, 116, -13, -10, -7, -145, +97, -159, 241, -10, 374, 205, 343, 343, +152, 299, -63, 83, -232, -193, -252, -409, +-125, -472, 57, -361, 223, -158, 299, 44, +283, 194, 187, 267, 80, 234, -8, 115, +-70, -46, -44, -191, 20, -254, 94, -189, +153, -17, 160, 148, 128, 178, 77, 53, +20, -156, -21, -335, -36, -367, -50, -215, +-20, 42, 30, 264, 86, 341, 179, 266, +231, 91, 230, -106, 165, -230, 43, -252, +-43, -217, -62, -158, -34, -98, 25, -31, +58, 28, 13, 77, -52, 114, -86, 102, +-35, 32, 102, -59, 262, -129, 366, -137, +366, -85, 259, -3, 88, 69, -66, 86, +-193, 26, -264, -88, -267, -196, -211, -267, +-67, -268, 157, -152, 422, 60, 603, 285, +625, 437, 437, 429, 81, 218, -278, -126, +-520, -464, -558, -646, -388, -610, -102, -375, +211, -18, 480, 324, 596, 542, 534, 588, +334, 441, 46, 141, -184, -232, -321, -541, +-328, -654, -166, -537, 39, -240, 191, 114, +262, 363, 214, 407, 107, 274, 38, 76, +5, -79, 24, -139, 64, -122, 78, -94, +81, -105, 39, -156, 5, -196, 12, -158, +22, -49, 48, 82, 32, 184, -18, 195, +-51, 116, -31, -4, 77, -102, 233, -126, +362, -105, 359, -83, 201, -77, -46, -106, +-274, -135, -355, -103, -227, -5, 11, 116, +225, 186, 348, 169, 303, 64, 164, -89, +38, -204, -49, -216, -49, -146, -4, -42, +18, 48, 36, 79, 56, 56, 87, 2, +144, -50, 148, -80, 78, -91, -42, -98, +-169, -74, -161, -15, -22, 56, 208, 125, +425, 146, 462, 70, 283, -76, -30, -214, +-319, -266, -466, -191, -399, -40, -165, 98, +134, 140, 378, 49, 479, -81, 433, -141, +272, -82, 73, 66, -127, 187, -253, 197, +-275, 80, -210, -114, -42, -272, 132, -317, +230, -262, 256, -153, 224, -15, 148, 114, +73, 204, 11, 252, -13, 238, 10, 147, +22, -8, 15, -176, -33, -290, -106, -326, +-148, -290, -115, -191, 35, -58, 263, 77, +459, 214, 513, 313, 368, 319, 23, 211, +-327, -1, -491, -232, -441, -387, -166, -416, +190, -296, 452, -78, 514, 129, 351, 249, +56, 255, -204, 156, -306, 7, -243, -116, +-40, -157, 197, -117, 333, -41, 330, 18, +171, 15, -87, -63, -307, -161, -347, -205, +-191, -123, 90, 60, 376, 235, 516, 310, +448, 217, 148, -34, -204, -308, -402, -433, +-384, -346, -135, -81, 197, 226, 391, 389, +386, 320, 185, 58, -119, -235, -272, -388, +-255, -343, -103, -140, 163, 109, 311, 265, +304, 265, 209, 151, 47, -12, -83, -143, +-130, -204, -114, -209, -24, -158, 73, -79, +99, -5, 122, 78, 115, 132, 69, 123, +25, 74, -12, 0, -10, -75, 19, -113, +70, -100, 84, -46, 69, 4, 27, 11, +-33, -18, -50, -59, -65, -98, -49, -101, +44, -53, 131, 11, 164, 72, 188, 118, +163, 137, 98, 129, 12, 68, -136, -55, +-200, -197, -156, -319, -56, -351, 126, -224, +262, 3, 260, 214, 164, 316, -1, 259, +-158, 103, -175, -51, -75, -119, 91, -77, +200, -14, 134, -20, 13, -102, -78, -211, +-96, -260, -7, -194, 131, -34, 227, 137, +220, 231, 101, 229, -65, 175, -143, 108, +-111, 40, -15, -32, 112, -129, 160, -253, +91, -359, 6, -359, -61, -221, -105, 6, +-47, 237, 75, 374, 168, 365, 204, 224, +141, 35, 27, -110, -58, -186, -121, -199, +-126, -195, -33, -200, 57, -194, 112, -163, +140, -67, 97, 88, 71, 216, 56, 286, +48, 288, 69, 204, 22, 66, -54, -83, +-119, -219, -178, -326, -164, -385, -28, -360, +147, -217, 272, 7, 310, 247, 225, 428, +102, 467, -33, 331, -148, 75, -182, -195, +-156, -370, -111, -399, -58, -301, 45, -137, +161, 11, 268, 85, 334, 120, 278, 144, +104, 148, -103, 137, -253, 79, -305, -32, +-236, -138, -109, -182, 69, -137, 226, -29, +262, 47, 227, 38, 141, -40, 42, -137, +-48, -158, -91, -58, -56, 113, 22, 250, +71, 256, 62, 118, -20, -89, -144, -269, +-147, -318, -47, -207, 118, -15, 289, 151, +328, 220, 238, 160, 15, 7, -245, -140, +-370, -200, -307, -134, -112, -3, 113, 110, +272, 156, 329, 103, 267, -14, 113, -115, +-44, -153, -182, -140, -226, -86, -141, -16, +-5, 61, 153, 130, 258, 163, 251, 143, +135, 49, -76, -112, -256, -258, -298, -303, +-191, -224, 4, -42, 193, 165, 306, 301, +323, 303, 227, 174, 71, 2, -84, -145, +-235, -248, -309, -269, -297, -212, -176, -114, +66, 10, 315, 129, 474, 213, 437, 223, +213, 131, -77, -8, -305, -121, -380, -173, +-270, -143, -51, -42, 152, 40, 251, 57, +176, 25, 26, -33, -109, -78, -174, -91, +-115, -71, 41, -20, 228, 47, 348, 108, +322, 168, 114, 176, -175, 88, -417, -63, +-491, -223, -345, -297, -53, -235, 305, -68, +544, 128, 563, 224, 364, 163, 32, 19, +-250, -103, -407, -131, -416, -41, -298, 103, +-102, 189, 96, 150, 247, 9, 298, -148, +243, -239, 150, -236, 32, -153, -51, -31, +-93, 59, -73, 109, -5, 145, 8, 171, +-35, 176, -113, 134, -153, 33, -81, -100, +51, -224, 179, -279, 281, -215, 273, -73, +165, 67, 11, 154, -189, 154, -325, 80, +-359, -6, -285, -42, -106, -11, 126, 45, +372, 81, 508, 80, 440, 24, 178, -62, +-163, -143, -432, -189, -500, -183, -353, -131, +-57, -32, 261, 114, 413, 244, 378, 298, +172, 260, -92, 111, -261, -105, -303, -281, +-182, -347, 9, -272, 158, -84, 232, 124, +162, 262, -5, 277, -139, 158, -191, -20, +-130, -166, 25, -230, 160, -172, 236, -23, +201, 130, 35, 225, -137, 199, -241, 53, +-248, -132, -140, -276, 33, -271, 187, -88, +277, 155, 279, 335, 168, 352, -26, 169, +-234, -113, -369, -343, -375, -407, -241, -274, +-5, -26, 255, 216, 440, 367, 422, 370, +253, 232, 22, 27, -202, -186, -321, -347, +-341, -367, -253, -234, -87, -11, 86, 203, +219, 300, 284, 252, 231, 101, 109, -74, +-25, -154, -173, -108, -222, -13, -163, 64, +-47, 80, 71, 27, 84, -46, 13, -100, +-55, -111, -87, -75, -61, -17, 52, 64, +170, 163, 233, 226, 205, 201, 50, 75, +-154, -112, -321, -278, -361, -328, -253, -205, +-33, 32, 206, 255, 369, 360, 381, 289, +192, 80, -69, -156, -274, -299, -332, -290, +-241, -153, -72, 36, 83, 193, 164, 258, +149, 214, 55, 106, -7, -5, -34, -103, +-29, -172, 16, -183, 14, -130, -24, -21, +-20, 94, -11, 166, -13, 167, -14, 86, +-50, -33, -55, -99, -42, -88, -49, -19, +5, 71, 69, 115, 85, 78, 75, -14, +27, -94, -21, -106, -47, -62, -86, 1, +-125, 63, -142, 89, -116, 61, 1, 25, +164, 4, 275, -6, 274, -5, 134, -1, +-99, 7, -320, 28, -390, 44, -273, 52, +-51, 56, 163, 2, 235, -88, 207, -154, +134, -168, 13, -102, -43, 49, -65, 228, +-111, 332, -142, 291, -178, 120, -171, -78, +-40, -224, 125, -270, 232, -201, 243, -93, +112, -6, -44, 57, -144, 115, -177, 176, +-125, 222, -41, 216, 17, 134, 12, -12, +-56, -171, -102, -253, -50, -214, 55, -105, +143, 23, 164, 127, 101, 168, -7, 148, +-131, 104, -201, 59, -182, 33, -79, 9, +20, -40, 57, -107, 50, -166, 22, -164, +41, -62, 73, 98, 88, 229, 69, 279, +-3, 223, -126, 76, -245, -97, -270, -196, +-180, -189, -9, -113, 152, -35, 229, 0, +212, 12, 121, 41, -15, 120, -130, 236, +-190, 302, -193, 229, -123, 25, -39, -210, +21, -366, 71, -368, 99, -195, 110, 71, +79, 283, 13, 338, -62, 248, -143, 91, +-178, -66, -124, -145, -17, -107, 82, 1, +122, 89, 77, 117, -9, 65, -116, -45, +-187, -136, -158, -165, -49, -112, 106, -4, +211, 113, 220, 227, 140, 290, -40, 235, +-233, 89, -342, -85, -328, -214, -175, -246, +36, -189, 222, -78, 321, 62, 287, 173, +155, 237, -40, 237, -238, 136, -340, -16, +-338, -136, -242, -190, -80, -158, 82, -47, +228, 92, 306, 193, 260, 224, 125, 173, +-44, 60, -214, -67, -338, -172, -363, -196, +-257, -137, -45, -37, 184, 80, 336, 180, +335, 229, 181, 220, -39, 147, -254, 28, +-364, -96, -335, -197, -177, -223, 55, -153, +220, -27, 255, 119, 186, 230, 41, 250, +-138, 161, -245, 15, -230, -105, -102, -140, +50, -82, 127, 19, 126, 108, 68, 124, +-29, 64, -129, -12, -181, -70, -174, -96, +-95, -63, 34, 36, 134, 150, 165, 213, +112, 184, 1, 77, -152, -58, -270, -170, +-264, -203, -133, -130, 67, 9, 188, 156, +168, 239, 47, 211, -84, 92, -139, -39, +-116, -94, -39, -54, 40, 20, 52, 53, +-21, 11, -122, -76, -191, -120, -149, -57, +-16, 101, 106, 261, 167, 311, 111, 211, +-27, -1, -142, -195, -211, -262, -198, -219, +-104, -102, 22, 42, 136, 157, 163, 237, +89, 286, -14, 255, -124, 126, -220, -72, +-240, -255, -176, -312, -27, -210, 144, -8, +241, 196, 215, 290, 78, 238, -111, 101, +-265, -43, -320, -108, -281, -66, -147, 7, +50, 74, 210, 112, 270, 85, 191, 7, +34, -79, -138, -125, -294, -101, -344, -1, +-238, 132, -19, 237, 174, 240, 247, 122, +169, -30, 6, -128, -166, -153, -260, -96, +-233, 21, -129, 119, 13, 133, 121, 75, +169, 1, 100, -23, -52, -2, -197, 53, +-281, 94, -239, 58, -95, -13, 79, -37, +191, -1, 183, 73, 92, 140, -26, 151, +-164, 74, -256, -75, -236, -195, -158, -194, +-41, -73, 64, 115, 145, 269, 170, 296, +62, 199, -111, 47, -264, -106, -271, -186, +-120, -133, 48, -9, 130, 88, 118, 104, +17, 64, -108, 21, -187, 12, -202, 43, +-126, 90, -23, 101, 51, 64, 65, 7, +30, -33, -19, -42, -88, -8, -126, 58, +-112, 93, -80, 50, -16, -13, 24, -21, +-5, 28, -75, 76, -137, 84, -155, 51, +-103, 1, -32, -20, 31, 11, 75, 69, +70, 97, 9, 76, -124, 16, -212, -55, +-200, -68, -126, 5, -43, 99, 14, 148, +47, 111, 56, 7, 55, -73, 33, -61, +-34, 2, -122, 68, -219, 107, -293, 125, +-275, 93, -159, 4, 32, -69, 236, -67, +314, -31, 244, 49, 87, 150, -139, 195, +-341, 137, -493, -3, -517, -147, -336, -197, +-20, -122, 293, 39, 459, 204, 417, 282, +200, 262, -77, 188, -329, 64, -449, -112, +-402, -261, -276, -305, -155, -215, -47, -33, +42, 165, 104, 308, 169, 352, 181, 300, +113, 208, 26, 84, -106, -63, -216, -193, +-309, -280, -379, -314, -347, -227, -240, -28, +-59, 213, 176, 401, 375, 457, 438, 349, +291, 131, -57, -105, -403, -243, -601, -261, +-591, -181, -368, -41, -49, 88, 255, 147, +404, 156, 341, 124, 123, 78, -150, 50, +-347, 35, -412, 46, -312, 83, -96, 111, +98, 82, 163, 4, 65, -101, -105, -185, +-226, -197, -237, -99, -161, 102, -14, 337, +102, 473, 147, 421, 88, 163, -64, -193, +-222, -459, -341, -485, -357, -269, -280, 84, +-107, 379, 116, 486, 278, 404, 269, 222, +106, 10, -127, -181, -316, -297, -391, -293, +-365, -159, -245, 53, -46, 229, 144, 313, +233, 294, 162, 174, -16, 4, -200, -140, +-300, -189, -301, -111, -234, 58, -77, 205, +92, 256, 151, 182, 54, 23, -79, -143, +-171, -249, -223, -235, -251, -58, -220, 173, +-89, 340, 60, 393, 101, 313, 26, 142, +-51, -37, -81, -204, -93, -291, -131, -263, +-191, -141, -205, 20, -174, 173, -145, 268, +-118, 315, -79, 296, 11, 196, 70, 33, +42, -157, -37, -266, -86, -205, -108, -39, +-138, 131, -175, 261, -223, 266, -229, 122, +-184, -87, -103, -225, -48, -197, 17, -5, +89, 205, 109, 313, 10, 276, -171, 138, +-284, -11, -252, -106, -128, -141, -47, -76, +-48, 39, -76, 129, -149, 130, -231, 60, +-217, -37, -87, -102, 71, -116, 133, -38, +39, 129, -116, 297, -188, 386, -191, 364, +-141, 205, -93, -29, -77, -252, -117, -418, +-179, -468, -198, -331, -183, -31, -103, 281, +-8, 492, 37, 561, 23, 503, 1, 332, +-21, 88, -80, -163, -190, -376, -303, -482, +-348, -406, -285, -199, -135, 26, 47, 213, +181, 379, 178, 461, 15, 427, -194, 283, +-348, 91, -357, -94, -241, -212, -129, -268, +-25, -241, 55, -151, 95, -32, 53, 95, +-32, 206, -126, 276, -226, 307, -351, 265, +-416, 143, -360, -13, -179, -159, 74, -226, +230, -181, 229, -79, 97, 59, -59, 210, +-159, 288, -253, 264, -332, 153, -320, 17, +-249, -71, -188, -102, -151, -133, -84, -101, +-10, -10, 44, 74, 61, 144, 35, 193, +-10, 187, -61, 171, -134, 151, -219, 117, +-284, 23, -318, -103, -276, -184, -235, -185, +-188, -166, -100, -97, 9, 39, 146, 206, +265, 395, 234, 543, 7, 477, -310, 170, +-524, -224, -560, -499, -460, -534, -227, -334, +49, 9, 228, 340, 216, 495, 48, 421, +-96, 223, -144, -10, -204, -167, -250, -167, +-252, -31, -205, 121, -143, 179, -105, 103, +-116, -15, -126, -107, -82, -139, -55, -87, +-65, 56, -65, 203, -43, 304, -44, 318, +-87, 222, -220, 19, -322, -178, -284, -262, +-184, -203, -129, -52, -93, 110, -16, 233, +52, 278, 26, 214, -57, 97, -131, 10, +-167, -33, -206, -57, -276, -66, -278, -44, +-187, -13, -84, 1, -8, 60, 33, 211, +-43, 318, -145, 264, -195, 83, -178, -124, +-128, -262, -56, -212, -40, -23, -132, 152, +-252, 201, -303, 145, -211, 77, -51, 100, +43, 185, 10, 242, -102, 129, -214, -167, +-253, -430, -214, -412, -109, -80, 10, 394, +54, 668, -26, 530, -164, 117, -282, -259, +-351, -385, -367, -247, -251, -21, -4, 127, +222, 182, 274, 180, 89, 183, -199, 192, +-445, 125, -529, -27, -395, -151, -101, -175, +142, -71, 207, 107, 68, 231, -169, 200, +-339, 51, -343, -76, -230, -36, -106, 107, +18, 203, 95, 169, 53, 25, -82, -136, +-231, -178, -323, -74, -305, 114, -232, 276, +-169, 288, -132, 102, -91, -116, -46, -206, +26, -137, 49, 43, -13, 260, -73, 398, +-119, 328, -207, 65, -311, -209, -352, -338, +-335, -261, -257, -9, -173, 225, -60, 243, +104, 117, 226, 81, 198, 154, 34, 194, +-172, 106, -336, -32, -441, -89, -450, -22, +-361, 66, -182, 56, 27, -90, 114, -229, +71, -159, 2, 132, -56, 404, -140, 482, +-194, 333, -177, 44, -115, -222, -101, -324, +-169, -207, -296, 34, -305, 201, -204, 201, +-121, 86, 0, -36, 147, -57, 189, 50, +76, 180, -190, 249, -478, 195, -549, -15, +-410, -223, -159, -224, 86, -15, 212, 235, +179, 355, 16, 225, -155, -52, -236, -253, +-239, -204, -204, 57, -230, 285, -313, 294, +-369, 115, -300, -146, -66, -266, 193, -100, +343, 197, 315, 361, 103, 319, -222, 143, +-506, -31, -637, -143, -540, -199, -315, -200, +-69, -149, 99, -38, 126, 155, 98, 353, +75, 419, 64, 332, 25, 162, -122, -1, +-304, -130, -395, -239, -408, -314, -307, -278, +-148, -99, -47, 186, -33, 419, -53, 428, +-40, 207, 36, -32, 97, -103, 70, 28, +-54, 198, -190, 164, -329, -107, -427, -359, +-366, -324, -280, 4, -235, 341, -132, 385, +105, 122, 370, -119, 422, -59, 130, 227, +-312, 397, -617, 220, -600, -183, -333, -456, +-58, -338, 69, 84, 17, 417, -77, 340, +-109, -29, -93, -299, -2, -201, 96, 202, +15, 570, -213, 535, -409, 82, -383, -441, +-177, -603, 14, -253, 3, 275, -157, 491, +-229, 274, -120, -110, -3, -264, 22, -49, +-6, 287, 13, 408, 57, 230, -106, -68, +-392, -230, -529, -211, -426, -125, -178, 1, +18, 145, 79, 245, 150, 262, 222, 168, +141, -17, -116, -170, -343, -151, -363, 31, +-288, 217, -280, 197, -254, -13, -100, -171, +75, -77, 79, 199, -74, 350, -147, 182, +-55, -169, 77, -315, 46, -117, -122, 220, +-282, 343, -353, 138, -348, -157, -299, -226, +-160, 3, 49, 302, 185, 349, 162, 106, +22, -135, -164, -180, -245, -88, -196, 32, +-129, 129, -126, 129, -203, 64, -286, 36, +-264, 66, -169, 36, 15, -68, 231, -73, +254, 92, -12, 271, -277, 281, -306, 112, +-229, -115, -169, -214, -177, -111, -184, 41, +-160, 23, -125, -127, -34, -128, 146, 146, +176, 490, -23, 558, -238, 266, -263, -137, +-173, -377, -163, -348, -189, -123, -174, 70, +-152, 74, -100, -44, 3, -38, 94, 224, +67, 506, -127, 463, -232, 127, -134, -201, +-66, -348, -195, -279, -270, -100, -137, 47, +-7, 69, -58, 71, -123, 206, -90, 371, +-20, 280, 3, -10, -62, -204, -125, -218, +-176, -133, -205, 40, -162, 200, -82, 199, +-50, 61, -67, -10, -144, 49, -209, 75, +-144, 28, 49, -7, 205, -22, 108, -68, +-188, -47, -424, 53, -429, 152, -204, 205, +28, 188, 98, 74, 28, -84, -74, -176, +-84, -120, -35, 68, 18, 255, -24, 256, +-192, 23, -340, -266, -337, -309, -224, -90, +-86, 177, 49, 367, 173, 409, 165, 281, +10, 58, -123, -107, -232, -205, -319, -310, +-320, -360, -193, -192, 14, 166, 110, 401, +58, 443, -65, 316, -234, 117, -320, -83, +-218, -179, 42, -158, 236, -95, 213, 8, +88, 111, -114, 140, -462, 14, -723, -103, +-609, -113, -144, -4, 370, 166, 506, 301, +350, 289, 135, 139, -97, -11, -346, -114, +-529, -161, -525, -162, -323, -132, -64, -75, +144, 42, 267, 250, 218, 381, 28, 275, +-257, 12, -430, -162, -306, -183, 7, -96, +249, 44, 209, 127, -56, 107, -308, 37, +-404, 70, -312, 101, -162, 2, -23, -148, +72, -139, 71, -1, 54, 170, 72, 258, +22, 220, -134, 59, -334, -133, -379, -166, +-156, -40, 32, 50, 77, 62, -1, 82, +-127, 106, -194, 81, -137, 1, 21, -67, +66, -29, -148, 54, -321, 89, -182, 28, +66, -53, 186, -19, 128, 160, -47, 282, +-297, 189, -449, -86, -308, -295, 25, -257, +150, -48, 8, 81, -125, 131, -89, 224, +-11, 296, -34, 238, -65, 43, -22, -150, +-66, -256, -259, -257, -285, -161, -38, 93, +172, 330, 78, 404, -207, 248, -284, -42, +-161, -263, -151, -262, -170, -109, -41, 59, +182, 115, 297, 160, 179, 259, -119, 264, +-383, 77, -492, -158, -373, -296, -166, -263, +-43, -77, 94, 182, 211, 372, 198, 303, +72, 77, -83, -66, -179, -84, -301, -89, +-446, -134, -394, -131, -15, -4, 325, 207, +290, 336, 13, 283, -171, 25, -156, -201, +-173, -214, -353, -57, -398, 23, -84, -46, +254, -49, 301, 176, 153, 415, -89, 351, +-268, -25, -368, -397, -389, -405, -219, -84, +73, 259, 308, 357, 302, 246, -36, 17, +-317, -135, -280, -149, -172, -49, -185, 15, +-277, -7, -131, -45, 218, 56, 325, 253, +82, 349, -143, 241, -214, -96, -157, -349, +-127, -329, -211, -143, -268, 16, -120, 168, +54, 323, 78, 348, -11, 175, -33, -88, +36, -230, -55, -220, -247, -88, -230, 107, +9, 171, 112, 102, -60, 59, -232, 128, +-146, 117, -33, -22, -106, -151, -213, -221, +-177, -204, 12, -62, 136, 190, 167, 405, +33, 406, -133, 198, -236, -88, -222, -254, +-104, -239, -60, -81, -101, -61, -118, -106, +-81, 7, -66, 205, -38, 266, 67, 175, +61, 64, -91, -69, -208, -148, -96, -37, +11, 179, -78, 182, -129, 34, -34, -36, +-26, -59, -167, -170, -158, -156, -54, -47, +-68, -24, -248, -83, -157, 137, 178, 491, +269, 524, 29, 210, -171, -81, -91, -242, +-73, -384, -257, -357, -261, -154, -161, 35, +-134, 120, -151, 198, -19, 287, 190, 216, +176, 41, -41, -38, -7, 0, 99, 41, +-112, 87, -465, 82, -478, -15, -104, -159, +121, -253, 34, -215, 56, -82, 107, 77, +-64, 212, -232, 323, -172, 333, -40, 176, +16, -118, -64, -190, -120, -9, -68, 146, +-22, 28, 27, -164, 14, -216, -143, -169, +-299, -84, -250, 92, -176, 184, -124, 92, +80, 90, 379, 390, 398, 558, -21, 229, +-430, -375, -385, -709, -247, -597, -265, -161, +-243, 328, 58, 506, 379, 320, 373, 27, +-41, 5, -294, 103, -270, -15, -224, -206, +-156, -215, -85, -36, -89, 149, -76, 198, +124, 95, 318, 71, 209, 33, -207, -86, +-536, -181, -440, -173, -138, 21, 31, 183, +127, 166, 185, 113, 100, 106, -156, 15, +-311, -74, -156, -107, 75, -68, 12, 37, +-108, 201, -64, 200, 17, -41, 88, -285, +-142, -178, -417, 94, -443, 109, -167, -46, +262, -18, 443, 197, 195, 284, -134, 224, +-190, 50, -190, -112, -268, -231, -275, -220, +-87, -139, 99, -44, 85, 65, -84, 167, +-174, 140, -62, 56, 58, 120, 54, 240, +-160, 210, -214, -47, 44, -286, 138, -250, +-119, -115, -454, -40, -294, -24, 260, 64, +399, 292, -118, 408, -455, 177, -134, -189, +197, -332, -24, -226, -411, 47, -241, 203, +209, 185, 244, 14, -53, -163, -81, -73, +65, 135, -109, 245, -336, 140, -323, -87, +-56, -297, 2, -303, -53, 20, -25, 356, +72, 384, 114, 39, 47, -139, -45, -96, +-248, 13, -294, 13, -121, -128, 61, -143, +68, 43, -147, 286, -146, 236, -14, -16, +-1, -176, -179, -86, -90, 7, 233, -41, +263, -12, -189, 120, -518, 194, -292, 116, +-21, -40, 26, -136, -51, -141, 190, 15, +303, 98, 17, 110, -288, 22, -344, -30, +-140, -46, -128, 49, -241, 142, -125, 145, +63, -68, 132, -285, 109, -135, 68, 187, +87, 326, 73, 128, -187, -85, -408, -161, +-348, -36, -99, 21, 42, -20, 4, -74, +-96, -61, -139, 124, -60, 251, 107, 212, +291, -27, 275, -155, 31, -128, -272, -68, +-492, -85, -435, -76, -205, 144, 60, 357, +109, 308, -1, -66, -25, -343, 163, -256, +179, -22, -77, 133, -163, 53, 35, 4, +-17, 78, -337, 232, -417, 223, -98, 66, +208, -175, 47, -324, -258, -228, -170, 11, +181, 181, 323, 176, 86, 128, -216, 139, +-136, 87, -31, -184, -208, -310, -480, -149, +-277, 180, 311, 302, 428, 272, -33, 168, +-390, -5, -164, -292, 117, -478, 54, -300, +-124, 14, -83, 284, 120, 391, 131, 477, +-181, 382, -529, -52, -374, -496, 26, -671, +257, -337, 150, 146, 56, 528, 183, 429, +165, 101, -168, -203, -510, -101, -521, 114, +-209, 43, 135, -208, 251, -296, 147, 11, +75, 287, 89, 285, 39, 79, -199, -82, +-410, -161, -250, -94, 74, 48, 62, 187, +-145, 59, -125, -249, 242, -183, 283, 193, +-188, 302, -519, 76, -126, -213, 339, -106, +147, 129, -266, 86, -233, -60, 161, -46, +56, 58, -348, 222, -320, 193, 93, -166, +211, -349, 33, -239, -39, 153, -16, 230, +-46, -28, -180, -56, -24, 226, 53, 390, +-145, 216, -227, -212, -108, -443, 38, -256, +-46, 98, -121, 307, 107, 64, 289, -361, +83, -275, -206, 166, -324, 517, -150, 418, +54, -60, 48, -209, -99, 8, -245, 118, +-149, -112, 104, -429, 218, -389, 163, 69, +-25, 372, -188, 295, -219, 85, -64, -63, +-52, 76, -135, 257, -132, 155, 155, -208, +324, -429, 22, -290, -417, -10, -386, 184, +61, 256, 310, 225, 85, 8, -232, -177, +-95, -100, 135, 212, 75, 182, -221, -94, +-298, -263, -1, -50, 82, 256, -129, 197, +-154, -157, 166, -357, 378, -133, 93, 208, +-329, 352, -395, 138, -151, -11, 100, -65, +113, -83, -46, -73, -74, -107, 20, -113, +81, -35, 40, 112, -29, 279, -122, 278, +-289, 60, -300, -123, 69, -213, 343, -214, +211, -129, -77, 30, -164, 110, -108, 125, +-141, 97, -225, 146, -43, 202, 77, 92, +9, -170, 38, -370, 126, -266, 229, 54, +74, 398, -195, 322, -294, -154, -415, -393, +-357, -221, 1, 224, 341, 438, 476, 218, +249, -102, -110, -225, -94, -114, -72, 56, +-307, 107, -490, -93, -257, -120, 324, -124, +381, -62, -35, 21, -201, 139, 59, 307, +245, 335, -32, 199, -336, 45, -161, -213, +191, -450, 150, -502, -207, -318, -359, 3, +-92, 340, 204, 437, 120, 415, -143, 311, +-67, 187, 284, -10, 376, -357, -69, -534, +-428, -321, -409, -106, -114, -126, 70, -110, +-28, 223, -84, 628, 50, 709, 353, 275, +410, -260, 50, -513, -386, -446, -383, -168, +-25, 109, 149, 152, -150, 56, -433, -88, +-46, -129, 426, 150, 305, 317, -143, 124, +-239, -113, 155, -19, 208, 174, -96, 156, +-237, -125, -48, -313, 55, -338, -145, -261, +-210, 0, -95, 275, -5, 392, 14, 334, +186, 200, 404, -42, 265, -292, -109, -210, +-387, -60, -343, -130, -162, -282, 11, -82, +-18, 439, -23, 655, 150, 195, 269, -440, +246, -651, -19, -338, -261, 389, -261, 608, +-196, 164, -79, -305, 64, -323, 223, 135, +227, 478, 26, 141, -250, -443, -187, -755, +94, -445, 115, 534, -8, 983, -179, 504, +-22, -250, 163, -690, -34, -394, -268, 280, +-114, 381, 128, -81, 163, -492, 64, -379, +54, 455, 176, 750, -21, 230, -385, -334, +-319, -570, 28, -356, 196, 170, 45, 420, +-104, 244, 83, -73, 309, -334, 52, -86, +-237, 210, -228, 206, -100, 63, 60, -192, +110, -325, 147, -5, 123, 247, -214, 188, +-391, -95, 35, -302, 380, -154, 230, 250, +-209, 447, -377, 358, -60, -239, 209, -773, +153, -428, -50, 390, -202, 720, -37, 195, +408, -681, 388, -699, -184, 257, -618, 1014, +-431, 674, 194, -547, 424, -1163, -11, -345, +-358, 787, -55, 787, 500, -171, 593, -912, +-28, -524, -571, 624, -384, 1039, -51, 272, +-44, -841, -69, -954, 172, 49, 326, 824, +102, 520, -62, -289, 48, -466, 71, -131, +-228, 281, -362, 233, -91, -134, 185, -388, +269, -280, 203, 145, 176, 504, -7, 495, +-360, 48, -546, -397, -186, -570, 352, -311, +460, 272, 91, 472, -181, 130, 17, -354, +201, -361, 32, 137, -266, 551, -231, 323, +-46, -264, 88, -606, 154, -306, 67, 348, +-33, 522, -72, 41, 21, -511, 180, -486, +130, 45, -97, 602, -345, 505, -132, -49, +333, -518, 455, -456, 3, 60, -562, 444, +-384, 305, 217, -223, 388, -530, 125, -396, +-200, 274, -136, 684, 181, 331, 217, -238, +75, -432, -114, -1, -287, 281, -134, 54, +-4, -424, 84, -524, 286, -261, 161, 376, +-75, 777, -165, 445, -49, -151, 190, -423, +57, -97, -260, 169, -248, -96, 50, -563, +304, -536, 412, 72, 136, 615, -232, 593, +-355, 64, -237, -179, 204, 34, 260, 144, +-38, -320, -125, -696, 24, -352, 108, 462, +20, 685, -46, 8, 83, -614, 142, -384, +-31, 549, -5, 876, 127, 138, 31, -875, +-238, -893, -436, -65, -138, 663, 300, 595, +423, -14, 190, -387, -37, -350, -56, 76, +29, 363, 19, 121, -144, -299, -134, -392, +11, 31, 147, 470, 187, 369, -37, -186, +-289, -620, -267, -533, 133, 119, 604, 753, +343, 620, -299, -98, -464, -677, 38, -538, +550, 80, 304, 386, -377, 176, -575, -205, +-72, -256, 384, 96, 234, 305, -201, 129, +-49, -271, 455, -407, 477, -4, -180, 433, +-645, 326, -279, -230, 315, -687, 469, -233, +-16, 632, -396, 700, -164, -273, 340, -1051, +639, -577, 215, 726, -566, 1094, -696, 230, +-89, -695, 557, -847, 551, -110, -17, 604, +-306, 620, -108, -6, 54, -760, 129, -839, +177, -58, 171, 736, 7, 908, -375, 379, +-292, -509, 306, -973, 388, -600, -49, 294, +-318, 991, -98, 522, 380, -498, 278, -962, +-29, -383, 100, 556, 87, 774, -139, 82, +-278, -631, -183, -600, 163, 79, 139, 643, +-86, 461, 45, -121, 320, -472, 419, -299, +108, 42, -359, 52, -336, -198, 160, -199, +339, 110, 59, 357, -311, 236, -278, -85, +122, -245, 357, -163, 263, 157, 74, 266, +-105, 20, -173, -493, 85, -618, 220, -82, +165, 434, 36, 519, -219, 166, -269, -186, +-175, -329, 210, -90, 574, 176, 297, 270, +-326, -131, -425, -495, 226, -246, 603, 131, +121, 235, -555, 86, -407, -117, 338, -47, +526, 134, 30, 110, -327, 27, -30, -119, +466, -234, 336, -135, -310, 13, -547, 31, +-119, -64, 352, -294, 448, -118, 201, 549, +25, 743, 17, 41, -44, -899, -113, -856, +-82, 198, 28, 780, 50, 255, 39, -556, +33, -564, 54, 99, 235, 770, 235, 493, +127, -413, -77, -813, -295, -444, -146, 315, +139, 524, 422, 150, 365, -126, -73, -46, +-288, 32, -139, -32, 111, -251, 157, -389, +-32, -221, -136, 14, 58, 256, 392, 353, +495, 209, 273, 116, -166, 35, -453, -160, +-317, -354, 67, -478, 293, -323, 155, -20, +-156, 235, 13, 310, 576, 293, 525, 106, +-141, -178, -719, -182, -365, -3, 537, 71, +697, -63, 175, -226, -365, -246, -441, -84, +79, 4, 491, 157, 350, 221, -144, 1, +-448, -139, -229, -169, 432, -61, 781, 108, +461, 143, -171, 136, -682, 22, -465, -304, +148, -422, 458, -167, 361, 102, 19, 202, +-124, 85, 73, -19, 264, 164, 259, 138, +164, -206, -107, -398, -261, -247, -261, 191, +-58, 390, 375, -23, 486, -358, 134, -249, +-211, 146, -133, 419, 202, -29, 518, -500, +297, -319, -276, 303, -521, 521, -226, 57, +422, -707, 611, -565, 126, 284, -271, 787, +-258, 446, 44, -580, 347, -940, 455, -304, +270, 632, 66, 907, -187, 123, -228, -817, +-79, -859, 56, -53, 125, 677, 17, 507, +-7, -150, 229, -432, 492, -191, 317, 82, +-11, 193, -12, 154, 41, -1, -38, -219, +-243, -453, -233, -254, 137, 150, 361, 372, +248, 217, 102, -196, 108, -385, 118, -122, +234, 277, 211, 319, 155, 32, 64, -288, +-269, -294, -471, -82, -193, -88, 260, -159, +527, -27, 532, 242, 233, 393, -46, 116, +-164, -436, 23, -518, 413, -128, 235, 384, +-372, 553, -568, 74, -66, -592, 697, -667, +800, -208, 131, 474, -410, 741, -270, 150, +149, -474, 517, -677, 410, -253, -123, 387, +-334, 382, -158, -79, 166, -379, 478, -199, +252, 193, -121, 416, -9, 175, 248, -216, +368, -449, 202, -427, -146, 20, -249, 171, +-131, 37, 61, -40, 317, 83, 319, 222, +97, 28, 108, -281, 307, -381, 357, 13, +265, 400, -173, 430, -586, -34, -432, -723, +27, -701, 761, -123, 964, 514, 28, 553, +-504, -21, -253, -439, 309, -279, 682, 132, +228, 475, -324, 369, -256, -184, 73, -479, +481, -562, 493, -377, -70, 88, -354, 380, +-184, 401, 123, 87, 349, -399, 223, -298, +268, 144, 462, 328, 320, 109, 13, -282, +-253, -303, -191, -23, 17, -8, -8, -98, +-22, -62, 265, 27, 416, 126, 234, -74, +34, -377, 151, -205, 462, 290, 338, 658, +-127, 384, -462, -343, -361, -744, 234, -658, +560, -144, 417, 306, 31, 548, -69, 431, +179, -73, 237, -511, 37, -500, -31, 39, +135, 372, 223, 175, 200, -359, 84, -457, +-15, 56, 70, 508, 236, 404, 169, -222, +-107, -563, -23, -364, 359, 192, 549, 363, +170, -34, -331, -389, -156, -197, 104, 87, +188, 101, 294, -118, 329, 96, 357, 371, +163, 149, -150, -294, -32, -510, 111, -223, +-7, 133, -117, 201, -49, -12, 360, -215, +627, -284, 288, -128, 32, 183, 239, 293, +264, 328, -5, 134, -298, -249, -310, -402, +41, -240, 259, -37, 350, 10, 440, -147, +187, -226, 1, -103, 118, 145, 361, 424, +435, 364, 186, 5, -252, -319, -494, -356, +-281, -224, 210, -43, 652, 110, 535, 41, +96, -161, -34, -238, 111, -23, 387, 252, +403, 277, -51, 18, -398, -248, -235, -304, +278, -158, 592, 210, 292, 219, -146, -83, +-129, -290, 205, -225, 494, 91, 392, 187, +22, 54, -225, -204, -71, -335, 238, -169, +339, 336, 172, 430, -29, 83, -11, -409, +229, -487, 330, 15, 196, 239, 118, 45, +154, -308, 208, -188, 5, 343, -286, 440, +-129, -131, 434, -664, 554, -415, 156, 235, +-104, 537, 43, 75, 531, -445, 515, -363, +-2, 223, -340, 587, -307, 172, 144, -589, +355, -802, 169, -190, 92, 451, 223, 487, +323, 5, 271, -277, 196, -43, 201, 173, +232, 66, 0, -208, -131, -257, -110, -178, +-180, -140, -15, -189, 267, 82, 686, 463, +656, 394, 107, -27, -77, -479, 77, -430, +279, -58, 67, 281, -309, 180, -293, -157, +174, -485, 421, -318, 271, 225, 279, 480, +453, 299, 559, -128, 103, -255, -494, -115, +-473, -41, 135, -207, 720, -242, 620, -117, +-139, 98, -657, 192, -176, -29, 728, -169, +1077, 4, 439, 262, -383, 412, -511, 87, +-15, -419, 457, -674, 370, -561, 35, -127, +-200, 319, -54, 512, 337, 351, 460, 32, +471, -218, 276, -123, -86, 75, -197, -38, +-66, -333, 293, -564, 360, -248, -24, 328, +-72, 455, 186, 101, 375, -229, 445, -130, +13, 200, -284, 233, 61, -128, 483, -394, +552, -240, 30, 82, -436, 69, -89, -310, +474, -353, 525, 120, 141, 613, -268, 395, +-135, -268, 358, -512, 523, -84, 348, 393, +-39, 122, -109, -428, 162, -631, 240, -146, +66, 295, -59, 273, 109, 23, 295, 2, +329, 167, 138, 113, -111, -165, 19, -357, +464, -299, 499, 32, 51, 240, -209, 86, +-8, -266, 459, -360, 362, -31, -252, 375, +-441, 401, -22, -117, 556, -516, 739, -369, +318, 203, 73, 553, 205, 154, 243, -384, +-44, -437, -540, -192, -390, 100, 417, 87, +812, -76, 450, -126, -159, -77, -226, 190, +423, 420, 764, 243, 217, -161, -522, -379, +-501, -502, 135, -454, 638, -97, 522, 319, +161, 568, 42, 231, 55, -245, 90, -322, +139, -51, 68, 144, -7, 15, 119, -224, +293, -278, 307, -77, 145, 109, 26, 113, +197, 171, 279, 159, 127, -102, -103, -431, +-161, -507, 141, -11, 513, 576, 552, 421, +164, -218, -186, -575, -203, -309, 57, 378, +233, 466, 270, -44, 265, -420, 263, -341, +194, -25, 70, 167, 74, 17, 90, -112, +137, -83, 125, 13, -59, 168, -76, 194, +195, 25, 451, -117, 525, -230, 316, -282, +-3, -187, -121, -35, -151, 85, -47, 29, +205, -60, 327, 78, 324, 391, 139, 348, +-76, -180, 50, -723, 411, -711, 588, 21, +274, 687, -255, 535, -380, -111, 21, -600, +367, -355, 308, 282, 72, 397, -104, -100, +143, -571, 493, -423, 445, 352, 143, 750, +82, 317, 237, -413, 160, -611, -259, -229, +-535, 168, 19, 61, 651, -314, 559, -240, +64, 147, -158, 544, 190, 442, 722, -92, +645, -470, -37, -405, -551, -123, -523, 93, +60, 85, 568, -129, 414, -143, 122, -5, +-16, 254, 160, 395, 513, 40, 421, -533, +53, -679, -137, -160, -153, 527, 15, 677, +192, 79, 211, -444, 191, -445, 165, -79, +216, 198, 314, 91, 73, -235, -183, -295, +85, -64, 522, 291, 464, 379, -87, 77, +-290, -239, 87, -310, 397, -125, 176, 91, +-133, 198, -83, 10, 282, -164, 585, -310, +452, -296, 54, -84, -95, 218, 45, 461, +108, 283, -36, -186, -131, -419, 63, -231, +347, 214, 507, 263, 484, -81, 262, -388, +-98, -372, -285, -58, -75, 204, 172, 138, +343, -48, 276, 9, 94, 256, 65, 289, +137, -104, 297, -482, 290, -270, 72, 171, +-99, 159, -53, -294, 107, -624, 303, -128, +335, 600, 199, 782, 31, 237, 44, -484, +133, -686, 120, -288, 144, 256, 190, 442, +173, 158, 167, -378, 131, -615, 112, -333, +101, 357, 91, 763, 232, 479, 242, -243, +-16, -801, -134, -579, 33, 67, 309, 506, +445, 286, 317, -174, 213, -311, 183, 45, +82, 340, -161, 157, -292, -269, -41, -502, +389, -250, 434, 83, 96, 167, -32, 114, +389, 95, 738, 173, 315, 157, -452, -187, +-604, -421, 10, -361, 687, 16, 674, 352, +94, 278, -379, -46, -264, -348, 305, -284, +577, 34, 353, 292, -79, 246, -142, -113, +236, -408, 518, -320, 347, 161, -56, 487, +-216, 263, -88, -271, 93, -517, 56, -220, +117, 141, 436, 274, 571, 91, 334, -171, +-145, -267, -160, -156, 230, 151, 340, 334, +146, 127, -82, -152, -135, -247, -14, -108, +193, 16, 370, -42, 418, -89, 215, -59, +-21, -14, 74, 16, 314, 25, 339, 45, +6, 114, -247, 88, -75, -52, 213, -189, +217, -188, 16, -39, 138, 58, 495, -2, +618, -129, 247, -85, -292, 61, -419, 151, +-55, 91, 466, -53, 616, -122, 130, -112, +-268, -94, -46, -78, 376, 1, 488, 137, +141, 153, -125, 22, -23, -185, 65, -197, +98, -69, 201, -21, 367, -52, 468, -90, +186, 75, -212, 270, -157, 220, 211, -35, +416, -300, 165, -297, -177, -114, -65, 157, +156, 158, 272, -25, 291, -168, 387, -147, +399, 72, 94, 158, -219, -1, -227, -106, +146, -55, 441, 104, 250, 174, -118, -47, +-103, -311, 275, -314, 458, -41, 205, 208, +-94, 180, 36, -96, 341, -230, 390, 24, +156, 249, -87, 330, -33, -2, 146, -436, +183, -508, 32, -185, -81, 300, 74, 466, +371, 109, 454, -380, 301, -325, 100, 57, +-16, 398, 27, 229, 135, -265, 214, -406, +169, -148, -46, 199, -141, 284, 21, 36, +302, -327, 434, -299, 305, -14, 165, 276, +131, 272, 90, -68, 86, -188, 101, -23, +69, 39, 40, -64, -17, -174, 80, -111, +250, 42, 240, 58, 212, -56, 212, 32, +223, 178, 214, 150, 74, 3, -80, -260, +-81, -325, 138, -113, 385, 39, 370, 169, +0, 81, -207, -25, 10, 20, 347, 55, +442, 66, 212, -16, 17, -134, -2, -247, +14, -175, 24, -62, 261, 116, 436, 259, +270, 76, -93, -104, -255, -158, 128, 22, +511, 285, 378, 139, -112, -319, -300, -552, +57, -237, 483, 305, 501, 471, 180, 101, +1, -312, -34, -287, -38, 3, 6, 241, +244, 279, 488, 118, 255, -52, -208, -314, +-237, -515, 169, -370, 428, 60, 360, 471, +136, 504, 65, 68, 144, -396, 115, -301, +94, 158, 102, 460, 53, 162, 24, -467, +78, -678, 137, -259, 222, 286, 258, 483, +244, 247, 256, -133, 99, -227, -43, -107, +-40, 45, 55, 160, 198, 127, 256, 18, +234, -231, 111, -416, 37, -178, 60, 245, +159, 350, 184, -73, 67, -385, 108, -105, +184, 418, 162, 518, 117, 14, 186, -420, +290, -479, 156, -181, -149, 90, -231, 109, +73, 36, 439, -24, 531, 129, 181, 230, +-210, 83, -130, -241, 350, -319, 610, 18, +181, 292, -425, 96, -394, -383, 224, -492, +593, 44, 327, 558, -68, 472, 11, -94, +361, -519, 380, -323, 152, 98, -21, 300, +-147, 97, -232, -183, -76, -209, 359, -51, +584, 99, 309, 95, -22, 55, 49, -28, +273, -46, 171, -47, -97, -25, -78, -8, +119, -119, 168, -144, 110, 19, 130, 241, +266, 272, 297, -27, 89, -445, -85, -496, +-23, -36, 259, 535, 457, 614, 256, 3, +-130, -550, -282, -457, -94, 101, 326, 355, +426, 4, 143, -364, 32, -203, 93, 254, +252, 422, 233, 91, 62, -283, 26, -262, +19, 51, 24, 182, 40, 5, 118, -227, +204, -312, 213, -54, 174, 229, 160, 382, +126, 260, 86, -114, 66, -382, 44, -370, +123, -28, 164, 257, 133, 265, 19, -61, +20, -347, 236, -196, 277, 190, 67, 428, +-178, 152, -35, -319, 434, -391, 551, -59, +117, 322, -322, 246, -232, -187, 234, -417, +462, -201, 203, 223, -114, 347, -130, 101, +160, -161, 388, -120, 310, 84, 48, 99, +-172, -100, -85, -328, 182, -231, 325, 118, +273, 318, 101, 135, 75, -199, 56, -194, +-130, 111, -199, 255, 97, 6, 503, -281, +477, -182, 10, 149, -193, 257, 138, 9, +314, -261, 116, -344, -129, -137, -147, 150, +49, 288, 192, 276, 323, 118, 335, -123, +57, -268, -215, -244, -60, -58, 366, 143, +480, 124, 148, -44, -201, -60, -182, -7, +-38, 18, 53, -61, 99, -165, 239, 18, +378, 136, 287, 160, 143, 49, 48, -119, +6, -101, -62, -3, -77, 51, 16, -51, +72, -150, 48, -216, 85, -13, 232, 183, +331, 120, 307, 27, 155, -91, -28, 3, +-162, 147, -113, 77, 167, -36, 297, -119, +115, -147, -157, -145, -192, -171, 112, -119, +370, 71, 374, 228, 222, 215, -7, 105, +-51, -53, 68, -79, 155, 61, 139, 70, +-179, -80, -340, -327, -43, -403, 318, -121, +511, 229, 332, 345, 78, 197, 73, -13, +26, -97, -86, 6, -56, 63, 3, -21, +17, -117, 38, -241, 15, -200, 151, -22, +302, 151, 267, 220, 201, 95, 67, -152, +-86, -157, -57, 52, -7, 181, -42, 148, +23, -159, 103, -381, 187, -168, 195, 231, +55, 431, 92, 96, 168, -441, 95, -473, +38, 23, 47, 473, 20, 324, -90, -151, +-154, -381, -3, -87, 272, 260, 277, 255, +199, -42, 187, -363, 28, -279, -48, -27, +13, 190, 29, 257, -52, 125, -223, -60, +-91, -227, 315, -160, 402, 2, 163, 100, +39, 107, 117, 12, 199, -15, 14, -32, +-257, -107, -235, -119, -24, -31, 141, 48, +169, 31, 159, 8, 212, -26, 186, 37, +82, 90, 72, 50, 70, 9, -40, -125, +-179, -211, -216, -227, -57, -90, 210, 225, +438, 377, 366, 238, -54, -74, -392, -330, +-226, -301, 326, -77, 514, 60, 145, 94, +-288, 56, -317, -30, 44, 18, 322, 125, +203, 220, -88, 164, -181, -148, -2, -495, +244, -510, 244, -143, 130, 354, -43, 512, +-177, 289, -19, -6, 178, -195, 165, -215, +-83, -124, -197, -54, 3, -66, 251, -37, +228, -17, -7, 100, -28, 130, 65, 32, +156, -8, 44, -42, -215, -3, -214, -42, +30, -54, 205, -95, 222, -54, 148, 52, +53, 134, -7, 99, -115, -138, 2, -219, +142, -167, -61, 37, -216, 250, -56, 321, +284, 210, 404, -143, 46, -440, -341, -448, +-201, -128, 201, 235, 343, 307, 149, 151, +-192, -30, -252, 1, -34, 120, 94, 90, +75, -151, 79, -405, 98, -337, 126, 27, +42, 362, -159, 354, -108, -27, 126, -354, +251, -173, 100, 246, -250, 316, -306, -21, +-11, -351, 187, -266, 201, 170, 87, 330, +-43, 88, 6, -272, 56, -362, 75, -66, +125, 185, -40, 140, -261, -7, -307, -23, +-119, 141, 243, 251, 408, 132, 226, -81, +-66, -294, -186, -467, -109, -320, 11, -14, +102, 180, 63, 272, -31, 228, -102, 221, +-86, 212, 39, 51, 104, -168, -9, -343, +-88, -374, -30, -250, 109, 2, 225, 167, +172, 274, 9, 204, -165, 43, -234, -93, +-186, -206, -138, -55, -89, 96, 107, 198, +364, 164, 359, -79, 128, -319, -92, -310, +-216, -56, -271, 135, -220, 103, -30, -22, +136, 37, 98, 166, -71, 155, -41, 56, +155, -89, 250, -185, 167, -166, -52, -57, +-297, 88, -307, 36, -110, -117, 140, -122, +247, 14, -33, 105, -213, 61, -65, 46, +177, 130, 293, 171, -26, -43, -292, -349, +-158, -355, 116, -27, 285, 362, 82, 352, +-318, -49, -440, -436, -128, -425, 182, -20, +251, 442, 163, 475, 132, 93, 134, -263, +-132, -292, -332, -57, -218, 84, -32, -5, +-2, -117, -10, -79, 82, 30, 126, 131, +63, 109, -55, -16, -72, -90, -61, -110, +-44, -55, 20, 2, 23, 112, -82, 201, +-96, 104, 39, -138, 93, -213, 6, -109, +-220, -44, -267, -74, -35, -144, 194, 30, +262, 272, 125, 335, -45, 182, -124, -60, +-238, -285, -306, -347, -108, -193, 167, 45, +191, 289, 20, 282, -79, 6, -80, -280, +-51, -317, -58, -25, -20, 223, 104, 237, +92, 73, -41, -56, -185, -64, -262, -8, +-135, 14, 90, -84, 167, -182, 58, -171, +-48, 16, -101, 151, -52, 62, -5, -58, +-24, -20, 4, 187, -70, 295, -109, 108, +-10, -211, 22, -391, -26, -281, -163, -45, +-167, 85, 45, 97, 176, 134, 93, 191, +-91, 202, -124, 55, -53, -198, -98, -310, +-154, -221, -11, 20, 122, 194, 34, 200, +-157, 113, -150, 8, 33, -175, 26, -274, +-42, -160, -38, 92, -34, 271, -85, 150, +-109, -50, 42, -79, 127, 55, -11, 117, +-158, -26, -166, -292, -148, -371, -135, -84, +-50, 292, 128, 433, 252, 151, 141, -171, +-101, -229, -284, -33, -266, 159, -102, 67, +53, -225, 66, -359, -90, -37, -165, 367, +-101, 408, 97, 0, 287, -380, 157, -258, +-179, 89, -324, 295, -222, 134, -63, -184, +-59, -292, -143, -78, -6, 229, 141, 289, +147, 23, 93, -291, -51, -257, -134, -19, +-167, 206, -178, 206, -133, -7, -79, -71, +-26, 3, 30, 49, 68, -40, 11, -177, +-76, -183, -120, -55, -27, 103, 133, 235, +74, 238, -181, 38, -305, -172, -206, -206, +-35, -139, 30, -37, 19, -10, 70, 126, +43, 231, -29, 169, -56, -24, -54, -227, +-26, -263, -79, -113, -210, 72, -307, 125, +-158, 77, 147, 28, 243, 101, 83, 189, +-157, 72, -185, -162, 19, -347, 126, -310, +73, 14, -230, 284, -586, 270, -409, 55, +175, -165, 589, -119, 333, 52, -250, 137, +-423, 80, -131, -28, 218, -125, 113, -120, +-302, -60, -499, -45, -219, -15, 277, -16, +376, 14, 44, 143, -252, 224, -208, 196, +50, 6, 131, -181, -50, -220, -264, -186, +-349, -179, -203, -111, 57, 85, 188, 269, +173, 353, 51, 178, -96, -22, -136, -52, +-145, -114, -204, -192, -155, -301, -3, -274, +33, -53, -16, 191, -72, 376, -26, 420, +77, 270, -53, -18, -188, -302, -156, -492, +-115, -440, -3, -155, 87, 210, 120, 507, +82, 445, -187, 146, -364, -141, -305, -341, +-108, -353, 133, -215, 187, 18, 85, 281, +3, 400, -6, 246, -89, -48, -204, -302, +-280, -355, -276, -201, -32, -24, 206, 176, +213, 306, -4, 298, -263, 153, -170, -146, +70, -428, -10, -347, -239, -51, -181, 240, +100, 362, 220, 255, -44, 25, -325, -234, +-235, -403, 26, -285, 167, 80, 118, 350, +-95, 366, -322, 88, -331, -206, -101, -331, +225, -218, 341, 78, 64, 380, -273, 422, +-307, 74, -137, -433, -14, -683, -92, -401, +-174, 195, 51, 678, 256, 714, 81, 263, +-242, -295, -401, -563, -124, -531, 236, -254, +252, 113, -12, 444, -335, 501, -400, 156, +-153, -260, 100, -366, 171, -147, 122, 158, +-19, 283, -157, 134, -287, -211, -248, -368, +49, -210, 262, 205, 120, 453, -228, 329, +-351, -60, -186, -387, 63, -364, 123, -90, +9, 221, -50, 298, -102, 139, -78, -61, +-27, -193, -57, -147, -211, -13, -282, 72, +-23, 53, 291, 86, 273, 95, -119, 31, +-443, -35, -329, -73, 11, -76, 221, -87, +155, -43, -165, 39, -390, 77, -235, 27, +120, 35, 280, 94, 84, 111, -154, -3, +-259, -142, -168, -169, -12, -83, 15, 56, +-58, 124, -163, 35, -80, -74, 33, 55, +11, 186, -79, 97, -96, -145, -5, -311, +-16, -235, -78, 35, -87, 244, -86, 305, +-46, 249, -51, 137, -163, -62, -180, -305, +-27, -525, 153, -430, 66, -14, -175, 427, +-154, 669, -3, 432, 61, -124, -81, -465, +-182, -306, -88, 115, -57, 299, -45, -4, +-85, -423, -165, -503, -120, -117, 48, 496, +229, 866, 152, 556, -154, -217, -313, -854, +-229, -788, 4, -17, -20, 675, -271, 660, +-284, -56, 41, -637, 464, -421, 452, 284, +-43, 702, -572, 366, -646, -338, -230, -690, +258, -430, 401, 133, 16, 498, -379, 497, +-292, 162, 61, -188, 232, -303, 77, -254, +-149, -146, -163, -24, -175, 163, -193, 313, +-108, 252, -42, 20, 97, -226, 51, -211, +-110, -7, -138, 113, -93, -2, 8, -287, +74, -269, 49, 170, -29, 658, -184, 668, +-382, 166, -411, -594, -126, -1039, 182, -702, +302, 169, 293, 915, 83, 869, -96, 235, +-293, -345, -478, -528, -364, -306, -145, 1, +160, 143, 319, 77, 99, 17, -152, 45, +-182, 101, -55, 63, 82, -48, 4, -76, +-233, -72, -273, -61, -204, -5, -34, 157, +141, 252, 96, 118, -6, -225, -59, -440, +-158, -247, -176, 188, -92, 472, -64, 403, +-45, 100, -128, -170, -102, -467, 150, -576, +209, -207, -4, 395, -303, 786, -431, 555, +-217, -173, 52, -704, 196, -634, 121, -25, +-142, 554, -225, 547, -42, 92, 167, -304, +92, -341, -217, -153, -394, 31, -218, 98, +60, 152, 93, 115, 6, 123, -38, 96, +-34, -79, -124, -253, -229, -343, -127, -141, +132, 238, 293, 527, 144, 488, -255, 128, +-558, -390, -608, -796, -325, -731, 206, -166, +623, 658, 702, 1164, 284, 837, -431, -39, +-970, -937, -839, -1054, -179, -390, 458, 419, +715, 742, 365, 456, -187, -63, -544, -423, +-546, -368, -158, -144, 112, 143, 95, 333, +32, 377, 56, 351, 124, 82, 34, -402, +-261, -681, -457, -544, -346, -14, 4, 520, +250, 681, 149, 430, -136, -72, -198, -453, +-14, -550, 56, -232, -65, 267, -215, 629, +-74, 466, 79, -151, -100, -529, -301, -623, +-175, -242, 126, 346, 116, 711, -192, 570, +-314, -79, -58, -667, 231, -668, 178, -28, +-14, 620, -143, 716, -276, 170, -354, -518, +-290, -678, -43, -372, 223, 213, 281, 604, +48, 612, -271, 168, -482, -525, -304, -788, +293, -368, 661, 437, 341, 828, -477, 464, +-1018, -234, -711, -608, 17, -417, 481, 42, +568, 316, 363, 261, -51, 95, -439, -88, +-535, -115, -290, -66, -66, -120, 41, -186, +130, 98, 236, 478, 99, 618, -338, 134, +-528, -610, -359, -933, 57, -566, 365, 301, +388, 859, 159, 694, -200, 117, -497, -223, +-533, -189, -263, -223, 69, -443, 355, -440, +260, 58, -105, 595, -400, 650, -344, 161, +34, -481, 345, -507, 350, 84, -103, 588, +-565, 421, -673, -361, -281, -900, 344, -623, +447, 280, 113, 879, -224, 751, -288, 109, +-17, -401, 45, -381, -95, -126, -162, -31, +-326, -88, -254, -128, 53, -33, 323, 239, +317, 464, -123, 248, -485, -313, -462, -572, +-103, -244, 178, 340, 234, 653, 121, 452, +-182, -209, -338, -735, -247, -674, -12, 65, +166, 747, 23, 682, -172, -29, -240, -733, +-138, -704, 41, -9, 95, 807, 25, 934, +-192, 279, -282, -657, -116, -1008, 193, -506, +254, 396, -67, 901, -460, 491, -571, -373, +-289, -898, 263, -490, 696, 466, 500, 1113, +-216, 824, -920, -163, -777, -1113, -4, -1261, +541, -357, 470, 805, -150, 1419, -463, 826, +-259, -498, 119, -1325, 203, -823, -13, 441, +-249, 1119, -465, 640, -356, -572, 55, -1152, +498, -491, 535, 804, 15, 1504, -604, 722, +-685, -780, -367, -1697, 89, -1060, 324, 390, +210, 1308, 39, 1037, -124, 50, -101, -616, +-93, -570, -60, -55, -134, 257, -321, 213, +-349, -197, -60, -382, 333, -134, 286, 302, +-50, 574, -241, 406, -151, -79, -66, -612, +-124, -651, -186, -213, -176, 382, -124, 603, +78, 436, 332, -5, 210, -276, -176, -284, +-600, -224, -576, -70, -27, 46, 410, 216, +520, 294, 217, 97, -275, -241, -668, -430, +-664, -136, -194, 244, 352, 432, 536, 378, +311, 114, -34, -224, -345, -449, -509, -380, +-423, -172, -154, 139, 157, 277, 203, 291, +136, 195, 220, -22, 97, -88, -239, -61, +-545, 84, -582, 37, -240, -209, 278, -327, +567, -108, 445, 255, -78, 399, -577, 229, +-605, -187, -313, -443, 28, -293, 414, 127, +549, 541, 138, 555, -450, 80, -818, -443, +-536, -688, 162, -510, 610, 84, 527, 657, +2, 739, -545, 173, -539, -461, -11, -493, +243, -81, -78, 204, -513, 173, -268, -23, +423, -136, 517, -61, 77, 100, -381, 226, +-412, 200, -153, -93, -105, -327, -144, -291, +70, 18, 222, 346, 69, 378, -145, 76, +-342, -313, -256, -370, 39, -117, 228, 270, +221, 316, -58, 100, -443, -66, -388, -92, +-30, -54, 229, -76, 200, -109, -56, -68, +-228, 94, -276, 193, -237, 135, -11, -109, +319, -199, 276, 8, -104, 174, -405, 195, +-270, 81, 21, -84, 34, -143, -58, -186, +-119, -161, -57, -139, -23, 75, -145, 300, +-118, 349, 107, 170, 263, -135, 97, -182, +-196, -40, -271, 35, -235, -160, -215, -264, +-199, -95, -103, 224, 145, 425, 216, 215, +141, -191, 129, -400, 83, -184, -147, 140, +-533, 379, -597, 424, -203, 23, 357, -484, +523, -563, 99, -93, -388, 426, -363, 480, +-4, 78, 225, -355, 3, -425, -200, -62, +-75, 368, -46, 496, -97, 195, -173, -205, +-30, -328, 124, -173, 23, 67, -134, 145, +-159, -38, -82, -349, -139, -343, -122, 167, +181, 624, 383, 596, 153, 136, -371, -226, +-677, -361, -537, -479, 12, -304, 671, -24, +727, 386, 102, 480, -647, 213, -841, -335, +-313, -627, 273, -217, 529, 449, 406, 863, +-58, 453, -540, -268, -600, -746, -125, -611, +376, -77, 442, 275, 69, 331, -311, 109, +-570, -49, -456, 38, 115, 168, 565, 209, +492, -4, -23, -294, -387, -260, -375, 41, +-299, 180, -192, 65, -9, -128, 198, -175, +238, -84, 64, 89, -29, 234, -127, 266, +-221, 62, -343, -166, -54, -135, 288, 6, +171, 116, 77, -10, -113, -74, -331, -176, +-586, -272, -403, -56, 340, 163, 791, 367, +484, 397, -299, 224, -660, -141, -450, -403, +35, -413, 352, -140, 202, 275, -227, 298, +-494, -11, -227, -327, 260, -178, 427, 214, +81, 444, -330, 366, -342, -49, 81, -469, +356, -447, 146, -34, -367, 397, -593, 361, +-338, -205, 68, -508, 388, -242, 403, 346, +257, 597, -193, 386, -458, -81, -397, -415, +-122, -478, 330, -269, 354, 118, -119, 372, +-554, 372, -362, 72, 138, -273, 430, -255, +301, 73, -99, 307, -278, 98, -297, -256, +-198, -385, -83, -110, 18, 372, 198, 493, +263, 217, 164, -214, -224, -353, -573, -264, +-447, -160, 68, 8, 510, 209, 449, 311, +-51, 264, -434, 60, -352, -127, -63, -174, +90, -208, 76, -87, 12, -3, -35, -36, +-33, -25, -64, 162, -122, 330, -60, 291, +64, -26, 198, -384, 45, -360, -440, -112, +-531, 208, -17, 231, 523, 19, 509, -105, +14, -23, -464, 185, -411, 222, -68, 58, +89, -228, -49, -388, -165, -179, 17, 233, +190, 362, 235, 127, 51, -188, -172, -289, +-238, -84, -225, 242, -176, 330, -23, 72, +229, -131, 203, -127, -17, -60, -236, -48, +-219, -131, -25, -154, 62, -16, 141, 168, +71, 275, -78, 215, -251, 82, -177, -48, +79, -67, 146, -88, -49, -290, -249, -346, +-126, -10, 68, 413, 221, 429, 151, -20, +-59, -353, -241, -324, -318, 51, -148, 485, +139, 444, 292, 12, 161, -485, -134, -554, +-350, -138, -177, 390, 112, 425, 20, 71, +-29, -362, 18, -395, 87, 23, 88, 432, +-160, 508, -214, 93, -76, -311, 160, -325, +133, -49, -231, 129, -365, -63, -43, -357, +317, -315, 250, 174, -76, 654, -155, 576, +-27, 67, -24, -301, -250, -394, -345, -240, +8, -106, 337, 11, 409, 146, 80, 186, +-402, 122, -463, -82, -185, -220, 176, -48, +281, 310, 172, 343, -42, 16, -182, -332, +-180, -352, -56, 39, 106, 191, -77, 101, +-141, -158, -46, -305, 99, 11, 125, 495, +-59, 639, -106, 38, 51, -745, 199, -843, +-115, -46, -471, 817, -282, 795, 307, 25, +444, -762, -99, -625, -491, 48, -145, 509, +571, 408, 533, 52, -293, -200, -896, -295, +-603, -105, 261, 141, 677, 170, 419, -6, +61, -117, -176, -65, -360, 68, -478, 216, +-290, 97, 249, -145, 511, -325, 267, -193, +-212, 224, -374, 460, -151, 213, 128, -254, +230, -337, -77, -183, -307, 13, -199, 154, +120, 223, 269, 136, 127, 45, 8, -3, +-153, -141, -298, -236, -154, -237, 208, 42, +287, 254, -210, 250, -616, 36, -194, -83, +678, -92, 806, -70, 3, 69, -671, 67, +-697, 28, -273, -149, 242, -166, 598, -16, +371, 221, -245, 255, -632, -34, -303, -246, +405, -370, 565, 16, 231, 486, -362, 610, +-649, 107, -426, -686, 154, -861, 541, -190, +397, 745, 33, 799, -330, 55, -320, -627, +-160, -519, -30, 105, 115, 498, 178, 387, +57, -198, -144, -507, -150, -164, 146, 397, +350, 549, -23, 52, -522, -640, -491, -786, +87, -223, 452, 662, 232, 1112, -142, 594, +-167, -516, 22, -1189, 83, -718, 121, 335, +-122, 1076, -231, 789, -143, -319, -52, -1026, +151, -838, 221, 227, 27, 1088, -260, 838, +-266, -234, 4, -978, 287, -716, 271, 154, +92, 941, -57, 730, -352, -160, -490, -792, +-248, -675, 274, 14, 566, 565, 318, 651, +-215, 69, -627, -554, -349, -632, 395, -123, +834, 553, 304, 807, -765, 448, -988, -390, +-281, -912, 632, -809, 830, -54, 213, 844, +-252, 939, -553, 275, -369, -646, 89, -934, +345, -214, 323, 733, -36, 898, -355, -28, +-369, -895, 9, -716, 302, 251, 249, 890, +66, 499, -117, -350, -300, -771, -267, -348, +-13, 256, 301, 505, 457, 230, 99, -70, +-419, -94, -523, -35, -119, -13, 291, -149, +275, -258, -51, -95, -117, 337, 79, 453, +136, 86, -17, -404, -130, -443, -79, -6, +-122, 362, -121, 428, -96, 26, 30, -337, +222, -518, 227, -159, 138, 414, -140, 694, +-404, 354, -284, -461, 286, -762, 608, -558, +73, 279, -661, 809, -720, 603, 75, -56, +660, -682, 443, -619, -135, -40, -247, 664, +27, 684, 2, 40, -84, -732, -202, -767, +-114, -114, 49, 556, 218, 825, 165, 402, +-110, -272, -150, -777, -146, -466, 23, 71, +88, 394, 82, 329, 93, 46, 19, -115, +-115, -177, -163, 60, -64, 134, -68, 144, +111, -47, 189, -231, 87, -320, -187, -176, +-408, 279, -130, 425, 343, 292, 491, -203, +25, -380, -358, -88, -314, 223, 110, 283, +334, -4, -56, -262, -451, -325, -358, -87, +230, 155, 535, 235, 247, 216, -191, 137, +-283, -100, -99, -254, -9, -22, -44, 61, +-29, -27, 275, -99, 252, -41, -228, 102, +-548, 111, -233, -11, 339, -10, 594, 152, +245, 141, -417, -61, -566, -471, -279, -484, +280, 190, 655, 756, 330, 604, -237, -213, +-625, -705, -507, -530, 146, 69, 630, 564, +539, 476, -171, -48, -671, -521, -381, -347, +176, 71, 427, 291, 189, 141, -62, -48, +-108, 81, -56, 111, 57, 114, 83, -93, +-82, -398, -204, -375, -190, 44, -180, 452, +-28, 392, 213, 67, 519, -349, 416, -520, +-45, -235, -451, 410, -621, 836, -149, 491, +453, -115, 467, -825, -146, -999, -774, -403, +-375, 491, 555, 1098, 920, 625, 310, -294, +-597, -686, -679, -403, -155, 185, 462, 601, +511, 387, -62, -223, -572, -690, -551, -581, +-29, 89, 450, 621, 621, 664, 306, 111, +-231, -516, -570, -747, -437, -241, 320, 629, +705, 884, 238, 369, -625, -447, -975, -881, +-275, -737, 805, 14, 1112, 798, 336, 936, +-640, 263, -1095, -711, -529, -1044, 596, -421, +1166, 741, 603, 1178, -645, 577, -1194, -561, +-549, -1259, 616, -758, 995, 420, 308, 1099, +-589, 766, -853, -240, -213, -1090, 655, -881, +902, 202, 363, 997, -474, 1020, -884, 136, +-589, -756, 46, -978, 624, -523, 570, 387, +92, 919, -377, 650, -430, -197, 37, -977, +464, -901, 483, 193, -97, 1336, -706, 1229, +-718, -182, -54, -1486, 661, -1299, 673, 21, +243, 1167, -350, 1206, -582, 237, -201, -875, +262, -1074, 480, -284, 166, 676, -331, 852, +-604, 208, -327, -421, 293, -597, 640, -226, +577, 249, -85, 477, -638, 282, -501, -254, +18, -415, 381, -225, 214, 115, -42, 376, +-150, 268, -167, 24, 11, -249, 260, -275, +246, -146, -56, -52, -308, 150, -227, 348, +17, 334, 107, -160, 160, -492, 220, -319, +-17, 245, -162, 644, -190, 358, -156, -492, +20, -953, 102, -370, 311, 596, 248, 1023, +-55, 430, -327, -478, -429, -857, -111, -445, +188, 397, 406, 881, 294, 470, -48, -503, +-167, -1001, -302, -512, -227, 421, 27, 853, +321, 534, 205, -220, -154, -621, -164, -280, +43, 300, 124, 423, -19, 54, -60, -379, +-60, -417, 86, -54, 98, 297, -91, 329, +-179, 20, -131, -136, 171, -63, 223, 28, +-27, 8, -193, -20, 17, 38, 284, 100, +155, 23, -189, -118, -406, -174, -222, -174, +99, -17, 367, 155, 251, 298, -62, 231, +-216, -71, -203, -244, 61, -174, 267, 37, +204, 133, -68, 76, -381, -119, -379, -169, +63, -75, 445, 147, 366, 258, 46, 49, +-327, -12, -390, -12, -180, -45, 142, -320, +314, -419, 349, 12, 238, 634, -205, 891, +-504, 219, -477, -735, 14, -1197, 496, -591, +443, 683, -26, 1229, -383, 601, -240, -549, +157, -934, 341, -285, 133, 489, -200, 504, +-371, -39, -161, -391, 132, -174, 272, 266, +213, 375, -22, -1, -249, -447, -253, -493, +29, -52, 231, 615, 183, 792, -87, 183, +-205, -640, 70, -993, 179, -484, -5, 555, +-81, 1207, -186, 833, -98, -474, -32, -1411, +51, -940, 299, 379, 240, 1241, 31, 870, +-213, -172, -253, -853, -208, -741, -52, -55, +167, 568, 227, 663, 238, 187, 43, -341, +-212, -525, -289, -408, -57, 121, 155, 621, +151, 511, 9, -122, -163, -721, -100, -618, +14, 124, 309, 879, 331, 805, -117, -74, +-450, -841, -462, -810, -34, -49, 427, 625, +525, 715, 264, 77, -259, -632, -553, -724, +-294, -67, 205, 852, 434, 895, 115, 3, +-278, -858, -336, -968, 77, -114, 551, 867, +398, 1017, -171, 99, -658, -968, -537, -1103, +5, -161, 489, 1026, 551, 1073, 149, 158, +-193, -780, -332, -725, -148, 86, 33, 528, +139, 253, 183, -348, -21, -440, -312, -65, +-266, 293, 174, 270, 459, 76, 262, 12, +-275, 18, -527, -26, -169, -233, 454, -166, +644, 134, 74, 263, -681, -1, -733, -306, +-32, -287, 678, 166, 739, 437, 76, 228, +-582, -206, -614, -484, -159, -206, 402, 365, +591, 614, 313, 172, -241, -484, -614, -675, +-539, -204, 78, 444, 711, 617, 603, 217, +17, -343, -602, -497, -589, -223, -92, 211, +348, 392, 440, 296, 203, 7, -72, -346, +-329, -465, -204, -128, 44, 478, 258, 623, +136, 80, -264, -583, -297, -766, 44, -158, +312, 681, 210, 834, -18, 163, -198, -643, +-131, -776, 1, -142, 122, 705, 170, 782, +-29, 86, -165, -716, -107, -910, -5, -127, +46, 696, -3, 793, -7, 83, 74, -567, +131, -519, 94, 33, -48, 520, -79, 373, +-33, -161, 3, -495, -23, -234, -172, 196, +-164, 276, -45, 36, 202, -189, 375, -87, +222, 34, -53, 118, -246, 206, -219, 211, +-136, 43, -61, -359, 51, -584, 171, -308, +116, 341, -19, 829, -34, 533, -50, -220, +34, -693, 73, -547, 44, -40, -78, 386, +-215, 434, -84, 125, 126, -139, 303, -164, +96, 49, -250, 180, -280, -56, -108, -336, +128, -362, 199, 33, 187, 504, 228, 432, +46, -40, -329, -427, -455, -282, -173, 116, +195, 313, 330, 170, 237, -117, 56, -287, +-169, -206, -284, 20, -157, 184, 157, 235, +356, 87, 95, -107, -186, -225, -263, -111, +-123, 255, 119, 343, 204, 46, 104, -407, +-99, -477, -276, -4, -108, 445, 252, 432, +291, -155, 87, -550, -260, -267, -178, 390, +24, 765, 12, 327, 58, -387, -12, -766, +-12, -514, -189, 152, -192, 466, 186, 375, +527, 29, 448, -146, -222, -16, -722, 53, +-570, -57, 106, -238, 656, -123, 532, 257, +-110, 449, -551, 106, -397, -525, 44, -667, +410, -160, 399, 595, 181, 816, -133, 236, +-496, -528, -441, -764, -11, -200, 476, 473, +441, 645, -91, 245, -462, -335, -290, -563, +267, -328, 488, 96, 171, 310, -346, 256, +-433, 162, -84, 58, 232, -60, 264, -256, +8, -307, -96, -54, -73, 230, -78, 296, +-66, 132, 103, -134, 271, -262, 105, -103, +-171, 80, -306, 128, -130, -14, 86, -82, +112, -22, 64, 45, 72, 117, 108, 100, +41, 91, -68, -7, -192, -102, -121, -204, +7, -238, 9, -58, -13, 115, 16, 252, +140, 172, 161, 32, 59, -48, -92, -65, +-98, 51, -37, 21, -54, -170, -149, -307, +-99, -144, 111, 235, 274, 372, 151, 250, +-170, -89, -229, -385, 15, -281, 283, 57, +75, 413, -223, 293, -254, -99, 28, -309, +264, -314, 35, -10, -139, 234, -162, 259, +57, 40, 238, -240, 101, -150, -35, 66, +-218, 244, -182, 181, 55, -26, 155, -185, +108, -253, -100, -130, -177, 41, -1, 232, +110, 213, 107, 51, 15, -114, -76, -150, +-41, 27, -34, 102, -30, 10, -48, -121, +-58, -120, 107, -16, 196, 180, 35, 253, +-198, 101, -187, -221, 135, -420, 244, -235, +-149, 176, -377, 462, -83, 338, 490, 12, +562, -332, -156, -369, -662, -57, -583, 246, +128, 255, 676, -60, 438, -278, -107, -210, +-492, 69, -282, 332, 130, 360, 377, 140, +229, -172, -186, -416, -428, -464, -339, -214, +109, 258, 393, 624, 320, 561, 58, 18, +-129, -551, -123, -578, -178, -163, -104, 355, +-13, 461, 76, 90, 97, -304, -97, -374, +-53, -30, 127, 376, 221, 391, 65, 46, +-255, -331, -316, -394, -113, -71, 249, 298, +416, 374, 153, 76, -257, -273, -470, -389, +-255, -181, 237, 156, 446, 373, 172, 242, +-168, -129, -310, -263, -89, -81, 223, 267, +206, 350, -28, -4, -283, -413, -213, -529, +71, -235, 285, 232, 174, 521, -137, 428, +-263, 108, -160, -236, 97, -361, 256, -206, +248, 69, 21, 228, -168, 164, -362, -4, +-311, -209, 72, -272, 407, -170, 462, 113, +41, 336, -432, 325, -557, 91, -86, -199, +483, -270, 595, -99, 126, 180, -524, 244, +-643, -118, -240, -442, 380, -341, 602, 150, +320, 560, -127, 482, -432, 22, -378, -452, +-70, -394, 324, 55, 422, 319, 44, 141, +-454, -230, -478, -291, -17, -119, 477, 152, +584, 298, 225, 214, -290, 2, -661, -149, +-471, -125, 116, -62, 547, 21, 435, 85, +-120, 70, -475, -111, -308, -262, 223, -172, +503, 161, 286, 389, -253, 319, -497, -11, +-222, -343, 101, -293, 201, 6, 90, 258, +106, 161, 146, -109, -77, -296, -348, -205, +-307, 83, 124, 311, 507, 298, 305, 31, +-185, -146, -403, -142, -212, -94, 142, -85, +214, -31, 7, 69, -173, 112, -135, 59, +77, -2, 232, -48, 200, -101, -17, 19, +-245, 90, -270, 69, -85, -66, 173, -134, +279, -16, 50, 96, -194, 202, -152, 85, +-10, -182, 195, -303, 113, -94, -127, 253, +-185, 208, -133, -33, 119, -176, 177, -9, +93, 205, -19, 125, -86, -135, 3, -373, +-29, -88, -167, 306, -178, 366, 7, 32, +245, -394, 302, -242, 23, 133, -224, 332, +-254, 138, -40, -255, 164, -361, 65, -84, +-69, 255, -11, 297, 163, 60, 91, -10, +-184, 44, -219, -41, -10, -224, 117, -317, +56, -122, -84, 126, -44, 323, 151, 283, +198, 62, 18, -177, -186, -254, -176, -12, +-20, 103, 39, 110, -55, -11, -131, -167, +50, -155, 228, 40, 179, 218, -13, 157, +-250, -55, -95, -151, 169, -6, 185, 101, +-91, 50, -444, -106, -290, -190, 126, -18, +496, 223, 476, 232, 12, -68, -420, -362, +-513, -204, -119, 296, 284, 465, 315, 118, +152, -464, -80, -596, -297, -68, -260, 595, +100, 685, 447, 73, 366, -654, -236, -701, +-647, -108, -500, 509, 103, 665, 741, 213, +641, -372, 24, -608, -557, -193, -497, 403, +-20, 549, 241, 160, 199, -464, -122, -649, +-279, -356, -101, 299, 228, 770, 446, 641, +271, 11, -182, -633, -471, -667, -302, -172, +119, 387, 365, 438, 94, 81, -341, -250, +-339, -290, 7, -36, 424, 251, 478, 337, +141, 139, -320, -232, -598, -447, -273, -213, +237, 202, 468, 510, 304, 291, -170, -230, +-432, -537, -316, -385, 35, 192, 417, 508, +354, 313, -24, -194, -255, -384, -188, -86, +36, 244, 112, 325, -10, -24, -215, -312, +-211, -352, 127, -89, 417, 357, 298, 477, +-60, 182, -457, -274, -458, -542, -113, -390, +258, 98, 496, 487, 294, 513, -37, 122, +-260, -309, -243, -288, -86, -31, -10, 126, +-37, -59, -98, -297, -44, -253, 114, 85, +164, 394, 192, 410, 285, 146, 164, -166, +-59, -137, -455, -118, -694, -128, -401, -220, +240, -219, 765, 80, 523, 281, -100, 367, +-422, 141, -246, -121, 77, -247, 152, -143, +91, 47, 1, 50, -92, 99, -147, 42, +-73, -20, 13, -98, 23, -123, -14, -41, +-76, -14, -7, 8, 135, 49, 235, 175, +200, 272, 72, 193, -165, -70, -346, -366, +-308, -434, -132, -166, 131, 164, 187, 298, +96, 159, 23, -38, 73, -71, 171, 44, +97, 201, -105, 144, -286, -64, -205, -231, +86, -260, 193, -151, -8, -39, -217, 164, +-168, 290, 111, 157, 329, -105, 222, -166, +-115, 19, -346, 146, -223, 112, 154, -92, +350, -226, 202, -153, -130, 88, -343, 263, +-332, 79, -75, -196, 261, -241, 318, 40, +128, 250, -199, 174, -255, 1, 43, -123, +275, -57, 220, -19, -116, -9, -310, -35, +-234, -27, -135, 30, 89, -21, 310, -8, +301, 11, -36, 93, -419, 124, -254, 32, +237, -78, 540, -166, 242, -94, -434, -15, +-749, 101, -304, 90, 500, 43, 764, 59, +257, -16, -486, -82, -654, -81, -163, 28, +383, 72, 516, -13, 182, -123, -258, -143, +-431, 20, -305, 222, 57, 333, 434, 156, +469, -229, -26, -423, -598, -252, -610, 79, +48, 298, 740, 260, 660, 60, -11, -149, +-682, -247, -629, -137, 21, 44, 487, 235, +387, 195, -165, -68, -379, -204, -137, -117, +224, 165, 381, 246, 133, 83, -224, -202, +-410, -398, -209, -289, 173, 62, 334, 487, +186, 459, -155, 75, -287, -314, -112, -365, +155, -67, 273, 157, 85, 212, -162, -9, +-265, -176, -192, -198, 110, -69, 339, 138, +243, 238, -127, 219, -377, 56, -194, -174, +112, -279, 272, -110, 114, 118, -123, 233, +-199, 57, -30, -206, 193, -286, 155, -97, +-15, 226, -190, 377, -178, 301, -56, -66, +103, -348, 208, -424, 122, -62, -143, 321, +-308, 302, -118, 3, 260, -337, 379, -193, +24, 157, -262, 355, -235, 144, 45, -249, +158, -314, -81, -54, -155, 225, -27, 187, +159, 15, 149, -66, -67, -51, -80, -61, +69, -113, 181, -80, 30, 42, -255, 89, +-289, 72, -38, 52, 240, 95, 221, 137, +-45, 15, -235, -222, -107, -316, 120, -146, +291, 129, 202, 254, -95, 129, -319, 8, +-356, -44, -43, -60, 261, -72, 351, -57, +59, 55, -287, 82, -227, 63, -8, -22, +222, -41, 215, -6, 76, -15, -54, -109, +-242, -167, -239, -8, -70, 166, 151, 245, +225, 115, 62, -79, -49, -147, -91, -115, +-34, -11, 10, 36, 10, 50, 62, -1, +61, -6, -49, -8, -173, -50, -100, -33, +82, 49, 116, 135, -28, 102, -144, -56, +7, -166, 262, -128, 231, 37, -141, 210, +-426, 221, -227, 9, 220, -257, 415, -310, +99, -143, -264, 71, -261, 269, -84, 317, +59, 159, 147, -139, 266, -347, 246, -206, +-68, 110, -420, 323, -439, 171, -86, -215, +354, -394, 480, -158, 197, 345, -299, 504, +-521, 135, -173, -421, 332, -563, 444, -142, +108, 488, -263, 666, -318, 153, -78, -477, +108, -681, 183, -240, 91, 381, -88, 632, +-184, 299, -151, -270, 91, -580, 236, -331, +195, 272, 8, 563, -212, 327, -195, -321, +-29, -625, 116, -266, 124, 383, -93, 652, +-190, 208, -17, -406, 190, -582, 217, -219, +46, 283, -98, 496, -157, 263, -183, -129, +-85, -359, 157, -293, 285, -6, 139, 260, +-161, 322, -288, 78, -198, -294, -17, -407, +197, -63, 299, 378, 203, 497, -48, 130, +-226, -349, -270, -529, -119, -281, 116, 161, +224, 392, 79, 332, -164, 76, -128, -146, +109, -252, 255, -201, 30, 26, -285, 216, +-268, 178, 26, -77, 310, -301, 242, -177, +-45, 182, -219, 403, -142, 253, -6, -171, +52, -411, 59, -358, 38, -20, 32, 314, +-57, 389, -69, 178, 6, -140, 147, -262, +147, -202, -85, 10, -238, 114, -182, 78, +68, -16, 230, -54, 150, 47, -39, 103, +-97, 28, -105, -119, -56, -97, 16, 17, +35, 84, 78, 33, 47, -55, 5, -26, +-41, 96, -49, 152, -20, 31, -35, -210, +-48, -288, -17, -92, 69, 169, 113, 257, +65, 148, -2, 12, -50, -44, -140, -44, +-183, -117, -62, -158, 122, -91, 250, 90, +162, 228, -14, 133, -138, -41, -162, -189, +-79, -128, -40, 45, 34, 146, 64, 64, +82, -96, 51, -96, -46, 56, -43, 172, +49, 74, 116, -108, -16, -188, -170, -81, +-179, 96, 32, 135, 182, 20, 114, -67, +-23, -97, -120, -35, -124, 54, -75, 129, +101, 167, 232, 48, 159, -122, -102, -279, +-259, -137, -131, 160, 125, 269, 246, 55, +49, -257, -258, -229, -364, 19, -43, 224, +416, 161, 434, 8, -19, -39, -367, 3, +-198, 89, 180, 2, 235, -191, -100, -274, +-305, -148, -184, 110, 68, 289, 211, 279, +154, 102, 62, -216, -31, -326, -20, -94, +-7, 254, -27, 332, -56, 17, -82, -272, +-12, -292, -28, -27, -59, 218, -38, 163, +71, -90, 183, -218, 150, -18, 34, 261, +-101, 315, -146, 42, -90, -296, 10, -341, +60, -78, 12, 240, -64, 279, -104, 4, +-14, -281, 102, -312, 186, -27, 200, 359, +13, 496, -208, 195, -314, -328, -136, -527, +180, -243, 261, 188, 29, 365, -162, 138, +-85, -218, 103, -288, 152, 9, -19, 334, +-140, 308, -86, -34, 51, -341, 100, -288, +68, 10, -22, 239, -107, 224, -105, -45, +-20, -220, 99, -155, 101, 97, -16, 243, +-72, 132, -8, -61, 70, -230, 88, -172, +44, 14, -53, 204, -171, 225, -176, 37, +-35, -205, 136, -327, 195, -153, 126, 204, +-23, 449, -135, 283, -110, -149, 30, -435, +146, -294, 26, 88, -132, 313, -142, 198, +-29, -119, 60, -292, 59, -153, 78, 165, +95, 334, 79, 218, -18, -54, -122, -252, +-96, -216, 7, -34, -18, 77, -152, 30, +-151, -111, 144, -107, 414, 125, 294, 357, +-126, 316, -416, -83, -296, -425, 51, -323, +309, 86, 179, 348, -121, 164, -220, -247, +-119, -427, 96, -152, 229, 299, 258, 515, +114, 280, -259, -146, -481, -361, -278, -229, +239, 52, 527, 171, 321, 43, -188, -105, +-513, -104, -299, 22, 154, 91, 427, -16, +251, -53, -59, 64, -260, 250, -250, 177, +-9, -139, 219, -326, 220, -226, -64, 113, +-272, 237, -189, 95, 60, -154, 256, -213, +251, -16, 84, 160, -135, 218, -227, 89, +-99, -50, 24, -125, 40, -92, -42, 6, +-82, 33, 10, -20, 161, -58, 246, -15, +74, 46, -204, 36, -277, -17, -69, 22, +193, 108, 228, 169, -3, 9, -278, -269, +-291, -339, 46, -65, 385, 349, 339, 424, +-77, 68, -361, -382, -248, -439, 83, -75, +338, 342, 237, 455, -117, 114, -393, -278, +-298, -374, 73, -110, 361, 168, 345, 158, +57, 36, -242, -59, -338, 7, -97, 120, +246, 80, 290, -56, -5, -197, -317, -180, +-316, -18, -6, 136, 342, 177, 444, 133, +183, 18, -290, -140, -543, -197, -304, -95, +211, 106, 522, 209, 313, 152, -229, -23, +-519, -190, -246, -240, 309, -117, 572, 108, +179, 274, -440, 285, -524, 22, -84, -253, +407, -321, 410, -90, 54, 221, -219, 245, +-291, 42, -196, -198, -14, -211, 242, -13, +275, 206, 99, 229, -156, 54, -219, -101, +-16, -104, 151, -26, 133, -38, -121, -125, +-282, -176, -143, -79, 137, 151, 311, 381, +199, 329, -52, 42, -187, -227, -159, -246, +-11, -131, 91, -88, 81, -84, 0, -85, +-51, 81, -39, 277, -2, 309, 14, 68, +-50, -256, -114, -254, -46, -6, 162, 208, +305, 179, 205, 11, -141, -142, -378, -237, +-298, -165, -3, 51, 245, 168, 245, 118, +29, -24, -193, -75, -192, 31, 76, 171, +352, 232, 277, 39, -115, -239, -500, -359, +-399, -226, 90, 48, 477, 216, 440, 240, +-22, 98, -434, -107, -422, -185, -39, -70, +354, 153, 421, 256, 105, 133, -287, -136, +-381, -340, -128, -265, 254, 5, 441, 241, +169, 272, -321, 132, -568, -97, -297, -260, +320, -171, 621, 53, 360, 219, -179, 141, +-449, -55, -283, -153, 75, -107, 281, 50, +124, 136, -114, 76, -172, -52, -30, -109, +85, -32, 95, 59, 121, 28, 79, -57, +-146, -124, -346, -86, -200, 28, 258, 179, +530, 298, 299, 224, -213, -13, -550, -342, +-422, -452, 39, -257, 388, 103, 362, 394, +121, 365, -115, 117, -253, -203, -230, -364, +2, -227, 286, 106, 317, 424, -16, 391, +-374, -59, -379, -498, -22, -503, 328, -16, +332, 489, 43, 497, -167, 39, -120, -458, +-31, -507, -11, -79, 46, 411, 117, 511, +10, 164, -163, -265, -163, -398, 35, -168, +199, 145, 121, 257, -15, 77, -84, -198, +-100, -216, 6, 5, 105, 222, 101, 209, +-38, -14, -201, -169, -190, -200, -12, -32, +235, 160, 300, 217, 80, 138, -162, -81, +-228, -201, -123, -238, 49, -117, 137, 43, +128, 179, -19, 236, -129, 112, -87, -59, +-5, -199, 68, -138, 92, 52, 110, 197, +-4, 140, -145, -69, -141, -250, -14, -215, +79, 58, 63, 300, 60, 266, 16, -75, +-21, -321, -73, -291, -91, 29, -24, 322, +85, 317, 158, 83, 61, -218, -87, -249, +-136, -62, -12, 119, 79, 51, -1, -144, +-88, -192, -62, -13, 62, 238, 185, 299, +132, 157, -80, -105, -193, -239, -112, -173, +74, -20, 147, 50, 28, 22, -122, 11, +-111, 42, 32, 40, 164, -21, 127, -52, +-77, -2, -179, 101, -94, 114, 76, 17, +176, -106, 63, -127, -130, 19, -207, 92, +10, -24, 266, -215, 183, -206, -129, 95, +-310, 375, -125, 371, 130, 12, 233, -326, +131, -298, -24, -10, -104, 194, -138, 22, +-76, -202, 26, -188, 116, 84, 96, 331, +-28, 245, -145, -36, -76, -258, 141, -163, +186, 126, 30, 226, -180, -23, -240, -315, +-34, -301, 215, 8, 268, 332, 86, 362, +-192, 104, -267, -232, -115, -312, 53, -87, +136, 174, 131, 228, 110, 83, 29, -122, +-66, -240, -105, -181, -106, 29, -81, 264, +-30, 257, 34, 7, 112, -243, 141, -241, +59, 71, 8, 327, -35, 221, -112, -205, +-163, -474, -102, -259, 84, 204, 223, 477, +149, 322, -55, -105, -146, -394, -85, -266, +-10, 130, 30, 311, 40, 99, 31, -190, +10, -247, -23, -40, 11, 157, 65, 180, +16, 26, -64, -132, -78, -73, 9, 87, +63, 136, -32, -10, -76, -151, -24, -126, +87, -36, 168, 55, 88, 106, -114, 81, +-182, 35, -34, -19, 111, -58, 66, -64, +-160, -18, -137, 61, 120, 72, 221, -14, +72, -103, -160, -72, -186, 46, 33, 123, +218, 82, 119, -40, -112, -102, -195, -63, +-60, 36, 90, 43, 49, -22, -72, -20, +-66, 27, 57, 71, 162, 46, 153, -29, +24, -54, -133, -39, -193, 13, -97, 26, +36, -59, 85, -121, 13, -59, -59, 159, +13, 307, 133, 202, 149, -121, -28, -412, +-188, -344, -152, 2, 18, 338, 197, 361, +200, 83, -9, -220, -262, -298, -312, -101, +-27, 170, 291, 283, 301, 155, 45, -138, +-195, -351, -210, -293, -17, 19, 192, 381, +196, 425, -8, 90, -205, -335, -208, -440, +-112, -77, 28, 352, 184, 420, 253, 13, +143, -444, -97, -491, -219, -63, -101, 459, +69, 552, 103, 123, 5, -406, -145, -460, +-134, -40, 48, 391, 234, 414, 191, 5, +-60, -416, -254, -481, -200, -132, 68, 286, +225, 392, 169, 183, -23, -69, -191, -112, +-153, -27, 0, 43, 149, 45, 152, -40, +-5, -150, -197, -207, -230, -135, -27, 55, +257, 267, 395, 323, 145, 143, -250, -170, +-422, -324, -200, -182, 194, 118, 325, 250, +110, 62, -177, -175, -237, -208, -54, 36, +168, 240, 184, 175, 41, -73, -82, -266, +-73, -175, 23, 87, 97, 273, 44, 166, +-105, -89, -234, -260, -222, -167, 43, 77, +343, 239, 376, 238, 64, 11, -303, -228, +-328, -317, -13, -135, 253, 155, 198, 314, +-21, 221, -179, -94, -216, -312, -138, -229, +23, 116, 220, 342, 283, 239, 88, -98, +-140, -338, -183, -222, 3, 81, 183, 255, +63, 122, -251, -118, -357, -177, -55, -10, +348, 149, 424, 142, 43, 0, -335, -139, +-327, -144, 17, -38, 304, 102, 242, 198, +19, 175, -166, -9, -220, -268, -134, -355, +35, -101, 188, 245, 143, 347, -79, 119, +-206, -195, -121, -265, 146, -52, 317, 256, +253, 334, -30, 77, -319, -250, -351, -362, +-116, -223, 167, 53, 244, 232, 126, 196, +-104, -5, -205, -132, -65, -18, 202, 151, +307, 165, 96, 19, -218, -116, -298, -171, +-88, -134, 146, -68, 177, -5, -2, 49, +-184, 118, -155, 195, 32, 123, 140, -55, +146, -200, 93, -163, 36, 20, 8, 171, +-56, 142, -109, -48, -102, -183, -90, -123, +-75, 83, -12, 201, 86, 103, 152, -135, +98, -277, -34, -148, -35, 179, 89, 395, +128, 254, 4, -121, -182, -375, -228, -279, +-101, 22, 29, 278, 87, 241, 60, -38, +32, -244, 60, -212, 108, 13, 91, 199, +2, 227, -76, 109, -86, -87, -29, -214, +-31, -176, -102, 12, -93, 163, 16, 145, +138, -19, 144, -162, 12, -144, -49, 24, +4, 193, 44, 166, 19, -15, -34, -163, +-82, -121, -38, 66, 37, 153, 22, 79, +-53, -109, -125, -250, -55, -175, 105, 69, +187, 289, 137, 288, -12, 77, -145, -162, +-110, -247, 54, -136, 139, 47, -14, 126, +-188, 38, -157, -104, 25, -122, 143, 14, +104, 174, 18, 216, -27, 87, -16, -91, +-8, -178, 20, -109, 30, -6, 42, 22, +18, -23, -72, -58, -143, -4, -114, 86, +-3, 133, 117, 94, 163, 42, 108, -12, +7, -81, -84, -165, -95, -173, -70, -35, +4, 115, 100, 170, 104, 104, -15, -4, +-146, -70, -123, -77, -17, -42, 76, 9, +137, 59, 108, 95, -13, 43, -168, -92, +-117, -159, 146, -71, 270, 74, 79, 114, +-235, 51, -363, -2, -193, -3, 167, 3, +358, -15, 238, -40, -47, -40, -222, 2, +-123, 43, 1, 28, 56, -53, 67, -89, +48, -30, -1, 78, -47, 143, -50, 96, +-39, -11, 7, -131, 32, -158, 30, -75, +0, 52, 4, 147, 56, 107, 68, -15, +-23, -115, -97, -106, -52, 13, 27, 108, +77, 108, 18, 14, -95, -88, -116, -109, +-33, -58, 110, 9, 218, 32, 140, 78, +-46, 96, -214, 39, -203, -64, 38, -142, +207, -76, 105, 66, -91, 158, -155, 81, +-46, -77, 51, -165, 68, -84, 44, 90, +17, 143, 26, 52, 24, -80, 27, -105, +-15, -20, -32, 83, -50, 94, -121, 11, +-135, -96, 5, -124, 197, -58, 216, 46, +63, 118, -96, 115, -96, 51, -18, -59, +34, -99, 19, -48, -56, 65, -101, 86, +-64, -50, 33, -208, 113, -192, 93, 42, +-20, 280, -85, 309, -19, 90, 109, -163, +104, -235, -30, -72, -127, 91, -88, 71, +-5, -101, 12, -211, 2, -110, 13, 102, +70, 285, 113, 300, 85, 103, -49, -181, +-170, -333, -126, -234, 52, 49, 198, 259, +126, 188, -98, -89, -229, -288, -107, -191, +163, 124, 262, 334, 52, 239, -223, -55, +-237, -242, 2, -131, 200, 76, 187, 121, +10, -52, -104, -223, -63, -168, 23, 81, +58, 308, -9, 271, -87, 22, -93, -197, +-60, -203, 4, -59, 85, 52, 98, 53, +59, -2, 15, -12, 11, 5, 31, 26, +18, 32, -56, -1, -127, -32, -131, -32, +-24, 32, 110, 115, 107, 93, 13, -75, +-16, -260, 54, -238, 77, 40, 12, 322, +-69, 315, -59, 17, 26, -269, 47, -247, +-53, 37, -190, 242, -183, 148, 27, -99, +224, -215, 203, -86, 58, 92, -28, 130, +1, 28, -5, -70, -89, -26, -132, 47, +-90, 56, 0, -3, 71, -50, 121, -22, +114, 16, 17, 26, -113, 12, -157, -11, +-7, -57, 171, -85, 156, -70, -51, -17, +-188, 83, -88, 174, 96, 153, 157, 20, +18, -113, -131, -154, -145, -104, -10, 11, +146, 89, 157, 77, 48, -48, -70, -168, +-72, -110, -2, 96, 46, 280, 11, 229, +-74, -28, -97, -257, -23, -214, 51, 35, +57, 207, 31, 121, 16, -155, 27, -311, +-12, -174, -6, 152, 20, 368, 2, 264, +-23, -27, -10, -205, 4, -160, -27, 1, +-35, 59, 6, -19, 64, -133, 37, -114, +26, 68, 41, 206, -10, 193, -69, 12, +-62, -136, -3, -167, 17, -83, -2, 37, +-18, 113, -22, 105, -1, 0, 59, -73, +116, -81, 76, -18, -42, 46, -92, 19, +-51, -54, 33, -66, 51, 19, -41, 93, +-91, 61, 42, 12, 198, 24, 121, 53, +-131, -17, -245, -188, -71, -269, 132, -104, +131, 229, 3, 399, -77, 198, -37, -169, +98, -328, 108, -156, -58, 153, -194, 260, +-92, 85, 132, -176, 167, -274, 22, -119, +-97, 120, -40, 242, 51, 170, 69, -1, +16, -126, -66, -108, -75, 5, -3, 79, +52, 61, 29, -25, -53, -106, -139, -139, +-104, -90, 41, 47, 212, 174, 221, 193, +31, 86, -118, -45, -94, -74, -13, -45, +23, -30, -2, -84, -45, -180, -31, -155, +-14, 25, 2, 229, -1, 271, 59, 110, +195, -78, 192, -137, -24, -71, -239, -8, +-220, -2, -63, -49, 51, -74, 121, -7, +108, 55, 1, 74, -115, 24, -90, -33, +72, -36, 174, 8, 135, 68, 30, 67, +-42, 32, -90, -29, -58, -81, -6, -112, +-38, -103, -104, -40, -107, 82, 18, 160, +155, 136, 196, 28, 116, -110, -42, -140, +-170, -46, -165, 73, -6, 99, 161, 3, +166, -81, 21, -46, -171, 36, -192, 79, +-18, 37, 115, -46, 118, -120, 31, -111, +10, -20, 78, 92, 83, 169, -18, 141, +-104, 19, -95, -129, -3, -134, 47, -14, +-65, 88, -163, 10, -94, -183, 89, -220, +227, -15, 186, 290, 36, 391, -74, 147, +-81, -182, -10, -283, 40, -137, -13, 59, +-107, 71, -54, -50, 77, -136, 91, -56, +-19, 125, -121, 217, -40, 149, 136, -36, +181, -143, 78, -141, -80, -53, -165, 50, +-112, 112, -38, 103, 9, -15, 56, -147, +79, -194, 40, -80, -12, 133, -5, 254, +72, 195, 109, -15, 6, -176, -114, -159, +-124, -35, 3, 77, 106, 70, 71, -29, +-62, -97, -133, -62, -70, 17, 29, 105, +135, 145, 157, 91, 39, -35, -135, -150, +-186, -124, -13, -17, 184, 55, 132, 29, +-60, -13, -149, 7, -71, 56, 62, 71, +114, -4, 110, -87, 65, -73, -29, 33, +-148, 89, -146, 25, 3, -72, 152, -80, +114, 45, -73, 140, -190, 62, -109, -130, +91, -237, 194, -110, 137, 159, -28, 322, +-139, 215, -77, -73, 27, -289, 78, -243, +75, 4, 5, 200, -77, 152, -121, -49, +-14, -199, 179, -136, 194, 95, -45, 255, +-238, 224, -139, -2, 115, -213, 231, -239, +63, -71, -178, 104, -228, 125, -30, -5, +176, -140, 165, -92, -23, 75, -110, 221, +-16, 196, 79, 22, 86, -155, 18, -199, +-10, -105, 0, 33, 12, 88, -47, 14, +-105, -54, -107, -47, 2, 43, 156, 132, +127, 147, -1, 50, -110, -102, -102, -186, +9, -142, 95, -15, 64, 135, 0, 171, +-3, 65, 22, -96, 2, -194, -80, -91, +-105, 88, -28, 169, 99, 54, 165, -97, +127, -98, -2, 71, -77, 198, -31, 119, +12, -95, -81, -294, -206, -260, -141, -38, +79, 193, 231, 263, 185, 148, 42, -16, +-89, -90, -138, -47, -61, 22, 28, 8, +65, -82, 63, -140, 40, -92, 9, 54, +-64, 129, -67, 82, 16, -18, 115, -31, +123, 64, 3, 124, -148, 28, -204, -150, +-43, -237, 178, -139, 225, 109, 27, 272, +-218, 195, -278, -80, -72, -286, 257, -194, +392, 114, 172, 314, -205, 173, -335, -154, +-106, -327, 169, -140, 215, 201, 50, 311, +-179, 71, -213, -253, 5, -298, 277, -42, +284, 233, -23, 260, -281, 55, -251, -123, +-4, -144, 161, -37, 139, 41, 2, 20, +-133, -4, -127, -22, 14, -67, 182, -77, +213, 10, 52, 181, -161, 274, -191, 134, +23, -186, 229, -400, 169, -257, -112, 124, +-288, 343, -177, 152, 75, -193, 247, -275, +184, 26, -42, 377, -242, 354, -204, -64, +85, -459, 324, -399, 266, 28, -35, 369, +-315, 317, -316, -54, -85, -364, 165, -296, +282, 64, 217, 406, 66, 411, -124, 73, +-207, -312, -106, -447, 92, -241, 179, 125, +39, 349, -150, 236, -154, -64, 20, -257, +121, -156, 55, 88, -93, 238, -102, 143, +28, -65, 121, -177, 92, -117, 4, 31, +-21, 71, 1, 14, 0, -57, -21, -22, +-11, 60, 7, 96, -6, 29, -43, -77, +-14, -75, 48, 10, 94, 77, 83, 32, +-20, -88, -127, -144, -143, -43, -27, 136, +103, 227, 98, 97, 26, -125, -18, -206, +-41, -88, -56, 72, -36, 100, 62, 6, +152, -100, 116, -61, -29, 68, -147, 147, +-146, 90, 38, -18, 226, -78, 203, -64, +-44, -54, -313, -84, -314, -63, -77, 39, +234, 168, 359, 175, 188, 11, -131, -179, +-314, -181, -200, -5, 90, 166, 280, 147, +210, -26, -41, -143, -266, -101, -186, 53, +134, 144, 363, 92, 218, -57, -187, -158, +-454, -154, -317, -69, 115, 64, 427, 211, +376, 256, 17, 115, -325, -126, -355, -295, +-75, -208, 216, 25, 267, 171, 51, 102, +-212, -75, -217, -110, 20, 47, 281, 220, +331, 190, 79, -16, -236, -220, -360, -253, +-208, -110, 94, 39, 255, 127, 203, 149, +41, 130, -107, 69, -165, -46, -105, -148, +7, -149, 100, -32, 104, 110, 28, 139, +-26, 33, -47, -106, -36, -135, -10, -10, +26, 111, 31, 111, 10, -21, -5, -129, +46, -85, 125, 56, 121, 136, -10, 72, +-162, -80, -207, -174, -114, -82, 55, 91, +121, 187, 94, 93, 36, -96, 14, -184, +30, -83, 16, 112, -28, 207, -61, 95, +-66, -113, -68, -204, -30, -130, 53, 26, +165, 109, 185, 101, 45, 42, -149, -20, +-195, -45, -43, -27, 114, 36, 112, 111, +-3, 81, -70, -100, -39, -271, 12, -233, +37, 60, 43, 325, -16, 305, -100, 13, +-119, -243, -25, -208, 139, 35, 222, 195, +108, 79, -115, -146, -205, -225, -49, -67, +180, 132, 184, 180, -35, 86, -194, -6, +-149, -18, 27, 8, 144, -11, 93, -70, +-35, -98, -120, -61, -86, -8, 18, 13, +92, 56, 102, 115, 94, 156, 22, 72, +-129, -122, -201, -260, -104, -189, 116, 55, +231, 234, 128, 184, -50, -13, -102, -118, +-26, -58, 76, 55, 70, 58, -51, -53, +-129, -136, -127, -88, -47, 34, 54, 106, +104, 105, 79, 77, 39, 62, 16, 21, +9, -76, -22, -180, -105, -202, -120, -99, +-21, 67, 131, 189, 215, 192, 136, 98, +-37, 0, -143, -62, -98, -57, -7, -30, +9, -58, -60, -103, -92, -111, -6, -22, +99, 118, 158, 169, 108, 100, -31, -25, +-158, -85, -149, -38, 11, 52, 154, 59, +141, -66, -24, -161, -154, -121, -121, 19, +61, 123, 203, 124, 167, 62, -23, 5, +-164, -12, -115, -4, 16, -3, 96, -17, +28, -52, -113, -104, -172, -122, -63, -52, +130, 125, 256, 251, 153, 192, -70, -39, +-178, -251, -96, -232, 87, -23, 126, 152, +-38, 122, -191, -15, -110, -65, 106, 24, +219, 112, 155, 60, 43, -82, -33, -139, +-120, -46, -193, 79, -148, 83, -32, -40, +78, -102, 144, -12, 120, 139, 29, 149, +-47, -19, -20, -192, 29, -185, -6, 3, +-86, 161, -47, 144, 53, -15, 68, -128, +10, -72, -58, 65, -30, 128, 60, 70, +115, -16, 74, -41, -30, -42, -93, -57, +-71, -100, -37, -116, -19, -48, -5, 73, +10, 190, 16, 205, 27, 126, 55, -31, +38, -188, -32, -235, -79, -150, -45, 11, +36, 112, 114, 91, 101, 30, 20, 49, +-55, 141, -48, 198, 9, 75, 13, -177, +-15, -369, -26, -321, -34, -60, -80, 185, +-62, 257, 55, 141, 164, 11, 131, -13, +-30, 38, -182, 57, -180, -36, -15, -168, +162, -206, 184, -71, 21, 160, -79, 309, +-29, 222, 74, -82, 84, -354, -7, -351, +-99, -58, -110, 287, -28, 376, 49, 147, +59, -179, -28, -311, -85, -122, -40, 162, +51, 263, 104, 101, 43, -165, -67, -280, +-98, -146, -16, 136, 93, 299, 119, 190, +59, -85, -29, -261, -79, -153, -62, 112, +34, 221, 118, 27, 53, -260, -83, -293, +-144, 2, -64, 345, 38, 382, 76, 88, +48, -220, -9, -282, -49, -77, -35, 121, +37, 90, 62, -110, -11, -237, -79, -107, +-38, 177, 40, 381, 71, 317, 61, 20, +62, -281, 42, -358, -13, -195, -56, 34, +-49, 127, -6, 70, -30, 3, -61, 40, +-52, 168, 13, 203, 86, 66, 43, -150, +-42, -260, -39, -189, 32, -50, 50, 20, +-26, 23, -100, 79, -25, 206, 138, 272, +177, 143, 56, -144, -130, -368, -198, -333, +-47, -68, 140, 237, 182, 345, 49, 219, +-116, -20, -132, -217, -43, -262, 4, -183, +-7, -32, -38, 99, -29, 146, 53, 134, +124, 108, 125, 105, 65, 91, -44, -1, +-149, -140, -163, -247, -64, -232, 114, -113, +214, 37, 145, 164, -6, 225, -141, 223, +-179, 117, -71, -57, 95, -219, 141, -270, +20, -180, -138, -28, -143, 107, 21, 178, +171, 207, 178, 199, 59, 135, -92, -7, +-161, -182, -149, -281, -85, -227, 6, -69, +104, 64, 170, 109, 118, 104, 20, 123, +-73, 122, -93, 50, -22, -105, 68, -231, +68, -192, -42, -28, -108, 142, -39, 202, +92, 179, 96, 145, -7, 94, -93, -14, +-128, -185, -82, -308, -4, -271, 20, -84, +-8, 111, -36, 172, 40, 120, 202, 50, +273, 30, 165, 55, -40, 56, -211, 17, +-220, -45, -81, -80, 37, -59, 61, 10, +-27, 74, -131, 38, -120, -75, -14, -162, +107, -114, 198, 73, 178, 220, 84, 192, +-33, 10, -166, -172, -217, -197, -149, -98, +18, -3, 159, 30, 224, 33, 164, 106, +75, 216, -17, 226, -96, 71, -89, -165, +-122, -282, -186, -210, -208, -68, -65, 16, +182, 24, 309, 44, 203, 111, -14, 159, +-135, 111, -109, -7, -10, -84, 35, -89, +-10, -49, -56, -32, -10, -21, 102, 32, +157, 93, 80, 109, -57, 12, -170, -109, +-167, -147, -77, -80, 24, 38, 67, 81, +50, 41, 62, -11, 114, -38, 121, -8, +12, 37, -142, 81, -199, 112, -62, 77, +126, 2, 168, -92, 23, -125, -127, -100, +-106, -66, 32, -56, 102, -58, 42, 0, +-45, 93, -91, 160, -30, 119, 35, 5, +62, -71, 67, -58, 72, 19, 60, 61, +9, 44, -46, 17, -64, 0, -46, 1, +-91, -21, -114, -100, -57, -173, 23, -191, +79, -118, 82, 15, 41, 153, 29, 259, +53, 259, 88, 155, 79, 2, -33, -112, +-150, -108, -157, -42, -51, -16, 72, -71, +126, -151, 65, -132, 2, 19, -25, 183, +-50, 203, -111, 53, -158, -165, -60, -267, +118, -175, 175, 13, 67, 174, -54, 223, +-33, 201, 115, 166, 202, 95, 112, -3, +-107, -116, -261, -200, -231, -225, -64, -220, +78, -154, 112, -13, 92, 155, 49, 250, +21, 184, -14, 18, -50, -105, -81, -96, +-81, 6, -15, 76, 77, 78, 143, 56, +128, 35, 46, 21, -45, -19, -83, -88, +-53, -152, -42, -169, -87, -112, -122, 0, +-30, 111, 118, 147, 148, 97, 79, 9, +1, -5, 11, 83, 27, 155, -49, 81, +-140, -131, -143, -300, -25, -245, 133, -12, +188, 219, 95, 262, -18, 118, -57, -74, +-44, -215, -90, -234, -189, -136, -162, 32, +57, 201, 282, 261, 313, 189, 135, 68, +-90, -14, -172, -36, -143, -93, -87, -217, +-35, -321, 15, -263, 60, -19, 34, 246, +-22, 332, -25, 195, 29, 7, 68, -73, +46, -10, -14, 70, -77, 46, -51, -78, +45, -192, 153, -165, 156, -6, 13, 166, +-130, 212, -182, 73, -98, -155, 21, -295, +29, -243, -103, -37, -159, 154, 30, 235, +339, 240, 421, 217, 80, 159, -363, 2, +-475, -210, -134, -339, 324, -295, 415, -98, +90, 94, -243, 145, -281, 89, -65, 31, +144, 48, 189, 117, 75, 123, -136, 20, +-274, -140, -177, -217, 85, -113, 271, 104, +240, 247, 43, 166, -114, -69, -114, -255, +-15, -207, 9, 5, -119, 134, -229, 55, +-91, -117, 227, -99, 425, 152, 295, 397, +-77, 369, -372, 12, -364, -372, -99, -467, +124, -224, 143, 106, 17, 202, -71, 57, +-44, -103, 87, -76, 241, 103, 221, 194, +9, 78, -255, -117, -319, -154, -140, 31, +94, 256, 228, 295, 188, 112, 4, -138, +-150, -310, -153, -341, -37, -263, 65, -109, +54, 78, -29, 188, -58, 179, 37, 96, +187, 67, 253, 151, 62, 225, -251, 163, +-407, -62, -245, -297, 110, -315, 318, -110, +223, 112, -48, 127, -228, -66, -171, -232, +61, -183, 204, 55, 156, 265, -16, 259, +-134, 98, -76, -27, 91, 7, 158, 125, +51, 127, -152, -58, -284, -316, -198, -416, +-12, -249, 171, 75, 228, 306, 160, 289, +55, 92, -45, -107, -149, -127, -242, 9, +-200, 137, -18, 139, 212, 15, 314, -82, +251, -66, 113, -27, -70, -53, -239, -163, +-306, -232, -220, -129, -46, 111, 89, 320, +156, 330, 153, 155, 105, -66, 6, -197, +-113, -187, -173, -96, -120, 9, 42, 83, +150, 113, 125, 93, 27, -3, -14, -124, +10, -177, 1, -117, -51, 11, -83, 105, +-41, 112, 45, 58, 51, 36, -67, 82, +-164, 119, -122, 51, 41, -139, 127, -300, +79, -266, 7, -22, -8, 267, 1, 358, +-1, 200, 15, -60, 1, -197, -15, -130, +-35, -16, -15, 11, 29, -62, 24, -134, +9, -107, -51, -15, -130, 78, -141, 144, +-47, 181, 77, 193, 134, 130, 121, -2, +85, -130, 61, -161, -19, -101, -140, -45, +-202, -68, -143, -148, 33, -147, 149, -21, +96, 165, -38, 276, -109, 207, -76, 23, +-15, -136, 41, -147, 111, 3, 194, 184, +175, 248, -16, 107, -254, -180, -322, -401, +-142, -395, 103, -158, 166, 118, 51, 244, +-77, 188, -89, 73, -11, 57, 50, 160, +57, 226, 26, 123, 34, -100, 86, -248, +94, -209, -5, -93, -155, -79, -224, -198, +-162, -273, -27, -131, 101, 197, 155, 464, +108, 468, -13, 253, -95, 0, -77, -126, +18, -129, 107, -126, 126, -176, 84, -228, +-52, -191, -198, -76, -257, 40, -200, 94, +-54, 67, 46, 52, 69, 95, 107, 164, +186, 206, 232, 148, 172, 34, 31, -84, +-137, -159, -254, -181, -257, -175, -135, -116, +59, -30, 138, 35, 41, 22, -120, -38, +-160, -52, -22, 69, 148, 282, 176, 395, +49, 271, -89, -30, -140, -305, -44, -384, +90, -283, 135, -125, 81, -2, -13, 73, +-87, 152, -128, 192, -142, 154, -125, 46, +-120, -66, -135, -68, -34, 25, 237, 118, +478, 134, 382, 51, -13, -66, -371, -177, +-410, -255, -216, -262, -51, -188, -36, -33, +-81, 147, 1, 273, 194, 308, 324, 251, +232, 136, 14, -4, -132, -122, -121, -164, +-11, -110, 31, -29, -39, -42, -155, -142, +-261, -243, -253, -235, -123, -79, 91, 141, +285, 332, 306, 396, 133, 318, -92, 141, +-162, -72, -76, -241, 74, -309, 135, -241, +50, -61, -118, 114, -261, 158, -284, 18, +-185, -187, -21, -242, 125, -50, 232, 264, +229, 428, 144, 292, 51, -37, -36, -280, +-108, -257, -151, -42, -151, 140, -99, 134, +-57, -23, -76, -186, -75, -237, -43, -154, +33, 6, 114, 139, 152, 193, 155, 188, +103, 174, -17, 148, -150, 72, -179, -74, +-81, -243, 46, -317, 38, -228, -115, -14, +-219, 174, -144, 210, 54, 100, 196, -63, +160, -157, 29, -104, -60, 50, -44, 200, +-11, 231, 5, 116, 8, -61, -18, -183, +-86, -154, -186, -35, -171, 52, -44, 22, +80, -89, 110, -137, 70, -45, 32, 117, +43, 191, 72, 115, 61, -30, 2, -99, +-104, -38, -201, 54, -222, 70, -139, 10, +-11, -56, 81, -53, 69, -21, -2, -22, +-47, -77, -22, -144, 65, -105, 164, 76, +206, 294, 100, 358, -97, 185, -262, -115, +-264, -317, -157, -269, -104, -59, -77, 85, +-21, 45, 99, -93, 234, -135, 244, -5, +100, 171, -101, 229, -189, 114, -117, -38, +9, -79, 36, -9, -33, 59, -123, 36, +-194, -43, -146, -101, 4, -88, 172, -49, +220, -55, 96, -110, -87, -141, -173, -52, +-88, 137, 72, 307, 156, 340, 77, 188, +-76, -49, -189, -233, -232, -266, -208, -138, +-90, 28, 87, 110, 208, 52, 176, -96, +-3, -184, -160, -115, -159, 89, -1, 269, +174, 281, 180, 115, 7, -112, -197, -228, +-281, -175, -192, -21, -7, 104, 128, 121, +130, 45, 45, -46, -27, -84, -47, -72, +-56, -44, -61, -11, -65, 33, -66, 78, +-63, 99, -41, 69, 25, -1, 72, -75, +63, -92, 20, -34, -25, 69, -48, 131, +-42, 64, -36, -104, -30, -241, -16, -196, +6, 39, -23, 279, -130, 291, -207, 48, +-157, -246, -7, -339, 104, -143, 132, 182, +102, 371, 96, 283, 102, 1, 62, -256, +-42, -316, -205, -163, -294, 84, -227, 230, +-22, 170, 145, -33, 133, -202, -64, -180, +-262, 1, -216, 162, 53, 157, 314, 3, +337, -123, 116, -86, -159, 83, -294, 210, +-210, 151, 7, -40, 129, -193, 21, -187, +-185, -67, -265, 36, -140, 37, 83, -28, +214, -62, 175, -18, 29, 79, -98, 147, +-101, 133, -27, 38, 19, -71, -22, -103, +-142, -39, -223, 36, -168, 32, 29, -48, +248, -111, 282, -69, 97, 45, -155, 136, +-263, 134, -188, 57, -42, -37, 50, -116, +12, -144, -98, -112, -179, -23, -125, 77, +28, 114, 197, 85, 240, 55, 125, 59, +-47, 65, -151, 7, -101, -98, -42, -167, +-82, -124, -171, 2, -143, 87, -14, 64, +46, -29, -43, -84, -157, -29, -126, 93, +62, 163, 264, 116, 286, -6, 137, -107, +-90, -106, -240, -41, -244, 2, -129, -1, +24, -20, 38, -17, -118, -28, -279, -65, +-226, -59, 62, 46, 354, 220, 392, 299, +145, 153, -156, -141, -310, -329, -250, -244, +-118, 13, -41, 190, -21, 135, -22, -71, +9, -207, 33, -148, 47, 40, 23, 177, +-23, 170, -39, 88, -11, 43, 49, 59, +73, 59, -3, -17, -188, -122, -350, -164, +-335, -125, -96, -79, 176, -84, 261, -72, +144, 22, -15, 158, -46, 223, 50, 152, +141, 37, 76, -9, -120, 11, -289, 12, +-282, -51, -161, -120, -50, -116, -24, -67, +-61, -63, -47, -118, 37, -137, 156, -22, +199, 177, 147, 296, 76, 236, 20, 72, +-30, -36, -119, -6, -203, 70, -258, 37, +-285, -149, -286, -352, -214, -378, -43, -178, +172, 96, 350, 233, 381, 158, 289, 4, +114, -28, -62, 138, -207, 368, -325, 422, +-347, 195, -254, -189, -91, -464, 4, -463, +-5, -244, -34, -29, 4, 2, 71, -107, +106, -156, 116, 2, 131, 295, 158, 507, +72, 510, -131, 345, -320, 104, -321, -159, +-154, -410, -17, -575, -13, -526, -71, -237, +-72, 124, -21, 308, 50, 218, 138, 10, +230, -58, 216, 125, 24, 393, -233, 471, +-354, 228, -232, -185, -30, -468, 26, -474, +-64, -295, -126, -126, -15, -50, 163, 6, +207, 140, 76, 306, -87, 366, -142, 259, +-99, 70, -83, -62, -148, -84, -201, -58, +-123, -81, 54, -172, 189, -256, 219, -236, +107, -98, -85, 80, -251, 194, -259, 190, +-84, 100, 106, 32, 155, 80, 45, 203, +-118, 243, -246, 79, -225, -225, -97, -461, +69, -450, 144, -172, 85, 172, -3, 336, +-62, 213, 6, -56, 118, -204, 128, -58, +-46, 288, -271, 513, -349, 364, -246, -106, +-94, -557, -11, -672, 29, -386, 75, 77, +181, 391, 253, 386, 173, 149, -49, -91, +-245, -157, -265, -12, -155, 217, -38, 333, +2, 207, -44, -127, -111, -451, -106, -534, +-4, -299, 117, 101, 149, 375, 64, 342, +-60, 87, -135, -118, -83, -93, 34, 98, +51, 212, -105, 104, -304, -139, -308, -295, +-102, -217, 155, 21, 286, 208, 235, 187, +58, -17, -107, -222, -146, -241, -106, -33, +-114, 255, -177, 381, -132, 240, 13, -51, +125, -269, 51, -283, -169, -150, -292, -24, +-153, 7, 188, -7, 400, 34, 273, 131, +-62, 196, -285, 169, -280, 70, -141, -19, +-22, -39, 1, -40, -45, -110, -127, -250, +-134, -333, -41, -227, 108, 69, 196, 381, +141, 474, -14, 270, -144, -69, -113, -281, +-3, -224, -2, -1, -168, 170, -285, 133, +-187, -78, 44, -266, 209, -279, 180, -114, +35, 87, -136, 190, -198, 177, -97, 133, +78, 142, 199, 171, 138, 126, -77, -49, +-315, -274, -387, -397, -218, -331, 30, -119, +143, 92, 110, 187, 90, 184, 140, 171, +148, 175, 9, 140, -161, 34, -231, -60, +-179, -48, -85, 33, -45, 30, -65, -172, +-114, -438, -120, -485, -29, -177, 114, 285, +214, 539, 208, 421, 65, 87, -130, -148, +-260, -117, -205, 87, 17, 234, 160, 159, +66, -120, -202, -430, -387, -563, -321, -412, +-80, -56, 169, 287, 297, 440, 289, 376, +187, 221, 49, 107, -124, 83, -282, 84, +-335, 7, -233, -156, -33, -335, 83, -440, +50, -409, -106, -231, -215, 33, -123, 272, +148, 396, 388, 383, 369, 276, 110, 150, +-196, 59, -355, 4, -350, -60, -234, -163, +-122, -277, -83, -346, -69, -342, 9, -251, +155, -65, 219, 183, 156, 389, 31, 433, +-40, 271, -17, 23, 31, -86, -1, 19, +-153, 173, -320, 130, -355, -161, -249, -495, +-99, -600, 49, -372, 181, 54, 270, 410, +261, 500, 135, 328, -20, 52, -147, -131, +-184, -119, -129, 39, -89, 172, -117, 143, +-187, -49, -206, -299, -116, -460, 25, -425, +161, -157, 237, 250, 201, 564, 79, 560, +-68, 220, -181, -195, -219, -368, -186, -191, +-119, 127, -47, 263, 24, 94, 58, -235, +7, -449, -120, -384, -155, -97, -20, 223, +164, 399, 238, 388, 130, 249, -45, 73, +-203, -86, -234, -192, -164, -215, -94, -161, +-94, -67, -130, -10, -81, -44, 20, -116, +119, -112, 193, 30, 239, 226, 184, 333, +11, 282, -201, 113, -330, -70, -319, -187, +-201, -214, -23, -184, 91, -133, 83, -84, +1, -41, -84, 29, -98, 110, -34, 148, +83, 121, 178, 68, 161, 55, 77, 94, +-20, 124, -141, 76, -267, -44, -344, -178, +-295, -281, -122, -308, 63, -237, 184, -53, +191, 192, 105, 347, 23, 321, 2, 139, +16, -54, 0, -95, -50, 20, -118, 150, +-181, 129, -209, -107, -156, -394, -70, -495, +-25, -307, -4, 53, 40, 329, 149, 389, +241, 296, 251, 202, 101, 147, -181, 30, +-416, -195, -431, -396, -216, -382, 39, -150, +172, 96, 149, 154, 59, 33, -22, -59, +-52, 27, -48, 216, -8, 318, 53, 214, +70, -15, 32, -196, -72, -223, -174, -115, +-241, -13, -248, -27, -162, -146, -6, -225, +168, -133, 294, 123, 297, 397, 128, 456, +-142, 239, -370, -113, -382, -363, -174, -336, +86, -75, 266, 206, 237, 277, 10, 86, +-289, -218, -436, -400, -277, -311, 77, -7, +392, 343, 452, 519, 221, 389, -149, 37, +-392, -319, -356, -433, -119, -238, 69, 84, +61, 267, -55, 161, -145, -115, -123, -311, +-9, -259, 117, 17, 180, 318, 172, 446, +104, 316, -6, 10, -137, -285, -252, -386, +-285, -226, -206, 53, -52, 211, 84, 117, +131, -125, 57, -277, -59, -180, -92, 131, +10, 410, 185, 419, 237, 130, 80, -244, +-177, -402, -345, -246, -324, 61, -141, 231, +80, 144, 171, -62, 67, -165, -127, -94, +-200, 30, -82, 69, 137, 23, 278, -3, +223, 49, 30, 137, -154, 147, -211, 59, +-191, -54, -186, -127, -195, -147, -146, -143, +-28, -107, 116, -46, 212, 29, 200, 76, +92, 67, -48, 47, -76, 72, 7, 173, +55, 267, -19, 213, -184, -27, -335, -338, +-354, -523, -176, -448, 116, -141, 320, 221, +275, 428, 89, 412, -26, 214, -34, -27, +-22, -168, -46, -188, -112, -115, -202, -28, +-227, 6, -108, -10, 75, -35, 152, -16, +79, 71, -16, 185, -49, 207, -50, 54, +-41, -224, -57, -449, -84, -424, -57, -83, +53, 402, 179, 725, 167, 656, -18, 197, +-246, -395, -359, -793, -283, -796, -59, -394, +154, 173, 236, 603, 194, 736, 95, 549, +4, 176, -76, -202, -147, -487, -166, -598, +-154, -479, -99, -146, -6, 270, 68, 549, +81, 538, 7, 257, -79, -148, -89, -467, +-7, -581, 109, -435, 161, -10, 75, 532, +-70, 917, -148, 838, -148, 206, -107, -680, +-120, -1279, -162, -1172, -131, -374, -7, 642, +197, 1254, 340, 1110, 255, 359, 1, -496, +-217, -919, -263, -707, -154, -105, -17, 462, +48, 631, 38, 356, -20, -120, -115, -501, +-170, -601, -117, -382, 52, 56, 235, 508, +231, 738, 5, 558, -242, 34, -294, -506, +-75, -728, 235, -477, 362, 70, 190, 517, +-175, 573, -476, 235, -511, -268, -282, -589, +90, -525, 424, -124, 533, 359, 400, 622, +52, 507, -340, 104, -573, -324, -548, -528, +-225, -392, 227, -36, 533, 317, 506, 440, +163, 255, -251, -101, -452, -418, -402, -487, +-166, -234, 142, 176, 338, 518, 301, 588, +61, 306, -191, -182, -300, -595, -233, -647, +-81, -285, 50, 275, 124, 642, 138, 528, +119, 32, 61, -446, -42, -521, -119, -160, +-111, 289, -88, 457, -101, 219, -114, -193, +-54, -385, 105, -265, 188, 6, 93, 226, +-96, 259, -221, 151, -153, -4, 49, -165, +247, -248, 269, -175, 51, 31, -259, 269, +-418, 315, -302, 92, 17, -211, 319, -351, +394, -199, 177, 125, -220, 343, -475, 235, +-392, -120, -47, -402, 369, -346, 567, 76, +371, 569, -122, 671, -596, 240, -691, -470, +-319, -976, 245, -814, 609, -62, 553, 794, +134, 1159, -348, 738, -580, -187, -445, -991, +-15, -1071, 456, -384, 620, 546, 338, 1048, +-259, 756, -781, -85, -793, -864, -267, -1005, +464, -421, 949, 443, 804, 1015, 103, 889, +-654, 149, -971, -681, -638, -1000, 76, -607, +655, 198, 781, 864, 367, 876, -286, 237, +-715, -587, -688, -1033, -246, -761, 296, 71, +599, 918, 528, 1162, 169, 624, -219, -334, +-378, -1024, -273, -946, -68, -239, 21, 529, +-52, 777, -122, 349, -69, -309, 74, -644, +208, -393, 253, 231, 161, 702, -55, 676, +-265, 171, -316, -439, -141, -736, 148, -550, +309, -24, 169, 437, -197, 502, -483, 168, +-409, -282, 3, -438, 437, -167, 576, 281, +335, 540, -108, 358, -445, -65, -432, -379, +-95, -399, 239, -133, 268, 134, -48, 163, +-411, -32, -433, -247, -98, -243, 340, 50, +614, 425, 514, 586, 82, 360, -382, -107, +-610, -452, -484, -518, -104, -327, 262, -36, +414, 168, 282, 287, -47, 307, -285, 178, +-285, -79, -151, -339, 53, -387, 230, -172, +253, 219, 173, 533, 55, 522, -118, 230, +-269, -220, -309, -580, -174, -596, 67, -277, +189, 214, 149, 539, 18, 415, -128, -73, +-182, -570, -97, -636, 99, -102, 298, 669, +355, 1119, 203, 864, -104, 5, -409, -923, +-531, -1309, -419, -909, -114, -55, 230, 683, +413, 847, 414, 451, 285, -81, 79, -276, +-122, -31, -306, 299, -422, 297, -386, -131, +-200, -630, 144, -708, 514, -192, 626, 600, +383, 1031, -91, 688, -615, -284, -842, -1246, +-591, -1438, -48, -589, 513, 853, 781, 1869, +636, 1716, 302, 457, -57, -1093, -394, -1830, +-631, -1422, -755, -303, -631, 706, -121, 1001, +579, 705, 1123, 267, 1144, 42, 460, -19, +-595, -134, -1418, -392, -1484, -648, -631, -555, +702, -22, 1674, 632, 1604, 956, 496, 635, +-964, -163, -1822, -881, -1500, -1033, -250, -477, +1056, 421, 1600, 1029, 1134, 986, 82, 317, +-830, -537, -1133, -986, -785, -822, -115, -188, +456, 445, 674, 656, 516, 432, 134, 32, +-258, -194, -437, -133, -385, 34, -190, 68, +69, -88, 263, -245, 358, -183, 322, 73, +118, 317, -175, 301, -434, -67, -491, -470, +-248, -569, 157, -206, 454, 457, 484, 915, +173, 809, -254, 104, -494, -757, -446, -1142, +-58, -788, 406, 130, 588, 949, 390, 1029, +-106, 363, -577, -566, -650, -1025, -317, -641, +159, 236, 521, 906, 535, 834, 231, 122, +-128, -615, -366, -785, -363, -289, -152, 375, +49, 604, 183, 234, 236, -381, 146, -661, +-44, -319, -257, 356, -374, 753, -231, 494, +147, -198, 516, -697, 576, -514, 213, 228, +-328, 845, -699, 671, -656, -236, -146, -1128, +481, -1179, 779, -239, 481, 956, -233, 1456, +-725, 859, -648, -317, -59, -1161, 613, -1043, +788, -135, 341, 741, -384, 922, -831, 292, +-605, -609, 81, -976, 626, -500, 664, 443, +192, 1066, -398, 812, -601, -75, -336, -831, +161, -847, 487, -195, 337, 453, -52, 523, +-296, 94, -273, -308, -35, -290, 186, 81, +188, 352, 40, 232, -117, -144, -185, -350, +-73, -212, 55, 131, 29, 346, 17, 171, +68, -111, 137, -241, 181, -104, 49, 170, +-208, 166, -397, -137, -357, -442, -46, -396, +325, 116, 446, 691, 235, 821, -74, 355, +-266, -444, -236, -1014, -20, -868, 189, -79, +201, 815, 4, 1180, -254, 647, -395, -471, +-206, -1352, 186, -1254, 451, -165, 430, 1135, +88, 1678, -332, 958, -500, -451, -292, -1476, +147, -1357, 456, -208, 359, 970, -81, 1323, +-442, 621, -432, -584, -68, -1314, 420, -1077, +585, -62, 298, 1069, -231, 1493, -683, 910, +-690, -267, -184, -1240, 493, -1341, 865, -534, +648, 557, -51, 1145, -713, 884, -890, 48, +-443, -752, 339, -988, 798, -525, 667, 281, +83, 871, -557, 865, -753, 295, -414, -446, +198, -843, 628, -643, 566, -86, 131, 452, +-340, 670, -527, 464, -333, 9, 69, -408, +346, -564, 321, -374, 55, 49, -253, 439, +-351, 522, -199, 234, 91, -185, 316, -452, +341, -380, 184, -15, -84, 345, -316, 415, +-403, 129, -299, -309, 19, -531, 453, -288, +636, 272, 286, 727, -336, 652, -793, 12, +-715, -748, -80, -1008, 655, -513, 1014, 375, +655, 1017, -217, 854, -921, 52, -978, -680, +-366, -803, 476, -209, 916, 474, 620, 622, +-117, 199, -659, -433, -618, -632, -120, -270, +390, 266, 537, 534, 264, 318, -127, -60, +-355, -182, -332, 25, -70, 155, 179, -67, +219, -481, 75, -627, -130, -78, -227, 757, +-153, 1036, 42, 357, 248, -768, 343, -1338, +210, -720, -94, 687, -316, 1573, -358, 1155, +-182, -300, 138, -1590, 303, -1525, 206, -229, +-56, 1248, -306, 1656, -335, 627, -87, -835, +275, -1492, 499, -855, 411, 467, -23, 1278, +-498, 877, -619, -247, -234, -1022, 378, -829, +664, 169, 401, 996, -220, 846, -737, -126, +-748, -1052, -205, -1137, 579, -274, 979, 850, +684, 1321, -93, 890, -790, -121, -875, -964, +-319, -1075, 445, -551, 751, 248, 378, 778, +-302, 695, -681, 141, -404, -388, 265, -541, +741, -240, 560, 256, -166, 407, -848, 127, +-879, -262, -118, -374, 862, -26, 1245, 461, +671, 617, -456, 176, -1345, -562, -1334, -967, +-394, -644, 765, 235, 1397, 976, 1065, 1020, +48, 233, -805, -746, -970, -1090, -410, -549, +343, 521, 605, 1220, 273, 931, -268, -178, +-574, -1212, -405, -1302, 150, -397, 611, 833, +609, 1354, 169, 704, -391, -484, -626, -1231, +-372, -922, 180, 258, 596, 1326, 524, 1397, +10, 379, -565, -992, -733, -1699, -401, -1210, +210, 126, 699, 1276, 725, 1379, 290, 447, +-342, -718, -710, -1144, -615, -544, -133, 499, +448, 1066, 717, 694, 531, -208, 6, -842, +-499, -705, -673, -29, -448, 521, -20, 433, +334, -166, 503, -670, 415, -597, 123, 133, +-176, 878, -353, 1082, -322, 568, -70, -418, +215, -1071, 282, -993, 100, -282, -186, 534, +-334, 881, -174, 595, 103, -64, 302, -581, +322, -700, 85, -408, -198, 93, -284, 555, +-139, 743, 87, 541, 236, 65, 205, -481, +-6, -733, -212, -510, -339, -23, -278, 339, +24, 326, 328, 58, 470, -179, 357, -64, +22, 279, -358, 393, -521, 117, -343, -369, +65, -604, 427, -279, 406, 428, 112, 818, +-201, 417, -337, -469, -198, -1129, 68, -845, +258, 248, 204, 1258, -4, 1234, -168, 118, +-125, -1081, 102, -1347, 217, -349, 83, 971, +-208, 1396, -374, 527, -216, -913, 118, -1529, +408, -804, 407, 628, 105, 1496, -242, 1058, +-359, -223, -184, -1179, 110, -982, 318, -49, +207, 789, -132, 774, -400, 16, -343, -546, +47, -513, 403, 25, 456, 431, 192, 263, +-161, -201, -347, -410, -228, -81, 85, 468, +246, 658, 167, 115, -99, -619, -352, -870, +-284, -429, 43, 459, 403, 947, 501, 579, +202, -250, -257, -781, -489, -635, -293, 51, +129, 650, 424, 604, 268, 98, -212, -423, +-492, -522, -279, -128, 275, 316, 684, 479, +524, 194, -161, -346, -768, -672, -715, -524, +-32, 51, 762, 758, 911, 1062, 250, 620, +-640, -289, -1039, -1171, -574, -1333, 360, -471, +1017, 790, 869, 1597, 61, 1225, -719, -178, +-871, -1576, -296, -1872, 458, -700, 793, 1135, +472, 2253, -214, 1709, -712, -113, -677, -1887, +-113, -2295, 469, -997, 707, 938, 533, 2088, +29, 1654, -458, 11, -615, -1538, -346, -1895, +155, -835, 585, 861, 579, 1894, 93, 1501, +-504, 72, -812, -1369, -466, -1775, 324, -840, +929, 544, 893, 1306, 169, 1031, -701, 68, +-1005, -738, -526, -751, 330, -169, 885, 381, +732, 456, 2, 93, -681, -211, -778, -178, +-321, 143, 343, 303, 746, -11, 651, -480, +166, -636, -361, -218, -620, 493, -524, 891, +-139, 517, 318, -244, 641, -718, 603, -565, +136, 155, -461, 675, -825, 545, -634, -120, +105, -776, 878, -772, 1071, -158, 452, 565, +-565, 855, -1210, 474, -912, -249, 117, -684, +1101, -507, 1298, 83, 456, 685, -748, 732, +-1420, 121, -1030, -684, 215, -1137, 1320, -759, +1421, 248, 476, 1189, -754, 1333, -1367, 518, +-909, -710, 176, -1472, 990, -1076, 1028, 87, +274, 1221, -553, 1430, -802, 475, -449, -798, +174, -1490, 532, -1036, 464, 164, 127, 1188, +-71, 1296, -63, 517, -75, -483, -198, -1055, +-413, -841, -326, -221, 140, 420, 653, 691, +752, 531, 233, 273, -543, -132, -949, -464, +-516, -636, 434, -555, 1128, -45, 956, 648, +-47, 1078, -1063, 715, -1264, -265, -467, -1213, +678, -1327, 1234, -336, 784, 990, -222, 1660, +-907, 992, -750, -496, 105, -1616, 852, -1489, +763, -123, 10, 1307, -710, 1644, -775, 627, +-127, -884, 590, -1622, 783, -971, 341, 516, +-387, 1483, -777, 1236, -497, -29, 165, -1302, +718, -1434, 816, -458, 298, 817, -362, 1415, +-747, 904, -674, -253, -81, -1106, 528, -1068, +746, -263, 457, 706, -151, 1039, -633, 598, +-586, -313, -7, -956, 618, -798, 854, -86, +364, 738, -464, 928, -917, 342, -748, -414, +59, -770, 831, -564, 945, 71, 352, 558, +-454, 488, -794, 245, -451, -104, 300, -355, +762, -379, 595, -346, -62, -57, -680, 389, +-686, 674, -143, 531, 523, -135, 788, -858, +365, -944, -368, -235, -779, 728, -483, 1155, +289, 570, 913, -551, 848, -1093, 114, -658, +-605, 375, -863, 1082, -510, 639, 146, -447, +579, -1080, 572, -695, 227, 419, -196, 1215, +-408, 826, -249, -365, 60, -1253, 355, -1091, +498, 106, 318, 1280, -100, 1407, -510, 478, +-692, -827, -387, -1537, 321, -1144, 859, -75, +816, 979, 148, 1374, -737, 862, -985, -120, +-337, -1001, 642, -1179, 1289, -476, 888, 592, +-364, 1269, -1359, 946, -1351, -193, -288, -1314, +1049, -1482, 1570, -499, 876, 888, -304, 1648, +-1063, 1145, -956, -88, -158, -1144, 550, -1265, +758, -446, 461, 469, -43, 908, -338, 662, +-350, 96, -208, -411, -69, -631, 121, -557, +243, -299, 263, 200, 271, 641, 107, 815, +-108, 501, -187, -238, -96, -843, 37, -868, +137, -231, 90, 610, -99, 1001, -180, 552, +-160, -394, 57, -1115, 316, -1015, 367, -64, +328, 955, 105, 1315, -227, 711, -417, -424, +-344, -1126, -89, -976, 294, -99, 569, 807, +403, 968, 7, 373, -480, -504, -676, -1072, +-278, -849, 368, 89, 905, 937, 822, 1212, +125, 655, -590, -527, -915, -1265, -585, -1063, +149, 38, 784, 1215, 788, 1416, 235, 368, +-390, -1151, -781, -1784, -443, -1029, 263, 713, +813, 1911, 807, 1520, 142, -35, -510, -1612, +-752, -1675, -364, -303, 192, 1241, 439, 1730, +343, 613, -56, -1059, -161, -1783, 83, -967, +307, 579, 240, 1641, -191, 1249, -495, -199, +-279, -1222, 403, -1245, 798, -152, 598, 1030, +-157, 1169, -1021, 439, -1000, -608, -275, -1083, +708, -718, 1299, 65, 912, 636, -32, 632, +-863, 243, -1025, -173, -377, -346, 547, -297, +991, -1, 746, 293, -16, 416, -799, 322, +-880, -185, -388, -637, 283, -653, 789, -234, +655, 438, 197, 696, -227, 327, -435, -209, +-231, -370, 181, -32, 470, 412, 450, 384, +64, -192, -571, -658, -839, -646, -526, -12, +232, 673, 1117, 660, 1271, 171, 515, -417, +-614, -606, -1441, -266, -1216, 247, 34, 472, +1391, 376, 1778, 147, 869, -198, -754, -355, +-1921, -424, -1576, -314, -62, 142, 1531, 497, +1932, 519, 884, 120, -675, -478, -1584, -698, +-1082, -218, 157, 509, 1224, 867, 1237, 536, +243, -379, -802, -947, -1194, -739, -574, -3, +444, 763, 1134, 802, 930, 154, 115, -568, +-655, -828, -903, -350, -321, 445, 383, 904, +789, 750, 590, 17, -99, -811, -542, -1077, +-581, -562, -235, 348, 260, 1028, 532, 978, +533, 117, 355, -843, -5, -1152, -370, -516, +-512, 546, -343, 1180, 172, 906, 634, -104, +588, -934, 89, -998, -583, -254, -830, 555, +-321, 725, 514, 267, 1139, -356, 958, -482, +-5, -138, -883, 277, -1110, 360, -526, 106, +488, -157, 1011, -106, 829, 146, 137, 137, +-624, -113, -868, -400, -455, -436, 268, -67, +849, 424, 911, 620, 335, 318, -355, -271, +-850, -598, -798, -447, -123, 134, 639, 749, +956, 756, 643, 115, -134, -799, -809, -1217, +-789, -686, -189, 526, 633, 1385, 1006, 1147, +628, 0, -127, -1366, -751, -1498, -759, -292, +-228, 1171, 412, 1741, 722, 811, 489, -803, +-29, -1798, -417, -1234, -424, 194, -153, 1327, +285, 1322, 680, 212, 537, -767, 104, -998, +-465, -343, -847, 429, -511, 636, 201, 364, +828, -213, 864, -346, 267, -122, -515, 2, +-812, 21, -317, -123, 468, -206, 939, 31, +612, 404, -231, 471, -867, 166, -852, -373, +-94, -674, 664, -331, 868, 264, 438, 751, +-297, 642, -557, -148, -278, -783, 273, -924, +663, -321, 438, 596, -100, 967, -469, 741, +-505, -86, -228, -818, 192, -870, 432, -276, +364, 545, 190, 899, -37, 550, -218, -303, +-157, -890, 39, -816, 328, -76, 427, 685, +151, 827, -242, 381, -477, -339, -292, -582, +156, -311, 445, 214, 316, 500, -148, 197, +-419, -342, -186, -669, 324, -415, 743, 221, +651, 803, 42, 761, -518, 46, -697, -725, +-444, -954, 179, -318, 607, 684, 475, 1154, +20, 588, -427, -581, -510, -1371, 6, -1014, +695, 287, 946, 1328, 500, 1294, -430, 217, +-1034, -1066, -857, -1331, 40, -507, 953, 624, +1001, 1269, 330, 847, -641, -232, -1086, -1084, +-477, -1219, 544, -499, 1226, 659, 1006, 1459, +10, 1302, -1003, 188, -1175, -1307, -445, -1999, +674, -1140, 1282, 704, 840, 2259, -127, 2077, +-1056, 210, -1111, -1928, -322, -2638, 674, -1170, +1260, 1084, 966, 2388, 115, 1797, -698, -141, +-994, -1709, -647, -1759, 202, -540, 741, 848, +846, 1442, 474, 909, -417, -29, -865, -757, +-763, -1007, -104, -669, 902, -48, 1348, 562, +944, 895, -158, 670, -1326, -15, -1572, -704, +-549, -916, 853, -304, 1682, 573, 1326, 988, +-181, 623, -1392, -322, -1528, -1085, -526, -1020, +1007, -174, 1836, 692, 1362, 1080, -93, 696, +-1391, -62, -1686, -614, -718, -760, 707, -371, +1577, 147, 1285, 538, -35, 523, -1272, 138, +-1448, -341, -441, -611, 1018, -372, 1910, 193, +1249, 639, -368, 467, -1611, -79, -1696, -597, +-447, -600, 1125, 60, 1719, 679, 1014, 768, +-327, 148, -1404, -596, -1332, -846, -252, -493, +972, 177, 1617, 532, 1201, 532, 66, 314, +-1109, 58, -1584, -161, -998, -461, 215, -701, +1355, -517, 1562, 324, 667, 1175, -636, 1206, +-1484, 248, -1165, -1258, 86, -1935, 1230, -976, +1456, 893, 748, 2178, -440, 1672, -1212, -165, +-904, -1886, -161, -1991, 589, -493, 807, 1175, +313, 1792, -127, 864, -347, -511, -118, -1222, +287, -791, 315, 135, -26, 623, -346, 532, +-275, -101, 136, -358, 689, -148, 668, 206, +9, 302, -708, -102, -1057, -401, -493, -410, +504, 73, 1194, 636, 1142, 654, 234, 157, +-680, -472, -1079, -761, -751, -423, 129, 242, +846, 488, 952, 320, 458, -94, -251, -443, +-882, -172, -826, 321, -163, 517, 611, 295, +1132, -317, 799, -669, 4, -486, -737, 149, +-1017, 756, -490, 724, 319, 101, 887, -781, +814, -1101, 181, -616, -532, 396, -815, 1268, +-409, 1230, 303, 304, 963, -886, 920, -1410, +199, -913, -684, 346, -1223, 1239, -802, 1119, +252, 187, 1280, -1032, 1418, -1249, 490, -463, +-839, 578, -1611, 1124, -995, 636, 384, -280, +1577, -782, 1593, -509, 244, 211, -1153, 719, +-1638, 473, -783, -190, 727, -625, 1558, -660, +1163, -175, -35, 328, -1125, 440, -1299, 347, +-337, 80, 690, -98, 1181, -89, 890, -126, +-132, -94, -780, 27, -734, 150, -212, 191, +461, 9, 654, -330, 303, -572, -100, -435, +-366, 53, -286, 648, 81, 860, 253, 609, +283, 25, 128, -655, -104, -894, -85, -694, +-39, -41, 58, 708, 150, 934, 65, 539, +-33, -304, 3, -1059, 29, -1031, 36, -93, +69, 932, -25, 1386, 58, 825, 161, -420, +78, -1235, 21, -1206, -152, -368, -240, 648, +-24, 983, 293, 610, 450, 0, 394, -531, +0, -536, -433, -185, -498, 97, -291, 301, +205, 243, 638, 130, 565, 157, 199, 44, +-272, -246, -739, -487, -584, -628, -14, -230, +560, 594, 1049, 1085, 813, 832, 82, -273, +-700, -1285, -1166, -1299, -836, -103, 54, 1359, +917, 1672, 1245, 562, 721, -1236, -392, -2021, +-1035, -993, -891, 883, -88, 1971, 869, 1329, +996, -423, 447, -1761, -281, -1429, -720, 98, +-503, 1400, -58, 1455, 318, 267, 436, -946, +214, -1333, 54, -636, -32, 448, -73, 927, +-78, 731, -107, -14, -70, -640, 150, -635, +350, -182, 328, 424, 168, 712, -311, 476, +-546, -219, -337, -730, -32, -658, 508, -161, +750, 559, 498, 708, 7, 188, -607, -484, +-794, -749, -380, -175, 285, 654, 839, 1035, +886, 459, 274, -615, -499, -1227, -868, -847, +-742, 395, -1, 1207, 719, 905, 862, -320, +578, -1345, -33, -1069, -532, 267, -618, 1570, +-386, 1520, 16, 154, 497, -1401, 698, -1716, +500, -594, -20, 833, -626, 1550, -777, 780, +-310, -524, 457, -1213, 923, -1011, 679, 17, +-118, 881, -730, 1084, -691, 755, -24, 40, +693, -725, 733, -1107, 200, -925, -545, -145, +-773, 926, -280, 1328, 386, 730, 822, -519, +550, -1515, -86, -1180, -472, 143, -473, 1431, +-60, 1657, 404, 493, 387, -969, 63, -1640, +-154, -1081, -271, 243, -83, 1174, 176, 1082, +158, 239, 125, -652, 31, -971, -8, -432, +183, 309, 228, 689, 76, 659, -115, 101, +-370, -333, -394, -436, -39, -391, 343, -160, +547, -7, 429, 171, -90, 328, -473, 372, +-409, 100, -41, -280, 463, -434, 697, -206, +423, 403, -210, 606, -803, 232, -843, -569, +-239, -979, 646, -435, 1154, 631, 767, 1336, +-160, 774, -996, -599, -982, -1658, -92, -1298, +846, 361, 1117, 1896, 486, 1964, -464, 371, +-1025, -1698, -618, -2504, 228, -1286, 758, 914, +620, 2426, -109, 2079, -536, 26, -420, -1993, +231, -2363, 676, -994, 506, 1242, 19, 2538, +-538, 1812, -562, -184, -195, -2054, 315, -2432, +441, -978, 209, 1113, -58, 2199, -323, 1664, +-41, -95, 245, -1627, 331, -1714, 295, -553, +-35, 1038, -268, 1686, -259, 988, -169, -365, +-14, -1486, 213, -1393, 141, -352, 120, 858, +167, 1437, 3, 916, 18, -233, 0, -1132, +-77, -1180, -30, -368, 48, 786, 178, 1339, +172, 928, 1, -77, -163, -1074, -249, -1309, +-157, -648, 88, 276, 171, 967, 167, 973, +209, 382, 160, -276, 253, -675, 154, -637, +-260, -248, -456, 285, -464, 596, -126, 604, +590, 211, 797, -422, 335, -750, -233, -717, +-843, -83, -741, 627, 145, 800, 800, 553, +976, -248, 535, -799, -404, -596, -894, 36, +-656, 643, -127, 759, 597, 168, 738, -598, +237, -663, -210, -356, -576, 258, -429, 585, +178, 150, 502, -295, 525, -386, 267, -20, +-240, 496, -356, 576, -111, 119, 123, -401, +268, -536, -6, -184, -470, 184, -481, 116, +-123, -182, 468, -275, 1028, 58, 804, 681, +13, 734, -812, 43, -1230, -796, -622, -1182, +464, -393, 1277, 862, 1301, 1436, 206, 879, +-1042, -567, -1585, -1678, -1069, -1466, 386, -70, +1578, 1439, 1651, 1827, 722, 754, -744, -786, +-1651, -1670, -1219, -1241, -58, 244, 1156, 1285, +1497, 1246, 583, 304, -488, -914, -1245, -1171, +-1192, -487, -36, 390, 951, 920, 1278, 595, +843, -208, -314, -610, -1044, -448, -834, 84, +-115, 649, 672, 538, 840, -120, 198, -671, +-393, -846, -640, -192, -405, 756, 159, 1030, +433, 522, 494, -568, 363, -1252, 123, -773, +-89, 470, -288, 1373, -460, 1095, -454, -242, +-8, -1502, 471, -1425, 722, -127, 418, 1375, +-295, 1722, -760, 548, -723, -1013, 94, -1724, +863, -939, 1051, 566, 509, 1506, -470, 1189, +-995, -148, -895, -1200, -84, -1280, 669, -344, +893, 918, 487, 1382, -287, 805, -756, -435, +-703, -1444, 73, -1356, 889, -116, 1108, 1267, +504, 1861, -570, 1011, -1275, -951, -1136, -2175, +-35, -1879, 1093, -64, 1402, 2080, 759, 2594, +-494, 1209, -1350, -1108, -1141, -2643, -83, -2137, +1029, -89, 1484, 1816, 915, 2365, -266, 1207, +-1269, -747, -1438, -1953, -589, -1841, 620, -537, +1435, 1074, 1307, 1934, 315, 1618, -987, 320, +-1597, -1312, -1052, -2105, 228, -1520, 1592, 32, +1845, 1760, 841, 2226, -802, 1135, -2058, -779, +-1748, -2219, -226, -2003, 1450, -424, 2221, 1417, +1264, 2266, -624, 1583, -1897, -151, -1844, -1680, +-339, -2036, 1573, -1044, 2187, 654, 1224, 1804, +-576, 1702, -2079, 278, -1940, -1403, -333, -2018, +1387, -1041, 2150, 790, 1300, 2016, -552, 1779, +-1783, 78, -1707, -1617, -386, -1913, 1279, -727, +1979, 905, 1315, 1627, -246, 978, -1638, -473, +-1970, -1397, -901, -1162, 745, -36, 1877, 1114, +1839, 1337, 504, 798, -1012, -291, -1874, -1127, +-1493, -1201, 18, -660, 1411, 443, 1961, 1114, +1163, 1079, -495, 290, -1776, -832, -1934, -1290, +-672, -830, 1071, 337, 2051, 1223, 1638, 1221, +175, 409, -1325, -565, -1914, -975, -1053, -823, +414, -215, 1560, 147, 1625, 248, 370, 454, +-876, 475, -1419, 480, -995, 98, 273, -565, +1059, -890, 1019, -610, 358, 269, -474, 1057, +-756, 1022, -422, 14, 84, -991, 447, -1298, +551, -530, 100, 802, -154, 1343, -262, 919, +-375, -280, -81, -1256, 24, -1061, 279, -199, +402, 771, 252, 1104, 90, 602, -183, -242, +-191, -805, -158, -692, -33, -270, 20, 359, +3, 606, 39, 284, 96, -158, 163, -495, +72, -304, 54, 157, -114, 707, -78, 630, +143, -52, 182, -573, 215, -997, -65, -582, +-390, 232, -395, 785, -78, 923, 326, 461, +557, -300, 398, -908, -92, -812, -420, -291, +-410, 633, -99, 1170, 356, 689, 441, -283, +192, -1280, -50, -1294, -322, -85, -271, 1204, +-37, 1660, 91, 723, 146, -993, 118, -1885, +137, -1252, 216, 485, 164, 1875, -106, 1846, +-285, 269, -359, -1546, -197, -2177, 253, -1264, +526, 661, 401, 2058, 29, 2005, -361, 563, +-525, -1258, -223, -2289, 254, -1591, 553, 260, +415, 1857, -13, 2272, -398, 810, -517, -1306, +-63, -2490, 374, -1782, 556, 476, 384, 2399, +-243, 2547, -632, 633, -560, -1783, -77, -2862, +428, -1709, 720, 697, 549, 2400, 89, 2276, +-252, 480, -622, -1311, -550, -2027, -219, -1332, +208, 92, 647, 1129, 657, 1394, 303, 998, +-339, 189, -750, -843, -627, -1443, -5, -1306, +736, -321, 921, 1186, 449, 1931, -415, 1357, +-952, -282, -733, -1928, -12, -2066, 742, -631, +931, 1256, 442, 2275, -347, 1523, -884, -363, +-688, -1859, 23, -2021, 756, -658, 1006, 1098, +481, 1930, -472, 1367, -1045, -74, -786, -1425, +26, -1729, 915, -750, 1081, 567, 323, 1513, +-570, 1349, -1035, 373, -698, -842, 300, -1479, +1024, -976, 926, 28, 258, 1026, -584, 1246, +-954, 605, -595, -484, 90, -1149, 617, -944, +639, -180, 418, 758, -96, 1118, -495, 685, +-498, -46, -308, -750, 239, -941, 620, -508, +647, 55, 245, 552, -337, 694, -719, 480, +-680, 49, -71, -378, 454, -586, 760, -547, +558, -224, -37, 311, -468, 739, -642, 729, +-289, 275, 269, -417, 672, -911, 730, -789, +210, -66, -462, 688, -954, 841, -979, 402, +-138, -448, 857, -932, 1412, -554, 1145, 198, +-58, 1011, -1183, 1090, -1636, 292, -899, -729, +625, -1334, 1706, -1076, 1629, -51, 331, 1103, +-1230, 1404, -2055, 716, -1304, -536, 386, -1395, +1803, -1085, 2000, 45, 731, 1301, -798, 1534, +-1795, 422, -1476, -934, -111, -1601, 1062, -1055, +1514, 310, 893, 1340, -251, 1199, -993, 199, +-1121, -841, -569, -1159, 364, -488, 938, 395, +1012, 927, 568, 780, -256, 124, -815, -475, +-892, -614, -407, -395, 299, -110, 713, 60, +719, 69, 191, 55, -370, 190, -566, 485, +-403, 527, 120, 192, 534, -435, 524, -994, +179, -871, -206, -25, -520, 905, -426, 1396, +1, 784, 325, -572, 574, -1491, 359, -1463, +-232, -334, -517, 1050, -479, 1707, -35, 1222, +660, -61, 724, -1097, 281, -1387, -281, -917, +-795, 36, -577, 808, 62, 1107, 523, 903, +638, 178, 222, -694, -385, -1219, -525, -1160, +-138, -275, 228, 1001, 530, 1595, 432, 1291, +5, 112, -305, -1258, -546, -1754, -415, -1189, +-123, 63, 354, 1203, 737, 1489, 606, 936, +114, 27, -566, -885, -828, -1099, -533, -765, +262, -244, 893, 527, 834, 857, 235, 769, +-622, 401, -944, -323, -516, -701, 255, -697, +731, -421, 661, 101, 149, 385, -345, 524, +-357, 478, -314, 282, -85, 20, 236, -442, +301, -763, 406, -676, 284, -152, -200, 595, +-579, 1130, -592, 851, -271, -31, 520, -996, +980, -1393, 581, -701, -68, 467, -781, 1453, +-807, 1523, -62, 392, 496, -1107, 625, -1877, +308, -1433, -276, 129, -385, 1719, -34, 2067, +139, 1032, 189, -851, -135, -2078, -438, -1799, +-183, -226, 266, 1505, 801, 1975, 789, 1059, +26, -720, -747, -1815, -995, -1393, -587, -18, +231, 1271, 837, 1438, 762, 497, 331, -736, +-284, -1158, -663, -566, -432, 383, -30, 858, +342, 560, 476, -208, 305, -783, -31, -617, +-325, -5, -354, 531, -120, 678, 90, 337, +189, -254, 164, -520, -62, -397, -122, -97, +41, 416, 283, 535, 348, 153, 19, -230, +-270, -664, -433, -525, -223, 100, 272, 645, +306, 822, 92, 205, -239, -546, -322, -888, +73, -527, 506, 412, 618, 1072, 67, 848, +-556, -97, -753, -1074, -253, -1328, 532, -554, +794, 704, 499, 1366, -339, 1111, -816, 29, +-600, -1089, -21, -1158, 623, -409, 727, 638, +462, 1117, -88, 625, -447, -458, -464, -1064, +-282, -824, 166, 6, 248, 968, 304, 1006, +159, 279, -188, -527, -183, -900, -157, -515, +17, 313, 252, 717, 328, 497, 122, -104, +-125, -559, -216, -417, -207, 74, 24, 422, +103, 149, 198, -334, 113, -535, -219, -128, +-223, 707, -226, 1075, 84, 540, 554, -545, +592, -1351, 301, -1149, -351, -72, -880, 1029, +-875, 1364, -118, 584, 814, -511, 1159, -1076, +769, -875, -398, 26, -1250, 727, -1198, 835, +-198, 445, 1142, -179, 1502, -528, 905, -573, +-539, -441, -1660, -190, -1286, 198, -153, 540, +1205, 871, 1667, 647, 718, -145, -738, -897, +-1566, -1437, -1203, -905, 108, 504, 1438, 1612, +1553, 1842, 722, 825, -681, -955, -1730, -2260, +-1387, -2132, -257, -622, 1095, 1286, 1848, 2541, +1245, 2197, -181, 572, -1480, -1395, -1878, -2498, +-887, -2050, 797, -502, 1900, 1347, 1760, 2194, +422, 1723, -1206, 345, -1961, -1095, -1417, -1687, +-13, -1339, 1422, -355, 1887, 635, 1098, 1097, +-275, 1212, -1433, 725, -1634, -113, -841, -784, +571, -1370, 1710, -1165, 1579, -216, 453, 862, +-987, 1495, -1854, 1237, -1404, 177, 152, -907, +1577, -1334, 1843, -927, 816, 5, -861, 680, +-1809, 945, -1394, 652, 7, 34, 1411, -358, +1676, -635, 729, -667, -693, -210, -1550, 179, +-1119, 499, 18, 708, 1010, 374, 1134, -136, +409, -399, -466, -463, -908, -324, -515, -24, +217, 61, 687, 121, 580, 231, -10, 340, +-546, 380, -608, 51, -243, -370, 267, -662, +616, -527, 352, 62, -159, 610, -375, 751, +-371, 392, 52, -98, 628, -569, 417, -640, +-91, -442, -575, -299, -941, 175, -237, 643, +677, 985, 1081, 935, 1008, 117, -67, -952, +-1169, -1622, -1405, -1228, -951, 16, 299, 1321, +1580, 1796, 1793, 1003, 1029, -340, -363, -1397, +-1810, -1470, -2140, -652, -1278, 426, 325, 1121, +2074, 1105, 2601, 553, 1568, -214, -380, -701, +-2315, -877, -2854, -663, -1591, -151, 680, 326, +2634, 671, 2842, 790, 1283, 547, -963, 77, +-2670, -463, -2567, -1020, -837, -1001, 1224, -433, +2492, 488, 2134, 1420, 466, 1469, -1229, 497, +-1967, -831, -1541, -1797, -250, -1656, 961, -296, +1379, 1167, 1057, 1894, 163, 1513, -569, 141, +-828, -1198, -781, -1703, -342, -1349, 120, -174, +573, 1047, 873, 1629, 749, 1400, 280, 263, +-568, -1088, -1295, -1924, -1252, -1602, -433, -176, +816, 1538, 1788, 2395, 1555, 1668, 288, -189, +-1273, -2151, -2183, -2717, -1493, -1425, 180, 781, +1784, 2594, 2253, 2646, 1067, 887, -768, -1317, +-2091, -2653, -1906, -2247, -427, -372, 1209, 1499, +1936, 2317, 1232, 1802, -95, 258, -1192, -1118, +-1325, -1778, -627, -1659, 280, -658, 886, 401, +714, 1279, 312, 1768, -183, 1298, -512, 223, +-337, -965, -236, -1816, 16, -1706, 343, -620, +314, 742, 313, 1635, 158, 1671, -237, 859, +-456, -411, -324, -1293, -82, -1507, 266, -1014, +457, -3, 195, 916, 16, 1285, -249, 1089, +-397, 308, -113, -596, 62, -963, 281, -856, +516, -247, 437, 270, -63, 407, -609, 261, +-923, -77, -753, -3, 258, 322, 1151, 539, +1363, 378, 635, -253, -772, -991, -1663, -1133, +-1394, -497, -90, 470, 1379, 1438, 1905, 1482, +961, 498, -536, -772, -1741, -1740, -1766, -1657, +-333, -449, 1073, 1122, 1697, 2127, 1066, 1710, +-424, 130, -1314, -1561, -1200, -2436, -124, -1479, +1070, 547, 1286, 2076, 316, 2355, -818, 859, +-1234, -1370, -830, -2412, 435, -1950, 1218, -103, +996, 1909, 253, 2355, -760, 1497, -1000, -369, +-604, -2004, -97, -2107, 522, -1140, 686, 573, +601, 1927, 423, 1870, -24, 809, -584, -783, +-1089, -1949, -1023, -1668, -322, -357, 717, 1144, +1666, 1860, 1653, 1342, 592, -84, -845, -1288, +-1999, -1552, -2016, -921, -846, 257, 850, 1007, +2166, 1130, 2279, 694, 1131, 57, -737, -497, +-2350, -959, -2604, -999, -1358, -654, 668, 119, +2528, 1216, 2948, 1771, 1597, 1330, -625, -146, +-2618, -1813, -3066, -2544, -1622, -1658, 465, 492, +2289, 2323, 2853, 2871, 1739, 1498, -88, -817, +-1848, -2374, -2615, -2503, -2080, -1135, -484, 727, +1444, 1853, 2614, 1906, 2494, 1015, 927, -232, +-1295, -1114, -2839, -1553, -2692, -1325, -1041, -339, +1280, 727, 2776, 1528, 2441, 1590, 942, 649, +-1105, -626, -2337, -1542, -2081, -1570, -1023, -696, +568, 445, 1729, 1246, 1839, 1375, 1188, 842, +68, -47, -1135, -782, -1832, -1192, -1545, -1133, +-522, -470, 932, 418, 1920, 1243, 1716, 1431, +673, 791, -896, -374, -1977, -1492, -1830, -1742, +-586, -897, 1151, 695, 2096, 1961, 1727, 2065, +129, 848, -1656, -1194, -2157, -2518, -1122, -2319, +809, -721, 2155, 1667, 1888, 2979, 169, 2341, +-1663, 448, -2248, -1932, -1206, -3093, 777, -2207, +2022, -135, 1921, 1980, 500, 2901, -1176, 1997, +-1862, 50, -1467, -1745, -206, -2550, 1049, -1848, +1650, -302, 1261, 1319, 303, 2034, -833, 1714, +-1493, 591, -1235, -730, -447, -1415, 754, -1433, +1446, -642, 1260, 232, 354, 756, -946, 908, +-1586, 546, -1229, 9, -65, -166, 1236, -286, +1659, -373, 993, -167, -352, -288, -1502, -324, +-1709, 81, -733, 320, 704, 695, 1658, 871, +1605, 345, 338, -308, -975, -1021, -1731, -1385, +-1530, -830, -111, 133, 1114, 1136, 1565, 1700, +1115, 1222, -187, 164, -1158, -996, -1239, -1780, +-493, -1390, 435, -325, 857, 769, 560, 1634, +-3, 1460, -306, 429, -342, -696, -117, -1530, +-36, -1494, 18, -554, 41, 682, 71, 1594, +240, 1650, 62, 681, -246, -749, -335, -1717, +-203, -1791, 355, -700, 856, 860, 636, 1893, +-103, 1804, -933, 467, -1326, -1157, -760, -2096, +296, -1626, 1303, -61, 1763, 1598, 1129, 2277, +-160, 1352, -1502, -341, -2213, -1916, -1693, -2351, +-68, -1096, 1781, 477, 2778, 1908, 2257, 2298, +357, 1112, -1979, -295, -3247, -1785, -2669, -2325, +-649, -1419, 1910, -59, 3490, 1754, 3142, 2661, +1183, 1954, -1541, 290, -3614, -1806, -3804, -3075, +-1988, -2536, 1076, -567, 3662, 1794, 4346, 3356, +2545, 2974, -798, 1051, -3645, -1530, -4556, -3341, +-2779, -3275, 603, -1546, 3339, 1098, 4175, 3058, +2566, 3352, -422, 1842, -2807, -683, -3599, -2664, +-2187, -3177, 183, -1914, 1961, 362, 2601, 2206, +1561, 2815, -230, 1857, -1220, -76, -1319, -1687, +-673, -2220, 345, -1721, 397, -313, -278, 974, +-586, 1415, -443, 1467, 648, 756, 1862, -2, +1644, -525, 206, -1177, -1975, -1149, -3278, -870, +-2224, -212, 427, 874, 3164, 1370, 4106, 1301, +2213, 642, -1170, -549, -3802, -1287, -4120, -1410, +-1808, -874, 1565, 116, 3774, 1016, 3729, 1438, +1500, 1203, -1360, 361, -3202, -811, -3250, -1557, +-1447, -1635, 837, -710, 2526, 748, 2932, 1824, +1809, 1962, -163, 795, -1927, -924, -2700, -2086, +-2179, -1996, -358, -630, 1577, 1192, 2689, 2198, +2416, 1746, 699, 269, -1343, -1279, -2546, -1842, +-2348, -1242, -925, -69, 1099, 801, 2292, 908, +2106, 637, 962, 336, -661, 465, -1779, 401, +-1961, -287, -1261, -1268, 41, -2013, 1307, -1448, +1912, 329, 1632, 2316, 444, 3099, -966, 1834, +-1845, -606, -2001, -2702, -892, -3165, 596, -1742, +1525, 543, 1829, 2230, 1021, 2547, -156, 1560, +-1105, -29, -1611, -1328, -1220, -1875, -317, -1541, +606, -481, 1359, 625, 1299, 1435, 415, 1440, +-532, 602, -1352, -303, -1157, -1023, -88, -938, +701, -268, 1100, 147, 480, 355, -664, 118, +-981, -298, -626, -166, 487, 341, 1469, 764, +1015, 925, -130, 426, -1357, -576, -1808, -1441, +-855, -1739, 693, -970, 1711, 521, 1763, 1959, +770, 2477, -762, 1602, -1481, -432, -1560, -2419, +-840, -3030, 399, -1913, 1066, 429, 1387, 2528, +1060, 3279, 298, 2143, -499, -103, -1203, -2280, +-1301, -3300, -821, -2612, 49, -637, 1097, 1797, +1625, 3404, 1313, 3316, 345, 1317, -1027, -1530, +-1959, -3692, -1673, -3776, -447, -1532, 1216, 1673, +2189, 4025, 1733, 3855, 380, 1312, -1384, -1960, +-2242, -4151, -1626, -3804, -93, -1185, 1553, 2058, +2063, 4139, 1295, 3884, -179, 1375, -1663, -1977, +-2023, -4171, -1113, -4060, 395, -1548, 1637, 1999, +1904, 4330, 1047, 4102, -432, 1395, -1680, -2201, +-2059, -4297, -1165, -3788, 248, -1059, 1467, 2247, +1879, 3757, 1188, 3080, 25, 820, -1081, -1655, +-1584, -2588, -1267, -2158, -439, -866, 476, 581, +965, 1164, 898, 1290, 659, 1132, 215, 508, +-280, -59, -464, -727, -706, -1210, -874, -1128, +-684, -663, -292, 289, 532, 1051, 1381, 1245, +1669, 1180, 1146, 460, -209, -596, -1741, -1375, +-2508, -1754, -1907, -1280, -249, 47, 1728, 1575, +2999, 2341, 2565, 1914, 796, 304, -1498, -1600, +-3136, -2504, -2884, -2191, -1192, -624, 1137, 1258, +2914, 2308, 3050, 2331, 1589, 1077, -668, -634, +-2481, -2029, -2843, -2567, -1708, -1631, 115, 161, +1778, 1931, 2464, 2704, 1887, 1993, 568, 90, +-927, -1842, -1940, -2550, -2010, -1967, -1260, -277, +101, 1496, 1518, 2252, 2243, 1909, 1753, 524, +339, -1089, -1299, -2063, -2240, -1998, -1879, -724, +-520, 1008, 1058, 2180, 1933, 2052, 1633, 652, +509, -1229, -697, -2247, -1591, -1812, -1575, -365, +-798, 1378, 382, 2128, 1608, 1459, 1705, 268, +791, -1044, -817, -1821, -2179, -1495, -1980, -701, +-463, 505, 1682, 1635, 2853, 2025, 2000, 1541, +-404, 100, -2716, -1634, -3355, -2646, -1862, -2296, +990, -699, 3013, 1461, 3259, 2867, 1671, 2866, +-1027, 1438, -2845, -817, -3011, -2627, -1617, -3176, +626, -2241, 2190, -92, 2468, 2160, 1572, 3270, +-187, 2850, -1587, 825, -1940, -1567, -1346, -2944, +-73, -2881, 919, -1210, 1223, 888, 820, 2202, +153, 2369, -246, 1394, -413, -43, -242, -1117, +-125, -1590, -182, -1488, -326, -766, -416, 34, +-37, 803, 440, 1464, 886, 1363, 1026, 869, +381, -69, -516, -1169, -1318, -1593, -1509, -1449, +-754, -597, 558, 749, 1772, 1612, 1969, 1789, +962, 1128, -781, -356, -2182, -1518, -2281, -1920, +-992, -1368, 1016, 148, 2492, 1426, 2511, 1838, +877, 1330, -1376, -50, -2777, -1149, -2495, -1442, +-687, -1024, 1521, -20, 2838, 670, 2361, 833, +460, 596, -1773, 165, -2934, -49, -2243, -111, +-332, -198, 1816, -374, 2884, -506, 2158, -409, +133, 69, -2044, 768, -2911, 1064, -2014, 612, +-61, -401, 1841, -1347, 2500, -1507, 1770, -432, +185, 1203, -1373, 2202, -2027, 1775, -1828, -113, +-758, -2218, 516, -2971, 1387, -1701, 1844, 938, +1373, 3164, 192, 3381, -968, 1391, -1764, -1566, +-1858, -3455, -893, -3277, 307, -1118, 1324, 1599, +1931, 3042, 1382, 2906, 392, 1176, -796, -920, +-1835, -2197, -1781, -2398, -1021, -1423, 261, 87, +1498, 1407, 1674, 1879, 1178, 1559, 177, 508, +-985, -653, -1269, -1239, -968, -1309, -480, -701, +276, -88, 502, 390, 479, 816, 560, 786, +387, 833, 367, 594, 162, -75, -464, -712, +-984, -1331, -1233, -1395, -937, -760, 92, 375, +1162, 1443, 1850, 2033, 1753, 1743, 562, 397, +-1157, -1209, -2478, -2492, -2627, -2693, -1310, -1347, +966, 833, 2906, 2884, 3339, 3560, 1797, 2258, +-1016, -396, -3384, -2993, -3641, -4050, -1833, -2870, +981, -24, 3224, 2766, 3310, 4074, 1450, 3109, +-1067, 495, -2721, -2144, -2553, -3557, -1017, -2988, +735, -921, 1665, 1474, 1443, 2837, 554, 2645, +-274, 1246, -627, -812, -626, -2045, -459, -2014, +-376, -1197, -284, 185, -26, 1147, 276, 1280, +625, 988, 672, 445, 183, -131, -461, -520, +-780, -781, -541, -813, 67, -413, 501, 155, +387, 670, -133, 789, -621, 314, -653, -307, +-42, -579, 831, -239, 1102, 452, 548, 825, +-524, 474, -1419, -405, -1279, -1311, -441, -1330, +601, -286, 1349, 1026, 1128, 1875, 384, 1634, +-422, 345, -1016, -1159, -993, -2006, -610, -1738, +-101, -611, 419, 781, 719, 1714, 734, 1780, +585, 1146, 203, 32, -415, -999, -950, -1553, +-1217, -1481, -872, -813, 26, 130, 892, 1050, +1469, 1423, 1276, 1196, 265, 606, -935, -187, +-1678, -737, -1414, -1001, -399, -848, 679, -542, +1291, -230, 1114, 267, 328, 634, -440, 1073, +-861, 1307, -772, 954, -310, 54, 11, -1325, +38, -2348, -21, -2189, 134, -750, 488, 1460, +659, 3161, 418, 3135, -237, 1325, -1052, -1310, +-1264, -3299, -674, -3370, 333, -1618, 1204, 890, +1144, 2860, 292, 3038, -676, 1707, -1251, -270, +-797, -1980, 194, -2232, 902, -1394, 852, -110, +-17, 1004, -906, 1205, -1209, 819, -561, 308, +621, -3, 1444, -66, 1271, -131, 92, -388, +-1243, -755, -1919, -694, -1388, -190, 99, 551, +1291, 1190, 1722, 925, 1088, 87, -232, -649, +-1071, -996, -1296, -487, -763, 435, 78, 777, +453, 515, 398, -279, 144, -1093, -102, -854, +6, 117, 383, 1193, 358, 1863, 112, 992, +-498, -641, -1267, -1947, -1111, -2417, -456, -971, +725, 1034, 1809, 2461, 1644, 2711, 573, 997, +-1076, -1144, -2273, -2550, -2095, -2646, -700, -988, +1077, 1190, 2151, 2526, 1856, 2507, 494, 868, +-979, -1261, -1814, -2382, -1488, -2166, -502, -453, +493, 1578, 1024, 2283, 726, 1645, 203, -42, +-298, -1699, -472, -1943, -136, -1020, 118, 496, +116, 1667, -242, 1481, -791, 534, -864, -598, +-359, -1345, 561, -1055, 1581, -180, 1641, 660, +422, 1167, -1225, 856, -2583, 17, -2502, -618, +-729, -1104, 1514, -751, 3140, 177, 2921, 752, +801, 1107, -1860, 692, -3612, -203, -3267, -856, +-1085, -1025, 1682, -523, 3519, 391, 3210, 1076, +1102, 965, -1706, 352, -3458, -620, -3066, -1245, +-1073, -751, 1467, 120, 2892, 983, 2335, 1238, +468, 383, -1462, -660, -2292, -1197, -1537, -822, +20, 281, 1215, 1253, 1429, 1260, 597, 346, +-576, -749, -1142, -1516, -1051, -1131, -331, -48, +517, 822, 767, 1443, 819, 1148, 332, 378, +-423, -316, -749, -1133, -1070, -1286, -789, -948, +9, -170, 552, 996, 1016, 1589, 927, 1344, +267, 361, -530, -827, -1266, -1467, -1380, -1157, +-761, -246, 225, 600, 1136, 961, 1377, 717, +862, 325, -101, 36, -1193, -128, -1605, -217, +-1051, -452, -69, -671, 927, -542, 1280, -68, +653, 593, -283, 1040, -1107, 915, -1106, 367, +-174, -358, 692, -765, 1047, -734, 403, -484, +-850, -62, -1478, 179, -1072, 277, 104, 459, +1439, 635, 1781, 668, 728, 477, -896, -172, +-2247, -1037, -2061, -1464, -495, -1238, 1233, -114, +2297, 1422, 1870, 2311, 363, 2056, -1480, 611, +-2456, -1482, -1983, -2986, -697, -2880, 998, -1198, +1983, 1369, 1820, 3467, 1003, 3754, -387, 1999, +-1557, -916, -1822, -3467, -1658, -4179, -750, -2627, +613, 264, 1400, 3026, 1887, 4228, 1460, 3192, +182, 623, -894, -2074, -1901, -3733, -2219, -3421, +-1362, -1369, -162, 1008, 1070, 2896, 2072, 3300, +2115, 1967, 1250, 241, -249, -1474, -1928, -2528, +-2817, -2245, -2392, -1381, -815, -35, 1274, 1544, +2695, 2442, 2656, 2460, 1121, 1301, -1068, -744, +-2442, -2410, -2419, -2831, -1121, -1670, 632, 587, +1472, 2298, 1184, 2401, 271, 1238, -590, -639, +-699, -1677, -94, -1232, 411, -219, 299, 790, +-194, 834, -1003, 15, -1263, -743, -706, -801, +258, -23, 1320, 1007, 1511, 1610, 879, 1021, +-202, -251, -1344, -1430, -1805, -2016, -1496, -1348, +-509, 98, 786, 1432, 1561, 2128, 1512, 1731, +732, 415, -392, -949, -1273, -1869, -1474, -1777, +-1064, -723, -325, 421, 406, 1386, 695, 1581, +682, 923, 644, 207, 470, -534, 100, -996, +-551, -872, -1328, -736, -1587, -369, -1123, 270, +51, 785, 1463, 1295, 2078, 1373, 1624, 625, +226, -512, -1487, -1559, -2453, -2102, -2357, -1195, +-957, 365, 984, 1678, 2219, 2416, 2397, 1435, +1253, -84, -543, -1375, -1946, -2065, -2471, -1330, +-1788, -202, -203, 797, 1216, 1451, 1864, 1378, +1762, 846, 652, 139, -758, -728, -1589, -1445, +-1936, -1530, -1254, -957, 136, 283, 1161, 1591, +1628, 2002, 1080, 1401, -156, 52, -1146, -1320, +-1466, -1692, -792, -1124, 141, -96, 627, 793, +623, 869, 28, 473, -586, 65, -561, -106, +-66, 196, 377, 458, 595, 206, 303, -307, +-330, -832, -807, -996, -1194, -403, -963, 419, +-12, 906, 804, 1037, 1352, 597, 1356, 86, +398, -105, -842, -474, -1845, -667, -2088, -859, +-1090, -1033, 332, -316, 1577, 728, 2169, 1732, +1506, 2232, 36, 1345, -1431, -378, -2351, -2074, +-2106, -2982, -778, -2287, 756, -200, 1973, 1955, +2095, 3218, 974, 2957, -504, 988, -1675, -1284, +-1907, -2677, -1167, -2753, 26, -1322, 929, 470, +1125, 1563, 633, 1770, -183, 1252, -521, 483, +-472, 55, -175, -227, 90, -772, -17, -1202, +-340, -1390, -540, -914, -375, 311, -95, 1492, +406, 2025, 633, 1519, 545, 291, 370, -938, +-292, -1535, -878, -1465, -1311, -925, -1282, -135, +-324, 490, 744, 1127, 1566, 1619, 1638, 1519, +672, 805, -595, -540, -1604, -1913, -1962, -2433, +-1312, -1701, -207, 43, 726, 1850, 1432, 2687, +1408, 2058, 805, 424, 47, -1270, -881, -2127, +-1448, -1675, -1465, -462, -1199, 698, -360, 1291, +818, 1022, 1636, 215, 1719, -339, 939, -452, +-496, -254, -1753, 267, -2143, 458, -1517, 232, +88, -36, 1371, -509, 1591, -721, 998, -476, +-168, -130, -1002, 469, -1109, 1068, -604, 1135, +106, 808, 449, 26, 269, -1065, -250, -1677, +-525, -1495, -425, -562, -46, 906, 467, 1989, +686, 2011, 421, 1068, -187, -468, -718, -1715, +-968, -1931, -797, -1248, -285, -20, 316, 1139, +663, 1531, 722, 1215, 634, 546, 176, -246, +-356, -740, -883, -775, -1336, -712, -1119, -485, +-348, -154, 634, 176, 1541, 748, 1593, 1116, +701, 1076, -573, 527, -1667, -514, -1912, -1342, +-1275, -1634, -67, -1042, 1197, 325, 1752, 1455, +1478, 1957, 479, 1477, -925, -1, -1814, -1423, +-1891, -2085, -1037, -1574, 380, -114, 1454, 1448, +1894, 2186, 1264, 1676, -138, 211, -1536, -1397, +-2244, -2095, -1635, -1602, -223, -156, 1237, 1291, +2091, 2048, 1742, 1717, 316, 353, -1225, -958, +-2150, -1863, -2090, -1897, -827, -841, 617, 587, +1641, 1824, 2009, 2296, 1244, 1526, -127, -33, +-1327, -1592, -2011, -2442, -1880, -1862, -836, -356, +452, 1240, 1554, 2157, 1980, 1817, 1344, 665, +31, -555, -1318, -1296, -2115, -1260, -1898, -672, +-516, -63, 1012, 455, 1725, 637, 1408, 551, +152, 388, -981, 161, -1278, -1, -844, -5, +221, 25, 833, -234, 354, -468, -359, -784, +-879, -746, -809, 47, 65, 899, 879, 1611, +1132, 1531, 760, 441, -227, -856, -1290, -1805, +-1595, -1942, -1091, -1024, -111, 355, 988, 1434, +1476, 2006, 1242, 1686, 409, 606, -717, -484, +-1516, -1507, -1545, -1969, -905, -1483, 146, -617, +1142, 677, 1449, 1887, 1133, 2228, 225, 1830, +-822, 480, -1514, -1392, -1789, -2627, -1186, -2763, +223, -1468, 1506, 881, 2149, 2828, 1816, 3408, +170, 2192, -1616, -349, -2541, -2520, -2302, -3336, +-722, -2449, 1006, -171, 2012, 1772, 1997, 2672, +1000, 2438, -179, 1011, -1077, -439, -1570, -1467, +-1607, -2135, -1217, -1892, -428, -959, 737, 235, +1810, 1756, 2171, 2659, 1570, 2202, -126, 808, +-1944, -1215, -2823, -2736, -2494, -2762, -821, -1465, +1227, 625, 2477, 2298, 2581, 2721, 1403, 1903, +-309, 211, -1719, -1399, -2474, -2192, -2052, -2014, +-770, -924, 572, 496, 1572, 1538, 1804, 1906, +1213, 1502, 292, 420, -697, -741, -1314, -1506, +-1294, -1663, -969, -1046, -476, 38, 161, 1155, +796, 1705, 1138, 1381, 1011, 392, 471, -837, +-286, -1529, -979, -1278, -1282, -300, -964, 850, +-281, 1420, 416, 968, 776, -80, 551, -1007, +252, -1312, 70, -588, -70, 639, 22, 1444, +-78, 1443, -516, 423, -885, -1024, -974, -1860, +-491, -1680, 452, -429, 1232, 1215, 1428, 2254, +998, 2106, -112, 808, -1304, -993, -1814, -2330, +-1686, -2498, -650, -1446, 768, 510, 1691, 2244, +1949, 2865, 1162, 2168, -271, 258, -1551, -1810, +-2055, -2890, -1579, -2543, -460, -909, 816, 1179, +1571, 2557, 1583, 2610, 856, 1452, -206, -370, +-1009, -1855, -1430, -2275, -1346, -1675, -737, -265, +137, 1128, 934, 1749, 1362, 1622, 1186, 713, +476, -376, -460, -947, -1291, -1087, -1577, -740, +-1138, -222, -210, 25, 743, 286, 1303, 473, +1202, 680, 567, 993, -167, 725, -881, 64, +-1127, -846, -926, -1580, -616, -1400, 85, -527, +704, 761, 889, 1656, 795, 1546, 258, 714, +-374, -350, -748, -1088, -866, -1044, -433, -419, +165, 95, 361, 392, 233, 254, -105, -200, +-348, -211, -90, 112, 320, 592, 600, 1107, +682, 848, 29, -89, -870, -1118, -1353, -1835, +-1334, -1537, -488, -279, 736, 1189, 1571, 2109, +1833, 2023, 1171, 881, -311, -591, -1650, -1663, +-2310, -2012, -1906, -1402, -418, -303, 1119, 884, +2172, 1719, 2208, 1756, 968, 1063, -648, -84, +-1957, -1203, -2328, -1649, -1455, -1239, 67, -322, +1401, 691, 2050, 1197, 1614, 1053, 308, 504, +-1035, -186, -1892, -653, -1821, -775, -823, -518, +498, -76, 1538, 440, 1754, 739, 1012, 565, +-157, 110, -1168, -478, -1630, -750, -1247, -468, +-396, 56, 403, 571, 999, 702, 1112, 304, +783, -174, 399, -409, -204, -288, -926, 29, +-1302, 246, -1359, 91, -857, -317, 200, -457, +1244, -289, 1867, 295, 1663, 1011, 582, 1062, +-810, 541, -1790, -373, -2061, -1371, -1649, -1635, +-561, -1052, 727, 36, 1750, 1279, 2382, 1991, +2064, 1803, 724, 868, -1115, -589, -2876, -1898, +-3405, -2429, -2216, -1918, 173, -392, 2629, 1460, +3760, 2743, 2867, 2760, 472, 1357, -1970, -817, +-3272, -2618, -2739, -3058, -961, -1884, 812, 331, +1905, 2309, 1881, 2964, 1038, 1972, 126, -79, +-611, -1943, -972, -2560, -943, -1673, -830, 108, +-484, 1694, 145, 2093, 622, 1199, 822, -269, +667, -1386, 185, -1509, -207, -635, -522, 490, +-617, 1119, -382, 945, -206, 171, 39, -530, +313, -794, 292, -534, 184, -12, -29, 346, +-299, 483, -243, 508, 86, 404, 330, 165, +349, -225, -123, -819, -770, -1160, -914, -849, +-549, 104, 395, 1304, 1221, 1989, 1304, 1559, +635, 76, -673, -1597, -1667, -2511, -1672, -2032, +-771, -365, 593, 1482, 1664, 2500, 1707, 2199, +788, 806, -412, -831, -1508, -1848, -1747, -1887, +-1023, -1147, 35, -71, 1057, 858, 1466, 1270, +1075, 1237, 193, 794, -656, 63, -1174, -596, +-1092, -955, -488, -937, 135, -493, 662, 144, +885, 490, 678, 651, 201, 520, -385, 118, +-819, -102, -898, -331, -556, -392, 29, -165, +609, 63, 914, 368, 731, 431, 221, 89, +-420, -313, -890, -679, -1006, -621, -737, -3, +3, 671, 793, 1077, 1181, 926, 1023, 97, +222, -804, -744, -1260, -1337, -1167, -1247, -390, +-405, 586, 645, 1163, 1169, 1228, 968, 764, +277, -57, -581, -727, -848, -1058, -546, -1001, +-116, -438, 351, 219, 351, 761, 11, 938, +-174, 612, -255, 69, -234, -430, 69, -557, +276, -344, 308, 42, 410, 252, 177, 154, +-261, -100, -728, -406, -1116, -413, -929, -82, +-21, 389, 1172, 841, 1884, 981, 1638, 600, +283, -171, -1563, -1082, -2664, -1719, -2337, -1581, +-639, -568, 1599, 921, 2907, 2279, 2508, 2684, +811, 1672, -1263, -290, -2595, -2304, -2452, -3343, +-1142, -2718, 457, -665, 1676, 1664, 1931, 3191, +1372, 3233, 568, 1720, -470, -336, -1327, -2120, +-1703, -2995, -1602, -2585, -836, -1356, 377, 347, +1533, 2085, 2205, 2992, 1905, 2858, 672, 1640, +-853, -632, -2230, -2665, -2676, -3690, -1882, -3303, +-377, -1086, 1461, 1584, 2724, 3612, 2663, 4217, +1621, 2605, -167, -139, -2123, -2689, -2987, -4041, +-2656, -3333, -1279, -1119, 897, 1258, 2520, 2835, +2986, 2954, 2282, 1750, 395, 211, -1657, -1114, +-2749, -1747, -2649, -1597, -1304, -1124, 575, -386, +1761, 357, 2078, 881, 1434, 1212, 255, 1157, +-562, 643, -983, -53, -1024, -703, -781, -1121, +-576, -968, -157, -450, 362, 116, 668, 595, +847, 683, 606, 465, 163, 211, -123, -8, +-346, -94, -424, -82, -475, -142, -684, -297, +-667, -452, -238, -508, 338, -347, 1059, 111, +1396, 703, 974, 1103, 118, 1059, -983, 455, +-1673, -558, -1503, -1385, -726, -1563, 270, -1034, +1137, 35, 1468, 1008, 1190, 1449, 586, 1292, +-207, 685, -920, -48, -1354, -721, -1350, -1184, +-918, -1316, -60, -989, 974, -195, 1641, 869, +1718, 1612, 982, 1571, -362, 775, -1654, -515, +-2137, -1507, -1548, -1612, -199, -891, 1359, 275, +2032, 1164, 1545, 1259, 366, 670, -1051, -224, +-1672, -853, -1251, -798, -338, -300, 665, 310, +1125, 653, 899, 438, 347, -26, -294, -430, +-811, -557, -900, -273, -546, 122, 40, 367, +605, 393, 762, 209, 613, 24, 242, -23, +-242, -27, -489, -78, -558, -262, -535, -509, +-470, -512, -246, -195, 171, 355, 715, 872, +1199, 941, 1082, 503, 361, -209, -700, -798, +-1634, -975, -1749, -673, -946, -134, 302, 343, +1447, 631, 1907, 616, 1273, 403, 134, 78, +-940, -292, -1516, -434, -1083, -271, -296, -14, +274, 247, 528, 171, 262, -351, -4, -679, +133, -570, 466, 103, 795, 1138, 773, 1543, +-13, 975, -1145, -256, -1783, -1648, -1668, -2045, +-551, -1233, 1032, 164, 2079, 1590, 2270, 1983, +1360, 1246, -347, 83, -1857, -1079, -2445, -1578, +-1863, -1192, -386, -458, 1089, 391, 1974, 1049, +1942, 1106, 949, 847, -289, 245, -1277, -511, +-1650, -895, -1165, -1008, -311, -750, 554, -187, +1071, 327, 893, 753, 431, 1017, 51, 958, +-271, 502, -358, -218, -269, -1007, -346, -1505, +-487, -1226, -477, -337, -112, 725, 569, 1500, +992, 1454, 889, 692, 314, -314, -484, -1087, +-1009, -1253, -1002, -835, -391, -86, 376, 623, +853, 874, 756, 695, 139, 177, -354, -386, +-525, -493, -318, -321, 73, 44, 261, 312, +205, 107, 45, -201, -103, -389, -158, -288, +-54, 112, 15, 478, 32, 531, 19, 291, +-20, -62, 18, -335, 75, -351, 127, -320, +97, -216, 3, -68, -114, -56, -332, 174, +-386, 358, -105, 339, 245, 372, 559, 147, +620, -147, 261, -276, -248, -405, -673, -445, +-772, -316, -378, -148, 233, 107, 644, 472, +751, 627, 372, 548, -261, 233, -622, -234, +-608, -554, -75, -570, 542, -322, 687, -77, +251, 72, -483, 87, -885, 36, -595, 214, +250, 500, 925, 602, 947, 403, 353, -199, +-426, -879, -837, -1125, -650, -787, -192, 41, +189, 859, 351, 1129, 206, 867, 233, 175, +361, -491, 308, -669, 163, -623, -313, -372, +-786, -117, -805, -93, -439, 29, 286, 299, +983, 597, 1104, 820, 740, 731, 34, 148, +-854, -663, -1333, -1286, -1182, -1433, -407, -866, +692, 236, 1449, 1316, 1536, 1800, 833, 1437, +-384, 280, -1399, -1055, -1641, -1763, -1007, -1622, +77, -588, 1062, 698, 1480, 1364, 1109, 1347, +314, 643, -552, -326, -1144, -822, -1093, -926, +-570, -712, 78, -181, 737, 212, 981, 539, +687, 892, 378, 786, -148, 366, -585, -245, +-603, -1112, -695, -1394, -468, -924, 26, -16, +409, 1212, 859, 1831, 1003, 1403, 498, 226, +-253, -1208, -847, -2074, -1019, -1793, -430, -414, +379, 1185, 758, 2126, 616, 1919, -54, 476, +-733, -1238, -786, -2156, -162, -1801, 772, -342, +1455, 1295, 1247, 2132, 187, 1561, -1180, 48, +-2189, -1416, -1989, -2118, -659, -1487, 1188, 55, +2759, 1462, 2802, 2092, 1264, 1581, -858, 144, +-2580, -1305, -2882, -1969, -1628, -1649, 269, -500, +1801, 824, 2277, 1454, 1596, 1275, 458, 584, +-565, -238, -1238, -558, -1195, -376, -704, -202, +-175, -186, 234, -442, 377, -744, 355, -578, +367, 89, 501, 942, 609, 1490, 598, 1354, +124, 512, -805, -675, -1380, -1582, -1373, -1793, +-650, -1242, 657, -131, 1590, 1014, 1718, 1583, +1070, 1456, -159, 756, -1179, -171, -1362, -756, +-962, -981, -263, -842, 499, -522, 770, -327, +639, 44, 340, 423, -43, 757, -136, 1025, +-5, 733, 79, 93, 81, -609, -70, -1128, +-441, -1038, -656, -455, -411, 235, 129, 779, +785, 894, 1015, 561, 662, 16, 55, -503, +-656, -727, -882, -540, -453, -12, 3, 583, +316, 826, 329, 504, -35, -230, -158, -1007, +71, -1312, 400, -737, 801, 323, 757, 1322, +30, 1827, -808, 1254, -1410, 33, -1331, -1164, +-420, -1986, 670, -1829, 1487, -864, 1675, 358, +1080, 1490, 95, 1965, -781, 1612, -1242, 649, +-1194, -563, -812, -1473, -309, -1718, 287, -1314, +738, -462, 1018, 411, 1133, 1015, 954, 1294, +482, 1099, -350, 625, -1185, -3, -1639, -738, +-1496, -1186, -724, -1217, 443, -865, 1547, -158, +2023, 630, 1791, 1151, 782, 1319, -551, 1021, +-1501, 224, -2006, -675, -1829, -1394, -885, -1609, +276, -1060, 1455, -62, 2370, 1034, 2320, 1719, +1382, 1593, -261, 826, -2116, -415, -2980, -1575, +-2488, -1974, -851, -1510, 1327, -203, 2757, 1383, +2771, 2222, 1600, 1884, -167, 491, -1590, -1304, +-2126, -2326, -1790, -1981, -791, -604, 410, 1079, +1312, 2093, 1689, 1897, 1387, 787, 501, -636, +-518, -1652, -1271, -1863, -1344, -1246, -813, -88, +-24, 1006, 734, 1706, 1131, 1675, 1179, 863, +767, -233, -15, -1279, -857, -1879, -1492, -1643, +-1437, -739, -560, 473, 750, 1662, 1920, 2135, +2134, 1607, 1062, 408, -554, -1171, -1977, -2273, +-2336, -2196, -1220, -1142, 476, 521, 1890, 1914, +2233, 2212, 1251, 1465, -276, 22, -1450, -1274, +-1740, -1741, -1010, -1436, 183, -515, 1016, 427, +1264, 925, 816, 1058, 21, 804, -424, 329, +-487, -149, -314, -602, -134, -919, -124, -895, +-167, -478, -133, 138, 147, 755, 580, 1044, +885, 794, 760, 205, 139, -508, -610, -984, +-1112, -950, -1016, -543, -380, 120, 454, 745, +1070, 978, 1035, 815, 595, 309, -36, -422, +-661, -954, -839, -1118, -570, -888, -17, -157, +582, 666, 805, 1208, 496, 1314, -28, 747, +-536, -175, -727, -970, -329, -1404, 321, -1195, +798, -490, 737, 301, 175, 938, -405, 1197, +-666, 976, -523, 408, -70, -285, 444, -910, +659, -1189, 504, -1009, 144, -413, -250, 413, +-441, 1042, -384, 1290, -99, 938, 220, 40, +302, -811, 262, -1389, 146, -1335, 52, -513, +43, 446, 21, 1164, -22, 1373, -104, 837, +-221, -5, -216, -679, 6, -1069, 278, -1017, +498, -559, 500, -32, 223, 489, -126, 853, +-505, 848, -685, 490, -500, -114, -40, -615, +650, -760, 1091, -460, 976, 72, 443, 406, +-379, 324, -1142, -100, -1321, -483, -793, -500, +167, -28, 1154, 593, 1498, 887, 1053, 678, +238, -53, -622, -820, -1039, -1081, -847, -755, +-346, -45, 118, 618, 370, 814, 478, 486, +456, -11, 443, -344, 371, -383, 150, -163, +-130, 36, -455, -5, -602, -146, -503, -176, +-194, -47, 211, 280, 620, 544, 957, 404, +917, -22, 335, -586, -511, -931, -1156, -761, +-1287, -183, -606, 535, 517, 1004, 1386, 1011, +1634, 588, 913, -60, -239, -687, -1101, -1074, +-1462, -1111, -1017, -828, -107, -205, 705, 586, +1219, 1215, 1180, 1465, 734, 1147, 177, 254, +-486, -828, -1024, -1640, -1113, -1852, -787, -1259, +-121, -104, 740, 1112, 1333, 1935, 1421, 1908, +893, 977, -95, -411, -984, -1640, -1434, -2081, +-1160, -1506, -376, -249, 452, 1024, 1127, 1612, +1288, 1322, 936, 443, 451, -465, -203, -887, +-831, -748, -1044, -354, -1029, -6, -579, 84, +316, -50, 1060, -61, 1491, 160, 1310, 443, +359, 596, -747, 370, -1444, -211, -1406, -743, +-424, -928, 787, -582, 1489, 88, 1402, 623, +361, 840, -811, 564, -1350, 37, -1060, -360, +2, -603, 969, -565, 1259, -353, 945, -133, +177, 167, -514, 454, -684, 607, -540, 528, +-276, 171, -13, -349, 101, -791, 234, -880, +439, -576, 587, -18, 608, 584, 381, 927, +-54, 856, -475, 441, -666, -202, -468, -806, +-134, -1056, 161, -874, 381, -367, 388, 267, +378, 734, 395, 867, 335, 739, 221, 420, +-7, -27, -370, -512, -552, -939, -475, -1152, +-258, -936, 118, -242, 398, 627, 613, 1294, +785, 1412, 704, 887, 405, 0, -133, -871, +-794, -1305, -1186, -1274, -994, -830, -281, -65, +708, 603, 1416, 1045, 1452, 1104, 978, 662, +108, 46, -695, -487, -1120, -767, -1190, -719, +-828, -511, -206, -276, 532, -43, 1274, 196, +1618, 489, 1313, 685, 433, 577, -740, 165, +-1547, -403, -1528, -816, -782, -760, 331, -258, +1146, 350, 1218, 709, 830, 590, 302, 18, +-91, -591, -197, -839, -292, -632, -416, -15, +-490, 645, -406, 927, 28, 723, 590, 152, +914, -516, 782, -903, 269, -803, -248, -383, +-448, 110, -361, 442, -98, 392, 134, 113, +53, -27, -68, 3, -10, 154, 203, 351, +588, 224, 805, -198, 570, -571, 9, -803, +-591, -717, -982, -238, -813, 286, -158, 652, +551, 899, 1080, 835, 1089, 405, 612, -153, +8, -815, -507, -1333, -729, -1304, -620, -690, +-250, 346, 212, 1338, 664, 1773, 890, 1365, +646, 185, 85, -1179, -513, -2031, -764, -1909, +-489, -803, 117, 755, 734, 1844, 943, 1936, +678, 1079, 137, -345, -446, -1403, -693, -1577, +-556, -1088, -283, -210, 142, 501, 594, 666, +827, 562, 901, 412, 659, 285, 6, 258, +-654, 105, -1105, -348, -1095, -846, -335, -1075, +717, -811, 1467, -29, 1654, 833, 1004, 1281, +-189, 1003, -1142, 135, -1602, -720, -1300, -1123, +-241, -852, 784, -121, 1520, 491, 1794, 668, +1230, 413, 251, -110, -768, -491, -1621, -488, +-1671, -255, -886, 78, 233, 372, 1397, 445, +1913, 292, 1530, 24, 635, -299, -577, -561, +-1371, -625, -1338, -434, -667, -78, 364, 313, +1034, 669, 1044, 721, 587, 446, -51, 76, +-388, -446, -255, -837, 67, -824, 297, -610, +248, -168, -27, 353, -203, 644, -142, 703, +137, 546, 443, 237, 553, -126, 430, -428, +66, -626, -270, -759, -407, -674, -394, -314, +-128, 131, 267, 629, 572, 1003, 746, 883, +680, 419, 333, -176, -51, -829, -416, -1142, +-720, -1014, -671, -615, -332, 52, 200, 750, +841, 1160, 1193, 1146, 1084, 656, 597, -194, +-152, -1024, -842, -1400, -1130, -1176, -919, -485, +-231, 365, 602, 995, 1181, 1120, 1321, 791, +846, 261, 34, -393, -630, -896, -930, -969, +-644, -754, 33, -249, 579, 444, 775, 790, +509, 693, 13, 339, -247, -226, -227, -578, +13, -514, 394, -265, 567, 50, 407, 234, +90, 154, -305, -19, -468, -129, -297, -145, +-63, -51, 290, 82, 633, 111, 746, 18, +656, -117, 313, -195, -194, -156, -587, -37, +-722, 114, -497, 137, 80, -26, 667, -193, +990, -277, 845, -200, 380, 116, -94, 375, +-490, 325, -498, 40, -237, -410, 7, -700, +239, -473, 351, 91, 402, 657, 470, 835, +462, 395, 285, -378, -20, -1016, -399, -1086, +-646, -530, -463, 276, 131, 941, 814, 1088, +1159, 697, 911, 111, 144, -472, -711, -899, +-1025, -1024, -676, -859, 13, -467, 788, 122, +1109, 763, 848, 1149, 421, 1145, -141, 708, +-624, -81, -680, -893, -483, -1401, -64, -1418, +621, -862, 1005, 89, 939, 940, 576, 1367, +-189, 1197, -777, 456, -754, -368, -360, -949, +240, -1125, 702, -818, 732, -317, 515, 218, +219, 684, -1, 874, -30, 782, -77, 322, +-157, -414, -267, -1011, -259, -1246, 90, -975, +447, -125, 729, 755, 754, 1235, 340, 1312, +-125, 755, -457, -137, -495, -860, -123, -1397, +304, -1452, 482, -876, 468, -67, 239, 791, +-93, 1411, -161, 1369, 39, 794, 323, 11, +498, -752, 322, -1204, -130, -1227, -457, -953, +-413, -429, -4, 287, 655, 973, 1066, 1380, +833, 1269, 181, 536, -590, -558, -1053, -1467, +-808, -1708, -102, -1156, 663, -68, 1198, 968, +1184, 1439, 700, 1233, 99, 499, -499, -369, +-839, -962, -720, -1152, -384, -934, 86, -413, +537, 237, 755, 740, 829, 921, 684, 796, +340, 312, -39, -304, -381, -759, -497, -959, +-371, -795, -153, -324, 207, 261, 518, 719, +522, 825, 368, 534, 106, -17, -91, -542, +38, -702, 233, -461, 307, -56, 238, 280, +10, 265, -189, -31, -183, -245, 48, -284, +245, -74, 294, 244, 246, 325, 64, 251, +-15, 41, 107, -247, 234, -384, 304, -442, +294, -370, 130, -105, 2, 220, 51, 524, +45, 582, -36, 258, -116, -281, -226, -769, +-170, -893, 188, -514, 620, 201, 938, 872, +998, 1109, 540, 723, -284, -137, -1024, -1031, +-1341, -1496, -956, -1253, 108, -350, 1211, 785, +1741, 1563, 1562, 1594, 654, 880, -551, -293, +-1334, -1358, -1397, -1802, -785, -1492, 234, -545, +1126, 618, 1455, 1438, 1187, 1576, 444, 1016, +-450, 38, -987, -912, -977, -1351, -482, -1153, +346, -540, 1023, 198, 1147, 696, 761, 794, +22, 569, -649, 151, -802, -266, -455, -532, +102, -595, 638, -434, 834, -69, 618, 304, +332, 509, -17, 458, -316, 113, -399, -309, +-426, -567, -251, -574, 155, -262, 602, 105, +894, 313, 829, 389, 388, 195, -214, -28, +-618, -113, -603, -184, -290, -53, 133, 102, +477, 15, 502, -176, 415, -507, 275, -774, +126, -527, 165, 168, 129, 1000, 13, 1506, +-133, 1128, -296, -62, -267, -1386, -72, -2066, +227, -1612, 559, -265, 717, 1194, 630, 1908, +333, 1470, -93, 310, -424, -865, -632, -1424, +-680, -1093, -312, -283, 307, 446, 904, 691, +1287, 400, 1117, -54, 434, -296, -422, -185, +-1124, 118, -1272, 282, -753, 110, 121, -307, +937, -583, 1312, -483, 1140, -104, 557, 349, +-66, 542, -449, 366, -643, 75, -617, -155, +-385, -293, -70, -317, 327, -339, 728, -372, +865, -210, 710, 112, 314, 452, -241, 632, +-564, 428, -522, -13, -253, -450, 99, -721, +367, -627, 433, -304, 430, 66, 428, 441, +278, 621, 46, 548, -224, 241, -442, -279, +-392, -734, -17, -829, 412, -521, 611, 52, +582, 586, 261, 727, -90, 462, -184, 7, +-124, -381, 29, -492, 99, -384, -12, -212, +-110, -56, 17, 52, 313, 123, 559, 188, +529, 205, 164, 85, -271, -71, -480, -156, +-316, -156, 135, -25, 563, 63, 659, -48, +352, -250, -118, -408, -420, -351, -427, -27, +-158, 389, 251, 643, 560, 567, 632, 169, +456, -339, 113, -691, -202, -796, -348, -561, +-309, -69, -86, 408, 160, 702, 253, 644, +225, 247, 163, -266, 179, -623, 257, -583, +272, -249, 185, 146, -7, 388, -195, 267, +-203, -17, -44, -231, 116, -323, 190, -146, +100, 85, -26, 148, 40, 129, 250, -34, +483, -185, 523, -156, 225, -43, -220, 134, +-528, 264, -475, 146, -130, -145, 255, -456, +446, -621, 404, -400, 308, 112, 164, 620, +122, 867, 147, 594, -3, -64, -183, -720, +-323, -1042, -340, -796, -24, -173, 402, 473, +595, 824, 603, 697, 363, 264, -96, -189, +-397, -461, -502, -551, -388, -461, 43, -296, +462, -131, 666, 160, 682, 472, 379, 651, +-101, 584, -462, 182, -630, -420, -513, -904, +-115, -1004, 401, -670, 797, 6, 879, 691, +600, 1046, 53, 971, -430, 443, -670, -319, +-669, -906, -331, -1139, 203, -888, 609, -212, +786, 462, 676, 869, 306, 868, -102, 477, +-417, -22, -535, -435, -388, -636, -68, -622, +251, -484, 457, -209, 511, 146, 402, 488, +208, 708, -11, 599, -227, 196, -381, -311, +-371, -735, -144, -791, 223, -492, 568, -65, +693, 363, 504, 544, 39, 455, -449, 275, +-667, -6, -480, -210, 54, -266, 537, -309, +659, -273, 451, -244, 82, -231, -202, -92, +-169, 127, 25, 411, 114, 632, 84, 573, +-149, 198, -348, -391, -220, -912, 102, -1043, +515, -706, 812, -22, 709, 742, 281, 1178, +-262, 1060, -767, 425, -912, -450, -618, -1122, +-46, -1288, 626, -827, 1036, 36, 1019, 783, +626, 1097, 9, 855, -536, 215, -792, -364, +-729, -684, -364, -723, 132, -536, 511, -313, +690, -26, 637, 380, 365, 753, 6, 876, +-309, 561, -467, -157, -324, -861, 9, -1090, +318, -731, 458, -30, 289, 498, -30, 504, +-287, 155, -298, -135, -25, -49, 307, 366, +468, 698, 379, 550, 107, -107, -233, -908, +-352, -1389, -238, -1246, -5, -513, 286, 458, +381, 1268, 289, 1610, 119, 1334, -109, 513, +-257, -558, -205, -1434, -18, -1749, 211, -1364, +327, -428, 249, 601, 127, 1285, 23, 1389, +-5, 932, -26, 210, -151, -451, -271, -859, +-236, -904, 32, -643, 442, -267, 734, 149, +604, 448, 59, 482, -599, 363, -963, 114, +-648, -135, 215, -176, 1014, -92, 1246, 15, +695, 24, -336, -147, -1113, -335, -1138, -381, +-463, -180, 458, 197, 1067, 453, 962, 474, +380, 244, -210, -94, -598, -282, -480, -333, +-62, -303, 193, -231, 318, -191, 234, -65, +7, 212, -108, 470, -182, 574, -166, 380, +47, -94, 316, -550, 497, -792, 448, -654, +137, -212, -234, 254, -463, 599, -446, 653, +-242, 446, 65, 149, 333, -204, 441, -435, +430, -478, 284, -444, 71, -300, -148, -117, +-337, 40, -360, 258, -198, 516, 117, 664, +369, 591, 411, 183, 255, -507, -36, -1100, +-234, -1202, -251, -647, -118, 364, 103, 1244, +284, 1441, 300, 788, 158, -377, -25, -1301, +-169, -1414, -191, -696, -81, 371, 55, 1105, +160, 1085, 200, 450, 130, -298, 7, -687, +-62, -555, -10, -173, 108, 77, 155, 44, +61, -185, -100, -300, -211, -83, -165, 349, +75, 704, 329, 699, 388, 273, 231, -330, +-55, -750, -280, -763, -270, -426, -121, 13, +43, 257, 162, 218, 164, 59, 184, -5, +241, 183, 240, 488, 130, 616, -163, 393, +-463, -194, -510, -842, -233, -1165, 233, -951, +641, -265, 719, 535, 435, 1064, -13, 1076, +-405, 612, -546, -31, -405, -569, -162, -756, +17, -594, 141, -300, 244, 11, 392, 219, +576, 281, 606, 317, 351, 321, -178, 179, +-804, -91, -1180, -435, -1015, -675, -324, -535, +674, -38, 1471, 603, 1617, 1028, 1056, 890, +-11, 266, -1057, -554, -1597, -1124, -1425, -1132, +-668, -697, 346, -27, 1152, 575, 1443, 885, +1168, 932, 422, 700, -411, 263, -996, -233, +-1111, -696, -719, -932, -73, -805, 500, -408, +872, 91, 879, 503, 505, 670, -4, 578, +-571, 307, -923, -40, -832, -349, -333, -477, +477, -329, 1209, 44, 1352, 418, 718, 499, +-360, 138, -1321, -489, -1586, -951, -935, -888, +183, -203, 1185, 743, 1570, 1374, 1083, 1309, +131, 535, -709, -530, -1100, -1323, -859, -1473, +-245, -914, 312, 26, 623, 867, 589, 1238, +280, 965, -53, 254, -251, -451, -276, -804, +-130, -681, 47, -225, 149, 163, 195, 282, +170, 202, 118, 36, -10, 33, -217, 147, +-311, 138, -270, 3, -32, -247, 331, -396, +515, -214, 466, 123, 160, 374, -320, 324, +-606, -32, -523, -354, -108, -371, 452, -47, +723, 390, 582, 528, 112, 249, -482, -264, +-807, -670, -723, -627, -212, -189, 512, 331, +1036, 643, 1007, 553, 439, 202, -369, -134, +-985, -327, -1004, -316, -538, -228, 156, -191, +713, -151, 795, -46, 460, 162, -22, 384, +-346, 453, -325, 281, -83, -84, 108, -388, +133, -445, 26, -258, -72, 73, -97, 268, +-6, 208, 72, 21, 2, -179, -100, -225, +-199, -62, -91, 136, 286, 242, 603, 226, +650, 87, 311, -74, -355, -166, -885, -192, +-967, -168, -586, -114, 127, -49, 706, 31, +894, 122, 757, 182, 376, 172, -46, 109, +-343, 12, -570, -82, -695, -120, -561, -133, +-251, -139, 202, -110, 646, -35, 802, 84, +645, 206, 247, 231, -236, 96, -581, -119, +-660, -244, -501, -188, -186, 4, 154, 184, +454, 179, 567, -20, 436, -222, 200, -229, +-99, -4, -290, 335, -292, 491, -249, 295, +-202, -124, -185, -581, -212, -787, -72, -557, +281, -56, 695, 528, 942, 972, 701, 983, +-18, 564, -861, -133, -1405, -866, -1306, -1216, +-539, -990, 500, -341, 1337, 442, 1598, 927, +1132, 888, 203, 485, -772, 9, -1405, -253, +-1393, -249, -786, -142, 91, -122, 883, -276, +1217, -436, 979, -416, 375, -170, -298, 254, +-738, 618, -787, 738, -529, 589, -155, 203, +192, -251, 418, -633, 462, -794, 382, -629, +223, -209, -16, 323, -181, 692, -305, 686, +-443, 365, -428, -110, -277, -459, 24, -451, +441, -205, 722, 79, 688, 249, 369, 173, +-172, -31, -707, -139, -853, -110, -623, 37, +-103, 198, 410, 200, 542, 22, 389, -204, +165, -337, 20, -273, 77, 18, 171, 361, +60, 514, -215, 391, -617, -8, -821, -482, +-561, -696, 78, -528, 838, -13, 1220, 571, +961, 827, 179, 594, -707, -15, -1228, -615, +-1074, -826, -380, -547, 438, 68, 980, 579, +875, 646, 301, 334, -343, -129, -699, -419, +-514, -325, -31, -32, 359, 200, 476, 227, +187, 25, -270, -204, -494, -221, -436, -55, +-21, 168, 405, 294, 475, 151, 284, -124, +-64, -311, -278, -297, -205, -13, -34, 344, +59, 512, -38, 374, -301, -42, -434, -493, +-222, -695, 283, -522, 805, -48, 915, 454, +456, 690, -349, 541, -1062, 121, -1260, -286, +-813, -452, 48, -313, 881, 6, 1271, 224, +1033, 189, 326, -20, -495, -256, -1025, -305, +-1023, -97, -592, 191, 51, 396, 535, 377, +649, 150, 488, -113, 126, -288, -166, -280, +-255, -151, -208, -14, -52, 91, 47, 96, +-1, 57, -100, 31, -229, -25, -310, -35, +-184, 0, 75, 23, 398, 116, 623, 191, +519, 143, 145, 24, -356, -180, -741, -379, +-796, -402, -504, -225, -39, 84, 398, 398, +624, 532, 604, 418, 407, 125, 88, -176, +-207, -331, -445, -333, -559, -197, -502, -86, +-322, -68, -45, -29, 273, 24, 495, 143, +552, 316, 388, 380, 38, 295, -295, 109, +-544, -118, -558, -312, -328, -421, -5, -444, +345, -365, 458, -139, 278, 210, 4, 545, +-240, 701, -316, 575, -186, 181, -46, -274, +92, -563, 162, -616, 75, -456, -10, -165, +-96, 123, -156, 374, -102, 537, -11, 479, +49, 191, 100, -188, 25, -478, -156, -455, +-247, -108, -210, 258, 12, 377, 324, 144, +439, -247, 275, -430, -89, -235, -486, 212, +-602, 560, -427, 534, -95, 153, 274, -332, +425, -597, 404, -526, 249, -236, 4, 114, +-187, 378, -326, 479, -376, 438, -304, 257, +-124, -44, 97, -354, 231, -528, 183, -471, +36, -189, -50, 157, 8, 373, 118, 381, +143, 224, -3, 16, -275, -107, -474, -116, +-459, -78, -158, -23, 250, -18, 472, -76, +412, -102, 108, -66, -205, 30, -299, 179, +-193, 252, -30, 157, 53, -47, -19, -270, +-189, -344, -312, -183, -249, 110, 30, 366, +407, 429, 596, 278, 399, 0, -84, -260, +-596, -395, -803, -436, -567, -356, -39, -140, +513, 163, 750, 521, 523, 738, 2, 619, +-503, 187, -686, -389, -507, -783, -134, -736, +241, -314, 449, 194, 437, 459, 211, 352, +-109, 53, -401, -155, -507, -82, -336, 205, +-22, 402, 293, 312, 406, -46, 216, -443, +-131, -555, -407, -310, -458, 73, -211, 339, +151, 265, 378, -64, 405, -301, 216, -228, +-58, 158, -305, 596, -441, 727, -471, 389, +-392, -239, -173, -768, 132, -892, 481, -546, +677, 11, 579, 423, 169, 524, -363, 364, +-741, 148, -780, 76, -474, 156, -78, 191, +224, 42, 327, -274, 278, -594, 241, -629, +285, -291, 270, 232, 101, 647, -262, 671, +-705, 279, -861, -256, -639, -577, -87, -465, +556, -2, 907, 499, 800, 713, 317, 477, +-285, -81, -737, -630, -824, -895, -579, -712, +-146, -182, 289, 394, 503, 787, 429, 830, +206, 531, -34, 131, -202, -207, -218, -412, +-182, -444, -170, -428, -180, -418, -231, -328, +-209, -111, 2, 255, 239, 662, 380, 872, +389, 708, 150, 189, -180, -437, -425, -847, +-557, -791, -426, -304, -72, 253, 228, 563, +397, 418, 337, -56, 28, -440, -248, -465, +-378, -77, -299, 482, 18, 811, 277, 713, +288, 230, 79, -357, -251, -746, -427, -821, +-358, -601, -137, -216, 136, 182, 297, 509, +293, 681, 151, 636, -72, 418, -286, 87, +-394, -250, -364, -440, -174, -478, 109, -400, +323, -224, 382, -27, 237, 155, -38, 304, +-276, 353, -370, 290, -341, 158, -259, -2, +-216, -126, -163, -185, 27, -196, 328, -167, +625, -70, 680, 84, 359, 217, -228, 275, +-818, 170, -1096, -63, -887, -255, -302, -318, +356, -226, 788, -32, 816, 126, 499, 218, +93, 300, -210, 376, -386, 378, -397, 212, +-380, -166, -417, -610, -385, -838, -255, -681, +62, -173, 511, 438, 781, 832, 662, 865, +176, 576, -491, 142, -950, -274, -890, -599, +-385, -746, 302, -651, 745, -288, 652, 268, +187, 740, -296, 856, -557, 545, -476, -59, +-215, -595, -20, -734, 99, -456, 147, 57, +192, 477, 249, 561, 231, 313, 60, -64, +-243, -319, -519, -329, -607, -114, -420, 147, +-62, 251, 273, 152, 458, -72, 462, -257, +292, -238, 52, -19, -212, 250, -433, 412, +-483, 357, -407, 91, -214, -220, 11, -419, +168, -414, 258, -204, 281, 96, 231, 342, +108, 402, -44, 264, -223, 20, -349, -186, +-371, -221, -297, -125, -161, -4, -38, 48, +82, 11, 206, -1, 312, 106, 366, 260, +282, 296, 7, 87, -367, -323, -668, -656, +-725, -599, -462, -95, -7, 573, 415, 999, +626, 870, 543, 244, 255, -473, -77, -900, +-317, -823, -421, -364, -429, 123, -382, 423, +-307, 455, -145, 316, 119, 213, 408, 191, +601, 178, 554, 86, 214, -159, -306, -454, +-770, -606, -918, -500, -631, -127, -66, 350, +504, 678, 769, 695, 629, 398, 215, -39, +-275, -370, -571, -467, -542, -316, -292, -49, +-13, 150, 143, 201, 86, 89, -26, -90, +-58, -184, -46, -110, 59, 108, 183, 360, +206, 478, 120, 330, -55, -6, -312, -342, +-506, -490, -537, -365, -424, -108, -90, 71, +356, 67, 692, -28, 737, 1, 409, 280, +-145, 678, -627, 847, -817, 532, -670, -203, +-272, -994, 131, -1348, 347, -1008, 344, -187, +232, 650, 128, 1121, 66, 1055, 17, 641, +-77, 173, -215, -212, -379, -475, -484, -663, +-434, -755, -191, -610, 187, -179, 560, 445, +742, 975, 577, 1062, 73, 626, -590, -167, +-1074, -912, -1085, -1153, -565, -763, 259, 82, +960, 933, 1156, 1276, 751, 927, -16, 70, +-718, -833, -1002, -1241, -796, -947, -301, -155, +163, 661, 367, 1029, 290, 796, 114, 174, +29, -416, 94, -629, 205, -400, 181, 45, +-62, 403, -423, 459, -645, 212, -588, -133, +-261, -376, 176, -384, 471, -175, 501, 101, +296, 287, 19, 290, -166, 145, -231, 6, +-262, -1, -311, 112, -344, 228, -278, 175, +-52, -109, 245, -457, 448, -611, 434, -386, +183, 156, -167, 679, -450, 828, -532, 480, +-406, -163, -192, -671, 41, -709, 226, -262, +359, 361, 413, 740, 276, 650, -23, 159, +-376, -400, -602, -676, -583, -575, -327, -186, +44, 250, 338, 487, 437, 503, 322, 354, +98, 146, -106, -27, -246, -171, -306, -280, +-272, -322, -179, -274, -68, -109, 20, 132, +31, 327, 3, 390, -1, 306, 36, 120, +128, -73, 169, -204, 36, -242, -203, -195, +-409, -73, -440, 91, -240, 210, 80, 246, +330, 159, 381, -5, 222, -115, -51, -110, +-257, -1, -342, 99, -311, 87, -206, -35, +-105, -160, 16, -137, 117, 60, 183, 304, +180, 417, 114, 273, 18, -67, -86, -395, +-186, -515, -320, -352, -396, 23, -330, 406, +-123, 620, 187, 547, 421, 216, 414, -210, +181, -538, -164, -575, -417, -323, -412, 75, +-210, 410, 4, 502, 112, 360, 67, 130, +-54, -38, -87, -86, -32, -87, 46, -134, +78, -239, -25, -325, -184, -266, -261, -5, +-202, 360, -11, 652, 206, 690, 271, 416, +141, -59, -110, -524, -368, -741, -439, -608, +-288, -190, -15, 283, 250, 532, 313, 485, +166, 221, -70, -43, -273, -101, -295, 19, +-157, 159, 25, 135, 171, -70, 172, -295, +40, -353, -122, -152, -281, 167, -362, 361, +-300, 291, -160, 32, 45, -206, 270, -221, +409, 9, 397, 304, 186, 448, -159, 322, +-474, 0, -610, -310, -520, -438, -262, -351, +39, -148, 232, 54, 298, 174, 293, 237, +260, 319, 218, 399, 94, 392, -169, 205, +-496, -175, -752, -581, -742, -751, -369, -519, +221, 70, 760, 706, 959, 1015, 655, 779, +0, 78, -672, -672, -1060, -1045, -924, -825, +-363, -124, 261, 637, 674, 1043, 674, 897, +336, 321, -65, -324, -333, -688, -360, -634, +-239, -282, -164, 116, -206, 328, -301, 299, +-287, 121, -84, -46, 245, -68, 554, 52, +641, 229, 377, 337, -111, 265, -612, 16, +-898, -300, -798, -505, -411, -458, 104, -139, +550, 275, 690, 527, 523, 495, 165, 214, +-213, -84, -424, -179, -421, -58, -298, 116, +-163, 105, -121, -143, -178, -432, -171, -486, +-23, -152, 260, 420, 535, 864, 560, 877, +274, 418, -266, -268, -799, -794, -1001, -900, +-769, -571, -163, -20, 537, 468, 951, 713, +877, 652, 367, 379, -327, 37, -849, -245, +-946, -359, -613, -311, -58, -156, 405, 17, +554, 124, 391, 156, 71, 129, -187, 88, +-272, 52, -223, 21, -134, -5, -111, -11, +-141, 14, -179, 78, -146, 154, -13, 176, +133, 128, 243, 22, 230, -108, 96, -217, +-112, -264, -347, -219, -479, -99, -439, 112, +-219, 349, 96, 486, 347, 477, 411, 285, +270, -11, -15, -260, -285, -379, -384, -348, +-323, -240, -178, -125, -70, -31, -57, 86, +-20, 280, 62, 492, 141, 578, 183, 442, +94, 83, -102, -352, -285, -591, -336, -538, +-203, -260, 15, 84, 139, 306, 93, 378, +-69, 357, -236, 291, -286, 165, -168, -67, +62, -325, 239, -449, 261, -288, 159, 129, +-50, 547, -270, 650, -399, 323, -421, -220, +-276, -618, -54, -590, 117, -188, 223, 276, +228, 501, 155, 411, 43, 188, -74, 32, +-172, 33, -241, 65, -279, -23, -273, -226, +-220, -410, -128, -390, 4, -125, 136, 264, +266, 564, 342, 634, 241, 471, -14, 147, +-384, -222, -690, -527, -669, -668, -315, -558, +222, -177, 625, 364, 615, 811, 221, 931, +-329, 637, -665, 58, -562, -514, -162, -791, +243, -699, 389, -372, 182, 36, -143, 342, +-330, 507, -310, 589, -97, 559, 78, 389, +69, 77, -19, -324, -107, -655, -84, -728, +61, -491, 123, -22, 17, 472, -198, 738, +-406, 677, -419, 325, -201, -115, 108, -397, +363, -409, 403, -162, 202, 167, -91, 343, +-350, 239, -463, -80, -407, -395, -233, -459, +30, -145, 248, 371, 315, 764, 218, 753, +-31, 278, -300, -388, -431, -837, -356, -761, +-71, -207, 259, 467, 386, 844, 219, 703, +-138, 160, -499, -399, -610, -605, -366, -393, +77, 49, 465, 393, 519, 407, 213, 164, +-218, -117, -518, -209, -519, -68, -226, 157, +156, 260, 339, 135, 230, -104, -75, -274, +-359, -231, -413, 27, -233, 315, 83, 427, +329, 305, 332, 18, 96, -268, -264, -390, +-513, -317, -495, -94, -219, 170, 176, 369, +450, 445, 402, 360, 88, 164, -291, -76, +-533, -272, -489, -327, -231, -260, 82, -121, +291, 31, 283, 132, 138, 197, -44, 244, +-187, 270, -236, 248, -256, 147, -220, -24, +-118, -193, -27, -270, 72, -208, 115, -38, +65, 128, 5, 191, -70, 126, -132, -12, +-133, -103, -144, -65, -140, 109, -74, 288, +-39, 351, -9, 236, 6, -33, -53, -277, +-65, -361, -47, -243, -17, -3, 35, 202, +-13, 260, -138, 171, -245, 46, -265, -19, +-110, 2, 114, 73, 210, 102, 154, 45, +-40, -41, -243, -59, -275, 10, -162, 128, +7, 191, 92, 95, -15, -131, -172, -340, +-244, -359, -159, -120, 66, 291, 243, 627, +262, 659, 85, 370, -219, -84, -448, -450, +-479, -540, -288, -381, 26, -129, 307, 54, +422, 146, 288, 222, -47, 334, -389, 456, +-550, 451, -428, 214, -70, -180, 279, -525, +422, -632, 277, -418, -101, -5, -424, 382, +-461, 567, -231, 493, 92, 251, 253, -40, +145, -239, -116, -282, -320, -197, -271, -31, +-3, 118, 257, 170, 302, 134, 81, 75, +-260, 50, -467, 67, -426, 79, -181, 19, +106, -106, 220, -198, 157, -166, 24, 1, +-61, 227, -32, 379, 21, 362, 4, 217, +-116, 1, -291, -220, -396, -375, -322, -445, +-81, -360, 181, -77, 334, 336, 319, 711, +145, 814, -81, 530, -257, -35, -329, -598, +-304, -853, -213, -680, -97, -194, 4, 342, +87, 665, 113, 660, 97, 395, 70, 38, +30, -228, -38, -329, -140, -287, -236, -154, +-314, -18, -288, 95, -117, 168, 114, 200, +296, 208, 306, 165, 94, 73, -198, -57, +-400, -170, -404, -194, -193, -102, 73, 64, +232, 217, 206, 261, 21, 145, -168, -39, +-227, -184, -156, -187, -18, -16, 53, 192, +1, 294, -111, 202, -241, -40, -238, -266, +-57, -293, 163, -66, 324, 252, 293, 460, +46, 389, -269, 41, -529, -343, -602, -515, +-380, -360, 9, 32, 378, 427, 583, 579, +477, 411, 134, 52, -288, -286, -594, -423, +-594, -299, -336, -9, 28, 264, 303, 380, +328, 279, 142, 10, -108, -265, -276, -372, +-242, -225, -63, 98, 109, 419, 184, 529, +102, 317, -98, -69, -261, -400, -319, -462, +-243, -202, -71, 172, 70, 394, 161, 322, +177, 35, 86, -241, -35, -276, -140, -48, +-206, 251, -198, 384, -141, 237, -52, -68, +57, -300, 87, -261, 36, 19, -35, 305, +-120, 374, -162, 128, -141, -272, -88, -535, +-11, -443, 37, -2, 68, 519, 98, 825, +75, 710, -8, 204, -144, -400, -296, -791, +-357, -775, -268, -365, -82, 182, 158, 568, +341, 642, 340, 422, 203, 102, -33, -123, +-277, -183, -416, -133, -446, -124, -340, -187, +-99, -227, 172, -143, 379, 115, 418, 435, +224, 590, -91, 442, -376, 24, -490, -431, +-355, -647, -81, -491, 168, -50, 271, 409, +182, 618, 10, 482, -132, 101, -205, -282, +-174, -429, -109, -296, -53, 6, 4, 273, +35, 339, 46, 200, 36, -32, -9, -192, +-73, -193, -131, -48, -162, 136, -144, 228, +-88, 182, -25, 29, 37, -141, 80, -234, +98, -179, 64, 3, -22, 221, -105, 385, +-167, 379, -186, 174, -169, -139, -145, -416, +-95, -506, 3, -350, 130, 9, 254, 397, +271, 614, 111, 549, -178, 224, -458, -197, +-517, -483, -285, -477, 88, -212, 397, 144, +432, 363, 138, 309, -248, 66, -475, -175, +-383, -232, -31, -61, 276, 211, 361, 377, +184, 302, -150, 41, -382, -245, -364, -386, +-151, -304, 105, -78, 193, 150, 77, 278, +-79, 274, -171, 180, -114, 71, 85, -25, +222, -93, 177, -116, -47, -95, -333, -26, +-456, 53, -340, 107, -37, 95, 293, 14, +404, -55, 245, -66, -65, -22, -338, 50, +-391, 95, -191, 80, 103, 55, 308, 66, +290, 107, 42, 129, -273, 45, -491, -138, +-467, -318, -187, -353, 184, -158, 461, 177, +507, 467, 281, 533, -88, 304, -419, -70, +-563, -364, -445, -418, -158, -218, 160, 89, +368, 305, 361, 303, 176, 108, -85, -143, +-306, -300, -360, -259, -245, -35, -9, 236, +216, 404, 248, 388, 98, 177, -117, -119, +-258, -336, -204, -384, -20, -257, 135, -32, +138, 178, -28, 283, -244, 277, -316, 196, +-184, 76, 97, -45, 347, -131, 376, -164, +199, -140, -105, -53, -395, 49, -508, 112, +-423, 127, -197, 96, 106, 49, 356, 19, +462, 12, 380, -7, 103, -56, -217, -93, +-417, -80, -442, 5, -299, 137, -65, 219, +114, 165, 191, -10, 160, -205, 74, -290, +36, -166, 5, 102, -42, 333, -94, 374, +-149, 185, -155, -97, -109, -271, -45, -233, +11, -47, 22, 97, -6, 82, -18, -71, +-5, -190, 23, -97, 71, 198, 84, 502, +32, 570, -82, 288, -227, -225, -308, -672, +-249, -791, -59, -499, 188, 37, 357, 541, +319, 787, 85, 656, -220, 261, -399, -197, +-324, -526, -77, -570, 170, -347, 247, -1, +93, 299, -141, 404, -278, 288, -206, 64, +50, -134, 264, -186, 278, -115, 91, -20, +-196, 47, -361, 54, -300, 53, -85, 93, +163, 121, 248, 93, 106, -18, -94, -175, +-201, -262, -141, -189, 64, 21, 215, 244, +172, 349, -41, 276, -311, 80, -409, -121, +-244, -226, 63, -221, 341, -157, 400, -57, +191, 48, -128, 138, -353, 203, -356, 200, +-155, 114, 71, -8, 185, -84, 138, -75, +-23, -9, -128, 34, -120, -29, -34, -172, +97, -270, 145, -192, 68, 71, -73, 402, +-219, 583, -260, 462, -170, 96, -29, -328, +118, -595, 218, -578, 202, -311, 105, 63, +-3, 373, -134, 524, -236, 471, -270, 254, +-225, -39, -75, -299, 109, -417, 254, -347, +285, -133, 151, 99, -81, 244, -243, 255, +-255, 173, -131, 74, 37, -3, 110, -52, +47, -97, -102, -131, -176, -118, -83, -51, +101, 59, 253, 140, 248, 130, 55, 55, +-209, -25, -370, -53, -334, -15, -122, 35, +120, 35, 239, -18, 202, -79, 65, -82, +-48, -8, -44, 86, 15, 149, 32, 124, +-39, 29, -198, -72, -330, -150, -312, -172, +-100, -120, 215, -7, 456, 143, 496, 280, +287, 319, -84, 196, -426, -61, -566, -314, +-462, -414, -186, -297, 130, -26, 341, 218, +376, 288, 246, 192, 48, 43, -95, -7, +-140, 80, -127, 174, -93, 129, -91, -89, +-148, -353, -170, -471, -126, -323, -30, 20, +142, 334, 286, 448, 318, 351, 223, 155, +-10, -3, -263, -54, -398, -72, -388, -152, +-216, -277, 50, -360, 235, -283, 286, -23, +205, 292, 44, 492, -48, 470, -68, 263, +-47, -18, -39, -253, -151, -351, -274, -331, +-257, -234, -109, -69, 171, 112, 426, 246, +439, 294, 249, 226, -106, 85, -457, -49, +-542, -127, -392, -140, -110, -121, 223, -100, +398, -67, 389, -1, 278, 123, 50, 238, +-168, 245, -322, 106, -421, -134, -349, -341, +-133, -353, 116, -122, 348, 220, 430, 468, +303, 443, 50, 131, -247, -285, -417, -547, +-360, -462, -156, -91, 108, 327, 282, 539, +253, 405, 100, 47, -74, -283, -183, -400, +-148, -269, -57, -17, 6, 167, 43, 193, +25, 121, 24, 51, 69, 38, 71, 51, +22, 12, -89, -102, -230, -218, -249, -215, +-92, -67, 135, 161, 305, 329, 289, 296, +91, 78, -152, -196, -307, -360, -274, -295, +-96, -40, 74, 257, 144, 411, 119, 314, +48, 30, 22, -288, 40, -459, 45, -361, +-24, -64, -187, 254, -299, 436, -239, 384, +-12, 146, 287, -115, 467, -279, 380, -304, +55, -212, -351, -56, -586, 104, -490, 222, +-140, 271, 273, 199, 518, -2, 435, -223, +121, -327, -192, -242, -337, 23, -254, 307, +-58, 407, 94, 252, 101, -62, -32, -325, +-135, -377, -99, -205, 42, 52, 216, 214, +263, 226, 111, 119, -129, -12, -311, -63, +-295, -38, -87, 13, 135, 62, 246, 67, +199, 3, -11, -100, -211, -208, -231, -253, +-96, -154, 113, 99, 258, 394, 209, 532, +14, 380, -196, -27, -289, -482, -196, -685, +0, -490, 153, -20, 199, 441, 129, 615, +-5, 423, -81, 31, -78, -294, -51, -379, +-37, -231, -58, -4, -90, 145, -41, 145, +90, 51, 210, -21, 219, -42, 42, -7, +-211, 46, -361, 55, -318, 29, -42, -12, +304, -54, 458, -88, 359, -97, 42, -56, +-325, 41, -486, 148, -390, 191, -99, 118, +230, -51, 368, -201, 294, -228, 125, -97, +-77, 124, -179, 269, -144, 227, -84, 26, +-22, -210, -19, -317, -88, -222, -95, 0, +-21, 213, 110, 299, 252, 245, 259, 106, +117, -59, -85, -184, -278, -244, -325, -249, +-202, -164, -21, 7, 156, 182, 225, 305, +161, 302, 67, 154, -22, -65, -60, -252, +-33, -317, -32, -232, -51, -33, -64, 170, +-88, 274, -63, 236, 7, 76, 60, -115, +116, -227, 129, -191, 56, -54, -28, 99, +-116, 177, -161, 129, -97, 9, 2, -95, +109, -126, 181, -85, 129, 4, -7, 108, +-157, 162, -255, 142, -197, 44, -12, -123, +202, -266, 327, -274, 252, -129, 41, 120, +-195, 326, -346, 331, -299, 148, -100, -94, +129, -221, 286, -162, 284, -1, 155, 111, +-29, 57, -204, -113, -285, -231, -250, -190, +-132, 7, 78, 238, 294, 347, 374, 284, +291, 115, 37, -61, -279, -186, -461, -251, +-422, -273, -160, -243, 193, -140, 421, 49, +438, 263, 234, 406, -88, 407, -311, 233, +-335, -50, -179, -311, 41, -454, 162, -411, +155, -203, 46, 79, -81, 311, -92, 395, +3, 311, 102, 110, 129, -105, 53, -236, +-74, -251, -152, -175, -122, -46, 16, 70, +129, 135, 113, 144, 10, 85, -110, -14, +-157, -86, -92, -88, 37, -15, 154, 79, +179, 126, 112, 78, 23, -53, -59, -169, +-117, -178, -125, -95, -123, 37, -115, 136, +-62, 151, 20, 130, 130, 95, 229, 44, +248, -31, 182, -154, 22, -262, -185, -263, +-314, -97, -317, 175, -189, 386, 31, 384, +210, 148, 261, -189, 193, -402, 71, -347, +4, -91, -7, 181, -25, 296, -68, 197, +-152, -5, -213, -140, -146, -133, 18, -30, +187, 59, 261, 65, 183, -14, 18, -87, +-125, -72, -165, 3, -85, 81, 34, 120, +81, 83, 52, 0, -1, -72, -47, -121, +-52, -130, -28, -81, -12, 17, 9, 136, +39, 220, 62, 204, 65, 54, 33, -155, +-25, -281, -72, -249, -72, -66, -26, 167, +40, 288, 80, 212, 61, 12, -7, -178, +-79, -250, -117, -165, -74, 1, 37, 145, +155, 213, 227, 199, 180, 112, 8, -22, +-206, -157, -368, -258, -345, -257, -97, -129, +247, 56, 502, 205, 495, 240, 198, 165, +-200, 50, -491, -12, -535, 7, -286, 23, +88, -39, 375, -164, 463, -277, 315, -281, +51, -126, -158, 104, -250, 282, -200, 357, +-96, 327, -48, 222, -14, 61, 22, -158, +71, -402, 165, -557, 218, -487, 165, -160, +22, 301, -173, 650, -281, 680, -211, 359, +-19, -116, 189, -462, 274, -535, 158, -346, +-54, -56, -215, 144, -234, 216, -87, 201, +128, 164, 274, 136, 270, 85, 108, -14, +-107, -160, -255, -293, -273, -325, -147, -213, +48, 32, 197, 323, 254, 505, 191, 468, +51, 186, -96, -244, -195, -585, -186, -638, +-95, -352, 13, 118, 114, 498, 175, 596, +170, 381, 106, 22, 11, -251, -97, -327, +-190, -241, -213, -101, -136, -22, 3, -1, +152, 37, 257, 115, 251, 195, 142, 210, +-31, 115, -185, -59, -227, -216, -163, -257, +-40, -165, 98, -4, 153, 149, 119, 206, +67, 146, -3, 30, -48, -90, -41, -157, +-33, -126, -9, -29, 31, 73, 55, 140, +88, 140, 80, 68, -7, -43, -84, -140, +-140, -180, -154, -146, -58, -36, 71, 105, +179, 206, 244, 233, 212, 156, 109, -7, +-46, -167, -242, -257, -349, -244, -292, -130, +-99, 35, 196, 181, 429, 259, 447, 246, +259, 147, -61, -22, -346, -194, -437, -294, +-330, -281, -86, -134, 193, 72, 366, 232, +409, 276, 312, 198, 74, 45, -191, -93, +-389, -157, -428, -146, -253, -101, 47, -62, +319, -33, 430, 3, 311, 71, 63, 166, +-150, 213, -241, 170, -174, 36, -22, -164, +97, -319, 113, -332, 35, -187, -55, 51, +-82, 287, -32, 413, 63, 355, 136, 148, +135, -137, 59, -391, -42, -496, -96, -390, +-69, -103, 23, 268, 106, 567, 105, 619, +6, 372, -126, -85, -191, -543, -116, -761, +56, -610, 225, -163, 303, 357, 234, 695, +62, 707, -120, 413, -249, -22, -270, -390, +-171, -580, -14, -560, 162, -362, 289, -77, +286, 225, 171, 472, -17, 568, -202, 466, +-272, 183, -203, -183, -25, -481, 173, -578, +271, -431, 249, -132, 127, 170, -39, 358, +-153, 378, -188, 258, -160, 94, -75, -37, +20, -123, 93, -156, 138, -155, 165, -144, +186, -110, 182, -47, 105, 37, -43, 111, +-219, 160, -344, 165, -321, 113, -132, 37, +131, -51, 336, -151, 391, -226, 278, -230, +80, -130, -70, 67, -96, 293, -56, 423, +-54, 346, -142, 60, -277, -322, -313, -606, +-155, -599, 174, -272, 547, 219, 722, 645, +550, 784, 101, 537, -448, 35, -813, -485, +-767, -778, -340, -696, 252, -296, 703, 205, +772, 551, 461, 580, -33, 324, -423, -33, +-490, -266, -265, -256, 49, -80, 251, 81, +211, 94, 14, -66, -132, -247, -102, -263, +94, -69, 282, 221, 283, 409, 88, 354, +-201, 84, -385, -228, -318, -372, -59, -283, +238, -51, 417, 160, 377, 217, 170, 125, +-73, -11, -240, -95, -269, -89, -196, -28, +-94, 6, 33, -15, 159, -37, 258, 3, +300, 113, 235, 203, 70, 164, -149, -45, +-330, -320, -349, -456, -188, -316, 84, 77, +348, 508, 446, 684, 307, 457, 7, -59, +-287, -580, -410, -789, -286, -560, 10, -43, +318, 464, 457, 696, 341, 564, 52, 180, +-249, -233, -401, -472, -313, -472, -59, -281, +206, -8, 350, 221, 306, 326, 145, 289, +-33, 143, -147, -53, -141, -220, -67, -285, +0, -225, 37, -70, 32, 120, 27, 262, +55, 285, 91, 176, 118, -22, 103, -222, +24, -321, -55, -285, -91, -133, -85, 69, +-19, 234, 53, 307, 101, 269, 122, 148, +95, -24, 40, -207, 1, -345, -30, -367, +-48, -242, -39, 16, -27, 301, 6, 445, +55, 375, 101, 112, 145, -205, 145, -374, +87, -320, -17, -100, -133, 119, -196, 197, +-155, 105, -5, -63, 173, -149, 282, -84, +262, 88, 112, 243, -96, 265, -232, 103, +-220, -153, -66, -354, 150, -384, 296, -208, +278, 80, 92, 307, -161, 358, -325, 216, +-286, -17, -48, -191, 266, -201, 467, -78, +426, 50, 145, 75, -217, -21, -437, -142, +-402, -159, -142, -25, 193, 169, 386, 287, +346, 224, 174, 0, -26, -232, -147, -328, +-139, -230, -67, -6, 8, 200, 53, 284, +55, 219, 54, 50, 65, -125, 63, -240, +46, -264, 11, -182, -22, -35, -13, 131, +42, 271, 107, 319, 119, 247, 53, 59, +-48, -189, -144, -387, -163, -446, -48, -307, +136, -16, 287, 295, 315, 485, 176, 439, +-59, 174, -252, -155, -293, -368, -160, -361, +63, -167, 234, 58, 272, 163, 180, 112, +20, -20, -100, -97, -103, -51, -15, 81, +88, 187, 144, 166, 106, 37, -11, -119, +-128, -211, -168, -183, -99, -81, 67, 15, +251, 71, 338, 83, 259, 84, 30, 86, +-228, 60, -342, -6, -248, -91, 6, -147, +291, -112, 413, 8, 295, 133, 27, 167, +-240, 62, -351, -108, -233, -226, 30, -199, +293, -27, 414, 172, 315, 264, 78, 184, +-162, -9, -296, -185, -254, -237, -93, -145, +84, 13, 217, 118, 255, 126, 213, 67, +128, -10, 6, -49, -106, -58, -175, -61, +-180, -48, -71, -8, 107, 57, 257, 113, +295, 103, 157, 3, -60, -139, -213, -205, +-225, -122, -65, 60, 157, 216, 264, 218, +206, 42, 35, -184, -125, -282, -136, -169, +-9, 89, 152, 292, 234, 274, 149, 40, +-44, -245, -205, -373, -228, -249, -98, 48, +117, 305, 288, 358, 317, 183, 198, -86, +18, -281, -119, -288, -172, -121, -117, 85, +-19, 203, 51, 175, 83, 27, 87, -138, +84, -213, 82, -154, 66, 3, 31, 171, +6, 253, 10, 198, 50, 43, 108, -126, +116, -230, 23, -227, -125, -147, -218, -59, +-186, 20, 1, 91, 273, 164, 434, 229, +377, 225, 118, 106, -206, -101, -391, -291, +-329, -341, -68, -214, 244, 13, 406, 205, +331, 232, 101, 109, -148, -31, -285, -90, +-243, -35, -65, 57, 134, 68, 271, -27, +311, -142, 260, -175, 140, -75, -21, 98, +-179, 211, -281, 176, -294, 14, -182, -170, +35, -255, 268, -184, 430, -4, 465, 160, +343, 224, 89, 162, -214, 10, -441, -139, +-485, -194, -322, -119, 7, 32, 370, 156, +578, 159, 530, 15, 259, -185, -103, -286, +-359, -204, -387, 37, -221, 293, 29, 376, +208, 229, 253, -54, 206, -288, 121, -328, +52, -174, 12, 43, -26, 155, -75, 103, +-117, -28, -108, -98, -19, -31, 127, 128, +261, 246, 294, 202, 179, -11, -31, -279, +-222, -440, -270, -370, -137, -87, 99, 268, +308, 501, 340, 484, 160, 215, -92, -175, +-248, -476, -209, -527, -7, -311, 209, 33, +305, 314, 230, 390, 58, 256, -74, 32, +-114, -147, -92, -193, -59, -133, -43, -55, +-15, -7, 68, 5, 191, 20, 296, 58, +286, 87, 128, 65, -95, -22, -269, -130, +-295, -177, -145, -123, 75, 23, 252, 177, +310, 246, 218, 197, 56, 48, -81, -141, +-144, -278, -104, -305, 11, -223, 122, -56, +172, 142, 148, 301, 83, 347, 13, 251, +-36, 48, -62, -189, -94, -358, -114, -376, +-65, -247, 63, -25, 242, 204, 380, 334, +362, 320, 177, 192, -109, 3, -347, -180, +-387, -288, -231, -290, 9, -207, 214, -63, +288, 103, 245, 224, 176, 270, 132, 239, +105, 125, 64, -45, -18, -209, -135, -305, +-231, -296, -238, -174, -132, 19, 58, 191, +248, 271, 344, 231, 316, 101, 189, -38, +30, -113, -83, -120, -116, -92, -98, -74, +-83, -97, -77, -120, -52, -71, 5, 64, +116, 214, 234, 279, 262, 173, 171, -60, +5, -269, -123, -308, -115, -130, -9, 152, +99, 321, 123, 236, 14, -63, -122, -368, +-139, -445, -7, -217, 187, 200, 302, 531, +246, 547, 46, 238, -163, -213, -222, -539, +-90, -557, 125, -281, 274, 95, 241, 364, +39, 407, -182, 231, -267, -25, -141, -211, +114, -241, 324, -147, 367, -2, 205, 100, +-63, 111, -256, 65, -249, 4, -57, -36, +177, -46, 280, -43, 196, -57, 6, -84, +-157, -72, -171, -2, -35, 97, 130, 171, +209, 165, 176, 54, 88, -89, 14, -171, +-2, -157, 15, -63, -14, 27, -99, 37, +-169, -25, -140, -89, 33, -67, 288, 58, +461, 225, 428, 314, 166, 219, -215, -50, +-491, -357, -509, -530, -247, -447, 182, -107, +544, 324, 623, 610, 388, 584, -23, 241, +-379, -233, -479, -569, -276, -583, 78, -281, +348, 130, 398, 394, 215, 371, -56, 132, +-213, -115, -175, -194, -2, -69, 184, 126, +229, 195, 127, 40, -10, -240, -110, -426, +-111, -352, -29, -20, 65, 376, 123, 572, +137, 424, 129, 19, 110, -400, 65, -576, +-2, -398, -84, -3, -149, 345, -137, 442, +-48, 253, 98, -70, 253, -296, 325, -295, +272, -111, 118, 97, -105, 182, -299, 109, +-346, -35, -229, -106, 16, -58, 295, 60, +453, 145, 408, 109, 185, -37, -103, -188, +-298, -249, -298, -181, -142, -5, 70, 182, +224, 273, 229, 234, 115, 84, -13, -108, +-86, -236, -65, -240, 31, -133, 131, 16, +179, 135, 147, 163, 62, 95, -32, 2, +-118, -54, -162, -58, -140, -37, -63, -29, +61, -59, 227, -105, 362, -96, 391, -5, +253, 134, -22, 230, -311, 206, -486, 40, +-418, -170, -115, -299, 258, -269, 506, -82, +511, 140, 289, 252, -13, 198, -231, 25, +-277, -141, -176, -189, -48, -97, 31, 56, +68, 149, 98, 128, 159, 20, 235, -102, +244, -149, 120, -95, -96, -8, -285, 51, +-328, 51, -179, 0, 100, -46, 362, -41, +466, 10, 348, 75, 52, 115, -254, 94, +-417, 11, -359, -87, -91, -151, 247, -157, +464, -97, 446, 2, 194, 75, -164, 95, +-420, 65, -409, 17, -126, -5, 264, 18, +540, 66, 534, 79, 225, 28, -212, -80, +-532, -207, -563, -271, -277, -204, 158, -20, +505, 208, 619, 363, 449, 341, 112, 139, +-188, -132, -345, -324, -341, -338, -222, -172, +-76, 46, 56, 172, 168, 150, 264, 36, +320, -58, 295, -54, 159, 36, -51, 104, +-230, 79, -283, -12, -192, -95, -22, -112, +130, -69, 164, -34, 117, -62, 77, -108, +85, -78, 140, 76, 157, 288, 66, 388, +-105, 245, -246, -103, -243, -444, -65, -550, +193, -342, 366, 59, 332, 390, 110, 447, +-165, 248, -317, -41, -257, -211, -38, -186, +195, -50, 316, 46, 268, 22, 87, -76, +-81, -138, -150, -83, -107, 71, 0, 210, +75, 211, 68, 68, 10, -129, -42, -260, +-30, -228, 45, -51, 124, 149, 158, 256, +128, 208, 51, 45, -21, -136, -46, -230, +-40, -190, -38, -69, -63, 56, -86, 115, +-65, 89, 25, 27, 166, -9, 282, 6, +301, 51, 189, 72, -11, 19, -201, -94, +-304, -186, -276, -183, -128, -75, 75, 85, +248, 198, 327, 189, 285, 76, 137, -58, +-55, -127, -196, -109, -227, -39, -149, 21, +10, 29, 166, 19, 247, 24, 210, 48, +65, 48, -110, -18, -233, -135, -239, -215, +-88, -156, 158, 44, 353, 287, 391, 400, +234, 278, -54, -28, -315, -337, -406, -468, +-277, -354, -2, -71, 258, 208, 373, 339, +305, 291, 123, 135, -74, -25, -193, -120, +-195, -133, -116, -98, 9, -65, 141, -44, +209, -34, 180, -17, 74, 26, -70, 80, +-184, 111, -195, 87, -88, 2, 93, -101, +248, -140, 294, -74, 204, 63, 19, 163, +-160, 135, -252, -23, -218, -204, -78, -253, +89, -113, 210, 131, 241, 304, 170, 265, +55, 25, -31, -251, -76, -367, -75, -242, +-61, 44, -61, 295, -42, 354, 15, 201, +109, -56, 201, -251, 217, -298, 129, -202, +-34, -38, -195, 93, -257, 145, -167, 127, +31, 74, 229, 34, 308, 31, 231, 43, +53, 27, -133, -46, -226, -169, -184, -270, +-58, -251, 86, -87, 172, 167, 164, 384, +95, 431, 19, 261, -27, -46, -38, -330, +-40, -451, -47, -357, -45, -120, -9, 124, +63, 270, 146, 281, 181, 194, 113, 72, +-34, -40, -176, -123, -224, -169, -123, -167, +83, -117, 269, -23, 314, 74, 180, 122, +-56, 98, -249, 32, -291, -30, -162, -37, +67, 2, 258, 36, 297, 26, 175, -35, +-22, -94, -163, -88, -173, -8, -78, 86, +47, 107, 115, 18, 96, -123, 34, -199, +-17, -123, -25, 83, 7, 287, 49, 334, +58, 171, 26, -115, -21, -348, -44, -382, +-42, -196, -23, 84, 7, 280, 42, 284, +82, 115, 110, -98, 101, -205, 45, -142, +-36, 30, -114, 181, -147, 196, -106, 55, +-12, -140, 100, -251, 190, -197, 201, -12, +123, 170, 6, 214, -116, 97, -184, -82, +-162, -173, -69, -106, 55, 66, 154, 208, +180, 187, 135, 16, 46, -183, -40, -275, +-82, -194, -83, -1, -68, 169, -40, 216, +9, 132, 69, -10, 115, -110, 125, -118, +89, -50, 7, 37, -88, 82, -144, 55, +-126, -17, -32, -83, 99, -95, 187, -32, +190, 60, 104, 123, -49, 103, -174, -15, +-209, -151, -127, -206, 37, -122, 192, 67, +248, 247, 181, 298, 34, 184, -120, -37, +-199, -255, -180, -359, -85, -303, 27, -122, +129, 100, 191, 285, 202, 367, 149, 319, +21, 152, -139, -91, -255, -325, -259, -441, +-130, -366, 92, -120, 282, 185, 334, 402, +218, 417, -5, 228, -217, -50, -292, -271, +-211, -316, -37, -182, 147, 18, 244, 141, +223, 122, 106, 6, -38, -101, -137, -104, +-149, 7, -109, 150, -33, 204, 46, 127, +91, -38, 104, -196, 85, -245, 52, -162, +21, -13, -8, 120, -48, 186, -74, 158, +-71, 70, -40, -16, 2, -81, 39, -110, +63, -96, 65, -61, 53, -23, 36, 20, +16, 61, 6, 96, -4, 123, -37, 105, +-59, 12, -58, -133, -38, -244, 5, -230, +51, -69, 77, 165, 74, 330, 46, 290, +8, 61, -14, -209, -25, -344, -24, -245, +-13, 10, 1, 227, 2, 260, -6, 116, +-9, -85, 5, -191, 20, -135, 24, 3, +14, 97, -4, 79, 6, -21, 24, -88, +44, -46, 57, 75, 45, 173, -6, 155, +-71, 8, -110, -187, -99, -300, -36, -244, +26, -44, 65, 184, 96, 310, 139, 273, +159, 106, 132, -83, 24, -194, -141, -200, +-294, -123, -343, -32, -220, 19, 41, 36, +319, 61, 446, 109, 355, 146, 97, 119, +-182, 11, -343, -139, -313, -239, -163, -199, +9, -36, 133, 151, 168, 251, 153, 194, +116, 19, 69, -156, 10, -227, -57, -163, +-134, -10, -162, 124, -116, 164, -6, 115, +127, 21, 198, -61, 156, -90, 21, -64, +-120, -29, -187, -18, -133, -13, 1, -1, +154, 26, 209, 75, 123, 109, -51, 80, +-196, -10, -210, -112, -102, -166, 58, -129, +180, -11, 203, 118, 122, 173, 5, 131, +-107, 18, -150, -108, -116, -164, -52, -123, +12, -23, 67, 74, 97, 122, 92, 95, +71, 22, 28, -45, -8, -79, -49, -68, +-96, -25, -134, 8, -127, 17, -41, 21, +115, 38, 258, 70, 270, 91, 110, 50, +-159, -69, -367, -197, -374, -235, -130, -127, +220, 99, 456, 314, 430, 354, 143, 169, +-228, -135, -457, -363, -412, -375, -145, -165, +176, 124, 350, 295, 323, 265, 147, 94, +-61, -81, -190, -145, -184, -86, -88, 3, +11, 34, 46, -7, 3, -60, -41, -63, +-39, 3, 36, 87, 126, 95, 171, 17, +119, -76, -10, -107, -148, -29, -198, 110, +-144, 193, -43, 126, 54, -64, 74, -257, +55, -315, 49, -169, 73, 101, 92, 323, +87, 359, 16, 196, -84, -52, -160, -233, +-174, -262, -114, -175, -24, -71, 63, 3, +121, 46, 156, 93, 149, 172, 107, 238, +23, 196, -72, 22, -157, -203, -206, -355, +-171, -341, -72, -145, 51, 112, 164, 295, +221, 341, 193, 234, 92, 43, -77, -142, +-223, -251, -256, -266, -145, -181, 53, -11, +211, 170, 232, 286, 106, 275, -83, 118, +-228, -111, -226, -287, -90, -329, 99, -210, +217, 22, 214, 252, 112, 362, -28, 302, +-147, 110, -215, -133, -197, -308, -99, -330, +73, -217, 218, -29, 266, 139, 165, 213, +-44, 186, -231, 111, -284, 41, -158, -8, +79, -39, 263, -67, 268, -111, 105, -144, +-144, -131, -285, -70, -234, 30, -23, 140, +202, 207, 282, 187, 163, 78, -68, -84, +-258, -230, -282, -252, -101, -113, 155, 114, +333, 295, 284, 293, 41, 77, -234, -224, +-358, -404, -267, -328, -29, -31, 186, 303, +252, 451, 179, 313, 18, 2, -77, -277, +-61, -356, 11, -211, 37, 39, -35, 210, +-167, 204, -218, 58, -130, -107, 53, -173, +247, -96, 298, 54, 195, 145, -6, 126, +-186, 20, -253, -83, -180, -85, -44, 16, +80, 116, 125, 107, 74, -38, -3, -241, +-45, -336, -12, -203, 57, 110, 103, 415, +57, 507, -56, 298, -176, -100, -193, -434, +-74, -495, 117, -264, 259, 88, 218, 333, +5, 322, -232, 91, -317, -161, -186, -257, +97, -143, 318, 98, 338, 283, 133, 265, +-166, 57, -357, -201, -313, -348, -67, -279, +193, -38, 299, 211, 190, 309, -33, 210, +-220, -10, -225, -195, -72, -216, 136, -69, +255, 119, 181, 211, -20, 140, -213, -48, +-263, -221, -145, -251, 47, -116, 156, 98, +143, 263, 28, 273, -71, 124, -49, -90, +65, -240, 167, -249, 138, -112, -49, 82, +-272, 202, -364, 185, -257, 54, 38, -96, +320, -164, 428, -114, 312, 1, 37, 102, +-229, 129, -344, 79, -288, 1, -103, -54, +104, -68, 201, -61, 178, -56, 42, -48, +-93, -27, -133, 16, -58, 74, 75, 119, +176, 118, 157, 67, 4, -5, -188, -79, +-302, -129, -219, -138, 6, -104, 227, -33, +296, 53, 187, 112, -20, 114, -171, 76, +-186, 35, -75, 8, 65, 3, 105, -9, +36, -64, -88, -137, -144, -169, -81, -115, +59, 26, 182, 169, 211, 221, 109, 159, +-63, 32, -208, -76, -257, -114, -171, -96, +-22, -73, 128, -76, 200, -71, 186, -14, +108, 103, 15, 221, -70, 248, -135, 126, +-187, -98, -210, -294, -142, -342, 11, -205, +211, 41, 344, 251, 321, 317, 115, 226, +-178, 49, -417, -113, -433, -192, -216, -164, +109, -74, 374, 10, 414, 47, 240, 28, +-30, -20, -254, -47, -331, -17, -219, 70, +-27, 169, 153, 205, 215, 121, 126, -78, +-17, -293, -121, -391, -118, -277, -9, 27, +126, 365, 156, 524, 53, 380, -151, -1, +-299, -401, -261, -569, -39, -393, 256, 13, +425, 397, 344, 526, 57, 342, -274, -7, +-468, -294, -394, -377, -133, -262, 174, -57, +361, 112, 346, 184, 178, 176, -37, 132, +-191, 66, -217, -27, -144, -119, -63, -171, +-4, -141, 3, -30, 7, 99, 36, 161, +94, 122, 154, 14, 158, -87, 64, -117, +-98, -63, -242, 22, -270, 68, -146, 48, +40, -10, 201, -54, 237, -40, 153, 21, +15, 77, -108, 81, -153, 15, -119, -85, +-59, -149, -10, -113, 32, 14, 62, 151, +106, 208, 107, 136, 53, -37, -39, -202, +-143, -247, -200, -153, -154, 21, -28, 173, +128, 219, 233, 165, 211, 65, 97, -27, +-74, -91, -206, -132, -230, -157, -140, -156, +-1, -93, 111, 29, 128, 165, 68, 247, +6, 223, -38, 100, -13, -66, 29, -184, +39, -211, 5, -151, -60, -39, -115, 68, +-101, 118, -37, 101, 19, 49, 54, -9, +63, -36, 72, -18, 74, 22, 52, 46, +-12, 30, -86, -23, -152, -75, -149, -91, +-62, -49, 58, 22, 143, 77, 133, 87, +50, 49, -49, -5, -83, -45, -56, -43, +-4, -13, 15, 18, -6, 20, -45, -23, +-55, -72, -4, -85, 72, -31, 115, 80, +79, 185, -20, 203, -126, 101, -163, -79, +-115, -245, 0, -302, 104, -211, 137, -17, +83, 175, -4, 284, -57, 291, -50, 200, +-2, 61, 18, -93, -11, -248, -89, -347, +-144, -332, -123, -181, 3, 79, 161, 343, +247, 467, 203, 378, 52, 111, -116, -194, +-218, -387, -222, -387, -156, -219, -54, 10, +32, 178, 103, 237, 157, 207, 187, 130, +170, 52, 74, -27, -93, -110, -245, -177, +-297, -192, -221, -126, -40, 16, 138, 169, +242, 232, 229, 161, 115, -4, -22, -152, +-113, -176, -134, -55, -99, 117, -49, 196, +-28, 106, -19, -112, -23, -305, -1, -321, +51, -106, 100, 220, 111, 461, 67, 459, +-20, 194, -100, -185, -132, -458, -107, -485, +-30, -265, 36, 67, 53, 317, 17, 357, +-23, 204, -21, -16, 41, -155, 111, -136, +126, -1, 54, 109, -92, 87, -238, -60, +-287, -219, -172, -250, 57, -96, 282, 152, +368, 325, 260, 303, 17, 104, -234, -135, +-372, -255, -331, -203, -137, -59, 93, 45, +261, 42, 293, -9, 210, -9, 69, 88, +-80, 218, -204, 245, -265, 82, -238, -198, +-125, -419, 51, -411, 222, -139, 313, 240, +258, 489, 69, 454, -168, 162, -319, -209, +-310, -419, -144, -363, 79, -112, 237, 158, +250, 279, 124, 204, -51, 27, -165, -113, +-161, -133, -79, -46, 23, 52, 79, 81, +62, 25, 3, -66, -43, -113, -36, -73, +11, 33, 55, 145, 43, 192, -14, 132, +-82, -7, -121, -165, -106, -267, -22, -246, +94, -95, 175, 122, 170, 292, 66, 319, +-87, 179, -203, -46, -223, -219, -138, -245, +21, -131, 159, 25, 205, 100, 131, 55, +-11, -42, -120, -86, -141, -17, -80, 122, +17, 214, 82, 168, 70, 3, 4, -177, +-75, -263, -97, -205, -57, -35, 7, 134, +69, 206, 100, 171, 79, 74, 23, -31, +-43, -103, -105, -124, -127, -120, -102, -85, +-36, -13, 53, 79, 131, 168, 151, 202, +100, 140, -8, -2, -117, -167, -176, -271, +-167, -247, -80, -102, 47, 97, 153, 244, +186, 262, 125, 158, 8, -5, -98, -138, +-163, -173, -163, -120, -98, -25, 0, 54, +88, 80, 123, 54, 98, 4, 41, -45, +-18, -73, -69, -53, -88, 8, -60, 85, +3, 137, 50, 128, 46, 37, 5, -102, +-48, -207, -79, -208, -67, -96, -17, 77, +45, 208, 99, 221, 96, 129, 45, -7, +-21, -117, -84, -161, -114, -139, -105, -83, +-62, -17, 13, 56, 87, 136, 109, 201, +74, 195, -12, 76, -99, -131, -129, -311, +-78, -344, 41, -183, 144, 110, 149, 373, +61, 437, -79, 253, -204, -70, -235, -345, +-149, -423, 19, -260, 190, 20, 275, 245, +228, 311, 90, 212, -95, 36, -243, -113, +-291, -165, -217, -134, -36, -64, 146, 6, +233, 47, 196, 62, 73, 52, -59, 29, +-129, 5, -118, -4, -45, 12, 23, 33, +20, 29, -39, -16, -84, -96, -64, -147, +33, -110, 140, 19, 169, 176, 99, 258, +-53, 190, -201, -11, -238, -229, -143, -326, +32, -231, 188, 11, 230, 256, 137, 357, +-30, 244, -175, -13, -218, -253, -143, -332, +-12, -206, 100, 36, 151, 234, 128, 279, +59, 148, -33, -65, -118, -215, -151, -214, +-126, -77, -48, 99, 57, 209, 130, 191, +147, 63, 80, -88, -60, -185, -163, -186, +-159, -101, -58, 16, 82, 111, 162, 157, +129, 152, 15, 108, -119, 31, -202, -63, +-164, -163, -32, -230, 115, -214, 207, -89, +193, 118, 95, 310, -41, 370, -181, 237, +-251, -49, -212, -335, -78, -449, 104, -315, +240, -5, 255, 294, 144, 414, -49, 294, +-219, 35, -256, -194, -160, -267, 15, -180, +181, -31, 220, 70, 125, 80, -44, 32, +-204, -5, -240, 13, -137, 69, 26, 101, +182, 69, 240, -8, 171, -97, 33, -146, +-134, -129, -239, -60, -221, 36, -125, 124, +8, 164, 127, 138, 173, 55, 170, -57, +99, -140, -37, -153, -139, -93, -173, 1, +-136, 78, -39, 109, 41, 91, 82, 43, +97, 1, 50, -24, -1, -41, -15, -50, +-23, -57, -33, -47, -62, -13, -110, 34, +-97, 69, -22, 76, 75, 54, 171, 14, +171, -11, 71, -25, -62, -43, -181, -69, +-206, -85, -124, -67, -9, 1, 95, 102, +138, 171, 87, 148, 10, 34, -51, -115, +-62, -202, -7, -153, 43, 0, 49, 147, +20, 184, -62, 78, -138, -97, -135, -201, +-61, -143, 58, 42, 139, 208, 118, 219, +41, 61, -29, -148, -48, -246, -1, -147, +28, 77, 2, 240, -71, 205, -167, -21, +-193, -256, -77, -307, 123, -115, 284, 200, +295, 398, 107, 328, -148, 23, -312, -314, +-306, -447, -116, -286, 137, 55, 279, 345, +239, 398, 44, 196, -175, -103, -258, -296, +-172, -285, 13, -104, 166, 105, 185, 202, +76, 154, -59, 29, -130, -71, -93, -84, +1, -29, 60, 26, 47, 40, -31, 10, +-115, -29, -120, -40, -32, -25, 90, 3, +177, 23, 148, 31, 31, 31, -78, 30, +-160, 22, -180, -8, -121, -47, -24, -81, +93, -73, 184, -8, 174, 85, 96, 147, +-22, 133, -167, 30, -242, -121, -206, -232, +-67, -227, 131, -92, 257, 120, 241, 302, +124, 343, -63, 208, -219, -52, -270, -308, +-219, -420, -53, -321, 145, -52, 244, 254, +236, 432, 113, 379, -84, 127, -223, -181, +-264, -379, -170, -361, 32, -141, 204, 140, +266, 315, 193, 298, -14, 118, -219, -101, +-308, -223, -249, -204, -44, -90, 171, 29, +280, 89, 260, 84, 112, 65, -87, 75, +-208, 94, -226, 69, -143, -28, -29, -163, +25, -248, 56, -200, 77, -15, 81, 201, +93, 311, 89, 240, 46, 37, -18, -163, +-116, -241, -205, -162, -207, -10, -120, 96, +18, 97, 143, 20, 198, -47, 181, -42, +106, 29, -11, 113, -103, 132, -138, 61, +-130, -52, -99, -152, -90, -177, -87, -115, +-42, -13, 55, 85, 180, 140, 279, 137, +264, 94, 118, 36, -122, -12, -350, -44, +-430, -77, -313, -114, -59, -140, 206, -129, +360, -56, 332, 73, 170, 214, -13, 287, +-127, 229, -166, 47, -150, -181, -133, -337, +-116, -338, -72, -171, -5, 85, 100, 289, +211, 335, 233, 209, 117, -6, -83, -191, +-243, -253, -246, -168, -104, -7, 91, 128, +208, 174, 163, 113, -3, -7, -189, -111, +-262, -148, -139, -96, 99, 18, 263, 140, +263, 204, 93, 160, -139, 15, -271, -170, +-245, -295, -83, -272, 129, -87, 235, 171, +179, 352, 15, 339, -160, 134, -221, -127, +-145, -286, 11, -254, 147, -73, 171, 104, +86, 143, -31, 39, -118, -99, -110, -136, +-30, -13, 25, 182, 42, 286, 1, 208, +-76, -10, -91, -229, -24, -308, 71, -215, +137, -39, 113, 95, 11, 131, -86, 94, +-139, 56, -114, 69, -29, 114, 54, 116, +85, 27, 38, -122, -49, -238, -83, -241, +-41, -120, 37, 60, 97, 193, 82, 216, +13, 137, -73, 19, -147, -56, -143, -72, +-44, -51, 80, -30, 161, -25, 143, -35, +37, -33, -93, -6, -184, 25, -184, 50, +-92, 59, 62, 53, 189, 47, 218, 28, +127, -11, -45, -66, -206, -125, -252, -137, +-154, -79, 21, 44, 183, 169, 222, 229, +114, 178, -54, 27, -183, -148, -194, -256, +-67, -242, 89, -118, 176, 51, 131, 193, +-6, 247, -118, 203, -149, 82, -95, -63, +-8, -169, 60, -209, 79, -162, 54, -50, +-7, 78, -29, 161, -4, 159, 9, 76, +2, -37, -31, -115, -60, -110, -40, -32, +0, 59, 20, 104, 36, 70, 12, -11, +-25, -79, -35, -92, -17, -40, 31, 33, +67, 65, 32, 37, -44, -24, -119, -53, +-132, -21, -35, 49, 88, 107, 174, 101, +163, 22, 28, -87, -129, -164, -221, -159, +-210, -75, -72, 44, 101, 144, 204, 188, +208, 160, 96, 69, -51, -53, -142, -165, +-160, -218, -115, -175, -39, -40, 21, 126, +51, 246, 43, 240, 24, 100, 40, -99, +76, -252, 95, -261, 44, -120, -71, 85, +-178, 237, -205, 246, -139, 111, 12, -82, +175, -213, 249, -210, 194, -86, 18, 77, +-160, 169, -225, 149, -166, 49, -38, -63, +80, -113, 128, -86, 107, -7, 36, 59, +-23, 64, -41, 22, -46, -31, -46, -61, +-59, -47, -77, 5, -45, 62, 47, 90, +139, 69, 180, 8, 105, -72, -59, -128, +-214, -121, -268, -49, -160, 57, 51, 141, +241, 153, 299, 82, 181, -27, -63, -114, +-260, -144, -300, -103, -155, -24, 87, 49, +236, 97, 228, 105, 89, 76, -103, 24, +-216, -36, -187, -86, -54, -97, 112, -64, +188, -7, 124, 44, -6, 63, -113, 44, +-132, 22, -66, 14, 16, 28, 62, 37, +52, 3, -17, -67, -68, -128, -56, -129, +31, -47, 130, 85, 132, 182, 33, 180, +-107, 80, -208, -60, -188, -153, -59, -147, +83, -68, 181, 10, 173, 42, 62, 34, +-46, 15, -90, 35, -62, 86, 11, 110, +35, 66, -21, -51, -105, -183, -151, -238, +-96, -152, 36, 34, 168, 218, 228, 289, +173, 198, 28, 2, -127, -186, -221, -252, +-200, -168, -85, -1, 35, 134, 107, 161, +96, 82, 46, -39, 6, -115, -15, -94, +-11, 9, 10, 119, 23, 154, 4, 88, +-47, -42, -86, -159, -70, -191, -26, -110, +26, 33, 66, 143, 74, 165, 56, 98, +-1, -8, -71, -88, -95, -95, -72, -50, +-2, -1, 79, 25, 106, 18, 92, 10, +26, 27, -72, 49, -137, 42, -151, -12, +-109, -92, -4, -138, 102, -96, 175, 27, +196, 162, 119, 218, -14, 149, -160, -18, +-278, -177, -267, -228, -114, -139, 99, 30, +291, 172, 327, 195, 176, 86, -55, -72, +-280, -175, -364, -158, -233, -33, 26, 120, +282, 201, 385, 170, 229, 51, -53, -98, +-300, -194, -397, -191, -252, -100, 22, 37, +275, 154, 390, 194, 265, 140, -13, 16, +-245, -112, -344, -177, -247, -133, -33, -5, +145, 115, 237, 163, 205, 106, 68, -9, +-56, -103, -119, -118, -131, -62, -83, -1, +-58, 18, -45, -11, 3, -31, 66, 20, +148, 128, 193, 211, 121, 184, -32, 12, +-199, -223, -301, -371, -232, -326, -32, -97, +197, 197, 336, 388, 280, 372, 57, 173, +-185, -84, -314, -261, -263, -280, -73, -170, +114, -12, 210, 101, 195, 131, 76, 114, +-63, 79, -121, 39, -104, 4, -42, -37, +5, -93, -6, -128, -29, -109, -23, -34, +24, 72, 91, 165, 126, 189, 93, 123, +3, -3, -125, -138, -213, -216, -181, -199, +-58, -80, 98, 78, 214, 199, 202, 231, +90, 141, -49, -23, -165, -172, -181, -218, +-101, -136, 11, 27, 106, 168, 119, 194, +43, 94, -30, -65, -68, -167, -48, -154, +35, -45, 74, 73, 50, 117, -16, 74, +-111, -6, -137, -42, -64, -2, 47, 64, +159, 78, 171, 2, 57, -128, -64, -205, +-147, -143, -138, 35, -36, 213, 40, 263, +67, 140, 57, -84, -7, -250, -34, -237, +8, -64, 56, 157, 93, 272, 44, 195, +-82, -19, -164, -220, -161, -288, -59, -178, +91, 44, 170, 233, 155, 279, 60, 177, +-83, 2, -149, -148, -98, -197, 9, -140, +109, -39, 101, 42, -25, 66, -143, 39, +-177, 3, -87, 7, 110, 50, 258, 102, +262, 108, 128, 38, -118, -84, -310, -201, +-327, -223, -194, -126, 43, 47, 239, 207, +287, 254, 219, 169, 78, 14, -63, -126, +-138, -176, -173, -129, -167, -46, -117, 8, +-61, 21, 26, 25, 138, 55, 217, 109, +229, 131, 130, 69, -60, -69, -214, -202, +-260, -222, -182, -94, -14, 117, 129, 264, +179, 227, 123, 28, 3, -197, -87, -279, +-74, -158, 19, 83, 98, 261, 96, 243, +-5, 44, -126, -190, -170, -283, -108, -171, +21, 61, 146, 241, 166, 249, 79, 94, +-46, -107, -136, -217, -105, -177, 9, -37, +106, 86, 139, 119, 60, 71, -79, -1, +-159, -35, -156, -22, -63, 13, 75, 35, +160, 25, 163, -9, 81, -47, -51, -73, +-126, -81, -110, -54, -42, 18, 47, 108, +85, 166, 57, 137, -1, 16, -70, -144, +-99, -236, -48, -182, 36, 1, 104, 199, +124, 266, 61, 144, -29, -89, -89, -269, +-109, -265, -67, -67, 7, 195, 55, 330, +72, 237, 37, -22, -32, -263, -49, -331, +-17, -184, 39, 80, 90, 265, 67, 257, +-7, 83, -84, -120, -145, -207, -112, -132, +-6, 28, 98, 141, 172, 119, 145, 0, +29, -116, -80, -130, -152, -25, -139, 103, +-55, 151, 36, 75, 110, -65, 124, -157, +70, -127, -8, 2, -69, 128, -87, 170, +-54, 85, -5, -66, 27, -175, 37, -164, +28, -52, 20, 86, 12, 178, 7, 162, +3, 54, -6, -71, -34, -145, -67, -139, +-53, -63, 1, 32, 63, 87, 99, 87, +67, 48, -7, 3, -64, -13, -89, 5, +-56, 23, 12, 6, 65, -53, 74, -119, +27, -141, -43, -66, -77, 78, -49, 205, +15, 244, 73, 148, 76, -41, 30, -214, +-27, -274, -71, -188, -68, -12, -22, 154, +28, 215, 48, 152, 34, 24, -14, -81, +-40, -109, -5, -63, 52, 4, 92, 38, +71, 25, -17, -22, -98, -62, -143, -54, +-129, -3, -27, 53, 94, 83, 167, 78, +171, 34, 80, -25, -26, -72, -91, -88, +-133, -62, -114, -11, -63, 44, -18, 71, +49, 53, 85, 7, 88, -35, 88, -39, +52, 3, 4, 50, -47, 61, -105, 14, +-105, -75, -51, -135, 17, -110, 80, -2, +92, 115, 57, 167, -2, 123, -59, 5, +-73, -104, -30, -138, 43, -96, 91, -12, +77, 58, 8, 70, -71, 43, -104, 12, +-88, -2, -35, -7, 39, -19, 87, -33, +99, -35, 76, -9, 14, 43, -41, 81, +-70, 69, -76, 2, -44, -84, -4, -128, +25, -83, 42, 20, 25, 100, -4, 111, +-16, 52, -1, -37, 44, -69, 76, -26, +58, 48, -3, 80, -81, 24, -149, -88, +-155, -174, -81, -149, 54, -7, 193, 169, +250, 273, 184, 221, 30, 34, -151, -172, +-264, -291, -244, -257, -115, -93, 62, 103, +213, 227, 241, 233, 143, 136, -1, -11, +-128, -135, -156, -182, -83, -142, 2, -43, +73, 65, 81, 129, 12, 113, -59, 45, +-96, -37, -59, -87, 54, -72, 142, -15, +152, 39, 79, 48, -63, 18, -171, -21, +-185, -40, -117, -7, 24, 44, 153, 67, +184, 46, 134, -21, 14, -84, -99, -104, +-133, -66, -113, 9, -52, 77, 27, 109, +84, 87, 112, 29, 96, -27, 28, -68, +-49, -91, -96, -86, -104, -50, -59, 13, +23, 88, 86, 141, 109, 128, 68, 39, +-28, -91, -97, -194, -105, -206, -48, -94, +57, 89, 126, 239, 128, 274, 72, 158, +-44, -56, -139, -254, -165, -324, -120, -233, +4, -26, 125, 189, 177, 301, 161, 261, +72, 103, -45, -81, -130, -200, -167, -199, +-130, -97, -38, 30, 48, 104, 97, 96, +101, 19, 74, -57, 38, -65, 12, -19, +-8, 54, -31, 98, -54, 74, -89, 3, +-102, -64, -57, -88, 31, -60, 130, -1, +172, 35, 110, 24, -5, -10, -118, -22, +-164, 3, -98, 52, 4, 81, 91, 48, +116, -29, 42, -97, -48, -101, -87, -31, +-64, 72, 29, 134, 101, 105, 86, 3, +25, -102, -59, -145, -103, -99, -77, 4, +-26, 81, 31, 93, 68, 57, 62, 12, +42, 3, 22, 29, 8, 40, -1, 5, +-30, -74, -76, -144, -89, -151, -54, -70, +19, 59, 101, 159, 128, 183, 76, 130, +-2, 31, -88, -56, -132, -100, -90, -102, +-15, -80, 61, -49, 107, -10, 80, 32, +34, 66, 6, 77, -32, 54, -54, 8, +-81, -32, -105, -50, -63, -42, 25, -14, +131, 19, 220, 33, 201, 34, 70, 23, +-124, -3, -306, -38, -331, -69, -182, -76, +70, -47, 314, 23, 393, 92, 274, 117, +31, 84, -221, 2, -342, -78, -279, -96, +-89, -47, 117, 21, 226, 54, 197, 15, +79, -65, -33, -109, -85, -67, -73, 45, +-22, 151, 9, 179, 5, 93, -5, -60, +-27, -158, -17, -145, 31, -48, 57, 63, +53, 103, 2, 43, -58, -57, -60, -114, +-24, -83, 30, 21, 81, 124, 71, 160, +17, 117, -45, 28, -97, -60, -81, -124, +-17, -157, 42, -156, 84, -116, 77, -13, +33, 138, 7, 262, -15, 283, -25, 152, +-30, -80, -46, -295, -45, -364, -26, -232, +1, 29, 40, 263, 78, 345, 74, 234, +39, 8, -6, -196, -52, -270, -59, -193, +-39, -28, -33, 121, -13, 173, 5, 132, +17, 35, 49, -55, 62, -87, 54, -59, +41, -2, -14, 42, -76, 44, -103, -5, +-93, -70, -14, -95, 80, -55, 128, 34, +134, 127, 68, 153, -37, 86, -119, -42, +-153, -162, -110, -192, -2, -110, 95, 35, +156, 153, 152, 174, 86, 93, -7, -28, +-105, -118, -170, -130, -164, -81, -87, -15, +31, 42, 144, 80, 196, 97, 159, 101, +60, 65, -57, -29, -148, -142, -159, -209, +-102, -170, -11, -17, 76, 176, 97, 282, +71, 216, 38, 19, -1, -188, -10, -273, +1, -177, -6, 27, -16, 189, -39, 198, +-57, 53, -23, -123, 27, -186, 80, -98, +99, 75, 31, 196, -58, 168, -107, 4, +-94, -171, -11, -224, 90, -121, 138, 65, +111, 210, 10, 212, -99, 69, -142, -109, +-109, -204, -30, -168, 51, -38, 91, 103, +84, 167, 62, 136, 30, 48, -4, -48, +-27, -109, -52, -118, -66, -85, -51, -26, +-34, 47, -1, 105, 45, 113, 67, 67, +74, -3, 49, -64, -3, -83, -31, -58, +-45, -17, -55, 11, -30, 5, -8, -10, +19, -6, 49, 33, 39, 80, 25, 89, +10, 38, -9, -55, -16, -127, -26, -133, +-27, -67, 1, 28, 26, 88, 43, 95, +42, 65, 15, 26, -23, 13, -66, 9, +-90, -21, -60, -76, 23, -122, 118, -117, +170, -32, 135, 90, 14, 167, -129, 141, +-217, 31, -203, -88, -59, -135, 122, -70, +220, 47, 193, 118, 47, 80, -107, -40, +-156, -144, -98, -135, 18, -14, 108, 126, +83, 180, -19, 104, -113, -49, -139, -160, +-47, -142, 95, -15, 190, 128, 181, 180, +57, 97, -95, -66, -181, -192, -172, -204, +-77, -101, 44, 48, 127, 160, 150, 192, +108, 137, 30, 40, -46, -58, -96, -129, +-110, -157, -84, -131, -30, -55, 49, 47, +118, 144, 136, 175, 79, 121, -23, 4, +-116, -113, -160, -166, -110, -125, -7, -18, +98, 89, 162, 144, 129, 118, 41, 28, +-46, -67, -107, -117, -101, -111, -53, -54, +-17, 25, 25, 75, 51, 83, 59, 56, +73, 8, 53, -31, 8, -37, -42, -20, +-87, 0, -82, 8, -23, -7, 46, -22, +95, -22, 81, -3, 7, 6, -68, -3, +-104, -26, -55, -42, 46, -6, 126, 82, +132, 168, 55, 170, -69, 50, -168, -152, +-169, -326, -68, -337, 78, -148, 187, 148, +179, 386, 76, 416, -48, 221, -134, -79, +-131, -305, -53, -347, 30, -210, 79, -7, +59, 133, -2, 150, -26, 91, -11, 41, +33, 40, 66, 71, 35, 63, -25, -29, +-78, -156, -99, -223, -57, -161, 17, 7, +84, 184, 111, 262, 83, 183, 27, 11, +-29, -145, -72, -196, -95, -129, -89, -23, +-52, 45, 10, 59, 86, 40, 147, 35, +150, 62, 79, 82, -42, 50, -157, -42, +-194, -139, -136, -170, -7, -100, 127, 40, +181, 159, 142, 178, 31, 94, -83, -35, +-118, -130, -74, -135, 1, -62, 59, 35, +55, 94, 7, 92, -36, 43, -57, -20, +-30, -61, 21, -76, 55, -69, 61, -36, +34, 22, 2, 80, -9, 113, -16, 101, +-24, 36, -34, -53, -54, -117, -61, -127, +-37, -84, 19, -10, 91, 63, 141, 100, +134, 98, 57, 71, -60, 20, -160, -44, +-192, -94, -129, -109, -8, -66, 118, 18, +184, 100, 150, 128, 53, 70, -45, -44, +-106, -132, -94, -134, -42, -36, 2, 97, +15, 176, -11, 143, -25, 10, 5, -132, +53, -178, 97, -112, 101, 9, 35, 107, +-62, 115, -140, 45, -144, -32, -53, -52, +60, -3, 134, 61, 124, 72, 40, -2, +-54, -106, -106, -154, -81, -95, -3, 48, +71, 185, 85, 213, 41, 102, -37, -75, +-84, -215, -73, -226, -14, -101, 59, 81, +91, 215, 69, 222, 8, 102, -49, -66, +-74, -188, -57, -199, -6, -113, 40, 20, +58, 127, 50, 160, 12, 115, -24, 25, +-34, -52, -32, -87, -12, -75, -2, -38, +-3, -9, 2, 6, 12, 15, 34, 30, +57, 50, 47, 66, 4, 39, -46, -30, +-93, -93, -92, -101, -42, -38, 39, 55, +115, 121, 131, 106, 84, 12, -1, -100, +-75, -155, -105, -110, -86, 9, -38, 116, +14, 144, 50, 89, 65, -5, 68, -74, +55, -82, 25, -44, -25, -6, -67, -1, +-87, -17, -64, -19, 0, 12, 66, 57, +105, 79, 79, 55, 5, -7, -64, -68, +-91, -88, -66, -52, 0, 13, 62, 53, +91, 44, 67, 14, 2, -14, -50, -16, +-77, 3, -68, 15, -33, 6, 9, -17, +48, -29, 79, -17, 83, 20, 57, 52, +6, 47, -63, 7, -112, -43, -114, -71, +-66, -51, 17, -7, 101, 30, 143, 39, +129, 29, 61, 25, -32, 31, -115, 37, +-152, 16, -132, -41, -54, -105, 53, -118, +141, -60, 175, 46, 126, 143, 9, 159, +-103, 73, -156, -52, -128, -133, -25, -128, +78, -47, 121, 45, 83, 77, -9, 48, +-74, -8, -63, -34, 0, -6, 71, 40, +86, 54, 22, 19, -70, -41, -133, -80, +-99, -67, 14, -8, 136, 44, 190, 55, +119, 30, -31, -2, -165, -15, -201, 1, +-122, 19, 33, 12, 163, -13, 188, -36, +106, -38, -32, -17, -129, 9, -134, 25, +-54, 24, 42, 17, 93, 26, 57, 34, +-21, 19, -76, -20, -68, -66, 15, -81, +107, -40, 144, 32, 79, 91, -54, 88, +-183, 19, -203, -68, -96, -102, 75, -46, +216, 55, 227, 121, 113, 95, -61, -18, +-188, -130, -206, -151, -103, -66, 40, 67, +138, 156, 136, 134, 61, 16, -8, -100, +-44, -126, -23, -58, 3, 45, 4, 93, +-34, 47, -73, -52, -63, -122, 8, -87, +105, 32, 154, 150, 112, 174, -12, 70, +-132, -88, -186, -190, -118, -176, 21, -59, +151, 84, 189, 165, 108, 137, -23, 41, +-142, -51, -162, -92, -86, -72, 41, -29, +129, 1, 143, 11, 70, 10, -26, 4, +-86, 10, -97, 24, -51, 36, 4, 40, +42, 28, 45, -4, 26, -49, 3, -92, +2, -102, 10, -53, 10, 44, -4, 143, +-35, 181, -51, 127, -36, -3, 14, -137, +63, -198, 84, -160, 46, -59, -31, 38, +-90, 88, -92, 98, -18, 101, 84, 114, +141, 108, 106, 43, -5, -89, -129, -233, +-176, -289, -121, -192, 12, 28, 148, 251, +194, 342, 127, 246, -1, 26, -114, -182, +-141, -257, -83, -177, 4, -28, 72, 84, +75, 96, 32, 33, -18, -27, -33, -31, +-13, 16, 30, 56, 50, 49, 33, -1, +1, -47, -32, -39, -40, 20, -43, 72, +-35, 51, -30, -50, -10, -162, 25, -186, +76, -73, 115, 124, 110, 278, 54, 277, +-53, 109, -154, -129, -199, -295, -139, -291, +-10, -133, 144, 71, 230, 203, 205, 209, +86, 117, -79, 4, -188, -72, -197, -90, +-107, -70, 21, -53, 129, -46, 138, -25, +80, 16, -8, 73, -67, 109, -48, 93, +0, 31, 47, -51, 38, -118, -10, -139, +-75, -95, -87, -5, -32, 90, 67, 145, +143, 135, 123, 68, 30, -36, -98, -117, +-169, -137, -144, -91, -30, 2, 92, 75, +171, 85, 153, 46, 59, -5, -44, -25, +-120, -3, -131, 31, -101, 32, -35, -11, +26, -68, 95, -88, 129, -40, 129, 44, +87, 105, -12, 93, -101, 4, -165, -94, +-152, -132, -72, -73, 44, 45, 134, 139, +161, 154, 114, 69, 36, -62, -38, -154, +-98, -162, -109, -85, -94, 27, -39, 111, +34, 138, 97, 106, 119, 34, 88, -42, +2, -103, -92, -127, -135, -93, -105, -9, +7, 89, 125, 151, 174, 139, 114, 45, +-17, -83, -147, -176, -195, -174, -136, -76, +-6, 60, 127, 157, 187, 168, 156, 102, +61, 7, -33, -66, -101, -96, -118, -100, +-109, -93, -80, -73, -28, -25, 36, 59, +110, 146, 160, 184, 150, 130, 73, -5, +-46, -150, -157, -218, -194, -162, -142, -18, +-19, 119, 108, 170, 170, 121, 143, 16, +56, -75, -38, -100, -99, -69, -90, -23, +-44, 10, 22, 19, 54, 31, 45, 57, +8, 76, -19, 58, -21, -10, -5, -92, +16, -147, 24, -131, 21, -42, 3, 66, +-4, 145, -15, 158, -8, 106, -14, 20, +-18, -63, -19, -117, 3, -133, 57, -103, +86, -39, 82, 31, 11, 75, -86, 85, +-164, 59, -146, 21, -38, -1, 131, 3, +255, 18, 236, 13, 83, -31, -146, -100, +-290, -142, -286, -105, -113, 3, 115, 133, +276, 210, 274, 179, 123, 51, -75, -101, +-219, -190, -204, -172, -85, -63, 76, 59, +160, 120, 140, 95, 33, 17, -76, -45, +-132, -49, -114, -3, -20, 41, 75, 40, +147, -10, 139, -63, 69, -69, -35, -18, +-120, 63, -163, 101, -134, 61, -46, -32, +62, -118, 165, -129, 184, -49, 130, 72, +12, 154, -104, 144, -175, 46, -160, -79, +-79, -148, 38, -130, 145, -43, 166, 58, +111, 110, -8, 85, -107, 7, -138, -69, +-83, -86, 19, -31, 111, 55, 137, 103, +69, 75, -49, -18, -144, -117, -136, -143, +-41, -68, 95, 63, 166, 162, 132, 149, +13, 26, -114, -124, -159, -190, -101, -114, +25, 58, 127, 199, 138, 207, 48, 64, +-64, -134, -125, -246, -87, -193, 8, -17, +92, 160, 109, 218, 47, 129, -44, -32, +-98, -151, -79, -142, -7, -26, 76, 98, +104, 137, 66, 69, -14, -55, -75, -144, +-94, -134, -67, -39, -20, 76, 33, 132, +73, 106, 87, 28, 84, -43, 50, -60, +0, -22, -68, 22, -115, 22, -133, -20, +-98, -75, -12, -101, 92, -64, 167, 27, +172, 121, 123, 165, 19, 130, -87, 32, +-174, -79, -195, -156, -145, -161, -36, -95, +86, 5, 183, 89, 226, 123, 172, 98, +60, 32, -97, -35, -213, -71, -241, -60, +-160, -14, -12, 34, 140, 55, 225, 35, +206, -16, 108, -64, -49, -73, -172, -39, +-208, 16, -133, 68, 0, 78, 131, 49, +181, -1, 138, -48, 36, -72, -78, -61, +-133, -14, -126, 36, -44, 63, 38, 47, +90, 2, 85, -46, 56, -67, 19, -40, +-20, 15, -40, 59, -59, 61, -47, 23, +-33, -23, 7, -38, 33, -7, 50, 33, +48, 35, 15, -7, -21, -72, -40, -107, +-13, -67, 14, 35, 37, 136, 13, 168, +-27, 102, -58, -21, -58, -122, -19, -156, +34, -110, 80, -31, 87, 32, 59, 69, +3, 75, -35, 79, -67, 79, -70, 45, +-64, -23, -55, -105, -15, -155, 45, -128, +118, -20, 140, 115, 108, 189, 14, 151, +-90, 22, -160, -117, -150, -180, -66, -127, +42, -2, 125, 102, 129, 122, 76, 56, +-4, -37, -51, -83, -54, -53, -21, 25, +9, 89, 25, 78, 14, 0, -26, -87, +-61, -128, -68, -95, -23, -13, 49, 72, +113, 123, 134, 116, 102, 64, 9, 1, +-102, -60, -171, -108, -160, -118, -69, -88, +58, -27, 151, 47, 156, 106, 81, 118, +-17, 84, -81, 32, -89, -16, -40, -48, +17, -70, 38, -85, 8, -90, -35, -64, +-52, 8, -16, 98, 54, 155, 96, 136, +81, 37, 10, -95, -61, -172, -101, -142, +-78, -24, -7, 99, 68, 148, 94, 97, +62, -19, 3, -113, -57, -119, -68, -47, +-42, 35, 12, 71, 40, 53, 46, 13, +27, -7, 3, 8, -11, 37, -13, 31, +0, -20, -8, -89, -17, -127, -35, -89, +-23, 13, 4, 124, 39, 173, 62, 124, +53, 7, 21, -110, -32, -157, -63, -114, +-65, -15, -24, 83, 18, 119, 50, 79, +38, 1, -7, -61, -34, -80, -33, -45, +14, 5, 59, 43, 73, 53, 26, 34, +-43, 8, -103, -11, -97, -15, -25, -19, +68, -31, 122, -49, 91, -56, 15, -36, +-68, 22, -91, 100, -55, 147, 19, 119, +65, 17, 55, -122, 10, -221, -46, -207, +-51, -75, -17, 113, 35, 255, 50, 257, +29, 114, -23, -91, -51, -235, -40, -237, +4, -110, 50, 65, 51, 176, 25, 170, +-32, 79, -57, -34, -40, -96, 7, -88, +43, -37, 44, 5, 12, 18, -32, 12, +-43, 12, -25, 28, 20, 44, 44, 44, +36, 16, -2, -24, -43, -56, -56, -66, +-36, -47, 12, -10, 57, 28, 75, 62, +44, 78, -9, 65, -59, 13, -74, -53, +-54, -101, -5, -99, 43, -30, 68, 62, +56, 120, 15, 99, -30, 11, -50, -85, +-35, -121, -7, -66, 11, 36, 11, 116, +-1, 112, -4, 25, 4, -78, 21, -123, +39, -85, 36, 4, 4, 76, -34, 81, +-57, 37, -42, -19, 0, -43, 43, -24, +54, 6, 41, 8, 2, -20, -32, -46, +-47, -37, -31, 21, -2, 89, 24, 110, +38, 55, 27, -45, 10, -125, -17, -129, +-34, -54, -51, 50, -43, 113, -11, 100, +42, 29, 83, -30, 81, -45, 45, -13, +-34, 25, -99, 19, -121, -30, -79, -74, +-1, -75, 79, -19, 115, 62, 94, 115, +38, 112, -36, 51, -63, -36, -65, -97, +-49, -100, -36, -68, -13, -18, 9, 32, +41, 66, 74, 80, 83, 67, 60, 21, +-5, -45, -76, -88, -124, -88, -106, -35, +-42, 49, 45, 102, 117, 95, 125, 33, +80, -51, -1, -104, -63, -92, -100, -35, +-80, 23, -39, 54, 11, 50, 47, 29, +58, 17, 57, 21, 38, 27, 22, 5, +-4, -42, -35, -84, -72, -93, -86, -50, +-65, 22, -3, 84, 82, 103, 138, 71, +140, 9, 61, -40, -63, -56, -167, -46, +-184, -20, -108, -5, 29, -10, 151, -20, +188, -13, 138, 18, 21, 60, -95, 95, +-160, 83, -138, 15, -71, -80, 1, -150, +55, -148, 99, -65, 133, 69, 127, 182, +73, 206, -32, 112, -146, -58, -214, -200, +-191, -233, -60, -136, 113, 34, 241, 173, +245, 201, 128, 120, -47, -8, -170, -97, +-192, -102, -124, -48, -29, 0, 44, -11, +72, -53, 67, -71, 64, -12, 66, 109, +63, 198, 19, 178, -71, 29, -136, -173, +-134, -278, -54, -206, 66, -4, 155, 195, +152, 253, 54, 132, -73, -73, -153, -205, +-129, -170, -26, -1, 87, 167, 136, 196, +100, 67, 6, -122, -79, -220, -101, -157, +-58, 22, 16, 179, 67, 202, 62, 85, +6, -88, -51, -190, -62, -156, -21, -19, +45, 120, 80, 169, 75, 106, 19, -10, +-46, -98, -97, -112, -90, -59, -38, 9, +28, 42, 67, 31, 61, 2, 38, -18, +12, -7, -5, 33, -13, 64, -7, 56, +-9, 10, -23, -49, -34, -92, -32, -97, +0, -63, 35, -8, 55, 50, 33, 81, +1, 78, -29, 58, -28, 37, -11, 15, +12, -14, 23, -50, 5, -92, -19, -116, +-43, -89, -30, -8, 6, 95, 44, 160, +43, 147, 11, 56, -19, -65, -33, -140, +-17, -119, 7, -26, 34, 65, 33, 86, +4, 24, -34, -62, -54, -95, -33, -40, +0, 72, 34, 154, 36, 128, 28, 1, +6, -143, -3, -199, -5, -128, 1, 30, +-2, 172, -8, 197, -20, 105, -35, -40, +-22, -152, 6, -164, 20, -84, 16, 17, +7, 86, 10, 102, 19, 77, 31, 44, +20, 17, -3, -15, -44, -61, -70, -99, +-67, -101, -20, -53, 40, 27, 74, 101, +64, 125, 20, 84, -27, 15, -54, -45, +-35, -68, -3, -49, 26, -20, 28, 4, +4, 7, -26, 1, -52, -6, -42, -7, +-8, 0, 30, 19, 59, 39, 77, 49, +68, 46, 12, 13, -59, -48, -118, -100, +-116, -109, -58, -52, 41, 47, 129, 124, +158, 131, 91, 57, -36, -56, -143, -129, +-168, -113, -94, -23, 32, 76, 134, 119, +157, 84, 90, 2, -17, -63, -109, -79, +-128, -51, -93, -15, -12, -2, 49, -1, +75, 9, 72, 41, 53, 84, 30, 91, +-3, 42, -47, -45, -75, -123, -70, -136, +-46, -69, -5, 33, 42, 105, 73, 102, +72, 34, 35, -42, -6, -61, -40, -20, +-48, 44, -47, 76, -23, 41, 5, -29, +24, -92, 31, -101, 11, -52, 0, 15, +-8, 63, 9, 71, 22, 56, 20, 39, +-6, 21, -35, -7, -52, -47, -47, -89, +-1, -103, 60, -57, 99, 36, 79, 122, +12, 137, -54, 60, -96, -63, -93, -158, +-59, -157, 10, -51, 69, 102, 103, 212, +84, 201, 51, 65, -5, -112, -67, -236, +-110, -240, -111, -118, -52, 57, 36, 194, +111, 229, 126, 151, 72, 15, -24, -103, +-97, -149, -99, -116, -42, -42, 36, 25, +70, 45, 53, 24, -15, -4, -61, -1, +-50, 37, 13, 79, 66, 78, 64, 9, +13, -90, -63, -155, -92, -134, -61, -20, +37, 117, 125, 190, 137, 145, 55, 5, +-70, -143, -157, -201, -165, -134, -77, 10, +49, 140, 150, 177, 163, 110, 96, -9, +-1, -99, -82, -113, -105, -60, -87, 6, +-43, 42, -10, 22, 23, -12, 38, -19, +59, 4, 60, 42, 44, 56, 16, 29, +-21, -20, -58, -54, -74, -44, -49, -8, +4, 19, 41, 16, 49, -12, 34, -38, +19, -33, -8, 9, -20, 51, -23, 65, +-17, 39, -11, -17, -5, -50, 7, -45, +37, -13, 56, 21, 48, 17, 14, -22, +-47, -60, -98, -57, -111, -9, -63, 60, +25, 111, 115, 105, 177, 42, 156, -40, +49, -103, -94, -117, -198, -81, -212, -22, +-135, 34, 2, 65, 143, 72, 217, 65, +181, 47, 71, 30, -64, 10, -147, -25, +-164, -72, -116, -111, -34, -112, 54, -60, +112, 42, 121, 142, 91, 181, 25, 127, +-59, 0, -117, -138, -121, -196, -62, -136, +27, 7, 113, 138, 125, 169, 63, 85, +-45, -52, -111, -137, -105, -112, -29, -2, +52, 115, 89, 136, 57, 48, -31, -80, +-87, -154, -66, -112, 24, 20, 99, 144, +106, 165, 38, 73, -71, -69, -145, -154, +-144, -128, -44, -30, 80, 64, 159, 90, +149, 43, 67, -14, -42, -21, -121, 27, +-133, 80, -89, 65, -7, -27, 57, -141, +98, -189, 83, -116, 36, 42, -21, 184, +-49, 217, -42, 120, -27, -31, -10, -140, +5, -147, 5, -66, -5, 25, -4, 66, +14, 40, 30, -16, 28, -44, -8, -17, +-28, 39, -35, 77, -18, 70, 1, 17, +21, -48, 16, -85, -3, -75, -22, -34, +-15, 19, 9, 59, 26, 64, 29, 39, +-1, 3, -37, -31, -42, -52, -10, -48, +32, -26, 49, -2, 35, 21, -5, 40, +-33, 47, -47, 48, -23, 30, 13, -15, +34, -82, 14, -131, -24, -121, -21, -41, +12, 94, 50, 205, 55, 217, 22, 102, +-45, -84, -103, -237, -109, -257, -48, -129, +47, 64, 118, 204, 124, 211, 64, 94, +-21, -52, -88, -124, -102, -97, -64, -14, +-24, 48, 8, 41, 17, -19, 21, -59, +19, -33, 43, 40, 67, 106, 62, 94, +8, -1, -72, -112, -121, -160, -113, -98, +-51, 36, 41, 152, 115, 171, 127, 82, +60, -55, -31, -151, -98, -147, -96, -54, +-50, 61, 21, 124, 65, 103, 64, 22, +16, -58, -42, -94, -66, -69, -53, -1, +-8, 66, 34, 95, 55, 69, 36, -1, +2, -77, -24, -116, -34, -97, -21, -22, +-4, 74, 13, 135, 9, 125, -16, 45, +-39, -61, -37, -131, -14, -127, 10, -53, +36, 44, 48, 111, 48, 115, 17, 63, +-23, -3, -63, -64, -78, -95, -83, -88, +-53, -57, 9, -3, 75, 60, 120, 109, +108, 121, 45, 74, -45, -18, -118, -108, +-133, -150, -83, -123, 6, -39, 77, 54, +107, 111, 59, 116, -17, 78, -82, 28, +-77, -22, -29, -59, 29, -85, 67, -96, +70, -76, 32, -11, -38, 71, -83, 123, +-93, 114, -65, 41, -23, -54, 30, -115, +86, -108, 114, -35, 87, 56, 5, 102, +-83, 77, -143, 7, -131, -56, -57, -71, +41, -40, 103, 9, 102, 30, 54, 20, +-27, 1, -71, -6, -68, 12, -21, 36, +14, 40, 12, 8, -9, -49, -19, -86, +-16, -75, 3, -15, 23, 57, 28, 96, +13, 74, -24, 14, -54, -46, -45, -70, +-24, -45, 10, -6, 36, 23, 46, 25, +30, 4, 0, -15, -39, -13, -67, 13, +-70, 30, -41, 28, 7, 1, 52, -35, +65, -47, 39, -24, -7, 17, -48, 54, +-69, 59, -46, 15, -4, -40, 27, -77, +20, -67, -1, -15, -20, 51, -26, 90, +-14, 75, 3, 19, 19, -49, 13, -84, +-11, -67, -33, -13, -31, 40, -22, 63, +-9, 46, -2, 5, 3, -32, 7, -42, +2, -22, 0, 0, -5, 15, -15, 16, +-25, 14, -27, 22, -22, 23, -6, 5, +11, -22, 3, -52, -4, -64, -26, -30, +-33, 41, -22, 106, 0, 114, 12, 49, +18, -56, 3, -130, -29, -127, -54, -48, +-55, 57, -16, 119, 29, 105, 51, 30, +45, -52, 11, -82, -35, -51, -76, 5, +-77, 33, -45, 12, 13, -36, 52, -55, +57, -11, 30, 66, -9, 119, -42, 93, +-52, -13, -43, -134, -32, -184, -14, -119, +-6, 30, 4, 166, 14, 200, 27, 114, +30, -37, 4, -149, -44, -156, -80, -72, +-77, 42, -45, 108, 7, 92, 53, 23, +70, -46, 45, -67, -15, -37, -62, 7, +-81, 38, -67, 43, -42, 32, -2, 15, +29, -3, 39, -20, 27, -46, 12, -66, +-10, -58, -37, -14, -52, 55, -49, 107, +-30, 109, -7, 56, 9, -34, 22, -115, +8, -132, -24, -81, -41, 1, -26, 75, +3, 109, 28, 89, 28, 25, 5, -37, +-47, -73, -90, -66, -90, -29, -35, 9, +40, 31, 88, 22, 85, -3, 25, -13, +-61, 5, -114, 32, -108, 53, -54, 40, +17, -16, 65, -79, 60, -103, 18, -69, +-30, 15, -59, 100, -65, 133, -54, 92, +-34, 1, -9, -82, 29, -111, 48, -74, +43, -5, 15, 39, -32, 39, -86, 12, +-115, -6, -95, 13, -25, 49, 46, 72, +78, 42, 79, -40, 44, -117, -8, -141, +-50, -83, -79, 34, -85, 134, -73, 153, +-46, 81, -12, -32, 30, -116, 56, -128, +63, -63, 34, 32, -10, 97, -50, 101, +-79, 46, -76, -31, -53, -85, -28, -91, +-9, -44, 6, 19, 13, 67, 15, 81, +16, 55, 10, 6, 3, -37, -20, -52, +-35, -45, -49, -27, -61, -11, -64, -5, +-45, -3, -7, 10, 33, 42, 61, 73, +56, 64, 21, 17, -43, -53, -93, -112, +-100, -107, -65, -40, -13, 53, 37, 110, +58, 92, 30, 26, -21, -46, -67, -71, +-76, -34, -54, 25, -28, 61, 10, 34, +31, -30, 26, -76, 9, -75, -9, -9, +-35, 71, -50, 107, -69, 74, -69, -10, +-44, -85, -9, -106, 27, -63, 50, 14, +50, 74, 30, 81, -13, 42, -61, -11, +-89, -41, -98, -40, -83, -19, -40, 0, +3, -2, 48, -13, 71, -21, 63, -3, +24, 39, -23, 67, -62, 69, -90, 28, +-101, -39, -93, -95, -54, -117, -6, -79, +43, 3, 73, 90, 73, 135, 45, 110, +-10, 34, -74, -49, -110, -100, -112, -88, +-92, -37, -49, 15, 5, 29, 53, 6, +77, -19, 70, -16, 43, 31, -17, 91, +-88, 102, -138, 50, -143, -56, -92, -151, +3, -167, 92, -90, 132, 46, 99, 148, +-3, 165, -119, 89, -179, -23, -159, -94, +-60, -98, 61, -47, 141, 11, 131, 30, +31, 14, -98, -12, -173, -11, -173, 27, +-91, 59, 23, 60, 102, 10, 118, -62, +70, -96, -20, -69, -96, 9, -129, 84, +-118, 104, -69, 56, -14, -35, 41, -99, +74, -98, 65, -34, 20, 58, -47, 110, +-105, 91, -120, 13, -86, -74, -25, -112, +43, -81, 69, 2, 40, 83, -17, 114, +-68, 82, -84, 6, -75, -71, -40, -114, +5, -101, 29, -33, 17, 44, -1, 98, +-17, 105, -32, 61, -38, -7, -47, -68, +-60, -88, -52, -72, -30, -36, -6, 15, +20, 53, 33, 67, 23, 62, -16, 40, +-64, 4, -80, -38, -82, -70, -54, -80, +-5, -58, 22, 0, 27, 59, 13, 93, +-28, 87, -57, 35, -57, -29, -38, -76, +-7, -85, 10, -45, -3, 6, -28, 41, +-63, 52, -77, 31, -49, 1, -4, -23, +35, -20, 49, 0, 17, 22, -34, 32, +-76, 14, -106, -14, -89, -41, -42, -58, +11, -46, 50, -6, 57, 45, 33, 79, +-17, 73, -81, 36, -114, -22, -101, -69, +-62, -75, 0, -50, 56, -7, 70, 28, +41, 40, -26, 35, -89, 21, -108, 12, +-84, 6, -42, -7, 12, -27, 41, -49, +38, -44, -2, -7, -48, 40, -66, 72, +-61, 49, -40, -12, -12, -70, 3, -88, +-2, -35, -16, 50, -41, 107, -50, 93, +-40, 9, -27, -88, -11, -132, -4, -88, +0, 16, -8, 109, -24, 128, -43, 65, +-57, -30, -66, -94, -57, -92, -26, -31, +4, 34, 31, 56, 32, 31, -11, -9, +-65, -18, -93, 10, -91, 50, -49, 64, +13, 16, 57, -63, 49, -124, -17, -120, +-85, -35, -114, 74, -94, 153, -27, 148, +48, 60, 78, -48, 57, -128, -11, -130, +-88, -67, -119, 14, -111, 70, -74, 62, +-20, 13, 30, -28, 56, -22, 53, 34, +26, 86, -14, 94, -72, 33, -130, -83, +-146, -172, -114, -179, -34, -76, 67, 88, +126, 207, 111, 229, 20, 130, -100, -43, +-184, -178, -179, -214, -91, -133, 33, 3, +109, 112, 100, 145, 30, 92, -71, 14, +-132, -43, -120, -54, -63, -26, 9, -5, +51, -11, 33, -28, -12, -34, -45, -1, +-62, 46, -54, 77, -37, 65, -24, -2, +-18, -74, -30, -108, -28, -76, -8, 13, +0, 98, -2, 129, -22, 83, -63, -9, +-78, -100, -67, -143, -39, -101, 9, -7, +44, 89, 32, 144, -12, 117, -66, 37, +-100, -59, -96, -123, -56, -118, 3, -55, +48, 30, 51, 81, 21, 83, -42, 45, +-92, -7, -104, -31, -80, -29, -38, -11, +11, 1, 35, -15, 22, -28, -8, -23, +-35, 4, -43, 53, -50, 76, -56, 52, +-54, -8, -57, -75, -42, -97, -13, -63, +16, 9, 30, 79, 20, 93, -23, 54, +-60, -9, -70, -47, -61, -42, -44, -18, +-38, 4, -39, -8, -37, -41, -24, -48, +8, -14, 58, 57, 68, 121, 22, 125, +-72, 54, -167, -68, -188, -163, -126, -177, +-13, -99, 101, 43, 151, 152, 104, 180, +-3, 115, -109, -1, -158, -95, -132, -135, +-71, -102, 0, -34, 34, 27, 29, 63, +5, 60, -18, 40, -30, 20, -23, -2, +-25, -18, -42, -36, -54, -42, -61, -33, +-52, -9, -33, 33, -12, 61, 7, 57, +11, 18, -2, -42, -16, -79, -33, -76, +-53, -23, -61, 50, -71, 97, -55, 97, +-17, 37, 6, -47, 16, -102, 13, -110, +-8, -56, -38, 26, -60, 92, -65, 119, +-50, 79, -39, 6, -33, -64, -25, -104, +-14, -90, 8, -43, 28, 18, 20, 73, +-10, 92, -63, 78, -126, 28, -137, -31, +-90, -69, -3, -85, 88, -57, 118, -6, +84, 41, -15, 71, -128, 56, -180, 14, +-149, -32, -60, -54, 47, -38, 104, -7, +86, 28, 25, 37, -62, 18, -123, -15, +-113, -41, -65, -34, -8, -2, 26, 29, +32, 43, 11, 30, -25, 4, -58, -25, +-71, -40, -67, -34, -44, -22, -10, 2, +4, 29, 13, 51, 17, 58, -3, 34, +-44, -6, -75, -58, -83, -100, -70, -89, +-30, -39, 13, 47, 41, 119, 34, 129, +-9, 85, -57, -6, -88, -89, -79, -123, +-41, -105, -7, -40, 13, 30, 7, 72, +-31, 82, -54, 59, -43, 26, -13, -3, +10, -26, 12, -42, -19, -55, -58, -55, +-90, -30, -86, 8, -35, 48, 23, 67, +62, 58, 50, 19, -9, -30, -65, -59, +-98, -65, -101, -28, -61, 17, -2, 47, +28, 54, 33, 21, 6, -16, -27, -34, +-48, -31, -50, -3, -43, 26, -42, 38, +-43, 19, -36, -25, -28, -53, -7, -48, +28, -7, 34, 48, -4, 83, -57, 71, +-99, 8, -107, -56, -74, -85, -6, -73, +59, -17, 72, 41, 26, 66, -43, 53, +-96, 11, -98, -21, -51, -31, -6, -13, +24, 14, 15, 18, -30, -1, -63, -30, +-60, -46, -22, -35, 23, -2, 34, 43, +4, 71, -41, 62, -84, 29, -91, -22, +-61, -62, -18, -73, 17, -54, 23, -14, +4, 27, -9, 57, -12, 62, -19, 37, +-24, 3, -43, -30, -67, -49, -80, -40, +-77, -16, -37, 13, 23, 31, 66, 33, +72, 22, 27, 0, -43, -20, -97, -39, +-120, -44, -100, -19, -38, 19, 19, 58, +47, 74, 43, 52, 3, 5, -38, -65, +-53, -113, -55, -101, -39, -39, -25, 52, +-23, 117, -23, 130, -19, 79, -3, -7, +6, -75, -10, -108, -34, -91, -58, -50, +-71, -8, -61, 42, -18, 73, 35, 87, +64, 83, 43, 52, -18, -6, -76, -77, +-122, -126, -113, -129, -65, -71, 0, 30, +61, 117, 84, 152, 45, 129, -13, 42, +-60, -64, -98, -136, -95, -143, -63, -78, +-21, 20, 12, 106, 17, 130, 6, 80, +-12, -5, -24, -83, -24, -101, -14, -56, +-6, 22, -2, 80, -28, 73, -66, 13, +-79, -58, -63, -95, -19, -56, 35, 28, +63, 99, 48, 106, -6, 38, -75, -58, +-114, -122, -95, -114, -33, -35, 35, 62, +66, 122, 47, 105, -7, 29, -73, -48, +-104, -88, -79, -71, -28, -28, 28, 9, +56, 27, 38, 20, -3, 14, -49, 16, +-74, 31, -72, 44, -49, 24, -23, -18, +-2, -63, 4, -80, 3, -50, 0, 3, +-11, 58, -15, 83, -16, 62, -24, 10, +-30, -48, -34, -68, -38, -49, -36, -5, +-34, 38, -25, 49, -14, 34, 3, -9, +23, -41, 17, -35, 5, -12, -12, 22, +-48, 42, -81, 29, -80, -3, -59, -29, +-30, -29, 15, -11, 54, 5, 66, 13, +40, 7, -15, -5, -66, -6, -95, 7, +-89, 23, -58, 24, -17, 1, 23, -34, +37, -54, 24, -38, 5, 11, -7, 59, +-22, 79, -45, 49, -61, -17, -64, -75, +-47, -83, -16, -37, 19, 28, 39, 75, +32, 67, -6, 15, -52, -42, -77, -64, +-58, -37, -8, 17, 25, 55, 33, 47, +11, -1, -31, -53, -60, -67, -58, -33, +-29, 31, 9, 74, 21, 70, 1, 20, +-27, -49, -42, -82, -27, -68, 6, -16, +27, 46, 21, 71, -22, 55, -75, 7, +-84, -44, -50, -62, 5, -43, 55, -1, +66, 31, 29, 39, -33, 22, -76, -9, +-77, -28, -36, -29, 6, -9, 17, 17, +1, 29, -24, 28, -39, 16, -39, -6, +-10, -24, 26, -41, 35, -41, 5, -19, +-36, 8, -59, 46, -57, 70, -27, 61, +-6, 23, 3, -35, 0, -86, -12, -97, +-25, -60, -14, 5, 11, 76, 27, 110, +17, 89, -27, 36, -72, -26, -91, -71, +-74, -82, -27, -64, 30, -33, 76, -1, +81, 27, 42, 56, -18, 73, -68, 73, +-95, 51, -93, -7, -66, -76, -17, -120, +28, -114, 55, -49, 65, 43, 46, 119, +2, 140, -51, 99, -90, 14, -101, -70, +-78, -113, -23, -108, 41, -62, 81, 6, +80, 56, 38, 80, -30, 75, -80, 42, +-101, 2, -94, -36, -49, -62, 16, -58, +64, -31, 78, 14, 50, 52, 2, 55, +-41, 25, -71, -22, -89, -51, -75, -47, +-26, -13, 26, 34, 55, 61, 57, 49, +36, 7, -2, -38, -46, -58, -76, -47, +-72, -9, -40, 29, 0, 43, 22, 33, +24, 9, 15, -14, 0, -17, -16, -8, +-16, 4, -13, 11, -7, 4, -19, -7, +-40, -24, -44, -31, -26, -24, 4, 1, +38, 32, 56, 52, 38, 54, -13, 30, +-62, -17, -88, -64, -77, -81, -34, -62, +17, -9, 51, 48, 62, 86, 36, 86, +2, 42, -19, -13, -35, -58, -54, -78, +-68, -71, -59, -49, -31, -12, 13, 30, +60, 73, 83, 94, 78, 84, 24, 43, +-58, -29, -121, -103, -120, -141, -69, -113, +3, -28, 59, 78, 76, 153, 53, 156, +12, 78, -24, -36, -41, -129, -29, -153, +-19, -93, -29, 8, -38, 93, -30, 114, +-7, 76, 17, 1, 39, -66, 38, -86, +17, -55, -18, 3, -50, 51, -49, 62, +-24, 42, 3, 2, 17, -29, 14, -41, +-2, -39, -20, -27, -23, -16, -8, -2, +3, 22, 5, 48, -2, 60, -12, 49, +-11, 14, -5, -31, -8, -67, -9, -73, +-14, -44, -30, 0, -40, 35, -22, 53, +10, 52, 44, 39, 55, 20, 32, -2, +-11, -30, -46, -58, -71, -71, -72, -59, +-31, -18, 22, 44, 51, 94, 51, 99, +26, 55, -2, -18, -25, -80, -33, -103, +-34, -73, -30, -8, -15, 48, 0, 68, +7, 54, 19, 21, 27, -12, 24, -29, +2, -26, -34, -16, -52, -14, -38, -19, +-6, -19, 34, -10, 60, 12, 46, 38, +-3, 48, -56, 42, -89, 11, -75, -30, +-20, -60, 48, -66, 87, -46, 83, -6, +31, 44, -29, 70, -62, 68, -68, 35, +-54, -13, -33, -51, -5, -64, 12, -50, +23, -16, 41, 20, 63, 41, 61, 42, +24, 26, -44, 4, -105, -13, -116, -17, +-78, -14, -13, -8, 65, -8, 122, -15, +117, -16, 45, -7, -39, 7, -96, 28, +-100, 43, -62, 35, -14, 11, 28, -26, +61, -56, 58, -63, 24, -39, -12, 8, +-33, 55, -37, 73, -24, 53, -10, 8, +10, -46, 31, -75, 34, -66, 5, -20, +-22, 29, -37, 61, -40, 66, -29, 41, +-1, -1, 24, -41, 44, -61, 43, -55, +21, -28, -13, 8, -33, 36, -39, 49, +-31, 46, -17, 27, -5, -3, 3, -32, +22, -50, 32, -47, 24, -24, 10, 7, +1, 27, -10, 32, -21, 25, -30, 11, +-26, -1, -9, -5, 10, -6, 8, -8, +1, -13, 10, -21, 13, -20, 8, -11, +5, 3, 6, 19, 4, 31, -4, 30, +-24, 20, -40, 4, -28, -16, -10, -31, +-6, -37, 4, -34, 27, -20, 46, 11, +43, 50, 24, 74, -10, 71, -41, 31, +-69, -32, -86, -89, -66, -111, -3, -81, +65, -8, 108, 76, 107, 131, 55, 131, +-27, 69, -91, -31, -112, -123, -81, -156, +-21, -115, 40, -28, 68, 68, 70, 130, +39, 133, 3, 77, -17, -4, -19, -73, +-25, -104, -32, -87, -35, -41, -30, 11, +-6, 47, 34, 56, 61, 46, 68, 25, +40, 6, -21, -15, -81, -28, -96, -33, +-58, -30, 8, -13, 69, 9, 100, 28, +78, 37, 17, 33, -59, 10, -103, -22, +-95, -38, -41, -39, 23, -23, 69, 7, +89, 36, 71, 56, 22, 55, -38, 31, +-81, -15, -86, -61, -55, -86, -8, -73, +38, -21, 78, 47, 77, 101, 38, 106, +-11, 58, -53, -18, -70, -86, -44, -117, +5, -87, 38, -13, 48, 59, 22, 99, +-20, 86, -40, 34, -24, -27, 3, -63, +34, -63, 52, -37, 36, -7, -11, 17, +-50, 26, -58, 26, -34, 24, 9, 19, +35, 15, 32, 2, 27, -21, 5, -37, +-17, -42, -18, -24, 0, 6, 12, 34, +5, 46, -18, 35, -30, 11, -24, -13, +2, -24, 14, -17, 24, -6, 31, 5, +11, 10, -22, 2, -31, -9, -14, -15, +14, -7, 28, 6, 16, 18, -15, 27, +-38, 30, -50, 21, -29, -4, 18, -24, +65, -40, 78, -48, 51, -38, -6, -11, +-66, 31, -87, 62, -58, 72, -16, 58, +31, 13, 57, -40, 52, -78, 29, -84, +7, -51, -13, 4, -25, 56, -18, 73, +-19, 57, -35, 23, -35, -12, -10, -28, +27, -20, 58, -3, 62, 1, 30, -8, +-14, -30, -51, -45, -77, -30, -59, 9, +2, 59, 54, 91, 69, 87, 40, 43, +-4, -28, -32, -93, -36, -125, -30, -103, +-18, -36, 9, 46, 19, 113, 8, 131, +5, 96, 19, 28, 32, -50, 26, -98, +-16, -105, -55, -79, -63, -33, -37, 15, +3, 56, 53, 82, 91, 85, 80, 64, +21, 16, -43, -51, -86, -105, -83, -117, +-45, -74, 10, 6, 56, 91, 80, 134, +62, 110, 18, 24, -25, -75, -52, -130, +-58, -113, -29, -33, 4, 61, 25, 113, +34, 95, 32, 20, 13, -58, -5, -93, +-17, -66, -18, -1, -10, 61, 4, 75, +6, 37, 3, -21, 5, -62, 8, -62, +1, -23, -3, 26, -5, 52, -5, 50, +-6, 27, -7, -6, -2, -29, 17, -33, +30, -25, 17, -15, -8, -7, -23, 3, +-31, 18, -29, 33, -11, 33, 14, 19, +38, -4, 47, -31, 28, -45, 2, -37, +-16, -4, -33, 33, -40, 42, -28, 23, +0, -15, 29, -43, 43, -38, 34, -6, +12, 32, -8, 48, -21, 34, -35, 1, +-24, -34, 2, -42, 18, -17, 25, 14, +26, 27, 8, 10, -13, -21, -28, -43, +-28, -33, -9, 12, 15, 71, 27, 93, +35, 59, 26, -16, 6, -98, -26, -129, +-46, -90, -43, -5, -19, 81, 8, 126, +35, 102, 51, 28, 49, -41, 24, -82, +-11, -80, -40, -41, -48, 5, -45, 29, +-26, 28, 7, 18, 40, 15, 56, 19, +50, 23, 18, 12, -15, -15, -38, -42, +-53, -50, -45, -39, -3, -9, 41, 31, +58, 58, 43, 53, 8, 24, -33, -19, +-44, -55, -31, -56, -3, -31, 31, 3, +47, 33, 27, 41, -2, 25, -24, -2, +-34, -23, -19, -30, 13, -22, 34, -5, +30, 9, 11, 15, -16, 15, -28, 8, +-15, -3, 2, -8, 14, -11, 21, -9, +7, 1, -25, 15, -39, 21, -20, 21, +8, 17, 29, 2, 35, -19, 19, -31, +-5, -27, -20, -9, -37, 16, -36, 35, +-5, 29, 26, 9, 29, -14, 28, -26, +17, -15, 8, 5, -4, 18, -25, 16, +-45, -2, -40, -23, -17, -30, 12, -13, +46, 20, 77, 42, 67, 45, 13, 18, +-54, -25, -97, -56, -93, -57, -35, -25, +37, 23, 88, 58, 100, 57, 65, 25, +-7, -10, -66, -35, -88, -34, -65, -18, +-12, -2, 31, 7, 41, 6, 38, -4, +28, 2, 16, 21, 10, 39, -5, 42, +-21, 8, -34, -38, -46, -70, -42, -68, +-14, -22, 37, 40, 78, 85, 81, 83, +43, 34, -19, -35, -64, -87, -77, -87, +-62, -40, -20, 24, 41, 71, 77, 79, +71, 43, 40, -11, 3, -51, -31, -58, +-48, -48, -54, -19, -49, 13, -13, 33, +30, 50, 51, 55, 60, 39, 53, 3, +21, -41, -30, -78, -66, -87, -72, -46, +-41, 18, 12, 76, 52, 100, 61, 73, +47, 9, 16, -56, -21, -83, -39, -68, +-33, -26, -14, 13, 4, 32, 8, 25, +12, 8, 17, 6, 21, 21, 23, 30, +22, 16, 2, -19, -25, -66, -39, -91, +-33, -68, -10, 1, 19, 83, 40, 130, +41, 109, 22, 26, -4, -73, -27, -135, +-29, -127, -16, -54, -5, 40, 1, 101, +14, 104, 25, 53, 29, -16, 27, -57, +11, -52, -13, -21, -32, 8, -45, 14, +-36, -2, 1, -18, 43, -14, 58, 11, +44, 44, 7, 60, -26, 32, -50, -11, +-50, -46, -19, -54, 18, -28, 44, 12, +38, 38, 16, 33, -5, 10, -17, -10, +-18, -12, -7, 11, 3, 34, 2, 32, +-7, 0, -10, -40, -7, -61, 11, -44, +24, 9, 27, 58, 21, 71, 4, 45, +-22, -5, -32, -55, -19, -67, 1, -39, +16, 1, 19, 30, 13, 29, 10, 8, +7, -3, 1, 5, -5, 24, -4, 28, +-8, 5, -23, -39, -26, -77, -3, -81, +28, -33, 45, 49, 40, 108, 18, 104, +-16, 39, -45, -56, -52, -128, -28, -126, +15, -56, 52, 39, 56, 106, 32, 109, +-1, 44, -34, -35, -54, -82, -43, -78, +-17, -30, 20, 24, 47, 50, 52, 34, +40, -4, 14, -33, -23, -33, -54, -2, +-63, 35, -41, 43, 5, 21, 54, -16, +81, -47, 70, -51, 25, -25, -37, 19, +-76, 47, -72, 51, -36, 36, 14, 8, +58, -16, 72, -26, 49, -24, 4, -12, +-30, -3, -38, 4, -33, 20, -23, 33, +-9, 41, 10, 38, 24, 23, 26, -4, +25, -31, 18, -43, 8, -38, -8, -17, +-25, 18, -31, 51, -16, 68, 2, 57, +16, 17, 23, -29, 26, -62, 18, -67, +6, -43, -4, 4, -10, 51, -13, 72, +-14, 61, -20, 25, -17, -22, 8, -60, +31, -65, 33, -47, 30, -16, 15, 18, +-13, 41, -34, 47, -31, 31, -18, 5, +3, -31, 26, -59, 27, -65, 17, -51, +10, -10, 0, 33, -2, 51, 5, 37, +7, -3, -4, -45, -10, -60, -17, -37, +-20, 1, -5, 27, 21, 24, 35, -7, +33, -37, 16, -43, -7, -19, -21, 24, +-20, 55, -19, 41, -12, -9, 6, -63, +23, -83, 27, -50, 27, 13, 25, 68, +9, 82, -10, 44, -29, -20, -38, -62, +-20, -54, 10, -3, 24, 51, 26, 70, +18, 46, -2, -10, -20, -50, -23, -45, +-10, 0, 11, 59, 24, 90, 14, 72, +-14, 21, -25, -34, -21, -59, -9, -40, +15, 4, 34, 42, 29, 55, 10, 39, +-16, 19, -34, 5, -21, 1, 9, 9, +20, 11, 22, -3, 17, -23, -8, -27, +-25, -14, -10, 15, 13, 45, 29, 52, +32, 29, 14, -14, -22, -48, -42, -56, +-33, -36, -11, 5, 28, 34, 62, 37, +49, 20, 18, -13, -13, -35, -42, -41, +-48, -37, -24, -27, 10, -20, 32, -14, +41, -5, 36, 10, 19, 27, 4, 35, +-11, 11, -25, -39, -28, -89, -21, -108, +-14, -81, 1, -14, 30, 59, 54, 98, +54, 84, 31, 25, -11, -49, -48, -101, +-58, -106, -43, -63, -13, -3, 31, 39, +62, 51, 56, 35, 31, 9, 2, -4, +-23, 1, -36, 14, -32, 16, -21, 1, +-2, -33, 16, -57, 20, -48, 22, -6, +21, 56, 11, 105, -2, 108, -12, 67, +-15, -1, -7, -64, -1, -86, 1, -60, +10, -8, 13, 49, 3, 84, -4, 82, +2, 52, 14, 20, 20, -1, 17, -9, +4, -4, -16, -2, -25, -9, -22, -13, +-7, -5, 21, 19, 37, 48, 31, 62, +15, 45, -3, 11, -21, -24, -21, -47, +-6, -39, 8, -7, 15, 23, 11, 36, +-7, 25, -15, -4, -8, -23, 8, -28, +27, -14, 33, 3, 18, 12, -12, 2, +-39, -18, -45, -32, -21, -38, 22, -31, +53, -14, 61, -8, 41, -10, -2, -21, +-40, -30, -54, -25, -35, -16, 0, -7, +31, -3, 41, -10, 32, -22, 16, -35, +-2, -36, -19, -22, -21, -6, -12, 1, +-9, -5, -8, -16, 9, -25, 27, -20, +35, -4, 33, 15, 16, 23, -9, 9, +-27, -17, -38, -39, -31, -46, 3, -26, +36, 13, 43, 46, 34, 55, 25, 42, +6, 15, -12, -10, -19, -16, -23, -7, +-21, 3, -14, 12, -6, 10, 10, 6, +39, 19, 59, 48, 44, 76, 8, 83, +-28, 55, -62, 2, -71, -51, -32, -78, +23, -54, 61, 12, 81, 75, 63, 112, +7, 106, -39, 61, -59, -1, -55, -46, +-24, -59, 19, -47, 38, -16, 36, 17, +37, 35, 27, 47, 8, 47, -4, 34, +-19, 9, -35, -25, -33, -55, -17, -61, +6, -39, 41, 1, 62, 33, 46, 43, +9, 22, -23, -21, -49, -58, -51, -67, +-23, -46, 16, -12, 45, 16, 49, 19, +27, -3, 2, -35, -8, -56, -13, -55, +-16, -40, -1, -26, 12, -16, 12, -16, +8, -12, 1, -5, 1, -1, 4, 0, +6, -18, 3, -42, 8, -59, 18, -53, +13, -23, 6, 14, -1, 40, -12, 34, +-20, 3, -11, -35, 6, -49, 20, -27, +37, 10, 34, 45, 8, 51, -12, 25, +-27, -12, -37, -37, -25, -28, 2, 9, +20, 50, 28, 72, 34, 65, 24, 32, +7, -4, 2, -32, -4, -32, -21, -2, +-24, 28, -18, 51, -13, 59, 14, 51, +44, 37, 47, 21, 34, 8, 18, 1, +-15, 3, -45, 11, -48, 20, -36, 26, +-12, 24, 23, 14, 51, 4, 57, 3, +55, 13, 32, 29, -12, 28, -47, 14, +-61, -10, -54, -35, -25, -39, 20, -19, +57, 9, 74, 27, 60, 28, 17, 7, +-28, -23, -49, -40, -47, -38, -33, -22, +-3, -11, 28, -10, 35, -19, 31, -31, +27, -30, 23, -18, 10, -2, -7, -5, +-22, -30, -32, -59, -27, -69, -12, -47, +14, -5, 47, 31, 61, 42, 42, 13, +7, -47, -29, -90, -47, -97, -40, -62, +-15, -2, 16, 50, 38, 66, 45, 40, +29, 1, 7, -33, -5, -48, -15, -38, +-24, -21, -27, -8, -21, 0, -1, 6, +25, 19, 45, 37, 55, 48, 45, 44, +5, 25, -43, -5, -67, -27, -60, -27, +-20, -10, 33, 18, 69, 40, 75, 48, +44, 47, -4, 42, -46, 42, -62, 44, +-47, 38, -17, 18, 12, -10, 35, -37, +47, -43, 42, -10, 27, 42, 13, 89, +-9, 106, -34, 76, -45, 14, -34, -49, +-6, -79, 27, -62, 56, -15, 62, 42, +36, 75, -8, 71, -48, 32, -58, -16, +-33, -44, 7, -50, 34, -35, 47, -12, +41, 9, 10, 21, -18, 17, -21, 3, +-12, -18, 3, -43, 13, -59, 5, -60, +-3, -41, 5, -4, 15, 35, 13, 50, +19, 24, 20, -31, -3, -92, -23, -124, +-21, -99, -12, -27, 14, 47, 40, 93, +35, 81, 11, 13, -11, -71, -28, -128, +-39, -122, -15, -65, 27, 17, 42, 83, +43, 97, 31, 63, -6, 1, -37, -61, +-41, -93, -34, -87, -8, -49, 30, 9, +53, 67, 51, 103, 37, 105, 2, 69, +-41, -1, -62, -72, -53, -113, -25, -99, +20, -30, 68, 68, 80, 145, 57, 161, +12, 106, -38, 12, -70, -73, -56, -107, +-23, -75, 10, -2, 44, 63, 56, 89, +37, 75, 11, 45, 0, 20, -5, 22, +-11, 35, -16, 29, -29, -4, -26, -52, +-10, -78, 10, -56, 40, 11, 65, 91, +56, 132, 20, 104, -20, 20, -51, -68, +-57, -109, -32, -87, 4, -27, 34, 31, +53, 49, 48, 22, 19, -14, -6, -23, +-15, -2, -13, 22, 0, 28, 5, -2, +-4, -58, -14, -98, -10, -95, 1, -42, +24, 29, 53, 77, 50, 69, 23, 9, +-9, -57, -38, -94, -54, -84, -36, -35, +5, 10, 38, 31, 53, 20, 54, -10, +27, -30, 0, -33, -13, -19, -30, -2, +-37, 2, -20, -8, 1, -16, 18, -13, +39, 7, 49, 22, 39, 16, 17, -5, +-9, -32, -31, -41, -36, -18, -21, 25, +5, 56, 31, 56, 51, 22, 43, -23, +14, -47, -3, -39, -12, 8, -20, 65, +-18, 89, -7, 65, 5, 5, 14, -52, +26, -71, 32, -35, 29, 36, 20, 90, +-1, 100, -26, 62, -38, -1, -29, -52, +0, -63, 36, -30, 61, 23, 56, 61, +19, 62, -26, 30, -46, -12, -37, -30, +-7, -19, 33, 5, 60, 25, 51, 26, +18, 6, -23, -18, -45, -31, -28, -27, +10, -9, 38, 10, 45, 15, 36, 8, +9, 0, -21, 0, -28, -1, -8, -8, +12, -20, 22, -42, 21, -58, 6, -50, +1, -16, 5, 35, 11, 72, 17, 68, +18, 17, 9, -59, -9, -114, -15, -120, +-2, -70, 15, 17, 28, 87, 29, 104, +14, 61, -3, -14, -13, -77, -7, -96, +10, -67, 30, -17, 35, 27, 18, 46, +-2, 34, -18, 15, -18, 0, 2, -8, +28, -13, 46, -21, 36, -23, 9, -17, +-8, 3, -14, 38, -12, 65, 2, 56, +19, 11, 24, -48, 16, -79, 10, -61, +14, 1, 24, 81, 29, 126, 19, 99, +-3, 15, -19, -75, -26, -116, -17, -87, +13, -1, 48, 87, 65, 122, 54, 94, +19, 24, -27, -45, -50, -76, -41, -55, +-16, -7, 17, 35, 52, 48, 68, 33, +46, 14, 17, -1, -6, -6, -28, -7, +-28, -16, -13, -29, 5, -36, 31, -24, +53, 6, 55, 40, 36, 59, 15, 38, +-13, -11, -39, -66, -37, -97, -11, -83, +20, -28, 55, 39, 76, 82, 65, 81, +30, 41, -15, -22, -52, -78, -62, -100, +-36, -81, 7, -34, 52, 19, 84, 57, +84, 62, 48, 48, -4, 18, -46, -13, +-68, -37, -48, -55, -5, -53, 36, -37, +68, -15, 75, 12, 50, 40, 14, 58, +-12, 55, -29, 34, -29, -6, -9, -46, +11, -65, 23, -56, 29, -20, 27, 26, +27, 58, 29, 67, 20, 52, 5, 21, +-4, -11, -10, -32, -11, -39, 1, -31, +18, -11, 28, 16, 34, 43, 26, 64, +11, 65, 6, 37, 8, -9, 6, -56, +2, -75, 7, -58, 7, -2, 9, 58, +25, 95, 33, 88, 35, 32, 29, -43, +16, -95, -5, -90, -15, -37, -8, 36, +2, 84, 22, 78, 40, 32, 32, -23, +19, -62, 16, -60, 14, -22, 12, 20, +14, 35, 8, 22, -10, -9, -13, -36, +-3, -32, 15, -4, 45, 25, 70, 33, +59, 16, 22, -20, -17, -48, -47, -49, +-49, -25, -12, 5, 41, 25, 73, 27, +77, 8, 56, -13, 10, -16, -22, -10, +-29, -3, -19, -2, -1, -9, 19, -19, +28, -17, 27, 1, 36, 19, 44, 35, +39, 31, 25, 4, -3, -24, -30, -38, +-35, -29, -17, 1, 22, 30, 61, 47, +75, 35, 60, 4, 15, -22, -26, -31, +-39, -17, -23, 12, 11, 37, 46, 40, +60, 27, 45, 1, 18, -23, 1, -30, +0, -19, 6, 6, 17, 21, 22, 29, +13, 33, 9, 26, 17, 15, 30, 2, +43, -15, 47, -35, 23, -41, -16, -28, +-34, 1, -22, 46, 10, 81, 55, 77, +82, 34, 69, -34, 29, -96, -14, -117, +-36, -78, -28, 8, 7, 91, 41, 126, +55, 93, 47, 15, 21, -66, 1, -111, +0, -99, 19, -46, 33, 20, 29, 60, +14, 60, -7, 36, -14, 8, 4, -15, +36, -26, 59, -33, 60, -41, 34, -44, +-2, -34, -23, -5, -15, 34, 11, 66, +36, 61, 50, 17, 39, -36, 13, -74, +-5, -74, -4, -34, 20, 18, 41, 61, +44, 59, 33, 19, 9, -22, -9, -41, +-8, -29, 11, -1, 40, 20, 59, 23, +50, 6, 20, -15, -7, -20, -17, -3, +-6, 22, 20, 37, 42, 32, 53, 4, +46, -21, 25, -30, 3, -15, -9, 13, +-1, 35, 9, 36, 21, 15, 36, -10, +44, -20, 43, -14, 37, 6, 23, 25, +7, 28, -10, 22, -18, 5, -7, -9, +18, -11, 54, -9, 72, 0, 60, 10, +35, 9, 3, 7, -26, 10, -29, 8, +-1, 4, 33, -4, 61, -14, 64, -18, +50, -21, 28, -6, 6, 13, -4, 25, +-2, 25, 12, 5, 22, -20, 23, -41, +30, -46, 42, -27, 50, 7, 51, 40, +35, 53, 8, 34, -17, -8, -28, -58, +-12, -84, 24, -69, 69, -21, 87, 40, +75, 79, 40, 73, -4, 29, -32, -32, +-32, -79, -11, -81, 24, -49, 58, -3, +65, 35, 56, 47, 43, 36, 30, 12, +20, -4, 7, -8, -3, -15, -8, -25, +-3, -41, 13, -44, 40, -25, 75, 13, +86, 58, 60, 78, 20, 55, -19, 1, +-42, -52, -36, -72, 4, -49, 49, 6, +74, 54, 75, 62, 47, 33, 13, -9, +-4, -31, -6, -19, 7, 11, 29, 35, +39, 33, 25, 5, 11, -35, 15, -49, +26, -17, 39, 36, 52, 68, 52, 60, +32, 16, 11, -43, -8, -74, -13, -55, +6, -2, 35, 51, 54, 72, 64, 48, +58, 3, 37, -34, 11, -45, -7, -31, +-11, -5, 0, 8, 20, 9, 39, 4, +56, 9, 59, 28, 49, 38, 28, 27, +5, -9, -9, -54, -11, -78, 4, -61, +27, -4, 48, 61, 65, 91, 59, 70, +37, 7, 15, -61, 0, -96, -4, -79, +7, -24, 29, 32, 50, 60, 56, 48, +43, 13, 22, -22, 11, -40, 9, -32, +13, -14, 29, -1, 46, 3, 50, 1, +36, 0, 17, 5, 3, 12, -1, 12, +9, 1, 27, -17, 46, -25, 59, -22, +59, -5, 37, 19, 15, 32, 7, 19, +4, -6, 3, -26, 14, -35, 35, -25, +50, 2, 57, 28, 56, 41, 41, 36, +23, 12, 4, -16, -13, -34, -9, -34, +14, -19, 40, 3, 60, 25, 69, 33, +62, 29, 33, 21, 2, 11, -16, 0, +-8, -13, 11, -19, 28, -24, 47, -26, +56, -10, 53, 16, 42, 45, 24, 66, +14, 55, 8, 17, -2, -33, 1, -74, +19, -79, 45, -41, 64, 22, 68, 70, +58, 84, 28, 56, -8, 3, -31, -44, +-20, -64, 21, -50, 65, -15, 86, 15, +79, 24, 47, 19, 4, 10, -23, 6, +-22, 13, 10, 12, 49, 0, 63, -23, +57, -49, 41, -53, 19, -21, 5, 28, +10, 63, 27, 65, 39, 30, 38, -26, +24, -69, 14, -70, 20, -37, 37, 11, +47, 45, 45, 51, 25, 30, 7, -9, +0, -31, 9, -30, 41, -16, 70, -3, +72, 2, 41, -4, 4, -10, -21, -5, +-20, 9, 8, 26, 51, 30, 81, 17, +75, -9, 42, -32, 2, -36, -15, -21, +-8, 5, 15, 25, 38, 30, 51, 19, +46, 4, 32, -7, 25, -5, 30, 4, +40, 6, 41, -7, 24, -23, 1, -31, +-9, -21, 1, 11, 30, 49, 66, 71, +88, 56, 77, 9, 29, -45, -19, -80, +-39, -76, -22, -31, 21, 31, 62, 81, +84, 88, 78, 56, 37, 6, 2, -45, +-3, -68, 10, -56, 26, -23, 32, 14, +32, 31, 30, 33, 28, 29, 30, 24, +39, 16, 50, 0, 47, -22, 26, -40, +5, -42, 5, -25, 14, 13, 27, 44, +46, 49, 52, 23, 43, -20, 27, -48, +20, -48, 31, -16, 43, 33, 41, 57, +27, 34, 13, -17, 3, -60, 6, -69, +26, -31, 56, 28, 75, 71, 68, 64, +41, 14, 4, -42, -15, -71, -15, -47, +4, 0, 31, 43, 55, 49, 69, 14, +63, -30, 44, -45, 27, -26, 15, 13, +2, 41, -7, 37, -7, 2, 13, -38, +41, -48, 66, -26, 80, 15, 74, 43, +43, 37, -4, 5, -35, -32, -25, -50, +10, -27, 45, 17, 69, 45, 72, 36, +58, 1, 31, -32, 10, -41, 9, -21, +22, 12, 26, 32, 21, 23, 15, -4, +11, -21, 20, -19, 45, 3, 67, 30, +72, 36, 57, 9, 22, -32, -10, -55, +-21, -41, -8, 1, 21, 42, 51, 59, +72, 39, 69, 0, 49, -30, 25, -34, +11, -17, 7, 8, 6, 20, 5, 10, +11, -8, 31, -15, 45, 6, 49, 32, +58, 41, 52, 29, 28, -1, -2, -32, +-16, -43, -7, -25, 17, 8, 44, 30, +62, 25, 63, 9, 47, -9, 29, -17, +10, 4, 4, 28, 15, 32, 23, 12, +25, -26, 29, -58, 32, -60, 39, -30, +43, 19, 42, 60, 38, 71, 27, 54, +9, 15, 1, -29, 4, -54, 17, -65, +37, -60, 48, -34, 52, 4, 46, 48, +34, 76, 21, 80, 9, 49, 8, -11, +10, -72, 15, -102, 26, -89, 40, -33, +48, 35, 50, 79, 44, 79, 34, 43, +22, -6, 6, -41, -2, -51, 12, -45, +31, -27, 43, -8, 44, 11, 37, 28, +29, 39, 23, 41, 15, 29, 16, -5, +26, -43, 27, -60, 21, -49, 21, -11, +29, 38, 36, 68, 39, 62, 38, 23, +33, -28, 20, -57, 8, -52, 5, -22, +19, 11, 39, 36, 43, 44, 39, 28, +33, 8, 23, -1, 15, -3, 15, -6, +23, -11, 33, -21, 38, -25, 29, -11, +17, 15, 15, 40, 20, 53, 32, 39, +41, 9, 40, -21, 34, -42, 18, -38, +7, -20, 9, 6, 23, 24, 39, 29, +44, 23, 41, 13, 33, 2, 22, -7, +14, -11, 17, -12, 30, -16, 44, -19, +42, -9, 23, 5, 8, 13, 4, 16, +7, 17, 22, 10, 48, 0, 68, -9, +62, -12, 30, -11, 0, -15, -17, -18, +-16, -18, 7, -11, 41, 3, 66, 20, +71, 30, 53, 24, 24, 4, 1, -18, +-9, -35, -2, -43, 16, -35, 34, -11, +40, 16, 36, 27, 39, 20, 45, 6, +48, -7, 44, -16, 30, -18, 6, -17, +-17, -12, -19, -14, 0, -12, 33, -3, +78, 6, 94, 21, 78, 22, 37, 14, +-13, -3, -47, -20, -41, -33, -2, -29, +48, -9, 86, 14, 87, 30, 59, 28, +21, 14, -6, -4, -16, -13, -9, -11, +14, -2, 30, 6, 35, 10, 33, 4, +36, -4, 41, 0, 45, 7, 39, 15, +22, 18, 0, 13, -16, 1, -10, -11, +13, -10, 42, 1, 64, 12, 66, 12, +44, 3, 13, -3, -6, -6, -6, 3, +8, 18, 26, 28, 37, 21, 41, -10, +34, -39, 21, -45, 20, -27, 30, 7, +35, 44, 29, 60, 15, 42, 5, 2, +2, -38, 8, -52, 22, -38, 38, -11, +47, 12, 42, 23, 23, 24, 8, 15, +7, 3, 20, -7, 32, -13, 34, -20, +29, -30, 15, -30, -2, -18, 1, 2, +22, 25, 43, 35, 59, 27, 53, 9, +22, -14, -7, -35, -19, -43, -14, -35, +11, -18, 38, 4, 54, 20, 62, 27, +51, 30, 29, 23, 10, 4, -4, -23, +-7, -51, -1, -61, 4, -40, 18, -1, +42, 41, 60, 70, 68, 65, 54, 30, +23, -20, -11, -61, -35, -71, -36, -49, +-8, -8, 38, 33, 79, 58, 88, 61, +68, 42, 29, 12, -12, -21, -40, -39, +-35, -46, -9, -34, 25, -7, 58, 23, +68, 50, 63, 60, 44, 48, 15, 14, +-6, -23, -20, -45, -23, -45, -8, -25, +21, 5, 46, 36, 64, 48, 67, 38, +44, 19, 13, -4, -19, -19, -29, -28, +-13, -26, 13, -12, 41, 6, 57, 19, +54, 22, 32, 19, 10, 7, 1, -7, +-3, -14, 8, -21, 23, -11, 25, 5, +18, 15, 10, 15, 12, 3, 24, -15, +39, -25, 41, -23, 31, -8, 15, 10, +-4, 19, -13, 18, -3, 5, 18, -13, +41, -24, 51, -27, 39, -18, 19, -4, +7, 6, 0, 8, 7, 3, 21, -1, +25, -4, 30, -5, 14, 2, -2, 6, +5, 0, 22, -12, 37, -21, 46, -22, +45, -15, 24, 6, -6, 22, -22, 28, +-18, 20, 6, 0, 33, -15, 52, -21, +58, -16, 41, 4, 14, 17, -13, 16, +-21, 5, -9, -9, 10, -10, 29, 5, +39, 18, 42, 29, 35, 26, 16, 4, +5, -25, 9, -38, 15, -29, 20, -1, +19, 32, 11, 45, 12, 36, 18, 6, +19, -24, 32, -34, 41, -21, 31, 2, +17, 22, 0, 27, -7, 17, 0, 1, +14, -5, 21, -3, 31, -5, 34, -7, +26, -11, 17, -12, 12, -4, 21, 12, +27, 28, 22, 29, 9, 14, -9, -17, +-10, -45, -1, -50, 15, -30, 48, 3, +74, 29, 65, 41, 31, 32, -8, 6, +-40, -14, -47, -28, -27, -31, 6, -28, +54, -27, 75, -18, 72, -6, 60, 20, +14, 51, -20, 56, -37, 32, -46, -18, +-32, -65, 0, -86, 36, -63, 66, -9, +85, 49, 72, 81, 37, 69, -14, 24, +-58, -32, -63, -63, -41, -58, 3, -30, +53, 7, 87, 25, 94, 25, 58, 18, +11, 10, -24, 4, -49, 4, -46, -1, +-15, -21, 20, -29, 47, -23, 64, -2, +58, 29, 44, 44, 26, 34, -6, 4, +-18, -33, -23, -52, -24, -37, 5, 2, +30, 41, 45, 63, 53, 49, 48, 8, +27, -28, -3, -47, -19, -42, -19, -17, +-4, 17, 7, 40, 23, 43, 37, 32, +29, 13, 22, -4, 11, -20, 6, -30, +7, -24, 4, -6, 8, 17, 8, 33, +3, 37, 2, 22, 7, -7, 16, -31, +20, -35, 29, -19, 34, 6, 26, 31, +6, 32, -4, 11, -6, -15, -15, -37, +6, -40, 24, -18, 30, 7, 42, 25, +31, 26, 13, 12, 1, -6, -7, -16, +-11, -14, -2, -12, 10, -12, 18, -14, +35, -13, 24, -3, 13, 8, 20, 19, +11, 21, 8, 6, 5, -15, 0, -28, +3, -29, 3, -14, 10, 5, 25, 15, +39, 13, 35, 1, 18, -11, 2, -13, +-20, 4, -26, 18, -16, 21, 16, 9, +41, -7, 46, -20, 49, -24, 14, -7, +-17, 14, -26, 24, -24, 18, -3, 6, +22, -6, 45, -8, 50, 1, 33, 12, +-2, 19, -15, 6, -9, -15, -13, -24, +10, -17, 25, 4, 23, 30, 20, 41, +6, 29, 6, 6, 18, -21, 21, -29, +19, -20, 10, -4, -8, 12, -19, 11, +-11, 8, 1, 6, 29, 10, 54, 22, +49, 18, 31, 3, -11, -20, -28, -44, +-31, -44, -26, -16, 12, 25, 41, 56, +51, 59, 38, 28, 9, -19, -2, -58, +-3, -66, -2, -40, 7, 0, 20, 31, +11, 36, -2, 23, 0, 3, 0, -12, +29, -11, 46, -5, 38, -9, 25, -21, +-9, -35, -33, -34, -32, -12, -17, 29, +13, 59, 52, 56, 61, 21, 33, -32, +13, -71, -11, -73, -26, -37, -18, 12, +-3, 50, 23, 55, 25, 32, 16, 1, +15, -23, 10, -24, 18, -14, 18, -4, +8, -2, 1, -15, -7, -21, -13, -5, +-5, 22, 11, 48, 18, 58, 32, 32, +25, -15, 4, -52, 4, -61, -5, -38, +1, 4, 9, 38, 9, 48, 19, 35, +8, 11, -4, -9, 5, -15, 20, -10, +20, -5, 22, -10, 23, -16, 0, -13, +-7, 3, -18, 27, -16, 43, 10, 34, +22, 7, 35, -23, 31, -45, 20, -38, +7, -9, -2, 20, -4, 35, -13, 29, +-9, 9, 5, -17, 12, -24, 16, -13, +26, 3, 38, 10, 24, 4, 10, -4, +-6, -14, -20, -13, -13, 1, -21, 16, +-1, 14, 31, 1, 34, -10, 37, -15, +32, -12, 10, 3, -14, 13, -17, 6, +-27, -9, -19, -23, 13, -23, 23, -1, +38, 23, 36, 34, 22, 26, 14, -3, +-13, -36, -21, -54, -14, -42, 2, -9, +13, 28, 18, 47, 23, 46, 15, 22, +12, -10, 1, -27, 1, -31, 4, -24, +0, -12, 4, 1, -11, 15, -7, 22, +7, 25, 16, 23, 40, 13, 30, 3, +16, -11, 4, -25, -26, -26, -36, -19, +-13, -4, 14, 13, 28, 25, 43, 35, +30, 34, 8, 26, -11, 12, -36, -9, +-17, -29, 9, -44, 20, -40, 30, -15, +17, 18, 4, 45, -9, 61, -4, 50, +8, 24, 17, -6, 25, -33, 6, -48, +-9, -51, -25, -39, -14, -14, 15, 19, +30, 55, 47, 79, 34, 73, 11, 34, +-25, -27, -50, -86, -25, -108, 3, -82, +31, -17, 51, 60, 45, 112, 12, 108, +-15, 46, -19, -32, -21, -88, 8, -99, +21, -67, 22, -16, 26, 34, -2, 60, +-5, 58, 0, 35, 3, 6, 19, -21, +30, -42, 19, -50, -5, -48, -10, -28, +-10, 7, 3, 42, 16, 62, 17, 51, +27, 17, 15, -33, 2, -70, 3, -72, +5, -37, 13, 14, 6, 50, 5, 59, +-1, 38, -9, 0, 2, -27, 10, -32, +22, -22, 29, -5, 31, 5, 11, 7, +-15, 4, -17, 3, -25, 11, -4, 16, +12, 12, 20, 2, 46, -12, 34, -19, +15, -10, 4, 8, -7, 19, -18, 22, +-26, 6, -14, -22, 5, -37, 35, -25, +39, 11, 35, 51, 29, 63, -2, 41, +-19, -2, -31, -49, -23, -72, 2, -54, +23, -12, 40, 33, 28, 57, 20, 49, +13, 23, -3, -5, -6, -21, -4, -21, +5, -15, -2, -15, -3, -22, -1, -21, +9, -11, 31, 13, 22, 41, 31, 50, +24, 36, -5, -2, -13, -44, -20, -67, +-11, -56, 8, -17, 20, 28, 16, 53, +16, 44, 16, 15, 5, -16, 11, -26, +0, -15, -1, 1, 12, 11, -9, 7, +-15, -11, -9, -25, 5, -25, 23, -6, +24, 27, 31, 43, 27, 34, 10, 8, +-14, -23, -23, -41, -18, -34, -14, -12, +3, 14, 15, 28, 33, 23, 38, 8, +32, -6, 26, -7, -6, 1, -22, 8, +-27, 3, -31, -10, -9, -20, 24, -21, +48, -3, 49, 23, 37, 38, 6, 37, +-18, 16, -33, -15, -42, -34, -7, -34, +21, -16, 30, 12, 34, 37, 16, 42, +4, 30, -10, 12, -10, -10, 4, -25, +13, -30, 13, -24, -2, -7, -10, 14, +-15, 33, 1, 43, 28, 40, 33, 22, +32, -9, 13, -43, -7, -60, -26, -51, +-31, -14, -1, 32, 22, 65, 32, 73, +28, 46, 11, -1, -4, -44, -16, -66, +-11, -57, 7, -25, 26, 16, 19, 41, +9, 47, -2, 41, -26, 18, -7, -10, +13, -25, 19, -30, 33, -28, 18, -13, +-4, 5, -25, 23, -28, 33, -10, 29, +21, 12, 36, -8, 27, -27, 23, -33, +-4, -19, -28, 8, -26, 32, -8, 38, +24, 24, 30, -1, 28, -28, 16, -39, +-8, -26, -15, 1, -21, 34, -9, 48, +11, 34, 20, 11, 22, -19, 17, -36, +10, -30, 2, -7, 2, 21, -12, 35, +-19, 31, -6, 14, -5, -6, 11, -18, +25, -10, 28, 8, 31, 18, 13, 19, +-12, 11, -25, -2, -27, -13, -23, -10, +-1, 2, 26, 14, 33, 22, 42, 17, +31, 5, 5, 0, -15, 1, -35, 5, +-39, 9, -31, 6, -5, 0, 26, -6, +49, -4, 51, 10, 29, 25, 2, 34, +-32, 25, -55, 4, -52, -18, -15, -30, +26, -20, 44, 5, 53, 31, 37, 39, +-1, 28, -24, -4, -34, -32, -24, -31, +-4, -12, 16, 15, 24, 40, 20, 40, +10, 18, -2, -12, -5, -30, -14, -29, +-5, -12, 10, 15, 1, 38, 1, 40, +4, 26, 4, 7, 5, -12, -7, -19, +-10, -18, -5, -12, -3, 2, 2, 11, +18, 23, 25, 36, 12, 36, -4, 23, +-23, 1, -29, -25, -22, -37, -9, -25, +13, 3, 28, 29, 41, 45, 30, 44, +2, 24, -19, -5, -35, -24, -31, -28, +-20, -12, -11, 14, 8, 31, 29, 32, +35, 21, 21, 12, 11, 8, -12, 7, +-37, 9, -45, 5, -37, -3, -7, -7, +20, -1, 37, 10, 50, 21, 31, 34, +-5, 30, -36, 10, -45, -13, -37, -21, +-12, -11, 19, 11, 28, 31, 28, 34, +9, 20, -7, -7, -16, -22, -21, -10, +-9, 17, 1, 41, 2, 48, -9, 31, +-13, -9, -2, -44, 2, -47, 8, -17, +16, 28, 10, 67, -13, 73, -27, 44, +-31, 3, -27, -31, -7, -36, 6, -17, +13, 10, 15, 26, 3, 25, -7, 16, +-15, 11, -18, 18, -15, 30, -10, 36, +-11, 21, -13, -8, -7, -33, -3, -40, +4, -20, 11, 21, 9, 60, 3, 72, +-20, 56, -38, 17, -37, -24, -29, -39, +-9, -29, 14, -5, 33, 20, 27, 37, +5, 36, -18, 24, -38, 15, -44, 11, +-31, 9, -9, 7, 9, 0, 19, -4, +18, -3, 5, 5, -14, 24, -32, 38, +-38, 42, -28, 29, -18, 7, -3, -11, +14, -17, 16, -6, 4, 11, -9, 28, +-23, 35, -32, 28, -27, 19, -21, 13, +-10, 7, 3, 6, 3, 7, 0, 6, +-8, 6, -15, 8, -18, 15, -19, 24, +-20, 30, -23, 28, -17, 19, -11, 5, +-8, 0, -6, 5, -3, 13, -6, 21, +-22, 25, -32, 19, -32, 9, -26, 4, +-13, 10, -2, 23, 8, 34, 1, 37, +-17, 24, -33, 1, -36, -22, -29, -28, +-13, -13, 6, 19, 3, 55, -5, 66, +-16, 54, -36, 24, -42, -10, -33, -32, +-14, -30, 5, -10, 7, 17, 1, 38, +-11, 44, -31, 38, -47, 25, -45, 19, +-35, 19, -18, 12, 2, 5, 6, -1, +1, -7, -11, -5, -26, 6, -41, 29, +-46, 47, -40, 50, -30, 40, -16, 18, +-3, -1, 0, -6, -5, 0, -15, 10, +-33, 19, -48, 21, -46, 13, -39, 7, +-24, 11, -3, 30, 1, 52, 0, 52, +-12, 37, -34, 4, -40, -34, -44, -46, +-44, -30, -27, 8, -10, 54, -6, 84, +-6, 81, -11, 51, -24, 6, -34, -30, +-43, -42, -48, -33, -40, -5, -31, 31, +-18, 53, -1, 63, -4, 65, -17, 48, +-30, 20, -52, -8, -62, -33, -52, -38, +-33, -16, -13, 21, 0, 60, -1, 85, +-19, 78, -41, 37, -53, -11, -55, -43, +-47, -44, -29, -14, -21, 31, -17, 65, +-17, 73, -28, 54, -35, 22, -36, -6, +-37, -20, -33, -16, -30, 1, -39, 20, +-44, 33, -38, 39, -30, 38, -19, 33, +-14, 26, -23, 15, -32, 1, -49, -7, +-63, -6, -53, 5, -36, 26, -23, 44, +-16, 53, -20, 42, -33, 18, -46, -3, +-57, -6, -55, 3, -40, 20, -30, 39, +-29, 42, -34, 30, -44, 13, -47, 0, +-47, 4, -38, 16, -30, 34, -31, 46, +-37, 43, -50, 23, -56, 1, -51, -6, +-47, -1, -38, 12, -29, 30, -33, 41, +-41, 43, -47, 36, -55, 27, -56, 23, +-51, 20, -53, 17, -46, 5, -35, 0, +-40, 5, -38, 16, -37, 32, -45, 47, +-53, 54, -57, 40, -54, 17, -49, -2, +-40, -11, -31, -3, -34, 17, -50, 37, +-63, 39, -64, 32, -60, 24, -50, 19, +-36, 24, -30, 34, -36, 38, -51, 26, +-66, 10, -74, -9, -67, -15, -50, 4, +-41, 35, -35, 63, -35, 71, -46, 53, +-60, 24, -66, -7, -68, -22, -64, -13, +-55, 12, -58, 40, -58, 55, -48, 51, +-45, 35, -41, 18, -38, 13, -53, 17, +-66, 18, -77, 17, -87, 15, -75, 9, +-52, 9, -35, 23, -27, 43, -29, 53, +-47, 50, -74, 35, -94, 13, -100, -7, +-81, -16, -56, -1, -36, 26, -29, 50, +-35, 59, -50, 52, -74, 33, -83, 9, +-85, -2, -77, 0, -67, 17, -64, 29, +-55, 33, -48, 35, -52, 32, -61, 29, +-64, 31, -74, 33, -80, 27, -77, 21, +-77, 12, -70, 10, -58, 12, -58, 26, +-60, 39, -59, 45, -73, 46, -77, 35, +-76, 23, -78, 11, -68, 4, -60, 5, +-60, 11, -64, 26, -70, 37, -72, 44, +-75, 48, -76, 42, -70, 26, -66, 8, +-66, -5, -67, -5, -75, 12, -74, 36, +-77, 57, -83, 63, -78, 49, -72, 22, +-71, 0, -67, -5, -67, 8, -72, 30, +-76, 49, -83, 47, -90, 32, -86, 15, +-81, 5, -73, 18, -60, 38, -62, 55, +-70, 55, -75, 28, -87, -5, -91, -23, +-83, -13, -79, 21, -71, 56, -64, 75, +-75, 71, -83, 41, -83, 1, -86, -13, +-81, -5, -69, 13, -70, 36, -80, 43, +-89, 32, -95, 19, -96, 19, -85, 33, +-69, 51, -62, 61, -62, 46, -74, 12, +-98, -18, -111, -31, -108, -12, -96, 31, +-76, 78, -65, 99, -68, 83, -70, 38, +-87, -9, -101, -36, -95, -28, -96, 8, +-90, 44, -82, 68, -87, 63, -83, 37, +-78, 15, -85, 11, -85, 19, -80, 31, +-89, 42, -98, 40, -103, 24, -105, 7, +-94, 3, -82, 12, -73, 31, -71, 51, +-79, 60, -97, 59, -112, 38, -114, 16, +-109, 6, -94, 1, -77, 7, -70, 21, +-73, 35, -81, 43, -94, 47, -114, 50, +-118, 43, -108, 28, -98, 18, -81, 10, +-72, 7, -72, 9, -73, 18, -93, 34, +-118, 48, -122, 51, -118, 47, -103, 36, +-75, 22, -66, 12, -69, 7, -75, 4, +-101, 11, -121, 28, -125, 47, -120, 58, +-98, 58, -79, 45, -74, 24, -75, 3, +-90, -6, -106, -3, -110, 19, -112, 48, +-110, 66, -102, 64, -97, 45, -90, 17, +-84, -2, -85, -3, -87, 11, -98, 33, +-110, 48, -118, 45, -127, 34, -112, 18, +-90, 18, -80, 33, -66, 41, -71, 44, +-98, 37, -120, 13, -139, -9, -139, -15, +-109, 7, -83, 42, -63, 73, -58, 85, +-81, 66, -109, 26, -132, -11, -145, -31, +-129, -21, -103, 13, -80, 44, -64, 64, +-72, 67, -93, 52, -112, 37, -128, 23, +-132, 19, -122, 18, -105, 11, -92, 5, +-86, 4, -85, 11, -87, 34, -98, 63, +-111, 79, -122, 75, -128, 46, -122, 5, +-112, -24, -99, -29, -80, -5, -75, 34, +-84, 64, -98, 74, -121, 64, -138, 37, +-132, 12, -119, 1, -98, 8, -78, 27, +-80, 38, -90, 36, -101, 26, -118, 18, +-125, 20, -118, 28, -114, 40, -103, 45, +-92, 40, -95, 27, -97, 16, -101, 15, +-108, 24, -113, 36, -120, 40, -119, 30, +-109, 19, -103, 14, -97, 21, -95, 38, +-101, 57, -113, 64, -124, 48, -127, 19, +-118, -6, -102, -15, -86, -1, -81, 29, +-95, 59, -112, 68, -126, 57, -135, 35, +-122, 11, -104, 4, -90, 10, -79, 19, +-92, 31, -115, 39, -129, 39, -137, 37, +-128, 36, -103, 34, -90, 32, -82, 24, +-86, 12, -105, 6, -116, 10, -119, 24, +-124, 44, -117, 55, -107, 51, -105, 37, +-104, 21, -102, 3, -97, 0, -98, 17, +-105, 34, -114, 46, -124, 48, -127, 41, +-121, 31, -106, 22, -89, 15, -77, 13, +-82, 16, -102, 19, -123, 25, -142, 36, +-139, 47, -120, 51, -97, 43, -71, 25, +-70, 8, -87, -4, -108, 0, -132, 17, +-140, 39, -128, 56, -111, 54, -90, 38, +-74, 17, -80, 7, -94, 11, -110, 23, +-130, 36, -135, 40, -126, 30, -113, 15, +-91, 9, -77, 17, -74, 34, -84, 53, +-110, 56, -134, 39, -136, 5, -128, -14, +-115, -6, -94, 20, -77, 48, -70, 63, +-84, 60, -111, 35, -131, 8, -142, -1, +-136, 8, -115, 31, -94, 48, -74, 47, +-70, 29, -85, 8, -104, -1, -126, 14, +-136, 39, -132, 62, -125, 66, -110, 46, +-89, 11, -74, -23, -69, -24, -77, 4, +-99, 41, -124, 75, -146, 75, -150, 47, +-128, 11, -94, -14, -67, -12, -51, 12, +-59, 35, -89, 49, -129, 50, -160, 34, +-160, 15, -130, 10, -90, 19, -58, 32, +-49, 39, -63, 30, -95, 17, -131, 7, +-149, 8, -141, 21, -116, 41, -92, 55, +-75, 48, -72, 28, -77, 6, -93, -8, +-107, -7, -113, 13, -118, 40, -121, 56, +-111, 53, -99, 36, -86, 15, -74, 4, +-80, 4, -88, 9, -103, 24, -122, 37, +-128, 43, -120, 37, -103, 25, -77, 16, +-66, 14, -77, 16, -91, 22, -113, 31, +-127, 34, -122, 30, -109, 23, -92, 17, +-73, 14, -73, 18, -85, 25, -97, 34, +-111, 41, -119, 36, -116, 25, -109, 16, +-100, 11, -89, 13, -79, 22, -79, 34, +-90, 45, -100, 40, -110, 26, -120, 16, +-116, 9, -103, 11, -85, 22, -72, 34, +-75, 36, -84, 31, -98, 18, -115, 10, +-121, 14, -109, 26, -93, 36, -76, 41, +-74, 34, -81, 13, -90, -2, -105, -4, +-113, 11, -105, 35, -95, 55, -92, 61, +-87, 43, -89, 12, -94, -7, -93, -10, +-94, 7, -93, 32, -91, 49, -95, 49, +-99, 31, -101, 10, -97, 1, -89, 13, +-80, 33, -79, 49, -88, 50, -100, 30, +-107, -4, -104, -25, -95, -19, -79, 14, +-74, 55, -74, 77, -82, 74, -101, 41, +-105, -2, -104, -25, -99, -26, -83, -5, +-74, 28, -75, 49, -83, 57, -98, 49, +-105, 32, -100, 22, -90, 18, -83, 18, +-78, 14, -78, 4, -85, -3, -91, -2, +-96, 15, -96, 45, -92, 66, -85, 68, +-82, 49, -76, 12, -77, -19, -85, -30, +-91, -16, -96, 14, -96, 42, -90, 58, +-81, 56, -72, 37, -70, 20, -70, 5, +-81, 1, -95, 3, -101, 10, -105, 18, +-96, 27, -83, 35, -74, 39, -63, 40, +-66, 35, -81, 21, -90, 7, -95, -1, +-99, 1, -91, 11, -81, 27, -79, 38, +-71, 37, -69, 31, -74, 18, -71, 9, +-79, 12, -90, 15, -91, 16, -96, 17, +-93, 18, -80, 21, -67, 23, -56, 26, +-52, 28, -65, 23, -87, 18, -108, 9, +-112, 2, -97, 7, -74, 20, -54, 35, +-48, 39, -53, 31, -72, 17, -96, 4, +-107, 1, -100, 11, -84, 22, -62, 32, +-56, 31, -56, 17, -65, 5, -80, 4, +-89, 12, -88, 26, -82, 36, -79, 38, +-73, 25, -75, 9, -75, -1, -67, 0, +-64, 15, -68, 29, -69, 34, -80, 32, +-90, 19, -92, 7, -82, 6, -69, 21, +-59, 33, -55, 34, -60, 26, -74, 8, +-89, -7, -91, -5, -95, 16, -81, 37, +-62, 50, -51, 46, -50, 30, -61, 6, +-72, -15, -79, -14, -89, -2, -84, 15, +-74, 33, -68, 41, -60, 35, -53, 27, +-60, 24, -66, 15, -69, 9, -81, 3, +-82, -2, -76, -4, -70, 6, -65, 22, +-56, 38, -60, 49, -63, 46, -70, 30, +-78, 4, -72, -15, -67, -17, -68, -6, +-61, 11, -58, 31, -71, 46, -69, 41, +-67, 27, -63, 11, -56, -1, -54, -2, +-61, 3, -72, 10, -76, 16, -76, 20, +-70, 23, -59, 22, -49, 21, -47, 22, +-56, 17, -74, 12, -78, 8, -77, 2, +-67, 3, -53, 15, -50, 28, -57, 33, +-61, 28, -68, 16, -76, 6, -69, -1, +-61, 1, -51, 13, -53, 25, -56, 29, +-62, 23, -61, 11, -64, 1, -65, 2, +-55, 3, -51, 12, -59, 24, -56, 23, +-62, 20, -64, 14, -59, 7, -60, 8, +-55, 11, -56, 14, -57, 15, -57, 14, +-63, 17, -66, 17, -53, 12, -55, 14, +-53, 12, -49, 9, -57, 10, -61, 14, +-65, 16, -63, 19, -62, 22, -57, 21, +-55, 17, -51, 9, -51, 7, -52, 8, +-57, 11, -61, 19, -68, 19, -59, 16, +-57, 16, -55, 12, -41, 12, -43, 14, +-49, 13, -56, 12, -64, 6, -66, 3, +-61, 8, -56, 20, -49, 33, -49, 35, +-51, 28, -56, 12, -59, -6, -60, -16, +-49, -9, -45, 12, -47, 31, -52, 42, +-56, 34, -58, 13, -62, -4, -45, -15, +-38, -10, -38, 11, -40, 25, -55, 29, +-61, 17, -60, 4, -60, -2, -40, -1, +-35, 14, -37, 26, -43, 31, -59, 17, +-64, -2, -60, -13, -47, -9, -41, 8, +-32, 27, -37, 37, -52, 33, -63, 15, +-66, -2, -65, -8, -46, -4, -27, 9, +-26, 24, -29, 27, -52, 20, -66, 6, +-68, -6, -65, -4, -45, 6, -23, 23, +-27, 33, -27, 26, -40, 8, -55, -9, +-65, -14, -65, -7, -53, 10, -43, 29, +-33, 42, -32, 37, -36, 18, -43, -4, +-47, -18, -51, -16, -52, -2, -56, 18, +-43, 32, -42, 37, -43, 27, -34, 12, +-36, -2, -41, -8, -40, -8, -40, -2, +-41, 10, -43, 18, -48, 19, -43, 17, +-48, 13, -45, 10, -36, 9, -31, 13, +-37, 17, -38, 12, -42, 8, -59, 4, +-61, -2, -47, 3, -41, 14, -29, 23, +-16, 28, -27, 23, -35, 14, -55, -2, +-61, -13, -55, -10, -43, -1, -26, 14, +-12, 25, -24, 27, -38, 22, -47, 9, +-59, -2, -53, -2, -42, 6, -30, 13, +-27, 15, -26, 9, -35, 2, -43, -1, +-46, 7, -43, 21, -42, 31, -29, 27, +-32, 15, -35, -6, -34, -24, -47, -24, +-36, -6, -33, 22, -33, 43, -25, 48, +-29, 35, -45, 8, -44, -23, -45, -35, +-39, -24, -33, 0, -24, 26, -20, 44, +-27, 44, -31, 21, -37, 1, -40, -15, +-42, -21, -39, -10, -30, 1, -22, 9, +-31, 21, -24, 24, -31, 18, -31, 13, +-27, 14, -37, 12, -37, 3, -33, -10, +-33, -16, -29, -14, -25, -5, -27, 19, +-22, 38, -29, 44, -31, 34, -33, 10, +-39, -12, -46, -28, -39, -25, -30, -5, +-25, 19, -15, 37, -11, 40, -19, 25, +-32, 9, -46, -6, -58, -12, -45, -8, +-36, 2, -10, 9, 8, 13, -2, 13, +-11, 6, -26, 2, -55, 1, -54, 2, +-40, 4, -26, 7, -6, 8, 0, 9, +-8, 12, -29, 9, -38, 6, -47, 8, +-45, 9, -31, 4, -15, 2, -10, 5, +-11, 5, -25, 7, -20, 6, -23, 8, +-32, 9, -19, 6, -23, 3, -30, -1, +-28, -3, -32, 3, -29, 7, -11, 13, +-10, 21, -3, 20, -18, 15, -36, 2, +-40, -12, -46, -11, -45, 0, -26, 13, +0, 24, 4, 29, 0, 24, -10, 9, +-33, -8, -50, -18, -42, -14, -40, -1, +-13, 11, 4, 21, 9, 22, 7, 17, +-19, 9, -40, 2, -44, -4, -50, -4, +-34, 2, -8, 7, -1, 11, 5, 14, +-2, 16, -15, 14, -35, 9, -35, 1, +-31, -6, -22, -10, -9, -7, -5, 5, +-8, 13, -11, 22, -22, 24, -23, 14, +-14, 0, -20, -10, -9, -10, -15, -5, +-24, 0, -19, 10, -17, 16, -21, 16, +-8, 14, -7, 12, -9, 9, -16, 7, +-26, 5, -28, 0, -28, -2, -21, -2, +-8, -2, 5, 7, -3, 16, -8, 20, +-16, 18, -21, 3, -25, -8, -9, -13, +-7, -11, -10, 3, -7, 16, -14, 18, +-16, 14, -16, 7, -17, 1, -9, -2, +-7, 4, -14, 14, -11, 20, -24, 16, +-20, 4, -15, -3, -8, -11, -3, -8, +2, 4, 2, 15, -17, 25, -24, 21, +-20, 7, -19, -1, -13, -4, 1, -3, +2, 4, 5, 11, -12, 12, -15, 6, +-18, 3, -30, 5, -18, 6, 1, 11, +-1, 19, 6, 18, 6, 11, -12, -2, +-16, -14, -23, -14, -18, -7, -14, 11, +-6, 29, 0, 38, 0, 32, -2, 10, +-3, -11, -8, -22, -11, -21, -15, -9, +-5, 11, -8, 29, -18, 34, -3, 23, +-4, 8, -4, -5, 6, -11, 8, -8, +-1, 0, -5, 8, -20, 11, -20, 8, +-21, 7, -10, 6, 12, 9, 22, 15, +17, 18, 5, 11, -10, 0, -34, -13, +-35, -17, -17, -9, 2, 8, 19, 29, +34, 42, 15, 35, -1, 11, -19, -15, +-32, -32, -21, -33, -5, -13, 8, 20, +21, 41, 18, 42, 5, 29, 2, 3, +-17, -15, -18, -23, -5, -17, 6, -3, +9, 11, 10, 21, 6, 17, -2, 7, +-1, 2, 0, 6, 3, 11, 6, 15, +6, 10, 1, -1, -3, -11, -16, -16, +-2, -11, 5, 9, 7, 31, 16, 44, +17, 36, 3, 14, -5, -14, -9, -36, +-9, -34, -4, -13, 3, 17, 17, 36, +19, 40, 17, 27, 9, 6, 0, -10, +-11, -16, -8, -10, 1, 2, 5, 13, +6, 13, 20, 4, 13, 1, 2, 3, +9, 9, 3, 18, 6, 20, 10, 10, +10, -4, 6, -16, 1, -19, -5, -9, +8, 6, 12, 25, 17, 33, 24, 26, +17, 8, 5, -13, -1, -19, -7, -15, +-10, -1, 4, 15, 19, 22, 25, 19, +24, 9, 20, -2, 3, -3, -3, -1, +-7, 5, -3, 14, 11, 13, 14, 6, +20, -1, 23, -7, 13, -8, 11, 2, +11, 15, 4, 20, 4, 25, 1, 18, +4, 2, 6, -14, 19, -20, 22, -10, +24, 2, 22, 18, 12, 29, 2, 29, +-7, 17, -8, 1, 5, -11, 17, -11, +21, -7, 36, 4, 27, 13, 13, 13, +5, 13, -2, 10, -6, 6, 6, 6, +18, 5, 29, 2, 29, 1, 22, -4, +17, -4, 5, 1, -1, 10, 1, 22, +11, 25, 15, 18, 25, 3, 28, -11, +17, -15, 9, -13, 13, 0, 5, 19, +7, 29, 16, 27, 19, 14, 23, -3, +18, -16, 16, -16, 15, -9, 17, 3, +17, 18, 23, 24, 17, 19, 14, 9, +11, 1, 6, -5, 7, -5, 18, -1, +27, 1, 34, 2, 34, 5, 23, 7, +13, 8, 1, 9, 2, 6, 11, 2, +24, 0, 26, -3, 39, -6, 35, 0, +16, 11, 4, 20, -1, 20, 1, 11, +15, -1, 32, -10, 34, -9, 33, -2, +22, 9, 12, 18, 8, 16, 10, 13, +13, 4, 23, 0, 20, -2, 21, -2, +24, 3, 14, 12, 12, 15, 22, 13, +22, 13, 17, 10, 23, 3, 19, -3, +16, -7, 18, -8, 23, -4, 25, 4, +33, 10, 33, 14, 26, 21, 12, 19, +7, 2, 15, -11, 20, -18, 23, -14, +29, -1, 35, 9, 27, 19, 28, 21, +21, 19, 9, 11, 8, -3, 20, -16, +26, -16, 32, -9, 33, 1, 33, 11, +28, 16, 19, 14, 17, 10, 15, 6, +12, 3, 17, -1, 30, -3, 27, -1, +30, -1, 31, 2, 29, 2, 21, 7, +17, 12, 13, 14, 12, 12, 16, 4, +25, -2, 34, -6, 34, -7, 36, -4, +32, 4, 19, 11, 8, 16, 11, 14, +12, 8, 19, 2, 30, -4, 38, -2, +32, 1, 28, 7, 22, 13, 13, 11, +14, 5, 15, 1, 22, 1, 27, -2, +33, -1, 36, 6, 33, 10, 22, 9, +19, 6, 20, -2, 20, -5, 21, 0, +27, 8, 24, 13, 25, 6, 36, 1, +29, -3, 29, -7, 29, -5, 27, 5, +25, 14, 19, 13, 15, 12, 22, 2, +24, -10, 29, -10, 40, -4, 39, 5, +32, 12, 31, 12, 20, 7, 9, 0, +14, -6, 18, -4, 32, 1, 39, 9, +40, 15, 39, 13, 26, 2, 14, -8, +17, -16, 20, -13, 24, 1, 32, 14, +40, 21, 39, 15, 32, 6, 24, -3, +13, -11, 16, -11, 19, -1, 27, 7, +35, 11, 35, 13, 30, 10, 28, 0, +22, -2, 24, -1, 28, -1, 28, 3, +31, 1, 30, -4, 32, -7, 23, -1, +23, 2, 32, 3, 33, 12, 30, 16, +32, 10, 27, -4, 28, -12, 23, -13, +18, -11, 27, -3, 29, 8, 38, 13, +42, 16, 33, 14, 30, 4, 23, -6, +14, -13, 21, -10, 24, -7, 32, 0, +42, 12, 34, 18, 30, 14, 26, 5, +20, 0, 22, -4, 20, -4, 32, -8, +41, -6, 37, -3, 33, 4, 27, 5, +32, 3, 25, 11, 24, 11, 29, 4, +30, -9, 32, -11, 33, -11, 31, -8, +30, 5, 28, 15, 26, 20, 29, 12, +27, 2, 35, -15, 39, -23, 35, -18, +32, -7, 30, 6, 24, 13, 28, 16, +30, 10, 33, 1, 35, -10, 37, -16, +37, -13, 26, -5, 22, 2, 23, 11, +24, 8, 32, 2, 39, 3, 36, -2, +40, -1, 26, 3, 21, 2, 23, -6, +19, -6, 28, -7, 37, -6, 42, 4, +37, 14, 32, 15, 30, 4, 23, -7, +22, -14, 27, -13, 28, -7, 36, 3, +39, 9, 37, 10, 32, 6, 24, -4, +28, -8, 25, -4, 24, 1, 36, -3, +42, 1, 34, 1, 33, -5, 32, -4, +26, -4, 26, 0, 30, 4, 32, 4, +37, 1, 36, -2, 35, -6, 31, 0, +20, 0, 22, -3, 33, 0, 33, 2, +35, 2, 42, -1, 34, 1, 29, -6, +26, -4, 20, 2, 25, 4, 33, 3, +42, -3, 49, 0, 34, -5, 29, -9, +26, -4, 11, 7, 22, 6, 31, 10, +40, 7, 48, -3, 37, -8, 34, -10, +26, -8, 15, -5, 27, 2, 27, 7, +34, 9, 45, -1, 45, -4, 40, -3, +27, -12, 26, -10, 23, -6, 24, -2, +34, 0, 42, 7, 45, 5, 38, 3, +26, -3, 24, -6, 13, -5, 22, -7, +38, 1, 39, 2, 48, 3, 42, -1, +28, -1, 25, -7, 22, -10, 23, -5, +39, -3, 36, 0, 43, 1, 46, 1, +27, -1, 27, 6, 16, 3, 13, -5, +39, -11, 38, -12, 48, -6, 53, 1, +32, 6, 30, 10, 14, 5, 13, -12, +31, -10, 30, -8, 45, -2, 50, 9, +36, 11, 35, 4, 22, -3, 16, -7, +25, -17, 34, -10, 47, -5, 48, 0, +46, 1, 40, -1, 28, -1, 21, -2, +23, -1, 28, 0, 34, 0, 41, -10, +45, -5, 37, -2, 29, -3, 28, 2, +27, 6, 28, 2, 33, 0, 39, 0, +42, -8, 37, -7, 29, -9, 34, -7, +27, -8, 32, -3, 46, 5, 36, 12, +37, 9, 32, -2, 21, -5, 27, -18, +19, -13, 31, -4, 50, 1, 43, 2, +50, 8, 40, 3, 24, -8, 19, -2, +14, -3, 24, -2, 35, -4, 46, -7, +58, -10, 52, -8, 35, -5, 27, 3, +21, 7, 11, 3, 22, 2, 46, -11, +51, -14, 52, -7, 44, -2, 30, -2, +20, 3, 11, 4, 25, -1, 39, 0, +42, -1, 53, -3, 51, -10, 35, -11, +27, -11, 24, -5, 25, -1, 28, 7, +41, 5, 51, -8, 49, -7, 41, -10, +36, -9, 31, -7, 25, 2, 28, -2, +34, -6, 44, -9, 44, -6, 43, -2, +46, -3, 28, 7, 24, 3, 32, -9, +35, -17, 48, -7, 41, -3, 37, 4, +34, 10, 20, 1, 30, -4, 30, -4, +36, -5, 52, -7, 45, 0, 45, -4, +29, -1, 18, -7, 29, -5, 20, 5, +39, -3, 57, -4, 52, -5, 52, -6, +34, -9, 20, 5, 16, 3, 17, -2, +32, 0, 49, -7, 51, -8, 54, -6, +43, 6, 24, 4, 20, 2, 19, -8, +30, -8, 40, -9, 45, -8, 59, 1, +48, -2, 35, -4, 32, -7, 21, -8, +34, -13, 38, -2, 41, 4, 57, -1, +38, -6, 41, -13, 41, -15, 22, -12, +41, -3, 36, 3, 42, 5, 54, -6, +36, -5, 41, -4, 30, -10, 19, -5, +35, 1, 32, -3, 41, -7, 57, -1, +50, -7, 46, 2, 31, 3, 17, -1, +24, -7, 28, -13, 38, -11, 58, -4, +54, 4, 43, 5, 36, 9, 20, -6, +23, -9, 27, -6, 40, -8, 56, -8, +52, -2, 48, -5, 38, -10, 28, -1, +26, -1, 27, 5, 44, 1, 46, -3, +47, -11, 51, -13, 35, -12, 34, -1, +27, 7, 25, 4, 38, 7, 36, -7, +50, -11, 50, -4, 33, 0, 45, -8, +36, -4, 29, -6, 39, -13, 36, -7, +46, -3, 44, 5, 37, 0, 43, -4, +37, -9, 28, -9, 42, -13, 45, -3, +38, 6, 46, -4, 37, 1, 28, -2, +29, -6, 24, -4, 38, 3, 45, -1, +42, -2, 58, -5, 46, -12, 32, -6, +29, -4, 20, 0, 28, -3, 38, -6, +50, -9, 61, -3, 54, -4, 40, -1, +32, 4, 18, -6, 13, -10, 36, -10, +46, -5, 52, -3, 63, 5, 46, 0, +37, -7, 27, -11, 19, -13, 35, 1, +31, 3, 45, 2, 60, -3, 48, -11, +44, -18, 36, -5, 29, 0, 28, 5, +28, 10, 42, -5, 47, -15, 48, -16, +46, -5, 37, -2, 38, 6, 29, 3, +32, 0, 38, -5, 36, -12, 47, -5, +46, -4, 41, -7, 41, -5, 32, -2, +36, -11, 42, -1, 40, 2, 46, -1, +42, 0, 30, -6, 34, -14, 37, -14, +36, -2, 47, 4, 40, 10, 45, -2, +45, -7, 26, -9, 34, -10, 27, 3, +25, 7, 50, -2, 46, -9, 52, -7, +48, -14, 28, 0, 32, 9, 18, 8, +27, 1, 49, -11, 45, -15, 57, -17, +51, -8, 40, -3, 34, 8, 19, 1, +29, 0, 34, -1, 38, -10, 54, -8, +47, 0, 39, -3, 36, -7, 29, 1, +33, -7, 35, 0, 32, 4, 43, 0, +38, -4, 36, -9, 45, -7, 35, 0, +33, 7, 34, 2, 33, 2, 42, -12, +39, -16, 41, -6, 47, -1, 33, -1, +41, 2, 41, -5, 36, -14, 42, -5, +38, -6, 47, -3, 47, -7, 38, -7, +39, -7, 30, -11, 36, -9, 44, 3, +41, 12, 45, 1, 37, 0, 34, -8, +30, -17, 26, -10, 39, 1, 46, 1, +46, 8, 44, 5, 39, -10, 38, -11, +29, -10, 28, -3, 39, -2, 42, -3, +44, -5, 48, 1, 39, -2, 33, 1, +35, 5, 30, -10, 40, -13, 44, -16, +41, -11, 48, -1, 37, 10, 37, 6, +43, 3, 28, -3, 39, -19, 45, -15, +37, -9, 43, -1, 38, 0, 41, -3, +43, -5, 33, 2, 37, -4, 41, -2, +39, 2, 39, -9, 41, -11, 37, -11, +36, -8, 43, -8, 37, 7, 41, 4, +42, -1, 41, -8, 50, -13, 34, -5, +30, -3, 35, -1, 27, 0, 39, -4, +44, -10, 46, 1, 51, 0, 42, -4, +35, 1, 30, -7, 23, -13, 33, -14, +47, -5, 49, 1, 51, 7, 50, -1, +37, -7, 31, -12, 27, -15, 30, -4, +42, 2, 42, 0, 51, -3, 52, -5, +38, -15, 34, -5, 31, 2, 30, 1, +34, 3, 39, -4, 45, -12, 44, -12, +45, -7, 43, -4, 40, 5, 37, -4, +32, -8, 44, -8, 35, -12, 38, -4, +48, 2, 37, 0, 42, -6, 42, -4, +32, -11, 46, -9, 38, -1, 37, 3, +43, 2, 30, -5, 41, -10, 42, -11, +38, -5, 45, -4, 42, 5, 39, -2, +42, -6, 34, -3, 31, -2, 35, -1, +29, 5, 40, -3, 51, -16, 44, -5, +45, -7, 38, -1, 34, 4, 31, 5, +30, -7, 48, -15, 47, -13, 46, -9, +48, -1, 40, -3, 36, 3, 28, -2, +31, -7, 43, -7, 45, -5, 50, -2, +42, 1, 34, -3, 34, -14, 29, -8, +35, 1, 35, 8, 41, 7, 51, 1, +40, -9, 38, -13, 34, -14, 27, -1, +33, 9, 37, 2, 43, 5, 44, 1, +35, -9, 39, -10, 36, 1, 28, 1, +32, 2, 37, 1, 38, -10, 42, -3, +37, 2, 37, 6, 40, 5, 32, 0, +35, -10, 41, -14, 38, -15, 45, -8, +43, 8, 41, 4, 41, 1, 37, -5, +41, -10, 36, -14, 41, -3, 42, 0, +40, -6, 50, -9, 39, -9, 33, 2, +31, 3, 29, 7, 39, 7, 43, -1, +43, -12, 45, -8, 38, -9, 35, -7, +31, 7, 31, 3, 38, 2, 38, 0, +45, -2, 46, -6, 43, 0, 36, -3, +34, -5, 34, -8, 35, -12, 41, -3, +45, 0, 43, 3, 42, 4, 38, 0, +40, -11, 37, -6, 37, -4, 39, -5, +40, -1, 39, -5, 38, -7, 44, -9, +43, -4, 45, 1, 43, 7, 39, -2, +40, -7, 34, -12, 38, -19, 44, -9, +37, 4, 41, 8, 44, 3, 38, 1, +46, -14, 41, -11, 41, -6, 39, -4, +34, -2, 40, -3, 34, -5, 37, -7, +48, -4, 49, -2, 45, 5, 42, -1, +32, -5, 28, -9, 29, -11, 32, -2, +36, 9, 47, 7, 52, -4, 52, -1, +40, -7, 25, -5, 25, -2, 28, 2, +27, 1, 45, -3, 50, -5, 53, -9, +51, -1, 37, -1, 35, -1, 36, -6, +29, -6, 33, -3, 41, -1, 39, -2, +52, -2, 51, -2, 39, -7, 41, -3, +33, -6, 36, -2, 39, 3, 34, 3, +44, -2, 46, -9, 41, -9, 45, -6, +39, 0, 39, -3, 43, 2, 35, 2, +37, -2, 35, -1, 37, 1, 41, -3, +43, -4, 44, -5, 45, -9, 39, -1, +39, -3, 39, 3, 36, 7, 32, -1, +41, -9, 44, -15, 49, -12, 48, -4, +43, 7, 41, 4, 34, 5, 25, 2, +29, -8, 41, -12, 44, -4, 54, -2, +50, -1, 46, -2, 41, -9, 32, -8, +37, -8, 37, 3, 34, 6, 48, -1, +50, -12, 46, -16, 48, -13, 34, -2, +32, 13, 35, 12, 36, 3, 48, -6, +40, -11, 40, -20, 47, -11, 38, -2, +41, 4, 41, 8, 45, -1, 42, -2, +41, -7, 39, -4, 33, -5, 35, -2, +35, -6, 43, -3, 42, 2, 44, 2, +41, 10, 44, 4, 34, 0, 32, -4, +30, -5, 32, -12, 42, -4, 44, 1, +51, 3, 51, 5, 47, -3, 46, -6, +37, -11, 32, -14, 38, -14, 43, -8, +48, -6, 54, 3, 53, 6, 50, -2, +47, -4, 33, -13, 41, -18, 36, -15, +36, -1, 44, 5, 44, 11, 47, 7, +48, -3, 46, -9, 43, -14, 36, -7, +33, -1, 35, -1, 36, 0, 41, 1, +52, -7, 49, 1, 48, 6, 42, -2, +47, -8, 35, -14, 32, -13, 35, -10, +39, 0, 46, 9, 49, 13, 53, 4, +48, -7, 40, -13, 33, -17, 31, -7, +28, 5, 36, 12, 41, 9, 46, 4, +52, -9, 55, -15, 47, -10, 43, -5, +32, 0, 32, 1, 31, -1, 36, -1, +39, 4, 50, 1, 53, 1, 54, -3, +46, -11, 38, -12, 31, -10, 28, -6, +36, 8, 33, 17, 50, 8, 51, 3, +52, -11, 50, -19, 38, -17, 40, -11, +34, -1, 39, 6, 44, 8, 47, 4, +49, -3, 51, -13, 43, -11, 42, -10, +41, -9, 40, 2, 39, 7, 43, 4, +42, 0, 48, -7, 47, -15, 48, -9, +43, -4, 44, -2, 43, 1, 41, -2, +45, -6, 43, -4, 41, 3, 34, 2, +48, 3, 37, -4, 47, -13, 48, -16, +49, -11, 46, -1, 44, 12, 40, 11, +43, 0, 40, -10, 39, -23, 43, -17, +42, -6, 43, 10, 47, 23, 41, 15, +43, 0, 39, -12, 33, -18, 37, -18, +41, -2, 42, 7, 52, 6, 52, 4, +46, -5, 53, -12, 40, -11, 44, -7, +39, -3, 37, -1, 41, -8, 41, -7, +45, 1, 42, 6, 47, 11, 46, 10, +45, -2, 41, -13, 34, -19, 37, -20, +33, -5, 46, 6, 49, 14, 57, 15, +52, 4, 48, -10, 38, -18, 31, -17, +27, -7, 30, 5, 44, 9, 50, 11, +56, 4, 56, -4, 48, -11, 40, -10, +36, -12, 37, -6, 35, 3, 40, 2, +41, 2, 53, -1, 50, 2, 44, 4, +50, 1, 38, -4, 40, -7, 35, -13, +36, -14, 47, -5, 46, 5, 51, 14, +51, 14, 48, 0, 44, -18, 44, -20, +29, -15, 38, -8, 47, 6, 47, 14, +53, 12, 45, -2, 51, -19, 43, -20, +41, -9, 32, 5, 39, 17, 35, 15, +42, 3, 42, -7, 45, -14, 44, -8, +43, 6, 39, 10, 43, 5, 36, 1, +40, -8, 37, -12, 47, -4, 44, 3, +49, 9, 46, 6, 39, -5, 44, -14, +33, -12, 41, -4, 36, 10, 47, 18, +40, 15, 43, 3, 40, -17, 49, -26, +42, -16, 43, -1, 49, 9, 47, 14, +47, 10, 41, -4, 39, -12, 39, -18, +41, -13, 43, 4, 44, 9, 49, 9, +46, 3, 49, -9, 43, -12, 40, -8, +41, -5, 38, 1, 44, 6, 39, -1, +51, -8, 51, -9, 50, -8, 49, 4, +37, 12, 38, 7, 29, 1, 37, -13, +37, -17, 44, -5, 46, 4, 57, 14, +50, 22, 40, 12, 37, -9, 30, -21, +32, -22, 30, -9, 45, 9, 51, 19, +56, 19, 57, 3, 49, -13, 40, -19, +31, -16, 31, -3, 33, 8, 42, 11, +49, 4, 53, -8, 62, -14, 47, -8, +47, 2, 34, 11, 30, 9, 27, 1, +34, -9, 40, -17, 53, -11, 57, 3, +54, 15, +}; \ No newline at end of file diff --git a/project/realtek_ameba1_va0_example/example_sources/i2s/src/birds_44100_2ch_16b.c b/project/realtek_ameba1_va0_example/example_sources/i2s/src/birds_44100_2ch_16b.c new file mode 100644 index 0000000..960ed33 --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/i2s/src/birds_44100_2ch_16b.c @@ -0,0 +1,32143 @@ +#include +int sample_size=128547; + +SECTION(".sdram.data") +short sample[]={ +1, 1, -2, 0, 1, 1, 0, 0, +-1, 3, -2, 0, 1, -1, 1, -1, +2, 2, -4, 3, -3, 5, -4, 1, +-1, 2, 0, -2, 3, -1, 1, 0, +-1, 2, -1, -2, 2, -1, 1, -1, +2, 1, -1, 1, -2, 2, -3, -1, +3, -1, 1, -2, 3, 0, 0, 0, +-2, 3, -4, 2, -3, 4, -3, 1, +2, 0, 1, -2, 1, -1, -2, -1, +1, 0, 3, -4, 5, -3, 3, -4, +2, -2, 0, -3, 3, -2, 2, -1, +2, 1, 0, -3, 4, -5, 2, -5, +3, 1, -1, 1, 1, 2, -1, 0, +-4, 3, -4, 0, 1, 0, 1, -1, +3, 0, 0, -2, 0, 1, -4, 1, +-2, 2, 2, -2, 5, -1, 0, 0, +-4, 4, -6, 2, 0, 1, 2, -1, +2, 2, -2, 0, -1, 0, -1, -3, +2, 2, -1, 2, 2, -1, 4, -6, +3, -3, 0, -2, 2, 0, 2, 0, +2, 3, -4, 1, -2, 0, -1, -2, +4, -3, 5, -3, 4, 1, -1, -1, +-1, 0, -2, -1, 2, -1, 4, -2, +4, 0, -1, -1, -1, -1, 0, -4, +5, 0, 0, 2, -1, 4, -3, 0, +-2, 0, -1, -3, 4, -1, 3, -3, +5, -1, 0, -2, -1, -1, -1, -2, +3, 0, 2, -1, 3, 1, -3, -1, +-1, 0, 0, -3, 2, 1, 0, 2, +0, 1, 0, -3, 0, 1, -6, 3, +-1, 4, -1, 1, 0, 2, -1, -3, +1, -3, 1, -1, 1, 3, -2, 2, +1, 0, 0, -2, -1, 1, -3, 1, +1, 0, 2, -1, 4, -2, 0, -4, +2, -2, 1, -3, 5, -3, 4, -1, +1, 2, -3, -2, 2, -2, 1, -3, +3, 1, 1, 1, -2, 4, -4, 2, +-4, 3, -4, 1, 3, 0, 1, 0, +0, 2, -1, -3, 2, -2, 0, 0, +1, 4, -4, 3, -1, 2, -2, -1, +0, 0, 0, -3, 6, -4, 6, -4, +3, 1, -5, 1, 0, 0, 0, -2, +2, 2, 0, 0, -1, 2, -4, 3, +-4, 3, -2, -2, 5, -2, 3, -3, +3, -2, 1, -3, 0, 1, -2, 2, +-1, 3, -1, -2, 3, -2, 0, -3, +1, 0, 0, 1, -2, 4, -4, 3, +-1, 1, -2, -2, 1, 1, -1, -2, +4, -2, 3, -1, -2, 2, -3, 1, +-1, 3, -4, 2, 0, 3, -3, 3, +-5, 4, -2, -1, 1, 0, -1, 0, +2, 1, -1, -1, 1, 1, -2, 0, +-2, 3, -1, 1, 0, 2, -3, 2, +-1, 2, -3, 0, 0, 2, 0, -1, +1, 1, -1, 1, -1, 1, -2, 0, +1, 1, -1, 0, 1, 2, -1, 0, +-1, 0, 1, -3, 4, -2, 2, -2, +3, 0, -1, -1, 1, 0, 0, -2, +2, -1, 2, -2, 2, 1, -1, -2, +2, 0, -1, -1, 2, -1, 3, -3, +3, -1, 0, -1, 0, 1, -2, -1, +3, 0, 0, -1, -1, 3, -2, 1, +-2, 1, -1, 0, 1, 0, 1, -3, +4, 0, -3, 1, -3, 3, -2, 2, +-2, 2, -2, 2, -2, 4, -5, 0, +1, 1, -2, 1, -2, 4, -2, 1, +-2, 2, -1, -1, 1, -1, 0, -2, +3, 1, -2, 2, -4, 5, -5, 4, +-5, 4, -3, 2, 0, 2, -2, -2, +4, -1, 0, -1, -1, 1, 1, -1, +1, 0, 1, -1, 1, 1, -3, 0, +1, 1, -1, 1, 0, 0, 2, -2, +1, 0, -1, -2, 4, -1, -2, 2, +-2, 5, -2, -1, 1, -1, 1, 0, +-2, 3, -3, 2, 2, 1, -2, -2, +4, -1, 0, -2, 0, 2, 0, 1, +-1, 1, 1, -4, 6, -4, 1, -2, +2, 1, -1, 1, -1, 1, 2, -3, +1, 2, -6, 4, -1, 2, -1, -2, +3, 0, 0, 0, -4, 4, -3, 2, +-1, 2, -3, 1, 1, 3, -5, 2, +-3, 5, -5, 3, -4, 3, 0, -1, +2, 0, -2, -1, 1, 1, -2, -2, +3, -2, 4, -4, 1, 0, 0, 0, +-1, 2, -5, 2, 0, 3, -4, 1, +0, 1, -1, 1, -4, 3, -3, 1, +1, 1, -2, 0, 1, 3, -5, 1, +-1, 1, 0, -1, 1, -1, 2, -3, +4, 0, -4, 2, -1, 3, -4, 1, +0, 1, 2, -2, 2, -2, 1, -2, +2, 1, -3, -1, 5, -2, 3, -5, +4, -2, 3, -2, -1, 1, 0, -1, +3, 0, -1, -1, 4, -1, 0, -2, +-1, 3, -1, 2, -2, 2, 0, -1, +3, 0, -3, 0, 0, 4, -4, 2, +-1, 0, 4, -3, 2, 0, -3, 1, +2, 0, -1, -3, 4, 2, -1, -1, +0, 0, 1, 0, -3, 4, -4, 3, +-1, 4, -5, 2, -1, 3, -3, 1, +-2, 0, 2, -1, -1, 4, -5, 4, +-3, 5, -7, 3, -3, 4, -3, 2, +-3, 4, -3, 3, -3, 2, -3, 0, +0, 4, -7, 4, -3, 5, -4, 3, +-4, 2, -1, 0, -2, 3, -5, 3, +-1, 5, -6, 1, 0, 0, 2, -4, +2, -4, 5, -4, 4, -2, 0, -3, +5, -2, -1, -3, 3, -1, 2, -2, +0, 0, 3, -3, 2, 0, -4, 1, +2, 1, -2, 0, 0, 2, 0, 0, +-1, 0, 1, -2, 2, 1, -4, 3, +-1, 6, -6, 3, -4, 5, -2, 1, +-2, 0, 2, -1, 3, -1, 0, -3, +6, -2, 0, -2, 1, 2, 0, 2, +-4, 3, 0, -1, 3, -1, -1, -3, +5, -1, 0, 0, -1, 2, 1, 0, +-1, 0, 0, -1, 2, 1, -3, 0, +3, 0, -1, 1, -2, 2, 0, -1, +1, -1, 1, -2, 4, -1, -1, -1, +1, 2, -3, 1, -2, 2, 0, 0, +0, -1, 1, -2, 2, 2, -6, 2, +-1, 4, -4, 1, -1, 0, 2, -1, +-2, 2, -2, -3, 6, -3, -1, -1, +1, 2, -1, -2, -1, 1, 1, -2, +2, -4, 3, -4, 5, -1, -2, -3, +4, -1, 0, -1, -2, 2, -1, 1, +0, -1, 1, -5, 7, -3, 1, -6, +7, -5, 4, -2, -1, 1, 0, -1, +2, -1, -1, -1, 2, 3, -5, 1, +0, 2, -1, 2, -5, 5, -4, 4, +-3, 4, -4, -1, 6, -2, 0, -2, +1, 2, 0, 0, -1, -1, 4, -3, +3, 0, -2, -1, 5, -1, -1, -1, +1, 1, 1, 0, -2, 3, -1, 1, +0, 3, -5, 2, 2, 1, -1, -1, +0, 2, 0, 1, -2, 2, -2, 2, +0, 2, -3, -1, 4, 0, 0, -3, +2, 1, 0, 2, -4, 2, 0, 1, +-1, 4, -6, 1, 3, -1, 1, -3, +1, 1, -1, 2, -3, 1, 0, -1, +2, 0, -2, -3, 6, -2, -1, -1, +-1, 2, 0, 0, -2, 0, 1, -2, +2, 2, -5, -1, 3, 0, -2, 2, +-5, 4, -1, 0, -2, 2, -4, 2, +0, 2, -5, 1, 0, 2, -1, -2, +1, -2, 3, -2, 0, -1, 0, -2, +3, 2, -7, 4, -3, 6, -6, 2, +-2, 1, 3, -4, 2, -2, 3, -6, +8, -5, 2, -4, 4, -1, 1, -3, +2, -2, 4, -1, -2, 4, -6, 4, +-1, 4, -5, 1, 1, 1, 1, -2, +2, -3, 5, -3, 2, 1, -4, 2, +2, 2, -3, -1, 4, -2, 4, -5, +3, -2, 3, -1, 1, 0, -1, 0, +2, 3, -4, -1, 3, -1, 2, -1, +-1, 1, 2, -1, 1, 1, -2, -1, +4, 0, -2, -1, 2, 0, 2, -1, +-2, 2, -1, 2, -2, 2, -2, -2, +5, 0, -2, -1, 2, -1, 2, -2, +0, -1, 2, -3, 2, 1, -2, -2, +4, -1, -2, 0, -2, 4, -4, 3, +-4, 2, 1, -3, 3, -1, -2, -2, +5, -3, 1, -4, 2, 0, 1, -1, +-1, 0, 0, -2, 2, 0, -3, -1, +2, 3, -5, 2, -3, 3, 0, -2, +0, -2, 2, -2, 1, 2, -4, 0, +2, 1, -1, -2, 0, -1, 3, -2, +0, 0, -1, 1, 2, 0, -3, -1, +2, 2, -3, 1, -2, 2, 1, 0, +0, -1, 1, -3, 5, -2, -1, -2, +4, 0, 1, -2, 2, -2, 3, -1, +0, 0, -1, 0, 3, 1, -2, -2, +6, -2, 1, -2, 1, -1, 4, -3, +3, -2, 1, -1, 4, 0, -2, -2, +3, 0, 1, -2, 2, -3, 7, -6, +5, -3, 2, -4, 7, -4, 1, -3, +3, 2, -1, 1, -3, 3, -1, 2, +-3, 2, -1, -2, 5, -2, 1, -4, +5, -2, 1, -1, -2, 1, 1, -1, +0, 1, -1, -2, 5, -2, -2, 0, +-1, 3, -3, 1, -2, 1, 2, -2, +0, 2, -5, 2, 0, 2, -5, 1, +0, 1, 1, -2, -1, 1, -1, 0, +-1, 1, -3, 0, 1, 3, -5, 2, +-3, 4, -2, -1, -1, -1, 1, 0, +-1, 3, -4, 0, 2, 2, -4, -1, +1, -1, 4, -4, 1, -2, 4, -4, +5, -4, 1, -4, 5, 0, -2, -1, +1, 1, 1, 0, -2, 1, -1, 2, +-2, 4, -5, 0, 5, -1, 0, -1, +0, 2, 0, 0, -2, 2, 0, 0, +1, 2, -4, 3, -1, 4, -4, 2, +-1, 0, 3, -2, 2, -1, 2, -3, +5, -2, 1, -4, 6, -2, 1, -1, +0, 2, 2, -3, 3, -3, 3, -3, +3, 1, -2, -1, 4, -2, 3, -4, +3, -1, 1, 0, -2, 3, -3, 2, +0, 3, -4, 0, 1, 2, -2, 0, +-1, 0, 2, 1, -3, 4, -5, 2, +0, 3, -5, 1, 0, 1, 1, -3, +2, -2, 2, -1, -1, 1, -3, 0, +2, 2, -5, 2, -1, 2, -1, -2, +1, -2, 3, -4, 3, -1, -1, -1, +2, 1, -3, -2, 2, -1, 1, -2, +-1, 2, -1, 0, 0, 0, -1, -1, +0, 3, -5, 2, -2, 4, -2, 0, +-1, 0, 1, -1, 0, 0, -1, -1, +2, 2, -4, 2, -1, 1, 1, -2, +-1, 1, 0, 0, 1, 0, 0, -2, +4, 0, -3, 1, -1, 3, -2, 2, +-2, 1, 2, -2, 2, 2, -5, 3, +-1, 3, -3, 1, 0, 3, -1, 1, +-1, 0, 2, -2, 2, 0, -2, 0, +4, 0, 0, -1, 0, 2, 0, -1, +1, -1, 1, 0, 2, 0, 1, -4, +6, -2, -1, 0, -1, 2, 1, -2, +3, -2, 2, -1, 0, 3, -5, 2, +-1, 2, -1, -1, 2, 0, 0, 0, +-1, 1, -2, 1, -2, 5, -7, 3, +1, 1, 1, -5, 4, -4, 3, -1, +-3, 4, -5, 3, 0, 1, -1, -3, +3, -1, 0, -3, 2, -2, 2, -1, +0, 1, -1, -1, 0, 2, -4, 0, +1, -1, 1, -1, -1, 3, -3, 3, +-4, 3, -4, 1, 0, 1, -2, 0, +0, 3, -3, 2, -4, 3, -2, 0, +0, 0, -1, 0, 2, 1, -2, -1, +1, 0, 1, -4, 3, -3, 4, -3, +3, -1, 0, -2, 4, -2, -1, 0, +-1, 4, -2, 0, 1, 0, 1, 0, +-1, 2, -3, 0, 3, 0, -1, 0, +0, 5, -4, 2, -2, 1, 0, 0, +1, 0, 1, -3, 5, -1, 0, -1, +0, 2, -2, 1, -1, 2, 0, 0, +0, 3, -4, 3, -3, 6, -7, 4, +-2, 2, 2, -3, 1, 2, -2, 2, +-3, 4, -4, 1, 2, -1, 2, -4, +3, 0, 0, 0, -2, 2, -1, -2, +4, -2, 1, -1, -1, 5, -6, 3, +-2, 1, -1, 1, -3, 4, -3, 1, +0, 2, -5, 3, -2, 2, -2, 0, +-2, 5, -5, 4, -4, 2, 0, -3, +3, -2, 0, -2, 2, 0, 1, -4, +3, -2, 2, -3, 2, -3, 4, -5, +4, -2, 1, -3, 3, -1, 0, -2, +0, 1, -1, 1, -1, 2, -2, 0, +1, 0, -1, -1, 0, 2, -2, 0, +2, -2, 3, -3, 0, 2, -3, 2, +-1, 1, -1, 0, 2, 0, 0, -2, +2, -1, 2, -4, 4, -2, 1, 0, +1, 1, -1, -2, 3, -1, 1, -3, +3, -1, 2, -1, 0, 3, -4, 4, +-3, 3, -3, 1, 1, 2, -1, -1, +3, -2, 3, -3, 2, -1, 0, -1, +2, 0, 1, -2, 3, 0, -1, -1, +2, -2, 2, -2, 1, 2, -1, -1, +3, -1, 0, -1, 0, 1, 0, -2, +1, 2, -1, 1, -1, 2, -2, 0, +-1, 2, -2, -1, 2, -1, 3, -4, +4, -3, 2, -3, 2, -2, 1, -2, +1, 3, -3, 1, 0, 2, -4, 4, +-8, 8, -7, 4, -2, 3, -3, 2, +-1, 2, -3, 0, -1, 2, -2, -1, +2, -1, 2, -2, 2, -1, 0, -3, +1, 1, -3, 1, 0, 2, -1, 0, +0, 0, 0, -2, 0, 1, -2, 0, +2, 0, 0, -1, 1, 1, -1, -1, +-2, 3, -3, 2, 0, 1, 1, -3, +3, -1, 0, -2, 1, -1, 2, -3, +3, 1, -1, 2, -3, 4, -3, -1, +2, -2, 3, -4, 3, 1, 0, 1, +-1, 1, 0, -3, 3, -2, 2, -3, +5, -2, 2, -2, 1, 1, 0, -3, +2, -1, 1, -1, 2, 0, 1, -1, +1, 1, -3, 2, -3, 3, -2, 0, +3, -1, 1, 0, -1, 3, -3, -1, +1, 1, -2, 2, 0, 0, 3, -4, +2, 2, -5, 3, -2, 1, 0, -2, +3, 0, 1, -2, 0, 3, -6, 5, +-6, 5, -3, 1, 0, 3, -4, 4, +-4, 3, -2, -3, 5, -5, 5, -6, +5, -2, 3, -4, 3, -2, 0, -1, +-1, 2, -1, -1, 2, 0, -1, 1, +-3, 4, -5, 3, -4, 3, -1, -1, +3, -2, 1, -2, 2, 0, -1, -2, +0, 2, -1, 0, 0, 2, -3, 4, +-6, 7, -6, 2, -1, 0, 2, -3, +4, -4, 4, -3, 1, 1, -2, -2, +5, -5, 5, -5, 4, -1, 1, -2, +2, -1, 0, -1, 0, 1, 1, -2, +1, 3, -4, 3, -2, 2, -2, 1, +-2, 4, -3, 2, -2, 3, -1, -1, +2, -2, 2, -2, 1, 1, -1, 1, +1, 0, 0, -1, 1, 0, 0, -2, +3, -1, 1, -3, 4, -2, 3, -4, +2, 1, -1, 0, 0, 1, -1, 2, +-4, 7, -7, 4, -2, 1, 0, 0, +-1, 2, 0, -3, 4, -2, 0, 0, +-1, 3, -3, 1, 0, 0, 1, -2, +0, 2, -2, 0, 0, 2, -3, 2, +-2, 3, -2, 1, -2, 3, -4, 2, +-1, 2, -2, 0, 0, 1, 0, -3, +2, 0, -1, 0, -1, 2, -1, 0, +0, 0, 1, -3, 2, 0, -2, 1, +-1, 2, -1, -1, 0, 1, 1, -3, +2, -2, 1, -1, 0, 3, -4, 3, +-3, 4, -3, 1, -2, 2, -2, 2, +-3, 5, -5, 4, -3, 4, -3, -1, +2, -2, 3, -5, 4, -2, 3, -2, +0, 3, -3, -1, 3, -4, 5, -5, +3, 0, 1, -1, 1, 0, 0, -1, +0, 1, -1, -1, 2, 0, 1, -2, +2, 1, -2, 0, 0, -1, 2, -3, +3, 0, 1, -2, 2, 0, -1, 0, +0, 0, 0, -1, 1, 1, 0, 1, +-2, 3, -2, -1, 1, 0, -1, 0, +2, -2, 4, -3, 1, 1, -1, -2, +3, -3, 2, -2, 2, 1, -1, 0, +0, 1, 0, -2, 0, 1, -1, 0, +0, 3, -3, 3, -3, 3, -2, -3, +4, -4, 4, -4, 3, -1, 1, 0, +-1, 3, -5, 2, -2, 3, -3, 0, +1, 1, 0, 0, -1, 1, 0, -3, +2, -1, -1, 0, 1, 2, -2, 0, +0, 0, 1, -3, 0, 1, 0, -2, +3, -1, 1, -1, 1, -1, 1, -3, +1, 1, -3, 4, -3, 2, 2, -4, +4, -1, -3, 2, -3, 3, -1, -1, +3, -2, 3, -3, 2, 0, -2, 1, +-2, 3, -3, 1, 1, 0, 2, -3, +2, 0, -2, 2, -3, 3, -2, 0, +2, 1, -1, 1, -2, 3, -2, -1, +0, 1, 0, -1, 2, -1, 2, -1, +-1, 3, -3, -1, 3, -2, 1, -1, +2, -1, 3, -3, 1, 2, -4, 2, +-1, 2, -2, 0, 2, 0, 0, 0, +-2, 3, -2, -1, 1, -1, 1, -1, +1, 1, 0, -1, 0, 2, -3, 1, +-2, 2, 0, -1, 2, -2, 2, -2, +1, 2, -5, 3, -3, 3, -1, -1, +1, 0, 1, -2, 1, 1, -3, 1, +-1, 1, 0, -2, 2, 0, 1, -3, +2, -3, 4, -5, 3, -1, 0, -1, +2, 0, 0, -2, 2, -2, 3, -4, +1, 0, 0, 1, -1, 1, 0, -2, +2, 0, -1, -1, 1, -1, 2, -2, +1, 1, -1, 0, 0, 0, 1, -4, +5, -4, 3, -3, 3, -2, 3, -3, +0, 3, -4, 2, 0, -1, 2, -3, +2, 2, -3, 2, -2, 2, 0, -1, +0, 1, -1, 1, -1, 3, -3, 2, +-3, 5, -3, 0, 0, 0, 2, -3, +3, -3, 4, -3, 1, 1, -1, -1, +3, -3, 3, -2, -1, 4, -3, 1, +0, -1, 2, -3, 2, 1, -2, 1, +-2, 4, -2, 0, 0, 0, 1, -1, +0, 1, -1, 1, -2, 3, -3, 2, +-2, 3, -1, -2, 2, -1, 1, -1, +0, 0, 2, -5, 6, -5, 5, -6, +4, -1, 0, 0, -2, 3, -2, 1, +-2, 3, -2, 0, 0, 2, -4, 3, +-4, 5, -3, 1, -2, 3, -3, 3, +-2, 1, -1, -1, 1, 0, 1, -4, +4, -2, 1, 0, -2, 2, -1, -1, +1, 0, -1, 0, 1, 1, -1, -1, +1, 0, 1, -3, 1, 1, -1, 2, +-3, 4, -3, 0, 2, -1, 0, -1, +0, 1, 0, -2, 3, -2, 2, -1, +-1, 2, -2, 0, 0, 2, -2, 1, +0, 0, 2, -2, 1, 0, -1, 1, +-2, 4, -4, 2, 0, 1, 0, -1, +0, 1, 0, -1, 0, 0, 1, -2, +3, 0, 0, -2, 2, -1, 1, -3, +2, -1, 2, -2, 1, 0, 1, -1, +0, 1, -2, 1, -1, 1, -1, 0, +1, 1, -1, 1, -3, 4, -4, 2, +-1, 1, -1, -1, 3, -2, 3, -4, +2, 0, -2, 1, -2, 3, -3, 2, +-1, 2, -2, 1, -2, 4, -5, 2, +-2, 2, 0, -1, 1, 0, 0, -1, +1, 0, -1, -2, 2, -1, 1, -1, +0, 1, 0, -1, 1, -1, 0, -2, +2, -1, 1, -3, 3, 0, 0, -1, +-1, 1, 0, -1, 0, 0, 0, 0, +1, 1, -2, 0, 0, 2, -3, 1, +-2, 2, 0, 0, -1, 3, -2, 0, +1, 0, -1, -1, 1, 0, 2, -3, +1, 1, 0, 0, -1, 2, -3, 1, +0, 0, 2, -4, 4, 0, 0, -1, +1, -2, 3, -3, 1, 1, -1, 0, +1, 1, -1, 0, 0, 1, -1, -1, +1, 0, 1, -1, 0, 2, -1, -1, +2, 0, -3, 3, -5, 7, -4, 1, +0, 0, 1, 0, -1, 1, -1, -1, +1, 1, -1, -1, 2, -1, 2, -1, +-2, 2, -1, 0, -1, 2, -2, 0, +2, -1, 0, 0, -2, 4, -3, 0, +-1, 1, 1, -2, 2, -2, 2, -3, +3, -2, 1, -3, 1, 2, -2, 0, +0, 1, 0, -1, 0, 1, -2, 1, +-1, 1, 0, -2, 1, 2, -3, 4, +-6, 6, -6, 5, -5, 5, -4, 1, +0, 2, -2, 1, -2, 2, -1, 0, +0, -1, 1, -2, 2, 1, -1, -1, +0, 2, -3, 2, -2, 1, 0, 0, +0, 1, -1, -1, 2, 0, 0, -3, +4, -4, 5, -6, 4, -1, 1, -1, +2, -3, 4, -5, 4, -1, 0, -2, +3, -1, 1, -1, 0, 0, 3, -5, +4, -2, 0, 2, -3, 4, -3, 2, +-2, 4, -4, 3, -4, 5, -4, 3, +-3, 3, -1, 0, 0, 1, -1, 0, +-1, 3, -2, -1, 1, 0, 1, 0, +-1, 1, 0, -1, 0, 3, -5, 3, +-2, 3, -2, 2, -3, 3, -2, 2, +-3, 3, -3, 1, 0, 1, -1, 0, +0, 1, -1, 0, 0, 0, -1, 1, +-2, 3, -2, 0, 0, 3, -4, 2, +-3, 3, -2, 1, -2, 1, 1, -2, +2, -1, 1, -3, 2, 0, -1, -1, +1, -1, 3, -4, 3, -1, 0, 0, +-2, 3, -2, -1, 1, -1, 2, -2, +1, 1, -2, 1, -1, 1, 0, -2, +1, 0, 0, 0, 0, 2, -2, 0, +-1, 2, -2, 2, -3, 3, -1, 0, +1, 1, -2, 1, -1, 3, -4, 2, +-2, 3, -1, 0, 0, 1, -1, 1, +-2, 4, -5, 2, 0, 1, 0, -1, +1, 1, 1, -3, 3, -3, 4, -4, +2, 0, 1, -1, 1, 1, -1, -1, +2, -1, 1, -2, 0, 2, 0, -2, +3, -2, 3, -4, 2, 0, 0, -1, +0, 0, 2, -2, 2, -1, 1, -2, +2, -1, 1, -4, 4, -2, 2, -2, +0, 2, -1, 0, -1, 0, 1, -3, +3, -1, 0, -1, 1, 1, -1, 0, +-1, 0, 2, -4, 3, -2, 1, 0, +0, 1, -1, -1, 0, 2, -2, -1, +1, -1, 2, -1, -2, 4, -4, 3, +-3, 3, -3, 0, 1, 0, 0, 0, +-1, 1, 1, -3, 3, -2, 0, 0, +-2, 4, -3, 1, 0, 1, -1, 0, +-1, 1, 0, -1, -1, 3, -3, 2, +-1, 1, 0, -1, 1, -1, 2, -4, +4, -3, 3, -4, 4, -2, 1, -1, +0, 1, -1, -1, 1, 1, -1, 0, +0, 1, 1, -2, 2, -2, 2, -3, +3, 0, -1, 0, -1, 3, -2, 2, +-3, 2, 1, -3, 3, -2, 2, -2, +2, 0, 0, -1, 2, -2, 3, -3, +0, 3, -2, 0, 1, -2, 4, -5, +4, -1, -1, 0, 0, 1, 0, -1, +1, -1, 3, -3, 1, 1, -1, 0, +0, 1, -1, -1, 2, -1, 1, -1, +-1, 2, -1, -1, 1, 0, 0, -2, +2, 0, 0, -1, 0, 1, -1, 1, +-3, 3, -1, -2, 3, -2, 1, -1, +0, 1, -1, 0, -1, 2, -2, 1, +-2, 3, -3, 3, -3, 3, -2, -2, +4, -3, 2, -3, 1, 1, 0, -1, +0, 1, -1, 0, 0, 0, 0, -1, +0, 3, -3, 1, 0, 0, 1, -1, +-1, 2, -3, 3, -3, 4, -3, -1, +3, -1, 1, -1, -1, 1, 0, -1, +1, 0, 1, -2, 1, 1, 0, -2, +2, -1, 1, -2, 1, 0, 2, -2, +1, -1, 2, -2, 1, 1, -3, 2, +-1, 2, 0, -2, 1, 2, -2, 2, +-3, 3, -1, -2, 3, -2, 2, -2, +2, 0, 1, -3, 2, -1, 1, -1, +0, 1, -1, 1, -1, 2, -2, 1, +-1, 2, -2, 0, 1, -1, 1, 1, +-3, 5, -5, 3, -3, 5, -6, 4, +-3, 3, -1, -1, 1, 1, 0, -2, +1, -1, 1, -2, 2, 0, -1, 0, +0, 1, 0, -2, 1, 0, -1, 0, +-1, 2, -1, 0, 0, 1, -1, -1, +0, 1, -1, 0, -1, 2, -2, 2, +-3, 5, -4, 0, 1, 0, -1, 0, +-1, 2, -1, 0, -1, 3, -2, -1, +1, -1, 2, -4, 3, -1, 2, -4, +4, -3, 4, -5, 3, -2, 2, -3, +3, -2, 2, -3, 3, 0, -1, -1, +1, 0, 1, -3, 3, -2, 2, -2, +1, 2, -3, 2, -3, 5, -5, 3, +-2, 2, 0, -1, 1, -1, 3, -5, +4, -2, 0, 1, -2, 3, -2, 1, +-1, 3, -4, 4, -4, 4, -3, 0, +2, -1, 1, -2, 2, 1, -2, 1, +-2, 3, -1, -1, 1, -1, 3, -3, +1, 2, -2, 0, 1, -2, 4, -5, +4, -2, 1, -1, 1, 0, 0, -2, +2, -1, 2, -4, 3, -1, 1, -2, +2, -1, 1, -2, 1, 1, -2, 2, +-3, 5, -5, 3, -2, 3, -3, 1, +-2, 3, -1, -1, 0, 1, 0, -2, +2, -1, 1, -3, 3, -2, 1, -1, +-1, 2, -1, -1, 1, 0, 0, -2, +2, 0, -1, 0, 0, 1, 0, -2, +1, 0, 1, -3, 3, -3, 3, -3, +1, 2, -3, 2, -3, 4, -3, 1, +-1, 1, 0, -1, 0, 2, -2, 0, +0, 2, -2, 0, 0, 1, 0, -1, +0, 2, -2, 1, -1, 1, 0, -1, +0, 3, -3, 1, -1, 2, 0, -2, +2, -2, 2, -1, 1, -1, 2, -3, +2, 1, -2, 0, 1, 0, 0, 0, +-1, 2, -1, 0, 0, 2, -2, 0, +0, 1, 0, -1, 1, 0, 1, -1, +-1, 3, -3, 2, -2, 1, 2, -3, +1, 1, -1, 1, 0, -2, 3, -3, +1, 2, -4, 4, -3, 3, -1, -2, +2, 0, 0, -2, 2, -1, 1, -2, +1, 2, -3, 2, -2, 3, -3, 2, +-3, 3, 0, -3, 3, -1, 1, -1, +-1, 1, 1, -4, 5, -5, 4, -4, +3, 1, -3, 1, 0, 1, -1, -1, +0, 2, -2, 1, -1, 1, 1, -4, +5, -4, 4, -6, 4, -1, 1, -1, +-1, 3, -2, 0, -1, 2, -1, -1, +0, 1, 0, -2, 2, 0, 1, -2, +-1, 3, -2, 0, 0, 1, -1, 0, +0, 2, -1, -1, 1, -2, 5, -7, +5, -2, 1, 1, -3, 4, -3, 1, +0, 1, -1, 0, -2, 3, 0, -1, +1, 0, 0, -1, 1, 2, -4, 2, +-1, 3, -3, 2, -3, 5, -3, 0, +0, 1, -1, 0, 0, 1, 0, -1, +1, 0, 2, -4, 3, -1, 0, 1, +-3, 4, -3, 2, -1, 1, 0, -2, +2, -1, 2, -5, 6, -4, 3, -3, +2, 0, 0, -1, 0, 2, -2, -1, +2, -1, 2, -3, 2, -1, 2, -2, +0, 0, 1, -2, 2, -1, 1, -1, +0, 1, 0, -2, 1, 0, 0, -1, +1, 0, 0, -1, 0, 4, -5, 1, +1, -1, 2, -3, 1, 1, -1, 1, +-2, 2, 0, -3, 2, 1, -3, 2, +-2, 2, 0, 0, -3, 5, -5, 4, +-4, 4, -4, 3, -3, 4, -3, 0, +1, 0, 0, -2, 1, 1, -2, 1, +-1, 2, -1, -1, 0, 3, -4, 2, +-2, 3, -1, -1, 0, 1, 1, -1, +-1, 2, 0, -2, 2, -2, 2, -2, +1, 1, -1, 0, 0, 1, -1, -1, +1, 2, -2, 0, 1, 0, 1, -3, +3, -1, 2, -4, 3, -2, 3, -3, +2, -1, 1, -1, 0, 2, -2, 0, +0, 1, 1, -2, 1, 0, 1, -2, +1, 1, -1, -2, 3, -2, 2, -2, +1, 1, 0, -2, 1, 2, -3, 2, +-2, 2, 1, -4, 4, -3, 3, -3, +2, -2, 2, -2, 1, -1, 3, -4, +3, 0, -2, 1, -1, 2, 0, -3, +2, 0, 0, -1, 1, 1, -2, 0, +0, 1, 0, -3, 3, -1, 2, -4, +4, -3, 3, -3, 1, 0, 1, -3, +2, -1, 3, -5, 5, -4, 4, -5, +3, 0, 0, -2, 2, -1, 1, -1, +0, 3, -4, 1, 0, 1, 0, -3, +3, -1, 1, -1, 0, 0, 1, -2, +1, 0, 1, -4, 5, -4, 4, -3, +0, 3, -3, 2, -3, 3, -2, 1, +-1, 2, -1, -1, 2, 0, -1, -1, +2, 0, -1, 0, -1, 4, -3, 1, +-1, 2, -1, -2, 2, 0, 0, -1, +1, -2, 5, -6, 5, -3, 2, -2, +0, 2, -2, 1, -1, 2, -1, -1, +1, 1, -2, 0, 1, 0, 0, -2, +2, 2, -4, 3, -3, 5, -4, 1, +-1, 1, 1, -3, 4, -3, 3, -2, +-1, 3, -2, 0, -1, 2, 0, -1, +-1, 3, -3, 3, -2, 1, 0, -3, +3, 0, 0, -4, 5, -2, 1, -1, +-1, 3, -3, 1, -1, 2, -2, 1, +-1, 3, -2, -1, 2, -2, 3, -4, +1, 1, 0, -1, 0, 1, 0, -1, +0, 1, 0, -3, 3, -1, -1, 1, +-2, 5, -5, 1, 1, -1, 1, -3, +2, 2, -3, 0, 1, 0, 1, -1, +-1, 2, -1, -1, 1, 0, 0, 0, +-1, 2, 0, -2, 1, 0, 1, -3, +2, 0, 1, -3, 3, -1, 1, -2, +1, 2, -2, -2, 3, 0, 0, -2, +2, 0, 0, -1, 0, 2, -2, 0, +-1, 3, -1, 0, -2, 3, -2, 2, +-3, 3, -1, -1, 0, 2, -3, 3, +-3, 4, -2, -2, 2, 1, -2, 1, +-2, 4, -3, 1, 0, 1, -1, -1, +1, 1, -1, -1, 1, 0, 1, -1, +-1, 2, 0, -1, 0, 1, -1, 1, +-3, 5, -3, 0, 1, -1, 2, -4, +4, -2, 1, -3, 4, -2, 1, -2, +2, 1, -3, 2, -3, 5, -4, 1, +0, 0, 1, -2, 1, 1, -1, 1, +-3, 3, -1, 0, 0, 0, 0, 0, +-1, 3, -3, 0, 1, 0, 0, -2, +2, 1, -2, 0, 0, 2, -2, -1, +1, 2, -3, 2, -2, 3, -2, 1, +-2, 4, -3, 1, -1, 0, 2, -2, +0, 1, 1, -4, 4, -2, 1, -1, +0, 1, 0, -2, 2, 0, 0, -2, +3, -1, -1, -1, 2, 1, -2, -1, +2, 0, 1, -4, 4, -2, 1, 0, +-3, 5, -3, 1, -1, 1, 1, -2, +0, 2, -2, 1, -1, 1, 0, -1, +1, 1, 0, -3, 3, 0, -1, -2, +4, -2, 1, -3, 3, 1, -2, 0, +-1, 3, -2, -1, 1, 0, 1, -3, +3, -3, 6, -6, 2, 1, -2, 3, +-5, 6, -3, -1, 2, -1, 1, -2, +1, 1, 0, -3, 3, 0, -1, 0, +0, 2, -2, -1, 2, -1, 1, -3, +2, 1, 0, -2, 2, -2, 3, -2, +-1, 1, 1, -2, 0, 3, -4, 3, +-2, 2, -1, 0, -2, 4, -4, 2, +-1, 2, -2, -1, 2, 1, -2, -1, +2, -1, 1, -3, 3, -1, 2, -3, +1, 1, -1, 1, -3, 4, -3, 2, +-2, 0, 3, -3, 1, 1, -2, 0, +1, 0, 0, -2, 2, 0, 0, -2, +2, 1, -3, 1, -1, 3, -3, 0, +1, 1, -1, -2, 3, -1, 1, -2, +0, 0, 2, -2, 0, 1, 0, 0, +-2, 4, -4, 2, -1, 1, 0, -2, +1, 2, -2, 0, 1, 0, -1, -2, +4, -1, -1, -1, 0, 4, -3, -1, +2, -1, 1, -2, 0, 1, 2, -5, +5, -4, 4, -2, -2, 3, -1, 0, +-1, 0, 1, -1, 1, 0, 0, -2, +3, 0, -2, 0, 0, 3, -3, 0, +1, 1, 0, -2, 1, 2, -3, 1, +0, 0, 1, -3, 3, -2, 3, -3, +0, 2, -2, 2, -3, 3, -1, -2, +3, -2, 3, -4, 2, 1, -3, 2, +-2, 4, -4, 1, 0, 3, -3, -1, +3, -2, 2, -4, 3, 0, 0, -2, +2, -1, 2, -1, -2, 3, -2, 0, +0, 1, 0, -1, -1, 3, -2, 1, +-1, 1, -1, -1, 1, 1, -1, -2, +3, 0, -1, -2, 3, -1, 1, -4, +4, -1, -1, 1, -2, 4, -2, -2, +3, -2, 3, -4, 1, 2, -1, 1, +-3, 3, 0, -1, 0, 0, 0, -1, +1, 1, -2, 1, -2, 6, -7, 4, +-2, 3, -3, -1, 3, -1, 2, -5, +3, 1, -1, 1, -3, 4, -3, 2, +-3, 3, 0, -1, 0, 0, 1, -2, +1, 1, -1, 0, -1, 2, -1, 0, +0, 3, -4, 0, 3, -1, 0, -2, +0, 5, -5, 1, 0, 2, -2, 1, +-2, 3, -2, 1, -2, 3, -1, -1, +1, -1, 3, -3, 0, 1, 0, 0, +-1, 2, -2, 1, -1, 4, -5, 2, +0, 1, 0, -4, 5, -1, 0, -3, +4, -2, 2, -4, 3, 0, 0, -2, +1, 1, 0, -1, 0, 0, 2, -2, +0, 0, 2, -3, 2, 0, 0, -1, +1, 0, 1, -3, 1, 3, -4, 1, +0, 2, -3, 1, 0, 2, -3, 0, +0, 4, -5, 2, -2, 3, -1, -1, +0, 1, 0, -2, 1, 0, 2, -3, +1, -1, 3, -3, 1, 1, -2, 1, +-1, 3, -3, 0, 0, 4, -5, 2, +-1, 3, -3, 0, 1, 1, -1, -2, +3, -1, 1, -2, 0, 3, -3, 1, +-1, 1, 2, -3, 0, 2, -2, 2, +-3, 3, -1, -2, 1, 3, -4, 2, +-2, 4, -3, 0, 1, 0, 0, -3, +3, 2, -4, 1, 0, 2, -1, -2, +1, 1, 1, -3, 2, -2, 3, -2, +0, 1, 0, 0, -2, 3, -2, 1, +-1, 2, -2, 2, -2, 3, -2, -2, +4, -1, 0, -3, 4, 0, -1, -1, +1, 2, -2, 0, 0, 1, 0, -2, +1, 2, -3, 3, -4, 4, -1, -1, +-1, 2, -1, 1, -2, 2, 1, -3, +3, -2, 2, -3, 3, -1, 0, -2, +2, 1, -2, 0, 1, 1, -1, -2, +3, -1, 0, -2, 2, 0, 2, -5, +4, -3, 4, -4, 1, 0, 1, -1, +-1, 2, -1, 0, -1, 2, -1, -1, +1, 0, 0, -2, 2, 1, -2, 0, +1, 1, -1, -3, 3, 1, -2, 0, +0, 0, 2, -3, 2, -1, 1, -2, +0, 3, -3, 2, -3, 3, 0, -2, +1, 1, -2, 2, -4, 5, -3, 0, +0, 3, -3, 1, -2, 5, -5, 2, +0, 0, 1, -4, 4, -1, 0, -1, +1, 0, 0, -1, 0, 1, 0, -1, +0, 1, 0, 0, -2, 4, -4, 3, +-4, 4, -1, -2, 3, -1, -1, 1, +-2, 5, -4, -1, 3, -1, 0, -1, +1, 2, -2, -1, 1, 2, -2, 1, +-2, 2, -1, 1, -1, 1, 1, -3, +2, 0, 0, 0, -2, 2, 1, -3, +3, -2, 3, -5, 5, -3, 3, -6, +6, -2, -1, 1, -2, 4, -2, -2, +3, -2, 2, -3, 2, 1, -2, 1, +-1, 2, 0, -1, -1, 1, 1, -1, +-1, 1, 0, -1, 1, 0, 0, -2, +2, 0, 0, -2, 1, 2, -3, 2, +-2, 4, -4, 1, 0, 3, -5, 3, +-3, 5, -3, -1, 2, -2, 3, -2, +-1, 2, -1, 0, 0, 0, 0, -1, +2, -1, 1, -3, 2, 1, -1, -1, +1, 1, -2, 0, 2, 0, -1, -3, +4, 0, -1, -1, -1, 5, -6, 5, +-5, 6, -4, 1, -1, 2, 0, -2, +1, 0, 1, -1, 0, -1, 3, -4, +2, 1, -2, 1, 0, 1, -2, 1, +-1, 4, -5, 2, -1, 4, -5, 2, +-1, 3, -2, -1, 2, 0, -1, 0, +-1, 3, -1, -2, 2, -2, 4, -3, +0, 2, -2, 1, 0, -1, 3, -5, +5, -2, 1, -2, 1, 2, -3, 2, +-2, 4, -4, 0, 2, 1, -1, -2, +2, 0, 0, -1, 0, 2, -1, -2, +2, 0, 1, -1, -1, 2, -1, 1, +-3, 5, -4, 2, -2, 2, 0, -2, +2, -1, 1, -3, 3, 0, -1, -1, +1, 3, -5, 3, -2, 3, -2, -1, +1, 1, -1, -1, 1, 0, 2, -5, +5, -4, 4, -3, 0, 1, 1, -3, +3, -2, 2, -2, 0, 1, 0, -3, +4, -1, -2, 1, 0, 1, 1, -6, +6, -2, 0, -1, 1, 1, -1, -2, +3, -1, 2, -3, 1, 0, 1, -2, +2, -2, 3, -4, 4, -3, 3, -3, +0, 3, -3, 2, -2, 2, 0, -3, +3, 1, -2, -1, 2, 0, -1, -1, +2, 0, -1, 0, 0, 2, -1, -2, +2, 0, 0, -1, 1, -1, 3, -4, +3, -2, 2, -2, 1, 0, 0, -1, +1, 0, 0, -1, 1, 1, -1, -2, +3, -1, 0, -1, 1, 1, -1, -1, +1, 2, -2, -1, 2, -1, 1, -2, +1, 1, 0, -1, 0, 0, 2, -2, +-1, 4, -5, 4, -3, 2, 1, -4, +4, -1, -1, 1, -3, 6, -6, 3, +-1, 1, 0, -3, 3, 1, -2, 0, +-1, 3, -3, 2, -3, 4, -3, 2, +-2, 2, -1, -1, 1, -1, 3, -5, +4, -2, 1, -1, 1, -1, 2, -4, +3, 1, -3, 1, -1, 3, -3, 1, +0, 1, -1, -2, 2, 1, -2, 1, +-3, 5, -4, 3, -3, 2, -1, 1, +-2, 3, -3, 2, -3, 4, -2, 0, +-1, 3, -3, 1, 1, -1, 2, -4, +3, 1, -2, 0, 0, 3, -4, 1, +1, 0, 0, -1, -1, 4, -3, 1, +-1, 2, -1, 0, -1, 2, -1, 0, +0, 0, 1, -1, 0, 1, -1, 0, +1, 0, 0, -3, 4, -1, 0, -2, +2, 1, -2, 0, 0, 3, -4, 2, +-2, 4, -3, 0, 1, -2, 4, -4, +2, 1, -3, 3, -4, 6, -4, 1, +0, -2, 4, -4, 2, 1, -2, 0, +1, 0, 0, -2, 2, 1, -2, 0, +0, 2, -3, 0, 3, -2, 1, -3, +2, 2, -3, 1, -1, 2, 0, -2, +1, 0, 1, -2, 1, -1, 2, -2, +1, 0, -1, 1, -1, 3, -2, -2, +3, -2, 3, -5, 6, -4, 2, -3, +2, 4, -7, 5, -4, 5, -4, 1, +0, 0, 2, -4, 3, -1, 1, -3, +3, -2, 3, -3, 1, 0, 1, -1, +1, -1, 1, -1, 0, 2, -3, 2, +-2, 3, -3, 1, 1, 1, -3, 0, +2, 0, 1, -4, 4, -2, 2, -3, +2, 1, -2, 0, 0, 1, 1, -3, +2, -1, 2, -1, -1, 2, -1, -1, +2, -2, 3, -4, 3, 0, -1, 0, +0, 2, -2, -2, 4, -1, 0, -2, +1, 2, -2, 1, -1, 3, -4, 1, +0, 2, -1, -2, 2, -1, 1, 0, +-2, 4, -4, 1, 1, -1, 2, -4, +3, 0, -1, 0, 1, -1, 2, -5, +5, -1, 0, -2, 1, 2, -2, 0, +2, -3, 4, -6, 5, -1, 0, -1, +1, -1, 2, -3, 3, -2, 2, -5, +6, -3, 1, -1, -1, 4, -3, 1, +-1, 1, 0, -2, 3, -2, 1, -2, +2, 0, 0, -1, 1, -1, 2, -5, +6, -3, 2, -3, 2, 0, 0, 1, +-2, 2, -2, 1, 0, 1, -1, -2, +3, 1, -3, 1, 0, 1, 0, -2, +1, 2, -3, 1, 0, 1, -1, 0, +0, 0, 0, 0, -1, 3, -3, 0, +2, -2, 4, -5, 3, -2, 2, -1, +0, 1, -1, -1, 3, -2, 1, -2, +2, -1, 1, -3, 4, -2, 0, -2, +4, 0, -2, 0, 0, 2, -2, 1, +0, 0, 0, -2, 2, 2, -2, -1, +1, -1, 2, 0, -3, 3, -1, -2, +4, -3, 2, -2, 1, 0, 0, -1, +2, 0, -2, -1, 3, 1, -2, -1, +1, 2, -3, 2, -2, 3, -3, 1, +1, 1, -2, -1, 2, -1, 2, -1, +-1, 1, -1, 1, 0, 1, -1, -1, +1, 0, 0, 0, 0, 0, 0, -3, +5, -1, -2, -1, 1, 3, -3, 0, +1, -1, 1, -2, 2, 2, -5, 3, +-2, 4, -4, 2, -2, 2, 0, -2, +2, -1, 1, -2, 1, 0, 1, -1, +0, -1, 2, -1, 0, 2, -4, 3, +-2, 4, -4, 1, 0, 1, -1, -2, +5, -3, 0, -2, 2, 2, -3, 0, +0, 1, 0, -1, 0, 1, -2, 2, +-2, 3, -2, 1, -3, 5, -5, 5, +-4, 3, -2, 0, 1, 1, -2, 1, +-1, 2, -1, -2, 4, -3, 2, -5, +7, -3, 0, -2, 2, 0, 1, -3, +3, -2, 1, -2, 3, 0, -2, 0, +0, 2, -2, 2, -2, 1, 0, -2, +4, -3, 3, -5, 4, -1, 1, -1, +-1, 2, -2, 0, 3, -1, -2, 1, +-1, 3, -2, 0, 0, 2, -4, 2, +1, 0, -1, -1, 0, 3, -3, 1, +0, -1, 2, -3, 3, -1, 0, -2, +3, -2, 2, -2, 0, 2, -2, 1, +0, 1, -1, -1, 1, 1, -1, 0, +0, 0, -1, 1, 0, 2, -3, -1, +4, -1, 0, -2, 1, 1, -1, 0, +1, 0, -1, -2, 3, 1, -3, 2, +-3, 4, -2, 0, 1, -1, 1, -2, +2, 0, 1, -3, 2, -1, 1, 0, +0, 0, 0, -1, 1, 3, -6, 4, +-1, -1, 4, -6, 5, -1, -2, 0, +2, 2, -4, 1, -1, 3, -2, 0, +1, 0, -1, 0, 0, 3, -4, 1, +1, -1, 2, -2, 0, 2, -3, 3, +-2, 3, -2, -2, 2, 0, 0, 1, +-1, 0, -1, 0, 2, 2, -6, 3, +-1, 3, -2, -2, 4, -2, 0, -2, +4, -1, -1, -1, 1, 1, -1, 1, +-1, -1, 3, -4, 5, -4, 3, -4, +3, -1, 1, 0, -1, -1, 3, -4, +5, -3, 1, -4, 5, -2, 1, -2, +1, 1, -2, 0, 3, -2, 1, -5, +6, -1, -1, -1, 1, 1, -2, 2, +-2, 2, -1, -2, 2, 0, 0, 0, +-1, -1, 4, -3, 2, -2, 1, -2, +3, 0, -1, 0, -1, 2, -1, 0, +1, 1, -3, 0, 3, 0, -2, -1, +2, 1, -2, 1, -1, 2, -2, -2, +5, -3, 2, -3, 1, 0, 2, -1, +-1, 1, -1, 1, 0, 1, -2, 2, +-2, 1, 2, -3, 2, 0, -2, 0, +3, -1, -1, -2, 3, 0, -1, 0, +-1, 3, -4, 2, 0, 3, -5, 1, +1, 1, 0, -1, 0, -1, 3, -4, +4, -2, 1, -2, 1, 0, 1, 0, +-1, -1, 2, -3, 4, -2, 1, -4, +5, -2, 1, -2, 2, -1, 0, -1, +1, 3, -5, 0, 3, 0, -2, 2, +-3, 4, -4, 2, 1, 0, -1, -2, +2, 1, -1, 1, -3, 2, 0, 0, +0, 0, 0, -2, 3, -1, 0, 0, +-1, 1, 0, -1, 2, -1, -1, -1, +2, 2, -3, -2, 4, -3, 2, -1, +-1, 5, -7, 3, 0, 2, -2, -1, +2, -2, 3, -3, 2, 0, -2, 1, +1, 0, -1, 0, -2, 3, 0, -1, +0, -1, 2, -3, 4, -1, -2, 2, +-2, 2, 0, -2, 3, -3, 2, -5, +8, -4, 1, -4, 5, -2, 1, -1, +1, 0, -1, -1, 3, 0, -2, -1, +2, 0, 1, -1, -2, 3, -2, 1, +0, 0, 1, -3, 2, -1, 3, -2, +0, -1, 1, 0, 0, 3, -6, 3, +0, 1, -1, 0, 0, 1, -3, 2, +0, 3, -5, 0, 3, -1, 1, -1, +-1, 2, -2, 3, -4, 5, -5, 2, +0, 0, 1, -1, -1, 0, 2, -2, +2, -2, 1, -1, 1, 1, -1, -1, +2, -2, 2, -3, 4, -1, -2, -1, +3, 0, -1, -1, 1, 1, -3, 4, +-4, 6, -7, 2, 2, 0, 1, -3, +0, 0, 2, 0, -1, -2, 3, -4, +5, -2, 1, -3, 2, -1, 2, 0, +-1, 0, -1, -1, 4, 0, -3, -1, +3, 0, -2, 1, 0, 1, -1, -3, +6, -2, -1, -1, 2, -2, 4, -4, +2, -1, 0, 0, 1, 1, -3, 2, +-2, 1, 2, -2, 0, 0, -1, 2, +-1, 2, -3, 0, 2, -1, 2, -4, +4, -3, 1, -1, 3, 1, -5, 0, +4, -1, 0, -1, -1, 3, -4, 4, +-3, 4, -4, 1, 0, 2, -3, 4, +-6, 4, 0, -1, 1, -1, 0, 0, +0, 2, -2, 1, -1, 0, 2, -2, +1, 2, -4, 1, 1, 2, -4, 2, +0, -1, 1, -2, 4, -1, -3, 0, +2, 3, -4, 1, -1, 0, 2, 0, +-1, 1, -2, 2, -2, 4, -3, 0, +0, -2, 5, -4, 3, -3, 1, -2, +3, 1, -3, 1, -1, 2, -1, 0, +1, 1, -5, 3, 0, 4, -6, 1, +1, 0, 1, -2, 1, 1, -2, 0, +2, -1, 1, -3, 2, -1, 2, 1, +-5, 4, -2, 1, 1, -1, 1, -4, +5, -4, 5, -4, 2, -2, 1, -1, +3, -1, -2, -2, 4, 0, -1, -1, +1, 0, 0, -1, 2, 1, -3, 0, +2, -2, 4, -4, 1, 0, -1, 3, +-3, 3, -3, 1, -1, 2, 0, 1, +-4, 3, -1, 1, 0, 0, -1, -1, +2, 0, 0, -1, 0, 0, 0, -1, +4, -3, 0, -3, 5, 0, -3, 2, +-2, 2, -1, 0, 1, 0, -1, -1, +1, 2, -2, 2, -5, 4, -1, 2, +-3, 1, 0, 0, -1, 3, -4, 4, +-5, 5, -4, 4, -4, 4, -5, 2, +1, 3, -6, 2, 1, -2, 4, -5, +4, -1, -2, 0, 3, 0, -2, -1, +2, -3, 6, -5, 2, -2, 2, -2, +3, -3, 3, -4, 2, 0, 1, 1, +-4, 3, -2, 2, 0, 0, 0, -4, +6, -4, 2, -1, 0, 1, -2, 0, +2, 1, -4, 1, 1, 1, -2, 2, +-4, 6, -6, 5, -4, 4, -4, 2, +-1, 1, 1, 0, -3, 1, 2, 0, +-1, 2, -4, 3, -2, 3, -2, 1, +-1, -1, 3, -5, 8, -6, 2, -4, +5, 0, -2, 0, -1, 3, -2, 1, +0, 0, 0, -3, 5, -2, 0, 1, +-3, 3, -1, 2, -3, 2, 0, -2, +2, -1, 2, -1, -2, 1, 1, 1, +-2, 2, -2, -1, 4, -2, 1, -2, +1, 0, 1, -1, 2, -2, -1, -1, +4, 0, -3, 1, -1, 2, -1, 2, +-3, 2, -1, -1, 2, 0, -1, 1, +-3, 2, 2, -1, -1, 0, 0, 0, +1, 0, -1, 0, 0, 1, -1, 2, +-4, 5, -4, -1, 6, -4, 1, -4, +5, -2, 2, -3, 2, -1, 1, -3, +4, -1, -1, 0, -1, 2, 0, 0, +-1, -1, 2, 0, -1, 1, -1, 1, +-2, 3, -2, 2, -3, 1, 0, 1, +-2, 4, -6, 3, 0, 1, -1, 0, +-1, 2, -2, 1, 0, 2, -4, 1, +2, -1, 2, -3, 1, 0, -1, 3, +-4, 4, -4, 3, -4, 5, -3, 3, +-5, 3, -1, 3, -3, 1, -1, 0, +1, 2, -3, 2, -3, 3, -1, 0, +0, 1, -3, 1, 2, 0, -1, -2, +2, 0, 0, -1, 1, 1, -3, 2, +0, 1, 0, -1, -1, 1, 2, -1, +0, -3, 4, -2, 1, 0, 0, 0, +-2, 2, 0, 0, 0, -1, 0, 0, +1, 2, -3, 0, 1, 0, 1, -2, +3, -3, 2, -3, 4, 0, -2, -1, +2, -2, 4, -4, 1, -1, 2, -2, +2, -3, 4, -4, 2, -2, 4, -3, +1, -2, 2, 0, 0, 0, 0, -2, +2, 1, -2, 2, -3, 2, -1, 0, +1, 2, -5, 1, 3, -3, 4, -4, +2, -1, 2, -3, 4, -3, 2, -3, +4, -4, 4, -2, -2, 1, 1, 0, +0, -1, 1, -3, 4, -3, 4, -4, +3, -4, 5, -3, 1, 2, -4, 2, +1, 1, -2, 0, 0, 1, 0, -1, +1, 0, -2, 0, 2, 0, -1, 0, +-2, 2, 2, -2, 0, 0, 0, 1, +-1, 2, -2, 2, -3, 2, 0, 2, +-4, 2, 0, -1, 1, 1, -2, 0, +1, -2, 3, -2, 0, 2, -4, 3, +0, 1, 0, -4, 5, -2, 2, -2, +1, -2, 3, -2, 0, 2, -3, 2, +-3, 3, -1, 1, -2, -1, 3, -2, +1, -1, 2, -3, 2, 0, 0, 2, +-4, 2, 0, 0, 2, -1, -2, 0, +1, 1, -2, 1, -3, 4, -5, 4, +-3, 4, -4, 1, 1, -1, 3, -3, +1, 0, 0, 3, -5, 5, -5, 4, +-2, 1, -1, 2, -6, 5, -2, 2, +-3, 1, 0, -1, 2, -1, 0, 1, +-2, 2, -1, 1, 1, -1, 0, -1, +2, 1, -3, 1, 0, 0, 0, 0, +-1, 1, 0, -2, 1, 1, -1, 1, +-3, 2, 1, 1, -3, 2, 1, -1, +1, -1, 2, -2, 1, -2, 4, -4, +3, -4, 3, -2, 1, 1, -3, 1, +0, 1, -1, 0, 1, 0, 0, -1, +2, 1, -2, 1, -1, 1, 2, -2, +0, -1, 2, -1, 0, -1, 1, -1, +-1, 0, 1, 1, -3, 1, 1, -1, +2, -1, 0, 0, 0, 2, -1, 1, +-2, 3, -4, 4, -3, 4, -6, 2, +-1, 2, -2, 0, -1, 0, 1, -1, +1, -1, 2, -3, 4, -4, 7, -5, +1, 1, -1, 5, -7, 5, -3, 0, +1, -2, 2, -1, -2, 1, 0, 0, +-1, 3, -5, 3, -1, 3, -4, 4, +-3, 4, -2, 1, 0, 1, 0, -2, +2, 0, -2, 3, -5, 2, 1, -1, +-1, -2, 3, -3, 2, -1, 1, 0, +0, -2, 5, -1, -1, 2, -2, 1, +1, 1, -3, 1, 0, -1, 2, -4, +3, -2, -1, 0, 0, 1, -1, -1, +1, 0, 1, 1, -2, 2, 0, 1, +0, 0, 2, -3, 4, -5, 6, -4, +1, -3, 4, -4, 1, 0, -2, 2, +-3, 2, -1, 2, -3, 4, -4, 4, +-1, 3, -3, 2, 0, 0, 3, -4, +3, -3, 1, 0, -2, 2, -3, 1, +-2, 1, -1, 2, -4, 2, 0, 2, +-2, 2, -1, 1, 1, 0, 2, -1, +0, 0, 1, -1, 0, 0, -2, 1, +-2, 2, -3, 1, -2, 1, -1, 2, +-3, 4, -4, 4, -1, 1, 2, -2, +2, 0, 0, 2, -2, 1, -1, 0, +0, 0, -2, 1, -3, 1, 1, -2, +0, -1, 0, 2, -2, 3, -1, 0, +2, -2, 4, -1, 0, 2, -3, 4, +-4, 4, -4, 0, 2, -4, 3, -4, +1, -1, 0, -1, 2, -3, 4, -4, +5, -4, 5, -2, 2, -1, 3, -1, +-1, 3, -2, 2, -3, 1, -1, 2, +-5, 2, -2, 1, -2, 0, 0, -1, +2, -2, 3, -2, 3, -2, 4, -3, +5, -2, 1, 0, 0, 1, -1, 1, +-3, 1, -2, 1, -3, 2, -3, 1, +-2, 1, 0, 2, -3, 2, 0, 3, +-1, 1, 1, -1, 3, -1, 2, -1, +-2, 2, -2, 2, -4, 3, -6, 4, +-4, 2, -2, -1, 2, -2, 1, 0, +1, 1, 0, 1, 1, 1, 2, -1, +1, -1, 1, 2, -4, 2, -3, 1, +-2, 0, 0, -2, -2, 1, -1, 3, +-5, 4, -2, 2, 1, 1, 0, 1, +1, 2, -2, 3, -3, 3, -3, 2, +-3, 2, -4, 2, -3, 0, -1, 0, +-2, 0, 1, -1, 2, -2, 3, 0, +1, -1, 5, -2, 2, -2, 4, -2, +0, 2, -5, 5, -6, 2, -3, 2, +-5, 4, -6, 4, -2, 1, 0, -2, +5, -2, 2, 2, -2, 3, 0, 2, +-1, 3, -4, 4, -5, 3, -2, 1, +-4, -1, 1, -2, -1, 1, -3, 3, +-3, 2, 0, 2, -1, 3, -2, 6, +-3, 5, -4, 4, -2, 4, -5, 2, +-2, 0, -2, -1, 0, -2, -1, -1, +-2, 2, 0, -1, 0, 0, 2, 2, +0, 1, 2, 1, -1, 3, -1, 3, +-5, 4, -5, 4, -4, 0, -2, -2, +1, -2, 1, -5, 3, -2, 3, -1, +0, 2, 1, 0, 5, -3, 3, 1, +-2, 5, -3, 2, -3, 1, -2, 2, +-5, 2, -5, 3, -5, 2, -1, 0, +-2, 3, -2, 5, -3, 4, 0, 1, +2, 0, 3, -1, 1, -1, 1, 0, +-3, 2, -5, 2, -3, 0, -2, 0, +-3, 2, -1, 1, 0, 1, -1, 3, +1, 0, 5, -3, 4, -2, 4, -2, +2, -2, 0, -1, -3, 2, -4, 2, +-6, 2, -2, 0, 0, -2, 4, -4, +4, -1, 4, -1, 4, -3, 6, -2, +3, 0, 0, -1, 0, 0, -2, 1, +-5, 1, -4, 3, -5, 1, -2, -1, +2, 0, 0, 1, 1, 2, 2, 2, +0, 2, 1, 1, -1, 3, -2, 1, +-4, 1, -3, 3, -6, 0, -1, -3, +2, -3, 1, -1, 1, 1, 2, 0, +3, -1, 4, -1, 4, 0, 0, 1, +-2, 2, -1, 0, -5, 2, -4, 1, +-3, -1, -2, 1, -4, 4, -2, 3, +-3, 3, 2, 1, 3, -1, 3, 1, +1, 1, 0, 0, -1, 0, -2, 0, +-3, -1, -3, -1, 0, -2, -1, -1, +1, -1, 4, -3, 4, 0, 3, 1, +2, 1, 2, 1, 0, 0, 1, 0, +-4, 2, -4, 0, -3, -1, -2, 1, +-4, 0, -1, 1, 1, 0, 3, -3, +6, 0, 2, 2, 2, -1, 3, 0, +0, 1, -3, 0, -3, 1, -3, -1, +-3, -2, -1, 0, -2, 0, 1, -2, +4, -2, 7, -3, 4, 0, 3, 3, +0, 0, 1, -1, 1, -1, -2, -1, +-3, 0, -4, 1, -4, 0, -3, 1, +0, 1, 0, 0, 2, 1, 6, -3, +6, -3, 4, 1, 1, -1, 2, -3, +-1, 1, -5, 3, -7, 0, -1, -3, +1, -4, 2, -2, 2, 0, 3, -1, +4, 0, 4, 0, 5, -2, 2, 2, +-3, 5, -5, 2, -6, 1, -3, -1, +-3, -1, -5, 4, -5, 2, 1, -2, +2, 1, 4, 0, 3, 0, 5, -1, +4, -1, 1, 2, -4, 2, -2, -2, +-2, -2, -3, -1, -1, -3, -1, 0, +-1, 1, 0, 1, 2, 1, 5, -2, +6, -2, 5, 0, 2, -2, 3, -4, +2, -5, 3, -6, -2, 0, -5, 3, +-5, -1, 0, 0, 1, 0, 4, -3, +7, -2, 7, -2, 5, -1, 2, 2, +0, -2, 2, -5, 1, -1, -4, 0, +-6, 1, -3, 1, -3, -1, 0, 2, +1, 1, 4, -1, 4, 1, 3, 3, +1, 0, 0, 2, -2, 2, -4, -1, +-4, 0, -2, -3, -2, -3, -1, 1, +-1, 0, 1, 0, 3, 1, 5, -1, +4, 0, 4, 1, 2, -1, 0, 0, +-1, -1, -3, -1, -5, 0, -3, -2, +0, -5, 3, -3, 3, -1, 3, 0, +3, 2, 3, 3, 0, 4, -2, 5, +-2, 1, -2, -2, -1, -2, -1, -4, +-3, -1, -4, 2, -4, 1, -3, 4, +-2, 4, 2, 0, 5, -1, 7, -1, +3, 2, -3, 5, -3, -1, -1, -2, +-3, 0, -5, 0, -5, 1, -4, 1, +0, -4, 6, -3, 5, 1, 2, 3, +1, 4, 2, 0, 5, -5, 3, 0, +-2, 0, -4, -2, -4, 1, -5, 0, +-4, -2, 1, -1, 2, -1, 2, 2, +3, 1, 6, -2, 5, 0, 3, 2, +-1, 1, -4, 3, -6, 3, -7, 0, +-6, 1, -4, 1, -4, 1, -2, 2, +3, -2, 7, -5, 9, -2, 8, -3, +5, -2, 4, -1, 2, -4, -1, -1, +-5, 2, -6, -1, -4, -2, 0, -2, +2, -4, 4, -2, 6, -1, 6, -2, +6, 0, 5, 1, 1, 0, -1, 2, +-3, 1, -6, 1, -7, 1, -2, -5, +2, -8, 4, -3, 4, -3, 4, 0, +4, 1, 6, -1, 5, -1, 6, -2, +3, -2, -2, 2, -4, -2, -1, -5, +-1, -4, 0, -5, 2, -4, 1, 2, +-1, 4, -1, 5, 1, 5, 2, 2, +1, 3, 1, 0, 1, -3, -2, 2, +-8, 3, -8, 2, -8, 4, -7, 3, +-3, -1, 3, 1, 3, 0, 4, 0, +7, 0, 5, -1, 2, 1, 0, 2, +-3, -1, -5, 1, -5, 0, -5, -2, +-4, 2, -5, 5, -4, 1, 3, 0, +6, 0, 5, 0, 4, 1, 5, -1, +2, -2, -2, 5, -9, 5, -11, 4, +-9, 5, -9, 2, -4, -1, 2, -2, +5, -3, 5, -1, 8, -1, 6, 0, +2, 2, 3, -1, 1, -2, -4, 3, +-8, 3, -8, 1, -7, 1, -2, -2, +0, -2, 2, 1, 5, -3, 8, -3, +8, 0, 5, 0, 1, 2, -1, 1, +-1, -2, -5, 3, -10, 5, -9, 2, +-7, 3, -5, 3, -2, 0, 3, 1, +6, -3, 10, -5, 10, -3, 7, -4, +5, -3, 1, 0, -4, -1, -6, 3, +-9, 4, -8, 0, -3, 0, 0, 0, +3, -2, 4, 3, 3, 2, 6, -3, +6, 1, 1, 2, -2, -1, -1, -1, +-2, -4, -4, -1, -5, 1, -4, -2, +-1, 0, 2, 1, 3, -2, 6, 1, +6, 1, 4, -1, 4, 0, 2, 0, +-3, 0, -6, 3, -6, -2, -3, -4, +-3, 2, -4, 2, -2, 0, 3, 1, +6, -1, 4, 2, 4, 2, 5, -3, +3, -2, 2, -1, -3, -2, -6, 1, +-4, -2, -3, -3, -3, 1, -1, 2, +-1, 1, 3, 1, 9, -5, 10, -4, +7, 0, 3, 0, -2, 1, -4, 2, +-5, -1, -7, 1, -5, -1, -2, -3, +-1, 0, 2, -1, 5, -2, 5, 3, +4, 1, 4, 0, 3, 2, -1, 2, +-5, 3, -7, 2, -5, -2, -5, -1, +-5, 2, -4, 0, -2, 3, 1, 2, +4, -1, 5, 3, 4, 1, 4, -2, +3, 2, -3, 2, -5, -1, -4, 0, +-5, -3, -2, -4, 0, -1, -1, 1, +-1, 2, 4, 1, 5, 0, 3, 5, +1, 4, 0, 0, 0, 1, -3, 1, +-7, 1, -8, 3, -6, 0, -6, 1, +-4, 3, 1, -1, 3, -1, 5, 3, +5, 0, 5, -1, 5, 0, 2, -1, +-2, -1, -3, 0, -4, -3, -4, -3, +-1, -2, -2, 0, -3, 3, 2, 1, +4, -1, 5, 3, 6, -2, 6, -2, +3, 0, 0, 0, -5, 1, -7, 2, +-5, -2, -6, 2, -7, 3, 0, -3, +3, -1, 5, 0, 8, -4, 7, 1, +4, 2, 2, -1, 0, 0, 0, -3, +-2, -3, -5, 0, -4, -3, -2, -2, +-1, -1, 4, -4, 6, -2, 5, 3, +4, 0, 4, 2, 3, 0, 2, -1, +-3, 4, -8, 3, -6, -3, -3, -1, +-4, -1, -3, 0, -1, 3, -1, 4, +0, 3, 4, 3, 5, -2, 5, 0, +2, 2, -1, -3, -1, -2, -3, 0, +-5, -4, -3, 0, -3, -1, 1, -5, +5, 0, 3, 3, 1, 2, 4, 4, +3, 1, 1, 0, 2, 0, -1, -3, +-3, -1, -5, 1, -6, 0, -6, 0, +0, -1, 3, -3, 3, 0, 7, -1, +8, -2, 3, 5, 0, 4, -2, 2, +-5, 4, -5, 1, -6, -2, -4, 0, +-2, -4, -1, -1, 0, 1, 3, -3, +7, -2, 8, -3, 11, -6, 8, -2, +4, -1, 1, -2, -3, 1, -5, -1, +-3, -4, -5, 2, -6, 3, -5, 2, +-1, 1, 7, -6, 11, -5, 8, 0, +5, -1, 3, 1, -2, 3, -4, 1, +-6, 1, -6, 0, -4, -3, -5, 3, +-4, 1, 0, -2, 5, 0, 5, -1, +8, -4, 8, 1, 2, 2, -2, 4, +-4, 4, -7, 1, -5, -1, -4, 1, +-6, 0, -4, 1, 1, -1, 4, -4, +7, -1, 8, -2, 7, -3, 6, 2, +1, 1, -1, -2, 0, -2, -2, -2, +-5, -1, -6, 3, -5, 0, -3, -1, +3, 0, 4, -1, 3, 2, 3, 5, +1, 1, 1, 1, 0, 2, -5, 2, +-8, 3, -5, -1, -4, -5, 0, -3, +3, -6, 3, -2, 4, 1, 5, -2, +8, -3, 7, 0, 5, -1, 1, -1, +2, -3, 1, -3, -5, 2, -7, 2, +-5, 0, -5, 4, -3, 2, 2, -1, +5, 0, 6, 0, 6, -1, 5, 0, +4, -2, 1, 0, -3, 2, -6, 0, +-6, 2, -9, 5, -7, 1, -3, 1, +1, 0, 3, -2, 6, 0, 6, -2, +6, -2, 3, 2, -1, 0, -3, 0, +-5, 2, -7, 0, -7, 1, -5, 2, +-4, -1, -1, 2, 1, 2, 2, 0, +5, 1, 4, 2, 2, 1, -2, 5, +-4, 3, -6, 1, -6, 4, -8, 3, +-7, 1, -4, 4, -3, 2, -1, 3, +2, 4, 3, 2, 3, 1, 5, 2, +2, 0, -2, 2, -2, 1, -4, -1, +-6, 2, -6, 2, -4, -2, -1, -1, +4, -1, 2, 0, 2, 4, 3, 0, +4, -1, 2, 1, 2, -3, -1, -1, +-5, 3, -7, -1, -5, -2, -2, -2, +0, -4, 1, 1, 0, 2, 4, -3, +7, -2, 8, -4, 9, -7, 5, 0, +0, -1, -2, -2, -2, 0, -5, 0, +-5, 2, -5, 4, -2, 0, 1, 1, +6, -2, 7, -1, 5, 2, 4, -1, +6, -5, 5, -2, 1, -3, 0, -5, +0, -1, -4, 1, -6, 3, -5, 5, +-1, -1, 3, -1, 5, 2, 3, -1, +4, 0, 2, 1, 1, -3, -1, 0, +-4, 0, -4, -3, -4, 0, -4, 0, +-3, -2, 0, 0, 4, -5, 7, -4, +5, 3, 0, 2, 2, -2, 4, -2, +2, -3, -3, 0, -3, 1, -5, -1, +-5, 2, -3, 1, 0, -1, -1, 4, +2, 2, 4, 0, 4, 1, 6, -1, +5, -4, 4, -1, 1, -2, -1, -3, +1, -5, 3, -6, 2, -4, 3, -3, +5, -3, 2, 2, 4, 1, 4, -1, +2, 4, -1, 3, 0, -1, -3, 2, +-4, 1, -5, -2, -3, -2, 0, -6, +4, -8, 5, -3, 3, -1, 2, 0, +2, 2, 3, -1, 2, -1, 2, 1, +-2, -1, -3, 0, -2, -2, -4, -1, +-4, 1, -2, -1, 1, -3, 2, 2, +2, 2, 0, 3, 2, 4, 1, 1, +1, 2, -1, 3, -2, -1, -2, 1, +-4, 2, -3, -2, 0, -2, 2, -1, +2, -1, 2, 2, 4, 0, 5, -3, +7, -1, 5, -2, 0, 1, -3, 4, +-3, -3, -2, -2, -2, 1, -5, 0, +-3, 1, -2, 2, 0, -1, 2, 1, +3, 0, 3, -1, 0, 3, -2, 3, +-3, -2, -1, -2, 0, -3, -4, 0, +-6, 3, -4, -1, 1, -3, 1, 2, +1, 1, 0, 2, 3, 2, 1, -1, +4, -1, 1, 0, 0, -2, 0, -3, +2, -5, 2, -3, -2, 3, -4, 4, +-1, 0, 3, 0, 5, -1, 4, 1, +2, 3, 1, 2, -1, 4, -5, 4, +-2, -2, -1, -1, -1, -1, -2, -2, +0, 1, -2, 2, -1, 3, -3, 6, +-1, 1, 4, -4, 7, -5, 6, -6, +4, -4, -2, 3, -7, 2, -6, 0, +-3, 0, -3, -2, 0, -2, 1, 1, +-1, 1, 0, 1, 4, -2, 3, -3, +3, 0, 0, -1, 0, -2, -2, 1, +-3, 0, -3, -2, 1, -1, 0, 0, +-1, 0, 5, -1, 4, -1, 3, 2, +4, -1, 5, -1, 0, 4, -2, 2, +0, -2, -1, 1, -1, -1, 1, -3, +1, 0, 2, -2, 6, -5, 5, 0, +4, 1, -1, 3, 0, 3, 1, -2, +0, 0, -2, 2, -4, 0, -5, 2, +-5, 1, -4, 1, -5, 3, -2, -1, +1, -2, 1, 1, 1, -2, 2, -2, +1, 0, -2, 0, -2, 0, -5, 2, +-4, 0, -4, 0, -3, 2, -4, 2, +-3, 3, -1, 1, 3, -2, 4, 1, +2, 0, 4, -1, 2, 1, 2, -1, +1, 0, -2, 6, -6, 4, -3, 3, +-1, 3, -1, 2, 2, 1, 2, 2, +4, -1, 4, 0, 4, 1, 1, 0, +1, 0, 1, -1, 0, -2, -2, 2, +-4, 1, -4, 1, -3, 1, -1, 0, +-3, 1, -1, 2, -1, 0, -3, 2, +-3, 3, -6, 3, -7, 3, -6, 1, +-4, -1, -7, 3, -5, 1, -4, -2, +0, -1, 1, -2, 2, -1, -1, 4, +0, -1, 4, -4, 6, -3, 3, 0, +0, 0, 1, 1, 1, -1, 1, -1, +5, -3, 6, -3, 5, -1, 6, -1, +8, -3, 6, -1, 9, -3, 5, 0, +2, 3, 0, 0, 2, -1, 0, -1, +4, -6, 3, -2, 0, 0, 0, -2, +1, -1, -1, 2, -2, -1, -1, 1, +-2, -1, -2, -2, -3, 1, -7, 2, +-7, 0, -7, 2, -6, -1, -5, -1, +-3, 0, -4, -1, -1, 0, -3, 3, +-3, 2, -3, 2, -1, 2, -2, 1, +-1, 1, 0, 1, 0, 0, 0, 2, +2, -1, 4, -1, 3, 3, 3, 1, +6, -1, 6, 4, 2, 4, 3, 2, +5, 1, 4, 0, 5, -1, 2, 2, +1, 1, -1, 2, 0, 2, -2, 2, +-1, 2, -2, 2, 0, -2, 1, -1, +-1, 1, -6, 4, -8, 3, -6, 0, +-7, 0, -8, 2, -7, -3, -4, -5, +-1, -4, -4, -1, -7, 3, -6, -2, +2, -6, 0, -1, -1, 0, -3, 1, +-4, 5, -7, 5, -4, 2, -3, 4, +-2, 2, 1, 1, 2, 1, 6, -2, +8, -1, 7, 2, 6, 1, 7, 3, +4, 4, 5, 0, 9, -4, 11, -5, +10, -3, 4, 0, 6, -1, 2, 1, +1, 4, -2, 3, 0, 1, 0, 0, +2, -2, -1, 0, -3, 1, -5, 0, +-6, 0, -7, -1, -6, -4, -5, -3, +-8, 1, -11, 3, -13, 5, -11, 3, +-8, -1, -5, -1, -2, -3, -4, 0, +-4, 1, -5, -1, -1, -1, -4, 3, +-4, 2, -2, 0, 3, 1, 1, 3, +1, 3, 7, 0, 9, -2, 9, 3, +7, 2, 9, 0, 9, 1, 8, 0, +10, -3, 9, -1, 8, 0, 6, -3, +10, -3, 8, -2, 6, -1, 4, 1, +3, 1, -2, 3, -2, 3, -5, 1, +-5, 0, -5, -1, -8, -1, -9, 2, +-12, 0, -11, 1, -11, 0, -9, -1, +-9, 0, -10, 2, -9, 1, -10, 2, +-9, 3, -11, 3, -9, 3, -9, 2, +-6, 1, -5, 0, 0, 0, -1, 2, +0, 4, 2, 3, 5, 2, 7, 2, +10, -1, 12, -1, 12, -1, 12, 0, +8, 4, 5, 5, 7, 0, 9, 0, +10, 0, 9, -2, 11, -1, 9, -2, +10, -2, 5, 1, 4, 0, 1, -2, +1, -1, -3, -1, -6, -1, -8, 1, +-11, 2, -15, 4, -14, 2, -12, 0, +-12, 1, -12, 3, -14, 2, -12, 0, +-8, -4, -6, -6, -5, -5, -6, -3, +-7, -3, -6, -2, -2, -3, -3, 0, +-2, 5, -3, 3, 4, 0, 8, -1, +11, -1, 10, 0, 11, 0, 12, 0, +9, 3, 8, 4, 8, 2, 10, 2, +12, -3, 17, -3, 13, 1, 12, 0, +14, -4, 13, 0, 7, 3, 1, 4, +1, 1, -1, -1, -2, 1, -9, 2, +-8, -1, -8, -2, -8, -2, -9, -2, +-10, 0, -11, -1, -9, -6, -7, -3, +-11, -2, -13, -1, -14, 1, -16, 1, +-15, -1, -11, -1, -10, -2, -7, -1, +-3, -3, 1, -4, 6, -2, 3, 1, +7, 0, 7, 0, 11, -1, 10, -1, +11, 2, 9, 1, 12, -2, 15, -1, +16, -2, 16, 0, 16, 0, 18, -1, +17, -1, 16, 1, 14, -2, 13, -3, +12, -3, 7, -4, 5, -2, -1, -1, +-3, -1, -6, -1, -6, 1, -12, 1, +-8, -1, -9, -2, -10, -1, -13, 1, +-14, -1, -17, 1, -19, 2, -19, -1, +-18, -1, -17, 0, -15, -2, -12, -1, +-10, 0, -6, -2, -1, -3, 2, -2, +5, -3, 5, -1, 8, -2, 8, -3, +12, -2, 9, -1, 14, -4, 15, -2, +18, -3, 19, -3, 22, -2, 22, -3, +23, -2, 21, 1, 16, 1, 15, 3, +9, 3, 8, 0, 8, -2, 4, 0, +0, 1, -2, -1, 0, -4, -1, -3, +-3, 0, -10, 2, -10, 2, -15, 3, +-15, 0, -18, 1, -20, 3, -25, 3, +-25, 3, -23, 0, -19, -3, -16, 0, +-17, 3, -16, 4, -14, 5, -8, 0, +-2, -3, 1, 0, 0, 0, 0, 1, +4, 0, 4, 0, 8, 0, 9, 1, +13, 2, 12, 2, 20, 0, 20, 1, +22, 1, 23, -2, 25, -2, 21, -1, +19, -2, 16, 0, 10, 1, 9, 0, +5, 1, 3, 3, 1, 0, 1, 0, +1, -1, -1, -2, -3, -1, -9, 1, +-11, -1, -15, -1, -17, 0, -23, 1, +-23, 1, -25, 0, -22, -1, -21, -1, +-17, -3, -14, -1, -15, 2, -13, 2, +-11, 0, -8, 2, -7, -1, -4, 1, +-5, 3, -4, 2, 2, -1, 7, -1, +10, 1, 11, 2, 19, -3, 23, -3, +26, 0, 22, 0, 26, -3, 25, -2, +23, -1, 17, 1, 16, 0, 14, 0, +10, 3, 8, 3, 7, 0, 9, 0, +6, 0, 5, -2, 3, -3, 1, -3, +-6, 0, -14, 4, -19, 1, -19, -3, +-18, -1, -26, 3, -26, 3, -27, 3, +-22, 1, -23, 3, -19, 3, -19, 1, +-15, 0, -12, -1, -12, 0, -14, 5, +-15, 4, -9, 0, -3, -2, 2, -1, +5, -1, 11, -2, 17, -2, 17, 2, +19, 3, 20, 0, 25, -1, 22, 1, +22, 1, 17, 1, 21, -2, 19, -3, +20, -2, 17, -1, 16, 1, 13, 1, +13, -2, 15, -3, 8, 0, 3, 1, +-2, -2, -3, -3, -9, -3, -14, -1, +-17, -2, -20, -1, -21, 0, -23, 1, +-21, 0, -21, -2, -14, -5, -16, -3, +-16, 0, -20, 1, -19, 2, -20, 1, +-16, -2, -11, -3, -8, -3, -4, -1, +-3, 2, 2, 2, 7, 0, 13, 1, +15, 3, 15, 4, 16, 4, 18, 1, +20, 2, 15, 5, 17, 2, 17, 0, +22, -1, 21, -3, 24, -2, 20, 2, +18, 1, 15, 2, 13, 2, 7, 3, +2, 2, -2, 3, -9, 1, -9, -1, +-13, -1, -16, 0, -18, 1, -20, 2, +-21, 1, -18, -2, -16, -2, -19, -2, +-17, -2, -21, -1, -21, 1, -26, 2, +-21, -1, -20, -1, -16, 0, -13, -1, +-7, -1, -2, 0, 2, 0, 6, 3, +7, 3, 11, 3, 12, 2, 16, 0, +17, -1, 18, -1, 20, -2, 20, -1, +22, -1, 22, -1, 25, 1, 22, 1, +24, 1, 20, 2, 21, -1, 15, 1, +11, 1, 4, 1, 1, -1, -2, -1, +-8, 0, -10, 1, -13, 0, -13, 0, +-14, -1, -14, 1, -19, 2, -19, 0, +-19, -1, -22, -1, -23, 0, -26, -1, +-22, -3, -24, -1, -20, 0, -19, -2, +-11, -1, -8, -3, 0, -3, 2, -1, +4, 2, 3, 4, 4, 3, 11, -2, +11, 0, 13, 2, 12, 0, 17, 0, +19, 0, 23, -2, 26, -2, 28, -2, +30, -3, 26, 0, 25, 1, 17, 1, +18, -2, 14, -5, 13, -3, 2, 2, +-2, 1, -4, 1, -6, 0, -6, 0, +-9, 1, -11, 3, -14, -1, -13, 0, +-19, 3, -24, 3, -27, 2, -26, -1, +-24, -4, -23, -4, -20, -3, -22, 0, +-17, 1, -17, 1, -9, 2, -11, 5, +-6, 3, -3, -1, 6, -5, 8, -5, +8, -3, 10, -3, 11, -3, 15, 0, +14, 1, 19, 1, 21, 1, 25, 0, +27, -1, 28, -1, 27, -2, 24, -1, +21, 1, 13, 1, 13, -1, 9, -1, +8, 0, 0, 4, -1, 3, -1, -2, +4, -6, 2, -3, -5, 1, -12, 4, +-17, 2, -18, 1, -23, 1, -23, -1, +-25, -3, -23, -2, -23, -2, -23, 0, +-20, 1, -20, 3, -16, 3, -15, 2, +-9, 2, -11, 2, -5, 1, -6, 0, +-1, -1, 1, -1, 3, -1, 8, -2, +14, -5, 19, -3, 22, -4, 27, -4, +27, -2, 26, 2, 23, 0, 23, 1, +19, 3, 14, 2, 15, -1, 14, -3, +16, -4, 11, -1, 10, 0, 5, 2, +5, 2, 0, 1, 2, -1, -4, 0, +-7, -1, -11, -1, -16, 0, -19, -1, +-22, -2, -20, -3, -21, -4, -19, -1, +-21, 1, -20, 3, -19, 3, -16, 0, +-11, -2, -11, -1, -8, -2, -11, -1, +-5, -3, -4, -6, 3, -3, 0, 1, +5, 0, 10, -2, 17, -2, 18, 0, +19, 1, 22, 0, 21, -1, 23, -1, +20, -1, 20, -2, 18, -3, 19, -3, +16, -1, 13, 2, 12, 1, 10, 2, +10, 3, 6, 1, 9, -2, 3, -2, +2, -2, -7, -1, -10, 0, -16, 1, +-18, -1, -17, -3, -17, -3, -17, 0, +-19, 1, -19, 3, -18, -1, -11, -5, +-12, -3, -13, -1, -13, -2, -15, 2, +-16, 4, -16, 1, -7, -2, -4, -4, +6, -4, 3, 2, 7, 3, 8, 1, +16, 1, 15, 0, 18, -1, 18, 0, +16, -1, 18, -2, 15, -1, 17, -1, +16, -2, 19, -2, 19, -4, 20, -2, +16, 1, 12, 0, 13, -2, 8, -1, +6, -2, -2, 0, -4, 0, -10, -1, +-9, 0, -16, 2, -15, -1, -14, -1, +-14, 1, -17, 4, -18, 4, -16, 1, +-17, 0, -14, 0, -19, 2, -19, 2, +-19, 1, -16, 1, -15, 2, -12, 3, +-8, 4, -6, 4, 2, 1, 4, 1, +9, 2, 5, 5, 8, 4, 7, 4, +10, 2, 10, 2, 11, 3, 10, 3, +12, 1, 17, 0, 16, -2, 21, -2, +18, 0, 15, 3, 11, 3, 9, 4, +3, 5, -3, 4, -1, -1, -4, -1, +-5, 1, -10, 1, -7, 0, -11, 0, +-7, -2, -8, -3, -6, -4, -10, -1, +-13, -2, -13, -4, -13, -3, -16, 0, +-17, -1, -14, -1, -17, 2, -13, 0, +-8, -2, -4, 0, -2, 0, 1, 0, +5, -1, 5, -1, 9, -1, 6, 0, +8, 0, 5, 1, 10, -3, 13, -5, +18, -4, 17, -1, 18, -2, 19, 0, +18, -1, 17, 0, 14, 0, 13, 0, +9, -1, 9, -2, 5, -2, 2, 0, +1, -2, -1, 0, -4, 2, -6, -2, +0, -5, -3, -3, -3, 0, -10, 2, +-11, 1, -12, -3, -12, -3, -15, -2, +-14, -3, -15, -1, -15, -1, -10, -4, +-7, -3, -3, 0, -6, 2, -5, 4, +-6, 4, -5, 4, -5, 5, -4, 5, +-1, 4, -1, 2, 6, 1, 4, 1, +9, 2, 7, 4, 9, 4, 11, 1, +17, -2, 17, 0, 15, 0, 15, -2, +13, -2, 9, 3, 0, 3, 1, 1, +2, -2, 4, 0, 1, 2, 0, 2, +0, 0, -1, -1, 0, -3, -3, -4, +-2, -4, -9, -2, -10, 0, -16, 1, +-12, 0, -14, 1, -14, 2, -14, -1, +-11, -1, -8, -1, -6, -3, 0, -3, +-1, -2, -1, -1, -4, 1, -1, -2, +0, -4, 1, -1, 0, 0, -1, 2, +5, 2, 6, 1, 12, 2, 10, 1, +15, -2, 13, -3, 16, -4, 13, -4, +12, -1, 8, 2, 5, 3, 4, 3, +4, -1, 8, -3, 6, -3, 7, -2, +4, -3, 4, 0, 0, 2, -4, 5, +-5, 4, -9, 2, -8, -1, -11, -4, +-8, -3, -11, -3, -6, -4, -6, -3, +-5, -1, -7, 1, -6, 0, -5, -2, +-2, -7, 0, -6, -5, -2, -5, 0, +-5, 2, -4, 4, -4, 1, 1, -2, +4, -3, 5, -2, 8, -3, 11, -5, +15, -4, 11, 2, 9, 4, 5, 3, +9, -1, 7, -2, 7, -2, 4, -1, +7, -3, 9, -3, 11, -2, 11, -1, +8, 0, 8, -3, 5, -5, 5, -4, +0, -4, 0, -2, -3, -1, -4, -2, +-4, 0, -9, 3, -8, 2, -10, 0, +-7, -1, -9, -1, -6, 1, -9, 6, +-7, 4, -9, 6, -10, 4, -12, 3, +-11, 1, -7, -2, -3, -5, 1, -2, +0, 1, 1, 4, 2, 4, 6, 0, +8, -4, 7, -3, 7, -4, 5, -3, +9, -2, 7, -1, 8, 2, 4, 4, +4, 3, 2, 1, 7, -2, 5, -2, +6, 1, 4, 4, 1, 5, 3, 2, +4, -3, 4, 0, -4, 0, -3, -4, +-5, -4, -4, -2, -2, -2, -2, 2, +-1, 3, -4, 1, -4, 1, -7, -2, +-4, -3, -7, -1, -6, -3, -6, -1, +-6, 4, -8, 5, -5, 2, -3, 1, +-4, -2, -2, -3, 0, -3, 4, -2, +4, 3, 3, 3, 4, -1, 8, -3, +6, -4, 6, -7, 8, -9, 8, -7, +7, 0, 2, 5, 7, 4, 5, 4, +7, 4, 3, -1, 6, -4, 4, -5, +5, -8, 6, -4, 3, 1, 1, 4, +-1, 1, 3, -4, 1, -6, 2, -5, +1, -6, -1, -2, -2, 1, -4, 4, +-6, 7, -7, 7, -5, 0, -8, 0, +-8, -3, -10, -3, -5, 0, -6, 5, +-4, 6, -5, 8, -4, 6, -3, 2, +0, -2, 2, -6, 0, -5, 0, 0, +-3, 3, -1, 8, -1, 6, 3, 1, +5, -3, 5, -5, 7, -6, 3, -2, +6, -1, 4, 3, 4, 9, -2, 8, +3, 2, 2, -3, 4, -8, 4, -8, +2, -4, 0, 1, -1, 1, 4, 3, +2, 5, -1, 7, -4, 3, -6, -3, +-5, -3, -7, 0, -7, 4, -7, 7, +-5, 4, -3, 0, 1, -2, -1, -4, +1, -7, 0, -8, 2, -7, -1, 0, +-1, 6, -2, 8, -2, 7, -3, 1, +-1, -7, 2, -7, -1, -5, 1, -3, +2, -1, 6, 2, 4, 6, 2, 7, +4, 0, 5, -7, 6, -7, 2, -6, +3, -3, 1, 1, 4, 4, 1, 5, +4, 4, 2, 0, 0, -3, 2, -8, +3, -9, 4, -1, 1, 5, -1, 7, +-1, 5, 1, -1, 1, -3, -2, -2, +-5, -4, -6, -4, -6, 1, -5, 6, +-4, 10, -2, 9, -1, 3, -3, -3, +0, -8, -2, -8, 0, -4, -4, 2, +-4, 5, -5, 10, -5, 9, -2, 4, +0, -2, 2, -7, 0, -9, 3, -4, +0, 2, 1, 7, 1, 9, 0, 8, +-1, 5, -3, 0, -1, -6, -2, -5, +1, -4, 2, 0, 5, 5, 4, 6, +5, 1, 7, -4, 9, -10, 6, -11, +4, -9, 0, -7, 1, -2, 4, 4, +2, 7, 2, 5, 0, -3, 1, -8, +-1, -8, 0, -6, 1, -4, 0, 3, +-2, 8, -7, 10, -3, 8, -3, 0, +0, -8, -3, -9, -2, -8, -5, 1, +-2, 6, 1, 8, -1, 10, -2, 7, +-2, -3, 2, -8, 3, -12, 4, -10, +2, -2, 0, 5, 1, 8, -1, 11, +1, 4, 1, -2, 1, -4, 0, -8, +2, -8, 3, -1, 3, 5, 2, 10, +4, 8, 1, 0, 2, -5, 0, -10, +2, -10, 2, -3, 0, 0, 2, 4, +-2, 12, -4, 13, -3, 4, 2, -3, +-3, -8, -6, -8, -4, -5, -2, 2, +1, 7, 1, 5, 5, 0, -3, 3, +-4, -3, -2, -10, 3, -11, 2, -6, +-3, 4, -5, 13, -3, 10, 2, 3, +4, -2, 1, -10, 2, -13, 1, -9, +2, -5, 2, 4, 2, 12, -1, 14, +-5, 13, -4, 4, -2, -8, 2, -10, +4, -8, 1, -3, 2, 7, -3, 10, +1, 10, 1, 8, 2, 1, -2, -6, +-3, -9, -2, -7, -3, 2, 2, 9, +0, 10, -1, 9, -2, 1, -1, -5, +-1, -5, -3, -7, -2, -7, -5, 0, +-2, 5, -1, 10, 1, 12, -2, 6, +-6, -2, -7, -7, -6, -10, -2, -6, +3, -2, 3, 4, 2, 9, -2, 9, +0, 1, 0, -4, 2, -12, 3, -12, +1, -5, 1, 3, -2, 9, 3, 11, +4, 5, 4, 2, 1, -4, -2, -13, +4, -13, 3, -5, 6, 3, 4, 9, +5, 9, 1, 4, 0, -1, 4, -7, +1, -10, 1, -7, -3, -7, 1, 0, +1, 11, 0, 14, 2, 5, 1, -4, +0, -14, -4, -12, 0, -8, 0, -1, +-2, 8, -4, 11, -5, 8, -3, 7, +-1, -2, 2, -13, 4, -16, 0, -13, +1, -3, -2, 10, 0, 12, 1, 11, +0, 5, 0, -6, 0, -12, 3, -13, +4, -13, 8, -1, 3, 9, 1, 10, +3, 9, 1, 2, 8, -10, 7, -12, +6, -11, -3, -5, -2, 2, 1, 9, +1, 16, 0, 17, -4, 4, -4, -6, +-3, -13, 3, -15, 7, -8, 6, 0, +3, 4, -5, 13, -4, 9, -2, 3, +-1, -3, -2, -14, -3, -16, -3, -5, +-3, 3, 2, 10, 4, 10, 1, 1, +2, -4, -5, -7, 0, -13, 1, -10, +2, -2, -4, 7, -6, 14, 0, 10, +4, 1, 9, -3, 3, -9, 0, -9, +-3, -6, -2, -3, 6, 4, 5, 12, +7, 10, 1, 7, -1, -1, -2, -13, +5, -15, 8, -8, 3, 0, 0, 9, +-2, 9, 2, 7, 4, 6, 3, -2, +2, -13, -3, -14, -3, -12, -2, 0, +1, 13, -2, 17, -7, 11, -5, 3, +-7, -7, -2, -9, 2, -12, 3, -11, +0, -1, -7, 10, -4, 13, -2, 10, +6, -1, 2, -10, -2, -11, -5, -10, +-4, -4, 4, 3, 5, 7, 6, 12, +-2, 12, -3, 2, 2, -10, 7, -16, +10, -14, 1, -1, 0, 6, -3, 10, +2, 11, 9, 3, 9, -1, 2, -2, +-6, -11, -2, -12, 1, -2, 2, 7, +5, 12, -1, 11, -1, 2, -6, -2, +-1, -7, 1, -11, 0, -8, -4, 0, +-12, 7, -7, 17, -3, 13, 2, 7, +-1, -2, -8, -11, -7, -13, -7, -6, +3, -1, 0, 7, 0, 13, -7, 10, +-5, 6, 1, -2, 3, -13, 7, -13, +2, -10, -1, 1, -4, 13, 0, 13, +7, 8, 2, 8, 1, -4, -3, -12, +3, -13, 6, -11, 9, 0, 7, 13, +-1, 13, -2, 12, -4, 5, 0, -5, +4, -9, 2, -10, -1, -7, -9, 4, +-3, 10, 0, 12, 3, 12, 2, -1, +-4, -13, -3, -13, -3, -13, 4, -5, +4, 2, 0, 6, -8, 13, -14, 13, +-4, 2, -2, -5, 3, -13, -3, -15, +-4, -3, -5, 7, 1, 11, 6, 13, +2, 6, -3, 2, -9, -3, -2, -13, +7, -12, 7, -4, 7, 3, -3, 15, +-2, 13, 3, 0, 12, -6, 11, -9, +3, -11, 1, -7, -2, -2, 2, 5, +5, 11, 7, 9, 4, 3, -3, -5, +0, -15, -1, -12, 5, -5, 2, 2, +-4, 9, -7, 12, -8, 7, 0, 7, +-1, 0, -1, -9, -8, -12, -9, -10, +-4, -1, -4, 14, 1, 15, -6, 11, +-7, 4, -7, -8, -1, -11, 7, -11, +7, -12, 6, -2, -4, 8, -4, 12, +0, 9, 7, 0, 10, -11, 2, -12, +3, -12, 1, -7, 7, 2, 11, 5, +10, 9, 3, 12, -4, 1, 1, -8, +5, -13, 10, -14, 7, -3, -2, 5, +-1, 5, -2, 9, 5, 6, 5, -1, +3, -3, -7, -8, -9, -12, -2, -4, +1, 4, 3, 11, -4, 11, -6, 0, +-7, -5, -5, -5, 2, -10, -1, -7, +0, -3, -9, 2, -7, 12, -1, 12, +5, 1, 8, -4, -3, -10, -5, -12, +-4, -6, 3, 0, 7, 5, 2, 12, +-1, 10, -5, 6, 3, -1, 8, -12, +12, -12, 6, -3, -4, 1, -1, 8, +1, 9, 9, 5, 7, 4, 3, -1, +-3, -7, -8, -6, 3, -10, 6, -3, +9, 10, -3, 12, -6, 8, -7, 5, +-5, -5, 3, -7, -2, -5, -6, -6, +-11, 0, -9, 8, -3, 11, -2, 12, +3, 0, -5, -10, -6, -9, -7, -7, +-1, -2, 2, 6, -1, 4, -3, 5, +-7, 8, -1, 1, 4, -3, 4, -6, +2, -12, -2, -5, 2, 3, 3, 6, +14, 5, 12, 3, 4, -1, -1, -2, +-4, -7, 5, -8, 7, -4, 8, 2, +2, 8, -4, 13, -1, 6, 1, -1, +11, -7, 3, -8, -3, -3, -9, -1, +-5, 1, 1, 9, 1, 10, 1, 4, +-8, -2, -6, -11, -3, -12, -2, -2, +2, 0, -6, 5, -7, 9, -11, 5, +-1, 2, 6, -2, 4, -11, 0, -10, +-9, -9, -3, -5, 3, 3, 9, 8, +6, 7, -6, 8, -3, -2, -2, -7, +8, -6, 9, -9, 9, -5, 3, 5, +-3, 9, 2, 10, 4, 4, 12, -8, +8, -10, 1, -5, -2, -6, 2, -2, +12, 3, 5, 8, 2, 11, -7, 6, +-6, -5, 0, -9, 4, -11, 4, -5, +-4, 2, -6, 3, -8, 6, -2, 7, +4, 0, 1, -4, -1, -9, -10, -10, +-8, -3, -4, 2, 4, 3, 3, 7, +-6, 3, -5, -2, -6, 0, 0, -2, +1, -4, -1, -2, -1, -3, -3, 4, +6, 9, 7, 5, 9, 1, 2, -4, +-1, -11, 1, -6, 2, -1, 10, 0, +8, 4, 6, 8, -1, 5, 1, 1, +10, -9, 9, -11, 8, -4, -6, 2, +-8, 7, -8, 11, -1, 6, 5, 3, +2, 0, -1, -8, -6, -11, -1, -10, +2, -6, 1, 7, -3, 11, -12, 8, +-9, 5, -6, -4, 4, -9, 3, -5, +-5, -7, -7, -4, -9, 3, -1, 8, +2, 10, 4, 7, -2, 0, -10, -1, +-5, -4, -2, -3, 7, 2, 3, 3, +2, 3, -1, 7, 2, 3, 9, -2, +8, -5, 9, -10, 0, -6, -1, 1, +5, 1, 9, 4, 12, 6, 2, 2, +1, -2, -5, -3, -3, -7, 3, -7, +5, -3, 2, 4, -7, 9, -5, 6, +-2, 0, 2, 1, -1, -3, -10, -4, +-8, -5, -9, -6, 2, 0, 3, 8, +0, 6, -4, 2, -9, -4, -4, -9, +-1, -8, 9, -6, 4, -3, -3, 5, +-3, 6, -4, 7, 6, 6, 4, -2, +2, -5, -7, -3, -6, -3, 2, 3, +7, 7, 12, 4, 6, 3, 2, 2, +1, -5, 5, -7, 12, -11, 9, -11, +6, 2, -6, 10, -6, 13, -4, 14, +-1, 3, 2, -4, -4, -4, -7, -6, +-5, -6, 3, 0, 4, 4, -2, 10, +-6, 9, -12, -2, -2, -8, -1, -8, +1, -7, -4, 0, -8, 2, -7, 5, +-6, 10, 3, 6, 2, 0, 0, -3, +-7, -9, -7, -7, 1, 0, 1, 6, +5, 8, -1, 8, -2, 3, -2, 3, +3, -3, 9, -9, 8, -9, 5, -4, +-3, 6, -2, 14, 4, 9, 8, 1, +9, -3, -1, -7, -3, -4, -5, 0, +1, 0, 2, 7, -2, 10, -3, 8, +-6, 6, -2, 1, -2, -6, -1, -6, +-3, -5, -10, -1, -4, 3, -3, 4, +3, 8, -5, 10, -7, 0, -9, -6, +-9, -7, -2, -5, -3, 4, 0, 8, +-4, 6, -5, 7, -2, 2, -1, -2, +5, -3, -1, -7, -1, -8, -2, 0, +3, 4, 8, 8, 8, 9, 6, 0, +0, -5, 1, -7, 3, -9, 5, -2, +5, 5, -2, 6, -1, 12, -4, 10, +2, 2, 5, -3, 3, -8, -1, -7, +-6, -2, -2, 2, -2, 7, 1, 11, +-2, 8, -7, 4, -7, -3, -7, -12, +2, -10, -2, -3, 0, 2, -5, 8, +-6, 8, -2, 2, -1, 1, 2, -3, +-4, -8, -5, -6, -5, -7, -1, -1, +7, 8, 3, 9, 4, 4, -1, -1, +0, -8, 0, -8, 7, -7, 9, -4, +0, 5, 0, 10, -3, 11, -1, 12, +4, 1, 5, -11, 7, -13, 1, -11, +5, -3, 2, 7, 6, 8, 5, 6, +0, 5, -2, -1, -5, -6, 0, -7, +0, -9, 0, -1, -3, 6, -8, 10, +-4, 11, -5, 6, -1, 0, -7, -3, +-6, -10, -6, -9, -2, -3, 4, 2, +1, 10, -1, 10, -5, 0, -3, -6, +-1, -6, -2, -5, 0, -1, -3, 2, +0, 3, -1, 10, 3, 9, 6, 3, +4, -4, 3, -11, -1, -13, 3, -5, +5, 2, 6, 8, 6, 11, -1, 6, +1, 4, -4, 0, 3, -7, 2, -7, +-1, -1, -3, 0, -2, 8, 1, 11, +0, 5, 4, 1, -2, -6, -6, -10, +-3, -9, -2, -5, 1, 4, -4, 12, +0, 7, -6, 7, -7, 3, -4, -9, +0, -12, 3, -9, -4, -3, -6, 5, +-4, 9, 1, 7, 7, 4, 4, -3, +2, -10, -2, -13, 3, -11, 3, 1, +1, 10, 1, 11, -2, 9, 1, 4, +2, -4, 7, -6, 3, -5, -3, -6, +0, 1, -2, 6, 5, 10, 4, 12, +3, 6, -2, -4, -3, -7, -1, -12, +1, -10, 6, 0, -1, 8, -5, 13, +-5, 11, -2, 1, 3, -8, 2, -12, +2, -12, -7, -3, -7, 2, -3, 5, +-1, 10, 1, 8, -2, 2, -3, -4, +-4, -12, 0, -14, 4, -7, 3, 0, +3, 10, -5, 13, 0, 6, 0, 1, +3, -3, 1, -11, 1, -11, 4, -7, +0, -1, 7, 9, 8, 8, 8, 2, +8, -2, 2, -9, 3, -12, 3, -10, +6, -2, -3, 7, -3, 13, -1, 9, +0, 7, 2, 0, 1, -9, 0, -12, +-1, -9, -1, -5, 0, 6, -2, 11, +0, 10, -3, 5, 1, -6, -1, -12, +-2, -12, -1, -11, -2, -1, -2, 10, +-7, 14, -4, 12, -2, 6, -1, -6, +4, -9, -1, -11, -1, -8, -3, -1, +2, 7, 1, 11, 1, 14, 2, 3, +0, -6, 2, -8, 0, -11, 4, -7, +5, 0, 4, 7, 1, 13, -2, 12, +4, 2, 1, -5, 4, -14, 5, -18, +3, -7, 1, 0, 3, 7, 3, 13, +-1, 10, 0, 0, 0, -7, 0, -17, +5, -16, 1, -7, 1, 1, -4, 11, +-4, 14, -5, 7, -1, -1, 1, -7, +-2, -13, 0, -11, -2, -5, -2, 3, +1, 12, 2, 8, 5, 5, -2, -1, +0, -9, -2, -15, 4, -8, 3, -4, +1, 5, 3, 9, 3, 8, 7, 5, +6, -4, 7, -12, 4, -14, -2, -7, +-1, 1, -4, 14, -2, 17, -2, 11, +3, 2, 4, -9, 3, -11, 3, -11, +0, -8, 1, -3, 2, 6, -1, 10, +-2, 15, -3, 5, 0, -6, -4, -11, +-2, -12, -6, -7, -5, 4, -1, 10, +-1, 10, 0, 13, -4, 4, -6, -2, +-6, -6, -3, -11, 0, -7, -3, 1, +1, 9, -3, 13, 1, 11, 5, -3, +6, -8, 0, -12, -2, -11, 2, -4, +2, 5, 4, 11, 2, 14, -1, 8, +0, 2, -2, -4, 3, -15, 3, -13, +4, -6, -1, 3, 0, 14, 3, 14, +2, 7, 2, -2, 0, -10, -1, -17, +0, -9, -1, -2, -2, 9, -7, 13, +-2, 13, -4, 5, 0, -3, 3, -15, +4, -18, 0, -10, -3, -3, -1, 8, +-1, 12, 2, 10, 1, 5, -3, -5, +0, -14, 0, -15, 3, -10, 2, -2, +2, 12, -2, 13, -1, 14, 2, 6, +2, -6, 5, -14, 2, -11, -1, -11, +2, 0, 2, 12, 3, 13, 0, 12, +3, 3, -2, -7, -1, -10, 1, -10, +2, -9, 3, 2, 0, 9, 1, 11, +0, 11, 1, 1, -1, -5, -8, -11, +-4, -11, -5, -6, -1, 7, -1, 11, +0, 16, -5, 11, -6, 3, -4, -4, +-7, -10, -3, -10, -3, -3, -4, 6, +-2, 11, 1, 14, 3, 4, 2, -3, +3, -9, -3, -13, -2, -9, 3, -3, +2, 8, 0, 15, 0, 16, 1, 3, +2, -3, 3, -14, 4, -15, 0, -11, +5, -3, 2, 6, 3, 14, 3, 12, +4, 4, 2, -4, -1, -13, 0, -13, +-3, -9, 1, -2, 2, 8, 1, 11, +1, 10, -1, 4, 0, -8, 1, -19, +5, -14, -3, -8, -4, 5, -2, 12, +-2, 14, -1, 10, -1, 3, -1, -10, +-1, -15, -1, -11, -2, -6, -5, 7, +1, 14, -1, 16, 0, 13, -1, 3, +-1, -9, 0, -15, 2, -13, 5, -9, +3, 4, 3, 11, -1, 19, -5, 13, +1, 2, 1, -10, 2, -14, -1, -14, +3, -4, 2, 6, 3, 13, 4, 15, +-2, 5, 0, -6, 1, -14, 3, -19, +5, -16, 4, -4, 1, 6, -4, 13, +1, 16, 0, 4, 1, -3, -1, -12, +-5, -15, -6, -11, -1, 1, 1, 9, +-2, 19, -4, 16, -6, 7, -8, -3, +2, -16, 5, -16, 4, -8, -2, 3, +-4, 13, -4, 18, 0, 13, 6, 4, +0, -6, -2, -16, -2, -15, 2, -12, +9, 0, 10, 10, 6, 15, -2, 6, +3, 0, 3, -11, 4, -15, 6, -13, +-1, -6, -7, 5, -3, 13, 2, 15, +4, 7, 7, -4, 3, -15, -9, -12, +-5, -10, 1, -6, 5, 8, 1, 13, +-5, 17, -11, 12, -8, 2, 1, -12, +0, -11, -4, -12, -4, -3, -6, 9, +0, 15, 5, 14, 8, 5, 0, -7, +-1, -14, -5, -14, 0, -11, 6, 2, +3, 10, -3, 16, -6, 18, -4, 6, +2, -4, 6, -12, 5, -15, -3, -13, +0, 3, -1, 10, 3, 20, 4, 14, +0, 5, -8, -5, -8, -14, 2, -18, +6, -9, 5, 3, 1, 12, -8, 20, +-7, 14, -1, 2, 6, -12, 5, -21, +2, -17, -7, -5, -8, 8, 0, 13, +4, 14, 5, 3, 1, 0, -5, -13, +0, -18, 5, -15, 6, -5, 2, 1, +4, 13, -3, 16, -3, 10, 2, 1, +1, -10, -2, -16, 0, -15, 3, -6, +1, 9, 5, 16, 7, 13, 1, 7, +0, -2, -3, -12, -3, -11, 1, -12, +4, 0, -1, 9, -2, 15, 2, 11, +0, 6, 4, -9, 5, -16, -1, -14, +-2, -14, 2, -2, 3, 11, -2, 17, +0, 15, -3, 4, -4, -11, 0, -17, +1, -18, 2, -12, 3, 5, 0, 11, +-3, 16, 0, 9, 3, 1, 1, -12, +5, -14, 0, -16, -4, -5, -3, 4, +3, 10, 5, 15, 5, 10, 2, 1, +-6, -6, -7, -12, 1, -14, 6, -5, +7, 5, 2, 12, -1, 17, -5, 8, +3, -1, 6, -14, 3, -16, -1, -13, +-7, 1, -4, 6, 4, 17, 7, 14, +3, 5, -3, -4, -5, -13, -6, -17, +4, -10, 5, -1, -2, 10, -7, 18, +-7, 12, -1, 2, 9, -9, 10, -18, +-1, -15, -7, -10, -4, 1, -2, 13, +5, 19, 6, 10, -1, 5, -10, -8, +-4, -15, 2, -15, 9, -10, 9, 1, +-2, 13, -7, 14, 1, 10, 7, 4, +8, -10, 4, -15, -4, -14, -10, -8, +1, 6, 8, 13, 8, 15, 2, 10, +-6, -1, -5, -18, 7, -18, 13, -16, +4, 0, -7, 10, -9, 15, -8, 14, +2, 12, 6, -3, 4, -13, -6, -16, +-8, -15, -4, -4, 6, 6, 12, 12, +4, 13, -5, 7, -10, 0, -9, -7, +2, -14, 7, -14, 3, 2, -10, 8, +-7, 19, -3, 18, 3, 8, 6, -5, +-1, -9, -12, -13, -7, -8, 7, -2, +12, 7, 8, 15, 3, 9, -6, 0, +0, -9, 7, -18, 10, -17, 4, -7, +-3, 4, -7, 11, -2, 18, 5, 14, +1, 7, -3, -8, -4, -16, -6, -16, +-1, -5, 4, 2, 7, 13, -3, 15, +-6, 11, -7, 2, -3, -10, 4, -16, +4, -14, 0, -7, -3, 6, -5, 20, +-6, 18, 1, 8, 6, -3, -3, -14, +-3, -13, -3, -12, 0, -1, 3, 8, +5, 16, 0, 12, -2, 8, 1, -6, +4, -16, 5, -15, 5, -10, -3, 1, +-3, 12, -3, 16, -1, 18, -4, 11, +2, -6, 0, -15, -1, -16, 1, -12, +2, 2, 3, 10, 1, 19, -5, 15, +-7, 5, -5, -9, 1, -13, 2, -19, +6, -9, 0, 3, -5, 12, -6, 16, +2, 10, 4, -2, 4, -10, 2, -17, +-3, -18, -3, -5, 2, 6, 2, 13, +4, 15, -2, 10, -8, 2, -6, -9, +6, -15, 6, -12, 3, -1, -1, 3, +-4, 13, 0, 12, 7, 10, 3, 4, +-4, -5, -10, -12, -7, -10, 0, -5, +13, 4, 10, 13, 2, 11, -4, 3, +-4, -4, 1, -12, 4, -10, 3, -7, +-4, -2, -9, 8, -5, 18, -3, 12, +7, 6, 5, -8, -5, -12, -13, -11, +-6, -5, 2, 1, 7, 12, 3, 13, +-6, 8, -8, 1, 0, -9, 5, -11, +5, -10, 0, -8, -5, 3, -9, 10, +5, 11, 13, 8, 6, 6, -4, -6, +-11, -9, -8, -13, 4, -3, 9, 8, +3, 15, -4, 11, -5, 8, -4, -2, +6, -9, 12, -15, 7, -14, -6, -1, +-9, 9, -5, 14, 4, 15, 9, 6, +0, -3, -11, -8, -10, -10, -4, -10, +6, -1, 8, 4, 1, 11, -9, 10, +-3, 3, 4, -9, 8, -11, 4, -13, +-6, -6, -10, 0, -3, 6, 5, 11, +9, 8, 4, 3, -5, -1, -11, -11, +1, -18, 12, -11, 10, 0, 3, 8, +-1, 14, -4, 5, 4, -2, 11, -9, +6, -11, 0, -13, -1, -4, -4, 2, +0, 13, 6, 12, 8, 4, 2, -2, +0, -9, -3, -14, 2, -12, 7, -5, +2, 6, -7, 16, -7, 14, -5, 8, +-2, 1, 2, -11, 3, -12, -4, -10, +-4, -1, -4, 7, -2, 12, 2, 9, +1, 8, -4, -3, -4, -9, -3, -11, +-2, -8, 1, -2, 5, 7, -1, 12, +-4, 14, -5, 7, 0, -5, 3, -11, +7, -13, 4, -11, -2, 3, -2, 9, +-1, 13, 3, 10, 7, 1, 4, -9, +-2, -9, -2, -13, 5, -7, 5, 2, +6, 7, 3, 8, -2, 6, -1, -2, +5, -9, 6, -13, 6, -14, 0, -4, +-9, 6, -7, 10, 2, 13, 2, 8, +0, 3, -8, -3, -11, -8, -8, -8, +0, 3, 1, 5, 0, 9, -2, 8, +-7, 6, -6, 1, 3, -4, 3, -9, +-2, -5, -7, -1, -4, 3, -1, 12, +9, 9, 9, 2, 2, -4, -4, -12, +-2, -12, 4, -7, 10, 0, 7, 6, +-1, 10, -5, 5, 0, 6, 1, -1, +7, -7, 5, -12, -2, -9, -4, -4, +1, 9, 4, 11, 6, 8, 0, 4, +-9, -5, -9, -11, 1, -7, 4, -4, +3, 4, -4, 10, -9, 9, -8, 5, +2, 4, 3, -6, 2, -9, -2, -11, +-8, -3, -8, 5, 3, 11, 5, 10, +0, 9, -6, -1, -6, -7, -3, -10, +9, -10, 9, -3, 3, 5, -5, 7, +-6, 12, -2, 7, 8, -3, 9, -6, +-2, -5, -8, -9, -1, 0, 3, 6, +5, 13, 4, 8, 1, 1, -5, -6, +-2, -6, 5, -11, 7, -6, 3, 1, +-4, 5, -9, 9, -1, 9, 2, 3, +2, -1, -2, -7, -6, -9, -8, -5, +0, -1, 7, 2, 4, 10, -3, 7, +-6, 1, -6, -5, 0, -8, 4, -10, +4, -3, -2, 2, -5, 10, -4, 7, +2, 3, 7, -2, 8, -10, 3, -11, +-1, -6, -2, -3, 3, 1, 7, 8, +4, 9, -1, 4, -1, 2, -2, -6, +0, -5, 2, -4, 4, -2, 1, 2, +-1, 11, -5, 10, -3, 8, 1, -1, +1, -6, -3, -5, -5, -3, -4, 0, +-2, 6, 1, 6, 3, 6, -3, 4, +-4, -4, -3, -8, 0, -8, 1, -7, +1, 3, -2, 4, -3, 8, -6, 9, +-4, 3, 2, -8, 5, -4, -2, -6, +-5, -5, -1, 0, 3, 6, 1, 10, +0, 11, -3, 2, -4, -4, -1, -8, +6, -10, 8, -6, 9, 0, 4, 1, +0, 4, 3, 2, 6, 1, 4, -6, +7, -13, 6, -13, -1, 1, -3, 4, +4, 8, 1, 9, -2, 5, -4, -2, +-4, -5, 0, -10, 6, -5, 2, -1, +-3, 3, -7, 9, -5, 7, -1, 0, +5, -2, 2, -8, -4, -7, -5, -4, +-4, 1, 0, 3, 5, 8, 0, 6, +-8, 6, -10, 1, -2, -3, 0, -3, +3, -1, 1, -2, -2, 3, -1, 4, +4, 6, 3, 5, 4, -3, 2, -9, +-3, -6, -1, -5, 7, 2, 7, 9, +0, 8, -3, 3, -5, 2, -2, -5, +7, -5, 6, -5, 0, 1, -9, 5, +-8, 8, -2, 4, 5, 5, 7, -3, +-1, -7, -8, -3, -7, -2, -4, 1, +2, 7, -1, 7, -7, 8, -10, 5, +-5, -4, 3, -9, 9, -9, 7, -8, +-4, 2, -8, 2, 1, 3, 4, 3, +8, -1, 6, -8, 2, -7, -1, -10, +3, -5, 5, 1, 6, 3, 4, 4, +0, 4, -3, -2, 5, -4, 7, -5, +6, -6, 1, -2, -2, 2, -2, 2, +2, 8, 4, 3, 2, 0, 0, -3, +-1, -5, -5, -3, -2, 4, 2, 0, +1, 3, -2, 4, -2, 3, -3, 2, +-2, -1, -2, -7, 0, -5, -2, -3, +1, 0, -2, 5, -2, 5, 2, -2, +1, -2, 0, -7, 2, -6, 1, -3, +-2, 1, -1, -1, 3, 4, 2, 1, +4, -1, 5, -6, 3, -6, 2, -4, +2, -2, 1, -3, 5, 1, 5, 5, +0, 5, -2, 2, 5, -4, 2, -4, +-1, 2, -4, 1, -3, 4, -2, 5, +0, 6, -3, 5, -2, 5, 0, -4, +0, -2, -3, -5, 0, -3, 1, 1, +0, 2, 2, 0, -1, 3, -3, 1, +-3, 0, -6, -1, -2, -5, 1, -4, +2, 0, -1, 2, -1, 5, -1, 4, +-3, 1, -3, -3, 1, -3, -1, -4, +1, 1, -1, -2, 4, -1, 6, 1, +5, 3, 0, -1, -2, -2, 3, -6, +2, -3, 1, 4, 3, 2, 2, 2, +2, 3, -2, 0, 2, -3, 7, -5, +6, -6, 1, -5, 1, -2, 0, 2, +0, 10, -2, 2, 4, -2, 0, -4, +-1, -4, -4, -3, -2, 2, 1, 0, +-1, 5, -6, 7, -8, 4, -5, 2, +1, 0, -2, -2, -4, 1, -4, 0, +-4, 0, -1, 1, 3, 0, 7, -2, +2, 2, -5, 0, -7, 0, -3, -3, +8, -3, 5, -2, 4, 2, 2, 0, +0, 2, 1, 0, 3, -3, 4, -3, +5, -6, 0, -3, -1, 6, -1, 4, +6, 0, 6, -2, 1, -4, 1, -5, +3, -3, 4, -5, 1, 1, 0, 2, +-1, 4, -6, 6, -5, 8, -6, 1, +-4, 3, -7, 0, -6, 0, -2, 1, +3, 2, -2, 3, -4, 4, -4, 1, +0, -2, -2, -1, -1, -2, -3, 0, +-2, 2, 0, 0, -1, 3, 2, 1, +4, -2, 1, -2, -3, 1, -3, -3, +5, -1, 4, -1, 1, 5, -2, 6, +-1, 1, 2, -5, 5, -5, 6, -6, +7, -3, 1, -1, 1, 0, -4, 6, +1, 7, 0, 3, -3, 3, -3, -2, +-2, -5, 1, -3, 1, 1, 1, 0, +3, 1, 1, -4, -2, 1, -5, 4, +-2, 2, -2, -1, -3, -3, 0, -4, +0, 2, -1, 3, 2, -1, 0, -2, +3, -2, -5, 0, -6, 4, -4, 1, +1, 1, 2, 1, 1, 0, 1, 0, +1, 5, -1, -4, 2, -4, 2, -2, +1, 2, -1, 2, -1, 3, 2, 1, +0, 3, 4, -1, 2, -4, -1, 0, +2, 0, -2, 1, -2, 5, -1, 0, +4, 0, 1, 1, -1, -3, 1, -4, +0, 3, -5, 1, -5, 4, -4, 1, +4, 1, 0, 0, 0, -2, 1, -5, +0, -1, 2, -3, -2, -2, -3, 2, +-1, 0, -1, 0, 2, 2, 0, -2, +4, -3, 1, -4, 0, -5, 2, -4, +5, 3, 1, 3, -3, 5, -5, 2, +2, 0, 0, -1, 3, -1, 0, -4, +2, 0, 3, -1, 1, 1, 2, 3, +3, -1, 5, -4, 2, -1, -4, 1, +-1, 0, 2, -3, 4, -4, 1, 2, +0, 3, 2, -1, -1, 0, -2, -3, +0, 1, -6, 5, -3, 4, -7, 0, +2, 1, 3, -4, 0, 1, -4, 2, +0, -5, 3, -4, -3, 2, -4, 0, +1, 3, -1, 5, -3, 3, -4, 1, +1, -1, 2, -2, -4, 2, -1, -3, +2, 0, 2, 5, -2, 6, -5, 1, +2, 1, 2, -5, 5, -3, 3, -4, +5, -3, 2, 1, -1, 2, 0, -2, +5, 3, 0, 3, -3, 0, -7, 1, +-1, -1, 2, -1, 1, 3, 2, -2, +-1, 0, 1, 3, -4, 2, -4, -2, +2, -2, 2, -5, -2, 4, -10, 8, +-6, 7, -3, 3, 0, 0, -1, -4, +0, 0, 1, -2, 1, -2, -3, 0, +2, 2, -2, 4, 0, 4, -3, -1, +-2, 1, 2, -1, -1, -3, 3, -3, +2, 1, 4, -2, 2, 2, 0, 1, +1, 0, 4, -4, 6, -7, 3, -6, +1, 2, 2, 1, -1, 4, -5, 4, +1, -1, 2, -3, 6, -2, -1, -5, +1, -2, 0, 1, -1, 2, -1, 1, +1, 0, 3, -4, -1, 1, -5, -1, +-2, 1, 1, -1, 2, -3, -1, -1, +-5, 7, -2, 5, -2, 3, -1, 0, +-2, -2, -3, 0, 0, 2, -5, -1, +4, 2, 0, 2, 1, 1, -3, 2, +-2, 1, 3, -4, 4, -1, 0, -3, +2, 0, 1, 3, 1, 3, -2, -3, +3, -1, 6, -4, 0, 0, 1, -3, +0, -6, 6, -1, 3, 1, 2, -2, +3, 1, -1, -1, 2, -3, -4, 1, +-2, 0, 2, -4, 5, -2, 1, -4, +-1, 2, 0, 0, 6, -5, 0, -4, +0, 2, -4, 0, -3, 6, -4, 4, +-6, 0, 4, 0, 1, 1, -2, 2, +-6, 4, -3, -2, 3, -4, 1, -1, +2, 2, 1, 4, 0, 3, 0, -5, +0, -3, 4, -2, 7, -3, 0, -2, +2, -1, -2, -2, 4, 5, -3, 2, +2, -1, 3, -1, 0, -1, -2, -2, +-3, 2, 2, -1, 5, -1, 2, -1, +-1, -1, -1, 0, 0, 0, 0, -3, +-4, 2, -1, 4, -3, 3, -4, 2, +-1, 0, 0, -3, 7, 0, 0, -4, +1, -2, -3, -2, 3, -4, 2, -2, +1, 3, 2, 1, 1, 1, -3, -1, +-1, -2, -1, 2, 2, 4, -1, -1, +-3, 1, 1, 2, -2, 4, 0, 2, +-1, -3, 5, -8, 7, -3, 2, -5, +2, 1, -2, 2, 4, 1, -1, 0, +1, -1, 4, -6, 5, -3, 0, -3, +-2, -2, -2, 3, 4, 3, -2, -1, +0, -1, -1, -1, -1, 1, 1, 1, +-2, -2, 4, -4, 0, 1, -1, -1, +-1, 0, 2, -1, 7, -4, 3, -6, +-1, 0, -3, -2, 2, -1, 6, -4, +5, -4, 3, 0, 4, 2, -4, -2, +1, -1, -1, -3, 6, 0, 1, 2, +-3, 0, 0, -3, 3, -1, 5, -1, +-2, 5, -1, 1, 1, -2, -3, -1, +-4, 4, -2, 1, 4, 3, 5, -1, +-6, 0, -6, 3, -3, 2, -2, 2, +1, 1, -1, -5, 7, -2, -4, 4, +-5, 6, -6, 3, 2, 1, 1, -2, +-7, 4, -6, 3, -2, 1, 1, -1, +3, -2, 3, -4, 4, 2, 0, -1, +-5, -1, 0, -1, 3, -1, 5, 1, +-2, 4, -3, -3, 3, -1, 0, -1, +3, -1, -1, 1, 2, 1, 0, -5, +1, -2, 3, -4, 8, -2, 6, -2, +4, -5, 0, -6, 3, 1, -2, 1, +-4, 4, -2, 1, 3, -4, 6, -1, +-4, 1, -1, -4, 2, -2, 6, -3, +4, -3, -2, 0, 3, -2, 0, -4, +1, 0, 3, -4, 7, -4, 4, -1, +-3, -3, -5, -3, 5, 2, 3, 0, +3, 4, -6, 2, -2, -1, -1, 1, +-3, 2, 3, -2, 2, -1, 4, 0, +-5, 2, -7, 5, 1, 0, 5, -3, +2, 2, -3, -1, -1, 0, 2, 0, +0, -2, 0, -1, 4, 2, 1, -1, +0, 3, -9, 0, 1, -2, 0, 1, +2, 3, -3, 3, -4, 5, -2, -1, +-2, -2, 0, 1, 2, 1, 2, -2, +2, -3, -2, -4, -3, 3, 2, 3, +-1, 2, -2, 4, -5, 2, 1, -2, +-3, 3, -4, -1, 6, -2, 3, -1, +5, 1, -8, 3, -7, 7, -3, -1, +2, -1, 3, -1, 3, 0, 0, 0, +-3, 2, -5, -2, 4, 1, 7, 1, +1, -2, -1, -3, -4, -4, 6, -4, +3, 2, 4, -1, 1, 0, -4, 2, +-4, 1, -6, 0, 4, 2, 7, -4, +3, -1, -6, 2, -5, 1, 0, -1, +6, 0, -2, 0, -1, 3, -4, 1, +0, -2, -2, 0, 1, 1, 4, 1, +-2, 5, -4, 2, -7, 2, -1, 2, +-1, 2, -2, 2, 1, 2, 2, -4, +1, 0, -4, -1, 2, -4, 9, -1, +2, 4, -5, -1, -1, 1, -2, 0, +4, 1, -4, 3, 0, 2, -2, 0, +-2, 4, -4, -1, -2, -2, 8, -3, +5, -3, 1, -1, 0, 2, -1, 0, +-5, 6, -7, 4, -3, 2, 4, 2, +1, -1, -1, -5, -2, -2, 3, -2, +5, 3, -3, 4, 2, -3, -3, -1, +-1, 4, -4, -1, 6, 0, 7, -1, +1, -1, -7, 1, -5, 1, 3, -4, +11, -1, 5, -4, 2, -2, -1, 2, +-5, 3, 1, -3, 3, -2, 11, -5, +3, 0, -4, 2, -4, 0, 0, -2, +9, 0, 1, -2, 1, 2, -3, 0, +-3, 0, -1, -1, 4, 2, 3, 2, +2, 4, -6, -3, -2, -3, -1, 2, +3, 4, 0, 3, -4, 2, 2, -4, +-2, 2, -1, 4, -1, -1, 7, -2, +4, 0, -4, -1, -4, 4, -2, 4, +1, 3, 0, 2, 1, -1, 1, -1, +-1, 5, -7, 2, -1, 2, 0, 2, +8, 0, 0, 2, -4, 4, -4, 0, +0, 2, 2, 4, -3, 2, 2, 0, +1, -3, 1, -5, 4, -1, 7, -1, +8, -2, 4, -4, -2, -3, -1, -1, +2, 3, 4, -1, 4, 0, 2, -2, +4, -1, -5, 1, 0, 3, -1, -2, +8, 0, 2, -1, 0, -1, 1, 2, +1, 1, 4, -2, 3, 2, 0, 1, +1, -1, -1, -1, -1, -1, 4, 1, +5, 3, 7, -2, -1, 0, 0, -2, +2, -2, 2, 2, 3, 2, 1, 0, +3, 4, -3, 0, 0, 1, 0, 3, +6, -3, 5, -4, 2, 1, -3, 0, +4, 1, 2, 0, 4, 0, 3, 0, +5, 1, 2, -1, -7, 3, -1, 1, +-1, 1, 7, 2, 2, 5, -3, 4, +-3, 5, -4, 0, 1, 0, 6, -1, +10, -3, 3, -1, -3, 3, -4, 2, +6, 3, 7, 0, 8, -4, 0, -4, +4, -3, 0, -2, 4, 3, 9, -1, +7, 0, 5, 1, -4, 0, 0, -2, +5, 0, 9, -4, 5, 1, -1, 4, +-2, 2, 1, 0, 5, -1, 9, -2, +6, 4, -2, 3, -4, -1, -4, -2, +10, 0, 7, 1, 7, 5, -1, 0, +-1, 0, -2, 2, -1, 1, 7, -2, +10, 0, 4, -2, 1, 0, 1, 2, +5, 1, 11, -3, 7, -4, 5, -5, +1, 0, 3, 4, 0, 3, 5, 2, +10, -2, 7, -4, 7, -2, 1, -5, +10, -5, 8, -5, 12, -5, 8, -2, +7, 2, 5, -4, 6, -3, 6, -4, +10, -3, 8, -3, 6, -4, 5, -3, +3, 3, 7, 3, 5, 0, 10, -4, +7, -4, 3, 0, -1, 3, -1, 2, +7, 2, 8, -2, 11, -3, 3, 1, +2, 4, 2, -1, 5, 0, 3, 0, +7, 1, 3, 3, 3, 3, -1, 3, +6, 2, 10, -1, 6, 0, 1, 1, +1, -3, 7, -2, 8, 3, 8, 3, +7, 5, 3, 1, 2, -2, 1, -1, +7, -1, 12, -5, 11, -2, 5, -1, +3, 3, 3, 5, 6, 3, 3, 0, +7, 2, 1, -1, 4, 0, 3, 0, +10, -2, 13, 0, 7, 4, 3, 1, +3, 0, 6, -3, 5, -3, 7, 1, +7, 4, 7, 4, 2, 5, 3, -1, +5, -1, 9, 0, 10, -3, 8, -7, +12, -4, 7, -4, 10, 2, 8, 1, +14, -1, 11, -3, 9, -4, 3, -2, +4, 2, 8, 1, 11, 1, 9, 1, +7, 2, 4, 2, 3, 2, 7, -5, +11, -4, 14, -1, 3, 4, 0, 5, +2, 5, 6, 3, 11, 4, 6, 0, +6, -1, 3, -4, 8, -3, 9, -1, +13, 4, 12, 3, 6, 3, -1, 4, +2, 2, 6, -1, 16, -3, 11, -5, +8, -1, 7, 0, 10, -2, 14, -1, +13, -1, 12, -5, 8, -3, 5, 0, +5, 1, 12, 1, 14, 1, 10, 0, +9, 2, 8, 2, 6, 0, 8, -3, +13, -5, 10, 0, 12, 2, 6, 0, +11, 1, 10, 0, 12, -1, 6, 2, +5, 0, 9, -4, 7, 3, 6, 5, +5, 5, 11, 2, 12, 0, 7, 0, +4, 1, 11, -3, 11, -2, 11, 1, +10, 2, 10, 2, 13, 2, 8, -1, +10, 1, 7, -2, 13, -2, 7, 0, +8, 3, 9, 0, 11, 2, 12, 1, +10, 3, 10, 2, 7, 0, 6, -3, +11, -2, 16, -1, 15, 3, 12, 4, +7, 3, 7, 2, 9, 0, 12, -2, +11, 1, 9, 1, 10, 1, 7, 3, +10, 4, 12, -1, 16, -3, 13, -7, +13, -6, 12, -6, 16, -3, 13, -1, +15, 4, 9, 7, 8, 6, 7, -1, +12, -4, 13, 0, 9, 5, 10, 6, +5, 5, 12, -2, 16, -4, 17, -3, +17, -2, 13, -1, 11, -2, 8, -4, +10, 4, 8, 5, 16, 3, 15, 0, +14, 0, 7, -1, 11, 3, 8, 1, +14, 1, 13, 4, 10, 4, 12, 2, +11, 3, 15, -1, 15, -2, 16, -2, +9, -1, 10, 0, 12, -1, 15, -3, +18, 0, 15, 1, 15, -1, 11, -3, +11, -3, 10, -2, 16, 2, 15, 2, +15, 4, 11, 4, 12, 1, 13, -1, +18, -3, 18, -5, 18, 0, 10, 4, +6, 4, 11, 2, 21, 0, 18, -2, +15, 0, 13, -4, 12, -4, 15, -3, +15, -2, 19, 1, 14, 9, 9, 8, +6, 6, 9, 1, 17, -2, 17, -3, +19, 1, 12, 3, 13, 5, 11, 3, +16, 0, 19, -1, 21, -2, 13, -4, +11, -2, 11, -1, 13, 2, 17, 5, +12, 4, 14, 1, 12, 2, 14, -1, +11, 0, 18, -2, 19, -1, 14, 2, +17, 3, 16, 2, 18, 4, 15, 1, +16, -1, 13, 1, 17, 0, 13, 0, +13, 4, 12, 6, 13, 4, 18, -1, +20, -3, 15, -3, 13, -2, 17, -6, +19, -2, 23, -1, 24, -1, 19, -1, +19, 1, 15, 1, 17, 2, 19, -1, +17, 1, 13, 4, 13, 4, 15, 2, +18, 1, 21, -2, 20, -4, 17, -6, +19, -6, 15, -6, 22, -3, 21, -1, +19, 6, 14, 4, 17, -1, 16, -3, +19, -2, 20, 0, 16, 7, 14, 7, +12, 7, 14, 6, 14, 7, 17, 5, +16, 1, 20, -5, 18, -4, 15, -2, +20, -1, 18, 1, 23, 1, 19, -2, +22, -2, 15, -4, 19, -3, 21, -6, +27, -4, 24, 2, 17, 8, 16, 5, +16, 4, 19, 1, 20, -1, 24, -2, +19, -4, 19, -4, 19, -1, 21, 1, +24, 1, 19, 0, 21, -7, 20, -9, +21, -4, 17, -3, 24, -1, 23, 1, +17, 4, 16, 4, 18, 3, 22, 0, +23, 2, 16, 0, 19, 0, 21, 3, +21, 5, 19, 3, 23, 3, 19, -1, +19, -2, 19, -1, 19, -5, 25, -8, +24, -4, 19, 0, 20, 2, 26, 2, +20, 0, 20, -3, 21, -1, 17, 1, +22, 2, 23, 0, 28, 2, 21, 4, +20, 5, 13, 4, 21, 4, 21, -1, +19, -1, 17, 2, 15, 0, 23, -2, +23, 1, 22, 2, 18, 1, 19, -1, +12, -1, 18, -3, 28, -2, 26, 2, +22, 9, 15, 6, 21, 2, 23, 0, +28, -1, 23, -3, 28, -1, 21, -1, +21, -2, 28, -1, 27, 0, 24, -1, +22, -5, 22, -6, 20, -2, 21, 1, +19, 2, 19, 1, 27, 1, 22, 2, +22, 4, 22, 1, 24, -2, 24, -4, +26, 0, 24, 4, 23, 8, 22, 5, +19, 3, 24, -2, 28, -7, 27, -8, +28, -8, 25, -6, 24, -3, 22, -3, +29, -3, 24, -2, 29, -3, 23, -6, +24, -2, 24, 0, 21, 4, 23, 6, +22, 9, 25, 5, 24, 2, 27, -1, +24, -3, 29, -6, 31, -5, 26, -3, +27, 0, 21, 2, 22, -1, 25, -4, +32, -3, 22, -4, 25, -5, 19, -2, +22, 0, 28, 2, 26, 8, 23, 5, +25, 0, 28, 0, 19, 2, 28, -1, +31, 0, 25, 4, 21, 7, 18, 4, +25, 2, 25, 0, 26, -4, 24, -7, +26, -4, 18, -1, 20, -1, 27, 1, +27, 2, 26, -1, 26, -1, 24, 0, +26, 1, 27, 0, 25, 4, 24, 5, +28, 6, 23, 5, 28, 6, 26, 1, +27, -1, 23, -4, 23, -3, 28, -4, +31, -2, 29, -3, 23, -5, 31, -5, +28, -4, 29, -5, 31, -4, 25, -2, +24, 2, 20, 5, 29, 5, 34, 2, +38, 4, 19, 2, 22, -1, 27, -1, +29, 3, 27, 3, 27, 2, 22, 1, +19, 2, 24, 0, 25, -4, 36, -8, +28, -8, 20, -5, 24, -1, 27, 2, +33, 4, 28, 5, 27, 4, 21, 2, +28, 2, 23, 2, 31, 3, 33, 3, +27, 4, 24, 4, 29, 1, 32, -3, +29, -2, 27, -4, 24, -5, 26, -2, +26, -3, 26, -2, 32, 1, 27, 1, +26, -2, 28, -5, 35, -5, 29, -1, +29, 3, 27, 5, 26, 10, 30, 9, +24, 9, 24, 5, 26, 1, 25, -5, +29, -6, 33, -6, 34, -3, 28, -3, +30, -4, 25, -6, 34, -7, 32, -6, +27, -3, 26, -2, 27, 1, 24, 6, +25, 9, 31, 10, 26, 7, 31, 1, +28, -2, 29, -1, 33, 0, 31, 0, +32, 4, 29, 3, 31, 0, 23, -4, +31, -6, 28, -6, 31, -4, 27, -2, +24, 0, 25, 0, 29, 1, 30, 3, +31, 3, 36, 3, 23, 3, 22, 1, +28, 2, 32, 5, 37, 7, 33, 3, +30, 2, 25, -1, 28, -3, 27, -6, +38, -5, 30, -1, 20, 1, 21, 0, +27, -2, 36, -3, 34, -2, 27, -1, +24, -2, 28, -1, 29, 2, 31, 3, +41, 5, 32, 6, 30, 4, 30, 2, +32, 2, 30, -1, 31, -2, 27, 0, +29, 4, 30, 3, 25, 0, 31, -5, +31, -8, 31, -10, 32, -9, 35, -6, +34, 0, 26, 6, 24, 9, 22, 8, +37, 9, 28, 9, 25, 5, 24, 3, +25, 5, 26, 5, 34, 6, 37, 4, +31, 2, 26, -1, 16, -2, 27, -4, +36, -5, 34, -6, 27, -2, 22, 2, +23, 3, 28, 2, 40, 0, 34, -2, +35, -1, 20, 3, 22, 7, 32, 11, +37, 11, 34, 6, 29, 5, 27, 5, +23, 1, 32, -3, 34, -6, 34, -5, +33, -2, 23, -2, 32, -4, 38, -8, +39, -9, 31, -7, 33, -6, 32, -3, +32, 0, 32, 5, 30, 8, 32, 11, +32, 8, 30, 2, 32, 0, 33, -1, +27, 1, 29, 1, 37, 2, 32, 1, +33, 0, 23, -4, 29, -7, 33, -11, +37, -9, 30, -5, 30, 2, 27, 3, +23, 4, 36, 2, 38, 0, 40, 1, +30, 4, 24, 4, 28, 4, 35, 4, +36, 7, 33, 9, 34, 6, 25, -4, +33, -10, 34, -12, 39, -8, 35, -6, +33, -5, 30, -4, 32, -3, 35, -3, +30, -2, 39, -2, 34, -2, 29, 0, +26, 6, 27, 9, 35, 8, 40, 4, +40, 3, 31, 2, 32, -1, 24, -4, +31, -3, 39, -3, 36, 0, 28, -1, +26, -3, 29, -6, 34, -7, 37, -7, +30, -3, 30, -3, 28, 1, 23, 6, +35, 8, 39, 9, 36, 8, 25, 4, +29, 2, 29, 2, 37, 3, 35, 3, +31, 5, 33, 5, 26, 1, 32, -6, +39, -11, 41, -16, 35, -14, 32, -9, +32, -1, 33, 3, 35, 4, 25, 2, +32, 2, 31, 3, 32, 4, 29, 5, +33, 7, 26, 9, 25, 12, 32, 8, +37, 3, 44, -3, 28, -5, 24, -7, +28, -6, 36, -4, 35, -3, 33, -2, +31, -1, 22, -4, 33, -5, 33, -6, +44, -5, 37, -2, 24, 4, 23, 8, +35, 10, 39, 10, 37, 7, 35, 3, +28, -3, 32, -7, 36, -4, 38, 1, +39, 2, 32, -1, 26, -4, 29, -6, +40, -8, 34, -10, 37, -10, 30, -6, +29, -1, 32, 3, 33, 7, 36, 7, +33, 8, 27, 5, 25, 2, 36, 3, +35, 5, 30, 5, 32, 6, 28, 6, +34, 3, 32, -2, 31, -6, 29, -10, +34, -11, 28, -9, 35, -4, 39, -2, +31, 0, 30, 0, 29, -1, 34, 0, +34, -1, 36, -1, 32, 4, 32, 11, +29, 15, 24, 12, 39, 6, 33, 3, +30, 2, 23, -1, 30, -4, 32, -4, +34, -1, 30, -1, 33, -3, 37, -5, +27, -6, 30, -9, 36, -9, 39, -8, +38, -3, 37, 4, 32, 9, 30, 9, +34, 7, 29, 6, 37, 5, 29, 1, +27, -1, 29, 0, 34, 3, 34, 2, +34, -1, 33, -4, 25, -5, 27, -9, +29, -12, 37, -9, 41, 0, 27, 5, +23, 6, 26, 6, 34, 4, 34, 0, +38, 1, 32, 1, 33, 3, 32, 6, +31, 8, 38, 8, 35, 8, 24, 4, +22, -5, 35, -10, 34, -10, 35, -8, +34, -7, 31, -3, 39, -4, 33, -6, +35, -2, 29, -2, 32, -2, 26, -1, +35, 4, 38, 9, 30, 15, 23, 16, +20, 10, 35, 2, 40, -3, 33, -3, +26, -4, 29, -5, 28, -2, 31, 0, +39, -2, 35, -6, 32, -8, 18, -6, +25, -2, 34, -1, 39, 3, 27, 6, +26, 6, 29, 6, 28, 4, 39, 3, +39, 2, 34, 3, 26, 4, 22, 6, +31, 7, 38, 5, 37, 0, 27, -4, +29, -7, 26, -10, 29, -8, 33, -7, +36, -2, 31, 3, 25, 6, 24, 3, +32, 0, 36, 0, 27, 0, 33, -1, +35, 4, 31, 8, 32, 8, 32, 5, +37, 4, 32, 2, 31, -3, 27, -7, +31, -6, 23, -5, 24, -5, 36, -4, +36, -2, 32, -2, 25, -4, 27, -7, +33, -6, 38, 0, 32, 7, 29, 10, +28, 10, 20, 9, 29, 7, 38, 0, +42, 0, 28, 1, 25, 0, 24, -1, +34, 2, 34, 3, 30, 0, 35, -7, +27, -10, 25, -10, 29, -7, 34, -1, +31, 1, 28, 5, 26, 7, 26, 3, +34, 3, 27, 2, 33, 0, 36, 2, +29, 6, 23, 8, 30, 8, 31, 6, +31, 4, 31, -1, 28, -7, 29, -10, +23, -9, 21, -5, 30, -1, 34, -2, +33, -4, 29, -5, 31, -2, 27, -2, +36, -1, 33, 2, 33, 7, 28, 12, +17, 15, 23, 12, 35, 6, 39, -2, +32, -8, 30, -8, 26, -6, 28, -5, +32, -4, 34, -6, 39, -6, 31, -5, +25, -5, 28, -8, 40, -6, 29, -2, +28, 1, 29, 1, 32, 4, 31, 7, +25, 6, 27, 4, 29, 4, 29, 3, +25, 3, 32, 3, 31, 4, 24, 2, +28, -2, 30, -7, 35, -8, 25, -8, +19, -7, 22, -4, 31, 2, 27, 5, +27, 5, 27, 2, 23, 1, 22, 1, +30, 1, 40, -1, 39, 5, 26, 11, +17, 13, 26, 9, 38, 4, 32, -1, +31, -9, 24, -14, 22, -12, 23, -8, +32, -4, 35, -1, 31, 1, 22, 1, +22, 0, 35, -4, 37, -6, 34, -5, +31, -1, 22, 7, 21, 12, 22, 13, +27, 9, 29, 3, 28, 0, 21, -2, +32, -5, 34, -4, 28, 0, 23, -3, +27, -5, 28, -7, 28, -9, 33, -9, +26, -3, 26, 1, 22, 3, 25, 3, +33, 2, 26, 1, 23, 2, 20, 2, +29, 3, 30, 4, 33, 8, 26, 11, +27, 9, 29, 3, 30, -3, 33, -9, +32, -11, 20, -11, 14, -10, 24, -10, +29, -4, 29, 3, 25, 6, 24, 4, +30, 3, 27, -1, 31, -3, 30, 0, +26, 6, 18, 6, 24, 8, 28, 10, +26, 8, 25, 2, 21, -1, 24, -5, +28, -7, 23, -7, 23, -6, 26, -5, +27, -3, 25, -4, 32, -4, 29, -4, +29, -4, 24, -2, 26, 4, 27, 7, +25, 8, 18, 2, 18, 2, 24, 2, +25, 0, 32, 1, 30, 4, 30, 4, +27, 5, 22, 4, 28, -1, 30, -7, +26, -10, 14, -8, 18, -7, 20, -4, +23, -1, 22, 1, 24, 3, 27, 1, +30, 0, 30, 1, 30, 3, 29, 4, +19, 7, 20, 7, 25, 7, 26, 5, +22, 2, 20, -4, 26, -10, 27, -10, +26, -7, 18, -5, 23, -3, 20, 0, +18, 3, 26, -2, 34, -6, 30, -5, +23, -4, 24, -3, 29, 5, 28, 12, +22, 13, 16, 11, 15, 7, 12, 1, +17, -2, 25, -4, 29, -6, 27, -6, +28, -3, 28, 0, 33, 2, 31, 0, +23, -3, 20, -5, 16, -6, 14, -6, +17, -4, 20, -2, 20, 3, 16, 5, +24, 6, 28, 7, 32, 13, 19, 15, +16, 14, 17, 8, 16, 4, 15, -3, +16, -5, 18, -5, 18, -4, 23, -4, +24, -2, 24, 0, 18, 1, 15, 2, +19, 1, 26, -4, 27, -7, 19, -6, +19, -2, 21, 3, 32, 8, 30, 15, +27, 18, 18, 14, 8, 6, 9, -5, +18, -14, 25, -18, 20, -15, 16, -5, +17, 6, 24, 11, 32, 14, 27, 14, +22, 8, 18, -4, 14, -8, 12, -10, +21, -12, 21, -9, 14, 1, 10, 8, +18, 9, 27, 10, 29, 12, 25, 10, +26, 2, 25, -6, 22, -13, 24, -17, +24, -12, 16, -6, 17, -1, 19, 1, +25, 3, 22, 2, 16, 1, 17, -4, +24, -8, 27, -12, 26, -11, 24, -4, +17, 4, 17, 9, 23, 15, 26, 15, +27, 12, 18, 6, 12, -2, 14, -10, +19, -14, 15, -18, 16, -15, 14, -10, +20, 0, 25, 8, 31, 13, 33, 9, +25, 7, 14, 1, 9, -4, 20, -8, +20, -4, 13, 2, 9, 4, 10, 3, +14, 4, 15, 4, 22, 2, 24, -1, +25, -2, 20, -3, 22, -3, 22, -3, +19, -2, 14, -1, 17, 2, 17, 0, +18, -3, 19, -6, 17, -5, 18, -3, +15, 0, 14, 1, 18, 5, 13, 10, +11, 12, 16, 7, 29, 0, 31, -4, +24, -2, 13, 0, 11, 2, 13, -1, +13, -4, 13, -9, 12, -6, 6, -2, +8, 1, 21, 1, 31, 2, 30, 2, +24, 1, 19, -2, 24, 1, 20, 6, +11, 12, 4, 12, 3, 7, 4, 0, +8, -7, 16, -13, 21, -15, 21, -11, +17, -3, 21, 4, 24, 12, 16, 15, +12, 10, 10, 3, 15, -2, 14, -3, +14, 0, 10, 0, 13, 1, 11, 0, +12, 5, 12, 6, 15, 4, 11, 2, +11, 2, 18, -1, 23, -2, 23, -3, +19, -4, 19, -5, 20, 0, 16, 5, +13, 8, 7, 4, 1, -1, -7, -4, +1, -5, 12, -5, 23, 0, 24, 4, +24, 11, 20, 15, 21, 15, 20, 9, +16, 6, 7, 1, -1, -2, -3, -7, +4, -11, 11, -15, 13, -13, 12, -8, +17, -1, 25, 3, 30, 8, 26, 7, +21, 3, 13, -1, 8, -3, 10, -3, +13, 2, 11, 5, 10, 9, 10, 8, +15, 4, 18, -4, 17, -9, 8, -11, +10, -11, 10, -8, 12, 1, 16, 4, +19, 4, 17, 6, 16, 5, 20, 4, +22, 4, 15, -2, 7, -10, 3, -14, +3, -14, 4, -9, 9, 3, 11, 12, +16, 19, 18, 17, 27, 11, 28, 5, +26, 1, 11, -7, 4, -10, 1, -9, +-1, -7, -4, -6, -3, -7, 2, -6, +11, -6, 20, -2, 26, 4, 29, 6, +29, 5, 20, 6, 11, 9, 8, 8, +4, 9, -4, 11, -5, 12, 0, 7, +12, -1, 17, -13, 21, -19, 18, -20, +16, -16, 12, -8, 13, 2, 14, 5, +12, 6, 7, 4, 9, 3, 14, 3, +18, 4, 15, 3, 13, 4, 9, 2, +2, 3, -3, 1, -4, -1, 2, -4, +7, -2, 13, 0, 24, 0, 31, 1, +30, 3, 20, 3, 15, 4, 8, 2, +1, 0, -10, -4, -11, -12, -7, -22, +6, -25, 15, -21, 23, -7, 24, 10, +23, 24, 22, 30, 22, 28, 17, 18, +6, 7, -3, -6, -4, -11, 0, -13, +6, -8, 7, -8, 7, -7, 6, -8, +10, -4, 13, 1, 17, 5, 12, 3, +8, -1, 6, -8, 11, -10, 17, -8, +22, -1, 16, 10, 7, 21, 0, 23, +0, 19, 3, 7, 0, -6, -3, -21, +2, -26, 10, -22, 21, -11, 29, -1, +30, 10, 21, 16, 14, 14, 9, 8, +5, 5, -3, -2, -11, -10, -15, -21, +-3, -27, 7, -24, 13, -11, 14, 3, +19, 21, 20, 32, 21, 34, 20, 24, +15, 12, 5, -2, -2, -12, -3, -15, +2, -12, 4, -9, -1, -6, -4, -7, +1, -7, 10, -8, 15, -6, 15, -3, +13, 3, 8, 5, 10, 4, 14, 1, +20, 3, 13, 6, 3, 13, -5, 16, +-1, 15, 3, 7, 3, -6, 1, -20, +5, -24, 6, -20, 11, -10, 18, 0, +19, 11, 16, 14, 10, 8, 10, 1, +14, -4, 10, -5, 2, -4, -8, -3, +-7, -5, -7, -10, -2, -11, 0, -10, +10, -3, 17, 6, 23, 17, 24, 20, +26, 21, 18, 14, 9, 8, 0, 0, +-5, -4, -10, -10, -15, -13, -14, -17, +-4, -22, 10, -24, 17, -16, 17, -4, +18, 8, 17, 18, 15, 23, 11, 17, +8, 8, 0, -1, -5, -3, -4, -3, +6, 2, 8, 6, 8, 5, 4, -3, +6, -11, 7, -19, 11, -18, 5, -10, +0, -2, 3, -1, 12, 2, 18, 3, +21, 5, 18, 6, 9, 10, -1, 11, +-9, 9, -13, -1, -17, -12, -20, -21, +-10, -24, 5, -15, 23, 4, 31, 21, +35, 32, 28, 32, 22, 25, 7, 10, +-5, -4, -18, -17, -26, -24, -25, -28, +-13, -27, 5, -24, 22, -15, 24, -4, +21, 8, 23, 14, 22, 20, 13, 19, +-2, 16, -14, 6, -17, -1, -11, -4, +-1, 4, 6, 10, 12, 13, 8, 8, +3, 0, 1, -12, 1, -19, -7, -21, +-10, -16, -4, -7, 9, 5, 19, 11, +25, 15, 23, 13, 18, 7, 9, 3, +-1, 2, -9, -5, -15, -12, -23, -19, +-25, -19, -10, -16, 13, -4, 27, 12, +31, 27, 29, 32, 26, 28, 14, 15, +4, 0, -10, -13, -21, -18, -30, -19, +-22, -18, -5, -18, 15, -17, 19, -15, +16, -7, 14, 2, 12, 13, 10, 19, +5, 23, -1, 21, -7, 16, -6, 4, +1, -3, 9, -7, 12, -6, 4, -3, +-4, -2, -8, -9, -4, -14, -7, -14, +-5, -9, 2, -3, 15, 7, 18, 13, +21, 12, 18, 5, 12, 0, 4, -6, +-3, -3, -12, 4, -21, 8, -23, 3, +-17, -3, -4, -14, 14, -20, 25, -18, +25, -2, 18, 15, 14, 28, 8, 30, +2, 23, -6, 10, -13, 0, -16, -12, +-5, -20, 1, -23, 7, -24, 5, -28, +4, -24, 0, -14, 2, 3, 4, 20, +4, 36, 2, 39, 5, 32, 9, 16, +11, -1, 9, -16, 4, -20, -3, -17, +-12, -6, -19, 2, -19, 5, -13, 1, +-4, -3, 5, -6, 21, -5, 27, -3, +27, 3, 14, 4, 8, 3, 1, 2, +-8, 6, -19, 9, -23, 12, -22, 9, +-11, -2, 2, -17, 14, -26, 17, -25, +9, -10, 6, 7, 9, 26, 14, 37, +9, 37, -3, 25, -8, 5, -6, -16, +3, -29, 3, -33, 3, -29, -5, -24, +-8, -15, -11, -6, -2, 4, 6, 10, +12, 17, 10, 21, 13, 23, 18, 12, +21, 1, 12, -10, -1, -11, -11, -8, +-18, 1, -18, 8, -13, 8, -4, -2, +0, -12, 4, -20, 13, -21, 20, -14, +18, 1, 7, 15, 0, 25, -5, 22, +-3, 14, -5, 5, -8, 0, -8, -9, +-2, -15, -1, -18, 2, -21, 1, -20, +-1, -9, -5, 7, 1, 26, 11, 37, +14, 39, 13, 26, 12, 5, 12, -17, +10, -30, 1, -33, -12, -24, -24, -14, +-29, -2, -27, 2, -10, 2, 5, -1, +17, 1, 22, 5, 29, 14, 28, 19, +24, 19, 6, 14, -15, 8, -30, -2, +-28, -8, -19, -8, -9, -5, 3, -7, +13, -12, 19, -16, 23, -17, 22, -13, +13, -1, 0, 7, -9, 15, -15, 17, +-12, 11, -5, -2, 4, -9, 7, -8, +11, -2, 8, 1, 5, 3, -6, 0, +-14, -4, -19, -6, -17, -2, -8, 5, +8, 14, 18, 18, 28, 20, 28, 15, +24, 7, 11, -5, -11, -12, -27, -19, +-34, -24, -29, -29, -21, -30, -7, -27, +11, -16, 24, 5, 34, 30, 35, 48, +31, 56, 10, 45, -10, 20, -23, -12, +-23, -34, -23, -43, -18, -37, -9, -23, +6, -4, 18, 10, 24, 18, 22, 16, +14, 11, 4, 2, -6, -5, -7, -11, +-4, -14, -5, -16, -6, -12, -2, -6, +7, 10, 8, 24, 5, 30, -4, 22, +-7, 8, -13, -12, -8, -26, -1, -32, +10, -19, 9, 4, 6, 28, 9, 36, +16, 32, 14, 20, -2, 4, -14, -14, +-18, -28, -17, -37, -14, -36, -12, -32, +-4, -20, 2, -3, 11, 20, 17, 40, +21, 55, 13, 54, 4, 39, -2, 11, +0, -17, -3, -37, -8, -38, -18, -29, +-15, -14, -6, -2, 0, 8, 2, 8, +7, 1, 9, -3, 13, -1, 18, 2, +20, 6, 13, 7, -2, 5, -14, -2, +-15, -8, -12, -6, -15, 1, -16, 6, +-11, 9, -3, 8, 12, 5, 19, 1, +24, 3, 12, 8, 3, 12, -4, 8, +-2, 3, -6, -5, -8, -14, -12, -20, +-8, -17, 0, -11, 9, -1, 10, 3, +7, 2, 4, -7, -1, -9, -4, -8, +-6, 3, -2, 15, 3, 27, 6, 30, +13, 30, 10, 22, 6, 11, -3, -6, +-5, -18, -12, -25, -16, -29, -20, -33, +-18, -28, -7, -19, 9, 0, 21, 21, +27, 39, 27, 46, 17, 40, 4, 17, +-7, -10, -13, -37, -20, -46, -26, -38, +-24, -16, -10, 8, 8, 29, 17, 36, +22, 33, 22, 22, 19, 9, 11, -5, +6, -16, -5, -23, -14, -26, -21, -28, +-14, -20, -4, -6, 6, 11, 6, 21, +6, 20, 6, 9, 5, -4, 2, -16, +-1, -17, -3, -4, -7, 18, -8, 33, +-2, 38, 6, 30, 8, 17, 5, -3, +3, -19, 1, -29, -2, -29, -11, -27, +-14, -18, -13, -12, 1, -4, 5, 8, +10, 21, 9, 28, 11, 29, 12, 18, +10, 5, 4, -11, -6, -21, -16, -18, +-24, -4, -19, 10, -10, 21, -5, 19, +-1, 10, 4, -2, 11, -6, 15, -5, +16, 4, 8, 11, 0, 15, -12, 13, +-16, 7, -17, -5, -11, -14, -13, -20, +-12, -19, -6, -17, 7, -9, 15, -2, +17, 11, 12, 23, 6, 36, 2, 40, +-2, 39, -5, 20, -5, -5, -5, -29, +-8, -40, -8, -39, -4, -23, -5, -2, +-5, 17, -3, 25, 2, 24, 3, 13, +4, 2, 0, -8, 3, -9, 2, -6, +0, 1, -5, 4, -6, 10, -12, 15, +-11, 20, -8, 21, -3, 21, -3, 11, +-5, -5, -3, -23, 4, -33, 12, -30, +10, -11, 3, 13, -3, 36, -7, 44, +-6, 39, -9, 20, -8, -6, -9, -33, +-7, -43, -11, -37, -2, -23, 2, -6, +4, 14, -3, 30, -2, 42, 1, 46, +3, 46, 1, 33, -2, 13, -2, -14, +-5, -33, -7, -39, -11, -31, -14, -16, +-17, 5, -18, 19, -10, 27, -2, 22, +6, 11, 8, -1, 14, -6, 16, -7, +15, 0, 0, 9, -12, 13, -24, 8, +-25, 7, -26, 6, -19, 9, -7, 10, +2, 9, 10, 2, 21, -4, 23, -11, +15, -10, 1, -6, -13, 6, -21, 16, +-24, 21, -24, 16, -18, 6, -7, -9, +5, -16, 13, -12, 13, 0, 7, 6, +-1, 9, -18, 11, -25, 13, -25, 11, +-16, 15, -10, 18, 5, 21, 14, 21, +21, 14, 20, -2, 11, -12, -9, -19, +-26, -20, -36, -17, -38, -8, -26, -1, +-15, 7, -2, 11, 16, 13, 31, 15, +38, 21, 26, 23, 6, 21, -20, 10, +-36, -2, -50, -12, -46, -12, -35, -6, +-14, 6, 4, 14, 22, 20, 31, 19, +28, 13, 15, 3, -4, 1, -21, 2, +-33, 6, -38, 5, -33, 0, -19, -10, +-4, -10, 9, -10, 17, -3, 18, 8, +9, 20, -8, 24, -16, 21, -20, 11, +-19, 5, -22, 4, -18, 7, -7, 9, +10, 9, 16, 4, 13, -1, 0, -5, +-11, -4, -20, -1, -22, 6, -24, 7, +-22, 4, -19, -4, -11, -10, 5, -14, +18, -5, 18, 11, 7, 28, -2, 36, +-9, 38, -17, 27, -22, 11, -27, -7, +-27, -17, -26, -20, -17, -15, -5, -11, +11, -4, 13, 5, 12, 18, 3, 30, +-2, 38, -9, 33, -17, 20, -21, -4, +-23, -25, -24, -36, -27, -34, -20, -22, +-9, 1, 0, 28, 1, 49, 1, 51, +3, 42, -1, 26, -6, 10, -13, -2, +-16, -9, -24, -17, -26, -17, -30, -16, +-18, -12, -5, -2, 4, 14, 7, 28, +5, 37, -5, 34, -18, 19, -25, -5, +-24, -25, -23, -33, -23, -22, -20, 0, +-7, 26, 7, 44, 12, 54, 4, 49, +-10, 36, -26, 14, -35, -8, -38, -25, +-36, -35, -34, -36, -25, -25, -10, -4, +13, 26, 23, 56, 19, 72, 4, 65, +-9, 39, -29, 0, -44, -36, -53, -62, +-48, -62, -37, -37, -23, 1, -3, 34, +15, 65, 20, 79, 17, 73, 12, 51, +-4, 24, -29, -9, -47, -36, -58, -55, +-51, -55, -38, -41, -20, -11, -6, 26, +13, 60, 18, 78, 18, 73, 4, 42, +-16, 1, -42, -36, -59, -55, -58, -54, +-38, -28, -14, 13, 1, 53, 12, 75, +13, 79, 7, 59, -3, 27, -25, -9, +-48, -41, -62, -62, -57, -64, -39, -46, +-6, -8, 16, 36, 32, 75, 28, 95, +10, 89, -14, 49, -38, -4, -62, -56, +-70, -85, -63, -80, -44, -44, -17, 6, +10, 58, 26, 92, 28, 103, 12, 84, +-12, 48, -37, 4, -55, -34, -64, -60, +-60, -66, -42, -54, -17, -23, 0, 22, +6, 67, 2, 90, -2, 83, -12, 48, +-22, 0, -35, -47, -40, -75, -43, -72, +-29, -36, -13, 14, 1, 69, -4, 101, +-14, 103, -19, 74, -26, 27, -39, -24, +-53, -64, -53, -86, -39, -77, -18, -40, +-2, 13, 8, 63, 11, 98, -1, 113, +-15, 97, -34, 50, -50, -13, -69, -75, +-66, -105, -56, -94, -33, -47, -12, 18, +7, 86, 16, 128, 13, 133, -7, 96, +-32, 32, -51, -35, -67, -79, -69, -94, +-53, -78, -30, -34, -6, 24, 8, 76, +10, 109, -2, 109, -24, 80, -54, 26, +-67, -35, -71, -82, -62, -101, -38, -86, +-6, -26, 15, 51, 27, 119, 15, 151, +-11, 137, -42, 78, -72, 0, -94, -76, +-93, -120, -72, -123, -35, -79, 4, -8, +32, 67, 40, 118, 28, 139, -2, 119, +-38, 68, -74, -1, -98, -64, -101, -105, +-80, -105, -47, -69, -10, -4, 15, 65, +27, 120, 19, 140, -4, 118, -36, 57, +-60, -19, -80, -79, -84, -100, -72, -83, +-44, -33, -13, 29, 11, 84, 17, 111, +-2, 103, -31, 66, -60, 17, -75, -32, +-77, -64, -74, -73, -55, -57, -25, -22, +7, 30, 20, 77, 17, 104, -7, 102, +-36, 78, -69, 35, -86, -17, -88, -65, +-74, -86, -51, -73, -17, -29, 10, 23, +16, 66, 6, 85, -14, 86, -40, 64, +-62, 28, -79, -11, -78, -37, -63, -45, +-38, -34, -18, -15, -6, 12, -13, 39, +-31, 67, -52, 80, -63, 71, -69, 42, +-68, 6, -58, -25, -35, -40, -15, -34, +-6, -8, -11, 26, -20, 57, -42, 69, +-67, 58, -85, 27, -83, -3, -70, -24, +-46, -31, -24, -24, -8, -4, -2, 21, +-7, 46, -22, 61, -46, 64, -78, 53, +-96, 36, -96, 14, -74, -7, -45, -25, +-20, -25, -8, -10, -1, 17, -13, 41, +-33, 51, -55, 45, -77, 31, -92, 8, +-88, -13, -70, -21, -42, -7, -12, 17, +8, 43, 11, 56, -10, 54, -49, 36, +-84, 14, -109, -7, -113, -21, -99, -23, +-67, -6, -35, 18, 3, 39, 24, 50, +27, 59, 1, 60, -44, 51, -95, 26, +-126, -8, -130, -38, -109, -46, -74, -34, +-35, -5, -2, 27, 18, 59, 17, 80, +-4, 82, -43, 55, -83, 17, -112, -15, +-113, -26, -95, -22, -65, -7, -37, 11, +-12, 32, -3, 48, -10, 53, -32, 42, +-57, 24, -81, 5, -94, -6, -92, -17, +-71, -23, -50, -14, -31, 16, -19, 47, +-9, 71, -22, 74, -49, 59, -76, 28, +-92, -3, -99, -31, -94, -41, -80, -27, +-55, 3, -32, 38, -15, 63, -11, 67, +-19, 64, -43, 48, -64, 25, -83, -2, +-93, -19, -100, -28, -85, -18, -62, -2, +-39, 19, -30, 38, -32, 55, -40, 61, +-47, 51, -61, 24, -76, -1, -87, -14, +-85, -7, -69, 7, -45, 29, -32, 50, +-37, 65, -55, 59, -68, 33, -79, -1, +-86, -23, -94, -27, -82, -13, -63, 8, +-41, 31, -28, 46, -23, 57, -32, 56, +-46, 46, -70, 29, -95, 17, -108, 2, +-104, -10, -86, -13, -62, -2, -45, 17, +-35, 35, -35, 46, -43, 47, -59, 38, +-70, 25, -79, 16, -78, 15, -75, 17, +-69, 26, -63, 29, -56, 26, -59, 12, +-68, -4, -77, -12, -80, -4, -77, 16, +-68, 39, -60, 56, -49, 63, -49, 55, +-52, 34, -60, 6, -67, -14, -75, -21, +-76, -5, -76, 21, -79, 44, -80, 54, +-81, 58, -79, 49, -69, 27, -67, -1, +-66, -21, -62, -28, -51, -15, -44, 10, +-39, 42, -47, 67, -63, 83, -90, 77, +-108, 46, -112, 0, -104, -37, -89, -51, +-67, -32, -49, 4, -36, 43, -32, 70, +-37, 84, -50, 71, -70, 40, -92, 4, +-107, -14, -109, -12, -95, 2, -81, 18, +-68, 30, -65, 32, -62, 30, -61, 20, +-52, 6, -50, 3, -61, 16, -78, 33, +-82, 49, -83, 53, -84, 50, -92, 42, +-96, 28, -90, 5, -73, -15, -59, -21, +-51, -5, -54, 18, -58, 38, -66, 49, +-78, 52, -98, 42, -105, 20, -97, -5, +-73, -16, -52, -8, -42, 23, -49, 55, +-60, 71, -77, 64, -96, 42, -116, 9, +-121, -19, -113, -35, -88, -22, -59, 12, +-36, 52, -29, 78, -37, 81, -57, 60, +-81, 28, -107, -2, -123, -19, -122, -22, +-106, -6, -87, 21, -68, 48, -58, 57, +-49, 50, -52, 31, -60, 10, -74, -8, +-86, -10, -97, 1, -90, 26, -80, 55, +-76, 75, -81, 70, -84, 46, -85, 11, +-86, -19, -86, -35, -83, -31, -77, -5, +-75, 38, -77, 75, -76, 87, -75, 65, +-74, 29, -79, -7, -79, -27, -84, -24, +-86, 1, -87, 36, -84, 71, -86, 82, +-89, 63, -91, 22, -83, -17, -78, -38, +-72, -34, -68, -12, -69, 33, -81, 77, +-92, 106, -101, 102, -99, 67, -94, 12, +-86, -33, -81, -55, -75, -48, -74, -20, +-77, 24, -88, 72, -101, 103, -109, 99, +-103, 65, -91, 18, -72, -18, -61, -34, +-51, -26, -50, 4, -64, 48, -98, 79, +-125, 82, -139, 53, -129, 11, -107, -28, +-78, -46, -51, -39, -32, -3, -29, 44, +-41, 88, -72, 108, -113, 94, -146, 48, +-152, -2, -136, -38, -102, -48, -71, -32, +-47, 5, -37, 45, -38, 81, -63, 97, +-89, 79, -112, 37, -123, -5, -126, -34, +-115, -40, -97, -26, -73, 7, -53, 48, +-47, 83, -59, 94, -82, 78, -102, 42, +-107, 2, -106, -30, -106, -42, -110, -33, +-105, -3, -95, 35, -76, 69, -66, 87, +-64, 88, -69, 69, -71, 44, -77, 18, +-89, -7, -106, -30, -118, -37, -122, -25, +-117, -2, -108, 26, -95, 56, -78, 80, +-55, 93, -48, 87, -58, 58, -76, 14, +-93, -25, -107, -47, -112, -44, -118, -17, +-118, 25, -112, 71, -99, 108, -86, 112, +-70, 78, -64, 20, -63, -33, -69, -68, +-76, -74, -88, -47, -95, 11, -101, 77, +-102, 132, -109, 145, -109, 111, -98, 41, +-80, -36, -69, -95, -63, -117, -69, -91, +-84, -17, -104, 79, -116, 157, -115, 184, +-103, 158, -92, 87, -75, -3, -64, -85, +-62, -128, -74, -118, -88, -54, -116, 39, +-140, 126, -151, 168, -132, 161, -95, 110, +-58, 33, -37, -52, -31, -108, -47, -111, +-78, -61, -108, 14, -131, 91, -149, 142, +-143, 153, -112, 119, -73, 59, -51, -16, +-45, -79, -59, -105, -86, -80, -120, -22, +-139, 44, -132, 98, -100, 134, -69, 138, +-45, 105, -42, 42, -58, -21, -89, -62, +-127, -68, -161, -49, -171, -16, -150, 24, +-97, 68, -38, 96, 4, 99, 7, 78, +-24, 50, -77, 21, -131, -5, -176, -27, +-195, -32, -180, -21, -126, 5, -59, 31, +-4, 52, 12, 60, -10, 64, -59, 57, +-108, 40, -155, 14, -180, -7, -176, -17, +-132, -8, -74, 7, -26, 28, -13, 49, +-25, 68, -60, 78, -105, 70, -142, 42, +-161, 11, -160, -15, -135, -30, -100, -36, +-63, -23, -42, 10, -36, 57, -45, 99, +-60, 113, -86, 94, -110, 57, -129, 10, +-130, -33, -126, -64, -120, -67, -115, -36, +-102, 21, -83, 75, -59, 110, -41, 117, +-34, 99, -43, 57, -64, 5, -99, -46, +-131, -72, -158, -64, -164, -23, -148, 28, +-110, 78, -71, 111, -34, 120, -14, 95, +-16, 41, -47, -25, -91, -69, -136, -76, +-159, -46, -159, 3, -135, 59, -99, 107, +-62, 134, -42, 123, -35, 74, -50, 6, +-76, -49, -106, -80, -126, -78, -136, -51, +-132, 0, -114, 62, -85, 118, -59, 147, +-48, 135, -52, 84, -61, 20, -82, -39, +-103, -81, -120, -98, -125, -74, -123, -14, +-111, 62, -97, 117, -75, 138, -57, 122, +-44, 82, -41, 24, -54, -33, -84, -74, +-117, -76, -141, -41, -146, 15, -138, 67, +-123, 103, -96, 116, -58, 108, -27, 71, +-14, 11, -34, -48, -74, -80, -123, -75, +-152, -30, -158, 26, -134, 84, -103, 130, +-70, 144, -39, 110, -21, 45, -38, -26, +-74, -72, -115, -88, -145, -66, -158, -20, +-143, 41, -100, 98, -48, 135, -14, 131, +-7, 89, -33, 31, -83, -20, -138, -58, +-166, -77, -165, -67, -137, -19, -96, 49, +-43, 111, -2, 136, 9, 121, -26, 75, +-85, 14, -144, -50, -178, -87, -185, -81, +-153, -30, -95, 42, -30, 106, 13, 133, +23, 124, -14, 87, -75, 31, -142, -33, +-184, -78, -196, -90, -173, -57, -119, 3, +-49, 67, 10, 117, 33, 142, 11, 131, +-39, 84, -107, 14, -164, -57, -194, -98, +-184, -88, -148, -42, -91, 25, -39, 89, +0, 129, 14, 130, -3, 94, -47, 33, +-101, -27, -149, -60, -173, -55, -166, -25, +-130, 16, -87, 54, -44, 81, -15, 85, +-4, 66, -20, 30, -52, -4, -94, -20, +-132, -16, -160, -6, -158, 9, -132, 30, +-87, 56, -42, 69, -6, 62, 2, 37, +-17, 11, -59, -5, -103, -6, -139, -1, +-159, 13, -160, 28, -130, 38, -77, 33, +-25, 22, 5, 8, 10, 8, -17, 22, +-62, 42, -112, 50, -146, 45, -158, 28, +-145, 8, -113, -12, -63, -23, -21, -12, +-4, 20, -17, 58, -47, 79, -88, 71, +-121, 44, -143, 15, -135, -8, -108, -22, +-71, -19, -40, -1, -23, 32, -27, 62, +-51, 76, -84, 64, -110, 37, -125, 6, +-122, -22, -103, -42, -70, -37, -47, -4, +-38, 51, -43, 98, -53, 119, -76, 99, +-97, 49, -113, -16, -108, -71, -91, -92, +-70, -62, -57, 7, -55, 88, -70, 140, +-84, 137, -88, 84, -83, 8, -78, -61, +-69, -94, -61, -79, -55, -14, -60, 70, +-72, 134, -84, 145, -91, 104, -102, 32, +-103, -44, -92, -98, -67, -110, -44, -73, +-31, 12, -40, 111, -59, 177, -81, 179, +-93, 120, -101, 21, -99, -83, -89, -158, +-71, -163, -58, -92, -48, 33, -49, 160, +-60, 236, -80, 221, -95, 125, -102, -14, +-92, -138, -71, -204, -47, -179, -37, -68, +-38, 85, -53, 207, -71, 251, -92, 202, +-105, 82, -110, -60, -100, -168, -81, -205, +-50, -152, -28, -33, -19, 106, -27, 207, +-46, 232, -76, 176, -106, 69, -125, -55, +-118, -148, -95, -173, -68, -120, -41, -12, +-21, 110, -22, 191, -36, 194, -61, 122, +-89, 14, -117, -88, -122, -142, -103, -129, +-60, -46, -25, 70, -10, 164, -16, 188, +-40, 132, -78, 26, -110, -78, -127, -139, +-120, -132, -96, -59, -61, 51, -24, 149, +2, 190, 2, 155, -18, 61, -59, -45, +-107, -117, -146, -134, -144, -90, -112, -2, +-65, 97, -30, 161, -8, 167, -2, 108, +-11, 16, -41, -74, -77, -125, -110, -120, +-125, -57, -118, 39, -87, 134, -53, 184, +-27, 166, -21, 82, -27, -26, -45, -115, +-66, -143, -85, -105, -93, -14, -93, 92, +-88, 168, -79, 175, -59, 109, -38, 1, +-22, -91, -22, -128, -34, -96, -58, -14, +-80, 81, -94, 142, -92, 145, -88, 87, +-78, -2, -66, -80, -45, -112, -28, -87, +-17, -15, -21, 70, -32, 135, -55, 154, +-85, 117, -111, 34, -117, -57, -109, -120, +-81, -127, -48, -72, -16, 26, 2, 121, +4, 179, -16, 172, -50, 97, -92, -20, +-119, -127, -126, -174, -104, -136, -74, -28, +-37, 106, -8, 201, 6, 223, -5, 157, +-32, 29, -67, -106, -98, -190, -119, -185, +-117, -92, -99, 43, -64, 160, -25, 215, +8, 195, 14, 106, -5, -14, -46, -117, +-86, -163, -113, -139, -120, -54, -111, 54, +-78, 143, -38, 177, -2, 149, 11, 70, +2, -29, -27, -111, -63, -136, -98, -93, +-115, -3, -108, 92, -81, 153, -50, 151, +-20, 85, -8, -12, -13, -96, -27, -131, +-40, -93, -58, -3, -75, 95, -88, 152, +-85, 145, -71, 78, -53, -16, -40, -94, +-30, -117, -29, -81, -28, 0, -38, 85, +-54, 138, -73, 134, -82, 77, -77, -7, +-61, -80, -45, -113, -34, -89, -28, -20, +-28, 64, -38, 129, -54, 147, -71, 109, +-78, 33, -80, -48, -68, -104, -46, -114, +-16, -71, -8, 8, -14, 92, -37, 141, +-63, 137, -87, 78, -92, -9, -79, -87, +-57, -121, -38, -95, -19, -20, -6, 74, +-8, 144, -33, 154, -63, 99, -86, 4, +-91, -86, -78, -133, -54, -114, -34, -38, +-18, 63, -15, 145, -21, 166, -36, 117, +-53, 26, -66, -72, -66, -133, -65, -132, +-59, -70, -47, 26, -34, 115, -30, 158, +-28, 139, -37, 73, -47, -16, -54, -96, +-54, -129, -56, -102, -54, -26, -55, 68, +-54, 145, -53, 171, -48, 135, -45, 43, +-40, -69, -33, -149, -27, -156, -33, -88, +-44, 22, -58, 128, -66, 185, -75, 170, +-73, 83, -60, -35, -28, -126, 0, -156, +13, -115, -2, -24, -32, 79, -71, 151, +-98, 168, -107, 118, -88, 27, -57, -61, +-24, -111, 4, -118, 22, -78, 11, -2, +-20, 78, -58, 128, -88, 127, -108, 81, +-100, 14, -71, -51, -29, -86, 3, -82, +18, -40, 6, 21, -27, 74, -64, 97, +-85, 85, -95, 48, -88, -3, -65, -47, +-24, -57, 8, -31, 20, 13, 5, 51, +-28, 64, -71, 51, -106, 19, -116, -24, +-84, -52, -35, -45, 10, -6, 29, 43, +18, 82, -18, 91, -53, 62, -86, 12, +-106, -41, -108, -71, -82, -65, -40, -28, +10, 23, 38, 68, 37, 91, 3, 85, +-48, 56, -97, 9, -117, -39, -114, -68, +-85, -71, -39, -49, 9, -2, 34, 54, +34, 96, 8, 100, -29, 71, -71, 18, +-98, -39, -106, -80, -88, -83, -52, -51, +-9, 3, 16, 50, 21, 75, 10, 75, +-13, 58, -47, 29, -68, -3, -77, -24, +-75, -33, -69, -38, -58, -38, -41, -29, +-16, -7, 2, 30, 12, 72, 4, 97, +-15, 95, -48, 60, -78, 1, -98, -68, +-98, -112, -80, -109, -42, -53, -2, 35, +23, 119, 24, 159, 8, 140, -29, 65, +-60, -37, -78, -121, -81, -150, -78, -118, +-63, -38, -41, 59, -14, 137, 3, 168, +11, 139, 4, 60, -16, -35, -55, -113, +-90, -150, -102, -133, -78, -61, -35, 40, +10, 136, 28, 183, 17, 165, -20, 84, +-61, -30, -86, -138, -76, -190, -49, -158, +-20, -52, -7, 77, -7, 174, -21, 196, +-39, 140, -57, 35, -60, -75, -53, -145, +-38, -147, -22, -88, -5, 3, -5, 83, +-19, 123, -41, 119, -54, 79, -59, 19, +-51, -37, -45, -72, -32, -77, -23, -61, +-12, -26, -10, 17, -19, 61, -39, 87, +-51, 79, -49, 40, -36, -8, -27, -45, +-15, -57, -13, -45, -23, -14, -44, 20, +-61, 41, -70, 33, -61, 7, -33, -11, +9, -4, 36, 23, 37, 50, 5, 59, +-43, 39, -97, -11, -130, -72, -129, -109, +-84, -91, -22, -19, 41, 72, 82, 141, +87, 160, 50, 117, -18, 22, -102, -89, +-162, -168, -174, -177, -132, -112, -58, -7, +30, 99, 101, 176, 133, 199, 104, 150, +23, 49, -82, -72, -163, -170, -199, -214, +-174, -187, -98, -92, 6, 54, 94, 193, +140, 268, 118, 247, 46, 135, -53, -34, +-139, -197, -184, -295, -170, -275, -108, -138, +-19, 55, 55, 219, 97, 294, 99, 259, +62, 135, -8, -35, -80, -183, -131, -247, +-143, -215, -122, -119, -70, 9, -5, 126, +54, 200, 74, 211, 51, 156, -2, 53, +-55, -60, -96, -152, -102, -198, -77, -177, +-31, -86, 6, 44, 22, 156, 4, 200, +-31, 169, -61, 81, -60, -26, -39, -113, +-7, -143, 13, -111, 13, -44, -16, 14, +-53, 46, -78, 52, -72, 51, -51, 52, +-19, 56, 8, 53, 16, 39, -2, -4, +-19, -68, -32, -118, -37, -122, -44, -71, +-53, 15, -64, 100, -59, 158, -43, 165, +-8, 107, 29, 0, 47, -106, 24, -166, +-28, -160, -87, -100, -105, -9, -81, 83, +-34, 149, 5, 160, 31, 113, 35, 28, +17, -60, -22, -123, -52, -146, -71, -120, +-69, -50, -55, 36, -25, 114, -1, 152, +10, 138, 7, 70, -4, -26, -24, -113, +-41, -157, -47, -133, -46, -43, -48, 71, +-42, 153, -38, 166, -31, 98, -19, -25, +12, -136, 35, -177, 38, -125, 11, -6, +-30, 125, -81, 194, -120, 167, -130, 56, +-90, -85, -16, -196, 66, -222, 117, -146, +123, 0, 69, 153, -29, 248, -135, 244, +-193, 142, -188, -19, -116, -179, -17, -279, +75, -272, 121, -155, 124, 29, 86, 208, +20, 316, -63, 306, -133, 178, -179, -24, +-179, -220, -128, -330, -31, -312, 74, -182, +149, 10, 166, 196, 122, 312, 23, 319, +-94, 217, -188, 41, -214, -153, -178, -294, +-94, -338, 10, -273, 109, -105, 159, 117, +149, 315, 76, 404, -26, 340, -120, 138, +-171, -128, -173, -355, -130, -440, -62, -340, +18, -98, 76, 183, 101, 382, 95, 412, +68, 269, 4, 22, -70, -217, -126, -344, +-145, -308, -127, -145, -73, 53, -4, 195, +56, 229, 81, 163, 79, 44, 55, -61, +16, -109, -40, -94, -91, -45, -125, -2, +-122, 13, -82, 1, -16, -15, 42, -12, +78, 13, 82, 44, 60, 61, 3, 52, +-56, 11, -90, -42, -96, -71, -91, -62, +-64, -25, -22, 13, 25, 28, 48, 20, +51, 3, 39, -10, 21, 3, -19, 40, +-66, 80, -103, 83, -108, 27, -81, -72, +-24, -165, 34, -192, 78, -123, 84, 17, +53, 171, -15, 268, -85, 252, -125, 114, +-115, -89, -67, -259, 6, -315, 66, -236, +84, -59, 50, 140, 2, 278, -43, 303, +-79, 206, -101, 25, -83, -158, -43, -268, +7, -272, 45, -176, 64, -15, 57, 148, +32, 248, -11, 243, -56, 138, -95, -16, +-107, -156, -89, -228, -43, -203, 10, -90, +69, 58, 102, 168, 88, 192, 27, 126, +-45, 17, -99, -90, -119, -148, -105, -136, +-57, -63, 0, 27, 43, 88, 60, 99, +65, 70, 53, 20, 26, -28, -15, -66, +-54, -81, -92, -69, -114, -32, -111, 13, +-66, 52, 10, 83, 91, 97, 134, 73, +120, 11, 53, -69, -28, -133, -106, -148, +-160, -105, -165, -17, -109, 94, -23, 180, +63, 196, 120, 126, 140, -4, 110, -139, +40, -219, -52, -209, -126, -109, -168, 39, +-159, 172, -106, 231, -17, 185, 72, 57, +143, -86, 158, -180, 120, -190, 42, -124, +-49, -9, -140, 97, -197, 142, -195, 111, +-121, 38, -2, -34, 129, -75, 224, -77, +235, -45, 130, 6, -47, 49, -206, 61, +-272, 35, -238, -8, -117, -48, 40, -73, +178, -69, 230, -31, 192, 37, 88, 103, +-34, 126, -136, 84, -190, 0, -194, -91, +-145, -156, -55, -164, 59, -100, 154, 19, +202, 137, 179, 194, 86, 166, -57, 77, +-188, -31, -246, -127, -205, -181, -96, -171, +45, -93, 162, 14, 210, 105, 164, 153, +62, 161, -48, 124, -128, 40, -164, -73, +-144, -165, -87, -195, -8, -162, 58, -78, +104, 39, 125, 156, 122, 223, 80, 197, +-6, 89, -120, -49, -198, -166, -197, -224, +-112, -207, 14, -109, 137, 44, 197, 180, +175, 228, 80, 181, -37, 77, -128, -49, +-159, -160, -142, -207, -80, -158, -2, -49, +70, 57, 108, 112, 111, 126, 72, 115, +11, 73, -51, -4, -87, -79, -96, -116, +-67, -109, -21, -79, 26, -31, 51, 38, +59, 106, 47, 124, 20, 77, -18, -2, +-31, -68, -21, -102, -7, -94, -11, -45, +-15, 27, -22, 82, -28, 78, -26, 21, +5, -38, 47, -63, 78, -50, 64, -10, +12, 43, -58, 87, -99, 88, -91, 28, +-36, -61, 25, -128, 65, -141, 65, -97, +34, -9, 0, 99, -11, 188, -8, 200, +-2, 117, -6, -22, -14, -151, -34, -227, +-50, -225, -44, -139, -1, 9, 50, 155, +82, 239, 74, 235, 40, 164, -14, 45, +-67, -93, -99, -215, -90, -278, -44, -253, +21, -143, 76, 23, 106, 204, 97, 340, +61, 365, 0, 242, -67, 10, -111, -245, +-105, -418, -68, -439, -14, -294, 44, -34, +104, 241, 135, 420, 123, 442, 71, 305, +-2, 67, -90, -189, -155, -377, -167, -436, +-108, -348, -12, -149, 91, 97, 168, 314, +196, 434, 153, 403, 55, 217, -73, -53, +-173, -299, -200, -430, -141, -399, -35, -229, +77, 18, 149, 250, 161, 370, 112, 333, +39, 181, -23, -8, -49, -167, -64, -251, +-74, -242, -76, -157, -57, -37, -29, 66, +20, 126, 84, 146, 142, 133, 153, 89, +106, 24, 7, -42, -101, -89, -177, -115, +-181, -113, -115, -79, 2, -17, 124, 45, +200, 82, 194, 83, 118, 62, 7, 33, +-92, 1, -150, -28, -133, -44, -54, -43, +34, -43, 74, -54, 67, -59, 33, -31, +5, 23, -2, 73, 25, 98, 62, 97, +78, 62, 44, -7, -23, -85, -99, -130, +-132, -115, -102, -59, -15, 7, 83, 55, +157, 75, 173, 67, 121, 42, 16, 12, +-74, -3, -119, -3, -110, -11, -68, -45, +-5, -85, 50, -101, 82, -78, 83, -14, +71, 74, 51, 150, 26, 171, -2, 109, +-17, -13, -28, -139, -40, -213, -50, -199, +-41, -99, -12, 49, 37, 178, 84, 223, +116, 159, 112, 17, 81, -127, 20, -202, +-54, -177, -120, -70, -133, 65, -88, 158, +-6, 162, 75, 72, 138, -57, 153, -147, +112, -149, 37, -71, -28, 41, -68, 125, +-76, 140, -58, 81, -17, -20, 22, -112, +47, -150, 48, -117, 42, -39, 38, 37, +46, 84, 55, 95, 56, 76, 36, 37, +2, -12, -39, -57, -68, -82, -72, -86, +-37, -71, 12, -42, 63, 7, 100, 61, +124, 99, 113, 97, 59, 60, -18, 2, +-77, -58, -108, -98, -104, -107, -59, -80, +19, -25, 91, 34, 142, 75, 148, 91, +113, 79, 42, 38, -36, -23, -99, -80, +-118, -103, -91, -87, -18, -41, 59, 14, +114, 62, 132, 81, 114, 63, 52, 15, +-17, -39, -57, -70, -54, -64, -31, -39, +7, 0, 40, 43, 60, 71, 47, 59, +14, 9, -12, -59, -13, -107, -2, -115, +27, -80, 70, 1, 106, 114, 101, 198, +55, 192, -27, 81, -100, -89, -132, -244, +-100, -314, -22, -261, 77, -82, 165, 162, +214, 360, 189, 410, 102, 280, -25, 27, +-147, -244, -225, -431, -217, -453, -111, -296, +60, -20, 218, 261, 305, 434, 283, 434, +160, 280, -21, 28, -180, -235, -252, -414, +-218, -439, -104, -306, 46, -72, 165, 175, +227, 350, 224, 397, 168, 301, 68, 99, +-37, -130, -122, -297, -162, -349, -157, -288, +-89, -148, 22, 24, 135, 179, 198, 267, +200, 264, 145, 180, 52, 55, -55, -79, +-124, -202, -129, -275, -77, -259, 4, -149, +85, 6, 126, 148, 118, 237, 67, 253, +13, 184, -20, 42, -19, -119, 5, -235, +35, -260, 46, -195, 51, -83, 49, 50, +27, 176, -19, 238, -50, 203, -53, 85, +-18, -62, 45, -179, 120, -230, 168, -199, +158, -86, 75, 74, -38, 199, -139, 223, +-182, 141, -147, -1, -31, -141, 115, -220, +233, -199, 268, -81, 209, 82, 70, 198, +-83, 203, -196, 105, -227, -38, -166, -169, +-20, -235, 147, -195, 261, -46, 266, 131, +179, 236, 36, 213, -102, 88, -173, -74, +-149, -208, -61, -254, 49, -177, 127, -7, +156, 161, 125, 225, 61, 163, -7, 27, +-45, -108, -45, -187, -9, -172, 38, -68, +76, 67, 84, 150, 66, 132, 23, 35, +-23, -74, -44, -143, -26, -146, 10, -80, +54, 30, 91, 126, 118, 153, 108, 96, +54, -7, -14, -107, -56, -167, -70, -158, +-48, -77, 6, 39, 77, 133, 118, 151, +118, 85, 85, -27, 38, -122, -5, -160, +-18, -119, -10, -11, 12, 105, 26, 148, +24, 96, 4, -21, -4, -133, 17, -178, +64, -137, 108, -25, 128, 108, 111, 187, +59, 165, -29, 57, -112, -80, -143, -181, +-97, -205, 3, -150, 124, -38, 220, 82, +245, 161, 175, 167, 43, 110, -98, 16, +-182, -83, -178, -154, -93, -167, 31, -119, +153, -35, 219, 50, 203, 104, 111, 105, +-3, 64, -87, -1, -97, -56, -47, -70, +34, -42, 100, -8, 118, 3, 70, -13, +0, -49, -48, -90, -43, -104, 3, -58, +78, 46, 142, 150, 165, 192, 119, 147, +23, 32, -81, -118, -137, -251, -124, -303, +-44, -230, 59, -53, 156, 147, 209, 281, +195, 306, 115, 216, 14, 42, -75, -155, +-124, -293, -129, -313, -76, -220, 15, -71, +109, 80, 161, 189, 172, 233, 139, 195, +80, 95, 8, -24, -42, -121, -60, -189, +-50, -220, -30, -192, -10, -92, 6, 40, +41, 141, 90, 183, 149, 165, 188, 96, +181, -10, 104, -116, -22, -173, -148, -160, +-204, -103, -171, -50, -60, -9, 89, 29, +233, 63, 311, 81, 287, 80, 162, 69, +-12, 48, -178, -5, -264, -91, -239, -170, +-96, -191, 94, -141, 251, -41, 312, 77, +255, 183, 105, 224, -54, 166, -168, 29, +-188, -126, -108, -233, 29, -249, 148, -171, +198, -31, 165, 112, 86, 195, -8, 175, +-66, 66, -65, -64, -4, -152, 73, -170, +119, -116, 110, -12, 62, 88, -9, 132, +-53, 94, -54, -5, 2, -110, 78, -169, +129, -159, 132, -81, 98, 39, 37, 152, +-13, 202, -49, 157, -51, 25, -15, -141, +49, -264, 100, -291, 115, -201, 94, -26, +57, 166, 8, 289, -22, 285, -23, 150, +18, -51, 71, -226, 97, -303, 90, -263, +64, -135, 16, 22, -24, 148, -50, 189, +-40, 148, 9, 65, 79, -12, 148, -65, +186, -96, 159, -110, 72, -108, -54, -92, +-152, -66, -172, -31, -93, 27, 44, 96, +178, 138, 258, 117, 244, 46, 120, -46, +-26, -131, -126, -185, -142, -181, -81, -114, +16, -6, 106, 93, 155, 147, 139, 141, +89, 86, 31, -6, -5, -114, -4, -192, +34, -197, 79, -126, 91, -17, 51, 83, +-14, 147, -78, 152, -78, 82, -10, -46, +102, -159, 200, -195, 233, -144, 179, -42, +59, 65, -91, 138, -184, 143, -187, 64, +-99, -66, 47, -174, 199, -193, 286, -119, +273, -7, 162, 90, 11, 141, -129, 123, +-196, 31, -171, -93, -60, -174, 90, -165, +212, -85, 255, 15, 212, 97, 83, 130, +-53, 87, -141, -23, -149, -137, -71, -183, +57, -131, 170, -14, 222, 106, 179, 176, +79, 157, -35, 43, -115, -123, -133, -259, +-66, -287, 53, -190, 161, -11, 213, 167, +199, 278, 114, 276, 6, 153, -89, -51, +-130, -249, -95, -357, -7, -337, 91, -212, +173, -23, 196, 176, 163, 320, 83, 348, +-12, 236, -76, 23, -75, -207, -32, -372, +18, -413, 55, -311, 83, -91, 90, 162, +86, 340, 79, 365, 83, 239, 87, 30, +65, -178, 10, -312, -42, -324, -86, -219, +-84, -52, -27, 94, 73, 163, 178, 148, +238, 91, 206, 19, 109, -43, -11, -79, +-112, -80, -164, -59, -135, -46, -31, -55, +114, -69, 221, -67, 237, -44, 168, -12, +60, 28, -59, 71, -126, 95, -104, 78, +-3, 18, 114, -57, 183, -119, 160, -156, +79, -161, -27, -127, -103, -52, -102, 36, +-10, 109, 114, 147, 212, 149, 221, 106, +143, 16, 20, -106, -97, -215, -171, -266, +-153, -236, -45, -139, 111, 3, 239, 156, +282, 265, 226, 277, 107, 176, -45, 0, +-167, -180, -201, -306, -128, -345, 7, -284, +150, -128, 231, 70, 237, 235, 187, 307, +92, 273, -21, 148, -93, -33, -117, -215, +-82, -338, -11, -356, 72, -261, 141, -90, +179, 98, 151, 243, 81, 306, 11, 266, +-29, 129, -40, -62, -11, -237, 31, -335, +70, -326, 88, -223, 66, -53, 29, 128, +26, 252, 35, 275, 55, 196, 69, 48, +66, -108, 58, -222, 42, -264, 7, -226, +-8, -126, -1, -8, 28, 83, 66, 122, +106, 126, 122, 106, 105, 61, 54, -8, +-9, -87, -49, -149, -39, -183, -10, -192, +51, -152, 114, -56, 147, 70, 152, 172, +112, 208, 29, 164, -37, 59, -74, -82, +-57, -218, 11, -296, 90, -268, 138, -146, +138, 11, 84, 141, 15, 217, -29, 221, +-11, 145, 40, 9, 98, -128, 116, -217, +73, -237, 7, -207, -48, -142, -67, -42, +-14, 78, 74, 169, 174, 200, 231, 173, +186, 103, 65, -15, -74, -168, -184, -297, +-196, -334, -91, -257, 98, -99, 271, 90, +345, 260, 277, 346, 107, 291, -80, 101, +-209, -143, -233, -330, -123, -391, 36, -327, +186, -167, 267, 38, 240, 214, 153, 283, +54, 228, -42, 100, -81, -29, -67, -128, +-16, -193, 45, -221, 80, -196, 74, -130, +57, -57, 50, 14, 58, 98, 74, 174, +109, 195, 119, 131, 100, 4, 50, -131, +-31, -229, -87, -268, -87, -230, -52, -120, +42, 19, 145, 126, 214, 168, 228, 151, +165, 107, 56, 43, -38, -40, -110, -128, +-136, -192, -102, -218, -7, -202, 104, -139, +190, -28, 217, 106, 179, 211, 109, 232, +40, 161, -23, 29, -37, -112, -30, -231, +-20, -287, -7, -263, -5, -168, 9, -42, +63, 76, 118, 166, 181, 223, 228, 225, +222, 160, 137, 24, -5, -153, -160, -316, +-261, -409, -255, -391, -126, -235, 82, 26, +310, 305, 437, 484, 416, 478, 267, 278, +28, -46, -205, -377, -329, -592, -325, -605, +-178, -392, 34, -35, 229, 317, 355, 526, +366, 529, 258, 329, 105, 8, -37, -315, +-121, -517, -143, -520, -121, -339, -85, -64, +-25, 191, 52, 339, 123, 346, 191, 220, +258, 15, 268, -179, 212, -278, 73, -262, +-103, -169, -231, -56, -273, 40, -217, 89, +-36, 74, 190, 13, 371, -40, 435, -49, +348, -14, 142, 25, -87, 33, -262, -3, +-311, -75, -207, -159, -6, -208, 181, -174, +287, -48, 273, 107, 182, 211, 76, 212, +-15, 107, -62, -63, -32, -223, 15, -298, +46, -246, 49, -91, 25, 83, 11, 181, +38, 167, 67, 68, 97, -57, 120, -150, +115, -165, 78, -102, 35, -4, -6, 60, +-7, 53, 12, -5, 13, -69, 12, -106, +41, -96, 68, -50, 92, 13, 107, 57, +107, 61, 94, 16, 63, -49, 0, -95, +-35, -108, -12, -98, 32, -65, 70, -13, +88, 39, 72, 60, 54, 39, 26, -10, +11, -66, 50, -111, 121, -123, 156, -96, +141, -32, 69, 42, -31, 88, -112, 75, +-135, 10, -87, -73, 46, -141, 191, -171, +273, -142, 271, -56, 197, 54, 66, 133, +-48, 142, -129, 75, -152, -36, -112, -149, +-46, -224, 28, -228, 129, -146, 213, -12, +278, 108, 291, 168, 217, 158, 71, 86, +-86, -20, -213, -130, -261, -210, -208, -230, +-73, -181, 96, -90, 275, 19, 383, 122, +385, 193, 294, 192, 115, 106, -98, -38, +-260, -181, -352, -271, -302, -278, -120, -201, +117, -56, 341, 99, 475, 198, 451, 203, +290, 131, 45, 21, -185, -86, -323, -170, +-323, -211, -213, -197, -29, -135, 168, -49, +299, 35, 343, 100, 321, 140, 212, 135, +85, 74, -36, -28, -145, -128, -199, -194, +-192, -214, -131, -185, 0, -101, 138, 12, +258, 114, 329, 165, 319, 154, 221, 86, +73, -15, -84, -129, -200, -215, -242, -239, +-193, -188, -88, -86, 79, 26, 251, 113, +351, 159, 361, 149, 264, 83, 85, -23, +-84, -128, -221, -202, -256, -229, -164, -205, +-15, -118, 134, 12, 253, 136, 301, 194, +272, 170, 161, 77, 16, -48, -107, -165, +-148, -234, -117, -226, -42, -148, 61, -44, +137, 48, 151, 108, 146, 136, 110, 128, +87, 74, 82, -24, 49, -131, 2, -213, +-33, -244, -53, -214, -18, -107, 41, 51, +98, 192, 131, 246, 129, 190, 98, 48, +69, -117, 50, -251, 30, -310, 14, -273, +23, -143, 14, 28, 17, 170, 47, 238, +68, 227, 85, 136, 91, -20, 68, -200, +65, -328, 41, -345, 5, -243, 8, -64, +43, 136, 91, 281, 131, 306, 124, 191, +83, -16, 19, -221, -41, -335, -84, -330, +-56, -217, 37, -43, 135, 126, 207, 216, +219, 204, 155, 109, 74, -14, -27, -118, +-108, -181, -114, -192, -71, -150, -3, -80, +84, -10, 148, 33, 203, 48, 226, 49, +191, 40, 104, 18, 2, -8, -95, -36, +-155, -65, -155, -102, -87, -140, 32, -156, +182, -127, 276, -56, 297, 43, 261, 132, +158, 183, 6, 164, -140, 64, -245, -92, +-238, -244, -137, -328, 0, -304, 154, -172, +303, 28, 386, 220, 373, 327, 245, 299, +43, 139, -162, -92, -312, -299, -376, -405, +-286, -366, -53, -195, 219, 36, 425, 234, +502, 325, 427, 271, 252, 107, -5, -92, +-268, -246, -408, -304, -381, -254, -225, -132, +25, 2, 288, 93, 483, 120, 525, 94, +375, 46, 90, 1, -175, -29, -326, -52, +-332, -72, -205, -96, -6, -122, 175, -137, +283, -119, 278, -66, 212, 12, 152, 94, +101, 153, 41, 159, -15, 101, -89, -16, +-160, -165, -185, -293, -138, -339, -1, -269, +210, -92, 378, 135, 428, 329, 335, 393, +122, 283, -125, 27, -305, -268, -370, -474, +-274, -500, -42, -335, 219, -45, 404, 247, +451, 422, 334, 411, 122, 228, -106, -41, +-269, -281, -292, -411, -163, -391, 25, -246, +199, -37, 288, 154, 266, 259, 172, 247, +55, 145, -56, -3, -98, -139, -72, -222, +-11, -224, 55, -153, 103, -55, 118, 20, +111, 46, 75, 33, 30, 11, 6, -2, +22, 4, 49, 27, 79, 42, 92, 11, +68, -68, 21, -160, -25, -213, -50, -198, +-7, -108, 72, 25, 147, 159, 190, 233, +158, 207, 63, 84, -35, -87, -111, -239, +-119, -319, -43, -303, 89, -184, 206, -2, +253, 173, 193, 274, 56, 265, -82, 150, +-155, -24, -150, -197, -46, -305, 94, -311, +212, -215, 266, -63, 223, 83, 116, 168, +3, 183, -119, 139, -183, 62, -147, -28, +-30, -107, 114, -165, 214, -198, 231, -205, +188, -167, 100, -75, 8, 58, -48, 181, +-38, 243, -5, 205, 12, 72, 10, -112, +-8, -276, -3, -351, 49, -292, 100, -126, +166, 71, 212, 212, 194, 259, 113, 204, +-19, 75, -157, -87, -223, -218, -204, -277, +-76, -254, 129, -172, 335, -51, 438, 86, +379, 201, 175, 240, -94, 174, -310, 22, +-373, -153, -283, -282, -61, -312, 186, -224, +358, -49, 413, 132, 334, 230, 165, 199, +-2, 76, -156, -67, -249, -164, -251, -187, +-165, -143, -6, -69, 170, -9, 288, 11, +324, 2, 269, -1, 148, 26, -6, 58, +-117, 53, -164, 8, -159, -62, -107, -131, +-28, -170, 65, -155, 179, -79, 247, 23, +258, 98, 206, 115, 92, 86, -40, 32, +-140, -33, -187, -101, -147, -151, -56, -168, +56, -144, 159, -92, 235, -16, 256, 76, +215, 152, 122, 165, -3, 108, -129, 0, +-194, -119, -195, -216, -115, -260, 27, -226, +180, -111, 305, 45, 334, 181, 230, 239, +65, 202, -111, 84, -215, -82, -205, -237, +-102, -305, 44, -256, 166, -115, 205, 43, +179, 152, 120, 175, 67, 127, 8, 36, +-43, -54, -64, -107, -48, -115, 5, -106, +67, -95, 107, -88, 137, -62, 110, -10, +31, 51, -38, 90, -55, 88, -12, 36, +63, -44, 108, -111, 116, -131, 91, -103, +42, -51, -15, -16, -31, -15, -1, -33, +46, -32, 78, 5, 79, 60, 56, 93, +36, 70, 2, -19, -16, -138, 5, -220, +54, -207, 104, -92, 129, 72, 94, 184, +32, 180, -44, 66, -103, -91, -95, -206, +-1, -215, 131, -114, 235, 41, 238, 153, +135, 152, -26, 42, -163, -103, -219, -201, +-152, -200, 11, -107, 191, 29, 300, 137, +287, 162, 159, 90, 1, -29, -130, -131, +-193, -172, -163, -157, -43, -110, 100, -47, +201, 27, 211, 84, 153, 113, 55, 107, +-41, 65, -103, -19, -81, -124, 6, -212, +102, -227, 148, -149, 122, -10, 42, 124, +-36, 190, -90, 157, -77, 48, 12, -85, +131, -170, 199, -161, 177, -74, 75, 16, +-37, 41, -114, -8, -125, -83, -67, -126, +50, -91, 150, 15, 189, 148, 156, 215, +81, 153, -1, -30, -54, -236, -73, -348, +-48, -305, -1, -132, 39, 92, 55, 259, +71, 290, 89, 184, 109, 6, 117, -151, +97, -217, 35, -194, -48, -125, -129, -67, +-144, -33, -73, -6, 47, 34, 161, 92, +221, 147, 191, 154, 110, 81, 14, -75, +-43, -242, -52, -324, -42, -263, -40, -94, +-45, 102, -46, 234, -7, 244, 79, 141, +189, -16, 260, -138, 239, -163, 106, -113, +-87, -60, -245, -56, -282, -93, -179, -121, +33, -94, 241, 6, 346, 161, 298, 287, +131, 292, -69, 131, -199, -139, -210, -387, +-105, -486, 37, -389, 144, -129, 163, 181, +114, 410, 44, 459, -3, 311, -6, 39, +27, -224, 47, -384, 48, -393, 22, -274, +-6, -89, -13, 93, -13, 206, -13, 216, +10, 154, 44, 68, 98, -1, 140, -54, +144, -100, 95, -146, 7, -184, -94, -200, +-149, -165, -125, -61, -28, 102, 82, 258, +168, 315, 193, 225, 154, 30, 77, -191, +-8, -346, -70, -367, -99, -243, -112, -38, +-81, 154, -11, 245, 88, 221, 189, 130, +234, 29, 193, -54, 88, -112, -63, -159, +-191, -186, -236, -192, -156, -159, 12, -63, +189, 92, 290, 235, 274, 294, 141, 219, +-40, 38, -182, -169, -195, -322, -97, -369, +47, -276, 154, -79, 162, 153, 82, 314, +-21, 340, -89, 235, -64, 43, 31, -188, +126, -364, 161, -394, 108, -253, 2, -3, +-85, 228, -120, 323, -68, 260, 33, 64, +127, -161, 160, -281, 116, -231, 28, -58, +-51, 114, -96, 158, -77, 57, -6, -111, +87, -217, 141, -166, 136, 34, 74, 251, +-11, 335, -78, 189, -95, -129, -61, -433, +17, -529, 86, -332, 125, 74, 115, 455, +65, 594, 11, 402, -20, -25, -31, -457, +-15, -652, -1, -505, 16, -91, 32, 346, +39, 557, 40, 442, 42, 95, 41, -285, +46, -483, 42, -403, 34, -96, 11, 247, +-27, 398, -64, 266, -63, -42, -13, -332, +66, -423, 126, -261, 146, 80, 110, 406, +41, 512, -36, 298, -88, -120, -93, -502, +-60, -632, -24, -439, 15, -23, 56, 398, +111, 612, 154, 496, 159, 124, 116, -288, +35, -511, -82, -456, -185, -191, -213, 101, +-130, 269, 23, 245, 177, 80, 263, -103, +256, -168, 145, -77, -25, 86, -163, 176, +-189, 119, -118, -58, 2, -245, 91, -337, +118, -264, 90, -43, 29, 220, -19, 380, +2, 357, 62, 170, 111, -81, 92, -291, +7, -388, -95, -341, -162, -167, -173, 51, +-82, 229, 73, 309, 223, 277, 301, 147, +268, -32, 130, -200, -54, -282, -227, -254, +-313, -139, -270, 2, -115, 101, 85, 114, +256, 65, 332, 3, 316, -6, 203, 48, +29, 115, -144, 125, -263, 34, -298, -161, +-231, -362, -87, -435, 110, -291, 285, 38, +362, 399, 307, 607, 141, 552, -77, 220, +-245, -256, -304, -653, -231, -765, -58, -531, +131, -64, 245, 411, 255, 693, 165, 667, +43, 349, -73, -112, -146, -489, -150, -626, +-83, -486, 4, -171, 73, 169, 95, 386, +86, 403, 64, 238, 35, 7, 5, -168, +1, -216, 8, -152, 8, -40, -23, 31, +-58, 24, -67, -45, -33, -108, 32, -101, +114, -4, 171, 129, 164, 224, 56, 203, +-95, 55, -197, -153, -181, -305, -56, -318, +124, -180, 255, 39, 262, 244, 109, 333, +-119, 258, -281, 49, -265, -177, -90, -317, +140, -316, 289, -194, 284, 3, 131, 201, +-71, 317, -192, 280, -158, 120, -32, -88, +83, -251, 106, -308, 39, -246, -57, -95, +-107, 101, -71, 227, 64, 216, 196, 100, +231, -33, 140, -102, -31, -83, -178, -29, +-214, 34, -151, 52, -16, -30, 108, -170, +155, -248, 125, -181, 56, 37, -3, 271, +-5, 386, 18, 335, 39, 111, 26, -219, +-38, -472, -113, -511, -121, -296, -51, 52, +65, 333, 155, 443, 170, 375, 101, 145, +-8, -123, -97, -291, -94, -292, -31, -168, +30, -46, 40, -11, 2, -5, -47, -5, +-45, 21, 10, 111, 98, 240, 162, 313, +147, 238, 53, -30, -72, -348, -166, -542, +-170, -535, -105, -296, -9, 108, 86, 481, +148, 657, 158, 541, 144, 192, 106, -196, +42, -471, -65, -555, -178, -407, -241, -138, +-210, 125, -98, 290, 79, 314, 259, 246, +350, 152, 291, 22, 106, -87, -128, -149, +-284, -188, -296, -198, -175, -170, 12, -102, +154, 24, 173, 132, 105, 183, 16, 207, +2, 180, 68, 81, 130, -47, 112, -189, +3, -272, -175, -262, -301, -181, -275, -31, +-77, 164, 187, 294, 365, 310, 354, 191, +176, 3, -79, -152, -267, -248, -283, -278, +-140, -197, 56, -52, 186, 95, 168, 190, +44, 210, -96, 187, -167, 115, -107, -44, +54, -206, 209, -273, 267, -213, 158, -57, +-53, 117, -243, 236, -315, 261, -218, 126, +13, -104, 230, -267, 333, -256, 259, -93, +50, 109, -165, 214, -272, 195, -225, 50, +-46, -154, 132, -265, 230, -183, 214, 30, +86, 239, -84, 296, -199, 187, -221, -21, +-123, -245, 35, -365, 171, -289, 239, -76, +207, 160, 70, 302, -93, 308, -220, 211, +-227, 46, -109, -149, 43, -281, 153, -318, +189, -248, 122, -89, 19, 117, -55, 312, +-68, 413, -31, 323, -11, 81, -39, -219, +-64, -455, -82, -500, -62, -316, 21, 21, +137, 376, 226, 547, 231, 460, 112, 178, +-67, -169, -232, -420, -321, -452, -288, -286, +-128, -11, 100, 208, 304, 250, 363, 145, +268, -2, 88, -94, -105, -43, -245, 98, +-262, 231, -166, 249, -25, 67, 64, -252, +76, -507, 61, -552, 59, -309, 68, 121, +94, 521, 110, 721, 75, 603, -22, 172, +-136, -335, -211, -669, -175, -679, -56, -375, +81, 52, 184, 395, 214, 545, 131, 414, +-12, 95, -126, -209, -129, -345, -48, -271, +27, -80, 46, 70, 27, 153, -47, 136, +-117, 15, -99, -103, 25, -113, 195, -17, +298, 130, 226, 192, 33, 132, -200, 4, +-385, -162, -410, -296, -246, -283, 34, -126, +330, 120, 465, 318, 403, 348, 223, 239, +-42, 71, -304, -123, -431, -239, -401, -240, +-208, -157, 46, -50, 226, -7, 309, -26, +274, 1, 121, 83, -17, 193, -98, 290, +-113, 290, -47, 151, -1, -94, -25, -382, +-62, -527, -129, -413, -159, -109, -90, 237, +45, 471, 222, 480, 341, 300, 280, -3, +108, -285, -115, -376, -333, -264, -405, -79, +-302, 81, -69, 144, 233, 127, 398, 76, +349, 11, 157, -11, -106, 47, -302, 76, +-315, 19, -190, -90, 56, -181, 263, -193, +266, -116, 123, 13, -68, 196, -227, 325, +-229, 281, -102, 93, 91, -123, 260, -287, +249, -327, 62, -248, -139, -63, -270, 176, +-253, 318, -95, 269, 90, 120, 241, -49, +290, -167, 167, -196, -14, -126, -156, 23, +-226, 160, -192, 141, -96, 7, 17, -121, +133, -177, 145, -133, 71, -7, 16, 137, +-28, 265, -52, 256, -17, 76, 27, -131, +75, -244, 75, -246, -24, -146, -132, -21, +-182, 109, -176, 210, -78, 188, 58, 78, +181, 5, 271, -35, 255, -61, 123, -94, +-30, -124, -193, -86, -316, -2, -332, 27, +-223, 55, -3, 106, 235, 123, 351, 77, +322, -15, 150, -80, -96, -42, -264, -16, +-276, -47, -149, -47, 63, -16, 189, 1, +152, 7, -14, 2, -193, 61, -241, 130, +-104, 86, 120, -7, 321, -39, 355, -55, +179, -63, -111, -72, -373, -50, -461, 36, +-307, 82, -20, 29, 255, 7, 395, 15, +352, 4, 169, -14, -66, -23, -246, 23, +-266, 102, -185, 67, -89, -30, -6, -99, +50, -150, 82, -152, 108, -64, 116, 83, +134, 273, 121, 337, 26, 179, -103, -70, +-205, -295, -247, -421, -191, -336, -96, -87, +35, 249, 191, 519, 276, 503, 255, 221, +160, -122, 12, -420, -117, -530, -244, -387, +-335, -82, -280, 274, -121, 495, 41, 421, +204, 183, 304, -87, 329, -300, 261, -334, +50, -193, -205, 31, -369, 245, -427, 258, +-314, 77, -63, -122, 224, -247, 442, -232, +433, -41, 179, 195, -110, 380, -321, 370, +-369, 89, -216, -256, 22, -443, 223, -432, +285, -192, 127, 160, -89, 440, -208, 522, +-201, 306, -58, -100, 115, -390, 194, -472, +183, -349, 48, -51, -148, 263, -237, 456, +-184, 442, -51, 183, 97, -129, 162, -326, +162, -400, 88, -315, -68, -76, -180, 186, +-151, 382, -45, 388, 64, 195, 102, -43, +65, -245, 7, -362, -63, -284, -126, -68, +-93, 173, 22, 328, 136, 285, 159, 99, +77, -82, -28, -225, -102, -244, -174, -121, +-194, 32, -108, 149, 33, 171, 129, 72, +157, -14, 150, -45, 143, -40, 76, 12, +-66, 43, -199, 7, -248, -32, -225, -82, +-140, -99, -9, -27, 169, 59, 312, 109, +305, 119, 143, 43, -42, -34, -183, -59, +-266, -62, -265, -20, -154, 43, 21, 42, +149, 6, 158, -52, 123, -100, 92, -60, +37, 37, -48, 118, -107, 177, -112, 142, +-72, 25, -56, -97, -52, -194, -4, -209, +67, -99, 91, 36, 69, 150, 25, 200, +9, 151, -21, 57, -84, -26, -108, -107, +-64, -116, -27, -67, -10, -28, 12, -12, +71, -19, 121, -27, 97, 30, 7, 95, +-80, 136, -145, 163, -156, 123, -106, 2, +-1, -135, 126, -250, 190, -252, 120, -140, +-18, -4, -134, 135, -175, 262, -130, 286, +-18, 207, 114, 59, 187, -104, 127, -216, +0, -276, -109, -279, -166, -145, -160, 71, +-99, 264, -10, 368, 93, 329, 139, 148, +113, -103, 58, -357, 2, -455, -37, -307, +-62, -9, -95, 288, -81, 462, -43, 402, +-39, 146, -44, -191, -13, -440, 44, -437, +107, -184, 112, 137, 71, 378, 16, 409, +-65, 208, -140, -99, -135, -346, -71, -392, +18, -178, 71, 133, 44, 358, 1, 387, +1, 189, 1, -130, 10, -375, 16, -428, +1, -236, -33, 94, -84, 359, -111, 432, +-35, 297, 70, 6, 138, -264, 153, -380, +73, -295, -90, -47, -236, 215, -316, 325, +-226, 258, 15, 46, 248, -189, 370, -318, +330, -281, 118, -80, -140, 207, -337, 387, +-379, 372, -217, 188, 8, -97, 141, -351, +178, -448, 109, -348, 7, -65, -33, 254, +-20, 436, 35, 419, 86, 225, 29, -78, +-66, -333, -139, -426, -179, -296, -123, 3, +-13, 292, 66, 407, 140, 321, 143, 52, +64, -272, -22, -469, -115, -411, -160, -113, +-94, 281, -2, 534, 106, 521, 176, 248, +113, -166, -22, -507, -166, -575, -287, -345, +-243, 64, -57, 419, 149, 516, 300, 329, +300, -19, 148, -346, -39, -447, -229, -280, +-303, 44, -213, 346, -68, 448, 77, 280, +179, -28, 154, -320, 66, -436, -51, -319, +-155, -57, -147, 210, -48, 380, 67, 351, +162, 157, 145, -79, 38, -254, -96, -290, +-217, -176, -231, -5, -111, 178, 27, 285, +136, 228, 178, 47, 131, -162, 34, -320, +-77, -307, -139, -137, -105, 112, -49, 358, +-6, 442, 20, 290, 19, 11, 2, -297, +-22, -460, -54, -374, -34, -123, 23, 178, +69, 401, 72, 376, 29, 160, -33, -123, +-89, -345, -144, -347, -125, -141, -23, 116, +75, 348, 118, 409, 101, 245, 37, -34, +-28, -334, -96, -508, -129, -404, -94, -133, +-30, 196, 27, 480, 61, 544, 50, 366, +35, 34, 9, -356, -43, -546, -71, -450, +-55, -179, -38, 192, -22, 476, -16, 480, +10, 261, 47, -114, 46, -438, 13, -467, +-10, -253, -55, 70, -108, 396, -128, 484, +-78, 308, 43, -10, 158, -354, 167, -476, +85, -303, -47, -23, -169, 277, -226, 430, +-185, 316, -55, 60, 118, -224, 190, -404, +128, -296, 22, -43, -63, 201, -106, 376, +-91, 333, -32, 105, 45, -142, 64, -358, +-12, -369, -119, -153, -156, 94, -120, 297, +-19, 373, 96, 220, 185, -9, 214, -237, +128, -366, -71, -246, -232, -2, -267, 203, +-201, 340, -72, 279, 68, 67, 155, -151, +163, -328, 55, -316, -62, -86, -74, 131, +-23, 280, 17, 313, 38, 158, 6, -51, +-50, -230, -116, -324, -170, -197, -128, 13, +10, 158, 107, 262, 127, 256, 85, 127, +38, -27, 8, -209, -43, -285, -97, -205, +-72, -105, -44, 27, -71, 207, -86, 296, +-49, 278, 20, 133, 80, -95, 63, -235, +32, -279, 20, -256, -32, -78, -85, 144, +-69, 278, -9, 277, 71, 117, 77, -75, +-20, -166, -106, -205, -159, -141, -202, 32, +-140, 171, 25, 207, 202, 119, 295, -53, +228, -145, 50, -156, -113, -127, -263, -13, +-325, 126, -227, 188, -58, 164, 97, 34, +181, -95, 137, -132, 75, -121, 32, -69, +-40, 48, -75, 141, -55, 159, -41, 71, +-27, -82, -70, -168, -115, -147, -60, -77, +7, 56, 41, 195, 94, 248, 90, 161, +33, -39, -48, -231, -154, -275, -170, -187, +-65, -21, 26, 175, 96, 302, 113, 266, +50, 78, -26, -160, -113, -284, -173, -229, +-91, -51, 8, 153, 38, 304, 38, 291, +-8, 96, -52, -184, -38, -383, -22, -377, +43, -164, 117, 134, 72, 398, -35, 502, +-138, 361, -220, 30, -174, -316, -64, -512, +47, -453, 173, -198, 204, 125, 80, 384, +-70, 452, -180, 274, -177, -15, -65, -259, +41, -328, 115, -186, 132, 54, 6, 253, +-154, 324, -228, 173, -182, -114, -24, -354, +138, -414, 190, -247, 156, 74, 37, 350, +-131, 475, -224, 378, -187, 80, -52, -227, +102, -380, 149, -334, 96, -108, 0, 124, +-125, 231, -224, 195, -199, 30, -73, -154, +91, -194, 205, -96, 203, 96, 107, 258, +-25, 262, -168, 140, -244, -30, -210, -206, +-91, -266, 52, -197, 139, -73, 114, 58, +39, 117, -53, 99, -137, 99, -139, 84, +-36, 55, 91, 40, 172, 3, 140, -55, +12, -95, -135, -118, -251, -64, -284, 45, +-175, 95, 7, 80, 182, 24, 258, -64, +182, -92, 31, -56, -96, 34, -173, 150, +-159, 182, -67, 84, 29, -56, 57, -189, +-5, -226, -103, -127, -132, 46, -93, 217, +-18, 283, 88, 165, 166, -48, 159, -243, +72, -330, -80, -241, -199, -8, -219, 248, +-175, 424, -103, 391, 9, 168, 115, -109, +169, -332, 133, -417, 28, -317, -67, -98, +-129, 140, -175, 280, -143, 265, -29, 162, +87, 57, 137, -35, 101, -73, -10, -63, +-115, -36, -191, -35, -195, -76, -83, -116, +83, -86, 198, -5, 203, 79, 74, 143, +-98, 168, -226, 140, -280, 54, -219, -64, +-20, -134, 169, -137, 253, -98, 212, -51, +66, 27, -103, 126, -240, 188, -305, 153, +-218, 38, -35, -101, 119, -216, 201, -277, +189, -225, 82, -13, -38, 271, -156, 440, +-209, 414, -137, 209, -16, -80, 62, -357, +78, -513, 10, -449, -80, -161, -138, 165, +-136, 357, -23, 379, 162, 276, 248, 117, +199, -37, 20, -139, -226, -118, -388, -47, +-387, -53, -222, -136, 69, -199, 318, -183, +389, -67, 267, 85, 20, 245, -215, 380, +-303, 359, -263, 155, -115, -97, 57, -282, +117, -330, 48, -269, -60, -150, -137, 22, +-107, 183, 16, 208, 137, 161, 198, 108, +154, 73, -20, 52, -206, -11, -316, -94, +-302, -115, -159, -121, 14, -124, 142, -58, +231, 54, 228, 146, 127, 167, -6, 75, +-129, -18, -214, -68, -237, -106, -224, -98, +-124, -17, 37, 69, 156, 127, 202, 107, +164, 41, 38, 23, -94, 4, -186, -59, +-209, -103, -115, -130, 20, -124, 72, -75, +53, -3, -28, 126, -102, 285, -107, 308, +-54, 189, 54, 3, 167, -200, 155, -321, +23, -327, -145, -222, -285, 2, -314, 196, +-199, 244, -7, 200, 211, 129, 327, 58, +275, 32, 101, 1, -127, -16, -313, -30, +-364, -114, -283, -209, -93, -202, 128, -97, +244, 67, 203, 202, 80, 229, -72, 182, +-170, 81, -175, -63, -87, -115, 40, -64, +116, 17, 69, 60, -58, 1, -182, -124, +-238, -194, -177, -194, -10, -95, 164, 127, +276, 332, 239, 404, 49, 307, -196, 49, +-350, -206, -347, -346, -190, -353, 52, -220, +255, 4, 312, 171, 183, 239, -67, 185, +-268, 58, -333, -9, -238, -19, -29, -12, +173, 18, 247, 14, 176, -40, -16, -100, +-207, -148, -264, -127, -179, 0, -12, 112, +148, 187, 189, 206, 116, 133, -54, 28, +-246, -72, -313, -159, -216, -162, -40, -108, +159, -66, 285, 2, 268, 86, 135, 145, +-79, 193, -280, 157, -341, 54, -282, -56, +-139, -171, 28, -240, 148, -190, 200, -75, +173, 66, 43, 177, -76, 170, -106, 111, +-103, 60, -72, 16, -31, 37, -19, 69, +-20, 35, -88, -54, -177, -190, -180, -317, +-89, -284, 44, -103, 199, 159, 279, 417, +247, 502, 104, 374, -156, 101, -386, -243, +-438, -477, -342, -487, -122, -321, 131, -51, +317, 211, 368, 330, 242, 341, -18, 245, +-221, 79, -303, -46, -278, -117, -135, -155, +35, -141, 137, -112, 138, -70, 5, 9, +-145, 65, -185, 90, -112, 121, 29, 101, +180, 64, 223, 22, 135, -36, -76, -73, +-339, -77, -452, -92, -333, -79, -75, -30, +229, 24, 431, 95, 434, 135, 230, 120, +-117, 90, -443, 13, -545, -81, -412, -133, +-135, -132, 165, -78, 345, 29, 363, 104, +223, 148, -47, 153, -262, 71, -305, -36, +-217, -115, -83, -142, 40, -83, 100, 13, +90, 83, -3, 120, -121, 87, -142, -28, +-71, -118, 8, -137, 63, -58, 68, 86, +50, 184, -3, 192, -91, 111, -167, -51, +-154, -204, -91, -243, -37, -149, 18, 44, +77, 221, 110, 264, 58, 194, -73, 30, +-156, -158, -158, -260, -110, -216, -39, -66, +77, 113, 160, 205, 138, 187, -4, 106, +-184, -24, -263, -141, -224, -173, -129, -121, +15, -12, 174, 77, 262, 121, 184, 130, +-17, 112, -217, 39, -281, -46, -248, -101, +-150, -98, 28, -52, 196, -2, 238, 50, +113, 98, -101, 97, -252, 32, -269, -54, +-186, -91, -32, -71, 175, -17, 285, 31, +229, 80, 9, 87, -245, 38, -361, -48, +-326, -108, -182, -84, 52, -12, 277, 60, +344, 108, 202, 116, -59, 70, -285, -27, +-347, -114, -281, -125, -94, -43, 155, 51, +311, 121, 271, 138, 46, 87, -244, -14, +-411, -136, -374, -206, -187, -151, 91, -12, +359, 124, 435, 217, 267, 226, -71, 137, +-374, -7, -478, -171, -394, -237, -180, -179, +109, -68, 322, 49, 334, 142, 155, 171, +-93, 152, -253, 88, -235, -1, -125, -31, +18, -33, 137, -54, 135, -65, -11, -85, +-223, -83, -350, -51, -264, -20, -41, 35, +178, 128, 336, 161, 379, 137, 203, 83, +-110, -15, -415, -85, -551, -132, -435, -171, +-172, -121, 126, -23, 386, 65, 472, 148, +320, 185, 10, 150, -299, 92, -447, -29, +-381, -134, -223, -142, 14, -110, 240, -34, +296, 57, 169, 81, -48, 68, -210, 21, +-227, -63, -145, -72, -21, 2, 123, 70, +176, 140, 49, 114, -144, -10, -308, -127, +-307, -222, -134, -220, 81, -48, 266, 171, +351, 336, 245, 371, -19, 191, -299, -70, +-457, -276, -405, -395, -202, -304, 16, -64, +231, 165, 323, 308, 238, 284, 51, 112, +-139, -26, -237, -107, -203, -123, -105, -30, +-12, 33, 60, 23, 43, -32, -63, -142, +-165, -172, -220, -62, -145, 87, 8, 235, +149, 327, 245, 253, 256, 102, 116, -85, +-116, -257, -322, -281, -425, -203, -364, -104, +-182, 28, 40, 117, 252, 152, 333, 182, +257, 150, 78, 92, -114, 69, -236, -16, +-242, -112, -187, -178, -95, -223, 8, -181, +43, -74, 5, 25, -36, 161, -55, 275, +-21, 269, 25, 202, 46, 76, 56, -82, +31, -176, -58, -251, -148, -255, -201, -136, +-195, 7, -106, 114, 21, 198, 122, 202, +189, 170, 151, 102, 14, -37, -149, -127, +-265, -148, -264, -155, -151, -109, -3, -28, +131, 56, 196, 128, 136, 126, -4, 53, +-130, 26, -219, 6, -200, -13, -109, 4, +-6, 19, 80, 32, 105, 20, 58, -54, +-32, -95, -129, -53, -185, -3, -139, 33, +-31, 62, 75, 50, 167, 38, 140, -6, +12, -46, -157, -9, -294, 59, -313, 75, +-187, 32, 11, -43, 188, -105, 279, -114, +218, -94, 53, -11, -145, 141, -300, 229, +-291, 208, -188, 96, -47, -40, 88, -149, +161, -204, 122, -205, 12, -93, -105, 89, +-162, 205, -110, 218, -40, 144, 22, 17, +68, -117, 29, -230, -47, -239, -134, -96, +-164, 117, -98, 243, 15, 259, 63, 161, +58, -5, 16, -181, -78, -291, -155, -231, +-180, -14, -95, 195, 70, 275, 170, 230, +181, 89, 108, -86, -46, -215, -240, -244, +-363, -111, -364, 82, -205, 184, 40, 158, +244, 75, 359, -33, 336, -115, 157, -138, +-106, -85, -341, 52, -426, 150, -353, 127, +-186, 53, 0, -30, 169, -88, 230, -107, +154, -73, 26, 21, -60, 153, -79, 191, +-65, 128, -50, 30, -35, -90, -55, -182, +-124, -212, -202, -157, -196, 12, -92, 194, +52, 258, 162, 211, 189, 96, 135, -76, +26, -206, -124, -259, -213, -178, -183, 18, +-84, 169, -19, 200, -14, 150, -54, 33, +-94, -93, -114, -143, -96, -100, 15, 56, +155, 227, 214, 250, 172, 147, 22, -40, +-157, -242, -308, -360, -379, -336, -326, -155, +-128, 154, 102, 405, 255, 466, 299, 363, +215, 113, 75, -192, -98, -420, -256, -493, +-285, -335, -220, -23, -124, 257, -40, 403, +39, 396, 76, 212, 86, -39, 38, -253, +-25, -328, -23, -196, -21, 28, -22, 206, +-31, 279, -54, 200, -58, -3, -89, -221, +-151, -336, -178, -269, -109, -28, -28, 211, +63, 349, 143, 324, 182, 139, 163, -114, +30, -314, -136, -350, -245, -177, -285, 92, +-252, 289, -157, 336, -13, 213, 119, -27, +200, -242, 149, -332, 52, -220, -32, 28, +-105, 265, -133, 353, -109, 268, -37, 56, +12, -184, -35, -326, -140, -306, -200, -128, +-172, 102, -90, 250, 61, 255, 213, 134, +294, -29, 222, -160, 12, -175, -207, -84, +-329, 57, -334, 153, -248, 139, -97, 33, +72, -82, 173, -138, 157, -99, 65, 33, +-1, 168, -28, 224, -47, 157, -65, -34, +-52, -225, -37, -319, -66, -259, -137, -55, +-176, 202, -150, 366, -72, 383, 15, 225, +105, -50, 176, -284, 174, -396, 72, -339, +-91, -123, -219, 109, -237, 274, -176, 331, +-79, 251, 22, 86, 98, -64, 66, -173, +-35, -166, -129, -80, -134, -5, -46, 68, +51, 86, 125, 24, 142, -46, 67, -99, +-78, -92, -230, 10, -306, 118, -263, 167, +-117, 173, 19, 67, 149, -81, 225, -185, +203, -216, 101, -116, -55, 54, -167, 160, +-213, 188, -226, 131, -197, -14, -93, -124, +36, -144, 104, -66, 121, 103, 58, 201, +0, 178, -53, 75, -104, -88, -96, -233, +-33, -265, 36, -195, 36, -23, -41, 170, +-140, 241, -170, 223, -149, 151, -96, 28, +45, -62, 156, -108, 186, -105, 93, -53, +-69, -35, -183, -81, -214, -89, -178, -63, +-79, 6, 54, 131, 125, 245, 107, 325, +3, 302, -119, 105, -147, -168, -138, -383, +-96, -476, -23, -403, 67, -180, 120, 109, +97, 397, 17, 518, -59, 419, -113, 207, +-172, -32, -186, -230, -130, -328, -41, -319, +48, -213, 73, -61, 66, 36, 53, 97, +26, 178, -24, 235, -56, 243, -61, 178, +-57, 65, -89, -58, -142, -177, -144, -270, +-91, -247, -37, -100, 15, 64, 65, 169, +115, 177, 118, 111, 50, 21, -47, -78, +-118, -121, -166, -56, -181, 71, -167, 144, +-84, 140, 39, 60, 123, -42, 113, -118, +45, -158, -35, -123, -114, -3, -168, 102, +-142, 117, -15, 68, 116, 5, 129, -20, +40, 9, -100, 42, -194, 104, -223, 141, +-155, 66, 7, -99, 183, -250, 231, -311, +107, -230, -81, -58, -219, 141, -237, 336, +-167, 404, -35, 285, 135, 72, 194, -148, +107, -272, -68, -268, -181, -183, -182, -39, +-114, 126, -27, 185, 59, 140, 112, 59, +46, -24, -77, -54, -160, -58, -142, -56, +-32, -5, 51, 47, 112, 50, 135, 42, +99, 31, -37, 13, -191, 8, -262, -44, +-227, -86, -129, -68, -32, -50, 100, -30, +212, 13, 211, 52, 111, 99, -35, 122, +-131, 95, -182, 91, -183, 97, -143, 42, +-40, -33, 47, -132, 45, -214, -16, -234, +-93, -206, -119, -96, -97, 111, -32, 290, +94, 367, 208, 326, 218, 152, 86, -56, +-97, -234, -257, -348, -316, -297, -283, -122, +-166, 61, 8, 182, 135, 205, 164, 135, +114, 44, 50, -53, 15, -95, 6, -32, +5, 49, 0, 92, -10, 75, -75, -3, +-178, -70, -262, -103, -259, -99, -169, -29, +-22, 70, 133, 103, 262, 65, 298, -39, +210, -137, 38, -149, -143, -81, -251, 59, +-256, 236, -182, 344, -69, 311, 29, 134, +70, -123, 23, -341, -57, -433, -112, -384, +-78, -183, 13, 85, 125, 311, 208, 406, +209, 344, 108, 182, -80, 10, -267, -127, +-371, -191, -345, -173, -194, -116, 18, -71, +224, -63, 317, -74, 275, -45, 102, 19, +-97, 107, -220, 182, -230, 212, -137, 174, +-16, 67, 79, -70, 81, -158, 0, -158, +-92, -94, -136, 2, -96, 80, -24, 102, +57, 68, 78, -31, 44, -129, -34, -163, +-119, -119, -144, -13, -98, 123, 18, 226, +122, 276, 160, 235, 110, 89, -16, -85, +-170, -235, -308, -317, -319, -291, -212, -182, +-15, -4, 169, 183, 278, 286, 291, 277, +189, 195, 25, 52, -154, -79, -258, -157, +-258, -171, -185, -91, -82, 17, -1, 77, +74, 89, 83, 40, 41, -48, -26, -115, +-54, -143, -35, -105, -4, 18, 37, 120, +81, 172, 106, 178, 58, 123, -47, 49, +-151, -11, -223, -58, -227, -60, -176, -53, +-55, -96, 97, -148, 221, -176, 235, -153, +157, -25, 43, 141, -68, 295, -147, 381, +-165, 310, -111, 91, -30, -162, -1, -365, +-34, -405, -71, -260, -75, -31, -50, 207, +11, 338, 81, 269, 147, 75, 142, -147, +54, -282, -65, -235, -136, -52, -153, 162, +-126, 338, -73, 346, -9, 177, 42, -61, +24, -281, -38, -362, -69, -267, -53, -92, +-3, 104, 44, 229, 88, 195, 91, 59, +34, -80, -90, -151, -184, -73, -184, 84, +-109, 226, 8, 299, 97, 218, 128, -8, +79, -259, -49, -438, -179, -441, -232, -249, +-165, 25, -46, 297, 97, 483, 199, 471, +238, 301, 168, 45, -8, -206, -182, -342, +-287, -348, -285, -261, -186, -89, -17, 81, +159, 179, 238, 207, 189, 154, 23, 64, +-129, -5, -204, -69, -164, -87, -41, -47, +106, -6, 220, 17, 201, 26, 60, 6, +-128, 4, -248, 29, -262, 55, -192, 94, +-45, 99, 103, 24, 216, -103, 210, -235, +124, -294, 19, -216, -55, -22, -89, 221, +-104, 426, -75, 460, -30, 295, 6, 3, +-9, -298, -54, -458, -71, -416, -69, -219, +-38, 44, 0, 248, 80, 286, 142, 178, +136, 12, 48, -110, -56, -102, -118, 5, +-138, 142, -108, 227, -36, 197, 39, 45, +49, -148, -38, -297, -156, -328, -216, -229, +-157, -64, -21, 99, 165, 208, 322, 222, +360, 166, 208, 86, -79, 27, -344, 12, +-451, 32, -385, 38, -193, 18, 52, -41, +236, -137, 267, -228, 143, -263, -32, -208, +-118, -56, -85, 137, 16, 299, 99, 376, +128, 328, 52, 161, -101, -43, -255, -212, +-289, -284, -164, -242, 22, -134, 166, -17, +219, 62, 181, 70, 65, 25, -73, -20, +-146, -32, -131, 14, -43, 92, 24, 151, +72, 181, 95, 160, 87, 84, 36, -20, +-53, -125, -133, -209, -178, -237, -168, -219, +-104, -144, 18, -6, 175, 137, 267, 236, +255, 270, 126, 210, -21, 91, -140, -30, +-200, -112, -176, -120, -87, -65, 14, -26, +42, -29, 2, -89, -62, -170, -85, -187, +-39, -97, 37, 78, 142, 286, 201, 402, +195, 349, 84, 147, -77, -130, -199, -349, +-239, -388, -194, -253, -119, -15, -19, 195, +48, 258, 55, 163, 13, -24, -30, -202, +-7, -236, 45, -104, 119, 103, 144, 281, +118, 319, 18, 190, -135, -24, -273, -230, +-327, -316, -250, -229, -96, -43, 78, 128, +201, 209, 240, 151, 186, 9, 56, -128, +-61, -191, -122, -115, -106, 65, -64, 233, +-14, 306, 19, 239, 21, 52, -18, -165, +-77, -333, -107, -379, -92, -262, -38, -57, +29, 142, 97, 269, 162, 282, 187, 205, +149, 83, 56, -36, -44, -93, -128, -86, +-166, -61, -170, -46, -114, -49, -31, -72, +45, -77, 89, -55, 105, 9, 115, 105, +122, 175, 110, 170, 63, 91, -3, -43, +-72, -178, -134, -245, -159, -204, -134, -55, +-29, 149, 93, 304, 176, 342, 179, 232, +107, 8, -24, -242, -167, -414, -248, -430, +-220, -268, -73, 5, 115, 273, 242, 432, +273, 422, 177, 259, 7, 23, -178, -187, +-277, -290, -247, -260, -119, -145, 19, -26, +88, 54, 86, 62, 27, 17, -43, -31, +-78, -36, -47, 15, 56, 104, 128, 173, +135, 183, 50, 123, -60, 5, -171, -128, +-248, -218, -242, -238, -149, -164, 6, -29, +125, 107, 187, 196, 188, 208, 145, 126, +69, -10, -35, -140, -83, -200, -95, -144, +-74, -5, -83, 143, -90, 234, -71, 206, +-38, 65, 5, -119, 45, -258, 110, -275, +145, -157, 132, 8, 74, 145, 7, 202, +-21, 161, -47, 71, -50, -1, -44, -15, +-15, 31, -6, 69, -16, 34, -24, -62, +-2, -177, 48, -248, 78, -207, 97, -62, +99, 131, 73, 279, 17, 294, -54, 176, +-82, 2, -62, -152, -19, -207, 7, -148, +31, -29, 39, 82, 38, 113, 20, 39, +6, -70, 5, -144, -4, -141, -39, -46, +-79, 103, -86, 231, -47, 281, 19, 216, +72, 55, 101, -131, 97, -287, 29, -351, +-66, -291, -148, -133, -161, 77, -117, 268, +-40, 361, 26, 329, 72, 186, 75, -29, +29, -223, -29, -321, -63, -299, -42, -163, +14, 22, 51, 171, 54, 240, 6, 208, +-77, 92, -162, -33, -192, -117, -146, -136, +-21, -85, 117, -14, 200, 44, 216, 66, +151, 46, 29, 5, -93, -25, -172, -41, +-158, -30, -80, 0, 25, 18, 98, 32, +128, 34, 90, 17, 0, 0, -89, -19, +-134, -31, -84, -22, 21, -9, 142, -3, +229, 15, 220, 31, 126, 31, -31, 21, +-142, 2, -174, -2, -96, 15, 11, 23, +94, 27, 117, 21, 58, -18, -20, -73, +-81, -116, -56, -122, 41, -67, 145, 21, +188, 106, 139, 166, 49, 165, -68, 95, +-131, 0, -146, -85, -84, -125, -8, -111, +28, -77, 23, -38, -16, 1, -29, 8, +-14, 6, 39, 20, 95, 58, 128, 108, +111, 129, 27, 92, -73, 24, -170, -66, +-205, -153, -196, -177, -144, -128, -63, -34, +36, 66, 114, 120, 150, 122, 148, 85, +106, 14, 47, -52, -30, -70, -99, -50, +-124, -14, -113, 14, -89, 20, -72, 16, +-59, 7, -50, -9, -30, -4, -11, 23, +40, 41, 111, 46, 166, 33, 159, 0, +101, -40, 16, -90, -72, -122, -137, -110, +-152, -57, -93, 29, 10, 137, 88, 223, +110, 242, 77, 168, 14, 13, -56, -171, +-77, -311, -23, -351, 103, -253, 230, -47, +275, 183, 214, 341, 71, 372, -115, 267, +-268, 79, -318, -123, -226, -262, -41, -291, +158, -224, 285, -107, 321, 17, 269, 112, +141, 163, -8, 176, -124, 149, -169, 93, +-156, 26, -118, -58, -55, -134, 6, -172, +57, -163, 63, -104, 65, -12, 63, 71, +76, 131, 65, 153, 17, 126, -23, 68, +-62, 0, -78, -67, -85, -104, -50, -112, +6, -91, 43, -35, 42, 30, -5, 74, +-38, 87, -87, 47, -109, -30, -118, -89, +-85, -114, -11, -80, 64, 14, 131, 118, +163, 190, 164, 189, 85, 100, -45, -27, +-183, -146, -268, -226, -259, -217, -194, -132, +-53, -18, 99, 93, 221, 152, 252, 155, +207, 131, 117, 77, 24, 22, -54, -3, +-129, -21, -149, -51, -132, -90, -93, -138, +-37, -149, 35, -108, 127, -28, 194, 86, +208, 183, 160, 193, 96, 115, 11, -23, +-62, -150, -101, -178, -85, -105, -29, 42, +27, 196, 57, 241, 74, 142, 82, -59, +73, -263, 55, -344, 39, -256, 38, -57, +49, 171, 41, 307, 28, 271, 25, 112, +26, -61, 3, -139, -21, -78, -40, 54, +-40, 155, -38, 136, -32, -41, -1, -300, +57, -465, 95, -414, 94, -132, 64, 267, +10, 595, -58, 699, -116, 510, -139, 96, +-96, -353, -9, -636, 63, -644, 88, -399, +71, -39, 24, 268, -35, 414, -88, 352, +-94, 151, -63, -50, -30, -155, -28, -129, +-26, -11, -19, 112, 4, 162, 32, 99, +47, -52, 55, -212, 26, -295, -29, -264, +-91, -122, -112, 71, -76, 239, -15, 314, +60, 267, 109, 128, 141, -29, 99, -135, +15, -154, -77, -97, -126, -12, -109, 38, +-59, 12, 32, -78, 114, -183, 176, -236, +169, -176, 105, -1, 22, 236, -54, 419, +-72, 449, -62, 305, 1, 33, 70, -264, +130, -456, 140, -463, 107, -296, 57, -29, +-9, 195, -50, 281, -70, 224, -39, 74, +21, -68, 90, -105, 140, -22, 142, 123, +111, 223, 33, 185, -45, 17, -107, -210, +-102, -393, -45, -409, 36, -232, 104, 54, +127, 332, 94, 464, 10, 387, -76, 153, +-125, -140, -106, -354, -36, -375, 41, -225, +97, 22, 96, 253, 41, 343, -49, 271, +-125, 75, -158, -168, -120, -328, -44, -338, +38, -213, 100, 6, 118, 217, 90, 325, +34, 302, -33, 149, -80, -56, -107, -201, +-126, -244, -136, -177, -124, -30, -87, 97, +-15, 147, 78, 102, 170, -20, 228, -123, +213, -146, 108, -89, -42, 45, -191, 181, +-266, 232, -231, 174, -97, 26, 67, -143, +199, -234, 234, -227, 169, -131, 58, 15, +-37, 121, -64, 146, -25, 104, 43, 21, +91, -37, 90, -43, 33, -17, -48, 28, +-90, 58, -82, 40, 2, 1, 102, -41, +188, -70, 213, -60, 170, -36, 73, -17, +-33, 4, -84, 7, -73, 7, -8, 31, +45, 59, 66, 77, 44, 72, -14, 20, +-59, -42, -71, -87, -7, -107, 81, -73, +164, -10, 179, 34, 142, 47, 62, 24, +-43, -19, -120, -35, -160, -19, -135, 26, +-93, 86, -49, 97, -6, 44, 45, -39, +88, -109, 87, -116, 79, -48, 49, 55, +26, 145, -23, 155, -76, 49, -111, -115, +-132, -250, -139, -282, -130, -175, -69, 39, +25, 273, 121, 418, 166, 382, 146, 169, +86, -118, -19, -362, -120, -457, -179, -356, +-141, -110, -46, 168, 48, 349, 81, 351, +57, 198, -8, -17, -86, -199, -112, -265, +-45, -184, 92, -12, 216, 152, 251, 217, +188, 159, 65, 33, -69, -95, -172, -173, +-187, -162, -118, -73, -22, 26, 40, 73, +65, 45, 86, -22, 133, -64, 170, -44, +187, 40, 182, 157, 143, 239, 44, 216, +-86, 80, -191, -120, -210, -297, -144, -367, +-40, -294, 84, -100, 202, 140, 268, 313, +248, 340, 153, 225, 34, 25, -69, -167, +-134, -258, -167, -214, -124, -53, -38, 134, +50, 243, 94, 220, 94, 74, 69, -137, +22, -301, -37, -335, -76, -226, -47, -11, +9, 211, 58, 340, 75, 333, 58, 194, +23, -4, -49, -152, -114, -204, -145, -153, +-111, -42, -69, 37, -34, 41, -14, -40, +12, -165, 43, -227, 54, -163, 81, 10, +102, 246, 94, 431, 26, 454, -72, 289, +-144, -18, -173, -334, -152, -502, -108, -477, +-15, -275, 64, 21, 122, 255, 132, 339, +121, 263, 108, 84, 69, -64, 6, -102, +-69, -44, -109, 69, -117, 149, -81, 107, +-5, -26, 85, -189, 161, -289, 160, -248, +108, -100, 24, 76, -31, 214, -54, 237, +-33, 145, 29, 14, 93, -91, 125, -99, +101, -14, 51, 87, 4, 154, -19, 134, +-22, 10, -16, -155, 9, -291, 22, -337, +28, -240, 29, -48, 54, 174, 89, 364, +120, 426, 126, 327, 103, 119, 49, -138, +-32, -333, -112, -384, -156, -294, -153, -93, +-97, 126, -16, 241, 63, 224, 119, 100, +126, -66, 91, -163, 48, -153, 10, -43, +-9, 118, -15, 222, -24, 214, -52, 111, +-87, -48, -126, -185, -129, -228, -105, -184, +-48, -83, 20, 19, 81, 67, 110, 69, +101, 50, 72, 29, 28, 44, -9, 90, +-54, 121, -92, 115, -104, 43, -95, -77, +-63, -185, -29, -245, 9, -223, 29, -112, +43, 40, 37, 175, 50, 246, 84, 219, +118, 123, 124, 6, 78, -94, 1, -133, +-92, -113, -164, -72, -186, -39, -132, -38, +-25, -54, 84, -57, 178, -19, 228, 59, +240, 160, 187, 224, 98, 203, -5, 88, +-82, -83, -129, -240, -139, -311, -95, -264, +-18, -115, 69, 79, 116, 230, 136, 275, +130, 218, 96, 93, 43, -37, -13, -120, +-25, -134, -12, -97, 21, -39, 38, -4, +56, -9, 50, -35, 8, -65, -46, -69, +-79, -27, -57, 44, -14, 125, 36, 186, +70, 188, 80, 128, 54, 16, -6, -126, +-48, -229, -60, -255, -32, -201, -12, -68, +-4, 86, -5, 193, -11, 220, -29, 155, +-41, 35, -16, -69, 28, -120, 47, -96, +28, -10, -11, 64, -40, 81, -63, 28, +-67, -77, -45, -155, 3, -162, 40, -101, +45, 26, 27, 159, 7, 221, -11, 197, +-29, 91, -49, -42, -43, -122, -26, -148, +-2, -117, 18, -38, 50, 24, 81, 37, +90, 17, 67, -22, 28, -32, 4, -1, +-20, 38, -42, 94, -47, 129, -34, 95, +2, 12, 31, -90, 60, -168, 82, -180, +103, -133, 82, -43, 47, 77, 17, 157, +7, 164, 21, 118, 36, 34, 53, -40, +63, -77, 40, -79, -18, -38, -70, 11, +-87, 15, -72, -12, -15, -49, 54, -74, +136, -49, 181, 8, 170, 70, 100, 126, +9, 125, -79, 55, -132, -32, -137, -108, +-96, -143, -16, -111, 39, -41, 57, 44, +53, 117, 37, 131, 21, 92, 15, 16, +21, -71, 18, -128, 10, -135, -29, -98, +-52, -12, -56, 86, -46, 152, -31, 171, +-17, 122, -6, 21, -10, -80, -21, -155, +-33, -174, -19, -118, 14, -34, 50, 39, +87, 86, 96, 79, 84, 48, 27, 18, +-44, -3, -119, 12, -159, 45, -160, 59, +-117, 45, -25, -1, 75, -66, 153, -114, +182, -132, 163, -109, 116, -35, 53, 52, +-4, 121, -49, 155, -64, 136, -77, 74, +-81, -6, -73, -87, -44, -131, 2, -114, +54, -65, 101, -4, 142, 48, 154, 61, +129, 43, 80, -2, 36, -46, -5, -48, +-38, -8, -63, 40, -65, 85, -46, 98, +-31, 62, -17, 0, 4, -74, 29, -117, +49, -100, 65, -58, 99, -8, 131, 41, +148, 56, 112, 40, 40, 17, -60, -4, +-157, 8, -226, 43, -234, 67, -156, 66, +-25, 25, 108, -56, 194, -135, 226, -178, +205, -158, 125, -57, 17, 77, -82, 187, +-130, 239, -154, 196, -155, 79, -135, -63, +-85, -173, -32, -199, 5, -138, 46, -42, +94, 50, 136, 97, 141, 66, 108, -3, +48, -60, -29, -76, -101, -29, -148, 51, +-133, 120, -67, 150, 8, 116, 40, 25, +48, -72, 36, -148, 21, -177, 11, -150, +28, -90, 72, -12, 111, 62, 110, 109, +56, 137, -9, 145, -68, 114, -104, 61, +-101, -2, -59, -68, 21, -118, 83, -147, +111, -150, 103, -113, 97, -53, 70, 20, +30, 104, -2, 172, -14, 193, -4, 158, +-4, 60, -3, -67, 13, -167, 28, -214, +25, -177, -1, -62, -21, 69, -25, 153, +-1, 165, 21, 105, 66, 14, 118, -63, +136, -99, 94, -71, 5, -13, -86, 21, +-144, 17, -157, -18, -118, -46, -28, -34, +75, 17, 120, 84, 110, 131, 66, 101, +17, 1, -29, -116, -61, -195, -62, -178, +-31, -64, -3, 85, 1, 203, -6, 228, +-8, 133, -13, -24, -15, -166, -27, -227, +-21, -172, -11, -42, -12, 95, -17, 185, +-4, 182, 26, 97, 45, -14, 45, -104, +30, -139, 8, -110, -19, -60, -59, -12, +-71, 30, -58, 53, -20, 69, 19, 81, +57, 79, 85, 62, 98, 18, 84, -58, +50, -132, 23, -159, -3, -129, -31, -38, +-51, 77, -54, 164, -20, 188, 21, 131, +55, 14, 78, -103, 98, -175, 89, -180, +59, -111, 21, -9, 5, 82, 10, 132, +18, 118, 18, 62, 18, 3, 5, -35, +-22, -48, -32, -39, -9, -25, 37, -13, +82, -11, 92, -22, 75, -22, 34, -5, +-16, 13, -62, 29, -68, 38, -43, 29, +-1, 14, 26, 0, 34, -7, 33, 6, +19, 18, -2, 15, -22, 1, -21, -24, +-10, -51, 2, -66, 12, -63, -1, -35, +-18, 10, -54, 40, -85, 61, -92, 74, +-55, 72, 10, 60, 85, 40, 140, 7, +135, -26, 65, -62, -63, -98, -184, -107, +-232, -92, -190, -59, -65, -4, 91, 51, +216, 97, 239, 126, 154, 115, -6, 75, +-159, 30, -232, -23, -198, -66, -71, -84, +84, -89, 186, -76, 192, -54, 110, -36, +2, -1, -71, 42, -78, 75, -40, 102, +20, 102, 56, 64, 40, 6, -3, -62, +-32, -111, -4, -104, 73, -57, 152, 18, +192, 87, 156, 97, 47, 47, -104, -41, +-214, -138, -230, -174, -136, -122, 30, -12, +210, 129, 335, 236, 345, 249, 228, 175, +27, 27, -167, -143, -276, -253, -279, -279, +-173, -217, -6, -79, 153, 71, 228, 187, +208, 240, 115, 206, 9, 118, -72, 13, +-105, -91, -77, -150, -15, -154, 31, -116, +37, -46, 3, 20, -38, 54, -65, 68, +-64, 56, -32, 24, 31, 3, 75, -11, +70, -16, 11, -8, -59, -8, -102, -7, +-94, 10, -52, 24, 20, 34, 88, 39, +99, 16, 45, -18, -47, -62, -133, -106, +-172, -109, -147, -74, -57, -18, 73, 58, +182, 131, 203, 169, 152, 159, 45, 90, +-73, -15, -165, -119, -201, -201, -166, -223, +-71, -160, 40, -43, 121, 87, 165, 190, +153, 217, 101, 169, 37, 71, -26, -46, +-50, -124, -42, -141, -18, -114, 8, -63, +33, -16, 29, 16, 13, 36, 10, 40, +30, 44, 76, 66, 111, 77, 105, 55, +66, -1, 2, -77, -55, -140, -75, -154, +-41, -115, 34, -29, 120, 82, 157, 162, +125, 184, 52, 148, -39, 63, -108, -30, +-116, -111, -71, -162, 15, -163, 98, -121, +134, -57, 111, 18, 58, 83, -13, 121, +-62, 131, -67, 108, -40, 63, 3, 18, +18, -25, -9, -56, -49, -73, -73, -86, +-61, -95, -12, -93, 63, -76, 111, -29, +117, 43, 54, 113, -48, 163, -140, 172, +-177, 119, -148, 24, -64, -77, 28, -152, +94, -169, 113, -126, 77, -50, 15, 30, +-43, 76, -92, 71, -113, 34, -95, -11, +-38, -34, 26, -8, 78, 40, 88, 84, +62, 105, 10, 71, -41, -11, -71, -105, +-66, -171, -41, -167, -7, -89, 24, 20, +41, 122, 53, 169, 63, 131, 58, 40, +51, -62, 38, -125, 17, -102, -12, -17, +-29, 73, -29, 124, -5, 98, 20, -1, +42, -118, 65, -190, 78, -169, 79, -55, +68, 81, 39, 182, -3, 202, -36, 120, +-48, -13, -28, -126, 42, -168, 115, -108, +152, 12, 124, 110, 40, 141, -61, 85, +-132, -35, -144, -145, -76, -192, 42, -141, +143, -8, 190, 127, 171, 206, 90, 203, +-11, 112, -97, -22, -136, -133, -119, -183, +-66, -153, -23, -73, 1, 6, 11, 67, +23, 87, 55, 61, 91, 27, 103, 5, +90, -2, 29, 14, -67, 27, -156, 20, +-203, 5, -192, -30, -109, -70, 17, -82, +138, -65, 205, -15, 173, 54, 55, 96, +-82, 98, -185, 58, -212, -25, -153, -103, +-32, -134, 88, -101, 168, 2, 154, 124, +70, 198, -38, 191, -136, 88, -172, -84, +-125, -236, -26, -301, 78, -243, 141, -69, +133, 138, 72, 289, 1, 323, -60, 220, +-68, 36, -27, -142, 30, -246, 63, -232, +52, -127, 0, -6, -39, 77, -35, 90, +14, 40, 99, -12, 158, -25, 138, 7, +55, 68, -63, 109, -147, 87, -134, 9, +-33, -91, 103, -162, 213, -149, 224, -68, +144, 45, 26, 138, -93, 156, -167, 93, +-163, -9, -105, -107, -8, -147, 99, -109, +169, -26, 205, 65, 192, 124, 120, 125, +20, 79, -82, 13, -166, -54, -201, -93, +-174, -101, -97, -90, 25, -60, 127, -20, +164, 24, 153, 73, 112, 103, 52, 106, +-6, 84, -59, 37, -98, -26, -112, -74, +-114, -100, -103, -97, -51, -66, 2, -30, +38, 10, 61, 44, 66, 60, 53, 65, +26, 59, -25, 42, -60, 21, -52, -12, +-28, -52, -6, -73, 18, -75, 21, -53, +-5, -3, -59, 43, -113, 66, -123, 65, +-84, 30, -20, -17, 74, -43, 169, -41, +216, -13, 190, 33, 90, 57, -48, 44, +-155, -6, -226, -76, -235, -116, -163, -99, +-32, -38, 101, 55, 198, 135, 230, 157, +206, 116, 141, 18, 44, -96, -39, -165, +-66, -175, -68, -121, -79, -15, -100, 88, +-100, 147, -59, 154, 25, 102, 111, 24, +190, -52, 224, -106, 172, -112, 58, -73, +-52, -23, -117, 29, -121, 58, -83, 53, +-15, 27, 66, -7, 114, -34, 86, -32, +24, -20, -22, -3, -34, 19, -20, 29, +13, 25, 46, 27, 75, 23, 65, 15, +23, 1, -19, -33, -45, -72, -62, -96, +-58, -92, -34, -38, 8, 50, 46, 131, +43, 177, 11, 153, -4, 59, -11, -54, +-17, -152, -14, -195, 4, -158, 19, -71, +20, 30, -12, 107, -39, 120, -36, 84, +-34, 39, -40, 2, -27, -14, -5, -8, +12, -6, 17, -13, 11, -32, 17, -58, +33, -59, 17, -31, -6, 8, -22, 48, +-38, 60, -49, 32, -47, -10, -35, -39, +0, -37, 29, 9, 39, 65, 52, 97, +60, 80, 37, -1, -2, -115, -42, -195, +-60, -200, -39, -110, -2, 45, 28, 195, +54, 277, 56, 246, 47, 103, 42, -79, +36, -224, 17, -275, -14, -208, -62, -63, +-81, 82, -47, 177, 10, 184, 70, 118, +120, 35, 125, -27, 92, -52, 34, -46, +-31, -42, -66, -56, -56, -77, -28, -90, +8, -60, 21, 20, 2, 105, -18, 162, +-13, 157, 17, 78, 84, -35, 146, -129, +159, -162, 117, -113, 17, -17, -119, 69, +-220, 105, -250, 74, -185, 0, -28, -59, +154, -75, 277, -33, 300, 46, 194, 103, +19, 103, -145, 54, -245, -32, -241, -108, +-129, -128, 7, -94, 110, -22, 148, 48, +102, 77, 27, 68, -32, 32, -60, -3, +-33, -10, 20, 8, 41, 29, 11, 45, +-53, 27, -117, -19, -116, -60, -52, -88, +49, -91, 146, -54, 177, -5, 108, 43, +-8, 78, -120, 87, -186, 85, -179, 76, +-110, 41, 4, -7, 136, -64, 205, -126, +182, -157, 86, -145, -35, -86, -127, 19, +-143, 130, -102, 199, -21, 204, 56, 132, +77, 13, 50, -96, 15, -167, -15, -176, +-20, -123, 8, -48, 52, 23, 97, 69, +104, 75, 43, 63, -40, 46, -107, 27, +-137, 19, -106, 17, -21, 11, 81, 4, +173, -15, 192, -43, 130, -69, 25, -94, +-84, -102, -156, -74, -134, -13, -34, 73, +89, 159, 171, 203, 153, 178, 55, 82, +-53, -61, -140, -188, -156, -242, -84, -201, +38, -80, 152, 61, 213, 153, 176, 169, +73, 104, -52, -3, -156, -81, -190, -84, +-135, -25, -24, 58, 90, 101, 147, 75, +122, -6, 51, -105, -20, -164, -59, -140, +-37, -48, 16, 78, 50, 168, 44, 171, +-3, 93, -78, -17, -127, -114, -126, -145, +-63, -96, 54, -2, 170, 88, 208, 130, +150, 100, 14, 17, -123, -79, -197, -146, +-188, -145, -114, -85, -5, 10, 80, 106, +116, 155, 111, 141, 78, 81, 27, -4, +-14, -79, -51, -110, -64, -94, -55, -43, +-43, 11, -32, 29, -10, 10, 8, -26, +23, -60, 30, -53, 25, 6, 30, 87, +52, 158, 59, 171, 49, 99, 9, -23, +-50, -158, -100, -248, -113, -238, -84, -136, +-6, 20, 77, 172, 128, 242, 146, 206, +127, 92, 68, -54, -7, -156, -76, -163, +-115, -88, -104, 34, -56, 126, 5, 131, +67, 56, 95, -64, 87, -173, 59, -197, +27, -122, 9, 19, 13, 165, 13, 238, +11, 202, 11, 91, 0, -54, -22, -159, +-41, -169, -52, -105, -23, -20, 40, 40, +96, 36, 122, -9, 106, -50, 38, -58, +-40, -4, -90, 92, -91, 166, -53, 185, +-1, 124, 31, 0, 58, -126, 72, -214, +51, -233, 7, -168, -32, -56, -51, 65, +-37, 164, -11, 201, 8, 172, 18, 94, +12, -18, -15, -112, -19, -149, 1, -121, +28, -33, 36, 72, 11, 126, -33, 104, +-69, 8, -95, -123, -86, -201, -28, -178, +53, -59, 117, 115, 125, 252, 72, 279, +-1, 187, -74, 12, -134, -162, -143, -248, +-93, -224, -18, -115, 60, 16, 108, 96, +114, 105, 82, 60, 16, -6, -59, -37, +-84, -15, -60, 37, -19, 95, 14, 120, +24, 87, 26, 16, 30, -76, 23, -159, +17, -192, 23, -169, 18, -94, -10, 25, +-26, 138, -17, 211, 26, 216, 61, 139, +60, 14, 36, -100, 14, -162, -10, -147, +-17, -73, -3, 8, 17, 56, 31, 49, +24, -3, -4, -51, -7, -61, 8, -20, +23, 61, 46, 128, 83, 135, 100, 80, +76, -16, 6, -109, -68, -145, -98, -115, +-85, -40, -52, 43, 3, 80, 50, 65, +71, 10, 78, -56, 71, -76, 61, -31, +58, 44, 31, 116, -21, 143, -73, 92, +-111, -11, -129, -126, -104, -203, -44, -188, +40, -89, 112, 42, 132, 155, 107, 201, +68, 157, 11, 56, -52, -56, -107, -124, +-136, -122, -118, -76, -66, -18, -19, 29, +19, 45, 41, 38, 43, 24, 31, 17, +37, 17, 62, 10, 82, -18, 52, -50, +-33, -62, -125, -41, -172, 8, -161, 59, +-86, 77, 24, 55, 121, -2, 160, -67, +138, -94, 79, -60, 22, 19, -30, 92, +-78, 105, -109, 54, -102, -35, -66, -115, +-17, -131, 28, -66, 85, 38, 143, 125, +158, 148, 110, 84, 36, -26, -48, -120, +-122, -153, -149, -107, -112, -13, -18, 82, +83, 133, 136, 118, 145, 55, 130, -10, +94, -66, 31, -87, -35, -73, -88, -49, +-95, -14, -87, 26, -68, 49, -9, 55, +79, 46, 141, 16, 154, -16, 117, -28, +49, -20, -26, 13, -92, 48, -122, 47, +-81, 7, -20, -57, 20, -119, 37, -125, +44, -63, 38, 40, 30, 140, 11, 179, +0, 132, 13, 27, 18, -81, -8, -129, +-33, -93, -50, -11, -60, 57, -61, 63, +-47, -9, -13, -107, 37, -161, 57, -121, +53, 16, 45, 180, 20, 280, -31, 264, +-79, 120, -103, -83, -79, -241, -28, -290, +14, -221, 47, -80, 61, 52, 26, 128, +-28, 136, -52, 98, -31, 62, 16, 55, +39, 60, 7, 59, -31, 19, -51, -64, +-45, -145, -10, -181, 43, -152, 69, -60, +58, 49, 12, 126, -36, 149, -43, 115, +-22, 57, 5, 15, 33, -2, 37, -4, +19, -15, -9, -53, -27, -99, -10, -130, +44, -122, 81, -46, 77, 74, 39, 176, +-12, 208, -50, 150, -55, 23, -26, -112, +32, -195, 71, -184, 72, -74, 45, 62, +15, 153, -4, 152, -1, 61, 16, -68, +33, -155, 31, -153, -4, -56, -40, 90, +-37, 185, -1, 174, 47, 62, 71, -89, +61, -192, 17, -184, -28, -72, -61, 83, +-56, 193, -19, 177, 19, 55, 42, -97, +49, -196, 45, -177, 31, -51, -5, 107, +-56, 203, -96, 173, -94, 35, -57, -116, +16, -191, 83, -143, 105, -3, 71, 134, +7, 177, -56, 97, -79, -62, -66, -197, +-38, -219, -11, -108, 3, 79, 0, 231, +3, 261, 6, 157, 16, -29, 33, -197, +43, -249, 27, -164, -15, -7, -86, 131, +-136, 163, -121, 82, -41, -45, 74, -133, +175, -122, 192, 0, 116, 158, -19, 249, +-144, 207, -188, 28, -127, -204, -13, -365, +90, -364, 118, -178, 67, 111, -16, 362, +-60, 449, -27, 318, 70, 33, 147, -246, +149, -383, 71, -313, -58, -77, -175, 184, +-214, 312, -156, 230, -19, -24, 128, -284, +216, -369, 221, -218, 157, 109, 41, 438, +-64, 557, -110, 374, -85, -36, -32, -464, +-1, -676, -10, -545, -34, -146, -55, 319, +-41, 597, 21, 542, 115, 208, 190, -204, +195, -450, 106, -384, -21, -65, -128, 293, +-187, 463, -193, 320, -129, -69, -17, -476, +90, -660, 148, -484, 140, -19, 71, 491, +-14, 768, -82, 667, -87, 243, -16, -273, +80, -617, 106, -625, 44, -315, -69, 107, +-166, 387, -191, 381, -132, 121, -6, -204, +131, -365, 196, -258, 163, 56, 65, 405, +-33, 553, -97, 385, -107, -16, -85, -440, +-33, -653, 12, -537, 17, -181, -9, 232, +-28, 510, -20, 512, 1, 255, 24, -86, +51, -322, 68, -341, 67, -165, 29, 76, +-15, 259, -37, 292, -38, 146, -56, -98, +-80, -303, -80, -359, -39, -245, 31, -19, +104, 220, 151, 381, 152, 386, 74, 225, +-48, -39, -132, -287, -126, -394, -49, -325, +44, -118, 85, 140, 78, 326, 37, 334, +-29, 159, -63, -101, -24, -302, 47, -314, +100, -150, 95, 98, 40, 312, -33, 361, +-91, 191, -117, -95, -75, -334, 32, -392, +138, -225, 177, 60, 123, 316, 7, 415, +-101, 274, -166, -41, -145, -337, -37, -452, +89, -321, 143, -11, 114, 304, 37, 474, +-29, 409, -59, 125, -60, -222, -32, -438, +21, -422, 50, -196, 32, 99, -17, 305, +-52, 336, -63, 175, -60, -74, -41, -245, +24, -236, 102, -61, 139, 161, 97, 281, +-2, 238, -108, 53, -173, -207, -183, -380, +-107, -346, 39, -123, 170, 173, 187, 382, +105, 391, -13, 224, -114, -43, -153, -301, +-113, -395, -13, -274, 103, -27, 138, 211, +66, 323, -52, 271, -125, 99, -119, -120, +-37, -288, 73, -299, 167, -152, 165, 66, +45, 233, -108, 281, -188, 208, -168, 38, +-66, -170, 55, -305, 148, -272, 183, -89, +142, 142, 37, 290, -52, 304, -95, 178, +-107, -60, -116, -295, -96, -380, -14, -254, +95, 6, 158, 260, 160, 374, 107, 320, +17, 115, -84, -162, -152, -355, -135, -351, +-14, -168, 109, 69, 152, 236, 115, 267, +23, 186, -94, 29, -168, -132, -147, -199, +-2, -146, 182, -29, 260, 67, 181, 96, +6, 79, -180, 50, -274, 0, -232, -51, +-61, -63, 169, -42, 305, -17, 247, -8, +74, 11, -109, 58, -221, 98, -223, 74, +-131, 5, 7, -69, 139, -127, 182, -146, +132, -100, 51, 19, -23, 156, -88, 220, +-123, 152, -110, 11, -28, -127, 61, -208, +86, -182, 45, -55, -14, 111, -78, 214, +-109, 178, -75, 12, 27, -160, 147, -230, +201, -166, 123, -1, -27, 196, -169, 318, +-254, 271, -237, 60, -96, -209, 100, -372, +252, -349, 257, -169, 121, 88, -58, 325, +-177, 424, -195, 311, -105, 45, 31, -234, +140, -387, 153, -359, 56, -175, -70, 85, +-107, 313, -74, 388, -8, 257, 47, -3, +52, -248, 23, -349, -1, -268, -18, -51, +1, 190, 50, 335, 65, 294, 24, 85, +-38, -166, -79, -315, -42, -285, 24, -115, +72, 105, 90, 263, 52, 282, -47, 154, +-126, -51, -142, -220, -54, -265, 120, -174, +245, -15, 247, 149, 155, 246, -37, 229, +-245, 107, -338, -67, -264, -226, -52, -290, +200, -216, 311, -39, 250, 177, 78, 328, +-124, 324, -236, 160, -181, -93, -8, -313, +190, -368, 266, -219, 152, 35, -61, 268, +-257, 351, -369, 234, -303, -15, -77, -249, +204, -335, 412, -214, 431, 41, 237, 261, +-36, 332, -276, 217, -406, -18, -355, -242, +-133, -333, 125, -260, 287, -63, 266, 157, +97, 274, -97, 251, -209, 125, -192, -29, +-38, -149, 153, -193, 264, -160, 215, -65, +19, 48, -198, 118, -307, 145, -291, 130, +-148, 58, 75, -57, 248, -155, 293, -193, +216, -141, 40, -2, -125, 154, -202, 262, +-181, 252, -73, 100, 68, -125, 147, -302, +140, -340, 43, -194, -85, 71, -163, 314, +-159, 410, -66, 282, 100, -25, 219, -355, +232, -508, 157, -394, 15, -48, -124, 358, +-175, 608, -154, 577, -72, 239, 30, -261, +67, -665, 42, -750, 17, -481, 8, 18, +40, 502, 96, 751, 137, 653, 127, 246, +49, -255, -85, -589, -170, -600, -181, -321, +-133, 81, -42, 382, 51, 447, 109, 259, +140, -80, 120, -359, 61, -413, 21, -201, +-3, 146, -54, 429, -80, 487, -64, 301, +-27, -43, -7, -391, -17, -555, -49, -454, +-48, -134, -26, 223, 4, 435, 68, 420, +145, 239, 155, -18, 67, -235, -68, -301, +-146, -207, -138, -24, -85, 128, -29, 174, +34, 121, 47, 35, -3, -59, -72, -137, +-79, -159, 12, -116, 141, -9, 190, 110, +148, 192, 50, 215, -91, 186, -247, 62, +-317, -141, -220, -318, 3, -350, 200, -201, +285, 48, 249, 289, 119, 399, -56, 324, +-205, 61, -249, -277, -120, -485, 72, -417, +164, -110, 144, 261, 78, 516, -23, 513, +-109, 257, -135, -145, -64, -514, 75, -631, +159, -407, 112, 5, 17, 380, -67, 557, +-115, 451, -115, 154, -56, -203, 75, -461, +216, -433, 213, -122, 95, 231, -24, 427, +-134, 382, -228, 87, -241, -289, -161, -569, +23, -588, 232, -244, 321, 302, 289, 717, +200, 809, 15, 527, -220, -30, -369, -580, +-344, -900, -154, -820, 82, -327, 225, 307, +276, 737, 226, 803, 65, 505, -123, 12, +-209, -421, -163, -650, -16, -544, 104, -145, +125, 277, 108, 493, 36, 443, -129, 177, +-254, -156, -241, -411, -89, -501, 143, -315, +323, 64, 345, 410, 231, 562, -23, 458, +-324, 140, -473, -243, -362, -555, -65, -657, +241, -418, 376, 43, 319, 489, 127, 709, +-124, 588, -289, 208, -266, -249, -118, -626, +69, -725, 170, -439, 148, 58, 91, 511, +29, 694, -67, 529, -125, 136, -116, -312, +-73, -637, -10, -639, 57, -287, 119, 207, +183, 596, 156, 664, 24, 394, -137, -59, +-242, -508, -223, -741, -75, -586, 105, -97, +268, 464, 321, 812, 167, 730, -102, 268, +-298, -333, -337, -811, -176, -916, 105, -544, +330, 150, 402, 800, 285, 1056, -21, 777, +-331, 122, -459, -607, -355, -1069, -74, -1024, +239, -473, 427, 325, 437, 944, 247, 1083, +-70, 705, -333, 20, -422, -657, -321, -976, +-60, -801, 204, -247, 351, 413, 349, 806, +175, 745, -109, 317, -307, -260, -340, -706, +-222, -744, 1, -378, 219, 176, 330, 662, +305, 788, 130, 498, -116, -19, -304, -541, +-352, -829, -257, -672, -50, -182, 187, 364, +364, 724, 359, 711, 156, 364, -132, -122, +-359, -555, -420, -730, -265, -494, 29, -19, +339, 417, 506, 646, 407, 573, 77, 243, +-302, -194, -562, -569, -564, -692, -311, -464, +110, -45, 526, 342, 701, 567, 520, 561, +111, 340, -352, -15, -650, -354, -611, -512, +-287, -401, 174, -148, 576, 92, 646, 248, +350, 306, -107, 240, -514, 48, -668, -162, +-443, -259, 21, -200, 510, -71, 779, 73, +637, 217, 181, 326, -343, 304, -730, 90, +-775, -210, -455, -445, 46, -525, 516, -419, +734, -108, 574, 316, 214, 672, -172, 765, +-469, 495, -514, 0, -292, -475, 26, -751, +311, -719, 408, -355, 252, 150, -14, 555, +-274, 673, -448, 435, -363, 15, -41, -341, +336, -500, 577, -397, 541, -50, 239, 315, +-156, 501, -519, 418, -688, 86, -527, -302, +-134, -557, 292, -584, 581, -331, 589, 129, +369, 529, 42, 703, -318, 590, -542, 212, +-476, -261, -207, -634, 128, -762, 386, -551, +436, -79, 275, 401, -11, 714, -317, 726, +-452, 409, -339, -91, -66, -569, 228, -801, +398, -638, 377, -162, 210, 368, -75, 745, +-333, 773, -398, 418, -272, -148, -40, -674, +216, -876, 343, -619, 291, -61, 98, 504, +-172, 848, -352, 780, -305, 320, -98, -291, +163, -753, 355, -832, 376, -501, 212, 46, +-71, 542, -350, 781, -439, 632, -311, 182, +-66, -323, 206, -637, 389, -638, 385, -354, +222, 77, -45, 438, -292, 584, -352, 456, +-218, 128, -8, -229, 208, -433, 320, -448, +253, -295, 58, -19, -161, 239, -308, 376, +-284, 354, -120, 177, 78, -51, 242, -203, +313, -298, 260, -311, 121, -157, -64, 66, +-221, 246, -286, 329, -248, 263, -131, 81, +46, -111, 186, -306, 239, -382, 200, -224, +69, 38, -94, 260, -174, 366, -145, 292, +-33, 84, 115, -134, 201, -314, 149, -341, +-4, -161, -206, 75, -357, 246, -335, 282, +-100, 178, 213, 13, 443, -142, 480, -263, +284, -258, -59, -117, -375, 74, -525, 238, +-413, 296, -85, 262, 251, 139, 414, -84, +360, -314, 116, -416, -164, -373, -334, -171, +-323, 124, -114, 358, 180, 499, 346, 456, +334, 184, 162, -147, -120, -389, -349, -506, +-410, -399, -302, -140, -10, 102, 303, 316, +441, 384, 383, 239, 176, 58, -142, -71, +-385, -159, -428, -130, -264, -57, 44, -23, +313, 35, 384, 21, 283, -70, 54, -79, +-217, -21, -371, 19, -319, 75, -98, 97, +191, 85, 347, 93, 309, 54, 151, -12, +-83, -36, -306, -69, -364, -141, -228, -180, +36, -157, 300, -36, 394, 149, 282, 260, +74, 261, -183, 166, -399, -5, -417, -195, +-206, -312, 109, -277, 370, -73, 424, 156, +295, 264, 75, 251, -185, 132, -378, -45, +-375, -219, -189, -307, 80, -234, 278, -32, +318, 160, 238, 271, 76, 290, -165, 186, +-334, 1, -317, -205, -122, -333, 152, -303, +347, -140, 357, 62, 215, 231, -50, 300, +-347, 233, -486, 73, -363, -114, -48, -220, +293, -200, 473, -109, 446, 7, 229, 112, +-123, 148, -438, 103, -521, 12, -348, -76, +1, -86, 332, -57, 474, -43, 409, 2, +158, 80, -224, 111, -499, 75, -479, -1, +-197, -73, 177, -81, 450, -89, 481, -102, +291, -24, -65, 106, -441, 161, -593, 122, +-406, 41, -5, -27, 395, -41, 591, -66, +519, -96, 225, -56, -214, 17, -610, 13, +-675, -55, -382, -79, 78, -4, 475, 124, +629, 192, 492, 178, 171, 118, -239, 4, +-544, -187, -527, -363, -238, -349, 100, -130, +346, 147, 403, 338, 285, 399, 57, 294, +-214, 56, -386, -238, -308, -445, -71, -404, +174, -126, 327, 190, 327, 397, 189, 432, +-36, 223, -289, -121, -399, -415, -284, -541, +-55, -383, 162, 23, 315, 419, 342, 625, +239, 588, 24, 232, -230, -272, -383, -641, +-338, -746, -161, -516, 78, -4, 317, 497, +449, 784, 345, 770, 28, 349, -333, -260, +-532, -685, -467, -815, -168, -618, 223, -118, +549, 425, 625, 782, 364, 822, -95, 430, +-485, -160, -620, -605, -454, -801, -106, -697, +269, -259, 535, 310, 538, 760, 239, 885, +-159, 548, -435, -58, -477, -584, -282, -854, +36, -779, 323, -309, 482, 364, 379, 895, +30, 989, -325, 547, -486, -174, -420, -783, +-157, -1030, 177, -841, 437, -233, 528, 557, +371, 1105, 9, 1100, -339, 553, -517, -242, +-476, -904, -236, -1151, 106, -917, 408, -267, +554, 563, 428, 1136, 86, 1142, -268, 618, +-484, -164, -478, -854, -233, -1135, 109, -928, +390, -303, 486, 508, 317, 1072, -30, 1079, +-336, 582, -470, -151, -351, -786, -32, -1026, +310, -795, 499, -193, 443, 518, 137, 949, +-264, 867, -550, 353, -567, -304, -280, -804, +173, -902, 544, -556, 661, 79, 449, 702, +11, 989, -426, 769, -647, 172, -547, -487, +-164, -922, 275, -944, 538, -538, 521, 115, +241, 704, -151, 957, -436, 762, -487, 243, +-263, -322, 105, -707, 406, -768, 493, -491, +325, -4, -36, 430, -377, 623, -527, 510, +-417, 179, -87, -197, 284, -471, 487, -529, +460, -337, 204, 21, -150, 362, -396, 537, +-407, 473, -208, 220, 95, -116, 303, -426, +314, -566, 161, -470, -83, -192, -300, 146, +-344, 412, -192, 494, 77, 408, 320, 181, +394, -117, 280, -329, 62, -382, -207, -294, +-408, -84, -421, 138, -228, 235, 72, 220, +330, 92, 391, -103, 269, -204, 52, -175, +-188, -57, -332, 149, -274, 311, -57, 269, +199, 101, 331, -121, 252, -316, 37, -344, +-187, -222, -351, -43, -359, 175, -173, 309, +123, 246, 372, 109, 447, -2, 303, -75, +35, -79, -236, -71, -416, -100, -417, -98, +-202, -66, 120, -69, 383, -17, 454, 122, +302, 232, -1, 225, -309, 84, -495, -134, +-441, -272, -129, -264, 282, -176, 564, 6, +596, 264, 338, 406, -102, 312, -512, 36, +-710, -264, -580, -429, -128, -373, 379, -179, +677, 97, 657, 386, 324, 498, -170, 320, +-549, -20, -647, -322, -398, -449, 86, -352, +486, -113, 582, 155, 392, 372, 2, 420, +-400, 231, -606, -67, -528, -281, -176, -351, +291, -262, 575, -73, 574, 126, 347, 270, +-18, 309, -367, 175, -538, -37, -484, -188, +-203, -252, 162, -214, 373, -59, 366, 118, +228, 214, 5, 225, -206, 121, -302, -59, +-237, -195, -25, -244, 209, -173, 299, 20, +231, 193, 63, 220, -149, 169, -318, 46, +-355, -119, -228, -210, 34, -177, 278, -53, +374, 122, 304, 200, 125, 106, -96, -20, +-255, -98, -292, -126, -192, -71, -21, 37, +112, 124, 150, 158, 117, 67, 51, -127, +-10, -220, -52, -139, -55, 29, -30, 179, +-2, 251, 16, 193, 55, 33, 70, -198, +33, -378, -31, -337, -89, -82, -100, 218, +-37, 406, 35, 404, 72, 224, 78, -48, +38, -320, -48, -470, -94, -392, -47, -119, +82, 197, 185, 390, 158, 401, 17, 258, +-137, 35, -258, -220, -283, -407, -154, -407, +90, -200, 329, 95, 416, 344, 262, 447, +-21, 360, -261, 105, -378, -236, -338, -514, +-122, -546, 163, -299, 366, 103, 355, 489, +131, 652, -150, 485, -308, 94, -315, -358, +-180, -672, 59, -648, 290, -301, 382, 184, +272, 614, -4, 737, -276, 468, -411, -18, +-372, -491, -174, -754, 121, -635, 383, -214, +500, 318, 373, 754, 39, 840, -309, 482, +-504, -97, -501, -625, -276, -885, 88, -755, +418, -304, 563, 296, 457, 819, 136, 978, +-227, 666, -480, 70, -527, -515, -347, -883, +-19, -896, 305, -536, 495, 80, 456, 673, +213, 962, -102, 778, -350, 248, -439, -346, +-306, -757, -37, -855, 221, -544, 359, 61, +330, 634, 139, 886, -114, 674, -321, 102, +-380, -498, -238, -850, 42, -836, 304, -392, +455, 318, 418, 881, 164, 1030, -195, 681, +-479, -19, -574, -708, -393, -1057, -10, -985, +364, -458, 565, 317, 532, 916, 258, 1085, +-117, 802, -424, 166, -539, -513, -396, -917, +-79, -945, 219, -555, 409, 112, 418, 668, +227, 888, -49, 740, -297, 239, -444, -403, +-362, -828, -91, -884, 191, -514, 389, 147, +442, 732, 308, 960, 39, 796, -281, 232, +-506, -506, -501, -988, -286, -993, 23, -553, +340, 158, 535, 769, 517, 991, 266, 792, +-134, 213, -485, -504, -581, -914, -408, -837, +-57, -382, 327, 244, 571, 730, 539, 828, +208, 552, -274, -15, -623, -603, -656, -858, +-359, -673, 132, -213, 598, 350, 813, 755, +649, 809, 134, 512, -472, -17, -858, -541, +-846, -786, -446, -685, 153, -322, 662, 187, +875, 628, 691, 781, 177, 576, -392, 106, +-725, -391, -718, -697, -401, -704, 80, -397, +512, 126, 705, 605, 559, 798, 135, 594, +-324, 120, -613, -392, -628, -725, -356, -763, +89, -448, 503, 102, 703, 597, 563, 785, +147, 603, -318, 175, -623, -289, -664, -599, +-403, -657, 59, -418, 505, 34, 707, 431, +559, 560, 132, 417, -352, 108, -660, -224, +-640, -425, -293, -455, 228, -249, 639, 135, +717, 439, 404, 474, -138, 309, -624, 10, +-789, -314, -553, -508, -29, -501, 512, -262, +797, 147, 694, 477, 254, 566, -312, 459, +-708, 177, -753, -200, -444, -484, 49, -589, +482, -468, 655, -136, 522, 247, 150, 488, +-274, 563, -522, 419, -480, 89, -204, -279, +141, -518, 361, -537, 379, -303, 212, 67, +-55, 383, -284, 529, -344, 432, -225, 103, +14, -277, 226, -492, 292, -495, 219, -295, +73, 70, -106, 421, -222, 576, -212, 480, +-95, 185, 60, -190, 160, -462, 140, -583, +45, -500, -54, -172, -111, 255, -105, 521, +-32, 568, 75, 395, 160, 44, 153, -293, +55, -489, -61, -493, -130, -218, -138, 206, +-91, 464, -16, 466, 49, 248, 70, -129, +57, -454, 19, -589, -13, -477, 8, -56, +74, 492, 103, 762, 85, 679, 9, 326, +-110, -183, -198, -632, -213, -807, -161, -664, +-4, -196, 186, 379, 277, 709, 231, 679, +80, 381, -103, -55, -193, -440, -190, -604, +-120, -490, 25, -109, 156, 375, 160, 645, +61, 554, -89, 211, -193, -225, -174, -633, +-85, -792, 27, -588, 170, -67, 249, 546, +214, 926, 90, 854, -93, 448, -241, -114, +-256, -659, -194, -925, -90, -764, 60, -278, +199, 312, 251, 699, 190, 682, 46, 377, +-82, -21, -155, -386, -181, -536, -150, -382, +-59, -27, 69, 329, 194, 491, 205, 358, +93, 70, -36, -243, -129, -485, -200, -539, +-200, -313, -74, 73, 148, 435, 309, 613, +273, 541, 77, 254, -146, -145, -307, -509, +-328, -664, -192, -505, 73, -120, 351, 281, +457, 537, 287, 562, -24, 343, -287, -29, +-407, -367, -372, -521, -194, -401, 85, -110, +358, 169, 456, 329, 328, 389, 77, 277, +-156, 14, -322, -241, -375, -347, -265, -280, +-5, -104, 245, 66, 341, 217, 249, 331, +44, 260, -158, 16, -265, -209, -265, -317, +-141, -276, 90, -112, 286, 78, 309, 253, +193, 376, 18, 291, -155, 50, -298, -205, +-338, -357, -216, -347, 15, -196, 202, -20, +282, 195, 263, 372, 143, 351, -28, 161, +-172, -77, -250, -254, -198, -293, -46, -225, +77, -102, 137, 102, 170, 289, 125, 310, +-8, 191, -162, -14, -250, -222, -213, -344, +-74, -331, 91, -207, 266, 51, 383, 337, +326, 504, 88, 447, -194, 181, -412, -179, +-482, -447, -371, -530, -106, -428, 223, -138, +477, 240, 523, 495, 347, 490, 35, 270, +-273, -37, -459, -277, -444, -355, -218, -293, +129, -99, 403, 156, 445, 317, 233, 277, +-89, 94, -372, -163, -496, -328, -354, -313, +25, -160, 407, 68, 602, 341, 533, 494, +196, 389, -254, 70, -584, -296, -693, -524, +-509, -516, -63, -309, 408, 24, 673, 399, +652, 618, 345, 514, -86, 176, -461, -197, +-657, -454, -538, -518, -135, -367, 279, -92, +529, 245, 552, 473, 314, 446, -74, 210, +-432, -63, -629, -308, -498, -420, -74, -339, +365, -103, 621, 211, 623, 440, 328, 418, +-134, 185, -555, -110, -754, -378, -574, -503, +-102, -381, 350, -62, 613, 301, 633, 528, +375, 518, -56, 273, -442, -58, -608, -368, +-455, -534, -85, -469, 275, -191, 460, 118, +409, 356, 145, 442, -189, 320, -428, 79, +-429, -158, -158, -313, 215, -284, 436, -92, +426, 92, 225, 215, -78, 225, -351, 50, +-459, -162, -359, -266, -97, -241, 185, -89, +350, 133, 356, 268, 253, 316, 88, 230, +-102, 14, -268, -185, -312, -257, -219, -260, +-60, -191, 94, -56, 210, 90, 240, 219, +173, 259, 30, 171, -112, 29, -168, -95, +-136, -186, -85, -199, -24, -107, 32, 40, +81, 185, 120, 209, 123, 101, 77, -42, +10, -108, -90, -130, -180, -117, -182, -84, +-92, -8, 39, 76, 150, 97, 173, 75, +120, 96, 30, 121, -56, 68, -100, -43, +-85, -157, -52, -193, -14, -128, 8, -53, +20, 20, 39, 107, 53, 159, 43, 136, +9, 72, -66, -32, -124, -78, -114, -60, +-49, -80, 76, -125, 218, -58, 244, 73, +141, 178, -50, 183, -258, 77, -346, -57, +-259, -168, -81, -269, 138, -251, 284, -30, +278, 243, 174, 382, 24, 339, -117, 132, +-164, -137, -167, -331, -150, -383, -56, -287, +62, -31, 128, 237, 155, 369, 90, 323, +-61, 141, -192, -111, -213, -269, -90, -317, +140, -258, 328, -47, 352, 230, 162, 392, +-158, 382, -421, 190, -475, -143, -292, -428, +57, -539, 365, -420, 473, -52, 349, 396, +73, 670, -195, 632, -329, 265, -314, -275, +-149, -657, 56, -713, 184, -426, 228, 79, +182, 568, 33, 740, -111, 519, -206, 27, +-228, -459, -116, -676, 70, -534, 224, -128, +313, 327, 224, 602, -8, 547, -199, 220, +-302, -184, -311, -463, -156, -497, 59, -299, +227, 10, 330, 249, 301, 351, 136, 295, +-53, 152, -232, -20, -343, -145, -315, -227, +-149, -236, 102, -161, 321, -27, 357, 106, +220, 224, 3, 285, -215, 198, -321, -20, +-243, -262, -56, -363, 142, -243, 261, -5, +234, 215, 54, 373, -146, 367, -236, 108, +-211, -212, -115, -413, 51, -389, 207, -164, +267, 114, 206, 280, 33, 339, -162, 244, +-258, 37, -270, -132, -181, -207, 25, -188, +235, -74, 336, -1, 283, -27, 49, -27, +-215, 37, -342, 99, -320, 143, -148, 144, +125, 92, 329, -15, 373, -169, 241, -267, +-12, -162, -236, 59, -342, 229, -335, 251, +-181, 118, 48, -145, 237, -351, 349, -351, +342, -126, 164, 240, -103, 567, -316, 595, +-371, 249, -252, -290, -11, -712, 236, -749, +359, -398, 288, 134, 67, 653, -211, 887, +-386, 591, -324, -69, -70, -644, 208, -847, +377, -594, 367, -39, 188, 544, -99, 863, +-361, 726, -437, 143, -277, -517, -1, -880, +242, -779, 331, -282, 263, 363, 115, 797, +-49, 813, -185, 432, -214, -184, -128, -713, +5, -816, 84, -446, 76, 142, 50, 616, +40, 737, 2, 457, -58, -64, -93, -603, +-60, -810, 21, -513, 71, 76, 76, 565, +77, 762, 44, 557, -14, 49, -64, -461, +-113, -692, -120, -531, -54, -86, -14, 348, +13, 527, 84, 406, 150, 48, 171, -298, +120, -388, -44, -235, -212, 21, -286, 240, +-241, 311, -59, 159, 176, -87, 329, -248, +353, -195, 179, -15, -150, 157, -397, 188, +-407, 71, -223, -120, 71, -270, 332, -259, +444, -36, 351, 275, 49, 478, -325, 448, +-525, 120, -434, -345, -104, -652, 270, -659, +492, -333, 464, 242, 191, 773, -200, 920, +-455, 578, -426, -142, -151, -831, 179, -1092, +347, -785, 283, -32, 87, 838, -139, 1279, +-246, 989, -160, 122, 13, -862, 144, -1403, +173, -1142, 83, -209, -39, 889, -122, 1530, +-147, 1288, -82, 269, 46, -931, 112, -1649, +99, -1441, 34, -377, -38, 942, -56, 1741, +-17, 1579, 23, 515, 76, -843, 100, -1723, +13, -1645, -145, -679, -232, 648, -181, 1578, +-17, 1615, 156, 771, 263, -452, 274, -1357, +181, -1464, -30, -787, -276, 272, -394, 1134, +-302, 1325, -78, 781, 156, -144, 307, -928, +352, -1179, 257, -804, 0, -7, -297, 758, +-400, 1065, -274, 771, -33, 107, 197, -562, +310, -889, 262, -760, 103, -215, -127, 449, +-304, 812, -278, 670, -92, 180, 95, -353, +213, -661, 223, -614, 149, -271, 34, 236, +-101, 625, -207, 619, -205, 261, -138, -176, +-47, -450, 68, -474, 171, -297, 222, -29, +207, 299, 87, 476, -91, 343, -233, 17, +-280, -237, -214, -330, -35, -280, 167, -145, +298, 88, 291, 358, 132, 418, -108, 179, +-281, -155, -295, -372, -132, -420, 125, -289, +321, 12, 313, 372, 107, 573, -173, 423, +-355, 15, -330, -398, -117, -565, 152, -444, +350, -86, 366, 328, 189, 564, -74, 446, +-267, 57, -297, -363, -190, -556, -60, -389, +67, 17, 183, 425, 204, 613, 106, 438, +-19, -23, -99, -475, -89, -667, -38, -528, +-8, -112, 14, 367, 27, 676, -12, 637, +-66, 263, -86, -234, -7, -535, 126, -553, +155, -341, 64, 12, -21, 364, -86, 501, +-138, 328, -132, -38, -54, -338, 77, -391, +176, -222, 129, 44, 1, 328, -104, 480, +-162, 329, -151, -64, -47, -428, 115, -557, +270, -383, 274, -35, 75, 317, -192, 544, +-362, 511, -365, 163, -186, -262, 100, -508, +378, -455, 487, -167, 318, 185, -35, 426, +-332, 458, -434, 207, -321, -201, -55, -498, +238, -513, 376, -248, 252, 166, -54, 522, +-300, 646, -318, 450, -103, -24, 193, -521, +387, -753, 365, -621, 124, -179, -243, 370, +-488, 760, -416, 764, -95, 363, 217, -257, +348, -720, 283, -790, 104, -441, -108, 150, +-214, 680, -130, 838, 64, 507, 170, -135, +91, -701, -93, -847, -209, -512, -188, 103, +-59, 667, 102, 888, 205, 615, 181, -39, +33, -651, -138, -861, -166, -591, -31, -47, +126, 490, 177, 748, 81, 634, -117, 174, +-268, -368, -284, -643, -129, -533, 145, -197, +348, 174, 332, 431, 147, 475, -118, 309, +-317, -9, -310, -311, -124, -402, 109, -282, +253, -98, 208, 74, 50, 221, -111, 280, +-206, 232, -176, 60, -33, -124, 113, -195, +199, -160, 170, -131, 64, -75, -34, 54, +-118, 179, -206, 195, -236, 92, -154, -46, +60, -137, 285, -171, 371, -162, 291, -41, +62, 179, -276, 315, -516, 263, -482, 51, +-141, -206, 340, -373, 632, -364, 539, -194, +169, 113, -317, 392, -685, 465, -680, 281, +-262, -49, 356, -333, 825, -415, 787, -294, +286, -21, -335, 279, -799, 429, -868, 320, +-427, 14, 265, -304, 814, -457, 868, -397, +371, -144, -263, 223, -619, 523, -635, 563, +-306, 327, 200, -61, 540, -416, 512, -592, +129, -511, -330, -195, -471, 235, -300, 526, +-33, 516, 224, 246, 364, -90, 314, -338, +113, -377, -170, -204, -285, 74, -158, 294, +-44, 309, -36, 93, -40, -186, -23, -311, +47, -247, 102, -68, 122, 134, 192, 265, +195, 291, -3, 187, -235, -21, -357, -182, +-284, -209, -45, -210, 161, -174, 276, -69, +324, 111, 167, 291, -119, 332, -319, 180, +-338, -55, -140, -282, 156, -395, 315, -269, +322, 44, 169, 368, -129, 478, -391, 264, +-454, -143, -275, -478, 104, -516, 434, -226, +535, 234, 389, 579, 27, 608, -393, 242, +-622, -304, -541, -683, -147, -647, 352, -247, +649, 274, 601, 635, 237, 658, -295, 323, +-674, -199, -674, -573, -283, -587, 285, -288, +684, 110, 698, 402, 364, 480, -183, 324, +-650, 0, -778, -320, -510, -434, 38, -337, +580, -91, 783, 170, 609, 346, 181, 395, +-348, 297, -728, 33, -743, -262, -370, -437, +215, -428, 658, -235, 719, 45, 419, 312, +-81, 500, -545, 488, -716, 211, -502, -183, +12, -473, 542, -560, 760, -415, 531, -91, +19, 301, -482, 608, -720, 647, -609, 327, +-174, -155, 376, -564, 735, -732, 684, -552, +249, -82, -303, 454, -638, 811, -646, 756, +-362, 286, 95, -355, 515, -836, 679, -899, +498, -480, 46, 201, -395, 816, -592, 1038, +-519, 728, -236, 15, 161, -759, 492, -1187, +586, -1021, 349, -325, -81, 565, -423, 1198, +-513, 1254, -356, 697, 4, -211, 377, -1057, +548, -1384, 398, -982, -9, -48, -433, 882, +-596, 1324, -446, 1055, -70, 240, 362, -704, +611, -1304, 510, -1181, 140, -349, -274, 690, +-467, 1316, -373, 1229, -133, 518, 123, -439, +294, -1166, 226, -1315, -4, -785, -203, 120, +-237, 876, -73, 1091, 144, 806, 223, 228, +220, -369, 150, -729, -32, -709, -202, -361, +-256, 98, -185, 400, -14, 455, 64, 349, +32, 107, 41, -208, 61, -439, 52, -441, +88, -210, 111, 107, 122, 385, 77, 541, +-109, 501, -276, 194, -263, -265, -144, -634, +47, -682, 201, -441, 222, -43, 165, 380, +25, 673, -160, 669, -193, 333, -94, -164, +48, -542, 188, -620, 199, -411, 67, -30, +-76, 383, -199, 638, -217, 540, -130, 92, +-40, -431, 54, -755, 154, -675, 152, -223, +106, 394, 97, 892, 91, 986, 35, 516, +-90, -273, -243, -952, -280, -1170, -164, -773, +5, 42, 145, 829, 244, 1179, 239, 895, +100, 142, -109, -652, -230, -1069, -154, -894, +45, -211, 163, 550, 173, 951, 124, 798, +-38, 219, -277, -426, -393, -821, -291, -808, +9, -338, 346, 318, 525, 752, 478, 786, +217, 442, -224, -86, -602, -512, -669, -749, +-378, -655, 128, -184, 551, 343, 638, 654, +412, 692, -36, 404, -512, -46, -686, -466, +-406, -740, 127, -627, 574, -139, 640, 370, +356, 674, -78, 670, -499, 336, -685, -153, +-466, -593, 1, -786, 435, -522, 573, 34, +378, 517, 88, 708, -136, 588, -318, 220, +-372, -233, -251, -603, -10, -684, 210, -389, +256, 61, 184, 401, 167, 529, 77, 450, +-175, 207, -398, -139, -392, -466, -144, -557, +195, -339, 420, 20, 509, 384, 415, 591, +30, 543, -500, 239, -789, -243, -615, -716, +-76, -852, 462, -540, 735, 63, 683, 678, +307, 988, -300, 838, -777, 318, -780, -401, +-318, -1028, 276, -1121, 693, -605, 764, 192, +458, 900, -121, 1145, -694, 817, -923, 106, +-623, -733, 8, -1290, 612, -1107, 912, -304, +786, 675, 264, 1363, -417, 1363, -899, 680, +-865, -354, -380, -1326, 219, -1694, 639, -1164, +748, -27, 504, 1124, 18, 1720, -466, 1456, +-657, 508, -493, -672, -140, -1542, 214, -1637, +457, -861, 505, 330, 348, 1305, 23, 1585, +-313, 1059, -492, 21, -443, -1037, -216, -1596, +71, -1307, 308, -335, 474, 795, 445, 1538, +168, 1520, -194, 750, -454, -391, -507, -1398, +-324, -1702, -21, -1119, 327, 3, 580, 1107, +535, 1673, 200, 1383, -258, 409, -658, -761, +-708, -1550, -390, -1501, 83, -659, 572, 458, +859, 1295, 702, 1453, 172, 866, -488, -116, +-916, -992, -843, -1363, -363, -1003, 260, -162, +792, 663, 918, 1092, 559, 981, -81, 441, +-680, -222, -912, -761, -628, -939, -39, -644, +544, -86, 839, 442, 714, 718, 233, 677, +-355, 391, -770, -70, -804, -537, -450, -746, +122, -576, 619, -130, 831, 369, 666, 645, +196, 636, -355, 342, -749, -148, -845, -588, +-528, -715, 72, -452, 630, 45, 872, 481, +699, 639, 200, 498, -360, 146, -776, -277, +-838, -579, -451, -577, 163, -273, 661, 129, +820, 424, 557, 471, 66, 315, -430, 64, +-771, -198, -744, -368, -302, -314, 278, -108, +739, 96, 827, 198, 484, 171, -51, 86, +-579, 31, -910, -20, -762, -83, -236, -101, +390, -114, 891, -142, 945, -93, 517, 34, +-70, 229, -677, 411, -1026, 388, -834, 93, +-267, -303, 443, -630, 1019, -685, 999, -383, +469, 157, -226, 700, -877, 948, -1086, 689, +-667, 42, 63, -634, 816, -993, 1159, -853, +804, -264, 83, 462, -637, 960, -1123, 945, +-1007, 393, -360, -398, 439, -956, 1066, -1008, +1136, -506, 596, 288, -146, 929, -825, 1123, +-1155, 748, -867, -55, -127, -824, 657, -1180, +1088, -954, 892, -230, 279, 552, -399, 1019, +-906, 1038, -961, 535, -451, -215, 276, -812, +810, -992, 878, -644, 499, 22, -42, 576, +-515, 838, -808, 717, -700, 198, -227, -427, +300, -837, 641, -818, 685, -343, 447, 290, +106, 748, -302, 897, -665, 648, -702, 27, +-385, -646, 57, -1027, 474, -874, 685, -288, +612, 394, 275, 878, -265, 985, -726, 600, +-758, -106, -405, -764, 136, -996, 637, -661, +811, -39, 545, 540, -6, 847, -599, 715, +-883, 207, -671, -421, -112, -816, 480, -711, +842, -225, 778, 291, 318, 664, -290, 730, +-739, 432, -838, -103, -536, -606, 0, -767, +528, -508, 831, -60, 750, 367, 280, 655, +-312, 661, -776, 328, -898, -202, -565, -616, +63, -671, 675, -412, 1014, -7, 836, 387, +212, 650, -515, 621, -1011, 254, -1024, -278, +-513, -652, 233, -676, 883, -397, 1100, 26, +751, 472, 60, 758, -638, 680, -1052, 224, +-911, -391, -299, -799, 436, -770, 950, -401, +987, 140, 530, 669, -177, 919, -857, 689, +-1125, 63, -767, -649, -20, -1005, 715, -819, +1128, -267, 976, 396, 354, 928, -422, 1033, +-1031, 609, -1145, -137, -630, -847, 176, -1109, +831, -782, 1042, -149, 760, 519, 170, 970, +-481, 951, -963, 456, -947, -276, -404, -902, +292, -999, 789, -548, 949, 125, 696, 739, +116, 1014, -570, 761, -1059, 81, -1055, -699, +-494, -1143, 309, -946, 954, -248, 1168, 544, +869, 1082, 146, 1104, -694, 583, -1250, -225, +-1177, -911, -484, -1144, 424, -778, 1071, -86, +1244, 566, 851, 926, 15, 832, -869, 367, +-1355, -211, -1176, -689, -371, -824, 611, -544, +1306, -81, 1414, 419, 823, 764, -228, 730, +-1197, 404, -1608, -108, -1190, -643, -151, -884, +945, -721, 1572, -258, 1428, 414, 545, 911, +-621, 954, -1489, 596, -1578, -80, -832, -772, +313, -1042, 1304, -811, 1679, -200, 1168, 564, +38, 1001, -1136, 892, -1745, 369, -1413, -387, +-360, -935, 818, -930, 1620, -480, 1618, 215, +752, 861, -487, 1023, -1444, 666, -1628, -22, +-945, -750, 143, -1071, 1084, -840, 1484, -247, +1147, 492, 229, 1013, -773, 994, -1356, 491, +-1210, -255, -455, -878, 444, -996, 1047, -608, +1180, 37, 789, 660, -3, 940, -799, 697, +-1141, 108, -912, -547, -299, -904, 374, -724, +839, -200, 962, 371, 688, 795, 47, 810, +-625, 404, -962, -172, -836, -688, -334, -827, +308, -516, 804, -67, 982, 386, 670, 683, +-80, 613, -823, 283, -1092, -125, -796, -473, +-107, -513, 633, -316, 1091, -79, 1029, 198, +395, 382, -504, 345, -1102, 169, -1104, -97, +-575, -323, 193, -325, 841, -181, 1089, 8, +823, 261, 128, 401, -606, 326, -982, 82, +-855, -239, -349, -448, 277, -403, 740, -217, +870, 56, 554, 349, -62, 481, -593, 389, +-776, 112, -593, -218, -143, -414, 322, -422, +627, -287, 680, -18, 400, 301, -88, 501, +-475, 476, -632, 214, -536, -160, -244, -489, +142, -619, 521, -501, 709, -100, 508, 424, +56, 764, -373, 758, -629, 395, -625, -213, +-320, -742, 163, -933, 631, -703, 796, -61, +499, 633, -70, 968, -573, 855, -825, 293, +-717, -461, -247, -957, 429, -967, 985, -467, +1047, 348, 512, 939, -264, 1015, -898, 605, +-1166, -156, -904, -878, -148, -1132, 744, -796, +1307, -4, 1163, 825, 403, 1165, -513, 904, +-1184, 223, -1319, -620, -770, -1179, 185, -1118, +1089, -442, 1462, 505, 1027, 1173, 78, 1182, +-845, 638, -1404, -199, -1290, -975, -509, -1284, +525, -934, 1319, -84, 1437, 797, 770, 1205, +-230, 1000, -1083, 359, -1440, -423, -1051, -985, +-96, -1040, 896, -557, 1465, 220, 1257, 825, +361, 943, -685, 583, -1383, -26, -1441, -619, +-758, -909, 324, -739, 1243, -197, 1565, 438, +1124, 834, 125, 802, -888, 445, -1468, -51, +-1358, -532, -566, -781, 488, -672, 1251, -305, +1415, 161, 846, 508, -184, 631, -1070, 521, +-1373, 197, -976, -243, -44, -546, 898, -549, +1385, -287, 1191, 101, 345, 471, -710, 632, +-1387, 429, -1389, -63, -688, -606, 331, -863, +1132, -628, 1432, -65, 1100, 582, 202, 1042, +-768, 1003, -1325, 423, -1222, -392, -554, -1070, +271, -1193, 929, -701, 1225, 73, 891, 793, +70, 1146, -737, 904, -1151, 216, -983, -545, +-310, -1018, 481, -915, 1075, -352, 1186, 318, +638, 839, -305, 948, -1096, 545, -1337, -133, +-876, -745, 13, -995, 868, -702, 1353, -88, +1208, 560, 379, 974, -661, 878, -1303, 330, +-1256, -361, -607, -898, 310, -971, 1030, -537, +1232, 118, 808, 735, -38, 999, -822, 727, +-1097, 133, -821, -513, -186, -947, 503, -905, +912, -416, 862, 242, 422, 820, -235, 999, +-750, 675, -844, 63, -571, -585, -85, -1005, +472, -901, 798, -336, 737, 363, 339, 911, +-237, 1004, -661, 573, -716, -110, -497, -786, +-48, -1105, 467, -792, 708, -78, 572, 636, +179, 1069, -304, 950, -574, 354, -555, -403, +-316, -1006, 117, -1078, 510, -545, 577, 193, +375, 770, 16, 972, -335, 697, -483, 110, +-425, -508, -205, -876, 147, -738, 385, -239, +406, 263, 291, 575, 61, 630, -193, 411, +-324, 35, -347, -368, -215, -568, 63, -427, +280, -138, 341, 117, 282, 318, 46, 411, +-250, 334, -410, 98, -367, -202, -99, -368, +275, -329, 462, -207, 417, -30, 170, 200, +-259, 378, -562, 363, -476, 168, -147, -103, +276, -299, 561, -340, 474, -270, 130, -101, +-279, 155, -595, 320, -510, 291, -105, 162, +289, -23, 546, -158, 507, -175, 141, -166, +-220, -99, -448, 28, -472, 85, -197, 93, +146, 114, 330, 70, 359, 20, 162, -52, +-98, -166, -218, -185, -250, -89, -149, 44, +95, 204, 220, 298, 200, 236, 111, 61, +-54, -202, -176, -413, -195, -399, -178, -195, +-59, 112, 92, 389, 162, 468, 198, 325, +175, 47, 41, -284, -74, -452, -153, -366, +-201, -111, -128, 190, 6, 360, 75, 320, +120, 156, 109, -84, 32, -301, -21, -330, +-54, -184, -79, 41, -16, 226, 28, 258, +11, 196, 41, 96, 62, -50, 8, -177, +-20, -202, -44, -151, -74, -76, -51, -24, +-32, 32, -6, 131, 98, 221, 143, 218, +90, 107, 28, -51, -64, -198, -161, -294, +-160, -273, -107, -102, 28, 159, 211, 343, +251, 340, 119, 155, -35, -94, -184, -282, +-265, -329, -203, -231, -22, -11, 201, 210, +346, 292, 256, 226, 20, 55, -178, -113, +-281, -178, -279, -169, -137, -105, 67, 6, +254, 92, 316, 121, 190, 109, -3, 37, +-120, -15, -209, -44, -256, -95, -202, -128, +-46, -91, 153, 7, 291, 137, 270, 207, +165, 175, 19, 78, -177, -102, -329, -297, +-326, -358, -160, -224, 114, 73, 313, 362, +342, 451, 258, 332, 72, 71, -211, -284, +-415, -514, -414, -479, -187, -196, 148, 210, +385, 478, 435, 472, 329, 296, 27, 3, +-323, -313, -472, -447, -383, -369, -134, -127, +183, 157, 373, 285, 372, 272, 202, 214, +-88, 78, -305, -98, -304, -198, -176, -217, +44, -140, 260, -23, 305, 70, 175, 160, +-46, 213, -273, 124, -317, -66, -183, -223, +-10, -274, 166, -167, 306, 56, 289, 273, +139, 390, -70, 311, -226, 20, -260, -308, +-219, -475, -153, -414, 17, -120, 230, 232, +322, 444, 253, 435, 96, 204, -99, -133, +-262, -363, -343, -393, -270, -218, -17, 88, +270, 319, 383, 358, 322, 220, 125, -43, +-160, -282, -399, -372, -450, -298, -262, -76, +116, 208, 431, 376, 499, 368, 340, 209, +7, -41, -394, -251, -609, -341, -505, -304, +-101, -120, 391, 122, 655, 266, 567, 271, +225, 163, -270, -9, -681, -160, -724, -234, +-353, -179, 234, -4, 705, 180, 749, 242, +407, 170, -130, 22, -668, -152, -890, -283, +-569, -273, 91, -112, 734, 123, 1003, 317, +713, 329, 52, 194, -635, 2, -1084, -223, +-984, -366, -331, -325, 493, -133, 1082, 141, +1136, 343, 584, 336, -200, 220, -864, 23, +-1167, -231, -861, -377, -86, -336, 672, -117, +1090, 194, 946, 359, 312, 314, -433, 184, +-972, -48, -1044, -297, -500, -379, 292, -263, +882, 24, 1050, 305, 678, 335, -74, 189, +-763, 22, -1076, -190, -822, -309, -125, -240, +583, -37, 994, 221, 954, 323, 395, 155, +-364, -49, -917, -163, -1023, -230, -592, -175, +141, -18, 748, 157, 1009, 277, 787, 197, +146, -30, -552, -167, -955, -188, -888, -163, +-365, -50, 272, 95, 718, 215, 855, 250, +589, 104, 18, -122, -514, -228, -784, -227, +-663, -144, -221, 39, 264, 211, 610, 296, +715, 235, 434, -13, -70, -248, -498, -289, +-699, -196, -569, -5, -160, 206, 265, 273, +586, 194, 689, -13, 453, -256, -1, -305, +-432, -141, -690, 83, -623, 286, -289, 332, +146, 171, 572, -64, 768, -287, 531, -379, +31, -225, -465, 38, -745, 242, -656, 321, +-238, 217, 294, 9, 723, -146, 782, -234, +407, -194, -165, -6, -633, 161, -792, 209, +-555, 137, -71, -35, 440, -184, 763, -230, +706, -196, 277, -38, -251, 199, -619, 331, +-679, 293, -449, 105, -38, -143, 402, -309, +669, -340, 578, -239, 215, 21, -202, 296, +-504, 395, -585, 282, -407, 14, -58, -256, +337, -370, 573, -313, 516, -116, 225, 195, +-154, 428, -470, 421, -544, 185, -363, -171, +-6, -429, 385, -449, 580, -286, 448, 13, +99, 369, -308, 531, -556, 393, -501, 39, +-212, -340, 163, -505, 492, -402, 571, -141, +354, 211, -11, 502, -361, 512, -537, 251, +-444, -139, -171, -457, 176, -521, 448, -348, +486, -56, 278, 280, -54, 511, -370, 486, +-480, 241, -334, -119, -39, -409, 275, -478, +472, -344, 415, -68, 143, 275, -214, 499, +-469, 462, -475, 172, -247, -242, 78, -526, +391, -535, 522, -297, 373, 123, 28, 533, +-322, 685, -495, 488, -398, 11, -118, -500, +212, -724, 442, -586, 441, -182, 199, 324, +-137, 661, -400, 648, -441, 309, -278, -206, +-20, -596, 259, -620, 459, -327, 418, 113, +152, 501, -166, 625, -375, 439, -408, 22, +-268, -449, -17, -684, 279, -547, 446, -165, +339, 287, 45, 597, -235, 621, -389, 373, +-351, -70, -155, -488, 127, -615, 402, -423, +503, -49, 308, 314, -43, 474, -357, 406, +-508, 155, -450, -206, -211, -442, 130, -403, +469, -156, 587, 170, 393, 392, 36, 395, +-286, 244, -482, -22, -487, -329, -282, -464, +88, -362, 437, -97, 563, 212, 397, 384, +45, 363, -340, 227, -582, -16, -553, -279, +-226, -368, 255, -261, 639, -30, 703, 205, +394, 287, -147, 227, -624, 93, -794, -120, +-553, -289, -24, -275, 524, -112, 805, 122, +679, 280, 192, 268, -397, 153, -773, -15, +-753, -213, -364, -299, 208, -218, 679, -30, +826, 185, 562, 270, 19, 189, -546, 43, +-854, -124, -740, -263, -245, -250, 367, -86, +805, 150, 848, 338, 459, 314, -172, 120, +-707, -99, -887, -306, -615, -408, -34, -283, +561, -8, 882, 291, 759, 450, 228, 341, +-412, 86, -836, -168, -861, -371, -466, -392, +183, -163, 755, 158, 969, 402, 681, 418, +25, 162, -618, -179, -932, -437, -824, -526, +-310, -332, 371, 97, 865, 508, 938, 697, +541, 533, -130, 79, -664, -384, -867, -667, +-720, -682, -235, -364, 380, 137, 778, 544, +797, 675, 431, 446, -93, 24, -492, -325, +-679, -512, -589, -464, -180, -160, 281, 218, +553, 478, 566, 485, 311, 214, -70, -142, +-380, -408, -556, -527, -467, -403, -103, -70, +303, 300, 561, 555, 566, 549, 260, 280, +-170, -65, -525, -355, -674, -510, -465, -437, +31, -181, 490, 135, 704, 369, 569, 388, +147, 222, -338, 12, -688, -170, -725, -279, +-333, -254, 236, -103, 653, 104, 778, 257, +530, 281, -21, 190, -572, 34, -866, -155, +-721, -336, -177, -403, 442, -278, 824, -4, +829, 284, 394, 470, -259, 473, -752, 291, +-858, -36, -518, -406, 118, -604, 652, -492, +843, -142, 622, 257, 39, 534, -581, 567, +-864, 337, -731, -91, -224, -522, 416, -683, +819, -462, 837, 13, 477, 485, -165, 735, +-698, 645, -840, 232, -610, -350, -112, -800, +427, -839, 720, -440, 690, 159, 315, 652, +-240, 828, -600, 617, -620, 113, -385, -454, +55, -783, 470, -671, 633, -210, 494, 314, +76, 646, -413, 656, -649, 343, -585, -144, +-263, -595, 221, -742, 610, -465, 709, 44, +493, 509, 5, 728, -481, 582, -706, 150, +-628, -360, -276, -733, 230, -702, 616, -257, +724, 293, 491, 676, 3, 713, -458, 357, +-674, -179, -608, -643, -239, -816, 250, -514, +570, 86, 608, 616, 386, 847, -20, 654, +-370, 130, -516, -431, -448, -796, -189, -785, +141, -363, 375, 207, 476, 636, 373, 746, +66, 480, -265, 11, -482, -421, -516, -643, +-265, -529, 153, -134, 506, 300, 638, 563, +440, 512, -23, 177, -465, -218, -705, -478, +-609, -501, -159, -254, 372, 128, 693, 417, +716, 474, 382, 267, -160, -74, -611, -319, +-774, -374, -567, -253, -60, -13, 456, 206, +756, 277, 708, 206, 295, 41, -260, -104, +-662, -125, -756, -92, -472, -78, 38, -57, +490, -40, 699, -28, 597, 31, 209, 116, +-261, 202, -596, 237, -657, 105, -406, -136, +36, -319, 449, -358, 670, -226, 576, 40, +186, 302, -317, 449, -675, 364, -698, 37, +-361, -321, 162, -499, 625, -416, 794, -109, +558, 266, 14, 533, -535, 549, -814, 249, +-693, -218, -225, -576, 366, -649, 774, -397, +809, 51, 426, 481, -187, 702, -688, 587, +-832, 155, -580, -356, -36, -678, 529, -662, +842, -324, 739, 166, 248, 577, -366, 705, +-755, 469, -779, -24, -447, -512, 109, -729, +615, -574, 807, -124, 595, 406, 69, 745, +-454, 701, -711, 306, -638, -263, -265, -719, +269, -805, 646, -486, 666, 76, 345, 616, +-136, 833, -517, 630, -614, 141, -432, -427, +-42, -789, 369, -737, 561, -321, 449, 245, +153, 674, -181, 755, -398, 484, -434, 0, +-300, -502, -28, -767, 274, -639, 403, -190, +341, 334, 178, 674, -60, 693, -307, 400, +-428, -85, -353, -555, -64, -766, 269, -569, +429, -81, 390, 417, 204, 695, -123, 651, +-420, 312, -500, -186, -304, -632, 75, -757, +411, -471, 513, 29, 385, 475, 61, 689, +-333, 591, -560, 221, -489, -293, -167, -702, +259, -722, 521, -354, 509, 158, 291, 588, +-52, 746, -381, 564, -495, 108, -384, -457, +-123, -820, 167, -728, 350, -291, 382, 251, +282, 674, 34, 780, -215, 537, -328, 45, +-300, -501, -152, -778, 80, -629, 262, -216, +328, 263, 221, 606, -31, 653, -249, 411, +-321, -42, -276, -502, -78, -686, 196, -508, +380, -113, 382, 334, 188, 633, -135, 643, +-378, 356, -433, -132, -298, -583, -3, -733, +312, -524, 454, -92, 374, 380, 112, 670, +-189, 646, -359, 333, -369, -154, -248, -571, +2, -676, 239, -450, 344, -31, 311, 404, +161, 632, -61, 571, -262, 255, -391, -226, +-329, -620, -59, -693, 234, -449, 388, 12, +376, 488, 178, 728, -126, 659, -383, 282, +-443, -294, -237, -721, 112, -774, 354, -474, +409, 60, 267, 556, -15, 768, -290, 652, +-424, 194, -348, -401, -51, -754, 258, -717, +380, -339, 312, 210, 124, 632, -120, 765, +-297, 563, -342, 40, -198, -525, 70, -805, +259, -693, 264, -247, 166, 298, 7, 683, +-152, 782, -230, 507, -193, -61, -41, -591, +151, -801, 229, -602, 175, -106, 52, 406, +-93, 711, -198, 690, -210, 299, -136, -276, +25, -686, 194, -722, 253, -389, 183, 125, +61, 545, -78, 707, -201, 539, -250, 78, +-180, -439, -24, -707, 133, -610, 217, -221, +228, 257, 154, 592, 5, 650, -170, 402, +-264, -75, -220, -531, -58, -685, 139, -490, +278, -65, 269, 388, 112, 637, -129, 585, +-330, 248, -360, -240, -180, -604, 98, -624, +337, -341, 416, 91, 301, 462, 45, 597, +-247, 455, -451, 93, -436, -318, -214, -538, +91, -470, 345, -193, 456, 151, 346, 400, +56, 460, -272, 319, -447, 23, -374, -269, +-94, -413, 224, -357, 419, -149, 376, 104, +116, 297, -224, 372, -446, 282, -427, 54, +-159, -193, 202, -343, 458, -331, 476, -178, +253, 42, -102, 242, -400, 340, -497, 280, +-334, 76, -1, -167, 325, -313, 471, -300, +383, -151, 108, 76, -205, 263, -420, 316, +-438, 211, -243, -34, 74, -280, 358, -356, +490, -246, 392, -13, 108, 254, -227, 398, +-470, 348, -509, 127, -283, -205, 95, -446, +421, -439, 516, -228, 335, 87, -10, 373, +-324, 468, -477, 355, -376, 79, -61, -259, +289, -446, 476, -384, 409, -155, 127, 129, +-200, 338, -435, 367, -483, 221, -304, -50, +44, -306, 381, -369, 537, -224, 426, 21, +125, 248, -220, 353, -463, 289, -511, 91, +-308, -173, 65, -353, 402, -336, 497, -168, +338, 49, 35, 235, -273, 322, -465, 286, +-422, 137, -153, -93, 205, -271, 450, -306, +463, -233, 251, -65, -77, 151, -384, 306, +-515, 333, -412, 195, -94, -85, 289, -314, +530, -365, 492, -253, 218, 15, -157, 310, +-447, 447, -519, 363, -337, 62, 20, -326, +368, -532, 495, -458, 351, -165, 45, 250, +-251, 554, -399, 571, -342, 312, -119, -114, +173, -495, 353, -596, 328, -419, 136, -65, +-114, 318, -301, 520, -313, 456, -172, 192, +53, -143, 257, -373, 325, -394, 219, -244, +13, 7, -197, 238, -297, 326, -248, 256, +-103, 76, 68, -128, 218, -260, 272, -273, +207, -175, 57, 10, -112, 194, -235, 287, +-266, 265, -210, 135, -51, -66, 170, -246, +337, -324, 349, -259, 204, -57, -64, 163, +-326, 288, -453, 293, -383, 158, -107, -70, +280, -255, 536, -301, 509, -185, 211, 48, +-203, 239, -518, 299, -559, 230, -298, 25, +151, -224, 520, -368, 582, -337, 311, -138, +-135, 145, -507, 358, -589, 428, -358, 330, +65, 54, 464, -279, 610, -491, 432, -478, +52, -237, -334, 124, -522, 434, -449, 558, +-196, 405, 128, 19, 370, -399, 399, -607, +246, -479, 13, -92, -187, 354, -281, 636, +-263, 581, -141, 184, 66, -342, 231, -704, +282, -675, 225, -258, 62, 294, -161, 699, +-320, 752, -344, 392, -206, -194, 46, -684, +292, -812, 411, -488, 341, 87, 108, 584, +-161, 782, -350, 582, -381, 71, -234, -479, +31, -776, 266, -654, 360, -181, 273, 351, +61, 679, -176, 673, -327, 323, -312, -194, +-126, -612, 129, -715, 325, -432, 360, 79, +214, 516, -44, 690, -280, 534, -371, 101, +-270, -384, -55, -689, 172, -659, 310, -281, +289, 227, 117, 592, -97, 692, -242, 479, +-242, 28, -117, -421, 51, -668, 186, -602, +237, -224, 159, 237, -11, 543, -192, 607, +-283, 379, -232, -50, -75, -429, 112, -600, +271, -469, 325, -72, 229, 345, 23, 578, +-196, 550, -324, 224, -295, -240, -151, -582, +43, -667, 226, -414, 315, 77, 250, 521, +68, 729, -148, 601, -283, 152, -281, -369, +-148, -706, 62, -721, 273, -358, 356, 179, +247, 601, -7, 730, -271, 485, -406, -13, +-342, -476, -113, -695, 197, -558, 435, -104, +449, 388, 219, 663, -112, 609, -382, 230, +-462, -267, -324, -610, -30, -662, 295, -385, +474, 102, 379, 504, 101, 637, -195, 473, +-379, 87, -376, -316, -189, -537, 87, -501, +321, -218, 367, 166, 212, 416, -28, 440, +-227, 255, -301, -58, -219, -328, -51, -418, +133, -297, 262, -6, 252, 294, 104, 416, +-74, 331, -198, 97, -221, -192, -157, -384, +-31, -383, 120, -200, 218, 81, 186, 298, +65, 328, -63, 215, -147, 29, -160, -145, +-104, -217, -13, -173, 85, -55, 132, 78, +106, 127, 45, 85, -19, 33, -76, -17, +-97, -52, -97, -61, -68, -63, 13, -51, +110, -16, 153, 23, 130, 86, 38, 157, +-83, 155, -173, 63, -187, -87, -90, -228, +84, -265, 206, -165, 203, 17, 77, 214, +-109, 318, -239, 241, -229, 38, -95, -180, +121, -301, 302, -245, 311, -51, 143, 153, +-92, 264, -283, 224, -334, 48, -233, -150, +-25, -253, 202, -213, 323, -50, 268, 133, +99, 221, -92, 181, -217, 48, -219, -108, +-125, -183, 7, -140, 135, -24, 179, 105, +116, 170, 1, 122, -103, 10, -150, -97, +-122, -154, -54, -131, 53, -53, 165, 44, +199, 125, 123, 136, -13, 78, -146, 5, +-213, -46, -197, -70, -94, -62, 86, -28, +242, 19, 255, 48, 133, 25, -54, -33, +-210, -67, -266, -63, -190, -34, -7, 27, +200, 103, 296, 159, 224, 141, 40, 29, +-154, -112, -268, -187, -242, -183, -98, -112, +94, 21, 231, 146, 239, 197, 120, 136, +-52, -18, -183, -148, -202, -158, -117, -83, +21, 36, 144, 162, 204, 197, 159, 108, +26, -63, -121, -232, -204, -268, -200, -141, +-113, 40, 22, 200, 158, 278, 238, 200, +218, 19, 96, -163, -68, -254, -205, -181, +-256, -7, -195, 132, -45, 196, 128, 159, +249, 22, 245, -127, 115, -210, -79, -177, +-238, -30, -263, 119, -139, 181, 59, 166, +246, 78, 311, -47, 193, -139, -43, -166, +-260, -107, -344, 13, -246, 101, -22, 119, +215, 99, 343, 35, 293, -51, 90, -108, +-146, -122, -300, -64, -298, 44, -149, 116, +57, 141, 212, 120, 265, 19, 192, -107, +32, -187, -131, -186, -221, -70, -207, 97, +-98, 202, 36, 213, 146, 126, 197, -51, +163, -202, 53, -248, -71, -172, -161, 18, +-188, 201, -135, 249, -20, 177, 108, 20, +201, -156, 201, -223, 100, -162, -57, -21, +-194, 145, -244, 202, -176, 111, -23, -36, +159, -171, 278, -214, 250, -108, 92, 68, +-99, 219, -242, 276, -269, 168, -166, -36, +13, -206, 174, -281, 244, -223, 189, -57, +51, 114, -107, 218, -211, 215, -194, 94, +-70, -48, 80, -128, 190, -129, 200, -59, +99, 42, -62, 102, -199, 103, -230, 38, +-136, -70, 20, -142, 168, -148, 246, -95, +196, 17, 49, 138, -105, 204, -209, 201, +-220, 103, -126, -61, 30, -191, 165, -247, +217, -203, 159, -53, 30, 127, -113, 240, +-209, 238, -196, 99, -71, -101, 86, -227, +197, -233, 212, -111, 125, 102, -21, 275, +-154, 302, -227, 162, -197, -102, -69, -340, +84, -402, 186, -265, 206, 26, 137, 338, +20, 493, -96, 402, -172, 108, -161, -267, +-62, -522, 43, -514, 109, -247, 116, 149, +60, 478, -20, 563, -77, 363, -92, -24, +-44, -411, 35, -584, 91, -436, 97, -50, +50, 362, -35, 581, -102, 492, -128, 130, +-99, -316, -11, -610, 86, -572, 135, -214, +132, 270, 71, 617, -24, 637, -98, 323, +-127, -154, -103, -557, -28, -679, 44, -442, +92, 23, 102, 457, 50, 636, -22, 476, +-66, 90, -85, -312, -55, -543, 17, -487, +66, -160, 76, 239, 55, 481, -1, 458, +-46, 198, -63, -155, -62, -419, -27, -480, +10, -294, 17, 53, 31, 363, 46, 480, +43, 374, 38, 97, 9, -211, -46, -409, +-68, -422, -57, -239, -28, 58, 33, 297, +79, 372, 64, 280, 11, 63, -64, -176, +-102, -313, -54, -296, 31, -128, 104, 117, +140, 293, 83, 314, -44, 186, -152, -46, +-186, -271, -119, -367, 19, -278, 144, -40, +203, 234, 159, 391, 18, 356, -128, 148, +-197, -139, -174, -363, -48, -404, 109, -247, +195, 37, 179, 301, 76, 400, -77, 295, +-188, 48, -194, -215, -99, -352, 42, -304, +139, -106, 155, 141, 114, 300, 21, 290, +-87, 140, -131, -78, -95, -245, -21, -276, +51, -174, 77, 7, 63, 192, 28, 277, +-30, 231, -80, 89, -75, -98, -25, -247, +38, -287, 75, -219, 58, -55, 22, 151, +2, 296, -24, 315, -40, 215, -19, 15, +-2, -191, -16, -312, -42, -311, -49, -177, +-11, 40, 54, 217, 90, 284, 94, 233, +66, 77, -12, -96, -96, -198, -132, -210, +-110, -114, -28, 43, 72, 161, 121, 193, +105, 139, 35, 5, -69, -138, -137, -227, +-121, -222, -24, -104, 115, 82, 197, 238, +162, 306, 42, 246, -119, 67, -241, -156, +-229, -330, -95, -362, 81, -214, 219, 31, +242, 258, 142, 366, -14, 292, -156, 71, +-207, -179, -140, -342, -12, -312, 114, -97, +183, 165, 140, 334, 16, 326, -116, 121, +-201, -161, -180, -373, -52, -405, 112, -206, +237, 123, 258, 383, 142, 459, -49, 312, +-225, 0, -304, -308, -227, -455, -38, -393, +154, -129, 274, 194, 257, 389, 101, 380, +-94, 196, -223, -72, -228, -279, -108, -329, +56, -214, 168, 12, 193, 216, 113, 271, +-31, 187, -151, 25, -192, -135, -139, -214, +-16, -182, 103, -67, 168, 83, 172, 179, +98, 174, -38, 96, -151, -6, -185, -100, +-132, -154, -13, -157, 112, -95, 187, 14, +176, 113, 50, 162, -121, 157, -215, 93, +-191, -11, -65, -126, 111, -194, 234, -163, +229, -42, 101, 78, -98, 147, -246, 147, +-247, 77, -114, -32, 81, -116, 222, -126, +226, -40, 116, 74, -62, 120, -221, 86, +-236, 2, -98, -101, 93, -152, 235, -119, +247, -14, 121, 117, -68, 184, -231, 121, +-278, -3, -163, -111, 32, -153, 198, -97, +258, 25, 181, 129, 21, 165, -121, 84, +-201, -90, -182, -218, -68, -210, 59, -78, +137, 121, 149, 273, 92, 289, 2, 157, +-85, -81, -147, -304, -142, -351, -61, -195, +42, 58, 134, 277, 181, 344, 132, 221, +14, -28, -108, -276, -195, -370, -198, -231, +-99, 56, 47, 316, 176, 404, 224, 266, +157, -20, 20, -308, -124, -451, -220, -354, +-200, -48, -71, 280, 80, 452, 187, 383, +193, 125, 89, -179, -51, -384, -153, -394, +-175, -187, -100, 121, 24, 344, 128, 368, +173, 192, 129, -84, 19, -301, -88, -361, +-161, -239, -180, 22, -101, 275, 39, 362, +160, 261, 216, 30, 171, -203, 47, -308, +-91, -262, -197, -104, -210, 113, -112, 256, +20, 235, 127, 93, 182, -84, 143, -196, +42, -178, -55, -78, -126, 51, -130, 165, +-61, 187, 23, 92, 89, -40, 108, -145, +65, -174, 4, -122, -58, -35, -110, 58, +-89, 146, -17, 161, 40, 100, 80, 8, +90, -76, 59, -120, 16, -120, -31, -81, +-74, 8, -83, 105, -68, 135, -46, 86, +8, -5, 74, -91, 119, -120, 129, -94, +61, -16, -65, 98, -160, 164, -187, 120, +-133, 10, 14, -100, 178, -149, 261, -114, +209, -34, 27, 57, -179, 131, -287, 119, +-260, 20, -94, -78, 141, -114, 299, -80, +296, 3, 145, 67, -91, 92, -276, 86, +-303, 29, -184, -56, 30, -95, 237, -82, +315, -40, 241, 4, 49, 23, -175, 32, +-300, 51, -286, 46, -157, 19, 56, 4, +247, 0, 308, -11, 241, -23, 73, -32, +-143, -17, -284, 4, -284, -1, -154, -22, +51, -20, 217, -2, 259, 19, 184, 34, +14, 37, -166, 36, -237, 26, -181, -11, +-31, -44, 144, -40, 230, -16, 192, -5, +75, -9, -96, -15, -236, -5, -250, 8, +-150, 22, 20, 43, 188, 59, 251, 44, +203, 0, 80, -51, -95, -69, -216, -36, +-202, 2, -96, 15, 42, 21, 144, 7, +147, -27, 78, -49, -19, -40, -111, 12, +-124, 89, -53, 104, 40, 60, 118, 9, +128, -47, 56, -93, -29, -88, -101, -59, +-143, -9, -98, 34, 1, 23, 80, 1, +116, 18, 92, 44, 31, 65, -19, 74, +-59, 42, -66, -8, -27, -59, 0, -119, +0, -129, 5, -72, 0, 4, 2, 65, +24, 93, 36, 85, 31, 66, 15, 30, +-25, -20, -49, -48, -39, -44, -14, -32, +31, -22, 62, -13, 34, 3, -19, 18, +-60, 4, -80, -30, -48, -38, 29, -12, +94, 33, 114, 74, 74, 95, -14, 88, +-92, 43, -129, -48, -103, -133, -17, -147, +66, -100, 95, -27, 82, 48, 38, 89, +-23, 100, -56, 85, -46, 32, -18, -9, +18, -6, 39, -14, 27, -35, 3, -52, +-29, -63, -56, -43, -59, -1, -44, 20, +-3, 45, 69, 67, 113, 41, 98, -8, +54, -36, -22, -33, -111, 6, -149, 37, +-114, 33, -15, 19, 91, 1, 123, -44, +89, -79, 28, -69, -51, -16, -96, 49, +-70, 87, -8, 78, 64, 52, 98, 2, +56, -66, -18, -106, -71, -89, -92, -27, +-70, 56, -10, 111, 61, 119, 114, 79, +101, -10, 22, -120, -53, -182, -100, -161, +-117, -57, -65, 78, 32, 180, 112, 211, +141, 159, 95, 28, -10, -115, -105, -192, +-153, -179, -130, -87, -30, 32, 78, 108, +135, 129, 122, 89, 34, 2, -64, -72, +-94, -90, -69, -52, -11, 30, 62, 90, +83, 95, 32, 64, -45, 6, -97, -77, +-78, -131, -4, -126, 57, -69, 88, 14, +72, 84, 0, 113, -59, 112, -60, 81, +-24, 9, 38, -69, 85, -99, 53, -81, +-23, -35, -89, 10, -119, 44, -79, 62, +10, 45, 93, -21, 141, -82, 113, -86, +17, -36, -67, 39, -104, 108, -92, 141, +-25, 127, 43, 38, 64, -103, 47, -205, +2, -205, -45, -116, -50, 21, -23, 143, +20, 212, 58, 191, 49, 67, 18, -102, +2, -202, -16, -184, -29, -65, -24, 78, +-24, 177, -25, 190, -19, 96, -8, -83, +18, -226, 49, -239, 56, -118, 43, 66, +10, 216, -35, 261, -59, 188, -55, 16, +-43, -176, -4, -269, 48, -209, 67, -51, +54, 117, 26, 211, -20, 193, -66, 85, +-91, -58, -79, -172, -15, -177, 62, -78, +109, 44, 121, 131, 71, 150, -34, 90, +-121, -2, -157, -92, -120, -143, -6, -112, +116, -17, 170, 68, 141, 120, 33, 115, +-99, 50, -176, -36, -160, -112, -46, -141, +111, -86, 199, 10, 178, 95, 64, 138, +-95, 107, -206, 19, -198, -73, -84, -134, +77, -123, 204, -44, 222, 51, 126, 110, +-32, 111, -179, 46, -234, -33, -174, -90, +-40, -103, 124, -57, 241, 20, 235, 78, +115, 98, -51, 68, -202, 10, -262, -36, +-190, -66, -29, -78, 149, -58, 254, -28, +227, 4, 87, 43, -99, 74, -230, 80, +-227, 71, -112, 25, 53, -51, 205, -100, +250, -99, 145, -56, -34, 20, -198, 80, +-268, 98, -201, 72, -36, -1, 153, -81, +284, -98, 269, -56, 113, 12, -92, 73, +-255, 92, -291, 66, -180, 16, 8, -52, +186, -89, 277, -66, 220, -18, 52, 18, +-130, 35, -241, 27, -222, 16, -90, 3, +75, -14, 215, -16, 258, 0, 159, 8, +-20, 6, -181, -4, -260, -8, -209, 2, +-60, 2, 111, -15, 239, -22, 253, -21, +133, -12, -42, 6, -194, 26, -249, 42, +-172, 49, -15, 22, 144, -22, 245, -51, +215, -60, 64, -52, -117, -19, -248, 20, +-252, 56, -115, 73, 86, 58, 249, 17, +293, -17, 179, -55, -35, -84, -234, -78, +-323, -40, -243, 17, -28, 79, 199, 110, +325, 99, 293, 51, 113, -31, -132, -114, +-317, -139, -343, -105, -187, -20, 65, 79, +277, 137, 358, 122, 270, 50, 36, -58, +-221, -135, -361, -134, -310, -58, -95, 55, +164, 148, 327, 153, 321, 71, 150, -52, +-105, -157, -303, -189, -332, -121, -177, 16, +74, 155, 272, 214, 317, 157, 210, 19, +-1, -121, -220, -197, -324, -167, -257, -51, +-60, 94, 163, 190, 286, 175, 262, 52, +126, -97, -59, -191, -207, -183, -249, -80, +-177, 62, -21, 176, 140, 202, 211, 112, +182, -37, 93, -145, -32, -161, -152, -100, +-209, 5, -173, 88, -46, 114, 107, 72, +201, -16, 210, -84, 129, -69, -27, -4, +-184, 53, -263, 69, -216, 37, -39, -20, +170, -61, 278, -61, 246, -4, 105, 69, +-94, 85, -264, 22, -303, -71, -169, -133, +65, -109, 250, -14, 299, 104, 201, 185, +-3, 169, -209, 39, -308, -117, -249, -204, +-52, -169, 179, -32, 300, 121, 254, 199, +89, 165, -114, 26, -266, -137, -291, -222, +-171, -174, 45, -23, 238, 141, 301, 220, +227, 192, 61, 80, -146, -70, -294, -180, +-299, -190, -162, -110, 56, 8, 240, 100, +296, 132, 216, 102, 40, 30, -158, -58, +-272, -106, -244, -91, -86, -29, 122, 56, +247, 136, 227, 149, 104, 79, -65, -50, +-214, -180, -252, -243, -148, -187, 33, -36, +192, 158, 243, 294, 177, 284, 38, 133, +-119, -76, -219, -251, -210, -291, -110, -173, +35, 29, 158, 207, 195, 271, 140, 175, +29, -18, -89, -207, -160, -288, -157, -217, +-80, -27, 44, 184, 146, 324, 170, 319, +116, 160, 9, -84, -108, -292, -175, -380, +-168, -312, -82, -108, 58, 159, 167, 357, +188, 390, 130, 244, 12, -9, -112, -253, +-175, -371, -158, -308, -63, -86, 71, 179, +156, 341, 153, 309, 87, 109, -17, -157, +-112, -344, -152, -344, -115, -159, -8, 108, +108, 335, 162, 385, 139, 223, 54, -47, +-71, -276, -166, -362, -179, -259, -103, -33, +34, 193, 156, 311, 192, 259, 131, 60, +7, -139, -126, -247, -194, -230, -156, -93, +-39, 93, 100, 219, 184, 235, 166, 128, +68, -38, -61, -162, -158, -203, -170, -164, +-98, -52, 7, 76, 97, 157, 133, 162, +112, 92, 55, -16, -11, -91, -63, -111, +-84, -87, -82, -27, -55, 52, -5, 94, +45, 77, 80, 11, 85, -57, 44, -87, +-15, -75, -64, -40, -86, 22, -59, 86, +8, 108, 71, 73, 98, 11, 71, -50, +2, -86, -65, -92, -109, -61, -120, 2, +-66, 73, 35, 107, 119, 83, 153, 11, +126, -64, 36, -111, -75, -108, -156, -47, +-172, 52, -102, 139, 19, 167, 127, 91, +173, -43, 141, -150, 48, -189, -58, -146, +-141, -27, -165, 103, -101, 186, 17, 172, +115, 59, 152, -68, 121, -135, 38, -134, +-70, -58, -157, 50, -162, 125, -74, 126, +43, 52, 133, -62, 158, -134, 108, -130, +9, -66, -94, 26, -164, 111, -158, 137, +-63, 104, 71, 31, 169, -47, 189, -94, +122, -89, -8, -63, -149, -34, -225, -10, +-179, 10, -29, 33, 135, 62, 225, 71, +198, 69, 70, 37, -89, -29, -205, -90, +-224, -101, -116, -61, 59, 22, 192, 93, +223, 107, 134, 57, -25, -35, -161, -130, +-224, -149, -184, -78, -31, 50, 151, 178, +244, 227, 206, 154, 63, -1, -108, -170, +-219, -271, -232, -249, -128, -102, 56, 108, +207, 269, 228, 290, 135, 177, -12, -18, +-143, -199, -199, -284, -154, -227, -32, -43, +106, 165, 179, 267, 152, 227, 47, 70, +-77, -126, -154, -264, -147, -266, -67, -126, +53, 102, 157, 278, 170, 305, 84, 179, +-44, -36, -148, -242, -175, -331, -117, -261, +-4, -57, 124, 186, 195, 335, 156, 301, +40, 125, -90, -100, -179, -275, -171, -313, +-80, -187, 36, 28, 141, 228, 176, 299, +105, 207, -22, 22, -123, -152, -149, -253, +-94, -227, -2, -82, 87, 102, 141, 224, +121, 226, 24, 104, -84, -53, -146, -171, +-127, -210, -42, -151, 53, -5, 128, 135, +162, 199, 107, 158, -23, 39, -135, -93, +-164, -168, -115, -163, -22, -78, 75, 52, +150, 157, 161, 170, 76, 95, -51, -31, +-135, -133, -155, -161, -110, -117, -10, -24, +92, 106, 157, 187, 162, 156, 76, 41, +-57, -84, -150, -174, -165, -177, -107, -107, +-3, 15, 111, 146, 178, 206, 138, 152, +8, 41, -102, -74, -132, -153, -98, -166, +-20, -105, 60, -12, 99, 79, 84, 126, +11, 111, -62, 51, -67, -7, -31, -53, +4, -69, 24, -48, 12, -11, -1, 24, +8, 53, -5, 41, -8, 1, 37, -38, +55, -74, 0, -91, -59, -48, -76, 27, +-45, 104, 8, 157, 55, 146, 90, 62, +88, -51, 11, -167, -85, -223, -123, -179, +-97, -59, -20, 84, 66, 211, 112, 238, +122, 144, 81, -6, -18, -136, -108, -204, +-134, -164, -95, -41, -18, 93, 56, 169, +105, 141, 125, 26, 78, -89, -25, -159, +-100, -164, -116, -76, -90, 63, -18, 168, +76, 208, 138, 162, 134, 47, 39, -84, +-97, -188, -177, -238, -156, -189, -57, -54, +74, 109, 171, 235, 185, 271, 96, 185, +-55, 11, -162, -184, -160, -303, -86, -273, +23, -94, 124, 131, 153, 290, 101, 306, +-5, 167, -120, -79, -159, -297, -102, -364, +-2, -226, 107, 45, 169, 293, 138, 385, +40, 288, -89, 26, -191, -280, -174, -439, +-54, -353, 77, -71, 165, 270, 175, 477, +87, 430, -61, 159, -174, -208, -180, -499, +-75, -536, 69, -299, 170, 95, 175, 451, +84, 578, -58, 410, -173, 65, -190, -299, +-93, -522, 56, -477, 174, -183, 201, 173, +121, 411, -27, 414, -161, 199, -209, -105, +-145, -340, 6, -399, 152, -220, 206, 94, +157, 354, 38, 429, -105, 287, -193, -17, +-172, -314, -70, -457, 52, -386, 137, -131, +150, 184, 92, 388, -1, 399, -84, 227, +-111, -28, -78, -227, -17, -284, 36, -209, +61, -44, 51, 114, 22, 175, -8, 123, +-33, 24, -49, -77, -46, -127, -20, -101, +25, -24, 62, 54, 72, 115, 58, 129, +16, 101, -51, 33, -99, -58, -95, -138, +-51, -164, 17, -150, 76, -81, 95, 58, +84, 195, 42, 233, -33, 170, -91, 33, +-97, -122, -65, -235, 6, -247, 81, -134, +99, 71, 71, 237, 20, 270, -55, 166, +-97, -19, -74, -208, -27, -290, 18, -224, +52, -41, 65, 175, 65, 311, 44, 266, +-4, 85, -52, -124, -81, -263, -93, -275, +-64, -149, 10, 54, 93, 237, 133, 289, +97, 178, 4, -5, -89, -161, -136, -259, +-105, -240, -20, -91, 54, 105, 96, 242, +103, 270, 57, 168, -9, -4, -52, -164, +-83, -257, -99, -234, -76, -91, -12, 85, +93, 213, 170, 238, 139, 138, 28, -31, +-96, -161, -194, -218, -191, -174, -60, -24, +118, 150, 233, 233, 209, 203, 60, 67, +-108, -104, -216, -227, -219, -256, -100, -167, +65, 30, 191, 204, 230, 258, 148, 204, +-13, 70, -144, -97, -200, -207, -177, -223, +-56, -140, 95, 8, 191, 135, 193, 169, +84, 140, -61, 57, -147, -56, -165, -142, +-107, -154, 25, -89, 129, 35, 130, 138, +65, 161, -18, 109, -75, 17, -76, -104, +-37, -182, 12, -160, 40, -55, 28, 69, +6, 153, 0, 148, 7, 89, 11, 14, +-12, -73, -44, -138, -41, -125, -11, -64, +36, 13, 83, 86, 80, 127, 22, 114, +-44, 48, -101, -74, -111, -170, -44, -159, +40, -54, 83, 82, 93, 202, 66, 211, +13, 89, -41, -85, -83, -226, -83, -264, +-34, -141, 7, 64, 33, 221, 81, 255, +110, 155, 59, -18, -34, -149, -109, -206, +-129, -172, -87, -44, 4, 98, 119, 148, +184, 127, 131, 66, -4, -17, -142, -93, +-210, -129, -154, -111, -4, -21, 145, 85, +223, 146, 184, 151, 31, 90, -159, -44, +-266, -168, -212, -216, -25, -166, 163, -21, +256, 159, 227, 247, 70, 211, -140, 78, +-259, -99, -210, -236, -60, -240, 86, -119, +179, 68, 197, 212, 116, 223, -24, 116, +-138, -30, -189, -176, -164, -233, -56, -143, +94, 20, 215, 153, 238, 215, 120, 171, +-83, 50, -250, -86, -285, -185, -158, -197, +68, -102, 252, 21, 283, 119, 158, 172, +-54, 152, -232, 53, -261, -59, -132, -150, +58, -177, 196, -109, 219, 14, 129, 117, +-22, 182, -145, 162, -187, 45, -138, -100, +-21, -198, 93, -211, 151, -106, 159, 50, +102, 174, -31, 221, -150, 161, -176, 1, +-123, -143, -16, -193, 107, -134, 171, 5, +136, 138, 22, 160, -97, 83, -144, -45, +-108, -156, -29, -168, 58, -50, 100, 103, +76, 192, 28, 165, -20, 38, -63, -100, +-65, -158, -28, -129, 7, -18, 17, 103, +18, 125, 31, 44, 33, -47, -6, -107, +-33, -91, -15, 6, -12, 101, -30, 125, +-4, 76, 39, -30, 50, -110, 30, -109, +-2, -43, -27, 52, -42, 122, -58, 84, +-44, -23, 3, -112, 52, -152, 91, -118, +105, 18, 66, 162, -10, 210, -102, 140, +-168, 3, -145, -134, -25, -203, 128, -173, +217, -38, 170, 125, 28, 187, -125, 110, +-225, 0, -197, -96, -30, -151, 149, -111, +229, 29, 177, 152, 13, 180, -146, 99, +-199, -32, -157, -136, -40, -165, 112, -121, +182, -11, 135, 95, 37, 129, -61, 100, +-123, 36, -121, -50, -70, -84, 2, -51, +72, -19, 109, -5, 110, 35, 69, 60, +-10, 48, -89, 18, -134, -7, -136, -30, +-74, -63, 42, -116, 151, -102, 189, -5, +131, 94, 17, 162, -109, 207, -218, 153, +-222, -11, -78, -191, 106, -297, 224, -276, +248, -107, 141, 127, -60, 322, -235, 373, +-279, 223, -169, -67, 34, -327, 214, -448, +285, -337, 213, -6, 18, 362, -184, 537, +-282, 438, -242, 92, -84, -342, 126, -615, +267, -551, 259, -176, 118, 318, -75, 633, +-218, 589, -249, 226, -146, -269, 35, -633, +177, -610, 214, -225, 154, 273, 26, 620, +-112, 628, -186, 271, -170, -240, -89, -632, +40, -696, 163, -385, 209, 131, 152, 563, +24, 718, -124, 524, -219, 67, -201, -424, +-75, -686, 97, -604, 221, -211, 212, 284, +75, 610, -81, 600, -166, 271, -155, -220, +-55, -594, 70, -626, 127, -292, 88, 220, +-2, 625, -69, 670, -53, 336, 9, -183, +41, -613, 30, -719, -3, -409, -53, 125, +-69, 571, -20, 678, 50, 402, 85, -83, +73, -486, 21, -602, -44, -360, -89, 113, +-90, 505, -51, 551, 10, 263, 83, -177, +133, -515, 106, -537, 13, -223, -96, 228, +-172, 550, -156, 515, -38, 155, 116, -273, +222, -518, 199, -451, 50, -84, -124, 331, +-230, 510, -228, 358, -89, -19, 112, -395, +241, -514, 248, -312, 136, 86, -55, 447, +-217, 545, -272, 308, -193, -106, -5, -472, +185, -573, 273, -336, 233, 90, 70, 454, +-125, 590, -236, 409, -227, -18, -108, -455, +74, -638, 196, -474, 196, -60, 106, 380, +-22, 634, -114, 570, -132, 195, -110, -309, +-38, -637, 66, -610, 121, -277, 118, 183, +86, 556, 4, 636, -96, 375, -157, -82, +-147, -489, -42, -631, 110, -436, 193, -34, +170, 376, 68, 599, -65, 525, -167, 187, +-189, -239, -116, -553, 25, -589, 138, -328, +170, 81, 140, 439, 59, 607, -53, 481, +-150, 100, -198, -335, -128, -596, 40, -561, +166, -244, 195, 193, 152, 550, 13, 647, +-147, 400, -214, -89, -161, -530, -5, -694, +157, -500, 191, -39, 124, 461, 23, 732, +-101, 629, -175, 178, -146, -381, -51, -725, +78, -670, 167, -286, 158, 227, 89, 615, +-6, 699, -120, 421, -181, -84, -149, -539, +-37, -672, 115, -458, 202, -56, 169, 362, +65, 637, -68, 591, -181, 220, -198, -275, +-99, -620, 64, -638, 195, -337, 207, 109, +115, 526, -12, 713, -145, 519, -226, 26, +-183, -473, -39, -711, 127, -565, 235, -138, +228, 329, 112, 628, -55, 628, -204, 271, +-251, -252, -160, -616, 21, -621, 193, -314, +256, 125, 186, 486, 40, 634, -129, 477, +-248, 44, -230, -425, -74, -649, 123, -546, +251, -207, 246, 215, 135, 558, -33, 651, +-208, 428, -290, -25, -199, -462, -8, -656, +163, -525, 265, -163, 274, 280, 160, 598, +-41, 624, -237, 322, -337, -160, -270, -560, +-49, -653, 211, -415, 386, 18, 384, 446, +171, 672, -161, 550, -421, 134, -465, -344, +-243, -629, 138, -593, 442, -276, 504, 152, +315, 505, -51, 616, -403, 414, -528, 11, +-354, -368, 15, -562, 376, -484, 521, -188, +388, 191, 66, 490, -288, 573, -477, 363, +-390, -31, -102, -406, 226, -593, 423, -508, +389, -179, 172, 239, -103, 568, -311, 632, +-349, 372, -225, -74, -15, -465, 205, -642, +329, -514, 291, -135, 151, 321, -40, 627, +-239, 627, -348, 294, -287, -193, -66, -592, +220, -713, 406, -481, 391, 17, 183, 529, +-145, 798, -419, 671, -450, 195, -225, -394, +126, -776, 414, -783, 471, -407, 265, 175, +-77, 670, -356, 810, -408, 540, -239, 4, +36, -506, 302, -732, 405, -587, 254, -159, +-3, 348, -199, 651, -284, 612, -223, 275, +-54, -193, 114, -574, 221, -657, 212, -418, +98, 17, -3, 442, -61, 662, -120, 570, +-142, 213, -115, -268, -49, -629, 89, -673, +223, -393, 253, 60, 185, 498, 12, 698, +-228, 550, -379, 122, -323, -370, -55, -681, +301, -632, 504, -265, 434, 229, 147, 611, +-249, 691, -544, 425, -526, -47, -202, -504, +260, -708, 595, -554, 577, -130, 247, 335, +-191, 649, -542, 662, -592, 352, -292, -158, +162, -608, 534, -756, 625, -512, 365, -2, +-71, 533, -446, 825, -594, 702, -418, 174, +-23, -483, 363, -903, 577, -838, 502, -321, +157, 390, -239, 896, -477, 923, -476, 454, +-246, -253, 95, -825, 395, -940, 517, -539, +374, 140, 56, 714, -248, 891, -435, 599, +-414, 25, -172, -555, 136, -857, 373, -728, +460, -234, 325, 348, 34, 765, -246, 839, +-402, 541, -365, -8, -156, -586, 109, -936, +334, -846, 419, -335, 286, 352, 17, 905, +-226, 1058, -350, 680, -311, -57, -130, -813, +111, -1199, 311, -970, 378, -210, 265, 672, +37, 1248, -192, 1205, -324, 527, -312, -438, +-169, -1209, 64, -1402, 302, -864, 405, 134, +315, 1066, 94, 1470, -156, 1159, -331, 257, +-362, -772, -246, -1428, -1, -1383, 285, -636, +451, 437, 406, 1272, 190, 1492, -114, 994, +-393, -16, -519, -1036, -393, -1549, -34, -1320, +374, -431, 599, 687, 557, 1477, 268, 1560, +-168, 908, -552, -209, -672, -1232, -449, -1660, +7, -1311, 461, -333, 715, 818, 652, 1548, +283, 1531, -231, 817, -639, -279, -745, -1256, +-478, -1610, 42, -1201, 556, -222, 822, 843, +723, 1491, 277, 1449, -342, 759, -818, -326, +-876, -1282, -483, -1610, 158, -1195, 738, -246, +992, 841, 788, 1558, 182, 1579, -566, 876, +-1039, -265, -959, -1324, -408, -1765, 336, -1408, +957, -389, 1136, 847, 745, 1715, -34, 1797, +-819, 1046, -1176, -263, -899, -1509, -182, -2023, +605, -1553, 1112, -333, 1076, 1100, 507, 2050, +-296, 2025, -936, 960, -1070, -644, -661, -1964, +13, -2292, 654, -1492, 1011, 56, 906, 1621, +389, 2410, -302, 1985, -842, 556, -944, -1148, +-610, -2272, -53, -2258, 558, -1130, 968, 509, +911, 1872, 413, 2304, -267, 1620, -813, 166, +-958, -1322, -678, -2132, -99, -1884, 590, -761, +1034, 647, 951, 1713, 422, 1984, -296, 1306, +-885, 17, -1047, -1236, -712, -1873, -21, -1631, +748, -628, 1176, 630, 1001, 1590, 332, 1808, +-489, 1160, -1066, -36, -1113, -1176, -617, -1752, +220, -1494, 992, -531, 1252, 632, 868, 1469, +86, 1631, -706, 1014, -1128, -62, -1006, -1058, +-400, -1535, 440, -1320, 1069, -507, 1110, 496, +612, 1263, -124, 1465, -772, 989, -1024, 64, +-769, -867, -159, -1415, 527, -1326, 920, -605, +832, 402, 393, 1211, -168, 1470, -621, 1020, +-766, 85, -578, -877, -134, -1404, 402, -1269, +740, -518, 709, 457, 384, 1179, -79, 1322, +-501, 837, -699, -10, -574, -788, -143, -1186, +381, -1059, 683, -446, 663, 356, 391, 933, +-59, 1085, -498, 771, -693, 140, -570, -534, +-168, -972, 342, -1004, 693, -573, 726, 119, +420, 733, -116, 1024, -603, 858, -790, 297, +-587, -372, -49, -883, 542, -1023, 827, -670, +679, 31, 208, 672, -347, 984, -693, 853, +-657, 350, -279, -301, 223, -834, 559, -1007, +596, -688, 375, -54, 14, 548, -305, 903, +-426, 900, -345, 504, -133, -97, 120, -668, +309, -983, 368, -885, 284, -379, 81, 282, +-140, 831, -283, 1052, -313, 823, -202, 211, +19, -538, 225, -1097, 346, -1150, 334, -625, +146, 202, -133, 939, -347, 1291, -390, 1021, +-225, 209, 70, -732, 339, -1330, 455, -1313, +353, -626, 48, 390, -290, 1218, -448, 1480, +-347, 1018, -67, 37, 254, -941, 457, -1471, +419, -1320, 163, -499, -179, 584, -426, 1321, +-415, 1424, -162, 851, 188, -139, 449, -1032, +452, -1387, 191, -1091, -156, -253, -418, 702, +-445, 1247, -180, 1176, 193, 564, 427, -321, +424, -999, 174, -1162, -187, -802, -411, -72, +-385, 704, -147, 1060, 193, 891, 408, 358, +375, -303, 160, -784, -145, -864, -383, -577, +-370, -53, -153, 482, 123, 716, 367, 597, +430, 297, 257, -103, -10, -442, -275, -564, +-426, -454, -330, -181, -48, 175, 249, 394, +432, 436, 386, 370, 151, 161, -119, -141, +-334, -355, -394, -433, -231, -362, 46, -137, +267, 123, 338, 328, 248, 476, 74, 426, +-107, 160, -256, -188, -297, -475, -192, -586, +6, -414, 193, -45, 278, 376, 253, 690, +166, 668, -3, 261, -228, -277, -368, -686, +-312, -789, -82, -504, 202, 65, 397, 595, +448, 848, 316, 682, -19, 186, -393, -374, +-564, -741, -438, -790, -60, -475, 346, 69, +550, 537, 529, 754, 289, 683, -156, 311, +-547, -214, -648, -656, -425, -831, 22, -641, +442, -95, 620, 496, 552, 866, 225, 869, +-279, 446, -655, -243, -694, -840, -392, -1070, +136, -769, 574, -18, 688, 734, 524, 1093, +135, 989, -377, 406, -691, -436, -626, -1081, +-275, -1179, 194, -708, 552, 141, 634, 894, +470, 1180, 103, 945, -338, 251, -599, -627, +-575, -1179, -304, -1119, 137, -525, 512, 344, +630, 1049, 481, 1177, 101, 760, -369, -13, +-659, -827, -625, -1225, -303, -958, 155, -245, +537, 575, 677, 1107, 512, 1050, 90, 515, +-390, -224, -693, -900, -698, -1107, -400, -713, +115, -41, 623, 588, 852, 972, 661, 852, +139, 350, -474, -256, -875, -759, -858, -892, +-414, -557, 257, -44, 827, 451, 995, 784, +666, 716, -5, 325, -676, -146, -1008, -597, +-842, -769, -274, -537, 428, -109, 955, 329, +1012, 681, 510, 693, -252, 368, -857, -94, +-1050, -536, -753, -726, -84, -538, 642, -141, +1058, 303, 914, 660, 269, 692, -506, 377, +-989, -68, -966, -506, -474, -725, 234, -586, +809, -182, 955, 272, 612, 638, -45, 713, +-636, 437, -827, -22, -606, -476, -170, -735, +310, -621, 647, -216, 677, 255, 383, 628, +-97, 736, -493, 448, -608, -29, -487, -497, +-208, -776, 200, -666, 544, -193, 602, 334, +370, 728, -42, 818, -452, 471, -634, -103, +-534, -625, -224, -911, 211, -725, 559, -146, +602, 456, 331, 840, -118, 873, -491, 429, +-562, -202, -401, -689, -108, -888, 278, -647, +513, -46, 412, 507, 125, 786, -186, 724, +-379, 282, -353, -280, -190, -645, 29, -746, +249, -476, 310, 69, 187, 533, 11, 698, +-147, 584, -234, 168, -211, -338, -143, -634, +-33, -662, 120, -403, 200, 100, 156, 529, +63, 664, -63, 543, -180, 183, -225, -301, +-190, -602, -67, -662, 89, -450, 143, 32, +109, 502, 63, 673, -5, 589, -91, 245, +-157, -287, -162, -656, -69, -702, 37, -443, +83, 96, 93, 592, 54, 734, -29, 554, +-89, 131, -104, -430, -43, -734, 55, -664, +65, -315, -21, 223, -99, 655, -113, 696, +-31, 456, 85, 46, 127, -448, 80, -710, +-42, -609, -214, -271, -298, 225, -201, 614, +18, 669, 238, 443, 313, 44, 170, -453, +-66, -713, -274, -584, -390, -202, -322, 281, +-91, 640, 144, 645, 306, 349, 327, -91, +174, -518, -63, -677, -289, -447, -409, -43, +-326, 359, -100, 580, 168, 498, 383, 184, +386, -159, 159, -448, -143, -522, -395, -299, +-458, 21, -277, 267, 12, 404, 265, 353, +392, 150, 308, -75, 57, -265, -240, -357, +-454, -236, -459, -57, -251, 90, 39, 225, +297, 276, 412, 190, 292, 75, 9, -72, +-265, -232, -429, -258, -395, -178, -196, -78, +15, 97, 185, 251, 287, 275, 252, 193, +130, 30, -27, -203, -221, -302, -355, -255, +-358, -132, -242, 76, 15, 276, 301, 298, +437, 192, 373, 26, 103, -193, -288, -304, +-560, -225, -577, -89, -351, 86, 73, 227, +488, 227, 619, 129, 429, 30, 19, -127, +-474, -206, -781, -128, -708, -44, -329, 15, +214, 96, 679, 104, 763, 73, 443, 77, +-101, 28, -661, -47, -915, -38, -705, -82, +-190, -156, 410, -143, 810, -53, 746, 96, +310, 295, -239, 328, -710, 170, -864, -32, +-589, -298, -84, -513, 435, -425, 769, -85, +706, 332, 282, 644, -273, 611, -763, 214, +-920, -248, -614, -631, -59, -742, 498, -431, +839, 125, 723, 609, 226, 816, -370, 581, +-846, 12, -951, -497, -593, -749, -3, -694, +560, -263, 845, 318, 683, 721, 184, 774, +-410, 444, -861, -134, -899, -581, -483, -744, +124, -599, 624, -129, 815, 420, 581, 699, +32, 644, -536, 281, -857, -257, -778, -604, +-300, -581, 325, -322, 733, 96, 724, 442, +339, 503, -225, 310, -692, -3, -835, -323, +-574, -388, -28, -213, 496, -24, 672, 144, +446, 235, 19, 149, -417, 29, -663, -19, +-554, -59, -210, -60, 176, 2, 450, -28, +393, -85, 49, -94, -256, -67, -405, 24, +-361, 161, -120, 182, 107, 123, 211, 82, +221, -50, 30, -228, -240, -263, -313, -200, +-212, -72, -43, 136, 149, 302, 200, 318, +97, 267, -46, 57, -244, -264, -382, -451, +-272, -428, -38, -220, 178, 173, 316, 494, +210, 539, -64, 397, -260, 41, -414, -469, +-468, -710, -251, -555, 85, -150, 338, 357, +438, 714, 257, 678, -96, 372, -388, -132, +-577, -667, -565, -819, -255, -523, 154, -49, +468, 462, 579, 769, 364, 665, -80, 301, +-464, -160, -680, -626, -654, -760, -304, -513, +219, -104, 624, 330, 719, 649, 394, 658, +-185, 431, -661, 31, -856, -467, -715, -747, +-210, -655, 408, -333, 782, 159, 752, 660, +320, 871, -321, 684, -828, 185, -977, -504, +-719, -989, -152, -994, 482, -546, 876, 196, +835, 936, 364, 1223, -315, 922, -866, 200, +-1057, -698, -821, -1311, -213, -1249, 504, -608, +962, 330, 950, 1161, 468, 1415, -295, 967, +-948, 120, -1174, -828, -877, -1397, -171, -1240, +607, -519, 1063, 417, 989, 1188, 402, 1347, +-422, 852, -1071, 28, -1236, -825, -831, -1323, +-51, -1143, 708, -464, 1095, 418, 929, 1141, +278, 1301, -541, 840, -1115, 67, -1171, -779, +-706, -1317, 23, -1195, 669, -529, 954, 356, +781, 1119, 243, 1354, -417, 963, -918, 169, +-1018, -727, -665, -1347, -70, -1297, 471, -653, +796, 274, 777, 1111, 365, 1446, -245, 1068, +-776, 208, -985, -747, -742, -1396, -213, -1367, +357, -653, 779, 346, 835, 1189, 461, 1462, +-163, 1011, -774, 96, -1055, -817, -847, -1377, +-312, -1257, 295, -519, 759, 386, 883, 1064, +587, 1279, -36, 889, -707, 121, -1075, -617, +-971, -1087, -485, -1101, 166, -610, 735, 86, +972, 727, 727, 1093, 92, 979, -632, 441, +-1078, -234, -1029, -881, -545, -1183, 124, -893, +704, -207, 964, 551, 770, 1120, 148, 1186, +-611, 683, -1069, -126, -1024, -914, -566, -1319, +98, -1052, 686, -298, 946, 570, 750, 1210, +149, 1307, -557, 758, -999, -119, -1015, -967, +-635, -1431, -49, -1178, 524, -324, 892, 621, +852, 1295, 355, 1417, -352, 848, -935, -127, +-1149, -1036, -899, -1531, -268, -1254, 495, -337, +1060, 658, 1113, 1334, 565, 1454, -320, 845, +-1073, -152, -1347, -1034, -1029, -1498, -252, -1237, +642, -307, 1231, 669, 1182, 1288, 502, 1372, +-429, 790, -1164, -177, -1393, -1007, -1006, -1434, +-175, -1159, 717, -244, 1255, 697, 1140, 1242, +432, 1291, -502, 712, -1216, -220, -1380, -984, +-947, -1343, -125, -1097, 735, -223, 1186, 682, +1011, 1166, 374, 1173, -439, 674, -1089, -159, +-1256, -857, -890, -1194, -157, -1007, 629, -263, +1066, 546, 950, 969, 393, 1014, -372, 643, +-1004, -56, -1176, -671, -819, -962, -129, -881, +582, -329, 964, 370, 853, 790, 348, 880, +-348, 656, -938, 104, -1099, -477, -783, -853, +-155, -921, 507, -522, 871, 160, 797, 684, +359, 934, -297, 849, -859, 338, -1022, -351, +-747, -857, -197, -1052, 386, -752, 732, -39, +719, 647, 373, 1007, -173, 956, -680, 449, +-891, -251, -717, -811, -261, -1058, 262, -816, +623, -113, 677, 588, 402, 952, -116, 914, +-618, 487, -810, -176, -635, -732, -233, -996, +237, -824, 542, -218, 521, 492, 253, 921, +-122, 953, -460, 589, -595, -42, -491, -661, +-247, -1034, 22, -978, 236, -390, 330, 389, +278, 930, 90, 1064, -171, 788, -397, 141, +-493, -597, -433, -1107, -222, -1138, 50, -598, +248, 243, 334, 925, 285, 1207, 66, 984, +-230, 297, -472, -549, -551, -1178, -416, -1307, +-136, -763, 194, 161, 470, 960, 515, 1323, +265, 1126, -167, 383, -582, -556, -762, -1264, +-619, -1415, -229, -869, 271, 102, 658, 978, +707, 1433, 373, 1273, -187, 511, -720, -503, +-956, -1309, -780, -1584, -285, -1092, 313, -44, +761, 1004, 824, 1609, 454, 1521, -162, 693, +-745, -484, -1031, -1459, -879, -1788, -365, -1232, +299, -31, 815, 1137, 906, 1764, 548, 1582, +-84, 610, -740, -659, -1097, -1566, -981, -1771, +-443, -1116, 316, 128, 915, 1250, 1033, 1736, +641, 1455, -93, 479, -850, -712, -1254, -1528, +-1101, -1681, -437, -1061, 441, 119, 1072, 1165, +1138, 1638, 624, 1432, -217, 550, -992, -596, +-1348, -1392, -1120, -1598, -370, -1103, 558, -41, +1161, 988, 1131, 1506, 541, 1397, -320, 634, +-1054, -413, -1315, -1201, -990, -1486, -225, -1127, +610, -167, 1076, 814, 982, 1366, 402, 1356, +-370, 714, -933, -287, -1092, -1088, -830, -1417, +-192, -1145, 512, -288, 900, 692, 841, 1295, +378, 1347, -278, 767, -788, -175, -983, -954, +-806, -1313, -273, -1165, 358, -418, 764, 528, +786, 1148, 410, 1276, -163, 855, -645, 20, +-873, -751, -780, -1187, -363, -1166, 175, -567, +566, 316, 687, 962, 485, 1197, 32, 913, +-408, 183, -703, -569, -789, -1032, -539, -1118, +-57, -663, 397, 129, 679, 779, 654, 1081, +275, 946, -256, 354, -703, -347, -897, -872, +-705, -1100, -204, -834, 364, -151, 781, 535, +818, 1032, 390, 1140, -239, 697, -769, -57, +-1028, -766, -847, -1228, -276, -1159, 369, -514, +848, 374, 935, 1132, 497, 1409, -203, 979, +-803, 105, -1117, -798, -949, -1383, -342, -1343, +365, -619, 899, 395, 1011, 1217, 546, 1464, +-202, 1003, -822, 79, -1115, -832, -922, -1372, +-302, -1298, 383, -595, 850, 392, 922, 1172, +508, 1415, -159, 984, -722, 113, -1013, -766, +-890, -1315, -362, -1315, 260, -655, 731, 333, +898, 1130, 590, 1402, -24, 1022, -620, 159, +-1006, -729, -973, -1295, -482, -1274, 169, -610, +693, 324, 904, 1028, 663, 1268, 71, 923, +-566, 144, -983, -638, -965, -1105, -510, -1098, +96, -556, 594, 206, 854, 812, 706, 1076, +175, 879, -456, 264, -917, -434, -990, -939, +-597, -1048, 12, -652, 551, 36, 877, 657, +790, 1035, 248, 952, -439, 380, -943, -350, +-1030, -873, -632, -1013, -7, -683, 541, -45, +872, 577, 806, 941, 268, 892, -442, 382, +-929, -265, -997, -719, -627, -873, -27, -658, +505, -120, 813, 440, 746, 790, 237, 801, +-398, 420, -809, -144, -879, -563, -574, -768, +-53, -663, 392, -199, 658, 338, 658, 661, +286, 724, -269, 452, -670, -35, -770, -443, +-569, -658, -139, -641, 316, -273, 596, 220, +586, 537, 249, 639, -227, 473, -571, 68, +-664, -313, -466, -565, -83, -598, 227, -302, +367, 128, 359, 382, 181, 486, -82, 429, +-286, 155, -407, -144, -403, -329, -253, -432, +-69, -343, 92, -115, 249, 84, 323, 272, +219, 446, -27, 424, -297, 214, -471, -92, +-450, -448, -268, -636, -45, -482, 213, -140, +443, 314, 436, 727, 166, 776, -212, 394, +-529, -177, -619, -709, -473, -913, -180, -605, +228, -17, 580, 542, 628, 907, 328, 807, +-177, 276, -641, -336, -798, -786, -617, -879, +-253, -503, 221, 74, 672, 543, 802, 792, +483, 709, -115, 269, -698, -260, -966, -670, +-809, -808, -348, -538, 282, -22, 833, 437, +966, 739, 568, 751, -159, 377, -823, -190, +-1067, -645, -830, -832, -276, -604, 381, -74, +865, 414, 930, 700, 548, 737, -136, 424, +-812, -104, -1097, -567, -872, -756, -309, -616, +368, -201, 914, 256, 1035, 591, 587, 751, +-195, 587, -895, 87, -1181, -448, -897, -786, +-207, -783, 495, -396, 906, 177, 893, 639, +477, 865, -184, 709, -795, 149, -1034, -478, +-799, -848, -250, -841, 348, -413, 763, 186, +866, 645, 564, 833, -76, 675, -718, 172, +-1023, -415, -852, -797, -267, -814, 400, -438, +795, 136, 804, 582, 454, 802, -135, 695, +-680, 224, -894, -366, -693, -774, -212, -831, +289, -471, 584, 103, 630, 574, 428, 786, +3, 709, -474, 285, -752, -289, -706, -724, +-359, -840, 134, -550, 525, -5, 630, 493, +459, 796, 65, 769, -414, 374, -694, -225, +-638, -739, -321, -897, 96, -572, 392, 12, +481, 543, 393, 821, 121, 718, -237, 277, +-489, -264, -549, -704, -419, -806, -101, -495, +260, 16, 456, 459, 470, 697, 280, 658, +-117, 339, -492, -152, -637, -598, -497, -806, +-122, -596, 269, -80, 479, 429, 464, 744, +233, 743, -145, 345, -461, -232, -543, -680, +-396, -795, -117, -490, 159, 73, 313, 516, +347, 687, 253, 544, 8, 136, -254, -279, +-405, -512, -423, -553, -290, -340, -46, 31, +204, 327, 384, 460, 401, 439, 172, 246, +-183, -49, -424, -351, -466, -535, -356, -463, +-113, -140, 183, 224, 390, 491, 394, 544, +192, 325, -77, -65, -305, -407, -461, -572, +-472, -452, -297, -70, 32, 310, 389, 463, +585, 438, 481, 244, 77, -77, -410, -334, +-738, -435, -760, -368, -388, -109, 220, 151, +721, 297, 819, 380, 434, 348, -199, 117, +-703, -180, -835, -397, -575, -455, -50, -302, +483, -3, 674, 276, 494, 483, 142, 484, +-280, 198, -549, -190, -521, -467, -332, -564, +-69, -367, 194, 39, 365, 390, 415, 568, +278, 531, -28, 189, -346, -254, -550, -555, +-529, -638, -226, -411, 167, 51, 424, 444, +507, 645, 344, 604, -80, 247, -464, -280, +-545, -621, -389, -682, -137, -463, 127, 35, +313, 522, 357, 718, 255, 616, 29, 219, +-242, -307, -397, -692, -372, -765, -254, -476, +-64, 116, 194, 651, 398, 811, 396, 637, +134, 184, -200, -477, -387, -913, -420, -837, +-309, -344, -90, 327, 147, 866, 323, 925, +362, 484, 238, -181, -36, -743, -300, -899, +-406, -556, -442, 49, -349, 639, -3, 823, +398, 479, 591, -36, 459, -422, 71, -591, +-368, -439, -681, -28, -684, 324, -330, 383, +178, 257, 572, 43, 709, -135, 482, -175, +-77, -98, -579, 4, -729, 17, -588, -48, +-215, -60, 259, -19, 600, 54, 668, 143, +375, 219, -144, 144, -546, -93, -683, -265, +-558, -272, -160, -165, 311, 37, 555, 252, +552, 342, 324, 185, -145, -53, -545, -209, +-593, -272, -403, -200, -91, 24, 222, 217, +367, 186, 394, 51, 291, -26, -6, -95, +-290, -71, -417, 17, -427, 72, -314, 79, +-57, -70, 272, -241, 518, -163, 550, 51, +276, 214, -236, 300, -642, 262, -727, -27, +-487, -355, 8, -447, 510, -313, 773, 3, +661, 383, 148, 565, -502, 423, -867, 9, +-767, -397, -339, -574, 239, -454, 706, -142, +769, 266, 478, 604, -52, 575, -629, 212, +-854, -193, -636, -505, -136, -582, 415, -371, +693, 40, 597, 419, 270, 586, -184, 475, +-621, 95, -717, -344, -376, -600, 58, -559, +366, -162, 502, 292, 381, 546, 94, 566, +-195, 294, -390, -204, -394, -590, -249, -589, +-52, -246, 153, 207, 252, 503, 220, 447, +184, 182, 107, -155, -106, -408, -331, -344, +-404, -26, -313, 242, -97, 294, 195, 131, +430, -152, 464, -344, 249, -194, -141, 125, +-511, 328, -662, 343, -465, 130, 15, -240, +455, -497, 627, -444, 506, -60, 143, 434, +-331, 667, -702, 442, -703, 3, -326, -458, +196, -758, 622, -594, 687, -74, 412, 486, +-17, 849, -529, 727, -818, 224, -632, -383, +-113, -877, 464, -937, 777, -444, 631, 274, +137, 867, -397, 1103, -736, 775, -728, -65, +-273, -944, 338, -1355, 684, -1026, 623, -105, +184, 959, -353, 1575, -618, 1343, -540, 330, +-221, -968, 216, -1810, 537, -1616, 484, -496, +107, 992, -307, 1981, -517, 1788, -385, 563, +-48, -970, 242, -2016, 398, -1924, 323, -655, +-4, 1055, -345, 2134, -461, 1924, -279, 552, +80, -1109, 350, -2073, 377, -1836, 179, -513, +-146, 1163, -391, 2111, -397, 1707, -184, 264, +139, -1271, 377, -2007, 369, -1493, 105, -39, +-216, 1399, -379, 1938, -352, 1287, -135, -192, +170, -1547, 351, -1951, 316, -1155, 75, 409, +-222, 1741, -386, 1947, -340, 1005, -65, -505, +253, -1784, 381, -2038, 247, -1028, -44, 609, +-284, 1894, -389, 2083, -284, 1061, 39, -621, +350, -1970, 439, -2173, 229, -1133, -163, 560, +-461, 1984, -477, 2274, -235, 1283, 123, -436, +482, -1961, 585, -2343, 279, -1367, -197, 315, +-617, 1809, -729, 2273, -339, 1433, 243, -190, +646, -1642, 710, -2127, 374, -1403, -199, 77, +-694, 1451, -828, 1919, -462, 1254, 192, -56, +693, -1180, 752, -1562, 395, -1086, -123, -72, +-537, 903, -704, 1270, -510, 840, -41, 27, +414, -595, 624, -800, 465, -566, 72, -98, +-250, 317, -426, 483, -461, 356, -276, 83, +47, -121, 310, -204, 417, -202, 280, -117, +-13, -25, -171, 15, -222, 145, -290, 236, +-218, 141, -38, -9, 99, -143, 187, -237, +229, -207, 193, -31, 69, 245, -83, 344, +-271, 169, -426, -93, -338, -310, -25, -389, +338, -204, 535, 177, 429, 494, 117, 493, +-299, 170, -628, -260, -610, -546, -240, -591, +268, -287, 642, 245, 667, 635, 294, 676, +-247, 356, -595, -159, -627, -587, -375, -739, +69, -485, 468, 7, 602, 490, 423, 781, +25, 665, -400, 177, -573, -380, -420, -755, +-144, -790, 171, -446, 469, 139, 549, 693, +305, 975, -166, 729, -564, 55, -606, -609, +-322, -1001, 106, -939, 527, -380, 669, 402, +377, 1068, -135, 1174, -620, 624, -810, -241, +-413, -997, 298, -1262, 751, -872, 707, -33, +259, 868, -322, 1359, -726, 1136, -730, 290, +-288, -720, 401, -1381, 824, -1305, 651, -566, +126, 469, -450, 1334, -759, 1484, -543, 841, +-101, -241, 311, -1293, 646, -1605, 589, -1024, +114, 43, -361, 1150, -573, 1659, -479, 1199, +-109, 108, 274, -1027, 410, -1603, 349, -1308, +132, -312, -168, 855, -318, 1553, -258, 1316, +-86, 362, 97, -655, 162, -1259, 62, -1215, +-31, -552, 39, 402, 106, 1102, 69, 1087, +-3, 531, -161, -217, -263, -828, -169, -888, +-35, -494, 152, 2, 395, 520, 357, 780, +10, 560, -299, 70, -442, -381, -360, -569, +-33, -400, 271, -154, 389, 81, 332, 369, +98, 396, -202, 154, -411, -22, -355, -151, +-63, -187, 186, -121, 270, -75, 226, -31, +107, 5, -53, 40, -199, 137, -213, 192, +-108, 140, 3, -3, 93, -174, 149, -281, +119, -251, 50, -64, 2, 227, -104, 374, +-185, 291, -149, 72, -59, -252, 137, -424, +290, -226, 196, 44, 22, 230, -183, 285, +-370, 123, -290, -97, 0, -259, 311, -258, +518, 48, 363, 348, -133, 298, -532, 30, +-611, -232, -345, -401, 228, -314, 678, 15, +711, 360, 360, 495, -308, 330, -872, -47, +-861, -419, -311, -565, 442, -347, 951, 48, +879, 357, 306, 501, -422, 461, -956, 202, +-952, -197, -369, -541, 422, -616, 963, -443, +922, -92, 372, 422, -313, 844, -824, 830, +-877, 391, -475, -344, 131, -1034, 699, -1169, +864, -651, 531, 281, -15, 1203, -527, 1434, +-740, 816, -551, -255, -175, -1284, 261, -1629, +644, -951, 646, 259, 292, 1297, -100, 1643, +-467, 1032, -615, -193, -414, -1225, -97, -1520, +289, -982, 583, 64, 523, 1005, 257, 1292, +-114, 858, -500, 12, -603, -751, -370, -978, +25, -628, 391, -54, 545, 455, 454, 650, +162, 451, -254, 79, -550, -217, -525, -345, +-229, -251, 173, -57, 423, 7, 440, -21, +336, 36, 64, 121, -277, 209, -469, 257, +-449, 147, -165, -92, 200, -335, 373, -472, +391, -318, 292, 104, 33, 472, -267, 556, +-463, 356, -425, -100, -84, -530, 253, -598, +371, -314, 404, 124, 244, 528, -98, 609, +-325, 283, -418, -184, -340, -520, -53, -547, +259, -189, 455, 228, 415, 454, 144, 465, +-146, 156, -374, -280, -511, -454, -358, -366, +85, -77, 453, 290, 579, 494, 425, 390, +-29, 28, -471, -364, -636, -527, -463, -415, +-15, -68, 436, 372, 690, 633, 575, 531, +50, 108, -512, -414, -745, -691, -549, -616, +-18, -186, 495, 440, 708, 790, 583, 667, +111, 241, -479, -403, -748, -874, -577, -789, +-92, -269, 464, 405, 690, 895, 532, 828, +167, 299, -299, -352, -584, -847, -551, -832, +-318, -279, 105, 345, 547, 747, 644, 719, +428, 210, 88, -378, -360, -651, -706, -510, +-706, -44, -335, 410, 316, 540, 861, 280, +932, -173, 506, -505, -226, -436, -887, 0, +-1108, 461, -712, 596, 134, 314, 926, -291, +1236, -820, 879, -777, 25, -149, -850, 613, +-1283, 1123, -1009, 992, -181, 143, 719, -903, +1228, -1481, 1124, -1192, 464, -131, -495, 1073, +-1199, 1731, -1225, 1387, -651, 188, 260, -1155, +1065, -1851, 1293, -1489, 871, -283, 31, 1084, +-859, 1887, -1353, 1594, -1103, 377, -238, -964, +706, -1736, 1282, -1598, 1207, -567, 482, 705, +-464, 1511, -1144, 1548, -1232, 790, -664, -352, +231, -1209, 943, -1434, 1149, -944, 774, -19, +50, 822, -598, 1236, -932, 1067, -868, 361, +-387, -474, 267, -1025, 759, -1079, 914, -587, +689, 180, 130, 755, -508, 953, -910, 714, +-934, 130, -504, -472, 283, -797, 967, -716, +1104, -319, 671, 129, -32, 474, -750, 609, +-1161, 503, -901, 229, -138, -115, 623, -423, +1045, -578, 970, -558, 420, -308, -352, 156, +-901, 595, -994, 794, -651, 674, 42, 169, +768, -521, 1108, -1002, 861, -978, 165, -429, +-585, 379, -1092, 1049, -1069, 1226, -375, 717, +581, -232, 1174, -1079, 1083, -1351, 411, -922, +-479, 30, -1116, 1019, -1071, 1449, -372, 1070, +505, 121, 1040, -887, 929, -1404, 283, -1187, +-467, -329, -891, 747, -770, 1376, -187, 1182, +485, 407, 780, -510, 576, -1152, 81, -1175, +-427, -565, -653, 307, -436, 975, 32, 1071, +418, 609, 540, -105, 337, -717, -79, -935, +-397, -671, -420, -104, -179, 494, 115, 832, +286, 728, 314, 237, 162, -327, -102, -697, +-235, -720, -161, -389, -34, 127, 48, 606, +88, 783, 39, 496, -10, -28, 27, -494, +48, -720, 70, -586, 93, -125, 0, 413, +-167, 721, -280, 613, -184, 173, 71, -345, +312, -677, 448, -646, 319, -241, -51, 306, +-404, 688, -601, 648, -500, 238, -12, -258, +593, -628, 843, -682, 570, -313, -17, 234, +-597, 620, -886, 648, -702, 315, -48, -197, +709, -557, 974, -584, 663, -312, 52, 130, +-615, 498, -924, 551, -621, 296, -7, -132, +518, -449, 740, -452, 548, -226, 45, 73, +-428, 349, -562, 400, -328, 189, 10, -73, +254, -250, 338, -275, 169, -102, -106, 78, +-166, 143, -39, 115, 82, -9, 144, -110, +113, -58, -75, 37, -302, 121, -346, 156, +-109, 37, 272, -152, 514, -242, 481, -225, +187, -57, -285, 189, -642, 348, -682, 363, +-359, 152, 266, -195, 814, -413, 900, -501, +473, -374, -231, 51, -824, 510, -1002, 769, +-641, 661, 106, 108, 855, -552, 1137, -1006, +740, -1032, -43, -386, -785, 598, -1110, 1290, +-781, 1386, -61, 674, 629, -567, 1006, -1534, +825, -1699, 167, -908, -515, 495, -838, 1635, +-705, 1936, -243, 1208, 292, -315, 635, -1688, +631, -2073, 280, -1391, -152, 41, -407, 1495, +-458, 2122, -296, 1626, 19, 284, 271, -1211, +335, -2015, 209, -1796, 32, -694, -89, 791, +-165, 1852, -148, 1931, -22, 1058, 49, -328, +44, -1536, 27, -1982, -30, -1448, -43, -168, +49, 1187, 112, 1908, 127, 1702, 75, 660, +-56, -705, -169, -1691, -252, -1830, -233, -1081, +0, 169, 277, 1303, 397, 1831, 341, 1458, +92, 352, -275, -864, -499, -1632, -485, -1678, +-233, -929, 247, 319, 632, 1434, 628, 1849, +275, 1388, -236, 223, -572, -1100, -609, -1916, +-390, -1820, 93, -795, 558, 714, 638, 1900, +389, 2142, 12, 1286, -350, -302, -520, -1766, +-408, -2310, -152, -1700, 132, -157, 369, 1547, +438, 2405, 296, 1977, 39, 505, -199, -1270, +-343, -2339, -382, -2148, -238, -823, 38, 956, +277, 2203, 385, 2240, 336, 1091, 135, -647, +-131, -2015, -318, -2246, -330, -1292, -230, 304, +-85, 1727, 117, 2182, 312, 1471, 362, 18, +268, -1414, 84, -2031, -167, -1555, -397, -308, +-482, 1076, -346, 1825, 1, 1565, 423, 533, +710, -730, 610, -1570, 125, -1527, -447, -720, +-812, 407, -777, 1289, -309, 1436, 381, 861, +921, -72, 954, -954, 419, -1308, -377, -989, +-941, -254, -968, 585, -464, 1149, 275, 1130, +844, 569, 954, -252, 519, -937, -210, -1184, +-745, -892, -855, -154, -486, 744, 166, 1292, +608, 1158, 663, 438, 420, -520, -59, -1267, +-441, -1383, -500, -779, -328, 272, 2, 1235, +304, 1562, 338, 1029, 207, -61, 39, -1106, +-137, -1583, -180, -1243, -139, -229, -117, 925, +10, 1603, 133, 1424, 121, 472, 80, -720, +33, -1499, -34, -1504, -90, -757, -128, 396, +-64, 1366, 67, 1599, 123, 973, 105, -140, +47, -1132, -60, -1555, -139, -1179, -140, -172, +-55, 898, 80, 1480, 161, 1287, 182, 417, +121, -620, -75, -1322, -231, -1347, -246, -656, +-148, 334, 69, 1112, 275, 1341, 321, 847, +225, -64, -23, -861, -323, -1240, -419, -1016, +-272, -242, -7, 609, 327, 1119, 490, 1064, +327, 469, 30, -312, -263, -912, -459, -1075, +-413, -667, -159, 69, 193, 722, 439, 999, +421, 762, 226, 158, -24, -466, -291, -866, +-448, -852, -387, -390, -140, 246, 169, 736, +410, 853, 463, 531, 308, 14, -3, -478, +-320, -797, -502, -710, -472, -243, -190, 296, +217, 685, 504, 719, 547, 383, 322, -71, +-26, -483, -354, -711, -582, -525, -527, -60, +-166, 365, 240, 602, 533, 532, 592, 181, +354, -202, -14, -466, -395, -513, -676, -288, +-573, 60, -163, 330, 253, 439, 588, 323, +704, 77, 450, -140, -42, -303, -540, -339, +-779, -201, -639, -34, -195, 121, 382, 252, +812, 277, 824, 203, 405, 61, -253, -121, +-794, -252, -901, -330, -536, -286, 99, -47, +690, 234, 885, 420, 620, 453, 57, 212, +-549, -168, -803, -468, -578, -608, -145, -414, +298, 74, 576, 499, 556, 700, 288, 562, +-97, 64, -389, -449, -434, -705, -311, -667, +-118, -263, 97, 312, 266, 686, 338, 738, +280, 426, 86, -130, -101, -555, -232, -726, +-333, -601, -313, -130, -132, 415, 108, 732, +336, 743, 446, 355, 360, -247, 70, -692, +-315, -822, -562, -557, -535, 44, -255, 628, +211, 906, 625, 703, 726, 73, 425, -562, +-144, -872, -653, -757, -802, -203, -541, 454, +31, 829, 615, 770, 842, 253, 622, -399, +83, -745, -532, -703, -834, -288, -663, 308, +-161, 645, 400, 611, 722, 321, 666, -183, +293, -547, -254, -537, -660, -299, -679, 88, +-357, 416, 126, 425, 548, 256, 668, 0, +445, -278, -19, -356, -482, -249, -644, -46, +-467, 223, -58, 319, 431, 196, 612, 34, +395, -146, 49, -257, -314, -189, -525, -38, +-382, 150, -60, 262, 250, 162, 411, -34, +291, -196, 59, -229, -100, -64, -246, 118, +-268, 205, -141, 190, -28, 12, 89, -212, +201, -274, 236, -165, 238, 99, 84, 347, +-212, 314, -398, 52, -399, -222, -213, -403, +154, -320, 505, 5, 648, 318, 406, 474, +-164, 360, -651, -45, -804, -446, -571, -562, +56, -353, 709, 75, 1006, 476, 798, 600, +62, 410, -785, -5, -1170, -465, -973, -674, +-226, -490, 740, -53, 1299, 423, 1180, 698, +443, 584, -654, 146, -1427, -357, -1385, -701, +-598, -702, 546, -313, 1397, 272, 1474, 743, +835, 834, -287, 463, -1352, -148, -1642, -700, +-1010, -919, 106, -655, 1149, -52, 1590, 603, +1211, 984, 211, 831, -880, 245, -1498, -466, +-1353, -954, -523, -930, 569, -442, 1314, 233, +1379, 830, 801, 996, -144, 616, -1007, -33, +-1351, -668, -1043, -964, -243, -697, 640, -155, +1199, 395, 1212, 802, 640, 758, -248, 331, +-968, -157, -1252, -585, -965, -697, -169, -424, +702, -70, 1212, 257, 1179, 487, 539, 470, +-402, 314, -1095, 62, -1235, -263, -800, -417, +54, -415, 865, -352, 1216, -87, 965, 253, +235, 513, -592, 627, -1064, 402, -994, -70, +-477, -502, 225, -779, 811, -699, 996, -215, +693, 413, 77, 909, -534, 966, -862, 466, +-786, -274, -398, -909, 163, -1136, 673, -721, +862, 74, 654, 800, 180, 1206, -423, 993, +-833, 203, -816, -673, -473, -1211, 77, -1148, +678, -487, 963, 394, 771, 1089, 212, 1285, +-477, 829, -962, -63, -993, -919, -538, -1356, +235, -1104, 906, -259, 1124, 662, 797, 1262, +37, 1305, -785, 654, -1169, -343, -946, -1148, +-256, -1398, 570, -920, 1088, 32, 1021, 895, +455, 1303, -315, 1092, -903, 314, -1008, -573, +-576, -1126, 86, -1161, 620, -584, 863, 256, +711, 870, 203, 1072, -345, 729, -692, 43, +-721, -554, -417, -918, 49, -846, 455, -274, +665, 367, 575, 751, 249, 790, -176, 390, +-563, -164, -679, -549, -449, -702, -78, -469, +328, 23, 669, 392, 719, 563, 386, 419, +-152, 37, -620, -215, -815, -332, -654, -323, +-124, -118, 548, 58, 961, 140, 878, 169, +339, 96, -425, 54, -982, 70, -1038, 1, +-559, -55, 264, -119, 980, -238, 1162, -170, +746, 24, -86, 174, -894, 329, -1216, 285, +-913, 42, -133, -176, 767, -394, 1270, -428, +1083, -126, 322, 218, -612, 450, -1229, 497, +-1204, 219, -566, -187, 412, -464, 1217, -570, +1350, -355, 747, 106, -228, 491, -1091, 656, +-1377, 457, -957, -50, -42, -466, 932, -643, +1417, -535, 1134, -108, 286, 412, -712, 719, +-1335, 615, -1237, 151, -529, -369, 425, -682, +1200, -646, 1329, -262, 752, 279, -168, 676, +-983, 721, -1285, 347, -923, -237, -132, -651, +718, -715, 1187, -409, 1049, 130, 432, 580, +-380, 745, -1007, 516, -1088, -52, -688, -579, +-19, -747, 724, -544, 1162, -76, 998, 470, +355, 775, -455, 654, -1060, 202, -1208, -384, +-792, -762, 111, -717, 1041, -345, 1408, 229, +1073, 739, 223, 825, -808, 479, -1491, -92, +-1387, -668, -549, -922, 596, -657, 1456, -64, +1565, 598, 878, 1023, -251, 872, -1273, 245, +-1640, -512, -1178, -1078, -113, -1081, 1012, -510, +1588, 342, 1367, 1109, 534, 1302, -570, 752, +-1401, -180, -1503, -1026, -892, -1383, 112, -1023, +1085, -101, 1523, 908, 1236, 1469, 389, 1217, +-675, 325, -1437, -717, -1490, -1428, -821, -1386, +291, -612, 1270, 458, 1619, 1339, 1207, 1522, +152, 900, -1054, -173, -1675, -1186, -1427, -1573, +-482, -1134, 752, -165, 1616, 911, 1604, 1574, +756, 1389, -467, 477, -1407, -637, -1622, -1455, +-1020, -1532, 139, -799, 1209, 314, 1575, 1290, +1156, 1618, 183, 1091, -875, 44, -1444, -1026, +-1255, -1588, -461, -1344, 545, -452, 1231, 656, +1295, 1452, 737, 1521, -198, 843, -996, -209, +-1225, -1148, -883, -1561, -145, -1214, 662, -274, +1119, 815, 1019, 1525, 440, 1466, -348, 683, +-922, -432, -1032, -1358, -673, -1638, 7, -1074, +701, 107, 1009, 1239, 828, 1722, 298, 1304, +-378, 176, -896, -1030, -953, -1691, -543, -1468, +110, -431, 700, 818, 987, 1589, 811, 1485, +200, 577, -524, -582, -960, -1331, -949, -1358, +-474, -700, 297, 315, 944, 1072, 1090, 1167, +693, 688, -66, -88, -830, -728, -1182, -927, +-905, -681, -140, -129, 717, 425, 1205, 715, +1073, 677, 363, 343, -539, -115, -1144, -494, +-1179, -658, -615, -562, 333, -219, 1121, 258, +1283, 645, 778, 752, -100, 500, -929, -2, +-1286, -551, -971, -908, -120, -786, 774, -242, +1239, 432, 1094, 956, 406, 978, -506, 463, +-1115, -274, -1142, -928, -642, -1119, 171, -661, +919, 142, 1184, 840, 900, 1129, 227, 800, +-591, 23, -1156, -720, -1151, -1097, -597, -895, +276, -175, 1047, 584, 1336, 1011, 995, 919, +127, 341, -867, -384, -1427, -900, -1273, -963, +-478, -508, 592, 213, 1389, 781, 1492, 927, +862, 637, -220, 23, -1209, -618, -1580, -921, +-1166, -726, -191, -167, 891, 444, 1577, 832, +1514, 765, 651, 280, -548, -296, -1449, -721, +-1669, -752, -1080, -345, 126, 175, 1318, 565, +1838, 671, 1402, 388, 253, -69, -1038, -424, +-1830, -546, -1663, -374, -590, -13, 776, 263, +1751, 373, 1819, 327, 895, 113, -484, -91, +-1565, -201, -1824, -239, -1108, -150, 163, -47, +1317, 10, 1800, 89, 1312, 175, 112, 214, +-1059, 163, -1620, 29, -1344, -156, -389, -318, +729, -321, 1431, -151, 1376, 113, 597, 368, +-420, 477, -1141, 298, -1250, -94, -726, -426, +110, -537, 831, -371, 1116, 8, 795, 375, +112, 582, -528, 473, -865, 74, -740, -327, +-266, -539, 238, -477, 609, -159, 671, 217, +353, 461, -77, 474, -364, 246, -444, -112, +-311, -374, -100, -431, 114, -293, 299, -3, +296, 277, 149, 407, 53, 331, -63, 70, +-166, -205, -183, -361, -193, -330, -105, -142, +101, 113, 187, 333, 217, 349, 242, 141, +93, -109, -139, -269, -275, -259, -315, -111, +-184, 86, 56, 228, 254, 211, 380, 31, +333, -175, 73, -235, -201, -117, -413, 93, +-447, 267, -179, 247, 187, 55, 421, -191, +503, -358, 348, -307, -23, -36, -413, 300, +-580, 459, -410, 326, -44, -8, 311, -377, +575, -532, 551, -361, 212, 36, -206, 455, +-528, 615, -580, 406, -287, -30, 106, -496, +428, -714, 572, -509, 416, -12, 54, 487, +-314, 757, -523, 622, -402, 147, -105, -386, +158, -753, 399, -735, 459, -305, 213, 244, +-55, 695, -246, 796, -384, 441, -296, -83, +-33, -547, 189, -779, 345, -585, 349, -84, +164, 447, -101, 761, -323, 650, -371, 199, +-180, -295, 86, -671, 289, -714, 379, -337, +265, 188, -36, 627, -289, 750, -355, 422, +-237, -71, 5, -505, 239, -707, 324, -497, +262, -41, 72, 411, -165, 653, -291, 489, +-250, 78, -111, -286, 96, -492, 256, -420, +261, -97, 147, 192, -4, 342, -163, 306, +-234, 66, -176, -116, -48, -164, 77, -163, +166, -39, 177, 50, 128, 24, 44, 24, +-49, 23, -122, 30, -158, 90, -167, 67, +-93, -34, 84, -107, 235, -160, 260, -136, +208, 32, 23, 180, -232, 210, -348, 117, +-300, -84, -118, -218, 201, -189, 415, -50, +379, 139, 200, 230, -78, 155, -384, -54, +-481, -262, -322, -293, -6, -121, 347, 160, +540, 383, 463, 363, 174, 98, -250, -259, +-576, -495, -578, -478, -293, -176, 155, 281, +583, 613, 685, 617, 408, 275, -62, -253, +-509, -680, -708, -766, -501, -433, -10, 145, +477, 678, 690, 884, 556, 629, 156, 17, +-337, -664, -660, -1003, -595, -799, -206, -206, +261, 536, 560, 1033, 596, 974, 366, 423, +-60, -369, -470, -1001, -608, -1085, -453, -607, +-80, 161, 358, 870, 616, 1112, 581, 758, +303, 76, -166, -647, -570, -1062, -678, -893, +-470, -289, 18, 443, 559, 939, 783, 919, +638, 496, 185, -150, -423, -755, -805, -943, +-741, -650, -312, -68, 324, 546, 800, 872, +818, 761, 450, 310, -107, -285, -638, -726, +-819, -776, -564, -479, -27, 45, 498, 529, +743, 695, 646, 571, 279, 218, -253, -242, +-654, -527, -704, -575, -408, -379, 86, 3, +526, 336, 708, 515, 578, 516, 131, 262, +-404, -128, -702, -435, -645, -568, -265, -441, +285, -53, 663, 356, 698, 624, 412, 612, +-108, 249, -593, -234, -754, -603, -523, -709, +-3, -426, 498, 99, 721, 559, 622, 729, +220, 540, -360, 79, -736, -416, -704, -676, +-337, -583, 205, -206, 657, 254, 766, 554, +490, 551, -61, 257, -583, -133, -778, -406, +-583, -451, -92, -274, 484, 14, 788, 273, +650, 356, 173, 221, -397, 6, -758, -169, +-677, -229, -225, -169, 336, -43, 699, 70, +660, 104, 259, 72, -268, 0, -636, -60, +-622, -23, -262, 40, 237, 51, 586, 27, +564, -45, 227, -138, -164, -161, -455, -109, +-514, 6, -265, 182, 132, 256, 410, 155, +456, 8, 268, -168, -31, -304, -292, -265, +-391, -115, -285, 95, -23, 279, 218, 279, +342, 158, 299, -1, 112, -203, -92, -314, +-210, -234, -249, -74, -167, 102, 7, 241, +147, 242, 210, 146, 210, -4, 130, -182, +28, -254, -100, -196, -217, -64, -215, 100, +-80, 201, 85, 216, 230, 155, 287, 6, +209, -149, 20, -226, -201, -194, -309, -67, +-204, 78, -9, 181, 188, 233, 311, 171, +272, 9, 95, -119, -102, -186, -246, -181, +-246, -66, -119, 52, 60, 135, 210, 181, +259, 136, 204, 53, 82, -15, -107, -87, +-247, -113, -237, -95, -103, -77, 81, -18, +255, 94, 299, 170, 189, 190, -21, 154, +-225, 24, -288, -134, -173, -231, 26, -238, +209, -112, 267, 101, 174, 283, -4, 332, +-165, 239, -212, 45, -98, -189, 46, -347, +119, -350, 117, -196, 52, 79, -45, 333, +-85, 452, -60, 401, 4, 156, 75, -216, +81, -506, -6, -564, -79, -357, -99, 78, +-72, 527, -11, 723, 59, 573, 91, 95, +102, -488, 51, -818, -47, -734, -114, -266, +-126, 386, -118, 850, -57, 863, 70, 415, +202, -284, 223, -852, 116, -959, -72, -578, +-233, 82, -304, 716, -227, 984, 1, 732, +271, 88, 380, -606, 259, -967, -3, -850, +-260, -323, -390, 378, -311, 879, -75, 916, +207, 472, 373, -237, 324, -829, 103, -997, +-137, -646, -299, 52, -299, 723, -167, 1007, +31, 755, 218, 66, 292, -695, 207, -1077, +41, -878, -126, -222, -205, 569, -182, 1044, +-94, 937, 39, 306, 169, -514, 190, -1043, +136, -986, 60, -412, -20, 374, -81, 943, +-117, 960, -124, 430, -74, -316, 19, -878, +152, -935, 261, -451, 246, 254, 96, 780, +-116, 860, -307, 448, -312, -211, -118, -735, +159, -828, 400, -440, 450, 194, 230, 679, +-106, 763, -383, 445, -435, -129, -206, -637, +130, -748, 373, -425, 450, 146, 289, 633, +-8, 749, -264, 470, -361, -67, -260, -586, +-10, -761, 214, -497, 323, 40, 300, 575, +144, 818, -68, 615, -211, 97, -249, -475, +-157, -797, 12, -669, 166, -178, 237, 417, +211, 802, 79, 768, -68, 365, -161, -231, +-170, -706, -78, -770, 50, -438, 116, 117, +126, 626, 73, 783, -9, 555, -44, 91, +-21, -435, -1, -718, 15, -580, -16, -175, +-69, 304, -85, 630, -38, 617, 71, 336, +179, -97, 173, -491, 45, -577, -155, -381, +-313, -32, -277, 350, -50, 531, 207, 441, +386, 180, 333, -171, 41, -431, -311, -458, +-512, -280, -417, 25, -42, 306, 358, 409, +548, 349, 412, 136, -2, -169, -424, -378, +-599, -424, -460, -284, -31, 3, 411, 259, +574, 411, 408, 391, 29, 135, -391, -194, +-570, -430, -425, -498, -82, -306, 281, 42, +467, 341, 386, 492, 120, 388, -207, 31, +-393, -333, -347, -532, -148, -485, 84, -166, +264, 219, 277, 451, 151, 450, -17, 169, +-146, -231, -167, -475, -94, -456, -9, -215, +50, 133, 45, 385, 14, 385, 26, 148, +70, -193, 90, -419, 117, -367, 72, -122, +-82, 161, -219, 339, -212, 286, -76, 40, +140, -237, 329, -384, 368, -278, 206, 19, +-92, 281, -350, 363, -388, 231, -218, -74, +100, -348, 410, -431, 522, -286, 339, 67, +-14, 404, -350, 500, -488, 357, -350, 6, +4, -376, 390, -541, 576, -444, 459, -116, +121, 316, -305, 575, -562, 561, -468, 298, +-90, -157, 342, -519, 622, -578, 567, -387, +209, 31, -261, 469, -596, 642, -569, 539, +-184, 172, 284, -324, 604, -596, 620, -558, +302, -252, -166, 241, -515, 613, -601, 670, +-347, 442, 100, -25, 484, -484, 603, -655, +412, -500, 29, -69, -345, 437, -558, 699, +-485, 643, -124, 289, 307, -234, 538, -605, +483, -651, 169, -366, -222, 143, -487, 564, +-476, 687, -209, 498, 156, 64, 401, -388, +402, -614, 170, -536, -139, -175, -335, 278, +-333, 566, -172, 592, 59, 350, 205, -75, +203, -439, 82, -595, -51, -485, -131, -124, +-133, 290, -85, 570, -23, 612, 10, 333, +-2, -131, -24, -516, -12, -670, 32, -519, +63, -96, 30, 377, -30, 648, -102, 593, +-152, 215, -157, -289, -62, -624, 96, -652, +218, -386, 210, 58, 77, 465, -120, 613, +-289, 431, -320, 15, -182, -410, 63, -623, +310, -555, 392, -241, 248, 194, -64, 513, +-343, 567, -434, 330, -299, -110, -12, -515, +321, -675, 494, -534, 373, -129, 50, 340, +-280, 618, -454, 574, -376, 216, -84, -286, +269, -659, 451, -716, 396, -405, 161, 114, +-138, 555, -361, 714, -358, 487, -148, -45, +123, -561, 320, -806, 357, -644, 238, -103, +35, 485, -164, 803, -253, 721, -218, 204, +-74, -454, 117, -846, 284, -808, 324, -329, +222, 363, 30, 832, -156, 854, -270, 424, +-249, -264, -51, -768, 208, -823, 355, -465, +333, 156, 150, 681, -78, 811, -244, 547, +-269, 15, -145, -497, 78, -677, 246, -499, +298, -93, 213, 344, 40, 593, -97, 563, +-164, 288, -181, -105, -110, -390, 27, -444, +166, -295, 239, -15, 222, 274, 98, 446, +-64, 434, -224, 222, -278, -53, -185, -247, +18, -324, 236, -239, 339, -20, 251, 187, +30, 318, -215, 331, -348, 204, -296, 28, +-87, -114, 147, -220, 313, -228, 300, -120, +122, 32, -130, 200, -311, 333, -333, 322, +-187, 180, 49, -50, 236, -303, 278, -422, +187, -316, -18, -42, -240, 307, -343, 549, +-254, 510, -57, 208, 162, -222, 273, -587, +230, -645, 54, -359, -164, 111, -321, 552, +-325, 708, -153, 475, 95, 13, 254, -467, +267, -728, 133, -602, -76, -177, -261, 308, +-320, 618, -241, 583, -21, 244, 184, -206, +260, -557, 204, -631, 44, -400, -126, -4, +-212, 363, -230, 504, -149, 371, 15, 66, +136, -282, 177, -499, 186, -475, 91, -255, +-37, 59, -141, 310, -212, 374, -213, 254, +-94, -2, 101, -278, 275, -405, 319, -354, +208, -179, -4, 68, -242, 263, -390, 292, +-309, 168, -38, -56, 297, -250, 496, -320, +455, -268, 164, -108, -232, 92, -508, 227, +-505, 249, -221, 141, 229, -36, 613, -190, +677, -284, 373, -280, -109, -148, -530, 59, +-650, 258, -409, 353, 86, 274, 546, 47, +732, -243, 547, -461, 97, -438, -376, -164, +-610, 233, -491, 563, -117, 599, 297, 298, +549, -178, 526, -598, 269, -692, -85, -359, +-326, 203, -381, 680, -241, 801, 0, 479, +205, -96, 290, -604, 270, -774, 162, -477, +20, 125, -101, 652, -187, 818, -197, 550, +-112, 12, -5, -495, 126, -696, 229, -481, +244, 18, 145, 509, -26, 721, -209, 546, +-289, 105, -236, -343, -67, -546, 154, -420, +291, -69, 290, 332, 169, 567, -89, 475, +-330, 149, -386, -203, -245, -397, -21, -339, +228, -89, 377, 195, 332, 386, 77, 377, +-258, 175, -466, -79, -446, -256, -219, -280, +128, -152, 412, 19, 471, 179, 271, 274, +-84, 239, -447, 114, -581, -53, -420, -212, +-54, -268, 320, -231, 524, -103, 452, 119, +127, 286, -278, 306, -547, 210, -548, -17, +-281, -273, 120, -402, 443, -372, 510, -159, +325, 156, -56, 353, -406, 385, -523, 236, +-388, -81, -93, -368, 254, -487, 452, -402, +380, -105, 128, 223, -170, 401, -372, 381, +-373, 143, -213, -209, 45, -467, 278, -517, +366, -317, 256, 42, 37, 343, -198, 451, +-319, 312, -277, -30, -108, -374, 134, -550, +336, -464, 363, -140, 194, 223, -75, 439, +-281, 411, -335, 137, -201, -205, 46, -439, +320, -476, 444, -281, 327, 39, 30, 280, +-270, 357, -409, 254, -313, 17, -13, -204, +325, -311, 497, -296, 417, -166, 123, 19, +-231, 182, -455, 264, -373, 235, -80, 112, +251, -55, 459, -218, 449, -316, 214, -274, +-108, -90, -336, 148, -366, 358, -210, 426, +47, 278, 300, -5, 438, -292, 358, -462, +120, -401, -177, -122, -368, 239, -375, 523, +-176, 573, 145, 348, 421, -21, 464, -380, +253, -568, -85, -457, -372, -98, -426, 351, +-225, 676, 64, 679, 318, 371, 391, -120, +248, -572, -23, -732, -236, -507, -286, 23, +-192, 617, -70, 917, 48, 766, 161, 254, +199, -416, 152, -876, 62, -841, -70, -353, +-203, 368, -307, 928, -280, 984, -94, 562, +177, -134, 368, -773, 381, -930, 157, -561, +-192, 92, -474, 716, -558, 925, -356, 613, +58, 31, 447, -546, 596, -799, 408, -551, +-8, -18, -443, 481, -670, 699, -593, 490, +-201, 46, 291, -357, 608, -553, 593, -415, +272, -54, -191, 258, -569, 388, -666, 277, +-455, 21, -46, -173, 381, -238, 596, -184, +515, -48, 182, 48, -228, 56, -553, 10, +-632, -54, -422, -57, 5, 5, 428, 41, +638, 39, 556, -19, 183, -122, -315, -176, +-663, -155, -694, -80, -359, 43, 178, 133, +629, 126, 754, 36, 509, -97, -25, -203, +-541, -224, -759, -170, -582, -49, -85, 98, +453, 171, 735, 133, 649, 22, 240, -122, +-268, -227, -603, -240, -606, -166, -295, -21, +187, 129, 523, 179, 588, 120, 399, 6, +30, -128, -318, -221, -451, -212, -342, -118, +-67, 40, 231, 186, 393, 201, 354, 104, +171, -42, -55, -212, -192, -280, -219, -183, +-113, 32, 35, 267, 131, 365, 156, 234, +122, -40, 56, -330, 24, -469, 40, -314, +36, 47, -5, 417, -54, 599, -112, 434, +-103, 15, -7, -415, 151, -634, 259, -472, +257, -12, 104, 463, -139, 720, -337, 588, +-357, 121, -145, -378, 179, -651, 415, -546, +445, -99, 227, 407, -152, 694, -475, 622, +-512, 211, -270, -282, 152, -576, 498, -550, +545, -187, 271, 297, -162, 604, -519, 612, +-584, 317, -316, -129, 132, -446, 496, -500, +552, -280, 270, 95, -158, 403, -516, 500, +-569, 367, -317, 72, 86, -205, 427, -330, +509, -286, 273, -105, -110, 114, -436, 258, +-543, 304, -343, 225, 27, 59, 325, -94, +433, -204, 293, -245, -10, -173, -320, -20, +-450, 154, -342, 288, -73, 304, 169, 173, +296, -53, 272, -282, 88, -400, -119, -317, +-234, -63, -260, 227, -186, 416, -45, 397, +96, 157, 167, -196, 190, -471, 138, -511, +23, -285, -146, 75, -278, 384, -272, 490, +-135, 328, 75, -27, 279, -380, 356, -558, +232, -450, -33, -123, -291, 215, -409, 410, +-303, 398, -34, 168, 298, -167, 475, -429, +388, -479, 119, -301, -199, -21, -437, 221, +-444, 336, -203, 268, 152, 57, 460, -187, +553, -355, 356, -345, -2, -170, -368, 36, +-543, 197, -439, 239, -99, 130, 325, -40, +640, -196, 625, -262, 270, -173, -199, -16, +-549, 111, -613, 164, -358, 97, 101, -43, +557, -142, 723, -167, 507, -100, 48, 38, +-402, 143, -645, 160, -523, 82, -125, -72, +319, -184, 605, -186, 597, -92, 290, 76, +-157, 221, -485, 240, -515, 141, -300, -33, +36, -207, 347, -281, 504, -186, 400, 36, +134, 260, -175, 352, -386, 271, -403, 59, +-243, -186, 21, -349, 290, -321, 426, -84, +361, 251, 132, 477, -172, 463, -413, 212, +-439, -150, -266, -435, 50, -501, 328, -286, +431, 149, 330, 557, 76, 686, -227, 462, +-421, 2, -426, -457, -248, -669, 57, -522, +321, -76, 392, 457, 300, 774, 70, 688, +-225, 262, -454, -285, -449, -667, -219, -677, +110, -327, 345, 194, 390, 627, 237, 745, +-45, 487, -301, 3, -407, -458, -320, -677, +-78, -528, 156, -105, 268, 348, 217, 622, +89, 595, -62, 272, -182, -175, -241, -523, +-199, -599, -80, -360, 58, 56, 158, 403, +176, 540, 111, 417, -16, 80, -167, -286, +-237, -497, -182, -469, -25, -206, 123, 138, +201, 379, 148, 412, 10, 247, -123, -33, +-183, -297, -147, -426, -33, -363, 96, -133, +155, 148, 128, 316, 41, 311, -75, 156, +-126, -93, -99, -312, -14, -373, 66, -269, +119, -61, 118, 166, 70, 272, -30, 205, +-123, 43, -118, -149, -31, -271, 82, -252, +165, -141, 155, 14, 81, 140, -43, 147, +-160, 69, -185, -30, -61, -116, 122, -140, +254, -97, 241, -52, 95, -12, -93, 29, +-235, 36, -239, 23, -81, 15, 150, -7, +325, -33, 304, -66, 101, -92, -149, -80, +-281, -11, -250, 75, -57, 118, 172, 95, +309, 22, 278, -78, 82, -150, -141, -148, +-245, -54, -198, 94, -40, 193, 131, 163, +222, 53, 187, -60, 61, -145, -95, -134, +-163, -21, -145, 99, -49, 164, 86, 140, +161, 31, 120, -66, 13, -89, -101, -47, +-152, 42, -93, 122, 23, 129, 101, 76, +125, 2, 60, -70, -54, -70, -156, -3, +-157, 68, -53, 127, 91, 133, 157, 59, +117, -18, 20, -63, -104, -70, -190, -23, +-181, 58, -67, 118, 101, 135, 189, 97, +160, 22, 41, -47, -106, -79, -226, -67, +-235, -8, -138, 57, 34, 108, 217, 127, +266, 104, 135, 44, -75, -43, -258, -105, +-326, -107, -238, -65, -16, 22, 227, 128, +348, 188, 231, 160, -19, 40, -275, -119, +-403, -214, -295, -187, -24, -71, 242, 95, +375, 232, 287, 240, 15, 110, -259, -94, +-382, -267, -296, -297, -36, -181, 213, 23, +328, 221, 241, 304, 24, 226, -172, 20, +-241, -217, -195, -367, -66, -333, 80, -140, +147, 110, 133, 306, 70, 341, 8, 181, +-7, -84, -48, -329, -100, -417, -110, -304, +-70, -49, 8, 210, 127, 342, 200, 277, +183, 52, 80, -210, -92, -365, -233, -348, +-238, -167, -94, 75, 133, 255, 284, 283, +278, 147, 146, -61, -43, -239, -244, -310, +-290, -234, -142, -52, 74, 143, 248, 246, +299, 198, 177, 52, -45, -107, -209, -213, +-225, -221, -107, -117, 79, 22, 219, 119, +228, 135, 89, 77, -77, 6, -174, -43, +-151, -63, -29, -49, 121, -39, 191, -35, +134, -15, 0, 8, -117, 50, -149, 97, +-95, 107, 12, 57, 146, -33, 182, -118, +91, -132, -43, -61, -127, 58, -149, 160, +-92, 192, 20, 121, 123, 2, 169, -116, +110, -163, -17, -97, -128, 31, -172, 147, +-123, 199, -23, 151, 80, 46, 141, -60, +144, -119, 46, -88, -80, 6, -155, 93, +-167, 138, -104, 127, 7, 44, 95, -40, +145, -59, 134, -23, 35, 32, -100, 70, +-184, 74, -196, 57, -108, 11, 21, -27, +135, -21, 183, 23, 139, 57, 15, 53, +-133, 26, -230, -5, -217, -21, -103, -14, +47, 9, 178, 46, 231, 72, 138, 62, +-29, 15, -184, -57, -261, -91, -217, -70, +-55, -14, 119, 54, 219, 124, 205, 133, +88, 53, -70, -64, -204, -162, -242, -195, +-155, -109, -6, 33, 131, 160, 184, 210, +156, 141, 62, -14, -45, -175, -145, -258, +-189, -204, -158, -64, -58, 87, 82, 189, +193, 185, 229, 72, 167, -67, 0, -170, +-193, -216, -299, -175, -250, -80, -61, 38, +199, 138, 358, 154, 332, 104, 143, 14, +-139, -121, -364, -228, -382, -252, -191, -167, +107, 7, 366, 174, 434, 256, 271, 210, +-20, 37, -303, -184, -411, -334, -296, -347, +-29, -186, 256, 84, 430, 295, 373, 344, +119, 228, -173, -30, -359, -280, -356, -399, +-163, -329, 121, -90, 347, 199, 380, 377, +217, 355, -61, 147, -280, -118, -322, -336, +-187, -388, 27, -231, 223, 52, 300, 301, +214, 390, 17, 278, -178, 27, -246, -229, +-167, -362, -24, -286, 130, -42, 208, 214, +159, 364, 31, 332, -88, 108, -171, -152, +-146, -319, -32, -294, 75, -84, 137, 167, +141, 324, 60, 324, -69, 151, -161, -97, +-168, -263, -92, -259, 58, -96, 181, 141, +186, 300, 69, 290, -80, 150, -206, -64, +-231, -235, -123, -263, 58, -118, 214, 109, +252, 290, 130, 328, -81, 201, -255, -36, +-296, -231, -180, -309, 36, -211, 218, 23, +281, 269, 186, 385, -19, 299, -223, 56, +-315, -204, -252, -359, -53, -321, 179, -104, +293, 183, 236, 382, 60, 378, -159, 169, +-309, -120, -287, -328, -80, -381, 154, -233, +262, 48, 190, 283, 21, 367, -140, 267, +-213, 24, -146, -219, 11, -361, 132, -312, +138, -105, 34, 119, -94, 267, -151, 283, +-77, 145, 65, -65, 170, -229, 143, -290, +2, -208, -158, -30, -235, 118, -167, 188, +19, 161, 218, 34, 305, -86, 206, -169, +-29, -187, -245, -110, -322, -3, -234, 58, +-7, 78, 230, 56, 351, 20, 295, -34, +85, -89, -174, -120, -337, -101, -321, -54, +-142, 7, 106, 62, 298, 84, 359, 74, +265, 11, 36, -100, -213, -167, -371, -151, +-350, -73, -138, 30, 171, 119, 410, 161, +462, 98, 278, -26, -65, -145, -385, -203, +-496, -157, -325, -37, 29, 97, 356, 194, +497, 187, 380, 83, 67, -62, -258, -176, +-423, -209, -382, -134, -136, 16, 183, 161, +378, 226, 367, 171, 200, 46, -30, -95, +-230, -200, -333, -186, -285, -68, -92, 76, +145, 206, 302, 233, 340, 154, 210, 15, +-43, -128, -282, -197, -377, -151, -284, -32, +-40, 129, 226, 247, 376, 240, 326, 106, +104, -58, -168, -185, -352, -201, -358, -103, +-173, 63, 82, 231, 278, 275, 322, 168, +200, -6, -32, -166, -229, -206, -294, -116, +-213, 23, -50, 164, 98, 219, 191, 158, +195, 24, 86, -94, -40, -132, -127, -85, +-169, -8, -155, 65, -84, 105, -2, 89, +95, 52, 166, 24, 144, -25, 50, -55, +-67, -55, -169, -64, -210, -37, -157, 16, +-19, 70, 137, 117, 227, 103, 198, 14, +64, -85, -129, -149, -255, -146, -246, -77, +-120, 38, 64, 125, 226, 152, 268, 83, +158, -36, -44, -133, -217, -167, -269, -128, +-183, -34, -17, 51, 162, 101, 256, 92, +212, 43, 43, -38, -137, -113, -225, -130, +-196, -104, -84, -52, 76, 1, 200, 57, +210, 112, 123, 91, -15, -12, -157, -111, +-215, -181, -154, -178, -5, -88, 153, 58, +233, 169, 177, 188, 41, 88, -98, -87, +-195, -237, -194, -269, -72, -144, 97, 57, +209, 202, 205, 251, 106, 154, -35, -51, +-152, -215, -212, -287, -154, -198, 6, 7, +168, 183, 235, 255, 193, 210, 70, 38, +-102, -140, -239, -236, -248, -226, -118, -102, +85, 95, 264, 220, 307, 253, 163, 169, +-50, -10, -216, -159, -277, -226, -201, -202, +-14, -59, 173, 103, 278, 223, 254, 259, +107, 165, -85, 7, -246, -125, -295, -200, +-188, -205, 6, -95, 205, 81, 327, 232, +288, 288, 75, 209, -182, 37, -347, -138, +-332, -264, -151, -254, 95, -88, 300, 161, +360, 342, 231, 359, -17, 203, -273, -78, +-392, -321, -299, -384, -61, -242, 176, 52, +328, 353, 333, 493, 172, 380, -87, 38, +-311, -322, -386, -508, -271, -428, -17, -109, +247, 308, 367, 574, 296, 539, 84, 208, +-181, -255, -361, -594, -321, -597, -127, -276, +85, 226, 221, 610, 237, 657, 156, 354, +38, -163, -103, -602, -226, -705, -245, -428, +-158, 97, -17, 570, 148, 710, 247, 464, +227, -36, 105, -522, -80, -727, -264, -543, +-321, -85, -209, 431, 15, 694, 244, 546, +352, 117, 260, -365, 27, -665, -204, -602, +-333, -240, -314, 240, -131, 575, 124, 573, +309, 264, 337, -184, 208, -523, -27, -578, +-244, -351, -347, 26, -301, 365, -81, 490, +220, 355, 396, 47, 342, -275, 118, -457, +-149, -401, -340, -182, -352, 99, -176, 315, +103, 381, 309, 261, 342, 4, 198, -252, +-39, -369, -223, -338, -257, -144, -169, 115, +-15, 298, 138, 331, 202, 203, 164, -16, +87, -223, -14, -318, -102, -259, -127, -81, +-91, 117, -47, 242, 9, 267, 80, 186, +146, 9, 156, -166, 82, -268, -32, -233, +-130, -86, -188, 107, -165, 269, -40, 308, +138, 197, 245, -21, 233, -247, 110, -327, +-86, -221, -262, 21, -286, 270, -156, 370, +36, 292, 226, 63, 327, -209, 243, -358, +21, -289, -210, -68, -335, 206, -281, 385, +-70, 354, 159, 151, 311, -102, 309, -324, +126, -348, -136, -181, -303, 80, -295, 329, +-144, 409, 66, 270, 235, 15, 271, -257, +160, -390, -29, -309, -195, -68, -258, 225, +-168, 416, -1, 382, 147, 166, 206, -121, +143, -371, -2, -416, -132, -239, -183, 33, +-137, 303, -16, 444, 98, 363, 134, 110, +90, -220, -16, -438, -108, -430, -121, -219, +-64, 103, 9, 397, 62, 495, 63, 323, +19, -34, -35, -378, -46, -524, -7, -394, +19, -63, -2, 302, -40, 502, -70, 406, +-44, 98, 42, -271, 112, -504, 95, -463, +26, -164, -78, 194, -172, 422, -171, 425, +-46, 203, 125, -149, 229, -403, 196, -458, +42, -276, -151, 44, -266, 306, -242, 398, +-92, 280, 134, -8, 334, -283, 346, -407, +154, -330, -135, -72, -377, 216, -427, 350, +-225, 286, 116, 56, 418, -226, 513, -346, +321, -274, -58, -63, -413, 200, -572, 316, +-409, 221, 0, 11, 406, -229, 598, -321, +505, -196, 136, 34, -329, 229, -613, 276, +-560, 143, -214, -70, 248, -233, 586, -253, +613, -92, 328, 119, -96, 226, -474, 199, +-627, 48, -446, -132, -17, -195, 409, -140, +622, 10, 518, 151, 150, 186, -271, 113, +-527, -15, -528, -131, -278, -131, 107, -33, +433, 83, 546, 131, 392, 109, 48, 30, +-300, -58, -506, -92, -477, -43, -212, 52, +167, 116, 465, 117, 526, 55, 308, -40, +-53, -96, -362, -87, -494, -18, -399, 77, +-105, 121, 235, 112, 463, 38, 465, -47, +239, -78, -107, -55, -404, 5, -514, 65, +-364, 58, -32, 12, 314, -22, 522, -22, +468, 10, 146, 62, -259, 79, -522, 32, +-509, -54, -232, -136, 161, -124, 458, -10, +507, 133, 285, 213, -78, 154, -402, -15, +-517, -183, -343, -269, -1, -173, 307, 40, +460, 241, 367, 305, 62, 166, -254, -99, +-414, -311, -381, -354, -134, -180, 186, 107, +372, 326, 338, 350, 128, 174, -130, -129, +-296, -367, -312, -391, -167, -202, 70, 100, +237, 322, 237, 352, 119, 203, -35, -79, +-150, -319, -184, -351, -128, -218, -29, 19, +61, 232, 120, 294, 137, 182, 84, -25, +-7, -208, -83, -257, -137, -176, -137, -31, +-52, 118, 59, 177, 139, 115, 158, 16, +100, -74, -8, -101, -114, -61, -180, -44, +-161, -33, -62, -22, 80, -19, 222, 28, +260, 107, 133, 137, -78, 106, -271, -15, +-327, -174, -182, -270, 86, -206, 307, -9, +381, 230, 249, 353, -35, 285, -316, 59, +-432, -225, -302, -414, 16, -362, 326, -95, +461, 245, 361, 453, 70, 419, -268, 162, +-467, -188, -422, -430, -141, -452, 212, -222, +457, 152, 481, 450, 269, 519, -91, 320, +-422, -57, -544, -387, -371, -522, 8, -391, +381, -26, 558, 372, 450, 565, 104, 484, +-283, 166, -521, -250, -498, -518, -219, -504, +168, -231, 441, 168, 499, 461, 334, 524, +5, 342, -328, -29, -484, -344, -414, -452, +-168, -344, 158, -75, 436, 225, 505, 391, +323, 373, -18, 180, -354, -81, -533, -279, +-446, -337, -121, -255, 267, -38, 504, 181, +488, 301, 235, 298, -141, 163, -448, -49, +-516, -236, -335, -316, -5, -229, 326, -48, +495, 148, 392, 286, 91, 275, -230, 132, +-429, -72, -419, -243, -205, -294, 91, -192, +315, -2, 381, 175, 273, 253, 31, 199, +-218, 41, -350, -137, -309, -247, -137, -223, +92, -93, 275, 74, 319, 187, 191, 181, +-21, 90, -196, -48, -271, -160, -235, -174, +-102, -114, 70, -12, 213, 93, 256, 119, +182, 89, 17, 20, -158, -52, -263, -95, +-243, -101, -104, -80, 88, -16, 231, 45, +254, 73, 155, 78, -21, 46, -193, -33, +-258, -72, -188, -89, -26, -73, 147, -7, +244, 52, 198, 69, 49, 36, -111, -28, +-195, -56, -162, -39, -45, 4, 70, 52, +127, 62, 120, 18, 77, -58, 20, -109, +-52, -84, -121, 11, -126, 108, -59, 151, +48, 109, 135, -9, 156, -122, 94, -166, +-13, -123, -126, 15, -180, 148, -114, 195, +25, 145, 133, 10, 167, -115, 122, -171, +10, -122, -112, 7, -163, 123, -126, 163, +-26, 138, 86, 40, 158, -78, 150, -129, +67, -92, -60, -23, -144, 59, -131, 97, +-68, 85, 20, 39, 131, -12, 171, -34, +100, -27, -3, -20, -88, 12, -142, 17, +-110, 3, -29, 2, 41, 7, 96, 30, +126, 53, 100, 50, 26, 27, -64, -10, +-124, -59, -144, -87, -115, -63, -6, 3, +141, 82, 220, 126, 186, 99, 38, 35, +-152, -58, -267, -135, -224, -146, -54, -85, +145, 34, 254, 135, 237, 162, 105, 126, +-98, 18, -249, -121, -258, -203, -160, -195, +16, -84, 207, 75, 291, 222, 221, 268, +43, 162, -184, -51, -330, -249, -295, -351, +-90, -287, 172, -49, 335, 240, 303, 404, +106, 375, -158, 117, -322, -224, -286, -459, +-117, -466, 83, -213, 244, 161, 264, 430, +134, 477, -41, 265, -176, -98, -239, -409, +-191, -501, -50, -321, 126, 28, 249, 336, +235, 452, 69, 330, -143, 18, -259, -306, +-223, -444, -66, -349, 147, -63, 269, 254, +186, 397, -11, 317, -172, 61, -219, -221, +-109, -360, 71, -293, 176, -51, 148, 205, +19, 312, -131, 217, -163, -1, -69, -202, +66, -260, 161, -150, 136, 54, 9, 212, +-91, 225, -121, 90, -106, -88, -35, -217, +52, -202, 93, -50, 107, 130, 97, 234, +40, 222, -80, 86, -181, -95, -177, -249, +-63, -255, 104, -111, 243, 91, 238, 268, +70, 314, -124, 183, -235, -54, -225, -271, +-80, -343, 106, -220, 218, 49, 214, 303, +129, 402, -10, 270, -146, -28, -229, -300, +-200, -397, -63, -264, 103, 18, 235, 281, +272, 392, 168, 291, -27, 42, -220, -195, +-322, -311, -257, -269, -28, -118, 225, 61, +373, 219, 324, 271, 91, 211, -187, 72, +-353, -103, -337, -239, -132, -271, 154, -186, +330, -8, 321, 191, 162, 305, -63, 273, +-249, 112, -313, -142, -224, -306, -18, -299, +206, -159, 305, 66, 242, 259, 75, 297, +-123, 194, -270, -6, -264, -198, -117, -284, +54, -241, 190, -89, 263, 112, 208, 248, +43, 263, -139, 153, -277, -47, -299, -234, +-136, -296, 120, -224, 314, -31, 347, 180, +187, 280, -113, 238, -362, 53, -384, -159, +-172, -277, 132, -256, 357, -92, 377, 116, +170, 238, -148, 210, -370, 66, -359, -103, +-147, -205, 130, -199, 331, -88, 333, 69, +144, 167, -98, 162, -263, 89, -318, -40, +-229, -151, -4, -176, 240, -122, 348, -2, +278, 132, 63, 179, -220, 144, -403, 12, +-342, -133, -78, -196, 232, -155, 424, -38, +368, 105, 64, 198, -273, 179, -421, 54, +-319, -100, -56, -197, 235, -176, 382, -69, +288, 91, 39, 200, -187, 183, -291, 76, +-248, -62, -72, -164, 114, -175, 202, -96, +211, 22, 148, 111, 4, 154, -147, 148, +-203, 67, -179, -38, -67, -120, 114, -178, +234, -164, 199, -56, 56, 120, -108, 246, +-199, 256, -155, 151, -29, -50, 107, -270, +169, -359, 104, -214, -11, 63, -78, 304, +-80, 411, -43, 279, 19, -23, 52, -324, +43, -428, 17, -273, -24, 23, -46, 304, +-14, 446, 50, 319, 75, -2, 43, -288, +-30, -390, -93, -296, -99, -43, -45, 247, +44, 394, 118, 298, 149, 42, 78, -199, +-49, -301, -132, -258, -148, -60, -113, 162, +6, 246, 154, 186, 197, 39, 123, -95, +-10, -155, -158, -121, -223, -16, -132, 58, +63, 63, 203, 28, 190, 5, 65, 5, +-71, 18, -184, 20, -186, -15, -36, -81, +117, -123, 170, -72, 144, 58, 36, 161, +-120, 178, -190, 79, -127, -117, -3, -261, +119, -225, 166, -61, 110, 149, -18, 274, +-129, 241, -157, 45, -89, -191, 25, -308, +126, -235, 146, -23, 69, 191, -38, 286, +-121, 202, -153, -19, -118, -201, -2, -258, +149, -164, 208, 17, 131, 178, -13, 217, +-158, 129, -247, -23, -180, -149, -2, -182, +159, -134, 250, -44, 223, 88, 42, 189, +-172, 171, -287, 78, -268, -51, -92, -188, +170, -231, 349, -154, 329, 30, 88, 225, +-234, 296, -416, 190, -343, -23, -73, -245, +267, -357, 446, -233, 339, 46, 39, 304, +-271, 395, -432, 231, -342, -59, -43, -324, +269, -410, 409, -228, 321, 96, 62, 336, +-232, 397, -396, 243, -320, -64, -67, -341, +210, -401, 359, -219, 312, 84, 99, 334, +-168, 415, -353, 265, -341, -64, -130, -371, +145, -431, 365, -247, 401, 74, 194, 365, +-141, 481, -410, 335, -444, -36, -204, -398, +168, -552, 426, -406, 458, 4, 233, 441, +-145, 658, -429, 511, -438, 51, -205, -484, +132, -764, 408, -610, 425, -73, 181, 556, +-132, 866, -341, 681, -354, 108, -168, -576, +112, -951, 298, -755, 301, -109, 132, 629, +-69, 1023, -191, 800, -213, 103, -142, -682, +-3, -1068, 129, -817, 179, -80, 140, 708, +35, 1096, -68, 826, -114, 47, -104, -730, +-42, -1065, 16, -794, 32, -41, 10, 728, +11, 1059, 45, 732, 87, -36, 85, -750, +21, -985, -88, -638, -192, 82, -180, 744, +-34, 923, 141, 508, 245, -197, 216, -744, +48, -825, -152, -401, -251, 257, -227, 734, +-83, 744, 98, 283, 221, -333, 236, -741, +134, -690, -28, -203, -155, 405, -240, 742, +-257, 608, -117, 116, 114, -457, 293, -758, +349, -587, 213, -75, -77, 501, -341, 775, +-417, 577, -271, 35, 42, -533, 327, -814, +425, -623, 293, -64, 2, 542, -281, 846, +-398, 664, -293, 91, -47, -519, 194, -830, +320, -689, 278, -175, 75, 441, -148, 801, +-234, 716, -199, 229, -82, -352, 54, -738, +125, -726, 120, -304, 90, 276, 56, 677, +28, 681, -37, 326, -152, -179, -198, -567, +-127, -619, 15, -351, 200, 80, 307, 430, +219, 541, -15, 388, -259, 70, -362, -265, +-221, -471, 45, -440, 268, -190, 330, 141, +196, 392, -24, 462, -204, 308, -264, -7, +-161, -321, 18, -463, 121, -352, 153, -72, +142, 263, 72, 460, -7, 400, -82, 106, +-153, -226, -173, -401, -82, -376, 83, -159, +239, 165, 270, 393, 148, 381, -79, 166, +-329, -74, -382, -287, -149, -393, 175, -301, +393, -18, 428, 277, 197, 419, -208, 372, +-480, 151, -456, -194, -165, -471, 230, -492, +514, -241, 503, 149, 182, 493, -263, 604, +-547, 378, -495, -115, -172, -563, 259, -714, +559, -487, 520, 36, 185, 623, -207, 882, +-497, 596, -573, -25, -297, -641, 158, -944, +492, -751, 580, -119, 401, 636, -20, 1035, +-463, 869, -655, 243, -497, -530, -44, -1057, +436, -1021, 655, -431, 513, 395, 99, 1018, +-353, 1117, -597, 618, -517, -228, -168, -957, +260, -1169, 507, -795, 477, -21, 218, 803, +-142, 1248, -396, 992, -431, 196, -279, -699, +-8, -1222, 275, -1143, 399, -467, 309, 524, +91, 1239, -137, 1257, -300, 626, -354, -327, +-220, -1129, 29, -1345, 218, -829, 289, 112, +264, 989, 109, 1330, -104, 980, -238, 125, +-269, -802, -195, -1272, -52, -1040, 92, -317, +214, 522, 288, 1094, 241, 1091, 46, 520, +-208, -286, -386, -896, -364, -1024, -152, -678, +174, -13, 448, 658, 480, 993, 208, 804, +-199, 229, -474, -431, -474, -870, -211, -876, +168, -463, 444, 182, 450, 751, 230, 927, +-105, 643, -406, 33, -419, -585, -160, -911, +97, -774, 257, -238, 320, 423, 178, 858, +-60, 850, -182, 410, -182, -228, -98, -733, +-2, -855, 37, -545, 72, 44, 107, 614, +86, 877, 55, 664, -10, 84, -138, -544, +-159, -848, -56, -707, 75, -184, 202, 468, +218, 860, 30, 761, -207, 221, -309, -428, +-199, -809, 98, -739, 354, -268, 388, 344, +184, 769, -188, 746, -501, 315, -487, -279, +-128, -683, 332, -674, 608, -322, 506, 160, +104, 541, -379, 618, -674, 377, -553, -28, +-81, -402, 424, -554, 674, -423, 560, -128, +142, 235, -344, 511, -643, 544, -608, 286, +-246, -117, 238, -505, 611, -656, 667, -453, +358, -7, -139, 485, -526, 757, -647, 623, +-463, 137, -19, -482, 438, -854, 622, -738, +463, -208, 107, 420, -264, 846, -481, 807, +-473, 302, -271, -357, 66, -800, 349, -776, +434, -317, 346, 252, 141, 638, -165, 688, +-416, 359, -464, -149, -308, -508, 15, -568, +350, -322, 503, 46, 414, 324, 121, 389, +-263, 275, -505, 73, -465, -117, -225, -220, +114, -234, 392, -183, 466, -111, 319, -13, +43, 161, -241, 316, -404, 359, -385, 210, +-212, -95, 48, -412, 270, -542, 381, -401, +364, -24, 181, 426, -122, 701, -378, 583, +-455, 104, -363, -447, -93, -737, 285, -625, +564, -182, 545, 355, 238, 706, -198, 641, +-574, 224, -682, -278, -419, -562, 94, -536, +571, -274, 768, 95, 582, 376, 66, 455, +-530, 335, -859, 96, -708, -161, -187, -351, +451, -388, 891, -291, 856, -74, 318, 211, +-399, 452, -878, 504, -872, 292, -400, -99, +283, -456, 825, -609, 897, -476, 464, -76, +-172, 405, -693, 686, -856, 610, -541, 209, +70, -291, 614, -636, 840, -663, 608, -380, +42, 119, -522, 553, -820, 705, -676, 512, +-128, 52, 488, -412, 826, -657, 731, -606, +194, -249, -472, 248, -828, 617, -716, 676, +-191, 428, 462, -67, 817, -533, 665, -741, +160, -609, -403, -146, -696, 436, -576, 805, +-172, 784, 297, 338, 578, -331, 537, -817, +239, -882, -171, -511, -502, 164, -550, 767, +-292, 959, 99, 639, 454, -18, 567, -670, +351, -945, -67, -731, -428, -135, -523, 549, +-334, 904, -7, 775, 307, 254, 459, -412, +341, -829, 73, -783, -171, -342, -340, 244, +-366, 711, -221, 791, 35, 458, 283, -96, +400, -582, 294, -754, 47, -544, -232, -87, +-411, 389, -361, 662, -115, 618, 188, 297, +408, -137, 390, -514, 117, -673, -193, -524, +-367, -119, -357, 320, -136, 654, 157, 733, +331, 430, 292, -137, 96, -667, -136, -882, +-245, -652, -196, -61, -69, 606, 62, 994, +142, 853, 141, 210, 58, -540, -36, -1032, +-84, -989, -87, -370, -46, 444, 18, 985, +71, 1029, 74, 536, 29, -239, -42, -863, +-84, -1055, -87, -708, -38, 8, 69, 654, +145, 974, 124, 867, 48, 322, -65, -400, +-212, -882, -239, -967, -71, -579, 140, 109, +272, 699, 293, 962, 156, 784, -131, 193, +-372, -475, -380, -898, -150, -900, 155, -447, +374, 227, 409, 734, 216, 924, -95, 677, +-340, 73, -409, -533, -282, -881, -8, -845, +255, -376, 372, 259, 370, 746, 249, 938, +-36, 696, -372, 85, -528, -563, -432, -988, +-125, -960, 319, -440, 676, 285, 687, 872, +309, 1112, -261, 797, -745, 59, -837, -677, +-439, -1122, 208, -1062, 744, -473, 898, 333, +591, 993, -45, 1225, -670, 870, -928, 77, +-669, -745, -79, -1272, 518, -1205, 863, -520, +775, 417, 265, 1191, -368, 1447, -775, 965, +-798, -25, -413, -1021, 194, -1565, 655, -1336, +761, -402, 507, 737, 7, 1552, -487, 1607, +-675, 837, -509, -348, -128, -1360, 256, -1771, +465, -1284, 448, -120, 258, 1067, -3, 1752, +-215, 1623, -315, 682, -328, -601, -266, -1605, +-109, -1857, 143, -1201, 417, 63, 503, 1284, +327, 1928, -1, 1656, -367, 544, -632, -842, +-578, -1842, -197, -1988, 293, -1120, 667, 358, +718, 1653, 396, 2131, -136, 1568, -627, 213, +-825, -1271, -608, -2155, -80, -1954, 518, -733, +878, 855, 748, 1965, 250, 2138, -331, 1281, +-783, -240, -872, -1643, -506, -2245, 98, -1759, +646, -377, 885, 1196, 684, 2169, 185, 2111, +-398, 1035, -842, -606, -879, -1957, -483, -2371, +139, -1610, 728, 23, 987, 1647, 747, 2403, +154, 1991, -559, 576, -1053, -1172, -982, -2308, +-384, -2257, 393, -1059, 993, 681, 1103, 2002, +632, 2277, -155, 1452, -860, -88, -1136, -1578, +-823, -2221, -107, -1777, 651, -469, 1088, 1071, +998, 2017, 422, 1964, -370, 987, -1006, -492, +-1135, -1728, -660, -2098, 152, -1437, 873, -47, +1150, 1362, 846, 2015, 122, 1688, -653, 558, +-1083, -865, -949, -1816, -337, -1811, 394, -937, +904, 367, 978, 1429, 580, 1724, -91, 1205, +-682, 149, -930, -960, -740, -1545, -183, -1375, +451, -585, 831, 464, 824, 1274, 449, 1425, +-148, 921, -678, 5, -875, -920, -655, -1381, +-115, -1158, 452, -382, 803, 568, 822, 1204, +447, 1244, -187, 711, -712, -151, -893, -946, +-689, -1228, -146, -928, 510, -238, 964, 555, +966, 1074, 450, 1070, -328, 604, -954, -128, +-1132, -803, -726, -1081, 116, -881, 905, -292, +1224, 477, 916, 1009, 101, 1042, -783, 611, +-1228, -109, -1032, -809, -305, -1081, 577, -824, +1124, -186, 1085, 554, 514, 998, -316, 931, +-951, 433, -1086, -254, -715, -782, -21, -913, +695, -627, 1059, -54, 914, 550, 334, 833, +-437, 731, -1011, 341, -1082, -198, -627, -634, +149, -762, 887, -570, 1181, -130, 866, 366, +96, 681, -738, 715, -1177, 463, -1025, -6, +-375, -469, 496, -754, 1133, -749, 1152, -387, +601, 203, -244, 688, -999, 888, -1222, 726, +-812, 187, -26, -506, 795, -983, 1219, -985, +995, -486, 292, 270, -562, 906, -1165, 1122, +-1144, 799, -558, 19, 293, -785, 1065, -1181, +1294, -1003, 793, -313, -96, 550, -931, 1104, +-1305, 1114, -960, 594, -98, -242, 807, -948, +1274, -1165, 1004, -830, 213, -87, -608, 663, +-1094, 1041, -992, 963, -330, 475, 425, -277, +879, -858, 876, -1025, 424, -774, -196, -171, +-617, 511, -696, 953, -456, 1017, -50, 610, +311, -130, 518, -808, 504, -1141, 268, -988, +-33, -297, -291, 563, -472, 1163, -476, 1256, +-233, 696, 127, -286, 441, -1121, 573, -1428, +439, -1024, 75, -29, -332, 987, -582, 1487, +-560, 1247, -264, 317, 181, -785, 550, -1446, +660, -1387, 448, -620, 6, 511, -458, 1324, +-704, 1429, -586, 826, -149, -211, 358, -1089, +688, -1356, 677, -975, 293, -104, -240, 813, +-606, 1223, -666, 988, -398, 318, 77, -490, +480, -967, 620, -904, 474, -455, 104, 172, +-291, 683, -534, 776, -538, 501, -271, 56, +123, -361, 414, -531, 545, -452, 440, -270, +64, 16, -339, 305, -532, 424, -488, 377, +-204, 235, 199, -7, 480, -257, 512, -450, +290, -481, -70, -236, -358, 142, -481, 439, +-391, 581, -92, 468, 225, 94, 410, -320, +453, -594, 260, -630, -112, -313, -386, 166, +-456, 528, -341, 667, -34, 510, 293, 103, +446, -325, 395, -641, 145, -692, -200, -350, +-414, 158, -422, 531, -238, 711, 74, 594, +347, 157, 437, -373, 313, -743, 12, -778, +-282, -383, -398, 185, -343, 645, -119, 850, +206, 633, 383, 68, 334, -514, 159, -888, +-101, -839, -329, -301, -348, 360, -186, 790, +52, 906, 255, 569, 313, -84, 216, -670, +25, -961, -183, -792, -263, -185, -207, 448, +-103, 852, 68, 932, 242, 529, 246, -163, +136, -743, 4, -1037, -160, -820, -257, -128, +-185, 563, -31, 967, 128, 980, 227, 456, +206, -310, 90, -897, -58, -1092, -185, -707, +-210, 53, -141, 685, -20, 1015, 135, 908, +251, 285, 240, -462, 111, -941, -97, -1040, +-269, -602, -293, 151, -165, 775, 53, 1060, +279, 853, 361, 180, 244, -534, 8, -1010, +-251, -1054, -408, -512, -342, 279, -78, 843, +241, 1048, 458, 771, 449, 91, 196, -586, +-184, -982, -510, -959, -565, -439, -274, 259, +192, 784, 546, 991, 613, 736, 352, 127, +-127, -483, -562, -908, -668, -965, -388, -511, +97, 188, 505, 743, 629, 1006, 431, 825, +31, 248, -377, -435, -585, -971, -505, -1101, +-194, -645, 213, 131, 522, 830, 567, 1203, +352, 1032, -30, 337, -436, -529, -657, -1216, +-537, -1350, -119, -752, 376, 230, 658, 1072, +606, 1473, 275, 1176, -224, 269, -653, -779, +-715, -1503, -400, -1506, 87, -687, 539, 445, +731, 1327, 532, 1644, 74, 1171, -400, 72, +-688, -1052, -648, -1705, -282, -1525, 233, -538, +619, 679, 687, 1552, 445, 1757, -2, 1087, +-479, -162, -738, -1330, -629, -1892, -210, -1513, +328, -322, 711, 971, 747, 1783, 422, 1800, +-131, 916, -641, -466, -814, -1615, -586, -1993, +-80, -1341, 484, -21, 813, 1216, 735, 1883, +303, 1696, -303, 617, -766, -758, -820, -1713, +-477, -1861, 96, -1088, 666, 213, 888, 1312, +630, 1798, 71, 1467, -517, 406, -841, -821, +-718, -1649, -245, -1739, 337, -943, 741, 297, +741, 1295, 375, 1723, -129, 1395, -550, 345, +-662, -859, -435, -1653, -74, -1689, 269, -875, +502, 349, 496, 1328, 289, 1717, 9, 1314, +-278, 253, -470, -903, -468, -1645, -277, -1637, +71, -786, 427, 416, 585, 1330, 482, 1648, +168, 1237, -266, 221, -590, -870, -644, -1577, +-421, -1572, 32, -782, 520, 346, 756, 1250, +640, 1647, 232, 1326, -330, 351, -785, -808, +-861, -1652, -489, -1757, 155, -950, 739, 309, +976, 1389, 724, 1895, 86, 1544, -600, 375, +-985, -1011, -909, -1951, -364, -1950, 392, -938, +919, 513, 984, 1681, 616, 2123, -52, 1558, +-714, 167, -1025, -1324, -848, -2185, -279, -1986, +426, -753, 948, 815, 1046, 1956, 638, 2235, +-114, 1432, -832, -151, -1165, -1652, -943, -2342, +-219, -1868, 645, -433, 1193, 1139, 1158, 2108, +540, 2149, -370, 1136, -1096, -475, -1280, -1795, +-835, -2232, 35, -1596, 887, -174, 1290, 1224, +1064, 2023, 310, 1969, -594, 930, -1183, -601, +-1192, -1745, -643, -2054, 216, -1417, 956, -88, +1227, 1213, 923, 1929, 177, 1823, -660, 815, +-1161, -587, -1113, -1656, -567, -1985, 260, -1397, +992, -120, 1239, 1147, 891, 1918, 129, 1890, +-697, 897, -1200, -565, -1142, -1716, -558, -2122, +319, -1533, 1077, -160, 1321, 1282, 923, 2157, +75, 2055, -840, 871, -1368, -755, -1234, -1989, +-498, -2317, 526, -1507, 1331, 94, 1463, 1608, +866, 2362, -166, 2002, -1141, 599, -1552, -1094, +-1188, -2220, -244, -2319, 859, -1253, 1544, 458, +1428, 1891, 596, 2423, -537, 1796, -1401, 210, +-1518, -1448, -869, -2349, 198, -2143, 1169, -860, +1499, 858, 1038, 2063, 128, 2262, -809, 1366, +-1323, -229, -1122, -1635, -416, -2176, 391, -1688, +1006, -365, 1141, 1057, 738, 1833, 38, 1758, +-653, 881, -1028, -437, -920, -1414, -437, -1641, +255, -1173, 871, -196, 1047, 815, 740, 1353, +118, 1318, -617, 718, -1057, -209, -942, -958, +-414, -1259, 300, -1060, 907, -359, 1058, 457, +715, 997, 49, 1176, -690, 855, -1082, 97, +-916, -621, -355, -1055, 391, -1107, 993, -648, +1070, 81, 609, 721, -122, 1160, -809, 1134, +-1075, 536, -785, -279, -147, -1013, 553, -1411, +989, -1127, 907, -282, 410, 716, -254, 1520, +-831, 1638, -988, 869, -627, -333, -9, -1439, +600, -1913, 941, -1387, 803, -158, 269, 1142, +-365, 1991, -819, 1854, -861, 743, -486, -700, +95, -1832, 620, -2101, 825, -1280, 612, 107, +150, 1422, -371, 2173, -756, 1861, -748, 577, +-347, -929, 183, -2015, 612, -2180, 747, -1270, +516, 239, 55, 1681, -435, 2400, -735, 1885, +-638, 422, -222, -1223, 263, -2353, 608, -2323, +653, -1061, 375, 676, -59, 2100, -476, 2557, +-678, 1676, -501, -65, -69, -1715, 350, -2535, +594, -2079, 542, -591, 208, 1120, -207, 2310, +-507, 2364, -568, 1176, -304, -498, 125, -1854, +417, -2371, 453, -1696, 287, -185, 18, 1287, +-216, 2146, -335, 1995, -291, 829, -99, -661, +83, -1761, 158, -2074, 212, -1366, 212, 0, +100, 1283, -44, 1964, -193, 1715, -321, 607, +-250, -715, -10, -1680, 206, -1898, 346, -1160, +338, 130, 111, 1271, -190, 1859, -391, 1575, +-378, 474, -119, -805, 186, -1682, 332, -1806, +328, -1004, 167, 276, -99, 1349, -278, 1810, +-290, 1393, -170, 242, 48, -942, 230, -1644, +271, -1589, 175, -716, -20, 470, -185, 1327, +-218, 1589, -159, 1086, -12, 28, 167, -955, +206, -1453, 97, -1297, -28, -495, -119, 482, +-117, 1190, -32, 1420, 40, 948, 74, -29, +61, -905, -15, -1373, -61, -1233, -49, -428, +-14, 547, 62, 1215, 103, 1386, 16, 838, +-77, -174, -102, -1009, -93, -1333, -18, -1016, +106, -179, 170, 626, 152, 1115, 32, 1154, +-165, 541, -257, -333, -163, -863, -1, -1008, +141, -722, 223, -60, 199, 512, 74, 816, +-116, 855, -275, 435, -246, -189, -56, -624, +131, -813, 248, -649, 272, -182, 134, 265, +-110, 681, -301, 892, -333, 565, -171, -21, +111, -514, 320, -863, 333, -801, 184, -335, +-49, 205, -279, 759, -374, 1049, -257, 692, +38, 1, 307, -627, 351, -1023, 188, -902, +-17, -316, -210, 367, -307, 958, -206, 1089, +-6, 572, 142, -174, 224, -801, 202, -1097, +68, -776, -58, -91, -124, 531, -184, 981, +-181, 997, -58, 435, 111, -287, 198, -846, +175, -1043, 76, -702, -42, -68, -139, 536, +-173, 1007, -130, 1007, -30, 445, 91, -278, +172, -897, 179, -1172, 121, -787, -16, -12, +-184, 708, -257, 1180, -192, 1093, -39, 372, +164, -515, 284, -1178, 236, -1275, 70, -624, +-134, 300, -257, 977, -207, 1285, -83, 955, +50, 32, 202, -854, 242, -1289, 115, -1117, +-35, -302, -157, 611, -205, 1128, -127, 1183, +-21, 645, 60, -308, 173, -1025, 208, -1207, +114, -804, -5, 60, -135, 794, -230, 1046, +-181, 912, -56, 282, 89, -580, 257, -1019, +289, -911, 110, -405, -113, 344, -268, 823, +-279, 831, -123, 546, 74, -49, 230, -684, +325, -837, 210, -545, -74, -40, -280, 471, +-313, 653, -193, 509, 46, 235, 240, -211, +284, -554, 196, -490, -12, -212, -234, 82, +-275, 307, -136, 301, 54, 208, 188, 129, +192, -69, 93, -235, -15, -203, -110, -128, +-158, -37, -98, 53, 10, 86, 57, 164, +50, 207, 47, 64, 51, -72, 36, -127, +7, -191, -24, -166, -58, -58, -98, 39, +-83, 208, -4, 311, 74, 187, 114, -13, +112, -190, 32, -314, -83, -256, -147, -106, +-137, 74, -62, 315, 55, 397, 137, 204, +162, -32, 119, -240, -20, -361, -166, -272, +-196, -90, -152, 98, -41, 328, 137, 377, +232, 191, 162, -44, 28, -270, -98, -380, +-178, -252, -172, -56, -95, 169, 36, 419, +161, 410, 174, 91, 116, -241, 31, -449, +-103, -401, -191, -86, -158, 223, -84, 397, +36, 418, 163, 148, 173, -245, 97, -442, +10, -364, -96, -55, -135, 268, -93, 314, +-61, 207, 3, 76, 91, -158, 97, -320, +80, -222, 68, -15, -2, 200, -81, 276, +-120, 104, -151, -53, -87, -72, 67, -148, +192, -185, 235, -82, 142, 52, -69, 204, +-215, 247, -237, 57, -187, -60, -22, -63, +182, -194, 251, -253, 187, -75, 55, 142, +-80, 320, -148, 280, -170, -8, -169, -164, +-71, -179, 83, -260, 202, -163, 246, 107, +160, 271, -21, 330, -166, 182, -254, -165, +-262, -272, -115, -198, 120, -192, 290, -37, +323, 207, 187, 281, -21, 265, -190, 74, +-317, -218, -346, -240, -150, -146, 159, -148, +365, 15, 393, 201, 235, 196, -43, 172, +-299, 54, -434, -153, -380, -142, -108, -91, +251, -137, 479, -39, 465, 92, 219, 130, +-121, 207, -401, 146, -521, -48, -419, -120, +-84, -195, 333, -263, 596, -77, 538, 128, +196, 224, -218, 301, -521, 166, -610, -105, +-389, -199, 63, -238, 480, -216, 643, -15, +488, 126, 63, 169, -386, 243, -606, 138, +-558, -52, -283, -96, 172, -156, 589, -216, +688, -121, 420, -16, -51, 125, -492, 284, +-689, 225, -570, 66, -172, -44, 360, -244, +730, -334, 676, -178, 243, 2, -316, 202, +-687, 381, -654, 270, -286, 34, 176, -132, +535, -312, 604, -359, 338, -181, -70, 38, +-393, 279, -492, 412, -342, 262, -86, 27, +158, -165, 352, -370, 399, -360, 217, -122, +-74, 102, -323, 284, -391, 360, -224, 193, +45, -22, 242, -180, 293, -290, 179, -242, +-33, -91, -176, 33, -169, 198, -70, 295, +19, 202, 19, 62, -29, -93, -34, -280, +52, -308, 147, -192, 148, -1, 36, 262, +-111, 391, -192, 268, -162, 59, -66, -197, +54, -379, 169, -309, 175, -127, 64, 61, +-28, 305, -77, 369, -109, 182, -97, -18, +-74, -173, -42, -274, 91, -232, 204, -124, +148, 63, 2, 273, -123, 259, -192, 107, +-146, 19, -23, -121, 109, -213, 189, -139, +106, -85, -77, -16, -137, 140, -51, 141, +74, 102, 122, 162, 17, 79, -141, -112, +-174, -225, -81, -319, 80, -218, 225, 102, +225, 304, 68, 370, -164, 336, -320, 8, +-224, -356, 23, -464, 161, -361, 186, -17, +170, 364, 61, 404, -44, 279, -87, 107, +-161, -209, -218, -377, -148, -254, -17, -98, +150, 83, 334, 225, 361, 183, 130, 131, +-243, 100, -511, -50, -465, -158, -151, -203, +235, -226, 543, -65, 553, 149, 152, 224, +-318, 279, -551, 209, -529, -70, -224, -280, +251, -322, 519, -247, 461, 17, 213, 253, +-139, 290, -417, 240, -450, 75, -273, -163, +25, -255, 296, -252, 383, -158, 278, 82, +40, 225, -245, 200, -342, 182, -230, 61, +-82, -140, 85, -233, 234, -251, 196, -153, +60, 109, -7, 244, -72, 230, -145, 190, +-137, -11, -105, -236, -62, -237, 57, -188, +181, -81, 173, 158, 55, 246, -71, 153, +-155, 105, -187, -1, -119, -147, 49, -200, +165, -219, 121, -100, 23, 153, -26, 233, +-59, 211, -90, 174, -77, -81, -51, -322, +-32, -265, 36, -135, 124, 64, 109, 341, +22, 326, -42, 45, -99, -165, -152, -289, +-69, -233, 107, 1, 121, 156, -20, 228, +-77, 202, -39, -68, -1, -244, 64, -130, +95, -5, -4, 117, -146, 222, -192, 53, +-67, -147, 137, -155, 231, -151, 154, -40, +-36, 217, -252, 288, -278, 169, -60, -58, +144, -349, 206, -358, 170, -75, 3, 147, +-181, 353, -191, 439, -74, 129, 56, -283, +127, -478, 57, -452, -24, -78, -22, 408, +-30, 560, -37, 412, 3, 43, -30, -447, +-79, -617, -19, -398, 48, -26, 78, 450, +98, 707, -2, 424, -156, -63, -160, -453, +-43, -652, 81, -457, 164, 29, 118, 466, +-39, 683, -184, 478, -214, -64, -82, -497, +108, -637, 181, -464, 130, 60, 20, 554, +-116, 643, -176, 387, -114, -87, -23, -559, +58, -646, 107, -349, 81, 122, 10, 558, +-41, 639, -92, 309, -133, -138, -113, -518, +6, -644, 146, -360, 153, 136, 39, 524, +-55, 659, -145, 435, -222, -48, -126, -535, +89, -789, 203, -593, 180, 22, 36, 628, +-169, 893, -265, 705, -180, 58, 7, -722, +192, -1085, 236, -805, 134, -48, -49, 779, +-274, 1190, -342, 899, -120, 46, 145, -868, +256, -1240, 258, -898, 123, -89, -147, 813, +-351, 1286, -359, 947, -159, 58, 164, -815, +399, -1228, 388, -921, 154, -76, -205, 748, +-476, 1137, -466, 882, -207, 103, 169, -689, +490, -1062, 492, -844, 161, -79, -230, 691, +-484, 946, -500, 699, -215, 101, 180, -610, +448, -931, 494, -664, 248, -17, -199, 665, +-516, 915, -526, 537, -263, -131, 161, -726, +498, -898, 505, -427, 196, 343, -236, 887, +-540, 939, -497, 327, -123, -650, 318, -1205, +534, -945, 359, -62, -74, 972, -439, 1442, +-518, 984, -274, -114, 177, -1285, 517, -1765, +488, -1054, 129, 378, -342, 1624, -624, 1969, +-497, 1080, -57, -551, 424, -1862, 667, -2135, +487, -1155, -14, 633, -524, 2113, -773, 2349, +-574, 1195, 4, -753, 576, -2278, 788, -2437, +547, -1218, -16, 742, -569, 2360, -802, 2564, +-618, 1252, -96, -767, 486, -2371, 758, -2565, +598, -1226, 150, 729, -364, 2244, -717, 2508, +-717, 1287, -364, -643, 174, -2113, 628, -2392, +761, -1303, 507, 515, -40, 1944, -617, 2260, +-858, 1329, -643, -360, -131, -1756, 472, -2121, +851, -1369, 706, 163, 153, 1600, -452, 2028, +-808, 1342, -716, -30, -244, -1383, 300, -1895, +651, -1333, 628, -133, 257, 1128, -200, 1759, +-531, 1348, -588, 242, -318, -904, 60, -1553, +303, -1326, 387, -416, 309, 607, 62, 1320, +-183, 1355, -293, 598, -283, -411, -186, -1107, +-46, -1275, 66, -796, 161, 124, 255, 912, +253, 1214, 82, 916, -197, 128, -433, -681, +-464, -1101, -246, -1018, 143, -407, 512, 407, +583, 968, 245, 1089, -263, 687, -615, -126, +-610, -849, -218, -1137, 298, -937, 551, -232, +445, 694, 104, 1254, -311, 1138, -529, 426, +-381, -508, -49, -1184, 232, -1293, 358, -743, +249, 298, -15, 1210, -215, 1407, -285, 863, +-211, -88, -28, -1015, 109, -1437, 163, -1106, +164, -172, 43, 880, -126, 1458, -209, 1243, +-211, 386, -114, -676, 53, -1370, 178, -1336, +259, -636, 209, 419, -78, 1314, -387, 1467, +-440, 785, -257, -265, 69, -1131, 408, -1425, +523, -977, 299, 26, -140, 1056, -561, 1479, +-699, 1055, -409, 83, 158, -916, 641, -1445, +727, -1170, 353, -192, -209, 934, -644, 1504, +-795, 1165, -517, 159, 131, -928, 655, -1488, +726, -1144, 428, -100, -89, 987, -566, 1491, +-707, 1090, -521, -20, -115, -1065, 381, -1384, +672, -922, 571, 24, 164, 984, -343, 1366, +-651, 919, -616, -76, -331, -1006, 121, -1289, +576, -834, 675, -2, 328, 858, -166, 1317, +-534, 991, -617, 67, -350, -892, 58, -1380, +348, -1063, 442, -149, 278, 821, -72, 1430, +-306, 1286, -299, 308, -180, -868, -52, -1546, +34, -1389, 53, -424, 63, 794, 100, 1549, +131, 1512, 96, 633, -60, -676, -271, -1602, +-366, -1616, -275, -757, -38, 502, 294, 1444, +498, 1622, 343, 1000, -40, -187, -409, -1319, +-612, -1673, -457, -1122, 2, -76, 394, 955, +549, 1506, 436, 1314, 33, 492, -421, -587, +-645, -1381, -533, -1436, -94, -798, 376, 129, +547, 1004, 451, 1478, 157, 1254, -312, 389, +-664, -719, -605, -1523, -179, -1561, 313, -838, +587, 290, 528, 1374, 164, 1853, -326, 1360, +-644, 118, -612, -1257, -233, -2025, 290, -1708, +593, -504, 500, 942, 134, 2008, -279, 2093, +-522, 1004, -514, -670, -282, -1983, 108, -2233, +430, -1317, 468, 221, 284, 1674, -21, 2350, +-374, 1750, -581, 187, -518, -1396, -203, -2267, +291, -1990, 695, -662, 683, 943, 253, 2063, +-354, 2225, -864, 1200, -950, -493, -454, -1895, +371, -2326, 1019, -1566, 1076, -14, 464, 1510, +-479, 2348, -1212, 2007, -1284, 511, -582, -1251, +492, -2279, 1272, -2138, 1308, -901, 575, 796, +-539, 2058, -1380, 2271, -1413, 1289, -635, -421, +456, -1852, 1256, -2227, 1350, -1466, 643, -2, +-445, 1463, -1216, 2169, -1287, 1721, -729, 360, +163, -1191, 959, -2088, 1217, -1809, 756, -569, +-82, 896, -753, 1856, -1048, 1851, -944, 820, +-374, -699, 417, -1762, 963, -1715, 1000, -721, +548, 537, -185, 1402, -882, 1479, -1188, 731, +-895, -393, -136, -1193, 750, -1193, 1295, -503, +1049, 332, 145, 820, -781, 791, -1287, 362, +-1153, -166, -389, -518, 576, -536, 1201, -216, +1133, 152, 374, 245, -534, 138, -1040, 70, +-1016, 60, -544, 40, 156, 13, 733, -40, +911, -125, 584, -216, -39, -233, -553, -50, +-760, 271, -655, 445, -267, 319, 219, -38, +549, -393, 570, -494, 309, -320, -48, 19, +-331, 438, -477, 618, -446, 328, -288, -159, +-77, -500, 189, -555, 427, -256, 489, 190, +352, 491, 30, 516, -426, 213, -797, -235, +-812, -488, -370, -459, 330, -170, 884, 245, +1042, 465, 675, 378, -211, 133, -1101, -198, +-1392, -440, -1004, -368, -86, -78, 1009, 183, +1588, 335, 1273, 317, 269, 99, -969, -143, +-1789, -240, -1674, -226, -637, -97, 790, 84, +1789, 131, 1805, 87, 870, 87, -586, 61, +-1813, 6, -2081, -23, -1238, -69, 284, -110, +1665, -110, 2099, -93, 1401, 5, -36, 161, +-1496, 238, -2190, 187, -1739, 28, -347, -152, +1268, -225, 2106, -233, 1738, -196, 514, -19, +-971, 246, -1974, 413, -1914, 376, -858, 129, +629, -207, 1727, -482, 1792, -594, 928, -408, +-320, 117, -1420, 693, -1786, 922, -1205, 591, +-65, -159, 1045, -859, 1586, -1082, 1257, -749, +295, 47, -778, 954, -1446, 1360, -1359, 930, +-611, -84, 357, -1093, 1118, -1460, 1301, -959, +771, 59, -117, 1041, -887, 1492, -1270, 1105, +-1066, 63, -321, -1048, 559, -1567, 1144, -1141, +1178, -95, 600, 889, -354, 1386, -1204, 1203, +-1422, 371, -843, -675, 150, -1317, 1026, -1228, +1387, -514, 956, 395, -94, 1041, -1075, 1151, +-1399, 739, -1002, 5, -120, -726, 830, -1099, +1274, -918, 946, -322, 141, 353, -683, 850, +-1170, 1036, -1079, 767, -441, 77, 437, -671, +1070, -1105, 1067, -1074, 479, -537, -351, 321, +-1023, 1109, -1167, 1432, -701, 1016, 124, -15, +915, -1084, 1179, -1645, 714, -1419, -149, -433, +-907, 882, -1167, 1856, -819, 1887, -122, 831, +625, -720, 1116, -1898, 988, -2133, 231, -1284, +-675, 304, -1187, 1828, -1082, 2430, -494, 1715, +355, 48, 1122, -1668, 1298, -2502, 672, -2025, +-415, -519, -1314, 1279, -1451, 2490, -792, 2389, +226, 1007, 1134, -897, 1456, -2353, 926, -2559, +-160, -1427, -1184, 348, -1563, 1978, -1067, 2698, +-23, 1970, 957, 180, 1407, -1652, 1101, -2651, +189, -2285, -839, -742, -1444, 1132, -1290, 2458, +-441, 2570, 620, 1301, 1305, -633, 1258, -2189, +514, -2613, -511, -1678, -1262, 87, -1341, 1712, +-698, 2460, 286, 2006, 1059, 541, 1222, -1173, +678, -2238, -256, -2152, -981, -1032, -1110, 496, +-681, 1766, 26, 2240, 665, 1589, 923, 110, +622, -1368, -59, -2143, -605, -1891, -746, -737, +-522, 798, -47, 1983, 317, 2145, 351, 1175, +287, -318, 119, -1614, -201, -2116, -279, -1522, +-123, -217, -89, 1126, -122, 1958, -152, 1770, +-134, 673, 104, -634, 325, -1591, 268, -1803, +85, -1133, -170, 24, -432, 1185, -504, 1818, +-348, 1469, 80, 387, 570, -781, 583, -1579, +174, -1614, -183, -834, -468, 348, -643, 1361, +-442, 1645, 13, 1043, 404, -21, 600, -995, +440, -1436, -48, -1149, -474, -334, -611, 591, +-496, 1181, -149, 1148, 302, 582, 583, -204, +513, -832, 57, -1009, -480, -742, -612, -210, +-365, 405, -56, 822, 249, 846, 414, 509, +242, -30, -80, -527, -288, -782, -306, -751, +-115, -385, 79, 208, 47, 699, -62, 866, +-81, 667, -55, 136, 42, -477, 140, -875, +64, -879, -94, -427, -225, 252, -309, 777, +-184, 941, 99, 639, 258, 11, 246, -579, +99, -919, -165, -828, -338, -234, -321, 417, +-180, 775, 45, 844, 218, 511, 247, -122, +180, -658, -12, -913, -277, -692, -414, -35, +-332, 532, -65, 776, 218, 754, 335, 346, +300, -292, 100, -774, -266, -827, -528, -392, +-463, 175, -154, 529, 217, 694, 432, 573, +367, 123, 120, -358, -192, -663, -459, -649, +-512, -268, -290, 164, 87, 476, 412, 676, +460, 551, 201, 94, -120, -420, -358, -781, +-498, -714, -409, -207, -58, 345, 299, 739, +430, 853, 270, 437, -20, -289, -186, -810, +-278, -894, -380, -498, -288, 198, -28, 748, +153, 885, 276, 565, 320, -97, 172, -675, +-46, -823, -313, -574, -596, -48, -538, 526, +-80, 796, 366, 617, 586, 126, 539, -415, +158, -712, -375, -640, -745, -265, -745, 248, +-297, 673, 323, 758, 666, 386, 632, -225, +300, -668, -238, -746, -659, -469, -726, 49, +-450, 571, 73, 843, 514, 663, 570, 43, +362, -582, 26, -842, -371, -715, -567, -256, +-470, 369, -216, 857, 106, 965, 329, 520, +361, -272, 301, -913, 118, -1124, -201, -778, +-453, 60, -533, 901, -423, 1343, -80, 1139, +351, 161, 625, -1023, 594, -1585, 187, -1302, +-426, -305, -843, 960, -827, 1722, -395, 1543, +289, 500, 842, -919, 913, -1820, 457, -1668, +-313, -640, -961, 760, -1060, 1771, -605, 1767, +126, 857, 813, -491, 1052, -1656, 671, -1885, +-91, -1049, -833, 265, -1132, 1437, -825, 1870, +-142, 1280, 599, 69, 1054, -1158, 905, -1835, +250, -1480, -547, -326, -1133, 895, -1140, 1635, +-487, 1548, 409, 663, 1073, -503, 1170, -1416, +566, -1626, -411, -967, -1171, 136, -1312, 1102, +-709, 1557, 342, 1267, 1149, 384, 1209, -702, +576, -1560, -369, -1664, -1104, -850, -1202, 393, +-634, 1467, 255, 1882, 932, 1367, 971, 103, +447, -1346, -220, -2217, -716, -1867, -842, -428, +-546, 1245, -25, 2281, 430, 2193, 607, 925, +461, -956, 135, -2410, -223, -2571, -511, -1284, +-587, 767, -400, 2379, -48, 2679, 324, 1598, +536, -359, 462, -2224, 168, -2863, -223, -1890, +-600, 107, -720, 2041, -419, 2808, 93, 2008, +498, 224, 668, -1649, 522, -2695, 49, -2220, +-512, -506, -830, 1378, -700, 2450, -201, 2165, +348, 742, 678, -941, 681, -2110, 334, -2193, +-209, -991, -677, 691, -831, 1801, -571, 1958, +-40, 1134, 477, -300, 764, -1472, 680, -1820, +244, -1234, -368, 17, -885, 1163, -950, 1593, +-466, 1244, 201, 278, 720, -790, 925, -1381, +618, -1291, -88, -525, -731, 529, -994, 1182, +-774, 1202, -168, 688, 463, -177, 815, -948, +798, -1209, 374, -847, -272, -6, -779, 799, +-926, 1104, -653, 856, -82, 199, 508, -572, +903, -1041, 860, -947, 262, -294, -486, 521, +-926, 973, -971, 887, -570, 348, 152, -400, +763, -904, 966, -884, 678, -387, 9, 356, +-618, 905, -933, 884, -903, 344, -454, -367, +242, -829, 804, -808, 1039, -363, 756, 283, +-34, 805, -816, 843, -1188, 361, -1090, -303, +-422, -743, 619, -758, 1344, -394, 1270, 161, +505, 651, -537, 785, -1341, 493, -1465, -64, +-821, -597, 257, -781, 1186, -536, 1464, -72, +942, 443, -103, 798, -1082, 724, -1459, 236, +-1126, -405, -291, -853, 728, -803, 1384, -351, +1229, 251, 415, 826, -555, 992, -1269, 548, +-1359, -188, -725, -853, 242, -1060, 1031, -631, +1280, 60, 803, 707, -106, 1119, -859, 862, +-1162, 57, -940, -690, -240, -1071, 530, -888, +931, -211, 838, 468, 347, 924, -245, 987, +-659, 446, -848, -322, -669, -831, -108, -945, +404, -561, 633, 69, 649, 566, 376, 872, +-124, 792, -568, 197, -800, -469, -670, -814, +-173, -772, 355, -350, 676, 222, 709, 632, +385, 758, -157, 512, -655, -27, -903, -509, +-674, -652, -63, -461, 494, -106, 780, 207, +743, 391, 290, 434, -375, 310, -845, 37, +-893, -219, -493, -332, 159, -341, 665, -269, +793, -85, 546, 156, 30, 400, -506, 505, +-786, 295, -703, -70, -305, -345, 224, -532, +598, -524, 663, -208, 454, 233, 28, 612, +-480, 741, -790, 430, -711, -93, -303, -542, +247, -842, 681, -756, 769, -200, 477, 486, +-78, 1005, -667, 1045, -928, 447, -704, -372, +-175, -1006, 440, -1264, 863, -824, 812, 167, +349, 1067, -284, 1443, -850, 1068, -1007, 73, +-627, -942, 18, -1524, 644, -1369, 990, -383, +825, 830, 216, 1548, -534, 1515, -1064, 664, +-1065, -580, -540, -1450, 249, -1606, 961, -981, +1187, 250, 768, 1341, -71, 1658, -956, 1148, +-1393, 80, -1051, -1010, -166, -1567, 771, -1382, +1364, -485, 1219, 718, 326, 1498, -754, 1463, +-1414, 748, -1335, -304, -546, -1206, 509, -1512, +1253, -1080, 1314, -87, 645, 968, -386, 1480, +-1175, 1225, -1310, 421, -772, -556, 104, -1274, +871, -1384, 1182, -826, 854, 164, 36, 1096, +-763, 1450, -1110, 1067, -896, 202, -254, -749, +461, -1385, 884, -1369, 848, -615, 357, 507, +-338, 1347, -796, 1452, -785, 834, -420, -175, +63, -1101, 452, -1499, 606, -1110, 478, -108, +106, 913, -328, 1399, -555, 1171, -499, 390, +-301, -535, -23, -1180, 319, -1266, 538, -704, +444, 218, 86, 965, -327, 1214, -575, 901, +-514, 165, -207, -631, 158, -1138, 439, -1136, +507, -532, 253, 367, -190, 1020, -474, 1169, +-425, 798, -210, 32, 0, -775, 202, -1237, +321, -1098, 232, -357, 2, 586, -195, 1192, +-260, 1215, -202, 686, -102, -212, -11, -1088, +93, -1428, 162, -992, 110, -26, -30, 961, +-123, 1476, -113, 1217, -56, 327, -36, -735, +-56, -1484, -45, -1489, -6, -643, 10, 581, +44, 1496, 118, 1601, 108, 829, -62, -347, +-242, -1353, -288, -1739, -168, -1124, 69, 200, +278, 1349, 295, 1758, 103, 1231, -159, -32, +-345, -1228, -358, -1719, -143, -1346, 186, -165, +338, 1150, 218, 1730, 7, 1366, -196, 259, +-330, -1000, -254, -1606, -16, -1353, 184, -443, +250, 797, 133, 1579, -91, 1397, -221, 500, +-217, -651, -129, -1436, 46, -1377, 203, -624, +197, 463, 14, 1367, -215, 1449, -282, 678, +-140, -425, 31, -1290, 171, -1402, 260, -720, +152, 321, -138, 1226, -375, 1444, -372, 756, +-89, -335, 244, -1176, 345, -1339, 233, -736, +3, 244, -289, 1060, -447, 1295, -315, 770, +55, -198, 418, -988, 429, -1156, 69, -660, +-267, 115, -393, 725, -348, 955, -109, 661, +241, -28, 449, -618, 333, -748, -58, -425, +-417, 56, -478, 344, -267, 400, 57, 279, +318, -22, 390, -256, 284, -212, 0, 14, +-376, 236, -533, 193, -327, -118, 6, -316, +253, -302, 378, -182, 342, 144, 111, 519, +-216, 613, -432, 341, -418, -240, -206, -767, +80, -803, 292, -434, 354, 144, 272, 761, +71, 1017, -191, 726, -406, 12, -447, -842, +-245, -1238, 73, -903, 334, -159, 466, 701, +378, 1309, 38, 1205, -360, 435, -602, -613, +-540, -1414, -145, -1428, 309, -651, 552, 458, +536, 1404, 224, 1643, -256, 964, -575, -266, +-590, -1427, -335, -1841, 90, -1222, 433, 41, +543, 1337, 422, 1996, 67, 1547, -356, 242, +-596, -1210, -569, -2077, -265, -1833, 185, -613, +527, 939, 646, 2091, 444, 2156, -107, 1034, +-620, -609, -734, -1976, -501, -2364, -55, -1483, +429, 164, 688, 1747, 588, 2500, 168, 1928, +-362, 308, -669, -1466, -610, -2493, -290, -2206, +117, -776, 446, 1014, 591, 2338, 462, 2459, +36, 1219, -439, -618, -611, -2073, -454, -2461, +-171, -1545, 140, 119, 436, 1639, 540, 2361, +313, 1876, -78, 373, -376, -1251, -483, -2154, +-397, -1971, -174, -832, 115, 671, 402, 1843, +524, 2132, 334, 1312, -70, -191, -440, -1555, +-554, -2116, -401, -1627, -117, -347, 270, 1108, +600, 2058, 514, 1985, 64, 848, -346, -777, +-517, -1977, -428, -2099, -141, -1179, 174, 277, +386, 1673, 373, 2264, 99, 1596, -191, 59, +-277, -1468, -197, -2198, -62, -1765, 17, -482, +38, 1011, 71, 2060, 53, 2039, -15, 887, +19, -696, 92, -1884, 31, -2079, -127, -1188, +-247, 241, -210, 1519, -20, 2089, 151, 1552, +239, 167, 258, -1248, 112, -1978, -189, -1675, +-425, -535, -385, 774, -84, 1687, 220, 1797, +355, 933, 359, -399, 198, -1419, -147, -1707, +-464, -1160, -517, -56, -270, 1002, 122, 1556, +413, 1371, 496, 469, 375, -649, 22, -1382, +-433, -1430, -697, -758, -558, 293, -60, 1140, +463, 1414, 680, 986, 550, 11, 160, -962, +-370, -1379, -754, -1054, -697, -191, -203, 729, +382, 1224, 674, 1070, 572, 348, 208, -543, +-224, -1081, -558, -1006, -636, -418, -357, 350, +136, 888, 490, 929, 539, 503, 341, -146, +-15, -682, -370, -832, -565, -554, -499, -55, +-128, 423, 336, 718, 570, 678, 483, 277, +164, -245, -226, -615, -484, -710, -546, -489, +-360, -23, 72, 481, 454, 805, 532, 717, +372, 186, 72, -436, -270, -787, -501, -760, +-536, -372, -316, 240, 102, 788, 446, 935, +548, 501, 425, -259, 114, -800, -290, -869, +-612, -534, -661, 75, -323, 704, 215, 998, +601, 716, 682, -49, 449, -785, -59, -1020, +-620, -719, -871, -72, -581, 648, 73, 1084, +633, 974, 801, 269, 541, -680, -23, -1201, +-593, -1012, -845, -366, -606, 452, 15, 1101, +586, 1193, 734, 647, 478, -283, 33, -1064, +-400, -1198, -657, -737, -603, -11, -193, 730, +331, 1144, 595, 963, 535, 303, 277, -493, +-107, -1010, -476, -989, -664, -528, -529, 128, +-36, 732, 496, 998, 690, 762, 518, 132, +118, -522, -340, -852, -666, -795, -694, -405, +-304, 201, 313, 695, 686, 815, 643, 548, +321, 12, -145, -486, -562, -692, -742, -622, +-540, -283, 43, 230, 606, 600, 744, 665, +495, 441, 22, 1, -486, -424, -734, -666, +-589, -637, -116, -248, 446, 289, 683, 650, +486, 745, 101, 478, -282, -92, -518, -614, +-479, -854, -229, -686, 115, -90, 375, 555, +390, 901, 242, 851, 45, 332, -198, -427, +-373, -927, -363, -952, -180, -500, 99, 247, +294, 840, 310, 982, 238, 667, 65, 7, +-205, -675, -364, -988, -306, -797, -122, -228, +80, 438, 236, 882, 327, 897, 295, 476, +65, -185, -249, -756, -434, -952, -382, -662, +-136, -53, 164, 577, 405, 948, 484, 829, +273, 259, -145, -422, -470, -898, -513, -933, +-285, -454, 61, 269, 337, 851, 463, 995, +380, 562, 89, -165, -243, -746, -451, -961, +-460, -664, -253, 41, 63, 694, 347, 958, +503, 693, 427, -7, 118, -639, -295, -843, +-592, -646, -548, -101, -202, 548, 184, 863, +465, 678, 538, 93, 300, -539, -90, -767, +-378, -584, -461, -185, -327, 366, -59, 766, +193, 693, 319, 255, 300, -311, 185, -732, +7, -736, -211, -372, -339, 135, -271, 623, +-85, 852, 108, 618, 251, 16, 281, -614, +175, -911, -36, -738, -254, -213, -314, 449, +-180, 937, 16, 939, 175, 416, 247, -355, +190, -935, 24, -991, -164, -530, -257, 196, +-192, 831, -31, 1006, 125, 612, 201, -91, +162, -707, 46, -916, -77, -627, -156, -31, +-139, 539, -55, 779, 15, 587, 53, 130, +58, -332, 35, -597, 36, -559, 60, -270, +49, 125, -29, 443, -126, 527, -160, 373, +-115, 82, -22, -261, 104, -516, 212, -534, +210, -292, 67, 126, -128, 521, -216, 654, +-166, 442, -92, 0, -3, -471, 100, -740, +145, -627, 144, -146, 108, 434, 11, 773, +-77, 707, -155, 280, -236, -310, -193, -752, +8, -793, 245, -412, 373, 196, 254, 690, +-36, 793, -279, 484, -418, -57, -370, -567, +-43, -755, 356, -514, 543, -13, 414, 461, +7, 650, -424, 482, -607, 95, -488, -315, +-96, -554, 421, -472, 744, -135, 649, 229, +152, 446, -481, 431, -840, 191, -735, -121, +-270, -366, 369, -447, 892, -281, 937, 57, +421, 345, -348, 444, -922, 323, -996, 41, +-548, -274, 192, -479, 861, -432, 1091, -114, +705, 262, -112, 473, -858, 446, -1090, 197, +-734, -148, -12, -415, 711, -491, 1045, -296, +808, 75, 127, 357, -618, 428, -970, 325, +-777, 72, -243, -223, 385, -409, 835, -392, +844, -156, 403, 149, -247, 322, -742, 344, +-809, 241, -505, 23, 4, -224, 568, -388, +864, -349, 656, -93, 91, 171, -501, 313, +-788, 373, -652, 274, -237, -24, 299, -346, +714, -497, 702, -360, 295, -5, -212, 301, +-563, 450, -603, 452, -367, 207, -7, -222, +362, -540, 572, -555, 487, -261, 148, 164, +-264, 458, -509, 538, -495, 415, -313, 54, +22, -416, 435, -666, 637, -505, 471, -85, +54, 313, -388, 549, -608, 554, -536, 277, +-247, -175, 193, -540, 595, -587, 677, -302, +379, 96, -124, 391, -550, 487, -672, 355, +-482, 88, -83, -191, 402, -403, 702, -405, +595, -192, 157, 33, -332, 207, -600, 352, +-549, 364, -276, 217, 105, -52, 458, -362, +586, -490, 397, -364, 8, -91, -362, 276, +-534, 554, -459, 522, -172, 234, 240, -193, +565, -592, 576, -657, 233, -345, -259, 135, +-585, 562, -580, 688, -268, 441, 220, -8, +614, -489, 645, -742, 289, -545, -255, -56, +-639, 417, -625, 671, -307, 575, 152, 196, +597, -257, 717, -592, 397, -622, -139, -317, +-602, 130, -730, 495, -450, 593, 38, 399, +519, 46, 772, -341, 581, -581, 30, -503, +-531, -181, -766, 215, -546, 518, -75, 542, +367, 302, 651, -53, 616, -407, 189, -559, +-345, -404, -622, -74, -540, 282, -212, 509, +175, 474, 473, 228, 568, -112, 349, -406, +-100, -504, -490, -380, -601, -91, -383, 264, +67, 496, 483, 495, 628, 268, 442, -108, +-9, -440, -512, -563, -726, -433, -487, -61, +33, 373, 503, 601, 682, 527, 510, 185, +70, -255, -424, -559, -684, -605, -563, -333, +-157, 150, 310, 529, 609, 613, 603, 381, +307, -72, -147, -449, -537, -568, -652, -448, +-425, -64, 24, 403, 452, 589, 633, 436, +484, 85, 87, -301, -358, -508, -612, -470, +-520, -209, -145, 233, 275, 556, 520, 516, +488, 214, 202, -190, -185, -511, -462, -546, +-476, -311, -219, 114, 138, 556, 369, 666, +385, 350, 213, -151, -40, -577, -253, -682, +-351, -402, -260, 90, -10, 588, 186, 809, +235, 506, 212, -133, 126, -672, -34, -826, +-192, -531, -266, 54, -191, 650, -19, 938, +120, 688, 190, 4, 203, -699, 125, -1017, +-25, -779, -165, -129, -221, 609, -155, 1083, +-6, 976, 105, 298, 128, -544, 125, -1117, +120, -1116, 25, -506, -135, 375, -200, 1085, +-133, 1271, -26, 767, 64, -163, 140, -1021, +204, -1389, 158, -1027, -51, -107, -249, 875, +-264, 1467, -136, 1316, 57, 402, 237, -742, +292, -1481, 187, -1467, -50, -695, -310, 466, +-364, 1434, -165, 1660, 105, 945, 303, -276, +342, -1306, 179, -1667, -82, -1160, -310, -23, +-376, 1118, -185, 1690, 99, 1353, 270, 248, +329, -951, 238, -1608, -25, -1442, -277, -497, +-359, 699, -250, 1495, -2, 1533, 220, 734, +334, -496, 328, -1398, 123, -1519, -209, -865, +-426, 219, -394, 1146, -129, 1477, 202, 1056, +400, 46, 417, -945, 228, -1362, -137, -1121, +-449, -350, -491, 601, -238, 1205, 150, 1208, +398, 642, 408, -267, 270, -1032, 1, -1250, +-323, -859, -482, -45, -354, 791, -18, 1215, +290, 1042, 405, 338, 355, -562, 155, -1158, +-172, -1140, -426, -543, -438, 318, -210, 1005, +136, 1171, 379, 712, 397, -119, 245, -852, +-9, -1120, -268, -793, -398, -44, -346, 686, +-110, 1010, 206, 789, 383, 146, 357, -546, +199, -895, -65, -734, -326, -176, -415, 435, +-288, 755, -5, 652, 278, 189, 365, -362, +252, -662, 53, -573, -134, -172, -235, 303, +-223, 557, -118, 496, 28, 191, 106, -229, +111, -522, 124, -500, 127, -211, 77, 180, +-18, 454, -155, 461, -247, 257, -200, -68, +-43, -391, 142, -485, 275, -309, 298, -15, +174, 280, -103, 434, -363, 360, -397, 149, +-217, -126, 68, -384, 350, -455, 472, -296, +354, -4, 8, 310, -421, 484, -615, 427, +-420, 165, 4, -243, 446, -562, 683, -544, +529, -245, 47, 171, -505, 540, -804, 623, +-601, 348, -17, -119, 561, -558, 829, -679, +640, -387, 55, 67, -570, 465, -863, 668, +-665, 484, -74, 1, 570, -441, 865, -647, +664, -517, 104, -92, -498, 339, -825, 569, +-704, 547, -176, 229, 462, -236, 798, -544, +674, -559, 240, -297, -298, 96, -716, 390, +-746, 502, -345, 412, 223, 95, 648, -286, +744, -492, 467, -458, -50, -236, -559, 71, +-812, 361, -636, 534, -63, 443, 555, 87, +847, -306, 699, -552, 197, -560, -443, -289, +-882, 160, -839, 559, -293, 685, 432, 434, +872, -64, 815, -541, 372, -756, -237, -579, +-736, -82, -859, 482, -516, 808, 106, 676, +640, 157, 801, -440, 573, -810, 111, -745, +-392, -266, -725, 352, -703, 803, -307, 811, +243, 317, 628, -331, 682, -754, 432, -795, +15, -425, -413, 183, -669, 703, -580, 850, +-175, 492, 283, -141, 567, -631, 579, -795, +328, -585, -64, -55, -419, 507, -570, 803, +-415, 679, -51, 164, 304, -430, 488, -770, +422, -728, 155, -316, -141, 254, -344, 694, +-395, 809, -262, 468, 3, -152, 246, -627, +352, -774, 300, -575, 143, -62, -76, 474, +-298, 752, -401, 668, -295, 219, -17, -325, +294, -661, 471, -707, 414, -408, 140, 121, +-230, 542, -517, 688, -541, 510, -245, 46, +227, -412, 580, -646, 605, -591, 324, -216, +-108, 254, -510, 549, -658, 589, -444, 316, +19, -123, 473, -434, 668, -553, 506, -430, +106, -36, -337, 345, -609, 498, -550, 429, +-208, 152, 228, -187, 537, -430, 531, -510, +263, -326, -67, 52, -343, 378, -459, 527, +-325, 435, -39, 110, 229, -284, 349, -586, +288, -615, 134, -285, -35, 204, -194, 595, +-245, 707, -158, 425, -17, -101, 92, -588, +132, -821, 126, -617, 123, -44, 79, 549, +-18, 854, -95, 699, -118, 161, -116, -444, +-92, -831, -8, -808, 151, -334, 255, 310, +184, 764, 4, 814, -150, 430, -217, -156, +-188, -641, -67, -824, 127, -563, 279, 10, +248, 527, 63, 746, -121, 578, -221, 108, +-208, -382, -109, -667, 43, -619, 228, -236, +317, 235, 195, 546, -10, 574, -176, 286, +-285, -126, -273, -412, -98, -525, 160, -406, +386, -54, 409, 304, 177, 478, -141, 411, +-371, 144, -422, -149, -242, -381, 87, -496, +394, -347, 498, -3, 315, 304, -35, 473, +-323, 433, -431, 174, -313, -157, -32, -458, +252, -591, 408, -411, 360, -4, 111, 409, +-168, 648, -311, 570, -290, 208, -145, -274, +67, -707, 249, -830, 300, -475, 191, 165, +26, 716, -108, 913, -184, 672, -182, 64, +-110, -663, -1, -1096, 144, -938, 239, -265, +222, 563, 120, 1109, -34, 1084, -190, 504, +-251, -370, -202, -1111, -41, -1282, 184, -765, +316, 153, 279, 992, 145, 1316, -41, 964, +-221, 127, -308, -796, -259, -1343, -81, -1197, +183, -426, 384, 548, 403, 1231, 232, 1293, +-48, 718, -336, -235, -493, -1115, -378, -1440, +6, -998, 422, -46, 611, 902, 472, 1389, +83, 1179, -352, 339, -589, -703, -512, -1377, +-138, -1322, 358, -576, 670, 452, 569, 1211, +145, 1332, -297, 770, -532, -190, -505, -1040, +-211, -1335, 242, -947, 570, -95, 552, 763, +237, 1189, -171, 1021, -432, 377, -436, -457, +-232, -1069, 86, -1135, 390, -647, 481, 121, +299, 800, -18, 1090, -273, 868, -344, 221, +-231, -558, -34, -1072, 176, -1064, 318, -563, +306, 210, 136, 903, -75, 1170, -204, 866, +-211, 119, -136, -737, -8, -1273, 140, -1172, +247, -464, 242, 491, 124, 1224, -32, 1349, +-139, 762, -190, -259, -183, -1183, -74, -1500, +127, -1009, 290, 8, 306, 1007, 181, 1487, +-11, 1175, -224, 208, -350, -874, -258, -1479, +29, -1285, 331, -413, 460, 638, 333, 1323, +40, 1300, -274, 560, -460, -464, -365, -1196, +16, -1291, 413, -713, 554, 220, 379, 971, +4, 1189, -366, 801, -519, -12, -360, -794, +53, -1123, 476, -885, 622, -218, 394, 526, +-41, 957, -420, 904, -538, 401, -363, -321, +22, -866, 439, -947, 648, -552, 487, 93, +66, 664, -355, 892, -557, 657, -467, 54, +-138, -580, 293, -879, 621, -707, 634, -192, +308, 393, -162, 750, -508, 697, -577, 261, +-357, -309, 49, -693, 460, -692, 668, -326, +556, 184, 159, 550, -303, 604, -581, 341, +-557, -106, -266, -499, 196, -605, 603, -376, +719, 36, 472, 382, -10, 498, -480, 352, +-665, 14, -489, -339, -61, -487, 404, -362, +678, -59, 620, 239, 279, 375, -184, 303, +-525, 78, -576, -183, -347, -325, 44, -299, +444, -150, 660, 57, 586, 204, 246, 206, +-211, 129, -573, 24, -640, -113, -358, -211, +136, -212, 569, -138, 751, -14, 609, 112, +159, 191, -392, 195, -701, 87, -620, -98, +-238, -241, 243, -270, 635, -178, 771, -1, +565, 181, 74, 269, -442, 209, -720, 25, +-642, -183, -253, -300, 296, -263, 752, -97, +880, 106, 556, 241, -62, 257, -621, 134, +-831, -75, -612, -249, -57, -290, 543, -193, +868, -22, 756, 155, 289, 276, -286, 249, +-668, 61, -681, -171, -337, -316, 164, -315, +580, -170, 723, 64, 536, 287, 106, 367, +-346, 230, -603, -45, -528, -298, -167, -416, +293, -343, 612, -102, 637, 199, 356, 408, +-66, 405, -422, 174, -538, -159, -351, -423, +39, -503, 410, -358, 585, -35, 483, 325, +192, 536, -139, 466, -397, 146, -478, -257, +-285, -557, 92, -629, 439, -404, 574, 63, +467, 534, 185, 721, -184, 528, -500, 72, +-539, -447, -238, -799, 228, -778, 577, -344, +631, 308, 394, 813, 14, 878, -365, 480, +-546, -165, -385, -763, 21, -1011, 394, -735, +538, -54, 421, 658, 158, 1010, -118, 812, +-301, 193, -305, -519, -116, -992, 132, -985, +296, -455, 315, 322, 222, 907, 83, 990, +-50, 560, -153, -144, -156, -788, -47, -1066, +106, -795, 218, -81, 252, 655, 182, 1010, +42, 844, -106, 245, -159, -499, -86, -1010, +77, -1005, 228, -458, 273, 347, 170, 934, +-6, 987, -139, 523, -143, -213, -31, -861, +125, -1056, 229, -666, 224, 96, 114, 781, +-15, 986, -100, 625, -97, -42, -6, -670, +107, -955, 165, -713, 175, -61, 139, 594, +58, 857, -31, 607, -75, 40, -60, -508, +37, -779, 163, -655, 233, -164, 195, 415, +69, 716, -79, 573, -152, 115, -97, -389, +87, -672, 278, -603, 326, -217, 182, 297, +-43, 643, -216, 586, -217, 171, -42, -347, +218, -661, 394, -606, 362, -231, 132, 257, +-138, 618, -299, 620, -260, 226, -28, -306, +269, -639, 430, -618, 383, -291, 168, 166, +-92, 534, -283, 608, -300, 324, -111, -144, +198, -506, 412, -603, 415, -413, 239, -33, +-5, 344, -222, 532, -302, 452, -177, 131, +106, -267, 356, -528, 419, -537, 290, -307, +60, 60, -173, 403, -279, 559, -197, 422, +47, 39, 313, -382, 437, -611, 323, -559, +57, -255, -190, 191, -275, 578, -179, 671, +54, 385, 311, -127, 440, -580, 322, -765, +36, -590, -205, -114, -252, 449, -141, 798, +51, 728, 267, 258, 403, -371, 333, -829, +106, -882, -130, -516, -243, 104, -198, 699, +-27, 967, 194, 720, 390, 68, 431, -631, +249, -1013, -67, -921, -300, -395, -314, 347, +-127, 953, 150, 1063, 417, 597, 522, -177, +360, -858, 1, -1132, -311, -862, -398, -165, +-233, 634, 72, 1114, 382, 1001, 559, 353, +493, -477, 173, -1064, -225, -1118, -453, -626, +-374, 169, -73, 882, 290, 1133, 562, 756, +604, -27, 333, -771, -106, -1108, -428, -899, +-439, -251, -188, 524, 174, 1029, 470, 958, +560, 349, 388, -427, 68, -958, -225, -1017, +-341, -573, -234, 176, 10, 843, 225, 1043, +363, 657, 406, -100, 304, -804, 71, -1091, +-147, -818, -249, -119, -208, 654, -54, 1072, +179, 885, 397, 186, 476, -623, 326, -1078, +27, -945, -244, -341, -334, 422, -229, 956, +24, 952, 332, 387, 544, -391, 485, -916, +183, -926, -161, -472, -353, 198, -326, 736, +-97, 845, 220, 471, 471, -160, 503, -687, +303, -810, -1, -503, -218, 37, -266, 525, +-170, 704, 12, 476, 232, -23, 382, -518, +383, -725, 254, -523, 79, -56, -99, 407, +-224, 644, -238, 514, -84, 75, 182, -427, +412, -706, 486, -602, 378, -178, 98, 314, +-213, 632, -381, 620, -317, 261, -48, -273, +325, -673, 579, -725, 556, -414, 283, 88, +-76, 537, -360, 719, -429, 531, -233, 47, +155, -479, 504, -774, 606, -691, 425, -279, +92, 263, -235, 673, -397, 747, -314, 435, +-12, -122, 341, -652, 541, -857, 480, -626, +238, -100, -55, 454, -277, 787, -332, 714, +-167, 257, 129, -358, 406, -803, 522, -824, +416, -432, 124, 134, -180, 622, -342, 796, +-288, 539, -45, -6, 291, -549, 522, -827, +503, -679, 246, -196, -69, 351, -268, 706, +-279, 700, -139, 323, 110, -228, 357, -687, +460, -801, 359, -489, 145, 49, -76, 518, +-218, 724, -233, 558, -95, 90, 151, -443, +388, -750, 465, -660, 327, -247, 54, 237, +-179, 572, -262, 610, -162, 333, 65, -102, +311, -477, 432, -610, 352, -441, 110, -101, +-111, 228, -191, 418, -134, 411, 12, 230, +220, -50, 368, -317, 352, -428, 179, -367, +-33, -203, -176, 28, -181, 275, -44, 413, +192, 362, 378, 127, 386, -189, 215, -441, +-24, -525, -205, -392, -208, -44, -44, 351, +195, 575, 375, 499, 382, 154, 207, -293, +-6, -618, -143, -661, -154, -372, -42, 120, +138, 549, 276, 667, 318, 408, 242, -71, +85, -497, -65, -679, -113, -532, -61, -106, +51, 372, 172, 620, 273, 513, 281, 130, +162, -304, -4, -583, -85, -592, -62, -309, +20, 144, 122, 506, 233, 581, 284, 336, +214, -95, 61, -486, -56, -650, -90, -501, +-36, -84, 69, 386, 194, 647, 281, 552, +279, 138, 165, -368, 12, -685, -101, -667, +-111, -313, -34, 215, 89, 626, 213, 681, +306, 359, 309, -159, 213, -579, 39, -705, +-132, -497, -210, -49, -145, 409, 31, 626, +274, 512, 464, 138, 478, -298, 272, -583, +-57, -593, -330, -339, -357, 68, -149, 427, +158, 563, 432, 410, 572, 41, 473, -364, +166, -601, -186, -562, -375, -247, -337, 197, +-120, 541, 191, 598, 503, 329, 641, -141, +498, -560, 111, -713, -309, -501, -525, -19, +-410, 479, -36, 722, 429, 579, 741, 95, +706, -479, 306, -822, -226, -737, -575, -272, +-531, 346, -152, 792, 333, 819, 674, 388, +713, -295, 423, -858, -36, -971, -420, -576, +-510, 113, -282, 745, 115, 985, 471, 685, +640, 3, 534, -707, 211, -1057, -172, -840, +-408, -196, -381, 509, -116, 926, 232, 853, +509, 322, 568, -391, 392, -902, 83, -933, +-204, -468, -356, 198, -281, 705, -28, 834, +260, 533, 456, -67, 494, -641, 334, -863, +61, -618, -183, -64, -291, 475, -241, 723, +-34, 582, 244, 121, 452, -420, 472, -739, +325, -645, 81, -205, -162, 314, -313, 622, +-285, 581, -63, 220, 266, -274, 507, -633, +536, -652, 347, -323, 44, 169, -258, 537, +-408, 600, -302, 342, 30, -105, 388, -528, +586, -691, 528, -482, 256, -11, -97, 440, +-345, 640, -393, 501, -209, 81, 143, -423, +493, -725, 627, -633, 476, -191, 124, 333, +-231, 654, -439, 613, -399, 231, -89, -300, +361, -672, 657, -679, 615, -321, 285, 192, +-121, 558, -399, 593, -424, 317, -196, -118, +195, -491, 530, -623, 610, -447, 396, -50, +49, 342, -236, 511, -334, 436, -252, 174, +-23, -190, 272, -505, 490, -599, 488, -411, +280, -16, -6, 377, -223, 595, -293, 553, +-199, 219, 29, -287, 318, -694, 490, -789, +431, -493, 194, 84, -59, 638, -229, 878, +-256, 676, -130, 90, 108, -601, 342, -1030, +448, -948, 359, -359, 153, 440, -66, 1002, +-216, 1049, -242, 551, -103, -274, 134, -998, +355, -1215, 433, -813, 336, 13, 125, 823, +-81, 1193, -211, 946, -212, 203, -78, -672, +137, -1209, 321, -1137, 395, -498, 339, 393, +186, 1075, -37, 1188, -237, 684, -300, -180, +-155, -972, 126, -1293, 407, -950, 539, -110, +445, 783, 139, 1254, -226, 1058, -439, 297, +-368, -633, -48, -1261, 358, -1233, 612, -539, +583, 434, 294, 1145, -111, 1232, -428, 649, +-469, -286, -218, -1074, 192, -1296, 544, -825, +662, 79, 482, 900, 95, 1212, -321, 866, +-544, 55, -447, -767, -56, -1174, 436, -986, +759, -283, 715, 544, 340, 1029, -189, 953, +-615, 389, -683, -370, -309, -920, 296, -1003, +796, -583, 903, 137, 557, 746, -48, 920, +-578, 621, -776, 3, -517, -619, 90, -912, +711, -730, 955, -184, 717, 437, 167, 778, +-414, 681, -755, 233, -661, -321, -163, -690, +482, -682, 897, -336, 854, 147, 406, 504, +-186, 552, -641, 301, -719, -73, -388, -379, +191, -474, 724, -342, 906, -72, 615, 193, +65, 323, -442, 266, -675, 93, -543, -101, +-99, -242, 449, -277, 818, -187, 766, -30, +348, 115, -168, 185, -533, 158, -622, 55, +-378, -64, 109, -162, 612, -198, 834, -153, +629, -48, 151, 58, -319, 129, -606, 139, +-580, 90, -209, -2, 330, -126, 730, -228, +778, -226, 453, -114, -38, 50, -447, 194, +-589, 255, -422, 183, -13, -13, 451, -258, +729, -398, 642, -327, 273, -76, -151, 216, +-444, 398, -505, 369, -284, 131, 122, -225, +509, -501, 648, -509, 481, -235, 142, 153, +-183, 452, -391, 503, -400, 288, -177, -92, +185, -463, 480, -608, 550, -418, 390, -12, +108, 377, -200, 554, -397, 448, -363, 108, +-88, -317, 276, -607, 524, -574, 520, -240, +292, 199, -31, 516, -294, 562, -385, 322, +-245, -97, 76, -498, 396, -653, 506, -460, +386, -39, 147, 374, -106, 577, -302, 491, +-323, 157, -131, -285, 179, -603, 410, -604, +451, -288, 313, 151, 71, 489, -190, 575, +-333, 376, -260, -39, 9, -470, 304, -659, +448, -487, 371, -70, 152, 359, -94, 580, +-248, 493, -230, 143, -42, -309, 192, -623, +332, -584, 301, -220, 153, 237, -7, 530, +-96, 519, -104, 224, -31, -195, 87, -536, +174, -594, 180, -301, 139, 160, 77, 493, +20, 531, -18, 279, -27, -121, -4, -480, +65, -608, 141, -402, 180, 44, 156, 453, +79, 594, -28, 412, -97, 15, -78, -411, +39, -658, 181, -586, 267, -194, 237, 318, +106, 658, -64, 634, -172, 282, -163, -225, +-23, -652, 170, -780, 311, -504, 328, 50, +217, 594, 6, 814, -191, 600, -278, 80, +-205, -496, 32, -863, 316, -798, 465, -304, +412, 357, 167, 826, -166, 853, -400, 432, +-384, -214, -123, -777, 267, -965, 544, -654, +547, 15, 287, 667, -86, 946, -376, 718, +-426, 124, -235, -537, 115, -938, 449, -865, +563, -339, 400, 354, 82, 830, -240, 843, +-411, 434, -345, -170, -69, -691, 289, -876, +544, -619, 521, -66, 239, 492, -131, 774, +-384, 664, -407, 242, -187, -288, 167, -696, +476, -774, 548, -477, 350, 46, 0, 529, +-304, 736, -405, 579, -266, 149, 13, -361, +323, -717, 511, -733, 449, -385, 168, 138, +-152, 573, -347, 717, -333, 524, -137, 74, +151, -438, 390, -755, 452, -708, 300, -324, +40, 217, -191, 656, -291, 784, -233, 523, +-46, -32, 167, -609, 316, -893, 348, -738, +258, -199, 69, 466, -129, 900, -253, 857, +-251, 355, -103, -367, 141, -922, 339, -997, +407, -550, 314, 183, 75, 817, -205, 1007, +-353, 658, -294, -41, -52, -723, 234, -1030, +425, -798, 438, -172, 266, 513, -33, 914, +-302, 847, -401, 351, -253, -319, 58, -826, +338, -919, 458, -559, 407, 70, 174, 642, +-148, 889, -368, 692, -353, 138, -135, -498, +153, -888, 364, -844, 439, -370, 340, 297, +94, 799, -183, 885, -349, 529, -318, -112, +-96, -718, 181, -972, 398, -729, 479, -113, +353, 554, 43, 931, -280, 841, -442, 310, +-335, -401, -13, -924, 334, -981, 531, -536, +501, 184, 227, 794, -158, 1001, -431, 691, +-438, 13, -186, -670, 185, -1015, 460, -858, +518, -255, 348, 465, 29, 921, -280, 905, +-401, 434, -289, -264, -16, -826, 273, -981, +429, -646, 385, 16, 204, 642, -27, 924, +-223, 756, -292, 192, -199, -484, -15, -905, +187, -878, 332, -416, 354, 256, 242, 774, +48, 886, -171, 548, -302, -81, -269, -668, +-79, -906, 164, -696, 348, -136, 387, 480, +279, 827, 53, 744, -194, 286, -330, -321, +-294, -756, -123, -805, 134, -453, 369, 120, +455, 614, 342, 771, 77, 534, -237, 22, +-436, -500, -404, -751, -138, -612, 238, -178, +531, 327, 567, 643, 320, 610, -87, 261, +-434, -206, -543, -550, -346, -602, 48, -352, +448, 57, 643, 409, 521, 522, 135, 355, +-297, 23, -557, -303, -516, -467, -184, -392, +287, -122, 643, 181, 678, 366, 349, 350, +-145, 153, -511, -117, -575, -323, -327, -376, +118, -227, 528, 39, 671, 259, 461, 334, +34, 246, -356, 13, -508, -233, -386, -350, +-56, -299, 320, -95, 552, 170, 502, 316, +199, 282, -166, 122, -378, -100, -358, -279, +-144, -314, 149, -207, 375, -5, 415, 193, +247, 273, -34, 225, -230, 104, -241, -89, +-111, -272, 64, -319, 204, -215, 249, -20, +195, 199, 45, 323, -99, 293, -123, 119, +-48, -159, 41, -400, 117, -423, 142, -224, +108, 92, 34, 387, -63, 490, -98, 328, +-12, -22, 103, -411, 146, -616, 116, -474, +41, -60, -47, 384, -98, 641, -78, 564, +24, 166, 137, -355, 168, -710, 104, -688, +18, -281, -51, 286, -83, 690, -77, 722, +-30, 380, 45, -185, 130, -681, 172, -809, +138, -496, 50, 75, -51, 609, -152, 812, +-178, 568, -63, 19, 123, -554, 263, -853, +283, -692, 155, -148, -55, 471, -230, 835, +-272, 751, -150, 261, 91, -368, 300, -814, +363, -844, 242, -429, 11, 212, -200, 720, +-293, 848, -232, 555, -23, -15, 232, -588, +381, -865, 345, -715, 150, -217, -101, 387, +-285, 791, -317, 796, -161, 425, 120, -161, +360, -691, 420, -874, 273, -622, 11, -83, +-214, 498, -315, 829, -245, 738, -12, 297, +251, -288, 372, -751, 322, -836, 136, -506, +-84, 53, -215, 573, -212, 806, -100, 640, +81, 164, 218, -403, 237, -770, 164, -748, +47, -351, -50, 218, -84, 666, -86, 768, +-51, 489, 27, -50, 91, -579, 119, -803, +134, -609, 106, -108, 42, 456, -35, 775, +-102, 686, -122, 250, -42, -335, 84, -765, +169, -781, 164, -400, 96, 180, -8, 668, +-107, 801, -125, 525, -53, -1, 48, -537, +118, -807, 121, -666, 59, -216, 3, 320, +-23, 691, -45, 716, -40, 416, 3, -58, +49, -513, 65, -738, 50, -615, 14, -218, +-13, 262, -26, 618, -9, 703, 40, 474, +83, 20, 59, -457, -7, -735, -72, -680, +-80, -304, 4, 211, 123, 638, 166, 792, +105, 570, -4, 38, -112, -533, -162, -863, +-81, -778, 98, -290, 232, 360, 226, 837, +101, 908, -65, 499, -170, -199, -171, -805, +-64, -991, 107, -656, 247, 26, 253, 681, +139, 982, -32, 772, -163, 141, -181, -567, +-97, -955, 47, -837, 209, -292, 289, 383, +207, 840, 26, 855, -122, 422, -168, -226, +-127, -727, -25, -830, 115, -502, 221, 57, +225, 544, 126, 733, 3, 553, -94, 93, +-140, -381, -122, -626, -19, -547, 116, -206, +204, 191, 207, 441, 121, 484, -32, 316, +-132, -9, -124, -304, -72, -417, 12, -360, +127, -162, 184, 96, 134, 293, 38, 372, +-46, 296, -88, 63, -89, -187, -62, -338, +15, -362, 110, -235, 139, 11, 89, 253, +20, 396, -49, 353, -85, 116, -75, -169, +-35, -368, 23, -425, 102, -283, 119, 14, +54, 308, -6, 457, -39, 380, -80, 99, +-98, -217, -48, -426, 41, -462, 119, -269, +132, 89, 76, 403, 5, 503, -73, 351, +-145, 22, -137, -325, -26, -514, 100, -456, +185, -159, 182, 240, 96, 507, -25, 480, +-129, 210, -193, -145, -156, -420, -13, -487, +152, -299, 244, 40, 229, 342, 130, 440, +-18, 297, -166, 27, -249, -214, -180, -348, +15, -336, 203, -165, 287, 89, 269, 283, +156, 319, -45, 212, -225, 43, -276, -140, +-166, -286, 42, -316, 239, -183, 309, 44, +270, 229, 144, 292, -63, 250, -243, 121, +-257, -79, -128, -274, 57, -355, 222, -267, +294, -40, 264, 188, 122, 326, -94, 356, +-245, 224, -221, -63, -87, -334, 74, -428, +210, -304, 258, -26, 194, 238, 37, 364, +-126, 341, -195, 144, -130, -148, -21, -326, +73, -296, 142, -142, 164, 39, 98, 163, +-2, 189, -75, 142, -109, 59, -95, -41, +-47, -94, 17, -85, 94, -78, 159, -97, +127, -81, 3, 6, -133, 117, -194, 183, +-132, 175, 3, 91, 132, -55, 205, -224, +148, -315, -49, -235, -205, 0, -204, 252, +-79, 388, 76, 347, 167, 129, 139, -207, +46, -488, -64, -525, -140, -262, -115, 171, +-25, 539, 50, 635, 75, 402, 59, -62, +30, -543, 16, -761, -17, -549, -62, -28, +-64, 512, -23, 783, 30, 638, 73, 167, +89, -384, 64, -760, -2, -742, -81, -310, +-79, 260, -3, 662, 75, 737, 110, 440, +97, -68, 26, -522, -46, -729, -63, -561, +-29, -78, 26, 395, 76, 624, 109, 561, +98, 228, 49, -221, -2, -526, -36, -559, +-69, -315, -64, 82, 25, 392, 136, 466, +185, 338, 144, 73, 48, -222, -82, -406, +-166, -389, -133, -185, 11, 94, 155, 299, +209, 367, 149, 292, 29, 89, -78, -186, +-118, -393, -74, -400, -5, -208, 51, 67, +85, 310, 89, 424, 66, 350, 48, 109, +4, -204, -82, -441, -136, -453, -117, -247, +-14, 53, 121, 337, 188, 498, 137, 434, +22, 172, -136, -202, -236, -522, -184, -580, +-36, -354, 109, 14, 211, 415, 202, 663, +82, 569, -65, 173, -216, -328, -282, -700, +-191, -708, -7, -345, 184, 172, 302, 619, +232, 781, 26, 528, -172, 5, -308, -523, +-300, -798, -128, -659, 84, -187, 217, 354, +257, 732, 195, 760, 69, 400, -96, -171, +-266, -662, -345, -823, -265, -560, -35, -25, +255, 514, 454, 818, 420, 720, 151, 239, +-239, -363, -522, -777, -512, -805, -202, -427, +220, 166, 516, 667, 534, 841, 285, 597, +-78, 33, -377, -548, -465, -833, -335, -695, +-53, -214, 256, 369, 464, 763, 467, 765, +271, 375, -66, -209, -399, -665, -526, -758, +-358, -478, 27, 9, 426, 483, 614, 718, +453, 590, 57, 169, -340, -315, -527, -614, +-409, -618, -61, -366, 296, 56, 466, 481, +401, 676, 155, 539, -126, 145, -327, -326, +-365, -632, -230, -642, 23, -373, 247, 98, +365, 571, 336, 746, 127, 534, -175, 62, +-386, -434, -396, -699, -211, -633, 93, -294, +342, 223, 415, 657, 273, 716, -10, 412, +-296, -54, -437, -478, -375, -659, -147, -536, +154, -185, 385, 285, 447, 614, 279, 576, +-65, 276, -433, -97, -605, -413, -463, -521, +-61, -387, 381, -105, 629, 244, 529, 461, +104, 390, -399, 162, -690, -66, -613, -269, +-224, -358, 271, -272, 597, -64, 594, 171, +277, 305, -167, 256, -523, 110, -640, -42, +-434, -191, 0, -275, 423, -209, 616, -24, +511, 162, 138, 244, -329, 205, -657, 90, +-629, -56, -242, -195, 272, -257, 638, -183, +674, -6, 336, 151, -199, 224, -599, 221, +-668, 132, -361, -36, 155, -204, 566, -296, +651, -246, 401, -61, -49, 142, -438, 268, +-559, 310, -403, 208, -27, -33, 372, -251, +539, -334, 415, -270, 128, -66, -214, 152, +-429, 278, -403, 313, -180, 202, 134, -48, +373, -241, 397, -286, 240, -238, 10, -80, +-228, 136, -344, 268, -291, 283, -111, 158, +121, -82, 307, -252, 333, -259, 202, -174, +0, -10, -217, 185, -361, 273, -334, 208, +-107, 34, 171, -166, 344, -248, 337, -189, +162, -76, -122, 71, -358, 215, -402, 235, +-224, 119, 63, -49, 268, -182, 299, -203, +166, -127, -49, -27, -236, 86, -291, 177, +-216, 175, -67, 89, 90, -15, 169, -91, +144, -128, 68, -154, -23, -149, -153, -58, +-246, 106, -226, 245, -93, 273, 85, 170, +227, -25, 235, -254, 107, -404, -113, -342, +-333, -65, -366, 274, -167, 480, 115, 427, +317, 144, 334, -204, 126, -457, -147, -499, +-321, -276, -338, 105, -171, 427, 92, 516, +258, 343, 258, 12, 145, -307, -32, -467, +-155, -403, -207, -144, -198, 195, -94, 429, +76, 425, 179, 209, 211, -87, 186, -336, +65, -422, -108, -299, -238, -35, -247, 252, +-123, 422, 74, 366, 231, 128, 290, -163, +215, -389, 33, -430, -176, -244, -305, 65, +-264, 366, -83, 485, 132, 332, 295, 22, +326, -289, 183, -481, -46, -419, -287, -133, +-397, 201, -263, 445, 23, 471, 280, 243, +404, -81, 314, -359, 26, -494, -296, -358, +-477, -19, -376, 307, -37, 480, 292, 403, +421, 99, 329, -238, 39, -443, -293, -426, +-449, -156, -364, 201, -87, 414, 216, 385, +343, 149, 246, -138, 46, -311, -157, -331, +-291, -185, -305, 64, -181, 241, 18, 261, +168, 164, 200, 17, 138, -109, 33, -185, +-121, -204, -261, -127, -285, 25, -156, 150, +27, 205, 164, 177, 194, 69, 116, -66, +-32, -200, -186, -260, -249, -143, -195, 69, +-48, 226, 92, 264, 151, 148, 115, -62, +34, -225, -60, -282, -141, -177, -182, 102, +-134, 320, -15, 297, 88, 107, 122, -149, +108, -328, 61, -290, -68, -91, -186, 155, +-183, 354, -71, 324, 69, 58, 178, -203, +184, -320, 73, -268, -80, -64, -201, 143, +-208, 263, -85, 273, 102, 118, 226, -116, +208, -242, 62, -233, -93, -131, -195, 32, +-213, 178, -92, 241, 112, 195, 239, 25, +199, -172, 44, -253, -116, -201, -188, -70, +-166, 97, -55, 237, 84, 281, 141, 175, +101, -45, 26, -243, -43, -318, -69, -257, +-42, -64, -56, 196, -84, 389, -60, 390, +11, 151, 69, -194, 85, -415, 43, -418, +-32, -205, -117, 139, -179, 409, -120, 441, +13, 238, 94, -95, 91, -356, 32, -378, +-56, -214, -100, -2, -117, 209, -114, 308, +-63, 223, 6, 49, 48, -114, 54, -199, +29, -166, -33, -79, -104, 14, -187, 119, +-187, 159, -67, 76, 96, -41, 178, -107, +133, -98, -5, -15, -157, 64, -256, 85, +-251, 74, -103, 1, 74, -120, 169, -149, +160, -59, 71, 40, -45, 123, -126, 167, +-186, 129, -191, 52, -116, -64, -21, -217, +73, -270, 151, -169, 161, -2, 88, 187, +-42, 353, -193, 356, -262, 168, -210, -111, +-68, -381, 98, -475, 228, -305, 260, 0, +174, 309, -3, 508, -236, 461, -367, 172, +-301, -218, -96, -535, 167, -584, 379, -316, +408, 90, 193, 469, -150, 677, -412, 531, +-431, 79, -219, -410, 68, -712, 282, -668, +358, -271, 246, 253, 46, 665, -143, 788, +-285, 512, -300, -30, -202, -557, -61, -858, +122, -749, 308, -238, 324, 399, 159, 880, +-96, 975, -312, 570, -373, -157, -250, -832, +-55, -1123, 130, -856, 258, -143, 256, 649, +153, 1139, -14, 1079, -203, 470, -345, -364, +-368, -1024, -247, -1196, 37, -770, 342, 30, +462, 812, 288, 1226, -93, 1046, -446, 342, +-569, -531, -426, -1163, -76, -1234, 315, -672, +495, 210, 382, 976, 70, 1274, -261, 945, +-482, 177, -518, -649, -344, -1172, 8, -1129, +366, -552, 513, 266, 404, 964, 42, 1211, +-404, 867, -623, 141, -552, -636, -240, -1164, +228, -1134, 544, -547, 519, 263, 259, 972, +-125, 1243, -465, 904, -579, 173, -471, -609, +-185, -1138, 242, -1144, 540, -628, 537, 147, +312, 874, -94, 1238, -527, 1025, -697, 360, +-521, -468, -114, -1141, 374, -1318, 656, -852, +581, 48, 231, 952, -206, 1407, -564, 1191, +-676, 420, -468, -550, -41, -1285, 432, -1424, +679, -888, 546, 83, 138, 1010, -304, 1433, +-615, 1204, -605, 435, -266, -556, 154, -1271, +421, -1379, 462, -836, 255, 122, -37, 1001, +-243, 1353, -358, 1087, -350, 350, -170, -569, +75, -1204, 218, -1234, 276, -715, 196, 131, +-16, 910, -213, 1224, -315, 1000, -263, 354, +-49, -487, 150, -1092, 170, -1147, 86, -679, +-26, 79, -159, 791, -186, 1108, -90, 920, +-17, 335, 38, -394, 68, -921, -3, -1019, +-73, -683, -85, -67, -129, 579, -151, 985, +-78, 975, 24, 562, 115, -118, 140, -789, +6, -1118, -178, -940, -258, -344, -252, 422, +-159, 1037, 75, 1170, 249, 728, 223, -10, +53, -727, -166, -1119, -330, -975, -324, -395, +-199, 339, -30, 912, 197, 1047, 331, 719, +241, 107, 1, -559, -244, -990, -445, -937, +-461, -480, -187, 149, 193, 731, 438, 987, +453, 796, 166, 303, -261, -323, -542, -846, +-547, -979, -272, -666, 147, -81, 444, 572, +445, 994, 260, 957, -89, 500, -422, -209, +-480, -879, -357, -1134, -139, -825, 218, -111, +444, 665, 380, 1145, 169, 1064, -159, 456, +-470, -348, -497, -976, -276, -1103, 36, -662, +345, 28, 437, 628, 233, 925, -43, 778, +-242, 262, -339, -292, -274, -641, -132, -692, +-11, -418, 118, -6, 216, 326, 194, 533, +77, 499, -64, 222, -229, -52, -347, -243, +-276, -391, -72, -375, 123, -225, 237, -48, +222, 209, 81, 427, -78, 424, -225, 298, +-328, 53, -262, -313, -109, -542, 50, -491, +194, -232, 240, 183, 81, 538, -136, 567, +-255, 349, -287, 22, -171, -375, 48, -577, +102, -463, 41, -176, -13, 188, -99, 469, +-126, 501, -63, 328, -29, 53, -65, -246, +-70, -423, -91, -380, -75, -198, 15, 36, +19, 226, -86, 285, -132, 246, -117, 159, +-39, 34, 86, -92, 81, -190, -42, -256, +-151, -256, -214, -119, -196, 104, -48, 294, +95, 382, 106, 325, 41, 79, -41, -248, +-132, -445, -112, -444, -51, -267, -71, 74, +-88, 380, -44, 519, -26, 488, -35, 226, +-5, -189, 16, -507, -8, -610, -22, -474, +-45, -116, -98, 312, -124, 609, -104, 711, +-75, 509, 29, 15, 136, -485, 97, -800, +-5, -817, -152, -417, -287, 215, -240, 750, +-55, 994, 81, 811, 177, 193, 194, -510, +26, -939, -126, -976, -185, -601, -271, 71, +-201, 705, -11, 1011, 57, 888, 112, 381, +141, -303, 8, -817, -158, -989, -202, -768, +-206, -166, -117, 540, 39, 984, 132, 1017, +120, 605, 28, -120, -165, -795, -318, -1092, +-263, -953, -98, -358, 71, 465, 214, 1028, +220, 1143, 13, 805, -236, 33, -373, -759, +-374, -1152, -191, -1078, 100, -528, 265, 342, +289, 1024, 166, 1214, -121, 921, -379, 186, +-462, -651, -404, -1133, -173, -1162, 170, -717, +346, 105, 343, 882, 190, 1248, -148, 1126, +-447, 516, -495, -348, -362, -1028, -116, -1286, +178, -1034, 298, -293, 218, 599, 125, 1228, +-76, 1321, -299, 845, -370, -4, -357, -871, +-242, -1354, 29, -1247, 256, -579, 332, 411, +253, 1223, -45, 1484, -388, 1102, -463, 200, +-320, -853, -127, -1517, 111, -1507, 237, -837, +151, 317, 21, 1388, -36, 1756, -86, 1353, +-149, 329, -253, -936, -307, -1732, -211, -1682, +-2, -906, 204, 333, 303, 1442, 231, 1815, +-48, 1391, -310, 359, -385, -901, -327, -1690, +-206, -1703, -6, -1012, 171, 203, 247, 1370, +238, 1850, 138, 1510, -126, 520, -419, -732, +-545, -1619, -425, -1764, -97, -1188, 313, -30, +507, 1171, 381, 1781, 83, 1612, -334, 755, +-600, -466, -547, -1488, -324, -1842, -4, -1352, +323, -236, 473, 1015, 394, 1815, 126, 1769, +-298, 906, -663, -349, -708, -1463, -472, -1924, +11, -1477, 529, -364, 681, 898, 447, 1768, +-12, 1777, -531, 1001, -789, -125, -668, -1230, +-343, -1804, 102, -1473, 498, -518, 643, 609, +473, 1501, 65, 1662, -475, 1044, -898, 69, +-909, -997, -480, -1632, 155, -1373, 753, -538, +933, 469, 555, 1360, -156, 1580, -810, 993, +-1097, 9, -868, -987, -232, -1559, 434, -1287, +853, -391, 848, 635, 370, 1409, -323, 1487, +-850, 798, -1038, -236, -786, -1212, -156, -1624, +503, -1146, 875, -94, 837, 974, 341, 1643, +-382, 1508, -942, 566, -1078, -623, -739, -1500, +-96, -1712, 572, -1083, 920, 98, 844, 1232, +311, 1763, -407, 1490, -924, 554, -1089, -644, +-805, -1577, -132, -1801, 564, -1169, 989, 32, +917, 1210, 347, 1842, -414, 1607, -1008, 621, +-1200, -621, -821, -1543, -18, -1760, 698, -1184, +983, -49, 805, 1082, 225, 1644, -503, 1471, +-968, 673, -1004, -389, -615, -1229, 19, -1499, +571, -1090, 788, -193, 575, 701, 69, 1175, +-456, 1129, -763, 652, -718, -53, -349, -640, +152, -882, 445, -727, 398, -325, 144, 87, +-220, 381, -479, 506, -473, 428, -210, 236, +123, 63, 346, -45, 285, -127, -17, -192, +-382, -268, -592, -306, -511, -265, -213, -147, +173, 101, 543, 362, 574, 480, 206, 513, +-293, 376, -682, 18, -831, -345, -657, -566, +-150, -673, 419, -573, 721, -223, 602, 242, +204, 697, -288, 961, -713, 827, -845, 364, +-606, -272, -134, -842, 365, -1053, 620, -850, +499, -378, 119, 249, -363, 812, -678, 1057, +-641, 906, -351, 416, 56, -242, 432, -781, +480, -1027, 194, -841, -216, -254, -513, 428, +-595, 885, -428, 898, -95, 460, 291, -144, +518, -650, 375, -836, -20, -561, -394, 53, +-606, 655, -553, 941, -264, 712, 87, 46, +322, -661, 345, -1104, 138, -1086, -132, -438, +-312, 523, -385, 1284, -267, 1476, -82, 930, +33, -46, 77, -932, 5, -1511, -147, -1468, +-217, -631, -158, 464, -51, 1236, 72, 1490, +105, 1044, -58, 140, -220, -705, -261, -1213, +-226, -1100, -73, -357, 38, 462, 28, 941, +-52, 916, -145, 331, -197, -429, -139, -888, +-61, -964, 3, -497, 14, 422, -39, 1160, +-116, 1335, -144, 887, -141, -85, -176, -1029, +-170, -1552, -100, -1482, -19, -646, 64, 593, +41, 1499, -121, 1754, -268, 1259, -310, 123, +-221, -1049, -63, -1693, 118, -1613, 228, -723, +200, 574, 35, 1585, -175, 1864, -342, 1230, +-522, -80, -631, -1372, -500, -2052, -131, -1790, +344, -625, 746, 885, 770, 2035, 363, 2323, +-212, 1503, -734, 9, -1022, -1412, -924, -2261, +-521, -2168, 53, -1103, 523, 427, 773, 1794, +732, 2347, 302, 1763, -330, 402, -821, -1037, +-981, -1973, -745, -1947, -169, -971, 447, 388, +722, 1556, 620, 2026, 233, 1433, -344, 151, +-806, -1113, -925, -1865, -671, -1789, -166, -866, +377, 462, 750, 1583, 771, 1967, 350, 1427, +-299, 247, -831, -961, -981, -1633, -722, -1492, +-183, -700, 439, 346, 725, 1149, 551, 1328, +78, 845, -494, -29, -865, -859, -766, -1210, +-270, -952, 321, -218, 713, 714, 736, 1395, +262, 1373, -454, 691, -1034, -308, -1153, -1300, +-690, -1780, 79, -1402, 761, -420, 1099, 745, +869, 1643, 73, 1857, -778, 1276, -1246, 171, +-1240, -999, -713, -1728, 147, -1700, 863, -967, +1120, 181, 893, 1300, 281, 1793, -525, 1438, +-1199, 518, -1407, -599, -992, -1536, -226, -1791, +517, -1201, 1043, -115, 1067, 1027, 573, 1810, +-95, 1817, -700, 1060, -1108, -85, -1053, -1234, +-548, -1973, 58, -1858, 488, -936, 698, 324, +544, 1419, 78, 1874, -372, 1536, -628, 684, +-671, -391, -412, -1254, -32, -1503, 244, -1122, +391, -325, 394, 538, 156, 1044, -269, 1051, +-650, 653, -801, -20, -584, -676, -145, -918, +276, -728, 593, -253, 668, 372, 377, 877, +-131, 1015, -590, 707, -864, 43, -884, -651, +-555, -1129, -38, -1228, 456, -780, 816, 67, +832, 887, 387, 1423, -334, 1411, -928, 766, +-1180, -144, -979, -971, -389, -1469, 357, -1334, +924, -620, 1025, 312, 641, 1063, -27, 1293, +-768, 930, -1165, 254, -1027, -473, -562, -960, +40, -885, 635, -333, 891, 299, 631, 715, +65, 661, -507, 236, -882, -264, -883, -664, +-454, -695, 158, -259, 604, 305, 650, 757, +347, 900, -160, 511, -671, -195, -867, -764, +-650, -1009, -182, -790, 287, -154, 549, 574, +551, 1098, 271, 1141, -175, 564, -530, -245, +-710, -898, -678, -1244, -362, -1060, 157, -348, +519, 491, 602, 1178, 393, 1430, -146, 1023, +-749, 177, -965, -739, -731, -1383, -149, -1393, +556, -841, 907, 16, 721, 902, 233, 1382, +-444, 1219, -1045, 593, -1228, -217, -922, -875, +-202, -1113, 663, -899, 1234, -341, 1181, 368, +560, 831, -423, 861, -1342, 541, -1616, 12, +-1123, -441, -180, -599, 801, -532, 1322, -248, +1135, 133, 403, 364, -514, 426, -1214, 346, +-1400, 71, -944, -163, -62, -208, 818, -162, +1248, -20, 990, 133, 197, 89, -757, -77, +-1460, -257, -1427, -391, -746, -284, 209, 121, +1115, 547, 1501, 843, 1070, 869, 79, 397, +-945, -363, -1592, -968, -1591, -1306, -884, -1201, +136, -525, 1019, 454, 1413, 1315, 1099, 1725, +288, 1454, -601, 569, -1205, -564, -1308, -1468, +-846, -1802, -69, -1425, 610, -496, 937, 608, +760, 1424, 115, 1647, -570, 1256, -906, 415, +-852, -579, -407, -1274, 253, -1415, 694, -1025, +699, -247, 329, 622, -279, 1168, -800, 1203, +-956, 758, -704, 82, -204, -536, 393, -944, +805, -1010, 809, -665, 433, -83, -154, 498, +-747, 860, -1086, 900, -1035, 622, -577, 130, +124, -399, 737, -754, 1022, -805, 903, -561, +385, -136, -341, 327, -919, 650, -1153, 764, +-1066, 614, -674, 188, -44, -336, 590, -743, +1026, -888, 1024, -611, 583, -2, -25, 637, +-592, 1054, -938, 1049, -961, 512, -737, -310, +-430, -1023, -24, -1388, 389, -1229, 586, -424, +638, 668, 599, 1463, 264, 1709, -226, 1334, +-618, 352, -824, -788, -824, -1616, -576, -1879, +-224, -1417, 145, -395, 493, 702, 645, 1537, +539, 1860, 271, 1508, -106, 646, -459, -362, +-681, -1264, -745, -1706, -563, -1519, -152, -896, +252, -17, 426, 889, 398, 1452, 221, 1529, +-82, 1087, -356, 268, -419, -559, -256, -1159, +24, -1380, 200, -1033, 134, -291, -93, 462, +-352, 980, -529, 1070, -503, 679, -245, 72, +66, -488, 386, -829, 613, -748, 530, -241, +194, 392, -171, 861, -523, 897, -759, 418, +-778, -303, -569, -925, -223, -1212, 129, -926, +343, -148, 468, 718, 542, 1270, 480, 1330, +297, 891, -6, 106, -444, -684, -851, -1184, +-1027, -1273, -936, -843, -515, -110, 162, 519, +709, 894, 951, 936, 944, 581, 583, 130, +-51, -149, -680, -337, -1115, -418, -1193, -290, +-758, -181, -5, -191, 627, -128, 960, 32, +844, 208, 267, 369, -418, 384, -897, 263, +-1026, 82, -697, -207, -67, -475, 581, -518, +958, -353, 918, 22, 438, 495, -324, 778, +-1046, 733, -1373, 397, -1092, -187, -368, -799, +396, -1109, 1006, -995, 1213, -504, 826, 285, +83, 1022, -673, 1370, -1138, 1263, -1126, 694, +-623, -179, 106, -983, 693, -1431, 913, -1348, +629, -763, -54, 42, -775, 749, -1158, 1161, +-933, 1159, -234, 781, 557, 210, 1128, -360, +1207, -747, 653, -810, -350, -655, -1274, -396, +-1662, -21, -1323, 331, -406, 534, 629, 647, +1330, 589, 1500, 330, 984, -11, -70, -443, +-1084, -859, -1556, -947, -1397, -599, -669, 80, +318, 824, 1106, 1287, 1360, 1246, 981, 673, +116, -287, -808, -1197, -1334, -1614, -1311, -1443, +-788, -713, 16, 450, 736, 1469, 1096, 1835, +995, 1515, 461, 634, -208, -515, -688, -1455, +-882, -1810, -835, -1408, -531, -422, -60, 696, +317, 1456, 480, 1549, 424, 1013, 197, 75, +-40, -948, -232, -1510, -346, -1274, -234, -433, +-2, 620, 159, 1441, 177, 1545, 70, 872, +-193, -172, -478, -1194, -592, -1794, -549, -1547, +-293, -561, 225, 652, 731, 1604, 954, 1878, +775, 1362, 279, 349, -368, -785, -994, -1551, +-1314, -1598, -1152, -1019, -592, -132, 133, 710, +874, 1130, 1348, 987, 1213, 505, 573, -1, +-237, -390, -1009, -510, -1420, -288, -1214, 53, +-531, 250, 280, 197, 914, -134, 1096, -521, +740, -617, 92, -337, -581, 158, -1033, 705, +-1001, 1040, -502, 860, 171, 239, 776, -458, +1029, -986, 756, -1083, 89, -632, -649, 46, +-1238, 563, -1378, 809, -866, 751, 27, 373, +881, -163, 1437, -539, 1429, -589, 801, -352, +-157, 25, -1127, 349, -1786, 483, -1761, 360, +-1051, 12, -39, -331, 961, -498, 1661, -467, +1782, -186, 1240, 252, 234, 592, -886, 700, +-1709, 556, -1936, 167, -1536, -397, -642, -887, +427, -1028, 1304, -732, 1733, -92, 1534, 656, +806, 1197, -95, 1315, -920, 933, -1505, 170, +-1641, -701, -1243, -1373, -518, -1617, 355, -1311, +1117, -488, 1461, 563, 1358, 1463, 844, 2000, +7, 1934, -827, 1098, -1404, -234, -1589, -1568, +-1284, -2473, -544, -2565, 390, -1695, 1236, -100, +1720, 1645, 1509, 2872, 662, 3105, -359, 2154, +-1250, 317, -1775, -1660, -1654, -3075, -938, -3395, +49, -2370, 1003, -384, 1671, 1729, 1699, 3222, +1040, 3519, 10, 2382, -1073, 276, -1800, -1908, +-1823, -3352, -1143, -3436, -29, -2118, 1051, -1, +1635, 2105, 1542, 3344, 857, 3222, -145, 1894, +-1060, -168, -1511, -2163, -1428, -3193, -775, -2963, +228, -1706, 985, 158, 1209, 1935, 1023, 2919, +419, 2806, -466, 1699, -1086, 21, -1138, -1571, +-780, -2516, -163, -2584, 548, -1813, 955, -394, +847, 1231, 392, 2371, -189, 2533, -756, 1788, +-1020, 445, -778, -1091, -208, -2176, 298, -2341, +638, -1581, 805, -199, 573, 1178, 13, 1949, +-463, 1894, -701, 1094, -713, -38, -430, -1022, +8, -1601, 317, -1484, 420, -672, 363, 278, +77, 915, -247, 1147, -303, 915, -155, 346, +50, -253, 240, -680, 239, -748, 6, -427, +-320, -17, -585, 308, -646, 480, -382, 306, +74, -66, 514, -308, 869, -398, 892, -291, +433, 72, -250, 491, -853, 738, -1183, 640, +-1080, 198, -484, -319, 341, -755, 937, -1013, +1114, -893, 821, -395, 185, 274, -514, 917, +-964, 1281, -958, 1177, -558, 681, 43, -39, +607, -783, 822, -1273, 583, -1380, 64, -1057, +-504, -311, -821, 512, -674, 1085, -167, 1381, +362, 1274, 672, 703, 627, -76, 249, -784, +-238, -1190, -600, -1169, -731, -823, -559, -302, +-125, 258, 372, 680, 704, 868, 709, 849, +374, 642, -163, 291, -679, -77, -967, -376, +-816, -632, -254, -820, 391, -802, 806, -540, +894, -160, 610, 313, 24, 894, -526, 1293, +-780, 1216, -821, 739, -634, -52, -159, -1024, +324, -1734, 545, -1814, 590, -1171, 491, -11, +188, 1210, -133, 2068, -319, 2232, -398, 1461, +-451, 17, -477, -1427, -399, -2304, -185, -2299, +152, -1366, 507, 83, 712, 1435, 695, 2184, +416, 2011, -70, 1064, -640, -125, -1078, -1150, +-1136, -1639, -788, -1395, -132, -718, 630, 41, +1227, 695, 1453, 954, 1164, 748, 324, 371, +-768, 69, -1597, -141, -1835, -264, -1497, -285, +-632, -243, 581, -196, 1672, -143, 2119, -59, +1762, 100, 789, 275, -514, 304, -1725, 179, +-2316, 15, -2047, -182, -1029, -352, 364, -319, +1617, -72, 2275, 215, 2039, 467, 1060, 550, +-250, 313, -1505, -88, -2239, -485, -2103, -788, +-1174, -724, 127, -306, 1326, 187, 2053, 681, +2037, 1017, 1258, 919, -4, 463, -1290, -136, +-2091, -752, -2123, -1197, -1374, -1267, -126, -854, +1156, -20, 2002, 877, 2136, 1503, 1443, 1703, +128, 1294, -1203, 298, -2022, -884, -2145, -1863, +-1491, -2246, -228, -1738, 1103, -573, 1972, 836, +2100, 2126, 1363, 2663, 44, 2142, -1257, 891, +-2053, -694, -2045, -2112, -1206, -2723, 102, -2330, +1325, -1173, 1995, 354, 1851, 1717, 949, 2430, +-305, 2327, -1407, 1436, -1978, 57, -1800, -1198, +-931, -1927, 292, -2047, 1353, -1472, 1797, -376, +1536, 730, 731, 1448, -312, 1645, -1164, 1263, +-1498, 428, -1260, -500, -610, -1160, 151, -1307, +712, -832, 896, -26, 786, 666, 438, 1045, +-32, 938, -374, 264, -485, -524, -424, -971, +-275, -1023, -121, -629, 19, 188, 111, 971, +133, 1318, 81, 1176, 11, 528, -24, -481, +-35, -1319, -10, -1605, 49, -1278, 134, -419, +153, 641, 0, 1434, -226, 1652, -340, 1191, +-298, 291, -193, -626, -22, -1225, 224, -1334, +385, -943, 376, -248, 265, 442, 41, 825, +-251, 825, -477, 567, -566, 196, -471, -158, +-157, -296, 232, -181, 522, -30, 626, -32, +511, -155, 200, -291, -140, -395, -402, -461, +-607, -296, -694, 211, -518, 734, -134, 976, +250, 974, 499, 643, 622, -38, 623, -809, +437, -1372, 74, -1463, -302, -970, -602, -141, +-798, 725, -802, 1358, -553, 1504, -61, 1129, +539, 422, 979, -401, 1023, -994, 679, -1122, +86, -930, -549, -561, -959, -53, -1041, 332, +-771, 469, -232, 493, 366, 482, 818, 450, +948, 391, 731, 239, 260, 26, -355, -236, +-848, -553, -993, -773, -729, -728, -198, -451, +359, -70, 723, 316, 821, 673, 641, 869, +181, 755, -387, 399, -759, 13, -838, -335, +-649, -595, -223, -670, 335, -589, 781, -445, +894, -152, 649, 225, 124, 478, -538, 615, +-1002, 690, -1009, 527, -623, 90, -34, -355, +644, -610, 1157, -705, 1146, -545, 627, -107, +-97, 338, -811, 605, -1259, 634, -1271, 310, +-853, -204, -115, -594, 716, -727, 1314, -505, +1442, 94, 1052, 720, 323, 1012, -473, 888, +-1110, 358, -1392, -455, -1189, -1135, -684, -1371, +-101, -1086, 501, -325, 996, 630, 1184, 1322, +1063, 1520, 709, 1191, 149, 390, -457, -595, +-933, -1275, -1240, -1390, -1271, -997, -924, -280, +-262, 466, 480, 907, 1145, 952, 1596, 614, +1516, 28, 801, -443, -202, -562, -1113, -401, +-1683, -16, -1650, 457, -970, 709, 21, 545, +921, 23, 1411, -673, 1355, -1196, 813, -1252, +-58, -797, -902, 82, -1274, 1129, -1064, 1854, +-423, 1946, 377, 1333, 988, 136, 1114, -1189, +715, -2101, -13, -2361, -770, -1842, -1243, -621, +-1215, 810, -734, 1830, 70, 2172, 945, 1861, +1531, 1058, 1571, 22, 989, -904, -3, -1431, +-1018, -1430, -1728, -1086, -1848, -625, -1353, -151, +-471, 214, 557, 378, 1406, 483, 1765, 652, +1689, 871, 1213, 1062, 257, 1109, -807, 797, +-1528, 21, -1840, -1033, -1710, -1962, -1135, -2425, +-262, -2221, 671, -1261, 1453, 337, 1901, 2055, +1876, 3241, 1329, 3461, 363, 2582, -775, 802, +-1681, -1329, -2083, -3134, -1961, -3961, -1340, -3515, +-317, -2009, 743, 79, 1574, 2144, 2104, 3456, +2130, 3670, 1433, 2912, 313, 1382, -783, -602, +-1752, -2321, -2323, -3198, -2073, -3162, -1224, -2313, +-254, -804, 742, 865, 1686, 2146, 2210, 2739, +2059, 2554, 1351, 1656, 299, 386, -984, -833, +-2076, -1732, -2455, -2161, -2082, -1975, -1109, -1249, +319, -256, 1668, 732, 2382, 1506, 2333, 1819, +1540, 1566, 137, 868, -1275, -57, -2129, -954, +-2210, -1458, -1538, -1425, -410, -963, 729, -230, +1570, 533, 1857, 1030, 1478, 1161, 683, 922, +-209, 396, -1028, -229, -1492, -761, -1457, -1053, +-1031, -981, -378, -602, 355, -81, 1022, 480, +1379, 979, 1320, 1203, 1018, 1045, 439, 579, +-448, -33, -1297, -693, -1750, -1273, -1679, -1553, +-1038, -1377, -26, -825, 966, 3, 1625, 951, +1799, 1731, 1408, 2134, 561, 2039, -349, 1265, +-1030, -63, -1461, -1475, -1483, -2563, -1003, -3052, +-351, -2639, 162, -1320, 588, 504, 872, 2295, +891, 3513, 831, 3677, 837, 2711, 665, 865, +256, -1370, -253, -3171, -950, -3883, -1681, -3480, +-1957, -2040, -1663, 141, -802, 2139, 535, 3156, +1891, 3182, 2785, 2359, 2888, 913, 1978, -607, +310, -1697, -1522, -2129, -2905, -1850, -3353, -1210, +-2781, -556, -1407, 60, 411, 533, 2039, 738, +3008, 842, 3155, 954, 2419, 1011, 981, 921, +-665, 596, -2044, 14, -2870, -674, -2933, -1321, +-2182, -1704, -878, -1576, 670, -931, 2038, -8, +2795, 999, 2809, 1780, 2105, 1999, 733, 1567, +-895, 644, -2185, -519, -2832, -1512, -2717, -1953, +-1746, -1709, -192, -906, 1323, 227, 2336, 1272, +2647, 1755, 2088, 1493, 871, 670, -460, -376, +-1544, -1188, -2132, -1430, -1915, -1048, -1076, -217, +-83, 695, 796, 1174, 1325, 1057, 1315, 525, +847, -206, 145, -816, -427, -929, -605, -609, +-455, -81, -183, 496, 116, 774, 235, 521, +0, 2, -378, -522, -606, -805, -558, -567, +-200, 70, 319, 703, 803, 1134, 1091, 1140, +1014, 546, 523, -429, -211, -1282, -985, -1640, +-1447, -1415, -1392, -738, -920, 236, -96, 1181, +861, 1704, 1476, 1687, 1562, 1218, 1168, 401, +418, -464, -454, -1159, -1142, -1608, -1458, -1642, +-1343, -1233, -793, -581, 46, 230, 803, 1016, +1186, 1542, 1155, 1729, 809, 1479, 266, 770, +-326, -96, -747, -914, -779, -1539, -554, -1701, +-310, -1336, -22, -686, 314, 56, 397, 691, +135, 1054, -124, 1079, -137, 853, -24, 553, +231, 320, 641, 161, 837, 57, 545, -147, +-107, -536, -877, -983, -1394, -1393, -1450, -1595, +-1031, -1202, -94, -237, 1070, 1004, 1902, 2254, +2130, 2916, 1672, 2485, 560, 1206, -898, -529, +-2176, -2277, -2748, -3304, -2261, -3138, -924, -1902, +716, -39, 2093, 1712, 2721, 2740, 2396, 2806, +1283, 1925, -227, 442, -1588, -958, -2336, -1775, +-2273, -1828, -1453, -1264, -145, -395, 1076, 466, +1744, 950, 1766, 818, 1168, 389, 161, -33, +-687, -419, -1015, -589, -893, -352, -461, 141, +121, 651, 494, 868, 424, 688, 48, 285, +-368, -304, -693, -972, -702, -1251, -241, -1028, +500, -517, 1178, 233, 1504, 1015, 1241, 1383, +424, 1273, -650, 789, -1637, -32, -2146, -959, +-1872, -1566, -961, -1548, 261, -863, 1513, 173, +2375, 1206, 2458, 1892, 1768, 1822, 496, 883, +-1013, -505, -2195, -1794, -2639, -2459, -2242, -2115, +-1122, -829, 284, 823, 1485, 2196, 2131, 2791, +2102, 2337, 1494, 937, 544, -778, -433, -2099, +-1131, -2590, -1405, -2116, -1295, -920, -915, 395, +-436, 1363, -18, 1708, 308, 1329, 501, 528, +637, -168, 826, -516, 960, -392, 877, 101, +583, 479, 110, 424, -506, 5, -1107, -702, +-1426, -1404, -1419, -1673, -1138, -1312, -496, -350, +441, 947, 1292, 2013, 1808, 2463, 1925, 2187, +1574, 1241, 741, -84, -371, -1362, -1400, -2254, +-2009, -2449, -2074, -1982, -1664, -1197, -861, -284, +250, 705, 1291, 1544, 1890, 2053, 2015, 2157, +1707, 1879, 973, 1272, 69, 312, -772, -912, +-1451, -1979, -1778, -2618, -1704, -2721, -1352, -2126, +-664, -927, 276, 489, 1135, 1878, 1705, 2904, +1919, 3139, 1672, 2506, 1022, 1316, 132, -159, +-821, -1649, -1612, -2758, -2005, -3066, -1843, -2517, +-1163, -1383, -200, 27, 803, 1344, 1556, 2100, +1844, 2201, 1598, 1788, 919, 1013, 47, 225, +-730, -295, -1189, -648, -1229, -840, -904, -869, +-366, -941, 181, -1067, 528, -1048, 533, -859, +268, -420, -68, 303, -232, 1121, -99, 1817, +219, 2177, 521, 1962, 717, 1210, 690, 84, +334, -1179, -222, -2180, -721, -2660, -1067, -2564, +-1186, -1766, -980, -451, -465, 936, 217, 2092, +898, 2770, 1360, 2730, 1520, 2012, 1350, 792, +803, -580, 1, -1694, -814, -2354, -1485, -2474, +-1810, -1943, -1645, -921, -1033, 221, -127, 1097, +840, 1544, 1529, 1593, 1784, 1284, 1607, 720, +1055, 272, 309, 82, -383, -42, -912, -217, +-1291, -485, -1440, -899, -1232, -1313, -830, -1594, +-396, -1541, 182, -910, 914, 211, 1463, 1429, +1699, 2432, 1693, 2841, 1308, 2424, 429, 1279, +-709, -330, -1748, -1938, -2392, -2940, -2451, -3098, +-1787, -2442, -485, -1138, 1048, 420, 2276, 1729, +2843, 2476, 2585, 2544, 1594, 2010, 156, 1054, +-1333, 8, -2381, -812, -2617, -1361, -2071, -1693, +-1002, -1671, 289, -1360, 1438, -939, 2016, -346, +1883, 412, 1234, 1090, 346, 1606, -502, 1877, +-1010, 1719, -1090, 1085, -808, 137, -297, -890, +144, -1680, 285, -2019, 209, -1822, 45, -1159, +-171, -240, -320, 659, -114, 1284, 391, 1460, +772, 1326, 880, 1025, 793, 534, 364, -16, +-362, -379, -976, -648, -1257, -935, -1227, -1122, +-828, -1141, -105, -973, 693, -463, 1281, 325, +1544, 1131, 1339, 1705, 648, 1818, -186, 1319, +-903, 355, -1412, -769, -1441, -1654, -965, -1927, +-263, -1507, 534, -662, 1203, 373, 1337, 1313, +960, 1697, 356, 1279, -347, 389, -926, -525, +-1004, -1179, -580, -1306, 32, -742, 582, 204, +838, 1015, 646, 1330, 182, 1046, -351, 268, +-775, -680, -884, -1426, -614, -1608, -75, -1099, +569, -133, 1055, 878, 1188, 1600, 911, 1736, +314, 1211, -410, 237, -1030, -768, -1323, -1448, +-1160, -1589, -651, -1160, 41, -342, 720, 490, +1167, 1075, 1275, 1273, 1063, 1001, 507, 353, +-224, -334, -808, -836, -1102, -1000, -1059, -743, +-612, -198, 13, 381, 470, 826, 659, 902, +648, 560, 384, 13, -32, -531, -260, -926, +-195, -936, -39, -530, 169, 86, 430, 645, +473, 921, 163, 816, -248, 452, -664, -16, +-972, -400, -890, -564, -427, -480, 210, -270, +931, -103, 1428, -64, 1370, -61, 798, -66, +-1, -67, -755, 54, -1247, 348, -1302, 626, +-863, 742, -190, 612, 435, 218, 830, -331, +871, -840, 590, -1163, 162, -1125, -219, -688, +-378, -39, -273, 569, 20, 1028, 319, 1234, +501, 1087, 462, 625, 94, 81, -481, -396, +-935, -770, -1138, -988, -968, -972, -341, -819, +522, -584, 1314, -200, 1830, 333, 1808, 861, +1136, 1295, 37, 1477, -1109, 1235, -1978, 578, +-2278, -294, -1846, -1181, -788, -1808, 481, -1935, +1562, -1457, 2153, -486, 2089, 672, 1444, 1597, +419, 2022, -654, 1817, -1354, 994, -1618, -155, +-1455, -1123, -840, -1592, -72, -1462, 459, -840, +743, -11, 808, 654, 637, 924, 425, 733, +354, 222, 287, -337, 178, -636, 67, -526, +-191, -29, -589, 604, -828, 1033, -833, 1030, +-668, 587, -284, -243, 262, -1187, 752, -1725, +1058, -1558, 1105, -849, 833, 195, 301, 1268, +-277, 1903, -743, 1811, -1005, 1081, -942, -42, +-565, -1075, -142, -1557, 213, -1421, 525, -853, +694, -34, 674, 684, 564, 983, 329, 800, +-15, 307, -298, -247, -445, -580, -496, -562, +-422, -209, -278, 290, -122, 679, 57, 770, +255, 514, 435, -48, 574, -660, 580, -999, +392, -924, 33, -565, -370, -40, -678, 520, +-789, 867, -625, 820, -195, 540, 287, 176, +710, -204, 963, -438, 861, -400, 491, -205, +1, 40, -583, 180, -977, 90, -951, -153, +-633, -426, -171, -688, 380, -705, 761, -324, +824, 342, 703, 1071, 512, 1605, 185, 1646, +-198, 1083, -440, -10, -531, -1287, -621, -2251, +-612, -2511, -386, -1926, -59, -604, 215, 924, +468, 2087, 715, 2567, 838, 2243, 737, 1200, +461, -107, 31, -1174, -454, -1699, -844, -1660, +-1033, -1190, -907, -558, -492, -26, 11, 246, +494, 319, 849, 335, 993, 458, 871, 745, +539, 1100, 152, 1280, -216, 1078, -551, 390, +-690, -593, -598, -1579, -470, -2283, -388, -2391, +-258, -1691, -64, -394, 211, 1085, 574, 2300, +951, 2873, 1159, 2616, 1023, 1611, 508, 96, +-234, -1426, -985, -2437, -1479, -2696, -1555, -2212, +-1152, -1118, -315, 201, 690, 1313, 1411, 1912, +1655, 1905, 1427, 1372, 756, 594, -186, -179, +-925, -728, -1150, -926, -993, -808, -617, -579, +-120, -356, 243, -174, 385, -91, 401, -136, +348, -108, 284, 119, 292, 442, 319, 707, +217, 868, -42, 797, -277, 411, -416, -179, +-477, -730, -382, -1059, -70, -1019, 279, -645, +514, -95, 581, 415, 384, 734, -30, 738, +-386, 421, -601, -39, -611, -347, -311, -411, +214, -259, 702, 75, 938, 481, 856, 695, +503, 587, -82, 168, -695, -416, -1092, -933, +-1171, -1186, -921, -1115, -350, -641, 374, 139, +1021, 942, 1408, 1468, 1417, 1559, 1036, 1187, +360, 528, -459, -285, -1138, -1047, -1505, -1413, +-1494, -1277, -1049, -932, -299, -527, 528, -90, +1287, 308, 1666, 607, 1432, 839, 780, 1023, +34, 1157, -652, 1096, -1064, 702, -1024, -12, +-671, -873, -268, -1630, 110, -1987, 342, -1809, +343, -1065, 190, 67, 32, 1206, -32, 1964, +88, 2135, 373, 1645, 680, 727, 782, -270, +577, -1072, 64, -1465, -663, -1369, -1312, -984, +-1493, -476, -1155, 10, -435, 324, 521, 433, +1410, 446, 1840, 439, 1664, 482, 951, 524, +-58, 523, -1011, 471, -1568, 300, -1551, -82, +-1016, -552, -210, -977, 564, -1217, 1012, -1136, +1074, -734, 786, -116, 262, 655, -188, 1300, +-395, 1527, -448, 1284, -320, 704, -15, -39, +256, -699, 283, -1108, 148, -1139, -16, -827, +-193, -367, -339, 28, -317, 271, -133, 331, +79, 317, 280, 297, 476, 283, 519, 311, +390, 374, 187, 352, -83, 211, -400, -41, +-546, -309, -428, -490, -232, -568, -62, -568, +213, -455, 420, -318, 383, -149, 265, 128, +136, 454, -55, 745, -164, 981, -121, 960, +-51, 644, -11, 160, 93, -457, 171, -1070, +90, -1359, -35, -1273, -58, -890, -110, -257, +-249, 473, -262, 1052, -82, 1351, 80, 1274, +260, 872, 487, 299, 562, -278, 393, -751, +131, -1008, -143, -1001, -400, -749, -578, -407, +-572, -45, -412, 311, -161, 560, 154, 625, +465, 591, 647, 452, 671, 240, 525, 53, +238, -70, -113, -157, -389, -192, -524, -244, +-514, -321, -382, -426, -164, -539, 70, -537, +229, -316, 271, 22, 272, 458, 213, 923, +168, 1178, 261, 1068, 364, 696, 286, 93, +86, -662, -172, -1334, -504, -1612, -778, -1388, +-768, -776, -479, 32, 8, 877, 552, 1440, +935, 1512, 1053, 1173, 882, 595, 420, -85, +-152, -623, -667, -942, -970, -1063, -965, -954, +-660, -654, -180, -298, 305, 132, 698, 556, +927, 826, 781, 915, 339, 830, -71, 472, +-330, -34, -490, -452, -430, -678, -163, -704, +78, -461, 154, -86, 109, 164, 6, 166, +-95, 35, -129, -162, -5, -270, 183, -106, +311, 291, 361, 704, 311, 970, 162, 850, +-28, 304, -274, -451, -468, -1170, -462, -1569, +-264, -1294, -32, -492, 174, 435, 396, 1237, +541, 1616, 400, 1310, 118, 524, -49, -408, +-126, -1110, -238, -1265, -247, -906, -65, -293, +99, 418, 67, 901, 7, 901, -1, 495, +-74, -78, -136, -592, 38, -806, 260, -691, +307, -298, 287, 229, 243, 669, 44, 844, +-191, 720, -293, 321, -288, -146, -240, -538, +-93, -799, 101, -816, 222, -510, 266, -83, +283, 298, 223, 564, 76, 677, -80, 568, +-135, 279, -109, -33, -66, -249, -40, -419, +-13, -451, 42, -286, 95, -50, 80, 133, +51, 241, 27, 201, 10, 98, -45, -28, +-101, -212, -40, -301, 129, -163, 232, -6, +224, 158, 171, 404, 93, 568, -84, 509, +-261, 292, -314, -116, -238, -602, -93, -937, +74, -999, 241, -758, 369, -177, 355, 520, +236, 1054, 70, 1278, -86, 1145, -176, 618, +-226, -110, -242, -771, -126, -1194, 42, -1270, +121, -899, 129, -287, 160, 305, 162, 763, +112, 982, 33, 799, -27, 362, -34, -57, +-25, -316, -28, -392, 7, -258, 48, -35, +71, 138, 43, 116, 36, -88, 69, -341, +-5, -495, -132, -491, -119, -267, -84, 120, +-79, 552, 42, 869, 282, 952, 415, 733, +349, 265, 188, -384, 16, -960, -182, -1222, +-319, -1130, -354, -700, -316, 43, -206, 758, +-27, 1131, 145, 1117, 308, 757, 457, 143, +502, -393, 403, -685, 240, -724, 32, -464, +-188, -28, -405, 223, -573, 223, -629, 98, +-511, -88, -186, -266, 288, -225, 689, 42, +891, 358, 853, 541, 573, 514, 116, 256, +-324, -93, -614, -401, -751, -574, -717, -534, +-466, -285, -126, -35, 217, 154, 515, 303, +670, 335, 644, 215, 533, 115, 372, 71, +92, 29, -261, -33, -504, -78, -655, -109, +-692, -126, -474, -171, -29, -162, 413, -64, +702, 37, 755, 74, 525, 93, 136, 75, +-167, 55, -350, 29, -405, 13, -259, 38, +42, 95, 222, 85, 173, 43, 77, -38, +-5, -159, -154, -213, -226, -149, -127, -121, +95, -87, 320, 33, 383, 140, 268, 137, +186, 136, 129, 163, -12, 153, -151, 75, +-207, -17, -312, -105, -404, -124, -325, -116, +-110, -149, 138, -189, 408, -157, 633, -129, +665, -62, 450, 135, 171, 344, -112, 404, +-413, 392, -615, 244, -621, -81, -435, -373, +-110, -452, 233, -396, 498, -204, 563, 52, +435, 218, 227, 246, 18, 150, -111, -92, +-65, -266, 30, -203, 55, 56, 33, 376, +-46, 629, -255, 640, -444, 358, -476, -179, +-375, -776, -141, -1173, 300, -1179, 840, -760, +1179, 33, 1092, 892, 693, 1494, 68, 1644, +-717, 1241, -1363, 304, -1533, -799, -1199, -1626, +-548, -1850, 272, -1391, 1106, -408, 1587, 682, +1559, 1459, 1117, 1616, 405, 1122, -379, 179, +-989, -770, -1283, -1278, -1205, -1138, -795, -484, +-206, 406, 309, 1100, 676, 1254, 890, 766, +878, -148, 621, -1103, 256, -1631, -57, -1481, +-229, -667, -306, 483, -303, 1501, -260, 1983, +-216, 1781, -167, 919, -143, -311, -189, -1439, +-134, -2020, 111, -1904, 339, -1193, 436, -153, +577, 906, 641, 1571, 478, 1662, 198, 1257, +-160, 534, -552, -271, -769, -825, -766, -1025, +-611, -908, -324, -565, 108, -184, 520, 75, +778, 258, 909, 295, 863, 204, 550, 188, +137, 308, -249, 365, -610, 325, -843, 228, +-788, 51, -526, -216, -215, -447, 83, -582, +342, -566, 520, -382, 617, -84, 617, 165, +572, 324, 447, 411, 224, 431, -48, 375, +-382, 310, -731, 236, -907, 154, -843, -26, +-554, -362, -126, -734, 392, -907, 912, -858, +1226, -550, 1146, 58, 795, 782, 338, 1261, +-232, 1366, -832, 1067, -1185, 416, -1219, -442, +-960, -1189, -406, -1524, 313, -1334, 903, -792, +1212, -36, 1248, 769, 972, 1311, 382, 1328, +-245, 909, -727, 260, -1004, -382, -982, -842, +-664, -983, -177, -759, 340, -273, 693, 172, +773, 431, 585, 491, 275, 376, -30, 137, +-205, -78, -200, -225, -88, -249, 37, -142, +106, 27, 40, 162, -107, 256, -263, 264, +-336, 156, -272, -75, -49, -302, 264, -440, +552, -463, 672, -347, 579, -53, 288, 286, +-98, 565, -426, 709, -572, 634, -564, 318, +-417, -100, -133, -552, 189, -875, 413, -885, +528, -593, 541, -153, 457, 386, 227, 846, +-56, 996, -272, 782, -424, 374, -499, -156, +-445, -689, -231, -981, 157, -873, 514, -510, +684, -17, 631, 491, 332, 847, -118, 917, +-490, 694, -644, 164, -504, -434, -123, -852, +282, -1029, 520, -866, 601, -254, 467, 499, +118, 1059, -221, 1256, -379, 956, -444, 187, +-401, -668, -132, -1286, 238, -1426, 408, -981, +436, -113, 422, 793, 227, 1415, -77, 1465, +-255, 892, -318, -34, -246, -868, -49, -1326, +129, -1241, 193, -635, 204, 216, 128, 870, +-46, 1090, -199, 817, -228, 203, -116, -435, +139, -804, 405, -823, 566, -443, 528, 187, +284, 753, -115, 953, -559, 687, -854, 60, +-828, -609, -500, -1066, 61, -1124, 647, -667, +1025, 177, 1098, 937, 876, 1294, 373, 1162, +-281, 575, -856, -283, -1113, -1012, -987, -1303, +-529, -1048, 49, -421, 553, 314, 862, 887, +882, 1094, 590, 801, 183, 198, -115, -385, +-258, -734, -334, -787, -276, -484, -106, 5, +15, 437, 22, 659, -39, 588, -151, 204, +-229, -230, -159, -520, 106, -619, 445, -463, +678, -61, 689, 328, 514, 551, 145, 573, +-374, 373, -771, 9, -832, -292, -656, -460, +-301, -453, 166, -263, 579, -11, 783, 173, +740, 309, 484, 294, 87, 111, -294, -68, +-420, -130, -332, -155, -163, -78, 10, 73, +128, 153, 132, 138, 34, 101, -107, -14, +-184, -158, -144, -255, 2, -272, 201, -220, +397, -94, 502, 64, 511, 292, 357, 527, +-17, 590, -427, 385, -654, 36, -693, -369, +-532, -735, -189, -911, 229, -731, 569, -232, +738, 413, 703, 930, 472, 1112, 139, 901, +-123, 382, -324, -327, -464, -932, -475, -1192, +-361, -1023, -219, -495, -40, 233, 203, 839, +417, 1113, 517, 1000, 518, 535, 360, -139, +77, -705, -220, -972, -398, -878, -398, -492, +-241, 55, 5, 539, 237, 765, 332, 660, +267, 369, 49, 14, -191, -319, -309, -489, +-254, -396, -54, -205, 256, -52, 529, 39, +614, 79, 429, 63, 53, 78, -344, 140, +-588, 239, -608, 320, -408, 290, -75, 78, +251, -196, 458, -460, 502, -646, 386, -623, +260, -312, 150, 123, -1, 534, -121, 807, +-156, 821, -203, 526, -270, 64, -274, -427, +-165, -738, -21, -758, 102, -577, 189, -320, +317, 17, 446, 322, 458, 494, 336, 544, +145, 527, -131, 415, -442, 226, -633, -54, +-533, -369, -243, -616, 42, -704, 330, -637, +564, -390, 528, -7, 327, 438, 153, 798, +1, 913, -158, 694, -225, 264, -182, -252, +-106, -682, -45, -843, -13, -678, -34, -312, +-63, 129, -69, 438, -4, 493, 146, 342, +351, 124, 468, -85, 420, -147, 261, -69, +-13, 23, -347, 76, -531, 91, -559, -33, +-442, -201, -120, -270, 280, -224, 552, -101, +690, 103, 641, 240, 316, 255, -151, 214, +-453, 123, -524, -53, -439, -164, -208, -178, +132, -158, 400, -115, 462, -42, 338, -6, +128, 86, -117, 235, -309, 296, -363, 219, +-230, 68, 21, -199, 276, -504, 459, -662, +494, -537, 319, -118, 22, 498, -279, 992, +-467, 1112, -492, 807, -338, 140, -57, -715, +262, -1369, 496, -1513, 559, -1051, 419, -176, +169, 782, -109, 1452, -339, 1586, -428, 1087, +-286, 166, 7, -733, 243, -1209, 319, -1172, +258, -690, 19, 15, -247, 602, -339, 746, +-252, 435, -37, -62, 307, -406, 629, -471, +669, -229, 374, 263, -34, 759, -425, 898, +-716, 612, -774, 29, -492, -666, 5, -1187, +489, -1252, 788, -889, 798, -221, 522, 585, +128, 1207, -259, 1359, -499, 1093, -529, 517, +-378, -194, -122, -792, 140, -1095, 303, -1081, +331, -739, 237, -217, 116, 265, -18, 606, +-130, 781, -128, 679, -19, 385, 55, 81, +95, -163, 154, -336, 168, -350, 88, -245, +11, -115, -97, -46, -223, -41, -265, -65, +-201, -52, -49, -28, 169, 39, 359, 154, +450, 248, 396, 234, 225, 161, -28, 60, +-276, -58, -407, -148, -390, -158, -253, -135, +12, -89, 261, -60, 345, -65, 291, -75, +158, -69, -40, -72, -168, -9, -137, 128, +25, 231, 237, 268, 380, 307, 293, 258, +45, 112, -235, -54, -485, -245, -607, -456, +-458, -571, -80, -574, 333, -430, 646, -98, +816, 340, 746, 720, 438, 959, -27, 932, +-479, 577, -748, 20, -775, -542, -619, -982, +-299, -1132, 123, -935, 487, -477, 673, 88, +740, 626, 656, 936, 371, 942, 36, 702, +-237, 300, -505, -154, -683, -453, -652, -559, +-416, -521, -82, -346, 269, -115, 543, -10, +643, 5, 556, 0, 358, -12, 91, 30, +-152, 186, -285, 368, -301, 507, -267, 515, +-180, 344, -88, 21, -39, -337, -4, -639, +32, -778, 69, -714, 169, -465, 299, -99, +385, 301, 368, 607, 280, 769, 93, 771, +-208, 617, -472, 294, -534, -115, -431, -487, +-211, -725, 58, -811, 291, -696, 419, -400, +425, -14, 313, 309, 180, 518, 100, 600, +34, 547, -55, 368, -106, 199, -145, 80, +-208, -52, -285, -187, -325, -288, -276, -435, +-117, -592, 117, -664, 409, -583, 628, -314, +688, 185, 594, 760, 351, 1192, -45, 1322, +-462, 1071, -767, 397, -891, -497, -782, -1280, +-423, -1673, 78, -1548, 594, -910, 971, 3, +1074, 863, 845, 1415, 408, 1512, -100, 1101, +-566, 398, -848, -306, -831, -810, -595, -1001, +-251, -825, 114, -435, 397, -37, 532, 226, +506, 292, 377, 176, 259, 24, 163, -26, +91, 88, 28, 313, -82, 526, -271, 552, +-447, 329, -508, -92, -442, -580, -259, -936, +66, -940, 409, -590, 654, -44, 730, 509, +615, 892, 311, 919, -105, 619, -458, 149, +-592, -322, -557, -612, -383, -588, -94, -328, +191, 13, 339, 267, 350, 308, 257, 121, +132, -155, 38, -393, -10, -436, -18, -188, +49, 251, 117, 641, 104, 820, -14, 671, +-158, 212, -250, -387, -289, -875, -243, -1052, +-61, -813, 161, -268, 322, 361, 369, 820, +341, 936, 244, 679, 54, 191, -108, -312, +-141, -590, -165, -559, -185, -280, -106, 88, +-17, 352, -43, 347, -92, 92, -99, -253, +-79, -489, 11, -486, 236, -204, 494, 253, +627, 691, 532, 869, 236, 669, -193, 137, +-627, -501, -869, -941, -786, -1008, -468, -704, +-30, -77, 421, 600, 774, 960, 895, 883, +766, 494, 465, -76, 88, -569, -313, -758, +-637, -620, -752, -246, -633, 223, -398, 529, +-118, 549, 155, 336, 382, 6, 540, -328, +620, -494, 588, -427, 436, -189, 194, 132, +-96, 410, -418, 493, -662, 374, -758, 125, +-690, -182, -436, -452, -8, -511, 497, -360, +950, -105, 1130, 209, 936, 492, 452, 557, +-171, 397, -776, 102, -1114, -251, -1029, -548, +-631, -641, -107, -506, 423, -171, 791, 262, +897, 615, 747, 743, 437, 627, 64, 277, +-282, -195, -519, -610, -588, -817, -505, -747, +-327, -394, -119, 90, 96, 509, 296, 728, +476, 698, 571, 426, 518, 22, 304, -343, +-18, -494, -352, -416, -568, -221, -584, -31, +-375, 112, -54, 147, 243, 49, 422, -74, +434, -91, 301, -24, 107, 88, -73, 211, +-125, 298, -76, 287, -29, 176, 6, -20, +26, -252, -37, -431, -165, -494, -254, -424, +-187, -192, 4, 134, 215, 424, 380, 568, +456, 514, 357, 285, 105, 1, -205, -245, +-432, -372, -455, -325, -269, -155, -41, -12, +159, 44, 318, 18, 353, -60, 218, -145, +22, -146, -110, -37, -132, 150, -77, 350, +29, 488, 119, 477, 124, 308, 32, 6, +-97, -372, -176, -709, -164, -841, -64, -721, +96, -362, 196, 164, 192, 662, 130, 952, +68, 987, 5, 713, -29, 180, -7, -376, +8, -768, -50, -933, -93, -796, -112, -405, +-117, 49, -71, 407, 33, 581, 131, 518, +201, 309, 248, 90, 263, -50, 190, -64, +12, 19, -215, 68, -359, 5, -364, -163, +-249, -378, -28, -543, 239, -529, 416, -279, +444, 133, 333, 534, 126, 802, -151, 820, +-367, 536, -418, 55, -326, -425, -126, -751, +170, -830, 403, -656, 436, -272, 305, 192, +113, 551, -125, 684, -322, 598, -382, 315, +-304, -76, -136, -390, 109, -506, 361, -423, +522, -160, 502, 165, 277, 380, -103, 388, +-477, 199, -692, -97, -642, -352, -307, -465, +193, -364, 631, -59, 864, 293, 777, 511, +389, 528, -126, 333, -611, 13, -922, -300, +-869, -480, -468, -457, 92, -275, 626, -51, +953, 153, 902, 278, 511, 284, -24, 206, +-487, 108, -739, 11, -709, -51, -429, -88, +-26, -118, 313, -117, 490, -104, 487, -113, +336, -72, 98, 29, -112, 129, -194, 197, +-155, 188, -84, 82, 4, -55, 53, -187, +6, -270, -89, -214, -125, -24, -84, 188, +3, 338, 117, 347, 224, 181, 242, -77, +181, -316, 87, -471, -2, -432, -77, -160, +-117, 190, -134, 428, -150, 508, -151, 400, +-127, 99, -97, -259, -3, -478, 157, -481, +303, -271, 405, 69, 455, 366, 338, 494, +45, 403, -288, 81, -553, -312, -682, -557, +-569, -547, -265, -289, 109, 144, 485, 550, +749, 726, 773, 596, 583, 199, 242, -315, +-180, -691, -575, -775, -792, -557, -753, -111, +-469, 394, -35, 702, 395, 666, 667, 339, +696, -116, 500, -498, 205, -611, -79, -412, +-280, -8, -356, 423, -296, 649, -176, 529, +-76, 152, -25, -312, -8, -693, -25, -812, +-10, -595, 90, -129, 258, 423, 406, 847, +445, 981, 319, 800, 39, 357, -303, -246, +-538, -806, -603, -1104, -493, -1051, -207, -672, +176, -64, 499, 582, 663, 1048, 607, 1149, +355, 845, 19, 277, -275, -332, -448, -783, +-445, -925, -303, -720, -115, -293, 45, 153, +148, 449, 174, 495, 160, 325, 161, 64, +207, -154, 235, -226, 192, -97, 86, 154, +-59, 345, -247, 349, -411, 148, -436, -200, +-280, -542, -40, -695, 226, -564, 453, -174, +530, 332, 434, 702, 227, 779, -46, 581, +-281, 175, -388, -305, -384, -605, -298, -607, +-115, -398, 88, -83, 223, 203, 280, 322, +273, 271, 216, 117, 156, -58, 83, -124, +4, -44, -79, 65, -199, 142, -324, 161, +-331, 60, -214, -115, -51, -255, 136, -310, +338, -235, 454, -23, 436, 214, 303, 357, +82, 375, -190, 244, -420, -16, -518, -286, +-443, -434, -233, -419, 60, -248, 318, 40, +442, 334, 433, 511, 342, 506, 177, 304, +-11, -32, -159, -367, -254, -577, -311, -578, +-311, -354, -265, 1, -144, 326, 46, 509, +239, 505, 374, 327, 443, 73, 385, -157, +197, -295, -17, -307, -200, -225, -362, -112, +-410, -7, -318, 51, -191, 60, -44, 54, +154, 39, 297, 30, 355, 66, 366, 123, +310, 145, 161, 133, -21, 86, -193, -19, +-318, -145, -369, -248, -340, -302, -233, -260, +-31, -126, 196, 37, 359, 191, 430, 290, +391, 283, 214, 198, -18, 95, -191, 1, +-267, -54, -267, -52, -182, -48, -62, -107, +31, -217, 87, -329, 104, -386, 62, -310, +2, -57, 1, 321, 76, 673, 161, 836, +229, 708, 225, 288, 100, -284, -91, -783, +-254, -1010, -358, -877, -356, -450, -225, 95, +-24, 580, 174, 844, 348, 790, 432, 475, +392, 63, 256, -315, 56, -537, -159, -513, +-304, -284, -369, 20, -347, 266, -226, 328, +-47, 160, 113, -125, 245, -365, 319, -446, +307, -286, 227, 88, 112, 508, -45, 769, +-178, 746, -221, 418, -185, -122, -121, -663, +-29, -974, 72, -939, 134, -570, 116, -8, +42, 526, -56, 836, -129, 831, -119, 538, +15, 108, 222, -248, 402, -408, 435, -378, +262, -213, -75, -34, -439, 28, -708, -53, +-744, -204, -477, -304, 14, -250, 534, -27, +913, 292, 1006, 602, 745, 759, 211, 657, +-381, 313, -842, -183, -1010, -684, -819, -999, +-368, -1007, 154, -691, 589, -130, 806, 493, +742, 950, 442, 1083, 83, 857, -186, 361, +-340, -208, -385, -648, -323, -830, -221, -710, +-124, -371, -33, 18, 52, 307, 128, 425, +222, 348, 298, 135, 297, -70, 222, -146, +98, -77, -71, 81, -236, 235, -328, 287, +-290, 183, -137, -57, 46, -336, 164, -517, +195, -510, 143, -321, 31, -7, -63, 330, +-38, 558, 53, 591, 148, 429, 220, 129, +204, -182, 48, -385, -164, -448, -329, -374, +-404, -186, -348, 15, -139, 140, 148, 188, +432, 172, 613, 113, 565, 53, 269, 22, +-122, 18, -442, 38, -596, 45, -535, -4, +-264, -75, 91, -111, 393, -122, 542, -99, +486, -33, 257, 36, -35, 67, -329, 53, +-522, 0, -467, -44, -181, -41, 145, -7, +419, 58, 567, 170, 475, 258, 186, 246, +-113, 120, -366, -108, -539, -376, -532, -561, +-336, -580, -71, -400, 223, -24, 519, 443, +714, 792, 691, 894, 442, 729, 30, 317, +-414, -254, -769, -777, -915, -1056, -757, -1021, +-326, -677, 216, -105, 731, 516, 1062, 986, +1033, 1147, 610, 942, -13, 452, -608, -163, +-972, -730, -932, -1064, -537, -1027, -30, -654, +419, -113, 688, 430, 655, 799, 347, 868, +10, 648, -211, 249, -328, -183, -302, -490, +-93, -582, 137, -474, 224, -225, 169, 70, +40, 271, -126, 307, -221, 198, -181, 17, +-46, -130, 109, -156, 224, -47, 221, 131, +101, 264, -32, 246, -72, 57, -33, -218, +48, -431, 113, -469, 100, -310, 2, 14, +-140, 382, -272, 601, -301, 572, -191, 331, +32, -37, 284, -399, 467, -613, 491, -609, +331, -390, 31, -38, -283, 302, -476, 525, +-474, 581, -301, 458, -28, 196, 221, -121, +360, -388, 355, -518, 229, -488, 34, -326, +-134, -78, -204, 170, -151, 342, -19, 415, +106, 375, 157, 241, 141, 70, 60, -100, +-73, -234, -189, -281, -220, -269, -183, -243, +-74, -189, 93, -97, 247, 23, 332, 177, +333, 345, 226, 458, 40, 448, -154, 285, +-306, -18, -393, -363, -342, -615, -155, -677, +71, -515, 265, -171, 376, 252, 343, 609, +200, 757, 22, 633, -139, 290, -224, -136, +-177, -498, -52, -670, 68, -584, 139, -274, +130, 101, 5, 372, -168, 472, -283, 380, +-262, 130, -104, -137, 159, -299, 434, -312, +599, -163, 556, 79, 277, 285, -181, 369, +-608, 291, -801, 39, -697, -287, -358, -528, +109, -586, 541, -403, 773, -7, 723, 448, +442, 770, 61, 824, -266, 552, -469, 35, +-499, -517, -345, -874, -110, -915, 56, -634, +129, -126, 134, 416, 86, 778, 55, 844, +113, 631, 206, 229, 276, -221, 293, -567, +190, -696, -53, -567, -336, -254, -548, 92, +-583, 352, -387, 454, -20, 375, 366, 184, +638, -12, 695, -143, 501, -189, 115, -168, +-283, -114, -517, -65, -513, -30, -326, -4, +-47, 27, 208, 65, 331, 100, 276, 125, +96, 124, -101, 77, -213, -4, -189, -92, +-20, -187, 208, -243, 358, -203, 344, -76, +177, 83, -108, 235, -400, 337, -531, 342, +-418, 223, -147, 6, 176, -232, 451, -410, +571, -481, 474, -403, 195, -174, -163, 134, +-436, 416, -504, 579, -360, 555, -85, 346, +225, 27, 427, -300, 419, -527, 229, -574, +-28, -438, -256, -188, -383, 86, -366, 299, +-178, 402, 106, 394, 329, 309, 418, 183, +404, 37, 272, -108, 19, -239, -244, -334, +-406, -361, -446, -306, -368, -186, -195, -10, +50, 211, 309, 401, 481, 466, 505, 392, +393, 209, 165, -49, -113, -302, -350, -455, +-460, -440, -410, -264, -203, -25, 57, 157, +226, 250, 253, 258, 185, 170, 64, 43, +-45, -27, -70, -25, 29, 1, 187, 17, +291, 8, 254, -37, 70, -110, -206, -180, +-464, -196, -566, -124, -454, 13, -185, 147, +175, 231, 509, 262, 684, 211, 647, 69, +423, -92, 71, -191, -278, -216, -524, -175, +-606, -95, -514, -4, -296, 79, -50, 104, +185, 54, 367, 14, 455, 33, 448, 66, +354, 92, 169, 108, -39, 64, -207, -44, +-327, -157, -374, -237, -318, -225, -191, -82, +-30, 101, 132, 216, 243, 244, 239, 177, +156, 16, 71, -154, 54, -233, 109, -178, +176, -12, 176, 166, 73, 245, -144, 196, +-397, 27, -550, -205, -503, -359, -254, -317, +116, -105, 484, 165, 728, 381, 750, 447, +513, 306, 75, 0, -399, -323, -727, -489, +-780, -429, -530, -183, -85, 161, 340, 452, +584, 522, 563, 329, 315, -23, -20, -372, +-256, -558, -312, -478, -213, -165, -31, 226, +163, 514, 295, 583, 287, 401, 108, 57, +-157, -293, -381, -504, -447, -499, -316, -318, +-48, -63, 250, 178, 465, 318, 497, 321, +349, 259, 114, 195, -103, 112, -265, 10, +-345, -98, -323, -241, -200, -387, -42, -433, +72, -324, 123, -67, 142, 263, 120, 534, +94, 625, 129, 491, 203, 154, 225, -262, +161, -574, 18, -658, -192, -494, -405, -138, +-507, 263, -433, 530, -209, 553, 90, 347, +402, 18, 630, -291, 668, -437, 506, -352, +203, -102, -201, 165, -574, 316, -744, 285, +-653, 94, -364, -146, 29, -301, 390, -296, +604, -129, 613, 128, 433, 332, 157, 377, +-120, 239, -332, -26, -404, -303, -333, -451, +-198, -417, -31, -203, 139, 121, 218, 409, +204, 536, 152, 460, 66, 204, -49, -139, +-98, -431, -61, -568, 3, -516, 65, -285, +127, 51, 126, 361, 36, 544, -97, 563, +-211, 414, -279, 127, -263, -218, -108, -494, +174, -601, 433, -495, 524, -212, 424, 141, +166, 428, -206, 526, -536, 391, -649, 108, +-500, -179, -157, -343, 269, -290, 602, -52, +695, 208, 502, 339, 114, 248, -317, -55, +-609, -425, -635, -644, -375, -555, 38, -148, +415, 419, 593, 889, 507, 1030, 206, 718, +-158, 31, -433, -722, -506, -1192, -317, -1201, +34, -720, 333, 98, 449, 899, 362, 1315, +102, 1171, -232, 543, -469, -292, -467, -977, +-202, -1244, 178, -985, 492, -298, 606, 508, +472, 1057, 113, 1129, -325, 727, -647, 28, +-711, -681, -500, -1094, -90, -1035, 370, -546, +712, 158, 818, 778, 639, 1063, 209, 935, +-304, 470, -683, -162, -795, -718, -651, -977, +-301, -874, 153, -480, 533, 66, 675, 557, +587, 825, 342, 798, 18, 488, -282, 20, +-424, -409, -372, -656, -195, -651, -6, -394, +114, -14, 144, 317, 87, 463, -18, 378, +-92, 147, -68, -91, 60, -245, 229, -237, +325, -65, 287, 142, 137, 247, -110, 201, +-366, 17, -496, -215, -441, -375, -242, -394, +45, -226, 327, 97, 519, 406, 543, 562, +382, 524, 119, 274, -133, -123, -334, -488, +-437, -666, -396, -599, -266, -319, -107, 72, +66, 429, 215, 634, 308, 622, 348, 409, +323, 78, 220, -262, 66, -513, -118, -607, +-295, -502, -406, -222, -383, 129, -253, 413, +-67, 529, 150, 438, 361, 188, 474, -94, +448, -289, 292, -325, 31, -184, -273, 29, +-495, 155, -532, 139, -373, 2, -91, -191, +209, -307, 431, -248, 492, -35, 389, 253, +171, 496, -101, 564, -325, 401, -416, 61, +-349, -346, -145, -664, 133, -756, 332, -588, +378, -215, 263, 257, 37, 669, -196, 845, +-328, 718, -321, 353, -155, -109, 102, -517, +299, -738, 364, -698, 294, -429, 83, -45, +-194, 299, -376, 486, -376, 501, -214, 385, +38, 187, 282, -24, 395, -174, 305, -246, +82, -274, -138, -263, -258, -199, -259, -95, +-142, 34, 43, 181, 201, 282, 238, 286, +150, 203, -10, 62, -177, -87, -280, -184, +-234, -227, -24, -216, 235, -137, 387, -26, +349, 73, 155, 148, -106, 182, -311, 168, +-373, 108, -292, 15, -107, -67, 100, -114, +239, -131, 273, -114, 231, -79, 126, -45, +-22, 10, -144, 77, -172, 119, -130, 148, +-54, 150, 29, 94, 75, 6, 69, -93, +41, -193, 10, -233, -31, -187, -53, -79, +-37, 69, -15, 201, 9, 256, 58, 243, +117, 168, 144, 31, 119, -122, 25, -229, +-105, -282, -224, -286, -280, -206, -225, -23, +-53, 206, 145, 393, 300, 450, 380, 333, +325, 71, 115, -228, -140, -450, -307, -501, +-344, -346, -270, -51, -98, 250, 117, 435, +247, 428, 243, 245, 141, -18, -8, -241, +-119, -342, -143, -288, -96, -108, 18, 104, +179, 242, 244, 244, 145, 124, -42, -32, +-212, -156, -313, -202, -297, -148, -151, -34, +87, 82, 309, 166, 407, 176, 357, 103, +177, 4, -76, -68, -297, -107, -411, -106, +-366, -80, -153, -48, 124, -9, 313, 18, +345, 29, 230, 47, 31, 80, -168, 109, +-275, 101, -225, 52, -33, -15, 173, -76, +276, -135, 249, -175, 114, -171, -85, -111, +-252, 11, -313, 157, -256, 270, -96, 301, +97, 211, 225, 25, 266, -188, 243, -355, +141, -383, 4, -229, -65, 20, -78, 246, +-88, 375, -96, 348, -106, 171, -156, -75, +-203, -291, -163, -366, -8, -275, 199, -96, +388, 123, 484, 305, 409, 344, 144, 250, +-203, 86, -479, -112, -597, -284, -526, -361, +-273, -310, 86, -128, 419, 101, 583, 285, +528, 388, 304, 355, -4, 175, -290, -57, +-401, -259, -289, -378, -70, -357, 103, -207, +142, 0, 36, 198, -121, 326, -207, 338, +-164, 219, -9, 6, 203, -205, 383, -308, +435, -277, 328, -135, 88, 73, -212, 257, +-449, 318, -525, 218, -433, -16, -194, -283, +118, -443, 361, -397, 443, -132, 366, 270, +215, 604, 83, 655, -15, 383, -113, -85, +-195, -558, -259, -795, -305, -655, -302, -216, +-200, 296, 23, 638, 294, 667, 450, 431, +438, 71, 308, -276, 77, -466, -181, -421, +-342, -214, -364, 24, -246, 180, -49, 222, +83, 172, 114, 35, 102, -125, 54, -182, +15, -119, 55, 16, 140, 189, 190, 310, +147, 292, -9, 138, -187, -129, -297, -438, +-320, -618, -209, -538, 18, -203, 251, 293, +406, 736, 424, 901, 255, 695, -59, 173, +-381, -480, -562, -936, -491, -971, -179, -612, +252, -15, 591, 584, 651, 895, 402, 772, +-17, 325, -428, -204, -652, -557, -565, -583, +-231, -328, 154, 53, 442, 334, 555, 336, +458, 109, 197, -156, -107, -308, -350, -252, +-467, -15, -400, 235, -175, 358, 103, 302, +315, 106, 376, -107, 276, -251, 74, -296, +-149, -216, -284, -70, -240, 35, -72, 95, +88, 132, 163, 129, 145, 103, 71, 86, +2, 64, -33, 28, -30, -15, -10, -76, +-29, -155, -93, -204, -136, -185, -109, -102, +-12, 41, 101, 203, 158, 291, 164, 271, +152, 156, 118, -43, 57, -241, -59, -320, +-227, -263, -347, -102, -319, 107, -146, 263, +108, 308, 327, 243, 404, 56, 311, -202, +105, -403, -101, -436, -191, -256, -166, 84, +-141, 437, -148, 641, -135, 557, -77, 179, +6, -312, 99, -670, 170, -728, 195, -453, +169, 5, 83, 403, -1, 584, -27, 523, +-54, 275, -123, -35, -157, -250, -145, -294, +-104, -217, -24, -98, 44, -6, 62, 9, +76, -36, 94, -79, 123, -69, 188, 41, +198, 215, 86, 310, -96, 267, -281, 103, +-390, -152, -333, -358, -135, -361, 114, -186, +335, 44, 429, 236, 369, 284, 182, 156, +-83, -46, -326, -206, -440, -243, -399, -121, +-179, 87, 165, 270, 431, 358, 467, 276, +275, 21, -45, -262, -350, -442, -467, -466, +-338, -295, -38, 42, 246, 379, 374, 545, +326, 452, 177, 146, 0, -205, -165, -429, +-265, -429, -265, -182, -163, 170, 14, 406, +194, 386, 243, 98, 121, -307, -78, -550, +-235, -484, -250, -160, -70, 280, 205, 643, +405, 738, 419, 490, 217, -4, -106, -507, +-383, -788, -510, -752, -480, -438, -282, 41, +59, 519, 408, 797, 583, 733, 521, 373, +274, -101, -81, -511, -376, -712, -459, -621, +-315, -289, -64, 147, 150, 511, 208, 642, +119, 496, -30, 161, -145, -238, -142, -538, +-33, -594, 108, -386, 238, -23, 312, 335, +264, 546, 111, 524, -125, 277, -379, -65, +-522, -342, -446, -462, -171, -386, 165, -163, +392, 84, 417, 267, 270, 308, 45, 193, +-95, 31, -85, -92, -6, -151, 44, -91, +28, 41, -50, 123, -140, 128, -179, 50, +-176, -106, -169, -237, -173, -289, -93, -246, +110, -82, 368, 142, 580, 339, 615, 486, +377, 485, -47, 277, -474, -49, -771, -413, +-806, -709, -570, -759, -178, -518, 248, -67, +595, 456, 761, 839, 747, 906, 513, 649, +82, 147, -325, -419, -555, -792, -620, -842, +-525, -609, -291, -176, -57, 294, 102, 589, +199, 617, 284, 433, 366, 132, 398, -157, +330, -320, 170, -326, -28, -206, -225, -35, +-388, 91, -476, 132, -421, 94, -257, -3, +-35, -94, 212, -114, 425, -71, 515, 22, +434, 129, 184, 188, -125, 182, -349, 116, +-431, -12, -316, -138, -71, -207, 121, -229, +178, -198, 148, -89, 47, 55, -43, 184, +-60, 265, -32, 256, 29, 137, 70, -29, +57, -172, 51, -245, 68, -200, 40, -53, +2, 90, -69, 167, -185, 147, -214, 28, +-136, -94, -58, -121, 50, -85, 192, -7, +232, 94, 163, 134, 47, 81, -60, -23, +-115, -123, -107, -131, -61, -24, 40, 110, +139, 209, 126, 224, 3, 92, -162, -156, +-302, -397, -356, -499, -222, -378, 78, -53, +405, 350, 590, 675, 525, 773, 233, 568, +-126, 106, -423, -450, -586, -874, -530, -959, +-297, -653, -13, -111, 230, 437, 400, 800, +437, 811, 354, 470, 187, 8, 1, -324, +-130, -412, -193, -254, -205, -13, -205, 117, +-224, 74, -239, -145, -160, -427, -24, -500, +137, -282, 324, 99, 458, 543, 423, 868, +241, 871, 6, 551, -231, -6, -412, -621, +-506, -1012, -448, -1051, -218, -766, 104, -212, +369, 405, 486, 851, 425, 1002, 213, 794, +-65, 330, -276, -143, -317, -502, -224, -679, +-80, -588, 3, -297, 16, 33, 42, 279, +119, 318, 157, 161, 141, -30, 88, -161, +-48, -171, -203, 15, -241, 302, -156, 477, +-32, 424, 125, 144, 230, -261, 207, -582, +114, -666, 42, -514, -22, -183, -103, 211, +-214, 482, -336, 557, -349, 477, -206, 279, +59, 37, 378, -161, 631, -295, 633, -355, +380, -327, -34, -238, -498, -108, -788, 42, +-746, 151, -439, 207, 3, 217, 462, 186, +720, 152, 660, 127, 327, 71, -90, -27, +-375, -168, -430, -338, -319, -440, -113, -372, +98, -118, 203, 253, 202, 545, 111, 581, +-45, 380, -190, 59, -257, -291, -246, -516, +-51, -506, 285, -310, 495, -32, 439, 231, +212, 381, -92, 407, -392, 327, -534, 117, +-482, -154, -272, -344, -17, -405, 192, -323, +343, -131, 451, 68, 426, 230, 251, 350, +44, 357, -150, 249, -269, 75, -299, -158, +-330, -362, -379, -441, -288, -372, -46, -119, +250, 237, 499, 472, 574, 495, 388, 314, +6, -57, -338, -423, -439, -562, -292, -442, +-71, -99, 115, 340, 177, 635, 109, 640, +-7, 341, -111, -162, -193, -615, -194, -788, +-78, -642, 115, -238, 341, 287, 451, 723, +348, 878, 59, 682, -293, 210, -549, -337, +-557, -740, -346, -844, -31, -609, 275, -124, +435, 384, 409, 664, 260, 601, 54, 291, +-172, -67, -300, -302, -247, -335, -39, -190, +153, 12, 209, 128, 113, 109, -93, 17, +-292, -85, -372, -128, -277, -84, -24, -4, +286, 76, 452, 151, 443, 150, 308, 71, +77, -14, -181, -90, -376, -143, -454, -137, +-373, -84, -165, 28, 55, 171, 243, 215, +307, 130, 229, -25, 87, -227, -42, -363, +-95, -306, -15, -56, 111, 303, 157, 571, +71, 539, -168, 230, -395, -212, -448, -625, +-313, -755, -17, -493, 342, -14, 517, 490, +455, 809, 253, 726, -13, 282, -204, -263, +-272, -687, -272, -785, -219, -506, -126, -36, +-42, 407, 69, 665, 135, 619, 91, 337, +21, -2, -14, -316, 5, -530, 120, -563, +227, -427, 182, -141, 29, 244, -187, 553, +-349, 630, -332, 439, -172, 47, 7, -334, +165, -502, 261, -415, 274, -127, 212, 194, +35, 318, -201, 199, -358, -54, -323, -312, +-112, -406, 208, -232, 454, 136, 441, 543, +132, 768, -274, 627, -559, 146, -599, -470, +-333, -944, 81, -1017, 427, -650, 628, -23, +635, 606, 371, 965, -37, 906, -447, 520, +-732, 12, -703, -438, -384, -716, 31, -738, +407, -466, 606, 7, 516, 447, 258, 651, +-57, 524, -323, 123, -407, -347, -310, -636, +-129, -578, 113, -163, 308, 413, 306, 840, +129, 865, -155, 455, -393, -190, -432, -816, +-231, -1184, 89, -1075, 374, -454, 503, 435, +428, 1189, 168, 1436, -178, 1069, -445, 270, +-529, -671, -405, -1354, -169, -1412, 95, -850, +328, 52, 440, 933, 359, 1393, 191, 1212, +7, 480, -207, -491, -366, -1265, -378, -1466, +-233, -982, 14, 13, 240, 1067, 299, 1641, +218, 1469, 32, 634, -172, -529, -262, -1492, +-213, -1808, -83, -1364, 86, -326, 218, 872, +249, 1689, 223, 1785, 120, 1121, -85, -18, +-330, -1097, -472, -1644, -392, -1468, -109, -660, +198, 414, 400, 1229, 448, 1423, 304, 972, +38, 115, -233, -778, -390, -1314, -360, -1225, +-188, -548, 4, 401, 186, 1195, 278, 1488, +191, 1117, 15, 198, -134, -877, -188, -1590, +-99, -1608, 54, -936, 109, 136, 77, 1171, +17, 1737, -56, 1573, -103, 728, -103, -428, +-107, -1353, -103, -1639, -41, -1219, 32, -311, +114, 688, 212, 1317, 226, 1305, 75, 714, +-97, -152, -200, -887, -235, -1159, -184, -919, +-102, -303, -33, 454, 97, 1010, 240, 1107, +231, 729, 141, 13, 24, -737, -132, -1124, +-217, -1006, -189, -507, -169, 183, -125, 775, +-26, 988, 50, 790, 159, 294, 305, -293, +333, -669, 189, -692, -70, -431, -387, 12, +-529, 432, -406, 559, -166, 342, 113, -67, +360, -481, 462, -643, 438, -393, 272, 104, +-96, 570, -452, 819, -594, 707, -531, 246, +-268, -338, 142, -813, 460, -975, 550, -695, +432, -140, 156, 439, -151, 880, -372, 924, +-486, 503, -459, -68, -217, -549, 160, -783, +487, -599, 587, -135, 401, 318, -10, 622, +-453, 612, -700, 265, -663, -153, -327, -526, +184, -765, 597, -614, 751, -128, 687, 419, +351, 876, -217, 1007, -721, 641, -932, 8, +-809, -619, -366, -1073, 209, -1090, 656, -643, +878, 5, 772, 662, 346, 1075, -159, 1020, +-518, 606, -702, 15, -655, -616, -376, -979, +-39, -872, 241, -447, 415, 122, 420, 631, +293, 781, 161, 568, 3, 165, -192, -330, +-300, -677, -284, -654, -195, -327, -19, 162, +135, 655, 124, 849, 40, 623, -45, 124, +-139, -509, -99, -980, 81, -996, 141, -602, +92, 50, 17, 744, -103, 1111, -134, 990, +-51, 524, 2, -124, 61, -730, 105, -994, +-31, -844, -154, -406, -142, 160, -166, 605, +-137, 743, 36, 576, 143, 217, 185, -179, +237, -464, 166, -541, 14, -383, -92, -43, +-196, 330, -279, 557, -260, 548, -224, 289, +-158, -154, -16, -604, 108, -850, 212, -721, +347, -228, 392, 412, 276, 938, 115, 1116, +-127, 824, -436, 155, -587, -620, -515, -1148, +-337, -1165, -41, -673, 260, 71, 360, 734, +366, 1012, 372, 778, 259, 242, 114, -299, +1, -607, -228, -527, -440, -194, -471, 151, +-388, 402, -192, 428, 60, 182, 180, -149, +214, -426, 231, -608, 155, -539, 142, -214, +219, 233, 147, 762, -61, 1109, -222, 966, +-328, 433, -373, -312, -333, -1094, -254, -1558, +-123, -1429, 82, -720, 289, 358, 438, 1375, +502, 1850, 409, 1631, 131, 796, -238, -418, +-499, -1470, -538, -1873, -383, -1497, -168, -523, +-14, 615, 115, 1384, 201, 1497, 175, 991, +108, 57, 110, -867, 94, -1258, 63, -1011, +83, -324, 43, 535, -61, 1137, -158, 1160, +-319, 638, -452, -215, -391, -1054, -185, -1428, +113, -1181, 401, -446, 530, 568, 496, 1409, +308, 1678, -80, 1311, -430, 360, -526, -843, +-469, -1660, -297, -1782, -20, -1224, 229, -119, +332, 1027, 281, 1665, 110, 1634, -95, 916, +-228, -205, -218, -1123, -89, -1513, 65, -1313, +205, -529, 249, 485, 104, 1226, -113, 1439, +-285, 1010, -380, 72, -287, -876, -81, -1401, +63, -1321, 169, -605, 245, 454, 194, 1294, +65, 1523, -40, 1051, -108, 48, -71, -988, +2, -1542, 19, -1405, 18, -604, -45, 545, +-226, 1434, -390, 1612, -404, 1040, -236, -23, +93, -1097, 454, -1649, 680, -1429, 668, -532, +377, 665, -101, 1536, -602, 1641, -953, 1016, +-923, -78, -488, -1191, 114, -1719, 628, -1427, +859, -501, 715, 695, 262, 1558, -253, 1600, +-580, 919, -582, -121, -328, -1133, 14, -1581, +298, -1202, 393, -300, 272, 704, -10, 1369, +-373, 1326, -631, 642, -613, -334, -275, -1212, +289, -1502, 783, -962, 925, 53, 680, 1069, +100, 1714, -628, 1516, -1054, 456, -978, -866, +-560, -1863, 44, -2049, 559, -1211, 745, 281, +650, 1699, 359, 2387, -94, 1969, -481, 560, +-618, -1118, -518, -2276, -168, -2417, 281, -1404, +547, 268, 529, 1774, 205, 2466, -323, 2015, +-723, 622, -771, -1010, -455, -2127, 104, -2331, +634, -1498, 845, 41, 720, 1506, 338, 2310, +-233, 2132, -733, 982, -930, -557, -769, -1818, +-308, -2332, 248, -1826, 624, -490, 689, 984, +447, 1951, 31, 2080, -300, 1298, -405, 32, +-315, -1114, -125, -1802, 29, -1695, 63, -809, +56, 290, 64, 1146, 13, 1535, -62, 1238, +-66, 418, -98, -441, -145, -1047, -61, -1201, +49, -788, 40, -136, -8, 391, 13, 682, +63, 649, 144, 378, 200, 107, 113, -49, +-104, -74, -383, -30, -566, -41, -478, -185, +-187, -423, 146, -645, 421, -676, 529, -361, +465, 207, 322, 833, 80, 1344, -249, 1415, +-516, 880, -669, -98, -650, -1185, -354, -1917, +106, -1925, 470, -1200, 583, -29, 461, 1199, +205, 2010, -64, 1995, -304, 1227, -406, 89, +-263, -962, -24, -1503, 137, -1391, 173, -831, +60, -140, -174, 424, -385, 614, -408, 400, +-223, 129, 131, 13, 492, 88, 586, 337, +424, 553, 162, 575, -190, 363, -552, -142, +-742, -818, -687, -1298, -347, -1302, 228, -844, +646, -39, 700, 845, 499, 1498, 72, 1692, +-409, 1231, -614, 281, -534, -673, -291, -1311, +79, -1470, 339, -1069, 386, -284, 370, 493, +213, 903, -152, 771, -512, 280, -684, -210, +-551, -464, -147, -312, 306, 190, 602, 693, +648, 895, 445, 590, 98, -160, -268, -940, +-573, -1368, -650, -1279, -502, -665, -283, 213, +4, 1030, 296, 1507, 438, 1352, 376, 665, +195, -149, 72, -848, 70, -1142, 55, -870, +-75, -290, -326, 269, -601, 566, -680, 396, +-472, -81, -78, -449, 397, -520, 744, -235, +825, 371, 644, 946, 158, 1148, -434, 826, +-826, 61, -975, -824, -817, -1488, -241, -1592, +439, -972, 865, 61, 937, 1048, 500, 1631, +-192, 1518, -631, 728, -819, -289, -736, -1123, +-250, -1472, 332, -1110, 730, -219, 879, 745, +615, 1324, -4, 1211, -651, 534, -1121, -424, +-1168, -1296, -642, -1554, 162, -1035, 885, -37, +1238, 1015, 1049, 1639, 424, 1564, -352, 848, +-964, -210, -1145, -1141, -856, -1568, -261, -1393, +384, -675, 745, 291, 706, 1030, 384, 1292, +-127, 1028, -539, 273, -595, -513, -360, -909, +59, -868, 423, -377, 480, 294, 292, 731, +-28, 800, -447, 451, -716, -170, -587, -673, +-166, -826, 347, -677, 667, -216, 594, 393, +273, 776, -166, 842, -637, 527, -828, -78, +-557, -546, -27, -742, 480, -590, 785, -93, +811, 406, 513, 723, -118, 788, -846, 402, +-1283, -368, -1217, -1032, -617, -1224, 292, -967, +1083, -274, 1396, 689, 1148, 1542, 522, 1830, +-285, 1315, -979, 274, -1259, -888, -1064, -1732, +-594, -1907, -31, -1448, 539, -470, 890, 703, +848, 1538, 448, 1719, -116, 1238, -521, 328, +-619, -595, -454, -1112, -102, -1108, 220, -650, +344, 126, 315, 765, 177, 907, -126, 530, +-505, -180, -713, -807, -613, -1096, -246, -996, +276, -373, 821, 591, 1060, 1391, 748, 1706, +52, 1394, -640, 438, -1003, -732, -948, -1552, +-589, -1829, -83, -1533, 407, -705, 662, 358, +612, 1243, 363, 1578, -97, 1316, -557, 722, +-629, -11, -367, -667, 47, -959, 505, -789, +730, -331, 535, 95, 13, 289, -593, 190, +-1034, -89, -1089, -302, -730, -343, -78, -177, +679, 184, 1277, 615, 1439, 915, 991, 872, +95, 503, -863, -122, -1530, -830, -1581, -1284, +-992, -1319, -158, -904, 641, -128, 1213, 679, +1213, 1222, 687, 1361, 11, 1043, -629, 378, +-891, -284, -643, -736, -261, -898, 145, -742, +476, -466, 372, -160, -67, 119, -400, 135, +-535, 50, -405, 178, 29, 430, 394, 653, +541, 790, 569, 627, 338, 126, -127, -482, +-533, -1075, -710, -1428, -630, -1183, -351, -456, +31, 414, 375, 1232, 489, 1659, 314, 1395, +27, 611, -179, -398, -232, -1257, -108, -1526, +133, -1156, 311, -407, 208, 451, -82, 1030, +-378, 1079, -698, 750, -847, 249, -545, -413, +64, -909, 684, -893, 1157, -501, 1180, 56, +615, 587, -196, 811, -954, 671, -1365, 295, +-1221, -219, -756, -585, -64, -505, 747, -289, +1142, -130, 1006, 91, 641, 103, 39, -74, +-668, -72, -928, 38, -686, 214, -235, 557, +241, 808, 443, 640, 247, 116, -119, -638, +-462, -1342, -602, -1521, -335, -1140, 169, -299, +630, 912, 981, 1865, 983, 2090, 400, 1594, +-501, 433, -1249, -1035, -1582, -2129, -1351, -2464, +-528, -1928, 493, -553, 1282, 1116, 1674, 2309, +1406, 2648, 572, 1974, -358, 493, -1147, -1130, +-1606, -2254, -1421, -2507, -714, -1879, 73, -594, +757, 955, 1093, 2080, 906, 2359, 495, 1830, +71, 673, -323, -715, -473, -1781, -402, -2113, +-295, -1638, -134, -662, -84, 378, -336, 1153, +-564, 1519, -443, 1333, -65, 723, 514, 88, +1140, -469, 1362, -839, 923, -861, 93, -670, +-868, -390, -1680, -124, -1890, 65, -1455, 225, +-592, 409, 539, 556, 1590, 572, 2119, 472, +1970, 213, 1139, -110, -198, -326, -1461, -517, +-2207, -574, -2317, -481, -1611, -340, -369, -90, +831, 175, 1775, 372, 2149, 506, 1710, 511, +815, 384, -213, 194, -1254, 80, -1804, -27, +-1660, -208, -1164, -426, -419, -641, 463, -757, +1021, -692, 1127, -333, 1045, 277, 798, 882, +339, 1342, -214, 1423, -732, 965, -1053, 110, +-1104, -900, -919, -1740, -491, -2008, 105, -1529, +674, -507, 992, 731, 1003, 1808, 803, 2232, +389, 1889, -138, 962, -673, -333, -1097, -1556, +-1182, -2238, -916, -2179, -459, -1370, 171, -55, +807, 1300, 1085, 2138, 1018, 2150, 715, 1427, +109, 216, -477, -1035, -748, -1741, -860, -1726, +-736, -1138, -375, -170, -146, 802, 48, 1250, +324, 1059, 300, 521, 139, -167, 250, -730, +345, -791, 348, -353, 437, 273, 344, 758, +-102, 898, -661, 572, -1222, -124, -1568, -898, +-1234, -1438, -324, -1417, 729, -757, 1674, 315, +2117, 1418, 1756, 2047, 774, 1934, -493, 1064, +-1741, -303, -2495, -1594, -2333, -2344, -1377, -2261, +31, -1271, 1551, 182, 2549, 1476, 2526, 2261, +1545, 2287, -2, 1384, -1583, -31, -2530, -1339, +-2481, -2164, -1525, -2120, 0, -1189, 1494, 78, +2322, 1236, 2164, 1957, 1124, 1894, -351, 1085, +-1577, -109, -2061, -1312, -1757, -2007, -806, -1854, +399, -969, 1275, 326, 1535, 1561, 1209, 2161, +479, 1838, -390, 725, -1094, -671, -1345, -1705, +-1004, -2028, -201, -1606, 574, -571, 1009, 618, +1027, 1544, 476, 1947, -423, 1609, -1055, 646, +-1143, -517, -759, -1449, 5, -1920, 782, -1770, +1146, -875, 1034, 390, 496, 1492, -312, 2081, +-975, 1899, -1218, 1031, -1033, -138, -426, -1283, +337, -2074, 777, -2071, 814, -1332, 578, -336, +96, 830, -353, 1844, -475, 2161, -337, 1811, +-149, 962, 56, -267, 230, -1454, 202, -2152, +-7, -2171, -300, -1497, -531, -264, -508, 1083, +-291, 2090, 13, 2346, 396, 1679, 631, 430, +553, -987, 378, -2040, 180, -2180, -175, -1448, +-495, -170, -630, 1178, -715, 2012, -613, 1994, +-249, 1093, 94, -340, 299, -1614, 455, -2218, +533, -1977, 550, -877, 471, 736, 205, 2117, +-154, 2722, -576, 2281, -923, 839, -902, -998, +-537, -2482, -100, -3086, 308, -2544, 636, -1062, +678, 869, 491, 2527, 290, 3192, -8, 2705, +-408, 1307, -643, -602, -621, -2335, -440, -3135, +-92, -2688, 396, -1245, 654, 676, 545, 2230, +288, 2755, -130, 2230, -670, 865, -972, -829, +-873, -2090, -506, -2458, 112, -1843, 863, -518, +1364, 1025, 1312, 2134, 758, 2387, -48, 1763, +-910, 425, -1566, -1091, -1750, -2136, -1436, -2411, +-691, -1877, 375, -711, 1386, 686, 1935, 1754, +1902, 2229, 1281, 2067, 146, 1263, -1050, 158, +-1873, -874, -2053, -1623, -1496, -1903, -581, -1697, +352, -1122, 1176, -423, 1534, 327, 1202, 1121, +531, 1715, -103, 1947, -583, 1808, -719, 1215, +-500, 148, -223, -1119, -50, -2149, 1, -2690, +-122, -2543, -365, -1603, -539, -101, -407, 1534, +60, 2833, 614, 3344, 997, 2849, 1113, 1470, +827, -403, 93, -2180, -815, -3272, -1456, -3424, +-1585, -2588, -1259, -913, -536, 1003, 421, 2473, +1248, 3228, 1655, 3099, 1552, 1993, 982, 278, +28, -1374, -994, -2484, -1652, -2846, -1779, -2373, +-1373, -1233, -517, 136, 441, 1372, 1144, 2139, +1459, 2226, 1364, 1709, 863, 787, 206, -288, +-403, -1221, -977, -1737, -1355, -1703, -1359, -1208, +-1066, -436, -510, 328, 286, 911, 1025, 1223, +1488, 1206, 1620, 945, 1281, 538, 448, 79, +-667, -382, -1704, -922, -2237, -1384, -2012, -1479, +-1088, -1197, 306, -575, 1723, 518, 2491, 1740, +2301, 2399, 1348, 2284, -162, 1407, -1735, -85, +-2641, -1666, -2598, -2881, -1710, -3223, -125, -2299, +1695, -544, 2847, 1321, 2790, 2907, 1707, 3632, +11, 3002, -1797, 1317, -3017, -724, -3018, -2506, +-1785, -3435, 45, -3175, 1769, -1851, 2862, 31, +2863, 1769, 1686, 2772, -128, 2803, -1799, 1882, +-2739, 382, -2628, -1073, -1526, -1918, 107, -1931, +1570, -1312, 2328, -323, 2173, 672, 1189, 1107, +-235, 918, -1518, 429, -2086, -181, -1781, -608, +-852, -515, 319, -103, 1242, 337, 1561, 735, +1315, 768, 686, 354, -224, -174, -1085, -784, +-1406, -1224, -1232, -1112, -804, -565, -40, 199, +798, 978, 1188, 1508, 1121, 1573, 768, 951, +168, -182, -419, -1184, -814, -1689, -1108, -1766, +-1159, -1196, -781, -12, -96, 1127, 675, 1811, +1258, 1879, 1339, 1320, 915, 428, 182, -631, +-651, -1598, -1244, -2022, -1368, -1788, -1047, -1095, +-402, -65, 332, 1083, 967, 1959, 1340, 2294, +1200, 1943, 542, 958, -351, -352, -1116, -1664, +-1417, -2495, -1102, -2485, -389, -1734, 344, -472, +887, 928, 1066, 1969, 825, 2422, 293, 2157, +-358, 1265, -883, 163, -1029, -899, -729, -1789, +-135, -2142, 483, -1806, 897, -1042, 913, -93, +393, 881, -359, 1548, -805, 1666, -880, 1313, +-699, 711, -188, 3, 463, -642, 830, -938, +781, -895, 428, -734, -149, -426, -709, -120, +-852, -28, -536, -20, -35, 59, 396, 232, +645, 537, 549, 894, 65, 1039, -472, 855, +-760, 386, -744, -375, -401, -1189, 160, -1714, +762, -1746, 1178, -1208, 1070, -241, 372, 912, +-562, 1876, -1337, 2258, -1654, 1959, -1288, 1012, +-387, -317, 633, -1528, 1441, -2223, 1716, -2252, +1304, -1618, 425, -522, -577, 718, -1435, 1763, +-1800, 2212, -1452, 1898, -512, 1135, 634, 172, +1476, -842, 1652, -1659, 1104, -1970, 140, -1602, +-777, -846, -1352, -50, -1434, 817, -971, 1556, +-145, 1761, 702, 1442, 1216, 780, 1245, -93, +836, -860, 124, -1355, -623, -1566, -1072, -1324, +-1050, -689, -725, 4, -317, 694, 75, 1274, +395, 1476, 582, 1318, 602, 862, 528, 85, +427, -711, 225, -1234, -71, -1484, -310, -1417, +-537, -900, -791, -56, -868, 743, -729, 1255, +-442, 1432, 81, 1235, 762, 694, 1263, -22, +1385, -622, 1108, -929, 402, -966, -558, -868, +-1340, -639, -1723, -250, -1631, 114, -1003, 351, +-5, 547, 953, 713, 1577, 851, 1762, 806, +1385, 474, 472, 23, -652, -413, -1529, -813, +-1757, -1072, -1316, -1038, -516, -671, 393, -177, +1131, 234, 1309, 630, 889, 1023, 205, 1059, +-458, 746, -882, 416, -879, 19, -486, -454, +84, -723, 592, -781, 838, -729, 665, -548, +107, -290, -581, -32, -1075, 209, -1153, 408, +-781, 563, -39, 629, 837, 633, 1507, 647, +1668, 533, 1174, 167, 179, -296, -991, -805, +-1970, -1317, -2372, -1520, -1970, -1234, -810, -542, +773, 412, 2203, 1309, 2972, 1904, 2770, 2039, +1565, 1529, -293, 503, -2159, -701, -3418, -1738, +-3562, -2182, -2430, -1933, -483, -1174, 1588, -78, +3232, 966, 3861, 1485, 3098, 1491, 1279, 1164, +-870, 589, -2711, 36, -3681, -323, -3403, -513, +-1941, -488, 95, -411, 1910, -469, 2959, -646, +2972, -834, 1994, -810, 436, -416, -1151, 283, +-2234, 1131, -2449, 1841, -1760, 2053, -481, 1572, +894, 485, 1787, -925, 1809, -2133, 1090, -2730, +-38, -2549, -1203, -1488, -1838, 142, -1601, 1683, +-680, 2677, 519, 2799, 1624, 2013, 2204, 713, +1914, -617, 813, -1607, -650, -2012, -2015, -1852, +-2838, -1296, -2719, -623, -1602, -80, 124, 386, +1864, 884, 3052, 1269, 3305, 1539, 2497, 1698, +857, 1482, -1074, 749, -2686, -389, -3536, -1682, +-3342, -2649, -2061, -2928, -130, -2373, 1779, -1004, +3129, 749, 3445, 2318, 2620, 3379, 1052, 3565, +-702, 2640, -2118, 922, -2767, -1030, -2556, -2822, +-1675, -3892, -389, -3740, 875, -2452, 1627, -506, +1760, 1554, 1437, 3137, 818, 3734, 161, 3164, +-301, 1726, -582, -90, -770, -1738, -918, -2742, +-1000, -2861, -886, -2136, -536, -914, -46, 359, +593, 1359, 1226, 1843, 1478, 1747, 1272, 1217, +809, 474, -11, -296, -1088, -839, -1842, -1047, +-1983, -987, -1551, -627, -515, -101, 862, 280, +1981, 537, 2407, 658, 1988, 509, 796, 185, +-733, -154, -2028, -480, -2673, -698, -2386, -699, +-1191, -446, 445, 52, 1933, 669, 2752, 1186, +2599, 1414, 1533, 1163, -43, 475, -1609, -470, +-2636, -1530, -2762, -2299, -2009, -2322, -726, -1619, +702, -368, 1950, 1193, 2674, 2529, 2604, 3202, +1721, 3063, 378, 1981, -979, 157, -2164, -1786, +-2865, -3316, -2690, -4044, -1761, -3605, -434, -2043, +1132, 188, 2473, 2409, 3033, 3916, 2776, 4298, +1792, 3468, 180, 1641, -1422, -582, -2511, -2560, +-3026, -3737, -2736, -3785, -1629, -2823, -212, -1227, +1170, 584, 2319, 2057, 2801, 2817, 2439, 2873, +1486, 2257, 266, 1090, -885, -153, -1703, -1156, +-2088, -1814, -2041, -1992, -1647, -1734, -1029, -1173, +-185, -403, 769, 299, 1583, 801, 2139, 1266, +2331, 1560, 1951, 1386, 1034, 950, -193, 390, +-1535, -414, -2718, -1176, -3283, -1522, -2886, -1466, +-1591, -1013, 260, -183, 2179, 703, 3568, 1254, +3877, 1342, 2904, 955, 1057, 187, -1034, -639, +-2876, -1085, -3901, -996, -3599, -540, -2177, 134, +-253, 841, 1694, 1154, 3098, 905, 3373, 388, +2594, -208, 1209, -865, -453, -1267, -1891, -1165, +-2578, -731, -2464, -171, -1789, 454, -742, 942, +470, 1145, 1531, 1133, 2072, 940, 1976, 522, +1414, -7, 529, -551, -506, -1059, -1371, -1405, +-1784, -1448, -1739, -1170, -1287, -611, -493, 137, +454, 930, 1249, 1627, 1650, 2027, 1567, 1906, +1085, 1281, 351, 264, -434, -926, -1053, -1905, +-1359, -2380, -1340, -2222, -1076, -1446, -575, -360, +104, 672, 719, 1487, 1114, 1949, 1273, 1903, +1143, 1479, 719, 896, 179, 261, -351, -368, +-799, -984, -1161, -1548, -1376, -1927, -1233, -2022, +-667, -1702, 6, -870, 646, 366, 1313, 1716, +1682, 2830, 1453, 3255, 869, 2719, 139, 1368, +-725, -428, -1484, -2245, -1791, -3504, -1536, -3701, +-875, -2747, -52, -1030, 770, 909, 1387, 2510, +1578, 3257, 1297, 2950, 730, 1841, 6, 339, +-697, -1054, -1160, -1902, -1301, -2071, -1100, -1635, +-582, -789, 34, 71, 534, 585, 840, 715, +903, 651, 737, 456, 419, 192, 25, 85, +-321, 232, -508, 344, -540, 245, -480, 26, +-386, -291, -308, -591, -194, -675, 11, -588, +277, -259, 542, 335, 843, 772, 1023, 755, +797, 439, 124, -88, -707, -727, -1441, -1122, +-1874, -992, -1675, -344, -745, 607, 548, 1442, +1740, 1862, 2459, 1661, 2396, 725, 1536, -620, +181, -1814, -1347, -2489, -2616, -2437, -3074, -1654, +-2525, -316, -1264, 1150, 425, 2206, 2087, 2645, +3039, 2564, 3003, 1860, 2212, 614, 841, -723, +-786, -1907, -2087, -2752, -2706, -2901, -2626, -2365, +-1931, -1280, -820, 194, 425, 1608, 1491, 2589, +2032, 2990, 2042, 2636, 1794, 1648, 1249, 380, +388, -942, -490, -2011, -1209, -2485, -1782, -2411, +-2046, -1884, -1882, -989, -1310, -12, -417, 839, +599, 1480, 1476, 1781, 2097, 1791, 2308, 1601, +1976, 1227, 1185, 727, 111, 101, -1057, -710, +-1986, -1565, -2404, -2314, -2342, -2799, -1904, -2677, +-1024, -1757, 230, -258, 1466, 1553, 2337, 3279, +2795, 4307, 2709, 4192, 1906, 2919, 539, 733, +-967, -1873, -2303, -4084, -3214, -5100, -3375, -4707, +-2621, -3070, -1146, -537, 700, 2117, 2425, 3947, +3438, 4534, 3452, 3933, 2611, 2382, 1147, 354, +-597, -1447, -2045, -2533, -2803, -2818, -2910, -2472, +-2398, -1730, -1300, -926, 70, -265, 1254, 338, +2050, 928, 2342, 1434, 2066, 1912, 1353, 2218, +466, 2023, -478, 1261, -1312, 132, -1746, -1215, +-1717, -2427, -1382, -3015, -831, -2815, -133, -1906, +542, -416, 1009, 1226, 1247, 2450, 1332, 2955, +1229, 2713, 812, 1742, 133, 347, -601, -945, +-1174, -1813, -1473, -2141, -1430, -1904, -1054, -1308, +-346, -568, 473, 194, 1074, 771, 1359, 1045, +1348, 1204, 925, 1243, 163, 997, -545, 563, +-929, 94, -997, -398, -797, -851, -410, -1178, +18, -1236, 372, -936, 535, -410, 407, 124, +136, 595, -125, 904, -330, 912, -307, 648, +80, 330, 522, 151, 768, 127, 808, 101, +492, -25, -277, -286, -1105, -693, -1637, -1168, +-1767, -1440, -1285, -1224, -160, -461, 1215, 646, +2342, 1788, 2811, 2559, 2362, 2561, 1079, 1622, +-646, -8, -2318, -1762, -3355, -3007, -3349, -3307, +-2298, -2534, -546, -936, 1423, 928, 2952, 2446, +3572, 3175, 3184, 2900, 1914, 1800, 67, 281, +-1705, -1248, -2819, -2287, -3118, -2462, -2628, -1932, +-1461, -1000, -39, 77, 1172, 871, 1997, 1116, +2289, 1011, 1926, 773, 1162, 532, 415, 456, +-160, 550, -650, 573, -970, 357, -1126, -135, +-1313, -875, -1533, -1685, -1451, -2144, -934, -1963, +-88, -1136, 963, 194, 2031, 1664, 2751, 2753, +2820, 3125, 2083, 2610, 604, 1294, -1224, -396, +-2854, -2005, -3790, -3200, -3677, -3532, -2426, -2801, +-373, -1315, 1789, 507, 3378, 2220, 3985, 3252, +3468, 3279, 1877, 2369, -260, 910, -2177, -629, +-3298, -1870, -3348, -2479, -2290, -2278, -597, -1512, +1033, -550, 2113, 375, 2329, 987, 1617, 1130, +413, 953, -694, 628, -1325, 383, -1269, 322, +-577, 294, 368, 249, 1115, 167, 1380, -141, +1007, -615, 26, -1015, -1100, -1248, -1815, -1208, +-1877, -773, -1378, -50, -380, 792, 872, 1491, +1909, 1771, 2303, 1561, 1995, 881, 1152, -89, +21, -949, -1144, -1505, -1980, -1670, -2147, -1316, +-1688, -525, -880, 361, 74, 1022, 922, 1240, +1363, 1011, 1358, 459, 1081, -276, 661, -848, +223, -875, -122, -454, -331, 163, -476, 781, +-572, 1126, -678, 1019, -766, 444, -752, -491, +-564, -1383, -238, -1850, 219, -1745, 758, -1015, +1186, 197, 1313, 1412, 1089, 2233, 578, 2415, +-94, 1831, -715, 652, -1098, -701, -1198, -1810, +-1079, -2341, -779, -2203, -311, -1465, 174, -343, +573, 768, 837, 1521, 971, 1773, 969, 1490, +818, 846, 471, 154, 82, -381, -333, -708, +-855, -723, -1207, -478, -1138, -271, -920, -241, +-669, -262, -114, -310, 599, -386, 1054, -315, +1230, -40, 1253, 268, 1050, 626, 533, 1001, +-148, 1127, -754, 953, -1169, 637, -1386, 147, +-1269, -566, -861, -1294, -312, -1721, 332, -1766, +985, -1443, 1335, -727, 1295, 292, 982, 1336, +467, 2186, -122, 2578, -567, 2205, -823, 1226, +-942, 17, -861, -1360, -591, -2495, -271, -2818, +29, -2393, 314, -1481, 488, -193, 441, 1056, +369, 1888, 459, 2292, 608, 2193, 616, 1559, +497, 741, 185, -30, -428, -744, -1149, -1360, +-1562, -1801, -1570, -1996, -1162, -1866, -237, -1330, +960, -358, 1906, 856, 2282, 1987, 1962, 2681, +975, 2659, -333, 1852, -1509, 507, -2180, -958, +-2108, -2068, -1426, -2503, -419, -2232, 654, -1356, +1489, -150, 1804, 841, 1586, 1327, 871, 1327, +-73, 900, -861, 322, -1336, 5, -1387, -2, +-862, 155, -82, 392, 495, 510, 836, 222, +960, -445, 747, -1142, 293, -1562, -191, -1622, +-614, -1178, -846, -159, -773, 1028, -489, 1839, +-70, 2110, 386, 1795, 680, 937, 695, -126, +626, -1003, 534, -1454, 301, -1386, -73, -1025, +-448, -624, -808, -195, -1062, 145, -1023, 182, +-667, 144, -132, 311, 471, 591, 1041, 863, +1387, 1094, 1333, 1107, 907, 781, 282, 136, +-401, -690, -1019, -1412, -1363, -1760, -1323, -1698, +-972, -1253, -517, -481, -52, 432, 409, 1186, +856, 1610, 1136, 1716, 1172, 1500, 1047, 941, +807, 283, 360, -266, -259, -781, -853, -1266, +-1286, -1539, -1524, -1611, -1518, -1484, -1214, -1007, +-605, -214, 256, 698, 1198, 1590, 1951, 2237, +2350, 2431, 2220, 2082, 1469, 1204, 228, -53, +-1175, -1388, -2393, -2493, -3010, -3044, -2804, -2825, +-1851, -1890, -418, -486, 1130, 1044, 2371, 2296, +2998, 2962, 2816, 2872, 1841, 2138, 470, 1002, +-844, -351, -1906, -1565, -2462, -2246, -2268, -2407, +-1489, -2123, -534, -1396, 378, -467, 1108, 398, +1505, 1178, 1451, 1715, 1036, 1868, 479, 1752, +22, 1365, -246, 648, -355, -213, -417, -1017, +-445, -1617, -420, -1885, -463, -1750, -612, -1251, +-621, -480, -380, 403, -35, 1213, 395, 1701, +868, 1700, 1109, 1346, 1048, 806, 789, 13, +279, -812, -457, -1256, -1001, -1296, -1118, -1104, +-946, -650, -584, -11, 2, 513, 535, 752, +657, 705, 421, 370, 146, -30, -106, -260, +-309, -323, -212, -206, 200, 131, 595, 480, +773, 651, 738, 633, 381, 393, -312, -76, +-1005, -625, -1394, -1144, -1386, -1448, -1012, -1342, +-319, -845, 551, -1, 1365, 1103, 1753, 2036, +1617, 2387, 1102, 2044, 303, 1096, -630, -279, +-1304, -1712, -1514, -2686, -1334, -2782, -851, -1996, +-214, -696, 317, 713, 609, 1879, 687, 2393, +629, 2096, 550, 1209, 529, 190, 536, -635, +477, -1141, 211, -1195, -236, -833, -722, -424, +-1051, -193, -1125, -130, -949, -182, -552, -250, +69, -149, 714, 197, 1159, 710, 1333, 1156, +1142, 1284, 571, 1041, -146, 441, -761, -435, +-1109, -1221, -1022, -1660, -594, -1629, -89, -1066, +363, -219, 597, 600, 515, 1254, 243, 1476, +-62, 1170, -339, 640, -434, 81, -326, -470, +-45, -747, 348, -701, 721, -534, 883, -295, +747, -95, 310, -80, -317, -71, -936, 17, +-1371, 86, -1433, 219, -998, 490, -202, 650, +669, 539, 1417, 238, 1795, -142, 1548, -502, +833, -710, 0, -714, -780, -463, -1348, -7, +-1404, 413, -1047, 594, -563, 578, -26, 377, +472, -24, 676, -420, 612, -595, 431, -531, +225, -201, 119, 267, 181, 625, 360, 779, +514, 680, 432, 236, 46, -366, -512, -859, +-1097, -1113, -1496, -1003, -1419, -504, -872, 181, +-10, 852, 994, 1252, 1802, 1207, 2055, 821, +1801, 211, 1103, -538, 14, -1047, -1136, -1096, +-1892, -857, -2125, -446, -1869, 98, -1132, 508, +-104, 622, 893, 509, 1639, 282, 1957, 94, +1725, 53, 1070, 66, 220, 94, -623, 131, +-1215, 53, -1418, -180, -1235, -422, -774, -619, +-199, -709, 283, -555, 598, -169, 661, 299, +539, 772, 419, 1103, 330, 1096, 204, 710, +148, 85, 119, -570, -23, -1025, -190, -1197, +-362, -1052, -601, -562, -722, 91, -565, 607, +-256, 894, 92, 923, 488, 677, 813, 276, +901, -79, 693, -308, 317, -370, -102, -305, +-461, -264, -688, -324, -685, -379, -509, -314, +-213, -132, 118, 107, 314, 408, 327, 653, +318, 679, 272, 449, 77, 90, -84, -252, +-45, -488, 29, -568, 48, -446, 119, -178, +142, 100, -33, 239, -243, 217, -361, 81, +-375, -65, -254, -122, -3, -48, 241, 137, +426, 343, 467, 420, 312, 312, 76, 44, +-85, -287, -186, -560, -224, -645, -158, -494, +-37, -173, 38, 208, 20, 529, -33, 641, +-53, 517, -105, 217, -174, -148, -98, -422, +124, -450, 256, -267, 305, -11, 384, 238, +383, 385, 139, 318, -164, 55, -385, -301, +-538, -556, -553, -603, -344, -440, -39, -59, +219, 467, 414, 908, 529, 1065, 496, 833, +325, 277, 89, -397, -136, -992, -302, -1345, +-379, -1221, -345, -671, -205, 15, -60, 709, +50, 1243, 124, 1334, 182, 1026, 197, 472, +183, -232, 129, -848, 43, -1122, -53, -1036, +-68, -661, -11, -110, 16, 416, 0, 726, +32, 704, 60, 383, -40, 9, -183, -281, +-238, -392, -233, -194, -160, 211, 41, 555, +318, 637, 503, 336, 530, -259, 370, -876, +76, -1231, -236, -1138, -432, -529, -513, 370, +-444, 1187, -224, 1606, 43, 1443, 219, 765, +307, -139, 361, -996, 334, -1482, 183, -1390, +21, -845, -30, -143, -48, 520, -129, 949, +-159, 971, -91, 648, -83, 229, -143, -142, +-58, -373, 65, -410, 65, -280, 62, -80, +140, 101, 115, 150, 12, 52, -25, -113, +-1, -280, 63, -363, 194, -241, 315, 27, +313, 335, 137, 607, -193, 676, -554, 449, +-792, 80, -803, -313, -500, -663, 49, -813, +690, -662, 1226, -316, 1445, 134, 1171, 564, +500, 804, -348, 762, -1178, 492, -1744, 71, +-1689, -387, -1007, -737, -101, -832, 738, -658, +1426, -286, 1685, 197, 1302, 697, 574, 990, +-108, 906, -666, 508, -996, -39, -947, -643, +-607, -1100, -195, -1170, 137, -822, 249, -229, +193, 450, 120, 1015, 77, 1273, 37, 1138, +154, 629, 430, -102, 629, -738, 618, -1073, +442, -1081, 41, -801, -532, -336, -1005, 115, +-1157, 430, -965, 592, -461, 655, 219, 656, +823, 582, 1155, 399, 1155, 114, 837, -267, +328, -650, -191, -893, -558, -911, -715, -713, +-628, -293, -371, 259, -121, 734, -33, 952, +-24, 889, -33, 588, -80, 145, -74, -281, +157, -515, 551, -538, 870, -415, 963, -228, +786, -68, 316, -4, -360, -34, -1006, -111, +-1397, -133, -1424, -56, -1022, 113, -292, 343, +521, 607, 1191, 765, 1585, 690, 1512, 360, +1022, -156, 330, -715, -411, -1146, -1024, -1343, +-1246, -1159, -1106, -565, -787, 254, -311, 1052, +242, 1620, 602, 1731, 679, 1314, 635, 514, +542, -444, 369, -1268, 171, -1655, 14, -1567, +-89, -1095, -193, -367, -282, 406, -340, 998, +-323, 1274, -227, 1183, -119, 824, -85, 328, +-36, -186, 101, -574, 250, -711, 320, -662, +366, -518, 426, -329, 425, -154, 282, -17, +48, 99, -158, 185, -316, 313, -504, 470, +-635, 540, -565, 478, -329, 309, -48, 7, +260, -348, 517, -602, 680, -679, 728, -564, +640, -269, 433, 51, 199, 293, -122, 413, +-534, 397, -814, 281, -848, 145, -776, 24, +-555, -38, -95, -36, 409, -21, 780, -40, +1054, -86, 1143, -186, 909, -302, 432, -332, +-151, -227, -765, -23, -1171, 236, -1194, 458, +-893, 524, -375, 365, 266, 91, 770, -202, +983, -445, 920, -503, 641, -313, 207, -18, +-196, 260, -428, 463, -452, 477, -323, 236, +-162, -111, -40, -413, 47, -569, 35, -527, +-63, -310, -58, 20, 77, 378, 143, 616, +167, 673, 278, 558, 371, 305, 284, -54, +145, -419, 6, -681, -195, -730, -433, -582, +-537, -339, -440, -54, -155, 240, 237, 424, +569, 505, 675, 570, 548, 607, 270, 533, +-121, 335, -504, -6, -659, -458, -522, -882, +-195, -1105, 209, -1035, 614, -635, 815, -14, +672, 622, 245, 1040, -257, 1134, -682, 918, +-866, 498, -692, 24, -216, -339, 327, -529, +734, -586, 903, -570, 772, -494, 332, -412, +-236, -329, -641, -169, -730, 62, -574, 272, +-230, 490, 225, 717, 630, 866, 761, 868, +550, 689, 125, 268, -297, -340, -617, -1017, +-732, -1578, -538, -1755, -82, -1391, 427, -583, +807, 488, 945, 1519, 808, 2142, 417, 2124, +-143, 1472, -687, 375, -995, -791, -1023, -1655, +-773, -1984, -265, -1689, 358, -915, 841, -20, +1062, 709, 1019, 1093, 760, 1058, 330, 692, +-131, 259, -485, -30, -699, -96, -796, 24, +-732, 193, -512, 219, -185, 33, 121, -338, +351, -791, 556, -1138, 773, -1120, 866, -672, +794, 58, 611, 842, 260, 1490, -283, 1777, +-835, 1491, -1218, 653, -1305, -366, -1019, -1244, +-448, -1771, 248, -1757, 968, -1161, 1498, -240, +1634, 662, 1323, 1245, 645, 1365, -276, 1062, +-1083, 504, -1475, -116, -1407, -562, -943, -733, +-202, -636, 505, -350, 933, -18, 1038, 226, +805, 332, 342, 256, -82, 48, -323, -182, +-375, -329, -217, -337, 100, -180, 335, 67, +349, 324, 144, 514, -176, 551, -526, 417, +-727, 181, -620, -134, -231, -463, 260, -692, +748, -715, 1078, -547, 1045, -254, 669, 120, +129, 509, -456, 744, -907, 746, -996, 573, +-722, 288, -305, -93, 145, -437, 517, -633, +678, -657, 561, -498, 312, -188, 80, 130, +-71, 363, -152, 464, -113, 388, 19, 145, +108, -108, 101, -254, 79, -249, 36, -73, +-82, 221, -213, 472, -270, 522, -300, 284, +-260, -166, -88, -682, 182, -1039, 468, -1019, +736, -556, 843, 160, 708, 883, 402, 1380, +-38, 1425, -625, 940, -1132, 125, -1258, -737, +-989, -1345, -476, -1514, 233, -1204, 980, -495, +1454, 362, 1442, 1020, 1060, 1283, 499, 1129, +-162, 663, -853, 47, -1268, -513, -1216, -849, +-866, -875, -379, -654, 246, -294, 766, 110, +910, 441, 786, 577, 593, 525, 319, 339, +41, 95, -118, -146, -193, -294, -286, -345, +-307, -323, -264, -245, -246, -109, -250, 61, +-178, 246, -24, 378, 176, 404, 389, 311, +554, 124, 588, -148, 486, -416, 294, -576, +17, -542, -295, -306, -483, 43, -506, 361, +-452, 599, -356, 660, -103, 478, 233, 149, +492, -174, 602, -436, 593, -593, 426, -598, +119, -411, -193, -91, -368, 234, -404, 459, +-336, 553, -140, 448, 114, 188, 295, -74, +357, -230, 283, -252, 113, -153, -84, -60, +-212, -44, -246, -100, -129, -175, 66, -229, +242, -189, 353, -15, 391, 270, 312, 526, +145, 624, -78, 508, -319, 191, -461, -268, +-433, -689, -273, -902, -15, -767, 285, -314, +516, 220, 549, 618, 438, 821, 275, 743, +90, 393, -136, -40, -294, -361, -334, -533, +-285, -522, -181, -346, -52, -118, 34, 44, +99, 148, 195, 215, 282, 222, 311, 182, +332, 179, 324, 160, 226, 71, 5, -66, +-242, -215, -419, -325, -451, -289, -366, -136, +-167, 39, 139, 214, 454, 345, 617, 292, +555, 65, 297, -194, -28, -357, -255, -379, +-339, -217, -304, 86, -126, 410, 88, 615, +214, 581, 229, 256, 190, -194, 87, -594, +-24, -853, -125, -857, -171, -507, -96, 45, +77, 586, 254, 1001, 377, 1151, 379, 873, +214, 266, -34, -413, -265, -947, -420, -1203, +-411, -1070, -218, -570, 90, 106, 350, 674, +507, 942, 520, 874, 368, 575, 74, 161, +-183, -215, -319, -402, -365, -357, -296, -225, +-101, -154, 100, -181, 228, -254, 334, -319, +363, -286, 272, -91, 203, 254, 149, 641, +-27, 908, -288, 859, -434, 489, -468, -63, +-349, -675, -25, -1179, 406, -1278, 743, -898, +871, -226, 701, 508, 275, 1103, -253, 1326, +-717, 1081, -943, 462, -849, -271, -478, -844, +110, -1094, 730, -991, 1116, -536, 1080, 89, +690, 605, 107, 828, -455, 735, -832, 380, +-874, -93, -570, -477, -88, -587, 377, -416, +701, -90, 730, 227, 414, 401, -64, 325, +-442, 55, -532, -211, -270, -304, 189, -202, +621, 27, 795, 269, 606, 386, 100, 228, +-495, -137, -948, -457, -1024, -546, -640, -395, +35, -28, 712, 455, 1171, 797, 1242, 780, +844, 441, 129, -96, -566, -630, -953, -921, +-918, -860, -567, -540, -60, -55, 365, 453, +575, 772, 550, 822, 380, 689, 133, 398, +-52, 19, -109, -339, -98, -599, -44, -747, +57, -739, 110, -536, 57, -194, -2, 164, +-19, 505, -15, 769, 35, 860, 50, 746, +10, 465, -43, 14, -56, -470, -24, -826, +113, -1037, 245, -1038, 286, -678, 281, -70, +219, 535, 69, 997, -67, 1237, -160, 1127, +-277, 645, -333, -51, -237, -698, -59, -1094, +146, -1124, 332, -810, 414, -284, 341, 259, +219, 633, 83, 697, -5, 503, -1, 227, +49, 11, 26, -65, -53, 17, -136, 126, +-251, 146, -376, 16, -373, -260, -157, -586, +181, -752, 517, -639, 801, -277, 899, 226, +696, 716, 219, 1002, -306, 987, -735, 659, +-947, 114, -878, -464, -504, -862, 56, -1004, +584, -869, 879, -464, 863, 87, 580, 544, +165, 781, -217, 768, -410, 516, -314, 90, +-38, -319, 155, -539, 235, -508, 197, -254, +-21, 126, -337, 429, -478, 490, -424, 267, +-251, -149, 72, -588, 541, -801, 940, -670, +1046, -227, 846, 383, 410, 924, -193, 1134, +-786, 938, -1149, 406, -1180, -287, -875, -904, +-257, -1191, 435, -1050, 976, -560, 1228, 60, +1121, 588, 669, 855, 123, 797, -302, 474, +-547, 72, -565, -232, -384, -331, -184, -256, +-120, -83, -141, 71, -147, 118, -106, 25, +19, -189, 220, -437, 504, -528, 761, -401, +831, -110, 656, 314, 376, 779, -40, 1009, +-575, 890, -966, 480, -1064, -135, -922, -767, +-522, -1132, 91, -1122, 679, -761, 1096, -179, +1257, 420, 1065, 800, 609, 852, 54, 619, +-447, 263, -788, -59, -853, -196, -679, -135, +-354, -13, -33, 51, 170, 7, 220, -254, +219, -623, 290, -809, 421, -686, 548, -323, +629, 250, 583, 893, 343, 1335, -36, 1352, +-436, 935, -797, 193, -979, -644, -897, -1303, +-545, -1588, -20, -1422, 584, -787, 1063, 104, +1235, 875, 1075, 1296, 694, 1341, 158, 987, +-420, 369, -820, -261, -964, -695, -893, -825, +-569, -665, -69, -376, 358, -83, 568, 122, +673, 179, 646, 85, 463, -50, 245, -103, +129, -1, 2, 217, -175, 476, -290, 645, +-325, 607, -354, 325, -330, -147, -178, -699, +16, -1070, 165, -1084, 322, -745, 491, -142, +561, 528, 453, 979, 282, 1113, 68, 941, +-184, 512, -398, -42, -482, -523, -465, -825, +-300, -882, -14, -728, 239, -396, 426, 77, +581, 524, 591, 735, 379, 698, 75, 453, +-204, 90, -456, -284, -588, -547, -462, -571, +-64, -333, 341, -12, 590, 266, 641, 453, +478, 459, 102, 238, -277, -68, -471, -333, +-502, -466, -374, -422, -59, -229, 307, 17, +536, 257, 623, 428, 544, 485, 215, 384, +-195, 157, -466, -124, -538, -364, -427, -503, +-89, -486, 263, -296, 442, 22, 487, 310, +452, 451, 239, 430, -102, 267, -350, -22, +-426, -295, -351, -422, -88, -351, 280, -108, +526, 189, 533, 374, 354, 400, 53, 263, +-221, 6, -383, -261, -381, -399, -242, -391, +-21, -270, 179, -82, 324, 104, 378, 225, +301, 338, 158, 412, 37, 345, -38, 172, +-50, 17, -3, -175, 4, -400, -75, -505, +-127, -427, -145, -271, -136, -69, -48, 163, +133, 355, 259, 425, 317, 413, 342, 346, +287, 205, 162, 16, 51, -150, -57, -331, +-165, -493, -213, -530, -254, -418, -311, -201, +-247, 133, -55, 455, 149, 615, 338, 595, +537, 405, 566, 49, 412, -307, 238, -496, +81, -462, -152, -252, -361, 33, -465, 228, +-529, 232, -474, 54, -231, -186, 92, -354, +411, -296, 680, 15, 777, 397, 667, 648, +459, 697, 134, 466, -250, -26, -568, -589, +-709, -955, -679, -960, -459, -598, -115, -44, +222, 517, 463, 911, 610, 966, 684, 631, +649, 98, 485, -382, 197, -640, -197, -641, +-580, -404, -789, -49, -725, 246, -442, 342, +-15, 238, 383, 4, 633, -190, 689, -228, +609, -106, 397, 105, 84, 331, -207, 440, +-370, 353, -405, 102, -352, -226, -216, -527, +-43, -643, 116, -514, 268, -175, 395, 239, +438, 574, 340, 689, 174, 530, -52, 155, +-297, -254, -444, -504, -381, -496, -175, -289, +92, 4, 356, 250, 537, 351, 571, 252, +419, 27, 92, -201, -279, -327, -533, -304, +-583, -124, -415, 129, -78, 359, 254, 462, +490, 394, 584, 177, 531, -106, 311, -387, +29, -569, -186, -567, -304, -358, -343, -33, +-275, 335, -99, 627, 55, 695, 105, 489, +107, 112, 140, -309, 199, -585, 199, -582, +187, -357, 216, -66, 248, 239, 160, 423, +-1, 349, -189, 108, -383, -109, -482, -256, +-359, -284, -59, -118, 271, 175, 542, 381, +621, 396, 428, 212, 114, -103, -128, -431, +-266, -601, -289, -513, -139, -191, 64, 238, +199, 596, 215, 705, 118, 560, -98, 202, +-287, -294, -289, -710, -83, -783, 189, -527, +396, -100, 511, 375, 438, 731, 154, 761, +-116, 473, -209, 9, -228, -433, -247, -664, +-158, -617, -20, -384, 36, -41, 7, 299, +43, 479, 102, 445, 135, 285, 224, 94, +371, -25, 429, -84, 351, -125, 159, -156, +-147, -181, -444, -242, -596, -306, -604, -308, +-444, -170, -82, 90, 353, 384, 663, 625, +820, 741, 767, 622, 477, 257, 52, -261, +-318, -778, -555, -1078, -596, -992, -439, -582, +-222, 13, -27, 622, 147, 1026, 243, 1046, +254, 727, 273, 229, 323, -255, 365, -573, +424, -662, 393, -578, 178, -375, -188, -135, +-547, 32, -803, 93, -842, 150, -567, 230, +-44, 292, 516, 329, 930, 341, 1119, 261, +1006, 104, 581, -90, -23, -273, -616, -399, +-984, -441, -1011, -407, -719, -279, -244, -91, +270, 99, 605, 267, 726, 413, 688, 483, +531, 448, 289, 318, 45, 153, -177, -46, +-379, -277, -469, -475, -413, -565, -269, -557, +-85, -447, 88, -231, 202, 79, 283, 410, +382, 666, 396, 771, 337, 703, 249, 447, +98, 56, -144, -354, -313, -667, -357, -825, +-374, -772, -324, -538, -139, -182, 119, 210, +339, 555, 470, 739, 508, 722, 426, 530, +237, 238, 9, -99, -181, -389, -302, -525, +-327, -478, -320, -350, -264, -187, -137, -15, +29, 85, 211, 87, 425, 79, 563, 93, +535, 140, 381, 227, 107, 332, -232, 354, +-477, 280, -573, 121, -506, -129, -275, -439, +28, -684, 291, -765, 512, -614, 599, -232, +522, 280, 326, 745, 81, 1029, -165, 985, +-378, 573, -493, -43, -455, -610, -282, -951, +-61, -956, 166, -636, 408, -110, 572, 403, +558, 703, 369, 691, 129, 438, -130, 62, +-373, -290, -520, -466, -474, -421, -287, -218, +-21, 80, 277, 323, 506, 405, 561, 312, +445, 94, 234, -171, -35, -351, -292, -408, +-390, -325, -315, -107, -162, 142, 1, 284, +125, 317, 159, 254, 161, 137, 123, 27, +87, -68, 126, -134, 211, -114, 244, -69, +203, -60, 60, -72, -190, -74, -417, -107, +-531, -123, -474, -73, -153, 43, 306, 185, +655, 294, 796, 291, 697, 183, 316, 20, +-149, -128, -501, -220, -657, -213, -588, -122, +-307, -24, 17, 15, 276, -5, 467, -107, +480, -223, 311, -235, 138, -64, 23, 208, +-65, 494, -81, 693, -20, 675, 3, 359, +-52, -162, -153, -693, -232, -1046, -262, -1093, +-159, -741, 77, -111, 339, 553, 522, 1047, +561, 1211, 422, 953, 132, 407, -170, -191, +-394, -661, -525, -906, -482, -852, -288, -556, +-19, -163, 267, 181, 463, 408, 482, 474, +387, 377, 214, 207, 24, 77, -106, -4, +-144, -24, -134, 11, -117, 50, -125, 14, +-159, -87, -161, -222, -106, -344, -9, -405, +124, -356, 294, -175, 479, 132, 563, 463, +468, 689, 183, 701, -223, 475, -612, 75, +-772, -359, -669, -679, -357, -750, 124, -563, +593, -197, 844, 173, 795, 402, 521, 437, +131, 329, -274, 143, -547, -8, -607, -54, +-451, 1, -169, 69, 104, 62, 279, -61, +366, -225, 328, -336, 176, -335, 31, -210, +-38, 27, -61, 272, -12, 419, 119, 410, +205, 276, 156, 39, -5, -221, -221, -391, +-381, -396, -428, -254, -311, -5, 5, 240, +399, 368, 669, 331, 742, 143, 568, -128, +193, -312, -266, -334, -638, -245, -748, -86, +-555, 147, -193, 337, 159, 372, 413, 239, +501, 38, 432, -160, 278, -303, 88, -331, +-33, -206, -53, -5, -65, 181, -102, 269, +-102, 226, -120, 88, -160, -70, -174, -211, +-123, -270, 9, -200, 192, -11, 351, 189, +397, 311, 325, 301, 167, 183, -39, 1, +-189, -160, -257, -246, -256, -257, -166, -214, +-22, -130, 62, -64, 86, -11, 97, 68, +92, 190, 56, 300, 48, 372, 113, 360, +207, 233, 255, -10, 217, -296, 107, -544, +-64, -659, -272, -588, -414, -324, -427, 40, +-306, 409, -76, 705, 213, 823, 477, 682, +616, 354, 562, -65, 373, -479, 85, -799, +-221, -870, -429, -660, -533, -259, -518, 193, +-328, 579, -51, 750, 177, 630, 396, 311, +571, -23, 524, -267, 335, -342, 132, -252, +-121, -78, -369, 45, -441, 41, -363, -73, +-198, -197, 50, -257, 277, -191, 362, -13, +304, 238, 172, 432, -23, 455, -200, 309, +-256, 107, -190, -99, -19, -280, 186, -363, +352, -334, 429, -264, 341, -161, 69, -30, +-271, 110, -560, 239, -653, 315, -460, 282, +-72, 174, 345, 33, 706, -84, 853, -148, +672, -120, 277, -32, -181, 51, -596, 35, +-815, -90, -741, -245, -382, -348, 131, -330, +540, -117, 698, 234, 633, 583, 342, 740, +-48, 608, -339, 221, -425, -273, -305, -671, +-80, -776, 135, -571, 277, -182, 282, 197, +106, 405, -121, 355, -258, 145, -282, -36, +-124, -67, 150, 65, 353, 294, 402, 450, +305, 375, 81, 42, -155, -411, -290, -843, +-291, -1020, -165, -752, -4, -124, 94, 573, +125, 1092, 127, 1224, 95, 895, 30, 239, +34, -480, 133, -988, 217, -1074, 186, -770, +58, -247, -115, 298, -304, 666, -420, 720, +-357, 500, -121, 111, 186, -236, 439, -390, +573, -348, 530, -164, 304, 89, -19, 264, +-373, 295, -636, 199, -629, -2, -379, -242, +-25, -395, 375, -405, 678, -250, 680, 12, +434, 312, 81, 540, -298, 573, -585, 359, +-609, 10, -333, -371, 69, -617, 405, -592, +561, -337, 495, 28, 211, 384, -136, 562, +-360, 466, -435, 172, -344, -140, -146, -358, +75, -413, 280, -296, 447, -33, 506, 224, +404, 347, 147, 298, -185, 150, -447, -25, +-569, -177, -516, -291, -281, -283, 15, -138, +282, 1, 507, 80, 620, 174, 551, 226, +377, 174, 104, 71, -274, -5, -566, -70, +-629, -123, -511, -139, -248, -68, 64, 33, +299, 93, 425, 75, 426, -46, 284, -233, +163, -327, 139, -228, 47, 74, -60, 473, +-60, 726, -121, 645, -277, 244, -324, -347, +-278, -849, -247, -1013, -103, -750, 157, -188, +389, 455, 543, 888, 595, 952, 478, 671, +172, 166, -192, -363, -461, -671, -551, -679, +-474, -455, -288, -119, -79, 191, 69, 354, +184, 338, 270, 187, 319, 28, 334, -70, +294, -83, 205, -47, 109, 5, 31, 13, +-67, -4, -196, -5, -333, -2, -458, 10, +-496, 15, -384, -48, -100, -137, 286, -171, +606, -132, 732, -36, 671, 150, 488, 333, +205, 356, -145, 211, -472, 25, -697, -155, +-757, -282, -651, -323, -380, -255, 63, -126, +536, -20, 776, 35, 758, 100, 632, 213, +381, 304, 28, 316, -287, 269, -509, 118, +-598, -127, -539, -392, -385, -545, -157, -513, +152, -277, 374, 70, 433, 416, 445, 618, +393, 566, 247, 273, 65, -94, -129, -385, +-316, -504, -400, -415, -332, -170, -144, 116, +86, 318, 223, 361, 243, 308, 158, 149, +-17, -93, -159, -318, -141, -430, -14, -419, +107, -240, 232, 77, 315, 400, 290, 634, +171, 683, -85, 455, -396, 28, -548, -442, +-475, -808, -253, -918, 102, -678, 482, -203, +615, 323, 456, 727, 194, 926, -78, 818, +-292, 446, -323, -19, -187, -436, -10, -723, +152, -761, 245, -546, 182, -232, -25, 92, +-268, 361, -438, 425, -422, 329, -133, 226, +291, 159, 644, 95, 797, 72, 646, 68, +263, 12, -217, -148, -630, -335, -841, -488, +-825, -533, -601, -392, -169, -65, 404, 333, +866, 668, 1030, 806, 861, 677, 403, 339, +-153, -96, -564, -517, -714, -735, -644, -724, +-442, -558, -196, -265, 32, 120, 223, 450, +396, 642, 525, 658, 500, 485, 345, 178, +128, -148, -102, -406, -264, -523, -393, -482, +-460, -324, -360, -113, -163, 103, 41, 270, +265, 377, 444, 378, 440, 282, 298, 119, +99, -69, -126, -245, -247, -327, -241, -326, +-179, -272, -78, -117, 21, 123, 66, 321, +59, 421, 51, 372, 74, 132, 85, -168, +54, -350, 63, -398, 63, -273, -7, -19, +-28, 212, -19, 279, -40, 215, -53, 65, +-19, -83, 26, -148, 39, -131, 47, -44, +9, 94, -58, 180, -83, 133, -25, -18, +100, -154, 217, -226, 285, -218, 212, -109, +-1, 90, -214, 238, -349, 256, -359, 153, +-203, 23, 1, -87, 173, -149, 348, -122, +423, -20, 364, 65, 213, 85, -58, 48, +-330, -71, -450, -224, -406, -274, -223, -223, +75, -34, 349, 283, 423, 531, 309, 558, +111, 405, -56, 60, -157, -368, -245, -675, +-221, -767, -72, -610, 85, -220, 210, 225, +289, 616, 278, 871, 112, 813, -193, 443, +-460, -28, -476, -517, -251, -839, 75, -824, +388, -550, 595, -155, 590, 323, 333, 690, +-16, 784, -352, 617, -611, 248, -676, -224, +-510, -595, -115, -715, 366, -570, 709, -222, +765, 190, 528, 509, 90, 646, -373, 538, +-570, 255, -482, -114, -284, -459, 12, -680, +284, -625, 319, -311, 200, 85, 116, 421, +22, 601, -98, 558, -147, 335, -119, 41, +-54, -210, 60, -353, 194, -394, 242, -368, +209, -234, 57, -39, -201, 112, -347, 189, +-336, 242, -211, 215, 31, 153, 276, 124, +404, 107, 413, 57, 319, -46, 73, -191, +-230, -312, -420, -349, -451, -286, -304, -127, +-45, 110, 234, 307, 431, 399, 407, 363, +211, 223, 29, 14, -104, -187, -226, -311, +-265, -294, -223, -185, -125, -50, 16, 66, +200, 125, 369, 123, 383, 84, 235, 32, +-45, 7, -333, 1, -454, -18, -376, -58, +-139, -40, 164, 1, 409, 40, 483, 88, +389, 105, 173, 28, -134, -105, -386, -234, +-491, -277, -443, -173, -171, 41, 213, 268, +489, 417, 593, 380, 486, 144, 148, -169, +-269, -404, -582, -462, -662, -296, -456, -39, +-47, 223, 413, 423, 710, 438, 724, 223, +454, -52, -19, -268, -473, -403, -720, -386, +-645, -200, -328, 42, 43, 269, 378, 417, +576, 407, 552, 252, 350, 36, 121, -234, +-123, -472, -386, -546, -496, -370, -415, -19, +-212, 360, 111, 570, 411, 541, 473, 314, +309, -52, 30, -390, -225, -530, -315, -494, +-267, -288, -81, 59, 200, 360, 410, 499, +437, 530, 263, 342, -57, -26, -469, -355, +-751, -554, -663, -581, -251, -348, 315, -25, +813, 250, 977, 493, 718, 575, 238, 450, +-262, 239, -675, -58, -836, -367, -765, -546, +-544, -596, -94, -507, 457, -194, 861, 199, +1038, 546, 841, 752, 270, 687, -333, 371, +-782, -58, -963, -518, -752, -789, -335, -717, +111, -421, 522, -17, 793, 400, 792, 636, +477, 612, -9, 394, -425, 100, -589, -201, +-507, -409, -237, -469, 46, -358, 190, -155, +248, 55, 212, 196, 142, 241, 106, 217, +31, 139, -43, 45, -52, 33, -64, 52, +-13, 14, 68, -63, -37, -174, -153, -289, +-94, -282, 19, -189, 131, -32, 147, 185, +37, 366, -52, 393, -51, 311, 27, 153, +170, -57, 263, -255, 166, -389, -55, -392, +-278, -265, -385, -98, -320, 100, -168, 279, +79, 338, 322, 278, 440, 158, 489, -1, +353, -81, -3, -82, -296, -74, -451, -82, +-491, -94, -313, -153, -69, -235, 149, -237, +391, -104, 465, 139, 344, 391, 149, 535, +-117, 499, -319, 239, -313, -138, -162, -488, +39, -670, 187, -586, 141, -250, 29, 124, +-20, 368, -69, 464, -57, 452, -25, 325, +-19, 130, 65, -69, 201, -238, 288, -326, +194, -331, -99, -283, -346, -170, -401, -27, +-299, 95, 31, 179, 380, 267, 429, 345, +307, 404, 114, 334, -144, 86, -310, -225, +-356, -510, -287, -694, -46, -634, 259, -338, +469, 76, 523, 510, 263, 811, -222, 827, +-542, 542, -557, 31, -321, -466, 56, -747, +411, -752, 617, -493, 507, -16, 172, 404, +-167, 535, -497, 375, -650, 79, -412, -151, +21, -229, 432, -146, 696, 97, 564, 329, +158, 348, -246, 139, -556, -152, -569, -411, +-301, -551, -6, -500, 276, -212, 502, 180, +485, 537, 299, 745, 19, 669, -335, 291, +-492, -194, -395, -608, -170, -809, 137, -631, +374, -167, 419, 328, 277, 664, 24, 674, +-190, 386, -316, -79, -341, -539, -164, -721, +140, -495, 383, -51, 493, 454, 306, 811, +-136, 764, -482, 319, -577, -322, -372, -877, +56, -1007, 439, -655, 622, -27, 576, 679, +250, 1125, -181, 1022, -504, 478, -683, -284, +-585, -962, -226, -1235, 240, -974, 683, -270, +799, 623, 552, 1265, 176, 1347, -284, 857, +-617, -5, -611, -893, -471, -1435, -242, -1374, +159, -706, 450, 230, 550, 1046, 509, 1446, +213, 1263, -111, 572, -278, -312, -353, -1083, +-226, -1362, 21, -1004, 80, -257, 33, 531, +13, 1030, -82, 1029, -117, 608, -45, -70, +19, -724, 150, -950, 328, -688, 404, -143, +311, 520, 67, 951, -281, 905, -596, 452, +-662, -258, -426, -959, -36, -1179, 384, -828, +695, -136, 670, 662, 377, 1211, 22, 1208, +-382, 695, -616, -101, -517, -896, -233, -1328, +175, -1132, 532, -425, 547, 457, 316, 1143, +-12, 1318, -433, 883, -641, 73, -509, -793, +-247, -1305, 173, -1178, 612, -535, 790, 316, +721, 1056, 402, 1308, -155, 981, -661, 291, +-894, -573, -849, -1220, -488, -1244, 62, -781, +559, -32, 843, 787, 825, 1230, 529, 1112, +56, 626, -391, -127, -619, -871, -598, -1215, +-346, -1045, 19, -451, 289, 332, 391, 962, +326, 1216, 67, 982, -207, 300, -299, -496, +-267, -1029, -93, -1113, 222, -740, 457, -104, +447, 556, 217, 923, -70, 859, -292, 497, +-391, -37, -368, -535, -255, -674, -90, -480, +96, -143, 248, 262, 329, 477, 356, 365, +247, 119, 49, -203, -40, -456, -96, -399, +-189, -158, -209, 123, -217, 443, -254, 540, +-133, 403, 109, 203, 294, -131, 381, -460, +289, -532, 75, -442, -81, -247, -197, 59, +-240, 289, -169, 380, -71, 375, 15, 228, +148, 57, 264, -60, 260, -162, 146, -201, +-35, -96, -230, 54, -361, 127, -326, 80, +-171, -32, -15, -192, 200, -367, 389, -390, +422, -179, 383, 188, 257, 565, -30, 745, +-295, 685, -455, 437, -553, -26, -459, -580, +-218, -915, 39, -973, 344, -747, 560, -248, +570, 337, 435, 841, 208, 1130, -44, 1010, +-252, 546, -415, -26, -511, -598, -472, -988, +-315, -1000, -66, -673, 243, -153, 518, 382, +631, 780, 476, 885, 179, 630, -140, 125, +-432, -397, -526, -724, -378, -690, -134, -317, +180, 212, 453, 681, 450, 832, 224, 546, +-113, -6, -463, -593, -555, -969, -383, -923, +-93, -476, 338, 219, 723, 937, 762, 1252, +483, 1008, 46, 374, -448, -422, -792, -1055, +-842, -1219, -587, -877, -84, -192, 401, 561, +688, 1038, 768, 1050, 612, 656, 246, 43, +-215, -573, -612, -980, -774, -944, -599, -471, +-148, 182, 381, 770, 700, 1064, 655, 870, +307, 296, -181, -420, -546, -986, -643, -1098, +-448, -726, -56, -20, 299, 754, 525, 1153, +616, 993, 473, 429, 130, -352, -246, -1000, +-572, -1081, -674, -623, -428, 107, -91, 791, +208, 1069, 465, 807, 462, 156, 238, -590, +14, -1039, -159, -978, -205, -465, -120, 317, +-23, 1009, 76, 1245, 141, 906, 99, 136, +-8, -679, -173, -1216, -300, -1281, -278, -746, +-154, 172, 28, 933, 234, 1282, 397, 1142, +454, 535, 366, -235, 134, -901, -151, -1230, +-368, -979, -466, -311, -428, 424, -325, 991, +-152, 1077, 94, 637, 249, -24, 354, -703, +490, -1048, 489, -756, 334, -53, 64, 674, +-309, 1119, -554, 979, -579, 341, -518, -501, +-288, -1271, 80, -1495, 348, -963, 524, 25, +601, 1088, 423, 1795, 67, 1761, -254, 979, +-455, -239, -449, -1415, -228, -2014, 53, -1809, +263, -865, 256, 460, 76, 1570, -134, 1998, +-299, 1583, -279, 517, -100, -686, 163, -1522, +478, -1668, 580, -1010, 405, 127, 94, 1106, +-386, 1485, -810, 1139, -798, 238, -482, -807, +-35, -1461, 538, -1372, 895, -598, 837, 498, +502, 1462, -91, 1786, -704, 1272, -950, 233, +-814, -956, -329, -1850, 409, -1941, 903, -1139, +919, 194, 530, 1480, -143, 2116, -732, 1799, +-902, 667, -664, -795, -211, -1854, 313, -2011, +749, -1237, 862, 163, 593, 1515, 71, 2126, +-485, 1776, -832, 592, -845, -951, -503, -2096, +113, -2350, 681, -1553, 833, 54, 578, 1698, +123, 2607, -375, 2402, -614, 1152, -484, -570, +-206, -1955, 138, -2464, 420, -1934, 345, -655, +71, 753, -169, 1712, -396, 1843, -367, 1209, +-46, 234, 249, -667, 495, -1105, 618, -904, +321, -332, -228, 283, -644, 640, -891, 499, +-799, 44, -260, -419, 400, -673, 905, -500, +1081, -17, 775, 445, 161, 794, -445, 892, +-870, 566, -979, 9, -692, -546, -197, -885, +279, -806, 630, -438, 690, 38, 387, 476, +-3, 600, -242, 414, -297, 155, -101, -89, +191, -147, 255, 46, 91, 200, -194, 185, +-532, 73, -655, -144, -419, -400, -77, -550, +307, -492, 725, -156, 881, 336, 665, 762, +219, 934, -345, 675, -832, 71, -979, -606, +-704, -1075, -153, -1039, 398, -455, 685, 363, +656, 1060, 374, 1322, -70, 960, -417, 149, +-493, -790, -371, -1459, -125, -1502, 199, -895, +466, 144, 491, 1236, 275, 1837, -67, 1675, +-416, 884, -630, -242, -587, -1235, -337, -1733, +-1, -1630, 330, -913, 534, 102, 545, 928, +392, 1374, 175, 1361, -34, 900, -252, 307, +-422, -272, -473, -743, -399, -820, -284, -652, +-140, -565, 65, -430, 254, -125, 387, 205, +458, 535, 402, 868, 198, 1052, -91, 915, +-349, 384, -502, -360, -460, -1046, -200, -1489, +69, -1405, 186, -668, 203, 384, 136, 1331, +-45, 1854, -201, 1653, -198, 728, -113, -533, +36, -1631, 322, -2095, 533, -1620, 467, -408, +182, 975, -320, 2003, -813, 2197, -951, 1405, +-731, 10, -224, -1410, 434, -2268, 873, -2026, +927, -790, 724, 684, 264, 1816, -398, 2195, +-852, 1497, -933, 71, -720, -1290, -173, -1979, +479, -1674, 815, -541, 746, 820, 355, 1810, +-247, 1940, -724, 1065, -804, -328, -615, -1553, +-202, -2151, 406, -1786, 824, -518, 886, 1051, +684, 2227, 80, 2496, -673, 1675, -1036, 104, +-1001, -1494, -620, -2460, 91, -2436, 663, -1363, +788, 280, 647, 1674, 261, 2299, -283, 2011, +-533, 903, -506, -482, -389, -1512, 7, -1864, +472, -1362, 602, -188, 431, 971, 4, 1585, +-556, 1440, -903, 525, -855, -640, -460, -1434, +135, -1615, 662, -1002, 903, 227, 809, 1330, +469, 1804, 17, 1626, -420, 798, -679, -415, +-684, -1429, -528, -1837, -249, -1494, 36, -527, +69, 573, -70, 1262, -113, 1339, -29, 896, +294, 140, 783, -518, 1014, -685, 819, -404, +256, 39, -560, 437, -1321, 549, -1664, 254, +-1435, -284, -772, -804, 143, -1018, 1125, -710, +1743, -55, 1683, 669, 1111, 1269, 178, 1370, +-921, 863, -1593, 121, -1523, -565, -948, -998, +-109, -1019, 648, -730, 952, -280, 779, 249, +233, 556, -446, 520, -776, 348, -636, 85, +-205, -161, 418, -123, 944, 140, 1048, 441, +725, 642, 1, 510, -941, 27, -1571, -544, +-1612, -1040, -1123, -1284, -175, -1025, 871, -297, +1547, 616, 1676, 1408, 1257, 1720, 422, 1429, +-525, 686, -1200, -308, -1430, -1224, -1322, -1606, +-855, -1297, -86, -629, 598, 74, 960, 707, +1021, 1030, 762, 892, 297, 497, -184, 58, +-610, -327, -792, -429, -693, -222, -497, 22, +-156, 180, 248, 199, 472, 34, 563, -138, +490, -272, 143, -349, -216, -190, -448, 79, +-625, 250, -627, 372, -360, 351, 0, 166, +284, 40, 530, -82, 642, -243, 480, -113, +189, 198, -155, 300, -516, 201, -714, -34, +-740, -353, -633, -587, -273, -670, 182, -498, +469, -9, 707, 593, 851, 1078, 581, 1305, +108, 1092, -298, 442, -733, -432, -1008, -1263, +-876, -1709, -526, -1544, -59, -836, 503, 192, +821, 1110, 719, 1600, 451, 1626, 96, 1151, +-343, 288, -572, -576, -519, -1136, -382, -1251, +-164, -915, 38, -337, 93, 218, 56, 579, +-49, 595, -154, 335, -54, 49, 209, -107, +359, -68, 404, 146, 340, 408, -120, 595, +-700, 517, -924, 88, -894, -520, -597, -1055, +94, -1284, 777, -1021, 1142, -292, 1175, 660, +701, 1476, -217, 1787, -1085, 1412, -1523, 545, +-1395, -463, -750, -1288, 159, -1687, 993, -1494, +1429, -724, 1270, 283, 602, 1070, -311, 1379, +-1117, 1200, -1502, 657, -1270, -61, -426, -655, +535, -875, 1133, -708, 1279, -325, 767, 77, +-245, 343, -1021, 413, -1247, 340, -1051, 236, +-431, 118, 433, -37, 1118, -177, 1316, -198, +890, -192, 10, -269, -867, -255, -1457, 5, +-1517, 365, -890, 633, 49, 732, 839, 618, +1337, 187, 1314, -461, 703, -1009, -76, -1234, +-748, -1035, -1283, -345, -1359, 605, -811, 1350, +-61, 1647, 541, 1434, 894, 676, 821, -386, +400, -1331, -75, -1767, -406, -1536, -496, -810, +-403, 169, -253, 1075, -72, 1522, 117, 1466, +115, 985, -127, 168, -295, -647, -306, -1120, +-205, -1211, 107, -907, 427, -278, 464, 431, +314, 978, 48, 1111, -349, 810, -597, 325, +-548, -327, -472, -924, -355, -1051, -29, -814, +271, -389, 389, 302, 392, 971, 239, 1291, +73, 1250, 24, 838, -82, 91, -243, -796, +-326, -1565, -493, -1819, -695, -1479, -559, -744, +-227, 407, 57, 1670, 534, 2373, 954, 2330, +885, 1608, 514, 320, -9, -1134, -687, -2296, +-1218, -2787, -1274, -2361, -879, -1197, -227, 353, +466, 1878, 874, 2807, 927, 2814, 742, 1973, +292, 464, -264, -1183, -633, -2333, -806, -2649, +-730, -2060, -371, -832, -11, 587, 185, 1771, +288, 2239, 167, 1845, -96, 853, -74, -413, +112, -1446, 164, -1730, 236, -1297, 151, -386, +-248, 740, -614, 1513, -804, 1538, -763, 938, +-365, -35, 229, -1022, 797, -1598, 1135, -1521, +980, -837, 333, 194, -494, 1207, -1297, 1786, +-1767, 1649, -1470, 901, -578, -118, 460, -1019, +1445, -1485, 1978, -1390, 1700, -809, 783, 46, +-446, 773, -1713, 1097, -2467, 1002, -2260, 482, +-1317, -212, 0, -655, 1444, -735, 2357, -398, +2382, 270, 1709, 850, 355, 1037, -1237, 727, +-2274, -71, -2618, -919, -2256, -1420, -1013, -1503, +590, -1013, 1765, 28, 2348, 1116, 2173, 1918, +1173, 2199, -140, 1671, -1336, 509, -2162, -771, +-2231, -1807, -1501, -2378, -303, -2226, 874, -1270, +1580, 60, 1640, 1288, 1073, 2178, 118, 2454, +-757, 1950, -1196, 911, -1104, -370, -629, -1561, +-19, -2169, 494, -2015, 682, -1318, 398, -326, +-199, 656, -732, 1407, -962, 1725, -761, 1406, +-109, 689, 694, -12, 1313, -583, 1427, -866, +852, -745, -136, -385, -1159, -26, -1932, 137, +-2136, -13, -1629, -250, -519, -313, 835, -232, +1939, -1, 2378, 448, 2000, 940, 967, 1198, +-341, 1120, -1524, 696, -2237, -149, -2284, -1160, +-1750, -1852, -828, -2012, 314, -1524, 1296, -394, +1817, 921, 1884, 1991, 1441, 2505, 567, 2183, +-361, 1199, -1156, -80, -1716, -1461, -1900, -2434, +-1596, -2525, -783, -1848, 227, -501, 1085, 1148, +1637, 2222, 1667, 2444, 1066, 1963, 74, 734, +-896, -856, -1521, -1984, -1601, -2281, -1100, -1763, +-202, -514, 772, 1040, 1360, 2214, 1234, 2567, +541, 1933, -420, 358, -1337, -1574, -1783, -2926, +-1461, -3194, -481, -2272, 730, -286, 1755, 2027, +2161, 3689, 1604, 4098, 322, 2972, -1118, 647, +-2236, -2005, -2591, -4018, -1976, -4554, -650, -3397, +833, -1066, 1940, 1696, 2276, 3859, 1677, 4450, +464, 3410, -832, 1266, -1706, -1314, -1797, -3238, +-1183, -3714, -183, -2751, 776, -792, 1174, 1383, +848, 2838, 42, 2969, -839, 1769, -1373, -116, +-1216, -1851, -360, -2727, 727, -2300, 1541, -787, +1762, 1067, 1126, 2530, -131, 2940, -1374, 2111, +-2146, 491, -2160, -1382, -1380, -2785, -163, -3014, +1111, -2218, 2010, -739, 2021, 1116, 1185, 2524, +62, 2938, -1089, 2457, -1955, 1231, -1920, -335, +-1014, -1647, 94, -2367, 960, -2298, 1429, -1528, +1281, -432, 428, 751, -586, 1617, -1245, 1868, +-1498, 1673, -1216, 1040, -406, 32, 518, -835, +1206, -1366, 1461, -1536, 1195, -1201, 477, -484, +-440, 400, -1207, 1216, -1628, 1592, -1666, 1433, +-1221, 781, -354, -333, 582, -1378, 1266, -1805, +1576, -1637, 1391, -853, 752, 449, 16, 1711, +-598, 2355, -1166, 2104, -1588, 1087, -1532, -356, +-1025, -1840, -417, -2710, 313, -2542, 1107, -1521, +1417, 82, 1122, 1822, 687, 2863, 256, 2858, +-332, 2039, -910, 547, -1204, -1228, -1262, -2501, +-1054, -2853, -489, -2334, 201, -1169, 709, 398, +943, 1849, 883, 2566, 587, 2454, 151, 1739, +-310, 546, -665, -822, -839, -1862, -812, -2241, +-499, -1950, 3, -1182, 303, -157, 250, 929, +97, 1719, -91, 2005, -280, 1847, -201, 1188, +140, 73, 437, -1028, 520, -1803, 373, -2150, +27, -1871, -553, -872, -1235, 478, -1538, 1541, +-1234, 2084, -548, 2161, 548, 1548, 1812, 320, +2372, -848, 1893, -1622, 724, -2093, -842, -1908, +-2384, -991, -3221, 55, -2862, 915, -1462, 1622, +430, 1945, 2358, 1718, 3610, 1093, 3401, 231, +1907, -759, -249, -1634, -2507, -2143, -3915, -2113, +-3855, -1437, -2559, -244, -364, 1070, 2033, 2145, +3564, 2733, 3790, 2572, 2738, 1538, 617, 6, +-1735, -1526, -3408, -2759, -3907, -3279, -3034, -2651, +-1142, -1101, 1031, 691, 2833, 2318, 3619, 3333, +2979, 3237, 1249, 2138, -746, 443, -2444, -1361, +-3414, -2623, -3157, -3029, -1776, -2611, -21, -1376, +1608, 202, 2794, 1472, 2972, 2335, 2053, 2628, +579, 2015, -1070, 903, -2497, -192, -3042, -1243, +-2493, -2002, -1231, -2088, 247, -1566, 1566, -731, +2484, 205, 2538, 1114, 1539, 1788, 152, 1965, +-1122, 1528, -2213, 710, -2593, -282, -1927, -1336, +-724, -2044, 569, -1961, 1738, -1189, 2238, -145, +1720, 988, 574, 1960, -590, 2227, -1521, 1612, +-2049, 448, -1818, -799, -792, -1731, 449, -2130, +1355, -1789, 1726, -652, 1488, 680, 593, 1586, +-736, 1974, -1744, 1727, -1900, 782, -1448, -326, +-493, -1167, 836, -1635, 1719, -1416, 1728, -631, +1161, 179, 149, 858, -1083, 1173, -1958, 800, +-2074, 116, -1436, -307, -257, -513, 1054, -476, +1943, 51, 2074, 786, 1469, 1096, 242, 754, +-1228, -39, -2204, -973, -2337, -1777, -1762, -2067, +-561, -1481, 845, -73, 1777, 1620, 2077, 2902, +1744, 3276, 702, 2542, -539, 751, -1457, -1542, +-1947, -3403, -1857, -4104, -1163, -3483, -181, -1622, +720, 998, 1268, 3285, 1397, 4318, 1129, 3912, +536, 2305, -164, -22, -812, -2252, -1275, -3583, +-1288, -3675, -911, -2539, -457, -625, 91, 1158, +700, 2239, 959, 2673, 842, 2330, 579, 1135, +111, -161, -503, -899, -919, -1304, -982, -1434, +-793, -1064, -393, -517, 194, -121, 616, 230, +650, 522, 569, 654, 339, 739, -182, 787, +-593, 631, -769, 303, -828, -112, -580, -573, +-53, -951, 407, -1023, 686, -754, 707, -283, +437, 305, 67, 866, -319, 1142, -671, 1043, +-838, 585, -848, -74, -675, -584, -229, -827, +323, -853, 769, -570, 980, -99, 867, 237, +497, 349, -92, 342, -701, 319, -1096, 345, +-1322, 286, -1275, 220, -730, 320, 138, 292, +1004, -52, 1543, -468, 1503, -819, 978, -1042, +143, -996, -858, -579, -1608, 239, -1802, 1183, +-1489, 1723, -709, 1752, 341, 1372, 1208, 478, +1646, -737, 1459, -1763, 683, -2295, -199, -2134, +-900, -1287, -1364, -56, -1380, 1251, -947, 2270, +-343, 2551, 249, 2001, 734, 949, 963, -303, +856, -1482, 480, -2161, -9, -2134, -410, -1533, +-571, -580, -663, 534, -798, 1410, -773, 1682, +-520, 1458, -236, 987, 178, 295, 815, -460, +1247, -840, 1204, -749, 849, -573, 198, -371, +-774, -32, -1713, 85, -2154, -131, -1987, -229, +-1223, -158, 146, -45, 1691, 318, 2659, 821, +2758, 1043, 1954, 986, 337, 661, -1523, -38, +-2901, -802, -3388, -1322, -2740, -1549, -1117, -1336, +817, -604, 2420, 348, 3162, 1145, 2704, 1620, +1305, 1612, -441, 1113, -1940, 369, -2662, -391, +-2364, -1007, -1259, -1274, 163, -1164, 1341, -813, +1859, -316, 1431, 199, 290, 577, -857, 773, +-1525, 789, -1495, 688, -651, 555, 609, 314, +1581, 0, 1923, -246, 1476, -511, 183, -771, +-1444, -842, -2684, -715, -3074, -406, -2408, 61, +-714, 473, 1501, 787, 3302, 1068, 3963, 1056, +3336, 679, 1448, 208, -1165, -275, -3392, -718, +-4537, -997, -4361, -1107, -2794, -1001, -268, -619, +2400, -117, 4315, 405, 4808, 1003, 3750, 1564, +1522, 1754, -1225, 1438, -3618, 701, -4878, -385, +-4573, -1565, -2767, -2334, -167, -2421, 2294, -1846, +4041, -654, 4463, 844, 3236, 2127, 998, 2792, +-1396, 2601, -3259, 1720, -3914, 473, -3165, -937, +-1417, -2086, 624, -2495, 2262, -2226, 2926, -1535, +2374, -525, 910, 512, -798, 1294, -2110, 1772, +-2414, 1873, -1558, 1651, -70, 1289, 1349, 713, +2152, -129, 1939, -1018, 779, -1785, -758, -2317, +-2165, -2384, -2906, -1805, -2443, -708, -1000, 644, +831, 1979, 2520, 2925, 3432, 3148, 3089, 2608, +1568, 1449, -496, -179, -2352, -1884, -3602, -3122, +-3788, -3599, -2683, -3239, -822, -2072, 1163, -281, +2839, 1662, 3647, 3149, 3278, 3884, 1981, 3752, +193, 2560, -1566, 609, -2820, -1369, -3429, -2945, +-3097, -3873, -1747, -3739, -33, -2494, 1477, -717, +2564, 1044, 2841, 2533, 2206, 3418, 1014, 3296, +-243, 2268, -1251, 865, -1945, -634, -2130, -1942, +-1678, -2585, -842, -2481, 50, -1885, 742, -864, +1099, 376, 1122, 1285, 838, 1679, 346, 1751, +70, 1418, 68, 651, -127, -142, -529, -666, +-714, -986, -813, -1063, -992, -769, -824, -285, +-150, 151, 506, 560, 890, 806, 1229, 613, +1243, 77, 503, -402, -540, -733, -1330, -957, +-1749, -752, -1598, 16, -662, 869, 674, 1452, +1791, 1787, 2276, 1600, 1869, 622, 552, -708, +-1197, -1879, -2664, -2664, -3249, -2727, -2645, -1879, +-981, -380, 1150, 1340, 2991, 2781, 3936, 3496, +3546, 3272, 1815, 2097, -597, 260, -2929, -1667, +-4418, -3165, -4437, -3846, -3031, -3436, -758, -2065, +1806, -249, 3776, 1548, 4352, 3026, 3607, 3796, +1985, 3476, -214, 2243, -2343, 587, -3576, -1186, +-3690, -2735, -2910, -3555, -1460, -3374, 296, -2352, +1788, -811, 2590, 957, 2724, 2520, 2241, 3363, +1279, 3219, 99, 2218, -1048, 649, -1912, -1093, +-2312, -2446, -2227, -2990, -1689, -2611, -816, -1419, +244, 90, 1308, 1388, 2081, 2247, 2366, 2385, +2108, 1617, 1208, 321, -156, -899, -1455, -1690, +-2318, -1837, -2688, -1331, -2364, -388, -1375, 693, +-80, 1469, 1253, 1629, 2388, 1253, 2929, 565, +2583, -291, 1420, -1062, -155, -1411, -1671, -1374, +-2797, -1137, -3280, -582, -2885, 192, -1596, 794, +161, 1262, 1881, 1745, 3294, 1894, 3845, 1447, +3053, 590, 1199, -551, -945, -1806, -2837, -2697, +-3985, -2897, -3896, -2310, -2646, -981, -717, 807, +1442, 2504, 3205, 3540, 3931, 3601, 3426, 2665, +1880, 957, -230, -1067, -2154, -2782, -3214, -3639, +-3189, -3458, -2379, -2365, -1101, -722, 343, 969, +1557, 2263, 2200, 2874, 2186, 2714, 1592, 1911, +653, 771, -258, -302, -954, -1061, -1381, -1452, +-1426, -1503, -1186, -1354, -865, -1159, -416, -929, +155, -578, 657, -89, 1033, 515, 1165, 1256, +961, 1997, 537, 2314, 28, 1957, -624, 1151, +-1189, 6, -1313, -1449, -1061, -2661, -563, -3081, +225, -2675, 974, -1563, 1181, 80, 907, 1748, +452, 2834, -163, 3117, -774, 2612, -1002, 1333, +-873, -309, -665, -1674, -209, -2487, 452, -2598, +827, -1860, 797, -630, 662, 535, 381, 1488, +-112, 1962, -534, 1590, -718, 722, -784, -85, +-818, -776, -710, -1244, -349, -1124, 150, -497, +588, 232, 903, 873, 1128, 1220, 1082, 1040, +634, 444, -12, -307, -610, -1051, -1227, -1480, +-1686, -1350, -1567, -854, -944, -163, -262, 694, +413, 1354, 1100, 1547, 1499, 1440, 1533, 1101, +1321, 490, 799, -278, 5, -983, -804, -1439, +-1433, -1652, -1841, -1654, -1882, -1276, -1514, -503, +-855, 363, 20, 1201, 1068, 1916, 1934, 2243, +2323, 2144, 2246, 1651, 1654, 709, 471, -571, +-944, -1915, -2039, -2961, -2753, -3376, -3080, -2969, +-2618, -1695, -1243, 212, 560, 2216, 2152, 3746, +3240, 4343, 3600, 3739, 2943, 2047, 1320, -178, +-632, -2305, -2324, -3868, -3462, -4393, -3760, -3598, +-2953, -1867, -1233, 96, 742, 1894, 2287, 3138, +3001, 3433, 2912, 2874, 2126, 1792, 730, 423, +-747, -860, -1764, -1697, -2159, -2086, -1911, -2108, +-1188, -1789, -408, -1235, 283, -499, 690, 317, +565, 1024, 295, 1586, 387, 1918, 569, 1865, +625, 1437, 756, 688, 685, -192, 173, -973, +-464, -1608, -1083, -1992, -1669, -1941, -1920, -1434, +-1477, -611, -422, 335, 814, 1162, 1789, 1741, +2288, 2058, 2102, 1994, 1208, 1461, -68, 598, +-1234, -391, -1980, -1395, -2248, -2219, -1954, -2570, +-1024, -2320, 174, -1458, 1085, -97, 1634, 1349, +1866, 2509, 1523, 3207, 784, 3094, 41, 1956, +-693, 156, -1374, -1727, -1679, -3188, -1599, -3722, +-1222, -3044, -524, -1409, 397, 608, 1222, 2394, +1656, 3368, 1693, 3123, 1377, 1844, 615, 179, +-443, -1316, -1327, -2192, -1768, -2145, -1752, -1327, +-1256, -228, -491, 635, 272, 888, 893, 542, +1238, -5, 1201, -416, 980, -513, 644, -56, +133, 893, -374, 1704, -683, 1805, -840, 1120, +-955, -116, -996, -1637, -895, -2917, -596, -3192, +-81, -2218, 519, -397, 1051, 1664, 1462, 3280, +1565, 3844, 1082, 3112, 264, 1299, -555, -935, +-1312, -2766, -1849, -3571, -1843, -3094, -1272, -1649, +-361, 139, 617, 1692, 1341, 2442, 1634, 2189, +1404, 1267, 640, 97, -247, -874, -805, -1203, +-973, -824, -755, -40, -160, 686, 411, 947, +627, 610, 373, -226, -272, -1262, -1022, -1958, +-1510, -1855, -1529, -970, -889, 375, 423, 1755, +1872, 2717, 2851, 2955, 3069, 2275, 2248, 755, +390, -1102, -1865, -2635, -3718, -3383, -4585, -3208, +-4012, -2165, -2070, -463, 582, 1360, 3072, 2671, +4710, 3202, 4940, 2929, 3661, 1931, 1288, 510, +-1493, -951, -3732, -2106, -4642, -2577, -4161, -2318, +-2620, -1655, -445, -734, 1620, 315, 2874, 1141, +3149, 1577, 2552, 1709, 1382, 1527, 116, 998, +-822, 351, -1290, -190, -1253, -650, -966, -982, +-763, -1038, -743, -979, -812, -939, -770, -726, +-459, -361, 112, 37, 872, 533, 1650, 1009, +2091, 1356, 1943, 1568, 1248, 1433, 100, 834, +-1317, -61, -2545, -1038, -3019, -1860, -2576, -2295, +-1303, -2130, 379, -1290, 1818, 25, 2642, 1362, +2757, 2293, 2008, 2595, 584, 2154, -826, 1013, +-1808, -501, -2281, -1775, -2010, -2268, -1010, -1944, +167, -1068, 1050, 69, 1433, 1039, 1185, 1425, +532, 1142, -230, 414, -849, -345, -1032, -781, +-666, -775, -36, -311, 629, 456, 1163, 1096, +1186, 1230, 593, 786, -221, -65, -975, -1029, +-1581, -1751, -1736, -1829, -1275, -1166, -458, -67, +525, 1091, 1500, 1885, 2090, 2016, 1997, 1507, +1367, 493, 342, -746, -895, -1621, -1906, -1757, +-2317, -1305, -2103, -494, -1376, 486, -275, 1249, +928, 1373, 1838, 811, 2134, -14, 1778, -715, +940, -1147, -105, -1057, -957, -374, -1371, 499, +-1334, 1204, -976, 1551, -433, 1326, 2, 502, +201, -586, 284, -1523, 303, -2040, 200, -1913, +137, -1081, 252, 131, 468, 1270, 669, 2038, +644, 2233, 290, 1744, -211, 727, -754, -414, +-1244, -1306, -1400, -1834, -1076, -1930, -479, -1438, +300, -486, 1042, 408, 1387, 953, 1267, 1265, +896, 1298, 334, 885, -326, 293, -798, -140, +-900, -374, -723, -394, -525, -233, -426, -55, +-358, -30, -205, -227, 46, -550, 231, -865, +411, -958, 747, -635, 1028, 14, 880, 807, +470, 1547, 21, 1917, -587, 1743, -1252, 1103, +-1485, 68, -1194, -1178, -659, -2130, 10, -2410, +729, -2090, 1230, -1308, 1258, -139, 852, 1039, +304, 1804, -239, 2156, -640, 2162, -752, 1707, +-548, 904, -217, -44, 23, -1052, 61, -1893, +23, -2356, -49, -2419, -211, -1957, -350, -893, +-253, 479, 69, 1809, 406, 2803, 670, 3077, +798, 2490, 631, 1225, 201, -394, -302, -1881, +-710, -2743, -991, -2789, -1057, -2130, -860, -984, +-369, 367, 342, 1486, 970, 2000, 1171, 1852, +1009, 1262, 578, 511, -101, -161, -685, -543, +-913, -619, -886, -563, -620, -501, -64, -467, +542, -403, 868, -334, 840, -288, 410, -126, +-297, 172, -969, 425, -1306, 539, -1136, 569, +-433, 548, 486, 369, 1260, 72, 1685, -79, +1627, -63, 990, -57, -71, -112, -1104, -298, +-1805, -606, -2081, -815, -1745, -833, -852, -689, +209, -269, 1076, 447, 1614, 1174, 1738, 1605, +1499, 1659, 991, 1292, 353, 475, -305, -545, +-919, -1437, -1443, -1968, -1719, -1944, -1673, -1387, +-1310, -524, -592, 395, 326, 1186, 1182, 1634, +1850, 1609, 2149, 1236, 1939, 677, 1253, 40, +205, -452, -1022, -687, -1964, -818, -2289, -932, +-2057, -921, -1447, -781, -496, -630, 560, -377, +1318, 106, 1654, 677, 1641, 1139, 1344, 1435, +869, 1519, 284, 1254, -310, 594, -741, -300, +-1063, -1162, -1418, -1800, -1543, -2108, -1247, -1916, +-704, -1140, -47, -18, 761, 1060, 1458, 1884, +1768, 2323, 1728, 2175, 1373, 1408, 593, 302, +-491, -800, -1457, -1675, -1997, -2123, -2038, -2012, +-1513, -1399, -556, -465, 442, 516, 1212, 1262, +1659, 1619, 1644, 1520, 1197, 1082, 462, 562, +-319, 19, -993, -500, -1394, -843, -1317, -1008, +-792, -1051, -130, -932, 448, -554, 861, -11, +1000, 514, 818, 1001, 374, 1290, -209, 1110, +-718, 570, -1024, -45, -1035, -639, -640, -1111, +47, -1218, 702, -819, 1225, -149, 1370, 407, +952, 747, 248, 935, -466, 859, -1079, 444, +-1385, -70, -1358, -479, -1053, -758, -397, -842, +450, -674, 1093, -333, 1417, 88, 1484, 487, +1140, 777, 358, 926, -338, 825, -696, 475, +-1030, 51, -1366, -430, -1246, -935, -759, -1244, +-295, -1186, 219, -759, 806, -106, 1149, 603, +1149, 1237, 967, 1603, 713, 1476, 288, 837, +-319, -19, -811, -818, -1068, -1422, -1230, -1632, +-1109, -1347, -620, -745, -10, -9, 520, 771, +938, 1367, 1115, 1535, 1001, 1307, 678, 764, +189, 21, -355, -710, -728, -1266, -825, -1431, +-683, -1135, -384, -642, -34, -60, 232, 640, +329, 1188, 219, 1321, 5, 1084, -148, 588, +-122, -87, -46, -775, 84, -1231, 346, -1286, +542, -924, 499, -263, 303, 489, -64, 1086, +-508, 1325, -741, 1063, -733, 387, -595, -396, +-283, -969, 101, -1145, 347, -861, 441, -240, +491, 393, 445, 755, 332, 788, 229, 466, +171, -47, 136, -425, 63, -517, -159, -326, +-507, 73, -827, 462, -1039, 589, -1048, 347, +-666, -113, 54, -604, 853, -931, 1528, -825, +1823, -300, 1586, 352, 979, 939, 20, 1258, +-1108, 1096, -1949, 485, -2254, -310, -1995, -991, +-1167, -1318, 16, -1202, 1218, -675, 2074, 65, +2283, 710, 1867, 1079, 1041, 1110, -46, 771, +-1101, 227, -1755, -248, -1906, -564, -1612, -745, +-868, -705, 85, -454, 886, -171, 1323, 39, +1354, 228, 953, 399, 285, 497, -273, 515, +-526, 445, -531, 269, -306, 37, 1, -281, +134, -643, 43, -832, -210, -793, -521, -561, +-690, -53, -576, 626, -149, 1153, 458, 1314, +1055, 1069, 1408, 418, 1277, -494, 542, -1316, +-468, -1700, -1256, -1469, -1625, -712, -1552, 299, +-936, 1269, 90, 1835, 1054, 1716, 1561, 938, +1557, -152, 1076, -1105, 147, -1654, -865, -1651, +-1385, -1001, -1337, 28, -869, 957, -98, 1454, +686, 1357, 1122, 741, 1074, -102, 617, -897, +-3, -1293, -609, -1039, -1004, -325, -910, 452, +-397, 985, 187, 1112, 658, 791, 858, 77, +670, -706, 192, -1194, -342, -1210, -650, -730, +-575, 73, -352, 876, -87, 1365, 318, 1284, +636, 650, 553, -211, 217, -914, -141, -1241, +-492, -1067, -719, -440, -571, 286, -69, 781, +405, 945, 642, 732, 706, 194, 529, -435, +135, -816, -279, -812, -585, -475, -738, 116, +-624, 723, -289, 979, 104, 803, 417, 354, +580, -231, 536, -767, 336, -1016, 120, -916, +-47, -541, -174, -30, -254, 461, -284, 813, +-286, 927, -278, 776, -191, 448, -58, 36, +67, -350, 209, -595, 344, -667, 386, -608, +384, -469, 292, -309, 51, -83, -206, 200, +-347, 390, -467, 491, -541, 628, -350, 672, +17, 467, 257, 129, 355, -136, 414, -403, +404, -702, 240, -804, 21, -701, -78, -524, +-117, -192, -276, 215, -370, 526, -258, 752, +-137, 875, -83, 797, 80, 540, 285, 183, +348, -213, 294, -599, 190, -900, 37, -1038, +-173, -934, -360, -606, -326, -143, -154, 376, +12, 869, 224, 1156, 401, 1150, 362, 913, +182, 471, -97, -183, -396, -802, -507, -1110, +-390, -1157, -187, -1023, 41, -582, 319, 24, +586, 509, 657, 817, 488, 941, 199, 848, +-135, 573, -479, 174, -703, -220, -735, -489, +-535, -554, -194, -480, 119, -356, 439, -176, +770, -47, 815, -112, 592, -205, 320, -146, +-60, 31, -459, 311, -621, 689, -627, 942, +-546, 901, -270, 515, 77, -172, 240, -870, +239, -1287, 217, -1356, 191, -998, 124, -265, +194, 545, 443, 1126, 586, 1308, 444, 1057, +129, 494, -306, -179, -799, -699, -1142, -879, +-1154, -709, -817, -326, -220, 98, 515, 367, +1228, 366, 1611, 125, 1507, -169, 1022, -352, +265, -334, -647, -92, -1330, 248, -1516, 545, +-1292, 709, -887, 552, -381, 94, 241, -368, +786, -665, 1023, -824, 1077, -747, 1035, -366, +787, 140, 378, 567, -27, 785, -402, 713, +-778, 482, -1111, 125, -1238, -355, -1086, -699, +-644, -720, 61, -523, 806, -193, 1288, 236, +1478, 642, 1335, 785, 744, 603, -25, 213, +-623, -285, -1011, -760, -1100, -974, -865, -850, +-456, -420, -23, 209, 237, 813, 258, 1201, +226, 1260, 165, 834, 110, 44, 235, -758, +544, -1327, 811, -1541, 837, -1250, 541, -488, +-21, 433, -724, 1131, -1349, 1447, -1582, 1347, +-1285, 838, -621, 61, 235, -654, 1070, -1106, +1607, -1193, 1674, -901, 1265, -401, 516, 116, +-305, 560, -949, 771, -1216, 702, -1097, 468, +-723, 187, -217, -119, 186, -378, 315, -479, +292, -419, 233, -301, 180, -90, 233, 208, +413, 406, 597, 397, 647, 285, 465, 55, +93, -275, -407, -533, -949, -588, -1288, -401, +-1172, -21, -671, 372, 62, 679, 860, 787, +1389, 579, 1422, 144, 1017, -322, 320, -731, +-450, -929, -982, -804, -1071, -403, -762, 111, +-208, 553, 373, 812, 697, 836, 605, 553, +262, 87, -163, -327, -566, -551, -698, -608, +-393, -523, 134, -257, 622, 91, 928, 286, +916, 329, 548, 307, -41, 201, -611, 8, +-924, -145, -920, -199, -641, -176, -196, -106, +254, -20, 571, 60, 655, 129, 473, 119, +229, 72, 114, 33, 89, -41, 69, -130, +88, -149, 113, -141, 5, -116, -287, -44, +-570, 46, -672, 93, -623, 94, -359, 51, +165, 9, 665, 0, 973, 48, 1066, 125, +840, 203, 335, 213, -215, 73, -690, -181, +-1026, -423, -1070, -639, -710, -727, -150, -523, +327, -44, 719, 493, 986, 946, 886, 1217, +465, 1142, 8, 604, -389, -201, -700, -961, +-748, -1465, -501, -1591, -67, -1193, 379, -400, +657, 472, 704, 1161, 522, 1462, 142, 1292, +-272, 781, -595, 90, -738, -495, -590, -768, +-169, -760, 305, -599, 629, -363, 746, -173, +651, -130, 347, -232, 0, -281, -239, -106, +-372, 244, -426, 630, -326, 1016, -125, 1219, +-15, 1007, -20, 395, -26, -407, -39, -1219, +-10, -1783, 146, -1862, 405, -1381, 650, -461, +703, 664, 515, 1618, 200, 2088, -218, 1901, +-665, 1139, -956, 76, -980, -912, -752, -1527, +-324, -1629, 212, -1249, 780, -572, 1214, 82, +1295, 561, 1014, 750, 538, 603, -49, 344, +-645, 181, -1032, 74, -1093, 90, -936, 244, +-625, 336, -109, 197, 485, -109, 850, -493, +931, -834, 823, -985, 543, -845, 147, -435, +-193, 144, -340, 723, -293, 1129, -199, 1182, +-121, 888, -42, 371, -48, -228, -203, -737, +-376, -965, -416, -901, -307, -638, -48, -289, +412, 35, 915, 230, 1197, 326, 1145, 383, +781, 413, 142, 400, -644, 389, -1293, 321, +-1503, 139, -1301, -110, -834, -383, -101, -665, +735, -779, 1326, -664, 1521, -412, 1350, -47, +875, 440, 227, 808, -355, 860, -730, 657, +-928, 322, -971, -107, -797, -495, -481, -690, +-171, -626, 138, -399, 479, -114, 727, 117, +820, 224, 829, 217, 764, 139, 530, 51, +106, 60, -351, 122, -703, 182, -956, 216, +-973, 117, -677, -182, -245, -466, 186, -567, +611, -484, 905, -251, 980, 150, 870, 560, +582, 750, 132, 621, -316, 270, -649, -217, +-815, -669, -715, -901, -380, -809, 40, -406, +427, 185, 653, 716, 641, 1017, 401, 978, +40, 554, -294, -143, -481, -797, -424, -1192, +-104, -1205, 314, -798, 682, -71, 848, 711, +649, 1255, 143, 1309, -451, 882, -925, 161, +-1071, -590, -836, -1156, -296, -1326, 418, -972, +1006, -250, 1184, 461, 997, 947, 561, 1090, +5, 797, -421, 177, -600, -420, -528, -792, +-212, -867, 86, -610, 142, -110, 51, 362, +-146, 618, -429, 618, -498, 396, -154, -20, +437, -431, 1010, -632, 1400, -561, 1408, -254, +886, 186, -32, 493, -1010, 547, -1751, 381, +-1996, 53, -1599, -335, -644, -570, 524, -559, +1496, -322, 2057, 24, 2108, 347, 1542, 524, +528, 526, -487, 335, -1245, -12, -1685, -375, +-1638, -578, -1088, -627, -305, -495, 448, -165, +996, 212, 1233, 467, 1207, 610, 929, 588, +468, 359, -16, 3, -414, -320, -641, -558, +-672, -641, -553, -559, -265, -342, 102, -43, +309, 292, 304, 536, 300, 591, 308, 453, +155, 249, -12, -20, 21, -345, 92, -535, +113, -478, 234, -348, 345, -190, 189, 33, +-83, 214, -265, 249, -410, 237, -419, 200, +-211, 117, 30, 38, 262, 15, 479, -58, +567, -173, 519, -253, 354, -305, 104, -316, +-142, -171, -321, 62, -339, 280, -180, 420, +27, 424, 163, 237, 252, -63, 258, -387, +110, -567, -17, -506, -10, -273, -39, 37, +-100, 381, 5, 554, 248, 457, 380, 183, +388, -109, 384, -352, 222, -459, -101, -385, +-316, -174, -397, 28, -410, 177, -342, 225, +-185, 143, 72, -16, 358, -95, 623, -69, +823, 27, 788, 161, 497, 277, 106, 214, +-272, -30, -567, -330, -662, -575, -553, -692, +-373, -501, -129, -50, 200, 404, 495, 721, +684, 871, 748, 695, 665, 223, 420, -323, +122, -741, -76, -906, -257, -749, -463, -410, +-544, 15, -487, 438, -321, 666, -69, 587, +204, 332, 501, 35, 711, -214, 693, -354, +541, -321, 342, -184, 74, 1, -226, 155, +-436, 161, -476, 8, -347, -138, -134, -258, +62, -345, 227, -275, 317, -18, 287, 218, +254, 379, 215, 481, 151, 441, 168, 204, +229, -76, 258, -304, 261, -485, 170, -622, +-22, -611, -245, -444, -438, -152, -509, 193, +-401, 518, -145, 752, 209, 847, 592, 661, +909, 236, 1038, -239, 857, -675, 371, -1038, +-240, -1106, -792, -820, -1080, -305, -963, 291, +-568, 841, 0, 1137, 664, 1073, 1098, 682, +1172, 106, 954, -505, 424, -911, -250, -1024, +-761, -886, -922, -520, -682, 27, -159, 467, +445, 645, 865, 653, 908, 514, 650, 184, +237, -112, -285, -232, -688, -240, -699, -234, +-379, -211, 30, -220, 450, -286, 819, -350, +913, -296, 622, -97, 184, 250, -147, 605, +-395, 779, -551, 694, -472, 387, -260, -149, +-55, -739, 184, -1118, 425, -1113, 551, -741, +535, -95, 458, 621, 369, 1168, 171, 1294, +-145, 922, -377, 181, -422, -615, -368, -1186, +-166, -1330, 242, -992, 602, -269, 663, 521, +488, 1074, 184, 1200, -176, 871, -457, 182, +-485, -568, -186, -1094, 294, -1176, 737, -771, +991, -85, 879, 550, 372, 960, -355, 963, +-1022, 544, -1266, -57, -929, -534, -162, -754, +728, -678, 1369, -356, 1509, 77, 1122, 358, +353, 360, -498, 163, -1081, -90, -1203, -322, +-813, -347, -42, -82, 775, 364, 1286, 730, +1222, 775, 564, 415, -280, -183, -915, -868, +-1156, -1395, -801, -1456, 64, -904, 957, 33, +1497, 1003, 1530, 1692, 1032, 1870, 132, 1377, +-851, 379, -1509, -745, -1551, -1637, -959, -2020, +-12, -1702, 908, -876, 1522, 135, 1591, 1026, +1066, 1520, 269, 1465, -434, 993, -861, 315, +-876, -338, -467, -787, 96, -904, 501, -748, +647, -469, 507, -197, 100, 50, -342, 187, +-555, 170, -476, 92, -116, 81, 448, 125, +973, 225, 1217, 326, 1102, 366, 630, 261, +-102, 28, -814, -260, -1215, -529, -1237, -716, +-915, -666, -265, -410, 537, -91, 1165, 220, +1483, 508, 1463, 659, 1047, 624, 352, 401, +-327, 87, -795, -230, -998, -473, -920, -581, +-565, -505, -89, -313, 279, -25, 484, 247, +603, 349, 621, 245, 499, 52, 349, -168, +313, -335, 299, -365, 203, -158, 119, 220, +-9, 559, -302, 669, -550, 550, -592, 180, +-506, -340, -255, -801, 217, -1028, 695, -959, +924, -591, 953, -63, 888, 464, 587, 835, +61, 1026, -345, 985, -465, 680, -490, 214, +-488, -255, -317, -725, -74, -1088, 37, -1190, +134, -1013, 336, -648, 502, -84, 565, 562, +647, 1081, 710, 1308, 568, 1227, 258, 830, +-82, 172, -459, -575, -795, -1128, -915, -1370, +-715, -1240, -280, -760, 230, -101, 733, 483, +1101, 861, 1186, 919, 993, 697, 589, 322, +96, -38, -349, -237, -651, -239, -745, -196, +-656, -147, -390, -138, -2, -237, 311, -428, +497, -546, 643, -481, 742, -207, 677, 197, +458, 622, 245, 887, 22, 906, -259, 645, +-438, 128, -443, -501, -312, -931, -99, -1062, +127, -921, 306, -500, 409, 85, 457, 538, +396, 766, 236, 743, 139, 481, 101, 101, +59, -207, 21, -367, -2, -362, 14, -271, +15, -157, -25, -81, -33, -69, 8, -127, +110, -147, 244, -74, 359, 101, 423, 289, +376, 408, 216, 370, -5, 163, -189, -149, +-247, -439, -171, -631, 79, -586, 369, -266, +512, 190, 534, 548, 399, 702, 61, 596, +-321, 219, -552, -342, -512, -794, -248, -921, +168, -703, 631, -209, 925, 451, 927, 925, +612, 999, 71, 705, -436, 126, -712, -568, +-684, -1047, -406, -1134, 46, -782, 535, -108, +788, 618, 708, 1055, 442, 1068, 117, 656, +-178, -60, -352, -827, -239, -1242, 110, -1105, +416, -494, 566, 312, 523, 1015, 262, 1313, +-117, 1091, -489, 361, -655, -591, -487, -1312, +-47, -1510, 503, -1196, 929, -414, 1053, 575, +834, 1335, 355, 1555, -198, 1222, -611, 438, +-721, -501, -592, -1227, -319, -1449, 116, -1157, +549, -520, 734, 227, 647, 833, 429, 1021, +165, 818, -137, 400, -264, -83, -111, -477, +81, -610, 234, -493, 335, -249, 265, -1, +132, 201, 11, 248, -126, 120, -181, -58, +-93, -148, 43, -191, 183, -164, 356, -38, +484, 138, 462, 246, 350, 263, 238, 188, +123, 63, -30, -134, -192, -330, -302, -433, +-370, -420, -329, -287, -107, -25, 183, 210, +469, 351, 691, 414, 720, 360, 558, 170, +309, -15, 48, -164, -198, -301, -385, -401, +-408, -366, -300, -257, -137, -166, 73, -51, +246, 158, 316, 302, 366, 328, 447, 310, +480, 286, 463, 177, 419, -14, 231, -260, +-68, -452, -308, -532, -470, -520, -472, -416, +-306, -134, -101, 237, 196, 538, 529, 658, +700, 630, 706, 440, 590, 73, 352, -380, +64, -690, -185, -779, -328, -647, -365, -338, +-342, 77, -294, 434, -183, 590, 50, 479, +343, 241, 559, -13, 686, -204, 761, -276, +674, -195, 361, -30, -43, 128, -447, 120, +-751, -37, -789, -234, -532, -406, -63, -502, +470, -361, 850, -4, 996, 415, 895, 720, +589, 804, 201, 586, -229, 136, -599, -386, +-716, -779, -574, -928, -275, -770, 100, -392, +443, 52, 618, 440, 639, 674, 606, 620, +491, 393, 266, 147, 26, -92, -218, -295, +-451, -338, -562, -251, -475, -149, -230, -136, +92, -161, 440, -164, 746, -143, 910, -101, +844, 65, 519, 288, 68, 417, -347, 403, +-667, 283, -774, 33, -586, -248, -223, -447, +210, -502, 626, -418, 874, -190, 897, 74, +742, 258, 417, 315, -15, 279, -395, 116, +-594, -94, -589, -214, -457, -194, -232, -111, +119, -1, 493, 112, 748, 213, 820, 187, +654, 41, 303, -118, -63, -257, -365, -395, +-522, -408, -455, -282, -219, -56, 63, 215, +303, 445, 515, 521, 620, 458, 456, 260, +138, -34, -120, -328, -264, -504, -219, -551, +6, -458, 221, -275, 332, -38, 345, 165, +248, 288, 67, 320, -97, 310, -164, 269, +-113, 216, 45, 115, 247, 1, 381, -148, +384, -362, 241, -564, -12, -607, -224, -491, +-226, -201, -61, 213, 127, 605, 305, 795, +417, 717, 372, 375, 199, -90, -79, -536, +-351, -794, -418, -769, -239, -452, 114, 6, +513, 434, 775, 662, 750, 636, 398, 337, +-125, -142, -513, -593, -611, -784, -510, -665, +-203, -266, 320, 258, 738, 719, 839, 941, +711, 800, 341, 295, -163, -325, -510, -841, +-553, -1075, -300, -943, 53, -490, 296, 88, +415, 591, 389, 814, 211, 749, 7, 482, +-61, 153, 26, -125, 152, -268, 263, -319, +334, -304, 258, -303, -10, -359, -342, -427, +-535, -379, -455, -204, -109, 86, 332, 451, +702, 792, 923, 898, 811, 691, 378, 252, +-51, -285, -398, -816, -670, -1086, -679, -975, +-382, -572, 39, -47, 389, 459, 596, 771, +623, 811, 448, 542, 226, 119, 109, -234, +79, -420, 76, -433, 67, -235, 1, 38, +-173, 217, -372, 217, -452, 58, -410, -211, +-185, -445, 257, -530, 725, -389, 1005, -77, +1027, 314, 771, 645, 230, 800, -419, 691, +-875, 343, -1051, -177, -918, -635, -446, -873, +181, -895, 739, -703, 1088, -262, 1113, 230, +820, 581, 350, 726, -121, 690, -468, 485, +-592, 191, -524, -118, -367, -342, -107, -463, +176, -466, 311, -386, 326, -277, 330, -186, +338, -59, 303, 101, 263, 263, 270, 369, +199, 424, 2, 404, -212, 275, -358, -6, +-365, -318, -274, -521, -146, -565, 78, -489, +352, -260, 535, 59, 577, 336, 509, 471, +347, 481, 93, 333, -170, 69, -346, -182, +-384, -354, -320, -477, -208, -439, -3, -226, +253, 49, 444, 292, 540, 451, 495, 439, +328, 278, 120, 2, -91, -294, -213, -506, +-223, -536, -214, -384, -176, -94, -38, 191, +149, 392, 269, 457, 335, 364, 374, 130, +287, -93, 95, -212, -40, -231, -62, -199, +-60, -110, -81, -56, -80, -99, -77, -168, +-69, -165, 27, -141, 162, -41, 275, 188, +379, 437, 418, 544, 356, 488, 178, 243, +-111, -115, -392, -494, -522, -780, -446, -833, +-198, -568, 174, -127, 568, 306, 796, 601, +775, 734, 524, 654, 106, 362, -317, -23, +-610, -294, -696, -440, -505, -489, -104, -418, +304, -238, 551, -62, 630, 65, 545, 122, +301, 127, 37, 87, -132, 77, -207, 124, +-160, 189, -36, 209, 41, 181, 21, 59, +-67, -109, -149, -280, -145, -430, -15, -484, +225, -363, 494, -177, 671, 51, 631, 308, +369, 489, -5, 511, -385, 420, -668, 209, +-749, -49, -538, -276, -86, -438, 388, -529, +720, -500, 844, -359, 716, -103, 391, 193, +21, 439, -264, 578, -398, 573, -381, 350, +-247, 8, -100, -333, 3, -591, 69, -695, +77, -548, 62, -197, 130, 221, 297, 543, +483, 689, 593, 582, 534, 244, 257, -212, +-171, -587, -582, -744, -823, -623, -813, -302, +-530, 129, -5, 532, 620, 763, 1052, 679, +1128, 328, 900, -124, 399, -510, -257, -752, +-731, -716, -841, -381, -671, 72, -319, 432, +89, 631, 388, 570, 525, 258, 480, -139, +305, -432, 150, -548, 47, -411, -21, -94, +47, 247, 168, 461, 136, 475, -20, 253, +-186, -105, -337, -449, -387, -606, -239, -536, +34, -268, 316, 102, 530, 451, 590, 620, +480, 574, 266, 341, -22, 19, -297, -269, +-417, -441, -362, -530, -190, -483, 22, -299, +192, -81, 278, 102, 268, 273, 164, 373, +56, 392, 22, 340, 46, 235, 95, 73, +161, -96, 212, -273, 168, -421, 0, -483, +-178, -423, -270, -280, -286, -33, -202, 256, +-1, 468, 220, 528, 370, 463, 429, 253, +386, -54, 241, -333, 34, -460, -161, -436, +-263, -285, -250, -82, -160, 103, -40, 212, +79, 230, 171, 135, 204, 19, 166, -63, +108, -103, 60, -101, 15, -17, -4, 95, +69, 163, 193, 138, 231, 60, 148, -57, +17, -180, -122, -281, -232, -295, -256, -231, +-170, -87, -36, 84, 111, 237, 293, 337, +428, 351, 430, 232, 318, 74, 111, -98, +-106, -272, -251, -347, -315, -288, -258, -219, +-140, -113, -80, 37, 1, 125, 161, 124, +277, 151, 323, 175, 363, 158, 332, 116, +193, 89, 28, 20, -150, -116, -309, -253, +-372, -302, -340, -290, -207, -197, 19, -37, +287, 135, 485, 272, 526, 327, 449, 198, +265, 17, -28, -79, -281, -128, -404, -136, +-398, -25, -261, 61, -40, 25, 203, -89, +372, -191, 382, -245, 285, -216, 168, -76, +37, 165, -103, 344, -184, 386, -196, 307, +-159, 125, -52, -124, 76, -321, 175, -422, +248, -351, 245, -146, 160, 41, 35, 151, +-95, 223, -168, 183, -195, 72, -148, -13, +24, -43, 234, -32, 406, 31, 448, 83, +255, 89, -67, 7, -333, -133, -509, -272, +-514, -353, -241, -324, 177, -126, 565, 139, +820, 402, 782, 583, 432, 564, -92, 317, +-650, -52, -970, -463, -883, -748, -483, -789, +131, -561, 751, -137, 1067, 356, 986, 704, +607, 827, 31, 689, -585, 338, -964, -97, +-909, -491, -483, -764, 104, -772, 617, -533, +839, -161, 695, 212, 289, 487, -190, 584, +-500, 486, -475, 243, -225, 45, 58, -59, +322, -138, 478, -203, 400, -231, 121, -323, +-193, -451, -384, -468, -407, -255, -276, 113, +-8, 512, 276, 830, 426, 917, 423, 609, +306, 35, 112, -582, -84, -1030, -202, -1103, +-240, -760, -222, -196, -147, 452, -24, 926, +85, 973, 109, 681, 107, 250, 159, -269, +192, -621, 174, -660, 140, -513, 67, -282, +-44, 13, -154, 230, -210, 336, -172, 360, +-64, 287, 78, 108, 200, -63, 268, -195, +303, -267, 219, -229, -48, -77, -314, 35, +-374, 73, -273, 79, -80, 40, 212, -39, +487, -39, 555, 7, 390, 66, 100, 121, +-204, 145, -467, 105, -585, -2, -456, -177, +-199, -277, 85, -282, 382, -249, 558, -107, +544, 161, 409, 330, 203, 381, -26, 355, +-243, 198, -383, -42, -378, -258, -283, -414, +-174, -403, -65, -275, 34, -129, 129, 49, +260, 214, 384, 238, 413, 220, 371, 231, +265, 213, 39, 135, -206, 53, -350, -52, +-398, -215, -386, -422, -328, -497, -205, -396, +-22, -200, 170, 57, 388, 357, 595, 557, +675, 598, 571, 474, 305, 228, -75, -92, +-498, -396, -801, -630, -835, -705, -636, -584, +-260, -253, 236, 199, 639, 601, 815, 758, +786, 633, 540, 291, 149, -125, -216, -484, +-492, -618, -598, -468, -423, -136, -121, 198, +83, 406, 174, 365, 128, 126, -14, -155, +-72, -351, -14, -401, 167, -231, 429, 87, +525, 373, 384, 454, 171, 336, -126, 107, +-514, -116, -773, -256, -756, -288, -486, -273, +-27, -203, 507, -119, 929, -73, 1056, -19, +787, 145, 205, 347, -442, 475, -911, 417, +-1043, 149, -752, -221, -159, -490, 424, -585, +788, -456, 874, -119, 634, 281, 170, 497, +-248, 467, -528, 262, -672, -38, -572, -333, +-249, -445, 141, -393, 507, -221, 703, 83, +588, 407, 263, 551, -85, 501, -357, 289, +-471, -29, -408, -367, -258, -625, -123, -753, +-3, -650, 138, -322, 300, 145, 452, 615, +478, 985, 318, 1097, 95, 807, -137, 171, +-379, -522, -485, -1077, -422, -1311, -322, -1089, +-157, -502, 118, 188, 362, 801, 493, 1125, +535, 1069, 422, 719, 165, 214, -111, -314, +-345, -667, -466, -819, -400, -774, -251, -524, +-122, -121, 35, 264, 192, 495, 236, 534, +216, 451, 253, 242, 287, -24, 243, -173, +134, -152, -27, -116, -182, -91, -323, -74, +-488, -117, -523, -218, -340, -251, -81, -186, +239, -26, 625, 210, 845, 461, 755, 578, +407, 467, -100, 112, -573, -339, -832, -662, +-851, -734, -601, -574, -140, -154, 317, 366, +675, 705, 857, 766, 692, 599, 280, 187, +-105, -301, -403, -661, -566, -794, -494, -668, +-274, -308, -52, 142, 119, 569, 216, 785, +228, 711, 193, 430, 142, 54, 75, -352, +32, -632, 33, -701, 21, -531, -30, -217, +-129, 67, -251, 252, -280, 389, -204, 429, +-64, 413, 172, 365, 413, 226, 459, -16, +282, -274, 29, -521, -227, -640, -445, -563, +-467, -335, -251, -21, 43, 338, 316, 591, +514, 677, 495, 618, 195, 437, -209, 57, +-488, -441, -576, -791, -456, -828, -109, -643, +335, -259, 639, 252, 652, 677, 447, 835, +101, 704, -361, 306, -697, -187, -708, -591, +-487, -760, -119, -625, 289, -233, 572, 220, +679, 566, 606, 652, 316, 460, -128, 88, +-512, -281, -677, -499, -621, -518, -382, -411, +-14, -159, 344, 166, 526, 403, 519, 510, +426, 516, 210, 319, -141, 5, -425, -270, +-516, -492, -417, -609, -167, -494, 137, -242, +359, 59, 336, 371, 135, 595, -19, 614, +-118, 458, -168, 147, -86, -237, 41, -531, +85, -586, 72, -440, 52, -198, 23, 53, +-37, 265, -117, 332, -173, 287, -185, 211, +-132, 121, 9, 9, 164, -60, 255, -121, +308, -162, 266, -182, 66, -201, -147, -195, +-292, -95, -406, 39, -408, 207, -227, 381, +63, 414, 312, 207, 442, -94, 450, -338, +282, -441, -35, -395, -312, -180, -446, 120, +-397, 334, -159, 367, 113, 292, 297, 137, +353, -52, 188, -211, -75, -305, -231, -318, +-315, -191, -287, -19, -71, 126, 150, 250, +306, 311, 435, 247, 358, 130, 66, -35, +-242, -207, -496, -299, -568, -287, -372, -204, +-76, -36, 189, 106, 371, 167, 383, 200, +301, 228, 213, 190, 111, 118, 6, 13, +-173, -145, -408, -314, -501, -383, -434, -323, +-242, -121, 91, 139, 405, 340, 529, 419, +458, 368, 245, 170, -12, -62, -231, -275, +-371, -433, -380, -420, -265, -202, -83, 44, +125, 242, 282, 345, 284, 288, 112, 118, +-144, -43, -321, -177, -281, -215, -44, -165, +246, -81, 406, 28, 320, 152, 104, 185, +-116, 141, -332, 48, -446, -103, -420, -270, +-304, -288, -61, -150, 246, 32, 497, 176, +635, 307, 536, 363, 179, 280, -263, 75, +-624, -166, -770, -410, -614, -554, -232, -504, +210, -231, 575, 156, 713, 527, 545, 708, +170, 600, -268, 259, -568, -150, -568, -527, +-342, -685, -45, -527, 216, -205, 333, 114, +285, 412, 104, 504, -99, 338, -161, 90, +-118, -154, -86, -327, -44, -256, 29, -64, +91, 93, 83, 212, -1, 234, -92, 86, +-139, -109, -159, -294, -162, -392, -75, -284, +123, -28, 300, 221, 377, 441, 307, 532, +26, 415, -337, 113, -550, -249, -552, -553, +-385, -675, -69, -568, 269, -216, 473, 255, +545, 633, 494, 741, 305, 584, 29, 193, +-352, -290, -745, -605, -850, -575, -622, -333, +-243, -74, 218, 100, 642, 189, 834, 202, +756, 201, 455, 207, 14, 241, -423, 230, +-743, 88, -857, -175, -680, -430, -299, -595, +109, -558, 451, -297, 650, 100, 657, 493, +516, 788, 245, 840, -113, 592, -457, 95, +-743, -470, -798, -900, -461, -1038, 18, -845, +338, -361, 511, 248, 540, 814, 362, 1124, +80, 1022, -146, 554, -294, -45, -371, -599, +-318, -925, -132, -934, 93, -645, 203, -172, +99, 305, -96, 565, -191, 615, -127, 505, +47, 244, 209, -78, 237, -269, 128, -279, +8, -127, -39, 69, -75, 153, -168, 38, +-316, -191, -429, -426, -352, -526, -63, -398, +310, -8, 599, 507, 624, 884, 350, 908, +-50, 607, -355, 82, -508, -502, -584, -937, +-515, -1028, -209, -768, 160, -281, 424, 242, +566, 647, 503, 803, 205, 715, -160, 436, +-406, 55, -452, -282, -340, -433, -185, -416, +-2, -239, 207, -46, 299, -44, 225, -177, +59, -221, -168, -193, -321, -34, -223, 332, +40, 688, 234, 782, 210, 595, 10, 107, +-161, -481, -210, -867, -149, -968, -11, -793, +64, -280, 32, 352, -4, 817, -2, 983, +58, 806, 96, 328, -68, -240, -291, -706, +-294, -885, -103, -704, 164, -245, 377, 304, +389, 732, 208, 797, -104, 466, -448, -98, +-591, -592, -492, -782, -279, -573, 96, -66, +527, 478, 681, 743, 505, 649, 130, 258, +-311, -232, -570, -556, -536, -607, -301, -447, +-32, -94, 125, 279, 231, 492, 312, 500, +246, 298, 33, -43, -271, -304, -501, -453, +-401, -449, -23, -196, 402, 169, 662, 428, +512, 541, 4, 412, -475, 74, -674, -338, +-575, -694, -287, -747, -25, -333, 163, 258, +352, 720, 456, 878, 442, 601, 290, -26, +-62, -634, -395, -925, -492, -741, -354, -200, +-43, 422, 140, 818, 17, 817, -154, 451, +-241, -101, -188, -649, 71, -898, 343, -717, +454, -234, 404, 356, 211, 829, -42, 899, +-300, 546, -545, -48, -619, -591, -477, -824, +-211, -693, 165, -288, 461, 273, 452, 674, +312, 724, 172, 446, -3, -46, -115, -522, +-227, -739, -324, -641, -200, -181, -7, 450, +87, 874, 95, 895, -88, 490, -330, -258, +-349, -930, -159, -1173, 186, -882, 531, -152, +582, 674, 328, 1184, -2, 1208, -273, 676, +-459, -182, -542, -932, -451, -1278, -195, -1078, +92, -372, 351, 476, 460, 1150, 265, 1352, +-40, 889, -256, -25, -341, -943, -144, -1476, +172, -1295, 273, -506, 249, 519, 113, 1364, +-173, 1590, -330, 1068, -389, 108, -481, -958, +-372, -1611, -71, -1453, 260, -662, 607, 375, +702, 1278, 431, 1523, 68, 1033, -267, 112, +-503, -846, -540, -1352, -467, -1164, -314, -498, +-78, 388, 138, 1096, 327, 1253, 422, 881, +314, 169, 101, -677, -96, -1245, -159, -1264, +-74, -725, -63, 110, -150, 843, -198, 1196, +-249, 1089, -204, 546, -19, -174, 97, -777, +196, -1023, 317, -804, 236, -286, 42, 273, +-111, 720, -311, 775, -420, 380, -288, -193, +-28, -683, 247, -796, 374, -354, 264, 295, +35, 829, -184, 1046, -251, 711, -209, -24, +-212, -736, -160, -1244, -33, -1258, 74, -674, +208, 177, 264, 986, 153, 1453, 7, 1241, +-170, 519, -243, -370, -67, -1128, 46, -1351, +-4, -917, -11, -149, -115, 658, -228, 1150, +-115, 1059, -72, 515, -86, -221, 79, -966, +179, -1306, 263, -986, 438, -205, 291, 682, +-75, 1361, -300, 1459, -513, 913, -605, 33, +-388, -880, -117, -1523, 97, -1516, 295, -923, +367, -49, 357, 873, 369, 1469, 274, 1404, +25, 843, -207, 5, -361, -836, -509, -1200, +-566, -980, -404, -456, -155, 212, 93, 659, +402, 644, 567, 407, 526, 100, 448, -293, +159, -479, -300, -350, -554, -68, -679, 270, +-674, 489, -323, 387, 109, 120, 443, -172, +722, -460, 651, -551, 226, -306, -186, 58, +-515, 347, -715, 484, -598, 383, -204, 117, +274, -105, 631, -308, 677, -447, 377, -329, +-98, -29, -475, 246, -614, 452, -540, 450, +-203, 245, 230, -6, 408, -287, 392, -518, +295, -507, 3, -357, -301, -90, -445, 303, +-437, 563, -136, 585, 297, 501, 518, 217, +530, -204, 264, -509, -285, -633, -669, -567, +-698, -259, -524, 107, -169, 381, 242, 527, +539, 496, 701, 269, 638, -57, 304, -324, +-140, -390, -557, -275, -837, -65, -796, 121, +-366, 208, 216, 202, 596, 116, 644, -59, +423, -197, -12, -254, -420, -217, -534, -37, +-387, 185, -20, 343, 431, 459, 634, 393, +532, 90, 139, -297, -482, -634, -901, -776, +-881, -558, -558, -92, -8, 462, 571, 927, +908, 1028, 956, 674, 661, 23, 86, -690, +-474, -1119, -870, -1068, -1002, -587, -723, 110, +-183, 741, 339, 1056, 701, 944, 709, 421, +361, -209, -26, -652, -260, -801, -344, -572, +-309, -90, -150, 292, 77, 466, 168, 367, +126, 8, 54, -302, -129, -393, -311, -315, +-334, 33, -228, 482, 91, 750, 504, 787, +605, 483, 344, -201, -81, -913, -523, -1405, +-694, -1466, -502, -824, -158, 323, 266, 1410, +608, 2025, 604, 1852, 343, 916, -9, -410, +-361, -1602, -564, -2143, -599, -1786, -453, -737, +-67, 548, 368, 1524, 616, 1794, 632, 1281, +436, 238, 65, -809, -398, -1334, -711, -1211, +-619, -499, -273, 481, 102, 1166, 425, 1228, +442, 698, 149, -197, -97, -1044, -228, -1496, +-277, -1339, -154, -533, 33, 564, 197, 1422, +312, 1789, 251, 1460, 98, 504, -101, -610, +-399, -1484, -551, -1848, -442, -1456, -185, -465, +199, 674, 486, 1520, 430, 1699, 218, 1118, +3, 86, -190, -1001, -168, -1649, -19, -1460, +54, -484, 131, 771, 72, 1669, -195, 1772, +-371, 1055, -428, -199, -411, -1473, -208, -2189, +162, -1994, 582, -936, 850, 597, 780, 1964, +415, 2576, -139, 2161, -673, 904, -915, -729, +-857, -2127, -552, -2684, -16, -2094, 461, -625, +618, 1056, 510, 2165, 230, 2235, -80, 1391, +-198, 41, -149, -1320, 16, -1977, 286, -1576, +353, -404, 84, 926, -313, 1750, -714, 1658, +-927, 772, -797, -537, -365, -1735, 332, -2148, +1077, -1508, 1464, -116, 1253, 1467, 512, 2449, +-437, 2320, -1246, 1189, -1542, -482, -1175, -2074, +-438, -2806, 336, -2250, 940, -669, 1079, 1231, +707, 2593, 176, 2765, -277, 1713, -585, -87, +-596, -1855, -299, -2792, 172, -2445, 587, -1039, +561, 816, 115, 2341, -333, 2778, -671, 1968, +-798, 411, -467, -1288, 137, -2446, 672, -2478, +929, -1439, 731, 122, 228, 1590, -338, 2217, +-820, 1718, -896, 570, -503, -635, 50, -1404, +583, -1330, 847, -576, 576, 316, -3, 895, +-504, 858, -805, 248, -768, -449, -392, -876, +105, -867, 630, -333, 1013, 471, 931, 1035, +418, 1151, -253, 786, -893, -2, -1212, -830, +-932, -1221, -210, -1057, 521, -426, 891, 374, +738, 872, 248, 883, -171, 529, -339, -105, +-326, -666, -145, -756, 103, -361, 233, 276, +276, 843, 173, 972, -158, 558, -464, -210, +-580, -1045, -484, -1478, -80, -1164, 451, -279, +760, 790, 712, 1578, 356, 1697, -142, 1065, +-513, 30, -616, -973, -496, -1637, -270, -1671, +6, -978, 354, 116, 591, 1152, 460, 1759, +91, 1567, -295, 614, -628, -469, -669, -1323, +-287, -1678, 185, -1157, 519, -117, 669, 748, +498, 1264, 170, 1263, -62, 672, -332, -30, +-653, -560, -758, -953, -582, -911, -252, -413, +240, 102, 732, 371, 828, 418, 558, 298, +244, 104, -37, -2, -279, 104, -427, 334, +-468, 467, -399, 293, -290, -224, -140, -826, +151, -1169, 362, -1088, 307, -459, 233, 541, +213, 1408, 111, 1819, 0, 1539, -111, 470, +-199, -837, -120, -1796, -4, -2122, -28, -1520, +-73, -242, -194, 985, -381, 1822, -295, 1969, +-21, 1251, 241, 108, 546, -990, 614, -1720, +354, -1613, 75, -822, -226, 146, -533, 1101, +-645, 1574, -603, 1140, -405, 181, 67, -739, +560, -1245, 733, -1073, 619, -328, 274, 563, +-231, 1233, -567, 1252, -580, 496, -423, -550, +-116, -1331, 275, -1548, 477, -1048, 470, 101, +385, 1359, 110, 1994, -317, 1719, -573, 666, +-598, -687, -442, -1775, 27, -2184, 515, -1673, +633, -402, 546, 947, 291, 1797, -146, 2000, +-448, 1463, -516, 373, -392, -739, -100, -1528, +196, -1648, 351, -1072, 336, -253, 149, 534, +-154, 1066, -394, 982, -434, 467, -268, -48, +72, -455, 438, -519, 570, -144, 412, 260, +158, 501, -204, 525, -627, 170, -664, -420, +-349, -867, -133, -948, 128, -637, 451, -59, +409, 629, 181, 1115, 47, 1088, -185, 641, +-298, 36, -61, -545, 199, -779, 342, -600, +362, -258, 111, 116, -329, 322, -740, 148, +-921, -182, -681, -466, -73, -527, 621, -172, +1134, 381, 1306, 892, 1043, 1267, 304, 1174, +-626, 486, -1258, -486, -1506, -1363, -1282, -1774, +-421, -1547, 527, -843, 1086, 246, 1323, 1279, +1050, 1682, 290, 1561, -417, 1025, -831, 76, +-916, -781, -584, -1194, -76, -1219, 362, -803, +658, -47, 582, 553, 178, 757, -323, 580, +-811, 147, -900, -328, -489, -643, 76, -569, +707, -147, 1170, 395, 1079, 936, 525, 1170, +-189, 860, -810, 167, -1137, -659, -1129, -1409, +-773, -1688, -222, -1313, 369, -417, 1016, 682, +1306, 1461, 960, 1713, 491, 1475, 21, 696, +-657, -284, -1097, -1020, -1009, -1394, -675, -1285, +-177, -681, 316, 36, 594, 571, 832, 802, +836, 680, 412, 356, -36, -7, -442, -208, +-798, -105, -764, 29, -414, 43, -22, 90, +320, 60, 529, -164, 527, -384, 277, -439, +-9, -287, -121, -24, -229, 301, -326, 638, +-256, 662, -264, 282, -280, -136, -58, -494, +75, -718, 142, -495, 417, -15, 559, 409, +470, 786, 267, 777, -238, 308, -723, -252, +-797, -807, -724, -1140, -417, -870, 240, -186, +682, 572, 781, 1238, 738, 1381, 417, 887, +-83, 149, -496, -665, -661, -1297, -534, -1393, +-248, -907, 122, -113, 419, 646, 387, 1175, +114, 1272, -190, 786, -370, -29, -208, -699, +115, -1018, 313, -890, 469, -281, 420, 393, +75, 804, -278, 858, -631, 448, -793, -266, +-498, -863, -112, -1027, 318, -763, 899, -140, +955, 781, 405, 1458, -88, 1327, -648, 655, +-1143, -102, -902, -976, -263, -1591, 320, -1435, +898, -723, 1130, 220, 778, 1054, 30, 1333, +-793, 1149, -1200, 644, -992, -200, -438, -833, +287, -816, 948, -480, 1141, -59, 773, 264, +77, 214, -575, -37, -904, -253, -856, -420, +-435, -259, 150, 246, 667, 698, 998, 946, +822, 899, 115, 424, -614, -337, -1035, -1110, +-1052, -1557, -567, -1346, 257, -535, 1031, 474, +1336, 1412, 896, 1897, 92, 1512, -552, 468, +-1021, -625, -1126, -1408, -680, -1749, -92, -1388, +349, -412, 666, 585, 754, 1287, 527, 1564, +104, 1230, -236, 391, -354, -486, -405, -1060, +-322, -1236, -67, -985, 31, -439, 2, 227, +-13, 740, -101, 882, -64, 792, 64, 581, +113, 225, 287, -214, 418, -529, 189, -693, +-84, -775, -270, -659, -543, -300, -481, 209, +-11, 748, 258, 1103, 396, 1046, 485, 580, +171, -91, -256, -823, -446, -1323, -501, -1299, +-308, -744, 192, 130, 668, 999, 864, 1583, +772, 1613, 278, 915, -615, -221, -1370, -1292, +-1523, -1990, -1080, -1956, -93, -1005, 1051, 361, +1716, 1614, 1804, 2410, 1236, 2267, -13, 1196, +-1179, -307, -1768, -1834, -1902, -2704, -1356, -2438, +-196, -1360, 861, 200, 1525, 1840, 1697, 2725, +1126, 2532, 212, 1511, -572, -55, -1128, -1607, +-1161, -2493, -742, -2486, -194, -1579, 389, -118, +624, 1347, 392, 2372, 153, 2423, -35, 1479, +-240, 137, -117, -1192, 254, -2122, 379, -2171, +266, -1368, 86, -201, -220, 983, -554, 1829, +-605, 2029, -346, 1507, -35, 443, 340, -706, +722, -1622, 750, -1982, 413, -1528, -106, -631, +-700, 374, -1045, 1321, -899, 1730, -336, 1409, +499, 795, 1209, 57, 1333, -701, 922, -1088, +159, -1152, -803, -961, -1496, -433, -1693, 101, +-1409, 465, -541, 747, 622, 843, 1567, 647, +2073, 340, 1877, 66, 940, -203, -251, -438, +-1344, -468, -2054, -334, -2040, -329, -1444, -307, +-575, -96, 440, -55, 1428, -63, 1985, 247, +1884, 611, 1401, 823, 547, 920, -709, 665, +-1592, 46, -1796, -660, -1793, -1274, -1327, -1588, +-157, -1425, 867, -730, 1405, 390, 1842, 1467, +1743, 2157, 887, 2339, -69, 1634, -935, 111, +-1630, -1471, -1761, -2646, -1308, -3019, -448, -2230, +544, -557, 1198, 1332, 1404, 2696, 1238, 3036, +645, 2425, -135, 1067, -706, -756, -998, -2192, +-1073, -2633, -832, -2273, -281, -1245, 212, 177, +550, 1360, 818, 1867, 721, 1686, 266, 1080, +-91, 238, -256, -551, -335, -884, -252, -806, +-91, -595, -75, -226, -100, 160, -129, 169, +-265, -13, -323, -168, -176, -285, 100, -164, +410, 154, 658, 550, 837, 904, 813, 883, +385, 516, -308, 47, -964, -561, -1370, -1122, +-1354, -1275, -915, -1103, -148, -524, 825, 385, +1583, 1021, 1753, 1296, 1347, 1288, 551, 794, +-423, 71, -1332, -550, -1757, -1034, -1445, -1150, +-714, -827, 125, -373, 910, 173, 1271, 767, +1041, 1075, 461, 878, -273, 262, -887, -405, +-897, -824, -394, -898, 190, -537, 736, 40, +938, 536, 548, 940, -125, 1003, -825, 553, +-1363, -27, -1334, -559, -657, -1007, 295, -1118, +1170, -873, 1669, -343, 1550, 408, 799, 957, +-305, 1102, -1275, 984, -1680, 563, -1330, 48, +-466, -340, 453, -683, 1149, -742, 1321, -519, +816, -371, -47, -252, -874, -91, -1341, -8, +-1095, 159, -201, 429, 810, 555, 1596, 653, +1859, 718, 1187, 552, -185, 237, -1574, -238, +-2441, -769, -2372, -1132, -1335, -1255, 252, -1048, +1833, -462, 2745, 385, 2552, 1211, 1438, 1618, +-172, 1436, -1809, 945, -2710, 236, -2461, -661, +-1385, -1238, 71, -1370, 1517, -1217, 2350, -694, +2141, 38, 1166, 637, -103, 993, -1391, 1098, +-2199, 901, -2097, 409, -1139, -224, 258, -728, +1520, -976, 2167, -952, 2012, -452, 1156, 319, +-90, 912, -1312, 1225, -2094, 1044, -2136, 208, +-1417, -788, -300, -1389, 819, -1507, 1745, -1182, +2139, -360, 1716, 814, 784, 1805, -214, 2147, +-1128, 1833, -1655, 897, -1560, -538, -1058, -1897, +-386, -2644, 324, -2553, 891, -1528, 1069, 75, +857, 1627, 512, 2647, 166, 2792, -128, 2075, +-316, 682, -339, -1074, -262, -2359, -362, -2640, +-513, -2169, -478, -1069, -411, 555, -211, 1840, +314, 2202, 754, 1873, 801, 1008, 707, -192, +443, -1198, -155, -1604, -650, -1416, -816, -788, +-831, 114, -527, 823, 75, 1031, 522, 836, +693, 383, 630, -125, 287, -386, -179, -378, +-543, -255, -633, 1, -322, 142, 167, -23, +481, -197, 615, -309, 635, -325, 234, -81, +-587, 299, -1101, 633, -992, 843, -594, 744, +95, 252, 1075, -428, 1659, -999, 1310, -1131, +455, -888, -443, -524, -1384, 167, -1986, 978, +-1696, 1283, -713, 1122, 393, 762, 1455, 142, +2267, -598, 2196, -1085, 1144, -1182, -300, -963, +-1644, -474, -2470, 232, -2378, 875, -1480, 1130, +-180, 1036, 1211, 648, 2176, -10, 2257, -652, +1635, -1078, 641, -1131, -508, -628, -1451, 94, +-1830, 660, -1631, 1053, -1063, 1076, -260, 614, +574, -53, 1151, -710, 1376, -1130, 1213, -1075, +699, -631, 91, 27, -433, 678, -824, 991, +-905, 1035, -750, 851, -582, 284, -231, -379, +280, -809, 572, -961, 718, -889, 790, -653, +490, -140, 3, 540, -279, 880, -552, 814, +-813, 711, -676, 413, -226, -87, 204, -347, +497, -447, 661, -546, 644, -542, 262, -401, +-306, -150, -578, 36, -514, 145, -497, 408, +-453, 711, -26, 675, 433, 464, 458, 276, +384, -123, 449, -662, 267, -986, -146, -907, +-262, -593, -202, -194, -353, 433, -473, 1022, +-394, 1138, -314, 889, -197, 485, 125, -100, +612, -714, 978, -1121, 946, -1157, 652, -718, +289, -119, -384, 385, -1236, 875, -1619, 1080, +-1387, 850, -745, 421, 266, -128, 1357, -589, +1975, -700, 1829, -628, 1016, -395, -178, 9, +-1280, 168, -1859, 83, -1801, 100, -1177, 79, +-159, 19, 892, 244, 1556, 620, 1649, 757, +1189, 518, 274, 32, -720, -476, -1352, -984, +-1450, -1423, -1037, -1422, -258, -722, 559, 372, +1063, 1351, 1094, 2067, 711, 2323, 123, 1637, +-433, 113, -780, -1451, -776, -2558, -505, -2977, +-168, -2306, 126, -730, 356, 1093, 533, 2561, +552, 3132, 370, 2731, 143, 1561, -69, -219, +-290, -2000, -455, -2976, -471, -3007, -449, -2231, +-417, -729, -148, 975, 291, 2374, 653, 3111, +939, 2793, 985, 1582, 499, 56, -278, -1438, +-856, -2638, -1172, -3011, -1159, -2315, -680, -1000, +-30, 475, 556, 1846, 1096, 2666, 1296, 2580, +963, 1838, 360, 680, -363, -782, -1060, -1968, +-1316, -2471, -1048, -2341, -533, -1534, 50, -258, +590, 987, 917, 1930, 953, 2331, 774, 1958, +429, 1075, -98, 41, -667, -953, -990, -1635, +-959, -1844, -750, -1597, -415, -931, 95, -57, +667, 726, 1116, 1255, 1310, 1481, 1133, 1374, +451, 925, -562, 241, -1387, -464, -1757, -989, +-1559, -1177, -731, -1097, 366, -844, 1271, -326, +1828, 303, 1891, 641, 1246, 713, 48, 757, +-1220, 645, -2087, 352, -2148, 89, -1335, -85, +12, -179, 1300, -305, 1958, -465, 1817, -526, +1029, -536, -130, -559, -1199, -441, -1757, -65, +-1616, 412, -831, 810, 281, 1064, 1300, 1208, +1819, 1073, 1493, 383, 440, -556, -813, -1296, +-1701, -1745, -1817, -1788, -1206, -1250, -244, -196, +865, 960, 1766, 1755, 1870, 2066, 1165, 1876, +125, 1042, -1010, -136, -1826, -1056, -1726, -1744, +-841, -2122, 198, -1728, 1017, -779, 1420, 213, +1156, 1118, 297, 1747, -478, 1831, -830, 1415, +-940, 665, -647, -256, 110, -1026, 819, -1409, +1129, -1423, 950, -1168, 212, -607, -755, 145, +-1408, 721, -1530, 1069, -1004, 1240, 31, 1008, +1013, 496, 1607, 14, 1733, -471, 1267, -822, +272, -828, -864, -655, -1621, -379, -1823, -49, +-1584, 94, -805, 136, 359, 256, 1210, 325, +1508, 408, 1481, 544, 1067, 587, 304, 573, +-463, 351, -1031, -240, -1262, -870, -1102, -1240, +-709, -1320, -180, -1009, 356, -297, 625, 551, +655, 1315, 670, 1716, 612, 1517, 347, 873, +-18, 47, -232, -771, -299, -1378, -427, -1488, +-464, -1080, -351, -473, -387, 158, -484, 594, +-308, 630, 82, 481, 494, 406, 890, 331, +1163, 348, 1153, 548, 790, 554, 33, 300, +-959, -85, -1805, -753, -2118, -1406, -1764, -1592, +-876, -1334, 500, -718, 2021, 292, 2786, 1406, +2455, 2131, 1470, 2191, 66, 1605, -1576, 626, +-2745, -581, -2859, -1682, -1999, -2126, -541, -1926, +1040, -1390, 2172, -573, 2459, 371, 1847, 1077, +629, 1398, -673, 1428, -1540, 1250, -1712, 940, +-1194, 531, -201, 13, 768, -563, 1195, -1079, +998, -1466, 330, -1714, -630, -1591, -1383, -917, +-1398, 40, -713, 1037, 317, 1911, 1317, 2295, +1946, 2061, 1950, 1378, 1242, 338, 0, -869, +-1373, -1863, -2412, -2381, -2720, -2324, -2136, -1732, +-867, -759, 662, 468, 2079, 1629, 2967, 2318, +2964, 2457, 2069, 2061, 585, 1149, -1109, -55, +-2602, -1226, -3388, -2133, -3071, -2586, -1802, -2306, +-75, -1327, 1626, -153, 2854, 944, 3205, 1958, +2551, 2455, 1165, 2105, -479, 1364, -1923, 440, +-2782, -743, -2747, -1711, -1777, -2092, -330, -1963, +1025, -1352, 1933, -338, 2162, 733, 1675, 1517, +719, 1831, -315, 1612, -1053, 936, -1382, -33, +-1368, -918, -901, -1435, -48, -1505, 564, -955, +693, -1, 779, 784, 823, 1203, 478, 1261, +66, 815, -79, -84, -339, -993, -877, -1497, +-1195, -1473, -993, -985, -482, -7, 177, 1230, +1012, 2044, 1724, 2141, 1886, 1660, 1430, 566, +486, -953, -816, -2218, -2188, -2735, -3066, -2526, +-2875, -1676, -1559, -188, 347, 1556, 2244, 2766, +3684, 3111, 4012, 2778, 2885, 1701, 810, -19, +-1544, -1687, -3622, -2806, -4720, -3268, -4327, -2910, +-2448, -1754, 291, -193, 2915, 1342, 4611, 2562, +4908, 3225, 3658, 3057, 1277, 2096, -1350, 742, +-3472, -784, -4611, -2282, -4403, -3242, -2857, -3325, +-471, -2623, 1949, -1277, 3657, 496, 4220, 2219, +3530, 3378, 1874, 3640, -161, 2939, -2012, 1398, +-3187, -618, -3437, -2493, -2803, -3662, -1389, -3734, +391, -2608, 1834, -681, 2630, 1382, 2736, 2994, +2090, 3642, 926, 3041, -313, 1429, -1321, -607, +-1893, -2328, -2004, -3179, -1781, -2981, -1175, -1703, +-235, 278, 651, 2071, 1295, 2936, 1755, 2716, +1946, 1611, 1662, -24, 872, -1670, -121, -2651, +-1101, -2568, -2029, -1691, -2570, -431, -2381, 959, +-1500, 1947, -155, 2129, 1375, 1714, 2679, 1023, +3341, 224, 3039, -507, 1737, -985, -117, -1178, +-1967, -1266, -3451, -1334, -4053, -1227, -3331, -863, +-1529, -275, 663, 567, 2688, 1565, 4059, 2398, +4209, 2762, 3016, 2425, 1027, 1270, -1189, -528, +-3083, -2417, -4024, -3717, -3801, -4088, -2592, -3344, +-676, -1438, 1381, 955, 2955, 3045, 3638, 4453, +3242, 4636, 2041, 3315, 512, 1129, -1160, -1204, +-2569, -3198, -3102, -4165, -2796, -3877, -1955, -2632, +-538, -809, 1085, 967, 2218, 2230, 2635, 2797, +2380, 2605, 1478, 1922, 191, 1038, -1002, 6, +-1818, -838, -2160, -1176, -1804, -1367, -854, -1558, +166, -1467, 973, -1136, 1433, -687, 1288, -78, +680, 703, 88, 1456, -330, 1907, -523, 1949, +-360, 1502, -85, 618, 47, -401, 39, -1310, +-150, -1996, -468, -2120, -689, -1579, -643, -778, +-190, 196, 593, 1224, 1301, 1800, 1585, 1794, +1348, 1366, 517, 584, -789, -381, -1994, -1203, +-2501, -1584, -2187, -1370, -1089, -713, 667, 112, +2411, 929, 3275, 1411, 3023, 1326, 1819, 750, +-152, -158, -2286, -1077, -3639, -1692, -3748, -1781, +-2711, -1165, -849, -35, 1359, 1153, 3205, 2065, +3977, 2424, 3447, 2032, 1947, 969, -76, -491, +-2057, -1849, -3312, -2630, -3476, -2780, -2679, -2186, +-1206, -835, 489, 643, 1808, 1809, 2435, 2567, +2398, 2655, 1801, 2082, 899, 1178, 33, 80, +-639, -1031, -1114, -1841, -1356, -2301, -1405, -2392, +-1369, -2054, -1199, -1352, -720, -288, 31, 1009, +797, 2269, 1482, 3185, 2098, 3371, 2288, 2656, +1748, 1136, 700, -870, -608, -2736, -1992, -3840, +-2921, -3922, -2969, -2920, -2171, -1052, -740, 999, +914, 2648, 2225, 3525, 2904, 3358, 2822, 2314, +1954, 825, 614, -630, -784, -1667, -1932, -2150, +-2495, -2118, -2383, -1712, -1754, -1143, -741, -550, +377, 61, 1216, 661, 1730, 1256, 1996, 1768, +1856, 1986, 1214, 1866, 349, 1291, -535, 185, +-1453, -1106, -2152, -2199, -2274, -2849, -1821, -2741, +-889, -1747, 446, -176, 1788, 1468, 2583, 2661, +2600, 3059, 1885, 2596, 639, 1334, -835, -292, +-2107, -1657, -2651, -2412, -2309, -2383, -1388, -1622, +-165, -539, 1081, 433, 1944, 1064, 2081, 1238, +1479, 1015, 564, 654, -189, 390, -674, 310, +-895, 314, -789, 280, -514, 66, -357, -480, +-372, -1176, -471, -1656, -503, -1718, -343, -1209, +23, -112, 576, 1196, 1239, 2188, 1782, 2528, +1869, 2110, 1189, 1076, -49, -277, -1293, -1560, +-2329, -2352, -2923, -2409, -2594, -1793, -1352, -808, +307, 250, 1902, 1169, 2985, 1631, 3219, 1577, +2553, 1355, 1158, 1050, -516, 539, -1928, 38, +-2738, -405, -2783, -987, -2124, -1508, -1064, -1764, +232, -1753, 1423, -1254, 1970, -245, 1875, 877, +1509, 1860, 972, 2531, 316, 2520, -251, 1712, +-600, 446, -904, -872, -1242, -1963, -1387, -2572, +-1241, -2484, -887, -1696, -290, -481, 463, 713, +1149, 1497, 1647, 1858, 1756, 1817, 1315, 1252, +569, 492, -270, 27, -1056, -258, -1458, -602, +-1409, -886, -1048, -1050, -423, -1135, 103, -1088, +337, -856, 508, -352, 482, 326, 179, 915, +144, 1366, 517, 1616, 847, 1553, 1000, 1199, +1007, 546, 570, -325, -457, -1160, -1660, -1855, +-2415, -2336, -2482, -2273, -1892, -1581, -625, -483, +1084, 886, 2628, 2265, 3516, 3216, 3439, 3340, +2288, 2523, 334, 963, -1825, -980, -3432, -2765, +-3977, -3854, -3454, -3922, -1974, -2871, 126, -914, +2089, 1302, 3304, 3092, 3618, 3990, 2979, 3639, +1517, 2267, -290, 424, -1878, -1488, -2801, -2774, +-2846, -2951, -2120, -2310, -939, -1228, 230, 41, +1115, 942, 1648, 1192, 1609, 1046, 1093, 675, +681, 300, 461, 267, 103, 626, -268, 1035, +-397, 1033, -614, 569, -1134, -253, -1459, -1457, +-1259, -2637, -827, -3033, -236, -2347, 700, -810, +1678, 1175, 2175, 2985, 2092, 4004, 1449, 3823, +273, 2340, -1103, 97, -2208, -2141, -2652, -3749, +-2217, -4156, -1093, -3205, 281, -1289, 1447, 906, +2069, 2594, 2100, 3212, 1573, 2723, 533, 1499, +-592, 34, -1334, -1184, -1612, -1768, -1384, -1510, +-585, -768, 341, -83, 865, 502, 1011, 806, +845, 473, 214, -190, -579, -695, -990, -925, +-990, -727, -721, -24, -42, 798, 868, 1344, +1497, 1471, 1658, 1135, 1335, 379, 446, -596, +-792, -1281, -1888, -1411, -2425, -1231, -2277, -802, +-1470, -151, -38, 388, 1645, 655, 2735, 746, +2858, 687, 2286, 533, 1041, 411, -720, 330, +-2095, 245, -2564, 42, -2380, -219, -1618, -365, +-302, -580, 967, -856, 1580, -874, 1557, -663, +1191, -404, 585, -37, -95, 442, -462, 860, +-332, 1120, -38, 1239, 88, 1222, 81, 871, +-90, 122, -564, -623, -1061, -1264, -1175, -1886, +-831, -2070, -156, -1558, 698, -658, 1441, 343, +1716, 1345, 1416, 2144, 708, 2417, -169, 1957, +-926, 957, -1350, -145, -1352, -1170, -947, -1867, +-316, -1952, 186, -1568, 378, -959, 434, -253, +439, 374, 276, 775, 154, 964, 264, 1011, +403, 949, 447, 812, 440, 627, 285, 430, +-103, 171, -600, -209, -997, -710, -1174, -1224, +-1081, -1516, -678, -1546, 23, -1302, 735, -623, +1158, 331, 1356, 1253, 1378, 2020, 1022, 2364, +308, 2058, -464, 1363, -1073, 410, -1468, -816, +-1543, -1892, -1120, -2516, -343, -2725, 346, -2387, +794, -1424, 1121, -34, 1208, 1495, 816, 2806, +203, 3458, -210, 3202, -455, 2114, -586, 457, +-388, -1404, -26, -2954, 100, -3626, 34, -3235, +-102, -1992, -417, -265, -656, 1398, -516, 2515, +-185, 2801, 232, 2222, 734, 1122, 1044, -6, +1060, -857, 795, -1265, 195, -1182, -506, -813, +-937, -412, -1071, -135, -970, -77, -583, -166, +-47, -267, 367, -206, 564, 113, 516, 520, +292, 858, 101, 1070, 77, 993, 127, 525, +177, -114, 324, -628, 461, -957, 299, -1104, +-93, -948, -522, -459, -927, 48, -1128, 349, +-989, 508, -611, 469, -101, 316, 501, 260, +1093, 218, 1481, 205, 1555, 355, 1282, 418, +662, 200, -174, -79, -992, -384, -1631, -771, +-1986, -1064, -1915, -1094, -1348, -750, -460, -141, +576, 505, 1604, 1125, 2321, 1493, 2439, 1356, +1924, 869, 964, 256, -250, -423, -1497, -950, +-2323, -1162, -2474, -1112, -2064, -806, -1184, -417, +25, -138, 1171, 141, 1899, 473, 2013, 710, +1590, 776, 934, 830, 195, 905, -545, 706, +-932, 185, -924, -342, -897, -782, -787, -1233, +-429, -1478, -196, -1269, -198, -692, -65, 26, +235, 702, 455, 1366, 679, 1812, 1004, 1644, +1117, 1015, 796, 232, 243, -687, -394, -1519, +-1051, -1872, -1485, -1649, -1481, -955, -1060, -68, +-301, 693, 611, 1288, 1293, 1511, 1491, 1203, +1257, 676, 693, 108, -98, -461, -885, -816, +-1267, -949, -1084, -937, -607, -674, -10, -250, +691, 114, 1156, 475, 1067, 827, 551, 990, +-127, 813, -852, 349, -1370, -131, -1344, -577, +-776, -982, 25, -1065, 822, -773, 1458, -286, +1694, 311, 1356, 835, 639, 1081, -220, 1085, +-1101, 794, -1707, 154, -1762, -541, -1361, -1038, +-673, -1211, 196, -1036, 972, -624, 1393, -25, +1537, 598, 1439, 993, 906, 1120, 47, 998, +-650, 594, -994, 75, -1177, -381, -1174, -793, +-802, -1048, -346, -1007, -105, -706, 165, -259, +579, 178, 821, 593, 828, 925, 800, 975, +744, 775, 537, 475, 179, 123, -277, -224, +-778, -570, -1268, -942, -1558, -1144, -1356, -1048, +-660, -707, 212, -60, 1052, 751, 1672, 1437, +1834, 1832, 1462, 1660, 697, 823, -272, -349, +-1227, -1471, -1799, -2213, -1705, -2249, -1116, -1499, +-301, -183, 635, 1247, 1369, 2212, 1438, 2438, +951, 1903, 336, 711, -333, -709, -950, -1869, +-1085, -2407, -657, -2088, -34, -1052, 492, 289, +841, 1485, 851, 2063, 461, 1801, -70, 956, +-504, -114, -804, -1020, -897, -1390, -717, -1189, +-289, -561, 251, 230, 696, 738, 923, 749, +912, 417, 660, -68, 300, -562, -54, -745, +-432, -365, -761, 314, -904, 812, -927, 986, +-809, 819, -400, 173, 179, -683, 701, -1248, +1077, -1365, 1234, -960, 1169, -122, 832, 766, +177, 1421, -580, 1609, -1189, 1076, -1576, 55, +-1633, -878, -1214, -1455, -371, -1541, 582, -1006, +1353, -34, 1808, 914, 1826, 1434, 1315, 1433, +456, 935, -480, 52, -1356, -830, -1896, -1343, +-1836, -1367, -1321, -911, -518, -140, 489, 591, +1363, 1035, 1760, 1108, 1648, 809, 1149, 349, +369, -103, -502, -476, -1127, -677, -1360, -650, +-1251, -390, -802, -115, -153, -45, 347, -35, +616, 33, 745, 29, 645, 87, 358, 394, +163, 671, 116, 734, 104, 630, 61, 270, +-59, -294, -275, -848, -564, -1213, -787, -1245, +-745, -902, -492, -258, -78, 552, 509, 1245, +999, 1496, 1146, 1253, 1007, 685, 589, 0, +-105, -644, -818, -1102, -1211, -1147, -1154, -817, +-744, -404, -182, 10, 407, 375, 854, 539, +936, 487, 680, 322, 258, 175, -232, 172, +-577, 217, -626, 172, -391, 153, 17, 88, +359, -199, 474, -520, 430, -689, 222, -742, +-161, -631, -519, -241, -664, 288, -602, 724, +-342, 1014, 110, 1025, 607, 659, 894, 154, +851, -282, 536, -685, 75, -896, -377, -756, +-662, -538, -756, -312, -684, 57, -453, 359, +-109, 499, 277, 585, 590, 549, 659, 384, +506, 188, 270, -67, 1, -313, -215, -407, +-292, -415, -277, -326, -219, -124, -111, 38, +41, 118, 138, 105, 65, 28, -117, -9, +-193, -36, -143, -70, -92, 62, 32, 317, +266, 408, 401, 396, 346, 371, 236, 104, +149, -368, -31, -681, -302, -745, -493, -711, +-499, -464, -316, 11, -32, 378, 174, 582, +241, 759, 219, 770, 130, 521, 34, 215, +50, -25, 159, -257, 230, -463, 220, -611, +176, -685, 93, -697, -97, -629, -384, -353, +-627, 84, -722, 546, -617, 967, -288, 1197, +216, 1131, 736, 824, 1080, 306, 1116, -361, +833, -947, 255, -1331, -486, -1483, -1049, -1306, +-1231, -828, -1089, -134, -633, 629, 37, 1268, +649, 1707, 1003, 1837, 1016, 1492, 690, 723, +222, -245, -250, -1211, -689, -1943, -860, -2238, +-590, -1958, -117, -1095, 339, 47, 695, 1129, +767, 1983, 466, 2314, -31, 1914, -542, 1002, +-924, -50, -995, -996, -709, -1605, -176, -1656, +530, -1195, 1161, -543, 1397, 37, 1202, 416, +662, 514, -200, 414, -1036, 302, -1417, 242, +-1383, 373, -1082, 703, -434, 858, 382, 656, +938, 209, 1102, -476, 1065, -1236, 833, -1668, +325, -1575, -194, -991, -426, -35, -535, 982, +-664, 1713, -604, 1873, -347, 1388, -166, 518, +-75, -434, 89, -1175, 268, -1406, 305, -1092, +310, -467, 408, 176, 396, 583, 160, 634, +-21, 379, -80, -46, -195, -375, -220, -417, +-63, -208, -49, 222, -269, 684, -465, 825, +-500, 597, -391, 162, -149, -372, 226, -851, +677, -1058, 1010, -880, 1044, -376, 764, 199, +287, 653, -316, 927, -918, 849, -1255, 404, +-1160, -117, -765, -489, -261, -619, 262, -475, +684, -124, 898, 262, 911, 517, 700, 523, +326, 288, -22, -94, -244, -482, -346, -763, +-362, -873, -361, -642, -361, -48, -364, 555, +-362, 971, -285, 1206, -146, 1132, 4, 685, +248, 12, 538, -695, 713, -1226, 796, -1467, +788, -1390, 529, -870, 39, -54, -501, 674, +-971, 1269, -1270, 1616, -1304, 1422, -1022, 830, +-402, 176, 423, -493, 1179, -1085, 1616, -1344, +1617, -1192, 1175, -759, 397, -253, -470, 190, +-1134, 539, -1447, 723, -1337, 739, -849, 670, +-212, 567, 339, 414, 727, 152, 828, -193, +597, -546, 269, -844, 68, -956, 27, -792, +119, -416, 198, 118, 154, 677, -2, 945, +-279, 869, -650, 599, -895, 115, -812, -410, +-421, -634, 123, -552, 676, -298, 1060, 58, +1101, 380, 735, 503, 121, 335, -455, -98, +-798, -557, -855, -815, -589, -771, -125, -341, +241, 351, 414, 952, 468, 1214, 288, 1077, +-86, 587, -309, -170, -312, -907, -270, -1263, +-86, -1205, 256, -861, 474, -211, 477, 559, +368, 1012, 117, 1057, -219, 820, -444, 313, +-478, -258, -410, -621, -278, -693, -87, -509, +105, -156, 231, 204, 302, 400, 324, 383, +301, 225, 267, -24, 208, -304, 54, -432, +-164, -331, -329, -188, -375, -27, -368, 224, +-334, 415, -179, 445, 79, 420, 254, 371, +326, 177, 371, -130, 307, -382, 76, -590, +-145, -761, -238, -738, -214, -456, -96, -55, +61, 451, 187, 958, 224, 1144, 134, 948, +-34, 533, -225, -44, -395, -657, -488, -1050, +-431, -1067, -186, -781, 197, -327, 571, 178, +808, 600, 835, 757, 595, 624, 132, 322, +-348, -42, -713, -282, -933, -256, -913, -78, +-595, 144, -143, 332, 251, 337, 541, 79, +721, -313, 715, -667, 531, -883, 295, -874, +80, -512, -126, 153, -263, 822, -268, 1269, +-230, 1436, -319, 1207, -525, 567, -667, -283, +-617, -1081, -370, -1609, 47, -1754, 598, -1455, +1129, -671, 1366, 374, 1217, 1266, 782, 1780, +133, 1844, -652, 1392, -1359, 518, -1762, -484, +-1698, -1251, -1156, -1609, -326, -1570, 561, -1083, +1363, -235, 1843, 563, 1803, 1053, 1298, 1196, +516, 959, -359, 443, -1107, -113, -1531, -527, +-1540, -638, -1174, -445, -578, -122, 87, 198, +677, 361, 998, 243, 972, -49, 740, -380, +428, -603, 74, -551, -159, -228, -143, 203, +-58, 623, -108, 883, -187, 860, -257, 556, +-475, 53, -713, -474, -688, -854, -492, -1010, +-208, -851, 305, -413, 949, 91, 1367, 489, +1407, 757, 1078, 857, 412, 697, -436, 315, +-1208, -62, -1678, -345, -1670, -595, -1223, -674, +-516, -481, 340, -226, 1129, 10, 1525, 248, +1478, 372, 1140, 373, 563, 338, -141, 198, +-679, -40, -975, -219, -1090, -238, -936, -141, +-563, -54, -193, 35, 141, 168, 466, 116, +660, -129, 649, -246, 524, -226, 369, -245, +213, -133, 28, 201, -175, 491, -289, 575, +-313, 505, -379, 280, -430, -148, -363, -659, +-252, -927, -140, -828, 76, -482, 354, 38, +552, 639, 632, 1058, 566, 1117, 326, 805, +19, 202, -309, -519, -631, -1114, -745, -1352, +-558, -1088, -253, -432, 112, 364, 505, 1047, +657, 1409, 431, 1291, 66, 688, -250, -195, +-462, -998, -455, -1434, -181, -1365, 217, -801, +544, 81, 669, 947, 561, 1459, 194, 1389, +-354, 796, -825, -44, -999, -870, -855, -1433, +-446, -1452, 154, -884, 764, 5, 1108, 860, +1049, 1451, 692, 1550, 201, 1009, -331, 67, +-716, -807, -791, -1388, -665, -1552, -475, -1129, +-192, -289, 92, 545, 222, 1177, 255, 1440, +347, 1169, 445, 519, 410, -184, 333, -782, +328, -1126, 217, -1072, -105, -689, -460, -161, +-708, 341, -829, 683, -724, 811, -364, 684, +125, 342, 561, -54, 806, -349, 816, -526, +663, -517, 378, -273, 27, 26, -264, 217, +-482, 352, -666, 388, -697, 185, -536, -179, +-315, -445, -87, -527, 218, -426, 537, -119, +747, 339, 791, 729, 627, 861, 265, 720, +-145, 318, -517, -303, -800, -886, -859, -1194, +-647, -1168, -282, -753, 162, 42, 608, 848, +871, 1318, 811, 1433, 466, 1130, -21, 337, +-450, -580, -690, -1157, -688, -1359, -435, -1249, +-20, -684, 368, 154, 621, 804, 681, 1093, +457, 1091, -7, 753, -449, 167, -719, -367, +-799, -676, -580, -773, -45, -681, 509, -421, +829, -37, 900, 316, 706, 524, 246, 604, +-289, 553, -708, 326, -907, -4, -813, -334, +-456, -608, 10, -722, 431, -566, 682, -215, +716, 189, 526, 569, 164, 842, -213, 807, +-419, 432, -426, -40, -278, -467, -15, -815, +234, -885, 284, -619, 154, -194, -62, 263, +-345, 656, -553, 776, -435, 585, -54, 263, +325, -34, 634, -280, 861, -395, 785, -297, +344, -154, -239, -153, -751, -138, -1068, -71, +-1046, -100, -649, -96, -30, 113, 571, 338, +974, 461, 1053, 506, 757, 387, 221, 86, +-292, -289, -629, -614, -770, -719, -683, -570, +-339, -276, 134, 97, 485, 461, 565, 624, +448, 540, 214, 348, -120, 133, -413, -147, +-470, -392, -335, -404, -148, -260, 78, -178, +325, -104, 474, -1, 489, 60, 428, 119, +250, 210, -107, 271, -520, 309, -779, 274, +-791, 81, -602, -214, -233, -476, 275, -579, +718, -458, 887, -184, 867, 239, 743, 667, +388, 785, -182, 564, -703, 172, -1047, -377, +-1131, -847, -849, -909, -305, -597, 258, -75, +725, 533, 1004, 969, 964, 1037, 625, 674, +214, -22, -168, -744, -536, -1174, -749, -1180, +-642, -725, -324, 56, -15, 856, 184, 1343, +271, 1335, 251, 852, 115, 44, -82, -843, +-145, -1433, -30, -1530, 104, -1116, 248, -236, +415, 767, 397, 1398, 160, 1552, -107, 1265, +-353, 508, -606, -468, -731, -1190, -586, -1426, +-220, -1223, 226, -703, 636, 59, 860, 815, +779, 1186, 426, 1080, -21, 674, -388, 80, +-551, -498, -483, -794, -275, -733, -57, -432, +96, -26, 120, 316, 17, 457, -135, 325, +-214, 34, -143, -230, 89, -355, 422, -252, +697, 65, 718, 368, 443, 523, -43, 460, +-583, 100, -946, -377, -975, -664, -697, -707, +-202, -502, 367, -28, 812, 535, 947, 895, +719, 878, 250, 482, -182, -104, -424, -688, +-472, -1051, -326, -986, -77, -498, 84, 167, +91, 762, 8, 1085, -81, 1008, -149, 583, +-173, -2, -97, -587, 127, -991, 392, -1034, +522, -698, 417, -210, 100, 255, -302, 585, +-551, 679, -498, 586, -226, 412, 109, 192, +424, 33, 529, -24, 277, -103, -119, -282, +-434, -496, -712, -687, -748, -744, -269, -603, +437, -245, 970, 336, 1261, 958, 1128, 1335, +409, 1327, -549, 913, -1225, 188, -1494, -648, +-1380, -1334, -820, -1648, 107, -1484, 999, -920, +1488, -53, 1521, 862, 1144, 1451, 354, 1582, +-569, 1312, -1151, 675, -1224, -149, -949, -852, +-439, -1198, 174, -1185, 581, -905, 625, -409, +490, 188, 256, 629, -69, 780, -266, 699, +-200, 470, -40, 153, 118, -155, 274, -358, +321, -377, 188, -278, -37, -129, -281, 56, +-489, 194, -574, 222, -474, 168, -210, -12, +125, -250, 420, -358, 625, -308, 682, -182, +532, 5, 254, 210, 9, 411, -215, 519, +-486, 433, -668, 255, -613, 57, -420, -224, +-185, -457, 80, -539, 305, -545, 415, -473, +442, -266, 445, -9, 428, 255, 315, 513, +101, 715, -120, 765, -300, 582, -453, 258, +-512, -79, -485, -449, -458, -752, -369, -852, +-98, -784, 288, -602, 641, -253, 856, 202, +891, 599, 705, 863, 320, 1016, -136, 968, +-563, 602, -977, 81, -1231, -370, -1068, -837, +-509, -1221, 164, -1228, 762, -874, 1146, -360, +1152, 244, 792, 834, 299, 1222, -167, 1259, +-555, 944, -780, 407, -750, -199, -505, -708, +-163, -937, 138, -922, 309, -733, 340, -367, +246, 21, 73, 266, -32, 408, -24, 466, +23, 431, 120, 345, 288, 270, 370, 238, +242, 185, -57, 38, -410, -133, -684, -372, +-754, -697, -567, -833, -137, -656, 371, -367, +724, 17, 843, 523, 796, 954, 544, 1126, +45, 1001, -490, 593, -793, 6, -864, -642, +-725, -1165, -309, -1353, 243, -1125, 616, -574, +714, 130, 630, 782, 377, 1211, -20, 1282, +-361, 964, -521, 363, -529, -310, -367, -834, +-14, -1074, 333, -1000, 472, -584, 412, -16, +238, 392, -6, 595, -224, 655, -328, 500, +-300, 228, -191, 5, -65, -168, 39, -269, +110, -247, 131, -199, 142, -181, 163, -180, +162, -156, 169, -61, 180, 90, 85, 244, +-99, 399, -268, 488, -411, 402, -504, 108, +-422, -280, -176, -605, 125, -762, 459, -669, +756, -265, 784, 285, 483, 740, 58, 957, +-326, 825, -620, 334, -704, -277, -525, -757, +-224, -953, 43, -808, 213, -382, 286, 178, +297, 651, 209, 822, 66, 672, 72, 289, +230, -182, 295, -508, 245, -548, 141, -352, +-151, 0, -596, 319, -876, 393, -841, 222, +-533, -68, 3, -364, 612, -540, 1039, -461, +1170, -90, 967, 377, 442, 714, -249, 836, +-867, 661, -1212, 149, -1135, -448, -676, -878, +-51, -1031, 516, -832, 864, -358, 881, 202, +607, 701, 183, 928, -205, 855, -395, 616, +-392, 217, -291, -275, -77, -579, 148, -672, +168, -671, 29, -524, -87, -230, -191, 75, +-249, 330, -142, 516, 76, 586, 249, 476, +352, 248, 381, 11, 270, -195, 50, -348, +-147, -364, -274, -278, -329, -191, -282, -107, +-154, -24, -38, 12, 22, 18, 55, 59, +97, 180, 149, 277, 193, 321, 205, 360, +172, 277, 110, -6, 57, -285, -24, -476, +-151, -609, -238, -541, -272, -261, -320, 37, +-291, 319, -123, 552, 79, 619, 282, 483, +493, 202, 556, -92, 436, -276, 209, -387, +-129, -424, -499, -313, -660, -129, -546, -29, +-283, 32, 26, 122, 313, 193, 488, 200, +477, 228, 266, 261, -26, 156, -218, -40, +-256, -157, -213, -251, -107, -334, 80, -253, +249, -36, 249, 131, 104, 217, -90, 232, +-284, 131, -424, -62, -387, -221, -109, -259, +283, -171, 532, 8, 546, 251, 403, 438, +124, 460, -242, 278, -474, -73, -484, -447, +-378, -654, -173, -650, 119, -454, 315, -72, +334, 367, 261, 636, 124, 679, -47, 544, +-111, 276, -58, -65, 10, -319, 41, -409, +-3, -389, -141, -316, -266, -229, -269, -193, +-141, -166, 82, -84, 337, 62, 508, 308, +501, 631, 271, 786, -91, 664, -412, 372, +-618, -78, -674, -656, -470, -1092, -57, -1166, +366, -886, 695, -333, 855, 367, 686, 973, +220, 1300, -274, 1225, -611, 749, -785, 56, +-737, -600, -415, -1058, 12, -1179, 316, -901, +487, -354, 581, 216, 546, 653, 351, 832, +114, 719, -91, 390, -286, -14, -470, -342, +-556, -462, -466, -391, -247, -210, -1, 24, +262, 234, 497, 302, 565, 193, 427, -21, +204, -218, -40, -332, -285, -309, -425, -119, +-359, 147, -172, 337, 18, 418, 167, 377, +203, 165, 81, -163, -92, -409, -190, -459, +-151, -324, 6, -66, 224, 231, 404, 428, +456, 423, 315, 197, 0, -166, -381, -501, +-670, -602, -738, -431, -506, -71, -45, 387, +459, 804, 818, 934, 886, 661, 593, 118, +63, -491, -461, -1009, -793, -1215, -837, -957, +-546, -338, -43, 362, 418, 921, 664, 1171, +679, 1034, 450, 562, 31, -65, -351, -596, +-486, -835, -418, -768, -254, -457, -18, -45, +181, 253, 212, 318, 150, 208, 73, -19, +-28, -204, -49, -170, 90, 56, 213, 337, +179, 588, 67, 657, -70, 431, -289, -5, +-469, -498, -382, -904, -60, -1028, 209, -813, +318, -350, 356, 212, 290, 693, 73, 938, +-132, 910, -192, 647, -147, 278, -23, -68, +152, -337, 231, -507, 122, -562, -126, -569, +-409, -554, -612, -462, -559, -258, -199, 11, +294, 351, 732, 738, 1017, 1005, 971, 985, +519, 709, -148, 225, -785, -410, -1214, -977, +-1226, -1236, -783, -1157, -114, -770, 531, -176, +957, 423, 1001, 861, 718, 1050, 304, 940, +-94, 634, -347, 251, -388, -155, -322, -483, +-227, -648, -143, -692, -170, -611, -302, -411, +-346, -156, -224, 104, 14, 347, 372, 507, +758, 563, 931, 507, 784, 318, 377, 39, +-154, -188, -674, -320, -1063, -399, -1154, -386, +-836, -239, -280, -100, 277, -19, 773, 79, +1089, 137, 1000, 128, 599, 159, 163, 187, +-231, 165, -576, 152, -746, 110, -698, -2, +-494, -97, -213, -194, 94, -281, 371, -261, +526, -175, 469, -80, 288, 61, 128, 172, +-18, 213, -183, 219, -257, 185, -184, 113, +-61, 42, 34, -50, 97, -138, 71, -162, +-84, -178, -265, -215, -304, -154, -169, -2, +58, 116, 309, 199, 522, 311, 568, 307, +410, 116, 115, -108, -279, -286, -673, -437, +-827, -433, -635, -206, -211, 138, 290, 464, +688, 646, 790, 584, 599, 306, 252, -144, +-153, -601, -486, -827, -595, -763, -493, -447, +-251, 74, 77, 585, 377, 854, 479, 827, +332, 528, 58, 33, -155, -412, -231, -649, +-193, -651, -79, -426, 80, -61, 174, 224, +135, 305, 1, 241, -144, 86, -222, -117, +-179, -186, -21, -44, 229, 182, 445, 368, +444, 464, 187, 343, -181, -4, -489, -416, +-601, -711, -459, -768, -133, -572, 217, -172, +499, 338, 652, 716, 561, 819, 216, 679, +-147, 356, -371, -84, -505, -445, -514, -588, +-284, -524, 44, -323, 242, -81, 283, 87, +233, 132, 122, 91, 18, 42, -28, 18, +-2, 92, 94, 259, 212, 383, 226, 387, +42, 269, -285, -2, -571, -357, -679, -636, +-561, -736, -179, -613, 400, -277, 878, 154, +1015, 571, 823, 812, 394, 775, -205, 549, +-780, 199, -1109, -233, -1085, -559, -695, -690, +-59, -666, 547, -492, 916, -189, 978, 132, +738, 408, 288, 558, -166, 558, -475, 457, +-595, 264, -530, 6, -347, -245, -161, -445, +-23, -537, 56, -520, 93, -384, 115, -119, +190, 194, 354, 457, 509, 636, 489, 628, +265, 398, -102, 58, -497, -309, -786, -591, +-865, -655, -694, -544, -257, -282, 309, 76, +762, 389, 968, 560, 924, 577, 595, 421, +34, 184, -534, -68, -883, -326, -922, -499, +-681, -518, -293, -414, 127, -199, 471, 47, +605, 284, 502, 476, 315, 533, 158, 429, +12, 227, -104, -50, -159, -308, -233, -452, +-320, -496, -337, -414, -290, -182, -199, 85, +-21, 303, 201, 390, 378, 342, 475, 233, +473, 85, 327, -72, 35, -143, -316, -145, +-543, -113, -556, -57, -405, -60, -151, -119, +145, -128, 354, -127, 424, -97, 387, 22, +227, 190, -18, 334, -211, 389, -309, 308, +-309, 122, -151, -124, 99, -338, 198, -422, +116, -407, 38, -322, 9, -99, -33, 131, +-19, 261, 45, 357, 42, 392, -14, 296, +-47, 142, -82, -14, -104, -161, -69, -280, +-1, -324, 90, -279, 231, -187, 328, -110, +249, -1, 0, 127, -276, 229, -437, 304, +-419, 322, -230, 255, 66, 140, 326, -25, +434, -220, 398, -374, 258, -423, 27, -357, +-201, -177, -331, 61, -336, 289, -217, 410, +25, 399, 251, 300, 298, 94, 172, -167, +-21, -289, -203, -274, -273, -217, -190, -126, +14, -10, 280, 86, 482, 134, 472, 101, +244, 57, -100, 75, -423, 79, -626, 27, +-636, -16, -393, -53, 56, -74, 480, -89, +720, -81, 773, -30, 574, 21, 115, 53, +-359, 95, -654, 86, -741, 20, -599, 4, +-244, 2, 175, -78, 496, -135, 632, -118, +593, -52, 396, 28, 63, 109, -303, 188, +-531, 236, -549, 188, -404, 49, -142, -126, +197, -282, 464, -365, 516, -333, 389, -202, +185, 35, -99, 310, -383, 499, -508, 485, +-411, 278, -157, 3, 166, -250, 434, -423, +525, -425, 406, -269, 143, -34, -193, 158, +-481, 216, -595, 162, -498, 93, -240, -9, +159, -88, 593, -31, 826, 100, 734, 211, +371, 266, -180, 168, -701, -43, -956, -281, +-898, -500, -567, -573, -22, -397, 553, -102, +960, 238, 1068, 591, 821, 767, 281, 666, +-351, 382, -861, -8, -1050, -408, -855, -708, +-421, -796, 47, -637, 438, -306, 666, 49, +675, 361, 475, 592, 163, 676, -129, 572, +-308, 346, -352, 110, -239, -115, -48, -373, +33, -566, -66, -643, -184, -623, -233, -483, +-235, -172, -117, 270, 140, 726, 367, 1005, +488, 983, 513, 667, 398, 126, 107, -513, +-273, -1018, -593, -1212, -733, -1015, -675, -520, +-429, 107, -49, 716, 301, 1102, 511, 1101, +606, 791, 549, 309, 353, -246, 121, -712, +-119, -907, -362, -835, -496, -589, -505, -235, +-450, 191, -315, 543, -92, 693, 140, 672, +343, 519, 503, 215, 569, -127, 452, -414, +158, -586, -168, -560, -419, -381, -600, -182, +-628, 78, -402, 327, -29, 407, 308, 391, +556, 334, 626, 156, 408, -32, 14, -158, +-335, -285, -564, -360, -591, -289, -345, -164, +35, -38, 369, 84, 591, 191, 594, 278, +363, 332, 31, 303, -329, 189, -640, 7, +-718, -229, -528, -483, -197, -619, 194, -524, +555, -204, 733, 209, 682, 595, 453, 838, +110, 815, -294, 458, -631, -98, -740, -622, +-599, -973, -322, -1040, 35, -679, 403, -56, +615, 526, 577, 929, 392, 1048, 158, 748, +-124, 193, -361, -335, -388, -689, -251, -767, +-96, -564, 62, -224, 203, 139, 210, 370, +81, 358, -72, 180, -174, 3, -196, -101, +-95, -77, 129, 66, 363, 239, 448, 339, +371, 273, 188, 6, -108, -340, -445, -594, +-620, -631, -545, -447, -292, -72, 41, 379, +395, 704, 662, 755, 708, 546, 505, 144, +158, -307, -245, -605, -567, -657, -634, -498, +-445, -154, -130, 253, 214, 551, 436, 591, +422, 369, 240, 7, 20, -360, -150, -604, +-180, -580, -69, -278, 71, 153, 148, 548, +165, 749, 132, 615, 29, 237, -155, -202, +-304, -559, -310, -718, -198, -611, -11, -314, +270, 35, 528, 315, 560, 469, 345, 484, +44, 399, -253, 238, -508, 44, -620, -139, +-485, -263, -147, -345, 243, -368, 537, -279, +679, -121, 605, 21, 280, 174, -158, 306, +-501, 333, -681, 225, -644, 39, -355, -157, +71, -250, 447, -208, 681, -57, 709, 156, +497, 323, 100, 323, -347, 153, -687, -143, +-777, -450, -633, -649, -329, -615, 103, -331, +549, 115, 806, 586, 808, 945, 610, 1029, +221, 760, -296, 209, -729, -450, -947, -997, +-894, -1261, -551, -1211, -39, -790, 462, -62, +847, 716, 960, 1273, 727, 1472, 307, 1237, +-136, 608, -538, -227, -752, -989, -710, -1412, +-516, -1364, -251, -890, 61, -128, 287, 589, +366, 994, 386, 1032, 376, 732, 288, 200, +167, -255, 53, -416, -79, -334, -245, -153, +-430, 1, -586, -22, -604, -208, -438, -388, +-135, -411, 241, -248, 585, 124, 775, 584, +764, 860, 514, 799, 77, 453, -371, -91, +-713, -646, -932, -970, -911, -950, -583, -613, +-76, -51, 436, 492, 823, 839, 966, 911, +794, 683, 347, 253, -190, -219, -631, -618, +-862, -808, -812, -729, -488, -443, -46, -23, +311, 417, 493, 671, 507, 691, 346, 521, +99, 200, -89, -177, -181, -456, -212, -553, +-164, -475, -93, -291, -91, -50, -138, 173, +-150, 301, -108, 298, 10, 263, 182, 235, +321, 166, 344, 32, 206, -86, -20, -190, +-209, -338, -350, -419, -393, -303, -260, -109, +-46, 88, 146, 304, 318, 450, 394, 416, +289, 255, 43, 17, -227, -218, -385, -357, +-349, -388, -175, -287, 81, -50, 330, 166, +434, 259, 338, 252, 123, 168, -145, 3, +-392, -138, -516, -183, -439, -149, -173, -94, +189, -25, 506, 56, 673, 111, 636, 139, +377, 197, -56, 232, -480, 170, -719, -16, +-710, -268, -457, -507, -42, -609, 320, -476, +496, -96, 538, 397, 506, 798, 395, 920, +231, 705, 48, 239, -175, -288, -475, -739, +-712, -950, -661, -850, -359, -526, 21, -99, +443, 350, 767, 682, 792, 828, 568, 806, +239, 594, -153, 181, -486, -304, -613, -710, +-510, -904, -229, -863, 119, -587, 354, -93, +402, 471, 276, 851, 42, 903, -177, 651, +-245, 223, -121, -251, 131, -586, 359, -648, +441, -443, 327, -154, 52, 102, -275, 256, +-495, 259, -513, 188, -368, 153, -143, 104, +127, -21, 381, -176, 563, -273, 631, -261, +520, -81, 229, 208, -132, 449, -498, 479, +-740, 243, -651, -192, -284, -606, 70, -727, +310, -483, 460, -53, 483, 405, 378, 736, +224, 778, 64, 488, -133, 35, -367, -410, +-463, -709, -328, -767, -98, -550, 119, -129, +301, 337, 327, 661, 178, 732, 13, 521, +-86, 132, -149, -272, -146, -502, -64, -503, +32, -342, 82, -114, 109, 98, 128, 194, +70, 180, -107, 169, -259, 169, -252, 110, +-136, 45, 20, -18, 247, -83, 422, -101, +329, -52, 12, -21, -305, -50, -505, -132, +-488, -217, -210, -218, 183, -65, 470, 210, +525, 475, 327, 536, 15, 355, -252, 5, +-462, -372, -561, -587, -432, -537, -144, -291, +190, 65, 489, 398, 601, 510, 426, 361, +69, 108, -298, -174, -529, -386, -534, -384, +-340, -158, -86, 138, 137, 373, 296, 439, +347, 290, 265, 0, 96, -309, -124, -526, +-335, -517, -406, -301, -260, -14, -9, 270, +215, 524, 337, 602, 277, 457, 52, 191, +-205, -124, -395, -430, -445, -592, -320, -535, +-68, -311, 205, -31, 443, 233, 561, 405, +435, 424, 85, 304, -304, 163, -617, 28, +-749, -116, -591, -216, -199, -257, 237, -262, +592, -169, 738, -17, 571, 99, 192, 161, +-184, 164, -464, 64, -600, -35, -538, -53, +-288, -20, 25, 52, 259, 133, 374, 132, +394, 44, 277, -72, 19, -165, -246, -223, +-373, -208, -331, -124, -143, 7, 131, 142, +364, 252, 415, 291, 239, 221, -78, 84, +-381, -76, -574, -248, -563, -353, -278, -326, +195, -165, 603, 64, 776, 312, 701, 465, +387, 431, -124, 222, -604, -120, -814, -504, +-762, -727, -537, -642, -135, -274, 367, 272, +757, 819, 875, 1059, 731, 878, 371, 361, +-121, -353, -554, -1016, -731, -1313, -671, -1120, +-462, -519, -109, 272, 293, 954, 561, 1310, +669, 1262, 591, 754, 262, -11, -194, -701, +-506, -1117, -546, -1148, -339, -776, 9, -201, +320, 331, 414, 690, 280, 804, 43, 632, +-166, 270, -264, -108, -210, -328, -44, -377, +139, -285, 309, -64, 420, 151, 335, 186, +50, 42, -272, -167, -456, -333, -478, -355, +-343, -164, 6, 128, 468, 389, 699, 540, +599, 544, 342, 344, 1, -7, -382, -357, +-607, -612, -581, -694, -359, -506, -26, -141, +299, 247, 550, 552, 684, 635, 575, 437, +237, 145, -168, -118, -532, -338, -723, -404, +-586, -300, -199, -151, 210, 20, 506, 178, +644, 241, 552, 220, 256, 153, -82, 3, +-353, -125, -532, -152, -536, -170, -318, -183, +42, -88, 418, 34, 645, 98, 559, 157, +215, 196, -173, 162, -432, 139, -467, 123, +-293, 25, -47, -150, 123, -331, 155, -455, +150, -444, 151, -267, 110, 64, 93, 459, +107, 713, 36, 699, -64, 472, -117, 65, +-179, -395, -233, -696, -236, -784, -177, -653, +11, -252, 232, 258, 321, 625, 319, 755, +236, 603, -7, 221, -248, -158, -321, -436, +-246, -564, -91, -423, 64, -84, 148, 193, +117, 344, -44, 366, -182, 180, -175, -120, +-98, -334, -10, -388, 98, -246, 198, 48, +249, 332, 245, 443, 196, 362, 41, 137, +-280, -129, -582, -326, -627, -418, -456, -373, +-122, -168, 312, 109, 575, 331, 550, 409, +371, 324, 114, 83, -137, -206, -315, -405, +-393, -388, -299, -136, -95, 196, 40, 442, +57, 483, -48, 262, -217, -113, -291, -467, +-191, -641, 87, -540, 467, -175, 668, 272, +567, 626, 251, 751, -206, 560, -611, 153, +-766, -292, -721, -639, -499, -737, -108, -562, +312, -204, 623, 219, 717, 568, 557, 676, +262, 519, -105, 191, -456, -169, -596, -420, +-473, -530, -212, -468, 83, -212, 285, 81, +284, 330, 94, 515, -140, 494, -261, 210, +-230, -150, -62, -441, 184, -569, 300, -397, +265, -4, 239, 371, 147, 552, -57, 414, +-231, 56, -414, -274, -544, -428, -454, -378, +-188, -120, 194, 212, 557, 402, 628, 389, +462, 220, 223, -74, -112, -366, -389, -484, +-410, -407, -282, -215, -121, 100, 30, 428, +134, 558, 158, 499, 19, 330, -134, 4, +-48, -398, 110, -636, 183, -616, 266, -408, +255, -55, 57, 343, -141, 576, -226, 534, +-256, 308, -297, 3, -252, -278, 4, -368, +307, -261, 447, -108, 449, 72, 278, 259, +-42, 319, -294, 188, -383, -83, -328, -397, +-180, -581, -66, -537, 107, -239, 388, 266, +551, 754, 525, 990, 277, 863, -240, 358, +-666, -316, -700, -845, -415, -1086, 58, -984, +451, -561, 505, -30, 369, 472, 224, 857, +70, 953, -64, 778, -167, 477, -221, 50, +-183, -443, -113, -792, 10, -866, 154, -664, +136, -241, 21, 190, -22, 454, 17, 542, +97, 447, 71, 181, -38, -87, -7, -180, +80, -162, 98, -119, 134, 1, 101, 144, +-51, 226, -146, 206, -167, 30, -184, -240, +-179, -468, -151, -588, -30, -492, 210, -104, +460, 366, 630, 713, 515, 872, 24, 706, +-443, 253, -607, -252, -523, -625, -271, -763, +-57, -690, 55, -449, 215, -48, 366, 346, +454, 527, 451, 546, 215, 427, -150, 109, +-426, -233, -529, -416, -349, -362, -35, -26, +133, 377, 219, 558, 272, 409, 191, -42, +90, -612, -33, -982, -246, -910, -342, -379, +-224, 402, 27, 1048, 288, 1264, 339, 963, +249, 272, 164, -464, -39, -979, -266, -1103, +-363, -774, -418, -201, -346, 362, -74, 726, +252, 746, 499, 473, 488, 68, 179, -335, +-105, -568, -191, -531, -131, -285, -26, 128, +-92, 550, -288, 714, -330, 585, -203, 173, +33, -436, 301, -896, 375, -974, 243, -634, +56, 41, -88, 708, -83, 1024, -76, 919, +-206, 395, -263, -341, -171, -792, -7, -758, +235, -395, 333, 116, 131, 554, -148, 689, +-317, 396, -322, -185, -186, -708, 6, -906, +258, -658, 407, -17, 330, 701, 215, 1138, +23, 1136, -323, 641, -513, -177, -489, -922, +-369, -1290, -88, -1093, 181, -433, 288, 278, +390, 796, 439, 1009, 340, 764, 151, 201, +-183, -368, -498, -729, -496, -695, -308, -253, +-65, 319, 165, 722, 159, 726, -1, 280, +-74, -355, -14, -872, 160, -1048, 267, -706, +220, 16, 142, 731, 38, 1157, -83, 1169, +-199, 721, -356, -51, -434, -829, -321, -1299, +-44, -1256, 309, -643, 494, 269, 358, 1033, +89, 1347, -163, 1032, -293, 157, -133, -758, +99, -1256, 156, -1203, 175, -530, 123, 505, +-11, 1291, -107, 1493, -320, 1016, -526, -12, +-430, -1091, -165, -1751, 239, -1690, 674, -785, +769, 505, 568, 1517, 239, 1936, -200, 1550, +-488, 432, -552, -799, -588, -1616, -453, -1760, +-69, -1134, 253, -73, 421, 950, 490, 1544, +368, 1374, 93, 562, -165, -388, -225, -1102, +-81, -1317, 52, -880, 146, -47, 205, 757, +90, 1220, -140, 1149, -382, 588, -533, -230, +-426, -982, -116, -1348, 303, -1187, 684, -508, +709, 430, 438, 1184, 140, 1432, -182, 1074, +-386, 250, -351, -616, -308, -1116, -261, -1130, +-89, -680, 40, 27, 119, 618, 189, 892, +108, 734, 6, 222, 36, -328, 147, -693, +320, -740, 363, -389, 179, 183, -21, 670, +-239, 841, -481, 601, -525, 83, -393, -417, +-157, -752, 160, -792, 386, -484, 487, -4, +484, 462, 270, 679, -18, 508, -197, 159, +-292, -154, -250, -369, -77, -351, 67, -36, +148, 314, 138, 488, -22, 414, -245, 52, +-372, -427, -311, -802, -79, -959, 229, -769, +494, -187, 566, 619, 444, 1332, 289, 1654, +72, 1326, -277, 410, -549, -700, -677, -1612, +-701, -1991, -456, -1633, 19, -688, 471, 474, +723, 1476, 634, 1952, 391, 1695, 211, 881, +-16, -203, -210, -1212, -263, -1705, -348, -1478, +-421, -692, -315, 263, -138, 962, -6, 1195, +113, 932, 185, 300, 219, -366, 276, -746, +265, -787, 150, -471, 24, 107, -89, 575, +-136, 714, -119, 545, -119, 86, -183, -486, +-276, -830, -242, -724, -67, -238, 132, 352, +311, 764, 317, 852, 159, 553, 61, -36, +-4, -650, -97, -1017, -146, -944, -165, -392, +-137, 399, 4, 1086, 199, 1334, 270, 987, +91, 196, -272, -747, -539, -1506, -493, -1632, +-208, -986, 223, 66, 631, 1075, 664, 1667, +391, 1565, 118, 837, -129, -202, -307, -1147, +-377, -1553, -424, -1228, -411, -442, -290, 395, +-103, 957, 107, 1034, 325, 646, 455, 34, +433, -507, 365, -736, 244, -547, -23, -40, +-288, 470, -417, 711, -427, 572, -343, 145, +-219, -407, -110, -877, 4, -1007, 159, -641, +348, 67, 513, 747, 506, 1157, 225, 1203, +-123, 763, -322, -51, -411, -883, -394, -1378, +-229, -1337, -24, -767, 93, 98, 131, 924, +182, 1389, 209, 1243, 80, 581, -117, -221, +-177, -922, -66, -1218, 137, -892, 297, -189, +281, 441, 77, 806, -206, 805, -418, 372, +-422, -215, -247, -603, -30, -626, 172, -281, +310, 135, 326, 411, 265, 533, 213, 435, +129, 106, -93, -237, -372, -511, -496, -712, +-399, -609, -148, -195, 207, 270, 527, 782, +567, 1147, 284, 993, -123, 349, -466, -457, +-568, -1173, -364, -1479, -4, -1184, 292, -457, +402, 505, 401, 1370, 342, 1636, 145, 1243, +-120, 431, -310, -521, -414, -1237, -440, -1412, +-341, -1062, -85, -344, 227, 444, 406, 899, +384, 918, 275, 621, 212, 91, 149, -363, +35, -477, -107, -295, -316, -8, -495, 288, +-499, 431, -362, 210, -76, -277, 320, -668, +584, -740, 560, -495, 356, -12, 149, 550, +-51, 939, -239, 1024, -345, 718, -342, 101, +-238, -563, -95, -1073, 56, -1209, 175, -829, +126, -163, -1, 521, -10, 1033, 72, 1093, +180, 635, 291, 4, 330, -512, 172, -710, +-182, -556, -513, -278, -617, -2, -462, 228, +-123, 300, 275, 259, 601, 167, 689, 52, +462, -6, 40, -75, -358, -210, -596, -219, +-637, -141, -389, -83, 79, 42, 461, 160, +676, 237, 673, 375, 252, 348, -373, 74, +-751, -229, -762, -523, -458, -672, 111, -459, +668, -87, 846, 358, 563, 802, 19, 847, +-481, 417, -704, -170, -616, -686, -229, -886, +320, -666, 697, -114, 757, 614, 527, 1120, +-20, 999, -715, 328, -1134, -653, -1038, -1479, +-476, -1591, 405, -960, 1223, 203, 1530, 1562, +1206, 2350, 341, 2104, -756, 964, -1512, -727, +-1603, -2351, -1114, -3072, -232, -2529, 753, -904, +1413, 1195, 1458, 2855, 911, 3358, 90, 2474, +-607, 598, -1055, -1409, -1171, -2780, -735, -2960, +39, -1956, 646, -326, 920, 1290, 820, 2283, +315, 2258, -358, 1394, -853, 80, -897, -1265, +-400, -1969, 302, -1666, 754, -656, 861, 598, +602, 1487, -7, 1619, -500, 977, -586, -204, +-556, -1218, -465, -1535, -183, -1216, 65, -292, +202, 868, 456, 1422, 684, 1218, 577, 653, +276, -238, -62, -1032, -424, -1152, -594, -688, +-536, 90, -439, 749, -308, 842, -87, 459, +239, -182, 615, -823, 791, -1059, 679, -679, +414, 195, -36, 1257, -593, 1820, -887, 1454, +-878, 363, -710, -1097, -214, -2323, 479, -2604, +955, -1687, 1149, 190, 972, 2090, 280, 3046, +-589, 2744, -1182, 1328, -1306, -687, -904, -2403, +-142, -3119, 676, -2561, 1300, -935, 1391, 1003, +815, 2495, -28, 2977, -802, 2043, -1367, 258, +-1384, -1447, -756, -2522, 178, -2429, 1036, -1094, +1429, 717, 1148, 2109, 399, 2353, -453, 1353, +-1044, -186, -1086, -1647, -671, -2529, -93, -2058, +516, -423, 896, 1370, 779, 2623, 324, 2801, +-227, 1670, -721, -267, -873, -2214, -531, -3310, +101, -3000, 700, -1435, 1020, 759, 840, 2748, +159, 3622, -606, 3010, -1088, 1155, -1160, -1180, +-699, -2921, 155, -3382, 953, -2494, 1355, -589, +1184, 1450, 422, 2649, -553, 2596, -1236, 1509, +-1402, -76, -939, -1484, -31, -2073, 795, -1611, +1299, -552, 1286, 638, 616, 1624, -209, 1767, +-846, 894, -1321, -318, -1223, -1370, -404, -1915, +491, -1564, 1043, -481, 1247, 814, 892, 1909, +19, 2228, -774, 1540, -1062, 257, -825, -1077, +-244, -1990, 363, -2159, 768, -1484, 766, -179, +319, 1101, -221, 1819, -589, 1743, -751, 909, +-630, -205, -123, -983, 621, -1218, 1096, -843, +991, -58, 445, 585, -315, 838, -1013, 611, +-1305, -120, -976, -744, -185, -898, 593, -695, +1075, -126, 1160, 590, 748, 1036, 54, 1084, +-555, 651, -959, -103, -1001, -722, -496, -1083, +210, -1028, 660, -340, 854, 370, 661, 757, +24, 955, -536, 635, -764, -151, -762, -758, +-386, -985, 308, -838, 885, -230, 1038, 589, +750, 1232, 180, 1484, -525, 1068, -1159, 105, +-1348, -983, -895, -1802, -37, -1963, 799, -1308, +1294, -29, 1338, 1272, 905, 2002, 74, 2006, +-781, 1181, -1294, -136, -1394, -1192, -941, -1682, +-8, -1624, 831, -842, 1257, 296, 1264, 1098, +751, 1417, -87, 1088, -811, 193, -1134, -608, +-920, -1107, -398, -1137, 86, -561, 537, 151, +798, 731, 647, 1165, 327, 977, -33, 281, +-397, -207, -463, -553, -296, -846, -152, -674, +18, -272, 168, 25, 184, 173, 43, 96, +-210, -53, -286, -21, -39, 204, 240, 554, +432, 861, 616, 826, 525, 416, 37, -152, +-516, -838, -936, -1460, -1070, -1598, -688, -1045, +46, -143, 690, 759, 1053, 1560, 1155, 1847, +832, 1376, 26, 541, -739, -425, -1060, -1240, +-949, -1443, -442, -1117, 143, -590, 487, 110, +598, 657, 388, 754, -40, 590, -300, 193, +-278, -331, -29, -497, 334, -208, 512, 322, +393, 780, 127, 839, -322, 518, -819, -68, +-879, -890, -513, -1446, 4, -1345, 621, -840, +1017, -80, 881, 858, 349, 1447, -253, 1487, +-679, 1163, -834, 500, -565, -327, 41, -880, +524, -1042, 683, -927, 546, -641, 137, -365, +-439, -243, -980, -103, -1026, 188, -391, 509, +410, 889, 1059, 1322, 1518, 1370, 1327, 884, +333, 87, -800, -981, -1606, -2058, -1910, -2393, +-1412, -1819, -346, -701, 793, 769, 1734, 2114, +2046, 2666, 1596, 2291, 577, 1164, -793, -372, +-1771, -1711, -1914, -2318, -1546, -2126, -615, -1251, +765, 9, 1679, 1150, 1703, 1724, 1167, 1538, +289, 819, -689, 5, -1308, -667, -1317, -977, +-789, -795, -28, -281, 614, 162, 964, 377, +934, 366, 542, 113, 8, -189, -444, -299, +-735, -129, -828, 220, -545, 436, 25, 364, +328, 74, 381, -330, 601, -757, 625, -779, +258, -204, 37, 454, -70, 901, -363, 1166, +-587, 977, -644, 187, -627, -827, -424, -1550, +10, -1766, 590, -1304, 1059, -218, 1139, 1118, +880, 2119, 302, 2255, -568, 1541, -1273, 285, +-1423, -1173, -1076, -2213, -428, -2349, 315, -1638, +971, -480, 1329, 831, 1211, 1870, 740, 2194, +80, 1741, -745, 706, -1355, -524, -1348, -1472, +-893, -1787, -104, -1433, 830, -704, 1296, 218, +1134, 993, 643, 1220, -33, 933, -699, 459, +-1056, -56, -946, -500, -527, -596, -14, -394, +601, -202, 1018, -25, 866, 149, 432, 195, +9, 50, -477, -35, -833, 30, -812, 12, +-597, -67, -277, -50, 293, 4, 846, 65, +1008, 175, 791, 249, 343, 202, -228, 144, +-811, -23, -1077, -361, -875, -644, -531, -690, +-45, -471, 670, -26, 1220, 558, 1340, 1087, +913, 1231, 21, 883, -834, 154, -1392, -735, +-1523, -1451, -972, -1635, -59, -1226, 653, -376, +1153, 724, 1416, 1664, 1168, 1997, 572, 1618, +-133, 640, -899, -646, -1357, -1807, -1328, -2317, +-986, -1951, -341, -886, 396, 559, 922, 1883, +1224, 2464, 1238, 2154, 924, 1093, 373, -464, +-307, -1792, -972, -2235, -1391, -1964, -1337, -1158, +-912, 117, -332, 1205, 430, 1601, 1166, 1502, +1501, 1046, 1441, 366, 1046, -224, 188, -595, +-863, -783, -1548, -782, -1743, -700, -1442, -646, +-585, -562, 418, -347, 1187, 49, 1684, 652, +1709, 1307, 1127, 1715, 166, 1576, -822, 869, +-1490, -233, -1619, -1451, -1240, -2337, -562, -2506, +169, -1820, 714, -447, 985, 1040, 1112, 2170, +1104, 2712, 833, 2435, 374, 1300, -208, -193, +-880, -1484, -1334, -2269, -1406, -2345, -1281, -1740, +-898, -674, -66, 497, 1000, 1300, 1910, 1634, +2321, 1505, 1959, 971, 892, 375, -561, -63, +-1967, -456, -2703, -750, -2444, -792, -1420, -795, +23, -839, 1463, -640, 2420, -218, 2618, 293, +1854, 788, 286, 1123, -1272, 1165, -2193, 860, +-2286, 244, -1420, -518, -17, -1034, 1143, -1087, +1772, -826, 1744, -315, 903, 272, -299, 666, +-1134, 706, -1491, 421, -1434, 11, -751, -293, +346, -463, 1225, -502, 1563, -171, 1338, 356, +664, 623, -170, 766, -896, 743, -1333, 260, +-1283, -470, -788, -1028, -217, -1285, 317, -1163, +753, -627, 806, 148, 694, 978, 690, 1556, +513, 1551, 177, 1084, -128, 328, -569, -531, +-1037, -1240, -1158, -1585, -867, -1402, -256, -770, +495, 76, 1003, 860, 1121, 1310, 936, 1289, +366, 771, -387, -2, -851, -700, -963, -1069, +-728, -967, -87, -346, 674, 475, 1129, 971, +995, 1087, 328, 775, -563, -78, -1352, -977, +-1672, -1555, -1248, -1645, -180, -1006, 1046, 162, +1960, 1291, 2281, 2047, 1698, 2127, 323, 1425, +-1134, 317, -2172, -940, -2548, -2013, -2000, -2295, +-660, -1900, 860, -1049, 1985, 263, 2380, 1456, +1901, 2022, 726, 2056, -682, 1455, -1711, 255, +-1890, -826, -1346, -1351, -366, -1502, 817, -1234, +1508, -537, 1374, 200, 814, 635, -103, 854, +-1182, 871, -1670, 478, -1394, -81, -695, -390, +385, -529, 1553, -527, 2114, -221, 1869, 293, +1025, 661, -306, 682, -1730, 416, -2539, -11, +-2369, -579, -1410, -1048, -13, -1059, 1480, -674, +2501, -21, 2570, 839, 1733, 1366, 320, 1319, +-1194, 905, -2256, 91, -2488, -887, -1728, -1454, +-277, -1470, 1213, -919, 2240, 123, 2375, 1117, +1367, 1597, -306, 1453, -1781, 556, -2531, -743, +-2284, -1733, -965, -2011, 974, -1365, 2584, 63, +3044, 1572, 2264, 2501, 630, 2517, -1358, 1559, +-2861, -224, -3194, -2127, -2394, -3223, -743, -3193, +1245, -2122, 2649, -155, 2976, 2034, 2320, 3536, +839, 3888, -930, 2944, -2123, 875, -2346, -1466, +-1651, -3295, -358, -4101, 786, -3477, 1245, -1684, +1118, 588, 591, 2639, -167, 3683, -693, 3437, +-616, 2158, -137, 265, 413, -1591, 852, -2718, +891, -2957, 395, -2322, -411, -922, -1201, 619, +-1546, 1743, -1175, 2284, -273, 2092, 789, 1247, +1578, 97, 1714, -947, 1228, -1648, 349, -1782, +-716, -1296, -1511, -489, -1619, 386, -1181, 1160, +-447, 1538, 465, 1356, 1195, 728, 1364, -163, +993, -1007, 454, -1368, 7, -1307, -438, -844, +-778, 60, -781, 861, -651, 1270, -598, 1324, +-453, 815, -89, -32, 398, -683, 882, -1068, +1258, -1168, 1344, -719, 1034, -49, 320, 462, +-735, 788, -1766, 746, -2269, 475, -2038, 201, +-1059, -116, 511, -290, 2006, -250, 2713, -219, +2552, -288, 1570, -309, -107, -300, -1683, -239, +-2528, 19, -2631, 354, -1888, 655, -391, 843, +1239, 670, 2328, 164, 2442, -384, 1631, -835, +329, -1181, -1025, -1026, -1900, -367, -1879, 227, +-1120, 812, -56, 1406, 1010, 1348, 1637, 683, +1465, 5, 698, -714, -290, -1409, -1264, -1520, +-1795, -1081, -1421, -341, -314, 534, 809, 1187, +1581, 1498, 1845, 1390, 1310, 760, 223, -62, +-864, -783, -1678, -1354, -1841, -1558, -1253, -1226, +-364, -561, 573, 294, 1396, 1069, 1689, 1458, +1340, 1519, 658, 1129, -145, 244, -976, -575, +-1503, -1058, -1390, -1388, -820, -1420, -224, -886, +409, -182, 1060, 330, 1267, 884, 994, 1404, +631, 1454, 141, 1070, -541, 519, -1110, -179, +-1263, -985, -974, -1628, -467, -1812, 158, -1349, +854, -522, 1220, 322, 1089, 1262, 751, 1986, +242, 1896, -515, 1239, -1176, 408, -1312, -582, +-922, -1474, -335, -1890, 343, -1735, 1072, -1094, +1337, -220, 881, 643, 229, 1395, -362, 1782, +-931, 1526, -1126, 845, -815, 48, -238, -713, +488, -1254, 1000, -1374, 962, -1017, 571, -455, +13, -10, -601, 353, -892, 650, -745, 756, +-386, 667, 64, 604, 530, 567, 762, 259, +608, -306, 293, -733, -23, -937, -460, -1043, +-746, -838, -565, -252, -232, 409, 73, 974, +451, 1177, 627, 1018, 469, 781, 234, 243, +-17, -669, -320, -1230, -540, -1208, -574, -1048, +-416, -607, -168, 254, 82, 958, 424, 1198, +815, 1045, 930, 713, 657, 307, 119, -225, +-558, -683, -1171, -880, -1418, -943, -1091, -989, +-332, -792, 534, -183, 1312, 573, 1684, 1279, +1450, 1755, 776, 1766, -229, 1142, -1273, -2, +-1865, -1268, -1864, -2320, -1195, -2661, 67, -2036, +1297, -758, 1946, 876, 1867, 2338, 1091, 3053, +-15, 2803, -995, 1649, -1632, -107, -1656, -1865, +-987, -2991, -73, -3145, 799, -2244, 1449, -676, +1458, 1023, 843, 2441, -41, 2829, -928, 2131, +-1371, 1064, -1082, -166, -318, -1332, 425, -1723, +839, -1407, 912, -1024, 639, -515, 65, 120, +-487, 378, -763, 350, -678, 443, -283, 682, +235, 817, 694, 812, 827, 746, 415, 417, +-244, -284, -729, -1112, -940, -1665, -701, -1657, +42, -1096, 785, -174, 1147, 830, 1092, 1683, +537, 1962, -326, 1448, -1158, 528, -1681, -345, +-1367, -979, -319, -1338, 739, -1262, 1616, -756, +2036, -279, 1418, 50, 139, 348, -1014, 485, +-1873, 514, -2182, 646, -1530, 731, -267, 696, +994, 661, 2061, 315, 2523, -451, 1865, -1121, +467, -1603, -950, -1837, -2111, -1374, -2626, -245, +-2080, 1057, -846, 2106, 504, 2533, 1745, 2183, +2489, 1100, 2340, -437, 1411, -1802, 104, -2521, +-1124, -2584, -2001, -1906, -2364, -509, -1887, 972, +-741, 1986, 385, 2438, 1317, 2194, 1986, 1268, +1960, 9, 1252, -1086, 263, -1702, -707, -1821, +-1377, -1489, -1602, -771, -1312, 70, -563, 679, +224, 992, 748, 1180, 1063, 1111, 989, 646, +420, 111, -157, -199, -433, -467, -563, -710, +-445, -683, 21, -509, 444, -357, 491, -216, +257, -143, -105, 4, -538, 344, -846, 641, +-749, 742, -286, 817, 344, 747, 929, 345, +1184, -210, 984, -799, 413, -1261, -328, -1367, +-923, -1075, -1205, -459, -1116, 327, -642, 1133, +8, 1626, 582, 1557, 951, 997, 1011, 195, +805, -549, 473, -1147, 85, -1439, -334, -1236, +-680, -677, -919, -59, -1092, 384, -1091, 701, +-718, 846, 103, 733, 1145, 526, 1933, 351, +2156, 223, 1700, -17, 534, -359, -1045, -576, +-2434, -750, -3061, -848, -2668, -646, -1398, -195, +452, 204, 2367, 505, 3607, 731, 3597, 741, +2284, 627, 190, 442, -1957, 199, -3518, 38, +-3822, -193, -2662, -550, -693, -823, 1239, -960, +2630, -1032, 3105, -856, 2450, -260, 978, 566, +-562, 1315, -1576, 1785, -1890, 1897, -1532, 1455, +-635, 373, 299, -869, 724, -1906, 633, -2507, +263, -2359, -187, -1489, -395, -223, -286, 1136, +-28, 2190, 370, 2510, 813, 2138, 998, 1374, +825, 331, 342, -786, -385, -1676, -1103, -2053, +-1480, -2004, -1494, -1749, -1175, -1118, -405, -167, +568, 847, 1296, 1890, 1829, 2636, 2156, 2685, +1817, 2095, 794, 958, -438, -709, -1724, -2341, +-2845, -3311, -3132, -3438, -2310, -2604, -801, -1013, +1010, 801, 2804, 2497, 3893, 3648, 3624, 3787, +2108, 2796, -29, 1005, -2254, -987, -3901, -2693, +-4185, -3722, -3027, -3638, -961, -2436, 1402, -630, +3284, 1182, 3974, 2549, 3341, 3099, 1700, 2747, +-405, 1751, -2271, 460, -3259, -811, -3133, -1777, +-2071, -2178, -433, -1957, 1246, -1381, 2315, -609, +2497, 249, 1970, 1013, 972, 1549, -259, 1664, +-1245, 1302, -1613, 672, -1474, -94, -1123, -887, +-613, -1448, 43, -1560, 579, -1129, 831, -223, +1087, 718, 1342, 1390, 1125, 1679, 488, 1288, +-173, 264, -906, -875, -1672, -1766, -1999, -2189, +-1603, -1822, -687, -602, 474, 987, 1692, 2375, +2607, 3117, 2688, 2916, 1772, 1581, 235, -581, +-1444, -2622, -2892, -3853, -3510, -3966, -2835, -2803, +-1204, -665, 699, 1712, 2503, 3511, 3767, 4338, +3831, 3947, 2539, 2325, 522, 122, -1565, -1937, +-3326, -3470, -4198, -4118, -3705, -3523, -2093, -2021, +-25, -293, 2044, 1425, 3687, 2706, 4252, 3240, +3533, 3142, 1949, 2396, -124, 1137, -2292, -242, +-3783, -1549, -4124, -2718, -3478, -3398, -2013, -3255, +151, -2372, 2304, -866, 3625, 1047, 4021, 2924, +3573, 4135, 2057, 4168, -183, 3017, -2178, 967, +-3433, -1488, -3936, -3597, -3455, -4612, -1906, -4154, +144, -2472, 1959, -126, 3169, 2240, 3594, 3923, +3064, 4275, 1656, 3199, -99, 1225, -1587, -991, +-2545, -2805, -2944, -3669, -2652, -3310, -1661, -1860, +-364, 135, 864, 1996, 1949, 3076, 2651, 3133, +2648, 2225, 2025, 498, 956, -1414, -475, -2658, +-1845, -2954, -2756, -2438, -3077, -1167, -2539, 508, +-1129, 1866, 589, 2615, 2181, 2688, 3335, 2003, +3541, 803, 2593, -504, 853, -1623, -1157, -2386, +-2914, -2610, -3865, -2150, -3573, -1226, -2112, -77, +-127, 1184, 1776, 2215, 3263, 2670, 3802, 2540, +3081, 1881, 1558, 753, -246, -556, -2063, -1734, +-3273, -2589, -3321, -2857, -2408, -2491, -1047, -1608, +477, -372, 1789, 928, 2437, 2160, 2354, 3038, +1825, 3110, 1065, 2512, 152, 1494, -804, 13, +-1487, -1645, -1745, -2909, -1811, -3540, -1654, -3394, +-996, -2377, -105, -809, 742, 936, 1664, 2545, +2337, 3593, 2245, 3802, 1576, 3040, 559, 1521, +-769, -271, -1946, -1994, -2514, -3307, -2414, -3762, +-1624, -3232, -343, -1980, 1034, -338, 2107, 1343, +2401, 2707, 1869, 3425, 963, 3181, -154, 2116, +-1226, 635, -1666, -937, -1457, -2252, -1014, -2918, +-377, -2685, 341, -1729, 748, -440, 804, 880, +693, 1939, 438, 2332, 188, 1826, 142, 838, +128, -229, -102, -1220, -464, -1759, -833, -1523, +-1098, -676, -976, 241, -348, 1016, 513, 1612, +1345, 1610, 1905, 893, 1865, -181, 1076, -1188, +-262, -1869, -1678, -1987, -2606, -1418, -2755, -422, +-1999, 746, -383, 1740, 1475, 2098, 2789, 1821, +3197, 1197, 2627, 402, 1298, -508, -371, -1181, +-1913, -1399, -2745, -1457, -2654, -1451, -2044, -1210, +-1093, -780, 165, -261, 1229, 447, 1762, 1383, +1965, 2268, 1901, 2788, 1544, 2655, 1007, 1721, +276, 133, -651, -1758, -1614, -3458, -2461, -4393, +-2889, -4124, -2594, -2621, -1534, -246, 143, 2370, +2054, 4417, 3576, 5305, 4189, 4748, 3613, 2748, +1847, -127, -633, -2845, -2890, -4639, -4227, -5153, +-4473, -4151, -3446, -1973, -1196, 478, 1375, 2495, +3223, 3623, 3940, 3655, 3526, 2785, 2106, 1451, +158, 37, -1524, -1166, -2351, -1887, -2305, -2052, +-1698, -1831, -824, -1406, -2, -853, 430, -247, +508, 226, 471, 630, 405, 1165, 434, 1647, +724, 1799, 1173, 1585, 1352, 1044, 891, 173, +5, -981, -1009, -2016, -2123, -2468, -2829, -2276, +-2434, -1620, -1117, -551, 564, 820, 2293, 1974, +3541, 2546, 3573, 2621, 2283, 2124, 260, 999, +-1831, -481, -3391, -1891, -3785, -2854, -2866, -3080, +-1153, -2425, 783, -1059, 2453, 639, 3185, 2125, +2764, 2922, 1658, 2909, 231, 2038, -1189, 615, +-1959, -772, -1824, -1821, -1201, -2320, -579, -2055, +-95, -1266, 225, -429, 241, 323, 103, 839, +235, 933, 643, 912, 1063, 953, 1358, 929, +1350, 864, 854, 740, -94, 320, -1265, -429, +-2270, -1243, -2708, -1899, -2311, -2150, -1070, -1815, +601, -963, 2066, 298, 2945, 1679, 3019, 2700, +2184, 2925, 714, 2347, -851, 1171, -2024, -446, +-2509, -1949, -2375, -2770, -1762, -2848, -719, -2269, +415, -1073, 1224, 385, 1599, 1434, 1589, 1932, +1341, 2037, 933, 1759, 399, 1193, -117, 490, +-545, -115, -901, -576, -1116, -1078, -1215, -1574, +-1128, -1862, -719, -1799, -159, -1389, 351, -549, +868, 679, 1251, 1890, 1241, 2666, 925, 2727, +511, 2051, 56, 771, -301, -791, -450, -2008, +-497, -2566, -588, -2473, -738, -1730, -899, -573, +-1020, 487, -934, 1201, -463, 1535, 286, 1364, +1200, 902, 2091, 592, 2529, 467, 2317, 404, +1423, 348, -200, 85, -2040, -554, -3397, -1383, +-3929, -2088, -3329, -2334, -1563, -1836, 762, -646, +2924, 912, 4310, 2466, 4406, 3504, 3177, 3488, +1034, 2312, -1430, 394, -3393, -1686, -4199, -3275, +-3723, -3888, -2182, -3344, -105, -1693, 1763, 439, +2835, 2089, 2836, 2905, 2023, 2943, 920, 2083, +-163, 604, -987, -705, -1265, -1478, -1022, -1681, +-600, -1233, -370, -450, -368, 160, -414, 371, +-419, 116, -321, -360, 32, -669, 643, -660, +1250, -174, 1529, 832, 1366, 1848, 800, 2214, +-94, 1774, -1090, 665, -1804, -893, -2004, -2327, +-1624, -3068, -728, -2806, 367, -1552, 1274, 187, +1833, 1819, 1877, 2888, 1371, 3052, 603, 2228, +-256, 754, -1141, -812, -1721, -2047, -1749, -2496, +-1256, -2061, -397, -1135, 556, -45, 1273, 909, +1511, 1410, 1244, 1340, 635, 847, -137, 227, +-858, -277, -1264, -470, -1138, -335, -518, 4, +296, 243, 1008, 194, 1382, -39, 1108, -409, +238, -729, -760, -721, -1539, -441, -1885, -27, +-1444, 460, -283, 811, 1010, 844, 1985, 729, +2423, 481, 2087, -6, 950, -502, -636, -771, +-2000, -769, -2625, -551, -2495, -179, -1672, 205, +-255, 392, 1149, 380, 1996, 222, 2283, 11, +2039, -166, 1202, -235, 76, -128, -842, 83, +-1352, 326, -1522, 498, -1384, 565, -995, 481, +-481, 92, 38, -428, 468, -886, 804, -1208, +1095, -1201, 1184, -741, 895, 11, 377, 736, +-119, 1340, -516, 1707, -735, 1530, -714, 842, +-525, 7, -273, -699, -98, -1287, -86, -1640, +-169, -1527, -290, -1048, -253, -411, 113, 247, +584, 787, 983, 1134, 1331, 1315, 1310, 1323, +675, 1055, -263, 598, -1087, 127, -1686, -468, +-1979, -1203, -1723, -1645, -810, -1601, 369, -1317, +1281, -808, 1812, -35, 1975, 736, 1516, 1331, +534, 1703, -312, 1706, -754, 1339, -1101, 803, +-1281, 159, -962, -576, -474, -1274, -315, -1763, +-179, -1924, 196, -1810, 445, -1393, 534, -508, +789, 724, 1024, 1890, 898, 2647, 471, 2839, +-9, 2331, -495, 1096, -982, -538, -1222, -2018, +-1005, -2947, -500, -3089, 58, -2381, 532, -1070, +742, 421, 615, 1671, 294, 2360, -68, 2395, +-254, 1861, -67, 943, 311, -60, 534, -829, +531, -1294, 344, -1412, -29, -1169, -586, -787, +-1091, -408, -1227, -61, -976, 262, -468, 510, +267, 584, 977, 627, 1339, 641, 1303, 470, +926, 232, 294, 131, -344, 54, -755, -121, +-850, -242, -656, -403, -347, -666, -121, -766, +-3, -697, -34, -496, -261, -103, -458, 400, +-300, 852, 159, 1096, 672, 1059, 1133, 717, +1435, 192, 1282, -374, 608, -808, -304, -935, +-1163, -814, -1784, -488, -1953, -22, -1568, 353, +-747, 449, 191, 313, 992, 74, 1529, -258, +1674, -448, 1422, -199, 1022, 352, 562, 834, +-42, 1059, -626, 991, -1013, 505, -1320, -338, +-1543, -1211, -1500, -1736, -1137, -1712, -530, -1254, +275, -424, 1194, 655, 2029, 1588, 2439, 2029, +2220, 1899, 1404, 1317, 156, 351, -1227, -714, +-2293, -1445, -2736, -1720, -2509, -1591, -1686, -1103, +-416, -372, 951, 299, 1951, 749, 2341, 1010, +2189, 1005, 1567, 874, 581, 728, -403, 433, +-1079, 52, -1483, -262, -1606, -548, -1346, -840, +-829, -1005, -299, -980, 265, -775, 822, -337, +1102, 218, 1051, 745, 887, 1217, 586, 1482, +90, 1309, -387, 690, -690, -113, -831, -876, +-676, -1489, -265, -1746, 66, -1430, 241, -627, +388, 346, 371, 1192, 99, 1696, -178, 1679, +-274, 1052, -318, 72, -305, -826, -44, -1396, +384, -1521, 617, -1132, 598, -343, 484, 462, +260, 958, -110, 1104, -412, 943, -565, 525, +-688, 38, -764, -278, -654, -450, -388, -605, +-4, -682, 504, -714, 946, -711, 1147, -449, +1164, 114, 925, 723, 334, 1235, -370, 1547, +-941, 1421, -1379, 795, -1529, -180, -1186, -1293, +-492, -2170, 209, -2380, 772, -1785, 1146, -588, +1232, 901, 945, 2159, 510, 2687, 231, 2344, +8, 1248, -325, -216, -567, -1473, -664, -2121, +-835, -2113, -1001, -1490, -860, -432, -453, 554, +26, 1172, 591, 1336, 1182, 1028, 1502, 493, +1403, -4, 897, -271, 117, -256, -692, -93, +-1299, 19, -1508, -54, -1199, -300, -583, -640, +47, -803, 568, -649, 844, -241, 717, 444, +410, 1129, 166, 1355, -49, 1041, -152, 406, +7, -380, 257, -1129, 326, -1430, 135, -1154, +-156, -493, -463, 348, -774, 1057, -805, 1304, +-408, 1040, 35, 469, 301, -261, 514, -914, +613, -1162, 437, -944, 221, -417, 166, 138, +119, 573, 37, 858, 60, 852, 59, 515, +-161, 113, -504, -152, -730, -370, -843, -480, +-838, -404, -491, -330, 207, -308, 892, -282, +1297, -188, 1422, 10, 1253, 283, 619, 600, +-295, 832, -989, 817, -1362, 540, -1511, 157, +-1224, -318, -536, -896, 100, -1218, 505, -1119, +905, -764, 1206, -198, 1089, 522, 727, 1112, +470, 1315, 90, 1145, -558, 673, -959, -11, +-910, -642, -884, -1028, -828, -1094, -378, -825, +210, -305, 611, 248, 894, 609, 985, 688, +742, 529, 286, 205, -145, -140, -451, -309, +-593, -241, -520, -68, -284, 103, -104, 243, +-41, 253, 9, 35, 72, -226, 80, -356, +114, -358, 246, -258, 326, -31, 238, 272, +113, 427, -42, 327, -274, 125, -410, -59, +-336, -233, -231, -343, -73, -216, 252, 48, +538, 238, 579, 383, 470, 448, 180, 257, +-324, -138, -830, -465, -1035, -634, -806, -695, +-296, -539, 247, -108, 803, 428, 1195, 798, +1170, 925, 836, 842, 368, 518, -312, -27, +-1087, -573, -1542, -865, -1452, -869, -998, -705, +-318, -417, 520, -35, 1228, 330, 1511, 519, +1411, 572, 1024, 553, 350, 448, -463, 267, +-1111, 36, -1447, -139, -1344, -220, -813, -294, +-116, -364, 506, -399, 911, -392, 984, -403, +751, -322, 322, -77, -103, 246, -389, 593, +-463, 841, -284, 887, 30, 674, 267, 199, +320, -327, 118, -716, -245, -891, -575, -852, +-717, -579, -619, -182, -249, 145, 317, 380, +871, 470, 1185, 374, 1094, 259, 561, 266, +-144, 340, -774, 372, -1167, 397, -1142, 287, +-721, -135, -185, -741, 260, -1176, 626, -1257, +884, -1002, 789, -401, 411, 479, 79, 1295, +-184, 1649, -466, 1447, -572, 905, -376, 116, +-52, -768, 76, -1356, 34, -1356, 62, -904, +147, -314, 103, 251, 56, 626, 119, 651, +82, 371, -85, -30, -140, -288, -100, -251, +-43, 80, 32, 498, 70, 776, 94, 817, +138, 489, 124, -227, 26, -986, -116, -1407, +-238, -1400, -320, -1003, -270, -218, -49, 644, +205, 1245, 327, 1518, 342, 1376, 282, 803, +136, 133, -91, -388, -233, -800, -252, -1017, +-267, -913, -250, -745, -80, -669, 93, -453, +102, -43, 120, 358, 268, 792, 314, 1229, +219, 1392, 110, 1159, -70, 603, -316, -196, +-479, -983, -500, -1465, -297, -1595, 20, -1337, +243, -621, 441, 197, 699, 777, 703, 1104, +341, 1189, -121, 984, -504, 584, -821, 176, +-897, -141, -596, -354, -90, -499, 346, -604, +622, -653, 739, -751, 652, -806, 357, -601, +41, -146, -154, 422, -285, 1058, -392, 1582, +-374, 1641, -283, 1141, -258, 321, -281, -634, +-202, -1519, -48, -2019, 122, -1891, 314, -1216, +586, -205, 829, 895, 811, 1759, 466, 2065, +9, 1685, -517, 825, -1051, -189, -1233, -1107, +-948, -1619, -517, -1551, -65, -999, 486, -234, +953, 531, 1109, 1018, 1011, 1048, 711, 745, +207, 252, -392, -266, -830, -585, -898, -590, +-648, -315, -347, 22, -72, 321, 90, 470, +87, 336, 11, -19, 36, -358, 146, -551, +248, -563, 371, -265, 578, 223, 735, 551, +681, 713, 318, 697, -279, 381, -893, -160, +-1394, -647, -1564, -904, -1159, -915, -341, -640, +512, -53, 1200, 678, 1645, 1209, 1628, 1276, +1151, 914, 471, 214, -278, -649, -1022, -1365, +-1413, -1594, -1307, -1275, -894, -541, -449, 430, +-19, 1296, 322, 1686, 444, 1529, 450, 928, +562, 27, 737, -898, 813, -1472, 775, -1580, +619, -1217, 190, -505, -494, 288, -1141, 934, +-1561, 1280, -1650, 1225, -1294, 806, -507, 215, +550, -311, 1451, -699, 1892, -877, 1850, -806, +1378, -500, 495, -80, -503, 298, -1223, 505, +-1548, 495, -1586, 339, -1221, 81, -516, -200, +209, -299, 753, -194, 1067, 9, 1152, 204, +948, 317, 458, 293, -73, 142, -404, -113, +-557, -363, -595, -496, -440, -522, -151, -401, +29, -76, 59, 297, 75, 550, -12, 672, +-110, 673, -64, 415, 49, -38, 117, -442, +273, -669, 405, -737, 307, -570, 108, -122, +-6, 333, -154, 547, -320, 585, -329, 440, +-222, 92, -126, -330, -75, -552, -15, -502, +26, -278, 2, 80, -25, 470, 40, 695, +225, 661, 403, 383, 473, -98, 403, -611, +188, -863, -164, -874, -471, -672, -666, -201, +-696, 360, -511, 745, -123, 918, 254, 887, +493, 592, 638, 136, 590, -223, 228, -452, +-146, -634, -212, -746, -162, -633, -148, -405, +-36, -205, 113, 36, 36, 330, -194, 559, +-298, 656, -315, 630, -289, 527, -93, 367, +250, 163, 489, -164, 545, -502, 391, -720, +98, -807, -227, -795, -422, -644, -410, -307, +-196, 128, 116, 590, 381, 992, 442, 1169, +231, 1130, -162, 816, -525, 236, -714, -438, +-746, -1013, -487, -1387, 98, -1418, 723, -1044, +1138, -439, 1256, 268, 1042, 936, 477, 1258, +-274, 1213, -1013, 903, -1500, 393, -1562, -172, +-1187, -520, -579, -590, 204, -534, 952, -421, +1372, -255, 1446, -168, 1340, -274, 959, -414, +235, -318, -499, -38, -1026, 337, -1410, 769, +-1505, 1133, -1139, 1157, -509, 748, 123, 118, +620, -512, 951, -1054, 1068, -1375, 936, -1306, +702, -851, 421, -229, 137, 421, -177, 911, +-461, 1143, -650, 1087, -741, 760, -786, 308, +-768, -87, -694, -364, -403, -562, 134, -697, +687, -693, 1099, -583, 1352, -427, 1374, -216, +939, 132, 200, 495, -458, 704, -1010, 785, +-1443, 717, -1512, 409, -1173, -22, -615, -383, +-5, -586, 567, -619, 1077, -459, 1283, -242, +1134, -66, 802, 50, 473, 132, 74, 176, +-331, 199, -605, 253, -794, 337, -972, 344, +-985, 219, -764, 31, -414, -151, -20, -380, +405, -523, 815, -461, 1025, -257, 1037, -1, +944, 279, 725, 488, 340, 506, -188, 334, +-692, 35, -1118, -274, -1462, -424, -1555, -448, +-1214, -307, -559, 33, 321, 379, 1258, 475, +2003, 363, 2201, 197, 1766, -43, 851, -301, +-321, -394, -1432, -340, -2103, -214, -2123, -65, +-1606, 103, -744, 194, 326, 219, 1256, 213, +1607, 160, 1463, 75, 1045, 25, 406, 52, +-216, 90, -604, 26, -747, -93, -711, -194, +-490, -281, -245, -416, -82, -439, -26, -263, +30, -4, 80, 279, 157, 599, 294, 868, +441, 895, 447, 592, 240, 53, -78, -591, +-329, -1100, -423, -1331, -383, -1156, -169, -559, +142, 282, 393, 1032, 464, 1380, 269, 1281, +-112, 822, -479, 98, -717, -633, -748, -1065, +-341, -1024, 325, -685, 797, -206, 935, 280, +907, 594, 587, 611, -5, 344, -591, -37, +-912, -337, -934, -429, -704, -276, -282, 7, +189, 342, 458, 593, 409, 617, 277, 335, +255, -100, 268, -485, 273, -747, 353, -801, +366, -610, 111, -256, -267, 171, -572, 556, +-796, 793, -977, 807, -828, 687, -315, 427, +332, 0, 882, -466, 1254, -767, 1311, -854, +932, -780, 175, -492, -545, -33, -1037, 364, +-1318, 636, -1170, 730, -600, 614, 66, 337, +575, 48, 891, -208, 954, -393, 692, -396, +242, -249, -150, -71, -391, 72, -511, 108, +-481, 31, -320, -140, -100, -287, 37, -346, +186, -205, 283, 129, 241, 443, 131, 648, +85, 767, 9, 637, -120, 189, -157, -319, +-128, -667, -191, -914, -215, -984, -50, -766, +126, -286, 261, 229, 385, 622, 391, 906, +197, 1030, -60, 890, -263, 543, -427, 92, +-474, -377, -430, -799, -283, -1099, -16, -1211, +302, -904, 530, -274, 651, 374, 570, 947, +375, 1306, 94, 1192, -259, 640, -569, -40, +-701, -614, -660, -964, -532, -912, -236, -532, +204, -45, 496, 382, 620, 638, 780, 540, +751, 142, 366, -223, -90, -455, -434, -539, +-739, -306, -889, 101, -632, 448, -215, 651, +110, 625, 367, 301, 572, -83, 551, -380, +402, -583, 231, -577, -1, -356, -273, -103, +-351, 75, -242, 166, -149, 211, -85, 180, +-16, 181, -8, 260, -94, 324, -102, 291, +46, 210, 231, 63, 312, -217, 252, -513, +133, -673, -34, -642, -231, -429, -338, -173, +-238, 199, -62, 641, 126, 874, 278, 768, +393, 509, 288, 221, -84, -175, -478, -608, +-663, -836, -638, -755, -332, -465, 290, -138, +911, 213, 1128, 489, 892, 601, 397, 473, +-291, 175, -968, -38, -1277, -128, -1113, -217, +-650, -197, -27, -8, 676, 141, 1132, 111, +1131, 25, 771, -139, 302, -336, -225, -427, +-611, -324, -686, -52, -533, 255, -345, 493, +-152, 604, -48, 517, -51, 255, -34, -88, +92, -371, 302, -570, 493, -599, 651, -417, +668, -106, 392, 179, -95, 350, -570, 394, +-891, 269, -973, 76, -735, -11, -243, -27, +286, 51, 631, 160, 813, 150, 744, -20, +417, -242, -4, -473, -275, -606, -395, -486, +-341, -146, -102, 293, 100, 723, 55, 943, +-120, 847, -273, 416, -379, -180, -351, -746, +-147, -1115, 201, -1107, 544, -658, 713, 24, +649, 643, 415, 1040, 61, 1101, -334, 732, +-567, 97, -632, -472, -544, -701, -344, -708, +-148, -567, -17, -201, 145, 177, 275, 275, +372, 201, 439, 165, 482, 138, 458, 102, +320, 162, 101, 266, -221, 315, -593, 187, +-850, -100, -890, -460, -655, -746, -207, -774, +221, -503, 564, -27, 830, 515, 896, 920, +724, 1032, 403, 755, 52, 202, -360, -380, +-696, -778, -809, -981, -665, -873, -416, -383, +-163, 177, 77, 538, 308, 740, 407, 754, +411, 474, 409, -9, 325, -366, 171, -493, +63, -473, -2, -326, -110, -27, -190, 212, +-242, 238, -370, 169, -475, 68, -434, -27, +-266, -13, -46, 42, 227, 120, 488, 161, +643, 57, 641, -176, 545, -338, 256, -428, +-165, -422, -522, -133, -648, 301, -542, 599, +-363, 763, -200, 748, -10, 422, 135, -170, +178, -719, 177, -1072, 165, -1159, 181, -897, +215, -312, 277, 462, 384, 1185, 441, 1575, +283, 1493, -134, 959, -581, 86, -924, -923, +-1055, -1645, -833, -1853, -283, -1528, 295, -736, +785, 274, 1096, 1166, 1144, 1703, 912, 1745, +447, 1285, -202, 493, -763, -388, -988, -1151, +-951, -1506, -736, -1413, -363, -964, 45, -255, +297, 481, 399, 958, 487, 1047, 529, 837, +443, 466, 327, 13, 278, -367, 152, -499, +-106, -347, -356, -182, -465, -78, -587, 27, +-650, 39, -470, -81, -163, -195, 66, -197, +321, -82, 610, 102, 731, 287, 601, 372, +390, 361, 208, 220, -18, 20, -283, -143, +-482, -236, -570, -249, -630, -199, -640, -123, +-453, -66, -100, -46, 288, -26, 648, -25, +893, -29, 859, -12, 643, 95, 316, 242, +-139, 348, -597, 379, -832, 319, -853, 141, +-645, -166, -280, -467, 87, -597, 366, -594, +514, -441, 508, -123, 385, 222, 240, 413, +109, 505, -29, 507, -118, 336, -100, 144, +-69, 66, -118, 3, -232, -87, -335, -182, +-354, -301, -306, -477, -112, -598, 157, -600, +363, -425, 477, -34, 533, 481, 423, 930, +182, 1176, -55, 1119, -254, 687, -449, -33, +-485, -784, -328, -1347, -178, -1484, -98, -1143, +-12, -469, 79, 325, 155, 1002, 248, 1285, +367, 1080, 415, 582, 318, 22, 132, -430, +-8, -593, -154, -460, -358, -193, -503, -20, +-512, -9, -447, -158, -209, -374, 138, -459, +434, -316, 594, 26, 602, 503, 442, 942, +183, 1102, -80, 840, -354, 264, -574, -480, +-544, -1143, -333, -1441, -127, -1199, 155, -516, +430, 301, 445, 994, 243, 1339, 45, 1175, +-80, 614, -232, -91, -334, -668, -255, -965, +-33, -927, 160, -592, 304, -61, 407, 382, +365, 552, 88, 568, -183, 454, -340, 160, +-458, -101, -474, -191, -342, -210, -179, -251, +39, -251, 380, -226, 667, -186, 723, -103, +570, 67, 241, 299, -146, 452, -443, 461, +-618, 361, -671, 148, -588, -130, -408, -421, +-131, -565, 196, -534, 521, -416, 709, -218, +692, 106, 514, 435, 274, 612, 3, 631, +-283, 477, -507, 156, -577, -162, -576, -387, +-496, -473, -260, -441, -9, -323, 177, -166, +398, -44, 591, 31, 612, 141, 488, 293, +315, 386, 75, 371, -191, 297, -398, 157, +-527, -21, -603, -207, -591, -313, -483, -333, +-202, -338, 209, -329, 591, -273, 828, -147, +884, 51, 674, 291, 256, 563, -241, 763, +-701, 731, -960, 405, -917, -54, -585, -551, +-4, -969, 605, -1070, 923, -783, 853, -257, +494, 321, -95, 811, -715, 1076, -989, 923, +-755, 431, -222, -118, 441, -537, 1025, -762, +1235, -655, 905, -284, 165, 74, -693, 293, +-1355, 312, -1605, 105, -1254, -140, -375, -256, +650, -164, 1432, 111, 1741, 442, 1436, 630, +636, 571, -286, 231, -1042, -298, -1421, -790, +-1241, -1047, -681, -947, -73, -452, 424, 260, +704, 903, 679, 1224, 482, 1161, 241, 678, +16, -101, -87, -791, -29, -1097, 14, -1052, +-12, -691, -122, -77, -321, 452, -469, 677, +-450, 692, -275, 497, 57, 175, 406, -73, +577, -164, 507, -194, 296, -177, 43, -90, +-196, -44, -307, -135, -257, -266, -151, -298, +-21, -220, 20, -78, -49, 196, -82, 508, +-84, 677, -129, 628, -55, 368, 195, -65, +421, -520, 471, -792, 384, -813, 115, -604, +-311, -178, -669, 294, -769, 636, -572, 763, +-117, 655, 436, 329, 841, -46, 875, -354, +563, -546, 97, -520, -394, -282, -793, 22, +-897, 268, -651, 331, -184, 210, 319, 1, +698, -206, 812, -344, 658, -261, 287, 8, +-136, 258, -413, 423, -505, 487, -482, 386, +-352, 108, -188, -274, -38, -563, 88, -666, +196, -581, 298, -328, 380, 62, 416, 443, +370, 661, 218, 659, -27, 445, -342, 136, +-597, -149, -681, -389, -584, -484, -274, -384, +194, -191, 550, -46, 661, 57, 579, 129, +344, 119, 13, 62, -239, 65, -352, 123, +-353, 160, -255, 173, -96, 164, 10, 64, +35, -77, 9, -209, -36, -292, -45, -281, +56, -177, 219, -48, 324, 66, 295, 140, +155, 139, -76, 80, -346, 40, -467, 45, +-312, 124, -40, 211, 210, 250, 384, 203, +383, 36, 152, -228, -206, -518, -505, -715, +-587, -669, -395, -337, 69, 172, 587, 673, +884, 1010, 856, 1002, 503, 645, -107, 51, +-746, -596, -1151, -1015, -1159, -1052, -768, -771, +-68, -240, 687, 411, 1159, 878, 1197, 959, +868, 700, 273, 169, -393, -420, -844, -779, +-922, -788, -739, -483, -392, 41, 51, 566, +409, 848, 528, 770, 446, 366, 269, -217, +58, -752, -128, -1031, -174, -895, -78, -419, +32, 213, 47, 799, 8, 1091, -43, 956, +-139, 513, -202, -67, -137, -617, -47, -898, +10, -807, 76, -486, 130, -49, 148, 358, +153, 567, 140, 515, 109, 263, 57, -68, +-30, -318, -163, -357, -277, -197, -308, 61, +-234, 335, -69, 493, 138, 434, 310, 143, +399, -252, 316, -569, 83, -694, -164, -618, +-347, -357, -418, 58, -291, 476, -24, 712, +230, 742, 389, 607, 420, 317, 285, -95, +36, -430, -201, -552, -356, -553, -433, -498, +-388, -300, -237, -63, -52, 30, 165, 122, +387, 333, 509, 450, 507, 449, 378, 449, +176, 379, -50, 142, -321, -148, -606, -402, +-757, -598, -713, -687, -461, -627, -6, -378, +518, 23, 877, 405, 965, 662, 787, 744, +378, 627, -142, 318, -594, -37, -843, -276, +-806, -388, -546, -413, -155, -323, 265, -173, +493, -107, 392, -147, 162, -164, 0, -120, +-67, 0, -2, 213, 239, 499, 475, 718, +497, 728, 244, 485, -187, 51, -640, -466, +-975, -923, -1050, -1153, -735, -997, -92, -497, +641, 155, 1191, 761, 1369, 1167, 1081, 1186, +411, 806, -373, 241, -962, -352, -1157, -852, +-935, -1051, -477, -863, 60, -425, 496, 55, +619, 465, 447, 682, 186, 630, -61, 361, +-211, 33, -151, -194, 112, -252, 366, -186, +434, -109, 276, -62, -74, -47, -481, -107, +-775, -163, -844, -120, -562, 8, 1, 171, +557, 359, 912, 484, 981, 415, 711, 143, +180, -213, -414, -548, -824, -797, -878, -821, +-600, -486, -164, 90, 313, 687, 674, 1128, +701, 1237, 387, 906, -44, 215, -447, -599, +-653, -1239, -528, -1483, -177, -1242, 206, -592, +521, 229, 638, 930, 499, 1346, 205, 1345, +-135, 917, -441, 260, -593, -401, -536, -877, +-299, -1041, 23, -907, 287, -530, 366, -54, +290, 288, 151, 424, 33, 469, -6, 389, +11, 216, 17, 113, 44, 93, 80, 101, +39, 124, -91, 90, -232, -61, -342, -314, +-365, -564, -278, -683, -103, -593, 159, -309, +431, 132, 544, 593, 493, 907, 374, 956, +206, 709, -37, 260, -313, -253, -518, -730, +-618, -966, -642, -862, -497, -536, -161, -103, +224, 347, 545, 588, 789, 576, 861, 446, +651, 245, 247, 18, -174, -118, -572, -132, +-827, -87, -783, -62, -517, -78, -237, -146, +1, -248, 269, -356, 534, -385, 653, -225, +590, 118, 408, 472, 180, 708, -67, 803, +-325, 656, -496, 175, -539, -444, -554, -933, +-493, -1144, -258, -1001, 119, -496, 518, 247, +802, 971, 863, 1376, 666, 1290, 216, 757, +-321, -48, -729, -878, -936, -1420, -914, -1447, +-570, -962, 4, -191, 555, 641, 908, 1273, +962, 1419, 687, 1064, 218, 453, -285, -241, +-636, -857, -704, -1160, -579, -1065, -389, -688, +-130, -167, 123, 336, 293, 681, 382, 772, +409, 630, 389, 398, 364, 166, 271, -42, +70, -166, -190, -250, -449, -369, -671, -481, +-761, -505, -612, -443, -215, -244, 264, 64, +653, 380, 923, 634, 969, 728, 666, 614, +164, 365, -335, 36, -752, -320, -964, -601, +-834, -696, -438, -602, -15, -395, 269, -136, +451, 162, 541, 398, 487, 445, 331, 371, +207, 314, 121, 267, -7, 185, -150, 80, +-256, -23, -386, -176, -505, -395, -494, -573, +-356, -598, -120, -464, 214, -200, 541, 140, +724, 470, 728, 703, 542, 784, 131, 698, +-348, 442, -665, -3, -773, -486, -663, -827, +-319, -977, 86, -890, 384, -506, 526, 68, +486, 613, 311, 958, 106, 1015, -94, 754, +-236, 227, -246, -372, -169, -765, -106, -858, +-37, -664, 64, -215, 108, 279, 64, 586, +23, 631, 41, 394, 66, -18, 11, -377, +-83, -547, -128, -495, -135, -196, -132, 206, +-42, 512, 131, 626, 266, 494, 308, 162, +319, -199, 216, -479, -82, -598, -426, -499, +-600, -243, -563, 27, -371, 261, -42, 422, +384, 427, 709, 269, 735, 93, 472, -21, +98, -109, -238, -167, -509, -147, -638, -94, +-464, -83, -82, -106, 201, -84, 270, -31, +257, -4, 164, 30, -43, 84, -207, 68, +-176, 7, -1, 25, 224, 111, 373, 212, +409, 301, 302, 278, -34, 105, -472, -197, +-736, -541, -749, -757, -531, -716, -80, -424, +485, 75, 900, 628, 963, 1001, 695, 1080, +242, 832, -302, 261, -785, -423, -956, -969, +-720, -1207, -284, -1038, 165, -513, 546, 139, +706, 690, 545, 957, 165, 852, -213, 475, +-395, 21, -400, -339, -244, -484, 101, -400, +413, -153, 460, 100, 305, 180, -11, 42, +-448, -166, -745, -317, -701, -353, -381, -179, +101, 176, 622, 500, 970, 640, 990, 547, +664, 254, 58, -110, -610, -394, -1096, -551, +-1244, -552, -962, -413, -303, -209, 447, 32, +991, 271, 1214, 438, 1085, 546, 564, 553, +-166, 382, -763, 66, -1042, -327, -952, -700, +-546, -831, -35, -613, 403, -169, 632, 365, +575, 789, 340, 865, 100, 579, -75, 71, +-147, -445, -123, -728, -64, -677, -18, -387, +-9, 20, -108, 373, -247, 503, -293, 408, +-243, 184, -88, -57, 169, -186, 387, -182, +494, -94, 452, 17, 275, 83, 67, 42, +-168, -85, -436, -217, -599, -279, -596, -238, +-474, -95, -187, 130, 300, 388, 713, 564, +802, 595, 662, 456, 379, 134, -65, -318, +-505, -740, -763, -994, -770, -1011, -553, -693, +-161, -33, 298, 715, 647, 1270, 732, 1466, +564, 1202, 250, 500, -104, -392, -420, -1152, +-561, -1527, -502, -1421, -368, -905, -161, -137, +153, 640, 457, 1136, 616, 1256, 560, 1059, +326, 592, -1, 0, -368, -461, -659, -717, +-708, -839, -504, -834, -175, -639, 193, -280, +575, 121, 800, 498, 721, 857, 410, 1040, +14, 841, -389, 321, -698, -299, -772, -857, +-586, -1142, -291, -986, 31, -454, 379, 234, +658, 808, 722, 1023, 561, 832, 298, 347, +-25, -228, -406, -608, -668, -667, -718, -530, +-594, -283, -243, 20, 257, 247, 612, 348, +683, 384, 507, 351, 158, 230, -201, 39, +-373, -178, -343, -327, -203, -344, -14, -249, +115, -70, 107, 122, 41, 228, -28, 152, +-78, -67, -108, -232, -111, -195, 0, 5, +193, 311, 298, 623, 280, 694, 157, 353, +-74, -271, -317, -887, -416, -1177, -338, -979, +-142, -348, 106, 499, 272, 1170, 267, 1320, +227, 934, 204, 213, 108, -547, -54, -1012, +-202, -1011, -265, -641, -227, -93, -165, 391, +-51, 625, 155, 602, 275, 398, 168, 92, +-11, -214, -110, -444, -118, -520, 6, -385, +202, -48, 260, 353, 160, 616, -50, 629, +-340, 386, -501, -79, -403, -581, -174, -832, +125, -725, 422, -345, 546, 179, 502, 637, +423, 863, 183, 778, -294, 379, -693, -191, +-809, -671, -715, -877, -369, -744, 216, -310, +742, 277, 902, 764, 701, 895, 343, 611, +-22, 100, -325, -434, -509, -770, -584, -751, +-552, -445, -420, -27, -173, 324, 193, 456, +548, 438, 693, 414, 600, 365, 363, 260, +53, 98, -263, -216, -412, -607, -399, -826, +-431, -785, -478, -509, -376, -29, -148, 491, +179, 833, 569, 921, 859, 815, 888, 561, +624, 170, 78, -313, -584, -761, -1007, -1070, +-1039, -1129, -834, -858, -434, -300, 134, 392, +665, 987, 1032, 1251, 1158, 1140, 901, 737, +315, 122, -410, -502, -1025, -872, -1203, -963, +-877, -824, -370, -464, 120, -46, 533, 237, +664, 419, 531, 541, 440, 520, 392, 377, +202, 245, -96, 121, -383, -57, -583, -252, +-619, -384, -469, -423, -169, -384, 146, -275, +332, -105, 384, 92, 416, 262, 460, 356, +388, 381, 102, 350, -245, 232, -490, 24, +-616, -184, -560, -359, -282, -458, 52, -369, +319, -127, 532, 93, 593, 260, 409, 364, +118, 332, -171, 193, -423, 32, -537, -148, +-439, -319, -162, -422, 155, -379, 351, -146, +390, 211, 272, 537, 36, 678, -174, 517, +-211, 99, -117, -382, -43, -726, -11, -802, +57, -560, 114, -93, 94, 427, 49, 771, +11, 792, -99, 527, -247, 81, -264, -391, +-128, -691, 64, -707, 293, -410, 432, 59, +363, 433, 179, 589, -43, 521, -293, 197, +-490, -221, -553, -481, -414, -531, -83, -357, +293, -18, 566, 248, 674, 393, 509, 462, +78, 351, -317, 99, -456, -127, -418, -296, +-254, -357, -57, -296, 33, -210, 65, -81, +92, 78, 75, 134, 72, 116, 101, 122, +129, 184, 171, 296, 208, 340, 134, 201, +-76, -48, -317, -322, -450, -533, -397, -550, +-167, -374, 141, -83, 380, 227, 404, 379, +258, 399, 94, 404, -60, 300, -206, 78, +-274, -71, -235, -178, -76, -334, 143, -374, +302, -209, 321, -29, 166, 58, -127, 79, +-397, 40, -472, -45, -293, -52, -8, 90, +234, 306, 409, 467, 464, 452, 343, 186, +131, -257, -72, -685, -246, -857, -401, -651, +-484, -158, -401, 415, -106, 828, 226, 855, +386, 489, 444, -33, 418, -452, 156, -626, +-151, -530, -298, -242, -350, 119, -244, 352, +12, 361, 187, 260, 254, 115, 252, -108, +63, -277, -235, -299, -393, -234, -370, -65, +-187, 189, 167, 352, 492, 346, 591, 178, +443, -101, 63, -330, -329, -411, -528, -339, +-525, -53, -297, 321, 30, 492, 216, 421, +287, 224, 282, -76, 165, -388, 41, -556, +-49, -498, -156, -260, -158, 33, -54, 332, +-13, 586, 35, 642, 128, 472, 68, 165, +-47, -233, -65, -601, -99, -721, -113, -562, +-45, -240, -12, 128, 29, 409, 98, 504, +115, 403, 110, 179, 88, 0, -26, -52, +-135, -66, -133, -84, -81, -69, -6, -39, +145, -61, 211, -154, 31, -232, -253, -240, +-410, -211, -364, -131, -97, 96, 334, 415, +671, 642, 648, 665, 291, 461, -198, 55, +-552, -437, -576, -822, -379, -886, -141, -604, +81, -142, 163, 309, 168, 598, 282, 621, +366, 407, 240, 106, 23, -98, -160, -135, +-264, -79, -232, -11, -83, 29, 46, -34, +65, -177, -6, -292, -59, -361, -38, -337, +-21, -119, -13, 192, 63, 442, 142, 591, +227, 568, 317, 339, 204, -3, -117, -353, +-409, -558, -563, -549, -460, -420, -78, -186, +351, 143, 576, 389, 507, 469, 234, 368, +-28, 91, -197, -184, -341, -326, -408, -346, +-319, -101, -172, 331, 45, 534, 359, 413, +543, 103, 484, -374, 239, -776, -155, -784, +-474, -402, -527, 174, -378, 697, -108, 901, +206, 691, 393, 173, 371, -354, 177, -590, +-93, -561, -281, -385, -239, -62, -55, 220, +107, 291, 200, 270, 196, 241, 100, 165, +-27, 13, -158, -233, -223, -412, -220, -345, +-233, -139, -236, 95, -125, 338, 133, 412, +404, 276, 544, 113, 573, -24, 456, -119, +101, -126, -404, -171, -832, -318, -1023, -426, +-848, -377, -338, -135, 255, 248, 752, 581, +1073, 722, 997, 628, 568, 322, 116, -84, +-332, -415, -780, -569, -991, -591, -897, -568, +-554, -467, -9, -210, 527, 180, 846, 593, +843, 888, 523, 921, 99, 635, -245, 72, +-484, -550, -528, -898, -285, -828, 50, -475, +247, -77, 249, 168, 89, 242, -152, 238, +-380, 219, -445, 230, -139, 287, 350, 326, +633, 275, 650, 82, 455, -204, 87, -431, +-308, -542, -638, -586, -797, -509, -614, -210, +-159, 276, 362, 735, 800, 932, 881, 824, +467, 438, -139, -222, -562, -861, -681, -1072, +-453, -820, 14, -309, 403, 282, 482, 725, +334, 832, 142, 585, -40, 152, -219, -217, +-330, -424, -367, -494, -293, -388, -47, -162, +234, 19, 431, 170, 506, 333, 335, 354, +8, 170, -237, -81, -370, -244, -348, -225, +-152, -19, 23, 259, 134, 396, 202, 204, +81, -255, -161, -690, -224, -817, -77, -509, +164, 156, 388, 893, 395, 1302, 131, 1087, +-176, 322, -371, -577, -410, -1210, -316, -1355, +-162, -926, 47, -117, 241, 658, 331, 1071, +348, 981, 230, 520, -76, -1, -355, -389, +-375, -569, -165, -498, 120, -260, 339, -24, +305, 155, -26, 266, -378, 230, -513, 75, +-383, -100, -51, -254, 311, -292, 560, -100, +651, 243, 467, 487, 42, 508, -412, 302, +-758, -118, -854, -573, -569, -792, -40, -657, +446, -207, 725, 384, 737, 833, 510, 885, +194, 505, -147, -98, -464, -634, -647, -879, +-622, -723, -351, -206, 68, 417, 347, 799, +392, 789, 267, 475, 115, -15, 97, -540, +196, -864, 244, -815, 100, -431, -250, 151, +-550, 704, -512, 952, -181, 781, 170, 300, +349, -289, 309, -756, 126, -887, -11, -594, +29, -24, 111, 463, 63, 649, -92, 550, +-204, 181, -156, -284, 26, -523, 203, -441, +256, -95, 166, 363, -25, 602, -274, 468, +-394, 81, -298, -402, -117, -722, 137, -665, +433, -316, 574, 173, 505, 608, 257, 751, +-131, 607, -458, 276, -535, -180, -428, -566, +-267, -728, -66, -661, 135, -317, 272, 217, +334, 684, 302, 885, 178, 644, 22, 37, +-68, -565, -14, -925, 125, -880, 120, -312, +-128, 508, -488, 1082, -701, 1111, -555, 548, +-118, -338, 329, -1077, 609, -1351, 693, -978, +606, -47, 365, 918, 11, 1453, -380, 1355, +-716, 595, -878, -475, -721, -1287, -239, -1508, +316, -1078, 643, -142, 656, 866, 422, 1424, +132, 1297, -49, 614, -161, -272, -297, -995, +-356, -1284, -254, -995, -47, -254, 129, 549, +111, 1039, -123, 1077, -351, 678, -312, -57, +20, -801, 447, -1133, 783, -931, 792, -307, +311, 529, -378, 1185, -847, 1274, -960, 720, +-785, -215, -378, -1120, 187, -1601, 701, -1371, +1002, -449, 970, 767, 566, 1703, -72, 1946, +-680, 1346, -981, 95, -824, -1223, -370, -2044, +168, -2034, 603, -1125, 702, 252, 458, 1487, +87, 2107, -280, 1783, -526, 670, -456, -613, +-44, -1560, 430, -1838, 688, -1253, 613, -131, +189, 958, -370, 1619, -759, 1502, -819, 639, +-536, -450, -50, -1344, 498, -1712, 903, -1255, +992, -171, 733, 999, 136, 1820, -574, 1886, +-1042, 1049, -1092, -279, -613, -1492, 169, -2099, +757, -1795, 967, -686, 808, 705, 318, 1751, +-195, 1987, -498, 1337, -690, 168, -702, -1003, +-387, -1690, 74, -1590, 535, -780, 847, 373, +736, 1320, 270, 1576, -274, 1068, -704, 136, +-696, -838, -301, -1484, 60, -1421, 265, -674, +305, 329, 153, 1192, -24, 1553, -112, 1166, +-87, 249, 41, -698, 142, -1335, 144, -1343, +108, -643, 8, 296, -166, 998, -295, 1206, +-377, 742, -378, -124, -164, -841, 137, -1146, +404, -889, 561, -61, 440, 800, 60, 1258, +-338, 1267, -583, 685, -541, -329, -207, -1235, +178, -1646, 385, -1365, 375, -481, 139, 577, +-185, 1394, -375, 1681, -369, 1227, -220, 283, +4, -647, 240, -1281, 415, -1371, 452, -868, +344, -82, 77, 702, -312, 1182, -623, 1053, +-709, 359, -601, -485, -258, -1070, 335, -1129, +900, -571, 1075, 354, 802, 1173, 197, 1483, +-529, 1040, -1060, -11, -1128, -1084, -663, -1689, +104, -1607, 707, -737, 931, 554, 804, 1513, +381, 1763, -124, 1327, -466, 282, -587, -905, +-550, -1559, -289, -1473, 204, -804, 573, 134, +612, 953, 410, 1377, 4, 1201, -460, 498, +-667, -389, -442, -1121, 51, -1399, 477, -1045, +685, -217, 609, 695, 309, 1380, -91, 1490, +-514, 821, -794, -233, -707, -1132, -282, -1520, +239, -1189, 711, -305, 985, 688, 762, 1399, +149, 1481, -444, 699, -830, -502, -822, -1324, +-367, -1529, 215, -1114, 677, -27, 767, 1243, +380, 1912, -178, 1669, -676, 635, -859, -768, +-428, -1802, 253, -2022, 689, -1489, 820, -339, +578, 1065, 30, 1982, -414, 1952, -686, 1151, +-798, -16, -500, -1078, -70, -1633, 216, -1520, +567, -792, 710, 239, 431, 1082, 10, 1341, +-473, 953, -760, 144, -486, -699, 76, -1163, +520, -1055, 695, -368, 430, 616, -190, 1329, +-755, 1399, -1056, 752, -920, -368, -251, -1358, +607, -1724, 1226, -1372, 1365, -334, 909, 1005, +59, 1797, -857, 1699, -1531, 891, -1578, -388, +-884, -1470, 152, -1711, 1064, -1102, 1522, 27, +1309, 1129, 484, 1580, -544, 1199, -1281, 204, +-1372, -959, -757, -1560, 202, -1359, 973, -620, +1237, 476, 890, 1411, 139, 1636, -607, 1150, +-1011, 189, -958, -824, -489, -1429, 172, -1460, +667, -855, 873, 212, 786, 1058, 315, 1275, +-343, 914, -782, 39, -729, -856, -205, -1194, +491, -866, 931, 75, 776, 1132, 129, 1590, +-619, 1255, -1114, 185, -1048, -1246, -454, -2176, +380, -2123, 1128, -1114, 1435, 574, 1192, 2103, +592, 2706, -253, 2220, -1199, 777, -1746, -1050, +-1448, -2437, -473, -2833, 695, -1994, 1560, -239, +1686, 1534, 1048, 2635, -20, 2581, -1069, 1250, +-1511, -610, -1163, -2183, -351, -2792, 621, -1933, +1361, -142, 1496, 1653, 993, 2770, -24, 2599, +-1154, 1170, -1805, -724, -1673, -2349, -870, -3068, +342, -2395, 1444, -749, 1890, 1112, 1619, 2632, +757, 3098, -360, 2267, -1198, 560, -1649, -1355, +-1507, -2643, -661, -2769, 185, -1740, 687, -42, +1035, 1459, 965, 2104, 431, 1785, -61, 717, +-340, -542, -464, -1224, -413, -1077, -347, -376, +-230, 413, 20, 778, 154, 534, 161, -108, +136, -797, -59, -1051, -153, -626, 41, 178, +142, 993, 74, 1478, -24, 1262, -282, 455, +-515, -572, -439, -1534, -69, -2021, 475, -1622, +889, -406, 850, 1061, 355, 2203, -343, 2537, +-954, 1783, -1238, 172, -1045, -1618, -428, -2723, +420, -2634, 1111, -1430, 1311, 285, 1034, 1736, +470, 2442, -198, 2128, -801, 924, -1129, -487, +-1025, -1448, -570, -1725, 84, -1317, 681, -312, +944, 765, 799, 1258, 303, 995, -318, 198, +-628, -754, -431, -1384, -17, -1219, 338, -258, +530, 1010, 401, 1991, 63, 2129, -212, 1267, +-419, -318, -597, -1988, -567, -2906, -226, -2588, +331, -1206, 914, 672, 1173, 2379, 855, 3151, +129, 2585, -694, 1017, -1247, -870, -1132, -2311, +-400, -2792, 413, -2190, 976, -705, 1180, 1037, +916, 2238, 262, 2417, -577, 1565, -1271, 11, +-1408, -1563, -883, -2346, 112, -1971, 1124, -674, +1636, 885, 1413, 1989, 621, 2212, -338, 1507, +-1034, 125, -1268, -1319, -1140, -2117, -687, -2055, +-15, -1276, 504, -18, 880, 1300, 1053, 2151, +649, 2114, -29, 1178, -444, -252, -537, -1546, +-279, -2198, 109, -1878, 205, -610, 89, 862, +-140, 1828, -566, 2001, -746, 1257, -472, -108, +-139, -1392, 234, -1940, 676, -1647, 884, -730, +874, 484, 598, 1448, -81, 1800, -720, 1458, +-1006, 628, -1043, -321, -724, -1150, -211, -1575, +222, -1390, 569, -733, 646, 56, 416, 771, +138, 1162, -96, 986, -187, 511, -37, 33, +210, -356, 366, -374, 303, -91, -152, 89, +-789, 109, -1112, -88, -991, -559, -508, -884, +198, -846, 883, -478, 1370, 316, 1454, 1206, +1057, 1681, 274, 1623, -693, 913, -1481, -413, +-1784, -1624, -1447, -2129, -433, -1938, 778, -979, +1509, 491, 1646, 1736, 1204, 2173, 251, 1652, +-642, 557, -1141, -628, -1247, -1546, -847, -1804, +-106, -1199, 655, -85, 1262, 863, 1345, 1426, +724, 1462, -115, 746, -830, -338, -1323, -1149, +-1168, -1440, -420, -1168, 354, -351, 915, 600, +1125, 1184, 845, 1295, 327, 876, -121, 100, +-437, -589, -576, -926, -482, -843, -223, -446, +101, 47, 278, 415, 231, 483, 93, 197, +-138, -198, -359, -366, -266, -290, 95, 25, +456, 528, 766, 899, 811, 826, 326, 322, +-331, -390, -802, -1104, -1033, -1429, -860, -1130, +-353, -456, 176, 407, 619, 1241, 820, 1586, +643, 1263, 326, 550, 49, -280, -255, -945, +-399, -1190, -308, -1037, -228, -515, -214, 139, +-234, 485, -291, 517, -188, 371, 133, 87, +368, -92, 414, 1, 388, 225, 179, 515, +-157, 643, -384, 268, -462, -407, -375, -1005, +-111, -1274, 154, -1068, 272, -444, 287, 498, +199, 1316, -65, 1517, -402, 1180, -610, 574, +-448, -256, 12, -1019, 398, -1324, 581, -1237, +581, -725, 364, 87, 30, 683, -320, 996, +-653, 954, -816, 511, -659, 2, -260, -449, +253, -666, 765, -421, 1043, -88, 829, 29, +183, 195, -494, 285, -854, 86, -772, -35, +-385, -53, 13, -63, 334, 39, 518, 52, +485, -30, 320, -136, 106, -346, -165, -293, +-374, 93, -410, 342, -314, 570, -14, 824, +385, 580, 498, -77, 400, -716, 207, -1153, +-89, -1246, -202, -955, -165, -235, -204, 819, +-144, 1614, -36, 1741, -81, 1378, -41, 498, +181, -775, 369, -1688, 494, -1929, 442, -1570, +132, -678, -194, 464, -357, 1403, -372, 1742, +-309, 1539, -217, 904, -43, -99, 150, -1032, +227, -1543, 292, -1524, 360, -945, 255, -46, +116, 764, -3, 1343, -182, 1520, -204, 1022, +-155, 163, -218, -674, -243, -1307, -214, -1435, +-115, -1144, 55, -521, 162, 426, 272, 1219, +451, 1552, 437, 1548, 209, 1044, 10, 18, +-246, -1054, -591, -1881, -768, -2147, -642, -1557, +-236, -389, 184, 1002, 468, 2136, 704, 2417, +669, 1818, 281, 660, -69, -809, -358, -2038, +-647, -2466, -603, -2066, -294, -932, -56, 616, +135, 1942, 247, 2607, 235, 2299, 145, 1058, +0, -586, -52, -2018, 11, -2722, 31, -2394, +23, -1148, -24, 544, -200, 2072, -373, 2770, +-406, 2413, -264, 1275, 130, -354, 543, -1895, +720, -2648, 668, -2366, 264, -1332, -407, 10, +-960, 1326, -1177, 2203, -906, 2249, -220, 1474, +556, 322, 1234, -822, 1610, -1684, 1354, -1870, +576, -1366, -435, -396, -1499, 640, -2076, 1216, +-1840, 1248, -1025, 820, 215, 43, 1530, -657, +2326, -881, 2320, -635, 1609, -104, 385, 565, +-1003, 973, -2026, 822, -2406, 189, -2202, -656, +-1308, -1253, 244, -1352, 1752, -884, 2585, 107, +2650, 1176, 1881, 1813, 498, 1728, -947, 921, +-2088, -258, -2571, -1363, -2147, -2098, -1121, -2058, +147, -1075, 1430, 274, 2288, 1406, 2424, 2144, +1801, 2169, 468, 1339, -987, 95, -1965, -1173, +-2278, -2140, -1748, -2312, -607, -1705, 643, -567, +1639, 877, 1908, 1989, 1349, 2295, 391, 1850, +-556, 772, -1206, -576, -1294, -1446, -825, -1643, +-9, -1419, 793, -732, 1044, 43, 715, 484, +157, 679, -674, 622, -1411, 401, -1314, 221, +-498, 154, 556, 254, 1647, 425, 2196, 434, +1644, 198, 273, -194, -1273, -805, -2480, -1414, +-2828, -1579, -2055, -1192, -488, -267, 1283, 891, +2647, 1850, 3003, 2389, 2308, 2149, 903, 1028, +-911, -452, -2456, -1734, -2944, -2472, -2330, -2352, +-1079, -1476, 382, -247, 1605, 1032, 2102, 1879, +1815, 1940, 967, 1369, -113, 465, -911, -457, +-1188, -1062, -989, -1152, -390, -727, 278, 6, +576, 525, 356, 577, -113, 288, -518, -293, +-647, -792, -433, -819, 24, -484, 570, 96, +979, 786, 1094, 1155, 894, 1022, 285, 639, +-580, 114, -1205, -410, -1378, -728, -1158, -868, +-440, -800, 466, -600, 981, -377, 1091, -70, +956, 213, 563, 443, 88, 791, -348, 1075, +-706, 951, -737, 590, -427, 100, -69, -617, +312, -1193, 557, -1372, 390, -1132, 105, -442, +-49, 414, -226, 1040, -351, 1228, -315, 959, +-233, 289, -28, -505, 443, -1030, 864, -1016, +962, -376, 676, 542, -9, 1256, -732, 1435, +-1139, 907, -1197, -185, -866, -1454, -245, -2248, +418, -2094, 957, -1081, 1279, 399, 1220, 1816, +769, 2660, 53, 2613, -786, 1656, -1315, 65, +-1209, -1579, -702, -2576, -61, -2650, 539, -1922, +831, -609, 729, 886, 404, 1961, -16, 2217, +-406, 1697, -615, 751, -523, -258, -167, -1087, +256, -1434, 562, -1198, 620, -633, 395, 33, +4, 590, -394, 794, -644, 583, -715, 247, +-634, -31, -445, -273, -142, -349, 317, -309, +736, -249, 923, -145, 937, -8, 750, 247, +310, 570, -356, 787, -1010, 737, -1462, 316, +-1671, -391, -1314, -1110, -291, -1475, 856, -1377, +1702, -789, 2120, 235, 1850, 1303, 822, 2014, +-451, 2085, -1542, 1431, -2173, 276, -1992, -1047, +-1141, -2143, -10, -2595, 1171, -2192, 1882, -1080, +1727, 445, 987, 1929, 32, 2763, -838, 2683, +-1215, 1783, -1022, 327, -453, -1234, 160, -2368, +539, -2721, 585, -2277, 269, -1264, -242, 62, +-516, 1421, -335, 2347, 130, 2613, 628, 2258, +919, 1214, 800, -285, 325, -1645, -391, -2480, +-1082, -2742, -1325, -2322, -1118, -1161, -571, 336, +336, 1705, 1262, 2733, 1822, 3211, 1756, 2761, +972, 1301, -165, -600, -1153, -2412, -1764, -3714, +-1794, -3865, -1143, -2627, -235, -501, 534, 1773, +1134, 3537, 1462, 4120, 1413, 3238, 988, 1315, +358, -873, -266, -2636, -834, -3515, -1224, -3191, +-1279, -1798, -1125, 21, -799, 1565, -130, 2414, +695, 2489, 1401, 1802, 1838, 620, 1634, -553, +800, -1335, -204, -1556, -1201, -1344, -1981, -827, +-2033, -170, -1351, 302, -264, 576, 986, 784, +1905, 838, 2089, 683, 1533, 496, 333, 253, +-1054, -177, -2008, -625, -2158, -1014, -1406, -1229, +-89, -986, 1213, -411, 2045, 313, 2093, 1185, +1296, 1789, -105, 1686, -1558, 1022, -2452, 24, +-2325, -1109, -1237, -1941, 260, -2075, 1660, -1463, +2484, -479, 2325, 540, 1200, 1491, -343, 1987, +-1518, 1672, -2098, 943, -2122, 270, -1368, -467, +16, -1123, 1231, -1352, 1748, -1247, 1664, -997, +1072, -690, 16, -273, -988, 280, -1328, 862, +-1059, 1383, -464, 1693, 326, 1665, 857, 1185, +767, 211, 325, -1101, -116, -2279, -541, -2738, +-750, -2398, -480, -1361, 18, 295, 486, 2011, +806, 3035, 729, 3033, 378, 2204, 2, 736, +-418, -1117, -725, -2555, -673, -3008, -344, -2611, +3, -1557, 307, 32, 465, 1672, 362, 2631, +246, 2517, 171, 1658, 31, 588, 17, -618, +114, -1700, 64, -1984, -124, -1520, -303, -934, +-413, -295, -337, 461, -152, 982, 3, 1222, +323, 1314, 648, 1165, 603, 791, 392, 129, +201, -768, -171, -1534, -576, -2009, -744, -2032, +-667, -1318, -316, -17, 165, 1427, 560, 2635, +824, 3073, 767, 2473, 410, 1122, 4, -772, +-421, -2697, -818, -3718, -916, -3499, -699, -2281, +-328, -270, 186, 2036, 779, 3666, 1203, 3959, +1230, 2968, 753, 1162, -23, -913, -833, -2672, +-1454, -3381, -1608, -2843, -1225, -1603, -456, -166, +504, 1145, 1342, 1921, 1823, 1889, 1747, 1338, +1048, 762, -63, 248, -1230, -216, -2107, -434, +-2264, -420, -1493, -542, -171, -873, 1148, -1090, +1984, -1013, 2032, -676, 1405, -136, 265, 630, +-1006, 1422, -1779, 1812, -1791, 1667, -1219, 1037, +-241, 38, 843, -1003, 1594, -1725, 1736, -1914, +1104, -1518, -79, -675, -1103, 239, -1554, 974, +-1536, 1403, -1044, 1304, -69, 852, 895, 479, +1458, 143, 1619, -255, 1328, -531, 620, -704, +-278, -855, -1122, -945, -1683, -948, -1817, -641, +-1447, 56, -580, 814, 551, 1398, 1546, 1779, +2129, 1692, 2195, 928, 1568, -183, 287, -1360, +-1085, -2320, -2005, -2546, -2290, -1902, -1946, -587, +-1019, 1030, 208, 2381, 1331, 2990, 2058, 2561, +2086, 1195, 1470, -547, 556, -1983, -456, -2685, +-1336, -2547, -1708, -1637, -1433, -242, -776, 1121, +26, 1960, 710, 2109, 999, 1657, 866, 739, +515, -367, 152, -1231, -68, -1438, -59, -1004, +59, -367, 113, 188, -16, 544, -406, 462, +-787, -97, -858, -629, -598, -692, -141, -354, +441, 270, 1078, 1058, 1480, 1669, 1308, 1734, +655, 1070, -250, -155, -1253, -1454, -1958, -2471, +-1925, -2935, -1157, -2396, 29, -876, 1197, 969, +1923, 2592, 1960, 3563, 1337, 3432, 369, 2199, +-563, 341, -1361, -1648, -1761, -3189, -1513, -3729, +-832, -3173, -33, -1766, 668, 42, 991, 1797, +825, 3126, 473, 3466, 225, 2664, 207, 1266, +399, -310, 481, -1797, 250, -2619, -315, -2464, +-1055, -1653, -1620, -600, -1752, 409, -1406, 1063, +-545, 1224, 838, 1100, 2238, 831, 2931, 427, +2701, 156, 1619, 99, -228, 61, -2237, -36, +-3445, -246, -3451, -498, -2402, -712, -606, -981, +1351, -1133, 2813, -851, 3384, -188, 2838, 592, +1333, 1380, -439, 1940, -1882, 1966, -2608, 1440, +-2338, 401, -1340, -902, -202, -1950, 774, -2458, +1361, -2303, 1441, -1550, 1136, -467, 508, 844, +-177, 2064, -565, 2600, -637, 2459, -465, 1832, +-54, 611, 313, -841, 305, -1893, 103, -2424, +-93, -2413, -309, -1753, -419, -783, -373, 130, +-309, 1089, -199, 1992, 277, 2474, 960, 2386, +1357, 1783, 1335, 725, 893, -754, -22, -2225, +-1164, -2983, -2070, -2986, -2405, -2449, -1982, -1165, +-779, 596, 910, 2081, 2590, 3167, 3585, 3671, +3383, 3031, 1897, 1475, -446, -342, -2740, -2178, +-4070, -3646, -4082, -4031, -2733, -3152, -396, -1529, +2026, 353, 3726, 2113, 4249, 3306, 3385, 3608, +1455, 2963, -877, 1666, -2889, 139, -3824, -1403, +-3419, -2693, -2068, -3307, -177, -3109, 1617, -2253, +2611, -817, 2677, 913, 2030, 2334, 842, 3128, +-440, 3226, -1239, 2427, -1413, 941, -1151, -650, +-839, -2046, -676, -2943, -527, -2964, -303, -2118, +106, -717, 719, 782, 1360, 1938, 1695, 2422, +1397, 2126, 546, 1225, -530, 49, -1519, -982, +-2131, -1549, -2043, -1505, -1183, -897, 96, -112, +1356, 633, 2259, 1189, 2393, 1082, 1535, 370, +24, -298, -1458, -821, -2382, -1250, -2512, -1215, +-1747, -571, -321, 293, 1195, 987, 2378, 1544, +2834, 1931, 2226, 1684, 815, 766, -764, -333, +-2154, -1438, -3004, -2439, -2877, -2802, -1776, -2311, +-172, -1224, 1426, 323, 2742, 1965, 3383, 3169, +2942, 3666, 1581, 3114, -99, 1575, -1759, -313, +-3078, -2198, -3480, -3724, -2936, -4234, -1717, -3547, +72, -1947, 1972, 216, 3368, 2417, 3826, 4035, +3281, 4541, 1800, 3736, -325, 1935, -2293, -373, +-3354, -2568, -3478, -3908, -2838, -4092, -1428, -3244, +402, -1562, 1881, 465, 2682, 2182, 2951, 3210, +2599, 3390, 1423, 2648, -3, 1193, -997, -505, +-1704, -1914, -2267, -2653, -2268, -2650, -1748, -1939, +-996, -650, -13, 715, 1070, 1714, 1969, 2164, +2508, 1899, 2498, 1065, 1849, -20, 711, -1091, +-675, -1711, -2052, -1720, -3052, -1258, -3256, -397, +-2460, 580, -990, 1310, 786, 1648, 2596, 1522, +3755, 958, 3653, 120, 2542, -768, 843, -1476, +-1336, -1837, -3305, -1793, -4271, -1285, -3999, -334, +-2479, 731, -143, 1624, 2221, 2244, 3918, 2276, +4448, 1607, 3633, 564, 1723, -584, -738, -1627, +-2996, -2319, -4203, -2468, -4109, -1986, -2929, -1044, +-906, 101, 1373, 1185, 3032, 1999, 3638, 2446, +3246, 2298, 2028, 1610, 247, 783, -1460, -189, +-2458, -1299, -2706, -2157, -2311, -2644, -1358, -2688, +-236, -1992, 700, -696, 1317, 742, 1582, 2132, +1547, 3183, 1263, 3330, 746, 2519, 168, 1197, +-336, -374, -809, -1921, -1165, -2904, -1359, -3055, +-1416, -2531, -1181, -1456, -493, 0, 380, 1349, +1221, 2207, 1899, 2563, 2076, 2369, 1637, 1557, +705, 431, -506, -580, -1557, -1351, -2178, -1855, +-2192, -1880, -1508, -1448, -317, -914, 891, -265, +1824, 694, 2241, 1536, 1905, 1821, 1030, 1671, +5, 1155, -1077, 243, -1920, -903, -2070, -1848, +-1530, -1987, -641, -1343, 486, -383, 1623, 853, +2217, 2068, 1985, 2393, 1245, 1576, 228, 129, +-975, -1427, -1948, -2600, -2222, -2808, -1885, -1870, +-1105, -165, 155, 1604, 1489, 2710, 2293, 2886, +2377, 2171, 1782, 733, 707, -803, -453, -1897, +-1436, -2392, -2013, -2174, -1927, -1396, -1395, -418, +-757, 429, -26, 916, 757, 1116, 1300, 1131, +1411, 1049, 1345, 1026, 1269, 986, 1050, 788, +555, 354, -157, -498, -1049, -1624, -2010, -2506, +-2624, -2832, -2595, -2461, -1873, -1194, -445, 705, +1406, 2567, 3035, 3880, 3828, 4134, 3650, 3036, +2471, 964, 365, -1443, -2040, -3454, -3883, -4414, +-4674, -4107, -4180, -2583, -2381, -330, 162, 1758, +2488, 3154, 4022, 3643, 4527, 3129, 3665, 1920, +1673, 425, -571, -1068, -2417, -2166, -3533, -2603, +-3622, -2472, -2680, -1905, -1204, -923, 255, 281, +1461, 1307, 2249, 1933, 2437, 2201, 2114, 2017, +1520, 1278, 599, 253, -497, -737, -1417, -1591, +-2024, -2082, -2294, -1900, -2014, -1207, -1171, -396, +-62, 486, 1107, 1274, 2095, 1586, 2497, 1441, +2201, 1057, 1362, 531, 136, 49, -1282, -275, +-2228, -543, -2314, -859, -1808, -1157, -988, -1293, +125, -1158, 1237, -730, 1745, -19, 1551, 954, +1182, 1835, 781, 2145, 208, 1961, -318, 1354, +-651, 193, -871, -1115, -952, -2116, -954, -2667, +-879, -2502, -576, -1566, -80, -195, 436, 1217, +931, 2315, 1374, 2751, 1698, 2416, 1622, 1506, +867, 266, -197, -935, -1161, -1714, -1946, -2049, +-2220, -1952, -1748, -1387, -907, -621, 67, 19, +1130, 498, 1823, 961, 1993, 1378, 1876, 1578, +1344, 1564, 368, 1274, -676, 590, -1413, -390, +-1783, -1419, -1815, -2119, -1505, -2218, -783, -1814, +120, -920, 861, 321, 1427, 1322, 1728, 1770, +1563, 1833, 1030, 1553, 294, 895, -511, 100, +-1143, -518, -1410, -903, -1343, -1192, -991, -1385, +-373, -1223, 330, -729, 771, -223, 830, 227, +683, 665, 364, 932, -76, 941, -329, 777, +-263, 566, -47, 349, 234, 50, 470, -286, +560, -479, 330, -622, -336, -787, -1117, -799, +-1564, -694, -1532, -602, -997, -384, -6, 82, +1198, 690, 2141, 1266, 2412, 1726, 1860, 1862, +815, 1345, -472, 197, -1777, -1136, -2578, -2267, +-2560, -2880, -1916, -2620, -789, -1446, 604, 163, +1743, 1730, 2383, 2977, 2536, 3374, 1998, 2628, +871, 1147, -425, -655, -1518, -2325, -2268, -3255, +-2504, -3189, -2067, -2097, -1075, -227, 135, 1568, +1330, 2536, 2262, 2682, 2581, 2144, 2195, 890, +1301, -539, 6, -1408, -1387, -1561, -2264, -1196, +-2386, -609, -2010, -20, -1208, 393, 45, 304, +1244, -154, 1853, -414, 1946, -318, 1653, 44, +1025, 731, 335, 1532, -295, 1911, -805, 1546, +-1116, 554, -1288, -812, -1397, -2172, -1320, -2990, +-956, -2885, -266, -1800, 682, -51, 1575, 1787, +2224, 3167, 2465, 3628, 1985, 2979, 910, 1442, +-447, -480, -1916, -2232, -2980, -3307, -3007, -3313, +-2181, -2247, -922, -588, 634, 995, 2058, 1960, +2785, 2158, 2656, 1678, 1817, 737, 561, -156, +-721, -570, -1637, -571, -1825, -285, -1311, 146, +-606, 310, -21, 110, 370, -277, 357, -886, +9, -1406, -302, -1385, -366, -893, -234, -80, +124, 938, 777, 1770, 1436, 2105, 1620, 1865, +1308, 1094, 588, 22, -503, -1044, -1691, -1826, +-2479, -2084, -2548, -1803, -1949, -1129, -895, -229, +420, 606, 1697, 1073, 2523, 1174, 2670, 1035, +2277, 769, 1335, 501, 12, 279, -1207, 179, +-2000, 134, -2378, -108, -2279, -497, -1647, -890, +-699, -1190, 212, -1253, 929, -1089, 1466, -635, +1792, 147, 1773, 856, 1397, 1244, 752, 1469, +6, 1502, -698, 1175, -1246, 610, -1533, -19, +-1422, -648, -973, -1150, -511, -1446, -155, -1573, +173, -1459, 421, -1061, 603, -436, 844, 339, +1086, 1111, 1133, 1779, 948, 2215, 683, 2138, +275, 1547, -420, 630, -1136, -460, -1547, -1526, +-1704, -2335, -1629, -2610, -1072, -2211, -27, -1303, +953, -167, 1541, 949, 1831, 1809, 1804, 2207, +1296, 2110, 591, 1645, 27, 994, -522, 280, +-1069, -439, -1414, -1057, -1524, -1502, -1436, -1750, +-1088, -1725, -419, -1460, 397, -994, 1119, -279, +1583, 613, 1725, 1479, 1541, 2175, 1039, 2550, +288, 2432, -469, 1697, -1002, 401, -1309, -1076, +-1339, -2349, -1015, -3213, -514, -3293, -150, -2425, +-15, -1045, 43, 508, 204, 2051, 511, 3056, +908, 3242, 1334, 2742, 1627, 1601, 1374, 10, +526, -1494, -462, -2506, -1349, -2908, -2127, -2566, +-2428, -1508, -1966, -208, -904, 928, 376, 1675, +1553, 1894, 2244, 1655, 2196, 1049, 1424, 269, +322, -338, -534, -712, -964, -924, -1025, -855, +-695, -504, -235, -180, 22, 1, -79, 111, +-395, 39, -676, -203, -802, -351, -696, -301, +-231, -66, 511, 368, 1269, 880, 1799, 1145, +1840, 930, 1292, 408, 440, -180, -512, -829, +-1525, -1300, -2184, -1317, -2119, -1018, -1687, -517, +-1103, 182, -143, 840, 915, 1213, 1596, 1236, +1945, 853, 2093, 191, 1840, -368, 1101, -717, +113, -846, -868, -570, -1741, -80, -2288, 201, +-2262, 246, -1718, 171, -892, -11, 144, -227, +1188, -366, 1829, -302, 1988, 47, 1855, 458, +1402, 692, 564, 765, -329, 620, -834, 165, +-1115, -375, -1401, -707, -1464, -780, -1196, -630, +-826, -303, -429, -11, 161, 128, 926, 189, +1564, 259, 1797, 397, 1648, 591, 1224, 687, +478, 634, -447, 438, -1228, -23, -1683, -653, +-1736, -1105, -1449, -1262, -883, -1138, -48, -651, +789, 200, 1251, 1119, 1433, 1761, 1386, 1908, +924, 1448, 295, 467, -149, -740, -533, -1750, +-842, -2208, -893, -1978, -770, -1087, -563, 152, +-233, 1302, 143, 2064, 485, 2215, 647, 1681, +552, 632, 334, -618, 86, -1669, -219, -2145, +-393, -1899, -337, -1152, -151, -192, 76, 800, +384, 1503, 671, 1637, 692, 1354, 355, 871, +-244, 255, -888, -356, -1298, -813, -1363, -1091, +-990, -1228, -210, -1209, 705, -927, 1401, -367, +1735, 322, 1646, 942, 1075, 1414, 187, 1603, +-717, 1330, -1428, 689, -1790, -114, -1706, -954, +-1164, -1606, -329, -1824, 455, -1559, 965, -878, +1209, 102, 1160, 1011, 860, 1497, 525, 1507, +221, 1092, -47, 423, -220, -170, -413, -517, +-728, -658, -979, -646, -1106, -559, -1067, -493, +-683, -447, -58, -388, 588, -194, 1283, 189, +1781, 578, 1702, 851, 1160, 985, 373, 825, +-633, 327, -1593, -331, -1998, -925, -1710, -1249, +-1021, -1137, -105, -580, 794, 283, 1304, 1112, +1369, 1507, 1117, 1252, 585, 423, -67, -637, +-577, -1494, -839, -1793, -773, -1329, -396, -215, +82, 1048, 426, 1902, 487, 2095, 322, 1550, +57, 419, -265, -812, -454, -1716, -372, -2073, +-183, -1734, -48, -811, 132, 281, 319, 1098, +407, 1437, 447, 1298, 479, 835, 396, 303, +175, -106, -153, -313, -471, -270, -668, -150, +-752, -193, -705, -344, -396, -516, 95, -698, +522, -700, 763, -431, 835, -19, 697, 504, +389, 1045, 46, 1279, -215, 1148, -428, 793, +-537, 228, -472, -432, -333, -997, -218, -1318, +-98, -1236, 5, -874, 73, -446, 150, 54, +203, 536, 263, 801, 380, 889, 367, 915, +238, 842, 147, 581, 31, 150, -147, -317, +-314, -727, -449, -1066, -538, -1151, -470, -875, +-249, -393, -54, 145, 72, 648, 231, 942, +358, 924, 384, 589, 413, 28, 432, -488, +298, -680, 121, -530, 7, -135, -220, 385, +-529, 768, -637, 703, -610, 220, -602, -433, +-434, -1057, -38, -1376, 286, -1166, 431, -555, +562, 258, 698, 1103, 704, 1624, 604, 1597, +432, 1183, 67, 489, -437, -356, -811, -1086, +-987, -1554, -1064, -1626, -962, -1218, -561, -564, +-49, 113, 404, 743, 875, 1134, 1302, 1133, +1426, 907, 1156, 619, 703, 295, 118, -47, +-638, -367, -1325, -593, -1650, -694, -1593, -732, +-1165, -658, -389, -394, 470, -55, 1105, 210, +1439, 441, 1418, 628, 1027, 620, 433, 385, +-81, 137, -458, 2, -720, -50, -754, 25, +-550, 190, -330, 213, -159, -30, -75, -460, +-149, -862, -271, -1040, -235, -886, -29, -373, +330, 377, 793, 1058, 1147, 1425, 1236, 1395, +1010, 984, 383, 321, -455, -387, -1196, -981, +-1702, -1221, -1819, -1045, -1361, -708, -454, -322, +545, 169, 1321, 484, 1675, 439, 1531, 332, +1003, 379, 309, 436, -363, 493, -769, 626, +-737, 623, -488, 242, -296, -355, -203, -910, +-245, -1304, -439, -1392, -598, -1028, -490, -318, +-126, 463, 357, 1096, 853, 1479, 1278, 1523, +1461, 1134, 1194, 385, 499, -405, -380, -983, +-1258, -1268, -1886, -1250, -1939, -934, -1323, -411, +-315, 80, 653, 395, 1290, 645, 1493, 829, +1220, 810, 623, 637, 53, 429, -306, 113, +-529, -271, -558, -585, -374, -820, -200, -938, +-103, -848, -41, -542, -124, -31, -281, 514, +-314, 899, -259, 1112, -120, 1051, 158, 562, +468, -69, 723, -536, 828, -880, 641, -1036, +254, -843, -121, -435, -452, -32, -770, 281, +-860, 505, -656, 663, -437, 720, -282, 594, +36, 338, 416, 25, 606, -338, 652, -697, +643, -874, 516, -713, 274, -305, -5, 84, +-194, 373, -320, 579, -458, 564, -501, 298, +-408, 54, -375, -38, -350, -83, -171, -72, +42, 55, 197, 139, 470, 58, 761, -106, +812, -322, 626, -574, 334, -612, -24, -366, +-417, -11, -707, 398, -743, 811, -597, 967, +-404, 788, -160, 406, 91, -83, 215, -526, +246, -769, 287, -798, 333, -617, 390, -322, +432, -36, 403, 213, 355, 373, 254, 395, +-36, 407, -415, 450, -699, 442, -885, 428, +-958, 390, -791, 133, -327, -316, 282, -759, +804, -1073, 1087, -1141, 1037, -809, 817, -126, +597, 610, 253, 1126, -183, 1301, -474, 1058, +-695, 512, -947, -58, -1065, -483, -969, -740, +-720, -798, -296, -671, 274, -432, 865, -171, +1354, 65, 1574, 245, 1435, 374, 976, 438, +217, 450, -674, 416, -1414, 292, -1831, 67, +-1815, -207, -1326, -481, -483, -663, 449, -645, +1171, -302, 1527, 248, 1495, 633, 1054, 696, +412, 526, -94, 68, -451, -582, -753, -964, +-824, -839, -587, -411, -279, 183, -122, 799, +-133, 1132, -237, 1014, -292, 542, -231, -59, +3, -585, 458, -946, 945, -1066, 1079, -888, +815, -484, 446, -46, 77, 363, -402, 720, +-835, 895, -1006, 836, -984, 644, -847, 331, +-482, -79, 35, -439, 447, -702, 652, -905, +757, -885, 842, -593, 873, -181, 743, 323, +394, 812, -137, 969, -654, 761, -1002, 359, +-1179, -122, -1113, -540, -714, -702, -143, -504, +413, -36, 921, 406, 1239, 653, 1142, 643, +678, 257, 54, -419, -517, -1008, -780, -1275, +-687, -1061, -364, -320, 25, 647, 298, 1485, +357, 1916, 201, 1628, -120, 721, -417, -356, +-554, -1311, -516, -1884, -231, -1790, 259, -1143, +668, -232, 838, 678, 861, 1253, 735, 1373, +343, 1175, -164, 685, -578, 50, -914, -423, +-1127, -625, -1033, -629, -661, -492, -191, -309, +292, -144, 715, -27, 996, -6, 1136, 19, +1072, 159, 742, 258, 239, 274, -346, 296, +-879, 254, -1161, 66, -1176, -121, -996, -165, +-601, -133, -35, -108, 493, -10, 802, 116, +929, 103, 899, -50, 649, -208, 253, -335, +-36, -396, -146, -302, -242, -21, -399, 322, +-518, 559, -586, 626, -599, 562, -511, 332, +-332, -37, -49, -396, 339, -615, 617, -613, +707, -453, 696, -294, 568, -95, 319, 121, +85, 177, -115, 120, -312, 175, -442, 341, +-518, 492, -641, 567, -693, 526, -566, 327, +-375, -53, -170, -591, 168, -1053, 617, -1243, +1041, -1116, 1353, -622, 1411, 157, 1060, 940, +325, 1475, -594, 1546, -1397, 1090, -1845, 325, +-1924, -444, -1640, -1036, -887, -1226, 190, -977, +1198, -560, 1931, -142, 2265, 211, 1982, 354, +1145, 352, 163, 356, -691, 376, -1360, 403, +-1712, 451, -1652, 395, -1342, 162, -878, -169, +-231, -528, 474, -828, 996, -869, 1260, -604, +1363, -160, 1332, 327, 1049, 743, 501, 921, +-141, 752, -721, 313, -1209, -170, -1492, -506, +-1384, -604, -964, -455, -480, -128, 58, 168, +669, 295, 1115, 232, 1237, 32, 1131, -171, +870, -267, 426, -212, -50, 57, -325, 392, +-450, 551, -617, 486, -840, 232, -1025, -217, +-1059, -676, -842, -890, -338, -744, 335, -257, +982, 368, 1443, 851, 1598, 1081, 1388, 959, +831, 443, 33, -273, -755, -853, -1349, -1108, +-1625, -1049, -1492, -672, -1027, -36, -422, 518, +203, 807, 766, 909, 1146, 810, 1258, 514, +1166, 202, 873, -99, 346, -425, -224, -703, +-625, -915, -954, -979, -1200, -725, -1109, -240, +-676, 341, -146, 912, 415, 1263, 907, 1230, +1059, 826, 817, 147, 372, -551, -126, -1041, +-510, -1244, -619, -1075, -443, -511, -91, 147, +304, 650, 558, 895, 510, 762, 153, 330, +-373, -158, -838, -520, -975, -527, -682, -163, +-108, 328, 538, 684, 1017, 695, 1113, 307, +831, -301, 315, -938, -296, -1331, -768, -1147, +-876, -452, -632, 363, -219, 1128, 176, 1603, +408, 1465, 391, 774, 130, -154, -220, -1007, +-437, -1464, -404, -1358, -152, -785, 251, -22, +674, 688, 921, 1058, 878, 930, 477, 471, +-212, -63, -847, -527, -1156, -718, -1125, -513, +-793, -86, -243, 311, 330, 596, 737, 649, +922, 412, 929, 5, 752, -395, 341, -674, +-125, -760, -392, -610, -499, -266, -586, 111, +-553, 467, -385, 714, -240, 751, -129, 645, +42, 486, 256, 210, 461, -162, 578, -502, +505, -802, 243, -1077, -31, -1084, -215, -697, +-324, -46, -301, 721, -144, 1406, 13, 1688, +106, 1389, 35, 623, -189, -332, -330, -1209, +-292, -1723, -188, -1666, 21, -999, 360, -11, +560, 889, 486, 1459, 347, 1514, 174, 960, +-146, 48, -454, -811, -506, -1264, -339, -1137, +-112, -482, 134, 374, 333, 1046, 244, 1250, +-145, 864, -499, 25, -633, -862, -514, -1403, +-67, -1381, 581, -835, 1129, 55, 1371, 978, +1174, 1569, 523, 1607, -394, 1107, -1346, 213, +-2018, -770, -2005, -1439, -1280, -1605, -217, -1303, +864, -562, 1710, 319, 2042, 946, 1785, 1220, +1085, 1144, 169, 732, -705, 184, -1287, -304, +-1490, -613, -1382, -721, -995, -691, -414, -550, +118, -270, 506, 51, 818, 326, 1012, 549, +1011, 653, 857, 547, 563, 235, 124, -178, +-358, -479, -752, -617, -1018, -603, -1120, -348, +-923, 99, -398, 491, 238, 679, 730, 632, +976, 368, 939, -77, 619, -570, 179, -886, +-178, -816, -383, -416, -457, 110, -427, 625, +-287, 912, -74, 784, 80, 421, 105, 20, +36, -379, -79, -637, -82, -575, 87, -351, +259, -166, 314, 20, 238, 169, 20, 157, +-222, 56, -328, -2, -261, 66, -78, 255, +153, 506, 314, 646, 360, 497, 286, 59, +30, -542, -350, -1090, -636, -1290, -709, -1031, +-496, -360, 1, 529, 566, 1292, 932, 1584, +977, 1318, 672, 667, 74, -157, -565, -949, +-929, -1377, -997, -1267, -820, -798, -313, -228, +384, 365, 858, 816, 944, 924, 760, 726, +328, 405, -296, 123, -764, -96, -809, -332, +-574, -459, -256, -414, 139, -388, 533, -405, +702, -241, 594, 89, 338, 384, -12, 576, +-376, 659, -596, 545, -589, 211, -375, -266, +-140, -655, -24, -770, 104, -646, 311, -342, +443, 169, 504, 680, 532, 845, 384, 654, +41, 322, -316, -157, -612, -657, -799, -843, +-745, -645, -476, -268, -87, 175, 402, 615, +822, 828, 942, 635, 729, 219, 296, -221, +-215, -623, -613, -827, -741, -640, -577, -182, +-238, 259, 118, 542, 398, 655, 502, 577, +391, 349, 107, 18, -258, -323, -543, -560, +-543, -660, -222, -659, 211, -447, 528, -21, +649, 391, 510, 687, 119, 848, -270, 710, +-396, 354, -328, -11, -221, -371, -104, -651, +-26, -728, -61, -669, -166, -496, -292, -181, +-287, 163, 7, 429, 457, 637, 851, 730, +1077, 670, 939, 471, 364, 159, -462, -198, +-1230, -521, -1633, -786, -1491, -896, -863, -766, +52, -402, 962, 51, 1531, 499, 1567, 839, +1122, 901, 384, 664, -397, 318, -898, -11, +-972, -270, -725, -373, -344, -314, -10, -296, +131, -391, 18, -468, -191, -457, -241, -338, +-84, -33, 217, 414, 620, 815, 991, 1009, +1049, 957, 641, 585, -60, -45, -751, -674, +-1272, -1103, -1433, -1241, -1030, -950, -239, -270, +481, 476, 868, 992, 918, 1147, 665, 845, +241, 224, -87, -482, -148, -995, 12, -946, +204, -384, 260, 254, 78, 815, -331, 1127, +-778, 864, -1049, 122, -1009, -642, -552, -1161, +215, -1259, 956, -858, 1422, -144, 1461, 571, +997, 1021, 202, 1077, -616, 821, -1187, 338, +-1316, -185, -976, -458, -384, -421, 187, -253, +565, -111, 640, -106, 427, -275, 112, -547, +-85, -752, -101, -669, 31, -137, 242, 683, +409, 1410, 365, 1760, 106, 1552, -230, 749, +-556, -390, -792, -1519, -760, -2241, -404, -2206, +92, -1419, 495, -217, 711, 1035, 687, 1921, +401, 2109, 32, 1597, -132, 607, -73, -494, +30, -1202, 44, -1318, -44, -980, -232, -375, +-521, 246, -744, 509, -665, 317, -308, -66, +167, -359, 659, -444, 1037, -222, 1106, 279, +801, 814, 257, 1052, -317, 859, -797, 361, +-1097, -278, -1072, -939, -667, -1321, -118, -1172, +318, -611, 644, 72, 836, 691, 733, 1027, +361, 949, -29, 553, -247, 48, -316, -353, +-293, -486, -212, -372, -114, -163, -15, 7, +12, 117, -82, 146, -175, 54, -132, -139, +8, -272, 127, -243, 197, -159, 275, -69, +309, 146, 199, 373, 13, 450, -114, 429, +-172, 318, -232, 84, -271, -127, -244, -312, +-161, -528, -8, -606, 152, -486, 230, -281, +227, 17, 157, 338, 42, 598, -66, 752, +-135, 650, -127, 310, -22, -72, 89, -430, +175, -665, 221, -636, 127, -362, -124, -9, +-373, 252, -480, 306, -418, 221, -184, 55, +184, -149, 526, -170, 680, 55, 590, 282, +295, 444, -132, 504, -509, 295, -693, -143, +-670, -574, -434, -884, 26, -936, 522, -579, +784, 58, 709, 664, 365, 1060, -143, 1123, +-646, 787, -894, 129, -723, -559, -252, -940, +309, -964, 783, -750, 967, -279, 747, 294, +267, 638, -291, 637, -777, 424, -960, 138, +-737, -116, -281, -229, 169, -118, 479, 105, +569, 219, 432, 123, 173, -136, -27, -493, +-47, -747, 20, -685, 96, -278, 185, 356, +138, 983, -156, 1315, -523, 1167, -756, 491, +-793, -469, -583, -1306, -84, -1671, 598, -1407, +1182, -597, 1397, 458, 1147, 1367, 493, 1706, +-369, 1336, -1145, 501, -1557, -449, -1453, -1223, +-865, -1468, -24, -1060, 742, -268, 1206, 541, +1255, 1090, 888, 1141, 274, 686, -338, -55, +-737, -775, -786, -1138, -495, -948, -76, -349, +219, 409, 310, 1068, 238, 1285, -11, 892, +-312, 127, -420, -704, -306, -1295, -49, -1364, +330, -848, 698, 12, 815, 827, 587, 1287, +95, 1287, -505, 806, -954, 15, -1052, -734, +-766, -1151, -202, -1132, 425, -714, 855, -82, +954, 551, 729, 963, 287, 985, -248, 680, +-702, 227, -832, -295, -580, -716, -166, -844, +222, -698, 512, -417, 609, -53, 421, 341, +71, 638, -220, 735, -387, 659, -489, 460, +-453, 159, -173, -225, 213, -609, 453, -865, +493, -855, 401, -594, 169, -158, -138, 370, +-343, 797, -369, 914, -321, 728, -272, 385, +-129, -19, 90, -409, 226, -579, 294, -476, +378, -302, 329, -167, 71, -11, -165, 79, +-259, -1, -338, -123, -407, -68, -294, 133, +-31, 343, 165, 539, 310, 651, 469, 495, +468, 96, 234, -340, -63, -694, -333, -912, +-537, -859, -564, -524, -402, -79, -137, 342, +160, 703, 408, 904, 561, 831, 583, 542, +425, 207, 137, -152, -191, -490, -523, -694, +-716, -728, -670, -634, -450, -448, -104, -193, +324, 121, 633, 451, 677, 736, 531, 863, +295, 785, -18, 478, -306, -25, -421, -572, +-407, -950, -394, -1011, -322, -708, -114, -183, +75, 314, 146, 634, 249, 721, 368, 533, +326, 219, 189, -32, 115, -220, 53, -343, +-116, -323, -316, -199, -376, -70, -320, 21, +-253, 111, -147, 176, 60, 136, 271, 28, +352, -22, 292, -15, 197, -19, 104, -55, +-24, -105, -118, -162, -104, -152, -66, -29, +-87, 140, -166, 297, -285, 398, -347, 354, +-232, 150, 15, -165, 296, -476, 528, -639, +624, -579, 518, -347, 202, 18, -218, 438, +-568, 730, -766, 773, -751, 573, -426, 170, +108, -281, 555, -610, 731, -726, 632, -607, +319, -307, -79, 42, -331, 331, -341, 458, +-238, 422, -150, 306, -82, 157, -21, -14, +1, -141, -47, -204, -94, -219, -16, -195, +157, -125, 284, -37, 357, 45, 356, 100, +140, 115, -259, 86, -564, 39, -635, -11, +-486, -26, -147, -9, 264, 11, 578, 58, +678, 117, 532, 90, 193, -28, -265, -138, +-679, -183, -812, -188, -589, -134, -125, 29, +423, 246, 791, 335, 758, 227, 370, 20, +-134, -209, -546, -406, -709, -409, -562, -171, +-177, 175, 258, 496, 517, 669, 490, 528, +263, 91, -36, -427, -297, -824, -409, -950, +-317, -698, -112, -169, 117, 461, 313, 986, +388, 1167, 275, 930, 58, 409, -177, -260, +-434, -870, -587, -1175, -450, -1099, -87, -722, +267, -124, 482, 490, 568, 894, 488, 1025, +251, 878, -25, 502, -253, 36, -451, -407, +-588, -714, -613, -822, -503, -727, -195, -475, +292, -87, 720, 339, 885, 641, 781, 749, +444, 636, -57, 289, -540, -125, -855, -463, +-913, -649, -685, -567, -242, -218, 290, 208, +761, 525, 979, 619, 796, 446, 249, 20, +-401, -509, -848, -879, -929, -874, -607, -487, +10, 153, 628, 842, 952, 1281, 845, 1246, +366, 737, -274, -90, -795, -928, -1006, -1460, +-852, -1492, -398, -985, 177, -140, 656, 703, +913, 1274, 897, 1409, 579, 1066, 77, 379, +-366, -373, -636, -900, -736, -1033, -619, -807, +-306, -350, -13, 196, 152, 599, 243, 649, +262, 376, 225, -16, 233, -354, 260, -534, +221, -435, 155, -65, 70, 370, -128, 671, +-355, 753, -441, 549, -408, 89, -364, -430, +-265, -815, -82, -983, 107, -850, 250, -432, +407, 119, 531, 620, 515, 947, 406, 1023, +213, 844, -129, 434, -498, -102, -725, -608, +-801, -962, -733, -1046, -440, -810, 47, -369, +553, 157, 885, 628, 940, 869, 670, 813, +153, 540, -370, 166, -666, -192, -683, -464, +-460, -558, -56, -433, 325, -216, 398, -23, +180, 158, -116, 225, -376, 114, -526, -9, +-416, -23, -31, -13, 454, 48, 808, 187, +861, 271, 587, 195, 109, -15, -437, -257, +-886, -406, -1036, -410, -802, -260, -300, 22, +250, 348, 637, 533, 757, 485, 582, 261, +184, -73, -211, -407, -374, -583, -300, -555, +-77, -350, 243, -11, 467, 383, 343, 667, +-65, 712, -478, 527, -749, 180, -793, -240, +-497, -585, 37, -733, 529, -645, 796, -370, +825, -38, 591, 216, 170, 396, -199, 503, +-394, 490, -467, 407, -423, 307, -261, 144, +-95, -71, -41, -319, -101, -588, -192, -769, +-190, -729, -20, -462, 255, -32, 500, 448, +665, 823, 687, 964, 463, 810, 44, 403, +-379, -55, -734, -422, -967, -692, -929, -793, +-596, -658, -147, -393, 317, -96, 711, 196, +848, 449, 702, 569, 477, 536, 255, 436, +-11, 300, -274, 69, -448, -219, -559, -421, +-625, -491, -569, -484, -362, -374, -96, -149, +169, 128, 427, 334, 609, 394, 594, 371, +407, 295, 155, 108, -94, -118, -302, -249, +-388, -241, -332, -144, -207, -12, -117, 103, +-102, 136, -132, 31, -148, -142, -106, -247, +9, -240, 158, -133, 300, 66, 409, 297, +446, 466, 330, 481, 76, 307, -235, 2, +-531, -325, -704, -586, -611, -664, -257, -485, +161, -128, 438, 240, 514, 518, 408, 638, +143, 574, -156, 328, -305, -25, -292, -338, +-192, -523, -22, -588, 184, -485, 319, -213, +302, 105, 125, 362, -139, 528, -360, 539, +-434, 370, -346, 110, -134, -135, 93, -352, +212, -499, 226, -478, 214, -276, 178, -41, +102, 139, 31, 294, 11, 400, 14, 376, +-3, 224, -42, 27, -114, -130, -249, -221, +-370, -233, -371, -170, -266, -82, -94, -40, +139, -43, 335, -77, 429, -103, 502, -39, +566, 115, 439, 271, 104, 398, -273, 446, +-595, 345, -824, 97, -883, -234, -736, -592, +-405, -847, 55, -838, 562, -517, 994, 36, +1199, 667, 1069, 1114, 628, 1189, -27, 866, +-713, 239, -1192, -479, -1334, -1005, -1146, -1188, +-649, -1024, 43, -569, 710, 53, 1130, 598, +1189, 916, 910, 988, 381, 803, -245, 412, +-723, -67, -930, -525, -870, -817, -551, -851, +-70, -644, 334, -262, 547, 198, 579, 545, +388, 666, 23, 590, -265, 343, -341, 13, +-301, -245, -203, -381, -34, -410, 88, -327, +85, -142, 79, 79, 153, 236, 171, 268, +115, 215, 87, 113, 40, -25, -120, -133, +-320, -152, -486, -150, -572, -149, -478, -95, +-158, 30, 313, 165, 773, 251, 1028, 279, +947, 228, 493, 47, -195, -197, -822, -350, +-1176, -377, -1219, -331, -898, -179, -249, 73, +465, 314, 982, 457, 1167, 458, 958, 289, +456, 27, -105, -227, -550, -417, -783, -480, +-726, -366, -420, -123, -56, 143, 174, 356, +247, 480, 209, 446, 78, 204, -79, -158, +-116, -453, 8, -578, 197, -491, 328, -180, +305, 234, 125, 547, -89, 659, -267, 571, +-399, 303, -409, -90, -279, -474, -136, -719, +7, -775, 191, -628, 326, -259, 309, 244, +211, 673, 126, 893, 51, 879, -33, 600, +-88, 123, -118, -355, -182, -697, -295, -864, +-344, -785, -250, -485, -56, -118, 163, 230, +348, 525, 389, 687, 287, 677, 103, 498, +-119, 208, -294, -105, -314, -363, -201, -505, +-69, -474, 35, -316, 146, -154, 197, -51, +89, 12, -100, 51, -195, 111, -224, 230, +-227, 366, -79, 418, 187, 325, 341, 115, +333, -121, 218, -323, 0, -456, -254, -456, +-421, -303, -434, -100, -266, 88, 0, 263, +205, 365, 289, 333, 298, 217, 189, 61, +-37, -118, -243, -260, -318, -286, -266, -196, +-100, -33, 146, 158, 344, 312, 354, 346, +185, 208, -100, -82, -404, -396, -550, -585, +-439, -569, -165, -345, 168, 77, 443, 566, +541, 868, 438, 854, 183, 571, -158, 89, +-478, -446, -644, -833, -551, -935, -227, -744, +203, -359, 595, 56, 749, 398, 502, 642, +-6, 743, -462, 662, -716, 418, -730, 71, +-448, -274, 35, -512, 475, -607, 718, -553, +750, -338, 546, -63, 97, 116, -439, 179, +-799, 220, -857, 277, -643, 340, -203, 390, +331, 358, 687, 190, 730, -84, 521, -392, +165, -626, -233, -670, -508, -482, -557, -122, +-366, 279, -25, 547, 279, 608, 433, 501, +411, 272, 148, -2, -261, -209, -548, -347, +-588, -416, -435, -370, -93, -236, 349, -91, +679, 94, 767, 295, 615, 408, 249, 380, +-254, 246, -716, 51, -936, -177, -829, -384, +-461, -448, 35, -340, 499, -146, 740, 116, +700, 398, 436, 516, 66, 403, -239, 168, +-381, -116, -416, -392, -333, -535, -133, -468, +68, -219, 187, 99, 191, 384, 45, 557, +-162, 505, -294, 198, -313, -174, -200, -424, +61, -501, 346, -363, 507, -24, 485, 310, +314, 448, 50, 348, -266, 66, -582, -270, +-762, -482, -682, -455, -355, -190, 66, 195, +415, 546, 585, 700, 556, 545, 394, 126, +194, -375, -27, -779, -246, -909, -356, -665, +-325, -154, -245, 410, -167, 855, -95, 993, +-76, 743, -119, 214, -119, -384, 12, -807, +252, -887, 463, -660, 500, -219, 313, 302, +15, 666, -239, 701, -423, 475, -547, 132, +-501, -204, -274, -421, -19, -472, 219, -340, +459, -78, 542, 141, 358, 242, 32, 287, +-241, 248, -401, 84, -443, -57, -343, -94, +-74, -110, 251, -130, 455, -119, 466, -120, +316, -125, 27, -81, -323, 19, -557, 165, +-552, 319, -357, 375, -101, 287, 111, 84, +288, -183, 429, -420, 489, -510, 452, -429, +324, -179, 60, 182, -290, 478, -560, 548, +-692, 380, -729, 49, -558, -303, -137, -492, +319, -405, 665, -78, 904, 321, 900, 558, +560, 506, 21, 181, -498, -294, -863, -692, +-995, -811, -856, -614, -439, -158, 119, 409, +619, 859, 912, 1022, 925, 846, 629, 378, +102, -216, -475, -760, -845, -1085, -855, -1044, +-602, -668, -221, -139, 250, 427, 594, 871, +625, 1012, 445, 833, 175, 434, -165, -70, +-397, -505, -351, -734, -161, -725, -35, -504, +-8, -178, -72, 117, -184, 327, -246, 401, +-156, 328, 90, 214, 364, 128, 518, 48, +542, -14, 419, -61, 96, -132, -354, -201, +-779, -239, -1034, -238, -948, -150, -490, 11, +160, 158, 750, 237, 1094, 241, 1089, 178, +758, 87, 219, -4, -351, -72, -780, -100, +-966, -126, -924, -181, -666, -210, -239, -173, +237, -84, 591, 40, 708, 211, 646, 379, +507, 442, 259, 330, -59, 74, -275, -225, +-395, -468, -535, -596, -581, -530, -420, -252, +-168, 110, 62, 416, 308, 607, 522, 611, +564, 429, 411, 166, 156, -132, -149, -429, +-422, -608, -509, -636, -379, -505, -180, -189, +37, 198, 243, 504, 325, 697, 247, 705, +123, 451, -10, 37, -175, -361, -301, -619, +-264, -641, -106, -451, 57, -154, 185, 154, +243, 370, 170, 419, 38, 330, -46, 159, +-82, -12, -102, -121, -92, -174, -88, -179, +-112, -117, -119, -28, -83, 40, -24, 78, +44, 78, 98, 33, 138, -26, 164, -71, +164, -78, 129, -61, 24, -14, -139, 76, +-262, 156, -320, 163, -313, 122, -198, 29, +-6, -114, 151, -210, 263, -198, 327, -131, +277, -46, 126, 39, -46, 102, -219, 137, +-321, 147, -282, 124, -146, 74, -8, 6, +89, -63, 111, -131, 81, -175, 32, -158, +-30, -74, -65, 10, -42, 57, -4, 99, +45, 149, 90, 149, 55, 96, -23, 38, +-58, -22, -100, -90, -146, -137, -124, -178, +-56, -208, -14, -163, 2, -40, 24, 101, +86, 253, 148, 379, 136, 394, 62, 246, +-23, -29, -103, -334, -159, -547, -180, -591, +-153, -442, -70, -114, 24, 293, 85, 616, +158, 740, 188, 594, 91, 222, -53, -208, +-125, -538, -136, -684, -101, -591, -29, -300, +46, 68, 85, 371, 49, 505, -31, 447, +-56, 248, -58, -15, -90, -216, -90, -262, +2, -178, 117, -34, 181, 91, 172, 99, +103, 20, -22, -60, -171, -113, -279, -100, +-282, -13, -183, 43, -33, 18, 126, -16, +259, -1, 313, 61, 263, 164, 106, 268, +-80, 307, -189, 207, -202, -48, -198, -357, +-175, -576, -107, -626, -40, -463, -20, -106, +11, 331, 100, 663, 201, 757, 262, 601, +290, 292, 255, -73, 97, -365, -168, -480, +-432, -457, -609, -398, -582, -312, -304, -200, +83, -58, 397, 138, 583, 360, 594, 544, +408, 628, 119, 512, -161, 198, -406, -174, +-524, -472, -453, -601, -293, -504, -115, -265, +120, -15, 318, 142, 336, 128, 235, 17, +130, -12, -13, 68, -157, 223, -175, 446, +-88, 582, -8, 450, 56, 99, 83, -331, +22, -715, -93, -908, -178, -799, -226, -400, +-245, 149, -194, 605, -11, 809, 271, 766, +532, 522, 645, 136, 488, -208, 54, -377, +-461, -423, -832, -419, -927, -342, -645, -204, +-56, -55, 501, 101, 807, 256, 843, 344, +601, 300, 145, 126, -316, -71, -641, -180, +-757, -155, -604, -30, -224, 139, 205, 252, +501, 209, 576, -27, 434, -341, 135, -519, +-152, -450, -263, -215, -251, 134, -251, 502, +-180, 659, 2, 497, 109, 182, 91, -155, +112, -443, 137, -574, 30, -440, -79, -107, +-37, 206, 49, 353, 66, 383, 86, 293, +122, 36, 43, -224, -166, -300, -335, -250, +-353, -159, -280, -53, -103, 31, 227, 105, +531, 204, 601, 299, 455, 372, 167, 342, +-190, 118, -477, -225, -591, -551, -523, -755, +-325, -689, -81, -321, 174, 189, 397, 648, +512, 890, 489, 808, 349, 473, 98, 35, +-199, -381, -422, -656, -475, -708, -338, -581, +-121, -346, 33, -57, 132, 235, 153, 465, +60, 579, -2, 559, 67, 407, 134, 136, +160, -183, 187, -430, 135, -519, -15, -454, +-137, -282, -228, -42, -342, 184, -398, 280, +-274, 233, -30, 121, 194, 45, 373, 76, +508, 183, 437, 268, 147, 242, -148, 6, +-316, -391, -371, -695, -313, -713, -196, -438, +-67, 63, 55, 580, 125, 849, 149, 765, +206, 400, 236, -48, 150, -352, -13, -492, +-145, -526, -227, -419, -229, -224, -111, -71, +72, 72, 166, 251, 137, 393, 61, 432, +-36, 355, -118, 185, -108, -6, -50, -188, +6, -345, 83, -421, 165, -390, 188, -272, +160, -66, 43, 161, -178, 333, -385, 413, +-442, 365, -281, 200, 83, 16, 463, -112, +641, -164, 537, -180, 181, -215, -258, -259, +-533, -254, -583, -179, -460, -3, -182, 253, +156, 459, 402, 491, 540, 330, 539, 31, +330, -258, -7, -408, -340, -392, -564, -255, +-545, -65, -281, 73, 44, 115, 296, 135, +431, 196, 397, 243, 212, 217, -32, 119, +-228, -25, -300, -212, -246, -369, -90, -369, +127, -185, 272, 57, 248, 247, 114, 339, +-74, 294, -242, 112, -269, -92, -151, -199, +16, -176, 167, -70, 235, 46, 179, 99, +62, 54, -41, -64, -103, -152, -112, -126, +-62, -12, 34, 117, 101, 220, 50, 226, +-68, 94, -134, -81, -136, -179, -85, -201, +57, -150, 218, -24, 260, 110, 159, 162, +9, 115, -112, 10, -160, -77, -138, -122, +-79, -120, -25, -38, 18, 106, 58, 196, +102, 175, 124, 76, 81, -63, -51, -206, +-161, -284, -147, -250, -15, -105, 151, 100, +277, 286, 252, 368, 66, 304, -159, 106, +-294, -130, -323, -307, -244, -363, -49, -277, +208, -81, 374, 117, 374, 233, 225, 237, +-13, 142, -258, 8, -365, -81, -277, -89, +-35, -31, 249, 45, 406, 105, 306, 103, +57, 6, -199, -154, -399, -282, -465, -319, +-300, -247, 8, -66, 306, 202, 521, 450, +626, 559, 541, 498, 243, 284, -192, -82, +-580, -475, -794, -702, -772, -702, -483, -496, +4, -128, 480, 267, 798, 567, 873, 692, +675, 580, 297, 308, -108, 27, -479, -235, +-703, -415, -671, -427, -443, -336, -163, -204, +104, -20, 288, 91, 361, 45, 348, -15, +303, 23, 313, 122, 339, 278, 229, 445, +-1, 483, -263, 309, -535, -34, -715, -440, +-671, -733, -398, -770, 47, -529, 523, -110, +824, 338, 894, 631, 721, 663, 261, 500, +-285, 268, -631, 3, -759, -221, -677, -320, +-358, -343, 29, -367, 307, -347, 472, -226, +489, 8, 340, 274, 135, 455, -53, 483, +-172, 339, -156, 38, -74, -263, -31, -410, +-43, -375, -93, -180, -149, 97, -129, 296, +1, 320, 195, 170, 341, -44, 313, -206, +122, -288, -115, -254, -308, -84, -353, 74, +-200, 164, 71, 266, 340, 333, 478, 295, +373, 159, 72, -114, -284, -441, -549, -631, +-549, -599, -265, -293, 138, 249, 479, 712, +603, 848, 434, 650, 120, 168, -177, -393, +-362, -710, -334, -716, -171, -475, -61, -59, +61, 325, 237, 511, 297, 499, 197, 268, +30, -74, -164, -317, -290, -419, -289, -334, +-139, -5, 145, 366, 418, 572, 497, 537, +417, 204, 209, -314, -122, -754, -438, -959, +-628, -798, -672, -235, -467, 480, -35, 1028, +479, 1223, 905, 976, 1042, 412, 728, -240, +118, -804, -479, -1124, -818, -1090, -859, -764, +-652, -269, -262, 283, 163, 765, 459, 1031, +651, 965, 711, 574, 553, 72, 221, -313, +-182, -515, -555, -546, -651, -437, -452, -310, +-166, -259, 137, -217, 398, -68, 443, 175, +310, 430, 125, 587, -68, 561, -234, 368, +-310, 82, -215, -244, 76, -448, 329, -425, +352, -311, 196, -200, -71, -43, -327, 59, +-335, 72, -109, 121, 150, 187, 301, 238, +244, 304, 23, 218, -151, -36, -168, -239, +-57, -344, 85, -332, 145, -104, 143, 165, +125, 316, 48, 350, -52, 173, -131, -157, +-190, -360, -147, -389, 2, -274, 151, -30, +262, 220, 275, 405, 122, 458, -78, 264, +-214, -9, -252, -159, -160, -255, -11, -290, +113, -202, 265, -117, 364, -30, 266, 102, +61, 191, -120, 233, -274, 217, -326, 48, +-245, -186, -92, -346, 74, -350, 184, -108, +202, 272, 219, 525, 265, 574, 261, 377, +169, -55, 41, -496, -103, -744, -285, -724, +-447, -418, -431, -19, -220, 336, 57, 636, +330, 746, 529, 619, 512, 372, 297, -8, +35, -421, -185, -670, -283, -756, -221, -657, +-91, -271, 24, 237, 105, 622, 100, 739, +37, 545, -17, 213, -92, -83, -177, -385, +-157, -581, -17, -481, 207, -179, 442, 119, +525, 365, 408, 525, 202, 489, -118, 190, +-479, -249, -650, -607, -581, -696, -359, -455, +-12, 14, 293, 470, 458, 718, 526, 654, +467, 278, 307, -217, 214, -560, 124, -609, +-39, -347, -225, 48, -428, 351, -599, 467, +-567, 341, -376, -24, -40, -369, 418, -460, +747, -307, 796, -39, 674, 216, 339, 389, +-145, 447, -515, 280, -653, -36, -580, -232, +-278, -288, 105, -293, 391, -159, 434, 47, +258, 138, 50, 89, -88, -56, -215, -208, +-188, -169, 35, 71, 241, 365, 319, 563, +296, 520, 138, 187, -85, -293, -268, -735, +-343, -905, -241, -667, -9, -148, 166, 442, +207, 929, 131, 1100, 29, 829, -20, 171, +-37, -642, -10, -1253, 112, -1359, 240, -917, +304, -36, 315, 993, 212, 1682, -51, 1652, +-430, 897, -766, -307, -768, -1465, -349, -2046, +232, -1765, 775, -712, 1100, 711, 964, 1861, +404, 2183, -270, 1544, -779, 257, -894, -1086, +-617, -1894, -152, -1885, 316, -1094, 607, 143, +582, 1240, 327, 1701, -34, 1419, -371, 599, +-461, -379, -238, -1131, 102, -1412, 417, -1112, +617, -320, 525, 548, 83, 1112, -432, 1209, +-731, 798, -704, 26, -348, -742, 249, -1181, +765, -1042, 914, -330, 666, 562, 170, 1185, +-385, 1250, -795, 606, -858, -447, -491, -1320, +55, -1611, 491, -1147, 819, -37, 932, 1158, +581, 1863, -1, 1791, -468, 946, -794, -325, +-817, -1475, -412, -2034, 99, -1729, 435, -713, +583, 494, 509, 1410, 288, 1736, 48, 1332, +-151, 418, -194, -563, -78, -1175, 10, -1176, +64, -673, 90, 41, -19, 707, -223, 1008, +-362, 746, -352, 65, -102, -679, 302, -1130, +650, -1026, 772, -369, 613, 565, 209, 1316, +-295, 1461, -729, 914, -849, -51, -599, -1027, +-147, -1542, 337, -1343, 726, -578, 798, 416, +520, 1222, 59, 1426, -350, 967, -549, 116, +-462, -779, -154, -1313, 265, -1211, 536, -576, +497, 322, 198, 1122, -213, 1420, -541, 1084, +-552, 315, -253, -618, 216, -1336, 625, -1458, +730, -942, 502, -50, 111, 871, -338, 1386, +-648, 1202, -671, 444, -441, -476, -54, -1095, +391, -1062, 729, -424, 846, 430, 643, 1061, +173, 1131, -327, 532, -689, -390, -811, -1139, +-560, -1437, -125, -1149, 209, -314, 445, 680, +596, 1393, 590, 1592, 473, 1232, 237, 454, +-101, -417, -347, -1106, -427, -1427, -406, -1292, +-287, -783, -142, -91, -64, 614, 44, 1081, +255, 1140, 497, 828, 670, 275, 637, -300, +310, -610, -164, -577, -581, -289, -794, 69, +-715, 219, -368, 44, 110, -275, 603, -544, +912, -577, 848, -254, 440, 308, -123, 887, +-640, 1237, -844, 1086, -637, 455, -186, -391, +289, -1190, 608, -1584, 653, -1313, 523, -573, +293, 325, -62, 1118, -420, 1469, -595, 1254, +-522, 641, -178, -167, 229, -844, 420, -1154, +396, -1113, 237, -701, 15, 12, -71, 632, +-6, 941, 80, 960, 136, 641, 100, 80, +-12, -443, -80, -787, -156, -838, -271, -574, +-321, -155, -242, 298, 75, 661, 539, 725, +735, 486, 578, 113, 278, -230, -152, -408, +-526, -399, -570, -278, -381, -92, -126, 38, +139, 48, 305, 78, 402, 158, 398, 142, +198, 73, -76, 50, -281, 39, -362, 12, +-162, 18, 177, 34, 393, 16, 454, -69, +292, -199, -76, -266, -322, -184, -428, -49, +-456, 80, -235, 234, 167, 318, 487, 246, +692, 143, 616, 23, 225, -150, -235, -223, +-554, -161, -606, -134, -334, -101, 16, -37, +290, -28, 446, -12, 425, 48, 296, 88, +181, 191, -8, 294, -240, 226, -396, 110, +-400, 37, -245, -149, 46, -396, 320, -561, +436, -568, 368, -297, 289, 179, 231, 597, +68, 868, -146, 885, -285, 511, -393, -117, +-394, -713, -259, -1064, -73, -1023, 181, -627, +442, -17, 534, 641, 503, 1081, 353, 1101, +85, 732, -136, 80, -287, -587, -382, -958, +-316, -937, -244, -577, -244, -46, -92, 368, +159, 560, 372, 556, 593, 347, 626, 46, +350, -150, 25, -215, -224, -175, -358, -51, +-311, 83, -210, 140, -156, 42, -135, -194, +-138, -393, 7, -448, 283, -295, 441, 104, +479, 574, 440, 844, 224, 801, -33, 404, +-226, -254, -382, -879, -406, -1168, -301, -958, +-186, -313, 20, 416, 258, 951, 386, 1153, +418, 866, 349, 183, 192, -481, 43, -854, +-155, -879, -307, -601, -254, -166, -145, 291, +-70, 677, 56, 788, 143, 547, 172, 146, +215, -258, 209, -620, 149, -768, 63, -553, +-71, -70, -140, 457, -120, 814, -122, 753, +-102, 261, -7, -331, 124, -746, 284, -863, +407, -497, 423, 231, 261, 850, -189, 1037, +-676, 694, -766, -107, -474, -867, -9, -1156, +538, -984, 935, -339, 977, 641, 640, 1311, +23, 1296, -601, 737, -933, -161, -922, -1011, +-561, -1358, 27, -1139, 582, -438, 921, 509, +906, 1169, 447, 1262, -135, 865, -489, 51, +-547, -808, -342, -1223, 32, -1102, 321, -528, +408, 360, 275, 1130, -41, 1381, -383, 998, +-506, 95, -378, -925, -84, -1550, 337, -1504, +826, -766, 1054, 389, 790, 1445, 160, 1882, +-575, 1447, -1158, 359, -1256, -871, -827, -1774, +-90, -1875, 675, -1054, 1187, 205, 1244, 1297, +850, 1771, 119, 1352, -588, 306, -888, -818, +-741, -1562, -330, -1471, 178, -555, 503, 551, +466, 1404, 166, 1670, -179, 1039, -372, -135, +-281, -1227, 17, -1893, 354, -1720, 600, -698, +632, 577, 394, 1644, -36, 2112, -516, 1587, +-843, 385, -776, -848, -303, -1716, 286, -1845, +731, -1147, 901, -39, 647, 1024, 76, 1558, +-402, 1289, -613, 450, -580, -577, -225, -1344, +258, -1350, 550, -644, 660, 342, 577, 1265, +175, 1707, -305, 1340, -629, 299, -814, -964, +-744, -1842, -306, -1967, 359, -1422, 1021, -339, +1286, 1029, 993, 2019, 440, 2144, -203, 1479, +-889, 374, -1206, -793, -967, -1637, -490, -1806, +18, -1263, 525, -433, 867, 327, 955, 907, +806, 1106, 445, 892, -48, 546, -517, 158, +-771, -236, -722, -497, -491, -608, -135, -567, +316, -407, 618, -254, 652, -15, 568, 347, +355, 636, -39, 810, -411, 815, -591, 415, +-557, -270, -279, -983, 167, -1524, 574, -1466, +721, -692, 530, 381, 147, 1433, -248, 2092, +-495, 1908, -456, 950, -235, -352, -24, -1553, +244, -2168, 467, -1995, 385, -1152, 156, 79, +-16, 1148, -233, 1611, -319, 1500, -99, 967, +198, 239, 418, -327, 511, -581, 284, -577, +-128, -439, -448, -364, -629, -386, -607, -452, +-302, -520, 164, -400, 702, 39, 1085, 643, +1045, 1203, 581, 1458, -142, 1193, -892, 425, +-1250, -642, -1061, -1589, -466, -1899, 360, -1465, +1054, -546, 1201, 572, 848, 1419, 225, 1565, +-427, 1092, -826, 321, -804, -472, -415, -984, +205, -957, 766, -471, 973, 136, 673, 604, +8, 735, -699, 368, -1132, -304, -1063, -865, +-376, -1045, 582, -672, 1286, 223, 1464, 1135, +1033, 1582, 165, 1401, -626, 538, -1117, -699, +-1282, -1692, -927, -2045, -174, -1567, 540, -377, +1027, 947, 1141, 1873, 793, 2123, 189, 1498, +-415, 227, -763, -1065, -580, -1834, -44, -1781, +396, -1019, 570, 31, 399, 1006, -136, 1467, +-715, 1108, -979, 270, -743, -508, 47, -967, +1082, -887, 1782, -252, 1769, 526, 983, 999, +-347, 936, -1639, 340, -2284, -509, -2012, -1187, +-918, -1317, 554, -854, 1741, -49, 2293, 822, +2152, 1432, 1236, 1452, -241, 871, -1573, -80, +-2204, -1021, -1950, -1512, -864, -1414, 561, -788, +1607, 292, 1888, 1317, 1313, 1662, 185, 1241, +-789, 257, -1148, -919, -962, -1672, -413, -1686, +237, -1000, 706, 211, 940, 1376, 883, 1904, +346, 1700, -441, 825, -938, -423, -939, -1410, +-549, -1819, 104, -1633, 730, -837, 969, 219, +759, 1010, 294, 1395, -201, 1355, -497, 821, +-516, 40, -371, -603, -79, -913, 318, -856, +586, -488, 535, 42, 130, 456, -424, 522, +-668, 223, -431, -252, 23, -594, 493, -613, +777, -287, 606, 304, 193, 883, -117, 1101, +-345, 886, -465, 322, -364, -500, -195, -1192, +22, -1341, 352, -993, 562, -322, 456, 461, +144, 998, -258, 1085, -493, 713, -348, 51, +10, -477, 337, -641, 590, -546, 615, -163, +328, 442, -51, 768, -342, 585, -607, 103, +-761, -550, -585, -1176, -44, -1350, 585, -891, +978, 15, 984, 1054, 642, 1802, 92, 1863, +-380, 1203, -602, 110, -576, -1041, -386, -1874, +-130, -2072, 67, -1499, 195, -353, 296, 854, +325, 1626, 196, 1763, 21, 1259, 18, 285, +219, -717, 397, -1306, 408, -1260, 244, -601, +-122, 308, -559, 968, -769, 1148, -695, 782, +-405, -103, 91, -1138, 637, -1777, 986, -1636, +1049, -653, 806, 709, 320, 1853, -274, 2472, +-817, 2249, -1038, 1003, -806, -696, -339, -2041, +205, -2710, 716, -2542, 862, -1500, 582, -6, +165, 1357, -226, 2154, -425, 2204, -243, 1625, +144, 722, 465, -166, 567, -803, 332, -1148, +-99, -1256, -495, -1141, -758, -901, -710, -625, +-350, -207, 77, 342, 532, 813, 957, 1095, +1107, 1244, 955, 1232, 543, 886, -170, 263, +-880, -444, -1198, -1173, -1153, -1721, -796, -1778, +-151, -1315, 570, -512, 1097, 490, 1288, 1394, +1120, 1827, 661, 1719, -15, 1131, -697, 239, +-1083, -634, -1047, -1265, -638, -1472, -27, -1210, +532, -670, 866, -36, 890, 551, 604, 875, +152, 869, -303, 665, -626, 277, -659, -203, +-432, -523, -33, -636, 511, -535, 895, -189, +823, 208, 476, 492, 56, 650, -429, 598, +-800, 253, -896, -276, -718, -792, -252, -1082, +381, -987, 929, -539, 1268, 148, 1186, 892, +659, 1335, -9, 1274, -656, 861, -1165, 247, +-1190, -492, -756, -1114, -226, -1357, 364, -1212, +960, -794, 1169, -123, 961, 638, 595, 1118, +41, 1173, -597, 896, -891, 395, -754, -169, +-423, -586, 8, -723, 498, -623, 824, -407, +816, -184, 454, 45, -94, 247, -571, 264, +-787, 165, -657, 122, -181, 93, 426, 54, +908, 15, 1028, -67, 705, -151, 164, -115, +-307, -19, -657, 81, -849, 249, -744, 256, +-380, -23, 103, -312, 616, -465, 978, -478, +997, -307, 654, 14, 133, 364, -358, 607, +-649, 618, -678, 424, -543, 153, -339, -263, +25, -687, 516, -784, 885, -613, 978, -254, +751, 290, 174, 749, -526, 871, -1016, 622, +-1171, 66, -895, -566, -222, -978, 554, -1068, +1237, -688, 1678, 160, 1624, 989, 1016, 1471, +-48, 1432, -1258, 710, -2065, -379, -2234, -1381, +-1806, -1988, -693, -1890, 918, -1055, 2337, 168, +3078, 1411, 2925, 2290, 1783, 2378, 7, 1642, +-1840, 314, -3174, -1241, -3432, -2419, -2501, -2825, +-799, -2275, 1148, -835, 2733, 849, 3403, 2186, +2995, 2879, 1654, 2574, -211, 1326, -1823, -337, +-2599, -1892, -2483, -2744, -1569, -2555, -122, -1602, +1150, -158, 1677, 1398, 1580, 2245, 1083, 2181, +270, 1556, -441, 422, -630, -823, -443, -1543, +-113, -1676, 273, -1312, 425, -587, 184, 173, +-269, 768, -710, 985, -908, 745, -538, 426, +335, 193, 1256, -96, 1800, -203, 1654, -29, +760, 12, -599, -106, -1844, -292, -2418, -663, +-2054, -973, -826, -906, 871, -390, 2395, 428, +3130, 1232, 2755, 1789, 1354, 1786, -644, 1011, +-2468, -204, -3340, -1317, -3036, -2101, -1735, -2332, +282, -1773, 2292, -643, 3361, 746, 3255, 1988, +2185, 2501, 337, 2249, -1558, 1337, -2577, -124, +-2592, -1499, -1849, -2232, -522, -2250, 818, -1579, +1628, -405, 1778, 763, 1354, 1556, 613, 1838, +-68, 1480, -562, 638, -782, -407, -608, -1236, +-251, -1460, 30, -1193, 242, -536, 391, 397, +398, 1104, 312, 1316, 214, 1093, -51, 428, +-452, -541, -641, -1338, -557, -1687, -333, -1466, +201, -634, 954, 488, 1436, 1574, 1435, 2194, +988, 1929, 79, 1031, -961, -180, -1738, -1500, +-2042, -2388, -1597, -2429, -453, -1713, 885, -416, +1999, 1154, 2490, 2308, 2079, 2598, 978, 1994, +-501, 670, -1837, -861, -2304, -2102, -1766, -2551, +-641, -1891, 764, -547, 1962, 858, 2222, 1955, +1463, 2282, 127, 1588, -1355, 199, -2353, -1286, +-2210, -2287, -948, -2331, 792, -1415, 2376, 107, +3191, 1720, 2680, 2684, 1019, 2560, -1013, 1502, +-2729, -177, -3479, -1869, -2849, -2856, -1150, -2823, +897, -1819, 2638, -179, 3413, 1483, 2921, 2540, +1389, 2649, -530, 1889, -1927, 577, -2381, -798, +-2060, -1774, -1044, -2087, 421, -1717, 1550, -888, +1864, 115, 1431, 910, 453, 1223, -644, 1162, +-1316, 811, -1345, 252, -809, -289, 194, -610, +1272, -738, 1788, -728, 1471, -397, 693, 94, +-178, 384, -1094, 573, -1727, 643, -1618, 334, +-828, -187, 213, -520, 1063, -693, 1524, -740, +1489, -427, 878, 40, 57, 409, -532, 773, +-832, 997, -764, 903, -267, 449, 174, -211, +344, -847, 502, -1339, 457, -1489, 74, -1047, +-286, -141, -477, 731, -531, 1355, -321, 1623, +89, 1216, 567, 372, 1008, -438, 1136, -1068, +856, -1363, 338, -1128, -238, -480, -770, 186, +-1124, 655, -1175, 901, -849, 819, -292, 377, +320, -249, 888, -690, 1196, -812, 1223, -665, +1111, -245, 719, 378, 118, 987, -366, 1183, +-734, 864, -1056, 345, -1207, -393, -1081, -1317, +-699, -1903, -52, -1800, 799, -1168, 1593, -93, +1935, 1326, 1680, 2487, 1070, 2854, 84, 2338, +-1093, 1031, -1756, -767, -1754, -2557, -1474, -3642, +-811, -3558, 297, -2414, 1331, -507, 1852, 1739, +1806, 3562, 1333, 4295, 553, 3735, -382, 2046, +-1120, -394, -1375, -2842, -1244, -4394, -880, -4545, +-331, -3347, 259, -1113, 764, 1518, 1125, 3570, +1298, 4372, 1279, 3892, 979, 2262, 424, -37, +-225, -2128, -1059, -3448, -1888, -3744, -2139, -2947, +-1645, -1398, -631, 443, 826, 2018, 2365, 2842, +3287, 2886, 3221, 2270, 2046, 1036, 66, -440, +-2056, -1636, -3661, -2397, -4151, -2598, -3202, -2096, +-1093, -1089, 1519, 266, 3807, 1579, 4867, 2338, +4266, 2515, 2285, 2020, -422, 760, -3022, -697, +-4587, -1792, -4546, -2430, -2975, -2385, -474, -1466, +2179, -169, 4184, 1043, 4782, 1919, 3696, 2078, +1351, 1542, -1374, 656, -3446, -334, -4185, -1122, +-3488, -1435, -1556, -1299, 809, -943, 2649, -382, +3565, 273, 3415, 657, 2077, 689, 44, 681, +-1740, 701, -2783, 503, -2885, 194, -2033, 28, +-505, -221, 1173, -700, 2318, -1085, 2546, -1120, +2015, -956, 976, -564, -355, 248, -1468, 1188, +-1939, 1789, -1775, 1858, -1074, 1344, 41, 335, +1135, -901, 1760, -1989, 1816, -2510, 1368, -2087, +443, -974, -688, 289, -1503, 1477, -1759, 2241, +-1457, 2194, -612, 1409, 567, 303, 1634, -651, +2163, -1315, 1922, -1619, 1141, -1350, 24, -662, +-1276, -139, -2194, 85, -2274, 258, -1668, 327, +-515, 329, 1108, 488, 2406, 790, 2746, 1123, +2267, 1098, 1089, 531, -492, -202, -1766, -1048, +-2306, -2041, -2130, -2465, -1311, -1920, -125, -821, +1032, 631, 1874, 2207, 2130, 3177, 1650, 3072, +674, 1840, -376, -77, -1099, -1875, -1291, -3105, +-1045, -3464, -609, -2529, -125, -716, 379, 1067, +774, 2441, 920, 3060, 852, 2601, 634, 1349, +240, -252, -209, -1667, -565, -2401, -702, -2419, +-583, -1747, -377, -436, -100, 898, 383, 1661, +890, 1878, 1051, 1622, 924, 863, 518, -101, +-209, -930, -832, -1355, -1044, -1344, -881, -1110, +-403, -677, 206, -64, 681, 502, 1005, 896, +1091, 1117, 748, 1170, 158, 916, -371, 323, +-781, -350, -850, -872, -457, -1289, 129, -1452, +620, -1080, 815, -374, 591, 288, 121, 837, +-302, 1165, -585, 1173, -580, 889, -197, 367, +332, -115, 762, -359, 1016, -608, 889, -878, +322, -908, -300, -758, -734, -632, -909, -439, +-791, 14, -392, 641, 122, 1143, 551, 1367, +762, 1299, 799, 956, 800, 286, 623, -600, +213, -1448, -117, -1961, -283, -1904, -560, -1385, +-884, -531, -850, 592, -481, 1610, -45, 2233, +519, 2277, 1090, 1615, 1309, 450, 1158, -787, +777, -1803, 163, -2379, -546, -2241, -1090, -1451, +-1412, -326, -1327, 837, -719, 1596, 228, 1856, +1222, 1731, 1828, 1131, 1756, 200, 1215, -616, +353, -1076, -742, -1281, -1471, -1257, -1588, -861, +-1337, -230, -687, 233, 359, 325, 1261, 387, +1607, 491, 1466, 353, 975, 299, 301, 593, +-402, 743, -886, 510, -929, 159, -780, -324, +-628, -1053, -274, -1658, 189, -1786, 501, -1311, +728, -394, 903, 644, 835, 1753, 562, 2586, +312, 2478, 67, 1568, -220, 343, -511, -1173, +-721, -2651, -800, -3265, -590, -2863, -177, -1693, +107, 87, 334, 1894, 715, 3135, 997, 3440, +994, 2553, 929, 960, 726, -693, 243, -2176, +-340, -3050, -864, -2836, -1285, -1852, -1456, -544, +-1290, 921, -816, 1986, 28, 2239, 1131, 1878, +2178, 984, 2760, -179, 2509, -1026, 1436, -1232, +-140, -868, -1801, -335, -3015, 53, -3331, 258, +-2605, 119, -1071, -379, 894, -835, 2754, -934, +3775, -684, 3578, 56, 2271, 1172, 310, 2032, +-1680, 2309, -3002, 1927, -3249, 694, -2462, -1123, +-967, -2793, 731, -3553, 2105, -3194, 2707, -1984, +2369, -84, 1300, 2070, -57, 3618, -1225, 4006, +-1771, 3192, -1560, 1485, -731, -596, 408, -2455, +1243, -3652, 1425, -3695, 1099, -2525, 336, -899, +-742, 659, -1522, 1917, -1595, 2502, -998, 2400, +193, 1748, 1556, 821, 2369, 33, 2403, -495, +1709, -923, 322, -1276, -1443, -1499, -2841, -1630, +-3216, -1552, -2581, -1144, -1125, -391, 1030, 801, +3215, 1977, 4276, 2584, 3812, 2601, 2235, 1978, +-132, 695, -2624, -856, -4195, -2189, -4267, -3017, +-2977, -3122, -729, -2338, 1856, -889, 3858, 821, +4472, 2327, 3607, 3131, 1635, 2905, -870, 1831, +-2880, 466, -3603, -965, -3147, -2137, -1849, -2381, +35, -1874, 1826, -1157, 2846, -224, 2973, 757, +2212, 1219, 680, 1181, -976, 949, -2081, 438, +-2318, -172, -1729, -500, -587, -522, 698, -285, +1571, 72, 1754, 433, 1418, 571, 861, 213, +111, -356, -718, -747, -1231, -1021, -1258, -1095, +-901, -646, -329, 114, 316, 669, 803, 1049, +1023, 1246, 1106, 1123, 1096, 800, 823, 320, +239, -241, -389, -757, -902, -1257, -1403, -1577, +-1657, -1579, -1227, -1314, -364, -737, 490, 272, +1414, 1401, 2259, 2229, 2476, 2674, 1983, 2449, +987, 1361, -431, -156, -1907, -1778, -2877, -3175, +-3121, -3730, -2551, -3153, -1149, -1718, 721, 222, +2597, 2319, 4004, 3873, 4459, 4203, 3520, 3234, +1338, 1345, -1273, -858, -3610, -2882, -5048, -4089, +-4928, -3863, -3221, -2457, -637, -569, 2225, 1316, +4665, 2700, 5711, 3169, 5026, 2649, 2932, 1471, +-53, 72, -3025, -1098, -4993, -1827, -5406, -2126, +-4144, -1889, -1665, -1175, 1125, -257, 3425, 654, +4665, 1319, 4562, 1659, 3256, 1588, 1061, 1056, +-1351, 244, -3051, -637, -3651, -1374, -3259, -1766, +-2018, -1733, -333, -1236, 1172, -220, 2182, 1089, +2609, 2100, 2505, 2524, 1817, 2202, 693, 999, +-310, -713, -1029, -2333, -1735, -3330, -2136, -3282, +-1775, -2173, -1111, -282, -458, 1901, 559, 3578, +1725, 4013, 2434, 3239, 2541, 1562, 2108, -712, +1080, -2759, -397, -3822, -1836, -3802, -2796, -2805, +-3074, -1096, -2457, 800, -982, 2299, 801, 3118, +2359, 3165, 3436, 2461, 3596, 1226, 2674, -184, +1070, -1374, -848, -2170, -2633, -2529, -3574, -2324, +-3448, -1705, -2464, -891, -716, 33, 1302, 984, +2844, 1793, 3534, 2244, 3320, 2258, 2238, 1853, +546, 1075, -1171, 27, -2362, -1149, -2836, -2095, +-2611, -2583, -1610, -2560, -207, -1981, 926, -934, +1743, 373, 2259, 1614, 2117, 2470, 1405, 2815, +604, 2522, -207, 1578, -1030, 194, -1554, -1197, +-1587, -2246, -1213, -2774, -570, -2615, 142, -1831, +803, -663, 1266, 654, 1425, 1755, 1301, 2400, +898, 2439, 231, 1803, -552, 700, -1227, -565, +-1576, -1713, -1407, -2337, -686, -2137, 366, -1272, +1295, -83, 1834, 1200, 1934, 2075, 1435, 2107, +386, 1323, -821, -2, -1793, -1387, -2290, -2327, +-2005, -2491, -1002, -1682, 257, -136, 1474, 1541, +2399, 2762, 2660, 3186, 2098, 2632, 969, 1136, +-313, -881, -1482, -2722, -2295, -3807, -2463, -3889, +-1915, -2837, -911, -740, 185, 1566, 1181, 3304, +1971, 4208, 2369, 3927, 2134, 2393, 1415, 293, +591, -1657, -316, -3030, -1226, -3501, -1788, -2991, +-1898, -1808, -1763, -411, -1392, 702, -618, 1371, +446, 1683, 1377, 1652, 2023, 1496, 2506, 1417, +2486, 1202, 1695, 738, 590, 49, -512, -927, +-1804, -2010, -2935, -2803, -3229, -3075, -2610, -2553, +-1331, -1137, 330, 730, 2057, 2541, 3439, 3878, +3925, 4238, 3361, 3412, 1982, 1518, -17, -927, +-2153, -3098, -3642, -4426, -4111, -4628, -3514, -3448, +-1780, -1165, 598, 1292, 2658, 3197, 3817, 4174, +3920, 3873, 3034, 2450, 1327, 485, -745, -1379, +-2470, -2629, -3364, -3077, -3302, -2669, -2221, -1557, +-471, -272, 1210, 799, 2416, 1562, 2921, 1868, +2495, 1606, 1392, 1057, 195, 443, -861, -186, +-1715, -641, -2060, -897, -1667, -1063, -850, -1057, +-94, -852, 654, -497, 1372, -82, 1525, 342, +1119, 758, 717, 1052, 371, 1082, -104, 889, +-469, 588, -573, 168, -594, -396, -577, -969, +-524, -1380, -405, -1477, -211, -1278, -25, -826, +284, -48, 722, 889, 1028, 1650, 1132, 2055, +1084, 1945, 745, 1315, 148, 308, -483, -905, +-1086, -1978, -1490, -2473, -1463, -2299, -1097, -1580, +-511, -426, 326, 834, 1174, 1749, 1699, 2162, +1862, 2060, 1670, 1515, 1060, 671, 136, -291, +-763, -1077, -1419, -1533, -1780, -1709, -1700, -1501, +-1144, -962, -376, -373, 366, 182, 1017, 690, +1476, 955, 1590, 1034, 1354, 1105, 850, 1021, +298, 692, -124, 331, -492, -33, -871, -563, +-1182, -1202, -1245, -1606, -1041, -1585, -671, -1254, +-100, -697, 681, 121, 1318, 1017, 1523, 1656, +1519, 1867, 1316, 1698, 686, 1270, -118, 579, +-795, -440, -1398, -1431, -1707, -2016, -1405, -2238, +-737, -1998, -13, -1061, 733, 220, 1262, 1284, +1326, 1970, 1105, 2171, 778, 1700, 339, 789, +-81, -136, -386, -824, -579, -1186, -583, -1232, +-492, -1018, -459, -667, -417, -390, -301, -265, +-170, -153, 69, 122, 508, 522, 969, 968, +1323, 1363, 1407, 1505, 1029, 1199, 250, 384, +-702, -743, -1551, -1799, -2005, -2452, -1881, -2421, +-1190, -1588, -16, -133, 1306, 1463, 2286, 2667, +2608, 3054, 2200, 2398, 1213, 955, -128, -715, +-1543, -2148, -2551, -2927, -2781, -2790, -2240, -1759, +-1040, -223, 594, 1199, 2071, 2118, 2849, 2428, +2843, 1993, 2125, 889, 817, -325, -648, -1133, +-1762, -1519, -2391, -1458, -2465, -887, -1806, -154, +-666, 285, 456, 358, 1425, 205, 2049, -48, +1890, -219, 1289, -64, 818, 390, 293, 906, +-325, 1271, -710, 1243, -935, 664, -1193, -290, +-1253, -1312, -956, -2087, -501, -2244, -59, -1669, +432, -637, 1023, 584, 1474, 1701, 1594, 2305, +1465, 2198, 996, 1538, 119, 577, -791, -468, +-1385, -1329, -1636, -1712, -1483, -1629, -958, -1294, +-293, -752, 351, -91, 851, 415, 1139, 694, +1233, 839, 1068, 836, 613, 751, 141, 706, +-72, 576, -182, 305, -337, -18, -371, -426, +-302, -870, -445, -1120, -690, -1087, -707, -828, +-582, -419, -376, 72, 36, 479, 586, 641, +1118, 626, 1526, 611, 1680, 586, 1480, 567, +882, 618, -100, 566, -1125, 233, -1872, -338, +-2342, -997, -2316, -1527, -1564, -1767, -408, -1578, +799, -841, 1996, 239, 2877, 1168, 2940, 1775, +2184, 2049, 997, 1726, -387, 899, -1734, 30, +-2549, -692, -2533, -1138, -1888, -1244, -915, -1132, +175, -879, 1123, -604, 1560, -487, 1432, -432, +1080, -219, 702, 174, 259, 712, -23, 1366, +57, 1870, 146, 1992, 75, 1611, 18, 666, +-240, -622, -824, -1841, -1336, -2673, -1527, -2885, +-1386, -2371, -749, -1264, 319, 63, 1463, 1292, +2379, 2232, 2733, 2690, 2312, 2554, 1260, 1973, +-95, 1153, -1362, 134, -2219, -1000, -2534, -1983, +-2344, -2635, -1639, -2895, -521, -2660, 575, -1762, +1358, -308, 1963, 1233, 2301, 2549, 2024, 3469, +1353, 3555, 698, 2624, -100, 1105, -1098, -563, +-1821, -2158, -2054, -3264, -1930, -3441, -1355, -2723, +-337, -1463, 710, -3, 1366, 1304, 1637, 2147, +1591, 2362, 1063, 2043, 296, 1406, -164, 636, +-333, -77, -418, -633, -246, -1050, 72, -1306, +83, -1383, -200, -1284, -582, -1003, -1011, -502, +-1235, 183, -1026, 867, -382, 1325, 603, 1427, +1574, 1163, 2081, 626, 2078, -35, 1603, -639, +587, -970, -578, -872, -1331, -501, -1671, -65, +-1777, 337, -1491, 480, -801, 233, -168, -224, +168, -695, 453, -1006, 846, -847, 1191, -155, +1443, 701, 1660, 1451, 1706, 1864, 1276, 1637, +294, 818, -936, -268, -2054, -1312, -2789, -2041, +-2908, -2219, -2282, -1747, -1000, -837, 617, 218, +2140, 1210, 3107, 1881, 3274, 1986, 2708, 1586, +1599, 890, 190, 21, -1214, -758, -2238, -1184, +-2625, -1342, -2504, -1268, -2071, -896, -1232, -424, +-44, -103, 1007, 153, 1744, 514, 2342, 872, +2536, 1025, 2015, 986, 1102, 843, 145, 521, +-878, -74, -1756, -687, -2110, -1043, -1881, -1160, +-1309, -1079, -634, -751, 81, -247, 735, 230, +1049, 589, 1062, 879, 1136, 996, 1178, 902, +953, 702, 647, 327, 299, -224, -254, -697, +-836, -991, -1252, -1134, -1532, -978, -1503, -497, +-1005, 44, -250, 542, 565, 952, 1341, 1056, +1818, 844, 1703, 474, 993, 4, 128, -453, +-533, -774, -931, -875, -980, -710, -625, -372, +-102, -27, 234, 278, 240, 505, 57, 571, +-150, 497, -402, 378, -562, 229, -352, 45, +112, -175, 580, -404, 1026, -613, 1273, -786, +1079, -798, 556, -519, -111, 9, -709, 659, +-1044, 1281, -1215, 1605, -1183, 1370, -762, 616, +-246, -452, 97, -1529, 498, -2183, 944, -2128, +1123, -1330, 1090, -38, 1035, 1255, 881, 2134, +463, 2360, -209, 1812, -867, 624, -1352, -666, +-1693, -1551, -1724, -1914, -1193, -1735, -244, -1022, +716, -36, 1490, 767, 1989, 1081, 2017, 1052, +1473, 832, 585, 375, -299, -112, -1029, -301, +-1491, -294, -1579, -295, -1344, -249, -890, -194, +-284, -199, 347, -174, 896, -123, 1237, -32, +1241, 126, 954, 254, 532, 276, 92, 179, +-272, -5, -506, -149, -616, -168, -611, -116, +-479, 35, -303, 270, -184, 330, -66, 196, +89, 26, 173, -221, 173, -468, 272, -527, +470, -380, 567, -122, 521, 110, 395, 280, +204, 381, -101, 333, -478, 196, -750, 126, +-806, 90, -681, 88, -375, 173, 91, 158, +570, -62, 898, -332, 869, -646, 457, -942, +-15, -945, -370, -621, -590, -50, -432, 736, +69, 1434, 470, 1743, 596, 1580, 512, 872, +161, -219, -427, -1258, -956, -1947, -1103, -2099, +-851, -1614, -378, -652, 305, 461, 1099, 1374, +1549, 1828, 1428, 1774, 931, 1194, 182, 264, +-628, -590, -1203, -1103, -1426, -1225, -1199, -958, +-620, -423, 0, 165, 556, 587, 946, 645, +936, 334, 627, -100, 255, -489, -129, -727, +-319, -604, -191, -99, 7, 605, 132, 1213, +188, 1373, 79, 1058, -202, 400, -498, -533, +-618, -1405, -483, -1758, -191, -1534, 178, -930, +531, -85, 654, 783, 545, 1357, 372, 1411, +118, 1013, -107, 487, -120, -13, -76, -437, +-91, -563, -75, -360, -115, -150, -239, -101, +-338, -146, -454, -324, -463, -616, -191, -802, +146, -719, 375, -271, 670, 447, 934, 1134, +818, 1569, 456, 1606, 175, 1181, -86, 408, +-465, -527, -775, -1358, -859, -1782, -884, -1745, +-872, -1409, -585, -766, -98, 134, 358, 889, +865, 1304, 1413, 1522, 1646, 1502, 1431, 1188, +952, 709, 187, 104, -847, -597, -1736, -1243, +-2125, -1717, -2016, -1875, -1425, -1556, -399, -760, +745, 309, 1628, 1296, 2034, 1894, 1903, 1983, +1361, 1493, 615, 514, -209, -525, -899, -1202, +-1211, -1409, -1202, -1142, -1080, -480, -818, 231, +-382, 605, -10, 519, 198, 126, 401, -328, +637, -660, 791, -646, 843, -172, 817, 509, +681, 1116, 418, 1478, -1, 1294, -526, 532, +-935, -469, -1130, -1394, -1139, -1922, -884, -1777, +-429, -1028, 56, 16, 516, 1013, 884, 1638, +1084, 1663, 1111, 1087, 914, 179, 518, -615, +100, -1031, -301, -1033, -669, -556, -890, 170, +-983, 646, -965, 723, -720, 424, -318, -215, +150, -824, 636, -1039, 918, -849, 937, -288, +841, 513, 594, 1185, 236, 1432, 8, 1145, +-152, 451, -383, -327, -575, -996, -677, -1346, +-730, -1128, -693, -509, -512, 69, -194, 471, +148, 711, 490, 595, 892, 182, 1168, -117, +1125, -139, 870, -12, 415, 192, -335, 467, +-1046, 578, -1339, 238, -1289, -389, -982, -936, +-409, -1216, 304, -1081, 893, -480, 1111, 408, +932, 1239, 517, 1649, -1, 1450, -418, 740, +-536, -244, -370, -1170, -14, -1680, 373, -1613, +538, -1018, 371, -61, 0, 921, -442, 1542, +-794, 1616, -934, 1200, -844, 459, -415, -404, +306, -1161, 916, -1519, 1204, -1303, 1210, -754, +842, -173, 169, 426, -417, 919, -706, 1051, +-769, 891, -612, 679, -295, 454, -62, 158, +-68, -199, -202, -603, -325, -981, -388, -1171, +-246, -1118, 171, -801, 729, -166, 1266, 620, +1606, 1258, 1499, 1574, 839, 1465, -251, 917, +-1437, 105, -2234, -668, -2389, -1163, -1995, -1342, +-1079, -1177, 254, -682, 1435, -133, 2104, 249, +2391, 514, 2198, 686, 1329, 690, 167, 621, +-717, 563, -1293, 387, -1746, 99, -1870, -187, +-1474, -508, -915, -783, -484, -834, 90, -679, +888, -378, 1432, 54, 1587, 476, 1616, 734, +1402, 785, 773, 618, -23, 282, -754, -118, +-1386, -452, -1716, -603, -1595, -525, -1186, -250, +-642, 82, 20, 334, 692, 425, 1171, 305, +1306, 27, 1146, -253, 892, -403, 573, -389, +130, -224, -216, 43, -296, 281, -393, 447, +-699, 499, -1001, 330, -1114, 26, -1059, -216, +-859, -383, -389, -483, 381, -417, 1161, -132, +1683, 228, 1947, 442, 1855, 476, 1206, 410, +129, 111, -988, -419, -1894, -781, -2408, -766, +-2316, -521, -1585, -45, -484, 634, 618, 1161, +1572, 1277, 2203, 1013, 2221, 409, 1652, -425, +726, -1247, -350, -1749, -1202, -1699, -1555, -1191, +-1476, -399, -1028, 660, -344, 1654, 194, 2096, +389, 1976, 416, 1427, 359, 430, 180, -744, +-31, -1669, -32, -2161, 262, -2127, 620, -1494, +838, -442, 826, 680, 449, 1570, -246, 2005, +-974, 1867, -1499, 1193, -1588, 194, -1118, -739, +-328, -1306, 453, -1401, 1137, -1030, 1634, -356, +1658, 338, 1060, 722, 171, 644, -564, 307, +-1126, -116, -1430, -565, -1145, -762, -448, -464, +194, 126, 659, 699, 868, 1127, 708, 1269, +340, 944, -60, 159, -446, -763, -661, -1399, +-540, -1607, -191, -1397, 194, -741, 470, 166, +597, 930, 566, 1340, 384, 1323, 163, 878, +-65, 285, -362, -201, -671, -523, -864, -544, +-854, -305, -623, -73, -220, 8, 317, -112, +879, -382, 1227, -583, 1275, -582, 1089, -418, +620, -53, -166, 498, -992, 944, -1494, 1076, +-1559, 967, -1266, 677, -625, 211, 258, -305, +943, -694, 1155, -892, 1095, -998, 878, -1038, +392, -865, -151, -456, -357, 18, -281, 543, +-214, 1139, -148, 1534, -56, 1473, -170, 1085, +-540, 519, -811, -283, -767, -1130, -496, -1634, +10, -1686, 683, -1330, 1206, -633, 1341, 189, +1097, 876, 642, 1251, 107, 1231, -459, 863, +-914, 374, -1108, 12, -1078, -174, -910, -228, +-619, -188, -248, -167, 119, -272, 485, -494, +828, -733, 1060, -862, 1164, -729, 1171, -244, +982, 431, 430, 1016, -409, 1369, -1222, 1408, +-1787, 1017, -1981, 272, -1683, -500, -927, -1046, +77, -1344, 1031, -1319, 1733, -903, 2069, -296, +1902, 266, 1264, 684, 406, 894, -452, 927, +-1149, 800, -1511, 463, -1590, 38, -1470, -298, +-1035, -551, -408, -657, 184, -541, 776, -329, +1305, -93, 1488, 154, 1330, 264, 1029, 166, +553, 38, -100, 9, -664, 20, -1025, 44, +-1266, 140, -1281, 304, -941, 366, -465, 210, +-72, 2, 344, -196, 761, -481, 985, -677, +1071, -571, 1041, -245, 745, 118, 237, 460, +-255, 724, -603, 740, -813, 468, -922, 54, +-890, -381, -699, -684, -426, -672, -119, -417, +250, -113, 582, 217, 753, 462, 826, 472, +869, 365, 816, 240, 573, 46, 147, -139, +-374, -260, -898, -360, -1283, -389, -1371, -329, +-1130, -255, -639, -94, 29, 146, 751, 338, +1314, 531, 1549, 709, 1407, 698, 901, 456, +141, 60, -618, -445, -1080, -972, -1203, -1274, +-1094, -1163, -797, -714, -354, -51, 151, 723, +579, 1335, 777, 1540, 786, 1329, 673, 775, +376, -7, 28, -748, -164, -1244, -276, -1429, +-411, -1240, -444, -732, -361, -106, -268, 468, +-86, 868, 195, 1033, 397, 934, 413, 599, +298, 242, 89, 11, -225, -187, -497, -352, +-559, -440, -431, -550, -69, -624, 500, -556, +901, -413, 894, -152, 637, 235, 200, 570, +-405, 782, -925, 813, -1138, 588, -1037, 242, +-705, -83, -193, -411, 472, -612, 1049, -519, +1249, -322, 1119, -197, 750, -44, 130, 83, +-464, 39, -801, -51, -978, -9, -987, 75, +-719, 146, -285, 373, 197, 621, 627, 579, +809, 375, 670, 100, 318, -396, 11, -892, +-88, -1039, -121, -861, -129, -457, -49, 114, +-46, 664, -150, 999, -157, 982, -102, 607, +-180, 100, -327, -356, -327, -649, -126, -594, +149, -231, 380, 158, 596, 402, 636, 400, +330, 69, -50, -441, -260, -832, -402, -886, +-464, -488, -348, 222, -116, 943, 134, 1427, +284, 1457, 256, 943, 62, 24, -249, -959, +-480, -1599, -433, -1708, -183, -1299, 175, -466, +619, 530, 921, 1291, 898, 1548, 596, 1295, +72, 663, -555, -128, -1075, -778, -1336, -1043, +-1220, -874, -716, -415, -2, 141, 664, 575, +1113, 643, 1254, 332, 1081, -128, 701, -528, +262, -730, -172, -571, -591, -54, -865, 581, +-930, 1053, -919, 1157, -792, 835, -477, 152, +-85, -692, 305, -1311, 726, -1426, 1130, -1073, +1325, -386, 1133, 489, 643, 1228, 51, 1442, +-643, 1097, -1320, 460, -1618, -269, -1414, -861, +-859, -1076, -110, -864, 649, -356, 1212, 198, +1407, 593, 1124, 749, 553, 603, -10, 193, +-470, -223, -747, -454, -748, -546, -536, -467, +-259, -161, -33, 160, 138, 354, 229, 479, +170, 507, 50, 397, 54, 199, 75, -62, +5, -330, -4, -540, 52, -679, 70, -670, +92, -409, 154, 17, 166, 455, 40, 808, +-115, 982, -164, 894, -205, 531, -315, -23, +-352, -616, -299, -1069, -212, -1188, 34, -927, +367, -395, 511, 252, 519, 826, 494, 1135, +313, 1070, 24, 680, -215, 130, -382, -396, +-486, -732, -535, -807, -474, -638, -270, -332, +-49, -14, 104, 246, 248, 379, 400, 382, +492, 334, 520, 267, 482, 178, 345, 67, +71, -45, -353, -128, -726, -221, -837, -341, +-732, -369, -486, -245, -66, -68, 396, 145, +675, 379, 764, 501, 699, 457, 410, 281, +-15, -33, -350, -400, -524, -593, -598, -522, +-515, -315, -228, -27, 110, 350, 346, 658, +508, 679, 578, 416, 389, 83, -48, -225, +-442, -524, -649, -682, -730, -575, -600, -302, +-143, -43, 438, 227, 849, 575, 1008, 785, +966, 704, 620, 487, -39, 188, -711, -264, +-1129, -712, -1276, -909, -1158, -838, -697, -587, +7, -170, 695, 343, 1231, 796, 1506, 1012, +1382, 919, 837, 576, 62, 89, -663, -413, +-1192, -780, -1458, -881, -1337, -691, -809, -336, +-115, 39, 477, 368, 902, 582, 1125, 588, +1073, 440, 741, 247, 254, 4, -223, -233, +-581, -325, -795, -304, -834, -277, -626, -209, +-213, -25, 216, 158, 521, 234, 662, 313, +563, 392, 213, 289, -189, 30, -459, -208, +-570, -413, -493, -614, -150, -624, 298, -307, +623, 170, 802, 609, 774, 951, 419, 1069, +-151, 774, -668, 123, -1015, -562, -1148, -1069, +-941, -1302, -418, -1142, 237, -599, 857, 124, +1302, 796, 1390, 1242, 1040, 1357, 435, 1111, +-234, 553, -882, -149, -1260, -782, -1172, -1196, +-800, -1257, -368, -938, 133, -395, 592, 217, +776, 782, 659, 1081, 437, 966, 244, 568, +94, 100, 9, -348, 21, -628, 48, -588, +-27, -312, -187, 9, -395, 261, -595, 350, +-619, 236, -459, 0, -218, -222, 121, -341, +532, -283, 801, -79, 849, 137, 724, 278, +422, 326, 37, 253, -300, 113, -542, 40, +-630, 89, -585, 180, -508, 198, -423, 70, +-244, -190, -12, -540, 200, -863, 460, -937, +762, -636, 921, -34, 819, 704, 542, 1355, +153, 1691, -390, 1531, -938, 840, -1173, -181, +-1013, -1176, -635, -1850, -131, -2025, 426, -1580, +832, -643, 871, 400, 610, 1266, 303, 1766, +86, 1723, -54, 1208, -91, 526, 11, -113, +114, -628, 0, -898, -300, -916, -595, -878, +-750, -856, -738, -737, -484, -439, 44, 13, +652, 581, 1066, 1202, 1202, 1651, 1072, 1650, +638, 1135, -47, 240, -733, -817, -1174, -1718, +-1236, -2084, -961, -1760, -440, -882, 180, 266, +673, 1313, 880, 1869, 814, 1763, 540, 1081, +181, 96, -77, -818, -191, -1332, -237, -1321, +-186, -824, -77, -48, -87, 668, -198, 1048, +-216, 1005, -185, 586, -185, -35, -90, -623, +167, -950, 367, -877, 381, -479, 352, 15, +303, 465, 139, 800, -51, 870, -154, 634, +-193, 285, -238, -26, -239, -293, -186, -489, +-149, -547, -127, -505, -33, -450, 143, -360, +284, -139, 332, 180, 350, 500, 344, 763, +224, 878, -8, 741, -205, 395, -352, -48, +-477, -508, -455, -853, -213, -910, 84, -691, +324, -362, 490, -4, 481, 373, 275, 649, +8, 709, -218, 599, -355, 422, -359, 195, +-205, -68, 54, -294, 279, -414, 379, -415, +377, -336, 212, -220, -108, -79, -370, 51, +-459, 138, -397, 189, -190, 216, 94, 230, +329, 249, 468, 244, 521, 193, 403, 123, +114, 37, -218, -119, -453, -302, -536, -421, +-440, -450, -162, -380, 165, -179, 383, 125, +453, 441, 355, 662, 135, 735, -81, 626, +-238, 323, -329, -118, -262, -552, -80, -851, +90, -922, 226, -710, 303, -247, 240, 327, +93, 830, -21, 1097, -106, 1045, -201, 686, +-249, 129, -212, -476, -152, -953, -121, -1125, +-7, -944, 185, -522, 325, 32, 392, 576, +446, 947, 391, 1078, 132, 957, -207, 581, +-499, 85, -727, -395, -795, -817, -584, -1054, +-130, -974, 367, -665, 800, -223, 1049, 328, +954, 820, 531, 1054, -10, 1034, -535, 804, +-950, 379, -1073, -175, -829, -665, -364, -929, +161, -954, 620, -765, 875, -369, 846, 105, +575, 507, 155, 771, -270, 850, -572, 696, +-658, 383, -523, 44, -256, -231, 20, -410, +215, -480, 296, -445, 282, -324, 220, -184, +155, -65, 77, 50, -15, 216, -120, 403, +-214, 497, -283, 478, -297, 395, -212, 182, +-59, -152, 120, -436, 306, -575, 427, -566, +399, -363, 231, -16, 3, 333, -260, 577, +-499, 619, -615, 428, -501, 131, -206, -160, +96, -366, 320, -422, 460, -327, 474, -143, +373, 75, 221, 234, 36, 285, -155, 260, +-296, 215, -408, 179, -502, 139, -527, 48, +-405, -83, -182, -216, 50, -364, 314, -490, +644, -451, 876, -190, 810, 211, 469, 614, +-41, 901, -637, 956, -1136, 694, -1327, 135, +-1065, -548, -431, -1100, 339, -1291, 1019, -1043, +1388, -416, 1265, 399, 678, 1105, -144, 1423, +-925, 1256, -1382, 655, -1333, -178, -827, -887, +-37, -1187, 738, -1042, 1201, -508, 1188, 226, +725, 820, 11, 1006, -695, 765, -1193, 226, +-1302, -378, -934, -776, -272, -797, 422, -453, +990, 92, 1246, 594, 1062, 870, 515, 827, +-135, 477, -692, -64, -1070, -543, -1198, -765, +-991, -720, -557, -464, -91, -52, 374, 341, +792, 542, 1008, 556, 951, 462, 676, 269, +279, 34, -207, -124, -716, -149, -1115, -122, +-1252, -131, -1095, -152, -656, -156, -18, -200, +620, -227, 1089, -116, 1267, 117, 1038, 350, +469, 524, -222, 590, -833, 482, -1204, 208, +-1178, -144, -797, -470, -282, -669, 201, -681, +600, -472, 776, -96, 625, 336, 283, 690, +-78, 835, -407, 702, -603, 359, -568, -55, +-345, -428, -51, -680, 190, -696, 253, -451, +190, -74, 32, 298, -196, 600, -326, 708, +-277, 552, -189, 216, -114, -165, 20, -475, +130, -573, 72, -446, -73, -162, -165, 220, +-182, 537, -182, 608, -107, 459, 41, 141, +115, -258, 40, -528, -93, -545, -191, -363, +-252, -12, -303, 393, -306, 637, -222, 619, +-90, 383, 36, 9, 170, -348, 238, -564, +173, -563, 7, -332, -183, 46, -337, 403, +-361, 597, -251, 564, -123, 355, -62, 45, +-65, -266, -108, -445, -172, -422, -243, -264, +-227, -18, -106, 238, 57, 370, 200, 341, +306, 220, 281, 61, 78, -56, -200, -84, +-456, -49, -648, -18, -700, -10, -571, -35, +-303, -101, -2, -168, 268, -127, 452, 35, +488, 215, 354, 373, 127, 486, -133, 419, +-375, 158, -522, -178, -566, -484, -561, -650, +-494, -548, -336, -221, -115, 185, 117, 553, +327, 733, 418, 628, 333, 351, 131, 20, +-77, -304, -289, -503, -472, -470, -518, -283, +-431, -53, -306, 175, -162, 320, -25, 287, +30, 133, -37, -27, -137, -103, -176, -51, +-104, 116, 19, 303, 140, 416, 210, 369, +124, 115, -139, -286, -436, -657, -612, -802, +-622, -615, -500, -177, -262, 376, 23, 889, +256, 1103, 333, 857, 255, 345, 73, -182, +-150, -620, -355, -855, -441, -727, -357, -306, +-180, 148, -48, 422, -13, 478, -103, 343, +-312, 66, -505, -205, -508, -250, -308, -49, +67, 266, 474, 573, 679, 704, 560, 477, +157, -12, -439, -529, -1023, -958, -1326, -1152, +-1202, -864, -685, -176, 65, 578, 771, 1184, +1181, 1486, 1132, 1259, 640, 566, -129, -254, +-886, -920, -1365, -1263, -1410, -1143, -1037, -642, +-414, 17, 221, 599, 651, 902, 770, 830, +623, 480, 292, 44, -103, -283, -432, -383, +-576, -246, -551, 23, -465, 260, -398, 328, +-346, 214, -321, -42, -306, -337, -233, -494, +-51, -416, 208, -157, 451, 201, 525, 529, +379, 680, 60, 587, -346, 317, -774, -39, +-1063, -346, -1065, -484, -761, -439, -289, -283, +181, -81, 559, 111, 745, 272, 626, 367, +291, 372, -100, 301, -473, 207, -774, 68, +-873, -137, -761, -318, -508, -393, -177, -406, +142, -293, 343, 34, 386, 447, 243, 726, +-43, 820, -301, 655, -447, 178, -539, -434, +-526, -916, -343, -1128, -93, -944, 100, -344, +245, 444, 270, 1111, 75, 1453, -243, 1307, +-506, 659, -650, -255, -659, -1039, -501, -1388, +-206, -1203, 99, -577, 298, 251, 349, 908, +293, 1127, 107, 880, -179, 320, -428, -314, +-535, -714, -531, -684, -464, -267, -343, 318, +-227, 809, -156, 929, -98, 566, -57, -126, +9, -830, 105, -1266, 167, -1231, 157, -667, +100, 253, -38, 1155, -252, 1697, -482, 1671, +-702, 1073, -838, 94, -737, -926, -416, -1610, +-40, -1698, 312, -1210, 599, -353, 653, 565, +407, 1215, 4, 1385, -366, 1112, -652, 547, +-799, -87, -727, -536, -476, -669, -194, -532, +15, -257, 121, -12, 133, 104, 42, 72, +-113, -35, -218, -98, -194, -13, -129, 175, +-55, 356, 53, 503, 113, 545, -26, 359, +-305, 8, -531, -341, -654, -581, -716, -664, +-586, -519, -216, -169, 195, 246, 475, 568, +637, 710, 602, 651, 266, 427, -274, 81, +-772, -277, -1032, -521, -978, -583, -673, -470, +-219, -195, 236, 162, 525, 466, 572, 602, +405, 523, 53, 278, -359, 12, -674, -217, +-781, -391, -652, -422, -284, -262, 169, -21, +446, 216, 413, 385, 126, 401, -276, 249, +-603, 37, -698, -164, -544, -280, -240, -239, +128, -34, 417, 209, 478, 355, 269, 360, +-147, 239, -635, -27, -969, -347, -955, -528, +-557, -467, 81, -230, 668, 145, 951, 587, +870, 853, 401, 764, -338, 440, -1024, 14, +-1388, -472, -1396, -858, -1043, -914, -337, -655, +519, -213, 1160, 331, 1357, 808, 1114, 1002, +527, 894, -260, 575, -974, 119, -1371, -359, +-1390, -695, -1136, -834, -678, -751, -116, -459, +400, -33, 745, 388, 895, 685, 845, 807, +580, 743, 177, 473, -243, 89, -645, -274, +-953, -530, -1061, -646, -953, -574, -696, -320, +-325, 21, 117, 331, 530, 518, 762, 515, +744, 357, 531, 152, 190, -15, -215, -152, +-535, -205, -684, -120, -693, 1, -596, 38, +-415, 41, -245, 44, -98, -10, 40, -130, +145, -159, 198, -30, 221, 153, 204, 290, +159, 394, 79, 395, -82, 222, -293, -38, +-456, -269, -544, -451, -532, -470, -390, -263, +-143, 54, 76, 344, 203, 539, 247, 528, +194, 294, 25, -29, -178, -285, -301, -395, +-305, -329, -229, -136, -90, 139, 54, 379, +136, 445, 108, 330, 6, 122, -136, -136, +-328, -361, -515, -427, -561, -285, -466, -18, +-251, 260, 101, 439, 444, 465, 579, 333, +517, 89, 319, -182, 24, -350, -278, -348, +-484, -187, -627, 79, -711, 356, -682, 451, +-504, 278, -224, -37, 87, -319, 389, -477, +629, -423, 705, -112, 595, 341, 360, 689, +31, 778, -398, 608, -791, 221, -997, -326, +-979, -782, -777, -899, -386, -696, 116, -270, +552, 312, 831, 788, 921, 908, 739, 686, +317, 293, -203, -137, -662, -469, -923, -555, +-892, -343, -624, 20, -262, 305, 56, 398, +254, 294, 312, -28, 281, -429, 196, -633, +67, -493, -41, -76, -40, 464, 2, 937, +-23, 1137, -88, 904, -156, 304, -318, -431, +-492, -1037, -481, -1321, -298, -1154, -92, -584, +122, 185, 355, 889, 488, 1283, 418, 1245, +227, 855, -16, 274, -305, -304, -567, -734, +-658, -907, -556, -787, -286, -450, 63, -67, +341, 263, 477, 484, 484, 546, 315, 475, +-34, 355, -417, 196, -654, 28, -676, -119, +-478, -250, -97, -323, 355, -271, 648, -140, +665, 14, 437, 174, 11, 297, -499, 283, +-830, 132, -873, -35, -673, -124, -231, -172, +371, -152, 840, 16, 956, 270, 706, 398, +188, 338, -452, 161, -954, -98, -1098, -386, +-863, -501, -362, -357, 244, -84, 749, 217, +978, 521, 847, 644, 400, 458, -194, 102, +-705, -239, -973, -513, -905, -589, -546, -356, +-66, 84, 357, 500, 615, 721, 619, 646, +409, 294, 136, -212, -109, -649, -292, -814, +-352, -641, -298, -196, -218, 383, -183, 867, +-173, 1032, -168, 812, -148, 321, -100, -300, +20, -826, 223, -1025, 429, -819, 513, -356, +445, 185, 235, 685, -126, 991, -543, 932, +-829, 545, -895, 37, -709, -418, -315, -726, +183, -765, 632, -510, 906, -107, 912, 277, +625, 550, 126, 616, -417, 460, -814, 191, +-924, -83, -735, -292, -322, -346, 120, -249, +415, -66, 518, 128, 445, 248, 189, 227, +-141, 109, -376, -23, -428, -112, -314, -127, +-54, -56, 309, 64, 587, 192, 547, 272, +202, 255, -251, 125, -646, -70, -903, -267, +-871, -382, -495, -339, 58, -124, 553, 159, +895, 419, 1026, 580, 801, 554, 230, 299, +-385, -92, -809, -464, -1002, -660, -914, -614, +-517, -346, -29, 85, 355, 560, 600, 836, +676, 782, 497, 458, 138, 3, -190, -459, +-401, -769, -497, -790, -388, -488, -84, -11, +207, 444, 323, 755, 299, 815, 139, 538, +-149, 89, -415, -293, -515, -524, -489, -559, +-323, -330, 23, 15, 415, 263, 643, 351, +650, 297, 455, 105, 90, -134, -311, -248, +-572, -131, -650, 124, -558, 356, -356, 462, +-123, 391, 93, 113, 269, -288, 349, -607, +299, -667, 184, -472, 94, -109, 39, 340, +21, 727, 37, 855, 20, 694, -131, 323, +-362, -174, -553, -614, -615, -783, -496, -666, +-175, -337, 243, 115, 603, 517, 786, 697, +714, 635, 395, 385, -25, 45, -424, -291, +-733, -516, -819, -542, -600, -363, -248, -60, +69, 269, 350, 512, 532, 598, 441, 508, +157, 266, -86, -83, -241, -413, -328, -614, +-255, -641, -29, -452, 190, -71, 250, 346, +163, 681, -35, 845, -276, 733, -454, 327, +-458, -175, -286, -568, -21, -768, 253, -725, +455, -383, 488, 135, 354, 558, 89, 714, +-233, 595, -493, 258, -594, -178, -525, -537, +-275, -611, 60, -353, 341, 97, 506, 537, +512, 816, 289, 791, -81, 409, -410, -202, +-610, -801, -654, -1141, -473, -1046, -110, -562, +283, 141, 558, 859, 652, 1337, 544, 1362, +262, 942, -131, 243, -518, -497, -746, -1028, +-748, -1201, -592, -1026, -307, -566, 83, 17, +419, 507, 566, 760, 612, 801, 557, 688, +312, 471, -48, 212, -343, -35, -534, -248, +-644, -410, -649, -537, -498, -574, -231, -459, +37, -224, 259, 67, 476, 404, 608, 694, +538, 765, 296, 589, 7, 258, -285, -173, +-530, -556, -637, -715, -549, -587, -349, -251, +-125, 158, 120, 497, 342, 660, 398, 569, +264, 251, 61, -128, -103, -405, -237, -540, +-279, -475, -158, -198, 16, 154, 86, 388, +78, 463, 31, 418, -91, 261, -226, 36, +-288, -123, -277, -155, -182, -124, -22, -100, +119, -88, 183, -113, 175, -187, 99, -255, +5, -209, -67, -6, -110, 279, -121, 557, +-92, 761, -79, 733, -109, 412, -150, -74, +-185, -559, -244, -925, -272, -1005, -183, -732, +12, -213, 210, 374, 366, 841, 403, 1022, +277, 855, 41, 401, -205, -124, -402, -496, +-474, -619, -416, -490, -288, -146, -158, 206, +-31, 360, 65, 280, 109, 28, 100, -294, +109, -502, 149, -449, 188, -135, 211, 313, +188, 739, 31, 963, -236, 843, -501, 377, +-682, -244, -706, -789, -512, -1094, -173, -1043, +214, -628, 563, -1, 756, 608, 703, 982, +436, 1022, 32, 722, -406, 224, -734, -257, +-830, -556, -699, -608, -420, -425, -64, -126, +273, 134, 460, 249, 463, 202, 323, 40, +108, -81, -112, -90, -272, -23, -335, 133, +-291, 329, -179, 374, -76, 216, -9, -18, +30, -245, 4, -425, -74, -421, -145, -197, +-155, 122, -135, 382, -80, 501, 27, 431, +136, 164, 154, -191, 110, -462, 39, -539, +-101, -389, -288, -65, -379, 325, -355, 601, +-256, 647, -76, 469, 152, 131, 273, -260, +250, -541, 134, -600, -40, -435, -234, -139, +-352, 172, -351, 387, -243, 461, -60, 364, +126, 134, 219, -83, 205, -171, 85, -141, +-136, -40, -354, 90, -403, 179, -278, 155, +-89, 17, 94, -173, 235, -304, 263, -318, +129, -205, -94, 5, -277, 240, -377, 401, +-391, 444, -274, 350, -35, 150, 198, -54, +313, -174, 285, -224, 132, -217, -95, -141, +-310, -64, -421, -64, -384, -105, -285, -108, +-174, -55, -25, 64, 139, 241, 224, 408, +260, 500, 244, 467, 123, 279, -70, -32, +-209, -350, -308, -593, -409, -697, -452, -601, +-371, -324, -226, 52, -52, 433, 164, 674, +384, 704, 474, 560, 417, 309, 236, 3, +-27, -246, -324, -367, -564, -391, -682, -355, +-629, -275, -420, -192, -111, -116, 189, -17, +399, 142, 487, 315, 457, 454, 296, 531, +62, 500, -180, 296, -400, -39, -537, -359, +-537, -563, -435, -631, -262, -512, -30, -226, +172, 113, 282, 367, 316, 495, 262, 497, +107, 378, -72, 174, -197, -38, -266, -172, +-265, -199, -202, -183, -139, -170, -132, -143, +-137, -80, -103, -49, -48, -46, -1, 32, +52, 171, 95, 253, 108, 264, 75, 241, +21, 157, -57, -5, -148, -160, -241, -251, +-294, -257, -299, -196, -236, -92, -115, 41, +32, 164, 151, 216, 246, 182, 255, 127, +147, 95, -48, 45, -240, -11, -390, -41, +-433, -52, -350, -89, -180, -131, 5, -128, +174, -92, 287, -20, 306, 116, 220, 250, +43, 283, -200, 205, -417, 80, -501, -77, +-428, -236, -256, -310, -20, -221, 210, -21, +325, 148, 293, 227, 175, 250, 18, 196, +-155, 40, -271, -127, -285, -177, -238, -128, +-169, -40, -95, 53, -83, 117, -151, 107, +-174, 18, -73, -85, 97, -118, 278, -42, +414, 95, 386, 214, 160, 290, -167, 238, +-500, 12, -774, -274, -840, -470, -612, -511, +-173, -360, 321, -7, 763, 432, 967, 759, +796, 843, 294, 635, -302, 188, -790, -384, +-1027, -880, -937, -1092, -545, -940, -24, -473, +448, 165, 703, 776, 672, 1160, 388, 1168, +0, 807, -349, 230, -502, -347, -419, -795, +-208, -996, -10, -885, 101, -573, 63, -201, +-101, 165, -263, 468, -305, 651, -207, 698, +18, 645, 303, 503, 511, 273, 503, -44, +246, -367, -180, -616, -606, -776, -847, -789, +-810, -585, -505, -217, -24, 206, 471, 592, +785, 871, 809, 940, 549, 771, 101, 425, +-398, -8, -791, -439, -904, -772, -687, -902, +-279, -787, 131, -497, 451, -123, 598, 254, +500, 581, 223, 754, -58, 706, -270, 510, +-407, 265, -455, -3, -354, -276, -154, -469, +24, -511, 115, -444, 180, -338, 197, -184, +135, 45, 34, 244, -53, 344, -173, 397, +-288, 381, -331, 230, -260, 28, -112, -95, +87, -153, 256, -197, 337, -163, 290, -45, +131, 55, -106, 43, -347, -23, -535, -73, +-610, -145, -498, -236, -178, -237, 244, -69, +596, 214, 739, 493, 629, 693, 312, 732, +-117, 527, -538, 52, -817, -550, -875, -1053, +-703, -1281, -342, -1129, 99, -589, 503, 210, +778, 1029, 848, 1570, 659, 1649, 265, 1245, +-199, 467, -620, -482, -900, -1302, -942, -1721, +-716, -1651, -292, -1132, 185, -297, 552, 603, +741, 1290, 734, 1578, 532, 1457, 187, 991, +-183, 293, -522, -423, -741, -926, -743, -1148, +-517, -1154, -204, -939, 118, -513, 372, -16, +477, 426, 417, 770, 303, 1010, 151, 1093, +-37, 936, -212, 531, -319, 11, -395, -498, +-398, -966, -310, -1274, -178, -1225, -47, -839, +122, -282, 282, 344, 357, 944, 351, 1318, +287, 1350, 112, 1067, -152, 534, -373, -145, +-474, -801, -486, -1250, -401, -1374, -195, -1185, +55, -715, 252, -32, 361, 679, 400, 1168, +370, 1359, 248, 1272, 27, 864, -194, 183, +-357, -536, -502, -1059, -591, -1313, -490, -1301, +-226, -950, 67, -275, 364, 492, 632, 1063, +706, 1365, 507, 1384, 178, 994, -190, 249, +-595, -536, -888, -1111, -860, -1401, -548, -1347, +-93, -891, 400, -175, 802, 563, 902, 1151, +649, 1464, 179, 1387, -278, 919, -621, 214, +-797, -554, -734, -1209, -427, -1542, -50, -1450, +287, -969, 526, -235, 614, 565, 477, 1216, +190, 1576, -94, 1557, -262, 1111, -372, 372, +-443, -414, -398, -1101, -236, -1580, -83, -1673, +42, -1284, 189, -568, 318, 248, 342, 1013, +261, 1563, 139, 1722, 2, 1402, -173, 737, +-345, -34, -405, -766, -305, -1342, -129, -1610, +31, -1446, 162, -936, 212, -243, 124, 499, +-18, 1135, -61, 1490, -51, 1455, -48, 1064, +25, 454, 160, -238, 217, -853, 145, -1251, +-15, -1325, -255, -1087, -494, -626, -561, -28, +-378, 586, -59, 1061, 271, 1258, 508, 1144, +558, 776, 410, 206, 193, -445, -32, -975, +-247, -1209, -400, -1127, -422, -761, -371, -162, +-259, 484, -97, 953, 56, 1133, 121, 1026, +151, 651, 200, 65, 279, -508, 330, -871, +314, -998, 171, -895, -66, -528, -332, -10, +-527, 455, -577, 790, -456, 945, -229, 833, +67, 514, 378, 89, 567, -377, 541, -775, +355, -942, 78, -846, -222, -560, -390, -130, +-333, 356, -164, 767, -42, 975, 2, 921, +-16, 633, -91, 182, -156, -322, -101, -773, +42, -1027, 180, -970, 294, -638, 375, -150, +327, 386, 107, 845, -194, 1060, -441, 927, +-544, 524, -465, -1, -198, -499, 162, -861, +433, -967, 485, -742, 364, -294, 151, 189, +-100, 600, -342, 867, -463, 863, -398, 551, +-159, 90, 126, -369, 355, -727, 441, -882, +376, -749, 165, -355, -115, 141, -334, 574, +-370, 852, -310, 915, -243, 693, -149, 217, +3, -282, 116, -664, 195, -906, 310, -920, +443, -631, 453, -171, 314, 266, 75, 624, +-247, 853, -622, 874, -867, 700, -820, 378, +-499, -8, -7, -381, 548, -688, 989, -897, +1122, -936, 888, -752, 368, -394, -280, 65, +-862, 568, -1171, 1020, -1094, 1287, -635, 1227, +41, 847, 685, 245, 1052, -490, 1036, -1199, +652, -1625, 13, -1611, -623, -1192, -971, -439, +-905, 508, -507, 1360, 69, 1862, 643, 1866, +990, 1380, 924, 525, 478, -510, -116, -1440, +-616, -1949, -933, -1900, -984, -1377, -710, -499, +-174, 537, 374, 1406, 760, 1866, 927, 1800, +865, 1262, 538, 446, 114, -450, -213, -1239, +-426, -1660, -614, -1572, -711, -1115, -672, -453, +-539, 321, -338, 1018, 5, 1419, 427, 1428, +781, 1101, 968, 526, 990, -186, 824, -849, +437, -1270, -174, -1353, -858, -1102, -1328, -576, +-1404, 110, -1114, 780, -527, 1280, 252, 1435, +932, 1169, 1233, 581, 1157, -174, 879, -944, +487, -1497, 20, -1565, -385, -1095, -571, -307, +-588, 562, -584, 1315, -586, 1702, -535, 1488, +-463, 750, -358, -182, -72, -1021, 446, -1564, +994, -1619, 1340, -1115, 1398, -265, 1076, 598, +350, 1256, -583, 1541, -1402, 1335, -1877, 705, +-1857, -60, -1300, -696, -309, -1114, 822, -1240, +1730, -1010, 2062, -501, 1753, 39, 949, 434, +-81, 724, -1025, 915, -1531, 908, -1474, 672, +-996, 343, -358, 23, 288, -338, 772, -744, +934, -1031, 755, -1039, 420, -802, 64, -413, +-247, 160, -462, 819, -491, 1285, -339, 1364, +-110, 1090, 97, 558, 281, -160, 427, -874, +464, -1335, 359, -1402, 138, -1092, -163, -535, +-491, 131, -746, 744, -823, 1156, -654, 1239, +-227, 1001, 396, 590, 1020, 93, 1401, -453, +1382, -899, 960, -1092, 201, -1028, -726, -774, +-1541, -316, -1944, 264, -1770, 775, -1045, 1070, +54, 1113, 1192, 912, 1976, 466, 2153, -151, +1717, -747, 808, -1120, -306, -1184, -1281, -970, +-1829, -483, -1878, 187, -1450, 806, -647, 1154, +330, 1182, 1153, 938, 1579, 444, 1528, -203, +1134, -772, 551, -1070, -101, -1074, -708, -841, +-1089, -387, -1207, 157, -1121, 583, -820, 819, +-244, 879, 429, 755, 948, 484, 1238, 152, +1358, -197, 1196, -511, 641, -704, -170, -783, +-959, -749, -1583, -539, -1900, -146, -1674, 295, +-854, 660, 279, 923, 1359, 1008, 2143, 792, +2418, 335, 1999, -157, 925, -579, -456, -915, +-1734, -1036, -2584, -859, -2740, -464, -2083, 26, +-830, 504, 609, 866, 1850, 1007, 2637, 854, +2774, 446, 2186, -45, 1030, -441, -352, -699, +-1621, -762, -2505, -570, -2757, -225, -2291, 86, +-1271, 280, -20, 380, 1183, 375, 2129, 255, +2639, 102, 2550, 6, 1852, -8, 678, -31, +-685, -86, -1920, -89, -2709, -54, -2835, -85, +-2203, -145, -1009, -111, 419, -27, 1747, 16, +2694, 61, 2968, 133, 2445, 190, 1245, 169, +-277, 89, -1709, -3, -2644, -90, -2833, -155, +-2242, -172, -1098, -123, 257, -28, 1484, 70, +2327, 150, 2562, 185, 2092, 169, 1070, 78, +-154, -71, -1269, -176, -2040, -190, -2235, -174, +-1796, -151, -941, -36, 38, 145, 965, 211, +1696, 174, 2045, 170, 1864, 176, 1183, 81, +186, -45, -859, -80, -1707, -86, -2119, -154, +-1949, -255, -1237, -300, -213, -245, 857, -137, +1768, 10, 2292, 223, 2221, 486, 1508, 651, +345, 599, -971, 385, -2092, 74, -2676, -346, +-2486, -778, -1559, -1000, -166, -913, 1274, -593, +2393, -81, 2914, 535, 2689, 1050, 1683, 1244, +159, 1062, -1437, 616, -2665, 23, -3227, -622, +-2893, -1116, -1685, -1233, 39, -971, 1719, -514, +2935, 18, 3404, 524, 2962, 866, 1643, 943, +-134, 779, -1829, 498, -3038, 190, -3484, -130, +-2939, -437, -1527, -653, 256, -730, 1909, -691, +3080, -528, 3446, -225, 2840, 184, 1467, 576, +-223, 830, -1811, 911, -2936, 776, -3265, 396, +-2686, -127, -1426, -620, 125, -940, 1594, -1019, +2641, -820, 3021, -370, 2650, 220, 1629, 748, +233, 1020, -1183, 993, -2300, 706, -2869, 201, +-2718, -388, -1887, -838, -611, -982, 800, -840, +2066, -492, 2883, -7, 2998, 506, 2329, 845, +1029, 888, -588, 704, -2091, 367, -3063, -95, +-3203, -561, -2477, -860, -1076, -884, 611, -675, +2172, -288, 3186, 209, 3348, 683, 2556, 968, +1033, 949, -771, 663, -2304, 196, -3168, -365, +-3155, -853, -2288, -1081, -814, -958, 813, -577, +2193, -62, 2991, 486, 3006, 922, 2231, 1090, +876, 933, -709, 549, -2080, 73, -2864, -442, +-2899, -883, -2200, -1082, -937, -986, 562, -673, +1942, -185, 2876, 388, 3084, 862, 2447, 1130, +1138, 1129, -494, 816, -2039, 295, -3055, -278, +-3214, -815, -2488, -1185, -1109, -1213, 576, -925, +2128, -453, 3116, 133, 3276, 748, 2559, 1209, +1135, 1341, -582, 1115, -2088, 640, -3006, 7, +-3113, -695, -2405, -1259, -1128, -1457, 343, -1282, +1708, -827, 2682, -144, 3020, 649, 2609, 1321, +1587, 1660, 184, 1592, -1288, 1137, -2491, 317, +-3075, -712, -2924, -1618, -2096, -2085, -731, -2000, +974, -1361, 2561, -243, 3514, 1067, 3538, 2127, +2644, 2578, 978, 2287, -1096, 1337, -2938, -65, +-3902, -1531, -3769, -2580, -2641, -2847, -755, -2287, +1441, -1087, 3242, 457, 4079, 1907, 3752, 2782, +2385, 2803, 337, 2037, -1775, 761, -3293, -715, +-3803, -1979, -3238, -2615, -1798, -2470, 84, -1706, +1853, -560, 3028, 715, 3338, 1761, 2754, 2271, +1467, 2153, -141, 1504, -1633, 534, -2607, -531, +-2855, -1439, -2384, -1968, -1354, -1963, -7, -1462, +1353, -653, 2371, 308, 2785, 1243, 2537, 1867, +1687, 1979, 305, 1607, -1261, 845, -2476, -213, +-3014, -1259, -2836, -1951, -1893, -2164, -317, -1863, +1438, -1001, 2815, 246, 3486, 1437, 3265, 2230, +2123, 2491, 302, 2106, -1641, 1072, -3142, -340, +-3796, -1663, -3444, -2524, -2137, -2759, -213, -2296, +1789, -1153, 3306, 389, 3989, 1819, 3660, 2736, +2354, 2988, 384, 2479, -1656, 1252, -3221, -354, +-3963, -1836, -3731, -2832, -2525, -3132, -646, -2616, +1381, -1365, 3060, 265, 4040, 1779, 4034, 2811, +2952, 3173, 1062, 2696, -1116, 1449, -3007, -142, +-4110, -1608, -4112, -2687, -3013, -3127, -1111, -2702, +1083, -1526, 2978, -3, 4068, 1464, 4089, 2559, +3044, 3018, 1184, 2645, -983, 1528, -2808, 59, +-3771, -1320, -3703, -2352, -2694, -2844, -1034, -2576, +851, -1570, 2445, -219, 3353, 1077, 3416, 2150, +2670, 2792, 1259, 2679, -456, 1810, -1990, 514, +-2967, -893, -3208, -2181, -2643, -3020, -1420, -3051, +150, -2179, 1694, -692, 2873, 987, 3389, 2520, +3049, 3524, 1825, 3509, 52, 2384, -1739, 598, +-3055, -1342, -3580, -3065, -3111, -4038, -1738, -3753, +143, -2282, 1968, -218, 3296, 1873, 3797, 3540, +3258, 4262, 1726, 3636, -313, 1876, -2197, -298, +-3409, -2274, -3672, -3685, -2939, -4096, -1404, -3209, +503, -1381, 2231, 621, 3333, 2312, 3610, 3437, +2983, 3655, 1508, 2776, -414, 1160, -2149, -566, +-3217, -2020, -3436, -3023, -2781, -3305, -1398, -2638, +338, -1268, 1946, 257, 3085, 1663, 3503, 2789, +3019, 3249, 1684, 2757, -115, 1543, -1844, 22, +-3041, -1538, -3431, -2827, -2908, -3403, -1603, -2977, +115, -1707, 1788, -38, 3021, 1652, 3510, 3012, +3092, 3588, 1808, 3054, -5, 1622, -1803, -174, +-3046, -1920, -3476, -3252, -2991, -3671, -1655, -2923, +204, -1352, 1985, 481, 3223, 2214, 3646, 3444, +3108, 3680, 1626, 2771, -381, 1102, -2260, -793, +-3431, -2502, -3633, -3626, -2831, -3741, -1203, -2703, +804, -888, 2570, 1086, 3602, 2783, 3687, 3853, +2792, 3884, 1073, 2716, -977, 776, -2683, -1287, +-3576, -3043, -3517, -4121, -2518, -4068, -808, -2787, +1093, -743, 2618, 1430, 3473, 3268, 3517, 4327, +2687, 4202, 1113, 2845, -744, 723, -2335, -1516, +-3301, -3363, -3497, -4393, -2831, -4212, -1367, -2796, +486, -655, 2189, 1529, 3373, 3301, 3786, 4274, +3229, 4063, 1763, 2657, -199, 595, -2089, -1473, +-3384, -3137, -3779, -4035, -3186, -3791, -1716, -2437, +273, -510, 2156, 1381, 3407, 2892, 3764, 3694, +3181, 3450, 1706, 2229, -264, 519, -2081, -1224, +-3182, -2678, -3402, -3452, -2756, -3262, -1363, -2187, +410, -567, 1991, 1155, 2961, 2607, 3188, 3440, +2653, 3331, 1394, 2245, -260, 562, -1751, -1262, +-2703, -2853, -2995, -3734, -2508, -3517, -1295, -2261, +271, -370, 1726, 1652, 2763, 3293, 3149, 4046, +2757, 3625, 1579, 2134, -111, 31, -1792, -2094, +-2954, -3679, -3343, -4258, -2822, -3618, -1437, -1941, +419, 277, 2139, 2423, 3242, 3919, 3522, 4321, +2901, 3510, 1428, 1751, -495, -474, -2205, -2594, +-3242, -4004, -3418, -4296, -2649, -3423, -1098, -1642, +739, 590, 2259, 2657, 3100, 4002, 3154, 4287, +2456, 3405, 1117, 1564, -467, -704, -1828, -2778, +-2656, -4105, -2827, -4285, -2258, -3256, -1101, -1370, +285, 875, 1521, 2910, 2398, 4120, 2744, 4139, +2421, 3048, 1470, 1190, 151, -986, -1216, -2908, +-2289, -4010, -2772, -4019, -2545, -2994, -1619, -1213, +-153, 936, 1390, 2879, 2562, 4020, 3117, 4070, +2875, 3098, 1753, 1328, 96, -904, -1604, -2974, +-2884, -4187, -3351, -4250, -2820, -3261, -1476, -1416, +326, 958, 2084, 3126, 3246, 4355, 3489, 4408, +2791, 3378, 1333, 1410, -501, -1089, -2166, -3305, +-3192, -4502, -3320, -4472, -2563, -3349, -1166, -1323, +508, 1216, 2051, 3426, 3075, 4533, 3310, 4399, +2732, 3228, 1487, 1160, -130, -1349, -1741, -3410, +-2885, -4387, -3267, -4246, -2818, -3098, -1698, -1068, +-126, 1361, 1549, 3342, 2862, 4288, 3419, 4159, +3129, 3045, 2044, 1005, 343, -1441, -1484, -3410, +-2815, -4350, -3343, -4189, -3020, -2954, -1882, -806, +-201, 1688, 1515, 3658, 2793, 4469, 3285, 4068, +2885, 2647, 1723, 386, 120, -2097, -1508, -3828, +-2624, -4313, -2928, -3730, -2442, -2227, -1356, 16, +125, 2281, 1572, 3686, 2496, 3972, 2679, 3335, +2219, 1862, 1207, -230, -204, -2223, -1537, -3414, +-2299, -3624, -2399, -3008, -1956, -1651, -982, 235, +345, 2053, 1578, 3132, 2328, 3312, 2455, 2791, +1967, 1584, 939, -193, -387, -1905, -1622, -2934, +-2366, -3190, -2454, -2793, -1885, -1653, -808, 127, +541, 1916, 1783, 3046, 2538, 3394, 2587, 3003, +1996, 1682, 877, -369, -578, -2304, -1930, -3477, +-2695, -3801, -2693, -3172, -1995, -1449, -741, 878, +793, 2886, 2166, 3983, 2917, 4036, 2832, 3002, +2037, 992, 724, -1395, -858, -3291, -2271, -4169, +-3002, -3961, -2900, -2735, -2054, -658, -660, 1635, +1020, 3307, 2475, 3988, 3193, 3733, 2978, 2536, +2055, 548, 641, -1567, -1027, -3056, -2457, -3678, +-3137, -3471, -2948, -2388, -2064, -580, -669, 1313, +992, 2642, 2459, 3249, 3206, 3142, 3076, 2204, +2223, 617, 782, -1017, -963, -2188, -2442, -2797, +-3193, -2793, -3118, -2028, -2244, -656, -760, 765, +975, 1807, 2470, 2404, 3286, 2438, 3171, 1738, +2240, 543, 748, -642, -988, -1514, -2486, -2037, +-3227, -2059, -3050, -1437, -2121, -408, -647, 537, +1065, 1204, 2499, 1659, 3164, 1746, 2938, 1259, +1992, 433, 555, -330, -1077, -969, -2431, -1531, +-3016, -1717, -2751, -1315, -1864, -599, -539, 121, +1059, 893, 2410, 1643, 3030, 1938, 2794, 1588, +1896, 847, 508, -63, -1110, -1079, -2525, -1978, +-3189, -2306, -2894, -1888, -1848, -985, -324, 96, +1398, 1265, 2808, 2241, 3384, 2527, 2968, 2027, +1742, 1099, 58, -44, -1680, -1307, -3022, -2304, +-3502, -2589, -2940, -2162, -1570, -1303, 180, -166, +1922, 1123, 3182, 2170, 3524, 2571, 2821, 2303, +1434, 1569, -245, 436, -1922, -940, -3157, -2075, +-3456, -2550, -2811, -2382, -1516, -1718, 186, -585, +1924, 810, 3129, 1951, 3409, 2487, 2796, 2387, +1543, 1717, -82, 555, -1773, -811, -3023, -1921, +-3391, -2414, -2851, -2258, -1623, -1599, 42, -484, +1779, 865, 3015, 1901, 3358, 2316, 2759, 2190, +1464, 1542, -201, 349, -1781, -984, -2866, -1966, +-3157, -2413, -2564, -2267, -1232, -1493, 397, -238, +1843, 1126, 2752, 2154, 2868, 2568, 2127, 2332, +811, 1483, -609, 110, -1788, -1321, -2490, -2289, +-2500, -2661, -1783, -2440, -618, -1497, 639, -29, +1772, 1368, 2468, 2325, 2424, 2775, 1628, 2528, +409, 1493, -905, 27, -1996, -1379, -2597, -2449, +-2457, -2928, -1564, -2609, -206, -1529, 1202, -13, +2394, 1515, 3044, 2677, 2709, 3157, 1364, 2737, +-365, 1471, -1848, -253, -2885, -1928, -3225, -3125, +-2521, -3464, -972, -2743, 737, -1144, 2158, 813, +3092, 2592, 3222, 3678, 2333, 3644, 651, 2432, +-1120, 448, -2376, -1690, -2966, -3353, -2885, -4007, +-1936, -3432, -379, -1797, 1086, 409, 2079, 2478, +2634, 3779, 2552, 3934, 1641, 2897, 252, 1009, +-1003, -1086, -1842, -2824, -2243, -3780, -2068, -3624, +-1246, -2420, -124, -603, 834, 1341, 1513, 2920, +1898, 3663, 1725, 3363, 913, 2188, -135, 412, +-945, -1548, -1455, -3085, -1599, -3684, -1199, -3261, +-351, -1979, 454, -68, 1012, 1919, 1367, 3288, +1390, 3697, 833, 3073, -91, 1498, -893, -590, +-1334, -2451, -1396, -3522, -1007, -3531, -228, -2493, +552, -697, 1037, 1335, 1237, 2907, 1184, 3499, +769, 3010, 35, 1609, -681, -325, -1065, -2100, +-1085, -3061, -879, -3032, -443, -2112, 121, -557, +532, 1125, 634, 2334, 637, 2726, 622, 2258, +452, 1119, 89, -305, -221, -1516, -321, -2123, +-313, -2032, -341, -1358, -335, -310, -210, 747, +-123, 1412, -152, 1505, -45, 1142, 259, 498, +428, -227, 415, -771, 463, -930, 443, -709, +141, -269, -241, 192, -441, 450, -574, 374, +-663, 56, -526, -319, -75, -549, 416, -485, +708, -93, 801, 462, 746, 953, 384, 1140, +-260, 833, -816, 83, -976, -812, -800, -1524, +-445, -1784, 99, -1357, 777, -292, 1233, 935, +1143, 1879, 618, 2264, -43, 1860, -705, 661, +-1260, -845, -1397, -2053, -869, -2610, -8, -2303, +686, -1130, 1150, 523, 1436, 2044, 1162, 2861, +297, 2662, -550, 1504, -972, -178, -1153, -1841, +-1102, -2912, -561, -2940, 342, -1887, 1004, -224, +1126, 1456, 953, 2685, 564, 2994, -174, 2166, +-947, 611, -1140, -1014, -739, -2268, -272, -2769, +115, -2234, 676, -961, 1169, 467, 1000, 1671, +407, 2338, -19, 2151, -402, 1206, -930, -6, +-1046, -1058, -596, -1718, -104, -1850, 164, -1429, +403, -580, 618, 388, 676, 1111, 549, 1412, +392, 1405, 325, 1128, 223, 490, -85, -341, +-485, -962, -745, -1281, -902, -1441, -1047, -1279, +-909, -630, -213, 187, 748, 860, 1499, 1419, +1920, 1755, 1897, 1517, 1243, 783, 28, -112, +-1297, -1039, -2219, -1823, -2426, -2072, -1996, -1666, +-961, -844, 596, 217, 2078, 1346, 2803, 2142, +2683, 2281, 1791, 1745, 240, 692, -1422, -621, +-2562, -1762, -2849, -2404, -2217, -2391, -884, -1634, +713, -310, 2139, 1105, 2937, 2183, 2780, 2666, +1753, 2333, 190, 1229, -1465, -242, -2711, -1653, +-3092, -2585, -2486, -2715, -1086, -2013, 658, -758, +2269, 702, 3280, 1988, 3363, 2700, 2421, 2594, +713, 1715, -1264, 391, -2893, -1008, -3688, -2220, +-3367, -2870, -1933, -2571, 121, -1418, 2046, 44, +3329, 1447, 3724, 2565, 3096, 2949, 1522, 2288, +-528, 861, -2338, -773, -3299, -2156, -3261, -2878, +-2316, -2651, -684, -1541, 1145, 68, 2400, 1611, +2769, 2562, 2468, 2631, 1677, 1883, 395, 585, +-962, -866, -1807, -2014, -2033, -2460, -1829, -2062, +-1170, -1075, -137, 82, 854, 1113, 1501, 1805, +1799, 1920, 1742, 1447, 1237, 713, 346, -70, +-673, -813, -1518, -1322, -1957, -1462, -1848, -1373, +-1104, -1067, 108, -386, 1330, 445, 2101, 1088, +2320, 1578, 1939, 1877, 901, 1605, -554, 649, +-1782, -553, -2345, -1598, -2229, -2279, -1527, -2380, +-286, -1656, 1143, -181, 2116, 1407, 2325, 2393, +1978, 2593, 1264, 2105, 219, 891, -862, -790, +-1533, -2113, -1741, -2495, -1694, -2081, -1332, -1230, +-486, -65, 511, 1124, 1259, 1781, 1797, 1691, +2134, 1230, 1875, 748, 1009, 193, -113, -431, +-1233, -856, -2129, -1031, -2396, -1201, -1868, -1320, +-707, -1008, 700, -298, 1910, 487, 2560, 1258, +2433, 1887, 1513, 1947, 89, 1276, -1302, 154, +-2167, -1043, -2295, -1913, -1708, -2151, -500, -1709, +935, -683, 1939, 600, 2289, 1568, 2077, 1846, +1227, 1548, -114, 839, -1291, -146, -1961, -1066, +-2121, -1494, -1713, -1306, -728, -765, 523, -169, +1620, 451, 2226, 1047, 2287, 1258, 1848, 902, +892, 390, -342, -16, -1402, -527, -2075, -1099, +-2333, -1223, -2041, -851, -1131, -411, 197, 31, +1513, 630, 2449, 1147, 2860, 1235, 2570, 949, +1505, 520, -16, 3, -1475, -603, -2570, -1166, +-3005, -1399, -2544, -1208, -1224, -737, 482, -77, +1999, 714, 2906, 1391, 3003, 1637, 2193, 1353, +705, 625, -903, -371, -2080, -1297, -2533, -1756, +-2205, -1520, -1206, -705, 176, 357, 1453, 1267, +2178, 1671, 2257, 1337, 1749, 341, 667, -815, +-649, -1546, -1628, -1609, -1994, -1050, -1869, 31, +-1244, 1262, -89, 1952, 1237, 1750, 2122, 879, +2425, -255, 2212, -1335, 1278, -1989, -310, -1896, +-1786, -1072, -2571, 62, -2682, 1009, -2064, 1545, +-619, 1636, 1173, 1271, 2518, 531, 3031, -324, +2757, -962, 1754, -1254, 142, -1260, -1558, -998, +-2631, -396, -2790, 345, -2140, 904, -867, 1185, +745, 1146, 2082, 726, 2608, 25, 2254, -708, +1332, -1197, 80, -1217, -1171, -778, -1928, -123, +-1856, 610, -1115, 1211, -76, 1328, 938, 891, +1623, 215, 1655, -488, 986, -1148, 19, -1480, +-766, -1261, -1202, -663, -1226, 84, -724, 886, +152, 1517, 917, 1644, 1292, 1256, 1282, 544, +877, -339, 100, -1190, -680, -1714, -1090, -1700, +-1060, -1178, -737, -382, -221, 444, 378, 1152, +949, 1516, 1262, 1396, 1112, 1013, 584, 537, +-44, -64, -647, -686, -1100, -1091, -1107, -1323, +-625, -1447, 12, -1227, 609, -542, 1184, 410, +1470, 1348, 1114, 1997, 306, 2104, -547, 1516, +-1252, 320, -1570, -1091, -1204, -2112, -326, -2379, +655, -1901, 1421, -835, 1731, 553, 1434, 1714, +687, 2108, -238, 1727, -1067, 963, -1552, 86, +-1430, -793, -712, -1384, 177, -1387, 848, -1051, +1291, -734, 1386, -315, 866, 367, 18, 960, +-532, 1192, -731, 1266, -796, 1199, -577, 622, +19, -411, 556, -1284, 699, -1646, 581, -1620, +369, -1217, -23, -311, -443, 835, -583, 1579, +-368, 1705, -36, 1446, 231, 888, 437, -3, +612, -919, 584, -1412, 294, -1490, 1, -1365, +-159, -932, -360, -97, -532, 849, -404, 1492, +-137, 1705, -37, 1503, 46, 842, 345, -244, +677, -1350, 730, -1890, 550, -1685, 297, -1020, +-41, -78, -461, 1032, -720, 1722, -714, 1486, +-504, 734, -162, 15, 236, -668, 575, -1192, +837, -1065, 913, -390, 642, 190, 116, 490, +-342, 656, -629, 545, -812, 70, -766, -413, +-357, -552, 174, -412, 550, -181, 815, 133, +985, 535, 793, 789, 203, 645, -430, 132, +-812, -430, -956, -833, -782, -1081, -232, -983, +439, -325, 850, 601, 944, 1259, 754, 1452, +321, 1186, -208, 376, -583, -748, -675, -1591, +-465, -1706, -99, -1139, 192, -194, 338, 823, +366, 1549, 199, 1554, -108, 834, -232, -70, +-4, -772, 308, -1169, 424, -1020, 388, -321, +281, 379, -63, 587, -581, 421, -858, 114, +-691, -262, -297, -515, 179, -358, 704, 216, +1127, 783, 1138, 916, 639, 608, -86, 66, +-687, -620, -1076, -1281, -1186, -1440, -848, -885, +-124, -12, 585, 734, 1029, 1324, 1219, 1655, +1040, 1343, 413, 399, -298, -613, -745, -1254, +-965, -1578, -953, -1620, -545, -1062, 43, 53, +469, 1069, 697, 1547, 798, 1680, 648, 1475, +270, 586, -125, -703, -363, -1518, -458, -1614, +-413, -1403, -221, -938, 12, 28, 77, 1109, +23, 1525, 38, 1230, 77, 844, 50, 454, +120, -272, 346, -1060, 470, -1236, 367, -914, +226, -699, 20, -437, -446, 293, -959, 1069, +-1037, 1257, -672, 1027, -110, 779, 543, 281, +1185, -665, 1513, -1502, 1281, -1549, 527, -978, +-403, -345, -1233, 360, -1768, 1245, -1715, 1653, +-948, 1101, 177, 246, 1161, -281, 1746, -726, +1811, -1141, 1307, -978, 388, -205, -637, 355, +-1418, 323, -1734, 196, -1561, 285, -968, 202, +-38, -159, 952, -161, 1611, 334, 1707, 521, +1385, 132, 742, -162, -246, -150, -1294, -362, +-1820, -697, -1723, -497, -1211, 88, -258, 319, +1010, 235, 1911, 346, 1981, 534, 1352, 341, +309, -67, -890, -179, -1792, -116, -1944, -354, +-1302, -681, -273, -560, 769, -145, 1619, 110, +1942, 419, 1390, 951, 253, 1137, -809, 636, +-1497, -107, -1794, -694, -1437, -1174, -451, -1466, +582, -1173, 1221, -253, 1512, 752, 1461, 1364, +931, 1564, 39, 1397, -801, 778, -1324, -199, +-1471, -1085, -1188, -1505, -488, -1486, 343, -1206, +941, -638, 1196, 246, 1099, 1062, 632, 1435, +18, 1452, -448, 1224, -687, 616, -765, -305, +-555, -1100, -74, -1486, 270, -1465, 244, -1060, +118, -304, 47, 548, -38, 1136, -107, 1300, +23, 1077, 258, 580, 332, -51, 153, -659, +-115, -963, -269, -856, -296, -561, -293, -240, +-159, 206, 164, 641, 440, 732, 393, 522, +101, 238, -207, -126, -453, -521, -646, -673, +-582, -485, -128, -123, 486, 265, 868, 545, +909, 585, 704, 327, 324, -78, -270, -414, +-889, -553, -1173, -435, -1074, -109, -767, 300, +-191, 576, 611, 496, 1218, 139, 1311, -235, +1001, -493, 478, -602, -164, -450, -792, -26, +-1139, 434, -1062, 648, -667, 584, -187, 376, +244, 124, 604, -198, 776, -510, 585, -586, +246, -492, 73, -431, -19, -284, -269, 70, +-485, 466, -437, 653, -353, 690, -356, 705, +-129, 488, 376, -83, 763, -658, 709, -894, +363, -862, -18, -687, -495, -269, -1049, 266, +-1159, 588, -562, 655, 252, 625, 798, 505, +1157, 270, 1295, -15, 885, -226, -115, -384, +-1041, -549, -1309, -629, -1149, -546, -888, -245, +-283, 199, 619, 530, 1127, 671, 907, 652, +570, 391, 442, -99, 93, -480, -457, -529, +-580, -409, -293, -186, -278, 193, -536, 477, +-395, 372, 4, 12, 70, -259, 49, -358, +402, -379, 721, -258, 534, 102, 173, 470, +62, 545, -112, 353, -576, 140, -862, -86, +-615, -414, -209, -585, 21, -377, 276, -39, +685, 168, 831, 302, 459, 408, -54, 349, +-345, 79, -599, -299, -865, -529, -704, -455, +-42, -230, 546, 47, 753, 456, 742, 791, +576, 712, 114, 284, -463, -221, -744, -705, +-670, -973, -470, -804, -213, -297, 104, 277, +406, 685, 499, 735, 405, 481, 312, 150, +299, -133, 238, -294, 5, -181, -288, 133, +-484, 240, -701, 19, -826, -301, -583, -639, +-29, -838, 496, -633, 863, -16, 1073, 715, +935, 1208, 386, 1257, -258, 851, -749, 157, +-1003, -621, -1013, -1238, -714, -1319, -186, -848, +292, -262, 609, 190, 799, 559, 762, 797, +459, 772, 113, 535, -66, 343, -266, 220, +-562, -49, -681, -483, -552, -850, -391, -930, +-220, -800, 89, -527, 487, 99, 738, 942, +803, 1443, 727, 1321, 483, 795, -18, 76, +-691, -773, -1212, -1489, -1280, -1687, -946, -1249, +-334, -361, 527, 593, 1367, 1335, 1665, 1761, +1344, 1668, 651, 938, -297, -128, -1281, -1092, +-1813, -1733, -1616, -1947, -830, -1522, 161, -477, +1042, 722, 1534, 1588, 1426, 1929, 803, 1715, +35, 928, -605, -228, -960, -1209, -984, -1619, +-685, -1497, -253, -965, 92, -109, 294, 684, +376, 990, 387, 865, 402, 603, 354, 269, +232, -133, 59, -376, -142, -266, -347, -42, +-506, -56, -448, -260, -205, -375, -17, -362, +132, -301, 289, -89, 309, 368, 166, 804, +143, 887, 282, 598, 323, 150, 235, -362, +76, -926, -267, -1222, -743, -939, -1049, -295, +-865, 352, -322, 818, 361, 1091, 1073, 1101, +1574, 725, 1563, 84, 887, -512, -192, -864, +-1154, -1002, -1797, -981, -1929, -684, -1384, -170, +-373, 316, 666, 697, 1470, 1021, 1951, 1187, +1848, 956, 1094, 336, 180, -310, -684, -835, +-1510, -1218, -1965, -1287, -1767, -925, -1122, -235, +-271, 486, 713, 1008, 1670, 1231, 2144, 1009, +1847, 463, 975, -132, -30, -606, -994, -859, +-1761, -821, -1960, -494, -1461, -8, -618, 428, +296, 649, 1168, 555, 1729, 276, 1700, -44, +1142, -408, 350, -649, -456, -573, -1142, -240, +-1525, 165, -1453, 505, -918, 764, -144, 740, +668, 327, 1368, -142, 1696, -466, 1428, -700, +615, -761, -363, -534, -1085, -116, -1491, 284, +-1439, 541, -878, 541, -72, 393, 678, 297, +1124, 98, 1172, -230, 912, -354, 402, -266, +-188, -201, -613, -115, -670, 108, -510, 264, +-418, 160, -308, -15, -48, -156, 183, -364, +207, -465, 197, -285, 359, 62, 442, 485, +359, 933, 280, 1064, 175, 627, -93, -90, +-418, -775, -625, -1347, -669, -1537, -541, -1105, +-178, -168, 312, 891, 802, 1624, 1073, 1731, +979, 1220, 557, 342, -107, -627, -804, -1403, +-1236, -1638, -1260, -1237, -806, -488, 12, 312, +887, 962, 1447, 1239, 1502, 1097, 1024, 662, +104, 60, -858, -500, -1369, -779, -1329, -862, +-951, -807, -346, -435, 448, 143, 1035, 534, +1099, 648, 828, 607, 458, 430, 22, 129, +-302, -203, -376, -410, -332, -348, -421, -131, +-589, 38, -624, 50, -466, -113, -173, -293, +290, -306, 827, -194, 1225, 8, 1274, 406, +921, 900, 230, 1039, -641, 594, -1351, -121, +-1615, -804, -1384, -1354, -691, -1489, 242, -926, +1139, 131, 1683, 1080, 1657, 1580, 1127, 1595, +243, 1049, -724, 15, -1347, -1141, -1411, -1825, +-1009, -1645, -372, -855, 412, 168, 1011, 1140, +1104, 1661, 774, 1498, 259, 755, -242, -241, +-576, -1160, -659, -1708, -396, -1499, -16, -551, +261, 557, 319, 1308, 174, 1590, 33, 1386, +-77, 524, -130, -711, -34, -1540, 142, -1687, +292, -1244, 241, -306, 40, 824, -136, 1646, +-336, 1704, -472, 1073, -380, 167, -142, -806, +135, -1543, 396, -1735, 647, -1251, 732, -208, +583, 864, 311, 1517, -37, 1661, -533, 1293, +-963, 498, -1048, -506, -792, -1323, -405, -1722, +164, -1625, 959, -928, 1595, 93, 1608, 1049, +1057, 1720, 237, 1829, -703, 1402, -1505, 546, +-1782, -626, -1415, -1625, -600, -2038, 360, -1829, +1177, -1069, 1638, 137, 1592, 1396, 962, 2068, +9, 2020, -810, 1450, -1199, 346, -1283, -992, +-1038, -1928, -331, -2132, 452, -1643, 882, -660, +1104, 555, 1080, 1534, 588, 1929, -247, 1748, +-876, 994, -1037, -97, -944, -1063, -568, -1707, +213, -1804, 1000, -1198, 1255, -201, 939, 713, +388, 1316, -297, 1580, -991, 1330, -1219, 475, +-804, -485, -113, -1068, 522, -1292, 1008, -1168, +1200, -536, 857, 360, 75, 891, -723, 927, +-1050, 823, -893, 514, -484, -150, 65, -766, +625, -868, 955, -540, 910, -208, 562, 79, +96, 483, -497, 667, -938, 435, -895, 157, +-535, 21, -94, -141, 374, -374, 741, -440, +812, -260, 613, -169, 306, -219, -145, -95, +-600, 238, -774, 509, -616, 573, -269, 562, +109, 439, 446, 22, 642, -453, 538, -765, +234, -903, -82, -776, -288, -365, -407, 196, +-410, 670, -239, 929, 44, 982, 259, 706, +351, 255, 392, -140, 399, -600, 209, -993, +-83, -1010, -227, -734, -274, -391, -351, -22, +-337, 514, -118, 1012, 189, 1125, 341, 919, +320, 562, 326, 105, 292, -484, 48, -1058, +-182, -1210, -102, -993, 107, -662, 65, -178, +-85, 411, -127, 915, -240, 1128, -503, 1077, +-560, 904, -180, 471, 375, -160, 725, -757, +942, -1259, 976, -1490, 605, -1316, -207, -764, +-1032, 72, -1334, 974, -1176, 1692, -785, 1939, +-42, 1599, 859, 726, 1374, -438, 1269, -1351, +873, -1831, 373, -1979, -391, -1540, -1077, -532, +-1221, 524, -919, 1273, -499, 1737, -65, 1913, +548, 1557, 1112, 726, 1241, -187, 1003, -1054, +601, -1782, -23, -2125, -798, -1900, -1389, -1147, +-1444, -105, -1026, 1036, -338, 2038, 464, 2512, +1264, 2267, 1765, 1395, 1692, 163, 1024, -1180, +-21, -2295, -1033, -2714, -1651, -2349, -1756, -1444, +-1348, -162, -523, 1223, 428, 2263, 1112, 2619, +1387, 2281, 1374, 1416, 1023, 210, 315, -1012, +-378, -1891, -757, -2290, -916, -2107, -990, -1394, +-807, -501, -385, 361, 0, 1221, 243, 1862, +559, 1996, 811, 1752, 770, 1278, 608, 406, +495, -704, 194, -1641, -352, -2279, -777, -2471, +-823, -1951, -755, -808, -683, 578, -322, 1841, +273, 2678, 754, 2791, 968, 2051, 999, 701, +851, -760, 401, -1883, -220, -2478, -692, -2489, +-920, -1793, -954, -583, -748, 563, -375, 1378, +77, 1938, 547, 2095, 935, 1639, 1073, 782, +902, -94, 507, -874, 57, -1473, -456, -1751, +-885, -1627, -1134, -1023, -1165, -187, -824, 441, +-207, 932, 431, 1391, 1014, 1465, 1431, 1005, +1438, 479, 960, 162, 326, -262, -332, -808, +-1144, -1085, -1756, -1114, -1766, -1099, -1257, -960, +-486, -515, 403, 156, 1367, 834, 2037, 1463, +2047, 1893, 1467, 1818, 650, 1217, -328, 284, +-1432, -802, -2175, -1913, -2168, -2671, -1681, -2574, +-838, -1693, 360, -418, 1574, 1049, 2202, 2348, +2152, 3045, 1795, 2876, 1097, 1847, -62, 293, +-1241, -1284, -1997, -2425, -2234, -2912, -2037, -2629, +-1375, -1500, -228, -30, 1001, 1116, 1832, 1789, +2228, 2077, 2305, 1884, 1839, 1093, 618, 164, +-838, -333, -1905, -592, -2504, -851, -2590, -979, +-1893, -969, -584, -955, 805, -930, 1857, -699, +2483, -198, 2483, 484, 1683, 1272, 404, 1829, +-843, 1885, -1792, 1535, -2196, 825, -1960, -219, +-1181, -1329, -125, -2113, 849, -2311, 1421, -2009, +1464, -1337, 1111, -361, 502, 801, -118, 1863, +-438, 2407, -478, 2421, -347, 2120, -141, 1318, +0, -8, -41, -1412, -314, -2462, -609, -2994, +-598, -2957, -321, -2189, 72, -722, 537, 980, +1034, 2476, 1225, 3436, 956, 3581, 448, 2798, +-104, 1276, -736, -552, -1300, -2303, -1429, -3576, +-1045, -3872, -523, -3091, -14, -1608, 570, 118, +1146, 1822, 1414, 3216, 1202, 3733, 699, 3159, +104, 1969, -530, 523, -1085, -1066, -1299, -2478, +-1086, -3234, -699, -3136, -224, -2452, 331, -1423, +720, -12, 826, 1578, 804, 2817, 665, 3278, +409, 3057, 130, 2351, -81, 977, -349, -906, +-649, -2516, -821, -3391, -754, -3577, -538, -3010, +-235, -1526, 187, 451, 646, 2186, 915, 3379, +831, 3824, 486, 3217, 213, 1699, 58, -239, +-169, -2014, -304, -3185, -253, -3529, -314, -2873, +-625, -1360, -880, 427, -823, 1869, -571, 2577, +-93, 2519, 712, 1769, 1524, 544, 1894, -624, +1691, -1290, 883, -1372, -296, -1023, -1479, -422, +-2221, 237, -2271, 571, -1685, 417, -658, -9, +538, -473, 1480, -763, 1938, -723, 1851, -324, +1336, 352, 593, 1018, -223, 1468, -830, 1568, +-1145, 1163, -1243, 363, -1096, -605, -799, -1530, +-477, -2086, -162, -2104, 186, -1640, 542, -789, +860, 370, 1145, 1537, 1321, 2317, 1275, 2544, +987, 2195, 300, 1336, -669, 207, -1603, -1039, +-2237, -2153, -2468, -2688, -2043, -2592, -812, -2109, +752, -1189, 2099, 214, 3089, 1651, 3352, 2605, +2563, 3113, 990, 3122, -778, 2231, -2344, 590, +-3506, -1177, -3758, -2702, -2850, -3684, -1223, -3718, +613, -2720, 2305, -1030, 3524, 946, 3851, 2735, +3098, 3744, 1547, 3647, -399, 2613, -2355, 988, +-3716, -841, -4061, -2396, -3247, -3192, -1537, -3064, +554, -2182, 2475, -771, 3761, 795, 4024, 1947, +3122, 2431, 1227, 2277, -965, 1503, -2690, 289, +-3639, -896, -3691, -1648, -2658, -1871, -762, -1543, +1211, -617, 2723, 543, 3648, 1388, 3591, 1748, +2267, 1591, 262, 770, -1568, -520, -2932, -1657, +-3681, -2230, -3338, -2174, -1811, -1357, 196, 115, +2033, 1669, 3305, 2755, 3661, 3121, 2874, 2598, +1250, 1145, -605, -836, -2190, -2605, -3229, -3630, +-3446, -3662, -2658, -2657, -1063, -924, 656, 1028, +2085, 2768, 3059, 3784, 3254, 3714, 2536, 2718, +1178, 1212, -460, -526, -2067, -2186, -3185, -3321, +-3372, -3657, -2625, -3192, -1175, -2043, 678, -407, +2372, 1430, 3282, 3000, 3199, 3852, 2290, 3735, +720, 2664, -1131, 922, -2493, -1021, -2991, -2697, +-2691, -3681, -1681, -3609, -104, -2523, 1459, -993, +2410, 490, 2571, 1810, 2081, 2758, 1028, 2854, +-328, 2164, -1496, 1296, -2076, 405, -2113, -680, +-1632, -1645, -603, -2109, 591, -2121, 1500, -1786, +1958, -1048, 1896, 31, 1271, 1131, 265, 1806, +-752, 1878, -1539, 1503, -1911, 809, -1656, -195, +-931, -1051, -105, -1212, 677, -862, 1358, -404, +1725, 163, 1506, 683, 881, 665, 134, 79, +-636, -497, -1238, -829, -1420, -1039, -1267, -892, +-901, -163, -430, 773, 153, 1409, 743, 1628, +1095, 1553, 1195, 1096, 1194, 173, 1036, -881, +592, -1600, -68, -1916, -743, -1951, -1347, -1562, +-1794, -639, -1827, 408, -1378, 1200, -531, 1752, +608, 2069, 1777, 1949, 2567, 1342, 2638, 531, +2012, -238, 825, -1004, -651, -1727, -1982, -2152, +-2823, -2133, -3053, -1768, -2489, -1149, -1157, -232, +539, 975, 1999, 2111, 2929, 2798, 3133, 2984, +2516, 2667, 1300, 1667, -189, 58, -1579, -1676, +-2546, -3069, -2899, -3865, -2495, -3871, -1473, -2960, +-210, -1221, 948, 877, 1734, 2744, 2102, 4016, +2024, 4465, 1548, 3832, 922, 2244, 200, 241, +-562, -1728, -1180, -3323, -1529, -4159, -1708, -4041, +-1716, -3079, -1380, -1568, -624, 187, 285, 1832, +1165, 3059, 1900, 3662, 2348, 3547, 2260, 2777, +1520, 1553, 400, 18, -702, -1557, -1633, -2776, +-2277, -3424, -2442, -3483, -2069, -2917, -1233, -1734, +-121, -202, 985, 1296, 1873, 2576, 2454, 3445, +2577, 3728, 2053, 3298, 1017, 2124, -174, 473, +-1304, -1316, -2333, -2993, -2896, -4179, -2614, -4468, +-1645, -3694, -478, -2056, 766, 129, 2007, 2427, +2809, 4224, 2693, 4987, 1895, 4517, 899, 2924, +-253, 614, -1477, -1850, -2298, -3803, -2416, -4669, +-1994, -4296, -1201, -2922, -81, -937, 1009, 1182, +1630, 2841, 1820, 3519, 1716, 3262, 1245, 2367, +475, 1018, -273, -440, -819, -1494, -1254, -1933, +-1456, -1933, -1265, -1659, -773, -1088, -206, -373, +366, 195, 882, 532, 1233, 814, 1238, 1082, +929, 1163, 440, 1013, -102, 751, -617, 372, +-928, -172, -946, -806, -753, -1257, -484, -1312, +-211, -1084, 71, -714, 377, -76, 671, 747, +897, 1295, 940, 1327, 735, 1073, 363, 657, +-143, -3, -755, -767, -1273, -1215, -1451, -1203, +-1208, -956, -597, -547, 254, 106, 1012, 765, +1484, 1088, 1635, 1071, 1396, 905, 736, 579, +-82, 44, -819, -525, -1386, -933, -1749, -1163, +-1702, -1168, -1228, -893, -556, -384, 258, 223, +1294, 856, 2190, 1401, 2458, 1577, 2068, 1288, +1222, 686, 4, -75, -1381, -798, -2445, -1345, +-2857, -1559, -2579, -1366, -1637, -895, -164, -298, +1347, 297, 2346, 732, 2704, 949, 2483, 1063, +1686, 1185, 529, 1151, -564, 866, -1420, 452, +-1962, -92, -2102, -860, -1813, -1651, -1272, -2127, +-592, -2158, 165, -1776, 961, -836, 1630, 627, +1994, 2031, 1978, 2892, 1646, 3170, 990, 2810, +-11, 1665, -1207, -120, -2145, -1893, -2470, -3158, +-2254, -3758, -1513, -3493, -317, -2285, 890, -494, +1696, 1332, 2022, 2818, 1888, 3696, 1311, 3636, +487, 2628, -218, 1063, -600, -552, -687, -1895, +-628, -2799, -682, -3080, -860, -2623, -1047, -1642, +-1079, -497, -886, 592, -396, 1540, 433, 2174, +1444, 2300, 2191, 1988, 2398, 1459, 1981, 704, +1008, -265, -326, -1153, -1689, -1681, -2637, -1916, +-2850, -1896, -2370, -1525, -1380, -844, -16, -22, +1352, 793, 2248, 1468, 2541, 1883, 2324, 1922, +1621, 1581, 534, 902, -585, 31, -1409, -810, +-1824, -1423, -1893, -1699, -1600, -1597, -1049, -1168, +-447, -575, 99, -5, 665, 491, 1209, 770, +1565, 810, 1626, 835, 1474, 916, 1083, 925, +370, 821, -539, 647, -1366, 345, -1920, -277, +-2141, -1102, -1880, -1753, -1077, -2016, -13, -1906, +1022, -1384, 1788, -345, 2098, 1024, 1996, 2169, +1556, 2721, 784, 2642, -125, 1997, -974, 817, +-1720, -697, -2294, -2000, -2257, -2671, -1518, -2718, +-540, -2154, 452, -1038, 1574, 324, 2439, 1421, +2495, 1978, 1833, 2076, 872, 1732, -336, 953, +-1623, 42, -2362, -621, -2233, -878, -1531, -923, +-589, -845, 473, -609, 1373, -369, 1712, -304, +1443, -328, 853, -256, 178, -90, -469, 104, +-893, 439, -958, 879, -650, 1193, -119, 1254, +395, 1059, 571, 574, 352, -154, -66, -995, +-444, -1709, -703, -2086, -661, -1987, -207, -1358, +442, -292, 933, 942, 1209, 1958, 1211, 2486, +694, 2500, -255, 1901, -1123, 720, -1529, -653, +-1504, -1712, -1122, -2330, -373, -2521, 543, -2107, +1163, -1137, 1314, -31, 1209, 925, 935, 1678, +385, 2177, -233, 2227, -516, 1791, -603, 1020, +-834, 103, -1070, -896, -944, -1887, -647, -2542, +-413, -2544, -6, -1937, 740, -897, 1344, 451, +1539, 1866, 1503, 2817, 1208, 2947, 370, 2372, +-735, 1253, -1547, -320, -1955, -1823, -2093, -2665, +-1757, -2793, -766, -2386, 469, -1363, 1492, 143, +2211, 1480, 2509, 2190, 2122, 2362, 1075, 2045, +-257, 1247, -1478, 164, -2337, -794, -2560, -1353, +-2040, -1539, -1015, -1443, 215, -1125, 1350, -664, +2111, -173, 2195, 173, 1610, 482, 609, 860, +-463, 1165, -1250, 1267, -1484, 1175, -1280, 871, +-738, 294, -3, -447, 660, -1084, 959, -1527, +826, -1670, 396, -1394, -194, -770, -782, -46, +-1041, 588, -798, 1098, -274, 1466, 315, 1499, +898, 1147, 1333, 637, 1356, 172, 950, -307, +262, -848, -569, -1213, -1318, -1195, -1731, -1007, +-1687, -803, -1293, -516, -663, -87, 204, 316, +1144, 583, 1701, 875, 1835, 1208, 1732, 1372, +1349, 1302, 550, 1033, -348, 518, -1051, -343, +-1649, -1310, -2132, -2083, -2129, -2510, -1578, -2397, +-834, -1621, -44, -383, 1019, 987, 2154, 2264, +2741, 3179, 2705, 3307, 2218, 2559, 1181, 1253, +-306, -249, -1770, -1745, -2812, -2947, -3321, -3497, +-3136, -3184, -2121, -2133, -594, -695, 929, 774, +2171, 2030, 2966, 2843, 3163, 3008, 2619, 2554, +1548, 1712, 327, 627, -818, -524, -1835, -1514, +-2552, -2154, -2701, -2462, -2281, -2476, -1634, -2044, +-822, -1109, 259, 85, 1364, 1195, 2111, 2018, +2465, 2517, 2526, 2498, 2181, 1886, 1328, 938, +176, -13, -1038, -840, -2131, -1480, -2823, -1751, +-2861, -1667, -2321, -1546, -1349, -1411, -83, -1040, +1183, -397, 2056, 334, 2423, 1101, 2355, 1946, +1934, 2641, 1230, 2739, 394, 2122, -396, 986, +-1046, -460, -1589, -1999, -2033, -3161, -2249, -3456, +-2064, -2860, -1416, -1698, -448, -185, 667, 1406, +1780, 2624, 2577, 3020, 2713, 2600, 2194, 1719, +1330, 635, 316, -453, -713, -1262, -1578, -1588, +-2022, -1443, -2008, -1147, -1708, -871, -1318, -578, +-832, -314, -296, -213, 279, -120, 914, 288, +1570, 890, 2067, 1310, 2306, 1515, 2153, 1529, +1485, 1211, 414, 468, -833, -412, -1986, -1096, +-2822, -1557, -3169, -1844, -2890, -1762, -1920, -1263, +-486, -646, 1031, -78, 2352, 636, 3334, 1461, +3629, 2009, 3003, 2101, 1764, 1875, 307, 1316, +-1170, 371, -2514, -806, -3273, -1836, -3222, -2433, +-2551, -2484, -1521, -1987, -252, -1058, 984, 136, +1971, 1281, 2475, 1965, 2475, 2141, 2111, 1922, +1533, 1328, 746, 372, -203, -539, -1038, -1013, +-1619, -1167, -2027, -1159, -2141, -946, -1831, -591, +-1330, -246, -728, -42, 99, 53, 1044, 132, +1736, 273, 2134, 457, 2346, 622, 2176, 733, +1477, 748, 443, 600, -635, 349, -1624, 27, +-2416, -357, -2793, -652, -2514, -767, -1774, -826, +-820, -870, 270, -786, 1458, -492, 2406, -164, +2804, 161, 2666, 639, 2181, 1193, 1307, 1536, +92, 1488, -1154, 1133, -2120, 590, -2748, -183, +-2972, -1030, -2592, -1647, -1643, -1848, -383, -1753, +858, -1428, 1917, -746, 2754, 135, 3117, 882, +2717, 1536, 1806, 2126, 726, 2329, -527, 1931, +-1866, 1162, -2788, 132, -2956, -1126, -2571, -2200, +-1799, -2647, -739, -2511, 425, -1916, 1388, -846, +1993, 466, 2237, 1485, 2228, 1976, 1938, 2093, +1347, 1925, 473, 1403, -479, 702, -1376, 26, +-2169, -622, -2680, -1293, -2623, -1819, -1941, -1971, +-814, -1726, 496, -1183, 1682, -336, 2491, 742, +2736, 1658, 2324, 1963, 1386, 1731, 313, 1169, +-611, 379, -1325, -423, -1708, -921, -1646, -966, +-1343, -678, -1022, -280, -573, 31, -43, 108, +314, -54, 478, -445, 691, -786, 941, -765, +1075, -406, 1126, 110, 1165, 727, 1004, 1357, +499, 1699, -246, 1457, -995, 794, -1683, 54, +-2213, -628, -2228, -1241, -1584, -1633, -592, -1661, +491, -1346, 1543, -894, 2340, -351, 2555, 358, +2081, 1165, 1166, 1744, 168, 1902, -753, 1810, +-1479, 1433, -1824, 524, -1697, -619, -1337, -1516, +-944, -1980, -449, -2090, 178, -1801, 677, -1058, +831, -110, 917, 717, 1195, 1256, 1300, 1502, +1032, 1539, 744, 1297, 457, 835, -139, 355, +-931, -62, -1465, -518, -1670, -931, -1739, -1110, +-1528, -1116, -851, -1084, 168, -839, 1125, -374, +1769, 29, 2047, 346, 1904, 728, 1268, 993, +407, 980, -375, 863, -904, 841, -1276, 748, +-1432, 474, -1224, 120, -809, -276, -480, -785, +-251, -1413, -19, -1967, 222, -2130, 470, -1784, +792, -921, 1148, 338, 1312, 1743, 1238, 2861, +935, 3316, 441, 2971, -189, 1870, -885, 288, +-1536, -1343, -1985, -2659, -2055, -3314, -1653, -3176, +-849, -2388, 185, -1215, 1290, 152, 2162, 1410, +2549, 2251, 2296, 2621, 1615, 2556, 693, 2023, +-409, 1181, -1495, 248, -2144, -699, -2275, -1570, +-1981, -2108, -1362, -2230, -544, -2031, 239, -1533, +882, -737, 1423, 137, 1746, 942, 1764, 1649, +1542, 2094, 1138, 2156, 474, 1903, -345, 1342, +-1044, 459, -1518, -605, -1884, -1523, -1973, -2161, +-1594, -2414, -915, -2178, -128, -1479, 734, -456, +1579, 586, 2126, 1385, 2199, 1920, 1793, 2137, +1125, 1947, 248, 1374, -756, 679, -1599, -57, +-1956, -899, -1954, -1630, -1700, -1972, -1126, -1977, +-294, -1676, 427, -951, 902, 37, 1318, 860, +1711, 1429, 1810, 1792, 1497, 1776, 995, 1336, +349, 768, -521, 184, -1434, -420, -2061, -948, +-2250, -1317, -1925, -1513, -1151, -1480, -121, -1126, +909, -495, 1707, 247, 2065, 990, 1942, 1502, +1484, 1634, 693, 1377, -283, 805, -1042, 32, +-1340, -720, -1376, -1175, -1243, -1285, -824, -1102, +-188, -575, 245, 124, 431, 667, 535, 872, +548, 820, 417, 512, 300, -107, 315, -760, +350, -979, 286, -701, 202, -192, 94, 432, +-129, 1103, -416, 1401, -695, 1028, -854, 238, +-818, -564, -602, -1231, -237, -1558, 226, -1282, +687, -473, 997, 375, 1046, 895, 851, 1091, +492, 950, 23, 442, -463, -150, -839, -479, +-903, -431, -762, -197, -540, 81, -153, 300, +321, 357, 572, 161, 519, -267, 310, -647, +97, -729, -125, -587, -271, -285, -201, 163, +30, 675, 212, 951, 310, 847, 448, 532, +494, 128, 157, -369, -364, -746, -686, -717, +-806, -364, -912, -41, -850, 168, -361, 304, +292, 274, 682, -1, 984, -339, 1341, -481, +1392, -294, 911, 83, 177, 456, -522, 714, +-1149, 752, -1607, 495, -1716, 20, -1413, -473, +-794, -756, -63, -789, 691, -562, 1437, -157, +1914, 275, 1886, 551, 1465, 547, 782, 308, +-112, -5, -1062, -242, -1702, -362, -1932, -404, +-1846, -208, -1410, 206, -594, 519, 280, 558, +968, 502, 1426, 372, 1704, -3, 1682, -475, +1298, -766, 716, -870, 128, -785, -440, -459, +-1051, 25, -1607, 491, -1843, 876, -1664, 1051, +-1266, 907, -709, 518, 75, 45, 1005, -457, +1733, -864, 2076, -965, 2082, -734, 1719, -372, +973, 1, -21, 383, -1000, 691, -1761, 708, +-2229, 482, -2394, 181, -2031, -137, -1205, -462, +-213, -667, 752, -615, 1696, -367, 2370, -3, +2553, 501, 2259, 920, 1601, 1001, 569, 732, +-661, 273, -1727, -339, -2432, -964, -2762, -1290, +-2638, -1233, -1875, -889, -667, -283, 559, 400, +1620, 957, 2485, 1295, 2895, 1365, 2650, 1116, +1811, 645, 677, 43, -493, -606, -1536, -1137, +-2237, -1371, -2466, -1309, -2247, -961, -1715, -377, +-937, 236, -58, 680, 798, 916, 1498, 917, +1951, 760, 2075, 533, 1964, 356, 1559, 255, +853, 169, -11, 19, -930, -297, -1855, -743, +-2496, -1146, -2567, -1410, -2116, -1357, -1340, -833, +-262, 73, 1013, 974, 2034, 1652, 2502, 2012, +2433, 1813, 1940, 1032, 1055, 29, -40, -858, +-925, -1418, -1357, -1561, -1489, -1315, -1499, -812, +-1346, -217, -984, 222, -593, 438, -375, 542, +-101, 556, 380, 459, 907, 403, 1301, 437, +1634, 404, 1821, 270, 1592, 151, 924, -8, +107, -257, -801, -510, -1674, -651, -2223, -726, +-2327, -702, -2023, -488, -1365, -144, -462, 228, +528, 571, 1441, 786, 2106, 781, 2400, 579, +2326, 314, 1885, 26, 1019, -189, -62, -285, +-1063, -300, -1895, -272, -2487, -271, -2650, -314, +-2207, -282, -1343, -157, -368, -7, 659, 138, +1645, 269, 2239, 233, 2295, 23, 1964, -201, +1418, -312, 662, -234, -141, 92, -741, 549, +-1103, 954, -1386, 1140, -1630, 940, -1712, 306, +-1587, -540, -1379, -1315, -981, -1807, -183, -1887, +931, -1423, 2062, -570, 2904, 368, 3192, 1202, +2787, 1794, 1695, 2025, 139, 1866, -1518, 1368, +-2841, 662, -3572, -158, -3641, -971, -2995, -1737, +-1691, -2300, -86, -2402, 1431, -1968, 2653, -1114, +3471, 41, 3651, 1305, 3074, 2330, 1961, 2773, +536, 2615, -1090, 1922, -2608, 767, -3569, -582, +-3782, -1679, -3308, -2281, -2170, -2392, -522, -2036, +1175, -1222, 2493, -203, 3337, 645, 3594, 1161, +3084, 1394, 1844, 1335, 339, 1038, -1020, 665, +-2098, 408, -2836, 243, -3014, 70, -2580, -177, +-1687, -481, -569, -804, 579, -1115, 1559, -1300, +2206, -1192, 2445, -775, 2270, -148, 1742, 485, +911, 1014, -133, 1344, -1163, 1397, -1874, 1155, +-2143, 737, -2007, 282, -1587, -147, -888, -520, +41, -773, 832, -922, 1233, -986, 1379, -1023, +1381, -976, 1139, -747, 776, -364, 494, 91, +313, 675, 15, 1343, -409, 1824, -885, 1934, +-1343, 1698, -1780, 1062, -2016, 17, -1757, -1178, +-905, -2160, 254, -2712, 1461, -2614, 2525, -1799, +3164, -486, 3056, 919, 2100, 2047, 634, 2578, +-992, 2342, -2506, 1504, -3505, 401, -3613, -657, +-2875, -1253, -1585, -1230, -1, -817, 1558, -343, +2669, 38, 3133, 180, 2995, -31, 2315, -442, +1237, -720, -61, -698, -1235, -386, -2053, 83, +-2485, 656, -2537, 1186, -2092, 1422, -1259, 1294, +-321, 974, 524, 511, 1329, -128, 1916, -831, +2051, -1368, 1813, -1695, 1409, -1801, 909, -1536, +290, -842, -398, 57, -1032, 964, -1557, 1722, +-1931, 2135, -2032, 2037, -1796, 1491, -1209, 670, +-333, -234, 716, -1000, 1696, -1504, 2297, -1721, +2424, -1578, 2096, -1211, 1375, -786, 395, -347, +-638, 131, -1459, 617, -1862, 1080, -1932, 1477, +-1746, 1721, -1307, 1717, -642, 1390, 0, 661, +470, -332, 888, -1355, 1323, -2176, 1542, -2601, +1448, -2419, 1235, -1605, 970, -408, 462, 837, +-216, 1896, -775, 2497, -1204, 2444, -1596, 1811, +-1824, 866, -1715, -140, -1269, -951, -593, -1447, +232, -1606, 1103, -1470, 1814, -1114, 2160, -688, +2120, -252, 1738, 190, 1016, 576, 67, 879, +-851, 1082, -1616, 1064, -2171, 819, -2378, 431, +-2058, 47, -1328, -229, -453, -335, 489, -329, +1478, -300, 2172, -317, 2253, -460, 1853, -753, +1261, -1029, 491, -1082, -392, -734, -1104, -10, +-1436, 911, -1475, 1749, -1397, 2246, -1207, 2197, +-813, 1511, -322, 332, 105, -928, 503, -1943, +976, -2537, 1337, -2523, 1387, -1806, 1220, -691, +960, 437, 558, 1391, 6, 2035, -585, 2160, +-1075, 1798, -1459, 1146, -1691, 371, -1608, -388, +-1133, -996, -392, -1400, 422, -1561, 1220, -1462, +1905, -1109, 2211, -603, 1962, 10, 1242, 629, +288, 1108, -703, 1409, -1593, 1517, -2133, 1319, +-2097, 809, -1616, 160, -871, -468, 23, -1062, +923, -1485, 1567, -1576, 1816, -1302, 1721, -767, +1357, -104, 702, 551, -99, 1062, -833, 1297, +-1321, 1215, -1550, 848, -1515, 371, -1172, -66, +-613, -412, 43, -626, 675, -610, 1116, -439, +1317, -288, 1297, -231, 1022, -209, 547, -241, +5, -353, -511, -421, -932, -252, -1101, 148, +-947, 621, -669, 1030, -395, 1317, -142, 1270, +72, 772, 171, -26, 224, -861, 328, -1527, +489, -1837, 648, -1642, 865, -966, 985, -110, +777, 693, 275, 1287, -308, 1514, -931, 1290, +-1547, 811, -1849, 319, -1623, -136, -1024, -531, +-250, -751, 642, -771, 1489, -625, 2018, -444, +2036, -277, 1615, -43, 905, 225, 17, 335, +-889, 296, -1557, 210, -1750, 128, -1529, 33, +-1125, -28, -649, 18, -98, 174, 382, 311, +668, 338, 809, 259, 979, 113, 1124, -111, +1144, -322, 1029, -481, 743, -548, 178, -467, +-544, -310, -1223, -155, -1749, 45, -1972, 254, +-1654, 439, -793, 606, 256, 725, 1153, 698, +1740, 549, 1908, 302, 1572, -99, 843, -600, +11, -986, -667, -1141, -1072, -1049, -1164, -698, +-932, -88, -466, 603, 59, 1128, 394, 1350, +446, 1252, 312, 797, 91, 89, -214, -629, +-458, -1088, -474, -1170, -188, -905, 263, -409, +649, 178, 860, 626, 888, 776, 627, 619, +67, 283, -534, -68, -905, -261, -1068, -295, +-1039, -230, -719, -103, -173, 23, 319, 37, +577, -69, 689, -202, 762, -221, 669, -102, +366, 80, 21, 226, -227, 352, -409, 401, +-520, 282, -462, 48, -244, -127, -44, -195, +63, -234, 111, -280, 88, -230, -52, -155, +-164, -224, -111, -375, 13, -400, 124, -313, +272, -187, 367, 49, 311, 469, 164, 907, +46, 1188, -43, 1239, -127, 1035, -151, 504, +-115, -329, -137, -1214, -249, -1822, -382, -2091, +-416, -1981, -301, -1401, -36, -416, 352, 649, +756, 1505, 991, 2099, 916, 2380, 501, 2204, +-41, 1650, -515, 848, -859, -117, -1011, -1162, +-852, -2100, -420, -2703, 32, -2804, 350, -2363, +605, -1422, 755, -117, 715, 1306, 533, 2406, +296, 2897, 26, 2779, -295, 2156, -578, 1146, +-696, 15, -670, -932, -532, -1505, -268, -1760, +81, -1777, 374, -1564, 565, -1161, 684, -689, +683, -187, 509, 353, 271, 889, 2, 1266, +-332, 1404, -736, 1326, -1074, 1086, -1166, 671, +-916, 172, -427, -223, 198, -472, 870, -656, +1409, -722, 1586, -670, 1313, -601, 692, -569, +-87, -535, -847, -487, -1436, -374, -1675, -141, +-1473, 207, -929, 640, -244, 1130, 409, 1486, +910, 1502, 1187, 1118, 1196, 424, 931, -467, +544, -1316, 199, -1842, -65, -1850, -307, -1322, +-469, -409, -541, 558, -623, 1274, -762, 1533, +-801, 1263, -707, 560, -547, -284, -260, -998, +279, -1336, 920, -1155, 1423, -549, 1697, 224, +1672, 976, 1247, 1449, 460, 1420, -483, 948, +-1353, 261, -1984, -501, -2253, -1154, -2040, -1513, +-1330, -1495, -333, -1175, 687, -677, 1590, -156, +2261, 328, 2440, 775, 2030, 1140, 1265, 1326, +397, 1340, -536, 1189, -1371, 816, -1869, 179, +-1974, -553, -1823, -1212, -1433, -1723, -793, -1927, +-50, -1645, 642, -988, 1300, -164, 1839, 706, +2072, 1458, 1888, 1808, 1315, 1678, 450, 1211, +-520, 570, -1345, -170, -1863, -816, -1994, -1105, +-1685, -1019, -1073, -831, -402, -591, 197, -197, +716, 191, 1101, 319, 1252, 315, 1195, 385, +1069, 456, 846, 403, 428, 346, -119, 319, +-598, 207, -972, -20, -1253, -258, -1351, -472, +-1141, -614, -667, -605, -116, -405, 371, -70, +788, 292, 1028, 538, 1005, 670, 853, 672, +664, 478, 350, 200, -12, 30, -251, -79, +-405, -175, -620, -210, -833, -227, -917, -348, +-861, -520, -700, -648, -373, -647, 162, -455, +793, -90, 1264, 393, 1477, 953, 1443, 1357, +1116, 1403, 446, 1107, -412, 575, -1164, -131, +-1609, -844, -1731, -1324, -1476, -1420, -819, -1228, +36, -844, 761, -330, 1224, 162, 1489, 450, +1527, 566, 1239, 618, 723, 645, 126, 639, +-467, 614, -979, 524, -1311, 382, -1419, 154, +-1264, -192, -856, -535, -273, -723, 366, -790, +926, -751, 1215, -613, 1217, -418, 1048, -250, +752, -130, 352, -26, 0, 147, -253, 379, +-502, 602, -785, 755, -1017, 860, -1169, 838, +-1212, 592, -1031, 181, -549, -220, 109, -555, +781, -813, 1385, -965, 1797, -955, 1839, -809, +1443, -565, 711, -294, -151, -21, -951, 255, +-1551, 500, -1865, 641, -1856, 703, -1550, 661, +-1003, 531, -310, 407, 426, 311, 1102, 205, +1617, 145, 1876, 70, 1854, -115, 1450, -405, +663, -722, -258, -1051, -1028, -1293, -1592, -1284, +-1867, -949, -1695, -368, -1127, 377, -443, 1147, +167, 1778, 666, 2053, 1013, 1873, 1096, 1324, +931, 532, 730, -383, 588, -1184, 390, -1626, +119, -1591, -102, -1235, -261, -748, -468, -213, +-713, 224, -846, 367, -761, 286, -558, 190, +-302, 223, 42, 389, 422, 656, 638, 915, +678, 1058, 690, 975, 696, 620, 544, 99, +274, -385, 31, -783, -165, -1034, -397, -1062, +-593, -928, -637, -767, -567, -579, -479, -328, +-325, -38, -72, 245, 181, 576, 324, 923, +384, 1179, 440, 1269, 500, 1158, 531, 845, +488, 388, 310, -211, -8, -836, -427, -1258, +-805, -1419, -981, -1427, -902, -1189, -628, -652, +-174, -39, 349, 421, 784, 745, 1024, 948, +996, 990, 622, 835, 13, 550, -568, 283, +-901, 85, -959, -162, -808, -418, -471, -559, +32, -582, 474, -566, 644, -486, 599, -294, +475, -43, 264, 116, -10, 165, -227, 137, +-273, 52, -205, -55, -146, -83, -113, -2, +-68, 156, -118, 278, -289, 292, -381, 208, +-285, 71, -134, -153, 74, -338, 402, -298, +721, -136, 812, -26, 668, 114, 409, 234, +56, 193, -358, 23, -640, -125, -693, -225, +-604, -296, -468, -348, -283, -358, -74, -281, +102, -76, 242, 167, 407, 433, 578, 735, +678, 955, 649, 912, 509, 631, 235, 208, +-127, -295, -448, -780, -622, -1063, -645, -1106, +-524, -951, -315, -640, -72, -210, 134, 254, +238, 695, 218, 1029, 163, 1213, 128, 1205, +97, 962, 61, 477, 81, -136, 195, -742, +344, -1138, 403, -1187, 324, -897, 127, -402, +-177, 176, -564, 656, -881, 858, -977, 695, +-839, 310, -528, -109, -80, -417, 402, -527, +794, -381, 1013, -49, 975, 329, 620, 613, +163, 709, -158, 547, -339, 235, -468, -131, +-484, -503, -406, -762, -391, -803, -485, -652, +-507, -347, -366, 38, -180, 438, -1, 742, +309, 859, 690, 756, 882, 489, 804, 85, +564, -413, 221, -860, -178, -1087, -532, -1097, +-693, -864, -609, -353, -393, 323, -202, 934, +-48, 1314, 83, 1366, 132, 1063, 70, 423, +-7, -344, 9, -965, 134, -1273, 270, -1246, +412, -931, 542, -457, 540, -10, 325, 250, +16, 348, -279, 350, -521, 335, -646, 351, +-566, 444, -338, 551, -91, 522, 82, 295, +207, -12, 302, -306, 302, -543, 228, -699, +203, -673, 205, -468, 143, -249, 77, -140, +116, -33, 160, 114, 77, 219, -58, 292, +-129, 444, -214, 586, -367, 557, -462, 372, +-407, 189, -318, -6, -238, -279, -51, -528, +226, -574, 379, -477, 400, -374, 421, -240, +427, 38, 334, 340, 202, 515, 72, 583, +-87, 580, -278, 397, -456, 24, -589, -361, +-598, -592, -510, -666, -386, -495, -185, -60, +106, 473, 339, 908, 426, 1101, 416, 937, +361, 450, 230, -219, 60, -844, -36, -1268, +-21, -1366, -13, -1084, -49, -460, -51, 329, +-38, 1031, -116, 1446, -259, 1513, -373, 1183, +-415, 555, -385, -188, -220, -845, 66, -1219, +324, -1194, 460, -819, 549, -245, 600, 278, +493, 608, 169, 680, -209, 503, -472, 165, +-566, -181, -520, -416, -313, -458, 20, -324, +338, -92, 517, 120, 565, 309, 461, 457, +229, 517, -58, 476, -353, 329, -583, 61, +-601, -271, -434, -606, -217, -852, 28, -951, +316, -863, 523, -610, 551, -217, 437, 219, +300, 582, 190, 807, 72, 967, -61, 1069, +-138, 1002, -152, 686, -222, 215, -418, -361, +-602, -1012, -616, -1589, -467, -1806, -255, -1547, +68, -920, 485, -113, 787, 746, 806, 1404, +660, 1586, 444, 1265, 119, 710, -279, 121, +-546, -387, -628, -672, -637, -626, -603, -363, +-415, -50, -111, 173, 142, 273, 270, 218, +359, 6, 448, -240, 430, -430, 253, -623, +47, -737, -138, -655, -340, -379, -477, -33, +-415, 359, -219, 789, -23, 1158, 161, 1337, +345, 1268, 426, 974, 344, 541, 138, -31, +-116, -626, -385, -1109, -546, -1448, -511, -1602, +-310, -1446, 20, -979, 387, -327, 602, 353, +658, 974, 618, 1392, 379, 1478, -94, 1271, +-491, 903, -637, 457, -697, 57, -706, -197, +-466, -306, -13, -400, 369, -496, 592, -566, +854, -597, 1096, -571, 1007, -463, 581, -302, +72, -116, -478, 18, -1090, 97, -1499, 140, +-1429, 191, -978, 309, -358, 558, 347, 855, +1014, 1027, 1381, 943, 1324, 592, 979, 6, +572, -655, 193, -1171, -128, -1370, -366, -1212, +-526, -708, -677, -42, -827, 461, -910, 604, +-877, 450, -744, 107, -450, -285, 3, -521, +518, -387, 968, 77, 1256, 662, 1309, 1130, +1117, 1332, 669, 1158, 53, 587, -540, -254, +-974, -1046, -1240, -1567, -1264, -1756, -985, -1603, +-518, -1081, -33, -306, 387, 436, 660, 917, +713, 1171, 532, 1173, 235, 904, -5, 481, +-113, 100, -137, -146, -99, -254, 40, -251, +206, -190, 223, -173, 126, -224, 55, -335, +3, -408, -152, -416, -334, -373, -397, -236, +-383, -35, -383, 90, -294, 163, -43, 224, +238, 269, 378, 309, 441, 395, 478, 484, +342, 495, 17, 364, -245, 98, -290, -251, +-162, -541, 74, -709, 372, -686, 594, -443, +565, -70, 251, 305, -164, 586, -519, 651, +-809, 501, -974, 231, -864, -24, -499, -240, +-37, -377, 433, -365, 862, -215, 1120, -51, +1095, 53, 795, 126, 349, 206, -136, 222, +-554, 174, -762, 132, -678, 140, -418, 152, +-123, 156, 113, 173, 213, 217, 80, 215, +-228, 77, -493, -187, -528, -446, -366, -667, +-51, -812, 429, -743, 910, -395, 1121, 79, +1005, 557, 667, 942, 175, 1093, -417, 919, +-938, 525, -1216, 31, -1242, -436, -1075, -737, +-703, -789, -148, -589, 443, -222, 897, 119, +1163, 372, 1203, 476, 980, 334, 523, -30, +1, -406, -435, -637, -766, -661, -981, -448, +-950, -57, -681, 341, -352, 665, -97, 746, +140, 520, 374, 163, 510, -151, 530, -363, +535, -382, 512, -206, 353, 36, 133, 155, +-7, 107, -144, -85, -317, -333, -396, -530, +-370, -560, -358, -373, -360, -30, -296, 290, +-138, 502, 57, 535, 242, 374, 386, 139, +486, -36, 505, -130, 403, -119, 220, -41, +97, 27, 39, 12, -74, -67, -264, -203, +-387, -314, -433, -294, -474, -163, -437, -10, +-208, 136, 124, 228, 409, 267, 603, 237, +722, 169, 659, 126, 349, 135, -80, 107, +-457, 17, -723, -76, -828, -189, -747, -346, +-470, -407, -60, -344, 361, -224, 696, -46, +934, 229, 998, 495, 773, 685, 338, 778, +-137, 727, -618, 485, -1013, 74, -1162, -436, +-1039, -855, -731, -1068, -308, -1043, 166, -720, +598, -144, 879, 426, 967, 805, 870, 935, +647, 817, 333, 495, -9, 123, -310, -170, +-512, -281, -617, -189, -639, -21, -589, 77, +-470, 119, -350, 59, -240, -125, -104, -359, +81, -514, 291, -547, 501, -484, 700, -329, +861, -56, 885, 257, 686, 540, 278, 742, +-215, 857, -668, 815, -1018, 562, -1188, 166, +-1070, -278, -685, -720, -206, -1017, 236, -1049, +649, -811, 997, -433, 1122, -18, 966, 376, +649, 651, 263, 689, -181, 522, -621, 290, +-853, 86, -818, -119, -631, -267, -373, -289, +-38, -231, 269, -144, 421, -33, 404, 40, +344, 51, 314, 6, 280, -76, 226, -172, +196, -203, 133, -149, -54, -43, -310, 86, +-515, 181, -641, 154, -674, 32, -543, -117, +-199, -204, 240, -152, 588, 62, 821, 331, +944, 540, 823, 580, 421, 388, -67, -17, +-465, -514, -758, -927, -907, -1049, -822, -814, +-497, -344, -110, 188, 163, 696, 300, 1019, +371, 992, 313, 657, 142, 222, 30, -192, +92, -487, 202, -572, 279, -415, 358, -107, +390, 212, 218, 396, -114, 396, -427, 219, +-673, -84, -848, -460, -831, -719, -590, -705, +-230, -430, 196, -16, 621, 435, 906, 842, +974, 1057, 854, 933, 586, 531, 162, 25, +-348, -405, -752, -682, -901, -775, -857, -652, +-669, -350, -286, -32, 217, 199, 580, 364, +718, 496, 725, 508, 626, 409, 361, 270, +18, 58, -247, -266, -416, -581, -568, -758, +-642, -723, -551, -499, -339, -125, -110, 319, +156, 682, 467, 803, 688, 699, 723, 477, +631, 199, 446, -71, 179, -182, -115, -172, +-377, -181, -558, -220, -596, -274, -520, -384, +-406, -486, -230, -515, 5, -453, 157, -302, +194, -81, 198, 103, 194, 218, 163, 313, +143, 396, 205, 464, 349, 554, 427, 616, +374, 581, 231, 408, -5, 107, -385, -291, +-779, -673, -974, -936, -904, -974, -626, -772, +-190, -431, 319, -72, 768, 238, 994, 390, +954, 342, 707, 183, 294, 20, -189, -114, +-571, -143, -768, -30, -772, 163, -608, 348, +-336, 521, -32, 638, 237, 639, 402, 507, +449, 271, 420, -60, 344, -457, 245, -817, +171, -1005, 122, -1033, 63, -908, -36, -612, +-200, -213, -431, 153, -679, 437, -871, 628, +-858, 706, -553, 718, -9, 740, 605, 728, +1154, 660, 1490, 530, 1435, 320, 942, 12, +218, -365, -494, -760, -1048, -1033, -1352, -1083, +-1280, -918, -860, -565, -321, -60, 151, 427, +522, 741, 727, 846, 666, 733, 426, 416, +225, 33, 109, -279, -8, -413, -97, -341, +-69, -152, 19, 61, 38, 291, -12, 466, +-40, 504, -83, 433, -212, 328, -328, 166, +-297, -51, -185, -287, -92, -518, 5, -727, +165, -850, 308, -811, 339, -579, 288, -221, +267, 183, 213, 577, 45, 873, -151, 933, +-245, 778, -294, 507, -379, 176, -431, -155, +-334, -365, -122, -411, 58, -351, 201, -263, +404, -166, 561, -87, 489, -71, 271, -132, +87, -218, -79, -267, -300, -240, -486, -157, +-479, -40, -350, 91, -263, 261, -153, 401, +102, 407, 325, 295, 364, 163, 358, 0, +361, -184, 189, -303, -100, -300, -267, -229, +-262, -129, -216, -16, -154, 78, -38, 110, +79, 94, 78, 77, -4, 67, -46, -11, +-27, -116, 27, -184, 148, -257, 323, -337, +428, -310, 372, -150, 171, 55, -115, 258, +-402, 460, -621, 580, -712, 567, -633, 436, +-412, 233, -129, -8, 183, -247, 512, -485, +778, -676, 898, -765, 880, -715, 719, -523, +412, -199, 5, 231, -442, 689, -856, 1016, +-1106, 1106, -1147, 940, -979, 567, -607, 56, +-95, -438, 391, -768, 747, -868, 975, -752, +1052, -480, 915, -177, 616, 62, 272, 182, +-58, 207, -378, 195, -611, 213, -707, 298, +-725, 460, -667, 588, -506, 578, -314, 415, +-123, 121, 82, -293, 273, -701, 462, -918, +654, -868, 753, -598, 709, -154, 558, 334, +297, 703, -82, 871, -472, 810, -734, 508, +-792, 93, -685, -275, -505, -503, -283, -559, +-19, -436, 204, -212, 334, 18, 390, 167, +413, 183, 402, 79, 334, -53, 227, -146, +145, -147, 56, -35, -92, 151, -242, 319, +-306, 395, -329, 347, -353, 207, -322, -2, +-180, -221, 31, -360, 242, -383, 413, -332, +497, -235, 405, -126, 131, -49, -218, -19, +-531, -15, -715, -33, -665, -44, -337, -26, +156, 23, 629, 101, 961, 208, 1072, 312, +903, 396, 446, 446, -169, 427, -724, 272, +-1075, -9, -1202, -348, -1051, -671, -630, -929, +-97, -1030, 367, -888, 722, -494, 926, 22, +926, 526, 738, 914, 437, 1096, 81, 1002, +-239, 681, -457, 252, -576, -163, -598, -494, +-491, -671, -278, -671, -60, -517, 96, -291, +216, -60, 298, 140, 265, 282, 126, 314, +12, 243, -23, 114, -25, -28, -19, -151, +33, -202, 148, -190, 226, -126, 146, -17, +-20, 111, -174, 227, -340, 336, -476, 424, +-400, 467, -132, 431, 139, 282, 324, -14, +432, -395, 422, -737, 264, -932, 14, -923, +-195, -660, -282, -178, -279, 363, -230, 771, +-154, 949, -81, 882, -23, 606, 37, 214, +133, -121, 281, -278, 423, -255, 466, -146, +379, -3, 179, 109, -141, 97, -508, -41, +-741, -210, -758, -368, -614, -480, -335, -497, +72, -416, 468, -298, 696, -143, 733, 75, +632, 328, 400, 553, 86, 750, -190, 878, +-330, 859, -348, 680, -286, 374, -168, -29, +-32, -444, 49, -770, 30, -967, -86, -1035, +-237, -923, -348, -660, -368, -344, -266, -1, +-52, 361, 237, 639, 554, 746, 805, 704, +864, 577, 698, 384, 390, 159, -44, -22, +-564, -89, -970, -79, -1124, -71, -1075, -107, +-817, -182, -302, -304, 366, -426, 950, -482, +1287, -451, 1325, -339, 1043, -141, 436, 90, +-342, 289, -998, 411, -1340, 446, -1344, 390, +-979, 266, -317, 97, 382, -87, 884, -234, +1132, -283, 1110, -225, 806, -70, 301, 130, +-219, 299, -616, 355, -851, 272, -892, 67, +-689, -208, -299, -481, 130, -647, 476, -641, +665, -477, 657, -226, 441, 66, 64, 341, +-314, 545, -524, 653, -519, 682, -331, 626, +-15, 486, 306, 276, 499, 31, 513, -238, +381, -518, 152, -743, -123, -812, -395, -741, +-566, -585, -586, -347, -496, -30, -316, 249, +-21, 432, 297, 563, 529, 655, 678, 669, +733, 619, 573, 520, 217, 378, -150, 184, +-436, -51, -659, -297, -740, -513, -583, -690, +-261, -817, 74, -863, 343, -805, 494, -616, +475, -264, 304, 177, 75, 622, -137, 1042, +-280, 1320, -319, 1276, -247, 942, -96, 454, +89, -136, 241, -730, 321, -1106, 330, -1189, +258, -1044, 87, -707, -111, -203, -257, 327, +-329, 727, -315, 928, -241, 916, -175, 661, +-102, 210, 3, -288, 95, -662, 141, -819, +183, -716, 222, -400, 210, 2, 132, 330, +-2, 467, -143, 389, -201, 205, -118, 32, +85, -58, 314, -4, 463, 206, 454, 428, +210, 489, -217, 337, -633, 23, -901, -368, +-976, -712, -774, -888, -275, -829, 298, -583, +721, -250, 952, 93, 1000, 384, 824, 532, +463, 555, 81, 569, -193, 577, -404, 493, +-589, 365, -667, 232, -588, 16, -444, -267, +-291, -484, -100, -611, 104, -661, 240, -591, +338, -400, 444, -171, 457, 42, 293, 223, +80, 356, -46, 417, -135, 411, -214, 340, +-192, 209, -93, 43, -15, -101, 52, -185, +148, -206, 202, -152, 143, -13, -22, 129, +-221, 209, -373, 215, -441, 146, -431, -15, +-297, -225, -18, -395, 271, -477, 457, -468, +594, -336, 648, -74, 495, 244, 178, 488, +-113, 593, -306, 523, -432, 274, -453, -79, +-320, -379, -122, -506, -7, -415, 17, -142, +34, 206, 9, 481, -121, 568, -241, 421, +-169, 115, 63, -212, 286, -446, 450, -531, +580, -462, 571, -327, 318, -206, -42, -129, +-301, -104, -465, -112, -587, -36, -572, 182, +-362, 456, -109, 700, 44, 858, 169, 823, +353, 559, 451, 136, 378, -337, 262, -748, +165, -984, -20, -1010, -251, -829, -355, -490, +-305, -103, -211, 234, -118, 511, -8, 680, +103, 681, 136, 533, 66, 309, 14, 61, +67, -157, 126, -302, 118, -310, 126, -162, +181, 63, 155, 247, -4, 339, -167, 298, +-258, 86, -339, -237, -396, -513, -329, -640, +-132, -594, 77, -383, 235, -26, 353, 348, +406, 578, 341, 623, 179, 518, 2, 278, +-131, -8, -214, -209, -232, -275, -178, -209, +-71, -23, 38, 177, 100, 270, 100, 247, +56, 121, -26, -112, -114, -343, -170, -468, +-185, -493, -176, -429, -113, -243, 33, -6, +197, 203, 315, 400, 376, 575, 363, 659, +241, 636, 21, 490, -231, 216, -444, -127, +-546, -469, -478, -735, -270, -802, 12, -654, +307, -395, 492, -87, 501, 220, 385, 414, +183, 468, -63, 446, -224, 380, -250, 269, +-225, 144, -218, 9, -203, -150, -170, -333, +-117, -480, -25, -514, 97, -393, 227, -174, +337, 83, 354, 344, 242, 524, 75, 516, +-77, 340, -217, 98, -288, -141, -229, -356, +-124, -462, -49, -395, 43, -224, 139, -64, +160, 78, 124, 183, 69, 187, -23, 75, +-112, -63, -150, -159, -170, -178, -149, -99, +-22, 53, 128, 232, 183, 394, 156, 442, +86, 317, -27, 75, -103, -199, -76, -446, +-7, -581, 55, -534, 140, -326, 195, -51, +121, 210, -59, 389, -225, 436, -308, 332, +-294, 136, -189, -44, -27, -180, 133, -295, +212, -316, 183, -213, 114, -63, 60, 98, +11, 295, -18, 456, 8, 493, 44, 398, +34, 191, 1, -94, -13, -350, -19, -492, +-25, -483, -14, -332, 18, -101, 19, 90, +-51, 177, -166, 159, -255, 82, -265, 14, +-169, 20, 28, 103, 257, 221, 393, 307, +385, 307, 272, 211, 108, 63, -54, -85, +-164, -192, -221, -232, -209, -213, -113, -179, +-8, -137, 14, -83, 6, -22, 40, 54, +50, 165, -18, 259, -78, 264, -67, 199, +-61, 109, -89, -23, -39, -159, 117, -224, +240, -215, 250, -178, 204, -125, 123, -84, +-25, -64, -189, -27, -255, 52, -227, 137, +-181, 236, -119, 339, -7, 380, 122, 341, +222, 253, 279, 100, 273, -97, 179, -295, +14, -488, -188, -669, -380, -774, -500, -763, +-505, -605, -346, -261, -15, 220, 348, 709, +585, 1116, 672, 1306, 622, 1156, 396, 718, +41, 129, -284, -498, -480, -1006, -571, -1245, +-586, -1194, -507, -938, -316, -545, -73, -101, +157, 300, 394, 609, 639, 813, 751, 888, +617, 805, 319, 570, -36, 250, -454, -108, +-833, -440, -943, -652, -707, -702, -277, -639, +207, -497, 652, -305, 920, -107, 886, 55, +583, 207, 167, 368, -226, 505, -540, 556, +-722, 498, -713, 363, -540, 179, -302, -33, +-9, -188, 336, -242, 586, -244, 626, -247, +544, -272, 391, -354, 96, -440, -240, -434, +-406, -299, -405, -39, -351, 335, -214, 696, +5, 874, 171, 827, 190, 584, 109, 164, +16, -311, -65, -653, -140, -763, -171, -650, +-81, -348, 118, 65, 309, 471, 424, 727, +471, 738, 385, 523, 81, 149, -357, -309, +-720, -699, -915, -880, -908, -817, -613, -535, +-55, -75, 550, 410, 1015, 760, 1259, 923, +1186, 876, 753, 618, 94, 267, -560, -73, +-1029, -369, -1250, -563, -1189, -608, -824, -553, +-269, -430, 260, -232, 670, 15, 967, 240, +1064, 401, 842, 452, 402, 365, -27, 151, +-342, -109, -594, -312, -726, -378, -618, -282, +-337, -48, -67, 229, 140, 437, 300, 475, +356, 316, 244, 23, 38, -291, -111, -528, +-124, -614, -59, -517, 18, -275, 137, 35, +276, 344, 297, 553, 173, 603, 28, 498, +-103, 250, -282, -125, -446, -501, -459, -736, +-302, -782, -51, -628, 227, -262, 462, 192, +564, 562, 467, 758, 193, 742, -131, 519, +-371, 197, -473, -105, -408, -332, -168, -462, +144, -497, 343, -489, 357, -460, 250, -390, +71, -259, -160, -37, -330, 270, -331, 574, +-185, 782, 8, 811, 180, 618, 289, 240, +322, -210, 271, -624, 123, -899, -54, -933, +-176, -707, -265, -333, -314, 86, -243, 488, +-68, 778, 81, 863, 137, 744, 132, 490, +94, 149, -5, -224, -138, -513, -204, -658, +-150, -642, -41, -484, 77, -240, 216, 15, +332, 225, 369, 337, 331, 336, 240, 269, +101, 210, -69, 182, -245, 199, -428, 248, +-589, 273, -665, 229, -613, 105, -432, -120, +-116, -390, 286, -604, 627, -709, 796, -696, +808, -520, 665, -188, 363, 211, 3, 604, +-277, 928, -423, 1086, -430, 1041, -340, 776, +-246, 311, -199, -242, -175, -738, -146, -1083, +-85, -1186, 33, -1011, 178, -622, 295, -131, +342, 351, 280, 684, 109, 809, -70, 737, +-177, 506, -229, 196, -229, -67, -142, -221, +11, -245, 157, -141, 249, 18, 281, 119, +260, 111, 182, -10, 62, -206, -53, -400, +-130, -506, -183, -456, -226, -244, -251, 46, +-229, 302, -176, 443, -155, 442, -159, 312, +-92, 107, 50, -85, 190, -189, 323, -197, +448, -157, 474, -108, 352, -44, 149, 3, +-52, 13, -228, 31, -354, 84, -360, 120, +-254, 98, -156, 24, -92, -76, -5, -194, +65, -295, 53, -331, 19, -253, 34, -83, +73, 105, 82, 270, 68, 379, 74, 357, +80, 239, 14, 107, -75, -34, -91, -179, +-85, -266, -113, -291, -101, -288, -7, -258, +101, -182, 169, -62, 200, 118, 200, 324, +180, 470, 106, 523, -48, 469, -215, 280, +-310, 1, -353, -287, -358, -520, -257, -644, +-45, -620, 146, -479, 261, -257, 366, 18, +463, 288, 454, 491, 324, 616, 131, 635, +-106, 519, -386, 293, -634, 35, -723, -197, +-593, -352, -303, -388, 66, -310, 463, -176, +791, -36, 907, 71, 771, 96, 474, 28, +88, -78, -327, -160, -632, -189, -754, -156, +-754, -44, -665, 138, -444, 335, -122, 469, +198, 492, 455, 396, 632, 185, 688, -122, +584, -423, 347, -590, 77, -579, -152, -407, +-306, -104, -342, 250, -252, 540, -112, 665, +21, 562, 82, 268, 18, -96, -121, -442, +-245, -699, -333, -761, -353, -586, -234, -267, +20, 101, 299, 461, 511, 719, 628, 793, +611, 684, 390, 443, 8, 118, -350, -244, +-573, -564, -668, -750, -611, -756, -397, -603, +-84, -341, 248, -25, 517, 279, 665, 477, +652, 526, 451, 467, 124, 362, -200, 241, +-461, 122, -636, 16, -661, -86, -520, -231, +-275, -422, 25, -586, 325, -626, 544, -511, +627, -254, 554, 117, 361, 506, 113, 746, +-133, 760, -344, 579, -473, 276, -467, -78, +-338, -369, -148, -520, 50, -540, 226, -459, +344, -320, 369, -182, 312, -42, 213, 121, +88, 277, -75, 399, -244, 480, -346, 481, +-360, 380, -324, 196, -251, -45, -115, -310, +52, -521, 187, -629, 287, -630, 380, -518, +435, -296, 401, -10, 304, 306, 195, 593, +30, 771, -207, 802, -437, 692, -585, 425, +-613, 38, -515, -361, -323, -674, -70, -844, +174, -811, 336, -580, 429, -241, 480, 115, +458, 421, 365, 598, 255, 609, 127, 483, +-23, 282, -178, 55, -322, -160, -430, -306, +-494, -347, -521, -305, -460, -205, -267, -68, +-10, 73, 242, 166, 485, 185, 680, 140, +742, 77, 630, 26, 381, 4, 57, 23, +-323, 74, -687, 99, -884, 69, -852, -7, +-643, -112, -293, -212, 173, -270, 644, -292, +950, -255, 982, -139, 759, 5, 367, 134, +-122, 281, -594, 431, -880, 497, -904, 450, +-722, 316, -380, 77, 72, -228, 487, -478, +713, -602, 741, -603, 623, -483, 374, -255, +44, 10, -245, 228, -411, 374, -467, 465, +-424, 513, -272, 504, -71, 424, 77, 261, +142, 10, 156, -302, 122, -596, 31, -792, +-59, -835, -76, -688, -20, -360, 50, 62, +110, 464, 194, 752, 288, 874, 295, 812, +190, 596, 61, 291, -90, -25, -294, -292, +-442, -479, -446, -574, -378, -574, -287, -498, +-131, -381, 70, -257, 218, -130, 292, -5, +360, 96, 429, 188, 414, 320, 298, 477, +170, 591, 43, 637, -141, 606, -354, 431, +-495, 82, -511, -354, -439, -736, -309, -981, +-93, -1040, 152, -869, 293, -489, 329, -18, +339, 418, 289, 748, 155, 938, 48, 950, +43, 800, 81, 542, 90, 219, 56, -146, +-20, -501, -167, -776, -385, -916, -558, -905, +-581, -756, -467, -483, -252, -112, 81, 279, +483, 598, 788, 816, 877, 928, 789, 887, +567, 681, 185, 354, -291, -17, -666, -365, +-838, -628, -842, -751, -686, -714, -356, -571, +53, -401, 390, -241, 563, -102, 576, 19, +462, 153, 250, 341, 13, 571, -137, 753, +-167, 804, -139, 684, -109, 389, -49, -49, +26, -514, 35, -837, -23, -927, -57, -795, +-49, -490, -49, -98, -44, 266, 10, 496, +73, 564, 67, 502, 7, 372, -24, 225, +-47, 99, -124, 12, -193, -58, -151, -150, +-36, -253, 76, -330, 182, -377, 292, -394, +351, -337, 299, -199, 155, -15, -5, 194, +-160, 413, -304, 593, -364, 686, -294, 650, +-173, 471, -63, 162, 15, -229, 41, -617, +11, -875, -26, -907, -19, -714, 53, -360, +156, 67, 245, 445, 288, 667, 256, 686, +150, 525, 14, 261, -115, 0, -203, -191, +-208, -284, -158, -266, -126, -161, -126, -40, +-136, 56, -140, 104, -131, 81, -66, -5, +83, -111, 240, -185, 307, -174, 308, -79, +271, 61, 150, 197, -36, 277, -171, 248, +-210, 104, -187, -114, -124, -328, -40, -455, +28, -438, 52, -287, 26, -41, -29, 241, +-78, 475, -91, 590, -76, 576, -31, 443, +72, 222, 196, -35, 260, -272, 254, -442, +192, -539, 79, -576, -64, -545, -202, -445, +-304, -297, -340, -101, -317, 161, -248, 457, +-110, 709, 96, 861, 280, 865, 387, 683, +440, 307, 430, -205, 305, -693, 89, -1002, +-134, -1074, -335, -898, -509, -474, -566, 98, +-448, 610, -239, 902, -24, 925, 186, 679, +347, 234, 402, -248, 358, -593, 274, -702, +192, -570, 122, -255, 45, 139, -14, 456, +-71, 568, -199, 475, -359, 242, -442, -60, +-440, -340, -381, -493, -233, -476, 11, -329, +268, -108, 439, 135, 519, 338, 540, 450, +467, 446, 296, 334, 109, 164, -51, -13, +-224, -171, -403, -288, -537, -328, -589, -294, +-549, -233, -423, -168, -220, -87, 52, -13, +326, 33, 544, 71, 691, 132, 741, 199, +645, 243, 414, 277, 90, 312, -260, 322, +-558, 267, -733, 126, -753, -80, -624, -289, +-388, -467, -82, -581, 226, -573, 456, -427, +569, -190, 559, 71, 441, 287, 264, 392, +62, 375, -137, 290, -281, 193, -337, 116, +-325, 87, -257, 109, -133, 158, 16, 170, +115, 82, 140, -88, 140, -271, 138, -430, +86, -519, 2, -468, -46, -273, -54, -27, +-62, 179, -73, 295, -73, 303, -57, 210, +-48, 83, -29, 12, 51, 52, 162, 181, +219, 321, 216, 376, 160, 269, 41, -12, +-103, -395, -226, -739, -308, -898, -328, -796, +-252, -446, -100, 78, 56, 631, 175, 1004, +253, 1066, 272, 833, 201, 395, 100, -122, +32, -563, -20, -798, -69, -792, -80, -596, +-53, -306, -17, -25, -10, 169, -41, 243, +-78, 220, -103, 175, -141, 154, -154, 145, +-84, 142, 31, 162, 121, 197, 179, 205, +207, 166, 182, 100, 108, 14, 40, -109, +17, -267, 11, -410, -8, -485, -39, -471, +-90, -352, -158, -131, -221, 117, -249, 304, +-212, 396, -116, 392, -7, 313, 116, 206, +257, 122, 358, 84, 374, 82, 334, 81, +251, 48, 102, -19, -104, -114, -296, -225, +-440, -316, -537, -360, -543, -365, -385, -342, +-107, -288, 169, -176, 385, 21, 530, 278, +571, 550, 484, 788, 296, 919, 103, 848, +-41, 544, -183, 66, -350, -491, -473, -993, +-525, -1295, -532, -1303, -482, -1011, -297, -494, +40, 117, 418, 692, 713, 1103, 905, 1267, +921, 1180, 663, 892, 194, 472, -291, 18, +-683, -388, -935, -699, -984, -892, -783, -940, +-399, -847, 4, -657, 328, -415, 580, -152, +712, 109, 665, 353, 499, 569, 311, 746, +104, 865, -114, 871, -275, 730, -343, 462, +-362, 97, -358, -327, -298, -719, -178, -969, +-65, -1030, 29, -915, 116, -662, 164, -325, +153, 43, 114, 396, 76, 677, 52, 848, +51, 888, 86, 775, 155, 522, 216, 182, +201, -181, 97, -507, -65, -725, -240, -779, +-391, -681, -471, -488, -424, -242, -223, 32, +54, 291, 323, 492, 536, 623, 617, 668, +478, 581, 161, 361, -200, 63, -490, -257, +-662, -548, -659, -731, -432, -740, -48, -576, +336, -298, 629, 18, 781, 313, 729, 533, +468, 635, 109, 609, -239, 495, -507, 333, +-679, 123, -730, -125, -641, -358, -450, -525, +-210, -619, 91, -625, 420, -499, 678, -230, +810, 104, 806, 410, 644, 630, 322, 715, +-100, 617, -505, 352, -798, 18, -929, -300, +-846, -548, -539, -638, -126, -513, 257, -230, +534, 95, 677, 378, 663, 553, 503, 537, +256, 305, 35, -35, -110, -330, -209, -486, +-253, -457, -216, -253, -166, 40, -167, 281, +-208, 358, -238, 250, -248, 35, -235, -165, +-151, -257, 45, -189, 280, 29, 463, 283, +570, 422, 581, 385, 464, 193, 233, -85, +-60, -353, -328, -497, -501, -452, -578, -273, +-568, -60, -455, 126, -261, 243, -42, 256, +167, 180, 368, 75, 528, -6, 577, -41, +488, -22, 299, 31, 30, 79, -272, 102, +-485, 86, -526, 35, -431, -40, -239, -135, +26, -226, 288, -260, 443, -210, 433, -103, +289, 13, 85, 126, -136, 215, -310, 237, +-362, 174, -303, 63, -205, -50, -94, -130, +47, -168, 190, -154, 259, -95, 250, -17, +238, 56, 235, 118, 173, 155, 56, 157, +-62, 129, -189, 73, -340, -26, -458, -148, +-472, -229, -354, -246, -147, -202, 105, -89, +383, 67, 612, 192, 680, 221, 565, 155, +326, 34, 24, -83, -300, -131, -561, -92, +-659, 4, -579, 112, -408, 174, -180, 143, +88, 32, 307, -95, 411, -172, 436, -160, +403, -57, 301, 76, 139, 152, -18, 134, +-134, 42, -221, -90, -284, -206, -284, -245, +-216, -189, -134, -59, -79, 102, -16, 245, +79, 322, 184, 314, 256, 234, 307, 117, +342, -15, 285, -161, 94, -290, -129, -341, +-315, -308, -473, -226, -557, -101, -468, 60, +-219, 195, 69, 260, 290, 260, 441, 213, +511, 128, 460, 46, 318, -1, 185, -7, +87, 15, -24, 30, -163, 10, -282, -44, +-364, -133, -457, -245, -553, -335, -530, -360, +-356, -302, -99, -178, 203, -3, 511, 201, +734, 382, 809, 494, 712, 545, 467, 543, +134, 465, -221, 291, -538, 49, -741, -219, +-764, -498, -597, -754, -322, -910, -20, -904, +274, -718, 514, -372, 601, 87, 521, 572, +324, 946, 37, 1104, -296, 1010, -544, 682, +-603, 204, -458, -276, -187, -603, 145, -690, +483, -553, 707, -275, 720, 12, 543, 185, +222, 166, -187, -35, -553, -296, -734, -476, +-704, -491, -521, -316, -258, 14, 26, 408, +259, 726, 382, 849, 386, 755, 330, 491, +259, 116, 180, -287, 87, -615, 18, -785, +-3, -774, -25, -593, -95, -272, -149, 100, +-154, 411, -163, 597, -195, 630, -180, 508, +-104, 260, -21, -36, 42, -293, 123, -440, +219, -458, 244, -370, 168, -215, 83, -18, +35, 176, -28, 308, -94, 358, -92, 325, +-45, 216, -50, 51, -127, -118, -197, -246, +-230, -318, -227, -310, -120, -202, 137, -20, +422, 172, 598, 333, 617, 433, 478, 427, +176, 286, -227, 51, -602, -212, -811, -440, +-814, -599, -646, -635, -318, -511, 114, -265, +487, 41, 687, 344, 739, 585, 690, 711, +491, 699, 149, 549, -185, 288, -398, -6, +-547, -265, -616, -448, -481, -528, -198, -509, +45, -427, 200, -313, 322, -175, 370, -47, +264, 39, 76, 113, -45, 203, -68, 282, +-71, 325, -58, 338, 16, 337, 84, 327, +43, 282, -61, 188, -135, 46, -176, -152, +-220, -397, -217, -626, -98, -762, 86, -756, +236, -569, 354, -214, 432, 209, 407, 586, +269, 830, 69, 881, -135, 741, -303, 460, +-421, 112, -475, -213, -446, -450, -342, -581, +-212, -608, -65, -526, 122, -357, 322, -145, +467, 68, 564, 253, 638, 367, 591, 379, +337, 290, -17, 137, -343, -40, -636, -191, +-844, -250, -830, -190, -581, -50, -235, 122, +94, 282, 400, 362, 637, 320, 699, 158, +567, -83, 356, -325, 136, -491, -84, -538, +-262, -449, -333, -240, -311, 33, -262, 299, +-237, 497, -204, 571, -157, 482, -112, 276, +-41, 28, 90, -204, 238, -369, 370, -417, +449, -338, 408, -181, 230, -30, -26, 63, +-285, 100, -454, 106, -471, 105, -327, 139, +-86, 238, 151, 341, 285, 356, 279, 242, +161, 2, 6, -320, -115, -612, -150, -754, +-78, -674, 65, -378, 169, 52, 173, 476, +84, 752, -66, 788, -218, 588, -284, 243, +-226, -124, -64, -403, 124, -505, 266, -411, +323, -189, 280, 52, 137, 206, -39, 231, +-168, 130, -224, -57, -209, -229, -137, -289, +-44, -211, 43, -28, 95, 192, 104, 374, +86, 440, 48, 344, -23, 120, -99, -147, +-135, -370, -109, -498, -48, -496, 18, -347, +97, -95, 186, 176, 213, 399, 175, 536, +127, 542, 61, 402, -48, 170, -151, -78, +-199, -301, -209, -452, -206, -473, -163, -362, +-67, -172, 34, 33, 105, 195, 159, 271, +178, 233, 128, 98, 38, -76, -27, -224, +-52, -295, -48, -264, -19, -119, 41, 116, +95, 352, 87, 505, 23, 542, -26, 465, +-55, 275, -97, 4, -119, -277, -100, -499, +-85, -626, -95, -646, -101, -551, -63, -360, +16, -117, 117, 127, 228, 326, 320, 441, +341, 453, 268, 400, 108, 342, -95, 295, +-272, 248, -389, 187, -446, 87, -398, -87, +-244, -328, -48, -559, 143, -690, 304, -656, +413, -452, 450, -133, 380, 210, 213, 467, +-3, 553, -217, 460, -378, 253, -418, 40, +-314, -101, -106, -131, 122, -49, 302, 96, +386, 218, 326, 264, 107, 207, -173, 45, +-397, -198, -518, -443, -509, -602, -333, -640, +-23, -540, 319, -292, 597, 65, 748, 430, +722, 707, 502, 825, 130, 743, -274, 478, +-611, 111, -795, -260, -766, -532, -531, -625, +-169, -528, 223, -291, 518, 1, 631, 249, +556, 370, 331, 335, 40, 169, -216, -63, +-383, -285, -434, -434, -377, -465, -250, -358, +-76, -136, 118, 151, 285, 450, 410, 692, +478, 801, 449, 728, 299, 465, 60, 59, +-210, -383, -462, -746, -656, -926, -705, -868, +-546, -593, -240, -198, 98, 186, 416, 458, +655, 577, 727, 545, 603, 396, 339, 194, +14, 4, -302, -134, -533, -210, -603, -223, +-497, -174, -278, -90, -7, 9, 260, 95, +421, 129, 426, 97, 298, 26, 76, -51, +-164, -97, -316, -92, -321, -44, -194, 13, +1, 57, 207, 55, 360, -8, 388, -107, +267, -184, 61, -203, -169, -156, -374, -50, +-501, 78, -499, 192, -352, 270, -112, 292, +131, 258, 336, 184, 485, 79, 543, -49, +487, -173, 350, -267, 159, -310, -58, -293, +-260, -221, -402, -123, -476, -30, -491, 32, +-452, 49, -331, 42, -118, 56, 145, 113, +396, 213, 566, 326, 587, 401, 455, 374, +215, 214, -74, -47, -323, -332, -452, -547, +-438, -608, -287, -491, -65, -242, 137, 44, +237, 266, 189, 352, 38, 303, -94, 188, +-145, 84, -97, 41, 38, 65, 210, 116, +347, 136, 379, 83, 279, -43, 83, -193, +-184, -306, -462, -332, -642, -258, -670, -112, +-551, 58, -283, 195, 88, 280, 458, 310, +749, 280, 912, 202, 869, 88, 600, -58, +187, -210, -257, -324, -650, -364, -886, -320, +-881, -189, -671, -12, -372, 151, -42, 269, +283, 322, 513, 303, 592, 251, 579, 205, +494, 161, 317, 100, 91, 9, -130, -119, +-331, -270, -489, -406, -554, -485, -452, -480, +-214, -374, 46, -177, 270, 63, 438, 289, +474, 473, 356, 588, 154, 611, -38, 531, +-179, 358, -270, 115, -280, -165, -200, -446, +-104, -659, -48, -741, -12, -661, 33, -442, +78, -117, 113, 240, 134, 529, 149, 680, +145, 661, 107, 483, 34, 212, -35, -73, +-79, -326, -109, -498, -135, -540, -146, -466, +-129, -315, -116, -105, -138, 126, -147, 301, +-91, 391, 13, 393, 139, 301, 292, 150, +429, 13, 493, -64, 445, -75, 279, -44, +31, -29, -280, -91, -599, -229, -796, -396, +-798, -517, -619, -519, -301, -363, 87, -67, +448, 301, 698, 625, 783, 803, 718, 801, +530, 631, 240, 339, -78, 3, -330, -325, +-480, -599, -517, -759, -468, -767, -350, -638, +-182, -399, -13, -79, 112, 243, 197, 472, +236, 571, 200, 537, 99, 406, 15, 244, +-5, 123, 18, 61, 53, 26, 105, -23, +147, -109, 126, -244, 31, -408, -72, -538, +-167, -555, -272, -424, -332, -171, -273, 142, +-107, 448, 93, 677, 262, 764, 389, 681, +442, 461, 351, 165, 141, -154, -86, -458, +-288, -671, -452, -733, -528, -637, -458, -409, +-242, -87, 12, 258, 223, 530, 400, 647, +506, 594, 473, 402, 334, 136, 177, -116, +6, -260, -192, -270, -356, -201, -402, -124, +-355, -79, -280, -86, -161, -119, 14, -137, +163, -94, 229, 24, 237, 180, 206, 292, +102, 317, -41, 254, -137, 125, -149, -19, +-106, -99, -28, -116, 88, -116, 209, -120, +240, -156, 161, -238, 40, -325, -104, -337, +-269, -215, -390, 27, -373, 329, -202, 595, +26, 741, 231, 695, 398, 432, 457, 17, +336, -431, 101, -805, -150, -1001, -352, -941, +-451, -628, -412, -149, -218, 368, 60, 788, +296, 1001, 432, 940, 470, 629, 389, 177, +187, -271, -69, -614, -281, -794, -415, -773, +-497, -578, -487, -307, -339, -39, -111, 199, +114, 389, 336, 499, 547, 523, 639, 475, +543, 351, 333, 148, 81, -98, -195, -329, +-445, -480, -579, -514, -557, -428, -436, -251, +-264, -43, -25, 109, 217, 154, 345, 116, +369, 49, 356, 0, 298, 31, 185, 169, +61, 364, -17, 513, -86, 533, -185, 381, +-237, 78, -212, -301, -201, -652, -192, -869, +-115, -886, 5, -704, 115, -369, 193, 51, +225, 468, 191, 795, 75, 978, -60, 971, +-128, 769, -107, 407, -26, -39, 81, -472, +184, -775, 231, -885, 152, -800, -48, -546, +-282, -197, -459, 133, -516, 388, -396, 545, +-87, 575, 293, 486, 570, 341, 676, 171, +605, -21, 352, -200, -19, -300, -370, -307, +-584, -245, -617, -139, -502, -4, -250, 115, +83, 166, 334, 153, 424, 105, 396, 41, +282, -11, 112, -45, -79, -57, -223, -51, +-260, -32, -223, -12, -148, 12, -24, 53, +103, 90, 178, 81, 191, 32, 169, -32, +146, -93, 94, -133, -16, -120, -127, -39, +-211, 76, -289, 162, -324, 183, -257, 124, +-92, -10, 117, -172, 313, -268, 467, -263, +508, -164, 372, 11, 100, 194, -192, 287, +-415, 264, -523, 151, -469, -10, -250, -155, +24, -215, 255, -199, 391, -154, 380, -119, +231, -132, 20, -181, -177, -189, -275, -109, +-243, 70, -111, 319, 64, 554, 192, 650, +228, 533, 178, 213, 30, -215, -157, -618, +-286, -864, -309, -873, -208, -629, -10, -226, +204, 186, 355, 508, 372, 670, 248, 623, +53, 407, -151, 132, -305, -103, -349, -241, +-272, -256, -122, -172, 26, -45, 120, 53, +145, 60, 110, -27, 53, -150, 40, -254, +104, -284, 200, -195, 238, -3, 191, 196, +80, 324, -103, 358, -320, 289, -466, 137, +-481, -27, -373, -137, -173, -162, 93, -127, +370, -72, 532, -28, 534, -9, 430, -13, +244, -8, 12, 26, -207, 94, -385, 159, +-476, 186, -443, 150, -302, 47, -81, -98, +150, -228, 322, -285, 388, -221, 320, -55, +173, 146, 13, 309, -149, 387, -260, 335, +-261, 165, -179, -39, -67, -190, 52, -255, +163, -220, 225, -91, 199, 58, 129, 145, +63, 159, -34, 104, -170, -11, -262, -133, +-250, -199, -165, -191, -37, -109, 145, 28, +310, 178, 339, 289, 231, 315, 58, 231, +-142, 77, -333, -98, -429, -236, -342, -286, +-116, -214, 120, -55, 316, 119, 449, 224, +435, 219, 273, 113, 54, -60, -135, -237, +-277, -344, -388, -345, -415, -258, -325, -128, +-197, 21, -70, 160, 90, 262, 257, 315, +369, 330, 396, 310, 365, 247, 314, 129, +201, -15, 22, -155, -147, -274, -285, -365, +-407, -419, -494, -442, -499, -431, -394, -385, +-211, -280, 15, -106, 271, 129, 506, 379, +628, 591, 591, 706, 447, 675, 251, 501, +-1, 244, -246, -51, -372, -319, -383, -492, +-367, -556, -342, -553, -275, -500, -177, -414, +-100, -319, -12, -200, 142, -34, 287, 160, +350, 361, 360, 531, 332, 604, 256, 546, +129, 389, -9, 168, -91, -57, -140, -211, +-199, -259, -234, -236, -249, -199, -272, -194, +-279, -221, -249, -265, -152, -301, 6, -271, +179, -118, 350, 102, 490, 307, 533, 464, +452, 530, 274, 451, 29, 273, -256, 82, +-515, -79, -636, -185, -573, -213, -382, -190, +-113, -147, 182, -102, 407, -80, 472, -87, +393, -79, 243, -33, 50, 54, -126, 179, +-193, 322, -167, 408, -122, 373, -71, 198, +-34, -76, -35, -366, -60, -576, -58, -612, +16, -418, 105, -55, 158, 349, 201, 659, +195, 784, 101, 672, -23, 376, -126, 14, +-202, -305, -236, -509, -225, -558, -166, -479, +-86, -333, -13, -174, 58, -29, 121, 87, +178, 178, 234, 248, 257, 292, 218, 293, +144, 262, 50, 195, -50, 103, -128, 13, +-148, -56, -132, -115, -136, -165, -161, -207, +-182, -251, -208, -299, -221, -313, -183, -270, +-69, -171, 94, -26, 253, 136, 406, 273, +530, 358, 543, 373, 422, 331, 205, 257, +-64, 156, -335, 18, -564, -143, -676, -311, +-624, -482, -456, -618, -204, -647, 99, -523, +363, -243, 516, 125, 525, 489, 419, 754, +272, 849, 98, 722, -85, 417, -195, 33, +-234, -352, -253, -680, -251, -864, -200, -865, +-105, -698, -1, -386, 90, 36, 176, 465, +214, 789, 170, 921, 68, 816, -50, 492, +-152, 53, -192, -369, -136, -653, -4, -728, +139, -593, 248, -331, 282, -51, 211, 160, +62, 265, -131, 263, -336, 206, -473, 145, +-491, 111, -375, 102, -144, 113, 151, 126, +468, 117, 718, 86, 779, 33, 639, -54, +337, -158, -87, -261, -512, -333, -807, -337, +-893, -254, -741, -89, -407, 146, 10, 386, +390, 544, 607, 572, 622, 474, 476, 261, +246, -1, 33, -229, -107, -374, -165, -424, +-146, -380, -91, -287, -47, -170, -32, -40, +-42, 82, -72, 199, -123, 335, -160, 443, +-147, 472, -98, 408, -19, 252, 83, 12, +177, -238, 237, -431, 245, -522, 211, -481, +147, -323, 25, -125, -135, 76, -260, 253, +-310, 355, -274, 371, -178, 344, -47, 277, +111, 165, 238, 40, 301, -72, 322, -158, +277, -207, 145, -237, -32, -264, -202, -294, +-323, -324, -381, -334, -367, -258, -248, -75, +-80, 197, 58, 503, 172, 742, 256, 795, +272, 626, 234, 272, 191, -175, 177, -583, +167, -822, 111, -858, 15, -717, -99, -456, +-241, -153, -378, 108, -423, 296, -347, 422, +-223, 496, -85, 502, 87, 446, 242, 325, +298, 136, 268, -88, 223, -280, 202, -419, +185, -485, 166, -462, 148, -364, 72, -237, +-98, -99, -290, 40, -438, 171, -505, 280, +-469, 354, -317, 364, -47, 297, 253, 156, +470, -32, 590, -210, 591, -319, 427, -348, +149, -286, -153, -159, -415, -20, -573, 94, +-593, 171, -449, 202, -177, 220, 139, 242, +428, 240, 594, 183, 569, 67, 390, -120, +114, -349, -200, -527, -455, -570, -557, -453, +-488, -181, -295, 181, -23, 520, 251, 732, +420, 757, 438, 591, 350, 301, 200, -24, +19, -307, -148, -495, -256, -553, -299, -492, +-283, -347, -195, -153, -68, 63, 34, 249, +105, 364, 155, 391, 164, 339, 145, 224, +111, 85, 56, -28, -8, -90, -60, -107, +-71, -84, -38, -40, 0, 4, 39, 37, +63, 60, 25, 56, -50, 17, -123, -61, +-195, -153, -245, -229, -228, -247, -117, -166, +70, 36, 256, 297, 390, 521, 428, 624, +333, 545, 144, 269, -74, -118, -264, -503, +-378, -772, -391, -829, -299, -659, -136, -337, +53, 60, 199, 444, 241, 706, 195, 786, +124, 711, 42, 497, -29, 165, -56, -208, +-58, -529, -55, -741, -44, -788, -23, -650, +-6, -362, -18, 8, -32, 354, -16, 565, +4, 602, 31, 467, 80, 201, 103, -99, +72, -316, 13, -409, -52, -372, -99, -233, +-123, -56, -120, 97, -78, 201, -15, 223, +58, 175, 130, 87, 159, -19, 137, -131, +88, -217, 29, -258, -21, -241, -51, -159, +-62, -26, -79, 97, -122, 167, -164, 156, +-186, 70, -187, -51, -141, -142, -37, -154, +111, -65, 268, 97, 393, 263, 456, 358, +421, 349, 274, 223, 66, 10, -173, -224, +-397, -407, -544, -516, -589, -529, -524, -436, +-363, -246, -137, -13, 124, 225, 356, 444, +499, 597, 557, 634, 519, 555, 381, 382, +186, 151, -29, -99, -215, -318, -338, -474, +-400, -535, -385, -510, -302, -403, -183, -222, +-37, 9, 120, 244, 240, 434, 296, 529, +288, 514, 217, 396, 79, 195, -106, -45, +-274, -231, -368, -324, -371, -328, -265, -238, +-49, -68, 215, 96, 432, 202, 552, 243, +557, 213, 416, 100, 156, -46, -132, -168, +-381, -226, -554, -201, -609, -85, -526, 77, +-331, 242, -110, 354, 77, 367, 235, 261, +337, 68, 354, -161, 331, -346, 302, -443, +251, -420, 166, -284, 66, -80, -14, 134, +-99, 311, -216, 406, -316, 401, -355, 311, +-336, 170, -270, 3, -162, -164, -13, -299, +145, -370, 246, -368, 295, -285, 322, -134, +305, 46, 217, 187, 96, 263, -18, 247, +-131, 139, -248, -15, -313, -145, -297, -209, +-248, -191, -183, -105, -59, 12, 114, 105, +267, 155, 346, 146, 364, 82, 317, 2, +172, -73, -44, -160, -246, -228, -382, -249, +-442, -226, -409, -158, -231, -35, 48, 116, +287, 249, 422, 309, 459, 270, 363, 138, +143, -33, -132, -202, -354, -315, -446, -329, +-417, -241, -269, -104, -11, 52, 259, 189, +443, 270, 493, 281, 400, 229, 192, 119, +-67, -7, -307, -135, -453, -265, -484, -358, +-412, -369, -245, -320, -5, -205, 234, -14, +401, 213, 466, 421, 433, 580, 311, 637, +120, 554, -97, 342, -272, 40, -381, -297, +-422, -577, -358, -730, -183, -719, 25, -553, +203, -273, 329, 38, 371, 307, 300, 475, +148, 528, -22, 489, -156, 409, -241, 319, +-259, 253, -188, 205, -73, 153, 25, 57, +100, -96, 127, -298, 91, -496, 34, -638, +-4, -674, -16, -587, -18, -366, 2, -51, +58, 284, 103, 576, 110, 800, 96, 912, +52, 873, -41, 680, -148, 369, -237, -37, +-297, -475, -302, -843, -207, -1046, -28, -1039, +175, -795, 354, -370, 474, 130, 479, 588, +357, 910, 135, 999, -127, 852, -357, 523, +-482, 93, -470, -338, -348, -653, -162, -796, +51, -740, 228, -506, 305, -171, 286, 156, +206, 403, 78, 511, -53, 464, -129, 305, +-117, 117, -63, -54, -4, -163, 68, -204, +116, -205, 90, -204, 29, -202, -20, -198, +-60, -168, -89, -91, -84, 24, -55, 146, +-34, 237, -45, 237, -69, 139, -99, -25, +-121, -192, -98, -298, 0, -291, 141, -177, +270, 11, 334, 205, 314, 337, 216, 346, +65, 242, -112, 66, -256, -137, -322, -320, +-309, -408, -242, -395, -121, -302, 13, -159, +109, 15, 153, 162, 165, 252, 145, 276, +85, 242, -9, 149, -87, 33, -127, -79, +-138, -147, -96, -144, 22, -70, 163, 31, +268, 137, 306, 217, 270, 234, 157, 157, +-11, 12, -187, -164, -314, -313, -381, -407, +-384, -419, -330, -332, -230, -144, -105, 87, +23, 320, 154, 505, 294, 597, 411, 563, +463, 430, 444, 217, 363, -26, 213, -228, +8, -347, -210, -404, -382, -387, -482, -308, +-500, -209, -436, -115, -298, -3, -121, 111, +65, 219, 225, 302, 326, 349, 352, 341, +321, 288, 241, 189, 133, 65, 37, -45, +-21, -115, -36, -161, -18, -175, -8, -164, +-34, -144, -105, -134, -210, -130, -325, -124, +-393, -86, -367, -19, -219, 82, 19, 209, +288, 352, 517, 457, 641, 480, 617, 381, +455, 170, 178, -119, -172, -419, -512, -671, +-748, -794, -816, -747, -685, -527, -385, -185, +11, 217, 416, 589, 738, 853, 899, 938, +855, 830, 599, 542, 200, 125, -238, -333, +-616, -710, -867, -935, -919, -957, -751, -780, +-417, -446, -25, -58, 353, 295, 659, 528, +820, 595, 771, 506, 547, 337, 232, 139, +-100, -18, -390, -96, -551, -104, -551, -88, +-432, -74, -266, -96, -80, -154, 99, -234, +219, -286, 237, -284, 205, -218, 172, -125, +128, -16, 56, 86, -19, 163, -70, 205, +-98, 248, -106, 285, -66, 290, 16, 242, +86, 140, 106, -32, 87, -241, 29, -438, +-59, -558, -152, -550, -196, -385, -168, -120, +-78, 188, 40, 467, 152, 648, 213, 664, +194, 521, 98, 255, -20, -53, -116, -331, +-174, -503, -189, -540, -139, -442, -38, -260, +69, -46, 154, 133, 232, 247, 259, 285, +191, 268, 57, 219, -81, 175, -213, 142, +-311, 125, -329, 95, -233, 50, -65, -7, +104, -57, 234, -101, 304, -122, 280, -118, +174, -90, 23, -66, -120, -47, -228, -36, +-275, -23, -253, -9, -158, 19, -24, 50, +118, 109, 248, 186, 349, 252, 380, 284, +321, 297, 166, 259, -53, 161, -284, 2, +-466, -181, -548, -356, -494, -472, -323, -503, +-90, -413, 146, -214, 346, 42, 463, 273, +486, 441, 412, 503, 270, 437, 89, 262, +-85, 56, -213, -131, -278, -236, -293, -253, +-250, -203, -162, -120, -60, -31, 22, 7, +72, -4, 71, -62, 25, -137, -33, -189, +-63, -175, -59, -108, -23, 17, 44, 179, +141, 327, 231, 383, 289, 333, 287, 170, +206, -79, 50, -350, -135, -544, -312, -606, +-440, -499, -475, -253, -381, 62, -188, 352, +59, 550, 301, 580, 474, 446, 507, 190, +388, -103, 167, -371, -82, -548, -299, -599, +-416, -497, -415, -288, -315, -20, -155, 234, +38, 423, 226, 494, 382, 435, 472, 259, +461, 37, 324, -171, 101, -311, -154, -356, +-400, -294, -596, -166, -660, -14, -548, 110, +-285, 182, 37, 181, 345, 135, 559, 51, +616, -47, 509, -139, 309, -178, 84, -165, +-109, -84, -237, 41, -271, 187, -229, 314, +-162, 391, -106, 355, -63, 217, -43, 16, +-48, -196, -80, -378, -110, -453, -101, -407, +-42, -247, 43, -24, 142, 197, 235, 347, +297, 418, 299, 398, 246, 300, 147, 163, +22, 50, -108, -52, -199, -136, -250, -195, +-276, -215, -289, -200, -281, -136, -244, -43, +-172, 85, -54, 213, 124, 295, 319, 292, +471, 217, 531, 71, 482, -100, 313, -258, +54, -346, -224, -329, -434, -185, -543, 35, +-535, 266, -404, 433, -172, 501, 77, 421, +269, 200, 375, -95, 407, -359, 343, -523, +189, -540, 1, -424, -147, -200, -241, 63, +-255, 288, -183, 404, -52, 421, 64, 360, +120, 249, 106, 82, 47, -86, -38, -232, +-107, -349, -137, -439, -108, -452, -20, -378, +95, -215, 189, -6, 241, 215, 230, 393, +145, 492, -4, 454, -160, 301, -291, 78, +-373, -150, -372, -343, -259, -454, -57, -473, +191, -392, 410, -237, 538, -53, 521, 85, +361, 184, 95, 238, -203, 234, -448, 164, +-554, 75, -501, -22, -335, -95, -125, -136, +87, -145, 246, -119, 322, -44, 307, 26, +236, 71, 139, 77, 56, 50, 6, -21, +-6, -108, -2, -180, 6, -183, -6, -122, +-46, -11, -115, 112, -193, 223, -264, 272, +-293, 229, -259, 98, -143, -61, 23, -210, +194, -289, 324, -270, 395, -151, 375, 25, +265, 221, 113, 358, -6, 409, -89, 348, +-152, 202, -200, 11, -219, -170, -230, -316, +-244, -379, -240, -361, -176, -261, -65, -111, +71, 73, 211, 249, 331, 381, 363, 421, +302, 383, 194, 288, 85, 174, -29, 44, +-131, -56, -207, -109, -245, -126, -251, -157, +-212, -197, -133, -245, -34, -263, 62, -235, +139, -149, 159, -6, 133, 190, 87, 359, +45, 462, 14, 480, 17, 422, 60, 285, +119, 114, 145, -64, 115, -209, 14, -322, +-133, -402, -274, -448, -355, -432, -371, -361, +-321, -226, -206, -50, -29, 161, 163, 370, +347, 545, 500, 628, 590, 594, 560, 434, +410, 197, 165, -104, -131, -420, -435, -681, +-658, -803, -744, -766, -675, -563, -482, -251, +-198, 124, 121, 467, 415, 685, 608, 712, +673, 574, 618, 308, 468, -9, 225, -314, +-70, -509, -345, -566, -517, -497, -563, -362, +-493, -186, -326, -17, -93, 127, 130, 206, +283, 235, 348, 242, 347, 242, 281, 202, +183, 129, 94, 30, 21, -70, -83, -183, +-215, -295, -328, -390, -375, -428, -359, -407, +-272, -312, -105, -159, 126, 51, 337, 282, +465, 485, 480, 603, 399, 631, 245, 543, +66, 361, -104, 95, -243, -218, -350, -516, +-397, -731, -378, -850, -301, -825, -192, -638, +-58, -295, 77, 124, 202, 542, 282, 862, +314, 1034, 300, 1010, 257, 804, 187, 440, +101, 16, 1, -389, -97, -711, -192, -918, +-262, -947, -298, -809, -286, -526, -225, -152, +-108, 267, 29, 651, 145, 928, 201, 1013, +213, 911, 201, 638, 188, 260, 153, -156, +91, -517, 3, -757, -84, -815, -168, -716, +-226, -485, -233, -172, -175, 185, -86, 498, +17, 691, 105, 720, 152, 616, 133, 393, +80, 104, 37, -183, 34, -388, 48, -475, +62, -436, 53, -332, 24, -195, -44, -65, +-131, 52, -189, 141, -166, 222, -83, 306, +21, 404, 102, 443, 150, 382, 138, 207, +69, -52, -23, -357, -84, -610, -115, -736, +-120, -667, -98, -436, -37, -114, 31, 202, +81, 452, 123, 584, 180, 591, 208, 479, +181, 317, 100, 140, -10, -34, -141, -212, +-245, -371, -287, -497, -256, -552, -187, -554, +-105, -483, -29, -335, 35, -123, 84, 99, +145, 314, 219, 483, 300, 609, 343, 647, +314, 569, 199, 359, 14, 69, -211, -276, +-414, -613, -537, -871, -523, -943, -376, -803, +-132, -490, 143, -90, 382, 322, 505, 641, +505, 816, 403, 786, 242, 585, 34, 298, +-179, 5, -335, -271, -387, -462, -357, -551, +-276, -541, -174, -474, -69, -363, -1, -218, +41, -32, 97, 159, 202, 352, 319, 511, +417, 622, 468, 631, 433, 507, 251, 246, +-61, -83, -405, -427, -666, -698, -783, -838, +-701, -782, -425, -522, -24, -111, 353, 321, +593, 696, 655, 926, 563, 965, 346, 788, +74, 446, -183, 23, -342, -375, -386, -695, +-332, -870, -211, -880, -40, -698, 120, -361, +222, 58, 243, 465, 208, 807, 109, 988, +-28, 961, -143, 730, -175, 377, -150, -21, +-95, -384, -26, -673, 31, -812, 18, -794, +-41, -650, -83, -430, -65, -141, -4, 186, +96, 516, 200, 766, 268, 899, 255, 873, +175, 683, 58, 340, -50, -85, -139, -512, +-184, -824, -190, -973, -172, -926, -174, -695, +-191, -317, -187, 116, -120, 524, -14, 801, +112, 914, 249, 840, 372, 595, 409, 222, +340, -180, 193, -520, 25, -710, -146, -756, +-284, -663, -366, -471, -374, -228, -328, -14, +-229, 150, -75, 262, 118, 370, 275, 453, +346, 490, 336, 468, 279, 386, 163, 212, +18, -44, -105, -343, -160, -580, -183, -723, +-199, -745, -202, -642, -180, -426, -166, -163, +-143, 119, -67, 358, 81, 539, 239, 655, +360, 695, 410, 612, 368, 425, 211, 148, +0, -171, -195, -500, -328, -764, -399, -900, +-393, -851, -319, -644, -187, -308, -37, 80, +110, 468, 238, 772, 341, 926, 392, 882, +376, 661, 285, 291, 138, -131, -61, -536, +-268, -812, -420, -873, -465, -714, -430, -420, +-340, -49, -190, 292, 21, 525, 239, 592, +419, 526, 539, 386, 578, 237, 485, 92, +283, -23, 25, -120, -235, -193, -478, -269, +-639, -337, -662, -356, -536, -269, -318, -118, +-50, 77, 222, 268, 458, 415, 595, 472, +612, 417, 515, 250, 334, 62, 87, -105, +-170, -218, -381, -267, -491, -235, -499, -145, +-411, -33, -253, 36, -60, 78, 92, 92, +188, 103, 246, 122, 298, 166, 319, 208, +294, 248, 225, 222, 130, 114, -19, -83, +-214, -316, -391, -522, -453, -615, -396, -550, +-251, -286, -46, 115, 181, 544, 333, 866, +369, 1000, 315, 890, 212, 552, 62, 45, +-83, -478, -157, -896, -151, -1120, -143, -1122, +-147, -898, -136, -506, -89, 0, -22, 500, +49, 908, 99, 1150, 131, 1181, 126, 964, +85, 540, 13, -24, -62, -583, -117, -1030, +-125, -1262, -83, -1226, 2, -921, 66, -432, +88, 132, 83, 618, 68, 945, 18, 1044, +-47, 905, -87, 555, -76, 104, -50, -343, +-15, -660, 44, -814, 116, -780, 147, -574, +125, -255, 62, 61, -20, 312, -123, 445, +-206, 489, -237, 442, -214, 327, -165, 173, +-78, 18, 49, -150, 184, -310, 254, -467, +260, -573, 235, -586, 200, -483, 136, -276, +55, 39, -38, 391, -122, 712, -197, 901, +-240, 924, -250, 773, -228, 467, -190, 27, +-137, -444, -79, -863, 5, -1132, 103, -1205, +186, -1066, 251, -720, 315, -195, 336, 388, +289, 924, 191, 1297, 79, 1451, -63, 1352, +-224, 1003, -355, 440, -410, -198, -408, -803, +-355, -1265, -234, -1499, -40, -1429, 167, -1056, +350, -455, 476, 215, 516, 838, 428, 1269, +235, 1423, -10, 1260, -232, 845, -394, 313, +-456, -184, -406, -598, -259, -855, -85, -938, +65, -871, 164, -702, 218, -451, 227, -138, +206, 254, 173, 661, 152, 1001, 118, 1178, +57, 1127, -32, 813, -122, 279, -205, -378, +-265, -964, -282, -1340, -221, -1416, -120, -1178, +-19, -686, 76, -75, 174, 532, 227, 988, +230, 1241, 205, 1266, 176, 1080, 115, 715, +22, 241, -68, -282, -132, -746, -198, -1098, +-255, -1276, -262, -1239, -182, -962, -51, -499, +94, 75, 228, 638, 322, 1108, 325, 1373, +230, 1362, 74, 1063, -96, 539, -267, -123, +-393, -775, -422, -1302, -335, -1577, -176, -1537, +21, -1194, 215, -632, 374, 71, 462, 773, +484, 1354, 441, 1694, 343, 1736, 166, 1458, +-77, 894, -341, 107, -561, -747, -718, -1530, +-781, -2065, -703, -2225, -455, -1949, -93, -1272, +317, -301, 707, 758, 995, 1693, 1081, 2276, +954, 2393, 642, 2031, 200, 1281, -312, 293, +-776, -706, -1096, -1538, -1211, -2033, -1100, -2131, +-764, -1836, -268, -1228, 285, -425, 780, 404, +1125, 1128, 1247, 1616, 1128, 1811, 787, 1682, +291, 1256, -273, 610, -775, -115, -1123, -818, +-1240, -1366, -1106, -1673, -755, -1661, -271, -1319, +262, -701, 740, 57, 1069, 823, 1162, 1436, +1021, 1781, 704, 1765, 296, 1393, -143, 754, +-537, -1, -836, -756, -989, -1357, -987, -1714, +-845, -1768, -591, -1515, -222, -987, 211, -279, +639, 523, 989, 1269, 1204, 1829, 1218, 2083, +997, 1971, 560, 1480, -7, 682, -629, -299, +-1191, -1249, -1552, -1990, -1595, -2359, -1309, -2279, +-747, -1737, -13, -819, 771, 305, 1437, 1378, +1824, 2197, 1830, 2573, 1463, 2408, 780, 1724, +-81, 679, -938, -515, -1586, -1572, -1897, -2271, +-1814, -2453, -1374, -2105, -664, -1328, 150, -328, +893, 680, 1426, 1477, 1680, 1946, 1591, 2008, +1194, 1692, 596, 1086, -61, 322, -658, -485, +-1094, -1184, -1308, -1676, -1265, -1849, -1016, -1674, +-626, -1188, -161, -486, 306, 312, 678, 1029, +908, 1544, 994, 1747, 954, 1612, 760, 1181, +431, 551, 38, -179, -340, -861, -677, -1390, +-917, -1673, -994, -1688, -887, -1413, -639, -872, +-280, -145, 154, 620, 593, 1309, 917, 1771, +1073, 1906, 1050, 1661, 844, 1072, 444, 237, +-80, -664, -608, -1471, -1018, -1994, -1245, -2124, +-1228, -1819, -950, -1137, -455, -204, 132, 783, +678, 1624, 1076, 2118, 1271, 2182, 1223, 1802, +943, 1051, 476, 77, -76, -901, -618, -1703, +-1054, -2154, -1281, -2170, -1230, -1738, -946, -942, +-499, 62, 44, 1047, 591, 1825, 993, 2211, +1173, 2124, 1129, 1579, 881, 708, 463, -291, +-7, -1190, -431, -1815, -752, -2018, -945, -1795, +-956, -1211, -804, -418, -538, 421, -206, 1138, +170, 1613, 522, 1740, 767, 1533, 853, 1040, +785, 359, 584, -381, 312, -1015, 15, -1419, +-265, -1503, -494, -1282, -628, -801, -660, -170, +-598, 466, -471, 962, -278, 1248, -48, 1270, +191, 1059, 408, 654, 581, 145, 669, -371, +655, -810, 518, -1118, 287, -1209, -6, -1073, +-319, -713, -593, -195, -745, 402, -750, 952, +-610, 1327, -345, 1421, 4, 1226, 342, 752, +591, 97, 688, -607, 637, -1201, 464, -1558, +231, -1577, -5, -1271, -207, -679, -356, 72, +-432, 817, -458, 1383, -442, 1644, -393, 1530, +-282, 1100, -89, 436, 173, -305, 432, -954, +621, -1372, 687, -1502, 604, -1321, 361, -884, +31, -263, -288, 396, -515, 963, -630, 1324, +-624, 1403, -490, 1160, -271, 654, -55, -36, +140, -739, 312, -1280, 440, -1527, 494, -1413, +486, -944, 418, -246, 283, 520, 64, 1146, +-185, 1492, -409, 1494, -558, 1173, -604, 600, +-527, -78, -349, -735, -90, -1234, 196, -1503, +446, -1485, 611, -1172, 675, -618, 594, 54, +370, 752, 56, 1320, -262, 1637, -533, 1615, +-715, 1252, -751, 618, -610, -155, -359, -938, +-59, -1524, 257, -1774, 557, -1639, 761, -1157, +823, -415, 745, 424, 546, 1183, 218, 1668, +-185, 1796, -573, 1549, -859, 978, -1011, 194, +-963, -630, -698, -1333, -275, -1746, 192, -1808, +617, -1511, 919, -911, 1047, -104, 966, 758, +714, 1511, 338, 1975, -98, 2073, -525, 1759, +-863, 1054, -1056, 68, -1048, -982, -828, -1868, +-416, -2372, 100, -2393, 606, -1885, 987, -932, +1177, 259, 1128, 1411, 834, 2281, 344, 2668, +-219, 2499, -739, 1780, -1119, 658, -1307, -626, +-1230, -1780, -890, -2566, -351, -2798, 282, -2427, +896, -1499, 1356, -228, 1552, 1102, 1407, 2193, +964, 2820, 319, 2815, -395, 2189, -1048, 1078, +-1497, -251, -1642, -1523, -1450, -2472, -994, -2897, +-366, -2689, 337, -1941, 994, -799, 1461, 514, +1663, 1734, 1558, 2593, 1148, 2928, 495, 2674, +-269, 1900, -992, 714, -1513, -640, -1734, -1883, +-1600, -2766, -1141, -3123, -459, -2853, 303, -2002, +1000, -706, 1494, 758, 1701, 2092, 1565, 3014, +1118, 3317, 448, 2900, -318, 1866, -1042, 419, +-1553, -1119, -1738, -2416, -1562, -3169, -1053, -3225, +-306, -2592, 499, -1442, 1187, -18, 1609, 1347, +1689, 2378, 1419, 2880, 868, 2784, 149, 2131, +-589, 1083, -1215, -161, -1587, -1341, -1642, -2234, +-1371, -2656, -807, -2531, -58, -1889, 698, -883, +1317, 308, 1668, 1427, 1660, 2233, 1282, 2550, +651, 2348, -85, 1673, -786, 655, -1339, -509, +-1610, -1552, -1539, -2271, -1181, -2517, -632, -2254, +47, -1532, 719, -481, 1252, 713, 1542, 1765, +1548, 2457, 1263, 2637, 725, 2269, 30, 1396, +-661, 192, -1227, -1082, -1562, -2094, -1610, -2640, +-1344, -2622, -802, -2044, -91, -993, 632, 284, +1248, 1479, 1653, 2313, 1748, 2648, 1465, 2397, +864, 1604, 64, 452, -751, -756, -1414, -1730, +-1783, -2240, -1764, -2223, -1357, -1715, -688, -874, +94, 78, 812, 903, 1330, 1443, 1558, 1631, +1492, 1516, 1177, 1154, 664, 628, 34, 33, +-552, -506, -980, -935, -1230, -1218, -1305, -1316, +-1144, -1157, -765, -755, -275, -193, 210, 407, +644, 949, 967, 1301, 1104, 1365, 1019, 1090, +800, 578, 498, -25, 125, -571, -279, -970, +-625, -1146, -850, -1072, -944, -775, -919, -371, +-723, 38, -383, 389, 1, 667, 342, 812, +628, 800, 828, 655, 894, 439, 797, 169, +595, -125, 329, -406, 11, -600, -346, -704, +-656, -708, -868, -609, -957, -396, -898, -102, +-665, 231, -287, 520, 143, 711, 510, 751, +813, 638, 1007, 377, 1021, 32, 858, -309, +589, -530, 245, -611, -168, -569, -607, -440, +-955, -234, -1169, -16, -1234, 154, -1090, 238, +-685, 285, -95, 317, 556, 325, 1149, 306, +1557, 294, 1645, 265, 1374, 190, 789, 13, +23, -244, -783, -533, -1455, -775, -1820, -918, +-1792, -881, -1382, -623, -657, -138, 225, 455, +1082, 1026, 1716, 1445, 1988, 1617, 1830, 1451, +1261, 938, 414, 142, -510, -744, -1343, -1527, +-1928, -2043, -2114, -2187, -1825, -1871, -1165, -1127, +-262, -85, 741, 1026, 1628, 1992, 2165, 2617, +2232, 2743, 1834, 2253, 1048, 1214, -25, -159, +-1123, -1538, -1967, -2641, -2390, -3205, -2298, -3042, +-1655, -2144, -599, -746, 600, 836, 1627, 2251, +2281, 3217, 2423, 3490, 2006, 2972, 1102, 1776, +-59, 205, -1195, -1437, -2044, -2828, -2426, -3667, +-2249, -3712, -1553, -2935, -480, -1500, 691, 297, +1701, 2130, 2337, 3583, 2439, 4303, 1982, 4077, +1082, 2940, -73, 1130, -1217, -982, -2106, -2974, +-2529, -4369, -2380, -4841, -1691, -4255, -627, -2727, +577, -572, 1664, 1777, 2419, 3838, 2636, 5087, +2245, 5209, 1351, 4162, 202, 2191, -995, -298, +-2034, -2783, -2657, -4699, -2690, -5547, -2131, -5155, +-1097, -3648, 192, -1372, 1481, 1216, 2458, 3572, +2912, 5163, 2762, 5599, 1999, 4843, 757, 3089, +-648, 686, -1913, -1916, -2805, -4157, -3141, -5519, +-2768, -5677, -1746, -4656, -363, -2666, 1052, -61, +2277, 2631, 3077, 4754, 3204, 5803, 2588, 5578, +1445, 4206, 14, 1936, -1469, -779, -2695, -3319, +-3308, -5075, -3142, -5693, -2311, -5113, -1007, -3512, +565, -1168, 2044, 1434, 3070, 3701, 3404, 5108, +2995, 5387, 1940, 4538, 447, 2750, -1191, 326, +-2604, -2175, -3469, -4131, -3562, -5102, -2881, -4958, +-1563, -3774, 140, -1796, 1877, 592, 3227, 2803, +3885, 4321, 3731, 4867, 2767, 4399, 1143, 3011, +-751, 962, -2486, -1328, -3708, -3276, -4176, -4437, +-3744, -4617, -2466, -3836, -668, -2225, 1225, -90, +2887, 2068, 3986, 3666, 4235, 4388, 3529, 4171, +2067, 3063, 193, 1242, -1718, -856, -3275, -2669, +-4090, -3734, -3970, -3923, -2982, -3265, -1404, -1884, +445, -88, 2177, 1626, 3408, 2844, 3863, 3345, +3459, 3130, 2334, 2247, 748, 858, -1007, -697, +-2529, -2001, -3458, -2782, -3592, -2916, -2953, -2438, +-1701, -1402, -64, -19, 1600, 1339, 2857, 2329, +3437, 2799, 3254, 2678, 2369, 1970, 957, 751, +-637, -683, -2042, -1948, -2956, -2744, -3199, -2930, +-2741, -2439, -1712, -1360, -348, 86, 1054, 1493, +2239, 2495, 2925, 2902, 2940, 2685, 2305, 1863, +1173, 596, -200, -820, -1520, -1983, -2515, -2647, +-2905, -2748, -2597, -2272, -1701, -1228, -454, 136, +873, 1436, 1991, 2323, 2627, 2670, 2622, 2443, +2010, 1630, 953, 351, -293, -1006, -1448, -2055, +-2217, -2567, -2439, -2500, -2104, -1855, -1293, -716, +-202, 635, 896, 1762, 1750, 2390, 2132, 2437, +2002, 1959, 1442, 1021, 601, -207, -340, -1379, +-1177, -2135, -1700, -2380, -1791, -2144, -1519, -1467, +-982, -403, -254, 804, 564, 1791, 1254, 2305, +1639, 2330, 1678, 1869, 1397, 950, 798, -276, +-52, -1439, -927, -2190, -1539, -2398, -1805, -2118, +-1689, -1371, -1166, -259, -334, 954, 567, 1884, +1298, 2307, 1732, 2221, 1808, 1701, 1447, 760, +759, -416, -53, -1477, -829, -2111, -1438, -2250, +-1730, -1945, -1639, -1226, -1220, -161, -576, 958, +210, 1795, 975, 2159, 1537, 2059, 1737, 1522, +1558, 593, 1070, -535, 365, -1460, -417, -1910, +-1099, -1856, -1516, -1389, -1561, -574, -1320, 409, +-861, 1227, -205, 1568, 515, 1436, 1064, 959, +1314, 257, 1304, -533, 1110, -1147, 696, -1360, +112, -1123, -477, -600, -919, 61, -1180, 731, +-1226, 1248, -1001, 1427, -524, 1220, 74, 705, +650, 49, 1050, -644, 1200, -1241, 1069, -1584, +700, -1536, 167, -1122, -438, -453, -928, 321, +-1126, 1081, -1050, 1633, -765, 1805, -327, 1519, +201, 855, 641, -23, 839, -890, 850, -1551, +785, -1808, 614, -1564, 311, -873, -40, 29, +-320, 870, -551, 1439, -757, 1641, -892, 1386, +-858, 725, -634, -116, -302, -863, 72, -1377, +501, -1574, 906, -1389, 1169, -804, 1152, -18, +858, 732, 416, 1308, -93, 1634, -619, 1586, +-1037, 1136, -1242, 392, -1169, -430, -875, -1182, +-435, -1714, 102, -1869, 665, -1550, 1122, -842, +1345, 89, 1273, 1009, 943, 1710, 424, 1989, +-184, 1752, -819, 1062, -1349, 115, -1623, -881, +-1544, -1682, -1111, -2091, -414, -1965, 418, -1323, +1247, -334, 1828, 761, 2011, 1739, 1772, 2315, +1157, 2300, 266, 1673, -720, 614, -1580, -632, +-2137, -1783, -2288, -2550, -1950, -2680, -1190, -2159, +-196, -1135, 821, 153, 1717, 1448, 2329, 2450, +2466, 2905, 2082, 2691, 1299, 1896, 247, 672, +-895, -747, -1917, -2058, -2527, -2935, -2565, -3155, +-2086, -2645, -1191, -1538, 4, -55, 1225, 1477, +2151, 2702, 2558, 3283, 2428, 3074, 1790, 2149, +732, 747, -494, -855, -1561, -2261, -2249, -3088, +-2423, -3132, -2025, -2441, -1147, -1195, -67, 329, +984, 1791, 1794, 2776, 2163, 3043, 1993, 2578, +1371, 1520, 507, 84, -418, -1390, -1266, -2517, +-1790, -2963, -1858, -2653, -1503, -1691, -851, -307, +-44, 1167, 772, 2321, 1407, 2864, 1670, 2670, +1534, 1852, 1068, 612, 387, -773, -391, -1971, +-1068, -2669, -1450, -2736, -1448, -2165, -1112, -1095, +-540, 280, 155, 1639, 827, 2639, 1253, 3008, +1339, 2659, 1090, 1638, 581, 175, -74, -1407, +-753, -2692, -1273, -3320, -1424, -3109, -1186, -2116, +-627, -556, 136, 1188, 944, 2693, 1538, 3537, +1694, 3482, 1382, 2570, 712, 1044, -192, -774, +-1116, -2440, -1775, -3523, -1946, -3741, -1649, -3088, +-959, -1737, 4, 40, 1010, 1872, 1767, 3261, +2074, 3861, 1898, 3554, 1334, 2429, 435, 712, +-621, -1215, -1550, -2863, -2097, -3779, -2143, -3783, +-1709, -2901, -885, -1338, 196, 554, 1249, 2290, +1994, 3419, 2247, 3687, 1981, 3126, 1260, 1855, +249, 127, -834, -1642, -1734, -2974, -2231, -3582, +-2208, -3394, -1710, -2474, -835, -930, 229, 883, +1284, 2467, 2101, 3442, 2472, 3652, 2307, 3042, +1610, 1699, 496, -115, -757, -1906, -1870, -3206, +-2563, -3747, -2670, -3448, -2174, -2330, -1185, -617, +86, 1264, 1340, 2760, 2273, 3527, 2664, 3491, +2454, 2690, 1677, 1220, 522, -569, -719, -2161, +-1725, -3131, -2277, -3377, -2322, -2908, -1867, -1730, +-979, -51, 104, 1619, 1118, 2821, 1809, 3319, +2050, 3085, 1821, 2111, 1159, 556, 236, -1146, +-663, -2482, -1323, -3170, -1634, -3117, -1587, -2363, +-1175, -1021, -484, 605, 301, 2032, 971, 2873, +1392, 3043, 1482, 2559, 1196, 1495, 575, 38, +-182, -1407, -866, -2428, -1304, -2842, -1434, -2664, +-1223, -1879, -664, -607, 93, 830, 827, 2015, +1377, 2694, 1602, 2774, 1438, 2228, 883, 1107, +79, -293, -740, -1595, -1385, -2485, -1736, -2787, +-1718, -2442, -1334, -1525, -627, -229, 263, 1088, +1124, 2096, 1738, 2591, 2011, 2513, 1887, 1886, +1311, 840, 405, -367, -555, -1394, -1361, -2061, +-1916, -2298, -2149, -2058, -1902, -1362, -1189, -416, +-243, 523, 716, 1278, 1548, 1788, 2093, 1923, +2175, 1621, 1705, 995, 869, 230, -85, -547, +-1001, -1195, -1746, -1576, -2097, -1570, -1907, -1207, +-1264, -617, -404, 38, 509, 628, 1315, 1018, +1829, 1151, 1871, 1005, 1476, 667, 811, 260, +4, -120, -813, -429, -1465, -626, -1792, -707, +-1683, -667, -1221, -554, -537, -383, 254, -150, +1026, 128, 1599, 384, 1793, 601, 1556, 720, +1025, 700, 326, 510, -453, 206, -1168, -135, +-1590, -448, -1607, -689, -1306, -762, -820, -652, +-197, -427, 493, -164, 1058, 119, 1290, 393, +1236, 586, 1006, 607, 638, 515, 144, 381, +-365, 200, -710, -69, -841, -349, -843, -516, +-726, -526, -492, -475, -169, -349, 141, -81, +340, 267, 440, 504, 497, 549, 488, 455, +376, 293, 199, 14, 71, -335, -34, -574, +-164, -582, -288, -431, -335, -196, -316, 102, +-290, 450, -238, 702, -104, 741, 53, 588, +198, 329, 314, -21, 392, -417, 403, -756, +321, -901, 142, -835, -95, -597, -334, -208, +-480, 299, -520, 773, -460, 1088, -296, 1172, +-19, 997, 287, 524, 515, -143, 615, -789, +585, -1226, 413, -1399, 126, -1224, -214, -673, +-464, 112, -570, 858, -553, 1382, -425, 1597, +-225, 1435, -14, 830, 196, -52, 334, -932, +386, -1584, 378, -1876, 339, -1688, 269, -1023, +149, -22, 8, 1036, -99, 1871, -208, 2250, +-347, 2076, -475, 1365, -490, 242, -409, -1052, +-284, -2124, -110, -2674, 145, -2576, 445, -1842, +679, -563, 788, 963, 809, 2287, 668, 3018, +299, 3015, -242, 2266, -782, 893, -1162, -780, +-1328, -2266, -1218, -3187, -749, -3332, -49, -2668, +662, -1317, 1228, 379, 1579, 1997, 1588, 3134, +1196, 3511, 524, 3011, -245, 1789, -980, 119, +-1539, -1639, -1778, -3053, -1617, -3712, -1133, -3455, +-396, -2376, 503, -714, 1350, 1231, 1917, 2957, +2084, 3930, 1767, 3878, 987, 2876, -113, 1145, +-1203, -958, -1993, -2908, -2349, -4095, -2175, -4181, +-1421, -3220, -268, -1503, 934, 621, 1876, 2667, +2433, 4051, 2459, 4336, 1841, 3519, 705, 1898, +-566, -184, -1637, -2344, -2368, -3976, -2623, -4534, +-2217, -3885, -1227, -2343, 43, -266, 1244, 1992, +2179, 3863, 2702, 4679, 2578, 4235, 1735, 2815, +472, 799, -807, -1503, -1867, -3529, -2603, -4587, +-2769, -4381, -2182, -3171, -1041, -1296, 250, 917, +1457, 2945, 2446, 4149, 2912, 4229, 2556, 3320, +1507, 1712, 173, -297, -1122, -2208, -2229, -3463, +-2885, -3755, -2761, -3110, -1858, -1726, -551, 51, +809, 1750, 2009, 2876, 2822, 3173, 2909, 2631, +2163, 1428, 888, -102, -525, -1500, -1833, -2403, +-2774, -2618, -3037, -2138, -2469, -1086, -1273, 233, +204, 1413, 1635, 2146, 2725, 2319, 3163, 1893, +2773, 970, 1667, -180, 189, -1190, -1309, -1817, +-2495, -1969, -3127, -1652, -3006, -926, -2137, -25, +-792, 782, 685, 1298, 2013, 1442, 2945, 1221, +3235, 741, 2715, 156, 1551, -343, 69, -642, +-1436, -692, -2689, -536, -3362, -295, -3192, -107, +-2221, -6, -770, -1, 853, -72, 2340, -184, +3322, -223, 3448, -93, 2685, 180, 1311, 444, +-342, 616, -1936, 670, -3080, 555, -3437, 177, +-2888, -383, -1652, -836, -63, -981, 1529, -892, +2748, -604, 3239, -44, 2847, 655, 1722, 1086, +230, 1058, -1268, 758, -2427, 335, -2941, -294, +-2622, -953, -1576, -1218, -150, -977, 1255, -508, +2291, 42, 2691, 682, 2345, 1214, 1296, 1259, +-154, 789, -1558, 83, -2503, -649, -2740, -1294, +-2187, -1600, -920, -1343, 716, -559, 2149, 465, +2952, 1428, 2939, 2034, 2092, 2043, 547, 1393, +-1274, 249, -2752, -1136, -3429, -2331, -3165, -2847, +-2022, -2469, -248, -1373, 1685, 164, 3140, 1822, +3709, 3100, 3308, 3413, 2057, 2642, 242, 1160, +-1700, -605, -3223, -2307, -3877, -3425, -3543, -3467, +-2333, -2419, -563, -772, 1351, 960, 2938, 2399, +3789, 3165, 3723, 2943, 2836, 1836, 1349, 338, +-457, -983, -2196, -1831, -3388, -2120, -3783, -1803, +-3423, -985, -2402, -92, -800, 473, 1044, 665, +2612, 688, 3592, 615, 3935, 459, 3493, 376, +2157, 513, 211, 659, -1762, 526, -3313, 101, +-4212, -426, -4212, -968, -3122, -1425, -1201, -1518, +971, -1019, 2883, -108, 4180, 861, 4515, 1643, +3684, 2034, 1891, 1802, -319, 955, -2399, -189, +-3872, -1244, -4378, -1978, -3755, -2168, -2237, -1686, +-288, -711, 1639, 371, 3102, 1303, 3765, 1901, +3527, 1972, 2500, 1460, 981, 599, -682, -298, +-2073, -1047, -2903, -1519, -3087, -1557, -2633, -1183, +-1625, -579, -294, 73, 1049, 669, 2132, 1088, +2784, 1218, 2799, 1036, 2078, 634, 781, 79, +-682, -545, -1908, -1057, -2645, -1262, -2693, -1109, +-1966, -641, -692, 52, 725, 817, 1875, 1363, +2485, 1454, 2374, 1075, 1532, 366, 251, -523, +-1016, -1332, -1898, -1735, -2173, -1530, -1783, -820, +-862, 130, 279, 1058, 1273, 1703, 1827, 1798, +1814, 1285, 1248, 355, 276, -663, -822, -1481, +-1674, -1889, -2005, -1786, -1714, -1189, -870, -278, +311, 705, 1470, 1516, 2196, 1979, 2262, 1995, +1719, 1552, 673, 717, -658, -335, -1885, -1390, +-2562, -2187, -2480, -2495, -1753, -2208, -567, -1387, +870, -167, 2114, 1199, 2667, 2334, 2372, 2850, +1495, 2614, 307, 1738, -990, 413, -2051, -1085, +-2459, -2286, -2072, -2763, -1152, -2427, -37, -1507, +1077, -266, 1906, 1014, 2167, 1940, 1766, 2194, +916, 1809, -43, 1039, -921, 139, -1600, -694, +-1888, -1244, -1693, -1401, -1110, -1226, -337, -850, +481, -360, 1215, 115, 1746, 500, 1924, 831, +1656, 1119, 998, 1219, 131, 1048, -779, 662, +-1626, 99, -2224, -674, -2268, -1463, -1710, -1867, +-778, -1674, 328, -1016, 1452, -40, 2308, 1100, +2615, 2032, 2276, 2268, 1414, 1692, 222, 617, +-1066, -580, -2110, -1630, -2643, -2173, -2591, -1915, +-1933, -956, -793, 248, 551, 1264, 1757, 1837, +2560, 1841, 2754, 1261, 2242, 302, 1127, -693, +-313, -1380, -1707, -1628, -2634, -1520, -2817, -1157, +-2197, -506, -940, 343, 673, 1129, 2160, 1691, +2956, 2063, 2828, 2095, 1866, 1458, 274, 141, +-1514, -1394, -2869, -2702, -3293, -3493, -2754, -3409, +-1421, -2154, 438, 27, 2232, 2375, 3299, 4098, +3404, 4722, 2674, 4031, 1245, 2081, -626, -625, +-2329, -3188, -3318, -4781, -3438, -5028, -2795, -3996, +-1498, -1953, 249, 582, 1964, 2867, 3118, 4277, +3502, 4602, 3125, 3880, 2013, 2307, 304, 254, +-1558, -1792, -2994, -3406, -3626, -4253, -3392, -4109, +-2331, -2994, -608, -1198, 1345, 904, 2921, 2845, +3668, 4075, 3431, 4201, 2310, 3218, 556, 1399, +-1369, -787, -2908, -2752, -3595, -3935, -3269, -4032, +-2046, -3019, -279, -1162, 1542, 991, 2928, 2787, +3492, 3784, 3083, 3771, 1811, 2721, 8, 884, +-1734, -1167, -2941, -2810, -3388, -3646, -2957, -3536, +-1677, -2491, 71, -773, 1689, 1088, 2802, 2545, +3299, 3293, 2995, 3227, 1789, 2381, 23, 960, +-1625, -630, -2773, -1989, -3298, -2855, -2992, -3053, +-1791, -2512, -46, -1382, 1649, 91, 2848, 1642, +3360, 2892, 2989, 3400, 1700, 2991, -137, 1812, +-1875, 90, -3006, -1860, -3348, -3390, -2865, -3877, +-1572, -3210, 212, -1676, 1885, 376, 2974, 2419, +3314, 3725, 2866, 3810, 1707, 2789, 56, 1106, +-1658, -779, -2902, -2380, -3347, -3200, -3004, -3005, +-1982, -1955, -415, -521, 1375, 829, 2823, 1825, +3443, 2337, 3170, 2199, 2198, 1407, 616, 314, +-1290, -620, -2852, -1279, -3493, -1712, -3173, -1733, +-2159, -1164, -563, -292, 1363, 466, 2855, 1038, +3352, 1464, 2930, 1511, 1874, 1035, 296, 328, +-1461, -264, -2700, -738, -3002, -1085, -2455, -1116, +-1285, -804, 227, -409, 1592, -106, 2309, 136, +2272, 338, 1583, 441, 465, 456, -673, 456, +-1458, 472, -1696, 484, -1369, 437, -650, 259, +170, -26, 776, -353, 1044, -699, 951, -1019, +559, -1128, 62, -887, -310, -385, -464, 202, +-439, 809, -282, 1310, -55, 1459, 99, 1137, +110, 487, 31, -267, -82, -948, -240, -1414, +-353, -1518, -279, -1216, -21, -600, 293, 163, +606, 869, 863, 1332, 912, 1485, 622, 1320, +63, 832, -602, 79, -1210, -718, -1606, -1320, +-1531, -1633, -879, -1619, 89, -1178, 1033, -352, +1795, 566, 2183, 1282, 1871, 1685, 829, 1696, +-461, 1231, -1549, 395, -2218, -480, -2325, -1114, +-1706, -1391, -499, -1299, 799, -891, 1780, -312, +2264, 263, 2147, 659, 1400, 803, 162, 763, +-1089, 607, -1865, 319, -2024, -28, -1712, -268, +-999, -365, 89, -431, 1179, -420, 1754, -198, +1727, 110, 1315, 250, 602, 263, -375, 275, +-1208, 196, -1529, -49, -1391, -258, -945, -271, +-264, -178, 513, -70, 1123, 109, 1335, 316, +1154, 411, 696, 336, 86, 150, -548, -58, +-1041, -226, -1230, -373, -1015, -495, -524, -479, +21, -234, 539, 99, 971, 358, 1104, 581, +839, 803, 381, 820, -32, 504, -446, -11, +-804, -536, -839, -942, -556, -1091, -271, -916, +-84, -469, 149, 119, 381, 682, 419, 986, +315, 903, 307, 558, 441, 159, 415, -187, +154, -384, -102, -357, -310, -167, -597, 17, +-874, 61, -858, -65, -503, -278, -55, -445, +437, -475, 944, -333, 1218, 13, 1083, 488, +664, 843, 76, 850, -651, 553, -1232, 99, +-1351, -417, -1085, -857, -624, -1017, 20, -808, +765, -317, 1229, 273, 1252, 757, 1011, 968, +559, 872, -90, 537, -691, 47, -999, -474, +-971, -842, -751, -971, -429, -877, -32, -579, +347, -150, 540, 251, 549, 546, 520, 773, +512, 928, 410, 882, 139, 596, -179, 192, +-404, -237, -585, -721, -717, -1202, -651, -1435, +-303, -1209, 128, -613, 457, 128, 704, 899, +833, 1587, 652, 1876, 172, 1502, -318, 613, +-628, -369, -755, -1220, -629, -1877, -285, -2080, +114, -1544, 407, -479, 514, 594, 442, 1406, +246, 1953, 48, 2072, -104, 1545, -274, 552, +-359, -467, -241, -1306, -20, -1904, 74, -2067, +82, -1665, 159, -863, 197, 99, 96, 1084, +-15, 1883, -33, 2195, -14, 1927, -58, 1201, +-92, 178, -60, -922, -19, -1775, -62, -2144, +-174, -1959, -206, -1271, -115, -239, -10, 846, +96, 1677, 309, 2057, 601, 1912, 679, 1257, +435, 266, 56, -770, -322, -1573, -722, -1951, +-1010, -1802, -927, -1145, -518, -147, -46, 854, +453, 1551, 938, 1846, 1117, 1715, 883, 1096, +495, 124, 52, -808, -446, -1383, -835, -1597, +-962, -1495, -854, -1027, -573, -267, -115, 494, +426, 1037, 794, 1320, 937, 1365, 911, 1150, +640, 687, 84, 67, -517, -571, -920, -1118, +-1090, -1472, -955, -1524, -437, -1190, 260, -526, +790, 300, 1024, 1100, 1027, 1672, 658, 1808, +-34, 1455, -629, 704, -901, -281, -902, -1226, +-657, -1791, -181, -1844, 355, -1458, 676, -711, +781, 308, 732, 1264, 439, 1757, -48, 1698, +-440, 1254, -628, 523, -690, -395, -571, -1224, +-273, -1640, 4, -1565, 206, -1140, 396, -505, +541, 264, 497, 974, 314, 1369, 192, 1361, +117, 1107, -38, 708, -218, 95, -328, -635, +-405, -1138, -546, -1291, -661, -1274, -563, -1116, +-209, -614, 267, 167, 801, 864, 1215, 1271, +1239, 1449, 877, 1360, 280, 872, -454, 76, +-1144, -708, -1532, -1233, -1472, -1436, -1027, -1316, +-307, -851, 522, -126, 1205, 584, 1519, 1018, +1449, 1157, 1095, 1092, 491, 781, -268, 184, +-931, -445, -1342, -830, -1457, -992, -1320, -1027, +-889, -799, -143, -242, 703, 394, 1366, 861, +1664, 1166, 1560, 1261, 1070, 925, 218, 208, +-735, -519, -1416, -1069, -1639, -1435, -1497, -1443, +-1047, -899, -263, 0, 674, 833, 1394, 1384, +1639, 1615, 1453, 1413, 988, 755, 219, -121, +-707, -905, -1393, -1401, -1610, -1499, -1453, -1199, +-976, -623, -169, 65, 737, 727, 1384, 1197, +1619, 1334, 1468, 1169, 972, 820, 172, 325, +-690, -280, -1290, -840, -1483, -1176, -1368, -1253, +-1026, -1095, -447, -693, 290, -78, 969, 589, +1393, 1112, 1503, 1335, 1314, 1195, 788, 761, +-2, 188, -832, -400, -1407, -877, -1592, -1081, +-1382, -935, -770, -557, 61, -126, 776, 243, +1209, 511, 1285, 632, 971, 594, 403, 409, +-135, 142, -513, -89, -722, -228, -681, -358, +-401, -482, -112, -450, -29, -233, -27, -27, +97, 111, 192, 316, 189, 526, 245, 482, +376, 215, 372, -19, 136, -175, -109, -386, +-198, -552, -280, -475, -419, -216, -437, 18, +-208, 214, 71, 409, 156, 511, 115, 421, +196, 201, 326, -60, 256, -335, 108, -579, +103, -677, 112, -564, -40, -270, -257, 114, +-300, 488, -240, 756, -296, 846, -333, 694, +-95, 329, 235, -125, 350, -540, 310, -839, +321, -932, 359, -794, 223, -516, -123, -189, +-390, 218, -413, 668, -340, 950, -329, 953, +-220, 804, 147, 559, 451, 114, 405, -487, +274, -951, 231, -1091, 75, -972, -229, -667, +-356, -161, -232, 423, -100, 832, -82, 931, +-51, 789, 84, 504, 175, 126, 95, -264, +-11, -499, 12, -515, 153, -423, 170, -342, +-1, -220, -122, -10, -116, 184, -145, 291, +-214, 402, -151, 501, 38, 421, 150, 136, +186, -157, 213, -370, 170, -538, 28, -572, +-76, -299, -56, 179, 7, 535, 19, 612, +-48, 488, -170, 199, -272, -240, -330, -655, +-296, -751, -120, -446, 201, 62, 547, 557, +738, 932, 662, 1015, 366, 629, -57, -109, +-517, -797, -836, -1167, -817, -1218, -517, -914, +-119, -179, 268, 730, 578, 1313, 640, 1339, +419, 976, 113, 401, -100, -333, -186, -1008, +-171, -1219, -60, -875, 84, -315, 50, 172, +-163, 570, -331, 778, -333, 573, -262, 40, +-136, -384, 203, -469, 655, -348, 843, -111, +647, 268, 271, 617, -138, 655, -658, 334, +-1142, -149, -1223, -612, -829, -901, -235, -841, +384, -425, 1052, 96, 1539, 511, 1481, 762, +987, 778, 343, 485, -404, 13, -1260, -350, +-1881, -447, -1825, -356, -1156, -177, -306, 39, +557, 188, 1395, 142, 1905, -80, 1757, -330, +1066, -469, 185, -460, -665, -290, -1372, 51, +-1659, 483, -1360, 810, -700, 859, 7, 627, +641, 284, 1093, -81, 1199, -503, 914, -889, +437, -994, -44, -762, -460, -394, -732, -55, +-758, 294, -629, 634, -437, 791, -141, 661, +181, 371, 399, 91, 532, -124, 591, -268, +593, -277, 467, -133, 170, 31, -224, 34, +-599, -129, -832, -337, -867, -511, -698, -624, +-265, -538, 378, -104, 961, 587, 1178, 1206, +1015, 1488, 582, 1343, -88, 759, -883, -214, +-1402, -1307, -1291, -2097, -727, -2248, -70, -1674, +638, -464, 1270, 1038, 1449, 2293, 980, 2848, +213, 2539, -387, 1419, -788, -247, -1077, -1923, +-1030, -2975, -558, -3063, -25, -2190, 229, -597, +321, 1201, 449, 2548, 543, 3036, 471, 2604, +408, 1396, 480, -249, 443, -1751, 86, -2580, +-400, -2533, -779, -1737, -1048, -484, -1188, 826, +-960, 1819, -312, 2243, 497, 1980, 1188, 1097, +1602, -56, 1576, -1084, 1076, -1780, 252, -2007, +-667, -1604, -1407, -651, -1728, 459, -1577, 1359, +-989, 1900, -133, 1906, 734, 1244, 1322, 116, +1488, -992, 1287, -1714, 805, -1909, 142, -1524, +-492, -602, -873, 536, -948, 1433, -885, 1799, +-740, 1578, -486, 839, -174, -183, 117, -1098, +415, -1565, 765, -1520, 1041, -1050, 1064, -273, +851, 599, 469, 1246, -95, 1462, -819, 1243, +-1403, 714, -1559, 18, -1297, -690, -726, -1268, +52, -1520, 832, -1303, 1359, -684, 1517, 70, +1343, 765, 853, 1322, 188, 1548, -429, 1219, +-915, 488, -1260, -273, -1333, -866, -1085, -1269, +-642, -1323, -85, -887, 575, -161, 1185, 474, +1454, 872, 1271, 1030, 815, 874, 161, 391, +-643, -212, -1292, -704, -1483, -973, -1223, -946, +-612, -589, 248, -56, 1058, 472, 1417, 930, +1264, 1224, 806, 1136, 151, 651, -637, 15, +-1200, -607, -1266, -1180, -995, -1501, -564, -1351, +43, -826, 689, -190, 1058, 484, 1054, 1123, +901, 1452, 578, 1336, -24, 990, -603, 574, +-835, 23, -864, -603, -839, -1012, -595, -1130, +-87, -1120, 392, -997, 663, -620, 792, -43, +780, 509, 483, 921, 21, 1224, -302, 1352, +-440, 1161, -501, 653, -477, -7, -331, -669, +-124, -1236, 10, -1593, 76, -1587, 129, -1152, +172, -379, 211, 510, 280, 1307, 360, 1861, +418, 2019, 398, 1636, 235, 768, -76, -314, +-471, -1316, -841, -2058, -1017, -2325, -932, -1962, +-584, -1067, 0, 68, 682, 1182, 1224, 2049, +1420, 2417, 1224, 2143, 732, 1385, 10, 383, +-828, -701, -1467, -1659, -1571, -2219, -1177, -2241, +-526, -1773, 227, -964, 942, 44, 1350, 1067, +1258, 1892, 811, 2288, 250, 2136, -355, 1517, +-843, 594, -1022, -503, -862, -1556, -489, -2250, +-45, -2352, 339, -1900, 557, -1037, 589, 96, +494, 1249, 298, 2059, 59, 2287, -114, 1911, +-159, 1087, -197, 60, -264, -895, -247, -1581, +-158, -1841, -135, -1585, -168, -954, -121, -282, +32, 259, 154, 698, 224, 995, 311, 1024, +394, 864, 358, 720, 227, 593, 99, 335, +-70, -74, -359, -545, -616, -985, -668, -1332, +-585, -1458, -480, -1240, -229, -667, 271, 153, +815, 1022, 1102, 1679, 1108, 1947, 906, 1773, +431, 1185, -296, 257, -1000, -798, -1410, -1670, +-1453, -2123, -1165, -2093, -536, -1602, 288, -705, +1006, 434, 1419, 1471, 1499, 2106, 1243, 2218, +678, 1818, -73, 972, -799, -120, -1286, -1148, +-1446, -1838, -1340, -2064, -965, -1782, -304, -1105, +516, -246, 1210, 583, 1550, 1228, 1561, 1575, +1272, 1603, 597, 1379, -331, 974, -1149, 405, +-1590, -247, -1653, -902, -1386, -1505, -763, -1933, +91, -1992, 837, -1577, 1243, -755, 1354, 333, +1265, 1530, 909, 2498, 326, 2879, -214, 2551, +-507, 1614, -712, 249, -941, -1255, -972, -2514, +-755, -3167, -551, -3046, -375, -2201, -8, -876, +503, 599, 846, 1897, 1010, 2760, 1144, 3009, +1078, 2581, 607, 1607, -40, 410, -613, -764, +-1119, -1785, -1479, -2500, -1441, -2689, -970, -2273, +-300, -1445, 410, -418, 1113, 750, 1565, 1878, +1553, 2615, 1151, 2724, 507, 2253, -313, 1333, +-1086, 60, -1505, -1332, -1487, -2409, -1172, -2869, +-628, -2647, 126, -1822, 897, -538, 1331, 885, +1356, 2057, 1126, 2703, 694, 2689, 92, 2009, +-500, 873, -863, -377, -954, -1457, -942, -2236, +-849, -2534, -577, -2206, -167, -1389, 192, -383, +468, 657, 792, 1612, 1100, 2249, 1159, 2348, +928, 1934, 504, 1135, -104, 86, -861, -997, +-1458, -1838, -1625, -2237, -1394, -2106, -838, -1495, +38, -583, 1005, 369, 1646, 1180, 1761, 1672, +1434, 1655, 752, 1197, -156, 606, -1018, 65, +-1556, -416, -1652, -764, -1309, -795, -634, -557, +192, -322, 944, -223, 1436, -164, 1533, -105, +1215, -102, 625, -134, -92, -59, -842, 151, +-1396, 404, -1546, 592, -1279, 656, -697, 557, +44, 290, 744, -84, 1255, -473, 1502, -777, +1381, -822, 800, -578, -18, -231, -697, 85, +-1099, 418, -1325, 715, -1270, 726, -765, 401, +-24, 81, 590, -76, 978, -234, 1143, -406, +999, -381, 503, -171, -100, -40, -524, -63, +-724, -91, -760, -100, -604, -132, -257, -140, +98, -3, 245, 285, 236, 570, 234, 724, +269, 750, 273, 647, 315, 354, 460, -178, +515, -771, 267, -1174, -190, -1344, -677, -1327, +-1131, -1024, -1423, -381, -1265, 418, -583, 1169, +356, 1797, 1258, 2129, 1970, 1977, 2235, 1358, +1789, 430, 754, -697, -484, -1853, -1692, -2691, +-2613, -2916, -2827, -2501, -2144, -1481, -845, 29, +652, 1663, 2030, 2950, 3002, 3608, 3174, 3485, +2362, 2488, 859, 747, -850, -1231, -2344, -2913, +-3255, -3940, -3288, -4077, -2330, -3223, -700, -1554, +1010, 514, 2380, 2473, 3175, 3857, 3129, 4326, +2164, 3797, 642, 2371, -895, 372, -2102, -1687, +-2796, -3323, -2805, -4216, -2039, -4171, -781, -3118, +536, -1260, 1660, 823, 2405, 2571, 2533, 3707, +1944, 4026, 848, 3334, -340, 1777, -1379, -113, +-2110, -1784, -2222, -2909, -1566, -3263, -492, -2776, +529, -1644, 1304, -283, 1727, 908, 1572, 1700, +838, 1948, -99, 1618, -856, 974, -1311, 329, +-1325, -151, -792, -421, 30, -449, 719, -293, +1133, -160, 1272, -196, 1043, -338, 405, -523, +-409, -725, -1104, -849, -1529, -716, -1612, -303, +-1249, 241, -476, 776, 489, 1235, 1376, 1528, +2006, 1559, 2229, 1240, 1855, 592, 842, -268, +-482, -1139, -1674, -1861, -2489, -2342, -2810, -2403, +-2383, -1865, -1148, -822, 455, 504, 1863, 1857, +2802, 2948, 3101, 3454, 2542, 3151, 1199, 2057, +-404, 404, -1787, -1483, -2718, -3156, -3001, -4149, +-2447, -4121, -1193, -3068, 287, -1260, 1528, 892, +2267, 2891, 2434, 4224, 2085, 4502, 1259, 3651, +113, 2003, -947, -48, -1525, -2101, -1680, -3622, +-1663, -4157, -1399, -3704, -740, -2569, 31, -973, +593, 879, 1024, 2474, 1449, 3333, 1608, 3394, +1318, 2884, 813, 1909, 254, 507, -502, -1010, +-1342, -2158, -1826, -2725, -1749, -2801, -1303, -2466, +-650, -1630, 209, -411, 1147, 795, 1777, 1713, +1867, 2346, 1523, 2664, 896, 2460, 12, 1653, +-952, 552, -1629, -608, -1792, -1776, -1542, -2701, +-998, -2994, -155, -2541, 787, -1496, 1415, -85, +1602, 1416, 1446, 2609, 957, 3150, 176, 2870, +-621, 1850, -1131, 395, -1309, -1100, -1226, -2269, +-831, -2826, -204, -2645, 364, -1791, 704, -588, +902, 630, 970, 1641, 802, 2218, 439, 2193, +56, 1657, -272, 832, -555, -117, -770, -1041, +-846, -1674, -784, -1858, -571, -1625, -191, -1023, +260, -155, 634, 734, 908, 1399, 1057, 1698, +984, 1598, 643, 1071, 151, 220, -395, -688, +-912, -1378, -1255, -1718, -1303, -1671, -1075, -1202, +-617, -358, 44, 565, 812, 1320, 1403, 1799, +1610, 1876, 1450, 1474, 996, 725, 266, -143, +-609, -966, -1378, -1666, -1805, -2049, -1798, -1943, +-1383, -1423, -610, -702, 370, 174, 1235, 1174, +1759, 2013, 1921, 2399, 1735, 2292, 1137, 1708, +163, 706, -902, -573, -1637, -1818, -1929, -2636, +-1923, -2808, -1558, -2347, -719, -1350, 330, -1, +1171, 1363, 1652, 2292, 1877, 2605, 1761, 2392, +1153, 1724, 302, 686, -402, -431, -965, -1314, +-1461, -1879, -1659, -2178, -1432, -2099, -1021, -1577, +-556, -769, 60, 145, 781, 1124, 1320, 2006, +1570, 2449, 1635, 2302, 1418, 1711, 785, 753, +-16, -442, -736, -1534, -1385, -2193, -1867, -2344, +-1920, -2048, -1547, -1366, -955, -421, -187, 512, +759, 1260, 1595, 1785, 2040, 2033, 2168, 1896, +2032, 1404, 1370, 693, 201, -165, -985, -1049, +-1900, -1705, -2555, -2013, -2756, -1911, -2234, -1366, +-1107, -523, 194, 335, 1390, 1009, 2352, 1444, +2778, 1592, 2446, 1369, 1600, 918, 573, 455, +-472, 31, -1389, -393, -2010, -747, -2219, -960, +-1934, -1074, -1263, -1093, -475, -895, 264, -517, +990, -106, 1636, 284, 1931, 695, 1706, 1043, +1184, 1193, 583, 1173, -126, 1046, -854, 775, +-1347, 343, -1525, -267, -1468, -985, -1242, -1639, +-816, -2044, -241, -2066, 349, -1629, 904, -721, +1422, 528, 1771, 1746, 1801, 2599, 1469, 2929, +772, 2626, -238, 1604, -1280, 110, -2029, -1322, +-2346, -2365, -2224, -2977, -1588, -2993, -441, -2277, +856, -1026, 1809, 325, 2291, 1487, 2355, 2368, +1933, 2785, 1006, 2559, -133, 1831, -1113, 831, +-1778, -311, -2103, -1450, -1976, -2283, -1364, -2590, +-483, -2383, 369, -1750, 1073, -740, 1604, 493, +1824, 1676, 1573, 2475, 932, 2694, 157, 2277, +-555, 1321, -1152, 46, -1528, -1271, -1541, -2275, +-1169, -2643, -541, -2320, 212, -1419, 932, -184, +1392, 1050, 1432, 1901, 1101, 2133, 499, 1811, +-231, 1113, -848, 174, -1133, -714, -1055, -1236, +-701, -1332, -153, -1141, 406, -740, 676, -229, +608, 185, 380, 400, 97, 525, -207, 612, +-351, 587, -180, 417, 141, 269, 340, 205, +372, 58, 268, -223, -17, -469, -459, -570, +-805, -588, -829, -614, -533, -506, -63, -133, +463, 331, 932, 648, 1202, 855, 1100, 1012, +597, 912, -98, 411, -725, -207, -1188, -661, +-1385, -966, -1170, -1155, -593, -1037, 60, -553, +636, -5, 1109, 371, 1328, 653, 1120, 842, +621, 834, 119, 655, -306, 493, -656, 412, +-806, 285, -777, 27, -703, -315, -563, -721, +-310, -1160, -76, -1529, 73, -1611, 283, -1252, +616, -455, 874, 640, 967, 1790, 961, 2674, +780, 2980, 281, 2531, -352, 1379, -855, -278, +-1240, -2019, -1522, -3335, -1479, -3883, -1014, -3512, +-295, -2246, 449, -383, 1128, 1589, 1657, 3118, +1851, 3885, 1577, 3783, 921, 2830, 97, 1259, +-685, -461, -1296, -1913, -1627, -2877, -1551, -3232, +-1094, -2899, -525, -2048, -2, -986, 498, 108, +842, 1166, 851, 2006, 690, 2372, 610, 2261, +592, 1921, 479, 1383, 312, 558, 183, -394, +-11, -1112, -385, -1522, -765, -1814, -1016, -1978, +-1168, -1802, -1157, -1341, -866, -783, -337, -120, +302, 774, 937, 1742, 1490, 2448, 1838, 2722, +1818, 2533, 1370, 1795, 610, 512, -347, -1046, +-1342, -2415, -2114, -3255, -2454, -3382, -2246, -2750, +-1506, -1509, -438, 61, 750, 1573, 1792, 2613, +2391, 3018, 2438, 2803, 2016, 2048, 1254, 941, +295, -195, -701, -1102, -1508, -1718, -1973, -2056, +-2137, -2053, -2030, -1736, -1540, -1247, -739, -681, +157, 7, 1060, 784, 1920, 1492, 2498, 2024, +2549, 2288, 2035, 2129, 1137, 1524, -42, 559, +-1380, -582, -2453, -1676, -2879, -2439, -2698, -2642, +-2028, -2279, -881, -1477, 564, -366, 1840, 770, +2525, 1613, 2581, 2011, 2197, 2015, 1424, 1688, +324, 1113, -768, 449, -1462, -157, -1703, -654, +-1672, -1022, -1452, -1280, -964, -1426, -346, -1410, +65, -1123, 272, -588, 585, 30, 962, 656, +1130, 1274, 1100, 1633, 1091, 1525, 1029, 1063, +634, 518, -18, -34, -596, -600, -1063, -979, +-1497, -980, -1726, -781, -1559, -618, -1113, -468, +-504, -233, 271, -19, 1072, 117, 1633, 272, +1881, 473, 1886, 628, 1583, 692, 852, 675, +-66, 570, -843, 301, -1461, -30, -1946, -290, +-2076, -533, -1717, -793, -1066, -913, -391, -816, +317, -615, 1107, -390, 1769, -15, 2038, 494, +1956, 905, 1669, 1093, 1122, 1132, 216, 1016, +-834, 645, -1691, 52, -2240, -548, -2521, -1027, +-2376, -1304, -1601, -1321, -388, -1065, 851, -585, +1931, 29, 2748, 628, 3016, 1045, 2494, 1186, +1366, 1094, 38, 766, -1258, 251, -2325, -249, +-2815, -579, -2550, -736, -1725, -702, -671, -468, +445, -133, 1418, 111, 1941, 198, 1889, 148, +1463, 8, 935, -158, 376, -257, -257, -190, +-818, 42, -1101, 289, -1100, 471, -1026, 549, +-919, 503, -595, 299, -40, -46, 473, -350, +773, -438, 937, -420, 1029, -419, 896, -363, +489, -184, 26, -36, -299, -18, -547, -18, +-792, 74, -886, 226, -703, 382, -433, 516, +-239, 627, 2, 643, 377, 484, 679, 128, +750, -342, 702, -820, 604, -1215, 343, -1366, +-5, -1134, -246, -600, -391, 115, -543, 898, +-609, 1551, -509, 1832, -385, 1637, -308, 1082, +-134, 321, 129, -583, 342, -1401, 512, -1833, +697, -1815, 754, -1487, 567, -880, 272, -24, +-26, 842, -379, 1473, -724, 1785, -903, 1715, +-861, 1288, -661, 598, -286, -220, 223, -973, +636, -1467, 867, -1593, 1008, -1314, 943, -718, +540, -1, -31, 610, -505, 995, -843, 1102, +-1030, 881, -933, 374, -579, -177, -180, -492, +224, -536, 652, -450, 870, -225, 715, 163, +488, 506, 394, 553, 189, 351, -216, 87, +-516, -209, -564, -552, -551, -783, -577, -766, +-427, -505, -44, -136, 293, 251, 445, 654, +514, 966, 525, 990, 410, 734, 120, 335, +-209, -107, -364, -533, -332, -832, -272, -928, +-199, -785, -46, -446, 99, -65, 104, 215, +36, 389, 43, 464, 119, 447, 87, 328, +-8, 179, 24, 116, 119, 130, 122, 123, +39, 104, -42, 57, -55, -95, -103, -340, +-253, -533, -343, -637, -265, -649, -147, -457, +-33, -58, 195, 348, 492, 659, 617, 860, +509, 842, 319, 497, 107, 14, -243, -342, +-614, -552, -718, -662, -579, -571, -392, -244, +-160, 147, 111, 364, 364, 392, 527, 314, +556, 127, 479, -123, 328, -311, 111, -394, +-106, -360, -305, -196, -471, 61, -539, 307, +-456, 476, -233, 523, 76, 457, 342, 326, +449, 120, 414, -188, 268, -497, 9, -701, +-250, -748, -403, -639, -394, -393, -239, -17, +-20, 432, 213, 804, 408, 979, 476, 920, +426, 666, 266, 261, 41, -192, -159, -572, +-326, -810, -501, -894, -609, -843, -580, -694, +-471, -438, -308, -98, -14, 253, 375, 575, +734, 904, 964, 1194, 1049, 1302, 966, 1143, +647, 737, 135, 128, -448, -597, -1045, -1326, +-1525, -1876, -1717, -2080, -1513, -1878, -937, -1257, +-138, -274, 732, 820, 1569, 1757, 2152, 2411, +2225, 2686, 1746, 2411, 918, 1609, -87, 515, +-1123, -675, -1934, -1827, -2291, -2726, -2182, -3136, +-1674, -2943, -824, -2216, 194, -1041, 1068, 454, +1692, 1962, 2103, 3104, 2163, 3640, 1723, 3456, +943, 2535, 82, 1051, -771, -626, -1570, -2158, +-2067, -3241, -2090, -3596, -1718, -3171, -1084, -2168, +-248, -830, 645, 598, 1359, 1834, 1783, 2610, +1931, 2821, 1719, 2507, 1142, 1800, 371, 828, +-413, -256, -1125, -1208, -1658, -1827, -1825, -2085, +-1548, -1972, -979, -1500, -249, -760, 533, 73, +1180, 780, 1479, 1214, 1365, 1371, 913, 1240, +276, 818, -329, 269, -713, -162, -844, -420, +-746, -529, -421, -452, 58, -224, 433, 2, +535, 103, 463, 64, 293, -47, -40, -201, +-453, -388, -706, -525, -696, -490, -567, -276, +-373, 18, 8, 325, 516, 626, 890, 844, +1039, 895, 1044, 731, 911, 413, 549, 68, +-22, -270, -651, -632, -1183, -929, -1514, -1050, +-1563, -998, -1332, -836, -835, -526, -94, -36, +764, 564, 1467, 1102, 1885, 1433, 2030, 1509, +1805, 1287, 1115, 712, 136, -65, -823, -792, +-1599, -1330, -2174, -1587, -2376, -1468, -2030, -1015, +-1246, -385, -271, 246, 731, 722, 1633, 947, +2250, 963, 2405, 820, 2076, 569, 1383, 329, +470, 187, -539, 99, -1436, 15, -2029, -103, +-2271, -285, -2135, -567, -1578, -889, -713, -1093, +258, -1059, 1142, -801, 1815, -340, 2144, 326, +2022, 1047, 1523, 1533, 840, 1696, 48, 1555, +-753, 1065, -1369, 290, -1673, -513, -1675, -1143, +-1442, -1539, -1057, -1656, -554, -1453, 45, -1000, +652, -440, 1149, 89, 1470, 550, 1615, 942, +1578, 1213, 1231, 1344, 533, 1360, -253, 1193, +-922, 796, -1492, 227, -1882, -431, -1904, -1098, +-1463, -1627, -720, -1865, 80, -1724, 838, -1237, +1480, -548, 1831, 168, 1800, 837, 1411, 1365, +767, 1623, 12, 1620, -714, 1453, -1300, 1130, +-1602, 632, -1595, 1, -1346, -669, -831, -1293, +-90, -1792, 656, -2056, 1228, -1936, 1542, -1403, +1578, -607, 1307, 304, 700, 1238, -88, 1972, +-840, 2283, -1429, 2151, -1705, 1656, -1532, 875, +-975, -73, -259, -981, 437, -1645, 1051, -1991, +1498, -2021, 1566, -1718, 1214, -1087, 680, -269, +139, 536, -433, 1213, -956, 1653, -1305, 1746, +-1440, 1508, -1356, 1012, -1001, 352, -392, -304, +315, -770, 936, -1001, 1441, -1047, 1761, -933, +1693, -689, 1186, -396, 430, -159, -375, -16, +-1114, 126, -1640, 316, -1777, 464, -1512, 549, +-1017, 656, -413, 755, 286, 712, 944, 501, +1319, 212, 1367, -123, 1219, -515, 936, -907, +534, -1168, 48, -1215, -413, -1048, -737, -663, +-883, -76, -888, 550, -806, 1087, -702, 1507, +-560, 1694, -344, 1493, -77, 955, 183, 262, +447, -500, 747, -1270, 1066, -1830, 1261, -1983, +1218, -1719, 973, -1155, 541, -369, -113, 550, +-867, 1378, -1478, 1868, -1828, 1968, -1907, 1748, +-1671, 1236, -1049, 478, -124, -360, 817, -1092, +1560, -1607, 2077, -1836, 2287, -1749, 2029, -1363, +1346, -726, 477, 38, -410, 784, -1285, 1392, +-1978, 1727, -2243, 1706, -2070, 1390, -1657, 875, +-1019, 220, -122, -476, 804, -1046, 1468, -1389, +1843, -1511, 1994, -1431, 1863, -1129, 1363, -599, +645, 39, -40, 633, -635, 1164, -1171, 1572, +-1570, 1680, -1727, 1411, -1653, 858, -1418, 150, +-1044, -618, -476, -1293, 277, -1672, 1069, -1652, +1761, -1291, 2257, -708, 2406, -4, 2076, 683, +1289, 1158, 200, 1325, -989, 1236, -2074, 950, +-2774, 500, -2858, -26, -2361, -495, -1474, -832, +-300, -978, 978, -889, 2038, -622, 2626, -284, +2710, 58, 2324, 330, 1482, 473, 338, 460, +-773, 326, -1654, 189, -2262, 125, -2452, 97, +-2086, 83, -1287, 94, -333, 71, 571, -47, +1321, -217, 1810, -345, 1888, -373, 1547, -326, +971, -249, 338, -106, -276, 113, -814, 278, +-1186, 304, -1293, 250, -1170, 198, -915, 162, +-507, 111, 17, 22, 511, -74, 878, -126, +1075, -138, 1067, -166, 860, -183, 460, -129, +-61, -47, -560, 17, -898, 91, -1027, 142, +-962, 98, -716, -14, -273, -82, 254, -71, +699, -22, 1022, 43, 1157, 157, 992, 299, +572, 343, 38, 240, -501, 47, -943, -224, +-1229, -510, -1241, -666, -895, -636, -353, -433, +138, -65, 547, 374, 927, 734, 1164, 941, +1065, 936, 732, 643, 447, 124, 171, -427, +-267, -812, -680, -952, -832, -901, -893, -672, +-1002, -243, -955, 240, -576, 562, -80, 684, +303, 678, 687, 568, 1153, 379, 1382, 181, +1208, -7, 839, -221, 389, -429, -208, -554, +-852, -565, -1285, -486, -1415, -331, -1314, -86, +-980, 205, -380, 424, 296, 523, 822, 524, +1157, 417, 1305, 231, 1205, 81, 890, -21, +410, -159, -148, -317, -611, -440, -922, -498, +-1115, -468, -1133, -383, -900, -244, -483, 16, +-15, 332, 384, 556, 725, 673, 975, 702, +1018, 593, 805, 347, 476, 44, 143, -258, +-191, -554, -532, -832, -763, -973, -773, -847, +-639, -538, -465, -170, -210, 278, 134, 744, +417, 1031, 542, 1053, 504, 847, 387, 460, +235, -3, 18, -374, -209, -575, -288, -655, +-223, -656, -138, -578, -76, -453, 33, -342, +189, -253, 243, -90, 167, 211, 72, 582, +-23, 908, -207, 1092, -363, 1026, -391, 645, +-358, 52, -266, -580, -31, -1118, 256, -1400, +470, -1306, 592, -849, 636, -153, 524, 563, +199, 1087, -160, 1322, -371, 1210, -511, 752, +-670, 111, -670, -520, -442, -1003, -142, -1182, +97, -981, 319, -509, 508, 54, 593, 538, +527, 815, 344, 856, 62, 652, -249, 275, +-424, -77, -424, -264, -290, -305, -57, -247, +197, -159, 345, -122, 379, -180, 251, -293, +-23, -373, -331, -363, -535, -252, -579, -34, +-456, 265, -234, 522, 7, 640, 218, 647, +394, 597, 572, 484, 665, 290, 589, 54, +442, -202, 329, -512, 142, -841, -148, -1061, +-486, -1098, -778, -929, -930, -547, -921, 11, +-804, 638, -553, 1156, -155, 1391, 298, 1346, +716, 1127, 1064, 760, 1326, 229, 1339, -348, +1019, -804, 509, -1095, -28, -1296, -643, -1388, +-1276, -1239, -1683, -831, -1672, -287, -1306, 344, +-720, 989, 35, 1458, 846, 1623, 1431, 1498, +1654, 1126, 1590, 544, 1216, -152, 544, -779, +-231, -1198, -844, -1386, -1175, -1325, -1261, -1028, +-1169, -604, -827, -128, -287, 351, 213, 699, +496, 790, 582, 661, 565, 445, 502, 268, +409, 183, 313, 207, 288, 354, 288, 533, +222, 566, 56, 372, -165, -57, -417, -660, +-660, -1245, -826, -1594, -804, -1591, -601, -1225, +-302, -599, 32, 129, 361, 831, 637, 1395, +802, 1709, 840, 1731, 784, 1505, 635, 1102, +338, 556, -1, -113, -289, -827, -587, -1435, +-890, -1843, -998, -1982, -859, -1773, -601, -1220, +-304, -467, 32, 322, 385, 1052, 640, 1617, +728, 1874, 715, 1801, 676, 1469, 583, 938, +431, 287, 233, -362, 20, -940, -236, -1385, +-583, -1601, -959, -1516, -1156, -1166, -1097, -663, +-858, -113, -437, 429, 180, 840, 814, 989, +1231, 929, 1366, 779, 1239, 535, 878, 267, +382, 103, -99, 51, -523, 46, -823, 11, +-909, -107, -859, -264, -793, -434, -679, -650, +-502, -850, -305, -891, -46, -719, 339, -388, +787, 36, 1131, 505, 1278, 948, 1246, 1215, +983, 1190, 388, 942, -346, 544, -910, -1, +-1262, -550, -1445, -875, -1322, -948, -893, -865, +-345, -637, 178, -261, 615, 133, 879, 397, +917, 509, 821, 496, 715, 351, 574, 101, +352, -155, 123, -316, -98, -381, -363, -348, +-647, -150, -875, 178, -1001, 441, -948, 551, +-679, 548, -250, 436, 242, 202, 687, -93, +984, -365, 1072, -534, 970, -597, 742, -599, +401, -504, 8, -293, -290, -62, -497, 177, +-727, 453, -950, 675, -1049, 708, -963, 529, +-696, 215, -323, -104, 173, -363, 780, -536, +1252, -505, 1436, -238, 1450, 89, 1229, 340, +597, 463, -265, 370, -993, 65, -1440, -264, +-1660, -458, -1621, -500, -1196, -433, -452, -258, +339, 3, 1018, 224, 1478, 292, 1604, 254, +1385, 210, 914, 206, 260, 270, -443, 389, +-1025, 440, -1333, 344, -1319, 139, -1044, -138, +-586, -492, -53, -817, 442, -955, 862, -877, +1109, -642, 1034, -265, 773, 179, 499, 559, +156, 797, -277, 910, -618, 937, -792, 843, +-891, 565, -963, 185, -856, -184, -504, -499, +-113, -727, 252, -833, 735, -816, 1221, -639, +1438, -339, 1361, -76, 1004, 67, 393, 131, +-332, 135, -977, 115, -1438, 123, -1612, 195, +-1441, 360, -966, 604, -371, 837, 187, 984, +670, 959, 1025, 690, 1168, 192, 1120, -454, +984, -1140, 769, -1699, 446, -1979, 16, -1905, +-398, -1449, -715, -648, -947, 322, -1105, 1234, +-1126, 1898, -969, 2216, -625, 2155, -211, 1722, +186, 1006, 629, 200, 1072, -537, 1347, -1115, +1391, -1470, 1245, -1571, 858, -1475, 258, -1265, +-451, -980, -1093, -627, -1529, -253, -1694, 118, +-1560, 508, -1052, 918, -274, 1298, 485, 1565, +1052, 1633, 1402, 1468, 1478, 1089, 1217, 526, +752, -171, 244, -881, -244, -1466, -691, -1813, +-910, -1891, -850, -1720, -689, -1320, -574, -750, +-390, -112, -98, 540, 159, 1134, 296, 1590, +390, 1882, 480, 1969, 500, 1780, 447, 1309, +327, 590, 144, -297, -91, -1194, -261, -1915, +-320, -2317, -268, -2285, -186, -1813, -118, -1014, +-63, -61, -14, 843, -26, 1525, -103, 1862, +-173, 1771, -164, 1345, -22, 800, 180, 230, +324, -333, 345, -745, 294, -898, 192, -840, +91, -694, -49, -507, -205, -276, -263, -29, +-177, 154, -91, 250, -65, 279, -65, 230, +-83, 109, -89, -12, -51, -89, 12, -120, +38, -88, 96, 27, 192, 204, 242, 368, +188, 411, 115, 301, -9, 105, -174, -94, +-267, -279, -228, -402, -135, -384, -40, -228, +72, -39, 199, 109, 312, 177, 280, 154, +101, 27, -113, -164, -240, -299, -303, -297, +-333, -218, -303, -98, -96, 120, 192, 394, +361, 584, 389, 652, 348, 583, 227, 384, +0, 111, -224, -196, -334, -504, -319, -722, +-293, -801, -207, -713, 3, -472, 257, -174, +375, 107, 356, 374, 253, 584, 128, 670, +-46, 632, -265, 477, -408, 237, -405, 12, +-299, -183, -140, -365, 72, -468, 284, -439, +420, -307, 389, -104, 291, 112, 181, 266, +12, 295, -187, 210, -284, 67, -330, -101, +-357, -297, -329, -426, -263, -354, -121, -128, +127, 92, 379, 284, 516, 460, 580, 520, +591, 414, 511, 259, 216, 119, -210, -71, +-565, -281, -791, -387, -957, -381, -971, -365, +-718, -387, -252, -343, 232, -161, 623, 49, +983, 189, 1226, 322, 1188, 439, 901, 454, +526, 369, 47, 232, -503, 60, -987, -127, +-1242, -299, -1253, -372, -1095, -287, -790, -147, +-321, -46, 182, 84, 588, 236, 918, 286, +1100, 174, 1054, -44, 843, -263, 600, -407, +327, -472, -7, -424, -376, -229, -637, 66, +-749, 375, -772, 639, -727, 783, -626, 761, +-494, 579, -291, 279, -15, -83, 220, -438, +399, -743, 568, -949, 746, -999, 875, -866, +878, -560, 697, -127, 399, 345, 38, 771, +-355, 1072, -735, 1192, -1010, 1079, -1117, 709, +-1056, 177, -809, -350, -371, -765, 128, -1000, +498, -1014, 763, -797, 986, -420, 1069, -39, +895, 220, 551, 347, 184, 359, -139, 267, +-447, 151, -682, 119, -738, 192, -659, 326, +-525, 447, -305, 499, -45, 441, 99, 225, +148, -122, 209, -480, 293, -775, 349, -939, +369, -908, 328, -692, 219, -352, 74, 37, +-42, 393, -131, 660, -241, 806, -318, 823, +-276, 726, -137, 545, -9, 294, 56, 27, +84, -222, 123, -430, 147, -548, 137, -560, +123, -495, 73, -341, -44, -143, -150, -5, +-223, 35, -315, 3, -378, -78, -319, -163, +-138, -206, 87, -146, 318, 58, 529, 365, +641, 693, 606, 958, 494, 1051, 315, 911, +-1, 565, -359, 68, -602, -499, -713, -997, +-718, -1326, -608, -1431, -391, -1287, -114, -938, +137, -485, 313, -17, 428, 423, 428, 813, +301, 1114, 217, 1295, 282, 1334, 349, 1211, +315, 909, 268, 449, 247, -104, 101, -658, +-203, -1126, -480, -1386, -632, -1344, -724, -1046, +-746, -650, -621, -244, -373, 111, -104, 322, +128, 382, 380, 377, 675, 367, 923, 425, +1022, 566, 940, 732, 661, 854, 251, 826, +-232, 578, -771, 194, -1206, -253, -1301, -709, +-1030, -1056, -561, -1187, -9, -1100, 541, -831, +946, -468, 1027, -123, 788, 166, 366, 366, +-95, 449, -472, 506, -637, 589, -559, 661, +-291, 712, 33, 757, 272, 748, 375, 597, +353, 249, 222, -227, 10, -711, -172, -1130, +-213, -1423, -100, -1458, 28, -1170, 115, -664, +146, -72, 67, 547, -127, 1068, -319, 1323, +-435, 1275, -449, 1026, -332, 663, -95, 237, +193, -175, 427, -476, 585, -594, 676, -551, +661, -439, 484, -291, 240, -158, -1, -131, +-265, -201, -569, -314, -817, -444, -928, -487, +-883, -347, -699, -14, -360, 454, 128, 920, +610, 1220, 940, 1267, 1082, 1009, 1074, 474, +852, -164, 423, -737, -40, -1169, -384, -1325, +-682, -1138, -910, -737, -906, -294, -687, 108, +-436, 449, -197, 695, 86, 770, 342, 703, +471, 583, 464, 404, 437, 134, 386, -136, +243, -324, 40, -451, -54, -518, -53, -436, +-51, -199, -57, 61, -4, 216, 62, 255, +36, 208, -88, 83, -224, -94, -337, -262, +-486, -338, -590, -267, -503, -87, -208, 132, +130, 326, 445, 442, 747, 471, 980, 410, +962, 268, 672, 94, 280, -106, -104, -341, +-495, -530, -849, -601, -1006, -605, -918, -575, +-673, -436, -384, -137, -19, 262, 377, 640, +673, 910, 766, 1057, 740, 1007, 614, 682, +333, 155, -48, -434, -321, -970, -409, -1306, +-435, -1322, -383, -990, -148, -404, 135, 245, +219, 776, 171, 1080, 72, 1097, -102, 837, +-333, 392, -458, -96, -407, -456, -206, -585, +55, -542, 335, -430, 608, -274, 767, -88, +705, 81, 448, 191, 123, 226, -214, 237, +-515, 241, -707, 187, -678, 55, -503, -119, +-310, -270, -117, -337, 104, -315, 243, -195, +228, 35, 140, 310, 118, 493, 175, 517, +219, 409, 288, 202, 407, -86, 483, -388, +392, -593, 172, -638, -117, -565, -394, -398, +-638, -139, -816, 170, -843, 463, -675, 689, +-421, 819, -139, 829, 197, 657, 546, 300, +811, -165, 887, -639, 843, -1009, 743, -1177, +539, -1089, 202, -731, -141, -168, -455, 444, +-730, 949, -906, 1237, -927, 1201, -827, 853, +-653, 333, -434, -233, -146, -734, 258, -1033, +676, -1051, 975, -773, 1130, -291, 1204, 227, +1090, 660, 672, 923, 61, 927, -509, 692, +-1013, 307, -1401, -162, -1490, -638, -1214, -954, +-702, -1012, -103, -851, 504, -556, 989, -157, +1215, 332, 1124, 789, 819, 1049, 379, 1084, +-83, 930, -461, 586, -697, 103, -775, -383, +-620, -753, -295, -972, 20, -992, 263, -748, +462, -314, 569, 133, 510, 473, 325, 668, +65, 697, -234, 527, -515, 179, -665, -215, +-686, -516, -592, -655, -379, -601, -67, -343, +274, 24, 582, 369, 803, 625, 862, 722, +746, 624, 518, 377, 239, 53, -74, -223, +-348, -334, -542, -280, -644, -142, -667, -12, +-585, 23, -467, -62, -358, -265, -204, -585, +4, -893, 176, -974, 319, -755, 503, -291, +656, 339, 671, 1000, 581, 1502, 473, 1719, +296, 1599, 12, 1158, -281, 477, -466, -297, +-583, -963, -674, -1391, -675, -1563, -518, -1482, +-272, -1167, -13, -681, 245, -154, 458, 303, +562, 610, 533, 734, 417, 719, 240, 630, +30, 503, -189, 397, -336, 361, -353, 368, +-290, 340, -214, 242, -89, 61, 68, -206, +178, -499, 241, -715, 290, -760, 297, -608, +218, -352, 82, -81, -77, 173, -234, 326, +-359, 301, -439, 126, -458, -83, -377, -221, +-194, -244, 23, -151, 198, 48, 337, 310, +447, 530, 475, 638, 422, 629, 329, 497, +210, 254, 59, -25, -80, -282, -178, -471, +-273, -555, -363, -537, -400, -445, -398, -315, +-364, -189, -254, -91, -88, -48, 55, -57, +170, -83, 315, -72, 432, 12, 409, 169, +282, 365, 164, 542, 59, 646, -70, 647, +-169, 547, -172, 356, -131, 93, -113, -172, +-83, -364, -34, -478, -18, -536, -41, -536, +-40, -499, 4, -463, 71, -429, 105, -356, +69, -233, 14, -94, -23, 76, -90, 324, +-163, 602, -161, 798, -117, 866, -63, 829, +43, 663, 188, 358, 254, -15, 221, -362, +172, -632, 133, -778, 73, -761, 13, -595, +-46, -376, -126, -177, -180, -10, -177, 109, +-192, 172, -248, 197, -225, 189, -121, 162, +-34, 136, 45, 137, 196, 158, 351, 164, +402, 157, 372, 197, 308, 264, 143, 265, +-117, 167, -336, 8, -455, -184, -493, -373, +-432, -519, -252, -569, -10, -488, 226, -326, +398, -150, 453, 32, 371, 193, 221, 286, +92, 314, -6, 346, -82, 426, -99, 512, +-78, 506, -120, 374, -194, 161, -245, -115, +-301, -453, -365, -757, -338, -898, -178, -832, +63, -599, 311, -245, 536, 169, 670, 538, +665, 757, 525, 815, 275, 746, -47, 568, +-372, 286, -616, -50, -735, -355, -713, -560, +-575, -654, -340, -617, -33, -453, 287, -188, +525, 118, 645, 374, 655, 490, 555, 441, +350, 250, 77, -23, -194, -277, -426, -427, +-597, -452, -648, -334, -534, -81, -318, 230, +-60, 499, 209, 654, 467, 651, 644, 485, +689, 188, 581, -163, 357, -468, 73, -676, +-251, -765, -560, -682, -746, -426, -763, -94, +-665, 204, -461, 429, -117, 576, 296, 635, +612, 587, 783, 437, 816, 213, 674, -62, +344, -359, -47, -615, -370, -785, -601, -816, +-701, -651, -596, -266, -313, 262, 1, 768, +269, 1096, 438, 1157, 457, 917, 320, 432, +112, -167, -114, -719, -302, -1079, -374, -1154, +-277, -936, -66, -513, 174, -28, 374, 383, +469, 639, 411, 737, 182, 695, -161, 520, +-497, 238, -712, -72, -765, -304, -609, -412, +-243, -422, 221, -341, 638, -160, 927, 75, +1027, 264, 869, 330, 459, 255, -43, 58, +-451, -184, -743, -338, -903, -319, -844, -157, +-556, 65, -209, 299, 83, 479, 330, 488, +505, 279, 505, -61, 353, -401, 170, -643, +35, -723, -64, -595, -140, -308, -156, 22, +-90, 345, 27, 652, 129, 851, 184, 853, +175, 680, 84, 411, -61, 74, -193, -310, +-311, -678, -401, -945, -392, -1059, -250, -975, +-48, -660, 135, -183, 321, 300, 477, 714, +494, 1037, 364, 1189, 225, 1082, 110, 730, +-48, 247, -213, -249, -263, -678, -256, -979, +-305, -1109, -365, -1046, -338, -808, -267, -446, +-211, -36, -104, 355, 118, 691, 376, 945, +546, 1082, 611, 1083, 583, 938, 439, 611, +171, 103, -116, -469, -328, -957, -430, -1280, +-445, -1392, -404, -1223, -298, -764, -138, -132, +-36, 486, -68, 928, -127, 1123, -108, 1074, +-62, 819, -28, 443, 106, 42, 339, -303, +516, -526, 563, -599, 563, -572, 515, -481, +323, -309, 3, -80, -296, 129, -503, 290, +-657, 408, -766, 467, -750, 422, -574, 278, +-323, 121, -49, 9, 235, -112, 480, -278, +633, -432, 680, -536, 624, -622, 473, -673, +255, -587, 39, -298, -122, 149, -225, 643, +-277, 1078, -299, 1363, -309, 1388, -319, 1079, +-287, 493, -239, -215, -203, -878, -136, -1361, +-9, -1576, 129, -1500, 257, -1157, 355, -605, +374, 18, 293, 558, 176, 940, 72, 1140, +-18, 1159, -80, 1020, -75, 759, -30, 440, +6, 129, 28, -154, 6, -406, -109, -611, +-271, -775, -385, -900, -423, -929, -388, -800, +-260, -523, -23, -151, 274, 242, 517, 594, +665, 852, 700, 960, 592, 886, 350, 651, +47, 320, -261, -13, -514, -263, -683, -426, +-732, -535, -620, -560, -368, -450, -76, -241, +193, -21, 432, 148, 586, 220, 586, 183, +437, 48, 197, -152, -60, -371, -257, -518, +-343, -464, -308, -157, -181, 308, 0, 753, +161, 1047, 240, 1136, 225, 965, 110, 531, +-92, -57, -299, -647, -402, -1119, -383, -1359, +-289, -1292, -145, -967, 73, -524, 318, -59, +486, 401, 540, 817, 519, 1074, 392, 1073, +158, 867, -93, 562, -294, 211, -469, -135, +-587, -414, -564, -589, -394, -616, -153, -475, +95, -223, 315, 30, 441, 188, 442, 226, +356, 165, 204, 33, -17, -173, -235, -424, +-346, -612, -342, -601, -273, -358, -163, 31, +-26, 439, 125, 775, 291, 983, 416, 1006, +438, 788, 361, 374, 237, -91, 62, -469, +-162, -666, -384, -666, -553, -546, -639, -400, +-565, -281, -313, -206, 23, -164, 325, -150, +529, -162, 600, -148, 512, -47, 273, 131, +-54, 327, -361, 488, -529, 585, -483, 655, +-248, 734, 66, 743, 349, 563, 534, 211, +565, -219, 411, -665, 117, -1082, -221, -1364, +-493, -1374, -620, -1072, -574, -553, -401, 69, +-174, 691, 49, 1153, 259, 1315, 429, 1212, +504, 965, 457, 618, 360, 177, 260, -277, +104, -632, -124, -846, -335, -950, -498, -953, +-623, -803, -612, -472, -369, -26, -19, 445, +271, 846, 494, 1062, 653, 1018, 640, 735, +411, 273, 56, -279, -293, -782, -534, -1091, +-580, -1119, -420, -849, -144, -355, 150, 234, +397, 771, 506, 1115, 445, 1170, 274, 957, +44, 542, -223, 6, -423, -513, -474, -872, +-406, -1005, -295, -913, -145, -661, 23, -334, +149, 17, 230, 326, 309, 519, 346, 587, +295, 558, 200, 438, 106, 242, -14, 39, +-160, -117, -261, -222, -245, -275, -150, -254, +-53, -150, 42, -11, 149, 81, 222, 108, +199, 107, 54, 89, -133, 44, -272, 9, +-359, 4, -413, -22, -356, -92, -163, -171, +51, -224, 228, -247, 435, -251, 651, -211, +726, -73, 602, 142, 386, 310, 131, 367, +-206, 343, -576, 280, -845, 193, -955, 104, +-907, 27, -688, -14, -287, -19, 201, -25, +619, -55, 870, -109, 967, -195, 921, -288, +688, -338, 282, -334, -153, -305, -473, -280, +-660, -244, -737, -154, -641, 23, -390, 269, +-139, 533, 72, 769, 294, 924, 439, 949, +403, 787, 267, 394, 148, -172, 30, -749, +-109, -1189, -212, -1431, -244, -1430, -232, -1147, +-180, -635, -78, 15, 25, 701, 105, 1274, +184, 1576, 244, 1545, 258, 1216, 229, 683, +141, 36, -26, -614, -193, -1101, -284, -1279, +-312, -1155, -303, -825, -208, -387, 1, 40, +235, 354, 388, 544, 440, 617, 380, 582, +201, 458, -42, 267, -272, 56, -442, -125, +-511, -285, -470, -431, -335, -500, -129, -418, +93, -175, 267, 150, 367, 430, 387, 585, +362, 605, 341, 488, 293, 231, 169, -95, +10, -389, -107, -582, -184, -632, -283, -530, +-371, -336, -365, -122, -263, 84, -145, 250, +-39, 340, 58, 351, 125, 287, 128, 158, +85, 15, 58, -68, 71, -40, 74, 71, +69, 171, 109, 216, 173, 225, 177, 160, +105, -34, 22, -284, -23, -469, -61, -531, +-125, -459, -178, -282, -210, -73, -252, 95, +-267, 184, -207, 220, -106, 256, -5, 303, +138, 336, 337, 360, 493, 364, 493, 296, +357, 118, 159, -164, -89, -471, -356, -660, +-511, -648, -490, -475, -367, -211, -192, 94, +45, 351, 283, 474, 400, 459, 354, 345, +203, 149, 32, -86, -92, -266, -157, -324, +-189, -282, -172, -203, -63, -94, 73, 88, +121, 317, 97, 479, 73, 495, 40, 360, +-14, 104, -39, -189, -25, -440, -39, -616, +-82, -668, -87, -532, -50, -228, -35, 139, +-32, 450, 2, 630, 73, 653, 150, 528, +192, 293, 155, 16, 58, -266, -50, -547, +-142, -732, -202, -696, -204, -468, -160, -171, +-91, 140, 14, 459, 165, 723, 285, 828, +295, 719, 227, 437, 151, 83, 59, -239, +-79, -464, -233, -579, -333, -609, -347, -557, +-299, -414, -197, -212, -28, -15, 145, 149, +241, 278, 261, 359, 259, 398, 215, 390, +89, 292, -64, 108, -111, -74, -44, -179, +21, -197, 31, -168, 46, -131, 65, -86, +35, -17, -51, 58, -140, 103, -201, 102, +-226, 65, -189, 46, -73, 71, 64, 74, +136, 4, 141, -88, 143, -147, 152, -175, +107, -183, -10, -171, -128, -141, -167, -92, +-122, -10, -41, 103, 40, 209, 97, 262, +127, 252, 119, 204, 90, 126, 50, -2, +-22, -153, -102, -246, -94, -225, -2, -97, +76, 81, 85, 232, 46, 297, -42, 251, +-159, 109, -244, -73, -253, -224, -216, -314, +-139, -327, 31, -231, 255, -68, 380, 40, +352, 26, 242, -58, 94, -132, -81, -153, +-235, -111, -305, 19, -266, 236, -138, 463, +41, 610, 204, 637, 288, 524, 278, 270, +186, -53, 33, -361, -122, -606, -251, -742, +-333, -750, -323, -651, -188, -453, -7, -168, +130, 154, 207, 438, 248, 631, 247, 719, +178, 689, 63, 532, -32, 270, -116, -26, +-197, -292, -202, -495, -134, -592, -88, -542, +-83, -388, -24, -196, 100, 17, 193, 241, +202, 404, 173, 439, 141, 348, 73, 169, +-37, -52, -148, -261, -218, -399, -227, -408, +-174, -280, -82, -49, 63, 240, 216, 508, +295, 635, 264, 565, 182, 329, 78, -19, +-80, -380, -294, -647, -434, -759, -421, -691, +-319, -437, -170, -58, 46, 332, 276, 595, +429, 655, 485, 555, 442, 363, 309, 96, +101, -194, -127, -389, -292, -429, -365, -359, +-385, -241, -353, -104, -239, 29, -79, 122, +78, 177, 213, 243, 333, 340, 396, 408, +361, 389, 237, 290, 71, 126, -137, -125, +-362, -456, -519, -759, -528, -898, -385, -807, +-129, -517, 164, -111, 427, 322, 597, 697, +610, 918, 459, 922, 185, 725, -137, 394, +-416, 26, -572, -278, -580, -456, -453, -507, +-257, -466, -28, -363, 209, -216, 369, -58, +432, 52, 428, 84, 358, 63, 217, 20, +55, -13, -93, -12, -218, 26, -326, 89, +-366, 174, -292, 274, -121, 336, 42, 290, +156, 118, 242, -118, 281, -331, 215, -463, +50, -487, -143, -385, -284, -166, -348, 104, +-317, 341, -190, 469, -22, 431, 145, 242, +278, 8, 355, -167, 368, -251, 305, -239, +175, -115, 32, 81, -58, 250, -102, 300, +-152, 212, -218, 13, -238, -252, -188, -498, +-128, -597, -99, -495, -34, -251, 53, 65, +93, 404, 82, 681, 54, 784, -8, 649, +-113, 337, -199, -24, -163, -340, -24, -563, +112, -642, 231, -554, 384, -348, 507, -103, +472, 119, 292, 266, 55, 319, -199, 297, +-441, 246, -595, 212, -616, 198, -542, 168, +-388, 110, -137, 37, 160, -62, 402, -218, +536, -393, 541, -510, 454, -535, 297, -468, +84, -297, -161, -31, -358, 267, -443, 523, +-396, 704, -267, 788, -84, 738, 112, 524, +263, 203, 347, -140, 388, -455, 344, -696, +160, -808, -69, -779, -238, -613, -350, -331, +-431, -6, -455, 270, -387, 449, -217, 523, +29, 505, 274, 404, 425, 255, 463, 108, +444, -9, 368, -97, 218, -136, 16, -129, +-158, -116, -261, -115, -273, -93, -206, -43, +-113, 3, -75, 19, -90, 0, -96, -52, +-88, -118, -117, -176, -157, -212, -127, -202, +-19, -113, 141, 49, 312, 231, 425, 358, +428, 387, 346, 314, 223, 162, 62, -19, +-174, -153, -439, -212, -601, -210, -613, -143, +-510, -3, -305, 126, 1, 150, 338, 87, +631, 12, 814, -57, 830, -131, 631, -194, +250, -214, -216, -196, -618, -168, -895, -112, +-1002, -7, -890, 95, -545, 169, -51, 250, +430, 339, 779, 371, 943, 311, 893, 180, +650, 43, 290, -78, -122, -200, -503, -316, +-753, -387, -788, -403, -611, -363, -309, -260, +21, -91, 333, 107, 600, 301, 720, 465, +630, 571, 365, 543, 8, 349, -340, 53, +-592, -232, -711, -450, -657, -582, -477, -600, +-219, -483, 103, -277, 413, -45, 585, 172, +593, 351, 512, 461, 397, 508, 236, 516, +52, 485, -106, 367, -226, 149, -316, -119, +-372, -361, -379, -553, -371, -671, -342, -670, +-242, -526, -72, -287, 133, -8, 303, 251, +393, 428, 421, 491, 373, 466, 222, 405, +14, 326, -198, 219, -328, 100, -348, -3, +-271, -90, -135, -188, 55, -312, 245, -441, +355, -525, 364, -531, 287, -445, 148, -261, +-30, 12, -224, 333, -355, 634, -383, 853, +-372, 936, -317, 820, -192, 497, -37, 47, +93, -407, 179, -789, 239, -1042, 286, -1088, +314, -886, 311, -507, 278, -53, 204, 380, +98, 707, -37, 845, -197, 777, -365, 560, +-466, 275, -482, -27, -389, -278, -189, -397, +62, -340, 308, -166, 498, 44, 572, 220, +522, 307, 334, 260, 36, 85, -255, -175, +-475, -439, -617, -629, -638, -672, -498, -529, +-242, -220, 59, 149, 339, 468, 556, 667, +669, 727, 638, 635, 482, 404, 244, 93, +-52, -193, -350, -368, -546, -416, -620, -369, +-575, -245, -436, -84, -219, 58, 45, 148, +302, 180, 469, 125, 526, -12, 477, -170, +342, -260, 154, -255, -51, -177, -220, -47, +-337, 133, -400, 314, -379, 428, -266, 421, +-140, 280, -42, 36, 61, -223, 177, -409, +264, -474, 314, -422, 330, -268, 294, -27, +203, 263, 65, 504, -74, 597, -236, 509, +-403, 291, -471, 9, -393, -280, -255, -522, +-87, -658, 107, -646, 309, -455, 438, -129, +462, 226, 396, 495, 257, 627, 70, 613, +-127, 475, -274, 226, -368, -85, -422, -359, +-412, -505, -317, -510, -143, -395, 69, -200, +245, 24, 384, 219, 473, 350, 484, 400, +393, 359, 176, 204, -98, -27, -343, -231, +-509, -328, -568, -331, -496, -270, -322, -143, +-69, 50, 219, 238, 472, 329, 585, 295, +545, 186, 382, 46, 169, -80, -54, -151, +-280, -162, -434, -161, -477, -165, -423, -161, +-281, -134, -79, -104, 129, -58, 293, 42, +374, 207, 390, 375, 328, 474, 152, 445, +-109, 281, -351, 16, -469, -258, -460, -448, +-340, -507, -135, -441, 146, -272, 428, -51, +600, 143, 594, 227, 427, 188, 131, 70, +-183, -38, -422, -79, -502, -33, -421, 86, +-260, 248, -57, 385, 162, 431, 294, 347, +245, 138, 62, -173, -145, -508, -287, -755, +-311, -818, -192, -672, 23, -353, 255, 82, +427, 553, 514, 926, 474, 1088, 262, 983, +-29, 635, -282, 116, -440, -435, -497, -869, +-448, -1102, -331, -1116, -179, -900, -31, -486, +126, 36, 265, 527, 356, 891, 409, 1081, +437, 1075, 394, 857, 264, 467, 53, -13, +-221, -491, -476, -874, -640, -1055, -665, -980, +-541, -687, -303, -280, -7, 141, 313, 491, +574, 705, 700, 726, 685, 562, 548, 300, +328, 50, 81, -133, -167, -232, -411, -260, +-609, -240, -738, -203, -739, -160, -614, -118, +-380, -78, -50, -51, 342, -26, 708, 21, +969, 103, 1031, 186, 859, 238, 483, 241, +1, 201, -472, 124, -827, 16, -999, -132, +-977, -293, -740, -410, -346, -415, 94, -299, +473, -100, 703, 118, 787, 322, 744, 480, +563, 549, 293, 485, -15, 307, -332, 67, +-588, -177, -735, -379, -734, -505, -608, -565, +-379, -559, -71, -475, 303, -286, 646, -18, +836, 260, 849, 481, 717, 632, 445, 693, +101, 635, -267, 454, -590, 203, -783, -61, +-837, -283, -729, -433, -495, -503, -206, -522, +91, -522, 350, -502, 547, -403, 668, -206, +659, 48, 512, 291, 299, 502, 93, 671, +-108, 747, -295, 650, -415, 384, -465, 50, +-409, -234, -293, -424, -151, -515, -17, -514, +63, -431, 105, -305, 146, -161, 150, -22, +139, 93, 127, 169, 137, 235, 183, 315, +226, 395, 216, 415, 136, 350, 24, 210, +-109, 21, -247, -192, -368, -399, -445, -587, +-429, -712, -329, -702, -165, -500, 62, -159, +267, 233, 393, 605, 455, 899, 450, 1033, +385, 952, 219, 661, -2, 220, -184, -273, +-286, -687, -336, -934, -318, -993, -241, -912, +-138, -714, -34, -412, 65, -42, 127, 318, +141, 618, 103, 829, 45, 928, 29, 885, +28, 687, 21, 345, 23, -78, 29, -480, +34, -743, 43, -818, 35, -713, 6, -488, +-25, -211, -60, 48, -82, 243, -87, 340, +-84, 343, -83, 278, -64, 205, -43, 157, +-5, 127, 38, 77, 86, 7, 131, -61, +165, -104, 182, -118, 180, -103, 128, -88, +24, -90, -103, -115, -235, -142, -335, -161, +-359, -152, -296, -93, -153, 40, 53, 226, +260, 409, 440, 512, 529, 487, 455, 316, +252, 57, -27, -226, -320, -473, -554, -644, +-667, -683, -610, -570, -362, -331, -5, -28, +361, 298, 648, 567, 803, 718, 732, 723, +457, 595, 63, 340, -328, -15, -628, -392, +-803, -655, -761, -731, -472, -621, -84, -374, +269, -49, 515, 271, 611, 510, 537, 595, +293, 508, -2, 275, -233, -19, -347, -289, +-321, -457, -167, -496, 46, -411, 205, -241, +255, -10, 181, 239, 18, 451, -172, 550, +-346, 508, -430, 350, -345, 134, -151, -102, +111, -320, 347, -481, 500, -542, 549, -485, +462, -305, 265, -68, 16, 142, -253, 266, +-485, 313, -601, 301, -574, 235, -444, 116, +-240, -5, 38, -66, 328, -34, 571, 53, +681, 142, 633, 171, 441, 128, 119, 23, +-222, -116, -500, -274, -669, -416, -673, -485, +-505, -430, -202, -256, 160, -10, 433, 209, +563, 346, 529, 410, 372, 429, 134, 391, +-105, 303, -290, 185, -376, 72, -326, -32, +-183, -130, -14, -249, 132, -391, 200, -522, +199, -549, 156, -425, 64, -186, -30, 82, +-117, 343, -184, 559, -198, 671, -166, 619, +-104, 410, -16, 91, 91, -235, 194, -479, +287, -584, 329, -549, 281, -417, 141, -234, +-52, -3, -264, 239, -424, 409, -518, 441, +-486, 371, -306, 259, -17, 154, 306, 47, +560, -63, 675, -165, 643, -226, 467, -242, +166, -221, -178, -194, -482, -165, -676, -110, +-716, 10, -608, 167, -390, 286, -96, 308, +183, 239, 399, 105, 546, -61, 580, -234, +500, -356, 328, -374, 112, -270, -98, -65, +-256, 203, -352, 428, -358, 513, -284, 449, +-146, 302, 21, 121, 167, -78, 213, -284, +181, -428, 81, -455, -75, -376, -223, -271, +-322, -171, -321, -64, -202, 62, -9, 181, +216, 271, 411, 312, 505, 297, 476, 227, +321, 144, 80, 73, -177, 11, -377, -67, +-482, -130, -461, -148, -298, -138, -83, -144, +148, -166, 335, -186, 408, -167, 351, -93, +179, 20, -48, 129, -237, 210, -382, 254, +-424, 270, -343, 244, -161, 165, 81, 32, +311, -102, 467, -202, 492, -262, 401, -306, +223, -329, 4, -315, -204, -239, -383, -104, +-464, 76, -403, 265, -267, 433, -81, 538, +98, 567, 219, 509, 286, 346, 275, 80, +231, -211, 137, -459, 4, -620, -105, -690, +-154, -657, -170, -534, -164, -333, -149, -80, +-123, 196, -81, 432, 20, 597, 121, 689, +187, 729, 237, 680, 255, 498, 261, 204, +205, -122, 65, -432, -99, -693, -267, -856, +-390, -861, -420, -708, -396, -444, -325, -133, +-188, 195, 19, 479, 238, 650, 394, 691, +483, 654, 497, 569, 452, 430, 329, 215, +164, -33, -35, -256, -271, -427, -459, -563, +-528, -635, -515, -609, -425, -484, -285, -302, +-88, -88, 161, 121, 381, 286, 498, 386, +483, 457, 372, 512, 224, 527, 66, 466, +-115, 344, -274, 179, -354, -27, -357, -276, +-281, -511, -142, -671, -28, -719, 31, -639, +82, -427, 140, -138, 187, 156, 163, 394, +107, 570, 85, 666, 109, 651, 133, 515, +148, 310, 123, 79, 59, -146, -30, -350, +-133, -496, -265, -576, -407, -579, -520, -486, +-521, -299, -374, -91, -129, 89, 167, 237, +438, 382, 643, 502, 754, 557, 714, 526, +496, 435, 156, 291, -203, 95, -487, -144, +-631, -392, -628, -619, -515, -748, -320, -718, +-70, -529, 177, -244, 363, 63, 385, 338, +301, 554, 194, 651, 83, 590, -36, 395, +-143, 173, -202, -5, -179, -134, -96, -217, +20, -242, 121, -236, 171, -229, 161, -221, +113, -185, 48, -129, -65, -65, -186, 8, +-274, 128, -289, 256, -192, 316, -35, 285, +124, 211, 255, 120, 342, 26, 383, -77, +332, -189, 167, -303, -42, -384, -260, -416, +-408, -388, -459, -297, -407, -119, -293, 159, +-117, 496, 106, 772, 310, 888, 427, 795, +428, 515, 312, 94, 153, -374, -15, -781, +-150, -1007, -211, -995, -233, -760, -172, -379, +-44, 59, 82, 430, 151, 652, 124, 704, +27, 625, -99, 440, -221, 188, -297, -73, +-302, -260, -225, -343, -84, -342, 99, -293, +308, -195, 453, -61, 510, 84, 450, 209, +325, 301, 176, 327, -13, 292, -220, 202, +-397, 56, -530, -158, -575, -399, -532, -602, +-406, -687, -204, -623, 26, -401, 268, -53, +495, 364, 660, 742, 667, 980, 517, 1003, +283, 802, 14, 415, -251, -60, -477, -511, +-598, -835, -557, -976, -398, -920, -166, -692, +114, -331, 333, 71, 445, 426, 432, 672, +338, 792, 181, 763, -35, 580, -276, 273, +-434, -79, -444, -405, -325, -628, -138, -708, +66, -628, 257, -411, 417, -110, 487, 198, +422, 452, 246, 590, -12, 586, -256, 448, +-411, 225, -470, -38, -447, -288, -353, -475, +-186, -538, 46, -464, 274, -272, 411, -25, +455, 224, 415, 395, 309, 433, 174, 332, +26, 139, -152, -91, -287, -268, -338, -309, +-295, -189, -212, 23, -137, 222, -74, 327, +-18, 308, 28, 148, 61, -125, 76, -424, +67, -615, 71, -623, 123, -445, 188, -132, +211, 238, 180, 566, 88, 772, 6, 806, +-56, 676, -126, 406, -181, 48, -219, -319, +-203, -605, -129, -757, -52, -754, -11, -612, +7, -351, 27, -31, 86, 280, 152, 499, +192, 575, 178, 491, 147, 301, 95, 70, +18, -134, -87, -281, -233, -341, -338, -301, +-338, -155, -241, 38, -63, 215, 136, 347, +304, 428, 431, 425, 468, 315, 404, 94, +214, -190, -75, -480, -360, -705, -550, -796, +-601, -702, -535, -440, -354, -63, -82, 347, +236, 705, 525, 917, 679, 932, 649, 736, +478, 398, 196, -2, -98, -381, -362, -677, +-555, -837, -610, -834, -520, -668, -297, -368, +-11, 12, 225, 386, 356, 683, 393, 848, +365, 847, 268, 661, 112, 329, -48, -87, +-169, -485, -207, -777, -195, -906, -154, -865, +-103, -658, -82, -335, -54, 42, 0, 403, +66, 689, 123, 851, 154, 868, 167, 731, +191, 488, 185, 181, 118, -148, -24, -453, +-183, -674, -312, -775, -376, -745, -367, -606, +-283, -387, -118, -132, 96, 138, 324, 380, +517, 548, 586, 612, 491, 585, 278, 474, +2, 295, -273, 79, -507, -112, -638, -251, +-611, -341, -434, -392, -152, -387, 167, -329, +435, -247, 573, -164, 580, -62, 468, 72, +275, 228, 31, 360, -216, 424, -410, 400, +-485, 295, -463, 119, -357, -85, -206, -271, +-35, -385, 139, -400, 289, -305, 383, -134, +397, 55, 328, 203, 189, 276, 38, 273, +-104, 220, -234, 119, -317, -19, -317, -158, +-236, -247, -93, -273, 56, -236, 178, -150, +251, -31, 243, 99, 178, 225, 73, 308, +-44, 316, -167, 232, -241, 95, -234, -39, +-161, -124, -73, -168, 10, -179, 90, -169, +162, -145, 186, -126, 187, -127, 167, -147, +110, -155, 39, -112, -37, 14, -93, 205, +-142, 401, -188, 530, -189, 554, -133, 463, +-49, 272, 35, -11, 83, -349, 99, -660, +84, -844, 48, -847, -1, -682, -42, -407, +-22, -49, 37, 354, 142, 731, 241, 988, +278, 1059, 228, 921, 78, 614, -144, 190, +-373, -279, -586, -719, -681, -1051, -600, -1192, +-336, -1089, 62, -761, 489, -273, 845, 260, +1018, 719, 951, 1006, 655, 1088, 192, 951, +-339, 619, -819, 170, -1107, -259, -1104, -550, +-846, -658, -414, -617, 73, -481, 518, -304, +835, -120, 920, 27, 797, 102, 522, 106, +181, 92, -148, 116, -394, 196, -529, 286, +-548, 333, -490, 311, -362, 237, -193, 108, +-8, -64, 144, -249, 261, -391, 353, -450, +387, -400, 365, -262, 270, -75, 113, 97, +-58, 223, -208, 292, -307, 307, -321, 259, +-271, 158, -175, 32, -56, -72, 67, -128, +167, -135, 198, -128, 169, -112, 112, -89, +72, -43, 37, 15, 11, 70, -23, 104, +-67, 120, -105, 123, -119, 118, -130, 79, +-119, -5, -95, -108, -35, -183, 56, -218, +133, -200, 164, -152, 142, -89, 83, -17, +5, 68, -50, 145, -80, 199, -79, 221, +-48, 219, 4, 211, 68, 196, 114, 135, +105, 23, 54, -117, -1, -239, -43, -313, +-65, -316, -90, -247, -118, -130, -147, -17, +-151, 60, -141, 88, -107, 57, -64, -38, +6, -130, 113, -138, 251, -29, 374, 156, +424, 364, 356, 531, 213, 600, 40, 522, +-160, 312, -361, 12, -521, -322, -558, -633, +-460, -822, -269, -845, -26, -731, 221, -529, +398, -241, 474, 110, 482, 467, 424, 759, +273, 936, 60, 959, -136, 815, -272, 518, +-331, 131, -375, -286, -382, -658, -337, -901, +-242, -943, -99, -787, 67, -491, 216, -145, +341, 177, 426, 420, 463, 559, 419, 581, +285, 493, 87, 323, -133, 132, -307, -29, +-419, -130, -458, -185, -431, -219, -330, -234, +-156, -207, 34, -141, 189, -67, 283, -18, +310, 22, 299, 77, 262, 131, 181, 152, +74, 128, -40, 53, -93, -46, -101, -132, +-93, -167, -97, -153, -101, -102, -107, -18, +-121, 99, -124, 208, -117, 264, -129, 230, +-114, 121, -32, -7, 106, -99, 245, -144, +314, -157, 325, -157, 287, -128, 187, -71, +31, -10, -147, 19, -300, 14, -377, -6, +-340, -8, -213, 15, -61, 43, 72, 40, +173, 27, 221, 45, 224, 100, 160, 152, +51, 175, -62, 152, -107, 88, -95, -13, +-86, -129, -89, -249, -70, -347, -31, -379, +10, -290, 52, -90, 100, 143, 137, 321, +134, 410, 120, 410, 97, 328, 23, 163, +-116, -69, -237, -303, -273, -448, -236, -460, +-148, -346, -33, -160, 92, 52, 201, 250, +275, 406, 280, 484, 214, 446, 91, 279, +-30, 45, -122, -167, -169, -301, -190, -372, +-183, -400, -155, -375, -94, -285, -12, -143, +47, 34, 58, 204, 52, 336, 70, 415, +102, 460, 121, 446, 116, 313, 90, 48, +30, -257, -33, -497, -87, -622, -131, -626, +-169, -486, -164, -217, -71, 120, 76, 448, +201, 701, 250, 790, 233, 666, 147, 372, +0, 19, -165, -315, -292, -603, -361, -794, +-331, -803, -205, -599, -9, -246, 173, 146, +277, 476, 299, 676, 263, 715, 195, 592, +96, 344, -13, 27, -87, -282, -103, -489, +-93, -518, -93, -383, -119, -171, -151, 37, +-185, 212, -173, 334, -83, 364, 58, 268, +197, 71, 288, -158, 335, -348, 302, -448, +153, -432, -87, -311, -326, -117, -488, 125, +-498, 390, -354, 600, -87, 661, 201, 539, +446, 290, 588, -7, 583, -295, 416, -538, +118, -686, -200, -700, -451, -558, -588, -281, +-581, 59, -443, 376, -221, 612, 52, 735, +302, 740, 470, 608, 503, 329, 415, -60, +252, -455, 58, -746, -127, -868, -285, -820, +-373, -622, -352, -307, -225, 80, -54, 462, +101, 754, 195, 883, 219, 823, 163, 617, +86, 340, 8, 29, -65, -292, -126, -576, +-149, -742, -94, -750, -6, -612, 52, -382, +70, -119, 84, 131, 95, 340, 91, 489, +64, 548, 19, 493, -46, 343, -111, 156, +-166, -6, -189, -133, -173, -238, -135, -318, +-48, -345, 86, -296, 226, -176, 299, -41, +293, 61, 230, 126, 144, 181, 16, 231, +-139, 255, -276, 227, -327, 152, -294, 52, +-196, -48, -57, -146, 79, -259, 167, -377, +195, -435, 193, -360, 150, -167, 54, 61, +-63, 265, -141, 418, -160, 496, -125, 481, +-66, 373, 6, 190, 80, -28, 152, -217, +215, -312, 234, -325, 186, -319, 72, -333, +-56, -330, -185, -266, -293, -150, -356, -19, +-347, 110, -254, 242, -66, 377, 154, 486, +336, 531, 431, 465, 430, 291, 334, 66, +161, -149, -45, -330, -248, -491, -401, -616, +-470, -634, -409, -501, -240, -259, -45, 14, +131, 262, 288, 457, 398, 579, 419, 602, +343, 518, 199, 322, 17, 49, -162, -206, +-270, -357, -311, -408, -300, -415, -246, -382, +-142, -271, -27, -90, 66, 99, 118, 237, +132, 304, 124, 303, 127, 254, 139, 185, +141, 95, 120, -30, 81, -161, 38, -242, +-38, -248, -131, -215, -221, -183, -291, -153, +-311, -91, -229, 25, -58, 177, 122, 308, +261, 373, 364, 363, 409, 302, 348, 189, +187, 18, -35, -196, -254, -388, -430, -484, +-477, -442, -382, -300, -209, -140, -25, -6, +158, 112, 318, 211, 407, 260, 377, 242, +260, 188, 101, 135, -47, 117, -146, 136, +-213, 157, -246, 114, -238, 3, -173, -125, +-88, -229, -7, -322, 69, -397, 124, -406, +148, -306, 148, -106, 126, 145, 75, 358, +-11, 462, -89, 442, -93, 343, -62, 203, +-36, 25, -14, -171, 16, -315, 34, -356, +45, -303, 46, -204, 24, -108, -15, -39, +-24, 30, 6, 137, 38, 266, 42, 350, +18, 353, -31, 290, -110, 180, -168, 8, +-183, -219, -170, -454, -129, -617, -6, -635, +185, -472, 354, -177, 437, 157, 433, 447, +336, 657, 130, 760, -136, 715, -392, 497, +-580, 146, -657, -237, -567, -542, -340, -716, +-37, -756, 257, -674, 493, -468, 624, -160, +624, 190, 504, 488, 282, 656, 3, 659, +-239, 535, -368, 348, -399, 128, -369, -111, +-282, -321, -140, -440, -14, -435, 62, -339, +87, -205, 66, -85, 9, -5, -38, 53, +-27, 116, 27, 163, 89, 155, 148, 112, +208, 99, 235, 134, 211, 173, 132, 171, +34, 117, -80, 31, -172, -62, -213, -152, +-214, -233, -207, -309, -190, -356, -140, -319, +-70, -189, 8, -21, 68, 127, 96, 245, +112, 347, 137, 433, 148, 466, 143, 402, +124, 246, 104, 42, 81, -165, 50, -354, +18, -511, -40, -610, -141, -618, -250, -505, +-286, -269, -247, 30, -186, 308, -112, 512, +22, 647, 172, 724, 272, 697, 284, 527, +247, 252, 173, -58, 74, -350, -15, -586, +-74, -734, -115, -786, -147, -724, -166, -519, +-165, -192, -143, 155, -121, 424, -85, 582, +-17, 645, 116, 615, 270, 494, 367, 308, +358, 93, 258, -108, 100, -243, -122, -302, +-359, -327, -541, -349, -607, -347, -522, -284, +-267, -165, 94, -37, 459, 70, 697, 150, +774, 208, 691, 242, 459, 235, 98, 167, +-312, 49, -642, -71, -805, -140, -758, -141, +-544, -93, -240, -25, 95, 56, 403, 153, +599, 238, 635, 247, 506, 149, 270, -31, +-8, -220, -244, -357, -368, -408, -375, -376, +-285, -266, -130, -80, 60, 157, 216, 364, +268, 460, 185, 418, 26, 278, -143, 100, +-259, -65, -291, -188, -225, -253, -92, -255, +88, -187, 283, -60, 414, 73, 429, 139, +319, 116, 129, 49, -80, -20, -251, -89, +-363, -149, -404, -176, -376, -154, -267, -80, +-98, 40, 86, 160, 227, 219, 311, 207, +342, 171, 319, 150, 258, 121, 153, 62, +13, -7, -149, -61, -268, -105, -326, -160, +-328, -229, -294, -301, -215, -340, -91, -301, +68, -169, 219, 14, 316, 192, 331, 335, +282, 437, 201, 482, 103, 440, 12, 291, +-70, 71, -122, -152, -133, -320, -114, -416, +-101, -444, -124, -404, -187, -286, -241, -104, +-245, 104, -193, 278, -89, 360, 58, 335, +240, 254, 405, 159, 512, 49, 496, -80, +345, -183, 99, -229, -171, -228, -402, -205, +-542, -165, -563, -111, -453, -37, -231, 78, +62, 236, 354, 378, 544, 424, 578, 358, +455, 220, 245, 38, 3, -184, -239, -400, +-452, -528, -573, -526, -546, -401, -380, -189, +-144, 43, 92, 227, 288, 338, 435, 387, +523, 385, 518, 323, 426, 205, 246, 67, +19, -43, -210, -114, -390, -171, -512, -228, +-581, -275, -581, -291, -456, -258, -216, -188, +62, -93, 309, 16, 520, 145, 687, 290, +747, 421, 668, 474, 446, 404, 138, 228, +-197, 7, -496, -214, -702, -406, -780, -531, +-729, -554, -561, -457, -293, -260, 37, -22, +344, 189, 535, 331, 597, 411, 561, 454, +486, 450, 359, 381, 176, 253, -21, 86, +-165, -98, -258, -270, -320, -402, -359, -490, +-376, -515, -374, -445, -318, -279, -192, -67, +-33, 135, 134, 292, 283, 401, 409, 453, +484, 440, 478, 352, 367, 191, 179, -13, +-32, -194, -212, -299, -341, -337, -425, -326, +-449, -255, -387, -129, -252, 7, -93, 107, +72, 150, 205, 143, 299, 119, 355, 113, +388, 132, 359, 147, 244, 121, 73, 39, +-96, -72, -241, -188, -350, -291, -398, -353, +-373, -337, -276, -223, -131, -24, 39, 197, +182, 366, 264, 445, 283, 432, 285, 346, +271, 212, 227, 46, 160, -138, 80, -312, +-17, -425, -133, -448, -261, -393, -390, -287, +-477, -130, -487, 73, -385, 273, -170, 394, +123, 405, 402, 325, 602, 184, 676, 23, +622, -100, 438, -163, 129, -178, -235, -160, +-529, -99, -668, -13, -663, 47, -531, 46, +-294, 15, 1, -10, 261, -25, 445, -44, +534, -56, 519, -49, 393, -21, 200, 27, +7, 90, -154, 134, -274, 122, -353, 58, +-354, -16, -283, -73, -177, -107, -80, -115, +6, -73, 73, 24, 133, 128, 154, 181, +143, 160, 131, 64, 140, -79, 147, -209, +134, -269, 113, -256, 58, -183, -48, -55, +-181, 116, -272, 273, -291, 354, -252, 335, +-179, 238, -46, 88, 125, -89, 278, -248, +353, -347, 328, -369, 224, -297, 65, -118, +-101, 115, -227, 302, -271, 384, -247, 357, +-174, 234, -80, 33, 22, -190, 92, -373, +100, -458, 49, -416, -13, -263, -51, -43, +-47, 179, 10, 360, 114, 480, 245, 528, +338, 488, 342, 347, 253, 111, 84, -177, +-158, -443, -407, -619, -591, -678, -655, -607, +-579, -396, -362, -75, -40, 266, 302, 524, +579, 631, 717, 572, 702, 384, 538, 137, +270, -93, -30, -260, -278, -343, -441, -329, +-489, -227, -435, -86, -304, 41, -143, 121, +7, 153, 96, 148, 110, 120, 96, 71, +87, 1, 85, -79, 83, -141, 100, -165, +122, -153, 133, -123, 120, -80, 85, -21, +20, 57, -61, 137, -132, 202, -166, 234, +-172, 224, -174, 175, -151, 88, -96, -39, +-13, -178, 77, -278, 165, -299, 223, -232, +251, -89, 238, 85, 162, 218, 14, 264, +-164, 227, -324, 118, -410, -43, -390, -206, +-271, -302, -77, -287, 135, -178, 323, -23, +448, 135, 486, 253, 398, 302, 200, 287, +-38, 225, -234, 119, -362, -14, -419, -144, +-404, -232, -320, -262, -173, -242, 6, -184, +175, -85, 284, 36, 339, 145, 345, 202, +305, 197, 207, 131, 60, 19, -107, -92, +-250, -161, -338, -175, -343, -142, -287, -65, +-199, 56, -77, 184, 80, 266, 225, 279, +283, 229, 253, 120, 168, -36, 82, -202, +24, -327, -8, -383, -29, -353, -36, -227, +-35, -23, -37, 181, -62, 315, -130, 359, +-218, 320, -276, 201, -245, 31, -124, -127, +67, -221, 250, -239, 376, -190, 436, -96, +423, 5, 295, 82, 62, 128, -199, 149, +-396, 146, -495, 112, -490, 48, -382, -40, +-202, -128, 19, -195, 233, -226, 396, -210, +461, -138, 403, -26, 259, 98, 92, 193, +-59, 241, -181, 233, -270, 178, -306, 106, +-263, 52, -142, 21, 7, -12, 105, -49, +141, -84, 133, -131, 115, -201, 80, -268, +28, -298, -36, -279, -90, -196, -108, -50, +-72, 134, -15, 312, 14, 454, 13, 536, +20, 533, 52, 418, 75, 202, 75, -70, +50, -345, 15, -573, -17, -687, -34, -658, +-54, -495, -89, -235, -100, 74, -54, 356, +31, 538, 108, 580, 152, 496, 143, 329, +84, 130, -13, -58, -118, -200, -218, -276, +-281, -289, -256, -246, -108, -173, 113, -95, +315, -19, 421, 50, 403, 102, 284, 128, +100, 129, -116, 99, -340, 42, -494, -19, +-497, -63, -336, -83, -89, -79, 153, -60, +330, -19, 414, 35, 405, 83, 308, 97, +135, 79, -84, 38, -283, -4, -391, -38, +-363, -52, -245, -37, -92, 4, 61, 52, +214, 90, 340, 90, 398, 29, 335, -94, +170, -225, -20, -307, -175, -306, -286, -212, +-350, -28, -344, 204, -270, 412, -136, 528, +33, 510, 191, 352, 276, 86, 273, -215, +218, -453, 161, -565, 96, -543, 3, -405, +-87, -179, -136, 78, -123, 304, -77, 448, +-34, 491, -28, 434, -40, 301, -35, 121, +-4, -71, 16, -254, 19, -399, 1, -469, +-10, -446, 1, -340, 25, -179, 30, 9, +0, 200, -20, 361, 13, 467, 75, 493, +98, 431, 66, 295, 14, 110, -17, -92, +-43, -274, -66, -411, -93, -482, -111, -471, +-88, -365, -17, -190, 67, -3, 105, 152, +82, 257, 29, 295, -9, 271, -28, 202, +-46, 117, -78, 43, -83, 2, -35, 8, +59, 60, 131, 111, 140, 123, 101, 92, +46, 23, -10, -90, -68, -240, -120, -388, +-161, -480, -165, -476, -105, -359, 2, -144, +93, 121, 133, 373, 122, 563, 92, 648, +53, 598, -9, 409, -100, 135, -186, -147, +-205, -359, -139, -462, -29, -455, 74, -362, +151, -224, 205, -74, 247, 55, 249, 137, +194, 170, 56, 165, -111, 145, -233, 127, +-279, 105, -288, 49, -283, -39, -251, -130, +-168, -187, -38, -194, 96, -142, 183, -37, +216, 100, 237, 234, 259, 328, 269, 338, +235, 237, 143, 48, 16, -158, -97, -316, +-181, -390, -252, -370, -313, -267, -348, -108, +-321, 69, -219, 208, -75, 257, 41, 207, +121, 96, 203, -13, 300, -70, 365, -59, +359, 14, 276, 125, 144, 232, -3, 283, +-148, 244, -284, 96, -400, -136, -467, -376, +-428, -532, -262, -562, -26, -469, 200, -273, +372, -4, 476, 284, 513, 521, 451, 651, +259, 645, -40, 505, -342, 269, -556, -7, +-637, -277, -593, -506, -442, -650, -200, -665, +118, -532, 452, -282, 709, 16, 803, 294, +713, 506, 482, 613, 178, 596, -158, 448, +-496, 207, -761, -62, -880, -290, -806, -426, +-554, -454, -198, -390, 165, -268, 475, -119, +706, 31, 814, 146, 758, 190, 539, 155, +219, 89, -117, 43, -380, 36, -536, 65, +-584, 128, -547, 205, -412, 258, -193, 246, +61, 159, 254, -5, 352, -223, 367, -426, +322, -541, 234, -540, 123, -437, -9, -263, +-137, -42, -209, 189, -192, 390, -117, 527, +-39, 587, 22, 568, 65, 488, 103, 344, +126, 137, 114, -130, 52, -423, -34, -677, +-101, -813, -115, -790, -93, -612, -80, -304, +-66, 88, -27, 479, 48, 771, 116, 886, +157, 800, 145, 540, 107, 177, 68, -195, +53, -493, 35, -669, 1, -698, -42, -578, +-63, -339, -69, -54, -75, 194, -94, 353, +-121, 418, -123, 404, -72, 337, 30, 242, +127, 138, 192, 36, 232, -53, 251, -130, +221, -206, 132, -292, -5, -369, -156, -397, +-269, -340, -303, -201, -261, -10, -186, 186, +-87, 347, 32, 443, 172, 454, 293, 369, +356, 220, 327, 58, 236, -75, 119, -155, +6, -183, -123, -187, -262, -193, -375, -207, +-397, -220, -322, -221, -180, -213, -4, -190, +172, -117, 329, 17, 450, 191, 498, 360, +425, 481, 246, 518, 9, 462, -220, 318, +-392, 100, -485, -169, -489, -429, -404, -604, +-232, -632, 6, -514, 247, -289, 403, -16, +447, 243, 405, 434, 313, 518, 160, 469, +-29, 298, -205, 57, -310, -170, -335, -323, +-270, -375, -144, -329, -1, -200, 108, -14, +173, 192, 200, 351, 181, 405, 94, 330, +-26, 160, -116, -44, -137, -231, -100, -361, +-48, -401, -12, -342, 9, -209, 20, -43, +13, 106, -21, 197, -67, 223, -89, 215, +-57, 221, 23, 243, 126, 246, 199, 199, +206, 102, 151, -44, 65, -224, -36, -404, +-155, -520, -271, -521, -323, -380, -289, -117, +-184, 189, -51, 441, 71, 573, 149, 567, +193, 441, 212, 231, 197, -13, 131, -240, +47, -393, -27, -441, -68, -398, -88, -298, +-108, -172, -135, -40, -151, 91, -144, 209, +-111, 292, -68, 320, -28, 291, 12, 224, +58, 155, 97, 82, 109, -11, 87, -117, +32, -207, -33, -275, -71, -322, -69, -343, +-49, -322, -27, -250, 5, -113, 46, 78, +81, 285, 74, 447, 11, 530, -86, 526, +-163, 435, -195, 260, -172, 21, -118, -233, +-35, -444, 65, -564, 171, -574, 220, -491, +190, -341, 83, -148, -59, 65, -197, 260, +-271, 398, -258, 454, -172, 442, -41, 381, +116, 290, 262, 171, 328, 17, 281, -160, +135, -316, -50, -414, -216, -436, -313, -383, +-329, -256, -267, -75, -145, 116, 16, 269, +156, 339, 218, 302, 192, 177, 101, 24, +-4, -97, -88, -153, -115, -143, -95, -76, +-36, 32, 38, 145, 126, 218, 175, 224, +157, 164, 55, 52, -78, -80, -195, -205, +-264, -304, -280, -368, -238, -368, -145, -282, +-15, -110, 133, 104, 250, 307, 295, 445, +267, 490, 203, 431, 116, 281, 30, 67, +-50, -154, -111, -317, -145, -380, -143, -343, +-123, -237, -110, -111, -115, 2, -135, 84, +-139, 133, -113, 144, -46, 112, 45, 53, +155, 1, 256, -23, 349, -22, 387, -6, +345, 23, 206, 55, 27, 86, -159, 102, +-309, 77, -401, -2, -410, -109, -335, -200, +-189, -230, -11, -190, 155, -96, 273, 27, +320, 157, 312, 262, 264, 303, 190, 253, +89, 127, -10, -35, -95, -182, -151, -280, +-180, -311, -184, -278, -164, -193, -117, -63, +-36, 95, 63, 236, 164, 310, 229, 301, +244, 234, 208, 127, 147, 1, 51, -118, +-56, -207, -155, -244, -197, -215, -180, -136, +-104, -42, -7, 28, 93, 68, 160, 91, +185, 106, 167, 102, 115, 74, 35, 26, +-47, -21, -87, -53, -73, -67, -20, -68, +38, -58, 83, -28, 100, 25, 77, 81, +10, 109, -76, 90, -149, 44, -175, -5, +-139, -36, -33, -57, 123, -76, 272, -89, +371, -87, 385, -68, 313, -37, 156, -2, +-51, 40, -266, 92, -418, 142, -468, 170, +-403, 152, -267, 69, -81, -57, 113, -173, +294, -238, 412, -232, 454, -161, 419, -42, +331, 112, 198, 259, 44, 343, -117, 324, +-268, 199, -381, 9, -432, -185, -410, -334, +-318, -406, -156, -397, 42, -295, 232, -106, +376, 128, 459, 328, 454, 435, 353, 430, +187, 335, 10, 183, -140, 9, -254, -151, +-322, -257, -335, -290, -287, -253, -214, -178, +-129, -104, -47, -60, 50, -38, 145, -8, +232, 49, 284, 117, 304, 175, 271, 201, +183, 189, 50, 135, -84, 43, -201, -62, +-284, -144, -317, -165, -280, -107, -190, 1, +-86, 98, 5, 129, 70, 86, 117, -7, +145, -117, 163, -213, 174, -264, 176, -236, +151, -119, 96, 45, 6, 200, -119, 295, +-252, 311, -351, 260, -375, 175, -315, 76, +-167, -26, 30, -118, 230, -184, 365, -215, +409, -214, 335, -200, 173, -180, -53, -141, +-264, -63, -405, 44, -426, 154, -348, 236, +-195, 278, -13, 270, 161, 216, 276, 123, +296, 3, 229, -120, 114, -213, -8, -241, +-117, -201, -187, -127, -205, -52, -179, 5, +-135, 41, -75, 58, -24, 56, 6, 35, +14, 16, 7, 20, -3, 47, -15, 72, +-28, 74, -37, 44, -30, -3, -19, -40, +9, -48, 45, -32, 86, 0, 95, 38, +95, 70, 72, 79, 24, 53, -66, -13, +-173, -98, -269, -172, -311, -209, -299, -205, +-233, -167, -123, -104, 14, -20, 158, 85, +269, 204, 322, 307, 303, 365, 226, 369, +106, 319, -6, 203, -95, 35, -161, -161, +-213, -347, -235, -478, -235, -524, -224, -482, +-211, -366, -193, -204, -144, -12, -54, 194, +84, 387, 231, 530, 365, 592, 435, 560, +430, 444, 326, 247, 150, -12, -89, -289, +-322, -524, -487, -658, -529, -651, -463, -508, +-309, -269, -120, 6, 64, 253, 206, 426, +280, 500, 286, 458, 240, 323, 173, 150, +121, -4, 116, -115, 129, -174, 122, -189, +63, -177, -28, -157, -145, -138, -270, -119, +-376, -105, -418, -87, -358, -47, -204, 33, +19, 145, 250, 245, 435, 294, 515, 274, +487, 196, 356, 77, 160, -64, -82, -201, +-296, -290, -434, -302, -444, -244, -348, -145, +-177, -41, 22, 43, 217, 107, 356, 153, +415, 183, 372, 196, 230, 187, 28, 148, +-167, 80, -297, -16, -334, -134, -269, -244, +-130, -299, 58, -273, 255, -157, 400, 20, +423, 195, 313, 306, 107, 321, -121, 240, +-310, 87, -414, -102, -398, -263, -267, -338, +-40, -303, 217, -174, 435, 0, 530, 154, +486, 249, 315, 271, 86, 232, -157, 141, +-346, 22, -447, -86, -430, -145, -307, -152, +-98, -124, 128, -80, 315, -37, 413, -5, +423, 16, 370, 26, 267, 26, 117, 11, +-56, -6, -194, -12, -267, -4, -277, 8, +-259, 16, -216, 21, -144, 35, -38, 60, +80, 83, 194, 83, 280, 58, 332, 12, +352, -46, 334, -100, 268, -130, 135, -126, +-45, -79, -238, 1, -378, 85, -442, 129, +-413, 108, -321, 23, -161, -90, 46, -191, +273, -234, 441, -197, 514, -77, 473, 106, +362, 297, 212, 430, 42, 456, -139, 354, +-287, 158, -367, -76, -373, -290, -320, -443, +-237, -506, -137, -475, -38, -358, 71, -186, +184, 3, 289, 176, 338, 318, 324, 417, +271, 464, 202, 442, 110, 346, -21, 185, +-167, -10, -281, -204, -312, -357, -278, -442, +-209, -442, -141, -359, -57, -208, 32, -29, +120, 134, 165, 244, 171, 286, 138, 260, +114, 185, 96, 92, 84, 14, 47, -36, +-11, -44, -71, -12, -114, 33, -137, 52, +-162, 25, -185, -47, -190, -142, -142, -229, +-46, -276, 68, -252, 147, -150, 191, 11, +208, 191, 204, 330, 150, 387, 33, 349, +-118, 230, -240, 61, -284, -111, -258, -251, +-177, -330, -76, -335, 31, -267, 118, -149, +187, -18, 187, 104, 114, 205, -17, 269, +-124, 287, -185, 246, -183, 149, -155, 11, +-107, -135, -41, -255, 46, -321, 121, -315, +146, -231, 110, -89, 47, 83, -8, 246, +-47, 353, -71, 368, -102, 302, -135, 174, +-150, 11, -123, -157, -86, -295, -67, -373, +-67, -369, -49, -292, 6, -162, 75, -12, +127, 133, 137, 251, 120, 325, 87, 343, +50, 300, -16, 200, -98, 65, -196, -75, +-253, -191, -252, -277, -192, -314, -122, -286, +-52, -189, 19, -55, 111, 79, 188, 175, +220, 209, 191, 178, 121, 108, 45, 23, +-23, -44, -84, -70, -154, -43, -218, 24, +-251, 88, -221, 109, -148, 72, -75, -12, +-23, -109, 37, -182, 119, -202, 194, -168, +219, -87, 179, 20, 99, 123, 10, 187, +-63, 200, -127, 170, -177, 124, -212, 81, +-187, 41, -100, -8, 17, -70, 95, -144, +120, -218, 96, -271, 70, -286, 36, -249, +-12, -136, -84, 42, -131, 247, -119, 422, +-41, 516, 55, 492, 127, 355, 160, 130, +165, -143, 150, -406, 95, -595, -8, -655, +-141, -552, -247, -311, -281, 1, -229, 311, +-135, 549, -30, 659, 79, 608, 185, 409, +273, 111, 300, -205, 250, -451, 132, -570, +11, -541, -72, -397, -103, -185, -131, 48, +-151, 257, -144, 394, -78, 438, -1, 390, +60, 278, 73, 140, 66, 0, 65, -137, +84, -251, 84, -326, 59, -347, 13, -312, +-21, -225, -26, -112, -8, 8, 13, 126, +17, 233, 23, 303, 52, 318, 103, 272, +124, 188, 88, 91, 13, -6, -39, -99, +-61, -173, -67, -220, -72, -229, -66, -201, +-17, -151, 64, -92, 143, -27, 159, 38, +128, 99, 67, 142, 22, 154, -7, 124, +-21, 74, -40, 25, -40, -12, -11, -35, +61, -40, 122, -26, 137, 4, 92, 35, +33, 47, -19, 29, -65, -8, -117, -45, +-167, -55, -176, -48, -102, -40, 46, -39, +199, -50, 314, -73, 366, -92, 369, -96, +310, -67, 171, 6, -46, 114, -277, 226, +-446, 302, -511, 301, -457, 206, -319, 43, +-120, -133, 107, -272, 346, -338, 536, -321, +626, -225, 562, -81, 390, 60, 163, 151, +-52, 180, -255, 161, -419, 125, -520, 92, +-500, 76, -364, 64, -155, 41, 43, 0, +193, -52, 289, -115, 339, -176, 336, -218, +269, -208, 154, -136, 27, -18, -51, 115, +-72, 225, -57, 288, -51, 297, -65, 248, +-86, 152, -106, 17, -127, -137, -160, -273, +-190, -358, -177, -376, -81, -329, 64, -224, +209, -70, 291, 117, 319, 293, 297, 411, +231, 444, 110, 385, -39, 252, -196, 75, +-302, -110, -336, -268, -299, -369, -243, -393, +-175, -329, -91, -202, 27, -57, 157, 67, +259, 160, 298, 218, 275, 233, 217, 202, +129, 144, 9, 75, -142, 12, -280, -38, +-349, -78, -323, -118, -224, -150, -98, -159, +29, -134, 132, -77, 210, -1, 241, 77, +207, 150, 102, 206, -25, 224, -131, 188, +-192, 102, -230, -19, -233, -153, -205, -267, +-132, -330, -31, -340, 93, -284, 180, -156, +219, 31, 217, 234, 189, 401, 119, 485, +13, 468, -112, 353, -221, 162, -290, -66, +-302, -280, -255, -430, -183, -474, -109, -411, +-36, -270, 40, -105, 107, 42, 142, 145, +149, 200, 151, 203, 167, 172, 177, 130, +162, 104, 101, 104, 4, 124, -117, 140, +-236, 129, -344, 77, -406, -9, -412, -117, +-344, -232, -214, -332, -27, -385, 155, -363, +294, -250, 363, -72, 387, 121, 354, 289, +267, 406, 123, 449, -33, 405, -178, 280, +-287, 110, -346, -64, -355, -202, -323, -288, +-258, -314, -155, -297, -27, -253, 91, -180, +164, -82, 197, 17, 220, 104, 234, 173, +226, 223, 183, 245, 113, 232, 21, 176, +-76, 85, -177, -23, -264, -113, -328, -164, +-340, -178, -285, -166, -149, -128, 21, -66, +181, 2, 276, 54, 325, 82, 306, 83, +229, 65, 88, 39, -59, 13, -169, -12, +-208, -29, -183, -31, -117, -12, -48, 15, +7, 30, 44, 24, 59, 6, 49, -20, +19, -38, -5, -34, -3, -8, 28, 40, +67, 100, 82, 147, 60, 150, 3, 88, +-53, -28, -90, -171, -100, -297, -84, -364, +-25, -344, 71, -232, 172, -34, 223, 203, +208, 420, 118, 552, 8, 556, -103, 425, +-177, 197, -213, -82, -180, -347, -95, -530, +25, -591, 135, -524, 217, -345, 237, -97, +190, 158, 104, 351, 19, 449, -52, 439, +-104, 334, -122, 162, -97, -31, -32, -195, +50, -284, 103, -283, 115, -202, 85, -76, +36, 66, -19, 178, -62, 221, -86, 183, +-76, 85, -20, -45, 80, -165, 185, -233, +256, -221, 258, -139, 209, -18, 110, 103, +-3, 189, -140, 213, -254, 177, -323, 94, +-304, -1, -213, -83, -66, -125, 91, -119, +225, -81, 316, -38, 356, 1, 337, 26, +260, 34, 140, 30, 16, 27, -75, 28, +-126, 32, -156, 29, -168, 19, -174, -5, +-160, -38, -127, -70, -74, -85, -16, -76, +38, -36, 98, 14, 166, 56, 218, 83, +233, 86, 201, 60, 146, 17, 84, -25, +46, -42, 4, -24, -39, 18, -95, 63, +-128, 88, -151, 76, -160, 25, -172, -57, +-156, -150, -111, -227, -19, -247, 100, -197, +206, -90, 265, 45, 271, 181, 238, 278, +170, 312, 61, 276, -60, 181, -165, 56, +-213, -68, -202, -163, -144, -212, -70, -209, +-10, -164, 28, -96, 47, -29, 49, 21, +32, 52, 0, 56, -15, 34, -5, -2, +43, -30, 92, -41, 121, -26, 101, 6, +58, 59, -10, 125, -72, 182, -141, 204, +-185, 178, -198, 98, -155, -18, -69, -148, +29, -260, 111, -329, 159, -327, 174, -245, +168, -105, 127, 62, 46, 215, -69, 306, +-162, 312, -216, 240, -214, 116, -173, -26, +-117, -147, -47, -215, 39, -206, 124, -130, +166, -15, 140, 97, 71, 173, 1, 194, +-42, 160, -73, 82, -102, -19, -135, -131, +-132, -218, -107, -256, -58, -236, -34, -174, +-7, -80, 27, 34, 84, 152, 130, 251, +142, 307, 106, 303, 18, 237, -97, 122, +-197, -15, -268, -142, -290, -231, -267, -270, +-165, -255, -4, -192, 176, -95, 306, -2, +348, 60, 287, 87, 153, 95, -10, 95, +-176, 95, -322, 93, -400, 91, -374, 88, +-244, 76, -59, 48, 110, 6, 206, -52, +235, -104, 200, -129, 136, -127, 21, -114, +-106, -90, -222, -60, -252, -30, -191, 1, +-78, 44, 27, 98, 108, 150, 171, 194, +218, 220, 210, 195, 124, 106, -46, -37, +-222, -196, -343, -325, -383, -380, -367, -337, +-299, -199, -165, -5, 49, 206, 279, 377, +451, 454, 504, 401, 439, 247, 301, 39, +121, -162, -81, -313, -298, -382, -475, -361, +-547, -260, -502, -109, -343, 56, -149, 186, +55, 253, 226, 255, 374, 212, 452, 132, +428, 31, 290, -70, 91, -148, -98, -181, +-223, -148, -284, -66, -281, 35, -230, 119, +-121, 170, 18, 174, 141, 112, 182, -15, +148, -166, 58, -289, -30, -336, -100, -290, +-125, -157, -113, 27, -61, 219, 35, 369, +159, 440, 267, 410, 288, 288, 208, 100, +68, -102, -82, -268, -193, -365, -283, -387, +-322, -347, -290, -258, -149, -126, 46, 19, +234, 141, 348, 223, 376, 269, 328, 280, +226, 256, 79, 191, -86, 88, -247, -34, +-342, -141, -331, -209, -213, -231, -55, -207, +103, -135, 229, -38, 331, 55, 356, 116, +295, 131, 142, 92, -38, 12, -189, -70, +-279, -106, -280, -89, -213, -29, -101, 57, +32, 141, 170, 190, 289, 181, 331, 103, +301, -24, 199, -153, 92, -230, -9, -232, +-95, -158, -174, -37, -222, 99, -224, 199, +-170, 228, -88, 174, 6, 58, 75, -86, +119, -209, 158, -271, 203, -249, 226, -157, +214, -19, 165, 129, 139, 252, 112, 326, +79, 347, 6, 304, -83, 201, -173, 56, +-246, -101, -273, -259, -266, -404, -223, -507, +-147, -530, -19, -450, 154, -265, 314, 1, +431, 298, 469, 563, 444, 737, 356, 768, +212, 642, 6, 373, -219, 16, -414, -349, +-515, -643, -514, -798, -410, -783, -238, -619, +-25, -353, 210, -34, 429, 286, 568, 539, +581, 669, 450, 667, 249, 551, 4, 346, +-219, 86, -416, -183, -519, -412, -502, -560, +-359, -594, -127, -505, 118, -314, 314, -73, +418, 173, 431, 376, 370, 495, 244, 512, +80, 434, -90, 271, -215, 65, -278, -133, +-281, -287, -259, -389, -221, -440, -185, -427, +-114, -348, -12, -210, 117, -33, 224, 156, +293, 327, 336, 455, 353, 522, 318, 496, +202, 362, 3, 145, -192, -95, -346, -309, +-419, -454, -457, -504, -430, -458, -329, -343, +-149, -186, 69, -15, 260, 136, 378, 232, +416, 275, 395, 291, 333, 296, 213, 285, +31, 248, -169, 170, -322, 47, -401, -100, +-413, -242, -376, -364, -269, -437, -116, -421, +82, -293, 253, -77, 361, 159, 375, 351, +298, 456, 152, 451, -31, 338, -206, 145, +-346, -83, -425, -292, -394, -422, -275, -440, +-84, -353, 90, -190, 229, 13, 303, 207, +319, 356, 269, 443, 165, 453, 21, 366, +-129, 196, -256, -13, -311, -216, -299, -389, +-260, -508, -211, -544, -140, -478, -37, -317, +72, -89, 139, 159, 177, 376, 182, 527, +197, 598, 179, 569, 131, 433, 36, 214, +-87, -40, -206, -278, -301, -458, -348, -553, +-340, -546, -280, -448, -152, -280, 16, -73, +199, 137, 308, 303, 340, 393, 295, 403, +210, 351, 85, 256, -56, 143, -200, 22, +-300, -96, -345, -193, -320, -249, -252, -269, +-179, -264, -100, -229, -7, -152, 114, -47, +236, 64, 310, 168, 346, 250, 334, 292, +301, 288, 188, 237, 5, 145, -228, 20, +-446, -116, -598, -246, -662, -344, -606, -389, +-419, -359, -128, -262, 220, -112, 536, 74, +759, 269, 820, 418, 716, 483, 456, 455, +108, 345, -270, 170, -581, -32, -776, -218, +-792, -357, -663, -430, -411, -430, -90, -367, +233, -259, 492, -123, 622, 34, 620, 191, +500, 324, 294, 419, 50, 455, -203, 404, +-376, 257, -460, 46, -432, -182, -331, -382, +-181, -503, -10, -502, 151, -366, 274, -127, +332, 152, 317, 392, 259, 521, 172, 505, +74, 362, -36, 124, -128, -154, -188, -394, +-205, -529, -206, -536, -177, -426, -144, -231, +-83, 10, -28, 230, 41, 395, 107, 498, +173, 532, 250, 479, 313, 350, 352, 168, +343, -38, 274, -246, 146, -431, -47, -572, +-245, -644, -437, -613, -560, -462, -598, -220, +-520, 67, -328, 355, -43, 608, 285, 774, +591, 811, 802, 698, 881, 447, 797, 100, +562, -272, 205, -601, -205, -822, -582, -898, +-836, -802, -927, -542, -819, -164, -560, 249, +-170, 614, 235, 843, 594, 891, 826, 762, +898, 487, 811, 107, 571, -304, 239, -642, +-116, -821, -423, -821, -630, -658, -728, -374, +-673, -24, -485, 323, -193, 603, 115, 758, +393, 757, 594, 611, 696, 368, 668, 73, +517, -233, 258, -503, -38, -689, -307, -770, +-492, -718, -576, -529, -563, -233, -443, 111, +-217, 441, 65, 709, 343, 865, 518, 849, +606, 645, 574, 297, 450, -110, 227, -486, +-41, -747, -291, -851, -460, -784, -514, -552, +-463, -200, -321, 169, -111, 464, 105, 628, +300, 651, 422, 544, 461, 347, 397, 110, +257, -119, 80, -309, -84, -422, -223, -446, +-294, -394, -309, -288, -260, -140, -169, 28, +-49, 201, 77, 350, 156, 441, 186, 439, +186, 334, 177, 153, 166, -58, 97, -273, +13, -451, -73, -535, -104, -479, -120, -301, +-134, -50, -138, 210, -109, 426, -44, 546, +19, 541, 49, 408, 53, 176, 44, -98, +50, -336, 66, -488, 85, -527, 89, -447, +84, -268, 70, -47, 47, 160, -32, 322, +-138, 422, -248, 429, -297, 343, -284, 202, +-212, 54, -78, -85, 86, -202, 248, -286, +358, -325, 389, -319, 336, -268, 186, -192, +-7, -96, -222, 22, -375, 156, -454, 289, +-437, 396, -343, 459, -180, 459, 17, 365, +208, 179, 336, -65, 382, -327, 332, -570, +214, -737, 60, -768, -92, -633, -225, -352, +-312, 28, -330, 434, -257, 783, -141, 1001, +-9, 1038, 84, 859, 156, 488, 165, 1, +108, -508, 12, -949, -103, -1229, -190, -1283, +-217, -1083, -160, -661, -33, -80, 98, 557, +217, 1119, 277, 1477, 272, 1549, 162, 1305, +-20, 780, -228, 69, -397, -676, -492, -1306, +-469, -1679, -344, -1696, -136, -1346, 96, -717, +313, 49, 468, 791, 526, 1364, 465, 1644, +286, 1580, 28, 1199, -229, 596, -458, -97, +-601, -734, -646, -1202, -533, -1426, -307, -1378, +-16, -1074, 279, -580, 517, 5, 659, 573, +651, 1029, 499, 1280, 250, 1286, -61, 1064, +-365, 648, -611, 91, -735, -497, -732, -990, +-591, -1286, -354, -1336, -53, -1134, 252, -716, +535, -149, 723, 466, 797, 1010, 724, 1364, +521, 1454, 221, 1269, -124, 848, -466, 259, +-765, -400, -957, -1008, -966, -1444, -792, -1627, +-453, -1505, -47, -1087, 390, -447, 769, 289, +1018, 993, 1072, 1548, 913, 1837, 580, 1773, +136, 1352, -325, 653, -703, -184, -947, -1000, +-1024, -1638, -936, -1981, -677, -1952, -298, -1541, +128, -811, 511, 87, 810, 965, 973, 1661, +993, 2051, 832, 2052, 526, 1656, 102, 929, +-356, 12, -756, -920, -1016, -1677, -1079, -2103, +-956, -2113, -661, -1706, -215, -957, 297, -19, +779, 922, 1082, 1673, 1177, 2083, 1058, 2060, +768, 1621, 330, 883, -189, 5, -674, -856, +-1017, -1536, -1163, -1890, -1091, -1860, -825, -1490, +-412, -872, 67, -130, 548, 607, 944, 1217, +1167, 1599, 1167, 1696, 968, 1497, 605, 1047, +154, 429, -350, -263, -784, -925, -1081, -1437, +-1168, -1705, -1032, -1679, -703, -1344, -229, -737, +291, 37, 754, 824, 1083, 1473, 1210, 1857, +1124, 1891, 813, 1542, 351, 873, -183, 9, +-659, -874, -1001, -1584, -1154, -1978, -1095, -1989, +-819, -1608, -374, -897, 171, 5, 686, 900, +1061, 1614, 1223, 2013, 1164, 2021, 900, 1630, +451, 923, -110, 37, -641, -856, -1028, -1585, +-1184, -2002, -1126, -2032, -847, -1675, -410, -998, +117, -130, 630, 755, 1019, 1489, 1208, 1943, +1158, 2037, 898, 1738, 494, 1104, 2, 264, +-490, -623, -900, -1398, -1116, -1911, -1109, -2050, +-890, -1781, -525, -1158, -67, -308, 402, 599, +809, 1382, 1051, 1881, 1106, 1993, 950, 1694, +626, 1055, 201, 219, -247, -633, -634, -1347, +-898, -1780, -997, -1832, -907, -1504, -653, -896, +-273, -140, 121, 625, 491, 1257, 759, 1628, +907, 1670, 895, 1388, 725, 846, 432, 145, +71, -574, -294, -1187, -598, -1572, -807, -1648, +-874, -1394, -786, -860, -547, -139, -208, 633, +174, 1286, 511, 1665, 739, 1691, 817, 1366, +767, 750, 567, -41, 260, -830, -98, -1432, +-404, -1705, -601, -1602, -684, -1161, -642, -483, +-489, 290, -246, 995, 30, 1481, 273, 1636, +459, 1438, 527, 949, 481, 271, 334, -469, +146, -1114, -54, -1526, -236, -1620, -360, -1373, +-390, -819, -327, -71, -200, 702, -62, 1328, +62, 1669, 151, 1653, 205, 1275, 212, 614, +173, -184, 99, -944, 29, -1487, -24, -1688, +-43, -1518, -67, -1045, -89, -376, -131, 361, +-173, 1003, -205, 1400, -221, 1480, -209, 1261, +-157, 819, -43, 242, 127, -348, 299, -844, +442, -1153, 497, -1221, 446, -1041, 276, -671, +36, -191, -242, 316, -515, 745, -719, 999, +-778, 1034, -683, 853, -450, 486, -137, 3, +215, -473, 541, -815, 783, -944, 892, -852, +837, -564, 613, -135, 266, 330, -144, 708, +-526, 908, -841, 881, -1010, 639, -1018, 246, +-836, -205, -496, -623, -65, -916, 372, -1003, +727, -859, 960, -521, 1046, -56, 947, 449, +675, 881, 262, 1133, -194, 1155, -626, 931, +-953, 486, -1126, -102, -1104, -699, -895, -1164, +-514, -1391, -30, -1330, 480, -982, 890, -405, +1134, 292, 1173, 958, 1003, 1445, 631, 1634, +114, 1474, -443, 991, -918, 283, -1229, -516, +-1290, -1237, -1100, -1719, -680, -1838, -135, -1561, +448, -947, 953, -117, 1262, 763, 1295, 1505, +1047, 1942, 587, 1973, 17, 1591, -563, 871, +-1027, -46, -1288, -977, -1277, -1711, -1008, -2086, +-531, -2031, 51, -1571, 619, -784, 1052, 183, +1280, 1121, 1248, 1824, 980, 2150, 501, 2049, +-84, 1543, -655, 725, -1087, -246, -1300, -1177, +-1266, -1880, -995, -2212, -536, -2108, 33, -1589, +619, -740, 1072, 288, 1323, 1280, 1317, 2023, +1064, 2369, 588, 2243, -7, 1651, -605, 689, +-1108, -439, -1408, -1488, -1401, -2236, -1084, -2528, +-542, -2292, 91, -1563, 728, -500, 1241, 672, +1494, 1708, 1407, 2379, 1020, 2544, 407, 2181, +-294, 1370, -942, 269, -1364, -884, -1499, -1837, +-1313, -2399, -827, -2470, -122, -2029, 629, -1163, +1221, -55, 1531, 1056, 1507, 1944, 1148, 2423, +540, 2391, -200, 1855, -893, 929, -1406, -199, +-1603, -1281, -1431, -2080, -933, -2427, -241, -2261, +500, -1612, 1153, -622, 1596, 495, 1695, 1487, +1417, 2139, 829, 2326, 72, 2024, -704, 1305, +-1338, 328, -1691, -689, -1681, -1532, -1324, -2035, +-686, -2108, 87, -1754, 852, -1060, 1421, -174, +1696, 718, 1634, 1435, 1273, 1850, 687, 1895, +-23, 1563, -723, 917, -1271, 106, -1571, -692, +-1572, -1332, -1292, -1703, -767, -1726, -106, -1388, +575, -769, 1150, -9, 1519, 730, 1595, 1299, +1367, 1583, 885, 1525, 270, 1141, -376, 529, +-941, -166, -1336, -796, -1468, -1235, -1303, -1395, +-887, -1243, -333, -827, 248, -263, 753, 317, +1107, 804, 1227, 1112, 1121, 1170, 807, 961, +372, 559, -88, 74, -459, -398, -689, -771, +-790, -969, -770, -953, -620, -731, -387, -356, +-133, 74, 84, 452, 271, 715, 425, 825, +541, 748, 585, 499, 547, 157, 437, -191, +281, -481, 80, -661, -142, -681, -369, -541, +-556, -290, -678, 3, -691, 268, -566, 459, +-326, 547, -20, 508, 305, 350, 607, 126, +838, -93, 912, -260, 805, -362, 521, -383, +135, -309, -287, -160, -666, 3, -935, 116, +-1033, 161, -941, 154, -672, 104, -280, 23, +181, -49, 619, -67, 975, -11, 1175, 102, +1179, 226, 962, 304, 551, 301, -11, 198, +-624, -13, -1168, -293, -1497, -550, -1555, -704, +-1315, -710, -795, -545, -43, -204, 795, 255, +1504, 715, 1915, 1056, 1940, 1188, 1555, 1066, +818, 687, -144, 99, -1111, -587, -1887, -1205, +-2287, -1595, -2210, -1658, -1649, -1366, -726, -747, +352, 94, 1357, 982, 2113, 1716, 2461, 2126, +2307, 2108, 1646, 1642, 649, 791, -457, -292, +-1472, -1374, -2242, -2218, -2602, -2650, -2448, -2562, +-1784, -1922, -752, -820, 456, 516, 1579, 1802, +2389, 2764, 2719, 3190, 2507, 2957, 1777, 2063, +660, 664, -601, -931, -1737, -2353, -2521, -3297, +-2778, -3564, -2453, -3057, -1606, -1845, -445, -209, +798, 1477, 1865, 2862, 2538, 3648, 2671, 3633, +2233, 2803, 1302, 1358, 91, -375, -1144, -2032, +-2120, -3270, -2647, -3805, -2603, -3504, -1987, -2442, +-912, -852, 370, 936, 1561, 2546, 2391, 3630, +2697, 3951, 2401, 3434, 1576, 2166, 385, 394, +-901, -1497, -2009, -3105, -2663, -4090, -2688, -4216, +-2111, -3419, -1095, -1858, 147, 138, 1377, 2160, +2319, 3770, 2705, 4577, 2452, 4376, 1642, 3221, +483, 1358, -777, -840, -1854, -2904, -2511, -4353, +-2587, -4844, -2067, -4272, -1067, -2775, 162, -668, +1354, 1624, 2234, 3596, 2602, 4776, 2357, 4897, +1567, 3964, 409, 2175, -868, -119, -1984, -2438, +-2654, -4240, -2720, -5091, -2151, -4824, -1081, -3522, +264, -1446, 1569, 998, 2549, 3260, 2982, 4785, +2750, 5229, 1892, 4545, 594, 2902, -874, 620, +-2186, -1829, -3043, -3869, -3228, -5013, -2712, -5046, +-1597, -4029, -98, -2185, 1475, 132, 2751, 2414, +3427, 4108, 3341, 4856, 2528, 4584, 1142, 3383, +-519, 1463, -2113, -770, -3266, -2778, -3690, -4113, +-3270, -4528, -2124, -3974, -513, -2574, 1216, -629, +2710, 1423, 3624, 3101, 3765, 4019, 3077, 4009, +1697, 3124, -85, 1573, -1849, -316, -3202, -2096, +-3864, -3320, -3706, -3724, -2737, -3298, -1163, -2171, +671, -560, 2347, 1172, 3515, 2569, 3919, 3307, +3487, 3305, 2313, 2605, 650, 1316, -1140, -294, +-2653, -1795, -3576, -2822, -3728, -3194, -3101, -2867, +-1819, -1895, -168, -477, 1504, 1044, 2843, 2277, +3568, 2936, 3515, 2910, 2696, 2218, 1297, 984, +-347, -499, -1886, -1815, -2974, -2621, -3396, -2768, +-3055, -2254, -2056, -1180, -641, 201, 882, 1506, +2205, 2373, 3015, 2608, 3116, 2194, 2511, 1251, +1412, -8, 67, -1272, -1269, -2192, -2326, -2540, +-2841, -2269, -2704, -1471, -1981, -324, -858, 912, +422, 1928, 1587, 2476, 2395, 2448, 2662, 1879, +2340, 893, 1503, -314, 363, -1471, -809, -2275, +-1746, -2542, -2267, -2255, -2286, -1485, -1816, -368, +-944, 851, 113, 1858, 1107, 2411, 1794, 2412, +2054, 1878, 1843, 918, 1229, -255, 366, -1357, +-530, -2105, -1266, -2330, -1674, -2024, -1671, -1267, +-1271, -209, -595, 898, 195, 1749, 902, 2141, +1359, 2037, 1473, 1501, 1247, 624, 733, -419, +56, -1354, -606, -1922, -1082, -2025, -1296, -1709, +-1203, -1039, -824, -103, -255, 886, 358, 1650, +886, 2013, 1224, 1934, 1267, 1423, 973, 565, +442, -452, -178, -1368, -739, -1932, -1155, -2004, +-1315, -1607, -1158, -852, -695, 120, -57, 1082, +598, 1735, 1129, 1887, 1424, 1581, 1382, 945, +1009, 100, 407, -772, -276, -1417, -916, -1643, +-1378, -1438, -1541, -917, -1362, -228, -905, 488, +-264, 1059, 437, 1323, 1062, 1230, 1457, 854, +1545, 304, 1307, -300, 815, -808, 197, -1076, +-428, -1034, -970, -720, -1325, -242, -1397, 278, +-1188, 725, -793, 978, -272, 938, 287, 611, +766, 112, 1043, -424, 1114, -873, 1012, -1105, +756, -1023, 363, -642, -70, -68, -451, 566, +-729, 1102, -901, 1384, -933, 1315, -803, 905, +-524, 250, -166, -500, 207, -1178, 542, -1616, +802, -1690, 916, -1365, 844, -702, 591, 153, +229, 1002, -177, 1653, -556, 1956, -824, 1831, +-909, 1267, -806, 374, -562, -631, -242, -1514, +122, -2074, 477, -2147, 758, -1687, 888, -816, +858, 249, 669, 1272, 333, 2001, -119, 2222, +-582, 1876, -956, 1076, -1152, 27, -1119, -1019, +-814, -1802, -297, -2125, 320, -1914, 904, -1231, +1319, -257, 1440, 761, 1213, 1589, 677, 2031, +-35, 1951, -761, 1380, -1316, 487, -1596, -515, +-1537, -1421, -1146, -2011, -473, -2097, 323, -1625, +1059, -731, 1580, 335, 1770, 1331, 1555, 2047, +975, 2276, 179, 1898, -648, 1011, -1354, -118, +-1796, -1228, -1873, -2080, -1532, -2437, -846, -2159, +17, -1330, 861, -188, 1548, 1003, 1940, 1979, +1921, 2494, 1456, 2409, 685, 1739, -210, 660, +-1076, -573, -1758, -1692, -2073, -2449, -1933, -2658, +-1375, -2259, -530, -1333, 448, -70, 1336, 1249, +1930, 2310, 2075, 2860, 1763, 2769, 1090, 2043, +217, 814, -697, -658, -1493, -2017, -1982, -2924, +-2001, -3146, -1564, -2630, -813, -1487, 99, 30, +1016, 1556, 1714, 2703, 1992, 3199, 1797, 2947, +1214, 2003, 360, 581, -590, -965, -1416, -2240, +-1869, -2954, -1839, -2962, -1373, -2275, -632, -1062, +232, 389, 1052, 1724, 1616, 2595, 1734, 2811, +1416, 2371, 813, 1385, 81, 55, -682, -1287, +-1299, -2279, -1598, -2699, -1502, -2481, -1066, -1657, +-385, -398, 393, 979, 1071, 2108, 1479, 2712, +1553, 2661, 1287, 1977, 721, 798, -29, -632, +-760, -1953, -1285, -2791, -1499, -2938, -1373, -2390, +-918, -1269, -247, 201, 457, 1671, 1012, 2745, +1325, 3135, 1311, 2768, 958, 1741, 369, 278, +-270, -1282, -801, -2538, -1104, -3155, -1109, -2996, +-803, -2121, -284, -727, 313, 871, 819, 2256, +1099, 3066, 1053, 3117, 717, 2411, 196, 1120, +-381, -451, -873, -1923, -1144, -2931, -1148, -3220, +-887, -2722, -392, -1557, 256, 4, 882, 1576, +1322, 2751, 1481, 3250, 1327, 2993, 858, 2036, +158, 559, -637, -1085, -1336, -2441, -1755, -3170, +-1753, -3158, -1354, -2439, -648, -1125, 241, 510, +1137, 2004, 1796, 2933, 2032, 3154, 1803, 2689, +1177, 1583, 276, 38, -690, -1505, -1487, -2600, +-1936, -3040, -1974, -2795, -1582, -1908, -820, -522, +151, 1025, 1082, 2284, 1750, 2911, 2005, 2831, +1828, 2140, 1261, 953, 410, -528, -538, -1890, +-1347, -2717, -1841, -2860, -1940, -2390, -1619, -1392, +-919, -26, -8, 1356, 911, 2345, 1635, 2741, +2016, 2549, 1939, 1827, 1418, 676, 568, -644, +-417, -1764, -1312, -2421, -1903, -2538, -2068, -2127, +-1770, -1247, -1045, -77, -47, 1089, 942, 1969, +1677, 2377, 2023, 2244, 1923, 1615, 1352, 630, +457, -506, -496, -1514, -1278, -2135, -1799, -2239, +-1946, -1831, -1609, -989, -834, 102, 115, 1141, +970, 1857, 1599, 2122, 1905, 1908, 1758, 1244, +1137, 279, 239, -708, -638, -1476, -1327, -1901, +-1734, -1911, -1761, -1468, -1329, -694, -568, 163, +264, 922, 969, 1501, 1457, 1772, 1622, 1613, +1387, 1089, 801, 405, 76, -302, -603, -957, +-1150, -1423, -1485, -1557, -1453, -1337, -1015, -854, +-320, -247, 394, 372, 1007, 909, 1412, 1254, +1483, 1309, 1136, 1082, 498, 688, -211, 209, +-837, -312, -1301, -781, -1497, -1067, -1327, -1109, +-819, -954, -154, -669, 483, -276, 990, 189, +1337, 629, 1409, 931, 1134, 1044, 604, 989, +11, 772, -556, 393, -1062, -87, -1373, -562, +-1327, -944, -959, -1147, -442, -1111, 113, -842, +660, -403, 1074, 151, 1207, 717, 1030, 1136, +667, 1281, 213, 1140, -275, 756, -748, 177, +-1042, -489, -1048, -1058, -808, -1357, -465, -1325, +-66, -996, 390, -429, 788, 287, 951, 991, +856, 1469, 616, 1567, 295, 1269, -117, 670, +-529, -108, -790, -930, -822, -1595, -701, -1866, +-510, -1638, -244, -1003, 104, -130, 421, 831, +582, 1671, 598, 2120, 579, 2000, 518, 1365, +317, 409, 16, -660, -225, -1627, -377, -2222, +-521, -2228, -651, -1636, -642, -651, -481, 471, +-248, 1507, -14, 2210, 238, 2327, 493, 1796, +683, 802, 727, -374, 612, -1466, 385, -2216, +102, -2403, -225, -1936, -538, -940, -721, 297, +-700, 1466, -556, 2302, -361, 2575, -117, 2151, +172, 1124, 403, -194, 501, -1469, 494, -2419, +441, -2784, 339, -2401, 186, -1359, 18, 41, +-137, 1434, -287, 2491, -430, 2927, -526, 2579, +-532, 1517, -452, 49, -280, -1428, -19, -2552, +297, -3029, 570, -2679, 752, -1568, 810, -31, +716, 1502, 440, 2672, 23, 3184, -441, 2828, +-845, 1661, -1107, 42, -1141, -1585, -902, -2847, +-437, -3423, 127, -3092, 673, -1912, 1105, -238, +1345, 1491, 1289, 2890, 918, 3610, 333, 3406, +-299, 2312, -871, 645, -1275, -1181, -1397, -2742, +-1210, -3637, -800, -3608, -239, -2667, 416, -1074, +1012, 767, 1363, 2414, 1437, 3455, 1266, 3608, +833, 2834, 143, 1385, -592, -352, -1160, -1993, +-1504, -3144, -1615, -3452, -1378, -2844, -773, -1576, +11, -8, 765, 1557, 1409, 2752, 1838, 3204, +1870, 2799, 1418, 1745, 636, 342, -234, -1131, +-1036, -2347, -1692, -2939, -2027, -2731, -1860, -1847, +-1197, -573, -294, 800, 623, 1967, 1437, 2611, +1983, 2545, 2039, 1818, 1566, 662, 761, -602, +-164, -1651, -1066, -2246, -1761, -2268, -2040, -1691, +-1806, -658, -1142, 481, -199, 1369, 792, 1863, +1615, 1929, 2094, 1504, 2104, 660, 1575, -280, +622, -1003, -474, -1418, -1456, -1530, -2160, -1294, +-2401, -728, -2026, -40, -1096, 506, 102, 833, +1298, 990, 2267, 970, 2753, 744, 2532, 406, +1663, 113, 411, -104, -949, -320, -2183, -520, +-2969, -627, -3004, -657, -2246, -679, -925, -638, +631, -413, 2094, -30, 3098, 376, 3342, 778, +2747, 1161, 1439, 1329, -269, 1090, -1960, 534, +-3163, -155, -3558, -928, -3040, -1641, -1731, -1923, +69, -1602, 1887, -858, 3230, 126, 3744, 1237, +3307, 2142, 1997, 2409, 127, 1950, -1794, 985, +-3237, -296, -3854, -1636, -3498, -2565, -2222, -2713, +-306, -2105, 1689, -965, 3196, 492, 3874, 1908, +3609, 2769, 2395, 2799, 501, 2101, -1489, 881, +-2997, -641, -3725, -2032, -3541, -2762, -2410, -2657, +-599, -1887, 1281, -622, 2688, 885, 3377, 2100, +3252, 2569, 2275, 2275, 719, 1402, -930, 119, +-2246, -1237, -2960, -2133, -2895, -2253, -2088, -1684, +-811, -662, 572, 569, 1732, 1623, 2387, 2071, +2406, 1766, 1860, 915, 915, -168, -238, -1180, +-1274, -1809, -1872, -1791, -1940, -1131, -1612, -130, +-950, 820, -30, 1456, 860, 1635, 1404, 1283, +1559, 475, 1426, -433, 991, -1040, 276, -1207, +-492, -1031, -1102, -591, -1486, 17, -1576, 507, +-1255, 597, -563, 368, 290, 102, 1085, -64, +1695, -113, 1939, 45, 1650, 431, 844, 803, +-255, 846, -1367, 447, -2207, -281, -2500, -1083, +-2080, -1690, -1019, -1867, 398, -1426, 1761, -356, +2698, 1014, 2933, 2155, 2387, 2667, 1160, 2414, +-460, 1418, -2044, -102, -3091, -1704, -3288, -2815, +-2633, -3030, -1320, -2336, 366, -1025, 2010, 558, +3125, 2004, 3399, 2839, 2832, 2753, 1592, 1888, +-54, 640, -1719, -669, -2927, -1765, -3392, -2321, +-3083, -2183, -2097, -1504, -588, -573, 1094, 388, +2489, 1203, 3262, 1697, 3342, 1742, 2735, 1367, +1448, 736, -299, 12, -2023, -719, -3270, -1315, +-3806, -1566, -3493, -1396, -2270, -913, -410, -229, +1576, 547, 3192, 1210, 4069, 1530, 3926, 1433, +2719, 962, 769, 232, -1354, -569, -3090, -1199, +-4011, -1488, -3867, -1393, -2696, -936, -865, -210, +1085, 562, 2627, 1141, 3398, 1401, 3262, 1325, +2316, 914, 824, 235, -750, -484, -1930, -994, +-2470, -1245, -2380, -1247, -1737, -937, -697, -328, +387, 342, 1137, 847, 1441, 1151, 1372, 1235, +986, 992, 379, 428, -196, -270, -530, -864, +-605, -1236, -495, -1325, -217, -1044, 119, -388, +305, 424, 243, 1094, 41, 1438, -175, 1403, +-356, 948, -456, 146, -392, -724, -149, -1349, +175, -1542, 453, -1255, 605, -602, 586, 189, +383, 892, 70, 1321, -206, 1319, -365, 890, +-411, 262, -386, -319, -284, -764, -142, -1008, +-61, -960, -57, -656, -42, -272, 68, 64, +274, 358, 521, 648, 743, 874, 818, 940, +637, 822, 166, 537, -518, 47, -1233, -657, +-1698, -1405, -1701, -1863, -1185, -1781, -244, -1124, +914, -3, 1951, 1328, 2493, 2452, 2330, 2928, +1493, 2464, 234, 1129, -1121, -644, -2260, -2286, +-2860, -3285, -2680, -3292, -1759, -2250, -413, -487, +1029, 1354, 2276, 2660, 2999, 3093, 2946, 2639, +2142, 1511, 792, 62, -831, -1254, -2329, -2026, +-3246, -2185, -3298, -1927, -2452, -1381, -867, -547, +1069, 429, 2743, 1287, 3645, 1918, 3551, 2282, +2447, 2152, 542, 1315, -1568, -109, -3153, -1665, +-3777, -2849, -3357, -3290, -2003, -2749, -43, -1174, +1924, 1005, 3265, 2937, 3624, 3898, 3018, 3658, +1688, 2276, -36, 71, -1724, -2208, -2898, -3694, +-3221, -3975, -2702, -3110, -1592, -1373, -159, 736, +1348, 2520, 2537, 3493, 2999, 3516, 2648, 2636, +1690, 1099, 361, -633, -1110, -2148, -2328, -3167, +-2890, -3435, -2686, -2802, -1807, -1461, -436, 225, +1103, 1922, 2353, 3227, 2960, 3705, 2789, 3185, +1880, 1830, 425, 3, -1174, -1858, -2448, -3269, +-3081, -3836, -2905, -3411, -1912, -2122, -336, -296, +1326, 1603, 2572, 3109, 3113, 3863, 2824, 3679, +1722, 2538, 86, 686, -1525, -1370, -2617, -3057, +-2999, -3971, -2614, -3866, -1478, -2685, 91, -745, +1560, 1322, 2522, 2958, 2837, 3792, 2466, 3595, +1412, 2427, -61, 712, -1459, -1035, -2415, -2430, +-2778, -3199, -2467, -3157, -1456, -2381, -1, -1133, +1436, 347, 2465, 1810, 2871, 2889, 2540, 3241, +1489, 2781, -34, 1643, -1541, -6, -2549, -1812, +-2852, -3154, -2431, -3507, -1353, -2819, 122, -1377, +1547, 460, 2514, 2186, 2837, 3115, 2439, 2936, +1401, 1916, 2, 473, -1376, -989, -2375, -1995, +-2759, -2217, -2439, -1706, -1504, -783, -190, 208, +1190, 964, 2268, 1312, 2698, 1231, 2375, 796, +1456, 161, 168, -429, -1191, -812, -2192, -966, +-2500, -859, -2119, -434, -1199, 162, 61, 666, +1285, 950, 2058, 999, 2189, 715, 1698, 109, +690, -530, -538, -908, -1553, -969, -2067, -748, +-1953, -290, -1214, 276, -65, 683, 1081, 749, +1808, 554, 1908, 243, 1392, -136, 410, -451, +-722, -536, -1579, -382, -1843, -136, -1457, 136, +-605, 395, 403, 507, 1193, 400, 1490, 193, +1236, -83, 544, -428, -278, -681, -893, -651, +-1094, -364, -866, 26, -339, 435, 280, 796, +738, 918, 848, 684, 602, 161, 109, -429, +-451, -858, -863, -1021, -969, -916, -688, -535, +-129, 29, 482, 566, 1036, 892, 1417, 997, +1396, 959, 833, 759, -87, 337, -999, -224, +-1715, -766, -2084, -1180, -1847, -1432, -936, -1404, +333, -925, 1515, -43, 2329, 902, 2571, 1614, +2027, 1949, 830, 1759, -583, 994, -1796, -66, +-2487, -1032, -2462, -1661, -1716, -1815, -524, -1454, +710, -762, 1681, 11, 2112, 683, 1906, 1110, +1215, 1217, 268, 1110, -682, 885, -1383, 518, +-1643, -7, -1419, -545, -867, -965, -144, -1235, +589, -1273, 1083, -954, 1191, -344, 947, 361, +516, 978, 3, 1342, -528, 1307, -865, 893, +-852, 295, -571, -263, -247, -670, 33, -866, +322, -828, 492, -593, 364, -306, 91, -89, +-64, 51, -92, 172, -160, 275, -197, 341, +21, 364, 276, 387, 241, 379, 95, 255, +80, 73, 28, -35, -245, -101, -451, -227, +-350, -385, -147, -438, -2, -427, 170, -432, +345, -344, 365, -68, 198, 280, -4, 568, +-143, 736, -226, 732, -201, 499, -11, 111, +270, -286, 471, -563, 489, -624, 363, -462, +55, -201, -394, 77, -740, 278, -823, 261, +-697, 30, -414, -214, 87, -335, 696, -300, +1065, -78, 1092, 327, 923, 716, 533, 876, +-113, 768, -734, 405, -1052, -216, -1092, -873, +-905, -1262, -423, -1255, 215, -896, 716, -270, +927, 473, 852, 1099, 528, 1354, 55, 1160, +-373, 651, -603, 38, -572, -532, -295, -920, +41, -970, 251, -692, 302, -325, 211, 5, +-34, 275, -323, 447, -415, 494, -232, 439, +17, 345, 204, 250, 364, 100, 436, -129, +271, -463, -71, -769, -321, -815, -362, -601, +-284, -228, -167, 341, -20, 991, 159, 1406, +226, 1308, 84, 761, -84, 17, -81, -802, +31, -1546, 79, -1844, 50, -1481, 93, -674, +144, 200, 24, 1031, -160, 1725, -178, 1909, +-47, 1430, 38, 629, 64, -203, 174, -1001, +243, -1617, 129, -1767, -56, -1400, -155, -730, +-164, 85, -162, 916, -118, 1481, 32, 1639, +210, 1440, 319, 874, 331, 24, 291, -796, +198, -1370, -19, -1632, -286, -1523, -506, -998, +-642, -204, -572, 609, -248, 1270, 266, 1658, +786, 1644, 1074, 1235, 1049, 497, 714, -404, +78, -1190, -703, -1666, -1318, -1772, -1498, -1473, +-1234, -785, -617, 162, 245, 1037, 1065, 1611, +1556, 1841, 1623, 1650, 1218, 1015, 444, 129, +-430, -770, -1154, -1455, -1623, -1819, -1701, -1783, +-1258, -1301, -473, -479, 338, 456, 1060, 1245, +1573, 1718, 1656, 1856, 1178, 1559, 316, 804, +-549, -150, -1182, -1006, -1478, -1613, -1304, -1859, +-731, -1635, -4, -975, 623, -107, 985, 771, +985, 1488, 622, 1824, 83, 1656, -345, 1071, +-534, 216, -509, -728, -332, -1497, -52, -1827, +198, -1685, 270, -1110, 204, -132, 110, 951, +-26, 1677, -148, 1903, -134, 1672, 1, 953, +112, -126, 164, -1147, 200, -1756, 164, -1845, +17, -1481, -150, -759, -294, 166, -367, 1001, +-287, 1448, -49, 1486, 276, 1256, 601, 853, +776, 280, 671, -363, 253, -889, -316, -1199, +-834, -1334, -1156, -1285, -1117, -942, -639, -282, +163, 503, 1014, 1214, 1533, 1663, 1541, 1710, +1085, 1326, 247, 521, -757, -515, -1522, -1357, +-1761, -1793, -1479, -1822, -818, -1398, 120, -519, +1039, 510, 1585, 1308, 1631, 1754, 1245, 1829, +555, 1420, -303, 624, -1107, -308, -1550, -1163, +-1582, -1779, -1295, -1982, -691, -1614, 173, -760, +1022, 254, 1518, 1206, 1577, 1886, 1317, 2068, +735, 1645, -87, 724, -912, -350, -1487, -1254, +-1652, -1843, -1452, -1928, -964, -1434, -217, -567, +595, 321, 1256, 1043, 1612, 1565, 1595, 1700, +1214, 1285, 513, 571, -367, -150, -1151, -796, +-1587, -1292, -1594, -1460, -1276, -1206, -626, -631, +273, 42, 1052, 650, 1441, 1080, 1410, 1201, +1043, 942, 470, 444, -179, -58, -698, -446, +-972, -709, -968, -758, -717, -560, -349, -243, +63, 44, 478, 233, 750, 303, 828, 319, +703, 279, 391, 189, -27, 68, -474, -72, +-816, -144, -877, -161, -610, -242, -139, -237, +331, -86, 697, 40, 891, 109, 829, 221, +477, 358, -42, 345, -469, 123, -671, -82, +-708, -192, -550, -307, -235, -431, 3, -451, +72, -268, 150, 8, 313, 212, 391, 374, +317, 458, 258, 460, 246, 412, 172, 248, +-42, 5, -330, -213, -504, -407, -488, -541, +-427, -645, -346, -642, -131, -402, 131, -11, +219, 378, 209, 743, 348, 1002, 516, 981, +358, 586, 54, 15, 11, -499, 35, -868, +-247, -1024, -568, -863, -554, -423, -359, 122, +-255, 528, -123, 656, 153, 557, 393, 364, +448, 118, 419, -133, 421, -269, 415, -206, +233, -79, -105, -29, -421, 32, -569, 144, +-599, 152, -591, 98, -404, 71, 65, -9, +573, -213, 862, -445, 866, -538, 666, -462, +287, -269, -224, 108, -628, 574, -770, 917, +-657, 1000, -348, 756, -35, 288, 244, -242, +501, -760, 568, -1085, 406, -1064, 219, -738, +145, -329, 69, 34, -116, 450, -230, 853, +-254, 1001, -338, 909, -444, 704, -403, 393, +-173, -140, 89, -816, 279, -1305, 451, -1394, +541, -1067, 542, -377, 438, 473, 167, 1251, +-155, 1660, -416, 1452, -630, 678, -773, -306, +-771, -1111, -532, -1501, -147, -1373, 286, -672, +779, 341, 1098, 1107, 991, 1258, 537, 918, +-34, 310, -545, -484, -976, -1149, -1165, -1223, +-919, -700, -353, 93, 284, 849, 765, 1325, +921, 1292, 768, 704, 413, -176, 40, -972, +-270, -1461, -464, -1475, -463, -936, -357, -8, +-256, 913, -171, 1505, -153, 1566, -140, 1050, +-46, 186, 189, -681, 507, -1310, 718, -1457, +779, -1048, 662, -252, 288, 607, -180, 1151, +-637, 1151, -1086, 675, -1302, -27, -987, -673, +-287, -1019, 380, -867, 931, -278, 1436, 481, +1593, 1045, 1195, 1122, 430, 727, -452, 35, +-1302, -788, -1897, -1375, -1907, -1419, -1211, -911, +-113, -109, 971, 679, 1782, 1311, 2206, 1631, +2016, 1372, 1062, 608, -303, -296, -1478, -1022, +-2140, -1514, -2172, -1681, -1590, -1287, -555, -417, +582, 534, 1451, 1337, 1855, 1813, 1701, 1785, +988, 1141, 27, 51, -760, -1038, -1173, -1777, +-1232, -1982, -963, -1519, -429, -538, 139, 610, +497, 1511, 608, 1837, 516, 1484, 289, 622, +46, -376, -94, -1126, -99, -1393, -15, -1068, +44, -330, -2, 460, -186, 1016, -449, 1120, +-659, 636, -674, -177, -420, -869, 111, -1205, +782, -1116, 1265, -544, 1312, 353, 1003, 1198, +352, 1565, -596, 1298, -1403, 567, -1687, -357, +-1485, -1189, -884, -1604, 33, -1406, 966, -607, +1497, 434, 1518, 1259, 1171, 1560, 544, 1260, +-202, 480, -784, -556, -1025, -1426, -924, -1657, +-685, -1246, -400, -415, -41, 571, 287, 1358, +487, 1708, 636, 1472, 755, 682, 717, -213, +481, -892, 171, -1319, -212, -1428, -685, -1157, +-1060, -628, -1113, -62, -795, 487, -233, 1017, +417, 1329, 1052, 1353, 1402, 1139, 1277, 658, +770, -116, -16, -1012, -906, -1660, -1510, -1807, +-1564, -1502, -1112, -771, -359, 234, 528, 1136, +1262, 1637, 1539, 1673, 1350, 1263, 793, 565, +-69, -159, -930, -687, -1389, -962, -1332, -1003, +-965, -909, -462, -739, 108, -528, 583, -250, +831, 169, 885, 673, 789, 1071, 572, 1262, +268, 1179, -33, 783, -309, 78, -604, -747, +-889, -1365, -1042, -1547, -911, -1269, -444, -678, +143, 17, 650, 715, 1032, 1211, 1209, 1316, +1042, 1084, 559, 668, -26, 146, -521, -432, +-863, -936, -969, -1176, -818, -1147, -550, -878, +-270, -372, 29, 285, 275, 950, 490, 1376, +752, 1321, 939, 856, 894, 185, 725, -493, +465, -1056, -74, -1343, -828, -1173, -1371, -603, +-1514, 71, -1351, 635, -882, 1000, -55, 1128, +905, 960, 1608, 567, 1894, 70, 1813, -438, +1249, -886, 189, -1212, -955, -1292, -1719, -994, +-2026, -429, -1939, 278, -1323, 1031, -207, 1631, +951, 1842, 1783, 1541, 2141, 774, 1936, -239, +1187, -1210, 61, -1877, -1078, -2129, -1849, -1858, +-2107, -1060, -1816, -7, -1051, 997, 36, 1774, +1129, 2154, 1781, 2027, 1829, 1388, 1458, 464, +806, -524, -74, -1425, -972, -1979, -1475, -2037, +-1476, -1673, -1153, -930, -561, 42, 176, 940, +736, 1545, 933, 1837, 841, 1771, 633, 1294, +292, 524, -125, -295, -389, -1005, -445, -1520, +-380, -1763, -292, -1605, -212, -1041, -82, -263, +9, 523, 73, 1192, 216, 1620, 392, 1664, +501, 1251, 493, 575, 348, -115, 56, -711, +-362, -1177, -739, -1380, -956, -1234, -910, -867, +-509, -413, 95, 100, 666, 586, 1079, 1009, +1245, 1266, 1111, 1221, 643, 941, -10, 503, +-659, -82, -1178, -712, -1383, -1249, -1204, -1487, +-736, -1373, -93, -1018, 564, -458, 1108, 285, +1375, 1054, 1302, 1625, 978, 1840, 409, 1711, +-330, 1179, -961, 233, -1326, -908, -1393, -1899, +-1195, -2443, -735, -2387, -51, -1701, 670, -421, +1191, 1085, 1422, 2274, 1414, 2765, 1110, 2480, +415, 1512, -386, 107, -998, -1295, -1429, -2185, +-1621, -2337, -1362, -1815, -648, -860, 195, 211, +860, 1039, 1322, 1402, 1495, 1315, 1223, 935, +570, 453, -143, 50, -684, -217, -1069, -353, +-1238, -414, -998, -446, -471, -532, 57, -673, +447, -675, 711, -442, 845, -108, 765, 298, +466, 738, 120, 1056, -135, 1125, -344, 912, +-543, 475, -562, -65, -382, -592, -195, -996, +-89, -1198, -27, -1103, 22, -776, 65, -355, +92, 136, 166, 616, 306, 931, 489, 1017, +626, 885, 612, 651, 414, 350, 54, -20, +-434, -340, -904, -549, -1133, -700, -992, -773, +-617, -757, -151, -638, 385, -389, 879, -28, +1088, 351, 947, 726, 639, 1036, 265, 1105, +-207, 888, -552, 503, -555, -8, -401, -542, +-334, -961, -297, -1180, -169, -1140, -58, -830, +-95, -367, -104, 125, 51, 599, 271, 999, +435, 1163, 539, 1071, 601, 819, 496, 426, +119, -107, -342, -658, -680, -1023, -831, -1148, +-813, -1145, -605, -934, -196, -473, 305, 85, +700, 619, 829, 1055, 715, 1310, 529, 1348, +242, 1104, -156, 578, -468, -147, -603, -854, +-631, -1351, -584, -1589, -403, -1489, -73, -967, +245, -178, 431, 596, 507, 1145, 516, 1426, +431, 1396, 187, 1011, -129, 414, -339, -144, +-405, -584, -356, -928, -223, -1103, -6, -1021, +219, -800, 263, -501, 120, -18, 6, 591, +-26, 1053, -117, 1251, -221, 1210, -142, 852, +20, 133, 75, -663, 109, -1213, 205, -1402, +276, -1207, 257, -617, 166, 217, 69, 921, +-50, 1213, -240, 1127, -430, 699, -487, 37, +-406, -565, -280, -906, -90, -926, 229, -628, +488, -143, 542, 342, 502, 622, 453, 697, +342, 639, 196, 407, 66, 38, -148, -281, +-513, -472, -872, -617, -1106, -754, -1175, -691, +-981, -417, -403, -111, 509, 252, 1482, 731, +2213, 1145, 2446, 1289, 1966, 1107, 857, 671, +-578, -6, -2029, -836, -3117, -1552, -3414, -1928, +-2774, -1873, -1398, -1333, 418, -383, 2294, 744, +3622, 1747, 3959, 2376, 3281, 2436, 1793, 1885, +-186, 848, -2177, -443, -3629, -1681, -4097, -2511, +-3457, -2675, -1929, -2156, 43, -1171, 1958, 98, +3278, 1392, 3656, 2272, 3094, 2469, 1769, 2074, +11, 1250, -1604, 110, -2631, -1067, -2912, -1823, +-2429, -1981, -1312, -1653, 39, -978, 1199, -85, +1944, 796, 2178, 1359, 1795, 1421, 879, 1089, +-187, 503, -1002, -158, -1465, -698, -1573, -1001, +-1234, -979, -503, -623, 297, -102, 896, 415, +1245, 779, 1299, 896, 952, 768, 335, 445, +-275, -49, -767, -586, -1135, -921, -1254, -974, +-1002, -864, -460, -538, 156, 17, 748, 572, +1219, 907, 1397, 1011, 1195, 943, 664, 677, +-71, 206, -813, -278, -1358, -610, -1542, -767, +-1274, -806, -613, -745, 142, -569, 750, -299, +1192, -13, 1365, 231, 1089, 463, 507, 739, +-54, 917, -483, 892, -834, 732, -951, 425, +-741, -77, -440, -610, -178, -991, 155, -1177, +459, -1168, 499, -862, 344, -327, 233, 188, +149, 600, -13, 911, -148, 1031, -107, 951, +45, 757, 179, 536, 238, 282, 200, -24, +38, -379, -179, -766, -395, -1120, -573, -1338, +-623, -1363, -512, -1114, -306, -507, -19, 390, +351, 1267, 700, 1880, 880, 2165, 952, 1977, +963, 1222, 748, 142, 252, -959, -356, -1861, +-980, -2329, -1545, -2213, -1819, -1627, -1594, -737, +-982, 313, -172, 1226, 823, 1742, 1875, 1887, +2549, 1706, 2488, 1201, 1759, 462, 665, -251, +-645, -753, -1960, -1149, -2857, -1457, -3020, -1449, +-2388, -1164, -1150, -777, 409, -269, 1990, 390, +3090, 1042, 3276, 1500, 2554, 1673, 1227, 1489, +-391, 914, -1964, 86, -2975, -802, -3023, -1487, +-2237, -1739, -953, -1530, 511, -936, 1775, -97, +2434, 719, 2288, 1272, 1514, 1383, 476, 1050, +-556, 457, -1334, -184, -1630, -717, -1387, -989, +-819, -922, -192, -543, 373, 10, 779, 553, +922, 918, 798, 1036, 474, 852, 163, 359, +-8, -317, -180, -945, -441, -1340, -639, -1408, +-658, -1123, -597, -481, -513, 377, -249, 1147, +229, 1544, 731, 1539, 1091, 1269, 1261, 750, +1176, 9, 737, -644, -48, -988, -908, -1116, +-1509, -1187, -1742, -1129, -1651, -839, -1186, -463, +-325, -130, 699, 304, 1521, 872, 1943, 1348, +1991, 1510, 1674, 1407, 915, 1157, -113, 651, +-1083, -124, -1823, -869, -2223, -1400, -2112, -1729, +-1502, -1839, -589, -1599, 451, -1002, 1449, -236, +2115, 597, 2253, 1471, 1903, 2109, 1181, 2255, +224, 1951, -778, 1328, -1580, 389, -1962, -717, +-1917, -1623, -1579, -2130, -1006, -2278, -194, -2041, +663, -1412, 1269, -525, 1576, 442, 1683, 1356, +1551, 2065, 1100, 2436, 395, 2378, -335, 1813, +-926, 777, -1390, -446, -1663, -1554, -1603, -2379, +-1260, -2751, -744, -2439, -74, -1532, 674, -417, +1315, 680, 1704, 1651, 1753, 2241, 1458, 2316, +929, 1955, 242, 1306, -608, 467, -1428, -478, +-1852, -1372, -1805, -2003, -1475, -2205, -867, -1931, +25, -1276, 894, -314, 1451, 793, 1715, 1690, +1685, 2082, 1220, 1944, 379, 1367, -466, 444, +-1072, -581, -1438, -1319, -1515, -1623, -1185, -1524, +-530, -1022, 189, -258, 784, 512, 1165, 1132, +1218, 1419, 959, 1242, 512, 715, -25, 63, +-523, -654, -840, -1313, -909, -1595, -777, -1342, +-540, -728, -187, 40, 245, 838, 572, 1494, +705, 1751, 737, 1544, 716, 1021, 497, 312, +47, -468, -320, -1140, -508, -1590, -739, -1742, +-948, -1589, -879, -1178, -552, -536, -139, 311, +320, 1178, 810, 1825, 1156, 2137, 1242, 2038, +1081, 1437, 643, 486, -24, -536, -745, -1458, +-1312, -2094, -1557, -2207, -1431, -1802, -931, -1119, +-184, -320, 544, 558, 1079, 1311, 1356, 1705, +1331, 1752, 1006, 1565, 450, 1097, -146, 341, +-624, -463, -922, -1071, -1000, -1438, -859, -1487, +-526, -1156, -96, -553, 254, 107, 493, 619, +607, 806, 476, 645, 169, 313, -117, -24, +-312, -301, -343, -342, -111, -44, 294, 409, +585, 779, 655, 959, 579, 882, 291, 488, +-257, -194, -824, -903, -1134, -1433, -1112, -1723, +-838, -1691, -382, -1234, 148, -434, 597, 493, +930, 1354, 1148, 2029, 1173, 2348, 1009, 2195, +711, 1561, 252, 574, -353, -524, -939, -1567, +-1389, -2411, -1703, -2766, -1703, -2525, -1149, -1852, +-239, -839, 665, 477, 1443, 1807, 1953, 2742, +1941, 3063, 1399, 2798, 562, 1965, -339, 602, +-1109, -991, -1533, -2274, -1467, -2911, -975, -2857, +-286, -2140, 334, -901, 701, 473, 764, 1524, +506, 1981, -32, 1841, -615, 1259, -893, 468, +-721, -284, -187, -723, 568, -696, 1347, -359, +1821, 5, 1710, 256, 1028, 332, -28, 186, +-1242, -188, -2243, -626, -2624, -877, -2280, -878, +-1367, -669, -119, -228, 1126, 321, 2037, 794, +2442, 1107, 2285, 1210, 1584, 1019, 584, 588, +-371, 95, -1101, -389, -1528, -826, -1638, -989, +-1490, -852, -1123, -647, -579, -446, 37, -200, +561, -9, 896, 53, 1103, 95, 1163, 230, +976, 438, 615, 751, 217, 1097, -200, 1174, +-618, 865, -854, 350, -758, -295, -523, -1050, +-328, -1641, -68, -1758, 205, -1429, 294, -809, +205, -8, 68, 750, -73, 1205, -186, 1350, +-118, 1257, 144, 946, 382, 545, 531, 216, +640, -79, 626, -361, 379, -557, -43, -720, +-468, -952, -833, -1137, -1107, -1081, -1130, -759, +-885, -316, -492, 211, 44, 835, 693, 1406, +1263, 1678, 1540, 1547, 1456, 1093, 1054, 437, +352, -354, -488, -1088, -1182, -1510, -1539, -1525, +-1457, -1244, -985, -767, -333, -143, 333, 422, +822, 663, 918, 635, 628, 529, 186, 425, +-158, 338, -311, 328, -263, 438, 27, 579, +463, 573, 788, 358, 782, -39, 439, -548, +-74, -1051, -630, -1383, -1132, -1461, -1416, -1250, +-1362, -723, -933, 26, -211, 787, 567, 1461, +1223, 1949, 1673, 2040, 1784, 1601, 1466, 767, +776, -207, -119, -1163, -1035, -1952, -1724, -2279, +-1900, -1960, -1551, -1145, -850, -149, 50, 794, +869, 1460, 1348, 1666, 1411, 1438, 1077, 938, +447, 306, -254, -254, -720, -573, -794, -644, +-618, -591, -336, -505, 32, -398, 366, -307, +482, -273, 376, -200, 232, 7, 121, 247, +-45, 385, -214, 492, -302, 587, -382, 511, +-490, 245, -526, -34, -388, -231, -78, -322, +288, -316, 631, -252, 913, -165, 1035, -55, +861, 9, 408, -54, -141, -201, -670, -314, +-1123, -349, -1319, -254, -1127, 0, -658, 389, +-125, 810, 342, 1092, 768, 1139, 1125, 933, +1160, 414, 795, -382, 335, -1233, -22, -1813, +-389, -1971, -725, -1735, -765, -1072, -537, 21, +-328, 1214, -154, 2078, 123, 2473, 330, 2397, +254, 1691, 61, 448, -15, -811, -36, -1761, +-123, -2378, -121, -2461, 53, -1882, 187, -891, +252, 160, 398, 1069, 490, 1667, 373, 1840, +176, 1609, -9, 1098, -296, 466, -655, -155, +-888, -697, -968, -1038, -911, -1102, -579, -980, +-11, -793, 580, -491, 1101, -54, 1507, 342, +1642, 541, 1339, 628, 719, 663, 32, 556, +-724, 328, -1499, 168, -1961, 54, -1912, -145, +-1515, -308, -971, -338, -202, -402, 801, -485, +1649, -429, 2045, -240, 2050, 15, 1803, 312, +1251, 532, 293, 562, -782, 435, -1540, 221, +-1985, -99, -2194, -429, -1929, -570, -1112, -438, +-148, -123, 632, 220, 1315, 465, 1816, 556, +1778, 418, 1271, 69, 681, -363, 144, -711, +-364, -803, -739, -584, -845, -175, -754, 322, +-650, 789, -561, 1003, -472, 835, -386, 450, +-261, 11, -68, -454, 194, -810, 521, -850, +811, -629, 924, -335, 798, -51, 556, 183, +290, 283, -84, 281, -462, 292, -617, 327, +-629, 347, -630, 393, -552, 444, -349, 349, +-144, 52, -51, -295, 23, -623, 176, -903, +344, -969, 473, -755, 543, -356, 555, 180, +519, 715, 422, 1018, 271, 1058, 6, 929, +-399, 543, -758, -88, -941, -601, -963, -804, +-815, -864, -446, -771, 107, -401, 668, 82, +1042, 398, 1140, 521, 942, 507, 513, 309, +-43, -8, -568, -221, -829, -283, -744, -250, +-440, -85, -62, 196, 268, 390, 481, 404, +471, 313, 155, 123, -266, -190, -502, -475, +-537, -599, -469, -575, -226, -462, 260, -245, +710, 84, 803, 425, 635, 646, 420, 724, +127, 695, -281, 565, -603, 290, -635, -99, +-491, -493, -361, -789, -185, -942, 83, -929, +257, -729, 261, -321, 234, 194, 225, 678, +170, 1049, 76, 1215, -9, 1057, -82, 611, +-117, 47, -91, -513, -83, -991, -51, -1200, +106, -1048, 212, -641, 123, -109, 18, 427, +20, 768, -30, 813, -214, 662, -312, 390, +-252, 25, -260, -267, -313, -348, -173, -291, +85, -196, 283, -52, 489, 77, 770, 66, +904, -56, 708, -132, 331, -158, -162, -197, +-776, -181, -1236, -26, -1335, 202, -1120, 392, +-665, 507, -28, 539, 645, 422, 1112, 133, +1257, -279, 1127, -677, 794, -920, 378, -956, +-29, -724, -365, -188, -542, 464, -611, 974, +-659, 1209, -651, 1135, -561, 748, -436, 137, +-367, -501, -291, -958, -29, -1127, 345, -993, +632, -646, 854, -201, 1087, 214, 1218, 507, +1051, 694, 584, 784, -24, 710, -664, 522, +-1263, 316, -1698, 60, -1808, -285, -1473, -606, +-829, -813, -123, -879, 588, -771, 1247, -491, +1655, -111, 1726, 319, 1560, 731, 1208, 1003, +625, 1049, -104, 883, -764, 543, -1274, 54, +-1650, -500, -1809, -950, -1636, -1178, -1099, -1135, +-345, -810, 391, -257, 1009, 340, 1476, 802, +1690, 1026, 1556, 937, 1151, 596, 674, 187, +138, -219, -502, -509, -1043, -511, -1318, -307, +-1397, -105, -1311, 59, -982, 154, -415, 94, +199, -86, 736, -234, 1155, -313, 1290, -311, +1104, -167, 733, 75, 215, 298, -341, 437, +-706, 480, -804, 454, -714, 333, -479, 111, +-95, -113, 293, -256, 496, -345, 495, -402, +299, -397, -30, -305, -338, -194, -532, -140, +-571, -113, -449, -7, -199, 140, 129, 228, +431, 327, 634, 514, 707, 644, 636, 606, +489, 451, 334, 231, 127, -76, -186, -469, +-566, -844, -893, -1053, -1115, -1069, -1180, -968, +-962, -714, -480, -181, 120, 495, 808, 1071, +1451, 1502, 1744, 1761, 1580, 1663, 1112, 1111, +467, 223, -305, -732, -1026, -1563, -1460, -2142, +-1605, -2261, -1529, -1776, -1141, -867, -484, 136, +165, 1087, 676, 1860, 1116, 2151, 1417, 1873, +1391, 1254, 1081, 503, 649, -303, 104, -1019, +-450, -1429, -794, -1462, -934, -1263, -971, -917, +-866, -433, -578, 76, -234, 454, 31, 707, +233, 868, 384, 893, 447, 788, 470, 600, +456, 336, 398, 53, 323, -248, 223, -553, +133, -743, 74, -749, -13, -638, -161, -413, +-343, -63, -466, 274, -513, 432, -563, 419, +-573, 252, -449, -42, -220, -295, 38, -356, +285, -201, 545, 172, 778, 656, 910, 1043, +986, 1129, 940, 856, 631, 289, 117, -495, +-458, -1306, -1037, -1802, -1534, -1809, -1769, -1429, +-1626, -782, -1155, 93, -378, 993, 612, 1597, +1483, 1812, 1981, 1737, 2116, 1403, 1914, 839, +1303, 163, 326, -489, -685, -1045, -1474, -1444, +-2006, -1634, -2146, -1592, -1798, -1303, -1132, -784, +-316, -151, 583, 495, 1366, 1105, 1751, 1588, +1710, 1750, 1418, 1539, 902, 1092, 192, 471, +-459, -293, -870, -968, -1088, -1344, -1157, -1402, +-1007, -1158, -635, -636, -236, -65, 62, 298, +375, 444, 720, 401, 886, 152, 795, -108, +585, -159, 319, 28, -45, 375, -436, 769, +-684, 1033, -726, 997, -596, 637, -322, 82, +42, -529, 392, -1032, 600, -1293, 587, -1262, +408, -994, 166, -614, -95, -227, -349, 141, +-495, 476, -426, 776, -239, 1013, -88, 1179, +36, 1236, 142, 1068, 190, 655, 190, 103, +165, -514, 124, -1099, 80, -1476, 71, -1536, +90, -1338, 47, -936, -45, -378, -88, 193, +-100, 672, -111, 1063, -91, 1314, -63, 1348, +-107, 1177, -259, 866, -405, 408, -395, -181, +-243, -766, -15, -1189, 318, -1353, 768, -1235, +1135, -882, 1129, -339, 765, 253, 255, 692, +-369, 882, -1078, 811, -1596, 517, -1654, 115, +-1266, -249, -623, -445, 115, -387, 839, -100, +1417, 264, 1696, 585, 1562, 812, 1119, 810, +540, 446, -165, -140, -899, -720, -1386, -1202, +-1505, -1523, -1359, -1528, -1019, -1126, -422, -444, +337, 332, 940, 1116, 1225, 1768, 1236, 2078, +999, 1952, 553, 1456, 8, 668, -480, -281, +-768, -1186, -826, -1893, -673, -2246, -361, -2119, +-6, -1602, 265, -849, 400, 39, 457, 912, +431, 1569, 212, 1899, -124, 1903, -371, 1598, +-480, 1026, -530, 325, -489, -367, -246, -961, +156, -1372, 550, -1520, 864, -1366, 1050, -992, +986, -522, 570, -5, -110, 448, -773, 701, +-1257, 753, -1577, 679, -1575, 529, -1049, 353, +-140, 228, 742, 197, 1355, 239, 1721, 273, +1737, 212, 1236, 50, 433, -177, -300, -470, +-861, -793, -1253, -1017, -1367, -1038, -1132, -843, +-742, -494, -403, -30, -76, 508, 280, 1014, +590, 1337, 816, 1403, 955, 1231, 984, 837, +887, 262, 654, -356, 263, -901, -265, -1275, +-768, -1403, -1096, -1296, -1219, -965, -1125, -439, +-817, 112, -382, 555, 102, 909, 572, 1153, +939, 1161, 1106, 933, 1077, 588, 908, 185, +603, -229, 211, -585, -172, -830, -546, -896, +-872, -789, -1009, -588, -939, -323, -779, -6, +-551, 282, -178, 455, 268, 555, 597, 650, +790, 623, 892, 396, 831, 113, 625, -112, +377, -341, 92, -561, -212, -593, -453, -393, +-589, -132, -655, 119, -665, 349, -585, 435, +-458, 307, -326, 57, -115, -188, 196, -343, +506, -367, 732, -256, 866, -31, 892, 241, +754, 441, 443, 484, 12, 376, -467, 174, +-860, -55, -1062, -263, -1076, -415, -900, -474, +-538, -415, -54, -256, 409, -64, 715, 133, +874, 317, 919, 409, 788, 386, 500, 307, +195, 161, -57, -42, -311, -203, -578, -273, +-726, -272, -735, -227, -693, -144, -539, -48, +-218, 12, 172, 56, 559, 130, 847, 205, +900, 247, 707, 251, 366, 197, -65, 55, +-512, -141, -768, -327, -693, -440, -431, -391, +-106, -184, 291, 50, 596, 254, 594, 400, +348, 375, 58, 166, -223, -77, -489, -228, +-588, -263, -463, -164, -212, 53, 105, 291, +398, 414, 558, 332, 601, 101, 525, -147, +285, -391, -83, -587, -405, -590, -561, -376, +-619, -90, -583, 136, -347, 313, 18, 472, +359, 529, 572, 443, 605, 324, 490, 229, +256, 101, -40, -76, -284, -241, -448, -355, +-539, -446, -549, -522, -431, -510, -153, -365, +164, -162, 431, 39, 694, 270, 868, 491, +804, 612, 494, 592, 25, 437, -556, 187, +-1136, -81, -1413, -301, -1228, -409, -756, -358, +-134, -177, 593, 27, 1229, 168, 1510, 203, +1370, 67, 954, -211, 377, -480, -267, -599, +-795, -528, -1094, -280, -1162, 126, -1032, 571, +-742, 862, -285, 950, 263, 849, 678, 536, +847, 88, 837, -335, 688, -640, 347, -801, +-112, -815, -424, -696, -435, -468, -254, -164, +14, 121, 300, 301, 442, 376, 313, 368, +-34, 306, -439, 231, -735, 184, -823, 216, +-652, 319, -262, 413, 210, 425, 601, 298, +764, 33, 686, -316, 496, -680, 289, -934, +102, -980, -22, -863, -55, -635, -32, -281, +-65, 139, -230, 487, -453, 734, -621, 940, +-673, 1075, -606, 1053, -407, 875, -70, 590, +309, 204, 612, -261, 796, -682, 833, -982, +729, -1172, 486, -1253, 143, -1195, -165, -996, +-375, -669, -519, -229, -597, 328, -574, 976, +-438, 1589, -295, 1963, -223, 1973, -164, 1593, +-66, 847, 65, -103, 215, -1010, 352, -1690, +498, -1969, 645, -1804, 693, -1345, 567, -742, +312, -138, 36, 328, -215, 644, -475, 817, +-690, 875, -782, 906, -767, 909, -683, 812, +-506, 652, -201, 468, 168, 194, 465, -177, +680, -535, 856, -815, 928, -1013, 794, -1126, +513, -1081, 236, -806, 11, -380, -213, 87, +-434, 573, -635, 933, -813, 1009, -948, 866, +-980, 607, -823, 264, -467, -13, -1, -80, +544, 5, 1079, 122, 1422, 192, 1450, 110, +1178, -168, 709, -591, 166, -991, -384, -1172, +-855, -1079, -1149, -749, -1234, -222, -1144, 377, +-900, 884, -529, 1172, -103, 1185, 301, 1006, +692, 747, 1012, 408, 1117, 31, 983, -259, +712, -435, 383, -563, 25, -618, -320, -584, +-584, -523, -747, -491, -835, -511, -817, -534, +-632, -479, -346, -326, -78, -39, 209, 419, +568, 988, 817, 1479, 804, 1684, 624, 1515, +370, 1012, 26, 235, -329, -670, -567, -1431, +-628, -1808, -522, -1782, -286, -1431, 4, -832, +279, -136, 480, 450, 521, 815, 357, 973, +92, 994, -205, 869, -529, 643, -756, 436, +-704, 243, -398, 19, -4, -156, 403, -271, +787, -378, 981, -440, 880, -428, 594, -412, +219, -400, -242, -348, -623, -279, -759, -214, +-750, -96, -706, 75, -562, 248, -315, 401, +-45, 557, 230, 671, 489, 653, 680, 516, +788, 305, 778, 9, 596, -318, 270, -577, +-103, -706, -461, -676, -696, -484, -715, -200, +-567, 79, -352, 255, -103, 264, 126, 122, +263, -68, 270, -229, 176, -269, 62, -111, +2, 205, 1, 551, 79, 816, 253, 895, +411, 744, 423, 376, 335, -125, 158, -628, +-199, -1026, -637, -1242, -889, -1207, -880, -929, +-685, -463, -305, 124, 252, 708, 777, 1147, +1037, 1382, 984, 1316, 681, 909, 186, 298, +-362, -355, -769, -904, -896, -1165, -733, -1107, +-370, -783, 73, -268, 490, 247, 753, 584, +739, 716, 447, 640, 49, 392, -316, 76, +-641, -199, -848, -378, -774, -454, -439, -442, +11, -316, 477, -81, 852, 174, 978, 384, +820, 566, 470, 630, 21, 478, -450, 175, +-797, -182, -898, -533, -716, -737, -327, -717, +82, -491, 363, -106, 502, 306, 470, 561, +260, 611, -13, 465, -196, 165, -239, -167, +-143, -418, 82, -492, 329, -331, 434, -62, +393, 205, 239, 432, -37, 521, -368, 406, +-610, 167, -695, -108, -638, -333, -441, -459, +-107, -461, 210, -344, 393, -154, 535, 23, +683, 132, 715, 198, 596, 260, 397, 284, +156, 260, -157, 224, -486, 174, -754, 42, +-931, -168, -952, -372, -718, -475, -279, -442, +190, -250, 547, 84, 790, 468, 896, 738, +756, 773, 411, 529, 68, 59, -200, -491, +-411, -942, -501, -1139, -424, -993, -276, -563, +-124, 29, 46, 632, 224, 1066, 326, 1223, +308, 1104, 168, 765, -39, 297, -262, -235, +-502, -697, -669, -977, -600, -1094, -321, -1045, +63, -748, 519, -278, 948, 218, 1133, 646, +979, 922, 615, 961, 175, 754, -357, 359, +-876, -78, -1155, -420, -1107, -578, -838, -516, +-481, -277, -94, 31, 287, 306, 553, 447, +671, 419, 686, 250, 632, -31, 506, -358, +321, -625, 156, -767, 68, -755, -59, -586, +-254, -236, -403, 219, -479, 647, -560, 998, +-623, 1196, -583, 1100, -449, 770, -269, 318, +5, -204, 346, -658, 681, -911, 952, -984, +1060, -909, 970, -713, 741, -463, 302, -252, +-313, -93, -845, 59, -1132, 246, -1227, 460, +-1106, 683, -695, 869, -128, 981, 334, 969, +633, 787, 795, 426, 783, -36, 598, -521, +342, -944, 141, -1229, 27, -1324, -88, -1191, +-193, -873, -254, -481, -307, -13, -341, 453, +-305, 779, -215, 979, -78, 1100, 61, 1118, +130, 1024, 116, 805, 83, 505, 40, 129, +-23, -341, -36, -822, 54, -1188, 152, -1396, +195, -1395, 177, -1167, 94, -756, -13, -239, +-89, 287, -105, 731, -40, 1065, 30, 1271, +77, 1316, 87, 1187, -17, 921, -241, 516, +-426, -20, -463, -574, -373, -984, -166, -1243, +198, -1287, 562, -1024, 727, -585, 723, -154, +581, 213, 249, 420, -156, 438, -477, 327, +-658, 171, -702, 87, -578, 152, -310, 337, +-45, 581, 141, 786, 321, 881, 456, 798, +461, 477, 357, -46, 220, -650, 60, -1225, +-114, -1668, -238, -1855, -284, -1646, -296, -1045, +-232, -214, -72, 701, 116, 1556, 256, 2107, +290, 2204, 208, 1846, 77, 1132, -81, 257, +-248, -583, -361, -1258, -344, -1593, -197, -1572, +-3, -1320, 173, -899, 338, -398, 426, 42, +377, 379, 223, 577, 57, 658, -97, 658, +-278, 576, -444, 446, -469, 352, -376, 293, +-231, 259, -29, 227, 225, 179, 485, 68, +670, -126, 675, -375, 499, -631, 201, -869, +-139, -994, -463, -948, -736, -735, -860, -384, +-762, 73, -521, 565, -218, 1026, 111, 1342, +431, 1439, 674, 1302, 800, 929, 830, 362, +758, -283, 546, -877, 199, -1267, -248, -1413, +-627, -1336, -820, -1021, -906, -564, -873, -127, +-596, 247, -195, 523, 137, 734, 390, 894, +603, 950, 654, 922, 508, 826, 350, 561, +240, 145, 60, -325, -158, -757, -295, -1049, +-293, -1122, -205, -944, -95, -525, 69, -34, +260, 368, 313, 625, 170, 686, -98, 530, +-375, 254, -603, -45, -735, -241, -635, -266, +-250, -174, 208, -21, 549, 184, 771, 346, +905, 370, 823, 257, 502, 90, 185, -101, +-12, -277, -246, -373, -517, -372, -693, -293, +-769, -171, -798, -111, -731, -78, -487, -32, +-78, -45, 370, -40, 725, 85, 902, 246, +920, 425, 751, 584, 378, 608, -2, 490, +-204, 260, -330, -82, -450, -404, -457, -612, +-335, -693, -253, -626, -245, -444, -156, -239, +11, -49, 101, 80, 127, 165, 121, 251, +33, 343, -116, 425, -219, 484, -195, 487, +-29, 403, 226, 176, 522, -131, 759, -384, +827, -543, 672, -583, 308, -441, -156, -157, +-578, 154, -900, 363, -1062, 429, -1033, 357, +-855, 139, -589, -163, -244, -405, 178, -531, +583, -511, 865, -343, 1070, -77, 1183, 216, +1082, 466, 758, 619, 324, 676, -138, 620, +-569, 464, -896, 264, -1044, 47, -1028, -187, +-880, -421, -639, -659, -357, -838, -46, -915, +272, -887, 518, -701, 685, -332, 771, 146, +782, 657, 691, 1057, 445, 1261, 123, 1254, +-101, 968, -236, 466, -340, -25, -388, -435, +-340, -704, -255, -770, -243, -692, -321, -538, +-400, -374, -420, -335, -366, -395, -252, -429, +-14, -384, 359, -251, 696, 32, 888, 475, +947, 958, 792, 1291, 420, 1389, -5, 1240, +-346, 817, -585, 155, -695, -553, -650, -1112, +-498, -1431, -336, -1495, -185, -1258, -89, -796, +-63, -272, -33, 210, 68, 571, 234, 745, +393, 803, 478, 769, 486, 644, 387, 509, +222, 377, 100, 195, 19, -12, -65, -221, +-86, -395, -50, -521, -97, -562, -304, -476, +-546, -310, -704, -157, -758, 8, -634, 139, +-266, 168, 221, 147, 681, 122, 1017, 71, +1134, 25, 974, -30, 565, -60, 46, -21, +-389, 41, -674, 118, -799, 278, -756, 433, +-566, 469, -302, 370, -51, 153, 145, -158, +290, -493, 358, -753, 368, -803, 341, -628, +284, -333, 207, -2, 82, 329, -108, 528, +-253, 505, -297, 376, -309, 259, -316, 108, +-209, -14, -1, -28, 166, 2, 273, 9, +357, 10, 333, 10, 207, 25, 75, 25, +-48, 2, -170, -39, -234, -153, -239, -327, +-236, -464, -218, -557, -126, -522, -31, -264, +15, 111, 87, 486, 205, 818, 268, 952, +253, 835, 197, 543, 123, 136, 14, -276, +-96, -554, -121, -683, -71, -673, -43, -547, +-55, -378, -99, -217, -157, -45, -228, 121, +-285, 255, -254, 368, -91, 465, 125, 475, +326, 386, 484, 223, 519, 17, 362, -179, +126, -322, -55, -399, -212, -363, -361, -242, +-392, -109, -313, 30, -215, 179, -134, 269, +-40, 296, 63, 279, 138, 207, 198, 83, +287, -62, 324, -217, 222, -350, 39, -437, +-85, -441, -146, -370, -198, -224, -177, 8, +-55, 276, 34, 506, 60, 688, 62, 749, +5, 636, -113, 382, -181, 41, -155, -313, +-68, -588, 30, -739, 142, -704, 224, -504, +233, -264, 202, -66, 165, 84, 69, 162, +-61, 176, -140, 158, -182, 178, -266, 271, +-329, 372, -274, 404, -117, 379, 59, 285, +218, 115, 339, -83, 397, -231, 337, -312, +158, -341, -18, -339, -94, -322, -152, -319, +-227, -299, -204, -240, -86, -140, -64, 8, +-156, 188, -204, 337, -139, 419, -45, 426, +54, 397, 196, 349, 358, 288, 419, 237, +313, 177, 112, 21, -71, -224, -225, -504, +-339, -755, -349, -888, -191, -809, 49, -511, +202, -56, 259, 411, 290, 766, 189, 932, +-74, 857, -319, 573, -443, 232, -509, -84, +-474, -343, -259, -496, 57, -525, 350, -496, +593, -432, 730, -307, 710, -69, 566, 222, +321, 481, 5, 666, -285, 718, -511, 543, +-675, 166, -740, -312, -682, -730, -534, -957, +-309, -925, -34, -645, 251, -175, 507, 341, +673, 747, 705, 936, 647, 891, 499, 644, +241, 280, -37, -114, -248, -440, -420, -607, +-521, -602, -503, -499, -393, -299, -237, -24, +-41, 192, 164, 274, 316, 276, 328, 178, +186, 5, -17, -146, -159, -226, -246, -200, +-275, -54, -146, 110, 147, 242, 414, 331, +540, 314, 527, 160, 364, -34, 57, -186, +-288, -268, -542, -266, -617, -160, -552, 14, +-408, 193, -209, 290, 15, 293, 218, 196, +374, -6, 469, -256, 533, -441, 565, -530, +478, -504, 200, -340, -173, -72, -525, 190, +-812, 386, -934, 491, -768, 494, -378, 423, +86, 334, 532, 265, 855, 233, 917, 186, +728, 75, 391, -132, 22, -420, -261, -716, +-390, -926, -427, -981, -423, -785, -372, -355, +-306, 150, -291, 595, -251, 930, -116, 1039, +73, 895, 269, 621, 463, 328, 592, 23, +575, -234, 399, -392, 142, -481, -125, -551, +-330, -572, -418, -494, -373, -302, -223, -66, +-35, 156, 88, 335, 130, 429, 92, 358, +-53, 159, -260, -38, -394, -148, -367, -175, +-205, -111, 19, 17, 318, 155, 641, 217, +822, 179, 778, 94, 585, 23, 283, -34, +-127, -55, -536, -54, -780, -61, -857, -97, +-815, -150, -640, -222, -359, -258, -51, -194, +233, -56, 442, 66, 568, 169, 611, 247, +558, 239, 428, 137, 294, 43, 165, 1, +18, -11, -98, 8, -124, 69, -153, 120, +-225, 131, -301, 92, -395, 26, -491, -66, +-511, -180, -471, -301, -377, -396, -176, -441, +127, -392, 420, -242, 631, -12, 772, 249, +832, 499, 746, 650, 521, 648, 235, 499, +-62, 260, -381, -13, -673, -235, -828, -360, +-825, -392, -735, -366, -540, -303, -246, -248, +44, -216, 257, -177, 419, -98, 525, 16, +555, 165, 498, 299, 404, 375, 327, 363, +257, 269, 145, 131, 21, 23, -82, -30, +-218, -26, -414, 10, -537, 59, -543, 50, +-519, -64, -473, -254, -327, -438, -91, -572, +160, -598, 368, -479, 532, -211, 618, 143, +603, 500, 527, 773, 414, 911, 240, 874, +18, 663, -192, 312, -337, -82, -450, -438, +-549, -707, -567, -848, -474, -813, -325, -634, +-145, -381, 41, -113, 204, 137, 288, 320, +283, 420, 249, 414, 235, 340, 219, 270, +191, 220, 188, 156, 238, 122, 257, 127, +160, 120, 4, 75, -132, 22, -267, -39, +-396, -102, -465, -163, -453, -225, -419, -280, +-368, -335, -260, -432, -105, -521, 56, -528, +233, -436, 436, -239, 651, 113, 782, 551, +756, 925, 570, 1134, 246, 1123, -154, 834, +-521, 338, -798, -221, -906, -664, -785, -853, +-471, -761, -78, -463, 297, -72, 573, 223, +665, 298, 529, 124, 257, -235, -39, -638, +-288, -895, -431, -898, -424, -615, -268, -106, +-22, 508, 208, 1048, 376, 1392, 452, 1477, +400, 1292, 255, 871, 91, 316, -85, -261, +-265, -775, -402, -1179, -458, -1392, -438, -1364, +-324, -1108, -128, -673, 87, -117, 292, 441, +473, 860, 533, 1045, 441, 982, 260, 683, +47, 233, -172, -238, -335, -573, -397, -668, +-368, -514, -307, -179, -225, 263, -121, 665, +9, 892, 149, 862, 265, 579, 345, 107, +428, -437, 446, -924, 316, -1213, 85, -1240, +-134, -996, -312, -546, -437, 20, -441, 574, +-301, 986, -147, 1153, -34, 1079, 67, 810, +124, 410, 90, -41, 31, -414, 21, -638, +53, -694, 67, -611, 71, -419, 80, -191, +88, -1, 88, 101, 110, 152, 170, 165, +243, 157, 259, 157, 173, 201, -14, 253, +-262, 269, -533, 218, -759, 99, -807, -76, +-593, -249, -236, -375, 155, -401, 562, -317, +889, -171, 970, -15, 803, 134, 510, 201, +155, 166, -248, 102, -576, 71, -696, 61, +-647, 90, -538, 152, -368, 194, -105, 166, +155, 82, 272, -41, 294, -159, 318, -228, +295, -218, 202, -145, 128, -50, 100, 8, +71, 4, -6, -65, -103, -145, -158, -183, +-179, -149, -213, -46, -214, 129, -128, 317, +3, 433, 85, 433, 128, 358, 127, 219, +52, 50, -43, -114, -104, -253, -143, -384, +-119, -497, -26, -587, 75, -610, 167, -526, +287, -300, 383, 65, 359, 535, 239, 979, +100, 1254, -97, 1262, -370, 975, -614, 416, +-701, -285, -618, -932, -413, -1347, -95, -1471, +305, -1282, 619, -830, 722, -264, 641, 229, +425, 561, 106, 712, -217, 703, -406, 595, +-384, 509, -226, 483, -45, 507, 103, 557, +195, 554, 181, 390, 56, 83, -98, -321, +-203, -768, -272, -1147, -281, -1317, -187, -1250, +-24, -968, 111, -529, 190, 3, 241, 509, +277, 887, 255, 1073, 154, 1107, 10, 1006, +-119, 769, -218, 447, -272, 129, -234, -176, +-94, -429, 59, -594, 174, -663, 258, -650, +280, -553, 205, -414, 56, -255, -100, -92, +-195, 43, -233, 137, -242, 242, -233, 339, +-185, 388, -93, 385, 9, 353, 87, 275, +180, 137, 278, -48, 319, -210, 264, -330, +144, -392, 8, -387, -133, -287, -265, -108, +-289, 119, -165, 321, -5, 468, 98, 533, +171, 465, 207, 209, 119, -138, -61, -456, +-180, -698, -219, -817, -241, -709, -209, -385, +-73, 38, 76, 439, 144, 754, 157, 892, +193, 822, 213, 596, 191, 305, 181, -16, +188, -319, 131, -559, -1, -700, -154, -772, +-302, -765, -452, -646, -534, -398, -488, -64, +-323, 308, -61, 641, 251, 862, 517, 893, +684, 743, 711, 476, 586, 169, 362, -99, +90, -256, -201, -305, -439, -260, -569, -198, +-598, -205, -558, -318, -458, -486, -318, -665, +-147, -786, 63, -761, 282, -533, 460, -121, +587, 424, 626, 975, 546, 1412, 360, 1617, +104, 1507, -168, 1091, -377, 462, -462, -281, +-400, -973, -250, -1461, -79, -1649, 70, -1519, +173, -1125, 173, -606, 41, -56, -147, 437, +-296, 771, -391, 906, -396, 909, -257, 785, +-7, 561, 274, 320, 516, 109, 666, -77, +720, -205, 636, -261, 362, -245, 0, -200, +-258, -164, -405, -154, -525, -156, -559, -186, +-454, -229, -356, -250, -353, -233, -343, -182, +-258, -84, -125, 47, 88, 209, 402, 374, +744, 510, 969, 589, 982, 583, 757, 429, +331, 123, -203, -279, -692, -664, -994, -935, +-1026, -984, -809, -763, -439, -300, -39, 283, +293, 824, 483, 1155, 525, 1197, 469, 915, +376, 390, 266, -201, 167, -696, 75, -1039, +-56, -1162, -217, -1036, -344, -713, -431, -302, +-450, 133, -336, 539, -113, 879, 114, 1085, +315, 1091, 464, 887, 473, 539, 328, 73, +135, -431, -70, -826, -262, -1008, -365, -1000, +-368, -807, -315, -457, -184, -38, 6, 315, +174, 534, 291, 614, 373, 589, 361, 449, +251, 245, 115, 54, -40, -88, -242, -185, +-380, -196, -377, -156, -287, -93, -168, -22, +-11, 21, 149, -4, 243, -38, 233, -85, +147, -175, 39, -244, -77, -212, -187, -142, +-203, -78, -80, 18, 86, 163, 205, 285, +318, 348, 407, 378, 370, 389, 198, 330, +-6, 207, -203, 60, -394, -91, -544, -265, +-584, -428, -524, -553, -412, -615, -238, -602, +17, -496, 301, -297, 548, 20, 704, 397, +743, 736, 662, 936, 471, 930, 164, 703, +-197, 312, -474, -175, -605, -591, -650, -796, +-589, -758, -391, -529, -141, -169, 73, 180, +247, 388, 379, 418, 442, 312, 395, 124, +247, -61, 58, -198, -112, -270, -286, -287, +-426, -258, -411, -219, -231, -159, -4, -36, +239, 178, 471, 425, 579, 646, 491, 760, +279, 691, 24, 412, -239, 6, -466, -444, +-582, -814, -544, -988, -390, -926, -220, -677, +-53, -299, 150, 101, 323, 434, 381, 658, +404, 757, 425, 701, 357, 543, 205, 317, +69, 37, -71, -247, -252, -443, -398, -528, +-452, -485, -460, -332, -407, -101, -256, 120, +-40, 252, 188, 253, 407, 172, 564, 39, +607, -101, 517, -190, 299, -196, -7, -154, +-299, -76, -510, 10, -614, 102, -565, 188, +-344, 263, -57, 330, 196, 383, 390, 343, +481, 186, 406, -48, 205, -287, -35, -499, +-257, -612, -402, -559, -398, -349, -262, -79, +-46, 170, 231, 341, 483, 405, 562, 342, +468, 199, 264, 42, -45, -69, -386, -148, +-582, -207, -585, -217, -462, -139, -232, -9, +67, 153, 289, 356, 389, 562, 393, 640, +295, 533, 147, 252, 59, -172, -9, -660, +-113, -1046, -191, -1214, -225, -1113, -279, -764, +-295, -238, -192, 336, -8, 839, 206, 1169, +420, 1272, 534, 1141, 490, 855, 307, 458, +11, -14, -315, -462, -521, -794, -577, -999, +-518, -1029, -337, -865, -70, -563, 156, -208, +305, 139, 391, 395, 384, 538, 293, 565, +193, 484, 70, 343, -102, 217, -265, 96, +-347, -18, -333, -107, -216, -153, -12, -147, +225, -80, 419, 6, 516, 95, 455, 148, +213, 113, -148, -43, -503, -259, -748, -474, +-807, -609, -644, -594, -293, -384, 139, -24, +550, 389, 854, 717, 967, 896, 833, 871, +486, 629, 31, 244, -386, -153, -684, -488, +-840, -678, -808, -693, -563, -557, -229, -327, +80, -66, 349, 137, 538, 262, 562, 290, +484, 220, 403, 94, 288, 5, 92, -33, +-129, -31, -343, -3, -529, 62, -634, 111, +-620, 87, -465, 26, -137, 9, 290, 11, +652, 25, 851, 81, 848, 151, 576, 130, +104, 2, -365, -189, -705, -380, -870, -517, +-780, -516, -443, -347, 0, -41, 393, 296, +639, 555, 679, 657, 535, 581, 266, 350, +-62, 56, -335, -221, -458, -399, -463, -448, +-376, -377, -166, -240, 86, -70, 241, 97, +317, 231, 356, 296, 305, 311, 158, 271, +13, 162, -126, -16, -287, -186, -374, -326, +-344, -434, -289, -446, -198, -333, -8, -175, +207, 10, 351, 204, 450, 360, 497, 444, +410, 466, 208, 416, -14, 308, -232, 156, +-412, -12, -489, -177, -465, -293, -365, -342, +-188, -311, 12, -229, 161, -132, 261, -81, +320, -92, 300, -150, 221, -218, 140, -265, +49, -209, -50, -34, -96, 214, -98, 474, +-84, 695, -25, 774, 52, 680, 56, 452, +12, 134, -17, -234, -73, -543, -179, -735, +-232, -796, -203, -711, -143, -477, -48, -176, +93, 133, 205, 388, 263, 548, 285, 563, +271, 431, 208, 204, 96, -28, -59, -224, +-224, -335, -350, -333, -401, -225, -381, -66, +-269, 94, -61, 214, 194, 306, 431, 342, +585, 302, 577, 208, 392, 94, 103, -67, +-208, -251, -491, -410, -665, -491, -665, -467, +-504, -345, -246, -177, 61, 29, 353, 223, +553, 351, 604, 398, 527, 402, 386, 371, +205, 297, -36, 172, -271, 26, -405, -164, +-442, -391, -429, -580, -328, -625, -141, -508, +42, -239, 191, 126, 313, 491, 349, 717, +282, 728, 168, 511, 32, 160, -101, -193, +-163, -445, -167, -528, -155, -395, -111, -153, +-16, 45, 65, 131, 89, 112, 75, -13, +45, -192, 3, -324, -38, -298, -80, -120, +-107, 126, -104, 364, -64, 548, 15, 595, +132, 498, 240, 286, 304, 23, 295, -219, +206, -393, 48, -497, -135, -483, -318, -379, +-467, -235, -517, -87, -416, 55, -234, 144, +-56, 179, 132, 160, 329, 114, 448, 94, +467, 126, 465, 166, 444, 220, 297, 258, +63, 218, -145, 80, -352, -100, -579, -299, +-692, -462, -613, -517, -417, -415, -164, -207, +151, 33, 438, 245, 574, 398, 560, 435, +456, 367, 288, 248, 94, 124, -81, 9, +-189, -58, -228, -105, -251, -167, -279, -247, +-272, -328, -227, -403, -172, -408, -97, -318, +18, -145, 127, 96, 211, 363, 267, 571, +269, 682, 230, 648, 205, 480, 147, 229, +21, -41, -92, -303, -151, -512, -219, -632, +-279, -635, -243, -543, -130, -388, -37, -190, +46, 32, 132, 229, 156, 397, 89, 507, +-4, 527, -61, 459, -67, 338, -40, 167, +15, -24, 77, -192, 105, -292, 78, -326, +35, -292, 14, -193, 17, -53, 42, 51, +115, 86, 192, 66, 191, 14, 88, -93, +-73, -212, -264, -282, -446, -253, -553, -140, +-527, 25, -380, 209, -148, 400, 131, 520, +403, 541, 607, 471, 709, 310, 691, 68, +554, -172, 319, -384, 12, -546, -328, -619, +-616, -590, -784, -478, -815, -266, -694, -9, +-405, 231, -23, 441, 347, 600, 654, 639, +826, 547, 783, 343, 554, 75, 203, -223, +-192, -492, -538, -654, -747, -639, -770, -483, +-578, -234, -221, 73, 179, 390, 513, 617, +719, 683, 709, 582, 481, 393, 151, 132, +-189, -189, -496, -478, -649, -641, -581, -695, +-364, -615, -81, -385, 226, -61, 471, 267, +586, 548, 563, 687, 399, 635, 97, 404, +-236, 63, -500, -295, -672, -522, -713, -545, +-556, -365, -243, -55, 122, 280, 462, 505, +711, 525, 768, 312, 615, -40, 346, -396, +53, -627, -210, -655, -380, -457, -445, -110, +-414, 272, -311, 554, -197, 691, -124, 660, +-67, 465, 7, 175, 81, -90, 154, -319, +245, -511, 289, -624, 229, -638, 114, -583, +-12, -431, -151, -176, -264, 146, -301, 466, +-236, 729, -88, 874, 85, 861, 228, 665, +341, 342, 404, -41, 376, -411, 246, -683, +60, -792, -167, -772, -409, -628, -592, -373, +-661, -82, -594, 163, -386, 345, -89, 432, +237, 430, 536, 362, 732, 250, 741, 125, +574, 44, 318, -3, 17, -28, -302, -31, +-538, -27, -618, -44, -547, -64, -377, -88, +-130, -114, 156, -145, 392, -167, 497, -187, +458, -190, 292, -162, 51, -71, -203, 58, +-398, 203, -464, 351, -364, 458, -172, 434, +31, 288, 225, 56, 359, -211, 336, -446, +173, -569, -11, -550, -146, -385, -233, -126, +-230, 150, -121, 388, 46, 548, 205, 569, +301, 471, 304, 293, 222, 48, 52, -234, +-164, -460, -323, -577, -370, -561, -361, -408, +-292, -127, -114, 193, 95, 456, 199, 572, +214, 497, 176, 244, 77, -88, -32, -408, +-67, -606, -25, -581, 68, -332, 178, 15, +269, 366, 291, 630, 211, 721, 14, 596, +-221, 320, -384, -28, -443, -346, -413, -571, +-268, -653, -60, -573, 113, -356, 224, -92, +280, 173, 240, 381, 122, 463, -1, 383, +-76, 186, -100, -72, -59, -305, 11, -442, +64, -410, 112, -188, 166, 156, 147, 487, +40, 723, -61, 769, -123, 564, -201, 163, +-259, -301, -217, -706, -109, -930, -29, -919, +46, -687, 136, -289, 184, 157, 155, 486, +94, 646, 25, 646, -29, 505, -60, 272, +-74, 60, -48, -69, 22, -98, 69, -70, +63, -34, 52, -36, 23, -105, -72, -255, +-156, -423, -181, -527, -191, -492, -157, -310, +-31, -8, 105, 354, 195, 687, 266, 863, +287, 828, 198, 606, 67, 257, -38, -143, +-144, -466, -224, -659, -217, -721, -178, -663, +-149, -526, -116, -384, -95, -236, -108, -71, +-112, 117, -68, 328, 27, 571, 171, 788, +358, 897, 512, 843, 559, 623, 469, 238, +236, -231, -102, -669, -444, -986, -714, -1119, +-838, -1007, -748, -690, -452, -248, -59, 229, +324, 634, 605, 875, 702, 929, 585, 778, +314, 460, -16, 77, -285, -270, -421, -515, +-405, -593, -249, -508, 6, -309, 242, -71, +357, 125, 333, 210, 215, 182, 36, 68, +-166, -70, -324, -162, -368, -159, -324, -68, +-246, 103, -145, 301, -18, 456, 79, 509, +128, 452, 185, 287, 269, 34, 322, -279, +309, -568, 236, -769, 117, -861, -37, -822, +-216, -591, -369, -214, -404, 210, -334, 612, +-222, 934, -82, 1077, 83, 1012, 189, 748, +195, 353, 164, -81, 148, -459, 129, -721, +108, -821, 85, -757, 47, -558, -24, -307, +-146, -61, -287, 141, -364, 263, -352, 272, +-247, 212, -37, 145, 215, 98, 401, 80, +488, 124, 452, 215, 275, 299, 9, 321, +-235, 266, -411, 117, -486, -104, -423, -342, +-259, -516, -64, -589, 132, -550, 270, -407, +316, -170, 288, 98, 200, 320, 59, 457, +-64, 524, -135, 506, -174, 406, -180, 252, +-122, 89, -29, -72, 50, -199, 97, -282, +108, -334, 76, -360, 18, -357, -57, -363, +-136, -356, -198, -296, -220, -171, -196, 11, +-119, 268, 26, 560, 231, 809, 405, 926, +484, 853, 480, 578, 376, 158, 117, -338, +-231, -800, -532, -1104, -723, -1169, -787, -1002, +-662, -644, -369, -184, -9, 282, 331, 655, +588, 882, 695, 944, 663, 842, 525, 600, +315, 294, 86, -20, -115, -293, -298, -489, +-442, -578, -501, -566, -480, -459, -411, -298, +-271, -131, -79, 17, 96, 135, 227, 189, +310, 194, 305, 175, 213, 132, 88, 58, +-6, -6, -51, -28, -27, 10, 42, 100, +112, 233, 153, 366, 148, 450, 59, 406, +-101, 199, -281, -153, -425, -566, -495, -932, +-468, -1126, -327, -1059, -78, -705, 202, -145, +437, 496, 593, 1056, 650, 1388, 557, 1403, +321, 1122, 28, 615, -248, 15, -494, -544, +-651, -950, -654, -1157, -512, -1144, -294, -936, +-38, -590, 229, -196, 454, 191, 548, 523, +491, 756, 327, 848, 107, 799, -129, 614, +-298, 349, -343, 77, -279, -164, -156, -357, +2, -454, 137, -466, 177, -447, 107, -414, +-16, -355, -138, -278, -197, -166, -167, -4, +-71, 208, 23, 431, 82, 614, 97, 684, +57, 617, -31, 418, -96, 114, -87, -237, +0, -519, 140, -665, 291, -657, 374, -514, +329, -268, 155, 3, -91, 215, -367, 327, +-597, 348, -717, 280, -675, 167, -461, 70, +-115, 37, 268, 48, 611, 92, 842, 130, +889, 129, 716, 67, 370, -63, -72, -242, +-514, -398, -821, -484, -893, -463, -747, -332, +-429, -113, -20, 148, 353, 395, 581, 560, +627, 616, 482, 565, 199, 418, -100, 183, +-308, -86, -411, -335, -382, -533, -216, -668, +8, -683, 190, -552, 301, -298, 322, 28, +216, 371, 7, 639, -202, 759, -347, 700, +-400, 465, -344, 104, -169, -257, 75, -523, +303, -624, 434, -546, 425, -322, 286, -31, +74, 240, -157, 415, -335, 453, -404, 354, +-363, 164, -259, -71, -124, -285, 3, -437, +92, -488, 146, -425, 195, -256, 227, -11, +247, 282, 266, 547, 241, 712, 118, 726, +-63, 575, -247, 276, -406, -106, -512, -494, +-486, -780, -324, -888, -106, -801, 104, -563, +281, -216, 391, 154, 410, 469, 338, 680, +221, 760, 83, 697, -46, 515, -136, 240, +-185, -74, -217, -372, -235, -587, -233, -671, +-207, -598, -165, -371, -100, -33, -29, 307, +32, 556, 87, 639, 135, 520, 169, 225, +192, -136, 188, -450, 157, -626, 119, -603, +86, -374, 18, -39, -93, 289, -199, 510, +-281, 562, -351, 435, -363, 189, -287, -91, +-146, -312, 18, -406, 189, -358, 332, -209, +388, -12, 334, 167, 217, 283, 69, 310, +-66, 257, -144, 145, -166, 5, -166, -140, +-152, -265, -132, -359, -133, -391, -140, -346, +-107, -232, -48, -51, 23, 188, 115, 412, +187, 561, 183, 597, 112, 493, 8, 261, +-101, -31, -169, -316, -148, -527, -71, -613, +33, -551, 129, -384, 152, -159, 86, 74, +-15, 276, -118, 398, -189, 433, -193, 396, +-116, 308, -3, 169, 111, 5, 194, -154, +191, -267, 95, -318, -47, -303, -201, -220, +-328, -81, -379, 58, -298, 142, -117, 145, +109, 85, 350, -22, 544, -123, 592, -176, +468, -150, 217, -36, -105, 137, -437, 297, +-662, 402, -708, 429, -584, 353, -338, 175, +-46, -54, 195, -280, 354, -460, 406, -568, +356, -565, 263, -459, 190, -285, 131, -65, +80, 178, 46, 374, -8, 497, -132, 548, +-272, 522, -381, 414, -438, 256, -408, 66, +-284, -123, -111, -286, 77, -418, 241, -495, +344, -484, 362, -399, 320, -255, 229, -71, +117, 129, 10, 291, -73, 384, -137, 399, +-199, 355, -242, 269, -227, 171, -191, 72, +-167, -12, -129, -92, -64, -180, -9, -281, +22, -380, 53, -449, 85, -447, 94, -353, +104, -151, 142, 124, 209, 409, 258, 642, +242, 768, 173, 727, 66, 525, -109, 213, +-333, -149, -524, -491, -619, -730, -608, -828, +-472, -763, -206, -561, 128, -276, 428, 39, +622, 333, 687, 537, 637, 622, 462, 601, +196, 509, -76, 364, -309, 196, -493, 43, +-590, -91, -578, -221, -468, -337, -284, -438, +-62, -512, 133, -531, 287, -463, 385, -312, +365, -88, 241, 174, 110, 422, -6, 588, +-108, 650, -163, 602, -138, 458, -88, 244, +-60, 10, -32, -205, 8, -371, 26, -488, +22, -550, 15, -551, 14, -476, -20, -332, +-91, -123, -163, 115, -210, 348, -207, 539, +-127, 639, 8, 610, 157, 472, 263, 253, +296, 5, 235, -230, 111, -406, -35, -478, +-176, -441, -253, -348, -239, -221, -189, -77, +-108, 46, -11, 111, 53, 129, 68, 123, +81, 108, 87, 86, 56, 79, 13, 98, +-9, 137, -53, 172, -104, 194, -126, 188, +-110, 139, -53, 38, 31, -97, 98, -241, +117, -366, 72, -451, -8, -453, -98, -361, +-160, -184, -169, 41, -124, 282, -31, 492, +84, 616, 190, 610, 249, 478, 214, 242, +108, -44, -37, -328, -184, -559, -296, -675, +-350, -637, -340, -478, -253, -229, -109, 72, +58, 365, 208, 568, 326, 632, 366, 550, +321, 356, 239, 91, 118, -171, -53, -358, +-212, -417, -321, -345, -391, -191, -428, -21, +-380, 117, -233, 163, -34, 98, 176, -30, +377, -162, 521, -253, 549, -247, 422, -142, +187, 22, -100, 196, -384, 338, -600, 401, +-688, 377, -613, 276, -399, 137, -122, -11, +168, -144, 428, -248, 603, -313, 626, -329, +504, -295, 305, -218, 62, -96, -202, 52, +-412, 181, -516, 252, -488, 256, -354, 188, +-161, 60, 36, -93, 173, -202, 194, -228, +109, -169, -13, -45, -106, 108, -170, 243, +-169, 322, -67, 306, 95, 202, 250, 58, +366, -90, 412, -220, 360, -287, 211, -277, +18, -218, -189, -140, -389, -55, -545, 16, +-607, 55, -555, 62, -401, 64, -168, 69, +112, 69, 354, 73, 507, 91, 535, 103, +433, 102, 244, 87, 40, 69, -135, 47, +-248, 15, -274, -32, -216, -86, -126, -142, +-19, -188, 66, -213, 87, -193, 57, -123, +0, -16, -93, 94, -191, 186, -263, 228, +-284, 204, -245, 123, -123, 19, 64, -71, +250, -105, 386, -82, 446, -20, 395, 45, +235, 82, 6, 59, -206, -21, -350, -121, +-411, -197, -375, -216, -256, -153, -122, -38, +-6, 89, 78, 198, 131, 261, 139, 252, +124, 194, 102, 112, 73, 35, 52, -31, +32, -105, -10, -192, -37, -265, -48, -321, +-65, -342, -93, -291, -109, -131, -113, 105, +-112, 347, -89, 530, -50, 602, -17, 514, +29, 272, 59, -58, 61, -374, 50, -588, +28, -636, -4, -513, -19, -247, 17, 77, +88, 355, 124, 505, 109, 499, 53, 359, +-33, 139, -145, -104, -246, -290, -294, -366, +-295, -326, -260, -210, -156, -63, -19, 71, +99, 167, 185, 196, 245, 165, 280, 110, +290, 53, 267, 1, 193, -24, 62, -31, +-81, -33, -234, -44, -365, -54, -426, -66, +-412, -79, -317, -82, -142, -52, 60, -5, +244, 45, 362, 95, 387, 140, 301, 154, +123, 128, -100, 55, -310, -37, -435, -138, +-418, -225, -274, -260, -34, -213, 234, -95, +442, 68, 504, 218, 407, 311, 202, 320, +-60, 236, -332, 73, -497, -99, -497, -223, +-374, -264, -206, -217, -13, -97, 158, 33, +222, 118, 175, 136, 100, 97, 42, 13, +15, -86, 5, -155, 31, -162, 77, -125, +97, -78, 68, -24, 14, 69, -44, 167, +-119, 244, -194, 326, -203, 396, -154, 377, +-85, 237, -10, -3, 58, -293, 95, -580, +86, -776, 32, -796, -42, -603, -110, -251, +-142, 167, -134, 539, -84, 775, 5, 823, +102, 682, 178, 410, 218, 117, 197, -125, +141, -278, 60, -340, -35, -333, -124, -304, +-205, -285, -292, -293, -361, -303, -368, -281, +-290, -198, -150, -47, 47, 155, 255, 364, +411, 523, 475, 577, 432, 517, 278, 342, +42, 91, -208, -164, -374, -355, -419, -457, +-360, -447, -223, -330, -45, -142, 102, 47, +169, 180, 171, 234, 124, 214, 18, 114, +-94, -30, -162, -163, -176, -236, -144, -241, +-75, -177, 24, -53, 147, 114, 254, 270, +305, 366, 287, 384, 213, 332, 52, 214, +-169, 48, -361, -126, -483, -258, -530, -332, +-458, -342, -272, -296, -20, -215, 227, -128, +426, -55, 524, -10, 488, 20, 335, 43, +122, 67, -97, 106, -256, 174, -329, 244, +-307, 300, -217, 332, -89, 334, 25, 281, +64, 164, 15, -1, -75, -189, -181, -393, +-247, -578, -209, -690, -54, -677, 146, -540, +320, -299, 438, 16, 467, 363, 362, 655, +143, 818, -117, 831, -327, 718, -457, 485, +-505, 171, -452, -152, -311, -427, -161, -638, +-48, -756, 63, -752, 196, -619, 294, -383, +357, -76, 410, 243, 429, 514, 364, 670, +198, 670, -31, 514, -268, 258, -484, -20, +-625, -234, -655, -338, -556, -328, -356, -240, +-105, -123, 152, -39, 372, -18, 516, -53, +564, -96, 503, -91, 381, -11, 227, 115, +39, 245, -146, 325, -281, 318, -363, 201, +-398, 7, -388, -181, -331, -295, -252, -329, +-160, -284, -67, -173, 30, -43, 138, 41, +236, 76, 297, 88, 340, 109, 338, 139, +266, 181, 137, 218, -7, 233, -147, 186, +-273, 72, -357, -72, -361, -208, -290, -317, +-175, -352, -56, -309, 68, -216, 161, -101, +186, 28, 176, 144, 155, 231, 102, 280, +33, 292, -34, 255, -95, 173, -149, 55, +-171, -67, -164, -165, -137, -214, -77, -211, +3, -168, 72, -115, 137, -64, 175, -39, +169, -37, 125, -26, 63, 32, 2, 131, +-45, 242, -84, 330, -126, 358, -174, 267, +-214, 61, -252, -197, -254, -424, -182, -555, +-61, -542, 77, -375, 222, -102, 341, 189, +386, 413, 319, 511, 170, 477, -12, 332, +-177, 130, -272, -63, -265, -192, -185, -240, +-93, -204, -26, -117, 8, -28, -26, 19, +-109, 19, -170, -39, -171, -136, -105, -222, +40, -244, 228, -184, 371, -38, 411, 157, +361, 343, 223, 454, 17, 453, -219, 322, +-417, 95, -515, -151, -506, -328, -420, -408, +-242, -380, -1, -250, 226, -70, 388, 78, +490, 154, 508, 168, 405, 149, 197, 103, +-41, 51, -257, 19, -400, 10, -451, -15, +-399, -53, -269, -90, -111, -115, 31, -126, +135, -101, 184, -40, 186, 39, 158, 111, +114, 175, 60, 217, 20, 226, -15, 198, +-59, 136, -101, 26, -119, -130, -120, -309, +-90, -452, -34, -513, 25, -442, 70, -237, +99, 72, 97, 406, 69, 668, 35, 760, +-7, 646, -65, 349, -126, -51, -183, -450, +-220, -736, -217, -823, -167, -685, -60, -382, +102, 3, 254, 379, 344, 658, 351, 761, +266, 675, 81, 439, -139, 120, -309, -216, +-370, -482, -305, -620, -134, -603, 76, -461, +251, -234, 299, 14, 197, 213, 1, 324, +-219, 364, -403, 340, -467, 281, -359, 212, +-118, 144, 162, 61, 406, -48, 539, -183, +512, -311, 344, -392, 109, -395, -125, -304, +-300, -121, -387, 103, -366, 286, -265, 365, +-148, 340, -77, 229, -44, 76, -25, -67, +-6, -141, 33, -133, 115, -61, 213, 19, +286, 74, 299, 87, 251, 51, 140, -35, +-35, -138, -241, -220, -398, -265, -464, -278, +-428, -236, -300, -128, -100, 37, 121, 222, +321, 397, 461, 522, 498, 553, 420, 458, +244, 256, -12, -12, -275, -284, -454, -496, +-505, -596, -442, -578, -276, -464, -34, -293, +202, -92, 327, 99, 330, 251, 241, 357, +98, 427, -67, 437, -172, 378, -156, 257, +-55, 104, 44, -61, 120, -200, 154, -287, +109, -295, -25, -239, -168, -154, -250, -87, +-259, -42, -208, -25, -89, -28, 80, -36, +229, -12, 296, 47, 293, 120, 223, 183, +80, 220, -99, 218, -245, 177, -330, 96, +-338, -4, -261, -106, -104, -199, 71, -277, +203, -307, 249, -282, 218, -202, 132, -74, +22, 95, -71, 259, -94, 363, -48, 375, +35, 313, 104, 182, 123, 13, 71, -147, +-46, -247, -197, -288, -309, -282, -319, -242, +-242, -180, -127, -119, 22, -60, 178, 3, +269, 84, 267, 181, 232, 272, 193, 331, +138, 349, 64, 314, 5, 213, -47, 44, +-123, -158, -234, -353, -320, -503, -336, -583, +-285, -550, -171, -385, 25, -113, 244, 209, +404, 510, 456, 702, 401, 729, 240, 573, +11, 283, -236, -67, -427, -380, -498, -582, +-415, -629, -216, -530, 46, -328, 294, -95, +451, 115, 467, 254, 340, 320, 112, 323, +-129, 274, -319, 179, -401, 59, -337, -63, +-145, -151, 77, -194, 252, -177, 330, -94, +281, 30, 112, 133, -103, 168, -298, 113, +-397, -12, -360, -172, -199, -298, 37, -325, +294, -225, 476, -40, 507, 171, 390, 336, +170, 390, -118, 304, -385, 118, -536, -100, +-525, -275, -379, -359, -142, -319, 121, -180, +341, 5, 437, 176, 396, 299, 253, 340, +72, 295, -96, 176, -197, 17, -212, -155, +-157, -301, -72, -396, 13, -415, 56, -350, +45, -198, -17, -10, -100, 162, -159, 286, +-147, 352, -71, 344, 40, 277, 159, 180, +270, 96, 336, 29, 330, -27, 236, -92, +80, -168, -96, -263, -257, -349, -364, -393, +-360, -369, -265, -269, -135, -92, 6, 119, +142, 318, 206, 460, 187, 510, 134, 441, +91, 279, 65, 69, 74, -140, 104, -321, +128, -438, 108, -469, 29, -403, -91, -268, +-201, -93, -268, 90, -254, 263, -147, 389, +15, 447, 163, 415, 259, 292, 261, 90, +164, -144, 16, -369, -123, -533, -224, -588, +-246, -491, -175, -258, -50, 54, 65, 358, +150, 572, 193, 613, 191, 469, 151, 197, +103, -104, 71, -350, 46, -458, -1, -400, +-51, -213, -111, -3, -195, 136, -279, 147, +-300, 46, -247, -108, -136, -224, 22, -233, +209, -103, 359, 121, 430, 356, 415, 495, +323, 472, 162, 285, -33, 3, -210, -282, +-307, -475, -326, -523, -289, -425, -203, -251, +-78, -67, 23, 58, 89, 100, 142, 74, +184, 38, 203, 34, 208, 101, 203, 221, +177, 353, 104, 427, 1, 392, -93, 232, +-174, -20, -237, -319, -231, -583, -137, -726, +2, -697, 127, -516, 224, -221, 266, 116, +240, 413, 156, 590, 42, 619, -79, 492, +-173, 255, -220, -15, -207, -242, -141, -374, +-28, -386, 92, -298, 187, -134, 245, 45, +272, 186, 248, 244, 160, 208, 31, 93, +-91, -70, -193, -240, -270, -360, -290, -400, +-227, -342, -117, -191, 9, 24, 139, 249, +253, 429, 295, 506, 259, 471, 176, 336, +74, 140, -39, -87, -130, -291, -154, -430, +-115, -484, -61, -476, 6, -417, 70, -312, +91, -162, 55, 15, -6, 212, -74, 396, +-113, 530, -95, 563, -24, 475, 65, 275, +171, 4, 258, -276, 282, -484, 238, -572, +157, -516, 50, -353, -68, -139, -173, 55, +-222, 185, -215, 230, -176, 200, -124, 120, +-36, 40, 73, -20, 161, -45, 213, -36, +244, -3, 233, 38, 180, 81, 110, 112, +65, 108, 46, 48, 41, -47, 33, -163, +28, -273, 14, -348, -32, -344, -109, -252, +-174, -88, -230, 93, -269, 241, -244, 307, +-144, 283, -8, 180, 156, 54, 333, -45, +489, -85, 577, -72, 585, -27, 494, 2, +316, -9, 58, -75, -255, -174, -556, -264, +-751, -297, -822, -263, -746, -165, -499, -33, +-118, 100, 290, 200, 646, 263, 874, 274, +920, 245, 767, 184, 475, 101, 121, -5, +-202, -124, -431, -251, -525, -345, -494, -376, +-365, -330, -199, -223, -49, -66, 49, 94, +94, 215, 107, 253, 114, 213, 119, 116, +154, -9, 214, -126, 254, -182, 257, -169, +251, -100, 209, -2, 124, 109, 22, 192, +-63, 224, -138, 175, -197, 51, -230, -126, +-234, -301, -206, -435, -120, -481, 16, -420, +181, -254, 322, -28, 403, 203, 406, 367, +320, 434, 167, 396, 24, 281, -72, 131, +-114, -1, -112, -98, -53, -158, 16, -198, +33, -234, -20, -285, -84, -324, -127, -336, +-125, -293, -49, -183, 107, -3, 273, 190, +379, 335, 395, 388, 305, 344, 112, 202, +-104, -1, -265, -207, -327, -335, -280, -359, +-114, -273, 106, -111, 282, 79, 356, 225, +313, 288, 167, 246, -26, 106, -201, -96, +-281, -285, -241, -408, -108, -426, 54, -339, +210, -174, 312, 8, 317, 159, 224, 232, +91, 225, -34, 152, -103, 66, -109, 2, +-53, -8, 40, 19, 129, 65, 166, 88, +142, 65, 56, -16, -59, -125, -152, -240, +-180, -330, -143, -376, -33, -355, 118, -285, +260, -185, 359, -71, 417, 64, 390, 196, +282, 312, 143, 382, 3, 398, -143, 346, +-246, 235, -276, 72, -247, -108, -184, -275, +-85, -392, 32, -461, 145, -475, 223, -441, +274, -363, 323, -252, 370, -100, 369, 83, +331, 281, 266, 440, 147, 513, -42, 471, +-232, 317, -368, 72, -426, -187, -389, -383, +-241, -455, -37, -400, 166, -245, 327, -70, +434, 52, 458, 81, 393, 28, 276, -81, +152, -182, 26, -216, -75, -154, -131, -26, +-151, 124, -163, 238, -143, 283, -88, 233, +-24, 110, 44, -50, 124, -202, 168, -320, +171, -379, 163, -375, 152, -297, 113, -163, +77, 13, 64, 200, 51, 364, 16, 455, +-21, 439, -44, 285, -40, 26, -12, -277, +62, -547, 172, -723, 269, -746, 300, -607, +253, -327, 135, 12, -26, 334, -185, 564, +-263, 671, -227, 638, -99, 493, 79, 266, +273, 5, 416, -250, 444, -450, 343, -586, +181, -635, 5, -594, -136, -467, -207, -288, +-180, -81, -58, 114, 112, 272, 253, 363, +338, 378, 353, 327, 278, 241, 113, 132, +-60, 26, -174, -66, -216, -130, -193, -168, +-111, -190, 11, -221, 147, -254, 255, -280, +321, -289, 335, -279, 304, -225, 234, -129, +148, 0, 59, 124, -22, 222, -85, 264, +-117, 247, -134, 179, -127, 95, -88, 9, +-24, -56, 44, -101, 113, -130, 160, -171, +189, -220, 208, -275, 205, -311, 160, -307, +125, -233, 116, -95, 89, 73, 42, 216, +31, 294, 38, 273, 23, 164, -12, -6, +-20, -185, -11, -313, -11, -340, -29, -268, +-23, -125, 19, 23, 80, 142, 153, 199, +259, 186, 342, 108, 360, 3, 320, -103, +235, -183, 98, -232, -49, -239, -155, -226, +-199, -208, -186, -188, -108, -154, 1, -109, +108, -43, 184, 31, 246, 115, 291, 192, +300, 249, 264, 256, 223, 212, 179, 106, +128, -30, 86, -165, 65, -275, 32, -353, +-20, -372, -63, -341, -93, -282, -137, -220, +-153, -159, -107, -106, -7, -40, 137, 48, +323, 164, 494, 285, 593, 383, 584, 412, +462, 346, 225, 171, -66, -75, -331, -343, +-498, -564, -533, -678, -426, -633, -200, -456, +92, -195, 348, 84, 507, 319, 536, 441, +435, 430, 239, 294, 20, 85, -146, -140, +-207, -321, -158, -423, -10, -415, 186, -311, +367, -132, 451, 73, 409, 244, 240, 322, +-9, 302, -248, 192, -381, 22, -400, -173, +-300, -333, -103, -432, 130, -449, 301, -395, +385, -284, 391, -149, 348, 4, 288, 148, +254, 273, 243, 357, 244, 386, 214, 329, +139, 190, 27, -16, -99, -240, -211, -441, +-265, -565, -242, -576, -144, -454, -2, -247, +156, -15, 276, 178, 341, 296, 357, 310, +342, 241, 315, 119, 282, -10, 228, -111, +180, -155, 120, -156, 23, -132, -83, -117, +-137, -112, -142, -114, -110, -111, -26, -114, +87, -108, 167, -93, 218, -83, 234, -84, +192, -73, 118, -60, 79, -37, 90, 7, +136, 80, 182, 158, 206, 203, 186, 178, +116, 77, 0, -94, -101, -288, -152, -465, +-156, -568, -106, -554, 24, -403, 186, -156, +322, 127, 386, 371, 368, 531, 272, 559, +137, 460, -7, 258, -117, 6, -158, -253, +-125, -462, -52, -594, 44, -637, 131, -604, +192, -493, 223, -311, 225, -79, 192, 161, +154, 376, 113, 519, 73, 562, 36, 492, +25, 333, 29, 100, 60, -150, 118, -362, +167, -485, 191, -520, 217, -477, 210, -385, +161, -268, 104, -163, 73, -77, 42, -28, +-6, 0, -40, 26, -30, 67, 2, 122, +54, 201, 135, 282, 264, 352, 391, 382, +453, 341, 426, 191, 314, -57, 120, -380, +-120, -707, -336, -958, -426, -1051, -364, -945, +-182, -626, 91, -150, 416, 384, 674, 844, +755, 1118, 649, 1136, 421, 910, 104, 493, +-217, -12, -435, -493, -497, -846, -431, -1018, +-267, -987, -40, -803, 194, -524, 364, -210, +448, 91, 452, 325, 387, 476, 269, 531, +154, 494, 76, 375, 44, 209, 51, 11, +83, -177, 93, -326, 57, -402, -37, -404, +-158, -333, -263, -226, -301, -117, -244, -35, +-70, 11, 191, 16, 457, -7, 631, -49, +684, -72, 589, -59, 376, -12, 122, 41, +-114, 80, -275, 88, -290, 70, -196, 23, +-71, -43, 51, -126, 165, -196, 199, -247, +135, -268, 69, -271, 57, -249, 73, -194, +125, -94, 228, 37, 358, 186, 433, 316, +417, 387, 330, 358, 197, 226, 32, -8, +-115, -293, -208, -558, -242, -725, -221, -745, +-129, -595, 10, -316, 152, 20, 277, 334, +372, 569, 407, 669, 391, 618, 329, 431, +247, 171, 158, -105, 77, -346, 2, -530, +-59, -625, -96, -628, -111, -539, -115, -385, +-91, -192, -48, -3, 24, 160, 118, 271, +212, 320, 290, 303, 357, 241, 368, 147, +294, 49, 178, -38, 71, -101, -48, -148, +-137, -182, -135, -208, -52, -205, 62, -190, +177, -176, 257, -170, 259, -168, 155, -185, +6, -206, -121, -223, -180, -207, -158, -143, +-38, -6, 164, 184, 366, 385, 485, 528, +513, 573, 440, 479, 273, 244, 51, -103, +-144, -477, -244, -795, -237, -967, -160, -949, +-26, -728, 136, -372, 267, 36, 311, 411, +289, 680, 235, 778, 161, 706, 87, 492, +61, 203, 74, -103, 102, -355, 117, -525, +120, -601, 105, -586, 74, -476, 47, -314, +52, -135, 100, 31, 195, 173, 302, 266, +380, 293, 381, 239, 286, 128, 92, -13, +-155, -142, -369, -235, -474, -262, -442, -223, +-251, -123, 51, 1, 381, 106, 643, 146, +776, 108, 743, -8, 564, -159, 297, -299, +18, -383, -214, -395, -339, -314, -377, -158, +-344, 51, -257, 246, -145, 378, -25, 416, +112, 352, 244, 191, 336, -23, 388, -257, +427, -457, 406, -577, 307, -577, 181, -468, +61, -277, -53, -49, -130, 178, -136, 353, +-67, 444, 18, 424, 86, 308, 134, 123, +152, -79, 121, -265, 67, -401, 27, -468, +22, -446, 51, -351, 123, -204, 197, -47, +253, 96, 290, 188, 294, 219, 239, 193, +150, 123, 58, 14, -14, -94, -61, -168, +-67, -187, -31, -168, 51, -116, 148, -46, +213, 24, 235, 55, 238, 39, 197, -28, +118, -122, 43, -223, 0, -286, -13, -291, +20, -235, 90, -127, 163, 30, 220, 182, +251, 284, 221, 296, 151, 217, 72, 67, +6, -106, -44, -258, -58, -346, -21, -349, +65, -268, 149, -133, 194, 9, 190, 99, +166, 120, 117, 68, 54, -23, 13, -116, +11, -170, 24, -180, 52, -133, 98, -45, +161, 57, 199, 118, 201, 118, 188, 60, +151, -21, 70, -106, -31, -170, -110, -203, +-150, -190, -154, -145, -86, -86, 39, -35, +182, -4, 308, 2, 397, 10, 415, 23, +354, 37, 232, 39, 101, 25, -17, -14, +-101, -74, -136, -154, -122, -231, -77, -288, +-19, -283, 32, -204, 69, -65, 92, 88, +124, 222, 170, 294, 231, 289, 306, 196, +367, 39, 372, -143, 320, -293, 225, -377, +105, -370, -40, -300, -168, -188, -231, -69, +-213, 38, -152, 98, -58, 105, 76, 74, +215, 34, 288, 1, 311, -4, 315, 9, +276, 25, 185, 21, 111, -1, 86, -47, +77, -107, 53, -176, 45, -221, 49, -228, +46, -185, 22, -111, 9, -33, 14, 15, +15, 31, 9, 16, 30, -16, 67, -54, +103, -62, 138, -29, 191, 42, 226, 120, +230, 166, 196, 139, 137, 45, 67, -98, +-4, -254, -82, -386, -122, -440, -95, -392, +-33, -248, 36, -55, 121, 143, 204, 290, +251, 350, 245, 317, 219, 214, 173, 56, +123, -114, 63, -263, 12, -350, -6, -367, +-7, -317, -25, -226, -47, -104, -42, 21, +-9, 131, 32, 198, 97, 208, 184, 154, +276, 66, 346, -30, 383, -105, 364, -157, +292, -172, 173, -154, 36, -115, -105, -85, +-241, -79, -339, -106, -354, -135, -280, -145, +-133, -118, 60, -56, 295, 39, 503, 141, +625, 221, 635, 241, 557, 195, 393, 85, +152, -55, -99, -188, -272, -276, -358, -317, +-367, -312, -300, -277, -154, -212, 12, -140, +146, -71, 228, -6, 283, 67, 300, 146, +296, 227, 281, 272, 262, 261, 229, 179, +173, 48, 99, -108, 16, -256, -68, -364, +-134, -392, -182, -336, -179, -221, -127, -91, +-55, 27, 8, 94, 85, 107, 180, 85, +257, 57, 299, 27, 318, 12, 295, 13, +217, 23, 106, 16, 5, -11, -66, -64, +-100, -120, -101, -156, -39, -154, 58, -130, +122, -96, 133, -65, 127, -48, 99, -50, +36, -59, -10, -62, 5, -39, 52, 12, +114, 85, 176, 141, 225, 147, 218, 89, +163, -9, 100, -131, 75, -236, 72, -292, +67, -266, 77, -175, 98, -56, 79, 52, +4, 124, -74, 127, -109, 77, -109, 11, +-51, -42, 67, -80, 213, -95, 327, -91, +387, -77, 381, -77, 318, -81, 203, -78, +61, -56, -48, -14, -100, 52, -120, 108, +-117, 123, -110, 76, -102, -19, -94, -153, +-57, -286, -4, -380, 78, -384, 198, -287, +330, -102, 436, 117, 487, 326, 450, 467, +308, 505, 99, 420, -118, 223, -316, -52, +-450, -334, -478, -572, -378, -707, -206, -701, +6, -555, 234, -306, 436, 8, 552, 323, +565, 564, 498, 666, 354, 616, 141, 427, +-67, 155, -213, -138, -278, -381, -276, -524, +-191, -533, -55, -426, 76, -238, 155, -46, +179, 89, 148, 137, 71, 103, -5, 8, +-25, -98, 20, -169, 105, -154, 205, -54, +320, 100, 384, 248, 350, 341, 220, 334, +63, 228, -90, 46, -216, -155, -266, -334, +-224, -448, -119, -472, 13, -399, 144, -268, +249, -111, 296, 32, 299, 151, 252, 233, +175, 270, 94, 245, 31, 175, -33, 69, +-71, -48, -57, -160, -15, -234, 34, -253, +88, -198, 137, -85, 163, 54, 157, 157, +137, 186, 99, 124, 63, 1, 19, -157, +-13, -295, -28, -373, -40, -352, -49, -237, +-38, -57, -1, 131, 34, 277, 71, 338, +136, 318, 197, 228, 232, 95, 233, -52, +214, -172, 146, -241, 57, -252, -18, -236, +-57, -197, -61, -155, -44, -110, -6, -65, +39, -15, 58, 25, 34, 63, -17, 95, +-58, 117, -87, 107, -68, 67, 1, 2, +109, -62, 227, -118, 325, -141, 376, -131, +368, -88, 305, -32, 193, 30, 67, 74, +-44, 89, -143, 60, -221, -4, -266, -91, +-269, -172, -251, -236, -189, -274, -80, -272, +71, -205, 259, -80, 447, 85, 583, 249, +638, 384, 595, 454, 436, 429, 182, 291, +-90, 70, -336, -194, -504, -438, -572, -605, +-516, -658, -366, -598, -160, -431, 68, -191, +290, 80, 478, 320, 583, 497, 587, 585, +511, 578, 361, 465, 159, 270, -46, 15, +-195, -256, -301, -491, -347, -627, -301, -647, +-172, -543, -19, -344, 110, -88, 208, 160, +259, 343, 247, 414, 180, 380, 101, 264, +51, 120, 15, -13, 6, -101, 21, -139, +55, -131, 72, -110, 79, -91, 84, -101, +61, -131, 24, -174, 5, -195, 9, -176, +16, -110, 26, -23, 48, 74, 43, 156, +14, 202, -24, 189, -47, 134, -50, 49, +-9, -37, 80, -103, 191, -126, 303, -119, +374, -99, 365, -86, 273, -75, 114, -85, +-68, -109, -242, -134, -341, -126, -341, -83, +-227, -5, -56, 84, 113, 158, 256, 189, +342, 176, 340, 112, 257, 13, 153, -101, +62, -188, -17, -224, -56, -204, -52, -149, +-15, -73, 7, 1, 21, 58, 33, 78, +48, 71, 63, 39, 89, 0, 133, -41, +157, -68, 137, -85, 82, -90, 1, -98, +-100, -93, -180, -68, -170, -24, -92, 25, +42, 80, 218, 126, 385, 150, 472, 121, +440, 43, 299, -67, 79, -173, -155, -249, +-345, -263, -457, -211, -453, -107, -344, 5, +-158, 101, 57, 142, 265, 111, 410, 22, +476, -72, 466, -133, 381, -133, 254, -70, +108, 39, -41, 143, -172, 203, -255, 196, +-275, 123, -260, -5, -185, -148, -61, -262, +76, -314, 176, -307, 235, -254, 256, -177, +245, -81, 208, 21, 149, 113, 93, 181, +46, 232, 2, 254, -12, 244, -2, 191, +19, 101, 20, -20, 20, -142, -3, -245, +-51, -305, -103, -327, -142, -307, -146, -256, +-102, -172, 9, -76, 168, 23, 334, 121, +467, 221, 515, 296, 471, 330, 304, 304, +44, 220, -229, 75, -418, -96, -496, -258, +-465, -370, -304, -422, -58, -394, 199, -292, +403, -134, 510, 28, 499, 163, 367, 243, +164, 267, -58, 227, -223, 141, -301, 32, +-290, -69, -197, -138, -39, -156, 141, -134, +275, -82, 343, -28, 337, 15, 244, 25, +84, -6, -112, -72, -275, -144, -358, -197, +-321, -196, -193, -125, 3, 5, 227, 144, +411, 258, 511, 309, 501, 275, 367, 143, +122, -54, -142, -260, -330, -398, -422, -432, +-386, -350, -231, -174, 11, 57, 238, 263, +378, 382, 411, 375, 341, 251, 171, 41, +-57, -177, -224, -337, -279, -394, -259, -350, +-169, -215, 1, -37, 195, 138, 300, 252, +320, 283, 284, 238, 204, 146, 88, 27, +-27, -83, -98, -162, -130, -201, -126, -214, +-87, -194, -12, -150, 64, -91, 91, -38, +106, 19, 121, 79, 124, 124, 93, 134, +61, 117, 29, 78, -4, 29, -15, -31, +-9, -80, 12, -111, 48, -112, 79, -89, +85, -46, 72, -7, 58, 14, 14, 7, +-28, -14, -48, -44, -54, -74, -66, -101, +-60, -104, -5, -81, 70, -36, 130, 9, +157, 55, 174, 94, 191, 123, 167, 135, +125, 137, 74, 115, 6, 63, -106, -27, +-188, -126, -194, -230, -160, -315, -95, -357, +12, -317, 152, -196, 252, -29, 275, 135, +239, 263, 157, 316, 44, 286, -91, 187, +-174, 67, -178, -44, -117, -109, -14, -113, +110, -67, 196, -21, 178, -6, 97, -39, +11, -104, -60, -186, -98, -246, -88, -257, +-15, -202, 81, -97, 178, 35, 231, 150, +229, 223, 167, 239, 52, 218, -64, 174, +-136, 127, -138, 76, -98, 28, -27, -25, +69, -89, 143, -173, 160, -263, 107, -345, +43, -376, -12, -336, -60, -223, -99, -64, +-95, 113, -27, 267, 61, 367, 138, 385, +189, 330, 202, 211, 163, 73, 79, -49, +5, -134, -57, -185, -103, -199, -136, -197, +-117, -195, -47, -200, 26, -198, 77, -189, +113, -160, 140, -97, 124, 8, 86, 121, +72, 211, 62, 269, 49, 298, 49, 281, +70, 221, 51, 127, -2, 21, -55, -88, +-104, -187, -150, -276, -185, -342, -168, -384, +-86, -381, 41, -319, 165, -194, 253, -34, +311, 144, 295, 308, 225, 430, 134, 474, +42, 425, -59, 288, -142, 100, -178, -105, +-178, -273, -152, -380, -119, -404, -87, -359, +-34, -260, 42, -139, 132, -23, 208, 52, +286, 93, 331, 116, 315, 137, 228, 147, +88, 148, -64, 141, -192, 116, -276, 54, +-305, -28, -267, -112, -185, -166, -88, -182, +47, -146, 175, -75, 251, 5, 260, 48, +240, 48, 189, 5, 116, -63, 47, -134, +-22, -164, -74, -131, -91, -36, -65, 87, +-10, 206, 42, 268, 74, 254, 67, 160, +35, 21, -49, -134, -139, -260, -162, -321, +-116, -290, -31, -187, 86, -46, 226, 87, +316, 185, 327, 219, 275, 188, 147, 93, +-38, -24, -229, -132, -346, -192, -368, -190, +-292, -122, -151, -27, 14, 65, 167, 131, +271, 157, 325, 125, 317, 55, 243, -36, +130, -107, 11, -146, -95, -153, -192, -137, +-227, -98, -193, -50, -108, 4, -8, 59, +106, 114, 212, 149, 263, 165, 258, 148, +194, 96, 70, -1, -88, -122, -229, -234, +-296, -296, -287, -296, -195, -228, -62, -106, +89, 48, 214, 190, 296, 291, 329, 319, +304, 274, 221, 166, 106, 42, -5, -76, +-119, -172, -230, -245, -294, -272, -316, -254, +-288, -201, -205, -131, -45, -44, 145, 47, +320, 133, 450, 196, 484, 231, 404, 211, +233, 141, 23, 40, -176, -56, -323, -130, +-379, -169, -342, -169, -211, -118, -51, -42, +104, 25, 217, 54, 249, 55, 189, 29, +80, -11, -26, -53, -119, -80, -171, -92, +-156, -83, -83, -62, 41, -20, 175, 27, +296, 75, 355, 117, 334, 163, 212, 183, +15, 156, -193, 79, -377, -28, -484, -151, +-473, -252, -352, -298, -152, -266, 97, -175, +354, -37, 524, 105, 583, 205, 521, 219, +349, 157, 107, 52, -124, -49, -297, -120, +-404, -132, -428, -81, -381, 18, -276, 119, +-131, 184, 16, 181, 150, 115, 249, 3, +300, -113, 278, -204, 226, -245, 157, -240, +71, -188, -5, -107, -58, -18, -88, 47, +-93, 91, -53, 120, -3, 146, 10, 165, +-5, 178, -50, 171, -105, 141, -152, 74, +-138, -14, -70, -113, 26, -204, 123, -268, +211, -273, 282, -216, 289, -114, 231, -7, +143, 88, 28, 148, -113, 165, -251, 134, +-329, 74, -360, 8, -335, -33, -247, -40, +-111, -12, 53, 29, 235, 64, 405, 83, +501, 84, 493, 51, 372, -3, 158, -68, +-88, -127, -320, -173, -467, -191, -503, -185, +-417, -151, -245, -98, -11, -13, 225, 92, +374, 199, 422, 269, 373, 299, 233, 278, +38, 201, -139, 66, -253, -92, -308, -233, +-272, -322, -161, -347, -18, -292, 100, -174, +190, -19, 233, 127, 193, 238, 88, 286, +-38, 264, -132, 170, -183, 43, -185, -82, +-116, -176, -5, -228, 108, -212, 186, -137, +237, -22, 226, 91, 136, 185, 2, 230, +-124, 208, -211, 115, -257, -12, -244, -148, +-168, -256, -52, -299, 79, -237, 183, -92, +260, 87, 290, 246, 270, 352, 185, 360, +55, 261, -98, 76, -247, -130, -350, -306, +-390, -400, -355, -392, -247, -281, -84, -107, +106, 82, 288, 244, 427, 355, 454, 388, +379, 339, 243, 223, 79, 76, -98, -81, +-240, -229, -316, -342, -346, -378, -319, -330, +-234, -209, -115, -47, 18, 122, 130, 248, +224, 301, 276, 275, 275, 190, 207, 63, +118, -63, 25, -143, -85, -147, -184, -100, +-224, -29, -197, 35, -135, 77, -47, 79, +48, 46, 91, -8, 76, -58, 19, -97, +-33, -112, -72, -103, -88, -70, -72, -30, +-9, 24, 88, 89, 168, 163, 222, 215, +237, 228, 186, 186, 72, 93, -78, -38, +-219, -176, -331, -287, -364, -331, -322, -285, +-207, -151, -40, 24, 139, 197, 288, 318, +383, 362, 392, 307, 286, 174, 106, -1, +-81, -166, -240, -280, -323, -313, -324, -269, +-246, -160, -130, -25, -2, 109, 99, 207, +157, 257, 170, 243, 123, 185, 52, 102, +3, 21, -22, -55, -36, -121, -32, -170, +3, -185, 23, -171, 11, -119, -20, -42, +-27, 48, -14, 120, -12, 167, -13, 174, +-11, 139, -18, 63, -47, -24, -61, -86, +-46, -102, -44, -84, -50, -34, -29, 31, +27, 91, 68, 115, 84, 96, 84, 39, +69, -30, 34, -90, -7, -109, -30, -96, +-50, -57, -78, -12, -108, 36, -133, 74, +-140, 90, -133, 72, -77, 44, 26, 20, +146, 7, 242, -4, 289, -6, 270, -5, +174, -1, 22, 1, -157, 11, -314, 26, +-389, 41, -362, 46, -245, 54, -85, 57, +88, 33, 203, -27, 235, -90, 216, -143, +179, -169, 109, -162, 18, -108, -34, -9, +-49, 123, -71, 246, -103, 325, -131, 327, +-150, 251, -180, 115, -182, -31, -124, -157, +-5, -242, 115, -272, 202, -234, 253, -161, +235, -82, 141, -20, 19, 31, -78, 72, +-143, 116, -178, 159, -160, 201, -111, 225, +-48, 221, 1, 172, 24, 88, 8, -27, +-42, -144, -90, -230, -99, -253, -51, -215, +25, -139, 98, -50, 154, 44, 165, 118, +134, 161, 67, 166, -14, 146, -107, 113, +-178, 80, -205, 50, -184, 34, -116, 18, +-30, -8, 29, -49, 55, -97, 58, -147, +40, -174, 20, -162, 34, -92, 58, 16, +79, 133, 88, 224, 81, 274, 47, 269, +-16, 209, -105, 101, -202, -27, -265, -139, +-269, -196, -212, -200, -102, -157, 27, -95, +144, -39, 213, -8, 234, 5, 204, 13, +140, 34, 47, 78, -53, 152, -131, 237, +-179, 296, -200, 287, -184, 199, -131, 45, +-65, -129, -16, -281, 27, -373, 62, -382, +89, -292, 103, -128, 110, 70, 93, 236, +51, 329, 2, 331, -54, 262, -114, 153, +-164, 34, -177, -76, -140, -137, -71, -139, +12, -82, 79, -2, 120, 69, 111, 108, +65, 115, 3, 76, -73, 1, -148, -80, +-188, -139, -172, -166, -112, -147, -15, -91, +100, -9, 187, 76, 226, 161, 214, 240, +158, 288, 43, 272, -104, 197, -239, 82, +-325, -44, -353, -158, -306, -229, -187, -247, +-34, -215, 114, -152, 241, -62, 313, 39, +318, 132, 255, 196, 153, 238, 14, 246, +-139, 202, -267, 106, -336, -4, -349, -101, +-314, -164, -228, -192, -110, -170, 10, -105, +125, -8, 228, 91, 297, 173, 300, 215, +241, 222, 139, 181, 21, 106, -106, 15, +-226, -76, -319, -157, -367, -197, -349, -188, +-260, -138, -114, -69, 59, 14, 215, 97, +326, 171, 356, 216, 297, 233, 168, 217, +10, 168, -156, 88, -293, -1, -362, -92, +-358, -170, -285, -221, -146, -218, 25, -167, +168, -82, 244, 19, 255, 125, 208, 211, +124, 254, 0, 238, -129, 169, -223, 63, +-254, -39, -220, -116, -127, -140, -9, -116, +82, -53, 128, 21, 133, 91, 104, 127, +52, 117, -22, 69, -97, 14, -157, -38, +-183, -74, -180, -95, -140, -86, -60, -41, +35, 38, 113, 121, 159, 189, 161, 214, +120, 191, 47, 122, -50, 29, -166, -69, +-256, -153, -284, -201, -240, -193, -136, -132, +11, -34, 138, 76, 194, 177, 176, 235, +101, 235, -4, 177, -90, 83, -135, -17, +-135, -80, -102, -93, -41, -55, 19, -2, +57, 43, 46, 51, -9, 20, -81, -41, +-152, -99, -192, -120, -169, -81, -87, 14, +16, 143, 101, 254, 158, 312, 160, 288, +96, 188, -7, 32, -99, -126, -168, -230, +-212, -261, -210, -238, -159, -169, -79, -72, +14, 34, 103, 122, 160, 191, 158, 244, +106, 283, 30, 280, -43, 228, -126, 123, +-200, -16, -240, -167, -235, -277, -184, -314, +-88, -262, 39, -143, 158, 13, 231, 164, +243, 267, 186, 288, 80, 239, -58, 143, +-189, 33, -283, -63, -318, -106, -307, -91, +-245, -40, -133, 12, 11, 62, 144, 100, +236, 112, 270, 86, 228, 34, 126, -33, +9, -89, -118, -123, -240, -121, -327, -75, +-342, 7, -274, 102, -133, 194, 33, 249, +168, 242, 240, 168, 232, 57, 149, -48, +31, -118, -98, -153, -208, -143, -262, -92, +-247, -8, -191, 77, -99, 130, 5, 134, +91, 101, 149, 42, 169, -5, 119, -23, +16, -15, -97, 10, -200, 55, -270, 89, +-277, 87, -218, 44, -107, -8, 19, -37, +133, -29, 196, 5, 192, 59, 138, 114, +61, 151, -27, 150, -126, 105, -218, 10, +-260, -102, -242, -188, -190, -210, -121, -163, +-30, -58, 46, 77, 109, 210, 161, 289, +171, 297, 104, 236, -11, 136, -140, 21, +-252, -90, -292, -171, -231, -182, -109, -126, +18, -36, 103, 49, 136, 101, 119, 104, +57, 80, -39, 43, -123, 17, -179, 10, +-207, 27, -186, 58, -121, 92, -45, 103, +20, 87, 60, 52, 66, 10, 43, -24, +13, -40, -27, -41, -77, -16, -119, 29, +-125, 75, -111, 93, -91, 67, -52, 15, +-3, -20, 23, -23, 12, 7, -29, 50, +-82, 79, -130, 85, -154, 71, -147, 36, +-102, 1, -49, -20, -4, -12, 42, 21, +73, 65, 76, 92, 57, 95, -1, 72, +-99, 30, -185, -25, -217, -67, -201, -70, +-149, -20, -88, 48, -31, 112, 9, 147, +38, 136, 52, 79, 56, 1, 55, -65, +49, -76, 20, -49, -31, 0, -95, 50, +-162, 89, -234, 110, -288, 126, -296, 114, +-246, 68, -152, -1, -15, -59, 141, -76, +269, -60, 315, -34, 277, 18, 190, 93, +61, 161, -107, 194, -263, 176, -394, 98, +-496, -8, -531, -117, -452, -188, -277, -190, +-41, -129, 198, -23, 380, 110, 465, 218, +438, 277, 308, 281, 122, 244, -82, 186, +-271, 104, -408, -17, -450, -145, -411, -252, +-323, -305, -229, -287, -144, -200, -65, -70, +6, 80, 60, 211, 104, 307, 152, 352, +187, 337, 173, 285, 121, 220, 62, 134, +-15, 34, -118, -74, -198, -171, -263, -244, +-333, -295, -379, -316, -366, -266, -309, -152, +-217, 9, -84, 186, 82, 340, 251, 437, +385, 456, 439, 384, 394, 247, 222, 73, +-42, -97, -309, -215, -505, -262, -614, -256, +-606, -196, -478, -101, -273, 4, -35, 92, +193, 140, 355, 154, 407, 154, 349, 127, +208, 91, 14, 66, -179, 47, -325, 35, +-402, 39, -400, 54, -308, 84, -153, 109, +6, 104, 124, 70, 165, 12, 113, -66, +3, -137, -122, -190, -213, -203, -244, -157, +-224, -52, -161, 103, -56, 279, 49, 418, +115, 479, 146, 436, 126, 278, 37, 37, +-78, -221, -192, -425, -296, -505, -356, -449, +-357, -273, -313, -21, -215, 232, -72, 410, +92, 485, 232, 453, 297, 348, 262, 209, +149, 55, -12, -97, -182, -217, -312, -296, +-380, -309, -392, -251, -353, -131, -266, 24, +-131, 170, 21, 265, 152, 315, 226, 309, +218, 244, 128, 138, -7, 13, -145, -103, +-255, -172, -305, -187, -304, -131, -273, -16, +-194, 109, -72, 207, 57, 257, 140, 233, +142, 154, 63, 36, -37, -91, -119, -193, +-179, -254, -217, -251, -241, -150, -253, 9, +-219, 175, -130, 306, -14, 381, 79, 387, +104, 326, 59, 207, -6, 76, -56, -52, +-79, -177, -86, -267, -99, -293, -131, -265, +-175, -181, -206, -70, -201, 47, -177, 160, +-155, 240, -136, 287, -115, 318, -92, 307, +-36, 251, 33, 162, 70, 38, 58, -104, +11, -219, -48, -269, -83, -221, -98, -107, +-118, 17, -140, 139, -163, 242, -203, 282, +-229, 245, -230, 131, -205, -24, -152, -158, +-93, -232, -55, -214, -14, -95, 42, 65, +91, 211, 113, 301, 79, 312, -27, 252, +-160, 149, -261, 33, -289, -54, -240, -114, +-148, -142, -71, -116, -41, -43, -48, 40, +-67, 114, -103, 142, -168, 120, -227, 68, +-236, -3, -180, -68, -70, -104, 47, -119, +123, -88, 122, 3, 40, 129, -79, 255, +-161, 351, -192, 389, -193, 372, -164, 280, +-120, 124, -91, -48, -77, -210, -90, -352, +-135, -443, -179, -469, -194, -393, -198, -212, +-174, 21, -115, 248, -42, 428, 15, 529, +38, 561, 28, 526, 10, 427, -3, 278, +-20, 99, -57, -90, -120, -257, -209, -400, +-290, -479, -341, -458, -340, -349, -280, -190, +-174, -20, -45, 120, 84, 252, 177, 372, +198, 446, 129, 461, -11, 416, -165, 308, +-293, 175, -370, 32, -355, -99, -272, -190, +-185, -245, -109, -272, -31, -245, 30, -186, +77, -109, 96, -18, 64, 75, 7, 159, +-57, 232, -128, 276, -197, 303, -282, 301, +-372, 247, -416, 156, -393, 47, -311, -72, +-158, -168, 30, -221, 177, -215, 245, -156, +230, -79, 142, 13, 24, 131, -79, 229, +-150, 283, -215, 287, -286, 233, -335, 142, +-329, 46, -286, -41, -232, -80, -189, -100, +-164, -128, -127, -130, -72, -89, -18, -24, +24, 45, 55, 97, 61, 146, 42, 188, +15, 195, -22, 182, -59, 173, -106, 157, +-171, 141, -228, 110, -275, 39, -313, -52, +-312, -135, -274, -186, -243, -188, -218, -176, +-171, -159, -107, -104, -31, -11, 59, 99, +162, 227, 252, 363, 274, 493, 186, 554, +2, 474, -229, 265, -433, -13, -543, -293, +-561, -485, -513, -549, -387, -486, -201, -306, +2, -56, 167, 199, 246, 407, 215, 495, +103, 458, -31, 343, -109, 183, -139, 11, +-179, -122, -226, -188, -251, -161, -256, -63, +-233, 54, -188, 148, -144, 181, -113, 134, +-102, 52, -121, -31, -128, -99, -101, -135, +-69, -132, -55, -83, -61, 22, -70, 135, +-60, 231, -43, 302, -41, 325, -54, 291, +-99, 201, -200, 49, -295, -107, -324, -218, +-281, -263, -206, -229, -148, -133, -124, -17, +-96, 101, -45, 199, 16, 261, 55, 276, +36, 231, -21, 146, -80, 68, -132, 9, +-161, -26, -179, -44, -220, -61, -273, -68, +-289, -53, -252, -33, -177, -11, -98, -1, +-42, 20, 11, 96, 34, 212, -14, 301, +-93, 316, -158, 237, -193, 102, -191, -49, +-161, -188, -123, -267, -70, -235, -32, -120, +-56, 30, -130, 151, -219, 200, -290, 185, +-298, 133, -227, 80, -112, 80, -7, 126, +46, 190, 25, 240, -42, 213, -132, 68, +-211, -155, -250, -370, -245, -465, -203, -381, +-125, -137, -35, 203, 37, 522, 53, 670, +2, 595, -94, 341, -193, 19, -277, -245, +-333, -375, -366, -357, -362, -218, -280, -52, +-115, 76, 73, 153, 226, 183, 285, 180, +209, 180, 32, 185, -177, 193, -374, 162, +-501, 71, -525, -44, -432, -134, -239, -181, +-17, -158, 143, -69, 210, 58, 166, 180, +25, 239, -149, 208, -292, 113, -362, -8, +-335, -80, -253, -55, -163, 39, -73, 142, +18, 204, 82, 191, 93, 115, 35, -4, +-66, -123, -176, -182, -274, -155, -326, -64, +-315, 74, -269, 210, -214, 297, -170, 291, +-142, 173, -117, -1, -84, -138, -53, -204, +-5, -182, 46, -87, 47, 54, 3, 212, +-46, 350, -83, 402, -116, 336, -172, 162, +-253, -57, -321, -236, -348, -330, -351, -321, +-316, -194, -254, 1, -193, 183, -127, 265, +-27, 220, 92, 123, 198, 78, 236, 102, +184, 164, 66, 196, -83, 158, -227, 64, +-338, -33, -421, -88, -460, -69, -439, -2, +-371, 61, -257, 76, -98, 16, 42, -109, +109, -214, 101, -225, 50, -95, 1, 132, +-37, 344, -93, 466, -154, 473, -191, 356, +-192, 158, -156, -60, -110, -237, -98, -322, +-126, -287, -200, -151, -294, 30, -322, 169, +-263, 220, -190, 188, -131, 103, -55, 4, +52, -58, 153, -54, 194, 20, 150, 121, +27, 203, -177, 247, -403, 231, -539, 122, +-540, -49, -438, -204, -269, -255, -74, -174, +94, -3, 196, 181, 216, 322, 151, 348, +27, 238, -106, 43, -199, -153, -239, -263, +-242, -228, -218, -68, -201, 141, -232, 289, +-293, 312, -347, 227, -369, 65, -313, -129, +-158, -255, 36, -235, 215, -71, 329, 149, +351, 315, 273, 367, 102, 320, -133, 196, +-365, 56, -544, -56, -635, -134, -600, -186, +-465, -204, -295, -198, -114, -163, 39, -98, +117, 4, 126, 151, 108, 306, 85, 401, +73, 415, 66, 348, 49, 231, -11, 103, +-135, -10, -273, -107, -361, -187, -406, -263, +-409, -314, -350, -304, -239, -220, -128, -63, +-54, 149, -31, 343, -40, 452, -53, 422, +-49, 268, -7, 75, 55, -66, 95, -105, +91, -30, 29, 107, -72, 208, -172, 187, +-266, 25, -372, -203, -427, -362, -391, -366, +-318, -190, -270, 85, -238, 325, -181, 412, +-57, 309, 137, 86, 334, -96, 439, -126, +373, 12, 124, 230, -199, 383, -484, 358, +-642, 153, -615, -149, -441, -395, -224, -462, +-38, -307, 61, -2, 57, 305, -11, 440, +-75, 342, -107, 82, -107, -184, -84, -311, +-16, -228, 73, 30, 92, 357, 0, 584, +-161, 581, -336, 333, -427, -59, -386, -432, +-248, -609, -81, -508, 29, -171, 16, 220, +-90, 462, -201, 459, -227, 255, -154, -34, +-49, -235, 9, -243, 22, -63, 5, 190, +-11, 375, 22, 399, 59, 269, -9, 52, +-196, -141, -401, -232, -518, -224, -507, -174, +-379, -101, -194, -8, -31, 99, 52, 192, +83, 252, 135, 265, 202, 224, 218, 119, +138, -20, -42, -143, -243, -186, -363, -125, +-368, 14, -312, 165, -276, 241, -281, 182, +-267, 28, -183, -122, -45, -174, 74, -78, +102, 123, 15, 299, -99, 345, -148, 212, +-104, -42, -1, -261, 83, -310, 68, -178, +-37, 68, -168, 284, -280, 344, -344, 222, +-355, 1, -344, -189, -309, -235, -226, -112, +-93, 113, 61, 314, 169, 370, 191, 245, +138, 37, 28, -129, -110, -187, -218, -151, +-243, -71, -207, 16, -152, 98, -119, 141, +-129, 127, -180, 78, -252, 42, -292, 39, +-266, 65, -207, 60, -109, -5, 44, -77, +205, -83, 282, 5, 199, 156, -20, 273, +-232, 297, -316, 218, -292, 65, -237, -101, +-181, -202, -166, -196, -180, -92, -184, 23, +-174, 58, -152, -16, -124, -127, -71, -157, +48, -30, 171, 214, 185, 466, 64, 581, +-111, 485, -250, 231, -275, -66, -212, -300, +-161, -394, -163, -351, -184, -196, -188, -19, +-169, 84, -154, 82, -129, 4, -67, -71, +11, -27, 78, 156, 106, 393, 29, 533, +-122, 471, -224, 240, -208, -25, -115, -237, +-62, -343, -129, -328, -242, -226, -267, -92, +-177, 25, -54, 71, -3, 65, -53, 69, +-114, 147, -117, 286, -82, 378, -31, 312, +7, 115, -12, -89, -64, -206, -112, -228, +-150, -185, -186, -105, -205, 27, -186, 160, +-130, 220, -76, 188, -51, 86, -54, -2, +-83, 2, -146, 49, -201, 76, -198, 59, +-115, 18, 31, -7, 170, -11, 203, -40, +86, -71, -131, -57, -339, 2, -451, 82, +-429, 154, -280, 194, -84, 210, 52, 176, +98, 88, 66, -24, -13, -131, -79, -178, +-89, -142, -62, -34, -19, 125, 17, 252, +5, 282, -88, 180, -219, -25, -331, -240, +-357, -331, -306, -255, -217, -75, -115, 123, +-18, 288, 81, 391, 170, 413, 188, 335, +111, 194, -13, 29, -107, -92, -186, -163, +-266, -238, -320, -315, -331, -359, -275, -316, +-148, -120, 1, 145, 100, 347, 101, 438, +47, 436, -41, 344, -162, 204, -275, 57, +-320, -86, -263, -172, -105, -174, 94, -151, +231, -101, 239, -29, 172, 47, 73, 119, +-69, 148, -292, 82, -561, -28, -723, -102, +-679, -122, -432, -79, -40, 28, 333, 148, +508, 263, 465, 319, 334, 278, 179, 173, +12, 53, -159, -43, -343, -112, -492, -154, +-552, -164, -505, -160, -352, -136, -160, -102, +12, -46, 155, 54, 255, 203, 263, 344, +183, 378, 38, 281, -168, 98, -360, -85, +-430, -171, -339, -187, -127, -144, 105, -50, +254, 50, 245, 115, 91, 132, -121, 90, +-298, 37, -394, 50, -386, 95, -294, 93, +-182, 29, -83, -96, 16, -167, 73, -133, +76, -44, 60, 84, 55, 200, 71, 253, +54, 250, -30, 171, -154, 37, -304, -108, +-396, -178, -335, -139, -153, -38, -1, 37, +66, 59, 74, 64, 8, 78, -85, 100, +-159, 106, -198, 73, -157, 21, -54, -47, +55, -69, 68, -26, -71, 29, -256, 81, +-319, 87, -207, 35, -23, -26, 127, -62, +189, -10, 148, 120, 51, 246, -105, 281, +-292, 194, -427, 5, -429, -200, -263, -306, +-12, -274, 142, -138, 121, 14, -1, 82, +-109, 117, -127, 175, -65, 245, -13, 295, +-19, 276, -54, 168, -62, 14, -30, -125, +-22, -225, -121, -268, -265, -252, -308, -202, +-186, -52, 22, 156, 167, 315, 145, 404, +-30, 372, -232, 214, -295, 9, -213, -190, +-141, -287, -153, -259, -173, -155, -132, -25, +0, 82, 166, 113, 279, 133, 283, 199, +156, 265, -62, 276, -279, 185, -431, 4, +-492, -154, -427, -272, -272, -308, -142, -236, +-52, -101, 37, 81, 145, 272, 217, 374, +209, 338, 143, 185, 30, 26, -82, -65, +-152, -85, -224, -83, -325, -93, -434, -129, +-455, -147, -296, -101, 12, 6, 279, 161, +355, 295, 235, 338, 23, 292, -139, 119, +-179, -92, -151, -213, -159, -226, -271, -132, +-402, -7, -391, 20, -178, -28, 109, -68, +291, -20, 305, 157, 216, 364, 64, 430, +-118, 319, -249, 48, -328, -273, -391, -441, +-387, -399, -278, -187, -87, 105, 131, 298, +298, 357, 341, 307, 206, 162, -78, -5, +-295, -118, -322, -160, -246, -129, -173, -49, +-162, 9, -236, 10, -277, -14, -156, -45, +91, -4, 304, 129, 317, 267, 134, 342, +-55, 326, -175, 168, -217, -92, -177, -303, +-132, -371, -134, -307, -198, -162, -266, -39, +-239, 62, -107, 182, 31, 295, 83, 359, +64, 325, -8, 180, -45, -10, 1, -170, +35, -237, -31, -227, -178, -156, -277, -24, +-220, 116, -49, 172, 99, 144, 92, 85, +-49, 57, -198, 102, -227, 147, -125, 100, +-36, 3, -61, -103, -143, -181, -214, -220, +-207, -220, -90, -153, 48, -14, 129, 169, +171, 351, 136, 435, 10, 391, -110, 243, +-196, 34, -253, -155, -218, -253, -134, -263, +-71, -171, -62, -58, -98, -55, -121, -107, +-105, -80, -79, 22, -67, 171, -60, 269, +-14, 247, 65, 173, 86, 102, -2, 1, +-118, -89, -204, -143, -167, -111, -32, 47, +8, 191, -57, 196, -120, 111, -118, 3, +-37, -39, 0, -38, -88, -105, -181, -183, +-164, -163, -97, -91, -35, -24, -72, -25, +-220, -83, -254, -19, -81, 231, 161, 477, +289, 562, 193, 422, -12, 159, -157, -50, +-150, -179, -55, -293, -76, -385, -221, -386, +-288, -268, -238, -107, -167, 27, -132, 98, +-143, 145, -149, 210, -50, 280, 111, 272, +216, 165, 177, 38, 6, -32, -71, -29, +33, 12, 96, 37, 0, 70, -249, 97, +-492, 77, -511, 5, -290, -91, -6, -195, +122, -255, 65, -235, 14, -164, 76, -56, +114, 69, 14, 158, -137, 258, -238, 332, +-200, 336, -92, 279, -20, 104, 17, -119, +-28, -200, -111, -130, -113, 24, -73, 144, +-42, 103, -3, -49, 31, -167, 22, -220, +-45, -198, -193, -149, -301, -94, -274, 36, +-215, 158, -172, 173, -130, 115, -35, 51, +184, 159, 390, 409, 431, 555, 236, 458, +-137, 104, -423, -349, -434, -648, -316, -713, +-244, -559, -254, -239, -281, 141, -183, 422, +73, 508, 315, 389, 433, 168, 317, -4, +-13, -7, -254, 89, -293, 85, -270, -41, +-230, -175, -189, -247, -135, -174, -84, -32, +-80, 102, -102, 202, -53, 183, 103, 101, +267, 72, 324, 67, 184, 27, -124, -64, +-422, -144, -556, -193, -444, -175, -216, -46, +-47, 115, 50, 189, 117, 174, 173, 127, +179, 109, 85, 104, -98, 43, -272, -47, +-300, -80, -163, -108, 25, -93, 87, -24, +-14, 53, -105, 183, -89, 242, -42, 132, +21, -50, 92, -250, 12, -289, -221, -105, +-407, 85, -465, 132, -370, 53, -112, -61, +207, -45, 416, 114, 409, 240, 183, 282, +-79, 258, -188, 140, -184, 16, -189, -101, +-235, -205, -294, -240, -262, -214, -125, -153, +34, -86, 119, -17, 83, 71, -38, 143, +-149, 179, -167, 119, -73, 57, 25, 83, +76, 166, 43, 248, -116, 234, -242, 88, +-158, -126, 43, -288, 147, -281, 61, -186, +-185, -97, -438, -45, -428, -27, -109, -10, +292, 75, 438, 249, 168, 386, -259, 383, +-453, 191, -275, -101, 61, -279, 199, -332, +26, -254, -294, -59, -431, 119, -217, 208, +135, 200, 292, 116, 183, -37, -39, -165, +-125, -124, 1, 11, 64, 160, -77, 242, +-255, 207, -369, 76, -317, -99, -114, -254, +13, -342, -16, -259, -51, 2, -40, 261, +2, 421, 88, 356, 118, 96, 74, -107, +33, -136, -53, -90, -194, -23, -306, 48, +-274, -12, -131, -129, 1, -145, 97, -107, +56, 70, -120, 269, -182, 287, -107, 181, +-16, -15, 19, -166, -74, -150, -198, -64, +-120, 4, 130, -13, 293, -53, 239, -6, +-72, 102, -448, 168, -493, 189, -293, 128, +-92, -12, 43, -81, 6, -142, -57, -165, +71, -34, 275, 49, 296, 96, 89, 127, +-155, 61, -334, 6, -348, -27, -204, -54, +-96, -15, -145, 64, -240, 137, -196, 158, +-58, 106, 65, -82, 134, -265, 122, -252, +100, -68, 73, 174, 67, 319, 107, 275, +54, 99, -143, -68, -341, -142, -421, -147, +-344, -32, -160, 33, -4, -11, 43, -19, +13, -70, -63, -97, -127, 10, -133, 137, +-84, 241, 26, 260, 166, 154, 287, -28, +313, -143, 176, -151, -25, -119, -242, -69, +-443, -68, -502, -104, -419, -59, -256, 87, +-51, 285, 102, 376, 110, 307, 28, 62, +-31, -239, -11, -347, 143, -276, 224, -119, +93, 59, -86, 129, -179, 82, -72, 5, +73, 14, -16, 76, -243, 183, -420, 266, +-393, 199, -150, 87, 130, -63, 208, -259, +26, -319, -208, -264, -276, -121, -96, 70, +173, 179, 310, 184, 273, 159, 37, 127, +-199, 127, -201, 144, -84, 16, -33, -201, +-138, -295, -364, -274, -490, -83, -310, 171, +124, 281, 447, 302, 393, 267, 57, 184, +-298, 87, -380, -80, -156, -297, 76, -462, +123, -435, 17, -241, -112, -9, -136, 200, +-5, 342, 136, 400, 146, 456, 2, 478, +-300, 288, -533, -60, -460, -375, -196, -637, +86, -650, 253, -373, 217, -42, 88, 310, +64, 548, 152, 475, 216, 262, 106, 15, +-164, -203, -430, -180, -565, 27, -489, 117, +-250, 60, 13, -92, 208, -289, 248, -286, +175, -62, 95, 171, 75, 320, 87, 292, +73, 141, -37, 7, -242, -100, -397, -161, +-364, -134, -140, -56, 87, 55, 95, 167, +-43, 172, -170, -13, -141, -235, 114, -263, +339, -39, 241, 231, -103, 310, -445, 200, +-482, -21, -110, -220, 281, -171, 317, 32, +62, 141, -245, 96, -320, -16, -77, -79, +182, -38, 118, 41, -187, 141, -400, 254, +-320, 198, -15, -76, 211, -283, 183, -349, +50, -272, -31, 11, -36, 246, -13, 208, +-28, 22, -127, -96, -175, 0, -28, 222, +79, 377, -34, 354, -167, 157, -227, -161, +-181, -413, -36, -411, 36, -236, -15, 20, +-111, 257, -97, 286, 100, 82, 273, -258, +242, -409, 35, -213, -172, 106, -309, 405, +-302, 555, -129, 396, 17, 42, 78, -201, +29, -175, -101, -8, -202, 122, -249, 61, +-120, -160, 80, -389, 183, -477, 224, -272, +160, 87, 19, 331, -108, 377, -212, 250, +-225, 101, -119, -32, -29, -51, -64, 109, +-122, 241, -155, 238, -84, 72, 163, -216, +328, -407, 226, -400, -60, -238, -393, -37, +-475, 136, -231, 220, 95, 253, 298, 254, +245, 116, -27, -57, -231, -168, -169, -169, +30, 48, 147, 240, 100, 204, -107, 14, +-297, -182, -284, -258, -67, -128, 103, 146, +35, 280, -123, 194, -186, -27, -49, -305, +225, -343, 376, -167, 258, 67, -63, 304, +-343, 346, -418, 192, -292, 41, -79, -27, +87, -61, 147, -87, 47, -72, -66, -79, +-72, -99, -33, -119, 54, -102, 83, -24, +49, 66, 14, 202, -49, 304, -114, 277, +-226, 154, -341, -35, -270, -135, -2, -198, +274, -237, 342, -186, 206, -131, -10, -15, +-155, 94, -151, 104, -113, 129, -113, 112, +-179, 93, -228, 158, -84, 206, 63, 156, +55, 36, 16, -165, 17, -354, 72, -349, +150, -222, 222, 5, 175, 311, -39, 425, +-205, 293, -280, -49, -356, -355, -431, -371, +-365, -227, -112, 76, 163, 395, 379, 416, +479, 252, 378, 26, 115, -187, -123, -224, +-123, -136, -42, -41, -116, 95, -297, 121, +-457, -46, -467, -125, -178, -110, 260, -137, +451, -88, 264, -34, -52, 18, -205, 113, +-107, 219, 130, 333, 249, 343, 94, 243, +-187, 146, -343, 19, -218, -169, 68, -367, +230, -486, 142, -504, -114, -381, -336, -173, +-333, 71, -118, 326, 131, 432, 222, 425, +93, 418, -114, 330, -155, 237, 23, 155, +285, -16, 409, -263, 216, -481, -164, -524, +-413, -348, -450, -151, -329, -99, -85, -130, +67, -129, 24, 22, -50, 350, -86, 623, +-17, 730, 185, 584, 389, 168, 426, -215, +227, -443, -122, -538, -403, -425, -427, -229, +-208, -17, 53, 154, 152, 154, -21, 79, +-327, 14, -418, -115, -124, -149, 293, 28, +457, 234, 281, 314, -43, 198, -276, -34, +-172, -116, 145, -27, 250, 118, 96, 210, +-128, 127, -245, -83, -147, -259, 17, -333, +53, -336, -91, -297, -215, -154, -189, 65, +-107, 261, -23, 373, 3, 388, 19, 320, +147, 227, 332, 83, 410, -132, 258, -292, +-8, -260, -267, -120, -409, -54, -350, -121, +-231, -238, -94, -271, 27, -41, -6, 353, +-50, 628, 20, 596, 144, 202, 250, -302, +284, -588, 216, -640, 16, -401, -201, 122, +-279, 564, -260, 588, -208, 278, -144, -118, +-44, -366, 64, -325, 174, -28, 261, 345, +205, 475, 54, 205, -145, -226, -293, -589, +-167, -760, 53, -585, 130, 24, 98, 735, +1, 987, -147, 712, -161, 199, 20, -346, +156, -668, 86, -605, -130, -180, -274, 300, +-175, 434, 23, 178, 153, -188, 167, -473, +100, -518, 35, -90, 67, 549, 168, 772, +119, 500, -144, 45, -388, -343, -385, -552, +-155, -525, 83, -261, 196, 125, 124, 401, +-41, 383, -98, 209, 27, 4, 248, -272, +291, -316, 46, -75, -189, 149, -257, 242, +-214, 190, -113, 71, 6, -77, 93, -286, +109, -318, 136, -77, 166, 170, 59, 253, +-201, 199, -411, -7, -254, -221, 122, -296, +359, -199, 348, 97, 89, 359, -235, 438, +-386, 420, -254, 110, 37, -426, 200, -759, +199, -631, 76, -87, -84, 489, -188, 723, +-163, 501, 104, -100, 426, -708, 455, -814, +137, -275, -319, 482, -608, 996, -566, 930, +-195, 218, 263, -687, 439, -1163, 219, -838, +-166, 56, -361, 800, -179, 914, 224, 381, +576, -381, 614, -888, 235, -802, -306, -98, +-584, 725, -449, 1062, -164, 722, -20, -67, +-42, -843, -88, -1076, 16, -553, 226, 253, +327, 788, 210, 762, 7, 205, -62, -340, +23, -482, 98, -323, 16, -7, -224, 279, +-377, 305, -269, 73, -34, -188, 160, -374, +267, -378, 250, -144, 198, 173, 186, 451, +113, 566, -89, 407, -350, 68, -536, -291, +-463, -509, -97, -561, 305, -376, 479, 47, +380, 407, 68, 463, -170, 240, -114, -136, +79, -415, 197, -376, 129, -43, -110, 352, +-284, 565, -252, 396, -121, -26, 1, -412, +94, -609, 148, -443, 130, 29, 40, 441, +-29, 534, -65, 254, -59, -213, 41, -543, +166, -530, 179, -227, 78, 235, -100, 610, +-307, 599, -320, 261, -34, -154, 298, -499, +474, -553, 355, -286, -67, 109, -495, 407, +-574, 444, -220, 173, 220, -221, 393, -486, +307, -535, 59, -310, -180, 198, -217, 629, +-22, 627, 199, 282, 234, -129, 144, -430, +38, -366, -113, -3, -258, 246, -260, 240, +-99, -12, -5, -386, 19, -540, 165, -467, +288, -238, 213, 222, 30, 677, -115, 749, +-160, 467, -117, 34, 62, -343, 204, -404, +96, -155, -148, 109, -303, 149, -239, -120, +-24, -475, 189, -638, 347, -442, 410, 37, +275, 481, -37, 685, -260, 551, -340, 144, +-343, -150, -116, -140, 216, 39, 299, 161, +122, -10, -82, -442, -131, -694, -36, -544, +78, -68, 104, 534, 42, 736, -37, 353, +-29, -202, 85, -617, 156, -559, 69, 37, +-49, 682, -23, 893, 101, 511, 119, -272, +12, -925, -176, -983, -389, -490, -409, 166, +-143, 660, 195, 706, 403, 338, 404, -100, +226, -367, 20, -416, -59, -235, -53, 107, +6, 348, 58, 291, -22, 18, -140, -293, +-160, -419, -81, -264, 37, 109, 128, 443, +198, 480, 144, 220, -55, -213, -247, -565, +-323, -645, -210, -434, 105, 81, 497, 612, +609, 799, 255, 551, -218, 17, -480, -499, +-373, -719, 62, -523, 478, -70, 534, 298, +170, 381, -337, 195, -601, -80, -438, -289, +0, -234, 341, 41, 380, 252, 100, 294, +-208, 131, -156, -177, 198, -391, 512, -370, +508, -54, 98, 327, -435, 462, -644, 287, +-388, -108, 65, -553, 418, -671, 473, -234, +153, 424, -256, 806, -392, 598, -213, -161, +148, -871, 497, -1040, 634, -499, 364, 485, +-224, 1120, -684, 948, -702, 258, -315, -469, +232, -888, 608, -781, 593, -215, 226, 380, +-179, 696, -305, 605, -161, 158, -6, -413, +73, -866, 127, -863, 167, -346, 181, 310, +164, 802, 47, 933, -219, 668, -437, 111, +-273, -535, 175, -945, 448, -882, 313, -434, +-22, 226, -274, 862, -297, 957, -42, 396, +326, -340, 412, -884, 155, -899, -31, -357, +54, 344, 139, 791, 48, 696, -122, 149, +-246, -439, -281, -722, -154, -551, 109, -63, +222, 465, 59, 670, -86, 458, -19, 42, +170, -340, 360, -478, 427, -332, 268, -66, +-71, 97, -384, 33, -395, -150, -82, -255, +260, -134, 341, 105, 167, 310, -116, 359, +-344, 183, -312, -52, -37, -206, 235, -255, +361, -142, 302, 83, 159, 267, 36, 237, +-99, 29, -189, -321, -88, -649, 120, -569, +222, -160, 189, 251, 142, 525, 27, 511, +-170, 259, -274, -24, -257, -240, -185, -336, +46, -194, 407, 36, 579, 193, 375, 285, +-66, 102, -451, -304, -417, -486, 45, -349, +502, -49, 572, 183, 177, 234, -378, 157, +-618, 0, -342, -128, 225, -82, 556, 76, +424, 145, 28, 105, -291, 59, -267, -37, +75, -146, 437, -230, 479, -198, 117, -64, +-357, 15, -565, 36, -365, 4, 27, -127, +347, -286, 467, -249, 362, 169, 155, 639, +34, 764, 16, 401, 6, -322, -51, -935, +-104, -979, -113, -356, -56, 447, 25, 774, +55, 504, 40, -128, 40, -624, 36, -613, +26, -205, 104, 355, 244, 785, 256, 662, +178, 19, 99, -565, -64, -805, -258, -656, +-274, -117, -111, 383, 97, 538, 315, 346, +464, 16, 352, -123, 37, -78, -231, 2, +-281, 38, -153, -29, 32, -161, 167, -337, +144, -386, 0, -257, -119, -88, -114, 83, +64, 260, 314, 356, 483, 300, 477, 181, +302, 121, 0, 75, -315, -25, -458, -183, +-368, -320, -117, -441, 163, -473, 291, -320, +228, -105, 6, 104, -180, 268, -37, 305, +389, 308, 658, 258, 489, 83, 11, -139, +-512, -219, -741, -141, -382, -12, 303, 78, +728, 29, 645, -95, 246, -203, -181, -275, +-461, -195, -428, -76, -52, -14, 349, 68, +506, 195, 367, 228, 18, 78, -323, -80, +-450, -143, -294, -175, 140, -124, 618, -2, +778, 112, 575, 145, 175, 138, -319, 130, +-666, 35, -622, -189, -224, -404, 211, -406, +436, -215, 447, -1, 273, 156, 9, 199, +-124, 132, -57, 6, 122, -3, 259, 151, +274, 202, 235, 19, 147, -236, -57, -388, +-226, -359, -264, -145, -262, 197, -152, 395, +143, 256, 431, -110, 498, -357, 298, -320, +-24, -137, -222, 176, -174, 431, 27, 243, +302, -192, 518, -490, 428, -452, 41, -53, +-346, 388, -522, 525, -406, 315, -13, -217, +454, -742, 646, -693, 402, -129, -8, 452, +-259, 788, -306, 659, -153, 32, 98, -698, +310, -964, 448, -639, 423, 1, 254, 667, +114, 950, -53, 609, -234, -112, -231, -788, +-122, -970, -34, -591, 79, 60, 127, 615, +69, 698, -8, 307, -7, -164, 148, -417, +390, -363, 494, -120, 344, 75, 75, 158, +-50, 208, 0, 139, 42, 19, 12, -95, +-85, -309, -246, -455, -282, -343, -80, -69, +204, 216, 356, 364, 315, 320, 178, 75, +97, -229, 106, -386, 108, -290, 137, -4, +237, 272, 238, 356, 169, 214, 157, -32, +86, -255, -131, -351, -376, -212, -470, -70, +-284, -78, 59, -131, 344, -153, 522, -36, +571, 169, 424, 329, 184, 390, -19, 180, +-142, -238, -146, -533, 44, -505, 347, -239, +426, 139, 98, 474, -348, 557, -579, 289, +-445, -226, 41, -648, 610, -695, 875, -444, +646, -3, 103, 494, -340, 763, -415, 528, +-186, -14, 120, -441, 418, -668, 558, -597, +356, -164, -43, 306, -306, 482, -309, 264, +-153, -91, 69, -337, 345, -357, 485, -123, +293, 166, -39, 371, -128, 390, 18, 131, +205, -161, 344, -353, 355, -488, 200, -430, +-54, -104, -241, 153, -234, 151, -143, 54, +-29, -29, 159, -24, 331, 103, 345, 213, +203, 162, 63, -56, 103, -275, 260, -396, +347, -268, 352, 98, 294, 372, 37, 459, +-357, 347, -590, -83, -507, -609, -224, -821, +181, -591, 728, -149, 1050, 342, 649, 639, +-107, 491, -489, 66, -409, -326, -101, -454, +337, -259, 661, 35, 548, 322, 74, 509, +-310, 395, -333, -6, -135, -345, 117, -493, +426, -563, 581, -503, 352, -248, -80, 93, +-340, 342, -306, 415, -127, 373, 96, 126, +309, -265, 330, -447, 209, -255, 230, 78, +406, 291, 456, 309, 317, 108, 104, -198, +-133, -351, -272, -262, -207, -42, -46, 29, +39, -60, -16, -94, -46, -74, 112, -27, +341, 67, 414, 121, 307, 23, 126, -237, +24, -388, 121, -249, 361, 91, 486, 454, +315, 664, -35, 506, -331, 6, -490, -487, +-378, -737, 45, -741, 440, -472, 558, -65, +460, 265, 187, 470, -61, 569, -57, 414, +121, 46, 250, -318, 207, -564, 45, -518, +-43, -149, 26, 229, 154, 381, 220, 231, +219, -130, 173, -469, 82, -455, -8, -80, +5, 312, 106, 541, 227, 446, 237, -10, +56, -415, -122, -560, -69, -443, 184, -52, +456, 316, 546, 351, 325, 106, -117, -250, +-352, -402, -187, -217, 47, 6, 131, 124, +201, 97, 279, -101, 314, -72, 343, 215, +356, 363, 250, 252, 2, -40, -168, -367, +-58, -509, 99, -373, 80, -80, -15, 149, +-100, 217, -126, 107, 30, -72, 346, -213, +608, -280, 542, -252, 216, -83, 32, 154, +141, 273, 290, 302, 256, 333, 64, 202, +-166, -66, -339, -311, -319, -408, -82, -310, +167, -144, 269, -22, 331, 19, 430, -69, +398, -197, 174, -225, 12, -140, 34, -5, +164, 217, 346, 413, 453, 430, 365, 245, +143, -44, -180, -281, -450, -376, -469, -328, +-274, -214, 66, -102, 465, 52, 678, 116, +566, 49, 241, -81, -3, -226, -28, -228, +75, -71, 255, 137, 446, 298, 404, 274, +89, 103, -254, -118, -410, -276, -275, -307, +82, -241, 440, -38, 593, 232, 391, 267, +17, 51, -186, -146, -133, -282, 92, -298, +365, -77, 506, 124, 425, 184, 174, 138, +-94, -36, -228, -217, -133, -321, 99, -308, +287, -58, 340, 317, 245, 476, 71, 308, +-41, 20, -29, -345, 120, -561, 297, -344, +328, 33, 228, 228, 144, 191, 116, -42, +149, -292, 208, -306, 165, 20, -38, 394, +-257, 472, -275, 167, 30, -342, 446, -670, +595, -546, 384, -105, 79, 344, -97, 540, +-65, 305, 221, -181, 569, -461, 574, -422, +232, -74, -127, 398, -341, 581, -367, 348, +-123, -179, 222, -702, 359, -817, 249, -471, +111, 85, 98, 484, 193, 532, 295, 254, +322, -120, 270, -277, 214, -137, 183, 87, +212, 178, 240, 89, 112, -106, -84, -265, +-128, -249, -102, -191, -157, -152, -165, -145, +-21, -190, 169, -53, 438, 286, 732, 480, +707, 424, 321, 178, -10, -202, -75, -495, +27, -478, 199, -264, 279, 35, 85, 278, +-215, 257, -362, 51, -253, -203, 98, -455, +394, -473, 383, -155, 269, 245, 257, 450, +347, 452, 498, 215, 567, -115, 321, -248, +-165, -216, -529, -105, -526, -21, -174, -134, +342, -243, 725, -234, 727, -166, 311, -22, +-291, 140, -653, 191, -450, 75, 165, -118, +795, -168, 1090, -35, 829, 141, 179, 325, +-379, 420, -555, 216, -339, -151, 93, -482, +433, -671, 459, -644, 258, -436, 9, -92, +-173, 251, -184, 455, 46, 508, 332, 356, +449, 126, 467, -93, 465, -235, 315, -152, +44, 29, -157, 67, -196, -49, -115, -262, +102, -490, 364, -550, 370, -269, 95, 169, +-109, 454, -45, 428, 155, 160, 302, -131, +425, -249, 441, -119, 146, 133, -220, 274, +-247, 181, 30, -108, 364, -345, 575, -382, +518, -203, 137, 47, -315, 134, -418, -27, +-74, -314, 366, -408, 569, -165, 476, 234, +177, 593, -161, 574, -297, 139, -92, -320, +287, -514, 502, -350, 500, 94, 350, 398, +62, 252, -142, -137, -64, -499, 136, -653, +249, -372, 198, 68, 47, 300, -56, 313, +4, 141, 168, -26, 296, 7, 335, 125, +278, 180, 90, 80, -98, -133, -88, -311, +163, -365, 484, -288, 555, -47, 279, 190, +-46, 227, -205, 98, -125, -155, 198, -372, +498, -326, 419, -90, -2, 226, -392, 452, +-433, 384, -150, 22, 277, -374, 652, -532, +747, -390, 484, -4, 155, 423, 79, 537, +185, 251, 252, -202, 201, -454, -57, -428, +-443, -271, -590, -35, -247, 132, 360, 94, +772, -28, 746, -107, 382, -128, -71, -97, +-307, 49, -87, 279, 434, 424, 757, 328, +605, 54, 62, -217, -484, -373, -611, -455, +-301, -522, 191, -439, 591, -163, 647, 121, +418, 421, 167, 575, 49, 369, 44, -6, +61, -288, 81, -342, 130, -166, 130, 45, +58, 145, -4, 63, 35, -119, 168, -263, +291, -279, 322, -156, 255, 27, 115, 117, +24, 113, 107, 137, 257, 192, 275, 150, +171, -27, 14, -278, -146, -484, -167, -517, +19, -225, 306, 279, 545, 602, 578, 495, +353, 51, 28, -387, -191, -571, -233, -441, +-93, 31, 113, 478, 228, 483, 261, 143, +275, -231, 262, -439, 263, -380, 244, -162, +150, 53, 70, 168, 67, 82, 82, -83, +96, -105, 131, -86, 153, -42, 66, 83, +-74, 175, -100, 201, 54, 126, 277, -34, +451, -115, 529, -190, 468, -282, 255, -269, +23, -195, -100, -106, -134, 30, -151, 86, +-87, 44, 89, -22, 253, -60, 325, 69, +339, 320, 270, 432, 96, 295, -64, -103, +-45, -555, 163, -797, 432, -687, 586, -174, +490, 447, 144, 723, -239, 556, -408, 106, +-255, -374, 88, -616, 345, -431, 370, 38, +242, 402, 61, 387, -89, 39, -42, -378, +238, -605, 483, -456, 504, 79, 334, 612, +115, 737, 62, 421, 184, -117, 246, -556, +154, -608, -128, -344, -473, -13, -490, 199, +-39, 94, 496, -220, 704, -341, 516, -211, +145, 67, -126, 400, -113, 580, 189, 441, +612, 60, 793, -315, 544, -487, 34, -430, +-421, -224, -609, -33, -490, 104, -80, 113, +410, -33, 582, -160, 418, -144, 193, -54, +38, 93, -15, 298, 122, 404, 401, 229, +546, -159, 397, -562, 123, -710, -74, -472, +-154, 18, -155, 509, -53, 724, 107, 484, +204, -25, 212, -407, 201, -498, 181, -357, +165, -56, 192, 168, 283, 187, 296, 27, +94, -223, -151, -325, -135, -217, 147, -26, +473, 240, 578, 409, 316, 307, -106, 64, +-301, -168, -154, -323, 182, -284, 396, -133, +295, 8, 31, 166, -145, 195, -122, 38, +102, -91, 398, -207, 585, -317, 533, -317, +267, -216, -6, -35, -95, 197, -18, 398, +94, 459, 103, 247, -4, -110, -116, -358, +-107, -411, 60, -238, 279, 106, 434, 308, +519, 216, 496, -37, 367, -299, 146, -430, +-124, -352, -283, -134, -205, 113, -6, 219, +168, 143, 303, -6, 355, -63, 244, 43, +107, 227, 65, 327, 75, 203, 143, -137, +269, -434, 325, -455, 251, -158, 84, 164, +-68, 219, -104, 9, -33, -361, 77, -627, +229, -423, 340, 126, 329, 616, 241, 808, +110, 595, 10, 63, 41, -448, 113, -692, +133, -590, 121, -218, 133, 185, 177, 417, +190, 410, 171, 145, 169, -246, 156, -552, +122, -602, 111, -372, 113, 95, 85, 586, +98, 766, 205, 565, 278, 116, 184, -453, +-14, -803, -137, -707, -83, -303, 80, 177, +281, 493, 431, 434, 420, 112, 302, -200, +226, -325, 197, -168, 169, 163, 86, 337, +-84, 249, -257, -15, -277, -335, -90, -502, +237, -388, 469, -122, 417, 97, 172, 168, +-32, 143, 21, 101, 371, 96, 698, 140, +657, 202, 206, 126, -368, -136, -655, -366, +-466, -429, 43, -353, 572, -92, 788, 229, +571, 368, 126, 289, -268, 80, -421, -196, +-205, -362, 222, -316, 527, -114, 554, 131, +344, 297, 16, 289, -182, 101, -87, -195, +205, -398, 463, -400, 509, -170, 306, 216, +5, 472, -189, 420, -201, 128, -87, -275, +61, -514, 99, -422, 44, -145, 95, 114, +319, 264, 522, 238, 566, 66, 410, -130, +68, -247, -220, -260, -162, -156, 126, 53, +330, 277, 322, 323, 175, 161, -10, -61, +-123, -209, -131, -245, -50, -148, 91, -19, +243, 14, 365, -41, 427, -82, 362, -85, +171, -50, -6, -19, -4, 5, 156, 23, +324, 24, 365, 34, 205, 81, -83, 119, +-245, 95, -164, -4, 53, -114, 234, -199, +242, -202, 86, -106, 6, 6, 149, 56, +412, 30, 609, -74, 582, -138, 281, -91, +-130, 11, -409, 107, -398, 156, -136, 108, +249, 10, 574, -84, 613, -124, 291, -115, +-125, -102, -270, -94, -78, -76, 236, -43, +476, 55, 471, 147, 218, 159, -54, 101, +-122, -34, -24, -188, 56, -216, 72, -140, +112, -54, 188, -20, 297, -33, 428, -76, +464, -83, 270, 22, -54, 204, -249, 282, +-167, 220, 102, 60, 343, -170, 406, -322, +220, -303, -88, -208, -186, -22, -48, 171, +114, 184, 229, 64, 284, -59, 288, -170, +347, -179, 428, -66, 373, 96, 145, 167, +-112, 77, -266, -55, -219, -102, 41, -83, +340, 16, 441, 139, 273, 175, -17, 54, +-174, -167, -70, -332, 215, -330, 434, -183, +422, 53, 197, 214, -49, 212, -90, 69, +102, -149, 324, -242, 410, -78, 327, 124, +127, 263, -64, 341, -92, 201, 19, -145, +145, -433, 195, -531, 131, -406, -2, -96, +-78, 262, -17, 463, 183, 396, 391, 63, +461, -317, 388, -425, 250, -235, 100, 49, +4, 328, -16, 408, 43, 149, 124, -222, +189, -403, 220, -357, 160, -124, 0, 144, +-127, 281, -123, 254, 13, 54, 216, -244, +393, -369, 428, -265, 329, -57, 207, 172, +147, 326, 129, 258, 102, 13, 76, -182, +94, -162, 101, -31, 79, 41, 61, 9, +33, -78, -13, -169, 12, -160, 141, -62, +253, 43, 252, 76, 219, 0, 212, -64, +213, 23, 216, 143, 230, 184, 206, 142, +103, 36, -23, -141, -99, -315, -83, -326, +67, -170, 266, -34, 409, 65, 389, 162, +153, 145, -128, 16, -201, -22, -51, 12, +200, 36, 409, 66, 444, 67, 289, 10, +104, -61, 4, -160, -6, -242, 15, -222, +7, -130, 30, -55, 201, 70, 391, 226, +424, 239, 278, 83, 21, -65, -222, -142, +-228, -149, 62, -18, 408, 211, 528, 290, +359, 120, -4, -216, -283, -499, -254, -526, +35, -261, 374, 145, 555, 446, 466, 445, +227, 174, 44, -178, -14, -355, -35, -280, +-40, -68, -28, 134, 35, 271, 223, 283, +444, 181, 460, 51, 203, -74, -150, -266, +-300, -461, -140, -512, 176, -362, 396, -69, +430, 282, 321, 515, 154, 518, 57, 265, +97, -141, 145, -418, 127, -355, 93, -66, +98, 279, 103, 461, 69, 305, 31, -127, +30, -550, 68, -690, 119, -465, 160, -50, +229, 318, 261, 479, 242, 405, 253, 142, +257, -126, 158, -236, 20, -184, -52, -85, +-43, 27, 5, 130, 105, 165, 205, 121, +251, 52, 256, -92, 213, -298, 115, -417, +47, -294, 37, 3, 70, 290, 142, 369, +202, 141, 148, -227, 64, -383, 85, -214, +158, 163, 184, 497, 167, 534, 125, 208, +126, -198, 203, -447, 284, -495, 249, -340, +68, -72, -155, 92, -250, 117, -123, 82, +156, 17, 415, -29, 549, 61, 445, 194, +130, 225, -167, 126, -235, -91, -19, -314, +355, -315, 600, -92, 495, 184, 55, 297, +-387, 135, -500, -216, -205, -495, 278, -470, +575, -85, 510, 379, 208, 598, -67, 476, +-66, 93, 174, -349, 394, -525, 399, -368, +241, -56, 83, 207, -29, 298, -123, 165, +-203, -71, -228, -216, -85, -208, 218, -114, +512, 30, 573, 107, 361, 99, 77, 74, +-46, 33, 60, -34, 242, -48, 269, -42, +108, -49, -89, -28, -122, 4, 5, -47, +135, -130, 173, -154, 135, -68, 99, 91, +136, 246, 227, 294, 314, 167, 269, -121, +104, -420, -46, -546, -93, -365, -2, 31, +208, 457, 407, 675, 443, 492, 251, -8, +-39, -456, -242, -594, -273, -370, -122, 53, +175, 344, 429, 274, 409, -38, 191, -329, +52, -348, 36, -82, 92, 251, 209, 426, +282, 327, 203, 9, 74, -258, 27, -320, +27, -168, 16, 72, 24, 190, 29, 106, +51, -52, 117, -223, 185, -322, 217, -234, +210, -2, 177, 200, 164, 342, 154, 382, +124, 245, 90, -33, 80, -275, 58, -410, +42, -379, 93, -153, 153, 119, 160, 272, +145, 287, 71, 105, -10, -185, 26, -349, +185, -265, 295, -19, 248, 272, 83, 425, +-115, 301, -189, -51, 16, -353, 365, -414, +577, -233, 468, 69, 106, 327, -249, 320, +-353, 50, -154, -262, 198, -413, 441, -327, +410, -36, 164, 252, -74, 359, -168, 239, +-73, 12, 162, -161, 355, -162, 386, -25, +275, 108, 74, 107, -114, -8, -182, -194, +-66, -336, 135, -283, 281, -46, 330, 193, +277, 320, 145, 226, 67, -26, 81, -227, +70, -216, -52, -19, -184, 204, -191, 247, +6, 83, 330, -173, 551, -299, 486, -191, +170, 51, -153, 239, -167, 243, 87, 49, +296, -167, 280, -312, 103, -342, -85, -207, +-174, 21, -115, 190, 41, 287, 152, 297, +241, 228, 338, 91, 352, -86, 203, -232, +-48, -273, -218, -244, -143, -117, 145, 56, +431, 160, 487, 131, 296, 14, -14, -79, +-219, -51, -203, -11, -97, 6, -9, 16, +55, -60, 84, -168, 144, -101, 275, 54, +376, 132, 339, 156, 231, 145, 133, 30, +60, -99, 24, -130, -6, -76, -64, -7, +-84, 53, -43, 18, 32, -71, 72, -140, +59, -205, 47, -187, 93, 11, 199, 169, +299, 162, 335, 101, 312, 31, 210, -68, +74, -81, -51, 29, -152, 142, -168, 123, +-33, 37, 179, -41, 301, -102, 233, -144, +51, -143, -146, -147, -225, -162, -94, -168, +158, -101, 348, 39, 399, 182, 339, 238, +216, 216, 43, 135, -64, 30, -29, -78, +61, -85, 128, 14, 177, 91, 117, 57, +-117, -45, -334, -218, -286, -384, -38, -402, +234, -216, 443, 55, 507, 276, 359, 345, +140, 271, 56, 115, 77, -28, 43, -98, +-42, -54, -95, 37, -57, 66, -3, 3, +6, -60, 23, -138, 40, -232, 16, -244, +41, -140, 165, -11, 290, 123, 296, 208, +250, 208, 204, 100, 116, -84, -10, -204, +-94, -126, -70, 27, -8, 143, -22, 197, +-40, 138, 2, -81, 67, -315, 121, -371, +182, -182, 215, 109, 140, 361, 43, 419, +77, 175, 155, -252, 155, -521, 91, -462, +44, -118, 38, 297, 48, 497, 25, 345, +-50, 7, -131, -299, -148, -371, -47, -156, +170, 149, 308, 293, 273, 253, 207, 54, +203, -225, 166, -382, 44, -296, -49, -114, +-26, 60, 17, 206, 30, 266, 4, 194, +-102, 79, -223, -61, -173, -198, 94, -229, +368, -127, 413, -13, 260, 73, 90, 116, +40, 102, 94, 29, 178, -14, 183, -14, +19, -29, -201, -88, -285, -124, -209, -112, +-47, -43, 92, 28, 163, 50, 169, 28, +154, 15, 183, -13, 221, -22, 186, 31, +112, 91, 63, 72, 76, 47, 77, 19, +14, -65, -87, -166, -184, -210, -224, -232, +-159, -189, -4, -26, 198, 209, 379, 362, +462, 353, 327, 203, 15, -20, -290, -250, +-406, -353, -215, -296, 196, -134, 497, 9, +474, 73, 178, 90, -166, 86, -361, 15, +-291, -32, -23, 3, 239, 77, 329, 154, +202, 224, -23, 201, -163, 49, -168, -222, +-26, -475, 174, -554, 273, -412, 236, -100, +152, 277, 48, 500, -95, 477, -180, 291, +-83, 73, 84, -111, 193, -208, 181, -221, +23, -164, -162, -90, -190, -53, -54, -65, +149, -54, 279, -33, 235, -15, 54, 52, +-49, 145, -14, 115, 52, 39, 126, 10, +156, -25, 28, -44, -168, -5, -258, -17, +-169, -50, 17, -53, 171, -79, 225, -100, +216, -37, 164, 38, 85, 101, 35, 149, +-7, 94, -101, -85, -95, -205, 52, -216, +141, -172, 33, -52, -155, 139, -214, 262, +-98, 318, 130, 294, 367, 122, 401, -150, +169, -382, -175, -491, -362, -406, -231, -163, +71, 128, 293, 301, 340, 299, 202, 185, +-45, 41, -251, -50, -252, 2, -97, 98, +47, 128, 97, 63, 79, -117, 69, -340, +90, -421, 97, -318, 122, -56, 110, 235, +-13, 399, -156, 356, -157, 112, -10, -216, +159, -361, 247, -217, 199, 94, -16, 326, +-265, 307, -337, 63, -169, -215, 56, -380, +182, -281, 212, 37, 169, 295, 62, 313, +-32, 140, -35, -137, 35, -346, 57, -355, +60, -152, 114, 93, 110, 199, -27, 145, +-200, 39, -306, -39, -297, -10, -165, 112, +86, 228, 330, 237, 407, 130, 293, -31, +83, -176, -111, -340, -184, -463, -148, -411, +-63, -199, 22, 9, 94, 157, 97, 244, +35, 272, -30, 228, -87, 212, -113, 233, +-66, 194, 24, 67, 102, -84, 79, -244, +-22, -351, -84, -380, -70, -329, -1, -191, +107, 1, 205, 129, 224, 220, 148, 280, +31, 224, -104, 94, -206, 5, -232, -106, +-201, -202, -156, -153, -130, -5, -94, 90, +30, 170, 225, 214, 386, 138, 378, -44, +229, -236, 50, -356, -101, -300, -197, -118, +-249, 62, -275, 148, -225, 112, -100, 4, +51, -23, 145, 56, 118, 152, -5, 178, +-93, 130, -36, 50, 110, -48, 220, -154, +249, -187, 176, -168, 35, -109, -155, 8, +-314, 95, -325, 57, -206, -54, -44, -141, +145, -121, 254, -25, 152, 72, -94, 104, +-214, 70, -137, 34, 18, 72, 199, 139, +304, 175, 160, 93, -132, -136, -294, -351, +-220, -386, -41, -246, 161, 49, 283, 336, +204, 414, -59, 240, -340, -81, -457, -385, +-309, -487, -33, -354, 178, -33, 252, 330, +224, 527, 150, 432, 125, 149, 158, -152, +75, -314, -152, -283, -314, -114, -306, 45, +-169, 81, -37, -1, 4, -92, -15, -122, +-2, -65, 68, 15, 123, 94, 115, 144, +61, 107, -33, 9, -79, -56, -64, -101, +-62, -111, -57, -76, -18, -32, 24, 9, +32, 93, -31, 176, -107, 197, -95, 100, +6, -78, 81, -209, 88, -198, 20, -118, +-138, -58, -280, -43, -251, -81, -84, -146, +105, -81, 233, 108, 262, 271, 176, 338, +38, 293, -64, 137, -118, -34, -187, -208, +-282, -338, -303, -340, -162, -231, 53, -78, +204, 118, 194, 284, 70, 320, -39, 182, +-82, -47, -85, -255, -58, -346, -51, -246, +-59, -1, -38, 188, 43, 257, 121, 210, +96, 79, 2, -33, -98, -66, -206, -62, +-261, -16, -211, 21, -63, -9, 98, -90, +170, -163, 124, -201, 30, -141, -45, 4, +-90, 132, -96, 137, -41, 44, -5, -49, +-20, -60, -16, 29, 4, 194, -42, 295, +-112, 239, -94, 45, -15, -188, 20, -361, +15, -380, -39, -258, -139, -82, -201, 47, +-119, 95, 47, 96, 161, 119, 163, 161, +61, 200, -81, 204, -134, 134, -97, -39, +-51, -216, -78, -305, -148, -286, -135, -168, +-12, 20, 102, 160, 113, 216, 0, 189, +-139, 123, -190, 53, -87, -45, 42, -189, +43, -271, -21, -238, -43, -107, -40, 83, +-31, 247, -47, 252, -96, 118, -116, -32, +-31, -93, 93, -46, 125, 63, 30, 120, +-99, 70, -172, -84, -166, -279, -151, -390, +-146, -288, -130, -33, -68, 244, 46, 424, +184, 386, 252, 137, 189, -113, 26, -235, +-149, -205, -278, -52, -297, 122, -210, 156, +-82, 42, 33, -175, 87, -353, 29, -308, +-91, -30, -163, 283, -148, 448, -76, 357, +77, 45, 244, -293, 282, -392, 129, -228, +-122, 29, -298, 236, -312, 291, -224, 134, +-100, -106, -33, -270, -78, -277, -142, -113, +-81, 132, 63, 285, 146, 281, 148, 95, +133, -171, 60, -318, -47, -261, -120, -96, +-149, 90, -171, 225, -180, 226, -155, 75, +-113, -54, -77, -68, -37, -16, 1, 38, +43, 43, 69, -37, 38, -140, -29, -201, +-84, -172, -121, -75, -85, 39, 29, 148, +137, 242, 113, 253, -45, 161, -229, -15, +-305, -167, -255, -210, -138, -187, -19, -130, +31, -44, 17, -22, 32, 12, 70, 132, +62, 222, 4, 216, -37, 145, -54, -9, +-60, -169, -43, -262, -24, -257, -65, -149, +-145, 3, -249, 98, -308, 127, -226, 95, +-16, 46, 187, 32, 248, 88, 161, 172, +-5, 175, -173, 51, -206, -114, -82, -276, +63, -368, 126, -311, 107, -96, -23, 162, +-298, 303, -567, 280, -551, 157, -230, -36, +213, -173, 547, -148, 547, -28, 187, 82, +-234, 140, -429, 106, -342, 36, -71, -42, +192, -117, 219, -139, -11, -96, -320, -62, +-492, -46, -419, -32, -105, -11, 257, -14, +407, -10, 270, 60, -2, 160, -228, 216, +-269, 227, -135, 153, 55, 0, 142, -149, +63, -215, -98, -216, -250, -187, -344, -180, +-320, -170, -177, -95, 18, 50, 153, 194, +195, 311, 171, 351, 94, 248, -27, 60, +-111, -34, -137, -50, -136, -85, -164, -142, +-207, -199, -179, -284, -68, -316, 20, -227, +34, -55, 0, 124, -43, 286, -75, 394, +-39, 425, 54, 349, 62, 179, -70, -40, +-176, -248, -180, -422, -147, -505, -116, -446, +-44, -253, 47, -5, 94, 265, 114, 485, +123, 519, 14, 354, -203, 132, -349, -82, +-353, -260, -273, -361, -118, -356, 66, -271, +184, -129, 179, 53, 102, 248, 25, 380, +-2, 381, -8, 236, -57, 25, -153, -186, +-220, -334, -276, -361, -302, -261, -205, -132, +2, -3, 182, 145, 240, 268, 170, 315, +-6, 300, -220, 204, -271, 30, -115, -212, +58, -417, 60, -421, -104, -241, -252, -24, +-215, 195, -33, 341, 165, 349, 221, 255, +57, 99, -205, -98, -336, -272, -258, -395, +-69, -374, 97, -165, 170, 108, 141, 311, +23, 400, -164, 315, -318, 96, -357, -135, +-256, -283, -51, -331, 190, -244, 342, -48, +286, 189, 40, 391, -220, 452, -333, 281, +-274, -44, -145, -413, -34, -661, -22, -627, +-114, -326, -178, 106, -72, 525, 145, 745, +259, 702, 146, 402, -79, -35, -302, -384, +-404, -552, -257, -578, 46, -441, 256, -210, +273, 51, 124, 322, -116, 503, -341, 492, +-419, 276, -308, -67, -91, -312, 87, -366, +164, -255, 164, -23, 112, 185, 7, 272, +-98, 244, -195, 41, -286, -216, -291, -352, +-128, -338, 105, -149, 255, 171, 216, 402, +-5, 448, -252, 306, -354, 20, -288, -269, +-117, -414, 59, -370, 136, -179, 76, 55, +-6, 255, -44, 308, -84, 210, -108, 71, +-72, -70, -34, -184, -29, -186, -83, -118, +-206, -19, -293, 62, -208, 68, 29, 51, +265, 82, 333, 102, 176, 78, -141, 28, +-404, -21, -440, -60, -256, -74, -7, -77, +181, -83, 230, -81, 124, -31, -111, 27, +-337, 71, -382, 69, -225, 26, 33, 21, +246, 69, 261, 100, 103, 113, -85, 54, +-213, -69, -259, -150, -196, -169, -70, -140, +11, -38, 12, 58, -27, 115, -117, 108, +-165, 4, -92, -77, 8, -7, 37, 118, +6, 188, -63, 133, -109, -31, -73, -206, +-5, -308, 0, -288, -47, -121, -84, 80, +-85, 228, -89, 299, -77, 296, -42, 240, +-39, 168, -106, 42, -183, -120, -184, -298, +-84, -475, 61, -541, 163, -377, 96, -71, +-98, 261, -200, 545, -146, 671, -36, 525, +53, 160, 44, -242, -71, -460, -179, -405, +-152, -138, -77, 163, -58, 305, -52, 167, +-45, -149, -89, -433, -153, -527, -162, -367, +-93, 10, 36, 459, 183, 804, 241, 833, +122, 479, -108, -90, -275, -630, -312, -929, +-225, -778, -51, -240, 48, 366, -70, 739, +-253, 695, -321, 234, -198, -341, 87, -654, +406, -515, 534, -46, 349, 460, -44, 700, +-453, 529, -682, 44, -598, -441, -280, -681, +94, -591, 369, -235, 388, 175, 114, 452, +-237, 548, -407, 434, -296, 169, -41, -106, +177, -267, 226, -304, 107, -262, -79, -193, +-176, -106, -161, -15, -163, 118, -201, 261, +-176, 319, -109, 257, -69, 106, 12, -99, +111, -242, 70, -231, -55, -93, -132, 50, +-138, 114, -109, 49, -46, -145, 28, -328, +75, -281, 64, -4, 24, 387, -43, 694, +-155, 706, -302, 423, -422, -46, -407, -614, +-217, -998, 42, -969, 220, -555, 295, 99, +320, 728, 230, 998, 59, 821, -74, 356, +-186, -127, -366, -441, -478, -527, -415, -393, +-268, -150, -97, 40, 131, 140, 306, 118, +273, 39, 72, 18, -119, 39, -195, 71, +-159, 110, -56, 64, 54, -25, 84, -66, +-32, -77, -217, -76, -280, -61, -255, -56, +-197, 4, -79, 123, 77, 226, 150, 244, +100, 128, 17, -118, -28, -353, -71, -439, +-145, -293, -189, 12, -150, 312, -89, 476, +-68, 451, -52, 257, -51, 34, -126, -158, +-143, -369, -7, -563, 177, -553, 220, -286, +107, 142, -96, 559, -312, 790, -432, 674, +-361, 227, -152, -324, 37, -686, 163, -730, +203, -443, 94, 54, -101, 495, -228, 627, +-193, 442, -38, 85, 130, -233, 176, -365, +44, -313, -195, -173, -364, -20, -371, 64, +-189, 103, 26, 145, 106, 144, 73, 102, +6, 123, -35, 125, -34, 22, -40, -110, +-110, -233, -205, -338, -220, -306, -112, -115, +82, 159, 244, 421, 290, 555, 150, 489, +-130, 263, -414, -88, -582, -471, -617, -763, +-481, -827, -159, -590, 235, -119, 555, 473, +717, 1008, 652, 1163, 308, 861, -200, 272, +-704, -450, -1002, -1016, -897, -1094, -478, -719, +43, -122, 478, 445, 708, 731, 609, 654, +242, 353, -160, -34, -452, -347, -602, -444, +-515, -344, -224, -184, 37, 16, 128, 221, +93, 335, 41, 369, 31, 384, 71, 320, +122, 115, 94, -230, -62, -553, -294, -686, +-440, -598, -438, -290, -262, 161, 4, 520, +215, 677, 247, 619, 99, 346, -111, -26, +-220, -337, -141, -532, 1, -537, 58, -321, +11, 35, -114, 387, -216, 624, -143, 587, +29, 209, 67, -242, -66, -498, -253, -627, +-299, -558, -156, -200, 75, 233, 178, 572, +52, 742, -181, 581, -320, 144, -242, -363, +-7, -716, 210, -711, 239, -330, 112, 209, +-20, 644, -116, 753, -208, 509, -304, 3, +-351, -495, -333, -692, -208, -595, -7, -315, +193, 127, 292, 492, 238, 639, 38, 610, +-198, 325, -395, -182, -492, -625, -332, -795, +73, -586, 498, -65, 664, 509, 440, 819, +-92, 705, -700, 267, -1019, -235, -867, -570, +-376, -580, 134, -335, 460, -2, 570, 263, +527, 325, 332, 242, 31, 137, -279, -16, +-504, -117, -535, -109, -376, -80, -169, -72, +-45, -135, 32, -199, 95, -45, 167, 242, +241, 495, 161, 632, -123, 451, -427, -66, +-525, -589, -443, -900, -201, -872, 123, -448, +342, 192, 408, 716, 342, 886, 141, 665, +-123, 247, -364, -113, -540, -237, -539, -191, +-364, -184, -133, -307, 116, -464, 328, -474, +359, -193, 152, 253, -115, 605, -350, 690, +-432, 471, -277, 10, 9, -449, 261, -595, +399, -314, 321, 160, -15, 538, -396, 598, +-639, 228, -671, -378, -431, -824, 32, -884, +419, -476, 461, 207, 248, 748, -26, 910, +-245, 709, -312, 234, -148, -231, 37, -443, +47, -383, -64, -193, -124, -50, -182, -39, +-315, -80, -327, -121, -152, -118, 76, -17, +279, 180, 381, 386, 233, 464, -115, 258, +-412, -151, -528, -493, -420, -556, -153, -309, +104, 121, 211, 491, 235, 657, 166, 545, +-28, 144, -243, -372, -338, -723, -294, -771, +-164, -432, 27, 188, 157, 697, 115, 799, +-51, 512, -180, -64, -231, -623, -220, -820, +-92, -596, 33, -64, 89, 583, 87, 965, +6, 888, -161, 417, -273, -275, -258, -860, +-110, -1002, 121, -695, 275, -88, 215, 559, +-39, 895, -336, 723, -551, 179, -559, -457, +-359, -865, -6, -789, 427, -240, 695, 472, +621, 1012, 213, 1111, -366, 676, -882, -66, +-950, -809, -518, -1300, 57, -1220, 477, -573, +596, 285, 334, 1050, -142, 1422, -438, 1115, +-418, 266, -198, -698, 81, -1295, 228, -1175, +140, -405, -31, 512, -190, 1073, -388, 1013, +-473, 370, -366, -534, -91, -1115, 260, -1005, +538, -318, 565, 634, 274, 1389, -209, 1404, +-624, 654, -718, -441, -550, -1395, -272, -1697, +66, -1121, 301, -74, 298, 876, 188, 1344, +72, 1150, -77, 475, -131, -216, -100, -625, +-90, -648, -87, -336, -54, 42, -123, 245, +-266, 273, -357, 85, -339, -242, -127, -392, +189, -270, 374, -25, 283, 306, 37, 551, +-173, 538, -244, 337, -162, -22, -78, -462, +-76, -692, -133, -625, -177, -324, -191, 130, +-163, 492, -126, 598, -1, 520, 216, 257, +340, -80, 243, -264, -18, -290, -331, -278, +-622, -212, -640, -102, -309, -7, 108, 82, +404, 211, 527, 299, 441, 240, 141, 48, +-211, -197, -543, -405, -725, -383, -647, -111, +-322, 179, 104, 359, 438, 448, 538, 385, +408, 208, 173, -18, -81, -269, -305, -437, +-470, -432, -508, -330, -415, -161, -232, 68, +13, 239, 192, 282, 213, 291, 135, 252, +166, 106, 223, -41, 136, -84, -84, -87, +-341, -27, -550, 87, -610, 82, -461, -79, +-143, -246, 242, -330, 509, -225, 571, 38, +411, 280, 31, 394, -397, 351, -635, 123, +-602, -185, -409, -412, -157, -424, 90, -231, +380, 81, 564, 411, 454, 612, 94, 529, +-342, 194, -700, -221, -819, -539, -546, -686, +-40, -614, 411, -287, 636, 194, 564, 605, +239, 789, -208, 610, -564, 125, -605, -363, +-283, -563, 97, -416, 248, -93, 66, 149, +-292, 225, -532, 151, -351, 2, 168, -113, +539, -128, 506, -58, 195, 65, -175, 171, +-436, 239, -424, 210, -228, 20, -103, -217, +-111, -335, -152, -316, -48, -140, 148, 135, +223, 351, 117, 402, -28, 272, -193, -12, +-335, -292, -326, -395, -148, -302, 67, -78, +207, 214, 255, 358, 170, 258, -60, 97, +-362, -26, -491, -105, -324, -80, -64, -52, +159, -71, 259, -83, 184, -109, -11, -96, +-164, 24, -252, 128, -277, 189, -257, 181, +-171, 33, 49, -147, 295, -200, 351, -96, +163, 90, -130, 181, -374, 193, -391, 163, +-186, 33, 14, -86, 57, -121, -8, -172, +-67, -186, -119, -159, -94, -162, -27, -94, +-27, 92, -117, 262, -167, 349, -76, 332, +95, 183, 241, -49, 238, -194, 56, -168, +-164, -61, -266, 27, -262, 4, -235, -169, +-216, -271, -211, -202, -188, -41, -118, 200, +61, 404, 208, 383, 209, 176, 147, -125, +133, -364, 125, -371, 78, -179, -56, 60, +-336, 266, -582, 408, -610, 437, -387, 215, +11, -190, 398, -513, 543, -592, 343, -361, +-56, 78, -389, 422, -423, 518, -216, 343, +59, -13, 218, -324, 133, -449, -113, -343, +-199, -22, -97, 301, -45, 482, -52, 462, +-95, 205, -163, -113, -144, -290, 7, -324, +120, -204, 81, -13, -31, 113, -143, 142, +-167, 29, -116, -212, -80, -389, -136, -353, +-160, -29, -20, 405, 226, 651, 378, 625, +303, 361, 0, -21, -391, -235, -644, -320, +-663, -447, -450, -466, -30, -314, 485, -135, +794, 134, 676, 426, 229, 496, -358, 358, +-786, 81, -836, -348, -485, -627, -2, -495, +351, -92, 520, 395, 498, 801, 260, 800, +-114, 379, -471, -149, -652, -585, -507, -783, +-122, -607, 267, -221, 476, 118, 396, 310, +112, 339, -189, 207, -416, 26, -584, -52, +-522, 12, -177, 112, 266, 191, 562, 211, +574, 85, 294, -151, -110, -314, -366, -286, +-406, -79, -346, 123, -292, 177, -225, 102, +-103, -37, 43, -161, 191, -174, 259, -121, +174, -21, 38, 116, -15, 222, -87, 269, +-155, 233, -226, 47, -331, -137, -269, -173, +56, -110, 287, -4, 222, 105, 127, 84, +62, -26, -80, -73, -238, -107, -409, -231, +-589, -271, -524, -121, -64, 58, 478, 203, +783, 358, 679, 414, 193, 350, -372, 195, +-646, -73, -594, -327, -327, -422, 41, -413, +311, -248, 338, 75, 131, 315, -186, 312, +-452, 126, -459, -154, -180, -335, 176, -243, +419, 42, 376, 295, 85, 444, -241, 429, +-398, 211, -295, -134, 31, -436, 308, -523, +334, -328, 115, 2, -261, 324, -560, 470, +-561, 247, -345, -195, -64, -472, 238, -462, +408, -164, 407, 283, 347, 562, 136, 566, +-217, 371, -443, 24, -441, -289, -365, -447, +-141, -483, 207, -370, 411, -109, 314, 159, +-36, 351, -429, 409, -566, 306, -345, 60, +24, -211, 322, -323, 442, -198, 323, 49, +30, 268, -205, 279, -282, 54, -301, -211, +-256, -364, -158, -355, -79, -103, -22, 268, +105, 487, 224, 465, 260, 253, 229, -75, +51, -313, -270, -348, -539, -282, -569, -212, +-331, -121, 67, 6, 427, 158, 553, 273, +384, 314, 3, 274, -341, 152, -455, -25, +-330, -134, -118, -166, 47, -200, 95, -195, +77, -89, 33, -8, -16, -15, -35, -41, +-35, -32, -43, 67, -88, 241, -124, 333, +-82, 316, -1, 170, 99, -130, 194, -380, +149, -398, -152, -280, -492, -66, -561, 176, +-273, 269, 185, 170, 537, 13, 568, -94, +299, -92, -112, 21, -449, 176, -491, 238, +-275, 176, -34, 28, 83, -181, 39, -361, +-111, -363, -167, -171, -37, 136, 111, 354, +213, 334, 238, 149, 138, -83, -48, -269, +-186, -278, -234, -133, -236, 97, -215, 310, +-175, 330, -84, 150, 101, -44, 254, -145, +218, -134, 69, -80, -101, -47, -250, -52, +-247, -109, -109, -169, 7, -127, 58, -19, +128, 115, 131, 235, 48, 275, -60, 226, +-191, 139, -269, 30, -162, -52, 37, -73, +143, -58, 122, -123, -37, -284, -223, -371, +-227, -243, -95, 55, 42, 375, 174, 493, +231, 312, 138, -41, -9, -313, -157, -380, +-273, -267, -320, 20, -228, 385, -32, 533, +170, 400, 287, 95, 248, -302, 79, -571, +-143, -540, -324, -277, -322, 143, -101, 454, +104, 435, 77, 213, -26, -99, -25, -401, +16, -429, 43, -182, 114, 152, 87, 439, +-97, 540, -224, 356, -194, 0, -95, -294, +76, -363, 209, -242, 103, -24, -162, 126, +-361, 63, -320, -153, -43, -351, 247, -383, +347, -134, 199, 277, -46, 619, -170, 688, +-112, 415, -21, 27, -4, -243, -123, -390, +-310, -372, -349, -241, -122, -139, 178, -64, +365, 37, 417, 129, 264, 186, -98, 177, +-419, 112, -488, -27, -348, -184, -99, -212, +167, -56, 281, 199, 252, 390, 147, 312, +-8, 63, -149, -195, -189, -397, -178, -347, +-105, -45, 52, 156, 94, 185, -64, 115, +-156, -61, -102, -259, -36, -289, 72, -69, +156, 301, 73, 596, -61, 632, -113, 256, +-57, -377, 96, -836, 205, -864, 40, -412, +-285, 345, -480, 861, -362, 859, 40, 439, +426, -238, 443, -768, 76, -749, -347, -335, +-488, 158, -211, 491, 336, 505, 685, 279, +485, 31, -118, -163, -699, -279, -917, -272, +-614, -112, 11, 86, 541, 186, 668, 149, +466, 20, 184, -101, -28, -109, -187, -59, +-326, 29, -435, 163, -474, 216, -306, 103, +80, -70, 421, -238, 505, -332, 321, -236, +-19, 49, -321, 338, -370, 460, -214, 312, +-10, -36, 178, -315, 239, -340, 46, -240, +-209, -108, -308, 36, -236, 140, -24, 200, +204, 219, 266, 132, 170, 51, 63, 38, +-16, -28, -139, -136, -268, -201, -286, -265, +-118, -220, 148, -12, 325, 189, 194, 272, +-215, 251, -573, 102, -534, -50, -36, -83, +614, -87, 897, -101, 578, -16, -75, 75, +-594, 74, -759, 53, -615, -4, -280, -148, +102, -193, 437, -104, 611, 16, 427, 190, +-10, 305, -428, 161, -634, -53, -440, -199, +96, -351, 507, -329, 566, 4, 374, 370, +-13, 591, -440, 584, -641, 206, -569, -404, +-264, -833, 186, -849, 506, -400, 515, 325, +326, 859, 53, 821, -240, 329, -377, -277, +-295, -665, -181, -591, -88, -155, 19, 265, +117, 502, 177, 474, 145, 126, 10, -315, +-133, -503, -184, -342, -65, 65, 187, 445, +352, 567, 203, 338, -190, -163, -528, -651, +-564, -818, -259, -601, 200, -60, 447, 595, +356, 1049, 81, 1035, -161, 505, -199, -318, +-50, -1002, 47, -1175, 78, -724, 134, 45, +41, 747, -171, 1114, -233, 880, -174, 105, +-123, -652, -38, -1043, 111, -961, 219, -341, +198, 522, 32, 1076, -188, 1035, -310, 423, +-236, -403, -35, -940, 195, -925, 323, -469, +262, 212, 124, 827, 29, 983, -115, 540, +-340, -126, -486, -653, -436, -851, -188, -600, +202, -79, 510, 373, 540, 661, 300, 641, +-79, 242, -473, -284, -636, -622, -384, -647, +143, -341, 646, 160, 832, 612, 453, 806, +-336, 682, -955, 224, -984, -405, -507, -845, +174, -933, 755, -716, 858, -132, 449, 592, +2, 988, -286, 900, -520, 432, -534, -257, +-230, -824, 88, -933, 293, -481, 389, 257, +272, 844, 2, 932, -258, 399, -411, -429, +-348, -923, -76, -829, 209, -247, 317, 502, +251, 892, 120, 690, -12, 140, -151, -471, +-283, -773, -320, -578, -193, -127, 6, 283, +233, 502, 433, 409, 419, 135, 116, -64, +-281, -104, -534, -73, -491, -24, -185, -9, +162, -78, 338, -203, 266, -257, 19, -165, +-140, 112, -79, 411, 70, 464, 143, 234, +94, -118, -42, -446, -126, -484, -103, -203, +-78, 124, -124, 366, -132, 465, -103, 267, +-88, -64, 14, -317, 176, -491, 239, -460, +224, -92, 163, 337, 4, 612, -234, 683, +-405, 352, -369, -275, -53, -674, 395, -760, +615, -605, 345, -65, -226, 575, -703, 810, +-784, 679, -353, 298, 306, -269, 659, -680, +566, -698, 191, -418, -208, 93, -273, 610, +-52, 780, 45, 512, -4, -19, -64, -605, +-152, -879, -206, -638, -119, -128, 5, 366, +118, 756, 235, 801, 198, 474, -19, 8, +-145, -489, -148, -787, -157, -591, -79, -166, +63, 159, 88, 385, 73, 408, 99, 196, +85, 24, 31, -90, -49, -193, -158, -119, +-158, 69, -79, 131, -67, 143, -50, 128, +96, -28, 198, -196, 157, -260, 68, -327, +-126, -237, -369, 96, -373, 360, -121, 422, +223, 366, 494, 83, 439, -289, 68, -389, +-268, -208, -392, 33, -287, 248, 23, 303, +313, 146, 272, -88, -53, -262, -379, -338, +-485, -247, -277, -34, 167, 142, 504, 215, +482, 240, 210, 211, -114, 159, -305, 37, +-240, -172, -100, -258, -26, -98, -6, 52, +-56, 51, -52, -16, 153, -77, 335, -102, +231, -30, -114, 76, -453, 130, -534, 88, +-254, -6, 177, -40, 500, 59, 586, 164, +331, 157, -173, 46, -534, -176, -559, -487, +-372, -557, -31, -196, 410, 352, 650, 737, +500, 756, 101, 315, -299, -308, -586, -679, +-643, -669, -345, -386, 165, 86, 551, 488, +672, 594, 437, 397, -113, -1, -586, -414, +-638, -531, -327, -305, 90, 10, 379, 226, +399, 291, 187, 139, -19, -35, -99, -5, +-104, 102, -67, 109, 19, 118, 85, 79, +74, -123, -40, -358, -175, -435, -205, -302, +-185, 40, -197, 375, -130, 479, 8, 351, +176, 110, 418, -194, 554, -452, 386, -519, +56, -328, -268, 71, -532, 570, -623, 836, +-354, 654, 146, 244, 499, -212, 502, -743, +162, -1046, -407, -861, -782, -364, -559, 276, +107, 903, 710, 1086, 924, 670, 603, -21, +-101, -543, -664, -682, -720, -473, -413, -74, +46, 358, 475, 602, 578, 501, 267, 104, +-189, -346, -552, -670, -633, -704, -380, -357, +31, 169, 389, 558, 597, 721, 580, 559, +303, 101, -102, -379, -423, -688, -593, -720, +-481, -311, 23, 346, 565, 820, 691, 867, +374, 507, -227, -86, -815, -616, -976, -883, +-554, -837, 224, -466, 943, 170, 1138, 744, +708, 974, -24, 789, -700, 196, -1073, -551, +-930, -994, -256, -978, 574, -454, 1098, 419, +1072, 1070, 427, 1137, -507, 701, -1124, -100, +-1098, -898, -491, -1258, 386, -969, 967, -170, +905, 663, 349, 1082, -337, 979, -811, 398, +-812, -390, -339, -1012, 331, -1127, 824, -586, +895, 250, 542, 862, -51, 1126, -620, 900, +-880, 198, -748, -522, -360, -919, 125, -967, +563, -635, 683, -17, 444, 616, 82, 925, +-271, 786, -489, 295, -361, -378, -5, -944, +340, -1051, 541, -589, 449, 324, 31, 1203, +-479, 1471, -784, 931, -717, -175, -283, -1251, +325, -1603, 719, -1112, 701, -126, 426, 845, +42, 1324, -393, 1153, -597, 480, -420, -417, +-75, -1039, 254, -1078, 468, -580, 402, 175, +86, 776, -280, 881, -544, 509, -584, -42, +-291, -447, 172, -604, 517, -464, 668, -99, +593, 240, 162, 430, -390, 470, -657, 210, +-551, -195, -213, -409, 183, -378, 383, -215, +283, 33, 67, 278, -74, 384, -147, 281, +-177, 105, -122, -86, 44, -271, 232, -298, +297, -184, 174, -127, -65, -50, -271, 102, +-312, 245, -178, 376, 5, 358, 93, 32, +118, -342, 172, -495, 226, -384, 117, -31, +-89, 409, -164, 642, -172, 509, -208, -1, +-122, -642, 11, -957, 63, -677, 170, -16, +326, 667, 290, 1020, 86, 812, -128, 173, +-326, -468, -443, -828, -323, -770, -51, -314, +166, 310, 330, 782, 428, 851, 271, 410, +1, -308, -119, -877, -198, -969, -303, -539, +-276, 157, -133, 697, 73, 851, 295, 609, +322, 93, 73, -430, -164, -619, -192, -403, +-68, 30, 85, 384, 129, 433, 26, 197, +-51, -136, -61, -415, -65, -447, 8, -224, +129, 69, 93, 302, -53, 368, -142, 190, +-189, -38, -144, -133, 66, -101, 244, -20, +205, 34, 15, 14, -152, -15, -175, -13, +20, 39, 251, 93, 269, 84, 95, -7, +-154, -108, -375, -163, -377, -181, -191, -168, +37, -54, 271, 86, 385, 195, 250, 297, +15, 290, -150, 97, -230, -114, -216, -236, +-55, -231, 159, -100, 274, 51, 233, 124, +82, 127, -154, 31, -378, -114, -429, -179, +-228, -137, 142, -50, 427, 114, 440, 263, +276, 204, 25, 36, -261, -11, -410, -9, +-355, -15, -192, -39, 40, -212, 245, -430, +322, -383, 341, -68, 332, 377, 118, 797, +-224, 881, -459, 440, -540, -271, -411, -899, +-21, -1191, 385, -927, 541, -91, 404, 809, +57, 1222, -286, 997, -389, 263, -233, -574, +56, -949, 297, -714, 325, -109, 155, 453, +-83, 598, -303, 320, -365, -89, -217, -370, +17, -337, 187, -43, 271, 265, 253, 396, +117, 256, -70, -98, -230, -416, -295, -534, +-170, -390, 55, 3, 210, 501, 237, 810, +130, 700, -85, 194, -216, -423, -112, -884, +115, -972, 190, -583, 66, 148, -44, 859, +-84, 1220, -169, 1008, -174, 220, -60, -797, +-32, -1401, -10, -1227, 170, -421, 312, 560, +262, 1197, 124, 1157, -50, 557, -223, -217, +-260, -764, -229, -896, -193, -619, -65, -97, +114, 412, 201, 679, 232, 630, 246, 281, +152, -156, -42, -429, -216, -525, -298, -476, +-209, -195, 4, 250, 149, 603, 166, 627, +117, 308, -15, -202, -149, -654, -148, -771, +-70, -448, 14, 132, 222, 724, 400, 985, +264, 677, -77, 9, -357, -623, -504, -947, +-440, -762, -133, -205, 247, 365, 492, 720, +527, 720, 371, 304, 48, -281, -342, -700, +-549, -751, -445, -396, -124, 277, 234, 894, +436, 989, 317, 485, 1, -245, -271, -843, +-366, -1043, -215, -697, 166, 55, 519, 777, +540, 1093, 231, 814, -203, 37, -586, -792, +-688, -1179, -426, -971, -19, -223, 356, 722, +591, 1217, 513, 983, 211, 316, -73, -455, +-262, -902, -333, -700, -209, -107, -37, 383, +51, 533, 133, 286, 193, -168, 131, -467, +-55, -412, -275, -135, -352, 168, -159, 330, +184, 271, 423, 111, 433, 36, 171, 10, +-235, 11, -504, 18, -459, -99, -114, -251, +357, -200, 649, -7, 557, 200, 77, 268, +-514, 96, -821, -163, -649, -328, -117, -316, +463, -28, 793, 323, 708, 432, 238, 294, +-331, 14, -655, -319, -616, -481, -327, -342, +100, 36, 466, 444, 594, 619, 469, 414, +142, -61, -274, -517, -568, -689, -639, -505, +-441, -38, 46, 428, 577, 629, 758, 509, +539, 136, 111, -286, -386, -494, -688, -447, +-572, -209, -214, 121, 148, 346, 407, 385, +450, 311, 288, 120, 102, -142, -109, -376, +-311, -475, -302, -332, -124, 54, 48, 486, +215, 664, 269, 424, 54, -64, -243, -543, +-339, -788, -197, -623, 84, -64, 294, 564, +289, 884, 147, 710, -17, 159, -170, -467, +-198, -812, -101, -710, -10, -221, 72, 431, +166, 858, 160, 743, 17, 241, -130, -363, +-164, -862, -108, -917, -33, -406, 29, 289, +43, 772, 4, 830, -20, 413, 17, -201, +80, -584, 122, -584, 133, -270, 61, 188, +-43, 513, -87, 486, -60, 162, -26, -236, +-4, -482, 8, -405, -68, -74, -179, 209, +-180, 291, -113, 185, -3, -35, 187, -187, +356, -140, 344, -25, 189, 43, -12, 103, +-190, 178, -258, 216, -215, 211, -155, 109, +-101, -136, -43, -438, 42, -584, 140, -458, +176, -84, 101, 415, -8, 794, -32, 764, +-38, 328, -52, -229, 7, -622, 68, -703, +69, -463, 47, -84, -14, 259, -150, 461, +-215, 416, -120, 187, 28, -40, 185, -173, +304, -166, 198, -21, -85, 145, -277, 163, +-289, -17, -190, -255, -21, -381, 140, -346, +200, -82, 186, 327, 198, 544, 227, 436, +139, 123, -118, -254, -372, -443, -463, -322, +-323, -38, -38, 216, 209, 316, 322, 222, +304, 25, 199, -173, 63, -286, -95, -258, +-245, -116, -281, 46, -185, 168, 9, 232, +260, 210, 354, 80, 181, -69, -70, -175, +-216, -231, -265, -130, -196, 139, -21, 341, +139, 326, 204, 111, 167, -219, 51, -493, +-104, -473, -248, -146, -255, 242, -32, 490, +235, 458, 312, 86, 241, -376, 55, -550, +-213, -355, -285, 76, -93, 561, 22, 763, +9, 511, 39, -9, 52, -490, -8, -752, +-11, -688, -46, -286, -208, 199, -232, 443, +-7, 455, 287, 305, 524, 34, 544, -141, +199, -99, -337, 2, -693, 53, -710, 11, +-380, -130, 154, -242, 585, -179, 684, 60, +407, 342, -89, 449, -475, 271, -551, -162, +-344, -592, -16, -691, 292, -424, 453, 79, +391, 623, 233, 848, 50, 596, -225, 60, +-484, -493, -516, -786, -298, -609, 53, -106, +421, 393, 547, 650, 302, 574, -104, 230, +-411, -206, -458, -509, -187, -547, 230, -357, +480, -46, 420, 218, 117, 313, -271, 272, +-475, 204, -354, 134, -82, 58, 164, -23, +297, -143, 226, -289, 31, -316, -89, -169, +-87, 62, -73, 246, -76, 304, -80, 229, +-42, 64, 99, -130, 253, -258, 235, -217, +57, -64, -144, 63, -286, 134, -280, 95, +-110, -25, 58, -85, 117, -53, 103, -8, +66, 41, 57, 106, 98, 115, 103, 98, +53, 95, -19, 43, -114, -45, -193, -107, +-157, -175, -40, -251, 16, -209, 7, -67, +-3, 62, -16, 181, 29, 258, 126, 195, +170, 79, 139, 7, 57, -50, -63, -79, +-118, -10, -82, 64, -39, 29, -38, -99, +-86, -243, -157, -309, -124, -193, 17, 72, +169, 313, 276, 371, 220, 300, -7, 120, +-209, -167, -238, -376, -98, -356, 141, -175, +288, 94, 142, 373, -120, 420, -255, 183, +-255, -95, -81, -270, 191, -346, 247, -280, +65, -48, -98, 174, -162, 262, -156, 252, +-4, 107, 198, -140, 220, -252, 106, -153, +5, 2, -111, 154, -236, 257, -207, 202, +-29, 51, 104, -82, 158, -194, 134, -256, +10, -205, -143, -94, -181, 35, -65, 178, +66, 261, 113, 192, 112, 71, 66, -43, +-26, -156, -76, -146, -53, -15, -30, 87, +-36, 94, -32, 20, -32, -88, -68, -139, +-47, -110, 76, -42, 190, 93, 170, 228, +31, 249, -149, 160, -241, -39, -138, -285, +109, -419, 269, -338, 135, -94, -193, 217, +-377, 441, -270, 437, 68, 257, 491, 11, +642, -252, 281, -407, -287, -329, -640, -90, +-684, 153, -391, 297, 198, 238, 638, 6, +618, -210, 310, -286, -98, -214, -435, -22, +-467, 202, -213, 355, 88, 373, 312, 245, +383, 37, 203, -193, -103, -375, -343, -475, +-445, -432, -348, -227, -43, 104, 278, 448, +401, 646, 340, 600, 180, 280, -31, -196, +-131, -566, -121, -623, -150, -405, -176, -44, +-112, 336, -31, 495, 12, 343, 89, 36, +115, -260, -19, -399, -119, -305, -49, -17, +88, 298, 188, 446, 217, 339, 87, 74, +-160, -217, -316, -409, -305, -374, -163, -137, +86, 152, 335, 361, 416, 374, 254, 174, +-42, -98, -319, -319, -468, -392, -386, -286, +-82, -59, 274, 185, 451, 351, 335, 355, +72, 146, -167, -127, -299, -261, -259, -217, +-26, -25, 205, 231, 248, 381, 142, 260, +-49, -36, -247, -343, -296, -528, -148, -488, +65, -249, 240, 96, 290, 395, 128, 532, +-107, 458, -239, 247, -255, -11, -151, -250, +45, -363, 195, -307, 271, -147, 256, 56, +102, 206, -69, 221, -188, 145, -338, 27, +-391, -132, -206, -249, 85, -269, 340, -213, +492, -50, 408, 180, 73, 325, -296, 355, +-539, 261, -536, 50, -189, -158, 274, -276, +571, -241, 592, -94, 297, 111, -210, 262, +-599, 202, -653, -81, -431, -369, -7, -457, +430, -310, 605, 50, 489, 426, 202, 585, +-126, 486, -381, 172, -451, -226, -336, -488, +-110, -429, 188, -116, 414, 189, 405, 322, +150, 208, -248, -70, -520, -284, -483, -291, +-178, -184, 220, -8, 526, 192, 601, 295, +401, 265, 57, 155, -319, -12, -619, -135, +-642, -147, -349, -113, 96, -64, 455, -6, +579, 52, 375, 91, -46, 81, -383, -20, +-481, -178, -293, -263, 102, -219, 421, -26, +496, 236, 311, 383, -70, 373, -422, 214, +-484, -57, -277, -317, -21, -359, 162, -217, +200, 9, 117, 225, 73, 254, 124, 109, +152, -88, 26, -253, -195, -301, -362, -179, +-347, 32, -100, 227, 265, 340, 509, 298, +416, 108, 73, -76, -253, -156, -401, -145, +-323, -110, -78, -87, 163, -84, 229, -49, +119, 25, -53, 90, -173, 108, -170, 87, +-52, 22, 113, -8, 224, -36, 235, -100, +145, -73, -36, 27, -209, 87, -288, 86, +-242, 50, -92, -62, 97, -141, 253, -89, +265, -3, 93, 84, -128, 170, -207, 196, +-144, 76, -52, -130, 100, -270, 214, -290, +125, -113, -67, 168, -168, 288, -184, 179, +-158, 0, 7, -140, 175, -164, 170, 2, +115, 178, 48, 196, -48, 84, -87, -112, +-29, -333, 16, -327, -45, -38, -145, 266, +-201, 379, -142, 314, 14, 30, 183, -329, +316, -394, 270, -167, 50, 101, -158, 298, +-262, 311, -242, 102, -96, -194, 105, -364, +164, -320, 62, -85, -40, 180, -76, 318, +20, 272, 152, 80, 158, -16, -1, 16, +-201, 41, -240, -12, -118, -132, 37, -268, +118, -319, 89, -199, -6, -11, -97, 162, +-61, 305, 76, 338, 192, 215, 196, 47, +67, -122, -100, -264, -206, -216, -183, -18, +-66, 86, 21, 111, 36, 107, -38, 13, +-123, -118, -100, -180, 57, -156, 210, -12, +224, 147, 151, 226, 4, 168, -196, 18, +-243, -122, -58, -145, 145, -34, 205, 74, +141, 103, -98, 44, -390, -59, -437, -173, +-215, -179, 93, -33, 386, 145, 555, 268, +445, 217, 102, -8, -250, -257, -493, -378, +-513, -205, -258, 168, 101, 440, 317, 435, +323, 174, 224, -263, 75, -596, -100, -570, +-264, -209, -327, 318, -187, 694, 89, 688, +374, 301, 487, -278, 293, -724, -155, -735, +-560, -377, -651, 124, -475, 538, -59, 686, +491, 490, 792, 64, 659, -356, 236, -595, +-256, -513, -597, -99, -549, 344, -206, 555, +92, 479, 248, 138, 241, -344, 51, -627, +-183, -616, -284, -389, -183, 71, 21, 545, +267, 787, 438, 698, 392, 323, 152, -217, +-196, -644, -439, -720, -443, -475, -229, -43, +93, 358, 325, 492, 327, 322, 43, 39, +-292, -206, -397, -321, -267, -237, 12, -31, +328, 181, 514, 329, 438, 320, 175, 163, +-142, -86, -475, -355, -594, -447, -368, -276, +19, 0, 333, 314, 465, 507, 397, 414, +108, 58, -244, -302, -421, -521, -396, -513, +-216, -204, 64, 226, 361, 491, 455, 461, +267, 202, -12, -176, -215, -401, -262, -283, +-157, -35, 11, 207, 109, 350, 88, 242, +-17, -44, -178, -273, -258, -358, -155, -327, +104, -106, 365, 225, 415, 463, 259, 460, +0, 240, -310, -83, -516, -392, -451, -544, +-200, -467, 63, -173, 333, 201, 495, 476, +400, 546, 161, 411, -70, 62, -235, -266, +-286, -348, -198, -222, -82, -28, -23, 115, +-6, 79, -54, -116, -96, -287, -79, -304, +9, -158, 128, 127, 165, 354, 162, 442, +224, 364, 285, 147, 217, -105, 71, -191, +-109, -117, -412, -116, -664, -130, -645, -139, +-364, -231, 101, -253, 582, -67, 784, 145, +536, 275, 73, 368, -293, 307, -430, 90, +-283, -96, -31, -214, 129, -247, 154, -129, +104, 24, 50, 55, -23, 56, -88, 98, +-139, 74, -135, 5, -54, -25, 4, -82, +26, -139, 18, -92, -18, -43, -66, -16, +-65, -4, 26, 15, 125, 41, 212, 130, +242, 226, 184, 271, 101, 224, -52, 54, +-239, -162, -346, -369, -334, -456, -241, -334, +-82, -98, 117, 145, 198, 283, 154, 273, +90, 136, 27, -13, 32, -78, 107, -54, +171, 48, 136, 165, 13, 213, -143, 109, +-280, -46, -272, -176, -107, -265, 104, -254, +204, -171, 107, -98, -75, 4, -215, 163, +-215, 275, -60, 266, 159, 114, 319, -79, +305, -182, 119, -117, -137, 32, -322, 132, +-331, 151, -143, 75, 143, -84, 327, -209, +325, -218, 160, -125, -88, 44, -284, 237, +-364, 234, -325, 68, -155, -144, 110, -264, +304, -198, 320, 20, 215, 219, -2, 243, +-231, 156, -276, 28, -99, -90, 136, -119, +277, -55, 268, -17, 74, -20, -183, -6, +-306, -30, -273, -49, -196, 8, -120, 26, +42, -14, 236, -20, 333, -2, 301, 11, +83, 66, -251, 127, -436, 114, -291, 39, +59, -34, 390, -121, 545, -169, 345, -109, +-126, -53, -577, 14, -752, 97, -501, 117, +64, 49, 601, 50, 776, 63, 518, 13, +-13, -39, -528, -88, -684, -92, -446, -27, +-11, 48, 376, 76, 528, 18, 420, -61, +111, -136, -215, -150, -399, -63, -422, 91, +-288, 232, -38, 323, 268, 293, 486, 68, +477, -211, 180, -399, -296, -395, -639, -209, +-652, 35, -288, 229, 310, 319, 750, 254, +756, 110, 372, -40, -176, -189, -653, -246, +-754, -189, -396, -72, 92, 69, 443, 211, +516, 256, 240, 125, -171, -72, -382, -190, +-298, -193, -69, -71, 196, 141, 375, 263, +325, 195, 100, 67, -167, -149, -363, -345, +-396, -395, -212, -290, 80, -59, 281, 276, +331, 525, 214, 484, -30, 235, -242, -76, +-283, -334, -160, -394, 31, -221, 210, 8, +274, 151, 162, 224, -33, 144, -189, -53, +-260, -165, -250, -199, -110, -181, 130, -54, +315, 103, 332, 198, 172, 251, -110, 221, +-346, 118, -345, -36, -148, -204, 72, -282, +240, -202, 256, -33, 102, 124, -79, 231, +-185, 178, -184, -3, -48, -199, 145, -284, +207, -245, 137, -62, 17, 189, -130, 335, +-209, 382, -176, 301, -89, 30, 14, -225, +134, -383, 208, -429, 173, -240, 38, 131, +-171, 332, -307, 324, -240, 176, -20, -121, +262, -335, 402, -274, 250, -31, -48, 212, +-251, 351, -278, 271, -154, -8, 70, -273, +175, -330, 39, -202, -127, 34, -158, 225, +-73, 227, 57, 108, 177, -5, 170, -64, +8, -63, -102, -44, -72, -65, 34, -106, +148, -109, 172, -57, 41, 41, -183, 88, +-311, 79, -265, 75, -83, 47, 153, 72, +272, 116, 211, 136, 25, 58, -176, -102, +-231, -266, -120, -318, 51, -222, 201, -37, +299, 161, 239, 254, 27, 198, -172, 84, +-324, 2, -382, -31, -233, -58, 33, -61, +248, -67, 352, -79, 289, -16, 10, 66, +-258, 82, -291, 75, -172, 48, -6, -27, +175, -45, 255, -22, 188, -4, 86, -12, +3, -63, -126, -153, -252, -160, -258, -44, +-157, 92, -13, 204, 149, 240, 236, 176, +164, 16, 34, -101, -41, -141, -83, -144, +-83, -79, -28, -3, 10, 27, 4, 52, +21, 41, 61, 2, 72, -16, 28, 7, +-73, -19, -165, -44, -156, -49, -38, -14, +90, 57, 127, 121, 58, 138, -69, 73, +-143, -50, -71, -147, 122, -167, 282, -114, +259, 11, 37, 148, -266, 237, -429, 218, +-313, 74, -10, -133, 299, -292, 418, -315, +247, -211, -76, -59, -283, 96, -279, 243, +-166, 325, -33, 287, 62, 157, 120, -59, +205, -271, 280, -346, 259, -232, 70, 2, +-220, 212, -439, 329, -468, 227, -278, -43, +44, -300, 353, -391, 491, -269, 394, 70, +116, 416, -253, 512, -506, 320, -453, -68, +-131, -458, 251, -583, 460, -394, 388, 21, +116, 479, -178, 696, -334, 502, -294, 45, +-108, -418, 54, -679, 141, -594, 185, -201, +126, 269, -8, 576, -117, 605, -183, 318, +-186, -103, -65, -451, 126, -581, 229, -401, +228, 32, 154, 420, -5, 559, -175, 436, +-237, 20, -164, -447, -37, -625, 74, -442, +147, -12, 107, 452, -56, 661, -188, 461, +-158, 9, -10, -418, 147, -598, 235, -455, +193, -117, 59, 256, -59, 471, -127, 454, +-161, 222, -183, -69, -153, -287, -23, -373, +159, -293, 276, -88, 252, 130, 87, 290, +-136, 332, -275, 196, -271, -59, -185, -318, +-58, -424, 103, -265, 240, 65, 298, 373, +254, 514, 98, 387, -87, 41, -213, -306, +-271, -507, -243, -494, -103, -248, 74, 75, +196, 320, 215, 402, 87, 337, -109, 162, +-189, -35, -99, -166, 76, -247, 231, -245, +224, -141, 12, 41, -238, 187, -322, 232, +-218, 134, 8, -65, 248, -254, 329, -301, +210, -137, -4, 134, -176, 342, -218, 405, +-138, 242, -30, -71, 28, -326, 58, -422, +62, -373, 40, -156, 41, 132, 26, 336, +-43, 396, -81, 303, -52, 80, 8, -144, +107, -249, 186, -258, 112, -167, -68, -10, +-201, 104, -247, 107, -165, 71, 22, 7, +183, -62, 233, -31, 150, 47, 7, 95, +-84, 91, -97, 1, -104, -110, -89, -127, +-21, -57, 17, 23, 28, 80, 63, 73, +77, 4, 49, -50, 15, -54, -13, 26, +-47, 112, -53, 154, -27, 101, -21, -46, +-36, -223, -47, -296, -42, -215, 2, -26, +64, 161, 110, 255, 102, 228, 54, 127, +7, 26, -29, -32, -72, -44, -144, -46, +-188, -94, -140, -153, -24, -152, 112, -96, +225, 17, 243, 169, 141, 230, 10, 153, +-90, 41, -161, -97, -162, -190, -98, -164, +-58, -46, -30, 74, 28, 143, 62, 116, +66, -5, 84, -103, 68, -112, -10, -21, +-57, 102, -42, 172, 16, 120, 99, -14, +107, -133, 1, -187, -124, -143, -196, -11, +-170, 105, -17, 143, 144, 82, 179, -11, +115, -68, 19, -91, -79, -87, -125, -17, +-124, 48, -108, 94, -27, 157, 114, 165, +218, 78, 223, -34, 107, -168, -92, -280, +-242, -216, -234, -7, -97, 192, 92, 272, +234, 180, 214, -60, 35, -266, -194, -266, +-356, -115, -330, 77, -68, 220, 291, 210, +496, 90, 394, -4, 60, -34, -275, -31, +-369, 35, -187, 91, 98, 38, 271, -88, +185, -225, -73, -274, -276, -213, -288, -55, +-158, 135, 25, 275, 178, 301, 207, 249, +153, 99, 88, -135, 14, -313, -38, -304, +-25, -124, -2, 136, -17, 334, -29, 316, +-44, 88, -84, -167, -68, -307, -11, -292, +-15, -122, -48, 112, -59, 230, -43, 182, +17, 15, 122, -170, 186, -212, 164, -78, +98, 141, -3, 303, -98, 319, -144, 150, +-133, -119, -75, -325, -3, -357, 52, -206, +53, 36, 8, 252, -47, 304, -95, 163, +-95, -72, -20, -273, 72, -339, 136, -227, +195, 25, 211, 312, 109, 487, -62, 450, +-213, 178, -310, -211, -267, -493, -66, -499, +163, -270, 274, 53, 196, 304, -3, 358, +-151, 194, -144, -75, -33, -282, 105, -286, +166, -87, 85, 184, -55, 364, -136, 325, +-123, 104, -36, -173, 62, -355, 99, -326, +89, -131, 50, 88, -23, 238, -91, 262, +-116, 117, -96, -92, -32, -213, 60, -208, +119, -78, 94, 116, 9, 239, -63, 205, +-65, 85, -9, -55, 51, -198, 87, -235, +85, -146, 51, -9, -7, 134, -96, 242, +-175, 217, -189, 86, -117, -86, 9, -255, +130, -329, 194, -235, 177, -16, 109, 254, +-1, 437, -105, 402, -141, 157, -107, -166, +-9, -403, 108, -419, 140, -217, 37, 68, +-95, 272, -152, 309, -135, 165, -50, -73, +38, -252, 62, -284, 60, -146, 72, 85, +88, 281, 96, 331, 82, 234, 25, 46, +-67, -152, -125, -259, -112, -238, -35, -119, +20, 12, -20, 77, -116, 57, -186, -33, +-117, -129, 110, -119, 349, 25, 422, 223, +265, 367, -40, 356, -328, 130, -423, -200, +-299, -424, -56, -398, 198, -159, 318, 153, +210, 339, -17, 285, -183, 25, -219, -269, +-154, -428, -11, -334, 142, -40, 227, 285, +258, 495, 231, 468, 69, 218, -210, -96, +-436, -315, -465, -354, -258, -216, 120, -6, +443, 144, 521, 160, 340, 53, -12, -73, +-375, -121, -515, -95, -356, 1, -39, 87, +275, 68, 429, -19, 325, -60, 91, -13, +-110, 104, -251, 241, -288, 246, -171, 62, +20, -171, 190, -310, 262, -314, 157, -136, +-68, 117, -244, 239, -268, 191, -148, 53, +38, -135, 205, -233, 279, -153, 241, 3, +122, 133, -38, 216, -180, 197, -229, 90, +-146, -19, -30, -91, 32, -130, 45, -101, +-5, -27, -71, 25, -79, 32, -15, -6, +85, -50, 197, -54, 248, -15, 150, 29, +-51, 55, -233, 28, -287, -16, -174, -2, +27, 48, 202, 112, 248, 169, 134, 122, +-74, -59, -269, -259, -330, -353, -184, -268, +102, -7, 355, 302, 415, 453, 233, 350, +-94, 49, -331, -294, -347, -479, -189, -385, +62, -102, 283, 218, 345, 441, 203, 437, +-58, 184, -305, -131, -411, -345, -292, -373, +-28, -200, 237, 50, 386, 187, 358, 166, +175, 80, -67, -9, -263, -61, -344, -16, +-245, 83, 8, 125, 245, 79, 318, -13, +186, -128, -72, -210, -297, -189, -361, -87, +-231, 45, 25, 144, 286, 177, 439, 161, +411, 112, 192, 21, -154, -98, -453, -183, +-538, -192, -355, -114, 8, 27, 361, 160, +525, 209, 401, 176, 42, 72, -342, -69, +-518, -187, -385, -239, -19, -212, 378, -87, +572, 80, 413, 217, -36, 303, -458, 280, +-565, 97, -346, -133, 39, -289, 390, -324, +475, -199, 279, 53, 11, 241, -187, 260, +-289, 147, -273, -39, -191, -201, -74, -235, +116, -130, 274, 35, 281, 194, 174, 254, +4, 173, -177, 34, -235, -82, -116, -125, +42, -81, 151, -25, 166, -26, 33, -72, +-170, -141, -279, -178, -223, -132, -46, -8, +160, 173, 298, 354, 285, 396, 134, 265, +-50, 46, -166, -168, -193, -272, -141, -226, +-28, -142, 67, -97, 97, -83, 79, -84, +18, -95, -37, -20, -51, 138, -40, 273, +-15, 323, 13, 244, 10, 13, -41, -229, +-96, -299, -111, -187, -39, 6, 114, 179, +254, 224, 308, 144, 217, 20, -20, -98, +-272, -192, -385, -240, -327, -188, -140, -42, +92, 106, 250, 169, 267, 142, 160, 53, +-27, -49, -185, -77, -223, -14, -115, 85, +114, 185, 326, 237, 359, 153, 187, -47, +-121, -243, -430, -348, -529, -332, -319, -175, +47, 27, 374, 172, 525, 243, 409, 234, +75, 134, -285, -19, -478, -147, -423, -185, +-165, -120, 160, 29, 394, 185, 434, 257, +256, 202, -46, 49, -307, -156, -394, -320, +-280, -336, -33, -208, 246, -1, 427, 188, +380, 282, 96, 259, -269, 155, -521, -1, +-542, -171, -266, -262, 191, -209, 545, -61, +606, 105, 379, 216, -12, 194, -349, 56, +-448, -76, -322, -146, -79, -147, 177, -61, +281, 56, 183, 128, -4, 124, -146, 50, +-175, -47, -88, -103, 32, -94, 89, -17, +95, 51, 108, 55, 124, 4, 77, -58, +-78, -114, -266, -122, -351, -66, -227, 18, +88, 121, 411, 239, 529, 300, 371, 250, +23, 111, -342, -102, -551, -344, -502, -458, +-232, -390, 123, -203, 372, 66, 410, 319, +288, 420, 99, 351, -76, 176, -203, -58, +-266, -270, -232, -364, -83, -295, 137, -96, +315, 166, 334, 399, 143, 463, -159, 271, +-386, -93, -414, -431, -224, -571, 81, -420, +320, -38, 373, 371, 229, 564, -1, 452, +-156, 114, -160, -288, -84, -538, -30, -495, +-13, -202, 7, 189, 67, 477, 118, 520, +65, 307, -67, -21, -175, -304, -178, -405, +-64, -295, 104, -68, 200, 153, 157, 257, +47, 203, -32, 17, -80, -185, -106, -248, +-72, -146, 20, 32, 95, 196, 116, 253, +76, 154, -40, -16, -171, -140, -220, -202, +-168, -184, -33, -53, 151, 107, 294, 193, +290, 216, 133, 169, -68, 21, -198, -128, +-228, -199, -167, -239, -44, -207, 71, -84, +132, 27, 146, 126, 91, 220, -31, 232, +-123, 143, -116, 27, -70, -103, -8, -198, +53, -178, 80, -62, 96, 80, 113, 188, +60, 191, -61, 79, -149, -82, -154, -220, +-87, -272, 19, -166, 78, 45, 70, 241, +61, 332, 58, 233, 24, -23, -9, -251, +-33, -341, -75, -285, -97, -65, -63, 206, +-5, 343, 77, 324, 150, 186, 138, -48, +43, -239, -66, -264, -135, -157, -116, 4, +-9, 120, 74, 96, 55, -47, -22, -169, +-85, -196, -85, -102, -24, 90, 76, 255, +170, 302, 187, 246, 80, 89, -80, -104, +-181, -225, -179, -227, -82, -150, 58, -33, +144, 40, 123, 44, 15, 21, -102, 8, +-140, 25, -81, 49, 28, 40, 135, -2, +177, -42, 101, -50, -53, -12, -164, 63, +-168, 121, -85, 111, 38, 43, 149, -48, +168, -126, 70, -131, -73, -33, -188, 72, +-196, 86, -34, 0, 191, -142, 280, -249, +172, -197, -52, 12, -261, 256, -298, 406, +-141, 380, 59, 157, 192, -155, 232, -343, +157, -325, 33, -148, -52, 80, -105, 195, +-138, 90, -118, -106, -57, -220, 18, -199, +92, -32, 125, 207, 86, 337, -4, 282, +-104, 98, -152, -116, -75, -259, 88, -222, +194, -31, 169, 168, 48, 232, -107, 98, +-232, -148, -232, -328, -86, -330, 114, -161, +253, 107, 269, 330, 159, 388, -41, 275, +-224, 48, -274, -203, -186, -325, -52, -259, +61, -68, 129, 132, 139, 234, 127, 206, +111, 89, 61, -61, -17, -191, -74, -242, +-103, -198, -110, -70, -100, 115, -80, 271, +-44, 287, 1, 149, 50, -59, 108, -232, +146, -284, 115, -138, 48, 116, 13, 307, +-12, 318, -57, 110, -114, -218, -157, -451, +-154, -427, -70, -169, 70, 174, 194, 428, +222, 468, 129, 283, -24, -32, -129, -310, +-139, -402, -84, -262, -26, 26, 12, 267, +34, 295, 41, 126, 34, -101, 26, -248, +7, -236, -20, -88, -16, 86, 31, 181, +64, 180, 40, 83, -24, -64, -73, -138, +-81, -88, -32, 30, 44, 125, 60, 132, +-9, 27, -72, -102, -68, -159, -26, -129, +49, -63, 136, 3, 167, 67, 107, 105, +-32, 95, -165, 67, -178, 31, -74, -6, +52, -43, 123, -62, 74, -65, -93, -39, +-200, 15, -106, 68, 86, 78, 211, 28, +198, -48, 63, -104, -115, -93, -210, -16, +-154, 70, 17, 120, 182, 111, 214, 35, +92, -53, -79, -98, -189, -93, -174, -35, +-56, 38, 65, 55, 96, 10, 23, -28, +-66, -23, -87, 8, -28, 47, 71, 72, +150, 57, 174, 3, 127, -43, 24, -53, +-95, -48, -179, -18, -186, 21, -111, 30, +-8, -23, 67, -90, 83, -122, 35, -84, +-41, 44, -54, 217, 11, 307, 101, 258, +162, 82, 133, -180, -3, -395, -146, -415, +-197, -247, -144, 26, -25, 285, 121, 398, +219, 313, 205, 96, 70, -141, -122, -289, +-287, -284, -326, -138, -173, 69, 93, 230, +299, 283, 330, 205, 192, 18, -20, -201, +-188, -346, -233, -345, -151, -194, 13, 68, +171, 337, 225, 463, 150, 354, -14, 78, +-172, -241, -230, -450, -191, -397, -120, -111, +-28, 226, 92, 437, 197, 396, 251, 103, +218, -273, 79, -508, -99, -490, -210, -210, +-190, 201, -65, 519, 58, 568, 108, 323, +81, -90, -8, -435, -124, -497, -167, -266, +-96, 92, 45, 388, 195, 463, 253, 266, +157, -76, -31, -383, -201, -511, -269, -398, +-187, -101, 12, 217, 179, 390, 228, 362, +173, 192, 43, -8, -111, -116, -200, -103, +-168, -38, -65, 19, 53, 55, 155, 43, +169, -18, 85, -95, -50, -172, -190, -207, +-248, -172, -169, -70, 9, 84, 218, 243, +377, 326, 361, 293, 131, 134, -163, -97, +-376, -280, -410, -317, -224, -200, 71, 17, +290, 206, 315, 243, 161, 105, -67, -86, +-224, -212, -235, -206, -118, -43, 64, 162, +191, 247, 191, 189, 99, 28, -15, -170, +-87, -270, -85, -210, -24, -40, 49, 157, +96, 273, 75, 222, -20, 54, -131, -130, +-224, -253, -256, -235, -154, -83, 68, 94, +297, 216, 405, 267, 325, 199, 73, 16, +-217, -168, -367, -292, -295, -309, -57, -169, +181, 49, 270, 227, 187, 316, 26, 269, +-115, 68, -199, -163, -217, -308, -173, -294, +-80, -101, 50, 163, 194, 329, 289, 320, +245, 148, 78, -112, -98, -311, -191, -324, +-160, -161, -12, 63, 148, 229, 176, 237, +29, 92, -203, -87, -364, -184, -304, -145, +-46, -5, 261, 123, 446, 166, 377, 122, +81, 13, -238, -103, -381, -157, -304, -138, +-55, -62, 215, 42, 319, 135, 241, 199, +82, 197, -78, 110, -187, -55, -221, -245, +-180, -362, -80, -299, 51, -71, 168, 190, +197, 342, 93, 316, -77, 124, -188, -118, +-198, -266, -87, -246, 116, -87, 277, 146, +321, 322, 241, 326, 41, 149, -200, -105, +-355, -303, -354, -362, -210, -288, 17, -114, +193, 91, 245, 220, 196, 236, 56, 144, +-114, -15, -203, -125, -163, -99, -8, 24, +189, 145, 309, 184, 255, 116, 56, -1, +-179, -101, -308, -159, -255, -168, -81, -132, +101, -83, 193, -38, 153, 7, 14, 46, +-138, 87, -203, 155, -138, 196, 1, 146, +109, 27, 148, -104, 147, -202, 111, -193, +61, -85, 31, 55, 10, 163, -28, 179, +-83, 81, -110, -65, -106, -171, -94, -178, +-88, -75, -76, 81, -35, 188, 30, 184, +102, 68, 149, -109, 136, -250, 52, -265, +-41, -129, -50, 109, 27, 329, 113, 394, +130, 263, 54, -3, -78, -264, -203, -384, +-235, -307, -161, -107, -53, 123, 34, 286, +82, 279, 81, 111, 49, -101, 32, -239, +46, -250, 80, -132, 112, 44, 99, 182, +42, 234, -26, 205, -78, 103, -91, -41, +-61, -165, -20, -221, -28, -185, -80, -57, +-113, 85, -86, 171, -4, 160, 90, 63, +158, -72, 143, -163, 47, -166, -35, -79, +-44, 64, -2, 185, 37, 202, 41, 107, +15, -34, -24, -147, -65, -169, -82, -75, +-38, 66, 25, 147, 40, 137, 12, 53, +-44, -88, -108, -218, -120, -249, -44, -161, +76, 16, 164, 204, 187, 314, 138, 291, +37, 152, -81, -35, -154, -189, -122, -247, +-15, -199, 103, -73, 138, 55, 33, 125, +-122, 98, -201, 3, -162, -100, -37, -136, +94, -79, 146, 39, 114, 155, 53, 221, +-4, 191, -28, 79, -18, -54, -14, -152, +-3, -176, 18, -115, 29, -33, 32, 14, +43, 20, 28, -13, -31, -53, -99, -51, +-144, -1, -132, 63, -66, 119, 22, 130, +110, 99, 161, 58, 151, 24, 99, -18, +26, -68, -51, -127, -95, -182, -95, -173, +-79, -80, -45, 40, 24, 134, 93, 171, +118, 139, 73, 64, -29, -11, -130, -63, +-155, -80, -96, -70, -19, -44, 50, -5, +111, 30, 139, 68, 116, 93, 44, 78, +-70, 0, -174, -100, -153, -159, 13, -130, +201, -34, 271, 70, 165, 117, -58, 93, +-270, 40, -363, 2, -296, -7, -84, 0, +183, 3, 344, -10, 330, -28, 181, -43, +-33, -42, -197, -14, -206, 22, -102, 45, +-12, 37, 37, -17, 66, -74, 66, -89, +54, -51, 30, 20, -14, 99, -46, 142, +-50, 122, -49, 60, -36, -25, -1, -113, +26, -164, 32, -141, 31, -74, 8, 17, +-7, 108, 13, 151, 51, 115, 74, 32, +46, -59, -34, -120, -93, -119, -82, -47, +-31, 46, 26, 108, 73, 117, 65, 76, +-2, -7, -85, -81, -124, -111, -96, -98, +-24, -52, 78, -1, 184, 24, 217, 39, +144, 78, 12, 99, -126, 79, -229, 25, +-219, -50, -70, -125, 119, -137, 209, -69, +145, 35, 0, 128, -123, 157, -156, 88, +-90, -30, 5, -127, 57, -166, 67, -107, +59, 24, 32, 124, 16, 141, 25, 84, +25, -19, 25, -96, 29, -108, 2, -56, +-29, 24, -31, 92, -42, 99, -90, 55, +-136, -22, -134, -98, -46, -128, 106, -100, +218, -39, 222, 38, 130, 102, -8, 124, +-104, 112, -107, 67, -52, -10, 0, -81, +34, -99, 32, -70, -13, 1, -68, 81, +-100, 93, -88, 11, -32, -111, 41, -216, +103, -215, 119, -84, 69, 113, -18, 276, +-78, 332, -73, 235, 2, 45, 99, -139, +128, -239, 65, -199, -38, -59, -117, 70, +-123, 105, -66, 39, -6, -94, 12, -198, +8, -192, 2, -83, 8, 72, 44, 224, +89, 312, 113, 296, 101, 163, 30, -40, +-84, -233, -168, -330, -159, -295, -65, -133, +76, 85, 188, 243, 186, 255, 64, 115, +-103, -96, -218, -263, -203, -281, -55, -138, +145, 101, 264, 292, 213, 335, 19, 213, +-188, -2, -273, -194, -185, -238, 4, -130, +165, 29, 221, 125, 163, 103, 27, -32, +-82, -180, -102, -233, -56, -152, 8, 27, +54, 225, 49, 328, -8, 272, -70, 102, +-98, -93, -90, -214, -64, -214, -27, -118, +34, -12, 89, 56, 101, 61, 81, 24, +47, -10, 16, -12, 7, -1, 20, 13, +32, 29, 23, 34, -20, 15, -85, -13, +-129, -33, -138, -36, -92, -9, 11, 53, +107, 113, 124, 116, 72, 40, 2, -104, +-20, -241, 21, -284, 72, -173, 75, 50, +33, 273, -32, 363, -77, 270, -64, 41, +-2, -197, 47, -304, 42, -223, -30, -14, +-137, 185, -210, 246, -180, 145, -40, -36, +140, -184, 238, -207, 212, -103, 112, 40, +12, 125, -29, 126, -7, 52, 11, -40, +-24, -72, -89, -26, -128, 31, -123, 60, +-76, 50, -9, 5, 47, -42, 91, -46, +123, -19, 124, 10, 72, 26, -16, 23, +-110, 13, -164, -2, -113, -28, 26, -65, +158, -83, 191, -81, 100, -57, -64, -13, +-179, 59, -161, 137, -44, 182, 89, 156, +162, 69, 117, -43, -7, -125, -117, -154, +-158, -135, -117, -72, -3, 15, 120, 79, +171, 95, 141, 60, 57, -39, -40, -142, +-86, -170, -65, -90, -13, 58, 32, 220, +46, 294, 10, 225, -55, 45, -97, -156, +-89, -276, -31, -227, 34, -57, 59, 121, +55, 211, 37, 157, 17, -27, 20, -222, +27, -311, 0, -240, -20, -33, 1, 208, +20, 360, 11, 339, -7, 166, -24, -50, +-16, -187, 5, -208, -2, -120, -27, -2, +-36, 61, -24, 36, 17, -38, 62, -123, +55, -148, 24, -61, 28, 80, 42, 187, +22, 223, -27, 161, -68, 18, -74, -103, +-38, -162, 3, -162, 18, -99, 7, -6, +-8, 65, -19, 116, -22, 118, -17, 57, +10, -23, 56, -70, 103, -86, 116, -63, +63, -8, -26, 42, -84, 42, -88, -3, +-49, -55, 13, -74, 58, -33, 38, 40, +-33, 91, -91, 81, -62, 38, 63, 9, +184, 20, 188, 44, 56, 48, -133, -18, +-245, -142, -191, -250, -24, -257, 120, -130, +156, 108, 89, 328, -8, 396, -70, 260, +-73, -7, -4, -243, 97, -328, 128, -232, +46, -16, -90, 194, -188, 262, -163, 176, +-9, -9, 143, -191, 179, -277, 103, -217, +-19, -59, -96, 115, -71, 225, 6, 234, +58, 146, 70, 21, 47, -90, -14, -137, +-68, -104, -82, -20, -45, 53, 16, 83, +52, 65, 43, 5, 3, -61, -67, -114, +-132, -138, -136, -124, -67, -53, 46, 51, +177, 152, 248, 199, 191, 180, 44, 95, +-86, -9, -127, -70, -84, -71, -24, -50, +14, -31, 22, -36, -2, -86, -39, -160, +-44, -191, -26, -130, -16, 7, -3, 166, +3, 271, -1, 264, 40, 146, 136, -2, +216, -111, 192, -136, 49, -95, -140, -35, +-255, -4, -232, 0, -122, -28, -16, -67, +58, -72, 111, -23, 129, 31, 87, 64, +4, 75, -89, 45, -128, -6, -70, -37, +53, -37, 150, -17, 175, 33, 129, 69, +51, 72, -12, 52, -55, 21, -90, -28, +-77, -66, -29, -98, -6, -113, -30, -108, +-77, -73, -118, -6, -105, 87, -18, 152, +93, 159, 173, 120, 198, 36, 154, -70, +58, -140, -62, -133, -157, -66, -188, 27, +-130, 94, -2, 98, 130, 32, 187, -48, +147, -84, 35, -51, -110, 8, -211, 61, +-179, 78, -51, 50, 71, -8, 129, -70, +118, -120, 55, -125, 5, -74, 20, -1, +72, 82, 95, 151, 56, 172, -28, 133, +-94, 50, -111, -70, -77, -148, -4, -136, +49, -53, 13, 42, -89, 92, -160, 28, +-140, -114, -38, -223, 102, -213, 210, -75, +229, 149, 153, 344, 41, 393, -50, 249, +-91, -4, -74, -214, -20, -286, 29, -216, +36, -66, -19, 66, -93, 86, -104, 15, +-23, -78, 72, -134, 103, -104, 58, 18, +-37, 144, -115, 212, -99, 199, 16, 97, +140, -43, 187, -128, 145, -154, 46, -130, +-69, -60, -153, 19, -157, 79, -103, 116, +-48, 113, -11, 45, 23, -55, 57, -150, +78, -194, 68, -164, 29, -41, -10, 115, +-16, 230, 17, 254, 79, 181, 113, 27, +66, -122, -32, -189, -113, -160, -137, -74, +-78, 24, 28, 86, 102, 77, 99, 12, +31, -63, -72, -98, -132, -76, -110, -21, +-46, 37, 26, 104, 107, 142, 161, 133, +148, 75, 59, -16, -69, -118, -176, -157, +-181, -119, -65, -41, 106, 30, 198, 58, +139, 31, -3, -6, -115, -11, -148, 12, +-90, 50, 13, 75, 88, 57, 114, -8, +115, -73, 93, -96, 50, -54, -21, 26, +-113, 85, -169, 75, -133, 14, -27, -60, +101, -94, 165, -55, 112, 49, -24, 129, +-147, 126, -192, 28, -123, -115, 22, -222, +148, -219, 196, -86, 157, 111, 52, 277, +-72, 320, -140, 216, -106, 9, -25, -194, +40, -303, 75, -259, 85, -97, 55, 94, +-2, 205, -62, 180, -111, 50, -112, -100, +-17, -198, 130, -181, 220, -42, 169, 130, +-12, 245, -193, 263, -237, 164, -125, -19, +62, -180, 209, -254, 214, -212, 71, -80, +-113, 64, -232, 132, -212, 115, -64, 18, +111, -100, 200, -147, 159, -85, 23, 32, +-95, 160, -99, 234, -22, 202, 54, 86, +95, -55, 80, -170, 27, -203, -6, -155, +-9, -65, 0, 36, 13, 89, -7, 62, +-63, -5, -103, -49, -112, -62, -85, -19, +21, 54, 140, 121, 163, 152, 94, 132, +-1, 48, -89, -63, -125, -155, -85, -187, +-2, -150, 74, -67, 98, 42, 57, 144, +8, 179, -8, 124, 3, 26, 21, -94, +17, -184, -33, -173, -91, -59, -107, 69, +-69, 160, 15, 149, 107, 42, 158, -76, +160, -120, 101, -70, 2, 65, -69, 181, +-68, 187, -21, 94, 13, -64, -27, -233, +-131, -313, -208, -251, -175, -96, -38, 89, +128, 227, 228, 265, 218, 197, 130, 80, +23, -34, -73, -87, -133, -75, -125, -23, +-57, 22, 11, 23, 51, -34, 67, -99, +65, -138, 47, -124, 32, -39, 3, 69, +-53, 126, -81, 114, -48, 54, 17, -20, +92, -41, 138, 6, 108, 84, 15, 123, +-95, 82, -190, -39, -198, -163, -84, -233, +86, -210, 215, -80, 226, 108, 99, 247, +-93, 270, -246, 157, -283, -49, -179, -238, +45, -290, 278, -176, 393, 49, 317, 256, +76, 310, -198, 180, -338, -58, -269, -266, +-57, -323, 146, -177, 227, 74, 178, 278, +37, 305, -138, 145, -233, -110, -180, -297, +-7, -304, 204, -140, 329, 87, 254, 255, +26, 275, -203, 151, -305, -13, -244, -127, +-65, -153, 102, -101, 170, -11, 144, 39, +55, 33, -61, 6, -141, -4, -139, -18, +-58, -46, 67, -78, 185, -75, 224, -24, +157, 87, 7, 212, -149, 275, -212, 212, +-131, 24, 49, -218, 208, -386, 234, -366, +103, -161, -113, 125, -268, 322, -269, 303, +-136, 87, 50, -166, 207, -293, 253, -203, +169, 59, 6, 330, -165, 424, -263, 274, +-207, -57, -10, -379, 216, -498, 337, -345, +289, -25, 96, 274, -148, 400, -325, 299, +-343, 35, -211, -249, -20, -385, 157, -305, +268, -60, 271, 228, 199, 434, 89, 433, +-49, 235, -171, -61, -206, -324, -142, -449, +-10, -379, 130, -165, 181, 107, 102, 310, +-45, 343, -164, 202, -169, -18, -60, -207, +68, -257, 121, -149, 86, 28, -18, 185, +-112, 239, -108, 158, -19, 1, 74, -124, +125, -180, 105, -139, 40, -30, -11, 57, +-21, 70, -6, 36, 7, -25, -5, -61, +-21, -29, -17, 33, -3, 80, 7, 95, +1, 50, -29, -36, -43, -88, -14, -76, +32, -17, 70, 49, 99, 79, 89, 41, +26, -40, -62, -123, -132, -141, -151, -76, +-95, 51, 11, 173, 101, 228, 114, 157, +67, -2, 17, -150, -14, -207, -34, -153, +-46, -29, -56, 78, -47, 105, 5, 64, +90, -24, 149, -98, 145, -90, 63, -10, +-49, 83, -136, 145, -167, 128, -108, 55, +47, -21, 196, -69, 246, -80, 167, -56, +-23, -53, -243, -76, -350, -85, -296, -55, +-126, 18, 104, 118, 301, 189, 358, 173, +256, 66, 42, -90, -186, -198, -311, -190, +-271, -77, -101, 69, 117, 175, 265, 166, +272, 58, 153, -71, -40, -142, -226, -131, +-275, -35, -139, 78, 101, 142, 310, 127, +361, 45, 191, -70, -106, -146, -368, -167, +-462, -140, -324, -71, -19, 21, 285, 130, +445, 229, 402, 261, 178, 188, -119, 40, +-336, -141, -380, -277, -237, -283, 6, -156, +209, 16, 282, 146, 205, 169, 9, 79, +-187, -55, -254, -122, -159, -77, 31, 55, +232, 193, 344, 236, 299, 155, 99, -3, +-145, -163, -315, -261, -356, -241, -249, -138, +-33, -17, 165, 70, 256, 129, 231, 148, +132, 144, 7, 122, -98, 76, -158, -3, +-155, -91, -94, -154, -12, -158, 64, -95, +114, 12, 104, 110, 49, 147, -2, 102, +-32, 6, -47, -95, -42, -146, -28, -102, +-7, 3, 20, 96, 34, 128, 26, 88, +11, -20, -5, -112, 7, -128, 60, -65, +119, 40, 137, 123, 90, 129, -21, 63, +-138, -46, -201, -149, -197, -168, -120, -87, +8, 40, 99, 148, 121, 187, 100, 114, +61, -21, 21, -143, 15, -183, 28, -122, +27, 16, 8, 147, -26, 207, -55, 152, +-63, 10, -67, -135, -69, -200, -52, -180, +-9, -84, 56, 30, 141, 99, 195, 114, +168, 92, 58, 47, -88, -3, -194, -34, +-185, -45, -75, -33, 59, 4, 132, 60, +112, 111, 28, 107, -47, 9, -70, -140, +-44, -262, -3, -280, 23, -147, 38, 92, +46, 293, 19, 356, -39, 246, -100, 15, +-123, -196, -92, -265, 1, -175, 123, 6, +211, 166, 206, 183, 93, 63, -73, -106, +-192, -217, -188, -205, -54, -71, 123, 83, +220, 175, 159, 172, -6, 100, -154, 21, +-201, -17, -142, -18, -13, 4, 105, 7, +147, -24, 97, -68, 7, -95, -81, -91, +-123, -53, -98, -12, -26, 4, 47, 24, +94, 57, 104, 101, 99, 142, 87, 152, +31, 81, -80, -54, -174, -192, -199, -264, +-131, -217, 18, -58, 171, 125, 231, 235, +171, 220, 39, 94, -73, -47, -105, -117, +-60, -93, 14, -13, 83, 63, 83, 68, +7, 4, -81, -86, -129, -135, -136, -115, +-98, -32, -28, 51, 46, 103, 94, 111, +103, 95, 74, 75, 46, 66, 25, 47, +12, 1, 9, -74, -5, -155, -57, -204, +-115, -194, -125, -116, -70, 2, 28, 118, +141, 193, 209, 202, 195, 150, 97, 73, +-31, 3, -126, -48, -140, -69, -84, -52, +-16, -31, 14, -41, -6, -73, -64, -105, +-95, -115, -60, -81, 19, 10, 94, 111, +147, 167, 154, 153, 94, 86, -8, -8, +-112, -73, -175, -81, -146, -35, -35, 30, +92, 75, 166, 41, 149, -55, 39, -142, +-88, -161, -159, -111, -140, -6, -30, 89, +115, 133, 203, 123, 196, 82, 91, 31, +-60, 0, -160, -12, -149, -8, -71, -2, +27, -4, 92, -14, 77, -32, -9, -65, +-111, -104, -172, -122, -143, -106, -33, -28, +110, 105, 227, 221, 250, 253, 138, 181, +-29, 16, -147, -170, -176, -271, -102, -236, +37, -95, 131, 69, 112, 162, -12, 135, +-150, 40, -193, -48, -99, -63, 59, -4, +186, 81, 218, 113, 160, 66, 75, -37, +10, -123, -43, -135, -105, -64, -173, 33, +-192, 99, -145, 80, -60, -8, 23, -89, +97, -94, 143, -22, 138, 93, 89, 169, +18, 136, -42, 14, -43, -129, -2, -215, +30, -183, 12, -52, -47, 92, -91, 173, +-56, 152, 24, 48, 70, -73, 65, -130, +25, -93, -35, 4, -61, 94, -31, 128, +35, 95, 94, 27, 116, -25, 82, -41, +11, -40, -62, -46, -94, -59, -80, -91, +-50, -117, -33, -107, -19, -49, -9, 32, +2, 131, 12, 200, 17, 210, 19, 165, +37, 83, 56, -43, 47, -160, 6, -229, +-48, -226, -79, -157, -62, -39, -15, 66, +49, 116, 107, 100, 120, 50, 79, 25, +16, 52, -41, 117, -65, 184, -36, 190, +8, 87, 17, -90, 3, -271, -18, -378, +-26, -347, -26, -184, -45, 23, -81, 188, +-77, 260, -15, 218, 82, 110, 159, 17, +164, -16, 78, 1, -48, 44, -163, 61, +-207, 19, -145, -75, -14, -168, 122, -213, +201, -165, 163, -33, 38, 139, -62, 274, +-74, 310, -22, 202, 57, -16, 97, -251, +66, -385, -6, -354, -76, -162, -119, 106, +-100, 325, -39, 384, 24, 264, 63, 32, +57, -196, -7, -311, -70, -246, -82, -49, +-43, 154, 22, 260, 84, 224, 102, 63, +57, -135, -26, -262, -89, -264, -97, -135, +-41, 72, 43, 247, 108, 298, 120, 202, +84, 8, 23, -183, -38, -263, -76, -186, +-77, 1, -41, 174, 38, 220, 109, 96, +106, -121, 25, -296, -74, -302, -139, -125, +-127, 149, -51, 367, 25, 405, 67, 241, +75, -12, 47, -222, 6, -296, -31, -210, +-51, -29, -41, 111, 11, 129, 57, 27, +59, -128, 7, -231, -58, -198, -80, -38, +-38, 174, 20, 345, 61, 390, 71, 278, +62, 57, 59, -183, 61, -340, 38, -352, +-2, -241, -39, -70, -61, 75, -51, 127, +-14, 94, -8, 35, -36, 0, -60, 27, +-59, 117, -39, 197, 19, 201, 77, 108, +79, -43, 21, -192, -39, -258, -52, -227, +-11, -131, 39, -36, 54, 18, 13, 21, +-56, 31, -101, 82, -58, 175, 57, 256, +161, 264, 180, 157, 110, -40, -17, -253, +-147, -378, -204, -358, -132, -202, 14, 28, +143, 241, 189, 343, 138, 308, 12, 178, +-106, 0, -146, -162, -102, -252, -35, -259, +1, -204, 2, -105, -15, 10, -39, 99, +-39, 141, 2, 146, 70, 129, 119, 110, +133, 104, 110, 105, 58, 87, -20, 23, +-105, -73, -164, -174, -163, -245, -105, -252, +10, -187, 140, -91, 212, 20, 188, 121, +99, 192, -16, 226, -117, 232, -177, 181, +-166, 80, -78, -51, 49, -175, 135, -259, +133, -264, 43, -198, -82, -93, -163, 20, +-138, 111, -24, 166, 109, 196, 186, 209, +182, 201, 107, 164, -3, 88, -107, -28, +-157, -158, -160, -255, -135, -282, -84, -224, +-16, -110, 50, 3, 124, 81, 169, 108, +147, 105, 81, 108, 11, 126, -60, 126, +-98, 93, -80, 13, -21, -105, 47, -211, +87, -234, 53, -169, -31, -45, -97, 87, +-99, 179, -29, 201, 73, 186, 115, 161, +74, 135, -6, 95, -72, 26, -117, -86, +-125, -212, -92, -302, -30, -306, 12, -220, +20, -69, 0, 78, -28, 163, -31, 166, +36, 123, 153, 69, 253, 33, 268, 32, +187, 52, 45, 61, -105, 48, -216, 14, +-235, -30, -160, -70, -47, -80, 33, -61, +66, -16, 38, 42, -43, 77, -122, 50, +-139, -24, -95, -110, -10, -163, 78, -143, +159, -32, 205, 112, 184, 216, 117, 222, +45, 135, -49, -14, -147, -150, -208, -209, +-210, -174, -148, -98, -28, -22, 91, 20, +179, 30, 222, 30, 199, 70, 127, 149, +69, 223, 3, 235, -72, 162, -99, 7, +-88, -163, -107, -270, -150, -268, -196, -187, +-212, -82, -142, -5, 22, 24, 197, 24, +302, 36, 281, 76, 150, 129, -9, 158, +-115, 137, -140, 62, -95, -24, -21, -79, +30, -95, 27, -78, -13, -47, -53, -33, +-45, -30, 13, -13, 97, 30, 154, 74, +140, 111, 62, 102, -37, 31, -133, -66, +-184, -131, -165, -147, -101, -104, -27, -21, +42, 57, 67, 80, 56, 60, 48, 19, +67, -16, 105, -37, 131, -27, 100, 6, +9, 38, -105, 68, -190, 102, -188, 110, +-77, 81, 68, 32, 165, -34, 161, -100, +57, -125, -76, -114, -139, -90, -106, -66, +-8, -54, 83, -61, 98, -52, 49, -8, +-12, 58, -72, 124, -90, 162, -47, 136, +11, 60, 43, -22, 62, -70, 67, -73, +68, -26, 72, 29, 65, 60, 30, 54, +-9, 35, -49, 15, -66, 3, -52, -2, +-50, 2, -90, -20, -116, -72, -98, -136, +-45, -179, 13, -194, 62, -159, 86, -79, +82, 21, 50, 121, 28, 215, 32, 269, +52, 262, 75, 197, 97, 96, 70, -17, +-12, -101, -109, -124, -166, -89, -156, -41, +-82, -15, 10, -33, 92, -89, 127, -148, +94, -155, 34, -87, -1, 39, -22, 161, +-37, 218, -63, 175, -111, 52, -157, -111, +-132, -236, -28, -264, 104, -189, 177, -60, +150, 81, 53, 182, -38, 223, -66, 214, +0, 194, 114, 166, 193, 120, 185, 54, +82, -20, -83, -104, -221, -175, -273, -214, +-222, -225, -103, -225, 24, -196, 95, -125, +112, -18, 102, 106, 74, 212, 43, 251, +25, 201, 1, 87, -27, -33, -52, -108, +-74, -109, -89, -49, -71, 28, -20, 74, +48, 82, 110, 71, 147, 53, 135, 37, +86, 28, 16, 13, -47, -20, -82, -71, +-72, -121, -47, -161, -41, -170, -68, -139, +-108, -73, -120, 14, -53, 97, 60, 142, +143, 141, 147, 95, 102, 30, 37, -14, +-5, 7, 7, 73, 32, 141, 7, 148, +-58, 65, -128, -89, -157, -243, -122, -311, +-25, -245, 92, -86, 178, 105, 180, 243, +108, 268, 18, 185, -41, 51, -58, -88, +-45, -195, -56, -242, -115, -218, -188, -139, +-192, -22, -86, 110, 98, 220, 263, 262, +330, 229, 272, 149, 122, 62, -50, -3, +-152, -28, -171, -43, -145, -89, -106, -175, +-63, -269, -29, -326, 8, -284, 47, -135, +61, 72, 31, 253, -11, 336, -33, 284, +-16, 152, 25, 16, 62, -63, 65, -62, +41, 3, -3, 62, -55, 72, -82, 17, +-49, -81, 17, -173, 99, -200, 166, -142, +163, -20, 70, 113, -47, 205, -140, 205, +-182, 109, -150, -53, -60, -209, 21, -295, +44, -277, -21, -160, -127, 4, -164, 140, +-65, 217, 139, 243, 361, 239, 439, 222, +281, 195, -45, 129, -357, 5, -493, -151, +-371, -283, -54, -346, 284, -309, 440, -186, +336, -22, 63, 101, -192, 148, -305, 122, +-244, 72, -74, 32, 95, 34, 183, 76, +182, 125, 98, 128, -47, 75, -199, -31, +-274, -146, -222, -215, -52, -186, 141, -70, +266, 93, 275, 221, 171, 243, 17, 141, +-99, -31, -133, -197, -87, -269, -13, -202, +19, -48, -40, 89, -151, 135, -228, 66, +-171, -66, 24, -144, 260, -80, 411, 102, +397, 309, 201, 425, -80, 367, -318, 126, +-410, -185, -328, -418, -124, -473, 64, -342, +155, -93, 135, 126, 44, 208, -46, 140, +-74, 6, -45, -103, 40, -106, 165, -3, +254, 132, 232, 194, 107, 144, -89, 6, +-269, -126, -330, -168, -245, -77, -81, 93, +90, 252, 204, 310, 234, 238, 166, 74, +30, -108, -105, -257, -168, -335, -149, -339, +-67, -287, 25, -195, 74, -65, 56, 70, +0, 166, -56, 198, -52, 171, 18, 108, +125, 65, 225, 84, 252, 155, 130, 216, +-94, 216, -304, 128, -405, -44, -337, -234, +-110, -336, 146, -301, 305, -150, 300, 29, +151, 144, -53, 124, -200, -7, -234, -163, +-133, -241, 42, -196, 176, -40, 206, 149, +145, 275, 16, 276, -99, 179, -137, 52, +-75, -25, 44, -20, 145, 63, 150, 138, +67, 136, -71, 30, -219, -151, -285, -332, +-228, -417, -104, -358, 39, -173, 168, 69, +229, 262, 206, 329, 146, 266, 67, 119, +-8, -42, -76, -138, -155, -121, -231, -25, +-240, 85, -168, 151, -26, 142, 145, 59, +278, -38, 313, -86, 266, -72, 175, -40, +59, -25, -78, -57, -205, -133, -290, -215, +-300, -225, -229, -141, -104, 25, 15, 208, +101, 334, 150, 342, 162, 245, 142, 86, +104, -70, 36, -178, -54, -207, -132, -173, +-170, -103, -156, -26, -64, 43, 58, 87, +141, 111, 151, 110, 100, 74, 26, -4, +-13, -95, -5, -161, 13, -174, 3, -127, +-29, -37, -69, 52, -82, 109, -55, 117, +6, 85, 60, 45, 52, 36, -28, 65, +-121, 106, -169, 117, -134, 66, -26, -59, +90, -207, 126, -305, 95, -292, 38, -161, +-3, 55, -9, 259, 2, 360, -2, 316, +2, 164, 14, -30, 11, -167, -6, -194, +-15, -123, -32, -38, -34, 13, -3, 1, +28, -57, 28, -120, 20, -135, 4, -97, +-38, -30, -101, 41, -143, 102, -140, 146, +-77, 174, 17, 192, 96, 188, 132, 137, +132, 47, 106, -57, 83, -140, 66, -164, +27, -132, -55, -81, -141, -44, -196, -53, +-192, -105, -117, -158, 18, -152, 125, -79, +148, 47, 85, 180, -14, 269, -92, 259, +-107, 164, -77, 24, -31, -101, 10, -165, +52, -130, 101, -18, 167, 123, 206, 225, +167, 246, 33, 152, -149, -37, -295, -250, +-323, -398, -217, -425, -27, -314, 127, -113, +172, 91, 107, 217, 3, 243, -82, 181, +-98, 95, -53, 46, 8, 74, 48, 155, +62, 220, 44, 206, 24, 97, 28, -68, +64, -208, 97, -254, 93, -205, 27, -117, +-79, -66, -181, -97, -224, -189, -195, -267, +-113, -247, -11, -99, 85, 142, 142, 374, +153, 496, 105, 465, 20, 321, -64, 125, +-98, -37, -82, -122, -20, -134, 57, -124, +113, -128, 125, -165, 114, -211, 55, -229, +-51, -191, -165, -112, -237, -19, -257, 55, +-211, 93, -111, 82, -7, 54, 49, 54, +67, 83, 82, 130, 126, 182, 184, 206, +229, 175, 219, 101, 155, 15, 49, -71, +-71, -138, -187, -170, -258, -181, -267, -181, +-210, -151, -90, -96, 54, -33, 134, 21, +116, 40, 18, 14, -100, -30, -169, -59, +-130, -30, -14, 77, 116, 234, 186, 362, +158, 390, 56, 283, -48, 78, -125, -155, +-136, -326, -66, -387, 40, -339, 114, -237, +136, -121, 101, -27, 36, 37, -30, 88, +-82, 147, -118, 187, -135, 187, -142, 145, +-129, 69, -117, -25, -126, -80, -136, -68, +-78, -4, 74, 73, 294, 129, 467, 137, +464, 90, 258, 9, -50, -76, -324, -158, +-436, -226, -370, -264, -218, -262, -86, -218, +-25, -128, -45, -3, -80, 129, -50, 234, +63, 297, 206, 306, 314, 270, 304, 195, +182, 103, 20, -1, -102, -92, -148, -152, +-107, -161, -25, -122, 30, -55, 17, -20, +-44, -45, -128, -117, -214, -198, -273, -255, +-256, -238, -175, -141, -44, 8, 120, 169, +266, 310, 322, 388, 272, 385, 125, 313, +-46, 191, -151, 37, -153, -113, -86, -233, +25, -300, 115, -299, 132, -225, 71, -94, +-39, 47, -169, 144, -262, 157, -291, 69, +-251, -83, -156, -215, -33, -247, 75, -145, +172, 65, 237, 290, 239, 420, 185, 390, +120, 213, 51, -36, -12, -235, -71, -304, +-117, -228, -150, -67, -155, 91, -139, 160, +-94, 127, -60, 13, -64, -117, -80, -213, +-75, -237, -57, -191, -16, -88, 47, 30, +107, 127, 140, 181, 158, 196, 153, 186, +120, 177, 49, 165, -51, 136, -147, 77, +-185, -21, -152, -147, -62, -261, 33, -316, +66, -284, -3, -169, -120, -5, -210, 141, +-204, 213, -107, 196, 42, 109, 166, -11, +203, -114, 146, -159, 51, -121, -35, -23, +-64, 100, -44, 202, -15, 239, -5, 190, +9, 83, 9, -48, -6, -154, -36, -191, +-95, -143, -174, -57, -196, 24, -143, 57, +-43, 23, 52, -60, 108, -125, 104, -132, +75, -59, 42, 59, 29, 160, 45, 190, +70, 140, 70, 36, 52, -60, 3, -99, +-71, -65, -152, 6, -210, 64, -226, 73, +-180, 39, -97, -16, -3, -58, 69, -59, +89, -34, 52, -18, 1, -21, -40, -54, +-46, -110, -13, -148, 53, -118, 124, -11, +190, 151, 204, 301, 137, 365, 6, 298, +-141, 123, -258, -101, -283, -275, -224, -329, +-145, -247, -109, -93, -90, 46, -65, 91, +-18, 42, 63, -61, 172, -135, 249, -121, +249, -17, 163, 116, 22, 214, -120, 224, +-186, 142, -165, 21, -79, -63, 9, -79, +43, -33, 8, 30, -48, 62, -115, 41, +-177, -13, -194, -70, -135, -103, -29, -95, +101, -64, 201, -45, 221, -55, 143, -92, +14, -134, -113, -136, -172, -68, -137, 60, +-33, 205, 81, 315, 153, 349, 132, 280, +41, 132, -73, -43, -161, -189, -216, -271, +-232, -254, -216, -160, -148, -33, -34, 67, +96, 112, 191, 76, 216, -19, 142, -128, +7, -182, -124, -156, -181, -42, -146, 118, +-29, 253, 112, 299, 200, 246, 176, 107, +59, -62, -99, -189, -228, -230, -282, -183, +-238, -76, -125, 38, 14, 112, 114, 126, +145, 85, 109, 16, 44, -47, -15, -80, +-40, -82, -50, -67, -54, -46, -62, -24, +-61, 5, -66, 37, -66, 71, -64, 94, +-61, 97, -42, 69, 6, 21, 52, -38, +75, -83, 65, -95, 39, -63, 2, -1, +-27, 78, -47, 127, -47, 113, -40, 27, +-36, -100, -34, -215, -24, -249, -14, -170, +5, 7, -1, 201, -53, 316, -138, 282, +-198, 114, -201, -113, -125, -293, -14, -341, +80, -230, 124, -8, 131, 222, 106, 360, +93, 352, 100, 205, 103, -12, 74, -209, +23, -315, -77, -298, -196, -176, -280, 3, +-287, 164, -209, 233, -55, 192, 90, 62, +164, -96, 130, -204, -2, -205, -177, -105, +-275, 42, -230, 154, -53, 181, 167, 109, +330, -14, 352, -112, 236, -123, 34, -48, +-159, 85, -279, 191, -281, 208, -176, 121, +-12, -20, 109, -153, 116, -210, 4, -180, +-149, -91, -254, -3, -250, 47, -144, 37, +21, -9, 160, -51, 219, -60, 185, -26, +92, 40, -25, 110, -102, 148, -111, 144, +-64, 92, -11, 9, 20, -68, 0, -105, +-66, -85, -161, -26, -218, 29, -209, 45, +-117, 12, 40, -53, 209, -104, 295, -105, +257, -46, 108, 39, -79, 115, -225, 147, +-261, 127, -207, 70, -104, 3, -4, -65, +52, -117, 30, -143, -36, -136, -122, -99, +-177, -29, -160, 46, -72, 102, 46, 112, +175, 92, 244, 64, 219, 53, 122, 58, +-1, 68, -115, 47, -151, -11, -108, -89, +-54, -152, -45, -166, -89, -114, -160, -22, +-175, 60, -112, 92, -14, 64, 43, -2, +24, -65, -67, -83, -150, -39, -159, 46, +-75, 129, 78, 163, 235, 134, 301, 55, +262, -37, 141, -106, -21, -117, -173, -81, +-248, -31, -251, -1, -186, 5, -75, -9, +31, -20, 51, -20, -26, -16, -165, -37, +-274, -63, -275, -71, -126, -29, 107, 67, +324, 197, 416, 289, 339, 280, 132, 143, +-91, -70, -258, -262, -313, -334, -259, -256, +-156, -77, -82, 104, -34, 196, -21, 158, +-24, 23, -16, -127, 11, -208, 27, -181, +42, -66, 45, 76, 28, 172, -11, 187, +-32, 142, -40, 80, -19, 46, 22, 48, +62, 64, 72, 59, 32, 11, -79, -67, +-222, -135, -341, -165, -367, -145, -273, -105, +-70, -77, 133, -82, 251, -85, 245, -57, +148, 21, 22, 119, -47, 203, -38, 219, +36, 166, 118, 77, 141, 12, 65, -10, +-73, 6, -223, 19, -304, 3, -286, -49, +-201, -103, -110, -129, -39, -110, -22, -73, +-46, -56, -66, -77, -44, -121, 11, -143, +99, -98, 175, 20, 201, 167, 168, 275, +119, 293, 67, 219, 28, 97, -6, -6, +-51, -40, -123, -4, -184, 56, -234, 74, +-265, 11, -285, -133, -289, -293, -272, -391, +-199, -366, -77, -224, 75, -19, 231, 155, +352, 234, 387, 194, 351, 85, 261, -16, +133, -33, -4, 57, -114, 227, -220, 382, +-308, 434, -352, 332, -333, 100, -257, -185, +-136, -410, -36, -499, 9, -437, -2, -272, +-26, -96, -31, 5, 9, -3, 59, -82, +93, -153, 110, -137, 117, -6, 121, 205, +149, 405, 154, 521, 92, 521, -43, 425, +-202, 271, -327, 91, -340, -100, -247, -289, +-113, -459, -22, -572, 0, -570, -39, -434, +-74, -188, -77, 77, -45, 265, -2, 306, +54, 213, 114, 56, 187, -52, 240, -40, +223, 109, 104, 310, -77, 459, -258, 459, +-350, 287, -312, -4, -168, -291, -29, -471, +31, -497, -7, -402, -84, -257, -128, -137, +-73, -69, 54, -34, 176, 15, 213, 110, +152, 235, 26, 338, -86, 366, -141, 303, +-128, 175, -91, 40, -80, -54, -119, -87, +-174, -75, -201, -57, -150, -70, -33, -123, +97, -198, 186, -255, 225, -255, 187, -189, +81, -70, -62, 60, -195, 162, -279, 206, +-252, 187, -131, 121, 23, 56, 133, 31, +158, 77, 88, 164, -19, 240, -141, 233, +-235, 115, -253, -96, -191, -315, -92, -467, +32, -479, 126, -339, 139, -94, 89, 154, +29, 313, -37, 320, -60, 184, -12, -15, +76, -170, 136, -194, 128, -52, 12, 197, +-160, 430, -302, 516, -349, 390, -299, 78, +-184, -298, -83, -587, -20, -683, 13, -555, +39, -261, 74, 78, 150, 335, 226, 429, +253, 355, 187, 174, 43, -15, -135, -141, +-253, -152, -276, -53, -214, 113, -122, 265, +-38, 334, -1, 269, -9, 78, -57, -188, +-104, -422, -122, -540, -79, -487, 3, -276, +97, 19, 148, 274, 138, 398, 67, 348, +-22, 174, -103, -20, -135, -130, -98, -110, +-9, 16, 55, 154, 49, 212, -58, 147, +-215, -12, -328, -189, -313, -293, -185, -268, +6, -131, 180, 51, 280, 192, 275, 224, +192, 138, 51, -24, -76, -183, -142, -261, +-140, -215, -110, -53, -99, 163, -141, 333, +-179, 378, -151, 279, -54, 82, 53, -130, +126, -269, 92, -299, -45, -230, -207, -122, +-289, -30, -239, 5, -37, 3, 217, -8, +385, 21, 372, 84, 192, 155, -60, 195, +-245, 187, -308, 129, -262, 52, -159, -13, +-55, -39, -6, -36, 1, -42, -31, -88, +-90, -180, -140, -282, -134, -333, -79, -282, +21, -118, 128, 122, 193, 349, 178, 475, +99, 436, -25, 253, -125, 4, -150, -206, +-86, -291, -8, -232, 19, -76, -57, 86, +-192, 179, -282, 152, -252, 20, -123, -148, +52, -269, 186, -295, 218, -214, 154, -69, +47, 77, -84, 169, -180, 197, -194, 170, +-120, 139, -2, 130, 127, 153, 199, 171, +173, 150, 49, 58, -125, -93, -300, -258, +-389, -372, -349, -396, -193, -315, -11, -162, +117, 7, 141, 130, 111, 187, 87, 189, +108, 175, 148, 172, 154, 175, 74, 161, +-56, 109, -172, 25, -226, -49, -218, -68, +-153, -30, -88, 32, -49, 50, -48, -34, +-71, -217, -110, -413, -126, -508, -102, -420, +-20, -150, 83, 191, 176, 459, 224, 543, +212, 432, 121, 195, -16, -37, -155, -161, +-249, -135, -257, -5, -142, 151, 25, 235, +146, 200, 144, 38, 17, -192, -187, -416, +-350, -547, -392, -538, -297, -376, -123, -116, +73, 156, 221, 357, 299, 441, 301, 407, +250, 305, 160, 192, 61, 113, -61, 83, +-190, 87, -294, 81, -335, 27, -300, -76, +-179, -209, -33, -335, 67, -423, 85, -445, +29, -387, -91, -253, -194, -67, -208, 127, +-105, 288, 89, 383, 301, 404, 410, 361, +372, 278, 199, 183, -32, 105, -236, 47, +-345, 10, -370, -32, -318, -90, -226, -171, +-138, -254, -96, -322, -79, -351, -71, -344, +-25, -288, 69, -185, 173, -31, 218, 150, +195, 320, 117, 425, 26, 430, -34, 323, +-36, 144, -6, -20, 31, -86, 22, -32, +-50, 90, -177, 182, -300, 154, -362, -17, +-333, -272, -246, -502, -135, -606, -28, -528, +79, -292, 172, 24, 248, 312, 281, 480, +253, 492, 159, 369, 48, 173, -62, -17, +-147, -132, -187, -142, -163, -55, -118, 71, +-89, 167, -101, 174, -140, 89, -194, -72, +-210, -254, -169, -407, -80, -472, 23, -427, +127, -253, 206, 18, 240, 318, 209, 543, +132, 608, 27, 471, -77, 189, -164, -123, +-211, -330, -217, -354, -186, -199, -141, 38, +-87, 221, -37, 256, 17, 128, 52, -103, +53, -331, 1, -453, -91, -423, -162, -256, +-135, -18, -29, 212, 110, 364, 215, 416, +234, 375, 151, 273, 31, 146, -101, 20, +-206, -91, -241, -174, -203, -213, -148, -210, +-96, -165, -84, -99, -112, -35, -131, -10, +-93, -33, -27, -88, 51, -127, 120, -111, +176, -16, 221, 124, 240, 258, 192, 329, +83, 318, -70, 227, -218, 94, -319, -41, +-338, -145, -297, -203, -200, -214, -72, -196, +45, -162, 96, -124, 89, -88, 35, -58, +-33, -21, -89, 36, -102, 96, -73, 139, +-6, 147, 79, 122, 161, 81, 184, 55, +151, 59, 87, 88, 21, 119, -59, 118, +-148, 70, -243, -16, -316, -114, -347, -208, +-298, -277, -184, -310, -40, -290, 84, -219, +174, -83, 203, 93, 170, 258, 100, 349, +39, 344, 3, 243, 6, 91, 15, -47, +11, -102, -18, -62, -57, 39, -108, 136, +-156, 166, -196, 77, -208, -114, -178, -332, +-111, -476, -58, -480, -26, -329, -11, -75, +7, 179, 48, 346, 130, 393, 207, 346, +255, 264, 250, 202, 161, 162, -23, 108, +-232, -5, -403, -172, -457, -339, -373, -422, +-191, -369, -4, -202, 133, -3, 178, 134, +151, 155, 86, 75, 20, -24, -32, -58, +-50, 10, -53, 143, -39, 270, -5, 317, +44, 252, 67, 98, 68, -69, 33, -193, +-36, -232, -121, -188, -185, -95, -236, -22, +-255, -4, -231, -59, -154, -152, -46, -220, +84, -203, 202, -87, 291, 109, 313, 322, +249, 457, 95, 442, -100, 283, -292, 37, +-401, -212, -379, -367, -235, -370, -47, -228, +136, -9, 258, 192, 275, 284, 166, 230, +-22, 54, -245, -170, -406, -349, -422, -403, +-272, -308, -23, -99, 245, 163, 427, 396, +460, 516, 330, 469, 89, 276, -182, -1, +-366, -266, -408, -422, -302, -406, -121, -240, +37, -2, 87, 197, 46, 270, -43, 183, +-121, -7, -152, -204, -115, -316, -37, -292, +63, -131, 139, 99, 181, 313, 180, 434, +150, 421, 88, 276, 9, 50, -85, -182, +-179, -347, -258, -383, -286, -279, -259, -84, +-173, 109, -60, 209, 50, 172, 116, 23, +129, -157, 72, -269, -15, -253, -82, -97, +-90, 145, -27, 363, 99, 456, 211, 378, +241, 153, 151, -131, -18, -343, -206, -399, +-330, -287, -357, -72, -283, 137, -136, 231, +31, 187, 146, 47, 166, -96, 79, -164, +-61, -133, -178, -45, -195, 40, -115, 70, +37, 48, 191, 9, 279, -2, 255, 27, +146, 92, -10, 147, -141, 151, -206, 98, +-206, 18, -190, -62, -183, -118, -194, -142, +-189, -148, -148, -143, -66, -121, 34, -83, +138, -35, 205, 21, 218, 65, 172, 77, +84, 66, -24, 49, -82, 50, -61, 91, +5, 168, 50, 248, 41, 268, -40, 189, +-159, 13, -284, -216, -360, -420, -352, -526, +-231, -489, -36, -317, 179, -56, 314, 204, +318, 386, 203, 447, 69, 396, -17, 250, +-39, 69, -29, -83, -21, -170, -37, -194, +-71, -161, -131, -95, -195, -32, -234, 1, +-197, 5, -90, -13, 48, -33, 138, -32, +143, 2, 77, 72, 5, 158, -39, 215, +-49, 192, -52, 75, -42, -119, -43, -323, +-59, -459, -82, -453, -78, -274, -36, 44, +53, 398, 150, 667, 198, 749, 145, 602, +8, 259, -167, -177, -302, -568, -362, -808, +-313, -831, -177, -627, 2, -256, 149, 158, +228, 501, 229, 699, 182, 728, 107, 586, +38, 334, -22, 47, -79, -220, -136, -437, +-162, -569, -166, -592, -154, -490, -125, -270, +-61, 25, 5, 319, 61, 525, 86, 580, +67, 476, 3, 244, -62, -51, -97, -324, +-77, -510, -15, -580, 73, -518, 141, -298, +159, 50, 97, 447, -10, 789, -102, 953, +-148, 831, -155, 412, -127, -208, -105, -835, +-115, -1253, -154, -1301, -160, -940, -124, -276, +-36, 474, 99, 1060, 251, 1293, 340, 1111, +303, 602, 149, -48, -44, -613, -203, -906, +-267, -852, -238, -519, -142, -54, -41, 373, +29, 613, 51, 596, 39, 365, 1, 23, +-58, -310, -130, -538, -167, -606, -154, -503, +-71, -251, 63, 85, 206, 421, 265, 668, +194, 736, 15, 573, -177, 217, -297, -208, +-278, -562, -118, -725, 117, -634, 304, -319, +362, 93, 254, 442, 21, 600, -257, 528, +-463, 262, -534, -104, -445, -434, -243, -603, +30, -561, 301, -325, 484, 26, 532, 368, +457, 589, 255, 615, -29, 443, -317, 137, +-515, -188, -600, -439, -528, -529, -297, -437, +27, -209, 338, 73, 534, 319, 548, 438, +380, 390, 82, 197, -217, -66, -412, -320, +-458, -481, -390, -477, -221, -301, 2, -19, +211, 281, 336, 515, 338, 605, 210, 504, +16, 233, -170, -125, -278, -466, -296, -663, +-223, -635, -113, -387, -7, 2, 74, 398, +123, 637, 138, 617, 134, 347, 113, -49, +72, -402, 1, -552, -73, -441, -122, -137, +-117, 201, -97, 423, -87, 437, -101, 238, +-112, -67, -105, -311, -37, -384, 81, -297, +174, -114, 176, 87, 89, 230, -50, 268, +-174, 218, -225, 121, -161, 8, -28, -113, +135, -212, 261, -248, 282, -198, 171, -72, +-39, 104, -263, 271, -400, 332, -401, 238, +-250, 33, -16, -188, 230, -333, 378, -328, +386, -173, 237, 65, -34, 275, -316, 349, +-474, 237, -449, -12, -260, -275, 24, -420, +333, -371, 533, -115, 545, 263, 342, 594, +-11, 696, -399, 501, -665, 74, -695, -452, +-467, -881, -79, -999, 324, -728, 583, -171, +630, 480, 443, 994, 107, 1157, -255, 890, +-509, 299, -582, -410, -457, -969, -173, -1142, +194, -861, 501, -259, 625, 428, 505, 928, +174, 1043, -284, 732, -690, 134, -866, -514, +-716, -961, -310, -1020, 223, -676, 709, -85, +969, 535, 873, 965, 448, 1036, -139, 719, +-664, 132, -952, -496, -890, -921, -514, -975, +20, -659, 490, -102, 765, 495, 763, 900, +471, 929, 5, 581, -440, 5, -716, -587, +-742, -976, -528, -1002, -144, -642, 248, -22, +530, 645, 616, 1096, 508, 1146, 252, 779, +-54, 128, -288, -566, -377, -1017, -325, -1052, +-181, -688, -44, -105, 23, 458, -14, 767, +-85, 697, -123, 309, -91, -181, 0, -547, +110, -639, 204, -411, 253, 29, 232, 473, +138, 732, -25, 712, -190, 417, -305, -34, +-312, -461, -199, -708, 3, -704, 202, -452, +308, -55, 249, 319, 38, 518, -244, 479, +-458, 235, -493, -102, -309, -376, 14, -436, +348, -264, 550, 46, 557, 361, 361, 535, +50, 468, -265, 204, -463, -107, -462, -343, +-267, -433, 15, -344, 242, -131, 296, 80, +159, 182, -127, 140, -386, -9, -476, -183, +-342, -280, -60, -228, 261, -21, 525, 262, +629, 499, 516, 586, 226, 463, -140, 162, +-439, -181, -604, -427, -572, -527, -370, -477, +-76, -308, 201, -92, 374, 84, 408, 203, +291, 284, 56, 317, -173, 270, -301, 147, +-293, -42, -216, -249, -90, -385, 64, -382, +201, -240, 262, 13, 239, 309, 177, 525, +100, 563, -12, 431, -140, 178, -254, -152, +-309, -462, -288, -626, -167, -590, 12, -379, +150, -44, 191, 309, 156, 530, 68, 510, +-42, 254, -141, -136, -182, -506, -152, -684, +-48, -536, 101, -91, 256, 477, 348, 949, +344, 1130, 222, 914, 17, 352, -227, -362, +-431, -990, -526, -1299, -497, -1178, -353, -700, +-114, -59, 141, 522, 340, 839, 422, 810, +422, 506, 346, 102, 216, -205, 64, -270, +-85, -102, -221, 163, -346, 341, -423, 303, +-410, 26, -328, -368, -154, -679, 95, -732, +384, -456, 592, 69, 620, 640, 462, 998, +162, 957, -219, 501, -596, -239, -825, -995, +-788, -1449, -531, -1382, -129, -759, 298, 246, +642, 1267, 783, 1887, 698, 1866, 480, 1205, +226, 107, -37, -1016, -288, -1717, -503, -1793, +-650, -1314, -747, -493, -729, 340, -519, 874, +-107, 999, 401, 813, 878, 487, 1179, 201, +1169, 50, 770, 0, 78, -48, -698, -153, +-1316, -340, -1572, -554, -1331, -670, -629, -554, +340, -197, 1238, 287, 1751, 727, 1660, 951, +994, 831, -33, 379, -1070, -233, -1740, -776, +-1801, -1052, -1238, -952, -270, -489, 725, 164, +1420, 753, 1587, 1069, 1231, 1026, 512, 632, +-276, 16, -868, -583, -1130, -942, -1021, -976, +-635, -700, -140, -213, 313, 283, 594, 594, +675, 647, 552, 479, 304, 191, -2, -72, +-273, -197, -418, -165, -434, -47, -353, 59, +-201, 71, -17, -24, 162, -166, 278, -251, +352, -209, 358, -47, 276, 158, 111, 322, +-101, 341, -312, 157, -467, -161, -498, -448, +-361, -583, -99, -487, 199, -142, 419, 346, +512, 768, 428, 950, 170, 805, -152, 333, +-394, -316, -511, -879, -463, -1137, -230, -1001, +125, -495, 437, 219, 583, 842, 526, 1099, +280, 912, -103, 371, -470, -318, -672, -866, +-614, -1018, -365, -716, -23, -113, 311, 527, +534, 928, 566, 915, 400, 509, 137, -85, +-117, -601, -318, -812, -396, -638, -342, -183, +-181, 306, -21, 589, 97, 540, 190, 203, +234, -254, 209, -595, 109, -636, -37, -345, +-188, 139, -330, 585, -370, 757, -270, 569, +-27, 106, 277, -404, 523, -703, 603, -625, +445, -190, 100, 397, -294, 825, -612, 833, +-740, 375, -620, -355, -248, -1024, 225, -1293, +617, -988, 780, -219, 617, 680, 162, 1321, +-363, 1423, -706, 941, -742, 110, -477, -713, +12, -1196, 516, -1139, 793, -597, 719, 143, +344, 739, -188, 960, -652, 722, -844, 130, +-656, -533, -191, -937, 316, -899, 649, -434, +702, 255, 463, 864, 31, 1089, -391, 826, +-593, 210, -537, -463, -264, -891, 102, -888, +408, -494, 491, 61, 315, 475, 29, 564, +-207, 336, -317, -23, -276, -299, -125, -348, +79, -157, 199, 135, 201, 336, 109, 330, +-15, 123, -120, -158, -185, -334, -151, -319, +-34, -147, 49, 111, 51, 316, 10, 317, +23, 135, 58, -74, 104, -211, 161, -232, +179, -98, 102, 114, -69, 217, -258, 122, +-387, -111, -407, -357, -264, -483, -7, -361, +272, 6, 437, 465, 414, 786, 233, 821, +5, 530, -185, 3, -278, -584, -250, -986, +-109, -1015, 67, -636, 200, 0, 218, 668, +114, 1111, -65, 1129, -249, 660, -384, -134, +-355, -939, -147, -1415, 145, -1322, 377, -662, +480, 303, 417, 1204, 178, 1667, -145, 1452, +-402, 637, -503, -407, -390, -1260, -120, -1585, +211, -1236, 435, -382, 452, 559, 240, 1198, +-105, 1312, -389, 857, -485, 19, -380, -819, +-89, -1300, 273, -1258, 547, -735, 569, 95, +362, 929, 6, 1439, -397, 1415, -689, 881, +-742, 35, -498, -812, -39, -1345, 449, -1366, +799, -885, 854, -102, 590, 657, 78, 1106, +-464, 1098, -824, 680, -889, 37, -616, -579, +-82, -952, 465, -950, 784, -586, 775, -14, +494, 549, 18, 898, -461, 916, -736, 607, +-708, 92, -418, -442, 24, -790, 439, -823, +655, -562, 594, -149, 320, 272, -48, 575, +-366, 668, -522, 534, -467, 238, -241, -109, +61, -401, 291, -552, 374, -524, 292, -319, +96, -7, -144, 308, -316, 509, -348, 516, +-250, 319, -60, 19, 159, -269, 307, -446, +358, -444, 294, -252, 153, 40, -45, 308, +-235, 432, -359, 360, -404, 113, -343, -210, +-168, -467, 107, -520, 433, -315, 627, 72, +562, 489, 218, 751, -239, 708, -639, 338, +-840, -226, -706, -759, -273, -1015, 283, -858, +771, -352, 1006, 304, 871, 862, 354, 1063, +-303, 794, -836, 208, -1046, -400, -865, -790, +-366, -803, 259, -418, 758, 139, 915, 547, +680, 635, 166, 410, -359, -35, -680, -471, +-672, -645, -385, -488, 29, -132, 382, 258, +544, 506, 457, 491, 201, 256, -88, -23, +-292, -182, -378, -136, -322, 40, -136, 156, +80, 81, 206, -160, 224, -467, 132, -648, +-12, -482, -154, 42, -225, 661, -202, 1033, +-101, 919, 52, 311, 206, -522, 315, -1175, +338, -1310, 220, -783, 12, 214, -204, 1170, +-330, 1596, -363, 1303, -288, 389, -87, -775, +144, -1608, 287, -1684, 287, -1009, 159, 97, +-31, 1163, -239, 1692, -348, 1403, -321, 470, +-145, -616, 119, -1354, 359, -1439, 501, -846, +472, 114, 243, 969, -118, 1297, -468, 960, +-629, 176, -537, -613, -182, -1048, 273, -944, +598, -342, 647, 451, 407, 991, -31, 998, +-490, 477, -782, -310, -773, -983, -469, -1228, +67, -929, 625, -194, 953, 648, 908, 1210, +522, 1293, -69, 913, -625, 209, -916, -547, +-827, -1029, -414, -1101, 158, -819, 621, -297, +747, 286, 506, 708, 41, 816, -439, 596, +-675, 170, -561, -249, -149, -504, 350, -527, +706, -308, 725, 62, 372, 356, -192, 404, +-722, 219, -972, -71, -773, -321, -186, -381, +561, -184, 1115, 173, 1227, 502, 823, 631, +54, 438, -770, -34, -1353, -573, -1442, -921, +-977, -915, -167, -501, 683, 156, 1265, 769, +1395, 1092, 987, 979, 244, 418, -481, -339, +-929, -923, -971, -1090, -618, -781, -51, -88, +439, 695, 606, 1190, 451, 1162, 81, 604, +-303, -272, -547, -1064, -549, -1400, -287, -1152, +137, -425, 513, 496, 674, 1195, 563, 1325, +239, 830, -188, -18, -521, -822, -625, -1244, +-463, -1086, -106, -379, 308, 559, 586, 1299, +606, 1506, 350, 1085, -75, 189, -502, -821, +-730, -1541, -675, -1676, -380, -1169, 59, -214, +496, 782, 746, 1401, 740, 1406, 473, 835, +42, -43, -407, -821, -684, -1149, -709, -906, +-507, -241, -121, 518, 318, 1008, 627, 1001, +719, 533, 557, -139, 212, -695, -208, -886, +-534, -652, -672, -157, -594, 332, -335, 570, +-19, 432, 252, 13, 440, -441, 505, -709, +438, -637, 240, -183, 10, 438, -196, 919, +-333, 1095, -365, 901, -275, 328, -75, -403, +147, -953, 277, -1128, 270, -913, 127, -381, +-74, 250, -267, 721, -332, 881, -227, 703, +-28, 268, 161, -217, 298, -570, 343, -710, +250, -621, 38, -342, -168, 25, -280, 387, +-258, 657, -130, 742, 39, 617, 176, 329, +249, -61, 211, -456, 73, -704, -98, -696, +-232, -457, -327, -98, -338, 226, -204, 375, +34, 321, 263, 135, 424, -82, 467, -190, +376, -85, 151, 166, -129, 367, -390, 381, +-520, 187, -458, -154, -244, -483, 69, -603, +362, -420, 467, 33, 365, 549, 139, 815, +-95, 646, -282, 121, -336, -550, -238, -1062, +-59, -1111, 136, -603, 258, 238, 242, 1042, +120, 1411, -42, 1104, -156, 261, -174, -687, +-54, -1318, 117, -1314, 213, -625, 177, 391, +17, 1191, -201, 1402, -355, 906, -345, -98, +-169, -1086, 72, -1528, 315, -1234, 448, -358, +397, 699, 187, 1410, -83, 1433, -297, 803, +-360, -162, -263, -982, -67, -1240, 147, -882, +305, -195, 296, 505, 113, 898, -144, 756, +-355, 212, -426, -322, -278, -591, 17, -533, +311, -183, 465, 242, 440, 439, 249, 323, +-16, 3, -240, -312, -347, -409, -291, -206, +-82, 180, 134, 553, 245, 669, 218, 377, +87, -183, -129, -669, -326, -873, -359, -716, +-211, -202, 41, 458, 318, 895, 494, 881, +477, 446, 242, -170, -89, -654, -383, -809, +-490, -597, -358, -103, -78, 429, 231, 704, +423, 611, 364, 268, 74, -151, -284, -476, +-481, -541, -422, -316, -112, 36, 309, 336, +634, 478, 685, 390, 395, 72, -131, -326, +-631, -616, -840, -671, -649, -466, -149, -44, +475, 481, 906, 926, 897, 1058, 452, 783, +-206, 201, -792, -503, -1038, -1134, -815, -1399, +-218, -1095, 467, -323, 961, 604, 1041, 1363, +671, 1627, 40, 1202, -562, 222, -894, -915, +-802, -1751, -355, -1904, 219, -1245, 656, -15, +789, 1305, 569, 2167, 99, 2165, -392, 1280, +-712, -123, -751, -1497, -460, -2298, 6, -2170, +429, -1168, 665, 251, 694, 1501, 500, 2117, +135, 1859, -257, 851, -540, -458, -617, -1523, +-458, -1947, -140, -1580, 242, -569, 550, 684, +652, 1648, 452, 1924, 52, 1429, -387, 408, +-730, -744, -793, -1594, -485, -1785, 70, -1231, +637, -242, 968, 712, 942, 1264, 521, 1261, +-134, 759, -732, 18, -1008, -613, -851, -852, +-342, -650, 287, -202, 775, 240, 912, 481, +662, 426, 125, 155, -446, -118, -781, -239, +-770, -172, -469, 55, 3, 276, 461, 274, +734, 20, 738, -331, 497, -600, 102, -618, +-287, -321, -548, 180, -629, 668, -522, 892, +-256, 685, 75, 164, 397, -369, 623, -698, +672, -706, 473, -336, 81, 223, -358, 626, +-710, 685, -839, 407, -636, -116, -136, -639, +487, -871, 963, -699, 1091, -237, 769, 315, +107, 737, -633, 850, -1147, 596, -1180, 98, +-696, -407, 87, -680, 861, -619, 1314, -286, +1232, 186, 596, 631, -290, 806, -1062, 585, +-1429, 77, -1211, -516, -454, -996, 523, -1130, +1292, -792, 1517, -100, 1133, 684, 305, 1267, +-600, 1377, -1232, 946, -1339, 145, -874, -752, +-87, -1387, 648, -1422, 1074, -865, 1051, 9, +584, 897, -92, 1458, -616, 1368, -807, 675, +-663, -270, -271, -1096, 186, -1493, 481, -1257, +549, -508, 409, 406, 154, 1133, -36, 1384, +-76, 1077, -62, 419, -68, -320, -121, -889, +-260, -1069, -413, -841, -395, -404, -147, 84, +241, 507, 612, 690, 791, 611, 630, 450, +172, 247, -398, -48, -848, -334, -921, -519, +-528, -634, 146, -623, 813, -379, 1167, 62, +1028, 570, 403, 983, -438, 1055, -1104, 667, +-1312, -37, -958, -802, -187, -1346, 640, -1344, +1167, -726, 1162, 232, 657, 1146, -89, 1643, +-713, 1423, -957, 552, -723, -560, -120, -1444, +550, -1741, 913, -1266, 790, -212, 290, 916, +-319, 1609, -764, 1586, -817, 845, -460, -268, +117, -1233, 603, -1623, 797, -1256, 642, -285, +198, 792, -340, 1453, -711, 1461, -749, 842, +-435, -187, 49, -1146, 508, -1543, 807, -1243, +815, -449, 477, 505, -23, 1223, -459, 1402, +-726, 989, -769, 187, -503, -644, -20, -1139, +438, -1144, 704, -703, 720, 12, 461, 698, +31, 1031, -406, 927, -669, 466, -623, -209, +-263, -799, 226, -987, 651, -763, 858, -261, +691, 373, 158, 868, -442, 935, -839, 571, +-931, 3, -663, -500, -60, -757, 580, -711, +952, -389, 930, 106, 530, 500, -76, 575, +-587, 435, -794, 259, -631, 18, -162, -240, +392, -365, 731, -378, 741, -377, 430, -290, +-87, -44, -572, 286, -771, 563, -606, 688, +-186, 558, 313, 134, 703, -449, 772, -908, +473, -991, -52, -619, -545, 51, -779, 740, +-629, 1134, -146, 1008, 440, 363, 879, -465, +972, -1015, 623, -1036, 35, -578, -501, 177, +-818, 875, -826, 1081, -512, 642, -34, -147, +389, -838, 610, -1089, 592, -781, 380, -29, +75, 795, -224, 1231, -395, 999, -363, 229, +-173, -658, 52, -1242, 274, -1268, 449, -663, +493, 324, 355, 1183, 79, 1503, -250, 1193, +-528, 405, -684, -560, -611, -1317, -239, -1541, +292, -1178, 739, -441, 925, 397, 756, 1085, +271, 1375, -399, 1165, -920, 577, -971, -160, +-547, -834, 142, -1207, 837, -1093, 1271, -533, +1161, 238, 437, 950, -515, 1288, -1257, 1065, +-1502, 352, -1125, -570, -259, -1330, 746, -1560, +1451, -1130, 1517, -224, 961, 790, 99, 1514, +-671, 1604, -1095, 1038, -1040, 137, -555, -743, +79, -1297, 551, -1263, 754, -715, 678, 2, +372, 594, -1, 897, -263, 820, -373, 470, +-340, 48, -237, -327, -135, -576, -25, -631, +117, -559, 225, -401, 254, -101, 266, 285, +279, 601, 190, 790, 27, 775, -116, 461, +-188, -74, -155, -600, -62, -914, 31, -878, +116, -480, 142, 134, 67, 707, -77, 995, +-165, 831, -182, 269, -157, -437, -12, -1003, +209, -1194, 340, -857, 369, -123, 351, 669, +268, 1205, 64, 1293, -182, 856, -364, 58, +-424, -717, -338, -1133, -162, -1093, 79, -619, +377, 116, 562, 763, 504, 1012, 265, 811, +-42, 282, -401, -362, -665, -896, -614, -1102, +-272, -843, 191, -188, 659, 536, 948, 1038, +863, 1215, 410, 969, -159, 246, -639, -625, +-901, -1195, -816, -1278, -408, -844, 141, 28, +648, 946, 882, 1460, 719, 1322, 301, 526, +-156, -613, -580, -1517, -784, -1778, -567, -1291, +-74, -170, 423, 1131, 804, 1899, 893, 1794, +572, 956, 27, -310, -445, -1476, -724, -1875, +-693, -1328, -330, -214, 91, 947, 353, 1688, +456, 1602, 352, 688, 75, -565, -162, -1531, +-141, -1760, 47, -1157, 229, -72, 333, 1012, +232, 1655, -81, 1491, -383, 577, -503, -485, +-311, -1185, 162, -1365, 628, -933, 804, 10, +665, 900, 238, 1242, -446, 1027, -1032, 424, +-1098, -359, -711, -943, -98, -1069, 630, -771, +1193, -225, 1262, 336, 837, 659, 146, 671, +-541, 445, -989, 117, -1026, -173, -619, -322, +57, -352, 672, -261, 981, -38, 909, 207, +523, 349, -84, 421, -686, 374, -945, 91, +-785, -332, -404, -632, 82, -694, 556, -525, +812, -133, 703, 367, 376, 680, 49, 626, +-248, 294, -428, -109, -372, -362, -143, -325, +166, -51, 412, 298, 499, 485, 422, 325, +140, -105, -318, -514, -720, -715, -839, -631, +-640, -204, -204, 388, 440, 734, 1080, 677, +1336, 362, 1055, -73, 388, -472, -442, -615, +-1177, -459, -1505, -110, -1198, 257, -335, 457, +737, 446, 1571, 343, 1799, 169, 1308, -83, +291, -288, -917, -361, -1814, -412, -1928, -414, +-1227, -207, -55, 145, 1170, 429, 1920, 556, +1828, 477, 1019, 173, -112, -269, -1141, -631, +-1595, -683, -1269, -351, -443, 187, 484, 655, +1215, 865, 1372, 714, 865, 164, 55, -522, +-706, -924, -1164, -896, -1081, -535, -511, 57, +239, 643, 882, 897, 1178, 686, 950, 178, +379, -373, -233, -760, -739, -804, -923, -444, +-620, 133, -73, 651, 412, 912, 733, 842, +787, 439, 450, -186, -68, -781, -444, -1076, +-605, -956, -558, -455, -302, 215, 58, 804, +378, 1108, 535, 964, 549, 371, 472, -387, +292, -979, 23, -1161, -262, -827, -459, -107, +-508, 648, -399, 1131, -84, 1149, 339, 660, +635, -118, 654, -777, 401, -1073, -40, -910, +-529, -336, -833, 321, -718, 698, -250, 707, +359, 385, 918, -102, 1190, -452, 961, -483, +299, -261, -456, 65, -975, 321, -1122, 373, +-839, 221, -176, -2, 554, -166, 965, -148, +992, 36, 696, 178, 155, 139, -427, -23, +-813, -245, -845, -431, -530, -453, -27, -252, +496, 102, 867, 447, 958, 616, 677, 529, +161, 188, -326, -247, -728, -546, -924, -592, +-730, -392, -240, 35, 351, 539, 806, 833, +952, 742, 771, 313, 300, -337, -316, -957, +-783, -1218, -879, -966, -604, -254, -97, 669, +512, 1319, 944, 1380, 960, 892, 616, -27, +78, -1080, -476, -1640, -807, -1338, -783, -410, +-453, 692, 22, 1550, 465, 1713, 705, 1059, +656, -72, 357, -1194, -31, -1801, -340, -1531, +-471, -614, -391, 440, -183, 1255, 98, 1495, +464, 996, 690, 116, 602, -628, 322, -999, +-30, -905, -452, -360, -802, 257, -787, 584, +-405, 624, 110, 423, 629, 0, 925, -332, +839, -334, 431, -167, -150, -44, -656, 18, +-814, 22, -536, -66, 13, -187, 565, -193, +917, -18, 848, 267, 361, 472, -265, 464, +-765, 263, -963, -86, -733, -487, -146, -673, +469, -499, 815, -99, 851, 336, 542, 699, +-4, 796, -444, 446, -556, -171, -381, -667, +-32, -922, 384, -869, 657, -388, 579, 315, +240, 812, -151, 973, -430, 824, -529, 332, +-456, -344, -226, -822, 85, -923, 340, -668, +441, -120, 377, 485, 257, 845, 117, 858, +-59, 489, -201, -140, -211, -692, -114, -938, +35, -822, 245, -333, 421, 314, 401, 755, +195, 841, -97, 615, -356, 127, -477, -377, +-368, -586, -61, -483, 254, -199, 440, 200, +408, 478, 132, 429, -211, 123, -413, -274, +-335, -598, -29, -650, 347, -390, 680, 67, +782, 554, 538, 866, 80, 783, -378, 314, +-639, -295, -687, -796, -514, -976, -97, -676, +362, -8, 609, 711, 554, 1130, 270, 1006, +-82, 362, -404, -504, -549, -1206, -373, -1387, +86, -899, 601, 57, 915, 981, 891, 1440, +489, 1284, -183, 571, -797, -440, -1064, -1219, +-901, -1359, -341, -881, 438, -84, 999, 718, +1058, 1222, 699, 1175, 74, 578, -638, -227, +-1069, -904, -926, -1252, -302, -1152, 442, -604, +1052, 218, 1268, 1022, 947, 1483, 241, 1419, +-581, 813, -1151, -192, -1178, -1276, -732, -1948, +27, -1814, 830, -891, 1265, 466, 1116, 1786, +548, 2435, -188, 2005, -897, 695, -1231, -946, +-972, -2284, -362, -2653, 367, -1813, 1011, -224, +1270, 1348, 1051, 2310, 500, 2280, -176, 1260, +-720, -222, -979, -1452, -910, -1944, -486, -1569, +154, -627, 628, 431, 814, 1218, 838, 1433, +582, 1042, -32, 370, -623, -278, -868, -768, +-829, -1003, -537, -907, 96, -557, 835, -97, +1289, 363, 1294, 738, 859, 899, 66, 754, +-858, 321, -1525, -225, -1568, -705, -919, -937, +113, -731, 1062, -137, 1642, 501, 1630, 914, +862, 954, -313, 558, -1237, -129, -1605, -799, +-1374, -1165, -551, -1027, 589, -458, 1508, 241, +1851, 796, 1484, 1071, 518, 934, -605, 440, +-1443, -108, -1737, -520, -1317, -762, -370, -706, +663, -388, 1410, -7, 1617, 338, 1140, 569, +159, 551, -857, 318, -1470, -15, -1429, -361, +-740, -590, 283, -554, 1307, -263, 1901, 163, +1635, 544, 633, 652, -561, 407, -1487, 7, +-1834, -402, -1438, -682, -400, -588, 789, -126, +1581, 398, 1670, 754, 1093, 786, 152, 421, +-821, -169, -1464, -651, -1434, -846, -795, -720, +112, -307, 982, 184, 1542, 481, 1554, 564, +1024, 506, 177, 338, -724, 141, -1399, -15, +-1572, -186, -1175, -400, -378, -617, 558, -713, +1349, -521, 1632, 39, 1268, 762, 457, 1251, +-505, 1249, -1272, 723, -1517, -265, -1102, -1352, +-193, -1929, 762, -1621, 1384, -549, 1468, 844, +1032, 1948, 267, 2197, -610, 1450, -1180, 90, +-1126, -1318, -676, -2146, -119, -1943, 441, -888, +809, 408, 734, 1450, 337, 1800, -13, 1283, +-245, 277, -352, -658, -176, -1187, 145, -1102, +342, -497, 311, 163, 74, 552, -219, 665, +-364, 424, -292, -63, -36, -351, 364, -299, +730, -116, 728, 148, 332, 337, -210, 210, +-718, -108, -1041, -349, -909, -453, -302, -356, +428, 18, 1006, 482, 1291, 715, 1081, 625, +428, 271, -319, -204, -847, -601, -1076, -759, +-924, -582, -380, -112, 285, 328, 794, 486, +1002, 415, 824, 200, 408, -134, -104, -412, +-632, -378, -950, -34, -837, 314, -382, 495, +169, 485, 724, 214, 1113, -246, 1026, -596, +548, -665, -43, -458, -597, -13, -976, 515, +-958, 814, -520, 737, 75, 348, 604, -271, +925, -879, 865, -1109, 478, -894, -56, -339, +-557, 443, -813, 1131, -685, 1376, -265, 1094, +261, 371, 785, -525, 1062, -1208, 853, -1406, +330, -1053, -305, -230, -920, 707, -1222, 1249, +-995, 1229, -342, 771, 486, -72, 1220, -965, +1514, -1325, 1160, -1024, 361, -360, -615, 410, +-1416, 999, -1577, 1085, -989, 632, -3, -46, +1005, -596, 1695, -789, 1664, -563, 822, -64, +-318, 452, -1238, 732, -1645, 577, -1338, 114, +-396, -335, 710, -621, 1439, -706, 1530, -497, +1003, -75, 103, 293, -769, 433, -1323, 426, +-1268, 334, -583, 143, 252, -47, 859, -100, +1178, -90, 1082, -112, 498, -129, -276, -80, +-740, 12, -816, 102, -615, 179, -174, 191, +329, 68, 642, -151, 611, -404, 321, -569, +21, -524, -229, -272, -383, 130, -325, 575, +-73, 838, 163, 822, 256, 597, 282, 195, +244, -329, 68, -748, -95, -895, -110, -806, +-60, -498, -35, 50, 35, 612, 129, 912, +141, 883, 64, 533, -19, -66, -30, -705, +17, -1133, 28, -1076, 26, -492, 56, 317, +64, 1004, -8, 1367, -17, 1220, 107, 513, +163, -414, 97, -1087, 60, -1329, -1, -1116, +-131, -480, -239, 309, -199, 862, 2, 977, +237, 716, 399, 298, 462, -154, 395, -523, +153, -600, -219, -389, -468, -139, -504, 66, +-407, 241, -156, 313, 237, 235, 578, 139, +666, 140, 490, 154, 218, 52, -107, -150, +-495, -354, -764, -516, -650, -626, -252, -486, +158, 21, 582, 623, 980, 1019, 1037, 1081, +676, 652, 127, -196, -442, -1027, -956, -1436, +-1173, -1218, -936, -351, -367, 801, 336, 1607, +932, 1663, 1228, 960, 1119, -288, 518, -1525, +-307, -2027, -905, -1527, -1064, -313, -838, 1053, +-272, 1898, 494, 1824, 1008, 905, 992, -424, +634, -1530, 118, -1834, -399, -1207, -705, -60, +-646, 1020, -342, 1594, -25, 1396, 253, 542, +436, -448, 395, -1140, 221, -1338, 83, -934, +17, -136, -43, 573, -75, 910, -70, 882, +-88, 524, -110, -64, -86, -560, 16, -708, +218, -560, 347, -205, 345, 251, 293, 600, +116, 712, -241, 541, -524, 90, -504, -438, +-321, -738, -128, -717, 225, -462, 613, -1, +749, 527, 617, 758, 329, 547, -70, 106, +-522, -389, -803, -737, -715, -652, -367, -155, +114, 465, 589, 931, 899, 1000, 907, 532, +544, -257, -44, -937, -559, -1238, -839, -996, +-870, -191, -590, 723, 7, 1207, 580, 1096, +849, 416, 840, -572, 620, -1299, 208, -1327, +-253, -670, -556, 403, -630, 1399, -524, 1749, +-290, 1253, 8, 172, 369, -1023, 643, -1756, +686, -1604, 539, -747, 215, 312, -249, 1217, +-652, 1546, -802, 1037, -600, 67, -128, -766, +434, -1204, 848, -1180, 913, -635, 582, 182, +-8, 808, -555, 1073, -791, 1032, -672, 725, +-211, 219, 392, -364, 768, -859, 747, -1102, +416, -1044, -108, -685, -619, -4, -796, 791, +-537, 1286, -77, 1242, 407, 696, 767, -190, +785, -1117, 419, -1570, -50, -1241, -379, -354, +-523, 698, -447, 1528, -143, 1724, 231, 1125, +463, 41, 381, -987, 143, -1575, -49, -1533, +-191, -855, -267, 133, -189, 945, 35, 1262, +190, 1026, 163, 415, 139, -281, 111, -818, +28, -973, -20, -643, 61, -70, 213, 400, +240, 668, 134, 733, 23, 509, -137, 54, +-323, -286, -434, -401, -334, -447, -45, -395, +244, -227, 455, -86, 559, 17, 463, 147, +143, 276, -267, 363, -479, 366, -451, 188, +-257, -113, 79, -339, 444, -430, 675, -340, +648, 37, 347, 472, -109, 614, -602, 448, +-891, 12, -829, -603, -427, -970, 196, -813, +813, -231, 1146, 567, 992, 1218, 427, 1272, +-273, 633, -904, -375, -1128, -1320, -775, -1731, +-72, -1272, 647, -112, 1093, 1197, 1052, 2055, +558, 2025, -141, 1066, -757, -439, -1033, -1861, +-751, -2515, -138, -2047, 419, -703, 759, 918, +743, 2171, 308, 2526, -225, 1804, -521, 256, +-527, -1389, -235, -2344, 292, -2311, 646, -1366, +634, 191, 410, 1743, 28, 2535, -413, 2208, +-621, 1021, -523, -533, -243, -1897, 121, -2519, +429, -2114, 433, -846, 252, 713, 95, 1866, +-146, 2217, -325, 1709, -167, 508, 116, -866, +263, -1734, 319, -1789, 348, -1133, 210, -30, +-53, 1095, -238, 1674, -286, 1467, -242, 718, +-171, -288, -86, -1225, 92, -1610, 222, -1297, +166, -537, 89, 372, 157, 1138, 164, 1436, +37, 1134, -13, 392, 29, -465, 6, -1093, +-61, -1270, -73, -958, -19, -245, 28, 608, +120, 1219, 203, 1310, 166, 920, 54, 220, +-81, -587, -191, -1192, -240, -1330, -225, -957, +-67, -307, 107, 350, 167, 879, 164, 1073, +178, 849, 208, 390, 175, -104, 174, -502, +275, -698, 185, -661, -108, -428, -357, -63, +-466, 318, -474, 559, -356, 637, 37, 551, +579, 228, 824, -248, 645, -607, 251, -770, +-158, -751, -620, -404, -937, 194, -703, 647, +-59, 799, 534, 739, 887, 410, 974, -208, +759, -712, 169, -789, -516, -530, -877, -68, +-810, 432, -518, 743, -104, 750, 435, 369, +792, -260, 649, -675, 274, -673, -69, -487, +-374, -152, -593, 332, -504, 592, -88, 391, +320, -8, 501, -299, 541, -404, 451, -270, +175, 91, -205, 461, -383, 621, -276, 453, +-88, 59, 81, -323, 235, -541, 242, -481, +-2, -181, -370, 115, -542, 210, -436, 67, +-167, -157, 218, -282, 710, -213, 1045, 102, +917, 573, 408, 828, -200, 604, -801, 60, +-1195, -559, -1095, -1074, -457, -1139, 345, -540, +1012, 408, 1410, 1160, 1265, 1436, 497, 1102, +-483, 187, -1253, -910, -1579, -1656, -1360, -1692, +-531, -983, 602, 161, 1474, 1277, 1761, 1858, +1453, 1620, 664, 691, -398, -453, -1344, -1352, +-1666, -1703, -1271, -1304, -475, -278, 450, 783, +1269, 1334, 1538, 1313, 1068, 807, 236, -92, +-509, -931, -1094, -1224, -1378, -914, -1025, -307, +-130, 327, 687, 816, 1142, 906, 1278, 516, +985, -76, 230, -514, -609, -610, -1050, -446, +-956, -89, -547, 383, 39, 692, 615, 582, +888, 135, 671, -346, 133, -705, -314, -865, +-558, -603, -646, 78, -406, 748, 9, 1032, +319, 903, 458, 369, 489, -447, 442, -1109, +283, -1222, 101, -706, -36, 200, -203, 1050, +-328, 1429, -454, 1122, -506, 230, -304, -871, +68, -1590, 420, -1519, 664, -742, 697, 397, +393, 1430, -146, 1795, -570, 1272, -809, 183, +-748, -946, -222, -1650, 467, -1576, 918, -759, +1064, 357, 837, 1236, 212, 1556, -499, 1162, +-919, 204, -1037, -761, -779, -1298, -146, -1312, +469, -757, 814, 171, 888, 1021, 595, 1383, +46, 1171, -466, 489, -759, -450, -787, -1260, +-416, -1567, 256, -1194, 838, -245, 1111, 825, +992, 1609, 408, 1852, -377, 1292, -1034, -30, +-1338, -1416, -1139, -2171, -405, -2121, 538, -1237, +1212, 341, 1412, 1907, 1114, 2652, 346, 2293, +-579, 1057, -1257, -643, -1379, -2125, -929, -2718, +-116, -2176, 741, -768, 1334, 838, 1464, 2002, +1037, 2392, 216, 1849, -644, 567, -1309, -842, +-1496, -1794, -1105, -2068, -313, -1625, 574, -608, +1260, 604, 1507, 1556, 1219, 1960, 485, 1732, +-461, 947, -1302, -201, -1597, -1360, -1263, -2051, +-496, -1969, 549, -1254, 1533, -83, 1923, 1257, +1570, 2147, 670, 2168, -530, 1388, -1660, 83, +-2145, -1320, -1730, -2233, -666, -2221, 599, -1372, +1710, -45, 2221, 1293, 1788, 2137, 579, 2185, +-792, 1444, -1763, 181, -2048, -1101, -1566, -1914, +-338, -2033, 1122, -1438, 2067, -284, 2118, 927, +1367, 1739, 129, 1911, -1215, 1319, -2147, 135, +-2112, -1127, -1186, -1919, 144, -1913, 1369, -1074, +2072, 262, 1987, 1461, 1038, 2088, -351, 1896, +-1440, 847, -1913, -588, -1659, -1680, -739, -1991, +513, -1448, 1571, -321, 1977, 854, 1651, 1550, +729, 1517, -486, 793, -1493, -277, -2005, -1158, +-1772, -1443, -828, -1127, 378, -347, 1413, 614, +1993, 1251, 1876, 1347, 1035, 1047, -148, 406, +-1158, -427, -1809, -1056, -1840, -1241, -1104, -1112, +56, -639, 1127, 168, 1811, 863, 1914, 1156, +1270, 1106, 85, 652, -1068, -160, -1858, -923, +-2013, -1273, -1374, -1153, -170, -540, 1083, 346, +1912, 1064, 2039, 1338, 1424, 1122, 319, 503, +-828, -251, -1694, -790, -1896, -979, -1298, -898, +-263, -519, 770, -65, 1554, 144, 1762, 205, +1178, 346, 123, 469, -773, 479, -1299, 486, +-1407, 420, -924, 53, 9, -445, 799, -792, +1115, -888, 1027, -632, 616, -22, -26, 657, +-558, 1119, -760, 1092, -610, 484, -248, -364, +104, -1024, 376, -1312, 566, -1056, 483, -225, +130, 751, -133, 1287, -166, 1275, -292, 801, +-394, -84, -208, -973, -25, -1314, 25, -1041, +201, -435, 394, 294, 377, 919, 257, 1111, +168, 838, -24, 289, -200, -332, -201, -760, +-168, -806, -140, -589, -29, -262, 27, 194, +-1, 571, 10, 566, 41, 322, 56, 6, +143, -324, 156, -497, 85, -375, 65, -68, +24, 311, -110, 700, -134, 760, 38, 325, +164, -152, 168, -518, 228, -893, 158, -968, +-100, -519, -340, 88, -442, 555, -341, 875, +-81, 929, 207, 640, 465, 158, 560, -423, +441, -870, 113, -925, -243, -672, -425, -253, +-437, 418, -294, 1038, 17, 1130, 336, 723, +474, 55, 350, -739, 155, -1360, -10, -1381, +-224, -670, -357, 366, -256, 1243, -88, 1661, +39, 1384, 109, 364, 146, -904, 130, -1744, +113, -1822, 147, -1084, 204, 199, 218, 1408, +100, 2042, -118, 1824, -249, 771, -333, -675, +-356, -1789, -222, -2177, 86, -1762, 402, -587, +529, 854, 447, 1899, 213, 2233, -91, 1714, +-355, 556, -528, -792, -439, -1894, -135, -2302, +209, -1731, 483, -454, 560, 908, 383, 1948, +74, 2339, -234, 1693, -470, 245, -523, -1278, +-230, -2305, 170, -2448, 414, -1479, 544, 201, +523, 1804, 192, 2696, -281, 2479, -590, 1150, +-651, -682, -476, -2220, -94, -2859, 290, -2290, +584, -733, 731, 1021, 604, 2263, 263, 2581, +-22, 1819, -271, 383, -555, -975, -660, -1832, +-476, -1994, -236, -1397, 43, -367, 417, 584, +675, 1210, 677, 1403, 502, 1224, 121, 797, +-355, 159, -697, -598, -759, -1220, -535, -1477, +-62, -1336, 515, -769, 895, 259, 893, 1322, +573, 1897, -25, 1770, -636, 973, -951, -298, +-858, -1589, -439, -2232, 146, -1886, 688, -798, +955, 604, 814, 1795, 377, 2282, -199, 1793, +-711, 543, -910, -852, -688, -1850, -205, -2143, +375, -1570, 847, -346, 1012, 942, 769, 1767, +162, 1893, -538, 1282, -987, 241, -1015, -846, +-614, -1634, -1, -1742, 679, -1124, 1125, -186, +1006, 751, 444, 1444, -240, 1561, -795, 1077, +-1032, 312, -858, -577, -225, -1311, 528, -1449, +1005, -1010, 1043, -324, 700, 477, 144, 1115, +-471, 1270, -902, 957, -903, 290, -576, -526, +-82, -1067, 402, -1144, 660, -820, 647, -237, +517, 464, 252, 1005, -159, 1100, -468, 788, +-516, 286, -474, -273, -302, -753, 87, -971, +468, -783, 649, -398, 660, 6, 438, 402, +20, 657, -387, 684, -665, 539, -783, 262, +-551, -81, -69, -379, 332, -550, 621, -604, +778, -510, 601, -268, 188, 99, -217, 498, +-491, 755, -643, 769, -522, 538, -138, 105, +256, -400, 573, -818, 767, -945, 678, -706, +297, -169, -219, 442, -648, 818, -975, 828, +-1047, 542, -636, -11, 120, -635, 827, -931, +1298, -736, 1435, -270, 1021, 320, 120, 920, +-779, 1195, -1422, 899, -1631, 251, -1185, -500, +-164, -1125, 933, -1352, 1668, -1113, 1811, -456, +1226, 456, 129, 1193, -1008, 1431, -1863, 1110, +-2006, 372, -1269, -563, -50, -1281, 1144, -1389, +1974, -905, 2043, -55, 1272, 916, 126, 1566, +-934, 1472, -1694, 664, -1814, -369, -1142, -1219, +-100, -1602, 795, -1320, 1390, -471, 1481, 557, +986, 1288, 163, 1392, -591, 896, -1028, 98, +-1141, -669, -918, -1150, -325, -1060, 350, -496, +830, 158, 1028, 693, 977, 958, 645, 826, +66, 404, -503, -114, -831, -501, -921, -625, +-709, -523, -226, -326, 278, -116, 623, 27, +782, 78, 666, 63, 284, 54, -188, 106, +-472, 282, -562, 498, -485, 554, -162, 398, +243, 77, 516, -405, 585, -859, 401, -1049, +131, -796, -150, -169, -414, 538, -547, 1127, +-418, 1398, -100, 1046, 171, 142, 383, -825, +570, -1452, 502, -1605, 136, -1138, -286, -171, +-497, 852, -528, 1545, -407, 1691, -26, 1209, +505, 296, 795, -625, 658, -1208, 320, -1395, +-55, -1166, -516, -591, -809, 120, -676, 705, +-228, 1025, 211, 1105, 521, 911, 656, 414, +515, -221, 112, -819, -333, -1190, -555, -1263, +-421, -954, -107, -182, 165, 775, 397, 1428, +566, 1602, 440, 1308, 124, 540, -133, -524, +-354, -1406, -531, -1753, -509, -1525, -326, -824, +-100, 140, 226, 1004, 612, 1477, 745, 1418, +619, 967, 311, 339, -175, -380, -635, -969, +-827, -1117, -722, -925, -326, -634, 293, -219, +808, 357, 938, 771, 753, 855, 282, 780, +-353, 577, -845, 129, -931, -395, -618, -679, +-84, -719, 449, -659, 739, -409, 719, -26, +471, 272, 22, 419, -325, 512, -382, 529, +-337, 406, -306, 259, -148, 89, 118, -230, +273, -558, 299, -762, 377, -750, 409, -482, +214, -29, -151, 521, -474, 1004, -628, 1134, +-577, 797, -371, 157, 107, -560, 726, -1189, +978, -1397, 746, -991, 319, -206, -192, 648, +-708, 1373, -933, 1648, -592, 1254, -12, 298, +411, -819, 616, -1641, 593, -1885, 324, -1472, +-103, -432, -418, 879, -343, 1859, -76, 2103, +91, 1608, 170, 469, 186, -930, -29, -1924, +-348, -2126, -423, -1545, -205, -330, 106, 1030, +484, 1875, 847, 1928, 853, 1280, 394, 61, +-231, -1198, -766, -1819, -995, -1621, -874, -805, +-444, 294, 173, 1205, 697, 1533, 881, 1176, +729, 364, 413, -558, 8, -1117, -452, -1070, +-661, -562, -531, 142, -248, 702, 44, 851, +313, 617, 469, 93, 441, -483, 281, -798, +39, -700, -216, -306, -358, 162, -360, 525, +-197, 687, -8, 584, 108, 243, 183, -198, +201, -479, 96, -503, -73, -383, -138, -182, +-49, 168, 93, 508, 278, 543, 375, 279, +238, -6, -36, -296, -242, -623, -386, -684, +-427, -331, -199, 131, 185, 534, 353, 824, +265, 747, 102, 240, -122, -334, -344, -747, +-287, -890, 5, -625, 337, -5, 600, 683, +610, 1084, 240, 982, -272, 449, -641, -327, +-757, -1025, -506, -1355, 80, -1145, 589, -416, +792, 513, 703, 1193, 292, 1386, -349, 1095, +-777, 376, -769, -579, -517, -1194, -84, -1187, +440, -743, 722, -22, 719, 724, 529, 1100, +184, 962, -229, 355, -452, -452, -465, -995, +-430, -1035, -212, -722, 136, -104, 253, 670, +249, 1112, 310, 966, 227, 450, -56, -170, +-212, -681, -186, -899, -163, -707, -113, -165, +58, 422, 232, 706, 322, 641, 293, 326, +108, -139, -96, -513, -170, -551, -236, -320, +-213, 50, -45, 373, 76, 380, 112, 78, +180, -273, 203, -511, 5, -482, -232, -100, +-233, 518, -221, 996, -207, 1032, 55, 594, +436, -168, 616, -949, 576, -1382, 371, -1259, +-44, -590, -548, 290, -885, 1044, -944, 1390, +-604, 1111, 86, 353, 763, -438, 1109, -958, +1117, -1099, 680, -809, -182, -146, -975, 491, +-1323, 809, -1200, 834, -556, 598, 460, 153, +1298, -269, 1515, -509, 1224, -584, 472, -541, +-671, -422, -1561, -255, -1614, 14, -1036, 293, +-175, 533, 839, 796, 1594, 882, 1592, 533, +876, -51, -191, -613, -1136, -1135, -1579, -1444, +-1374, -1128, -610, -205, 482, 829, 1411, 1586, +1657, 1895, 1279, 1568, 557, 594, -486, -724, +-1452, -1865, -1764, -2397, -1347, -2090, -548, -1041, +419, 343, 1357, 1657, 1841, 2515, 1580, 2493, +717, 1646, -369, 327, -1321, -1122, -1871, -2217, +-1719, -2514, -845, -2019, 394, -955, 1456, 426, +1980, 1638, 1816, 2177, 978, 2013, -236, 1275, +-1342, 170, -1929, -897, -1801, -1552, -1077, -1676, +3, -1331, 1096, -651, 1805, 151, 1822, 760, +1202, 1075, 241, 1211, -766, 1124, -1496, 653, +-1682, 26, -1309, -478, -501, -964, 553, -1371, +1498, -1323, 1818, -796, 1437, -31, 605, 758, +-456, 1345, -1400, 1514, -1867, 1184, -1616, 428, +-662, -445, 568, -1086, 1554, -1330, 1906, -1140, +1548, -545, 579, 137, -665, 616, -1591, 893, +-1814, 922, -1343, 616, -347, 167, 798, -199, +1596, -424, 1696, -621, 1125, -718, 155, -517, +-860, -143, -1506, 135, -1441, 356, -796, 601, +55, 708, 828, 493, 1208, 110, 1027, -215, +469, -392, -193, -456, -721, -441, -907, -293, +-623, -62, -92, 50, 395, 66, 691, 121, +670, 209, 332, 272, -133, 366, -517, 391, +-649, 200, -507, -113, -194, -404, 170, -632, +516, -659, 610, -395, 350, 62, -35, 487, +-295, 740, -389, 718, -381, 440, -175, 84, +299, -272, 642, -598, 517, -668, 128, -522, +-200, -418, -561, -303, -918, 10, -769, 400, +-64, 704, 598, 948, 962, 1049, 1142, 733, +973, 53, 223, -730, -722, -1393, -1301, -1638, +-1408, -1263, -1175, -417, -522, 595, 509, 1456, +1454, 1813, 1852, 1450, 1636, 595, 979, -393, +8, -1220, -1149, -1576, -2005, -1346, -2158, -712, +-1660, 81, -720, 778, 551, 1158, 1852, 1145, +2589, 843, 2429, 324, 1535, -231, 155, -612, +-1383, -819, -2571, -873, -2881, -691, -2198, -339, +-795, 43, 921, 367, 2392, 625, 3010, 775, +2544, 760, 1270, 546, -351, 208, -1900, -155, +-2807, -572, -2662, -988, -1580, -1092, -72, -838, +1377, -371, 2359, 289, 2520, 1047, 1779, 1542, +492, 1478, -810, 846, -1698, -85, -1975, -1034, +-1638, -1730, -806, -1881, 231, -1291, 1013, -187, +1355, 907, 1305, 1658, 871, 1919, 195, 1539, +-403, 616, -721, -492, -837, -1331, -816, -1686, +-546, -1597, -179, -1045, 137, -106, 471, 818, +769, 1423, 879, 1659, 766, 1438, 471, 696, +-22, -300, -688, -1236, -1226, -1862, -1378, -1900, +-1073, -1255, -400, -126, 499, 1153, 1384, 2127, +1856, 2377, 1612, 1760, 787, 522, -312, -1005, +-1427, -2308, -2135, -2764, -1985, -2173, -1063, -839, +201, 810, 1423, 2239, 2211, 2888, 2142, 2423, +1213, 1076, -111, -564, -1368, -1962, -2148, -2698, +-2066, -2460, -1191, -1331, 41, 194, 1199, 1490, +1883, 2215, 1771, 2258, 1021, 1586, 46, 432, +-856, -681, -1370, -1424, -1292, -1798, -798, -1766, +-153, -1203, 487, -368, 885, 378, 821, 1026, +539, 1584, 251, 1759, -120, 1401, -448, 683, +-486, -170, -329, -1029, -244, -1689, -160, -1907, +116, -1523, 338, -674, 337, 327, 303, 1197, +312, 1696, 200, 1714, -68, 1293, -343, 473, +-457, -455, -376, -1144, -210, -1479, -21, -1465, +244, -1063, 450, -364, 385, 402, 162, 989, +38, 1270, -105, 1238, -342, 922, -393, 291, +-193, -408, -9, -835, 92, -979, 255, -886, +459, -495, 533, -5, 406, 297, 46, 399, +-392, 373, -716, 162, -923, -78, -889, -71, +-366, 145, 457, 371, 1095, 532, 1367, 498, +1235, 197, 532, -315, -505, -870, -1365, -1181, +-1716, -1024, -1409, -513, -534, 166, 588, 932, +1556, 1532, 1922, 1541, 1467, 952, 460, 77, +-624, -848, -1543, -1600, -1971, -1859, -1516, -1452, +-391, -504, 707, 650, 1445, 1667, 1698, 2163, +1228, 1857, 184, 841, -814, -435, -1333, -1621, +-1313, -2376, -767, -2201, 178, -1055, 1025, 436, +1355, 1685, 1016, 2374, 154, 2268, -688, 1187, +-1142, -479, -1220, -1854, -803, -2417, 96, -2201, +955, -1218, 1234, 364, 1030, 1809, 571, 2387, +-150, 2153, -837, 1344, -1029, -8, -799, -1442, +-479, -2182, -94, -2104, 380, -1484, 667, -413, +671, 901, 608, 1857, 520, 2047, 285, 1570, +-69, 685, -473, -472, -892, -1556, -1147, -2024, +-1026, -1675, -568, -789, 107, 335, 902, 1342, +1594, 1842, 1808, 1679, 1376, 916, 497, -190, +-544, -1112, -1537, -1540, -2133, -1478, -2032, -954, +-1292, -94, -150, 662, 1096, 1058, 2052, 1148, +2403, 927, 2026, 478, 1047, 33, -297, -377, +-1658, -761, -2552, -1010, -2630, -1009, -1886, -800, +-585, -406, 940, 255, 2322, 1071, 3009, 1649, +2690, 1750, 1537, 1295, -65, 284, -1695, -1015, +-2879, -2069, -3104, -2537, -2257, -2164, -827, -894, +693, 740, 2044, 2088, 2833, 2846, 2671, 2673, +1716, 1466, 411, -235, -966, -1692, -2097, -2522, +-2603, -2552, -2406, -1759, -1598, -427, -300, 875, +1128, 1729, 2215, 2012, 2726, 1747, 2498, 1019, +1481, 101, -63, -689, -1649, -1219, -2750, -1531, +-2961, -1516, -2248, -1039, -877, -253, 822, 530, +2286, 1199, 2851, 1642, 2466, 1600, 1472, 1002, +77, 97, -1390, -808, -2279, -1467, -2310, -1688, +-1802, -1355, -945, -631, 217, 207, 1281, 925, +1845, 1341, 1853, 1383, 1455, 1071, 768, 487, +-102, -162, -984, -702, -1649, -1062, -1851, -1240, +-1515, -1118, -813, -662, 166, -42, 1231, 611, +1894, 1208, 1897, 1470, 1393, 1261, 501, 674, +-648, -172, -1649, -1080, -2063, -1677, -1812, -1736, +-992, -1209, 250, -185, 1436, 1010, 2066, 1899, +2012, 2180, 1248, 1759, -69, 663, -1408, -843, +-2136, -2103, -2009, -2612, -1118, -2316, 271, -1286, +1586, 361, 2233, 2035, 1988, 2944, 911, 2765, +-563, 1775, -1769, 256, -2260, -1505, -1888, -2815, +-718, -3036, 749, -2234, 1799, -795, 2143, 858, +1775, 2239, 707, 2884, -608, 2548, -1534, 1384, +-1868, -80, -1640, -1417, -879, -2340, 132, -2514, +1014, -1886, 1562, -824, 1605, 417, 1141, 1499, +442, 2008, -370, 1940, -1148, 1440, -1499, 525, +-1345, -473, -914, -1152, -194, -1482, 695, -1456, +1326, -957, 1462, -253, 1186, 312, 535, 699, +-414, 904, -1248, 847, -1586, 534, -1404, 118, +-749, -123, 226, -175, 1163, -271, 1648, -389, +1518, -296, 870, -159, -112, -244, -1081, -380, +-1675, -227, -1706, 84, -1087, 269, -53, 455, +933, 777, 1606, 887, 1782, 582, 1246, 104, +204, -366, -775, -890, -1452, -1318, -1811, -1323, +-1536, -837, -565, -148, 530, 580, 1240, 1286, +1551, 1689, 1420, 1513, 714, 888, -282, 81, +-1029, -762, -1314, -1514, -1121, -1803, -519, -1414, +189, -655, 695, 135, 859, 933, 628, 1568, +202, 1677, -133, 1172, -315, 369, -364, -459, +-238, -1184, -76, -1618, -37, -1519, -12, -917, +49, -52, 32, 833, 52, 1509, 187, 1751, +230, 1453, 52, 634, -191, -419, -315, -1312, +-328, -1819, -226, -1820, 129, -1182, 610, -82, +868, 1017, 722, 1784, 251, 2019, -352, 1515, +-943, 438, -1311, -767, -1174, -1735, -570, -2128, +208, -1714, 969, -682, 1580, 594, 1751, 1725, +1312, 2274, 460, 1941, -539, 921, -1503, -342, +-2123, -1532, -2142, -2336, -1475, -2230, -255, -1257, +1136, -87, 2273, 999, 2798, 2000, 2484, 2372, +1383, 1777, -251, 747, -1938, -266, -3061, -1364, +-3215, -2229, -2430, -2252, -940, -1557, 934, -647, +2622, 521, 3521, 1854, 3381, 2620, 2296, 2451, +568, 1637, -1435, 365, -3136, -1170, -3947, -2510, +-3665, -3115, -2338, -2718, -232, -1477, 2028, 180, +3736, 1883, 4400, 3144, 3761, 3421, 1878, 2651, +-607, 1188, -2856, -673, -4300, -2434, -4487, -3437, +-3207, -3402, -892, -2463, 1566, -793, 3384, 1156, +4182, 2705, 3711, 3423, 2006, 3192, -205, 2005, +-2112, 213, -3344, -1563, -3554, -2793, -2558, -3214, +-858, -2681, 767, -1317, 1967, 375, 2584, 1807, +2327, 2668, 1236, 2758, -80, 2005, -986, 665, +-1334, -751, -1295, -1778, -858, -2201, -85, -2079, +487, -1424, 404, -334, -93, 697, -473, 1239, +-597, 1452, -496, 1489, 109, 1116, 1155, 438, +1897, -34, 1810, -388, 1024, -904, -286, -1243, +-1908, -1154, -3108, -961, -3117, -685, -1904, -54, +46, 749, 2164, 1264, 3755, 1395, 4078, 1282, +2855, 866, 562, 53, -1895, -781, -3716, -1266, +-4326, -1430, -3458, -1285, -1387, -757, 1096, -34, +3086, 670, 4016, 1213, 3692, 1441, 2184, 1313, +73, 877, -1856, 119, -3128, -739, -3468, -1371, +-2725, -1679, -1193, -1589, 488, -928, 1893, 115, +2807, 1118, 2927, 1831, 2220, 2056, 948, 1562, +-548, 477, -1810, -784, -2550, -1787, -2683, -2217, +-2055, -1918, -746, -952, 761, 385, 1976, 1587, +2684, 2196, 2664, 2009, 1779, 1167, 336, -23, +-1150, -1146, -2247, -1787, -2636, -1740, -2280, -1166, +-1294, -315, 142, 483, 1528, 891, 2281, 908, +2279, 744, 1718, 477, 726, 327, -474, 438, +-1443, 511, -1941, 224, -1946, -333, -1481, -1041, +-644, -1748, 364, -2023, 1264, -1503, 1811, -311, +1912, 1185, 1519, 2523, 652, 3116, -427, 2579, +-1303, 1132, -1864, -698, -2069, -2315, -1609, -3179, +-549, -3000, 519, -1871, 1270, -220, 1748, 1336, +1794, 2342, 1207, 2595, 328, 2115, -453, 1113, +-1121, -55, -1560, -1061, -1532, -1687, -1065, -1882, +-390, -1601, 286, -897, 928, -44, 1402, 719, +1390, 1332, 856, 1573, 149, 1260, -533, 602, +-1177, -65, -1443, -676, -989, -1084, -188, -990, +451, -509, 905, -87, 1098, 171, 691, 337, +-176, 297, -839, -9, -983, -293, -793, -270, +-239, 44, 704, 418, 1425, 724, 1340, 916, +658, 846, -208, 371, -1116, -357, -1763, -1063, +-1696, -1582, -906, -1747, 221, -1323, 1228, -391, +1778, 745, 1810, 1799, 1308, 2430, 269, 2348, +-815, 1534, -1397, 98, -1574, -1529, -1494, -2697, +-906, -3036, 33, -2472, 732, -1054, 1118, 730, +1370, 2273, 1293, 3179, 842, 3132, 282, 2091, +-297, 491, -879, -1210, -1280, -2616, -1321, -3286, +-1032, -3023, -536, -1985, 159, -382, 936, 1409, +1494, 2860, 1617, 3575, 1308, 3310, 659, 1999, +-265, 20, -1269, -2024, -1918, -3562, -1917, -4049, +-1314, -3181, -308, -1269, 907, 1076, 1917, 3173, +2195, 4263, 1740, 3871, 841, 2194, -405, -146, +-1629, -2446, -2225, -4020, -2003, -4267, -1177, -3091, +30, -962, 1271, 1427, 2006, 3385, 1969, 4311, +1330, 3927, 313, 2315, -871, -58, -1808, -2415, +-2059, -4006, -1590, -4413, -652, -3477, 471, -1376, +1430, 1236, 1912, 3437, 1804, 4523, 1109, 4174, +54, 2472, -1000, -90, -1792, -2600, -2085, -4153, +-1669, -4314, -737, -3146, 291, -949, 1213, 1537, +1817, 3285, 1809, 3772, 1254, 3179, 439, 1718, +-439, -235, -1176, -1849, -1559, -2549, -1496, -2470, +-1060, -1859, -427, -845, 257, 264, 784, 967, +984, 1197, 916, 1282, 755, 1257, 529, 927, +163, 450, -215, 40, -402, -400, -511, -910, +-704, -1208, -866, -1193, -821, -974, -631, -529, +-350, 183, 175, 843, 870, 1160, 1423, 1249, +1669, 1231, 1511, 893, 867, 191, -172, -576, +-1322, -1174, -2217, -1609, -2507, -1747, -2048, -1389, +-983, -546, 411, 577, 1832, 1649, 2847, 2271, +3004, 2278, 2235, 1634, 882, 386, -768, -1069, +-2351, -2121, -3220, -2535, -3025, -2309, -2008, -1397, +-493, 9, 1228, 1317, 2622, 2146, 3204, 2469, +2855, 2163, 1707, 1175, 98, -84, -1501, -1234, +-2612, -2155, -2898, -2580, -2335, -2195, -1202, -1150, +153, 201, 1418, 1537, 2265, 2473, 2440, 2680, +1967, 2098, 1077, 843, -1, -717, -1060, -1979, +-1830, -2525, -2094, -2380, -1873, -1591, -1260, -270, +-304, 1092, 783, 1980, 1718, 2273, 2226, 1988, +2075, 1127, 1318, -87, 205, -1200, -1008, -1943, +-1947, -2185, -2272, -1772, -1894, -748, -976, 521, +197, 1642, 1269, 2258, 1890, 2140, 1885, 1308, +1306, 11, 427, -1335, -455, -2157, -1230, -2182, +-1689, -1537, -1592, -426, -1079, 885, -361, 1878, +582, 2105, 1493, 1597, 1827, 769, 1492, -148, +733, -1098, -409, -1749, -1640, -1762, -2281, -1343, +-2027, -750, -1069, 71, 385, 1024, 1920, 1727, +2801, 2016, 2604, 1870, 1386, 1193, -480, 49, +-2262, -1231, -3277, -2268, -3226, -2691, -2031, -2364, +-12, -1364, 1958, 123, 3125, 1671, 3341, 2725, +2600, 3044, 935, 2602, -1051, 1420, -2522, -214, +-3123, -1769, -2864, -2840, -1792, -3187, -188, -2746, +1337, -1566, 2265, 126, 2507, 1805, 2129, 2936, +1152, 3320, -171, 2859, -1294, 1521, -1866, -302, +-1905, -1885, -1454, -2858, -581, -3105, 344, -2457, +962, -1054, 1218, 500, 1095, 1704, 645, 2358, +168, 2381, -149, 1779, -354, 785, -407, -243, +-271, -1016, -140, -1467, -137, -1627, -186, -1463, +-283, -958, -415, -341, -369, 201, -61, 763, +300, 1320, 617, 1513, 940, 1308, 1055, 956, +723, 396, 103, -447, -546, -1194, -1152, -1554, +-1532, -1589, -1420, -1338, -822, -674, 82, 303, +1096, 1178, 1857, 1661, 2024, 1805, 1529, 1548, +496, 741, -810, -381, -1923, -1294, -2412, -1796, +-2131, -1904, -1140, -1459, 297, -436, 1686, 711, +2567, 1504, 2636, 1824, 1786, 1694, 258, 1008, +-1373, -46, -2535, -934, -2878, -1364, -2267, -1426, +-904, -1102, 730, -410, 2150, 296, 2871, 695, +2596, 835, 1470, 756, -126, 484, -1735, 174, +-2781, -14, -2847, -81, -2000, -118, -591, -186, +1024, -296, 2357, -435, 2889, -509, 2453, -456, +1230, -219, -425, 234, -1976, 747, -2841, 1044, +-2727, 970, -1784, 494, -352, -251, 1154, -1013, +2218, -1515, 2494, -1489, 2037, -777, 1057, 384, +-199, 1509, -1306, 2178, -1914, 2103, -2048, 1159, +-1743, -389, -965, -1950, 14, -2885, 812, -2802, +1401, -1651, 1799, 232, 1752, 2169, 1166, 3395, +290, 3449, -598, 2285, -1319, 282, -1814, -1837, +-1921, -3270, -1424, -3621, -536, -2847, 313, -1106, +1056, 947, 1716, 2456, 1918, 3136, 1465, 2990, +762, 1954, 6, 369, -909, -1063, -1707, -2027, +-1941, -2462, -1627, -2241, -1033, -1440, -160, -363, +893, 738, 1605, 1550, 1701, 1871, 1416, 1765, +905, 1279, 93, 421, -793, -455, -1259, -1021, +-1216, -1311, -979, -1319, -669, -930, -161, -403, +358, -23, 510, 321, 456, 693, 524, 842, +556, 784, 426, 811, 353, 801, 363, 455, +186, -43, -249, -499, -705, -986, -1032, -1382, +-1218, -1431, -1160, -1106, -684, -450, 128, 412, +931, 1219, 1550, 1799, 1918, 2067, 1796, 1800, +1070, 934, -81, -231, -1338, -1373, -2327, -2328, +-2735, -2797, -2398, -2451, -1288, -1323, 344, 229, +1987, 1868, 3129, 3154, 3382, 3580, 2561, 2936, +842, 1385, -1279, -659, -3075, -2595, -3828, -3826, +-3318, -3956, -1850, -2885, 164, -897, 2171, 1327, +3411, 3122, 3409, 4037, 2309, 3745, 576, 2303, +-1235, 287, -2523, -1676, -2862, -3107, -2257, -3605, +-1062, -3024, 257, -1632, 1274, 140, 1701, 1778, +1520, 2759, 939, 2884, 243, 2307, -306, 1140, +-588, -374, -657, -1619, -595, -2126, -466, -2033, +-387, -1539, -361, -659, -255, 362, -67, 1066, +143, 1301, 387, 1220, 634, 972, 714, 590, +486, 148, 39, -231, -425, -500, -733, -707, +-752, -837, -481, -789, -35, -497, 372, -91, +526, 318, 380, 677, 17, 821, -397, 620, +-672, 187, -674, -265, -325, -548, 298, -524, +895, -176, 1120, 331, 882, 739, 289, 801, +-523, 472, -1256, -131, -1492, -860, -1158, -1405, +-535, -1382, 205, -753, 949, 190, 1367, 1119, +1240, 1779, 750, 1906, 179, 1378, -406, 373, +-900, -753, -1079, -1649, -945, -2038, -662, -1824, +-310, -1116, 82, -140, 448, 859, 680, 1587, +755, 1850, 711, 1684, 591, 1180, 358, 400, +-44, -441, -502, -1109, -889, -1511, -1160, -1596, +-1188, -1317, -842, -777, -196, -99, 481, 619, +1052, 1194, 1454, 1421, 1449, 1316, 940, 1003, +117, 512, -767, -74, -1461, -544, -1713, -845, +-1394, -1002, -681, -925, 140, -686, 857, -494, +1270, -262, 1267, 100, 858, 420, 234, 673, +-329, 995, -725, 1270, -895, 1265, -768, 949, +-439, 354, -124, -551, 36, -1574, 43, -2298, +-10, -2402, 0, -1806, 162, -576, 422, 1036, +626, 2536, 638, 3348, 421, 3147, -10, 1980, +-617, 189, -1149, -1728, -1284, -3162, -971, -3599, +-357, -2927, 406, -1458, 1080, 368, 1312, 2078, +978, 3092, 321, 3059, -396, 2207, -1011, 918, +-1254, -573, -909, -1831, -198, -2318, 476, -2033, +921, -1337, 952, -418, 474, 538, -245, 1133, +-873, 1214, -1205, 973, -1063, 609, -417, 250, +453, 23, 1190, -54, 1518, -75, 1243, -135, +433, -302, -593, -583, -1462, -791, -1904, -716, +-1723, -389, -862, 68, 267, 642, 1145, 1133, +1638, 1165, 1663, 698, 1072, 76, 99, -479, +-711, -891, -1156, -970, -1306, -561, -1040, 133, +-431, 652, 133, 772, 428, 600, 458, 148, +340, -551, 148, -1091, -55, -1035, -115, -453, +71, 300, 355, 1085, 423, 1743, 277, 1750, +88, 874, -328, -336, -974, -1373, -1321, -2199, +-1124, -2428, -682, -1564, -30, -58, 941, 1292, +1741, 2327, 1847, 2847, 1371, 2324, 491, 867, +-707, -726, -1826, -1972, -2362, -2724, -2130, -2678, +-1231, -1652, 48, -54, 1286, 1438, 2076, 2411, +2152, 2711, 1500, 2152, 432, 781, -663, -817, +-1513, -1971, -1844, -2455, -1534, -2220, -850, -1160, +-96, 428, 595, 1744, 999, 2272, 928, 2064, +568, 1238, 192, -83, -176, -1380, -459, -2010, +-430, -1828, -165, -1116, 59, -69, 149, 1055, +98, 1712, -150, 1597, -564, 996, -882, 229, +-861, -601, -541, -1235, 9, -1337, 762, -918, +1505, -267, 1791, 371, 1316, 902, 290, 1178, +-905, 986, -2048, 407, -2747, -169, -2518, -610, +-1350, -1005, 261, -1094, 1847, -603, 3028, 87, +3276, 559, 2358, 910, 634, 1111, -1328, 852, +-2969, 226, -3741, -392, -3317, -840, -1881, -1044, +76, -890, 2043, -407, 3388, 266, 3603, 881, +2686, 1125, 979, 944, -1082, 524, -2825, -98, +-3553, -837, -3131, -1241, -1848, -1003, -38, -405, +1739, 230, 2803, 865, 2796, 1274, 1855, 1071, +409, 352, -1048, -435, -2053, -1005, -2260, -1204, +-1630, -881, -525, -131, 563, 718, 1293, 1310, +1471, 1343, 1069, 809, 249, 34, -585, -759, +-1066, -1396, -1171, -1503, -965, -940, -417, -138, +268, 528, 668, 1102, 772, 1461, 832, 1277, +651, 716, 104, 204, -414, -308, -675, -934, +-896, -1307, -1089, -1244, -866, -996, -276, -548, +218, 238, 588, 1064, 944, 1538, 1068, 1563, +797, 1160, 285, 393, -280, -496, -878, -1202, +-1338, -1482, -1408, -1243, -1076, -633, -460, 61, +281, 634, 969, 939, 1370, 892, 1312, 621, +896, 341, 246, 118, -569, -50, -1303, -139, +-1613, -198, -1368, -335, -769, -541, -34, -673, +715, -610, 1227, -347, 1215, 64, 710, 551, +31, 947, -637, 1058, -1166, 870, -1190, 474, +-625, -47, 114, -531, 703, -768, 1031, -765, +886, -646, 170, -409, -758, -93, -1374, 125, +-1441, 213, -987, 290, -142, 422, 880, 567, +1678, 661, 1783, 668, 1115, 565, 21, 250, +-1183, -329, -2163, -964, -2356, -1374, -1594, -1470, +-358, -1185, 915, -402, 1948, 722, 2337, 1740, +1892, 2303, 872, 2261, -439, 1565, -1729, 301, +-2425, -1238, -2296, -2554, -1628, -3148, -599, -2818, +647, -1667, 1659, 70, 2031, 1969, 1838, 3413, +1326, 3899, 480, 3247, -593, 1633, -1450, -503, +-1799, -2570, -1805, -3941, -1640, -4157, -1051, -3158, +-41, -1282, 835, 930, 1367, 2899, 1770, 4070, +1879, 4078, 1327, 2937, 374, 1060, -458, -985, +-1200, -2723, -1922, -3751, -2259, -3705, -1921, -2581, +-1123, -882, -250, 841, 631, 2339, 1521, 3287, +2127, 3226, 2184, 2259, 1725, 1006, 888, -241, +-257, -1482, -1513, -2380, -2483, -2532, -2839, -2111, +-2486, -1476, -1500, -600, -71, 559, 1437, 1654, +2527, 2339, 2871, 2570, 2386, 2285, 1150, 1325, +-465, -138, -1832, -1587, -2534, -2578, -2490, -2860, +-1744, -2302, -503, -960, 726, 737, 1406, 2068, +1430, 2543, 1001, 2218, 303, 1290, -385, -65, +-744, -1274, -644, -1687, -187, -1337, 279, -660, +433, 146, 284, 821, -50, 933, -588, 468, +-1148, -185, -1275, -717, -934, -889, -371, -561, +408, 108, 1201, 861, 1561, 1470, 1381, 1566, +851, 986, 95, 66, -795, -848, -1511, -1628, +-1799, -2013, -1680, -1714, -1193, -829, -368, 260, +587, 1244, 1323, 1932, 1627, 2139, 1508, 1720, +994, 799, 217, -251, -591, -1168, -1222, -1820, +-1487, -1957, -1376, -1454, -1010, -614, -473, 219, +106, 989, 533, 1546, 695, 1582, 691, 1140, +671, 592, 627, 86, 498, -456, 265, -900, +-89, -994, -609, -858, -1195, -761, -1557, -606, +-1535, -211, -1144, 256, -367, 635, 689, 1010, +1626, 1353, 2063, 1407, 1924, 1007, 1257, 260, +131, -573, -1147, -1345, -2103, -1963, -2530, -2034, +-2388, -1260, -1530, -103, -138, 918, 1202, 1839, +2106, 2408, 2473, 2025, 2179, 934, 1192, -133, +-126, -1077, -1310, -1876, -2148, -2014, -2471, -1399, +-2153, -563, -1229, 200, -5, 902, 1039, 1394, +1673, 1491, 1924, 1251, 1748, 834, 1022, 334, +-60, -252, -967, -900, -1538, -1408, -1894, -1577, +-1827, -1394, -1129, -864, -100, 29, 766, 1067, +1353, 1815, 1631, 2002, 1341, 1653, 538, 861, +-362, -223, -1075, -1221, -1456, -1693, -1331, -1568, +-713, -1055, -8, -313, 453, 452, 682, 895, +629, 874, 242, 600, -286, 288, -633, 12, +-598, -111, -275, 38, 102, 329, 400, 457, +578, 295, 524, -46, 157, -438, -310, -815, +-670, -1022, -990, -834, -1218, -280, -1049, 325, +-429, 749, 287, 994, 832, 1030, 1248, 741, +1470, 295, 1219, 34, 465, -92, -450, -341, +-1282, -594, -1933, -675, -2134, -808, -1635, -1037, +-661, -914, 366, -289, 1296, 476, 1995, 1208, +2137, 1912, 1594, 2240, 579, 1801, -553, 733, +-1561, -568, -2263, -1817, -2383, -2737, -1806, -2968, +-768, -2276, 361, -824, 1386, 858, 2105, 2271, +2145, 3156, 1471, 3272, 444, 2399, -629, 778, +-1508, -909, -1941, -2168, -1791, -2848, -1176, -2762, +-324, -1837, 504, -489, 1011, 711, 1134, 1488, +902, 1792, 342, 1657, -226, 1200, -497, 629, +-524, 203, -421, 0, -189, -214, 49, -598, +85, -984, -58, -1247, -292, -1388, -510, -1221, +-514, -564, -361, 378, -177, 1264, 142, 1875, +506, 2004, 633, 1564, 570, 723, 515, -248, +310, -1060, -182, -1496, -673, -1556, -1012, -1347, +-1323, -901, -1383, -320, -895, 189, -85, 612, +682, 1083, 1329, 1507, 1726, 1655, 1574, 1471, +871, 968, -51, 107, -926, -977, -1617, -1928, +-1959, -2411, -1779, -2252, -1106, -1425, -292, -121, +407, 1268, 1034, 2314, 1469, 2691, 1473, 2273, +1109, 1233, 616, -66, 51, -1264, -627, -2018, +-1216, -2075, -1478, -1494, -1478, -594, -1343, 305, +-984, 991, -275, 1301, 597, 1142, 1321, 611, +1737, 28, 1728, -332, 1254, -449, 374, -413, +-731, -187, -1644, 206, -2098, 460, -2064, 398, +-1444, 219, -294, 38, 872, -263, 1509, -607, +1596, -724, 1273, -574, 543, -345, -321, -68, +-929, 370, -1150, 870, -1006, 1149, -576, 1127, +-45, 917, 340, 495, 452, -207, 294, -1006, +-74, -1562, -413, -1696, -528, -1424, -458, -757, +-245, 255, 110, 1313, 476, 2000, 673, 2107, +622, 1670, 316, 792, -139, -347, -559, -1376, +-850, -1923, -972, -1897, -859, -1416, -540, -611, +-116, 345, 316, 1142, 611, 1511, 704, 1449, +723, 1115, 658, 619, 379, 39, -25, -480, +-396, -756, -772, -786, -1174, -744, -1358, -679, +-1127, -491, -601, -239, 61, -32, 803, 255, +1464, 683, 1711, 1027, 1366, 1143, 626, 1060, +-295, 698, -1210, 11, -1817, -755, -1922, -1322, +-1546, -1615, -821, -1519, 127, -872, 1062, 139, +1636, 1069, 1744, 1690, 1450, 1960, 766, 1698, +-222, 811, -1194, -359, -1790, -1364, -1953, -1981, +-1673, -2034, -868, -1429, 175, -360, 1063, 832, +1672, 1796, 1890, 2189, 1526, 1907, 633, 1061, +-444, -144, -1447, -1306, -2139, -1989, -2163, -2045, +-1505, -1483, -480, -429, 626, 717, 1571, 1587, +2094, 2051, 1964, 1936, 1171, 1153, 7, 79, +-1111, -858, -1903, -1595, -2270, -2015, -2022, -1839, +-1115, -1089, 2, -74, 927, 954, 1635, 1816, +2013, 2280, 1802, 2107, 1031, 1294, 21, 143, +-920, -1034, -1632, -2015, -2033, -2451, -1991, -2090, +-1417, -1127, -511, 54, 418, 1202, 1260, 2006, +1860, 2159, 1948, 1676, 1472, 827, 599, -100, +-442, -871, -1376, -1313, -2009, -1335, -2164, -993, +-1664, -523, -595, -90, 590, 309, 1417, 584, +1744, 632, 1524, 566, 737, 471, -269, 317, +-1004, 154, -1278, 30, -1159, -30, -656, 15, +152, 33, 760, -130, 740, -337, 271, -495, +-258, -730, -686, -870, -948, -566, -803, 62, +-194, 688, 505, 1269, 973, 1686, 1135, 1583, +969, 896, 454, -52, -340, -969, -1136, -1681, +-1579, -2010, -1521, -1789, -1090, -1027, -422, -16, +414, 894, 1133, 1576, 1461, 1982, 1404, 1929, +1013, 1350, 324, 516, -501, -278, -1218, -1039, +-1602, -1715, -1552, -1970, -1144, -1688, -490, -1144, +326, -447, 1056, 507, 1416, 1498, 1405, 2098, +1097, 2224, 459, 1984, -342, 1269, -1018, 39, +-1495, -1326, -1771, -2349, -1670, -2831, -1022, -2675, +18, -1731, 1046, -122, 1785, 1604, 2159, 2882, +2016, 3422, 1133, 3044, -267, 1700, -1535, -198, +-2338, -1931, -2621, -3022, -2169, -3326, -1013, -2705, +332, -1216, 1394, 514, 2022, 1803, 2114, 2536, +1604, 2734, 752, 2222, -96, 1134, -807, 7, +-1315, -858, -1593, -1558, -1635, -2072, -1438, -2127, +-1039, -1668, -423, -955, 403, -123, 1282, 915, +1941, 2007, 2173, 2634, 1922, 2505, 1069, 1792, +-299, 655, -1653, -820, -2552, -2190, -2867, -2890, +-2506, -2771, -1410, -1954, 122, -589, 1502, 963, +2390, 2169, 2696, 2714, 2308, 2573, 1295, 1811, +37, 594, -1096, -698, -1982, -1677, -2468, -2181, +-2310, -2175, -1565, -1647, -567, -719, 412, 323, +1234, 1191, 1749, 1735, 1793, 1905, 1392, 1664, +772, 1019, 69, 141, -652, -692, -1188, -1312, +-1368, -1659, -1264, -1626, -1026, -1177, -707, -448, +-293, 396, 181, 1183, 655, 1653, 1016, 1649, +1149, 1223, 1034, 474, 694, -436, 189, -1205, +-367, -1548, -884, -1380, -1220, -790, -1251, 43, +-960, 862, -470, 1364, 54, 1333, 523, 792, +772, 12, 674, -718, 422, -1220, 234, -1291, +105, -789, -28, 85, -65, 918, 23, 1442, +-3, 1541, -258, 1108, -589, 175, -858, -889, +-989, -1652, -882, -1922, -432, -1622, 256, -747, +918, 454, 1341, 1561, 1431, 2241, 1197, 2288, +600, 1665, -317, 545, -1189, -777, -1695, -1919, +-1847, -2525, -1654, -2471, -954, -1776, 99, -516, +1034, 981, 1662, 2190, 1968, 2803, 1756, 2750, +989, 1970, -63, 568, -1081, -1021, -1814, -2286, +-2055, -2904, -1765, -2757, -1089, -1873, -179, -461, +749, 1062, 1400, 2230, 1664, 2742, 1536, 2531, +1011, 1699, 247, 445, -479, -888, -1021, -1873, +-1363, -2272, -1462, -2112, -1263, -1450, -799, -392, +-180, 707, 459, 1455, 997, 1769, 1325, 1702, +1347, 1205, 1030, 387, 476, -376, -197, -840, +-875, -1061, -1392, -1064, -1582, -792, -1379, -390, +-842, -110, -131, 42, 579, 230, 1110, 410, +1345, 503, 1212, 673, 775, 937, 251, 961, +-285, 633, -813, 150, -1111, -461, -1079, -1166, +-911, -1597, -709, -1509, -300, -1022, 272, -242, +688, 715, 863, 1479, 893, 1728, 744, 1462, +353, 850, -146, 77, -517, -646, -758, -1104, +-881, -1130, -720, -758, -285, -282, 140, 73, +344, 322, 338, 409, 202, 199, -48, -146, +-292, -276, -324, -128, -79, 122, 234, 448, +460, 880, 648, 1137, 698, 899, 336, 264, +-341, -483, -941, -1219, -1301, -1769, -1428, -1818, +-1182, -1252, -482, -269, 429, 822, 1184, 1715, +1667, 2177, 1842, 2078, 1539, 1392, 687, 334, +-445, -705, -1445, -1504, -2103, -1969, -2330, -1937, +-1917, -1412, -897, -637, 305, 225, 1333, 1064, +2091, 1664, 2364, 1840, 1893, 1589, 857, 996, +-322, 170, -1402, -711, -2161, -1395, -2335, -1650, +-1830, -1435, -837, -893, 291, -166, 1262, 579, +1900, 1083, 2039, 1208, 1564, 1034, 630, 653, +-401, 149, -1287, -319, -1870, -638, -1961, -779, +-1502, -710, -656, -466, 311, -146, 1172, 223, +1713, 578, 1743, 740, 1259, 641, 457, 372, +-396, -10, -1113, -444, -1562, -724, -1580, -694, +-1161, -416, -541, -34, 73, 366, 604, 667, +1005, 700, 1141, 437, 984, 64, 711, -243, +435, -403, 50, -370, -486, -177, -980, 57, +-1259, 227, -1377, 218, -1294, -18, -860, -316, +-117, -454, 696, -417, 1394, -224, 1834, 215, +1856, 787, 1366, 1120, 479, 1037, -546, 674, +-1410, 109, -1925, -649, -2061, -1354, -1847, -1658, +-1251, -1467, -356, -910, 582, -112, 1383, 810, +2022, 1608, 2394, 2004, 2238, 1913, 1473, 1412, +325, 558, -1036, -528, -2397, -1550, -3301, -2230, +-3340, -2425, -2468, -2056, -902, -1113, 1005, 198, +2708, 1526, 3664, 2534, 3579, 2939, 2433, 2567, +627, 1470, -1232, -72, -2672, -1637, -3308, -2754, +-2936, -3098, -1790, -2572, -397, -1290, 841, 379, +1723, 1901, 2039, 2822, 1752, 2893, 1113, 2099, +428, 689, -175, -867, -667, -2073, -948, -2567, +-978, -2234, -918, -1228, -829, 113, -617, 1350, +-210, 2055, 252, 2014, 590, 1324, 777, 280, +819, -751, 633, -1438, 282, -1575, -46, -1133, +-290, -329, -519, 475, -633, 1013, -532, 1146, +-344, 845, -223, 267, -81, -300, 152, -676, +321, -793, 313, -627, 237, -265, 150, 99, +-18, 338, -236, 457, -326, 504, -204, 502, +41, 428, 253, 274, 369, 64, 339, -248, +32, -682, -482, -1057, -851, -1151, -919, -882, +-732, -265, -227, 594, 527, 1433, 1142, 1947, +1358, 1896, 1187, 1193, 605, 27, -335, -1221, +-1253, -2180, -1753, -2537, -1704, -2112, -1164, -1019, +-270, 380, 737, 1645, 1541, 2417, 1839, 2498, +1514, 1886, 776, 791, -85, -429, -967, -1412, +-1640, -1930, -1774, -1922, -1351, -1477, -658, -772, +133, 25, 896, 720, 1384, 1147, 1430, 1298, +1084, 1239, 460, 962, -211, 485, -771, -62, +-1142, -536, -1208, -862, -913, -993, -442, -920, +16, -616, 427, -146, 759, 263, 884, 484, +777, 615, 500, 652, 115, 463, -315, 162, +-680, -32, -891, -167, -889, -343, -664, -412, +-273, -289, 169, -112, 586, 52, 867, 270, +896, 451, 676, 403, 307, 147, -152, -147, +-600, -437, -899, -688, -1010, -697, -934, -363, +-615, 151, -53, 634, 561, 984, 998, 1104, +1194, 861, 1094, 257, 632, -453, -72, -988, +-758, -1263, -1237, -1257, -1396, -878, -1136, -192, +-490, 517, 297, 1016, 929, 1247, 1179, 1207, +1045, 884, 641, 329, 32, -273, -581, -727, +-855, -995, -744, -1097, -477, -934, -167, -506, +203, -15, 422, 426, 328, 794, 74, 948, +-112, 810, -199, 485, -251, 81, -270, -311, +-128, -537, 121, -542, 269, -382, 285, -113, +348, 151, 409, 253, 262, 190, -49, 43, +-362, -178, -711, -398, -1033, -455, -1130, -304, +-842, -22, -178, 322, 699, 673, 1479, 934, +1896, 977, 1795, 732, 1098, 254, -121, -368, +-1467, -1033, -2442, -1573, -2716, -1775, -2197, -1501, +-967, -768, 666, 261, 2147, 1372, 2917, 2301, +2760, 2714, 1815, 2370, 392, 1330, -1121, -130, +-2279, -1660, -2722, -2862, -2357, -3360, -1411, -2948, +-245, -1697, 863, 15, 1679, 1674, 1970, 2900, +1731, 3427, 1239, 3055, 654, 1902, -76, 415, +-829, -1034, -1377, -2240, -1664, -2930, -1723, -2916, +-1468, -2320, -851, -1376, 13, -179, 915, 1156, +1691, 2308, 2168, 2946, 2158, 3022, 1558, 2584, +575, 1515, -532, -125, -1622, -1798, -2459, -3009, +-2681, -3675, -2227, -3628, -1312, -2550, -121, -683, +1232, 1266, 2359, 2900, 2847, 4025, 2631, 4189, +1923, 3133, 815, 1274, -637, -760, -2047, -2581, +-2858, -3807, -2973, -4009, -2542, -3107, -1554, -1486, +-40, 308, 1507, 1857, 2550, 2862, 2972, 3075, +2810, 2481, 1971, 1430, 546, 313, -1025, -708, +-2217, -1467, -2796, -1760, -2751, -1653, -2036, -1362, +-756, -938, 594, -377, 1540, 183, 2012, 622, +2035, 961, 1524, 1195, 670, 1234, -103, 1014, +-614, 582, -931, 73, -1059, -415, -969, -854, +-782, -1120, -637, -1069, -433, -754, -60, -355, +319, 57, 565, 445, 755, 678, 846, 673, +691, 517, 359, 330, 80, 150, -117, -4, +-288, -85, -402, -90, -423, -83, -461, -128, +-594, -230, -731, -353, -650, -458, -352, -510, +37, -462, 497, -267, 1031, 87, 1375, 521, +1301, 906, 877, 1127, 262, 1098, -528, 773, +-1279, 164, -1682, -596, -1613, -1239, -1176, -1560, +-518, -1510, 208, -1086, 887, -350, 1347, 463, +1464, 1089, 1260, 1418, 879, 1432, 365, 1146, +-222, 672, -758, 140, -1168, -381, -1392, -832, +-1366, -1158, -1117, -1316, -648, -1252, 42, -931, +807, -364, 1404, 384, 1730, 1136, 1718, 1612, +1266, 1661, 415, 1300, -616, 567, -1554, -389, +-2088, -1227, -2038, -1652, -1464, -1582, -505, -1083, +668, -287, 1654, 560, 2032, 1155, 1774, 1316, +1103, 1068, 135, 537, -907, -121, -1576, -680, +-1618, -910, -1206, -776, -554, -424, 201, 16, +846, 435, 1121, 650, 1021, 554, 691, 251, +259, -90, -212, -386, -633, -556, -899, -504, +-889, -256, -657, 40, -274, 267, 180, 393, +584, 398, 758, 282, 726, 122, 579, 11, +318, -22, -54, -23, -343, -35, -494, -81, +-550, -201, -555, -391, -525, -537, -479, -524, +-349, -336, -106, -7, 224, 419, 612, 807, +1029, 980, 1241, 862, 1078, 499, 596, -13, +-99, -518, -904, -866, -1575, -979, -1826, -831, +-1546, -485, -849, -88, 61, 264, 963, 532, +1662, 657, 1909, 618, 1545, 475, 783, 274, +-54, 14, -836, -258, -1404, -422, -1473, -403, +-1029, -255, -443, -70, 27, 132, 378, 279, +529, 182, 379, -183, 108, -543, -9, -689, +101, -611, 322, -245, 584, 442, 807, 1181, +837, 1545, 475, 1360, -273, 745, -1101, -187, +-1651, -1250, -1841, -1981, -1581, -1994, -770, -1397, +392, -469, 1432, 642, 2101, 1624, 2314, 2015, +1975, 1720, 1038, 1022, -229, 163, -1425, -720, +-2212, -1386, -2441, -1572, -2035, -1293, -1092, -795, +81, -223, 1104, 403, 1818, 932, 2094, 1142, +1813, 1071, 1053, 878, 139, 510, -695, -54, +-1344, -564, -1652, -851, -1469, -986, -948, -984, +-315, -752, 325, -350, 862, 57, 1089, 406, +935, 714, 600, 947, 290, 1041, 23, 937, +-216, 621, -358, 142, -337, -418, -268, -990, +-305, -1423, -413, -1489, -499, -1116, -493, -459, +-309, 308, 100, 1045, 606, 1522, 945, 1539, +1002, 1127, 795, 462, 345, -275, -242, -898, +-752, -1237, -1045, -1226, -1039, -918, -701, -416, +-137, 164, 401, 643, 780, 861, 894, 829, +649, 612, 175, 215, -224, -235, -461, -486, +-520, -481, -375, -359, -85, -136, 156, 163, +264, 312, 234, 188, 135, -49, 11, -250, +-90, -382, -161, -368, -129, -158, -44, 155, +12, 432, 22, 554, 38, 485, 16, 290, +-13, 37, -12, -214, 30, -354, 69, -356, +112, -327, 129, -303, 90, -201, 20, -82, +-48, -65, -165, -25, -327, 169, -410, 339, +-292, 349, -47, 344, 206, 376, 448, 271, +626, 29, 608, -159, 361, -252, -2, -342, +-364, -429, -662, -447, -794, -368, -662, -245, +-293, -121, 159, 62, 512, 332, 716, 554, +747, 627, 503, 583, 47, 426, -372, 131, +-612, -211, -665, -478, -452, -601, 13, -549, +474, -365, 694, -168, 617, -23, 231, 74, +-309, 99, -749, 50, -886, 49, -641, 194, +-62, 412, 566, 568, 963, 598, 990, 464, +675, 110, 122, -411, -430, -884, -788, -1116, +-816, -1042, -571, -662, -228, -41, 62, 609, +290, 1029, 345, 1125, 237, 951, 177, 534, +282, -36, 359, -488, 332, -657, 265, -664, +111, -599, -252, -408, -650, -183, -845, -95, +-790, -90, -544, -13, -96, 162, 487, 372, +972, 589, 1133, 773, 992, 837, 657, 675, +140, 244, -514, -344, -1080, -901, -1340, -1308, +-1268, -1458, -868, -1238, -157, -644, 644, 181, +1271, 1013, 1576, 1607, 1488, 1802, 979, 1542, +143, 836, -753, -159, -1422, -1092, -1670, -1668, +-1425, -1807, -796, -1473, 8, -672, 769, 307, +1316, 1047, 1475, 1394, 1211, 1395, 681, 1028, +62, 348, -568, -339, -1043, -747, -1206, -900, +-1014, -916, -621, -746, -158, -377, 331, -5, +790, 240, 986, 470, 851, 760, 595, 920, +381, 787, 23, 490, -406, 137, -606, -393, +-599, -1036, -663, -1400, -676, -1286, -432, -870, +-60, -235, 228, 640, 520, 1466, 850, 1830, +1029, 1622, 853, 968, 383, -1, -171, -1053, +-642, -1849, -976, -2122, -1005, -1737, -608, -768, +15, 443, 514, 1488, 753, 2108, 722, 2130, +389, 1440, -166, 224, -668, -1035, -858, -1916, +-650, -2191, -126, -1759, 551, -737, 1186, 507, +1500, 1576, 1286, 2120, 599, 1903, -345, 1016, +-1339, -147, -2096, -1223, -2247, -1958, -1681, -2077, +-621, -1458, 704, -357, 2049, 789, 2918, 1664, +2865, 2082, 1918, 1894, 482, 1108, -1070, -21, +-2360, -1097, -2965, -1794, -2659, -1976, -1622, -1646, +-240, -865, 1061, 143, 1981, 1006, 2285, 1434, +1949, 1414, 1194, 1073, 366, 511, -389, -104, +-994, -496, -1303, -537, -1197, -379, -861, -237, +-466, -171, -96, -207, 203, -401, 350, -661, +380, -753, 351, -547, 355, -78, 426, 535, +536, 1123, 606, 1482, 628, 1477, 481, 1075, +2, 348, -691, -524, -1222, -1286, -1439, -1735, +-1357, -1783, -889, -1428, -16, -733, 930, 148, +1563, 967, 1762, 1481, 1551, 1607, 934, 1396, +34, 889, -835, 203, -1326, -397, -1355, -768, +-1091, -955, -659, -964, -92, -773, 458, -539, +745, -396, 742, -214, 616, 93, 402, 371, +110, 597, -109, 865, -136, 1026, -41, 864, +46, 453, 84, -37, 87, -550, 10, -994, +-187, -1175, -477, -1000, -651, -578, -573, -78, +-288, 407, 123, 776, 617, 914, 970, 788, +988, 477, 711, 76, 311, -327, -201, -626, +-696, -726, -904, -610, -698, -295, -326, 146, +-3, 571, 234, 810, 382, 757, 286, 410, +11, -129, -169, -722, -101, -1189, 85, -1304, +319, -931, 611, -216, 857, 570, 774, 1284, +304, 1767, -328, 1727, -907, 1107, -1353, 210, +-1480, -686, -1114, -1489, -378, -2000, 425, -1964, +1121, -1416, 1593, -615, 1687, 282, 1350, 1156, +712, 1779, -20, 1963, -664, 1715, -1104, 1124, +-1279, 297, -1189, -584, -925, -1296, -589, -1677, +-196, -1685, 241, -1367, 607, -792, 853, -114, +1040, 482, 1134, 929, 1068, 1221, 858, 1287, +482, 1099, -98, 767, -757, 367, -1300, -134, +-1616, -673, -1632, -1071, -1282, -1241, -644, -1203, +201, -964, 1081, -523, 1740, 53, 2019, 618, +1937, 1036, 1443, 1268, 570, 1309, -413, 1085, +-1185, 573, -1724, -87, -2018, -727, -1942, -1267, +-1409, -1596, -611, -1543, 237, -1090, 1084, -397, +1916, 402, 2428, 1171, 2389, 1673, 1849, 1737, +937, 1410, -346, 780, -1735, -104, -2720, -1054, +-2980, -1739, -2547, -1975, -1495, -1758, 14, -1082, +1568, -2, 2629, 1168, 2933, 2003, 2525, 2245, +1560, 1860, 278, 915, -939, -383, -1774, -1609, +-2118, -2297, -1996, -2247, -1470, -1547, -664, -426, +216, 813, 968, 1781, 1477, 2160, 1689, 1892, +1539, 1142, 1028, 131, 310, -874, -430, -1591, +-1056, -1884, -1389, -1733, -1315, -1159, -941, -317, +-406, 537, 195, 1238, 728, 1701, 1055, 1776, +1196, 1388, 1146, 687, 837, -112, 303, -904, +-305, -1562, -913, -1891, -1400, -1759, -1576, -1230, +-1287, -461, -596, 436, 339, 1341, 1302, 1988, +2034, 2114, 2182, 1717, 1615, 955, 551, -89, +-633, -1247, -1715, -2122, -2350, -2380, -2195, -2030, +-1293, -1210, -75, -41, 1124, 1183, 2010, 2020, +2274, 2241, 1787, 1888, 796, 1070, -324, -27, +-1231, -1026, -1721, -1607, -1664, -1736, -1083, -1478, +-212, -871, 570, -112, 1075, 505, 1267, 871, +1097, 1043, 585, 1024, 12, 798, -354, 456, +-489, 105, -469, -239, -333, -566, -180, -834, +-114, -960, -128, -871, -161, -575, -170, -155, +-85, 314, 145, 753, 461, 1017, 749, 992, +903, 710, 799, 274, 412, -241, -129, -725, +-660, -999, -1051, -992, -1146, -773, -893, -395, +-397, 104, 203, 590, 781, 901, 1108, 976, +1071, 852, 791, 549, 408, 74, -77, -462, +-550, -872, -821, -1079, -806, -1107, -589, -908, +-211, -425, 245, 203, 645, 758, 807, 1153, +674, 1344, 336, 1208, -46, 714, -430, 41, +-697, -595, -689, -1104, -363, -1394, 105, -1340, +551, -952, 823, -395, 790, 182, 447, 697, +-12, 1062, -417, 1197, -637, 1074, -647, 736, +-452, 276, -112, -232, 281, -715, 572, -1068, +659, -1191, 549, -1072, 323, -727, 27, -190, +-250, 415, -416, 906, -444, 1209, -349, 1279, +-133, 1003, 123, 395, 277, -289, 300, -871, +274, -1310, 210, -1470, 111, -1177, 53, -529, +44, 187, 36, 797, 16, 1243, -17, 1388, +-65, 1118, -144, 553, -227, -55, -237, -559, +-120, -922, 73, -1104, 270, -1027, 440, -722, +540, -336, 472, 43, 268, 423, 18, 744, +-246, 893, -522, 839, -677, 602, -633, 202, +-419, -247, -73, -597, 423, -759, 888, -692, +1107, -397, 1023, -4, 714, 309, 214, 428, +-401, 316, -992, 17, -1321, -313, -1266, -524, +-846, -515, -194, -236, 575, 224, 1232, 645, +1505, 870, 1319, 841, 847, 514, 227, -61, +-414, -652, -897, -1017, -1043, -1062, -881, -804, +-541, -322, -157, 226, 150, 659, 335, 822, +447, 685, 481, 352, 457, -7, 443, -277, +432, -400, 342, -360, 176, -192, -14, -16, +-244, 49, -476, -15, -593, -121, -578, -181, +-446, -161, -204, -53, 88, 166, 383, 429, +682, 550, 927, 441, 998, 172, 782, -201, +293, -614, -327, -896, -882, -908, -1245, -658, +-1296, -215, -912, 314, -153, 774, 653, 1032, +1291, 1039, 1636, 806, 1513, 400, 875, -83, +27, -550, -709, -917, -1226, -1110, -1464, -1118, +-1252, -961, -680, -625, -4, -117, 589, 462, +1050, 978, 1269, 1335, 1176, 1465, 863, 1291, +488, 785, 54, 45, -429, -745, -875, -1404, +-1114, -1804, -1098, -1831, -869, -1420, -466, -664, +112, 240, 736, 1109, 1218, 1776, 1438, 2045, +1377, 1802, 974, 1099, 291, 124, -441, -895, +-1037, -1709, -1397, -2077, -1383, -1891, -987, -1229, +-392, -277, 214, 695, 779, 1387, 1195, 1621, +1303, 1396, 1106, 825, 783, 113, 417, -507, +-45, -849, -565, -871, -918, -665, -1041, -370, +-1058, -95, -921, 70, -467, 73, 192, -31, +793, -89, 1233, -10, 1500, 172, 1429, 380, +912, 550, 103, 586, -691, 395, -1277, -3, +-1538, -448, -1335, -788, -616, -930, 306, -797, +1062, -392, 1497, 103, 1521, 513, 999, 777, +102, 826, -744, 600, -1244, 215, -1352, -132, +-977, -392, -205, -577, 610, -620, 1118, -511, +1260, -352, 1082, -198, 633, -5, 23, 225, +-468, 433, -679, 571, -651, 611, -521, 508, +-333, 256, -120, -99, 30, -484, 97, -787, +186, -898, 321, -788, 470, -498, 575, -87, +622, 366, 564, 743, 357, 935, 42, 903, +-285, 678, -554, 300, -664, -181, -563, -648, +-324, -964, -90, -1055, 123, -919, 316, -600, +404, -163, 384, 296, 374, 657, 392, 840, +389, 857, 340, 750, 264, 541, 150, 251, +-48, -89, -320, -442, -514, -773, -548, -1036, +-469, -1153, -329, -1037, -85, -649, 191, -63, +385, 571, 533, 1110, 702, 1420, 787, 1382, +737, 1008, 560, 412, 278, -271, -140, -879, +-628, -1242, -1036, -1339, -1196, -1224, -1037, -886, +-582, -350, 66, 206, 796, 652, 1335, 983, +1511, 1144, 1369, 1026, 984, 666, 371, 217, +-290, -210, -795, -558, -1090, -754, -1214, -769, +-1109, -654, -788, -494, -342, -324, 167, -152, +729, 13, 1256, 189, 1583, 400, 1565, 600, +1213, 691, 565, 608, -276, 359, -1081, -16, +-1568, -433, -1605, -758, -1223, -855, -539, -675, +285, -284, 962, 169, 1261, 543, 1183, 724, +898, 639, 524, 290, 150, -192, -101, -609, +-183, -820, -232, -797, -321, -528, -410, -59, +-472, 451, -492, 813, -373, 928, -62, 784, +359, 431, 721, -49, 917, -527, 862, -849, +569, -913, 154, -737, -215, -421, -420, -60, +-438, 268, -344, 455, -151, 429, 58, 240, +143, 52, 53, -28, -53, -15, -60, 52, +15, 194, 170, 340, 442, 323, 705, 88, +805, -232, 650, -509, 294, -717, -152, -822, +-580, -722, -912, -402, -989, 7, -732, 353, +-241, 617, 282, 823, 764, 926, 1098, 817, +1140, 513, 879, 129, 471, -301, 28, -791, +-369, -1218, -643, -1397, -732, -1251, -653, -802, +-422, -105, -106, 694, 233, 1372, 565, 1740, +829, 1685, 875, 1157, 670, 260, 288, -756, +-167, -1612, -571, -2074, -760, -1996, -663, -1374, +-329, -344, 133, 793, 605, 1659, 900, 2015, +922, 1834, 709, 1168, 345, 161, -100, -841, +-492, -1462, -687, -1603, -644, -1371, -490, -864, +-280, -203, 13, 362, 367, 637, 654, 655, +815, 574, 892, 470, 869, 357, 613, 279, +145, 263, -372, 211, -796, 11, -1102, -342, +-1172, -720, -844, -994, -158, -1070, 608, -868, +1236, -369, 1607, 286, 1639, 881, 1207, 1240, +397, 1235, -466, 824, -1120, 163, -1525, -494, +-1588, -963, -1178, -1128, -388, -922, 412, -433, +1050, 116, 1549, 511, 1803, 669, 1605, 589, +1022, 307, 297, -84, -437, -409, -1166, -531, +-1685, -466, -1727, -297, -1279, -68, -566, 182, +274, 378, 1140, 452, 1774, 392, 1893, 242, +1573, 44, 989, -188, 179, -416, -703, -580, +-1299, -632, -1443, -548, -1202, -340, -655, -73, +100, 210, 759, 495, 1082, 711, 1064, 733, +791, 562, 348, 320, -100, 34, -368, -345, +-358, -708, -174, -867, 66, -825, 254, -687, +316, -444, 208, -73, 4, 309, -166, 565, +-206, 689, -130, 699, 71, 593, 314, 395, +492, 147, 553, -118, 495, -351, 293, -522, +6, -652, -244, -750, -369, -745, -424, -577, +-386, -290, -206, 31, 75, 377, 349, 744, +565, 996, 706, 975, 761, 713, 644, 345, +390, -85, 100, -575, -163, -981, -430, -1144, +-671, -1072, -749, -852, -612, -492, -359, 8, +1, 538, 457, 955, 905, 1183, 1170, 1179, +1183, 923, 975, 431, 585, -213, 47, -843, +-509, -1275, -938, -1402, -1125, -1212, -1052, -764, +-709, -166, -146, 444, 469, 916, 963, 1133, +1275, 1062, 1318, 789, 1033, 419, 483, -27, +-105, -507, -579, -867, -878, -987, -901, -918, +-594, -725, -104, -372, 364, 129, 666, 584, +776, 789, 632, 750, 288, 572, -52, 256, +-232, -162, -263, -496, -169, -592, 33, -502, +319, -326, 529, -103, 553, 117, 416, 232, +201, 200, -77, 80, -350, -40, -473, -120, +-383, -151, -227, -126, -50, -44, 198, 56, +483, 115, 678, 99, 747, 25, 707, -74, +554, -161, 251, -197, -118, -168, -448, -95, +-658, 10, -721, 117, -592, 152, -249, 73, +213, -66, 629, -184, 925, -258, 994, -276, +803, -175, 462, 55, 113, 294, -225, 392, +-491, 323, -543, 135, -381, -156, -192, -492, +-14, -693, 163, -614, 296, -288, 356, 145, +392, 568, 438, 828, 483, 775, 460, 400, +353, -152, 161, -706, -81, -1076, -358, -1112, +-592, -795, -639, -259, -430, 333, -14, 836, +506, 1098, 944, 1029, 1157, 711, 1051, 293, +632, -144, 5, -551, -622, -860, -993, -1013, +-966, -998, -649, -844, -157, -572, 419, -192, +922, 276, 1111, 737, 965, 1067, 683, 1196, +358, 1113, -58, 797, -462, 273, -689, -347, +-675, -917, -542, -1319, -323, -1477, 70, -1349, +581, -913, 936, -247, 1017, 457, 913, 1012, +665, 1334, 174, 1354, -416, 1025, -781, 442, +-807, -173, -605, -677, -253, -1021, 187, -1130, +585, -968, 760, -639, 718, -267, 562, 121, +357, 498, 141, 766, 1, 874, -33, 838, +-37, 627, -94, 202, -149, -340, -220, -825, +-300, -1139, -243, -1246, 9, -1079, 292, -577, +525, 127, 722, 741, 799, 1132, 611, 1329, +260, 1270, -76, 851, -348, 207, -517, -402, +-481, -898, -227, -1306, 120, -1512, 368, -1362, +480, -905, 491, -328, 403, 287, 191, 903, +-56, 1360, -178, 1471, -114, 1227, 48, 764, +259, 201, 440, -385, 494, -886, 342, -1190, +28, -1260, -297, -1148, -470, -903, -447, -526, +-220, -31, 178, 506, 670, 987, 1019, 1317, +1032, 1405, 724, 1170, 238, 609, -330, -168, +-830, -953, -1064, -1528, -896, -1724, -443, -1493, +117, -885, 667, -62, 1098, 731, 1268, 1268, +1122, 1451, 752, 1278, 324, 810, -122, 177, +-544, -433, -811, -879, -821, -1115, -644, -1133, +-387, -939, -64, -585, 309, -131, 586, 337, +740, 701, 818, 887, 810, 916, 665, 775, +419, 436, 143, -15, -129, -434, -375, -748, +-493, -932, -463, -937, -344, -741, -188, -396, +46, 25, 332, 435, 527, 734, 541, 837, +458, 725, 318, 424, 121, 13, -59, -398, +-74, -663, 67, -689, 213, -512, 288, -233, +308, 67, 231, 285, 74, 308, -103, 133, +-209, -89, -192, -237, -43, -292, 142, -237, +258, -37, 289, 203, 287, 322, 202, 312, +62, 250, -18, 114, 28, -101, 134, -286, +228, -377, 282, -427, 318, -440, 284, -352, +168, -161, 36, 69, 4, 309, 51, 522, +62, 605, 7, 479, -46, 175, -108, -222, +-186, -610, -241, -867, -153, -882, 100, -627, +423, -160, 712, 389, 934, 860, 1023, 1100, +873, 1021, 425, 614, -179, -20, -764, -705, +-1190, -1249, -1340, -1503, -1109, -1371, -476, -859, +393, -86, 1172, 740, 1649, 1387, 1756, 1674, +1480, 1538, 816, 1017, -66, 218, -865, -667, +-1347, -1387, -1450, -1765, -1170, -1743, -588, -1335, +170, -614, 877, 241, 1331, 1005, 1452, 1492, +1266, 1605, 809, 1331, 177, 756, -466, 19, +-901, -701, -1048, -1203, -917, -1357, -537, -1188, +40, -788, 646, -261, 1064, 263, 1164, 637, +992, 796, 582, 760, 22, 569, -504, 274, +-793, -49, -771, -326, -500, -515, -117, -597, +310, -565, 669, -412, 836, -149, 749, 143, +543, 376, 337, 507, 96, 506, -176, 337, +-337, 43, -396, -266, -424, -492, -401, -603, +-231, -563, 59, -347, 390, -55, 693, 166, +891, 308, 890, 389, 687, 340, 304, 155, +-138, -9, -498, -82, -660, -142, -594, -184, +-375, -102, -90, 49, 230, 101, 464, 24, +524, -104, 465, -288, 404, -554, 304, -760, +169, -703, 123, -352, 169, 189, 151, 799, +75, 1322, -11, 1511, -120, 1189, -252, 406, +-313, -591, -253, -1500, -110, -2025, 79, -1957, +328, -1294, 559, -254, 701, 844, 705, 1657, +590, 1912, 368, 1550, 65, 771, -234, -147, +-443, -945, -601, -1389, -695, -1342, -628, -901, +-319, -292, 127, 273, 579, 629, 991, 673, +1269, 448, 1255, 111, 927, -174, 376, -299, +-246, -233, -831, -31, -1225, 184, -1279, 281, +-965, 200, -406, -55, 258, -366, 850, -568, +1230, -566, 1312, -383, 1118, -80, 708, 258, +222, 497, -176, 528, -433, 380, -603, 165, +-661, -27, -597, -179, -425, -280, -209, -318, +41, -316, 340, -341, 647, -375, 836, -324, +854, -150, 725, 89, 479, 341, 100, 556, +-296, 629, -538, 486, -576, 189, -463, -145, +-246, -455, 6, -681, 247, -724, 394, -574, +434, -333, 427, -72, 438, 212, 421, 468, +317, 610, 153, 608, -20, 491, -225, 243, +-400, -125, -462, -513, -348, -781, -65, -839, +271, -677, 508, -340, 619, 99, 607, 503, +448, 720, 155, 690, -85, 472, -178, 147, +-173, -184, -105, -418, 12, -494, 92, -442, +80, -328, -22, -203, -103, -85, -77, 4, +78, 71, 301, 120, 502, 168, 589, 207, +498, 197, 224, 108, -103, -13, -372, -106, +-481, -158, -388, -168, -115, -104, 241, 7, +547, 64, 672, 7, 582, -124, 296, -274, +-49, -393, -324, -412, -453, -278, -424, -19, +-246, 289, 30, 543, 329, 657, 542, 585, +638, 337, 593, -26, 427, -384, 177, -646, +-77, -784, -263, -768, -346, -559, -342, -212, +-224, 161, -38, 478, 142, 687, 238, 712, +252, 532, 220, 205, 173, -170, 155, -496, +201, -654, 254, -587, 278, -360, 248, -75, +160, 203, 18, 377, -135, 354, -225, 171, +-194, -33, -85, -192, 47, -304, 143, -306, +190, -155, 144, 31, 34, 127, -31, 150, +22, 139, 153, 47, 331, -98, 489, -188, +545, -173, 411, -107, 129, -9, -198, 123, +-459, 243, -556, 249, -441, 116, -192, -98, +105, -328, 341, -534, 448, -620, 424, -493, +361, -171, 281, 224, 175, 590, 112, 831, +145, 829, 138, 535, 31, 56, -111, -452, +-225, -859, -325, -1043, -362, -913, -237, -533, +63, -45, 371, 423, 555, 750, 615, 830, +595, 667, 433, 354, 118, 4, -203, -282, +-393, -460, -489, -543, -490, -532, -335, -433, +-10, -312, 328, -204, 553, -45, 674, 184, +702, 417, 564, 587, 264, 663, -90, 590, +-371, 335, -561, -65, -633, -509, -545, -862, +-298, -1017, 49, -941, 429, -641, 730, -160, +884, 378, 845, 808, 621, 1039, 238, 1044, +-169, 808, -476, 346, -648, -212, -706, -700, +-601, -1019, -316, -1140, 77, -997, 427, -589, +666, -55, 782, 426, 750, 770, 551, 923, +259, 840, -43, 554, -295, 192, -478, -157, +-534, -440, -449, -609, -249, -648, -2, -605, +230, -499, 397, -322, 499, -80, 506, 180, +431, 431, 301, 637, 150, 717, -11, 599, +-169, 325, -311, -28, -392, -399, -384, -706, +-251, -823, -24, -713, 253, -461, 512, -155, +671, 175, 674, 441, 512, 545, 192, 494, +-188, 388, -507, 237, -660, 29, -605, -155, +-326, -235, 89, -270, 460, -304, 647, -301, +636, -259, 462, -244, 202, -245, -63, -189, +-218, -65, -192, 93, -49, 289, 65, 499, +117, 637, 105, 616, -6, 425, -213, 81, +-345, -356, -294, -770, -107, -1022, 147, -1026, +452, -785, 720, -345, 830, 215, 700, 757, +406, 1118, 30, 1193, -373, 970, -739, 486, +-917, -146, -845, -748, -569, -1165, -161, -1303, +337, -1107, 780, -605, 1038, 41, 1063, 617, +882, 990, 522, 1095, 70, 900, -365, 467, +-664, -19, -800, -402, -764, -643, -567, -742, +-235, -688, 125, -540, 423, -377, 613, -204, +700, 35, 654, 332, 490, 627, 244, 834, +-17, 870, -251, 666, -421, 222, -463, -351, +-331, -844, -99, -1085, 150, -1004, 352, -641, +457, -122, 391, 339, 189, 559, -46, 492, +-242, 245, -336, -24, -253, -153, -43, -64, +209, 218, 402, 536, 470, 712, 405, 608, +241, 216, -2, -359, -240, -928, -353, -1323, +-313, -1405, -201, -1135, -24, -574, 196, 124, +354, 808, 376, 1332, 311, 1595, 202, 1531, +58, 1146, -113, 501, -235, -275, -257, -1015, +-176, -1543, -38, -1749, 132, -1581, 276, -1067, +328, -330, 270, 427, 183, 1035, 96, 1374, +24, 1391, -6, 1103, -3, 622, -42, 86, +-133, -390, -238, -744, -281, -917, -226, -894, +-39, -710, 242, -453, 539, -164, 730, 139, +697, 386, 406, 490, -40, 471, -527, 383, +-883, 228, -943, 17, -610, -142, 7, -184, +667, -140, 1130, -67, 1253, 12, 948, 41, +294, -29, -472, -176, -1043, -314, -1229, -387, +-986, -348, -431, -168, 247, 109, 826, 350, +1110, 478, 987, 480, 593, 347, 138, 107, +-271, -126, -564, -265, -599, -321, -362, -333, +-54, -302, 143, -247, 267, -210, 322, -179, +251, -81, 81, 105, -50, 320, -116, 488, +-168, 573, -199, 512, -123, 267, 45, -94, +247, -440, 416, -696, 510, -799, 465, -686, +274, -391, -1, -41, -257, 288, -439, 549, +-483, 671, -408, 615, -246, 452, -30, 243, +198, -2, 359, -256, 437, -419, 446, -475, +398, -474, 270, -440, 117, -337, -39, -203, +-201, -78, -333, 33, -372, 182, -316, 367, +-159, 548, 71, 654, 291, 656, 404, 501, +409, 159, 308, -340, 115, -840, -96, -1176, +-227, -1212, -265, -900, -213, -273, -94, 491, +69, 1146, 220, 1461, 310, 1331, 297, 761, +202, -77, 69, -894, -58, -1397, -163, -1438, +-200, -1016, -161, -296, -65, 475, 33, 1027, +119, 1192, 180, 949, 201, 445, 157, -118, +75, -540, -14, -700, -60, -583, -43, -314, +32, -54, 116, 86, 158, 72, 119, -71, +21, -240, -100, -301, -189, -177, -217, 96, +-136, 422, 43, 679, 248, 755, 375, 593, +385, 234, 276, -209, 91, -592, -127, -793, +-276, -769, -297, -553, -212, -234, -98, 66, +24, 243, 126, 260, 174, 169, 162, 52, +173, -10, 216, 57, 247, 254, 241, 476, +186, 607, 29, 575, -206, 335, -432, -96, +-530, -590, -457, -990, -219, -1167, 114, -1055, +456, -660, 690, -93, 728, 488, 560, 933, +271, 1136, -65, 1043, -353, 709, -523, 252, +-529, -208, -402, -576, -222, -747, -69, -711, +44, -542, 131, -327, 208, -95, 287, 106, +411, 231, 547, 274, 624, 300, 566, 326, +354, 323, -11, 233, -463, 71, -899, -148, +-1163, -398, -1146, -619, -825, -675, -257, -509, +472, -155, 1156, 298, 1578, 751, 1620, 1022, +1292, 994, 634, 665, -189, 145, -952, -460, +-1464, -959, -1621, -1191, -1394, -1115, -869, -821, +-157, -369, 570, 132, 1130, 557, 1410, 817, +1400, 936, 1088, 916, 541, 749, -84, 455, +-631, 111, -1012, -253, -1132, -598, -973, -855, +-588, -934, -112, -823, 329, -559, 674, -216, +897, 149, 907, 452, 696, 633, 362, 666, +-14, 575, -432, 387, -787, 147, -941, -109, +-853, -330, -554, -462, -52, -455, 562, -300, +1112, -29, 1385, 270, 1249, 480, 714, 499, +-53, 277, -847, -138, -1434, -596, -1604, -926, +-1263, -987, -558, -707, 277, -127, 1024, 569, +1497, 1150, 1522, 1432, 1097, 1316, 414, 814, +-271, 72, -811, -689, -1086, -1261, -1023, -1503, +-667, -1355, -205, -861, 213, -178, 509, 497, +650, 1011, 595, 1236, 391, 1114, 129, 697, +-90, 143, -235, -374, -288, -715, -246, -817, +-119, -664, 11, -340, 108, 1, 163, 210, +195, 283, 184, 245, 151, 134, 108, 21, +19, 20, -134, 103, -261, 162, -313, 135, +-293, 49, -187, -109, 43, -297, 308, -397, +481, -308, 521, -90, 448, 159, 229, 346, +-107, 395, -437, 242, -606, -34, -580, -293, +-369, -405, -3, -336, 409, -84, 675, 245, +715, 492, 552, 517, 221, 327, -222, -18, +-605, -398, -807, -670, -790, -689, -547, -466, +-94, -97, 437, 279, 887, 568, 1098, 657, +982, 534, 584, 278, 27, 15, -562, -199, +-974, -324, -1064, -338, -847, -275, -444, -221, +68, -193, 536, -173, 797, -125, 785, -39, +559, 109, 215, 283, -120, 418, -339, 454, +-368, 364, -237, 144, -50, -134, 89, -358, +145, -453, 107, -412, 23, -248, -55, -6, +-95, 201, -89, 274, -14, 217, 62, 91, +58, -63, -11, -195, -81, -234, -165, -150, +-200, 1, -87, 138, 181, 225, 459, 251, +637, 207, 658, 101, 483, -22, 83, -118, +-419, -171, -822, -192, -987, -184, -909, -156, +-587, -113, -80, -68, 433, -15, 765, 46, +892, 114, 841, 167, 644, 187, 340, 168, +30, 125, -220, 60, -402, -14, -567, -82, +-680, -113, -670, -127, -520, -134, -295, -141, +10, -126, 368, -92, 666, -28, 796, 54, +758, 153, 568, 223, 266, 234, -90, 152, +-406, 9, -609, -147, -663, -236, -592, -234, +-412, -135, -173, 11, 78, 155, 311, 209, +503, 150, 567, -8, 497, -168, 352, -256, +167, -212, -55, -53, -234, 194, -306, 414, +-290, 492, -260, 371, -227, 115, -194, -221, +-182, -550, -210, -764, -189, -747, -44, -516, +212, -151, 512, 265, 797, 682, 941, 972, +823, 1029, 415, 834, -174, 455, -789, -62, +-1265, -618, -1456, -1056, -1262, -1218, -723, -1073, +17, -679, 754, -135, 1329, 433, 1598, 839, +1477, 971, 999, 840, 317, 539, -417, 180, +-1044, -113, -1427, -260, -1452, -264, -1135, -194, +-583, -122, 62, -120, 675, -217, 1094, -357, +1217, -446, 1035, -431, 645, -297, 150, -45, +-326, 275, -671, 554, -810, 711, -751, 729, +-545, 603, -280, 345, -5, 19, 229, -306, +396, -586, 464, -764, 447, -777, 378, -620, +273, -329, 109, 47, -59, 424, -175, 678, +-255, 731, -366, 591, -450, 318, -443, -32, +-356, -342, -211, -495, 29, -448, 332, -281, +604, -68, 740, 124, 704, 244, 511, 227, +194, 100, -228, -48, -630, -128, -843, -141, +-821, -79, -626, 34, -269, 164, 157, 223, +463, 182, 545, 44, 466, -121, 311, -268, +151, -339, 34, -307, 26, -141, 110, 107, +172, 356, 113, 494, -38, 498, -271, 345, +-568, 53, -793, -311, -784, -590, -536, -699, +-86, -596, 477, -303, 978, 134, 1215, 549, +1113, 799, 685, 789, 56, 530, -596, 79, +-1081, -396, -1259, -734, -1055, -823, -571, -656, +26, -265, 592, 202, 965, 560, 982, 675, +683, 559, 223, 282, -249, -57, -606, -338, +-699, -428, -507, -322, -157, -108, 177, 95, +409, 225, 479, 234, 334, 115, 7, -74, +-305, -216, -475, -236, -502, -143, -356, 5, +-20, 168, 319, 282, 480, 263, 456, 104, +313, -99, 68, -259, -172, -336, -282, -284, +-234, -84, -114, 187, 3, 412, 57, 512, +15, 448, -145, 218, -339, -119, -436, -449, +-346, -658, -78, -679, 320, -499, 715, -163, +934, 227, 853, 542, 482, 689, -87, 626, +-684, 385, -1129, 56, -1271, -242, -1067, -422, +-564, -438, 87, -302, 716, -68, 1148, 142, +1273, 238, 1060, 196, 591, 60, -9, -122, +-583, -275, -979, -318, -1086, -206, -931, -12, +-576, 199, -112, 360, 326, 422, 585, 341, +652, 171, 571, -29, 366, -194, 85, -298, +-131, -292, -235, -215, -255, -110, -208, -15, +-96, 73, 11, 104, 49, 90, 6, 58, +-61, 45, -143, 11, -240, -27, -309, -42, +-267, -13, -124, 3, 73, 24, 302, 81, +529, 164, 629, 189, 547, 154, 311, 76, +-21, -35, -390, -198, -683, -347, -818, -420, +-752, -373, -517, -234, -184, -17, 159, 226, +449, 434, 610, 528, 636, 492, 558, 335, +394, 109, 161, -120, -67, -273, -266, -345, +-435, -336, -543, -250, -553, -137, -486, -81, +-353, -70, -173, -50, 54, -13, 281, 26, +457, 105, 544, 230, 539, 343, 406, 381, +165, 338, -100, 232, -327, 85, -515, -81, +-590, -236, -508, -352, -323, -422, -98, -446, +168, -423, 392, -334, 463, -164, 362, 77, +181, 344, -23, 569, -202, 692, -313, 671, +-294, 490, -187, 183, -79, -157, 11, -432, +116, -589, 163, -621, 117, -538, 39, -363, +-14, -141, -78, 69, -139, 260, -154, 428, +-103, 536, -36, 523, 18, 379, 57, 133, +98, -142, 76, -390, -34, -513, -165, -444, +-237, -196, -248, 94, -175, 316, -1, 378, +235, 252, 406, -21, 432, -289, 311, -428, +80, -358, -226, -110, -496, 231, -610, 505, +-539, 601, -368, 474, -118, 184, 165, -182, +365, -474, 427, -607, 416, -554, 335, -379, +179, -131, -2, 119, -143, 328, -260, 444, +-344, 483, -377, 444, -343, 339, -248, 153, +-101, -75, 59, -308, 193, -473, 235, -539, +183, -469, 75, -283, -18, -25, -51, 207, +-1, 363, 80, 400, 144, 340, 137, 206, +41, 54, -145, -67, -340, -117, -473, -117, +-491, -91, -362, -54, -89, -16, 208, -14, +419, -52, 483, -92, 399, -101, 183, -79, +-71, -25, -252, 63, -299, 174, -240, 247, +-122, 231, -11, 133, 51, -17, 28, -187, +-69, -318, -198, -342, -295, -237, -311, -44, +-203, 176, 11, 357, 289, 434, 522, 390, +594, 248, 451, 44, 143, -163, -252, -314, +-606, -397, -795, -434, -739, -417, -476, -321, +-80, -158, 340, 49, 658, 299, 746, 555, +590, 723, 249, 715, -157, 525, -507, 181, +-677, -237, -640, -616, -446, -809, -171, -759, +118, -494, 340, -122, 458, 232, 456, 438, +337, 443, 128, 278, -105, 57, -329, -121, +-482, -160, -497, -43, -363, 174, -150, 354, +96, 408, 309, 292, 409, 43, 339, -272, +136, -505, -122, -559, -341, -409, -464, -151, +-438, 129, -256, 320, 15, 342, 244, 167, +385, -80, 419, -273, 332, -307, 154, -164, +-44, 138, -235, 472, -376, 704, -451, 707, +-471, 464, -444, 32, -336, -429, -164, -782, +52, -907, 304, -775, 544, -431, 671, -24, +649, 317, 453, 499, 110, 518, -283, 399, +-607, 234, -795, 106, -777, 78, -573, 129, +-285, 192, -10, 177, 207, 62, 314, -149, +319, -406, 271, -614, 242, -652, 259, -483, +296, -155, 269, 230, 165, 562, -36, 716, +-343, 628, -670, 329, -849, -62, -824, -410, +-606, -585, -217, -522, 270, -247, 683, 136, +905, 491, 878, 693, 625, 667, 223, 403, +-216, -9, -596, -436, -810, -761, -818, -897, +-652, -789, -373, -467, -33, -40, 274, 374, +469, 695, 502, 853, 403, 806, 238, 583, +63, 293, -102, 14, -205, -218, -225, -381, +-198, -444, -178, -440, -169, -428, -173, -427, +-196, -395, -237, -310, -224, -153, -107, 82, +81, 383, 243, 668, 354, 851, 409, 844, +363, 629, 173, 234, -71, -226, -284, -634, +-445, -864, -549, -840, -524, -553, -339, -141, +-69, 257, 160, 517, 323, 559, 408, 344, +356, -8, 153, -333, -86, -496, -265, -449, +-364, -174, -372, 227, -231, 605, 12, 808, +227, 789, 311, 536, 269, 132, 111, -299, +-125, -629, -342, -810, -428, -813, -389, -668, +-257, -410, -70, -118, 129, 172, 265, 420, +315, 607, 279, 687, 176, 655, 22, 521, +-146, 322, -295, 68, -381, -182, -397, -368, +-336, -459, -188, -480, 19, -437, 208, -338, +342, -198, 384, -56, 323, 80, 159, 206, +-46, 308, -230, 352, -340, 335, -373, 267, +-344, 169, -288, 52, -234, -56, -214, -136, +-179, -178, -75, -196, 106, -192, 331, -167, +560, -103, 694, -1, 649, 113, 399, 207, +1, 269, -461, 259, -859, 152, -1080, -19, +-1042, -180, -757, -286, -305, -318, 182, -267, +592, -144, 823, 0, 833, 113, 645, 187, +354, 246, 65, 306, -157, 364, -322, 391, +-402, 356, -399, 219, -375, -34, -398, -364, +-418, -664, -394, -830, -321, -791, -177, -546, +87, -138, 415, 312, 690, 679, 790, 872, +676, 872, 362, 692, -91, 406, -576, 82, +-913, -219, -981, -481, -770, -667, -361, -748, +143, -696, 575, -509, 772, -178, 671, 232, +363, 613, -17, 835, -340, 842, -538, 619, +-550, 221, -404, -244, -209, -600, -62, -743, +45, -647, 113, -367, 145, 17, 170, 358, +217, 553, 251, 548, 244, 375, 159, 103, +-15, -153, -244, -321, -455, -351, -592, -254, +-593, -63, -449, 125, -202, 238, 67, 236, +295, 138, 435, -26, 485, -187, 431, -277, +297, -239, 123, -97, -58, 103, -255, 285, +-415, 404, -483, 408, -468, 286, -400, 71, +-262, -159, -93, -344, 56, -438, 162, -419, +238, -285, 274, -83, 279, 138, 243, 318, +164, 405, 61, 376, -50, 255, -183, 79, +-297, -97, -363, -210, -372, -223, -332, -164, +-245, -74, -145, 8, -55, 48, 28, 32, +121, -1, 208, 0, 289, 70, 348, 183, +363, 283, 294, 300, 122, 190, -133, -56, +-404, -368, -631, -621, -738, -684, -682, -496, +-459, -90, -135, 401, 203, 823, 473, 1022, +620, 907, 604, 507, 455, -26, 225, -527, +-17, -854, -224, -924, -356, -725, -421, -371, +-434, -2, -412, 284, -371, 448, -319, 462, +-221, 376, -64, 269, 139, 211, 351, 191, +531, 189, 616, 166, 560, 92, 344, -72, +5, -288, -385, -490, -723, -599, -912, -578, +-869, -403, -608, -105, -203, 249, 238, 546, +601, 713, 765, 701, 712, 522, 486, 222, +151, -91, -211, -336, -484, -457, -597, -445, +-535, -307, -363, -114, -150, 64, 34, 173, +140, 204, 124, 141, 37, 20, -34, -108, +-55, -178, -60, -166, -25, -57, 60, 110, +158, 300, 209, 442, 197, 472, 131, 351, +19, 125, -145, -140, -335, -366, -485, -485, +-539, -451, -524, -300, -425, -108, -204, 37, +110, 92, 427, 51, 669, -20, 764, -37, +663, 71, 371, 309, -30, 605, -427, 818, +-706, 817, -816, 544, -747, 43, -519, -565, +-202, -1088, 90, -1342, 290, -1221, 367, -767, +340, -135, 258, 488, 176, 953, 109, 1152, +69, 1067, 35, 788, -14, 445, -94, 113, +-193, -165, -312, -380, -423, -539, -486, -670, +-462, -749, -339, -721, -116, -539, 163, -212, +447, 230, 665, 686, 743, 1014, 627, 1084, +325, 873, -120, 416, -602, -184, -988, -757, +-1148, -1104, -1021, -1125, -619, -812, -41, -245, +561, 432, 1006, 996, 1168, 1267, 998, 1163, +558, 726, -19, 66, -557, -616, -911, -1104, +-998, -1238, -833, -1003, -497, -478, -117, 161, +192, 714, 352, 1005, 353, 975, 244, 656, +117, 186, 38, -274, 41, -565, 113, -620, +197, -442, 214, -134, 124, 191, -84, 416, +-350, 478, -569, 357, -657, 130, -596, -123, +-384, -321, -77, -412, 232, -364, 446, -211, +523, -7, 454, 176, 284, 292, 78, 305, +-89, 229, -189, 106, -228, 11, -251, -16, +-279, 35, -318, 129, -342, 218, -325, 226, +-226, 111, -44, -120, 175, -379, 362, -570, +466, -598, 443, -416, 290, -48, 51, 379, +-203, 718, -414, 837, -526, 690, -513, 311, +-404, -169, -253, -574, -83, -755, 80, -658, +213, -314, 314, 142, 395, 545, 409, 752, +317, 703, 128, 418, -117, 0, -374, -396, +-560, -637, -626, -676, -555, -525, -364, -236, +-97, 99, 162, 359, 353, 495, 435, 515, +400, 441, 270, 302, 105, 152, -52, 21, +-173, -90, -261, -191, -303, -269, -296, -316, +-245, -317, -174, -269, -92, -155, -17, 10, +30, 186, 31, 320, 12, 387, -3, 372, +1, 286, 26, 148, 87, 3, 154, -123, +168, -206, 82, -242, -74, -228, -255, -176, +-399, -81, -457, 35, -387, 147, -207, 218, +29, 248, 240, 212, 368, 114, 379, -8, +281, -95, 97, -129, -99, -94, -246, -12, +-323, 74, -345, 109, -302, 80, -225, -10, +-150, -112, -75, -174, 17, -137, 92, -7, +152, 175, 188, 337, 184, 418, 142, 357, +85, 168, 9, -96, -67, -341, -136, -493, +-217, -499, -318, -359, -387, -98, -386, 199, +-306, 455, -155, 607, 62, 614, 284, 457, +429, 193, 436, -120, 318, -404, 103, -578, +-151, -579, -362, -426, -447, -166, -393, 130, +-241, 377, -77, 497, 54, 478, 113, 350, +91, 184, 5, 32, -72, -57, -89, -86, +-54, -85, -2, -98, 55, -144, 80, -222, +35, -298, -75, -329, -186, -262, -254, -87, +-250, 166, -174, 430, -27, 638, 139, 713, +256, 621, 265, 373, 174, 29, 12, -334, +-189, -617, -370, -741, -444, -677, -392, -444, +-244, -99, -44, 245, 168, 476, 302, 547, +307, 470, 203, 278, 45, 63, -133, -82, +-271, -101, -311, -26, -246, 90, -129, 170, +5, 149, 126, 21, 192, -153, 165, -307, +73, -362, -44, -278, -161, -75, -277, 157, +-352, 328, -351, 363, -283, 262, -182, 69, +-45, -127, 120, -242, 280, -214, 388, -58, +427, 163, 367, 355, 201, 448, -42, 391, +-298, 206, -504, -45, -604, -272, -584, -413, +-455, -430, -253, -347, -29, -201, 150, -45, +255, 88, 296, 168, 301, 217, 280, 264, +257, 330, 227, 388, 166, 413, 32, 359, +-173, 203, -411, -64, -633, -375, -777, -639, +-757, -751, -541, -652, -165, -333, 276, 131, +678, 605, 926, 931, 927, 1010, 658, 782, +200, 302, -316, -279, -765, -771, -1042, -1033, +-1041, -979, -760, -620, -315, -64, 144, 501, +520, 913, 716, 1059, 679, 908, 455, 518, +160, 32, -119, -405, -312, -666, -378, -703, +-326, -540, -233, -259, -170, 39, -172, 255, +-228, 341, -299, 304, -311, 185, -226, 41, +-44, -58, 196, -75, 441, -10, 614, 105, +638, 235, 468, 325, 154, 328, -224, 224, +-585, 35, -842, -198, -905, -403, -765, -515, +-484, -485, -126, -305, 255, -15, 555, 281, +688, 488, 643, 549, 464, 455, 196, 240, +-90, 6, -318, -149, -432, -175, -435, -91, +-360, 48, -258, 139, -163, 105, -119, -60, +-143, -284, -186, -467, -177, -497, -95, -319, +64, 41, 285, 465, 495, 805, 588, 934, +516, 800, 281, 429, -92, -66, -522, -537, +-858, -842, -1000, -912, -911, -741, -599, -396, +-118, 15, 400, 379, 804, 632, 979, 724, +889, 660, 560, 477, 82, 239, -419, -10, +-801, -215, -964, -336, -880, -358, -592, -306, +-189, -197, 201, -66, 469, 48, 554, 119, +472, 154, 270, 149, 32, 125, -159, 93, +-256, 67, -269, 42, -220, 21, -153, 0, +-112, -10, -115, -9, -138, 11, -168, 51, +-180, 110, -136, 159, -38, 178, 69, 157, +171, 104, 243, 20, 249, -73, 179, -163, +63, -231, -91, -264, -266, -244, -412, -185, +-482, -84, -461, 66, -340, 246, -140, 398, +92, 486, 291, 496, 402, 416, 400, 238, +294, 21, 103, -177, -119, -318, -298, -381, +-378, -363, -368, -296, -292, -210, -183, -129, +-91, -58, -58, 11, -56, 110, -29, 252, +29, 414, 88, 540, 145, 577, 182, 493, +158, 286, 55, -19, -92, -334, -236, -547, +-327, -602, -329, -513, -231, -309, -75, -55, +70, 170, 140, 310, 119, 372, 23, 376, +-108, 347, -228, 296, -287, 220, -260, 86, +-146, -97, 23, -288, 179, -423, 260, -436, +261, -283, 196, 6, 73, 344, -96, 599, +-255, 659, -364, 481, -422, 131, -415, -270, +-313, -572, -154, -662, -1, -507, 116, -191, +203, 161, 238, 418, 220, 506, 165, 429, +88, 274, 0, 117, -81, 28, -155, 23, +-212, 60, -253, 55, -278, -19, -281, -160, +-254, -319, -209, -424, -141, -405, -51, -255, +50, 1, 143, 284, 238, 517, 321, 630, +336, 616, 248, 481, 80, 260, -156, -7, +-436, -268, -663, -493, -723, -636, -589, -664, +-295, -548, 92, -289, 461, 83, 661, 477, +628, 793, 384, 935, 6, 864, -388, 578, +-640, 157, -659, -290, -462, -635, -153, -793, +156, -750, 357, -565, 373, -292, 206, 6, +-36, 254, -235, 415, -338, 520, -331, 581, +-206, 589, -33, 526, 79, 389, 84, 174, +33, -100, -37, -395, -101, -631, -113, -739, +-37, -677, 71, -460, 125, -123, 84, 256, +-30, 570, -195, 736, -357, 730, -444, 551, +-397, 253, -234, -70, -13, -316, 207, -433, +374, -400, 417, -229, 322, 14, 133, 230, +-81, 342, -281, 301, -419, 122, -465, -132, +-421, -362, -317, -478, -154, -397, 42, -124, +210, 253, 301, 601, 308, 804, 227, 766, +62, 473, -148, 12, -325, -463, -424, -800, +-416, -864, -289, -632, -61, -188, 188, 313, +357, 706, 374, 858, 239, 730, -4, 371, +-287, -75, -528, -443, -617, -601, -512, -531, +-251, -278, 81, 52, 385, 331, 541, 441, +484, 377, 248, 189, -64, -26, -354, -181, +-531, -204, -544, -107, -388, 57, -121, 203, +153, 261, 318, 189, 324, 33, 188, -142, +-39, -264, -271, -278, -408, -159, -408, 49, +-285, 266, -76, 402, 160, 418, 325, 310, +359, 114, 257, -116, 45, -298, -221, -387, +-441, -367, -539, -257, -486, -79, -298, 113, +-21, 283, 259, 399, 444, 445, 454, 403, +296, 290, 37, 133, -240, -41, -462, -204, +-551, -305, -483, -327, -303, -283, -77, -200, +141, -87, 284, 23, 308, 104, 235, 160, +118, 204, -15, 237, -136, 263, -210, 270, +-236, 247, -253, 181, -251, 73, -203, -60, +-126, -181, -60, -258, 10, -263, 80, -195, +116, -71, 93, 61, 49, 158, 5, 190, +-46, 156, -105, 66, -135, -34, -134, -99, +-136, -97, -150, -15, -136, 125, -88, 260, +-48, 340, -35, 340, -9, 241, 10, 52, +-16, -151, -60, -303, -67, -361, -52, -312, +-42, -169, -14, 11, 29, 168, 26, 253, +-39, 250, -134, 175, -217, 82, -270, 8, +-255, -20, -141, -6, 30, 44, 162, 90, +211, 102, 180, 64, 73, 0, -92, -53, +-235, -60, -286, -21, -241, 55, -143, 141, +-18, 191, 78, 156, 78, 38, -19, -138, +-137, -299, -221, -381, -241, -331, -172, -146, +-17, 142, 147, 441, 253, 647, 271, 678, +189, 532, 5, 250, -220, -86, -403, -375, +-490, -528, -461, -527, -312, -402, -94, -221, +138, -50, 325, 64, 418, 133, 382, 184, +214, 247, -43, 332, -302, 427, -491, 478, +-550, 429, -457, 251, -222, -21, 63, -314, +296, -541, 413, -636, 386, -558, 198, -328, +-87, -18, -351, 278, -478, 492, -442, 571, +-271, 515, -33, 361, 172, 157, 253, -53, +190, -207, 22, -279, -175, -272, -315, -204, +-318, -88, -179, 37, 36, 131, 228, 169, +317, 157, 259, 115, 72, 74, -180, 51, +-388, 55, -479, 72, -436, 80, -282, 49, +-62, -25, 128, -120, 217, -189, 199, -199, +122, -130, 23, 3, -50, 169, -59, 315, +-20, 389, 17, 370, 23, 280, -29, 144, +-131, -20, -261, -184, -365, -312, -396, -404, +-323, -444, -159, -404, 43, -256, 216, -13, +326, 292, 346, 588, 273, 789, 128, 806, +-37, 617, -184, 254, -285, -188, -329, -587, +-319, -820, -273, -830, -195, -620, -111, -263, +-34, 143, 34, 481, 90, 674, 113, 687, +107, 550, 91, 312, 72, 53, 43, -162, +8, -288, -51, -332, -126, -300, -197, -215, +-264, -108, -316, -14, -308, 71, -220, 137, +-68, 178, 100, 198, 248, 210, 327, 197, +292, 157, 138, 90, -74, 3, -273, -97, +-401, -171, -426, -199, -325, -164, -139, -74, +54, 51, 194, 169, 246, 252, 192, 256, +60, 174, -94, 44, -199, -86, -227, -185, +-186, -205, -96, -126, 4, 23, 52, 174, +31, 276, -34, 285, -121, 187, -221, 11, +-266, -174, -204, -298, -61, -294, 100, -152, +247, 74, 334, 297, 310, 448, 159, 456, +-59, 295, -288, 15, -484, -271, -600, -470, +-576, -508, -392, -371, -116, -102, 171, 211, +422, 468, 571, 578, 559, 514, 385, 308, +116, 36, -192, -221, -470, -386, -623, -417, +-601, -311, -442, -112, -194, 112, 71, 288, +275, 376, 351, 348, 287, 210, 135, 2, +-46, -206, -209, -346, -286, -362, -252, -244, +-131, -23, 9, 230, 123, 445, 180, 533, +160, 447, 51, 215, -99, -71, -228, -331, +-301, -471, -316, -436, -256, -234, -136, 40, +-13, 281, 79, 399, 148, 358, 183, 181, +162, -49, 87, -239, -1, -297, -84, -200, +-155, 4, -203, 222, -209, 365, -182, 363, +-135, 220, -75, -4, 8, -212, 75, -320, +88, -266, 55, -79, 8, 153, -48, 333, +-109, 383, -155, 260, -159, 2, -140, -292, +-102, -501, -50, -541, 4, -366, 35, -28, +57, 362, 82, 682, 100, 837, 82, 755, +34, 449, -44, 13, -149, -417, -264, -729, +-343, -839, -351, -717, -277, -399, -154, 1, +7, 362, 184, 593, 323, 653, 362, 545, +312, 330, 199, 97, 36, -79, -156, -172, +-312, -177, -409, -138, -449, -116, -425, -143, +-322, -193, -149, -226, 52, -202, 237, -90, +379, 114, 430, 353, 357, 537, 173, 587, +-58, 472, -281, 201, -443, -146, -489, -458, +-398, -632, -218, -611, -9, -398, 163, -62, +262, 289, 253, 539, 157, 620, 30, 514, +-81, 267, -167, -40, -205, -298, -188, -423, +-139, -392, -96, -234, -55, -7, -12, 206, +21, 329, 37, 330, 46, 229, 44, 64, +26, -96, -11, -195, -58, -207, -104, -136, +-141, -6, -162, 127, -155, 213, -125, 226, +-80, 169, -35, 56, 12, -71, 52, -181, +81, -234, 97, -208, 91, -103, 49, 46, +-15, 206, -79, 340, -131, 408, -171, 366, +-186, 222, -178, 6, -164, -226, -145, -417, +-113, -504, -56, -466, 24, -297, 117, -30, +213, 265, 279, 502, 264, 620, 154, 584, +-33, 401, -260, 115, -454, -191, -532, -427, +-446, -519, -229, -449, 45, -250, 299, 9, +449, 245, 421, 368, 219, 342, -68, 196, +-324, 0, -472, -169, -450, -240, -251, -185, +23, -23, 246, 177, 358, 335, 331, 380, +171, 293, -73, 109, -292, -109, -400, -294, +-371, -384, -234, -353, -42, -223, 128, -47, +196, 121, 140, 240, 28, 290, -83, 272, +-159, 207, -167, 126, -80, 50, 71, -19, +194, -75, 227, -107, 162, -116, 0, -102, +-214, -61, -392, -2, -456, 54, -392, 96, +-218, 113, 29, 82, 271, 22, 397, -36, +373, -66, 222, -64, -4, -33, -230, 16, +-379, 68, -392, 94, -265, 88, -61, 66, +148, 54, 295, 63, 328, 89, 224, 121, +19, 127, -212, 72, -408, -44, -513, -188, +-471, -314, -291, -366, -29, -297, 235, -113, +437, 134, 522, 369, 460, 521, 263, 527, +-3, 376, -270, 118, -473, -151, -563, -356, +-508, -432, -340, -362, -115, -179, 118, 46, +305, 238, 389, 329, 358, 299, 230, 166, +53, -16, -140, -189, -297, -295, -363, -298, +-333, -188, -224, -4, -50, 196, 133, 350, +250, 421, 247, 386, 147, 246, -1, 38, +-155, -170, -254, -324, -245, -388, -144, -356, +-1, -237, 115, -75, 160, 92, 107, 219, +-28, 283, -191, 287, -302, 248, -307, 176, +-205, 89, -19, -2, 202, -81, 358, -135, +389, -162, 304, -160, 130, -123, -99, -55, +-321, 22, -472, 82, -505, 118, -442, 127, +-299, 113, -99, 80, 123, 47, 313, 23, +431, 14, 461, 10, 389, -6, 202, -39, +-35, -76, -254, -95, -400, -86, -453, -39, +-413, 46, -291, 142, -118, 210, 34, 211, +141, 135, 189, 1, 182, -146, 126, -260, +66, -287, 39, -199, 22, -19, -10, 183, +-42, 337, -80, 387, -122, 309, -155, 129, +-158, -77, -128, -232, -85, -282, -39, -218, +5, -81, 22, 49, 18, 110, -7, 81, +-18, -23, -13, -144, -1, -191, 19, -116, +55, 76, 82, 319, 83, 520, 46, 583, +-22, 462, -119, 166, -226, -217, -297, -568, +-301, -774, -226, -770, -84, -548, 92, -180, +264, 225, 361, 567, 346, 766, 217, 764, +10, 577, -211, 275, -368, -60, -399, -363, +-294, -552, -113, -582, 81, -461, 222, -241, +244, 16, 143, 243, -26, 382, -186, 394, +-274, 298, -257, 140, -115, -27, 85, -151, +243, -188, 300, -153, 240, -85, 83, -17, +-127, 35, -304, 57, -365, 51, -310, 51, +-170, 77, 16, 108, 183, 122, 251, 103, +189, 41, 45, -63, -94, -177, -188, -253, +-196, -250, -110, -157, 44, 1, 181, 171, +222, 301, 158, 350, 9, 302, -195, 178, +-362, 21, -410, -120, -312, -209, -115, -234, +117, -213, 319, -166, 413, -98, 352, -19, +170, 55, -67, 121, -268, 177, -377, 210, +-360, 201, -227, 146, -50, 62, 97, -24, +180, -79, 176, -88, 91, -57, -31, -5, +-116, 32, -134, 16, -107, -58, -40, -166, +58, -253, 132, -263, 142, -166, 83, 26, +-10, 269, -122, 485, -223, 584, -264, 518, +-228, 304, -142, 2, -37, -304, 69, -535, +168, -623, 223, -558, 212, -365, 152, -100, +74, 166, -6, 377, -98, 504, -192, 524, +-246, 439, -270, 275, -253, 67, -179, -146, +-58, -318, 78, -409, 198, -402, 276, -298, +286, -132, 202, 40, 49, 180, -119, 256, +-234, 259, -267, 209, -225, 137, -118, 67, +9, 10, 91, -31, 108, -63, 49, -96, +-58, -125, -153, -132, -173, -111, -100, -61, +26, 14, 162, 94, 260, 142, 265, 139, +169, 96, -9, 33, -201, -22, -339, -53, +-381, -43, -313, -7, -155, 30, 29, 43, +176, 23, 241, -21, 222, -67, 142, -91, +32, -71, -44, -13, -57, 56, -22, 118, +22, 152, 33, 134, 4, 73, -80, -2, +-203, -74, -307, -134, -344, -169, -286, -167, +-119, -126, 104, -52, 324, 47, 472, 159, +506, 262, 410, 319, 191, 302, -87, 195, +-348, 14, -522, -188, -563, -347, -481, -414, +-300, -364, -68, -209, 153, -1, 314, 184, +384, 280, 354, 276, 250, 194, 102, 82, +-26, 2, -108, 0, -140, 67, -135, 148, +-117, 179, -91, 119, -85, -34, -119, -232, +-159, -402, -171, -471, -143, -396, -94, -190, +-9, 74, 118, 303, 241, 431, 308, 435, +318, 342, 256, 200, 120, 63, -71, -23, +-255, -53, -369, -62, -413, -95, -376, -168, +-249, -259, -63, -338, 123, -358, 238, -277, +284, -97, 265, 133, 172, 349, 54, 485, +-27, 503, -62, 407, -67, 233, -53, 28, +-32, -164, -58, -296, -154, -351, -251, -344, +-285, -295, -239, -207, -125, -84, 57, 50, +285, 169, 438, 255, 455, 294, 357, 271, +168, 191, -104, 86, -378, -16, -534, -92, +-527, -133, -415, -141, -230, -129, 11, -114, +242, -99, 383, -75, 407, -39, 371, 25, +284, 120, 122, 212, -51, 258, -195, 233, +-306, 130, -395, -35, -421, -214, -339, -348, +-184, -373, -10, -260, 176, -45, 340, 207, +427, 413, 401, 497, 272, 415, 90, 186, +-127, -117, -325, -396, -417, -551, -392, -514, +-272, -303, -101, 5, 93, 306, 245, 505, +294, 527, 238, 370, 128, 107, -1, -159, +-118, -345, -183, -400, -170, -321, -101, -153, +-44, 30, 2, 159, 36, 200, 40, 173, +24, 112, 17, 60, 50, 36, 76, 43, +70, 51, 40, 31, -19, -33, -116, -126, +-219, -211, -265, -234, -209, -177, -74, -50, +90, 116, 243, 270, 321, 342, 291, 298, +161, 153, -20, -44, -184, -234, -300, -352, +-309, -348, -223, -224, -84, -20, 47, 200, +123, 365, 146, 411, 122, 321, 68, 129, +29, -109, 24, -326, 36, -451, 50, -433, +33, -280, -30, -49, -145, 188, -263, 369, +-299, 446, -248, 393, -101, 234, 109, 36, +319, -142, 457, -263, 451, -311, 301, -286, +45, -209, -257, -97, -501, 24, -593, 132, +-508, 215, -277, 265, 22, 260, 311, 183, +500, 37, 510, -133, 362, -269, 117, -327, +-120, -285, -286, -136, -339, 82, -267, 287, +-131, 400, 8, 379, 102, 228, 113, -1, +38, -224, -69, -362, -136, -378, -121, -270, +-46, -90, 71, 89, 203, 204, 267, 239, +232, 199, 94, 109, -80, 10, -239, -50, +-331, -62, -297, -39, -161, -3, 15, 36, +161, 67, 239, 71, 240, 35, 145, -28, +-25, -106, -179, -186, -245, -245, -213, -245, +-101, -163, 42, 6, 192, 224, 263, 426, +227, 529, 106, 480, -57, 275, -201, -43, +-283, -385, -266, -628, -157, -676, -13, -512, +112, -194, 186, 178, 196, 478, 148, 613, +54, 545, -39, 318, -78, 24, -86, -229, +-64, -368, -46, -365, -38, -249, -44, -83, +-75, 66, -89, 152, -58, 155, 25, 97, +128, 26, 209, -21, 234, -42, 162, -33, +-3, 3, -189, 42, -322, 57, -374, 49, +-302, 26, -113, -3, 152, -35, 368, -64, +456, -88, 415, -99, 243, -87, -19, -44, +-288, 28, -457, 110, -479, 173, -378, 190, +-173, 144, 80, 38, 285, -94, 367, -197, +333, -236, 229, -192, 99, -69, -53, 95, +-157, 229, -176, 277, -144, 221, -95, 82, +-54, -97, -12, -249, -15, -317, -67, -273, +-101, -142, -91, 29, -35, 187, 47, 281, +157, 295, 254, 243, 276, 146, 202, 27, +82, -89, -70, -177, -220, -230, -318, -253, +-321, -245, -228, -186, -106, -75, 32, 58, +158, 183, 220, 281, 208, 323, 143, 285, +76, 172, 9, 17, -45, -141, -60, -263, +-37, -316, -28, -290, -36, -188, -51, -36, +-60, 118, -73, 232, -92, 278, -68, 247, +-20, 147, 26, 9, 65, -126, 103, -215, +136, -226, 116, -163, 59, -59, -3, 56, +-64, 146, -129, 177, -160, 141, -134, 60, +-65, -31, 7, -98, 83, -127, 159, -112, +179, -69, 135, -1, 41, 77, -69, 138, +-173, 163, -251, 150, -241, 95, -150, -2, +-6, -129, 152, -240, 283, -290, 327, -256, +265, -143, 119, 29, -51, 215, -218, 338, +-335, 345, -343, 245, -254, 77, -97, -96, +72, -206, 215, -214, 302, -135, 288, -15, +212, 86, 91, 112, -46, 44, -177, -81, +-263, -193, -286, -238, -249, -191, -174, -59, +-49, 116, 120, 268, 274, 344, 365, 326, +362, 231, 279, 102, 101, -29, -137, -135, +-340, -207, -461, -249, -457, -271, -335, -267, +-107, -233, 154, -157, 354, -34, 450, 121, +434, 273, 295, 385, 72, 427, -154, 382, +-308, 243, -347, 43, -291, -165, -150, -339, +15, -444, 126, -452, 175, -361, 151, -193, +80, 11, -23, 206, -96, 343, -95, 395, +-35, 356, 46, 241, 110, 84, 131, -74, +97, -194, 18, -252, -78, -251, -139, -201, +-154, -117, -102, -20, 6, 63, 98, 118, +141, 145, 104, 141, 32, 100, -58, 31, +-135, -39, -156, -86, -119, -96, -38, -62, +62, 2, 146, 71, 183, 118, 164, 121, +103, 69, 41, -24, -21, -125, -79, -182, +-114, -179, -129, -126, -120, -41, -125, 58, +-118, 128, -87, 153, -38, 145, 27, 128, +105, 104, 187, 70, 242, 29, 249, -27, +210, -113, 129, -206, -8, -271, -160, -272, +-275, -185, -331, -15, -312, 186, -233, 352, +-83, 417, 78, 350, 203, 165, 260, -80, +245, -301, 180, -410, 88, -372, 22, -214, +-1, -2, -7, 187, -19, 288, -40, 273, +-83, 158, -145, 9, -202, -108, -207, -154, +-129, -125, -15, -49, 119, 26, 222, 71, +260, 65, 218, 12, 110, -55, -12, -91, +-116, -77, -166, -27, -148, 33, -74, 87, +14, 117, 72, 110, 78, 63, 52, 1, +16, -54, -27, -97, -49, -126, -56, -131, +-36, -107, -21, -52, -12, 25, 5, 112, +23, 188, 47, 228, 62, 206, 67, 112, +57, -35, 25, -182, -18, -273, -57, -282, +-78, -203, -71, -54, -38, 119, 5, 250, +56, 288, 78, 220, 74, 81, 38, -73, +-19, -196, -67, -250, -110, -217, -113, -117, +-71, 6, 6, 116, 97, 188, 175, 217, +225, 202, 212, 149, 125, 63, -16, -38, +-170, -136, -314, -222, -383, -271, -344, -256, +-178, -172, 63, -45, 306, 90, 491, 196, +533, 243, 413, 222, 162, 155, -132, 70, +-381, 5, -533, -12, -536, 6, -379, 25, +-119, 6, 147, -58, 356, -151, 456, -241, +438, -296, 296, -275, 102, -167, -70, -5, +-196, 157, -248, 279, -229, 346, -153, 356, +-84, 315, -53, 238, -28, 131, -2, -5, +24, -172, 56, -351, 116, -502, 185, -564, +220, -496, 190, -286, 118, 26, -3, 361, +-149, 617, -254, 713, -280, 612, -203, 342, +-70, -7, 88, -314, 224, -503, 273, -538, +216, -431, 76, -232, -78, -25, -198, 122, +-247, 198, -207, 219, -81, 200, 74, 173, +212, 151, 287, 129, 275, 91, 180, 27, +25, -65, -125, -176, -237, -275, -284, -328, +-250, -309, -148, -212, -3, -45, 124, 168, +215, 368, 253, 496, 228, 510, 145, 394, +40, 153, -71, -160, -159, -453, -203, -631, +-189, -640, -123, -465, -50, -154, 31, 192, +105, 467, 156, 598, 183, 553, 165, 360, +124, 97, 59, -141, -14, -288, -94, -327, +-165, -279, -212, -181, -207, -85, -152, -28, +-57, -8, 53, 7, 156, 40, 243, 95, +268, 158, 234, 207, 151, 211, 26, 158, +-98, 50, -199, -82, -228, -198, -200, -258, +-131, -241, -36, -161, 68, -47, 138, 76, +151, 171, 122, 206, 85, 177, 44, 105, +-12, 16, -43, -71, -48, -139, -39, -158, +-31, -126, -22, -57, 13, 20, 34, 89, +54, 137, 76, 149, 95, 121, 75, 59, +11, -22, -54, -100, -99, -158, -140, -180, +-161, -164, -122, -106, -37, -12, 59, 91, +141, 175, 208, 225, 247, 231, 224, 180, +166, 77, 75, -50, -41, -164, -185, -239, +-307, -265, -351, -233, -307, -148, -192, -32, +-9, 88, 212, 187, 392, 249, 469, 264, +419, 230, 272, 153, 48, 37, -195, -97, +-368, -212, -440, -285, -393, -303, -267, -249, +-77, -127, 132, 23, 294, 161, 385, 252, +410, 276, 364, 237, 231, 143, 44, 27, +-152, -75, -316, -139, -421, -160, -427, -145, +-315, -113, -121, -82, 108, -56, 300, -35, +417, -12, 411, 23, 289, 80, 109, 150, +-66, 202, -189, 210, -241, 170, -206, 83, +-109, -52, 5, -198, 88, -309, 121, -347, +93, -297, 26, -171, -39, 1, -82, 183, +-74, 334, -36, 412, 35, 391, 101, 280, +141, 106, 140, -102, 94, -304, 25, -447, +-47, -496, -91, -431, -93, -261, -51, -19, +19, 254, 87, 494, 119, 625, 96, 602, +25, 422, -76, 117, -156, -241, -192, -558, +-146, -742, -36, -733, 95, -532, 219, -193, +291, 194, 294, 524, 216, 714, 91, 728, +-46, 568, -166, 288, -251, -32, -277, -312, +-234, -506, -144, -593, -25, -568, 99, -446, +223, -260, 294, -46, 296, 174, 235, 375, +123, 517, -17, 569, -161, 513, -252, 356, +-269, 119, -215, -150, -100, -389, 51, -544, +186, -575, 262, -475, 274, -281, 224, -48, +131, 166, 5, 320, -98, 388, -164, 366, +-188, 275, -177, 157, -137, 44, -67, -44, +1, -109, 61, -147, 107, -157, 136, -155, +158, -149, 174, -133, 188, -103, 186, -57, +147, 3, 61, 63, -49, 114, -182, 152, +-293, 170, -354, 157, -328, 117, -206, 62, +-30, 4, 164, -63, 313, -137, 389, -201, +373, -237, 272, -228, 130, -165, -7, -45, +-85, 115, -98, 279, -69, 397, -48, 421, +-57, 324, -123, 118, -220, -153, -304, -423, +-313, -607, -214, -635, -21, -481, 249, -185, +518, 176, 696, 514, 700, 739, 518, 778, +198, 607, -201, 282, -576, -113, -812, -482, +-823, -731, -615, -789, -242, -646, 190, -347, +570, 20, 776, 354, 759, 565, 548, 601, +206, 472, -151, 235, -417, -25, -509, -220, +-418, -292, -219, -235, 14, -104, 195, 29, +266, 106, 202, 89, 61, -21, -78, -169, +-142, -269, -107, -267, 21, -149, 186, 48, +293, 256, 297, 396, 187, 408, 1, 287, +-210, 72, -363, -163, -383, -328, -276, -371, +-76, -294, 143, -135, 330, 43, 423, 176, +399, 220, 270, 177, 98, 85, -77, -14, +-210, -82, -270, -103, -261, -79, -202, -33, +-133, 1, -50, 3, 47, -18, 137, -37, +219, -25, 277, 28, 301, 114, 264, 187, +171, 206, 33, 139, -127, -19, -277, -223, +-358, -393, -342, -456, -231, -366, -50, -130, +158, 196, 345, 502, 442, 673, 413, 634, +267, 389, 44, 7, -183, -398, -355, -697, +-409, -787, -332, -642, -146, -313, 89, 90, +309, 450, 441, 663, 438, 683, 308, 520, +94, 238, -134, -76, -321, -334, -402, -477, +-353, -491, -200, -396, 5, -223, 192, -23, +324, 157, 353, 280, 291, 329, 172, 302, +40, 216, -78, 86, -148, -58, -153, -186, +-108, -266, -51, -283, -5, -233, 30, -132, +38, 2, 30, 139, 26, 245, 38, 292, +67, 266, 90, 175, 114, 36, 118, -121, +93, -250, 32, -318, -31, -313, -72, -242, +-93, -116, -91, 32, -55, 167, 3, 264, +52, 307, 90, 289, 115, 224, 121, 122, +101, -4, 59, -138, 26, -263, -2, -351, +-23, -374, -44, -321, -48, -189, -39, 7, +-32, 222, -17, 386, 13, 449, 49, 396, +82, 235, 118, 4, 146, -219, 151, -355, +122, -374, 66, -281, -9, -112, -101, 59, +-166, 172, -199, 194, -168, 127, -77, 5, +51, -103, 179, -150, 266, -113, 290, -7, +240, 126, 125, 236, -26, 278, -163, 222, +-238, 77, -232, -112, -147, -281, -5, -384, +154, -383, 269, -271, 313, -77, 253, 132, +112, 294, -72, 363, -240, 325, -330, 195, +-310, 25, -176, -128, 37, -211, 265, -202, +432, -119, 481, -14, 392, 64, 181, 78, +-86, 25, -320, -68, -442, -148, -431, -169, +-285, -104, -57, 23, 186, 165, 354, 267, +393, 286, 326, 197, 197, 30, 50, -150, +-80, -284, -150, -328, -149, -266, -105, -123, +-48, 49, 5, 193, 45, 274, 57, 275, +55, 200, 52, 76, 62, -58, 66, -169, +62, -243, 52, -268, 30, -235, 3, -154, +-21, -45, -22, 76, 5, 193, 50, 282, +99, 319, 124, 293, 106, 203, 50, 54, +-20, -126, -98, -295, -155, -412, -167, -448, +-101, -378, 19, -210, 154, 17, 268, 246, +322, 424, 293, 499, 175, 439, 6, 260, +-159, 21, -273, -206, -296, -357, -227, -391, +-83, -307, 80, -147, 211, 21, 271, 133, +260, 164, 181, 113, 68, 19, -43, -67, +-110, -98, -108, -62, -56, 26, 22, 126, +93, 190, 138, 181, 138, 108, 82, -2, +-6, -114, -98, -195, -156, -213, -166, -171, +-114, -95, -9, -21, 130, 39, 257, 72, +332, 83, 321, 83, 218, 85, 45, 86, +-153, 74, -298, 37, -341, -16, -275, -79, +-114, -131, 97, -148, 298, -109, 405, -26, +384, 73, 247, 150, 48, 170, -159, 111, +-307, -1, -349, -125, -267, -214, -94, -232, +110, -161, 295, -25, 403, 125, 394, 234, +278, 263, 100, 197, -81, 67, -229, -82, +-299, -195, -275, -239, -174, -202, -45, -104, +84, 12, 186, 98, 248, 132, 252, 119, +219, 76, 166, 17, 88, -29, -2, -51, +-87, -56, -148, -61, -183, -60, -182, -49, +-115, -23, 2, 17, 134, 68, 242, 108, +300, 118, 268, 80, 146, -4, -14, -110, +-151, -189, -230, -199, -229, -128, -131, -2, +29, 135, 181, 227, 259, 229, 248, 132, +162, -31, 27, -191, -95, -277, -153, -254, +-117, -121, -19, 72, 100, 244, 200, 315, +233, 257, 173, 87, 44, -129, -100, -306, +-208, -373, -237, -304, -184, -120, -60, 107, +100, 291, 239, 367, 319, 316, 310, 158, +228, -39, 99, -211, -26, -304, -119, -289, +-168, -177, -159, -25, -99, 115, -29, 197, +30, 203, 67, 132, 84, 14, 88, -110, +85, -193, 83, -211, 83, -156, 72, -49, +53, 80, 25, 191, 8, 251, 4, 235, +20, 153, 53, 32, 97, -93, 123, -192, +104, -239, 28, -230, -79, -175, -175, -110, +-222, -47, -199, 10, -94, 63, 86, 113, +284, 167, 413, 217, 436, 240, 334, 209, +137, 116, -105, -28, -305, -185, -397, -307, +-354, -345, -197, -287, 29, -151, 250, 18, +388, 169, 397, 242, 293, 216, 121, 120, +-68, 13, -219, -67, -288, -89, -264, -50, +-153, 20, -8, 72, 135, 68, 243, 5, +301, -83, 308, -157, 268, -177, 190, -126, +85, -15, -35, 112, -152, 200, -243, 211, +-294, 143, -295, 17, -228, -123, -96, -225, +75, -254, 243, -199, 381, -78, 457, 59, +462, 168, 381, 221, 224, 207, 16, 130, +-205, 15, -388, -100, -484, -177, -474, -191, +-354, -134, -140, -32, 130, 80, 385, 160, +553, 172, 586, 102, 487, -30, 275, -177, +13, -272, -230, -276, -376, -180, -397, -5, +-309, 197, -147, 343, 36, 375, 176, 283, +245, 100, 249, -113, 212, -277, 150, -340, +91, -287, 46, -150, 18, 11, -9, 125, +-38, 156, -76, 102, -108, 6, -122, -75, +-97, -96, -29, -42, 71, 68, 182, 183, +270, 250, 299, 224, 249, 103, 128, -84, +-29, -277, -178, -415, -266, -440, -259, -335, +-157, -122, 4, 137, 183, 372, 317, 509, +352, 509, 266, 369, 96, 121, -86, -166, +-219, -407, -257, -534, -186, -508, -36, -349, +133, -106, 258, 141, 305, 325, 260, 394, +146, 343, 19, 206, -69, 42, -112, -103, +-109, -183, -88, -190, -63, -144, -48, -86, +-39, -35, -13, -7, 43, 4, 125, 9, +218, 27, 291, 55, 308, 81, 239, 86, +103, 58, -60, -5, -206, -86, -296, -153, +-293, -176, -197, -147, -41, -62, 115, 56, +241, 167, 308, 234, 291, 242, 204, 186, +85, 80, -26, -56, -107, -187, -145, -278, +-124, -308, -57, -281, 34, -198, 113, -74, +162, 69, 171, 207, 144, 310, 96, 349, +45, 313, -3, 207, -35, 52, -54, -122, +-75, -277, -99, -372, -114, -382, -95, -312, +-29, -179, 72, -10, 204, 161, 326, 287, +392, 344, 366, 323, 250, 241, 64, 118, +-149, -25, -325, -159, -398, -256, -354, -300, +-221, -288, -47, -232, 122, -142, 243, -26, +288, 95, 266, 192, 217, 252, 168, 270, +138, 250, 116, 183, 96, 77, 63, -50, +7, -172, -72, -266, -158, -312, -227, -301, +-248, -227, -210, -105, -115, 40, 23, 166, +170, 250, 287, 272, 344, 230, 334, 141, +268, 33, 159, -58, 44, -109, -51, -124, +-104, -112, -116, -89, -103, -74, -88, -83, +-82, -106, -77, -120, -61, -95, -32, -20, +19, 91, 102, 200, 195, 271, 257, 263, +260, 160, 197, -9, 89, -182, -36, -299, +-120, -310, -132, -204, -76, -12, 9, 189, +88, 313, 128, 302, 101, 155, 6, -81, +-98, -313, -150, -445, -121, -419, -15, -234, +127, 61, 250, 361, 306, 554, 264, 567, +141, 399, -26, 103, -167, -226, -227, -485, +-178, -590, -47, -519, 112, -304, 239, -30, +286, 220, 225, 381, 78, 418, -94, 327, +-226, 158, -267, -28, -193, -176, -28, -246, +163, -230, 311, -158, 377, -54, 329, 45, +182, 105, -14, 114, -189, 90, -275, 48, +-250, 4, -123, -28, 54, -43, 207, -46, +279, -43, 246, -49, 135, -67, -9, -85, +-133, -79, -187, -42, -146, 22, -40, 94, +87, 155, 178, 181, 210, 155, 185, 71, +124, -36, 59, -125, 11, -173, -4, -169, +9, -115, 14, -38, -11, 25, -70, 43, +-135, 18, -173, -36, -152, -83, -56, -90, +112, -37, 296, 64, 437, 189, 474, 286, +389, 311, 187, 230, -89, 53, -347, -176, +-508, -387, -525, -518, -390, -518, -129, -369, +191, -98, 472, 219, 624, 490, 599, 632, +415, 598, 128, 389, -175, 65, -403, -277, +-484, -530, -400, -622, -182, -525, 79, -280, +292, 23, 402, 280, 380, 412, 239, 385, +41, 234, -134, 33, -216, -129, -196, -196, +-93, -147, 51, -17, 182, 124, 234, 197, +197, 154, 104, -2, 5, -208, -80, -379, +-123, -434, -107, -337, -50, -104, 22, 193, +84, 450, 121, 571, 137, 505, 135, 274, +127, -46, 113, -354, 87, -546, 44, -556, +-5, -383, -65, -100, -122, 192, -154, 392, +-140, 445, -84, 340, 4, 127, 119, -108, +232, -275, 310, -324, 322, -252, 269, -105, +165, 53, 16, 158, -151, 179, -289, 118, +-349, 13, -319, -76, -208, -106, -32, -73, +178, 5, 357, 92, 454, 145, 440, 132, +322, 51, 132, -69, -79, -177, -248, -241, +-320, -239, -290, -169, -178, -42, -28, 103, +122, 219, 223, 273, 244, 258, 187, 178, +92, 52, -2, -89, -67, -200, -91, -253, +-60, -235, 9, -161, 87, -55, 150, 50, +179, 133, 164, 166, 115, 143, 47, 80, +-20, 13, -87, -38, -139, -60, -163, -58, +-150, -41, -107, -30, -38, -32, 54, -57, +173, -93, 290, -111, 373, -88, 396, -23, +332, 76, 177, 172, -32, 232, -247, 226, +-419, 140, -495, -6, -430, -158, -236, -271, +33, -309, 296, -254, 481, -119, 541, 49, +466, 189, 283, 252, 63, 227, -133, 125, +-254, -12, -279, -131, -222, -189, -125, -170, +-37, -83, 19, 30, 56, 120, 74, 154, +99, 129, 138, 55, 195, -38, 244, -118, +249, -149, 182, -124, 50, -64, -114, -2, +-256, 44, -332, 59, -307, 41, -184, 1, +12, -36, 224, -52, 392, -34, 464, 2, +422, 50, 262, 93, 32, 116, -196, 104, +-362, 58, -425, -13, -365, -83, -191, -136, +52, -161, 288, -153, 447, -108, 485, -40, +388, 31, 180, 77, -81, 95, -316, 85, +-443, 54, -418, 19, -242, -2, 27, -2, +308, 24, 513, 59, 577, 81, 469, 71, +216, 27, -104, -49, -391, -141, -565, -228, +-572, -270, -406, -243, -117, -145, 200, 2, +459, 171, 602, 311, 600, 377, 447, 340, +207, 207, -39, 14, -228, -176, -337, -313, +-360, -356, -307, -296, -209, -153, -103, 8, +-3, 132, 87, 180, 167, 151, 238, 71, +296, -13, 322, -65, 303, -60, 224, -3, +92, 68, -66, 105, -200, 92, -278, 36, +-272, -36, -197, -94, -77, -114, 51, -99, +143, -61, 166, -36, 139, -43, 100, -80, +76, -108, 77, -96, 111, -16, 151, 124, +159, 279, 107, 378, 3, 363, -128, 209, +-232, -46, -267, -318, -206, -509, -57, -548, +131, -419, 296, -159, 378, 143, 341, 375, +201, 462, 1, 394, -190, 217, -306, 3, +-309, -160, -205, -223, -35, -184, 140, -88, +270, 8, 320, 50, 279, 28, 159, -39, +17, -109, -91, -139, -146, -102, -139, -7, +-80, 116, -1, 209, 62, 228, 81, 161, +61, 36, 17, -110, -27, -226, -48, -270, +-26, -218, 27, -93, 90, 60, 137, 187, +158, 256, 143, 238, 98, 148, 39, 16, +-15, -116, -42, -209, -45, -230, -40, -185, +-36, -99, -48, -1, -70, 78, -86, 114, +-78, 105, -37, 63, 43, 20, 145, -7, +242, -7, 301, 19, 299, 53, 227, 72, +96, 57, -56, -2, -191, -87, -283, -163, +-309, -198, -265, -176, -156, -97, -15, 14, +133, 128, 250, 199, 318, 204, 322, 144, +263, 49, 151, -49, 13, -113, -119, -130, +-204, -103, -230, -53, -197, 0, -110, 28, +10, 29, 128, 20, 215, 19, 249, 27, +220, 46, 126, 54, 2, 33, -123, -26, +-216, -111, -255, -191, -215, -214, -93, -159, +86, -25, 256, 154, 371, 318, 397, 398, +317, 355, 145, 188, -72, -49, -271, -282, +-388, -434, -396, -463, -284, -362, -94, -168, +118, 57, 285, 237, 369, 333, 352, 329, +255, 248, 114, 127, -32, 8, -148, -83, +-203, -129, -197, -135, -148, -111, -71, -84, +26, -62, 123, -47, 192, -37, 209, -32, +179, -16, 106, 13, 7, 52, -98, 89, +-179, 111, -206, 102, -167, 61, -72, -10, +61, -85, 189, -135, 274, -132, 294, -74, +241, 25, 125, 120, -17, 169, -147, 143, +-231, 46, -256, -95, -209, -215, -109, -259, +14, -199, 127, -53, 209, 129, 243, 272, +221, 317, 151, 236, 67, 57, -3, -156, +-51, -316, -77, -367, -78, -286, -66, -103, +-60, 118, -62, 289, -51, 361, -23, 311, +27, 166, 96, -24, 169, -188, 217, -284, +215, -296, 157, -234, 53, -121, -74, -3, +-188, 89, -253, 136, -238, 145, -146, 121, +0, 83, 154, 46, 270, 30, 307, 31, +263, 42, 152, 41, 12, 18, -123, -40, +-209, -124, -225, -217, -173, -275, -82, -265, +25, -174, 120, -19, 173, 171, 173, 339, +137, 433, 79, 414, 25, 283, -16, 69, +-33, -161, -39, -351, -39, -444, -44, -425, +-49, -301, -45, -122, -24, 63, 20, 205, +78, 281, 139, 285, 178, 234, 169, 152, +104, 63, -2, -20, -115, -87, -201, -139, +-224, -168, -168, -173, -41, -151, 116, -105, +253, -35, 318, 39, 288, 98, 168, 122, +-3, 109, -168, 66, -275, 16, -293, -29, +-218, -41, -73, -24, 99, 8, 238, 33, +303, 38, 273, 10, 169, -37, 24, -85, +-105, -101, -177, -77, -176, -13, -117, 58, +-27, 107, 60, 101, 110, 38, 113, -64, +80, -157, 32, -200, -7, -157, -28, -36, +-21, 130, 3, 274, 36, 343, 58, 295, +57, 146, 33, -65, 0, -261, -31, -382, +-44, -381, -44, -264, -36, -69, -18, 129, +4, 269, 27, 306, 57, 239, 85, 96, +107, -60, 111, -176, 91, -204, 45, -145, +-11, -23, -73, 105, -123, 196, -147, 202, +-130, 124, -78, -12, -5, -150, 77, -241, +152, -244, 202, -161, 202, -18, 153, 123, +77, 210, -13, 206, -101, 119, -167, -13, +-186, -126, -159, -174, -94, -133, -8, -27, +82, 107, 150, 203, 181, 215, 169, 130, +126, -9, 61, -158, -8, -255, -58, -269, +-82, -189, -85, -53, -76, 92, -64, 190, +-42, 218, -11, 172, 32, 79, 75, -25, +110, -98, 125, -127, 120, -103, 88, -50, +33, 17, -39, 65, -103, 83, -142, 59, +-142, 12, -100, -45, -20, -86, 75, -100, +157, -68, 195, -9, 191, 60, 137, 110, +40, 128, -75, 88, -164, 1, -209, -105, +-194, -183, -117, -206, 1, -149, 125, -31, +218, 118, 248, 243, 212, 302, 125, 267, +9, 156, -104, -8, -178, -176, -204, -306, +-176, -359, -110, -329, -28, -222, 51, -72, +125, 91, 177, 234, 202, 335, 199, 367, +162, 335, 82, 233, -28, 83, -144, -100, +-236, -275, -273, -403, -242, -442, -142, -377, +14, -216, 176, -2, 297, 218, 337, 378, +288, 440, 159, 379, -9, 224, -171, 21, +-275, -168, -287, -297, -222, -319, -106, -245, +37, -107, 161, 34, 235, 130, 247, 146, +199, 97, 106, 5, 1, -78, -93, -119, +-145, -91, -151, -8, -128, 102, -86, 183, +-26, 203, 33, 150, 74, 47, 98, -85, +104, -193, 93, -246, 72, -222, 46, -141, +24, -30, 5, 72, -20, 153, -51, 186, +-70, 172, -77, 115, -66, 49, -41, -14, +-11, -63, 18, -99, 44, -109, 61, -101, +67, -75, 62, -50, 53, -20, 40, 9, +26, 42, 13, 68, 6, 95, 1, 115, +-14, 125, -42, 97, -57, 32, -61, -70, +-55, -173, -37, -246, -7, -247, 28, -171, +59, -23, 76, 147, 78, 292, 66, 341, +43, 275, 13, 107, -6, -94, -18, -268, +-25, -343, -26, -295, -19, -136, -11, 57, +1, 214, 3, 271, -1, 225, -6, 98, +-9, -49, -4, -163, 10, -190, 20, -138, +24, -36, 22, 54, 11, 103, -3, 85, +-1, 22, 12, -54, 26, -88, 39, -65, +54, 13, 57, 105, 46, 172, 14, 174, +-35, 108, -79, -22, -107, -163, -112, -272, +-82, -301, -32, -238, 14, -96, 48, 73, +72, 226, 94, 306, 126, 303, 152, 216, +159, 81, 140, -59, 81, -159, -24, -208, +-146, -198, -262, -147, -338, -76, -332, -18, +-233, 18, -59, 31, 156, 43, 342, 65, +440, 102, 421, 133, 293, 148, 93, 117, +-115, 48, -278, -59, -352, -164, -322, -236, +-223, -230, -100, -150, 23, -18, 118, 119, +161, 224, 167, 251, 154, 195, 127, 73, +97, -65, 60, -178, 17, -225, -30, -204, +-84, -114, -139, 1, -163, 104, -146, 157, +-94, 160, -10, 116, 91, 51, 169, -19, +200, -69, 167, -91, 80, -77, -29, -52, +-126, -27, -183, -20, -174, -16, -107, -12, +-5, -1, 109, 14, 195, 46, 204, 81, +142, 108, 26, 100, -106, 58, -199, -15, +-218, -88, -170, -149, -68, -165, 49, -135, +147, -55, 203, 42, 198, 130, 138, 170, +58, 161, -31, 103, -108, 17, -148, -81, +-140, -145, -105, -164, -57, -128, -9, -62, +34, 17, 71, 81, 96, 120, 96, 115, +88, 78, 71, 21, 40, -28, 10, -66, +-14, -79, -45, -72, -79, -41, -112, -11, +-136, 10, -135, 15, -91, 20, -6, 22, +112, 39, 226, 59, 284, 84, 256, 89, +137, 60, -51, -18, -245, -115, -374, -204, +-394, -237, -277, -199, -47, -80, 208, 89, +406, 260, 482, 357, 403, 342, 190, 203, +-80, -8, -327, -226, -461, -368, -446, -395, +-300, -292, -71, -102, 162, 111, 315, 259, +362, 308, 308, 248, 179, 125, 22, -16, +-111, -114, -192, -146, -197, -107, -144, -42, +-65, 17, 5, 33, 45, 13, 35, -31, +-3, -63, -36, -68, -48, -32, -25, 28, +38, 89, 104, 102, 155, 68, 170, -3, +128, -68, 41, -108, -62, -90, -158, -19, +-199, 85, -177, 168, -121, 192, -45, 127, +34, -3, 72, -158, 72, -279, 57, -320, +47, -246, 55, -84, 76, 121, 89, 288, +95, 370, 77, 333, 19, 204, -55, 21, +-120, -143, -167, -248, -177, -266, -144, -218, +-86, -139, -20, -67, 46, -9, 95, 26, +132, 55, 155, 89, 156, 145, 135, 205, +99, 242, 37, 210, -34, 109, -99, -48, +-159, -209, -202, -332, -199, -372, -154, -314, +-80, -161, 9, 27, 98, 197, 174, 307, +218, 345, 215, 296, 171, 184, 90, 39, +-30, -98, -156, -205, -239, -260, -259, -269, +-201, -222, -76, -126, 72, 8, 189, 139, +244, 247, 209, 296, 107, 276, -30, 173, +-161, 18, -240, -150, -233, -273, -153, -333, +-24, -304, 112, -196, 203, -27, 229, 150, +197, 296, 115, 360, 13, 338, -83, 231, +-162, 74, -212, -105, -214, -254, -174, -334, +-91, -325, 33, -252, 157, -125, 239, 15, +267, 135, 215, 200, 84, 214, -73, 176, +-210, 123, -285, 67, -262, 23, -150, -10, +21, -32, 187, -52, 281, -74, 271, -109, +177, -136, 7, -146, -170, -125, -276, -83, +-278, -16, -185, 62, -18, 143, 155, 196, +263, 211, 274, 170, 179, 90, 14, -25, +-150, -145, -270, -240, -294, -259, -201, -194, +-31, -53, 155, 114, 303, 260, 342, 321, +250, 270, 68, 103, -141, -115, -303, -313, +-358, -407, -299, -364, -150, -187, 37, 61, +184, 300, 247, 436, 237, 425, 156, 268, +36, 41, -55, -186, -81, -330, -58, -354, +-4, -255, 36, -85, 29, 95, -31, 206, +-126, 226, -207, 153, -213, 33, -147, -90, +-30, -162, 122, -164, 254, -89, 300, 20, +264, 113, 156, 150, 5, 131, -137, 59, +-228, -27, -252, -91, -197, -92, -103, -35, +-3, 53, 83, 117, 125, 124, 108, 51, +59, -78, 2, -229, -39, -325, -41, -315, +-5, -174, 44, 51, 91, 297, 100, 469, +56, 507, -23, 379, -115, 125, -191, -176, +-197, -413, -130, -512, -9, -438, 134, -235, +245, 25, 262, 245, 174, 358, 7, 323, +-174, 169, -295, -32, -309, -190, -210, -258, +-16, -208, 191, -67, 326, 116, 353, 258, +256, 304, 58, 226, -158, 65, -320, -129, +-371, -285, -285, -353, -102, -298, 99, -147, +251, 53, 298, 220, 230, 306, 82, 281, +-85, 166, -215, 0, -246, -148, -176, -228, +-45, -203, 107, -97, 228, 47, 251, 162, +175, 212, 34, 171, -125, 57, -238, -92, +-264, -213, -201, -262, -69, -214, 66, -95, +147, 64, 163, 205, 118, 285, 25, 271, +-56, 174, -76, 23, -32, -126, 54, -233, +142, -263, 175, -214, 126, -93, -7, 49, +-179, 164, -314, 210, -363, 186, -309, 96, +-139, -17, 95, -117, 299, -162, 412, -145, +414, -76, 294, 9, 96, 88, -116, 126, +-276, 123, -344, 79, -319, 25, -221, -29, +-68, -58, 84, -69, 178, -63, 206, -60, +173, -54, 76, -52, -35, -39, -112, -20, +-133, 15, -93, 55, -4, 97, 92, 121, +167, 122, 184, 91, 119, 46, -4, -9, +-144, -62, -265, -109, -302, -134, -228, -139, +-76, -119, 102, -81, 246, -22, 298, 40, +252, 94, 130, 118, -25, 114, -146, 86, +-194, 57, -173, 27, -86, 10, 24, 3, +94, 3, 102, -13, 55, -51, -34, -107, +-115, -151, -144, -170, -108, -139, -23, -59, +86, 56, 173, 158, 215, 216, 189, 210, +96, 150, -31, 56, -147, -32, -234, -94, +-257, -113, -206, -105, -109, -83, 4, -73, +115, -74, 184, -78, 203, -58, 183, -9, +128, 76, 57, 169, -5, 240, -68, 248, +-118, 180, -157, 37, -194, -131, -212, -276, +-180, -345, -101, -317, 20, -194, 168, -18, +293, 160, 354, 280, 327, 318, 197, 269, +0, 160, -215, 25, -392, -92, -461, -173, +-386, -194, -207, -162, 27, -98, 257, -30, +403, 23, 418, 46, 318, 41, 139, 10, +-59, -24, -224, -47, -321, -38, -316, 3, +-217, 72, -79, 146, 63, 199, 177, 199, +217, 134, 169, 2, 76, -161, -29, -309, +-109, -387, -134, -358, -98, -209, -11, 24, +95, 280, 156, 468, 147, 522, 70, 408, +-69, 161, -220, -152, -302, -423, -285, -563, +-164, -517, 35, -305, 250, 3, 397, 299, +424, 493, 310, 516, 98, 378, -148, 136, +-362, -118, -472, -305, -432, -377, -276, -339, +-61, -217, 162, -66, 324, 68, 377, 153, +331, 187, 207, 180, 50, 153, -96, 114, +-194, 64, -224, -4, -186, -73, -126, -135, +-67, -169, -19, -162, 4, -105, 2, -15, +5, 82, 21, 145, 50, 161, 95, 120, +142, 45, 165, -40, 148, -100, 75, -118, +-38, -90, -159, -31, -251, 30, -278, 64, +-215, 65, -98, 33, 41, -9, 165, -47, +237, -55, 229, -32, 164, 16, 69, 59, +-35, 87, -115, 78, -150, 33, -144, -38, +-102, -108, -60, -149, -24, -134, 11, -66, +37, 39, 57, 137, 90, 200, 114, 198, +105, 128, 67, 3, 11, -131, -65, -227, +-139, -247, -191, -195, -195, -84, -140, 46, +-47, 158, 63, 214, 173, 211, 235, 161, +226, 90, 164, 16, 62, -43, -65, -88, +-173, -120, -230, -144, -225, -158, -160, -160, +-60, -128, 38, -62, 113, 33, 135, 133, +103, 216, 55, 250, 11, 229, -29, 151, +-36, 38, -8, -82, 24, -170, 39, -211, +35, -201, 4, -151, -41, -70, -90, 13, +-119, 83, -105, 116, -61, 113, -15, 85, +23, 44, 50, 0, 60, -29, 64, -36, +73, -18, 74, 10, 70, 37, 43, 46, +-4, 34, -58, -1, -111, -43, -155, -78, +-158, -92, -110, -77, -34, -32, 54, 19, +127, 64, 150, 88, 125, 84, 63, 55, +-14, 17, -69, -22, -82, -45, -67, -47, +-29, -29, 5, -6, 16, 17, 3, 24, +-21, 7, -50, -30, -58, -66, -31, -87, +19, -76, 74, -29, 112, 51, 107, 137, +62, 199, -12, 205, -95, 149, -151, 36, +-161, -100, -129, -224, -55, -295, 36, -291, +105, -208, 137, -72, 122, 79, 65, 203, +3, 279, -44, 300, -62, 268, -46, 188, +-10, 88, 14, -21, 16, -136, -11, -247, +-65, -329, -122, -357, -146, -315, -131, -203, +-55, -26, 61, 178, 171, 359, 238, 458, +242, 448, 171, 323, 56, 119, -69, -110, +-172, -297, -225, -401, -225, -397, -189, -299, +-123, -143, -49, 22, 16, 151, 68, 220, +119, 237, 154, 209, 181, 156, 189, 97, +162, 42, 92, -16, -19, -75, -148, -135, +-249, -179, -296, -195, -276, -171, -188, -101, +-51, 7, 84, 123, 191, 209, 247, 230, +240, 181, 171, 72, 74, -55, -24, -154, +-97, -185, -131, -134, -131, -20, -104, 105, +-63, 186, -39, 183, -27, 89, -20, -71, +-21, -232, -22, -333, 0, -320, 36, -184, +76, 40, 106, 275, 113, 447, 89, 493, +39, 390, -28, 165, -88, -114, -123, -356, +-132, -491, -109, -487, -53, -348, 3, -123, +43, 118, 54, 298, 35, 368, 1, 322, +-24, 191, -27, 28, 6, -105, 59, -166, +110, -139, 129, -47, 107, 57, 36, 114, +-71, 99, -185, 9, -268, -117, -286, -224, +-211, -259, -66, -195, 112, -43, 273, 139, +362, 286, 346, 342, 236, 286, 57, 140, +-135, -40, -292, -190, -373, -255, -360, -229, +-250, -137, -89, -31, 78, 41, 216, 53, +291, 23, 287, -13, 230, -15, 135, 34, +26, 128, -81, 219, -175, 255, -243, 193, +-266, 34, -244, -173, -175, -357, -66, -449, +68, -396, 193, -204, 286, 68, 314, 328, +259, 488, 132, 494, -37, 349, -204, 98, +-309, -173, -334, -369, -267, -429, -128, -350, +36, -171, 175, 39, 256, 206, 251, 278, +172, 245, 49, 132, -74, 1, -157, -101, +-175, -141, -140, -113, -74, -40, 2, 34, +61, 78, 80, 74, 64, 29, 23, -38, +-21, -94, -45, -113, -40, -84, -12, -16, +29, 71, 55, 148, 52, 190, 19, 176, +-29, 108, -78, 3, -113, -113, -123, -216, +-99, -272, -40, -259, 45, -174, 123, -34, +176, 126, 181, 258, 132, 327, 37, 304, +-74, 195, -172, 35, -222, -122, -220, -229, +-161, -252, -55, -196, 64, -87, 159, 25, +204, 92, 186, 93, 109, 39, 2, -33, +-87, -82, -139, -75, -139, -7, -96, 94, +-29, 185, 39, 216, 82, 170, 80, 59, +47, -80, -9, -199, -68, -260, -97, -245, +-88, -157, -54, -24, -7, 104, 39, 185, +81, 207, 99, 174, 92, 108, 58, 29, +14, -44, -34, -96, -82, -120, -118, -125, +-126, -119, -112, -97, -74, -53, -17, 6, +48, 74, 109, 141, 148, 191, 148, 200, +113, 156, 42, 66, -43, -52, -119, -171, +-167, -255, -182, -278, -155, -226, -89, -116, +3, 28, 92, 164, 161, 253, 187, 269, +163, 217, 95, 115, 7, -5, -73, -110, +-134, -167, -169, -169, -165, -127, -128, -61, +-64, 8, 8, 58, 74, 80, 115, 71, +121, 42, 98, 5, 59, -32, 14, -62, +-26, -73, -65, -58, -86, -19, -83, 34, +-57, 90, -12, 130, 34, 142, 53, 114, +48, 41, 20, -59, -17, -155, -55, -215, +-77, -215, -78, -153, -53, -43, -15, 85, +31, 188, 75, 230, 105, 208, 98, 135, +64, 37, 20, -58, -30, -126, -77, -159, +-105, -154, -116, -124, -103, -81, -76, -34, +-29, 18, 31, 72, 83, 131, 108, 184, +102, 210, 66, 188, 5, 103, -66, -35, +-115, -191, -129, -312, -100, -354, -28, -293, +65, -134, 137, 83, 161, 295, 125, 425, +50, 430, -52, 303, -155, 83, -223, -156, +-235, -344, -185, -427, -79, -376, 49, -215, +175, -10, 258, 175, 272, 289, 221, 309, +124, 242, -6, 122, -138, -7, -242, -111, +-287, -161, -276, -159, -194, -125, -60, -74, +81, -19, 187, 22, 235, 49, 212, 61, +141, 59, 40, 47, -54, 30, -116, 12, +-134, -1, -111, -3, -56, 9, 0, 26, +32, 36, 17, 28, -23, -1, -67, -54, +-87, -112, -67, -146, -6, -134, 79, -69, +149, 38, 170, 154, 142, 238, 60, 255, +-56, 188, -170, 47, -236, -120, -229, -261, +-154, -325, -34, -287, 99, -152, 198, 37, +234, 220, 193, 336, 94, 347, -30, 244, +-143, 63, -210, -134, -212, -281, -155, -334, +-61, -274, 32, -125, 106, 55, 148, 205, +147, 281, 113, 260, 62, 151, -6, -3, +-72, -145, -129, -226, -150, -222, -142, -142, +-106, -16, -42, 108, 36, 196, 100, 216, +141, 169, 147, 68, 111, -44, 26, -138, +-80, -191, -154, -192, -174, -143, -137, -65, +-51, 21, 50, 93, 136, 141, 164, 160, +133, 154, 58, 126, -40, 81, -134, 20, +-195, -48, -197, -121, -129, -189, -29, -231, +80, -228, 171, -169, 213, -51, 197, 102, +136, 253, 45, 353, -55, 366, -161, 273, +-233, 89, -251, -138, -212, -336, -122, -442, +5, -417, 135, -267, 233, -35, 264, 198, +229, 365, 129, 412, -11, 332, -151, 161, +-245, -34, -257, -193, -197, -265, -91, -244, +48, -156, 167, -47, 223, 42, 200, 83, +114, 79, -6, 43, -135, 8, -229, -6, +-240, 12, -179, 51, -71, 89, 51, 100, +165, 77, 234, 26, 229, -38, 164, -101, +69, -141, -53, -145, -167, -118, -237, -64, +-239, 4, -188, 75, -109, 133, -13, 162, +85, 157, 148, 117, 175, 52, 174, -30, +147, -104, 73, -149, -29, -154, -112, -120, +-159, -57, -174, 11, -146, 68, -86, 102, +-10, 108, 42, 90, 72, 57, 95, 21, +93, -5, 54, -22, 14, -36, -10, -45, +-15, -51, -22, -57, -28, -55, -37, -40, +-62, -13, -100, 21, -114, 53, -88, 72, +-30, 77, 35, 66, 113, 40, 176, 12, +181, -8, 125, -19, 40, -29, -60, -43, +-150, -61, -208, -79, -198, -84, -137, -72, +-54, -32, 28, 33, 100, 108, 137, 162, +122, 173, 67, 128, 14, 40, -35, -70, +-65, -164, -57, -204, -17, -168, 27, -70, +50, 52, 47, 151, 32, 188, -15, 148, +-83, 42, -135, -87, -145, -182, -113, -198, +-48, -126, 38, 10, 117, 150, 142, 230, +117, 218, 61, 112, 4, -41, -38, -181, +-49, -245, -21, -204, 18, -68, 27, 99, +11, 224, -32, 249, -99, 156, -167, -22, +-199, -204, -158, -309, -43, -290, 103, -142, +238, 85, 310, 295, 286, 403, 155, 363, +-34, 185, -203, -71, -310, -310, -330, -439, +-240, -411, -76, -238, 112, 15, 245, 253, +285, 395, 231, 392, 94, 254, -79, 40, +-209, -166, -260, -293, -213, -310, -100, -224, +39, -71, 153, 81, 196, 182, 160, 200, +71, 150, -32, 59, -105, -29, -131, -82, +-98, -86, -28, -50, 31, -4, 62, 30, +55, 41, 6, 26, -58, -3, -118, -30, +-129, -40, -86, -36, -9, -19, 82, 1, +157, 18, 181, 27, 139, 31, 50, 31, +-32, 31, -105, 29, -161, 22, -182, 1, +-161, -25, -105, -55, -32, -79, 48, -83, +136, -55, 187, 0, 183, 68, 137, 126, +69, 152, -21, 133, -128, 67, -215, -36, +-242, -144, -216, -225, -131, -245, 0, -194, +143, -79, 244, 75, 264, 227, 219, 328, +130, 344, -5, 265, -139, 107, -233, -95, +-270, -281, -252, -399, -177, -411, -42, -310, +107, -121, 209, 108, 252, 312, 238, 428, +166, 422, 35, 294, -108, 86, -209, -141, +-260, -318, -253, -399, -163, -356, -21, -206, +127, -1, 228, 190, 265, 309, 236, 325, +124, 242, -42, 92, -191, -70, -287, -187, +-307, -231, -247, -203, -105, -124, 66, -30, +201, 47, 276, 86, 284, 91, 217, 74, +94, 65, -55, 71, -167, 88, -222, 93, +-226, 70, -175, 5, -87, -88, -16, -185, +23, -244, 43, -237, 66, -147, 78, 2, +80, 163, 87, 280, 96, 310, 89, 243, +63, 103, 20, -58, -30, -185, -103, -241, +-178, -208, -216, -113, -205, -2, -145, 82, +-51, 110, 50, 83, 141, 24, 189, -33, +198, -54, 175, -36, 119, 18, 39, 82, +-45, 129, -107, 131, -133, 84, -140, 7, +-123, -77, -100, -149, -91, -179, -91, -161, +-84, -104, -54, -29, 10, 46, 89, 107, +183, 141, 262, 142, 289, 121, 245, 82, +133, 40, -33, 3, -216, -25, -368, -47, +-429, -70, -389, -98, -251, -123, -57, -140, +140, -137, 297, -104, 369, -36, 340, 59, +240, 166, 99, 252, -26, 288, -111, 251, +-158, 144, -164, -13, -151, -178, -137, -306, +-126, -359, -112, -321, -77, -196, -35, -16, +26, 167, 109, 297, 191, 341, 239, 287, +218, 161, 121, 0, -18, -144, -164, -236, +-255, -249, -254, -186, -174, -74, -41, 44, +100, 133, 193, 173, 208, 156, 132, 88, +7, -1, -134, -83, -240, -136, -256, -147, +-168, -109, -4, -35, 165, 57, 264, 143, +281, 198, 200, 197, 43, 137, -124, 27, +-244, -107, -280, -231, -232, -301, -118, -288, +41, -185, 176, -15, 235, 174, 208, 320, +111, 374, -21, 312, -147, 156, -218, -38, +-205, -204, -134, -292, -20, -274, 95, -166, +165, -18, 172, 103, 117, 149, 32, 109, +-47, 14, -114, -87, -126, -140, -84, -110, +-25, 1, 18, 144, 38, 257, 38, 284, +4, 212, -56, 63, -93, -113, -85, -253, +-35, -308, 34, -269, 98, -160, 139, -29, +128, 74, 64, 125, -12, 127, -84, 95, +-128, 64, -139, 54, -105, 75, -41, 108, +23, 125, 71, 98, 86, 22, 54, -86, +-4, -189, -63, -250, -84, -244, -60, -172, +-13, -51, 46, 80, 93, 179, 96, 220, +66, 202, 11, 135, -51, 48, -112, -24, +-155, -63, -147, -73, -86, -60, 2, -42, +92, -28, 152, -25, 165, -30, 120, -37, +36, -33, -58, -15, -143, 9, -192, 30, +-187, 49, -138, 58, -40, 58, 75, 52, +170, 49, 220, 40, 205, 20, 129, -10, +10, -48, -124, -94, -222, -131, -255, -139, +-206, -111, -99, -43, 32, 53, 155, 145, +225, 212, 206, 227, 121, 182, -3, 80, +-117, -48, -193, -169, -202, -247, -130, -264, +-14, -212, 94, -112, 167, 12, 170, 129, +105, 214, 2, 247, -89, 227, -141, 162, +-147, 64, -107, -43, -44, -130, 15, -190, +62, -209, 78, -182, 72, -114, 44, -24, +-4, 70, -30, 140, -20, 171, -3, 154, +9, 94, 7, 12, -4, -64, -31, -116, +-56, -120, -57, -80, -32, -14, -3, 51, +15, 97, 26, 100, 37, 65, 20, 5, +-11, -52, -29, -89, -35, -92, -26, -61, +3, -5, 38, 42, 67, 65, 53, 54, +7, 17, -48, -28, -106, -52, -139, -44, +-116, -5, -40, 47, 55, 94, 130, 114, +181, 94, 172, 35, 91, -43, -26, -119, +-135, -166, -209, -168, -230, -124, -190, -50, +-80, 38, 50, 117, 152, 170, 212, 188, +215, 168, 154, 113, 50, 34, -57, -57, +-125, -141, -160, -201, -156, -217, -118, -181, +-66, -93, -12, 24, 27, 143, 47, 233, +53, 261, 34, 211, 24, 98, 34, -47, +55, -182, 83, -267, 96, -266, 71, -183, +8, -46, -84, 103, -162, 219, -205, 262, +-197, 222, -139, 112, -37, -29, 91, -154, +197, -223, 245, -217, 233, -143, 142, -27, +2, 88, -131, 160, -212, 172, -220, 129, +-168, 52, -80, -34, 20, -94, 91, -114, +127, -92, 123, -41, 86, 21, 32, 60, +-14, 69, -37, 46, -41, 10, -48, -30, +-45, -55, -48, -62, -63, -41, -75, -4, +-68, 40, -20, 75, 52, 90, 119, 78, +171, 44, 174, -9, 113, -67, 0, -115, +-127, -134, -227, -115, -269, -63, -227, 10, +-102, 87, 54, 142, 202, 159, 289, 128, +289, 62, 196, -19, 28, -88, -152, -134, +-270, -143, -307, -115, -242, -60, -89, -2, +87, 49, 212, 87, 250, 106, 211, 102, +108, 80, -36, 45, -157, 3, -220, -41, +-202, -78, -125, -98, -11, -92, 110, -65, +183, -24, 172, 17, 107, 50, 8, 62, +-79, 55, -130, 35, -131, 22, -84, 14, +-21, 19, 31, 33, 62, 38, 61, 18, +28, -23, -28, -78, -65, -122, -69, -138, +-36, -111, 36, -42, 114, 56, 144, 142, +118, 192, 39, 182, -62, 121, -156, 24, +-214, -76, -200, -145, -120, -161, -15, -128, +88, -65, 163, -6, 194, 32, 156, 43, +70, 35, -14, 19, -71, 16, -91, 40, +-70, 78, -24, 106, 28, 106, 35, 65, +-2, -15, -59, -115, -119, -202, -151, -238, +-126, -199, -55, -92, 50, 52, 147, 189, +213, 277, 226, 280, 173, 199, 74, 62, +-44, -90, -150, -208, -214, -252, -224, -216, +-166, -114, -75, 10, 13, 114, 82, 162, +112, 150, 96, 85, 62, -3, 27, -82, +2, -118, -14, -102, -16, -38, -4, 49, +11, 123, 22, 155, 19, 132, -7, 61, +-43, -35, -80, -129, -86, -185, -64, -187, +-34, -128, 4, -28, 42, 74, 66, 145, +76, 169, 68, 141, 48, 77, 3, -2, +-50, -68, -87, -100, -94, -91, -79, -59, +-38, -20, 24, 9, 81, 26, 104, 22, +104, 12, 85, 11, 33, 25, -38, 42, +-101, 52, -142, 38, -151, 1, -137, -56, +-86, -111, -3, -138, 76, -117, 138, -48, +185, 53, 197, 151, 160, 211, 74, 208, +-25, 139, -131, 18, -233, -110, -290, -203, +-269, -228, -170, -178, -24, -70, 132, 56, +274, 160, 338, 203, 292, 171, 164, 77, +-3, -39, -178, -137, -317, -182, -366, -161, +-293, -79, -134, 33, 65, 137, 252, 197, +372, 196, 362, 140, 220, 46, 12, -66, +-183, -156, -341, -203, -397, -193, -323, -138, +-150, -48, 56, 53, 242, 140, 365, 188, +381, 188, 258, 137, 60, 51, -136, -49, +-278, -131, -343, -176, -303, -161, -170, -90, +-11, 10, 118, 98, 210, 154, 242, 157, +204, 105, 110, 23, 3, -58, -71, -113, +-114, -120, -136, -87, -116, -37, -80, 2, +-59, 19, -55, 5, -35, -20, 3, -31, +46, -2, 100, 64, 161, 146, 192, 205, +164, 212, 73, 141, -43, -3, -165, -176, +-269, -319, -302, -380, -236, -330, -102, -182, +68, 29, 225, 234, 328, 374, 328, 405, +220, 323, 45, 160, -136, -28, -270, -190, +-318, -279, -271, -283, -141, -215, 10, -107, +131, 7, 203, 90, 216, 127, 167, 128, +73, 114, -35, 88, -102, 60, -123, 31, +-107, 7, -65, -21, -18, -57, 6, -99, +-1, -125, -22, -125, -30, -92, -23, -34, +8, 44, 55, 120, 101, 177, 125, 190, +113, 156, 65, 82, -6, -15, -102, -116, +-184, -190, -217, -222, -182, -199, -98, -122, +11, -9, 123, 102, 208, 190, 222, 232, +170, 213, 80, 130, -21, 12, -118, -109, +-180, -195, -182, -219, -130, -172, -55, -72, +29, 53, 97, 155, 127, 200, 100, 173, +38, 86, -17, -31, -53, -129, -72, -175, +-50, -157, 7, -86, 61, 9, 73, 84, +55, 117, 18, 100, -46, 49, -115, -9, +-140, -40, -111, -31, -41, 13, 40, 60, +126, 83, 182, 59, 162, -11, 78, -109, +-14, -185, -94, -203, -147, -140, -152, -16, +-95, 128, -16, 236, 36, 266, 60, 201, +70, 61, 51, -106, 6, -232, -34, -267, +-26, -202, 8, -65, 43, 101, 77, 230, +93, 273, 53, 210, -34, 68, -121, -100, +-167, -231, -169, -289, -119, -250, -20, -127, +89, 41, 158, 189, 174, 274, 144, 271, +76, 195, -29, 72, -119, -56, -148, -155, +-116, -196, -47, -178, 37, -117, 105, -43, +121, 22, 56, 60, -45, 65, -131, 44, +-176, 15, -164, -2, -79, 8, 61, 38, +200, 77, 271, 109, 266, 110, 188, 68, +38, -6, -149, -101, -291, -188, -341, -229, +-301, -205, -190, -123, -19, 2, 152, 131, +261, 228, 288, 255, 252, 211, 172, 114, +62, -3, -44, -107, -112, -168, -151, -170, +-173, -128, -174, -68, -147, -15, -107, 13, +-66, 21, -12, 22, 68, 32, 146, 59, +206, 100, 235, 129, 215, 124, 132, 70, +-3, -25, -140, -136, -229, -215, -262, -228, +-226, -158, -129, -26, -2, 131, 106, 246, +168, 270, 175, 189, 127, 35, 40, -137, +-43, -256, -93, -274, -82, -183, -22, -18, +50, 157, 100, 265, 106, 266, 54, 159, +-35, -12, -122, -181, -168, -275, -157, -261, +-94, -144, 0, 27, 101, 182, 166, 264, +165, 247, 105, 141, 21, -6, -72, -142, +-133, -214, -130, -206, -65, -129, 22, -21, +93, 72, 135, 116, 129, 112, 58, 70, +-44, 16, -127, -23, -165, -36, -160, -25, +-106, 1, -12, 23, 87, 36, 150, 29, +172, 8, 149, -20, 81, -46, -15, -68, +-97, -79, -129, -80, -114, -59, -73, -14, +-10, 50, 52, 114, 84, 160, 76, 163, +44, 115, 0, 19, -50, -98, -92, -199, +-96, -238, -58, -197, 3, -81, 61, 73, +107, 208, 126, 267, 101, 226, 38, 94, +-25, -79, -75, -228, -103, -293, -107, -249, +-76, -101, -22, 91, 26, 259, 56, 331, +72, 279, 63, 121, 22, -82, -29, -253, +-51, -333, -40, -297, -11, -155, 29, 39, +74, 206, 92, 284, 66, 255, 12, 136, +-43, -19, -99, -150, -143, -206, -136, -175, +-75, -75, 4, 43, 81, 130, 146, 146, +178, 92, 145, -1, 63, -91, -24, -140, +-96, -118, -148, -38, -155, 61, -114, 133, +-47, 150, 18, 98, 80, 1, 121, -98, +124, -156, 90, -150, 37, -77, -20, 25, +-63, 117, -87, 168, -81, 155, -51, 76, +-14, -34, 14, -134, 32, -184, 37, -167, +32, -93, 23, 6, 19, 104, 13, 171, +8, 182, 6, 134, 3, 48, -4, -45, +-16, -117, -44, -151, -66, -141, -64, -93, +-34, -23, 8, 41, 54, 83, 90, 93, +98, 78, 65, 47, 11, 13, -38, -10, +-72, -11, -89, 4, -74, 19, -31, 22, +19, 1, 58, -42, 77, -92, 65, -133, +27, -141, -26, -95, -66, -3, -76, 105, +-53, 197, -10, 244, 40, 225, 75, 133, +81, -4, 54, -144, 15, -244, -26, -275, +-62, -225, -76, -116, -62, 19, -28, 140, +12, 207, 38, 205, 49, 145, 40, 51, +11, -38, -26, -96, -40, -109, -21, -82, +20, -33, 59, 12, 90, 37, 90, 35, +47, 13, -22, -25, -83, -56, -126, -65, +-147, -45, -132, -6, -66, 37, 25, 69, +107, 85, 159, 81, 181, 57, 151, 15, +76, -26, -5, -63, -61, -85, -103, -86, +-131, -65, -128, -30, -93, 12, -59, 49, +-26, 70, 19, 66, 66, 42, 84, 6, +88, -26, 90, -44, 84, -34, 56, -2, +20, 36, -13, 60, -53, 60, -97, 26, +-114, -33, -94, -97, -51, -135, -3, -127, +49, -69, 87, 20, 93, 106, 73, 157, +39, 163, -8, 116, -50, 31, -74, -59, +-67, -121, -31, -138, 22, -114, 70, -62, +94, 2, 82, 52, 40, 72, -21, 63, +-74, 41, -102, 17, -101, 3, -79, -3, +-38, -7, 16, -15, 64, -25, 91, -35, +99, -36, 91, -24, 59, 6, 11, 45, +-31, 76, -58, 83, -73, 59, -77, 6, +-58, -57, -27, -110, 0, -127, 21, -96, +38, -26, 41, 49, 25, 101, 2, 115, +-12, 91, -16, 34, -3, -31, 27, -68, +60, -60, 77, -19, 65, 36, 27, 76, +-23, 73, -81, 24, -135, -56, -161, -137, +-147, -179, -91, -157, 0, -68, 107, 58, +202, 182, 249, 264, 229, 267, 150, 181, +33, 37, -102, -118, -214, -240, -270, -297, +-253, -268, -174, -167, -57, -24, 74, 114, +189, 211, 247, 245, 226, 218, 147, 140, +44, 35, -61, -70, -139, -147, -160, -181, +-118, -168, -54, -114, 6, -37, 59, 42, +89, 106, 69, 132, 16, 116, -39, 70, +-79, 12, -97, -47, -70, -84, 2, -86, +89, -57, 143, -13, 157, 29, 128, 49, +53, 44, -53, 21, -144, -8, -187, -32, +-181, -39, -134, -15, -43, 24, 67, 54, +155, 67, 185, 56, 170, 19, 116, -35, +26, -80, -66, -103, -120, -97, -133, -60, +-119, -5, -85, 49, -30, 90, 26, 109, +71, 98, 100, 63, 113, 19, 100, -22, +58, -54, -1, -79, -53, -92, -90, -90, +-105, -71, -98, -37, -60, 12, -2, 65, +54, 116, 92, 144, 109, 134, 94, 83, +39, -2, -33, -98, -86, -177, -109, -215, +-97, -191, -52, -101, 24, 30, 94, 159, +130, 252, 131, 278, 104, 224, 40, 97, +-48, -64, -123, -216, -159, -308, -162, -318, +-125, -243, -43, -103, 58, 64, 135, 209, +173, 293, 176, 297, 142, 223, 70, 100, +-16, -37, -91, -149, -141, -210, -167, -204, +-151, -140, -99, -48, -28, 40, 34, 97, +81, 110, 102, 80, 101, 19, 83, -42, +58, -69, 32, -60, 14, -25, 0, 27, +-16, 76, -33, 98, -49, 84, -72, 39, +-96, -16, -102, -63, -76, -86, -23, -82, +48, -51, 120, -8, 168, 27, 162, 35, +104, 22, 21, -3, -66, -21, -139, -19, +-164, 2, -127, 36, -55, 71, 18, 80, +82, 56, 118, 5, 101, -55, 37, -99, +-31, -107, -75, -74, -88, -9, -67, 66, +-6, 123, 67, 134, 103, 95, 92, 21, +55, -62, 0, -124, -61, -145, -100, -119, +-96, -52, -68, 24, -30, 77, 11, 96, +50, 84, 69, 52, 65, 18, 51, 1, +37, 9, 21, 29, 11, 41, 4, 31, +-4, -7, -26, -66, -60, -123, -87, -156, +-87, -147, -64, -91, -18, -2, 42, 91, +100, 158, 129, 184, 112, 168, 64, 115, +7, 42, -56, -27, -112, -76, -132, -101, +-103, -104, -52, -92, 4, -73, 59, -50, +100, -22, 104, 7, 73, 38, 38, 63, +18, 76, -6, 73, -34, 53, -51, 18, +-64, -14, -90, -39, -105, -50, -84, -47, +-30, -32, 38, -10, 115, 15, 191, 30, +229, 34, 198, 34, 109, 27, -18, 12, +-167, -9, -298, -36, -344, -60, -291, -75, +-158, -75, 26, -55, 219, -11, 358, 45, +393, 93, 320, 115, 171, 109, -21, 71, +-203, 10, -320, -54, -339, -94, -265, -94, +-129, -59, 29, -9, 160, 36, 225, 54, +218, 32, 149, -20, 57, -77, -24, -108, +-73, -94, -88, -33, -69, 54, -33, 134, +1, 179, 9, 168, 5, 96, -1, -15, +-14, -114, -29, -163, -21, -152, 12, -93, +44, -8, 57, 68, 57, 104, 33, 83, +-14, 20, -57, -54, -66, -104, -48, -113, +-18, -71, 21, 4, 65, 87, 86, 144, +69, 160, 31, 133, -12, 76, -59, 8, +-95, -55, -96, -106, -57, -140, -10, -159, +34, -158, 69, -139, 88, -93, 76, -10, +44, 100, 18, 204, 4, 277, -14, 286, +-24, 214, -25, 71, -31, -104, -44, -265, +-48, -357, -42, -347, -25, -231, -7, -47, +17, 148, 48, 291, 76, 346, 81, 295, +64, 160, 35, -12, 4, -164, -33, -256, +-58, -263, -60, -196, -44, -79, -36, 45, +-32, 137, -16, 172, 1, 157, 7, 103, +19, 28, 42, -40, 61, -79, 60, -86, +54, -60, 48, -20, 24, 20, -25, 46, +-69, 46, -96, 20, -105, -27, -91, -73, +-37, -95, 37, -83, 95, -38, 125, 29, +139, 101, 116, 149, 56, 150, -22, 101, +-89, 17, -135, -83, -153, -164, -129, -195, +-61, -166, 20, -83, 90, 25, 140, 121, +164, 174, 147, 170, 100, 111, 35, 25, +-35, -59, -106, -119, -158, -134, -178, -113, +-154, -68, -96, -21, -14, 23, 76, 58, +152, 82, 193, 95, 187, 102, 136, 97, +61, 65, -25, 2, -104, -80, -157, -159, +-162, -206, -129, -200, -73, -128, -4, -3, +63, 140, 96, 250, 93, 282, 71, 220, +49, 85, 20, -76, -5, -211, -12, -273, +-1, -234, 0, -116, -6, 38, -14, 164, +-25, 216, -46, 175, -57, 62, -39, -74, +-2, -167, 34, -183, 72, -118, 101, 1, +86, 125, 28, 198, -39, 190, -89, 100, +-110, -37, -97, -163, -45, -224, 30, -200, +99, -102, 135, 35, 133, 159, 88, 228, +8, 211, -76, 115, -128, -18, -142, -136, +-113, -201, -61, -196, 2, -126, 57, -24, +89, 82, 90, 151, 79, 167, 62, 136, +40, 75, 13, 2, -9, -62, -25, -106, +-42, -120, -61, -111, -65, -81, -55, -40, +-41, 13, -28, 64, -2, 105, 33, 117, +57, 98, 69, 57, 75, 5, 64, -43, +33, -77, -6, -83, -27, -65, -38, -38, +-49, -7, -56, 10, -40, 10, -19, -2, +-6, -11, 14, -9, 41, 13, 49, 49, +38, 82, 27, 92, 20, 72, 5, 19, +-8, -49, -15, -110, -18, -138, -28, -129, +-28, -80, -13, -12, 10, 51, 27, 89, +39, 97, 46, 84, 38, 56, 17, 28, +-8, 14, -40, 13, -69, 7, -89, -14, +-82, -50, -41, -92, 24, -122, 93, -126, +151, -88, 171, -10, 142, 79, 66, 149, +-40, 171, -140, 134, -206, 55, -226, -36, +-176, -110, -62, -136, 75, -98, 179, -20, +225, 65, 202, 115, 113, 108, -12, 45, +-114, -49, -156, -129, -136, -156, -73, -114, +15, -19, 90, 88, 113, 164, 70, 176, +-5, 121, -80, 15, -132, -95, -138, -162, +-76, -158, 24, -87, 123, 20, 187, 122, +198, 178, 142, 162, 37, 79, -76, -41, +-155, -150, -189, -210, -170, -202, -106, -135, +-16, -29, 65, 76, 123, 154, 149, 192, +141, 179, 100, 128, 44, 57, -15, -17, +-63, -81, -97, -130, -110, -154, -103, -153, +-75, -119, -36, -63, 19, 8, 78, 86, +122, 150, 138, 176, 114, 156, 53, 94, +-22, 5, -93, -85, -144, -147, -159, -166, +-119, -133, -48, -63, 31, 23, 105, 95, +156, 139, 156, 141, 109, 99, 44, 31, +-22, -43, -78, -95, -111, -119, -106, -115, +-71, -81, -41, -28, -15, 30, 15, 67, +42, 84, 53, 80, 58, 58, 70, 24, +70, -11, 47, -33, 15, -39, -21, -28, +-58, -14, -88, 0, -89, 9, -58, 2, +-7, -10, 42, -22, 84, -24, 99, -16, +74, -1, 20, 7, -38, 2, -85, -8, +-104, -26, -76, -42, -9, -33, 64, 7, +123, 75, 139, 142, 112, 183, 44, 163, +-47, 80, -132, -56, -180, -209, -169, -326, +-102, -355, -4, -273, 103, -99, 180, 119, +197, 316, 149, 424, 67, 409, -26, 272, +-102, 64, -143, -151, -132, -302, -79, -356, +-14, -305, 41, -178, 76, -30, 76, 92, +39, 153, -5, 147, -24, 106, -23, 60, +-2, 36, 31, 39, 62, 62, 61, 76, +27, 55, -17, -13, -58, -106, -90, -188, +-98, -224, -71, -187, -21, -86, 33, 49, +81, 177, 108, 252, 106, 249, 76, 164, +36, 39, -7, -87, -44, -174, -72, -195, +-92, -154, -96, -77, -84, -5, -56, 42, +-13, 60, 37, 52, 94, 39, 139, 32, +158, 48, 137, 70, 78, 82, -8, 65, +-100, 13, -171, -61, -195, -132, -167, -169, +-95, -157, 5, -90, 107, 12, 168, 112, +180, 176, 142, 177, 68, 127, -25, 37, +-96, -55, -118, -123, -97, -145, -49, -116, +6, -56, 51, 17, 66, 73, 44, 99, +9, 93, -26, 60, -48, 17, -57, -29, +-35, -56, 1, -74, 35, -76, 56, -68, +62, -46, 51, -8, 25, 36, 3, 78, +-7, 107, -12, 114, -16, 96, -24, 47, +-27, -15, -40, -78, -54, -117, -62, -130, +-54, -112, -27, -70, 14, -16, 67, 42, +115, 81, 143, 102, 140, 100, 98, 85, +26, 60, -63, 18, -137, -27, -187, -71, +-187, -100, -137, -111, -54, -88, 41, -38, +127, 26, 180, 89, 177, 124, 127, 121, +54, 71, -21, -12, -78, -90, -111, -141, +-98, -138, -62, -83, -25, 12, 5, 106, +16, 168, 4, 174, -18, 116, -26, 14, +-7, -96, 25, -167, 61, -174, 92, -125, +109, -39, 85, 47, 31, 111, -42, 121, +-107, 86, -149, 25, -147, -30, -88, -54, +-5, -39, 73, 7, 128, 54, 139, 78, +103, 58, 36, -7, -33, -83, -89, -142, +-107, -150, -85, -102, -32, -4, 30, 109, +76, 195, 87, 219, 66, 163, 20, 53, +-38, -79, -79, -189, -84, -238, -66, -211, +-18, -113, 34, 16, 78, 143, 91, 222, +76, 232, 38, 168, -11, 56, -48, -66, +-71, -165, -72, -207, -49, -190, -12, -125, +27, -29, 48, 64, 60, 134, 53, 159, +33, 145, 0, 93, -24, 27, -33, -33, +-35, -74, -30, -88, -15, -79, -3, -53, +-3, -26, -4, -8, 2, 5, 4, 9, +17, 19, 33, 28, 51, 44, 59, 59, +42, 65, 11, 46, -25, -1, -63, -52, +-94, -96, -98, -106, -71, -76, -28, -20, +36, 52, 94, 105, 131, 128, 127, 97, +94, 30, 37, -56, -28, -126, -75, -155, +-103, -131, -101, -57, -77, 35, -43, 110, +-2, 145, 29, 130, 53, 81, 63, 9, +69, -48, 66, -84, 54, -82, 35, -56, +3, -25, -34, -1, -64, -1, -83, -11, +-85, -20, -60, -18, -12, 5, 36, 36, +82, 68, 104, 78, 94, 68, 49, 30, +-8, -18, -58, -62, -88, -88, -88, -81, +-63, -49, -15, 1, 37, 40, 71, 54, +92, 46, 80, 23, 42, 2, -8, -18, +-44, -17, -70, -5, -78, 9, -66, 16, +-43, 9, -11, -5, 18, -22, 46, -28, +71, -24, 84, -4, 83, 27, 60, 47, +32, 56, -16, 36, -65, 6, -104, -32, +-120, -62, -107, -71, -70, -54, -13, -22, +53, 9, 108, 33, 141, 41, 141, 32, +116, 28, 58, 23, -7, 30, -75, 34, +-127, 37, -151, 19, -147, -18, -109, -66, +-45, -110, 35, -120, 105, -95, 157, -34, +176, 47, 147, 120, 80, 165, -15, 149, +-93, 86, -144, -7, -157, -88, -121, -135, +-49, -137, 35, -90, 95, -22, 121, 44, +103, 75, 45, 70, -22, 41, -72, -3, +-75, -29, -47, -31, 5, -2, 58, 31, +89, 53, 78, 51, 24, 20, -41, -22, +-104, -63, -135, -81, -109, -73, -38, -35, +56, 13, 139, 44, 189, 58, 169, 44, +90, 24, -22, -1, -129, -15, -193, -10, +-198, 2, -140, 19, -38, 18, 80, 6, +166, -14, 191, -32, 163, -39, 78, -37, +-21, -17, -105, -1, -142, 17, -129, 25, +-72, 25, 3, 20, 62, 17, 94, 27, +75, 33, 20, 30, -32, 14, -74, -17, +-80, -49, -45, -79, 24, -78, 91, -53, +138, -2, 138, 51, 79, 90, -12, 98, +-118, 63, -196, 5, -208, -61, -148, -99, +-41, -92, 85, -41, 197, 36, 238, 97, +210, 126, 118, 96, -8, 22, -124, -71, +-199, -141, -210, -154, -157, -112, -55, -23, +47, 73, 121, 144, 153, 161, 121, 112, +66, 25, 12, -71, -28, -122, -45, -123, +-28, -72, -5, 4, 5, 68, 5, 94, +-22, 65, -57, 2, -75, -72, -67, -121, +-21, -110, 45, -50, 116, 49, 150, 133, +144, 181, 82, 155, -15, 68, -103, -47, +-170, -148, -183, -196, -129, -183, -31, -109, +73, -5, 158, 94, 194, 159, 153, 161, +77, 116, -23, 40, -116, -27, -165, -78, +-156, -93, -96, -75, -9, -47, 81, -15, +132, 1, 147, 10, 116, 12, 42, 7, +-22, 6, -74, 5, -98, 18, -93, 24, +-58, 36, -16, 40, 19, 37, 44, 28, +46, 3, 37, -25, 20, -61, 3, -91, +1, -104, 5, -90, 12, -41, 8, 27, +6, 107, -14, 163, -36, 181, -48, 149, +-50, 69, -27, -33, 10, -131, 49, -188, +77, -195, 82, -151, 58, -75, 1, -1, +-50, 60, -92, 86, -99, 99, -65, 97, +2, 103, 77, 114, 129, 114, 140, 93, +97, 32, 19, -62, -77, -173, -154, -262, +-174, -288, -148, -236, -66, -100, 38, 70, +138, 235, 191, 329, 181, 328, 119, 233, +24, 71, -67, -94, -131, -218, -142, -256, +-103, -213, -48, -115, 20, -4, 65, 74, +83, 106, 62, 78, 29, 30, -9, -18, +-32, -38, -30, -22, -15, 13, 17, 49, +44, 58, 49, 44, 37, 7, 15, -34, +-9, -50, -35, -39, -37, 6, -43, 51, +-42, 76, -35, 54, -33, -12, -23, -98, +-7, -173, 20, -190, 52, -138, 91, -17, +117, 130, 113, 250, 93, 303, 33, 253, +-44, 127, -124, -49, -181, -207, -198, -303, +-157, -305, -71, -216, 32, -76, 146, 73, +219, 179, 230, 222, 192, 198, 98, 126, +-19, 44, -130, -31, -192, -74, -205, -92, +-158, -81, -74, -63, 18, -54, 106, -47, +146, -40, 131, -19, 88, 11, 27, 50, +-36, 92, -70, 108, -53, 103, -27, 63, +15, 13, 47, -50, 46, -101, 22, -134, +-21, -137, -67, -103, -94, -44, -74, 28, +-27, 94, 41, 138, 118, 149, 145, 123, +127, 74, 66, -3, -22, -74, -112, -124, +-165, -138, -165, -117, -118, -66, -24, 7, +65, 61, 137, 88, 178, 80, 156, 48, +95, 12, 17, -20, -53, -22, -114, -10, +-132, 18, -126, 36, -102, 31, -52, 4, +-7, -40, 39, -75, 90, -90, 123, -64, +132, -10, 126, 50, 103, 100, 33, 108, +-36, 76, -102, 3, -153, -70, -170, -122, +-143, -129, -81, -82, -2, -2, 83, 85, +138, 143, 160, 159, 147, 121, 92, 35, +40, -57, -17, -136, -67, -167, -103, -156, +-109, -97, -102, -17, -82, 60, -33, 115, +17, 136, 69, 129, 108, 91, 118, 37, +105, -18, 57, -72, -10, -107, -83, -129, +-124, -113, -135, -72, -103, -5, -22, 68, +68, 125, 145, 157, 174, 141, 145, 84, +68, -5, -35, -98, -128, -165, -190, -190, +-185, -151, -136, -75, -42, 27, 62, 114, +145, 167, 187, 170, 175, 131, 126, 68, +50, -3, -18, -55, -75, -88, -113, -99, +-116, -99, -115, -98, -98, -84, -73, -69, +-33, -30, 11, 25, 62, 92, 117, 153, +152, 182, 165, 169, 136, 100, 74, -3, +-7, -112, -102, -195, -167, -216, -197, -176, +-171, -77, -107, 32, -10, 126, 87, 168, +149, 155, 173, 100, 144, 18, 86, -51, +16, -95, -51, -99, -94, -73, -102, -43, +-76, -8, -44, 9, 9, 19, 44, 22, +54, 37, 48, 56, 20, 72, -6, 76, +-21, 51, -21, 3, -14, -59, 1, -114, +18, -146, 20, -145, 27, -93, 16, -22, +5, 61, -2, 123, -9, 159, -14, 156, +-11, 117, -7, 61, -18, -6, -18, -63, +-18, -106, -17, -130, 15, -130, 51, -108, +80, -63, 89, -14, 80, 37, 28, 69, +-42, 85, -109, 82, -166, 58, -162, 32, +-107, 7, -14, -1, 113, 2, 222, 12, +266, 21, 227, 9, 127, -17, -39, -68, +-193, -115, -287, -142, -306, -126, -229, -65, +-79, 21, 90, 119, 225, 190, 297, 213, +270, 175, 160, 83, 28, -27, -121, -131, +-215, -187, -224, -191, -166, -135, -64, -46, +54, 44, 140, 106, 162, 120, 139, 94, +64, 37, -27, -19, -90, -51, -132, -52, +-130, -20, -83, 16, -7, 45, 59, 43, +122, 16, 155, -28, 136, -64, 93, -72, +22, -53, -54, -2, -114, 56, -154, 96, +-162, 95, -129, 52, -60, -12, 8, -87, +96, -129, 165, -130, 186, -78, 169, 6, +112, 90, 26, 150, -65, 159, -135, 118, +-177, 36, -172, -57, -119, -125, -55, -153, +37, -129, 120, -75, 165, 4, 162, 70, +121, 108, 43, 103, -49, 62, -109, 3, +-139, -57, -121, -87, -59, -78, 13, -35, +88, 30, 132, 81, 134, 105, 80, 82, +3, 26, -87, -53, -147, -120, -146, -146, +-99, -118, -11, -41, 88, 55, 154, 139, +165, 173, 120, 137, 37, 51, -69, -66, +-135, -155, -160, -191, -125, -145, -43, -37, +49, 93, 123, 193, 146, 222, 113, 169, +36, 43, -47, -102, -106, -213, -127, -250, +-84, -191, -21, -72, 53, 73, 101, 181, +111, 220, 77, 176, 14, 73, -50, -45, +-95, -137, -96, -163, -64, -119, -10, -29, +57, 69, 95, 128, 104, 134, 72, 80, +19, -5, -40, -95, -78, -146, -93, -145, +-86, -93, -55, -9, -22, 72, 17, 124, +54, 130, 75, 96, 87, 40, 87, -21, +77, -54, 46, -61, 14, -33, -33, 3, +-82, 27, -113, 23, -132, -4, -127, -42, +-90, -81, -26, -101, 48, -88, 120, -41, +170, 31, 173, 100, 158, 152, 103, 163, +27, 136, -52, 69, -125, -12, -180, -90, +-199, -148, -173, -168, -120, -149, -35, -94, +57, -21, 132, 48, 200, 101, 225, 121, +202, 115, 136, 76, 48, 26, -68, -25, +-171, -60, -228, -73, -243, -60, -193, -28, +-97, 9, 14, 40, 126, 55, 205, 47, +230, 20, 200, -21, 136, -55, 26, -77, +-86, -67, -169, -40, -209, -2, -187, 41, +-115, 73, -16, 80, 83, 64, 160, 34, +182, -3, 151, -40, 96, -62, 5, -74, +-73, -61, -122, -32, -139, 8, -119, 41, +-58, 61, 9, 59, 57, 35, 92, 0, +92, -35, 69, -62, 51, -64, 20, -44, +-9, -3, -29, 34, -41, 63, -59, 63, +-55, 43, -42, 9, -34, -24, -3, -39, +23, -28, 35, 2, 50, 31, 53, 39, +39, 25, 10, -14, -12, -60, -39, -100, +-35, -103, -12, -68, 6, 4, 28, 85, +37, 148, 17, 170, -14, 137, -38, 61, +-59, -30, -64, -108, -38, -149, -9, -152, +34, -110, 70, -54, 88, 0, 85, 40, +65, 67, 25, 75, -13, 75, -36, 79, +-62, 81, -74, 66, -66, 32, -65, -21, +-60, -79, -43, -134, -6, -156, 34, -138, +92, -71, 132, 24, 139, 121, 122, 181, +67, 185, -10, 128, -85, 30, -143, -76, +-167, -154, -144, -181, -78, -141, -8, -59, +75, 36, 126, 103, 134, 127, 111, 98, +59, 37, 2, -31, -41, -76, -57, -80, +-52, -46, -29, 11, 0, 68, 13, 94, +26, 79, 20, 23, -3, -41, -33, -101, +-59, -127, -70, -115, -58, -69, -17, -5, +34, 57, 87, 106, 124, 127, 133, 116, +118, 82, 67, 35, -9, -8, -92, -55, +-151, -92, -179, -117, -156, -117, -92, -98, +-5, -59, 88, -9, 149, 45, 164, 92, +132, 118, 66, 115, -5, 91, -63, 52, +-89, 17, -90, -19, -52, -41, -9, -61, +25, -74, 40, -84, 20, -90, -9, -85, +-40, -57, -53, -5, -37, 61, 2, 121, +59, 156, 88, 148, 99, 98, 68, 8, +15, -86, -39, -157, -82, -173, -101, -132, +-87, -46, -40, 50, 17, 123, 67, 148, +97, 120, 82, 46, 54, -41, 8, -109, +-40, -127, -67, -100, -66, -38, -50, 22, +-13, 62, 24, 71, 40, 54, 46, 23, +42, 1, 21, -8, 5, 6, -6, 27, +-15, 41, -13, 28, 0, -6, -4, -58, +-10, -103, -16, -127, -31, -109, -34, -50, +-20, 31, 2, 113, 23, 165, 51, 167, +64, 120, 54, 34, 44, -56, 7, -130, +-29, -156, -56, -136, -69, -77, -61, 0, +-33, 72, 4, 114, 28, 114, 51, 76, +48, 20, 13, -34, -12, -69, -34, -81, +-39, -60, -18, -26, 21, 11, 53, 38, +73, 54, 66, 49, 24, 34, -26, 14, +-74, -2, -110, -13, -99, -14, -55, -18, +10, -22, 76, -34, 120, -45, 113, -56, +73, -53, 14, -36, -48, 3, -88, 57, +-87, 113, -61, 145, -10, 139, 43, 90, +66, 7, 58, -96, 38, -185, -8, -230, +-44, -207, -56, -124, -39, 6, -10, 141, +31, 245, 51, 275, 45, 222, 28, 101, +-12, -49, -44, -181, -49, -249, -43, -240, +-11, -158, 26, -37, 54, 88, 51, 168, +40, 186, 9, 147, -36, 74, -54, -11, +-53, -74, -32, -100, 5, -90, 34, -55, +49, -16, 40, 7, 21, 18, -17, 15, +-39, 11, -42, 11, -34, 24, -4, 36, +28, 47, 43, 44, 42, 29, 25, 0, +-6, -28, -39, -52, -53, -64, -55, -64, +-36, -46, -1, -21, 34, 9, 63, 34, +77, 60, 58, 74, 27, 78, -14, 61, +-53, 26, -71, -24, -72, -68, -55, -102, +-20, -106, 18, -76, 50, -14, 66, 52, +67, 106, 43, 122, 12, 95, -21, 31, +-46, -42, -47, -103, -37, -121, -15, -91, +3, -24, 10, 51, 14, 110, 2, 124, +-2, 91, -5, 18, 2, -57, 12, -112, +25, -120, 39, -89, 40, -25, 25, 39, +-1, 81, -30, 84, -49, 60, -59, 19, +-39, -20, -13, -42, 24, -37, 49, -18, +54, 5, 48, 11, 29, 0, -4, -24, +-27, -43, -44, -48, -45, -24, -32, 22, +-8, 74, 9, 107, 30, 106, 38, 61, +33, -7, 21, -82, 9, -129, -14, -135, +-26, -95, -39, -26, -51, 51, -48, 102, +-31, 118, -3, 89, 37, 37, 72, -13, +88, -40, 78, -45, 58, -21, 4, 9, +-54, 29, -98, 19, -121, -13, -110, -54, +-69, -77, -10, -79, 49, -47, 98, 8, +117, 67, 99, 107, 73, 122, 18, 102, +-34, 55, -58, -10, -67, -67, -63, -102, +-52, -101, -41, -84, -31, -53, -12, -16, +5, 22, 20, 50, 51, 72, 72, 79, +82, 76, 80, 52, 53, 14, 7, -36, +-46, -74, -95, -94, -124, -87, -118, -54, +-78, 5, -27, 63, 38, 100, 99, 104, +128, 78, 121, 24, 93, -37, 34, -88, +-20, -106, -64, -93, -93, -51, -99, -7, +-72, 32, -43, 52, -10, 55, 29, 42, +49, 28, 55, 18, 63, 18, 50, 23, +40, 27, 26, 14, 13, -14, -9, -51, +-31, -79, -59, -96, -81, -83, -86, -46, +-72, 7, -40, 57, 20, 94, 77, 103, +128, 86, 146, 46, 135, 1, 75, -37, +-12, -52, -102, -56, -170, -44, -191, -27, +-154, -9, -82, -5, 23, -9, 119, -18, +177, -19, 186, -11, 152, 13, 73, 41, +-17, 74, -98, 94, -152, 93, -159, 55, +-125, -3, -77, -75, -22, -132, 25, -160, +59, -142, 93, -84, 121, 9, 136, 106, +128, 184, 91, 210, 30, 177, -55, 83, +-138, -42, -196, -160, -220, -226, -183, -230, +-90, -161, 34, -47, 155, 79, 241, 172, +258, 207, 204, 175, 101, 100, -30, 4, +-135, -72, -188, -109, -191, -99, -141, -62, +-73, -16, -8, 2, 43, -9, 68, -41, +72, -67, 65, -68, 65, -23, 64, 58, +68, 147, 62, 200, 33, 195, -24, 116, +-91, -18, -135, -166, -141, -262, -113, -270, +-37, -184, 49, -36, 126, 124, 166, 232, +150, 253, 81, 173, -6, 34, -99, -113, +-150, -201, -149, -202, -94, -113, -13, 21, +73, 148, 124, 204, 135, 173, 98, 63, +33, -76, -41, -187, -87, -220, -104, -169, +-76, -46, -33, 91, 24, 189, 62, 208, +72, 152, 50, 37, 7, -87, -41, -175, +-61, -191, -60, -138, -27, -34, 21, 74, +63, 151, 80, 167, 82, 126, 49, 44, +1, -37, -44, -99, -87, -115, -103, -96, +-82, -47, -46, 2, 2, 35, 47, 42, +67, 30, 65, 8, 51, -10, 31, -20, +13, -7, 0, 19, -10, 50, -13, 65, +-8, 60, -5, 32, -13, -8, -23, -52, +-32, -84, -36, -101, -28, -92, -2, -66, +25, -27, 45, 16, 56, 56, 38, 77, +13, 84, -7, 72, -30, 58, -32, 41, +-19, 28, -8, 9, 10, -11, 24, -37, +17, -65, 2, -97, -12, -114, -37, -109, +-43, -70, -29, -8, -6, 70, 26, 132, +48, 165, 43, 151, 26, 97, -3, 11, +-19, -74, -33, -134, -27, -140, -11, -100, +7, -26, 26, 43, 41, 87, 28, 80, +9, 34, -20, -32, -44, -82, -56, -95, +-36, -58, -20, 15, 11, 100, 33, 152, +38, 150, 32, 82, 29, -21, 6, -129, +1, -190, -5, -190, -5, -121, -1, -9, +2, 111, -5, 189, -7, 200, -15, 143, +-27, 49, -36, -59, -24, -140, -7, -173, +14, -146, 19, -82, 18, -4, 12, 55, +5, 95, 11, 102, 14, 88, 24, 64, +33, 41, 22, 20, 9, 2, -13, -29, +-45, -61, -66, -92, -73, -105, -61, -96, +-27, -58, 22, -4, 55, 58, 75, 105, +71, 126, 39, 109, 8, 67, -27, 15, +-53, -30, -47, -63, -31, -66, -5, -53, +17, -30, 30, -11, 28, 6, 9, 7, +-12, 5, -34, -2, -52, -6, -49, -8, +-29, -5, -2, 1, 25, 17, 50, 31, +66, 44, 76, 48, 78, 50, 41, 33, +-3, 1, -55, -46, -106, -86, -125, -111, +-111, -105, -70, -64, 0, 6, 70, 75, +134, 127, 157, 136, 139, 105, 64, 32, +-27, -49, -114, -114, -166, -133, -163, -106, +-110, -39, -26, 37, 71, 97, 131, 118, +165, 100, 132, 46, 71, -13, -8, -60, +-84, -78, -125, -73, -125, -46, -105, -21, +-49, -4, 8, -2, 51, 0, 68, 4, +80, 21, 67, 48, 55, 81, 41, 95, +18, 80, -5, 35, -37, -26, -69, -93, +-73, -133, -73, -137, -53, -94, -30, -25, +2, 49, 39, 100, 63, 113, 78, 83, +70, 30, 44, -30, 13, -61, -16, -56, +-38, -21, -50, 24, -47, 66, -45, 74, +-31, 50, 0, 0, 8, -52, 26, -94, +34, -104, 19, -82, 10, -36, 0, 11, +-8, 52, -2, 70, 10, 71, 22, 58, +22, 47, 16, 33, -8, 21, -29, 0, +-44, -24, -56, -57, -46, -86, -22, -105, +23, -92, 67, -50, 93, 20, 99, 88, +61, 137, 10, 136, -35, 89, -81, 4, +-96, -84, -96, -153, -75, -171, -37, -129, +17, -37, 59, 73, 92, 174, 104, 221, +84, 203, 59, 111, 35, -14, -21, -140, +-58, -227, -98, -256, -118, -208, -107, -107, +-68, 22, -8, 138, 60, 214, 107, 229, +132, 185, 108, 95, 62, -4, -15, -92, +-73, -140, -107, -146, -97, -112, -58, -60, +-2, -3, 49, 34, 72, 46, 60, 33, +34, 12, -28, -7, -57, -3, -60, 17, +-37, 53, 17, 79, 59, 85, 70, 52, +59, -11, 17, -85, -39, -140, -82, -160, +-90, -125, -73, -43, -10, 61, 69, 147, +124, 192, 146, 167, 107, 88, 32, -27, +-59, -132, -136, -196, -169, -189, -161, -123, +-99, -17, -6, 89, 79, 162, 152, 176, +168, 138, 140, 57, 80, -28, 9, -94, +-58, -117, -98, -100, -103, -54, -95, -7, +-64, 32, -31, 41, -15, 23, 18, -4, +29, -18, 39, -18, 60, 1, 60, 27, +57, 52, 42, 55, 23, 39, -2, 3, +-31, -30, -56, -54, -73, -51, -69, -31, +-42, -3, -5, 16, 33, 22, 43, 8, +52, -12, 36, -35, 26, -39, 16, -27, +-9, 7, -18, 39, -19, 61, -27, 64, +-14, 46, -16, 7, -8, -30, -7, -51, +5, -48, 18, -33, 44, -4, 56, 18, +52, 25, 39, 4, 11, -26, -41, -57, +-73, -64, -112, -48, -109, -8, -81, 41, +-27, 88, 44, 114, 107, 109, 160, 69, +184, 14, 146, -48, 77, -93, -29, -119, +-126, -111, -198, -83, -217, -39, -188, 4, +-118, 42, -11, 63, 90, 72, 179, 71, +221, 65, 192, 50, 134, 39, 36, 24, +-62, 12, -126, -14, -165, -43, -159, -80, +-126, -107, -68, -117, -5, -101, 58, -56, +104, 17, 120, 96, 119, 159, 93, 180, +49, 156, -6, 81, -73, -18, -108, -122, +-129, -185, -110, -191, -57, -132, 1, -32, +75, 79, 124, 153, 125, 172, 94, 124, +21, 34, -54, -67, -107, -129, -116, -138, +-89, -86, -30, -1, 38, 90, 72, 140, +92, 127, 63, 58, -1, -34, -55, -119, +-91, -155, -77, -129, -19, -46, 45, 58, +103, 145, 108, 171, 87, 137, 19, 48, +-60, -54, -124, -135, -155, -157, -140, -123, +-70, -52, 23, 24, 108, 80, 154, 89, +168, 63, 114, 14, 54, -18, -28, -24, +-100, 4, -130, 47, -132, 83, -106, 75, +-44, 27, 6, -55, 57, -137, 88, -186, +100, -173, 77, -99, 44, 20, 2, 133, +-35, 210, -48, 214, -46, 153, -36, 46, +-20, -60, -15, -136, 5, -157, 5, -123, +3, -54, 0, 12, -11, 57, 3, 64, +14, 40, 25, -3, 36, -34, 21, -44, +-4, -20, -24, 18, -31, 58, -35, 78, +-23, 76, -4, 44, 3, -1, 24, -49, +20, -78, 6, -87, -4, -68, -23, -40, +-21, 0, -5, 36, 8, 61, 26, 65, +29, 55, 26, 29, -1, 4, -28, -22, +-44, -42, -40, -54, -13, -49, 15, -37, +42, -16, 49, -2, 39, 18, 19, 31, +-17, 43, -32, 46, -43, 49, -46, 43, +-14, 26, 7, -8, 28, -53, 34, -103, +12, -131, -18, -130, -27, -89, -17, -15, +10, 88, 39, 176, 59, 225, 49, 209, +34, 126, -17, -3, -64, -138, -103, -240, +-115, -266, -86, -212, -29, -91, 37, 50, +104, 169, 124, 223, 124, 205, 75, 118, +18, 10, -44, -83, -87, -124, -106, -113, +-88, -61, -56, 0, -27, 46, -3, 51, +17, 23, 13, -25, 25, -55, 17, -54, +22, -16, 45, 38, 61, 93, 70, 112, +58, 83, 14, 11, -40, -72, -96, -140, +-121, -158, -120, -120, -86, -31, -30, 68, +38, 152, 98, 176, 128, 145, 123, 62, +71, -38, 4, -123, -56, -161, -101, -145, +-102, -79, -75, 5, -38, 83, 20, 122, +55, 120, 70, 73, 61, 11, 25, -50, +-22, -85, -53, -93, -66, -67, -61, -19, +-33, 34, 3, 76, 29, 96, 55, 83, +50, 47, 32, -11, 9, -65, -17, -106, +-27, -116, -35, -97, -26, -45, -11, 23, +-2, 91, 13, 132, 14, 138, 0, 101, +-18, 36, -36, -44, -41, -105, -33, -139, +-11, -126, 0, -80, 24, -8, 40, 58, +45, 107, 53, 121, 41, 102, 11, 58, +-11, 11, -50, -37, -66, -75, -80, -95, +-82, -92, -77, -79, -43, -49, 0, -12, +51, 36, 93, 78, 123, 111, 113, 123, +84, 105, 21, 55, -38, -14, -103, -84, +-131, -132, -129, -152, -94, -129, -31, -79, +34, -7, 76, 56, 110, 103, 89, 120, +44, 111, -13, 80, -64, 45, -91, 7, +-71, -26, -37, -55, 2, -73, 45, -92, +68, -95, 70, -86, 62, -50, 16, 5, +-33, 66, -70, 110, -94, 128, -90, 109, +-73, 57, -43, -13, -9, -76, 30, -116, +73, -116, 104, -82, 114, -17, 92, 48, +39, 94, -28, 100, -90, 73, -134, 21, +-148, -31, -115, -66, -58, -71, 11, -53, +78, -17, 106, 14, 103, 31, 81, 25, +25, 15, -31, -1, -65, -6, -76, 0, +-59, 19, -22, 35, 7, 42, 17, 32, +10, 1, -7, -42, -17, -75, -19, -89, +-16, -72, -2, -32, 15, 23, 24, 69, +31, 96, 18, 87, 2, 53, -29, 5, +-53, -38, -52, -66, -39, -66, -25, -45, +3, -14, 23, 9, 41, 27, 45, 25, +40, 13, 17, -5, -1, -16, -34, -16, +-57, 1, -70, 19, -69, 31, -53, 30, +-17, 19, 13, -7, 51, -32, 64, -48, +60, -41, 35, -22, 3, 10, -32, 38, +-55, 61, -70, 59, -56, 31, -28, -10, +4, -48, 24, -75, 29, -77, 10, -53, +-1, -10, -16, 37, -28, 78, -23, 90, +-14, 77, -5, 38, 14, -11, 18, -58, +15, -82, 1, -80, -21, -51, -33, -10, +-33, 31, -27, 56, -19, 63, -9, 46, +-4, 20, -1, -13, 5, -35, 5, -43, +7, -32, 0, -15, -1, 1, -1, 12, +-12, 18, -16, 14, -24, 15, -29, 18, +-24, 25, -21, 21, -10, 10, 7, -10, +10, -30, 2, -53, 0, -65, -13, -54, +-30, -18, -32, 35, -28, 88, -15, 117, +4, 111, 9, 64, 17, -7, 16, -83, +3, -129, -21, -137, -40, -99, -58, -30, +-56, 48, -35, 104, 2, 123, 31, 100, +49, 48, 51, -18, 40, -65, 10, -83, +-20, -64, -56, -27, -78, 13, -80, 31, +-59, 26, -29, -4, 18, -38, 47, -56, +58, -39, 54, 6, 32, 64, 1, 108, +-21, 120, -47, 82, -52, 5, -47, -89, +-40, -160, -32, -184, -16, -143, -10, -52, +-3, 65, 3, 160, 11, 203, 18, 178, +29, 99, 30, -15, 20, -111, -10, -164, +-46, -154, -73, -100, -84, -16, -73, 60, +-47, 106, -14, 106, 29, 70, 55, 14, +69, -36, 64, -66, 29, -61, -15, -38, +-51, -4, -75, 23, -81, 41, -68, 43, +-53, 38, -30, 26, 3, 14, 23, -1, +38, -11, 38, -26, 26, -45, 18, -63, +3, -66, -15, -55, -34, -19, -49, 27, +-52, 78, -49, 108, -34, 114, -18, 88, +-2, 37, 8, -31, 20, -94, 21, -132, +3, -127, -20, -91, -38, -32, -41, 26, +-22, 79, -6, 105, 19, 107, 30, 77, +29, 29, 14, -20, -12, -55, -56, -75, +-85, -69, -97, -46, -79, -16, -34, 9, +25, 29, 66, 29, 94, 18, 86, -2, +52, -12, -9, -9, -69, 8, -111, 27, +-116, 47, -98, 53, -52, 40, -2, 1, +45, -46, 67, -88, 64, -102, 33, -89, +2, -42, -35, 23, -55, 88, -64, 126, +-63, 130, -55, 92, -38, 29, -26, -40, +-3, -91, 26, -112, 44, -94, 49, -51, +43, 0, 21, 33, -7, 44, -46, 33, +-86, 13, -110, -5, -114, -1, -87, 18, +-34, 45, 21, 67, 61, 70, 79, 38, +81, -19, 66, -84, 32, -128, -6, -143, +-39, -109, -63, -39, -83, 51, -84, 124, +-80, 157, -66, 139, -44, 78, -22, -6, +9, -79, 39, -126, 53, -129, 65, -92, +55, -26, 30, 41, -4, 91, -33, 107, +-60, 91, -80, 44, -78, -12, -68, -61, +-47, -90, -30, -93, -16, -64, -1, -21, +6, 25, 12, 60, 15, 81, 13, 76, +19, 56, 9, 20, 10, -16, -1, -42, +-17, -51, -32, -50, -39, -39, -50, -26, +-60, -13, -64, -7, -61, -4, -49, -4, +-14, 5, 6, 21, 43, 49, 57, 70, +62, 74, 48, 51, 18, 14, -30, -37, +-72, -88, -101, -118, -98, -108, -82, -67, +-41, -1, -8, 64, 34, 107, 54, 107, +55, 75, 28, 22, -9, -32, -47, -67, +-72, -67, -79, -37, -59, 6, -48, 44, +-22, 62, 3, 41, 26, -1, 31, -48, +26, -76, 12, -82, 2, -50, -14, 8, +-33, 67, -46, 101, -55, 103, -72, 67, +-71, 6, -57, -57, -36, -97, -8, -107, +18, -79, 40, -30, 52, 29, 51, 70, +39, 86, 18, 70, -18, 38, -53, -2, +-79, -31, -93, -44, -98, -39, -90, -27, +-67, -8, -31, 0, -3, 0, 31, -10, +60, -16, 71, -21, 66, -9, 47, 18, +11, 48, -21, 66, -50, 73, -76, 57, +-93, 19, -99, -31, -102, -74, -81, -108, +-52, -116, -17, -93, 20, -41, 52, 23, +73, 87, 75, 127, 66, 134, 38, 102, +1, 47, -49, -16, -89, -70, -110, -101, +-114, -95, -105, -66, -84, -24, -55, 12, +-9, 31, 21, 22, 60, 3, 74, -16, +76, -22, 65, -7, 42, 32, 2, 77, +-51, 105, -101, 96, -134, 57, -150, -15, +-127, -97, -88, -157, -12, -170, 54, -137, +110, -55, 132, 45, 116, 128, 59, 167, +-23, 158, -111, 99, -162, 18, -185, -56, +-151, -96, -87, -103, 9, -75, 85, -31, +141, 10, 144, 29, 96, 27, 12, 9, +-84, -9, -153, -18, -179, 0, -173, 29, +-113, 54, -33, 64, 46, 53, 100, 12, +120, -41, 105, -83, 59, -96, -7, -77, +-69, -26, -112, 36, -127, 87, -128, 105, +-94, 89, -59, 38, -18, -29, 25, -85, +57, -106, 77, -94, 69, -47, 43, 19, +3, 81, -49, 110, -93, 103, -119, 59, +-117, -5, -89, -69, -50, -106, 3, -109, +46, -74, 71, -15, 57, 51, 26, 97, +-16, 115, -59, 96, -77, 51, -86, -9, +-77, -64, -55, -104, -24, -116, 9, -98, +26, -48, 27, 9, 11, 62, 0, 97, +-12, 109, -25, 90, -33, 51, -39, 1, +-42, -47, -52, -81, -62, -87, -54, -78, +-42, -56, -24, -25, -7, 14, 12, 44, +29, 62, 32, 67, 27, 65, 1, 50, +-31, 30, -67, 2, -77, -29, -83, -56, +-79, -74, -56, -81, -20, -69, 9, -38, +25, 9, 26, 51, 24, 82, 1, 96, +-28, 87, -55, 50, -58, 4, -56, -41, +-39, -74, -18, -88, 3, -74, 10, -40, +1, -1, -18, 27, -34, 48, -67, 51, +-74, 39, -71, 17, -39, -4, -10, -22, +24, -24, 43, -14, 48, 2, 26, 18, +-12, 31, -47, 29, -73, 15, -104, -7, +-102, -26, -84, -46, -48, -57, -8, -55, +26, -35, 53, -3, 59, 35, 47, 67, +25, 81, -18, 73, -60, 50, -104, 12, +-111, -30, -107, -66, -79, -76, -44, -70, +2, -47, 48, -17, 68, 14, 67, 32, +45, 40, -5, 38, -52, 29, -96, 19, +-108, 13, -96, 9, -74, 4, -39, -9, +-2, -21, 33, -40, 42, -51, 39, -46, +16, -21, -25, 11, -49, 45, -67, 69, +-65, 67, -56, 32, -40, -12, -18, -57, +-3, -86, 4, -84, -1, -41, -11, 19, +-23, 78, -45, 109, -49, 102, -46, 53, +-37, -19, -26, -88, -17, -128, -4, -124, +-6, -72, 2, 4, -3, 81, -14, 125, +-24, 127, -41, 82, -50, 15, -60, -51, +-65, -93, -63, -100, -45, -70, -21, -20, +0, 29, 22, 52, 37, 53, 29, 28, +3, -1, -42, -20, -73, -13, -93, 8, +-96, 38, -78, 62, -42, 62, 6, 25, +43, -30, 62, -87, 47, -125, 1, -129, +-53, -85, -97, -12, -112, 69, -109, 132, +-70, 164, -18, 140, 39, 77, 71, -3, +77, -77, 54, -129, 12, -137, -53, -106, +-96, -51, -120, 8, -115, 57, -102, 74, +-68, 59, -31, 21, 10, -13, 41, -32, +55, -22, 57, 16, 43, 62, 18, 91, +-7, 97, -51, 64, -93, -5, -135, -94, +-145, -160, -136, -189, -96, -162, -36, -79, +41, 42, 100, 150, 131, 218, 114, 232, +65, 183, -25, 73, -104, -53, -175, -157, +-193, -211, -163, -205, -96, -137, -2, -39, +74, 55, 113, 123, 105, 146, 64, 120, +-1, 67, -78, 10, -122, -33, -136, -55, +-109, -49, -66, -28, -15, -8, 34, -6, +51, -12, 38, -26, 8, -35, -26, -28, +-43, 1, -62, 35, -60, 64, -51, 79, +-38, 68, -28, 24, -22, -31, -16, -81, +-31, -106, -29, -100, -24, -53, -8, 13, +1, 80, -2, 121, -3, 126, -18, 89, +-51, 26, -71, -45, -80, -106, -69, -142, +-55, -130, -28, -79, 10, -7, 37, 63, +47, 123, 24, 144, -5, 124, -47, 71, +-83, 4, -99, -65, -103, -115, -76, -129, +-43, -106, 2, -57, 39, 6, 53, 58, +49, 85, 26, 84, -15, 65, -63, 27, +-94, -9, -104, -29, -96, -32, -71, -26, +-39, -11, -6, 0, 30, -2, 31, -18, +29, -27, 2, -28, -16, -17, -37, 5, +-42, 43, -46, 69, -52, 75, -56, 55, +-54, 15, -56, -36, -55, -81, -48, -98, +-24, -82, -6, -46, 18, 12, 27, 64, +30, 94, 14, 88, -19, 59, -52, 12, +-64, -28, -72, -48, -61, -45, -54, -30, +-37, -10, -42, 4, -35, 0, -42, -24, +-34, -45, -26, -50, -8, -31, 26, 8, +61, 64, 70, 112, 51, 133, 0, 114, +-69, 56, -146, -31, -187, -117, -183, -172, +-137, -179, -60, -141, 28, -53, 107, 51, +148, 136, 137, 177, 84, 173, -2, 118, +-76, 36, -142, -45, -156, -104, -139, -134, +-99, -123, -47, -82, 1, -30, 32, 14, +34, 50, 26, 65, 6, 62, -11, 46, +-25, 32, -30, 17, -25, 1, -19, -11, +-33, -23, -40, -37, -54, -42, -57, -40, +-61, -29, -54, -12, -39, 19, -27, 47, +-8, 63, 2, 60, 13, 40, 8, 1, +-2, -42, -11, -73, -24, -83, -36, -70, +-52, -29, -59, 23, -64, 72, -72, 99, +-61, 102, -34, 71, -10, 15, 8, -46, +12, -90, 19, -113, 9, -105, -4, -65, +-27, -5, -48, 51, -58, 96, -70, 118, +-55, 106, -49, 61, -37, 9, -36, -45, +-29, -87, -24, -106, -15, -94, -4, -65, +18, -24, 26, 21, 27, 64, 4, 87, +-17, 92, -61, 79, -108, 48, -138, 2, +-135, -36, -98, -65, -44, -82, 27, -82, +92, -55, 114, -18, 113, 18, 65, 50, +-4, 71, -96, 66, -156, 42, -182, 8, +-157, -25, -106, -50, -27, -52, 46, -38, +99, -16, 101, 11, 80, 33, 29, 37, +-28, 27, -92, 7, -125, -18, -118, -39, +-91, -41, -48, -27, -9, -1, 20, 21, +33, 38, 29, 42, 16, 33, -13, 14, +-35, -6, -62, -27, -69, -39, -71, -38, +-63, -31, -45, -23, -18, -6, -3, 13, +7, 33, 10, 48, 19, 59, 13, 53, +-5, 32, -35, 3, -64, -30, -77, -72, +-86, -99, -74, -98, -59, -72, -22, -30, +7, 35, 32, 95, 45, 130, 32, 128, +4, 101, -34, 44, -66, -27, -87, -85, +-87, -117, -66, -123, -36, -99, -12, -52, +7, 3, 13, 45, 9, 73, -22, 83, +-46, 75, -54, 52, -46, 29, -22, 6, +-5, -12, 14, -28, 12, -39, -1, -50, +-30, -57, -59, -55, -82, -38, -96, -14, +-78, 16, -41, 44, 3, 64, 40, 66, +64, 56, 57, 29, 22, -9, -28, -39, +-61, -59, -95, -68, -101, -53, -100, -21, +-66, 13, -23, 36, 11, 54, 30, 52, +33, 30, 24, -1, -4, -22, -26, -34, +-42, -35, -53, -22, -47, 2, -46, 23, +-40, 36, -44, 36, -42, 18, -39, -16, +-31, -42, -28, -56, -6, -48, 14, -24, +40, 16, 28, 54, 7, 81, -37, 83, +-70, 56, -101, 6, -109, -42, -95, -75, +-63, -86, -11, -76, 40, -39, 71, 7, +70, 46, 36, 64, -11, 64, -62, 43, +-96, 11, -104, -15, -79, -28, -42, -30, +-9, -15, 15, 5, 28, 19, 9, 17, +-18, 4, -55, -17, -63, -36, -62, -47, +-34, -40, -1, -23, 27, 5, 36, 38, +17, 65, -9, 71, -46, 61, -76, 37, +-94, 5, -86, -35, -62, -61, -31, -73, +-2, -68, 21, -49, 22, -19, 14, 11, +-3, 39, -10, 58, -10, 64, -18, 51, +-18, 30, -26, 4, -33, -19, -55, -41, +-68, -49, -79, -43, -83, -27, -68, -7, +-37, 14, 10, 28, 46, 34, 71, 32, +73, 24, 47, 7, 0, -8, -50, -23, +-91, -36, -113, -46, -121, -39, -98, -19, +-56, 9, -8, 38, 28, 64, 43, 74, +52, 64, 28, 37, 2, 0, -35, -53, +-47, -98, -56, -116, -55, -100, -45, -62, +-31, 2, -24, 66, -23, 113, -23, 132, +-22, 119, -19, 72, -6, 10, 5, -48, +4, -87, -9, -108, -28, -101, -44, -74, +-61, -44, -72, -14, -66, 24, -54, 55, +-11, 74, 21, 85, 57, 89, 62, 78, +47, 54, 0, 15, -41, -36, -85, -86, +-118, -121, -125, -135, -99, -117, -64, -68, +-14, 5, 31, 78, 71, 129, 85, 151, +63, 144, 22, 101, -20, 29, -53, -50, +-84, -111, -103, -147, -93, -142, -75, -100, +-41, -33, -16, 39, 14, 102, 15, 131, +16, 119, 3, 72, -9, 11, -20, -53, +-25, -96, -25, -101, -16, -73, -11, -22, +-4, 37, -2, 76, -15, 84, -42, 55, +-70, 7, -77, -45, -76, -86, -52, -92, +-20, -56, 20, 2, 53, 65, 62, 105, +54, 110, 17, 71, -28, 6, -80, -64, +-109, -113, -112, -128, -82, -100, -36, -38, +16, 34, 54, 94, 66, 126, 51, 111, +19, 63, -29, 2, -77, -51, -100, -84, +-100, -85, -66, -62, -33, -30, 12, -2, +45, 19, 56, 27, 43, 22, 15, 15, +-16, 14, -52, 15, -68, 27, -78, 39, +-68, 43, -51, 26, -31, -2, -14, -36, +1, -67, 3, -81, 5, -67, 2, -36, +1, 4, -8, 45, -15, 76, -14, 82, +-17, 66, -20, 31, -28, -13, -29, -52, +-33, -68, -37, -62, -37, -39, -38, -6, +-32, 29, -34, 47, -21, 48, -17, 37, +-3, 10, 10, -25, 26, -41, 17, -39, +13, -24, 0, -5, -9, 22, -37, 39, +-63, 41, -84, 24, -81, 1, -68, -21, +-52, -32, -26, -29, 3, -15, 39, -3, +59, 8, 66, 12, 54, 11, 18, 2, +-21, -6, -62, -7, -85, 0, -99, 12, +-87, 24, -68, 26, -37, 16, -9, -7, +23, -31, 34, -51, 37, -52, 20, -34, +9, 3, -3, 40, -11, 69, -21, 79, +-41, 61, -52, 20, -65, -30, -63, -72, +-56, -88, -36, -71, -13, -31, 13, 16, +34, 59, 39, 79, 33, 67, 6, 31, +-27, -13, -59, -50, -75, -64, -73, -52, +-39, -19, -7, 21, 22, 51, 31, 56, +32, 38, 11, -1, -19, -40, -46, -65, +-63, -65, -58, -39, -44, 6, -14, 50, +10, 75, 22, 75, 14, 50, -6, 3, +-26, -46, -41, -78, -39, -81, -23, -63, +3, -24, 20, 22, 30, 60, 18, 71, +-7, 62, -53, 35, -80, -6, -87, -42, +-62, -60, -31, -59, 13, -38, 50, -8, +67, 21, 61, 35, 27, 39, -17, 28, +-58, 7, -79, -15, -79, -27, -53, -31, +-18, -23, 8, -6, 18, 14, 9, 25, +-5, 30, -25, 28, -35, 21, -44, 6, +-33, -9, -17, -23, 18, -35, 31, -44, +36, -39, 12, -24, -18, -5, -44, 17, +-59, 46, -61, 66, -45, 71, -21, 56, +-9, 29, 1, -12, 3, -55, -1, -89, +-9, -99, -20, -83, -25, -46, -14, 3, +4, 56, 18, 97, 30, 110, 18, 93, +-5, 60, -46, 15, -71, -29, -92, -64, +-86, -81, -66, -80, -29, -65, 12, -44, +51, -19, 80, 3, 82, 23, 63, 44, +24, 63, -20, 73, -58, 75, -84, 66, +-98, 42, -93, -3, -78, -54, -49, -97, +-11, -122, 21, -119, 46, -83, 58, -24, +67, 44, 51, 103, 31, 137, -11, 136, +-45, 105, -80, 47, -97, -19, -100, -76, +-85, -108, -51, -116, -5, -99, 41, -62, +73, -13, 87, 32, 75, 62, 45, 78, +-5, 81, -51, 65, -83, 40, -98, 10, +-102, -18, -87, -44, -50, -62, -5, -62, +42, -48, 66, -26, 81, 8, 64, 41, +36, 57, -2, 54, -31, 34, -59, 0, +-76, -31, -89, -51, -84, -51, -57, -37, +-19, -7, 20, 28, 46, 54, 59, 62, +55, 48, 44, 18, 18, -16, -11, -45, +-43, -58, -71, -54, -77, -34, -71, -4, +-45, 24, -18, 40, 11, 42, 20, 33, +28, 15, 18, -3, 15, -16, 0, -18, +-11, -11, -19, -4, -15, 5, -14, 10, +-9, 9, -7, 1, -20, -7, -34, -20, +-46, -30, -42, -30, -28, -26, -8, -10, +16, 13, 40, 34, 56, 50, 50, 56, +29, 50, -15, 30, -47, -2, -80, -40, +-87, -69, -82, -81, -52, -74, -18, -47, +21, -5, 44, 37, 61, 71, 59, 90, +37, 87, 12, 59, -8, 19, -22, -20, +-33, -53, -45, -74, -61, -77, -67, -71, +-65, -55, -46, -32, -22, -3, 9, 28, +48, 60, 70, 85, 86, 94, 79, 87, +55, 65, -3, 23, -58, -31, -112, -87, +-129, -128, -113, -142, -73, -117, -23, -62, +29, 13, 62, 88, 76, 145, 69, 165, +40, 141, 13, 77, -17, -6, -34, -85, +-41, -140, -30, -155, -20, -123, -21, -58, +-29, 17, -39, 81, -34, 113, -27, 108, +-6, 77, 9, 23, 29, -32, 40, -73, +41, -86, 24, -72, 8, -36, -22, 7, +-46, 44, -53, 61, -46, 60, -24, 43, +-5, 14, 12, -14, 17, -31, 17, -40, +4, -41, -8, -35, -20, -26, -26, -18, +-15, -10, -6, 2, 4, 21, 5, 40, +4, 55, -5, 60, -8, 52, -16, 31, +-6, 0, -7, -33, -6, -60, -10, -75, +-8, -69, -14, -47, -24, -15, -36, 16, +-40, 38, -25, 52, -6, 55, 20, 49, +45, 39, 55, 25, 49, 11, 25, -7, +-8, -27, -35, -49, -55, -65, -75, -71, +-72, -63, -56, -40, -14, -3, 20, 44, +47, 84, 53, 103, 50, 95, 27, 61, +9, 10, -11, -43, -27, -83, -32, -103, +-34, -94, -34, -58, -31, -9, -19, 35, +-10, 61, 3, 68, 5, 57, 14, 35, +24, 9, 26, -14, 27, -27, 15, -30, +-5, -23, -34, -16, -48, -14, -52, -16, +-33, -19, -12, -20, 18, -15, 45, -4, +61, 13, 52, 33, 25, 45, -16, 48, +-54, 43, -81, 24, -92, -5, -68, -34, +-32, -56, 20, -67, 64, -63, 88, -45, +88, -18, 64, 19, 18, 52, -26, 69, +-52, 72, -70, 59, -65, 30, -58, -5, +-43, -37, -27, -58, -2, -64, 6, -56, +19, -36, 24, -9, 39, 17, 57, 35, +65, 44, 60, 41, 34, 30, -10, 14, +-63, -1, -103, -13, -120, -17, -102, -16, +-69, -13, -21, -8, 36, -7, 88, -10, +125, -16, 124, -17, 86, -12, 22, -4, +-33, 7, -87, 21, -101, 37, -99, 43, +-67, 37, -33, 22, 1, 1, 29, -28, +57, -51, 65, -63, 51, -60, 28, -41, +-3, -8, -22, 28, -35, 60, -38, 73, +-30, 65, -19, 42, -11, 6, 5, -34, +22, -64, 31, -76, 38, -68, 13, -38, +-5, 0, -26, 33, -34, 58, -42, 68, +-37, 62, -31, 40, -7, 11, 11, -21, +28, -47, 43, -60, 46, -60, 37, -48, +18, -25, -6, 1, -28, 25, -33, 41, +-41, 49, -34, 48, -24, 40, -16, 22, +-5, 0, -1, -22, 9, -40, 23, -51, +34, -49, 27, -37, 23, -16, 8, 6, +4, 23, -3, 30, -12, 32, -21, 26, +-25, 17, -32, 6, -25, -1, -12, -5, +-1, -5, 14, -7, 7, -8, 2, -10, +4, -17, 11, -21, 12, -20, 12, -16, +6, -7, 5, 4, 8, 15, 3, 26, +5, 32, -5, 30, -15, 24, -34, 15, +-38, 2, -34, -13, -14, -25, -10, -34, +-5, -36, 1, -36, 13, -29, 33, -16, +45, 8, 46, 37, 38, 61, 22, 76, +-5, 74, -26, 54, -50, 15, -69, -32, +-83, -76, -85, -105, -56, -109, -11, -86, +43, -38, 82, 23, 113, 82, 108, 124, +88, 139, 33, 120, -25, 71, -76, -1, +-106, -75, -112, -133, -85, -157, -48, -138, +1, -89, 44, -22, 63, 50, 74, 106, +65, 136, 41, 134, 13, 99, -7, 44, +-19, -15, -19, -66, -21, -97, -30, -103, +-30, -86, -37, -53, -33, -14, -28, 21, +-7, 46, 19, 55, 50, 54, 61, 44, +70, 28, 56, 14, 24, 0, -23, -15, +-69, -26, -96, -31, -92, -34, -61, -31, +-18, -20, 35, -5, 73, 11, 99, 25, +95, 34, 62, 37, 18, 33, -40, 18, +-85, -5, -105, -27, -97, -37, -66, -40, +-14, -36, 25, -21, 63, 1, 83, 23, +89, 43, 70, 56, 40, 58, -6, 48, +-46, 25, -77, -9, -91, -45, -76, -73, +-54, -86, -17, -80, 17, -49, 49, -5, +77, 45, 84, 88, 62, 110, 32, 102, +-4, 66, -40, 14, -60, -43, -71, -89, +-52, -115, -20, -110, 16, -72, 34, -17, +51, 38, 39, 81, 18, 100, -14, 91, +-37, 59, -37, 14, -24, -29, -4, -58, +17, -67, 41, -59, 50, -39, 48, -17, +18, 4, -16, 19, -44, 25, -60, 26, +-53, 26, -34, 24, -2, 21, 25, 17, +37, 14, 29, 4, 33, -13, 19, -28, +4, -38, -15, -43, -20, -35, -15, -16, +2, 6, 9, 27, 12, 42, 2, 46, +-18, 37, -26, 20, -32, 2, -22, -15, +-3, -24, 11, -22, 15, -14, 25, -6, +31, 2, 25, 8, 7, 10, -21, 3, +-29, -5, -29, -12, -11, -15, 7, -10, +26, 0, 25, 9, 20, 18, -7, 25, +-26, 29, -40, 29, -51, 24, -42, 7, +-15, -11, 20, -24, 55, -37, 78, -46, +74, -47, 54, -39, 15, -22, -32, 5, +-70, 36, -88, 58, -75, 70, -46, 71, +-15, 57, 18, 26, 51, -13, 54, -49, +56, -76, 36, -87, 21, -75, 5, -47, +-9, -6, -23, 36, -24, 64, -18, 73, +-18, 64, -25, 43, -38, 16, -36, -10, +-21, -24, 2, -28, 30, -18, 55, -6, +63, 1, 58, 0, 30, -8, -3, -23, +-29, -39, -58, -45, -74, -33, -74, -8, +-39, 26, 4, 62, 48, 87, 66, 93, +67, 80, 42, 45, 8, -5, -17, -57, +-35, -100, -37, -124, -32, -119, -28, -85, +-18, -32, 5, 27, 16, 84, 19, 122, +8, 132, 3, 112, 11, 72, 21, 18, +31, -39, 33, -83, 18, -104, -20, -104, +-44, -89, -66, -58, -58, -23, -40, 12, +-11, 44, 20, 68, 60, 83, 85, 86, +93, 76, 66, 54, 19, 16, -26, -33, +-68, -79, -89, -111, -85, -119, -62, -95, +-26, -48, 15, 14, 48, 77, 73, 122, +81, 135, 60, 111, 34, 53, -4, -22, +-29, -89, -52, -127, -57, -128, -54, -91, +-24, -26, -4, 43, 17, 96, 29, 115, +33, 96, 34, 46, 26, -16, 9, -67, +-3, -92, -13, -83, -20, -48, -16, 3, +-14, 50, -3, 76, 6, 70, 6, 39, +4, -3, 2, -42, 7, -65, 6, -65, +8, -43, -4, -7, -1, 27, -6, 48, +-5, 54, -5, 47, -5, 29, -9, 5, +-5, -17, -2, -31, 13, -33, 28, -30, +27, -21, 18, -15, -2, -9, -16, -3, +-25, 5, -29, 17, -34, 29, -22, 34, +-9, 33, 8, 22, 30, 8, 40, -12, +49, -31, 35, -44, 16, -44, -2, -33, +-13, -8, -29, 22, -36, 40, -41, 41, +-32, 29, -14, 4, 8, -24, 28, -43, +42, -42, 42, -27, 29, 0, 17, 28, +-4, 45, -10, 46, -23, 32, -34, 9, +-32, -18, -19, -39, 2, -43, 14, -27, +22, -3, 24, 17, 29, 27, 15, 20, +3, 1, -15, -22, -25, -40, -31, -43, +-24, -26, -13, 9, 10, 53, 20, 87, +28, 92, 36, 67, 31, 20, 22, -43, +5, -99, -18, -128, -39, -119, -47, -75, +-44, -12, -29, 54, -8, 105, 9, 127, +33, 111, 44, 63, 54, 7, 48, -42, +34, -74, 6, -87, -15, -75, -40, -46, +-45, -10, -49, 17, -44, 30, -32, 30, +-9, 23, 16, 16, 40, 15, 54, 17, +55, 22, 48, 22, 21, 14, -4, -3, +-23, -25, -41, -43, -50, -50, -54, -47, +-37, -33, -6, -10, 32, 19, 50, 46, +60, 59, 45, 55, 25, 38, -7, 11, +-33, -21, -46, -50, -37, -59, -28, -52, +-4, -33, 22, -8, 39, 17, 48, 36, +30, 42, 10, 34, -10, 17, -24, -3, +-35, -19, -29, -28, -13, -29, 10, -23, +32, -10, 33, 1, 29, 10, 15, 15, +-5, 16, -22, 14, -27, 8, -22, -1, +-4, -6, 2, -9, 14, -11, 20, -10, +19, -6, 5, 2, -20, 13, -37, 19, +-38, 21, -18, 21, -2, 19, 20, 12, +31, -2, 34, -17, 29, -28, 9, -31, +-6, -26, -16, -14, -29, 4, -40, 22, +-34, 35, -19, 33, 14, 21, 26, 5, +31, -11, 27, -25, 27, -24, 15, -14, +11, 1, 3, 13, -10, 19, -22, 16, +-42, 5, -45, -11, -38, -25, -21, -30, +0, -23, 22, -3, 47, 21, 72, 38, +79, 47, 58, 42, 18, 21, -34, -11, +-74, -40, -100, -58, -96, -59, -67, -42, +-10, -11, 35, 24, 80, 52, 98, 63, +97, 52, 69, 28, 20, 2, -34, -22, +-69, -36, -87, -36, -82, -26, -50, -14, +-13, -2, 22, 5, 40, 8, 40, 4, +39, -3, 33, -3, 22, 9, 15, 22, +13, 36, 1, 45, -7, 36, -23, 9, +-28, -25, -41, -55, -45, -72, -45, -71, +-26, -44, 0, -1, 40, 43, 73, 78, +83, 91, 77, 74, 44, 36, 0, -13, +-41, -62, -68, -91, -78, -90, -70, -64, +-53, -19, -17, 27, 28, 63, 64, 81, +80, 74, 72, 45, 52, 7, 24, -31, +0, -53, -29, -59, -41, -54, -52, -42, +-54, -18, -52, 6, -37, 24, -2, 36, +27, 49, 46, 56, 55, 51, 61, 36, +55, 10, 40, -22, 7, -52, -31, -79, +-59, -89, -73, -74, -70, -35, -44, 12, +-8, 58, 29, 90, 56, 100, 59, 81, +58, 41, 39, -10, 17, -55, -12, -80, +-32, -81, -40, -62, -34, -31, -22, 0, +-7, 22, 5, 32, 7, 28, 9, 15, +14, 6, 16, 6, 20, 16, 23, 27, +22, 30, 24, 19, 12, -2, -8, -35, +-25, -68, -39, -90, -37, -85, -31, -56, +-10, -3, 8, 58, 31, 109, 40, 131, +43, 116, 31, 66, 15, -5, -5, -76, +-22, -126, -32, -141, -26, -116, -18, -60, +-8, 10, -2, 69, 1, 105, 12, 107, +21, 80, 27, 33, 29, -17, 29, -50, +22, -60, 5, -47, -9, -24, -28, -1, +-36, 14, -47, 13, -39, 2, -20, -12, +14, -20, 42, -14, 59, 3, 54, 25, +40, 49, 11, 60, -16, 47, -35, 16, +-52, -13, -53, -41, -35, -54, -10, -50, +16, -28, 41, 0, 44, 27, 36, 39, +19, 35, 1, 20, -9, 2, -18, -11, +-18, -13, -14, -3, -3, 18, 1, 33, +5, 36, -3, 22, -7, -5, -9, -36, +-10, -56, -2, -61, 12, -42, 22, -4, +27, 36, 27, 64, 21, 72, 12, 57, +-7, 28, -24, -12, -33, -48, -26, -68, +-14, -61, 2, -39, 13, -9, 18, 17, +20, 33, 12, 30, 12, 16, 8, 1, +7, -3, 2, 2, -3, 16, -5, 27, +-4, 28, -6, 14, -14, -14, -25, -47, +-27, -75, -14, -85, 8, -70, 31, -27, +42, 33, 46, 87, 34, 114, 19, 105, +-6, 63, -31, -1, -47, -71, -55, -123, +-39, -136, -16, -109, 19, -50, 46, 20, +59, 80, 51, 113, 34, 110, 9, 68, +-14, 9, -39, -45, -53, -78, -51, -87, +-35, -66, -15, -27, 11, 13, 38, 42, +48, 50, 53, 36, 45, 9, 31, -18, +10, -35, -18, -35, -43, -17, -60, 10, +-62, 36, -51, 44, -19, 35, 14, 14, +52, -13, 75, -38, 82, -52, 66, -50, +36, -31, -12, -1, -50, 30, -77, 47, +-77, 53, -57, 46, -28, 32, 10, 10, +43, -9, 68, -21, 71, -27, 57, -25, +25, -18, -7, -9, -29, -3, -39, 1, +-35, 11, -32, 22, -24, 32, -15, 39, +-3, 41, 11, 37, 24, 27, 24, 10, +28, -11, 24, -31, 21, -41, 14, -43, +6, -36, -6, -21, -19, 4, -28, 29, +-32, 53, -19, 66, -8, 67, 7, 49, +15, 19, 21, -15, 25, -45, 26, -65, +20, -68, 10, -56, 3, -30, -5, 5, +-8, 42, -12, 65, -13, 72, -14, 62, +-18, 39, -22, 7, -14, -28, 2, -55, +24, -67, 33, -61, 32, -46, 33, -25, +24, 1, 11, 23, -12, 40, -28, 48, +-36, 43, -30, 29, -21, 10, -8, -14, +11, -40, 26, -59, 29, -65, 22, -62, +16, -45, 11, -15, 4, 19, -3, 42, +-1, 51, 2, 42, 9, 18, 4, -15, +-3, -44, -9, -60, -13, -54, -18, -32, +-21, -3, -12, 19, 3, 30, 23, 22, +33, 1, 36, -24, 30, -41, 17, -43, +0, -29, -15, -2, -21, 30, -21, 53, +-18, 52, -19, 28, -11, -11, 0, -52, +16, -79, 24, -80, 28, -53, 25, -9, +28, 38, 23, 72, 12, 84, -1, 66, +-17, 26, -28, -21, -38, -55, -33, -65, +-14, -46, 8, -8, 21, 35, 26, 63, +26, 70, 20, 53, 8, 16, -8, -25, +-20, -50, -25, -52, -18, -28, -8, 11, +11, 54, 20, 84, 25, 89, 11, 68, +-9, 32, -22, -11, -25, -44, -21, -59, +-14, -49, 1, -23, 19, 12, 34, 39, +33, 54, 24, 52, 8, 38, -10, 22, +-28, 12, -34, 2, -22, 1, 1, 6, +17, 12, 20, 10, 22, 0, 20, -17, +11, -26, -10, -27, -23, -19, -21, -1, +-4, 23, 12, 44, 25, 53, 32, 46, +30, 24, 19, -8, -7, -36, -31, -53, +-43, -56, -36, -44, -24, -17, -4, 13, +24, 33, 55, 38, 62, 33, 46, 17, +23, -7, 0, -28, -22, -37, -43, -42, +-49, -38, -41, -33, -16, -24, 6, -21, +26, -16, 36, -12, 41, -3, 39, 7, +27, 20, 15, 31, 3, 36, -6, 21, +-18, -9, -26, -49, -29, -84, -24, -106, +-18, -104, -13, -77, -4, -29, 16, 26, +37, 73, 54, 97, 57, 94, 45, 63, +27, 14, -7, -41, -35, -84, -55, -109, +-57, -104, -48, -76, -30, -32, -4, 9, +29, 38, 56, 50, 63, 48, 54, 31, +35, 12, 14, 0, -6, -4, -23, 1, +-35, 12, -35, 16, -31, 15, -22, 2, +-9, -21, 6, -46, 18, -57, 20, -52, +21, -27, 22, 11, 21, 57, 14, 96, +5, 113, -5, 103, -11, 72, -15, 25, +-13, -27, -6, -69, -2, -85, 0, -77, +3, -47, 10, -8, 13, 35, 11, 69, +0, 87, -3, 83, -3, 65, 7, 40, +15, 18, 20, 2, 20, -7, 14, -9, +5, -3, -11, -2, -21, -4, -25, -11, +-23, -13, -15, -10, 2, 1, 22, 21, +36, 43, 36, 58, 28, 61, 15, 46, +3, 23, -11, -4, -23, -28, -21, -46, +-14, -46, 0, -31, 8, -5, 15, 18, +14, 32, 8, 35, -6, 27, -15, 5, +-13, -13, -8, -25, 6, -28, 19, -22, +31, -8, 33, 2, 24, 12, 5, 9, +-19, -2, -37, -16, -46, -28, -40, -35, +-17, -37, 15, -34, 42, -20, 59, -11, +60, -8, 51, -9, 21, -14, -9, -24, +-38, -29, -53, -28, -50, -22, -32, -15, +-7, -8, 18, -4, 36, -4, 41, -10, +36, -18, 25, -29, 13, -36, 0, -38, +-13, -28, -22, -17, -21, -4, -14, 0, +-10, 0, -9, -8, -9, -15, 3, -24, +17, -25, 29, -18, 34, -6, 36, 7, +28, 20, 15, 22, -4, 14, -20, -4, +-30, -23, -38, -38, -37, -46, -20, -41, +8, -21, 32, 7, 44, 35, 40, 51, +34, 55, 28, 46, 17, 30, 1, 8, +-12, -8, -17, -16, -21, -13, -22, -6, +-23, 2, -17, 8, -13, 13, -5, 10, +4, 6, 23, 9, 45, 24, 58, 45, +53, 67, 31, 82, 5, 82, -22, 62, +-47, 28, -69, -14, -71, -50, -47, -75, +-6, -74, 31, -44, 58, 5, 76, 54, +81, 92, 60, 113, 18, 111, -20, 85, +-47, 46, -58, 0, -59, -36, -44, -55, +-18, -59, 15, -50, 34, -30, 39, -5, +36, 19, 37, 32, 35, 42, 22, 48, +8, 47, 0, 39, -9, 26, -22, 4, +-33, -20, -37, -44, -28, -60, -17, -61, +-1, -46, 23, -21, 48, 10, 62, 31, +55, 43, 33, 38, 4, 18, -17, -14, +-40, -44, -52, -65, -51, -67, -32, -53, +-5, -30, 24, -5, 43, 15, 51, 21, +43, 13, 24, -6, 5, -29, -5, -49, +-9, -57, -13, -55, -16, -44, -11, -33, +3, -24, 12, -16, 12, -15, 12, -16, +6, -11, 3, -6, 0, -3, 2, 0, +4, 0, 6, -12, 5, -28, 3, -46, +6, -57, 16, -59, 17, -44, 13, -21, +7, 6, 2, 31, -3, 42, -12, 35, +-18, 15, -20, -14, -8, -39, 4, -50, +14, -39, 25, -16, 37, 12, 38, 38, +22, 53, 2, 47, -11, 27, -21, 0, +-33, -25, -36, -38, -29, -32, -10, -9, +9, 22, 21, 50, 26, 70, 32, 72, +33, 60, 25, 34, 12, 8, 3, -16, +2, -33, -2, -35, -13, -16, -25, 7, +-24, 29, -19, 46, -17, 57, -10, 58, +11, 53, 35, 42, 48, 32, 47, 19, +36, 11, 27, 3, 10, 1, -14, 3, +-39, 9, -49, 15, -47, 22, -38, 25, +-23, 26, -1, 21, 26, 14, 47, 5, +57, 2, 57, 4, 56, 13, 42, 25, +14, 31, -19, 26, -43, 17, -58, 0, +-61, -19, -52, -36, -34, -40, -2, -32, +29, -12, 57, 8, 71, 23, 73, 29, +55, 27, 24, 11, -11, -11, -37, -31, +-50, -40, -48, -41, -42, -31, -28, -19, +-5, -11, 19, -10, 34, -12, 35, -21, +32, -29, 29, -32, 25, -27, 23, -18, +14, -5, 2, 0, -10, -9, -20, -28, +-30, -49, -31, -67, -26, -68, -15, -54, +0, -25, 23, 6, 46, 31, 61, 42, +55, 35, 37, 3, 10, -41, -17, -78, +-38, -97, -48, -96, -42, -72, -29, -32, +-7, 13, 15, 49, 33, 66, 44, 58, +44, 34, 32, 5, 15, -21, 2, -41, +-6, -48, -13, -42, -20, -29, -25, -18, +-27, -8, -24, -3, -14, 3, 3, 7, +21, 17, 38, 29, 50, 42, 55, 48, +51, 47, 28, 36, -6, 19, -41, -4, +-62, -22, -68, -30, -57, -26, -28, -14, +11, 6, 46, 26, 69, 41, 77, 47, +64, 49, 35, 45, -1, 42, -33, 41, +-57, 43, -61, 44, -51, 40, -31, 28, +-8, 11, 12, -11, 30, -30, 42, -45, +48, -39, 43, -15, 32, 23, 22, 60, +11, 93, -4, 105, -23, 96, -39, 62, +-45, 15, -39, -33, -23, -68, 0, -80, +23, -65, 47, -36, 61, 5, 62, 45, +43, 71, 15, 77, -20, 65, -47, 33, +-59, -2, -51, -31, -27, -46, 2, -51, +25, -42, 39, -28, 47, -11, 45, 4, +28, 17, 2, 21, -17, 18, -23, 8, +-18, -4, -10, -21, 1, -39, 11, -54, +12, -61, 5, -60, -3, -47, -1, -25, +7, 5, 15, 32, 13, 50, 14, 45, +19, 19, 22, -21, 8, -66, -10, -106, +-23, -123, -23, -112, -17, -68, -9, -12, +11, 41, 34, 82, 42, 97, 33, 76, +16, 28, -2, -34, -16, -90, -28, -128, +-39, -130, -33, -101, -8, -53, 24, 8, +39, 63, 44, 94, 42, 96, 36, 73, +13, 32, -16, -16, -36, -60, -42, -88, +-38, -95, -32, -84, -12, -55, 15, -16, +41, 30, 53, 69, 53, 98, 45, 108, +32, 101, 4, 72, -28, 23, -53, -32, +-62, -79, -56, -110, -38, -112, -13, -83, +21, -26, 60, 44, 78, 111, 78, 154, +59, 162, 29, 131, -8, 71, -43, 0, +-68, -61, -67, -101, -47, -104, -23, -74, +1, -22, 27, 32, 49, 72, 56, 88, +46, 83, 26, 64, 10, 43, 1, 22, +-2, 18, -6, 26, -12, 35, -13, 32, +-23, 18, -30, -12, -28, -48, -16, -73, +-4, -76, 13, -53, 33, -4, 56, 54, +67, 108, 56, 132, 31, 119, 3, 72, +-26, 5, -48, -59, -58, -100, -52, -108, +-29, -84, -4, -41, 21, 6, 40, 39, +53, 50, 53, 33, 37, 6, 15, -18, +-5, -23, -12, -13, -16, 7, -12, 23, +-4, 29, 5, 18, 3, -13, -3, -55, +-12, -88, -14, -103, -9, -91, -1, -52, +12, 0, 34, 47, 53, 78, 54, 77, +39, 45, 16, -6, -6, -53, -29, -86, +-47, -96, -54, -80, -42, -44, -14, -8, +16, 19, 38, 31, 50, 26, 57, 6, +51, -14, 31, -29, 7, -33, -5, -30, +-14, -17, -26, -5, -37, 2, -34, 0, +-20, -8, -4, -15, 8, -16, 21, -11, +37, 5, 47, 18, 48, 22, 38, 15, +22, 1, 4, -20, -15, -36, -30, -41, +-37, -28, -31, -1, -18, 31, 2, 53, +20, 61, 39, 48, 51, 20, 48, -14, +29, -38, 9, -49, -3, -40, -8, -11, +-16, 33, -21, 70, -19, 89, -13, 81, +-2, 49, 4, 2, 12, -40, 19, -68, +28, -67, 32, -39, 31, 12, 27, 61, +18, 94, 4, 101, -16, 84, -31, 44, +-39, -2, -33, -42, -18, -63, 7, -60, +33, -34, 55, 3, 63, 41, 54, 62, +27, 65, -6, 48, -35, 18, -46, -12, +-42, -28, -26, -28, 0, -15, 29, 2, +53, 19, 61, 28, 49, 25, 26, 10, +-4, -7, -32, -23, -45, -31, -36, -31, +-13, -20, 16, -6, 35, 9, 46, 14, +43, 14, 35, 7, 16, 1, -7, -1, +-25, 0, -28, -1, -16, -5, 1, -12, +14, -22, 21, -39, 24, -53, 16, -59, +6, -49, 1, -27, 3, 9, 6, 45, +11, 71, 16, 74, 18, 53, 18, 8, +11, -47, -1, -96, -13, -121, -14, -120, +-7, -87, 7, -31, 18, 34, 28, 83, +30, 105, 25, 94, 12, 55, 0, -1, +-10, -52, -13, -88, -7, -96, 5, -78, +19, -45, 33, -8, 36, 24, 26, 43, +11, 45, -4, 32, -16, 19, -21, 6, +-15, -2, 2, -8, 20, -11, 38, -17, +46, -21, 39, -24, 19, -20, 2, -13, +-9, 5, -13, 30, -14, 56, -10, 66, +2, 58, 14, 27, 23, -14, 23, -56, +17, -77, 11, -75, 10, -45, 14, 4, +22, 64, 28, 111, 28, 127, 20, 101, +4, 47, -11, -24, -21, -83, -25, -114, +-24, -108, -9, -66, 14, 2, 40, 68, +59, 112, 65, 121, 55, 98, 33, 50, +1, -5, -31, -51, -48, -74, -48, -70, +-35, -42, -16, -7, 7, 26, 34, 46, +57, 47, 68, 35, 57, 21, 34, 8, +15, -2, -1, -6, -20, -6, -30, -9, +-29, -16, -17, -26, -6, -33, 9, -36, +28, -26, 46, -7, 56, 18, 55, 42, +40, 59, 25, 52, 9, 29, -12, -10, +-33, -50, -43, -84, -34, -98, -14, -88, +7, -53, 32, -6, 56, 43, 74, 76, +74, 87, 59, 75, 32, 43, 0, -1, +-32, -47, -55, -83, -63, -99, -50, -93, +-23, -68, 8, -32, 42, 7, 70, 40, +87, 61, 85, 62, 64, 54, 28, 38, +-9, 14, -40, -9, -62, -27, -67, -44, +-47, -55, -17, -56, 15, -46, 43, -33, +66, -17, 76, 1, 69, 23, 47, 42, +19, 57, -1, 58, -18, 52, -29, 33, +-32, 7, -21, -26, -5, -51, 10, -65, +19, -62, 27, -46, 29, -16, 28, 17, +26, 46, 28, 62, 29, 67, 24, 58, +14, 40, 3, 15, -3, -7, -7, -26, +-12, -35, -10, -39, -3, -34, 10, -22, +21, -5, 28, 15, 33, 35, 33, 52, +24, 67, 13, 66, 7, 52, 6, 24, +8, -11, 7, -47, 4, -69, 2, -75, +7, -60, 8, -23, 6, 24, 10, 64, +24, 92, 30, 98, 35, 76, 34, 30, +31, -24, 24, -74, 12, -99, -3, -93, +-14, -59, -13, -10, -7, 43, 0, 79, +11, 88, 29, 67, 40, 32, 37, -9, +24, -44, 18, -66, 16, -61, 15, -39, +13, -5, 12, 22, 14, 35, 13, 30, +3, 16, -9, -9, -15, -30, -9, -39, +-2, -28, 13, -8, 32, 16, 56, 31, +70, 33, 65, 21, 41, -1, 13, -29, +-17, -47, -39, -53, -53, -41, -45, -21, +-19, 2, 20, 18, 55, 28, 74, 26, +78, 14, 70, -5, 47, -15, 12, -17, +-14, -12, -28, -8, -28, -2, -22, -2, +-9, -5, 5, -13, 20, -19, 27, -20, +28, -8, 27, 4, 35, 18, 43, 30, +43, 37, 38, 28, 28, 10, 10, -13, +-12, -29, -30, -38, -36, -34, -30, -17, +-11, 8, 18, 27, 50, 44, 69, 46, +75, 33, 66, 9, 38, -11, 2, -27, +-26, -30, -39, -24, -35, -5, -17, 17, +6, 35, 35, 41, 53, 37, 60, 25, +49, 8, 31, -14, 12, -26, 2, -31, +-2, -24, 3, -9, 6, 10, 16, 19, +21, 26, 20, 31, 12, 33, 8, 28, +12, 21, 19, 12, 30, 3, 39, -10, +47, -23, 45, -37, 28, -41, -1, -35, +-25, -21, -34, 2, -27, 35, -9, 66, +19, 84, 52, 78, 77, 52, 81, 9, +65, -42, 36, -89, 3, -114, -24, -113, +-36, -76, -34, -16, -13, 51, 14, 102, +40, 126, 52, 111, 55, 67, 45, 6, +26, -53, 7, -98, -1, -113, 0, -99, +13, -62, 28, -16, 33, 31, 31, 58, +20, 64, 7, 53, -9, 34, -13, 13, +-8, -5, 13, -19, 35, -26, 54, -31, +62, -36, 58, -42, 37, -43, 12, -41, +-13, -26, -23, -3, -19, 26, -2, 53, +17, 69, 35, 62, 48, 34, 49, -6, +36, -42, 16, -71, 1, -80, -7, -65, +-4, -31, 14, 6, 33, 43, 43, 65, +44, 61, 38, 34, 25, 2, 5, -27, +-7, -40, -11, -38, -4, -21, 11, -1, +34, 17, 51, 24, 61, 21, 51, 8, +32, -9, 8, -20, -8, -19, -18, -7, +-13, 12, 0, 27, 21, 38, 37, 36, +48, 21, 53, -2, 47, -19, 33, -29, +17, -27, 2, -13, -9, 9, -5, 26, +1, 39, 9, 36, 16, 23, 28, 3, +37, -13, 45, -21, 43, -17, 42, -9, +36, 8, 27, 22, 14, 28, 4, 27, +-10, 23, -17, 11, -15, -2, -4, -11, +14, -11, 40, -11, 63, -6, 73, 0, +64, 9, 49, 10, 28, 9, 5, 7, +-18, 10, -32, 10, -26, 8, -6, 4, +19, 1, 42, -8, 63, -14, 65, -18, +59, -20, 45, -20, 30, -7, 11, 7, +2, 19, -6, 26, -2, 27, 4, 15, +17, -2, 21, -21, 23, -35, 25, -47, +32, -44, 41, -30, 48, -6, 52, 20, +50, 42, 39, 53, 20, 47, 1, 24, +-17, -7, -27, -45, -24, -74, -6, -84, +19, -72, 54, -43, 79, 1, 87, 44, +80, 75, 59, 81, 28, 66, -2, 30, +-27, -13, -35, -57, -31, -82, -13, -84, +8, -63, 38, -35, 58, 0, 66, 28, +61, 45, 54, 46, 43, 37, 34, 20, +26, 4, 18, -5, 9, -7, 0, -12, +-4, -17, -9, -26, -5, -37, 3, -45, +19, -41, 37, -27, 65, -1, 83, 31, +85, 62, 65, 77, 38, 70, 7, 41, +-19, 0, -39, -41, -43, -66, -31, -71, +1, -52, 34, -15, 62, 28, 75, 56, +78, 64, 62, 49, 37, 22, 13, -10, +0, -28, -7, -29, -5, -14, 5, 8, +21, 29, 35, 38, 38, 32, 29, 12, +15, -16, 11, -43, 14, -48, 23, -31, +30, 6, 42, 43, 50, 67, 56, 68, +45, 49, 32, 12, 14, -31, 1, -65, +-12, -73, -13, -57, -3, -20, 19, 22, +38, 57, 52, 72, 61, 63, 65, 34, +57, 2, 42, -28, 24, -42, 6, -44, +-6, -31, -11, -14, -9, 3, 2, 8, +17, 10, 30, 6, 45, 3, 56, 9, +60, 24, 55, 35, 46, 38, 29, 28, +13, 6, -3, -27, -9, -57, -12, -77, +-4, -73, 9, -49, 28, -3, 41, 46, +59, 81, 65, 91, 61, 75, 45, 32, +29, -19, 13, -66, 2, -93, -4, -94, +-3, -66, 7, -25, 21, 19, 40, 49, +51, 61, 57, 51, 49, 28, 37, 0, +20, -24, 14, -39, 8, -37, 10, -28, +11, -14, 24, -4, 36, 2, 49, 3, +50, 1, 44, -1, 29, 1, 17, 5, +5, 11, -1, 13, 0, 11, 8, 1, +21, -11, 35, -22, 48, -25, 57, -24, +62, -13, 54, 2, 36, 21, 19, 30, +10, 29, 5, 13, 5, -4, 1, -20, +6, -31, 15, -35, 32, -28, 44, -12, +54, 11, 55, 28, 59, 39, 49, 41, +39, 33, 24, 14, 12, -6, -5, -25, +-13, -34, -13, -35, 3, -27, 21, -14, +40, 3, 56, 19, 65, 31, 69, 32, +64, 30, 46, 24, 21, 18, 1, 10, +-15, 3, -14, -8, -4, -14, 11, -20, +22, -22, 38, -27, 48, -24, 57, -13, +54, 6, 51, 25, 40, 47, 29, 63, +16, 66, 14, 47, 7, 19, 1, -17, +-4, -53, 3, -77, 15, -80, 35, -62, +52, -22, 65, 24, 68, 62, 66, 82, +53, 81, 30, 58, 4, 21, -20, -18, +-31, -48, -25, -63, 3, -60, 34, -41, +67, -14, 82, 9, 87, 22, 73, 23, +52, 20, 17, 13, -7, 8, -26, 6, +-23, 13, -8, 14, 23, 10, 49, 0, +62, -15, 61, -36, 56, -52, 42, -55, +27, -36, 12, -4, 5, 32, 8, 58, +19, 69, 31, 59, 38, 31, 40, -10, +32, -49, 22, -73, 14, -72, 16, -53, +25, -21, 39, 13, 44, 41, 49, 51, +40, 49, 27, 31, 10, 3, 5, -22, +-1, -31, 7, -31, 25, -22, 53, -12, +70, -2, 76, 1, 58, 1, 33, -7, +5, -10, -15, -8, -25, 0, -18, 11, +3, 25, 32, 30, 64, 28, 81, 16, +80, -2, 61, -22, 35, -34, 3, -37, +-11, -28, -16, -12, -5, 8, 10, 22, +29, 31, 42, 28, 52, 19, 48, 8, +40, -2, 29, -8, 26, -5, 26, 1, +35, 7, 40, 5, 43, -3, 33, -17, +18, -26, 0, -32, -8, -26, -8, -10, +5, 18, 26, 44, 53, 67, 77, 70, +88, 54, 83, 19, 54, -19, 16, -57, +-19, -79, -35, -83, -38, -59, -14, -23, +14, 24, 49, 64, 70, 89, 86, 87, +81, 65, 61, 32, 25, -6, 4, -44, +-4, -64, 1, -67, 12, -52, 25, -29, +30, 1, 33, 21, 32, 32, 30, 33, +29, 32, 27, 28, 30, 25, 35, 19, +44, 12, 50, -3, 50, -17, 36, -34, +20, -42, 4, -42, 4, -31, 8, -9, +17, 22, 25, 42, 41, 51, 49, 42, +53, 19, 44, -13, 36, -38, 22, -51, +21, -48, 26, -29, 38, 7, 43, 40, +42, 57, 33, 47, 21, 18, 12, -22, +4, -53, 2, -70, 9, -63, 27, -33, +46, 12, 69, 50, 74, 74, 71, 67, +52, 36, 30, -6, 0, -45, -12, -70, +-18, -64, -11, -37, 2, -1, 24, 31, +40, 52, 59, 45, 67, 21, 69, -14, +57, -39, 44, -45, 29, -33, 22, -8, +11, 22, 3, 40, -4, 42, -9, 26, +-5, -3, 9, -34, 30, -48, 49, -45, +67, -25, 78, 4, 81, 33, 68, 44, +47, 39, 11, 17, -18, -9, -38, -35, +-28, -49, -8, -42, 22, -14, 44, 16, +66, 41, 71, 45, 72, 31, 59, 5, +42, -22, 21, -39, 10, -40, 7, -27, +17, -3, 24, 19, 26, 32, 23, 28, +18, 12, 14, -8, 10, -20, 15, -23, +27, -13, 48, 5, 63, 26, 73, 37, +70, 32, 59, 9, 33, -19, 8, -46, +-15, -55, -20, -45, -17, -17, 2, 15, +21, 44, 46, 58, 63, 53, 74, 30, +69, 3, 57, -23, 38, -34, 23, -34, +11, -20, 9, -3, 6, 15, 6, 19, +5, 14, 5, 2, 15, -11, 29, -16, +43, -3, 45, 17, 51, 35, 55, 40, +59, 38, 45, 21, 29, -1, 4, -25, +-10, -40, -17, -43, -7, -27, 5, -5, +29, 20, 45, 30, 61, 28, 65, 16, +60, 5, 46, -10, 35, -17, 20, -11, +8, 10, 3, 26, 10, 34, 19, 27, +23, 10, 25, -19, 27, -45, 30, -62, +31, -60, 38, -42, 40, -9, 44, 26, +41, 57, 41, 70, 35, 69, 27, 52, +11, 25, 5, -9, -1, -36, 5, -54, +10, -62, 27, -66, 38, -57, 48, -38, +50, -13, 53, 18, 45, 50, 37, 71, +28, 82, 18, 76, 9, 52, 7, 11, +9, -37, 10, -78, 15, -100, 19, -101, +31, -76, 39, -32, 47, 20, 49, 59, +50, 83, 43, 80, 39, 58, 29, 25, +21, -11, 8, -37, 1, -48, -2, -51, +14, -45, 25, -33, 39, -18, 43, -5, +45, 10, 39, 21, 35, 33, 27, 39, +25, 41, 18, 37, 14, 23, 16, -5, +24, -33, 28, -54, 26, -60, 22, -52, +19, -27, 24, 5, 28, 42, 36, 64, +37, 70, 40, 55, 36, 25, 37, -14, +27, -43, 20, -59, 8, -54, 6, -36, +6, -10, 21, 12, 34, 32, 44, 43, +42, 42, 40, 29, 35, 14, 30, 3, +21, -1, 16, -3, 14, -5, 17, -7, +24, -11, 30, -18, 37, -25, 37, -24, +30, -12, 20, 5, 16, 26, 14, 42, +20, 53, 25, 48, 36, 31, 40, 8, +42, -12, 37, -34, 33, -43, 18, -40, +10, -27, 5, -11, 11, 9, 18, 21, +34, 28, 40, 28, 45, 24, 42, 15, +38, 9, 31, 0, 24, -6, 16, -11, +14, -11, 18, -13, 26, -14, 39, -19, +44, -17, 43, -10, 28, 2, 16, 9, +6, 14, 5, 15, 4, 17, 12, 15, +22, 10, 43, 1, 59, -4, 70, -11, +62, -11, 42, -11, 15, -12, -2, -16, +-16, -17, -19, -19, -11, -16, 8, -11, +33, 0, 56, 10, 68, 24, 72, 29, +61, 28, 42, 17, 21, 1, 4, -15, +-7, -28, -9, -39, -1, -43, 10, -39, +27, -25, 35, -6, 41, 14, 36, 25, +37, 26, 39, 18, 45, 9, 46, -2, +49, -10, 42, -16, 36, -17, 19, -19, +2, -16, -16, -13, -21, -12, -14, -15, +3, -11, 24, -5, 58, 1, 86, 10, +94, 21, 85, 23, 63, 20, 29, 11, +-8, 0, -37, -14, -50, -25, -39, -34, +-12, -31, 24, -20, 58, -3, 86, 13, +90, 28, 79, 31, 53, 27, 27, 16, +1, 3, -9, -9, -17, -12, -11, -13, +1, -7, 20, 0, 29, 6, 35, 9, +34, 9, 33, 3, 35, -3, 39, -3, +43, 2, 45, 7, 42, 14, 31, 17, +18, 17, 1, 14, -12, 5, -17, -4, +-7, -11, 7, -12, 31, -4, 47, 4, +66, 12, 67, 13, 59, 9, 37, 1, +17, -2, -3, -7, -7, -4, -6, 4, +5, 16, 18, 24, 30, 29, 36, 21, +41, 0, 39, -25, 32, -42, 22, -46, +19, -36, 22, -18, 31, 10, 35, 37, +33, 57, 27, 58, 14, 44, 8, 15, +2, -16, 3, -43, 6, -52, 16, -47, +26, -30, 40, -10, 45, 8, 48, 18, +38, 24, 25, 24, 11, 19, 7, 10, +7, 2, 18, -6, 28, -10, 34, -15, +34, -20, 31, -29, 24, -31, 11, -29, +-1, -19, -4, -6, 9, 12, 24, 26, +41, 35, 52, 31, 61, 23, 52, 8, +32, -7, 7, -25, -10, -37, -19, -44, +-18, -39, -7, -30, 15, -16, 33, 0, +49, 15, 56, 22, 63, 27, 55, 30, +43, 29, 24, 20, 13, 7, 0, -13, +-7, -33, -7, -53, -2, -61, 1, -54, +6, -31, 17, -2, 35, 29, 51, 56, +62, 72, 68, 67, 62, 48, 46, 14, +21, -22, -3, -54, -26, -70, -36, -69, +-38, -50, -19, -23, 9, 10, 45, 38, +74, 56, 89, 63, 84, 57, 67, 40, +39, 21, 9, -5, -20, -26, -39, -39, +-41, -45, -26, -45, -6, -31, 19, -12, +45, 10, 63, 32, 68, 51, 64, 59, +57, 58, 37, 42, 18, 18, -1, -11, +-10, -33, -22, -46, -22, -46, -18, -36, +0, -17, 20, 5, 41, 29, 53, 45, +67, 48, 67, 39, 55, 28, 32, 10, +12, -5, -15, -17, -27, -24, -28, -29, +-12, -25, 4, -18, 26, -3, 45, 8, +56, 18, 58, 21, 47, 22, 31, 18, +13, 11, 5, -2, -1, -8, -3, -14, +3, -20, 16, -19, 24, -8, 26, 3, +21, 12, 15, 16, 9, 15, 12, 6, +16, -6, 28, -19, 38, -25, 43, -25, +37, -19, 30, -6, 17, 8, 4, 16, +-9, 20, -13, 18, -6, 9, 6, -4, +23, -16, 39, -24, 50, -27, 49, -26, +37, -16, 22, -7, 12, 2, 4, 7, +1, 8, 2, 4, 16, 1, 21, -2, +26, -4, 28, -5, 28, -3, 11, 3, +0, 6, -2, 3, 10, -3, 21, -12, +34, -19, 41, -22, 47, -22, 45, -17, +35, -2, 12, 12, -7, 23, -21, 27, +-22, 26, -14, 15, 5, 1, 26, -12, +42, -18, 55, -21, 58, -17, 51, -5, +32, 10, 13, 17, -8, 18, -20, 11, +-20, 2, -10, -9, 3, -12, 18, -5, +31, 7, 39, 16, 41, 26, 42, 29, +33, 26, 22, 10, 8, -10, 5, -30, +8, -37, 13, -35, 18, -20, 20, 3, +21, 28, 14, 42, 11, 45, 11, 35, +18, 15, 18, -10, 20, -27, 30, -35, +41, -28, 38, -13, 31, 4, 19, 19, +8, 28, -5, 25, -5, 18, -5, 5, +8, -3, 14, -5, 21, -3, 26, -4, +34, -5, 33, -8, 28, -10, 21, -13, +15, -10, 12, -5, 18, 7, 25, 20, +27, 30, 22, 29, 16, 22, 2, 5, +-9, -19, -11, -41, -6, -50, 2, -48, +13, -31, 38, -8, 61, 15, 76, 31, +68, 41, 47, 38, 18, 25, -9, 5, +-34, -10, -48, -22, -44, -29, -29, -31, +-7, -28, 25, -28, 59, -26, 75, -21, +73, -11, 72, -1, 59, 21, 27, 45, +-6, 57, -24, 54, -35, 35, -47, 0, +-42, -36, -31, -69, -5, -85, 20, -79, +45, -49, 66, -9, 83, 35, 82, 68, +67, 82, 41, 72, 7, 44, -34, 3, +-59, -36, -66, -61, -52, -64, -34, -53, +4, -30, 39, -3, 71, 18, 90, 25, +96, 26, 76, 21, 41, 15, 9, 9, +-18, 5, -39, 3, -51, 5, -47, -1, +-26, -15, 0, -27, 25, -28, 43, -25, +60, -12, 65, 8, 57, 30, 47, 43, +36, 42, 20, 28, -6, 6, -16, -22, +-19, -44, -24, -52, -26, -41, -9, -17, +15, 15, 30, 42, 42, 60, 50, 61, +54, 42, 48, 10, 36, -17, 15, -38, +-6, -47, -17, -45, -22, -30, -16, -7, +-4, 17, 4, 35, 14, 44, 26, 41, +39, 34, 31, 20, 27, 7, 20, -6, +14, -17, 5, -28, 7, -29, 7, -25, +5, -11, 5, 4, 9, 21, 8, 31, +5, 38, 1, 34, 3, 21, 4, -1, +14, -21, 15, -35, 21, -34, 25, -26, +32, -9, 34, 10, 27, 29, 15, 35, +0, 27, -3, 9, -5, -9, -12, -27, +-13, -40, 4, -41, 22, -26, 25, -8, +33, 11, 41, 22, 39, 29, 25, 22, +12, 12, 5, -2, -4, -12, -7, -17, +-12, -14, -7, -13, 4, -11, 11, -13, +16, -13, 28, -15, 36, -10, 22, -3, +14, 6, 16, 13, 20, 21, 12, 21, +8, 13, 8, -2, 4, -16, 0, -27, +2, -30, 3, -27, 4, -14, 5, 0, +18, 12, 26, 15, 40, 14, 38, 6, +30, -3, 16, -12, 6, -14, -10, -6, +-24, 9, -26, 18, -20, 22, -5, 18, +22, 6, 39, -6, 44, -15, 48, -24, +50, -23, 22, -12, -5, 4, -21, 18, +-26, 25, -27, 20, -18, 14, 1, 4, +17, -4, 38, -9, 48, -6, 51, 1, +39, 10, 16, 17, -8, 18, -17, 7, +-8, -9, -12, -21, -11, -24, 5, -20, +22, -6, 25, 12, 22, 31, 23, 40, +13, 38, 5, 25, 5, 8, 15, -13, +21, -27, 20, -29, 21, -22, 14, -12, +7, 2, -9, 12, -17, 13, -18, 9, +-9, 8, 0, 6, 16, 7, 42, 14, +54, 23, 50, 20, 43, 11, 20, -2, +-9, -19, -28, -39, -26, -48, -34, -41, +-27, -20, -6, 9, 25, 38, 42, 57, +50, 62, 48, 46, 30, 18, 10, -18, +-1, -48, -2, -67, -2, -64, -4, -45, +4, -16, 10, 12, 21, 33, 14, 36, +2, 31, -1, 18, -1, 4, -1, -9, +7, -13, 34, -10, 45, -5, 42, -7, +35, -12, 24, -22, 1, -32, -25, -37, +-33, -31, -33, -14, -23, 14, -8, 44, +17, 61, 46, 58, 63, 41, 55, 6, +32, -32, 18, -64, 3, -77, -16, -69, +-25, -41, -23, -6, -12, 29, -3, 52, +21, 57, 27, 44, 23, 24, 15, 1, +16, -18, 12, -26, 10, -22, 18, -15, +20, -8, 14, -2, 8, -2, 2, -12, +-2, -20, -11, -19, -11, -5, -11, 13, +4, 34, 12, 51, 17, 59, 26, 46, +34, 17, 24, -18, 5, -45, 5, -61, +2, -58, -4, -40, -3, -9, 6, 20, +10, 41, 7, 48, 17, 43, 17, 28, +8, 10, -3, -6, -2, -13, 9, -15, +19, -10, 23, -6, 18, -5, 24, -11, +24, -15, 10, -16, -4, -9, -9, 3, +-12, 21, -24, 37, -9, 43, 7, 36, +19, 18, 27, -4, 35, -25, 33, -43, +24, -45, 17, -32, 7, -8, -1, 12, +-2, 30, -7, 35, -11, 31, -15, 18, +-2, 0, 4, -19, 13, -24, 13, -20, +18, -9, 26, 3, 36, 10, 35, 7, +20, 4, 12, -4, 2, -10, -14, -16, +-19, -12, -15, -3, -15, 10, -23, 17, +-1, 15, 23, 5, 35, -4, 34, -11, +36, -15, 37, -15, 26, -8, 10, 3, +-11, 12, -17, 11, -18, 4, -27, -9, +-26, -19, -7, -26, 17, -21, 21, -6, +32, 14, 41, 27, 35, 35, 24, 30, +19, 14, 11, -10, -12, -34, -21, -51, +-19, -52, -13, -40, 0, -15, 9, 12, +15, 36, 16, 47, 25, 49, 18, 38, +15, 15, 12, -7, 6, -22, -1, -30, +1, -30, 5, -26, 0, -17, 1, -9, +5, 1, -8, 11, -12, 19, -6, 22, +9, 25, 8, 24, 27, 21, 39, 12, +35, 5, 20, -4, 14, -15, 5, -25, +-18, -26, -34, -24, -35, -17, -17, -6, +6, 7, 18, 17, 31, 26, 39, 33, +43, 36, 23, 32, 9, 27, -3, 18, +-24, 4, -35, -12, -23, -26, 2, -39, +11, -45, 21, -40, 29, -23, 25, 1, +15, 25, 3, 43, -3, 58, -12, 60, +-1, 48, 6, 28, 12, 8, 22, -15, +24, -33, 13, -46, -3, -51, -11, -50, +-25, -40, -23, -24, -1, -3, 15, 22, +29, 49, 39, 71, 49, 81, 32, 73, +19, 48, -3, 8, -32, -38, -50, -81, +-38, -105, -14, -104, 4, -78, 26, -32, +44, 25, 51, 77, 47, 111, 21, 116, +-1, 87, -18, 34, -17, -23, -24, -70, +-14, -97, 10, -99, 21, -76, 20, -42, +24, -3, 28, 33, 7, 55, -8, 62, +-3, 56, -1, 39, 2, 18, 5, -3, +21, -22, 27, -39, 29, -47, 13, -51, +-4, -48, -9, -37, -11, -15, -8, 11, +-2, 37, 14, 56, 16, 62, 17, 50, +26, 28, 24, -6, 12, -42, 1, -69, +5, -76, 1, -63, 7, -32, 12, 6, +11, 37, 5, 55, 4, 60, 3, 45, +-7, 22, -8, -7, 2, -25, 6, -33, +16, -30, 21, -21, 31, -8, 29, 1, +31, 7, 10, 6, -10, 5, -16, 2, +-19, 4, -24, 10, -16, 16, 6, 15, +12, 12, 15, 5, 36, -5, 46, -15, +37, -18, 17, -15, 13, -2, 0, 9, +-5, 19, -12, 22, -23, 20, -24, 4, +-19, -16, -5, -33, 11, -37, 34, -26, +42, -2, 35, 28, 36, 55, 30, 63, +13, 54, -11, 29, -18, -3, -29, -39, +-32, -65, -17, -72, -1, -56, 17, -28, +31, 7, 41, 37, 30, 56, 21, 56, +20, 43, 12, 23, 2, 2, -7, -15, +-4, -22, -7, -21, 4, -17, 3, -14, +-2, -16, -4, -21, -1, -23, -1, -20, +8, -10, 28, 4, 29, 27, 20, 44, +31, 50, 31, 44, 15, 25, -8, -6, +-10, -36, -18, -60, -20, -68, -11, -57, +2, -31, 15, 3, 19, 33, 18, 52, +14, 51, 18, 35, 16, 14, 4, -11, +10, -24, 9, -25, 2, -15, -6, -5, +8, 7, 11, 11, -6, 9, -15, -3, +-14, -17, -7, -25, -1, -26, 17, -19, +24, 1, 23, 24, 30, 41, 30, 41, +27, 32, 12, 12, -2, -10, -20, -30, +-23, -41, -18, -38, -18, -25, -10, -7, +1, 13, 12, 25, 20, 28, 34, 22, +40, 11, 32, -1, 34, -7, 24, -8, +5, -1, -19, 5, -21, 8, -27, 4, +-32, -5, -26, -14, -7, -20, 18, -22, +38, -13, 51, 4, 49, 23, 41, 35, +27, 40, -1, 35, -14, 20, -28, -3, +-37, -23, -43, -35, -16, -36, 12, -27, +23, -9, 30, 11, 34, 31, 29, 42, +13, 41, 6, 32, -3, 21, -14, 5, +-8, -10, -1, -23, 10, -28, 13, -30, +15, -24, 3, -14, -6, 1, -11, 16, +-16, 30, -9, 40, 9, 44, 29, 39, +32, 28, 33, 8, 31, -16, 13, -41, +1, -57, -15, -60, -27, -48, -34, -22, +-15, 13, 7, 42, 22, 66, 30, 74, +32, 65, 26, 38, 11, 4, 2, -30, +-9, -55, -18, -67, -11, -61, -5, -42, +16, -14, 24, 15, 25, 37, 11, 45, +10, 48, 0, 42, -20, 29, -24, 7, +-6, -11, 12, -23, 14, -28, 23, -31, +34, -28, 23, -18, 11, -5, -9, 7, +-21, 22, -32, 30, -23, 34, -9, 28, +14, 16, 34, 2, 33, -12, 29, -27, +24, -33, 16, -29, -8, -16, -28, 4, +-27, 24, -24, 36, -6, 39, 16, 28, +32, 13, 29, -7, 28, -26, 24, -38, +5, -37, -8, -24, -15, -4, -18, 20, +-20, 42, -9, 47, 7, 40, 15, 24, +23, 6, 20, -17, 21, -32, 13, -37, +11, -28, 2, -13, 2, 9, 1, 26, +-12, 35, -20, 34, -13, 25, -5, 10, +-5, -4, 2, -16, 19, -18, 23, -9, +29, 5, 29, 14, 31, 19, 13, 18, +-5, 15, -19, 5, -27, -4, -26, -12, +-26, -13, -18, -7, 0, 3, 22, 11, +32, 19, 33, 22, 44, 18, 36, 8, +22, 2, 1, 0, -11, 1, -29, 2, +-38, 7, -38, 9, -35, 7, -20, 3, +1, -1, 25, -6, 43, -6, 53, 0, +50, 12, 31, 22, 16, 32, -9, 33, +-32, 25, -52, 9, -57, -6, -47, -22, +-19, -29, 15, -26, 34, -12, 46, 8, +52, 28, 49, 38, 27, 38, -2, 28, +-18, 6, -32, -20, -32, -34, -27, -33, +-10, -20, 2, -4, 18, 18, 24, 36, +22, 44, 19, 36, 9, 19, 1, -4, +-3, -22, -7, -31, -13, -30, -13, -21, +4, -3, 8, 16, 5, 35, -3, 42, +4, 38, 3, 26, 3, 13, 7, -2, +3, -13, -5, -19, -11, -18, -8, -17, +-4, -11, -4, -1, 0, 7, 3, 13, +18, 22, 24, 32, 22, 38, 9, 35, +-1, 25, -15, 11, -28, -7, -28, -26, +-25, -36, -17, -35, -5, -20, 11, 1, +24, 21, 32, 37, 43, 46, 32, 45, +16, 35, -6, 15, -18, -4, -32, -21, +-36, -28, -28, -27, -21, -14, -15, 5, +-5, 22, 10, 32, 26, 33, 35, 26, +33, 19, 20, 12, 16, 9, 1, 7, +-16, 7, -36, 9, -43, 8, -45, 1, +-36, -3, -14, -7, 9, -5, 24, 2, +36, 10, 48, 17, 47, 28, 25, 35, +1, 32, -28, 19, -40, 3, -47, -14, +-39, -20, -28, -18, -4, -7, 19, 10, +26, 27, 30, 34, 26, 33, 12, 23, +-2, 5, -10, -15, -16, -21, -23, -15, +-15, 3, -8, 23, 2, 40, 2, 48, +0, 45, -10, 27, -14, -2, -6, -32, +-1, -49, 2, -47, 6, -27, 12, 4, +17, 37, 10, 64, -3, 76, -22, 65, +-26, 41, -32, 10, -30, -18, -23, -36, +-7, -36, 4, -23, 9, -5, 14, 14, +16, 25, 8, 26, -1, 23, -8, 15, +-12, 11, -19, 13, -15, 21, -17, 30, +-9, 36, -11, 32, -10, 17, -14, -5, +-10, -24, -5, -38, -3, -39, 2, -27, +8, 0, 11, 31, 10, 59, 5, 72, +-3, 69, -25, 52, -36, 24, -40, -10, +-34, -31, -29, -39, -14, -33, 2, -18, +19, 1, 33, 18, 31, 34, 19, 38, +2, 36, -15, 26, -30, 18, -43, 13, +-43, 11, -37, 9, -20, 9, -5, 6, +9, 1, 16, -3, 20, -4, 18, -3, +7, 3, -5, 15, -19, 29, -33, 38, +-38, 43, -36, 38, -25, 26, -20, 8, +-8, -5, 2, -16, 16, -16, 16, -9, +11, 3, 0, 15, -9, 28, -18, 34, +-29, 33, -32, 27, -28, 20, -24, 15, +-18, 11, -10, 6, 3, 6, 3, 6, +4, 7, -1, 6, -4, 6, -12, 6, +-15, 9, -17, 14, -19, 21, -18, 26, +-20, 30, -23, 29, -21, 25, -16, 15, +-10, 6, -10, 0, -5, 1, -7, 6, +-2, 12, -4, 18, -10, 23, -22, 24, +-31, 22, -32, 13, -32, 8, -27, 4, +-17, 7, -9, 15, -1, 24, 7, 32, +8, 38, -5, 35, -16, 24, -31, 8, +-35, -11, -36, -25, -29, -28, -20, -21, +-5, -3, 7, 22, 4, 50, -2, 64, +-6, 65, -17, 54, -30, 34, -42, 8, +-40, -15, -36, -31, -21, -34, -8, -25, +6, -8, 8, 11, 4, 31, -1, 40, +-11, 44, -25, 41, -39, 32, -48, 23, +-45, 20, -40, 19, -29, 18, -18, 11, +0, 6, 4, 2, 6, -3, 1, -7, +-6, -6, -17, -3, -28, 9, -39, 26, +-46, 41, -45, 49, -39, 50, -33, 43, +-23, 31, -14, 13, -2, 0, -1, -6, +-1, -4, -7, 1, -12, 9, -25, 15, +-38, 21, -48, 21, -48, 16, -43, 9, +-37, 8, -26, 9, -9, 22, 0, 40, +2, 53, -1, 54, -3, 45, -20, 30, +-32, 4, -41, -26, -40, -43, -45, -45, +-45, -32, -35, -8, -20, 25, -10, 57, +-6, 81, -7, 86, -5, 76, -12, 51, +-19, 20, -30, -12, -34, -33, -43, -42, +-47, -39, -47, -26, -39, -3, -33, 23, +-26, 45, -13, 56, -1, 63, -1, 66, +-9, 61, -19, 44, -27, 24, -44, 4, +-56, -17, -64, -34, -54, -39, -44, -30, +-28, -8, -14, 18, -4, 48, 2, 72, +-2, 86, -16, 82, -32, 58, -46, 22, +-52, -11, -57, -38, -51, -47, -45, -41, +-29, -17, -23, 15, -19, 47, -17, 66, +-16, 74, -23, 65, -31, 46, -35, 22, +-36, 1, -37, -15, -36, -20, -35, -17, +-29, -6, -34, 8, -39, 22, -45, 31, +-40, 38, -37, 39, -30, 38, -23, 34, +-15, 30, -15, 24, -21, 17, -29, 6, +-36, -3, -51, -7, -61, -6, -61, -2, +-48, 10, -37, 26, -25, 39, -20, 50, +-15, 53, -20, 44, -27, 28, -38, 10, +-47, -3, -55, -7, -58, -2, -52, 6, +-41, 19, -33, 33, -28, 43, -30, 40, +-32, 33, -41, 20, -45, 8, -48, 0, +-47, 2, -44, 9, -35, 20, -30, 32, +-30, 44, -33, 47, -38, 42, -48, 27, +-54, 9, -56, -3, -49, -6, -50, -3, +-42, 4, -37, 15, -28, 29, -31, 38, +-35, 43, -42, 43, -45, 38, -51, 30, +-56, 26, -57, 23, -51, 21, -52, 19, +-52, 16, -49, 6, -36, 1, -37, 1, +-39, 6, -40, 13, -36, 25, -39, 36, +-44, 47, -52, 53, -55, 51, -57, 36, +-55, 20, -51, 4, -46, -6, -40, -12, +-32, -6, -32, 6, -36, 22, -50, 36, +-59, 41, -65, 36, -63, 32, -61, 25, +-55, 20, -45, 19, -36, 24, -30, 32, +-31, 38, -40, 36, -49, 27, -63, 15, +-69, 3, -75, -11, -68, -16, -58, -7, +-46, 13, -41, 35, -36, 57, -34, 70, +-36, 70, -45, 55, -56, 35, -64, 12, +-66, -9, -69, -22, -66, -19, -63, -8, +-53, 12, -57, 33, -59, 49, -57, 55, +-48, 53, -46, 41, -44, 29, -41, 17, +-37, 13, -45, 14, -57, 18, -66, 18, +-73, 18, -84, 16, -86, 15, -79, 9, +-60, 8, -46, 12, -34, 24, -28, 39, +-26, 50, -32, 53, -46, 51, -66, 41, +-83, 26, -97, 10, -100, -5, -92, -15, +-71, -13, -56, 0, -39, 20, -31, 38, +-29, 54, -35, 59, -43, 56, -61, 46, +-76, 30, -83, 12, -84, 2, -84, -3, +-77, 1, -69, 12, -65, 25, -63, 30, +-55, 33, -50, 35, -47, 34, -54, 32, +-60, 30, -63, 29, -65, 32, -75, 33, +-80, 29, -79, 25, -77, 20, -78, 12, +-73, 10, -66, 11, -56, 13, -58, 22, +-60, 35, -60, 40, -58, 45, -69, 47, +-76, 42, -77, 33, -75, 24, -79, 15, +-75, 8, -68, 3, -60, 5, -60, 7, +-60, 14, -65, 25, -67, 35, -73, 40, +-71, 45, -76, 48, -75, 46, -75, 37, +-69, 25, -67, 12, -66, 1, -66, -7, +-66, -5, -73, 5, -75, 22, -74, 38, +-75, 55, -82, 63, -82, 61, -79, 48, +-72, 29, -72, 10, -70, -2, -68, -5, +-65, 2, -69, 16, -72, 33, -75, 47, +-79, 51, -86, 43, -89, 32, -89, 19, +-82, 8, -81, 6, -73, 17, -65, 30, +-58, 45, -64, 56, -68, 57, -73, 43, +-77, 19, -88, -5, -91, -20, -88, -23, +-82, -8, -80, 16, -74, 45, -68, 65, +-63, 75, -73, 74, -80, 58, -84, 30, +-82, 2, -86, -13, -85, -11, -80, -3, +-70, 10, -68, 28, -72, 41, -81, 43, +-86, 36, -94, 24, -95, 18, -97, 18, +-89, 28, -79, 40, -67, 54, -63, 61, +-61, 56, -64, 36, -74, 11, -93, -12, +-107, -28, -112, -30, -108, -14, -102, 15, +-88, 51, -74, 82, -65, 99, -67, 94, +-67, 72, -71, 37, -80, 2, -98, -25, +-100, -37, -96, -30, -95, -5, -96, 22, +-88, 47, -83, 65, -84, 69, -88, 56, +-82, 37, -79, 19, -79, 12, -87, 11, +-85, 18, -81, 26, -81, 36, -91, 42, +-97, 42, -101, 33, -104, 19, -106, 7, +-98, 3, -89, 5, -80, 15, -75, 28, +-69, 44, -74, 55, -79, 61, -94, 60, +-106, 51, -114, 31, -113, 18, -112, 8, +-104, 4, -92, 1, -79, 6, -72, 15, +-70, 26, -74, 35, -79, 42, -87, 44, +-97, 48, -114, 50, -119, 47, -115, 37, +-106, 27, -100, 19, -88, 13, -77, 8, +-71, 7, -72, 8, -71, 13, -76, 21, +-91, 33, -112, 44, -121, 51, -123, 51, +-118, 48, -113, 42, -94, 32, -76, 21, +-66, 15, -68, 9, -69, 7, -74, 4, +-90, 7, -111, 16, -121, 30, -125, 44, +-124, 55, -116, 59, -97, 58, -84, 49, +-75, 36, -74, 20, -74, 5, -84, -4, +-96, -7, -108, -2, -109, 13, -112, 34, +-112, 54, -111, 65, -104, 67, -100, 57, +-95, 42, -92, 20, -85, 4, -85, -4, +-84, -3, -87, 7, -91, 22, -102, 38, +-109, 48, -116, 47, -122, 42, -127, 32, +-115, 20, -98, 15, -86, 22, -80, 33, +-68, 40, -65, 43, -75, 44, -97, 38, +-113, 22, -128, 3, -140, -10, -142, -16, +-123, -6, -101, 17, -82, 43, -68, 66, +-57, 83, -61, 83, -78, 69, -101, 40, +-116, 11, -135, -14, -144, -29, -140, -30, +-121, -13, -103, 12, -86, 37, -72, 54, +-63, 66, -71, 67, -84, 59, -101, 46, +-113, 36, -126, 25, -131, 20, -132, 19, +-121, 18, -111, 13, -98, 8, -91, 4, +-86, 4, -86, 7, -85, 16, -88, 36, +-94, 57, -106, 73, -113, 80, -123, 75, +-126, 58, -128, 29, -120, 0, -114, -22, +-105, -30, -94, -25, -79, -3, -75, 25, +-79, 51, -87, 68, -97, 74, -113, 69, +-130, 55, -139, 33, -133, 15, -125, 4, +-113, 1, -99, 8, -80, 22, -77, 33, +-81, 39, -90, 36, -96, 31, -108, 21, +-119, 18, -126, 19, -121, 24, -117, 31, +-114, 41, -108, 44, -96, 44, -93, 38, +-94, 29, -98, 18, -97, 15, -102, 15, +-107, 22, -111, 30, -114, 39, -120, 40, +-120, 34, -116, 25, -107, 18, -104, 14, +-99, 17, -96, 26, -94, 40, -100, 53, +-105, 64, -117, 62, -123, 49, -128, 28, +-124, 8, -116, -9, -103, -15, -93, -10, +-81, 8, -82, 30, -90, 54, -105, 66, +-115, 68, -126, 58, -133, 43, -133, 24, +-119, 9, -107, 4, -95, 7, -86, 12, +-78, 20, -87, 28, -103, 36, -119, 40, +-128, 40, -135, 37, -136, 37, -126, 35, +-106, 34, -94, 33, -87, 30, -83, 24, +-82, 15, -95, 8, -107, 7, -117, 9, +-117, 19, -122, 31, -124, 46, -119, 54, +-110, 55, -106, 47, -104, 37, -105, 25, +-102, 13, -102, 1, -96, -1, -97, 9, +-99, 24, -106, 35, -111, 45, -120, 48, +-125, 47, -128, 41, -123, 34, -116, 27, +-103, 21, -92, 16, -80, 13, -77, 14, +-82, 16, -98, 18, -112, 22, -129, 26, +-140, 36, -144, 44, -131, 50, -118, 51, +-100, 45, -81, 32, -67, 20, -71, 7, +-82, -2, -97, -4, -112, 2, -132, 16, +-139, 32, -138, 47, -125, 57, -115, 55, +-99, 47, -85, 31, -73, 17, -78, 7, +-86, 8, -97, 12, -108, 23, -124, 31, +-134, 39, -135, 39, -127, 33, -120, 21, +-107, 13, -92, 9, -79, 14, -76, 24, +-74, 38, -83, 52, -99, 58, -121, 52, +-134, 37, -138, 11, -131, -8, -126, -14, +-115, -6, -101, 11, -85, 33, -76, 51, +-69, 62, -77, 63, -92, 54, -113, 33, +-126, 13, -139, 1, -142, 0, -137, 7, +-121, 24, -107, 39, -91, 50, -77, 48, +-68, 37, -74, 22, -85, 7, -100, -1, +-114, 4, -131, 19, -136, 38, -134, 56, +-129, 67, -124, 64, -112, 51, -99, 27, +-83, -1, -74, -24, -69, -27, -72, -13, +-80, 11, -98, 38, -115, 66, -134, 79, +-147, 73, -151, 52, -140, 27, -119, 1, +-93, -14, -74, -16, -57, -2, -51, 16, +-57, 34, -77, 45, -102, 52, -133, 49, +-155, 38, -165, 22, -154, 12, -131, 10, +-100, 16, -75, 24, -54, 35, -50, 39, +-55, 35, -73, 25, -97, 17, -125, 8, +-143, 6, -150, 10, -141, 21, -124, 34, +-105, 49, -90, 55, -76, 50, -72, 37, +-72, 21, -78, 5, -88, -5, -102, -10, +-108, -4, -113, 11, -116, 32, -121, 48, +-120, 57, -114, 54, -103, 45, -97, 29, +-85, 15, -76, 5, -75, 3, -83, 4, +-87, 9, -97, 18, -110, 30, -124, 38, +-127, 43, -125, 40, -115, 34, -103, 24, +-83, 19, -69, 14, -67, 15, -77, 16, +-85, 19, -99, 25, -114, 32, -127, 33, +-126, 33, -120, 28, -108, 24, -98, 18, +-82, 15, -72, 14, -72, 17, -81, 22, +-88, 28, -99, 35, -107, 40, -118, 40, +-118, 34, -117, 25, -111, 19, -106, 13, +-97, 11, -91, 12, -81, 18, -79, 25, +-78, 35, -88, 43, -95, 46, -103, 36, +-108, 27, -119, 19, -119, 12, -115, 8, +-104, 11, -93, 16, -79, 27, -73, 34, +-72, 36, -80, 35, -86, 29, -98, 19, +-109, 12, -121, 10, -119, 16, -112, 23, +-99, 33, -89, 38, -75, 41, -73, 37, +-77, 25, -83, 9, -89, -1, -100, -5, +-109, 0, -113, 13, -106, 31, -99, 47, +-93, 59, -93, 61, -87, 50, -87, 29, +-89, 8, -94, -7, -93, -10, -94, -7, +-93, 9, -94, 27, -91, 42, -92, 51, +-95, 49, -99, 37, -99, 22, -102, 7, +-96, 1, -94, 7, -84, 20, -81, 34, +-77, 47, -83, 52, -90, 47, -100, 31, +-105, 6, -107, -15, -103, -26, -97, -22, +-85, -2, -77, 28, -73, 57, -76, 74, +-74, 79, -88, 69, -99, 44, -106, 10, +-103, -14, -105, -27, -100, -27, -91, -17, +-79, 6, -74, 28, -74, 46, -78, 54, +-86, 57, -97, 50, -103, 38, -105, 27, +-98, 22, -93, 18, -84, 18, -82, 17, +-78, 14, -77, 6, -81, 0, -87, -4, +-90, -3, -95, 7, -97, 25, -96, 47, +-92, 64, -89, 69, -83, 66, -83, 49, +-77, 23, -76, -4, -77, -22, -85, -30, +-88, -24, -94, -7, -96, 16, -97, 37, +-93, 52, -89, 60, -80, 57, -75, 43, +-69, 30, -71, 17, -69, 7, -76, 1, +-85, 1, -97, 3, -98, 8, -105, 14, +-103, 20, -98, 26, -86, 33, -80, 36, +-72, 40, -65, 39, -62, 38, -71, 31, +-80, 20, -90, 10, -91, 3, -98, -2, +-97, 1, -97, 6, -85, 18, -82, 28, +-79, 37, -75, 38, -69, 36, -69, 30, +-73, 22, -73, 12, -70, 9, -79, 12, +-87, 14, -92, 15, -90, 16, -97, 16, +-94, 18, -92, 18, -79, 21, -71, 22, +-61, 24, -55, 26, -51, 29, -59, 25, +-72, 22, -89, 17, -104, 12, -114, 4, +-108, 3, -99, 7, -80, 16, -65, 27, +-51, 36, -49, 39, -48, 35, -59, 26, +-73, 16, -92, 6, -104, 1, -107, 3, +-99, 10, -91, 19, -73, 27, -61, 32, +-55, 33, -57, 23, -55, 13, -67, 5, +-75, 3, -86, 7, -89, 15, -89, 25, +-83, 34, -81, 38, -78, 37, -74, 27, +-73, 15, -77, 5, -74, -1, -71, -2, +-63, 7, -66, 18, -66, 28, -70, 33, +-70, 35, -83, 31, -88, 22, -93, 10, +-90, 6, -82, 6, -72, 16, -65, 28, +-57, 34, -55, 34, -56, 31, -65, 20, +-74, 7, -90, -5, -88, -9, -94, 0, +-94, 16, -88, 31, -71, 45, -61, 50, +-51, 48, -49, 37, -53, 23, -62, 4, +-70, -12, -76, -17, -80, -11, -91, -2, +-86, 9, -81, 23, -71, 35, -70, 40, +-62, 39, -58, 31, -52, 27, -57, 25, +-65, 20, -66, 13, -68, 9, -78, 5, +-82, 1, -83, -2, -75, -4, -74, 0, +-67, 12, -67, 22, -56, 35, -58, 45, +-60, 50, -64, 46, -66, 37, -74, 20, +-78, 1, -73, -13, -68, -18, -68, -15, +-67, -6, -65, 6, -55, 20, -62, 35, +-69, 46, -73, 44, -66, 36, -69, 25, +-63, 14, -59, 3, -55, -2, -54, -2, +-57, 2, -67, 6, -72, 11, -76, 15, +-76, 19, -76, 21, -67, 23, -64, 22, +-51, 21, -49, 21, -46, 22, -53, 19, +-63, 15, -76, 11, -78, 9, -78, 4, +-75, 1, -66, 3, -55, 12, -51, 22, +-50, 30, -58, 33, -59, 31, -64, 23, +-68, 15, -78, 7, -70, 1, -68, -2, +-60, 1, -53, 10, -51, 20, -54, 26, +-55, 29, -61, 26, -62, 19, -62, 9, +-62, 2, -68, 1, -61, 3, -57, 3, +-48, 9, -56, 19, -58, 25, -57, 23, +-57, 21, -66, 18, -63, 13, -59, 8, +-60, 7, -59, 8, -54, 11, -56, 13, +-56, 15, -58, 15, -55, 14, -62, 16, +-63, 18, -67, 16, -54, 13, -53, 12, +-56, 15, -53, 11, -48, 10, -53, 9, +-57, 10, -61, 13, -64, 16, -65, 16, +-62, 20, -65, 22, -57, 22, -58, 20, +-54, 18, -54, 11, -49, 7, -52, 7, +-51, 8, -55, 9, -58, 14, -61, 19, +-67, 20, -66, 16, -55, 16, -58, 16, +-57, 14, -50, 11, -38, 13, -44, 14, +-44, 14, -52, 12, -55, 12, -62, 7, +-66, 4, -66, 3, -61, 8, -58, 15, +-53, 26, -49, 34, -48, 36, -51, 32, +-50, 25, -58, 11, -56, -1, -63, -12, +-57, -16, -52, -11, -44, 5, -46, 19, +-47, 33, -50, 40, -56, 41, -55, 29, +-57, 13, -64, 0, -55, -9, -44, -16, +-36, -11, -41, 2, -35, 17, -43, 25, +-50, 29, -62, 24, -60, 13, -61, 4, +-61, 0, -53, -4, -37, 1, -34, 12, +-37, 22, -38, 29, -42, 31, -58, 21, +-60, 7, -66, -6, -59, -12, -53, -13, +-42, -3, -42, 10, -32, 25, -33, 35, +-41, 37, -52, 32, -61, 21, -66, 5, +-65, -4, -66, -8, -54, -7, -37, 0, +-25, 11, -29, 22, -23, 28, -36, 25, +-51, 20, -65, 10, -67, 0, -68, -7, +-66, -4, -55, 1, -35, 12, -22, 24, +-26, 33, -29, 31, -27, 22, -41, 8, +-51, -5, -61, -13, -65, -14, -68, -8, +-55, 3, -51, 17, -41, 31, -34, 40, +-32, 42, -32, 33, -36, 19, -41, 2, +-44, -12, -49, -19, -49, -17, -53, -9, +-51, 5, -59, 18, -44, 30, -40, 35, +-43, 37, -44, 27, -35, 17, -34, 6, +-37, -3, -40, -8, -42, -8, -39, -7, +-39, -2, -43, 7, -39, 15, -47, 19, +-46, 20, -47, 17, -42, 16, -51, 12, +-45, 11, -40, 9, -34, 10, -31, 13, +-35, 17, -39, 15, -37, 11, -41, 8, +-53, 7, -63, 1, -58, -2, -52, 1, +-40, 9, -42, 16, -27, 24, -18, 27, +-19, 27, -29, 21, -34, 15, -47, 4, +-61, -7, -60, -13, -57, -11, -50, -6, +-38, 3, -28, 14, -13, 23, -15, 27, +-25, 27, -40, 23, -40, 15, -54, 4, +-58, -2, -55, -3, -48, 2, -38, 8, +-30, 13, -28, 15, -26, 13, -27, 8, +-33, 3, -42, -1, -42, 0, -49, 7, +-41, 18, -45, 27, -38, 32, -31, 27, +-27, 20, -36, 7, -34, -8, -32, -23, +-44, -26, -45, -20, -35, -5, -33, 15, +-33, 34, -33, 45, -24, 49, -27, 41, +-33, 26, -48, 5, -43, -18, -45, -33, +-45, -33, -39, -24, -34, -7, -30, 13, +-22, 30, -19, 43, -25, 48, -29, 36, +-30, 20, -38, 4, -36, -8, -43, -18, +-40, -21, -41, -14, -35, -4, -29, 2, +-21, 9, -29, 16, -31, 24, -23, 23, +-29, 20, -34, 14, -28, 13, -28, 13, +-33, 14, -40, 9, -34, 2, -36, -9, +-30, -15, -35, -16, -28, -13, -25, -9, +-27, 6, -26, 25, -22, 38, -25, 43, +-32, 43, -31, 31, -32, 14, -38, -3, +-39, -18, -49, -28, -40, -27, -35, -17, +-27, 0, -28, 17, -16, 32, -13, 40, +-11, 39, -16, 28, -28, 16, -34, 4, +-46, -6, -58, -12, -52, -11, -44, -7, +-36, 1, -24, 7, 3, 10, 5, 14, +3, 14, -9, 9, -13, 5, -26, 2, +-48, 2, -60, 1, -51, 2, -40, 3, +-34, 6, -17, 7, -4, 8, -3, 8, +1, 11, -16, 12, -27, 9, -38, 6, +-40, 7, -49, 8, -45, 9, -38, 6, +-26, 3, -14, 2, -11, 5, -9, 4, +-13, 6, -25, 7, -23, 7, -19, 6, +-23, 9, -36, 9, -21, 8, -20, 5, +-22, 3, -30, 0, -30, -3, -28, -2, +-32, 3, -33, 6, -22, 9, -9, 14, +-11, 21, -7, 21, -2, 19, -21, 15, +-31, 7, -40, -6, -39, -13, -48, -12, +-45, -4, -42, 5, -23, 14, -2, 22, +3, 28, 4, 28, 0, 24, -7, 13, +-18, 1, -39, -11, -49, -17, -46, -18, +-39, -9, -42, -1, -17, 9, -1, 17, +5, 23, 9, 22, 9, 19, -2, 13, +-24, 8, -38, 2, -44, -2, -45, -5, +-49, -3, -42, 0, -16, 5, -7, 7, +1, 11, 2, 13, 6, 16, -5, 16, +-12, 15, -28, 11, -38, 7, -34, 0, +-32, -5, -28, -8, -19, -10, -10, -8, +-5, 2, -7, 8, -6, 15, -13, 21, +-13, 25, -27, 21, -21, 15, -15, 3, +-17, -5, -19, -11, -10, -10, -10, -6, +-22, -3, -22, 1, -21, 9, -17, 14, +-17, 17, -23, 16, -10, 15, -7, 12, +-6, 12, -11, 9, -10, 8, -22, 6, +-26, 5, -27, 1, -30, -1, -25, -2, +-22, -1, -12, -3, 0, 1, 4, 9, +-1, 16, -8, 19, -8, 21, -19, 17, +-18, 7, -26, -4, -22, -9, -10, -13, +-4, -12, -11, -6, -9, 6, -5, 15, +-13, 19, -14, 17, -16, 14, -17, 8, +-15, 4, -18, 0, -8, -2, -7, 2, +-9, 8, -16, 15, -9, 20, -19, 19, +-25, 13, -19, 3, -16, -1, -12, -7, +-6, -12, -2, -8, -1, 0, 5, 8, +1, 17, -16, 23, -20, 25, -26, 17, +-18, 7, -19, 0, -18, -3, -10, -4, +0, -3, 2, 1, 3, 7, 5, 12, +-9, 13, -17, 9, -13, 4, -19, 3, +-27, 5, -30, 5, -12, 7, -2, 10, +3, 17, -2, 20, 7, 18, 9, 13, +-6, 5, -13, -6, -16, -13, -21, -15, +-23, -11, -16, -5, -15, 9, -11, 23, +-1, 33, -2, 38, 2, 35, -2, 21, +-1, 5, -4, -11, -5, -19, -10, -23, +-12, -20, -14, -11, -12, 3, -1, 17, +-9, 30, -19, 35, -10, 30, -2, 20, +-2, 9, -8, -1, 2, -8, 5, -12, +11, -9, 2, -4, -2, 3, -4, 8, +-17, 11, -22, 9, -19, 8, -20, 7, +-18, 7, 0, 6, 14, 10, 20, 14, +24, 18, 11, 17, 7, 11, -5, 3, +-22, -6, -37, -15, -35, -17, -25, -13, +-10, -4, 5, 10, 14, 25, 31, 37, +32, 43, 14, 34, 3, 19, -8, -1, +-22, -18, -34, -31, -25, -34, -18, -29, +-3, -11, 5, 13, 15, 34, 24, 42, +18, 43, 8, 34, 3, 19, 1, -1, +-15, -13, -22, -21, -12, -23, -6, -17, +6, -6, 7, 3, 10, 15, 9, 20, +10, 19, 1, 13, -2, 6, 0, 2, +-2, 4, 2, 7, 3, 11, 5, 14, +8, 14, 4, 7, 2, 0, -1, -8, +-8, -14, -18, -16, -4, -13, 4, -1, +5, 16, 7, 31, 14, 42, 19, 43, +15, 32, 5, 16, -5, -3, -5, -24, +-9, -36, -11, -37, -4, -24, -5, -5, +4, 17, 13, 32, 20, 40, 18, 39, +18, 29, 12, 13, 5, 0, 0, -11, +-11, -16, -11, -14, -5, -7, 1, 1, +5, 11, 4, 14, 9, 13, 17, 5, +22, 1, 5, 1, 3, 3, 8, 7, +6, 14, 3, 19, 5, 20, 10, 14, +10, 4, 10, -6, 6, -15, 4, -20, +-1, -17, -6, -9, 6, 3, 11, 15, +13, 28, 15, 33, 24, 30, 22, 20, +16, 5, 7, -11, 0, -18, -1, -19, +-8, -15, -10, -6, -5, 8, 8, 17, +19, 22, 23, 21, 26, 16, 23, 8, +23, 0, 10, -4, 0, -2, -3, -2, +-5, 3, -8, 10, 0, 15, 11, 13, +12, 9, 17, 3, 20, -1, 23, -7, +20, -8, 10, -7, 12, 2, 12, 12, +8, 18, 2, 20, 5, 25, 1, 22, +2, 13, 5, 1, 3, -10, 13, -20, +21, -18, 22, -11, 23, -2, 25, 9, +21, 20, 12, 28, 8, 31, -3, 26, +-6, 17, -10, 4, -3, -6, 9, -12, +17, -11, 18, -9, 27, -3, 38, 5, +28, 13, 18, 13, 11, 14, 4, 13, +1, 11, -6, 7, -4, 6, 4, 5, +16, 6, 21, 3, 31, 2, 31, 1, +23, -1, 22, -5, 16, -4, 8, -1, +1, 5, -1, 12, 0, 22, 7, 25, +14, 24, 14, 16, 25, 7, 28, -6, +27, -12, 17, -15, 10, -14, 11, -10, +12, 4, 7, 17, 2, 27, 13, 29, +16, 27, 18, 17, 23, 5, 21, -7, +18, -16, 16, -18, 16, -13, 14, -8, +18, 1, 15, 12, 19, 21, 24, 24, +18, 21, 15, 13, 14, 7, 12, 1, +7, -3, 6, -6, 8, -5, 15, -2, +26, 1, 27, 1, 35, 3, 35, 4, +29, 7, 21, 7, 14, 8, 5, 9, +-1, 8, 4, 5, 8, 3, 20, 0, +25, 0, 26, -4, 36, -5, 41, -5, +32, 2, 16, 9, 9, 18, 0, 21, +-1, 20, 0, 12, 6, 5, 22, -4, +31, -10, 35, -11, 33, -6, 33, -1, +23, 8, 15, 16, 10, 18, 7, 16, +11, 14, 10, 8, 16, 3, 22, 0, +22, -1, 18, -3, 22, -1, 25, 2, +17, 9, 13, 13, 11, 15, 20, 13, +24, 13, 20, 12, 17, 11, 21, 5, +24, 0, 16, -4, 17, -6, 16, -9, +20, -7, 24, -4, 24, 2, 29, 7, +33, 11, 34, 13, 27, 19, 23, 22, +10, 18, 6, 5, 13, -6, 16, -14, +21, -18, 22, -17, 25, -7, 31, 0, +35, 9, 30, 16, 26, 21, 29, 21, +22, 20, 15, 15, 7, 8, 8, -3, +17, -13, 23, -18, 27, -15, 30, -10, +35, -2, 31, 4, 34, 12, 30, 15, +22, 16, 19, 12, 16, 10, 16, 7, +13, 5, 12, 2, 15, 0, 27, -3, +30, -2, 26, -1, 30, -1, 31, 0, +31, 3, 28, 1, 25, 5, 18, 10, +17, 12, 15, 14, 10, 14, 15, 9, +15, 4, 22, -1, 31, -4, 34, -6, +34, -7, 35, -6, 36, -1, 30, 4, +23, 11, 10, 14, 8, 16, 11, 14, +11, 9, 15, 5, 21, 1, 30, -4, +36, -3, 38, -1, 31, 2, 28, 5, +26, 12, 18, 13, 14, 11, 13, 6, +15, 3, 15, 1, 22, 1, 25, -1, +28, -2, 34, -1, 35, 5, 36, 9, +31, 10, 22, 9, 19, 8, 20, 2, +21, -2, 19, -6, 22, -2, 21, 2, +28, 9, 26, 12, 21, 11, 29, 4, +35, 1, 32, -1, 27, -5, 30, -7, +29, -5, 28, 0, 27, 10, 24, 14, +21, 14, 16, 12, 16, 11, 21, 2, +25, -7, 24, -11, 30, -10, 40, -5, +40, 2, 38, 7, 31, 13, 31, 12, +28, 10, 16, 6, 9, 1, 12, -5, +15, -5, 18, -4, 31, 0, 37, 5, +39, 12, 40, 15, 39, 15, 35, 8, +22, 0, 15, -7, 14, -13, 20, -17, +20, -12, 23, -2, 29, 9, 34, 17, +40, 21, 40, 17, 36, 11, 30, 4, +26, -2, 16, -9, 12, -12, 17, -11, +17, -3, 23, 4, 29, 8, 35, 11, +35, 13, 33, 13, 30, 9, 28, 1, +26, -2, 20, -2, 25, -1, 28, -2, +27, 1, 29, 3, 31, 1, 30, -3, +31, -6, 32, -7, 23, -2, 21, 1, +26, 2, 32, 3, 34, 10, 31, 15, +31, 16, 32, 10, 30, 1, 26, -9, +29, -12, 25, -13, 17, -12, 21, -10, +27, -3, 29, 5, 32, 11, 40, 13, +42, 16, 36, 15, 31, 11, 29, 3, +25, -4, 16, -11, 14, -13, 21, -10, +23, -7, 26, -5, 35, 3, 42, 11, +37, 17, 33, 17, 29, 14, 28, 6, +21, 3, 20, -2, 22, -4, 20, -4, +23, -5, 35, -9, 42, -6, 38, -4, +36, -1, 33, 4, 27, 6, 30, 2, +31, 5, 25, 10, 22, 12, 27, 8, +29, 3, 30, -8, 32, -11, 32, -11, +33, -11, 31, -10, 30, -1, 30, 7, +28, 15, 26, 19, 27, 18, 29, 10, +26, 4, 31, -7, 38, -19, 39, -23, +36, -19, 33, -14, 32, -3, 30, 5, +26, 11, 23, 15, 29, 16, 30, 11, +31, 6, 35, -3, 35, -9, 36, -16, +39, -15, 36, -12, 26, -5, 23, -1, +22, 6, 23, 11, 24, 10, 26, 3, +35, 3, 39, 3, 36, 0, 38, -3, +39, 0, 28, 2, 20, 4, 23, -1, +22, -6, 19, -7, 23, -5, 30, -8, +37, -5, 41, 0, 41, 9, 36, 15, +33, 16, 31, 8, 28, 1, 22, -8, +22, -13, 25, -15, 27, -11, 28, -8, +32, 0, 39, 6, 38, 10, 37, 10, +35, 9, 29, 3, 24, -4, 27, -8, +28, -7, 24, -2, 24, 1, 31, -1, +40, -3, 42, 1, 35, 3, 33, -4, +33, -5, 32, -4, 27, -4, 25, -3, +27, 1, 30, 3, 31, 5, 33, 3, +38, 1, 37, -1, 35, -4, 35, -6, +31, 1, 22, 1, 19, -2, 24, -3, +32, 0, 35, 1, 32, 3, 36, 1, +42, 0, 39, 0, 32, 1, 29, -6, +28, -6, 23, -1, 19, 3, 24, 3, +30, 5, 36, 0, 43, -3, 49, -1, +43, -1, 30, -8, 28, -8, 30, -8, +18, 2, 11, 7, 20, 7, 29, 7, +32, 11, 41, 6, 48, -1, 43, -6, +35, -8, 34, -10, 31, -8, 20, -8, +15, -4, 25, 0, 29, 6, 27, 7, +35, 9, 44, 2, 45, -5, 45, -3, +41, -2, 31, -10, 25, -12, 26, -10, +24, -7, 22, -4, 27, -1, 34, 0, +41, 6, 44, 7, 44, 4, 39, 2, +29, 1, 25, -6, 24, -5, 15, -5, +14, -7, 28, -6, 38, 2, 38, 2, +43, 3, 49, 2, 43, 0, 33, -2, +26, -1, 25, -9, 23, -10, 20, -7, +27, -4, 39, -3, 38, -1, 36, 0, +45, 2, 48, 1, 34, -1, 25, 0, +27, 6, 20, 5, 9, -1, 19, -6, +38, -10, 41, -13, 38, -9, 50, -5, +56, 0, 39, 4, 30, 8, 30, 9, +19, 9, 8, -4, 18, -13, 31, -11, +30, -7, 33, -9, 47, 0, 52, 8, +41, 11, 35, 10, 34, 4, 27, -2, +16, -3, 18, -9, 25, -16, 30, -14, +40, -6, 48, -5, 48, -1, 47, 1, +45, 0, 40, -1, 31, 0, 24, -2, +21, -2, 23, -1, 26, -1, 30, 1, +35, 0, 39, -9, 45, -9, 44, -3, +38, -2, 30, -4, 28, 0, 28, 2, +26, 6, 28, 4, 29, 1, 33, 0, +38, 1, 41, -5, 42, -8, 37, -8, +30, -8, 30, -10, 34, -6, 28, -8, +26, -6, 38, 0, 46, 6, 39, 10, +34, 14, 38, 6, 33, -1, 23, -3, +23, -9, 27, -19, 21, -15, 21, -7, +39, -2, 50, 1, 44, 2, 45, 3, +51, 10, 41, 4, 27, -6, 23, -6, +18, -2, 14, -3, 18, -2, 28, -2, +35, -4, 42, -7, 53, -8, 58, -11, +53, -8, 41, -6, 31, -3, 26, 3, +23, 8, 15, 4, 11, 4, 22, 2, +40, -6, 50, -16, 51, -12, 51, -9, +49, -3, 38, -2, 29, -1, 23, 1, +13, 6, 12, 2, 25, -1, 37, -1, +40, 0, 43, -2, 51, -1, 55, -8, +45, -10, 34, -11, 28, -11, 25, -9, +24, -3, 25, -2, 26, 4, 32, 9, +43, 4, 50, -8, 51, -7, 47, -8, +41, -10, 37, -9, 35, -8, 29, -6, +25, 2, 26, 1, 31, -4, 35, -6, +43, -7, 46, -10, 43, -3, 43, -2, +47, -4, 39, 1, 25, 8, 23, 3, +30, -4, 33, -14, 36, -17, 46, -10, +47, -3, 38, -3, 37, 4, 38, 10, +26, 6, 20, -1, 29, -3, 32, -5, +29, -3, 38, -6, 51, -7, 50, -3, +44, 0, 45, -4, 36, -2, 20, -1, +20, -8, 28, -7, 24, 4, 21, 3, +41, -3, 56, -5, 54, -4, 52, -6, +52, -5, 41, -10, 26, -5, 20, 6, +16, 5, 15, -3, 20, 1, 33, -1, +47, -6, 51, -8, 51, -8, 54, -7, +50, 3, 33, 6, 23, 4, 20, 2, +18, -2, 21, -11, 30, -7, 39, -7, +41, -11, 48, -6, 58, 1, 55, -1, +41, -2, 35, -5, 34, -7, 25, -7, +22, -9, 34, -14, 39, -6, 36, 3, +44, 3, 57, -1, 46, -3, 34, -9, +42, -13, 45, -15, 28, -15, 24, -10, +41, -3, 40, 1, 33, 6, 46, 4, +55, -4, 42, -8, 35, -3, 42, -5, +34, -9, 20, -9, 22, -3, 34, 0, +35, 0, 32, -7, 44, -6, 57, -2, +54, -4, 48, -7, 46, 3, 36, 4, +21, 0, 18, -2, 23, -6, 27, -13, +30, -11, 41, -11, 56, -6, 60, 2, +49, 5, 43, 4, 39, 11, 28, 3, +19, -8, 23, -10, 26, -6, 30, -7, +42, -8, 55, -8, 54, -5, 51, -1, +48, -5, 42, -11, 32, -5, 27, -1, +26, -1, 25, 3, 32, 5, 45, 0, +47, -2, 44, -7, 50, -12, 51, -13, +39, -12, 32, -10, 34, 2, 28, 7, +22, 4, 30, 5, 38, 7, 36, -5, +41, -11, 53, -10, 51, -3, 35, -1, +36, -2, 46, -9, 38, -5, 28, -2, +33, -10, 39, -13, 36, -7, 40, -6, +48, 0, 44, 5, 37, 3, 39, -2, +44, -5, 39, -8, 30, -9, 29, -10, +43, -12, 47, -9, 40, 6, 39, 3, +46, -4, 43, -1, 31, 2, 29, -4, +29, -5, 25, -6, 26, -2, 38, 3, +47, 1, 41, -4, 44, -1, 57, -5, +54, -11, 38, -10, 32, -5, 31, -5, +23, -1, 21, 0, 28, -3, 36, -6, +42, -7, 53, -10, 61, -3, 58, -2, +49, -5, 39, 0, 34, 6, 26, -2, +14, -7, 13, -10, 28, -10, 44, -8, +46, -4, 50, -4, 61, 3, 60, 5, +45, 0, 37, -7, 34, -7, 23, -14, +18, -13, 31, -3, 35, 4, 31, 2, +41, 3, 58, -1, 57, -5, 48, -12, +44, -17, 41, -14, 34, -2, 29, 0, +29, 2, 27, 9, 29, 9, 39, -3, +48, -11, 46, -17, 48, -15, 48, -8, +40, -2, 37, -2, 38, 6, 33, 5, +27, 1, 34, 0, 38, -3, 35, -12, +39, -10, 47, -5, 48, -3, 42, -6, +42, -7, 42, -6, 35, -1, 31, -6, +37, -11, 42, -4, 40, 4, 41, 0, +46, 0, 45, 0, 36, -2, 29, -8, +33, -12, 38, -17, 35, -10, 36, -2, +46, 3, 45, 8, 38, 9, 45, -2, +49, -7, 36, -7, 26, -10, 33, -11, +33, -2, 22, 5, 26, 7, 46, 0, +51, -7, 45, -9, 51, -6, 54, -13, +37, -12, 28, 2, 32, 9, 25, 7, +16, 8, 28, 0, 47, -9, 48, -13, +46, -15, 56, -18, 56, -10, 44, -7, +40, -2, 36, 7, 24, 7, 19, -2, +29, 0, 35, 1, 33, -6, 41, -10, +54, -8, 52, -4, 43, 2, 39, -4, +37, -8, 32, -2, 28, 1, 33, -8, +36, -3, 32, 4, 34, 3, 42, 0, +43, -1, 34, -7, 37, -8, 45, -8, +40, -4, 33, 2, 32, 8, 35, 3, +32, 2, 34, 1, 41, -10, 42, -18, +37, -12, 41, -6, 48, -1, 39, -1, +32, -1, 41, 2, 44, 0, 37, -12, +37, -13, 42, -6, 39, -4, 39, -6, +47, -2, 49, -6, 41, -8, 38, -6, +39, -6, 33, -11, 30, -10, 38, -9, +44, 0, 42, 11, 42, 10, 45, 0, +40, 0, 34, -2, 34, -11, 31, -17, +26, -13, 30, -6, 41, 2, 45, 1, +46, 4, 45, 9, 45, 5, 40, -8, +39, -11, 37, -11, 30, -10, 26, -6, +32, -1, 40, -3, 42, -2, 42, -4, +46, -4, 48, 0, 43, 1, 35, -4, +33, 3, 35, 6, 32, -4, 31, -13, +41, -13, 45, -16, 40, -15, 43, -9, +47, -1, 42, 7, 33, 11, 39, 4, +44, 3, 33, 3, 28, -9, 39, -20, +47, -16, 39, -13, 38, -7, 43, -2, +41, 2, 37, -2, 42, -2, 45, -6, +36, -1, 33, 2, 37, -4, 41, -5, +40, 3, 38, -1, 39, -8, 40, -11, +41, -11, 36, -11, 35, -7, 41, -10, +42, -4, 37, 7, 39, 7, 44, 0, +40, -1, 40, -8, 48, -13, 47, -11, +33, -4, 28, -3, 35, -2, 32, -1, +27, 0, 34, -3, 44, -7, 43, -10, +46, 0, 51, 3, 49, -3, 42, -4, +36, 2, 33, -3, 28, -8, 22, -13, +29, -15, 40, -11, 48, -3, 49, -1, +49, 6, 52, 5, 50, -1, 40, -7, +33, -8, 31, -14, 27, -15, 28, -8, +35, 0, 43, 1, 42, 2, 46, -3, +54, -3, 51, -5, 41, -13, 35, -13, +34, -1, 31, 2, 30, 1, 31, 2, +34, 3, 38, -3, 43, -8, 46, -14, +44, -11, 45, -8, 45, -6, 42, -2, +39, 5, 40, 1, 34, -7, 32, -8, +43, -6, 41, -12, 32, -10, 39, -4, +48, 1, 44, 2, 36, -1, 41, -7, +45, -4, 37, -6, 33, -11, 43, -11, +46, -3, 34, -1, 37, 3, 45, 3, +37, -1, 30, -7, 40, -9, 44, -13, +39, -8, 38, -5, 43, -4, 45, 0, +41, 6, 38, -2, 42, -6, 40, -5, +32, -2, 31, -3, 35, -1, 33, 0, +29, 5, 35, 1, 48, -12, 50, -15, +44, -5, 45, -6, 43, -6, 38, 0, +34, 4, 34, 5, 29, 3, 30, -8, +44, -14, 50, -14, 45, -13, 46, -10, +49, -2, 45, -2, 39, -3, 37, 2, +32, 3, 27, -5, 31, -7, 41, -7, +44, -6, 46, -5, 50, -2, 47, -1, +38, 2, 34, -4, 35, -13, 31, -13, +30, -4, 35, 0, 36, 7, 35, 8, +43, 6, 52, 2, 44, -4, 38, -12, +38, -13, 35, -14, 30, -10, 27, 3, +33, 10, 36, 3, 39, 3, 44, 5, +46, 3, 37, -6, 35, -10, 39, -10, +38, -1, 32, 2, 28, 1, 32, 1, +36, 4, 37, -5, 38, -9, 42, -5, +40, 1, 35, 2, 38, 7, 40, 6, +36, 3, 32, -2, 34, -9, 41, -15, +39, -13, 38, -16, 43, -11, 46, 3, +41, 9, 41, 3, 42, 2, 38, -1, +38, -6, 40, -10, 39, -13, 36, -13, +42, -1, 43, 1, 38, -4, 43, -7, +50, -8, 44, -11, 34, -3, 34, 3, +31, 3, 28, 5, 33, 8, 39, 6, +44, 1, 42, -8, 44, -12, 45, -9, +41, -6, 35, -12, 35, -4, 32, 6, +28, 5, 35, 2, 38, 2, 37, 0, +42, 0, 46, -3, 46, -5, 44, -3, +41, 1, 35, -5, 34, -5, 34, -5, +33, -10, 36, -12, 39, -4, 44, -1, +45, 1, 43, 3, 42, 4, 41, 3, +38, -1, 39, -10, 40, -10, 35, -4, +38, -4, 39, -6, 39, -2, 41, -2, +39, -5, 37, -7, 41, -8, 44, -10, +43, -4, 44, -2, 45, 3, 43, 7, +39, 2, 40, -7, 39, -7, 34, -11, +35, -18, 41, -17, 44, -7, 38, 1, +37, 9, 44, 6, 43, 3, 39, 2, +40, -4, 47, -16, 42, -12, 38, -6, +43, -6, 38, -4, 33, -1, 38, -4, +40, -2, 34, -5, 35, -7, 42, -6, +49, -3, 50, -3, 46, 3, 45, 5, +42, -1, 34, -5, 29, -5, 28, -11, +28, -11, 31, -6, 34, 3, 36, 9, +47, 9, 50, -1, 52, -3, 53, -2, +44, -4, 32, -9, 24, -3, 25, -2, +28, 0, 27, 3, 28, 1, 42, -3, +51, -2, 49, -7, 53, -9, 54, -3, +44, 0, 36, -2, 35, 0, 36, -4, +34, -7, 28, -6, 31, -2, 40, -3, +40, 0, 40, -2, 47, -3, 55, -1, +49, -2, 39, -8, 40, -4, 39, -4, +33, -6, 33, -5, 40, 2, 37, 2, +33, 3, 42, 0, 46, -6, 45, -9, +42, -8, 42, -9, 46, -3, 39, 0, +37, -2, 44, -3, 41, 4, 34, 1, +37, -1, 36, -2, 34, -1, 37, 0, +38, 0, 42, -5, 43, -4, 43, -4, +45, -8, 45, -8, 39, -1, 39, -2, +40, -3, 38, 4, 38, 8, 32, 2, +33, -2, 42, -9, 44, -15, 45, -14, +50, -11, 49, -6, 43, 5, 43, 6, +41, 4, 35, 4, 30, 6, 23, -2, +29, -7, 40, -13, 41, -9, 45, -3, +54, -1, 52, -3, 48, 1, 46, -3, +42, -8, 36, -9, 31, -8, 37, -9, +39, 0, 34, 6, 35, 6, 46, 0, +52, -7, 47, -15, 46, -15, 49, -14, +42, -9, 32, 2, 31, 13, 36, 13, +34, 9, 37, 1, 47, -5, 45, -9, +37, -13, 40, -21, 47, -14, 43, -5, +38, -1, 41, 3, 42, 10, 41, 4, +46, -1, 44, -1, 39, -5, 42, -7, +39, -3, 33, -5, 34, -3, 35, -2, +34, -5, 40, -7, 44, 1, 41, 1, +45, 1, 43, 7, 41, 10, 45, 3, +38, 2, 30, -3, 34, -4, 30, -5, +28, -10, 37, -12, 41, -2, 43, 0, +48, 2, 52, 4, 51, 6, 48, -1, +46, -4, 45, -7, 40, -10, 31, -14, +35, -14, 39, -14, 41, -9, 47, -7, +48, -5, 54, 2, 56, 8, 49, 2, +51, -2, 48, -4, 37, -9, 34, -16, +42, -18, 38, -17, 33, -8, 39, 1, +44, 5, 44, 9, 46, 12, 46, 5, +49, -2, 47, -7, 45, -11, 44, -15, +37, -9, 34, -4, 34, 0, 34, -1, +37, -1, 36, 1, 42, 1, 51, -7, +51, -5, 49, 4, 48, 6, 44, -1, +43, -4, 47, -10, 37, -13, 29, -14, +36, -12, 34, -10, 36, -2, 46, 6, +45, 11, 49, 13, 54, 9, 49, -3, +48, -8, 41, -12, 34, -17, 33, -15, +31, -6, 28, 2, 31, 11, 38, 11, +41, 10, 44, 5, 49, 0, 51, -12, +57, -15, 49, -13, 45, -8, 44, -6, +33, 0, 31, 0, 33, 1, 30, -2, +35, -1, 37, 1, 40, 5, 48, 1, +53, 1, 53, 1, 53, -3, 50, -10, +40, -11, 37, -13, 33, -10, 25, -8, +33, -2, 36, 9, 32, 18, 42, 12, +52, 7, 52, 2, 50, -6, 54, -17, +48, -18, 37, -18, 41, -14, 37, -8, +33, 0, 39, 4, 41, 9, 45, 7, +47, 5, 48, -1, 51, -8, 50, -14, +44, -11, 41, -10, 42, -11, 41, -9, +39, 0, 41, 6, 39, 7, 42, 3, +44, 2, 41, -3, 50, -8, 48, -15, +45, -12, 50, -7, 41, -4, 42, -3, +47, 1, 41, 0, 40, -1, 46, -5, +43, -6, 42, -3, 45, 3, 32, 2, +38, 3, 50, 2, 37, 0, 39, -10, +51, -13, 46, -17, 49, -13, 50, -8, +43, 1, 46, 10, 42, 15, 39, 7, +44, 0, 42, -7, 37, -16, 40, -24, +44, -17, 41, -10, 44, -1, 43, 11, +46, 23, 47, 20, 38, 12, 43, -1, +43, -9, 32, -15, 35, -18, 36, -20, +38, -8, 43, 2, 42, 7, 49, 6, +56, 6, 48, 2, 46, -4, 53, -12, +48, -11, 39, -11, 44, -7, 43, -5, +35, -1, 39, -2, 40, -6, 41, -10, +43, -5, 43, 0, 45, 5, 42, 8, +48, 12, 48, 10, 43, 5, 47, -7, +40, -13, 33, -18, 37, -21, 36, -18, +33, -6, 41, 3, 49, 10, 49, 14, +56, 17, 57, 9, 48, 0, 49, -11, +42, -17, 31, -19, 33, -15, 26, -8, +26, 2, 37, 7, 43, 10, 51, 10, +53, 9, 57, 1, 57, -4, 49, -10, +46, -11, 38, -10, 36, -11, 37, -11, +35, -1, 36, 2, 38, 2, 42, 2, +42, 2, 52, -1, 55, 1, 42, 3, +46, 4, 51, 1, 41, -2, 38, -6, +39, -7, 37, -12, 34, -15, 37, -13, +48, -4, 45, 1, 47, 10, 52, 14, +51, 15, 50, 6, 46, -6, 45, -19, +44, -20, 38, -19, 28, -13, 35, -9, +51, 2, 43, 11, 47, 15, 57, 12, +44, 6, 48, -9, 53, -19, 42, -22, +44, -15, 39, -6, 31, 5, 38, 13, +38, 19, 35, 13, 40, 5, 44, -3, +40, -9, 46, -14, 46, -11, 40, -2, +45, 8, 38, 10, 40, 8, 45, 3, +33, 1, 40, -6, 41, -12, 35, -11, +48, -3, 47, 0, 41, 7, 52, 9, +49, 7, 36, -1, 44, -9, 45, -15, +31, -12, 40, -9, 41, 0, 33, 9, +47, 17, 45, 17, 37, 14, 46, 4, +39, -9, 42, -23, 51, -26, 43, -20, +40, -8, 45, 1, 49, 9, 46, 12, +48, 15, 47, 8, 41, -2, 41, -10, +37, -13, 40, -19, 41, -16, 41, -5, +45, 7, 43, 8, 47, 9, 50, 8, +44, 2, 50, -7, 48, -12, 39, -12, +42, -7, 40, -7, 40, -2, 39, 2, +43, 7, 42, 2, 40, -4, 53, -9, +52, -8, 48, -10, 53, -5, 48, 4, +40, 12, 37, 10, 37, 6, 30, 1, +32, -7, 41, -18, 36, -16, 42, -8, +48, 1, 45, 5, 58, 15, 55, 21, +41, 21, 42, 8, 37, -6, 31, -19, +32, -22, 31, -22, 29, -12, 36, 1, +49, 13, 50, 18, 55, 21, 58, 13, +54, 1, 53, -12, 41, -17, 37, -20, +32, -15, 27, -7, 35, 4, 33, 9, +40, 11, 51, 7, 47, 0, 56, -10, +63, -13, 53, -12, 46, -5, 47, 2, +38, 10, 29, 11, 31, 8, 27, 1, +29, -4, 40, -14, 39, -16, 51, -13, +59, -3, 54, 7, 55, 15, +}; \ No newline at end of file diff --git a/project/realtek_ameba1_va0_example/example_sources/i2s/src/birds_48000_2ch_16b.c b/project/realtek_ameba1_va0_example/example_sources/i2s/src/birds_48000_2ch_16b.c new file mode 100644 index 0000000..9bb76a1 --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/i2s/src/birds_48000_2ch_16b.c @@ -0,0 +1,34985 @@ +#include +int sample_size=139916; + +SECTION(".sdram.data") +short sample[]={ +1, 1, -2, 0, 0, 1, 1, 0, +-1, 2, -2, 2, 0, -1, 1, -1, +2, 0, 1, 2, -4, 4, -3, 5, +-4, 1, -1, 2, 0, -2, 2, -1, +2, 0, 0, 2, -2, 0, 1, -2, +2, -1, 1, -1, 2, 1, -1, 1, +-2, 2, -3, -1, 3, -1, 1, -2, +2, 0, 2, 0, -1, 2, -3, 3, +-4, 3, -3, 4, -2, 0, 2, 0, +1, -2, 1, -1, -2, -1, 0, 0, +3, -3, 5, -3, 4, -4, 3, -3, +1, -2, 1, -3, 3, -2, 2, 0, +2, 1, 0, -3, 4, -5, 2, -6, +3, 0, 0, 1, 0, 2, 1, 1, +-3, 1, -5, 2, -3, 0, 1, 0, +1, -1, 3, 0, 0, -2, 0, 1, +-3, 1, -3, 2, 0, -1, 4, -2, +3, -1, -2, 2, -5, 4, -5, 2, +1, 1, 2, -1, 2, 2, -2, 0, +-1, 0, -1, -3, 1, 0, 0, 3, +0, 1, 3, -4, 4, -6, 2, -2, +0, -2, 2, 0, 2, 0, 2, 3, +-3, 1, -3, 0, -1, -1, 2, -3, +5, -4, 5, -1, 2, 1, -1, -1, +-1, 0, -2, -1, 2, -1, 4, -2, +4, 0, 0, -1, -1, -1, -1, -3, +3, -2, 3, 1, -1, 3, -1, 3, +-3, 0, -2, 0, -1, -3, 4, -1, +3, -3, 5, -1, 1, -2, -1, -1, +-1, -2, 1, -1, 3, 0, 3, 0, +2, 1, -3, -1, -1, 0, 0, -3, +2, 1, 0, 2, 0, 2, 0, -2, +1, -1, -4, 2, -5, 4, 0, 3, +-1, 1, 0, 1, -1, -3, 1, -3, +1, -1, 1, 3, -2, 3, 0, 1, +1, -2, 0, -1, -2, 2, -2, 1, +1, 0, 3, -1, 4, -2, 0, -4, +2, -2, 1, -3, 4, -3, 5, -2, +2, 2, -2, 0, -1, -2, 2, -3, +1, -2, 3, 1, 0, 1, -2, 4, +-4, 2, -4, 3, -5, 1, 2, 0, +2, -1, 0, 2, -1, 0, 1, -3, +1, -1, 0, 1, 0, 4, -4, 3, +-1, 2, -2, -1, 0, 0, 0, -2, +4, -4, 6, -5, 5, -1, -1, 2, +-4, 1, 1, -1, 0, -1, 2, 2, +0, 0, -1, 2, -4, 3, -4, 3, +-3, -1, 3, -2, 4, -3, 3, -2, +3, -3, 1, -2, -1, 1, -2, 2, +-1, 3, -1, -2, 3, -2, 0, -3, +1, -1, 1, 1, -1, 3, -4, 4, +-3, 2, -1, -1, -1, -1, 1, 1, +-1, -2, 4, -2, 3, -1, -1, 2, +-3, 1, -1, 2, -3, 2, -2, 2, +0, 3, -4, 4, -5, 3, -1, -1, +1, 0, -1, 0, 2, 1, -1, -1, +1, 1, -1, 0, -2, 2, -2, 2, +0, 1, -1, 2, -3, 2, -1, 1, +-3, 0, 0, 2, 0, -1, 1, 1, +-1, 1, -1, 1, -2, 0, 0, 1, +0, 0, 0, 1, 1, 2, -1, 0, +-1, 0, 1, -3, 4, -2, 2, -2, +3, 0, 0, -1, 0, 0, 1, -1, +1, -1, 2, -2, 2, -1, 1, 1, +-1, -2, 2, 0, -1, -1, 2, -1, +3, -3, 3, -1, 1, -1, 0, 1, +-2, 0, 0, -1, 3, -1, -1, 0, +-1, 3, -2, 1, -2, 1, -1, 0, +1, 0, 1, -3, 4, -1, 0, 1, +-4, 2, -2, 3, -2, 2, -2, 2, +-2, 3, -3, 4, -5, 0, 1, 1, +-2, 1, -2, 4, -2, 2, -2, 2, +-2, 0, 1, -1, 0, -1, 1, -1, +2, 1, -3, 2, -4, 5, -5, 4, +-5, 4, -4, 2, 0, 2, -2, -1, +2, -2, 3, -1, -2, 0, 0, 0, +1, -1, 1, 0, 1, -1, 1, 1, +-3, 0, 1, 1, 0, 1, -1, 1, +1, -2, 2, -1, -1, -1, 2, -2, +3, 0, -3, 3, -2, 4, -2, -1, +1, -1, 1, 0, -1, 3, -4, 2, +2, 2, -1, -1, 1, -1, 4, -2, +-1, -1, 1, 2, 0, 1, -1, 1, +1, -4, 6, -4, 2, -2, 2, 1, +0, 1, -2, 2, 0, -2, 3, -1, +-2, 4, -5, 4, 0, 1, -1, -2, +3, 0, 0, 0, -4, 4, -4, 2, +-1, 2, -3, 1, 0, 2, -2, 2, +-5, 3, -3, 5, -5, 3, -3, 3, +0, -1, 2, 0, -2, -1, 1, 1, +-1, -1, 1, -2, 5, -4, 2, -2, +0, 1, 0, 0, -3, 2, -4, 2, +0, 3, -4, 1, 0, 1, 0, 1, +-3, 3, -4, 2, 1, 1, -1, 0, +0, 1, -1, 3, -5, 1, 0, 1, +0, -1, 1, -1, 2, -3, 5, 0, +-3, 2, -2, 3, -3, 2, -3, 1, +2, 0, 2, -2, 1, -2, 2, -1, +1, 1, -3, -1, 5, -2, 3, -5, +3, -2, 4, -2, 0, 0, -2, 0, +3, -1, 1, 0, 0, -1, 4, -2, +-1, -1, -1, 3, -1, 2, -2, 2, +-1, -1, 4, 0, -2, 0, -1, 3, +-2, 4, -4, 1, 1, -1, 5, -3, +0, 0, -3, 1, 2, 0, -1, -3, +4, 2, 0, 0, -1, -1, 2, 0, +-1, 2, -5, 4, -2, 3, -2, 4, +-5, 2, -1, 3, -3, 1, -2, 0, +2, -1, 0, 3, -5, 4, -3, 5, +-6, 4, -6, 3, -2, 3, -3, 2, +-3, 4, -3, 3, -3, 2, -3, 0, +0, 4, -6, 4, -4, 5, -3, 4, +-5, 3, -2, 0, 0, 1, -4, 3, +-4, 4, -2, 5, -6, 1, 0, 0, +2, -4, 2, -4, 4, -4, 6, -2, +0, -3, 3, -2, 3, -3, -1, -2, +4, -1, 1, -2, 0, 0, 3, -3, +2, 0, -4, 1, 1, 1, -1, 0, +-2, 2, 1, 1, -1, 0, -1, -1, +2, -1, 0, 1, -4, 4, -1, 6, +-6, 3, -4, 5, -2, 2, -2, 0, +0, -1, 4, -1, 0, -2, 3, -3, +5, -2, -1, -1, 2, 2, -1, 2, +-4, 3, 0, -1, 3, -1, -1, -3, +3, -2, 3, 0, -2, 1, 0, 1, +1, 0, -2, 0, 1, -1, 1, 1, +-3, 0, 3, 0, 0, 1, -2, 2, +-1, 0, 1, -1, 0, -2, 3, -1, +2, -1, -1, 0, 1, 2, -3, 1, +-2, 2, 0, 0, 0, -1, 0, -2, +3, 1, -4, 2, -3, 3, -2, 3, +-4, 0, 1, -1, 2, 0, -3, 2, +-1, -3, 6, -3, -1, -1, 0, 2, +0, -1, -2, 0, 0, 0, 2, -4, +2, -4, 5, -3, 3, -1, -2, -3, +4, -1, 0, -1, -2, 2, -1, 1, +0, 0, 0, -4, 6, -4, 3, -4, +3, -6, 8, -4, 2, -1, -1, 1, +1, -1, 2, -1, -1, -1, 2, 3, +-4, 1, -2, 2, 1, 2, -4, 4, +-5, 5, -3, 4, -5, 3, -1, -2, +6, -2, -1, -2, 1, 2, 0, 0, +-1, -1, 3, -3, 5, -1, -2, 0, +2, -1, 3, -1, -2, 0, 2, 1, +0, 0, -2, 3, -1, 1, 0, 3, +-5, 2, 1, 1, 0, -1, -1, 1, +1, 2, -1, 1, -3, 2, -1, 2, +-1, 1, -2, -1, 4, 0, 0, -3, +2, 1, 1, 2, -4, 2, -2, 1, +1, 3, -5, 3, -3, 0, 4, -2, +0, -2, 1, 2, -1, 2, -3, 1, +0, -1, 3, 0, -2, -2, 4, -2, +3, -2, -3, 1, 0, 1, -1, 0, +-2, -1, 2, -1, 1, 2, -5, -1, +3, 0, -1, 2, -5, 4, -2, 1, +-1, 1, -4, 2, -1, 2, -2, 1, +-4, 1, 1, 1, -1, -2, 1, -2, +3, -2, 1, -1, -1, -2, 4, 1, +-4, 3, -6, 6, -3, 4, -6, 2, +0, -1, 3, -4, 2, -2, 4, -6, +8, -5, 2, -4, 4, -1, 2, -2, +1, -3, 4, -2, 2, 2, -6, 5, +-4, 4, -2, 3, -5, 1, 2, 1, +1, -2, 2, -3, 5, -3, 4, 0, +-4, 2, 0, 2, -1, 0, -1, -1, +6, -3, 3, -5, 3, -2, 3, -1, +1, 0, -1, 0, 2, 3, -3, 0, +1, -1, 4, -1, -1, 0, 0, 0, +3, 0, -1, 1, 0, -1, 4, 0, +-2, -1, 2, 0, 2, -1, -2, 2, +-2, 2, -1, 3, -4, -1, 3, -1, +3, 0, -2, -1, 3, -1, 1, -2, +0, -1, 2, -3, 2, 1, -2, -2, +3, -1, 0, -1, -3, 3, -2, 4, +-5, 3, -3, 0, 3, -3, 2, -1, +-1, -2, 5, -3, 1, -4, 2, 0, +2, -1, -1, 0, -1, -2, 2, -1, +-1, -1, -1, 0, 1, 3, -6, 2, +-2, 3, 0, -2, 0, -2, 2, -2, +2, 2, -4, 1, 0, 1, 1, -1, +-2, -2, 2, -1, 3, -2, -1, 1, +0, 1, 2, 0, -3, -1, 2, 2, +-2, 1, -3, 2, 1, 1, 1, -1, +-1, -2, 4, -3, 3, -2, 0, -1, +4, 0, 1, -2, 2, -2, 3, -1, +1, 0, -2, 0, 3, 1, -1, -1, +2, -2, 5, -2, -1, -1, 2, -2, +4, -3, 2, -2, 1, -1, 4, 0, +-2, -2, 2, 0, 2, -1, 0, -2, +5, -5, 7, -5, 2, -3, 4, -4, +6, -4, 1, -2, 3, 2, -1, 1, +-3, 3, -1, 2, -2, 2, -3, -1, +4, -2, 3, -3, 2, -3, 5, -2, +-1, 0, -2, 1, 1, -1, 0, 1, +-1, -2, 5, -2, -1, -1, -2, 3, +-2, 2, -3, 1, 0, -1, 3, -1, +-2, 3, -4, 2, 0, 2, -5, 1, +0, 1, 1, -2, -1, 1, -1, 0, +0, 1, -3, 0, 0, 2, -1, 3, +-6, 3, -2, 3, -2, -1, -1, -1, +1, 0, 0, 3, -5, 0, 1, 2, +-2, 0, -3, -1, 4, -3, 2, -3, +1, -2, 5, -4, 4, -4, 1, -4, +5, 0, -2, -1, 0, 1, 2, 0, +-1, 1, -2, 1, 0, 4, -5, 2, +-1, -1, 5, -1, -1, 0, 0, 2, +0, 0, -2, 2, 0, 0, 2, 1, +-3, 3, -2, 4, -2, 3, -4, 1, +1, -1, 3, -2, 1, -1, 3, -3, +5, -2, 1, -4, 6, -2, 2, -1, +-1, 2, 1, -1, 3, -3, 3, -3, +4, -1, 1, 1, -1, -1, 5, -2, +3, -4, 3, -1, 1, 0, -1, 3, +-4, 2, 0, 3, -3, 1, -2, 1, +1, 2, -3, 0, 0, 0, 2, 2, +-4, 4, -5, 2, 0, 3, -5, 1, +-1, 1, 1, -2, 1, -3, 2, -1, +1, 0, -3, 1, -1, 0, 1, 2, +-5, 2, -1, 2, -1, -2, 1, -2, +3, -4, 4, -2, -1, -1, 1, 1, +0, 0, -2, -2, 3, -1, 0, -1, +-1, 2, -1, 0, 0, 0, -1, -1, +0, 3, -4, 2, -3, 4, -1, 2, +-2, -1, 0, 0, 1, -1, -1, 0, +0, -1, 2, 2, -4, 2, -1, 1, +1, -2, -1, 0, -1, 0, 2, 0, +-1, -1, 3, -1, 2, 1, -4, 2, +0, 3, -2, 2, -2, 1, 2, -2, +3, 2, -5, 3, -2, 3, -2, 1, +-2, 2, 0, 2, -2, 0, 0, -1, +3, -2, 1, 0, -2, 0, 4, 0, +0, -1, 0, 2, 0, 0, 1, -1, +1, 0, 2, 1, 1, -2, 3, -4, +5, -1, -2, 1, -1, 2, 1, -2, +3, -2, 2, -1, 1, 2, -4, 2, +-3, 2, -1, 0, 0, -1, 2, 0, +0, 0, -1, 1, -2, 1, -2, 5, +-7, 3, 0, 1, 1, -4, 3, -5, +4, -2, 0, 2, -5, 4, -3, 2, +0, -1, 0, -3, 3, -1, 0, -3, +2, -2, 2, -1, 0, 1, -1, -1, +0, 1, -3, 1, -2, -1, 2, -1, +0, 0, -2, 3, -3, 3, -4, 3, +-4, 1, 0, 1, -2, 0, 0, 3, +-2, 2, -4, 3, -3, 2, 0, 0, +-1, 0, 0, 0, 1, 1, -2, -1, +1, 0, 1, -4, 3, -3, 4, -3, +4, -1, 0, -1, 3, -2, 2, -2, +-2, 2, -1, 3, -2, 0, 1, 0, +1, 0, -1, 2, -3, 0, 3, 0, +0, -1, 0, 4, -2, 4, -4, 1, +-1, 1, 1, 0, 1, -1, 2, -3, +5, -1, 0, -1, 0, 2, -2, 1, +-1, 2, 0, 0, 1, 2, -3, 3, +-3, 4, -4, 6, -7, 4, -1, 1, +2, -3, 1, 2, -2, 2, -3, 4, +-4, 2, 1, 0, 2, -4, 3, -2, +2, 0, -1, 1, -2, 1, 0, -2, +4, -2, 1, -1, -1, 5, -6, 3, +-3, 1, -1, 1, -2, 3, -4, 2, +-1, 1, -2, 3, -5, 3, -1, 1, +-2, 1, -2, 5, -5, 4, -4, 2, +-1, -3, 3, -2, 1, -2, 1, 0, +2, -2, 2, -4, 3, -2, 2, -3, +2, -3, 4, -5, 4, -2, 1, -3, +3, -1, 1, -2, 0, 0, -1, 1, +-1, 2, -2, 1, -1, 0, 1, 0, +-1, 0, 0, 2, -2, 0, 2, -2, +3, -3, 1, 1, -3, 2, -2, 1, +-1, 0, 1, 0, 1, -1, 0, -2, +2, -2, 2, -4, 4, -2, 1, 0, +1, 1, -1, -2, 2, -1, 2, -3, +2, -2, 3, -1, 1, 0, -2, 4, +-4, 4, -3, 3, -3, 1, 1, 2, +-1, -1, 2, -2, 3, -3, 2, -1, +0, -1, 1, 0, 1, -1, 2, -1, +2, 0, -1, -1, 2, -2, 2, -2, +1, 2, -1, -1, 3, -1, 1, -1, +0, 1, 0, -1, 1, 0, 0, 2, +-1, 1, -1, 2, -2, 0, -1, 2, +-2, -1, 2, -1, 3, -4, 4, -3, +3, -3, 2, -2, 1, -3, 2, 0, +-1, 3, -3, 1, 0, 2, -5, 4, +-8, 8, -7, 4, -2, 3, -3, 2, +-1, 2, -2, 0, -2, 1, -1, 1, +-1, -1, 2, -1, 2, -2, 2, -1, +0, -3, 1, 1, -3, 1, -1, 2, +0, 0, -1, 0, 0, -1, 0, -1, +-1, 1, -1, 0, 2, 0, 0, -1, +1, 1, -1, -1, -2, 3, -3, 2, +-1, 2, 1, -2, 3, -2, 2, -1, +0, -1, 1, -2, 2, -2, 3, 1, +-1, 2, -3, 4, -3, -1, 1, -2, +3, -4, 3, -1, 1, 1, -1, 1, +-1, -1, 2, -3, 3, -2, 3, -3, +5, -2, 2, -2, 1, 1, 0, -3, +2, -2, 1, -1, 2, 0, 1, -1, +1, 0, -1, 2, -3, 3, -3, 3, +-1, 0, 3, -1, 1, 0, -1, 3, +-3, 0, 0, 0, -1, 2, -2, 2, +2, -3, 4, -2, -1, 3, -5, 3, +-1, 0, 0, -2, 3, 0, 1, -2, +0, 2, -5, 5, -7, 5, -4, 2, +-1, 1, -2, 4, -5, 4, -4, 1, +-1, -4, 5, -5, 5, -6, 5, -2, +3, -4, 3, -3, 1, -1, -1, 1, +-1, 1, 1, -1, 1, 0, -2, 2, +-3, 4, -5, 3, -4, 3, -1, -1, +3, -2, 1, -2, 2, 0, 0, -2, +-1, 0, 0, 1, -1, 0, 0, 3, +-4, 5, -6, 7, -6, 2, -1, 0, +2, -3, 4, -4, 4, -4, 3, 0, +-2, 0, 2, -4, 6, -6, 5, -3, +3, -1, 1, -2, 2, -1, 0, -1, +0, 1, 1, -2, 2, 2, -3, 4, +-3, 2, -2, 1, -2, 3, -2, 4, +-3, 2, -2, 3, -1, -1, 2, -2, +2, -2, 1, 1, -1, 1, 1, 0, +0, -1, 1, 0, 0, -1, 1, -1, +3, -2, 1, -3, 4, -2, 3, -4, +2, 1, -1, 0, 0, 1, 0, 1, +-3, 6, -7, 6, -5, 2, 0, 0, +0, 1, -1, 1, 1, -3, 4, -2, +0, 0, -1, 3, -3, 1, -1, 0, +1, -2, 1, 1, -2, 1, -1, 0, +-1, 2, -3, 2, -2, 3, -2, 1, +-2, 3, -4, 2, -1, 2, -2, 0, +-1, 1, 0, -2, 1, -2, 1, 0, +-2, 1, -1, 2, -1, 0, 0, 0, +1, -3, 2, 0, -2, 1, -1, 2, +-1, -1, 0, 1, 1, -1, 2, -3, +2, -2, 1, 0, -1, 3, -4, 3, +-3, 4, -3, 1, -2, 2, -2, 2, +-2, 5, -5, 4, -4, 5, -3, 1, +-1, -2, 3, -3, 3, -4, 4, -2, +3, -2, 0, 3, -3, -1, 2, -4, +5, -5, 4, -1, 1, 0, 1, -1, +0, -1, 0, 0, -1, 1, 0, -1, +2, 0, 1, -2, 2, 1, -2, 0, +-1, -1, 2, -3, 3, -1, 2, -1, +2, -1, 1, 0, -1, 0, 0, 0, +0, -1, 1, 1, 0, 1, -2, 3, +-2, 0, 1, -1, 0, 0, 0, -1, +4, -3, 3, -1, -1, 1, 0, -3, +3, -3, 2, -2, 2, 1, -1, 0, +0, 1, 0, -2, 0, 0, -1, 0, +0, 1, -1, 3, -3, 3, -3, 2, +-1, -4, 4, -4, 4, -4, 3, -1, +1, 0, 0, 3, -5, 2, -3, 3, +-3, 1, -1, 0, 1, 1, -1, 1, +-1, 0, 1, -3, 2, -1, -1, 0, +1, 2, -2, 0, -1, 0, 1, -3, +0, -1, -1, 0, 2, -2, 3, -1, +1, -1, 1, -1, 1, -3, 1, 1, +-3, 4, -3, 3, 1, -3, 5, -2, +-1, 1, -4, 3, -2, 1, 1, -2, +3, -2, 3, -3, 1, 0, -2, 1, +-2, 3, -3, 1, 0, 0, 2, -3, +2, -1, 0, 1, -3, 3, -3, 2, +-1, 0, 2, 1, -1, 1, -2, 3, +-2, -1, 0, 1, 0, -1, 2, -1, +2, -1, 1, 2, -3, 2, 0, -2, +3, -2, 1, -1, 2, -2, 3, -3, +1, 2, -4, 2, -1, 2, -2, 0, +1, 0, 2, -1, -2, 2, -2, 1, +-1, -2, 1, -1, 1, -1, 1, 1, +0, -1, 0, 2, -3, 1, -2, 2, +-1, 0, 2, -2, 2, -2, 2, 0, +-2, 3, -5, 3, -2, 2, -1, -1, +1, 0, 1, -2, 1, 1, -3, 1, +-2, 1, 0, -1, 1, -1, 2, -1, +1, -3, 3, -4, 4, -4, 2, -1, +0, -1, 2, 0, 0, -2, 1, -2, +3, -4, 2, -1, 0, 1, 0, 1, +-1, -1, 1, -2, 1, 0, -1, -1, +1, -1, 2, -2, 1, 1, -1, 0, +0, 0, 0, -3, 4, -4, 4, -4, +3, -2, 3, -3, 3, -1, -1, 4, +-4, 2, 0, -1, 2, -3, 2, 2, +-2, 2, -3, 2, 0, 0, 0, 0, +-1, 1, -1, 2, -2, 2, -3, 3, +-3, 5, -3, 0, 0, 0, 2, -3, +3, -3, 4, -3, 2, 0, -1, 0, +1, -2, 4, -3, 2, 1, -2, 4, +-3, 0, 0, -1, 2, -3, 2, 1, +-2, 1, -2, 4, -2, 1, -1, 0, +1, -1, 1, 0, 0, 1, -1, 2, +-2, 3, -3, 2, -2, 3, -1, -2, +2, -1, 1, -1, 0, 0, 1, -3, +5, -5, 6, -6, 5, -4, 3, 0, +-1, 1, -2, 3, -2, 1, -2, 3, +-2, 0, 0, 2, -3, 3, -4, 5, +-3, 3, -2, 1, -2, 4, -3, 2, +-2, 0, -1, -1, 1, 0, 1, -4, +4, -2, 2, 0, -2, 2, -2, 0, +1, -1, 0, 0, 0, 1, 0, 0, +-1, -1, 1, -1, 1, -3, 1, 1, +-1, 2, -3, 4, -4, 1, 1, -1, +1, -1, 0, 0, 0, 0, 1, -2, +3, -2, 1, 0, -1, 2, -2, 0, +0, 2, -2, 1, -1, 0, 2, -2, +2, -1, 0, 0, -1, 3, -3, 3, +-3, 2, 1, 0, 0, -1, 0, 1, +0, -1, 0, 0, 1, -2, 3, 0, +1, -1, 1, -1, 2, -2, 1, -2, +2, -1, 2, -2, 1, 0, 1, -1, +0, 1, -2, 1, -1, 1, -1, 0, +1, 1, 0, 1, -2, 3, -4, 3, +-3, 1, -1, 0, 0, -1, 3, -2, +3, -4, 2, 0, -2, 1, -2, 3, +-3, 2, -2, 2, -2, 1, -2, 3, +-3, 3, -5, 2, -1, 1, 0, -1, +1, 0, 0, -1, 1, 0, -1, -2, +1, -1, 2, -1, 0, 0, 0, 0, +1, -1, 0, -1, 1, -2, 2, -1, +1, -3, 3, 0, 0, -1, -1, 1, +0, -1, 0, 0, 0, 0, 1, 1, +-1, 0, -1, 1, 0, 2, -3, 1, +-2, 2, 0, 0, -1, 3, -2, 0, +1, 0, 0, -1, 0, 0, 2, -2, +2, -1, 0, 1, 0, 0, -2, 2, +-3, 1, 0, 0, 2, -4, 4, 0, +1, -1, 0, -2, 3, -3, 2, 0, +-1, 1, 0, 0, 0, 1, -1, 0, +0, 1, -1, -1, 1, 0, 1, -1, +0, 2, -1, 0, 2, -1, -1, 1, +-5, 6, -5, 5, -3, 0, 1, 0, +1, 0, -1, 1, -1, -1, 1, 1, +-1, -1, 1, -1, 3, -1, -1, 1, +-2, 1, 0, 1, -2, 2, -1, -1, +2, -1, -1, 1, -2, 4, -3, 0, +-1, 1, 1, -2, 2, -2, 2, -3, +3, -2, 2, -3, 1, -1, 0, 2, +-2, 0, 0, 1, 0, -1, 0, 1, +-2, 1, -1, 1, 0, -2, 1, 1, +-1, 4, -5, 5, -6, 6, -5, 5, +-5, 4, -3, 1, 0, 2, -2, 1, +-2, 2, -1, 0, 0, -1, 0, -2, +2, 0, 0, 0, -1, 0, -1, 3, +-3, 2, -1, 1, 0, 0, 0, 1, +-1, -1, 2, 0, 0, -3, 3, -4, +5, -6, 5, -3, 2, 0, 1, -2, +3, -4, 5, -4, 3, -1, 0, -2, +3, -1, 1, -1, 0, 0, 2, -4, +4, -4, 2, 1, -2, 4, -3, 3, +-2, 3, -2, 4, -4, 3, -4, 5, +-4, 3, -3, 3, -1, 0, 0, 1, +-1, 0, -1, 2, -2, 1, -1, -1, +2, 0, 0, 0, -1, 1, 0, -1, +0, 3, -5, 3, -2, 3, -2, 2, +-3, 3, -2, 2, -2, 3, -4, 2, +-1, 1, 0, 1, -1, 0, 0, 1, +-1, 0, 0, 0, -1, 1, -2, 3, +-2, 0, 0, 2, -2, 3, -4, 3, +-2, 2, -2, 1, -1, 0, 2, -2, +2, -1, 1, -3, 2, 0, -1, -1, +0, -1, 3, -4, 3, -2, 2, -1, +-1, 2, -2, 2, -1, -2, 1, -1, +2, -2, 1, 1, -2, 1, -1, 1, +0, -2, 1, -1, 0, 0, 0, 1, +-1, 1, -2, 1, -1, 2, -2, 2, +-3, 3, -1, 0, 1, 1, -2, 1, +-1, 3, -3, 2, -3, 3, -1, 1, +0, 0, 0, 1, -1, 2, -3, 4, +-4, 2, 0, 1, 0, -1, 1, 1, +1, -3, 2, -3, 4, -4, 3, -1, +1, 0, 1, 0, 0, 1, 0, -1, +2, -1, 1, -1, 0, 2, 0, -2, +3, -2, 3, -4, 2, -1, 1, 0, +0, 0, 1, -1, 3, -2, 1, -1, +1, -2, 2, -1, 1, -4, 4, -2, +2, -2, 0, 2, -1, 1, -1, 0, +0, -2, 3, -2, 2, -1, 0, 0, +1, 1, -1, 0, -1, 0, 2, -4, +3, -2, 1, 0, 0, 1, -1, -1, +0, 1, -1, 1, -1, -1, 2, -1, +1, 0, -3, 4, -4, 3, -3, 3, +-3, 0, 1, 0, 0, 0, -1, 1, +0, -2, 3, -3, 2, -1, -1, 2, +-3, 3, -2, 1, 0, 1, -1, 0, +-1, 1, 0, -1, -1, 2, -3, 3, +-2, 1, 0, 0, 1, -1, 1, -2, +3, -4, 4, -3, 3, -4, 4, -2, +1, -1, 0, 1, -1, -1, 1, 1, +0, 0, -1, 1, 1, -1, 2, -2, +2, -3, 2, -2, 2, 0, -1, 0, +-1, 3, -2, 2, -3, 2, 0, -2, +3, -3, 2, -2, 2, -1, 1, 0, +0, -1, 3, -3, 3, -2, -1, 3, +-2, 0, 1, -2, 4, -5, 5, -2, +0, 0, -1, 1, 0, 0, 0, -1, +2, -2, 3, -2, 0, 1, -1, 0, +0, 1, -1, -1, 2, -1, 1, -1, +-1, 2, -1, 0, 1, 0, 0, -1, +1, -1, 2, 0, 0, -1, 0, 1, +-1, 1, -3, 3, -1, -2, 3, -2, +2, -1, 0, 1, -1, 0, -1, 1, +-2, 2, -2, 2, -2, 3, -3, 3, +-3, 2, -2, -2, 4, -3, 2, -3, +1, 1, 0, -1, 0, 0, -1, 1, +-1, 0, 0, -1, 0, 0, -1, 3, +-3, 1, 0, 0, 1, -1, -1, 2, +-3, 3, -3, 4, -4, 0, 1, -1, +3, -1, -1, 0, -1, 0, 0, -1, +1, 0, 1, -2, 1, 1, 0, -2, +2, -1, 1, -2, 1, 0, 2, -1, +1, -2, 1, -2, 2, -1, -1, 1, +-3, 2, -1, 1, 0, -2, 1, 2, +-2, 2, -3, 3, -2, -1, 2, -2, +3, -2, 2, -1, 2, -1, 1, -3, +2, -1, 1, -1, 0, 1, -1, 1, +-1, 2, -2, 1, -1, 2, -2, 1, +0, -1, 2, -1, 0, 3, -5, 4, +-4, 3, -3, 5, -6, 4, -3, 3, +-1, -1, 1, 1, 0, -1, 1, -1, +1, -2, 2, -1, 1, 0, -1, 1, +0, 0, 0, -2, 1, 0, -1, 0, +-1, 2, -1, 0, 0, 1, -1, -1, +0, 0, 0, 0, -1, 1, -1, 2, +-2, 3, -4, 4, -3, 0, 1, 0, +-1, 0, -1, 2, -1, 0, -1, 3, +-2, 0, 0, -1, 2, -3, 3, -3, +3, -2, 2, -4, 4, -3, 4, -5, +3, -2, 2, -3, 3, -2, 2, -3, +3, -1, 0, -1, 0, 0, 1, -1, +2, -3, 3, -2, 2, -1, 1, 2, +-3, 2, -3, 5, -5, 3, -3, 2, +0, 0, 1, -1, 2, -3, 4, -4, +3, 0, -1, 2, -2, 3, -2, 1, +-1, 3, -4, 4, -4, 4, -4, 1, +1, -1, 1, -2, 2, 0, 0, 1, +-3, 2, -1, 2, -1, -1, 2, -1, +3, -3, 1, 2, -2, 0, 0, -2, +3, -5, 5, -3, 2, -1, 1, 0, +0, -1, 1, -1, 2, -2, 2, -4, +3, -1, 1, -2, 2, -1, 1, -2, +1, 0, -1, 2, -3, 4, -5, 4, +-4, 3, -2, 2, -3, 2, -2, 2, +-1, -1, 0, 1, 0, -2, 2, -1, +1, -3, 3, -2, 2, -2, 0, 1, +-2, 1, 0, -1, 1, -1, 1, -2, +2, 0, -1, 0, 0, 1, 0, -2, +1, 0, 1, -2, 2, -3, 3, -4, +2, 0, -1, 2, -3, 3, -3, 3, +-3, 1, -1, 1, 0, -1, 0, 2, +-2, 0, 0, 2, -2, 1, -1, 1, +0, 0, 0, 0, -1, 2, -2, 1, +-1, 0, 0, -1, 0, 3, -3, 1, +-1, 2, 0, -1, 1, -2, 2, -1, +1, -1, 1, -3, 3, -2, 0, 1, +-2, 0, 1, 0, 0, 0, -1, 2, +-1, 0, 0, 2, -2, 0, -1, 1, +0, 0, 0, 0, 2, -1, 0, 0, +-2, 3, -3, 2, -2, 1, 2, -3, +1, 1, -1, 1, 0, -1, 2, -3, +3, 0, -2, 3, -4, 4, -3, 1, +0, -2, 2, 0, 0, -2, 2, -1, +1, -2, 1, 2, -2, 2, -3, 3, +-2, 2, -4, 3, -2, 0, 2, -3, +3, -1, 0, -1, -1, 1, 1, -4, +5, -5, 4, -4, 4, 0, -2, 1, +-1, 1, 0, -1, -1, 1, -1, 2, +-2, 1, -1, 0, 2, -4, 5, -4, +4, -6, 4, -1, 2, -1, -1, 3, +-2, 1, -1, 1, -1, 0, -1, 0, +0, 0, 1, -2, 2, 0, 1, -2, +-1, 3, -2, 0, 0, 1, -1, 0, +0, 2, 0, 0, -1, -1, 3, -5, +6, -6, 4, -1, 0, 2, -3, 4, +-3, 1, 0, 1, -1, 0, -2, 3, +-1, 0, 1, -1, 0, -1, 1, 0, +-1, 2, -4, 2, -1, 3, -3, 3, +-3, 5, -3, 0, 0, 1, -1, 0, +0, 1, 0, -1, 0, 0, 2, -2, +3, -3, 2, 0, -1, 2, -3, 4, +-3, 2, -1, 1, 0, -2, 2, -1, +2, -4, 5, -5, 4, -4, 2, -1, +1, -1, 0, 0, -1, 2, -2, -1, +3, -1, 2, -3, 2, -1, 2, -2, +0, 0, 1, -2, 2, -1, 1, -1, +1, 0, 0, 0, 1, -2, 1, 0, +0, -1, 1, 0, 0, -1, 0, 4, +-5, 2, -1, -1, 3, -3, 1, 0, +0, 1, -2, 2, -2, 0, 1, -3, +1, 2, -3, 2, -2, 2, 0, 0, +-3, 5, -5, 4, -4, 4, -4, 3, +-3, 4, -4, 2, -1, 0, 1, -1, +0, -2, 1, 1, -2, 1, -1, 2, +-1, -1, 0, 2, -3, 2, -3, 3, +-1, 0, -1, 0, 1, 0, 0, 0, +-1, 2, 0, -2, 2, -2, 2, -2, +1, 1, -1, 0, 0, 1, -1, -1, +1, 1, -1, 1, -1, 0, 1, -1, +1, -3, 3, -1, 2, -4, 3, -2, +3, -3, 2, -1, 1, -1, 1, 2, +-2, 1, -1, 1, 1, -1, 1, -1, +1, 0, 1, -2, 1, 1, -1, -2, +3, -2, 2, -2, 1, 1, 0, -2, +1, 0, -1, 2, -3, 2, -1, 0, +2, -5, 4, -3, 3, -3, 2, -2, +2, -2, 1, -1, 2, -4, 4, -1, +-1, 1, -2, 2, -1, -1, 1, -2, +1, 0, 0, -1, 1, 1, -2, 0, +0, 1, 0, -3, 3, -1, 2, -3, +3, -3, 4, -3, 2, -1, 1, -1, +1, -2, 2, -2, 4, -5, 5, -4, +4, -5, 3, 0, 0, -2, 2, -1, +1, -1, 1, 2, -3, 2, -2, 1, +0, -1, 1, -3, 3, -1, 0, -1, +0, 0, 1, -2, 1, 0, 1, -3, +4, -4, 5, -4, 2, 1, -2, 3, +-3, 2, -3, 2, -1, 1, -1, 2, +-1, -1, 2, 0, -1, -1, 2, 0, +0, -1, -1, 3, -2, 2, -2, 2, +-1, 0, 0, -2, 2, 0, 0, -1, +2, -2, 5, -6, 5, -3, 2, -2, +1, 1, -2, 1, -1, 2, -2, 0, +1, 0, 0, 1, -1, 0, 1, -1, +0, -2, 2, 2, -4, 3, -3, 5, +-4, 2, -2, 1, 1, -2, 3, -3, +4, -3, 1, 1, -2, 2, -2, 0, +-1, 2, 0, -1, -1, 3, -3, 3, +-2, 2, -1, -3, 3, -1, 0, -2, +3, -4, 4, -2, 0, 0, -2, 3, +-3, 1, -1, 2, -2, 1, -1, 3, +-2, -1, 1, -2, 3, -4, 2, -1, +0, 0, 0, 0, 0, 0, 0, -1, +0, 1, 1, -3, 3, -1, -1, 1, +-2, 5, -5, 2, 0, 0, 1, -3, +2, 0, 0, 2, -3, 0, 2, 0, +0, 0, -1, 2, -1, -1, 1, 0, +0, 0, -1, 2, 0, -2, 1, 0, +1, -2, 2, -1, 1, -1, 2, -3, +2, -1, 1, -1, 1, 2, -2, -2, +3, 0, 0, -2, 1, 0, 1, -1, +0, 1, -1, 1, -2, 1, 0, 2, +-2, 0, -2, 3, -2, 2, -3, 3, +-1, -1, 0, 2, -3, 3, -3, 5, +-3, 0, 1, -1, 0, 1, -2, 2, +-2, 4, -2, 1, 0, 1, -1, -1, +1, 1, -1, -1, 0, 0, 2, -1, +-1, 2, -1, 0, 0, 0, 0, 1, +-1, 3, -4, 4, -2, -1, 1, -1, +2, -4, 4, -2, 1, -3, 4, -2, +2, -2, 2, 0, 0, 1, -4, 4, +-3, 4, -3, 0, 1, 0, 1, -2, +1, 1, -1, 1, -3, 3, -2, 1, +0, 0, 0, 0, 0, 2, -3, 2, +-1, 0, 1, -1, 1, -1, 2, 1, +-2, 0, 0, 2, -2, -1, 1, 1, +-2, 2, -3, 3, -1, 1, -2, 3, +-2, 3, -3, 1, 0, -1, 2, -1, +0, 1, 1, -4, 4, -2, 1, -1, +0, 1, -1, -1, 2, -1, 0, -1, +2, -2, 1, -1, 0, 0, 2, 1, +-2, -1, 2, 0, 1, -4, 4, -2, +2, -1, -3, 4, -3, 3, -2, 1, +0, -1, 1, -1, -1, 2, -2, 1, +-1, 1, 0, -1, 1, 1, 0, -3, +3, 0, -1, -1, 3, -2, 3, -3, +2, -1, 2, 1, -3, 1, -1, 2, +-2, -1, 1, 0, 1, -3, 3, -3, +6, -6, 3, -1, -1, 2, -4, 6, +-5, 3, 0, -2, 2, -1, 1, -1, +1, 1, 0, -3, 3, 0, -1, 0, +0, 2, -2, 0, 1, -1, 2, -3, +1, -1, 2, 0, 0, -2, 3, -2, +2, -1, -1, 1, 1, -2, 0, 3, +-4, 3, -2, 2, -1, 0, -1, 3, +-4, 3, -2, 2, -2, 1, 0, -1, +1, 1, -2, -1, 2, -1, 1, -3, +3, -1, 3, -3, 1, 0, 0, 1, +-3, 3, -3, 3, -3, 1, 0, -2, +4, -2, 0, 1, -2, 0, 1, 0, +0, -2, 2, 0, 0, -2, 2, 0, +-1, 1, -2, 2, -2, 2, -2, 0, +1, 0, -1, -2, 3, -1, 1, -2, +0, 0, 2, -2, 0, 1, 0, 0, +-1, 3, -4, 3, -2, 2, -1, -1, +1, -1, 0, 2, -2, 0, 1, 0, +-1, -2, 4, -1, 0, -2, 0, 4, +-2, 1, -1, -1, 3, -2, 0, 0, +1, -1, 3, -6, 6, -4, 3, -2, +-2, 3, -1, 0, -1, 0, 0, -1, +2, 0, -1, -1, 3, -1, 0, 0, +-1, 1, -1, 2, -3, 0, 1, 1, +0, -2, 1, 2, -3, 1, -1, 0, +1, -3, 2, -2, 4, -3, 2, -1, +-1, 2, -2, 3, -3, 2, 0, -2, +3, -2, 3, -4, 2, 1, -3, 2, +-2, 4, -4, 2, -1, 2, -2, 1, +-1, -2, 4, -3, 2, -3, 3, 0, +0, -2, 2, -1, 2, -1, -2, 3, +-2, 1, 0, 1, 0, -1, 0, 1, +-2, 3, -1, 1, -1, 0, 0, -1, +1, 1, -1, -2, 3, 0, -1, -2, +2, -1, 2, -3, 3, -2, 2, 0, +-2, 3, -2, 2, -1, -2, 4, -3, +2, -3, 1, 2, -1, 1, -3, 3, +-1, 0, 1, 0, -1, -1, 2, 0, +-1, 1, -1, 3, -4, 6, -6, 4, +-2, 2, -3, -1, 3, -1, 2, -5, +3, 0, 0, 1, -3, 3, -3, 3, +-4, 3, -2, 1, 0, -1, 0, 0, +1, -2, 1, 1, -1, 0, -1, 2, +-1, 0, 1, 3, -4, 1, 1, 0, +2, -3, 0, 2, -2, 4, -4, 1, +1, 2, -3, 1, -2, 3, -2, 1, +-2, 3, -1, 0, 0, -1, 3, -3, +2, -1, -1, 1, 0, 1, -2, 2, +-1, 2, -2, 4, -5, 2, 0, 1, +0, -4, 5, -1, 1, -3, 2, -2, +4, -4, 2, -2, 2, -1, -1, -1, +1, 1, -1, -1, 0, 0, 2, -2, +0, 0, 2, -3, 3, -1, 0, -1, +1, 0, 0, -2, 2, 0, -2, 3, +-3, 1, 0, 2, -3, 1, 0, 2, +-3, 0, 0, 4, -4, 2, -4, 3, +-1, 0, -1, 0, 1, 0, 0, -1, +2, -1, 2, -3, 1, -1, 3, -3, +1, 1, -2, 1, -1, 3, -3, 0, +0, 3, -4, 3, -3, 2, -2, 2, +-2, 0, 1, 0, -1, -2, 3, -1, +1, -2, 0, 3, -3, 1, -2, 1, +2, -3, 1, 0, -1, 2, -2, 3, +-3, 1, 1, -1, 0, 3, -4, 2, +-2, 4, -3, 0, 1, 0, 0, -3, +3, 1, -2, 2, -3, 2, 1, 0, +-1, -1, 2, 0, 1, -3, 3, -2, +3, -2, 0, 1, 0, 0, -1, 3, +-3, 2, -1, 2, -2, 2, -1, 3, +-3, 1, 1, -2, 3, -1, 0, -3, +4, 0, -1, -1, 1, 2, -1, 0, +-1, 1, 0, -1, 0, 0, 0, 3, +-5, 4, -3, 2, -1, -1, -1, 2, +-1, 1, -2, 2, 1, -3, 3, -2, +2, -3, 4, -1, 0, -2, 2, 0, +0, 1, -1, 0, 1, 0, -1, -2, +3, -1, 0, -2, 2, 0, 2, -5, +3, -3, 5, -4, 2, -1, 1, -1, +0, 1, -2, 1, 0, 0, -2, 2, +0, -1, 1, 0, 0, -2, 2, 1, +-2, 0, 1, 1, -1, -2, 2, -1, +1, 1, -3, 0, 2, -1, 2, -3, +2, -1, 1, -2, 0, 3, -3, 2, +-3, 3, -1, -1, 1, 0, -1, 1, +-3, 4, -4, 3, -1, 1, -1, 3, +-3, 1, -2, 5, -5, 2, 0, 0, +1, -4, 4, -2, 1, -1, 0, 0, +1, -1, -1, 0, 0, 0, 0, 0, +0, 1, 0, 0, -2, 4, -4, 3, +-4, 4, -2, -1, 3, -2, 0, 0, +-1, 4, -4, 2, -1, -2, 3, -1, +0, 0, 1, 2, -2, -1, 1, 2, +-2, 1, -2, 2, -1, 1, -1, 2, +0, -2, 2, -2, 1, 0, -1, 1, +-2, 1, 2, -3, 3, -2, 3, -5, +5, -3, 3, -6, 6, -3, 1, 0, +-2, 4, -2, 1, 0, -3, 3, -2, +2, -2, 2, 1, -3, 1, -1, 2, +0, -1, -1, 1, 1, -1, 0, 1, +-1, 0, 1, 0, 0, -1, 1, -1, +1, -1, 0, -1, 0, 2, -3, 2, +-2, 4, -4, 1, 0, 3, -4, 3, +-4, 5, -3, 2, -1, -2, 4, -2, +1, -1, -2, 2, -1, 0, 0, 0, +0, -1, 2, -1, 1, -3, 2, 1, +-1, -1, 1, 0, -1, 1, 0, 0, +1, -2, 0, -2, 4, 0, -2, 0, +-1, 5, -6, 5, -5, 6, -4, 2, +-2, 2, 0, -1, 0, -1, 1, 0, +0, -1, 1, -2, 4, -3, 1, 2, +-2, 1, 0, 1, -2, 1, -1, 4, +-5, 2, -2, 4, -4, 3, -3, 3, +-1, 1, -1, -1, 2, 0, -2, 1, +-1, 3, -1, -2, 2, -2, 4, -3, +1, 1, -2, 2, -1, 0, 1, -4, +5, -4, 3, -2, 1, -1, 0, 2, +-3, 2, -2, 4, -4, 0, 2, 1, +0, -2, 1, 0, 1, -1, -1, 1, +0, 0, 0, -2, 3, 0, 0, 0, +-1, 2, -1, 1, -3, 5, -4, 2, +-2, 2, -1, -1, 2, -1, 1, -2, +3, -1, 1, 0, 0, 0, 0, 3, +-5, 3, -2, 3, -2, -1, 1, 1, +-1, -1, 0, 0, 2, -4, 4, -5, +5, -4, 2, -1, 0, 0, 2, -3, +3, -2, 2, -2, 0, 1, 0, -3, +4, -1, -1, 1, -1, 2, 0, -4, +5, -4, 4, -1, 0, 0, 1, 0, +-1, -2, 4, -1, 2, -3, 1, 0, +1, -2, 2, -2, 3, -4, 4, -3, +4, -4, 2, 0, -2, 3, -3, 2, +-2, 1, 1, -3, 2, 1, -2, -1, +2, 0, -1, -1, 1, 0, 0, 0, +-1, 2, 0, 0, 0, -2, 2, 0, +-1, -1, 2, -2, 3, -4, 3, -2, +2, -2, 1, 0, 0, -1, 1, 0, +0, -1, 1, 0, -1, 0, 1, -2, +2, -1, 0, 0, 1, 1, -1, -1, +1, 2, -2, -1, 1, -1, 2, -2, +1, 0, 1, 0, -1, 0, 1, -1, +2, 0, -3, 5, -5, 4, -3, 1, +1, -4, 4, -1, 0, 1, -2, 5, +-6, 4, -3, 2, 0, -2, 2, -1, +2, 1, -3, 1, -1, 3, -3, 2, +-3, 4, -3, 2, -2, 2, -1, -1, +0, -1, 2, -4, 4, -4, 2, -1, +1, -1, 1, -2, 3, -3, 2, 1, +-3, 1, -1, 3, -3, 1, 0, 1, +-1, -2, 1, 0, 0, 1, -3, 3, +-3, 5, -4, 2, -2, 2, -1, 1, +-2, 3, -3, 2, -3, 4, -2, 0, +-1, 2, -3, 2, 0, 0, 1, -3, +3, -2, 1, 1, -2, 1, -1, 3, +-4, 1, 1, 0, 0, -1, -1, 4, +-3, 2, -2, 2, -1, 1, -1, 1, +-1, 1, -1, 0, 0, 0, 1, -1, +0, 1, -1, 0, 1, 0, 0, -3, +4, -1, 1, -2, 2, 0, 0, 0, +-1, 1, -1, 3, -4, 3, -2, 3, +-3, -1, 2, -2, 4, -4, 2, 1, +-2, 3, -4, 6, -4, 3, -2, -1, +2, -4, 4, -2, 0, 1, -1, 0, +1, 0, 0, -2, 2, 1, -2, 0, +0, 2, -3, 1, 1, -1, 2, -4, +1, 0, 0, 2, -3, 2, 0, 1, +0, -2, 1, 0, 1, -2, 1, -1, +2, -2, 2, 0, -1, 0, 0, 3, +-3, 0, 1, -2, 3, -3, 4, -5, +5, -4, 2, -2, 1, 4, -7, 5, +-4, 5, -4, 1, -1, 1, 2, -3, +3, -2, 2, -2, 1, -3, 4, -2, +2, -3, 1, 0, 1, -1, 1, -1, +1, -1, 1, 2, -3, 2, -2, 3, +-4, 2, 0, 1, -1, 0, -2, 0, +2, -1, 1, -4, 4, -2, 2, -3, +2, 1, -2, 0, -1, 1, 1, -2, +1, -2, 3, -1, 1, 1, -2, 1, +0, -2, 2, -3, 3, -4, 3, 0, +-1, 0, 0, 2, -2, -2, 3, -1, +1, -2, 0, 0, 0, 2, -2, 2, +-2, 3, -3, 1, 0, 2, -1, -2, +2, -1, 1, 0, -1, 4, -4, 2, +0, 0, 2, -3, 3, -2, 1, 0, +-1, 0, 1, -3, 3, -5, 5, -1, +0, -2, 1, 2, -2, 0, 1, -2, +4, -6, 5, -3, 2, 0, 0, -1, +2, -2, 3, -3, 3, -3, 3, -5, +6, -3, 1, -1, -1, 4, -3, 2, +-2, 1, -1, -1, 2, -2, 2, -2, +1, -1, 2, 0, 0, -1, 1, -2, +2, -5, 6, -3, 2, -3, 2, 0, +1, 1, -1, 2, -3, 1, 0, 1, +-1, -1, 1, -1, 2, 1, -3, 1, +0, 1, 0, -2, 1, 2, -3, 1, +-1, 1, 0, 0, -1, 0, 0, 0, +0, 2, -2, 2, -2, -1, 3, -3, +4, -5, 3, -2, 2, -1, 0, 1, +-2, -1, 3, -2, 1, -2, 2, -1, +1, -2, 3, -3, 2, -2, 1, -2, +4, 0, -2, 0, 0, 2, -2, 1, +0, 0, 0, -2, 2, 1, 0, 1, +-2, -1, 3, -1, 0, 1, -4, 2, +0, -3, 4, -3, 2, -2, 1, 0, +0, -1, 3, 0, -2, -1, 2, 1, +0, 0, -1, 0, 0, 2, -3, 2, +-2, 3, -3, 1, 1, 1, -2, -1, +1, -1, 3, -1, -1, 1, -1, 1, +0, 1, -1, 0, 0, -1, 1, 0, +0, 0, -1, -1, 1, -3, 5, -1, +-2, -1, 1, 3, -2, 1, -1, -1, +1, -2, 2, 0, -1, 3, -5, 3, +-2, 4, -4, 2, -2, 2, 0, -2, +2, -1, 1, -2, 1, 0, 1, -1, +0, -1, 1, -1, 2, 0, -3, 2, +-3, 4, -3, 3, -3, 1, 0, 1, +-1, -2, 5, -3, 1, -3, 1, 1, +-1, 1, -2, 1, 1, 0, 0, -1, +0, 2, -2, 2, -2, 3, -2, 1, +-3, 5, -5, 5, -4, 3, -3, 0, +1, 1, -1, 1, -1, 2, -2, 0, +1, -3, 3, -4, 3, -5, 7, -3, +0, -2, 2, 0, 1, -3, 3, -2, +1, -2, 3, -1, 1, 0, -2, 1, +0, 2, -3, 2, -2, 0, 1, -2, +4, -3, 3, -5, 4, -1, 2, -1, +0, 1, -3, 1, 2, -1, 1, 0, +-2, 2, -1, 2, -1, 0, -1, 2, +-4, 2, 1, 0, -1, -1, 0, 3, +-2, 2, -2, 0, 2, -3, 3, -2, +2, -1, 1, -2, 3, -2, 2, -1, +0, 2, -2, 1, 0, 1, -1, -1, +1, 1, -1, 1, 0, 0, -1, 0, +0, 2, -2, 1, -1, -1, 4, -1, +0, -2, 1, 1, -1, 0, 1, 0, +-1, -2, 2, 0, 0, 2, -4, 4, +-2, 2, -1, -1, 1, -1, 1, -2, +2, 0, 1, -3, 2, -1, 1, 0, +0, 0, -1, -1, 2, 1, -4, 4, +-4, 2, 1, -4, 6, -5, 3, 0, +-2, 0, 2, 2, -4, 1, -1, 3, +-2, 0, 0, 0, 0, 0, 0, 2, +-2, 2, -3, 0, 2, -2, 1, -1, +-1, 2, -3, 3, -2, 3, -2, -2, +2, 0, 0, 1, 0, 0, -2, 0, +2, 1, -2, 2, -5, 4, -1, 2, +-1, -2, 4, -2, 0, -2, 4, -1, +0, -1, 0, 1, 0, 1, -2, 0, +1, -3, 4, -4, 4, -4, 3, -3, +3, -1, 1, 0, -1, -1, 3, -4, +5, -3, 1, -4, 5, -2, 2, -2, +1, 0, -1, 1, 0, -1, 2, -4, +2, -4, 6, -1, -1, -1, 1, 1, +-2, 2, -2, 2, -1, -1, 1, -1, +2, 0, -2, 0, 1, -2, 4, -3, +1, -2, 2, -2, 2, 0, -1, 0, +-1, 2, -1, 0, 2, 1, -3, 0, +2, 0, 0, -1, -1, 0, 1, 1, +-2, 2, -1, 1, -1, -2, 5, -3, +2, -3, 1, 0, 2, -1, 0, 0, +-1, 1, 0, 1, -1, 1, -2, 2, +-1, -1, 3, -3, 1, 0, -1, 0, +3, -1, -1, -2, 3, 0, 0, 0, +-1, 2, -3, 2, -2, 3, -2, 2, +-4, 1, 2, 0, -1, -1, 1, -1, +3, -4, 4, -2, 1, -2, 1, 0, +1, 0, 0, 0, 0, -3, 4, -2, +2, -3, 3, -4, 4, -2, 1, -2, +2, -1, 0, -1, 1, 3, -5, 1, +1, 0, 1, 1, -3, 4, -4, 3, +-2, 1, 1, -1, -1, -1, 2, 1, +-2, 1, -3, 2, 0, 0, 0, 0, +-1, -2, 3, -2, 1, 0, -1, 1, +-1, 0, 2, -1, 1, -1, 0, 0, +1, 2, -3, -2, 4, -3, 2, -2, +0, 4, -6, 4, -3, 2, 0, 1, +-1, -2, 3, -3, 3, -2, 1, 1, +-2, 1, 1, 0, -1, 0, -2, 3, +0, 0, 0, -1, 1, -2, 4, -3, +1, 1, -2, 3, -2, 1, 1, -2, +2, -3, 3, -5, 8, -4, 1, -4, +4, -2, 2, -1, 1, 0, -1, -1, +1, 0, 1, -1, -2, 0, 3, -1, +0, 0, -2, 3, -2, 1, 0, 0, +1, -3, 2, -1, 3, -1, 1, -2, +-1, 0, 2, 1, -4, 4, -4, 2, +0, 1, -1, 0, 0, 1, -3, 2, +0, 3, -5, 0, 1, -1, 3, -1, +-1, 1, -1, 2, -3, 4, -5, 4, +-4, 1, 1, 0, 1, -1, -1, 0, +2, -2, 2, -2, 1, -1, 2, 1, +-1, 0, 1, -2, 1, -3, 4, -2, +2, -1, -1, -1, 3, 0, -1, -1, +1, 1, -2, 4, -4, 6, -7, 3, +-2, 1, 3, -2, -1, -2, 2, 1, +1, -1, -1, -3, 4, -4, 5, -2, +1, -3, 2, -1, 2, 0, 0, 0, +-3, -1, 4, 0, 0, 0, -1, -1, +2, 0, -2, 1, 0, 0, -1, -3, +6, -2, 0, -1, 1, -2, 4, -4, +3, -2, 1, 0, 1, 0, 0, 2, +-4, 2, -1, 0, 2, -2, 0, 0, +-1, 2, -1, 2, -3, 0, 1, -1, +2, -3, 4, -4, 1, -2, 3, 0, +-1, 1, -4, 0, 5, -1, -1, -1, +-1, 3, -4, 4, -3, 4, -4, 1, +-1, 1, -1, 3, -6, 5, -3, 2, +1, -2, 0, -1, 0, 1, 0, 2, +-2, 1, -1, 0, 2, -2, 2, 1, +-4, 2, 0, 1, -2, 3, -2, 0, +0, -2, 3, -2, 2, -1, -3, 1, +2, 3, -4, 1, -2, 0, 2, 0, +-1, 1, -2, 1, -2, 4, -3, 2, +-2, -1, 2, -3, 6, -4, 2, -3, +2, -2, 3, 1, -3, 1, -1, 2, +-2, 0, 2, 0, -4, 2, -2, 4, +-3, 3, -5, 1, 2, -1, 1, -2, +1, 1, -2, 0, 2, -1, 1, -3, +1, -1, 3, 0, -3, 3, -4, 3, +1, 0, 0, -2, 2, -4, 5, -4, +5, -4, 2, -2, 1, -1, 3, -1, +-2, -2, 3, 0, 1, -1, 0, 0, +1, -1, 1, 0, 1, 1, -3, -1, +3, -3, 4, -4, 1, 0, -1, 3, +-3, 3, -3, 1, -2, 2, 0, 1, +-2, 2, -4, 2, 1, 0, -1, 0, +0, -1, 2, 0, 0, -1, 0, 0, +0, -1, 4, -3, 0, -3, 4, -1, +1, 1, -4, 3, -1, 1, -1, 0, +1, 0, -1, -1, 1, 2, -2, 2, +-5, 4, -1, 2, -3, 1, -1, 0, +1, 2, -3, 4, -4, 4, -5, 5, +-3, 4, -5, 4, -4, 2, 1, 3, +-6, 2, 0, -1, 4, -5, 5, -2, +0, 0, 0, 0, 2, 0, -3, -2, +5, -4, 5, -5, 2, -2, 2, -2, +3, -3, 3, -4, 2, -1, 2, 1, +-2, 2, -4, 3, 0, 1, -1, -2, +3, -5, 6, -3, 2, 0, 0, 1, +-2, 0, 2, 1, -3, 1, 0, 1, +0, 1, -4, 5, -5, 6, -6, 4, +-3, 3, -4, 2, 0, 1, 0, 0, +-3, 1, 2, 0, 0, 2, -4, 3, +-2, 3, -2, 2, -1, 0, -1, -3, +6, -6, 6, -6, 2, -3, 5, 0, +-2, 0, -1, 3, -2, 1, 0, 0, +0, -2, 3, -3, 4, 0, -3, 2, +-1, 3, -2, 2, -3, 1, 0, -2, +2, -1, 2, -1, -2, 1, 0, 1, +0, 2, -4, 0, 3, -2, 3, -2, +1, -1, 1, 0, 2, -2, 1, -2, +-1, -1, 4, 0, -3, 1, -2, 2, +0, 2, -3, 2, -2, 0, 1, -1, +2, 0, -3, 2, -1, 1, 2, -1, +-1, 0, 0, 0, 1, 0, -1, 0, +0, 1, -1, 1, -2, 5, -6, 2, +2, -3, 5, -4, 1, -3, 5, -2, +2, -3, 2, -1, 1, -3, 4, -1, +0, 0, -2, 2, 1, 1, -2, -1, +1, -1, 1, 1, -1, 1, -1, 1, +-2, 3, -2, 2, -3, 1, 0, 1, +-1, 4, -6, 3, -1, 2, 0, 0, +-1, 1, -2, 2, -1, 1, -1, 2, +-4, 1, 3, -1, 2, -3, 1, 0, +0, 3, -4, 4, -4, 3, -4, 4, +-3, 4, -4, 3, -4, 3, -1, 3, +-3, 0, 0, 0, 1, 2, -3, 2, +-3, 3, -2, 0, 1, 1, -3, 1, +0, 1, 1, -1, 0, -1, 2, 0, +0, -1, 1, 1, -3, 2, 0, 1, +0, -1, -2, 1, 2, 0, 0, -3, +3, -3, 3, -1, 0, 0, 0, 1, +-2, 2, 1, 0, 0, -1, 0, 0, +1, 2, -3, 0, 0, 0, 1, -1, +2, -3, 2, -3, 3, -1, 2, 0, +-2, -1, 4, -3, 3, -4, 1, -1, +2, -2, 2, -3, 4, -4, 2, -2, +3, -2, 3, -3, 1, -1, 2, 1, +-1, -1, 1, -2, 1, 1, -2, 2, +-3, 2, -1, 0, 2, 2, -4, 2, +0, -2, 5, -4, 2, -2, 2, -1, +3, -4, 4, -3, 2, -3, 5, -4, +4, -2, -2, 1, 1, 0, 1, -1, +0, -3, 3, -3, 4, -4, 3, -4, +3, -4, 5, -2, -1, 2, -3, 2, +1, 1, -2, 0, 0, 1, 0, -1, +1, 0, -1, 0, 0, 0, 2, 0, +-3, 1, 0, 1, 2, -2, 0, 0, +0, 1, -1, 2, -2, 2, -3, 2, +0, 2, -3, 3, -3, 0, 2, 0, +-1, 1, -1, -1, 2, -2, 3, -1, +-1, 2, -4, 3, 0, 1, 0, -4, +4, -3, 4, -2, 0, -2, 3, -2, +2, 0, -1, 2, -4, 2, -2, 3, +-1, 1, -2, -1, 3, -2, 1, -1, +1, -3, 2, -1, 1, 2, -2, 2, +-3, 1, 2, -1, 0, -1, -1, 0, +1, 1, -2, 1, -3, 4, -5, 4, +-3, 4, -4, 2, -1, 0, 4, -2, +1, -2, 1, 2, -2, 4, -5, 5, +-5, 3, -2, 1, -1, 2, -6, 5, +-3, 2, -2, 1, -2, 0, 2, -2, +1, 0, -1, 2, -2, 2, 0, 0, +1, -1, 0, -1, 2, 1, -3, 1, +-1, 0, 1, 0, -1, 1, 0, -1, +0, -1, 1, 1, -3, 1, -1, 2, +0, 1, -3, 2, 1, -1, 1, -1, +2, -2, 1, -2, 3, -3, 4, -4, +2, -3, 3, 0, -2, 1, -2, 1, +0, 1, -1, 0, 1, 0, 0, -1, +2, 1, -1, 1, -2, 1, 2, -1, +0, -2, 1, -1, 1, -1, 0, -1, +0, -1, -1, 0, 1, 1, -3, 1, +1, -1, 2, -1, 0, 0, 0, 2, +-1, 1, -1, 2, -4, 4, -3, 4, +-4, 3, -5, 2, -1, 2, -2, 0, +-1, 0, 1, -1, 1, -1, 2, -3, +2, -4, 7, -5, 4, -3, 0, 3, +-3, 6, -7, 4, -2, -1, 1, -2, +2, -1, -2, 1, -1, 0, 0, 2, +-5, 3, -2, 3, -2, 3, -4, 5, +-2, 3, -2, 1, 0, 1, 0, -2, +2, 0, -2, 3, -6, 2, 0, 0, +-1, -2, 1, -3, 3, -2, 1, 0, +0, -1, 1, -2, 5, 0, -2, 2, +-2, 1, 1, 1, -3, 1, -1, 0, +1, -4, 3, -3, 1, -1, -1, 1, +0, 0, -1, -1, 2, 0, 0, 1, +-2, 2, 0, 1, 0, 0, 2, -2, +3, -5, 6, -5, 3, -3, 2, -4, +4, -3, -1, 1, -2, 2, -3, 2, +-1, 2, -3, 4, -4, 4, -1, 3, +-3, 2, -2, 1, 2, -3, 3, -4, +3, -2, 0, 1, -2, 2, -3, 1, +-2, 1, -1, 2, -4, 2, 0, 2, +-1, 2, -2, 1, 0, 1, 2, -1, +1, 0, 0, 0, 1, -1, -1, 0, +-2, 1, -2, 2, -3, 1, -2, 1, +-1, 2, -2, 4, -4, 4, -3, 3, +1, -1, 2, -2, 2, 1, -1, 2, +-2, 1, -1, 0, 0, 0, -2, 1, +-3, 1, 0, -1, 1, -2, 0, 1, +-1, 3, -2, 2, 0, -1, 3, -2, +4, 0, -1, 2, -3, 4, -4, 4, +-4, 1, 1, -3, 3, -4, 2, -2, +0, 0, 0, -2, 3, -4, 4, -4, +5, -4, 4, -2, 2, -1, 3, -1, +-1, 3, -2, 3, -3, 1, -1, 2, +-3, 2, -4, 2, -1, 1, -2, 0, +1, -1, 2, -2, 3, -2, 3, -2, +4, -3, 5, -2, 2, 0, 0, 1, +0, 1, -3, 1, -2, 1, -2, 1, +-3, 2, -3, 1, -2, 1, 0, 2, +-3, 2, 0, 3, -1, 2, 0, -1, +3, -1, 3, -1, 0, 0, -3, 2, +-2, 2, -5, 3, -6, 4, -4, 2, +-2, -1, 2, -2, 1, 0, 1, 1, +1, 1, 0, 1, 2, 0, 1, -2, +2, 0, 0, 2, -4, 2, -3, 1, +-2, 0, 0, -2, -2, 0, -1, 3, +-4, 4, -4, 3, 1, 1, 0, 1, +1, 1, 0, 2, -2, 3, -3, 3, +-3, 2, -3, 2, -4, 2, -4, 0, +-1, 0, -2, 0, 0, 0, 1, -2, +3, -1, 2, 0, 2, -1, 5, -2, +2, -2, 4, -2, 1, 1, -4, 5, +-6, 3, -4, 1, -3, 3, -7, 4, +-4, 3, -1, 0, 1, -2, 5, -2, +1, 2, -2, 3, 0, 2, -1, 3, +-3, 4, -6, 4, -3, 2, -3, 0, +-2, -2, 1, -1, -2, 2, -3, 3, +-3, 2, 0, 2, -1, 3, -2, 6, +-2, 6, -4, 4, -2, 4, -4, 3, +-4, 1, -1, -1, -2, -1, 0, -2, +-1, 0, -2, 2, 0, -1, 0, 0, +2, 2, 0, 1, 2, 1, 1, 2, +-1, 3, -2, 3, -6, 4, -4, 3, +-4, -1, -2, -2, 1, -2, 1, -5, +3, -3, 3, -1, 1, 1, 0, 2, +3, -2, 5, -2, 1, 3, -2, 5, +-3, 1, -3, 1, -2, 2, -5, 2, +-5, 3, -5, 3, -2, 0, -1, 2, +-2, 4, -3, 5, -2, 3, 1, 1, +2, 0, 3, -1, 1, -1, 1, 0, +-2, 2, -5, 2, -4, 1, -2, 0, +-3, 1, -2, 2, 0, 0, 0, 2, +-1, 3, 2, -1, 5, -3, 4, -2, +4, -2, 2, -2, 1, -2, -2, 1, +-3, 2, -5, 2, -5, 1, -1, -1, +1, -3, 4, -4, 4, -1, 4, -1, +4, -3, 6, -2, 4, 0, 0, -1, +0, -1, -1, 1, -4, 1, -5, 2, +-4, 3, -5, 0, -1, -1, 2, 0, +0, 1, 1, 2, 2, 2, 0, 2, +1, 1, 0, 2, -1, 3, -3, 0, +-4, 2, -4, 3, -6, -1, -1, -3, +2, -3, 1, -1, 1, 1, 2, 0, +3, -1, 4, -1, 4, 0, 3, 0, +-1, 2, -1, 2, -2, 0, -5, 2, +-4, 1, -3, -1, -2, 0, -4, 4, +-2, 3, -3, 3, -1, 3, 3, 0, +3, 0, 3, 1, 1, 1, 0, 0, +-1, 0, -2, 0, -3, -1, -3, -1, +-1, -2, 0, -2, -1, 0, 3, -2, +4, -2, 4, 1, 3, 1, 2, 1, +2, 1, 0, 0, 1, 0, -3, 2, +-5, 1, -3, -1, -2, 0, -3, 1, +-4, 0, 0, 1, 1, -1, 4, -3, +6, 0, 2, 2, 2, -1, 3, 0, +1, 1, -2, 0, -3, 1, -3, 0, +-4, -2, -2, -1, -1, 0, -2, 0, +1, -2, 4, -2, 7, -3, 4, -1, +3, 3, 1, 1, 0, -1, 2, -1, +-1, -1, -2, -1, -3, 0, -4, 1, +-4, 0, -3, 1, 0, 1, 0, 0, +1, 1, 5, -2, 6, -4, 5, 0, +2, 1, 1, -2, 2, -2, -2, 2, +-6, 3, -7, 0, -1, -3, 1, -4, +2, -3, 2, 0, 2, -1, 4, -1, +4, 1, 4, -1, 5, -1, 0, 3, +-3, 5, -5, 2, -6, 1, -3, -1, +-3, -1, -4, 3, -6, 4, -1, -1, +2, 0, 3, 1, 4, 0, 3, 0, +5, -1, 4, -1, 1, 2, -4, 2, +-2, -2, -2, -2, -3, -1, -2, -3, +-1, -2, -1, 1, -1, 1, 0, 1, +3, 0, 5, -2, 6, -2, 5, 0, +2, -2, 3, -4, 2, -5, 3, -6, +1, -3, -4, 3, -6, 1, -4, -1, +1, 1, 1, -1, 4, -3, 7, -2, +7, -2, 5, -1, 3, 2, 0, 0, +1, -5, 2, -3, -1, 0, -6, 0, +-5, 2, -3, 0, -3, -1, 0, 2, +1, 1, 4, -1, 4, 0, 3, 3, +2, 1, 0, 0, -1, 3, -3, 0, +-4, -1, -4, 0, -2, -3, -2, -3, +-1, 1, -1, 0, 1, 0, 2, 1, +5, 0, 5, -1, 4, 1, 4, 0, +1, -1, 0, 0, -1, -1, -3, -1, +-5, 0, -3, -2, -1, -5, 2, -4, +3, -1, 3, -1, 3, 1, 3, 3, +2, 3, -1, 5, -2, 5, -2, 0, +-2, -2, -1, -2, -1, -4, -3, -2, +-4, 2, -4, 1, -3, 2, -3, 5, +-1, 2, 3, -1, 6, -1, 7, -1, +3, 2, -3, 5, -3, 0, -1, -2, +-2, 0, -5, 0, -5, 0, -5, 2, +-3, -1, 2, -5, 6, -2, 4, 1, +2, 3, 1, 4, 2, 1, 5, -5, +4, -1, -1, 1, -4, -2, -4, -1, +-4, 1, -5, -1, -3, -2, 2, -1, +2, -1, 2, 2, 3, 1, 6, -2, +5, -1, 4, 2, 1, 1, -3, 2, +-5, 4, -7, 2, -7, 0, -6, 1, +-4, 1, -4, 1, -2, 2, 2, -1, +6, -5, 9, -3, 9, -2, 6, -3, +4, -1, 3, -2, 1, -4, -2, 0, +-5, 2, -6, -1, -4, -2, 0, -2, +2, -4, 3, -3, 6, -1, 6, -2, +6, -1, 6, 1, 4, 0, 0, 0, +-1, 2, -3, 1, -6, 1, -7, 1, +-3, -4, 1, -8, 4, -4, 4, -3, +4, -2, 4, 1, 5, 0, 6, -1, +5, -1, 6, -2, 3, -2, -2, 2, +-4, -1, -2, -5, -1, -4, -1, -4, +1, -5, 2, -1, 0, 3, -1, 4, +-1, 5, 1, 5, 2, 2, 1, 3, +1, 1, 1, -3, -1, 1, -6, 3, +-9, 2, -8, 3, -8, 4, -6, 1, +-1, -1, 3, 1, 3, 0, 4, 0, +7, 0, 6, -1, 3, 0, 1, 2, +-2, 0, -4, 0, -5, 1, -5, -1, +-5, -1, -4, 3, -5, 5, -4, 1, +3, 0, 6, 0, 5, 0, 4, 1, +5, 0, 4, -3, 0, 1, -4, 6, +-11, 4, -10, 4, -9, 5, -9, 2, +-4, -1, 1, -2, 5, -3, 5, -2, +7, -1, 8, -1, 3, 1, 2, 1, +3, -2, 0, -1, -5, 4, -8, 3, +-8, 1, -7, 1, -3, -1, 0, -3, +1, 1, 4, -1, 7, -4, 9, -1, +7, 0, 4, 0, 0, 2, -1, 1, +-1, -2, -5, 3, -10, 5, -9, 3, +-8, 2, -6, 4, -4, 1, 0, 0, +4, 0, 7, -4, 11, -5, 10, -3, +7, -4, 5, -3, 2, 0, -3, -1, +-5, 2, -8, 5, -9, 2, -6, -1, +-2, 1, 1, -1, 4, -1, 4, 4, +3, 2, 6, -3, 6, 1, 2, 2, +-2, -1, -1, -1, -1, -3, -3, -3, +-5, 1, -5, 0, -3, -2, 0, 1, +2, 1, 3, -2, 6, 1, 6, 1, +4, -1, 4, 0, 3, 0, -1, -1, +-5, 2, -6, 2, -5, -4, -3, -3, +-3, 3, -4, 2, -2, 0, 2, 1, +6, -1, 5, 1, 3, 3, 5, -1, +4, -3, 3, -1, 1, -2, -4, -1, +-6, 1, -4, -2, -3, -3, -3, 1, +-1, 2, -1, 1, 1, 2, 7, -2, +10, -6, 9, -2, 6, 0, 2, 0, +-3, 1, -4, 2, -5, -1, -7, 1, +-6, 0, -2, -3, -1, -1, 1, 0, +4, -3, 5, 0, 5, 3, 4, 0, +4, 0, 3, 2, -1, 2, -5, 3, +-7, 2, -5, -1, -5, -2, -5, 2, +-4, 1, -3, 1, -1, 4, 2, 0, +4, 0, 5, 3, 4, 1, 4, -2, +3, 2, -2, 3, -5, -1, -4, 0, +-5, -1, -4, -4, -1, -3, 0, 0, +-1, 1, 0, 2, 4, 1, 5, 0, +3, 5, 1, 5, 0, 1, 0, 0, +-1, 1, -5, 0, -8, 2, -7, 2, +-6, 0, -6, 2, -3, 3, 1, -1, +3, -1, 5, 3, 5, 1, 5, -1, +5, 0, 4, 0, 0, -1, -3, 0, +-3, -1, -4, -3, -4, -3, -1, -2, +-2, 0, -3, 3, 1, 2, 4, -2, +5, 2, 6, 1, 6, -3, 5, -1, +2, 0, -1, 0, -6, 1, -7, 2, +-5, -2, -6, 1, -7, 4, -2, -2, +3, -3, 4, 1, 7, -3, 8, -3, +6, 3, 3, 1, 2, -1, 0, 0, +0, -3, -2, -3, -5, 0, -5, -2, +-2, -3, -2, -1, 2, -2, 6, -4, +6, 1, 5, 2, 4, 0, 4, 2, +3, 0, 2, -1, -2, 3, -8, 4, +-7, -2, -4, -2, -3, -1, -4, -1, +-2, 1, -1, 4, -1, 4, 1, 3, +4, 3, 5, -2, 5, 0, 3, 2, +-1, -2, -1, -3, -2, 0, -5, -2, +-4, -3, -3, 1, -3, -3, 2, -5, +5, 1, 3, 3, 1, 2, 4, 4, +4, 2, 1, 0, 2, 1, 1, -2, +-2, -3, -4, 0, -5, 1, -6, 0, +-6, 0, 0, -1, 3, -3, 3, 0, +6, 0, 8, -3, 5, 3, 1, 6, +-1, 2, -3, 3, -5, 4, -5, 0, +-6, -2, -4, 0, -2, -4, -1, -2, +0, 1, 2, -2, 6, -3, 7, -2, +10, -5, 11, -5, 6, -1, 3, -2, +0, -2, -3, 1, -5, -1, -3, -4, +-5, 1, -6, 3, -5, 2, -3, 2, +3, -3, 10, -7, 11, -3, 7, 0, +5, -1, 2, 1, -2, 3, -4, 1, +-6, 1, -6, 1, -4, -3, -5, 1, +-5, 3, -3, -1, 2, -2, 5, 0, +5, -2, 8, -4, 8, 1, 2, 2, +-2, 4, -3, 4, -7, 2, -6, -1, +-4, 0, -5, 1, -6, 0, -2, 1, +2, -2, 4, -4, 7, -1, 8, -2, +7, -3, 6, 1, 2, 2, -1, -1, +0, -2, -1, -2, -3, -2, -6, 1, +-6, 3, -5, -1, -2, -1, 3, 0, +4, -1, 3, 1, 3, 5, 2, 2, +1, 0, 1, 2, -2, 2, -7, 2, +-7, 3, -5, -3, -4, -5, 0, -3, +3, -6, 3, -3, 4, 1, 4, -1, +7, -3, 8, -1, 6, 0, 3, -1, +1, -1, 2, -4, 0, -2, -5, 2, +-7, 2, -5, 0, -5, 3, -4, 3, +0, -1, 4, -1, 6, 0, 6, -1, +6, -1, 5, 0, 4, -2, 1, 0, +-3, 2, -6, 0, -6, 1, -9, 5, +-8, 2, -5, 0, -1, 1, 2, -2, +4, -1, 6, 0, 6, -3, 6, -1, +3, 2, -1, 0, -3, 0, -5, 2, +-7, 1, -7, 0, -6, 2, -4, 0, +-3, 0, 0, 3, 1, 1, 3, 0, +5, 1, 4, 2, 2, 1, -1, 4, +-4, 4, -5, 1, -6, 3, -7, 4, +-8, 1, -6, 2, -4, 4, -3, 2, +-1, 3, 2, 4, 3, 2, 3, 1, +5, 2, 4, 0, -1, 1, -2, 2, +-3, -1, -5, 0, -6, 3, -6, 1, +-4, -2, -1, -1, 4, -1, 2, 0, +2, 4, 3, 2, 4, -2, 3, 1, +2, -1, 1, -3, -2, 1, -6, 3, +-7, -2, -5, -2, -2, -2, 0, -4, +1, 0, 0, 3, 2, -2, 6, -3, +7, -2, 9, -7, 8, -5, 4, 1, +-1, -2, -2, -2, -2, 0, -5, 0, +-5, 1, -5, 4, -3, 1, 0, 0, +4, 0, 7, -3, 6, 1, 4, 2, +4, -2, 6, -5, 5, -2, 1, -3, +0, -5, 0, -2, -3, 1, -6, 2, +-6, 5, -3, 3, 1, -2, 4, 0, +5, 2, 3, -1, 4, 0, 2, 1, +1, -3, 0, -1, -4, 1, -4, -3, +-4, -2, -4, 1, -4, -1, -2, -1, +1, -1, 5, -6, 7, -3, 5, 3, +0, 2, 1, -2, 4, -2, 3, -3, +-1, -2, -3, 1, -4, 0, -5, 0, +-5, 3, -2, 0, 0, -1, -1, 4, +2, 2, 4, 0, 4, 1, 6, 0, +6, -4, 4, -2, 3, -1, 0, -3, +-1, -3, 2, -6, 3, -6, 2, -4, +3, -3, 5, -3, 2, 1, 3, 2, +4, -1, 3, 2, 0, 5, -1, 1, +-1, 0, -4, 2, -4, 0, -5, -2, +-3, -2, 0, -6, 3, -8, 5, -4, +4, -1, 2, -1, 2, 1, 3, 1, +3, -2, 2, 0, 2, 1, -2, -1, +-3, 0, -2, -2, -4, -1, -4, 1, +-3, 0, 0, -3, 2, 0, 2, 3, +1, 2, 0, 4, 2, 3, 1, 1, +1, 2, -1, 3, -2, -1, -2, 0, +-4, 3, -4, -1, -1, -3, 1, -1, +2, -1, 2, 0, 2, 2, 4, -1, +5, -3, 7, -1, 5, -2, 1, 0, +-3, 4, -3, -1, -3, -4, -1, 0, +-3, 1, -5, 0, -2, 2, -2, 1, +0, -1, 2, 1, 3, 0, 3, -1, +1, 2, -2, 4, -3, 0, -2, -2, +0, -2, -1, -3, -5, 1, -6, 3, +-3, -2, 1, -3, 1, 2, 1, 1, +0, 2, 3, 3, 2, 0, 3, -2, +3, 0, 0, -1, 0, -2, 0, -3, +2, -5, 2, -3, -2, 3, -4, 4, +-2, 0, 2, 0, 5, -1, 5, 0, +3, 3, 1, 3, 1, 2, -2, 5, +-5, 3, -2, -2, -1, -1, -1, -1, +-2, -2, 0, 0, -1, 2, -2, 2, +-2, 5, -3, 5, 1, -1, 5, -5, +7, -5, 6, -6, 4, -4, -2, 3, +-7, 2, -7, 0, -3, 0, -3, -1, +-2, -3, 1, 0, 0, 1, -1, 1, +1, 1, 4, -3, 3, -3, 3, 0, +0, -1, 0, -2, -1, 0, -3, 1, +-3, -2, -1, -2, 2, 0, -1, 0, +0, 0, 5, -1, 4, -1, 3, 2, +4, -1, 5, -2, 1, 3, -2, 4, +-1, -1, 0, -1, -1, 1, 0, -2, +1, -2, 1, 0, 3, -3, 6, -5, +5, 0, 4, 1, 0, 2, -1, 4, +1, 0, 0, -2, -1, 2, -3, 1, +-4, 0, -5, 2, -5, 1, -4, 1, +-5, 3, -2, 0, 1, -3, 1, 1, +1, -1, 1, -3, 2, -1, -1, 0, +-2, 0, -3, 1, -5, 2, -4, 0, +-4, 0, -3, 2, -4, 2, -4, 3, +-2, 2, 1, -2, 5, -1, 3, 1, +3, -1, 4, 0, 2, 1, 2, -1, +1, 0, -2, 6, -6, 4, -4, 3, +-1, 3, -2, 3, 1, 1, 2, 2, +3, 1, 4, -1, 4, 1, 4, 1, +1, 0, 1, 0, 1, -1, 0, -2, +-1, 1, -4, 2, -4, 1, -4, 1, +-2, 1, -1, 0, -3, 2, -1, 2, +-1, 0, -3, 2, -3, 3, -6, 3, +-7, 3, -7, 2, -4, -1, -6, 1, +-7, 3, -5, -1, -3, -2, 0, -1, +1, -2, 2, -1, -1, 4, -1, 0, +3, -4, 6, -4, 5, -1, 1, 0, +0, 1, 1, 0, 1, -1, 2, -1, +5, -3, 6, -3, 5, -1, 6, -1, +8, -3, 6, -1, 8, -2, 7, -2, +3, 2, 1, 2, 1, -1, 2, -1, +0, -2, 4, -6, 3, -2, 0, 0, +0, -2, 1, -2, 0, 2, -2, 0, +-1, 0, -1, 1, -2, -2, -2, -1, +-4, 2, -7, 2, -7, 0, -7, 2, +-6, 0, -6, -1, -3, 0, -4, -1, +-2, -1, -1, 2, -3, 3, -3, 2, +-3, 2, -1, 2, -2, 1, -1, 1, +0, 1, 0, 0, 0, 2, 1, 1, +3, -2, 4, 1, 3, 3, 4, 0, +6, 0, 6, 4, 2, 4, 3, 2, +5, 1, 4, 0, 5, -1, 3, 1, +1, 2, 0, 1, -1, 2, 0, 2, +-2, 2, -1, 2, -2, 2, 0, -2, +1, -1, -1, 1, -5, 3, -8, 4, +-7, 1, -6, -1, -8, 1, -8, 1, +-7, -4, -3, -5, -1, -4, -4, -1, +-7, 3, -7, -1, 1, -6, 1, -3, +-1, 0, -2, 0, -3, 3, -5, 6, +-7, 4, -3, 2, -3, 4, -2, 2, +1, 1, 2, 1, 5, -2, 8, -2, +8, 1, 6, 2, 7, 1, 6, 4, +3, 3, 6, -1, 9, -4, 11, -5, +10, -3, 4, 0, 6, -1, 3, 0, +1, 3, -1, 4, -1, 2, 0, 1, +1, -1, 2, -2, -2, 0, -3, 1, +-5, 0, -6, 0, -7, -1, -7, -3, +-5, -4, -7, 0, -10, 2, -12, 4, +-13, 5, -10, 1, -8, -1, -4, -1, +-2, -3, -4, 0, -4, 1, -5, -1, +-2, -2, -2, 2, -5, 3, -3, 1, +0, 0, 3, 2, 0, 3, 2, 3, +7, 0, 9, -2, 9, 3, 7, 3, +8, 0, 10, 1, 8, 1, 9, -2, +10, -3, 9, 0, 7, -1, 7, -3, +10, -3, 8, -2, 6, -1, 4, 1, +4, 1, -1, 2, -2, 3, -3, 2, +-6, 0, -4, 0, -6, -2, -8, 0, +-9, 2, -12, 0, -11, 1, -11, 0, +-10, -1, -8, 0, -10, 2, -9, 2, +-10, 1, -9, 3, -10, 3, -11, 3, +-9, 3, -9, 2, -6, 1, -5, 0, +-1, 0, 0, 1, -1, 4, 1, 4, +3, 2, 6, 2, 8, 1, 11, -1, +12, -1, 12, -1, 12, 0, 8, 4, +5, 5, 7, 1, 8, -1, 10, 1, +9, -1, 10, -2, 10, -1, 9, -2, +9, -1, 5, 1, 4, 0, 1, -2, +1, -1, -2, -1, -6, -1, -7, 0, +-10, 1, -13, 3, -15, 4, -13, 1, +-12, 0, -12, 1, -12, 3, -14, 2, +-12, 0, -9, -3, -7, -6, -5, -6, +-6, -4, -6, -3, -7, -3, -4, -2, +-2, -3, -3, 1, -2, 5, -3, 3, +3, 0, 8, -1, 10, -1, 11, 0, +10, 0, 12, 0, 11, 1, 9, 4, +8, 3, 8, 2, 10, 2, 12, -3, +17, -3, 14, 1, 11, 1, 14, -4, +14, -2, 11, 2, 3, 4, 1, 3, +0, 0, -1, -1, -3, 1, -9, 2, +-8, -1, -8, -2, -8, -2, -8, -2, +-10, -1, -11, 1, -11, -4, -7, -5, +-8, -2, -12, -2, -13, -1, -14, 1, +-16, 1, -15, -1, -12, -1, -10, -2, +-9, -1, -4, -2, -2, -4, 4, -4, +5, -1, 4, 1, 7, 0, 7, 0, +11, -1, 10, -1, 11, 2, 9, 2, +10, -2, 15, -1, 15, -2, 16, -1, +16, 0, 17, 0, 18, -1, 17, -1, +16, 1, 14, -2, 13, -3, 13, -3, +8, -4, 6, -3, 1, -1, -2, -1, +-5, -1, -6, -1, -7, 1, -12, 1, +-8, -1, -9, -2, -10, -1, -12, 1, +-14, -1, -16, 0, -19, 2, -19, 1, +-19, -2, -18, 0, -17, 0, -14, -2, +-12, -1, -10, 0, -6, -2, -1, -3, +1, -2, 5, -3, 4, -2, 7, -1, +8, -3, 10, -3, 11, -1, 9, -2, +15, -4, 15, -2, 18, -3, 19, -3, +21, -2, 22, -3, 22, -3, 23, 0, +18, 1, 16, 2, 14, 3, 8, 2, +8, 0, 8, -2, 4, 0, 0, 1, +-2, 0, 0, -4, -1, -4, -1, -1, +-7, 1, -10, 2, -11, 3, -16, 2, +-15, 0, -18, 1, -20, 3, -25, 3, +-25, 3, -23, 1, -21, -3, -16, -2, +-17, 2, -17, 3, -15, 5, -13, 4, +-7, -1, -2, -3, 1, 0, 0, 0, +-1, 1, 4, 0, 4, 0, 7, 0, +8, 0, 11, 2, 12, 2, 14, 1, +21, 0, 20, 1, 22, 1, 23, -2, +25, -2, 22, -1, 19, -2, 18, -1, +12, 1, 9, 1, 8, 0, 4, 2, +3, 2, 1, 0, 1, 0, 1, -1, +-1, -2, -2, -1, -8, 1, -10, 0, +-14, -1, -16, 0, -20, 0, -24, 1, +-23, 1, -25, 0, -22, -1, -21, -1, +-17, -3, -14, -1, -15, 1, -14, 3, +-12, 0, -9, 1, -8, 1, -6, -1, +-4, 2, -5, 3, -3, 2, 2, -1, +7, -1, 10, 1, 10, 2, 17, -2, +22, -4, 26, -1, 24, 1, 23, -1, +27, -3, 24, -2, 22, -1, 17, 1, +16, 0, 14, 0, 10, 3, 9, 3, +7, 1, 9, 0, 8, 0, 5, -1, +5, -3, 2, -3, 0, -3, -7, 1, +-14, 4, -19, 1, -20, -3, -17, -2, +-24, 2, -26, 3, -27, 3, -25, 2, +-22, 1, -22, 4, -18, 3, -19, 1, +-15, 0, -12, -1, -12, 0, -13, 4, +-15, 5, -12, 1, -5, -2, -1, -2, +3, -1, 6, -1, 13, -2, 17, -2, +17, 2, 19, 3, 20, 0, 25, -1, +23, 1, 22, 1, 19, 1, 19, 0, +21, -3, 19, -3, 20, -2, 16, -1, +16, 1, 13, 1, 13, -2, 15, -3, +10, -1, 4, 1, 0, -1, -3, -3, +-5, -3, -12, -2, -15, -1, -18, -2, +-20, -1, -21, 0, -23, 1, -21, 0, +-22, -1, -15, -4, -15, -4, -16, -1, +-18, 1, -20, 1, -19, 2, -20, 0, +-15, -2, -11, -3, -8, -3, -4, -1, +-3, 2, 0, 2, 5, 1, 10, 0, +15, 2, 15, 3, 16, 4, 16, 3, +19, 1, 20, 2, 15, 5, 17, 2, +17, 0, 21, -1, 21, -2, 23, -3, +23, 1, 18, 2, 17, 1, 14, 2, +12, 2, 6, 3, 2, 2, -2, 3, +-9, 1, -9, -1, -11, -1, -15, 0, +-17, 1, -19, 1, -20, 2, -21, 0, +-17, -2, -17, -2, -19, -2, -17, -2, +-21, -1, -21, 1, -25, 2, -23, 0, +-20, -2, -19, 0, -14, 0, -12, -1, +-5, -1, -2, 0, 3, 0, 6, 3, +7, 3, 11, 3, 12, 2, 14, 1, +17, -1, 17, -1, 20, -1, 20, -2, +21, -1, 22, -1, 22, -1, 25, 1, +22, 1, 24, 1, 21, 2, 21, 0, +18, 0, 12, 1, 8, 1, 2, 0, +1, -1, -4, -1, -8, 0, -10, 1, +-13, 0, -13, 0, -14, -1, -14, 0, +-17, 2, -20, 1, -18, -1, -21, -1, +-22, -1, -24, 0, -25, -1, -22, -3, +-24, -1, -20, 0, -20, -2, -13, -1, +-9, -2, -4, -3, 2, -2, 2, 0, +5, 3, 2, 4, 6, 2, 11, -2, +11, 0, 13, 2, 12, 0, 16, 0, +19, 0, 21, -1, 26, -2, 26, -2, +30, -3, 29, -2, 26, 0, 24, 1, +17, 1, 18, -2, 14, -5, 14, -4, +6, 1, -2, 2, -2, 1, -6, 1, +-5, 0, -7, 0, -9, 2, -12, 3, +-14, -1, -13, 0, -18, 3, -24, 3, +-26, 2, -27, 0, -24, -3, -24, -4, +-21, -4, -21, -2, -21, 1, -17, 1, +-16, 1, -9, 2, -11, 5, -7, 4, +-4, 0, 3, -4, 9, -6, 7, -4, +10, -3, 10, -3, 13, -2, 15, 0, +14, 1, 19, 1, 21, 1, 24, 0, +27, -1, 27, -1, 28, -2, 25, -2, +24, 0, 17, 1, 13, 0, 12, -1, +9, -1, 8, 0, 0, 4, -1, 3, +-1, -1, 3, -6, 4, -4, -2, -1, +-8, 3, -15, 4, -17, 1, -19, 1, +-23, 1, -23, -1, -25, -3, -23, -2, +-23, -2, -24, 0, -20, 1, -21, 2, +-17, 3, -16, 2, -12, 2, -9, 2, +-10, 2, -5, 1, -6, 0, -1, -1, +1, -1, 2, -1, 7, -1, 11, -4, +17, -4, 20, -3, 24, -4, 28, -4, +27, -1, 26, 2, 23, 0, 23, 1, +20, 3, 14, 2, 15, 0, 14, -2, +16, -4, 13, -3, 11, 0, 8, 1, +5, 2, 4, 2, 0, 1, 2, -1, +-3, 0, -7, -1, -9, -1, -15, 0, +-17, 0, -21, -2, -21, -2, -20, -4, +-21, -3, -19, 0, -21, 1, -20, 3, +-19, 3, -17, 0, -11, -2, -12, -1, +-8, -2, -10, -2, -8, -1, -5, -5, +-2, -6, 3, -2, 0, 1, 5, 0, +10, -2, 16, -2, 19, 0, 18, 1, +22, 0, 21, -1, 22, -1, 22, -1, +20, -1, 20, -2, 18, -3, 19, -3, +16, -1, 13, 2, 13, 1, 10, 2, +11, 3, 7, 2, 8, -1, 7, -2, +2, -2, 0, -2, -8, -1, -10, 0, +-16, 1, -18, -1, -17, -3, -17, -3, +-17, -1, -19, 1, -19, 2, -19, 2, +-16, -3, -10, -5, -13, -2, -13, -1, +-13, -2, -15, 2, -16, 4, -17, 2, +-9, -1, -6, -3, 2, -5, 5, -1, +4, 3, 8, 2, 9, 1, 17, 1, +15, 0, 18, -1, 18, 0, 16, -1, +18, -2, 16, -1, 16, -1, 17, -2, +17, -2, 20, -3, 19, -4, 20, -1, +15, 1, 12, 0, 13, -2, 8, -1, +7, -2, 0, -1, -3, 0, -7, -1, +-10, -1, -11, 1, -17, 1, -14, -1, +-14, -1, -14, 1, -17, 4, -18, 4, +-16, 1, -17, 0, -14, 0, -16, 1, +-20, 2, -19, 1, -19, 1, -15, 1, +-15, 2, -12, 3, -8, 4, -7, 4, +1, 1, 3, 1, 8, 1, 7, 4, +6, 5, 8, 4, 7, 4, 11, 2, +10, 2, 11, 3, 10, 3, 12, 1, +17, 0, 16, -2, 20, -2, 20, -1, +16, 2, 14, 3, 10, 3, 8, 4, +1, 5, -3, 3, -1, -1, -4, -1, +-4, 1, -10, 1, -7, 0, -10, 0, +-9, -1, -7, -2, -8, -4, -6, -3, +-11, -1, -13, -2, -13, -4, -13, -3, +-16, 0, -18, -1, -14, -2, -16, 1, +-16, 2, -10, -2, -7, -1, -3, 0, +-2, 0, 2, 0, 5, -1, 5, -1, +9, -1, 6, 0, 8, 0, 6, 1, +7, -1, 12, -4, 15, -5, 19, -3, +16, -1, 19, -2, 19, 0, 18, -1, +17, 0, 14, 0, 14, 0, 10, -1, +9, -2, 8, -2, 3, -1, 2, 0, +0, -2, -1, 1, -5, 2, -6, -2, +0, -5, -3, -3, -3, 0, -8, 2, +-11, 2, -11, -1, -12, -4, -13, -2, +-15, -2, -14, -3, -16, -1, -15, -1, +-10, -4, -7, -3, -3, 0, -5, 1, +-6, 3, -5, 4, -6, 4, -4, 4, +-6, 5, -2, 5, -1, 4, 0, 2, +6, 1, 4, 1, 8, 2, 8, 4, +8, 4, 10, 3, 14, -1, 18, -1, +15, 0, 15, 0, 14, -2, 13, -1, +9, 3, 0, 3, 1, 1, 2, -2, +4, -1, 3, 2, -1, 2, 1, 1, +-1, 0, 0, -2, -1, -3, -3, -4, +-2, -4, -9, -2, -10, 0, -15, 1, +-13, 0, -12, 0, -15, 2, -13, 1, +-14, -1, -9, -1, -8, -2, -5, -3, +0, -3, -1, -2, -1, -1, -4, 1, +-2, -1, 0, -4, 0, -2, 2, 0, +-2, 1, 2, 2, 5, 2, 7, 1, +12, 2, 10, 1, 15, -2, 13, -3, +15, -4, 14, -4, 12, -2, 11, 1, +6, 2, 5, 3, 3, 2, 5, -2, +8, -3, 6, -3, 7, -2, 4, -3, +4, -1, 2, 2, -4, 4, -4, 5, +-8, 3, -8, 1, -9, -2, -10, -4, +-8, -3, -11, -3, -6, -4, -6, -3, +-5, -1, -6, 1, -7, 0, -5, -1, +-4, -5, 0, -8, -2, -4, -5, -1, +-5, 0, -5, 2, -4, 4, -4, 1, +0, -2, 4, -3, 4, -2, 7, -2, +9, -4, 14, -5, 14, -2, 10, 3, +8, 4, 5, 3, 9, -1, 7, -2, +7, -2, 4, -1, 6, -2, 9, -3, +10, -2, 12, -2, 9, 0, 8, -1, +7, -4, 5, -5, 5, -4, 0, -4, +0, -2, -2, -1, -5, -2, -3, -1, +-8, 2, -8, 3, -9, 1, -9, -1, +-7, -1, -9, -1, -6, 2, -9, 6, +-7, 4, -8, 6, -10, 5, -11, 3, +-12, 2, -9, 0, -6, -4, -1, -4, +1, -1, 0, 2, 1, 4, 2, 4, +6, 0, 8, -4, 7, -3, 8, -4, +5, -4, 8, -2, 8, -2, 7, 0, +7, 3, 4, 4, 4, 3, 2, 1, +7, -2, 5, -2, 5, 0, 5, 3, +1, 5, 3, 4, 3, -1, 5, -2, +1, 1, -5, -1, -3, -4, -5, -4, +-4, -2, -2, -2, -2, 1, -1, 3, +-4, 1, -4, 1, -6, 0, -6, -3, +-5, -2, -7, -1, -6, -3, -6, 0, +-6, 4, -8, 5, -6, 2, -3, 1, +-4, -1, -3, -3, -1, -3, 2, -3, +5, 0, 4, 4, 3, 2, 5, -2, +8, -3, 6, -4, 6, -7, 8, -9, +8, -8, 9, -3, 3, 4, 5, 5, +7, 4, 5, 4, 6, 3, 3, -2, +6, -4, 4, -5, 5, -8, 6, -5, +3, 0, 2, 4, -1, 3, 1, -2, +3, -6, 1, -5, 2, -5, 0, -6, +-1, -1, -2, 1, -4, 4, -6, 7, +-7, 8, -5, 2, -7, 0, -8, -1, +-9, -4, -8, -2, -5, 2, -6, 6, +-4, 6, -5, 8, -4, 6, -3, 2, +-1, -1, 2, -5, 0, -6, 0, -2, +-2, 1, -3, 5, -1, 8, -1, 5, +4, 0, 5, -3, 5, -5, 7, -6, +3, -3, 6, -1, 4, 1, 5, 7, +0, 10, -1, 5, 4, 0, 2, -5, +5, -8, 4, -8, 2, -4, 0, 1, +-1, 1, 3, 2, 3, 4, 0, 7, +-2, 6, -6, 0, -5, -4, -6, -2, +-7, 1, -7, 5, -7, 7, -5, 4, +-3, 0, 1, -2, -1, -3, 0, -6, +0, -8, 1, -8, 1, -5, -2, 2, +-1, 7, -2, 8, -2, 7, -3, 1, +-1, -7, 2, -7, -1, -5, 0, -4, +2, -2, 4, 0, 6, 4, 2, 7, +3, 6, 4, -2, 5, -7, 6, -7, +2, -6, 3, -4, 1, 0, 3, 3, +2, 5, 2, 5, 4, 2, 0, -1, +1, -4, 2, -9, 3, -8, 4, -1, +1, 5, -1, 7, -1, 6, 0, 1, +1, -3, -1, -2, -4, -3, -6, -5, +-6, -3, -6, 2, -5, 7, -4, 10, +-2, 9, -1, 3, -3, -2, 0, -7, +-2, -8, -1, -6, -1, -1, -5, 3, +-4, 7, -6, 11, -4, 8, -2, 3, +0, -2, 2, -7, 0, -9, 3, -5, +1, 0, 0, 5, 2, 8, 0, 9, +0, 7, -2, 4, -3, -2, -1, -6, +-2, -5, 1, -4, 2, -1, 5, 4, +4, 6, 4, 3, 6, -2, 8, -7, +8, -11, 5, -10, 3, -9, 0, -6, +1, -2, 4, 4, 2, 7, 2, 6, +0, -1, 1, -7, 0, -9, -1, -7, +1, -6, 0, -2, 0, 5, -3, 9, +-7, 10, -3, 8, -3, 1, 0, -7, +-2, -9, -2, -9, -3, -3, -5, 5, +1, 7, 0, 9, -1, 10, -2, 5, +-2, -4, 2, -8, 3, -12, 4, -11, +3, -4, 0, 4, 1, 7, 0, 10, +0, 9, 1, 1, 1, -3, 1, -5, +0, -8, 2, -8, 3, -1, 3, 4, +2, 9, 4, 10, 2, 3, 1, -3, +1, -7, 0, -11, 3, -8, 1, -2, +0, 0, 2, 5, -2, 12, -4, 13, +-4, 5, 1, -2, 0, -7, -6, -8, +-5, -7, -4, -2, 0, 4, 1, 7, +2, 4, 5, 0, -3, 3, -4, -3, +-2, -10, 2, -11, 3, -8, -1, 0, +-5, 10, -5, 13, -1, 7, 3, 2, +3, -4, 1, -11, 2, -13, 1, -9, +2, -6, 2, 2, 2, 11, 1, 14, +-4, 14, -5, 10, -3, -2, -1, -10, +3, -9, 3, -8, 1, -2, 2, 7, +-3, 10, 0, 10, 1, 9, 2, 4, +0, -4, -4, -8, -2, -9, -3, -4, +-2, 5, 2, 9, 0, 10, -1, 9, +-2, 1, -1, -5, 0, -5, -3, -6, +-2, -8, -4, -3, -4, 3, -1, 7, +-1, 11, 1, 11, -3, 5, -6, -2, +-7, -7, -6, -10, -3, -7, 2, -3, +3, 2, 3, 7, 0, 10, -2, 6, +1, -1, 0, -6, 3, -13, 3, -12, +1, -5, 1, 2, -2, 8, 1, 11, +5, 7, 3, 3, 4, 0, -2, -8, +0, -14, 4, -11, 3, -3, 6, 4, +4, 9, 5, 9, 2, 5, -1, 0, +4, -5, 2, -10, 1, -8, -1, -7, +-3, -5, 2, 3, 0, 13, 0, 13, +2, 5, 1, -4, 0, -13, -4, -13, +-1, -9, 1, -4, -1, 4, -3, 11, +-5, 10, -5, 8, -2, 6, -1, -4, +2, -14, 4, -16, 0, -13, 1, -5, +-1, 8, -1, 12, 1, 11, 0, 9, +0, 0, 0, -9, 1, -12, 3, -13, +4, -12, 8, -1, 4, 9, 0, 10, +4, 9, 0, 5, 6, -6, 8, -12, +7, -12, 3, -9, -4, -3, -1, 3, +1, 10, 1, 16, 0, 17, -4, 6, +-4, -4, -4, -11, 0, -15, 6, -12, +6, -3, 6, 1, 0, 7, -6, 13, +-3, 8, -2, 3, -1, -3, -2, -13, +-3, -17, -3, -8, -3, 1, -1, 7, +5, 12, 2, 7, 2, -2, 0, -4, +-5, -8, 1, -13, 1, -10, 2, -3, +-3, 6, -7, 13, -1, 13, 2, 4, +7, -1, 7, -6, 1, -10, 0, -8, +-4, -5, -1, -2, 6, 4, 5, 12, +7, 11, 2, 8, -1, 2, -2, -9, +1, -16, 8, -12, 6, -5, 2, 3, +-1, 10, -2, 9, 2, 7, 4, 6, +3, -1, 3, -12, -2, -14, -3, -13, +-2, -6, -1, 7, 1, 16, -5, 16, +-7, 9, -5, 1, -7, -8, -2, -9, +2, -12, 3, -12, 2, -4, -6, 7, +-5, 13, -3, 12, 1, 6, 6, -5, +0, -11, -2, -11, -5, -10, -4, -4, +4, 3, 5, 6, 6, 11, 1, 13, +-4, 7, 0, -5, 4, -13, 10, -17, +8, -11, 0, 1, 0, 6, -3, 10, +2, 11, 9, 4, 9, -1, 5, -1, +-4, -8, -5, -13, 1, -8, 0, 2, +4, 9, 4, 13, -1, 10, -1, 1, +-6, -2, -2, -7, 1, -11, 0, -10, +-1, -2, -10, 3, -11, 13, -5, 17, +-2, 11, 3, 5, -3, -4, -8, -12, +-7, -13, -7, -6, 2, -2, 1, 5, +0, 12, -4, 12, -8, 8, -1, 4, +1, -7, 5, -14, 7, -13, 1, -9, +-1, 2, -4, 13, -1, 14, 7, 8, +3, 9, 1, 1, -2, -10, -1, -13, +5, -13, 6, -9, 10, 4, 6, 14, +-1, 13, -2, 12, -4, 6, -1, -4, +4, -8, 2, -10, 1, -9, -6, -2, +-8, 8, -1, 11, 0, 13, 4, 11, +1, -3, -4, -13, -3, -13, -3, -13, +2, -7, 5, 1, 1, 4, -3, 10, +-13, 15, -10, 9, -3, -1, -1, -6, +3, -14, -3, -15, -4, -4, -5, 6, +-1, 10, 6, 13, 4, 9, 0, 3, +-6, 1, -8, -7, 2, -14, 7, -10, +7, -3, 7, 4, -3, 15, -3, 14, +2, 2, 10, -5, 13, -8, 6, -11, +2, -10, 0, -5, -2, 0, 3, 7, +5, 11, 7, 8, 4, 3, -3, -4, +0, -14, -1, -14, 3, -7, 5, -1, +-2, 6, -5, 12, -9, 10, -6, 7, +1, 7, -1, -1, -1, -9, -8, -12, +-10, -10, -4, -4, -5, 10, 0, 16, +-2, 13, -8, 9, -6, -1, -7, -10, +2, -11, 7, -11, 7, -12, 6, -2, +-3, 7, -5, 12, -1, 10, 4, 4, +11, -7, 6, -12, 2, -12, 3, -11, +1, -5, 8, 3, 11, 5, 10, 9, +4, 12, -4, 3, -1, -7, 4, -11, +8, -15, 11, -9, 2, 2, -2, 5, +-1, 6, -1, 9, 6, 5, 5, -1, +3, -3, -5, -7, -10, -12, -4, -7, +0, 1, 3, 8, 0, 13, -6, 7, +-6, -3, -8, -5, -4, -6, 2, -10, +-1, -7, 0, -3, -7, 1, -9, 9, +-2, 14, 1, 6, 9, -2, 4, -6, +-5, -12, -5, -11, -4, -5, 4, 0, +7, 5, 2, 12, 0, 11, -5, 7, +0, 2, 7, -8, 10, -14, 12, -8, +1, -1, -4, 3, -1, 9, 2, 9, +9, 5, 7, 4, 3, 0, -1, -7, +-9, -6, -1, -9, 5, -8, 8, 4, +6, 12, -6, 11, -5, 8, -8, 4, +-5, -5, 3, -7, -1, -5, -5, -6, +-9, -3, -11, 6, -4, 10, -3, 13, +1, 9, 1, -5, -6, -10, -6, -9, +-7, -7, -1, -2, 2, 6, -1, 5, +-2, 4, -6, 8, -5, 5, 3, -2, +4, -3, 4, -9, 0, -11, -1, -3, +2, 4, 3, 6, 13, 5, 13, 4, +5, 0, 1, -1, -4, -5, 0, -8, +7, -7, 7, -2, 8, 4, 0, 10, +-4, 13, -1, 6, 1, -1, 11, -6, +5, -9, -2, -4, -7, -1, -9, -1, +-1, 5, 1, 11, 2, 8, -1, 3, +-9, -3, -5, -12, -3, -12, -3, -3, +2, 0, -4, 3, -7, 9, -10, 7, +-8, 3, 4, 1, 5, -5, 4, -12, +-2, -10, -9, -9, -3, -5, 3, 2, +8, 8, 9, 7, -4, 8, -5, 3, +-3, -6, 2, -6, 10, -7, 8, -9, +9, -3, 2, 6, -3, 9, 2, 10, +3, 5, 11, -6, 11, -11, 2, -6, +0, -5, -2, -5, 7, 0, 11, 4, +4, 9, 1, 11, -7, 5, -6, -5, +0, -9, 3, -11, 5, -7, -2, 0, +-6, 3, -7, 4, -7, 8, 1, 5, +3, -1, 1, -5, -2, -9, -10, -10, +-8, -4, -5, 2, 2, 2, 6, 6, +-4, 6, -6, -1, -5, -1, -5, 0, +2, -3, 0, -4, -1, -2, -1, -3, +-3, 4, 5, 9, 7, 6, 9, 2, +6, -1, -2, -9, 1, -10, 0, -3, +5, -1, 10, 0, 8, 5, 6, 8, +-1, 5, 0, 2, 9, -7, 9, -12, +10, -7, 0, 0, -9, 4, -8, 9, +-7, 10, 2, 5, 5, 3, 2, -1, +-1, -8, -6, -11, -2, -10, 2, -8, +1, 3, 0, 11, -9, 9, -12, 7, +-8, 3, -4, -7, 5, -8, 2, -5, +-5, -7, -7, -4, -9, 2, -3, 7, +2, 10, 3, 9, 3, 3, -8, -1, +-8, -2, -4, -5, 0, -2, 7, 2, +3, 3, 2, 3, 0, 7, 0, 4, +8, -1, 8, -4, 9, -8, 6, -10, +-3, -2, 1, 1, 6, 1, 10, 5, +11, 6, 2, 2, 1, -2, -4, -3, +-5, -6, 2, -8, 4, -5, 5, 0, +-2, 7, -8, 9, -4, 4, -2, 0, +2, 1, -1, -3, -10, -4, -8, -5, +-9, -6, -2, -3, 5, 6, 0, 8, +-1, 4, -7, 0, -8, -6, -3, -9, +0, -8, 9, -6, 4, -3, -3, 4, +-2, 6, -5, 6, 3, 7, 6, 2, +3, -5, -1, -4, -9, -3, -4, -2, +3, 4, 7, 7, 12, 4, 7, 3, +2, 3, 1, -3, 2, -7, 10, -9, +11, -13, 8, -6, 2, 6, -8, 11, +-5, 14, -4, 13, -1, 3, 2, -4, +-3, -4, -7, -5, -6, -7, -1, -2, +6, 2, 1, 6, -3, 11, -9, 6, +-11, -4, -1, -8, -1, -8, 1, -7, +-3, -1, -8, 2, -7, 3, -8, 9, +-1, 9, 4, 2, 1, -1, -1, -5, +-9, -9, -6, -6, 1, 0, 1, 6, +5, 8, 0, 9, -2, 4, -2, 3, +0, 1, 7, -7, 9, -10, 7, -8, +3, -2, -4, 8, -1, 14, 4, 9, +8, 1, 10, -2, 1, -6, -3, -6, +-4, -1, -3, -1, 3, 2, 0, 9, +-2, 10, -4, 8, -6, 6, -2, 1, +-2, -6, -2, -6, -1, -5, -10, -3, +-6, 2, -4, 4, 0, 5, 2, 10, +-7, 8, -7, -2, -10, -6, -9, -7, +-2, -5, -3, 3, -1, 8, -2, 6, +-6, 7, -2, 5, -3, -1, 2, -2, +4, -4, -2, -8, -1, -7, -2, 1, +3, 4, 8, 8, 8, 10, 7, 2, +2, -4, 0, -6, 3, -9, 3, -7, +6, 1, 3, 5, -2, 7, -1, 12, +-4, 10, 1, 2, 5, -2, 3, -7, +1, -8, -5, -4, -4, 0, -1, 4, +-2, 9, 2, 11, -4, 7, -7, 3, +-7, -4, -7, -12, 2, -11, -1, -4, +-1, 1, -2, 6, -8, 9, -3, 5, +-2, 1, 0, 1, 1, -5, -5, -8, +-5, -6, -5, -7, -2, -2, 7, 7, +4, 10, 4, 6, 1, 1, -1, -5, +0, -9, 1, -7, 9, -7, 7, -3, +0, 6, 0, 10, -3, 11, -2, 12, +4, 4, 4, -8, 8, -13, 3, -12, +2, -8, 5, 1, 2, 8, 7, 7, +4, 6, 0, 5, -2, -1, -5, -6, +-1, -7, 1, -9, -1, -5, 0, 4, +-7, 8, -6, 11, -4, 10, -4, 4, +-1, 0, -7, -3, -6, -10, -6, -10, +-4, -4, 4, 0, 2, 7, 0, 12, +-3, 5, -5, -4, -1, -6, -2, -6, +-1, -5, 0, 0, -3, 2, 0, 3, +-1, 9, 1, 10, 6, 5, 4, -1, +4, -8, 1, -13, -1, -11, 5, -2, +5, 3, 7, 9, 6, 11, -1, 6, +1, 4, -3, 1, 0, -5, 4, -8, +-1, -3, -1, 0, -4, 2, 0, 10, +1, 10, 0, 4, 4, 1, -2, -6, +-6, -10, -3, -9, -3, -6, 1, 0, +-2, 10, -2, 10, -1, 6, -8, 7, +-6, 0, -4, -10, 1, -12, 3, -9, +-3, -4, -6, 4, -4, 9, -1, 8, +6, 5, 6, 1, 3, -7, 0, -11, +-2, -13, 4, -9, 2, 2, 1, 10, +1, 11, -2, 9, 0, 5, 2, -2, +5, -6, 7, -5, -2, -6, -1, -4, +-1, 3, -1, 7, 6, 11, 4, 12, +3, 6, -1, -3, -4, -7, -1, -11, +-1, -12, 5, -4, 4, 4, -4, 11, +-5, 13, -5, 9, -1, -1, 3, -8, +2, -12, 2, -12, -6, -5, -8, 1, +-4, 3, -2, 8, 1, 10, 0, 5, +-3, 0, -3, -6, -4, -13, 1, -13, +4, -7, 3, 0, 4, 9, -4, 14, +-2, 8, 1, 2, 1, -1, 4, -7, +-1, -12, 3, -10, 3, -6, 0, 0, +7, 9, 8, 8, 8, 2, 9, -1, +3, -7, 3, -11, 2, -12, 5, -7, +3, 1, -5, 10, -2, 13, -1, 8, +0, 7, 2, 0, 1, -8, 0, -12, +-1, -10, -2, -7, 0, 1, -2, 10, +-1, 11, -1, 9, -3, 2, 1, -8, +-1, -12, -2, -12, -1, -11, -2, -3, +-1, 8, -6, 14, -6, 13, -2, 10, +-3, 0, 2, -8, 3, -9, -1, -11, +-1, -7, -3, -1, 2, 7, 2, 10, +0, 14, 3, 7, 0, -4, 1, -7, +1, -10, 1, -10, 5, -5, 4, 2, +4, 8, 1, 13, -2, 12, 4, 3, +2, -4, 3, -11, 6, -19, 4, -12, +2, -3, 1, 3, 4, 10, 2, 13, +-1, 8, 0, -1, 0, -7, 0, -16, +5, -17, 2, -9, 1, -2, -2, 7, +-5, 14, -4, 12, -5, 4, 1, -3, +0, -8, -2, -13, 0, -11, -2, -5, +-3, 2, 1, 11, 1, 10, 5, 6, +1, 2, -2, -4, 0, -13, -1, -14, +5, -7, 2, -3, 1, 6, 3, 9, +3, 8, 6, 6, 7, -2, 6, -10, +7, -15, 0, -11, -1, -4, -2, 5, +-4, 16, -2, 16, -2, 10, 3, 2, +4, -9, 3, -11, 3, -11, 1, -9, +0, -6, 2, 2, 0, 8, -1, 12, +-3, 14, -2, 2, 0, -7, -4, -11, +-2, -12, -5, -8, -6, 1, -1, 10, +-1, 9, 0, 12, -1, 10, -5, 0, +-6, -3, -6, -8, -2, -11, 0, -7, +-3, 1, 1, 8, -2, 12, -1, 13, +4, 2, 6, -7, 4, -10, -2, -13, +-1, -9, 2, -2, 2, 6, 4, 11, +2, 14, -1, 9, 0, 3, -2, -2, +1, -12, 3, -16, 4, -9, 2, -3, +-2, 8, 1, 15, 3, 13, 2, 6, +2, -2, 0, -9, -1, -17, 0, -11, +-1, -4, -1, 5, -6, 12, -5, 14, +-2, 11, -4, 2, 1, -5, 3, -16, +4, -18, 0, -10, -3, -4, -1, 6, +-1, 12, 1, 11, 3, 8, -2, 0, +-2, -9, 0, -16, 1, -14, 3, -9, +2, -1, 2, 12, -2, 13, -2, 14, +2, 9, 2, -2, 4, -12, 5, -13, +0, -11, 0, -9, 2, 4, 2, 13, +3, 13, 0, 12, 3, 4, -1, -6, +-2, -10, 1, -10, 1, -10, 3, -4, +2, 7, 0, 9, 1, 12, 0, 9, +1, 0, -1, -5, -8, -11, -4, -11, +-5, -8, -2, 4, -1, 10, -1, 14, +-1, 15, -7, 7, -5, 1, -5, -6, +-7, -10, -3, -10, -3, -3, -4, 5, +-2, 10, 0, 14, 3, 8, 2, -1, +3, -5, 1, -12, -4, -12, 0, -8, +3, -1, 2, 9, 0, 15, 0, 17, +1, 5, 2, -2, 2, -11, 5, -16, +1, -13, 2, -8, 5, 0, 1, 8, +3, 15, 3, 11, 4, 4, 2, -4, +-1, -12, 0, -14, -2, -10, -1, -5, +3, 4, 1, 10, 2, 11, 0, 9, +-1, 2, 0, -10, 1, -19, 5, -14, +-2, -9, -5, 3, -2, 11, -2, 14, +-1, 12, -1, 7, -1, -2, -1, -14, +-1, -14, -1, -11, -2, -5, -5, 7, +1, 14, 0, 16, -1, 15, 0, 6, +-2, -4, 0, -14, 0, -14, 3, -13, +5, -6, 3, 6, 3, 12, -1, 19, +-5, 14, 0, 4, 1, -8, 2, -14, +0, -15, 1, -10, 4, 1, 1, 9, +4, 15, 3, 14, -2, 3, 0, -6, +1, -14, 3, -19, 5, -17, 4, -8, +3, 3, -3, 9, -2, 17, 1, 12, +0, 1, 1, -5, -2, -13, -5, -15, +-6, -11, -1, 0, 1, 8, -1, 17, +-4, 19, -4, 10, -8, 3, -4, -9, +4, -18, 5, -14, 3, -6, -3, 4, +-4, 13, -4, 18, -1, 14, 6, 6, +2, -2, -2, -14, -2, -16, -1, -14, +5, -8, 10, 3, 10, 12, 5, 14, +-2, 6, 3, 0, 3, -10, 3, -15, +6, -14, 2, -10, -6, 1, -6, 9, +-1, 15, 3, 13, 4, 5, 7, -6, +2, -15, -9, -12, -6, -10, 0, -8, +4, 5, 3, 12, -3, 16, -8, 15, +-11, 9, -5, -4, 2, -13, -1, -11, +-4, -12, -4, -3, -6, 8, -1, 14, +4, 15, 8, 8, 3, -2, -1, -12, +-2, -14, -5, -14, 3, -8, 6, 5, +2, 10, -3, 16, -6, 18, -5, 7, +1, -2, 5, -10, 7, -14, 0, -16, +-2, -5, 0, 6, -1, 13, 4, 20, +4, 12, 0, 4, -8, -5, -9, -13, +0, -18, 6, -12, 5, 0, 4, 8, +-4, 17, -9, 19, -5, 10, 1, -1, +6, -14, 5, -21, 2, -17, -6, -6, +-9, 7, -2, 12, 3, 15, 5, 7, +4, 1, -3, -5, -4, -17, 2, -18, +6, -13, 5, -4, 2, 1, 4, 12, +-2, 16, -4, 11, 1, 4, 2, -6, +-1, -14, -2, -16, 2, -13, 3, -1, +1, 12, 6, 16, 7, 13, 1, 7, +0, -1, -2, -11, -4, -11, -1, -13, +3, -6, 2, 5, -3, 12, 0, 15, +2, 10, 0, 4, 4, -10, 5, -16, +-1, -14, -2, -15, 1, -6, 4, 8, +-1, 15, -1, 17, 0, 11, -4, -1, +-3, -14, 0, -17, 1, -18, 2, -11, +3, 4, 1, 10, -3, 16, -2, 12, +3, 5, 1, -7, 3, -14, 4, -15, +-2, -14, -4, -2, -2, 5, 3, 10, +5, 15, 5, 11, 3, 3, -4, -4, +-8, -10, -2, -14, 4, -11, 7, 0, +5, 7, 1, 14, -2, 16, -5, 7, +3, -1, 6, -13, 3, -16, 0, -15, +-6, -3, -7, 4, 0, 11, 6, 18, +7, 10, 1, 3, -3, -6, -5, -14, +-6, -17, 3, -11, 6, -2, -1, 7, +-6, 17, -8, 16, -5, 6, 4, -2, +11, -14, 8, -18, -3, -14, -7, -9, +-4, 2, -2, 13, 4, 19, 6, 12, +2, 7, -8, -3, -8, -14, -1, -15, +4, -14, 11, -7, 7, 4, -4, 14, +-7, 14, 1, 10, 7, 5, 8, -8, +5, -15, -1, -14, -9, -12, -6, -1, +5, 10, 8, 15, 7, 14, 0, 9, +-6, -3, -5, -18, 6, -18, 13, -17, +7, -4, -5, 8, -8, 14, -10, 15, +-4, 14, 4, 8, 6, -7, 2, -14, +-7, -16, -8, -15, -4, -4, 5, 5, +12, 11, 7, 14, -2, 9, -8, 3, +-11, -4, -5, -9, 4, -16, 7, -11, +1, 3, -10, 9, -7, 19, -3, 19, +2, 10, 6, -2, 3, -8, -8, -12, +-12, -12, -1, -5, 10, 0, 11, 10, +7, 15, 2, 8, -6, 0, -1, -8, +6, -17, 10, -18, 7, -11, -1, 1, +-6, 7, -6, 15, 1, 17, 5, 13, +0, 4, -3, -9, -4, -16, -6, -16, +-2, -6, 3, 1, 7, 10, 1, 16, +-6, 13, -6, 8, -7, -3, 0, -13, +5, -16, 4, -13, 0, -6, -3, 6, +-5, 19, -6, 20, -2, 10, 6, 2, +1, -11, -4, -14, -3, -13, -3, -9, +1, 2, 4, 10, 5, 16, 0, 12, +-2, 8, 0, -3, 4, -15, 4, -16, +6, -13, 1, -5, -4, 7, -3, 14, +-2, 17, -2, 18, -4, 9, 2, -7, +0, -15, -1, -16, 1, -14, 2, -2, +3, 7, 3, 16, -2, 19, -6, 12, +-7, 0, -3, -10, 1, -14, 2, -19, +6, -9, 1, 2, -4, 10, -7, 16, +-1, 13, 4, 3, 4, -7, 4, -13, +0, -19, -4, -16, -2, -3, 2, 7, +2, 13, 4, 15, -1, 11, -7, 5, +-8, -6, 2, -13, 8, -15, 4, -7, +2, 0, -2, 5, -4, 14, 1, 12, +7, 10, 3, 5, -3, -4, -9, -11, +-8, -11, -4, -7, 8, -1, 14, 9, +7, 14, 0, 9, -5, 2, -3, -5, +1, -12, 4, -10, 3, -7, -2, -3, +-9, 4, -6, 16, -5, 15, 2, 10, +8, 1, 2, -11, -8, -12, -13, -10, +-5, -5, 2, 1, 7, 11, 4, 14, +-4, 9, -9, 4, -4, -5, 3, -11, +6, -10, 3, -10, -1, -5, -6, 5, +-8, 10, 5, 11, 13, 8, 7, 7, +-2, -4, -10, -8, -11, -12, -2, -9, +8, 3, 8, 11, 0, 15, -4, 10, +-5, 7, -4, -2, 6, -9, 12, -14, +9, -15, -3, -5, -9, 6, -7, 12, +-1, 16, 7, 12, 8, 3, -3, -5, +-11, -8, -10, -10, -4, -10, 5, -2, +8, 3, 4, 10, -7, 11, -7, 7, +1, -4, 6, -11, 8, -12, 2, -12, +-7, -4, -10, 0, -3, 6, 4, 11, +9, 9, 6, 4, -2, 1, -10, -7, +-6, -16, 7, -17, 13, -6, 8, 2, +2, 10, -2, 14, -4, 5, 4, -2, +11, -8, 8, -10, 1, -13, 0, -8, +-3, -1, -3, 7, 2, 15, 8, 9, +7, 3, 1, -3, 0, -9, -3, -14, +1, -12, 7, -7, 4, 3, -5, 13, +-8, 16, -6, 10, -4, 6, -1, -3, +3, -12, 2, -12, -4, -9, -4, -1, +-4, 6, -3, 12, 1, 10, 2, 9, +-2, 2, -4, -7, -4, -10, -3, -11, +-2, -7, 2, 0, 5, 8, -1, 12, +-4, 14, -5, 8, -1, -3, 2, -10, +6, -12, 7, -14, 1, -5, -2, 6, +-2, 10, -1, 13, 4, 9, 7, 0, +4, -9, -1, -9, -3, -12, 4, -10, +5, -1, 5, 5, 5, 8, 1, 8, +-3, 4, 0, -4, 6, -10, 6, -13, +6, -14, 1, -5, -8, 5, -9, 9, +0, 13, 3, 10, 2, 5, -3, 0, +-10, -5, -11, -9, -7, -6, 1, 4, +1, 5, 0, 9, -2, 8, -6, 6, +-8, 3, 0, -2, 4, -7, 1, -8, +-5, -3, -7, -1, -4, 5, 0, 12, +9, 9, 9, 2, 3, -3, -3, -11, +-3, -13, 2, -9, 8, -3, 10, 2, +4, 9, -3, 8, -4, 5, 0, 6, +1, -2, 7, -7, 6, -12, -1, -10, +-4, -6, -1, 5, 3, 12, 5, 9, +5, 7, -3, 1, -10, -8, -7, -11, +2, -7, 4, -4, 3, 3, -3, 9, +-8, 10, -10, 5, -2, 5, 4, -1, +2, -8, 1, -10, -4, -10, -9, -1, +-7, 6, 3, 11, 5, 10, 1, 9, +-5, 1, -6, -6, -5, -9, 4, -11, +11, -8, 7, 1, 0, 6, -6, 8, +-6, 12, -1, 6, 8, -3, 10, -6, +0, -4, -8, -9, -4, -3, 2, 4, +4, 10, 5, 12, 3, 6, -1, -1, +-5, -6, -1, -6, 5, -11, 7, -7, +4, 0, -2, 4, -9, 8, -5, 10, +2, 6, 2, 1, 1, -3, -3, -8, +-7, -9, -8, -4, 0, -1, 7, 2, +5, 9, -2, 8, -5, 3, -7, -3, +-3, -7, 2, -10, 5, -8, 3, -1, +-3, 4, -5, 10, -4, 7, 2, 3, +7, -1, 8, -9, 5, -12, 0, -8, +-2, -4, 0, -1, 5, 4, 7, 10, +2, 7, -1, 4, -1, 1, -2, -6, +0, -5, 2, -4, 4, -2, 2, 0, +0, 8, -3, 11, -5, 9, -1, 6, +1, -3, 0, -6, -3, -5, -5, -3, +-4, 0, -2, 5, 0, 6, 3, 6, +-1, 6, -4, 0, -4, -7, -2, -8, +1, -9, 1, -5, 1, 4, -2, 4, +-3, 8, -6, 9, -5, 5, 0, -6, +5, -6, 2, -4, -5, -7, -4, -3, +1, 2, 3, 7, 1, 11, 0, 11, +-3, 2, -4, -4, -2, -7, 5, -10, +8, -8, 9, -2, 7, 0, 1, 3, +0, 4, 4, 2, 6, 0, 4, -7, +7, -13, 6, -14, 0, -1, -4, 4, +2, 6, 3, 9, -1, 7, -3, 2, +-4, -3, -3, -7, 2, -10, 6, -4, +2, -1, -3, 3, -7, 9, -6, 8, +-2, 1, 3, -1, 5, -6, -1, -8, +-5, -6, -5, -2, -4, 1, 1, 4, +5, 8, 0, 6, -7, 6, -11, 2, +-4, -2, 0, -4, 2, -1, 3, -2, +-1, 0, -2, 4, 0, 4, 4, 6, +3, 4, 4, -3, 2, -9, -3, -6, +-2, -5, 5, -1, 8, 7, 3, 10, +-2, 5, -4, 3, -5, 0, 0, -6, +7, -5, 6, -5, 0, 1, -8, 5, +-9, 8, -4, 5, 2, 5, 7, 2, +4, -7, -5, -5, -8, -2, -7, -2, +-3, 2, 2, 7, -1, 7, -7, 8, +-10, 6, -7, -2, 0, -8, 7, -9, +9, -10, 3, -4, -7, 3, -6, 2, +2, 3, 4, 3, 8, -1, 6, -8, +3, -7, -1, -9, 2, -8, 5, -1, +6, 2, 5, 3, 3, 5, -2, 3, +-2, -3, 6, -4, 7, -5, 6, -6, +2, -3, -2, 2, -2, 1, 0, 6, +4, 6, 3, 1, 1, -1, 0, -4, +-2, -5, -5, -2, -2, 4, 2, 0, +1, 2, -2, 4, -2, 3, -3, 2, +-2, 1, -2, -4, -1, -7, -1, -4, +-2, -3, 1, 1, -2, 5, -2, 5, +2, -2, 1, -2, 0, -6, 1, -7, +2, -5, -1, 0, -2, 0, 1, 0, +3, 4, 2, 0, 4, -1, 5, -6, +3, -6, 2, -4, 2, -2, 1, -3, +3, -1, 6, 4, 3, 5, -2, 4, +0, 0, 5, -5, 1, -3, -1, 2, +-4, 1, -3, 4, -2, 5, 0, 6, +-2, 5, -3, 6, -1, 0, 0, -4, +-1, -2, -3, -6, 1, -2, 1, 1, +0, 2, 2, 0, 0, 3, -3, 2, +-2, 0, -5, 0, -4, -3, 0, -5, +2, -2, 1, 0, -1, 3, -1, 5, +-1, 4, -3, 1, -4, -3, 1, -3, +-1, -4, 0, -1, 0, 0, 0, -2, +6, 0, 6, 2, 4, 3, -1, -1, +-2, -2, 3, -6, 2, -4, 1, 3, +3, 3, 2, 1, 3, 3, 0, 2, +-1, -1, 4, -4, 7, -5, 5, -6, +1, -5, 1, -2, 0, 1, 0, 10, +-2, 5, 2, -2, 2, -3, -1, -4, +-2, -4, -4, -1, -1, 2, 1, 0, +-1, 6, -6, 7, -8, 4, -6, 2, +0, 1, 0, -2, -4, 0, -4, 1, +-4, 0, -3, 0, 0, 1, 4, -1, +7, -2, 2, 2, -5, 0, -7, 0, +-5, -2, 6, -3, 7, -3, 4, 1, +4, 1, 1, 0, 0, 2, 2, -1, +3, -3, 4, -3, 5, -6, 0, -4, +-1, 5, -1, 5, 3, 1, 8, -1, +3, -3, 1, -5, 2, -4, 3, -4, +4, -4, 1, 1, 0, 2, -1, 4, +-6, 5, -5, 9, -6, 3, -5, 2, +-5, 2, -7, -1, -5, 1, 0, 1, +3, 2, -3, 3, -4, 4, -4, 1, +0, -2, -1, -1, -2, -2, -2, -1, +-3, 2, 0, 1, 0, 1, -1, 3, +3, 0, 4, -2, 1, -2, -3, 1, +-4, -3, 4, -1, 5, -1, 2, 3, +-1, 7, -2, 4, 0, -2, 3, -5, +5, -5, 7, -6, 7, -3, 1, -1, +1, 0, -4, 5, -1, 8, 2, 4, +-3, 3, -3, 1, -3, -4, -1, -5, +1, -1, 1, 1, 1, 0, 3, 1, +1, -4, -1, 0, -5, 4, -3, 3, +-1, 0, -3, -2, -2, -4, 1, -2, +-1, 3, 0, 2, 2, -1, 0, -2, +3, -2, -4, -1, -6, 4, -5, 2, +-1, 1, 2, 1, 1, 1, 1, -1, +1, 2, 0, 4, -1, -5, 2, -4, +2, -2, 1, 2, 0, 2, -2, 3, +2, 2, 1, 2, 1, 2, 5, -3, +0, -3, 0, 1, 2, 0, -2, 2, +-2, 5, -1, 0, 4, 0, 2, 1, +-1, -1, 0, -5, 1, 1, -3, 2, +-5, 2, -5, 4, -2, 0, 4, 1, +0, 0, 0, -2, 1, -5, 0, -2, +2, -2, 0, -3, -4, 1, -1, 2, +-2, -1, 0, 1, 2, 1, 0, -2, +4, -3, 1, -4, 0, -5, 1, -5, +5, 2, 3, 3, -1, 4, -5, 4, +-2, 1, 2, -1, 0, -1, 3, -2, +0, -4, 2, 0, 3, -1, 1, 0, +2, 3, 3, 1, 4, -4, 5, -3, +-1, 0, -4, 1, 0, -1, 3, -4, +4, -4, 1, 2, 0, 3, 2, -1, +0, 0, -3, -2, 1, -1, -4, 4, +-4, 5, -5, 2, -6, 0, 4, 0, +2, -4, 0, 1, -4, 2, -1, -4, +3, -5, -1, 1, -5, 1, -1, 1, +1, 5, -2, 4, -4, 2, -3, 1, +2, -2, 1, -2, -4, 2, -1, -3, +2, -1, 2, 4, 0, 7, -6, 2, +-1, 1, 2, -2, 3, -5, 5, -3, +3, -4, 5, -3, 2, 1, -1, 2, +-1, -2, 5, 2, 2, 4, -2, 1, +-5, 0, -6, 1, 2, -2, 1, 1, +2, 2, 2, -2, -1, 0, 1, 3, +-3, 2, -5, -2, 1, -2, 2, -5, +1, -1, -7, 7, -9, 8, -5, 6, +-2, 2, 0, -1, -1, -4, 0, 0, +1, -2, 2, -2, -3, 0, 1, 1, +0, 3, -2, 5, 0, 1, -4, -1, +0, 1, 1, -1, -1, -3, 3, -3, +2, 1, 4, -2, 3, 1, 0, 2, +1, 0, 2, -2, 6, -6, 5, -8, +2, -4, 1, 3, 2, 1, -1, 4, +-5, 4, 1, 0, 1, -3, 6, -2, +2, -4, -1, -4, 2, 0, -1, 2, +-1, 1, -1, 1, 2, -1, 3, -4, +-1, 1, -5, -1, -3, 1, 1, 0, +2, -3, 1, -3, -4, 3, -4, 7, +-1, 4, -2, 3, 0, -1, -3, -2, +-3, 0, 0, 2, -5, -1, 3, 1, +2, 2, 0, 1, 0, 1, -4, 3, +0, -2, 4, -3, 3, -1, 0, -3, +2, 0, 1, 3, 1, 4, -1, -2, +0, -1, 7, -3, 2, -2, 0, 0, +0, -5, 1, -5, 7, 0, 2, 1, +2, -2, 3, 1, -1, -1, 2, -3, +-3, 0, -4, 2, 0, -3, 4, -3, +4, -3, 0, -2, -1, 3, 1, -1, +6, -5, 0, -4, 0, 2, -3, 0, +-4, 5, -2, 6, -7, 1, 0, 0, +4, 1, -1, 1, -3, 3, -7, 3, +-2, -3, 3, -4, 1, -1, 2, 2, +1, 3, 0, 4, 0, -3, 0, -5, +1, -2, 7, -2, 4, -3, 0, -1, +1, -1, -2, -2, 4, 5, -2, 3, +0, -1, 4, -1, 0, -1, -1, -2, +-3, 0, -1, 1, 4, -2, 5, -1, +1, -1, -1, -1, -1, 0, 0, 0, +0, -3, -3, 1, -2, 4, -1, 3, +-5, 2, -2, 2, -2, -2, 3, -2, +6, 0, 0, -4, 1, -2, -3, -2, +2, -4, 3, -3, 1, 2, 2, 2, +2, 1, -1, 1, -3, -2, -1, -1, +-1, 3, 2, 3, -1, -1, -3, 1, +1, 2, -2, 4, -1, 3, 0, -1, +1, -7, 8, -5, 4, -4, 3, -4, +1, 2, -1, 2, 4, 1, -1, 0, +1, -1, 4, -6, 5, -4, 2, -2, +-1, -3, -3, 1, 1, 4, 3, 1, +-3, -1, 1, -1, -2, -1, -1, 1, +1, 1, -2, -1, 3, -4, 2, 0, +-2, 0, 0, -1, -1, 0, 5, -2, +6, -5, 2, -5, -2, 0, -3, -2, +2, -1, 6, -4, 6, -4, 2, -1, +5, 2, -2, -1, -2, -2, 1, -2, +0, -3, 7, 1, -1, 2, -3, 0, +0, -3, 3, -1, 5, -2, 0, 4, +-2, 3, 1, -1, -1, -2, -4, 2, +-4, 3, -1, 1, 5, 3, 4, -1, +-6, 0, -6, 3, -3, 2, -3, 2, +2, 2, -2, -3, 5, -5, 3, 1, +-6, 6, -5, 5, -5, 3, 3, 0, +1, -2, -7, 4, -6, 3, -3, 1, +0, -1, 2, -1, 3, -4, 3, -1, +4, 2, -2, -2, -4, -1, 1, -1, +3, -1, 5, 1, -1, 4, -4, -2, +3, -2, 0, 0, 2, -1, 1, 0, +0, 2, 2, -1, 0, -5, 1, -2, +3, -4, 8, -2, 6, -2, 4, -4, +0, -7, 2, -1, 1, 1, -5, 2, +-3, 4, -1, -2, 5, -4, 4, 0, +-5, 0, -1, -4, 2, -2, 5, -3, +6, -3, -2, -1, 2, 0, 2, -4, +0, -2, 2, -1, 4, -5, 7, -3, +3, -1, -4, -3, -5, -3, 5, 2, +3, 0, 3, 3, -3, 4, -6, -1, +1, 0, -4, 2, -1, 1, 3, -2, +2, -1, 4, 0, -5, 2, -7, 5, +0, 1, 5, -4, 4, 1, -2, 1, +-3, -1, 1, 1, 2, -1, -1, -2, +1, 0, 4, 2, 1, -1, 0, 3, +-9, 1, -1, -2, 1, 0, 1, 3, +1, 3, -5, 4, -3, 3, -2, -2, +-2, -1, 0, 1, 2, 1, 2, -2, +2, -3, -1, -4, -4, 1, 1, 4, +1, 2, -2, 3, -3, 4, -4, 0, +2, -1, -5, 3, -3, -1, 6, -2, +3, -1, 6, 1, -5, 2, -9, 7, +-4, 2, -1, -2, 3, -1, 3, -1, +3, 0, -1, 0, -3, 2, -5, -2, +3, 1, 8, 1, 2, -2, 0, -3, +-4, -3, 1, -5, 6, -1, 2, 2, +5, -2, -1, 1, -4, 2, -4, 1, +-6, 0, 3, 2, 7, -3, 5, -3, +-4, 2, -6, 2, -3, 0, 4, -1, +4, 0, -3, 1, -1, 3, -4, 1, +0, -2, -2, 0, 0, 1, 5, 0, +0, 4, -3, 4, -6, 2, -5, 2, +0, 2, -2, 2, -1, 2, 1, 1, +2, -4, 1, 0, -4, 0, 0, -4, +8, -3, 6, 3, -4, 1, -3, -1, +-2, 1, 0, 0, 3, 2, -4, 3, +0, 2, -2, 0, -2, 4, -3, 0, +-4, -2, 5, -2, 8, -3, 2, -3, +0, 1, 0, 1, -2, 1, -6, 6, +-7, 4, -3, 2, 4, 2, 2, 0, +-1, -5, -1, -3, -1, -2, 7, 0, +0, 5, -1, 2, 1, -4, -3, 1, +-1, 4, -4, -1, 5, 0, 8, -1, +3, -1, -5, 0, -7, 2, -1, -2, +7, -3, 10, -2, 3, -4, 2, -1, +-2, 3, -5, 3, 1, -3, 2, -2, +10, -5, 7, -2, -3, 2, -3, 1, +-4, -2, 5, -1, 7, -1, 0, -1, +1, 2, -3, 0, -3, 0, -1, -1, +4, 2, 3, 2, 3, 4, -3, 0, +-5, -5, -1, -1, -1, 3, 4, 4, +-2, 3, -3, 1, 2, -4, -2, 1, +-1, 4, -1, 0, 4, -2, 7, 0, +-1, -1, -4, 1, -4, 5, -1, 3, +1, 3, 0, 2, 1, -1, 1, -1, +0, 5, -7, 3, -2, 1, -1, 3, +5, 1, 6, 0, -3, 4, -4, 3, +-4, 0, 1, 3, 2, 4, -3, 2, +2, 0, 2, -2, 0, -5, 3, -2, +6, -1, 8, -1, 7, -3, 2, -4, +-3, -3, 0, 0, 2, 3, 4, -1, +4, 0, 1, -2, 5, -1, -3, 0, +-2, 3, -1, 0, 2, -2, 8, 0, +0, -2, 1, 0, 1, 2, 1, 1, +4, -2, 3, 2, 0, 2, 1, -1, +0, -1, -2, -1, 2, -1, 4, 3, +6, 2, 6, -2, -2, 0, 0, -2, +2, -2, 2, 2, 4, 3, 1, 0, +3, 3, -1, 2, -2, -1, 0, 3, +2, 2, 7, -4, 5, -3, 1, 1, +-3, 0, 4, 1, 3, 0, 3, 0, +4, 0, 3, 1, 6, -1, -4, 1, +-5, 3, -1, 1, 0, 1, 7, 2, +2, 5, -3, 4, -3, 5, -5, 1, +0, -1, 4, 0, 10, -2, 7, -3, +1, 1, -5, 3, -2, 2, 7, 3, +7, 0, 8, -4, 1, -4, 3, -3, +2, -3, 1, 2, 9, 1, 7, -1, +7, 1, 2, 1, -4, -1, 1, -2, +5, 0, 9, -4, 6, 0, 0, 4, +-2, 3, 0, 0, 4, 0, 7, -2, +10, 0, 2, 5, -2, 2, -5, -2, +-3, -2, 10, 0, 7, 1, 7, 5, +1, 1, -2, -1, -1, 2, -3, 2, +3, -1, 9, -1, 9, 0, 3, -2, +1, 0, 1, 2, 5, 1, 11, -3, +8, -4, 6, -5, 2, -3, 2, 3, +2, 4, 0, 3, 8, 1, 9, -3, +7, -4, 6, -2, 1, -5, 9, -5, +8, -5, 11, -5, 10, -4, 7, 2, +6, -1, 5, -4, 6, -3, 7, -4, +10, -3, 7, -3, 6, -4, 5, -3, +3, 2, 7, 4, 5, 1, 8, -3, +10, -5, 4, -3, 2, 2, -3, 3, +1, 2, 7, 2, 8, -2, 11, -3, +4, 0, 2, 4, 2, 0, 4, -1, +4, 1, 5, 0, 6, 2, 3, 3, +2, 3, -1, 3, 7, 2, 10, -1, +6, 0, 2, 1, 0, -2, 5, -4, +8, 2, 8, 3, 8, 4, 5, 4, +3, 0, 2, -2, 1, -1, 7, -1, +12, -5, 12, -3, 6, -1, 4, 1, +2, 5, 6, 5, 4, 1, 5, 1, +6, 2, 1, -1, 4, 0, 3, 0, +9, -2, 14, -1, 8, 4, 4, 2, +2, 0, 5, -1, 5, -4, 6, -2, +7, 2, 7, 4, 7, 4, 2, 5, +3, -1, 5, -1, 8, 0, 11, -2, +7, -7, 11, -5, 9, -4, 8, -2, +9, 3, 9, 0, 14, -1, 11, -3, +9, -4, 3, -2, 3, 2, 7, 1, +10, 1, 10, 1, 8, 2, 6, 2, +3, 3, 4, 0, 8, -6, 12, -4, +14, -1, 4, 4, 0, 5, 2, 5, +4, 3, 11, 4, 8, 2, 6, -1, +5, -2, 4, -4, 9, -3, 9, 0, +13, 4, 12, 3, 7, 3, 0, 4, +1, 3, 4, 0, 12, -2, 15, -4, +9, -4, 8, 0, 7, -1, 11, -2, +14, -1, 13, -1, 12, -5, 9, -4, +6, -1, 4, 1, 9, 1, 15, 1, +12, 0, 9, 0, 9, 2, 8, 2, +6, 0, 8, -3, 13, -5, 10, -1, +12, 2, 7, 0, 9, 1, 11, 1, +10, -1, 11, 0, 4, 3, 6, -1, +9, -4, 7, 3, 6, 5, 5, 5, +10, 3, 13, 0, 9, 0, 4, 1, +7, -1, 12, -3, 10, -1, 11, 1, +9, 2, 10, 2, 13, 2, 8, -1, +10, 1, 7, -1, 11, -2, 11, -1, +6, 2, 9, 2, 9, 0, 12, 2, +12, 1, 10, 3, 10, 2, 7, 0, +6, -3, 9, -2, 15, -1, 16, 1, +14, 4, 10, 4, 6, 3, 8, 2, +9, -1, 12, -2, 11, 1, 9, 1, +10, 1, 7, 2, 9, 5, 11, 1, +15, -2, 15, -5, 13, -7, 12, -6, +13, -6, 16, -3, 13, -1, 15, 4, +10, 7, 8, 7, 7, 1, 9, -4, +14, -2, 10, 3, 10, 6, 8, 6, +5, 4, 14, -3, 16, -4, 17, -3, +17, -2, 13, -1, 12, -1, 8, -5, +10, 1, 8, 6, 11, 4, 16, 2, +15, 0, 13, 0, 7, -1, 11, 3, +8, 1, 13, 1, 15, 3, 9, 5, +12, 2, 11, 3, 13, 2, 15, -2, +16, -2, 15, -2, 8, -1, 10, 0, +12, -1, 14, -3, 18, -1, 15, 1, +16, 0, 12, -2, 11, -3, 10, -3, +12, -1, 16, 2, 15, 2, 15, 4, +11, 4, 12, 1, 13, -1, 17, -2, +18, -5, 18, -3, 15, 3, 7, 4, +7, 3, 14, 2, 22, -1, 17, -2, +15, 0, 13, -4, 12, -4, 15, -3, +15, -2, 18, -1, 18, 6, 11, 9, +8, 7, 5, 5, 11, 0, 17, -2, +17, -3, 19, 1, 13, 3, 13, 5, +11, 4, 14, 1, 18, -1, 20, -1, +19, -3, 11, -4, 12, -2, 11, -1, +14, 2, 17, 5, 12, 4, 14, 1, +12, 2, 13, 0, 12, -1, 13, -1, +21, -2, 16, 0, 15, 3, 17, 3, +16, 2, 18, 4, 15, 1, 16, -1, +13, 1, 16, 1, 15, -1, 12, 2, +13, 5, 11, 6, 14, 2, 19, -2, +20, -3, 15, -3, 13, -2, 17, -6, +19, -3, 21, -1, 25, -1, 21, -1, +19, 0, 18, 1, 15, 1, 18, 2, +19, -1, 17, 1, 13, 4, 13, 4, +15, 2, 17, 1, 20, -1, 22, -3, +17, -5, 19, -6, 17, -6, 16, -5, +23, -3, 21, 0, 19, 6, 14, 4, +16, 0, 17, -3, 17, -2, 21, -2, +17, 4, 15, 8, 13, 7, 13, 7, +14, 6, 14, 7, 17, 5, 16, 1, +19, -5, 20, -5, 14, -2, 19, -1, +18, 0, 21, 2, 22, 0, 20, -2, +21, -2, 15, -4, 19, -3, 21, -6, +26, -4, 26, 1, 18, 7, 17, 6, +15, 4, 18, 3, 19, 0, 22, -1, +24, -3, 18, -4, 19, -4, 19, -1, +20, 1, 24, 1, 20, 1, 20, -4, +20, -10, 21, -6, 19, -3, 18, -2, +25, -1, 22, 2, 17, 4, 16, 4, +18, 3, 21, 0, 24, 2, 17, 1, +17, -1, 21, 1, 21, 4, 20, 4, +20, 3, 23, 3, 18, -2, 19, -2, +19, -1, 19, -4, 24, -8, 25, -5, +21, -1, 18, 1, 24, 2, 25, 2, +18, -1, 21, -3, 20, -1, 17, 1, +22, 2, 23, 0, 28, 2, 23, 4, +21, 5, 15, 4, 15, 4, 23, 2, +19, -2, 19, 0, 16, 2, 16, 0, +23, -2, 23, 1, 22, 2, 18, 1, +19, -1, 15, -1, 12, -2, 25, -3, +27, -1, 26, 4, 20, 9, 15, 5, +21, 2, 23, 0, 28, -1, 24, -3, +27, -2, 25, 0, 18, -2, 25, -2, +28, -1, 26, 0, 23, -2, 22, -6, +22, -6, 20, -2, 21, 1, 20, 2, +17, 1, 26, 1, 25, 1, 21, 3, +22, 3, 22, 0, 24, -3, 24, -4, +26, 0, 24, 4, 23, 8, 22, 6, +19, 3, 22, 0, 28, -6, 27, -8, +28, -8, 27, -8, 25, -5, 23, -3, +23, -3, 29, -3, 24, -2, 29, -3, +25, -6, 22, -3, 26, -1, 21, 2, +23, 5, 22, 7, 23, 8, 25, 4, +24, 2, 27, -1, 24, -3, 28, -6, +32, -5, 26, -3, 28, -1, 23, 2, +21, 1, 22, -3, 29, -4, 30, -3, +21, -4, 25, -5, 19, -2, 21, 0, +28, 1, 26, 7, 24, 7, 23, 2, +29, -1, 24, 1, 20, 1, 31, -1, +30, 1, 25, 5, 21, 7, 18, 4, +24, 2, 25, 1, 26, -3, 24, -6, +26, -6, 23, -2, 17, -1, 23, -1, +27, 2, 27, 2, 26, -1, 26, -1, +24, 0, 26, 1, 27, 0, 26, 3, +23, 5, 27, 6, 26, 5, 24, 6, +28, 5, 26, 0, 27, -1, 23, -4, +23, -3, 28, -4, 30, -3, 31, -2, +24, -4, 27, -5, 32, -4, 26, -4, +31, -5, 30, -4, 25, -2, 24, 2, +20, 5, 28, 5, 32, 2, 39, 3, +26, 3, 17, 0, 26, -2, 27, 0, +29, 4, 26, 3, 27, 2, 21, 1, +19, 2, 24, 0, 24, -3, 33, -7, +33, -9, 21, -6, 22, -3, 24, 0, +30, 3, 32, 4, 28, 5, 26, 4, +21, 2, 28, 2, 24, 2, 28, 3, +34, 3, 29, 4, 25, 4, 25, 3, +31, -1, 31, -3, 29, -2, 27, -4, +24, -5, 26, -2, 27, -3, 25, -3, +31, 0, 29, 1, 26, 0, 26, -4, +31, -5, 34, -4, 28, 0, 29, 3, +27, 5, 26, 10, 30, 9, 25, 9, +23, 6, 26, 3, 25, -3, 27, -6, +30, -6, 35, -5, 32, -3, 28, -3, +30, -4, 25, -6, 33, -7, 33, -6, +27, -4, 26, -2, 26, -1, 26, 4, +23, 8, 28, 10, 30, 10, 26, 6, +31, 1, 28, -2, 29, -1, 33, 0, +31, 0, 33, 3, 29, 4, 31, 1, +27, -2, 25, -5, 32, -6, 28, -6, +31, -4, 27, -2, 24, 0, 25, 0, +28, 1, 31, 3, 29, 3, 36, 3, +31, 3, 20, 2, 25, 1, 28, 2, +33, 6, 37, 7, 33, 3, 31, 2, +25, 0, 28, -3, 26, -5, 33, -6, +37, -3, 24, 0, 20, 1, 22, -1, +29, -2, 36, -3, 34, -2, 27, -1, +24, -2, 27, -2, 30, 1, 28, 3, +38, 4, 38, 6, 30, 6, 30, 3, +30, 2, 32, 2, 30, -1, 31, -2, +28, 0, 28, 3, 31, 4, 26, 1, +28, -3, 32, -7, 30, -9, 32, -10, +32, -8, 36, -5, 33, 0, 26, 6, +25, 9, 21, 8, 34, 9, 33, 9, +24, 7, 25, 3, 24, 4, 26, 5, +27, 5, 36, 6, 36, 4, 31, 2, +27, -1, 17, -2, 23, -4, 35, -5, +35, -6, 31, -5, 23, 0, 23, 3, +23, 3, 31, 2, 40, 0, 34, -2, +35, -1, 22, 2, 19, 6, 30, 10, +35, 12, 37, 8, 31, 5, 29, 5, +25, 4, 24, 0, 33, -3, 34, -6, +34, -5, 34, -2, 24, -2, 29, -3, +37, -7, 40, -9, 35, -8, 30, -7, +34, -5, 31, -2, 32, 1, 32, 5, +30, 8, 32, 11, 32, 9, 30, 3, +31, 1, 33, -1, 31, 0, 25, 1, +33, 1, 36, 2, 32, 1, 32, 0, +23, -4, 28, -7, 33, -11, 37, -10, +33, -7, 28, 0, 31, 3, 22, 3, +28, 4, 38, 1, 38, 0, 40, 1, +29, 4, 24, 4, 27, 4, 33, 4, +37, 6, 33, 9, 35, 8, 29, 1, +27, -7, 34, -11, 35, -11, 39, -7, +34, -6, 33, -5, 30, -4, 31, -3, +36, -3, 30, -2, 35, -2, 39, -2, +30, -2, 29, 2, 25, 7, 29, 9, +35, 8, 40, 4, 41, 3, 32, 2, +32, 0, 26, -4, 26, -3, 37, -3, +38, -2, 33, 0, 26, -2, 27, -4, +29, -6, 34, -7, 37, -7, 31, -3, +29, -3, 30, -1, 23, 5, 29, 7, +38, 9, 39, 9, 32, 7, 25, 3, +30, 2, 29, 2, 37, 3, 36, 3, +30, 5, 34, 5, 28, 3, 28, -3, +36, -8, 40, -14, 40, -16, 33, -13, +32, -8, 32, 0, 33, 3, 36, 4, +25, 2, 30, 2, 32, 3, 31, 4, +31, 4, 30, 6, 32, 7, 23, 10, +27, 12, 32, 7, 37, 3, 44, -3, +30, -5, 23, -7, 27, -7, 33, -5, +38, -3, 32, -3, 35, -1, 27, -2, +24, -4, 34, -5, 33, -6, 44, -5, +39, -2, 25, 3, 22, 7, 30, 9, +39, 10, 37, 9, 37, 6, 32, 1, +28, -5, 33, -7, 36, -4, 38, 1, +39, 2, 33, 0, 27, -3, 26, -5, +37, -7, 37, -9, 34, -10, 36, -9, +28, -4, 30, 0, 32, 4, 33, 7, +36, 7, 34, 8, 28, 6, 24, 2, +31, 2, 38, 4, 31, 5, 32, 5, +30, 6, 29, 6, 34, 2, 32, -2, +31, -6, 29, -10, 34, -11, 30, -10, +30, -6, 40, -3, 34, -1, 30, 0, +29, -1, 30, -1, 34, 0, 34, -1, +36, -1, 33, 3, 31, 10, 32, 15, +22, 14, 34, 8, 38, 4, 31, 3, +28, 1, 23, -2, 31, -4, 32, -4, +34, -1, 30, -1, 32, -3, 38, -5, +30, -5, 27, -8, 34, -9, 38, -9, +39, -7, 37, -1, 37, 5, 31, 9, +30, 9, 34, 7, 29, 6, 36, 5, +32, 2, 26, -1, 28, -1, 31, 2, +35, 3, 33, 1, 35, -2, 32, -4, +25, -5, 27, -9, 29, -12, 35, -10, +42, -2, 31, 4, 23, 6, 23, 6, +30, 6, 34, 2, 35, 0, 38, 1, +31, 1, 33, 3, 32, 6, 30, 8, +37, 8, 37, 8, 29, 7, 20, -1, +28, -8, 37, -11, 33, -9, 36, -8, +33, -7, 31, -3, 39, -4, 33, -6, +35, -3, 30, -2, 31, -2, 29, -2, +28, 1, 39, 6, 35, 11, 29, 16, +22, 15, 21, 9, 35, 2, 40, -3, +35, -3, 27, -3, 27, -5, 30, -4, +27, -1, 36, 0, 38, -3, 35, -7, +30, -8, 18, -6, 25, -2, 33, -1, +39, 2, 30, 6, 24, 6, 30, 6, +27, 5, 33, 3, 41, 3, 37, 2, +33, 3, 25, 4, 22, 6, 31, 7, +37, 5, 39, 1, 29, -3, 28, -6, +28, -9, 26, -9, 31, -8, 34, -6, +36, -1, 30, 4, 25, 6, 24, 3, +31, 0, 37, 0, 29, 0, 29, -1, +36, 1, 32, 7, 32, 8, 31, 7, +34, 4, 37, 4, 32, 2, 31, -3, +27, -7, 31, -6, 26, -5, 21, -5, +32, -5, 37, -3, 35, -2, 29, -2, +24, -5, 28, -7, 34, -6, 38, 0, +32, 7, 29, 10, 30, 10, 21, 9, +25, 9, 34, 3, 42, -1, 37, 1, +26, 1, 25, 0, 25, -1, 35, 2, +34, 3, 30, 1, 35, -6, 30, -10, +24, -10, 27, -9, 32, -4, 34, 0, +29, 2, 28, 6, 25, 6, 27, 3, +34, 3, 27, 2, 31, 0, 37, 1, +32, 5, 24, 7, 26, 8, 32, 7, +30, 5, 32, 3, 30, -2, 28, -8, +29, -10, 24, -9, 20, -6, 28, -1, +33, -1, 35, -3, 30, -5, 31, -4, +29, -2, 29, -2, 37, 0, 32, 3, +33, 7, 28, 12, 17, 15, 21, 13, +32, 8, 39, 1, 35, -6, 30, -9, +29, -7, 25, -6, 30, -5, 32, -4, +35, -6, 39, -6, 32, -5, 26, -5, +25, -7, 38, -7, 35, -4, 26, 0, +29, 1, 29, 2, 33, 5, 30, 7, +25, 6, 27, 4, 29, 4, 29, 3, +25, 3, 29, 3, 34, 4, 26, 3, +26, 0, 28, -4, 32, -8, 34, -8, +24, -8, 19, -7, 22, -4, 30, 1, +28, 5, 26, 5, 28, 3, 25, 1, +22, 1, 24, 1, 34, 0, 41, 0, +38, 6, 25, 11, 17, 13, 24, 10, +38, 5, 34, 1, 31, -6, 27, -13, +22, -14, 22, -10, 25, -7, 34, -3, +35, -1, 30, 1, 22, 1, 21, 0, +33, -3, 38, -6, 34, -5, 33, -3, +26, 3, 21, 10, 21, 13, 23, 12, +28, 8, 29, 2, 28, 0, 21, -2, +30, -5, 35, -5, 30, -1, 24, -2, +24, -4, 29, -6, 27, -8, 30, -10, +32, -8, 25, -2, 26, 1, 22, 3, +24, 3, 33, 2, 28, 1, 24, 2, +20, 2, 24, 2, 30, 3, 31, 5, +32, 9, 25, 11, 27, 9, 29, 3, +30, -3, 33, -8, 33, -11, 25, -11, +14, -10, 18, -10, 28, -8, 29, -1, +29, 4, 24, 6, 25, 4, 30, 3, +27, -1, 30, -3, 31, -1, 28, 5, +20, 6, 20, 7, 28, 9, 27, 10, +26, 6, 24, 1, 21, -1, 24, -5, +28, -7, 23, -7, 23, -6, 25, -5, +28, -3, 25, -3, 29, -4, 32, -4, +29, -4, 28, -4, 24, -1, 26, 4, +27, 7, 25, 8, 19, 3, 17, 1, +23, 3, 24, 1, 29, 0, 32, 2, +29, 4, 30, 4, 25, 5, 22, 4, +28, -1, 30, -7, 27, -10, 16, -8, +16, -7, 20, -6, 21, -2, 23, 0, +22, 2, 25, 3, 27, 1, 30, 0, +30, 1, 30, 3, 30, 4, 21, 7, +18, 7, 24, 7, 26, 6, 25, 4, +20, 0, 22, -6, 26, -11, 27, -10, +25, -7, 18, -5, 23, -3, 21, -1, +17, 3, 23, 0, 32, -5, 33, -6, +26, -4, 22, -4, 25, -2, 29, 7, +28, 12, 22, 13, 16, 11, 15, 8, +12, 2, 15, -1, 22, -3, 28, -5, +28, -6, 27, -5, 28, -2, 29, 1, +33, 2, 31, 0, 23, -3, 20, -5, +17, -6, 14, -6, 16, -5, 18, -3, +21, 0, 17, 4, 18, 5, 25, 6, +29, 8, 32, 13, 19, 15, 16, 14, +17, 9, 16, 5, 16, -1, 15, -5, +18, -5, 17, -5, 20, -4, 24, -4, +24, -2, 24, 0, 18, 1, 15, 2, +18, 1, 24, -3, 29, -7, 21, -7, +19, -4, 19, 0, 25, 5, 33, 10, +29, 16, 27, 18, 17, 14, 8, 6, +8, -4, 16, -12, 24, -18, 23, -17, +17, -10, 16, 1, 19, 8, 27, 12, +32, 14, 26, 14, 22, 7, 18, -4, +15, -8, 11, -9, 19, -12, 23, -11, +17, -4, 11, 5, 12, 9, 22, 9, +28, 11, 28, 12, 25, 10, 26, 2, +25, -5, 22, -12, 23, -17, 25, -14, +19, -8, 16, -3, 18, 0, 21, 2, +26, 3, 20, 2, 16, 1, 17, -4, +24, -8, 27, -12, 26, -12, 25, -7, +20, 1, 15, 7, 20, 12, 24, 16, +27, 14, 26, 11, 17, 5, 12, -3, +14, -10, 19, -13, 16, -18, 16, -16, +15, -12, 16, -4, 23, 4, 27, 11, +33, 12, 32, 8, 23, 6, 13, 0, +9, -4, 19, -8, 21, -5, 14, 1, +10, 4, 8, 3, 13, 3, 14, 4, +17, 4, 23, 1, 24, -1, 25, -2, +20, -3, 22, -3, 22, -3, 20, -2, +15, -2, 15, 1, 18, 1, 17, -1, +19, -4, 18, -6, 17, -5, 18, -3, +15, 0, 14, 1, 18, 4, 14, 9, +11, 12, 13, 9, 24, 3, 32, -3, +29, -3, 20, -1, 11, 1, 11, 2, +13, -1, 13, -4, 13, -9, 13, -7, +7, -3, 6, 0, 15, 1, 28, 1, +31, 2, 28, 2, 22, 0, 20, -2, +24, 1, 20, 6, 12, 12, 5, 12, +3, 8, 4, 2, 6, -4, 12, -10, +19, -15, 22, -14, 20, -9, 17, -2, +22, 5, 24, 12, 16, 15, 12, 11, +10, 4, 14, -1, 15, -4, 14, -1, +12, 0, 11, 1, 13, 1, 11, 1, +12, 6, 12, 6, 15, 4, 12, 2, +10, 2, 16, 0, 22, -2, 24, -3, +21, -3, 18, -5, 20, -4, 19, 1, +16, 6, 12, 8, 7, 4, 2, -1, +-7, -4, -2, -5, 8, -6, 19, -2, +24, 2, 24, 7, 23, 13, 20, 16, +21, 14, 20, 8, 16, 6, 7, 1, +0, -2, -3, -6, 1, -10, 9, -14, +13, -15, 12, -11, 13, -5, 19, 0, +27, 4, 30, 8, 26, 7, 21, 3, +14, -1, 8, -3, 9, -4, 13, 0, +12, 4, 11, 7, 9, 9, 11, 7, +16, 2, 18, -5, 16, -9, 8, -11, +10, -11, 10, -9, 11, -1, 15, 4, +18, 4, 19, 5, 16, 6, 17, 4, +21, 4, 21, 3, 14, -3, 7, -10, +3, -14, 3, -14, 3, -11, 8, 0, +10, 9, 14, 16, 16, 19, 21, 15, +28, 9, 28, 4, 25, 0, 10, -7, +4, -10, 1, -9, -1, -7, -3, -6, +-4, -7, -1, -6, 6, -6, 15, -5, +22, 0, 27, 5, 29, 6, 29, 5, +20, 6, 12, 9, 8, 8, 6, 9, +-2, 10, -5, 12, -4, 10, 5, 4, +14, -5, 18, -15, 21, -19, 18, -20, +16, -16, 12, -9, 13, 1, 14, 5, +13, 6, 9, 5, 7, 3, 11, 3, +16, 4, 18, 4, 14, 3, 13, 4, +9, 2, 2, 3, -3, 1, -4, -1, +0, -3, 6, -3, 9, 0, 18, 0, +27, 0, 32, 2, 28, 3, 19, 3, +15, 4, 8, 2, 2, 0, -9, -3, +-11, -10, -9, -19, 0, -25, 11, -24, +19, -16, 24, -1, 24, 14, 23, 26, +22, 30, 22, 28, 18, 19, 8, 9, +-2, -4, -4, -10, -2, -13, 4, -10, +7, -7, 7, -8, 6, -7, 7, -8, +10, -3, 13, 1, 17, 5, 13, 3, +9, 0, 6, -6, 9, -10, 14, -9, +20, -5, 21, 3, 13, 14, 5, 22, +-1, 23, 0, 18, 3, 7, 1, -5, +-3, -19, 0, -26, 7, -24, 16, -16, +26, -6, 31, 4, 28, 13, 19, 16, +13, 13, 9, 8, 5, 5, -2, -1, +-10, -9, -16, -19, -7, -26, 4, -27, +11, -18, 14, -5, 15, 9, 20, 25, +20, 33, 21, 33, 20, 24, 15, 13, +6, 0, -1, -10, -3, -15, 0, -13, +4, -10, 2, -7, -3, -6, -3, -7, +3, -7, 11, -8, 15, -6, 15, -3, +14, 2, 8, 5, 9, 5, 12, 2, +18, 2, 18, 4, 9, 9, 0, 15, +-5, 16, 0, 14, 3, 6, 3, -6, +1, -19, 4, -24, 6, -22, 9, -13, +16, -4, 19, 6, 18, 14, 14, 12, +9, 6, 11, 0, 14, -4, 10, -5, +3, -4, -7, -3, -7, -4, -7, -9, +-4, -11, -1, -11, 4, -7, 13, 0, +19, 10, 24, 18, 24, 20, 26, 21, +18, 14, 10, 9, 2, 1, -4, -3, +-8, -8, -13, -12, -16, -15, -11, -19, +1, -23, 13, -23, 17, -14, 17, -3, +18, 8, 17, 17, 16, 23, 12, 19, +10, 11, 3, 2, -3, -3, -6, -3, +-1, -2, 7, 3, 8, 6, 8, 4, +4, -3, 6, -11, 7, -18, 11, -19, +8, -13, 1, -4, 1, -1, 7, 0, +15, 3, 19, 4, 21, 5, 17, 6, +8, 10, -1, 11, -8, 10, -13, 1, +-15, -9, -20, -18, -15, -24, -4, -21, +13, -8, 26, 10, 33, 24, 34, 33, +28, 32, 22, 25, 8, 11, -3, -2, +-15, -14, -24, -22, -27, -27, -20, -28, +-6, -26, 12, -21, 24, -12, 23, -2, +21, 9, 23, 14, 22, 20, 15, 19, +2, 17, -11, 9, -17, 1, -15, -4, +-6, -1, 2, 7, 8, 11, 12, 13, +7, 7, 3, 0, 1, -12, 1, -18, +-5, -21, -10, -18, -7, -11, 3, 0, +14, 9, 22, 13, 25, 15, 22, 12, +17, 6, 8, 3, -1, 2, -8, -4, +-14, -11, -21, -18, -26, -20, -18, -18, +2, -11, 20, 3, 30, 18, 30, 29, +29, 32, 25, 27, 14, 15, 5, 1, +-8, -11, -18, -17, -28, -19, -27, -18, +-14, -18, 4, -18, 19, -17, 18, -13, +16, -5, 14, 3, 12, 13, 10, 19, +6, 23, 0, 22, -6, 18, -8, 9, +-2, -1, 5, -5, 12, -7, 10, -5, +2, -2, -5, -3, -8, -9, -4, -14, +-7, -14, -6, -10, -1, -5, 11, 4, +18, 11, 19, 14, 21, 9, 16, 3, +10, -2, 3, -6, -4, -2, -12, 4, +-21, 8, -23, 4, -19, -1, -9, -10, +7, -18, 21, -21, 26, -12, 23, 4, +17, 19, 13, 29, 7, 30, 2, 23, +-6, 11, -12, 1, -17, -9, -8, -18, +-1, -22, 5, -23, 7, -26, 4, -28, +3, -22, 0, -11, 3, 5, 4, 21, +4, 36, 2, 39, 4, 34, 8, 21, +11, 5, 10, -11, 7, -19, 1, -20, +-6, -14, -14, -3, -19, 3, -19, 5, +-13, 1, -5, -3, 3, -6, 18, -5, +26, -4, 29, 1, 21, 4, 10, 4, +6, 2, -1, 3, -10, 7, -20, 9, +-23, 12, -22, 9, -13, 0, -1, -14, +11, -24, 18, -27, 13, -18, 7, -2, +7, 14, 11, 30, 14, 38, 7, 36, +-3, 24, -8, 6, -7, -14, 2, -27, +3, -33, 4, -31, -1, -27, -7, -20, +-10, -12, -9, -3, 0, 6, 7, 11, +12, 17, 10, 21, 12, 23, 17, 14, +21, 4, 16, -7, 4, -12, -6, -10, +-15, -5, -19, 4, -17, 9, -11, 7, +-3, -3, 0, -12, 4, -20, 12, -21, +19, -16, 20, -4, 11, 10, 3, 22, +-3, 25, -5, 19, -3, 11, -6, 4, +-8, -1, -8, -9, -2, -15, -1, -18, +1, -20, 2, -21, 0, -14, -3, -1, +-4, 16, 6, 31, 13, 39, 14, 37, +13, 23, 12, 3, 12, -17, 11, -29, +3, -34, -8, -27, -21, -18, -27, -7, +-30, 1, -21, 2, -4, 1, 9, -1, +18, 2, 23, 6, 29, 14, 28, 19, +25, 19, 11, 15, -9, 10, -26, 2, +-31, -6, -24, -9, -16, -7, -6, -5, +5, -8, 14, -13, 19, -16, 23, -17, +22, -14, 16, -3, 3, 5, -6, 12, +-13, 17, -14, 15, -10, 6, -2, -5, +5, -9, 8, -7, 11, -2, 8, 1, +6, 3, -4, 1, -12, -3, -18, -6, +-19, -4, -14, 1, -1, 9, 12, 16, +21, 19, 29, 20, 28, 14, 24, 7, +13, -4, -8, -11, -24, -17, -33, -23, +-32, -27, -25, -30, -16, -29, 0, -24, +15, -11, 27, 10, 34, 32, 35, 48, +32, 56, 13, 47, -6, 26, -20, -3, +-24, -27, -23, -41, -22, -42, -15, -32, +-5, -17, 9, 0, 19, 12, 24, 18, +22, 16, 15, 12, 6, 4, -4, -3, +-8, -9, -5, -13, -4, -16, -5, -15, +-6, -11, 0, -3, 8, 13, 8, 25, +5, 30, -4, 23, -6, 11, -12, -7, +-10, -22, -4, -31, 5, -28, 11, -10, +7, 13, 6, 32, 10, 36, 17, 31, +14, 20, -1, 5, -13, -12, -17, -25, +-18, -35, -15, -37, -14, -34, -8, -27, +-2, -14, 5, 3, 12, 25, 18, 42, +21, 55, 13, 54, 5, 41, -2, 17, +0, -10, -2, -32, -5, -40, -13, -35, +-19, -23, -12, -10, -4, 1, 0, 9, +2, 8, 7, 1, 9, -3, 12, -1, +17, 1, 20, 5, 17, 7, 6, 6, +-8, 3, -16, -5, -14, -8, -12, -5, +-15, 2, -16, 6, -11, 9, -5, 8, +9, 6, 17, 2, 24, 2, 19, 5, +7, 11, 0, 11, -4, 7, -2, 2, +-7, -6, -8, -14, -12, -20, -9, -18, +-2, -13, 7, -3, 11, 2, 8, 4, +6, -2, 2, -9, -2, -9, -5, -6, +-6, 5, -1, 16, 3, 27, 5, 30, +12, 30, 11, 25, 8, 15, 0, 1, +-4, -13, -7, -21, -14, -26, -17, -30, +-20, -33, -17, -27, -7, -19, 8, -2, +20, 18, 26, 36, 28, 45, 22, 45, +10, 29, -1, 5, -10, -21, -15, -42, +-22, -46, -26, -36, -24, -15, -11, 7, +6, 27, 16, 36, 21, 35, 22, 27, +21, 15, 15, 2, 9, -10, 3, -19, +-7, -24, -15, -27, -21, -28, -14, -20, +-5, -8, 5, 8, 7, 19, 6, 22, +6, 14, 5, 3, 4, -10, 1, -18, +-1, -15, -4, 0, -7, 20, -8, 33, +-3, 38, 5, 32, 8, 21, 6, 3, +4, -13, 2, -25, 1, -30, -5, -29, +-12, -25, -15, -16, -12, -11, 1, -4, +5, 7, 9, 20, 10, 27, 10, 30, +12, 23, 11, 11, 8, -2, 0, -16, +-9, -22, -18, -15, -24, -2, -18, 11, +-10, 21, -5, 20, -2, 12, 2, 1, +9, -5, 13, -6, 17, -1, 13, 7, +6, 13, -3, 15, -13, 12, -16, 6, +-17, -5, -11, -13, -12, -20, -13, -19, +-9, -18, 1, -12, 12, -6, 16, 3, +16, 15, 10, 27, 5, 37, 2, 40, +-2, 39, -5, 21, -5, -1, -5, -24, +-7, -38, -9, -41, -5, -32, -4, -14, +-5, 6, -5, 20, -2, 26, 2, 23, +3, 12, 4, 2, 0, -7, 2, -9, +3, -7, 1, -1, -3, 3, -5, 7, +-8, 12, -13, 17, -10, 21, -7, 21, +-3, 21, -3, 11, -5, -3, -4, -20, +2, -32, 10, -33, 12, -20, 6, 1, +1, 24, -5, 41, -7, 44, -7, 37, +-9, 18, -8, -7, -9, -32, -7, -43, +-11, -39, -5, -28, 1, -13, 4, 5, +2, 22, -4, 35, -1, 44, 1, 47, +3, 45, 1, 32, -2, 14, -2, -11, +-4, -30, -6, -39, -9, -35, -13, -24, +-15, -6, -19, 11, -16, 22, -8, 27, +-1, 21, 6, 10, 8, -1, 14, -6, +16, -7, 17, -2, 6, 6, -7, 13, +-19, 11, -26, 7, -25, 7, -26, 6, +-17, 9, -6, 10, 2, 9, 9, 2, +20, -3, 24, -10, 18, -11, 7, -8, +-7, 0, -17, 11, -22, 19, -24, 21, +-23, 14, -17, 4, -7, -9, 5, -16, +12, -13, 14, -2, 8, 5, 3, 8, +-11, 10, -22, 12, -26, 12, -23, 12, +-15, 16, -8, 18, 6, 21, 14, 21, +20, 15, 21, 1, 14, -10, -1, -17, +-20, -20, -31, -19, -39, -14, -35, -5, +-23, 1, -13, 8, 0, 11, 16, 13, +30, 15, 38, 20, 30, 23, 14, 23, +-10, 15, -29, 4, -43, -7, -51, -13, +-43, -11, -32, -4, -12, 7, 5, 14, +21, 20, 31, 19, 29, 15, 20, 5, +3, 1, -14, 1, -27, 4, -36, 6, +-38, 4, -30, -2, -17, -11, -3, -10, +9, -10, 17, -4, 18, 6, 13, 17, +-3, 24, -13, 23, -19, 16, -20, 8, +-20, 4, -22, 5, -17, 7, -6, 9, +10, 9, 16, 4, 14, 0, 3, -5, +-8, -5, -17, -3, -22, 3, -23, 7, +-24, 6, -21, 2, -18, -5, -10, -11, +5, -14, 18, -6, 19, 9, 10, 25, +0, 34, -6, 38, -14, 33, -19, 20, +-24, 4, -27, -11, -27, -18, -25, -20, +-17, -15, -6, -11, 10, -5, 13, 3, +13, 14, 7, 26, -1, 36, -4, 37, +-13, 29, -18, 13, -22, -10, -23, -27, +-24, -36, -27, -34, -21, -24, -11, -3, +-2, 21, 2, 44, 0, 52, 3, 47, +1, 36, -2, 20, -8, 6, -13, -3, +-17, -10, -24, -17, -26, -17, -30, -16, +-22, -13, -8, -6, 1, 8, 7, 22, +7, 33, 2, 37, -9, 31, -20, 14, +-25, -8, -24, -26, -23, -33, -23, -24, +-21, -5, -11, 19, 2, 38, 11, 51, +9, 53, -1, 45, -15, 30, -29, 8, +-36, -11, -38, -26, -36, -35, -34, -36, +-27, -28, -15, -10, 6, 15, 21, 44, +23, 67, 13, 72, 0, 58, -14, 30, +-32, -7, -45, -39, -53, -62, -49, -63, +-39, -42, -27, -8, -10, 24, 9, 54, +19, 75, 19, 79, 16, 66, 9, 44, +-9, 18, -31, -13, -48, -37, -58, -55, +-52, -56, -41, -45, -25, -21, -12, 12, +5, 46, 17, 71, 19, 79, 15, 66, +0, 33, -19, -5, -44, -38, -59, -55, +-59, -55, -43, -34, -19, 2, -4, 41, +8, 68, 14, 80, 11, 73, 5, 49, +-8, 18, -29, -15, -50, -43, -62, -62, +-58, -65, -43, -50, -14, -18, 10, 22, +27, 61, 33, 88, 21, 97, 2, 78, +-21, 35, -43, -15, -64, -61, -70, -85, +-64, -81, -47, -50, -23, -5, 3, 44, +21, 82, 29, 101, 22, 98, 3, 72, +-20, 35, -42, -5, -57, -38, -64, -61, +-60, -66, -45, -56, -21, -30, -4, 9, +6, 53, 4, 84, 1, 91, -6, 71, +-15, 33, -25, -12, -36, -53, -40, -76, +-43, -72, -30, -40, -16, 5, -1, 57, +0, 94, -11, 106, -17, 92, -22, 55, +-30, 9, -43, -36, -54, -70, -52, -87, +-39, -76, -19, -43, -4, 5, 6, 53, +12, 89, 4, 110, -8, 109, -24, 78, +-39, 28, -56, -33, -70, -85, -65, -106, +-55, -92, -34, -49, -14, 10, 4, 74, +15, 120, 16, 136, 4, 117, -20, 67, +-40, 4, -57, -52, -69, -85, -67, -94, +-51, -76, -30, -34, -8, 19, 6, 68, +11, 104, 3, 113, -13, 95, -40, 55, +-62, 0, -69, -54, -70, -90, -59, -101, +-35, -82, -5, -25, 14, 46, 26, 111, +20, 148, -2, 147, -30, 105, -58, 38, +-84, -36, -97, -97, -89, -125, -65, -117, +-30, -71, 6, -5, 31, 64, 40, 113, +32, 138, 8, 128, -25, 89, -59, 30, +-87, -33, -102, -84, -96, -110, -73, -100, +-41, -61, -8, 1, 15, 64, 27, 116, +22, 140, 3, 128, -26, 81, -51, 13, +-71, -53, -84, -93, -82, -98, -66, -73, +-38, -22, -10, 35, 11, 85, 17, 110, +2, 106, -24, 76, -52, 33, -72, -14, +-76, -51, -77, -71, -69, -70, -48, -49, +-18, -13, 10, 36, 20, 78, 18, 103, +-3, 104, -30, 85, -60, 49, -82, 3, +-89, -46, -83, -79, -66, -85, -42, -62, +-9, -17, 12, 30, 16, 68, 6, 85, +-12, 87, -36, 69, -56, 38, -75, 2, +-81, -28, -72, -44, -53, -42, -31, -29, +-14, -9, -6, 17, -14, 41, -31, 67, +-51, 80, -62, 74, -68, 50, -69, 17, +-64, -14, -47, -35, -25, -40, -10, -26, +-7, 1, -12, 33, -22, 59, -43, 69, +-66, 59, -84, 31, -85, 3, -75, -19, +-56, -30, -33, -29, -16, -16, -4, 5, +-2, 29, -10, 50, -25, 62, -48, 64, +-77, 53, -95, 38, -98, 18, -81, -1, +-55, -20, -29, -27, -13, -19, -4, 0, +-3, 26, -18, 45, -36, 51, -57, 44, +-77, 31, -91, 10, -90, -10, -75, -21, +-52, -13, -24, 7, 0, 31, 12, 51, +7, 57, -20, 50, -56, 32, -87, 12, +-109, -7, -113, -20, -102, -24, -74, -11, +-45, 11, -11, 32, 17, 46, 28, 54, +21, 61, -11, 59, -55, 47, -101, 22, +-127, -10, -130, -37, -112, -46, -81, -38, +-45, -14, -13, 15, 12, 46, 20, 71, +11, 84, -15, 76, -53, 46, -89, 11, +-113, -17, -113, -26, -97, -23, -70, -10, +-44, 6, -19, 25, -5, 42, -4, 53, +-18, 50, -41, 36, -64, 19, -84, 3, +-95, -7, -92, -17, -72, -23, -53, -17, +-35, 9, -23, 38, -11, 64, -13, 75, +-34, 69, -60, 49, -82, 19, -94, -9, +-99, -34, -94, -41, -81, -28, -58, -1, +-36, 31, -19, 58, -11, 67, -13, 67, +-30, 58, -52, 40, -71, 16, -86, -7, +-95, -21, -100, -28, -85, -18, -64, -4, +-42, 15, -31, 33, -30, 50, -37, 60, +-43, 59, -52, 41, -66, 15, -79, -6, +-88, -14, -84, -6, -69, 7, -46, 27, +-33, 47, -34, 63, -50, 63, -63, 45, +-74, 15, -82, -13, -90, -27, -93, -24, +-78, -9, -60, 11, -40, 32, -28, 45, +-23, 56, -29, 57, -41, 50, -60, 35, +-85, 22, -103, 11, -108, -4, -100, -12, +-81, -12, -59, 1, -44, 18, -35, 35, +-35, 45, -41, 48, -55, 41, -67, 30, +-76, 19, -80, 15, -77, 15, -73, 20, +-68, 28, -62, 29, -56, 25, -59, 12, +-67, -3, -76, -12, -80, -7, -79, 9, +-71, 30, -64, 49, -55, 61, -48, 62, +-50, 51, -53, 29, -61, 3, -67, -14, +-75, -21, -76, -8, -76, 15, -78, 38, +-80, 51, -80, 57, -81, 56, -75, 42, +-68, 19, -67, -6, -66, -23, -61, -28, +-51, -16, -45, 7, -39, 36, -44, 61, +-56, 79, -78, 83, -101, 65, -111, 28, +-111, -14, -101, -43, -86, -50, -65, -29, +-49, 4, -37, 40, -32, 66, -35, 83, +-45, 78, -61, 54, -82, 21, -99, -7, +-110, -15, -106, -9, -92, 5, -79, 20, +-68, 30, -65, 32, -62, 31, -62, 23, +-55, 10, -49, 2, -54, 9, -69, 23, +-81, 40, -82, 51, -83, 53, -85, 49, +-92, 41, -96, 29, -91, 8, -76, -12, +-62, -22, -53, -13, -52, 8, -56, 28, +-61, 43, -69, 51, -83, 51, -100, 39, +-105, 18, -97, -5, -75, -16, -55, -11, +-43, 14, -46, 46, -55, 67, -68, 70, +-85, 56, -104, 31, -119, 1, -121, -23, +-111, -35, -87, -22, -61, 10, -39, 47, +-29, 74, -33, 83, -48, 70, -69, 44, +-93, 13, -115, -10, -125, -22, -119, -20, +-104, -3, -86, 22, -69, 47, -59, 57, +-50, 53, -50, 37, -56, 18, -68, -1, +-80, -11, -91, -7, -97, 8, -87, 33, +-79, 59, -76, 76, -81, 70, -84, 49, +-85, 17, -86, -12, -86, -32, -85, -35, +-80, -21, -75, 12, -76, 52, -77, 81, +-76, 85, -75, 62, -74, 29, -79, -5, +-79, -25, -83, -27, -86, -8, -87, 21, +-85, 56, -84, 80, -87, 79, -90, 53, +-90, 13, -82, -21, -78, -38, -72, -35, +-68, -16, -68, 23, -77, 65, -88, 98, +-98, 108, -101, 89, -97, 47, -92, -4, +-85, -40, -80, -56, -75, -47, -74, -21, +-76, 19, -86, 64, -98, 98, -108, 104, +-107, 82, -98, 42, -83, 1, -68, -26, +-58, -34, -50, -23, -50, 8, -64, 48, +-95, 77, -122, 84, -138, 62, -134, 25, +-117, -14, -93, -40, -65, -47, -43, -29, +-30, 10, -30, 53, -44, 92, -73, 108, +-111, 96, -143, 55, -153, 8, -143, -30, +-115, -47, -84, -42, -58, -16, -42, 21, +-35, 57, -42, 87, -67, 97, -90, 77, +-112, 38, -122, -1, -126, -30, -119, -41, +-104, -33, -84, -9, -62, 27, -48, 64, +-49, 90, -64, 92, -86, 73, -103, 39, +-107, 2, -106, -28, -105, -41, -110, -37, +-107, -14, -100, 19, -85, 54, -70, 79, +-65, 90, -65, 85, -70, 64, -71, 41, +-77, 17, -88, -6, -104, -27, -116, -37, +-122, -30, -120, -12, -113, 13, -102, 40, +-90, 66, -71, 85, -52, 94, -49, 85, +-59, 56, -75, 15, -91, -21, -105, -45, +-111, -47, -116, -29, -119, 6, -116, 47, +-107, 88, -95, 114, -82, 107, -68, 70, +-64, 16, -63, -33, -68, -66, -74, -75, +-85, -57, -93, -10, -99, 50, -101, 108, +-104, 144, -110, 138, -107, 95, -95, 27, +-79, -43, -69, -96, -63, -117, -67, -98, +-80, -37, -98, 49, -113, 132, -118, 178, +-110, 179, -99, 136, -87, 62, -72, -22, +-63, -93, -62, -129, -74, -119, -86, -64, +-110, 19, -134, 105, -150, 159, -144, 170, +-115, 141, -79, 82, -50, 6, -34, -69, +-32, -112, -49, -109, -78, -62, -106, 6, +-127, 79, -146, 132, -148, 155, -127, 138, +-91, 91, -62, 28, -47, -40, -47, -90, +-63, -104, -89, -76, -120, -21, -138, 40, +-135, 91, -108, 128, -78, 141, -53, 123, +-40, 74, -47, 12, -68, -39, -99, -67, +-135, -66, -164, -46, -171, -15, -152, 22, +-105, 63, -50, 92, -5, 101, 11, 87, +-6, 63, -47, 36, -98, 11, -146, -13, +-183, -30, -195, -31, -178, -20, -127, 4, +-66, 28, -12, 49, 12, 59, 2, 63, +-37, 61, -83, 50, -129, 30, -166, 6, +-182, -11, -171, -17, -127, -7, -74, 7, +-29, 26, -13, 46, -20, 64, -47, 76, +-87, 76, -126, 57, -152, 28, -163, 1, +-155, -20, -129, -32, -96, -36, -62, -22, +-43, 8, -36, 51, -43, 92, -54, 113, +-76, 104, -99, 76, -120, 36, -131, -7, +-129, -44, -125, -67, -119, -65, -115, -33, +-102, 19, -85, 70, -63, 106, -45, 118, +-35, 108, -38, 77, -51, 32, -78, -17, +-110, -58, -138, -73, -161, -59, -164, -19, +-148, 28, -113, 74, -77, 107, -42, 121, +-18, 107, -12, 66, -29, 7, -65, -48, +-108, -76, -145, -71, -161, -38, -158, 9, +-134, 60, -101, 105, -66, 132, -45, 129, +-35, 92, -42, 32, -63, -26, -90, -67, +-115, -83, -130, -72, -136, -42, -130, 8, +-113, 65, -86, 117, -61, 146, -49, 141, +-50, 100, -57, 43, -72, -15, -92, -62, +-111, -92, -123, -95, -125, -63, -122, -2, +-110, 67, -97, 117, -77, 138, -60, 127, +-47, 94, -40, 44, -46, -10, -68, -57, +-98, -80, -127, -67, -144, -27, -145, 25, +-137, 71, -123, 103, -98, 116, -63, 111, +-33, 82, -15, 31, -23, -27, -53, -69, +-97, -83, -137, -62, -156, -14, -155, 38, +-130, 91, -102, 131, -71, 144, -42, 116, +-22, 60, -30, -8, -60, -59, -97, -85, +-131, -82, -153, -50, -157, -2, -135, 55, +-92, 105, -45, 136, -14, 131, -6, 94, +-26, 41, -68, -8, -121, -47, -158, -72, +-169, -77, -156, -51, -125, 3, -83, 67, +-34, 119, 1, 136, 9, 121, -22, 79, +-75, 24, -132, -36, -170, -80, -186, -89, +-173, -59, -130, 1, -71, 68, -15, 118, +18, 134, 21, 121, -16, 85, -72, 34, +-134, -26, -178, -71, -196, -91, -186, -74, +-146, -26, -87, 34, -23, 89, 22, 128, +31, 143, 5, 126, -43, 80, -106, 15, +-159, -51, -192, -94, -190, -95, -163, -61, +-116, -5, -64, 58, -21, 109, 8, 134, +13, 124, -9, 85, -52, 27, -101, -27, +-146, -59, -171, -58, -171, -34, -143, 3, +-105, 40, -64, 70, -29, 86, -8, 81, +-6, 57, -25, 23, -56, -7, -95, -20, +-130, -16, -158, -8, -161, 5, -142, 23, +-105, 47, -62, 65, -23, 68, 1, 54, +-1, 29, -25, 6, -65, -6, -105, -6, +-138, -1, -158, 11, -162, 25, -141, 37, +-97, 36, -45, 27, -7, 15, 11, 6, +4, 11, -27, 27, -70, 44, -116, 50, +-146, 45, -158, 30, -148, 11, -123, -7, +-80, -21, -36, -19, -8, 2, -7, 37, +-26, 68, -58, 80, -95, 67, -124, 41, +-143, 14, -136, -7, -112, -21, -79, -21, +-48, -8, -27, 19, -22, 49, -36, 71, +-63, 74, -93, 57, -114, 30, -126, 2, +-121, -23, -104, -42, -74, -39, -50, -13, +-39, 35, -41, 83, -47, 114, -63, 114, +-85, 82, -103, 29, -114, -31, -106, -77, +-89, -92, -70, -62, -58, 0, -54, 75, +-65, 132, -80, 144, -88, 110, -86, 47, +-81, -24, -75, -77, -67, -95, -60, -70, +-55, -6, -60, 71, -71, 131, -83, 147, +-89, 117, -99, 56, -104, -16, -99, -77, +-82, -109, -58, -102, -39, -53, -31, 33, +-42, 122, -60, 178, -80, 180, -92, 130, +-100, 42, -100, -55, -94, -137, -79, -171, +-64, -138, -53, -47, -47, 75, -51, 184, +-63, 240, -81, 217, -95, 127, -102, -1, +-95, -119, -77, -195, -54, -198, -40, -123, +-36, 8, -43, 143, -59, 232, -76, 247, +-95, 185, -106, 69, -110, -62, -101, -162, +-85, -205, -57, -172, -33, -75, -21, 53, +-21, 167, -34, 229, -56, 220, -85, 150, +-111, 44, -126, -69, -117, -150, -96, -174, +-71, -130, -47, -37, -25, 77, -20, 169, +-28, 203, -47, 168, -71, 82, -99, -20, +-120, -105, -121, -145, -101, -126, -61, -48, +-28, 58, -11, 151, -13, 190, -30, 159, +-61, 74, -95, -29, -119, -110, -127, -145, +-115, -119, -91, -42, -58, 61, -24, 149, +1, 190, 3, 165, -11, 87, -45, -13, +-87, -94, -131, -134, -150, -122, -135, -63, +-100, 26, -57, 113, -27, 165, -8, 166, +-2, 112, -9, 29, -34, -57, -66, -115, +-99, -129, -121, -92, -125, -15, -108, 78, +-76, 155, -46, 186, -25, 158, -21, 76, +-27, -23, -43, -108, -62, -143, -81, -121, +-91, -50, -94, 47, -91, 136, -85, 180, +-73, 161, -54, 85, -35, -16, -21, -96, +-22, -128, -32, -101, -54, -29, -75, 59, +-91, 128, -94, 152, -90, 122, -84, 50, +-74, -33, -61, -94, -41, -112, -26, -81, +-17, -13, -21, 65, -30, 128, -49, 154, +-76, 134, -103, 69, -116, -16, -116, -91, +-100, -130, -71, -117, -41, -53, -13, 40, +3, 125, 4, 178, -13, 176, -42, 116, +-81, 14, -111, -93, -126, -163, -118, -166, +-92, -100, -63, 15, -29, 134, -5, 210, +6, 221, -5, 158, -29, 41, -61, -85, +-91, -176, -114, -198, -120, -139, -110, -25, +-86, 98, -51, 187, -15, 217, 11, 183, +13, 95, -6, -16, -43, -112, -81, -161, +-109, -151, -119, -85, -117, 12, -96, 106, +-60, 166, -23, 174, 4, 130, 11, 50, +-1, -41, -28, -113, -62, -136, -94, -101, +-113, -23, -113, 67, -92, 137, -64, 161, +-35, 126, -13, 48, -8, -41, -16, -110, +-29, -130, -41, -88, -58, -4, -73, 87, +-87, 146, -87, 153, -77, 106, -60, 24, +-46, -60, -35, -111, -29, -111, -29, -63, +-29, 16, -39, 92, -54, 138, -72, 136, +-82, 88, -79, 13, -67, -60, -51, -106, +-39, -108, -31, -62, -27, 10, -30, 86, +-41, 137, -56, 145, -71, 107, -78, 37, +-81, -39, -71, -96, -54, -117, -26, -92, +-9, -30, -9, 49, -21, 117, -45, 146, +-69, 128, -89, 66, -92, -15, -79, -86, +-59, -120, -41, -104, -24, -43, -9, 42, +-4, 120, -18, 157, -46, 138, -72, 70, +-89, -21, -90, -98, -76, -134, -54, -114, +-35, -45, -20, 47, -15, 130, -18, 168, +-29, 144, -45, 73, -60, -19, -67, -100, +-66, -139, -64, -124, -58, -60, -47, 29, +-34, 111, -30, 156, -28, 148, -34, 96, +-43, 18, -52, -63, -54, -119, -55, -126, +-56, -83, -54, -6, -55, 80, -54, 148, +-53, 171, -49, 142, -46, 63, -42, -40, +-36, -128, -28, -163, -29, -131, -37, -46, +-49, 59, -60, 148, -68, 188, -75, 165, +-73, 83, -62, -26, -34, -115, -6, -155, +12, -135, 7, -65, -16, 30, -49, 116, +-82, 164, -103, 161, -105, 103, -85, 17, +-56, -63, -26, -109, 0, -120, 20, -91, +17, -27, -7, 49, -41, 110, -73, 134, +-98, 114, -109, 63, -95, -1, -66, -58, +-27, -87, 2, -83, 18, -46, 10, 9, +-16, 62, -52, 93, -77, 94, -91, 70, +-94, 29, -83, -19, -56, -53, -18, -55, +10, -28, 20, 13, 7, 48, -21, 64, +-60, 56, -96, 32, -117, -6, -104, -42, +-64, -54, -18, -34, 18, 7, 29, 51, +15, 85, -19, 91, -51, 65, -82, 20, +-103, -30, -110, -66, -95, -72, -61, -48, +-17, -5, 24, 41, 41, 78, 32, 92, +-3, 83, -50, 54, -96, 11, -116, -34, +-117, -64, -95, -73, -57, -60, -11, -25, +24, 25, 37, 74, 28, 102, 0, 96, +-35, 64, -73, 14, -98, -38, -106, -78, +-93, -85, -63, -62, -23, -16, 8, 33, +21, 66, 18, 78, 4, 71, -22, 52, +-52, 23, -69, -6, -77, -24, -75, -33, +-70, -37, -61, -39, -48, -33, -26, -17, +-6, 11, 8, 50, 11, 84, 0, 100, +-21, 90, -52, 54, -79, -2, -98, -65, +-99, -109, -85, -114, -54, -74, -16, 1, +15, 85, 26, 145, 20, 159, -2, 122, +-37, 43, -63, -51, -79, -125, -81, -150, +-79, -124, -66, -55, -48, 34, -23, 114, +-3, 162, 8, 161, 10, 111, -1, 29, +-24, -57, -62, -122, -92, -151, -102, -133, +-81, -68, -42, 23, 1, 116, 26, 175, +25, 180, 0, 129, -39, 36, -73, -72, +-86, -160, -71, -191, -46, -149, -19, -48, +-7, 71, -6, 165, -17, 198, -33, 163, +-51, 78, -60, -27, -58, -115, -48, -154, +-33, -135, -18, -69, -4, 16, -5, 86, +-18, 123, -39, 121, -52, 89, -59, 36, +-54, -19, -48, -61, -39, -78, -28, -73, +-20, -51, -10, -16, -11, 24, -20, 64, +-39, 87, -51, 81, -50, 48, -39, 3, +-30, -35, -20, -55, -12, -54, -16, -33, +-30, -2, -49, 28, -64, 42, -70, 31, +-61, 6, -35, -11, 4, -7, 32, 16, +40, 43, 20, 59, -19, 52, -68, 19, +-113, -34, -134, -87, -123, -110, -76, -84, +-19, -15, 39, 69, 79, 135, 89, 161, +64, 135, 9, 60, -66, -42, -136, -134, +-174, -181, -166, -163, -117, -89, -45, 10, +36, 106, 101, 176, 132, 200, 113, 163, +47, 78, -48, -32, -134, -135, -188, -201, +-196, -211, -153, -162, -72, -57, 24, 82, +101, 204, 140, 269, 121, 251, 59, 156, +-30, 6, -116, -151, -173, -269, -184, -301, +-147, -225, -76, -69, 5, 108, 67, 243, +99, 296, 98, 255, 64, 141, 1, -14, +-67, -159, -120, -239, -143, -236, -135, -168, +-100, -60, -45, 59, 16, 155, 63, 209, +73, 207, 48, 150, -1, 54, -50, -50, +-91, -138, -104, -192, -89, -192, -51, -131, +-10, -23, 16, 97, 19, 180, -4, 199, +-38, 157, -62, 71, -60, -27, -41, -109, +-12, -143, 10, -123, 16, -66, -2, -6, +-36, 34, -67, 51, -79, 52, -67, 51, +-45, 53, -15, 56, 9, 53, 16, 40, +1, 3, -16, -55, -29, -107, -35, -127, +-41, -100, -48, -33, -58, 50, -64, 122, +-56, 165, -39, 161, -6, 101, 28, 2, +47, -97, 31, -160, -12, -168, -69, -125, +-104, -50, -98, 38, -62, 115, -20, 160, +13, 153, 33, 101, 34, 20, 17, -60, +-19, -120, -48, -145, -68, -131, -71, -75, +-62, 1, -41, 80, -13, 137, 4, 153, +10, 124, 5, 52, -6, -37, -25, -115, +-40, -156, -47, -140, -46, -66, -48, 38, +-44, 129, -40, 170, -35, 144, -28, 54, +-11, -63, 19, -153, 37, -175, 37, -120, +12, -9, -25, 113, -72, 188, -112, 184, +-132, 102, -113, -24, -57, -147, 19, -219, +87, -208, 123, -115, 118, 26, 62, 164, +-29, 248, -128, 248, -188, 164, -196, 23, +-145, -131, -58, -249, 34, -290, 101, -234, +127, -95, 117, 81, 75, 235, 12, 321, +-65, 304, -130, 188, -175, 5, -183, -182, +-149, -310, -72, -334, 27, -253, 114, -98, +163, 84, 160, 240, 105, 323, 8, 311, +-100, 210, -186, 47, -214, -132, -189, -274, +-120, -336, -28, -309, 69, -189, 140, -1, +163, 204, 132, 358, 53, 403, -42, 316, +-126, 119, -171, -126, -175, -339, -139, -439, +-81, -381, -8, -189, 56, 70, 93, 301, +101, 418, 89, 380, 55, 210, -10, -25, +-77, -236, -127, -345, -145, -315, -132, -173, +-87, 10, -26, 162, 36, 229, 74, 204, +83, 112, 72, 1, 46, -82, 5, -111, +-47, -89, -93, -43, -124, -3, -124, 13, +-93, 5, -35, -12, 23, -16, 66, 0, +83, 28, 77, 53, 45, 61, -12, 45, +-63, 3, -91, -45, -96, -71, -92, -64, +-70, -32, -34, 5, 11, 26, 42, 25, +52, 12, 47, -4, 34, -9, 13, 11, +-27, 48, -70, 82, -103, 83, -109, 33, +-87, -56, -38, -147, 17, -194, 64, -161, +86, -55, 75, 88, 32, 216, -36, 276, +-96, 233, -126, 92, -114, -97, -70, -254, +-3, -316, 56, -262, 85, -116, 66, 70, +24, 228, -20, 305, -58, 279, -89, 156, +-100, -19, -78, -180, -40, -271, 6, -273, +42, -189, 62, -46, 61, 109, 43, 224, +9, 259, -33, 201, -74, 77, -102, -67, +-105, -182, -83, -231, -39, -196, 10, -89, +65, 47, 100, 156, 96, 195, 50, 154, +-17, 63, -77, -42, -112, -123, -118, -152, +-95, -121, -46, -45, 6, 36, 44, 89, +59, 100, 65, 76, 57, 31, 36, -15, +1, -54, -36, -78, -72, -79, -103, -57, +-117, -18, -105, 22, -57, 57, 15, 84, +89, 97, 132, 78, 127, 25, 74, -47, +0, -115, -74, -149, -137, -134, -170, -74, +-153, 18, -90, 119, -8, 188, 69, 193, +120, 126, 140, 8, 118, -119, 60, -207, +-22, -223, -99, -159, -153, -35, -170, 102, +-145, 203, -84, 229, 0, 165, 81, 41, +144, -89, 159, -177, 128, -194, 61, -144, +-21, -46, -107, 62, -177, 131, -205, 136, +-175, 86, -89, 15, 26, -46, 145, -77, +227, -76, 236, -46, 147, 0, -11, 42, +-170, 62, -260, 48, -265, 11, -188, -28, +-56, -61, 90, -75, 199, -63, 229, -22, +186, 42, 89, 103, -24, 127, -122, 95, +-181, 23, -199, -62, -171, -135, -104, -169, +-7, -146, 96, -63, 172, 53, 203, 153, +173, 195, 84, 165, -48, 83, -172, -15, +-242, -108, -227, -170, -144, -184, -22, -136, +103, -46, 190, 51, 206, 123, 146, 158, +48, 159, -52, 121, -126, 44, -163, -59, +-152, -151, -106, -193, -37, -181, 31, -121, +83, -25, 115, 87, 127, 185, 116, 226, +70, 185, -13, 80, -119, -47, -194, -157, +-204, -219, -140, -219, -31, -151, 90, -23, +177, 119, 198, 213, 149, 221, 50, 158, +-56, 56, -133, -61, -159, -161, -145, -207, +-91, -171, -20, -76, 50, 28, 97, 97, +115, 123, 98, 124, 51, 104, -8, 54, +-60, -21, -90, -86, -96, -116, -69, -110, +-27, -84, 18, -43, 46, 16, 58, 84, +54, 124, 37, 109, 5, 47, -25, -25, +-30, -79, -18, -104, -7, -92, -11, -46, +-15, 20, -21, 76, -26, 86, -29, 44, +-11, -16, 25, -55, 63, -62, 79, -39, +54, 3, 0, 52, -63, 89, -99, 88, +-94, 34, -46, -47, 12, -116, 56, -143, +70, -121, 51, -55, 17, 37, -7, 136, +-11, 201, -6, 191, -2, 103, -6, -26, +-13, -145, -31, -221, -48, -233, -50, -173, +-20, -50, 28, 93, 69, 204, 83, 247, +66, 220, 30, 141, -22, 26, -70, -101, +-99, -212, -93, -275, -55, -265, 4, -180, +59, -39, 98, 128, 106, 280, 85, 367, +43, 341, -17, 193, -77, -33, -112, -263, +-105, -418, -72, -444, -23, -328, 29, -103, +86, 157, 127, 364, 135, 452, 104, 400, +48, 229, -25, -4, -105, -232, -159, -390, +-166, -436, -113, -356, -26, -181, 70, 43, +149, 256, 193, 404, 181, 438, 114, 335, +8, 120, -108, -132, -186, -339, -197, -435, +-136, -393, -39, -236, 66, -11, 139, 211, +164, 352, 134, 363, 72, 257, 5, 90, +-37, -78, -54, -203, -67, -257, -75, -233, +-75, -149, -57, -38, -32, 59, 10, 119, +67, 144, 126, 141, 155, 110, 137, 58, +68, -6, -31, -61, -126, -98, -184, -117, +-177, -111, -113, -78, -6, -21, 108, 37, +189, 77, 205, 86, 154, 71, 60, 47, +-41, 19, -120, -10, -153, -35, -121, -45, +-42, -43, 37, -43, 73, -53, 70, -60, +40, -39, 11, 7, -3, 57, 10, 90, +43, 101, 73, 88, 73, 43, 31, -25, +-35, -95, -103, -131, -132, -116, -108, -65, +-32, -4, 59, 45, 137, 72, 174, 73, +156, 56, 80, 29, -19, 5, -90, -4, +-121, -3, -107, -13, -67, -46, -9, -83, +43, -101, 77, -87, 85, -38, 77, 38, +61, 118, 41, 169, 15, 158, -8, 79, +-19, -40, -29, -151, -41, -214, -50, -202, +-43, -115, -20, 17, 22, 147, 67, 219, +105, 201, 118, 98, 103, -43, 65, -160, +4, -205, -65, -166, -123, -62, -133, 63, +-95, 152, -22, 169, 55, 103, 120, -13, +154, -118, 139, -160, 83, -125, 13, -35, +-41, 67, -71, 133, -75, 138, -58, 80, +-20, -12, 17, -100, 43, -147, 49, -135, +45, -72, 39, 3, 40, 62, 50, 92, +57, 92, 54, 70, 33, 32, 1, -14, +-37, -55, -65, -80, -75, -87, -50, -77, +-7, -55, 41, -17, 82, 33, 111, 79, +125, 103, 105, 91, 49, 53, -22, -2, +-76, -57, -106, -95, -108, -108, -76, -91, +-9, -46, 62, 10, 120, 57, 150, 85, +141, 90, 98, 71, 29, 29, -42, -28, +-99, -80, -118, -103, -99, -92, -38, -54, +36, -4, 96, 45, 128, 76, 130, 78, +96, 49, 32, 0, -28, -47, -58, -71, +-54, -64, -33, -41, 2, -6, 34, 34, +57, 66, 56, 69, 30, 36, -1, -22, +-15, -81, -11, -114, 2, -111, 32, -72, +72, 6, 105, 111, 104, 192, 67, 202, +-3, 120, -77, -26, -125, -183, -124, -291, +-73, -309, 9, -216, 100, -26, 176, 199, +215, 370, 189, 410, 112, 298, -3, 74, +-119, -180, -207, -384, -232, -467, -175, -394, +-42, -187, 119, 82, 250, 321, 310, 447, +275, 425, 157, 276, -9, 45, -161, -200, +-245, -385, -238, -449, -156, -374, -24, -189, +106, 43, 195, 252, 232, 378, 217, 389, +157, 280, 63, 89, -33, -122, -114, -283, +-157, -348, -164, -315, -121, -205, -30, -53, +79, 103, 167, 224, 205, 276, 192, 251, +133, 163, 45, 46, -54, -77, -120, -192, +-133, -268, -94, -273, -25, -194, 54, -60, +112, 82, 129, 193, 104, 251, 52, 244, +5, 163, -21, 27, -19, -121, 3, -230, +31, -263, 45, -216, 50, -121, 51, -4, +41, 120, 7, 214, -33, 237, -54, 176, +-49, 56, -12, -78, 48, -182, 117, -229, +165, -208, 166, -115, 104, 27, 4, 162, +-98, 226, -168, 196, -179, 90, -119, -47, +1, -166, 135, -224, 238, -194, 268, -84, +219, 66, 98, 184, -45, 213, -165, 147, +-225, 25, -209, -108, -114, -207, 37, -235, +183, -166, 270, -15, 262, 144, 178, 236, +47, 219, -83, 112, -165, -36, -166, -172, +-102, -249, -3, -229, 89, -110, 144, 59, +153, 192, 114, 222, 53, 150, -9, 22, +-44, -102, -47, -181, -19, -184, 24, -105, +65, 18, 84, 123, 79, 155, 52, 101, +8, 1, -31, -94, -44, -148, -24, -144, +9, -82, 50, 18, 85, 112, 113, 154, +117, 124, 82, 40, 19, -59, -35, -138, +-64, -173, -68, -144, -41, -59, 12, 48, +77, 133, 116, 153, 121, 100, 95, 1, +54, -96, 10, -153, -15, -149, -17, -78, +-3, 33, 17, 126, 27, 145, 22, 86, +4, -24, -4, -128, 12, -177, 53, -153, +96, -64, 124, 59, 123, 161, 92, 190, +29, 132, -56, 17, -124, -106, -141, -189, +-93, -204, -1, -153, 111, -52, 205, 60, +248, 146, 210, 173, 105, 141, -28, 68, +-141, -25, -191, -110, -164, -163, -75, -163, +41, -114, 152, -36, 216, 43, 212, 98, +138, 109, 34, 81, -60, 27, -101, -33, +-82, -68, -20, -64, 54, -32, 108, -4, +116, 3, 69, -14, 4, -46, -44, -85, +-48, -105, -15, -80, 48, 2, 115, 106, +160, 179, 156, 185, 95, 120, 0, 3, +-91, -137, -138, -255, -126, -303, -56, -245, +38, -93, 131, 94, 197, 244, 211, 310, +163, 277, 76, 155, -17, -21, -90, -195, +-128, -304, -127, -310, -77, -222, 6, -86, +95, 56, 152, 166, 173, 227, 157, 221, +112, 150, 50, 45, -13, -60, -50, -141, +-60, -198, -48, -220, -30, -191, -11, -101, +3, 21, 31, 122, 73, 177, 126, 179, +174, 135, 192, 52, 161, -51, 72, -139, +-49, -176, -159, -155, -204, -101, -174, -52, +-77, -14, 57, 21, 196, 54, 293, 77, +312, 82, 238, 75, 98, 63, -67, 36, +-206, -22, -268, -104, -233, -173, -100, -191, +75, -149, 228, -61, 307, 46, 288, 151, +175, 218, 24, 208, -109, 116, -187, -24, +-176, -160, -87, -243, 41, -246, 149, -170, +197, -42, 174, 92, 108, 184, 20, 193, +-49, 117, -74, -3, -44, -110, 24, -167, +91, -162, 121, -98, 106, 1, 60, 90, +-6, 132, -49, 103, -58, 19, -19, -82, +50, -154, 111, -173, 136, -130, 123, -38, +81, 76, 25, 170, -19, 202, -50, 152, +-51, 29, -21, -124, 37, -247, 89, -295, +115, -245, 106, -108, 78, 71, 37, 229, +-5, 303, -25, 263, -19, 119, 23, -67, +71, -226, 96, -301, 92, -277, 73, -171, +32, -29, -10, 105, -40, 181, -51, 179, +-26, 121, 27, 42, 93, -24, 154, -69, +186, -97, 162, -110, 87, -109, -26, -97, +-129, -74, -176, -46, -141, -3, -34, 59, +98, 118, 209, 139, 265, 105, 233, 35, +112, -51, -22, -129, -118, -181, -146, -187, +-103, -138, -20, -46, 69, 54, 137, 126, +155, 152, 125, 128, 75, 67, 23, -23, +-6, -121, -4, -192, 30, -200, 72, -142, +93, -45, 68, 53, 15, 126, -51, 158, +-88, 132, -61, 42, 17, -80, 123, -172, +207, -194, 233, -142, 185, -49, 80, 51, +-59, 126, -165, 150, -197, 104, -150, -3, +-38, -122, 106, -193, 233, -179, 292, -97, +264, 7, 156, 93, 17, 140, -115, 129, +-190, 54, -187, -59, -108, -154, 23, -180, +156, -133, 239, -46, 252, 44, 188, 110, +61, 129, -61, 81, -140, -21, -152, -128, +-90, -182, 23, -153, 136, -57, 211, 59, +211, 150, 141, 180, 40, 128, -60, 3, +-123, -152, -130, -267, -65, -287, 44, -200, +148, -40, 206, 130, 212, 254, 154, 292, +57, 225, -40, 68, -112, -128, -128, -291, +-80, -363, 5, -327, 95, -206, 170, -32, +197, 153, 174, 298, 110, 354, 22, 293, +-54, 126, -83, -88, -61, -282, -16, -399, +27, -403, 60, -285, 84, -75, 90, 157, +87, 328, 80, 373, 81, 284, 87, 106, +80, -94, 39, -257, -12, -333, -59, -301, +-91, -180, -78, -24, -20, 104, 74, 163, +171, 151, 234, 101, 221, 36, 144, -26, +37, -68, -68, -84, -143, -72, -163, -52, +-113, -47, -4, -58, 129, -70, 223, -67, +239, -45, 180, -17, 85, 19, -26, 59, +-110, 90, -126, 92, -64, 54, 43, -11, +143, -78, 186, -130, 151, -159, 73, -160, +-24, -128, -98, -61, -110, 20, -41, 92, +71, 138, 177, 153, 229, 134, 198, 75, +105, -22, -10, -136, -113, -228, -173, -267, +-153, -236, -57, -149, 85, -22, 214, 120, +280, 238, 259, 286, 171, 238, 43, 105, +-95, -66, -187, -221, -195, -320, -116, -343, +11, -281, 143, -139, 225, 43, 241, 205, +207, 297, 133, 298, 29, 216, -60, 69, +-108, -104, -113, -260, -69, -352, 0, -350, +76, -254, 139, -96, 178, 78, 161, 220, +102, 298, 33, 292, -15, 199, -39, 40, +-33, -138, 2, -279, 41, -343, 75, -316, +88, -212, 66, -54, 31, 113, 25, 237, +32, 279, 47, 232, 65, 114, 69, -34, +62, -164, 55, -245, 33, -262, 2, -211, +-8, -114, -1, -6, 26, 79, 60, 119, +98, 127, 120, 115, 116, 81, 81, 27, +26, -44, -29, -113, -50, -161, -34, -187, +-4, -190, 54, -149, 112, -60, 145, 55, +154, 156, 129, 206, 60, 188, -11, 112, +-59, -6, -75, -139, -40, -251, 30, -300, +100, -255, 140, -136, 138, 9, 90, 131, +27, 208, -23, 228, -23, 179, 17, 70, +70, -63, 113, -173, 107, -231, 56, -233, +-4, -198, -52, -134, -67, -41, -19, 70, +60, 159, 152, 199, 223, 187, 216, 136, +128, 47, 3, -81, -121, -221, -199, -319, +-184, -327, -72, -242, 105, -92, 265, 82, +343, 242, 302, 339, 162, 323, -15, 183, +-161, -34, -237, -244, -203, -370, -75, -384, +72, -298, 204, -139, 268, 51, 241, 211, +162, 282, 73, 246, -20, 136, -75, 13, +-78, -90, -45, -164, 10, -210, 61, -219, +82, -182, 71, -117, 56, -51, 50, 14, +57, 91, 70, 165, 101, 197, 120, 160, +110, 59, 79, -69, 16, -180, -58, -251, +-91, -266, -84, -214, -44, -105, 45, 23, +140, 122, 207, 166, 231, 158, 191, 122, +97, 70, 2, 0, -75, -82, -127, -156, +-133, -204, -86, -218, 8, -196, 110, -134, +188, -31, 217, 92, 190, 197, 128, 236, +65, 195, 0, 90, -36, -41, -34, -165, +-28, -258, -17, -289, -6, -252, -5, -158, +9, -42, 58, 67, 109, 153, 165, 213, +217, 231, 233, 195, 188, 98, 81, -50, +-61, -215, -195, -350, -269, -415, -247, -381, +-122, -230, 69, 10, 282, 270, 422, 459, +437, 501, 337, 374, 146, 113, -87, -204, +-266, -477, -342, -620, -305, -578, -152, -351, +45, -16, 224, 308, 346, 512, 375, 545, +296, 401, 161, 129, 20, -181, -86, -434, +-137, -543, -139, -479, -114, -278, -78, -20, +-20, 206, 51, 338, 117, 351, 178, 249, +245, 69, 272, -122, 244, -252, 152, -283, +-3, -228, -156, -130, -250, -28, -271, 53, +-204, 90, -32, 73, 176, 17, 351, -35, +433, -52, 391, -27, 230, 12, 18, 34, +-177, 22, -298, -26, -296, -100, -170, -174, +20, -209, 188, -170, 285, -54, 280, 90, +203, 197, 105, 223, 16, 156, -51, 16, +-55, -145, -12, -266, 27, -296, 50, -217, +47, -64, 23, 93, 11, 180, 35, 173, +62, 89, 89, -26, 114, -126, 122, -169, +99, -141, 61, -61, 19, 24, -11, 65, +-4, 45, 13, -11, 13, -70, 11, -105, +36, -100, 63, -63, 85, -6, 103, 44, +109, 65, 102, 46, 86, -8, 47, -65, +-12, -100, -35, -108, -10, -97, 30, -67, +66, -20, 88, 30, 78, 58, 61, 51, +40, 14, 14, -36, 19, -86, 72, -119, +133, -120, 157, -89, 138, -27, 71, 41, +-21, 86, -101, 82, -135, 30, -114, -45, +-18, -115, 122, -162, 235, -167, 281, -119, +260, -29, 177, 71, 55, 137, -49, 142, +-124, 82, -153, -17, -126, -124, -67, -206, +-5, -237, 79, -195, 169, -90, 239, 36, +289, 131, 284, 172, 203, 153, 66, 83, +-78, -14, -200, -116, -259, -197, -234, -232, +-129, -206, 16, -135, 181, -40, 329, 60, +394, 148, 373, 200, 275, 185, 103, 99, +-93, -34, -245, -168, -343, -260, -331, -285, +-194, -237, 13, -124, 232, 23, 412, 149, +485, 210, 423, 191, 254, 115, 24, 12, +-185, -86, -317, -164, -332, -208, -248, -205, +-94, -159, 92, -85, 247, -4, 326, 66, +344, 118, 299, 144, 187, 128, 72, 65, +-39, -31, -140, -123, -196, -188, -197, -214, +-157, -200, -55, -139, 76, -42, 196, 63, +293, 140, 336, 168, 305, 144, 204, 74, +65, -21, -80, -126, -190, -208, -241, -240, +-213, -209, -132, -126, -1, -21, 167, 72, +302, 137, 364, 162, 349, 138, 239, 68, +71, -31, -83, -127, -212, -197, -260, -228, +-196, -217, -66, -153, 74, -44, 201, 80, +283, 171, 300, 195, 250, 151, 136, 56, +2, -61, -109, -167, -148, -232, -125, -232, +-62, -170, 28, -76, 116, 16, 149, 84, +151, 125, 136, 138, 100, 118, 86, 57, +80, -38, 47, -135, 4, -211, -29, -243, +-53, -226, -33, -144, 19, -9, 74, 137, +118, 231, 135, 237, 121, 152, 90, 10, +66, -140, 49, -258, 30, -310, 14, -281, +22, -171, 18, -16, 12, 129, 34, 219, +60, 242, 74, 198, 91, 89, 86, -66, +66, -228, 65, -335, 41, -344, 7, -253, +5, -94, 34, 92, 75, 246, 120, 313, +133, 262, 109, 106, 61, -96, 1, -265, +-52, -344, -85, -322, -53, -211, 32, -51, +124, 108, 195, 206, 225, 218, 183, 151, +112, 41, 29, -67, -65, -148, -118, -190, +-107, -187, -63, -141, 2, -75, 82, -11, +142, 30, 194, 47, 225, 50, 210, 45, +145, 28, 54, 5, -40, -19, -120, -45, +-162, -73, -148, -109, -79, -143, 33, -156, +172, -131, 267, -70, 297, 19, 279, 107, +208, 169, 81, 184, -60, 130, -186, 12, +-256, -137, -224, -267, -123, -331, 5, -301, +146, -181, 286, 0, 376, 184, 389, 308, +305, 326, 140, 226, -56, 35, -227, -179, +-343, -344, -371, -409, -261, -349, -38, -183, +213, 30, 408, 217, 500, 319, 459, 299, +323, 173, 114, -7, -141, -177, -345, -283, +-416, -299, -354, -229, -189, -109, 47, 12, +288, 93, 472, 120, 531, 101, 429, 58, +188, 14, -78, -18, -269, -41, -347, -61, +-301, -80, -155, -103, 31, -126, 191, -137, +284, -118, 281, -70, 222, 0, 163, 77, +117, 140, 64, 164, 12, 136, -46, 54, +-119, -70, -174, -208, -181, -311, -126, -337, +8, -262, 203, -99, 364, 109, 429, 299, +375, 392, 208, 342, -20, 152, -223, -118, +-347, -367, -358, -504, -228, -477, 0, -295, +236, -22, 403, 245, 454, 414, 363, 426, +179, 286, -33, 50, -215, -191, -302, -364, +-251, -421, -100, -353, 75, -194, 223, 1, +291, 169, 265, 260, 179, 251, 73, 164, +-35, 31, -94, -101, -88, -198, -42, -234, +19, -199, 76, -117, 110, -29, 118, 30, +108, 46, 73, 32, 32, 12, 7, -1, +17, 1, 41, 20, 68, 40, 90, 32, +85, -22, 50, -106, 6, -183, -35, -216, +-48, -189, -2, -100, 71, 23, 141, 148, +187, 227, 175, 224, 98, 134, 5, -14, +-78, -169, -125, -283, -102, -325, -12, -282, +112, -155, 214, 16, 253, 175, 200, 270, +79, 274, -55, 184, -140, 33, -164, -133, +-106, -265, 16, -321, 141, -286, 236, -175, +266, -31, 212, 97, 112, 170, 8, 184, +-105, 147, -178, 80, -167, -2, -80, -80, +50, -142, 171, -183, 230, -205, 223, -199, +171, -151, 86, -58, 3, 67, -48, 179, +-41, 241, -10, 220, 9, 114, 13, -47, +1, -213, -13, -328, 16, -343, 66, -246, +115, -76, 177, 100, 213, 220, 194, 259, +121, 211, 4, 99, -129, -49, -211, -183, +-223, -263, -151, -274, 8, -224, 207, -133, +378, -14, 440, 112, 362, 210, 167, 240, +-80, 180, -289, 45, -373, -117, -325, -252, +-155, -314, 78, -278, 278, -150, 394, 24, +404, 174, 301, 234, 141, 186, -11, 68, +-153, -64, -243, -157, -257, -188, -196, -160, +-68, -95, 98, -31, 237, 6, 314, 9, +315, -1, 245, 3, 124, 32, -18, 59, +-117, 53, -162, 13, -163, -50, -124, -116, +-54, -162, 23, -169, 124, -122, 216, -35, +257, 55, 251, 108, 189, 112, 78, 81, +-43, 31, -135, -29, -186, -92, -162, -142, +-86, -167, 13, -157, 114, -119, 199, -60, +250, 18, 250, 102, 199, 161, 107, 161, +-10, 104, -126, 4, -190, -106, -200, -200, +-145, -255, -27, -248, 114, -170, 246, -38, +333, 105, 313, 210, 194, 239, 37, 188, +-122, 73, -215, -81, -210, -226, -124, -302, +7, -279, 133, -168, 199, -20, 198, 108, +155, 172, 101, 165, 53, 106, -3, 18, +-47, -61, -64, -107, -50, -115, -4, -108, +55, -97, 96, -91, 129, -76, 132, -37, +77, 18, 1, 69, -49, 94, -51, 81, +-3, 27, 66, -47, 107, -109, 117, -131, +98, -112, 58, -66, 4, -25, -31, -11, +-21, -23, 18, -37, 59, -24, 82, 17, +76, 67, 55, 94, 36, 71, 5, -9, +-16, -118, -4, -206, 36, -224, 84, -151, +123, -10, 121, 130, 75, 197, 14, 159, +-57, 39, -106, -105, -94, -207, -9, -218, +111, -135, 218, 5, 250, 128, 186, 168, +53, 104, -94, -23, -195, -148, -213, -211, +-125, -188, 33, -92, 197, 34, 298, 134, +296, 165, 191, 111, 46, 6, -88, -99, +-175, -162, -192, -171, -124, -141, 1, -93, +129, -31, 208, 37, 209, 87, 155, 113, +65, 109, -25, 76, -93, 6, -99, -87, +-36, -180, 56, -231, 129, -205, 148, -107, +105, 27, 28, 141, -42, 191, -90, 157, +-81, 58, -6, -66, 105, -157, 186, -175, +198, -114, 130, -22, 24, 37, -70, 30, +-124, -28, -119, -96, -56, -126, 54, -89, +146, 8, 188, 132, 168, 210, 105, 186, +28, 48, -34, -147, -68, -305, -68, -350, +-35, -264, 9, -84, 42, 121, 56, 265, +71, 291, 87, 200, 106, 41, 117, -116, +109, -205, 66, -213, -4, -162, -84, -98, +-144, -54, -134, -27, -55, -1, 57, 38, +161, 92, 220, 144, 201, 158, 133, 107, +44, -18, -27, -179, -52, -300, -48, -315, +-40, -212, -41, -40, -46, 134, -44, 241, +-5, 243, 73, 149, 175, 6, 251, -119, +257, -166, 168, -137, 4, -80, -170, -51, +-275, -67, -266, -105, -140, -121, 63, -85, +249, 13, 345, 156, 311, 277, 169, 304, +-17, 191, -165, -38, -222, -291, -170, -458, +-48, -471, 78, -320, 157, -55, 159, 225, +109, 421, 44, 459, 0, 331, -9, 88, +18, -165, 43, -346, 50, -408, 38, -345, +8, -200, -11, -23, -12, 132, -14, 215, +-12, 212, 11, 152, 41, 73, 90, 8, +133, -43, 148, -86, 120, -128, 52, -168, +-40, -195, -122, -194, -151, -143, -109, -31, +-14, 124, 86, 263, 166, 316, 194, 243, +166, 74, 101, -132, 22, -302, -47, -377, +-86, -324, -107, -167, -108, 28, -68, 186, +2, 248, 95, 216, 188, 131, 234, 38, +205, -42, 121, -98, -11, -145, -144, -177, +-228, -192, -218, -184, -106, -135, 60, -27, +214, 120, 294, 245, 273, 294, 153, 228, +-13, 69, -158, -124, -206, -283, -145, -367, +-22, -337, 104, -198, 170, 6, 146, 210, +61, 331, -32, 334, -90, 229, -67, 53, +18, -160, 110, -337, 159, -403, 138, -323, +51, -122, -43, 117, -107, 284, -113, 320, +-47, 225, 48, 30, 131, -173, 160, -280, +123, -243, 44, -94, -32, 77, -87, 161, +-93, 114, -47, -25, 33, -169, 111, -220, +145, -126, 129, 74, 67, 266, -11, 335, +-75, 208, -96, -75, -74, -373, -10, -529, +62, -445, 111, -135, 127, 259, 100, 540, +49, 574, 3, 332, -22, -78, -31, -468, +-16, -650, -3, -543, 12, -191, 28, 232, +38, 515, 39, 533, 41, 300, 41, -59, +42, -371, 46, -490, 41, -371, 33, -76, +12, 240, -22, 396, -59, 309, -68, 48, +-36, -246, 32, -415, 99, -374, 140, -135, +140, 198, 95, 459, 28, 499, -42, 269, +-88, -120, -95, -478, -66, -633, -33, -513, +2, -170, 38, 241, 83, 545, 133, 603, +161, 386, 152, 7, 104, -349, 24, -518, +-85, -451, -181, -209, -216, 66, -156, 248, +-27, 271, 123, 153, 234, -26, 273, -153, +226, -150, 98, -30, -61, 115, -173, 177, +-187, 112, -121, -52, -11, -227, 79, -331, +117, -301, 105, -134, 58, 109, -1, 317, +-19, 394, 19, 312, 77, 112, 113, -119, +88, -303, 8, -388, -87, -351, -154, -202, +-179, -3, -123, 179, 6, 289, 154, 307, +268, 231, 303, 88, 240, -80, 98, -223, +-73, -284, -230, -253, -311, -148, -284, -17, +-156, 86, 23, 119, 199, 89, 309, 29, +336, -10, 285, 8, 157, 69, -9, 124, +-163, 120, -266, 27, -299, -153, -244, -342, +-121, -436, 53, -354, 230, -95, 343, 248, +352, 526, 253, 620, 74, 475, -123, 116, +-262, -326, -303, -671, -233, -766, -77, -566, +102, -153, 225, 301, 264, 629, 211, 717, +105, 538, -8, 161, -104, -258, -154, -551, +-142, -620, -75, -462, 5, -167, 70, 148, +94, 365, 90, 418, 72, 303, 48, 98, +17, -98, 0, -206, 3, -203, 10, -121, +4, -20, -28, 34, -59, 22, -68, -42, +-39, -103, 16, -110, 91, -39, 155, 80, +179, 192, 125, 231, -2, 159, -136, -7, +-204, -196, -169, -317, -45, -313, 121, -184, +246, 16, 273, 213, 162, 325, -41, 303, +-229, 148, -297, -68, -207, -250, -13, -333, +189, -295, 300, -164, 276, 21, 130, 202, +-57, 313, -183, 296, -178, 166, -76, -22, +45, -196, 108, -296, 85, -294, 4, -201, +-77, -42, -108, 135, -60, 233, 69, 214, +191, 107, 234, -18, 169, -96, 22, -95, +-134, -51, -212, 6, -196, 53, -105, 33, +27, -71, 126, -196, 155, -249, 122, -172, +58, 31, 1, 250, -8, 377, 11, 366, +34, 208, 38, -74, 1, -363, -72, -519, +-125, -467, -111, -216, -34, 107, 74, 349, +155, 443, 172, 387, 116, 189, 20, -62, +-76, -253, -106, -311, -65, -238, -1, -106, +40, -25, 34, -9, -8, -5, -50, -4, +-44, 22, 6, 104, 86, 223, 154, 306, +161, 282, 95, 90, -14, -208, -124, -458, +-179, -565, -156, -489, -86, -219, 4, 163, +90, 496, 147, 656, 158, 569, 148, 270, +119, -96, 69, -391, -14, -547, -122, -509, +-213, -306, -242, -49, -190, 176, -74, 303, +93, 311, 258, 247, 348, 162, 311, 45, +161, -65, -53, -132, -236, -174, -309, -198, +-258, -190, -113, -153, 59, -73, 167, 48, +169, 139, 103, 184, 20, 206, -2, 189, +50, 107, 118, -5, 130, -136, 66, -245, +-74, -278, -234, -239, -312, -146, -247, 9, +-44, 186, 197, 297, 361, 312, 365, 211, +221, 41, -7, -115, -215, -219, -299, -277, +-229, -253, -63, -143, 109, -4, 195, 123, +154, 197, 34, 209, -94, 187, -165, 126, +-127, -12, 9, -171, 163, -264, 261, -253, +233, -143, 75, 19, -125, 165, -275, 254, +-311, 250, -200, 106, 16, -107, 218, -261, +328, -269, 292, -140, 123, 52, -88, 188, +-238, 220, -272, 145, -170, -24, 10, -202, +159, -264, 235, -162, 211, 39, 93, 232, +-64, 299, -182, 220, -227, 45, -171, -167, +-37, -333, 105, -353, 207, -217, 242, -1, +183, 203, 46, 311, -103, 304, -218, 214, +-233, 65, -136, -116, 5, -255, 122, -317, +186, -291, 167, -179, 79, -7, -11, 186, +-65, 351, -64, 412, -27, 307, -11, 79, +-37, -197, -61, -428, -79, -511, -75, -396, +-19, -126, 81, 216, 182, 482, 241, 544, +210, 397, 79, 111, -87, -205, -236, -425, +-319, -456, -300, -317, -170, -71, 30, 159, +239, 256, 358, 204, 335, 77, 205, -50, +29, -94, -143, -16, -255, 119, -259, 236, +-169, 251, -39, 96, 54, -191, 78, -454, +66, -567, 58, -448, 61, -109, 77, 299, +102, 614, 108, 725, 63, 550, -31, 130, +-136, -335, -209, -653, -188, -702, -89, -470, +38, -85, 148, 273, 212, 503, 191, 523, +84, 314, -50, 4, -136, -250, -123, -347, +-46, -267, 24, -91, 46, 54, 35, 141, +-21, 154, -97, 69, -121, -58, -53, -122, +88, -88, 239, 26, 298, 154, 205, 190, +22, 127, -193, 9, -370, -142, -421, -279, +-306, -303, -75, -196, 210, 8, 423, 231, +459, 352, 356, 323, 167, 203, -87, 41, +-319, -136, -431, -239, -410, -244, -249, -175, +-14, -74, 178, -11, 286, -18, 310, -22, +217, 31, 66, 119, -43, 223, -107, 300, +-109, 282, -46, 147, -1, -76, -20, -344, +-52, -516, -107, -474, -159, -240, -133, 79, +-36, 366, 107, 501, 270, 445, 343, 245, +262, -43, 99, -294, -106, -377, -312, -284, +-406, -117, -345, 44, -168, 133, 102, 141, +339, 106, 401, 51, 301, -5, 100, -2, +-144, 56, -309, 75, -316, 20, -207, -79, +8, -169, 227, -200, 288, -149, 192, -48, +31, 101, -147, 266, -248, 332, -205, 242, +-72, 55, 110, -142, 261, -288, 257, -328, +95, -267, -97, -114, -241, 103, -281, 284, +-181, 312, -11, 209, 150, 58, 270, -90, +278, -180, 146, -193, -20, -122, -151, 16, +-223, 150, -207, 159, -125, 49, -28, -80, +87, -163, 156, -170, 119, -90, 50, 36, +7, 170, -34, 275, -51, 249, -18, 80, +23, -114, 67, -232, 85, -257, 18, -187, +-93, -74, -163, 42, -189, 160, -153, 219, +-44, 163, 80, 62, 191, 1, 271, -35, +261, -59, 147, -88, 7, -120, -141, -108, +-277, -32, -340, 20, -300, 35, -155, 73, +67, 116, 269, 119, 355, 68, 319, -18, +162, -79, -65, -50, -241, -15, -288, -37, +-212, -54, -34, -29, 141, -7, 194, 6, +112, 4, -57, 8, -210, 73, -238, 131, +-109, 88, 95, 0, 292, -36, 368, -51, +260, -61, 19, -68, -251, -69, -437, -20, +-435, 63, -243, 74, 29, 21, 273, 8, +395, 15, 362, 5, 205, -11, -9, -23, +-202, -1, -277, 77, -230, 101, -143, 24, +-58, -58, 12, -114, 57, -157, 85, -147, +108, -61, 115, 73, 131, 249, 131, 343, +62, 244, -55, 25, -162, -197, -236, -373, +-236, -415, -165, -276, -72, -20, 56, 293, +198, 526, 275, 509, 261, 259, 184, -56, +53, -349, -74, -521, -187, -477, -300, -254, +-333, 61, -234, 371, -82, 503, 67, 389, +214, 163, 304, -85, 330, -287, 282, -343, +114, -239, -127, -49, -313, 170, -415, 284, +-402, 195, -238, 3, 12, -163, 273, -258, +454, -220, 430, -37, 198, 181, -72, 361, +-284, 398, -377, 196, -294, -134, -90, -379, +121, -465, 270, -369, 260, -93, 79, 228, +-110, 463, -210, 519, -204, 320, -80, -53, +86, -349, 181, -469, 199, -418, 124, -197, +-48, 107, -202, 358, -233, 479, -159, 401, +-27, 133, 105, -147, 162, -324, 164, -399, +108, -344, -25, -145, -157, 101, -178, 315, +-102, 415, 5, 324, 87, 113, 98, -98, +55, -275, 1, -364, -64, -282, -124, -85, +-105, 139, -8, 307, 106, 321, 164, 178, +125, 0, 27, -153, -57, -251, -123, -220, +-185, -89, -189, 48, -103, 152, 27, 173, +121, 87, 156, -2, 152, -39, 148, -47, +117, -15, 15, 36, -125, 34, -223, -6, +-249, -42, -216, -89, -133, -97, -12, -29, +151, 52, 294, 102, 325, 124, 209, 76, +33, -8, -118, -51, -225, -63, -277, -55, +-247, -2, -127, 48, 36, 40, 149, 6, +160, -47, 128, -97, 100, -78, 59, 6, +-14, 87, -84, 155, -117, 176, -100, 105, +-63, -10, -56, -118, -49, -202, -2, -207, +64, -106, 91, 19, 77, 129, 36, 195, +12, 180, -2, 99, -49, 19, -102, -60, +-99, -120, -53, -107, -24, -60, -9, -27, +11, -12, 64, -17, 116, -30, 112, 10, +41, 76, -45, 120, -116, 153, -157, 159, +-146, 89, -85, -31, 20, -157, 135, -256, +190, -252, 130, -151, 5, -26, -111, 100, +-171, 228, -158, 291, -78, 256, 40, 150, +152, 0, 184, -141, 105, -230, -13, -280, +-111, -278, -164, -156, -165, 41, -115, 227, +-40, 349, 56, 363, 128, 245, 134, 39, +94, -205, 41, -410, -9, -443, -40, -273, +-64, 7, -94, 280, -85, 453, -49, 432, +-37, 230, -45, -71, -31, -354, 11, -476, +72, -357, 117, -81, 104, 206, 63, 399, +11, 401, -64, 210, -136, -72, -141, -315, +-91, -406, -12, -271, 58, 7, 66, 266, +21, 398, -2, 343, 2, 109, 1, -184, +11, -390, 16, -427, 3, -254, -27, 46, +-71, 314, -112, 432, -75, 374, 24, 152, +106, -129, 151, -329, 142, -376, 43, -254, +-110, -11, -241, 224, -315, 324, -247, 275, +-38, 95, 191, -129, 341, -289, 371, -319, +245, -205, 14, 33, -212, 283, -364, 401, +-367, 354, -201, 171, 6, -93, 133, -333, +179, -445, 135, -394, 37, -175, -25, 129, +-31, 369, -3, 452, 59, 372, 82, 152, +12, -130, -74, -350, -140, -426, -179, -312, +-138, -47, -36, 237, 43, 393, 113, 379, +156, 198, 113, -96, 32, -367, -47, -480, +-132, -368, -157, -67, -91, 294, -6, 528, +92, 538, 171, 322, 144, -43, 29, -405, +-99, -584, -234, -500, -294, -197, -195, 190, +-9, 468, 176, 505, 305, 310, 302, -12, +166, -321, -4, -450, -184, -345, -299, -74, +-265, 232, -142, 431, -8, 407, 121, 185, +184, -109, 141, -355, 57, -435, -52, -318, +-150, -78, -157, 172, -74, 355, 29, 383, +133, 247, 170, 32, 104, -168, -8, -286, +-133, -270, -231, -145, -223, 16, -106, 183, +21, 283, 124, 245, 177, 90, 152, -101, +74, -275, -27, -337, -117, -242, -135, -48, +-87, 192, -39, 396, -1, 434, 21, 277, +19, 19, 4, -268, -16, -448, -48, -419, +-48, -221, -3, 47, 49, 310, 76, 423, +63, 320, 14, 94, -42, -168, -94, -355, +-144, -347, -131, -161, -42, 74, 56, 300, +110, 416, 116, 333, 71, 109, 9, -166, +-52, -421, -111, -507, -127, -361, -88, -100, +-28, 204, 24, 468, 59, 552, 54, 420, +39, 147, 23, -215, -18, -497, -63, -531, +-68, -364, -50, -76, -34, 269, -21, 493, +-15, 474, 9, 271, 44, -68, 50, -394, +22, -491, -1, -346, -32, -81, -82, 241, +-122, 469, -121, 450, -55, 242, 65, -67, +163, -374, 167, -476, 95, -325, -24, -73, +-143, 207, -217, 409, -213, 391, -130, 194, +21, -60, 160, -310, 184, -404, 109, -254, +12, -18, -64, 205, -105, 370, -96, 355, +-49, 162, 24, -67, 68, -287, 34, -400, +-64, -289, -142, -58, -153, 157, -104, 329, +-4, 365, 101, 210, 182, 0, 215, -211, +157, -358, -11, -303, -187, -90, -267, 117, +-245, 283, -156, 344, -25, 220, 94, 15, +162, -182, 159, -335, 57, -318, -55, -110, +-79, 99, -36, 248, 5, 323, 34, 240, +28, 50, -17, -129, -71, -280, -134, -313, +-172, -159, -117, 29, 12, 159, 103, 257, +129, 267, 98, 161, 50, 24, 20, -139, +-14, -273, -73, -261, -97, -167, -59, -76, +-46, 63, -75, 224, -85, 297, -51, 281, +10, 159, 73, -50, 74, -209, 39, -268, +27, -282, 2, -191, -58, 13, -87, 197, +-58, 291, 2, 263, 75, 104, 78, -72, +-9, -160, -95, -202, -144, -172, -194, -31, +-183, 123, -66, 202, 102, 188, 247, 63, +295, -88, 202, -150, 34, -156, -114, -127, +-253, -24, -326, 108, -262, 181, -112, 183, +39, 95, 156, -43, 174, -122, 110, -130, +64, -113, 20, -50, -48, 61, -75, 143, +-56, 160, -43, 89, -27, -50, -51, -156, +-108, -163, -96, -115, -23, -23, 19, 114, +57, 223, 101, 241, 84, 139, 29, -52, +-45, -228, -144, -278, -179, -210, -97, -71, +-1, 108, 68, 264, 116, 306, 94, 204, +24, -2, -44, -206, -129, -287, -172, -218, +-91, -51, 3, 137, 36, 288, 41, 313, +12, 175, -42, -70, -48, -306, -31, -409, +-8, -321, 69, -87, 119, 190, 61, 419, +-37, 502, -132, 375, -215, 81, -195, -248, +-97, -478, 2, -505, 116, -332, 208, -51, +170, 236, 34, 429, -98, 433, -188, 239, +-173, -29, -69, -253, 31, -331, 102, -226, +140, -12, 64, 192, -91, 317, -203, 279, +-225, 64, -141, -204, 20, -388, 154, -403, +190, -226, 156, 72, 51, 331, -104, 467, +-213, 425, -212, 191, -117, -113, 33, -327, +138, -387, 138, -270, 74, -40, -21, 154, +-138, 234, -225, 193, -204, 43, -95, -134, +55, -199, 181, -138, 218, 16, 159, 197, +51, 281, -79, 226, -200, 95, -246, -69, +-199, -222, -85, -265, 47, -201, 135, -89, +126, 34, 62, 112, -18, 107, -105, 96, +-153, 97, -107, 71, 5, 50, 116, 35, +175, -6, 133, -58, 14, -95, -122, -118, +-234, -80, -289, 19, -225, 88, -72, 91, +100, 59, 232, -14, 248, -83, 145, -88, +6, -44, -106, 45, -173, 151, -163, 185, +-83, 104, 11, -23, 58, -152, 29, -229, +-60, -188, -127, -55, -123, 112, -76, 252, +1, 274, 100, 142, 167, -56, 161, -236, +87, -328, -47, -275, -174, -82, -223, 157, +-199, 364, -146, 439, -63, 320, 45, 83, +133, -167, 170, -355, 128, -416, 30, -320, +-59, -123, -118, 101, -167, 258, -166, 286, +-83, 209, 34, 109, 117, 16, 136, -55, +77, -74, -30, -59, -123, -34, -191, -35, +-199, -72, -107, -113, 45, -100, 171, -33, +218, 47, 149, 116, -3, 160, -151, 164, +-249, 123, -280, 31, -202, -75, -13, -135, +162, -138, 249, -104, 231, -62, 115, 0, +-42, 89, -182, 169, -285, 185, -291, 116, +-167, -4, 4, -129, 135, -228, 203, -278, +191, -228, 95, -42, -16, 222, -126, 413, +-204, 446, -181, 314, -76, 72, 22, -200, +76, -426, 68, -521, -5, -415, -86, -133, +-138, 165, -140, 348, -50, 385, 120, 309, +236, 170, 234, 23, 123, -101, -86, -145, +-299, -91, -404, -38, -369, -65, -195, -145, +76, -200, 308, -187, 391, -87, 307, 51, +101, 196, -139, 339, -282, 395, -298, 282, +-219, 59, -60, -162, 82, -304, 114, -327, +43, -264, -57, -154, -133, 0, -122, 161, +-22, 214, 99, 180, 180, 131, 195, 87, +96, 66, -84, 39, -241, -33, -323, -102, +-295, -115, -160, -121, 0, -126, 123, -75, +215, 26, 242, 120, 177, 173, 60, 130, +-60, 29, -165, -38, -225, -79, -238, -110, +-219, -92, -121, -15, 27, 64, 143, 122, +198, 119, 187, 59, 93, 24, -36, 20, +-141, -23, -206, -79, -194, -112, -85, -133, +32, -120, 72, -72, 55, -6, -17, 106, +-92, 259, -112, 320, -79, 242, -1, 92, +116, -97, 181, -262, 122, -334, -15, -314, +-169, -194, -292, 18, -315, 194, -214, 245, +-45, 210, 159, 149, 307, 77, 315, 40, +199, 19, 8, -11, -201, -17, -340, -44, +-359, -134, -269, -213, -90, -201, 114, -107, +238, 41, 223, 179, 124, 232, -14, 205, +-134, 138, -184, 15, -152, -98, -52, -108, +62, -48, 117, 26, 65, 60, -52, 6, +-169, -110, -234, -186, -209, -201, -78, -148, +89, 18, 229, 236, 283, 377, 194, 395, +-6, 259, -227, 8, -355, -219, -349, -345, +-211, -358, 7, -254, 213, -55, 313, 125, +260, 223, 64, 229, -163, 133, -306, 26, +-324, -14, -208, -19, -9, -10, 174, 18, +247, 16, 196, -30, 36, -87, -156, -135, +-261, -150, -234, -68, -113, 56, 53, 141, +173, 201, 183, 198, 101, 121, -60, 25, +-238, -67, -315, -151, -246, -169, -96, -124, +86, -81, 244, -35, 295, 44, 229, 110, +78, 163, -130, 194, -298, 145, -340, 48, +-285, -53, -157, -159, -1, -236, 123, -214, +189, -119, 198, 3, 119, 131, -15, 188, +-94, 151, -106, 99, -101, 51, -68, 15, +-31, 37, -20, 68, -17, 45, -65, -28, +-153, -141, -193, -277, -141, -324, -36, -219, +99, -19, 232, 235, 281, 450, 238, 497, +99, 369, -140, 120, -364, -198, -441, -444, +-385, -507, -217, -400, 17, -185, 229, 81, +355, 273, 351, 342, 193, 331, -52, 225, +-228, 71, -302, -43, -287, -110, -169, -152, +-7, -149, 110, -122, 154, -93, 87, -35, +-63, 38, -172, 73, -176, 99, -94, 122, +41, 98, 179, 64, 225, 27, 158, -26, +-13, -68, -258, -76, -435, -85, -416, -92, +-235, -60, 31, -12, 298, 41, 447, 107, +423, 135, 225, 120, -94, 93, -406, 27, +-545, -62, -472, -123, -253, -138, 32, -112, +266, -32, 369, 63, 340, 118, 174, 155, +-81, 147, -268, 66, -306, -32, -231, -107, +-111, -143, 10, -107, 86, -21, 104, 56, +56, 105, -54, 119, -142, 56, -130, -54, +-59, -126, 13, -135, 63, -60, 69, 73, +55, 173, 15, 198, -59, 149, -143, 23, +-172, -137, -128, -237, -71, -225, -24, -107, +29, 81, 82, 231, 110, 264, 65, 202, +-54, 59, -145, -118, -165, -243, -132, -250, +-78, -147, 9, 17, 117, 161, 166, 209, +119, 175, -26, 93, -189, -29, -263, -137, +-233, -174, -153, -138, -30, -45, 117, 49, +240, 107, 247, 128, 116, 128, -86, 95, +-245, 19, -280, -56, -244, -103, -153, -99, +8, -57, 172, -11, 243, 35, 173, 85, +-9, 105, -191, 72, -275, -6, -249, -73, +-155, -91, 2, -63, 190, -13, 285, 31, +239, 77, 51, 90, -193, 54, -343, -19, +-354, -93, -264, -105, -87, -55, 141, 15, +316, 77, 331, 113, 176, 114, -68, 68, +-277, -22, -347, -105, -304, -132, -161, -72, +64, 18, 260, 93, 319, 138, 203, 126, +-43, 61, -297, -41, -418, -151, -367, -206, +-193, -154, 59, -28, 319, 101, 439, 198, +352, 236, 85, 184, -237, 73, -443, -77, +-468, -208, -353, -232, -135, -163, 131, -58, +322, 49, 341, 136, 193, 170, -34, 160, +-220, 115, -260, 32, -184, -26, -66, -30, +68, -40, 151, -58, 117, -68, -32, -87, +-228, -82, -348, -53, -287, -24, -93, 18, +118, 102, 284, 159, 382, 151, 326, 118, +93, 49, -206, -41, -464, -94, -549, -139, +-424, -171, -181, -124, 92, -34, 345, 49, +472, 126, 399, 182, 155, 170, -148, 127, +-386, 52, -444, -72, -349, -143, -192, -139, +34, -106, 239, -35, 299, 51, 200, 81, +7, 73, -171, 43, -237, -30, -193, -83, +-96, -43, 29, 26, 153, 90, 165, 146, +31, 104, -148, -12, -301, -120, -320, -211, +-181, -236, 16, -114, 201, 90, 331, 268, +329, 376, 160, 328, -105, 114, -345, -117, +-463, -298, -398, -396, -210, -311, -10, -94, +193, 124, 317, 281, 285, 316, 141, 195, +-45, 35, -193, -61, -239, -124, -182, -108, +-90, -15, -6, 34, 59, 23, 50, -24, +-43, -124, -141, -179, -213, -109, -193, 25, +-71, 161, 71, 289, 187, 320, 259, 217, +243, 73, 96, -104, -119, -258, -310, -284, +-419, -216, -393, -130, -245, -14, -51, 92, +160, 137, 309, 168, 322, 180, 214, 130, +38, 87, -134, 63, -238, -20, -244, -109, +-196, -170, -117, -219, -18, -204, 42, -114, +26, -20, -16, 83, -48, 216, -50, 285, +-9, 257, 29, 189, 47, 66, 56, -79, +37, -168, -39, -239, -127, -267, -188, -186, +-207, -49, -161, 62, -53, 154, 57, 209, +144, 194, 192, 164, 142, 92, 13, -38, +-137, -124, -253, -146, -277, -157, -195, -130, +-63, -62, 71, 16, 172, 91, 190, 140, +100, 108, -30, 43, -143, 25, -220, 5, +-204, -13, -122, 1, -28, 17, 59, 28, +105, 32, 87, -16, 20, -84, -70, -86, +-153, -35, -185, 5, -125, 39, -25, 62, +72, 50, 161, 40, 155, 5, 52, -42, +-96, -30, -245, 32, -322, 76, -277, 63, +-125, 10, 58, -62, 211, -110, 280, -113, +218, -94, 68, -22, -112, 117, -275, 218, +-310, 227, -235, 149, -119, 25, 15, -93, +124, -174, 162, -211, 104, -194, -1, -75, +-108, 93, -162, 201, -121, 222, -53, 167, +2, 57, 59, -66, 56, -185, -3, -252, +-81, -203, -152, -33, -158, 154, -84, 251, +20, 257, 63, 166, 60, 15, 29, -149, +-51, -274, -133, -275, -178, -119, -156, 98, +-30, 244, 113, 273, 180, 204, 175, 61, +99, -98, -45, -214, -224, -248, -350, -142, +-378, 38, -274, 166, -62, 180, 153, 120, +306, 30, 370, -67, 302, -127, 113, -135, +-133, -74, -344, 55, -426, 148, -371, 135, +-227, 71, -57, -6, 110, -70, 220, -104, +209, -98, 107, -46, -6, 60, -69, 172, +-78, 187, -64, 124, -51, 34, -36, -76, +-47, -168, -100, -210, -179, -190, -213, -74, +-156, 107, -36, 237, 93, 251, 177, 191, +185, 72, 129, -87, 28, -205, -111, -258, +-206, -204, -201, -35, -118, 131, -38, 200, +-10, 183, -27, 108, -70, -14, -101, -115, +-115, -142, -90, -90, 17, 58, 147, 219, +211, 256, 192, 179, 77, 25, -88, -167, +-243, -320, -352, -368, -377, -289, -283, -76, +-79, 216, 125, 422, 259, 465, 300, 371, +230, 150, 106, -132, -44, -366, -209, -490, +-288, -434, -262, -197, -183, 98, -97, 316, +-21, 416, 47, 379, 77, 197, 86, -34, +46, -236, -18, -330, -27, -247, -19, -48, +-23, 140, -22, 259, -42, 265, -56, 143, +-62, -62, -98, -250, -156, -338, -178, -268, +-116, -48, -40, 179, 40, 328, 122, 352, +170, 227, 184, 9, 118, -215, -33, -350, +-172, -322, -259, -127, -285, 120, -250, 293, +-164, 338, -32, 239, 93, 26, 188, -188, +182, -320, 94, -296, 13, -114, -63, 128, +-119, 311, -132, 348, -101, 245, -33, 42, +12, -179, -26, -318, -120, -323, -194, -187, +-189, 25, -134, 201, -23, 272, 127, 216, +251, 82, 293, -67, 194, -171, -7, -171, +-207, -84, -324, 46, -340, 144, -276, 153, +-152, 73, 7, -40, 137, -121, 181, -134, +128, -61, 42, 74, -8, 186, -30, 224, +-48, 153, -65, -22, -55, -203, -38, -310, +-51, -294, -109, -146, -166, 86, -172, 294, +-125, 391, -46, 356, 34, 171, 116, -86, +178, -293, 176, -395, 88, -355, -58, -171, +-194, 50, -242, 225, -210, 322, -131, 310, +-39, 188, 53, 35, 101, -95, 52, -181, +-43, -161, -129, -81, -138, -11, -63, 57, +29, 91, 104, 49, 146, -19, 115, -76, +12, -107, -135, -66, -259, 43, -308, 130, +-251, 170, -114, 172, 11, 76, 131, -62, +217, -166, 218, -218, 150, -170, 19, -24, +-115, 113, -189, 178, -220, 183, -224, 106, +-189, -32, -87, -127, 32, -145, 98, -82, +124, 69, 80, 187, 17, 197, -26, 130, +-82, 3, -109, -154, -81, -256, -15, -257, +42, -176, 33, -8, -40, 168, -132, 240, +-171, 229, -154, 177, -124, 70, -19, -31, +110, -90, 180, -114, 170, -91, 52, -41, +-94, -41, -189, -84, -214, -89, -182, -65, +-98, -9, 25, 101, 113, 213, 124, 299, +63, 334, -59, 234, -139, 6, -146, -238, +-133, -413, -89, -477, -20, -397, 63, -192, +117, 71, 108, 345, 43, 508, -35, 475, +-89, 310, -141, 94, -187, -117, -174, -272, +-112, -335, -26, -309, 52, -204, 73, -64, +67, 30, 56, 84, 36, 157, -6, 220, +-46, 247, -61, 220, -58, 135, -62, 24, +-103, -88, -148, -196, -141, -274, -91, -246, +-41, -113, 7, 41, 53, 152, 101, 185, +125, 142, 91, 67, 6, -24, -75, -104, +-134, -115, -171, -32, -181, 83, -166, 145, +-90, 142, 23, 74, 112, -22, 125, -99, +73, -149, 2, -151, -72, -74, -140, 45, +-171, 116, -122, 110, 7, 59, 120, 2, +130, -20, 53, 5, -75, 35, -175, 85, +-221, 138, -198, 114, -84, -9, 84, -167, +219, -283, 214, -305, 77, -206, -95, -43, +-219, 141, -240, 323, -182, 407, -75, 327, +85, 146, 189, -64, 166, -228, 35, -284, +-121, -245, -191, -150, -173, -6, -105, 139, +-25, 185, 54, 144, 111, 71, 70, -9, +-42, -51, -136, -56, -167, -61, -95, -38, +4, 19, 71, 52, 121, 48, 134, 42, +95, 30, -32, 13, -177, 10, -256, -31, +-247, -81, -165, -78, -75, -56, 26, -44, +155, -14, 224, 26, 196, 62, 88, 106, +-44, 121, -131, 95, -179, 89, -186, 100, +-158, 59, -79, -7, 21, -88, 56, -181, +24, -229, -44, -230, -107, -188, -117, -64, +-93, 132, -30, 292, 86, 365, 196, 341, +229, 199, 137, 5, -25, -168, -190, -310, +-298, -347, -312, -240, -259, -66, -132, 92, +28, 191, 138, 203, 165, 138, 122, 55, +61, -34, 22, -95, 7, -63, 6, 17, +2, 75, 0, 95, -23, 54, -97, -22, +-194, -77, -265, -104, -260, -99, -180, -38, +-50, 56, 94, 102, 225, 86, 298, 10, +268, -96, 145, -153, -26, -134, -180, -52, +-259, 90, -252, 251, -181, 345, -77, 318, +16, 168, 69, -62, 44, -285, -25, -413, +-94, -427, -108, -311, -49, -87, 43, 157, +146, 343, 213, 406, 207, 339, 115, 190, +-54, 30, -233, -103, -352, -182, -372, -187, +-273, -143, -100, -92, 105, -63, 267, -68, +319, -72, 257, -38, 89, 24, -94, 105, +-212, 176, -237, 211, -167, 191, -57, 110, +46, -13, 95, -124, 53, -168, -31, -142, +-111, -72, -134, 18, -91, 84, -24, 102, +52, 73, 80, -13, 55, -110, -4, -161, +-90, -145, -140, -71, -134, 47, -62, 166, +52, 245, 135, 277, 159, 223, 107, 84, +-9, -77, -148, -218, -287, -309, -330, -309, +-264, -232, -112, -92, 79, 87, 219, 236, +294, 293, 277, 265, 169, 178, 15, 44, +-150, -76, -253, -151, -264, -175, -211, -120, +-116, -17, -35, 57, 40, 89, 87, 77, +73, 13, 26, -68, -35, -122, -54, -143, +-35, -105, -7, 7, 30, 108, 70, 163, +103, 183, 88, 151, 6, 84, -93, 22, +-183, -30, -230, -64, -222, -57, -166, -55, +-51, -97, 88, -146, 209, -174, 242, -167, +186, -72, 88, 78, -19, 227, -110, 348, +-162, 376, -156, 256, -93, 37, -22, -193, +-1, -372, -33, -407, -69, -283, -76, -78, +-61, 145, -13, 313, 49, 322, 117, 185, +156, -16, 121, -206, 25, -288, -81, -212, +-139, -36, -153, 161, -130, 327, -83, 360, +-26, 230, 30, 20, 41, -199, -8, -346, +-57, -338, -69, -212, -41, -41, 6, 136, +49, 233, 89, 193, 92, 68, 47, -62, +-60, -147, -165, -112, -194, 22, -152, 164, +-58, 272, 47, 290, 112, 163, 126, -61, +66, -287, -55, -442, -175, -445, -233, -279, +-185, -31, -83, 224, 46, 435, 162, 501, +226, 405, 227, 207, 120, -40, -52, -250, +-203, -350, -291, -345, -286, -263, -198, -107, +-51, 56, 120, 161, 224, 206, 227, 186, +114, 108, -49, 33, -164, -28, -206, -80, +-146, -83, -28, -42, 108, -6, 216, 16, +213, 27, 100, 11, -71, 0, -215, 19, +-265, 42, -243, 72, -143, 104, -2, 86, +131, 2, 222, -120, 208, -239, 128, -294, +32, -233, -44, -68, -81, 150, -103, 364, +-93, 471, -54, 404, -14, 192, 9, -95, +-20, -351, -58, -464, -72, -407, -69, -224, +-41, 18, -9, 221, 57, 293, 127, 226, +148, 84, 101, -61, 2, -123, -81, -74, +-127, 39, -137, 162, -103, 230, -36, 196, +35, 59, 54, -119, -11, -270, -120, -334, +-206, -281, -198, -147, -105, 10, 42, 147, +215, 221, 341, 215, 353, 157, 200, 84, +-63, 29, -316, 11, -444, 27, -420, 39, +-276, 29, -60, -8, 152, -83, 268, -175, +244, -246, 103, -260, -51, -192, -119, -46, +-87, 132, 5, 285, 86, 370, 129, 355, +91, 229, -30, 44, -183, -134, -290, -256, +-263, -281, -120, -219, 50, -114, 174, -9, +219, 62, 187, 72, 88, 34, -43, -11, +-131, -34, -149, -12, -89, 54, -9, 121, +42, 166, 82, 181, 96, 149, 84, 74, +34, -23, -48, -119, -124, -200, -172, -236, +-178, -229, -134, -181, -47, -75, 92, 63, +220, 180, 276, 254, 236, 265, 105, 196, +-28, 85, -137, -27, -198, -106, -186, -125, +-116, -82, -17, -35, 41, -22, 28, -51, +-23, -123, -78, -186, -78, -175, -29, -75, +44, 93, 141, 285, 198, 398, 202, 370, +121, 208, -25, -37, -156, -276, -232, -393, +-226, -349, -171, -178, -94, 49, -2, 219, +51, 255, 55, 160, 17, -11, -28, -182, +-16, -245, 26, -157, 92, 20, 141, 208, +138, 321, 92, 288, -24, 133, -166, -71, +-286, -250, -326, -316, -255, -235, -116, -66, +45, 99, 175, 199, 235, 187, 223, 76, +128, -61, 5, -166, -88, -183, -124, -79, +-100, 94, -61, 242, -15, 306, 17, 251, +23, 90, -4, -111, -58, -286, -100, -380, +-105, -338, -73, -181, -15, 14, 46, 184, +110, 280, 167, 278, 187, 204, 154, 92, +71, -21, -21, -87, -106, -93, -155, -70, +-174, -52, -153, -44, -84, -57, -8, -76, +57, -75, 92, -50, 105, 12, 115, 101, +122, 170, 115, 178, 80, 121, 22, 10, +-40, -122, -105, -221, -148, -243, -159, -169, +-117, -10, -11, 176, 100, 310, 175, 343, +183, 249, 125, 54, 15, -180, -121, -369, +-225, -445, -250, -370, -172, -163, -9, 100, +154, 326, 255, 443, 269, 413, 176, 258, +21, 41, -152, -160, -265, -278, -270, -283, +-178, -195, -42, -81, 59, 16, 95, 65, +75, 53, 12, 6, -49, -34, -78, -35, +-51, 11, 42, 92, 117, 163, 142, 187, +90, 153, -11, 64, -111, -59, -209, -169, +-255, -233, -230, -230, -130, -148, 14, -21, +123, 104, 183, 190, 193, 213, 158, 156, +102, 40, 6, -88, -65, -182, -92, -191, +-90, -104, -72, 33, -87, 164, -89, 237, +-71, 206, -42, 79, -1, -90, 33, -233, +88, -286, 138, -217, 143, -72, 113, 74, +47, 176, -3, 200, -26, 146, -48, 62, +-50, -2, -45, -16, -19, 23, -5, 66, +-13, 53, -22, -21, -18, -124, 21, -220, +62, -247, 84, -173, 100, -23, 97, 155, +71, 283, 19, 296, -47, 194, -81, 37, +-72, -116, -33, -202, -3, -185, 19, -94, +36, 20, 40, 104, 35, 103, 17, 22, +6, -77, 5, -144, -2, -145, -32, -68, +-71, 65, -89, 195, -68, 273, -15, 263, +45, 155, 84, -9, 105, -177, 89, -307, +20, -351, -68, -289, -145, -145, -163, 46, +-131, 231, -64, 346, 3, 356, 53, 266, +81, 94, 62, -108, 12, -263, -39, -327, +-64, -288, -40, -155, 12, 15, 48, 157, +57, 234, 24, 228, -44, 140, -128, 19, +-185, -79, -184, -134, -114, -126, 13, -69, +134, -4, 203, 47, 216, 66, 161, 49, +52, 12, -63, -19, -155, -37, -174, -39, +-125, -15, -36, 9, 55, 23, 110, 35, +127, 32, 83, 15, -1, 0, -84, -18, +-133, -30, -103, -26, -14, -12, 93, -6, +198, 5, 236, 24, 197, 32, 84, 29, +-59, 18, -150, 0, -173, -2, -101, 14, +-1, 23, 79, 26, 120, 26, 85, 0, +15, -48, -54, -96, -84, -125, -30, -111, +65, -48, 157, 34, 187, 111, 140, 165, +60, 169, -49, 111, -120, 25, -147, -59, +-119, -115, -41, -123, 11, -97, 32, -65, +14, -27, -21, 5, -29, 8, -14, 6, +34, 18, 88, 51, 122, 97, 125, 128, +65, 113, -23, 59, -120, -13, -190, -101, +-206, -168, -190, -172, -136, -119, -60, -31, +31, 62, 106, 116, 145, 125, 153, 100, +125, 43, 76, -26, 14, -67, -60, -65, +-111, -40, -124, -6, -110, 16, -88, 20, +-72, 16, -60, 9, -53, -7, -35, -9, +-19, 13, 13, 35, 74, 45, 138, 44, +171, 24, 148, -9, 89, -48, 9, -94, +-72, -122, -133, -113, -154, -68, -114, 5, +-24, 102, 62, 194, 107, 243, 101, 222, +58, 121, -6, -37, -65, -202, -75, -321, +-21, -350, 95, -262, 216, -79, 275, 136, +242, 305, 134, 377, -28, 330, -193, 187, +-302, 1, -305, -174, -192, -278, -14, -287, +167, -219, 283, -111, 321, 4, 286, 97, +181, 153, 44, 176, -80, 166, -156, 124, +-168, 68, -147, 1, -104, -78, -45, -143, +11, -173, 57, -163, 63, -111, 64, -28, +63, 52, 70, 114, 77, 150, 41, 145, +0, 103, -38, 46, -68, -19, -80, -76, +-84, -106, -49, -112, 3, -93, 39, -45, +48, 17, 9, 63, -25, 87, -64, 73, +-102, 13, -113, -55, -116, -100, -71, -113, +-2, -71, 67, 19, 129, 114, 160, 184, +169, 197, 116, 132, 4, 20, -122, -95, +-236, -192, -272, -234, -246, -196, -167, -107, +-29, 0, 109, 99, 220, 152, 253, 156, +218, 137, 143, 93, 52, 38, -20, 4, +-95, -11, -145, -33, -145, -63, -125, -103, +-84, -144, -31, -147, 36, -107, 121, -35, +186, 68, 211, 167, 178, 201, 123, 155, +53, 47, -25, -87, -81, -174, -103, -166, +-76, -81, -22, 62, 29, 200, 56, 242, +72, 161, 82, -13, 77, -212, 62, -334, +46, -314, 35, -172, 43, 33, 49, 228, +38, 314, 27, 253, 25, 100, 26, -58, +6, -138, -17, -97, -36, 18, -42, 130, +-38, 163, -37, 67, -23, -147, 17, -373, +70, -475, 97, -381, 92, -99, 64, 269, +15, 577, -47, 702, -104, 581, -138, 242, +-121, -183, -53, -530, 27, -675, 77, -581, +87, -304, 64, 29, 18, 294, -37, 415, +-86, 360, -96, 180, -71, -13, -37, -137, +-26, -153, -28, -71, -23, 50, -13, 143, +14, 155, 36, 71, 49, -76, 55, -219, +27, -294, -23, -273, -80, -155, -114, 18, +-92, 188, -45, 296, 24, 306, 82, 218, +123, 75, 139, -62, 86, -144, 8, -152, +-77, -97, -125, -18, -114, 35, -76, 26, +1, -44, 83, -142, 150, -221, 184, -226, +149, -126, 85, 60, 5, 278, -58, 430, +-72, 447, -64, 317, -9, 75, 56, -204, +114, -416, 145, -483, 124, -392, 88, -179, +31, 68, -24, 236, -56, 280, -69, 208, +-36, 66, 19, -65, 82, -107, 135, -46, +144, 82, 128, 200, 70, 221, -6, 117, +-74, -71, -114, -279, -91, -415, -34, -393, +42, -213, 104, 52, 127, 312, 104, 456, +33, 424, -50, 243, -111, -20, -125, -268, +-79, -388, -9, -339, 60, -166, 101, 69, +93, 270, 40, 343, -43, 280, -116, 109, +-156, -116, -138, -294, -75, -352, 0, -287, +70, -122, 113, 91, 114, 261, 80, 331, +26, 289, -36, 140, -79, -49, -104, -189, +-123, -244, -135, -207, -131, -87, -107, 49, +-57, 131, 20, 141, 108, 69, 188, -49, +232, -132, 208, -145, 110, -90, -27, 31, +-168, 162, -257, 229, -256, 205, -161, 96, +-14, -63, 130, -194, 224, -242, 225, -211, +151, -107, 47, 28, -38, 122, -65, 147, +-34, 114, 27, 41, 81, -25, 96, -46, +67, -32, -5, 2, -68, 43, -95, 57, +-70, 33, 14, -4, 106, -43, 185, -70, +214, -63, 183, -40, 106, -23, 2, -3, +-69, 8, -87, 5, -52, 14, 12, 40, +52, 64, 66, 79, 41, 70, -13, 21, +-55, -37, -74, -80, -29, -106, 50, -91, +133, -37, 182, 16, 167, 43, 122, 44, +35, 13, -58, -24, -125, -35, -160, -19, +-138, 21, -99, 78, -60, 101, -19, 66, +22, -5, 73, -80, 90, -122, 86, -99, +72, -21, 44, 75, 23, 152, -25, 153, +-74, 57, -107, -93, -129, -228, -137, -287, +-138, -231, -103, -67, -27, 151, 63, 345, +143, 429, 166, 348, 141, 131, 81, -134, +-16, -357, -110, -456, -174, -389, -160, -185, +-82, 75, 12, 290, 73, 373, 76, 303, +40, 130, -28, -68, -95, -219, -110, -264, +-45, -184, 80, -27, 201, 130, 252, 213, +218, 189, 119, 88, -4, -36, -121, -138, +-189, -180, -175, -144, -100, -53, -13, 34, +41, 73, 64, 48, 81, -13, 122, -59, +161, -57, 183, 2, 187, 102, 170, 204, +113, 245, 7, 187, -112, 40, -199, -147, +-208, -304, -147, -367, -53, -309, 59, -144, +173, 76, 253, 266, 268, 348, 208, 300, +106, 151, -3, -42, -87, -200, -142, -260, +-167, -205, -125, -54, -46, 119, 37, 233, +89, 238, 97, 134, 83, -48, 47, -233, +-2, -333, -56, -313, -75, -177, -37, 32, +14, 229, 59, 341, 75, 338, 61, 220, +35, 40, -26, -116, -91, -196, -138, -189, +-136, -105, -94, -5, -59, 47, -28, 31, +-12, -55, 14, -170, 42, -227, 52, -177, +75, -32, 98, 179, 102, 378, 65, 467, +-22, 398, -104, 180, -160, -124, -171, -390, +-148, -510, -103, -468, -16, -278, 58, -6, +114, 224, 134, 333, 123, 305, 116, 163, +91, -2, 46, -94, -20, -91, -84, -18, +-112, 89, -116, 151, -80, 106, -11, -15, +71, -166, 149, -277, 168, -276, 134, -166, +65, -7, -6, 147, -42, 238, -54, 220, +-23, 120, 37, -1, 95, -93, 125, -101, +106, -27, 62, 68, 16, 141, -14, 154, +-21, 76, -22, -67, -7, -214, 15, -318, +24, -328, 28, -216, 30, -35, 53, 170, +86, 349, 116, 427, 128, 366, 114, 200, +76, -29, 11, -250, -68, -372, -131, -369, +-160, -252, -147, -54, -90, 141, -16, 241, +58, 229, 113, 125, 129, -29, 104, -144, +65, -169, 26, -107, -1, 27, -12, 166, +-16, 231, -28, 201, -55, 95, -88, -53, +-125, -180, -131, -228, -112, -199, -68, -116, +-5, -15, 55, 53, 100, 72, 109, 64, +94, 42, 63, 28, 22, 50, -11, 92, +-53, 121, -89, 118, -103, 62, -101, -44, +-75, -151, -45, -227, -9, -246, 19, -187, +35, -64, 43, 76, 37, 192, 52, 248, +84, 219, 116, 132, 127, 25, 93, -74, +29, -128, -54, -126, -134, -93, -181, -55, +-177, -35, -105, -42, -4, -57, 95, -55, +180, -18, 226, 54, 242, 147, 203, 216, +127, 220, 34, 142, -52, -1, -106, -161, +-139, -280, -131, -310, -81, -240, -6, -91, +73, 88, 115, 227, 135, 275, 134, 236, +107, 131, 65, 6, 7, -92, -23, -135, +-23, -124, -2, -79, 27, -27, 40, -2, +57, -10, 50, -35, 12, -63, -37, -72, +-76, -41, -69, 19, -33, 92, 11, 161, +54, 195, 76, 174, 78, 104, 44, -9, +-11, -139, -49, -230, -61, -256, -37, -214, +-15, -103, -6, 41, -4, 160, -7, 219, +-17, 202, -36, 113, -38, 1, -7, -84, +32, -122, 47, -93, 29, -14, -7, 58, +-35, 83, -58, 50, -68, -37, -59, -128, +-24, -167, 21, -146, 45, -67, 42, 60, +24, 174, 6, 222, -11, 198, -27, 104, +-47, -21, -46, -107, -33, -145, -12, -138, +8, -80, 29, -6, 62, 33, 86, 35, +88, 11, 63, -25, 28, -32, 5, -4, +-16, 31, -39, 80, -47, 125, -43, 116, +-15, 56, 15, -33, 42, -124, 66, -179, +87, -174, 103, -125, 81, -39, 48, 72, +20, 151, 6, 167, 16, 136, 31, 67, +45, -11, 60, -62, 59, -82, 25, -71, +-32, -25, -74, 15, -87, 14, -73, -11, +-21, -45, 40, -73, 116, -60, 172, -13, +182, 43, 141, 101, 63, 135, -21, 107, +-97, 33, -136, -46, -136, -113, -96, -143, +-22, -115, 33, -53, 55, 23, 57, 99, +43, 133, 29, 116, 16, 62, 18, -16, +20, -91, 18, -133, 7, -133, -30, -96, +-52, -17, -56, 74, -49, 141, -35, 172, +-23, 149, -9, 70, -6, -28, -14, -113, +-25, -168, -33, -167, -15, -107, 16, -30, +49, 37, 84, 83, 96, 84, 91, 56, +51, 29, -13, 3, -82, -1, -141, 26, +-163, 53, -155, 58, -105, 40, -17, -6, +75, -66, 148, -111, 181, -131, 170, -120, +134, -63, 78, 18, 23, 90, -27, 141, +-57, 155, -67, 122, -79, 60, -81, -15, +-73, -89, -46, -130, -5, -119, 43, -77, +87, -23, 128, 32, 153, 60, 147, 56, +112, 29, 66, -17, 27, -51, -10, -44, +-39, -6, -62, 39, -66, 81, -50, 100, +-34, 75, -23, 24, -6, -42, 15, -102, +39, -116, 53, -88, 72, -47, 104, 0, +133, 44, 148, 56, 117, 42, 54, 21, +-33, -1, -127, 0, -202, 28, -241, 58, +-210, 70, -114, 57, 12, 6, 128, -72, +199, -141, 226, -178, 208, -162, 139, -75, +43, 48, -56, 158, -116, 229, -145, 228, +-158, 150, -150, 27, -124, -101, -73, -186, +-27, -195, 7, -134, 44, -46, 88, 40, +130, 94, 144, 81, 123, 22, 78, -38, +12, -75, -58, -65, -121, -5, -150, 69, +-126, 128, -61, 150, 7, 117, 38, 35, +48, -56, 40, -132, 26, -174, 14, -167, +15, -123, 45, -59, 87, 15, 116, 77, +104, 115, 50, 139, -10, 145, -64, 117, +-101, 70, -104, 13, -78, -48, -11, -101, +57, -136, 101, -153, 110, -141, 101, -97, +94, -40, 65, 30, 29, 107, -1, 170, +-14, 193, -6, 170, -3, 94, -6, -21, +5, -127, 21, -197, 30, -211, 18, -148, +-6, -31, -23, 85, -24, 156, -1, 166, +18, 113, 56, 30, 106, -46, 136, -93, +120, -90, 53, -42, -35, 5, -110, 24, +-152, 10, -154, -24, -112, -47, -27, -34, +69, 12, 117, 73, 116, 125, 82, 120, +36, 46, -7, -61, -46, -159, -66, -202, +-56, -154, -24, -36, -1, 101, 1, 206, +-6, 230, -7, 151, -12, 10, -13, -130, +-23, -217, -27, -211, -15, -117, -10, 12, +-14, 129, -16, 193, 0, 174, 28, 91, +45, -11, 46, -96, 34, -138, 13, -122, +-7, -77, -43, -33, -69, 10, -69, 41, +-48, 58, -10, 73, 25, 82, 60, 78, +85, 62, 98, 23, 88, -44, 58, -117, +31, -156, 9, -149, -18, -89, -40, 12, +-56, 113, -48, 178, -12, 184, 25, 121, +56, 11, 77, -97, 96, -169, 93, -186, +70, -138, 35, -48, 9, 43, 6, 112, +14, 134, 19, 104, 18, 49, 17, -3, +4, -36, -21, -48, -33, -41, -16, -28, +23, -16, 69, -10, 92, -17, 87, -25, +61, -16, 19, 1, -29, 17, -66, 31, +-67, 38, -43, 29, -5, 15, 23, 2, +33, -7, 35, 0, 26, 15, 9, 18, +-12, 10, -25, -7, -18, -31, -8, -55, +4, -67, 12, -63, 0, -38, -15, 4, +-45, 35, -78, 55, -93, 71, -78, 75, +-27, 67, 37, 54, 105, 32, 144, 0, +130, -30, 60, -64, -58, -97, -173, -108, +-229, -96, -212, -71, -117, -25, 21, 28, +159, 74, 239, 112, 223, 127, 122, 107, +-32, 68, -167, 27, -232, -22, -206, -63, +-98, -82, 46, -89, 161, -83, 202, -63, +159, -46, 64, -24, -29, 14, -79, 51, +-74, 80, -35, 104, 21, 102, 55, 67, +45, 16, 7, -46, -27, -101, -23, -113, +33, -83, 110, -27, 174, 47, 190, 97, +140, 91, 30, 38, -109, -45, -211, -134, +-234, -175, -163, -139, -22, -48, 146, 76, +290, 198, 356, 254, 314, 230, 172, 137, +-21, -13, -189, -164, -279, -257, -280, -279, +-187, -227, -38, -107, 117, 34, 214, 152, +227, 228, 168, 233, 70, 173, -22, 85, +-86, -15, -104, -105, -72, -152, -15, -154, +29, -120, 39, -58, 13, 7, -26, 46, +-57, 64, -68, 66, -55, 42, -11, 15, +47, -1, 78, -13, 66, -15, 9, -8, +-56, -8, -99, -8, -99, 6, -67, 21, +-10, 30, 62, 39, 102, 32, 85, 3, +20, -29, -68, -73, -142, -109, -172, -108, +-149, -75, -69, -25, 47, 43, 160, 114, +205, 161, 182, 170, 105, 132, -5, 49, +-107, -50, -180, -142, -200, -210, -160, -221, +-71, -160, 32, -54, 110, 66, 159, 170, +163, 218, 124, 196, 70, 124, 7, 20, +-39, -80, -50, -134, -38, -139, -15, -109, +9, -62, 32, -18, 31, 12, 16, 33, +9, 40, 19, 40, 53, 55, 96, 74, +113, 73, 97, 42, 54, -16, -7, -87, +-57, -142, -75, -154, -47, -122, 17, -49, +99, 52, 152, 140, 146, 181, 93, 174, +16, 118, -66, 33, -116, -51, -112, -122, +-66, -164, 14, -163, 92, -126, 132, -69, +121, -1, 78, 64, 17, 109, -43, 130, +-69, 125, -61, 94, -29, 51, 9, 10, +17, -29, -10, -56, -47, -72, -72, -84, +-67, -94, -32, -95, 35, -85, 93, -55, +121, 2, 102, 70, 26, 130, -69, 169, +-148, 169, -177, 116, -150, 28, -75, -66, +11, -141, 79, -171, 113, -147, 99, -86, +48, -10, -8, 54, -60, 80, -100, 64, +-113, 27, -92, -14, -39, -34, 20, -12, +71, 32, 90, 74, 74, 103, 34, 93, +-17, 34, -57, -51, -73, -133, -61, -178, +-36, -158, -4, -79, 24, 21, 40, 116, +51, 167, 62, 146, 60, 71, 54, -23, +45, -104, 30, -126, 6, -75, -18, 10, +-31, 88, -27, 125, -4, 95, 19, 4, +39, -105, 61, -181, 76, -186, 80, -104, +75, 22, 57, 135, 23, 202, -15, 187, +-40, 92, -48, -32, -25, -131, 40, -168, +109, -118, 149, -10, 138, 90, 73, 139, +-19, 120, -102, 29, -146, -85, -130, -169, +-49, -189, 62, -123, 149, 5, 190, 128, +175, 203, 105, 210, 13, 140, -73, 21, +-127, -94, -134, -168, -97, -179, -48, -127, +-15, -50, 4, 20, 12, 72, 24, 87, +53, 63, 87, 31, 102, 9, 98, -2, +58, 6, -21, 24, -112, 25, -180, 15, +-207, -3, -180, -40, -93, -74, 24, -82, +135, -66, 202, -22, 187, 42, 91, 89, +-35, 101, -148, 81, -209, 21, -198, -61, +-117, -119, -1, -133, 105, -88, 171, 12, +154, 124, 78, 195, -20, 198, -116, 122, +-170, -26, -153, -182, -78, -283, 21, -293, +107, -192, 146, -12, 124, 173, 65, 299, +-1, 322, -58, 229, -70, 63, -39, -107, +14, -226, 55, -251, 63, -182, 31, -70, +-19, 32, -42, 89, -29, 83, 24, 32, +103, -14, 157, -25, 144, 1, 75, 56, +-30, 103, -126, 103, -153, 48, -93, -39, +20, -127, 145, -168, 226, -134, 216, -52, +136, 53, 27, 138, -84, 158, -160, 108, +-171, 18, -129, -78, -52, -140, 49, -136, +134, -77, 185, 6, 208, 85, 183, 129, +111, 122, 18, 78, -76, 17, -156, -45, +-199, -87, -188, -101, -133, -96, -35, -76, +78, -42, 148, -5, 165, 38, 147, 81, +105, 105, 49, 106, -4, 85, -53, 44, +-92, -14, -110, -63, -113, -93, -112, -103, +-82, -84, -28, -52, 15, -18, 45, 19, +63, 47, 66, 61, 53, 65, 30, 60, +-16, 45, -55, 27, -58, 1, -38, -36, +-17, -65, 5, -76, 22, -71, 17, -42, +-13, 6, -65, 46, -113, 66, -124, 66, +-92, 37, -37, -7, 42, -38, 135, -45, +202, -30, 214, 7, 162, 46, 51, 57, +-73, 37, -165, -14, -228, -78, -236, -115, +-176, -104, -61, -54, 65, 27, 169, 111, +224, 155, 224, 145, 186, 84, 114, -18, +22, -117, -46, -170, -66, -174, -68, -123, +-77, -27, -97, 72, -103, 136, -79, 158, +-13, 130, 68, 64, 145, -8, 209, -74, +219, -113, 155, -108, 47, -69, -53, -23, +-114, 26, -124, 56, -95, 57, -39, 37, +34, 7, 99, -24, 110, -36, 65, -28, +8, -16, -27, 1, -34, 21, -19, 29, +11, 25, 42, 27, 71, 25, 73, 17, +40, 8, -2, -15, -33, -52, -53, -83, +-63, -99, -54, -85, -29, -27, 11, 55, +45, 129, 46, 175, 16, 164, -2, 88, +-9, -15, -15, -114, -18, -183, -8, -189, +10, -133, 21, -47, 17, 45, -15, 111, +-39, 120, -37, 88, -33, 46, -40, 10, +-33, -12, -14, -11, 5, -5, 16, -8, +16, -18, 10, -39, 21, -61, 33, -57, +16, -30, -5, 6, -20, 43, -34, 61, +-47, 44, -49, 5, -43, -28, -21, -44, +14, -24, 33, 26, 41, 75, 54, 98, +60, 77, 38, 2, 3, -103, -35, -184, +-59, -208, -50, -152, -18, -27, 13, 122, +40, 239, 57, 281, 54, 220, 46, 75, +42, -92, 36, -223, 19, -275, -7, -227, +-50, -102, -81, 37, -66, 147, -19, 192, +35, 162, 90, 89, 126, 16, 121, -34, +87, -52, 33, -46, -27, -42, -64, -53, +-61, -72, -38, -89, -5, -79, 20, -21, +15, 60, -7, 131, -19, 168, -9, 146, +24, 65, 87, -40, 144, -126, 160, -162, +130, -128, 51, -45, -70, 42, -183, 97, +-244, 99, -237, 47, -144, -22, 15, -67, +177, -73, 282, -28, 301, 45, 208, 100, +51, 107, -107, 71, -221, -1, -258, -81, +-194, -126, -70, -120, 46, -73, 128, -2, +145, 56, 95, 78, 26, 68, -29, 35, +-59, 1, -44, -11, 4, 1, 39, 21, +30, 40, -14, 42, -80, 12, -125, -32, +-107, -67, -41, -90, 53, -90, 143, -56, +179, -11, 129, 33, 27, 71, -82, 86, +-165, 86, -192, 83, -158, 66, -80, 27, +35, -19, 151, -73, 206, -129, 183, -157, +98, -148, -13, -101, -109, -11, -146, 95, +-125, 177, -66, 211, 15, 183, 70, 95, +73, -17, 44, -111, 12, -171, -15, -176, +-21, -128, 2, -60, 41, 7, 84, 59, +109, 76, 79, 69, 6, 56, -67, 39, +-120, 23, -136, 19, -98, 16, -18, 11, +76, 5, 164, -12, 196, -37, 155, -61, +67, -85, -36, -102, -126, -94, -160, -54, +-110, 11, -7, 93, 104, 168, 173, 204, +155, 180, 67, 95, -33, -33, -121, -159, +-161, -234, -125, -230, -27, -149, 88, -20, +180, 98, 213, 164, 162, 164, 63, 96, +-52, -3, -150, -77, -191, -88, -155, -44, +-63, 32, 47, 92, 129, 96, 145, 45, +99, -41, 31, -128, -31, -166, -60, -133, +-36, -45, 13, 71, 48, 160, 49, 178, +16, 122, -49, 26, -110, -74, -133, -139, +-110, -135, -33, -71, 82, 19, 180, 97, +207, 130, 153, 102, 31, 28, -100, -61, +-185, -133, -200, -154, -153, -117, -62, -42, +34, 51, 97, 128, 118, 157, 108, 134, +74, 75, 27, -3, -11, -74, -46, -108, +-64, -102, -59, -62, -47, -9, -38, 26, +-23, 24, -3, -1, 12, -36, 25, -63, +30, -49, 25, 7, 29, 82, 49, 150, +59, 176, 55, 129, 28, 28, -22, -96, +-76, -208, -109, -257, -110, -217, -71, -107, +5, 41, 80, 177, 127, 241, 146, 215, +134, 119, 88, -14, 21, -129, -47, -172, +-100, -136, -117, -42, -91, 70, -43, 135, +15, 124, 70, 49, 95, -62, 89, -166, +65, -200, 35, -149, 12, -33, 10, 108, +14, 215, 12, 235, 11, 171, 10, 55, +-4, -78, -24, -164, -41, -169, -52, -111, +-30, -32, 25, 31, 81, 44, 116, 10, +121, -33, 81, -60, 8, -46, -58, 22, +-94, 110, -88, 172, -51, 184, -3, 128, +28, 17, 52, -102, 71, -194, 63, -236, +28, -206, -13, -118, -43, -9, -50, 100, +-31, 179, -8, 200, 9, 168, 18, 96, +14, -7, -11, -99, -21, -145, -7, -138, +17, -76, 36, 21, 30, 103, -3, 127, +-43, 87, -74, -14, -96, -133, -86, -201, +-34, -183, 40, -83, 106, 73, 130, 218, +98, 283, 34, 245, -33, 117, -98, -55, +-143, -197, -137, -252, -85, -215, -15, -111, +56, 10, 104, 90, 116, 108, 95, 78, +44, 18, -28, -30, -79, -32, -79, 3, +-48, 55, -10, 105, 17, 119, 24, 84, +26, 18, 30, -66, 25, -146, 17, -189, +20, -183, 24, -133, 5, -39, -19, 74, +-27, 167, -9, 220, 34, 209, 62, 130, +60, 14, 38, -92, 18, -157, -5, -158, +-18, -100, -10, -23, 7, 38, 24, 60, +32, 34, 17, -18, -7, -56, -6, -59, +8, -18, 22, 56, 42, 122, 75, 139, +99, 102, 91, 23, 43, -70, -31, -134, +-86, -140, -97, -97, -80, -21, -46, 51, +6, 80, 49, 66, 70, 18, 78, -45, +74, -78, 63, -53, 60, 10, 49, 81, +12, 135, -39, 135, -83, 71, -116, -29, +-129, -134, -104, -203, -50, -193, 25, -109, +98, 9, 132, 122, 120, 193, 89, 189, +46, 118, -11, 16, -68, -80, -115, -129, +-137, -119, -117, -75, -69, -22, -25, 24, +11, 44, 36, 42, 45, 29, 36, 19, +30, 17, 45, 16, 70, 4, 81, -25, +44, -53, -37, -62, -122, -42, -169, 1, +-168, 51, -113, 76, -17, 67, 83, 27, +148, -35, 158, -84, 121, -90, 65, -44, +14, 32, -33, 95, -77, 105, -108, 61, +-106, -18, -77, -99, -33, -135, 9, -101, +54, -15, 111, 79, 155, 142, 151, 139, +98, 66, 29, -36, -49, -121, -118, -153, +-149, -118, -126, -37, -52, 55, 47, 120, +118, 134, 144, 93, 141, 31, 123, -27, +83, -74, 23, -87, -37, -72, -87, -50, +-96, -19, -89, 19, -77, 45, -36, 54, +39, 53, 114, 34, 152, 2, 148, -22, +104, -28, 38, -17, -30, 16, -91, 48, +-122, 49, -92, 16, -35, -39, 9, -101, +31, -132, 42, -102, 43, -24, 36, 76, +26, 157, 8, 177, 0, 125, 13, 26, +19, -74, -3, -127, -28, -108, -45, -38, +-57, 35, -62, 70, -57, 39, -38, -45, +1, -129, 44, -162, 57, -110, 53, 21, +46, 173, 25, 273, -19, 279, -66, 173, +-99, -7, -96, -180, -56, -279, -10, -277, +24, -183, 53, -48, 59, 66, 23, 130, +-27, 137, -52, 103, -38, 67, 3, 55, +38, 58, 25, 62, -13, 46, -42, -11, +-52, -93, -39, -159, -2, -181, 47, -147, +69, -60, 60, 41, 21, 117, -27, 149, +-46, 131, -32, 80, -9, 32, 18, 5, +38, -4, 34, -5, 14, -20, -12, -58, +-27, -100, -12, -129, 36, -127, 76, -68, +82, 37, 56, 143, 12, 204, -33, 192, +-56, 108, -50, -19, -15, -135, 39, -200, +72, -181, 72, -78, 49, 48, 20, 141, +-1, 162, -5, 101, 8, -12, 25, -119, +36, -166, 23, -132, -15, -22, -42, 110, +-35, 188, -1, 174, 43, 75, 69, -65, +67, -175, 33, -200, -10, -127, -47, 6, +-65, 141, -45, 203, -8, 152, 24, 27, +43, -111, 49, -197, 45, -182, 34, -73, +5, 74, -40, 185, -85, 201, -100, 108, +-82, -37, -33, -156, 38, -190, 92, -119, +104, 17, 69, 138, 10, 178, -50, 112, +-78, -28, -72, -168, -49, -227, -22, -172, +-2, -22, 2, 149, 0, 256, 4, 248, +7, 132, 17, -42, 33, -195, 43, -250, +32, -187, -1, -49, -61, 93, -122, 165, +-138, 134, -94, 29, -5, -83, 104, -141, +185, -108, 188, 15, 115, 160, -9, 246, +-129, 223, -188, 79, -155, -134, -60, -317, +47, -388, 114, -302, 107, -78, 44, 192, +-30, 395, -60, 445, -24, 309, 65, 47, +141, -217, 155, -371, 101, -354, -8, -176, +-129, 75, -205, 268, -203, 306, -120, 165, +16, -89, 145, -310, 219, -366, 222, -223, +166, 72, 63, 389, -41, 554, -103, 470, +-103, 155, -59, -260, -14, -589, 0, -671, +-15, -464, -38, -66, -56, 354, -41, 598, +15, 558, 100, 272, 177, -112, 204, -402, +151, -449, 40, -239, -73, 101, -155, 385, +-195, 456, -186, 258, -118, -119, -13, -486, +86, -659, 144, -527, 148, -132, 95, 354, +18, 705, -56, 761, -94, 500, -68, 42, +15, -404, 94, -650, 102, -598, 39, -292, +-66, 97, -158, 370, -193, 405, -156, 207, +-56, -98, 77, -327, 175, -345, 194, -148, +135, 177, 40, 467, -47, 547, -100, 359, +-107, -16, -88, -410, -43, -640, 4, -594, +20, -312, 3, 70, -22, 402, -28, 548, +-13, 445, 7, 163, 29, -143, 53, -335, +68, -339, 68, -178, 36, 44, -7, 229, +-34, 302, -38, 220, -45, 19, -68, -205, +-84, -345, -72, -342, -26, -203, 41, 14, +107, 231, 150, 378, 156, 394, 95, 267, +-15, 38, -111, -210, -140, -369, -95, -382, +-9, -255, 64, -36, 87, 195, 74, 341, +33, 327, -29, 161, -63, -78, -34, -279, +29, -330, 88, -219, 105, -8, 72, 219, +9, 359, -56, 325, -102, 121, -115, -146, +-67, -350, 34, -391, 133, -241, 177, 17, +143, 268, 44, 408, -63, 357, -144, 117, +-169, -188, -113, -406, 2, -440, 108, -267, +143, 32, 111, 315, 40, 471, -23, 430, +-56, 193, -62, -130, -46, -384, -3, -459, +40, -335, 49, -78, 18, 178, -27, 330, +-55, 323, -63, 159, -60, -71, -45, -236, +10, -252, 84, -117, 134, 91, 124, 250, +52, 279, -49, 176, -135, -33, -182, -267, +-177, -390, -95, -332, 41, -120, 164, 153, +192, 362, 129, 407, 24, 290, -79, 69, +-145, -190, -144, -370, -83, -373, 22, -212, +119, 26, 135, 232, 62, 324, -47, 276, +-120, 125, -127, -75, -66, -252, 32, -316, +131, -234, 182, -51, 130, 142, -4, 261, +-134, 275, -191, 189, -164, 25, -68, -166, +44, -298, 135, -291, 180, -147, 166, 66, +85, 243, -13, 314, -75, 269, -101, 108, +-109, -125, -116, -323, -91, -377, -13, -253, +88, -15, 152, 227, 165, 363, 129, 355, +56, 213, -37, -29, -120, -266, -159, -379, +-110, -314, 14, -122, 118, 93, 152, 239, +118, 269, 38, 202, -70, 66, -154, -91, +-169, -189, -82, -183, 88, -95, 230, 14, +251, 83, 148, 95, -21, 76, -188, 48, +-273, 2, -243, -47, -101, -64, 109, -50, +278, -24, 294, -11, 170, -2, -4, 27, +-156, 75, -232, 99, -213, 64, -121, -1, +7, -69, 131, -123, 183, -147, 150, -119, +77, -25, 6, 104, -59, 204, -107, 206, +-126, 106, -94, -28, -9, -148, 67, -211, +86, -180, 48, -64, -5, 90, -65, 201, +-106, 205, -97, 84, -27, -88, 84, -208, +181, -221, 191, -125, 94, 41, -47, 219, +-175, 320, -253, 275, -246, 90, -131, -160, +46, -345, 210, -378, 276, -263, 204, -49, +48, 191, -105, 377, -191, 416, -187, 277, +-96, 23, 30, -232, 133, -381, 159, -376, +88, -232, -34, -3, -104, 231, -96, 377, +-48, 356, 15, 176, 54, -75, 48, -279, +20, -349, -1, -265, -18, -67, -5, 158, +39, 316, 67, 328, 44, 179, -8, -53, +-64, -253, -74, -325, -23, -247, 36, -70, +76, 130, 90, 267, 55, 284, -35, 175, +-115, -9, -146, -182, -100, -266, 39, -227, +194, -103, 259, 53, 228, 190, 119, 253, +-71, 217, -256, 96, -338, -65, -277, -214, +-97, -289, 142, -247, 295, -107, 293, 87, +174, 268, -9, 347, -178, 284, -238, 99, +-157, -138, 11, -327, 192, -367, 267, -234, +179, -5, -10, 223, -201, 347, -342, 302, +-359, 112, -217, -130, 25, -302, 275, -322, +434, -169, 418, 72, 227, 267, -24, 333, +-250, 240, -392, 34, -391, -187, -228, -319, +14, -312, 220, -179, 302, 27, 225, 207, +51, 281, -120, 238, -212, 115, -194, -26, +-57, -140, 121, -191, 248, -175, 252, -103, +114, 3, -96, 89, -259, 133, -315, 146, +-267, 118, -113, 40, 94, -67, 249, -155, +294, -193, 236, -156, 86, -40, -80, 106, +-183, 229, -203, 275, -143, 201, -21, 22, +98, -183, 153, -322, 133, -333, 39, -187, +-79, 57, -157, 288, -167, 407, -104, 343, +36, 103, 177, -215, 237, -457, 213, -497, +120, -310, -20, 44, -137, 405, -175, 614, +-155, 582, -83, 287, 14, -166, 66, -581, +53, -763, 27, -636, 9, -253, 16, 231, +57, 616, 109, 761, 139, 604, 124, 205, +49, -255, -75, -573, -162, -621, -184, -409, +-155, -49, -82, 284, 9, 448, 80, 395, +123, 148, 141, -169, 110, -390, 55, -402, +20, -193, -1, 126, -47, 401, -78, 497, +-72, 378, -41, 99, -13, -243, -7, -496, +-29, -549, -53, -377, -44, -54, -23, 262, +6, 440, 65, 424, 138, 265, 161, 33, +100, -187, -22, -297, -123, -265, -152, -123, +-118, 46, -68, 156, -13, 168, 41, 108, +45, 28, -3, -58, -67, -132, -85, -160, +-19, -134, 102, -49, 183, 63, 177, 159, +112, 208, 6, 212, -133, 164, -269, 29, +-315, -162, -217, -320, -12, -354, 178, -231, +277, -12, 272, 224, 178, 377, 27, 384, +-130, 226, -239, -65, -229, -359, -79, -496, +91, -389, 165, -94, 146, 248, 88, 497, +-2, 536, -89, 349, -135, 9, -108, -369, +-1, -612, 123, -580, 156, -287, 91, 101, +3, 423, -72, 559, -115, 454, -117, 186, +-71, -142, 35, -416, 178, -481, 235, -274, +159, 66, 42, 337, -61, 442, -162, 326, +-237, 21, -238, -322, -159, -571, 8, -598, +205, -316, 314, 176, 306, 617, 244, 816, +116, 707, -91, 299, -291, -244, -381, -701, +-317, -920, -125, -780, 89, -304, 221, 281, +274, 702, 246, 821, 120, 622, -60, 199, +-187, -244, -204, -562, -113, -653, 30, -443, +116, -42, 123, 324, 106, 498, 39, 446, +-111, 210, -240, -99, -259, -356, -155, -497, +41, -429, 248, -138, 351, 222, 322, 487, +180, 560, -75, 417, -346, 107, -473, -245, +-379, -537, -117, -662, 179, -504, 356, -113, +361, 326, 233, 643, 18, 698, -201, 473, +-301, 83, -244, -333, -97, -655, 74, -722, +168, -461, 155, -10, 102, 430, 51, 677, +-30, 627, -108, 333, -127, -74, -102, -461, +-56, -679, 6, -587, 65, -222, 123, 234, +182, 589, 165, 675, 54, 464, -96, 71, +-216, -364, -250, -681, -161, -718, -2, -415, +162, 91, 296, 579, 311, 831, 147, 704, +-102, 268, -287, -285, -344, -753, -232, -934, +11, -714, 255, -150, 388, 513, 378, 974, +194, 1017, -114, 626, -372, -19, -459, -674, +-350, -1074, -93, -1041, 201, -572, 400, 151, +455, 799, 342, 1095, 82, 935, -207, 413, +-388, -254, -413, -800, -275, -979, -22, -746, +215, -214, 349, 395, 357, 784, 222, 791, +-31, 460, -255, -53, -345, -548, -301, -784, +-141, -635, 77, -211, 257, 309, 336, 711, +297, 779, 132, 501, -95, 30, -281, -462, +-354, -794, -304, -774, -144, -406, 71, 102, +277, 554, 387, 765, 322, 646, 106, 280, +-159, -170, -362, -561, -423, -731, -299, -550, +-44, -131, 251, 299, 468, 590, 489, 646, +277, 449, -66, 86, -396, -316, -586, -621, +-545, -682, -296, -448, 93, -61, 485, 302, +695, 540, 602, 586, 275, 442, -152, 151, +-529, -188, -677, -447, -533, -504, -188, -348, +245, -109, 594, 106, 648, 247, 388, 305, +-25, 262, -425, 105, -657, -98, -579, -238, +-227, -245, 235, -149, 639, -24, 784, 111, +573, 240, 131, 331, -349, 303, -712, 109, +-794, -166, -553, -403, -117, -519, 347, -485, +677, -279, 704, 76, 454, 463, 104, 733, +-243, 739, -490, 444, -510, -19, -305, -457, +-14, -731, 262, -755, 408, -486, 333, -36, +108, 398, -139, 656, -361, 618, -454, 314, +-306, -77, 14, -377, 357, -502, 575, -402, +559, -90, 306, 258, -51, 475, -406, 480, +-653, 248, -649, -112, -381, -430, 12, -594, +384, -548, 603, -262, 577, 170, 367, 531, +69, 699, -265, 628, -513, 319, -527, -112, +-329, -507, -34, -739, 260, -713, 431, -401, +409, 62, 227, 479, -47, 733, -325, 721, +-451, 431, -366, -22, -131, -481, 148, -770, +357, -747, 408, -402, 317, 90, 111, 541, +-165, 797, -367, 724, -390, 348, -261, -181, +-47, -664, 192, -876, 334, -699, 321, -223, +179, 320, -54, 741, -284, 872, -360, 630, +-250, 124, -35, -428, 202, -795, 364, -819, +376, -501, 231, 0, -21, 474, -293, 756, +-437, 723, -383, 387, -194, -86, 53, -493, +287, -674, 407, -586, 365, -278, 198, 122, +-52, 445, -282, 583, -358, 488, -257, 209, +-75, -131, 131, -379, 289, -462, 311, -399, +189, -199, -8, 65, -202, 280, -316, 383, +-278, 349, -126, 184, 56, -28, 215, -180, +306, -275, 291, -324, 190, -242, 34, -49, +-134, 146, -254, 285, -285, 328, -235, 239, +-119, 67, 45, -110, 177, -291, 236, -386, +219, -281, 121, -49, -31, 178, -149, 333, +-174, 358, -114, 229, 5, 25, 139, -171, +202, -326, 147, -339, 8, -176, -177, 43, +-334, 217, -366, 288, -211, 231, 68, 91, +334, -59, 483, -194, 447, -278, 220, -237, +-103, -94, -386, 82, -524, 233, -440, 295, +-159, 275, 169, 184, 379, 6, 412, -221, +261, -382, 0, -416, -233, -328, -349, -105, +-304, 165, -94, 371, 177, 498, 338, 471, +348, 243, 221, -68, -21, -319, -271, -478, +-400, -483, -388, -296, -221, -54, 78, 161, +343, 344, 443, 378, 381, 237, 195, 69, +-94, -53, -345, -146, -437, -152, -352, -80, +-112, -39, 182, 2, 363, 45, 370, -4, +246, -82, 21, -73, -226, -19, -369, 17, +-336, 68, -155, 98, 113, 86, 314, 91, +346, 80, 246, 20, 68, -26, -160, -41, +-337, -84, -355, -150, -214, -180, 30, -158, +279, -53, 394, 117, 325, 242, 152, 272, +-70, 218, -305, 89, -437, -86, -368, -246, +-131, -320, 162, -253, 384, -51, 424, 157, +309, 260, 113, 260, -123, 168, -334, 14, +-402, -154, -297, -282, -73, -296, 166, -171, +305, 27, 309, 188, 224, 278, 69, 289, +-153, 194, -321, 28, -337, -164, -194, -310, +49, -334, 278, -225, 374, -46, 318, 133, +147, 266, -118, 296, -380, 215, -486, 62, +-369, -110, -86, -215, 237, -211, 445, -137, +478, -35, 344, 72, 67, 141, -269, 137, +-495, 77, -501, -13, -300, -84, 32, -84, +332, -57, 471, -44, 432, -9, 236, 62, +-98, 109, -417, 96, -529, 40, -381, -38, +-67, -82, 269, -79, 476, -94, 470, -99, +284, -21, -42, 100, -397, 160, -589, 136, +-494, 67, -170, -7, 225, -38, 517, -48, +594, -82, 453, -93, 141, -39, -275, 22, +-623, 10, -679, -53, -428, -81, -13, -26, +384, 90, 609, 179, 582, 191, 355, 154, +11, 81, -361, -49, -573, -237, -494, -376, +-212, -339, 98, -132, 331, 125, 407, 314, +327, 398, 141, 347, -103, 166, -327, -92, +-384, -348, -235, -463, -3, -348, 211, -65, +334, 217, 326, 399, 200, 437, 1, 266, +-238, -43, -390, -337, -351, -520, -166, -496, +47, -219, 229, 185, 337, 500, 331, 640, +218, 561, 13, 211, -221, -254, -375, -610, +-361, -750, -219, -617, -13, -207, 216, 295, +402, 664, 439, 823, 263, 681, -59, 210, +-377, -341, -536, -703, -470, -815, -202, -651, +154, -218, 482, 298, 637, 689, 511, 856, +143, 675, -280, 184, -565, -336, -604, -680, +-401, -807, -70, -669, 273, -253, 523, 272, +559, 708, 327, 896, -39, 699, -350, 189, +-489, -360, -416, -740, -172, -872, 124, -684, +369, -180, 486, 441, 369, 908, 48, 997, +-289, 626, -472, -22, -462, -638, -271, -988, +28, -982, 315, -601, 497, 73, 509, 769, +301, 1157, -47, 1050, -356, 507, -516, -226, +-490, -853, -291, -1143, 15, -1023, 316, -528, +520, 214, 528, 904, 302, 1213, -39, 1016, +-339, 434, -501, -297, -465, -898, -231, -1135, +84, -959, 355, -422, 486, 320, 399, 944, +116, 1147, -204, 869, -422, 272, -458, -406, +-277, -899, 39, -1017, 341, -743, 501, -170, +452, 486, 187, 919, -182, 928, -489, 533, +-598, -60, -445, -614, -76, -907, 336, -818, +611, -385, 642, 228, 398, 767, -16, 990, +-417, 780, -638, 244, -591, -373, -284, -840, +132, -989, 456, -758, 566, -233, 434, 380, +115, 832, -237, 951, -463, 693, -479, 195, +-263, -322, 75, -686, 369, -782, 495, -586, +407, -170, 122, 276, -227, 566, -471, 611, +-519, 410, -345, 76, -13, -260, 316, -489, +489, -527, 468, -354, 250, -32, -75, 298, +-344, 508, -431, 525, -322, 353, -72, 72, +194, -243, 327, -490, 293, -565, 132, -442, +-96, -176, -295, 136, -350, 390, -234, 493, +-1, 446, 247, 277, 388, 12, 357, -238, +202, -369, -22, -369, -266, -254, -424, -45, +-413, 150, -230, 235, 45, 225, 297, 122, +397, -57, 324, -187, 149, -199, -72, -127, +-270, 22, -336, 222, -228, 320, -9, 244, +220, 81, 331, -125, 262, -308, 71, -352, +-139, -256, -313, -103, -380, 90, -282, 269, +-45, 302, 228, 195, 416, 74, 434, -21, +273, -79, 23, -78, -227, -71, -402, -96, +-435, -104, -280, -72, 1, -67, 284, -54, +445, 44, 419, 176, 217, 244, -77, 204, +-348, 53, -500, -148, -443, -271, -166, -269, +214, -196, 512, -53, 618, 179, 478, 372, +128, 389, -289, 210, -609, -71, -712, -325, +-520, -435, -78, -359, 384, -176, 666, 76, +681, 349, 424, 498, -15, 403, -427, 120, +-641, -193, -579, -406, -235, -438, 222, -293, +531, -59, 573, 185, 380, 378, 21, 423, +-357, 265, -586, -8, -580, -233, -333, -344, +86, -320, 460, -180, 606, 7, 525, 177, +273, 291, -74, 301, -384, 162, -537, -33, +-500, -177, -267, -247, 72, -236, 327, -122, +390, 49, 311, 177, 143, 229, -72, 205, +-243, 78, -303, -87, -224, -203, -24, -244, +195, -183, 297, -14, 258, 164, 124, 224, +-63, 196, -249, 116, -353, -28, -330, -165, +-165, -212, 88, -159, 298, -34, 374, 127, +311, 201, 153, 124, -51, 3, -219, -80, +-294, -123, -253, -107, -115, -22, 39, 75, +133, 142, 148, 152, 109, 43, 47, -137, +-9, -220, -49, -154, -57, -3, -38, 144, +-10, 239, 7, 233, 33, 126, 68, -55, +63, -272, 19, -392, -42, -307, -92, -57, +-100, 218, -44, 397, 25, 418, 66, 280, +79, 45, 62, -216, -5, -421, -77, -466, +-89, -313, -18, -30, 107, 246, 189, 400, +156, 399, 26, 269, -117, 69, -237, -165, +-290, -366, -221, -434, -31, -316, 208, -67, +388, 200, 395, 393, 206, 445, -58, 335, +-270, 89, -376, -225, -352, -492, -174, -564, +86, -389, 313, -48, 390, 335, 267, 607, +13, 623, -218, 377, -323, -14, -303, -422, +-165, -683, 57, -649, 274, -340, 380, 100, +319, 526, 97, 742, -175, 620, -366, 233, +-415, -231, -320, -617, -101, -762, 174, -576, +403, -163, 500, 328, 388, 734, 93, 857, +-240, 593, -464, 86, -528, -441, -407, -808, +-120, -875, 223, -618, 483, -139, 563, 420, +426, 864, 120, 974, -214, 685, -459, 145, +-536, -410, -418, -811, -146, -936, 171, -739, +419, -261, 509, 333, 397, 808, 141, 962, +-146, 714, -362, 206, -439, -339, -327, -730, +-87, -866, 163, -662, 329, -157, 364, 419, +250, 813, 34, 855, -194, 508, -354, -63, +-370, -582, -215, -866, 45, -833, 289, -435, +442, 211, 447, 781, 263, 1037, -54, 875, +-361, 338, -551, -351, -541, -882, -298, -1081, +72, -915, 398, -372, 568, 345, 539, 898, +302, 1089, -40, 895, -350, 371, -525, -282, +-492, -779, -257, -980, 46, -844, 291, -364, +430, 259, 401, 722, 211, 890, -44, 747, +-275, 302, -431, -294, -408, -749, -194, -911, +78, -722, 302, -204, 433, 420, 417, 851, +251, 956, -14, 728, -307, 169, -507, -510, +-510, -968, -328, -1024, -55, -692, 245, -79, +479, 562, 555, 939, 434, 954, 133, 625, +-246, 11, -527, -619, -574, -929, -399, -828, +-77, -411, 281, 162, 539, 655, 581, 841, +362, 696, -53, 269, -467, -308, -677, -754, +-598, -844, -261, -590, 203, -138, 618, 379, +812, 749, 686, 821, 248, 590, -319, 137, +-763, -377, -904, -725, -692, -776, -210, -564, +340, -165, 747, 311, 873, 676, 659, 778, +177, 576, -351, 149, -693, -318, -751, -648, +-531, -737, -122, -558, 321, -142, 633, 354, +694, 715, 464, 781, 44, 519, -365, 64, +-617, -403, -635, -713, -408, -778, -13, -545, +393, -72, 663, 434, 672, 745, 396, 744, +-35, 461, -430, 33, -656, -372, -647, -622, +-383, -652, 43, -430, 463, -20, 694, 371, +634, 555, 304, 493, -149, 256, -534, -61, +-695, -324, -561, -455, -176, -429, 307, -196, +658, 164, 718, 438, 444, 481, -42, 347, +-524, 94, -779, -215, -696, -450, -309, -532, +217, -429, 649, -131, 809, 252, 635, 511, +198, 563, -322, 455, -693, 199, -770, -148, +-538, -434, -107, -579, 337, -543, 613, -312, +631, 45, 406, 356, 23, 528, -346, 553, +-533, 385, -472, 73, -217, -266, 103, -500, +332, -554, 395, -391, 290, -70, 68, 258, +-179, 479, -331, 522, -325, 349, -177, 11, +51, -323, 236, -499, 292, -496, 230, -322, +103, 1, -61, 344, -196, 552, -232, 548, +-163, 353, -30, 26, 105, -298, 166, -508, +126, -586, 35, -479, -55, -167, -109, 228, +-110, 496, -54, 576, 41, 474, 134, 193, +170, -146, 117, -399, 11, -518, -86, -445, +-136, -135, -135, 250, -89, 468, -19, 471, +43, 287, 69, -48, 64, -377, 35, -565, +-2, -563, -12, -318, 33, 165, 89, 616, +103, 771, 78, 643, 2, 297, -108, -173, +-193, -597, -215, -799, -184, -734, -69, -387, +111, 146, 248, 587, 273, 737, 191, 604, +32, 279, -127, -129, -196, -465, -190, -604, +-128, -508, -1, -182, 134, 268, 173, 597, +110, 631, -15, 395, -147, 26, -200, -384, +-152, -710, -66, -782, 42, -543, 174, -48, +248, 518, 224, 900, 123, 905, -37, 590, +-199, 106, -265, -428, -232, -832, -160, -913, +-49, -644, 94, -148, 212, 384, 251, 709, +193, 687, 62, 416, -62, 56, -140, -301, +-177, -518, -172, -483, -111, -222, -11, 128, +115, 412, 211, 483, 193, 317, 82, 44, +-36, -243, -122, -470, -191, -549, -210, -391, +-130, -58, 54, 302, 250, 556, 320, 612, +216, 461, 15, 152, -184, -221, -317, -538, +-327, -664, -204, -522, 32, -179, 298, 201, +454, 482, 380, 582, 124, 473, -158, 181, +-350, -168, -413, -438, -345, -518, -162, -369, +100, -94, 351, 162, 457, 316, 367, 388, +149, 328, -79, 116, -260, -142, -365, -315, +-353, -339, -193, -230, 62, -60, 272, 90, +340, 228, 250, 331, 64, 276, -129, 61, +-249, -162, -277, -297, -209, -311, -32, -203, +189, -29, 315, 138, 289, 297, 164, 378, +0, 271, -158, 45, -291, -191, -342, -344, +-257, -365, -58, -249, 142, -89, 257, 88, +286, 292, 230, 390, 95, 308, -61, 112, +-186, -105, -251, -259, -203, -294, -65, -236, +59, -132, 123, 38, 163, 236, 158, 322, +70, 268, -71, 117, -200, -83, -254, -261, +-197, -350, -63, -326, 89, -209, 250, 23, +372, 292, 361, 480, 181, 493, -79, 312, +-317, 2, -463, -312, -465, -496, -315, -522, +-50, -390, 253, -103, 479, 244, 527, 485, +385, 507, 112, 334, -185, 60, -406, -200, +-479, -337, -368, -344, -97, -236, 222, -28, +433, 201, 432, 323, 222, 272, -75, 104, +-343, -132, -489, -308, -425, -335, -130, -227, +250, -43, 528, 197, 609, 426, 455, 491, +96, 331, -313, 16, -598, -316, -693, -522, +-542, -527, -155, -358, 298, -72, 612, 275, +699, 560, 530, 607, 170, 392, -222, 47, +-532, -275, -662, -480, -511, -512, -132, -366, +253, -116, 503, 194, 570, 439, 415, 484, +86, 317, -271, 67, -548, -178, -626, -370, +-401, -416, 19, -304, 405, -70, 625, 221, +630, 434, 381, 436, -33, 244, -446, -23, +-718, -286, -706, -473, -374, -477, 87, -276, +451, 51, 640, 367, 614, 542, 354, 510, +-45, 281, -409, -22, -600, -317, -526, -509, +-225, -521, 134, -327, 392, -34, 469, 226, +342, 406, 64, 430, -238, 285, -438, 58, +-429, -158, -188, -306, 159, -303, 404, -144, +453, 40, 325, 172, 75, 243, -208, 168, +-412, -30, -452, -203, -319, -270, -65, -231, +191, -84, 345, 122, 363, 255, 282, 314, +142, 273, -28, 104, -200, -106, -307, -232, +-290, -263, -175, -249, -26, -166, 112, -37, +214, 97, 241, 216, 185, 261, 61, 196, +-79, 68, -161, -54, -156, -151, -112, -207, +-62, -172, -5, -65, 44, 79, 88, 199, +122, 205, 123, 102, 82, -32, 23, -101, +-63, -127, -157, -124, -194, -101, -145, -52, +-39, 32, 84, 92, 166, 92, 168, 74, +112, 100, 28, 121, -51, 74, -98, -25, +-91, -135, -63, -195, -28, -159, 0, -86, +13, -22, 26, 51, 45, 129, 53, 159, +40, 130, 7, 68, -63, -28, -120, -78, +-121, -64, -72, -67, 23, -116, 162, -103, +249, 3, 216, 121, 89, 193, -101, 166, +-282, 56, -345, -65, -261, -167, -100, -262, +100, -269, 261, -101, 295, 159, 225, 345, +103, 384, -42, 268, -144, 41, -165, -199, +-167, -350, -145, -381, -55, -285, 55, -51, +121, 203, 154, 355, 123, 354, 3, 227, +-139, 7, -218, -198, -186, -296, -31, -314, +186, -228, 341, -14, 349, 239, 174, 389, +-117, 393, -381, 245, -484, -43, -386, -340, +-109, -514, 219, -516, 435, -303, 458, 89, +296, 480, 30, 685, -208, 618, -328, 275, +-323, -223, -187, -610, 7, -733, 151, -558, +218, -151, 220, 343, 128, 688, -20, 707, +-139, 413, -217, -64, -224, -491, -115, -676, +57, -556, 203, -201, 303, 227, 275, 546, +89, 610, -120, 400, -252, 40, -321, -307, +-284, -498, -114, -475, 81, -266, 231, 19, +327, 240, 315, 347, 176, 317, 2, 200, +-168, 42, -307, -95, -349, -188, -266, -241, +-79, -222, 159, -135, 339, -8, 353, 113, +225, 221, 28, 285, -179, 226, -310, 47, +-288, -184, -143, -346, 45, -329, 204, -151, +271, 72, 201, 260, 18, 388, -158, 354, +-236, 108, -216, -188, -136, -394, 7, -417, +164, -253, 257, 9, 251, 215, 143, 319, +-41, 326, -199, 193, -266, -1, -266, -144, +-177, -208, 12, -192, 211, -91, 325, -7, +319, -15, 154, -37, -104, 4, -293, 67, +-350, 119, -286, 149, -94, 137, 159, 81, +335, -22, 374, -164, 264, -265, 40, -197, +-185, -3, -317, 183, -354, 260, -279, 207, +-91, 21, 116, -227, 271, -372, 358, -330, +335, -102, 166, 237, -80, 547, -289, 618, +-374, 364, -309, -107, -119, -573, 122, -787, +310, -637, 356, -225, 242, 280, 17, 726, +-236, 883, -387, 581, -335, -26, -112, -579, +151, -842, 343, -715, 393, -274, 290, 287, +66, 734, -207, 872, -408, 594, -421, -2, +-246, -584, 11, -886, 235, -791, 330, -355, +286, 239, 160, 713, 10, 858, -133, 643, +-215, 153, -191, -425, -87, -801, 31, -767, +87, -363, 74, 181, 50, 612, 42, 744, +11, 529, -43, 83, -87, -440, -83, -783, +-21, -721, 49, -278, 75, 266, 77, 648, +75, 757, 39, 518, -15, 42, -61, -432, +-106, -682, -126, -601, -77, -240, -23, 199, +-4, 480, 40, 509, 112, 295, 160, -65, +169, -339, 106, -380, -51, -226, -206, 10, +-283, 218, -262, 315, -123, 221, 93, 4, +274, -198, 360, -249, 312, -133, 86, 45, +-222, 179, -413, 179, -400, 60, -228, -116, +40, -260, 293, -277, 433, -112, 408, 172, +199, 414, -142, 499, -440, 347, -528, -34, +-368, -445, -38, -676, 298, -644, 493, -330, +475, 195, 247, 709, -110, 929, -401, 740, +-473, 170, -305, -533, 1, -1013, 266, -1046, +350, -614, 252, 142, 61, 919, -145, 1281, +-245, 1021, -180, 255, -23, -671, 114, -1319, +177, -1337, 135, -692, 24, 316, -77, 1218, +-136, 1558, -142, 1116, -66, 100, 52, -989, +111, -1641, 103, -1510, 49, -620, -22, 609, +-58, 1557, -36, 1776, 3, 1146, 43, -47, +92, -1214, 91, -1799, -11, -1540, -156, -575, +-232, 648, -190, 1532, -47, 1676, 118, 1038, +238, -56, 281, -1068, 241, -1523, 103, -1251, +-120, -432, -327, 547, -392, 1230, -282, 1299, +-72, 761, 144, -91, 292, -846, 352, -1179, +303, -977, 114, -335, -171, 439, -376, 973, +-374, 1019, -209, 600, 21, -48, 220, -629, +311, -893, 265, -771, 125, -291, -81, 332, +-271, 760, -313, 775, -182, 417, 4, -89, +153, -515, 228, -684, 211, -555, 133, -198, +25, 273, -100, 624, -202, 637, -212, 336, +-157, -76, -80, -385, 19, -495, 125, -400, +199, -194, 227, 83, 186, 371, 56, 475, +-108, 315, -235, 11, -280, -226, -231, -326, +-82, -301, 109, -194, 261, -16, 314, 241, +237, 424, 46, 358, -170, 81, -299, -213, +-284, -387, -122, -418, 115, -297, 307, -30, +333, 304, 179, 548, -74, 518, -296, 214, +-371, -199, -262, -500, -33, -557, 208, -378, +366, -22, 359, 352, 192, 563, -50, 472, +-243, 135, -306, -267, -234, -530, -113, -500, +2, -201, 121, 201, 205, 523, 187, 605, +84, 372, -29, -71, -99, -479, -92, -664, +-45, -570, -13, -223, 6, 225, 27, 589, +12, 703, -37, 505, -80, 79, -75, -348, +20, -560, 137, -539, 153, -330, 69, -5, +-12, 328, -73, 498, -127, 407, -143, 104, +-97, -227, 3, -397, 128, -345, 178, -147, +102, 109, -17, 363, -109, 480, -161, 335, +-156, -21, -71, -375, 69, -553, 226, -472, +299, -193, 196, 147, -38, 432, -264, 570, +-380, 448, -347, 88, -164, -293, 102, -509, +361, -469, 487, -221, 383, 106, 83, 368, +-232, 477, -413, 362, -409, 32, -239, -332, +30, -533, 282, -481, 376, -206, 244, 179, +-38, 508, -279, 647, -336, 519, -183, 133, +85, -354, 321, -690, 406, -738, 297, -481, +18, -14, -317, 479, -499, 786, -403, 752, +-104, 377, 191, -192, 340, -659, 315, -815, +175, -604, -20, -117, -181, 437, -202, 802, +-70, 781, 105, 367, 170, -243, 78, -731, +-93, -847, -205, -554, -200, -3, -97, 552, +52, 866, 176, 787, 210, 305, 129, -334, +-33, -781, -165, -830, -150, -502, -13, 15, +129, 500, 178, 743, 103, 673, -72, 295, +-235, -220, -297, -584, -222, -626, -10, -394, +242, -54, 367, 267, 304, 459, 115, 464, +-131, 296, -314, 2, -322, -285, -168, -404, +47, -328, 221, -163, 250, -1, 138, 152, +-18, 256, -151, 278, -212, 201, -159, 28, +-21, -134, 112, -195, 196, -164, 183, -135, +92, -97, -5, 6, -82, 136, -165, 205, +-229, 162, -223, 43, -109, -76, 105, -146, +301, -172, 371, -161, 300, -53, 105, 148, +-199, 299, -466, 300, -533, 146, -334, -88, +76, -300, 487, -390, 644, -332, 480, -139, +111, 154, -337, 400, -677, 467, -704, 314, +-371, 20, 180, -270, 699, -411, 876, -370, +587, -178, 38, 104, -507, 350, -859, 427, +-832, 283, -383, -10, 256, -301, 779, -452, +903, -423, 534, -225, -67, 95, -512, 421, +-670, 581, -537, 493, -138, 204, 315, -162, +564, -463, 489, -596, 123, -509, -305, -223, +-475, 173, -355, 483, -119, 553, 129, 372, +320, 67, 363, -219, 257, -380, 34, -346, +-215, -152, -279, 106, -152, 299, -46, 314, +-35, 129, -40, -136, -33, -297, 17, -288, +85, -158, 110, 31, 143, 196, 212, 285, +166, 280, -39, 162, -247, -35, -356, -180, +-301, -209, -92, -211, 118, -190, 241, -114, +320, 27, 276, 208, 51, 332, -202, 300, +-343, 124, -320, -95, -114, -299, 157, -395, +309, -287, 330, -11, 222, 302, -27, 478, +-304, 385, -452, 62, -407, -316, -154, -531, +211, -466, 473, -142, 531, 283, 381, 586, +49, 616, -344, 308, -597, -190, -600, -608, +-323, -713, 132, -461, 529, -4, 672, 444, +522, 681, 125, 613, -363, 256, -685, -227, +-679, -568, -339, -603, 181, -359, 611, 7, +738, 320, 545, 476, 109, 431, -401, 207, +-735, -117, -747, -370, -435, -431, 87, -321, +580, -91, 782, 151, 658, 325, 302, 395, +-179, 348, -609, 155, -787, -126, -625, -357, +-173, -457, 363, -392, 701, -185, 702, 75, +408, 318, -51, 493, -494, 506, -711, 290, +-606, -67, -205, -383, 317, -548, 695, -521, +723, -310, 398, 23, -99, 379, -531, 633, +-723, 639, -618, 341, -235, -101, 275, -499, +671, -718, 753, -657, 474, -310, -25, 182, +-475, 633, -676, 845, -602, 676, -298, 189, +130, -400, 513, -834, 678, -914, 552, -578, +171, 24, -269, 641, -546, 1009, -585, 945, +-421, 458, -104, -265, 262, -919, 531, -1203, +577, -972, 342, -309, -54, 512, -388, 1137, +-515, 1299, -430, 921, -151, 159, 216, -699, +489, -1289, 531, -1320, 300, -748, -106, 163, +-471, 971, -596, 1327, -457, 1077, -122, 353, +282, -527, 573, -1197, 587, -1320, 326, -783, +-69, 160, -387, 1012, -464, 1368, -324, 1111, +-94, 379, 139, -501, 293, -1160, 242, -1331, +39, -918, -164, -121, -249, 670, -162, 1072, +45, 999, 195, 586, 226, 14, 212, -492, +125, -754, -51, -688, -203, -356, -256, 69, +-205, 371, -53, 460, 58, 397, 46, 218, +28, -58, 56, -331, 56, -471, 58, -394, +96, -149, 112, 144, 122, 393, 82, 537, +-81, 521, -255, 276, -282, -130, -197, -527, +-45, -704, 134, -596, 224, -299, 210, 90, +143, 463, -3, 694, -168, 657, -194, 342, +-106, -115, 20, -493, 158, -631, 217, -509, +131, -205, -5, 181, -132, 519, -221, 652, +-201, 452, -113, 1, -33, -471, 55, -756, +149, -696, 159, -311, 114, 247, 96, 763, +97, 1014, 70, 807, -11, 184, -148, -548, +-270, -1069, -268, -1140, -145, -695, 10, 69, +139, 797, 235, 1168, 252, 1006, 153, 389, +-32, -379, -196, -944, -220, -1066, -81, -676, +95, 32, 172, 680, 170, 963, 119, 774, +-32, 236, -254, -365, -387, -774, -341, -858, +-112, -545, 210, 41, 461, 575, 532, 815, +418, 711, 121, 318, -298, -167, -621, -539, +-669, -749, -413, -679, 42, -276, 474, 229, +649, 580, 536, 715, 203, 581, -256, 214, +-623, -200, -652, -562, -316, -755, 185, -588, +581, -125, 647, 346, 408, 648, 21, 701, +-385, 464, -659, 37, -614, -405, -267, -729, +183, -742, 514, -373, 554, 153, 339, 560, +75, 709, -130, 596, -302, 269, -376, -146, +-300, -520, -103, -701, 128, -556, 258, -173, +228, 219, 172, 466, 161, 528, 46, 422, +-196, 184, -397, -137, -403, -443, -199, -566, +115, -414, 362, -106, 488, 243, 493, 517, +287, 604, -154, 465, -613, 126, -794, -338, +-573, -750, -65, -850, 435, -570, 716, -33, +723, 556, 456, 940, -56, 949, -597, 597, +-847, 8, -650, -667, -145, -1124, 384, -1056, +723, -513, 758, 227, 476, 880, -46, 1147, +-596, 922, -911, 330, -788, -433, -290, -1115, +318, -1304, 776, -841, 921, 4, 695, 877, +165, 1412, -461, 1335, -896, 692, -892, -252, +-484, -1183, 74, -1683, 527, -1436, 745, -541, +667, 585, 319, 1468, -161, 1728, -551, 1263, +-651, 304, -465, -775, -136, -1548, 192, -1661, +432, -1020, 512, 52, 419, 1058, 164, 1575, +-164, 1399, -419, 634, -500, -387, -393, -1266, +-159, -1609, 102, -1219, 316, -292, 470, 750, +464, 1482, 240, 1593, -94, 1030, -377, 44, +-514, -1000, -445, -1654, -215, -1572, 84, -808, +400, 272, 595, 1232, 521, 1681, 208, 1397, +-210, 525, -604, -560, -738, -1411, -527, -1623, +-127, -1086, 331, -105, 733, 865, 859, 1434, +596, 1369, 62, 714, -540, -203, -917, -996, +-866, -1360, -453, -1103, 109, -379, 652, 429, +930, 982, 784, 1101, 296, 781, -316, 204, +-793, -391, -895, -831, -571, -928, -19, -629, +519, -116, 823, 383, 776, 687, 399, 718, +-140, 523, -619, 155, -838, -301, -709, -660, +-289, -733, 247, -497, 668, -58, 832, 392, +675, 642, 255, 650, -258, 417, -666, -9, +-855, -458, -715, -709, -252, -631, 323, -263, +751, 207, 869, 549, 634, 635, 153, 476, +-360, 146, -752, -244, -860, -547, -580, -610, +-39, -394, 489, -33, 796, 306, 753, 476, +397, 434, -73, 253, -511, 14, -789, -223, +-737, -370, -334, -323, 200, -139, 661, 57, +851, 182, 654, 194, 204, 125, -299, 56, +-744, 15, -921, -40, -671, -91, -155, -101, +420, -116, 880, -142, 968, -103, 622, 4, +97, 170, -468, 359, -932, 435, -1000, 272, +-635, -63, -50, -423, 611, -675, 1062, -660, +972, -349, 473, 153, -163, 660, -785, 939, +-1097, 801, -859, 280, -256, -376, 462, -871, +1042, -999, 1110, -689, 630, -72, -52, 579, +-702, 985, -1127, 939, -1034, 439, -471, -288, +262, -869, 915, -1053, 1193, -758, 901, -91, +266, 618, -414, 1062, -972, 1075, -1148, 605, +-791, -163, -91, -850, 631, -1177, 1068, -1012, +978, -397, 470, 355, -161, 895, -718, 1094, +-1006, 857, -816, 245, -225, -433, 429, -898, +853, -973, 864, -604, 506, 13, 8, 536, +-440, 816, -763, 791, -788, 404, -451, -176, +49, -674, 473, -890, 693, -700, 644, -180, +391, 389, 71, 776, -307, 897, -647, 679, +-723, 133, -477, -504, -85, -959, 323, -1001, +620, -601, 687, 23, 519, 603, 137, 954, +-377, 947, -755, 527, -750, -134, -426, -742, +65, -1000, 551, -767, 807, -225, 687, 346, +264, 757, -299, 842, -763, 552, -870, 13, +-565, -543, -22, -834, 512, -688, 839, -236, +805, 244, 422, 614, -135, 750, -617, 570, +-846, 140, -733, -376, -330, -727, 187, -720, +632, -403, 848, 17, 722, 399, 277, 656, +-269, 673, -721, 399, -910, -73, -717, -517, +-203, -694, 399, -566, 874, -242, 1016, 140, +697, 479, 68, 671, -588, 595, -1020, 238, +-1037, -252, -602, -621, 71, -701, 722, -501, +1086, -141, 973, 274, 452, 639, -220, 778, +-807, 577, -1073, 92, -848, -467, -258, -809, +419, -776, 915, -451, 1022, 33, 689, 541, +83, 881, -589, 848, -1062, 419, -1051, -241, +-547, -822, 172, -1007, 812, -747, 1138, -214, +976, 396, 415, 897, -299, 1054, -915, 754, +-1180, 121, -902, -590, -223, -1058, 498, -1029, +964, -578, 1010, 36, 665, 629, 101, 993, +-496, 944, -946, 493, -985, -172, -552, -798, +93, -1038, 634, -765, 923, -195, 884, 428, +507, 897, -86, 996, -701, 644, -1092, -24, +-1039, -733, -517, -1138, 219, -1000, 857, -403, +1160, 338, 1033, 939, 499, 1166, -267, 912, +-974, 272, -1304, -474, -1059, -1018, -342, -1124, +485, -733, 1068, -91, 1251, 517, 956, 895, +247, 899, -600, 547, -1224, 27, -1356, -479, +-891, -802, -26, -766, 835, -431, 1375, 9, +1386, 466, 806, 767, -159, 742, -1082, 464, +-1584, 19, -1405, -495, -594, -841, 462, -840, +1308, -548, 1617, -21, 1236, 595, 309, 958, +-758, 929, -1511, 573, -1591, -51, -953, -705, +80, -1031, 1068, -919, 1640, -458, 1500, 234, +676, 839, -453, 1018, -1413, 767, -1755, 204, +-1288, -495, -277, -953, 804, -933, 1573, -535, +1687, 84, 1037, 727, -69, 1035, -1114, 866, +-1653, 351, -1431, -347, -593, -921, 416, -1059, +1202, -756, 1485, -180, 1139, 500, 302, 993, +-638, 1033, -1280, 639, -1336, -14, -800, -677, +32, -1013, 763, -873, 1154, -390, 1123, 227, +654, 754, -107, 938, -822, 680, -1138, 137, +-967, -473, -442, -872, 192, -827, 703, -411, +952, 120, 887, 604, 472, 860, -176, 720, +-739, 281, -972, -256, -814, -711, -346, -829, +246, -559, 733, -150, 976, 271, 838, 616, +271, 688, -483, 468, -1005, 120, -1052, -259, +-649, -517, 24, -489, 688, -296, 1092, -78, +1055, 178, 525, 368, -297, 370, -970, 236, +-1177, 17, -881, -234, -247, -354, 455, -280, +956, -136, 1079, 55, 762, 286, 103, 402, +-575, 334, -961, 121, -921, -172, -524, -412, +48, -445, 561, -312, 851, -102, 802, 175, +385, 412, -199, 480, -641, 360, -775, 93, +-602, -211, -196, -403, 244, -433, 566, -337, +697, -126, 562, 169, 168, 421, -270, 522, +-553, 413, -632, 128, -499, -221, -215, -508, +142, -619, 494, -521, 703, -182, 591, 302, +212, 688, -214, 805, -531, 615, -665, 148, +-549, -426, -201, -831, 259, -924, 668, -652, +794, -42, 526, 601, 11, 948, -480, 920, +-783, 501, -804, -181, -504, -782, 52, -1025, +673, -838, 1068, -240, 977, 510, 414, 979, +-301, 1006, -883, 624, -1160, -62, -1000, -764, +-389, -1122, 439, -980, 1132, -388, 1334, 427, +910, 1038, 105, 1140, -706, 773, -1248, 92, +-1301, -677, -776, -1177, 96, -1151, 960, -588, +1442, 271, 1255, 1016, 494, 1260, -416, 960, +-1146, 302, -1452, -495, -1138, -1114, -326, -1270, +623, -866, 1328, -66, 1455, 752, 901, 1185, +-4, 1093, -858, 586, -1382, -125, -1328, -772, +-662, -1080, 292, -918, 1121, -345, 1492, 374, +1174, 869, 315, 936, -649, 603, -1329, 51, +-1491, -516, -1013, -872, -79, -854, 888, -469, +1487, 114, 1481, 639, 849, 870, -128, 741, +-1010, 376, -1484, -86, -1364, -527, -661, -773, +311, -714, 1103, -416, 1440, 6, 1168, 388, +353, 599, -605, 613, -1248, 434, -1338, 87, +-840, -313, 53, -560, 907, -547, 1372, -311, +1267, 40, 582, 396, -398, 617, -1191, 553, +-1481, 194, -1152, -315, -325, -751, 596, -845, +1236, -533, 1428, 11, 1075, 604, 247, 1030, +-662, 1041, -1260, 574, -1322, -153, -844, -864, +-92, -1224, 610, -1022, 1103, -415, 1196, 313, +733, 916, -58, 1149, -777, 870, -1148, 231, +-1027, -475, -453, -970, 282, -1000, 910, -574, +1216, 37, 994, 610, 266, 947, -608, 866, +-1219, 387, -1307, -248, -809, -786, 18, -995, +813, -740, 1312, -192, 1311, 415, 698, 888, +-262, 984, -1072, 632, -1369, 28, -1082, -586, +-362, -975, 478, -920, 1083, -469, 1228, 139, +843, 709, 82, 995, -688, 823, -1079, 323, +-979, -280, -504, -795, 147, -995, 708, -757, +945, -225, 795, 385, 339, 875, -271, 993, +-742, 688, -855, 134, -642, -471, -232, -934, +286, -1004, 703, -615, 816, 6, 610, 621, +159, 1004, -368, 940, -695, 472, -707, -168, +-497, -786, -92, -1102, 394, -882, 687, -265, +650, 421, 363, 948, -76, 1083, -459, 733, +-595, 93, -512, -595, -247, -1070, 167, -1046, +516, -527, 582, 153, 414, 708, 102, 968, +-244, 825, -455, 352, -472, -234, -347, -727, +-79, -886, 240, -613, 405, -123, 397, 316, +282, 584, 70, 633, -169, 446, -308, 115, +-352, -265, -285, -536, -65, -524, 187, -290, +320, -30, 337, 188, 242, 353, -2, 411, +-268, 321, -410, 100, -380, -178, -159, -356, +189, -351, 430, -252, 459, -111, 320, 83, +0, 292, -399, 398, -576, 326, -428, 121, +-107, -128, 284, -301, 553, -341, 509, -285, +217, -149, -152, 75, -505, 280, -609, 324, +-345, 241, 52, 98, 380, -74, 570, -169, +474, -174, 123, -165, -209, -103, -428, 14, +-492, 82, -297, 88, 36, 111, 267, 97, +367, 43, 308, 0, 73, -88, -139, -183, +-227, -176, -249, -81, -152, 42, 73, 189, +212, 293, 212, 265, 150, 131, 20, -85, +-130, -329, -191, -436, -195, -347, -159, -123, +-30, 168, 102, 407, 162, 467, 196, 340, +187, 96, 76, -213, -45, -428, -122, -426, +-188, -247, -186, 27, -77, 276, 32, 368, +85, 294, 123, 131, 107, -94, 35, -295, +-17, -338, -46, -223, -79, -27, -47, 173, +20, 262, 20, 234, 15, 162, 55, 55, +54, -84, 1, -187, -21, -200, -43, -152, +-73, -83, -58, -32, -33, 13, -24, 94, +50, 190, 136, 234, 127, 183, 69, 56, +10, -90, -84, -219, -165, -298, -160, -272, +-113, -120, 0, 119, 173, 314, 262, 364, +182, 245, 38, 25, -102, -190, -226, -316, +-263, -316, -175, -196, 2, 17, 208, 215, +344, 292, 281, 242, 72, 96, -130, -72, +-253, -165, -297, -179, -228, -147, -62, -66, +129, 38, 283, 102, 309, 122, 179, 106, +1, 39, -110, -12, -193, -37, -252, -80, +-234, -123, -123, -116, 50, -50, 225, 60, +301, 171, 248, 207, 145, 164, 5, 67, +-177, -102, -322, -284, -338, -361, -215, -275, +23, -34, 252, 260, 347, 438, 316, 419, +207, 257, 0, -21, -261, -344, -426, -523, +-411, -475, -205, -217, 103, 156, 350, 443, +437, 498, 391, 377, 189, 152, -144, -152, +-410, -391, -467, -443, -342, -330, -93, -87, +197, 168, 370, 284, 381, 276, 247, 229, +-4, 125, -251, -40, -327, -165, -254, -218, +-98, -197, 122, -102, 290, 1, 294, 84, +161, 167, -44, 213, -258, 138, -326, -33, +-225, -191, -67, -273, 92, -231, 250, -61, +320, 155, 249, 329, 86, 392, -106, 272, +-235, -15, -260, -313, -222, -471, -167, -439, +-31, -200, 171, 132, 307, 386, 301, 468, +190, 356, 25, 81, -152, -217, -287, -386, +-344, -382, -263, -206, -29, 76, 243, 301, +377, 365, 353, 275, 211, 59, -29, -190, +-290, -346, -446, -362, -418, -243, -185, -10, +174, 244, 444, 381, 500, 369, 363, 229, +76, 4, -299, -208, -569, -324, -589, -337, +-333, -229, 113, -16, 518, 186, 664, 280, +523, 260, 183, 148, -276, -11, -662, -151, +-746, -230, -468, -204, 45, -67, 559, 116, +787, 232, 633, 223, 226, 122, -292, -26, +-749, -185, -880, -291, -548, -269, 60, -121, +667, 93, 992, 289, 850, 346, 315, 253, +-339, 95, -895, -104, -1122, -297, -830, -374, +-145, -293, 600, -97, 1104, 158, 1141, 341, +658, 344, -60, 246, -713, 85, -1122, -147, +-1071, -337, -507, -380, 252, -266, 860, -14, +1112, 258, 865, 363, 246, 305, -437, 183, +-944, -27, -1075, -266, -673, -378, 45, -321, +687, -105, 1032, 190, 955, 354, 432, 290, +-286, 146, -860, -17, -1078, -212, -805, -310, +-165, -247, 503, -70, 939, 170, 1022, 323, +653, 239, -22, 32, -663, -109, -1019, -196, +-948, -229, -442, -146, 239, 6, 773, 166, +1008, 276, 835, 216, 284, 12, -382, -146, +-861, -186, -981, -182, -675, -118, -97, 10, +445, 138, 783, 236, 841, 239, 550, 85, +18, -122, -478, -225, -764, -232, -730, -175, +-384, -26, 78, 150, 462, 267, 696, 294, +661, 165, 306, -89, -163, -271, -532, -284, +-700, -193, -586, -18, -223, 183, 179, 273, +505, 231, 686, 80, 604, -154, 257, -312, +-174, -260, -533, -77, -706, 131, -590, 304, +-269, 328, 132, 178, 530, -37, 762, -248, +635, -377, 221, -304, -263, -76, -638, 148, +-758, 292, -549, 308, -114, 170, 374, -21, +743, -155, 783, -234, 453, -205, -69, -42, +-538, 130, -783, 206, -696, 182, -327, 57, +155, -110, 583, -210, 790, -229, 650, -178, +224, -15, -260, 203, -604, 328, -690, 309, +-521, 157, -175, -70, 239, -261, 581, -341, +674, -314, 464, -159, 92, 109, -278, 334, +-528, 392, -582, 273, -418, 25, -105, -230, +263, -363, 534, -343, 571, -205, 373, 51, +48, 330, -297, 456, -524, 369, -522, 107, +-319, -221, 22, -438, 381, -450, 576, -307, +492, -49, 201, 286, -176, 510, -485, 484, +-567, 234, -399, -131, -90, -428, 259, -501, +529, -365, 562, -111, 350, 215, 15, 489, +-315, 531, -520, 329, -499, -14, -293, -355, +9, -526, 317, -466, 494, -251, 448, 38, +218, 341, -96, 522, -379, 480, -481, 255, +-363, -73, -105, -365, 189, -482, 424, -412, +474, -207, 307, 94, 6, 387, -312, 517, +-495, 417, -454, 115, -228, -266, 71, -523, +365, -546, 519, -357, 438, 3, 157, 411, +-185, 662, -439, 630, -486, 316, -319, -172, +-35, -591, 262, -724, 452, -560, 440, -179, +223, 288, -85, 630, -354, 684, -455, 446, +-361, 5, -150, -445, 103, -655, 348, -543, +476, -214, 380, 200, 115, 531, -175, 624, +-368, 455, -415, 85, -309, -359, -100, -654, +171, -637, 399, -359, 431, 47, 237, 434, +-47, 636, -282, 588, -396, 321, -344, -97, +-161, -480, 95, -618, 357, -478, 504, -158, +406, 202, 114, 436, -210, 466, -442, 325, +-512, 41, -406, -285, -161, -454, 160, -389, +469, -156, 590, 144, 442, 370, 126, 412, +-192, 305, -422, 100, -511, -187, -424, -418, +-165, -452, 193, -303, 482, -37, 559, 239, +390, 386, 67, 368, -292, 252, -549, 45, +-595, -211, -381, -361, 28, -330, 458, -166, +707, 68, 649, 249, 290, 283, -219, 214, +-641, 84, -795, -113, -599, -278, -138, -292, +389, -168, 748, 38, 786, 230, 478, 294, +-50, 229, -553, 106, -806, -63, -714, -238, +-325, -298, 204, -219, 648, -49, 830, 154, +663, 267, 216, 228, -329, 106, -748, -39, +-861, -194, -603, -280, -83, -218, 467, -47, +829, 174, 844, 340, 494, 322, -79, 152, +-610, -50, -879, -246, -770, -392, -327, -369, +251, -170, 723, 106, 896, 360, 676, 449, +146, 313, -437, 75, -827, -159, -881, -353, +-574, -409, -7, -246, 576, 43, 932, 312, +895, 447, 449, 343, -197, 54, -726, -249, +-944, -464, -801, -523, -318, -336, 310, 53, +805, 447, 965, 678, 723, 631, 158, 288, +-434, -168, -791, -529, -857, -707, -625, -631, +-127, -281, 431, 183, 781, 547, 809, 678, +504, 500, 25, 122, -390, -232, -632, -460, +-675, -522, -437, -353, -1, -20, 381, 309, +577, 503, 549, 466, 298, 201, -54, -128, +-347, -381, -536, -519, -526, -466, -257, -207, +131, 139, 448, 443, 600, 589, 501, 488, +165, 202, -228, -111, -542, -370, -674, -509, +-503, -455, -66, -236, 388, 53, 666, 308, +671, 409, 384, 320, -59, 134, -476, -53, +-735, -207, -687, -285, -285, -245, 239, -102, +631, 89, 781, 241, 624, 287, 171, 229, +-370, 101, -770, -61, -862, -240, -561, -379, +2, -389, 540, -233, 846, 30, 822, 292, +425, 465, -175, 484, -675, 343, -873, 72, +-696, -275, -185, -548, 399, -591, 770, -377, +822, -19, 519, 333, -54, 555, -608, 561, +-862, 346, -764, -40, -340, -454, 253, -677, +720, -579, 876, -207, 709, 259, 233, 623, +-371, 745, -771, 571, -826, 143, -578, -396, +-112, -800, 389, -854, 694, -527, 729, 12, +472, 519, -17, 803, -468, 766, -645, 425, +-565, -93, -282, -578, 144, -797, 501, -635, +633, -197, 510, 288, 146, 618, -319, 684, +-613, 464, -641, 50, -442, -407, -50, -714, +393, -683, 672, -327, 690, 154, 441, 555, +-22, 730, -469, 592, -696, 207, -665, -264, +-398, -660, 49, -770, 476, -486, 708, 14, +672, 477, 353, 732, -121, 660, -510, 278, +-679, -218, -610, -641, -281, -819, 173, -596, +516, -70, 625, 465, 508, 798, 191, 804, +-189, 456, -445, -73, -518, -553, -414, -827, +-156, -759, 147, -353, 364, 173, 472, 590, +418, 755, 173, 595, -146, 200, -397, -235, +-528, -556, -457, -643, -151, -435, 237, -40, +537, 346, 637, 568, 454, 520, 37, 225, +-389, -145, -665, -425, -690, -525, -391, -393, +106, -75, 531, 263, 736, 463, 670, 448, +307, 219, -197, -96, -607, -317, -774, -377, +-631, -285, -204, -80, 298, 145, 666, 267, +781, 257, 573, 144, 107, -18, -386, -121, +-704, -120, -745, -90, -467, -78, 1, -59, +435, -41, 677, -34, 664, 7, 386, 82, +-43, 161, -436, 232, -654, 211, -616, 41, +-326, -181, 90, -332, 462, -356, 666, -235, +606, 4, 284, 254, -176, 425, -574, 428, +-736, 204, -578, -143, -168, -418, 322, -502, +695, -363, 785, -55, 531, 287, 26, 530, +-488, 562, -792, 324, -764, -95, -415, -479, +120, -659, 605, -561, 840, -224, 725, 206, +282, 562, -288, 708, -716, 560, -832, 152, +-611, -321, -130, -648, 408, -699, 782, -459, +834, -34, 522, 404, -28, 677, -543, 661, +-799, 350, -741, -128, -392, -553, 127, -730, +595, -590, 804, -193, 673, 300, 240, 680, +-280, 765, -634, 521, -717, 50, -528, -467, +-109, -790, 376, -766, 671, -419, 656, 110, +356, 605, -85, 831, -464, 695, -618, 290, +-524, -235, -227, -677, 172, -818, 484, -602, +554, -141, 388, 373, 97, 714, -205, 745, +-398, 484, -438, 44, -332, -430, -104, -736, +186, -724, 378, -398, 388, 87, 280, 515, +103, 719, -131, 642, -342, 318, -430, -139, +-348, -564, -84, -765, 230, -619, 413, -199, +418, 282, 294, 624, 39, 713, -276, 526, +-482, 135, -470, -334, -233, -693, 127, -741, +422, -449, 514, 13, 410, 434, 136, 671, +-231, 649, -511, 378, -556, -63, -360, -523, +5, -765, 371, -637, 542, -236, 486, 236, +269, 611, -49, 746, -359, 593, -493, 199, +-429, -320, -220, -744, 53, -822, 279, -534, +380, -61, 364, 422, 229, 737, -17, 760, +-233, 497, -329, 35, -305, -471, -181, -765, +27, -694, 217, -358, 319, 81, 295, 476, +117, 666, -126, 595, -284, 297, -322, -146, +-260, -545, -67, -685, 186, -520, 367, -166, +397, 249, 262, 575, -15, 675, -291, 517, +-428, 138, -402, -331, -219, -670, 76, -713, +347, -469, 455, -59, 376, 375, 141, 656, +-142, 673, -332, 437, -380, 17, -317, -424, +-133, -670, 113, -615, 291, -323, 348, 88, +293, 464, 142, 638, -64, 569, -250, 284, +-380, -151, -365, -553, -157, -708, 130, -577, +335, -225, 405, 238, 325, 610, 97, 739, +-186, 609, -403, 219, -440, -315, -251, -710, +70, -788, 319, -561, 413, -105, 341, 398, +121, 713, -155, 756, -363, 512, -426, 8, +-297, -512, -1, -772, 272, -702, 380, -349, +325, 156, 165, 575, -58, 760, -249, 673, +-343, 290, -295, -258, -92, -686, 151, -812, +276, -607, 252, -154, 154, 340, 6, 684, +-142, 787, -225, 575, -213, 85, -100, -447, +80, -765, 211, -747, 218, -407, 136, 89, +12, 516, -119, 735, -204, 664, -209, 282, +-142, -248, 1, -651, 164, -748, 251, -518, +220, -70, 120, 378, -2, 658, -129, 684, +-227, 425, -245, -42, -162, -496, -14, -711, +130, -617, 212, -271, 232, 172, 182, 526, +64, 665, -98, 545, -232, 187, -263, -282, +-177, -622, -10, -666, 168, -433, 283, -26, +269, 388, 129, 628, -89, 614, -292, 352, +-375, -79, -273, -491, -41, -660, 214, -531, +387, -197, 403, 206, 261, 508, 14, 595, +-254, 448, -445, 117, -452, -268, -275, -515, +0, -518, 260, -315, 429, -6, 434, 285, +253, 446, -45, 439, -327, 265, -452, -19, +-364, -280, -104, -412, 191, -373, 398, -197, +413, 37, 227, 239, -78, 357, -355, 351, +-471, 202, -364, -29, -74, -241, 253, -352, +468, -324, 477, -179, 280, 22, -41, 213, +-340, 329, -493, 319, -430, 173, -177, -51, +150, -247, 401, -326, 471, -273, 344, -113, +76, 99, -210, 265, -412, 317, -449, 236, +-303, 29, -27, -217, 260, -351, 454, -317, +475, -153, 303, 89, 10, 314, -288, 403, +-488, 329, -505, 114, -296, -192, 49, -429, +370, -460, 518, -302, 429, -33, 150, 262, +-172, 447, -410, 445, -475, 284, -317, 0, +-6, -301, 309, -449, 475, -386, 426, -181, +185, 80, -120, 299, -372, 379, -490, 301, +-422, 96, -170, -171, 168, -354, 444, -348, +537, -185, 404, 45, 121, 250, -198, 351, +-437, 308, -522, 146, -397, -91, -91, -303, +262, -369, 479, -274, 464, -90, 261, 108, +-30, 262, -304, 324, -468, 282, -429, 146, +-195, -64, 134, -246, 400, -309, 488, -271, +368, -152, 104, 37, -208, 223, -447, 329, +-513, 318, -378, 161, -70, -103, 282, -311, +518, -367, 520, -286, 306, -66, -28, 219, +-345, 415, -514, 434, -473, 263, -231, -70, +117, -403, 409, -538, 492, -440, 350, -163, +70, 219, -212, 523, -382, 595, -381, 419, +-224, 66, 35, -336, 275, -579, 368, -559, +288, -335, 89, 13, -141, 353, -304, 522, +-317, 465, -197, 234, 3, -74, 207, -326, +321, -410, 286, -330, 131, -135, -73, 106, +-243, 282, -298, 323, -232, 236, -94, 64, +64, -123, 205, -251, 271, -279, 235, -212, +115, -61, -41, 122, -182, 253, -259, 292, +-258, 234, -181, 90, -17, -99, 187, -257, +337, -324, 354, -270, 238, -95, 7, 116, +-251, 260, -423, 307, -443, 241, -288, 64, +27, -147, 371, -283, 554, -292, 489, -164, +201, 54, -180, 232, -488, 298, -577, 257, +-405, 98, -28, -134, 378, -321, 593, -376, +514, -280, 188, -57, -229, 200, -537, 376, +-584, 427, -369, 336, 14, 92, 400, -219, +603, -453, 528, -511, 232, -366, -146, -68, +-441, 262, -525, 499, -401, 548, -147, 356, +151, -14, 369, -397, 405, -602, 280, -523, +72, -203, -130, 213, -257, 553, -284, 656, +-225, 446, -75, 3, 119, -464, 249, -732, +281, -648, 223, -248, 75, 261, -130, 658, +-294, 778, -353, 540, -278, 40, -80, -486, +165, -797, 355, -741, 411, -334, 303, 205, +74, 628, -171, 782, -345, 597, -387, 140, +-277, -381, -47, -731, 193, -749, 340, -419, +340, 84, 199, 514, -16, 717, -222, 619, +-337, 250, -304, -229, -129, -608, 106, -722, +300, -506, 369, -57, 281, 392, 70, 655, +-173, 655, -341, 376, -356, -70, -222, -487, +-13, -711, 190, -637, 311, -275, 296, 194, +149, 552, -50, 696, -210, 579, -260, 221, +-187, -223, -42, -563, 106, -684, 211, -521, +232, -129, 142, 284, -18, 550, -185, 610, +-279, 423, -254, 43, -126, -337, 43, -568, +207, -569, 314, -304, 305, 102, 174, 440, +-29, 597, -222, 521, -327, 196, -297, -231, +-169, -558, 7, -675, 183, -513, 301, -101, +296, 354, 171, 660, -24, 721, -206, 480, +-296, 16, -267, -443, -132, -722, 63, -720, +260, -395, 355, 97, 290, 522, 83, 728, +-174, 626, -364, 241, -402, -236, -276, -589, +-31, -696, 254, -489, 450, -45, 445, 401, +235, 656, -69, 637, -337, 331, -462, -127, +-399, -511, -177, -678, 126, -574, 391, -209, +474, 244, 328, 558, 58, 632, -209, 456, +-376, 98, -386, -279, -234, -514, 10, -537, +254, -340, 375, 4, 311, 315, 117, 453, +-102, 401, -259, 185, -297, -110, -207, -343, +-51, -418, 119, -314, 249, -60, 270, 232, +161, 401, -4, 387, -148, 226, -221, -29, +-207, -278, -128, -404, -3, -361, 135, -173, +219, 88, 191, 290, 84, 334, -37, 248, +-128, 88, -164, -87, -136, -199, -65, -209, +26, -135, 107, -14, 132, 98, 99, 125, +42, 82, -17, 35, -71, -12, -95, -48, +-99, -60, -84, -63, -29, -60, 63, -36, +135, -1, 153, 39, 114, 105, 19, 163, +-91, 151, -173, 64, -190, -73, -114, -209, +40, -269, 178, -211, 220, -64, 152, 120, +-1, 277, -166, 312, -250, 196, -213, -3, +-76, -198, 125, -302, 295, -254, 322, -83, +191, 112, -20, 244, -221, 259, -331, 142, +-305, -47, -165, -203, 43, -257, 240, -187, +326, -25, 262, 139, 106, 220, -71, 192, +-201, 79, -231, -68, -166, -170, -54, -172, +73, -90, 166, 29, 169, 136, 91, 169, +-16, 107, -109, 2, -150, -96, -127, -152, +-68, -140, 22, -76, 132, 11, 199, 97, +173, 141, 70, 117, -62, 52, -171, -11, +-216, -52, -191, -71, -92, -62, 73, -31, +226, 12, 266, 45, 182, 38, 21, -10, +-145, -56, -250, -69, -254, -56, -147, -20, +36, 42, 219, 112, 296, 160, 230, 144, +66, 47, -118, -86, -248, -175, -268, -192, +-174, -153, -8, -54, 159, 75, 249, 172, +221, 194, 96, 118, -62, -28, -181, -147, +-205, -162, -138, -100, -16, 1, 107, 124, +189, 198, 196, 167, 112, 44, -26, -125, +-150, -258, -210, -256, -195, -126, -112, 41, +11, 190, 139, 275, 227, 232, 237, 81, +154, -96, 12, -228, -135, -243, -235, -123, +-250, 38, -171, 150, -25, 198, 133, 156, +245, 30, 254, -110, 151, -201, -21, -201, +-190, -93, -272, 59, -221, 159, -68, 184, +121, 147, 274, 51, 306, -63, 182, -142, +-37, -166, -242, -117, -342, -10, -289, 85, +-108, 118, 119, 112, 297, 74, 345, -1, +239, -74, 31, -116, -179, -118, -306, -56, +-298, 44, -165, 112, 25, 139, 182, 132, +261, 59, 236, -59, 116, -156, -43, -199, +-173, -158, -228, -25, -192, 124, -84, 207, +39, 212, 141, 134, 195, -25, 178, -177, +91, -246, -26, -217, -126, -79, -183, 113, +-178, 237, -106, 238, 8, 150, 123, -5, +204, -163, 203, -223, 115, -174, -26, -53, +-162, 104, -239, 201, -219, 164, -110, 42, +50, -95, 209, -200, 286, -201, 232, -82, +78, 81, -98, 218, -233, 277, -274, 197, +-202, 16, -49, -158, 115, -264, 224, -269, +235, -160, 148, 6, 9, 149, -132, 227, +-215, 207, -192, 91, -79, -41, 59, -121, +172, -135, 210, -87, 149, 4, 16, 82, +-132, 110, -226, 87, -214, 8, -106, -90, +40, -146, 173, -147, 245, -98, 209, 2, +82, 117, -65, 192, -180, 211, -228, 159, +-187, 27, -67, -120, 78, -217, 186, -247, +215, -186, 152, -40, 32, 125, -101, 234, +-199, 248, -212, 146, -122, -36, 22, -188, +151, -245, 216, -198, 193, -44, 90, 156, +-47, 292, -164, 296, -227, 159, -203, -82, +-92, -313, 51, -406, 162, -328, 209, -101, +179, 199, 88, 435, -24, 488, -123, 336, +-178, 34, -153, -307, -58, -527, 39, -520, +104, -291, 120, 66, 81, 402, 9, 566, +-55, 485, -91, 195, -81, -186, -20, -495, +51, -579, 95, -391, 96, -22, 51, 355, +-26, 572, -93, 532, -126, 243, -116, -168, +-54, -518, 40, -637, 113, -455, 140, -55, +122, 379, 56, 646, -32, 621, -98, 320, +-126, -118, -111, -508, -48, -683, 24, -553, +76, -175, 104, 268, 86, 576, 23, 616, +-37, 384, -72, 7, -85, -349, -53, -546, +13, -497, 62, -213, 76, 161, 65, 435, +22, 499, -30, 340, -56, 35, -66, -274, +-55, -462, -17, -460, 12, -252, 17, 73, +30, 357, 45, 478, 44, 410, 40, 182, +24, -110, -23, -343, -63, -441, -65, -369, +-50, -148, -16, 128, 44, 321, 80, 370, +64, 280, 16, 83, -52, -141, -100, -293, +-77, -319, -3, -212, 71, -4, 127, 209, +132, 319, 52, 293, -68, 148, -160, -72, +-186, -275, -125, -366, -1, -301, 121, -100, +195, 157, 189, 352, 91, 397, -55, 279, +-164, 43, -201, -218, -155, -389, -27, -394, +116, -235, 194, 28, 186, 277, 102, 397, +-35, 342, -159, 146, -205, -108, -159, -303, +-43, -355, 81, -254, 149, -47, 152, 175, +109, 305, 22, 291, -79, 157, -130, -41, +-109, -214, -48, -282, 25, -229, 71, -89, +74, 91, 53, 236, 15, 277, -41, 211, +-82, 71, -74, -101, -29, -241, 29, -288, +71, -243, 68, -114, 34, 72, 10, 242, +-8, 320, -34, 292, -37, 165, -13, -31, +-2, -212, -17, -315, -41, -314, -50, -199, +-22, -4, 37, 177, 82, 273, 95, 271, +87, 169, 40, 4, -41, -137, -109, -209, +-132, -203, -106, -104, -29, 41, 64, 154, +117, 193, 114, 162, 64, 56, -25, -82, +-112, -192, -141, -238, -97, -194, 11, -59, +137, 114, 199, 249, 161, 306, 52, 255, +-95, 99, -222, -105, -249, -287, -157, -371, +-3, -304, 152, -110, 243, 121, 224, 304, +113, 366, -33, 272, -160, 61, -207, -169, +-153, -331, -40, -336, 81, -171, 169, 73, +174, 276, 87, 356, -37, 266, -150, 35, +-207, -219, -167, -391, -42, -399, 109, -212, +228, 90, 265, 347, 184, 460, 19, 387, +-157, 144, -281, -165, -292, -392, -171, -459, +13, -343, 181, -73, 279, 218, 256, 390, +116, 387, -66, 233, -202, -8, -241, -227, +-168, -330, -21, -288, 114, -123, 188, 96, +181, 248, 87, 264, -47, 171, -154, 20, +-192, -128, -151, -210, -45, -197, 73, -107, +151, 28, 178, 147, 149, 189, 50, 150, +-78, 66, -166, -28, -183, -110, -127, -156, +-16, -158, 100, -105, 178, -8, 190, 91, +106, 151, -51, 166, -181, 132, -219, 54, +-160, -49, -24, -149, 138, -197, 239, -156, +229, -42, 115, 70, -65, 140, -222, 154, +-264, 106, -181, 13, -16, -82, 156, -132, +240, -106, 206, -7, 86, 90, -82, 120, +-223, 84, -240, 8, -123, -88, 52, -148, +203, -138, 261, -60, 193, 58, 37, 162, +-137, 174, -261, 86, -266, -29, -139, -121, +42, -153, 194, -100, 258, 11, 206, 113, +67, 165, -76, 128, -176, -10, -206, -166, +-144, -232, -25, -180, 83, -33, 144, 151, +147, 279, 93, 289, 10, 174, -71, -37, +-136, -259, -153, -361, -101, -279, -8, -71, +83, 163, 158, 321, 178, 329, 114, 182, +1, -55, -110, -280, -191, -371, -204, -264, +-128, -13, 1, 249, 132, 397, 215, 357, +207, 148, 111, -134, -23, -369, -150, -452, +-225, -324, -196, -33, -77, 269, 63, 444, +172, 416, 204, 209, 136, -73, 10, -313, +-107, -417, -173, -335, -161, -93, -73, 186, +42, 361, 133, 362, 173, 195, 137, -58, +40, -273, -64, -363, -140, -300, -182, -97, +-153, 162, -45, 336, 85, 347, 182, 211, +216, -15, 162, -220, 45, -308, -82, -269, +-185, -134, -218, 64, -151, 228, -31, 262, +80, 170, 161, 14, 179, -138, 117, -204, +21, -162, -65, -64, -128, 56, -132, 161, +-72, 191, 7, 118, 73, -3, 109, -113, +90, -172, 36, -158, -19, -90, -78, -8, +-113, 80, -80, 154, -13, 159, 39, 102, +77, 18, 92, -63, 70, -113, 31, -124, +-10, -103, -55, -43, -83, 52, -79, 125, +-64, 129, -40, 73, 14, -14, 74, -91, +116, -120, 132, -101, 85, -40, -24, 62, +-130, 150, -183, 154, -175, 76, -89, -32, +62, -122, 203, -148, 262, -106, 205, -31, +38, 52, -156, 125, -275, 131, -283, 53, +-171, -47, 34, -106, 232, -107, 317, -51, +264, 27, 97, 75, -123, 93, -282, 84, +-304, 31, -202, -48, -14, -92, 190, -89, +306, -57, 290, -13, 159, 17, -46, 26, +-231, 38, -309, 53, -272, 42, -142, 17, +56, 4, 235, 1, 308, -9, 267, -20, +137, -31, -57, -26, -231, -4, -302, 6, +-252, -9, -102, -24, 89, -17, 228, 0, +258, 19, 191, 33, 41, 37, -133, 36, +-230, 32, -215, 5, -109, -32, 53, -47, +192, -31, 230, -11, 173, -5, 55, -10, +-105, -15, -233, -5, -255, 7, -176, 19, +-31, 37, 136, 56, 240, 55, 239, 25, +162, -21, 27, -62, -134, -65, -223, -29, +-196, 4, -97, 15, 30, 21, 133, 11, +155, -18, 105, -45, 23, -48, -71, -20, +-129, 47, -106, 104, -29, 96, 56, 51, +123, 4, 127, -48, 62, -92, -18, -91, +-86, -67, -137, -27, -126, 23, -46, 34, +41, 10, 99, 3, 116, 26, 80, 48, +24, 67, -21, 74, -58, 44, -68, -2, +-36, -47, -3, -104, 0, -135, 3, -103, +4, -35, -2, 31, 8, 78, 29, 94, +36, 83, 30, 64, 15, 31, -21, -16, +-48, -46, -43, -47, -24, -36, 10, -26, +52, -18, 57, -7, 16, 9, -31, 18, +-66, -2, -80, -32, -47, -38, 23, -15, +87, 26, 114, 66, 94, 91, 23, 94, +-59, 70, -115, 7, -128, -84, -83, -145, +2, -141, 72, -92, 95, -24, 83, 45, +45, 86, -11, 99, -51, 93, -53, 54, +-32, 3, -2, -10, 30, -6, 38, -21, +22, -39, -1, -54, -31, -63, -56, -44, +-60, -5, -48, 17, -18, 37, 43, 63, +102, 58, 111, 16, 83, -23, 33, -39, +-46, -26, -122, 13, -149, 38, -114, 33, +-24, 20, 78, 6, 123, -32, 104, -72, +55, -79, -13, -45, -79, 13, -94, 68, +-55, 88, 6, 74, 71, 48, 98, 0, +60, -63, -9, -104, -62, -97, -90, -49, +-84, 26, -40, 92, 23, 121, 86, 110, +119, 57, 87, -35, 10, -133, -56, -183, +-99, -163, -118, -71, -80, 54, 5, 159, +88, 209, 136, 192, 129, 102, 56, -34, +-45, -149, -122, -197, -155, -169, -124, -77, +-30, 32, 71, 104, 130, 129, 133, 105, +69, 32, -30, -48, -89, -88, -88, -81, +-53, -26, 9, 51, 72, 95, 80, 93, +30, 63, -41, 10, -93, -66, -89, -124, +-28, -134, 38, -96, 77, -25, 89, 50, +49, 100, -22, 115, -64, 109, -57, 74, +-21, 5, 36, -67, 83, -98, 65, -87, +-2, -49, -68, -5, -113, 31, -109, 55, +-46, 61, 39, 28, 109, -39, 143, -87, +107, -84, 18, -36, -62, 32, -101, 98, +-101, 137, -51, 139, 19, 85, 60, -32, +60, -157, 34, -217, -12, -189, -50, -93, +-48, 35, -22, 145, 17, 210, 55, 201, +55, 103, 26, -53, 7, -176, -6, -208, +-24, -139, -28, -11, -23, 113, -25, 188, +-25, 184, -19, 89, -9, -76, 14, -215, +44, -248, 57, -162, 50, -2, 27, 159, +-12, 252, -49, 246, -59, 143, -53, -31, +-39, -199, 0, -270, 47, -211, 67, -68, +57, 91, 35, 197, -3, 211, -49, 138, +-82, 15, -92, -114, -63, -188, 6, -159, +73, -56, 112, 54, 121, 132, 77, 151, +-18, 102, -105, 20, -152, -66, -145, -131, +-67, -138, 53, -73, 145, 17, 170, 86, +125, 125, 17, 110, -103, 47, -174, -32, +-168, -104, -76, -142, 68, -109, 179, -26, +200, 60, 134, 123, 3, 136, -139, 83, +-215, -3, -187, -85, -75, -136, 74, -124, +195, -54, 228, 35, 160, 99, 25, 119, +-123, 79, -221, 5, -221, -60, -136, -100, +0, -97, 150, -45, 246, 26, 235, 78, +126, 98, -25, 76, -171, 24, -257, -24, +-233, -55, -113, -76, 52, -72, 199, -47, +260, -20, 207, 11, 67, 47, -105, 75, +-226, 80, -235, 74, -143, 39, 3, -29, +155, -88, 249, -105, 217, -85, 80, -29, +-88, 42, -224, 88, -267, 97, -194, 69, +-41, 1, 134, -75, 268, -100, 290, -71, +178, -13, -3, 50, -182, 89, -288, 85, +-269, 52, -138, 0, 40, -62, 198, -89, +277, -66, 230, -22, 83, 13, -89, 33, +-217, 31, -247, 20, -164, 10, -19, -5, +130, -17, 239, -12, 250, 3, 142, 8, +-24, 6, -174, -3, -256, -8, -231, 0, +-110, 5, 47, -8, 189, -20, 263, -22, +221, -19, 83, -8, -78, 10, -208, 28, +-248, 43, -176, 49, -34, 27, 116, -14, +227, -45, 243, -58, 139, -59, -24, -38, +-180, -3, -266, 32, -231, 62, -85, 73, +101, 55, 248, 17, 295, -14, 208, -48, +22, -80, -176, -84, -305, -59, -304, -13, +-162, 45, 55, 95, 245, 111, 332, 93, +281, 44, 109, -33, -117, -110, -298, -139, +-354, -118, -251, -50, -35, 42, 190, 118, +333, 139, 346, 101, 214, 21, -20, -79, +-247, -139, -363, -132, -315, -62, -126, 41, +116, 135, 297, 162, 344, 108, 243, 4, +31, -108, -198, -181, -333, -178, -311, -94, +-142, 39, 91, 162, 270, 214, 320, 167, +238, 46, 59, -89, -153, -182, -301, -193, +-311, -117, -186, 10, 19, 136, 208, 198, +292, 160, 253, 38, 124, -99, -46, -187, +-190, -191, -250, -110, -211, 18, -89, 138, +70, 204, 186, 175, 210, 60, 162, -75, +70, -155, -48, -157, -156, -97, -208, 0, +-183, 80, -78, 114, 66, 91, 176, 19, +217, -62, 184, -87, 75, -46, -79, 16, +-211, 61, -265, 67, -208, 34, -43, -19, +152, -58, 269, -65, 267, -23, 163, 47, +-7, 89, -188, 61, -300, -16, -277, -98, +-114, -136, 103, -97, 260, -4, 299, 105, +213, 182, 32, 180, -166, 77, -293, -71, +-292, -182, -160, -202, 54, -118, 240, 26, +303, 152, 229, 202, 67, 154, -120, 21, +-261, -130, -296, -218, -207, -195, -22, -74, +177, 85, 291, 198, 281, 219, 172, 158, +0, 36, -188, -100, -304, -188, -295, -188, +-167, -113, 32, -4, 214, 87, 295, 130, +257, 118, 124, 65, -60, -14, -220, -85, +-279, -108, -216, -79, -52, -16, 137, 63, +247, 136, 233, 151, 129, 96, -22, -16, +-173, -142, -255, -230, -214, -229, -74, -131, +96, 31, 218, 205, 238, 305, 165, 274, +34, 128, -111, -64, -211, -233, -221, -297, +-147, -222, -22, -51, 109, 134, 187, 255, +184, 252, 111, 124, 3, -62, -102, -226, +-162, -288, -158, -221, -92, -52, 19, 146, +124, 297, 171, 340, 148, 246, 69, 46, +-40, -177, -137, -336, -180, -378, -160, -288, +-73, -89, 57, 157, 161, 345, 191, 398, +151, 294, 56, 80, -65, -162, -154, -334, +-178, -367, -134, -245, -28, -15, 92, 220, +159, 347, 152, 307, 93, 125, -1, -120, +-94, -316, -147, -367, -139, -247, -64, -20, +48, 224, 137, 379, 163, 358, 126, 171, +40, -80, -76, -283, -164, -362, -182, -280, +-125, -82, -7, 137, 119, 285, 189, 305, +174, 175, 87, -26, -37, -184, -150, -255, +-195, -216, -150, -81, -41, 91, 88, 211, +176, 241, 180, 165, 107, 18, -7, -120, +-118, -193, -175, -197, -153, -133, -72, -18, +25, 95, 103, 161, 133, 162, 115, 99, +65, 0, 4, -79, -50, -110, -79, -101, +-85, -60, -74, 9, -39, 74, 10, 95, +53, 67, 83, 2, 84, -59, 46, -87, +-8, -78, -55, -49, -84, 2, -75, 65, +-24, 106, 40, 97, 87, 51, 96, -9, +58, -61, -9, -89, -68, -91, -108, -62, +-121, -5, -81, 62, 8, 103, 95, 98, +145, 45, 148, -28, 95, -88, -1, -116, +-99, -98, -164, -32, -169, 61, -101, 139, +10, 168, 113, 109, 169, -11, 159, -122, +90, -182, -8, -178, -99, -100, -159, 22, +-156, 133, -80, 192, 30, 163, 117, 55, +152, -63, 129, -130, 59, -141, -38, -87, +-131, 10, -173, 98, -130, 135, -29, 106, +75, 19, 145, -84, 155, -138, 103, -128, +12, -68, -84, 16, -155, 98, -169, 137, +-105, 121, 14, 65, 127, -9, 188, -72, +176, -97, 95, -83, -32, -58, -159, -32, +-225, -10, -188, 8, -57, 28, 99, 56, +208, 70, 224, 72, 142, 58, 0, 11, +-137, -54, -222, -98, -213, -97, -99, -54, +63, 24, 187, 90, 226, 109, 163, 72, +24, -4, -116, -99, -206, -153, -221, -126, +-138, -34, 25, 91, 181, 198, 246, 224, +201, 148, 68, 4, -90, -153, -204, -260, +-240, -269, -178, -166, -28, 15, 141, 199, +232, 296, 208, 267, 103, 135, -35, -50, +-150, -209, -199, -284, -162, -238, -56, -80, +75, 119, 166, 249, 175, 260, 106, 158, +-7, -14, -112, -185, -161, -279, -137, -251, +-56, -105, 55, 106, 153, 271, 175, 311, +109, 218, -4, 34, -115, -171, -174, -308, +-158, -319, -80, -198, 34, 14, 146, 229, +196, 341, 152, 296, 45, 133, -75, -74, +-168, -248, -184, -320, -119, -248, -16, -72, +90, 132, 167, 276, 165, 286, 77, 168, +-40, -7, -128, -162, -149, -252, -102, -235, +-19, -113, 66, 57, 129, 194, 140, 242, +79, 176, -24, 37, -112, -100, -150, -189, +-115, -207, -33, -140, 54, -3, 124, 127, +162, 196, 129, 176, 21, 81, -99, -45, +-161, -142, -150, -176, -84, -140, 6, -44, +93, 78, 156, 164, 160, 169, 81, 100, +-36, -15, -123, -117, -156, -162, -135, -139, +-59, -72, 41, 36, 122, 148, 167, 190, +151, 135, 58, 22, -65, -91, -149, -173, +-167, -181, -122, -124, -33, -21, 74, 105, +160, 194, 174, 191, 90, 109, -36, 1, +-117, -98, -130, -161, -93, -163, -19, -105, +55, -19, 96, 67, 93, 120, 39, 123, +-39, 77, -73, 19, -53, -29, -18, -63, +12, -66, 24, -41, 9, -7, -1, 25, +8, 52, -2, 45, -12, 10, 22, -27, +58, -61, 31, -89, -31, -78, -71, -21, +-71, 51, -34, 119, 15, 160, 57, 143, +89, 65, 92, -38, 30, -148, -63, -217, +-118, -206, -115, -116, -64, 10, 18, 142, +86, 234, 117, 225, 120, 121, 75, -18, +-18, -136, -103, -202, -135, -178, -109, -75, +-45, 53, 29, 149, 84, 169, 119, 97, +118, -18, 53, -113, -43, -166, -104, -159, +-116, -73, -93, 55, -30, 157, 57, 206, +125, 185, 146, 96, 93, -25, -24, -136, +-138, -216, -181, -235, -140, -166, -40, -33, +80, 117, 169, 232, 189, 273, 121, 210, +-13, 64, -136, -118, -173, -266, -130, -310, +-45, -215, 59, -22, 139, 178, 150, 303, +95, 301, -4, 168, -112, -56, -160, -268, +-122, -366, -38, -293, 63, -74, 149, 184, +167, 355, 110, 373, 8, 233, -112, -32, +-196, -305, -172, -440, -63, -365, 60, -120, +151, 198, 182, 438, 132, 480, 10, 307, +-122, -3, -191, -335, -159, -540, -46, -507, +85, -255, 172, 113, 177, 441, 99, 579, +-29, 463, -148, 171, -198, -175, -148, -450, +-23, -538, 110, -383, 194, -69, 192, 244, +102, 428, -38, 405, -160, 203, -209, -77, +-164, -309, -37, -406, 110, -305, 197, -42, +193, 241, 114, 411, -11, 405, -136, 219, +-197, -75, -165, -336, -69, -457, 44, -398, +128, -177, 154, 115, 116, 343, 37, 419, +-49, 327, -104, 116, -105, -113, -62, -258, +-5, -279, 41, -193, 61, -37, 52, 109, +26, 174, -2, 140, -26, 54, -45, -43, +-50, -114, -37, -124, -4, -74, 39, 1, +67, 70, 71, 120, 56, 128, 17, 102, +-44, 41, -94, -41, -101, -121, -70, -161, +-13, -160, 50, -125, 89, -30, 94, 110, +77, 215, 31, 229, -40, 160, -91, 32, +-98, -111, -72, -223, -14, -255, 61, -184, +100, -15, 87, 170, 52, 270, -6, 246, +-73, 121, -97, -59, -69, -224, -26, -290, +16, -231, 49, -69, 64, 131, 66, 287, +55, 304, 20, 178, -28, -15, -65, -189, +-87, -282, -91, -258, -56, -124, 15, 66, +91, 234, 132, 292, 110, 208, 31, 44, +-60, -111, -124, -227, -131, -268, -73, -192, +8, -27, 67, 146, 100, 255, 101, 266, +57, 168, -4, 11, -46, -141, -76, -243, +-97, -257, -90, -159, -49, 1, 30, 150, +129, 235, 173, 223, 122, 108, 15, -48, +-99, -163, -190, -217, -200, -187, -97, -63, +66, 104, 203, 215, 239, 231, 151, 152, +-7, 2, -148, -148, -227, -242, -210, -252, +-92, -159, 60, 23, 180, 190, 231, 257, +182, 228, 47, 126, -96, -26, -180, -161, +-202, -225, -148, -207, -19, -109, 115, 32, +195, 141, 193, 169, 97, 145, -39, 74, +-133, -28, -166, -120, -142, -159, -45, -131, +80, -40, 141, 77, 117, 153, 50, 156, +-26, 101, -76, 15, -77, -97, -44, -176, +2, -174, 36, -92, 36, 22, 15, 123, +1, 161, 2, 129, 10, 69, 9, -3, +-17, -84, -45, -139, -42, -127, -15, -72, +25, -3, 73, 67, 89, 118, 51, 126, +-10, 90, -68, 4, -112, -112, -102, -178, +-30, -148, 44, -45, 83, 80, 93, 194, +73, 220, 27, 129, -23, -26, -68, -175, +-91, -263, -66, -231, -17, -74, 13, 113, +40, 237, 86, 251, 110, 153, 65, -6, +-20, -134, -96, -200, -130, -194, -110, -103, +-44, 38, 55, 133, 154, 146, 181, 113, +108, 51, -22, -27, -146, -95, -209, -128, +-168, -117, -38, -44, 107, 57, 206, 130, +217, 155, 124, 133, -45, 44, -206, -87, +-269, -187, -191, -215, -12, -160, 160, -25, +252, 143, 242, 241, 121, 231, -71, 132, +-228, -22, -254, -179, -154, -256, -8, -211, +115, -75, 188, 99, 194, 219, 115, 223, +-13, 126, -124, -6, -183, -145, -181, -231, +-108, -195, 21, -59, 155, 85, 238, 185, +219, 214, 84, 152, -106, 34, -253, -90, +-287, -182, -183, -202, 18, -128, 211, -14, +292, 87, 231, 155, 65, 174, -133, 121, +-259, 18, -244, -82, -107, -159, 68, -176, +194, -112, 222, 1, 153, 100, 20, 170, +-110, 181, -180, 104, -174, -28, -95, -148, +20, -214, 113, -196, 155, -81, 157, 62, +102, 174, -19, 221, -136, 179, -178, 44, +-147, -105, -65, -186, 50, -176, 146, -81, +170, 59, 111, 156, -3, 152, -106, 71, +-144, -48, -112, -152, -41, -175, 41, -83, +95, 60, 91, 170, 50, 193, 6, 116, +-38, -19, -69, -127, -59, -159, -22, -119, +8, -11, 17, 100, 17, 129, 28, 63, +37, -24, 11, -91, -27, -110, -27, -51, +-8, 50, -19, 117, -29, 120, 3, 62, +41, -38, 50, -110, 33, -112, 3, -57, +-22, 27, -37, 108, -53, 114, -56, 32, +-26, -66, 21, -131, 63, -153, 96, -100, +104, 34, 65, 164, -5, 211, -89, 156, +-159, 37, -164, -97, -80, -187, 58, -201, +182, -123, 216, 25, 135, 158, -5, 180, +-142, 96, -227, -4, -201, -93, -54, -148, +119, -129, 219, -14, 212, 116, 94, 182, +-72, 153, -181, 49, -194, -71, -137, -150, +-17, -163, 121, -115, 182, -13, 143, 88, +55, 129, -38, 111, -108, 62, -130, -15, +-99, -77, -42, -75, 28, -37, 85, -16, +112, 0, 108, 39, 68, 60, -4, 50, +-79, 22, -127, -2, -141, -23, -107, -46, +-17, -92, 95, -123, 176, -73, 182, 26, +111, 109, 2, 169, -114, 207, -215, 158, +-230, 13, -116, -158, 57, -277, 190, -302, +251, -198, 215, 1, 69, 213, -122, 357, +-259, 357, -272, 186, -158, -86, 30, -323, +200, -445, 282, -376, 246, -107, 93, 248, +-106, 495, -249, 523, -282, 320, -201, -54, +-32, -435, 158, -630, 273, -529, 259, -173, +132, 283, -46, 606, -192, 633, -254, 367, +-202, -70, -55, -494, 108, -677, 203, -504, +206, -88, 133, 359, 10, 640, -116, 622, +-185, 295, -176, -174, -111, -571, -1, -718, +123, -540, 201, -111, 194, 356, 109, 661, +-21, 696, -152, 441, -224, -5, -196, -446, +-79, -683, 79, -629, 206, -301, 230, 157, +132, 529, -19, 648, -134, 473, -174, 77, +-131, -368, -23, -638, 86, -594, 127, -254, +88, 220, 6, 603, -63, 691, -64, 444, +-11, -11, 34, -465, 39, -720, 19, -631, +-20, -232, -63, 266, -64, 622, -12, 666, +51, 392, 84, -55, 77, -444, 35, -607, +-25, -467, -76, -78, -96, 356, -76, 574, +-30, 474, 31, 139, 98, -266, 134, -539, +103, -528, 16, -236, -84, 178, -163, 511, +-172, 564, -88, 307, 49, -96, 179, -424, +231, -533, 162, -359, 6, 23, -146, 380, +-234, 510, -228, 360, -106, 18, 80, -344, +220, -516, 259, -410, 196, -89, 43, 289, +-134, 531, -250, 497, -265, 208, -165, -182, +16, -497, 188, -572, 271, -359, 247, 27, +114, 387, -70, 580, -207, 517, -246, 201, +-186, -231, -43, -562, 120, -625, 206, -403, +189, -1, 101, 396, -17, 630, -107, 596, +-133, 289, -120, -172, -71, -555, 21, -667, +102, -480, 124, -100, 112, 320, 72, 606, +-11, 617, -102, 347, -157, -76, -152, -459, +-67, -631, 73, -513, 177, -181, 191, 217, +126, 521, 13, 606, -106, 434, -181, 78, +-183, -308, -105, -570, 27, -588, 133, -353, +170, 18, 151, 369, 90, 583, -8, 568, +-107, 303, -181, -101, -189, -459, -85, -618, +73, -517, 174, -195, 195, 209, 156, 539, +34, 653, -119, 478, -207, 61, -194, -391, +-85, -663, 80, -646, 188, -343, 177, 123, +104, 550, 6, 742, -108, 610, -175, 189, +-153, -329, -72, -690, 44, -723, 147, -445, +173, 9, 128, 448, 53, 693, -44, 645, +-143, 307, -182, -173, -142, -566, -36, -672, +104, -483, 197, -124, 186, 269, 103, 577, +-13, 654, -134, 430, -203, 2, -175, -427, +-57, -661, 95, -601, 203, -291, 205, 123, +121, 509, 6, 709, -118, 593, -213, 186, +-214, -304, -113, -647, 40, -690, 179, -424, +246, 9, 210, 414, 91, 648, -65, 617, +-201, 283, -253, -198, -186, -573, -32, -656, +141, -447, 246, -66, 236, 321, 132, 578, +-15, 619, -166, 391, -256, -38, -222, -455, +-74, -649, 108, -565, 239, -272, 259, 112, +179, 467, 40, 651, -127, 575, -262, 249, +-277, -193, -152, -545, 28, -655, 177, -495, +266, -152, 277, 256, 183, 569, 6, 648, +-184, 442, -316, 30, -324, -403, -183, -647, +51, -598, 276, -300, 403, 116, 368, 491, +156, 675, -151, 559, -400, 189, -477, -259, +-328, -580, -2, -644, 333, -440, 505, -72, +456, 312, 211, 573, -145, 596, -442, 359, +-525, -20, -356, -366, -20, -555, 326, -515, +512, -276, 459, 66, 213, 385, -121, 567, +-399, 518, -478, 238, -328, -139, -41, -457, +254, -597, 425, -504, 398, -204, 210, 180, +-42, 511, -262, 648, -357, 507, -299, 142, +-137, -268, 70, -562, 256, -637, 334, -452, +277, -78, 144, 339, -32, 620, -218, 646, +-338, 381, -322, -55, -161, -471, 95, -701, +330, -646, 425, -305, 345, 189, 114, 621, +-195, 805, -430, 648, -451, 202, -254, -343, +63, -734, 357, -820, 483, -570, 378, -77, +99, 453, -213, 780, -403, 761, -382, 418, +-195, -96, 63, -542, 305, -732, 406, -608, +289, -235, 55, 239, -148, 591, -266, 669, +-271, 463, -155, 72, 11, -354, 152, -633, +230, -633, 202, -373, 93, 34, 0, 426, +-54, 651, -109, 614, -142, 337, -128, -90, +-86, -497, 8, -695, 149, -596, 244, -265, +246, 168, 167, 546, -2, 699, -224, 556, +-372, 172, -350, -287, -142, -630, 183, -692, +449, -450, 502, -23, 337, 413, 20, 677, +-343, 654, -566, 355, -508, -91, -199, -506, +226, -705, 563, -601, 616, -243, 374, 195, +-15, 553, -398, 698, -611, 562, -519, 182, +-172, -299, 247, -666, 561, -748, 622, -499, +385, -31, -13, 471, -380, 794, -582, 786, +-521, 406, -216, -190, 168, -727, 472, -940, +588, -723, 444, -169, 100, 480, -258, 911, +-474, 929, -488, 521, -302, -119, 1, -706, +303, -962, 494, -766, 480, -219, 254, 406, +-51, 824, -307, 859, -448, 518, -401, -26, +-172, -555, 112, -848, 342, -779, 458, -375, +393, 166, 160, 629, -119, 852, -333, 752, +-413, 368, -322, -171, -107, -677, 136, -949, +338, -838, 420, -372, 316, 259, 79, 810, +-163, 1067, -320, 882, -350, 309, -242, -423, +-41, -1020, 178, -1200, 339, -843, 373, -91, +255, 711, 45, 1238, -169, 1245, -309, 696, +-330, -172, -233, -983, -45, -1407, 186, -1228, +366, -493, 396, 464, 271, 1221, 54, 1470, +-173, 1108, -330, 264, -365, -690, -275, -1361, +-71, -1467, 195, -946, 406, -9, 454, 920, +331, 1453, 90, 1399, -195, 763, -431, -217, +-519, -1116, -388, -1552, -61, -1356, 322, -587, +571, 444, 598, 1299, 405, 1620, 44, 1295, +-361, 435, -635, -629, -642, -1430, -367, -1651, +69, -1217, 477, -283, 711, 778, 677, 1498, +376, 1597, -86, 1073, -518, 136, -743, -875, +-662, -1520, -291, -1536, 216, -938, 646, 36, +831, 976, 703, 1511, 284, 1454, -285, 846, +-759, -127, -908, -1082, -657, -1585, -121, -1450, +475, -767, 895, 221, 976, 1146, 665, 1636, +51, 1504, -629, 781, -1041, -279, -982, -1266, +-511, -1749, 163, -1559, 797, -757, 1133, 371, +997, 1382, 428, 1859, -341, 1614, -979, 714, +-1170, -540, -830, -1618, -152, -2023, 574, -1592, +1075, -511, 1133, 821, 711, 1861, 3, 2164, +-694, 1548, -1074, 229, -965, -1235, -468, -2189, +169, -2204, 728, -1302, 1019, 162, 913, 1596, +454, 2383, -177, 2152, -734, 994, -966, -587, +-792, -1911, -352, -2422, 203, -1903, 732, -606, +1003, 906, 853, 2022, 357, 2287, -271, 1613, +-784, 287, -966, -1119, -777, -2029, -308, -2079, +320, -1282, 876, -24, 1066, 1187, 802, 1917, +232, 1887, -431, 1086, -928, -138, -1044, -1267, +-739, -1861, -124, -1714, 598, -883, 1108, 268, +1138, 1297, 680, 1819, -52, 1607, -758, 738, +-1142, -411, -1047, -1364, -516, -1768, 269, -1455, +977, -561, 1256, 516, 981, 1355, 315, 1667, +-453, 1307, -1009, 425, -1137, -590, -809, -1330, +-135, -1543, 632, -1166, 1120, -345, 1086, 572, +612, 1263, -62, 1475, -686, 1107, -1010, 308, +-902, -590, -434, -1259, 205, -1457, 751, -1080, +942, -259, 739, 656, 290, 1310, -225, 1455, +-629, 1001, -767, 143, -621, -762, -247, -1341, +248, -1383, 651, -859, 769, 10, 588, 842, +218, 1310, -216, 1239, -567, 674, -702, -124, +-559, -819, -160, -1181, 328, -1100, 650, -593, +697, 143, 513, 770, 152, 1077, -288, 988, +-613, 543, -688, -84, -496, -667, -89, -1007, +376, -987, 692, -577, 737, 57, 493, 647, +26, 991, -466, 966, -758, 560, -737, -47, +-389, -622, 168, -982, 657, -979, 831, -558, +644, 104, 198, 681, -316, 977, -665, 899, +-699, 486, -421, -102, 33, -658, 436, -984, +613, -922, 540, -473, 279, 135, -62, 645, +-333, 925, -426, 890, -351, 524, -162, -23, +71, -567, 267, -931, 363, -974, 339, -642, +198, -66, -11, 524, -196, 944, -301, 1040, +-306, 751, -189, 161, 16, -529, 209, -1062, +332, -1185, 354, -805, 227, -85, -16, 661, +-256, 1182, -390, 1259, -356, 792, -156, -40, +123, -872, 358, -1357, 455, -1309, 368, -690, +102, 237, -221, 1066, -426, 1474, -415, 1284, +-214, 538, 79, -428, 350, -1201, 473, -1502, +382, -1204, 124, -372, -191, 621, -420, 1301, +-432, 1449, -228, 1018, 88, 161, 375, -748, +489, -1308, 354, -1328, 56, -816, -252, 54, +-450, 874, -423, 1275, -157, 1152, 186, 580, +413, -233, 444, -910, 260, -1174, -66, -977, +-345, -414, -428, 337, -309, 919, -36, 1056, +267, 784, 419, 248, 362, -356, 158, -786, +-122, -872, -360, -641, -398, -190, -234, 330, +11, 671, 261, 686, 426, 482, 390, 161, +187, -211, -63, -485, -301, -562, -427, -448, +-341, -198, -89, 131, 191, 365, 398, 436, +433, 408, 271, 276, 24, 22, -211, -239, +-374, -392, -376, -432, -196, -339, 61, -122, +263, 117, 339, 308, 274, 459, 123, 464, +-45, 271, -200, -38, -294, -342, -271, -550, +-133, -562, 57, -336, 215, 23, 279, 408, +253, 690, 176, 686, 31, 345, -175, -149, +-341, -580, -360, -791, -210, -692, 43, -276, +285, 270, 426, 698, 439, 850, 289, 641, +-29, 172, -376, -346, -557, -708, -491, -810, +-190, -605, 206, -147, 487, 347, 565, 669, +468, 764, 173, 602, -255, 205, -579, -282, +-644, -672, -436, -831, -33, -683, 376, -217, +597, 348, 604, 769, 401, 920, -11, 716, +-462, 184, -707, -459, -652, -935, -319, -1060, +176, -725, 572, -24, 691, 681, 568, 1064, +252, 1061, -211, 646, -605, -84, -703, -817, +-503, -1197, -117, -1077, 309, -507, 588, 300, +628, 946, 465, 1180, 130, 974, -280, 373, +-565, -439, -610, -1070, -436, -1216, -79, -856, +330, -148, 588, 652, 613, 1151, 420, 1130, +42, 678, -387, -50, -654, -801, -646, -1212, +-385, -1059, 25, -471, 420, 287, 651, 933, +637, 1156, 369, 880, -66, 296, -482, -399, +-714, -970, -687, -1097, -405, -721, 63, -105, +547, 487, 832, 915, 771, 951, 385, 586, +-175, 47, -683, -492, -921, -859, -780, -844, +-305, -471, 320, 4, 832, 456, 1000, 772, +744, 754, 164, 428, -489, 5, -933, -435, +-983, -739, -626, -709, -19, -390, 607, 15, +1012, 413, 979, 704, 484, 686, -219, 386, +-801, -34, -1050, -456, -886, -711, -357, -645, +332, -332, 896, 67, 1074, 463, 758, 714, +90, 644, -601, 317, -1003, -97, -971, -499, +-539, -719, 105, -637, 691, -301, 962, 119, +812, 505, 307, 722, -321, 635, -751, 295, +-804, -142, -542, -540, -128, -741, 313, -619, +631, -251, 695, 185, 478, 555, 62, 745, +-362, 603, -590, 208, -577, -243, -406, -630, +-105, -790, 280, -595, 567, -131, 599, 349, +387, 713, 17, 831, -377, 576, -612, 69, +-600, -445, -388, -827, -29, -890, 369, -533, +609, 48, 566, 562, 276, 870, -144, 860, +-485, 445, -569, -138, -442, -616, -200, -872, +143, -786, 450, -325, 501, 252, 306, 657, +21, 808, -250, 648, -390, 188, -343, -319, +-190, -645, 9, -750, 220, -546, 316, -71, +239, 412, 82, 666, -74, 676, -198, 438, +-236, -18, -195, -444, -127, -659, -18, -649, +123, -393, 199, 70, 166, 486, 86, 659, +-22, 603, -142, 349, -214, -83, -219, -471, +-154, -651, -18, -632, 112, -365, 141, 103, +107, 518, 65, 672, 4, 610, -75, 334, +-142, -141, -171, -561, -119, -719, -12, -618, +62, -250, 89, 279, 90, 662, 42, 723, +-35, 531, -89, 135, -105, -385, -59, -711, +34, -710, 76, -459, 19, -9, -66, 481, +-115, 721, -95, 635, 1, 365, 100, -44, +126, -490, 78, -711, -32, -623, -191, -333, +-294, 110, -249, 525, -74, 689, 143, 573, +298, 285, 282, -141, 104, -567, -113, -715, +-295, -547, -391, -182, -328, 263, -122, 614, +102, 673, 271, 453, 341, 77, 260, -344, +65, -644, -157, -625, -344, -329, -409, 55, +-298, 408, -82, 585, 165, 501, 370, 217, +405, -101, 231, -385, -41, -533, -304, -420, +-458, -135, -407, 135, -183, 329, 84, 411, +299, 325, 394, 128, 306, -77, 77, -253, +-197, -357, -419, -278, -484, -109, -351, 33, +-101, 164, 163, 265, 362, 256, 403, 157, +243, 51, -26, -93, -274, -236, -425, -260, +-411, -189, -243, -104, -41, 41, 127, 206, +255, 282, 288, 245, 210, 143, 86, -42, +-69, -243, -247, -301, -359, -249, -359, -135, +-260, 52, -40, 250, 235, 310, 413, 235, +425, 105, 265, -81, -56, -264, -403, -293, +-589, -193, -555, -62, -321, 102, 76, 227, +464, 232, 622, 144, 498, 57, 168, -74, +-281, -196, -675, -177, -796, -84, -601, -25, +-190, 38, 321, 106, 711, 100, 758, 73, +466, 77, -23, 40, -556, -38, -889, -43, +-832, -54, -449, -128, 91, -163, 605, -114, +843, -17, 673, 140, 237, 314, -269, 323, +-701, 175, -869, -8, -666, -244, -229, -478, +262, -494, 664, -251, 794, 119, 565, 484, +107, 681, -407, 538, -819, 137, -911, -283, +-614, -631, -107, -749, 415, -507, 792, -15, +815, 474, 455, 777, -81, 755, -603, 355, +-937, -191, -895, -591, -491, -766, 62, -665, +571, -249, 840, 287, 731, 684, 309, 795, +-234, 582, -724, 92, -944, -408, -754, -690, +-260, -729, 292, -491, 696, -5, 809, 476, +559, 704, 51, 650, -480, 336, -823, -155, +-844, -547, -506, -623, 58, -460, 567, -132, +782, 260, 635, 496, 212, 474, -311, 267, +-716, -29, -835, -321, -612, -395, -129, -248, +388, -68, 663, 90, 578, 217, 241, 209, +-175, 91, -535, 6, -669, -28, -502, -66, +-171, -54, 183, 3, 441, -24, 425, -80, +134, -95, -179, -80, -366, -22, -411, 101, +-268, 190, -22, 160, 147, 112, 223, 66, +210, -75, 18, -233, -232, -264, -317, -210, +-239, -105, -97, 73, 86, 259, 203, 323, +161, 303, 44, 209, -101, -43, -291, -326, +-382, -460, -257, -420, -41, -224, 159, 134, +305, 457, 264, 550, 28, 462, -190, 224, +-338, -220, -463, -621, -425, -696, -165, -469, +137, -64, 356, 402, 438, 716, 278, 691, +-43, 430, -330, 0, -531, -522, -606, -823, +-432, -702, -70, -324, 284, 140, 526, 583, +564, 781, 318, 630, -97, 286, -450, -138, +-664, -579, -685, -769, -435, -610, 25, -262, +471, 137, 717, 509, 642, 691, 227, 607, +-311, 357, -707, -40, -858, -495, -722, -745, +-272, -677, 306, -405, 720, 18, 810, 506, +546, 832, 9, 823, -564, 513, -922, -37, +-949, -662, -641, -1025, -95, -971, 485, -542, +860, 135, 872, 840, 507, 1211, -96, 1073, +-680, 527, -1017, -267, -1007, -1034, -639, -1370, +-11, -1120, 623, -440, 986, 438, 942, 1180, +502, 1421, -192, 1056, -838, 320, -1161, -563, +-1047, -1261, -528, -1401, 206, -955, 835, -170, +1100, 688, 899, 1286, 294, 1312, -466, 812, +-1060, 51, -1246, -743, -946, -1278, -277, -1255, +469, -739, 990, 32, 1086, 818, 710, 1290, +11, 1207, -717, 670, -1163, -72, -1151, -841, +-706, -1317, -38, -1230, 583, -660, 926, 136, +886, 912, 492, 1338, -97, 1223, -669, 652, +-1007, -148, -963, -941, -562, -1394, -6, -1252, +482, -632, 785, 220, 804, 1017, 482, 1433, +-58, 1250, -598, 568, -942, -317, -927, -1107, +-562, -1477, -42, -1215, 466, -450, 811, 475, +826, 1219, 478, 1465, -88, 1094, -671, 287, +-1026, -586, -972, -1241, -569, -1403, -16, -955, +510, -151, 843, 639, 850, 1165, 506, 1258, +-89, 840, -703, 127, -1061, -561, -1020, -1034, +-631, -1150, -54, -814, 526, -206, 910, 430, +928, 930, 541, 1114, -104, 868, -743, 323, +-1097, -303, -1023, -891, -584, -1181, 27, -968, +594, -378, 929, 325, 902, 943, 481, 1232, +-203, 1020, -834, 402, -1107, -368, -958, -1043, +-489, -1323, 127, -1027, 668, -331, 938, 472, +827, 1116, 346, 1349, -315, 1018, -851, 285, +-1062, -544, -905, -1218, -463, -1436, 91, -1018, +597, -177, 904, 679, 856, 1289, 416, 1435, +-228, 991, -813, 133, -1127, -757, -1059, -1400, +-619, -1498, 53, -918, 725, 16, 1132, 870, +1058, 1403, 490, 1427, -331, 834, -1034, -82, +-1343, -921, -1152, -1444, -526, -1409, 302, -718, +1015, 236, 1298, 998, 994, 1391, 245, 1274, +-603, 610, -1222, -289, -1390, -1032, -1035, -1428, +-291, -1237, 548, -458, 1159, 458, 1264, 1093, +805, 1341, -5, 1095, -827, 362, -1333, -488, +-1330, -1104, -846, -1351, -68, -1057, 721, -243, +1169, 607, 1085, 1114, 570, 1219, -159, 902, +-857, 206, -1242, -542, -1163, -1046, -676, -1201, +50, -863, 737, -113, 1078, 600, 948, 970, +446, 1024, -251, 730, -886, 120, -1182, -507, +-1017, -885, -485, -977, 201, -691, 770, -69, +982, 522, 780, 830, 275, 872, -370, 643, +-916, 136, -1107, -410, -884, -794, -358, -944, +277, -727, 758, -155, 889, 437, 667, 811, +175, 951, -441, 772, -909, 244, -1017, -386, +-758, -847, -262, -1052, 288, -849, 672, -248, +765, 436, 557, 897, 119, 1040, -400, 798, +-790, 224, -883, -409, -657, -876, -218, -1059, +262, -816, 604, -178, 691, 492, 497, 900, +67, 970, -438, 704, -766, 155, -773, -444, +-512, -864, -106, -998, 315, -738, 556, -140, +517, 507, 272, 907, -69, 973, -399, 699, +-581, 161, -554, -444, -369, -902, -122, -1075, +113, -811, 278, -159, 331, 534, 260, 971, +78, 1060, -163, 803, -377, 226, -486, -463, +-465, -1005, -311, -1194, -67, -897, 159, -201, +295, 554, 336, 1064, 247, 1202, 21, 903, +-251, 235, -471, -544, -553, -1139, -452, -1332, +-214, -954, 83, -155, 374, 671, 531, 1208, +441, 1313, 128, 921, -287, 137, -637, -712, +-762, -1309, -614, -1411, -258, -921, 200, -43, +594, 809, 735, 1352, 541, 1414, 89, 928, +-447, 56, -852, -843, -947, -1456, -698, -1547, +-211, -981, 337, 5, 750, 970, 841, 1569, +556, 1602, 20, 985, -555, -52, -954, -1082, +-1014, -1717, -710, -1676, -161, -897, 443, 265, +860, 1273, 894, 1779, 555, 1590, -19, 725, +-637, -447, -1048, -1391, -1073, -1794, -711, -1492, +-71, -527, 610, 652, 1016, 1496, 977, 1739, +530, 1327, -169, 366, -857, -725, -1243, -1491, +-1160, -1706, -625, -1272, 171, -271, 879, 809, +1185, 1493, 972, 1635, 338, 1181, -459, 225, +-1105, -796, -1353, -1449, -1100, -1593, -410, -1140, +450, -186, 1084, 809, 1206, 1418, 809, 1516, +77, 1047, -705, 141, -1223, -769, -1276, -1346, +-847, -1468, -98, -1017, 654, -99, 1072, 798, +1016, 1334, 533, 1405, -172, 938, -782, 61, +-1075, -797, -1016, -1317, -602, -1385, 56, -913, +649, -29, 921, 827, 815, 1323, 374, 1345, +-230, 829, -727, -26, -968, -804, -906, -1247, +-518, -1297, 65, -841, 576, 10, 820, 801, +718, 1234, 305, 1239, -226, 775, -656, -8, +-869, -719, -812, -1152, -472, -1218, 22, -797, +448, -10, 669, 714, 635, 1127, 329, 1155, +-112, 726, -486, 4, -730, -652, -785, -1048, +-549, -1122, -111, -736, 322, -21, 627, 635, +706, 1018, 473, 1067, 18, 699, -458, 59, +-802, -542, -888, -961, -639, -1095, -157, -789, +364, -151, 758, 485, 846, 970, 527, 1164, +-34, 895, -577, 259, -947, -438, -1010, -1010, +-677, -1277, -97, -1033, 477, -353, 880, 466, +930, 1146, 533, 1412, -107, 1075, -690, 312, +-1065, -545, -1077, -1218, -658, -1454, -12, -1082, +597, -245, 988, 675, 958, 1327, 454, 1443, +-238, 964, -807, 110, -1104, -742, -1001, -1309, +-496, -1387, 154, -903, 684, -41, 945, 817, +810, 1347, 304, 1348, -311, 802, -788, -34, +-1020, -821, -892, -1313, -417, -1342, 162, -804, +634, 86, 890, 912, 774, 1366, 294, 1291, +-292, 690, -786, -165, -1046, -919, -913, -1341, +-418, -1234, 181, -593, 668, 268, 900, 952, +757, 1262, 272, 1090, -332, 472, -830, -298, +-1037, -897, -837, -1166, -336, -991, 212, -402, +643, 296, 857, 831, 720, 1074, 250, 929, +-336, 406, -818, -248, -1020, -791, -820, -1061, +-313, -919, 241, -393, 683, 248, 901, 772, +733, 1057, 201, 926, -431, 389, -910, -286, +-1052, -805, -771, -1021, -221, -843, 331, -329, +743, 287, 904, 769, 670, 979, 85, 799, +-552, 266, -955, -319, -995, -723, -664, -873, +-119, -716, 398, -259, 748, 280, 829, 686, +522, 845, -55, 676, -582, 216, -866, -284, +-847, -621, -518, -775, -34, -651, 376, -224, +636, 280, 688, 615, 427, 737, -66, 591, +-524, 191, -756, -250, -727, -548, -455, -685, +-30, -588, 370, -200, 605, 246, 590, 533, +294, 639, -144, 526, -503, 183, -664, -196, +-585, -476, -284, -619, 65, -514, 291, -155, +379, 212, 341, 407, 159, 489, -83, 428, +-274, 180, -394, -105, -419, -292, -311, -414, +-140, -405, 15, -229, 163, -21, 292, 147, +313, 328, 179, 461, -58, 407, -305, 206, +-466, -74, -465, -404, -313, -625, -112, -556, +111, -282, 355, 95, 478, 530, 357, 802, +57, 698, -293, 276, -557, -257, -616, -732, +-479, -914, -218, -658, 148, -131, 507, 402, +654, 818, 494, 918, 95, 581, -388, 19, +-734, -508, -780, -850, -567, -847, -218, -458, +221, 74, 643, 512, 812, 770, 597, 767, +93, 438, -484, -52, -889, -492, -946, -774, +-675, -760, -189, -409, 402, 74, 872, 477, +962, 743, 602, 761, -53, 448, -705, -67, +-1048, -530, -969, -803, -559, -764, 26, -379, +599, 129, 933, 519, 883, 733, 471, 716, +-173, 401, -795, -87, -1092, -526, -949, -745, +-485, -687, 128, -368, 710, 67, 1042, 435, +920, 682, 355, 742, -383, 490, -974, -2, +-1180, -482, -901, -785, -274, -799, 391, -483, +840, 35, 946, 508, 691, 807, 158, 844, +-471, 507, -931, -81, -1015, -606, -716, -878, +-188, -816, 358, -402, 745, 150, 874, 594, +669, 818, 140, 765, -495, 396, -935, -151, +-1007, -625, -672, -850, -65, -744, 511, -324, +817, 203, 796, 596, 473, 799, -61, 729, +-590, 339, -877, -208, -809, -659, -445, -858, +41, -706, 436, -252, 624, 274, 606, 647, +377, 795, -31, 691, -469, 292, -739, -238, +-738, -666, -471, -848, -34, -691, 390, -243, +616, 262, 588, 650, 348, 830, -60, 700, +-485, 276, -703, -281, -636, -743, -349, -902, +36, -646, 342, -128, 473, 397, 449, 751, +271, 819, -39, 551, -349, 81, -525, -407, +-538, -758, -390, -789, -87, -478, 247, -7, +442, 413, 481, 669, 360, 699, 43, 486, +-344, 76, -594, -378, -617, -719, -400, -789, +-26, -496, 313, 0, 485, 455, 466, 740, +265, 762, -74, 440, -397, -82, -544, -556, +-481, -795, -268, -696, 6, -267, 226, 247, +331, 585, 342, 686, 237, 516, 6, 133, +-237, -253, -390, -488, -432, -564, -349, -435, +-150, -121, 89, 204, 295, 404, 415, 472, +362, 402, 106, 194, -219, -84, -428, -359, +-468, -531, -379, -490, -174, -220, 99, 123, +331, 409, 421, 553, 320, 475, 89, 185, +-151, -181, -347, -462, -473, -574, -467, -436, +-304, -81, -7, 279, 329, 451, 557, 459, +556, 333, 278, 66, -168, -221, -572, -393, +-785, -435, -705, -319, -297, -61, 269, 167, +721, 297, 830, 376, 523, 367, -43, 187, +-573, -87, -832, -324, -745, -451, -371, -416, +155, -204, 578, 78, 662, 322, 463, 496, +132, 480, -257, 220, -530, -141, -547, -419, +-398, -561, -176, -479, 80, -158, 285, 219, +401, 477, 397, 585, 223, 483, -72, 130, +-360, -273, -546, -549, -546, -642, -301, -481, +67, -81, 353, 325, 494, 582, 467, 661, +195, 500, -225, 80, -513, -387, -532, -648, +-372, -676, -139, -466, 106, -14, 291, 457, +360, 698, 304, 683, 135, 414, -112, -49, +-331, -501, -405, -756, -347, -726, -226, -385, +-40, 180, 199, 658, 390, 812, 413, 678, +210, 313, -107, -274, -335, -799, -422, -937, +-388, -654, -236, -104, -20, 513, 191, 925, +336, 893, 360, 458, 246, -156, 1, -692, +-259, -911, -389, -691, -434, -185, -420, 402, +-211, 798, 166, 737, 489, 316, 590, -141, +413, -463, 40, -592, -363, -443, -662, -70, +-711, 282, -447, 392, 8, 312, 433, 138, +679, -60, 664, -169, 318, -159, -230, -70, +-632, 15, -726, 12, -585, -49, -247, -61, +191, -27, 541, 35, 683, 114, 533, 198, +109, 207, -353, 48, -626, -174, -676, -281, +-499, -259, -101, -145, 325, 45, 550, 244, +563, 344, 394, 233, 3, 10, -433, -162, +-613, -256, -523, -259, -294, -126, 15, 99, +271, 231, 376, 167, 393, 45, 295, -25, +28, -90, -250, -85, -397, -4, -435, 56, +-380, 88, -203, 27, 78, -159, 370, -245, +550, -112, 527, 84, 237, 224, -239, 300, +-622, 273, -736, 31, -572, -293, -166, -446, +327, -389, 686, -170, 776, 177, 518, 481, +-35, 560, -606, 358, -878, -43, -758, -407, +-366, -572, 161, -484, 635, -219, 795, 141, +618, 506, 215, 644, -338, 429, -772, 53, +-829, -302, -545, -546, -57, -570, 440, -352, +691, 29, 621, 387, 343, 575, -54, 534, +-488, 251, -736, -167, -589, -498, -190, -628, +173, -462, 419, -41, 500, 349, 361, 557, +94, 566, -173, 328, -370, -120, -411, -526, +-305, -636, -136, -412, 57, -13, 216, 372, +249, 522, 208, 387, 177, 122, 91, -190, +-112, -411, -321, -357, -405, -73, -345, 199, +-173, 304, 81, 214, 339, -15, 476, -271, +412, -329, 146, -101, -229, 182, -547, 341, +-661, 338, -477, 140, -44, -198, 387, -467, +609, -495, 581, -226, 325, 227, -81, 601, +-508, 625, -751, 311, -640, -107, -248, -524, +234, -764, 620, -597, 698, -125, 472, 397, +102, 796, -363, 825, -751, 457, -781, -82, +-437, -623, 94, -963, 584, -854, 786, -318, +593, 343, 126, 875, -368, 1103, -704, 861, +-769, 148, -451, -703, 115, -1277, 570, -1273, +709, -664, 497, 301, 21, 1206, -437, 1602, +-625, 1252, -531, 276, -236, -922, 164, -1758, +497, -1742, 541, -878, 264, 458, -136, 1662, +-444, 2049, -506, 1394, -288, 79, 29, -1283, +275, -2085, 402, -1870, 326, -676, 32, 906, +-297, 2028, -460, 2109, -371, 1102, -75, -448, +241, -1724, 392, -2127, 332, -1488, 102, -75, +-201, 1410, -402, 2133, -396, 1695, -204, 379, +91, -1073, 340, -1942, 402, -1786, 231, -672, +-74, 785, -313, 1780, -391, 1836, -310, 920, +-74, -505, 201, -1655, 354, -1942, 322, -1212, +113, 202, -167, 1539, -358, 2021, -385, 1456, +-211, 197, 96, -1186, 333, -2037, 367, -1849, +188, -681, -85, 837, -295, 1943, -389, 2092, +-306, 1208, -27, -309, 284, -1704, 441, -2256, +353, -1701, 42, -327, -312, 1238, -501, 2232, +-435, 2133, -180, 1024, 156, -592, 484, -1967, +592, -2365, 346, -1588, -83, -103, -500, 1409, +-743, 2247, -580, 1984, -80, 766, 418, -775, +702, -1894, 675, -2076, 316, -1261, -217, 126, +-675, 1398, -839, 1925, -577, 1476, -4, 346, +548, -825, 785, -1497, 627, -1439, 200, -735, +-266, 253, -599, 1051, -700, 1255, -489, 799, +-54, 47, 374, -547, 611, -797, 543, -665, +215, -269, -131, 160, -351, 436, -462, 463, +-427, 272, -202, 22, 98, -142, 325, -207, +417, -202, 301, -126, 32, -34, -151, 1, +-203, 93, -269, 221, -277, 205, -142, 75, +17, -57, 126, -176, 199, -242, 230, -196, +191, -25, 77, 231, -61, 349, -226, 222, +-397, -16, -406, -236, -187, -380, 146, -339, +444, -73, 534, 291, 376, 525, 67, 466, +-320, 149, -622, -248, -632, -524, -331, -606, +130, -406, 540, 53, 707, 502, 531, 702, +76, 588, -391, 199, -630, -277, -605, -634, +-347, -734, 66, -488, 441, -38, 602, 416, +494, 739, 172, 755, -239, 406, -533, -115, +-538, -573, -330, -810, -66, -735, 231, -351, +490, 200, 547, 702, 329, 971, -94, 800, +-499, 221, -636, -427, -458, -891, -104, -1036, +309, -736, 628, -102, 626, 624, 279, 1148, +-201, 1137, -637, 590, -813, -207, -488, -926, +161, -1262, 671, -1041, 780, -368, 493, 490, +-20, 1178, -518, 1362, -776, 921, -665, 53, +-191, -853, 445, -1401, 822, -1311, 688, -654, +228, 284, -311, 1161, -710, 1533, -689, 1186, +-323, 333, 74, -725, 444, -1508, 681, -1528, +527, -861, 63, 153, -365, 1161, -568, 1655, +-513, 1322, -209, 387, 175, -706, 387, -1473, +396, -1557, 273, -927, 21, 124, -233, 1126, +-320, 1585, -242, 1229, -79, 322, 91, -617, +164, -1216, 91, -1281, -20, -791, -1, 46, +91, 859, 96, 1188, 47, 913, -42, 311, +-199, -383, -260, -876, -160, -872, -38, -503, +127, -50, 361, 433, 407, 757, 142, 684, +-187, 289, -391, -171, -443, -503, -270, -545, +57, -333, 304, -118, 391, 106, 331, 370, +120, 408, -157, 192, -379, 12, -408, -113, +-191, -191, 86, -156, 242, -97, 266, -62, +199, -18, 79, 9, -72, 48, -202, 140, +-216, 192, -124, 153, -18, 33, 68, -126, +136, -255, 144, -283, 85, -185, 33, 45, +-22, 297, -131, 372, -186, 268, -145, 56, +-62, -244, 112, -424, 280, -280, 239, -20, +82, 173, -86, 287, -293, 228, -376, 29, +-207, -157, 77, -283, 357, -227, 522, 79, +363, 348, -90, 314, -488, 76, -621, -172, +-474, -366, -21, -387, 504, -164, 743, 177, +631, 439, 203, 480, -441, 270, -902, -90, +-853, -426, -351, -566, 342, -395, 883, -38, +966, 281, 563, 465, -88, 506, -712, 368, +-1031, 61, -830, -315, -203, -583, 516, -605, +976, -430, 933, -106, 448, 361, -184, 790, +-718, 882, -920, 588, -691, 1, -196, -716, +381, -1173, 811, -1065, 822, -457, 452, 442, +-57, 1251, -524, 1436, -739, 895, -603, -62, +-275, -1064, 111, -1628, 513, -1339, 706, -357, +518, 755, 154, 1515, -200, 1575, -520, 834, +-608, -317, -409, -1238, -118, -1527, 230, -1103, +544, -187, 575, 768, 372, 1274, 74, 1137, +-303, 502, -583, -307, -564, -884, -296, -944, +77, -561, 403, -29, 544, 440, 476, 649, +235, 515, -136, 183, -475, -126, -577, -314, +-410, -327, -70, -172, 279, -17, 443, 0, +431, -19, 324, 42, 68, 120, -249, 201, +-449, 258, -478, 192, -287, -6, 60, -238, +314, -428, 392, -451, 374, -193, 239, 218, +-22, 508, -291, 549, -464, 352, -438, -64, +-146, -483, 195, -620, 349, -428, 401, -57, +356, 357, 95, 618, -201, 529, -362, 151, +-421, -267, -315, -543, -41, -540, 247, -209, +441, 185, 447, 423, 234, 490, -47, 307, +-277, -99, -459, -402, -497, -445, -239, -297, +186, 7, 486, 335, 579, 497, 431, 395, +23, 71, -408, -305, -624, -512, -562, -483, +-224, -239, 223, 153, 572, 517, 702, 641, +474, 450, -55, 18, -548, -452, -745, -692, +-578, -634, -111, -275, 395, 297, 677, 733, +675, 761, 377, 479, -160, -27, -627, -620, +-740, -909, -503, -713, -26, -196, 478, 425, +689, 882, 567, 871, 258, 432, -166, -164, +-516, -701, -598, -920, -465, -619, -179, -26, +254, 496, 605, 786, 627, 673, 412, 174, +98, -366, -311, -641, -664, -567, -743, -185, +-506, 276, 19, 535, 626, 454, 955, 103, +843, -311, 344, -531, -349, -384, -925, 42, +-1108, 461, -767, 601, -15, 387, 765, -129, +1205, -691, 1104, -881, 477, -503, -379, 188, +-1071, 839, -1281, 1165, -884, 879, -80, 29, +738, -925, 1215, -1469, 1174, -1287, 647, -401, +-204, 739, -999, 1582, -1301, 1679, -1023, 912, +-331, -345, 532, -1455, 1171, -1866, 1272, -1367, +836, -213, 60, 1046, -769, 1845, -1309, 1741, +-1250, 763, -585, -524, 317, -1496, 1049, -1795, +1340, -1269, 1033, -147, 257, 956, -598, 1571, +-1174, 1517, -1234, 797, -734, -255, 80, -1103, +804, -1446, 1146, -1178, 993, -420, 424, 445, +-255, 1061, -753, 1249, -957, 923, -809, 205, +-324, -547, 278, -1031, 737, -1092, 915, -686, +773, 10, 326, 616, -274, 925, -764, 882, +-972, 478, -831, -109, -300, -602, 451, -815, +1019, -679, 1096, -299, 695, 113, 57, 442, +-617, 602, -1103, 554, -1077, 341, -506, 41, +249, -274, 842, -505, 1078, -591, 881, -524, +309, -249, -401, 190, -897, 591, -1005, 788, +-741, 723, -157, 330, 548, -291, 1032, -850, +1059, -1062, 604, -803, -100, -166, -747, 579, +-1135, 1125, -1030, 1207, -364, 708, 520, -163, +1126, -980, 1165, -1352, 664, -1126, -130, -384, +-877, 585, -1193, 1306, -874, 1401, -119, 842, +653, -94, 1063, -982, 912, -1409, 317, -1212, +-384, -460, -845, 539, -862, 1275, -438, 1344, +205, 799, 689, -31, 753, -813, 443, -1235, +-42, -1084, -483, -445, -652, 360, -444, 967, +-16, 1090, 364, 722, 538, 87, 442, -539, +105, -903, -266, -858, -445, -459, -362, 105, +-100, 613, 154, 848, 294, 697, 314, 234, +180, -289, -63, -659, -225, -750, -200, -525, +-81, -88, 13, 395, 73, 738, 81, 730, +18, 361, -8, -129, 32, -534, 48, -722, +68, -602, 95, -197, 30, 308, -117, 670, +-255, 703, -258, 401, -73, -74, 170, -505, +370, -711, 448, -584, 277, -168, -73, 335, +-397, 683, -591, 674, -549, 330, -174, -130, +399, -523, 800, -711, 768, -547, 351, -91, +-221, 390, -703, 663, -891, 616, -665, 276, +-48, -197, 659, -539, 976, -602, 776, -400, +270, -21, -359, 378, -847, 569, -861, 473, +-417, 154, 154, -241, 587, -475, 740, -436, +538, -219, 76, 55, -378, 320, -569, 416, +-424, 269, -113, 20, 157, -181, 318, -287, +305, -227, 83, -40, -143, 101, -155, 145, +-32, 111, 79, -4, 140, -106, 131, -76, +-10, 13, -231, 92, -360, 155, -265, 120, +41, -43, 376, -194, 531, -248, 452, -210, +156, -39, -282, 188, -622, 339, -700, 374, +-475, 228, 42, -85, 628, -343, 926, -472, +773, -486, 243, -253, -412, 181, -893, 575, +-990, 778, -630, 654, 55, 150, 765, -465, +1133, -930, 924, -1090, 277, -712, -466, 141, +-1005, 969, -1062, 1407, -593, 1268, 94, 438, +699, -719, 1011, -1560, 843, -1710, 257, -1048, +-399, 206, -794, 1385, -802, 1940, -475, 1660, +20, 539, 461, -936, 675, -1931, 575, -2003, +212, -1213, -176, 150, -405, 1480, -462, 2112, +-340, 1788, -65, 679, 204, -746, 334, -1799, +290, -2032, 131, -1424, -15, -199, -112, 1135, +-172, 1943, -139, 1885, -21, 1044, 48, -229, +46, -1392, 34, -1965, -9, -1716, -53, -727, +0, 585, 86, 1612, 121, 1944, 122, 1479, +52, 391, -72, -854, -172, -1713, -249, -1844, +-247, -1214, -61, -100, 208, 1020, 374, 1731, +388, 1741, 250, 998, -49, -143, -369, -1163, +-515, -1711, -465, -1617, -208, -860, 237, 294, +609, 1347, 658, 1839, 394, 1591, -63, 676, +-467, -563, -623, -1600, -552, -1997, -254, -1572, +230, -434, 602, 958, 626, 1964, 387, 2140, +42, 1384, -301, -37, -506, -1479, -468, -2261, +-261, -2078, -5, -982, 248, 633, 418, 1989, +418, 2415, 251, 1758, 9, 302, -205, -1319, +-338, -2314, -386, -2247, -285, -1174, -46, 444, +200, 1855, 354, 2388, 383, 1832, 275, 451, +56, -1141, -184, -2177, -330, -2177, -326, -1213, +-233, 262, -103, 1611, 75, 2190, 269, 1761, +364, 569, 321, -855, 188, -1851, -13, -1961, +-250, -1210, -435, 46, -476, 1258, -325, 1842, +1, 1565, 390, 635, 684, -535, 677, -1438, +309, -1642, -225, -1114, -674, -151, -853, 853, +-657, 1436, -132, 1339, 506, 702, 953, -176, +947, -971, 461, -1307, -271, -1065, -858, -434, +-1022, 342, -706, 992, -70, 1216, 577, 928, +948, 271, 880, -484, 373, -1033, -300, -1176, +-761, -864, -859, -182, -550, 650, 41, 1235, +527, 1264, 680, 742, 562, -98, 205, -936, +-246, -1403, -493, -1262, -476, -553, -285, 444, +29, 1287, 303, 1563, 345, 1106, 232, 137, +85, -881, -86, -1510, -183, -1484, -157, -787, +-134, 282, -88, 1239, 53, 1645, 139, 1299, +116, 353, 79, -740, 37, -1471, -25, -1554, +-78, -978, -123, 31, -104, 1053, 8, 1602, +105, 1412, 121, 588, 94, -461, 28, -1277, +-73, -1553, -141, -1146, -141, -216, -69, 788, +54, 1421, 146, 1423, 179, 784, 166, -175, +38, -1019, -153, -1425, -249, -1196, -234, -433, +-122, 473, 86, 1148, 273, 1343, 323, 920, +252, 101, 54, -688, -232, -1171, -414, -1191, +-366, -674, -173, 134, 104, 833, 398, 1164, +483, 992, 301, 397, 26, -321, -244, -882, +-443, -1087, -446, -806, -255, -170, 53, 496, +350, 927, 463, 957, 362, 568, 160, -29, +-78, -570, -318, -889, -450, -842, -394, -417, +-177, 169, 106, 658, 356, 868, 469, 690, +402, 252, 175, -226, -135, -634, -394, -821, +-516, -628, -447, -163, -166, 327, 210, 680, +485, 735, 560, 461, 402, 47, 95, -351, +-220, -654, -488, -674, -604, -346, -431, 95, +-59, 446, 299, 615, 550, 510, 591, 179, +379, -176, 45, -436, -305, -527, -616, -385, +-668, -78, -376, 216, 28, 402, 384, 424, +652, 260, 683, 30, 403, -161, -59, -307, +-519, -342, -769, -224, -699, -67, -349, 75, +165, 211, 655, 281, 877, 252, 708, 157, +219, 6, -395, -156, -839, -266, -892, -332, +-550, -290, 27, -78, 601, 187, 882, 381, +756, 468, 324, 349, -256, 26, -714, -304, +-773, -537, -481, -598, -70, -346, 330, 115, +576, 499, 568, 694, 344, 613, -2, 204, +-319, -305, -444, -635, -384, -727, -234, -537, +-42, -60, 150, 442, 287, 721, 339, 723, +277, 414, 98, -99, -80, -512, -205, -710, +-309, -677, -342, -341, -230, 180, -25, 594, +199, 777, 386, 671, 445, 232, 333, -320, +51, -706, -304, -823, -547, -608, -561, -84, +-356, 489, 35, 854, 470, 857, 723, 433, +652, -206, 260, -702, -285, -887, -704, -696, +-796, -152, -544, 450, -26, 812, 533, 814, +830, 415, 738, -201, 334, -651, -243, -770, +-717, -570, -826, -82, -554, 436, -55, 662, +447, 593, 724, 313, 680, -151, 363, -518, +-130, -565, -571, -389, -720, -74, -539, 294, +-149, 458, 303, 372, 620, 193, 648, -63, +397, -302, -41, -354, -468, -255, -645, -76, +-523, 174, -192, 321, 267, 253, 590, 106, +543, -49, 263, -209, -65, -253, -388, -158, +-526, -12, -362, 162, -64, 262, 224, 179, +402, 0, 345, -161, 131, -241, -39, -149, +-176, 38, -280, 165, -233, 214, -108, 161, +-10, -31, 102, -226, 202, -274, 235, -178, +243, 53, 139, 308, -120, 359, -348, 166, +-419, -97, -343, -322, -94, -411, 264, -243, +556, 75, 642, 346, 389, 475, -137, 372, +-607, 13, -801, -381, -683, -564, -206, -464, +443, -132, 904, 285, 991, 564, 621, 572, +-143, 332, -876, -74, -1174, -488, -982, -674, +-321, -523, 578, -142, 1216, 307, 1295, 641, +825, 683, -89, 393, -1054, -68, -1509, -498, +-1247, -739, -416, -662, 642, -266, 1400, 275, +1496, 718, 974, 852, 3, 585, -1067, 54, +-1647, -504, -1408, -871, -549, -861, 515, -465, +1347, 135, 1580, 709, 1122, 995, 175, 818, +-832, 281, -1458, -377, -1449, -887, -820, -995, +169, -662, 1048, -83, 1433, 539, 1224, 961, +539, 931, -358, 485, -1091, -126, -1351, -697, +-1058, -964, -340, -746, 489, -260, 1096, 251, +1276, 696, 951, 842, 216, 574, -582, 131, +-1115, -310, -1238, -653, -863, -673, -94, -395, +702, -70, 1189, 231, 1227, 465, 743, 494, +-98, 372, -872, 181, -1240, -110, -1115, -360, +-531, -423, 298, -409, 974, -319, 1218, -50, +952, 260, 284, 501, -491, 628, -1006, 483, +-1071, 77, -712, -350, -104, -680, 526, -799, +938, -554, 955, -33, 579, 538, -10, 948, +-559, 953, -858, 487, -813, -190, -492, -807, +2, -1134, 515, -938, 831, -287, 804, 448, +490, 1016, -9, 1216, -552, 843, -859, 58, +-800, -728, -476, -1209, 22, -1181, 589, -627, +937, 177, 884, 900, 475, 1281, -140, 1132, +-728, 477, -1029, -384, -919, -1087, -412, -1366, +314, -1040, 915, -241, 1126, 611, 876, 1204, +232, 1357, -560, 916, -1092, 47, -1122, -821, +-678, -1345, 55, -1305, 769, -671, 1124, 234, +973, 975, 424, 1308, -287, 1112, -854, 424, +-1034, -413, -739, -1016, -154, -1219, 413, -906, +778, -181, 855, 539, 579, 984, 68, 1043, +-413, 636, -705, -4, -723, -548, -456, -898, +-34, -900, 364, -449, 624, 172, 650, 626, +432, 823, 77, 670, -321, 197, -628, -282, +-660, -595, -417, -699, -73, -464, 300, -10, +631, 349, 743, 545, 524, 505, 67, 189, +-422, -122, -747, -275, -801, -352, -538, -279, +11, -73, 618, 71, 967, 142, 892, 170, +426, 108, -269, 53, -866, 71, -1082, 34, +-835, -38, -194, -73, 583, -170, 1102, -245, +1117, -127, 645, 47, -143, 184, -882, 327, +-1213, 303, -1010, 87, -369, -121, 477, -322, +1133, -458, 1266, -308, 820, 28, 8, 307, +-814, 487, -1273, 473, -1170, 183, -561, -189, +337, -448, 1126, -570, 1392, -439, 1002, -46, +178, 359, -723, 611, -1305, 622, -1303, 293, +-741, -187, 159, -518, 1020, -647, 1420, -526, +1165, -135, 417, 350, -513, 684, -1219, 692, +-1361, 350, -906, -144, -96, -551, 769, -713, +1321, -563, 1254, -147, 636, 348, -220, 689, +-967, 725, -1286, 403, -1034, -130, -368, -571, +441, -735, 1055, -584, 1194, -156, 841, 339, +175, 670, -567, 729, -1061, 440, -1070, -102, +-688, -579, -80, -748, 612, -598, 1106, -207, +1117, 302, 656, 700, -62, 764, -760, 491, +-1171, -2, -1153, -521, -652, -786, 219, -691, +1058, -333, 1407, 194, 1155, 688, 439, 849, +-507, 616, -1308, 140, -1542, -419, -1076, -845, +-125, -880, 904, -504, 1551, 78, 1516, 676, +828, 1031, -214, 886, -1182, 328, -1635, -368, +-1381, -965, -533, -1156, 555, -813, 1385, -116, +1591, 685, 1155, 1253, 280, 1231, -733, 619, +-1436, -251, -1505, -1021, -967, -1379, -69, -1133, +874, -361, 1458, 597, 1437, 1324, 860, 1446, +-63, 889, -999, -41, -1526, -955, -1418, -1484, +-723, -1336, 312, -593, 1224, 391, 1616, 1245, +1364, 1557, 524, 1159, -619, 267, -1490, -757, +-1667, -1464, -1144, -1499, -132, -892, 984, 63, +1667, 1028, 1583, 1585, 799, 1412, -324, 607, +-1268, -423, -1646, -1283, -1325, -1608, -411, -1204, +706, -286, 1453, 743, 1521, 1483, 968, 1567, +16, 956, -935, -34, -1441, -1014, -1303, -1568, +-630, -1443, 297, -722, 1062, 290, 1349, 1189, +1085, 1590, 368, 1314, -512, 505, -1116, -478, +-1202, -1268, -827, -1562, -135, -1206, 613, -350, +1085, 662, 1091, 1421, 661, 1574, -39, 1058, +-699, 108, -1033, -897, -951, -1551, -505, -1565, +158, -871, 763, 258, 1010, 1271, 845, 1719, +377, 1404, -239, 440, -785, -716, -993, -1538, +-774, -1687, -249, -1056, 361, 69, 829, 1130, +991, 1648, 746, 1396, 153, 504, -512, -561, +-935, -1287, -986, -1409, -639, -927, 21, -39, +714, 820, 1089, 1204, 985, 1026, 468, 446, +-274, -279, -928, -795, -1183, -922, -902, -678, +-207, -175, 597, 352, 1140, 675, 1187, 725, +699, 504, -114, 107, -863, -300, -1227, -581, +-1081, -658, -448, -514, 441, -169, 1137, 273, +1292, 631, 874, 758, 98, 581, -718, 159, +-1226, -352, -1199, -790, -620, -919, 247, -612, +973, -42, 1260, 571, 1028, 995, 357, 961, +-484, 480, -1077, -194, -1182, -828, -819, -1132, +-130, -885, 636, -215, 1122, 516, 1127, 1022, +715, 1093, 29, 635, -712, -112, -1179, -767, +-1151, -1097, -659, -935, 128, -309, 892, 420, +1309, 922, 1209, 1025, 599, 667, -320, 23, +-1135, -603, -1458, -969, -1166, -914, -369, -438, +617, 230, 1360, 759, 1524, 934, 1053, 734, +124, 228, -881, -396, -1506, -839, -1482, -893, +-845, -543, 139, 20, 1084, 553, 1617, 853, +1488, 749, 687, 298, -417, -235, -1320, -661, +-1687, -794, -1381, -523, -444, -45, 746, 386, +1633, 652, 1801, 619, 1176, 283, 44, -136, +-1121, -442, -1828, -546, -1720, -400, -812, -75, +447, 211, 1507, 352, 1921, 369, 1454, 232, +319, 14, -922, -136, -1727, -221, -1762, -232, +-995, -138, 187, -46, 1260, 6, 1788, 76, +1505, 158, 513, 210, -654, 194, -1455, 100, +-1600, -50, -1050, -226, -57, -339, 923, -298, +1469, -121, 1355, 125, 635, 360, -306, 477, +-1039, 358, -1289, 22, -976, -327, -270, -519, +488, -494, 1011, -235, 1078, 133, 653, 442, +6, 589, -563, 452, -863, 80, -771, -296, +-359, -519, 117, -522, 507, -285, 695, 67, +549, 364, 167, 497, -195, 422, -406, 158, +-434, -171, -292, -388, -98, -430, 99, -309, +279, -51, 318, 223, 194, 386, 86, 388, +-1, 208, -119, -61, -178, -280, -185, -372, +-189, -302, -83, -114, 107, 123, 186, 326, +211, 362, 247, 194, 155, -42, -60, -227, +-226, -286, -309, -201, -287, -36, -113, 141, +107, 240, 277, 193, 384, 17, 336, -172, +103, -238, -156, -148, -366, 34, -468, 223, +-324, 283, 10, 166, 302, -46, 467, -263, +490, -369, 297, -274, -60, -6, -415, 302, +-579, 457, -456, 363, -135, 83, 203, -270, +491, -509, 610, -481, 429, -206, 61, 197, +-309, 535, -566, 601, -562, 365, -275, -45, +87, -476, 392, -709, 564, -586, 493, -171, +199, 316, -154, 675, -444, 749, -516, 467, +-317, -19, -43, -487, 192, -778, 410, -720, +462, -319, 246, 187, -13, 628, -196, 818, +-352, 603, -368, 144, -173, -324, 66, -684, +248, -765, 365, -480, 330, 7, 144, 484, +-101, 761, -309, 676, -381, 282, -242, -181, +3, -572, 217, -752, 354, -561, 360, -111, +171, 360, -118, 704, -317, 719, -351, 372, +-232, -83, -10, -484, 214, -703, 319, -575, +295, -186, 157, 250, -59, 584, -244, 629, +-292, 345, -218, -41, -71, -346, 123, -501, +260, -408, 263, -108, 163, 167, 27, 324, +-123, 341, -224, 161, -215, -59, -118, -146, +4, -174, 112, -136, 176, -5, 172, 50, +123, 22, 45, 24, -41, 24, -112, 24, +-151, 77, -169, 89, -138, 8, -12, -76, +162, -131, 256, -168, 254, -103, 187, 66, +-3, 188, -236, 209, -346, 127, -314, -54, +-174, -203, 100, -212, 362, -115, 422, 53, +310, 200, 110, 221, -173, 105, -427, -104, +-473, -278, -311, -289, -20, -130, 309, 125, +523, 354, 509, 397, 300, 215, -55, -103, +-436, -397, -619, -522, -513, -412, -200, -75, +228, 345, 603, 625, 686, 619, 446, 319, +25, -159, -408, -595, -683, -785, -636, -617, +-275, -157, 212, 390, 588, 796, 687, 862, +502, 542, 110, -50, -342, -671, -649, -997, +-630, -860, -313, -367, 124, 309, 472, 894, +613, 1074, 525, 778, 227, 147, -190, -584, +-524, -1068, -604, -1054, -443, -582, -99, 126, +308, 799, 587, 1114, 618, 909, 433, 346, +58, -335, -383, -905, -651, -1067, -647, -740, +-382, -125, 102, 539, 585, 954, 782, 924, +667, 551, 287, -24, -268, -624, -722, -938, +-820, -823, -568, -385, -59, 200, 521, 699, +851, 884, 777, 704, 407, 261, -110, -288, +-607, -705, -821, -794, -659, -575, -213, -135, +310, 364, 670, 659, 738, 670, 544, 471, +140, 90, -351, -317, -679, -544, -700, -573, +-430, -395, 18, -50, 450, 278, 685, 478, +666, 543, 367, 408, -128, 84, -557, -262, +-722, -495, -588, -566, -193, -400, 314, -28, +658, 347, 710, 606, 488, 643, 43, 372, +-449, -70, -733, -466, -689, -699, -333, -640, +178, -268, 583, 228, 726, 610, 601, 727, +220, 540, -315, 122, -702, -345, -748, -644, +-485, -651, -22, -383, 468, 35, 753, 414, +711, 591, 360, 495, -172, 184, -622, -170, +-778, -410, -603, -455, -172, -308, 369, -51, +742, 207, 753, 353, 422, 304, -93, 124, +-574, -69, -783, -201, -605, -225, -151, -155, +361, -36, 693, 67, 686, 104, 355, 82, +-126, 23, -541, -47, -679, -50, -482, 12, +-64, 50, 378, 47, 618, 15, 526, -60, +197, -143, -162, -161, -437, -116, -526, -19, +-352, 139, 2, 254, 320, 210, 465, 82, +400, -62, 170, -229, -109, -311, -324, -243, +-390, -97, -281, 99, -41, 272, 189, 290, +327, 189, 331, 53, 195, -125, -4, -285, +-156, -298, -234, -178, -240, -25, -135, 138, +29, 249, 151, 239, 209, 151, 215, 17, +150, -151, 58, -249, -50, -228, -173, -130, +-236, 15, -172, 151, -28, 213, 122, 210, +246, 137, 286, -6, 211, -147, 41, -223, +-165, -208, -302, -105, -258, 33, -93, 143, +92, 216, 254, 225, 318, 121, 235, -31, +60, -134, -119, -190, -247, -180, -251, -76, +-143, 37, 18, 117, 171, 175, 254, 164, +239, 91, 159, 23, 18, -42, -158, -101, +-258, -111, -226, -93, -97, -76, 72, -22, +238, 80, 304, 160, 234, 188, 63, 177, +-143, 93, -278, -54, -261, -180, -116, -245, +72, -222, 227, -84, 265, 115, 177, 281, +15, 334, -141, 265, -216, 103, -149, -110, +-9, -297, 92, -369, 126, -305, 102, -113, +27, 151, -57, 364, -85, 455, -60, 400, +-2, 181, 66, -157, 90, -455, 26, -574, +-56, -472, -96, -151, -92, 291, -54, 634, +10, 717, 68, 503, 93, 28, 102, -504, +55, -811, -34, -769, -105, -391, -125, 196, +-124, 720, -94, 919, -5, 706, 127, 160, +223, -487, 210, -921, 93, -932, -83, -546, +-230, 64, -303, 661, -254, 973, -72, 848, +185, 341, 362, -328, 347, -839, 161, -977, +-93, -717, -308, -155, -392, 483, -296, 901, +-75, 916, 186, 523, 359, -119, 357, -715, +184, -1000, -44, -846, -236, -311, -320, 369, +-264, 879, -118, 993, 70, 651, 233, -19, +292, -710, 215, -1071, 66, -938, -94, -391, +-193, 344, -201, 924, -141, 1062, -39, 700, +95, -5, 188, -719, 182, -1083, 127, -935, +56, -375, -18, 350, -76, 902, -111, 1005, +-127, 615, -98, -51, -27, -679, 80, -980, +204, -795, 273, -230, 220, 408, 66, 826, +-133, 845, -306, 452, -321, -153, -160, -671, +88, -853, 332, -613, 463, -73, 366, 480, +90, 768, -216, 694, -424, 310, -412, -238, +-173, -669, 136, -746, 362, -455, 453, 60, +344, 549, 86, 759, -179, 619, -339, 203, +-341, -324, -177, -702, 64, -727, 247, -400, +328, 113, 296, 593, 152, 817, -45, 660, +-190, 214, -251, -326, -204, -727, -67, -782, +93, -467, 205, 60, 241, 574, 188, 833, +55, 728, -76, 328, -160, -223, -174, -676, +-100, -791, 21, -552, 101, -82, 128, 441, +107, 759, 38, 726, -29, 418, -41, -48, +-17, -512, 1, -722, 15, -576, -12, -207, +-62, 235, -86, 582, -60, 657, 22, 470, +136, 121, 194, -296, 139, -564, -7, -543, +-195, -321, -321, 15, -271, 362, -62, 529, +177, 463, 363, 245, 377, -69, 167, -359, +-159, -475, -435, -396, -515, -172, -324, 123, +56, 346, 402, 409, 550, 340, 418, 142, +46, -140, -361, -352, -582, -428, -546, -355, +-237, -126, 208, 141, 521, 335, 551, 430, +328, 347, -46, 78, -420, -219, -570, -431, +-445, -501, -142, -352, 203, -43, 437, 258, +447, 455, 265, 477, -27, 251, -298, -111, +-403, -407, -316, -545, -122, -461, 91, -153, +258, 202, 286, 432, 184, 474, 32, 276, +-107, -86, -173, -395, -139, -498, -60, -386, +13, -114, 55, 204, 41, 401, 13, 377, +25, 156, 66, -158, 86, -396, 111, -407, +102, -219, -8, 43, -162, 271, -235, 348, +-180, 220, -28, -31, 176, -274, 339, -386, +368, -278, 226, -7, -40, 249, -304, 362, +-401, 298, -309, 60, -67, -232, 246, -410, +481, -408, 500, -207, 280, 141, -53, 427, +-356, 499, -488, 371, -385, 63, -84, -305, +285, -521, 541, -510, 547, -294, 326, 85, +-40, 445, -410, 598, -573, 526, -430, 246, +-68, -180, 330, -512, 605, -585, 606, -443, +328, -101, -95, 334, -483, 605, -637, 624, +-445, 425, -30, 11, 380, -418, 629, -609, +607, -545, 305, -255, -127, 197, -471, 571, +-611, 684, -465, 548, -91, 187, 317, -281, +574, -599, 569, -636, 322, -411, -44, 27, +-376, 478, -560, 701, -499, 655, -188, 357, +220, -118, 496, -523, 540, -673, 340, -539, +-10, -149, -344, 325, -515, 632, -438, 673, +-164, 454, 170, 43, 396, -374, 416, -603, +229, -577, -56, -298, -286, 121, -357, 469, +-273, 612, -81, 528, 119, 227, 218, -173, +190, -477, 72, -597, -50, -488, -127, -164, +-138, 223, -100, 516, -43, 632, 2, 487, +9, 106, -13, -313, -24, -598, -3, -662, +41, -461, 62, -49, 29, 382, -25, 639, +-92, 624, -143, 325, -164, -137, -112, -525, +19, -678, 161, -566, 232, -236, 183, 187, +41, 520, -144, 608, -293, 419, -322, 35, +-206, -365, 7, -602, 249, -602, 387, -381, +341, -2, 112, 371, -187, 568, -395, 524, +-422, 242, -265, -177, 9, -533, 315, -675, +490, -562, 415, -215, 143, 226, -177, 555, +-408, 635, -447, 431, -276, 11, 38, -436, +337, -708, 458, -688, 381, -364, 159, 117, +-116, 530, -338, 713, -382, 577, -229, 140, +17, -377, 241, -732, 358, -790, 329, -483, +188, 71, -8, 573, -181, 816, -254, 711, +-223, 238, -97, -376, 75, -796, 244, -867, +327, -554, 284, 49, 139, 629, -46, 896, +-200, 770, -280, 282, -232, -354, -36, -783, +202, -827, 347, -520, 351, 34, 209, 572, +0, 815, -186, 703, -275, 309, -236, -218, +-77, -599, 129, -663, 263, -445, 296, -56, +213, 344, 54, 583, -80, 586, -152, 373, +-184, 22, -150, -300, -45, -447, 92, -401, +200, -207, 245, 68, 205, 318, 82, 454, +-68, 431, -217, 238, -280, -18, -217, -214, +-50, -315, 159, -293, 314, -129, 321, 82, +179, 246, -46, 337, -256, 314, -353, 181, +-288, 20, -95, -110, 122, -211, 292, -237, +323, -157, 200, -24, -19, 125, -234, 276, +-341, 348, -303, 288, -135, 132, 85, -91, +244, -319, 278, -422, 200, -333, 21, -97, +-190, 221, -330, 494, -310, 564, -163, 382, +40, 32, 217, -368, 276, -639, 206, -615, +32, -317, -168, 120, -315, 530, -336, 711, +-204, 555, 22, 166, 208, -293, 281, -648, +222, -720, 60, -468, -137, -33, -285, 394, +-318, 634, -234, 574, -30, 260, 166, -154, +256, -504, 232, -644, 110, -512, -58, -189, +-177, 187, -227, 453, -217, 488, -115, 312, +39, 13, 140, -303, 177, -498, 189, -487, +114, -304, -6, -23, -109, 243, -188, 372, +-225, 334, -178, 160, -32, -102, 152, -329, +294, -407, 315, -342, 206, -176, 12, 51, +-208, 243, -374, 300, -359, 221, -162, 38, +142, -171, 411, -297, 511, -315, 396, -233, +86, -68, -275, 113, -513, 230, -512, 251, +-269, 160, 132, 1, 526, -151, 701, -258, +545, -297, 156, -233, -294, -72, -605, 125, +-626, 292, -348, 353, 119, 263, 539, 52, +730, -214, 606, -435, 229, -472, -228, -280, +-552, 59, -594, 419, -356, 622, 26, 531, +382, 187, 565, -260, 512, -623, 267, -691, +-60, -396, -300, 113, -386, 590, -304, 812, +-99, 654, 119, 192, 257, -345, 294, -714, +248, -739, 135, -374, 5, 195, -104, 664, +-184, 820, -202, 606, -134, 135, -38, -367, +76, -668, 190, -628, 250, -270, 218, 223, +99, 611, -69, 715, -228, 496, -289, 78, +-239, -334, -89, -540, 115, -466, 269, -176, +303, 198, 239, 501, 55, 563, -201, 359, +-373, 28, -366, -270, -212, -405, -1, -324, +228, -89, 371, 174, 354, 366, 155, 400, +-154, 254, -407, 21, -484, -185, -371, -288, +-103, -248, 218, -106, 444, 50, 461, 194, +264, 275, -62, 244, -406, 134, -578, -14, +-496, -172, -207, -261, 159, -257, 442, -187, +532, -26, 378, 182, 40, 302, -325, 300, +-554, 202, -552, -8, -321, -249, 40, -389, +376, -397, 517, -256, 436, 21, 156, 273, +-215, 384, -473, 360, -511, 171, -350, -134, +-67, -383, 252, -487, 445, -419, 409, -164, +200, 151, -73, 363, -311, 415, -397, 286, +-322, -5, -130, -317, 114, -503, 308, -499, +363, -285, 253, 49, 52, 329, -168, 450, +-307, 366, -305, 86, -186, -254, 17, -496, +239, -547, 370, -364, 333, -29, 141, 283, +-107, 450, -287, 404, -337, 150, -225, -168, +-9, -406, 250, -489, 426, -376, 408, -105, +200, 172, -99, 331, -336, 344, -408, 207, +-279, -21, 12, -215, 321, -310, 491, -303, +450, -195, 211, -29, -115, 133, -393, 242, +-452, 264, -265, 192, 35, 58, 321, -99, +474, -242, 436, -319, 210, -273, -87, -106, +-313, 112, -377, 317, -275, 427, -59, 360, +185, 138, 385, -139, 433, -374, 303, -471, +61, -359, -208, -81, -372, 252, -379, 514, +-210, 583, 76, 412, 359, 90, 481, -258, +373, -516, 100, -555, -213, -340, -420, 38, +-398, 444, -186, 698, 82, 668, 314, 379, +394, -68, 288, -506, 50, -727, -179, -626, +-286, -229, -251, 331, -140, 793, -32, 915, +79, 666, 175, 145, 197, -470, 152, -877, +71, -861, -49, -452, -172, 193, -283, 794, +-311, 1028, -202, 813, 24, 277, 261, -392, +393, -875, 356, -893, 120, -497, -203, 114, +-463, 691, -562, 930, -423, 712, -72, 213, +319, -349, 569, -744, 548, -742, 267, -362, +-148, 147, -516, 561, -679, 695, -579, 468, +-214, 58, 243, -321, 571, -539, 632, -485, +411, -187, 12, 141, -400, 349, -649, 372, +-627, 199, -369, -38, 29, -192, 409, -238, +596, -184, 533, -59, 247, 39, -130, 60, +-467, 29, -636, -30, -559, -68, -255, -32, +167, 23, 510, 44, 646, 34, 529, -29, +171, -124, -289, -175, -631, -161, -720, -102, +-492, 5, -34, 109, 451, 141, 733, 93, +705, -12, 373, -135, -148, -215, -590, -221, +-760, -166, -593, -54, -150, 83, 362, 166, +692, 153, 723, 68, 447, -59, -9, -182, +-436, -244, -641, -225, -558, -137, -224, 5, +220, 137, 522, 179, 593, 128, 447, 28, +130, -95, -220, -200, -427, -228, -423, -173, +-238, -57, 41, 99, 292, 205, 400, 189, +341, 92, 167, -45, -43, -203, -179, -281, +-224, -218, -157, -42, -19, 183, 95, 346, +151, 332, 150, 143, 104, -127, 45, -378, +24, -466, 41, -301, 37, 32, 0, 379, +-42, 588, -99, 515, -116, 181, -61, -237, +66, -559, 205, -619, 272, -348, 235, 106, +70, 520, -156, 725, -335, 592, -365, 171, +-196, -301, 97, -613, 354, -628, 463, -313, +364, 167, 79, 564, -282, 713, -515, 543, +-488, 121, -235, -321, 157, -578, 482, -563, +560, -257, 356, 192, -23, 538, -403, 646, +-597, 491, -501, 121, -161, -270, 254, -490, +537, -477, 534, -240, 255, 109, -139, 393, +-484, 501, -587, 412, -413, 164, -68, -116, +295, -295, 507, -329, 450, -229, 161, -35, +-194, 155, -468, 271, -539, 303, -349, 228, +-10, 76, 282, -69, 428, -180, 366, -242, +130, -217, -175, -104, -402, 52, -440, 207, +-283, 306, -26, 292, 185, 156, 296, -54, +280, -267, 123, -393, -77, -356, -207, -155, +-261, 116, -233, 346, -130, 437, 11, 334, +122, 64, 175, -261, 188, -489, 135, -508, +30, -301, -123, 27, -260, 331, -289, 486, +-198, 419, -26, 148, 177, -202, 329, -477, +340, -557, 181, -391, -72, -73, -303, 230, +-409, 407, -323, 410, -94, 224, 214, -77, +443, -356, 455, -488, 271, -415, -11, -190, +-293, 67, -464, 264, -419, 338, -176, 255, +152, 57, 440, -168, 559, -338, 425, -366, +123, -237, -231, -45, -491, 127, -532, 235, +-341, 215, 14, 86, 399, -72, 657, -209, +620, -262, 296, -181, -137, -37, -492, 88, +-630, 159, -487, 137, -127, 23, 328, -97, +664, -160, 697, -158, 422, -74, -16, 56, +-421, 146, -643, 161, -555, 96, -213, -41, +205, -164, 532, -197, 641, -144, 480, -17, +115, 145, -288, 242, -520, 226, -495, 117, +-277, -47, 34, -206, 324, -281, 495, -213, +447, -26, 232, 195, -50, 335, -303, 332, +-418, 192, -365, -27, -181, -242, 73, -360, +312, -306, 427, -78, 371, 231, 172, 458, +-102, 489, -358, 309, -455, -8, -370, -322, +-134, -497, 167, -455, 378, -176, 426, 245, +305, 592, 63, 683, -216, 476, -407, 62, +-440, -378, -315, -644, -61, -617, 223, -301, +379, 184, 373, 623, 241, 792, 4, 614, +-268, 181, -462, -320, -451, -664, -247, -693, +54, -408, 302, 58, 397, 507, 323, 743, +104, 658, -165, 298, -356, -167, -404, -545, +-285, -678, -53, -497, 158, -99, 266, 320, +232, 598, 122, 631, -15, 397, -141, 2, +-223, -383, -236, -596, -161, -546, -41, -250, +83, 137, 165, 432, 175, 540, 115, 428, +3, 128, -139, -219, -229, -458, -218, -510, +-101, -347, 50, -42, 165, 252, 200, 413, +121, 390, -11, 211, -129, -51, -183, -293, +-155, -421, -57, -389, 66, -205, 146, 57, +147, 265, 93, 334, -9, 263, -101, 79, +-126, -157, -87, -335, -6, -370, 66, -268, +117, -79, 122, 135, 86, 264, 6, 241, +-94, 115, -134, -58, -86, -218, 8, -280, +112, -228, 170, -113, 149, 32, 78, 142, +-36, 149, -148, 81, -192, -9, -110, -95, +54, -141, 207, -121, 269, -74, 196, -38, +39, 2, -131, 34, -246, 34, -234, 23, +-86, 15, 125, -4, 304, -28, 331, -57, +187, -86, -48, -92, -233, -52, -289, 26, +-202, 96, 2, 118, 203, 86, 314, 14, +278, -78, 102, -146, -110, -155, -234, -85, +-229, 45, -112, 166, 52, 194, 185, 119, +223, 12, 161, -88, 30, -152, -108, -126, +-163, -18, -148, 93, -66, 159, 58, 154, +150, 68, 147, -37, 67, -87, -42, -77, +-131, -17, -146, 70, -69, 131, 36, 124, +104, 73, 126, 5, 71, -64, -30, -77, +-135, -24, -171, 44, -108, 104, 18, 141, +132, 110, 153, 31, 98, -31, 1, -67, +-113, -68, -190, -23, -186, 51, -93, 111, +62, 136, 173, 115, 185, 55, 107, -17, +-21, -65, -155, -81, -241, -55, -224, 4, +-124, 63, 38, 109, 208, 127, 271, 110, +176, 61, -9, -16, -197, -88, -312, -113, +-307, -93, -167, -38, 57, 53, 268, 146, +346, 190, 222, 157, -9, 46, -248, -101, +-395, -205, -348, -206, -130, -121, 134, 18, +328, 171, 369, 254, 215, 212, -56, 67, +-289, -125, -383, -274, -298, -298, -63, -197, +176, -16, 316, 177, 292, 293, 121, 278, +-86, 134, -218, -82, -236, -284, -169, -377, +-39, -308, 91, -117, 147, 113, 136, 296, +82, 349, 17, 232, -3, 3, -27, -244, +-78, -400, -111, -390, -100, -222, -53, 30, +30, 250, 140, 345, 201, 271, 186, 64, +98, -181, -54, -346, -204, -372, -254, -248, +-176, -33, 11, 173, 208, 287, 299, 256, +256, 102, 122, -90, -56, -247, -241, -310, +-296, -248, -178, -89, 18, 96, 198, 227, +297, 235, 259, 133, 89, -16, -113, -150, +-227, -226, -214, -210, -92, -105, 80, 23, +212, 114, 238, 138, 130, 94, -28, 27, +-148, -26, -178, -58, -107, -60, 26, -43, +152, -39, 189, -32, 121, -13, -4, 9, +-113, 47, -151, 92, -111, 110, -25, 77, +100, 3, 184, -84, 152, -136, 39, -114, +-75, -27, -137, 84, -146, 170, -87, 191, +17, 124, 114, 15, 167, -97, 136, -162, +29, -131, -85, -26, -161, 92, -162, 179, +-94, 194, 4, 128, 93, 28, 144, -67, +144, -119, 57, -94, -62, -11, -142, 75, +-171, 128, -139, 141, -48, 91, 50, 2, +117, -55, 150, -53, 122, -13, 21, 37, +-103, 70, -181, 74, -200, 61, -134, 22, +-18, -19, 96, -29, 172, 0, 174, 43, +100, 60, -29, 47, -160, 19, -235, -8, +-213, -21, -108, -14, 30, 6, 156, 38, +230, 68, 186, 69, 47, 41, -109, -20, +-227, -78, -262, -90, -187, -59, -25, -4, +130, 60, 219, 124, 211, 136, 113, 71, +-30, -35, -166, -133, -243, -195, -210, -165, +-95, -50, 47, 81, 154, 183, 185, 206, +149, 128, 60, -17, -38, -166, -133, -254, +-186, -227, -175, -111, -104, 31, 16, 151, +139, 203, 216, 153, 223, 30, 140, -92, +-25, -180, -200, -216, -298, -178, -264, -93, +-108, 14, 128, 116, 321, 159, 366, 131, +260, 68, 37, -36, -224, -161, -389, -242, +-365, -247, -173, -157, 103, 5, 348, 161, +440, 250, 330, 235, 85, 107, -197, -94, +-386, -273, -388, -359, -217, -312, 47, -121, +298, 130, 436, 307, 371, 344, 140, 242, +-133, 13, -331, -231, -380, -380, -257, -380, +-17, -220, 239, 42, 384, 283, 352, 393, +166, 325, -93, 116, -285, -128, -324, -329, +-211, -393, -19, -278, 174, -34, 291, 223, +271, 374, 130, 361, -66, 191, -217, -57, +-238, -274, -149, -365, -14, -274, 127, -47, +206, 192, 177, 348, 66, 362, -50, 198, +-144, -47, -175, -252, -104, -336, 8, -239, +95, -19, 143, 202, 137, 331, 59, 323, +-59, 169, -152, -60, -174, -237, -126, -280, +-6, -176, 132, 26, 201, 230, 154, 315, +28, 263, -108, 112, -215, -88, -229, -238, +-131, -266, 33, -145, 188, 60, 258, 249, +192, 333, 19, 279, -173, 96, -289, -121, +-277, -269, -137, -304, 66, -185, 225, 38, +281, 264, 203, 382, 23, 330, -175, 129, +-300, -119, -298, -312, -168, -367, 46, -250, +235, -12, 294, 246, 214, 397, 43, 368, +-159, 169, -302, -98, -305, -303, -141, -385, +86, -303, 240, -71, 245, 184, 122, 340, +-40, 354, -171, 210, -211, -25, -132, -240, +15, -362, 128, -320, 145, -138, 62, 74, +-59, 234, -144, 296, -126, 226, -14, 50, +115, -136, 178, -260, 120, -285, -20, -188, +-165, -21, -235, 115, -182, 184, -22, 176, +169, 73, 294, -48, 272, -137, 102, -189, +-127, -166, -287, -74, -316, 16, -206, 64, +12, 78, 229, 56, 347, 24, 317, -24, +147, -76, -92, -115, -289, -114, -352, -79, +-261, -30, -58, 29, 166, 71, 320, 85, +357, 71, 262, 9, 52, -93, -180, -163, +-349, -161, -378, -102, -239, -9, 25, 80, +296, 148, 455, 150, 433, 65, 215, -52, +-111, -157, -395, -203, -497, -161, -359, -53, +-46, 71, 278, 175, 474, 203, 463, 138, +247, 15, -72, -114, -331, -197, -432, -201, +-357, -114, -114, 27, 179, 159, 368, 225, +383, 188, 253, 81, 48, -48, -154, -166, +-298, -211, -333, -144, -233, -21, -29, 114, +180, 220, 311, 229, 340, 153, 224, 26, +-2, -109, -236, -192, -367, -175, -343, -86, +-168, 51, 84, 193, 300, 262, 383, 212, +293, 73, 72, -76, -177, -188, -347, -203, +-369, -120, -222, 25, 9, 190, 220, 279, +324, 230, 284, 90, 117, -75, -103, -195, +-257, -194, -291, -98, -204, 32, -53, 162, +85, 219, 179, 177, 206, 62, 131, -60, +10, -128, -88, -117, -150, -54, -172, 18, +-141, 80, -70, 106, 6, 86, 96, 52, +164, 27, 154, -17, 76, -53, -29, -54, +-133, -62, -200, -56, -199, -14, -115, 35, +25, 85, 162, 121, 230, 96, 195, 11, +73, -80, -104, -144, -239, -152, -263, -104, +-178, -6, -23, 91, 148, 147, 260, 137, +250, 49, 118, -61, -72, -142, -224, -167, +-270, -130, -197, -44, -52, 37, 118, 93, +237, 102, 249, 68, 140, 7, -36, -74, +-178, -125, -228, -127, -183, -97, -72, -47, +76, 1, 194, 52, 216, 106, 150, 107, +34, 24, -105, -73, -201, -153, -203, -191, +-108, -156, 40, -51, 177, 84, 234, 176, +174, 187, 49, 97, -80, -62, -180, -211, +-208, -276, -130, -208, 20, -36, 161, 134, +221, 233, 184, 240, 77, 114, -52, -77, +-157, -221, -212, -287, -167, -216, -29, -35, +130, 144, 225, 241, 223, 247, 143, 138, +4, -40, -155, -181, -255, -243, -236, -215, +-104, -88, 84, 94, 252, 213, 314, 254, +212, 203, 19, 52, -157, -108, -263, -202, +-262, -230, -145, -164, 40, -14, 200, 128, +282, 232, 252, 258, 118, 174, -58, 30, +-216, -100, -297, -183, -245, -215, -90, -160, +99, -18, 263, 144, 336, 260, 256, 283, +42, 190, -192, 29, -344, -132, -344, -254, +-196, -269, 26, -148, 237, 70, 357, 279, +320, 372, 142, 318, -103, 123, -317, -144, +-392, -344, -286, -381, -64, -245, 157, 21, +310, 308, 348, 478, 243, 449, 26, 198, +-212, -154, -365, -429, -368, -512, -215, -366, +33, -37, 266, 343, 367, 575, 306, 552, +122, 272, -121, -148, -325, -518, -363, -639, +-229, -463, -29, -61, 147, 396, 238, 661, +227, 623, 143, 300, 33, -183, -97, -589, +-215, -714, -252, -513, -190, -65, -74, 424, +76, 697, 208, 639, 254, 288, 199, -200, +68, -600, -109, -724, -272, -521, -322, -95, +-227, 385, -30, 677, 190, 621, 336, 282, +323, -167, 154, -552, -76, -685, -261, -507, +-344, -122, -294, 314, -110, 589, 125, 572, +300, 295, 344, -115, 251, -464, 53, -595, +-168, -469, -314, -163, -347, 191, -242, 440, +2, 477, 270, 304, 402, 9, 337, -284, +131, -453, -115, -420, -312, -237, -369, 17, +-261, 248, -27, 373, 216, 348, 344, 174, +316, -81, 149, -291, -71, -374, -229, -331, +-258, -150, -182, 89, -46, 273, 102, 339, +194, 263, 188, 83, 130, -125, 48, -279, +-47, -316, -115, -224, -124, -47, -87, 131, +-47, 242, 4, 269, 68, 207, 133, 56, +162, -114, 121, -240, 24, -268, -78, -179, +-157, -21, -191, 158, -149, 288, -22, 303, +142, 193, 242, -7, 242, -222, 145, -326, +-23, -270, -207, -82, -298, 166, -240, 338, +-87, 361, 94, 238, 259, 4, 327, -239, +234, -360, 29, -294, -187, -98, -323, 155, +-316, 354, -155, 391, 64, 251, 246, 32, +333, -203, 268, -358, 64, -321, -172, -144, +-309, 101, -296, 328, -161, 412, 30, 305, +203, 85, 277, -174, 221, -361, 67, -374, +-107, -221, -233, 34, -248, 292, -140, 428, +16, 367, 149, 161, 206, -103, 159, -344, +33, -429, -99, -309, -174, -77, -171, 183, +-88, 392, 32, 439, 117, 305, 131, 43, +79, -257, -21, -442, -106, -434, -124, -252, +-78, 36, -11, 327, 47, 490, 70, 431, +46, 166, -4, -183, -45, -451, -40, -518, +0, -354, 19, -37, -2, 298, -36, 496, +-67, 442, -58, 190, 9, -151, 92, -434, +113, -522, 70, -360, -6, -39, -106, 270, +-181, 439, -164, 413, -44, 199, 114, -125, +221, -377, 216, -466, 99, -357, -78, -85, +-227, 198, -273, 371, -200, 381, -34, 210, +181, -70, 347, -307, 342, -408, 165, -338, +-98, -110, -338, 164, -439, 333, -325, 331, +-43, 177, 273, -84, 487, -299, 484, -341, +245, -238, -115, -25, -430, 214, -572, 316, +-440, 237, -82, 55, 314, -172, 562, -316, +581, -271, 351, -87, -60, 126, -455, 265, +-633, 258, -519, 109, -175, -88, 251, -234, +570, -258, 632, -125, 416, 74, 43, 207, +-340, 225, -592, 134, -589, -38, -310, -170, +111, -191, 472, -117, 627, 29, 510, 154, +172, 187, -221, 127, -493, 15, -556, -106, +-397, -146, -74, -85, 276, 25, 506, 111, +528, 131, 327, 96, -3, 17, -316, -62, +-503, -92, -492, -52, -276, 35, 65, 105, +381, 124, 535, 89, 450, 9, 167, -71, +-167, -100, -413, -76, -495, -2, -381, 83, +-105, 121, 209, 115, 439, 53, 488, -30, +333, -75, 37, -69, -275, -28, -481, 36, +-491, 71, -286, 47, 37, 4, 345, -24, +524, -22, 479, 7, 201, 55, -176, 81, +-468, 51, -549, -18, -386, -104, -54, -146, +294, -90, 502, 33, 480, 158, 242, 214, +-97, 147, -394, -9, -519, -166, -397, -265, +-99, -217, 210, -41, 419, 163, 449, 295, +262, 273, -49, 87, -308, -160, -423, -331, +-370, -348, -136, -182, 161, 82, 356, 301, +366, 364, 211, 252, -28, 2, -231, -271, +-322, -406, -279, -347, -108, -127, 110, 152, +245, 334, 236, 351, 128, 217, -14, -35, +-130, -281, -184, -363, -158, -285, -77, -99, +15, 127, 86, 276, 131, 278, 132, 143, +73, -52, -11, -213, -81, -258, -132, -190, +-144, -63, -82, 81, 20, 171, 109, 153, +157, 68, 144, -22, 69, -93, -34, -94, +-127, -56, -182, -44, -162, -33, -74, -22, +53, -21, 190, 10, 266, 83, 203, 131, +32, 131, -167, 66, -311, -69, -309, -210, +-139, -271, 111, -192, 309, -6, 382, 215, +282, 346, 37, 317, -239, 142, -414, -114, +-395, -348, -174, -423, 140, -284, 386, 2, +460, 303, 335, 462, 57, 413, -255, 177, +-454, -147, -453, -396, -239, -472, 86, -333, +369, -21, 499, 314, 424, 508, 168, 486, +-175, 244, -456, -112, -542, -402, -377, -522, +-34, -417, 324, -103, 537, 280, 520, 530, +270, 551, -95, 352, -408, -7, -545, -366, +-449, -542, -155, -474, 199, -198, 442, 170, +503, 447, 373, 530, 91, 408, -234, 96, +-449, -239, -474, -428, -323, -429, -56, -262, +246, 12, 469, 271, 496, 398, 314, 369, +1, 193, -316, -48, -515, -248, -501, -334, +-262, -304, 97, -148, 405, 72, 529, 240, +434, 314, 158, 279, -192, 136, -459, -61, +-518, -232, -364, -315, -72, -256, 246, -100, +464, 80, 470, 241, 259, 301, -46, 229, +-313, 68, -448, -120, -396, -261, -182, -291, +91, -192, 302, -18, 382, 151, 315, 246, +118, 231, -125, 113, -306, -53, -353, -198, +-260, -255, -77, -196, 133, -62, 288, 90, +318, 188, 202, 184, 8, 106, -165, -17, +-260, -135, -262, -181, -172, -147, -25, -73, +131, 33, 238, 109, 250, 116, 164, 82, +8, 16, -153, -50, -257, -92, -257, -102, +-151, -90, 20, -42, 181, 22, 259, 62, +227, 77, 105, 75, -66, 29, -212, -43, +-257, -73, -189, -89, -42, -77, 121, -19, +232, 41, 229, 69, 117, 56, -36, 3, +-160, -47, -197, -54, -136, -30, -22, 14, +79, 55, 127, 62, 122, 22, 84, -47, +34, -103, -28, -101, -99, -30, -134, 67, +-104, 136, -21, 146, 78, 80, 146, -36, +152, -132, 90, -166, -9, -127, -114, -4, +-178, 128, -144, 191, -27, 176, 93, 75, +159, -56, 159, -147, 93, -168, -21, -97, +-125, 28, -163, 128, -127, 163, -37, 143, +68, 61, 146, -51, 162, -123, 110, -114, +5, -60, -106, 12, -150, 79, -117, 98, +-55, 79, 30, 34, 132, -12, 172, -34, +115, -28, 19, -24, -63, 1, -128, 21, +-136, 8, -75, 2, -1, 3, 58, 12, +105, 36, 126, 54, 98, 49, 30, 28, +-54, -4, -115, -49, -142, -84, -134, -78, +-65, -30, 65, 40, 184, 107, 223, 124, +161, 87, 11, 23, -163, -64, -266, -134, +-235, -148, -91, -102, 97, 1, 231, 108, +259, 159, 185, 152, 25, 91, -161, -30, +-265, -149, -248, -209, -148, -189, 17, -83, +195, 63, 289, 203, 249, 270, 109, 212, +-94, 39, -279, -162, -339, -310, -238, -350, +-17, -237, 216, 9, 342, 267, 299, 406, +119, 382, -125, 161, -303, -155, -316, -409, +-188, -495, -8, -357, 168, -40, 272, 285, +237, 471, 95, 452, -63, 220, -182, -119, +-239, -403, -201, -504, -81, -373, 80, -71, +218, 245, 261, 430, 169, 422, -20, 219, +-196, -97, -264, -361, -205, -444, -49, -332, +147, -63, 266, 233, 212, 389, 38, 356, +-129, 157, -218, -116, -180, -316, -31, -357, +122, -222, 181, 24, 130, 240, 2, 311, +-134, 213, -165, 12, -86, -181, 37, -262, +142, -198, 162, -26, 73, 152, -46, 239, +-109, 187, -121, 38, -96, -123, -23, -225, +55, -197, 92, -56, 106, 112, 102, 222, +63, 239, -33, 144, -146, -14, -194, -179, +-142, -274, -12, -221, 144, -65, 254, 123, +230, 277, 71, 314, -110, 200, -224, -11, +-241, -226, -139, -340, 32, -294, 177, -93, +229, 169, 192, 360, 96, 391, -37, 223, +-157, -59, -230, -304, -206, -398, -87, -296, +67, -50, 201, 212, 274, 373, 233, 364, +86, 188, -103, -55, -262, -243, -324, -315, +-235, -254, -16, -111, 217, 54, 364, 204, +351, 271, 169, 237, -92, 130, -300, -25, +-370, -177, -277, -266, -42, -257, 210, -151, +340, 23, 314, 203, 165, 304, -42, 281, +-223, 150, -311, -77, -270, -270, -114, -321, +101, -243, 268, -71, 300, 143, 206, 285, +41, 288, -141, 178, -271, -9, -270, -187, +-143, -279, 17, -262, 152, -146, 246, 34, +252, 197, 143, 270, -25, 237, -184, 103, +-294, -90, -289, -249, -127, -296, 109, -230, +297, -60, 356, 143, 252, 265, 4, 272, +-271, 150, -406, -53, -324, -219, -81, -287, +195, -230, 374, -62, 370, 127, 176, 237, +-117, 219, -345, 97, -386, -62, -234, -181, +13, -216, 248, -155, 359, -23, 287, 113, +82, 174, -133, 154, -272, 80, -318, -41, +-241, -145, -45, -178, 189, -141, 334, -47, +326, 85, 182, 168, -60, 174, -307, 107, +-412, -32, -303, -153, -42, -196, 241, -152, +419, -45, 392, 87, 141, 186, -186, 198, +-396, 109, -393, -31, -210, -158, 60, -202, +302, -151, 382, -37, 259, 112, 24, 202, +-183, 185, -287, 90, -268, -37, -127, -144, +58, -183, 176, -139, 214, -39, 195, 64, +109, 129, -37, 158, -163, 140, -204, 58, +-179, -38, -80, -114, 85, -172, 218, -176, +227, -102, 121, 47, -30, 198, -162, 265, +-198, 232, -126, 105, -2, -94, 119, -288, +169, -358, 110, -228, 4, 24, -70, 259, +-84, 401, -61, 357, -10, 128, 41, -173, +52, -394, 37, -407, 9, -216, -29, 63, +-46, 316, -16, 445, 44, 347, 75, 65, +57, -224, -1, -377, -71, -360, -103, -189, +-84, 78, -18, 317, 64, 393, 127, 265, +148, 21, 79, -198, -39, -298, -123, -276, +-149, -120, -132, 99, -54, 231, 87, 231, +190, 129, 181, -13, 92, -119, -38, -156, +-170, -112, -223, -14, -142, 55, 34, 66, +183, 36, 211, 9, 119, 3, -9, 11, +-127, 22, -204, 12, -154, -32, 1, -94, +129, -123, 170, -67, 146, 53, 53, 153, +-91, 183, -185, 119, -161, -41, -62, -216, +60, -265, 149, -172, 159, 5, 84, 190, +-38, 280, -134, 232, -157, 48, -98, -172, +4, -301, 105, -271, 152, -103, 109, 111, +15, 258, -77, 275, -138, 135, -151, -75, +-104, -221, 12, -255, 150, -162, 209, 4, +149, 160, 22, 221, -115, 167, -226, 39, +-233, -98, -106, -176, 63, -171, 193, -113, +257, -21, 209, 104, 34, 191, -164, 174, +-280, 91, -284, -21, -158, -154, 74, -230, +288, -203, 369, -78, 258, 112, -12, 265, +-294, 287, -421, 163, -331, -37, -80, -241, +236, -355, 434, -273, 392, -31, 153, 226, +-149, 387, -377, 342, -427, 117, -259, -156, +43, -368, 308, -398, 410, -202, 320, 98, +85, 324, -190, 401, -377, 298, -370, 41, +-180, -248, 84, -405, 298, -347, 365, -116, +267, 164, 47, 366, -195, 410, -356, 257, +-347, -45, -165, -342, 88, -442, 313, -321, +417, -53, 315, 247, 44, 446, -262, 459, +-450, 239, -413, -125, -155, -434, 187, -552, +422, -414, 467, -46, 293, 369, -41, 632, +-355, 605, -471, 277, -346, -221, -73, -644, +239, -763, 441, -508, 399, 34, 155, 598, +-132, 866, -331, 713, -366, 219, -229, -421, +23, -886, 242, -904, 324, -461, 243, 222, +57, 828, -111, 1025, -203, 696, -210, 16, +-139, -698, -12, -1063, 115, -888, 176, -263, +160, 495, 80, 1018, -26, 1035, -96, 507, +-117, -275, -89, -886, -27, -1060, 21, -715, +31, 1, 11, 709, 9, 1054, 37, 843, +77, 193, 93, -534, 55, -956, -27, -884, +-136, -375, -205, 322, -155, 841, -6, 894, +152, 460, 245, -192, 225, -712, 83, -850, +-108, -544, -232, 39, -252, 582, -166, 806, +-4, 592, 150, 69, 237, -473, 226, -770, +119, -658, -31, -192, -149, 371, -230, 721, +-265, 677, -177, 290, 25, -247, 221, -672, +338, -737, 323, -426, 140, 100, -141, 593, +-362, 776, -415, 559, -280, 58, 2, -475, +282, -793, 421, -724, 366, -292, 141, 291, +-144, 741, -353, 834, -388, 513, -244, -61, +-7, -591, 207, -835, 319, -693, 290, -233, +118, 342, -101, 747, -222, 798, -225, 466, +-148, -71, -22, -550, 88, -785, 129, -651, +115, -204, 87, 326, 56, 680, 30, 694, +-23, 395, -126, -62, -198, -476, -166, -642, +-60, -511, 96, -166, 257, 228, 303, 489, +180, 530, -46, 356, -266, 57, -363, -252, +-250, -457, -11, -467, 216, -278, 332, 20, +276, 297, 95, 451, -103, 429, -238, 222, +-255, -84, -136, -356, 28, -463, 120, -356, +151, -105, 149, 206, 94, 431, 19, 451, +-50, 251, -119, -69, -172, -322, -155, -414, +-45, -339, 113, -107, 248, 191, 270, 394, +161, 391, -38, 205, -278, -19, -399, -225, +-268, -371, 24, -373, 289, -193, 430, 97, +393, 335, 124, 424, -250, 356, -484, 141, +-465, -176, -214, -446, 148, -513, 455, -337, +548, -3, 359, 355, -25, 582, -405, 560, +-568, 247, -442, -229, -115, -605, 282, -711, +555, -497, 541, -28, 260, 525, -108, 865, +-411, 752, -579, 262, -481, -346, -114, -817, +289, -938, 537, -631, 570, 8, 375, 687, +-20, 1035, -433, 903, -647, 365, -568, -349, +-211, -937, 260, -1112, 592, -774, 637, -78, +389, 656, -30, 1105, -421, 1066, -604, 538, +-511, -249, -192, -927, 207, -1176, 477, -921, +513, -277, 338, 508, 24, 1118, -282, 1220, +-435, 736, -403, -78, -229, -854, 32, -1247, +286, -1123, 399, -495, 328, 414, 138, 1148, +-79, 1326, -251, 909, -350, 101, -314, -761, +-124, -1304, 102, -1253, 244, -627, 292, 267, +257, 1037, 110, 1330, -87, 1035, -223, 289, +-271, -594, -231, -1192, -114, -1215, 23, -712, +147, 47, 248, 768, 291, 1156, 215, 1023, +21, 443, -212, -300, -380, -871, -380, -1037, +-213, -792, 70, -235, 362, 420, 504, 896, +391, 972, 59, 622, -301, 35, -498, -549, +-454, -897, -196, -866, 154, -485, 424, 102, +471, 661, 307, 925, 24, 795, -294, 326, +-458, -280, -335, -761, -69, -920, 141, -678, +275, -139, 318, 464, 181, 855, -41, 871, +-171, 511, -191, -63, -133, -597, -37, -858, +23, -749, 48, -317, 88, 253, 107, 721, +80, 875, 52, 622, -11, 76, -131, -508, +-166, -831, -85, -778, 33, -378, 156, 221, +235, 727, 156, 881, -63, 604, -254, 31, +-306, -534, -171, -826, 110, -728, 347, -294, +397, 271, 244, 713, -74, 802, -412, 509, +-543, -13, -350, -512, 54, -730, 449, -594, +620, -217, 462, 227, 74, 556, -370, 620, +-661, 412, -608, 49, -223, -318, 268, -536, +610, -506, 664, -292, 415, 21, -26, 345, +-444, 547, -663, 519, -588, 254, -243, -119, +203, -481, 569, -656, 689, -530, 490, -165, +63, 298, -368, 671, -615, 749, -618, 483, +-360, -34, 79, -585, 476, -867, 622, -726, +477, -240, 159, 343, -193, 787, -441, 875, +-500, 530, -386, -62, -123, -608, 192, -852, +397, -673, 427, -189, 325, 320, 126, 651, +-157, 692, -398, 409, -471, -57, -369, -437, +-111, -585, 218, -457, 455, -143, 495, 180, +338, 370, 29, 374, -319, 246, -512, 56, +-465, -117, -250, -215, 58, -237, 339, -200, +468, -134, 401, -62, 186, 70, -86, 236, +-317, 349, -416, 339, -363, 162, -187, -131, +54, -418, 260, -542, 373, -436, 381, -120, +253, 297, -1, 634, -278, 692, -436, 396, +-440, -114, -302, -570, -16, -748, 332, -582, +571, -155, 551, 339, 282, 685, -112, 687, +-489, 361, -685, -110, -577, -477, -188, -585, +306, -454, 672, -159, 760, 176, 519, 403, +20, 452, -526, 336, -849, 119, -766, -119, +-339, -316, 245, -393, 754, -346, 943, -195, +677, 44, 69, 306, -561, 489, -916, 485, +-843, 258, -388, -107, 241, -438, 770, -604, +931, -532, 635, -220, 76, 228, -480, 593, +-823, 699, -794, 491, -380, 64, 198, -383, +664, -658, 840, -657, 625, -396, 116, 57, +-423, 485, -775, 696, -784, 622, -405, 275, +181, -186, 666, -540, 847, -676, 642, -548, +91, -178, -510, 280, -826, 614, -746, 684, +-304, 493, 306, 71, 752, -398, 786, -692, +439, -720, -87, -449, -546, 54, -703, 561, +-520, 832, -127, 760, 302, 331, 569, -286, +563, -769, 324, -907, -41, -671, -395, -118, +-571, 515, -464, 915, -157, 898, 211, 476, +502, -161, 558, -728, 338, -946, -48, -750, +-395, -223, -529, 422, -410, 852, -133, 875, +176, 527, 409, -64, 444, -621, 264, -866, +13, -711, -201, -261, -347, 280, -367, 705, +-242, 804, -14, 542, 225, 56, 383, -441, +364, -729, 182, -694, -70, -374, -311, 81, +-422, 483, -330, 678, -89, 599, 190, 295, +398, -104, 412, -466, 196, -661, -105, -607, +-317, -298, -389, 116, -282, 485, -29, 722, +223, 688, 340, 333, 276, -204, 88, -680, +-126, -882, -241, -707, -216, -205, -110, 424, +17, 900, 114, 992, 153, 599, 117, -87, +27, -728, -51, -1076, -87, -934, -86, -325, +-47, 425, 11, 949, 64, 1063, 78, 714, +50, 37, -12, -635, -68, -1020, -89, -979, +-79, -496, -15, 186, 86, 731, 147, 982, +124, 867, 55, 379, -43, -290, -179, -798, +-254, -988, -155, -792, 42, -239, 209, 394, +293, 834, 274, 962, 110, 698, -163, 119, +-375, -489, -387, -884, -191, -928, 92, -579, +323, 28, 423, 574, 331, 882, 77, 870, +-203, 475, -381, -120, -398, -633, -252, -901, +7, -831, 249, -395, 366, 191, 378, 671, +298, 923, 82, 837, -234, 377, -479, -240, +-518, -773, -356, -1037, -26, -875, 388, -330, +691, 336, 688, 869, 354, 1111, -162, 890, +-650, 259, -864, -454, -653, -988, -120, -1165, +469, -864, 848, -200, 861, 533, 493, 1073, +-114, 1217, -679, 858, -927, 131, -734, -638, +-224, -1195, 351, -1300, 773, -840, 876, -25, +586, 806, 25, 1364, -519, 1384, -813, 787, +-771, -160, -389, -1057, 171, -1557, 617, -1407, +770, -624, 610, 428, 205, 1325, -291, 1693, +-624, 1329, -646, 386, -404, -706, -32, -1522, +301, -1758, 471, -1219, 449, -136, 281, 971, +43, 1684, -171, 1743, -293, 1069, -331, -63, +-308, -1173, -212, -1819, -34, -1734, 218, -912, +451, 298, 497, 1376, 324, 1931, 24, 1706, +-313, 746, -592, -534, -637, -1604, -374, -2053, +61, -1648, 486, -496, 731, 890, 661, 1888, +299, 2101, -201, 1439, -641, 156, -825, -1213, +-656, -2098, -204, -2091, 355, -1161, 795, 284, +869, 1565, 541, 2176, 23, 1922, -493, 855, +-843, -595, -845, -1790, -472, -2247, 86, -1779, +601, -539, 874, 935, 775, 2005, 375, 2254, +-151, 1601, -653, 246, -916, -1245, -788, -2217, +-339, -2291, 248, -1378, 768, 180, 987, 1654, +780, 2386, 261, 2131, -393, 977, -945, -637, +-1087, -1978, -718, -2440, -44, -1852, 644, -454, +1082, 1123, 1053, 2145, 552, 2236, -180, 1412, +-832, -3, -1133, -1417, -934, -2176, -339, -2014, +387, -1031, 947, 395, 1116, 1621, 825, 2118, +191, 1757, -536, 684, -1060, -693, -1123, -1775, +-678, -2102, 62, -1551, 763, -336, 1132, 1031, +1015, 1899, 465, 1944, -276, 1216, -887, -27, +-1104, -1260, -833, -1908, -216, -1720, 447, -839, +904, 367, 991, 1367, 672, 1736, 79, 1395, +-519, 527, -880, -544, -888, -1350, -533, -1563, +49, -1154, 588, -310, 860, 651, 801, 1325, +436, 1420, -113, 963, -621, 143, -867, -743, +-764, -1312, -343, -1322, 206, -791, 647, 60, +854, 865, 753, 1282, 324, 1173, -270, 610, +-730, -196, -893, -927, -731, -1228, -270, -1024, +337, -453, 843, 284, 1032, 904, 774, 1140, +147, 930, -562, 388, -1044, -308, -1108, -878, +-674, -1082, 110, -884, 850, -356, 1213, 352, +1051, 918, 407, 1089, -446, 836, -1085, 269, +-1223, -435, -829, -965, -68, -1061, 713, -731, +1147, -111, 1079, 566, 561, 985, -197, 971, +-846, 573, -1103, -44, -909, -616, -371, -907, +322, -830, 885, -440, 1069, 133, 825, 642, +241, 839, -469, 720, -997, 360, -1103, -134, +-753, -568, -84, -760, 651, -674, 1124, -347, +1104, 115, 600, 521, -181, 722, -887, 682, +-1192, 402, -994, -41, -385, -464, 416, -738, +1060, -775, 1211, -512, 835, -1, 125, 515, +-663, 828, -1174, 869, -1146, 581, -634, 10, +126, -615, 858, -1006, 1220, -982, 1030, -533, +416, 154, -370, 789, -1032, 1109, -1234, 993, +-888, 426, -196, -366, 605, -990, 1203, -1190, +1247, -900, 699, -210, -130, 579, -901, 1091, +-1296, 1143, -1087, 739, -372, 8, 499, -732, +1146, -1137, 1239, -1074, 733, -574, -55, 163, +-756, 788, -1120, 1056, -964, 944, -346, 488, +359, -202, 828, -782, 925, -1022, 618, -906, +62, -459, -443, 179, -692, 733, -647, 1021, +-361, 960, 18, 500, 336, -197, 519, -811, +514, -1131, 314, -1050, 37, -497, -215, 301, +-413, 972, -505, 1288, -396, 1090, -109, 367, +224, -552, 484, -1229, 572, -1420, 430, -1000, +96, -86, -284, 875, -549, 1438, -597, 1399, +-402, 723, -27, -305, 374, -1171, 629, -1512, +629, -1225, 365, -382, -62, 655, -479, 1350, +-702, 1436, -617, 919, -245, -9, 230, -902, +604, -1340, 731, -1213, 529, -593, 74, 298, +-388, 1020, -651, 1219, -644, 903, -364, 252, +77, -490, 456, -949, 617, -946, 535, -589, +239, -37, -142, 514, -441, 788, -569, 690, +-473, 356, -166, -69, 190, -416, 436, -531, +546, -448, 454, -283, 125, -28, -265, 252, +-499, 410, -533, 408, -363, 314, -20, 134, +329, -105, 517, -321, 485, -476, 246, -465, +-87, -218, -351, 131, -477, 412, -428, 570, +-187, 530, 124, 246, 346, -150, 452, -473, +409, -646, 149, -566, -195, -201, -409, 235, +-454, 547, -342, 667, -66, 536, 247, 179, +427, -225, 434, -555, 271, -717, -33, -563, +-316, -131, -439, 307, -392, 599, -187, 716, +106, 563, 351, 147, 438, -343, 344, -706, +88, -809, -207, -540, -376, -33, -388, 452, +-265, 779, 1, 824, 282, 493, 388, -60, +317, -576, 149, -896, -90, -851, -311, -382, +-362, 241, -243, 697, -37, 909, 177, 777, +304, 274, 290, -340, 164, -800, -26, -969, +-206, -722, -262, -137, -208, 441, -115, 825, +33, 950, 209, 677, 265, 74, 186, -527, +73, -938, -62, -1020, -209, -620, -254, 68, +-161, 656, -16, 988, 130, 977, 224, 506, +217, -199, 121, -789, -11, -1087, -143, -929, +-213, -320, -188, 368, -102, 842, 22, 1039, +165, 819, 257, 192, 237, -486, 119, -927, +-70, -1055, -243, -734, -304, -69, -226, 578, +-53, 982, 166, 1034, 335, 629, 344, -53, +198, -666, -30, -1049, -265, -1037, -407, -527, +-359, 205, -135, 766, 161, 1035, 404, 925, +485, 406, 349, -268, 46, -790, -309, -1030, +-556, -870, -539, -321, -236, 314, 195, 786, +528, 990, 625, 807, 441, 284, 36, -303, +-414, -769, -669, -999, -586, -824, -225, -266, +228, 364, 555, 821, 622, 1010, 421, 812, +53, 282, -331, -349, -565, -881, -557, -1122, +-330, -877, 26, -234, 381, 481, 574, 1023, +526, 1216, 279, 915, -88, 220, -455, -575, +-655, -1204, -566, -1371, -212, -911, 253, -39, +596, 814, 668, 1372, 474, 1423, 83, 858, +-387, -80, -709, -1001, -685, -1562, -364, -1467, +87, -687, 509, 356, 726, 1215, 614, 1633, +236, 1415, -219, 558, -582, -536, -715, -1415, +-551, -1749, -147, -1322, 324, -306, 642, 794, +684, 1566, 465, 1768, 66, 1227, -385, 127, +-696, -1023, -714, -1775, -433, -1815, 36, -1034, +504, 191, 761, 1275, 706, 1861, 358, 1733, +-160, 853, -629, -423, -816, -1516, -657, -1998, +-236, -1616, 295, -520, 715, 725, 827, 1626, +597, 1925, 116, 1433, -439, 286, -805, -948, +-806, -1755, -480, -1863, 41, -1187, 585, -11, +879, 1085, 762, 1719, 321, 1709, -241, 994, +-703, -134, -850, -1170, -619, -1756, -140, -1657, +390, -827, 745, 319, 754, 1248, 442, 1703, +-15, 1542, -444, 716, -665, -416, -573, -1357, +-277, -1778, 58, -1478, 353, -534, 523, 587, +478, 1414, 278, 1717, 20, 1344, -246, 397, +-446, -692, -489, -1499, -367, -1743, -97, -1249, +253, -214, 521, 835, 579, 1501, 427, 1621, +107, 1114, -295, 142, -587, -858, -651, -1536, +-479, -1634, -99, -1043, 371, -33, 700, 921, +740, 1526, 499, 1608, 50, 1053, -469, 50, +-831, -990, -844, -1700, -482, -1753, 108, -1028, +668, 118, 963, 1179, 855, 1817, 366, 1796, +-293, 1004, -821, -256, -1015, -1433, -798, -2061, +-216, -1819, 474, -774, 930, 565, 991, 1642, +682, 2119, 98, 1759, -547, 615, -965, -814, +-986, -1910, -618, -2238, -5, -1606, 619, -268, +1013, 1128, 1018, 2057, 598, 2217, -98, 1458, +-773, 20, -1143, -1424, -1058, -2266, -508, -2165, +292, -1117, 977, 383, 1255, 1635, 1010, 2236, +322, 1990, -518, 884, -1137, -613, -1279, -1800, +-888, -2236, -113, -1763, 712, -543, 1227, 826, +1230, 1792, 721, 2117, -96, 1626, -860, 394, +-1247, -983, -1125, -1876, -555, -2030, 243, -1383, +928, -162, 1224, 1068, 1033, 1838, 425, 1952, +-365, 1280, -995, 51, -1209, -1155, -955, -1882, +-335, -1907, 444, -1156, 1061, 69, 1235, 1206, +906, 1907, 220, 1940, -556, 1144, -1115, -174, +-1229, -1381, -864, -2058, -145, -1963, 667, -1035, +1226, 337, 1281, 1564, 808, 2216, -3, 1996, +-840, 871, -1348, -627, -1302, -1839, -720, -2339, +189, -1890, 1066, -598, 1497, 932, 1284, 2052, +532, 2373, -456, 1708, -1274, 273, -1550, -1250, +-1170, -2236, -307, -2345, 719, -1458, 1456, 77, +1551, 1536, 976, 2348, -9, 2235, -1001, 1150, +-1545, -459, -1396, -1814, -663, -2403, 343, -2030, +1204, -777, 1502, 808, 1121, 1973, 320, 2311, +-573, 1712, -1216, 368, -1296, -1100, -818, -2021, +-88, -2104, 622, -1333, 1090, -2, 1110, 1232, +693, 1857, 43, 1761, -601, 985, -998, -217, +-989, -1236, -629, -1649, -43, -1442, 602, -721, +1012, 267, 987, 1065, 602, 1399, -16, 1250, +-682, 633, -1060, -226, -964, -924, -507, -1245, +135, -1153, 756, -612, 1065, 161, 927, 787, +445, 1127, -235, 1124, -856, 664, -1091, -69, +-863, -692, -325, -1066, 362, -1114, 944, -726, +1104, -65, 778, 557, 157, 1036, -534, 1223, +-1006, 906, -1021, 218, -609, -525, 19, -1149, +644, -1416, 1001, -1082, 911, -294, 467, 625, +-135, 1413, -710, 1698, -998, 1208, -828, 187, +-331, -929, 260, -1746, 759, -1848, 954, -1113, +731, 80, 209, 1249, -372, 1996, -799, 1900, +-885, 950, -600, -373, -93, -1545, 437, -2129, +781, -1787, 776, -690, 461, 617, 3, 1714, +-467, 2206, -779, 1748, -739, 520, -369, -868, +118, -1920, 541, -2239, 747, -1623, 639, -344, +278, 1080, -183, 2151, -588, 2352, -751, 1504, +-564, 42, -151, -1433, 291, -2391, 604, -2337, +665, -1225, 443, 364, 60, 1793, -345, 2546, +-633, 2205, -638, 865, -337, -804, 81, -2108, +433, -2546, 608, -1882, 522, -439, 206, 1129, +-178, 2253, -473, 2446, -582, 1540, -420, 32, +-46, -1384, 307, -2258, 463, -2224, 413, -1210, +218, 255, -34, 1514, -236, 2186, -336, 1972, +-298, 904, -128, -476, 54, -1581, 142, -2084, +192, -1744, 226, -658, 171, 642, 44, 1634, +-86, 1997, -228, 1529, -326, 422, -239, -782, +-16, -1663, 187, -1921, 327, -1362, 362, -228, +210, 918, -64, 1694, -308, 1843, -417, 1198, +-316, 43, -38, -1070, 222, -1762, 337, -1774, +328, -1004, 186, 171, -56, 1208, -250, 1770, +-302, 1632, -234, 757, -65, -402, 140, -1321, +261, -1723, 258, -1425, 144, -494, -42, 583, +-187, 1341, -219, 1594, -172, 1200, -52, 275, +120, -700, 214, -1332, 156, -1460, 37, -992, +-68, -117, -131, 728, -103, 1287, -20, 1401, +42, 907, 73, 3, 66, -824, 1, -1322, +-56, -1345, -57, -769, -33, 141, 18, 918, +92, 1357, 87, 1293, -12, 616, -85, -330, +-102, -1052, -93, -1333, -28, -1071, 87, -334, +162, 452, 167, 991, 96, 1211, -67, 920, +-228, 156, -242, -566, -122, -935, 27, -993, +153, -667, 224, -47, 204, 485, 97, 785, +-70, 882, -240, 609, -284, 44, -154, -451, +36, -742, 182, -802, 268, -531, 258, -82, +106, 317, -120, 698, -296, 893, -339, 628, +-218, 93, 30, -386, 264, -766, 352, -894, +277, -607, 99, -122, -127, 378, -317, 870, +-371, 1037, -241, 649, 34, 10, 289, -575, +362, -983, 240, -991, 51, -541, -133, 83, +-280, 690, -288, 1094, -140, 975, 39, 382, +161, -296, 227, -848, 201, -1097, 79, -816, +-44, -196, -110, 400, -167, 868, -196, 1066, +-130, 755, 20, 107, 156, -516, 202, -950, +160, -1017, 62, -634, -46, -44, -136, 511, +-173, 965, -144, 1060, -63, 644, 47, -16, +144, -640, 184, -1095, 165, -1102, 88, -565, +-55, 163, -203, 796, -257, 1195, -194, 1102, +-58, 461, 128, -362, 268, -1042, 270, -1329, +150, -976, -32, -158, -203, 619, -258, 1128, +-177, 1274, -62, 828, 63, -56, 203, -858, +246, -1275, 140, -1191, -2, -533, -122, 351, +-201, 975, -177, 1219, -76, 1027, 7, 322, +89, -552, 191, -1103, 202, -1192, 110, -782, +1, 13, -117, 725, -220, 1027, -209, 996, +-104, 577, 18, -203, 170, -860, 296, -1031, +252, -799, 59, -248, -140, 437, -273, 834, +-281, 835, -144, 590, 40, 83, 191, -545, +307, -848, 291, -707, 77, -317, -178, 186, +-308, 577, -298, 637, -159, 473, 66, 205, +240, -211, 286, -540, 219, -524, 47, -284, +-174, -13, -286, 237, -218, 332, -54, 256, +112, 186, 203, 89, 178, -112, 81, -240, +-17, -201, -105, -132, -157, -52, -120, 39, +-19, 77, 49, 126, 56, 208, 46, 159, +50, 0, 49, -91, 31, -140, 3, -196, +-25, -161, -57, -61, -95, 26, -92, 171, +-29, 305, 50, 252, 101, 72, 121, -99, +90, -254, -6, -316, -105, -222, -150, -82, +-134, 91, -63, 314, 45, 403, 127, 246, +161, 23, 144, -173, 47, -333, -104, -341, +-193, -194, -186, -31, -132, 159, -11, 358, +153, 366, 232, 187, 170, -30, 48, -240, +-72, -376, -162, -309, -185, -130, -138, 53, +-42, 291, 90, 461, 178, 338, 165, 16, +107, -275, 26, -453, -98, -409, -187, -129, +-170, 173, -107, 359, -15, 438, 115, 303, +185, -47, 147, -356, 71, -446, -14, -310, +-109, 2, -134, 281, -94, 315, -64, 217, +-13, 105, 74, -92, 103, -293, 84, -289, +78, -122, 46, 78, -33, 253, -93, 251, +-127, 65, -151, -58, -85, -72, 56, -141, +178, -190, 235, -112, 189, 10, 18, 143, +-163, 257, -236, 180, -228, -10, -154, -59, +22, -78, 199, -212, 251, -250, 192, -85, +73, 116, -56, 292, -136, 326, -163, 105, +-177, -127, -137, -167, -12, -209, 125, -262, +220, -106, 243, 140, 150, 277, -17, 330, +-154, 211, -242, -108, -273, -278, -183, -218, +20, -195, 218, -146, 324, 75, 295, 250, +136, 283, -53, 250, -202, 47, -318, -219, +-351, -248, -194, -152, 89, -153, 317, -59, +404, 149, 333, 213, 120, 183, -143, 152, +-351, -8, -440, -171, -360, -131, -97, -92, +234, -137, 462, -61, 490, 75, 309, 118, +7, 179, -288, 204, -480, 53, -511, -92, +-340, -131, 8, -222, 383, -253, 602, -63, +544, 125, 240, 214, -145, 295, -456, 231, +-611, -21, -523, -180, -183, -214, 253, -250, +566, -164, 635, 35, 433, 133, 23, 175, +-386, 243, -599, 155, -582, -30, -370, -93, +13, -126, 445, -209, 690, -181, 611, -71, +267, 22, -183, 176, -552, 293, -691, 207, +-563, 63, -200, -36, 288, -215, 680, -339, +740, -238, 439, -62, -61, 99, -527, 306, +-725, 376, -571, 197, -188, -5, 233, -154, +547, -320, 607, -362, 380, -206, 8, -5, +-322, 212, -488, 395, -431, 357, -222, 142, +15, -48, 227, -235, 382, -396, 385, -331, +197, -103, -72, 101, -306, 269, -397, 364, +-283, 250, -43, 41, 176, -118, 288, -248, +264, -293, 110, -191, -84, -57, -185, 59, +-162, 215, -68, 295, 16, 211, 24, 81, +-19, -51, -42, -231, 11, -322, 109, -256, +163, -118, 117, 93, -7, 325, -136, 382, +-194, 244, -159, 49, -70, -187, 39, -370, +151, -340, 189, -177, 109, -15, 5, 199, +-54, 374, -93, 313, -111, 112, -90, -55, +-72, -194, -36, -276, 89, -233, 200, -136, +169, 22, 40, 232, -85, 294, -174, 166, +-184, 60, -99, -30, 22, -171, 139, -205, +188, -123, 90, -83, -79, -14, -139, 132, +-69, 152, 48, 99, 122, 146, 75, 139, +-73, -27, -175, -169, -151, -263, -41, -322, +115, -162, 234, 137, 222, 308, 77, 368, +-135, 355, -305, 95, -279, -273, -67, -453, +120, -433, 178, -230, 188, 154, 146, 415, +31, 378, -52, 261, -90, 91, -159, -203, +-218, -376, -168, -285, -53, -137, 86, 15, +263, 185, 378, 222, 295, 151, 12, 129, +-331, 72, -528, -76, -446, -162, -149, -203, +207, -229, 507, -102, 591, 110, 310, 209, +-150, 258, -472, 274, -573, 100, -455, -167, +-96, -303, 329, -319, 527, -226, 456, 27, +229, 246, -91, 292, -376, 256, -466, 140, +-359, -82, -119, -234, 165, -258, 355, -235, +368, -95, 236, 132, -1, 227, -257, 198, +-343, 183, -246, 81, -109, -107, 36, -220, +196, -250, 238, -221, 127, -31, 24, 193, +-23, 245, -93, 225, -149, 171, -134, -34, +-105, -236, -68, -242, 33, -194, 159, -123, +192, 80, 109, 244, -13, 202, -113, 126, +-174, 82, -181, -45, -92, -164, 67, -203, +166, -219, 127, -113, 34, 123, -19, 234, +-48, 214, -82, 205, -88, 64, -63, -223, +-45, -329, -19, -225, 57, -105, 129, 102, +105, 350, 25, 332, -36, 77, -86, -133, +-145, -265, -119, -283, 35, -106, 144, 94, +69, 187, -54, 242, -71, 156, -33, -114, +3, -243, 63, -131, 97, -13, 20, 91, +-115, 216, -194, 136, -138, -89, 39, -165, +199, -150, 221, -138, 113, 25, -78, 251, +-267, 282, -276, 166, -76, -40, 124, -315, +201, -393, 193, -167, 82, 73, -108, 252, +-210, 431, -154, 369, -36, -2, 79, -342, +126, -488, 52, -444, -23, -98, -24, 363, +-25, 560, -42, 474, -10, 205, -3, -241, +-64, -588, -67, -561, 8, -294, 56, 78, +83, 516, 96, 704, 0, 430, -146, -20, +-172, -394, -76, -631, 41, -572, 140, -185, +160, 267, 59, 594, -95, 669, -206, 355, +-202, -159, -64, -522, 110, -637, 181, -489, +142, -31, 50, 470, -75, 661, -169, 519, +-154, 159, -73, -322, 8, -646, 77, -591, +108, -264, 73, 181, 8, 569, -39, 646, +-85, 363, -128, -47, -128, -424, -48, -643, +91, -535, 171, -131, 115, 309, 5, 598, +-73, 641, -160, 376, -222, -81, -130, -527, +69, -781, 194, -667, 198, -159, 98, 448, +-84, 831, -240, 861, -249, 486, -125, -214, +59, -869, 212, -1082, 232, -754, 133, -43, +-33, 726, -242, 1170, -354, 1031, -212, 355, +54, -537, 221, -1154, 268, -1169, 230, -647, +56, 168, -198, 956, -362, 1290, -356, 925, +-173, 107, 121, -718, 367, -1196, 418, -1087, +263, -422, -36, 407, -357, 998, -509, 1120, +-408, 685, -131, -89, 222, -770, 500, -1066, +497, -857, 204, -173, -164, 578, -434, 935, +-529, 831, -369, 395, -18, -261, 312, -812, +491, -903, 463, -530, 182, 102, -234, 708, +-516, 915, -536, 585, -321, -19, 54, -605, +417, -911, 547, -687, 376, -32, 11, 625, +-370, 972, -568, 841, -446, 150, -74, -741, +327, -1208, 532, -980, 405, -207, 26, 769, +-354, 1396, -527, 1260, -424, 441, -78, -680, +337, -1589, 550, -1678, 434, -780, 68, 570, +-363, 1667, -621, 1977, -532, 1236, -155, -227, +304, -1584, 624, -2180, 619, -1729, 268, -337, +-234, 1329, -643, 2346, -770, 2191, -502, 917, +52, -897, 573, -2272, 788, -2484, 617, -1499, +139, 235, -409, 1939, -756, 2686, -760, 2052, +-427, 418, 118, -1424, 598, -2585, 759, -2419, +563, -1040, 140, 764, -334, 2179, -685, 2567, +-751, 1666, -502, -51, -41, -1656, 444, -2436, +736, -2055, 710, -659, 372, 1009, -169, 2112, +-672, 2209, -858, 1266, -658, -294, -201, -1636, +357, -2141, 790, -1682, 822, -440, 426, 1045, +-148, 1956, -636, 1873, -831, 960, -631, -376, +-160, -1529, 333, -1888, 649, -1345, 648, -258, +337, 931, -89, 1692, -442, 1596, -606, 746, +-486, -361, -155, -1265, 162, -1580, 338, -1136, +387, -230, 292, 692, 59, 1325, -170, 1381, +-285, 746, -294, -192, -224, -940, -101, -1281, +18, -1105, 107, -410, 198, 452, 270, 1053, +232, 1204, 52, 842, -208, 95, -426, -652, +-474, -1074, -309, -1081, 22, -626, 396, 116, +603, 765, 468, 1084, 49, 999, -399, 464, +-649, -315, -575, -920, -185, -1139, 289, -946, +543, -322, 486, 537, 209, 1168, -175, 1256, +-479, 784, -497, -38, -250, -842, 56, -1291, +281, -1217, 357, -591, 229, 393, -17, 1214, +-205, 1421, -283, 985, -243, 154, -89, -752, +67, -1353, 143, -1359, 174, -749, 136, 220, +-6, 1108, -150, 1479, -213, 1173, -210, 353, +-122, -626, 32, -1317, 156, -1406, 241, -896, +255, 9, 77, 967, -241, 1499, -442, 1288, +-405, 481, -195, -486, 119, -1212, 422, -1420, +524, -997, 337, -94, -51, 892, -465, 1449, +-697, 1290, -584, 537, -147, -433, 385, -1213, +722, -1450, 673, -982, 265, 0, -252, 1009, +-644, 1504, -797, 1225, -595, 345, -38, -689, +529, -1396, 751, -1395, 610, -661, 222, 405, +-279, 1254, -642, 1476, -693, 918, -487, -149, +-103, -1083, 355, -1389, 654, -1023, 625, -204, +308, 731, -156, 1317, -550, 1222, -675, 501, +-532, -469, -213, -1173, 228, -1245, 616, -738, +667, 43, 343, 834, -113, 1301, -480, 1116, +-630, 349, -478, -580, -117, -1254, 220, -1331, +412, -739, 420, 177, 202, 1012, -124, 1467, +-313, 1238, -300, 316, -192, -777, -72, -1485, +19, -1513, 52, -811, 56, 312, 80, 1264, +117, 1639, 130, 1297, 67, 301, -99, -895, +-288, -1648, -366, -1607, -285, -829, -80, 323, +219, 1290, 469, 1656, 445, 1328, 150, 410, +-217, -752, -513, -1564, -611, -1595, -377, -930, +62, 64, 406, 992, 548, 1498, 466, 1375, +129, 692, -308, -287, -599, -1162, -628, -1514, +-355, -1196, 112, -446, 467, 423, 543, 1163, +421, 1492, 129, 1212, -306, 403, -646, -619, +-648, -1428, -309, -1633, 160, -1148, 510, -205, +600, 871, 407, 1680, -1, 1797, -435, 1093, +-666, -133, -590, -1366, -227, -2028, 257, -1765, +573, -717, 553, 619, 265, 1754, -126, 2206, +-437, 1648, -548, 278, -454, -1234, -182, -2179, +187, -2133, 451, -1154, 464, 281, 295, 1621, +22, 2330, -306, 1979, -547, 682, -573, -864, +-374, -1997, 17, -2293, 479, -1569, 744, -158, +616, 1256, 171, 2155, -392, 2195, -857, 1230, +-968, -321, -581, -1699, 150, -2328, 847, -1952, +1139, -720, 845, 788, 85, 1970, -771, 2382, +-1304, 1719, -1216, 202, -494, -1380, 498, -2282, +1236, -2191, 1358, -1147, 805, 399, -179, 1749, +-1119, 2332, -1513, 1899, -1151, 577, -250, -1015, +726, -2076, 1338, -2160, 1308, -1326, 611, 48, +-392, 1401, -1152, 2140, -1332, 1911, -944, 818, +-185, -642, 637, -1807, 1167, -2111, 1119, -1415, +517, -116, -257, 1170, -816, 1919, -1053, 1818, +-952, 856, -453, -542, 274, -1638, 861, -1842, +1049, -1138, 793, 9, 208, 1039, -493, 1541, +-1040, 1315, -1172, 466, -796, -563, -64, -1226, +750, -1193, 1276, -573, 1147, 210, 393, 748, +-512, 855, -1148, 567, -1307, 84, -885, -351, +-44, -567, 796, -477, 1248, -138, 1080, 177, +351, 244, -490, 145, -1002, 74, -1064, 62, +-724, 47, -116, 25, 502, -11, 875, -76, +845, -161, 414, -235, -169, -214, -598, -11, +-762, 285, -663, 444, -321, 348, 130, 40, +485, -312, 601, -495, 448, -421, 136, -175, +-175, 188, -395, 541, -486, 589, -427, 254, +-274, -192, -79, -499, 164, -565, 396, -326, +493, 83, 418, 417, 185, 545, -194, 401, +-611, 18, -852, -355, -738, -506, -252, -425, +398, -130, 891, 252, 1046, 461, 765, 404, +16, 197, -872, -93, -1366, -375, -1261, -444, +-646, -248, 330, 29, 1258, 239, 1596, 348, +1178, 299, 217, 87, -925, -136, -1735, -236, +-1780, -237, -999, -146, 277, 25, 1447, 132, +1929, 109, 1534, 82, 442, 86, -921, 48, +-1926, 0, -2056, -25, -1254, -68, 133, -108, +1474, -111, 2101, -102, 1747, -40, 616, 98, +-816, 216, -1915, 231, -2167, 144, -1453, -22, +-52, -174, 1393, -227, 2109, -233, 1797, -202, +731, -55, -641, 187, -1758, 380, -2075, 418, +-1456, 268, -207, -19, 1117, -319, 1861, -535, +1678, -586, 790, -361, -367, 140, -1383, 672, +-1794, 923, -1390, 704, -416, 76, 674, -641, +1443, -1052, 1538, -992, 933, -485, -46, 339, +-980, 1110, -1483, 1350, -1328, 879, -629, -62, +263, -1011, 1013, -1460, 1325, -1163, 1020, -314, +270, 661, -532, 1357, -1104, 1436, -1274, 809, +-919, -235, -169, -1193, 626, -1568, 1146, -1136, +1198, -179, 725, 761, -115, 1324, -979, 1341, +-1434, 764, -1207, -186, -426, -1035, 498, -1373, +1192, -1080, 1369, -338, 859, 488, -130, 1053, +-1038, 1159, -1401, 817, -1137, 173, -410, -533, +502, -1020, 1165, -1069, 1211, -675, 669, -56, +-122, 528, -829, 922, -1194, 1029, -1056, 738, +-462, 97, 346, -602, 993, -1056, 1136, -1133, +732, -778, 12, -65, -724, 740, -1159, 1317, +-1075, 1383, -520, 805, 267, -203, 962, -1154, +1179, -1645, 774, -1469, -3, -632, -756, 566, +-1153, 1618, -1022, 2014, -485, 1461, 209, 171, +846, -1212, 1153, -2067, 884, -2053, 132, -1140, +-694, 346, -1174, 1759, -1130, 2424, -653, 1977, +88, 601, 871, -1072, 1317, -2269, 1103, -2446, +287, -1547, -729, 15, -1418, 1615, -1403, 2560, +-746, 2346, 193, 1063, 1052, -686, 1459, -2149, +1150, -2650, 254, -1949, -785, -454, -1473, 1195, +-1464, 2418, -765, 2627, 237, 1606, 1071, -129, +1411, -1764, 1106, -2648, 282, -2373, -682, -1053, +-1356, 684, -1431, 2124, -852, 2701, 109, 2074, +985, 497, 1379, -1257, 1119, -2430, 333, -2540, +-607, -1525, -1270, 121, -1359, 1631, -825, 2423, +64, 2214, 873, 1060, 1245, -541, 1011, -1865, +272, -2350, -577, -1833, -1084, -603, -1060, 798, +-601, 1879, 57, 2236, 646, 1633, 920, 303, +726, -1111, 142, -2022, -450, -2104, -733, -1335, +-682, -14, -351, 1349, 99, 2165, 350, 2008, +342, 966, 281, -420, 123, -1601, -175, -2115, +-293, -1697, -161, -580, -83, 702, -111, 1709, +-134, 2007, -163, 1386, -78, 222, 180, -929, +334, -1692, 253, -1775, 83, -1121, -150, -61, +-401, 1029, -508, 1750, -423, 1685, -121, 858, +365, -247, 653, -1205, 455, -1695, 58, -1465, +-241, -613, -500, 488, -643, 1387, -459, 1652, +-45, 1156, 336, 209, 572, -752, 549, -1356, +191, -1364, -279, -809, -561, 35, -601, 826, +-437, 1231, -85, 1093, 327, 536, 581, -189, +539, -786, 161, -1014, -363, -845, -625, -413, +-492, 149, -211, 653, 71, 882, 333, 768, +403, 385, 189, -124, -105, -560, -289, -783, +-312, -764, -154, -464, 50, 63, 79, 572, +-26, 842, -81, 810, -74, 466, -31, -90, +78, -617, 140, -911, 47, -850, -98, -407, +-219, 219, -306, 725, -232, 943, 18, 775, +222, 261, 267, -333, 197, -775, 4, -948, +-237, -691, -349, -76, -308, 484, -169, 787, +39, 847, 207, 567, 250, 0, 208, -537, +71, -865, -167, -858, -369, -398, -407, 234, +-261, 642, 12, 798, 250, 716, 337, 298, +300, -292, 124, -748, -204, -855, -491, -530, +-519, 6, -298, 413, 41, 636, 341, 689, +440, 442, 312, -16, 64, -432, -225, -680, +-463, -643, -517, -295, -334, 112, 1, 415, +334, 638, 484, 648, 346, 329, 47, -147, +-219, -586, -412, -817, -504, -633, -375, -129, +-38, 369, 290, 730, 430, 864, 320, 558, +55, -91, -146, -669, -234, -916, -335, -761, +-376, -233, -210, 409, 26, 821, 173, 865, +284, 524, 320, -92, 190, -639, -8, -829, +-237, -667, -520, -244, -623, 306, -333, 718, +133, 771, 468, 472, 604, -24, 494, -494, +106, -721, -384, -635, -731, -295, -773, 173, +-430, 598, 145, 780, 582, 579, 688, 64, +518, -464, 113, -741, -387, -700, -703, -376, +-709, 120, -431, 589, 52, 840, 480, 712, +588, 185, 435, -435, 163, -796, -201, -815, +-504, -534, -557, -13, -403, 549, -144, 924, +151, 935, 337, 472, 361, -262, 310, -869, +163, -1124, -116, -925, -386, -253, -520, 582, +-506, 1186, -306, 1353, 69, 885, 444, -161, +645, -1181, 572, -1593, 180, -1294, -385, -391, +-806, 783, -871, 1624, -569, 1702, 9, 995, +624, -250, 943, -1433, 802, -1889, 257, -1449, +-469, -370, -1006, 917, -1052, 1791, -633, 1789, +29, 1005, 694, -202, 1048, -1387, 875, -1939, +275, -1527, -468, -452, -1020, 767, -1098, 1673, +-692, 1822, -32, 1129, 640, -13, 1050, -1137, +948, -1809, 390, -1623, -343, -665, -979, 508, +-1226, 1405, -883, 1708, -116, 1257, 673, 279, +1161, -773, 1115, -1511, 488, -1601, -417, -961, +-1132, 52, -1340, 977, -913, 1512, -3, 1440, +900, 784, 1282, -179, 999, -1136, 251, -1707, +-615, -1520, -1180, -623, -1168, 532, -609, 1492, +210, 1883, 874, 1487, 1021, 410, 635, -943, +23, -2009, -525, -2193, -829, -1295, -773, 236, +-400, 1653, 89, 2367, 474, 2084, 607, 828, +468, -909, 173, -2306, -158, -2658, -448, -1749, +-592, 34, -509, 1811, -241, 2711, 110, 2388, +419, 1023, 545, -868, 425, -2434, 139, -2842, +-223, -1890, -575, -71, -729, 1780, -526, 2769, +-74, 2418, 358, 1010, 618, -779, 649, -2255, +387, -2713, -107, -1843, -599, -131, -839, 1543, +-691, 2460, -234, 2218, 281, 975, 631, -595, +718, -1847, 503, -2321, 50, -1679, -448, -209, +-781, 1209, -796, 1950, -472, 1863, 34, 965, +498, -372, 760, -1446, 709, -1828, 349, -1416, +-195, -355, -734, 819, -996, 1505, -770, 1517, +-196, 913, 390, -84, 805, -987, 914, -1413, +575, -1256, -83, -532, -687, 444, -982, 1117, +-874, 1251, -393, 911, 225, 200, 684, -612, +857, -1133, 696, -1154, 212, -658, -383, 160, +-812, 856, -925, 1104, -681, 885, -172, 310, +385, -410, 815, -950, 946, -1057, 597, -654, +-92, 88, -694, 748, -980, 1002, -927, 808, +-490, 258, 184, -430, 746, -894, 967, -914, +775, -516, 214, 144, -421, 759, -834, 971, +-966, 675, -776, 60, -244, -555, 394, -869, +863, -764, 1039, -322, 763, 275, 50, 772, +-703, 879, -1136, 520, -1181, -86, -773, -605, +89, -806, 1002, -643, 1414, -218, 1126, 305, +329, 706, -631, 774, -1347, 488, -1483, -22, +-958, -532, -2, -780, 947, -648, 1451, -268, +1282, 201, 513, 639, -500, 828, -1263, 619, +-1445, 111, -1049, -476, -254, -861, 686, -816, +1342, -419, 1330, 121, 687, 682, -207, 1004, +-1004, 810, -1407, 215, -1187, -472, -439, -984, +450, -1013, 1107, -536, 1271, 103, 818, 695, +-13, 1102, -752, 965, -1131, 285, -1079, -466, +-578, -965, 165, -1061, 754, -643, 954, 34, +744, 605, 244, 971, -290, 963, -661, 442, +-844, -270, -728, -775, -256, -961, 271, -733, +570, -181, 669, 351, 570, 727, 210, 905, +-261, 670, -633, 56, -807, -527, -659, -819, +-202, -784, 295, -422, 629, 106, 735, 538, +546, 750, 100, 673, -405, 282, -792, -239, +-891, -592, -559, -635, 25, -417, 517, -86, +776, 201, 766, 378, 403, 438, -199, 361, +-722, 142, -929, -123, -749, -292, -237, -344, +357, -329, 733, -234, 777, -48, 512, 176, +30, 400, -469, 507, -765, 349, -756, 15, +-461, -267, 12, -468, 450, -566, 664, -420, +618, -55, 358, 346, -68, 664, -527, 729, +-793, 418, -726, -64, -373, -487, 127, -798, +579, -838, 783, -450, 654, 175, 247, 759, +-313, 1096, -792, 927, -918, 272, -647, -469, +-145, -1030, 422, -1265, 836, -911, 861, -38, +503, 859, -52, 1386, -631, 1331, -996, 635, +-910, -363, -434, -1188, 177, -1566, 724, -1263, +997, -290, 828, 823, 280, 1513, -412, 1579, +-972, 943, -1131, -174, -806, -1170, -155, -1623, +585, -1438, 1111, -598, 1135, 585, 638, 1464, +-164, 1642, -970, 1132, -1388, 154, -1145, -876, +-386, -1504, 502, -1520, 1202, -903, 1395, 162, +886, 1159, -87, 1581, -1006, 1315, -1463, 545, +-1270, -436, -502, -1234, 471, -1514, 1196, -1167, +1364, -311, 893, 703, -8, 1383, -889, 1426, +-1331, 890, -1166, 34, -513, -829, 305, -1361, +953, -1340, 1181, -768, 862, 151, 121, 1027, +-647, 1443, -1075, 1226, -1028, 524, -556, -366, +121, -1130, 687, -1471, 926, -1189, 761, -339, +238, 692, -397, 1391, -799, 1449, -800, 894, +-488, -16, -47, -919, 351, -1453, 578, -1358, +574, -629, 337, 382, -59, 1169, -422, 1406, +-563, 1049, -480, 279, -292, -566, -37, -1162, +278, -1292, 515, -866, 505, -52, 237, 737, +-149, 1172, -476, 1135, -590, 650, -438, -91, +-124, -779, 206, -1173, 451, -1115, 509, -548, +292, 280, -111, 936, -431, 1181, -474, 981, +-306, 388, -104, -387, 84, -1025, 259, -1265, +320, -960, 198, -197, -19, 658, -196, 1194, +-260, 1234, -216, 800, -125, 19, -40, -843, +50, -1382, 140, -1294, 156, -606, 64, 350, +-65, 1168, -129, 1489, -107, 1141, -54, 294, +-36, -685, -54, -1420, -52, -1565, -16, -961, +6, 123, 22, 1155, 78, 1663, 133, 1394, +70, 489, -108, -597, -258, -1453, -286, -1733, +-173, -1152, 42, 52, 250, 1180, 314, 1735, +187, 1524, -48, 560, -266, -678, -376, -1527, +-313, -1696, -63, -1121, 230, 66, 337, 1232, +218, 1730, 24, 1428, -164, 472, -312, -727, +-305, -1509, -118, -1546, 100, -958, 232, 88, +231, 1166, 75, 1624, -127, 1270, -226, 382, +-216, -677, -136, -1413, 19, -1435, 179, -829, +220, 125, 99, 1090, -116, 1535, -276, 1176, +-245, 273, -86, -729, 62, -1388, 188, -1351, +260, -673, 159, 288, -103, 1148, -344, 1477, +-403, 1017, -214, 55, 115, -872, 327, -1355, +318, -1177, 171, -438, -66, 470, -329, 1144, +-448, 1282, -317, 776, 18, -111, 373, -890, +471, -1183, 207, -881, -153, -205, -354, 461, +-395, 879, -288, 916, -19, 502, 297, -157, +453, -654, 328, -746, -31, -454, -380, -7, +-493, 303, -351, 401, -71, 350, 215, 132, +375, -156, 370, -272, 221, -158, -78, 68, +-414, 250, -531, 183, -339, -106, -31, -306, +213, -313, 356, -232, 378, 2, 235, 372, +-45, 609, -325, 549, -453, 184, -383, -387, +-164, -808, 98, -787, 290, -440, 355, 84, +296, 667, 132, 1004, -102, 880, -329, 352, +-456, -431, -389, -1097, -140, -1197, 149, -736, +368, -11, 469, 777, 375, 1312, 66, 1237, +-306, 579, -568, -370, -599, -1228, -329, -1533, +109, -1093, 448, -171, 578, 848, 479, 1563, +132, 1576, -308, 837, -581, -315, -595, -1387, +-380, -1847, -1, -1423, 356, -353, 529, 895, +506, 1821, 281, 1927, -105, 1108, -456, -221, +-614, -1481, -542, -2116, -239, -1780, 177, -642, +502, 789, 644, 1946, 536, 2267, 105, 1521, +-439, 100, -730, -1364, -671, -2288, -371, -2203, +73, -1111, 495, 456, 694, 1856, 586, 2501, +207, 2016, -286, 596, -629, -1081, -665, -2292, +-439, -2488, -78, -1564, 278, 13, 523, 1580, +587, 2515, 400, 2312, -22, 1023, -450, -674, +-612, -2020, -486, -2487, -234, -1833, 47, -392, +335, 1133, 531, 2163, 473, 2296, 167, 1384, +-185, -148, -417, -1530, -482, -2196, -387, -1929, +-181, -869, 83, 516, 354, 1676, 519, 2164, +435, 1713, 116, 490, -271, -922, -524, -1905, +-527, -2070, -341, -1368, -61, -105, 304, 1213, +600, 2058, 540, 2035, 145, 1089, -265, -384, +-490, -1685, -495, -2194, -296, -1731, 1, -585, +265, 807, 410, 1942, 338, 2235, 63, 1461, +-196, 18, -278, -1397, -214, -2165, -90, -1953, +3, -919, 31, 457, 55, 1674, 75, 2208, +25, 1713, -19, 428, 39, -1005, 93, -1975, +24, -2058, -122, -1228, -239, 76, -233, 1309, +-78, 2033, 101, 1872, 208, 829, 261, -561, +225, -1650, 25, -1998, -261, -1459, -440, -324, +-369, 861, -86, 1683, 200, 1828, 343, 1134, +370, -69, 275, -1149, 9, -1689, -329, -1529, +-526, -726, -462, 343, -171, 1208, 188, 1582, +431, 1309, 496, 448, 389, -586, 85, -1315, +-336, -1485, -653, -1029, -664, -121, -322, 800, +197, 1346, 587, 1339, 674, 744, 488, -211, +97, -1052, -392, -1380, -746, -1079, -730, -308, +-324, 566, 234, 1146, 615, 1203, 661, 720, +420, -88, 36, -820, -346, -1125, -604, -906, +-617, -305, -327, 398, 130, 884, 470, 948, +551, 603, 411, 24, 115, -534, -234, -826, +-494, -738, -575, -356, -404, 118, -4, 522, +400, 739, 575, 654, 480, 271, 191, -211, +-172, -575, -442, -715, -549, -591, -469, -224, +-151, 250, 270, 661, 519, 831, 505, 603, +322, 55, 31, -496, -281, -793, -495, -769, +-544, -437, -384, 107, -24, 657, 344, 946, +533, 764, 516, 152, 324, -519, -7, -871, +-376, -825, -640, -460, -651, 117, -333, 694, +163, 992, 553, 812, 691, 175, 565, -573, +182, -993, -351, -928, -781, -481, -836, 175, +-435, 797, 186, 1108, 665, 935, 801, 264, +574, -616, 75, -1168, -476, -1111, -814, -603, +-762, 121, -310, 838, 301, 1224, 694, 1065, +696, 412, 400, -466, -20, -1116, -411, -1191, +-650, -769, -632, -113, -303, 586, 190, 1079, +539, 1101, 594, 645, 436, -73, 140, -744, +-228, -1062, -537, -917, -668, -445, -510, 166, +-51, 720, 451, 993, 685, 844, 593, 323, +275, -317, -148, -759, -526, -869, -723, -674, +-614, -220, -158, 346, 401, 743, 697, 807, +643, 548, 355, 60, -66, -422, -476, -670, +-719, -673, -676, -454, -273, -24, 320, 424, +709, 657, 707, 632, 419, 370, -35, -49, +-496, -432, -730, -658, -631, -662, -240, -359, +293, 136, 650, 542, 618, 738, 318, 674, +-49, 284, -375, -266, -533, -692, -456, -858, +-213, -665, 104, -112, 357, 494, 405, 862, +289, 910, 121, 567, -90, -99, -301, -722, +-392, -995, -321, -858, -117, -335, 140, 362, +301, 867, 310, 983, 247, 711, 104, 132, +-138, -527, -336, -940, -353, -933, -221, -541, +-34, 62, 140, 630, 267, 931, 334, 850, +281, 416, 59, -197, -231, -729, -421, -954, +-414, -765, -224, -256, 50, 348, 304, 824, +469, 962, 443, 657, 162, 58, -229, -545, +-492, -931, -508, -922, -297, -479, 21, 184, +292, 761, 446, 1013, 438, 778, 236, 162, +-76, -477, -345, -883, -478, -927, -430, -524, +-209, 154, 85, 727, 344, 958, 497, 741, +459, 128, 214, -512, -155, -823, -499, -773, +-619, -411, -426, 184, -65, 708, 268, 862, +497, 599, 529, 28, 296, -545, -64, -767, +-347, -628, -462, -294, -389, 189, -171, 655, +84, 788, 268, 529, 327, 53, 275, -459, +155, -770, -18, -708, -218, -355, -337, 112, +-289, 570, -127, 839, 55, 734, 208, 263, +285, -353, 247, -810, 103, -897, -109, -606, +-286, -67, -305, 538, -168, 954, 12, 944, +162, 486, 243, -216, 218, -825, 89, -1038, +-89, -776, -228, -185, -248, 492, -144, 953, +12, 956, 145, 505, 202, -154, 161, -710, +56, -918, -59, -700, -144, -184, -156, 381, +-91, 735, -14, 728, 35, 404, 59, -46, +53, -431, 32, -614, 38, -537, 60, -258, +51, 105, -16, 412, -108, 532, -159, 437, +-139, 202, -69, -104, 33, -401, 152, -555, +226, -487, 190, -211, 40, 187, -137, 537, +-216, 655, -174, 479, -105, 92, -31, -354, +67, -683, 134, -728, 147, -427, 137, 99, +81, 583, -14, 795, -88, 659, -163, 235, +-236, -310, -203, -729, -31, -817, 191, -537, +354, -7, 334, 526, 111, 799, -153, 703, +-340, 309, -430, -210, -328, -634, 2, -749, +364, -504, 541, -43, 451, 408, 110, 641, +-312, 564, -574, 256, -579, -134, -339, -457, +99, -563, 550, -391, 762, -52, 604, 268, +120, 451, -463, 435, -822, 225, -789, -63, +-424, -310, 136, -444, 703, -385, 989, -127, +788, 189, 182, 400, -517, 435, -971, 287, +-979, 17, -552, -272, 124, -469, 770, -462, +1090, -210, 899, 148, 250, 413, -533, 490, +-1033, 363, -1027, 80, -567, -231, 131, -446, +767, -484, 1046, -290, 839, 52, 241, 329, +-470, 429, -922, 374, -907, 184, -519, -90, +42, -327, 588, -430, 889, -344, 785, -91, +326, 180, -274, 326, -730, 345, -824, 260, +-586, 73, -153, -158, 374, -346, 789, -398, +827, -245, 459, 23, -108, 227, -604, 334, +-793, 372, -630, 259, -243, -20, 249, -321, +666, -489, 752, -424, 459, -133, -6, 192, +-420, 392, -621, 473, -547, 401, -282, 104, +60, -294, 392, -556, 573, -553, 502, -289, +209, 103, -175, 410, -461, 534, -526, 491, +-417, 254, -185, -159, 175, -549, 526, -662, +632, -432, 431, -32, 36, 325, -372, 543, +-597, 569, -571, 355, -349, -41, 20, -433, +439, -613, 684, -485, 601, -147, 235, 203, +-237, 432, -589, 481, -668, 341, -488, 94, +-130, -164, 318, -376, 658, -431, 679, -277, +368, -54, -97, 121, -480, 275, -616, 375, +-496, 340, -217, 180, 139, -80, 460, -363, +588, -490, 445, -396, 107, -166, -259, 155, +-495, 472, -524, 579, -357, 419, -32, 94, +349, -318, 596, -638, 553, -638, 218, -331, +-236, 110, -560, 518, -609, 695, -386, 544, +30, 173, 467, -278, 681, -654, 548, -720, +132, -414, -365, 57, -662, 469, -613, 675, +-317, 582, 100, 243, 528, -175, 731, -525, +549, -654, 100, -480, -391, -102, -706, 300, +-678, 562, -341, 569, 121, 349, 552, 14, +772, -341, 614, -572, 131, -537, -413, -272, +-740, 87, -684, 420, -315, 571, 129, 462, +490, 185, 681, -155, 562, -458, 130, -556, +-356, -397, -616, -95, -570, 236, -295, 480, +63, 512, 376, 339, 558, 50, 509, -262, +194, -471, -234, -488, -541, -331, -591, -45, +-364, 280, 52, 492, 447, 507, 626, 328, +524, 1, 173, -340, -307, -539, -669, -533, +-682, -309, -337, 85, 161, 453, 554, 609, +681, 510, 512, 188, 115, -219, -350, -524, +-653, -622, -644, -458, -346, -56, 87, 373, +469, 604, 644, 568, 550, 274, 231, -155, +-193, -473, -542, -568, -655, -463, -476, -133, +-85, 312, 339, 573, 601, 527, 593, 266, +326, -97, -84, -407, -460, -520, -623, -435, +-485, -160, -126, 252, 261, 550, 504, 538, +517, 287, 301, -74, -46, -420, -365, -570, +-506, -462, -402, -162, -106, 266, 208, 622, +385, 642, 378, 318, 216, -145, -16, -547, +-222, -694, -341, -503, -315, -87, -122, 393, +107, 755, 221, 747, 232, 306, 198, -296, +102, -731, -50, -816, -194, -525, -265, 10, +-212, 572, -60, 915, 85, 826, 169, 303, +206, -392, 181, -905, 75, -994, -69, -625, +-185, 22, -220, 686, -150, 1091, -13, 995, +96, 402, 128, -379, 124, -1000, 127, -1194, +83, -841, -52, -98, -178, 691, -190, 1211, +-109, 1216, -12, 648, 69, -224, 139, -1008, +200, -1383, 180, -1146, 13, -376, -197, 561, +-281, 1288, -213, 1500, -61, 1011, 124, 14, +266, -984, 285, -1536, 171, -1427, -52, -689, +-295, 378, -375, 1320, -227, 1694, 22, 1261, +238, 227, 349, -871, 292, -1565, 90, -1586, +-152, -888, -340, 218, -367, 1219, -176, 1694, +87, 1393, 255, 416, 326, -725, 286, -1493, +85, -1607, -178, -1003, -339, 69, -340, 1075, +-184, 1596, 55, 1425, 242, 575, 337, -561, +330, -1384, 154, -1546, -148, -1036, -390, -83, +-435, 873, -265, 1422, 39, 1366, 304, 690, +425, -313, 392, -1109, 177, -1365, -168, -1076, +-449, -350, -500, 530, -295, 1146, 58, 1263, +345, 880, 427, 116, 352, -709, 170, -1204, +-116, -1177, -390, -669, -480, 125, -325, 861, +-9, 1218, 277, 1068, 401, 457, 378, -374, +233, -1036, -42, -1224, -333, -877, -464, -157, +-377, 618, -112, 1118, 203, 1123, 394, 615, +393, -162, 252, -835, 23, -1119, -224, -900, +-380, -269, -386, 457, -234, 933, 45, 971, +303, 566, 393, -90, 330, -671, 164, -904, +-87, -703, -325, -180, -416, 389, -323, 730, +-84, 717, 198, 370, 358, -148, 326, -560, +172, -671, -17, -462, -171, -42, -241, 372, +-216, 564, -115, 492, 20, 215, 101, -170, +111, -480, 118, -541, 131, -345, 107, -3, +40, 331, -66, 488, -192, 419, -250, 198, +-185, -113, -35, -401, 135, -487, 264, -339, +304, -77, 226, 204, 9, 404, -267, 418, +-412, 270, -345, 47, -135, -216, 139, -422, +382, -444, 472, -279, 357, -8, 48, 284, +-353, 470, -603, 463, -523, 275, -187, -64, +235, -435, 584, -599, 678, -466, 428, -144, +-53, 245, -549, 563, -805, 622, -631, 376, +-114, -44, 447, -474, 790, -690, 772, -540, +365, -150, -243, 257, -728, 572, -857, 660, +-571, 401, 8, -59, 589, -454, 863, -644, +714, -553, 235, -191, -341, 231, -751, 511, +-817, 592, -495, 433, 81, 49, 612, -358, +808, -574, 626, -537, 207, -274, -288, 89, +-688, 369, -776, 495, -481, 459, 30, 224, +499, -134, 743, -418, 671, -505, 311, -401, +-189, -163, -625, 123, -815, 383, -634, 534, +-113, 461, 473, 152, 817, -221, 791, -496, +430, -590, -138, -452, -680, -102, -930, 320, +-732, 629, -152, 665, 503, 386, 878, -81, +829, -521, 445, -749, -106, -650, -618, -248, +-868, 282, -725, 707, -243, 808, 340, 509, +733, -29, 780, -549, 519, -830, 82, -727, +-380, -281, -704, 289, -738, 745, -442, 864, +54, 532, 498, -62, 698, -579, 611, -821, +308, -717, -94, -287, -472, 282, -676, 732, +-580, 850, -214, 537, 216, -38, 521, -539, +607, -780, 456, -717, 134, -340, -232, 204, +-503, 651, -559, 814, -356, 606, -10, 98, +311, -442, 484, -760, 446, -758, 222, -430, +-58, 85, -282, 555, -393, 807, -357, 710, +-171, 245, 83, -321, 282, -686, 354, -768, +294, -556, 149, -80, -49, 423, -260, 724, +-392, 731, -357, 410, -153, -100, 139, -521, +389, -717, 480, -651, 365, -292, 85, 202, +-257, 563, -516, 688, -552, 540, -314, 134, +108, -315, 493, -597, 638, -654, 492, -434, +149, -8, -261, 381, -581, 587, -646, 563, +-405, 274, 28, -131, 450, -420, 662, -548, +570, -485, 242, -173, -173, 220, -517, 455, +-626, 494, -448, 347, -83, 52, 310, -247, +555, -451, 524, -508, 275, -338, -29, 5, +-296, 325, -451, 506, -400, 500, -173, 274, +100, -79, 299, -423, 347, -633, 256, -568, +109, -215, -47, 236, -192, 591, -247, 713, +-180, 500, -53, 41, 62, -442, 124, -768, +130, -779, 125, -405, 116, 172, 57, 664, +-35, 862, -99, 661, -118, 154, -117, -407, +-98, -795, -35, -857, 99, -519, 232, 61, +240, 589, 109, 843, -60, 718, -179, 271, +-219, -268, -179, -682, -61, -823, 118, -583, +268, -66, 271, 440, 123, 721, -60, 685, +-189, 341, -229, -137, -177, -524, -68, -692, +84, -557, 251, -166, 315, 261, 199, 542, +10, 586, -150, 356, -264, -23, -296, -334, +-189, -499, 25, -501, 266, -280, 424, 77, +371, 368, 124, 484, -166, 394, -372, 142, +-426, -129, -284, -349, 4, -488, 310, -426, +490, -148, 437, 171, 168, 398, -153, 487, +-373, 379, -426, 111, -287, -194, -22, -466, +240, -591, 398, -452, 390, -98, 197, 298, +-73, 590, -267, 649, -320, 428, -247, 30, +-85, -419, 113, -770, 266, -809, 298, -444, +195, 148, 43, 671, -87, 909, -170, 779, +-193, 308, -146, -359, -62, -936, 56, -1108, +186, -763, 245, -61, 210, 681, 109, 1130, +-34, 1084, -180, 567, -249, -224, -224, -969, +-105, -1305, 94, -1047, 273, -317, 318, 553, +240, 1180, 99, 1285, -78, 834, -236, 26, +-308, -816, -265, -1329, -113, -1260, 125, -630, +339, 264, 420, 1032, 331, 1350, 112, 1100, +-161, 384, -403, -523, -495, -1244, -340, -1425, +28, -959, 411, -79, 606, 811, 523, 1345, +205, 1309, -208, 690, -521, -260, -593, -1103, +-393, -1450, 20, -1146, 461, -337, 683, 601, +545, 1244, 148, 1334, -265, 842, -510, -21, +-537, -866, -336, -1314, 51, -1183, 443, -549, +607, 298, 469, 973, 129, 1201, -235, 934, +-444, 296, -434, -472, -249, -1045, 37, -1163, +333, -794, 484, -122, 396, 570, 134, 1015, +-150, 1053, -324, 668, -327, -6, -194, -698, +-7, -1102, 184, -1052, 315, -589, 317, 114, +178, 789, -20, 1151, -172, 1040, -221, 488, +-183, -299, -91, -1009, 38, -1317, 171, -1053, +254, -326, 237, 553, 126, 1218, -19, 1369, +-125, 909, -181, 17, -194, -917, -135, -1465, +21, -1349, 208, -619, 314, 374, 285, 1195, +151, 1492, -31, 1106, -226, 195, -347, -809, +-287, -1436, -46, -1402, 247, -733, 439, 240, +423, 1070, 215, 1411, -79, 1101, -346, 274, +-467, -649, -332, -1244, 33, -1281, 400, -750, +555, 103, 437, 853, 122, 1189, -245, 1010, +-486, 382, -484, -414, -221, -988, 196, -1108, +541, -763, 611, -106, 370, 565, -32, 953, +-392, 932, -539, 519, -434, -132, -125, -722, +272, -977, 583, -802, 627, -298, 364, 306, +-50, 761, -408, 886, -561, 616, -466, 50, +-168, -540, 226, -863, 565, -787, 671, -379, +471, 171, 64, 622, -341, 781, -568, 577, +-543, 104, -288, -407, 99, -714, 471, -685, +665, -351, 590, 119, 258, 495, -177, 624, +-510, 471, -605, 108, -452, -311, -101, -581, +336, -568, 659, -293, 705, 92, 450, 395, +3, 498, -440, 379, -659, 86, -568, -256, +-227, -467, 214, -446, 574, -226, 696, 73, +534, 306, 169, 376, -254, 275, -541, 56, +-576, -183, -374, -320, -25, -313, 356, -195, +619, -11, 653, 160, 438, 222, 52, 177, +-360, 96, -626, -11, -612, -137, -312, -216, +148, -211, 550, -144, 744, -33, 669, 87, +319, 174, -193, 205, -604, 152, -711, 5, +-502, -162, -98, -262, 340, -260, 670, -158, +769, 9, 577, 176, 137, 266, -354, 232, +-677, 83, -710, -114, -455, -266, 5, -302, +504, -208, 838, -31, 843, 147, 471, 252, +-110, 253, -618, 135, -830, -56, -678, -227, +-214, -294, 360, -237, 783, -97, 866, 70, +590, 218, 88, 287, -415, 212, -700, 18, +-661, -191, -328, -317, 133, -320, 534, -198, +720, 8, 627, 228, 289, 361, -146, 320, +-497, 114, -616, -148, -447, -349, -72, -417, +345, -321, 620, -89, 642, 188, 401, 393, +20, 425, -340, 257, -531, -38, -469, -323, +-178, -488, 199, -472, 492, -271, 586, 51, +448, 370, 169, 541, -135, 469, -378, 183, +-482, -189, -359, -498, -43, -636, 312, -535, +539, -190, 556, 278, 387, 639, 95, 706, +-249, 462, -518, 23, -537, -453, -267, -785, +159, -809, 519, -475, 650, 102, 514, 655, +203, 911, -164, 749, -465, 260, -536, -351, +-316, -849, 72, -1006, 404, -715, 538, -88, +447, 582, 217, 981, -44, 924, -250, 451, +-330, -210, -235, -788, -18, -1055, 196, -872, +313, -287, 307, 428, 214, 929, 86, 994, +-37, 621, -140, -11, -167, -643, -94, -1027, +42, -979, 169, -477, 244, 248, 240, 827, +152, 1017, 15, 768, -116, 181, -159, -503, +-96, -987, 49, -1044, 199, -627, 275, 90, +226, 753, 80, 1034, -76, 837, -157, 276, +-121, -417, -1, -943, 141, -1040, 231, -646, +227, 55, 132, 712, 10, 993, -82, 779, +-110, 221, -56, -408, 50, -860, 137, -927, +172, -546, 171, 98, 130, 659, 53, 856, +-29, 619, -73, 105, -69, -421, 4, -742, +121, -746, 215, -409, 228, 131, 152, 587, +18, 717, -106, 481, -153, 29, -86, -423, +87, -672, 266, -622, 332, -295, 230, 175, +31, 568, -161, 661, -241, 405, -160, -58, +47, -493, 281, -684, 406, -555, 345, -181, +125, 268, -124, 605, -288, 646, -287, 336, +-113, -154, 162, -550, 381, -673, 434, -498, +316, -124, 91, 293, -142, 580, -297, 590, +-295, 303, -120, -130, 164, -477, 386, -607, +436, -491, 315, -179, 104, 193, -119, 465, +-276, 533, -285, 371, -119, 35, 153, -321, +368, -538, 419, -538, 307, -335, 102, -5, +-122, 329, -263, 537, -255, 515, -87, 249, +167, -151, 379, -490, 430, -625, 282, -521, +29, -214, -193, 200, -275, 560, -203, 682, +-6, 478, 238, 37, 416, -427, 408, -720, +203, -731, -70, -442, -240, 52, -239, 548, +-120, 814, 60, 715, 259, 281, 396, -299, +364, -765, 178, -913, -53, -690, -212, -187, +-241, 408, -142, 859, 40, 947, 245, 595, +409, -44, 426, -670, 253, -1011, -38, -950, +-273, -511, -333, 153, -206, 789, 29, 1091, +293, 892, 489, 288, 499, -435, 279, -976, +-64, -1124, -330, -811, -397, -155, -251, 584, +23, 1076, 317, 1083, 526, 595, 553, -156, +350, -839, -9, -1161, -339, -995, -462, -418, +-327, 331, -30, 942, 303, 1130, 554, 784, +616, 78, 411, -641, 22, -1065, -340, -1038, +-474, -581, -346, 120, -51, 773, 279, 1075, +512, 859, 551, 237, 371, -471, 75, -952, +-202, -1035, -337, -685, -282, -31, -78, 650, +143, 1031, 303, 920, 395, 368, 391, -360, +254, -925, 29, -1084, -161, -770, -249, -114, +-215, 603, -85, 1044, 120, 986, 336, 444, +470, -318, 426, -926, 204, -1092, -83, -771, +-290, -132, -328, 555, -207, 986, 33, 942, +317, 425, 529, -294, 523, -844, 287, -979, +-42, -684, -291, -114, -369, 485, -258, 838, +-5, 778, 287, 343, 490, -247, 497, -706, +310, -813, 30, -551, -190, -69, -270, 415, +-216, 688, -75, 620, 120, 251, 308, -242, +400, -628, 360, -712, 227, -458, 64, -15, +-99, 407, -217, 637, -246, 561, -136, 199, +91, -276, 333, -634, 472, -703, 463, -446, +295, 0, 10, 425, -260, 658, -385, 597, +-313, 249, -68, -243, 275, -636, 544, -747, +594, -538, 407, -111, 90, 351, -224, 663, +-416, 692, -399, 411, -161, -71, 209, -536, +516, -779, 607, -699, 456, -337, 161, 160, +-155, 587, -365, 767, -382, 614, -189, 184, +135, -355, 430, -763, 550, -840, 451, -557, +216, -57, -53, 451, -263, 772, -338, 757, +-226, 398, 25, -156, 304, -660, 490, -874, +505, -697, 330, -244, 38, 279, -223, 683, +-347, 790, -285, 531, -64, 31, 244, -481, +489, -799, 539, -770, 364, -407, 73, 105, +-180, 547, -293, 751, -253, 624, -94, 215, +144, -296, 365, -701, 460, -805, 379, -544, +191, -61, -19, 406, -179, 689, -245, 678, +-186, 362, -6, -129, 234, -575, 424, -766, +458, -614, 311, -213, 58, 231, -162, 551, +-261, 628, -203, 428, -21, 49, 215, -340, +394, -582, 425, -572, 281, -336, 44, -10, +-136, 274, -191, 426, -133, 410, -1, 247, +189, -5, 346, -265, 377, -414, 259, -407, +65, -290, -110, -108, -195, 122, -156, 330, +-2, 419, 220, 343, 382, 116, 390, -175, +243, -417, 25, -524, -167, -455, -230, -190, +-134, 182, 66, 488, 279, 583, 399, 417, +355, 55, 175, -352, -18, -630, -141, -663, +-159, -414, -70, 27, 91, 459, 238, 670, +314, 559, 295, 182, 183, -267, 29, -590, +-88, -674, -110, -476, -53, -62, 52, 374, +163, 613, 261, 552, 291, 235, 212, -174, +58, -499, -61, -625, -86, -501, -37, -155, +46, 264, 144, 546, 243, 568, 284, 324, +220, -72, 81, -444, -37, -640, -90, -578, +-64, -261, 16, 183, 127, 545, 235, 655, +292, 454, 262, 25, 144, -428, 4, -693, +-99, -672, -115, -363, -53, 115, 54, 544, +171, 708, 274, 537, 320, 113, 282, -357, +162, -657, -7, -684, -153, -436, -210, -8, +-145, 409, 13, 621, 234, 552, 430, 244, +498, -163, 378, -496, 110, -624, -195, -512, +-372, -205, -319, 178, -94, 473, 190, 560, +437, 403, 570, 65, 501, -314, 244, -571, +-89, -605, -330, -394, -381, -11, -255, 380, +-11, 602, 289, 551, 552, 239, 639, -204, +483, -575, 125, -714, -268, -542, -508, -123, +-473, 358, -190, 676, 229, 691, 613, 378, +775, -142, 611, -627, 180, -843, -300, -685, +-586, -228, -533, 342, -193, 767, 255, 849, +613, 531, 739, -61, 576, -665, 198, -983, +-224, -858, -490, -356, -477, 299, -216, 825, +155, 979, 476, 675, 637, 51, 565, -618, +296, -1025, -61, -965, -344, -475, -429, 196, +-283, 748, 11, 960, 326, 739, 542, 177, +558, -473, 380, -914, 95, -942, -175, -542, +-342, 67, -325, 594, -132, 838, 138, 717, +369, 269, 494, -317, 464, -759, 276, -846, +19, -548, -195, -23, -291, 470, -253, 716, +-79, 634, 173, 259, 399, -247, 488, -650, +415, -746, 230, -491, -6, -23, -213, 422, +-323, 641, -272, 559, -59, 214, 244, -241, +483, -598, 551, -682, 424, -456, 170, -26, +-124, 393, -352, 607, -402, 539, -225, 227, +106, -199, 423, -565, 589, -690, 536, -498, +298, -75, -27, 362, -292, 616, -402, 591, +-319, 296, -57, -162, 292, -578, 564, -742, +617, -557, 434, -113, 100, 361, -225, 651, +-428, 634, -427, 319, -193, -163, 208, -579, +567, -726, 681, -539, 503, -111, 148, 343, +-209, 600, -422, 566, -414, 282, -194, -121, +164, -470, 491, -623, 620, -515, 489, -189, +191, 203, -118, 463, -304, 505, -324, 361, +-202, 79, 33, -261, 304, -529, 494, -597, +494, -427, 315, -73, 53, 304, -172, 555, +-286, 603, -261, 405, -108, -9, 140, -468, +390, -761, 498, -757, 406, -425, 179, 119, +-53, 627, -217, 873, -263, 748, -178, 273, +18, -370, 250, -898, 417, -1060, 434, -760, +299, -101, 97, 614, -97, 1048, -224, 1028, +-242, 551, -119, -204, 93, -907, 310, -1220, +428, -1006, 395, -349, 235, 460, 30, 1054, +-138, 1176, -225, 784, -196, 35, -57, -752, +142, -1215, 313, -1158, 393, -610, 360, 200, +241, 918, 52, 1223, -155, 984, -290, 310, +-269, -509, -81, -1129, 191, -1276, 435, -861, +540, -63, 452, 759, 181, 1232, -161, 1149, +-406, 544, -427, -312, -211, -1052, 151, -1340, +489, -1022, 635, -233, 534, 644, 234, 1205, +-140, 1210, -427, 655, -478, -202, -277, -972, +86, -1307, 446, -1050, 649, -316, 605, 537, +334, 1111, -56, 1165, -406, 683, -552, -108, +-419, -831, -47, -1176, 407, -1015, 733, -404, +758, 373, 481, 936, 19, 1050, -446, 700, +-702, 48, -591, -616, -145, -997, 419, -955, +835, -502, 897, 169, 577, 730, 26, 925, +-492, 714, -765, 193, -663, -416, -206, -838, +410, -883, 866, -546, 928, 20, 608, 551, +75, 792, -448, 659, -753, 240, -689, -273, +-271, -650, 324, -722, 802, -481, 931, -55, +666, 356, 160, 566, -369, 494, -703, 209, +-688, -136, -340, -398, 198, -474, 695, -357, +910, -116, 717, 140, 246, 303, -264, 308, +-607, 183, -662, 5, -410, -161, 56, -265, +547, -268, 836, -170, 756, -24, 371, 110, +-108, 181, -477, 171, -630, 89, -505, -21, +-128, -123, 361, -189, 745, -190, 815, -125, +535, -22, 78, 71, -344, 132, -603, 139, +-599, 97, -297, 18, 190, -92, 625, -201, +808, -242, 655, -182, 256, -48, -194, 103, +-512, 220, -582, 253, -394, 170, -10, -14, +419, -241, 708, -389, 696, -364, 408, -168, +11, 104, -327, 333, -504, 413, -457, 306, +-184, 38, 206, -292, 540, -518, 647, -504, +495, -253, 189, 103, -121, 405, -347, 518, +-424, 395, -305, 93, -16, -278, 316, -555, +528, -585, 531, -340, 356, 48, 91, 394, +-193, 553, -386, 472, -390, 184, -179, -206, +151, -536, 443, -632, 556, -439, 448, -61, +190, 325, -106, 555, -323, 541, -382, 293, +-245, -97, 46, -472, 354, -652, 503, -536, +445, -187, 250, 222, 16, 512, -204, 575, +-334, 398, -291, 40, -76, -362, 210, -620, +413, -600, 454, -311, 340, 92, 129, 433, +-117, 580, -300, 484, -323, 170, -154, -250, +127, -581, 368, -645, 449, -412, 348, -9, +139, 376, -87, 578, -238, 518, -249, 225, +-105, -187, 113, -544, 290, -649, 338, -438, +250, -33, 98, 358, -36, 557, -102, 489, +-101, 195, -32, -192, 77, -515, 165, -610, +185, -401, 156, 8, 104, 386, 46, 553, +1, 453, -24, 149, -25, -227, 5, -525, +73, -603, 142, -395, 179, 14, 163, 407, +101, 591, 4, 498, -79, 184, -100, -222, +-35, -555, 93, -673, 215, -501, 271, -89, +225, 376, 99, 665, -58, 642, -165, 336, +-176, -122, -73, -554, 101, -779, 261, -674, +336, -261, 299, 284, 158, 708, -45, 802, +-212, 536, -279, 39, -207, -489, 5, -845, +272, -845, 445, -461, 453, 138, 289, 673, +1, 902, -288, 722, -425, 225, -338, -379, +-58, -843, 302, -957, 546, -648, 556, -36, +338, 586, 0, 926, -306, 840, -438, 385, +-352, -236, -92, -764, 250, -971, 510, -755, +550, -202, 368, 429, 69, 839, -228, 853, +-402, 501, -379, -43, -164, -566, 158, -859, +456, -785, 572, -381, 435, 167, 125, 617, +-204, 783, -403, 619, -400, 210, -193, -278, +130, -667, 433, -789, 557, -586, 444, -144, +155, 346, -167, 676, -376, 714, -382, 459, +-205, 20, 66, -438, 347, -734, 511, -732, +463, -420, 220, 56, -82, 490, -306, 709, +-364, 639, -250, 313, -15, -157, 249, -585, +429, -781, 438, -656, 274, -267, 32, 234, +-182, 640, -287, 789, -258, 609, -109, 149, +91, -412, 260, -814, 346, -877, 328, -568, +209, 3, 23, 593, -152, 925, -257, 840, +-253, 372, -125, -291, 94, -848, 296, -1032, +401, -756, 374, -145, 212, 530, -44, 960, +-274, 949, -359, 508, -265, -163, -28, -766, +234, -1030, 415, -836, 449, -288, 324, 361, +69, 830, -206, 934, -381, 635, -367, 64, +-154, -531, 144, -897, 374, -883, 461, -500, +403, 86, 191, 616, -105, 881, -338, 772, +-383, 329, -235, -268, 22, -754, 264, -926, +410, -709, 429, -179, 297, 429, 56, 837, +-195, 877, -346, 546, -333, -34, -148, -619, +107, -950, 332, -870, 465, -411, 447, 225, +244, 754, -68, 956, -339, 749, -444, 202, +-317, -451, -16, -922, 308, -997, 512, -640, +533, -1, 340, 625, 0, 976, -323, 906, +-470, 430, -376, -242, -92, -803, 247, -1026, +476, -815, 517, -241, 364, 424, 79, 882, +-222, 952, -390, 617, -357, 11, -156, -601, +122, -956, 352, -912, 436, -476, 356, 161, +176, 700, -37, 926, -217, 771, -293, 273, +-228, -359, -71, -828, 116, -943, 279, -666, +361, -101, 323, 497, 188, 859, -4, 846, +-199, 466, -305, -127, -271, -662, -101, -903, +122, -764, 312, -300, 391, 288, 341, 730, +177, 840, -56, 589, -258, 82, -337, -461, +-273, -795, -102, -788, 137, -447, 356, 79, +455, 557, 384, 771, 171, 646, -117, 242, +-365, -270, -454, -657, -330, -745, -36, -512, +310, -75, 551, 379, 563, 648, 336, 619, +-35, 316, -377, -112, -543, -476, -451, -621, +-143, -496, 248, -167, 557, 212, 641, 474, +451, 507, 70, 314, -320, 1, -555, -298, +-535, -461, -261, -423, 164, -204, 549, 84, +710, 309, 554, 384, 148, 286, -293, 64, +-558, -179, -554, -345, -293, -371, 121, -226, +504, 19, 672, 233, 539, 331, 179, 292, +-221, 118, -470, -124, -487, -305, -286, -351, +51, -257, 382, -43, 562, 195, 496, 318, +218, 287, -123, 148, -352, -52, -387, -239, +-241, -319, 14, -271, 271, -121, 416, 78, +385, 233, 189, 271, -70, 212, -236, 95, +-243, -84, -129, -257, 31, -323, 174, -254, +245, -96, 231, 109, 131, 278, -23, 329, +-122, 251, -110, 58, -33, -206, 48, -411, +117, -423, 143, -246, 116, 38, 56, 326, +-33, 486, -98, 423, -66, 165, 42, -196, +128, -516, 144, -614, 105, -411, 31, -10, +-49, 393, -97, 635, -86, 596, -3, 273, +108, -203, 170, -611, 141, -751, 64, -541, +-11, -70, -65, 434, -85, 731, -73, 697, +-27, 355, 42, -167, 121, -639, 170, -821, +155, -619, 84, -141, -6, 400, -102, 761, +-178, 765, -156, 414, -20, -126, 150, -626, +269, -858, 283, -695, 171, -204, -19, 376, +-196, 782, -276, 832, -220, 499, -35, -61, +192, -597, 342, -878, 348, -774, 205, -320, +-13, 274, -203, 726, -292, 853, -251, 619, +-80, 125, 159, -432, 343, -806, 385, -838, +272, -523, 57, 9, -165, 536, -306, 827, +-308, 768, -151, 403, 109, -138, 339, -641, +425, -874, 332, -731, 109, -298, -126, 253, +-281, 702, -309, 844, -186, 629, 54, 166, +280, -372, 374, -771, 324, -838, 157, -551, +-49, -50, -194, 458, -227, 771, -159, 756, +-13, 430, 151, -78, 238, -562, 225, -805, +145, -702, 36, -301, -51, 225, -83, 645, +-87, 778, -64, 584, 1, 133, 71, -392, +108, -748, 129, -766, 130, -453, 91, 58, +27, 548, -44, 786, -104, 675, -123, 274, +-57, -263, 59, -705, 153, -823, 176, -577, +132, -89, 51, 439, -51, 770, -123, 756, +-115, 421, -39, -84, 54, -564, 117, -806, +124, -697, 72, -311, 14, 185, -15, 597, +-37, 751, -48, 601, -26, 232, 20, -221, +56, -598, 65, -742, 47, -589, 14, -215, +-11, 228, -25, 578, -16, 712, 22, 579, +72, 218, 79, -240, 32, -614, -32, -757, +-83, -604, -71, -208, 18, 267, 126, 648, +167, 793, 117, 621, 20, 165, -83, -379, +-156, -781, -136, -873, -3, -593, 162, -43, +246, 534, 207, 893, 78, 879, -73, 465, +-169, -181, -176, -756, -91, -996, 59, -793, +210, -231, 269, 426, 209, 886, 72, 960, +-84, 601, -179, -41, -173, -660, -87, -965, +47, -837, 197, -347, 286, 279, 241, 764, +87, 904, -72, 642, -159, 94, -159, -479, +-98, -815, 11, -780, 140, -406, 227, 117, +224, 553, 133, 732, 19, 599, -77, 206, +-132, -254, -139, -569, -76, -624, 44, -414, +158, -50, 214, 285, 196, 468, 103, 474, +-39, 303, -131, 2, -128, -279, -84, -410, +-16, -391, 87, -246, 172, -16, 171, 204, +97, 340, 8, 367, -61, 252, -90, 21, +-88, -202, -62, -337, 6, -366, 96, -267, +141, -55, 110, 180, 49, 354, -16, 402, +-70, 270, -86, 14, -66, -232, -26, -391, +31, -420, 103, -279, 121, -6, 65, 272, +4, 441, -29, 430, -63, 223, -97, -76, +-84, -328, -17, -463, 67, -431, 129, -203, +128, 135, 73, 412, 8, 504, -63, 381, +-134, 95, -152, -237, -73, -471, 47, -514, +149, -340, 196, -2, 162, 349, 69, 528, +-42, 452, -135, 186, -193, -141, -165, -401, +-43, -494, 113, -368, 225, -80, 247, 232, +188, 423, 71, 406, -70, 212, -197, -42, +-249, -246, -165, -354, 18, -335, 193, -181, +282, 51, 281, 250, 203, 326, 39, 266, +-150, 127, -268, -39, -253, -201, -114, -310, +87, -302, 255, -159, 309, 52, 273, 223, +165, 291, -17, 266, -204, 167, -274, 0, +-197, -194, -44, -331, 128, -342, 255, -207, +296, 16, 251, 214, 110, 331, -90, 357, +-237, 246, -237, -6, -127, -276, 18, -420, +160, -382, 247, -177, 246, 95, 149, 296, +-7, 373, -147, 320, -194, 120, -129, -150, +-29, -320, 60, -312, 128, -184, 166, -16, +134, 124, 45, 188, -38, 174, -92, 116, +-110, 31, -88, -57, -40, -95, 19, -84, +90, -77, 154, -95, 144, -90, 44, -25, +-86, 78, -181, 161, -180, 189, -84, 151, +45, 53, 154, -93, 207, -244, 140, -316, +-44, -239, -195, -29, -216, 210, -120, 368, +24, 382, 141, 243, 167, -28, 105, -340, +11, -533, -89, -487, -143, -198, -109, 207, +-25, 539, 46, 640, 74, 460, 66, 63, +38, -402, 21, -721, 4, -705, -39, -347, +-69, 175, -56, 621, -13, 788, 35, 600, +74, 153, 89, -355, 70, -728, 16, -786, +-62, -471, -92, 49, -43, 509, 36, 743, +94, 666, 112, 301, 86, -177, 15, -566, +-48, -730, -63, -572, -35, -139, 15, 318, +63, 590, 101, 617, 109, 402, 77, 10, +27, -371, -14, -568, -44, -524, -73, -258, +-60, 111, 24, 391, 128, 469, 184, 371, +161, 147, 85, -130, -28, -351, -136, -424, +-168, -321, -92, -89, 54, 159, 173, 322, +208, 366, 147, 289, 37, 105, -65, -147, +-117, -361, -93, -422, -31, -300, 27, -64, +69, 186, 91, 371, 84, 423, 61, 312, +45, 71, 1, -217, -79, -435, -133, -465, +-128, -300, -50, -34, 74, 241, 173, 450, +176, 497, 98, 350, -25, 62, -170, -289, +-238, -551, -176, -572, -38, -358, 97, -24, +199, 349, 218, 627, 129, 642, -2, 364, +-143, -78, -261, -515, -268, -750, -149, -644, +28, -259, 200, 220, 302, 623, 243, 783, +59, 589, -130, 136, -276, -374, -325, -734, +-225, -778, -29, -476, 143, 15, 238, 486, +253, 770, 182, 736, 64, 381, -88, -145, +-248, -615, -340, -825, -306, -675, -133, -237, +125, 287, 371, 698, 472, 833, 360, 605, +67, 102, -292, -440, -531, -791, -515, -809, +-242, -479, 147, 56, 461, 560, 563, 827, +415, 751, 110, 344, -220, -225, -432, -686, +-451, -838, -295, -633, -25, -163, 258, 372, +455, 746, 481, 793, 333, 496, 51, -20, +-280, -517, -500, -765, -488, -674, -237, -318, +145, 150, 486, 553, 614, 722, 443, 580, +79, 194, -296, -257, -512, -574, -474, -647, +-207, -486, 148, -150, 403, 267, 469, 593, +340, 669, 92, 470, -160, 80, -334, -349, +-366, -628, -252, -655, -27, -442, 196, -41, +337, 425, 371, 720, 255, 686, 6, 362, +-262, -110, -408, -527, -379, -710, -189, -615, +93, -294, 327, 179, 418, 607, 325, 741, +90, 539, -189, 142, -393, -290, -434, -594, +-311, -648, -67, -461, 206, -101, 401, 332, +446, 618, 294, 587, -12, 325, -362, -16, +-584, -333, -555, -511, -268, -473, 151, -272, +507, 25, 640, 333, 460, 470, 36, 364, +-421, 150, -686, -59, -640, -249, -316, -354, +140, -311, 514, -147, 639, 72, 473, 256, +101, 306, -298, 213, -578, 74, -629, -66, +-407, -201, -3, -275, 393, -221, 604, -59, +566, 122, 283, 231, -139, 233, -528, 153, +-696, 30, -528, -107, -108, -222, 356, -254, +658, -168, 671, -3, 366, 144, -123, 218, +-533, 228, -688, 170, -520, 34, -93, -131, +370, -259, 640, -296, 610, -203, 318, -16, +-107, 162, -449, 272, -560, 311, -435, 229, +-113, 19, 274, -202, 515, -320, 498, -318, +292, -186, -8, 27, -304, 202, -444, 295, +-380, 308, -160, 188, 130, -45, 359, -230, +409, -286, 290, -259, 93, -147, -135, 49, +-308, 217, -341, 288, -241, 259, -53, 102, +160, -123, 318, -259, 332, -258, 214, -182, +33, -40, -170, 145, -330, 263, -371, 249, +-233, 127, 21, -60, 252, -215, 361, -242, +314, -169, 132, -61, -133, 77, -351, 211, +-409, 241, -276, 150, -19, 0, 210, -143, +308, -209, 253, -174, 87, -89, -115, 6, +-262, 111, -287, 183, -208, 171, -70, 91, +77, -5, 163, -81, 159, -120, 95, -146, +20, -159, -85, -117, -202, 5, -254, 160, +-201, 264, -64, 264, 100, 156, 228, -26, +240, -238, 134, -392, -55, -379, -274, -170, +-384, 144, -285, 408, -42, 491, 202, 346, +344, 47, 309, -264, 94, -474, -154, -496, +-316, -293, -346, 53, -220, 374, 16, 519, +217, 434, 275, 173, 218, -147, 79, -392, +-78, -472, -171, -360, -210, -99, -195, 213, +-98, 426, 59, 437, 167, 260, 206, -7, +205, -262, 128, -411, -18, -386, -172, -202, +-256, 62, -228, 310, -93, 429, 89, 352, +231, 128, 290, -140, 236, -362, 83, -442, +-111, -324, -270, -67, -306, 230, -198, 450, +-6, 460, 183, 257, 314, -40, 318, -317, +178, -483, -32, -430, -257, -179, -393, 132, +-327, 389, -92, 494, 173, 373, 358, 96, +399, -195, 244, -420, -46, -490, -331, -321, +-479, -1, -384, 299, -80, 471, 241, 440, +408, 196, 387, -127, 185, -376, -131, -468, +-384, -344, -448, -39, -311, 271, -36, 426, +233, 373, 343, 151, 261, -116, 82, -292, +-110, -341, -258, -251, -316, -41, -258, 172, +-98, 268, 80, 238, 189, 127, 194, -9, +129, -119, 31, -186, -111, -205, -246, -145, +-294, -10, -208, 119, -43, 192, 110, 202, +193, 136, 176, 20, 79, -106, -67, -223, +-200, -256, -249, -135, -199, 61, -67, 213, +69, 268, 145, 196, 136, 16, 73, -164, +-10, -267, -95, -265, -160, -102, -180, 169, +-119, 332, -7, 288, 87, 110, 122, -125, +112, -310, 80, -321, -18, -168, -148, 50, +-202, 271, -145, 378, -23, 251, 102, -19, +189, -235, 178, -323, 71, -266, -69, -80, +-188, 117, -219, 243, -135, 286, 29, 199, +182, -8, 238, -191, 165, -251, 14, -213, +-118, -102, -203, 52, -211, 182, -100, 240, +87, 208, 226, 68, 226, -122, 108, -241, +-51, -237, -163, -147, -190, -7, -141, 146, +-22, 258, 99, 276, 141, 164, 102, -40, +34, -228, -32, -315, -70, -286, -51, -143, +-43, 85, -74, 308, -82, 418, -39, 335, +29, 65, 75, -245, 84, -424, 43, -417, +-26, -227, -103, 84, -173, 363, -153, 459, +-40, 343, 67, 71, 101, -232, 76, -394, +8, -344, -69, -174, -102, 23, -117, 215, +-115, 308, -72, 242, -8, 87, 40, -71, +54, -181, 46, -194, 2, -127, -58, -45, +-130, 46, -198, 137, -177, 154, -58, 69, +92, -38, 176, -103, 150, -106, 38, -41, +-108, 43, -222, 81, -272, 84, -205, 55, +-41, -39, 107, -140, 174, -140, 155, -50, +71, 40, -36, 117, -115, 165, -174, 144, +-200, 79, -152, -9, -67, -145, 20, -260, +104, -249, 162, -127, 153, 32, 77, 208, +-46, 356, -186, 362, -260, 202, -231, -47, +-117, -309, 36, -471, 176, -411, 258, -173, +240, 120, 131, 386, -51, 522, -263, 435, +-368, 154, -306, -206, -124, -509, 116, -602, +333, -413, 426, -58, 313, 314, 32, 603, +-276, 666, -448, 409, -397, -44, -174, -474, +87, -722, 281, -670, 359, -315, 276, 167, +96, 582, -82, 789, -238, 673, -311, 253, +-268, -270, -156, -696, -19, -875, 160, -681, +319, -175, 322, 410, 173, 859, -58, 992, +-274, 701, -375, 79, -315, -600, -147, -1051, +30, -1073, 189, -629, 271, 95, 241, 785, +135, 1165, -22, 1063, -196, 500, -334, -267, +-374, -923, -298, -1209, -80, -987, 218, -347, +432, 427, 429, 1036, 182, 1238, -186, 920, +-482, 212, -567, -586, -429, -1158, -115, -1256, +256, -807, 477, -22, 450, 754, 214, 1223, +-103, 1184, -372, 656, -517, -114, -493, -825, +-293, -1209, 45, -1094, 369, -543, 511, 209, +437, 881, 144, 1207, -277, 1031, -574, 451, +-617, -278, -443, -921, -76, -1228, 347, -1013, +565, -392, 498, 358, 246, 992, -107, 1244, +-433, 975, -576, 339, -520, -396, -313, -992, +45, -1214, 417, -954, 572, -342, 489, 388, +235, 999, -161, 1244, -548, 994, -697, 376, +-551, -386, -200, -1046, 253, -1334, 598, -1078, +655, -364, 432, 524, 51, 1214, -341, 1411, +-622, 1039, -662, 259, -438, -629, -38, -1288, +401, -1438, 664, -1010, 611, -165, 282, 751, +-134, 1342, -494, 1392, -658, 921, -513, 83, +-146, -799, 221, -1344, 438, -1349, 459, -810, +270, 70, -2, 909, -207, 1332, -334, 1223, +-372, 667, -272, -154, -51, -926, 143, -1290, +244, -1128, 274, -548, 172, 252, -29, 942, +-209, 1223, -310, 1046, -287, 500, -116, -264, +97, -934, 183, -1196, 134, -972, 45, -390, +-71, 334, -181, 914, -175, 1111, -82, 885, +-17, 335, 33, -337, 70, -861, 21, -1038, +-59, -833, -81, -336, -102, 277, -149, 798, +-135, 1032, -50, 900, 42, 449, 123, -195, +139, -802, 17, -1113, -157, -994, -251, -499, +-259, 192, -212, 842, -43, 1184, 177, 1028, +262, 467, 184, -235, 8, -848, -193, -1132, +-334, -954, -327, -417, -215, 258, -68, 829, +135, 1060, 306, 880, 308, 395, 133, -222, +-100, -778, -316, -1029, -473, -856, -436, -388, +-159, 197, 191, 728, 424, 983, 471, 855, +263, 445, -124, -112, -455, -663, -582, -974, +-460, -892, -133, -486, 249, 93, 465, 675, +433, 1012, 255, 952, -64, 538, -388, -100, +-491, -752, -402, -1116, -242, -1007, 44, -476, +356, 252, 448, 894, 330, 1185, 111, 974, +-205, 358, -478, -381, -502, -960, -309, -1121, +-30, -783, 269, -169, 442, 435, 349, 842, +96, 914, -131, 603, -287, 77, -339, -395, +-254, -669, -123, -683, -13, -423, 106, -43, +206, 276, 212, 496, 122, 545, -3, 353, +-144, 72, -294, -137, -346, -302, -230, -407, +-34, -354, 138, -210, 238, -46, 228, 189, +106, 407, -44, 441, -178, 345, -303, 170, +-314, -137, -197, -448, -51, -553, 93, -437, +216, -159, 232, 235, 72, 546, -128, 573, +-245, 383, -289, 99, -224, -266, -26, -542, +105, -545, 74, -343, 22, -39, -38, 293, +-114, 500, -121, 486, -58, 313, -29, 59, +-62, -219, -70, -407, -83, -410, -92, -270, +-24, -65, 37, 143, -21, 267, -112, 279, +-131, 228, -110, 140, -28, 23, 86, -93, +87, -184, -21, -248, -130, -267, -199, -178, +-219, 12, -131, 213, 27, 347, 115, 382, +91, 276, 27, 15, -52, -280, -134, -448, +-116, -448, -55, -302, -62, -4, -90, 306, +-63, 486, -27, 526, -32, 398, -28, 72, +6, -304, 13, -549, -11, -606, -23, -459, +-44, -127, -92, 270, -124, 567, -111, 707, +-89, 621, -28, 248, 95, -245, 136, -640, +66, -847, -35, -757, -179, -321, -292, 266, +-240, 750, -70, 988, 64, 875, 155, 370, +208, -299, 109, -809, -70, -1009, -152, -864, +-216, -386, -277, 260, -164, 793, 3, 1018, +58, 880, 108, 417, 145, -212, 49, -732, +-120, -976, -195, -902, -209, -482, -181, 169, +-59, 750, 77, 1039, 137, 966, 113, 522, +21, -158, -158, -779, -310, -1080, -288, -1015, +-146, -563, 12, 178, 159, 836, 244, 1137, +158, 1066, -73, 595, -280, -174, -383, -852, +-367, -1162, -193, -1080, 77, -595, 249, 193, +294, 896, 228, 1206, 8, 1100, -270, 594, +-436, -190, -456, -869, -364, -1184, -111, -1118, +198, -647, 347, 121, 347, 843, 225, 1225, +-63, 1197, -378, 748, -505, -12, -440, -754, +-265, -1201, -4, -1257, 240, -862, 290, -107, +206, 699, 119, 1244, -66, 1329, -280, 927, +-366, 181, -366, -650, -304, -1242, -101, -1369, +155, -993, 302, -203, 328, 708, 204, 1339, +-102, 1467, -404, 1054, -464, 214, -336, -763, +-165, -1446, 51, -1575, 219, -1132, 206, -200, +78, 912, -9, 1643, -52, 1699, -100, 1143, +-164, 107, -263, -1041, -307, -1736, -222, -1711, +-37, -1061, 164, 30, 286, 1155, 287, 1772, +101, 1680, -182, 996, -360, -107, -377, -1196, +-309, -1754, -186, -1656, 2, -974, 165, 145, +243, 1253, 245, 1821, 182, 1685, -13, 944, +-298, -174, -507, -1229, -527, -1766, -344, -1661, +-4, -968, 361, 157, 507, 1231, 385, 1777, +120, 1663, -258, 952, -562, -141, -593, -1193, +-432, -1793, -177, -1701, 141, -944, 399, 192, +473, 1278, 362, 1872, 94, 1722, -301, 899, +-645, -253, -722, -1320, -550, -1894, -166, -1713, +347, -857, 665, 305, 615, 1361, 304, 1881, +-160, 1624, -611, 798, -792, -257, -660, -1259, +-363, -1796, 41, -1563, 429, -749, 634, 281, +570, 1227, 276, 1701, -179, 1448, -668, 697, +-954, -255, -846, -1198, -400, -1650, 192, -1336, +741, -562, 942, 360, 661, 1227, 47, 1609, +-611, 1269, -1031, 454, -1052, -496, -639, -1303, +-2, -1568, 566, -1106, 885, -223, 826, 713, +370, 1409, -268, 1513, -785, 946, -1029, 26, +-919, -929, -439, -1558, 203, -1485, 708, -728, +913, 300, 746, 1210, 210, 1688, -454, 1440, +-951, 537, -1084, -560, -808, -1411, -252, -1737, +393, -1353, 835, -383, 936, 754, 651, 1571, +38, 1753, -590, 1271, -991, 305, -1080, -792, +-778, -1608, -155, -1807, 494, -1279, 939, -219, +993, 921, 592, 1706, -83, 1821, -737, 1202, +-1144, 122, -1145, -973, -653, -1667, 113, -1720, +736, -1114, 983, -57, 838, 1000, 344, 1601, +-332, 1581, -859, 990, -1043, 50, -855, -869, +-357, -1425, 234, -1433, 667, -886, 781, -16, +534, 771, 59, 1179, -427, 1146, -739, 742, +-760, 108, -489, -490, -37, -836, 353, -844, +458, -562, 324, -164, 44, 186, -289, 423, +-495, 507, -466, 421, -223, 244, 85, 80, +320, -26, 333, -106, 110, -168, -226, -233, +-513, -296, -596, -298, -433, -239, -130, -102, +235, 145, 560, 375, 577, 479, 251, 514, +-208, 419, -602, 122, -812, -237, -775, -489, +-434, -636, 101, -664, 564, -478, 730, -109, +546, 325, 160, 734, -294, 962, -691, 849, +-850, 448, -689, -119, -295, -691, 181, -1024, +545, -989, 608, -667, 384, -161, -15, 427, +-449, 892, -692, 1059, -634, 893, -367, 443, +1, -161, 373, -689, 507, -995, 327, -965, +-33, -552, -378, 76, -573, 645, -569, 943, +-363, 832, -40, 376, 313, -181, 517, -642, +406, -837, 57, -644, -307, -122, -559, 471, +-611, 874, -431, 897, -115, 472, 184, -204, +350, -803, 325, -1141, 113, -1054, -133, -433, +-301, 452, -385, 1195, -310, 1496, -135, 1177, +-5, 358, 67, -535, 62, -1235, -48, -1589, +-180, -1307, -213, -415, -147, 572, -47, 1253, +66, 1493, 112, 1141, -13, 342, -187, -482, +-254, -1078, -257, -1245, -164, -808, -16, -22, +46, 650, 14, 984, -65, 866, -150, 288, +-197, -412, -148, -857, -74, -984, -12, -684, +19, 84, -10, 902, -78, 1320, -136, 1232, +-141, 609, -147, -340, -181, -1146, -166, -1572, +-100, -1482, -26, -740, 54, 397, 63, 1334, +-62, 1748, -218, 1554, -306, 729, -285, -421, +-171, -1348, -14, -1749, 148, -1505, 232, -593, +197, 605, 47, 1545, -149, 1878, -306, 1444, +-467, 347, -610, -925, -596, -1840, -353, -2059, +41, -1439, 482, -184, 791, 1178, 737, 2131, +336, 2308, -194, 1543, -682, 187, -995, -1168, +-986, -2107, -694, -2325, -203, -1664, 306, -387, +650, 1029, 799, 2086, 664, 2309, 208, 1584, +-375, 290, -819, -1028, -982, -1924, -813, -2027, +-333, -1278, 266, -66, 661, 1127, 709, 1916, +489, 1901, 44, 1032, -489, -206, -856, -1298, +-916, -1899, -663, -1779, -201, -942, 305, 268, +690, 1379, 812, 1948, 559, 1738, 11, 844, +-571, -330, -939, -1294, -942, -1676, -631, -1371, +-102, -574, 461, 389, 723, 1128, 591, 1344, +188, 985, -338, 233, -776, -594, -871, -1130, +-565, -1159, -29, -707, 473, 69, 758, 913, +696, 1442, 216, 1344, -445, 702, -994, -209, +-1176, -1146, -855, -1736, -189, -1619, 505, -877, +987, 166, 1083, 1180, 647, 1806, -165, 1779, +-893, 1109, -1266, 56, -1237, -1011, -765, -1700, +15, -1754, 732, -1186, 1095, -201, 1035, 901, +611, 1666, -70, 1731, -803, 1148, -1317, 210, +-1372, -816, -911, -1610, -197, -1783, 487, -1241, +999, -262, 1112, 805, 750, 1650, 150, 1916, +-440, 1474, -932, 546, -1151, -548, -934, -1527, +-406, -2031, 132, -1766, 508, -862, 697, 299, +578, 1331, 172, 1854, -271, 1688, -561, 1016, +-686, 71, -578, -876, -252, -1441, 75, -1438, +292, -951, 404, -172, 384, 601, 154, 1045, +-236, 1066, -601, 737, -796, 155, -691, -497, +-328, -882, 83, -862, 432, -549, 658, -37, +624, 536, 287, 937, -189, 1003, -602, 690, +-855, 80, -901, -569, -651, -1053, -193, -1250, +279, -1014, 680, -342, 878, 469, 715, 1136, +181, 1490, -486, 1317, -986, 647, -1181, -194, +-990, -953, -464, -1442, 220, -1412, 808, -851, +1052, -14, 853, 785, 341, 1255, -339, 1205, +-954, 730, -1176, 74, -967, -578, -517, -978, +40, -885, 594, -386, 885, 203, 735, 650, +263, 734, -289, 432, -734, -23, -938, -460, +-775, -733, -293, -614, 264, -152, 629, 360, +646, 765, 371, 905, -83, 594, -576, -40, +-854, -622, -774, -962, -415, -955, 48, -535, +415, 127, 577, 759, 516, 1158, 216, 1097, +-196, 525, -521, -221, -699, -837, -704, -1210, +-480, -1174, -29, -639, 396, 131, 592, 853, +558, 1351, 254, 1371, -302, 846, -815, 31, +-962, -801, -734, -1380, -211, -1419, 448, -962, +874, -215, 828, 630, 461, 1259, -94, 1375, +-734, 994, -1163, 320, -1194, -418, -818, -953, +-116, -1110, 678, -891, 1215, -384, 1228, 271, +740, 764, -101, 894, -1034, 699, -1591, 272, +-1475, -222, -808, -533, 119, -600, 961, -492, +1337, -200, 1113, 147, 437, 359, -409, 424, +-1107, 379, -1413, 159, -1178, -101, -481, -206, +385, -194, 1061, -120, 1243, 39, 841, 143, +56, 68, -819, -89, -1455, -255, -1464, -385, +-894, -328, -47, 2, 841, 415, 1433, 738, +1384, 908, 694, 735, -287, 147, -1158, -542, +-1645, -1048, -1552, -1319, -873, -1196, 66, -587, +909, 305, 1383, 1145, 1268, 1663, 641, 1646, +-195, 1049, -920, 68, -1308, -940, -1231, -1630, +-703, -1783, 23, -1338, 629, -455, 932, 562, +812, 1351, 270, 1655, -399, 1424, -829, 764, +-924, -141, -690, -966, -155, -1397, 430, -1347, +732, -877, 667, -118, 295, 669, -267, 1162, +-761, 1223, -961, 866, -801, 263, -395, -342, +142, -803, 639, -1029, 860, -912, 719, -487, +299, 72, -260, 579, -790, 877, -1087, 899, +-1053, 652, -672, 215, -48, -281, 569, -670, +954, -824, 1012, -709, 721, -390, 133, 34, +-528, 435, -992, 689, -1158, 762, -1059, 604, +-701, 214, -132, -270, 465, -673, 933, -884, +1086, -766, 822, -303, 308, 308, -256, 832, +-726, 1106, -971, 974, -941, 407, -721, -356, +-439, -1009, -72, -1370, 323, -1309, 556, -694, +623, 293, 643, 1182, 474, 1655, 66, 1638, +-371, 1069, -685, 67, -840, -952, -813, -1661, +-576, -1879, -253, -1481, 83, -579, 419, 449, +626, 1309, 607, 1806, 418, 1764, 117, 1177, +-241, 296, -532, -627, -707, -1393, -739, -1715, +-555, -1508, -178, -939, 208, -148, 409, 709, +422, 1332, 306, 1559, 68, 1355, -224, 739, +-409, -60, -392, -763, -201, -1246, 58, -1368, +202, -1002, 139, -316, -63, 385, -305, 907, +-494, 1097, -543, 861, -376, 343, -95, -213, +193, -662, 480, -857, 626, -658, 487, -142, +167, 436, -169, 859, -495, 916, -733, 527, +-796, -122, -659, -743, -375, -1152, -35, -1145, +239, -636, 390, 163, 496, 904, 542, 1319, +466, 1308, 293, 879, 17, 159, -377, -584, +-775, -1103, -1001, -1298, -1005, -1068, -758, -462, +-223, 201, 398, 688, 806, 947, 971, 891, +920, 521, 559, 114, -25, -141, -613, -317, +-1050, -420, -1219, -338, -975, -202, -347, -183, +327, -179, 799, -70, 980, 86, 744, 250, +161, 383, -459, 379, -893, 265, -1033, 103, +-784, -150, -243, -424, 379, -530, 846, -446, +994, -191, 767, 224, 199, 624, -527, 797, +-1141, 694, -1373, 351, -1085, -195, -423, -763, +288, -1090, 888, -1056, 1212, -697, 1041, -46, +458, 706, -270, 1232, -888, 1384, -1187, 1149, +-1061, 534, -541, -285, 132, -1007, 674, -1422, +911, -1389, 730, -914, 164, -192, -529, 514, +-1050, 1022, -1132, 1214, -698, 1049, 14, 617, +715, 76, 1175, -432, 1191, -761, 670, -812, +-243, -675, -1136, -452, -1628, -127, -1520, 226, +-843, 462, 124, 602, 973, 652, 1453, 519, +1438, 250, 833, -76, -169, -484, -1089, -861, +-1543, -956, -1463, -680, -883, -100, 3, 601, +840, 1155, 1317, 1334, 1269, 1058, 713, 360, +-155, -565, -950, -1324, -1359, -1623, -1302, -1429, +-824, -763, -93, 289, 607, 1298, 1035, 1803, +1090, 1708, 745, 1094, 145, 108, -424, -922, +-775, -1636, -892, -1787, -809, -1299, -507, -359, +-72, 670, 287, 1404, 466, 1585, 460, 1207, +287, 435, 55, -528, -136, -1313, -298, -1509, +-336, -1049, -180, -182, 33, 783, 166, 1481, +177, 1545, 84, 948, -142, 5, -420, -965, +-575, -1677, -584, -1758, -455, -1105, -91, -36, +421, 1038, 826, 1758, 952, 1836, 734, 1272, +264, 321, -330, -726, -919, -1485, -1283, -1650, +-1252, -1241, -837, -486, -212, 351, 479, 971, +1106, 1137, 1378, 865, 1107, 393, 471, -61, +-278, -404, -988, -512, -1403, -325, -1301, -8, +-747, 218, -3, 249, 676, 38, 1072, -337, +1009, -607, 551, -563, -74, -232, -673, 245, +-1050, 742, -1003, 1039, -557, 898, 56, 359, +646, -292, 1000, -844, 932, -1112, 447, -912, +-231, -344, -880, 253, -1333, 654, -1332, 823, +-786, 727, 44, 364, 834, -131, 1385, -504, +1490, -606, 1046, -448, 231, -125, -689, 215, +-1486, 438, -1869, 470, -1613, 276, -854, -68, +92, -362, 1000, -501, 1644, -472, 1803, -232, +1395, 164, 545, 517, -491, 690, -1405, 651, +-1898, 401, -1849, -44, -1299, -573, -396, -957, +578, -1011, 1350, -697, 1731, -102, 1580, 590, +957, 1128, 136, 1332, -659, 1115, -1301, 521, +-1642, -272, -1531, -1022, -1024, -1511, -303, -1593, +507, -1200, 1170, -393, 1462, 575, 1378, 1410, +947, 1950, 214, 2018, -586, 1434, -1216, 318, +-1558, -962, -1516, -2047, -1057, -2616, -288, -2415, +573, -1421, 1319, 112, 1726, 1704, 1534, 2836, +787, 3140, -152, 2443, -1017, 897, -1645, -963, +-1795, -2545, -1375, -3388, -569, -3153, 354, -1830, +1190, 110, 1721, 1996, 1675, 3281, 1058, 3527, +121, 2553, -889, 691, -1668, -1375, -1902, -2984, +-1506, -3588, -623, -2933, 451, -1298, 1314, 740, +1676, 2527, 1463, 3421, 778, 3149, -151, 1884, +-1004, -3, -1476, -1897, -1498, -3064, -1043, -3164, +-179, -2311, 684, -778, 1144, 994, 1185, 2402, +902, 2999, 256, 2661, -559, 1528, -1096, -34, +-1147, -1502, -843, -2440, -312, -2644, 351, -2119, +861, -981, 956, 504, 663, 1860, 179, 2556, +-370, 2391, -851, 1534, -1017, 234, -751, -1170, +-223, -2159, 253, -2370, 583, -1785, 790, -602, +708, 741, 268, 1713, -249, 2027, -586, 1643, +-733, 736, -671, -303, -362, -1150, 41, -1621, +317, -1484, 417, -753, 387, 138, 165, 795, +-162, 1120, -317, 1065, -239, 646, -71, 77, +126, -430, 265, -741, 210, -711, -27, -382, +-328, -8, -574, 292, -656, 474, -466, 374, +-67, 42, 352, -237, 726, -373, 940, -382, +769, -179, 240, 201, -392, 564, -915, 748, +-1189, 625, -1091, 214, -572, -264, 187, -679, +811, -972, 1104, -986, 1005, -647, 542, -82, +-104, 546, -699, 1077, -1006, 1300, -917, 1121, +-518, 633, 39, -34, 567, -724, 819, -1216, +678, -1391, 254, -1217, -281, -656, -714, 125, +-818, 790, -524, 1220, -18, 1400, 439, 1201, +685, 629, 623, -90, 279, -746, -171, -1157, +-536, -1208, -720, -954, -664, -517, -350, 2, +104, 474, 525, 776, 742, 882, 666, 822, +313, 604, -187, 274, -662, -64, -953, -344, +-886, -583, -438, -782, 172, -840, 660, -680, +891, -368, 828, 10, 448, 490, -121, 1018, +-583, 1313, -788, 1194, -822, 747, -665, 35, +-255, -858, 221, -1602, 499, -1869, 584, -1523, +566, -630, 383, 520, 70, 1556, -195, 2190, +-338, 2166, -403, 1345, -452, -1, -478, -1340, +-419, -2223, -246, -2388, 37, -1741, 377, -510, +640, 839, 735, 1867, 624, 2233, 295, 1802, +-181, 830, -704, -261, -1088, -1180, -1142, -1633, +-851, -1459, -285, -872, 416, -176, 1041, 483, +1407, 902, 1389, 902, 896, 603, -6, 267, +-995, 15, -1670, -165, -1830, -268, -1509, -285, +-740, -248, 353, -204, 1430, -158, 2058, -94, +2004, 23, 1342, 195, 273, 311, -952, 273, +-1948, 139, -2331, -15, -1985, -200, -1022, -353, +258, -331, 1450, -117, 2194, 149, 2213, 394, +1515, 552, 398, 464, -831, 142, -1851, -231, +-2294, -587, -1975, -812, -1037, -689, 168, -291, +1274, 162, 1995, 618, 2109, 976, 1554, 996, +500, 660, -734, 147, -1744, -427, -2201, -955, +-1973, -1264, -1129, -1220, 59, -759, 1218, 32, +1989, 857, 2161, 1454, 1633, 1706, 513, 1471, +-776, 693, -1748, -379, -2176, -1408, -1973, -2116, +-1128, -2179, 114, -1497, 1285, -353, 2013, 952, +2100, 2126, 1453, 2660, 274, 2289, -971, 1241, +-1871, -166, -2156, -1601, -1705, -2553, -668, -2668, +567, -1995, 1574, -780, 2034, 640, 1787, 1829, +920, 2437, -234, 2355, -1280, 1599, -1913, 371, +-1935, -867, -1328, -1718, -288, -2073, 830, -1871, +1605, -1098, 1789, -29, 1403, 922, 600, 1505, +-363, 1640, -1144, 1283, -1490, 535, -1346, -331, +-814, -1020, -113, -1326, 509, -1108, 846, -455, +881, 281, 700, 826, 329, 1073, -99, 865, +-390, 202, -485, -520, -434, -948, -302, -1042, +-159, -775, -24, -108, 81, 687, 132, 1209, +119, 1317, 54, 1012, -1, 282, -28, -662, +-34, -1375, -9, -1604, 44, -1316, 122, -567, +163, 410, 63, 1241, -143, 1649, -308, 1485, +-335, 816, -263, -66, -154, -841, 26, -1291, +253, -1310, 388, -917, 379, -277, 283, 371, +95, 781, -170, 858, -409, 680, -545, 368, +-549, 14, -369, -247, -34, -280, 312, -139, +550, -19, 625, -38, 514, -153, 233, -280, +-85, -378, -341, -455, -544, -393, -683, -31, +-642, 499, -372, 870, 5, 1002, 328, 927, +528, 544, 628, -112, 622, -817, 457, -1345, +134, -1488, -221, -1127, -517, -416, -738, 395, +-829, 1104, -724, 1492, -399, 1420, 107, 955, +649, 259, 1007, -491, 1016, -1007, 700, -1125, +168, -964, -429, -653, -873, -201, -1051, 221, +-935, 431, -540, 486, 4, 493, 529, 473, +880, 442, 936, 375, 708, 227, 271, 30, +-294, -206, -780, -496, -996, -737, -861, -775, +-442, -590, 89, -268, 540, 90, 785, 441, +803, 745, 582, 873, 131, 731, -390, 397, +-741, 41, -844, -284, -717, -547, -381, -669, +109, -631, 598, -525, 878, -339, 844, -15, +529, 312, -1, 509, -607, 628, -1010, 690, +-1020, 543, -689, 155, -171, -274, 445, -553, +1010, -690, 1228, -659, 951, -365, 362, 78, +-322, 438, -941, 636, -1288, 611, -1258, 283, +-868, -191, -203, -564, 568, -725, 1192, -607, +1459, -143, 1277, 476, 722, 915, -7, 1011, +-706, 761, -1220, 174, -1391, -586, -1155, -1173, +-684, -1371, -150, -1129, 404, -474, 898, 405, +1161, 1146, 1143, 1503, 910, 1417, 488, 895, +-70, 42, -600, -826, -1005, -1341, -1259, -1370, +-1267, -982, -954, -325, -364, 376, 322, 845, +958, 979, 1467, 785, 1638, 310, 1255, -224, +434, -528, -490, -539, -1271, -337, -1718, 47, +-1630, 477, -998, 707, -94, 584, 770, 146, +1329, -482, 1436, -1053, 1102, -1293, 420, -1093, +-427, -489, -1085, 419, -1274, 1347, -987, 1914, +-365, 1925, 372, 1339, 951, 255, 1132, -983, +856, -1929, 247, -2356, -474, -2155, -1064, -1291, +-1295, 1, -1094, 1230, -548, 1987, 233, 2161, +1022, 1800, 1537, 1040, 1587, 87, 1107, -789, +236, -1358, -725, -1480, -1510, -1242, -1876, -847, +-1691, -409, -1060, 5, -180, 279, 760, 398, +1480, 500, 1769, 661, 1699, 863, 1296, 1044, +476, 1121, -531, 932, -1315, 352, -1752, -555, +-1837, -1514, -1532, -2214, -884, -2439, -44, -2068, +802, -1055, 1496, 458, 1898, 2035, 1901, 3167, +1460, 3502, 641, 2909, -395, 1475, -1354, -436, +-1950, -2316, -2093, -3628, -1808, -3952, -1106, -3213, +-123, -1671, 832, 285, 1582, 2165, 2080, 3400, +2171, 3706, 1652, 3162, 675, 1932, -365, 195, +-1312, -1585, -2087, -2828, -2333, -3284, -1870, -3003, +-1032, -2054, -139, -603, 780, 922, 1650, 2103, +2180, 2707, 2145, 2657, 1596, 1972, 722, 870, +-394, -313, -1559, -1303, -2321, -1963, -2411, -2172, +-1913, -1851, -924, -1116, 413, -192, 1647, 714, +2345, 1445, 2397, 1804, 1821, 1684, 658, 1144, +-718, 352, -1786, -526, -2260, -1226, -2063, -1504, +-1281, -1344, -209, -854, 817, -160, 1573, 537, +1859, 1005, 1575, 1165, 889, 1010, 77, 585, +-725, 19, -1330, -526, -1535, -928, -1342, -1071, +-868, -901, -238, -508, 437, -19, 1039, 497, +1372, 959, 1345, 1195, 1100, 1110, 647, 738, +-95, 206, -943, -391, -1566, -982, -1790, -1428, +-1544, -1548, -836, -1284, 120, -726, 1014, 55, +1614, 928, 1807, 1664, 1524, 2091, 815, 2125, +-49, 1616, -767, 551, -1276, -772, -1533, -1971, +-1374, -2803, -842, -3043, -257, -2480, 199, -1184, +588, 504, 859, 2162, 902, 3377, 837, 3746, +839, 3138, 771, 1697, 474, -275, 50, -2252, +-470, -3555, -1164, -3879, -1778, -3287, -1952, -1834, +-1649, 197, -866, 2048, 337, 3080, 1621, 3252, +2585, 2689, 2963, 1509, 2523, 66, 1278, -1175, +-391, -1945, -2000, -2113, -3088, -1728, -3333, -1122, +-2730, -524, -1459, 42, 202, 493, 1765, 714, +2819, 813, 3203, 915, 2847, 999, 1790, 991, +318, 825, -1150, 433, -2298, -146, -2935, -782, +-2904, -1362, -2189, -1703, -1007, -1611, 407, -1066, +1740, -254, 2626, 671, 2891, 1510, 2544, 1975, +1591, 1889, 170, 1295, -1285, 349, -2353, -724, +-2857, -1585, -2707, -1955, -1829, -1743, -430, -1049, +1015, -39, 2091, 992, 2623, 1656, 2458, 1702, +1592, 1176, 368, 288, -805, -653, -1718, -1291, +-2152, -1414, -1888, -1020, -1113, -253, -199, 600, +639, 1128, 1227, 1142, 1380, 752, 1100, 129, +523, -539, -117, -927, -529, -862, -591, -501, +-419, 8, -162, 530, 113, 774, 239, 562, +62, 99, -287, -398, -555, -758, -617, -735, +-412, -271, 10, 351, 494, 878, 902, 1187, +1109, 1079, 984, 464, 515, -441, -156, -1236, +-879, -1625, -1385, -1513, -1461, -990, -1150, -168, +-528, 763, 341, 1481, 1142, 1756, 1553, 1598, +1519, 1076, 1095, 295, 386, -493, -417, -1133, +-1074, -1570, -1427, -1676, -1422, -1384, -1043, -843, +-346, -148, 435, 619, 1003, 1257, 1217, 1637, +1101, 1716, 740, 1401, 229, 717, -315, -79, +-721, -837, -801, -1452, -621, -1715, -392, -1507, +-158, -983, 153, -320, 396, 342, 337, 847, +53, 1091, -143, 1054, -130, 827, -23, 551, +204, 335, 579, 181, 832, 83, 688, -61, +184, -364, -513, -770, -1155, -1169, -1467, -1509, +-1385, -1557, -889, -1050, 36, -107, 1104, 1045, +1873, 2198, 2138, 2888, 1829, 2664, 943, 1643, +-343, 154, -1648, -1520, -2559, -2885, -2690, -3385, +-1926, -2865, -571, -1526, 932, 225, 2151, 1792, +2717, 2725, 2473, 2846, 1537, 2153, 189, 863, +-1162, -516, -2108, -1513, -2408, -1895, -2023, -1657, +-1059, -1000, 184, -173, 1228, 581, 1770, 962, +1766, 818, 1238, 425, 331, 34, -523, -333, +-966, -576, -986, -493, -705, -117, -211, 376, +294, 774, 520, 853, 368, 625, 3, 233, +-378, -321, -680, -940, -728, -1246, -377, -1108, +269, -695, 946, -79, 1415, 680, 1464, 1249, +987, 1390, 120, 1169, -878, 640, -1740, -156, +-2152, -1000, -1892, -1555, -1085, -1586, 12, -1036, +1186, -125, 2144, 858, 2526, 1661, 2212, 1973, +1317, 1536, 17, 463, -1344, -840, -2318, -1952, +-2639, -2471, -2247, -2121, -1240, -967, 49, 547, +1226, 1910, 1991, 2702, 2194, 2658, 1855, 1717, +1115, 201, 194, -1305, -652, -2318, -1213, -2575, +-1410, -2021, -1290, -895, -944, 320, -503, 1256, +-105, 1694, 220, 1514, 441, 852, 570, 123, +716, -375, 893, -529, 961, -272, 832, 206, +533, 496, 86, 413, -481, 27, -1046, -609, +-1391, -1286, -1449, -1658, -1275, -1517, -831, -844, +-68, 256, 807, 1424, 1493, 2228, 1872, 2464, +1904, 2084, 1531, 1158, 754, -67, -264, -1253, +-1242, -2141, -1904, -2472, -2111, -2194, -1886, -1545, +-1311, -756, -419, 130, 633, 1017, 1493, 1710, +1943, 2101, 2005, 2146, 1701, 1874, 1033, 1325, +204, 480, -587, -626, -1266, -1686, -1702, -2423, +-1779, -2749, -1582, -2549, -1145, -1742, -412, -537, +464, 775, 1219, 2027, 1720, 2929, 1919, 3148, +1728, 2623, 1182, 1593, 403, 281, -475, -1119, +-1292, -2337, -1858, -3017, -2012, -2944, -1681, -2217, +-963, -1080, -52, 233, 860, 1411, 1545, 2092, +1839, 2216, 1680, 1896, 1128, 1236, 350, 471, +-427, -104, -1006, -483, -1256, -752, -1156, -860, +-782, -875, -269, -964, 222, -1073, 529, -1047, +544, -880, 320, -510, 5, 113, -210, 864, +-186, 1564, 57, 2064, 360, 2159, 607, 1747, +739, 931, 647, -160, 276, -1312, -239, -2203, +-699, -2649, -1032, -2615, -1185, -1993, -1077, -864, +-686, 431, -106, 1606, 545, 2484, 1109, 2843, +1440, 2579, 1513, 1779, 1297, 603, 763, -652, +22, -1671, -731, -2307, -1379, -2500, -1768, -2147, +-1760, -1314, -1343, -259, -618, 698, 278, 1331, +1107, 1600, 1632, 1551, 1784, 1202, 1575, 674, +1055, 272, 371, 92, -281, -19, -798, -169, +-1185, -381, -1420, -720, -1375, -1121, -1067, -1458, +-683, -1628, -262, -1434, 315, -726, 987, 341, +1472, 1457, 1692, 2387, 1711, 2833, 1436, 2585, +737, 1686, -267, 317, -1301, -1236, -2104, -2495, +-2492, -3099, -2334, -2986, -1555, -2210, -286, -937, +1120, 495, 2247, 1696, 2819, 2425, 2699, 2582, +1926, 2209, 697, 1425, -705, 452, -1922, -425, +-2580, -1057, -2518, -1495, -1854, -1724, -807, -1635, +385, -1332, 1432, -942, 1995, -408, 1949, 283, +1429, 936, 652, 1454, -178, 1807, -814, 1860, +-1093, 1501, -1030, 784, -687, -137, -202, -1059, +172, -1736, 285, -2020, 217, -1849, 72, -1277, +-120, -455, -300, 400, -246, 1091, 143, 1431, +598, 1424, 837, 1234, 877, 904, 738, 415, +283, -73, -394, -391, -959, -637, -1240, -903, +-1260, -1099, -979, -1150, -393, -1066, 351, -736, +1008, -109, 1429, 655, 1538, 1346, 1215, 1781, +522, 1782, -240, 1265, -895, 369, -1380, -667, +-1479, -1534, -1120, -1928, -514, -1713, 194, -1050, +913, -155, 1336, 801, 1252, 1528, 819, 1662, +238, 1143, -413, 299, -930, -535, -1018, -1147, +-664, -1332, -111, -925, 429, -100, 789, 740, +788, 1254, 459, 1277, -11, 807, -491, 3, +-827, -857, -871, -1483, -598, -1601, -102, -1134, +491, -264, 979, 682, 1192, 1441, 1058, 1765, +612, 1522, -24, 787, -674, -171, -1164, -1023, +-1325, -1531, -1104, -1561, -611, -1117, 27, -359, +659, 415, 1111, 994, 1278, 1264, 1174, 1149, +782, 654, 147, 0, -497, -572, -938, -935, +-1127, -975, -1011, -664, -559, -146, 16, 384, +446, 803, 643, 921, 670, 670, 497, 194, +132, -321, -191, -769, -257, -987, -142, -832, +9, -370, 220, 206, 452, 694, 468, 923, +183, 829, -194, 509, -576, 83, -911, -306, +-976, -533, -670, -544, -149, -388, 484, -192, +1124, -80, 1468, -64, 1317, -61, 757, -67, +20, -68, -684, 31, -1183, 287, -1339, 563, +-1062, 726, -488, 702, 133, 450, 632, 2, +885, -508, 827, -942, 526, -1185, 127, -1103, +-219, -688, -375, -93, -307, 478, -59, 935, +231, 1202, 447, 1193, 517, 877, 345, 388, +-101, -96, -625, -507, -994, -826, -1141, -997, +-958, -969, -386, -830, 402, -623, 1157, -300, +1719, 166, 1894, 667, 1521, 1113, 665, 1422, +-406, 1441, -1406, 1078, -2097, 404, -2264, -414, +-1806, -1221, -827, -1795, 340, -1951, 1382, -1595, +2053, -789, 2187, 265, 1786, 1243, 985, 1874, +-31, 2019, -929, 1615, -1453, 732, -1623, -330, +-1424, -1177, -845, -1591, -133, -1496, 390, -970, +691, -216, 815, 469, 729, 869, 516, 881, +381, 542, 339, 18, 259, -450, 160, -648, +51, -492, -198, -17, -566, 567, -810, 995, +-847, 1071, -739, 768, -461, 115, 0, -761, +500, -1509, 890, -1743, 1101, -1399, 1076, -655, +777, 336, 275, 1308, -256, 1892, -696, 1859, +-974, 1269, -998, 290, -723, -746, -321, -1426, +32, -1558, 343, -1240, 600, -611, 703, 155, +662, 760, 553, 985, 333, 805, 18, 360, +-259, -159, -417, -526, -491, -610, -467, -389, +-353, 38, -214, 480, -65, 747, 108, 738, +288, 433, 451, -109, 575, -666, 586, -989, +433, -958, 126, -666, -248, -216, -576, 308, +-765, 747, -755, 891, -491, 733, -56, 444, +377, 98, 753, -244, 966, -441, 873, -406, +544, -234, 113, -9, -417, 161, -876, 150, +-1013, -36, -824, -278, -471, -537, -4, -732, +491, -654, 789, -241, 820, 388, 706, 1058, +536, 1570, 254, 1683, -104, 1289, -380, 410, +-499, -752, -575, -1832, -641, -2456, -560, -2413, +-305, -1650, -8, -344, 237, 1046, 469, 2092, +699, 2558, 833, 2348, 779, 1494, 566, 306, +219, -801, -224, -1520, -643, -1747, -940, -1530, +-1034, -1021, -843, -440, -437, 18, 27, 250, +472, 318, 813, 330, 983, 418, 934, 645, +679, 974, 327, 1234, -19, 1246, -354, 869, +-621, 112, -685, -818, -578, -1699, -465, -2308, +-390, -2398, -275, -1801, -105, -664, 127, 694, +439, 1930, 797, 2723, 1086, 2851, 1152, 2289, +893, 1157, 341, -296, -362, -1635, -1038, -2487, +-1479, -2696, -1566, -2278, -1250, -1324, -551, -117, +374, 997, 1173, 1740, 1596, 1984, 1613, 1726, +1240, 1113, 514, 377, -356, -305, -974, -767, +-1150, -926, -1008, -820, -680, -611, -227, -402, +159, -223, 351, -105, 404, -108, 384, -146, +320, -45, 278, 212, 301, 505, 316, 736, +207, 871, -33, 804, -256, 469, -395, -60, +-470, -593, -442, -979, -226, -1084, 107, -873, +390, -434, 557, 80, 562, 513, 327, 757, +-61, 725, -384, 424, -588, -1, -630, -312, +-415, -417, 30, -331, 521, -83, 861, 287, +939, 608, 764, 696, 368, 504, -199, 69, +-747, -475, -1096, -940, -1175, -1179, -978, -1149, +-501, -782, 150, -118, 792, 650, 1268, 1268, +1463, 1569, 1318, 1469, 868, 1019, 195, 369, +-557, -390, -1161, -1073, -1498, -1409, -1518, -1310, +-1170, -1007, -525, -646, 227, -249, 973, 142, +1537, 461, 1646, 705, 1255, 900, 609, 1061, +-76, 1165, -692, 1081, -1061, 709, -1046, 64, +-742, -721, -371, -1464, -10, -1923, 272, -1953, +370, -1503, 289, -621, 132, 472, 2, 1447, +-26, 2041, 109, 2116, 377, 1636, 663, 797, +785, -127, 653, -915, 254, -1397, -363, -1456, +-1042, -1190, -1463, -767, -1423, -289, -986, 121, +-257, 359, 638, 438, 1436, 446, 1834, 438, +1718, 475, 1133, 519, 243, 528, -689, 497, +-1382, 401, -1634, 144, -1394, -262, -786, -692, +-21, -1053, 653, -1227, 1027, -1119, 1076, -744, +829, -187, 362, 513, -94, 1163, -346, 1505, +-442, 1438, -412, 1031, -208, 404, 93, -277, +287, -831, 267, -1141, 134, -1124, -17, -825, +-179, -401, -324, -25, -341, 231, -201, 327, +-3, 324, 181, 307, 373, 289, 515, 285, +496, 329, 354, 379, 161, 342, -93, 205, +-386, -27, -543, -277, -469, -462, -284, -552, +-133, -581, 76, -517, 337, -390, 430, -263, +347, -78, 241, 200, 112, 496, -65, 761, +-163, 977, -130, 978, -60, 719, -25, 303, +50, -227, 153, -828, 151, -1263, 31, -1364, +-52, -1179, -61, -757, -130, -138, -258, 528, +-262, 1052, -98, 1340, 57, 1312, 208, 993, +418, 493, 563, -50, 498, -541, 284, -892, +35, -1037, -215, -952, -443, -687, -587, -370, +-570, -36, -424, 292, -200, 537, 81, 622, +381, 610, 596, 518, 680, 341, 625, 146, +431, 2, 136, -100, -182, -167, -415, -197, +-527, -247, -516, -318, -402, -413, -210, -520, +9, -559, 187, -415, 262, -136, 276, 219, +257, 651, 189, 1040, 177, 1183, 283, 1025, +365, 659, 287, 98, 106, -594, -123, -1241, +-417, -1590, -711, -1515, -811, -1062, -651, -384, +-291, 402, 200, 1119, 675, 1508, 976, 1475, +1050, 1124, 876, 583, 454, -44, -70, -559, +-564, -887, -907, -1048, -1006, -1026, -835, -807, +-456, -500, 6, -149, 428, 262, 765, 628, +932, 846, 766, 916, 357, 838, -31, 527, +-286, 67, -460, -353, -484, -617, -294, -723, +-31, -620, 127, -315, 150, 17, 88, 184, +-10, 152, -101, 23, -129, -160, -22, -270, +153, -157, 286, 180, 353, 572, 347, 891, +244, 969, 88, 665, -106, 59, -336, -646, +-484, -1275, -450, -1575, -261, -1287, -47, -555, +143, 299, 343, 1075, 520, 1567, 490, 1508, +249, 936, 24, 109, -77, -710, -155, -1216, +-255, -1226, -234, -843, -57, -267, 96, 389, +77, 865, 13, 941, 3, 639, -36, 140, +-129, -386, -83, -736, 138, -798, 293, -596, +302, -184, 285, 303, 236, 689, 49, 843, +-172, 747, -286, 406, -294, -28, -264, -415, +-169, -708, 6, -849, 164, -722, 241, -370, +273, 20, 280, 352, 213, 581, 75, 677, +-71, 584, -134, 331, -119, 33, -78, -187, +-49, -358, -28, -461, 7, -399, 66, -201, +97, 6, 74, 162, 48, 244, 26, 198, +11, 103, -35, -8, -95, -172, -75, -300, +64, -230, 200, -71, 239, 60, 205, 246, +154, 473, 63, 573, -112, 488, -268, 275, +-314, -104, -250, -554, -123, -894, 29, -1010, +182, -883, 327, -461, 381, 168, 315, 769, +185, 1163, 28, 1281, -106, 1084, -181, 563, +-226, -110, -245, -724, -153, -1145, 6, -1293, +108, -1062, 126, -545, 143, 29, 168, 521, +149, 878, 92, 973, 19, 727, -30, 313, +-34, -65, -25, -306, -29, -395, -3, -300, +37, -103, 67, 89, 61, 154, 31, 39, +50, -187, 64, -400, -36, -510, -139, -474, +-116, -251, -84, 106, -83, 506, 5, 822, +216, 959, 391, 843, 398, 498, 275, -35, +122, -641, -46, -1083, -224, -1230, -331, -1086, +-353, -653, -316, 38, -219, 706, -59, 1097, +104, 1153, 253, 915, 401, 408, 499, -156, +473, -547, 352, -728, 189, -686, -8, -388, +-210, 10, -409, 225, -565, 228, -631, 120, +-555, -41, -308, -226, 100, -274, 522, -102, +807, 191, 906, 446, 797, 558, 488, 477, +56, 214, -340, -108, -606, -391, -742, -563, +-742, -563, -553, -365, -251, -117, 66, 75, +369, 232, 599, 337, 678, 307, 622, 185, +513, 106, 358, 69, 96, 30, -231, -28, +-470, -71, -622, -104, -702, -118, -602, -152, +-267, -179, 168, -129, 532, -24, 741, 51, +735, 79, 491, 93, 132, 75, -150, 56, +-329, 33, -407, 15, -329, 23, -80, 76, +168, 98, 221, 68, 133, 20, 58, -70, +-31, -180, -170, -209, -225, -147, -135, -121, +64, -96, 281, 3, 389, 121, 317, 145, +212, 130, 166, 149, 85, 168, -63, 134, +-168, 55, -217, -31, -320, -109, -404, -124, +-341, -116, -153, -139, 71, -185, 315, -172, +551, -138, 683, -109, 598, 4, 356, 215, +103, 372, -163, 406, -437, 387, -616, 243, +-627, -54, -476, -341, -193, -449, 127, -427, +410, -297, 561, -69, 525, 143, 364, 241, +168, 235, -18, 111, -114, -120, -62, -268, +27, -212, 56, 16, 39, 308, -10, 573, +-167, 670, -374, 523, -479, 133, -450, -413, +-323, -928, -62, -1210, 373, -1147, 868, -724, +1175, 10, 1120, 808, 785, 1412, 258, 1654, +-437, 1451, -1128, 757, -1515, -242, -1450, -1191, +-1013, -1774, -361, -1800, 414, -1258, 1163, -317, +1587, 682, 1579, 1416, 1212, 1637, 595, 1296, +-132, 511, -774, -415, -1184, -1107, -1295, -1295, +-1095, -956, -644, -252, -98, 564, 354, 1146, +683, 1249, 883, 808, 896, -9, 692, -916, +367, -1537, 47, -1624, -165, -1112, -274, -157, +-314, 906, -292, 1709, -250, 1999, -210, 1702, +-164, 863, -142, -271, -185, -1333, -161, -1961, +33, -2004, 276, -1499, 398, -632, 496, 379, +627, 1237, 611, 1662, 417, 1605, 148, 1161, +-190, 473, -550, -266, -760, -791, -779, -1015, +-661, -963, -437, -695, -81, -330, 332, -40, +649, 162, 836, 292, 921, 277, 825, 189, +510, 196, 130, 310, -226, 365, -561, 335, +-813, 255, -835, 118, -640, -109, -360, -349, +-79, -522, 186, -596, 401, -530, 547, -325, +622, -48, 616, 174, 575, 319, 468, 404, +274, 434, 33, 394, -252, 334, -587, 269, +-844, 202, -911, 101, -774, -115, -465, -454, +-53, -776, 429, -910, 906, -860, 1212, -592, +1187, -67, 899, 607, 502, 1139, 22, 1370, +-546, 1266, -1020, 833, -1230, 137, -1181, -658, +-884, -1284, -342, -1527, 321, -1329, 871, -838, +1184, -159, 1264, 592, 1098, 1192, 638, 1384, +40, 1150, -480, 635, -856, 16, -1031, -537, +-939, -898, -613, -976, -157, -744, 319, -296, +663, 126, 781, 394, 659, 492, 395, 438, +99, 250, -135, 28, -223, -145, -172, -248, +-59, -235, 53, -119, 106, 37, 42, 160, +-91, 250, -238, 270, -328, 198, -312, 12, +-161, -214, 100, -384, 395, -463, 615, -444, +669, -288, 542, 5, 256, 314, -100, 566, +-407, 705, -561, 664, -578, 408, -480, 40, +-260, -374, 40, -750, 302, -924, 466, -807, +541, -484, 534, -54, 439, 446, 218, 856, +-43, 998, -248, 825, -396, 472, -489, 8, +-481, -502, -353, -895, -65, -976, 310, -755, +587, -372, 693, 98, 605, 553, 309, 859, +-107, 919, -459, 733, -636, 279, -571, -284, +-273, -732, 122, -984, 420, -1006, 572, -663, +586, -5, 397, 661, 55, 1119, -241, 1252, +-379, 956, -441, 259, -421, -538, -219, -1171, +129, -1444, 368, -1230, 427, -566, 441, 293, +380, 1059, 144, 1493, -123, 1401, -266, 803, +-318, -57, -254, -829, -79, -1293, 100, -1308, +182, -862, 205, -108, 178, 613, 56, 1031, +-114, 1042, -221, 661, -217, 57, -89, -502, +153, -814, 398, -828, 556, -504, 553, 59, +369, 624, 40, 934, -369, 860, -734, 413, +-884, -220, -754, -787, -383, -1122, 158, -1088, +684, -613, 1023, 171, 1103, 884, 935, 1268, +520, 1240, -59, 815, -646, 80, -1033, -692, +-1106, -1202, -859, -1273, -379, -909, 150, -288, +594, 382, 865, 895, 891, 1096, 646, 870, +272, 344, -43, -226, -213, -630, -308, -805, +-329, -691, -218, -311, -60, 144, 25, 503, +18, 668, -43, 577, -147, 222, -225, -184, +-189, -476, 16, -613, 325, -555, 599, -256, +710, 140, 640, 438, 421, 580, 32, 548, +-450, 324, -786, -16, -833, -289, -680, -451, +-375, -469, 44, -325, 457, -91, 728, 103, +792, 250, 655, 328, 362, 245, -23, 56, +-338, -86, -418, -134, -330, -155, -176, -87, +-14, 52, 110, 146, 143, 146, 82, 121, +-41, 51, -154, -80, -184, -202, -111, -267, +39, -268, 226, -208, 403, -89, 499, 56, +516, 260, 408, 486, 107, 600, -290, 486, +-578, 203, -695, -151, -656, -522, -443, -819, +-96, -904, 286, -676, 585, -193, 737, 401, +716, 891, 527, 1109, 224, 990, -44, 591, +-243, -18, -405, -657, -487, -1090, -446, -1182, +-326, -921, -193, -379, -21, 295, 204, 842, +405, 1106, 508, 1042, 530, 674, 429, 80, +199, -508, -84, -887, -319, -974, -419, -769, +-368, -350, -198, 161, 35, 580, 242, 766, +331, 671, 285, 413, 103, 91, -128, -230, +-285, -456, -299, -465, -179, -308, 57, -139, +350, -19, 568, 53, 605, 79, 412, 62, +64, 77, -307, 131, -559, 220, -626, 304, +-499, 322, -227, 186, 94, -55, 352, -307, +493, -534, 484, -666, 363, -590, 252, -279, +150, 123, 12, 504, -108, 777, -150, 848, +-183, 648, -245, 263, -286, -195, -238, -595, +-115, -777, 16, -722, 119, -534, 200, -288, +321, 26, 441, 308, 466, 479, 370, 539, +210, 541, -16, 468, -301, 324, -557, 109, +-632, -173, -457, -454, -179, -648, 78, -704, +345, -629, 560, -400, 545, -55, 367, 353, +196, 716, 58, 910, -93, 826, -207, 505, +-217, 61, -158, -408, -90, -750, -37, -837, +-13, -656, -34, -315, -61, 92, -72, 402, +-28, 504, 87, 405, 267, 218, 431, 9, +466, -134, 375, -130, 202, -41, -75, 34, +-374, 81, -533, 90, -561, -22, -471, -181, +-208, -266, 165, -246, 465, -160, 642, 4, +699, 181, 553, 257, 182, 246, -234, 202, +-473, 104, -523, -60, -445, -162, -243, -179, +63, -163, 342, -132, 466, -66, 409, -20, +246, 25, 32, 145, -187, 270, -337, 288, +-355, 201, -215, 54, 18, -195, 254, -479, +435, -653, 505, -598, 398, -291, 154, 233, +-136, 781, -376, 1095, -495, 1054, -469, 668, +-296, -5, -27, -791, 265, -1374, 484, -1523, +563, -1154, 466, -399, 253, 497, 0, 1241, +-241, 1600, -403, 1438, -404, 782, -211, -111, +65, -869, 260, -1231, 319, -1161, 264, -718, +56, -75, -202, 509, -334, 757, -300, 590, +-151, 160, 112, -255, 449, -466, 681, -429, +626, -136, 317, 343, -60, 781, -418, 900, +-695, 657, -788, 149, -596, -486, -175, -1050, +298, -1285, 667, -1118, 832, -644, 731, 43, +429, 774, 59, 1268, -288, 1350, -500, 1090, +-534, 568, -411, -84, -188, -673, 63, -1033, +253, -1127, 336, -940, 299, -519, 194, -32, +81, 372, -44, 656, -137, 784, -126, 672, +-25, 401, 49, 118, 85, -115, 136, -299, +176, -364, 130, -302, 50, -181, -23, -80, +-138, -38, -242, -47, -262, -66, -195, -51, +-54, -29, 145, 29, 329, 131, 439, 232, +431, 250, 311, 196, 108, 115, -136, 13, +-335, -94, -415, -157, -376, -156, -236, -132, +12, -89, 246, -61, 343, -63, 312, -75, +211, -70, 41, -73, -123, -52, -175, 46, +-91, 174, 80, 244, 275, 276, 383, 308, +288, 255, 61, 121, -197, -31, -436, -199, +-594, -398, -550, -542, -272, -587, 116, -531, +464, -327, 715, 27, 823, 429, 718, 761, +418, 965, -12, 938, -434, 631, -715, 133, +-788, -394, -694, -850, -458, -1110, -101, -1078, +286, -774, 565, -303, 698, 225, 740, 694, +641, 947, 373, 943, 63, 731, -192, 377, +-440, -48, -643, -378, -693, -535, -552, -556, +-280, -463, 41, -262, 353, -72, 576, -4, +642, 5, 553, 0, 373, -12, 131, 16, +-104, 145, -259, 314, -304, 463, -288, 532, +-234, 461, -142, 237, -70, -83, -32, -407, +1, -667, 33, -779, 67, -720, 154, -502, +274, -179, 370, 193, 385, 511, 327, 716, +207, 789, -16, 730, -306, 532, -505, 203, +-527, -176, -419, -508, -214, -723, 33, -811, +256, -731, 397, -490, 438, -144, 370, 187, +242, 429, 140, 568, 81, 599, 11, 509, +-68, 334, -109, 187, -146, 79, -203, -42, +-274, -170, -322, -263, -304, -383, -190, -535, +-4, -646, 245, -648, 504, -511, 662, -194, +681, 301, 574, 822, 339, 1203, -26, 1324, +-414, 1126, -717, 565, -876, -236, -853, -1025, +-610, -1555, -198, -1683, 284, -1354, 731, -645, +1022, 212, 1060, 965, 822, 1436, 418, 1515, +-49, 1161, -490, 533, -801, -134, -869, -667, +-713, -965, -434, -955, -97, -677, 221, -296, +446, 45, 539, 252, 497, 288, 376, 175, +267, 33, 177, -29, 106, 48, 50, 235, +-28, 454, -174, 570, -357, 484, -485, 196, +-501, -226, -417, -667, -229, -956, 77, -934, +393, -614, 630, -120, 730, 399, 669, 810, +444, 954, 90, 787, -290, 413, -535, -39, +-596, -437, -531, -634, -349, -563, -76, -310, +185, 5, 330, 248, 357, 320, 289, 187, +175, -56, 72, -304, 11, -448, -21, -370, +-3, -55, 70, 358, 122, 688, 98, 821, +-14, 671, -148, 258, -239, -291, -284, -778, +-273, -1039, -147, -958, 55, -560, 242, 8, +351, 552, 367, 889, 330, 914, 228, 635, +49, 178, -103, -288, -140, -570, -156, -591, +-187, -382, -147, -51, -47, 256, -17, 387, +-65, 274, -98, -9, -97, -318, -73, -504, +19, -478, 228, -216, 468, 198, 618, 619, +581, 856, 361, 784, 5, 400, -412, -175, +-759, -716, -877, -1004, -727, -969, -405, -624, +4, -24, 418, 596, 751, 947, 893, 922, +818, 614, 577, 120, 249, -394, -116, -709, +-468, -734, -705, -514, -740, -123, -596, 297, +-371, 544, -113, 547, 139, 354, 353, 57, +510, -261, 606, -469, 615, -478, 522, -316, +335, -50, 93, 249, -188, 457, -479, 483, +-682, 348, -759, 113, -696, -170, -477, -428, +-103, -519, 353, -417, 805, -205, 1096, 64, +1083, 360, 772, 549, 266, 527, -320, 338, +-850, 51, -1122, -275, -1033, -545, -676, -642, +-203, -545, 295, -272, 693, 115, 886, 489, +849, 710, 631, 724, 314, 532, -30, 161, +-334, -277, -533, -640, -588, -818, -515, -762, +-357, -461, -169, -23, 30, 395, 219, 670, +396, 745, 533, 603, 571, 287, 473, -93, +246, -394, -59, -495, -363, -410, -562, -230, +-595, -53, -433, 89, -149, 152, 143, 97, +360, -27, 450, -97, 395, -72, 245, 7, +61, 116, -90, 227, -124, 301, -77, 288, +-33, 191, -1, 20, 27, -192, -5, -381, +-107, -482, -223, -479, -247, -347, -132, -88, +59, 215, 247, 460, 391, 572, 456, 513, +371, 306, 151, 45, -133, -194, -377, -349, +-476, -365, -375, -242, -166, -83, 33, 18, +209, 44, 338, 6, 345, -71, 212, -147, +31, -149, -99, -57, -135, 107, -100, 294, +-14, 450, 85, 503, 134, 417, 98, 206, +-7, -103, -121, -455, -180, -742, -161, -841, +-68, -727, 80, -410, 186, 60, 202, 544, +153, 878, 94, 1006, 37, 894, -15, 517, +-28, -10, 2, -489, 2, -812, -55, -934, +-93, -796, -111, -442, -119, -21, -89, 333, +-3, 550, 95, 570, 170, 420, 223, 210, +259, 29, 254, -67, 164, -53, -12, 28, +-220, 68, -355, 12, -371, -136, -283, -331, +-105, -507, 141, -562, 351, -423, 448, -101, +416, 293, 282, 631, 71, 830, -186, 799, +-374, 515, -419, 71, -342, -376, -174, -705, +86, -834, 339, -746, 448, -460, 385, -48, +234, 358, 41, 619, -180, 682, -342, 566, +-380, 288, -305, -73, -154, -370, 64, -501, +303, -462, 485, -263, 535, 35, 413, 296, +127, 410, -241, 343, -554, 126, -705, -150, +-621, -371, -299, -465, 161, -377, 578, -111, +836, 221, 841, 464, 565, 547, 119, 448, +-354, 197, -757, -110, -949, -370, -810, -492, +-402, -441, 117, -266, 608, -59, 932, 132, +944, 262, 645, 294, 172, 239, -301, 152, +-639, 60, -761, -19, -644, -63, -340, -96, +33, -120, 331, -116, 489, -104, 494, -113, +371, -85, 162, 1, -52, 98, -178, 174, +-183, 206, -127, 153, -55, 36, 24, -90, +52, -207, -3, -272, -90, -212, -125, -39, +-94, 158, -20, 313, 79, 364, 189, 265, +246, 49, 222, -189, 148, -387, 61, -485, +-19, -394, -84, -118, -118, 202, -133, 421, +-148, 507, -154, 440, -134, 200, -111, -134, +-56, -405, 68, -507, 219, -423, 338, -174, +424, 146, 451, 396, 324, 495, 52, 407, +-257, 121, -512, -246, -668, -516, -636, -580, +-409, -427, -84, -87, 268, 328, 593, 640, +779, 722, 754, 546, 559, 156, 240, -318, +-147, -672, -521, -783, -762, -634, -794, -270, +-608, 201, -254, 593, 164, 730, 516, 576, +701, 219, 673, -202, 469, -527, 196, -609, +-66, -428, -260, -67, -352, 340, -324, 617, +-222, 613, -116, 345, -48, -61, -14, -477, +-11, -763, -27, -792, -2, -543, 98, -99, +254, 410, 394, 814, 449, 981, 370, 877, +152, 537, -159, 23, -438, -540, -585, -967, +-587, -1125, -439, -987, -147, -585, 206, -10, +499, 582, 657, 1022, 631, 1162, 430, 951, +129, 477, -166, -93, -383, -594, -469, -888, +-407, -890, -253, -619, -82, -205, 59, 194, +150, 453, 174, 499, 162, 357, 157, 122, +191, -100, 231, -221, 222, -181, 149, 13, +37, 242, -111, 368, -287, 323, -425, 109, +-432, -219, -287, -533, -69, -691, 174, -612, +401, -302, 524, 154, 493, 572, 346, 777, +122, 729, -131, 471, -319, 59, -393, -370, +-381, -615, -299, -608, -134, -422, 57, -139, +197, 143, 268, 304, 284, 308, 247, 202, +190, 38, 133, -99, 62, -114, -10, -23, +-89, 74, -202, 143, -319, 163, -339, 82, +-247, -75, -103, -220, 59, -301, 247, -289, +406, -153, 463, 70, 408, 267, 264, 371, +49, 367, -201, 235, -413, -5, -516, -258, +-470, -417, -303, -439, -50, -327, 216, -97, +396, 187, 451, 423, 413, 531, 310, 476, +149, 259, -23, -57, -157, -363, -247, -565, +-305, -595, -316, -430, -287, -124, -205, 203, +-55, 439, 131, 531, 291, 461, 399, 265, +444, 29, 372, -175, 194, -296, -3, -310, +-173, -241, -330, -139, -413, -37, -365, 35, +-251, 59, -133, 58, 26, 50, 204, 34, +314, 33, 358, 73, 365, 125, 315, 145, +183, 136, 17, 100, -146, 16, -279, -100, +-356, -206, -364, -282, -309, -299, -180, -226, +22, -90, 225, 60, 366, 200, 430, 289, +401, 288, 254, 216, 41, 122, -143, 31, +-245, -38, -277, -58, -241, -46, -142, -59, +-35, -132, 43, -237, 90, -337, 104, -386, +67, -322, 9, -107, -7, 227, 48, 574, +128, 802, 200, 809, 241, 555, 194, 91, +49, -438, -126, -853, -269, -1013, -360, -867, +-359, -476, -248, 23, -68, 490, 117, 797, +289, 848, 409, 641, 428, 288, 349, -91, +202, -404, 7, -554, -184, -491, -310, -268, +-368, 12, -354, 247, -256, 335, -96, 224, +60, -23, 192, -275, 291, -431, 325, -412, +286, -182, 203, 194, 89, 566, -58, 779, +-178, 746, -221, 455, -194, -27, -139, -545, +-62, -908, 32, -997, 112, -786, 136, -339, +95, 194, 16, 637, -73, 860, -133, 812, +-117, 528, 5, 132, 192, -209, 371, -391, +446, -405, 353, -286, 93, -109, -245, 13, +-558, 12, -748, -95, -713, -234, -422, -307, +41, -243, 519, -36, 882, 254, 1015, 549, +851, 739, 420, 724, -128, 488, -629, 86, +-951, -393, -987, -813, -729, -1031, -287, -978, +191, -656, 587, -134, 798, 442, 772, 893, +531, 1084, 197, 969, -90, 588, -277, 68, +-373, -420, -373, -744, -297, -827, -203, -661, +-115, -332, -31, 25, 47, 293, 116, 420, +200, 381, 281, 207, 308, -1, 264, -130, +172, -131, 40, -25, -122, 130, -263, 257, +-331, 283, -285, 175, -144, -46, 26, -305, +147, -494, 195, -532, 170, -408, 86, -157, +-24, 158, -68, 440, -12, 591, 75, 570, +161, 391, 223, 106, 205, -179, 67, -372, +-128, -447, -294, -406, -391, -257, -391, -63, +-260, 88, -23, 168, 248, 189, 493, 160, +624, 101, 546, 49, 265, 22, -96, 17, +-403, 34, -578, 48, -579, 17, -390, -49, +-79, -98, 238, -118, 468, -119, 548, -84, +451, -18, 224, 42, -46, 67, -317, 55, +-509, 7, -502, -38, -276, -46, 29, -22, +305, 23, 512, 107, 563, 212, 399, 267, +115, 227, -152, 93, -380, -125, -537, -371, +-543, -549, -380, -591, -143, -467, 119, -172, +397, 246, 637, 641, 734, 867, 632, 869, +350, 648, -46, 228, -450, -305, -771, -779, +-914, -1046, -803, -1048, -445, -785, 40, -303, +537, 275, 938, 790, 1101, 1101, 921, 1115, +448, 830, -136, 337, -664, -232, -977, -745, +-944, -1055, -601, -1054, -137, -754, 300, -279, +617, 237, 712, 663, 534, 871, 209, 814, +-69, 541, -245, 152, -335, -236, -295, -501, +-100, -582, 118, -493, 221, -279, 193, -6, +92, 218, -55, 312, -188, 269, -221, 127, +-144, -40, -8, -149, 132, -147, 229, -34, +221, 131, 113, 258, -15, 261, -71, 116, +-52, -128, 13, -361, 88, -475, 119, -424, +73, -212, -33, 116, -168, 440, -281, 610, +-300, 568, -201, 349, -3, 17, 231, -328, +425, -570, 504, -637, 427, -515, 205, -238, +-93, 98, -357, 382, -492, 552, -460, 575, +-289, 448, -37, 206, 197, -86, 344, -345, +370, -499, 285, -516, 122, -411, -56, -213, +-176, 27, -200, 235, -124, 369, 3, 416, +113, 368, 157, 242, 145, 85, 78, -72, +-38, -207, -158, -275, -217, -277, -209, -258, +-146, -225, -20, -161, 138, -68, 268, 48, +336, 194, 332, 348, 236, 454, 69, 459, +-113, 336, -264, 86, -371, -233, -386, -516, +-270, -670, -71, -643, 132, -431, 297, -86, +380, 304, 339, 620, 207, 756, 43, 661, +-110, 370, -213, -17, -208, -383, -111, -623, +9, -662, 103, -482, 148, -154, 111, 177, +-20, 398, -179, 472, -282, 382, -270, 157, +-141, -96, 86, -270, 347, -326, 551, -243, +607, -46, 468, 176, 135, 329, -303, 366, +-662, 259, -804, 9, -694, -291, -387, -516, +37, -592, 453, -468, 730, -146, 776, 275, +598, 644, 275, 833, -69, 762, -337, 424, +-490, -80, -490, -573, -337, -881, -120, -920, +41, -685, 120, -241, 139, 270, 107, 676, +60, 852, 72, 775, 150, 491, 231, 89, +286, -313, 287, -601, 178, -695, -47, -572, +-309, -289, -520, 33, -596, 297, -480, 440, +-188, 428, 177, 288, 499, 99, 684, -65, +670, -162, 446, -189, 78, -164, -285, -114, +-508, -68, -528, -35, -382, -10, -140, 16, +117, 50, 293, 84, 328, 113, 221, 129, +39, 116, -131, 63, -218, -14, -186, -95, +-31, -183, 179, -240, 339, -220, 365, -119, +256, 22, 32, 169, -252, 291, -477, 353, +-521, 319, -368, 182, -104, -27, 194, -244, +445, -407, 568, -480, 508, -430, 284, -248, +-38, 24, -339, 304, -498, 515, -467, 594, +-281, 505, -8, 275, 269, -28, 435, -324, +419, -527, 249, -578, 14, -470, -207, -255, +-356, 0, -393, 224, -290, 366, -58, 411, +198, 371, 365, 278, 423, 156, 396, 21, +267, -111, 35, -232, -212, -324, -381, -362, +-447, -330, -410, -238, -286, -99, -90, 88, +150, 292, 373, 435, 499, 461, 498, 374, +384, 197, 173, -41, -82, -277, -312, -437, +-445, -462, -447, -341, -309, -128, -75, 74, +141, 204, 248, 263, 244, 245, 168, 150, +55, 35, -44, -27, -73, -27, 5, -3, +148, 15, 269, 15, 289, -14, 177, -72, +-41, -143, -304, -194, -511, -186, -561, -102, +-433, 28, -179, 149, 152, 227, 468, 262, +663, 231, 680, 119, 530, -34, 244, -154, +-93, -211, -385, -208, -566, -154, -601, -77, +-492, 7, -285, 82, -59, 105, 159, 62, +337, 17, 441, 24, 460, 55, 408, 80, +275, 103, 85, 100, -97, 35, -239, -71, +-340, -172, -373, -240, -319, -226, -205, -99, +-59, 72, 92, 195, 217, 244, 255, 218, +203, 105, 116, -61, 56, -194, 63, -232, +122, -155, 180, 6, 175, 168, 84, 244, +-106, 211, -342, 75, -521, -133, -548, -318, +-394, -363, -98, -238, 256, -8, 570, 236, +752, 409, 735, 441, 500, 297, 96, 15, +-344, -288, -679, -473, -797, -468, -654, -291, +-296, 2, 128, 316, 462, 511, 607, 488, +524, 258, 268, -77, -39, -390, -253, -557, +-314, -498, -239, -233, -83, 127, 99, 435, +251, 585, 313, 522, 231, 270, 24, -66, +-222, -364, -406, -519, -443, -489, -315, -317, +-71, -83, 206, 145, 428, 298, 509, 332, +425, 285, 230, 226, 13, 162, -168, 76, +-296, -18, -349, -122, -314, -259, -195, -390, +-49, -434, 61, -348, 115, -131, 140, 166, +133, 448, 101, 610, 101, 592, 157, 382, +218, 29, 218, -345, 146, -600, 8, -655, +-186, -501, -386, -181, -501, 193, -470, 480, +-300, 574, -44, 458, 245, 194, 512, -119, +666, -362, 645, -437, 465, -319, 173, -79, +-201, 165, -549, 310, -735, 303, -697, 150, +-475, -71, -135, -255, 226, -320, 505, -242, +632, -43, 580, 194, 385, 355, 127, 371, +-126, 234, -323, -9, -404, -270, -357, -434, +-242, -447, -99, -304, 66, -34, 190, 266, +220, 479, 191, 535, 138, 419, 51, 161, +-54, -156, -98, -424, -68, -562, -9, -541, +47, -364, 108, -73, 138, 237, 92, 468, +-16, 572, -137, 533, -232, 356, -283, 74, +-257, -242, -110, -493, 147, -600, 398, -527, +520, -294, 476, 24, 291, 326, -15, 507, +-363, 495, -605, 303, -634, 28, -450, -221, +-116, -348, 277, -287, 587, -69, 700, 175, +567, 327, 245, 302, -157, 81, -500, -257, +-658, -554, -568, -651, -264, -467, 125, -36, +451, 488, 595, 903, 515, 1033, 249, 779, +-88, 186, -372, -526, -509, -1069, -432, -1259, +-158, -1030, 168, -422, 391, 369, 446, 1039, +333, 1330, 80, 1141, -228, 553, -455, -215, +-488, -881, -289, -1224, 48, -1130, 379, -622, +579, 115, 581, 787, 372, 1139, 1, 1067, +-395, 619, -665, -43, -710, -688, -522, -1080, +-159, -1075, 268, -688, 626, -68, 809, 562, +761, 979, 472, 1055, 21, 798, -433, 300, +-728, -287, -790, -767, -641, -979, -320, -885, +96, -541, 471, -50, 661, 433, 642, 758, +467, 848, 195, 683, -109, 315, -347, -124, +-428, -484, -352, -672, -182, -642, -9, -401, +106, -53, 145, 267, 109, 447, 19, 431, +-70, 254, -95, 24, -26, -169, 116, -263, +264, -206, 328, -28, 278, 156, 136, 247, +-89, 210, -331, 52, -482, -162, -477, -337, +-336, -406, -99, -332, 175, -96, 410, 218, +545, 467, 525, 570, 355, 507, 111, 263, +-121, -102, -311, -448, -427, -648, -421, -644, +-320, -444, -182, -111, -27, 249, 128, 530, +249, 654, 321, 590, 349, 368, 319, 58, +223, -254, 84, -493, -83, -604, -250, -550, +-380, -335, -410, -22, -329, 283, -182, 484, +1, 522, 205, 388, 388, 141, 477, -114, +448, -289, 309, -329, 79, -216, -201, -20, +-440, 129, -542, 162, -472, 82, -260, -81, +17, -248, 280, -309, 456, -218, 488, -6, +385, 260, 186, 486, -64, 568, -285, 455, +-406, 176, -392, -192, -255, -539, -19, -739, +224, -722, 362, -496, 367, -119, 238, 318, +25, 685, -190, 844, -320, 746, -334, 436, +-215, 19, 10, -387, 228, -671, 347, -752, +353, -613, 241, -312, 18, 46, -232, 340, +-382, 493, -377, 501, -233, 399, -7, 224, +228, 25, 379, -134, 365, -224, 201, -264, +-20, -275, -192, -247, -270, -174, -246, -74, +-125, 48, 47, 184, 194, 278, 241, 291, +178, 228, 43, 109, -116, -33, -245, -146, +-282, -209, -172, -231, 52, -200, 280, -115, +393, -13, 343, 77, 164, 146, -75, 181, +-280, 174, -371, 129, -336, 50, -198, -35, +-6, -93, 167, -124, 260, -129, 269, -106, +219, -74, 117, -42, -20, 9, -136, 72, +-174, 113, -145, 141, -82, 155, -4, 124, +59, 51, 78, -34, 60, -129, 34, -211, +3, -231, -35, -179, -53, -77, -39, 58, +-18, 185, 2, 250, 40, 253, 96, 206, +136, 102, 141, -39, 92, -168, -10, -249, +-131, -287, -235, -282, -280, -201, -230, -33, +-78, 178, 106, 362, 261, 451, 362, 397, +370, 201, 242, -72, 13, -329, -204, -487, +-326, -483, -340, -309, -262, -31, -102, 245, +97, 424, 234, 444, 255, 306, 185, 74, +56, -157, -72, -309, -140, -339, -134, -239, +-75, -53, 45, 135, 191, 248, 244, 244, +157, 135, -12, -9, -176, -132, -291, -198, +-320, -180, -236, -92, -53, 19, 175, 117, +351, 178, 408, 167, 343, 92, 170, 1, +-63, -65, -273, -104, -398, -109, -398, -88, +-249, -61, 0, -27, 229, 6, 345, 23, +324, 33, 191, 53, 2, 85, -177, 110, +-274, 102, -238, 59, -75, -3, 124, -60, +255, -115, 275, -162, 195, -179, 36, -154, +-148, -77, -278, 47, -312, 179, -246, 276, +-96, 301, 83, 223, 211, 59, 262, -137, +258, -311, 192, -394, 68, -324, -36, -125, +-72, 106, -80, 293, -90, 383, -96, 335, +-107, 165, -152, -61, -200, -267, -182, -365, +-64, -315, 119, -171, 307, 19, 448, 218, +479, 339, 349, 327, 72, 220, -246, 61, +-489, -122, -596, -280, -544, -358, -334, -331, +-17, -188, 313, 21, 538, 213, 583, 347, +454, 394, 211, 310, -79, 121, -322, -92, +-400, -271, -290, -378, -89, -365, 82, -238, +147, -53, 83, 137, -59, 285, -179, 349, +-205, 303, -121, 153, 44, -54, 241, -234, +395, -311, 434, -275, 339, -146, 129, 42, +-145, 223, -391, 316, -517, 276, -496, 106, +-342, -140, -80, -361, 201, -453, 392, -359, +441, -86, 360, 288, 221, 595, 96, 667, +4, 458, -86, 57, -168, -401, -232, -733, +-284, -776, -312, -507, -283, -52, -159, 398, +64, 663, 310, 658, 449, 435, 445, 106, +339, -222, 144, -439, -99, -460, -291, -312, +-371, -91, -331, 103, -182, 206, -4, 218, +94, 154, 114, 19, 102, -126, 58, -182, +17, -134, 39, -20, 114, 135, 178, 276, +182, 319, 89, 239, -78, 53, -226, -218, +-310, -490, -315, -623, -202, -530, 7, -222, +225, 229, 383, 661, 437, 891, 339, 813, +92, 439, -218, -135, -476, -698, -569, -994, +-439, -920, -120, -536, 278, 25, 587, 574, +660, 883, 465, 824, 99, 461, -299, -29, +-591, -442, -649, -612, -447, -505, -100, -206, +239, 142, 475, 356, 555, 323, 457, 107, +220, -139, -62, -296, -301, -286, -448, -101, +-450, 145, -297, 320, -53, 356, 192, 243, +349, 44, 368, -141, 257, -262, 67, -295, +-139, -223, -276, -88, -264, 18, -126, 80, +36, 122, 141, 136, 165, 117, 120, 95, +48, 81, -9, 57, -35, 23, -29, -18, +-10, -74, -24, -147, -80, -200, -130, -197, +-127, -138, -60, -27, 46, 123, 133, 252, +163, 296, 163, 252, 148, 129, 114, -61, +57, -241, -47, -319, -199, -280, -329, -149, +-346, 40, -231, 212, -20, 300, 214, 294, +373, 191, 395, -11, 278, -248, 81, -416, +-105, -434, -190, -272, -172, 33, -143, 367, +-145, 605, -145, 628, -109, 383, -41, -46, +41, -473, 124, -723, 179, -695, 195, -398, +166, 28, 86, 393, 6, 576, -25, 552, +-41, 356, -98, 72, -150, -176, -155, -291, +-133, -273, -82, -180, -4, -71, 50, 2, +63, 7, 76, -36, 93, -77, 115, -77, +172, 3, 208, 159, 145, 288, -2, 304, +-178, 212, -332, 21, -393, -219, -305, -376, +-111, -350, 119, -182, 324, 30, 425, 215, +395, 290, 251, 209, 24, 33, -223, -142, +-396, -242, -444, -215, -355, -65, -113, 130, +207, 288, 438, 359, 470, 283, 307, 56, +24, -211, -277, -406, -453, -478, -424, -397, +-207, -148, 86, 186, 306, 455, 377, 547, +308, 417, 165, 121, 2, -201, -151, -416, +-254, -448, -275, -264, -208, 54, -67, 333, +112, 432, 237, 294, 218, -39, 72, -395, +-111, -561, -244, -463, -249, -155, -88, 250, +165, 602, 372, 746, 439, 602, 319, 207, +52, -284, -244, -668, -448, -812, -517, -688, +-454, -351, -248, 101, 73, 534, 395, 791, +575, 760, 551, 464, 361, 36, 54, -377, +-263, -655, -446, -706, -425, -515, -243, -159, +-8, 242, 169, 547, 206, 641, 122, 501, +-15, 200, -131, -168, -155, -479, -78, -607, +48, -502, 175, -217, 280, 134, 310, 427, +234, 564, 77, 496, -148, 249, -380, -67, +-518, -326, -473, -456, -248, -421, 62, -243, +323, -11, 430, 192, 370, 306, 191, 281, +-8, 148, -104, 3, -77, -103, -4, -151, +43, -97, 34, 24, -30, 113, -117, 134, +-171, 91, -181, -31, -170, -175, -173, -266, +-163, -288, -58, -220, 144, -52, 382, 154, +576, 334, 624, 475, 441, 502, 74, 350, +-332, 72, -668, -255, -826, -577, -738, -766, +-453, -710, -74, -423, 313, 18, 616, 496, +761, 839, 755, 913, 568, 710, 195, 285, +-209, -244, -484, -677, -607, -858, -601, -772, +-453, -475, -223, -44, -21, 368, 115, 604, +201, 615, 279, 448, 356, 176, 398, -102, +362, -288, 238, -341, 66, -274, -120, -128, +-291, 21, -425, 112, -477, 130, -404, 84, +-247, -8, -42, -92, 184, -115, 391, -84, +506, -8, 484, 93, 311, 171, 32, 192, +-229, 164, -393, 80, -422, -45, -282, -153, +-53, -210, 120, -229, 177, -204, 158, -112, +76, 19, -21, 145, -60, 240, -51, 275, +-8, 217, 49, 81, 71, -71, 53, -192, +53, -246, 68, -198, 43, -63, 8, 73, +-46, 157, -152, 165, -220, 82, -178, -46, +-99, -118, -27, -112, 93, -67, 212, 14, +228, 104, 159, 133, 52, 84, -49, -9, +-110, -107, -114, -142, -83, -71, -12, 53, +96, 163, 150, 229, 97, 200, -34, 41, +-186, -196, -310, -410, -356, -499, -243, -399, +19, -120, 328, 248, 552, 584, 585, 767, +399, 709, 81, 399, -236, -81, -482, -581, +-593, -918, -514, -946, -294, -648, -32, -151, +197, 362, 371, 742, 441, 851, 398, 635, +275, 224, 101, -165, -54, -387, -155, -389, +-198, -205, -205, 11, -205, 119, -223, 80, +-241, -110, -184, -377, -65, -512, 73, -389, +239, -86, 402, 306, 468, 697, 378, 907, +191, 824, -29, 483, -244, -46, -409, -610, +-502, -989, -472, -1069, -292, -871, -8, -423, +271, 152, 448, 656, 483, 954, 368, 973, +146, 693, -109, 245, -287, -179, -317, -504, +-234, -674, -101, -619, -8, -375, 15, -69, +24, 199, 80, 330, 145, 265, 155, 89, +132, -74, 68, -175, -67, -160, -207, 24, +-243, 288, -170, 466, -61, 456, 78, 246, +204, -107, 232, -459, 166, -653, 82, -633, +24, -430, -38, -96, -116, 259, -221, 491, +-334, 557, -355, 492, -244, 323, -21, 101, +265, -99, 543, -245, 669, -335, 555, -354, +260, -303, -149, -210, -563, -84, -798, 53, +-746, 151, -470, 204, -75, 219, 360, 196, +669, 161, 723, 138, 515, 104, 144, 34, +-213, -71, -412, -213, -419, -366, -301, -442, +-107, -368, 88, -137, 195, 201, 210, 499, +147, 600, 19, 477, -131, 217, -229, -105, +-266, -399, -213, -538, 16, -476, 325, -276, +498, -18, 444, 224, 242, 371, -29, 410, +-320, 361, -506, 206, -528, -38, -395, -261, +-168, -384, 57, -395, 232, -284, 363, -98, +455, 81, 427, 229, 269, 343, 79, 366, +-106, 283, -241, 140, -293, -58, -308, -273, +-357, -413, -369, -436, -235, -324, 6, -56, +279, 269, 502, 474, 576, 499, 431, 354, +98, 36, -251, -328, -435, -540, -381, -528, +-193, -312, 6, 64, 149, 449, 171, 662, +95, 619, -12, 322, -107, -142, -186, -573, +-204, -780, -120, -713, 37, -408, 245, 51, +417, 519, 437, 825, 273, 854, -22, 592, +-342, 127, -558, -371, -559, -737, -372, -849, +-90, -673, 206, -262, 402, 227, 440, 587, +344, 674, 180, 491, -25, 166, -219, -144, +-305, -323, -232, -328, -36, -188, 144, -1, +210, 120, 148, 123, -23, 50, -222, -48, +-355, -119, -351, -117, -202, -56, 66, 18, +335, 93, 459, 156, 440, 148, 316, 75, +109, -4, -130, -75, -330, -133, -441, -146, +-431, -113, -283, -40, -78, 86, 119, 200, +271, 205, 303, 111, 221, -37, 90, -223, +-31, -357, -95, -332, -47, -137, 73, 177, +150, 485, 135, 597, -14, 437, -256, 92, +-427, -327, -438, -674, -293, -747, -15, -491, +319, -53, 508, 417, 485, 764, 329, 801, +93, 487, -128, -3, -246, -476, -277, -768, +-264, -741, -202, -422, -116, 18, -39, 419, +63, 659, 133, 642, 106, 407, 39, 97, +-5, -204, -14, -452, 47, -569, 173, -529, +230, -357, 156, -61, 2, 295, -199, 564, +-347, 631, -343, 471, -207, 128, -39, -247, +113, -473, 231, -482, 276, -293, 261, 14, +167, 263, -21, 308, -236, 164, -363, -77, +-323, -312, -135, -408, 155, -277, 412, 36, +480, 419, 285, 714, -81, 746, -419, 452, +-607, -67, -555, -624, -259, -993, 123, -997, +434, -637, 621, -61, 650, 530, 448, 921, +90, 966, -295, 693, -629, 249, -763, -208, +-608, -567, -264, -752, 117, -704, 447, -411, +608, 32, 522, 436, 291, 644, 5, 574, +-264, 251, -402, -188, -368, -545, -230, -657, +-38, -449, 190, 17, 327, 539, 288, 875, +110, 848, -153, 459, -378, -131, -443, -722, +-299, -1130, -20, -1172, 269, -762, 464, -14, +496, 797, 357, 1344, 79, 1395, -236, 949, +-463, 177, -528, -687, -417, -1327, -206, -1447, +36, -1018, 264, -241, 419, 620, 418, 1251, +286, 1392, 127, 994, -53, 208, -248, -682, +-377, -1327, -375, -1459, -241, -1012, -18, -120, +206, 879, 300, 1551, 260, 1619, 125, 1071, +-72, 94, -225, -963, -260, -1672, -188, -1771, +-59, -1239, 98, -243, 217, 858, 249, 1640, +231, 1826, 157, 1354, -6, 389, -231, -688, +-423, -1456, -469, -1659, -312, -1254, -25, -390, +242, 589, 412, 1276, 447, 1421, 319, 1020, +81, 256, -176, -589, -359, -1206, -395, -1340, +-279, -928, -102, -136, 72, 728, 227, 1339, +274, 1468, 172, 1032, 8, 158, -129, -834, +-189, -1535, -128, -1666, 15, -1188, 103, -280, +97, 739, 51, 1517, -11, 1765, -75, 1376, +-106, 477, -102, -587, -108, -1392, -104, -1641, +-49, -1289, 19, -496, 90, 444, 180, 1166, +240, 1392, 167, 1071, -3, 368, -138, -430, +-216, -1006, -232, -1152, -177, -878, -102, -299, +-39, 400, 71, 950, 216, 1130, 250, 895, +179, 326, 86, -399, -43, -968, -178, -1137, +-216, -900, -182, -381, -168, 261, -122, 788, +-31, 988, 40, 836, 130, 417, 267, -129, +345, -568, 272, -723, 83, -601, -193, -276, +-459, 154, -521, 491, -377, 547, -151, 323, +106, -56, 339, -444, 455, -643, 454, -497, +354, -79, 80, 386, -290, 728, -538, 822, +-594, 588, -487, 105, -207, -428, 175, -841, +460, -975, 551, -732, 464, -237, 232, 304, +-57, 766, -296, 969, -443, 751, -497, 256, +-399, -253, -122, -645, 231, -782, 511, -558, +586, -123, 419, 295, 54, 594, -367, 648, +-654, 390, -713, 1, -517, -358, -101, -668, +365, -762, 668, -493, 755, -11, 661, 487, +326, 893, -198, 1011, -677, 703, -917, 136, +-877, -455, -554, -947, -39, -1149, 448, -918, +776, -395, 885, 222, 694, 794, 264, 1098, +-192, 999, -516, 610, -694, 71, -682, -518, +-459, -931, -147, -955, 135, -647, 346, -169, +440, 365, 384, 732, 257, 752, 137, 506, +-16, 118, -195, -339, -297, -665, -291, -680, +-222, -419, -80, 1, 92, 481, 148, 812, +87, 792, 11, 464, -74, -52, -148, -633, +-79, -1009, 87, -986, 142, -623, 99, -36, +37, 619, -71, 1058, -141, 1084, -92, 762, +-19, 229, 18, -385, 87, -859, 89, -993, +-58, -794, -156, -369, -142, 153, -162, 575, +-155, 743, -11, 643, 122, 351, 164, -19, +217, -343, 227, -525, 115, -513, -18, -309, +-108, 25, -207, 360, -279, 558, -263, 557, +-229, 343, -181, -43, -63, -475, 65, -790, +159, -834, 271, -537, 383, 1, 371, 582, +245, 1008, 93, 1106, -138, 805, -424, 189, +-582, -529, -541, -1075, -398, -1218, -164, -901, +142, -274, 333, 412, 361, 901, 373, 991, +359, 672, 235, 159, 107, -327, 4, -605, +-201, -551, -414, -260, -478, 66, -427, 333, +-291, 453, -62, 333, 130, 43, 192, -248, +224, -485, 224, -618, 148, -519, 142, -212, +216, 196, 172, 681, -11, 1065, -179, 1065, +-290, 679, -363, 66, -364, -667, -308, -1315, +-226, -1586, -88, -1333, 107, -612, 295, 394, +432, 1333, 501, 1828, 445, 1733, 229, 1097, +-101, 52, -405, -1048, -545, -1753, -497, -1818, +-316, -1253, -129, -269, 4, 752, 122, 1408, +200, 1502, 183, 1070, 116, 249, 106, -653, +107, -1199, 70, -1185, 71, -718, 80, 25, +10, 781, -84, 1200, -178, 1108, -334, 578, +-452, -215, -403, -997, -226, -1411, 35, -1292, +319, -729, 501, 146, 529, 1053, 439, 1604, +190, 1620, -193, 1108, -467, 135, -525, -957, +-466, -1671, -310, -1794, -60, -1339, 185, -388, +318, 718, 317, 1498, 200, 1734, 14, 1387, +-158, 511, -241, -519, -197, -1253, -69, -1522, +72, -1287, 201, -560, 253, 376, 144, 1119, +-56, 1441, -229, 1237, -355, 518, -362, -416, +-205, -1150, -26, -1446, 88, -1205, 185, -449, +246, 531, 195, 1290, 76, 1531, -24, 1177, +-99, 326, -95, -677, -23, -1392, 16, -1562, +20, -1136, 9, -221, -83, 828, -262, 1525, +-399, 1586, -403, 1024, -252, 50, 39, -963, +379, -1589, 632, -1578, 705, -943, 546, 104, +175, 1134, -291, 1671, -728, 1527, -984, 818, +-887, -229, -464, -1229, 91, -1714, 579, -1500, +842, -723, 794, 362, 449, 1325, -34, 1690, +-444, 1344, -621, 534, -522, -463, -251, -1305, +64, -1574, 312, -1152, 393, -313, 291, 617, +49, 1297, -281, 1409, -569, 924, -659, 87, +-483, -814, -54, -1432, 481, -1406, 858, -725, +908, 240, 639, 1152, 92, 1717, -582, 1562, +-1023, 649, -1033, -570, -718, -1617, -203, -2098, +347, -1727, 685, -590, 736, 843, 588, 1988, +278, 2398, -149, 1845, -491, 497, -617, -1050, +-544, -2179, -258, -2486, 160, -1797, 481, -373, +573, 1164, 416, 2229, 9, 2430, -474, 1664, +-767, 246, -747, -1215, -425, -2169, 92, -2337, +592, -1624, 835, -257, 779, 1168, 497, 2131, +20, 2341, -508, 1660, -857, 352, -916, -1031, +-677, -2032, -213, -2321, 291, -1735, 625, -481, +695, 885, 502, 1849, 132, 2135, -217, 1632, +-390, 553, -378, -602, -237, -1491, -59, -1869, +50, -1511, 61, -593, 57, 403, 64, 1166, +17, 1531, -56, 1316, -68, 612, -80, -207, +-138, -860, -115, -1202, 0, -1071, 60, -541, +22, 43, -9, 478, 19, 698, 66, 638, +142, 386, 200, 131, 141, -30, -36, -78, +-285, -46, -514, -22, -559, -94, -374, -276, +-78, -504, 222, -678, 452, -650, 529, -321, +465, 207, 336, 783, 128, 1281, -169, 1454, +-442, 1115, -621, 335, -690, -668, -556, -1572, +-199, -2011, 223, -1794, 512, -1003, 580, 105, +456, 1226, 221, 1984, -28, 2049, -257, 1441, +-401, 444, -342, -601, -132, -1334, 63, -1527, +166, -1216, 156, -629, 18, -2, -207, 475, +-391, 611, -411, 410, -253, 153, 53, 22, +410, 46, 591, 238, 513, 478, 308, 590, +32, 522, -313, 234, -618, -298, -750, -916, +-673, -1316, -350, -1304, 177, -900, 602, -190, +715, 636, 591, 1321, 273, 1683, -188, 1543, +-540, 860, -609, -69, -486, -878, -230, -1379, +115, -1455, 341, -1057, 386, -337, 376, 396, +270, 856, -29, 866, -387, 488, -635, 1, +-666, -364, -424, -461, -11, -191, 385, 306, +622, 740, 644, 893, 456, 612, 142, -59, +-196, -803, -503, -1295, -656, -1377, -583, -992, +-404, -259, -179, 556, 102, 1231, 346, 1533, +441, 1273, 366, 610, 197, -139, 78, -794, +67, -1133, 68, -985, -16, -497, -209, 52, +-473, 467, -669, 554, -638, 248, -385, -199, +3, -484, 439, -510, 747, -229, 827, 325, +691, 877, 293, 1145, -260, 984, -703, 398, +-933, -411, -955, -1165, -651, -1608, -38, -1486, +549, -783, 895, 188, 930, 1079, 529, 1618, +-113, 1575, -567, 928, -784, -1, -814, -855, +-508, -1395, 37, -1391, 511, -804, 808, 89, +861, 925, 541, 1352, -47, 1182, -640, 551, +-1088, -323, -1204, -1169, -824, -1566, -121, -1287, +606, -495, 1122, 506, 1226, 1348, 878, 1694, +232, 1437, -475, 683, -999, -303, -1145, -1145, +-891, -1557, -365, -1459, 244, -885, 676, -15, +762, 786, 569, 1228, 173, 1246, -305, 802, +-591, 34, -568, -624, -320, -926, 73, -859, +411, -410, 490, 213, 344, 667, 79, 822, +-288, 629, -635, 125, -706, -440, -450, -772, +-12, -811, 445, -604, 680, -133, 580, 423, +283, 770, -114, 851, -559, 618, -822, 88, +-697, -414, -267, -691, 237, -721, 635, -414, +826, 85, 770, 500, 431, 755, -179, 776, +-846, 402, -1265, -301, -1266, -953, -806, -1222, +-12, -1098, 803, -605, 1317, 207, 1350, 1096, +962, 1729, 314, 1767, -435, 1147, -1032, 151, +-1259, -914, -1085, -1701, -666, -1924, -159, -1597, +378, -807, 798, 267, 918, 1222, 703, 1708, +239, 1608, -264, 1000, -567, 117, -611, -692, +-440, -1124, -114, -1115, 193, -723, 335, -31, +333, 631, 242, 919, 27, 753, -314, 208, +-621, -464, -716, -937, -546, -1112, -172, -935, +318, -308, 818, 584, 1060, 1338, 837, 1693, +242, 1538, -435, 810, -905, -265, -1023, -1212, +-823, -1737, -424, -1794, 55, -1360, 476, -519, +669, 461, 609, 1255, 384, 1576, -20, 1381, +-478, 873, -654, 219, -492, -442, -162, -880, +261, -935, 631, -637, 718, -193, 447, 157, +-63, 293, -617, 180, -1023, -78, -1106, -285, +-830, -350, -282, -247, 408, 37, 1049, 425, +1424, 790, 1335, 943, 742, 787, -134, 379, +-989, -230, -1556, -873, -1585, -1281, -1065, -1335, +-306, -1009, 446, -346, 1068, 425, 1295, 1038, +990, 1347, 409, 1284, -219, 843, -749, 195, +-877, -380, -608, -765, -257, -898, 116, -759, +447, -508, 441, -235, 76, 51, -295, 162, +-493, 76, -521, 77, -269, 267, 156, 497, +436, 692, 551, 791, 566, 613, 355, 152, +-66, -406, -465, -959, -686, -1377, -687, -1348, +-495, -818, -178, -53, 179, 749, 442, 1425, +472, 1661, 274, 1307, 11, 552, -176, -378, +-235, -1192, -142, -1530, 66, -1301, 274, -692, +289, 95, 72, 796, -204, 1114, -483, 997, +-766, 640, -830, 146, -499, -470, 68, -910, +640, -911, 1103, -577, 1232, -84, 843, 439, +134, 769, -610, 776, -1199, 529, -1372, 121, +-1113, -354, -643, -603, 29, -478, 768, -284, +1137, -140, 1042, 66, 733, 129, 246, -30, +-427, -98, -887, -14, -858, 101, -529, 329, +-84, 663, 319, 810, 437, 585, 228, 79, +-109, -617, -431, -1286, -604, -1536, -445, -1287, +-12, -650, 442, 375, 822, 1454, 1045, 2048, +856, 2006, 191, 1368, -643, 199, -1294, -1146, +-1582, -2129, -1394, -2468, -691, -2078, 255, -947, +1061, 594, 1579, 1915, 1629, 2602, 1089, 2483, +238, 1519, -588, 40, -1268, -1394, -1620, -2325, +-1408, -2501, -759, -1935, -32, -799, 625, 627, +1049, 1823, 1027, 2355, 690, 2167, 304, 1363, +-90, 150, -400, -1084, -468, -1922, -389, -2093, +-288, -1598, -139, -696, -74, 269, -273, 1031, +-532, 1467, -524, 1466, -255, 1014, 190, 407, +779, -143, 1278, -620, 1314, -874, 809, -840, +24, -651, -861, -392, -1628, -144, -1905, 37, +-1611, 184, -917, 346, 55, 508, 1112, 581, +1895, 544, 2145, 403, 1818, 123, 923, -156, +-338, -345, -1480, -520, -2177, -576, -2348, -497, +-1839, -380, -766, -177, 390, 81, 1376, 286, +2040, 444, 2074, 524, 1477, 487, 612, 345, +-349, 174, -1292, 76, -1797, -22, -1702, -184, +-1281, -381, -656, -586, 154, -732, 837, -749, +1112, -564, 1108, -108, 991, 475, 708, 1006, +259, 1385, -252, 1409, -726, 974, -1035, 201, +-1113, -724, -989, -1564, -662, -2001, -154, -1815, +407, -1064, 848, 1, 1024, 1138, 971, 1993, +746, 2223, 342, 1824, -144, 948, -637, -239, +-1050, -1398, -1199, -2142, -1026, -2282, -658, -1769, +-149, -718, 476, 574, 959, 1689, 1091, 2227, +979, 2058, 658, 1304, 84, 166, -458, -988, +-726, -1694, -848, -1782, -808, -1356, -510, -555, +-224, 400, -73, 1100, 163, 1238, 360, 919, +253, 374, 139, -266, 261, -751, 345, -795, +344, -412, 422, 162, 406, 657, 79, 898, +-422, 769, -940, 258, -1420, -451, -1544, -1119, +-1042, -1495, -149, -1347, 819, -676, 1678, 322, +2111, 1346, 1862, 1995, 1045, 2032, -75, 1417, +-1269, 270, -2230, -1018, -2543, -2008, -2064, -2423, +-1024, -2071, 332, -1005, 1702, 345, 2565, 1509, +2553, 2237, 1716, 2338, 351, 1643, -1155, 396, +-2284, -887, -2628, -1871, -2137, -2270, -984, -1846, +483, -818, 1750, 351, 2360, 1369, 2127, 1976, +1158, 1906, -193, 1196, -1396, 128, -2012, -1014, +-1947, -1853, -1279, -2025, -213, -1496, 821, -471, +1429, 762, 1505, 1784, 1112, 2173, 410, 1773, +-390, 725, -1050, -562, -1343, -1581, -1142, -2019, +-486, -1823, 293, -1042, 843, 51, 1077, 1064, +901, 1759, 245, 1932, -578, 1466, -1090, 524, +-1139, -544, -792, -1407, -113, -1887, 638, -1868, +1090, -1210, 1129, -98, 795, 1026, 139, 1844, +-601, 2109, -1092, 1701, -1214, 795, -976, -295, +-388, -1334, 316, -2060, 750, -2117, 830, -1507, +671, -626, 285, 400, -186, 1463, -457, 2095, +-438, 2087, -277, 1593, -104, 694, 90, -469, +236, -1527, 203, -2149, 16, -2197, -249, -1658, +-492, -604, -546, 654, -393, 1741, -149, 2337, +173, 2164, 510, 1292, 637, 59, 521, -1225, +362, -2099, 175, -2174, -150, -1513, -462, -373, +-607, 900, -696, 1838, -690, 2110, -438, 1614, +-76, 477, 180, -863, 348, -1868, 479, -2240, +537, -1884, 550, -814, 478, 674, 244, 1986, +-78, 2678, -453, 2518, -827, 1451, -966, -186, +-755, -1783, -362, -2848, 30, -3040, 397, -2270, +664, -788, 669, 1001, 494, 2511, 310, 3181, +57, 2865, -310, 1735, -594, 64, -656, -1683, +-546, -2887, -320, -3094, 70, -2292, 500, -771, +656, 1001, 525, 2327, 284, 2755, -94, 2296, +-594, 1109, -940, -450, -939, -1778, -679, -2434, +-214, -2248, 448, -1318, 1095, 48, 1410, 1408, +1234, 2257, 672, 2358, -80, 1724, -874, 493, +-1506, -917, -1755, -1978, -1573, -2417, -1014, -2162, +-127, -1295, 885, -50, 1666, 1163, 1986, 1964, +1815, 2251, 1143, 1987, 67, 1198, -1029, 180, +-1815, -780, -2079, -1518, -1698, -1879, -906, -1819, +-41, -1397, 788, -781, 1405, -125, 1493, 593, +1046, 1299, 417, 1780, -153, 1950, -585, 1806, +-724, 1277, -546, 339, -281, -824, -94, -1865, +-1, -2544, -41, -2713, -222, -2224, -448, -1113, +-540, 354, -338, 1827, 124, 2937, 629, 3344, +983, 2898, 1117, 1691, 929, 10, 345, -1707, +-482, -2967, -1221, -3476, -1579, -3160, -1510, -2027, +-1082, -327, -335, 1379, 550, 2621, 1284, 3246, +1651, 3115, 1586, 2150, 1122, 615, 311, -968, +-658, -2173, -1431, -2790, -1780, -2719, -1679, -1967, +-1133, -794, -277, 461, 579, 1537, 1184, 2172, +1459, 2226, 1388, 1769, 965, 955, 364, -27, +-209, -951, -752, -1592, -1212, -1786, -1402, -1538, +-1284, -956, -945, -219, -373, 453, 373, 959, +1040, 1226, 1470, 1215, 1626, 991, 1401, 636, +741, 216, -228, -200, -1261, -664, -2032, -1163, +-2244, -1471, -1806, -1429, -821, -1098, 504, -459, +1782, 582, 2482, 1708, 2365, 2364, 1584, 2365, +291, 1724, -1217, 488, -2359, -997, -2735, -2321, +-2337, -3157, -1270, -3064, 315, -1926, 1942, -247, +2886, 1453, 2794, 2898, 1833, 3620, 321, 3200, +-1370, 1798, -2724, -46, -3185, -1841, -2518, -3114, +-1035, -3473, 678, -2821, 2137, -1386, 2954, 377, +2795, 1908, 1656, 2782, -11, 2830, -1592, 2064, +-2613, 740, -2778, -669, -2050, -1688, -681, -2022, +825, -1713, 1948, -979, 2379, -12, 2029, 821, +1024, 1111, -298, 901, -1479, 451, -2066, -109, +-1903, -559, -1156, -592, -105, -263, 894, 141, +1475, 544, 1520, 812, 1154, 671, 496, 236, +-369, -259, -1128, -825, -1406, -1222, -1260, -1145, +-901, -681, -266, -9, 545, 731, 1093, 1329, +1196, 1615, 1007, 1401, 586, 599, 3, -477, +-500, -1308, -845, -1715, -1111, -1764, -1169, -1261, +-863, -204, -270, 897, 438, 1655, 1074, 1935, +1373, 1648, 1202, 951, 676, 58, -55, -932, +-800, -1737, -1284, -2026, -1364, -1769, -1069, -1133, +-493, -207, 184, 855, 801, 1754, 1250, 2244, +1336, 2191, 943, 1544, 205, 473, -615, -771, +-1234, -1912, -1409, -2547, -1065, -2457, -404, -1754, +276, -614, 810, 688, 1062, 1747, 949, 2341, +545, 2362, -26, 1772, -606, 814, -982, -196, +-993, -1149, -643, -1896, -78, -2138, 486, -1802, +877, -1108, 945, -249, 559, 662, -132, 1390, +-680, 1686, -878, 1528, -836, 1069, -556, 466, +-5, -192, 566, -733, 844, -945, 774, -891, +452, -745, -65, -473, -614, -169, -865, -36, +-693, -27, -267, 12, 181, 125, 519, 332, +661, 649, 470, 953, -15, 1032, -496, 836, +-756, 402, -761, -285, -488, -1050, -2, -1614, +557, -1800, 1043, -1506, 1207, -776, 844, 221, +73, 1269, -777, 2031, -1427, 2256, -1651, 1905, +-1288, 1012, -471, -205, 473, -1359, 1281, -2112, +1702, -2319, 1548, -1947, 889, -1096, -7, 14, +-909, 1125, -1596, 1958, -1790, 2206, -1376, 1832, +-484, 1113, 573, 230, 1394, -708, 1679, -1512, +1333, -1947, 526, -1815, -383, -1213, -1092, -485, +-1447, 266, -1352, 1068, -816, 1652, -27, 1744, +738, 1416, 1207, 805, 1265, 7, 945, -732, +337, -1244, -374, -1532, -931, -1494, -1116, -1046, +-941, -408, -598, 222, -220, 853, 131, 1334, +414, 1475, 581, 1320, 606, 916, 542, 230, +457, -532, 308, -1094, 52, -1412, -203, -1500, +-399, -1254, -629, -630, -836, 172, -855, 859, +-708, 1288, -435, 1432, 41, 1258, 666, 789, +1181, 140, 1390, -465, 1265, -847, 785, -974, +-23, -934, -886, -804, -1494, -539, -1746, -165, +-1581, 149, -965, 360, -45, 540, 853, 694, +1484, 830, 1761, 849, 1592, 621, 928, 225, +-62, -187, -1053, -578, -1681, -916, -1706, -1095, +-1211, -1002, -455, -638, 382, -183, 1081, 199, +1327, 555, 1037, 941, 445, 1101, -196, 894, +-715, 576, -937, 269, -782, -146, -347, -550, +183, -744, 629, -781, 839, -728, 691, -564, +207, -330, -428, -91, -959, 137, -1177, 334, +-1012, 497, -488, 605, 281, 632, 1061, 637, +1588, 642, 1644, 502, 1144, 150, 229, -275, +-847, -737, -1803, -1224, -2334, -1511, -2215, -1393, +-1412, -897, -88, -111, 1376, 784, 2527, 1529, +3018, 1982, 2655, 2007, 1462, 1476, -254, 526, +-1990, -581, -3259, -1583, -3652, -2137, -2946, -2086, +-1365, -1549, 559, -660, 2348, 391, 3582, 1207, +3801, 1525, 2847, 1457, 1095, 1122, -882, 585, +-2596, 71, -3606, -278, -3588, -486, -2508, -515, +-736, -431, 1106, -422, 2485, -536, 3089, -721, +2790, -859, 1721, -763, 249, -350, -1195, 308, +-2198, 1088, -2475, 1769, -1971, 2064, -891, 1784, +403, 951, 1474, -270, 1909, -1541, 1603, -2444, +781, -2764, -307, -2391, -1334, -1284, -1848, 236, +-1617, 1649, -798, 2608, 290, 2851, 1359, 2297, +2088, 1194, 2154, -65, 1456, -1162, 234, -1847, +-1124, -2015, -2283, -1745, -2890, -1186, -2663, -572, +-1602, -80, -27, 346, 1605, 806, 2837, 1190, +3339, 1457, 2947, 1661, 1733, 1652, 23, 1226, +-1701, 389, -3003, -738, -3585, -1903, -3255, -2714, +-2019, -2925, -245, -2428, 1538, -1229, 2908, 365, +3477, 1887, 3052, 3054, 1834, 3613, 243, 3276, +-1300, 2056, -2400, 355, -2790, -1438, -2474, -3018, +-1618, -3915, -432, -3764, 751, -2641, 1533, -911, +1776, 1009, 1595, 2663, 1112, 3617, 488, 3597, +-51, 2667, -405, 1164, -632, -517, -795, -1947, +-928, -2783, -1000, -2863, -907, -2226, -607, -1135, +-181, 55, 366, 1074, 989, 1715, 1419, 1862, +1433, 1561, 1140, 977, 636, 266, -201, -418, +-1187, -874, -1850, -1048, -1991, -999, -1651, -697, +-796, -214, 438, 183, 1613, 446, 2308, 630, +2326, 625, 1624, 399, 365, 87, -1035, -224, +-2151, -516, -2681, -703, -2415, -704, -1368, -490, +111, -64, 1562, 497, 2558, 1021, 2793, 1362, +2188, 1360, 945, 933, -559, 202, -1911, -713, +-2717, -1678, -2736, -2327, -2023, -2327, -858, -1710, +455, -621, 1665, 789, 2508, 2138, 2739, 3012, +2251, 3243, 1185, 2727, -91, 1423, -1305, -355, +-2335, -2094, -2889, -3425, -2683, -4046, -1841, -3675, +-653, -2335, 765, -355, 2120, 1762, 2919, 3442, +2989, 4267, 2432, 4076, 1258, 2896, -306, 1026, +-1684, -1014, -2604, -2750, -3032, -3760, -2768, -3806, +-1796, -2986, -507, -1591, 783, 71, 1947, 1586, +2691, 2568, 2726, 2925, 2123, 2716, 1126, 1941, +-10, 799, -1027, -314, -1740, -1209, -2085, -1806, +-2064, -1996, -1737, -1806, -1212, -1347, -499, -677, +366, 27, 1200, 563, 1846, 992, 2254, 1403, +2295, 1561, 1829, 1321, 937, 908, -201, 386, +-1435, -348, -2561, -1080, -3229, -1480, -3121, -1524, +-2199, -1246, -673, -617, 1126, 225, 2765, 949, +3779, 1325, 3784, 1304, 2728, 884, 993, 160, +-930, -603, -2665, -1058, -3785, -1053, -3829, -701, +-2801, -138, -1161, 539, 671, 1058, 2332, 1115, +3312, 762, 3277, 265, 2432, -298, 1121, -898, +-411, -1263, -1767, -1197, -2516, -825, -2560, -332, +-2076, 237, -1229, 763, -155, 1076, 941, 1160, +1777, 1094, 2103, 857, 1912, 440, 1353, -51, +529, -551, -422, -1021, -1257, -1367, -1729, -1468, +-1800, -1294, -1517, -868, -915, -243, -87, 482, +764, 1192, 1402, 1775, 1671, 2047, 1533, 1862, +1069, 1260, 396, 329, -331, -766, -941, -1727, +-1304, -2299, -1380, -2362, -1226, -1869, -878, -964, +-330, 46, 302, 937, 823, 1622, 1148, 1973, +1274, 1889, 1152, 1496, 776, 966, 286, 385, +-211, -197, -650, -765, -1013, -1316, -1293, -1760, +-1375, -2005, -1089, -1972, -504, -1551, 106, -697, +696, 466, 1309, 1707, 1673, 2753, 1527, 3248, +1030, 2942, 398, 1885, -360, 343, -1147, -1378, +-1683, -2883, -1764, -3707, -1391, -3553, -733, -2478, +33, -838, 784, 944, 1359, 2430, 1582, 3215, +1393, 3103, 925, 2243, 297, 938, -386, -448, +-943, -1518, -1250, -2041, -1280, -2003, -1015, -1484, +-504, -673, 59, 102, 518, 574, 816, 713, +911, 674, 802, 524, 548, 284, 203, 97, +-154, 135, -416, 299, -531, 333, -533, 202, +-466, -15, -380, -315, -309, -588, -208, -676, +-32, -615, 208, -376, 450, 124, 716, 640, +968, 816, 989, 649, 610, 285, -87, -252, +-847, -825, -1499, -1134, -1876, -987, -1714, -403, +-920, 461, 243, 1278, 1402, 1787, 2255, 1828, +2535, 1254, 2098, 144, 1085, -1094, -246, -2068, +-1638, -2540, -2722, -2381, -3071, -1612, -2567, -382, +-1450, 979, 57, 2039, 1652, 2575, 2804, 2657, +3130, 2261, 2712, 1318, 1742, 86, 345, -1104, +-1126, -2140, -2221, -2821, -2721, -2885, -2634, -2381, +-2024, -1412, -1040, -85, 101, 1270, 1168, 2310, +1879, 2903, 2084, 2913, 1965, 2285, 1655, 1245, +1055, 47, 232, -1151, -558, -2078, -1213, -2486, +-1747, -2432, -2032, -1995, -1960, -1222, -1533, -315, +-804, 517, 113, 1207, 1010, 1656, 1731, 1811, +2204, 1758, 2287, 1542, 1907, 1176, 1155, 710, +170, 137, -908, -596, -1826, -1388, -2338, -2111, +-2411, -2667, -2153, -2831, -1556, -2344, -575, -1238, +625, 265, 1692, 1958, 2425, 3475, 2807, 4333, +2720, 4210, 2025, 3104, 819, 1194, -568, -1170, +-1868, -3413, -2893, -4837, -3405, -5078, -3175, -4179, +-2206, -2320, -716, 137, 1004, 2489, 2541, 4042, +3438, 4534, 3486, 4022, 2797, 2684, 1548, 855, +-32, -925, -1529, -2192, -2522, -2771, -2923, -2734, +-2803, -2242, -2154, -1506, -1049, -791, 210, -201, +1279, 353, 2017, 897, 2336, 1368, 2172, 1812, +1597, 2165, 814, 2171, -39, 1672, -890, 782, +-1533, -359, -1780, -1608, -1666, -2616, -1321, -3033, +-799, -2786, -155, -1944, 474, -603, 938, 924, +1200, 2179, 1317, 2861, 1307, 2912, 1070, 2329, +563, 1206, -107, -98, -757, -1195, -1241, -1903, +-1482, -2142, -1431, -1907, -1101, -1368, -483, -698, +278, 11, 911, 615, 1276, 959, 1396, 1130, +1224, 1248, 685, 1192, -45, 892, -641, 480, +-949, 46, -996, -407, -816, -825, -472, -1143, +-75, -1254, 276, -1063, 505, -624, 499, -120, +290, 346, 36, 736, -193, 941, -353, 874, +-276, 606, 101, 318, 508, 154, 749, 127, +820, 113, 631, 23, 38, -174, -762, -495, +-1401, -923, -1745, -1318, -1692, -1434, -1074, -1092, +42, -311, 1305, 727, 2331, 1775, 2804, 2514, +2509, 2629, 1469, 1947, -42, 589, -1661, -1055, +-2949, -2482, -3490, -3262, -3098, -3162, -1900, -2186, +-200, -611, 1595, 1093, 2965, 2460, 3562, 3156, +3303, 3003, 2276, 2107, 672, 776, -1061, -672, +-2390, -1888, -3051, -2473, -3030, -2333, -2356, -1701, +-1180, -786, 121, 195, 1210, 890, 1970, 1115, +2289, 1034, 2048, 827, 1397, 592, 669, 457, +84, 500, -402, 584, -800, 522, -1028, 236, +-1158, -282, -1349, -995, -1540, -1729, -1457, -2141, +-1003, -2012, -260, -1330, 674, -189, 1683, 1177, +2511, 2363, 2879, 3040, 2618, 3024, 1662, 2248, +159, 886, -1526, -681, -2969, -2131, -3793, -3205, +-3726, -3545, -2689, -2977, -900, -1714, 1132, -88, +2845, 1585, 3827, 2870, 3902, 3392, 3009, 3048, +1312, 2002, -671, 605, -2350, -790, -3317, -1900, +-3374, -2468, -2481, -2346, -974, -1702, 594, -838, +1795, 48, 2352, 765, 2100, 1106, 1181, 1090, +49, 863, -882, 559, -1360, 366, -1245, 321, +-600, 295, 270, 253, 1006, 195, 1365, -32, +1217, -447, 502, -861, -542, -1152, -1464, -1275, +-1905, -1109, -1804, -617, -1248, 83, -283, 859, +872, 1491, 1844, 1767, 2289, 1628, 2128, 1087, +1470, 233, 499, -632, -590, -1275, -1570, -1632, +-2122, -1608, -2074, -1135, -1556, -355, -783, 446, +97, 1033, 883, 1241, 1332, 1064, 1388, 602, +1185, -50, 830, -681, 421, -935, 48, -721, +-212, -236, -379, 355, -499, 886, -584, 1139, +-683, 1001, -764, 469, -762, -378, -613, -1235, +-340, -1775, 40, -1852, 522, -1411, 991, -467, +1279, 710, 1278, 1729, 990, 2342, 479, 2374, +-145, 1760, -711, 661, -1076, -586, -1199, -1657, +-1125, -2272, -901, -2321, -516, -1834, -59, -923, +358, 155, 679, 1078, 885, 1639, 980, 1760, +962, 1437, 813, 833, 496, 194, 136, -315, +-229, -657, -693, -755, -1118, -587, -1214, -345, +-1037, -241, -845, -249, -547, -270, 36, -327, +675, -390, 1066, -306, 1226, -52, 1259, 231, +1116, 547, 705, 909, 103, 1122, -507, 1056, +-973, 817, -1285, 472, -1389, -56, -1195, -745, +-785, -1382, -271, -1736, 323, -1768, 932, -1490, +1304, -881, 1336, 16, 1113, 996, 703, 1866, +167, 2463, -334, 2521, -670, 1919, -867, 933, +-945, -215, -842, -1488, -587, -2504, -293, -2824, +-15, -2491, 251, -1732, 457, -617, 479, 602, +389, 1550, 388, 2119, 520, 2324, 627, 2058, +601, 1398, 473, 647, 168, -58, -396, -714, +-1069, -1291, -1512, -1727, -1606, -1970, -1370, -1956, +-713, -1627, 322, -922, 1380, 99, 2089, 1227, +2274, 2193, 1857, 2727, 898, 2630, -307, 1874, +-1408, 655, -2111, -705, -2197, -1834, -1711, -2437, +-870, -2428, 118, -1867, 1048, -870, 1656, 226, +1798, 1011, 1498, 1360, 792, 1305, -78, 897, +-812, 360, -1285, 31, -1426, -20, -1084, 92, +-388, 295, 253, 489, 667, 443, 912, 14, +937, -651, 671, -1249, 237, -1588, -205, -1617, +-595, -1215, -833, -317, -811, 793, -589, 1656, +-239, 2073, 183, 2015, 557, 1452, 712, 532, +674, -422, 611, -1145, 513, -1474, 283, -1370, +-63, -1035, -409, -667, -743, -277, -1016, 80, +-1077, 199, -852, 143, -420, 199, 109, 422, +667, 680, 1155, 927, 1408, 1116, 1311, 1094, +907, 781, 337, 199, -289, -553, -886, -1264, +-1291, -1694, -1386, -1770, -1169, -1517, -780, -954, +-354, -163, 71, 661, 497, 1292, 897, 1635, +1140, 1715, 1175, 1522, 1070, 1032, 874, 420, +519, -111, -14, -581, -593, -1058, -1073, -1422, +-1400, -1584, -1550, -1601, -1480, -1416, -1151, -917, +-567, -170, 227, 669, 1097, 1496, 1828, 2142, +2285, 2430, 2336, 2270, 1872, 1648, 915, 631, +-332, -595, -1602, -1780, -2608, -2686, -3033, -3063, +-2757, -2778, -1859, -1898, -555, -620, 879, 795, +2109, 2028, 2872, 2821, 2996, 3001, 2405, 2565, +1275, 1694, -2, 550, -1153, -703, -2054, -1733, +-2478, -2283, -2258, -2406, -1546, -2154, -673, -1522, +183, -676, 912, 142, 1401, 890, 1531, 1510, +1298, 1827, 833, 1850, 330, 1675, -49, 1241, +-266, 543, -358, -250, -415, -989, -445, -1561, +-425, -1863, -436, -1828, -558, -1470, -650, -847, +-530, -64, -250, 743, 87, 1412, 509, 1745, +925, 1663, 1113, 1315, 1050, 814, 822, 96, +392, -686, -267, -1188, -863, -1314, -1117, -1211, +-1056, -912, -822, -390, -406, 193, 162, 602, +591, 765, 645, 685, 417, 365, 163, -6, +-67, -238, -279, -321, -285, -268, 19, -20, +430, 330, 701, 581, 787, 666, 677, 591, +263, 314, -402, -139, -1026, -645, -1385, -1124, +-1407, -1430, -1119, -1399, -544, -1023, 220, -354, +1030, 595, 1616, 1593, 1756, 2253, 1493, 2354, +946, 1879, 170, 919, -684, -372, -1295, -1687, +-1512, -2623, -1391, -2836, -1002, -2271, -434, -1173, +117, 120, 491, 1345, 663, 2188, 678, 2381, +606, 1913, 542, 1035, 529, 108, 536, -639, +488, -1117, 267, -1220, -119, -939, -575, -539, +-947, -262, -1123, -143, -1076, -142, -835, -214, +-400, -246, 201, -101, 776, 249, 1169, 727, +1332, 1140, 1191, 1289, 715, 1122, 62, 655, +-552, -94, -996, -896, -1127, -1474, -883, -1711, +-443, -1512, 19, -891, 412, -102, 601, 642, +520, 1241, 275, 1480, -4, 1256, -276, 787, +-426, 282, -395, -247, -209, -654, 107, -755, +480, -654, 786, -483, 882, -254, 722, -87, +310, -80, -263, -76, -843, 2, -1292, 71, +-1465, 157, -1232, 375, -618, 603, 178, 634, +953, 448, 1569, 140, 1798, -215, 1488, -533, +813, -713, 46, -720, -679, -513, -1260, -114, +-1445, 308, -1210, 554, -793, 605, -325, 513, +180, 244, 569, -154, 678, -478, 593, -600, +420, -521, 231, -215, 123, 216, 157, 571, +305, 757, 476, 753, 507, 468, 279, -53, +-166, -585, -701, -971, -1221, -1125, -1519, -947, +-1393, -457, -877, 176, -94, 800, 826, 1214, +1644, 1258, 2036, 976, 1959, 490, 1505, -169, +677, -808, -400, -1112, -1385, -1052, -1971, -796, +-2122, -395, -1860, 108, -1190, 491, -258, 622, +684, 548, 1447, 356, 1896, 151, 1900, 57, +1468, 58, 770, 73, -34, 107, -772, 129, +-1263, 30, -1418, -191, -1248, -414, -839, -599, +-311, -707, 162, -627, 508, -326, 666, 87, +614, 528, 484, 931, 393, 1144, 303, 1037, +188, 627, 148, 38, 120, -563, -6, -994, +-163, -1188, -311, -1123, -520, -761, -702, -180, +-676, 377, -443, 755, -144, 935, 191, 885, +555, 612, 834, 238, 900, -82, 715, -297, +379, -371, -8, -324, -359, -265, -622, -293, +-715, -363, -623, -368, -414, -257, -117, -71, +173, 163, 323, 444, 326, 659, 318, 684, +286, 488, 125, 167, -58, -162, -76, -416, +5, -556, 38, -535, 67, -354, 143, -86, +118, 146, -66, 245, -253, 211, -360, 84, +-379, -53, -288, -121, -74, -80, 163, 64, +358, 263, 471, 403, 424, 398, 233, 237, +27, -37, -105, -341, -193, -576, -224, -645, +-166, -513, -55, -230, 28, 117, 35, 443, +-15, 626, -45, 603, -68, 402, -134, 88, +-174, -240, -60, -449, 146, -437, 258, -259, +302, -24, 373, 208, 403, 370, 230, 361, +-59, 172, -293, -138, -465, -442, -568, -599, +-512, -576, -278, -375, 0, 9, 231, 496, +410, 900, 523, 1066, 514, 906, 381, 448, +174, -162, -44, -753, -227, -1210, -345, -1360, +-382, -1075, -317, -508, -180, 128, -50, 763, +50, 1243, 118, 1344, 175, 1095, 197, 626, +191, 3, 156, -629, 89, -1037, -2, -1125, +-71, -934, -56, -523, -1, -3, 15, 461, +0, 730, 29, 715, 62, 436, -8, 85, +-147, -206, -227, -381, -241, -325, -212, -19, +-101, 360, 122, 614, 369, 606, 516, 270, +526, -292, 377, -859, 113, -1210, -182, -1198, +-391, -741, -498, 40, -496, 862, -353, 1453, +-114, 1614, 113, 1271, 245, 560, 318, -283, +363, -1049, 335, -1481, 199, -1420, 42, -955, +-27, -321, -35, 315, -92, 814, -159, 1015, +-136, 862, -73, 505, -102, 124, -141, -197, +-43, -386, 66, -409, 67, -291, 55, -110, +125, 68, 139, 153, 49, 103, -18, -33, +-19, -191, 16, -328, 95, -350, 224, -193, +323, 65, 309, 348, 147, 599, -149, 684, +-488, 512, -743, 189, -833, -170, -673, -521, +-262, -771, 301, -786, 878, -569, 1313, -219, +1437, 204, 1135, 588, 510, 803, -267, 777, +-1042, 553, -1645, 188, -1790, -236, -1347, -615, +-556, -821, 263, -789, 995, -550, 1548, -170, +1663, 288, 1241, 737, 565, 991, -65, 924, +-592, 580, -950, 96, -1004, -457, -760, -955, +-390, -1194, -28, -1059, 205, -626, 244, -40, +176, 579, 115, 1064, 75, 1275, 37, 1152, +127, 710, 370, 52, 593, -581, 643, -989, +543, -1116, 286, -982, -172, -633, -701, -188, +-1070, 200, -1150, 462, -942, 598, -473, 654, +150, 659, 730, 603, 1099, 457, 1194, 224, +1005, -97, 599, -464, 104, -775, -333, -924, +-619, -882, -717, -658, -611, -248, -369, 262, +-135, 706, -38, 937, -25, 928, -26, 705, +-58, 331, -96, -91, -5, -412, 290, -544, +655, -516, 908, -381, 957, -207, 776, -64, +346, -5, -266, -26, -885, -96, -1316, -136, +-1463, -97, -1257, 27, -713, 212, 24, 445, +742, 673, 1308, 771, 1605, 659, 1494, 335, +1038, -142, 408, -659, -274, -1080, -888, -1321, +-1219, -1274, -1196, -864, -968, -178, -614, 592, +-129, 1273, 357, 1696, 631, 1697, 678, 1261, +635, 514, 553, -366, 401, -1158, 218, -1607, +57, -1642, -49, -1326, -142, -743, -234, -25, +-308, 642, -344, 1107, -310, 1284, -214, 1155, +-117, 813, -86, 358, -48, -119, 66, -509, +212, -695, 302, -695, 342, -593, 394, -434, +439, -259, 398, -111, 236, 10, 17, 111, +-166, 190, -311, 308, -482, 454, -622, 537, +-607, 506, -422, 383, -175, 154, 100, -167, +373, -469, 580, -646, 702, -670, 724, -527, +628, -244, 435, 49, 221, 276, -58, 402, +-433, 413, -750, 325, -856, 201, -820, 79, +-711, -11, -419, -43, 44, -30, 486, -22, +811, -43, 1058, -87, 1146, -178, 962, -288, +551, -337, 37, -272, -535, -112, -1023, 113, +-1230, 347, -1113, 507, -765, 499, -246, 313, +342, 54, 785, -214, 980, -438, 940, -510, +713, -366, 335, -102, -65, 164, -350, 387, +-464, 502, -413, 408, -270, 130, -130, -189, +-24, -448, 50, -573, 36, -529, -55, -336, +-73, -44, 42, 292, 133, 555, 151, 672, +211, 635, 334, 468, 360, 192, 247, -151, +122, -476, -9, -696, -198, -729, -419, -597, +-534, -378, -480, -124, -261, 155, 79, 368, +431, 473, 649, 533, 651, 592, 483, 599, +200, 504, -171, 303, -515, -21, -659, -437, +-553, -837, -271, -1081, 87, -1089, 476, -817, +763, -309, 792, 298, 530, 819, 91, 1104, +-364, 1110, -727, 867, -866, 468, -699, 33, +-271, -310, 234, -507, 647, -579, 876, -583, +868, -531, 587, -451, 97, -382, -401, -288, +-692, -114, -719, 100, -551, 290, -228, 491, +190, 701, 580, 852, 762, 882, 650, 771, +306, 465, -103, -31, -454, -636, -688, -1243, +-711, -1676, -465, -1727, -23, -1319, 442, -552, +793, 431, 942, 1399, 860, 2059, 555, 2199, +78, 1783, -457, 911, -865, -180, -1038, -1171, +-977, -1817, -682, -1973, -181, -1604, 391, -865, +832, -42, 1052, 645, 1045, 1052, 850, 1108, +493, 843, 61, 437, -322, 92, -586, -84, +-745, -73, -796, 68, -706, 211, -488, 212, +-185, 33, 99, -303, 318, -718, 503, -1078, +708, -1175, 851, -900, 845, -319, 729, 401, +513, 1094, 128, 1613, -393, 1772, -886, 1424, +-1224, 628, -1310, -310, -1079, -1139, -588, -1696, +30, -1827, 702, -1446, 1292, -685, 1617, 194, +1566, 930, 1159, 1330, 462, 1331, -397, 1000, +-1114, 473, -1470, -98, -1436, -525, -1061, -722, +-418, -686, 278, -466, 785, -158, 1025, 114, +985, 288, 670, 328, 229, 215, -133, 10, +-333, -197, -375, -328, -240, -343, 46, -216, +294, 2, 372, 242, 249, 449, -8, 556, +-329, 511, -623, 345, -732, 105, -566, -195, +-184, -492, 269, -694, 720, -720, 1049, -580, +1088, -328, 809, -2, 349, 367, -185, 662, +-690, 772, -990, 697, -945, 503, -642, 215, +-249, -141, 164, -449, 506, -629, 674, -663, +601, -545, 385, -283, 156, 21, -13, 273, +-120, 430, -153, 458, -76, 325, 48, 81, +112, -138, 99, -259, 79, -250, 43, -96, +-56, 167, -186, 421, -256, 536, -290, 417, +-294, 78, -205, -385, -3, -832, 255, -1077, +518, -967, 756, -496, 843, 169, 724, 837, +456, 1329, 79, 1464, -434, 1140, -965, 468, +-1255, -341, -1177, -1053, -828, -1461, -294, -1474, +387, -1089, 1057, -395, 1462, 392, 1452, 999, +1121, 1274, 624, 1191, 38, 821, -610, 279, +-1137, -280, -1298, -707, -1101, -895, -732, -828, +-247, -582, 336, -237, 787, 134, 911, 436, +803, 573, 633, 546, 397, 396, 128, 182, +-68, -50, -155, -233, -232, -325, -305, -345, +-298, -309, -258, -226, -247, -95, -250, 62, +-187, 233, -52, 363, 126, 409, 322, 352, +500, 210, 591, -10, 557, -272, 426, -491, +227, -588, -45, -511, -325, -270, -486, 54, +-508, 346, -460, 575, -387, 667, -194, 554, +109, 278, 391, -32, 560, -305, 613, -511, +562, -613, 367, -573, 73, -373, -207, -72, +-366, 227, -405, 440, -358, 549, -205, 497, +28, 288, 230, 30, 342, -165, 342, -257, +236, -228, 63, -125, -110, -52, -219, -46, +-246, -100, -143, -169, 34, -225, 204, -210, +324, -87, 387, 148, 366, 414, 247, 593, +73, 608, -145, 442, -357, 112, -466, -318, +-430, -697, -285, -898, -54, -808, 220, -430, +464, 68, 560, 487, 501, 756, 366, 824, +211, 637, 25, 263, -179, -120, -306, -392, +-333, -537, -287, -525, -195, -371, -75, -159, +15, 7, 74, 115, 149, 191, 244, 228, +298, 206, 318, 176, 335, 180, 317, 151, +213, 62, 7, -65, -222, -202, -398, -314, +-456, -313, -405, -193, -264, -33, -22, 127, +281, 283, 534, 352, 623, 245, 521, 16, +265, -216, -34, -359, -245, -383, -334, -251, +-325, 11, -192, 317, 10, 557, 171, 634, +230, 465, 221, 93, 166, -319, 63, -661, +-37, -871, -129, -849, -171, -526, -112, -23, +39, 485, 208, 903, 342, 1141, 398, 1050, +319, 611, 119, -7, -110, -602, -311, -1035, +-430, -1209, -404, -1046, -222, -578, 61, 43, +311, 592, 479, 907, 533, 929, 453, 721, +230, 374, -48, -10, -241, -305, -339, -409, +-363, -335, -282, -214, -98, -154, 89, -177, +211, -242, 311, -309, 370, -312, 314, -189, +228, 77, 185, 428, 105, 763, -102, 931, +-329, 807, -443, 430, -467, -85, -359, -648, +-75, -1133, 319, -1300, 664, -1048, 854, -492, +816, 182, 524, 819, 74, 1243, -410, 1300, +-794, 967, -949, 357, -833, -314, -488, -836, +45, -1085, 626, -1037, 1052, -683, 1140, -127, +890, 414, 413, 756, -138, 826, -608, 641, +-878, 266, -844, -170, -532, -499, -85, -587, +345, -436, 666, -144, 756, 160, 545, 369, +129, 387, -286, 198, -526, -75, -475, -268, +-155, -294, 282, -164, 657, 56, 795, 275, +625, 386, 177, 265, -373, -54, -844, -382, +-1051, -543, -867, -492, -347, -250, 307, 153, +881, 587, 1225, 826, 1215, 750, 810, 415, +148, -81, -502, -581, -913, -893, -964, -907, +-718, -675, -283, -278, 169, 203, 480, 616, +589, 814, 519, 804, 343, 652, 114, 369, +-52, 19, -108, -313, -102, -564, -63, -723, +23, -762, 102, -642, 92, -369, 25, -38, +-10, 286, -22, 588, -8, 802, 40, 857, +50, 741, 13, 486, -38, 83, -56, -372, +-43, -735, 51, -973, 195, -1076, 273, -920, +288, -465, 272, 117, 193, 647, 48, 1044, +-72, 1241, -157, 1136, -264, 715, -334, 88, +-275, -538, -128, -991, 56, -1158, 241, -1010, +384, -615, 404, -104, 313, 370, 198, 665, +74, 690, -5, 505, -5, 250, 43, 40, +41, -63, -26, -21, -100, 87, -188, 152, +-309, 110, -397, -64, -337, -348, -100, -634, +215, -754, 523, -634, 787, -305, 901, 150, +771, 617, 381, 944, -108, 1031, -553, 848, +-863, 432, -957, -108, -800, -603, -397, -913, +128, -1003, 603, -857, 873, -484, 881, 22, +652, 468, 286, 739, -93, 801, -356, 656, +-402, 326, -210, -85, 37, -413, 182, -554, +238, -483, 188, -230, -17, 121, -311, 409, +-471, 501, -450, 348, -323, 5, -85, -418, +297, -735, 733, -789, 1013, -550, 1021, -79, +785, 491, 359, 961, -200, 1134, -750, 964, +-1115, 501, -1202, -124, -1009, -736, -526, -1128, +114, -1169, 703, -865, 1105, -338, 1237, 226, +1054, 666, 603, 865, 104, 789, -287, 491, +-528, 120, -581, -184, -448, -323, -247, -300, +-130, -166, -128, -2, -147, 105, -142, 104, +-85, -14, 43, -227, 236, -449, 498, -528, +741, -422, 839, -173, 718, 191, 481, 631, +160, 954, -303, 992, -769, 752, -1030, 294, +-1049, -303, -874, -853, -475, -1146, 95, -1121, +640, -798, 1044, -277, 1250, 289, 1162, 712, +813, 871, 322, 758, -177, 469, -594, 136, +-835, -119, -835, -197, -648, -121, -343, -10, +-47, 50, 152, 24, 219, -181, 215, -521, +253, -776, 359, -777, 482, -546, 588, -126, +633, 446, 548, 1017, 296, 1365, -58, 1340, +-426, 950, -765, 281, -963, -493, -948, -1157, +-694, -1537, -263, -1553, 274, -1165, 807, -435, +1157, 384, 1224, 1012, 1025, 1329, 656, 1327, +158, 987, -376, 424, -773, -167, -949, -614, +-942, -819, -731, -756, -322, -524, 140, -245, +452, 2, 604, 154, 681, 171, 633, 70, +457, -53, 255, -104, 142, -23, 37, 163, +-123, 401, -258, 600, -313, 655, -338, 506, +-358, 167, -298, -310, -135, -802, 38, -1093, +172, -1075, 317, -760, 474, -219, 562, 408, +494, 886, 346, 1101, 168, 1052, -51, 762, +-281, 294, -439, -210, -487, -614, -451, -851, +-281, -877, -16, -730, 220, -432, 396, -8, +549, 429, 613, 695, 489, 741, 225, 596, +-46, 307, -296, -43, -507, -369, -589, -572, +-432, -557, -56, -327, 320, -31, 566, 230, +647, 422, 553, 483, 264, 344, -117, 76, +-388, -198, -499, -401, -484, -472, -323, -391, +-11, -200, 320, 28, 530, 249, 619, 413, +580, 486, 327, 428, -53, 250, -372, 1, +-521, -247, -521, -434, -342, -516, 2, -458, +302, -254, 448, 45, 487, 307, 461, 445, +291, 444, -15, 323, -286, 83, -412, -193, +-410, -382, -264, -417, 34, -285, 364, -30, +544, 232, 523, 383, 351, 399, 75, 277, +-186, 49, -359, -207, -399, -373, -310, -410, +-130, -339, 75, -192, 238, -9, 352, 143, +373, 247, 285, 351, 153, 412, 41, 351, +-32, 194, -53, 49, -19, -112, 14, -322, +-36, -482, -106, -486, -136, -372, -146, -214, +-126, -18, -25, 196, 144, 363, 257, 425, +312, 417, 342, 363, 311, 250, 207, 80, +95, -81, 0, -236, -105, -406, -188, -523, +-219, -514, -266, -389, -312, -176, -246, 135, +-71, 435, 120, 603, 289, 614, 482, 486, +583, 204, 499, -149, 331, -416, 186, -508, +25, -419, -200, -198, -377, 62, -468, 231, +-527, 237, -493, 84, -294, -136, -4, -322, +294, -351, 569, -151, 755, 198, 752, 513, +614, 687, 398, 672, 82, 412, -271, -58, +-562, -576, -702, -931, -698, -990, -536, -723, +-241, -247, 85, 285, 354, 741, 532, 982, +643, 895, 687, 509, 631, 11, 466, -412, +197, -640, -163, -651, -525, -455, -763, -137, +-773, 168, -580, 329, -232, 312, 169, 145, +491, -77, 666, -218, 683, -216, 593, -87, +390, 111, 102, 320, -173, 436, -347, 389, +-405, 189, -382, -97, -288, -402, -137, -609, +18, -623, 162, -432, 298, -88, 408, 291, +436, 586, 344, 690, 196, 561, -4, 237, +-233, -150, -413, -443, -434, -530, -293, -415, +-73, -175, 180, 93, 409, 290, 553, 348, +567, 238, 421, 29, 125, -184, -221, -315, +-487, -326, -590, -197, -512, 22, -255, 255, +71, 423, 349, 458, 529, 349, 586, 129, +516, -135, 306, -392, 45, -562, -161, -581, +-285, -419, -340, -140, -317, 193, -189, 510, +-18, 692, 84, 647, 107, 393, 109, 24, +148, -356, 200, -591, 200, -587, 187, -389, +206, -127, 248, 157, 206, 382, 74, 414, +-87, 242, -268, 14, -431, -163, -476, -276, +-322, -272, -36, -100, 267, 171, 522, 369, +628, 408, 498, 276, 219, 12, -41, -303, +-207, -545, -296, -597, -255, -426, -86, -85, +95, 312, 206, 618, 215, 705, 129, 577, +-62, 268, -256, -175, -313, -608, -183, -801, +63, -679, 291, -351, 451, 73, 515, 498, +394, 766, 116, 741, -123, 458, -208, 30, +-224, -386, -249, -640, -195, -655, -68, -486, +27, -204, 23, 129, 10, 395, 65, 488, +110, 417, 142, 257, 233, 84, 368, -23, +430, -79, 373, -118, 222, -150, -33, -170, +-331, -212, -539, -277, -616, -319, -573, -280, +-371, -113, -7, 140, 386, 408, 664, 626, +814, 739, 792, 658, 565, 362, 190, -87, +-184, -583, -460, -976, -601, -1089, -557, -876, +-379, -431, -183, 136, -6, 682, 151, 1033, +241, 1054, 254, 783, 264, 340, 310, -124, +347, -480, 399, -648, 429, -641, 334, -512, +78, -302, -272, -89, -590, 45, -812, 95, +-845, 148, -611, 222, -152, 283, 374, 320, +808, 344, 1069, 308, 1106, 191, 865, 27, +397, -153, -177, -311, -695, -411, -1000, -441, +-1011, -407, -751, -293, -329, -123, 154, 55, +523, 214, 698, 359, 724, 461, 633, 482, +453, 410, 220, 276, 3, 119, -200, -69, +-383, -283, -468, -466, -427, -559, -306, -567, +-141, -491, 26, -326, 159, -73, 236, 233, +322, 520, 398, 714, 387, 772, 327, 680, +244, 430, 104, 69, -116, -311, -293, -616, +-350, -801, -370, -815, -361, -659, -251, -377, +-38, -26, 198, 330, 378, 616, 483, 750, +506, 713, 427, 532, 257, 266, 46, -42, +-138, -327, -273, -502, -325, -514, -326, -418, +-305, -285, -227, -126, -95, 22, 60, 91, +231, 85, 429, 79, 559, 91, 548, 131, +425, 203, 204, 304, -104, 359, -380, 325, +-539, 219, -568, 40, -455, -216, -213, -499, +63, -705, 302, -764, 505, -624, 598, -287, +549, 176, 390, 627, 171, 956, -57, 1052, +-274, 830, -439, 340, -498, -235, -425, -714, +-250, -974, -46, -944, 163, -642, 387, -162, +554, 323, 582, 655, 444, 728, 232, 566, +1, 257, -237, -98, -439, -375, -527, -473, +-449, -396, -265, -192, -18, 83, 257, 311, +481, 405, 566, 347, 495, 172, 325, -70, +99, -281, -160, -392, -351, -395, -383, -275, +-287, -54, -143, 166, 7, 287, 122, 318, +158, 266, 163, 162, 138, 56, 94, -33, +98, -113, 166, -134, 233, -95, 239, -61, +182, -63, 29, -72, -206, -75, -414, -106, +-525, -124, -503, -88, -261, 8, 149, 136, +531, 258, 750, 308, 790, 257, 597, 132, +197, -20, -219, -149, -523, -224, -657, -213, +-602, -130, -359, -36, -55, 11, 199, 10, +404, -58, 503, -172, 419, -249, 242, -194, +102, 5, 4, 265, -72, 523, -80, 696, +-23, 683, 4, 416, -34, -43, -123, -549, +-206, -943, -259, -1118, -235, -979, -80, -521, +158, 95, 389, 681, 537, 1093, 558, 1208, +428, 964, 166, 472, -119, -85, -341, -553, +-495, -852, -524, -912, -401, -730, -185, -399, +75, -41, 329, 249, 478, 431, 478, 472, +387, 377, 230, 220, 53, 95, -83, 11, +-140, -25, -140, -8, -124, 37, -116, 45, +-136, -16, -165, -121, -155, -247, -98, -354, +-6, -405, 116, -362, 268, -208, 443, 58, +554, 369, 528, 623, 335, 726, 7, 626, +-383, 339, -689, -55, -769, -442, -640, -704, +-336, -746, 108, -572, 548, -242, 818, 109, +836, 358, 636, 444, 311, 390, -71, 243, +-405, 73, -591, -36, -588, -48, -412, 13, +-147, 72, 102, 62, 267, -47, 358, -199, +351, -318, 232, -349, 82, -278, -12, -99, +-53, 137, -55, 338, 18, 431, 142, 394, +206, 256, 154, 34, 8, -206, -191, -376, +-354, -409, -428, -312, -380, -109, -165, 134, +186, 317, 519, 373, 712, 292, 727, 89, +530, -159, 174, -316, -249, -336, -605, -259, +-752, -125, -635, 79, -331, 282, 11, 380, +296, 325, 470, 163, 492, -26, 403, -200, +250, -316, 76, -327, -32, -208, -53, -25, +-59, 153, -95, 259, -104, 255, -107, 152, +-141, 9, -171, -134, -166, -243, -96, -266, +39, -173, 209, 9, 352, 191, 398, 307, +342, 310, 211, 218, 24, 60, -141, -104, +-233, -216, -266, -258, -235, -248, -126, -192, +2, -114, 67, -58, 86, -9, 97, 63, +95, 174, 64, 280, 43, 358, 82, 377, +166, 306, 239, 130, 251, -120, 190, -380, +74, -584, -93, -661, -284, -577, -412, -330, +-432, 2, -337, 345, -145, 639, 112, 811, +373, 771, 568, 538, 616, 186, 511, -206, +309, -574, 31, -832, -244, -862, -430, -658, +-528, -293, -531, 124, -388, 501, -138, 726, +93, 711, 287, 477, 491, 159, 582, -125, +478, -306, 296, -336, 107, -234, -130, -73, +-360, 41, -443, 49, -387, -45, -257, -164, +-48, -247, 185, -237, 338, -121, 352, 79, +271, 309, 134, 454, -52, 443, -207, 298, +-256, 112, -203, -77, -57, -251, 132, -354, +301, -352, 411, -297, 412, -218, 248, -110, +-40, 16, -351, 143, -592, 257, -648, 316, +-460, 282, -107, 185, 279, 56, 630, -59, +840, -136, 782, -142, 485, -79, 82, 10, +-338, 60, -680, 10, -824, -120, -716, -259, +-370, -349, 102, -336, 498, -157, 683, 151, +676, 490, 476, 712, 131, 706, -202, 456, +-398, 39, -408, -410, -262, -722, -49, -765, +144, -555, 274, -195, 291, 160, 151, 384, +-65, 392, -221, 226, -290, 29, -230, -72, +-18, -33, 229, 134, 379, 345, 396, 457, +292, 358, 83, 45, -137, -370, -276, -780, +-304, -1014, -217, -892, -67, -409, 56, 237, +113, 828, 128, 1189, 123, 1181, 84, 794, +26, 166, 35, -492, 126, -967, 211, -1089, +204, -865, 104, -419, -44, 96, -217, 528, +-373, 730, -420, 667, -304, 398, -59, 29, +223, -267, 448, -392, 571, -353, 546, -192, +360, 40, 77, 229, -245, 300, -544, 256, +-671, 115, -551, -99, -275, -303, 65, -412, +433, -392, 689, -235, 682, 8, 463, 285, +147, 511, -203, 589, -509, 453, -639, 165, +-501, -184, -168, -502, 197, -640, 465, -544, +566, -278, 477, 64, 207, 387, -115, 558, +-336, 497, -432, 248, -389, -48, -230, -289, +-30, -408, 169, -383, 347, -212, 478, 47, +499, 262, 381, 350, 135, 294, -171, 158, +-421, -4, -556, -148, -552, -266, -383, -305, +-117, -213, 145, -63, 375, 34, 559, 107, +619, 193, 530, 225, 364, 168, 111, 73, +-236, 2, -529, -59, -633, -111, -569, -142, +-374, -108, -91, -16, 174, 65, 352, 97, +439, 55, 410, -76, 269, -247, 163, -327, +141, -243, 68, 16, -45, 381, -65, 677, +-78, 719, -203, 472, -318, -5, -308, -551, +-270, -935, -232, -994, -77, -698, 165, -168, +379, 425, 528, 851, 595, 970, 534, 783, +303, 371, -30, -135, -335, -543, -518, -708, +-543, -631, -441, -387, -258, -72, -69, 205, +66, 352, 173, 348, 257, 220, 309, 67, +334, -45, 319, -86, 255, -70, 164, -25, +83, 14, 11, 9, -87, -5, -207, -5, +-333, -2, -450, 8, -499, 18, -427, -27, +-210, -111, 127, -167, 469, -158, 687, -100, +728, 20, 632, 207, 443, 353, 170, 347, +-154, 207, -455, 36, -675, -132, -759, -261, +-699, -322, -505, -293, -160, -187, 292, -71, +663, 5, 790, 50, 738, 121, 608, 229, +365, 306, 39, 316, -256, 279, -475, 156, +-589, -53, -575, -304, -460, -498, -288, -556, +-38, -440, 242, -173, 399, 157, 436, 461, +444, 624, 394, 567, 262, 305, 96, -34, +-79, -325, -260, -487, -384, -476, -383, -303, +-264, -47, -63, 202, 135, 343, 234, 357, +240, 298, 155, 145, -5, -77, -147, -291, +-160, -415, -55, -437, 62, -331, 172, -81, +281, 229, 317, 500, 267, 673, 130, 659, +-125, 409, -407, 8, -547, -425, -493, -774, +-308, -924, -10, -777, 359, -392, 598, 96, +565, 536, 356, 835, 109, 928, -137, 750, +-310, 378, -318, -50, -189, -431, -26, -705, +126, -775, 233, -618, 223, -340, 73, -44, +-150, 244, -353, 416, -460, 402, -373, 299, +-61, 213, 329, 153, 647, 94, 796, 72, +687, 70, 365, 34, -65, -90, -486, -263, +-769, -423, -861, -527, -767, -506, -501, -315, +-60, 13, 470, 378, 878, 677, 1030, 805, +900, 707, 514, 420, 2, 35, -441, -376, +-679, -669, -703, -754, -577, -675, -368, -482, +-142, -182, 62, 174, 234, 466, 393, 640, +518, 665, 517, 529, 393, 265, 208, -40, +-9, -310, -191, -484, -318, -524, -429, -439, +-451, -275, -330, -75, -145, 120, 42, 271, +248, 372, 426, 385, 458, 312, 351, 175, +186, 8, -22, -167, -198, -295, -255, -333, +-228, -318, -162, -252, -66, -92, 23, 130, +65, 313, 61, 415, 50, 399, 65, 219, +87, -64, 69, -284, 51, -390, 72, -372, +45, -205, -19, 40, -26, 232, -19, 278, +-39, 218, -54, 83, -29, -60, 17, -140, +36, -145, 45, -91, 37, 22, -20, 141, +-73, 181, -78, 101, -7, -43, 110, -162, +217, -226, 283, -222, 236, -135, 56, 40, +-152, 203, -305, 266, -375, 213, -309, 95, +-128, -18, 48, -110, 207, -152, 363, -114, +423, -17, 370, 62, 241, 86, 8, 62, +-260, -25, -425, -173, -445, -266, -339, -263, +-121, -172, 168, 51, 384, 350, 417, 547, +300, 554, 117, 413, -42, 107, -138, -289, +-226, -610, -249, -760, -144, -712, 7, -443, +139, -39, 241, 357, 297, 694, 263, 887, +93, 794, -191, 446, -445, 15, -494, -439, +-322, -787, -37, -866, 267, -682, 512, -364, +626, 45, 525, 474, 243, 743, -78, 771, +-383, 588, -614, 240, -679, -195, -549, -555, +-220, -712, 224, -640, 604, -374, 779, 1, +690, 350, 384, 586, -53, 639, -443, 491, +-570, 211, -475, -130, -293, -447, -27, -666, +244, -661, 335, -416, 245, -58, 148, 285, +79, 532, -28, 611, -124, 503, -146, 269, +-111, -1, -48, -224, 58, -352, 184, -393, +241, -380, 225, -278, 127, -105, -94, 60, +-298, 155, -357, 216, -308, 243, -158, 198, +78, 145, 294, 123, 405, 107, 415, 62, +342, -27, 142, -157, -142, -281, -363, -347, +-458, -327, -407, -229, -217, -45, 34, 174, +285, 335, 441, 401, 402, 359, 220, 231, +48, 41, -77, -149, -196, -288, -263, -316, +-249, -240, -184, -122, -75, 0, 67, 91, +245, 129, 382, 119, 378, 81, 239, 33, +-13, 8, -290, 2, -442, -9, -424, -48, +-255, -55, 10, -19, 280, 16, 455, 55, +473, 98, 361, 99, 149, 18, -136, -106, +-372, -226, -484, -279, -473, -211, -281, -33, +62, 181, 377, 362, 556, 428, 583, 315, +413, 58, 67, -224, -312, -421, -589, -460, +-665, -308, -497, -74, -145, 169, 285, 377, +630, 462, 754, 342, 633, 92, 287, -142, +-167, -319, -550, -415, -730, -369, -632, -187, +-337, 36, 4, 247, 322, 399, 542, 428, +587, 316, 449, 136, 236, -92, 28, -342, +-213, -521, -433, -526, -493, -322, -403, 13, +-212, 360, 82, 562, 375, 560, 483, 385, +380, 75, 151, -271, -116, -488, -285, -534, +-311, -443, -232, -204, -31, 126, 228, 381, +413, 501, 441, 533, 297, 383, 24, 58, +-344, -269, -679, -493, -753, -599, -505, -503, +-47, -224, 480, 59, 883, 306, 965, 517, +697, 573, 254, 456, -207, 267, -610, 6, +-821, -290, -807, -501, -664, -586, -357, -579, +131, -405, 608, -68, 926, 288, 1037, 591, +808, 758, 274, 688, -285, 405, -720, 20, +-954, -409, -859, -736, -516, -785, -109, -585, +295, -260, 638, 134, 824, 486, 756, 651, +433, 597, -18, 389, -405, 119, -582, -161, +-544, -374, -333, -469, -50, -418, 138, -255, +225, -57, 246, 118, 189, 218, 133, 241, +100, 210, 27, 135, -42, 47, -52, 30, +-62, 51, -39, 31, 53, -33, 32, -118, +-112, -237, -146, -302, -60, -259, 46, -159, +143, -2, 142, 200, 39, 365, -48, 397, +-57, 331, 0, 201, 118, 16, 242, -177, +239, -334, 80, -410, -135, -359, -322, -224, +-384, -66, -309, 119, -166, 281, 60, 339, +293, 291, 420, 192, 483, 46, 441, -63, +178, -86, -154, -77, -363, -76, -479, -84, +-473, -101, -283, -163, -61, -237, 138, -240, +365, -128, 470, 83, 389, 326, 229, 499, +8, 543, -233, 401, -342, 99, -276, -255, +-119, -548, 68, -676, 190, -571, 143, -258, +37, 91, -12, 336, -58, 450, -70, 468, +-33, 392, -26, 232, 4, 47, 109, -130, +232, -269, 289, -331, 174, -329, -101, -283, +-334, -180, -403, -49, -341, 70, -96, 153, +267, 232, 443, 309, 383, 377, 250, 401, +44, 280, -187, 27, -320, -259, -356, -518, +-295, -690, -86, -658, 199, -415, 420, -52, +530, 352, 427, 703, 43, 857, -379, 753, +-577, 404, -525, -88, -274, -520, 78, -754, +403, -755, 608, -533, 553, -112, 268, 314, +-50, 526, -359, 473, -614, 234, -598, -31, +-277, -193, 126, -225, 491, -115, 702, 119, +564, 329, 193, 356, -183, 183, -499, -80, +-606, -336, -426, -512, -145, -555, 113, -401, +372, -78, 524, 283, 457, 592, 275, 752, +11, 663, -318, 318, -489, -129, -430, -529, +-249, -783, 17, -746, 285, -400, 420, 66, +386, 484, 208, 704, -29, 634, -211, 332, +-320, -104, -343, -527, -194, -722, 82, -564, +326, -184, 477, 276, 433, 693, 104, 846, +-301, 624, -542, 125, -557, -475, -314, -932, +89, -996, 437, -659, 614, -88, 603, 566, +353, 1061, -45, 1116, -386, 742, -619, 104, +-682, -603, -482, -1114, -111, -1217, 329, -875, +714, -183, 797, 639, 573, 1240, 236, 1373, +-178, 1010, -550, 280, -646, -571, -539, -1244, +-391, -1491, -105, -1186, 267, -446, 481, 419, +555, 1124, 502, 1451, 227, 1281, -81, 671, +-253, -134, -345, -899, -301, -1337, -80, -1232, +79, -676, 59, 67, 29, 733, -2, 1075, +-96, 989, -114, 568, -46, -61, 12, -676, +120, -951, 287, -789, 396, -351, 370, 246, +206, 788, -70, 991, -402, 790, -643, 289, +-640, -394, -393, -1006, -31, -1178, 356, -866, +665, -253, 709, 484, 480, 1091, 168, 1280, +-190, 990, -526, 362, -613, -406, -450, -1071, +-161, -1341, 227, -1070, 540, -393, 554, 420, +350, 1080, 67, 1334, -315, 1061, -610, 396, +-595, -420, -399, -1103, -106, -1334, 322, -1022, +678, -352, 793, 438, 709, 1089, 411, 1309, +-95, 1034, -587, 435, -860, -344, -898, -1057, +-679, -1311, -224, -1059, 284, -500, 683, 251, +868, 950, 793, 1246, 493, 1082, 53, 622, +-364, -65, -600, -774, -625, -1180, -448, -1152, +-127, -729, 180, -47, 353, 644, 390, 1102, +272, 1203, 6, 879, -227, 208, -299, -518, +-271, -1012, -127, -1130, 153, -849, 409, -305, +482, 325, 340, 809, 82, 942, -166, 748, +-336, 350, -395, -161, -357, -580, -247, -670, +-95, -487, 76, -184, 225, 190, 312, 454, +356, 430, 316, 234, 147, -30, -3, -332, +-53, -474, -119, -346, -199, -116, -208, 149, +-217, 443, -255, 544, -166, 431, 51, 260, +244, -7, 361, -350, 360, -529, 198, -504, +11, -389, -114, -170, -214, 114, -237, 304, +-166, 381, -76, 379, 1, 254, 115, 89, +239, -28, 277, -124, 210, -199, 69, -169, +-110, -37, -280, 87, -370, 126, -309, 68, +-163, -39, -20, -186, 173, -351, 364, -404, +425, -257, 400, 46, 332, 413, 133, 684, +-151, 746, -353, 626, -487, 348, -554, -115, +-444, -615, -220, -914, 15, -978, 293, -807, +525, -390, 587, 146, 504, 649, 329, 1028, +99, 1134, -122, 876, -298, 400, -440, -132, +-514, -650, -470, -992, -328, -1010, -107, -736, +173, -278, 444, 226, 617, 652, 579, 880, +349, 813, 63, 462, -232, -33, -473, -487, +-518, -741, -369, -680, -144, -335, 140, 148, +416, 604, 481, 835, 321, 694, 49, 257, +-294, -294, -540, -781, -520, -1005, -326, -850, +-37, -385, 370, 272, 720, 930, 775, 1247, +547, 1085, 169, 562, -285, -153, -680, -834, +-855, -1205, -773, -1131, -436, -673, 54, 8, +466, 673, 705, 1060, 768, 1047, 630, 693, +311, 140, -108, -440, -505, -891, -748, -1019, +-724, -737, -424, -187, 49, 413, 504, 894, +720, 1066, 628, 817, 290, 271, -160, -389, +-514, -936, -647, -1118, -533, -875, -209, -308, +155, 425, 419, 1010, 581, 1153, 601, 854, +407, 265, 75, -465, -269, -1024, -567, -1085, +-681, -686, -489, -33, -174, 638, 105, 1035, +374, 979, 505, 519, 381, -162, 159, -789, +-35, -1072, -178, -920, -201, -404, -119, 322, +-30, 970, 60, 1246, 135, 1036, 122, 407, +41, -372, -88, -1006, -243, -1313, -309, -1160, +-251, -510, -123, 346, 51, 994, 240, 1286, +391, 1162, 454, 632, 398, -74, 214, -727, +-47, -1167, -281, -1167, -431, -698, -465, -26, +-401, 624, -296, 1061, -120, 1042, 106, 603, +246, -6, 340, -638, 470, -1029, 508, -893, +400, -319, 198, 376, -115, 949, -439, 1139, +-579, 811, -571, 146, -496, -641, -260, -1316, +80, -1495, 331, -1029, 498, -151, 601, 843, +511, 1633, 217, 1875, -110, 1439, -359, 484, +-482, -685, -405, -1649, -175, -2038, 81, -1741, +266, -835, 263, 385, 104, 1450, -88, 1976, +-263, 1793, -313, 972, -194, -148, 7, -1136, +286, -1670, 542, -1554, 560, -789, 371, 277, +74, 1141, -369, 1484, -780, 1212, -835, 440, +-582, -536, -213, -1303, 287, -1509, 762, -1067, +914, -175, 757, 843, 383, 1614, -197, 1757, +-738, 1208, -950, 241, -839, -855, -437, -1744, +226, -2008, 792, -1488, 966, -387, 769, 891, +263, 1858, -378, 2116, -823, 1568, -884, 408, +-625, -931, -202, -1866, 280, -2030, 701, -1398, +872, -178, 710, 1154, 291, 2002, -237, 2057, +-678, 1330, -878, 26, -783, -1351, -392, -2230, +196, -2308, 698, -1497, 836, -14, 622, 1529, +224, 2508, -246, 2577, -575, 1701, -575, 200, +-359, -1312, -79, -2277, 249, -2407, 438, -1685, +307, -437, 54, 839, -166, 1704, -380, 1868, +-401, 1358, -137, 493, 161, -395, 393, -1000, +593, -1075, 551, -688, 139, -117, -353, 413, +-700, 652, -902, 464, -795, 38, -306, -391, +307, -659, 810, -580, 1075, -178, 950, 276, +469, 644, -122, 885, -626, 820, -940, 420, +-951, -107, -639, -603, -178, -890, 260, -817, +598, -492, 710, -65, 500, 370, 129, 601, +-156, 519, -294, 294, -252, 54, -5, -137, +231, -119, 242, 78, 76, 203, -187, 186, +-502, 89, -662, -97, -503, -338, -194, -517, +131, -549, 524, -359, 837, 42, 845, 493, +570, 837, 129, 923, -394, 633, -834, 67, +-983, -559, -771, -1029, -296, -1103, 241, -686, +611, 32, 705, 759, 561, 1247, 225, 1263, +-188, 769, -453, -33, -487, -887, -365, -1471, +-140, -1517, 155, -1006, 425, -98, 513, 942, +377, 1698, 97, 1841, -235, 1373, -522, 472, +-646, -576, -545, -1392, -294, -1756, 19, -1605, +323, -937, 521, -4, 557, 800, 445, 1294, +251, 1424, 57, 1137, -140, 609, -332, 72, +-454, -451, -464, -803, -381, -798, -274, -641, +-140, -565, 47, -448, 227, -181, 359, 127, +445, 424, 443, 740, 314, 993, 77, 1041, +-190, 771, -403, 192, -512, -499, -441, -1108, +-192, -1495, 58, -1428, 178, -799, 205, 151, +169, 1076, 33, 1726, -145, 1847, -218, 1304, +-170, 267, -81, -893, 87, -1797, 361, -2088, +536, -1573, 473, -451, 225, 827, -210, 1855, +-703, 2246, -949, 1785, -864, 657, -521, -704, +39, -1856, 614, -2325, 918, -1799, 909, -556, +700, 784, 268, 1810, -342, 2203, -803, 1686, +-941, 452, -826, -889, -436, -1804, 174, -1953, +675, -1264, 832, -66, 672, 1137, 256, 1909, +-307, 1895, -729, 1042, -809, -240, -654, -1406, +-319, -2091, 219, -2009, 708, -1086, 892, 325, +834, 1664, 512, 2451, -149, 2367, -789, 1392, +-1049, -110, -993, -1552, -642, -2440, 2, -2497, +584, -1648, 790, -191, 720, 1240, 470, 2130, +-5, 2279, -432, 1653, -538, 465, -491, -767, +-351, -1613, 43, -1858, 468, -1374, 605, -309, +479, 798, 137, 1493, -373, 1583, -803, 981, +-928, -74, -726, -1037, -270, -1572, 288, -1539, +728, -815, 908, 348, 806, 1340, 498, 1793, +87, 1695, -328, 1042, -626, -29, -708, -1086, +-617, -1732, -419, -1779, -132, -1197, 77, -204, +44, 756, -82, 1303, -112, 1331, -36, 924, +238, 239, 689, -414, 992, -694, 937, -541, +551, -166, -109, 244, -882, 527, -1483, 499, +-1661, 145, -1361, -366, -721, -830, 124, -1019, +1034, -762, 1679, -185, 1760, 481, 1351, 1098, +616, 1410, -375, 1177, -1284, 563, -1646, -121, +-1415, -706, -819, -1031, -33, -1003, 651, -728, +947, -319, 833, 172, 390, 518, -245, 556, +-707, 425, -750, 224, -477, -43, 3, -186, +590, -63, 1001, 199, 1032, 472, 709, 644, +46, 527, -823, 101, -1485, -425, -1658, -909, +-1366, -1240, -652, -1213, 329, -731, 1188, 45, +1645, 883, 1629, 1528, 1162, 1714, 369, 1398, +-503, 709, -1150, -198, -1416, -1080, -1382, -1575, +-1064, -1470, -434, -933, 282, -284, 784, 349, +1013, 860, 988, 1036, 694, 837, 257, 462, +-184, 58, -581, -303, -786, -438, -731, -287, +-570, -49, -316, 127, 62, 215, 370, 143, +513, -34, 569, -174, 443, -296, 100, -345, +-223, -183, -436, 66, -606, 231, -651, 351, +-462, 381, -132, 241, 162, 85, 400, -2, +601, -154, 621, -245, 423, -46, 148, 227, +-174, 299, -506, 206, -702, 0, -743, -293, +-683, -536, -430, -662, -5, -614, 341, -295, +559, 234, 781, 767, 828, 1162, 508, 1304, +76, 1057, -295, 447, -695, -353, -989, -1140, +-941, -1652, -653, -1666, -271, -1184, 229, -333, +691, 622, 825, 1332, 655, 1652, 396, 1578, +53, 1077, -350, 271, -568, -529, -535, -1080, +-418, -1267, -239, -1057, -25, -570, 84, -28, +84, 415, 26, 628, -88, 538, -155, 271, +-25, 21, 219, -110, 356, -73, 400, 115, +378, 357, 48, 560, -517, 587, -871, 316, +-930, -194, -825, -752, -414, -1171, 272, -1270, +852, -938, 1156, -230, 1177, 648, 770, 1416, +-44, 1782, -893, 1568, -1435, 871, -1519, -46, +-1125, -916, -383, -1518, 465, -1693, 1154, -1344, +1445, -551, 1226, 372, 592, 1077, -247, 1374, +-1017, 1254, -1462, 807, -1417, 166, -811, -456, +106, -824, 853, -841, 1245, -583, 1210, -206, +585, 144, -362, 362, -1039, 412, -1247, 344, +-1098, 249, -591, 145, 184, 11, 910, -136, +1300, -203, 1194, -187, 580, -216, -277, -287, +-1031, -217, -1505, 56, -1497, 386, -907, 629, +-43, 730, 714, 660, 1244, 331, 1397, -233, +1014, -807, 311, -1167, -365, -1210, -949, -858, +-1362, -114, -1305, 756, -746, 1395, -57, 1647, +503, 1470, 863, 824, 880, -127, 554, -1068, +106, -1672, -273, -1725, -476, -1264, -476, -479, +-364, 444, -221, 1204, -49, 1539, 121, 1457, +123, 1019, -92, 285, -276, -495, -312, -1022, +-264, -1221, -59, -1096, 279, -644, 476, -3, +430, 623, 268, 1050, -1, 1090, -370, 786, +-595, 339, -559, -252, -482, -840, -407, -1067, +-159, -918, 164, -603, 346, -79, 405, 603, +359, 1118, 190, 1313, 59, 1210, 20, 788, +-82, 91, -233, -723, -313, -1465, -437, -1819, +-652, -1640, -662, -1088, -384, -205, -110, 980, +196, 2003, 679, 2431, 980, 2246, 854, 1494, +503, 284, 26, -1056, -593, -2167, -1136, -2755, +-1313, -2583, -1070, -1705, -550, -391, 104, 1084, +666, 2325, 920, 2905, 907, 2702, 699, 1807, +264, 379, -249, -1137, -602, -2241, -787, -2660, +-784, -2304, -518, -1314, -148, -32, 98, 1216, +239, 2065, 282, 2199, 101, 1652, -118, 664, +-60, -506, 111, -1441, 161, -1738, 223, -1409, +207, -649, -99, 373, -485, 1275, -730, 1619, +-826, 1345, -664, 631, -217, -310, 338, -1167, +845, -1621, 1137, -1513, 1006, -893, 445, 37, +-305, 1001, -1064, 1678, -1659, 1789, -1712, 1308, +-1110, 453, -200, -483, 759, -1207, 1610, -1511, +1989, -1341, 1671, -776, 825, 13, -291, 706, +-1479, 1066, -2344, 1072, -2445, 714, -1796, 86, +-729, -467, 581, -731, 1820, -678, 2437, -262, +2323, 374, 1638, 877, 376, 1037, -1103, 780, +-2146, 90, -2589, -726, -2475, -1296, -1629, -1525, +-196, -1342, 1154, -621, 2029, 415, 2388, 1355, +2049, 2015, 1053, 2186, -155, 1660, -1261, 599, +-2078, -588, -2293, -1601, -1799, -2264, -803, -2388, +350, -1808, 1262, -692, 1678, 532, 1540, 1582, +900, 2292, 1, 2434, -782, 1919, -1188, 963, +-1141, -206, -747, -1347, -195, -2075, 330, -2150, +652, -1683, 607, -872, 184, 71, -384, 917, +-814, 1526, -963, 1719, -732, 1368, -125, 704, +617, 53, 1228, -494, 1464, -831, 1118, -827, +307, -550, -653, -196, -1527, 77, -2075, 119, +-2076, -79, -1478, -275, -404, -310, 843, -231, +1875, -26, 2363, 368, 2160, 835, 1347, 1152, +189, 1190, -993, 950, -1911, 375, -2332, -516, +-2186, -1397, -1598, -1927, -706, -1993, 349, -1497, +1256, -461, 1775, 755, 1909, 1798, 1628, 2433, +922, 2403, 51, 1702, -749, 633, -1406, -611, +-1816, -1828, -1879, -2532, -1512, -2473, -728, -1790, +202, -542, 1006, 986, 1566, 2090, 1722, 2456, +1340, 2214, 524, 1350, -425, -48, -1205, -1406, +-1613, -2172, -1529, -2229, -974, -1605, -121, -390, +772, 1040, 1337, 2145, 1302, 2574, 745, 2183, +-95, 952, -996, -809, -1650, -2385, -1743, -3184, +-1175, -3009, -159, -1825, 948, 155, 1836, 2247, +2159, 3716, 1660, 4115, 520, 3214, -815, 1217, +-1961, -1231, -2568, -3385, -2375, -4525, -1429, -4216, +-81, -2623, 1216, -263, 2087, 2245, 2249, 4038, +1627, 4433, 506, 3462, -697, 1547, -1591, -827, +-1854, -2835, -1463, -3723, -646, -3328, 318, -1895, +1023, 105, 1143, 1963, 686, 3001, -102, 2859, +-896, 1642, -1371, -103, -1261, -1724, -537, -2664, +466, -2531, 1321, -1367, 1764, 309, 1549, 1901, +632, 2862, -589, 2780, -1635, 1740, -2211, 156, +-2115, -1558, -1360, -2801, -244, -3035, 937, -2379, +1870, -1124, 2127, 550, 1574, 2086, 597, 2868, +-458, 2823, -1475, 2081, -2056, 788, -1786, -642, +-873, -1774, 138, -2381, 933, -2316, 1400, -1643, +1373, -665, 717, 428, -244, 1370, -1004, 1827, +-1418, 1821, -1461, 1485, -1005, 745, -187, -197, +642, -934, 1239, -1391, 1461, -1537, 1242, -1253, +627, -627, -205, 166, -982, 972, -1496, 1503, +-1700, 1573, -1543, 1224, -963, 444, -105, -638, +725, -1502, 1312, -1813, 1577, -1632, 1421, -928, +864, 239, 177, 1457, -416, 2244, -945, 2311, +-1427, 1645, -1635, 481, -1381, -918, -856, -2177, +-288, -2760, 412, -2459, 1131, -1471, 1418, 3, +1176, 1626, 773, 2736, 391, 2955, -97, 2424, +-675, 1292, -1085, -297, -1250, -1816, -1235, -2710, +-956, -2805, -389, -2201, 240, -1079, 702, 366, +933, 1729, 914, 2503, 682, 2550, 310, 2045, +-119, 1101, -506, -138, -759, -1317, -856, -2067, +-763, -2226, -419, -1847, 43, -1101, 304, -151, +261, 853, 121, 1628, -39, 1980, -236, 1945, +-276, 1520, -38, 642, 290, -439, 494, -1346, +501, -1947, 322, -2152, -26, -1793, -575, -832, +-1205, 412, -1535, 1432, -1338, 2006, -785, 2197, +85, 1871, 1266, 920, 2204, -267, 2298, -1182, +1599, -1802, 406, -2125, -1068, -1816, -2456, -930, +-3214, 31, -2958, 830, -1778, 1509, -101, 1912, +1711, 1855, 3217, 1398, 3706, 698, 2910, -166, +1257, -1069, -818, -1799, -2821, -2179, -3966, -2083, +-3855, -1437, -2704, -352, -763, 864, 1491, 1919, +3206, 2610, 3854, 2745, 3409, 2140, 1921, 905, +-234, -547, -2278, -1899, -3602, -2928, -3879, -3270, +-2997, -2621, -1264, -1201, 740, 448, 2503, 1993, +3525, 3130, 3389, 3412, 2134, 2745, 328, 1415, +-1437, -255, -2829, -1813, -3473, -2780, -3027, -3022, +-1691, -2568, -75, -1424, 1437, 31, 2625, 1260, +3046, 2137, 2475, 2620, 1260, 2388, -207, 1498, +-1703, 457, -2792, -533, -3003, -1468, -2330, -2064, +-1123, -2067, 237, -1571, 1462, -811, 2374, 45, +2632, 899, 1957, 1606, 721, 1967, -508, 1812, +-1626, 1209, -2459, 385, -2510, -562, -1730, -1506, +-597, -2075, 593, -1952, 1678, -1249, 2228, -303, +1916, 731, 951, 1712, -161, 2233, -1120, 1996, +-1828, 1129, -2069, -26, -1588, -1112, -530, -1862, +587, -2133, 1383, -1755, 1723, -704, 1551, 537, +822, 1447, -355, 1918, -1468, 1906, -1930, 1265, +-1742, 236, -1140, -693, -89, -1365, 1112, -1655, +1772, -1321, 1704, -572, 1171, 169, 260, 803, +-875, 1164, -1798, 955, -2126, 335, -1785, -169, +-894, -427, 306, -545, 1426, -355, 2052, 246, +2018, 885, 1378, 1091, 225, 747, -1134, 24, +-2111, -834, -2375, -1620, -2013, -2059, -1097, -1826, +199, -820, 1341, 684, 1952, 2165, 2056, 3112, +1586, 3221, 551, 2380, -580, 670, -1425, -1443, +-1913, -3224, -1931, -4069, -1410, -3795, -552, -2439, +346, -214, 1030, 2183, 1366, 3858, 1357, 4340, +1018, 3643, 436, 2000, -207, -174, -800, -2215, +-1245, -3503, -1324, -3754, -1027, -2942, -615, -1318, +-164, 470, 408, 1782, 866, 2493, 947, 2662, +788, 2096, 518, 896, 59, -249, -506, -902, +-900, -1279, -992, -1446, -856, -1189, -547, -680, +-48, -265, 462, 60, 668, 375, 622, 585, +535, 676, 254, 757, -242, 781, -601, 623, +-763, 322, -832, -53, -666, -475, -215, -863, +255, -1041, 582, -911, 736, -554, 631, -69, +328, 488, -15, 958, -373, 1150, -686, 1027, +-836, 600, -853, -5, -728, -511, -371, -782, +134, -874, 597, -732, 911, -343, 971, 67, +772, 293, 371, 355, -198, 336, -742, 320, +-1096, 345, -1310, 295, -1314, 219, -906, 290, +-159, 339, 672, 113, 1343, -270, 1599, -629, +1362, -918, 781, -1062, -41, -948, -958, -511, +-1620, 263, -1806, 1136, -1560, 1683, -916, 1780, +25, 1535, 920, 881, 1507, -168, 1649, -1253, +1216, -2032, 413, -2327, -364, -2004, -977, -1140, +-1377, 10, -1388, 1212, -1010, 2185, -462, 2567, +92, 2220, 582, 1358, 903, 256, 953, -904, +730, -1834, 329, -2228, -121, -2034, -450, -1403, +-577, -500, -662, 527, -789, 1355, -797, 1679, +-593, 1543, -331, 1166, -26, 606, 491, -105, +1053, -689, 1281, -845, 1135, -698, 757, -545, +113, -341, -793, -26, -1665, 91, -2129, -97, +-2076, -230, -1525, -183, -444, -104, 997, 108, +2229, 556, 2798, 946, 2622, 1048, 1677, 947, +101, 592, -1596, -73, -2863, -777, -3386, -1275, +-2963, -1532, -1638, -1451, 124, -919, 1783, -73, +2911, 759, 3125, 1378, 2342, 1676, 911, 1534, +-695, 1010, -2019, 316, -2659, -382, -2432, -961, +-1493, -1257, -199, -1221, 998, -952, 1746, -536, +1767, -49, 1003, 379, -129, 663, -1084, 794, +-1576, 776, -1449, 677, -637, 553, 524, 335, +1472, 44, 1907, -193, 1713, -421, 774, -683, +-678, -837, -2076, -806, -2938, -626, -2998, -284, +-2145, 154, -464, 512, 1581, 799, 3244, 1059, +3951, 1081, 3572, 773, 2107, 344, -185, -95, +-2499, -533, -4081, -872, -4636, -1059, -4021, -1103, +-2284, -937, 127, -549, 2551, -85, 4290, 394, +4832, 940, 4044, 1480, 2189, 1754, -274, 1599, +-2699, 1062, -4418, 202, -4952, -887, -4120, -1888, +-2152, -2421, 276, -2370, 2481, -1765, 4048, -646, +4490, 733, 3519, 1958, 1572, 2707, -655, 2754, +-2625, 2132, -3778, 1106, -3747, -140, -2624, -1407, +-855, -2281, 992, -2486, 2394, -2167, 2927, -1508, +2429, -580, 1132, 387, -446, 1152, -1804, 1666, +-2445, 1883, -2071, 1778, -904, 1499, 511, 1105, +1677, 481, 2200, -328, 1826, -1132, 697, -1822, +-719, -2308, -2035, -2407, -2850, -1961, -2688, -1039, +-1578, 157, 26, 1427, 1709, 2514, 3021, 3113, +3467, 3050, 2812, 2378, 1248, 1211, -662, -322, +-2352, -1884, -3532, -3047, -3849, -3578, -3052, -3404, +-1465, -2534, 368, -1061, 2092, 735, 3325, 2386, +3649, 3495, 3002, 3943, 1670, 3611, -5, 2378, +-1604, 558, -2765, -1266, -3392, -2759, -3267, -3746, +-2230, -3909, -681, -3071, 816, -1562, 2046, 107, +2782, 1647, 2739, 2876, 1983, 3484, 843, 3203, +-300, 2203, -1224, 911, -1886, -465, -2146, -1727, +-1856, -2490, -1162, -2587, -329, -2197, 419, -1446, +928, -366, 1140, 724, 1083, 1418, 767, 1709, +313, 1743, 71, 1422, 69, 727, -69, -25, +-437, -559, -682, -899, -757, -1073, -912, -958, +-991, -567, -631, -128, 47, 260, 590, 626, +924, 809, 1234, 605, 1264, 113, 647, -345, +-316, -664, -1126, -914, -1636, -906, -1763, -393, +-1267, 423, -181, 1116, 1040, 1576, 1953, 1808, +2278, 1519, 1830, 567, 614, -658, -990, -1755, +-2425, -2552, -3198, -2802, -3005, -2283, -1822, -1100, +20, 437, 1947, 1970, 3406, 3097, 3976, 3531, +3362, 3154, 1662, 1987, -565, 285, -2734, -1498, +-4251, -2951, -4584, -3768, -3633, -3700, -1781, -2727, +533, -1178, 2762, 523, 4141, 2096, 4268, 3311, +3378, 3823, 1798, 3392, -241, 2225, -2217, 708, +-3465, -922, -3752, -2423, -3237, -3403, -2094, -3563, +-545, -2922, 1026, -1716, 2164, -178, 2691, 1441, +2676, 2760, 2148, 3398, 1238, 3196, 152, 2276, +-915, 865, -1768, -745, -2247, -2127, -2314, -2895, +-1982, -2896, -1312, -2132, -421, -837, 581, 523, +1518, 1626, 2153, 2319, 2367, 2363, 2119, 1639, +1326, 456, 104, -702, -1150, -1537, -2074, -1866, +-2601, -1614, -2626, -905, -2019, 63, -963, 1006, +257, 1570, 1467, 1597, 2465, 1203, 2930, 560, +2641, -225, 1642, -963, 231, -1372, -1217, -1411, +-2409, -1259, -3144, -896, -3225, -245, -2517, 437, +-1134, 923, 506, 1359, 2061, 1787, 3328, 1889, +3848, 1482, 3233, 720, 1644, -287, -323, -1452, +-2184, -2434, -3592, -2900, -4110, -2725, -3532, -1882, +-2118, -472, -247, 1208, 1723, 2695, 3277, 3571, +3928, 3612, 3535, 2807, 2232, 1318, 354, -524, +-1549, -2257, -2892, -3395, -3326, -3678, -2933, -3109, +-2003, -1869, -751, -296, 566, 1215, 1634, 2341, +2200, 2874, 2210, 2754, 1722, 2075, 893, 1058, +18, 19, -699, -796, -1214, -1307, -1449, -1510, +-1361, -1464, -1105, -1302, -795, -1121, -358, -899, +169, -567, 632, -120, 992, 424, 1165, 1084, +1055, 1796, 711, 2271, 277, 2198, -254, 1629, +-871, 767, -1277, -402, -1283, -1752, -1011, -2766, +-530, -3079, 198, -2699, 910, -1721, 1189, -262, +1008, 1325, 630, 2538, 125, 3090, -482, 2975, +-925, 2184, -982, 816, -830, -676, -617, -1840, +-162, -2522, 448, -2600, 814, -1954, 816, -844, +701, 263, 503, 1201, 103, 1858, -353, 1877, +-638, 1240, -746, 426, -797, -274, -814, -888, +-685, -1263, -340, -1116, 119, -543, 533, 130, +839, 743, 1076, 1163, 1147, 1174, 889, 756, +347, 116, -238, -593, -783, -1224, -1350, -1498, +-1708, -1301, -1548, -828, -971, -193, -340, 592, +272, 1259, 921, 1533, 1402, 1503, 1552, 1285, +1464, 842, 1157, 196, 571, -516, -191, -1113, +-911, -1484, -1469, -1660, -1838, -1656, -1897, -1332, +-1604, -654, -1045, 144, -302, 921, 624, 1650, +1551, 2137, 2157, 2248, 2347, 2025, 2150, 1452, +1487, 503, 338, -699, -959, -1930, -1977, -2906, +-2664, -3363, -3058, -3142, -2867, -2180, -1875, -586, +-305, 1289, 1317, 2983, 2613, 4090, 3428, 4299, +3557, 3476, 2794, 1799, 1249, -262, -549, -2220, +-2138, -3719, -3284, -4391, -3780, -3953, -3381, -2567, +-2084, -784, -293, 977, 1421, 2469, 2600, 3336, +3044, 3369, 2842, 2745, 2053, 1712, 760, 450, +-614, -748, -1625, -1582, -2117, -2020, -2067, -2142, +-1526, -1961, -793, -1539, -110, -952, 468, -227, +707, 508, 510, 1128, 287, 1627, 388, 1919, +562, 1883, 614, 1527, 723, 889, 759, 85, +415, -678, -160, -1323, -734, -1819, -1303, -2030, +-1791, -1843, -1893, -1294, -1383, -507, -384, 364, +755, 1126, 1684, 1679, 2232, 2017, 2236, 2061, +1612, 1712, 531, 1018, -647, 149, -1574, -778, +-2111, -1675, -2238, -2344, -1862, -2572, -959, -2288, +145, -1487, 1009, -255, 1550, 1093, 1851, 2234, +1711, 3032, 1120, 3268, 413, 2657, -251, 1271, +-935, -471, -1491, -2140, -1688, -3350, -1580, -3712, +-1222, -3044, -593, -1566, 243, 279, 1050, 2011, +1563, 3173, 1719, 3374, 1581, 2560, 1105, 1137, +258, -386, -717, -1630, -1444, -2256, -1789, -2088, +-1745, -1301, -1294, -289, -601, 546, 114, 892, +727, 689, 1152, 200, 1258, -254, 1110, -513, +874, -417, 509, 191, 16, 1102, -427, 1764, +-693, 1788, -836, 1151, -944, 44, -998, -1337, +-940, -2635, -729, -3242, -327, -2781, 208, -1413, +745, 434, 1197, 2260, 1529, 3525, 1529, 3815, +1027, 3009, 270, 1314, -485, -743, -1191, -2515, +-1755, -3489, -1915, -3387, -1563, -2323, -838, -750, +65, 862, 908, 2064, 1462, 2466, 1635, 2059, +1349, 1155, 623, 76, -198, -829, -751, -1203, +-965, -959, -870, -297, -415, 442, 175, 898, +562, 868, 589, 350, 219, -523, -431, -1453, +-1103, -1994, -1521, -1831, -1539, -1015, -1005, 204, +126, 1499, 1493, 2509, 2571, 2967, 3083, 2696, +2823, 1636, 1618, 27, -314, -1644, -2351, -2887, +-3924, -3416, -4595, -3163, -4029, -2183, -2296, -639, +104, 1062, 2489, 2405, 4290, 3113, 5037, 3140, +4471, 2507, 2769, 1365, 354, 6, -2158, -1291, +-3999, -2246, -4652, -2580, -4149, -2312, -2754, -1710, +-787, -887, 1197, 79, 2588, 925, 3154, 1448, +2931, 1680, 2079, 1673, 907, 1369, -191, 814, +-955, 233, -1310, -247, -1244, -666, -979, -973, +-778, -1044, -735, -988, -794, -959, -812, -832, +-635, -531, -220, -182, 389, 218, 1121, 690, +1792, 1097, 2107, 1397, 1914, 1572, 1266, 1440, +232, 911, -1055, 114, -2277, -786, -2960, -1610, +-2875, -2172, -2037, -2299, -622, -1861, 910, -889, +2087, 377, 2714, 1555, 2728, 2346, 2001, 2595, +700, 2214, -630, 1228, -1616, -136, -2197, -1435, +-2221, -2179, -1555, -2187, -479, -1613, 526, -676, +1214, 373, 1433, 1167, 1125, 1425, 509, 1124, +-192, 456, -786, -258, -1042, -724, -818, -825, +-282, -535, 326, 91, 912, 797, 1251, 1217, +1061, 1154, 418, 625, -330, -197, -1014, -1079, +-1570, -1739, -1751, -1859, -1398, -1335, -699, -385, +169, 704, 1099, 1613, 1864, 2037, 2134, 1879, +1841, 1226, 1151, 194, 147, -929, -992, -1660, +-1906, -1757, -2308, -1358, -2176, -645, -1595, 249, +-661, 1054, 451, 1415, 1455, 1152, 2051, 457, +2077, -282, 1592, -865, 748, -1179, -210, -1009, +-973, -353, -1361, 452, -1361, 1124, -1077, 1517, +-600, 1463, -135, 872, 133, -79, 245, -1051, +303, -1778, 283, -2079, 175, -1790, 142, -934, +261, 193, 461, 1239, 653, 1976, 677, 2248, +411, 1944, -26, 1128, -514, 72, -1009, -886, +-1365, -1562, -1342, -1919, -952, -1870, -368, -1309, +361, -411, 1038, 403, 1377, 917, 1311, 1226, +1006, 1330, 542, 1064, -59, 530, -605, 47, +-888, -263, -858, -407, -664, -364, -500, -197, +-419, -43, -356, -32, -219, -210, 11, -501, +197, -803, 343, -969, 600, -810, 935, -318, +1018, 361, 739, 1101, 347, 1705, -86, 1925, +-676, 1686, -1274, 1066, -1487, 114, -1246, -1034, +-777, -1988, -191, -2401, 476, -2263, 1054, -1711, +1310, -787, 1134, 354, 686, 1331, 175, 1915, +-312, 2181, -658, 2146, -753, 1716, -576, 987, +-274, 130, -20, -797, 66, -1646, 40, -2211, +-3, -2440, -107, -2301, -272, -1658, -353, -555, +-208, 722, 103, 1922, 410, 2811, 654, 3087, +795, 2628, 698, 1563, 354, 124, -109, -1346, +-530, -2432, -854, -2862, -1044, -2621, -1029, -1847, +-786, -719, -293, 521, 369, 1517, 950, 1992, +1170, 1901, 1064, 1406, 733, 730, 163, 63, +-461, -415, -834, -607, -926, -604, -835, -541, +-518, -492, 30, -461, 572, -398, 865, -335, +861, -295, 516, -169, -100, 90, -763, 353, +-1216, 506, -1294, 559, -900, 571, -131, 511, +703, 296, 1360, 31, 1701, -82, 1625, -63, +1057, -55, 106, -97, -883, -238, -1621, -507, +-2034, -755, -1990, -844, -1405, -794, -470, -579, +474, -95, 1209, 599, 1649, 1241, 1736, 1612, +1519, 1666, 1069, 1368, 493, 679, -115, -246, +-695, -1133, -1223, -1785, -1611, -2031, -1738, -1785, +-1599, -1148, -1183, -321, -471, 515, 377, 1222, +1162, 1628, 1793, 1632, 2130, 1323, 2047, 841, +1540, 260, 696, -272, -395, -593, -1467, -742, +-2141, -860, -2276, -945, -1982, -904, -1382, -768, +-496, -630, 480, -406, 1224, 15, 1607, 542, +1680, 1007, 1492, 1335, 1117, 1512, 627, 1455, +68, 1064, -447, 366, -802, -472, -1100, -1242, +-1425, -1812, -1548, -2102, -1309, -1978, -832, -1353, +-261, -367, 443, 672, 1174, 1541, 1651, 2144, +1788, 2345, 1661, 2007, 1245, 1189, 461, 152, +-546, -851, -1433, -1653, -1960, -2099, -2073, -2077, +-1713, -1609, -924, -820, 25, 101, 845, 916, +1438, 1457, 1707, 1637, 1573, 1437, 1096, 1002, +403, 523, -314, 23, -941, -460, -1356, -800, +-1386, -979, -999, -1050, -400, -1008, 178, -774, +649, -330, 945, 175, 982, 646, 755, 1078, +319, 1295, -220, 1102, -691, 608, -995, 43, +-1065, -509, -806, -992, -230, -1236, 409, -1063, +960, -526, 1342, 82, 1303, 523, 817, 798, +157, 944, -496, 847, -1060, 464, -1368, -13, +-1385, -407, -1171, -695, -675, -841, 77, -777, +797, -527, 1254, -172, 1467, 221, 1451, 565, +1043, 810, 301, 929, -332, 828, -669, 513, +-961, 128, -1307, -299, -1350, -774, -975, -1153, +-519, -1265, -98, -1047, 422, -555, 928, 75, +1171, 723, 1137, 1287, 964, 1605, 734, 1503, +367, 956, -175, 181, -688, -583, -982, -1218, +-1170, -1595, -1227, -1561, -965, -1153, -448, -548, +104, 147, 576, 857, 950, 1382, 1114, 1537, +1028, 1354, 759, 899, 344, 243, -162, -452, +-592, -1049, -808, -1406, -794, -1361, -605, -993, +-304, -522, 12, 36, 244, 683, 329, 1181, +237, 1327, 45, 1149, -125, 739, -146, 158, +-77, -496, 2, -1043, 181, -1307, 433, -1209, +552, -780, 475, -136, 279, 550, -67, 1089, +-479, 1324, -724, 1137, -748, 571, -655, -156, +-428, -780, -78, -1117, 234, -1075, 390, -665, +459, -51, 491, 488, 434, 776, 328, 783, +233, 490, 177, 19, 144, -367, 95, -520, +-55, -429, -342, -124, -666, 270, -922, 553, +-1072, 553, -1002, 257, -582, -182, 99, -629, +833, -927, 1469, -860, 1810, -417, 1693, 177, +1229, 751, 476, 1170, -536, 1245, -1507, 890, +-2109, 233, -2244, -497, -1897, -1072, -1080, -1325, +16, -1202, 1127, -730, 1973, -57, 2297, 575, +2057, 993, 1417, 1143, 505, 978, -528, 545, +-1388, 43, -1841, -347, -1885, -609, -1553, -753, +-846, -701, 32, -471, 795, -206, 1261, -3, +1390, 171, 1154, 340, 604, 463, -4, 514, +-402, 502, -551, 403, -502, 224, -264, 2, +13, -299, 134, -633, 62, -823, -151, -815, +-441, -649, -657, -267, -666, 328, -405, 917, +82, 1266, 660, 1281, 1170, 950, 1426, 286, +1242, -563, 549, -1312, -382, -1690, -1151, -1551, +-1572, -936, -1632, -47, -1258, 895, -443, 1629, +538, 1875, 1289, 1511, 1607, 664, 1506, -345, +1002, -1180, 127, -1660, -812, -1670, -1349, -1129, +-1388, -211, -1052, 707, -420, 1326, 343, 1479, +939, 1129, 1161, 442, 976, -348, 494, -1024, +-82, -1297, -632, -1015, -997, -356, -949, 367, +-515, 908, 29, 1120, 508, 961, 814, 428, +817, -312, 504, -947, 19, -1254, -444, -1141, +-661, -623, -561, 132, -355, 867, -118, 1341, +241, 1344, 587, 851, 625, 79, 368, -656, +37, -1133, -290, -1234, -595, -894, -724, -246, +-501, 394, -17, 811, 409, 945, 631, 759, +709, 289, 594, -300, 271, -738, -126, -857, +-454, -673, -679, -237, -730, 355, -545, 842, +-210, 974, 147, 761, 426, 334, 577, -204, +553, -712, 383, -994, 178, -978, 10, -704, +-122, -266, -218, 211, -272, 619, -285, 877, +-287, 914, -271, 737, -183, 424, -61, 44, +54, -316, 181, -564, 316, -663, 380, -641, +389, -533, 357, -393, 207, -228, -43, 11, +-252, 261, -365, 409, -478, 501, -541, 629, +-374, 677, -37, 514, 217, 207, 331, -60, +393, -286, 425, -567, 350, -781, 158, -780, +-22, -661, -82, -474, -129, -146, -282, 226, +-371, 513, -279, 726, -154, 863, -103, 842, +2, 652, 202, 354, 335, 3, 336, -365, +268, -701, 161, -947, 12, -1039, -186, -921, +-357, -616, -340, -196, -187, 277, -34, 748, +143, 1089, 345, 1186, 409, 1058, 300, 761, +103, 276, -176, -351, -431, -876, -505, -1121, +-390, -1157, -204, -1044, 1, -674, 247, -120, +512, 372, 660, 712, 595, 907, 371, 926, +87, 771, -231, 474, -534, 96, -716, -256, +-733, -493, -552, -555, -242, -494, 55, -387, +334, -234, 660, -76, 842, -62, 729, -167, +494, -202, 224, -103, -154, 80, -496, 358, +-623, 707, -628, 938, -564, 922, -338, 618, +-8, 35, 208, -644, 250, -1146, 225, -1367, +212, -1268, 169, -794, 120, -66, 226, 657, +461, 1155, 586, 1308, 466, 1094, 190, 603, +-186, -15, -640, -558, -1034, -851, -1194, -830, +-1050, -563, -634, -175, -37, 190, 653, 388, +1286, 351, 1614, 119, 1526, -153, 1110, -336, +457, -359, -371, -185, -1118, 116, -1492, 415, +-1452, 646, -1155, 696, -754, 441, -261, -11, +320, -414, 803, -675, 1019, -821, 1074, -773, +1057, -461, 880, 0, 533, 429, 148, 724, +-207, 782, -549, 634, -893, 388, -1164, 20, +-1233, -423, -1065, -711, -651, -721, -12, -548, +688, -259, 1195, 120, 1444, 523, 1448, 768, +1090, 729, 417, 458, -251, 54, -743, -418, +-1052, -821, -1090, -976, -861, -847, -487, -458, +-83, 110, 202, 688, 266, 1108, 238, 1288, +201, 1099, 130, 509, 128, -263, 311, -947, +609, -1403, 829, -1535, 832, -1229, 560, -528, +60, 324, -576, 1016, -1195, 1398, -1559, 1433, +-1477, 1115, -1007, 488, -304, -239, 505, -825, +1225, -1160, 1647, -1172, 1662, -873, 1277, -411, +599, 65, -162, 492, -810, 745, -1173, 752, +-1186, 578, -937, 333, -521, 62, -58, -216, +243, -422, 317, -477, 288, -410, 233, -300, +182, -110, 215, 162, 364, 379, 546, 416, +652, 339, 582, 184, 321, -86, -72, -385, +-558, -571, -1041, -571, -1299, -365, -1161, -8, +-703, 354, -44, 647, 700, 789, 1281, 673, +1468, 319, 1248, -112, 721, -525, 19, -841, +-649, -926, -1041, -735, -1049, -335, -736, 139, +-223, 544, 318, 794, 668, 854, 665, 657, +397, 256, 26, -167, -374, -461, -669, -591, +-643, -597, -273, -476, 220, -199, 655, 115, +928, 286, 931, 328, 628, 315, 112, 237, +-445, 73, -836, -95, -960, -184, -829, -196, +-497, -156, -69, -83, 327, -5, 593, 69, +653, 130, 488, 121, 257, 78, 127, 43, +95, -13, 75, -102, 73, -148, 106, -145, +96, -136, -66, -100, -357, -24, -594, 55, +-673, 94, -627, 95, -404, 57, 54, 15, +545, -3, 885, 25, 1058, 90, 1002, 165, +659, 221, 155, 187, -336, 18, -754, -221, +-1042, -440, -1071, -638, -755, -729, -243, -581, +220, -178, 594, 320, 907, 775, 989, 1114, +730, 1240, 301, 1006, -100, 406, -456, -350, +-719, -1025, -746, -1471, -523, -1598, -135, -1282, +288, -597, 596, 214, 712, 929, 637, 1381, +368, 1438, -16, 1136, -377, 591, -643, -49, +-737, -548, -576, -773, -188, -764, 254, -624, +581, -411, 733, -215, 713, -125, 501, -178, +175, -276, -110, -242, -289, -7, -393, 332, +-422, 689, -313, 1039, -127, 1219, -19, 1047, +-17, 522, -25, -192, -34, -958, -35, -1595, +51, -1893, 247, -1725, 497, -1111, 688, -179, +685, 854, 490, 1687, 196, 2090, -186, 1935, +-603, 1281, -911, 329, -1001, -632, -870, -1342, +-547, -1645, -95, -1514, 419, -1021, 926, -375, +1263, 194, 1278, 601, 999, 750, 562, 614, +28, 372, -531, 208, -954, 98, -1104, 64, +-1025, 167, -812, 311, -450, 310, 79, 116, +595, -192, 877, -548, 929, -850, 827, -985, +579, -872, 220, -526, -119, -15, -315, 534, +-328, 991, -244, 1204, -167, 1097, -93, 735, +-30, 223, -65, -326, -220, -770, -377, -965, +-419, -914, -332, -687, -128, -375, 248, -57, +727, 168, 1101, 288, 1215, 353, 1050, 399, +630, 412, -5, 398, -730, 386, -1307, 317, +-1504, 151, -1344, -76, -955, -321, -341, -590, +433, -765, 1103, -740, 1465, -559, 1496, -290, +1236, 93, 741, 541, 138, 835, -382, 854, +-723, 664, -913, 363, -978, -24, -865, -404, +-597, -651, -300, -682, -26, -528, 277, -284, +576, -28, 762, 155, 825, 229, 827, 213, +764, 139, 557, 55, 183, 52, -248, 106, +-599, 164, -870, 209, -1006, 192, -878, 5, +-530, -296, -129, -514, 268, -564, 651, -467, +909, -243, 981, 125, 895, 512, 662, 736, +276, 689, -156, 425, -511, 17, -752, -440, +-812, -790, -635, -909, -294, -748, 95, -335, +443, 215, 649, 702, 655, 998, 462, 1015, +143, 708, -187, 118, -423, -534, -490, -1028, +-321, -1247, 28, -1120, 410, -646, 726, 55, +847, 763, 652, 1253, 194, 1325, -353, 981, +-830, 354, -1067, -352, -975, -958, -595, -1304, +-1, -1239, 654, -746, 1096, -50, 1173, 569, +964, 979, 551, 1089, 38, 828, -375, 273, +-580, -301, -580, -707, -353, -876, -29, -772, +140, -401, 118, 81, 9, 462, -204, 638, +-457, 602, -492, 381, -173, -3, 363, -390, +905, -614, 1319, -606, 1463, -391, 1183, -10, +480, 362, -428, 544, -1280, 516, -1860, 318, +-1978, -6, -1549, -358, -658, -568, 417, -571, +1352, -375, 1957, -68, 2156, 250, 1853, 471, +1064, 548, 80, 469, -774, 231, -1393, -112, +-1717, -424, -1605, -589, -1080, -627, -361, -511, +344, -223, 896, 133, 1191, 401, 1246, 568, +1092, 624, 738, 511, 288, 235, -140, -95, +-475, -376, -654, -577, -670, -641, -562, -566, +-309, -374, 31, -110, 276, 199, 318, 464, +291, 594, 315, 543, 269, 378, 90, 177, +-22, -92, 35, -386, 94, -538, 112, -480, +217, -361, 341, -224, 255, -29, 4, 168, +-197, 247, -341, 244, -442, 227, -367, 177, +-147, 93, 68, 32, 283, 12, 480, -59, +566, -165, 534, -244, 404, -293, 187, -326, +-48, -248, -249, -53, -353, 164, -298, 341, +-121, 439, 60, 402, 174, 207, 254, -73, +262, -372, 134, -557, -3, -538, -17, -351, +-16, -88, -82, 230, -79, 494, 95, 547, +307, 385, 386, 117, 389, -147, 381, -362, +229, -458, -68, -402, -289, -217, -382, -22, +-414, 133, -381, 220, -278, 202, -91, 79, +166, -55, 424, -97, 663, -57, 831, 37, +788, 161, 527, 272, 171, 239, -184, 40, +-487, -235, -653, -484, -623, -662, -479, -653, +-299, -361, -45, 82, 262, 474, 520, 747, +687, 871, 748, 715, 686, 298, 485, -209, +205, -636, -12, -882, -166, -856, -357, -608, +-513, -258, -539, 146, -461, 510, -291, 672, +-56, 577, 195, 341, 468, 67, 687, -172, +718, -332, 602, -350, 436, -252, 223, -98, +-48, 72, -308, 178, -462, 134, -466, -18, +-333, -147, -135, -257, 46, -341, 202, -303, +307, -89, 304, 150, 263, 319, 241, 440, +185, 489, 145, 377, 185, 128, 236, -122, +260, -323, 260, -488, 179, -617, 9, -623, +-195, -494, -387, -251, -502, 57, -473, 374, +-301, 635, -23, 810, 320, 826, 666, 587, +938, 176, 1037, -258, 870, -659, 440, -1006, +-117, -1123, -653, -931, -1020, -508, -1062, 23, +-798, 570, -366, 997, 209, 1157, 796, 1007, +1130, 605, 1166, 63, 959, -498, 485, -886, +-136, -1024, -658, -942, -913, -671, -827, -209, +-444, 278, 97, 571, 621, 661, 914, 636, +879, 467, 617, 151, 231, -114, -249, -229, +-648, -241, -734, -237, -498, -218, -133, -209, +249, -249, 631, -323, 898, -347, 866, -256, +535, -38, 137, 295, -157, 616, -385, 777, +-543, 717, -507, 470, -322, 23, -131, -532, +70, -989, 304, -1165, 492, -1009, 559, -565, +519, 68, 447, 716, 361, 1190, 176, 1296, +-113, 980, -350, 329, -423, -418, -396, -1030, +-280, -1327, 18, -1223, 417, -726, 657, 2, +636, 691, 444, 1127, 154, 1189, -178, 868, +-443, 240, -503, -459, -282, -1002, 136, -1205, +574, -985, 903, -427, 995, 212, 738, 730, +185, 1008, -500, 910, -1077, 479, -1264, -75, +-959, -515, -278, -742, 547, -717, 1226, -471, +1521, -82, 1358, 262, 800, 393, 18, 299, +-713, 90, -1151, -147, -1179, -342, -778, -340, +-64, -92, 697, 315, 1227, 679, 1305, 805, +843, 579, 75, 94, -628, -517, -1072, -1119, +-1113, -1480, -623, -1375, 220, -769, 1017, 115, +1497, 1003, 1548, 1652, 1146, 1885, 374, 1556, +-548, 737, -1305, -299, -1616, -1247, -1363, -1882, +-648, -1987, 251, -1516, 1054, -691, 1559, 240, +1585, 1044, 1107, 1507, 379, 1502, -299, 1122, +-770, 526, -926, -104, -698, -616, -207, -882, +276, -870, 571, -671, 643, -409, 466, -163, +76, 60, -331, 185, -546, 178, -514, 104, +-242, 77, 236, 103, 767, 177, 1134, 277, +1215, 354, 989, 350, 472, 215, -224, -16, +-857, -281, -1214, -527, -1249, -707, -993, -693, +-454, -485, 275, -197, 941, 91, 1365, 375, +1520, 594, 1365, 669, 881, 581, 220, 348, +-385, 54, -801, -235, -993, -461, -949, -577, +-664, -535, -232, -383, 158, -144, 403, 132, +546, 321, 625, 329, 599, 195, 464, 7, +338, -193, 313, -340, 301, -368, 216, -195, +133, 139, 44, 483, -184, 657, -464, 632, +-592, 404, -571, -18, -452, -501, -163, -877, +296, -1038, 720, -942, 923, -597, 954, -115, +911, 380, 694, 757, 245, 983, -211, 1035, +-433, 863, -475, 493, -499, 54, -463, -376, +-272, -801, -57, -1110, 38, -1189, 123, -1032, +303, -716, 475, -229, 549, 364, 608, 905, +696, 1239, 678, 1311, 465, 1119, 164, 667, +-154, 21, -504, -655, -804, -1143, -916, -1367, +-756, -1277, -380, -883, 81, -292, 553, 286, +964, 725, 1179, 930, 1141, 860, 888, 591, +480, 234, 27, -80, -373, -242, -647, -240, +-745, -200, -684, -155, -478, -132, -137, -188, +196, -345, 413, -504, 559, -545, 686, -411, +745, -115, 647, 271, 438, 654, 244, 888, +42, 914, -217, 704, -412, 271, -458, -308, +-378, -796, -207, -1034, 2, -1034, 199, -804, +341, -343, 423, 189, 457, 575, 392, 769, +244, 750, 146, 526, 109, 181, 71, -130, +35, -327, 5, -381, 1, -326, 21, -227, +4, -129, -31, -71, -30, -74, 12, -130, +107, -148, 230, -87, 340, 64, 414, 242, +407, 380, 296, 408, 112, 289, -92, 41, +-222, -249, -242, -499, -142, -643, 105, -570, +369, -266, 506, 154, 538, 502, 453, 687, +186, 660, -174, 404, -469, -61, -569, -568, +-440, -880, -149, -893, 257, -630, 674, -143, +929, 466, 935, 908, 673, 1013, 196, 796, +-302, 325, -641, -311, -734, -868, -583, -1141, +-253, -1051, 197, -609, 617, 54, 794, 697, +698, 1066, 452, 1074, 154, 721, -126, 94, +-326, -634, -318, -1154, -53, -1234, 275, -855, +495, -179, 577, 563, 479, 1130, 208, 1314, +-147, 1053, -487, 367, -653, -510, -538, -1224, +-175, -1511, 322, -1356, 783, -784, 1035, 87, +1000, 951, 690, 1477, 209, 1519, -289, 1108, +-637, 345, -720, -518, -604, -1195, -369, -1451, +8, -1261, 434, -738, 699, -62, 714, 588, +556, 976, 338, 982, 78, 713, -187, 302, +-257, -141, -102, -489, 75, -610, 216, -517, +327, -301, 299, -69, 178, 139, 67, 251, +-55, 205, -165, 45, -166, -96, -62, -161, +63, -193, 194, -159, 354, -40, 478, 123, +476, 234, 381, 268, 274, 220, 174, 123, +52, -28, -101, -223, -235, -378, -323, -440, +-375, -407, -315, -267, -104, -22, 163, 197, +427, 335, 653, 407, 735, 395, 638, 253, +433, 67, 192, -84, -43, -214, -261, -338, +-405, -406, -400, -355, -295, -253, -145, -170, +46, -72, 219, 114, 303, 274, 343, 328, +411, 318, 472, 304, 475, 256, 456, 127, +393, -67, 190, -294, -86, -460, -304, -531, +-459, -524, -488, -447, -356, -223, -176, 109, +54, 429, 370, 619, 624, 663, 716, 587, +689, 365, 557, -3, 328, -415, 62, -691, +-169, -780, -313, -681, -364, -426, -353, -58, +-317, 308, -249, 549, -96, 569, 155, 401, +414, 169, 588, -57, 698, -219, 762, -276, +684, -202, 411, -54, 44, 104, -332, 143, +-660, 32, -811, -145, -703, -317, -373, -460, +100, -489, 572, -297, 884, 54, 997, 436, +901, 715, 627, 809, 277, 649, -111, 272, +-490, -208, -702, -634, -673, -888, -466, -899, +-158, -664, 192, -284, 485, 120, 624, 467, +639, 674, 610, 634, 519, 434, 326, 206, +103, -14, -117, -226, -345, -339, -521, -311, +-554, -210, -421, -136, -174, -140, 128, -163, +448, -164, 732, -144, 899, -112, 882, 18, +639, 225, 242, 386, -164, 423, -509, 363, +-741, 202, -747, -52, -518, -300, -169, -463, +232, -501, 615, -423, 858, -220, 908, 26, +801, 221, 551, 306, 178, 308, -214, 216, +-500, 29, -612, -148, -566, -220, -429, -184, +-210, -103, 116, -2, 463, 102, 716, 202, +822, 208, 736, 96, 459, -57, 112, -187, +-202, -322, -442, -418, -526, -387, -422, -247, +-191, -30, 68, 220, 289, 435, 487, 519, +617, 484, 535, 334, 262, 87, -12, -200, +-201, -424, -274, -537, -166, -537, 57, -426, +241, -247, 335, -28, 346, 159, 265, 279, +106, 318, -59, 317, -153, 285, -150, 244, +-49, 173, 125, 71, 301, -39, 394, -192, +372, -397, 226, -573, -9, -607, -212, -509, +-242, -264, -110, 101, 65, 488, 232, 746, +377, 792, 418, 600, 326, 225, 137, -213, +-133, -599, -368, -805, -417, -767, -258, -481, +54, -65, 426, 348, 718, 617, 800, 679, +602, 511, 170, 137, -296, -323, -568, -678, +-604, -785, -487, -631, -186, -248, 296, 235, +703, 671, 840, 921, 770, 883, 506, 510, +61, -48, -359, -591, -565, -972, -502, -1075, +-219, -863, 97, -410, 307, 124, 414, 583, +399, 806, 250, 779, 53, 564, -59, 266, +-23, -21, 89, -211, 199, -298, 295, -319, +333, -299, 225, -308, -39, -366, -344, -427, +-529, -387, -487, -239, -208, 8, 194, 329, +567, 672, 844, 886, 925, 844, 678, 553, +249, 111, -122, -394, -435, -864, -675, -1088, +-687, -989, -433, -635, -50, -163, 300, 324, +536, 683, 637, 831, 562, 721, 357, 385, +178, -2, 98, -289, 78, -433, 76, -427, +68, -242, 13, 11, -133, 196, -327, 234, +-439, 131, -444, -90, -330, -337, -25, -504, +419, -509, 815, -326, 1026, -16, 1017, 345, +771, 645, 283, 797, -320, 726, -790, 449, +-1024, -1, -1015, -471, -712, -787, -179, -906, +392, -857, 859, -605, 1119, -166, 1096, 276, +810, 587, 378, 723, -61, 706, -408, 540, +-580, 285, -564, -5, -450, -251, -262, -411, +8, -477, 234, -449, 320, -363, 326, -265, +331, -181, 338, -64, 309, 82, 266, 235, +269, 345, 242, 411, 97, 423, -105, 360, +-283, 178, -377, -110, -348, -380, -257, -537, +-133, -564, 76, -490, 330, -286, 514, 4, +579, 279, 542, 441, 426, 493, 227, 427, +-24, 228, -244, -26, -370, -233, -377, -381, +-311, -482, -205, -436, -19, -243, 218, 10, +409, 242, 523, 418, 531, 464, 415, 370, +237, 164, 39, -110, -140, -369, -222, -528, +-221, -527, -214, -374, -179, -106, -59, 161, +114, 361, 244, 454, 312, 418, 365, 243, +353, 14, 215, -154, 40, -226, -53, -228, +-61, -189, -61, -104, -81, -56, -81, -92, +-76, -161, -77, -170, -16, -152, 108, -99, +220, 60, 321, 302, 403, 492, 412, 546, +334, 458, 155, 213, -115, -120, -376, -469, +-515, -748, -481, -849, -291, -679, 16, -310, +390, 112, 699, 456, 817, 670, 726, 735, +450, 611, 53, 317, -331, -36, -601, -285, +-700, -427, -567, -487, -230, -453, 167, -310, +463, -136, 607, 6, 618, 95, 483, 129, +237, 120, 6, 82, -139, 78, -207, 123, +-170, 184, -58, 208, 30, 196, 38, 110, +-25, -36, -114, -194, -161, -346, -117, -466, +37, -468, 271, -333, 515, -159, 671, 52, +643, 290, 420, 471, 88, 517, -269, 462, +-573, 305, -742, 75, -695, -155, -395, -341, +52, -472, 466, -533, 745, -490, 844, -353, +728, -118, 440, 155, 96, 395, -195, 549, +-366, 599, -407, 476, -328, 198, -187, -127, +-65, -422, 21, -631, 74, -690, 76, -533, +62, -207, 117, 179, 261, 494, 436, 672, +569, 649, 585, 414, 425, 24, 93, -384, +-315, -667, -660, -739, -840, -582, -800, -270, +-530, 129, -55, 503, 523, 745, 978, 729, +1141, 463, 1026, 59, 677, -335, 118, -639, +-460, -777, -795, -651, -827, -297, -641, 116, +-309, 439, 68, 626, 356, 595, 510, 341, +513, -25, 377, -338, 213, -522, 101, -517, +13, -305, -18, 11, 77, 306, 175, 476, +130, 469, -15, 263, -168, -62, -311, -393, +-391, -586, -313, -586, -92, -404, 173, -97, +414, 254, 569, 529, 577, 628, 452, 548, +247, 319, -20, 21, -278, -248, -410, -418, +-389, -517, -256, -517, -65, -386, 117, -185, +239, -1, 286, 164, 248, 308, 141, 382, +49, 390, 22, 339, 44, 244, 87, 98, +145, -57, 202, -219, 201, -370, 89, -469, +-88, -469, -222, -380, -282, -220, -279, 27, +-182, 289, 9, 474, 213, 528, 357, 478, +425, 306, 409, 36, 304, -245, 130, -424, +-66, -466, -215, -388, -270, -224, -234, -35, +-143, 125, -32, 217, 78, 231, 164, 147, +204, 37, 180, -46, 127, -93, 79, -110, +37, -68, 0, 31, 9, 127, 101, 165, +209, 127, 228, 50, 147, -58, 27, -172, +-102, -270, -212, -299, -261, -260, -215, -151, +-101, 3, 26, 157, 174, 280, 342, 353, +439, 337, 422, 213, 312, 68, 121, -90, +-82, -253, -227, -345, -307, -311, -294, -244, +-190, -169, -105, -43, -59, 85, 46, 129, +195, 126, 286, 156, 326, 175, 363, 159, +341, 120, 222, 95, 72, 45, -87, -64, +-250, -203, -353, -287, -370, -304, -308, -269, +-158, -161, 63, -7, 309, 148, 486, 273, +528, 329, 467, 227, 321, 54, 70, -58, +-194, -109, -361, -145, -418, -98, -363, 18, +-206, 63, 7, 6, 228, -102, 375, -194, +385, -244, 300, -225, 193, -117, 78, 93, +-54, 293, -157, 384, -196, 363, -189, 250, +-134, 52, -23, -174, 91, -342, 180, -423, +247, -355, 250, -170, 180, 13, 71, 125, +-53, 206, -145, 216, -185, 131, -190, 31, +-104, -27, 76, -45, 266, -24, 416, 36, +448, 83, 279, 92, -15, 26, -277, -96, +-463, -231, -543, -329, -406, -359, -65, -256, +321, -35, 652, 212, 839, 446, 758, 592, +421, 560, -60, 335, -580, 4, -934, -377, +-948, -685, -666, -806, -172, -696, 433, -387, +917, 52, 1081, 480, 927, 750, 541, 824, +-1, 676, -568, 351, -941, -48, -954, -420, +-626, -710, -109, -803, 417, -661, 769, -362, +823, -6, 586, 315, 174, 527, -256, 582, +-510, 471, -476, 245, -250, 58, 11, -45, +260, -118, 448, -187, 463, -218, 275, -266, +-19, -380, -277, -478, -406, -435, -395, -196, +-255, 153, -2, 519, 261, 815, 415, 927, +435, 710, 352, 225, 193, -351, 2, -855, +-149, -1119, -224, -1016, -240, -613, -211, -64, +-134, 528, -18, 938, 82, 979, 110, 725, +103, 346, 142, -126, 188, -529, 185, -677, +160, -603, 117, -433, 35, -191, -71, 74, +-167, 252, -210, 340, -173, 360, -76, 299, +52, 142, 174, -23, 249, -155, 295, -246, +285, -266, 125, -172, -152, -29, -351, 50, +-364, 76, -259, 78, -77, 39, 190, -35, +455, -44, 562, -5, 461, 47, 221, 101, +-62, 141, -329, 135, -535, 76, -572, -49, +-409, -207, -167, -281, 96, -281, 370, -252, +547, -135, 559, 107, 457, 298, 284, 370, +77, 380, -131, 299, -312, 107, -397, -112, +-361, -302, -267, -424, -167, -397, -67, -278, +25, -144, 110, 13, 222, 182, 349, 243, +413, 224, 397, 224, 340, 232, 202, 191, +-27, 114, -238, 38, -357, -63, -398, -216, +-389, -409, -341, -498, -242, -432, -83, -268, +92, -55, 279, 216, 487, 463, 643, 591, +665, 579, 531, 435, 267, 194, -88, -102, +-478, -382, -775, -607, -851, -705, -713, -642, +-421, -398, 6, -14, 447, 405, 732, 695, +827, 749, 751, 572, 491, 235, 127, -148, +-208, -477, -468, -618, -599, -515, -495, -232, +-223, 89, 11, 341, 141, 419, 175, 284, +84, 32, -40, -213, -69, -371, -5, -396, +167, -231, 410, 59, 529, 338, 431, 455, +244, 392, 11, 206, -324, -13, -655, -191, +-799, -276, -706, -288, -412, -264, 29, -193, +519, -117, 912, -75, 1061, -32, 879, 101, +400, 289, -205, 443, -728, 471, -1021, 318, +-983, 10, -597, -316, -24, -526, 486, -582, +799, -444, 876, -132, 677, 241, 264, 475, +-148, 497, -441, 349, -632, 102, -659, -193, +-461, -404, -127, -442, 233, -364, 554, -182, +706, 109, 590, 405, 295, 547, -29, 522, +-301, 355, -454, 84, -452, -233, -335, -510, +-196, -701, -83, -746, 31, -583, 166, -244, +317, 194, 454, 623, 482, 967, 349, 1103, +145, 910, -62, 386, -291, -262, -461, -844, +-469, -1233, -386, -1284, -287, -946, -107, -361, +154, 273, 370, 822, 490, 1120, 536, 1094, +459, 805, 244, 366, -14, -134, -249, -538, +-424, -762, -461, -826, -354, -718, -220, -440, +-102, -58, 47, 286, 191, 493, 237, 536, +217, 474, 239, 307, 283, 62, 271, -135, +196, -175, 71, -133, -83, -108, -216, -84, +-352, -75, -500, -126, -522, -219, -357, -252, +-122, -202, 155, -71, 509, 130, 793, 369, +835, 547, 628, 560, 234, 362, -247, -15, +-644, -420, -847, -684, -847, -732, -618, -587, +-202, -218, 230, 265, 583, 637, 823, 771, +812, 705, 510, 431, 120, -6, -204, -431, +-456, -712, -570, -793, -483, -651, -279, -316, +-72, 96, 93, 501, 199, 757, 232, 766, +210, 566, 170, 254, 115, -117, 55, -465, +30, -671, 33, -689, 18, -507, -30, -215, +-120, 50, -235, 226, -285, 363, -235, 427, +-130, 422, 47, 395, 289, 320, 459, 147, +428, -87, 235, -325, 0, -543, -235, -641, +-437, -571, -480, -370, -310, -95, -43, 236, +218, 516, 440, 658, 541, 664, 409, 567, +72, 346, -286, -50, -511, -504, -575, -801, +-462, -830, -154, -672, 255, -345, 583, 112, +680, 553, 554, 802, 297, 808, -81, 568, +-500, 146, -729, -300, -684, -637, -462, -761, +-119, -625, 258, -270, 538, 149, 669, 501, +652, 657, 460, 568, 96, 281, -314, -81, +-597, -380, -682, -521, -589, -507, -348, -392, +-4, -151, 327, 149, 514, 379, 531, 494, +462, 531, 313, 419, 28, 152, -291, -129, +-482, -358, -506, -545, -374, -604, -128, -466, +151, -228, 355, 49, 352, 337, 175, 566, +14, 629, -85, 532, -159, 299, -145, -37, +-31, -377, 65, -576, 84, -566, 69, -406, +50, -179, 23, 51, -30, 251, -104, 331, +-163, 304, -186, 236, -164, 163, -70, 62, +80, -25, 202, -81, 272, -135, 311, -167, +252, -184, 62, -201, -136, -198, -273, -113, +-385, 7, -426, 151, -317, 320, -77, 428, +188, 346, 374, 97, 458, -175, 432, -372, +247, -444, -49, -389, -304, -191, -439, 85, +-424, 306, -238, 372, 22, 329, 227, 214, +346, 48, 315, -122, 103, -247, -122, -318, +-246, -308, -318, -179, -289, -21, -95, 113, +118, 230, 266, 307, 403, 279, 425, 183, +225, 54, -67, -111, -337, -251, -539, -304, +-551, -278, -345, -191, -73, -34, 172, 99, +353, 161, 394, 191, 328, 224, 249, 212, +160, 154, 67, 77, -45, -38, -242, -197, +-442, -338, -500, -383, -429, -318, -254, -132, +45, 107, 353, 308, 515, 408, 504, 405, +353, 272, 123, 59, -103, -147, -285, -333, +-386, -450, -370, -398, -255, -186, -87, 40, +105, 225, 263, 337, 302, 319, 187, 179, +-34, 23, -252, -116, -334, -207, -219, -205, +30, -146, 287, -65, 408, 39, 319, 153, +121, 186, -81, 151, -285, 75, -427, -47, +-442, -212, -373, -304, -214, -241, 49, -83, +323, 75, 535, 203, 638, 319, 528, 363, +201, 288, -206, 105, -561, -113, -757, -343, +-707, -519, -424, -556, -26, -401, 365, -90, +647, 276, 701, 588, 503, 711, 146, 586, +-258, 269, -549, -106, -590, -466, -415, -674, +-151, -614, 115, -348, 295, -49, 332, 244, +238, 474, 49, 482, -121, 299, -159, 70, +-118, -154, -88, -321, -53, -282, 10, -110, +76, 47, 97, 168, 46, 244, -44, 186, +-114, 17, -145, -160, -162, -323, -159, -391, +-71, -279, 111, -43, 281, 188, 370, 399, +349, 525, 156, 486, -175, 269, -462, -52, +-573, -377, -520, -611, -329, -673, -22, -535, +283, -194, 469, 240, 542, 602, 515, 742, +368, 652, 137, 354, -171, -82, -558, -480, +-834, -633, -805, -510, -541, -267, -176, -41, +253, 110, 640, 189, 828, 202, 786, 201, +548, 203, 168, 229, -252, 246, -604, 178, +-823, -16, -829, -268, -592, -486, -223, -606, +147, -541, 456, -290, 643, 74, 666, 440, +559, 738, 342, 856, 29, 723, -301, 350, +-598, -163, -805, -655, -739, -973, -360, -1026, +69, -798, 348, -336, 507, 224, 547, 756, +412, 1092, 159, 1095, -75, 752, -236, 225, +-342, -325, -368, -763, -271, -963, -79, -891, +121, -583, 203, -137, 101, 300, -80, 551, +-186, 618, -157, 548, -18, 347, 152, 51, +244, -197, 203, -295, 82, -242, -10, -75, +-43, 96, -81, 150, -169, 36, -305, -174, +-421, -396, -391, -521, -170, -467, 163, -188, +484, 261, 650, 709, 554, 936, 240, 852, +-124, 516, -380, 12, -512, -522, -582, -924, +-537, -1037, -286, -846, 61, -433, 340, 55, +520, 490, 569, 754, 410, 795, 90, 647, +-230, 355, -425, -1, -448, -297, -343, -432, +-201, -425, -39, -279, 157, -84, 288, -18, +272, -122, 152, -213, -30, -216, -238, -163, +-322, 41, -184, 402, 63, 708, 235, 782, +220, 620, 45, 198, -131, -350, -207, -776, +-187, -958, -80, -918, 38, -605, 60, -51, +19, 505, -7, 874, 2, 981, 61, 795, +98, 356, -36, -167, -256, -625, -319, -870, +-189, -812, 39, -478, 280, 9, 409, 496, +351, 796, 150, 755, -154, 397, -463, -130, +-591, -582, -509, -781, -328, -640, -23, -220, +392, 306, 661, 674, 627, 740, 371, 518, +-16, 97, -400, -335, -583, -582, -523, -602, +-301, -447, -51, -127, 106, 226, 204, 459, +297, 520, 294, 406, 151, 126, -91, -172, +-375, -367, -512, -473, -344, -421, 23, -158, +411, 177, 656, 417, 560, 538, 127, 463, +-355, 189, -635, -179, -654, -548, -455, -775, +-176, -639, 33, -160, 204, 373, 373, 761, +458, 875, 444, 616, 318, 51, 15, -533, +-323, -890, -486, -859, -442, -465, -214, 109, +67, 621, 126, 864, -30, 757, -173, 373, +-244, -145, -189, -646, 44, -894, 307, -774, +442, -372, 438, 159, 305, 669, 84, 924, +-150, 793, -391, 356, -588, -208, -606, -661, +-455, -826, -205, -688, 140, -320, 436, 194, +476, 612, 354, 747, 231, 587, 78, 200, +-63, -281, -149, -637, -267, -745, -318, -575, +-173, -104, -1, 475, 85, 865, 102, 914, +-36, 606, -277, -33, -372, -723, -264, -1129, +-12, -1101, 339, -634, 587, 119, 543, 829, +278, 1221, -23, 1189, -270, 686, -445, -100, +-538, -824, -494, -1237, -292, -1212, -26, -709, +228, 58, 429, 794, 426, 1286, 185, 1297, +-85, 749, -271, -117, -341, -952, -166, -1460, +134, -1369, 269, -724, 261, 197, 191, 1081, +-34, 1581, -270, 1437, -348, 753, -418, -198, +-482, -1140, -342, -1637, -59, -1432, 244, -704, +570, 242, 717, 1130, 532, 1537, 199, 1282, +-120, 557, -400, -361, -539, -1120, -524, -1364, +-442, -1046, -283, -378, -63, 443, 134, 1087, +310, 1265, 419, 978, 359, 381, 177, -395, +-20, -1061, -151, -1329, -132, -1101, -52, -462, +-83, 318, -161, 933, -202, 1206, -249, 1087, +-214, 597, -48, -63, 79, -658, 155, -994, +281, -943, 305, -553, 148, -38, -13, 457, +-160, 785, -348, 728, -417, 319, -281, -211, +-42, -664, 215, -815, 368, -482, 315, 108, +126, 653, -94, 1004, -239, 965, -236, 452, +-205, -251, -211, -871, -144, -1283, -27, -1239, +71, -694, 194, 85, 268, 848, 192, 1386, +59, 1393, -90, 868, -237, 90, -192, -715, +-5, -1277, 39, -1297, -9, -806, -13, -81, +-115, 658, -228, 1130, -139, 1113, -64, 672, +-99, 31, 1, -685, 151, -1218, 197, -1246, +331, -746, 443, 35, 223, 837, -106, 1404, +-305, 1453, -501, 956, -612, 161, -452, -689, +-190, -1385, 16, -1603, 211, -1250, 348, -545, +363, 305, 360, 1104, 364, 1512, 248, 1352, +12, 807, -201, 33, -345, -756, -482, -1181, +-570, -1081, -484, -667, -262, -81, -42, 482, +214, 702, 483, 577, 568, 344, 516, 40, +437, -318, 162, -479, -265, -370, -527, -121, +-650, 186, -710, 448, -503, 465, -90, 258, +255, -1, 554, -277, 750, -514, 590, -529, +180, -270, -193, 64, -496, 333, -703, 477, +-655, 428, -343, 201, 91, -27, 493, -211, +697, -391, 602, -438, 247, -250, -192, 32, +-505, 277, -615, 457, -547, 455, -256, 274, +156, 45, 389, -204, 405, -457, 357, -540, +178, -445, -133, -272, -361, 27, -460, 386, +-413, 578, -106, 582, 292, 503, 508, 253, +542, -132, 368, -449, -92, -609, -555, -625, +-718, -436, -646, -100, -424, 212, -60, 432, +304, 536, 560, 482, 702, 265, 652, -34, +366, -295, -37, -394, -435, -326, -754, -152, +-866, 42, -646, 173, -153, 214, 355, 188, +631, 86, 631, -80, 410, -200, 9, -253, +-383, -229, -536, -84, -451, 127, -180, 289, +241, 417, 569, 461, 626, 298, 446, -28, +9, -380, -566, -672, -912, -773, -885, -565, +-602, -145, -120, 361, 435, 829, 825, 1047, +972, 872, 857, 378, 442, -282, -114, -879, +-590, -1153, -916, -1013, -995, -531, -720, 114, +-225, 702, 265, 1033, 639, 1013, 754, 619, +525, 32, 146, -471, -149, -758, -305, -765, +-345, -450, -289, -1, -125, 322, 83, 468, +168, 380, 133, 61, 76, -255, -64, -383, +-259, -370, -342, -159, -303, 250, -136, 612, +223, 786, 563, 757, 586, 407, 323, -244, +-69, -897, -483, -1368, -694, -1503, -577, -1067, +-288, -100, 76, 978, 464, 1792, 652, 2059, +536, 1619, 263, 611, -70, -627, -385, -1676, +-564, -2143, -602, -1846, -494, -938, -177, 242, +240, 1270, 544, 1782, 652, 1620, 572, 872, +323, -161, -56, -1014, -479, -1360, -722, -1162, +-612, -476, -294, 428, 50, 1106, 370, 1269, +481, 910, 274, 163, -3, -684, -164, -1314, +-262, -1516, -259, -1163, -114, -305, 55, 698, +205, 1453, 311, 1787, 266, 1535, 128, 719, +-34, -315, -292, -1216, -520, -1772, -523, -1756, +-355, -1109, -73, -96, 290, 917, 500, 1600, +416, 1680, 219, 1124, 23, 185, -168, -833, +-197, -1556, -63, -1624, 29, -957, 92, 157, +139, 1230, -10, 1804, -259, 1656, -386, 856, +-431, -335, -409, -1493, -227, -2169, 102, -2081, +491, -1235, 799, 113, 849, 1496, 616, 2411, +182, 2515, -355, 1775, -779, 449, -924, -1058, +-833, -2253, -533, -2682, -38, -2136, 419, -826, +612, 741, 560, 1949, 347, 2334, 45, 1853, +-165, 789, -191, -531, -113, -1632, 76, -1977, +318, -1437, 344, -310, 89, 911, -274, 1709, +-650, 1741, -903, 1056, -878, -75, -580, -1291, +-44, -2073, 661, -1999, 1265, -1100, 1470, 300, +1155, 1704, 426, 2487, -448, 2312, -1202, 1291, +-1542, -218, -1308, -1754, -683, -2709, 38, -2620, +691, -1510, 1074, 183, 989, 1831, 557, 2775, +78, 2644, -323, 1526, -592, -158, -603, -1789, +-348, -2742, 68, -2620, 497, -1520, 636, 124, +340, 1750, -111, 2711, -475, 2593, -746, 1543, +-766, 20, -387, -1505, 175, -2484, 663, -2489, +923, -1577, 799, -174, 372, 1256, -143, 2133, +-643, 2049, -926, 1191, -775, 53, -325, -964, +190, -1470, 657, -1237, 845, -496, 573, 321, +41, 870, -437, 910, -758, 422, -824, -245, +-569, -749, -139, -935, 334, -694, 801, -51, +1045, 666, 857, 1093, 346, 1135, -274, 767, +-865, 44, -1202, -739, -1041, -1185, -443, -1160, +273, -705, 784, 18, 883, 665, 569, 928, +99, 812, -228, 408, -346, -197, -320, -685, +-151, -760, 81, -419, 218, 151, 271, 719, +238, 992, 2, 794, -329, 213, -533, -563, +-577, -1256, -414, -1471, 7, -1050, 488, -193, +760, 790, 729, 1535, 430, 1732, -22, 1275, +-420, 381, -606, -590, -576, -1374, -405, -1744, +-181, -1503, 94, -703, 417, 327, 596, 1243, +453, 1765, 113, 1602, -243, 768, -568, -247, +-705, -1099, -467, -1633, -21, -1507, 355, -697, +605, 247, 654, 937, 429, 1317, 134, 1214, +-73, 635, -322, -11, -623, -505, -763, -899, +-650, -980, -385, -617, 5, -99, 503, 263, +831, 413, 765, 395, 480, 254, 199, 77, +-57, -2, -278, 103, -418, 314, -469, 461, +-424, 372, -326, -24, -217, -593, -6, -1045, +272, -1195, 366, -935, 278, -214, 230, 721, +207, 1473, 109, 1821, 6, 1582, -93, 658, +-190, -559, -161, -1556, -35, -2092, -4, -1923, +-51, -984, -99, 244, -255, 1274, -393, 1922, +-264, 1923, -10, 1206, 230, 153, 514, -870, +634, -1629, 440, -1736, 171, -1150, -82, -291, +-386, 617, -604, 1383, -643, 1532, -577, 941, +-351, 31, 105, -791, 555, -1242, 731, -1119, +655, -482, 386, 341, -60, 1057, -467, 1347, +-606, 951, -529, 57, -339, -862, -14, -1448, +330, -1515, 482, -964, 469, 117, 395, 1285, +167, 1955, -222, 1862, -523, 1055, -607, -156, +-549, -1320, -270, -2059, 233, -2109, 586, -1370, +624, -114, 528, 1079, 277, 1816, -127, 2006, +-424, 1570, -518, 617, -448, -440, -219, -1295, +75, -1694, 290, -1441, 365, -761, 297, -4, +86, 690, -197, 1096, -403, 957, -435, 478, +-294, 0, 2, -396, 354, -553, 563, -300, +503, 107, 292, 398, 30, 548, -356, 452, +-687, 30, -621, -514, -323, -890, -132, -947, +101, -672, 417, -161, 455, 468, 244, 1006, +101, 1165, -59, 889, -277, 387, -243, -188, +23, -656, 233, -770, 353, -566, 359, -246, +130, 98, -269, 316, -664, 210, -905, -86, +-824, -371, -381, -546, 255, -411, 849, 35, +1226, 541, 1289, 994, 969, 1290, 252, 1150, +-605, 509, -1211, -381, -1487, -1223, -1408, -1727, +-775, -1690, 156, -1199, 846, -349, 1223, 716, +1304, 1487, 892, 1689, 159, 1506, -461, 960, +-831, 76, -925, -727, -660, -1155, -197, -1248, +229, -992, 568, -365, 675, 306, 430, 690, +10, 736, -466, 480, -871, 55, -875, -373, +-476, -646, 42, -585, 620, -216, 1108, 271, +1169, 787, 770, 1140, 146, 1069, -499, 573, +-972, -136, -1170, -902, -1082, -1521, -706, -1675, +-194, -1279, 349, -450, 949, 564, 1304, 1352, +1094, 1691, 644, 1622, 251, 1094, -292, 215, +-896, -619, -1117, -1181, -943, -1419, -609, -1217, +-136, -626, 313, 32, 574, 534, 795, 789, +881, 738, 578, 474, 133, 138, -235, -146, +-620, -193, -839, -44, -689, 39, -342, 47, +15, 95, 325, 57, 521, -148, 543, -360, +349, -445, 62, -352, -92, -132, -167, 139, +-291, 465, -313, 702, -239, 581, -281, 189, +-263, -182, -48, -509, 74, -716, 123, -545, +357, -109, 551, 292, 513, 669, 384, 852, +64, 588, -468, 86, -785, -427, -784, -921, +-703, -1141, -379, -831, 232, -196, 660, 501, +774, 1144, 769, 1415, 560, 1100, 129, 471, +-312, -256, -602, -976, -646, -1399, -471, -1318, +-188, -780, 158, -36, 421, 654, 400, 1149, +160, 1294, -123, 944, -343, 230, -314, -473, +-31, -913, 217, -1027, 373, -711, 490, -76, +367, 499, 30, 831, -291, 851, -616, 475, +-799, -174, -583, -769, -214, -1029, 131, -902, +651, -467, 1030, 274, 773, 1115, 236, 1509, +-194, 1200, -741, 549, -1152, -153, -913, -959, +-325, -1561, 214, -1518, 759, -941, 1116, -116, +991, 748, 442, 1269, -326, 1295, -997, 1023, +-1199, 455, -915, -343, -380, -856, 291, -815, +910, -509, 1151, -127, 902, 215, 314, 270, +-343, 64, -792, -152, -931, -343, -744, -416, +-277, -139, 258, 348, 718, 736, 1002, 950, +847, 912, 222, 509, -480, -164, -948, -899, +-1101, -1453, -849, -1534, -206, -1023, 580, -155, +1192, 773, 1302, 1576, 792, 1899, 50, 1466, +-538, 498, -981, -521, -1151, -1290, -837, -1714, +-285, -1605, 175, -872, 522, 102, 738, 911, +713, 1433, 433, 1543, 35, 1119, -253, 314, +-354, -486, -403, -1027, -353, -1237, -127, -1081, +26, -638, 11, -45, 1, 531, -48, 844, +-113, 866, -25, 747, 76, 526, 122, 180, +293, -224, 420, -516, 234, -675, -39, -769, +-205, -722, -444, -460, -584, -39, -279, 462, +130, 917, 294, 1136, 432, 975, 469, 500, +147, -127, -246, -802, -433, -1290, -502, -1349, +-398, -941, -5, -198, 487, 639, 799, 1330, +863, 1678, 667, 1467, 90, 665, -760, -403, +-1404, -1360, -1524, -1987, -1142, -1998, -289, -1214, +791, 17, 1565, 1228, 1833, 2169, 1616, 2475, +759, 1897, -469, 707, -1386, -725, -1826, -2064, +-1884, -2728, -1338, -2424, -273, -1443, 733, -47, +1408, 1507, 1718, 2571, 1427, 2722, 639, 2076, +-162, 852, -815, -669, -1202, -1947, -1098, -2567, +-678, -2419, -168, -1523, 370, -177, 626, 1186, +453, 2229, 205, 2526, 42, 1902, -166, 748, +-238, -513, 30, -1636, 332, -2246, 364, -2046, +243, -1206, 70, -117, -215, 969, -530, 1774, +-624, 2046, -426, 1707, -140, 837, 168, -241, +553, -1207, 790, -1866, 665, -1913, 294, -1319, +-210, -460, -749, 470, -1046, 1330, -924, 1728, +-443, 1488, 296, 946, 1036, 305, 1362, -428, +1167, -960, 624, -1141, -187, -1122, -1045, -839, +-1573, -314, -1686, 151, -1387, 477, -589, 737, +481, 848, 1402, 705, 1985, 427, 2048, 164, +1428, -80, 383, -327, -695, -482, -1622, -430, +-2118, -316, -1981, -337, -1396, -297, -594, -100, +335, -48, 1267, -82, 1904, 141, 1980, 504, +1638, 745, 1045, 896, 48, 871, -1085, 487, +-1689, -131, -1803, -774, -1781, -1317, -1322, -1589, +-253, -1455, 748, -874, 1293, 106, 1723, 1158, +1890, 1931, 1356, 2334, 452, 2159, -381, 1151, +-1160, -347, -1708, -1739, -1736, -2738, -1287, -3013, +-499, -2296, 424, -806, 1100, 949, 1382, 2390, +1349, 3034, 964, 2805, 280, 1883, -389, 393, +-819, -1273, -1034, -2374, -1062, -2625, -807, -2233, +-296, -1278, 170, 26, 489, 1182, 766, 1805, +813, 1812, 476, 1379, 61, 689, -172, -116, +-292, -719, -333, -890, -224, -777, -83, -573, +-75, -226, -100, 140, -117, 192, -228, 29, +-327, -117, -257, -255, -46, -259, 236, -40, +505, 284, 714, 662, 856, 936, 788, 855, +370, 505, -267, 76, -884, -470, -1313, -1028, +-1408, -1272, -1125, -1203, -541, -856, 289, -115, +1163, 678, 1700, 1127, 1710, 1325, 1260, 1252, +505, 759, -392, 93, -1244, -485, -1733, -958, +-1593, -1170, -995, -973, -248, -576, 528, -128, +1126, 421, 1255, 912, 924, 1076, 354, 803, +-329, 209, -884, -401, -924, -799, -492, -915, +45, -663, 570, -150, 926, 343, 804, 757, +274, 1032, -367, 893, -996, 397, -1410, -125, +-1292, -611, -640, -1013, 235, -1123, 1060, -925, +1605, -489, 1658, 175, 1154, 795, 227, 1074, +-787, 1081, -1507, 864, -1656, 407, -1178, -40, +-347, -386, 489, -694, 1130, -747, 1338, -546, +961, -391, 206, -294, -596, -144, -1203, -39, +-1325, 47, -794, 269, 126, 486, 1017, 572, +1680, 672, 1845, 714, 1201, 555, -46, 272, +-1354, -143, -2294, -642, -2514, -1034, -1866, -1237, +-578, -1199, 950, -846, 2248, -195, 2804, 613, +2411, 1323, 1302, 1624, -192, 1431, -1710, 984, +-2648, 362, -2611, -462, -1779, -1115, -527, -1355, +864, -1329, 2001, -1032, 2395, -433, 1919, 230, +927, 727, -261, 1019, -1433, 1096, -2181, 916, +-2162, 483, -1391, -94, -157, -610, 1106, -911, +1971, -1009, 2194, -781, 1751, -156, 799, 529, +-382, 1009, -1460, 1238, -2120, 1009, -2143, 228, +-1515, -700, -511, -1318, 536, -1518, 1464, -1347, +2065, -771, 2028, 201, 1361, 1281, 451, 1998, +-457, 2126, -1255, 1720, -1671, 787, -1558, -547, +-1104, -1812, -497, -2578, 159, -2660, 742, -1947, +1054, -594, 992, 920, 710, 2164, 387, 2808, +77, 2672, -174, 1854, -328, 492, -337, -1126, +-263, -2318, -338, -2655, -495, -2318, -501, -1465, +-434, -73, -342, 1357, 3, 2116, 523, 2143, +803, 1668, 783, 759, 689, -354, 417, -1238, +-139, -1602, -615, -1459, -799, -935, -846, -133, +-683, 627, -192, 1001, 332, 976, 619, 676, +701, 209, 571, -220, 213, -398, -215, -372, +-543, -255, -641, -22, -396, 143, 54, 31, +406, -152, 571, -266, 652, -343, 534, -252, +-34, 49, -787, 396, -1121, 685, -959, 851, +-582, 736, 45, 288, 943, -333, 1607, -902, +1502, -1146, 797, -1000, -24, -715, -874, -259, +-1688, 496, -2002, 1134, -1525, 1274, -567, 1085, +447, 738, 1423, 165, 2208, -521, 2298, -1021, +1501, -1191, 223, -1073, -1092, -721, -2137, -152, +-2551, 520, -2160, 1004, -1196, 1133, 40, 996, +1306, 606, 2172, -5, 2284, -603, 1772, -1025, +914, -1169, -128, -847, -1115, -196, -1724, 403, +-1804, 852, -1469, 1118, -871, 994, -102, 500, +646, -121, 1158, -721, 1373, -1117, 1262, -1112, +834, -754, 271, -190, -241, 452, -667, 893, +-906, 1031, -858, 1006, -703, 724, -533, 140, +-168, -448, 299, -821, 566, -960, 700, -906, +797, -718, 616, -316, 166, 304, -177, 796, +-393, 873, -680, 773, -822, 655, -586, 299, +-155, -147, 229, -355, 494, -446, 651, -540, +670, -552, 395, -451, -125, -238, -519, -24, +-564, 86, -488, 229, -509, 528, -382, 740, +73, 638, 454, 447, 457, 273, 383, -87, +444, -586, 346, -945, -28, -971, -265, -726, +-216, -404, -245, 56, -421, 681, -464, 1108, +-374, 1107, -306, 849, -189, 467, 106, -72, +550, -645, 930, -1061, 997, -1196, 769, -925, +471, -379, 25, 123, -728, 581, -1425, 986, +-1612, 1059, -1318, 796, -692, 390, 244, -117, +1260, -558, 1917, -701, 1940, -656, 1356, -504, +350, -160, -766, 138, -1596, 137, -1908, 74, +-1694, 109, -1026, 62, -63, 25, 897, 246, +1526, 596, 1672, 760, 1347, 606, 599, 198, +-345, -276, -1111, -736, -1462, -1201, -1358, -1496, +-849, -1298, -91, -523, 636, 494, 1071, 1377, +1104, 2038, 779, 2334, 252, 1872, -283, 604, +-686, -906, -823, -2118, -671, -2864, -376, -2860, +-73, -1899, 181, -331, 384, 1329, 540, 2620, +554, 3130, 394, 2813, 184, 1834, -11, 298, +-213, -1435, -400, -2680, -480, -3096, -457, -2790, +-450, -1808, -379, -308, -80, 1231, 325, 2465, +653, 3111, 920, 2860, 1010, 1816, 665, 433, +-30, -967, -658, -2216, -1047, -2966, -1221, -2827, +-1038, -1895, -504, -608, 84, 750, 617, 1968, +1107, 2675, 1300, 2607, 1032, 1966, 503, 969, +-134, -338, -823, -1589, -1272, -2322, -1244, -2490, +-870, -2119, -365, -1186, 173, 23, 648, 1131, +926, 1966, 956, 2330, 802, 2035, 511, 1266, +62, 330, -477, -619, -895, -1392, -1011, -1794, +-888, -1799, -661, -1425, -309, -730, 185, 78, +707, 775, 1114, 1252, 1306, 1474, 1196, 1417, +669, 1066, -221, 481, -1095, -183, -1636, -765, +-1752, -1112, -1337, -1171, -447, -1050, 552, -772, +1343, -262, 1835, 313, 1907, 631, 1383, 706, +342, 752, -853, 706, -1828, 472, -2235, 201, +-1878, -1, -874, -125, 417, -206, 1500, -340, +1982, -479, 1795, -526, 1068, -535, 13, -559, +-1016, -486, -1667, -191, -1750, 241, -1244, 650, +-318, 947, 715, 1134, 1536, 1214, 1824, 963, +1371, 244, 354, -616, -798, -1288, -1647, -1717, +-1858, -1819, -1411, -1446, -592, -590, 394, 498, +1382, 1419, 1927, 1941, 1700, 2065, 916, 1726, +-72, 841, -1111, -238, -1831, -1065, -1765, -1701, +-998, -2107, -31, -1890, 796, -1097, 1326, -170, +1377, 703, 816, 1451, -30, 1846, -613, 1756, +-869, 1289, -933, 560, -625, -289, 73, -1000, +750, -1384, 1102, -1444, 1059, -1269, 541, -851, +-331, -193, -1121, 452, -1524, 873, -1442, 1149, +-799, 1229, 188, 942, 1062, 464, 1600, 23, +1746, -423, 1397, -783, 568, -854, -492, -724, +-1369, -513, -1782, -207, -1778, 39, -1393, 104, +-527, 161, 542, 274, 1255, 329, 1509, 409, +1494, 536, 1161, 586, 499, 583, -234, 464, +-835, 28, -1202, -590, -1233, -1068, -981, -1304, +-576, -1280, -68, -897, 403, -203, 628, 577, +655, 1282, 668, 1696, 640, 1607, 445, 1091, +114, 365, -163, -409, -265, -1094, -340, -1491, +-461, -1407, -443, -955, -342, -386, -394, 190, +-484, 588, -341, 642, 4, 506, 384, 421, +756, 360, 1073, 312, 1199, 441, 1052, 593, +586, 487, -199, 223, -1117, -173, -1855, -815, +-2118, -1406, -1815, -1596, -1054, -1400, 124, -906, +1564, -71, 2614, 975, 2732, 1849, 2086, 2245, +1026, 2049, -373, 1371, -1857, 413, -2810, -713, +-2848, -1702, -2068, -2121, -762, -1978, 713, -1531, +1908, -846, 2461, 19, 2231, 798, 1339, 1267, +120, 1438, -990, 1394, -1638, 1193, -1681, 892, +-1153, 508, -235, 30, 679, -498, 1165, -989, +1105, -1371, 614, -1650, -197, -1712, -1060, -1327, +-1489, -548, -1241, 357, -486, 1267, 485, 2012, +1380, 2297, 1944, 2064, 1979, 1453, 1407, 534, +341, -572, -931, -1577, -2052, -2234, -2677, -2426, +-2578, -2129, -1756, -1434, -475, -455, 937, 697, +2199, 1723, 2976, 2326, 2992, 2464, 2243, 2152, +952, 1392, -591, 325, -2077, -794, -3142, -1751, +-3387, -2409, -2690, -2580, -1330, -2079, 292, -1084, +1815, -12, 2889, 990, 3211, 1925, 2676, 2442, +1479, 2226, -18, 1585, -1447, 811, -2495, -205, +-2890, -1266, -2461, -1931, -1346, -2102, 7, -1866, +1196, -1220, 1972, -262, 2164, 721, 1746, 1461, +905, 1815, -65, 1716, -851, 1209, -1289, 389, +-1419, -512, -1238, -1183, -633, -1517, 158, -1427, +613, -801, 696, 87, 781, 791, 831, 1185, +550, 1280, 137, 968, -48, 223, -193, -665, +-611, -1323, -1077, -1548, -1178, -1348, -867, -761, +-364, 238, 268, 1361, 1044, 2060, 1702, 2150, +1902, 1752, 1569, 843, 801, -507, -306, -1825, +-1592, -2602, -2702, -2718, -3138, -2275, -2576, -1283, +-1157, 208, 630, 1780, 2353, 2812, 3664, 3111, +4047, 2842, 3183, 1957, 1405, 461, -735, -1163, +-2815, -2405, -4328, -3124, -4752, -3228, -3851, -2602, +-1808, -1383, 766, 76, 3108, 1464, 4617, 2568, +4940, 3201, 3947, 3143, 1902, 2376, -538, 1197, +-2716, -158, -4213, -1592, -4697, -2800, -3991, -3373, +-2255, -3203, 21, -2410, 2187, -1092, 3693, 553, +4222, 2141, 3687, 3272, 2279, 3666, 442, 3241, +-1373, 2058, -2759, 325, -3418, -1540, -3295, -3046, +-2452, -3812, -1006, -3584, 621, -2377, 1896, -564, +2618, 1333, 2761, 2860, 2263, 3614, 1265, 3321, +107, 2077, -929, 278, -1663, -1530, -1986, -2794, +-1966, -3234, -1674, -2766, -1037, -1410, -156, 444, +651, 2071, 1249, 2907, 1693, 2820, 1936, 1946, +1816, 538, 1240, -1042, 367, -2295, -545, -2744, +-1441, -2325, -2232, -1380, -2594, -169, -2317, 1094, +-1472, 1961, -240, 2138, 1168, 1793, 2435, 1188, +3231, 466, 3281, -249, 2446, -803, 922, -1100, +-832, -1213, -2457, -1292, -3674, -1332, -4037, -1193, +-3262, -839, -1595, -297, 415, 459, 2328, 1373, +3781, 2204, 4321, 2702, 3677, 2671, 2119, 1970, +143, 606, -1859, -1155, -3411, -2799, -4063, -3840, +-3743, -4074, -2603, -3353, -860, -1639, 1053, 557, +2632, 2573, 3528, 4089, 3531, 4747, 2700, 4133, +1416, 2440, -55, 321, -1583, -1785, -2741, -3467, +-3102, -4189, -2785, -3862, -2024, -2732, -773, -1086, +741, 602, 1947, 1910, 2555, 2669, 2583, 2780, +2048, 2335, 1024, 1616, -181, 752, -1204, -202, +-1890, -906, -2161, -1184, -1831, -1358, -981, -1546, +-24, -1511, 772, -1242, 1324, -865, 1433, -372, +1026, 278, 426, 1021, -60, 1637, -401, 1955, +-520, 1915, -340, 1453, -88, 631, 41, -308, +51, -1162, -82, -1856, -360, -2163, -621, -1862, +-709, -1193, -507, -398, 52, 560, 800, 1431, +1386, 1836, 1586, 1770, 1342, 1359, 594, 647, +-581, -237, -1762, -1043, -2433, -1526, -2405, -1523, +-1709, -1061, -367, -358, 1352, 422, 2768, 1115, +3310, 1440, 2928, 1281, 1758, 721, -55, -115, +-2044, -974, -3457, -1600, -3845, -1824, -3210, -1473, +-1764, -578, 181, 539, 2159, 1553, 3579, 2247, +3965, 2403, 3281, 1916, 1831, 885, -35, -461, +-1880, -1734, -3162, -2537, -3537, -2802, -3045, -2489, +-1893, -1471, -359, -79, 1107, 1165, 2095, 2116, +2485, 2661, 2333, 2597, 1730, 2013, 894, 1172, +92, 167, -547, -871, -1020, -1682, -1305, -2189, +-1401, -2407, -1394, -2267, -1322, -1790, -1069, -1014, +-532, 56, 186, 1264, 877, 2396, 1503, 3204, +2073, 3383, 2304, 2800, 1918, 1516, 1041, -262, +-93, -2099, -1377, -3455, -2515, -4010, -3049, -3668, +-2810, -2426, -1903, -593, -514, 1257, 1000, 2721, +2199, 3515, 2866, 3424, 2901, 2558, 2253, 1243, +1108, -153, -193, -1285, -1396, -1972, -2246, -2193, +-2526, -2018, -2272, -1581, -1612, -1047, -648, -501, +377, 61, 1161, 612, 1663, 1159, 1959, 1664, +1960, 1953, 1523, 1958, 778, 1642, -28, 868, +-856, -270, -1681, -1429, -2224, -2363, -2251, -2879, +-1804, -2727, -954, -1823, 249, -408, 1525, 1129, +2423, 2377, 2686, 3008, 2298, 2918, 1366, 2105, +94, 731, -1253, -741, -2298, -1875, -2653, -2455, +-2274, -2360, -1422, -1653, -311, -662, 855, 266, +1768, 933, 2126, 1230, 1814, 1147, 1043, 842, +230, 528, -370, 346, -753, 309, -900, 313, +-771, 273, -516, 69, -363, -421, -361, -1065, +-446, -1570, -510, -1753, -435, -1497, -182, -713, +236, 451, 800, 1595, 1405, 2349, 1843, 2508, +1838, 2031, 1169, 1053, 33, -190, -1125, -1396, +-2118, -2233, -2819, -2472, -2847, -2096, -2020, -1293, +-627, -330, 925, 620, 2285, 1361, 3108, 1653, +3183, 1551, 2506, 1345, 1220, 1066, -321, 605, +-1686, 127, -2582, -270, -2859, -763, -2485, -1306, +-1657, -1661, -574, -1799, 644, -1662, 1619, -1056, +1987, -74, 1856, 950, 1515, 1849, 1030, 2491, +432, 2584, -126, 1982, -500, 897, -768, -333, +-1079, -1461, -1340, -2291, -1366, -2627, -1170, -2342, +-801, -1503, -222, -360, 472, 725, 1106, 1458, +1590, 1826, 1780, 1872, 1502, 1477, 880, 774, +136, 204, -643, -99, -1260, -377, -1482, -696, +-1361, -926, -985, -1065, -399, -1136, 87, -1094, +315, -898, 477, -479, 528, 131, 294, 715, +95, 1179, 293, 1518, 670, 1629, 906, 1474, +1020, 1079, 980, 429, 522, -381, -433, -1145, +-1551, -1791, -2329, -2279, -2529, -2357, -2170, -1876, +-1244, -990, 197, 168, 1775, 1476, 3012, 2650, +3597, 3336, 3318, 3266, 2143, 2413, 321, 952, +-1672, -832, -3245, -2520, -3949, -3679, -3730, -4022, +-2671, -3422, -921, -1937, 1050, 71, 2621, 2013, +3482, 3447, 3570, 4024, 2850, 3525, 1463, 2215, +-199, 523, -1698, -1254, -2676, -2590, -2922, -3007, +-2467, -2615, -1506, -1766, -372, -637, 604, 459, +1319, 1079, 1696, 1184, 1555, 1007, 1063, 651, +688, 306, 487, 249, 183, 540, -190, 950, +-369, 1094, -479, 814, -849, 217, -1325, -704, +-1444, -1879, -1162, -2829, -748, -2993, -173, -2250, +700, -810, 1611, 1009, 2136, 2730, 2162, 3853, +1722, 4031, 801, 3079, -437, 1235, -1637, -905, +-2456, -2807, -2622, -3994, -2047, -4075, -952, -3038, +314, -1235, 1394, 788, 2020, 2417, 2140, 3179, +1793, 2968, 972, 2023, -98, 709, -991, -577, +-1490, -1496, -1605, -1777, -1257, -1370, -456, -669, +379, -52, 856, 486, 1008, 801, 911, 583, +429, -10, -318, -545, -873, -863, -1026, -898, +-920, -494, -554, 249, 172, 961, 995, 1393, +1525, 1462, 1658, 1139, 1386, 459, 632, -436, +-475, -1164, -1571, -1417, -2286, -1330, -2434, -1052, +-2014, -537, -1042, 64, 409, 482, 1909, 682, +2788, 747, 2853, 685, 2340, 543, 1266, 425, +-319, 346, -1767, 278, -2479, 139, -2531, -106, +-2118, -295, -1178, -424, 103, -668, 1156, -887, +1605, -855, 1547, -652, 1210, -415, 667, -89, +29, 345, -411, 757, -424, 1044, -159, 1201, +46, 1254, 95, 1139, 55, 666, -174, -64, +-649, -720, -1084, -1309, -1177, -1880, -879, -2084, +-293, -1688, 474, -905, 1227, 0, 1673, 933, +1631, 1790, 1157, 2340, 417, 2345, -385, 1734, +-1028, 763, -1369, -246, -1350, -1181, -986, -1837, +-412, -1977, 97, -1683, 345, -1165, 414, -533, +453, 98, 385, 583, 208, 863, 165, 990, +298, 1006, 412, 936, 448, 806, 442, 635, +317, 456, -7, 234, -459, -86, -872, -513, +-1126, -1006, -1166, -1398, -965, -1554, -488, -1509, +197, -1189, 816, -494, 1175, 392, 1353, 1236, +1390, 1955, 1120, 2350, 515, 2192, -210, 1627, +-839, 856, -1297, -178, -1550, -1307, -1462, -2148, +-942, -2608, -211, -2712, 393, -2327, 796, -1417, +1101, -147, 1224, 1260, 949, 2537, 390, 3344, +-76, 3415, -345, 2728, -539, 1440, -558, -204, +-285, -1886, 23, -3166, 97, -3633, 31, -3208, +-91, -2071, -369, -502, -634, 1077, -591, 2264, +-316, 2801, 24, 2580, 467, 1747, 888, 674, +1077, -299, 1029, -989, 732, -1281, 155, -1166, +-490, -824, -907, -451, -1063, -171, -1024, -73, +-749, -127, -277, -231, 180, -269, 475, -103, +576, 247, 471, 611, 253, 904, 93, 1077, +77, 993, 123, 575, 165, -13, 278, -521, +439, -868, 406, -1072, 111, -1071, -277, -766, +-672, -264, -1011, 148, -1127, 389, -958, 515, +-600, 466, -133, 323, 415, 263, 974, 231, +1395, 193, 1566, 286, 1453, 424, 1039, 344, +361, 92, -425, -159, -1146, -463, -1696, -819, +-1994, -1073, -1925, -1098, -1433, -807, -648, -267, +283, 328, 1255, 914, 2068, 1387, 2462, 1490, +2302, 1186, 1655, 684, 694, 97, -452, -523, +-1579, -976, -2320, -1161, -2486, -1127, -2167, -872, +-1445, -506, -391, -221, 732, 16, 1608, 309, +2026, 595, 1914, 748, 1429, 783, 807, 848, +117, 902, -557, 699, -923, 221, -934, -274, +-898, -682, -850, -1099, -580, -1431, -265, -1424, +-188, -1043, -180, -430, 17, 226, 290, 839, +478, 1443, 692, 1819, 993, 1662, 1127, 1101, +888, 399, 409, -420, -154, -1255, -768, -1789, +-1303, -1833, -1539, -1423, -1390, -679, -912, 123, +-167, 793, 670, 1319, 1287, 1512, 1493, 1247, +1324, 771, 865, 259, 185, -282, -580, -702, +-1149, -901, -1250, -966, -940, -880, -467, -569, +110, -180, 752, 146, 1158, 480, 1090, 807, +643, 985, 38, 887, -630, 508, -1216, 49, +-1435, -362, -1143, -776, -496, -1062, 256, -1013, +967, -687, 1512, -220, 1692, 334, 1381, 817, +739, 1065, -35, 1103, -858, 918, -1540, 417, +-1807, -243, -1617, -807, -1124, -1149, -419, -1190, +392, -961, 1056, -548, 1408, 16, 1536, 587, +1466, 966, 1038, 1114, 277, 1058, -453, 760, +-880, 293, -1095, -158, -1214, -557, -1089, -905, +-676, -1066, -291, -972, -88, -671, 167, -256, +550, 146, 803, 529, 836, 866, 806, 994, +779, 873, 659, 628, 396, 325, 25, -4, +-412, -316, -877, -643, -1316, -978, -1560, -1145, +-1380, -1059, -769, -768, 24, -222, 817, 516, +1482, 1205, 1828, 1702, 1723, 1840, 1206, 1408, +420, 487, -492, -610, -1338, -1603, -1812, -2236, +-1715, -2258, -1192, -1611, -466, -456, 381, 885, +1170, 1953, 1500, 2434, 1240, 2272, 703, 1481, +129, 249, -502, -1030, -1014, -2007, -1068, -2414, +-657, -2088, -83, -1154, 416, 68, 779, 1232, +896, 1967, 656, 2000, 186, 1417, -273, 503, +-626, -473, -854, -1180, -885, -1392, -682, -1140, +-276, -542, 221, 189, 647, 697, 893, 784, +942, 539, 779, 128, 469, -348, 138, -708, +-192, -667, -542, -173, -808, 446, -911, 852, +-926, 987, -817, 831, -460, 267, 66, -528, +569, -1135, 965, -1378, 1194, -1205, 1230, -590, +1074, 248, 653, 1008, -6, 1520, -688, 1576, +-1226, 1010, -1574, 62, -1646, -809, -1320, -1387, +-607, -1576, 275, -1249, 1068, -462, 1629, 480, +1878, 1199, 1708, 1491, 1111, 1350, 288, 796, +-572, -44, -1370, -844, -1879, -1325, -1879, -1394, +-1464, -1051, -793, -390, 90, 334, 998, 869, +1609, 1118, 1772, 1034, 1539, 682, 1008, 253, +259, -156, -536, -489, -1111, -673, -1351, -667, +-1300, -454, -961, -175, -389, -49, 158, -48, +495, -3, 685, 43, 744, 24, 586, 139, +318, 447, 156, 682, 116, 734, 106, 649, +73, 353, -19, -142, -192, -674, -438, -1093, +-700, -1277, -805, -1145, -676, -713, -404, -59, +16, 692, 565, 1291, 1003, 1496, 1146, 1283, +1044, 783, 714, 159, 131, -454, -559, -959, +-1078, -1186, -1240, -1029, -1036, -667, -594, -289, +-64, 91, 472, 407, 864, 540, 941, 492, +723, 345, 355, 196, -94, 158, -481, 209, +-642, 199, -547, 154, -243, 148, 141, 22, +404, -279, 475, -554, 423, -695, 228, -742, +-119, -654, -467, -330, -648, 152, -645, 590, +-478, 913, -138, 1067, 324, 913, 736, 491, +914, 38, 814, -352, 500, -716, 72, -896, +-347, -774, -631, -568, -749, -379, -725, -68, +-563, 262, -284, 443, 59, 544, 406, 592, +638, 511, 642, 348, 482, 163, 262, -76, +15, -304, -194, -402, -286, -418, -287, -368, +-246, -203, -168, -25, -43, 84, 92, 126, +136, 83, 27, 15, -138, -11, -192, -39, +-145, -70, -98, 37, -3, 275, 203, 404, +377, 398, 387, 396, 289, 282, 202, -83, +106, -501, -94, -713, -343, -745, -501, -702, +-499, -464, -337, -28, -77, 334, 137, 536, +231, 708, 236, 799, 181, 666, 82, 382, +23, 126, 75, -87, 179, -299, 232, -482, +219, -614, 179, -683, 109, -698, -44, -658, +-295, -460, -548, -91, -700, 333, -701, 750, +-520, 1085, -153, 1208, 332, 1083, 795, 768, +1090, 275, 1120, -340, 880, -891, 388, -1272, +-283, -1471, -890, -1408, -1196, -1068, -1201, -516, +-944, 175, -431, 852, 198, 1392, 724, 1753, +1017, 1829, 1017, 1496, 728, 802, 302, -76, +-132, -982, -557, -1740, -842, -2179, -771, -2175, +-395, -1652, 45, -712, 447, 344, 735, 1306, +752, 2046, 458, 2313, 2, 1958, -472, 1150, +-859, 185, -1014, -730, -855, -1426, -452, -1708, +128, -1496, 791, -959, 1277, -362, 1388, 135, +1153, 444, 631, 512, -164, 419, -955, 314, +-1382, 245, -1420, 308, -1227, 580, -764, 834, +-41, 800, 650, 506, 1024, 20, 1105, -658, +1047, -1330, 806, -1679, 332, -1579, -156, -1065, +-403, -218, -503, 735, -628, 1517, -664, 1889, +-483, 1700, -252, 1052, -135, 193, -43, -657, +125, -1258, 278, -1397, 305, -1086, 306, -514, +393, 89, 422, 519, 244, 655, 28, 510, +-53, 163, -124, -221, -230, -424, -184, -381, +-38, -139, -67, 282, -278, 697, -460, 828, +-504, 640, -425, 263, -232, -215, 73, -695, +475, -1009, 861, -1024, 1064, -713, 987, -194, +670, 314, 207, 706, -356, 934, -908, 855, +-1240, 458, -1206, -29, -885, -412, -440, -605, +43, -569, 493, -318, 798, 41, 925, 368, +880, 544, 644, 498, 292, 259, -24, -96, +-232, -456, -337, -728, -362, -870, -361, -763, +-362, -310, -361, 286, -367, 759, -346, 1079, +-249, 1224, -119, 1072, 25, 617, 257, -11, +525, -662, 697, -1172, 782, -1440, 809, -1453, +661, -1119, 280, -435, -213, 304, -693, 913, +-1084, 1415, -1302, 1624, -1285, 1356, -996, 794, +-421, 193, 333, -421, 1056, -992, 1539, -1316, +1669, -1287, 1416, -968, 826, -509, 37, -63, +-718, 316, -1246, 602, -1459, 735, -1310, 736, +-849, 670, -263, 577, 259, 445, 652, 227, +835, -77, 721, -405, 422, -712, 163, -924, +35, -929, 42, -708, 140, -327, 199, 181, +151, 688, 10, 941, -233, 893, -570, 675, +-850, 281, -886, -231, -631, -577, -183, -625, +338, -473, 815, -200, 1102, 135, 1075, 410, +708, 502, 141, 345, -400, -42, -753, -479, +-871, -770, -719, -828, -333, -577, 78, -21, +327, 621, 446, 1078, 452, 1217, 235, 1022, +-112, 538, -308, -164, -315, -854, -281, -1236, +-153, -1249, 141, -1007, 414, -515, 494, 192, +444, 808, 300, 1065, 30, 1021, -273, 746, +-455, 254, -477, -267, -416, -607, -301, -700, +-133, -569, 51, -274, 190, 76, 274, 336, +319, 416, 319, 337, 291, 162, 259, -83, +195, -333, 45, -432, -156, -337, -316, -204, +-373, -67, -371, 150, -354, 365, -268, 447, +-58, 433, 165, 409, 283, 330, 339, 109, +372, -173, 296, -397, 79, -587, -129, -750, +-231, -763, -230, -545, -144, -199, -5, 225, +131, 725, 217, 1088, 207, 1112, 96, 859, +-67, 443, -243, -103, -397, -663, -486, -1035, +-451, -1087, -259, -867, 70, -479, 434, -20, +718, 422, 850, 710, 781, 737, 480, 551, +31, 250, -398, -82, -724, -286, -927, -262, +-933, -104, -680, 97, -273, 289, 118, 366, +422, 223, 643, -100, 744, -461, 673, -751, +478, -905, 263, -846, 67, -477, -122, 139, +-255, 763, -275, 1207, -233, 1425, -269, 1337, +-433, 880, -614, 158, -672, -632, -556, -1294, +-281, -1683, 132, -1737, 649, -1405, 1131, -665, +1362, 296, 1262, 1149, 906, 1695, 361, 1878, +-333, 1634, -1044, 977, -1584, 73, -1798, -799, +-1592, -1391, -1010, -1632, -226, -1539, 588, -1060, +1328, -281, 1808, 473, 1856, 977, 1484, 1192, +830, 1091, 39, 698, -734, 179, -1314, -297, +-1578, -597, -1488, -617, -1102, -405, -542, -103, +70, 191, 624, 357, 965, 284, 1008, 38, +833, -267, 571, -532, 254, -618, -48, -444, +-179, -93, -117, 310, -56, 681, -116, 892, +-187, 860, -247, 590, -429, 142, -673, -354, +-726, -752, -579, -980, -366, -971, -20, -686, +533, -232, 1096, 211, 1403, 549, 1389, 777, +1065, 856, 457, 714, -318, 373, -1057, 11, +-1581, -265, -1733, -507, -1473, -674, -925, -611, +-206, -381, 594, -158, 1253, 63, 1541, 273, +1467, 374, 1154, 374, 639, 345, -8, 236, +-558, 27, -891, -171, -1066, -250, -1054, -198, +-800, -100, -438, -32, -113, 68, 194, 178, +487, 101, 659, -127, 656, -245, 549, -228, +408, -241, 266, -200, 110, 50, -78, 371, +-240, 550, -300, 566, -324, 463, -394, 218, +-429, -200, -361, -667, -258, -922, -160, -861, +17, -576, 272, -138, 490, 412, 609, 901, +625, 1132, 494, 1043, 240, 656, -46, 55, +-352, -605, -642, -1133, -747, -1352, -590, -1144, +-317, -583, 1, 141, 372, 826, 638, 1300, +587, 1418, 288, 1105, -41, 426, -311, -400, +-478, -1091, -444, -1446, -186, -1369, 180, -872, +499, -83, 659, 746, 625, 1344, 379, 1493, +-71, 1143, -577, 458, -921, -335, -990, -1051, +-801, -1481, -396, -1422, 162, -875, 727, -59, +1082, 744, 1096, 1349, 824, 1586, 405, 1294, +-81, 534, -534, -350, -779, -1056, -766, -1485, +-632, -1517, -447, -1043, -180, -256, 82, 512, +215, 1113, 247, 1427, 313, 1300, 420, 780, +443, 125, 366, -484, 327, -956, 316, -1153, +160, -1008, -159, -618, -479, -127, -704, 332, +-825, 658, -764, 806, -478, 742, -46, 476, +392, 108, 712, -215, 835, -437, 780, -550, +604, -475, 320, -219, -2, 47, -265, 218, +-466, 343, -643, 396, -710, 256, -601, -62, +-402, -361, -203, -510, 36, -507, 337, -341, +609, -2, 769, 428, 784, 758, 618, 861, +286, 733, -93, 386, -442, -163, -733, -736, +-871, -1117, -771, -1223, -491, -1031, -120, -483, +302, 305, 689, 984, 883, 1354, 798, 1429, +477, 1144, 31, 437, -382, -425, -648, -1045, +-718, -1321, -573, -1344, -242, -1032, 150, -350, +467, 403, 657, 905, 666, 1112, 426, 1077, +-7, 753, -419, 217, -687, -294, -801, -622, +-692, -763, -286, -740, 259, -568, 680, -264, +881, 99, 877, 387, 637, 547, 189, 606, +-301, 550, -689, 343, -896, 43, -860, -265, +-583, -536, -171, -707, 251, -671, 571, -421, +721, -64, 683, 305, 460, 641, 111, 859, +-228, 795, -416, 447, -434, 11, -317, -387, +-94, -737, 161, -903, 291, -767, 236, -423, +76, -13, -147, 404, -412, 716, -560, 764, +-412, 563, -57, 265, 295, -10, 584, -244, +823, -386, 855, -349, 559, -199, 50, -140, +-473, -160, -889, -112, -1100, -68, -1000, -110, +-594, -84, -18, 118, 538, 327, 933, 448, +1068, 506, 884, 446, 440, 218, -69, -111, +-468, -451, -704, -685, -771, -698, -632, -518, +-282, -233, 153, 114, 476, 450, 568, 619, +482, 571, 291, 404, 8, 216, -304, -15, +-473, -282, -430, -429, -279, -363, -101, -233, +116, -170, 340, -97, 473, -2, 491, 56, +444, 105, 313, 188, 30, 254, -354, 296, +-679, 308, -813, 213, -747, -14, -525, -289, +-151, -509, 324, -577, 722, -456, 884, -208, +876, 168, 786, 585, 530, 792, 52, 678, +-474, 378, -880, -57, -1115, -579, -1090, -912, +-753, -870, -236, -544, 277, -53, 707, 508, +984, 932, 1002, 1058, 741, 821, 362, 258, +3, -440, -346, -993, -650, -1230, -751, -1088, +-580, -569, -275, 178, 1, 899, 181, 1338, +267, 1359, 263, 969, 162, 277, -19, -553, +-145, -1238, -101, -1545, 29, -1422, 145, -868, +293, 25, 431, 908, 383, 1429, 158, 1552, +-88, 1303, -313, 652, -550, -242, -717, -1008, +-678, -1391, -414, -1367, -28, -1030, 383, -453, +723, 284, 870, 926, 750, 1195, 412, 1071, +1, 700, -349, 164, -537, -391, -524, -746, +-360, -792, -152, -591, 26, -248, 122, 120, +100, 385, -16, 451, -153, 290, -214, 17, +-147, -225, 58, -351, 358, -292, 641, -30, +746, 276, 594, 477, 225, 527, -268, 348, +-731, -59, -985, -471, -949, -686, -663, -700, +-202, -502, 322, -74, 757, 450, 948, 838, +830, 930, 453, 679, 9, 193, -311, -367, +-463, -853, -451, -1081, -281, -921, -53, -431, +86, 183, 94, 734, 21, 1063, -63, 1060, +-132, 736, -171, 230, -150, -327, -11, -806, +231, -1057, 451, -968, 520, -599, 386, -146, +80, 276, -290, 578, -537, 680, -531, 612, +-312, 466, -12, 270, 297, 88, 516, -2, +467, -44, 150, -151, -201, -332, -480, -529, +-728, -697, -749, -744, -328, -624, 324, -322, +859, 176, 1197, 766, 1253, 1222, 829, 1383, +-4, 1198, -829, 691, -1332, -31, -1503, -790, +-1345, -1385, -805, -1649, 45, -1507, 890, -1023, +1420, -266, 1554, 601, 1341, 1278, 768, 1574, +-74, 1509, -842, 1115, -1220, 445, -1190, -314, +-897, -917, -413, -1204, 152, -1191, 553, -950, +638, -523, 536, 24, 356, 501, 77, 748, +-195, 764, -266, 624, -151, 376, -4, 78, +143, -195, 282, -365, 322, -378, 206, -290, +5, -159, -219, 8, -428, 160, -559, 221, +-548, 207, -380, 110, -99, -95, 207, -295, +463, -358, 638, -299, 682, -180, 548, -9, +297, 179, 60, 367, -140, 504, -377, 488, +-607, 341, -671, 175, -551, -37, -357, -303, +-134, -484, 111, -542, 311, -544, 412, -479, +441, -297, 445, -63, 439, 178, 371, 421, +205, 636, -8, 765, -193, 722, -351, 489, +-477, 183, -511, -130, -483, -472, -459, -748, +-385, -851, -160, -804, 184, -664, 532, -392, +785, 6, 898, 414, 842, 723, 595, 927, +206, 1030, -210, 929, -600, 558, -979, 78, +-1224, -337, -1125, -762, -663, -1155, -49, -1274, +539, -1044, 999, -621, 1201, -104, 1056, 464, +660, 969, 205, 1259, -215, 1240, -565, 930, +-774, 437, -768, -120, -570, -619, -265, -901, +37, -948, 249, -842, 339, -581, 319, -208, +197, 110, 39, 303, -36, 422, -22, 466, +21, 433, 105, 355, 257, 281, 367, 244, +311, 214, 86, 110, -230, -45, -539, -215, +-733, -477, -733, -760, -512, -822, -95, -634, +371, -367, 704, -20, 836, 439, 822, 869, +655, 1102, 270, 1089, -246, 822, -655, 355, +-840, -221, -850, -804, -668, -1231, -252, -1348, +255, -1115, 603, -611, 713, 32, 661, 653, +473, 1115, 138, 1302, -223, 1156, -456, 714, +-540, 107, -503, -488, -305, -910, 38, -1083, +346, -987, 471, -601, 426, -77, 279, 332, +64, 553, -156, 655, -300, 594, -329, 370, +-262, 130, -150, -54, -38, -202, 53, -273, +113, -243, 131, -199, 140, -182, 160, -180, +164, -167, 163, -102, 182, 25, 149, 168, +11, 311, -162, 443, -307, 486, -435, 363, +-505, 71, -419, -287, -194, -589, 80, -752, +381, -718, 682, -417, 817, 72, 655, 550, +293, 873, -91, 955, -423, 714, -659, 208, +-695, -348, -513, -772, -236, -952, 16, -842, +188, -484, 272, 18, 301, 506, 263, 789, +137, 786, 41, 543, 116, 141, 260, -279, +292, -532, 240, -541, 143, -356, -113, -36, +-521, 277, -834, 401, -886, 299, -693, 61, +-289, -223, 264, -460, 786, -548, 1102, -390, +1160, -7, 930, 416, 434, 717, -201, 836, +-787, 711, -1166, 288, -1207, -272, -891, -737, +-353, -999, 218, -987, 675, -681, 904, -203, +846, 312, 562, 745, 167, 930, -191, 862, +-384, 653, -402, 314, -330, -141, -168, -499, +61, -646, 189, -683, 120, -636, -12, -444, +-109, -158, -205, 115, -248, 344, -146, 513, +54, 587, 224, 508, 330, 312, 384, 89, +336, -111, 167, -282, -39, -373, -196, -341, +-295, -254, -329, -178, -273, -99, -153, -24, +-45, 11, 16, 17, 47, 41, 82, 137, +128, 247, 174, 301, 203, 341, 199, 355, +156, 214, 99, -67, 51, -310, -27, -481, +-145, -606, -231, -566, -264, -328, -307, -47, +-319, 214, -212, 459, -27, 609, 153, 589, +350, 410, 525, 133, 548, -124, 426, -283, +216, -385, -88, -426, -439, -345, -646, -174, +-610, -53, -406, 3, -134, 73, 150, 158, +386, 200, 505, 202, 455, 237, 243, 259, +-26, 156, -209, -26, -257, -143, -228, -225, +-151, -318, -3, -311, 181, -146, 273, 48, +209, 168, 54, 230, -127, 223, -303, 113, +-426, -67, -396, -215, -159, -262, 201, -199, +483, -55, 564, 157, 485, 367, 294, 472, +-13, 416, -334, 189, -492, -158, -475, -486, +-371, -659, -181, -653, 87, -486, 292, -158, +342, 255, 293, 567, 193, 685, 38, 633, +-91, 452, -102, 169, -40, -139, 18, -343, +41, -410, -2, -389, -127, -324, -252, -241, +-282, -198, -196, -179, -19, -126, 214, -19, +426, 151, 530, 420, 462, 698, 210, 782, +-127, 641, -417, 365, -609, -44, -680, -573, +-540, -1021, -194, -1185, 211, -1031, 555, -621, +797, -23, 837, 613, 573, 1102, 111, 1320, +-326, 1185, -622, 722, -782, 83, -758, -530, +-497, -989, -102, -1185, 225, -1045, 422, -614, +542, -75, 588, 411, 499, 741, 295, 831, +81, 681, -104, 363, -283, -9, -455, -319, +-553, -457, -506, -423, -328, -280, -105, -77, +128, 140, 371, 285, 545, 283, 546, 143, +391, -59, 182, -233, -43, -333, -270, -316, +-416, -156, -391, 88, -234, 290, -54, 398, +104, 415, 203, 305, 174, 50, 31, -248, +-121, -436, -193, -452, -147, -316, -3, -79, +197, 196, 375, 402, 459, 448, 390, 303, +158, 6, -180, -341, -512, -575, -720, -575, +-712, -363, -450, -9, -13, 416, 450, 798, +793, 939, 901, 737, 702, 274, 257, -283, +-253, -812, -656, -1164, -851, -1166, -776, -779, +-431, -160, 44, 471, 449, 957, 665, 1171, +686, 1057, 502, 652, 138, 86, -250, -452, +-464, -778, -467, -835, -356, -656, -176, -312, +48, 57, 201, 283, 207, 313, 148, 202, +78, -7, -16, -190, -59, -198, 40, -21, +183, 231, 212, 484, 129, 653, 21, 605, +-127, 315, -341, -112, -476, -563, -368, -920, +-69, -1029, 189, -850, 305, -449, 351, 60, +332, 546, 178, 866, -41, 958, -174, 826, +-186, 531, -125, 188, 5, -117, 164, -355, +231, -507, 138, -560, -81, -569, -342, -562, +-565, -505, -620, -352, -406, -127, 11, 147, +458, 486, 829, 831, 1039, 1025, 941, 966, +504, 700, -109, 258, -705, -320, -1149, -874, +-1275, -1195, -995, -1225, -434, -984, 195, -514, +728, 59, 1012, 572, 962, 925, 667, 1052, +283, 928, -83, 645, -329, 297, -393, -78, +-344, -408, -263, -606, -173, -686, -137, -670, +-219, -543, -334, -332, -330, -94, -194, 144, +36, 362, 369, 506, 729, 562, 924, 525, +849, 378, 533, 133, 71, -107, -426, -264, +-863, -359, -1138, -410, -1109, -357, -745, -208, +-222, -91, 287, -17, 745, 73, 1065, 135, +1057, 129, 737, 144, 326, 183, -49, 178, +-398, 157, -665, 146, -753, 82, -666, -25, +-462, -108, -200, -199, 82, -279, 342, -269, +511, -192, 505, -111, 357, 7, 193, 132, +62, 198, -84, 219, -222, 214, -251, 170, +-166, 102, -53, 37, 33, -49, 94, -132, +85, -161, -35, -169, -213, -207, -311, -196, +-254, -81, -80, 56, 142, 142, 372, 227, +545, 324, 561, 296, 407, 113, 139, -94, +-215, -260, -594, -410, -817, -459, -748, -318, +-431, -31, 10, 291, 458, 554, 751, 654, +771, 544, 564, 261, 238, -162, -135, -584, +-455, -815, -592, -798, -539, -563, -353, -132, +-77, 374, 232, 749, 447, 877, 458, 764, +274, 427, 20, -40, -164, -434, -231, -647, +-201, -661, -105, -482, 39, -159, 156, 148, +167, 294, 76, 286, -62, 188, -181, 17, +-223, -154, -160, -175, -2, -25, 231, 183, +434, 356, 463, 460, 265, 396, -62, 123, +-383, -256, -578, -593, -570, -769, -356, -725, +-33, -481, 278, -76, 524, 392, 654, 724, +573, 820, 269, 709, -80, 439, -318, 47, +-463, -332, -536, -551, -436, -580, -155, -459, +123, -249, 262, -35, 281, 101, 228, 131, +125, 92, 27, 47, -25, 18, -16, 59, +54, 198, 165, 343, 240, 400, 176, 356, +-56, 198, -366, -86, -603, -411, -678, -652, +-561, -736, -220, -632, 303, -342, 788, 46, +1011, 445, 933, 747, 630, 825, 149, 694, +-422, 441, -899, 85, -1133, -308, -1061, -582, +-681, -691, -97, -671, 475, -526, 861, -261, +992, 38, 863, 312, 510, 509, 69, 574, +-303, 530, -530, 410, -596, 212, -510, -28, +-337, -257, -166, -440, -36, -532, 45, -532, +86, -435, 105, -225, 146, 59, 260, 329, +428, 542, 526, 659, 453, 591, 215, 349, +-132, 31, -495, -307, -768, -574, -868, -659, +-762, -586, -427, -385, 75, -75, 565, 249, +881, 480, 982, 585, 867, 551, 506, 381, +-27, 160, -543, -73, -870, -311, -936, -484, +-754, -525, -420, -459, -34, -291, 328, -67, +563, 155, 589, 364, 449, 510, 280, 523, +140, 408, 6, 216, -101, -39, -153, -283, +-214, -432, -300, -493, -341, -463, -315, -297, +-255, -53, -140, 181, 48, 347, 248, 388, +398, 328, 478, 224, 474, 87, 347, -60, +95, -138, -230, -148, -490, -128, -575, -79, +-496, -46, -309, -86, -50, -128, 212, -126, +375, -127, 425, -90, 386, 24, 242, 178, +19, 316, -175, 388, -288, 347, -324, 205, +-248, -4, -37, -230, 162, -385, 186, -424, +95, -398, 34, -303, 8, -89, -32, 123, +-26, 248, 34, 339, 52, 395, 6, 344, +-35, 213, -62, 68, -96, -72, -100, -203, +-55, -298, 10, -323, 98, -274, 228, -189, +325, -118, 279, -24, 75, 95, -188, 197, +-389, 276, -451, 324, -360, 303, -138, 221, +141, 104, 356, -57, 436, -236, 397, -375, +272, -423, 66, -375, -153, -228, -303, -18, +-348, 205, -291, 370, -122, 419, 118, 373, +285, 256, 284, 42, 152, -190, -27, -290, +-196, -276, -273, -226, -219, -149, -56, -44, +179, 54, 409, 121, 508, 128, 407, 79, +147, 57, -177, 81, -460, 74, -632, 24, +-639, -15, -431, -50, -34, -71, 381, -85, +658, -89, 774, -56, 714, -2, 409, 34, +-51, 67, -450, 101, -682, 77, -739, 16, +-599, 4, -278, 5, 110, -63, 433, -128, +609, -130, 628, -82, 512, -11, 266, 63, +-70, 137, -384, 207, -550, 236, -540, 177, +-399, 45, -160, -116, 150, -263, 421, -357, +525, -354, 450, -264, 288, -86, 65, 163, +-214, 398, -442, 519, -505, 454, -385, 243, +-142, -10, 156, -243, 411, -411, 525, -439, +456, -324, 249, -120, -43, 87, -346, 205, +-552, 201, -585, 140, -450, 73, -186, -27, +193, -89, 590, -32, 818, 89, 771, 194, +484, 264, 14, 219, -508, 51, -871, -163, +-967, -381, -814, -551, -440, -549, 86, -348, +604, -71, 965, 245, 1071, 572, 878, 759, +419, 709, -160, 483, -691, 150, -1010, -226, +-1005, -562, -711, -769, -284, -775, 137, -578, +477, -260, 671, 63, 679, 350, 507, 571, +228, 674, -56, 618, -258, 435, -351, 211, +-317, 7, -164, -216, -2, -446, 23, -593, +-87, -646, -189, -618, -233, -486, -238, -208, +-151, 187, 69, 618, 302, 941, 449, 1031, +514, 858, 486, 464, 318, -89, 13, -664, +-338, -1078, -615, -1210, -733, -1011, -685, -560, +-477, 10, -141, 586, 206, 1020, 444, 1147, +576, 967, 602, 593, 489, 110, 288, -396, +75, -775, -149, -911, -370, -828, -493, -602, +-508, -285, -466, 103, -365, 460, -180, 662, +39, 697, 239, 620, 411, 416, 537, 108, +561, -198, 418, -448, 137, -591, -162, -562, +-397, -401, -574, -220, -644, 3, -507, 256, +-192, 394, 147, 402, 423, 379, 606, 287, +599, 103, 347, -56, -20, -168, -337, -286, +-552, -359, -605, -307, -424, -194, -87, -78, +246, 36, 504, 142, 625, 231, 533, 304, +277, 334, -37, 287, -369, 172, -647, 0, +-721, -216, -564, -453, -274, -607, 76, -579, +434, -343, 681, 17, 736, 397, 612, 711, +360, 865, 24, 764, -348, 388, -644, -130, +-741, -611, -622, -946, -381, -1058, -67, -816, +282, -283, 553, 293, 625, 748, 511, 1022, +321, 996, 93, 624, -171, 100, -372, -372, +-388, -689, -264, -772, -120, -610, 22, -313, +166, 27, 228, 303, 154, 394, 12, 291, +-115, 112, -189, -34, -188, -108, -76, -66, +135, 70, 353, 230, 447, 333, 398, 306, +254, 102, 18, -209, -296, -498, -555, -640, +-620, -587, -484, -354, -226, 23, 88, 433, +412, 713, 656, 758, 716, 581, 559, 232, +262, -190, -101, -527, -449, -663, -637, -606, +-582, -379, -353, -23, -47, 340, 261, 577, +443, 582, 423, 371, 259, 41, 56, -303, +-118, -563, -189, -623, -126, -429, 6, -64, +113, 333, 160, 649, 161, 747, 120, 559, +13, 193, -159, -210, -298, -541, -318, -711, +-230, -656, -78, -417, 153, -97, 424, 197, +578, 402, 502, 489, 261, 469, -18, 371, +-288, 215, -517, 35, -620, -133, -514, -251, +-225, -332, 138, -371, 446, -325, 638, -192, +676, -52, 504, 79, 144, 222, -250, 324, +-539, 325, -686, 214, -646, 42, -391, -141, +-5, -244, 362, -230, 622, -118, 726, 64, +632, 255, 347, 345, -52, 284, -451, 86, +-723, -199, -772, -475, -630, -650, -355, -626, +32, -387, 456, 4, 754, 444, 834, 827, +727, 1032, 462, 952, 39, 585, -435, 26, +-791, -576, -956, -1044, -886, -1265, -571, -1221, +-105, -863, 364, -227, 756, 505, 960, 1104, +869, 1433, 540, 1417, 135, 1033, -268, 363, +-608, -415, -761, -1076, -701, -1423, -521, -1369, +-281, -954, 6, -274, 243, 424, 351, 897, +379, 1059, 389, 924, 349, 527, 248, 25, +138, -325, 33, -415, -92, -320, -246, -152, +-416, -6, -568, -5, -617, -157, -509, -343, +-269, -424, 56, -352, 404, -109, 674, 291, +794, 689, 735, 875, 472, 773, 62, 438, +-351, -61, -674, -581, -900, -929, -950, -991, +-737, -774, -318, -322, 168, 217, 605, 652, +896, 892, 956, 886, 746, 632, 317, 227, +-177, -207, -593, -583, -838, -793, -855, -775, +-626, -561, -237, -217, 148, 202, 406, 550, +516, 701, 483, 666, 308, 478, 80, 169, +-89, -177, -176, -439, -212, -551, -182, -506, +-112, -360, -81, -150, -115, 71, -150, 245, +-142, 312, -85, 287, 40, 258, 200, 231, +323, 163, 347, 40, 233, -72, 29, -164, +-158, -291, -302, -410, -393, -377, -353, -215, +-181, -37, 13, 150, 185, 346, 336, 456, +393, 410, 295, 261, 74, 46, -179, -178, +-360, -330, -382, -389, -264, -351, -59, -183, +189, 48, 385, 210, 428, 264, 310, 245, +104, 158, -143, 4, -374, -129, -508, -182, +-478, -161, -278, -113, 37, -56, 363, 16, +599, 85, 685, 120, 590, 151, 308, 208, +-102, 231, -486, 168, -711, -2, -727, -230, +-534, -460, -175, -599, 199, -559, 436, -299, +526, 123, 535, 567, 482, 867, 364, 903, +209, 657, 40, 216, -165, -268, -438, -695, +-682, -933, -709, -907, -484, -661, -153, -297, +219, 119, 596, 502, 811, 747, 756, 837, +524, 788, 214, 571, -148, 187, -462, -260, +-608, -651, -556, -877, -340, -902, -23, -732, +259, -362, 397, 149, 377, 630, 223, 898, +-2, 878, -191, 616, -245, 217, -135, -220, +91, -551, 316, -661, 436, -526, 395, -267, +198, -12, -96, 188, -375, 274, -521, 240, +-494, 177, -345, 150, -134, 101, 115, -14, +352, -159, 533, -260, 627, -280, 585, -167, +376, 73, 63, 338, -276, 492, -596, 435, +-753, 157, -609, -259, -259, -624, 64, -728, +290, -519, 441, -137, 491, 290, 424, 647, +291, 804, 146, 669, -9, 310, -212, -120, +-412, -503, -455, -737, -309, -759, -97, -548, +103, -165, 279, 270, 340, 604, 236, 741, +71, 635, -45, 332, -118, -55, -158, -381, +-130, -523, -44, -481, 40, -318, 83, -107, +108, 89, 128, 189, 94, 187, -48, 167, +-217, 175, -276, 142, -205, 78, -83, 22, +81, -39, 298, -93, 428, -97, 315, -49, +21, -21, -276, -44, -481, -114, -520, -198, +-332, -233, 15, -150, 346, 59, 524, 331, +485, 523, 254, 512, -33, 307, -271, -27, +-462, -372, -561, -579, -468, -561, -221, -364, +80, -57, 380, 278, 580, 493, 559, 469, +313, 278, -35, 33, -355, -224, -541, -398, +-531, -381, -354, -174, -120, 98, 93, 332, +257, 442, 344, 370, 317, 143, 196, -144, +18, -409, -192, -550, -367, -484, -399, -265, +-249, 0, -17, 261, 193, 501, 325, 606, +314, 514, 143, 293, -96, 18, -309, -280, +-435, -519, -424, -598, -268, -493, -25, -269, +224, -10, 442, 231, 559, 395, 476, 433, +184, 341, -180, 208, -502, 85, -715, -46, +-719, -168, -473, -234, -82, -264, 310, -254, +618, -155, 738, -14, 590, 94, 251, 154, +-106, 172, -391, 102, -568, -6, -594, -54, +-444, -43, -171, 2, 105, 78, 292, 141, +382, 125, 392, 39, 284, -68, 54, -155, +-201, -216, -355, -220, -365, -161, -242, -55, +-18, 73, 236, 190, 404, 275, 394, 284, +197, 203, -101, 74, -378, -74, -563, -233, +-584, -343, -377, -347, 29, -230, 455, -37, +722, 191, 773, 395, 622, 475, 270, 392, +-219, 171, -637, -157, -815, -508, -772, -721, +-582, -675, -243, -379, 211, 89, 631, 623, +855, 998, 840, 1027, 623, 723, 240, 172, +-220, -500, -590, -1075, -732, -1315, -677, -1138, +-496, -610, -192, 107, 185, 785, 482, 1222, +639, 1340, 661, 1077, 493, 469, 124, -242, +-285, -823, -529, -1147, -540, -1136, -345, -786, +-28, -260, 276, 245, 415, 616, 345, 797, +147, 737, -70, 468, -223, 104, -263, -203, +-175, -354, -12, -372, 154, -270, 310, -63, +417, 140, 364, 194, 129, 87, -178, -101, +-404, -277, -486, -370, -441, -294, -245, -64, +135, 207, 540, 428, 702, 549, 592, 541, +357, 359, 51, 42, -306, -289, -567, -550, +-618, -692, -480, -624, -212, -349, 105, 10, +382, 352, 593, 595, 686, 622, 561, 421, +247, 152, -125, -91, -471, -304, -700, -407, +-673, -347, -382, -217, 10, -71, 346, 91, +571, 211, 645, 241, 514, 213, 228, 144, +-82, 3, -334, -119, -512, -151, -556, -162, +-410, -188, -113, -139, 241, -19, 546, 67, +654, 116, 484, 174, 139, 194, -209, 157, +-436, 139, -471, 126, -325, 44, -99, -109, +87, -279, 155, -420, 150, -469, 154, -384, +140, -159, 98, 181, 97, 532, 104, 726, +30, 692, -62, 482, -112, 118, -165, -313, +-223, -635, -240, -775, -215, -743, -103, -491, +108, -45, 277, 398, 325, 678, 314, 751, +223, 580, -5, 224, -233, -129, -321, -397, +-275, -553, -147, -502, 6, -230, 118, 74, +152, 270, 72, 371, -91, 338, -191, 128, +-169, -147, -96, -337, -16, -390, 82, -278, +179, -25, 240, 258, 252, 425, 226, 421, +146, 274, -61, 37, -383, -196, -615, -354, +-615, -421, -445, -367, -138, -178, 263, 76, +547, 297, 579, 403, 447, 375, 234, 205, +-12, -57, -216, -302, -353, -428, -388, -347, +-271, -87, -82, 217, 39, 440, 60, 491, +-21, 317, -176, -11, -285, -361, -254, -597, +-75, -628, 247, -412, 568, -23, 668, 377, +525, 668, 213, 747, -212, 556, -590, 184, +-758, -228, -746, -576, -590, -738, -275, -659, +119, -390, 469, -18, 688, 364, 694, 628, +505, 664, 222, 487, -119, 177, -444, -155, +-594, -397, -514, -519, -295, -508, -23, -321, +215, -46, 312, 202, 227, 415, 19, 538, +-181, 449, -265, 158, -224, -171, -67, -436, +162, -568, 295, -451, 278, -114, 246, 256, +205, 509, 50, 524, -134, 279, -287, -67, +-460, -331, -546, -434, -436, -363, -186, -118, +163, 190, 514, 387, 641, 408, 526, 290, +328, 54, 59, -238, -258, -445, -426, -474, +-382, -365, -252, -164, -103, 141, 34, 436, +130, 557, 163, 513, 61, 377, -108, 116, +-106, -254, 48, -560, 149, -655, 212, -556, +283, -316, 224, 35, 25, 389, -149, 581, +-225, 538, -253, 337, -290, 63, -283, -214, +-106, -365, 190, -321, 397, -187, 463, -40, +417, 137, 207, 290, -93, 310, -307, 170, +-383, -83, -338, -374, -204, -566, -91, -570, +34, -364, 274, 47, 497, 536, 560, 895, +471, 990, 157, 761, -342, 234, -689, -383, +-696, -855, -438, -1081, -11, -1020, 391, -671, +522, -189, 426, 287, 291, 705, 155, 943, +15, 910, -97, 700, -185, 398, -221, -14, +-180, -466, -116, -785, -8, -872, 134, -724, +160, -370, 59, 51, -15, 362, -12, 517, +50, 528, 107, 376, 44, 109, -45, -115, +1, -180, 80, -162, 97, -125, 128, -24, +124, 112, 2, 207, -121, 231, -159, 137, +-175, -82, -185, -328, -175, -512, -139, -591, +-10, -465, 215, -95, 446, 339, 616, 672, +579, 860, 196, 796, -294, 448, -567, -22, +-596, -444, -442, -705, -196, -760, -31, -654, +71, -406, 223, -29, 362, 334, 446, 517, +467, 550, 306, 481, -20, 241, -320, -94, +-504, -344, -493, -429, -248, -283, 20, 74, +146, 423, 225, 559, 272, 413, 202, 10, +105, -517, 9, -923, -174, -990, -330, -649, +-305, 2, -131, 711, 125, 1177, 326, 1236, +326, 862, 242, 199, 163, -472, -21, -954, +-240, -1115, -347, -883, -405, -389, -401, 153, +-221, 590, 73, 780, 358, 672, 531, 366, +443, -17, 137, -375, -112, -571, -191, -538, +-144, -325, -41, 33, -49, 446, -221, 691, +-338, 676, -285, 429, -125, -55, 121, -609, +341, -950, 365, -951, 232, -599, 60, 26, +-80, 653, -92, 998, -63, 987, -155, 619, +-261, -33, -229, -624, -114, -831, 69, -665, +286, -274, 317, 201, 106, 581, -149, 689, +-309, 432, -333, -89, -225, -606, -62, -888, +154, -813, 365, -360, 393, 312, 286, 901, +180, 1185, -38, 1078, -358, 559, -515, -203, +-492, -891, -393, -1271, -158, -1184, 120, -652, +258, 28, 339, 588, 431, 944, 415, 971, +293, 614, 92, 68, -236, -434, -507, -739, +-500, -702, -331, -312, -115, 217, 118, 644, +193, 780, 67, 516, -53, -28, -66, -592, +35, -978, 201, -1014, 267, -605, 214, 79, +142, 731, 48, 1136, -65, 1199, -167, 869, +-304, 218, -423, -535, -400, -1123, -219, -1352, +80, -1101, 388, -409, 491, 436, 331, 1091, +82, 1347, -150, 1068, -291, 294, -189, -584, +46, -1161, 149, -1294, 165, -916, 169, -66, +72, 856, -40, 1417, -137, 1450, -356, 905, +-529, -69, -437, -1062, -200, -1707, 148, -1770, +575, -1103, 783, 49, 675, 1136, 427, 1805, +68, 1888, -322, 1251, -515, 124, -558, -962, +-588, -1653, -455, -1762, -105, -1214, 212, -261, +387, 719, 483, 1420, 444, 1543, 238, 1014, +-30, 148, -215, -673, -199, -1218, -51, -1285, +61, -808, 148, -31, 206, 714, 117, 1184, +-85, 1214, -310, 800, -499, 99, -511, -661, +-303, -1207, 28, -1353, 430, -1040, 725, -322, +684, 543, 425, 1207, 152, 1434, -144, 1147, +-367, 435, -373, -397, -314, -990, -297, -1184, +-188, -969, -25, -411, 63, 238, 141, 714, +188, 898, 99, 707, 6, 229, 29, -282, +122, -648, 277, -766, 378, -547, 271, -64, +73, 454, -102, 789, -329, 806, -516, 483, +-510, -12, -376, -457, -154, -755, 139, -801, +362, -547, 470, -120, 504, 330, 378, 640, +111, 630, -111, 358, -241, 37, -298, -227, +-221, -390, -56, -327, 71, -22, 146, 302, +147, 478, 21, 454, -184, 180, -344, -254, +-363, -654, -218, -910, 37, -933, 322, -630, +531, -15, 557, 734, 434, 1367, 292, 1653, +101, 1390, -212, 604, -495, -413, -642, -1342, +-712, -1914, -621, -1906, -273, -1295, 181, -308, +560, 754, 732, 1602, 614, 1959, 390, 1692, +225, 955, 23, -28, -179, -1003, -252, -1624, +-304, -1652, -403, -1120, -396, -267, -250, 557, +-98, 1076, 18, 1182, 125, 875, 186, 278, +217, -337, 269, -716, 278, -807, 188, -602, +70, -119, -41, 398, -122, 680, -133, 685, +-114, 435, -127, -40, -197, -554, -279, -837, +-245, -732, -88, -300, 94, 248, 272, 681, +343, 864, 231, 728, 98, 288, 39, -300, +-35, -807, -114, -1045, -150, -884, -166, -332, +-137, 399, -12, 1042, 171, 1334, 273, 1123, +178, 484, -117, -364, -441, -1186, -558, -1660, +-413, -1483, -105, -723, 312, 270, 656, 1164, +660, 1673, 408, 1590, 153, 964, -77, 33, +-267, -900, -357, -1484, -404, -1461, -431, -901, +-377, -115, -239, 601, -60, 1018, 136, 1006, +335, 618, 453, 54, 440, -458, 378, -723, +291, -640, 84, -239, -186, 267, -367, 631, +-434, 700, -409, 460, -314, 19, -201, -492, +-102, -901, 3, -1008, 144, -691, 315, -61, +480, 598, 539, 1056, 368, 1237, 37, 1043, +-227, 445, -361, -355, -420, -1057, -374, -1413, +-208, -1302, -21, -753, 89, 42, 126, 820, +168, 1331, 213, 1357, 150, 874, -32, 154, +-167, -562, -153, -1097, -12, -1187, 179, -762, +306, -99, 276, 463, 87, 798, -173, 829, +-389, 485, -444, -59, -322, -498, -126, -668, +69, -495, 238, -107, 329, 238, 315, 453, +256, 535, 210, 418, 131, 111, -67, -209, +-329, -465, -487, -678, -453, -690, -268, -386, +21, 36, 359, 479, 581, 943, 519, 1165, +216, 907, -161, 276, -469, -466, -571, -1132, +-410, -1471, -89, -1300, 218, -717, 380, 110, +407, 1007, 387, 1579, 288, 1558, 70, 1046, +-166, 242, -326, -626, -417, -1254, -441, -1416, +-362, -1130, -148, -512, 143, 235, 364, 786, +415, 954, 333, 815, 244, 432, 198, -74, +127, -421, 17, -465, -118, -279, -312, -14, +-484, 261, -511, 428, -410, 305, -194, -102, +151, -534, 482, -747, 608, -673, 502, -357, +301, 131, 116, 633, -69, 960, -240, 1023, +-341, 755, -350, 207, -269, -413, -141, -938, +-6, -1216, 131, -1069, 177, -553, 76, 87, +-18, 689, 2, 1089, 83, 1063, 184, 616, +286, 35, 334, -458, 226, -702, -68, -626, +-408, -383, -603, -128, -575, 118, -348, 276, +-4, 295, 358, 243, 631, 151, 684, 47, +471, -5, 88, -63, -294, -189, -549, -233, +-650, -166, -536, -111, -170, -32, 257, 100, +546, 182, 704, 268, 635, 390, 202, 332, +-373, 74, -734, -205, -782, -477, -561, -667, +-92, -561, 470, -243, 820, 127, 773, 570, +388, 881, -133, 766, -547, 310, -709, -231, +-610, -696, -258, -886, 247, -719, 642, -257, +770, 394, 651, 988, 271, 1138, -342, 747, +-926, -20, -1160, -941, -954, -1573, -374, -1545, +452, -913, 1204, 161, 1528, 1421, 1316, 2274, +622, 2273, -373, 1453, -1256, 52, -1639, -1570, +-1467, -2783, -866, -3036, 7, -2226, 888, -586, +1439, 1345, 1460, 2847, 976, 3370, 229, 2713, +-456, 1114, -934, -779, -1180, -2333, -1022, -3037, +-415, -2653, 283, -1433, 750, 123, 933, 1533, +786, 2328, 303, 2248, -318, 1465, -804, 284, +-937, -991, -598, -1859, 40, -1892, 588, -1190, +842, -90, 814, 1000, 451, 1607, -138, 1548, +-530, 849, -585, -257, -557, -1191, -486, -1533, +-247, -1328, 13, -606, 149, 474, 324, 1288, +594, 1391, 684, 1031, 490, 406, 202, -458, +-118, -1098, -444, -1135, -594, -696, -545, 13, +-456, 668, -350, 874, -172, 626, 89, 106, +434, -527, 727, -993, 779, -998, 623, -495, +351, 382, -89, 1343, -599, 1821, -879, 1507, +-889, 560, -770, -751, -409, -2015, 213, -2633, +768, -2272, 1073, -932, 1141, 938, 825, 2480, +103, 3086, -679, 2629, -1196, 1259, -1312, -598, +-980, -2233, -314, -3072, 449, -2852, 1111, -1620, +1438, 149, 1188, 1791, 493, 2835, -277, 2838, +-956, 1678, -1411, -7, -1361, -1538, -773, -2511, +81, -2501, 903, -1400, 1390, 248, 1315, 1729, +751, 2418, -30, 1983, -749, 737, -1124, -695, +-1012, -1953, -580, -2558, -40, -1949, 519, -412, +884, 1248, 828, 2484, 447, 2881, -48, 2154, +-546, 556, -861, -1330, -779, -2845, -322, -3369, +280, -2673, 791, -1037, 1028, 1011, 825, 2796, +200, 3613, -517, 3172, -1016, 1624, -1190, -508, +-935, -2397, -257, -3344, 557, -3130, 1164, -1852, +1370, 58, 1062, 1810, 288, 2716, -602, 2559, +-1225, 1546, -1413, 96, -1073, -1265, -289, -2021, +538, -1874, 1127, -1043, 1378, 27, 1077, 1094, +334, 1793, -379, 1630, -938, 701, -1342, -413, +-1223, -1370, -484, -1901, 366, -1684, 939, -783, +1228, 393, 1117, 1523, 479, 2202, -369, 2041, +-939, 1130, -1046, -117, -733, -1293, -176, -2046, +376, -2153, 754, -1544, 797, -374, 440, 856, +-71, 1680, -472, 1871, -704, 1370, -739, 392, +-486, -556, 89, -1111, 762, -1191, 1115, -753, +972, -18, 466, 571, -226, 830, -899, 702, +-1282, 104, -1165, -574, -559, -881, 217, -843, +826, -510, 1152, 109, 1106, 730, 648, 1071, +3, 1069, -551, 655, -934, -36, -1032, -637, +-665, -1017, -9, -1120, 511, -676, 789, 62, +836, 561, 473, 854, -153, 937, -598, 510, +-774, -228, -759, -765, -422, -981, 204, -887, +786, -402, 1042, 344, 905, 1017, 471, 1434, +-128, 1387, -784, 755, -1275, -212, -1305, -1187, +-801, -1865, 2, -1952, 772, -1347, 1258, -198, +1367, 1046, 1075, 1867, 404, 2096, -429, 1646, +-1075, 570, -1386, -616, -1320, -1403, -752, -1722, +138, -1555, 873, -766, 1254, 283, 1284, 1044, +877, 1399, 133, 1246, -600, 516, -1061, -310, +-1091, -896, -713, -1197, -225, -997, 203, -369, +607, 259, 801, 782, 644, 1167, 350, 1015, +26, 385, -329, -123, -483, -437, -367, -768, +-217, -817, -83, -493, 83, -149, 188, 85, +169, 176, 16, 76, -218, -56, -290, -27, +-79, 168, 193, 476, 377, 795, 559, 891, +622, 631, 329, 164, -187, -405, -662, -1052, +-1001, -1548, -1049, -1559, -648, -993, 31, -161, +638, 670, 1006, 1436, 1158, 1850, 1006, 1603, +404, 918, -396, 74, -927, -810, -1070, -1386, +-854, -1394, -336, -1040, 184, -535, 488, 114, +599, 632, 444, 762, 60, 645, -250, 350, +-316, -138, -175, -482, 131, -415, 433, -34, +503, 472, 350, 828, 88, 818, -339, 504, +-801, -31, -903, -782, -608, -1381, -161, -1434, +390, -1057, 893, -465, 1021, 358, 708, 1150, +161, 1509, -366, 1443, -718, 1093, -832, 454, +-578, -308, -26, -841, 458, -1036, 670, -979, +628, -752, 341, -468, -131, -290, -684, -203, +-1074, -22, -923, 268, -256, 562, 468, 926, +1059, 1322, 1497, 1388, 1421, 990, 620, 305, +-458, -605, -1325, -1667, -1846, -2357, -1798, -2235, +-1073, -1477, -35, -332, 995, 1054, 1804, 2217, +2043, 2667, 1638, 2335, 747, 1354, -494, -28, +-1566, -1369, -1940, -2185, -1769, -2308, -1207, -1801, +-109, -799, 1122, 379, 1752, 1330, 1657, 1743, +1131, 1511, 320, 845, -588, 93, -1233, -557, +-1376, -939, -1024, -914, -364, -521, 310, -40, +794, 273, 999, 401, 868, 325, 461, 61, +-30, -206, -441, -299, -716, -155, -833, 162, +-658, 408, -162, 419, 258, 211, 350, -118, +457, -525, 663, -836, 549, -673, 195, -74, +29, 507, -74, 908, -343, 1159, -568, 1044, +-638, 406, -645, -529, -532, -1322, -219, -1739, +262, -1649, 796, -962, 1125, 162, 1109, 1374, +827, 2189, 269, 2240, -534, 1580, -1215, 454, +-1439, -892, -1213, -2000, -685, -2413, -14, -2033, +648, -1124, 1162, 35, 1344, 1211, 1124, 2017, +653, 2173, 28, 1686, -735, 721, -1322, -414, +-1390, -1343, -1040, -1777, -408, -1610, 459, -1041, +1151, -254, 1288, 589, 994, 1140, 484, 1183, +-159, 856, -750, 412, -1058, -62, -967, -478, +-598, -608, -142, -448, 405, -256, 913, -98, +1005, 72, 679, 195, 280, 157, -121, 7, +-571, -28, -850, 36, -806, 9, -608, -65, +-330, -56, 160, -7, 717, 44, 1000, 130, +926, 231, 602, 236, 133, 179, -415, 114, +-913, -89, -1072, -411, -854, -655, -538, -692, +-107, -504, 539, -120, 1113, 398, 1353, 933, +1168, 1231, 504, 1117, -362, 618, -1053, -136, +-1477, -946, -1480, -1526, -897, -1621, -54, -1222, +609, -452, 1084, 549, 1393, 1483, 1303, 1969, +828, 1852, 221, 1171, -475, 93, -1120, -1101, +-1391, -2030, -1284, -2313, -929, -1861, -317, -845, +363, 483, 866, 1740, 1180, 2419, 1270, 2329, +1075, 1570, 648, 275, 68, -1163, -572, -2071, +-1137, -2211, -1423, -1836, -1294, -1003, -883, 190, +-349, 1186, 343, 1588, 1051, 1548, 1457, 1202, +1497, 610, 1267, 4, 684, -429, -251, -694, +-1142, -801, -1637, -763, -1732, -689, -1391, -642, +-585, -562, 343, -371, 1079, -31, 1595, 491, +1769, 1104, 1428, 1602, 661, 1721, -277, 1333, +-1108, 518, -1581, -565, -1582, -1657, -1178, -2393, +-544, -2499, 130, -1881, 656, -657, 944, 734, +1082, 1883, 1134, 2588, 991, 2679, 638, 2005, +172, 746, -404, -609, -1007, -1701, -1363, -2322, +-1403, -2330, -1287, -1767, -963, -809, -258, 287, +707, 1128, 1625, 1565, 2225, 1621, 2249, 1283, +1601, 719, 455, 221, -920, -156, -2142, -515, +-2718, -762, -2449, -792, -1532, -790, -234, -842, +1132, -718, 2177, -372, 2642, 77, 2359, 554, +1248, 958, -296, 1176, -1585, 1118, -2276, 770, +-2242, 170, -1396, -531, -104, -1016, 1007, -1102, +1679, -908, 1838, -493, 1314, 54, 255, 519, +-743, 731, -1310, 631, -1525, 305, -1349, -65, +-624, -320, 392, -468, 1201, -506, 1553, -232, +1425, 264, 884, 574, 132, 717, -599, 799, +-1152, 572, -1379, -25, -1161, -674, -652, -1115, +-137, -1294, 353, -1139, 749, -636, 816, 70, +705, 838, 694, 1457, 605, 1617, 316, 1321, +27, 734, -288, -34, -744, -797, -1110, -1372, +-1134, -1593, -822, -1359, -247, -761, 446, 16, +953, 758, 1122, 1244, 1030, 1352, 638, 1025, +-40, 375, -643, -338, -926, -881, -938, -1093, +-629, -882, 5, -248, 699, 501, 1120, 958, +1046, 1090, 496, 889, -302, 201, -1095, -674, +-1610, -1342, -1571, -1675, -891, -1488, 205, -679, +1290, 436, 2049, 1428, 2274, 2075, 1719, 2134, +478, 1522, -893, 532, -1953, -603, -2512, -1710, +-2352, -2283, -1406, -2158, -17, -1611, 1297, -651, +2162, 604, 2361, 1596, 1821, 2044, 718, 2055, +-581, 1526, -1600, 457, -1927, -618, -1575, -1234, +-803, -1481, 257, -1426, 1224, -966, 1539, -254, +1249, 353, 669, 688, -228, 870, -1210, 865, +-1666, 507, -1460, -18, -874, -346, 32, -497, +1151, -556, 1964, -402, 2088, 11, 1611, 468, +670, 705, -633, 643, -1892, 366, -2556, -39, +-2385, -564, -1538, -1016, -295, -1095, 1096, -803, +2237, -285, 2665, 469, 2257, 1172, 1206, 1404, +-188, 1221, -1512, 746, -2357, -72, -2463, -954, +-1728, -1454, -406, -1489, 991, -1050, 2054, -153, +2455, 838, 1902, 1472, 537, 1611, -1007, 1156, +-2141, 109, -2572, -1063, -2114, -1847, -776, -1989, +1022, -1337, 2519, -28, 3060, 1387, 2523, 2370, +1186, 2615, -603, 2038, -2285, 675, -3170, -1140, +-3011, -2667, -1985, -3328, -321, -3051, 1481, -1908, +2691, -43, 2982, 1972, 2440, 3420, 1175, 3918, +-467, 3336, -1803, 1698, -2369, -470, -2117, -2440, +-1172, -3770, 61, -4062, 961, -3132, 1257, -1344, +1092, 758, 596, 2628, -101, 3644, -643, 3561, +-689, 2554, -316, 928, 189, -882, 664, -2275, +935, -2924, 774, -2840, 201, -2013, -566, -631, +-1263, 754, -1546, 1759, -1217, 2270, -422, 2165, +556, 1480, 1394, 455, 1747, -573, 1517, -1375, +872, -1791, -38, -1664, -998, -1082, -1593, -310, +-1587, 493, -1155, 1187, -479, 1534, 356, 1405, +1086, 880, 1381, 103, 1171, -740, 688, -1275, +232, -1379, -164, -1186, -571, -592, -809, 276, +-761, 945, -645, 1287, -599, 1327, -476, 886, +-166, 114, 269, -547, 724, -959, 1124, -1183, +1348, -1009, 1263, -431, 839, 142, 75, 568, +-933, 811, -1842, 724, -2271, 472, -2078, 222, +-1253, -71, 122, -273, 1601, -274, 2546, -216, +2728, -252, 2223, -308, 1014, -304, -602, -296, +-1915, -204, -2578, 59, -2620, 366, -1939, 643, +-601, 835, 926, 740, 2102, 328, 2523, -194, +2085, -639, 1055, -1027, -214, -1203, -1370, -851, +-1978, -216, -1805, 302, -1059, 854, -78, 1399, +914, 1392, 1579, 817, 1585, 175, 1001, -448, +143, -1155, -792, -1553, -1569, -1385, -1781, -865, +-1187, -122, -109, 667, 891, 1227, 1584, 1499, +1851, 1417, 1445, 883, 498, 129, -536, -567, +-1405, -1151, -1868, -1526, -1655, -1471, -949, -1017, +-110, -340, 752, 464, 1463, 1133, 1687, 1464, +1369, 1524, 757, 1215, 34, 449, -743, -372, +-1370, -905, -1524, -1252, -1153, -1466, -585, -1277, +-47, -663, 563, -56, 1124, 397, 1261, 918, +1003, 1395, 671, 1475, 252, 1160, -352, 679, +-947, 86, -1257, -639, -1166, -1337, -782, -1775, +-280, -1730, 331, -1162, 948, -385, 1225, 393, +1089, 1262, 783, 1953, 344, 1966, -319, 1421, +-1003, 696, -1332, -168, -1159, -1079, -678, -1723, +-113, -1899, 547, -1603, 1177, -938, 1318, -126, +865, 663, 263, 1358, -279, 1765, -823, 1632, +-1127, 1072, -977, 356, -530, -375, 87, -1000, +734, -1357, 1045, -1314, 897, -900, 507, -388, +-19, 9, -585, 342, -884, 623, -798, 755, +-495, 699, -105, 613, 337, 598, 688, 466, +741, 43, 509, -472, 222, -795, -83, -961, +-493, -1043, -746, -841, -594, -311, -283, 300, +-11, 854, 328, 1163, 601, 1104, 574, 908, +367, 614, 155, -56, -95, -880, -370, -1257, +-552, -1194, -573, -1044, -430, -650, -204, 124, +23, 838, 304, 1172, 677, 1140, 927, 877, +849, 545, 483, 122, -68, -378, -699, -745, +-1228, -891, -1416, -946, -1114, -989, -433, -839, +362, -327, 1117, 361, 1619, 1036, 1621, 1588, +1175, 1831, 414, 1600, -577, 823, -1461, -296, +-1903, -1448, -1841, -2373, -1208, -2663, -62, -2128, +1114, -1017, 1847, 445, 1978, 1905, 1486, 2866, +545, 3050, -456, 2419, -1258, 1101, -1709, -585, +-1581, -2121, -904, -3050, -62, -3141, 742, -2335, +1383, -929, 1523, 635, 1079, 2072, 324, 2833, +-529, 2552, -1208, 1675, -1348, 641, -894, -530, +-154, -1488, 493, -1709, 847, -1392, 916, -1041, +694, -594, 195, 6, -350, 352, -701, 363, +-762, 374, -521, 551, -87, 757, 390, 823, +765, 805, 801, 721, 375, 383, -232, -268, +-692, -1034, -927, -1602, -821, -1717, -246, -1343, +506, -592, 1015, 324, 1179, 1218, 964, 1863, +334, 1901, -474, 1307, -1222, 446, -1682, -349, +-1424, -940, -499, -1304, 506, -1329, 1357, -938, +1970, -445, 1850, -102, 883, 188, -306, 422, +-1280, 492, -1993, 531, -2159, 663, -1496, 731, +-334, 698, 836, 673, 1862, 434, 2492, -213, +2241, -901, 1143, -1396, -210, -1769, -1433, -1759, +-2361, -1085, -2598, 42, -1936, 1224, -771, 2149, +470, 2532, 1627, 2257, 2412, 1351, 2470, -10, +1803, -1385, 685, -2296, -529, -2632, -1529, -2409, +-2190, -1512, -2334, -126, -1729, 1174, -642, 2045, +385, 2438, 1246, 2242, 1914, 1454, 2042, 320, +1532, -774, 678, -1515, -254, -1821, -1045, -1732, +-1509, -1273, -1578, -541, -1198, 210, -473, 723, +240, 998, 724, 1173, 1035, 1146, 1054, 771, +621, 252, 29, -102, -334, -334, -506, -599, +-563, -735, -335, -634, 132, -475, 473, -337, +484, -211, 267, -145, -59, -23, -454, 271, +-793, 581, -835, 718, -520, 784, 7, 822, +599, 621, 1058, 175, 1177, -349, 916, -887, +360, -1283, -323, -1368, -882, -1116, -1182, -579, +-1177, 121, -834, 880, -262, 1485, 317, 1662, +771, 1369, 1009, 731, 977, -13, 751, -669, +437, -1195, 77, -1440, -309, -1262, -638, -769, +-871, -187, -1049, 267, -1125, 589, -949, 811, +-400, 821, 485, 658, 1417, 470, 2030, 323, +2138, 203, 1664, -31, 589, -348, -854, -556, +-2201, -714, -2985, -843, -2926, -760, -2054, -406, +-568, 13, 1237, 327, 2862, 591, 3727, 754, +3477, 727, 2157, 618, 219, 445, -1771, 219, +-3317, 64, -3892, -116, -3191, -428, -1556, -729, +316, -901, 1908, -1001, 2910, -1015, 3044, -742, +2233, -123, 824, 644, -578, 1322, -1528, 1763, +-1887, 1908, -1672, 1621, -951, 757, -30, -393, +599, -1449, 731, -2247, 522, -2549, 132, -2175, +-257, -1258, -396, -62, -278, 1184, -42, 2157, +312, 2514, 733, 2254, 983, 1626, 927, 739, +595, -292, 23, -1252, -685, -1890, -1263, -2067, +-1510, -1966, -1471, -1686, -1140, -1064, -424, -186, +477, 743, 1186, 1707, 1697, 2498, 2094, 2752, +2064, 2411, 1368, 1609, 293, 318, -858, -1293, +-2042, -2658, -2970, -3394, -3102, -3405, -2303, -2596, +-928, -1146, 717, 518, 2409, 2122, 3673, 3373, +3908, 3871, 2956, 3403, 1214, 2078, -836, 289, +-2801, -1499, -4079, -2960, -4119, -3774, -2973, -3616, +-1079, -2517, 1099, -880, 2966, 820, 3915, 2218, +3719, 3003, 2545, 3009, 745, 2345, -1184, 1276, +-2680, 63, -3325, -1058, -3036, -1870, -1991, -2181, +-478, -1968, 1086, -1453, 2182, -766, 2530, 20, +2218, 764, 1450, 1357, 377, 1669, -719, 1565, +-1436, 1117, -1613, 496, -1426, -226, -1088, -945, +-613, -1448, -11, -1570, 513, -1238, 784, -468, +988, 436, 1270, 1153, 1307, 1603, 873, 1607, +253, 979, -355, -52, -1058, -1067, -1736, -1837, +-1998, -2191, -1643, -1868, -832, -806, 208, 639, +1335, 2008, 2329, 2932, 2779, 3142, 2381, 2449, +1239, 823, -258, -1235, -1786, -2963, -3035, -3937, +-3508, -3938, -2874, -2857, -1413, -936, 329, 1274, +2034, 3103, 3421, 4168, 3982, 4284, 3353, 3294, +1775, 1467, -155, -573, -2028, -2359, -3538, -3642, +-4210, -4118, -3713, -3531, -2262, -2169, -383, -589, +1545, 1013, 3229, 2362, 4182, 3104, 4030, 3266, +2938, 2906, 1279, 2002, -709, 774, -2635, -484, +-3870, -1674, -4120, -2737, -3543, -3378, -2275, -3326, +-372, -2629, 1705, -1386, 3234, 281, 3936, 2085, +3937, 3591, 3143, 4295, 1448, 3949, -643, 2656, +-2376, 669, -3471, -1592, -3933, -3533, -3573, -4567, +-2282, -4359, -435, -3038, 1358, -1016, 2718, 1230, +3480, 3169, 3505, 4244, 2701, 4075, 1257, 2799, +-350, 894, -1670, -1135, -2536, -2787, -2933, -3638, +-2759, -3462, -1966, -2311, -806, -559, 365, 1278, +1431, 2662, 2313, 3222, 2734, 2932, 2537, 1847, +1869, 150, 834, -1569, -493, -2667, -1762, -2961, +-2653, -2565, -3067, -1521, -2815, -13, -1759, 1400, +-230, 2336, 1324, 2740, 2674, 2523, 3509, 1699, +3439, 540, 2419, -650, 780, -1659, -1070, -2362, +-2727, -2619, -3761, -2295, -3793, -1521, -2754, -522, +-1037, 618, 796, 1724, 2423, 2466, 3557, 2688, +3744, 2438, 2895, 1744, 1450, 672, -209, -531, +-1895, -1626, -3132, -2470, -3423, -2852, -2795, -2680, +-1660, -2041, -299, -1024, 1073, 168, 2092, 1348, +2476, 2434, 2288, 3112, 1766, 3079, 1060, 2507, +225, 1587, -663, 270, -1365, -1267, -1697, -2570, +-1796, -3369, -1781, -3575, -1426, -3046, -680, -1859, +129, -337, 914, 1271, 1765, 2698, 2347, 3613, +2267, 3815, 1684, 3193, 807, 1883, -365, 260, +-1562, -1373, -2338, -2788, -2552, -3643, -2192, -3667, +-1274, -2916, -37, -1643, 1209, -102, 2148, 1430, +2405, 2679, 1951, 3391, 1149, 3301, 164, 2460, +-895, 1180, -1576, -268, -1616, -1634, -1294, -2622, +-833, -2942, -195, -2504, 436, -1533, 763, -330, +804, 880, 707, 1871, 486, 2331, 233, 2018, +137, 1178, 152, 206, 38, -764, -252, -1534, +-595, -1769, -923, -1335, -1114, -494, -931, 328, +-328, 1034, 463, 1590, 1240, 1657, 1823, 1096, +1956, 152, 1460, -832, 401, -1607, -935, -2009, +-2107, -1846, -2736, -1156, -2674, -182, -1830, 897, +-289, 1775, 1422, 2098, 2682, 1875, 3195, 1333, +2875, 637, 1833, -185, 374, -944, -1162, -1330, +-2360, -1424, -2803, -1471, -2540, -1418, -1920, -1151, +-1007, -744, 156, -265, 1157, 374, 1702, 1219, +1936, 2070, 1958, 2674, 1720, 2805, 1291, 2280, +725, 1109, -28, -505, -906, -2245, -1781, -3700, +-2529, -4425, -2891, -4107, -2636, -2746, -1731, -622, +-275, 1801, 1479, 3893, 3071, 5121, 4038, 5198, +4086, 4011, 3089, 1740, 1172, -968, -1148, -3305, +-3114, -4779, -4261, -5142, -4486, -4216, -3641, -2265, +-1711, 5, 689, 2000, 2675, 3337, 3764, 3773, +3881, 3330, 3071, 2291, 1519, 1004, -282, -270, +-1709, -1310, -2373, -1915, -2310, -2053, -1770, -1863, +-985, -1491, -186, -1006, 335, -446, 501, 50, +495, 419, 444, 839, 393, 1352, 481, 1722, +800, 1787, 1210, 1548, 1351, 1036, 942, 245, +149, -801, -763, -1816, -1780, -2402, -2656, -2417, +-2771, -1982, -1926, -1198, -530, -70, 1059, 1193, +2605, 2135, 3619, 2579, 3547, 2614, 2360, 2160, +529, 1167, -1421, -166, -3036, -1516, -3802, -2570, +-3418, -3085, -2121, -2880, -407, -1963, 1351, -554, +2721, 1014, 3189, 2288, 2709, 2945, 1683, 2918, +383, 2160, -960, 886, -1848, -434, -1955, -1509, +-1488, -2194, -877, -2284, -364, -1763, 35, -980, +261, -233, 217, 435, 99, 863, 237, 933, +609, 910, 1003, 948, 1306, 942, 1400, 884, +1114, 811, 409, 571, -599, 20, -1664, -725, +-2461, -1447, -2701, -1988, -2210, -2142, -1021, -1796, +516, -1017, 1901, 116, 2818, 1397, 3092, 2468, +2596, 2946, 1431, 2694, -29, 1872, -1367, 588, +-2246, -943, -2525, -2196, -2319, -2822, -1714, -2833, +-749, -2292, 305, -1224, 1105, 125, 1540, 1213, +1628, 1806, 1469, 2039, 1162, 1946, 725, 1556, +222, 970, -228, 325, -609, -195, -924, -614, +-1116, -1078, -1211, -1538, -1163, -1837, -845, -1847, +-339, -1562, 148, -949, 614, 51, 1069, 1230, +1296, 2229, 1175, 2759, 852, 2653, 464, 1942, +45, 734, -286, -706, -440, -1878, -486, -2500, +-553, -2570, -677, -2085, -826, -1128, -965, -52, +-1026, 796, -836, 1344, -321, 1542, 397, 1309, +1248, 881, 2068, 598, 2512, 477, 2408, 413, +1746, 371, 444, 220, -1261, -233, -2779, -948, +-3724, -1697, -3875, -2233, -3002, -2288, -1216, -1689, +936, -539, 2911, 901, 4235, 2341, 4490, 3391, +3590, 3608, 1815, 2812, -423, 1240, -2539, -678, +-3895, -2457, -4174, -3610, -3408, -3861, -1825, -3120, +102, -1486, 1792, 476, 2799, 2011, 2898, 2835, +2249, 3008, 1265, 2442, 243, 1200, -654, -153, +-1188, -1119, -1223, -1626, -900, -1616, -529, -1080, +-361, -357, -370, 178, -413, 372, -421, 166, +-356, -269, -99, -611, 403, -707, 1004, -462, +1436, 256, 1517, 1274, 1230, 2052, 619, 2179, +-245, 1648, -1152, 568, -1798, -872, -2010, -2216, +-1733, -3004, -995, -2978, 3, -2063, 931, -559, +1605, 1047, 1925, 2358, 1758, 3056, 1187, 2930, +459, 2001, -341, 604, -1150, -829, -1698, -1982, +-1781, -2491, -1410, -2222, -691, -1454, 190, -478, +980, 495, 1445, 1200, 1466, 1449, 1099, 1232, +488, 725, -230, 157, -880, -290, -1256, -469, +-1185, -367, -674, -70, 62, 203, 770, 241, +1277, 84, 1345, -199, 821, -558, -76, -766, +-960, -675, -1623, -388, -1883, 2, -1461, 451, +-416, 790, 791, 856, 1772, 765, 2349, 594, +2335, 222, 1614, -269, 317, -646, -1147, -799, +-2234, -732, -2652, -498, -2452, -143, -1665, 207, +-371, 386, 960, 393, 1850, 269, 2245, 77, +2209, -102, 1671, -223, 713, -208, -294, -60, +-1021, 150, -1409, 368, -1522, 510, -1375, 566, +-1019, 492, -551, 158, -68, -320, 354, -760, +684, -1114, 972, -1258, 1177, -1043, 1118, -471, +750, 241, 262, 878, -180, 1411, -534, 1714, +-732, 1542, -726, 929, -568, 158, -340, -523, +-141, -1094, -74, -1536, -118, -1645, -219, -1363, +-310, -852, -192, -248, 191, 346, 619, 823, +983, 1134, 1310, 1305, 1356, 1338, 877, 1146, +44, 753, -779, 321, -1423, -149, -1861, -787, +-1966, -1415, -1535, -1673, -590, -1560, 484, -1277, +1298, -792, 1790, -82, 1983, 639, 1677, 1217, +848, 1622, -42, 1756, -582, 1542, -912, 1107, +-1212, 576, -1241, -51, -848, -733, -433, -1354, +-313, -1779, -188, -1924, 152, -1835, 419, -1507, +502, -799, 678, 269, 953, 1415, 1015, 2317, +748, 2798, 316, 2759, -121, 2098, -574, 853, +-1013, -660, -1222, -2009, -1040, -2894, -594, -3127, +-79, -2629, 394, -1547, 698, -189, 714, 1108, +493, 2043, 166, 2444, -145, 2304, -249, 1717, +-31, 841, 317, -77, 527, -790, 544, -1246, +401, -1421, 108, -1271, -357, -938, -885, -583, +-1208, -247, -1171, 59, -855, 348, -332, 538, +365, 587, 1001, 630, 1333, 643, 1326, 499, +1027, 272, 485, 146, -129, 95, -609, -40, +-841, -189, -802, -287, -560, -486, -284, -710, +-97, -763, 1, -688, -32, -500, -235, -147, +-443, 310, -379, 751, -13, 1042, 462, 1112, +910, 922, 1294, 510, 1447, 0, 1152, -508, +456, -853, -390, -932, -1172, -811, -1753, -517, +-1963, -93, -1704, 287, -1033, 451, -173, 383, +637, 200, 1270, -67, 1633, -365, 1635, -426, +1346, -102, 973, 419, 542, 847, -14, 1055, +-564, 1020, -945, 642, -1234, -75, -1482, -910, +-1561, -1564, -1365, -1790, -928, -1579, -302, -1040, +476, -192, 1326, 808, 2070, 1632, 2437, 2026, +2271, 1934, 1590, 1453, 513, 633, -764, -368, +-1904, -1190, -2597, -1635, -2721, -1713, -2298, -1467, +-1401, -934, -180, -246, 1058, 346, 1955, 751, +2332, 999, 2244, 1021, 1756, 904, 918, 785, +-37, 572, -794, 233, -1285, -96, -1566, -362, +-1574, -631, -1257, -887, -768, -1011, -283, -977, +235, -791, 758, -406, 1075, 100, 1086, 594, +956, 1052, 750, 1403, 373, 1465, -109, 1115, +-495, 455, -737, -288, -831, -972, -657, -1515, +-276, -1746, 41, -1491, 212, -801, 354, 85, +409, 925, 237, 1532, -56, 1764, -235, 1493, +-287, 751, -327, -167, -283, -944, -11, -1424, +384, -1521, 609, -1182, 611, -485, 518, 287, +352, 837, 47, 1083, -286, 1058, -490, 788, +-607, 348, -720, -69, -760, -315, -631, -467, +-380, -608, -30, -680, 432, -709, 868, -725, +1110, -566, 1178, -122, 1080, 450, 693, 971, +63, 1387, -553, 1565, -1046, 1326, -1421, 684, +-1524, -234, -1204, -1260, -576, -2097, 82, -2404, +633, -2020, 1039, -1067, 1239, 241, 1136, 1572, +767, 2473, 400, 2671, 184, 2143, -38, 1030, +-349, -323, -566, -1466, -655, -2091, -798, -2158, +-980, -1701, -947, -802, -637, 184, -216, 917, +251, 1303, 805, 1276, 1303, 897, 1516, 394, +1370, -44, 884, -273, 169, -263, -583, -118, +-1189, 8, -1499, -12, -1374, -186, -888, -482, +-291, -753, 255, -779, 683, -559, 850, -121, +681, 540, 398, 1150, 174, 1357, -25, 1100, +-151, 548, -60, -149, 175, -886, 329, -1372, +261, -1361, 22, -929, -248, -238, -540, 537, +-806, 1129, -789, 1301, -414, 1046, 1, 531, +262, -128, 461, -775, 608, -1133, 537, -1086, +312, -702, 182, -174, 159, 299, 95, 664, +33, 883, 65, 832, 58, 510, -139, 137, +-456, -118, -692, -322, -814, -469, -867, -446, +-711, -356, -207, -318, 477, -302, 1038, -266, +1342, -156, 1420, 39, 1238, 294, 656, 587, +-184, 814, -877, 845, -1276, 638, -1492, 303, +-1419, -84, -927, -592, -260, -1072, 240, -1226, +589, -1057, 963, -696, 1213, -156, 1095, 508, +761, 1068, 513, 1309, 223, 1220, -329, 868, +-854, 291, -964, -345, -878, -836, -894, -1087, +-754, -1057, -275, -751, 253, -255, 613, 251, +877, 592, 992, 693, 828, 585, 438, 320, +15, -12, -322, -259, -536, -303, -594, -184, +-463, -19, -239, 133, -92, 254, -40, 249, +6, 49, 66, -198, 81, -340, 93, -368, +190, -308, 310, -152, 301, 111, 189, 361, +75, 420, -89, 285, -304, 98, -411, -69, +-339, -229, -241, -340, -115, -258, 154, -21, +463, 181, 588, 322, 541, 437, 381, 407, +35, 139, -459, -233, -890, -501, -1033, -643, +-806, -695, -341, -563, 158, -193, 670, 304, +1106, 706, 1232, 900, 1020, 909, 653, 735, +157, 345, -526, -186, -1210, -652, -1557, -877, +-1444, -867, -1030, -718, -424, -463, 334, -123, +1052, 234, 1456, 470, 1496, 557, 1270, 573, +803, 524, 112, 402, -622, 220, -1175, 7, +-1453, -145, -1355, -218, -887, -285, -251, -352, +350, -395, 801, -394, 994, -398, 905, -386, +593, -239, 177, 20, -186, 329, -416, 642, +-458, 852, -286, 887, 3, 705, 237, 290, +330, -203, 212, -609, -88, -845, -428, -899, +-663, -764, -712, -445, -548, -86, -157, 194, +377, 398, 880, 470, 1176, 383, 1137, 270, +709, 253, 72, 320, -548, 363, -1025, 388, +-1214, 379, -1021, 169, -566, -305, -83, -855, +308, -1206, 641, -1253, 879, -1018, 821, -491, +492, 294, 159, 1098, -85, 1590, -347, 1593, +-552, 1222, -529, 622, -272, -165, 2, -945, +74, -1395, 32, -1336, 61, -911, 143, -370, +119, 159, 55, 560, 95, 683, 123, 517, +-2, 169, -128, -168, -130, -312, -88, -190, +-30, 155, 38, 532, 70, 778, 91, 824, +133, 567, 135, -41, 65, -772, -60, -1294, +-183, -1452, -283, -1275, -322, -755, -223, 36, +6, 789, 227, 1295, 329, 1521, 343, 1393, +293, 889, 175, 262, -26, -252, -199, -659, +-251, -959, -255, -1000, -273, -837, -214, -718, +-31, -642, 104, -401, 100, -16, 118, 350, +253, 745, 320, 1162, 248, 1388, 149, 1280, +21, 876, -194, 229, -397, -542, -506, -1184, +-471, -1528, -245, -1583, 45, -1291, 244, -616, +422, 142, 666, 705, 740, 1046, 483, 1192, +57, 1099, -328, 789, -656, 397, -889, 51, +-850, -210, -505, -385, -34, -514, 357, -606, +612, -650, 734, -735, 691, -811, 457, -693, +148, -336, -80, 152, -215, 712, -334, 1290, +-402, 1662, -355, 1573, -273, 1042, -260, 270, +-281, -609, -216, -1437, -79, -1970, 76, -1988, +239, -1502, 461, -669, 722, 339, 865, 1294, +727, 1931, 358, 2034, -69, 1569, -564, 745, +-1051, -189, -1238, -1043, -1014, -1574, -622, -1621, +-221, -1215, 254, -556, 756, 172, 1060, 793, +1098, 1079, 951, 992, 631, 664, 144, 194, +-406, -277, -814, -575, -913, -609, -714, -388, +-436, -77, -170, 215, 36, 431, 107, 446, +57, 217, 4, -130, 56, -412, 161, -565, +253, -556, 366, -279, 553, 172, 717, 504, +724, 681, 484, 733, -3, 558, -582, 134, +-1113, -376, -1500, -756, -1522, -929, -1049, -893, +-275, -606, 507, -58, 1147, 616, 1597, 1149, +1682, 1304, 1346, 1076, 761, 536, 102, -218, +-612, -994, -1213, -1509, -1430, -1559, -1246, -1169, +-848, -451, -441, 448, -45, 1253, 285, 1665, +435, 1608, 444, 1152, 502, 400, 659, -488, +788, -1213, 809, -1566, 747, -1523, 558, -1091, +114, -405, -525, 320, -1120, 914, -1526, 1259, +-1666, 1268, -1440, 953, -839, 432, 71, -92, +1023, -516, 1686, -798, 1927, -882, 1780, -754, +1269, -440, 426, -51, -491, 294, -1174, 495, +-1513, 510, -1607, 389, -1395, 179, -832, -94, +-139, -280, 464, -274, 884, -131, 1112, 63, +1140, 232, 912, 321, 451, 292, -41, 156, +-369, -71, -531, -314, -600, -468, -526, -523, +-291, -485, -45, -277, 47, 65, 66, 384, +68, 582, -27, 680, -111, 669, -69, 432, +38, 21, 100, -372, 218, -621, 378, -732, +379, -683, 209, -386, 55, 75, -41, 424, +-197, 568, -333, 577, -324, 424, -224, 100, +-133, -292, -83, -534, -32, -535, 19, -371, +18, -86, -16, 281, -15, 591, 93, 713, +275, 613, 424, 315, 472, -146, 402, -613, +210, -854, -107, -884, -408, -745, -618, -376, +-708, 145, -630, 589, -358, 844, 25, 933, +332, 834, 528, 508, 646, 88, 583, -232, +251, -442, -113, -611, -219, -738, -172, -689, +-157, -489, -104, -295, 45, -104, 118, 148, +-33, 410, -231, 593, -302, 658, -315, 626, +-291, 531, -125, 385, 187, 209, 442, -66, +549, -394, 481, -643, 260, -777, -39, -814, +-311, -766, -439, -578, -388, -240, -172, 165, +116, 590, 365, 966, 451, 1156, 305, 1161, +-25, 952, -396, 495, -642, -111, -750, -705, +-699, -1172, -353, -1436, 222, -1376, 779, -987, +1144, -423, 1258, 226, 1094, 859, 624, 1223, +-40, 1258, -748, 1049, -1319, 649, -1589, 126, +-1462, -339, -1027, -564, -426, -584, 311, -523, +982, -413, 1365, -260, 1449, -169, 1375, -241, +1103, -392, 517, -382, -201, -174, -775, 132, +-1197, 506, -1486, 904, -1458, 1179, -1050, 1119, +-460, 705, 119, 122, 583, -459, 907, -973, +1065, -1325, 998, -1379, 806, -1072, 562, -547, +302, 53, 32, 616, -258, 998, -503, 1155, +-662, 1065, -742, 752, -785, 336, -773, -37, +-722, -311, -525, -506, -90, -658, 439, -713, +893, -652, 1209, -529, 1392, -376, 1326, -156, +854, 182, 168, 508, -436, 699, -947, 781, +-1377, 749, -1540, 517, -1331, 136, -880, -241, +-321, -499, 222, -623, 742, -586, 1159, -408, +1281, -212, 1114, -56, 806, 49, 505, 126, +150, 171, -237, 192, -528, 229, -716, 304, +-890, 356, -1008, 307, -932, 156, -682, -14, +-347, -188, 18, -400, 410, -523, 791, -471, +1009, -292, 1045, -63, 985, 193, 828, 423, +547, 525, 114, 449, -380, 238, -819, -60, +-1195, -318, -1492, -432, -1550, -446, -1237, -318, +-655, -16, 127, 322, 994, 477, 1773, 416, +2195, 276, 2068, 97, 1459, -153, 507, -350, +-589, -392, -1564, -325, -2124, -205, -2128, -68, +-1676, 88, -921, 185, 38, 215, 986, 220, +1536, 189, 1577, 118, 1322, 47, 850, 25, +238, 66, -301, 87, -625, 17, -747, -94, +-721, -188, -531, -264, -299, -385, -121, -455, +-42, -351, 0, -132, 54, 116, 100, 390, +189, 685, 325, 898, 452, 876, 444, 578, +255, 85, -36, -509, -289, -1012, -410, -1299, +-416, -1275, -288, -877, -26, -184, 251, 599, +439, 1187, 444, 1393, 224, 1238, -135, 787, +-471, 118, -698, -564, -771, -1020, -494, -1075, +91, -824, 639, -424, 893, 42, 945, 437, +843, 635, 459, 568, -109, 284, -629, -66, +-912, -337, -942, -432, -757, -313, -397, -70, +44, 234, 389, 511, 464, 642, 344, 530, +257, 187, 260, -213, 267, -545, 277, -764, +355, -799, 372, -626, 159, -312, -185, 78, +-494, 450, -710, 728, -914, 824, -963, 765, +-668, 610, -127, 317, 461, -103, 943, -518, +1266, -776, 1315, -854, 998, -797, 334, -568, +-371, -161, -882, 237, -1233, 534, -1311, 707, +-978, 709, -382, 537, 205, 265, 637, 6, +906, -226, 955, -392, 726, -404, 320, -278, +-67, -115, -324, 34, -479, 107, -513, 84, +-429, -36, -241, -198, -57, -314, 61, -339, +201, -178, 284, 136, 247, 427, 144, 623, +92, 754, 43, 714, -74, 390, -156, -96, +-141, -493, -139, -769, -215, -959, -194, -965, +-25, -717, 132, -263, 256, 211, 374, 582, +406, 858, 268, 1020, 27, 970, -176, 716, +-351, 335, -460, -93, -469, -519, -406, -879, +-251, -1132, 6, -1205, 298, -911, 512, -337, +643, 265, 608, 810, 448, 1227, 225, 1305, +-80, 954, -402, 352, -638, -250, -702, -733, +-644, -986, -513, -887, -231, -527, 175, -78, +468, 325, 591, 604, 731, 615, 808, 314, +580, -69, 154, -337, -227, -513, -520, -507, +-793, -229, -880, 148, -617, 458, -232, 646, +76, 646, 314, 383, 530, 19, 585, -279, +473, -509, 325, -613, 152, -508, -88, -275, +-315, -54, -341, 92, -235, 170, -150, 211, +-92, 184, -27, 174, 1, 236, -62, 311, +-120, 316, -43, 254, 126, 163, 275, -16, +307, -298, 235, -551, 120, -679, -35, -641, +-217, -447, -336, -217, -274, 96, -121, 509, +53, 822, 208, 854, 339, 660, 392, 412, +206, 126, -168, -263, -511, -647, -665, -838, +-645, -766, -393, -507, 142, -210, 756, 111, +1107, 402, 1043, 575, 689, 574, 154, 366, +-513, 93, -1076, -63, -1281, -140, -1093, -220, +-664, -200, -101, -31, 552, 128, 1050, 129, +1185, 60, 951, -56, 551, -240, 89, -392, +-379, -417, -659, -269, -671, -1, -518, 277, +-345, 493, -166, 602, -55, 544, -47, 332, +-49, 22, 25, -266, 197, -486, 389, -609, +553, -557, 678, -340, 640, -46, 347, 203, +-108, 353, -547, 396, -858, 296, -982, 111, +-839, 5, -452, -29, 57, 3, 466, 106, +720, 177, 823, 113, 693, -66, 361, -272, +-22, -483, -269, -605, -388, -513, -369, -222, +-177, 166, 51, 584, 105, 882, -27, 940, +-185, 710, -315, 233, -388, -323, -331, -821, +-125, -1129, 198, -1109, 519, -711, 701, -94, +685, 506, 506, 938, 222, 1127, -149, 964, +-457, 478, -606, -126, -624, -567, -514, -712, +-322, -702, -145, -562, -26, -228, 121, 136, +251, 278, 344, 225, 417, 171, 465, 156, +485, 115, 419, 112, 265, 192, 44, 285, +-268, 310, -608, 177, -844, -87, -899, -417, +-725, -705, -341, -799, 78, -631, 417, -257, +707, 235, 884, 700, 867, 994, 656, 1002, +353, 685, 26, 160, -355, -374, -672, -749, +-809, -962, -719, -941, -503, -578, -267, -40, +-44, 383, 180, 639, 361, 772, 410, 713, +412, 396, 406, -52, 323, -369, 181, -490, +74, -483, 15, -375, -73, -128, -168, 142, +-211, 248, -291, 211, -419, 138, -481, 34, +-407, -33, -243, -7, -37, 44, 215, 117, +459, 162, 625, 94, 652, -108, 596, -292, +413, -391, 63, -450, -321, -347, -590, 2, +-640, 383, -517, 630, -353, 769, -203, 751, +-29, 471, 117, -56, 173, -592, 180, -975, +169, -1162, 168, -1075, 194, -689, 230, -68, +302, 660, 401, 1280, 439, 1587, 281, 1491, +-99, 1012, -516, 240, -857, -692, -1045, -1467, +-972, -1834, -570, -1750, -21, -1229, 482, -384, +893, 543, 1127, 1303, 1131, 1734, 901, 1738, +476, 1319, -113, 607, -669, -202, -956, -958, +-987, -1431, -856, -1504, -579, -1246, -200, -715, +143, -23, 327, 616, 410, 993, 492, 1042, +529, 845, 457, 511, 342, 98, 292, -281, +213, -491, 17, -433, -244, -254, -411, -139, +-498, -42, -618, 43, -639, 26, -446, -93, +-163, -195, 49, -202, 273, -106, 547, 53, +721, 235, 677, 350, 490, 380, 311, 316, +137, 150, -89, -29, -328, -166, -496, -241, +-571, -248, -627, -203, -648, -134, -512, -74, +-216, -51, 142, -33, 486, -23, 787, -27, +913, -29, 808, 9, 584, 127, 264, 259, +-164, 351, -586, 379, -817, 331, -865, 186, +-725, -72, -417, -375, -67, -561, 235, -610, +443, -554, 529, -355, 486, -35, 362, 264, +230, 422, 110, 505, -17, 514, -110, 373, +-112, 181, -72, 84, -88, 33, -170, -40, +-285, -128, -349, -216, -350, -344, -283, -506, +-86, -604, 162, -599, 353, -442, 463, -102, +531, 364, 477, 809, 282, 1111, 49, 1189, +-145, 972, -330, 442, -484, -256, -463, -923, +-305, -1391, -174, -1479, -101, -1163, -23, -560, +62, 167, 134, 840, 209, 1241, 316, 1224, +405, 863, 395, 360, 262, -141, 94, -497, +-27, -590, -166, -443, -355, -196, -496, -29, +-516, 1, -476, -107, -311, -306, -9, -450, +299, -415, 519, -195, 614, 178, 577, 628, +400, 997, 158, 1095, -83, 835, -335, 311, +-553, -366, -576, -1013, -402, -1401, -209, -1360, +7, -878, 296, -152, 471, 577, 401, 1137, +197, 1347, 28, 1125, -85, 589, -225, -61, +-329, -609, -288, -931, -100, -971, 97, -747, +243, -310, 360, 177, 419, 478, 299, 566, +16, 558, -211, 420, -348, 140, -456, -98, +-480, -188, -372, -205, -222, -241, -51, -257, +226, -237, 545, -210, 719, -159, 694, -58, +502, 123, 175, 334, -177, 458, -444, 461, +-609, 373, -672, 187, -617, -59, -476, -336, +-251, -532, 35, -565, 345, -490, 610, -358, +725, -140, 667, 176, 489, 464, 266, 615, +17, 634, -246, 509, -471, 230, -570, -76, +-580, -317, -551, -451, -402, -470, -156, -405, +49, -277, 221, -134, 430, -32, 597, 36, +614, 137, 504, 277, 352, 378, 146, 382, +-100, 330, -320, 225, -467, 74, -566, -99, +-609, -254, -576, -323, -451, -334, -172, -338, +209, -329, 564, -280, 800, -173, 892, -2, +772, 208, 441, 453, 5, 684, -452, 787, +-823, 645, -978, 288, -876, -145, -534, -603, +12, -976, 576, -1075, 904, -841, 896, -383, +629, 152, 150, 640, -447, 996, -904, 1062, +-953, 764, -620, 264, -88, -220, 528, -580, +1047, -766, 1237, -664, 967, -330, 329, 14, +-465, 248, -1156, 334, -1560, 214, -1517, -21, +-949, -208, -43, -250, 868, -112, 1516, 164, +1740, 463, 1440, 629, 717, 587, -137, 306, +-879, -159, -1353, -645, -1381, -978, -982, -1048, +-415, -779, 114, -218, 525, 448, 721, 989, +664, 1235, 478, 1156, 256, 720, 44, 17, +-81, -664, -54, -1046, 7, -1106, 8, -901, +-48, -432, -189, 149, -377, 545, -479, 695, +-437, 680, -264, 484, 43, 187, 371, -52, +563, -154, 547, -188, 381, -192, 157, -133, +-77, -53, -262, -65, -304, -179, -236, -286, +-132, -291, -14, -213, 20, -81, -42, 166, +-82, 459, -78, 653, -116, 669, -111, 502, +57, 167, 307, -265, 457, -640, 461, -820, +352, -794, 79, -572, -316, -172, -651, 264, +-773, 597, -644, 754, -280, 716, 220, 475, +684, 127, 907, -193, 793, -442, 440, -565, +-1, -485, -450, -247, -803, 33, -900, 260, +-698, 335, -289, 246, 179, 64, 584, -132, +796, -300, 771, -338, 535, -167, 153, 93, +-216, 302, -436, 440, -507, 486, -484, 390, +-368, 143, -217, -206, -76, -504, 48, -652, +151, -639, 247, -477, 336, -179, 398, 199, +414, 516, 352, 677, 200, 648, -29, 443, +-318, 159, -567, -106, -678, -340, -635, -476, +-426, -444, -36, -284, 378, -119, 617, -7, +655, 82, 545, 134, 309, 113, 3, 61, +-230, 63, -344, 115, -361, 156, -294, 169, +-155, 176, -27, 120, 30, -1, 29, -130, +-4, -241, -44, -299, -38, -271, 65, -170, +215, -51, 319, 55, 310, 131, 202, 148, +14, 101, -234, 53, -438, 34, -433, 70, +-226, 156, 25, 226, 245, 250, 392, 194, +383, 36, 178, -204, -146, -473, -448, -685, +-588, -716, -509, -503, -184, -86, 304, 397, +725, 819, 909, 1046, 814, 959, 448, 591, +-123, 35, -714, -563, -1117, -979, -1193, -1075, +-924, -884, -360, -468, 353, 111, 953, 666, +1223, 954, 1134, 915, 760, 606, 184, 88, +-423, -445, -836, -773, -929, -804, -789, -564, +-502, -115, -109, 396, 277, 766, 498, 856, +513, 642, 396, 189, 221, -356, 25, -818, +-137, -1036, -174, -897, -89, -470, 19, 103, +52, 670, 22, 1040, -18, 1060, -87, 758, +-179, 275, -192, -270, -110, -726, -35, -907, +16, -783, 77, -479, 128, -77, 147, 308, +153, 543, 146, 557, 123, 378, 84, 87, +24, -200, -76, -360, -201, -327, -292, -149, +-304, 97, -229, 345, -77, 491, 114, 454, +280, 216, 388, -142, 369, -472, 197, -665, +-40, -682, -245, -537, -386, -240, -408, 162, +-256, 525, -5, 720, 227, 743, 379, 626, +426, 380, 335, 13, 125, -339, -111, -525, +-288, -558, -399, -541, -433, -449, -356, -233, +-206, -35, -33, 34, 168, 124, 374, 319, +499, 443, 519, 451, 430, 449, 260, 426, +61, 272, -163, 11, -430, -245, -667, -465, +-764, -626, -695, -688, -447, -621, -29, -393, +457, -30, 824, 334, 968, 604, 882, 736, +586, 706, 137, 501, -333, 175, -697, -126, +-860, -310, -780, -397, -525, -411, -163, -326, +227, -187, 477, -108, 443, -134, 239, -165, +57, -147, -45, -72, -62, 76, 63, 304, +309, 567, 497, 737, 485, 717, 242, 483, +-152, 88, -574, -385, -913, -828, -1065, -1116, +-909, -1108, -430, -770, 235, -217, 869, 384, +1283, 900, 1350, 1206, 1021, 1160, 387, 790, +-336, 271, -904, -275, -1154, -764, -1034, -1033, +-665, -974, -186, -641, 289, -200, 586, 225, +589, 556, 392, 694, 150, 603, -73, 343, +-209, 41, -169, -178, 56, -253, 312, -210, +436, -132, 371, -80, 124, -47, -244, -63, +-594, -132, -817, -163, -824, -103, -524, 20, +1, 171, 518, 344, 871, 474, 995, 453, +834, 248, 417, -67, -132, -391, -626, -671, +-887, -841, -829, -766, -526, -389, -114, 155, +324, 700, 661, 1110, 721, 1247, 473, 1015, +88, 449, -305, -293, -595, -981, -637, -1408, +-411, -1449, -63, -1086, 282, -421, 551, 332, +637, 958, 506, 1339, 242, 1369, -68, 1026, +-367, 450, -562, -177, -586, -703, -440, -996, +-174, -1021, 121, -809, 324, -418, 362, 14, +281, 304, 152, 423, 41, 469, -5, 413, +7, 258, 16, 135, 28, 96, 66, 94, +76, 112, 1, 123, -129, 63, -255, -101, +-349, -341, -364, -568, -286, -681, -134, -619, +93, -389, 358, -14, 524, 423, 530, 787, +444, 966, 320, 898, 144, 594, -94, 157, +-345, -318, -524, -747, -615, -964, -646, -889, +-544, -612, -268, -233, 89, 195, 411, 518, +673, 605, 846, 534, 827, 391, 567, 191, +183, -10, -202, -122, -567, -132, -815, -91, +-812, -64, -594, -69, -325, -118, -98, -203, +129, -305, 389, -385, 596, -356, 652, -150, +565, 185, 388, 500, 177, 710, -49, 802, +-288, 700, -470, 310, -533, -254, -550, -767, +-540, -1084, -412, -1127, -132, -857, 235, -302, +588, 403, 822, 1041, 860, 1382, 680, 1304, +282, 843, -215, 130, -632, -655, -883, -1271, +-959, -1505, -794, -1272, -362, -684, 186, 67, +655, 812, 936, 1328, 954, 1409, 695, 1074, +269, 520, -199, -114, -569, -716, -712, -1102, +-644, -1149, -493, -906, -289, -482, -40, 9, +174, 442, 313, 716, 387, 767, 409, 629, +391, 416, 370, 202, 303, 2, 144, -135, +-84, -215, -326, -307, -555, -426, -725, -500, +-747, -498, -552, -417, -161, -213, 278, 74, +636, 365, 896, 607, 988, 726, 787, 666, +360, 470, -114, 194, -542, -130, -867, -443, +-962, -652, -763, -690, -376, -578, 5, -382, +263, -143, 435, 130, 534, 366, 516, 451, +388, 400, 252, 334, 166, 294, 76, 239, +-56, 151, -178, 56, -274, -43, -398, -192, +-505, -395, -500, -563, -385, -606, -188, -510, +99, -298, 419, -2, 658, 316, 747, 586, +688, 751, 452, 777, 38, 664, -392, 403, +-670, -15, -772, -461, -693, -791, -408, -962, +-29, -947, 287, -685, 482, -208, 530, 333, +430, 772, 251, 1007, 63, 986, -118, 698, +-240, 197, -248, -355, -178, -736, -116, -862, +-60, -746, 29, -395, 102, 76, 93, 457, +42, 637, 22, 585, 50, 304, 63, -83, +4, -397, -82, -547, -127, -510, -134, -260, +-138, 108, -85, 429, 56, 606, 212, 591, +291, 368, 315, 34, 310, -283, 175, -515, +-118, -598, -431, -495, -596, -261, -579, -10, +-426, 212, -158, 385, 217, 448, 585, 356, +763, 183, 664, 45, 367, -47, 23, -125, +-275, -169, -519, -145, -638, -96, -501, -81, +-160, -103, 145, -96, 262, -49, 268, -13, +228, 7, 92, 53, -110, 90, -218, 53, +-157, 3, 14, 30, 221, 110, 364, 202, +410, 291, 349, 298, 104, 180, -296, -58, +-636, -373, -770, -657, -702, -774, -436, -664, +17, -350, 535, 128, 903, 634, 971, 984, +750, 1088, 358, 921, -129, 465, -617, -158, +-927, -739, -894, -1120, -571, -1195, -156, -919, +250, -385, 580, 213, 706, 706, 558, 953, +218, 884, -147, 566, -365, 149, -414, -227, +-339, -449, -99, -471, 244, -317, 457, -67, +439, 138, 270, 172, -36, 29, -440, -162, +-730, -306, -734, -359, -484, -248, -77, 46, +408, 379, 829, 597, 1021, 630, 920, 468, +533, 163, -57, -166, -662, -413, -1098, -551, +-1247, -558, -1035, -441, -482, -261, 219, -48, +810, 182, 1148, 367, 1205, 492, 942, 566, +370, 525, -301, 330, -812, 25, -1045, -340, +-966, -685, -611, -834, -142, -684, 290, -314, +579, 163, 634, 627, 476, 874, 243, 793, +39, 442, -100, -50, -148, -502, -120, -734, +-65, -682, -22, -426, -4, -59, -71, 295, +-204, 487, -287, 471, -279, 309, -196, 80, +-10, -115, 231, -196, 412, -172, 497, -85, +452, 17, 292, 81, 101, 56, -105, -50, +-353, -179, -554, -265, -615, -272, -557, -188, +-399, -25, -70, 200, 395, 430, 739, 574, +801, 594, 673, 469, 429, 188, 40, -215, +-386, -626, -693, -922, -798, -1038, -696, -914, +-423, -477, -27, 192, 388, 856, 675, 1319, +729, 1464, 572, 1218, 289, 595, -35, -219, +-344, -972, -538, -1448, -544, -1525, -442, -1216, +-299, -618, -70, 124, 232, 791, 494, 1179, +620, 1252, 561, 1061, 351, 642, 58, 97, +-277, -367, -583, -651, -722, -802, -630, -857, +-371, -776, -53, -529, 296, -174, 634, 190, +806, 535, 717, 863, 433, 1039, 73, 894, +-301, 454, -622, -108, -778, -660, -698, -1058, +-458, -1128, -176, -824, 130, -261, 447, 371, +680, 858, 719, 1023, 570, 846, 332, 415, +47, -119, -301, -534, -598, -677, -719, -606, +-682, -425, -486, -164, -90, 105, 361, 280, +641, 356, 678, 384, 511, 352, 195, 245, +-147, 76, -351, -124, -370, -291, -271, -352, +-110, -309, 55, -182, 126, -2, 92, 162, +29, 229, -34, 135, -78, -70, -106, -227, +-116, -213, -38, -52, 135, 207, 273, 513, +301, 708, 239, 592, 84, 146, -149, -459, +-352, -979, -415, -1180, -332, -962, -152, -382, +76, 393, 252, 1067, 280, 1337, 237, 1129, +218, 562, 171, -159, 49, -778, -104, -1061, +-226, -954, -264, -568, -223, -58, -166, 384, +-68, 614, 116, 622, 265, 465, 225, 202, +60, -89, -72, -342, -125, -498, -94, -500, +57, -317, 225, 20, 256, 384, 159, 617, +-30, 637, -296, 440, -487, 45, -456, -435, +-274, -775, -27, -817, 265, -586, 492, -166, +544, 320, 489, 702, 409, 870, 171, 770, +-268, 405, -657, -115, -804, -588, -764, -851, +-534, -833, -67, -539, 490, -44, 853, 490, +872, 849, 629, 864, 292, 549, -41, 69, +-319, -422, -495, -750, -578, -781, -571, -546, +-478, -176, -296, 194, -6, 418, 351, 456, +624, 429, 689, 407, 569, 351, 340, 250, +53, 98, -241, -184, -403, -549, -405, -797, +-410, -825, -471, -649, -446, -282, -290, 204, +-45, 639, 282, 880, 637, 914, 876, 795, +885, 553, 647, 196, 167, -246, -447, -672, +-923, -998, -1065, -1143, -950, -1025, -679, -632, +-232, -46, 303, 589, 758, 1076, 1065, 1256, +1155, 1126, 915, 753, 392, 198, -268, -395, +-886, -801, -1205, -957, -1065, -914, -636, -673, +-171, -289, 268, 61, 597, 285, 653, 443, +520, 545, 440, 521, 400, 391, 245, 265, +-19, 156, -294, 8, -517, -175, -625, -330, +-578, -411, -378, -418, -81, -362, 192, -248, +342, -86, 384, 96, 413, 253, 457, 347, +423, 380, 207, 366, -118, 291, -390, 128, +-562, -74, -623, -252, -499, -400, -211, -458, +89, -344, 329, -116, 526, 86, 599, 242, +461, 352, 201, 356, -67, 249, -321, 105, +-501, -51, -524, -219, -367, -362, -85, -428, +194, -356, 359, -124, 390, 206, 289, 512, +81, 673, -133, 588, -220, 259, -162, -187, +-71, -581, -30, -796, 7, -754, 77, -456, +116, 0, 89, 470, 49, 773, 15, 801, +-77, 581, -219, 194, -279, -254, -192, -603, +-33, -739, 164, -611, 364, -246, 433, 184, +331, 482, 155, 593, -52, 513, -282, 215, +-471, -174, -555, -445, -477, -538, -221, -449, +130, -176, 438, 126, 632, 313, 658, 425, +428, 456, 10, 319, -333, 83, -455, -123, +-428, -282, -291, -357, -102, -318, 15, -240, +51, -145, 82, 3, 89, 117, 69, 130, +78, 113, 106, 128, 132, 192, 171, 297, +208, 343, 156, 233, -18, 16, -246, -235, +-416, -465, -448, -570, -314, -491, -60, -281, +221, 8, 404, 272, 393, 385, 253, 399, +102, 405, -39, 324, -179, 125, -265, -39, +-263, -132, -162, -262, 25, -380, 216, -328, +324, -147, 303, -2, 131, 64, -144, 79, +-392, 42, -477, -37, -341, -62, -84, 39, +157, 230, 343, 412, 457, 489, 434, 374, +278, 54, 79, -372, -102, -736, -260, -854, +-401, -651, -482, -204, -430, 326, -192, 756, +131, 895, 343, 673, 419, 223, 455, -237, +353, -545, 63, -625, -190, -488, -307, -204, +-350, 127, -256, 345, -23, 370, 162, 285, +239, 167, 268, -18, 177, -217, -76, -302, +-319, -283, -402, -198, -346, -13, -149, 219, +186, 356, 485, 349, 592, 205, 492, -45, +182, -281, -206, -398, -467, -393, -552, -229, +-461, 103, -190, 407, 91, 492, 232, 397, +290, 205, 282, -74, 178, -364, 58, -543, +-25, -534, -124, -351, -178, -89, -106, 184, +-26, 454, -7, 634, 63, 616, 132, 425, +54, 129, -48, -241, -65, -583, -91, -723, +-119, -616, -67, -349, -19, -12, 3, 296, +62, 477, 112, 488, 113, 345, 110, 133, +79, -13, -32, -53, -133, -65, -138, -83, +-91, -75, -35, -45, 86, -43, 209, -108, +154, -199, -84, -243, -322, -233, -418, -201, +-338, -108, -71, 117, 328, 411, 652, 629, +681, 677, 405, 535, -33, 209, -438, -231, +-606, -658, -506, -895, -300, -824, -79, -495, +108, -58, 163, 345, 169, 600, 272, 628, +366, 449, 284, 173, 90, -52, -95, -138, +-228, -110, -269, -48, -186, 10, -39, 24, +59, -60, 60, -193, -9, -295, -58, -359, +-43, -350, -21, -178, -21, 104, 29, 360, +110, 539, 176, 607, 270, 500, 313, 242, +142, -85, -165, -395, -423, -563, -562, -551, +-485, -437, -160, -239, 250, 57, 531, 323, +571, 455, 385, 444, 114, 269, -91, -12, +-234, -231, -362, -340, -406, -338, -318, -99, +-184, 302, 2, 527, 285, 462, 512, 222, +532, -171, 380, -617, 77, -836, -293, -684, +-516, -254, -510, 288, -353, 740, -98, 901, +192, 711, 380, 250, 393, -260, 247, -556, +9, -591, -218, -484, -291, -249, -175, 66, +0, 262, 134, 288, 206, 267, 193, 238, +103, 168, -13, 34, -136, -184, -215, -385, +-223, -395, -224, -233, -242, -30, -210, 200, +-55, 390, 206, 392, 437, 247, 550, 101, +573, -24, 474, -115, 175, -127, -280, -149, +-712, -266, -983, -397, -984, -424, -657, -297, +-126, -9, 400, 351, 831, 624, 1087, 723, +989, 623, 595, 344, 175, -29, -229, -356, +-659, -541, -949, -591, -973, -583, -771, -538, +-366, -391, 161, -105, 617, 270, 866, 642, +834, 897, 536, 925, 145, 683, -186, 196, +-431, -393, -545, -821, -420, -906, -117, -680, +152, -308, 268, 23, 224, 198, 54, 244, +-170, 237, -379, 219, -453, 227, -215, 276, +236, 322, 572, 306, 670, 179, 578, -60, +313, -315, -53, -480, -403, -559, -685, -585, +-796, -490, -607, -202, -191, 244, 288, 681, +721, 916, 911, 886, 675, 623, 139, 112, +-363, -541, -644, -1000, -651, -1039, -368, -730, +74, -236, 413, 306, 484, 714, 357, 839, +179, 657, 12, 277, -158, -102, -292, -350, +-356, -475, -357, -475, -232, -322, 22, -113, +269, 41, 441, 182, 506, 331, 362, 362, +64, 212, -186, -20, -337, -206, -383, -258, +-261, -141, -67, 99, 63, 333, 160, 381, +198, 137, 59, -302, -163, -694, -228, -822, +-107, -583, 104, -18, 331, 679, 430, 1205, +279, 1273, -14, 795, -263, -13, -399, -794, +-399, -1283, -300, -1334, -155, -900, 37, -155, +222, 576, 320, 1025, 351, 1057, 298, 714, +77, 224, -229, -205, -398, -487, -328, -573, +-102, -453, 159, -223, 346, -11, 309, 152, +14, 260, -326, 249, -504, 121, -456, -40, +-208, -195, 136, -296, 430, -243, 612, 8, +635, 322, 407, 506, 1, 499, -414, 300, +-738, -82, -863, -512, -669, -771, -217, -739, +271, -417, 621, 98, 765, 616, 677, 905, +427, 818, 130, 397, -186, -167, -472, -647, +-642, -876, -639, -767, -429, -337, -53, 245, +271, 700, 398, 840, 349, 673, 202, 303, +92, -178, 114, -637, 209, -880, 242, -801, +107, -444, -209, 85, -514, 616, -560, 926, +-314, 885, 32, 533, 285, 13, 358, -507, +258, -843, 80, -854, -16, -512, 37, 24, +111, 463, 73, 645, -65, 585, -189, 292, +-191, -144, -56, -466, 126, -518, 245, -320, +238, 67, 124, 462, -71, 604, -297, 436, +-394, 70, -307, -376, -145, -699, 73, -709, +351, -441, 547, -21, 560, 431, 414, 716, +121, 723, -245, 528, -497, 186, -528, -240, +-421, -580, -273, -726, -90, -681, 100, -406, +242, 66, 321, 539, 329, 842, 252, 830, +114, 426, -18, -171, -70, -677, 7, -950, +132, -855, 121, -317, -99, 439, -430, 1019, +-676, 1162, -646, 792, -316, 37, 123, -755, +472, -1263, 659, -1301, 686, -772, 573, 143, +334, 995, 4, 1457, -356, 1382, -675, 737, +-865, -237, -808, -1092, -454, -1500, 70, -1357, +501, -701, 683, 251, 608, 1090, 359, 1454, +102, 1236, -54, 577, -156, -239, -282, -927, +-357, -1271, -297, -1134, -127, -554, 66, 213, +152, 835, 37, 1108, -209, 997, -372, 531, +-277, -179, 49, -840, 442, -1132, 761, -970, +826, -440, 473, 313, -153, 1012, -693, 1319, +-946, 1067, -917, 353, -673, -544, -242, -1298, +287, -1617, 740, -1310, 1004, -435, 985, 685, +647, 1599, 83, 1963, -510, 1622, -915, 634, +-952, -630, -644, -1672, -177, -2149, 311, -1860, +655, -867, 688, 416, 445, 1524, 104, 2098, +-237, 1876, -495, 937, -517, -261, -223, -1271, +231, -1816, 587, -1665, 702, -849, 516, 226, +63, 1157, -442, 1656, -773, 1466, -821, 660, +-576, -345, -147, -1210, 358, -1688, 794, -1506, +996, -674, 909, 425, 523, 1402, -106, 1943, +-723, 1754, -1083, 843, -1072, -397, -609, -1498, +112, -2083, 690, -1904, 950, -1000, 901, 270, +540, 1409, 31, 1991, -351, 1798, -574, 954, +-722, -175, -665, -1187, -338, -1720, 89, -1574, +513, -833, 826, 220, 799, 1164, 425, 1587, +-71, 1331, -542, 588, -768, -329, -567, -1146, +-176, -1550, 117, -1304, 282, -542, 301, 384, +158, 1175, -9, 1549, -103, 1293, -106, 519, +-9, -387, 111, -1117, 152, -1436, 132, -1127, +86, -335, -31, 500, -192, 1072, -302, 1194, +-377, 742, -386, -52, -211, -749, 65, -1116, +323, -1045, 521, -441, 541, 417, 295, 1051, +-88, 1317, -424, 1173, -600, 513, -517, -439, +-197, -1252, 160, -1640, 369, -1446, 397, -707, +230, 269, -67, 1129, -312, 1633, -394, 1565, +-326, 901, -159, -8, 55, -813, 268, -1329, +420, -1358, 453, -890, 364, -175, 142, 562, +-202, 1101, -535, 1176, -698, 710, -681, -57, +-497, -767, -90, -1155, 488, -1049, 959, -440, +1069, 424, 805, 1169, 259, 1484, -411, 1169, +-963, 280, -1166, -763, -913, -1512, -284, -1745, +403, -1328, 826, -303, 931, 864, 746, 1612, +330, 1750, -132, 1313, -452, 359, -580, -754, +-573, -1478, -401, -1571, 3, -1116, 439, -313, +628, 535, 562, 1168, 313, 1392, -97, 1090, +-506, 390, -666, -426, -458, -1100, -10, -1398, +407, -1165, 653, -475, 669, 376, 461, 1123, +127, 1528, -260, 1310, -629, 504, -811, -469, +-660, -1230, -247, -1521, 233, -1197, 671, -400, +966, 524, 872, 1261, 372, 1547, -215, 1123, +-671, 95, -888, -921, -707, -1459, -217, -1487, +310, -968, 706, 97, 765, 1256, 417, 1895, +-95, 1762, -574, 929, -862, -333, -664, -1481, +-60, -2021, 487, -1870, 771, -1134, 795, 58, +482, 1311, -35, 2029, -426, 1934, -676, 1197, +-804, 134, -591, -890, -177, -1539, 112, -1641, +403, -1182, 690, -318, 639, 614, 308, 1234, +-94, 1305, -538, 855, -760, 88, -496, -685, +21, -1141, 456, -1120, 684, -597, 577, 279, +91, 1091, -495, 1454, -917, 1215, -1071, 409, +-797, -654, -106, -1470, 675, -1722, 1228, -1368, +1375, -432, 1015, 811, 279, 1691, -575, 1817, +-1314, 1290, -1654, 256, -1350, -936, -527, -1665, +430, -1617, 1197, -911, 1534, 165, 1291, 1155, +535, 1578, -415, 1290, -1170, 451, -1423, -643, +-1056, -1435, -242, -1534, 607, -1074, 1144, -228, +1195, 807, 747, 1529, 27, 1607, -641, 1106, +-1006, 216, -985, -730, -602, -1358, -3, -1511, +527, -1141, 816, -268, 875, 695, 639, 1221, +103, 1220, -484, 740, -810, -125, -702, -908, +-205, -1194, 437, -918, 895, -107, 872, 908, +369, 1529, -326, 1484, -927, 791, -1163, -434, +-887, -1669, -241, -2261, 538, -2004, 1186, -958, +1435, 617, 1217, 2037, 690, 2688, -50, 2417, +-927, 1288, -1624, -362, -1695, -1893, -1059, -2762, +-32, -2664, 1003, -1539, 1658, 166, 1640, 1727, +1002, 2664, 16, 2604, -970, 1446, -1492, -251, +-1321, -1814, -673, -2733, 196, -2480, 1036, -1125, +1495, 615, 1402, 2115, 790, 2861, -208, 2444, +-1225, 1034, -1803, -711, -1715, -2232, -1043, -3040, +23, -2687, 1132, -1350, 1800, 351, 1834, 1967, +1316, 2993, 371, 2945, -619, 1881, -1308, 206, +-1669, -1525, -1497, -2657, -723, -2797, 88, -1947, +590, -441, 952, 1070, 1063, 1973, 709, 2046, +181, 1375, -182, 232, -394, -822, -465, -1257, +-402, -1011, -345, -340, -238, 388, -9, 768, +144, 624, 159, 95, 160, -570, 44, -1021, +-144, -925, -95, -330, 100, 444, 132, 1150, +63, 1495, -36, 1221, -278, 467, -504, -474, +-476, -1385, -187, -1969, 286, -1866, 757, -984, +935, 336, 687, 1606, 127, 2428, -518, 2448, +-1034, 1549, -1241, -2, -1040, -1637, -481, -2682, +291, -2727, 988, -1783, 1307, -255, 1189, 1233, +762, 2220, 177, 2436, -433, 1767, -932, 514, +-1143, -728, -987, -1517, -548, -1722, 54, -1349, +621, -457, 924, 574, 881, 1196, 519, 1171, +-49, 601, -527, -255, -604, -1065, -309, -1432, +72, -1059, 379, -81, 532, 1086, 407, 1978, +97, 2162, -171, 1490, -365, 140, -548, -1458, +-618, -2653, -435, -2908, -14, -2119, 535, -608, +1025, 1144, 1160, 2594, 804, 3154, 124, 2578, +-636, 1155, -1197, -586, -1229, -2043, -670, -2756, +109, -2557, 743, -1500, 1118, 75, 1141, 1561, +767, 2397, 107, 2327, -671, 1416, -1285, -42, +-1418, -1496, -986, -2308, -120, -2144, 858, -1117, +1527, 319, 1604, 1577, 1096, 2212, 250, 2046, +-590, 1144, -1124, -214, -1269, -1478, -1124, -2135, +-703, -2066, -84, -1387, 424, -274, 784, 968, +1045, 1939, 895, 2251, 309, 1753, -240, 623, +-509, -716, -507, -1778, -212, -2219, 131, -1805, +205, -610, 101, 754, -87, 1719, -460, 2043, +-746, 1592, -614, 482, -293, -825, 4, -1739, +396, -1923, 762, -1453, 894, -510, 862, 607, +586, 1465, -38, 1799, -654, 1542, -966, 831, +-1063, -39, -889, -863, -447, -1448, -2, -1567, +366, -1181, 630, -503, 615, 219, 378, 849, +125, 1167, -90, 999, -189, 567, -81, 124, +146, -273, 327, -421, 371, -222, 135, 21, +-415, 112, -942, 80, -1120, -184, -938, -632, +-460, -893, 193, -847, 828, -527, 1310, 159, +1479, 1009, 1238, 1582, 635, 1714, -212, 1357, +-1072, 396, -1649, -889, -1763, -1829, -1309, -2145, +-308, -1878, 797, -954, 1482, 398, 1659, 1596, +1359, 2162, 568, 1899, -339, 1014, -954, -84, +-1244, -1097, -1160, -1737, -652, -1716, 56, -988, +744, 53, 1280, 895, 1356, 1412, 822, 1497, +45, 941, -641, -38, -1194, -911, -1336, -1377, +-851, -1385, -95, -900, 555, -38, 1003, 776, +1113, 1231, 813, 1284, 334, 884, -85, 175, +-391, -489, -563, -880, -537, -915, -347, -637, +-58, -197, 205, 228, 281, 478, 201, 440, +61, 124, -164, -226, -360, -366, -284, -302, +36, -39, 377, 409, 679, 821, 853, 916, +613, 601, 23, 21, -527, -664, -896, -1255, +-1036, -1416, -811, -1064, -332, -427, 154, 367, +572, 1154, 810, 1572, 724, 1412, 439, 838, +174, 94, -94, -634, -344, -1093, -386, -1182, +-282, -951, -224, -418, -214, 173, -233, 482, +-288, 522, -227, 411, 42, 165, 314, -61, +407, -65, 413, 103, 330, 340, 68, 598, +-229, 599, -407, 163, -462, -466, -374, -1008, +-134, -1270, 121, -1130, 257, -628, 289, 180, +254, 1045, 82, 1506, -214, 1415, -504, 991, +-609, 365, -371, -425, 65, -1078, 407, -1326, +576, -1250, 594, -820, 425, -82, 132, 543, +-188, 908, -509, 1032, -763, 781, -794, 311, +-558, -140, -154, -530, 327, -658, 789, -399, +1041, -93, 877, 19, 320, 156, -333, 293, +-776, 169, -860, -9, -602, -41, -214, -68, +126, -38, 396, 59, 527, 40, 475, -36, +320, -136, 126, -332, -120, -334, -338, -3, +-415, 284, -370, 457, -192, 730, 171, 797, +465, 371, 481, -261, 374, -818, 177, -1181, +-95, -1243, -203, -982, -166, -361, -195, 585, +-180, 1441, -62, 1765, -48, 1598, -92, 1052, +33, 31, 245, -1110, 401, -1793, 502, -1916, +432, -1537, 144, -712, -164, 335, -339, 1260, +-379, 1713, -335, 1660, -263, 1238, -145, 448, +42, -508, 187, -1248, 237, -1590, 308, -1469, +359, -884, 256, -52, 125, 702, 23, 1264, +-143, 1535, -220, 1255, -163, 527, -180, -271, +-239, -988, -236, -1414, -198, -1389, -86, -1060, +70, -437, 163, 444, 262, 1183, 430, 1527, +467, 1581, 284, 1267, 82, 450, -107, -572, +-404, -1467, -687, -2070, -765, -2062, -576, -1349, +-177, -221, 198, 1061, 458, 2106, 683, 2436, +712, 1992, 403, 1029, 39, -265, -222, -1569, +-513, -2353, -682, -2400, -514, -1786, -229, -590, +-27, 842, 147, 2012, 246, 2604, 240, 2373, +167, 1324, 36, -161, -53, -1592, -18, -2542, +30, -2691, 27, -1963, 18, -600, -57, 978, +-237, 2270, -382, 2779, -406, 2404, -282, 1374, +60, -96, 465, -1588, 690, -2524, 721, -2592, +507, -1887, -24, -754, -637, 508, -1062, 1638, +-1165, 2286, -841, 2195, -191, 1435, 523, 374, +1159, -687, 1576, -1550, 1497, -1896, 900, -1618, +42, -873, -951, 119, -1814, 933, -2084, 1277, +-1699, 1192, -870, 723, 301, -9, 1508, -647, +2282, -883, 2379, -705, 1854, -265, 848, 339, +-425, 861, -1582, 969, -2259, 609, -2402, -88, +-2052, -845, -1082, -1306, 390, -1335, 1759, -880, +2549, 22, 2693, 1027, 2138, 1720, 972, 1841, +-390, 1315, -1595, 324, -2406, -770, -2519, -1683, +-1905, -2183, -889, -1933, 296, -927, 1466, 314, +2261, 1357, 2448, 2079, 2001, 2241, 909, 1652, +-477, 577, -1592, -604, -2204, -1690, -2177, -2314, +-1445, -2197, -330, -1497, 804, -378, 1677, 955, +1913, 1970, 1437, 2301, 579, 1985, -318, 1115, +-1031, -120, -1333, -1164, -1124, -1605, -521, -1603, +279, -1244, 920, -526, 1019, 138, 676, 508, +157, 679, -598, 636, -1335, 438, -1425, 257, +-805, 159, 111, 194, 1133, 347, 1998, 461, +2132, 374, 1328, 108, -21, -291, -1425, -878, +-2501, -1424, -2839, -1585, -2221, -1279, -868, -507, +763, 549, 2218, 1522, 2984, 2211, 2796, 2398, +1850, 1814, 395, 601, -1293, -753, -2590, -1869, +-2937, -2488, -2362, -2369, -1238, -1599, 100, -500, +1324, 698, 2023, 1660, 2023, 2009, 1463, 1726, +536, 1031, -419, 157, -1023, -640, -1188, -1112, +-956, -1137, -395, -731, 229, -58, 564, 471, +449, 600, 48, 420, -374, -30, -627, -592, +-594, -863, -296, -734, 166, -355, 661, 222, +1004, 845, 1093, 1157, 918, 1040, 398, 703, +-388, 242, -1063, -267, -1358, -629, -1316, -824, +-896, -865, -92, -731, 667, -541, 1028, -321, +1088, -30, 944, 223, 581, 433, 142, 744, +-263, 1046, -626, 1026, -777, 730, -586, 347, +-255, -225, 76, -886, 423, -1291, 554, -1357, +343, -1055, 91, -384, -47, 404, -208, 999, +-341, 1229, -334, 1071, -263, 549, -146, -185, +185, -821, 650, -1102, 936, -863, 929, -146, +580, 692, -83, 1300, -739, 1433, -1122, 965, +-1212, 3, -976, -1176, -455, -2091, 166, -2273, +721, -1649, 1136, -453, 1308, 949, 1127, 2130, +645, 2727, -45, 2545, -815, 1606, -1305, 141, +-1252, -1397, -823, -2445, -251, -2719, 339, -2272, +752, -1253, 824, 105, 621, 1383, 281, 2133, +-112, 2159, -451, 1577, -619, 687, -528, -239, +-209, -1020, 184, -1418, 501, -1304, 634, -848, +520, -251, 214, 337, -169, 728, -498, 762, +-677, 497, -711, 197, -621, -54, -444, -274, +-171, -350, 240, -316, 656, -267, 886, -181, +951, -71, 870, 106, 590, 391, 92, 667, +-550, 807, -1114, 685, -1500, 248, -1671, -415, +-1351, -1080, -447, -1454, 630, -1436, 1492, -1016, +2026, -180, 2078, 839, 1447, 1695, 333, 2128, +-807, 1960, -1733, 1210, -2200, 97, -1958, -1118, +-1167, -2122, -138, -2587, 965, -2330, 1772, -1433, +1873, -115, 1348, 1335, 534, 2445, -357, 2840, +-1027, 2472, -1216, 1466, -948, 67, -400, -1349, +160, -2368, 520, -2724, 602, -2396, 377, -1549, +-80, -390, -458, 893, -476, 1975, -153, 2539, +311, 2562, 738, 2046, 930, 952, 764, -445, +310, -1672, -347, -2448, -1006, -2742, -1318, -2482, +-1215, -1572, -826, -240, -115, 1105, 784, 2225, +1529, 2995, 1878, 3192, 1645, 2524, 831, 1062, +-221, -695, -1127, -2360, -1719, -3613, -1845, -3949, +-1374, -3088, -553, -1312, 219, 802, 846, 2727, +1306, 3943, 1489, 3991, 1343, 2849, 896, 970, +310, -1025, -262, -2626, -788, -3483, -1180, -3333, +-1294, -2216, -1189, -584, -968, 997, -503, 2091, +224, 2541, 956, 2334, 1554, 1520, 1858, 394, +1573, -653, 782, -1344, -141, -1557, -1060, -1395, +-1853, -966, -2109, -365, -1679, 151, -810, 460, +299, 678, 1395, 830, 2038, 809, 2033, 642, +1414, 473, 272, 238, -1006, -159, -1932, -575, +-2202, -941, -1698, -1207, -595, -1130, 669, -687, +1690, -89, 2167, 649, 1930, 1433, 1011, 1831, +-334, 1615, -1643, 963, -2446, 38, -2384, -1008, +-1475, -1837, -133, -2118, 1225, -1736, 2242, -906, +2538, 32, 1954, 958, 684, 1737, -701, 1982, +-1659, 1554, -2126, 876, -2118, 262, -1447, -413, +-203, -1048, 1005, -1337, 1662, -1302, 1757, -1105, +1420, -843, 644, -525, -395, -83, -1162, 445, +-1311, 974, -1003, 1434, -437, 1699, 292, 1675, +823, 1273, 831, 449, 460, -709, 43, -1903, +-354, -2639, -691, -2667, -699, -2081, -333, -906, +128, 704, 547, 2215, 814, 3065, 734, 3042, +416, 2317, 73, 1046, -306, -632, -652, -2160, +-743, -2937, -527, -2901, -195, -2253, 108, -1076, +369, 466, 463, 1899, 348, 2664, 246, 2514, +180, 1734, 51, 762, 2, -320, 89, -1413, +109, -1989, -28, -1794, -207, -1257, -355, -726, +-414, -88, -301, 590, -135, 1019, 10, 1227, +303, 1315, 623, 1199, 641, 890, 449, 359, +283, -427, 25, -1218, -377, -1792, -671, -2090, +-747, -1900, -614, -1068, -251, 181, 190, 1505, +551, 2611, 807, 3077, 808, 2653, 520, 1546, +144, -62, -231, -1925, -635, -3351, -904, -3768, +-871, -3202, -620, -1856, -255, 106, 234, 2207, +779, 3666, 1180, 3988, 1261, 3200, 909, 1648, +243, -240, -512, -2044, -1192, -3201, -1590, -3279, +-1529, -2456, -1050, -1223, -282, 100, 603, 1260, +1359, 1930, 1809, 1910, 1796, 1423, 1247, 880, +293, 402, -799, -55, -1763, -374, -2293, -437, +-2075, -433, -1136, -629, 125, -939, 1295, -1097, +2006, -1002, 2042, -690, 1505, -208, 515, 467, +-680, 1228, -1590, 1736, -1872, 1793, -1576, 1422, +-867, 668, 115, -308, 1065, -1214, 1662, -1793, +1717, -1905, 1111, -1523, 29, -758, -968, 94, +-1493, 811, -1587, 1310, -1315, 1413, -590, 1087, +377, 674, 1137, 372, 1539, 39, 1602, -318, +1273, -550, 604, -707, -221, -847, -1013, -935, +-1590, -964, -1826, -783, -1653, -244, -1040, 474, +-82, 1099, 953, 1568, 1761, 1820, 2189, 1586, +2158, 799, 1524, -233, 342, -1316, -938, -2235, +-1870, -2574, -2274, -2161, -2143, -1125, -1493, 310, +-446, 1738, 679, 2731, 1616, 2973, 2134, 2315, +2027, 941, 1414, -662, 569, -1969, -362, -2655, +-1207, -2631, -1678, -1934, -1585, -739, -1080, 590, +-380, 1626, 345, 2103, 859, 2018, 999, 1459, +814, 549, 479, -466, 148, -1238, -60, -1448, +-73, -1094, 33, -512, 109, 29, 67, 440, +-197, 570, -600, 253, -856, -327, -813, -698, +-519, -651, -78, -294, 465, 298, 1052, 1024, +1457, 1616, 1392, 1778, 876, 1335, 106, 334, +-807, -890, -1654, -1978, -2043, -2740, -1757, -2893, +-913, -2122, 208, -614, 1259, 1081, 1915, 2565, +1989, 3510, 1489, 3547, 630, 2606, -255, 1018, +-1046, -817, -1634, -2506, -1734, -3550, -1317, -3659, +-635, -2887, 98, -1476, 715, 201, 991, 1806, +849, 3053, 525, 3495, 268, 2934, 182, 1742, +315, 331, 475, -1124, 422, -2273, 85, -2669, +-514, -2286, -1189, -1459, -1659, -479, -1749, 436, +-1435, 1042, -692, 1225, 516, 1138, 1873, 928, +2781, 581, 2915, 246, 2306, 115, 990, 89, +-859, 40, -2597, -71, -3516, -282, -3418, -510, +-2440, -706, -817, -952, 1005, -1131, 2495, -975, +3302, -445, 3216, 251, 2188, 982, 603, 1657, +-962, 2013, -2140, 1886, -2633, 1305, -2276, 299, +-1340, -902, -292, -1882, 634, -2418, 1266, -2405, +1463, -1843, 1302, -936, 847, 181, 194, 1420, +-355, 2346, -610, 2614, -624, 2381, -432, 1731, +-43, 575, 301, -765, 326, -1781, 147, -2349, +-32, -2485, -230, -2072, -390, -1235, -412, -360, +-343, 478, -295, 1376, -135, 2139, 366, 2495, +989, 2367, 1351, 1809, 1357, 868, 1017, -445, +270, -1867, -760, -2815, -1729, -3054, -2315, -2804, +-2335, -2033, -1675, -617, -407, 991, 1189, 2274, +2696, 3232, 3582, 3671, 3454, 3134, 2226, 1769, +177, 119, -2050, -1579, -3672, -3131, -4248, -4010, +-3669, -3790, -2002, -2648, 270, -1047, 2403, 693, +3837, 2264, 4246, 3321, 3476, 3618, 1775, 3107, +-352, 1991, -2354, 615, -3626, -814, -3757, -2147, +-2903, -3072, -1410, -3321, 385, -2925, 1902, -2002, +2666, -606, 2663, 985, 2066, 2291, 1001, 3067, +-208, 3273, -1080, 2744, -1415, 1521, -1299, 43, +-986, -1349, -762, -2484, -634, -3052, -485, -2838, +-257, -1934, 143, -612, 711, 764, 1306, 1854, +1677, 2394, 1537, 2271, 876, 1579, -73, 549, +-1052, -510, -1840, -1286, -2192, -1607, -1889, -1392, +-976, -761, 221, -40, 1369, 641, 2216, 1166, +2436, 1150, 1813, 552, 526, -115, -918, -618, +-2032, -1076, -2546, -1314, -2337, -1040, -1390, -327, +-9, 450, 1358, 1056, 2411, 1564, 2835, 1924, +2358, 1759, 1140, 987, -319, -17, -1679, -1027, +-2721, -2030, -3080, -2720, -2548, -2701, -1311, -2033, +200, -912, 1638, 567, 2807, 2057, 3380, 3151, +3036, 3658, 1869, 3301, 347, 2040, -1202, 344, +-2598, -1407, -3412, -3038, -3349, -4085, -2604, -4129, +-1313, -3220, 401, -1611, 2121, 415, 3374, 2429, +3827, 3946, 3430, 4550, 2230, 4036, 383, 2588, +-1586, 579, -2974, -1575, -3509, -3293, -3337, -4103, +-2525, -3955, -1084, -2974, 598, -1339, 1916, 526, +2656, 2110, 2944, 3120, 2744, 3429, 1836, 2956, +502, 1796, -605, 266, -1333, -1221, -1955, -2285, +-2340, -2728, -2185, -2555, -1657, -1789, -948, -570, +-40, 684, 959, 1631, 1823, 2131, 2408, 2040, +2575, 1399, 2203, 465, 1340, -569, 165, -1419, +-1138, -1774, -2346, -1648, -3150, -1142, -3228, -316, +-2460, 580, -1125, 1264, 483, 1623, 2181, 1597, +3501, 1181, 3849, 480, 3172, -343, 1878, -1107, +118, -1646, -1928, -1866, -3576, -1736, -4302, -1202, +-3976, -307, -2594, 674, -484, 1514, 1739, 2145, +3512, 2346, 4404, 1928, 4172, 1071, 2869, 43, +831, -1001, -1462, -1876, -3361, -2402, -4262, -2440, +-4074, -1948, -2980, -1078, -1164, -31, 954, 992, +2674, 1806, 3545, 2341, 3529, 2447, 2753, 2008, +1358, 1285, -344, 499, -1772, -452, -2542, -1458, +-2699, -2205, -2316, -2642, -1456, -2711, -419, -2164, +493, -1049, 1151, 266, 1514, 1572, 1597, 2743, +1457, 3378, 1107, 3139, 590, 2206, 72, 928, +-385, -537, -817, -1946, -1148, -2867, -1339, -3080, +-1419, -2699, -1301, -1840, -803, -584, -30, 764, +765, 1801, 1505, 2394, 2015, 2571, 2032, 2249, +1545, 1423, 656, 383, -460, -546, -1451, -1271, +-2097, -1785, -2258, -1930, -1835, -1635, -878, -1150, +280, -641, 1300, 84, 2025, 1002, 2232, 1653, +1797, 1821, 962, 1648, 19, 1164, -978, 342, +-1812, -699, -2109, -1662, -1766, -2049, -1044, -1673, +-103, -890, 988, 97, 1912, 1306, 2231, 2265, +1881, 2323, 1161, 1458, 215, 111, -892, -1325, +-1840, -2472, -2225, -2866, -2038, -2272, -1471, -890, +-493, 806, 779, 2206, 1861, 2880, 2389, 2774, +2310, 1929, 1673, 542, 663, -853, -405, -1861, +-1329, -2368, -1944, -2276, -2017, -1656, -1615, -781, +-1051, 85, -429, 704, 282, 1019, 966, 1139, +1359, 1115, 1405, 1040, 1341, 1026, 1271, 988, +1084, 816, 664, 459, 47, -231, -722, -1237, +-1615, -2190, -2384, -2743, -2694, -2777, -2435, -2143, +-1578, -753, -150, 1037, 1567, 2709, 3042, 3885, +3803, 4162, 3742, 3288, 2846, 1512, 1112, -680, +-1101, -2747, -3107, -4106, -4375, -4437, -4655, -3694, +-3805, -2001, -1919, 112, 451, 1954, 2549, 3184, +3966, 3643, 4533, 3247, 3966, 2212, 2326, 878, +248, -531, -1646, -1739, -3042, -2451, -3700, -2609, +-3433, -2346, -2380, -1724, -995, -763, 330, 347, +1435, 1286, 2191, 1884, 2449, 2179, 2233, 2123, +1760, 1591, 1037, 704, 63, -243, -907, -1106, +-1647, -1809, -2126, -2104, -2292, -1810, -1964, -1143, +-1171, -396, -157, 412, 918, 1170, 1895, 1561, +2445, 1522, 2399, 1235, 1826, 797, 878, 306, +-364, -80, -1613, -346, -2308, -598, -2281, -894, +-1791, -1163, -1043, -1292, -41, -1194, 1026, -848, +1680, -264, 1677, 563, 1349, 1478, 1017, 2056, +582, 2119, 35, 1837, -402, 1150, -686, 16, +-879, -1174, -951, -2091, -955, -2635, -907, -2600, +-686, -1885, -266, -707, 213, 617, 677, 1807, +1117, 2583, 1496, 2722, 1733, 2243, 1547, 1327, +791, 170, -190, -928, -1082, -1665, -1836, -2020, +-2224, -2023, -1972, -1616, -1271, -936, -435, -272, +527, 234, 1435, 654, 1907, 1083, 1992, 1433, +1846, 1585, 1329, 1562, 436, 1303, -539, 712, +-1280, -154, -1707, -1118, -1841, -1913, -1699, -2245, +-1229, -2092, -448, -1545, 355, -578, 990, 567, +1484, 1407, 1731, 1779, 1577, 1836, 1106, 1608, +452, 1049, -290, 316, -950, -324, -1338, -754, +-1414, -1044, -1239, -1292, -823, -1382, -207, -1127, +420, -648, 786, -192, 831, 221, 703, 628, +434, 904, 33, 960, -282, 843, -319, 654, +-166, 462, 67, 238, 325, -70, 511, -351, +550, -502, 285, -639, -346, -788, -1070, -804, +-1526, -709, -1584, -626, -1217, -478, -443, -129, +627, 396, 1675, 955, 2335, 1452, 2332, 1812, +1678, 1819, 674, 1236, -523, 148, -1726, -1080, +-2522, -2146, -2624, -2814, -2153, -2798, -1256, -1963, +-25, -577, 1198, 918, 2045, 2272, 2489, 3217, +2480, 3299, 1864, 2448, 790, 1040, -401, -619, +-1422, -2182, -2163, -3158, -2504, -3305, -2293, -2585, +-1544, -1074, -487, 731, 639, 2082, 1685, 2662, +2411, 2615, 2561, 1979, 2135, 760, 1295, -546, +114, -1369, -1188, -1578, -2126, -1315, -2416, -803, +-2206, -249, -1657, 237, -699, 426, 516, 154, +1477, -263, 1903, -419, 1933, -291, 1638, 60, +1061, 690, 423, 1439, -167, 1889, -674, 1729, +-1023, 984, -1218, -160, -1350, -1473, -1398, -2575, +-1242, -3065, -834, -2727, -146, -1588, 736, 54, +1555, 1744, 2169, 3057, 2468, 3626, 2188, 3257, +1331, 2054, 163, 360, -1167, -1388, -2443, -2777, +-3112, -3437, -2863, -3141, -2002, -2001, -804, -448, +634, 995, 1962, 1910, 2726, 2175, 2761, 1850, +2153, 1068, 1097, 163, -116, -433, -1184, -609, +-1798, -502, -1739, -169, -1177, 209, -538, 302, +-8, 103, 357, -249, 385, -794, 96, -1330, +-232, -1452, -369, -1122, -317, -494, -106, 378, +338, 1295, 995, 1926, 1523, 2103, 1604, 1791, +1282, 1045, 617, 57, -366, -932, -1476, -1710, +-2327, -2071, -2610, -1956, -2279, -1463, -1488, -711, +-387, 134, 849, 801, 1950, 1125, 2589, 1166, +2658, 1018, 2281, 771, 1439, 523, 242, 311, +-937, 190, -1786, 161, -2272, 21, -2396, -299, +-2070, -667, -1338, -1012, -446, -1232, 357, -1239, +990, -1060, 1475, -623, 1781, 95, 1799, 774, +1510, 1177, 969, 1411, 297, 1527, -381, 1372, +-969, 937, -1389, 382, -1546, -203, -1348, -767, +-910, -1198, -494, -1455, -168, -1572, 136, -1488, +381, -1161, 550, -631, 748, 48, 991, 778, +1142, 1443, 1080, 1994, 870, 2255, 610, 2040, +188, 1427, -473, 559, -1129, -446, -1522, -1433, +-1690, -2224, -1682, -2604, -1329, -2416, -494, -1727, +506, -747, 1245, 315, 1666, 1280, 1863, 1960, +1750, 2224, 1230, 2079, 583, 1638, 63, 1042, +-435, 389, -954, -277, -1334, -882, -1505, -1347, +-1503, -1662, -1321, -1774, -879, -1652, -193, -1351, +555, -872, 1189, -179, 1594, 647, 1726, 1444, +1582, 2102, 1168, 2508, 519, 2525, -209, 2043, +-793, 1036, -1173, -298, -1361, -1604, -1276, -2669, +-906, -3315, -448, -3221, -136, -2348, -16, -1074, +34, 347, 163, 1793, 418, 2871, 766, 3264, +1152, 3033, 1519, 2258, 1608, 973, 1142, -525, +273, -1801, -617, -2618, -1423, -2910, -2131, -2562, +-2431, -1603, -2087, -407, -1190, 684, -37, 1491, +1118, 1869, 1994, 1820, 2320, 1430, 1994, 773, +1128, 75, 124, -425, -602, -744, -972, -927, +-1032, -867, -754, -556, -325, -235, -18, -44, +-2, 82, -242, 103, -540, -67, -745, -282, +-801, -356, -627, -266, -140, -18, 555, 397, +1251, 868, 1761, 1139, 1880, 1004, 1486, 560, +753, 33, -88, -547, -1012, -1107, -1870, -1361, +-2237, -1243, -2027, -916, -1608, -414, -1040, 241, +-143, 840, 839, 1195, 1514, 1258, 1877, 984, +2076, 413, 2005, -170, 1513, -567, 687, -811, +-237, -799, -1118, -439, -1878, -4, -2315, 214, +-2254, 245, -1758, 178, -1019, 19, -96, -183, +899, -338, 1649, -361, 1961, -143, 1959, 247, +1731, 569, 1191, 728, 360, 758, -421, 577, +-850, 137, -1106, -360, -1374, -683, -1481, -783, +-1291, -694, -957, -429, -616, -121, -177, 72, +458, 156, 1160, 207, 1661, 284, 1795, 427, +1626, 603, 1228, 687, 555, 643, -293, 486, +-1058, 120, -1575, -448, -1762, -955, -1627, -1219, +-1243, -1246, -622, -1017, 191, -456, 904, 373, +1277, 1200, 1435, 1769, 1400, 1916, 1013, 1551, +425, 721, -30, -370, -382, -1409, -722, -2075, +-898, -2193, -858, -1717, -721, -746, -504, 408, +-187, 1423, 159, 2084, 474, 2222, 642, 1777, +587, 870, 397, -268, 184, -1336, -85, -2023, +-331, -2112, -395, -1646, -286, -866, -103, 42, +116, 934, 407, 1531, 669, 1639, 706, 1391, +437, 967, -74, 420, -685, -162, -1165, -644, +-1379, -972, -1264, -1163, -764, -1244, 27, -1166, +850, -847, 1448, -304, 1737, 330, 1668, 903, +1188, 1356, 404, 1597, -447, 1465, -1181, 970, +-1669, 280, -1811, -492, -1559, -1227, -946, -1718, +-158, -1808, 531, -1499, 979, -846, 1204, 57, +1183, 916, 932, 1437, 617, 1550, 332, 1289, +64, 735, -139, 118, -280, -333, -502, -579, +-797, -667, -1004, -635, -1110, -554, -1071, -494, +-738, -451, -176, -404, 415, -266, 1043, 45, +1625, 425, 1819, 726, 1517, 930, 924, 972, +139, 728, -811, 221, -1657, -388, -1998, -928, +-1749, -1239, -1146, -1185, -336, -748, 535, -9, +1159, 812, 1384, 1391, 1294, 1478, 957, 1010, +406, 136, -182, -831, -620, -1561, -842, -1791, +-785, -1371, -457, -384, -16, 798, 350, 1714, +499, 2107, 414, 1890, 210, 1076, -65, -67, +-347, -1129, -458, -1848, -346, -2069, -174, -1695, +-52, -839, 110, 172, 290, 979, 393, 1395, +432, 1395, 473, 1059, 457, 569, 322, 117, +77, -199, -237, -324, -512, -247, -678, -146, +-752, -193, -717, -331, -465, -485, -28, -661, +403, -731, 686, -566, 823, -232, 802, 191, +603, 707, 293, 1149, -10, 1277, -239, 1120, +-432, 782, -536, 265, -489, -344, -362, -888, +-251, -1259, -145, -1315, -37, -1058, 37, -684, +101, -268, 170, 208, 211, 613, 277, 819, +384, 891, 370, 915, 252, 859, 163, 648, +71, 279, -81, -156, -246, -554, -381, -906, +-495, -1143, -538, -1099, -426, -771, -212, -311, +-44, 185, 71, 645, 216, 928, 344, 950, +382, 700, 398, 226, 437, -303, 383, -633, +215, -652, 80, -417, -34, -4, -278, 475, +-552, 785, -637, 697, -611, 258, -607, -336, +-497, -931, -168, -1330, 186, -1309, 376, -876, +484, -207, 619, 580, 716, 1304, 688, 1662, +588, 1562, 421, 1159, 85, 520, -379, -257, +-755, -958, -951, -1454, -1047, -1657, -1042, -1449, +-805, -919, -356, -296, 97, 320, 508, 864, +947, 1158, 1323, 1122, 1427, 910, 1193, 648, +790, 354, 287, 41, -372, -265, -1070, -515, +-1539, -655, -1669, -716, -1492, -726, -994, -608, +-234, -334, 542, -26, 1111, 213, 1426, 425, +1446, 608, 1146, 646, 621, 472, 102, 222, +-292, 54, -592, -32, -766, -41, -712, 71, +-502, 213, -308, 198, -154, -44, -76, -440, +-132, -821, -254, -1028, -266, -968, -122, -601, +149, 28, 544, 724, 956, 1245, 1204, 1459, +1217, 1334, 944, 899, 333, 276, -439, -374, +-1131, -933, -1632, -1212, -1840, -1119, -1584, -827, +-873, -500, 50, -84, 906, 342, 1492, 502, +1685, 402, 1463, 331, 946, 386, 305, 436, +-318, 486, -734, 605, -778, 655, -569, 402, +-360, -110, -235, -657, -201, -1108, -301, -1381, +-499, -1338, -601, -910, -460, -229, -112, 486, +332, 1069, 790, 1446, 1200, 1548, 1446, 1295, +1353, 690, 855, -60, 103, -706, -724, -1127, +-1488, -1295, -1956, -1205, -1892, -871, -1273, -380, +-342, 70, 563, 367, 1202, 599, 1485, 795, +1367, 842, 899, 719, 322, 542, -116, 317, +-391, -12, -559, -356, -538, -628, -357, -835, +-200, -938, -110, -863, -44, -607, -88, -169, +-238, 349, -318, 765, -292, 1029, -216, 1134, +-36, 924, 244, 387, 521, -171, 744, -577, +827, -887, 659, -1036, 310, -888, -46, -530, +-351, -145, -660, 173, -861, 411, -790, 585, +-560, 702, -395, 703, -232, 547, 89, 300, +431, 8, 603, -326, 649, -661, 652, -864, +564, -792, 370, -461, 113, -72, -110, 232, +-245, 470, -364, 607, -483, 516, -491, 251, +-402, 43, -375, -38, -358, -80, -210, -83, +-3, 18, 141, 128, 339, 109, 635, -21, +819, -187, 768, -414, 556, -615, 274, -584, +-63, -333, -424, -4, -696, 370, -753, 761, +-637, 964, -467, 871, -262, 571, -18, 153, +166, -300, 230, -641, 256, -799, 297, -777, +339, -583, 393, -309, 432, -46, 409, 186, +364, 353, 298, 397, 91, 396, -251, 433, +-565, 453, -781, 432, -925, 428, -945, 355, +-739, 73, -287, -348, 274, -754, 763, -1052, +1061, -1155, 1077, -935, 893, -380, 693, 317, +449, 905, 66, 1247, -302, 1266, -528, 937, +-739, 407, -967, -105, -1065, -487, -981, -728, +-767, -802, -411, -714, 88, -513, 637, -273, +1144, -41, 1495, 152, 1564, 298, 1337, 399, +847, 444, 113, 449, -706, 413, -1387, 300, +-1800, 99, -1858, -148, -1512, -407, -821, -612, +39, -687, 828, -527, 1354, -95, 1560, 399, +1430, 672, 965, 685, 374, 507, -86, 80, +-417, -520, -708, -933, -839, -912, -693, -580, +-399, -86, -178, 502, -109, 987, -164, 1143, +-260, 922, -291, 443, -219, -110, 5, -588, +418, -926, 884, -1066, 1090, -957, 926, -625, +590, -217, 263, 169, -120, 532, -577, 810, +-910, 899, -1011, 807, -976, 616, -840, 319, +-506, -58, -32, -398, 378, -650, 608, -859, +722, -929, 805, -750, 869, -412, 847, -1, +662, 486, 289, 883, -214, 958, -678, 742, +-995, 371, -1169, -70, -1151, -476, -849, -692, +-347, -615, 178, -253, 670, 199, 1088, 532, +1258, 683, 1055, 587, 583, 159, 2, -475, +-517, -1008, -773, -1269, -722, -1135, -456, -538, +-97, 333, 211, 1176, 356, 1779, 316, 1888, +100, 1359, -211, 432, -456, -550, -559, -1396, +-512, -1890, -255, -1813, 189, -1253, 599, -442, +808, 424, 864, 1090, 822, 1365, 588, 1318, +151, 1024, -298, 500, -654, -72, -953, -464, +-1131, -629, -1041, -631, -711, -512, -285, -344, +161, -187, 578, -59, 891, -4, 1082, -7, +1142, 66, 994, 203, 634, 265, 151, 276, +-390, 297, -876, 255, -1148, 86, -1188, -98, +-1060, -167, -757, -143, -279, -121, 253, -71, +653, 51, 862, 133, 939, 71, 871, -81, +612, -222, 246, -337, -24, -396, -136, -328, +-213, -96, -350, 221, -480, 488, -559, 613, +-602, 614, -579, 499, -467, 235, -285, -117, +-3, -433, 355, -620, 610, -617, 703, -474, +705, -325, 620, -159, 415, 53, 182, 177, +-10, 149, -195, 122, -363, 221, -459, 381, +-533, 509, -649, 569, -693, 527, -583, 353, +-408, 28, -231, -448, 35, -922, 425, -1200, +838, -1222, 1191, -956, 1411, -379, 1363, 368, +955, 1058, 243, 1504, -605, 1544, -1351, 1135, +-1803, 446, -1935, -276, -1775, -883, -1241, -1211, +-338, -1136, 664, -797, 1499, -407, 2075, -29, +2263, 259, 1906, 358, 1109, 352, 204, 355, +-593, 374, -1241, 394, -1654, 440, -1715, 437, +-1501, 286, -1146, 13, -648, -306, -10, -635, +614, -866, 1049, -848, 1270, -580, 1362, -169, +1344, 279, 1123, 680, 663, 906, 78, 849, +-485, 520, -975, 66, -1363, -334, -1503, -566, +-1298, -590, -883, -408, -437, -98, 61, 169, +625, 292, 1066, 253, 1234, 86, 1181, -115, +996, -243, 659, -263, 205, -119, -176, 183, +-365, 460, -476, 554, -641, 467, -847, 221, +-1018, -192, -1067, -625, -913, -873, -512, -826, +75, -472, 701, 86, 1226, 619, 1544, 972, +1573, 1087, 1294, 877, 731, 350, -14, -312, +-737, -842, -1299, -1097, -1603, -1083, -1568, -807, +-1215, -270, -690, 310, -115, 689, 445, 868, +916, 903, 1197, 750, 1255, 461, 1151, 178, +873, -99, 395, -399, -141, -663, -541, -870, +-848, -988, -1126, -867, -1207, -494, -950, 3, +-493, 550, 1, 1038, 520, 1287, 943, 1204, +1057, 812, 838, 189, 439, -464, -20, -957, +-418, -1216, -614, -1192, -554, -808, -297, -201, +61, 359, 402, 754, 576, 901, 479, 717, +129, 305, -356, -144, -797, -493, -983, -559, +-800, -288, -331, 156, 260, 560, 806, 742, +1107, 581, 1058, 127, 725, -457, 221, -1025, +-339, -1340, -766, -1150, -883, -523, -691, 227, +-327, 949, 57, 1502, 339, 1603, 433, 1165, +304, 391, 8, -473, -297, -1176, -450, -1488, +-388, -1318, -146, -772, 223, -71, 620, 599, +888, 1018, 926, 1018, 677, 669, 129, 187, +-527, -290, -1003, -641, -1180, -698, -1080, -433, +-733, -32, -217, 326, 310, 588, 700, 659, +901, 479, 943, 126, 843, -259, 548, -571, +107, -742, -260, -731, -433, -516, -521, -178, +-592, 166, -544, 489, -387, 712, -251, 756, +-151, 668, -8, 535, 182, 319, 380, -3, +537, -341, 575, -627, 431, -905, 166, -1115, +-70, -1043, -228, -645, -325, -37, -308, 667, +-171, 1321, -19, 1673, 89, 1544, 89, 964, +-76, 129, -275, -747, -332, -1451, -267, -1771, +-159, -1578, 57, -890, 372, 26, 558, 855, +504, 1412, 374, 1554, 237, 1173, -14, 401, +-337, -457, -515, -1089, -457, -1287, -271, -982, +-59, -293, 170, 490, 338, 1075, 249, 1252, +-102, 928, -450, 194, -620, -649, -589, -1275, +-297, -1462, 246, -1168, 834, -495, 1250, 375, +1367, 1170, 1093, 1616, 450, 1583, -400, 1103, +-1279, 288, -1950, -628, -2081, -1324, -1569, -1605, +-659, -1480, 356, -964, 1281, -166, 1897, 583, +2027, 1055, 1678, 1234, 988, 1112, 140, 716, +-666, 212, -1232, -248, -1476, -565, -1443, -707, +-1172, -714, -689, -631, -150, -435, 279, -145, +606, 139, 875, 380, 1024, 573, 1006, 653, +862, 552, 602, 276, 214, -103, -232, -416, +-629, -584, -919, -633, -1095, -513, -1083, -177, +-782, 243, -242, 558, 332, 687, 760, 618, +976, 368, 954, -36, 686, -495, 285, -839, +-78, -884, -318, -604, -435, -153, -457, 342, +-391, 767, -233, 917, -36, 725, 88, 379, +104, 10, 42, -358, -65, -619, -98, -613, +26, -418, 205, -232, 304, -70, 298, 103, +170, 184, -57, 130, -259, 36, -328, -1, +-254, 73, -85, 248, 128, 479, 292, 638, +358, 571, 330, 241, 167, -269, -150, -832, +-485, -1223, -685, -1257, -687, -905, -434, -228, +44, 595, 563, 1288, 912, 1582, 994, 1397, +780, 853, 294, 126, -320, -646, -793, -1230, +-987, -1393, -967, -1130, -721, -653, -190, -121, +447, 421, 863, 821, 948, 928, 801, 767, +449, 479, -101, 199, -627, -11, -839, -222, +-722, -414, -464, -455, -151, -396, 227, -395, +570, -398, 702, -229, 602, 76, 374, 355, +64, 545, -282, 652, -540, 613, -622, 385, +-505, -9, -272, -444, -93, -723, -3, -758, +133, -613, 324, -313, 442, 162, 499, 643, +535, 848, 445, 722, 168, 447, -174, 62, +-471, -426, -711, -787, -811, -811, -691, -558, +-416, -194, -44, 218, 408, 619, 801, 826, +947, 685, 803, 321, 447, -85, -15, -475, +-450, -771, -708, -794, -712, -490, -492, -46, +-165, 329, 157, 565, 406, 655, 502, 584, +416, 384, 176, 91, -152, -231, -461, -490, +-587, -628, -424, -676, -52, -609, 326, -331, +574, 81, 647, 440, 492, 702, 128, 847, +-241, 738, -393, 423, -354, 83, -259, -248, +-155, -553, -54, -713, -27, -715, -91, -627, +-198, -429, -307, -120, -273, 189, 9, 430, +423, 624, 797, 726, 1048, 698, 1033, 548, +639, 295, -51, -27, -824, -345, -1429, -625, +-1650, -836, -1402, -891, -770, -735, 82, -388, +921, 28, 1485, 443, 1605, 785, 1292, 918, +682, 777, -56, 478, -679, 161, -975, -121, +-924, -322, -646, -369, -292, -304, 4, -299, +131, -388, 39, -464, -158, -465, -250, -386, +-158, -162, 72, 214, 405, 629, 789, 922, +1057, 1022, 991, 898, 539, 495, -120, -100, +-751, -674, -1239, -1077, -1443, -1244, -1179, -1064, +-511, -518, 222, 189, 724, 778, 929, 1111, +861, 1092, 558, 699, 164, 92, -107, -552, +-146, -1002, 0, -966, 183, -474, 266, 120, +161, 658, -157, 1061, -582, 1066, -932, 558, +-1077, -182, -920, -827, -405, -1223, 321, -1234, +987, -827, 1413, -168, 1482, 499, 1122, 964, +436, 1098, -340, 942, -982, 570, -1312, 72, +-1229, -335, -800, -473, -239, -386, 262, -226, +582, -105, 641, -105, 453, -254, 161, -500, +-53, -719, -115, -743, -38, -410, 133, 265, +329, 1024, 423, 1583, 313, 1766, 47, 1447, +-264, 645, -562, -412, -783, -1456, -786, -2178, +-506, -2287, -59, -1722, 358, -709, 636, 467, +734, 1504, 609, 2079, 289, 2026, -24, 1423, +-134, 465, -68, -536, 27, -1186, 48, -1332, +-19, -1075, -167, -561, -410, 43, -672, 453, +-750, 464, -548, 170, -166, -175, 282, -401, +727, -432, 1053, -195, 1108, 272, 843, 772, +360, 1042, -175, 946, -650, 551, -1001, 1, +-1134, -620, -942, -1154, -481, -1332, 8, -1055, +381, -494, 670, 136, 837, 697, 751, 1017, +425, 986, 49, 662, -199, 205, -302, -221, +-314, -460, -261, -458, -178, -298, -85, -109, +0, 34, 6, 125, -87, 145, -173, 61, +-145, -114, -23, -258, 99, -265, 173, -187, +238, -119, 305, 16, 284, 246, 143, 413, +-24, 451, -125, 421, -175, 306, -231, 89, +-270, -109, -253, -275, -189, -475, -67, -606, +91, -553, 202, -394, 237, -169, 211, 127, +131, 409, 22, 634, -74, 755, -135, 649, +-132, 339, -41, -13, 66, -350, 149, -614, +213, -683, 196, -515, 30, -207, -223, 103, +-419, 288, -481, 297, -401, 207, -174, 48, +164, -141, 489, -185, 668, -1, 640, 224, +427, 389, 70, 500, -324, 447, -605, 142, +-707, -281, -638, -655, -383, -911, 55, -927, +511, -593, 772, -13, 747, 563, 479, 981, +45, 1145, -444, 980, -815, 493, -874, -169, +-592, -726, -117, -973, 397, -945, 812, -722, +967, -279, 778, 252, 354, 607, -154, 663, +-640, 507, -935, 256, -891, -2, -553, -189, +-114, -215, 270, -60, 514, 141, 564, 219, +427, 118, 188, -118, -10, -444, -56, -713, +-1, -742, 64, -469, 148, 46, 193, 662, +53, 1154, -268, 1327, -587, 1064, -773, 373, +-789, -517, -594, -1286, -154, -1660, 463, -1507, +1049, -859, 1373, 76, 1313, 1017, 874, 1620, +158, 1636, -640, 1103, -1284, 275, -1576, -590, +-1424, -1263, -870, -1469, -99, -1117, 629, -412, +1126, 353, 1288, 954, 1083, 1188, 593, 964, +0, 389, -508, -322, -787, -918, -755, -1145, +-454, -902, -69, -336, 207, 361, 307, 992, +269, 1291, 82, 1068, -207, 447, -402, -324, +-390, -1019, -227, -1391, 49, -1270, 415, -687, +731, 125, 812, 855, 601, 1278, 163, 1313, +-388, 936, -858, 249, -1063, -489, -936, -1017, +-522, -1198, 53, -1007, 590, -529, 909, 71, +939, 632, 704, 978, 294, 987, -198, 717, +-639, 314, -839, -161, -697, -600, -343, -830, +37, -796, 359, -592, 573, -303, 588, 49, +365, 404, 39, 656, -223, 735, -378, 669, +-479, 497, -482, 238, -284, -100, 66, -464, +367, -770, 490, -897, 474, -785, 350, -487, +109, -56, -171, 431, -347, 808, -371, 916, +-326, 763, -286, 462, -184, 102, 11, -279, +180, -541, 258, -555, 328, -405, 387, -259, +284, -134, 29, 10, -174, 79, -258, 2, +-328, -116, -403, -93, -346, 75, -123, 273, +96, 457, 234, 617, 380, 625, 497, 380, +427, -17, 184, -406, -88, -720, -334, -913, +-527, -874, -574, -589, -453, -185, -228, 212, +42, 570, 299, 836, 488, 908, 587, 743, +558, 451, 376, 140, 102, -193, -202, -499, +-508, -688, -704, -732, -698, -663, -528, -510, +-249, -297, 128, -27, 496, 274, 681, 571, +647, 795, 486, 864, 256, 757, -36, 454, +-300, -11, -418, -518, -412, -900, -397, -1031, +-363, -851, -215, -421, -6, 76, 112, 468, +169, 691, 284, 699, 374, 484, 316, 195, +189, -32, 119, -206, 69, -331, -65, -341, +-260, -244, -372, -118, -353, -20, -290, 58, +-226, 141, -100, 177, 104, 117, 287, 19, +352, -22, 297, -16, 209, -16, 127, -46, +17, -88, -94, -143, -121, -171, -82, -108, +-66, 34, -105, 188, -189, 326, -300, 402, +-346, 347, -238, 158, -16, -127, 243, -423, +474, -616, 610, -624, 592, -466, 389, -186, +37, 188, -343, 554, -630, 763, -781, 757, +-738, 549, -429, 173, 60, -244, 496, -568, +715, -719, 692, -672, 469, -445, 114, -129, +-216, 179, -358, 396, -318, 461, -220, 404, +-143, 293, -81, 154, -24, -4, 2, -127, +-32, -195, -88, -218, -64, -210, 74, -162, +224, -86, 315, -5, 370, 64, 333, 107, +96, 113, -276, 84, -557, 41, -638, -6, +-533, -27, -257, -15, 118, 3, 460, 32, +657, 90, 648, 120, 444, 59, 94, -58, +-335, -149, -699, -184, -813, -188, -622, -143, +-218, -8, 287, 195, 705, 328, 825, 292, +595, 128, 160, -74, -292, -286, -616, -431, +-705, -382, -534, -141, -172, 179, 231, 477, +496, 660, 519, 592, 347, 248, 83, -228, +-184, -659, -372, -923, -397, -902, -266, -569, +-67, -46, 143, 533, 319, 1000, 389, 1168, +298, 978, 105, 533, -107, -62, -340, -669, +-546, -1086, -562, -1183, -324, -985, 32, -557, +328, 23, 502, 564, 568, 910, 491, 1025, +279, 905, 22, 581, -197, 161, -386, -265, +-542, -605, -615, -794, -587, -805, -426, -660, +-84, -389, 376, -14, 746, 372, 885, 642, +797, 748, 511, 671, 68, 386, -399, 3, +-755, -341, -921, -586, -846, -651, -546, -466, +-99, -99, 391, 282, 802, 548, 980, 618, +815, 461, 334, 87, -271, -400, -750, -803, +-946, -925, -802, -704, -344, -213, 264, 424, +766, 1014, 966, 1317, 798, 1202, 332, 697, +-258, -67, -752, -849, -994, -1394, -928, -1539, +-582, -1217, -71, -524, 433, 291, 790, 979, +940, 1371, 847, 1368, 504, 972, 36, 316, +-366, -373, -620, -871, -732, -1039, -670, -888, +-418, -516, -117, -24, 85, 437, 198, 668, +260, 581, 253, 273, 221, -87, 237, -382, +260, -535, 225, -449, 163, -126, 96, 282, +-57, 601, -278, 752, -423, 681, -432, 362, +-392, -112, -344, -561, -232, -872, -55, -984, +115, -835, 246, -448, 388, 56, 516, 533, +533, 880, 451, 1026, 314, 953, 65, 672, +-285, 226, -589, -273, -755, -710, -802, -996, +-720, -1039, -443, -812, 0, -413, 475, 67, +825, 526, 957, 822, 820, 869, 427, 695, +-85, 386, -504, 37, -696, -274, -659, -497, +-426, -555, -48, -429, 308, -229, 410, -50, +243, 121, -27, 225, -282, 171, -479, 36, +-515, -25, -300, -19, 108, -5, 545, 73, +833, 204, 855, 271, 602, 201, 172, 14, +-329, -213, -782, -378, -1026, -426, -950, -345, +-585, -140, -76, 154, 396, 429, 690, 542, +749, 461, 560, 241, 190, -68, -182, -381, +-365, -567, -336, -581, -167, -437, 104, -166, +386, 188, 463, 525, 224, 711, -180, 684, +-537, 476, -765, 142, -792, -245, -528, -566, +-48, -726, 432, -685, 739, -470, 843, -165, +736, 107, 414, 302, 19, 446, -271, 512, +-417, 476, -469, 397, -419, 302, -269, 153, +-111, -42, -41, -265, -76, -513, -163, -723, +-210, -778, -131, -629, 82, -310, 337, 116, +545, 547, 680, 860, 681, 963, 470, 816, +89, 450, -307, 23, -648, -335, -909, -612, +-986, -779, -792, -752, -416, -557, 7, -296, +429, -22, 757, 243, 844, 466, 701, 569, +493, 542, 292, 453, 56, 339, -197, 154, +-390, -106, -510, -342, -597, -464, -624, -497, +-525, -466, -312, -338, -66, -119, 177, 136, +415, 327, 595, 393, 615, 379, 473, 327, +251, 190, 18, -19, -200, -196, -353, -261, +-384, -218, -307, -116, -191, 6, -114, 108, +-102, 137, -129, 48, -148, -111, -125, -230, +-38, -254, 93, -192, 230, -45, 349, 161, +433, 363, 434, 487, 296, 465, 52, 286, +-235, 2, -509, -299, -691, -553, -662, -668, +-391, -570, -1, -283, 328, 67, 494, 375, +497, 580, 350, 639, 83, 541, -181, 294, +-306, -34, -296, -324, -210, -505, -65, -586, +124, -537, 283, -331, 331, -39, 239, 232, +30, 437, -214, 550, -390, 517, -431, 338, +-338, 97, -142, -128, 71, -329, 199, -481, +227, -505, 219, -361, 199, -138, 145, 51, +69, 203, 19, 337, 12, 408, 13, 359, +-5, 210, -42, 28, -105, -119, -224, -211, +-348, -238, -386, -198, -318, -116, -188, -53, +1, -37, 217, -52, 368, -88, 440, -100, +511, -26, 566, 118, 454, 262, 159, 383, +-191, 446, -504, 394, -751, 206, -881, -72, +-842, -397, -633, -707, -283, -877, 159, -796, +623, -458, 1009, 63, 1197, 645, 1102, 1078, +737, 1207, 170, 994, -476, 492, -1018, -168, +-1302, -766, -1299, -1120, -1022, -1172, -500, -942, +150, -482, 749, 96, 1127, 592, 1199, 897, +980, 994, 535, 874, -38, 560, -553, 138, +-861, -307, -937, -675, -791, -858, -435, -819, +12, -588, 362, -220, 548, 203, 583, 528, +432, 661, 111, 624, -197, 436, -333, 142, +-327, -138, -267, -319, -147, -404, 12, -398, +96, -297, 81, -116, 81, 87, 150, 232, +175, 270, 127, 230, 91, 147, 69, 28, +-36, -95, -216, -151, -390, -150, -525, -152, +-570, -143, -445, -81, -132, 39, 303, 163, +733, 245, 1004, 278, 1005, 253, 687, 123, +109, -96, -530, -291, -1005, -373, -1226, -370, +-1175, -305, -807, -141, -185, 96, 469, 315, +953, 451, 1164, 469, 1042, 342, 634, 113, +113, -130, -357, -337, -684, -465, -798, -460, +-661, -308, -347, -70, -21, 170, 178, 361, +246, 477, 220, 462, 112, 271, -39, -51, +-123, -360, -64, -545, 95, -567, 260, -396, +340, -57, 276, 317, 95, 575, -100, 659, +-263, 576, -389, 339, -420, -12, -321, -380, +-183, -654, -59, -775, 94, -731, 261, -504, +337, -102, 288, 363, 195, 724, 120, 901, +51, 879, -27, 632, -82, 207, -110, -248, +-154, -603, -249, -821, -336, -857, -321, -675, +-189, -357, 2, -22, 203, 291, 361, 550, +388, 689, 295, 682, 132, 531, -70, 277, +-254, -14, -327, -275, -263, -458, -137, -513, +-29, -423, 67, -264, 166, -127, 193, -41, +80, 14, -95, 50, -190, 101, -219, 203, +-235, 333, -154, 415, 71, 384, 284, 233, +353, 19, 307, -191, 175, -363, -41, -467, +-271, -449, -420, -304, -440, -117, -305, 57, +-67, 222, 151, 345, 265, 361, 303, 281, +270, 155, 119, 0, -99, -163, -267, -275, +-318, -282, -264, -194, -113, -45, 109, 131, +313, 285, 373, 352, 268, 283, 44, 67, +-243, -230, -486, -487, -543, -602, -392, -540, +-125, -302, 182, 98, 435, 549, 540, 848, +473, 881, 267, 674, -30, 280, -347, -215, +-584, -659, -640, -910, -469, -904, -132, -667, +268, -295, 616, 82, 749, 394, 541, 624, +87, 738, -362, 700, -655, 516, -758, 223, +-626, -109, -257, -390, 200, -560, 558, -608, +739, -526, 742, -312, 542, -60, 134, 108, +-364, 173, -741, 209, -871, 258, -757, 315, +-437, 371, 38, 391, 493, 313, 731, 121, +705, -146, 485, -426, 150, -632, -217, -673, +-485, -517, -567, -205, -443, 170, -157, 472, +158, 605, 371, 575, 449, 425, 357, 187, +60, -56, -316, -232, -557, -354, -589, -416, +-459, -380, -168, -262, 235, -131, 590, 24, +761, 214, 720, 367, 488, 413, 91, 345, +-382, 202, -774, 14, -940, -197, -827, -385, +-495, -450, -45, -365, 403, -198, 694, 24, +747, 294, 585, 490, 278, 490, -59, 327, +-293, 94, -395, -173, -414, -417, -328, -536, +-144, -476, 45, -259, 170, 31, 205, 308, +115, 512, -70, 564, -237, 387, -314, 51, +-295, -266, -153, -456, 103, -496, 359, -348, +505, -34, 495, 282, 355, 441, 128, 396, +-151, 179, -453, -130, -697, -398, -764, -503, +-598, -391, -254, -102, 131, 258, 436, 568, +585, 700, 565, 570, 425, 205, 244, -255, +48, -669, -163, -899, -322, -829, -356, -465, +-298, 46, -224, 549, -152, 909, -89, 984, +-77, 733, -117, 248, -126, -306, -29, -741, +175, -900, 396, -777, 511, -444, 439, 21, +204, 471, -68, 712, -282, 670, -444, 434, +-550, 114, -506, -195, -304, -404, -66, -476, +151, -394, 380, -176, 537, 60, 484, 201, +232, 264, -66, 289, -289, 217, -416, 56, +-441, -63, -344, -94, -103, -108, 200, -129, +422, -123, 482, -117, 396, -127, 185, -110, +-123, -44, -426, 64, -579, 208, -528, 339, +-332, 373, -97, 284, 99, 99, 264, -143, +403, -376, 481, -501, 476, -480, 398, -316, +224, -22, -67, 310, -382, 525, -597, 531, +-702, 345, -727, 33, -570, -291, -194, -483, +236, -445, 577, -187, 835, 183, 943, 485, +777, 571, 358, 406, -151, 40, -599, -402, +-899, -730, -995, -807, -860, -618, -487, -209, +20, 311, 506, 766, 842, 1004, 957, 961, +814, 640, 429, 134, -99, -413, -599, -871, +-873, -1107, -839, -1020, -598, -662, -251, -178, +180, 344, 540, 790, 647, 1005, 530, 936, +314, 645, 27, 214, -275, -245, -412, -593, +-316, -751, -141, -709, -32, -493, -7, -192, +-60, 84, -161, 293, -240, 397, -210, 367, +-35, 263, 226, 171, 441, 97, 538, 26, +530, -24, 385, -69, 70, -137, -345, -200, +-741, -236, -1009, -243, -1010, -183, -682, -47, +-123, 102, 472, 206, 930, 248, 1132, 226, +1034, 156, 678, 71, 168, -11, -354, -72, +-756, -99, -953, -120, -954, -168, -771, -207, +-424, -196, 12, -131, 417, -35, 661, 96, +703, 261, 624, 403, 486, 439, 249, 324, +-44, 89, -255, -187, -369, -424, -494, -575, +-587, -582, -516, -400, -304, -85, -78, 237, +133, 488, 363, 626, 540, 595, 560, 416, +417, 173, 186, -99, -90, -379, -360, -575, +-507, -642, -453, -584, -284, -371, -95, -29, +109, 309, 279, 562, 321, 714, 237, 694, +123, 451, 2, 72, -147, -303, -282, -575, +-295, -661, -176, -547, -19, -306, 117, -17, +217, 246, 236, 400, 146, 411, 26, 315, +-47, 154, -80, -4, -101, -110, -96, -166, +-86, -184, -102, -147, -121, -69, -107, 7, +-63, 58, -4, 83, 57, 72, 104, 25, +140, -29, 164, -70, 165, -79, 140, -66, +62, -31, -81, 41, -217, 128, -297, 168, +-327, 151, -290, 100, -155, -3, 23, -135, +160, -213, 262, -198, 325, -138, 295, -61, +168, 19, 12, 84, -150, 125, -286, 146, +-322, 141, -241, 110, -108, 57, 14, -7, +95, -70, 111, -132, 84, -174, 40, -165, +-16, -96, -61, -12, -56, 42, -22, 77, +15, 123, 66, 157, 90, 137, 38, 83, +-30, 31, -59, -25, -98, -88, -143, -132, +-135, -169, -75, -204, -25, -191, -4, -100, +9, 26, 43, 160, 110, 299, 153, 395, +127, 382, 56, 230, -22, -25, -96, -308, +-151, -521, -179, -598, -168, -514, -111, -270, +-19, 90, 51, 446, 107, 685, 175, 729, +180, 542, 77, 181, -54, -213, -122, -520, +-137, -677, -113, -634, -54, -406, 19, -77, +74, 243, 80, 455, 19, 504, -45, 403, +-55, 197, -60, -45, -91, -221, -92, -263, +-13, -193, 96, -66, 170, 64, 183, 111, +141, 60, 51, -20, -80, -85, -212, -119, +-290, -84, -273, 0, -175, 43, -36, 19, +110, -15, 239, -7, 308, 40, 293, 126, +183, 227, 11, 300, -139, 286, -200, 137, +-201, -126, -197, -403, -171, -588, -107, -626, +-43, -483, -22, -171, -2, 229, 67, 578, +164, 752, 238, 702, 278, 479, 288, 163, +226, -167, 51, -402, -200, -482, -439, -455, +-604, -401, -601, -325, -380, -226, -29, -105, +293, 58, 516, 260, 613, 453, 544, 593, +325, 618, 55, 457, -197, 147, -417, -193, +-523, -466, -467, -598, -324, -537, -167, -335, +33, -97, 249, 92, 351, 157, 300, 84, +201, -7, 101, 0, -40, 88, -164, 239, +-175, 446, -96, 580, -19, 490, 42, 197, +82, -190, 58, -573, -36, -847, -136, -900, +-198, -688, -235, -258, -243, 249, -182, 639, +-5, 811, 254, 774, 502, 567, 640, 225, +568, -121, 243, -333, -229, -410, -658, -428, +-906, -400, -887, -305, -537, -172, 26, -35, +523, 109, 802, 252, 853, 340, 670, 321, +281, 182, -163, -6, -520, -148, -728, -184, +-729, -114, -501, 23, -119, 175, 264, 258, +515, 198, 576, -25, 454, -316, 191, -506, +-93, -487, -248, -307, -259, -22, -250, 330, +-238, 608, -123, 634, 45, 421, 111, 121, +89, -187, 113, -447, 139, -573, 51, -476, +-66, -189, -63, 125, 22, 315, 65, 380, +69, 363, 103, 215, 116, -50, 7, -256, +-193, -298, -339, -247, -354, -163, -292, -65, +-152, 17, 125, 82, 441, 166, 602, 259, +553, 339, 356, 380, 57, 293, -268, 44, +-506, -277, -592, -570, -525, -754, -347, -709, +-125, -402, 109, 56, 330, 509, 481, 825, +516, 889, 444, 690, 276, 330, 22, -78, +-247, -443, -435, -671, -474, -707, -352, -594, +-151, -386, 4, -126, 106, 147, 159, 386, +113, 541, 17, 587, 12, 519, 92, 341, +140, 73, 164, -218, 187, -436, 140, -519, +4, -469, -117, -324, -200, -115, -299, 111, +-390, 257, -363, 272, -185, 192, 45, 89, +236, 42, 398, 89, 511, 190, 441, 267, +180, 253, -103, 66, -284, -284, -365, -618, +-350, -743, -258, -612, -143, -251, -24, 247, +79, 678, 130, 859, 152, 742, 206, 397, +237, -17, 171, -317, 26, -469, -109, -528, +-201, -480, -242, -319, -192, -150, -46, -24, +112, 119, 168, 284, 130, 403, 58, 431, +-31, 362, -112, 210, -117, 34, -67, -136, +-15, -292, 44, -400, 125, -418, 181, -356, +185, -218, 144, -15, 17, 189, -191, 340, +-381, 412, -446, 377, -329, 236, -27, 62, +344, -76, 597, -150, 626, -172, 417, -190, +35, -231, -347, -264, -555, -247, -579, -169, +-460, -3, -209, 232, 104, 435, 353, 502, +506, 402, 563, 161, 457, -128, 192, -344, +-129, -420, -416, -365, -582, -221, -526, -46, +-273, 75, 27, 114, 267, 130, 414, 181, +426, 235, 295, 237, 82, 171, -133, 59, +-271, -92, -296, -267, -221, -386, -63, -354, +137, -173, 270, 50, 258, 230, 145, 330, +-19, 322, -193, 187, -279, -9, -225, -160, +-86, -204, 68, -148, 194, -40, 234, 60, +171, 99, 63, 55, -33, -53, -96, -144, +-115, -144, -85, -54, -8, 65, 79, 176, +95, 239, 10, 194, -93, 46, -138, -106, +-134, -184, -83, -201, 46, -156, 199, -45, +265, 85, 200, 157, 67, 144, -63, 61, +-143, -34, -159, -98, -123, -127, -67, -111, +-19, -22, 20, 112, 56, 195, 97, 183, +123, 100, 103, -21, 2, -158, -124, -261, +-172, -283, -105, -204, 36, -44, 187, 148, +285, 306, 244, 369, 69, 306, -141, 128, +-278, -90, -325, -271, -283, -360, -144, -330, +81, -187, 296, 8, 393, 168, 348, 245, +188, 227, -38, 130, -260, 7, -364, -77, +-302, -93, -100, -48, 165, 21, 372, 86, +383, 115, 203, 72, -39, -49, -263, -197, +-427, -298, -458, -316, -290, -242, -6, -76, +273, 167, 484, 407, 612, 546, 598, 539, +402, 400, 46, 128, -357, -243, -667, -568, +-811, -721, -747, -685, -457, -477, -6, -136, +438, 230, 756, 523, 880, 681, 771, 645, +468, 432, 96, 166, -269, -84, -577, -310, +-720, -434, -642, -416, -419, -326, -161, -203, +86, -34, 267, 85, 352, 65, 359, -5, +319, -2, 299, 68, 332, 183, 320, 342, +173, 474, -50, 466, -294, 277, -543, -46, +-711, -421, -691, -707, -473, -787, -96, -624, +355, -279, 716, 141, 883, 503, 861, 674, +611, 628, 136, 453, -347, 233, -643, -12, +-758, -217, -698, -315, -431, -339, -68, -362, +224, -363, 414, -293, 503, -123, 444, 119, +274, 347, 87, 477, -79, 472, -176, 319, +-156, 38, -80, -243, -34, -399, -36, -399, +-73, -259, -130, -15, -153, 217, -85, 330, +66, 284, 245, 113, 351, -80, 299, -218, +116, -289, -102, -260, -288, -111, -361, 47, +-264, 138, -39, 225, 223, 314, 428, 328, +469, 257, 299, 94, -3, -185, -328, -477, +-556, -635, -554, -604, -307, -343, 60, 138, +400, 612, 593, 840, 539, 775, 288, 448, +-6, -67, -253, -530, -377, -737, -312, -694, +-160, -449, -62, -62, 47, 298, 210, 494, +300, 522, 241, 368, 105, 65, -70, -216, +-231, -377, -305, -417, -265, -268, -96, 67, +177, 396, 421, 574, 498, 548, 436, 269, +269, -195, -13, -639, -328, -915, -554, -927, +-671, -586, -629, 30, -361, 665, 70, 1102, +540, 1216, 919, 957, 1045, 436, 787, -164, +249, -705, -330, -1068, -731, -1143, -875, -937, +-788, -543, -515, -52, -123, 448, 244, 851, +493, 1044, 660, 947, 712, 580, 577, 117, +286, -259, -74, -480, -447, -554, -655, -494, +-575, -367, -334, -279, -67, -251, 215, -191, +424, -30, 436, 200, 308, 433, 138, 581, +-39, 577, -201, 423, -300, 179, -279, -118, +-77, -378, 211, -462, 365, -384, 322, -282, +150, -172, -106, -25, -333, 60, -341, 71, +-143, 112, 101, 176, 275, 220, 292, 286, +130, 286, -76, 107, -176, -129, -145, -279, +-23, -357, 100, -312, 146, -85, 143, 161, +129, 306, 66, 356, -28, 244, -105, -45, +-171, -299, -186, -392, -92, -360, 55, -203, +183, 37, 274, 256, 268, 417, 121, 458, +-65, 285, -198, 27, -254, -133, -202, -225, +-69, -292, 54, -253, 175, -159, 317, -92, +358, 5, 229, 125, 39, 197, -125, 234, +-268, 221, -328, 78, -271, -139, -141, -311, +14, -374, 146, -250, 200, 68, 203, 392, +232, 561, 271, 554, 253, 329, 162, -82, +44, -487, -86, -729, -248, -752, -415, -520, +-463, -156, -327, 188, -86, 494, 170, 713, +410, 725, 548, 568, 487, 320, 276, -43, +35, -421, -170, -657, -279, -751, -248, -707, +-133, -424, -20, 34, 73, 460, 115, 711, +80, 703, 21, 458, -28, 154, -102, -114, +-178, -392, -162, -577, -42, -512, 153, -250, +379, 35, 521, 277, 479, 467, 324, 540, +98, 405, -230, 66, -537, -339, -652, -637, +-573, -692, -368, -467, -53, -43, 245, 393, +424, 678, 512, 716, 513, 473, 391, 36, +259, -383, 192, -611, 91, -572, -68, -287, +-239, 76, -427, 350, -591, 465, -587, 382, +-435, 79, -171, -276, 226, -457, 619, -406, +796, -199, 771, 56, 610, 270, 256, 411, +-191, 442, -520, 275, -650, -18, -606, -216, +-361, -280, -10, -301, 303, -230, 448, -45, +373, 108, 174, 133, 6, 56, -116, -93, +-224, -217, -181, -162, 25, 60, 223, 332, +312, 538, 315, 563, 210, 335, 14, -73, +-181, -521, -314, -847, -332, -873, -193, -564, +25, -60, 173, 481, 207, 924, 141, 1102, +44, 909, -12, 367, -33, -370, -32, -1046, +41, -1378, 172, -1237, 268, -660, 313, 231, +308, 1153, 194, 1713, -55, 1647, -402, 968, +-729, -115, -809, -1231, -512, -1951, 0, -1981, +530, -1291, 962, -92, 1111, 1195, 838, 2050, +269, 2128, -344, 1416, -791, 204, -898, -1035, +-666, -1835, -254, -1956, 190, -1389, 533, -331, +631, 803, 482, 1551, 195, 1674, -149, 1210, +-420, 378, -445, -508, -218, -1164, 95, -1412, +389, -1169, 596, -484, 587, 338, 262, 966, +-226, 1230, -617, 1068, -760, 505, -622, -247, +-212, -894, 352, -1203, 795, -999, 914, -325, +696, 500, 256, 1118, -258, 1298, -692, 881, +-886, -14, -713, -955, -251, -1533, 227, -1536, +589, -890, 867, 209, 917, 1269, 564, 1873, +27, 1815, -415, 1093, -740, -46, -857, -1180, +-601, -1918, -121, -1978, 279, -1321, 515, -245, +585, 815, 468, 1540, 255, 1723, 35, 1291, +-147, 444, -200, -469, -102, -1104, -7, -1236, +45, -888, 89, -277, 57, 390, -101, 891, +-280, 985, -377, 607, -329, -61, -72, -731, +302, -1130, 628, -1057, 771, -505, 678, 335, +359, 1122, -87, 1491, -541, 1256, -830, 528, +-798, -415, -488, -1228, -56, -1559, 386, -1284, +732, -555, 804, 360, 574, 1140, 163, 1443, +-243, 1162, -506, 466, -535, -384, -345, -1092, +1, -1351, 372, -1069, 555, -397, 470, 441, +179, 1151, -200, 1421, -517, 1149, -578, 486, +-359, -363, 42, -1133, 471, -1491, 723, -1277, +670, -613, 389, 259, 5, 1046, -402, 1405, +-660, 1161, -672, 450, -469, -400, -127, -1030, +283, -1137, 637, -683, 831, 81, 786, 801, +464, 1174, -8, 992, -438, 300, -734, -550, +-803, -1192, -552, -1437, -151, -1185, 169, -456, +397, 467, 565, 1223, 610, 1582, 539, 1467, +386, 917, 116, 127, -189, -643, -375, -1207, +-429, -1435, -403, -1277, -293, -807, -156, -178, +-77, 483, 3, 988, 169, 1167, 392, 1005, +594, 586, 691, 34, 564, -435, 206, -631, +-234, -547, -603, -264, -793, 65, -736, 220, +-442, 92, -19, -191, 445, -469, 820, -604, +931, -458, 709, -35, 259, 512, -270, 1011, +-705, 1252, -841, 1044, -633, 446, -220, -331, +223, -1085, 557, -1549, 666, -1465, 586, -898, +417, -107, 149, 709, -203, 1312, -492, 1461, +-602, 1157, -494, 551, -162, -197, 214, -821, +410, -1136, 413, -1149, 295, -861, 92, -264, +-57, 388, -50, 815, 29, 984, 102, 900, +138, 526, 86, -3, -18, -471, -79, -783, +-145, -849, -252, -639, -318, -271, -290, 143, +-94, 532, 310, 737, 671, 655, 710, 369, +513, 18, 215, -274, -192, -414, -527, -399, +-578, -290, -417, -121, -191, 19, 61, 51, +251, 54, 361, 124, 421, 166, 348, 116, +121, 61, -122, 49, -299, 36, -360, 12, +-178, 17, 136, 33, 361, 25, 453, -37, +387, -150, 97, -252, -217, -244, -369, -132, +-450, -11, -434, 112, -183, 254, 188, 318, +480, 249, 680, 153, 659, 51, 349, -105, +-83, -219, -441, -192, -623, -140, -525, -128, +-216, -79, 91, -29, 325, -29, 451, -8, +425, 48, 306, 84, 202, 169, 47, 282, +-168, 265, -349, 149, -418, 77, -354, -25, +-153, -238, 128, -451, 357, -578, 436, -554, +365, -287, 292, 152, 243, 548, 114, 824, +-88, 918, -238, 698, -348, 186, -414, -407, +-354, -884, -208, -1095, -27, -964, 219, -556, +451, 16, 534, 622, 511, 1051, 395, 1130, +161, 868, -69, 332, -224, -317, -348, -814, +-374, -995, -281, -855, -245, -456, -234, 32, +-74, 390, 157, 559, 353, 565, 560, 395, +651, 117, 462, -102, 150, -201, -110, -208, +-301, -129, -360, -1, -282, 109, -197, 136, +-152, 23, -135, -199, -140, -384, -27, -451, +224, -352, 412, -39, 470, 403, 476, 753, +363, 867, 123, 696, -93, 232, -262, -397, +-395, -938, -403, -1170, -305, -976, -202, -402, +-30, 280, 199, 828, 353, 1129, 413, 1059, +401, 568, 291, -103, 145, -634, 4, -891, +-187, -854, -310, -574, -256, -172, -153, 249, +-86, 623, 21, 796, 124, 659, 160, 319, +194, -58, 222, -421, 191, -705, 131, -748, +42, -482, -83, -19, -140, 463, -121, 800, +-120, 794, -114, 399, -42, -158, 69, -610, +206, -857, 349, -765, 427, -253, 402, 436, +194, 926, -254, 1025, -688, 671, -772, -68, +-522, -794, -116, -1137, 383, -1078, 823, -636, +1007, 194, 863, 1033, 425, 1384, -185, 1173, +-706, 556, -952, -299, -910, -1050, -571, -1357, +-35, -1184, 494, -596, 859, 265, 963, 1004, +685, 1288, 147, 1124, -318, 569, -539, -257, +-520, -965, -285, -1237, 64, -1069, 322, -523, +409, 291, 310, 1037, 46, 1378, -288, 1187, +-491, 500, -466, -455, -265, -1270, 50, -1617, +474, -1365, 902, -561, 1049, 523, 774, 1470, +196, 1880, -480, 1551, -1065, 620, -1288, -523, +-1038, -1505, -447, -1951, 277, -1592, 915, -589, +1255, 572, 1194, 1468, 765, 1767, 75, 1305, +-574, 336, -880, -709, -794, -1474, -458, -1593, +4, -934, 403, 89, 530, 1014, 364, 1608, +49, 1563, -247, 776, -377, -329, -262, -1302, +17, -1893, 328, -1771, 571, -900, 649, 273, +499, 1339, 153, 2029, -286, 1967, -691, 1110, +-873, -67, -680, -1131, -191, -1807, 342, -1806, +739, -1123, 902, -105, 708, 898, 207, 1509, +-287, 1448, -560, 812, -631, -101, -457, -995, +-37, -1449, 369, -1198, 584, -445, 664, 474, +564, 1302, 191, 1705, -257, 1422, -578, 536, +-779, -628, -811, -1607, -537, -2006, -3, -1778, +643, -1049, 1167, 91, 1261, 1325, 915, 2100, +396, 2118, -198, 1485, -836, 479, -1195, -608, +-1065, -1478, -654, -1838, -195, -1553, 283, -848, +700, -94, 925, 554, 938, 1005, 755, 1091, +400, 859, -57, 539, -492, 184, -754, -185, +-755, -453, -574, -588, -290, -603, 105, -487, +486, -337, 655, -185, 635, 84, 539, 418, +314, 662, -57, 815, -400, 821, -580, 484, +-583, -125, -381, -788, -3, -1372, 413, -1590, +687, -1167, 682, -282, 421, 723, 52, 1639, +-299, 2124, -502, 1863, -458, 965, -256, -227, +-62, -1372, 168, -2085, 418, -2138, 457, -1574, +266, -556, 82, 581, -84, 1378, -281, 1630, +-300, 1433, -70, 902, 201, 231, 405, -298, +514, -561, 365, -596, 0, -484, -340, -379, +-560, -368, -654, -411, -525, -483, -182, -516, +269, -336, 762, 106, 1092, 666, 1057, 1183, +656, 1452, 21, 1293, -698, 689, -1184, -234, +-1207, -1214, -823, -1834, -161, -1808, 611, -1223, +1141, -300, 1175, 724, 815, 1451, 238, 1569, +-368, 1158, -784, 470, -849, -277, -584, -860, +-71, -1039, 509, -755, 908, -217, 929, 315, +530, 677, -118, 709, -751, 316, -1133, -308, +-1090, -834, -516, -1049, 360, -817, 1111, -96, +1463, 807, 1316, 1439, 679, 1586, -148, 1168, +-789, 210, -1179, -927, -1271, -1768, -907, -2043, +-214, -1612, 457, -556, 948, 686, 1157, 1660, +969, 2125, 478, 1892, -103, 956, -596, -297, +-768, -1370, -476, -1897, 29, -1710, 413, -964, +569, 4, 437, 918, -19, 1442, -579, 1277, +-936, 579, -915, -201, -419, -784, 470, -1011, +1371, -729, 1851, -56, 1692, 632, 890, 1016, +-347, 936, -1551, 404, -2239, -370, -2163, -1061, +-1345, -1346, -46, -1100, 1231, -467, 2061, 334, +2326, 1085, 1984, 1503, 985, 1384, -402, 783, +-1598, -105, -2191, -976, -2039, -1480, -1156, -1482, +143, -1032, 1286, -154, 1864, 898, 1726, 1577, +921, 1584, -148, 1001, -920, 4, -1150, -1054, +-942, -1691, -434, -1697, 169, -1110, 635, -44, +897, 1102, 951, 1803, 640, 1875, -36, 1357, +-697, 337, -989, -792, -877, -1560, -460, -1830, +156, -1594, 727, -844, 968, 131, 819, 906, +422, 1335, -48, 1423, -410, 1094, -535, 430, +-470, -266, -289, -751, 22, -933, 384, -810, +597, -439, 531, 52, 164, 439, -352, 537, +-658, 316, -542, -106, -161, -494, 278, -648, +665, -507, 769, -91, 492, 489, 117, 965, +-148, 1096, -354, 869, -465, 349, -383, -398, +-229, -1090, -52, -1358, 228, -1164, 505, -651, +547, 57, 351, 719, 20, 1076, -339, 1038, +-496, 624, -327, 6, 5, -473, 309, -639, +556, -580, 641, -294, 451, 240, 100, 695, +-205, 730, -454, 408, -682, -101, -754, -728, +-512, -1250, 17, -1333, 592, -882, 963, -56, +1007, 905, 748, 1680, 270, 1929, -219, 1535, +-530, 661, -617, -416, -522, -1398, -315, -2004, +-83, -2019, 85, -1386, 199, -306, 292, 807, +329, 1563, 234, 1789, 62, 1465, -10, 675, +115, -295, 320, -1063, 422, -1369, 377, -1114, +180, -399, -187, 427, -581, 994, -768, 1150, +-713, 845, -474, 85, -55, -884, 461, -1631, +871, -1806, 1054, -1240, 985, -98, 665, 1132, +177, 2066, -375, 2504, -853, 2179, -1038, 994, +-835, -573, -418, -1872, 70, -2619, 576, -2697, +864, -2004, 753, -743, 402, 637, 19, 1721, +-311, 2242, -420, 2133, -204, 1533, 156, 693, +453, -126, 572, -737, 408, -1096, 31, -1248, +-357, -1207, -664, -1016, -784, -782, -596, -489, +-222, -48, 172, 459, 597, 863, 974, 1106, +1107, 1242, 983, 1247, 644, 978, 43, 445, +-664, -191, -1114, -862, -1214, -1485, -1047, -1814, +-612, -1677, 29, -1145, 674, -359, 1126, 573, +1288, 1394, 1146, 1813, 753, 1771, 162, 1314, +-495, 542, -975, -299, -1117, -998, -910, -1415, +-434, -1427, 138, -1082, 615, -555, 884, 31, +886, 563, 627, 866, 217, 884, -209, 724, +-554, 414, -684, -27, -560, -404, -272, -597, +162, -628, 661, -454, 919, -100, 786, 252, +457, 503, 70, 648, -375, 619, -748, 340, +-898, -123, -813, -622, -490, -997, 49, -1087, +618, -844, 1067, -341, 1295, 331, 1127, 991, +610, 1348, -4, 1276, -601, 906, -1104, 363, +-1239, -306, -926, -940, -445, -1310, 58, -1324, +638, -1065, 1091, -591, 1143, 82, 903, 755, +550, 1142, 29, 1171, -563, 921, -879, 476, +-810, -47, -535, -485, -172, -704, 273, -692, +678, -532, 864, -323, 744, -121, 348, 94, +-163, 261, -586, 260, -785, 168, -693, 125, +-296, 101, 258, 64, 763, 32, 1032, -24, +923, -115, 499, -153, 2, -84, -397, 0, +-699, 103, -852, 259, -747, 258, -421, 8, +13, -271, 490, -438, 886, -492, 1038, -402, +862, -159, 445, 165, -45, 465, -457, 635, +-672, 594, -670, 401, -541, 149, -357, -230, +-42, -639, 404, -793, 796, -685, 977, -423, +903, 20, 533, 524, -86, 837, -694, 837, +-1076, 532, -1163, -11, -876, -586, -256, -966, +460, -1078, 1108, -814, 1592, -108, 1711, 716, +1353, 1304, 564, 1534, -528, 1228, -1569, 391, +-2157, -623, -2210, -1500, -1757, -2005, -721, -1900, +752, -1164, 2122, -65, 2961, 1101, 3092, 2060, +2378, 2451, 951, 2104, -777, 1152, -2369, -203, +-3356, -1593, -3352, -2547, -2376, -2817, -788, -2269, +1006, -962, 2535, 600, 3342, 1914, 3237, 2751, +2286, 2829, 708, 2015, -995, 617, -2206, -930, +-2652, -2222, -2365, -2787, -1424, -2478, -75, -1564, +1102, -240, 1651, 1216, 1637, 2151, 1269, 2270, +594, 1849, -167, 996, -597, -187, -584, -1175, +-357, -1638, -27, -1638, 315, -1228, 421, -543, +194, 155, -218, 718, -636, 984, -899, 837, +-741, 523, -76, 295, 806, 55, 1544, -183, +1838, -160, 1501, 5, 559, -3, -713, -117, +-1844, -292, -2405, -629, -2178, -943, -1190, -964, +304, -604, 1840, 80, 2899, 857, 3108, 1517, +2367, 1871, 850, 1651, -1027, 798, -2614, -333, +-3346, -1341, -3082, -2068, -1966, -2346, -193, -1958, +1751, -1021, 3099, 202, 3435, 1474, 2880, 2330, +1561, 2484, -262, 2052, -1866, 1059, -2630, -326, +-2572, -1553, -1883, -2220, -686, -2283, 588, -1760, +1471, -752, 1797, 379, 1599, 1264, 1012, 1766, +320, 1771, -246, 1251, -646, 397, -780, -565, +-583, -1275, -253, -1460, 9, -1231, 209, -675, +365, 163, 413, 922, 349, 1286, 270, 1255, +131, 866, -189, 108, -534, -785, -640, -1437, +-542, -1693, -327, -1456, 157, -699, 850, 322, +1370, 1349, 1482, 2090, 1218, 2134, 552, 1502, +-402, 519, -1289, -675, -1885, -1827, -2019, -2469, +-1484, -2376, -396, -1668, 836, -474, 1890, 974, +2462, 2141, 2280, 2608, 1437, 2313, 180, 1319, +-1201, -65, -2152, -1408, -2228, -2353, -1544, -2494, +-443, -1716, 861, -448, 1951, 841, 2246, 1877, +1651, 2299, 502, 1855, -870, 709, -2044, -689, +-2444, -1883, -1788, -2435, -380, -2115, 1234, -1067, +2593, 401, 3204, 1850, 2666, 2689, 1155, 2602, +-712, 1710, -2394, 241, -3385, -1388, -3260, -2582, +-2046, -2969, -246, -2486, 1599, -1270, 2978, 316, +3415, 1759, 2786, 2604, 1319, 2635, -451, 1937, +-1803, 756, -2359, -534, -2223, -1553, -1498, -2056, +-249, -1957, 1039, -1368, 1770, -503, 1803, 400, +1249, 1023, 289, 1233, -703, 1148, -1309, 820, +-1369, 312, -945, -203, -101, -550, 933, -706, +1670, -760, 1724, -610, 1175, -186, 411, 216, +-407, 433, -1236, 601, -1750, 633, -1615, 331, +-902, -151, 54, -484, 893, -657, 1423, -756, +1574, -596, 1232, -176, 511, 209, -189, 539, +-641, 859, -855, 1007, -725, 869, -249, 430, +160, -177, 326, -769, 472, -1253, 512, -1498, +238, -1287, -145, -582, -390, 291, -520, 996, +-499, 1489, -242, 1596, 151, 1113, 595, 323, +1000, -419, 1143, -1013, 934, -1345, 489, -1245, +-36, -730, -554, -81, -973, 440, -1188, 787, +-1109, 915, -726, 743, -194, 279, 370, -296, +888, -690, 1184, -812, 1229, -708, 1156, -371, +884, 162, 363, 765, -153, 1161, -530, 1091, +-855, 696, -1120, 176, -1205, -563, -1052, -1405, +-686, -1909, -96, -1823, 678, -1280, 1444, -368, +1900, 891, 1833, 2120, 1390, 2795, 673, 2726, +-370, 1930, -1367, 537, -1798, -1169, -1729, -2754, +-1453, -3667, -840, -3578, 163, -2587, 1162, -923, +1768, 1127, 1880, 3011, 1583, 4133, 991, 4183, +183, 3180, -658, 1324, -1226, -1009, -1374, -3164, +-1224, -4456, -883, -4549, -384, -3500, 163, -1541, +649, 875, 1025, 3010, 1249, 4204, 1315, 4282, +1192, 3327, 806, 1504, 263, -637, -359, -2432, +-1150, -3527, -1900, -3739, -2147, -3024, -1753, -1651, +-900, 28, 341, 1600, 1806, 2623, 2964, 2951, +3392, 2691, 2914, 1878, 1533, 610, -382, -721, +-2298, -1755, -3709, -2419, -4159, -2604, -3387, -2187, +-1579, -1322, 778, -137, 3073, 1148, 4593, 2080, +4786, 2490, 3619, 2417, 1482, 1694, -1065, 413, +-3342, -890, -4638, -1850, -4557, -2425, -3174, -2429, +-947, -1675, 1526, -504, 3631, 655, 4737, 1619, +4438, 2102, 2825, 1918, 424, 1269, -2005, 402, +-3679, -496, -4180, -1174, -3472, -1436, -1717, -1317, +469, -1008, 2300, -531, 3385, 80, 3615, 556, +2852, 701, 1203, 674, -670, 698, -2118, 674, +-2883, 438, -2831, 167, -1986, 23, -580, -204, +979, -636, 2153, -1033, 2572, -1140, 2279, -1031, +1497, -787, 364, -231, -844, 627, -1687, 1421, +-1952, 1854, -1706, 1820, -1014, 1293, 18, 358, +1041, -777, 1690, -1820, 1852, -2456, 1578, -2339, +888, -1491, -122, -351, -1086, 799, -1651, 1802, +-1736, 2311, -1352, 2105, -517, 1318, 574, 297, +1567, -589, 2131, -1230, 2042, -1591, 1430, -1503, +509, -951, -654, -343, -1765, -21, -2322, 148, +-2162, 294, -1491, 324, -348, 337, 1159, 496, +2362, 772, 2754, 1089, 2429, 1154, 1501, 734, +106, 74, -1264, -630, -2110, -1518, -2320, -2315, +-1945, -2392, -1068, -1711, 43, -644, 1089, 721, +1859, 2171, 2138, 3121, 1790, 3181, 962, 2269, +-27, 621, -847, -1155, -1260, -2557, -1231, -3386, +-913, -3307, -495, -2131, -43, -408, 418, 1196, +774, 2441, 918, 3049, 873, 2743, 704, 1703, +383, 279, -32, -1155, -410, -2140, -659, -2490, +-683, -2268, -530, -1443, -335, -162, -60, 1010, +397, 1672, 869, 1878, 1051, 1690, 970, 1061, +681, 188, 86, -648, -587, -1220, -981, -1392, +-1023, -1275, -770, -1008, -274, -556, 279, 17, +700, 526, 997, 887, 1101, 1099, 846, 1178, +322, 1024, -194, 562, -624, -68, -875, -620, +-739, -1050, -275, -1386, 262, -1415, 675, -980, +813, -321, 594, 284, 163, 795, -239, 1132, +-533, 1200, -626, 1015, -392, 600, 73, 94, +533, -239, 875, -431, 1031, -688, 811, -905, +256, -897, -310, -755, -714, -639, -901, -480, +-844, -113, -537, 449, -77, 977, 371, 1300, +676, 1370, 786, 1207, 803, 797, 786, 113, +580, -713, 195, -1479, -109, -1951, -262, -1940, +-490, -1516, -814, -807, -916, 172, -663, 1196, +-280, 1965, 157, 2331, 715, 2144, 1180, 1376, +1306, 260, 1139, -866, 783, -1792, 229, -2352, +-429, -2321, -970, -1697, -1335, -729, -1428, 374, +-1081, 1287, -350, 1755, 576, 1859, 1433, 1625, +1864, 981, 1720, 112, 1207, -624, 424, -1054, +-584, -1262, -1362, -1292, -1602, -1024, -1473, -484, +-1058, 60, -250, 308, 737, 330, 1417, 428, +1613, 484, 1424, 330, 952, 305, 332, 579, +-319, 748, -821, 577, -955, 263, -833, -114, +-708, -710, -494, -1381, -89, -1774, 303, -1705, +554, -1130, 760, -248, 908, 711, 839, 1732, +591, 2538, 354, 2574, 135, 1850, -117, 792, +-393, -493, -627, -1961, -776, -3040, -769, -3229, +-491, -2639, -115, -1427, 124, 254, 336, 1903, +684, 3069, 974, 3471, 1008, 2859, 952, 1496, +841, -43, 504, -1499, -14, -2674, -535, -3100, +-993, -2616, -1344, -1619, -1453, -382, -1280, 964, +-849, 1952, -104, 2246, 889, 1999, 1898, 1297, +2625, 251, 2737, -709, 2099, -1205, 875, -1144, +-652, -704, -2124, -235, -3119, 93, -3318, 261, +-2635, 128, -1261, -319, 512, -774, 2307, -942, +3548, -816, 3815, -332, 3057, 588, 1521, 1585, +-366, 2186, -2087, 2285, -3118, 1786, -3221, 560, +-2462, -1123, -1105, -2682, 462, -3509, 1827, -3371, +2614, -2459, 2614, -926, 1888, 1039, 723, 2857, +-511, 3897, -1446, 3897, -1787, 2927, -1499, 1272, +-705, -646, 345, -2363, 1166, -3544, 1437, -3803, +1241, -2966, 682, -1525, -236, -44, -1174, 1295, +-1634, 2226, -1486, 2536, -790, 2303, 378, 1633, +1614, 776, 2356, 53, 2436, -443, 1901, -843, +763, -1192, -810, -1432, -2330, -1586, -3163, -1632, +-3068, -1426, -2204, -949, -666, -143, 1398, 1005, +3345, 2044, 4274, 2582, 3904, 2623, 2565, 2134, +509, 1062, -1849, -344, -3714, -1688, -4422, -2683, +-3865, -3166, -2288, -2950, -52, -2007, 2290, -587, +3990, 989, 4469, 2350, 3698, 3109, 1971, 3001, +-306, 2117, -2381, 893, -3485, -407, -3480, -1669, +-2658, -2378, -1198, -2244, 597, -1681, 2111, -987, +2909, -93, 2959, 791, 2258, 1213, 885, 1198, +-672, 1013, -1851, 611, -2337, 30, -2077, -396, +-1236, -546, -68, -455, 1038, -179, 1674, 158, +1728, 477, 1385, 563, 869, 220, 190, -308, +-584, -691, -1145, -958, -1300, -1116, -1086, -903, +-634, -264, -57, 381, 509, 808, 882, 1126, +1043, 1247, 1111, 1099, 1095, 795, 854, 358, +338, -159, -255, -639, -748, -1108, -1208, -1487, +-1603, -1616, -1555, -1491, -932, -1151, -119, -494, +663, 505, 1528, 1518, 2281, 2253, 2483, 2665, +2075, 2528, 1231, 1640, 9, 299, -1395, -1179, +-2527, -2612, -3084, -3573, -3005, -3635, -2200, -2786, +-753, -1316, 1001, 525, 2704, 2441, 3984, 3853, +4471, 4232, 3800, 3494, 1989, 1896, -377, -99, +-2685, -2074, -4477, -3631, -5212, -4178, -4511, -3492, +-2628, -2008, -163, -240, 2468, 1463, 4676, 2706, +5694, 3170, 5237, 2785, 3535, 1788, 951, 514, +-1907, -680, -4217, -1530, -5383, -2015, -5140, -2109, +-3550, -1729, -1121, -1006, 1420, -150, 3482, 679, +4634, 1293, 4650, 1635, 3622, 1644, 1770, 1252, +-484, 567, -2406, -238, -3462, -1010, -3611, -1571, +-2967, -1802, -1664, -1666, -106, -1128, 1243, -150, +2164, 1057, 2590, 2019, 2566, 2494, 2062, 2377, +1103, 1509, 80, 48, -678, -1547, -1314, -2843, +-1933, -3439, -2116, -3102, -1668, -1909, -1061, -107, +-458, 1901, 461, 3481, 1554, 4034, 2319, 3519, +2566, 2195, 2352, 243, 1657, -1851, 476, -3355, +-933, -3933, -2152, -3624, -2906, -2526, -3054, -894, +-2430, 843, -1081, 2231, 562, 3050, 2050, 3223, +3185, 2742, 3670, 1740, 3216, 464, 2000, -773, +372, -1718, -1416, -2327, -2923, -2533, -3614, -2260, +-3418, -1668, -2507, -918, -942, -75, 927, 803, +2497, 1598, 3392, 2133, 3524, 2304, 2902, 2115, +1607, 1581, -29, 767, -1515, -251, -2483, -1322, +-2844, -2148, -2615, -2581, -1725, -2584, -438, -2116, +681, -1230, 1495, -73, 2105, 1135, 2283, 2105, +1854, 2686, 1125, 2791, 398, 2334, -361, 1350, +-1102, 48, -1559, -1220, -1598, -2194, -1288, -2737, +-728, -2713, -75, -2122, 560, -1149, 1084, 40, +1375, 1195, 1411, 2053, 1215, 2480, 780, 2361, +135, 1684, -585, 647, -1206, -517, -1559, -1595, +-1487, -2274, -938, -2276, -28, -1638, 924, -638, +1601, 537, 1933, 1627, 1848, 2182, 1232, 1991, +204, 1150, -898, -101, -1783, -1371, -2273, -2267, +-2117, -2531, -1303, -1979, -173, -707, 981, 865, +1996, 2235, 2607, 3049, 2558, 3113, 1846, 2330, +746, 803, -430, -1072, -1494, -2740, -2257, -3763, +-2486, -3945, -2096, -3188, -1249, -1468, -242, 696, +726, 2569, 1564, 3823, 2175, 4263, 2372, 3603, +2015, 1992, 1319, 45, 559, -1720, -274, -2987, +-1124, -3498, -1713, -3166, -1901, -2193, -1833, -918, +-1601, 258, -1083, 1065, -220, 1533, 763, 1707, +1541, 1615, 2104, 1482, 2525, 1410, 2494, 1209, +1800, 794, 789, 194, -211, -645, -1341, -1652, +-2525, -2519, -3205, -3016, -3071, -2974, -2247, -2171, +-939, -689, 624, 1048, 2198, 2683, 3445, 3883, +3927, 4252, 3509, 3618, 2374, 2047, 670, -137, +-1333, -2309, -3045, -3911, -3975, -4671, -4027, -4371, +-3147, -2898, -1341, -673, 861, 1541, 2709, 3244, +3784, 4154, 3966, 3987, 3300, 2820, 1895, 1081, +30, -731, -1767, -2153, -2998, -2939, -3458, -3024, +-3082, -2390, -1870, -1271, -223, -109, 1291, 850, +2393, 1547, 2910, 1864, 2643, 1689, 1721, 1214, +600, 665, -422, 77, -1316, -440, -1938, -760, +-2011, -962, -1484, -1081, -717, -1036, -37, -828, +654, -497, 1327, -117, 1551, 272, 1237, 661, +829, 981, 524, 1104, 137, 1002, -295, 770, +-528, 459, -581, 27, -595, -508, -573, -1023, +-522, -1386, -415, -1481, -237, -1319, -69, -951, +170, -314, 556, 537, 915, 1333, 1094, 1889, +1136, 2080, 1021, 1809, 632, 1128, 64, 156, +-514, -966, -1069, -1952, -1464, -2452, -1502, -2379, +-1220, -1827, -749, -874, -65, 303, 758, 1334, +1431, 1975, 1788, 2185, 1851, 1966, 1603, 1399, +999, 601, 143, -285, -693, -1021, -1327, -1476, +-1724, -1695, -1785, -1618, -1419, -1206, -762, -657, +-51, -137, 602, 371, 1163, 788, 1525, 975, +1581, 1041, 1347, 1106, 886, 1035, 371, 747, +-38, 408, -378, 89, -724, -333, -1056, -908, +-1248, -1433, -1195, -1646, -950, -1514, -573, -1159, +-11, -608, 715, 160, 1302, 986, 1516, 1601, +1527, 1859, 1412, 1777, 960, 1450, 231, 928, +-455, 126, -1041, -864, -1548, -1661, -1692, -2096, +-1317, -2240, -688, -1956, -22, -1076, 666, 103, +1201, 1124, 1349, 1831, 1194, 2174, 929, 1976, +568, 1270, 151, 385, -195, -401, -449, -949, +-594, -1216, -575, -1222, -491, -1014, -460, -691, +-429, -421, -331, -285, -213, -201, -51, -8, +282, 323, 721, 717, 1114, 1126, 1385, 1438, +1371, 1484, 954, 1128, 216, 346, -660, -692, +-1461, -1683, -1956, -2365, -1977, -2512, -1508, -1985, +-591, -839, 616, 632, 1748, 2001, 2462, 2889, +2578, 2997, 2088, 2227, 1137, 852, -100, -683, +-1410, -2027, -2420, -2849, -2800, -2919, -2505, -2198, +-1625, -899, -259, 527, 1262, 1647, 2419, 2294, +2918, 2394, 2771, 1845, 2031, 778, 808, -331, +-545, -1088, -1621, -1484, -2284, -1521, -2516, -1112, +-2155, -432, -1239, 124, -155, 355, 817, 322, +1652, 140, 2084, -96, 1829, -221, 1272, -53, +840, 363, 374, 842, -204, 1217, -627, 1307, +-849, 941, -1078, 172, -1265, -771, -1176, -1657, +-824, -2213, -402, -2175, 2, -1547, 463, -572, +1008, 553, 1442, 1600, 1593, 2246, 1524, 2292, +1212, 1816, 532, 1014, -351, 64, -1076, -859, +-1504, -1514, -1640, -1726, -1418, -1588, -906, -1258, +-293, -752, 302, -143, 784, 350, 1087, 641, +1225, 806, 1173, 856, 862, 791, 388, 729, +37, 679, -99, 513, -210, 247, -350, -56, +-369, -437, -302, -848, -410, -1103, -650, -1116, +-727, -924, -635, -590, -491, -158, -215, 281, +236, 571, 749, 645, 1218, 620, 1564, 610, +1679, 584, 1492, 566, 971, 612, 109, 596, +-865, 353, -1639, -115, -2175, -711, -2416, -1280, +-2096, -1664, -1216, -1761, -122, -1453, 989, -683, +2079, 318, 2873, 1163, 2972, 1733, 2352, 2037, +1318, 1870, 85, 1199, -1210, 375, -2245, -359, +-2640, -924, -2365, -1208, -1655, -1231, -721, -1096, +282, -849, 1137, -600, 1551, -490, 1473, -446, +1162, -285, 824, 39, 433, 484, 64, 1057, +-20, 1630, 112, 1966, 133, 1940, 62, 1461, +5, 516, -260, -679, -800, -1800, -1291, -2603, +-1513, -2900, -1468, -2587, -1044, -1714, -187, -529, +873, 671, 1867, 1706, 2566, 2436, 2705, 2710, +2188, 2489, 1173, 1923, -77, 1165, -1257, 238, +-2107, -804, -2503, -1758, -2464, -2456, -1999, -2838, +-1110, -2851, -32, -2370, 872, -1314, 1523, 97, +2053, 1483, 2304, 2657, 2017, 3476, 1401, 3584, +797, 2816, 112, 1480, -790, -39, -1597, -1557, +-1995, -2834, -2043, -3468, -1782, -3267, -1102, -2408, +-113, -1177, 812, 166, 1382, 1345, 1631, 2123, +1621, 2369, 1210, 2142, 504, 1611, -44, 924, +-271, 226, -389, -357, -391, -811, -142, -1147, +111, -1339, 54, -1380, -222, -1272, -574, -1010, +-972, -563, -1224, 52, -1125, 701, -649, 1204, +157, 1431, 1117, 1338, 1852, 967, 2130, 412, +2008, -199, 1468, -720, 482, -979, -584, -870, +-1292, -533, -1634, -134, -1777, 254, -1637, 478, +-1101, 372, -436, 7, 8, -436, 258, -838, +554, -1022, 922, -747, 1222, -60, 1450, 727, +1651, 1418, 1721, 1842, 1418, 1744, 626, 1102, +-471, 150, -1575, -858, -2456, -1703, -2917, -2185, +-2800, -2142, -2049, -1574, -790, -696, 709, 277, +2106, 1187, 3041, 1834, 3303, 2011, 2923, 1730, +2036, 1160, 817, 406, -517, -393, -1697, -975, +-2435, -1257, -2631, -1350, -2454, -1227, -2020, -857, +-1232, -424, -143, -124, 861, 106, 1580, 417, +2168, 771, 2538, 992, 2351, 1022, 1639, 936, +771, 760, -124, 384, -1067, -199, -1823, -738, +-2111, -1048, -1906, -1158, -1398, -1104, -785, -843, +-137, -406, 510, 62, 958, 433, 1068, 732, +1073, 951, 1169, 985, 1151, 867, 912, 666, +632, 302, 313, -207, -184, -653, -735, -945, +-1152, -1116, -1452, -1078, -1573, -732, -1316, -231, +-718, 246, 6, 691, 759, 1011, 1444, 1039, +1833, 821, 1706, 477, 1070, 47, 265, -383, +-392, -711, -831, -871, -1011, -809, -843, -549, +-401, -221, 48, 82, 266, 349, 214, 530, +37, 568, -154, 495, -386, 386, -558, 253, +-433, 90, -37, -104, 402, -317, 823, -517, +1182, -700, 1254, -819, 953, -749, 426, -427, +-195, 86, -729, 688, -1035, 1261, -1200, 1593, +-1219, 1464, -912, 869, -415, -43, -44, -1077, +266, -1916, 688, -2253, 1036, -1954, 1124, -1060, +1082, 168, 1030, 1332, 884, 2126, 516, 2371, +-83, 1964, -714, 965, -1205, -258, -1571, -1244, +-1767, -1797, -1574, -1909, -899, -1547, 14, -779, +866, 131, 1551, 818, 1993, 1082, 2034, 1060, +1586, 880, 800, 498, -36, 18, -765, -266, +-1314, -302, -1577, -293, -1524, -287, -1236, -228, +-778, -192, -208, -199, 369, -172, 875, -126, +1211, -48, 1269, 92, 1057, 226, 695, 282, +286, 237, -93, 98, -379, -74, -552, -167, +-625, -161, -600, -103, -468, 49, -306, 266, +-194, 336, -91, 225, 50, 75, 159, -126, +173, -378, 201, -526, 353, -488, 520, -300, +567, -58, 504, 142, 381, 292, 203, 381, +-74, 342, -421, 215, -704, 136, -811, 102, +-751, 78, -547, 128, -184, 193, 268, 97, +683, -136, 926, -387, 838, -685, 441, -948, +6, -954, -328, -678, -565, -193, -528, 495, +-132, 1208, 322, 1657, 558, 1731, 589, 1375, +439, 567, 46, -465, -512, -1377, -976, -1971, +-1105, -2103, -891, -1693, -481, -854, 98, 166, +833, 1098, 1425, 1694, 1553, 1866, 1260, 1600, +712, 912, -22, 34, -742, -699, -1235, -1128, +-1426, -1225, -1235, -993, -724, -520, -145, 28, +383, 482, 825, 673, 995, 519, 821, 147, +500, -244, 149, -576, -188, -737, -318, -566, +-186, -83, -2, 564, 118, 1150, 186, 1384, +134, 1192, -82, 689, -372, -79, -584, -970, +-594, -1612, -408, -1744, -118, -1432, 229, -830, +544, -40, 655, 759, 562, 1316, 410, 1444, +196, 1149, -47, 673, -137, 203, -91, -237, +-80, -535, -90, -522, -74, -298, -132, -133, +-247, -102, -337, -145, -444, -302, -481, -568, +-279, -776, 47, -784, 285, -501, 508, 76, +810, 759, 944, 1320, 730, 1623, 395, 1562, +152, 1117, -92, 391, -440, -468, -745, -1257, +-854, -1731, -872, -1795, -897, -1570, -760, -1111, +-372, -374, 75, 451, 491, 1038, 983, 1362, +1467, 1536, 1645, 1494, 1445, 1204, 1021, 772, +368, 236, -548, -398, -1461, -1023, -2019, -1535, +-2131, -1843, -1843, -1811, -1141, -1353, -130, -527, +901, 471, 1672, 1351, 2032, 1889, 1936, 1998, +1476, 1622, 819, 793, 69, -199, -646, -975, +-1107, -1364, -1232, -1356, -1169, -951, -1032, -285, +-750, 328, -340, 616, -7, 516, 186, 158, +366, -263, 586, -605, 756, -701, 832, -405, +841, 183, 772, 795, 601, 1290, 317, 1493, +-103, 1180, -585, 419, -946, -506, -1125, -1359, +-1151, -1890, -959, -1864, -569, -1289, -121, -382, +314, 592, 706, 1370, 982, 1725, 1111, 1544, +1089, 897, 866, 48, 491, -653, 108, -1027, +-261, -1054, -610, -675, -848, -14, -960, 529, +-995, 735, -874, 625, -564, 189, -171, -445, +276, -920, 704, -1033, 928, -815, 937, -284, +852, 452, 645, 1103, 317, 1420, 63, 1293, +-81, 757, -266, 42, -480, -641, -619, -1174, +-697, -1346, -732, -1026, -680, -436, -504, 84, +-212, 454, 105, 695, 412, 655, 773, 310, +1098, -38, 1182, -157, 1025, -91, 730, 55, +216, 271, -513, 519, -1113, 560, -1344, 207, +-1293, -373, -1028, -888, -533, -1191, 112, -1165, +719, -737, 1071, 9, 1064, 844, 783, 1473, +353, 1651, -122, 1316, -459, 592, -532, -327, +-370, -1170, -47, -1659, 318, -1663, 529, -1206, +456, -395, 166, 546, -226, 1302, -615, 1642, +-868, 1519, -935, 1025, -793, 300, -348, -493, +324, -1176, 890, -1514, 1181, -1362, 1236, -882, +996, -348, 439, 196, -180, 724, -583, 1030, +-753, 1011, -747, 828, -552, 635, -254, 420, +-57, 141, -65, -187, -186, -556, -304, -918, +-383, -1143, -330, -1164, -40, -978, 433, -532, +954, 148, 1407, 851, 1629, 1366, 1431, 1587, +770, 1438, -243, 922, -1342, 180, -2143, -553, +-2408, -1070, -2181, -1317, -1524, -1291, -429, -955, +811, -436, 1720, 19, 2211, 325, 2401, 554, +2141, 694, 1308, 689, 235, 624, -614, 575, +-1176, 441, -1625, 190, -1884, -76, -1712, -352, +-1213, -650, -747, -831, -350, -806, 247, -629, +980, -330, 1445, 74, 1585, 462, 1619, 714, +1479, 792, 983, 686, 264, 418, -439, 60, +-1073, -293, -1567, -537, -1724, -604, -1518, -475, +-1112, -200, -600, 103, 11, 332, 634, 425, +1109, 341, 1306, 105, 1220, -168, 1002, -360, +748, -416, 397, -338, -14, -139, -257, 111, +-301, 315, -414, 459, -703, 498, -985, 349, +-1110, 71, -1083, -169, -943, -336, -616, -457, +-10, -476, 748, -314, 1383, 2, 1782, 310, +1965, 460, 1809, 474, 1171, 404, 180, 131, +-857, -352, -1731, -738, -2314, -801, -2429, -633, +-1983, -294, -1090, 264, -45, 878, 929, 1242, +1753, 1248, 2248, 946, 2200, 362, 1667, -408, +830, -1173, -158, -1696, -1023, -1766, -1489, -1402, +-1556, -771, -1299, 98, -756, 1111, -130, 1873, +272, 2110, 400, 1914, 415, 1357, 358, 423, +197, -660, -5, -1551, -62, -2087, 147, -2203, +487, -1815, 756, -979, 869, 60, 739, 1036, +280, 1742, -393, 2024, -1047, 1816, -1510, 1165, +-1597, 247, -1207, -633, -503, -1223, 234, -1424, +893, -1217, 1446, -685, 1722, -18, 1497, 537, +798, 743, -10, 583, -648, 253, -1153, -142, +-1429, -555, -1204, -764, -585, -553, 39, -41, +517, 510, 821, 966, 832, 1245, 569, 1200, +211, 731, -158, -71, -499, -894, -664, -1432, +-540, -1607, -223, -1431, 136, -875, 417, -57, +572, 716, 600, 1221, 486, 1390, 287, 1174, +88, 668, -137, 141, -423, -277, -699, -542, +-866, -540, -861, -321, -666, -98, -321, 6, +144, -54, 677, -273, 1105, -513, 1282, -606, +1231, -538, 987, -336, 475, 55, -281, 570, +-1027, 958, -1485, 1076, -1571, 988, -1349, 748, +-837, 352, -61, -127, 698, -548, 1098, -809, +1148, -939, 1049, -1023, 788, -1022, 299, -813, +-181, -421, -357, 15, -290, 492, -221, 1042, +-171, 1474, -78, 1542, -84, 1269, -342, 824, +-690, 206, -829, -591, -715, -1306, -424, -1676, +73, -1668, 695, -1320, 1183, -683, 1348, 73, +1177, 744, 793, 1176, 321, 1286, -195, 1068, +-689, 640, -1018, 219, -1117, -57, -1053, -195, +-880, -227, -604, -186, -262, -166, 76, -252, +411, -444, 739, -671, 992, -837, 1131, -831, +1181, -539, 1131, 16, 852, 634, 252, 1120, +-540, 1398, -1270, 1396, -1782, 1025, -1983, 349, +-1772, -377, -1156, -930, -272, -1272, 654, -1378, +1420, -1153, 1926, -655, 2073, -95, 1776, 390, +1122, 736, 323, 904, -461, 927, -1110, 816, +-1479, 525, -1588, 132, -1536, -204, -1245, -461, +-711, -634, -138, -628, 394, -468, 943, -266, +1376, -42, 1483, 178, 1321, 264, 1045, 173, +625, 49, 38, 9, -524, 17, -909, 30, +-1173, 85, -1315, 215, -1187, 352, -794, 338, +-369, 160, -17, -24, 372, -211, 754, -475, +971, -670, 1061, -612, 1069, -340, 880, -5, +464, 317, -19, 610, -418, 769, -685, 676, +-850, 372, -928, -20, -879, -416, -698, -685, +-448, -684, -171, -463, 159, -187, 491, 111, +703, 388, 796, 495, 850, 428, 867, 325, +770, 193, 503, 5, 92, -155, -391, -263, +-873, -356, -1247, -392, -1381, -344, -1231, -280, +-848, -170, -293, 37, 367, 242, 996, 407, +1423, 593, 1551, 728, 1358, 677, 864, 437, +162, 72, -547, -387, -1022, -881, -1196, -1230, +-1155, -1249, -947, -939, -595, -414, -150, 262, +307, 955, 651, 1426, 788, 1532, 782, 1296, +673, 775, 406, 60, 77, -641, -132, -1150, +-237, -1407, -359, -1363, -449, -1008, -414, -465, +-330, 108, -233, 596, -37, 918, 223, 1036, +400, 928, 417, 621, 319, 284, 145, 54, +-124, -127, -413, -300, -557, -403, -523, -485, +-328, -592, 88, -617, 614, -530, 922, -388, +885, -135, 647, 223, 260, 538, -284, 751, +-807, 830, -1101, 694, -1115, 394, -901, 84, +-522, -214, 8, -501, 631, -616, 1108, -487, +1248, -311, 1121, -198, 794, -59, 244, 72, +-338, 64, -714, -32, -918, -42, -1014, 39, +-905, 98, -580, 202, -161, 453, 284, 637, +659, 561, 809, 371, 687, 123, 373, -314, +62, -803, -74, -1036, -106, -959, -136, -673, +-98, -213, -29, 331, -73, 789, -164, 1028, +-149, 952, -102, 586, -174, 119, -314, -307, +-344, -613, -198, -650, 52, -381, 281, -3, +487, 297, 650, 438, 573, 331, 234, -44, +-92, -513, -270, -848, -400, -888, -465, -543, +-380, 88, -181, 771, 54, 1304, 241, 1511, +292, 1264, 194, 593, -36, -322, -327, -1168, +-493, -1657, -415, -1691, -179, -1291, 146, -533, +554, 385, 878, 1154, 939, 1526, 744, 1449, +345, 1000, -206, 315, -765, -396, -1180, -898, +-1346, -1041, -1179, -831, -692, -395, -34, 117, +590, 537, 1043, 665, 1248, 449, 1177, 43, +888, -364, 496, -658, 94, -718, -305, -443, +-672, 89, -885, 665, -931, 1072, -920, 1159, +-814, 885, -544, 297, -188, -475, 169, -1148, +542, -1442, 937, -1301, 1249, -824, 1307, -106, +1029, 704, 548, 1308, -5, 1431, -647, 1094, +-1278, 513, -1606, -157, -1501, -748, -1064, -1056, +-423, -995, 296, -623, 930, -104, 1333, 363, +1376, 662, 1025, 746, 486, 567, -26, 179, +-450, -206, -726, -433, -770, -536, -612, -516, +-361, -293, -128, 28, 52, 263, 187, 408, +228, 502, 141, 494, 42, 374, 57, 186, +76, -55, 12, -304, -11, -506, 39, -650, +68, -699, 77, -552, 120, -211, 173, 200, +139, 583, -3, 871, -131, 987, -165, 874, +-205, 531, -307, 26, -355, -523, -314, -983, +-250, -1193, -91, -1074, 214, -679, 459, -120, +518, 471, 519, 942, 475, 1152, 284, 1042, +17, 668, -204, 162, -363, -332, -468, -680, +-528, -812, -516, -726, -377, -481, -162, -184, +15, 94, 144, 301, 282, 388, 417, 377, +495, 331, 520, 269, 491, 189, 381, 90, +164, -17, -193, -101, -588, -175, -815, -280, +-813, -371, -670, -342, -402, -205, 10, -38, +425, 163, 674, 378, 762, 497, 724, 474, +503, 337, 127, 85, -233, -256, -454, -532, +-567, -590, -593, -459, -457, -249, -164, 36, +139, 388, 349, 661, 499, 688, 580, 464, +460, 155, 96, -131, -311, -414, -572, -638, +-700, -666, -718, -482, -500, -222, -22, 7, +503, 268, 861, 589, 1006, 783, 984, 725, +719, 535, 164, 287, -488, -86, -980, -532, +-1229, -844, -1266, -907, -1052, -777, -547, -505, +116, -96, 737, 378, 1225, 791, 1495, 1005, +1436, 956, 1010, 682, 331, 262, -379, -210, +-955, -623, -1341, -860, -1466, -846, -1235, -609, +-690, -269, -53, 72, 483, 371, 878, 573, +1107, 600, 1112, 480, 869, 311, 454, 106, +-6, -131, -399, -295, -675, -323, -827, -295, +-814, -270, -585, -193, -196, -17, 199, 152, +491, 227, 649, 292, 621, 381, 362, 354, +-17, 153, -337, -90, -520, -286, -571, -479, +-439, -642, -85, -598, 323, -279, 618, 161, +791, 569, 802, 900, 543, 1072, 52, 927, +-467, 425, -861, -229, -1103, -798, -1121, -1182, +-834, -1302, -312, -1074, 294, -540, 860, 128, +1279, 751, 1406, 1192, 1157, 1362, 640, 1228, +37, 806, -584, 192, -1100, -445, -1280, -961, +-1084, -1253, -719, -1222, -316, -884, 149, -376, +574, 186, 772, 717, 700, 1051, 502, 1040, +311, 734, 157, 315, 43, -115, 3, -486, +34, -651, 42, -541, -46, -267, -197, 26, +-389, 256, -579, 350, -632, 271, -513, 67, +-310, -152, -41, -308, 324, -337, 669, -211, +838, -4, 834, 179, 687, 293, 392, 325, +37, 253, -275, 124, -512, 43, -624, 69, +-608, 153, -538, 206, -471, 152, -360, -28, +-162, -305, 46, -638, 242, -903, 492, -923, +768, -624, 919, -74, 847, 602, 612, 1232, +285, 1635, -167, 1658, -705, 1219, -1099, 395, +-1151, -576, -918, -1416, -538, -1934, -58, -2003, +452, -1542, 824, -676, 886, 287, 672, 1120, +380, 1677, 153, 1804, -2, 1473, -89, 883, +-65, 261, 56, -295, 111, -719, -39, -914, +-324, -913, -593, -878, -743, -860, -754, -769, +-575, -530, -155, -151, 411, 334, 896, 898, +1157, 1432, 1188, 1710, 990, 1562, 527, 996, +-120, 138, -744, -836, -1157, -1674, -1250, -2074, +-1048, -1890, -619, -1195, -58, -190, 472, 862, +804, 1641, 884, 1907, 753, 1617, 467, 891, +140, -30, -84, -850, -188, -1322, -235, -1350, +-205, -955, -103, -276, -63, 436, -151, 930, +-222, 1080, -201, 878, -184, 403, -178, -182, +-59, -694, 186, -958, 366, -880, 384, -524, +355, -71, 325, 356, 205, 708, 22, 882, +-115, 781, -172, 489, -208, 174, -245, -98, +-232, -335, -181, -501, -149, -547, -130, -509, +-54, -458, 100, -390, 251, -223, 321, 49, +342, 352, 355, 627, 318, 829, 164, 866, +-54, 685, -224, 346, -357, -65, -473, -489, +-471, -823, -275, -925, 3, -773, 242, -488, +429, -169, 514, 175, 419, 501, 193, 691, +-48, 695, -244, 576, -360, 409, -360, 200, +-227, -42, 5, -259, 231, -395, 357, -427, +392, -376, 322, -282, 89, -164, -212, -32, +-408, 77, -459, 149, -385, 192, -188, 216, +73, 229, 299, 246, 442, 249, 518, 213, +475, 151, 268, 84, -35, -22, -318, -186, +-492, -343, -533, -433, -417, -448, -151, -376, +150, -192, 362, 82, 452, 379, 401, 611, +224, 727, 10, 700, -159, 509, -285, 164, +-328, -256, -227, -633, -54, -876, 98, -918, +223, -719, 301, -305, 262, 219, 133, 712, +12, 1038, -68, 1108, -153, 903, -230, 475, +-246, -70, -195, -611, -147, -1005, -116, -1123, +-7, -944, 170, -563, 309, -62, 378, 454, +432, 852, 437, 1054, 281, 1050, -15, 822, +-316, 412, -568, -48, -756, -480, -787, -854, +-575, -1056, -159, -986, 301, -716, 715, -331, +1004, 157, 1036, 656, 756, 981, 287, 1073, +-212, 972, -675, 699, -1007, 267, -1060, -248, +-809, -684, -380, -925, 102, -962, 542, -819, +832, -494, 888, -62, 719, 346, 384, 653, +-22, 829, -385, 826, -614, 631, -650, 329, +-506, 21, -258, -229, -2, -399, 190, -476, +286, -463, 295, -370, 247, -240, 188, -121, +124, -19, 47, 100, -42, 267, -139, 430, +-222, 499, -284, 477, -299, 403, -230, 223, +-96, -74, 63, -363, 236, -538, 385, -591, +436, -500, 349, -245, 170, 90, -49, 395, +-293, 595, -507, 615, -614, 438, -527, 168, +-271, -106, 18, -321, 248, -421, 410, -384, +484, -248, 444, -57, 329, 135, 182, 255, +6, 285, -166, 257, -294, 216, -398, 182, +-488, 149, -533, 77, -463, -37, -280, -160, +-66, -287, 152, -427, 421, -502, 723, -404, +889, -126, 788, 251, 464, 618, -1, 887, +-548, 967, -1040, 784, -1312, 334, -1223, -279, +-765, -871, -92, -1238, 607, -1251, 1164, -899, +1406, -260, 1217, 494, 650, 1125, -107, 1419, +-839, 1303, -1327, 808, -1399, 67, -1058, -663, +-411, -1109, 349, -1172, 967, -876, 1250, -291, +1118, 384, 632, 875, -36, 1003, -683, 773, +-1158, 288, -1318, -276, -1071, -704, -514, -835, +133, -637, 729, -194, 1144, 317, 1235, 717, +951, 890, 406, 788, -189, 435, -695, -67, +-1049, -515, -1199, -749, -1069, -751, -706, -567, +-276, -227, 149, 168, 572, 457, 899, 563, +1019, 540, 911, 432, 636, 243, 265, 27, +-181, -119, -652, -151, -1048, -126, -1243, -124, +-1188, -147, -890, -153, -375, -171, 237, -220, +784, -211, 1158, -71, 1261, 151, 1014, 362, +486, 521, -149, 590, -731, 517, -1138, 294, +-1236, -18, -992, -340, -549, -587, -79, -699, +343, -637, 671, -392, 773, -26, 601, 370, +283, 690, -49, 833, -359, 741, -575, 455, +-605, 79, -450, -286, -197, -579, 69, -721, +233, -636, 245, -355, 169, -2, 9, 335, +-201, 606, -324, 709, -290, 587, -205, 297, +-140, -52, -38, -375, 95, -559, 124, -539, +19, -355, -110, -56, -173, 301, -183, 562, +-181, 605, -111, 466, 25, 184, 113, -183, +72, -478, -47, -566, -155, -464, -222, -213, +-274, 155, -312, 497, -294, 656, -202, 595, +-81, 358, 35, 12, 159, -321, 235, -541, +202, -586, 68, -432, -105, -118, -271, 239, +-367, 512, -334, 611, -214, 523, -106, 304, +-60, 12, -66, -271, -105, -440, -161, -436, +-231, -308, -245, -100, -162, 146, -19, 330, +125, 373, 246, 304, 317, 175, 252, 31, +44, -65, -212, -83, -447, -51, -631, -20, +-704, -9, -625, -24, -410, -73, -135, -145, +133, -167, 354, -73, 482, 94, 471, 252, +324, 395, 110, 489, -130, 421, -355, 188, +-505, -119, -561, -413, -568, -619, -532, -626, +-426, -403, -247, -54, -37, 319, 176, 624, +354, 734, 418, 607, 331, 347, 146, 44, +-46, -259, -239, -476, -425, -504, -520, -366, +-482, -164, -378, 51, -256, 244, -120, 329, +-5, 262, 28, 112, -41, -32, -133, -102, +-177, -65, -126, 76, -17, 253, 97, 388, +191, 415, 195, 275, 38, -31, -235, -412, +-490, -716, -623, -796, -618, -593, -504, -187, +-290, 319, -28, 809, 207, 1091, 326, 987, +304, 576, 174, 78, -17, -377, -224, -730, +-392, -860, -438, -671, -343, -264, -179, 150, +-55, 409, -11, 483, -69, 391, -237, 164, +-444, -113, -534, -264, -444, -185, -191, 57, +186, 356, 536, 619, 682, 698, 551, 464, +183, 15, -355, -465, -914, -878, -1279, -1137, +-1299, -1033, -963, -519, -352, 182, 354, 832, +935, 1318, 1212, 1486, 1089, 1185, 602, 520, +-108, -234, -815, -861, -1306, -1232, -1443, -1221, +-1207, -848, -699, -272, -91, 324, 430, 765, +723, 919, 756, 764, 579, 410, 261, 11, +-103, -283, -411, -384, -566, -281, -567, -47, +-493, 197, -422, 324, -369, 290, -331, 117, +-317, -149, -296, -400, -207, -497, -26, -396, +215, -149, 441, 180, 528, 491, 429, 668, +168, 638, -184, 435, -581, 129, -935, -194, +-1102, -421, -1004, -487, -668, -413, -225, -258, +202, -71, 549, 105, 739, 256, 671, 355, +395, 380, 39, 331, -313, 250, -635, 149, +-842, -8, -857, -204, -711, -345, -460, -399, +-151, -404, 140, -295, 331, -2, 391, 383, +297, 673, 58, 811, -208, 762, -385, 447, +-492, -83, -552, -624, -493, -1002, -298, -1128, +-71, -901, 103, -330, 238, 396, 279, 1031, +136, 1414, -145, 1409, -417, 960, -598, 182, +-673, -646, -621, -1228, -426, -1388, -140, -1105, +132, -478, 303, 285, 349, 890, 306, 1127, +155, 961, -96, 497, -351, -94, -506, -583, +-542, -757, -512, -556, -431, -91, -313, 450, +-214, 856, -152, 919, -99, 573, -61, -56, +-6, -719, 80, -1193, 154, -1303, 168, -963, +135, -230, 54, 654, -105, 1392, -311, 1749, +-522, 1605, -721, 993, -838, 82, -753, -862, +-472, -1542, -125, -1734, 204, -1414, 503, -717, +666, 142, 577, 904, 267, 1335, -108, 1347, +-430, 1017, -679, 471, -801, -108, -735, -523, +-512, -669, -249, -577, -35, -340, 93, -91, +140, 71, 103, 105, -15, 34, -157, -65, +-223, -93, -185, 11, -125, 187, -57, 353, +42, 491, 114, 552, 31, 430, -206, 137, +-450, -202, -599, -476, -691, -638, -702, -643, +-511, -447, -143, -99, 225, 279, 476, 569, +630, 707, 626, 672, 372, 494, -94, 199, +-592, -141, -945, -424, -1046, -571, -893, -562, +-558, -409, -126, -128, 279, 201, 530, 473, +575, 600, 439, 545, 139, 337, -241, 87, +-576, -136, -761, -322, -752, -430, -537, -380, +-145, -193, 253, 33, 460, 245, 403, 391, +135, 403, -233, 270, -556, 77, -700, -115, +-620, -254, -384, -279, -62, -154, 265, 69, +466, 271, 451, 368, 213, 349, -186, 223, +-635, -27, -953, -323, -985, -515, -685, -502, +-137, -322, 457, -23, 857, 375, 962, 740, +749, 861, 218, 692, -482, 366, -1080, -36, +-1392, -484, -1405, -844, -1114, -928, -515, -731, +267, -360, 961, 118, 1325, 612, 1295, 938, +929, 992, 307, 819, -428, 487, -1048, 54, +-1380, -380, -1394, -687, -1176, -829, -780, -785, +-273, -557, 231, -192, 619, 213, 841, 551, +901, 755, 783, 809, 491, 696, 111, 417, +-274, 60, -642, -272, -933, -513, -1059, -638, +-997, -611, -795, -420, -490, -122, -106, 188, +305, 431, 637, 539, 781, 485, 717, 320, +502, 133, 183, -18, -191, -145, -499, -206, +-665, -149, -702, -29, -647, 33, -504, 39, +-334, 44, -190, 35, -57, -43, 66, -149, +154, -151, 200, -22, 221, 147, 208, 276, +170, 377, 108, 412, -13, 303, -200, 78, +-379, -152, -500, -350, -553, -481, -512, -440, +-357, -218, -126, 76, 74, 341, 195, 528, +245, 548, 219, 370, 92, 79, -97, -192, +-255, -362, -315, -387, -287, -276, -198, -71, +-63, 188, 65, 394, 136, 445, 113, 342, +24, 157, -99, -75, -263, -302, -452, -426, +-561, -375, -533, -175, -404, 88, -164, 324, +178, 457, 472, 457, 580, 326, 523, 101, +350, -151, 90, -328, -199, -367, -419, -262, +-568, -50, -677, 218, -716, 424, -643, 424, +-447, 212, -180, -82, 106, -333, 383, -476, +611, -440, 706, -185, 639, 222, 451, 595, +185, 775, -173, 723, -575, 474, -884, 50, +-1012, -462, -957, -828, -751, -892, -383, -694, +78, -309, 494, 219, 779, 701, 918, 913, +846, 805, 542, 494, 92, 102, -381, -274, +-759, -522, -940, -535, -871, -305, -613, 31, +-280, 295, 20, 397, 224, 335, 307, 86, +300, -287, 241, -579, 140, -611, 17, -359, +-53, 81, -29, 580, 4, 985, -26, 1136, +-87, 915, -146, 379, -280, -296, -457, -898, +-511, -1269, -387, -1283, -196, -916, -9, -281, +198, 433, 403, 1021, 490, 1306, 405, 1225, +227, 855, 6, 324, -256, -217, -515, -649, +-651, -883, -619, -869, -436, -631, -137, -282, +175, 57, 391, 336, 489, 509, 476, 543, +308, 472, -11, 363, -370, 220, -620, 63, +-693, -77, -578, -202, -292, -303, 113, -314, +494, -227, 682, -96, 635, 48, 392, 194, +-14, 300, -485, 286, -807, 153, -885, -8, +-751, -106, -416, -158, 104, -175, 632, -92, +933, 119, 912, 332, 603, 399, 91, 316, +-498, 145, -952, -96, -1102, -364, -925, -501, +-504, -412, 44, -179, 565, 89, 907, 378, +967, 609, 723, 613, 249, 371, -298, 37, +-745, -270, -975, -517, -919, -593, -610, -407, +-174, -21, 240, 387, 541, 667, 651, 720, +543, 517, 308, 115, 62, -355, -154, -710, +-307, -810, -352, -627, -301, -217, -226, 314, +-187, 790, -175, 1026, -171, 931, -159, 564, +-131, 31, -64, -533, 76, -932, 275, -1011, +451, -761, 513, -320, 447, 178, 261, 643, +-53, 960, -442, 985, -754, 701, -897, 251, +-833, -203, -565, -571, -152, -774, 309, -724, +695, -445, 919, -68, 910, 281, 653, 537, +208, 622, -297, 511, -717, 279, -918, 22, +-860, -207, -570, -338, -154, -325, 222, -203, +450, -26, 519, 148, 439, 250, 203, 231, +-102, 126, -341, 2, -432, -93, -373, -132, +-188, -97, 110, -3, 442, 115, 614, 224, +490, 278, 138, 243, -278, 114, -639, -66, +-888, -250, -904, -371, -621, -369, -136, -212, +359, 37, 742, 294, 982, 502, 997, 596, +682, 510, 120, 239, -431, -128, -811, -466, +-996, -653, -950, -637, -631, -427, -179, -66, +218, 379, 499, 742, 660, 853, 643, 691, +408, 341, 67, -90, -219, -504, -406, -775, +-496, -797, -416, -542, -156, -117, 137, 321, +300, 661, 325, 828, 244, 725, 40, 372, +-241, -40, -452, -357, -518, -543, -484, -553, +-330, -338, -20, -20, 349, 229, 604, 342, +671, 332, 563, 202, 293, -16, -80, -205, +-416, -235, -608, -75, -646, 167, -545, 370, +-356, 462, -142, 405, 60, 171, 232, -189, +337, -526, 333, -678, 241, -594, 140, -332, +71, 43, 30, 459, 22, 775, 39, 850, +18, 687, -119, 348, -330, -103, -520, -536, +-613, -765, -566, -739, -345, -511, 13, -138, +392, 283, 679, 596, 794, 703, 684, 611, +375, 369, -12, 56, -382, -256, -685, -486, +-827, -557, -706, -446, -403, -202, -89, 102, +184, 382, 428, 558, 538, 592, 403, 480, +135, 243, -85, -80, -229, -388, -322, -591, +-291, -653, -113, -541, 114, -243, 242, 145, +228, 503, 105, 762, -98, 846, -316, 678, +-463, 277, -456, -184, -300, -549, -61, -752, +194, -760, 408, -517, 497, -70, 435, 387, +248, 664, -28, 700, -320, 516, -528, 172, +-595, -232, -518, -547, -287, -615, 21, -398, +293, 2, 473, 424, 534, 742, 416, 847, +120, 651, -224, 183, -487, -402, -637, -911, +-642, -1156, -453, -1024, -115, -570, 249, 71, +522, 742, 647, 1252, 602, 1408, 398, 1164, +74, 614, -302, -76, -619, -710, -767, -1108, +-730, -1194, -571, -993, -303, -559, 55, -23, +380, 447, 546, 723, 604, 807, 598, 748, +453, 584, 155, 357, -168, 120, -406, -100, +-562, -284, -651, -427, -646, -541, -508, -575, +-267, -481, -14, -278, 196, -22, 398, 277, +569, 581, 603, 762, 457, 721, 209, 502, +-59, 167, -325, -236, -542, -574, -637, -715, +-565, -611, -388, -322, -185, 52, 33, 396, +260, 618, 396, 649, 361, 459, 197, 122, +16, -210, -127, -438, -246, -543, -279, -474, +-171, -224, -7, 103, 80, 348, 84, 454, +57, 449, -24, 350, -156, 164, -257, -34, +-292, -143, -266, -151, -166, -121, -17, -99, +114, -88, 179, -107, 183, -169, 126, -242, +39, -245, -38, -116, -90, 123, -119, 388, +-115, 632, -86, 780, -81, 705, -111, 388, +-149, -61, -180, -511, -232, -873, -273, -1019, +-230, -864, -78, -456, 112, 76, 282, 589, +395, 936, 387, 1014, 243, 797, 20, 358, +-205, -124, -390, -475, -472, -616, -440, -545, +-332, -272, -210, 79, -91, 316, 16, 351, +88, 208, 110, -58, 98, -348, 112, -510, +150, -444, 186, -158, 209, 249, 202, 657, +94, 927, -128, 934, -385, 627, -597, 98, +-715, -467, -671, -909, -448, -1116, -123, -1007, +233, -600, 554, -22, 746, 548, 732, 934, +527, 1047, 186, 862, -219, 452, -587, -22, +-803, -404, -810, -601, -643, -583, -368, -382, +-37, -104, 271, 133, 451, 245, 474, 221, +368, 83, 183, -54, -25, -97, -204, -65, +-312, 31, -331, 205, -265, 362, -158, 358, +-68, 194, -8, -22, 29, -231, 12, -407, +-54, -443, -129, -283, -157, -2, -147, 274, +-116, 456, -46, 499, 63, 372, 148, 92, +150, -232, 108, -470, 43, -540, -80, -417, +-254, -140, -367, 219, -374, 524, -308, 657, +-182, 587, 16, 351, 207, 7, 279, -340, +237, -565, 124, -595, -37, -438, -218, -169, +-340, 122, -362, 344, -290, 454, -143, 426, +40, 258, 179, 32, 226, -129, 185, -172, +53, -127, -159, -28, -356, 91, -406, 176, +-304, 167, -134, 57, 39, -115, 188, -265, +269, -327, 222, -283, 51, -137, -153, 73, +-303, 280, -384, 413, -389, 443, -282, 357, +-68, 178, 157, -17, 295, -149, 311, -211, +214, -229, 30, -188, -184, -105, -360, -55, +-424, -73, -371, -109, -278, -106, -176, -57, +-42, 49, 114, 207, 209, 369, 251, 480, +261, 499, 199, 394, 44, 160, -125, -142, +-234, -420, -325, -622, -417, -697, -452, -600, +-380, -349, -251, -10, -96, 349, 90, 619, +305, 717, 451, 646, 466, 461, 365, 202, +170, -76, -84, -279, -355, -373, -570, -391, +-680, -358, -646, -287, -476, -209, -206, -138, +84, -61, 318, 63, 454, 224, 490, 374, +422, 485, 248, 536, 29, 483, -193, 280, +-395, -30, -529, -330, -547, -534, -469, -629, +-331, -576, -133, -364, 79, -58, 227, 231, +301, 422, 312, 507, 243, 485, 92, 364, +-72, 174, -189, -22, -259, -158, -272, -199, +-227, -189, -159, -175, -129, -161, -137, -118, +-130, -62, -88, -50, -39, -39, 4, 46, +53, 174, 93, 251, 109, 265, 85, 249, +40, 192, -25, 62, -104, -94, -193, -211, +-266, -263, -301, -245, -291, -177, -223, -76, +-108, 48, 28, 161, 138, 215, 232, 193, +264, 139, 199, 106, 42, 70, -144, 16, +-308, -27, -418, -44, -424, -57, -327, -97, +-166, -133, 4, -128, 161, -96, 274, -37, +311, 78, 259, 213, 126, 285, -76, 253, +-302, 156, -465, 30, -495, -121, -403, -259, +-235, -309, -15, -218, 198, -34, 318, 129, +311, 215, 216, 249, 83, 229, -76, 123, +-219, -43, -287, -161, -275, -170, -225, -112, +-159, -28, -93, 57, -82, 116, -142, 113, +-179, 40, -112, -60, 32, -118, 198, -89, +355, 22, 428, 146, 334, 245, 89, 293, +-218, 214, -522, -8, -771, -271, -846, -458, +-672, -517, -296, -419, 154, -145, 595, 251, +906, 620, 944, 829, 654, 805, 141, 540, +-400, 93, -825, -438, -1028, -884, -954, -1089, +-617, -985, -147, -603, 317, -41, 635, 551, +723, 1018, 570, 1213, 252, 1075, -109, 657, +-399, 109, -503, -408, -412, -808, -218, -994, +-31, -913, 89, -646, 90, -310, -33, 34, +-200, 343, -301, 572, -283, 683, -150, 691, +81, 621, 341, 476, 518, 255, 506, -37, +282, -337, -97, -577, -506, -744, -793, -808, +-861, -698, -689, -417, -321, -43, 148, 341, +573, 676, 810, 900, 797, 934, 547, 769, +138, 455, -322, 62, -717, -341, -905, -683, +-808, -880, -486, -870, -93, -676, 259, -369, +513, -18, 599, 323, 475, 610, 214, 756, +-45, 713, -247, 540, -384, 319, -455, 78, +-409, -177, -251, -398, -61, -507, 66, -494, +136, -415, 190, -311, 193, -156, 130, 58, +36, 240, -43, 337, -149, 390, -261, 398, +-329, 296, -303, 111, -196, -45, -34, -121, +149, -170, 286, -198, 338, -148, 281, -34, +131, 55, -85, 48, -310, -13, -497, -61, +-603, -117, -570, -203, -357, -255, 1, -186, +384, 23, 659, 293, 737, 539, 604, 706, +302, 730, -92, 546, -486, 130, -774, -419, +-882, -924, -795, -1235, -527, -1250, -143, -926, +260, -309, 600, 461, 813, 1176, 838, 1609, +643, 1640, 279, 1264, -147, 568, -546, -297, +-843, -1107, -959, -1627, -845, -1741, -530, -1453, +-97, -824, 319, -4, 614, 795, 753, 1364, +726, 1582, 534, 1459, 220, 1044, -121, 419, +-444, -256, -688, -791, -774, -1086, -649, -1176, +-388, -1092, -91, -811, 195, -383, 404, 70, +477, 465, 415, 776, 311, 999, 176, 1094, +7, 995, -165, 676, -283, 216, -364, -264, +-409, -716, -375, -1110, -273, -1301, -152, -1168, +-28, -776, 130, -256, 277, 320, 353, 880, +356, 1270, 313, 1375, 191, 1202, -31, 797, +-270, 221, -427, -416, -486, -972, -477, -1309, +-377, -1365, -178, -1161, 52, -723, 237, -101, +347, 564, 396, 1072, 389, 1325, 313, 1344, +146, 1110, -72, 602, -254, -69, -394, -695, +-525, -1122, -591, -1324, -488, -1299, -246, -986, +23, -390, 294, 324, 560, 915, 711, 1276, +629, 1418, 368, 1267, 49, 751, -302, 18, +-671, -672, -903, -1161, -853, -1406, -566, -1358, +-154, -967, 299, -332, 709, 360, 908, 959, +802, 1365, 441, 1481, -8, 1246, -397, 720, +-677, 42, -805, -660, -721, -1241, -434, -1539, +-87, -1478, 232, -1080, 475, -443, 607, 296, +562, 969, 345, 1435, 63, 1619, -163, 1455, +-291, 944, -388, 237, -445, -479, -397, -1105, +-249, -1555, -104, -1691, 11, -1416, 140, -817, +275, -80, 346, 660, 316, 1291, 219, 1672, +104, 1681, -29, 1292, -194, 652, -349, -58, +-406, -732, -325, -1280, -167, -1588, -13, -1538, +118, -1157, 204, -574, 188, 102, 66, 764, +-44, 1278, -59, 1517, -51, 1420, -47, 1035, +22, 471, 147, -165, 217, -750, 174, -1172, +51, -1338, -144, -1222, -381, -885, -551, -394, +-526, 176, -307, 720, -3, 1114, 295, 1260, +508, 1144, 562, 815, 442, 309, 247, -289, +41, -829, -162, -1154, -340, -1204, -424, -1003, +-410, -572, -347, 17, -232, 591, -79, 986, +59, 1134, 119, 1039, 147, 718, 186, 202, +256, -352, 316, -762, 334, -966, 265, -982, +90, -787, -145, -382, -383, 98, -543, 506, +-575, 803, -462, 944, -258, 858, 5, 587, +298, 213, 523, -211, 578, -620, 466, -891, +253, -931, -21, -773, -280, -469, -395, -55, +-322, 391, -165, 765, -49, 967, -1, 948, +-6, 724, -61, 343, -139, -114, -145, -565, +-45, -914, 93, -1044, 211, -905, 313, -558, +378, -97, 324, 396, 125, 822, -151, 1050, +-396, 986, -530, 668, -519, 207, -343, -277, +-38, -685, 283, -937, 471, -935, 471, -661, +341, -232, 141, 209, -90, 586, -317, 847, +-452, 891, -437, 662, -258, 263, 1, -172, +248, -558, 408, -818, 437, -873, 339, -677, +125, -283, -134, 174, -332, 569, -373, 834, +-322, 922, -260, 780, -189, 394, -62, -84, +68, -489, 149, -785, 227, -943, 347, -874, +457, -556, 445, -127, 312, 271, 94, 602, +-193, 831, -538, 888, -818, 773, -876, 518, +-680, 178, -296, -179, 194, -502, 693, -759, +1044, -921, 1113, -926, 873, -741, 395, -412, +-198, 4, -758, 464, -1119, 902, -1170, 1221, +-882, 1298, -331, 1083, 309, 636, 835, 30, +1082, -660, 1002, -1284, 617, -1637, 26, -1615, +-568, -1250, -938, -597, -960, 256, -672, 1096, +-187, 1703, 365, 1930, 827, 1720, 1017, 1130, +842, 274, 380, -683, -165, -1505, -618, -1950, +-917, -1922, -997, -1485, -805, -733, -359, 209, +168, 1097, 601, 1706, 859, 1903, 935, 1654, +799, 1056, 456, 274, 70, -548, -221, -1259, +-416, -1651, -592, -1610, -702, -1233, -696, -664, +-595, 27, -443, 725, -198, 1250, 165, 1468, +547, 1361, 837, 993, 981, 433, 986, -226, +831, -834, 489, -1240, -46, -1364, -683, -1200, +-1204, -787, -1421, -194, -1303, 448, -909, 1013, +-285, 1376, 440, 1408, 1010, 1091, 1239, 524, +1157, -174, 906, -885, 558, -1434, 136, -1602, +-273, -1296, -524, -649, -590, 140, -583, 913, +-588, 1507, -578, 1708, -521, 1381, -455, 655, +-354, -205, -95, -980, 366, -1514, 886, -1656, +1263, -1318, 1415, -608, 1278, 214, 789, 934, +7, 1415, -847, 1533, -1538, 1230, -1905, 605, +-1842, -96, -1325, -679, -435, -1080, 607, -1243, +1526, -1108, 2020, -701, 1961, -184, 1413, 247, +549, 559, -409, 799, -1195, 935, -1558, 884, +-1450, 649, -1000, 345, -416, 52, 185, -272, +676, -645, 922, -962, 860, -1072, 594, -941, +267, -656, -50, -237, -316, 334, -483, 926, +-483, 1311, -335, 1362, -124, 1115, 69, 649, +241, 11, 391, -672, 466, -1198, 425, -1423, +272, -1303, 35, -908, -258, -348, -553, 267, +-767, 809, -821, 1167, -665, 1243, -291, 1042, +263, 680, 859, 241, 1304, -256, 1443, -725, +1229, -1027, 695, -1093, -82, -969, -935, -687, +-1634, -233, -1951, 303, -1776, 770, -1133, 1053, +-153, 1123, 918, 987, 1772, 643, 2157, 118, +2006, -465, 1382, -939, 440, -1175, -583, -1155, +-1412, -904, -1855, -425, -1876, 195, -1493, 770, +-786, 1123, 106, 1201, 930, 1042, 1469, 666, +1606, 111, 1385, -480, 937, -916, 371, -1098, +-231, -1046, -767, -798, -1098, -367, -1207, 134, +-1142, 540, -905, 785, -432, 880, 187, 822, +744, 619, 1108, 332, 1306, 18, 1347, -301, +1105, -566, 534, -721, -222, -785, -945, -751, +-1531, -569, -1876, -226, -1795, 184, -1191, 546, +-216, 825, 836, 997, 1730, 958, 2301, 658, +2383, 208, 1858, -233, 811, -613, -464, -916, +-1649, -1037, -2491, -904, -2777, -571, -2374, -134, +-1378, 321, -80, 713, 1194, 961, 2193, 987, +2746, 762, 2716, 351, 2079, -96, 989, -451, +-282, -690, -1470, -768, -2363, -630, -2758, -331, +-2545, -18, -1786, 205, -703, 337, 457, 393, +1501, 349, 2285, 221, 2664, 84, 2527, 3, +1877, -8, 818, -26, -429, -77, -1619, -96, +-2499, -63, -2874, -61, -2616, -120, -1768, -145, +-555, -82, 762, -13, 1934, 21, 2745, 66, +2968, 133, 2517, 188, 1474, 178, 102, 111, +-1280, 27, -2345, -56, -2842, -128, -2666, -170, +-1888, -163, -740, -100, 506, -9, 1595, 80, +2341, 151, 2568, 184, 2196, 175, 1324, 105, +214, -26, -871, -147, -1742, -192, -2211, -182, +-2138, -169, -1574, -131, -736, 3, 165, 163, +1007, 210, 1678, 175, 2031, 168, 1942, 181, +1412, 117, 561, -7, -412, -76, -1306, -78, +-1936, -105, -2130, -186, -1823, -274, -1090, -297, +-132, -238, 850, -138, 1700, -5, 2241, 182, +2302, 422, 1808, 618, 862, 646, -323, 504, +-1491, 265, -2370, -59, -2705, -466, -2368, -840, +-1435, -1005, -138, -909, 1190, -619, 2263, -165, +2857, 396, 2844, 918, 2156, 1215, 912, 1189, +-578, 886, -1950, 411, -2907, -163, -3236, -745, +-2786, -1154, -1618, -1228, -29, -986, 1537, -574, +2744, -90, 3359, 392, 3233, 769, 2318, 943, +822, 888, -837, 675, -2273, 403, -3219, 117, +-3468, -178, -2866, -456, -1549, -651, 88, -728, +1644, -706, 2843, -583, 3429, -343, 3208, 6, +2223, 392, 773, 702, -787, 878, -2158, 900, +-3058, 726, -3248, 351, -2675, -133, -1527, -590, +-112, -906, 1280, -1025, 2377, -912, 2960, -572, +2919, -67, 2264, 476, 1148, 882, -179, 1041, +-1438, 956, -2400, 656, -2877, 179, -2740, -363, +-2021, -797, -896, -978, 396, -905, 1634, -640, +2590, -237, 3035, 241, 2828, 669, 1987, 889, +679, 862, -821, 665, -2171, 341, -3051, -85, +-3229, -519, -2668, -825, -1489, -904, 24, -769, +1551, -472, 2763, -49, 3368, 416, 3187, 806, +2229, 993, 734, 917, -922, 629, -2311, 193, +-3132, -323, -3216, -789, -2563, -1058, -1324, -1032, +171, -751, 1582, -321, 2630, 181, 3091, 663, +2867, 1000, 2005, 1084, 702, 898, -757, 535, +-2022, 99, -2802, -375, -2956, -804, -2475, -1055, +-1458, -1052, -129, -839, 1235, -467, 2367, 33, +3025, 548, 3015, 940, 2301, 1148, 1052, 1120, +-452, 827, -1892, 355, -2923, -171, -3263, -679, +-2832, -1088, -1764, -1247, -301, -1103, 1249, -750, +2527, -273, 3237, 285, 3218, 839, 2466, 1234, +1135, 1341, -443, 1145, -1874, 730, -2851, 173, +-3172, -469, -2781, -1064, -1798, -1412, -499, -1421, +847, -1152, 2019, -663, 2800, 2, 3011, 730, +2590, 1334, 1658, 1652, 389, 1625, -976, 1269, +-2181, 597, -2938, -313, -3084, -1238, -2623, -1897, +-1640, -2119, -252, -1869, 1339, -1158, 2731, -74, +3538, 1129, 3552, 2102, 2788, 2564, 1349, 2400, +-517, 1655, -2355, 466, -3614, -913, -3973, -2115, +-3427, -2791, -2108, -2752, -238, -2051, 1767, -859, +3342, 574, 4077, 1898, 3826, 2737, 2677, 2861, +883, 2288, -1110, 1223, -2773, -105, -3689, -1410, +-3688, -2343, -2825, -2650, -1326, -2320, 428, -1521, +2003, -434, 3042, 738, 3345, 1709, 2889, 2236, +1801, 2232, 360, 1748, -1096, 934, -2234, -36, +-2812, -973, -2760, -1688, -2136, -2024, -1094, -1895, +170, -1374, 1406, -614, 2342, 270, 2771, 1142, +2636, 1780, 1986, 2001, 854, 1791, -577, 1229, +-1911, 366, -2773, -649, -3037, -1524, -2687, -2043, +-1690, -2153, -196, -1822, 1417, -1015, 2712, 124, +3429, 1250, 3412, 2073, 2605, 2469, 1116, 2351, +-692, 1660, -2350, 502, -3470, -819, -3804, -1937, +-3279, -2613, -1976, -2746, -189, -2286, 1660, -1250, +3125, 151, 3917, 1524, 3874, 2516, 2974, 2975, +1370, 2820, -549, 2011, -2301, 688, -3522, -803, +-3997, -2081, -3637, -2907, -2464, -3128, -736, -2656, +1138, -1552, 2760, -79, 3847, 1381, 4164, 2499, +3563, 3105, 2138, 3059, 222, 2288, -1750, 974, +-3339, -495, -4182, -1791, -4074, -2736, -3043, -3126, +-1325, -2784, 690, -1778, 2541, -413, 3807, 987, +4216, 2155, 3698, 2881, 2353, 2969, 470, 2343, +-1497, 1175, -3039, -189, -3806, -1426, -3700, -2357, +-2797, -2831, -1321, -2672, 409, -1860, 1996, -659, +3088, 579, 3492, 1669, 3184, 2505, 2231, 2849, +798, 2505, -782, 1581, -2132, 357, -2986, -936, +-3215, -2123, -2761, -2949, -1722, -3123, -325, -2518, +1140, -1294, 2401, 220, 3208, 1732, 3368, 2993, +2767, 3643, 1467, 3348, -205, 2165, -1829, 490, +-3030, -1294, -3570, -2906, -3275, -3941, -2180, -3963, +-539, -2900, 1220, -1141, 2699, 826, 3615, 2628, +3742, 3904, 2966, 4239, 1412, 3412, -480, 1705, +-2197, -298, -3343, -2128, -3699, -3510, -3204, -4112, +-1969, -3633, -282, -2187, 1443, -337, 2799, 1402, +3529, 2785, 3532, 3600, 2764, 3571, 1316, 2629, +-461, 1117, -2066, -473, -3119, -1843, -3464, -2854, +-3065, -3315, -1993, -3002, -478, -1953, 1112, -567, +2442, 804, 3293, 2035, 3479, 2958, 2888, 3239, +1601, 2710, -57, 1587, -1668, 201, -2865, -1244, +-3414, -2524, -3197, -3305, -2251, -3288, -800, -2446, +813, -1064, 2245, 513, 3213, 2020, 3507, 3166, +3024, 3588, 1819, 3061, 163, 1770, -1527, 135, +-2806, -1506, -3432, -2886, -3303, -3638, -2410, -3430, +-897, -2321, 854, -729, 2375, 957, 3365, 2488, +3637, 3519, 3089, 3673, 1740, 2856, -83, 1369, +-1881, -369, -3169, -2020, -3675, -3289, -3327, -3833, +-2182, -3407, -477, -2092, 1363, -314, 2854, 1469, +3666, 2959, 3668, 3879, 2843, 3906, 1308, 2909, +-573, 1193, -2272, -724, -3359, -2460, -3663, -3757, +-3153, -4257, -1907, -3695, -205, -2199, 1493, -234, +2793, 1736, 3503, 3371, 3522, 4320, 2801, 4270, +1427, 3157, -272, 1304, -1855, -781, -2985, -2663, +-3501, -4008, -3327, -4479, -2414, -3857, -907, -2288, +808, -260, 2326, 1718, 3383, 3318, 3787, 4241, +3377, 4178, 2166, 3067, 434, 1266, -1389, -688, +-2867, -2416, -3680, -3656, -3676, -4090, -2852, -3506, +-1343, -2077, 513, -276, 2216, 1446, 3370, 2838, +3770, 3646, 3380, 3592, 2207, 2656, 482, 1174, +-1325, -456, -2705, -1963, -3371, -3080, -3295, -3500, +-2500, -3089, -1119, -1978, 521, -458, 1965, 1123, +2897, 2483, 3203, 3351, 2868, 3461, 1896, 2711, +458, 1319, -1048, -343, -2217, -1970, -2879, -3249, +-2950, -3789, -2348, -3370, -1166, -2115, 280, -358, +1628, 1506, 2639, 3083, 3124, 3968, 2971, 3889, +2135, 2836, 737, 1083, -882, -931, -2283, -2747, +-3144, -3954, -3316, -4230, -2705, -3474, -1384, -1877, +323, 161, 1940, 2166, 3072, 3681, 3531, 4331, +3242, 3947, 2191, 2644, 557, 749, -1205, -1328, +-2598, -3116, -3359, -4171, -3369, -4242, -2580, -3345, +-1144, -1695, 549, 349, 2019, 2310, 2950, 3734, +3223, 4320, 2848, 3925, 1865, 2600, 475, 658, +-952, -1426, -2085, -3188, -2731, -4219, -2809, -4244, +-2258, -3256, -1210, -1545, 61, 507, 1247, 2467, +2162, 3848, 2679, 4279, 2666, 3701, 2077, 2318, +1034, 439, -225, -1554, -1450, -3190, -2372, -4064, +-2775, -4005, -2577, -3076, -1786, -1490, -499, 460, +948, 2355, 2178, 3706, 2947, 4185, 3118, 3742, +2548, 2514, 1300, 700, -277, -1383, -1805, -3193, +-2929, -4218, -3352, -4265, -2927, -3419, -1785, -1831, +-191, 287, 1500, 2431, 2839, 3960, 3485, 4524, +3317, 4120, 2396, 2843, 913, 840, -786, -1477, +-2269, -3435, -3188, -4498, -3346, -4521, -2744, -3607, +-1557, -1901, -53, 361, 1455, 2615, 2656, 4148, +3278, 4616, 3199, 4106, 2460, 2765, 1213, 717, +-298, -1589, -1768, -3439, -2834, -4360, -3264, -4330, +-2986, -3442, -2101, -1766, -771, 424, 779, 2520, +2212, 3908, 3166, 4358, 3421, 3940, 2968, 2693, +1858, 704, 262, -1541, -1420, -3353, -2696, -4297, +-3305, -4308, -3197, -3407, -2380, -1666, -984, 591, +640, 2740, 2094, 4131, 3041, 4464, 3271, 3826, +2753, 2355, 1623, 213, 142, -2068, -1369, -3718, +-2483, -4313, -2931, -3969, -2683, -2835, -1873, -981, +-644, 1209, 765, 3006, 1960, 3900, 2613, 3890, +2641, 3137, 2147, 1684, 1192, -256, -102, -2105, +-1364, -3299, -2185, -3655, -2430, -3282, -2194, -2269, +-1509, -699, -414, 1095, 828, 2552, 1849, 3266, +2404, 3260, 2429, 2686, 1938, 1526, 993, -110, +-217, -1720, -1396, -2789, -2216, -3185, -2501, -3018, +-2215, -2264, -1432, -870, -301, 862, 951, 2349, +2007, 3188, 2590, 3386, 2567, 2949, 2013, 1717, +1010, -152, -306, -1999, -1615, -3253, -2517, -3786, +-2786, -3573, -2429, -2447, -1535, -511, -245, 1619, +1171, 3256, 2346, 4066, 2943, 3990, 2829, 2993, +2117, 1167, 955, -1034, -475, -2921, -1874, -4010, +-2809, -4170, -3051, -3449, -2611, -1906, -1611, 179, +-210, 2184, 1337, 3517, 2600, 4005, 3200, 3710, +3009, 2619, 2208, 836, 975, -1150, -535, -2708, +-1987, -3543, -2938, -3670, -3149, -3081, -2683, -1759, +-1691, 15, -316, 1666, 1217, 2766, 2523, 3263, +3198, 3155, 3127, 2342, 2432, 939, 1218, -609, +-349, -1843, -1875, -2602, -2911, -2882, -3263, -2577, +-2917, -1627, -1928, -292, -484, 965, 1112, 1872, +2470, 2404, 3253, 2462, 3252, 1898, 2529, 853, +1278, -284, -280, -1201, -1821, -1830, -2919, -2122, +-3264, -1913, -2866, -1180, -1880, -212, -470, 620, +1106, 1218, 2435, 1640, 3127, 1767, 3057, 1410, +2339, 689, 1145, -59, -322, -680, -1764, -1246, +-2756, -1666, -3019, -1656, -2605, -1174, -1714, -503, +-463, 157, 1010, 868, 2287, 1572, 2979, 1934, +2935, 1738, 2280, 1137, 1163, 351, -263, -543, +-1731, -1477, -2839, -2163, -3202, -2270, -2772, -1769, +-1749, -909, -336, 88, 1250, 1163, 2618, 2113, +3334, 2537, 3210, 2261, 2326, 1513, 922, 545, +-698, -580, -2212, -1708, -3246, -2457, -3476, -2557, +-2833, -2092, -1540, -1284, 66, -244, 1688, 940, +2965, 1980, 3535, 2527, 3202, 2472, 2140, 1963, +699, 1108, -881, -62, -2347, -1316, -3305, -2233, +-3421, -2560, -2767, -2363, -1574, -1752, -28, -742, +1600, 534, 2875, 1683, 3420, 2369, 3164, 2505, +2264, 2137, 934, 1309, -623, 130, -2121, -1106, +-3140, -2039, -3381, -2422, -2863, -2263, -1761, -1681, +-270, -709, 1358, 525, 2684, 1616, 3335, 2217, +3164, 2313, 2286, 1990, 924, 1191, -632, -3, +-2016, -1190, -2930, -2032, -3155, -2415, -2632, -2298, +-1465, -1647, 21, -555, 1434, 716, 2477, 1812, +2923, 2455, 2637, 2540, 1692, 2095, 403, 1137, +-871, -191, -1900, -1466, -2504, -2313, -2516, -2656, +-1906, -2505, -876, -1751, 280, -472, 1385, 895, +2232, 1954, 2551, 2606, 2191, 2775, 1284, 2288, +111, 1181, -1082, -187, -2051, -1458, -2592, -2433, +-2508, -2914, -1772, -2729, -583, -1872, 732, -557, +1928, 889, 2812, 2155, 3043, 2974, 2355, 3122, +936, 2490, -641, 1199, -1957, -407, -2889, -1937, +-3233, -3061, -2701, -3480, -1382, -3009, 211, -1721, +1635, 22, 2721, 1790, 3267, 3183, 3024, 3808, +1926, 3419, 291, 2090, -1294, 204, -2404, -1752, +-2951, -3289, -2942, -3991, -2209, -3654, -859, -2365, +586, -442, 1683, 1595, 2393, 3204, 2697, 3984, +2361, 3741, 1356, 2537, 61, 719, -1061, -1196, +-1826, -2788, -2224, -3727, -2153, -3742, -1519, -2826, +-518, -1279, 457, 517, 1195, 2188, 1716, 3344, +1916, 3677, 1579, 3148, 743, 1933, -213, 252, +-945, -1548, -1425, -2989, -1608, -3659, -1351, -3450, +-647, -2480, 157, -894, 767, 987, 1190, 2614, +1429, 3547, 1300, 3631, 672, 2843, -188, 1290, +-908, -641, -1319, -2363, -1412, -3434, -1134, -3624, +-483, -2903, 281, -1444, 853, 408, 1158, 2150, +1251, 3258, 1105, 3464, 631, 2780, -68, 1375, +-710, -424, -1059, -2055, -1095, -3002, -936, -3112, +-584, -2444, -79, -1158, 390, 414, 611, 1795, +635, 2597, 639, 2666, 602, 2037, 404, 903, +61, -408, -220, -1509, -319, -2098, -314, -2092, +-331, -1572, -351, -680, -270, 337, -148, 1152, +-131, 1519, -145, 1422, 26, 994, 309, 366, +431, -294, 415, -778, 459, -932, 462, -759, +230, -377, -139, 61, -382, 387, -512, 449, +-628, 251, -651, -86, -422, -408, 34, -564, +465, -452, 715, -71, 800, 441, 765, 906, +486, 1138, -69, 972, -651, 391, -958, -419, +-921, -1190, -679, -1695, -298, -1732, 252, -1155, +870, -105, 1246, 1012, 1148, 1870, 677, 2258, +75, 1994, -539, 1025, -1099, -344, -1417, -1611, +-1209, -2428, -516, -2595, 259, -1993, 819, -730, +1219, 817, 1441, 2158, 1155, 2865, 365, 2710, +-448, 1725, -906, 230, -1111, -1358, -1168, -2595, +-887, -3072, -174, -2588, 641, -1321, 1088, 268, +1106, 1751, 921, 2778, 543, 2983, -136, 2223, +-872, 821, -1162, -697, -884, -1965, -428, -2699, +-66, -2599, 350, -1692, 914, -401, 1198, 871, +878, 1881, 329, 2368, -39, 2110, -392, 1229, +-885, 114, -1076, -891, -743, -1592, -247, -1868, +67, -1672, 277, -1048, 503, -174, 659, 670, +658, 1225, 519, 1428, 383, 1393, 325, 1125, +237, 549, -24, -216, -396, -846, -681, -1201, +-840, -1398, -987, -1418, -1046, -1046, -724, -335, +49, 389, 918, 974, 1563, 1474, 1927, 1758, +1912, 1544, 1368, 895, 314, 83, -927, -768, +-1950, -1570, -2421, -2044, -2299, -1955, -1677, -1388, +-533, -547, 956, 469, 2231, 1485, 2817, 2169, +2696, 2286, 1922, 1830, 561, 920, -1004, -265, +-2249, -1408, -2840, -2199, -2650, -2488, -1737, -2172, +-373, -1247, 1092, 46, 2324, 1311, 2962, 2248, +2780, 2666, 1863, 2393, 464, 1446, -1078, 127, +-2384, -1226, -3057, -2290, -2900, -2762, -1957, -2503, +-490, -1619, 1124, -372, 2517, 969, 3337, 2096, +3352, 2708, 2499, 2623, 977, 1872, -840, 698, +-2473, -595, -3505, -1799, -3664, -2669, -2834, -2862, +-1195, -2213, 728, -998, 2383, 353, 3435, 1617, +3718, 2606, 3131, 2953, 1736, 2411, -124, 1171, +-1906, -331, -3072, -1717, -3398, -2669, -2910, -2892, +-1729, -2298, -86, -1058, 1519, 462, 2514, 1810, +2766, 2599, 2472, 2633, 1768, 1976, 635, 827, +-653, -514, -1602, -1694, -2001, -2379, -1980, -2357, +-1610, -1690, -840, -678, 145, 373, 999, 1270, +1545, 1846, 1802, 1916, 1758, 1488, 1338, 824, +569, 107, -365, -599, -1229, -1167, -1811, -1438, +-1985, -1441, -1646, -1296, -789, -910, 378, -212, +1456, 538, 2122, 1111, 2322, 1561, 2019, 1863, +1157, 1721, -137, 967, -1401, -119, -2185, -1168, +-2367, -1978, -2021, -2403, -1190, -2250, 49, -1368, +1332, 70, 2154, 1499, 2326, 2386, 2027, 2604, +1416, 2242, 510, 1270, -525, -215, -1317, -1656, +-1681, -2427, -1745, -2394, -1622, -1833, -1158, -958, +-307, 156, 595, 1216, 1266, 1784, 1763, 1715, +2112, 1304, 1999, 860, 1324, 381, 339, -193, +-710, -692, -1681, -952, -2316, -1083, -2325, -1256, +-1678, -1300, -545, -938, 751, -269, 1866, 453, +2518, 1163, 2528, 1789, 1849, 2008, 642, 1596, +-716, 691, -1793, -421, -2305, -1440, -2188, -2059, +-1485, -2109, -292, -1593, 1016, -605, 1926, 576, +2280, 1500, 2158, 1845, 1516, 1670, 364, 1124, +-846, 291, -1687, -637, -2089, -1319, -2054, -1493, +-1514, -1189, -525, -665, 630, -117, 1625, 455, +2200, 1010, 2310, 1266, 2000, 1022, 1247, 542, +156, 143, -936, -255, -1745, -798, -2219, -1215, +-2315, -1153, -1911, -761, -996, -365, 241, 47, +1454, 598, 2353, 1099, 2825, 1256, 2738, 1056, +1985, 691, 699, 251, -720, -269, -1950, -837, +-2783, -1282, -2986, -1390, -2408, -1157, -1134, -705, +439, -96, 1861, 629, 2793, 1289, 3065, 1624, +2576, 1509, 1399, 986, -102, 156, -1456, -779, +-2313, -1514, -2524, -1764, -2083, -1420, -1103, -623, +176, 357, 1365, 1207, 2106, 1652, 2292, 1490, +1981, 714, 1164, -368, -13, -1268, -1141, -1655, +-1823, -1480, -2004, -804, -1793, 270, -1145, 1372, +-56, 1958, 1169, 1783, 2038, 1023, 2401, -1, +2339, -1036, 1732, -1815, 468, -2041, -1049, -1593, +-2168, -653, -2669, 375, -2619, 1159, -1919, 1583, +-531, 1629, 1120, 1289, 2406, 627, 2996, -166, +2906, -820, 2193, -1188, 901, -1287, -712, -1174, +-2091, -796, -2781, -157, -2701, 501, -1978, 966, +-753, 1194, 734, 1148, 1992, 777, 2586, 153, +2409, -537, 1684, -1078, 622, -1273, -582, -1038, +-1582, -515, -1999, 126, -1712, 795, -939, 1276, +31, 1306, 955, 880, 1596, 259, 1698, -386, +1183, -1014, 314, -1434, -501, -1407, -1043, -972, +-1271, -339, -1105, 379, -492, 1101, 334, 1591, +987, 1620, 1299, 1231, 1289, 575, 948, -230, +271, -1036, -487, -1616, -996, -1771, -1119, -1461, +-936, -817, -551, -51, -38, 685, 518, 1277, +1019, 1527, 1267, 1375, 1117, 1019, 642, 586, +66, 50, -497, -540, -982, -983, -1173, -1235, +-910, -1409, -358, -1412, 217, -1043, 761, -313, +1268, 583, 1466, 1425, 1106, 2002, 367, 2118, +-425, 1648, -1110, 636, -1536, -664, -1431, -1789, +-781, -2352, 118, -2251, 970, -1573, 1565, -459, +1720, 824, 1364, 1807, 654, 2106, -197, 1755, +-977, 1068, -1494, 272, -1536, -551, -1026, -1227, +-210, -1456, 525, -1242, 1044, -922, 1372, -632, +1325, -180, 748, 469, -30, 985, -526, 1190, +-719, 1260, -796, 1239, -677, 834, -208, -39, +367, -969, 677, -1523, 665, -1674, 524, -1536, +289, -1038, -101, -119, -470, 924, -583, 1581, +-392, 1712, -86, 1505, 176, 1053, 373, 308, +553, -584, 635, -1240, 479, -1480, 175, -1467, +-51, -1286, -190, -798, -387, 12, -533, 875, +-417, 1470, -165, 1701, -45, 1582, 4, 1087, +209, 197, 547, -882, 742, -1696, 678, -1889, +478, -1519, 234, -837, -98, 71, -482, 1089, +-717, 1716, -726, 1549, -555, 881, -264, 199, +99, -427, 438, -1018, 715, -1229, 902, -820, +866, -168, 526, 282, 30, 525, -371, 661, +-629, 545, -802, 116, -799, -353, -483, -552, +11, -474, 419, -281, 690, -36, 913, 304, +971, 657, 664, 795, 74, 570, -483, 69, +-818, -442, -955, -814, -830, -1060, -377, -1051, +252, -575, 734, 253, 936, 1011, 892, 1402, +616, 1411, 165, 1005, -307, 147, -612, -888, +-671, -1616, -475, -1714, -140, -1228, 148, -393, +309, 554, 373, 1353, 300, 1657, 53, 1271, +-199, 462, -192, -321, 77, -900, 342, -1188, +424, -983, 388, -327, 297, 334, 15, 587, +-456, 481, -817, 227, -804, -106, -505, -425, +-103, -509, 357, -193, 836, 388, 1168, 845, +1109, 902, 626, 600, -42, 104, -613, -514, +-1008, -1157, -1193, -1470, -1038, -1170, -489, -424, +220, 348, 780, 966, 1110, 1461, 1220, 1654, +983, 1251, 381, 352, -275, -580, -707, -1199, +-934, -1530, -993, -1654, -735, -1348, -214, -476, +276, 591, 575, 1319, 746, 1613, 790, 1676, +602, 1390, 241, 501, -121, -688, -348, -1476, +-451, -1631, -439, -1471, -300, -1145, -76, -433, +71, 608, 56, 1392, 17, 1476, 53, 1121, +75, 786, 49, 403, 122, -282, 330, -1019, +468, -1257, 402, -995, 268, -745, 125, -586, +-191, -107, -700, 681, -1051, 1216, -968, 1210, +-570, 977, -37, 742, 568, 253, 1161, -619, +1500, -1433, 1379, -1610, 780, -1167, -62, -572, +-882, 13, -1537, 776, -1833, 1509, -1549, 1575, +-707, 899, 336, 149, 1211, -307, 1739, -716, +1831, -1116, 1437, -1068, 654, -425, -296, 234, +-1134, 388, -1638, 234, -1717, 219, -1409, 300, +-760, 120, 134, -203, 1028, -130, 1613, 337, +1717, 532, 1456, 206, 927, -131, 101, -155, +-907, -231, -1655, -567, -1840, -695, -1584, -292, +-998, 206, -22, 310, 1144, 232, 1926, 353, +1997, 531, 1464, 390, 555, 8, -544, -186, +-1522, -123, -1984, -201, -1727, -534, -930, -699, +49, -439, 979, -71, 1705, 138, 1935, 445, +1414, 939, 381, 1152, -637, 768, -1346, 85, +-1748, -508, -1686, -974, -1006, -1363, 0, -1436, +837, -925, 1319, 9, 1531, 883, 1437, 1394, +931, 1564, 116, 1426, -682, 911, -1230, 52, +-1467, -838, -1359, -1397, -871, -1537, -122, -1393, +591, -1048, 1042, -423, 1207, 421, 1066, 1124, +617, 1439, 51, 1457, -399, 1274, -649, 786, +-763, -19, -678, -838, -310, -1361, 128, -1524, +295, -1359, 204, -869, 99, -118, 38, 646, +-43, 1154, -107, 1301, -2, 1119, 218, 691, +338, 129, 239, -461, -2, -883, -210, -954, +-287, -744, -299, -464, -279, -148, -119, 284, +191, 662, 439, 733, 410, 545, 157, 289, +-137, -25, -375, -402, -582, -655, -661, -612, +-432, -342, 87, 14, 619, 354, 899, 574, +898, 572, 699, 320, 354, -53, -174, -375, +-768, -543, -1134, -498, -1144, -253, -935, 108, +-549, 458, 95, 592, 827, 411, 1281, 56, +1289, -274, 982, -501, 501, -602, -84, -484, +-680, -124, -1083, 321, -1137, 607, -867, 639, +-438, 494, -9, 282, 365, 32, 669, -279, +771, -540, 562, -582, 250, -493, 81, -437, +6, -325, -193, -36, -439, 347, -483, 605, +-379, 676, -358, 704, -320, 673, -15, 369, +466, -197, 778, -697, 706, -895, 390, -869, +41, -726, -368, -388, -894, 108, -1203, 498, +-917, 643, -185, 649, 484, 595, 911, 450, +1211, 213, 1282, -45, 856, -232, -66, -377, +-957, -530, -1307, -624, -1208, -590, -1005, -383, +-614, -2, 137, 380, 903, 604, 1122, 684, +814, 618, 545, 330, 431, -130, 103, -476, +-412, -536, -604, -436, -369, -261, -226, 54, +-440, 393, -536, 477, -219, 233, 72, -99, +45, -296, 82, -366, 442, -377, 721, -257, +562, 70, 215, 427, 74, 559, -21, 427, +-374, 219, -786, 35, -810, -224, -460, -513, +-129, -563, 57, -310, 318, -8, 696, 173, +837, 295, 529, 400, 40, 380, -278, 177, +-491, -159, -765, -460, -869, -529, -486, -375, +169, -156, 622, 126, 759, 515, 738, 799, +584, 720, 176, 337, -367, -126, -710, -584, +-721, -922, -563, -932, -352, -582, -91, -58, +213, 439, 453, 734, 492, 709, 395, 454, +312, 150, 299, -113, 258, -283, 77, -238, +-202, 32, -410, 243, -589, 154, -785, -116, +-790, -419, -452, -718, 81, -836, 542, -584, +870, 2, 1068, 677, 982, 1164, 527, 1288, +-73, 1014, -588, 442, -915, -262, -1041, -945, +-940, -1346, -572, -1223, -72, -718, 342, -195, +622, 210, 796, 549, 781, 781, 532, 800, +194, 607, -15, 396, -160, 280, -410, 118, +-645, -212, -657, -621, -511, -898, -368, -918, +-203, -786, 86, -530, 455, 29, 710, 808, +801, 1376, 767, 1423, 611, 1042, 263, 452, +-297, -277, -908, -1056, -1278, -1602, -1244, -1653, +-897, -1175, -320, -343, 469, 538, 1269, 1245, +1659, 1701, 1493, 1766, 953, 1286, 174, 383, +-762, -593, -1553, -1370, -1833, -1846, -1491, -1918, +-710, -1419, 203, -424, 1014, 680, 1504, 1511, +1498, 1905, 1009, 1833, 310, 1276, -349, 300, +-814, -750, -1010, -1444, -921, -1630, -587, -1409, +-193, -853, 110, -47, 292, 676, 373, 984, +385, 903, 400, 675, 381, 393, 290, 34, +151, -294, -24, -369, -211, -181, -398, -16, +-516, -86, -429, -278, -202, -375, -27, -365, +108, -315, 258, -161, 327, 208, 226, 661, +124, 901, 200, 794, 318, 444, 305, 14, +212, -475, 47, -984, -283, -1222, -723, -962, +-1034, -382, -943, 230, -498, 705, 98, 1013, +760, 1140, 1354, 973, 1644, 492, 1426, -116, +660, -615, -346, -894, -1204, -1006, -1788, -984, +-1946, -727, -1529, -268, -659, 200, 329, 574, +1162, 891, 1758, 1137, 1998, 1151, 1652, 778, +862, 164, 33, -406, -759, -876, -1514, -1220, +-1953, -1297, -1836, -1009, -1300, -415, -558, 272, +306, 828, 1238, 1172, 1964, 1190, 2127, 837, +1646, 295, 781, -237, -141, -647, -1022, -862, +-1733, -830, -1977, -551, -1611, -114, -879, 315, +-49, 601, 787, 635, 1488, 435, 1793, 159, +1576, -151, 978, -481, 238, -658, -499, -560, +-1128, -250, -1504, 124, -1505, 446, -1097, 709, +-427, 798, 321, 537, 1036, 83, 1563, -288, +1678, -552, 1272, -737, 453, -744, -434, -504, +-1085, -116, -1472, 255, -1486, 514, -1050, 565, +-341, 439, 397, 333, 957, 222, 1189, -46, +1113, -309, 795, -340, 290, -248, -245, -196, +-619, -111, -676, 94, -531, 258, -431, 199, +-357, 31, -159, -97, 96, -263, 219, -441, +187, -429, 231, -193, 394, 145, 437, 546, +354, 951, 282, 1069, 194, 699, -30, 51, +-334, -593, -571, -1168, -667, -1524, -635, -1408, +-421, -774, -29, 178, 434, 1110, 865, 1686, +1079, 1712, 981, 1225, 605, 426, 16, -468, +-645, -1247, -1133, -1635, -1306, -1467, -1089, -879, +-489, -143, 326, 564, 1077, 1077, 1496, 1242, +1478, 1065, 1010, 652, 169, 100, -738, -434, +-1306, -741, -1389, -847, -1124, -856, -661, -654, +3, -176, 715, 323, 1107, 590, 1059, 650, +786, 593, 440, 419, 38, 142, -276, -166, +-379, -388, -339, -391, -369, -213, -519, -22, +-632, 67, -580, 2, -390, -179, -82, -313, +370, -294, 861, -184, 1222, 4, 1287, 360, +1010, 824, 434, 1061, -344, 797, -1098, 184, +-1545, -472, -1579, -1060, -1195, -1465, -464, -1414, +409, -762, 1210, 234, 1686, 1089, 1677, 1561, +1233, 1627, 470, 1226, -440, 374, -1163, -705, +-1452, -1598, -1274, -1849, -800, -1405, -159, -580, +561, 377, 1050, 1233, 1098, 1667, 794, 1519, +327, 870, -149, -32, -500, -918, -668, -1575, +-550, -1702, -213, -1119, 109, -105, 307, 837, +297, 1410, 150, 1594, 26, 1353, -75, 547, +-131, -594, -60, -1442, 93, -1709, 255, -1459, +293, -752, 145, 255, -36, 1232, -197, 1761, +-386, 1594, -473, 932, -363, 83, -140, -811, +115, -1504, 355, -1748, 595, -1429, 732, -575, +666, 470, 449, 1265, 175, 1644, -200, 1587, +-672, 1112, -1012, 309, -1032, -614, -781, -1342, +-427, -1713, 73, -1672, 784, -1120, 1459, -212, +1685, 711, 1357, 1468, 700, 1848, -115, 1719, +-977, 1191, -1621, 305, -1768, -786, -1379, -1665, +-624, -2036, 260, -1879, 1046, -1250, 1557, -218, +1676, 992, 1297, 1876, 511, 2119, -366, 1850, +-983, 1149, -1241, 18, -1272, -1186, -997, -1973, +-331, -2132, 400, -1705, 832, -845, 1063, 259, +1132, 1272, 848, 1842, 174, 1907, -575, 1491, +-978, 625, -1029, -382, -903, -1212, -503, -1749, +235, -1797, 966, -1248, 1260, -343, 1039, 537, +566, 1169, -18, 1525, -695, 1527, -1180, 997, +-1126, 90, -610, -701, 32, -1141, 595, -1299, +1027, -1149, 1201, -563, 923, 266, 245, 835, +-535, 944, -1000, 868, -1005, 695, -718, 226, +-278, -436, 253, -863, 732, -814, 974, -480, +892, -188, 565, 77, 142, 449, -394, 669, +-868, 515, -961, 232, -701, 68, -317, -47, +105, -241, 522, -430, 793, -407, 790, -227, +587, -172, 299, -219, -113, -111, -547, 187, +-767, 466, -693, 570, -415, 568, -65, 528, +267, 284, 546, -166, 644, -560, 485, -809, +191, -904, -93, -764, -282, -385, -397, 129, +-422, 592, -305, 875, -60, 994, 180, 870, +315, 491, 367, 96, 404, -272, 377, -711, +164, -1022, -99, -998, -226, -738, -269, -423, +-338, -96, -359, 363, -213, 876, 66, 1129, +295, 1048, 341, 783, 314, 419, 332, -32, +264, -597, 20, -1095, -183, -1209, -117, -1013, +87, -720, 98, -305, -47, 226, -118, 741, +-161, 1070, -354, 1124, -568, 1031, -496, 815, +-67, 352, 429, -234, 734, -778, 935, -1241, +990, -1483, 722, -1385, 57, -959, -768, -257, +-1275, 575, -1295, 1351, -1056, 1856, -599, 1896, +165, 1446, 968, 566, 1384, -508, 1275, -1338, +916, -1797, 481, -1986, -172, -1724, -890, -913, +-1231, 101, -1108, 936, -744, 1492, -365, 1837, +70, 1882, 660, 1440, 1143, 646, 1240, -192, +1027, -991, 676, -1687, 147, -2091, -550, -2037, +-1204, -1498, -1490, -628, -1306, 391, -803, 1428, +-125, 2235, 625, 2521, 1342, 2196, 1772, 1361, +1711, 230, 1141, -1006, 214, -2102, -765, -2680, +-1478, -2562, -1773, -1912, -1629, -888, -1072, 376, +-233, 1592, 612, 2405, 1172, 2611, 1393, 2245, +1378, 1443, 1081, 346, 461, -801, -216, -1698, +-662, -2210, -858, -2263, -971, -1808, -955, -1032, +-685, -219, -277, 572, 44, 1350, 264, 1893, +559, 1996, 801, 1780, 794, 1378, 642, 657, +537, -346, 354, -1295, -72, -2007, -576, -2435, +-831, -2376, -800, -1691, -749, -554, -662, 723, +-309, 1868, 239, 2647, 704, 2827, 941, 2279, +1004, 1143, 938, -222, 647, -1424, 119, -2222, +-427, -2557, -780, -2361, -945, -1562, -941, -418, +-732, 611, -388, 1357, 24, 1889, 457, 2110, +847, 1822, 1059, 1105, 1014, 279, 727, -483, +332, -1144, -101, -1601, -573, -1762, -935, -1564, +-1146, -963, -1166, -192, -869, 396, -318, 848, +276, 1294, 830, 1507, 1293, 1238, 1500, 713, +1281, 331, 741, 45, 164, -409, -469, -885, +-1224, -1094, -1762, -1114, -1783, -1101, -1353, -996, +-671, -643, 116, -59, 1001, 577, 1790, 1176, +2131, 1701, 1883, 1934, 1246, 1692, 465, 1045, +-464, 154, -1476, -851, -2161, -1874, -2201, -2619, +-1805, -2669, -1115, -1994, -105, -913, 1073, 390, +1971, 1716, 2242, 2713, 2063, 3092, 1676, 2708, +948, 1637, -149, 180, -1228, -1266, -1949, -2345, +-2226, -2877, -2127, -2786, -1659, -1959, -752, -636, +414, 605, 1409, 1449, 2005, 1928, 2279, 2083, +2275, 1786, 1754, 1000, 601, 155, -745, -311, +-1777, -553, -2402, -797, -2638, -959, -2264, -981, +-1252, -957, 55, -955, 1234, -880, 2079, -581, +2543, -75, 2429, 575, 1641, 1300, 462, 1815, +-699, 1903, -1632, 1636, -2146, 1069, -2118, 193, +-1586, -845, -699, -1760, 281, -2261, 1078, -2263, +1475, -1888, 1434, -1214, 1079, -292, 515, 778, +-66, 1774, -405, 2355, -487, 2451, -407, 2265, +-229, 1736, -55, 708, 10, -607, -108, -1812, +-402, -2645, -632, -3030, -582, -2922, -319, -2182, +40, -848, 458, 719, 928, 2156, 1216, 3207, +1110, 3633, 704, 3287, 212, 2200, -319, 638, +-912, -1054, -1369, -2603, -1407, -3665, -1029, -3863, +-549, -3152, -84, -1826, 439, -254, 993, 1335, +1369, 2763, 1352, 3639, 989, 3583, 479, 2749, +-84, 1557, -666, 181, -1141, -1280, -1297, -2542, +-1095, -3226, -743, -3181, -322, -2608, 184, -1736, +619, -547, 805, 900, 827, 2261, 763, 3105, +593, 3265, 337, 2932, 93, 2179, -99, 835, +-349, -906, -627, -2410, -809, -3298, -790, -3593, +-617, -3293, -371, -2230, -33, -525, 392, 1257, +773, 2670, 929, 3587, 777, 3794, 448, 3093, +209, 1654, 68, -128, -136, -1799, -295, -2993, +-273, -3524, -258, -3245, -462, -2136, -774, -539, +-893, 1037, -764, 2160, -495, 2626, -5, 2459, +757, 1716, 1504, 584, 1880, -512, 1779, -1208, +1157, -1401, 145, -1184, -989, -708, -1914, -91, +-2326, 430, -2145, 569, -1474, 330, -472, -84, +621, -503, 1475, -762, 1919, -741, 1902, -416, +1492, 171, 858, 815, 106, 1315, -571, 1575, +-993, 1459, -1204, 919, -1227, 119, -1049, -784, +-767, -1607, -471, -2091, -182, -2118, 134, -1732, +464, -1013, 767, -6, 1039, 1112, 1264, 2016, +1327, 2489, 1205, 2483, 833, 1992, 114, 1118, +-794, 56, -1638, -1093, -2220, -2119, -2468, -2662, +-2196, -2648, -1223, -2281, 191, -1585, 1539, -452, +2626, 934, 3309, 2093, 3217, 2803, 2250, 3174, +724, 3052, -894, 2136, -2326, 613, -3426, -1018, +-3802, -2462, -3176, -3508, -1818, -3829, -156, -3247, +1495, -1935, 2896, -216, 3753, 1599, 3758, 3089, +2871, 3807, 1377, 3585, -423, 2597, -2232, 1112, +-3569, -570, -4085, -2089, -3618, -3044, -2288, -3218, +-452, -2681, 1456, -1607, 3038, -191, 3950, 1181, +3938, 2097, 2942, 2445, 1145, 2259, -874, 1549, +-2514, 450, -3511, -677, -3780, -1486, -3168, -1849, +-1678, -1766, 202, -1174, 1858, -162, 3078, 851, +3741, 1510, 3475, 1760, 2151, 1560, 301, 792, +-1405, -386, -2721, -1488, -3568, -2138, -3606, -2271, +-2570, -1804, -832, -684, 999, 784, 2533, 2097, +3495, 2921, 3608, 3100, 2758, 2507, 1239, 1134, +-470, -685, -1972, -2369, -3045, -3469, -3481, -3768, +-3096, -3173, -1893, -1816, -288, -70, 1204, 1695, +2409, 3142, 3168, 3858, 3217, 3641, 2502, 2677, +1256, 1296, -238, -292, -1747, -1862, -2940, -3065, +-3421, -3629, -3068, -3499, -2028, -2736, -493, -1465, +1235, 141, 2654, 1814, 3328, 3167, 3168, 3872, +2322, 3750, 912, 2817, -799, 1279, -2207, -505, +-2915, -2167, -2910, -3368, -2287, -3790, -1085, -3265, +439, -2044, 1762, -619, 2487, 716, 2554, 1907, +2081, 2758, 1131, 2882, -105, 2304, -1257, 1503, +-1956, 713, -2154, -224, -1940, -1222, -1243, -1912, +-176, -2155, 875, -2066, 1622, -1680, 1977, -947, +1887, 60, 1320, 1076, 412, 1749, -544, 1909, +-1335, 1650, -1835, 1115, -1854, 293, -1359, -648, +-620, -1200, 131, -1138, 833, -769, 1432, -338, +1729, 194, 1521, 673, 961, 703, 283, 211, +-427, -366, -1065, -728, -1392, -967, -1379, -1039, +-1140, -662, -760, 141, -303, 963, 251, 1468, +780, 1632, 1094, 1554, 1192, 1156, 1201, 353, +1100, -635, 772, -1412, 218, -1824, -417, -1970, +-1009, -1854, -1530, -1294, -1851, -354, -1779, 573, +-1311, 1264, -512, 1761, 532, 2060, 1620, 1999, +2445, 1510, 2696, 780, 2330, 54, 1439, -641, +174, -1347, -1183, -1932, -2280, -2191, -2926, -2081, +-3029, -1704, -2446, -1116, -1218, -273, 339, 825, +1745, 1912, 2730, 2658, 3156, 2970, 2883, 2881, +1994, 2285, 727, 1085, -652, -497, -1847, -2039, +-2642, -3231, -2896, -3893, -2505, -3876, -1585, -3085, +-434, -1570, 678, 339, 1517, 2168, 1997, 3569, +2123, 4362, 1858, 4339, 1346, 3380, 747, 1749, +66, -115, -630, -1900, -1186, -3338, -1512, -4131, +-1690, -4119, -1737, -3362, -1534, -2081, -959, -512, +-150, 1085, 685, 2442, 1455, 3357, 2064, 3703, +2382, 3440, 2205, 2653, 1483, 1501, 451, 89, +-573, -1372, -1458, -2568, -2133, -3298, -2445, -3531, +-2301, -3252, -1727, -2430, -821, -1159, 230, 271, +1208, 1608, 1977, 2731, 2478, 3481, 2581, 3729, +2134, 3377, 1228, 2384, 135, 931, -922, -700, +-1922, -2314, -2700, -3667, -2889, -4425, -2343, -4326, +-1359, -3353, -275, -1718, 877, 332, 2014, 2439, +2778, 4120, 2771, 4948, 2115, 4740, 1229, 3535, +232, 1591, -904, -684, -1916, -2808, -2419, -4254, +-2342, -4685, -1869, -4098, -1089, -2721, -44, -870, +963, 1080, 1578, 2672, 1805, 3463, 1781, 3415, +1467, 2765, 847, 1676, 106, 326, -500, -911, +-961, -1688, -1326, -1961, -1454, -1912, -1243, -1635, +-787, -1105, -267, -447, 261, 109, 752, 455, +1142, 712, 1282, 978, 1118, 1154, 744, 1123, +266, 937, -235, 672, -686, 295, -940, -223, +-946, -806, -773, -1234, -529, -1329, -277, -1153, +-24, -855, 251, -374, 532, 347, 782, 1044, +940, 1359, 907, 1275, 675, 1009, 316, 600, +-157, -22, -720, -728, -1217, -1183, -1449, -1235, +-1322, -1043, -871, -731, -150, -221, 629, 431, +1226, 935, 1562, 1109, 1621, 1045, 1330, 874, +696, 557, -57, 63, -744, -467, -1289, -868, +-1680, -1118, -1776, -1197, -1474, -1048, -918, -670, +-256, -147, 570, 423, 1542, 1002, 2280, 1460, +2449, 1570, 2072, 1291, 1312, 748, 232, 56, +-1044, -629, -2156, -1191, -2772, -1521, -2801, -1507, +-2258, -1189, -1174, -698, 255, -135, 1575, 391, +2409, 763, 2705, 952, 2514, 1055, 1833, 1171, +797, 1182, -251, 974, -1121, 622, -1752, 189, +-2081, -413, -2038, -1168, -1676, -1831, -1141, -2169, +-501, -2134, 199, -1749, 932, -883, 1564, 442, +1952, 1786, 2018, 2711, 1801, 3136, 1325, 3059, +555, 2369, -477, 1010, -1554, -709, -2276, -2237, +-2469, -3294, -2221, -3770, -1526, -3503, -438, -2432, +700, -826, 1536, 885, 1963, 2368, 2001, 3425, +1648, 3795, 977, 3314, 219, 2137, -347, 637, +-635, -812, -683, -2001, -628, -2806, -673, -3085, +-829, -2734, -1012, -1896, -1091, -855, -993, 175, +-671, 1114, -69, 1874, 799, 2283, 1699, 2245, +2279, 1896, 2382, 1384, 1954, 671, 1060, -221, +-149, -1059, -1426, -1601, -2431, -1871, -2862, -1940, +-2658, -1738, -1962, -1234, -885, -534, 427, 234, +1606, 961, 2326, 1547, 2541, 1897, 2333, 1925, +1713, 1632, 745, 1046, -309, 266, -1172, -538, +-1693, -1199, -1901, -1606, -1815, -1702, -1436, -1486, +-895, -1026, -352, -475, 146, 42, 668, 493, +1172, 759, 1529, 811, 1635, 821, 1542, 892, +1277, 936, 751, 883, -19, 751, -856, 565, +-1548, 210, -1991, -432, -2139, -1190, -1863, -1767, +-1127, -2012, -157, -1942, 816, -1536, 1605, -703, +2038, 505, 2085, 1707, 1837, 2505, 1294, 2762, +515, 2506, -321, 1783, -1081, 621, -1759, -781, +-2285, -1974, -2299, -2631, -1691, -2755, -803, -2366, +92, -1479, 1083, -262, 2071, 920, 2571, 1712, +2336, 2055, 1618, 2036, 695, 1631, -444, 879, +-1623, 42, -2334, -582, -2305, -857, -1732, -922, +-913, -888, 38, -719, 983, -471, 1601, -318, +1676, -313, 1302, -323, 730, -228, 106, -72, +-483, 110, -878, 415, -973, 821, -743, 1145, +-291, 1262, 223, 1166, 543, 834, 513, 267, +203, -467, -186, -1229, -512, -1822, -720, -2102, +-648, -1968, -226, -1385, 372, -428, 857, 706, +1152, 1722, 1258, 2356, 992, 2561, 266, 2295, +-643, 1485, -1307, 277, -1557, -945, -1468, -1836, +-1079, -2360, -379, -2521, 468, -2170, 1094, -1323, +1310, -300, 1260, 631, 1076, 1391, 691, 1974, +101, 2262, -374, 2127, -541, 1613, -629, 861, +-865, 7, -1071, -915, -961, -1830, -687, -2484, +-466, -2603, -173, -2176, 433, -1343, 1111, -211, +1475, 1106, 1543, 2300, 1459, 2941, 1083, 2878, +233, 2261, -779, 1193, -1525, -257, -1922, -1671, +-2091, -2560, -1920, -2815, -1186, -2597, -72, -1899, +993, -676, 1812, 730, 2362, 1771, 2487, 2272, +2001, 2347, 988, 2005, -240, 1260, -1375, 267, +-2224, -651, -2577, -1250, -2288, -1511, -1487, -1515, +-405, -1306, 715, -946, 1666, -491, 2204, -69, +2136, 223, 1529, 515, 596, 864, -393, 1150, +-1165, 1265, -1476, 1213, -1382, 993, -987, 554, +-362, -93, 319, -752, 821, -1269, 961, -1605, +759, -1650, 332, -1335, -217, -743, -760, -77, +-1037, 516, -882, 1001, -437, 1384, 96, 1536, +640, 1343, 1137, 910, 1400, 450, 1270, 33, +816, -427, 147, -920, -621, -1223, -1306, -1198, +-1710, -1027, -1726, -843, -1422, -606, -904, -244, +-195, 162, 689, 458, 1435, 691, 1782, 991, +1827, 1271, 1693, 1376, 1295, 1286, 545, 1031, +-286, 569, -953, -192, -1509, -1089, -2011, -1867, +-2207, -2391, -1892, -2533, -1256, -2135, -568, -1216, +214, -8, 1253, 1247, 2255, 2392, 2748, 3197, +2718, 3323, 2311, 2699, 1450, 1557, 153, 200, +-1257, -1199, -2399, -2458, -3119, -3301, -3346, -3481, +-2915, -2932, -1811, -1838, -377, -489, 1007, 851, +2144, 2002, 2906, 2785, 3181, 3030, 2833, 2724, +1958, 2041, 852, 1116, -245, 61, -1251, -959, +-2114, -1764, -2649, -2255, -2664, -2486, -2233, -2460, +-1634, -2044, -899, -1200, 70, -113, 1117, 948, +1917, 1783, 2359, 2362, 2534, 2585, 2440, 2298, +1935, 1573, 1036, 673, -52, -178, -1163, -919, +-2154, -1492, -2800, -1747, -2894, -1688, -2480, -1567, +-1680, -1467, -588, -1219, 625, -718, 1645, -66, +2250, 614, 2444, 1343, 2293, 2121, 1856, 2695, +1190, 2724, 420, 2150, -313, 1133, -930, -162, +-1447, -1588, -1892, -2827, -2194, -3449, -2219, -3261, +-1857, -2449, -1132, -1245, -192, 200, 847, 1635, +1855, 2685, 2573, 3020, 2731, 2661, 2314, 1887, +1566, 916, 661, -109, -294, -978, -1189, -1495, +-1827, -1569, -2064, -1342, -1946, -1073, -1643, -820, +-1274, -548, -822, -310, -330, -215, 193, -148, +765, 165, 1377, 712, 1902, 1178, 2231, 1440, +2298, 1550, 1965, 1461, 1210, 1036, 163, 284, +-987, -512, -2030, -1120, -2798, -1542, -3158, -1824, +-3002, -1816, -2255, -1432, -1037, -863, 369, -334, +1691, 233, 2791, 966, 3522, 1680, 3562, 2067, +2846, 2085, 1668, 1849, 326, 1326, -1032, 474, +-2306, -598, -3155, -1605, -3325, -2289, -2886, -2532, +-2075, -2299, -1006, -1642, 181, -676, 1269, 453, +2099, 1441, 2495, 2001, 2473, 2141, 2145, 1949, +1632, 1444, 949, 611, 96, -293, -739, -880, +-1370, -1117, -1820, -1185, -2117, -1106, -2091, -855, +-1738, -516, -1266, -214, -702, -37, 58, 50, +933, 120, 1623, 238, 2038, 403, 2297, 567, +2316, 691, 1910, 758, 1098, 709, 110, 530, +-869, 284, -1753, -26, -2455, -380, -2792, -648, +-2569, -760, -1929, -815, -1084, -864, -122, -840, +956, -635, 1981, -323, 2644, -40, 2807, 299, +2575, 781, 2064, 1273, 1212, 1548, 84, 1487, +-1067, 1166, -1992, 690, -2628, 18, -2958, -770, +-2821, -1446, -2158, -1801, -1110, -1832, 74, -1670, +1168, -1279, 2099, -579, 2826, 228, 3116, 903, +2754, 1503, 1939, 2061, 967, 2337, -138, 2100, +-1379, 1479, -2455, 639, -2953, -436, -2861, -1589, +-2376, -2407, -1588, -2660, -579, -2457, 486, -1869, +1367, -878, 1947, 331, 2212, 1334, 2256, 1890, +2073, 2082, 1641, 2039, 947, 1711, 83, 1124, +-777, 476, -1582, -131, -2279, -730, -2700, -1345, +-2623, -1819, -2017, -1975, -1018, -1788, 176, -1342, +1327, -645, 2221, 293, 2696, 1268, 2639, 1872, +2039, 1929, 1094, 1608, 125, 1034, -697, 289, +-1339, -440, -1698, -905, -1677, -985, -1412, -757, +-1125, -400, -765, -64, -282, 102, 153, 65, +385, -181, 528, -569, 747, -816, 967, -733, +1078, -383, 1124, 92, 1166, 653, 1061, 1244, +671, 1657, 31, 1610, -676, 1112, -1333, 433, +-1930, -224, -2291, -835, -2128, -1361, -1442, -1664, +-513, -1647, 484, -1349, 1456, -936, 2238, -453, +2568, 164, 2306, 903, 1571, 1555, 657, 1871, +-238, 1883, -1033, 1730, -1615, 1246, -1833, 319, +-1666, -725, -1330, -1529, -970, -1962, -531, -2095, +35, -1908, 559, -1325, 805, -478, 855, 358, +1028, 1000, 1280, 1374, 1250, 1535, 964, 1514, +715, 1247, 439, 813, -110, 372, -842, -12, +-1391, -423, -1630, -833, -1732, -1076, -1673, -1120, +-1267, -1111, -470, -1024, 491, -705, 1305, -267, +1834, 77, 2052, 370, 1909, 723, 1343, 980, +560, 999, -196, 886, -750, 843, -1135, 810, +-1395, 629, -1388, 330, -1091, -6, -710, -393, +-437, -888, -230, -1473, -16, -1972, 205, -2135, +430, -1870, 708, -1163, 1048, -86, 1278, 1196, +1301, 2394, 1132, 3158, 775, 3285, 276, 2731, +-326, 1579, -966, 90, -1558, -1400, -1972, -2613, +-2071, -3276, -1775, -3266, -1110, -2665, -217, -1680, +803, -472, 1744, 778, 2384, 1794, 2536, 2410, +2170, 2646, 1496, 2507, 629, 1977, -386, 1199, +-1400, 343, -2068, -527, -2285, -1363, -2124, -1972, +-1659, -2224, -971, -2167, -204, -1866, 464, -1295, +1029, -516, 1497, 278, 1760, 1008, 1763, 1653, +1565, 2074, 1217, 2169, 655, 1990, -83, 1556, +-793, 849, -1310, -91, -1692, -1038, -1965, -1785, +-1913, -2275, -1478, -2407, -830, -2121, -102, -1451, +689, -512, 1479, 460, 2045, 1237, 2233, 1792, +1987, 2099, 1455, 2089, 745, 1717, -129, 1111, +-1046, 468, -1721, -234, -1971, -1014, -1947, -1660, +-1710, -1968, -1204, -1989, -454, -1762, 261, -1188, +753, -310, 1136, 541, 1524, 1162, 1804, 1607, +1745, 1839, 1385, 1699, 903, 1245, 287, 722, +-521, 184, -1366, -372, -1986, -872, -2249, -1242, +-2087, -1470, -1509, -1527, -641, -1342, 338, -877, +1225, -243, 1854, 454, 2074, 1111, 1908, 1535, +1469, 1632, 746, 1401, -151, 899, -915, 210, +-1290, -515, -1380, -1046, -1331, -1270, -1095, -1242, +-589, -943, -27, -374, 298, 263, 448, 713, +539, 875, 550, 825, 435, 563, 312, 31, +301, -607, 347, -967, 324, -868, 242, -471, +169, 42, 35, 654, -194, 1226, -462, 1387, +-713, 978, -854, 244, -829, -498, -650, -1134, +-340, -1525, 66, -1447, 506, -845, 872, -16, +1052, 641, 1001, 995, 771, 1092, 413, 881, +-26, 380, -472, -159, -824, -470, -912, -455, +-801, -257, -621, -4, -326, 229, 108, 357, +474, 304, 583, 21, 466, -398, 265, -689, +70, -721, -134, -577, -269, -299, -221, 103, +-19, 580, 173, 913, 276, 921, 380, 685, +505, 353, 409, -62, -8, -516, -464, -781, +-711, -676, -813, -338, -911, -44, -873, 151, +-474, 288, 141, 306, 580, 113, 846, -207, +1171, -449, 1424, -440, 1284, -177, 731, 184, +49, 512, -584, 729, -1156, 751, -1585, 521, +-1726, 99, -1518, -372, -1009, -695, -355, -807, +329, -701, 1032, -396, 1661, 5, 1957, 376, +1828, 574, 1397, 528, 752, 297, -69, 8, +-953, -220, -1606, -342, -1902, -407, -1912, -316, +-1659, 10, -1060, 385, -244, 561, 515, 542, +1089, 486, 1477, 335, 1713, -33, 1686, -467, +1349, -746, 826, -863, 278, -829, -242, -598, +-787, -187, -1347, 262, -1758, 664, -1822, 966, +-1578, 1046, -1185, 854, -651, 479, 80, 42, +937, -420, 1645, -816, 2026, -976, 2117, -832, +1912, -521, 1377, -178, 553, 166, -383, 513, +-1238, 729, -1872, 677, -2266, 450, -2392, 171, +-2063, -120, -1330, -422, -423, -642, 469, -658, +1354, -473, 2116, -188, 2519, 220, 2490, 688, +2098, 986, 1407, 967, 404, 678, -728, 243, +-1704, -322, -2375, -907, -2729, -1261, -2730, -1279, +-2213, -1042, -1214, -569, -52, 55, 1009, 649, +1930, 1092, 2639, 1340, 2901, 1345, 2601, 1084, +1811, 645, 774, 96, -306, -502, -1305, -1031, +-2057, -1330, -2433, -1368, -2400, -1167, -2053, -730, +-1465, -152, -705, 375, 109, 741, 881, 927, +1513, 915, 1934, 772, 2074, 564, 2009, 387, +1717, 281, 1150, 204, 399, 103, -424, -101, +-1285, -459, -2090, -870, -2562, -1218, -2533, -1426, +-2084, -1343, -1368, -857, -400, -37, 770, 814, +1802, 1490, 2402, 1934, 2521, 1982, 2246, 1493, +1631, 636, 711, -278, -285, -1026, -1023, -1469, +-1374, -1555, -1489, -1318, -1503, -863, -1387, -313, +-1090, 136, -705, 385, -452, 507, -261, 565, +82, 522, 570, 427, 1023, 408, 1364, 441, +1663, 393, 1821, 267, 1621, 158, 1036, 21, +298, -195, -514, -442, -1360, -609, -2019, -696, +-2324, -735, -2260, -646, -1867, -397, -1194, -68, +-340, 274, 570, 584, 1410, 781, 2045, 794, +2372, 628, 2381, 392, 2094, 129, 1451, -109, +510, -247, -474, -298, -1343, -294, -2057, -266, +-2545, -277, -2639, -315, -2216, -283, -1432, -171, +-542, -32, 389, 99, 1338, 235, 2056, 275, +2330, 141, 2190, -78, 1802, -255, 1243, -314, +517, -194, -209, 132, -746, 554, -1082, 931, +-1345, 1133, -1582, 1028, -1712, 541, -1652, -200, +-1487, -972, -1242, -1575, -742, -1893, 110, -1812, +1165, -1274, 2182, -459, 2926, 402, 3193, 1169, +2877, 1738, 1969, 2009, 616, 1951, -923, 1582, +-2310, 1000, -3264, 284, -3679, -477, -3522, -1213, +-2751, -1891, -1469, -2348, 15, -2390, 1404, -1981, +2546, -1216, 3361, -184, 3679, 979, 3349, 2032, +2482, 2663, 1291, 2764, -120, 2392, -1628, 1583, +-2915, 431, -3656, -795, -3767, -1752, -3303, -2283, +-2277, -2400, -798, -2124, 795, -1449, 2122, -526, +3060, 344, 3555, 951, 3474, 1297, 2709, 1406, +1435, 1272, 57, 965, -1155, 629, -2127, 402, +-2810, 251, -3028, 96, -2718, -118, -1983, -389, +-1001, -682, 62, -978, 1065, -1228, 1850, -1297, +2322, -1097, 2440, -649, 2218, -58, 1703, 518, +935, 1002, -17, 1321, -986, 1411, -1725, 1244, +-2099, 894, -2108, 477, -1833, 69, -1341, -310, +-599, -615, 262, -818, 924, -937, 1251, -990, +1379, -1023, 1390, -986, 1193, -798, 864, -465, +568, -67, 389, 419, 182, 1020, -157, 1591, +-574, 1905, -1010, 1904, -1428, 1612, -1819, 969, +-2017, -12, -1789, -1113, -1049, -2046, -9, -2639, +1102, -2721, 2152, -2187, 2941, -1131, 3225, 168, +2786, 1393, 1704, 2277, 294, 2592, -1203, 2259, +-2572, 1453, -3486, 437, -3648, -553, -3071, -1187, +-1980, -1290, -583, -985, 906, -545, 2170, -141, +2930, 133, 3153, 151, 2878, -123, 2169, -501, +1145, -730, -52, -699, -1144, -421, -1943, -4, +-2410, 507, -2570, 1031, -2336, 1373, -1703, 1393, +-855, 1174, -21, 834, 739, 360, 1461, -257, +1951, -895, 2049, -1376, 1834, -1680, 1473, -1804, +1032, -1636, 492, -1089, -131, -301, -748, 547, +-1281, 1333, -1718, 1926, -1992, 2161, -2012, 1956, +-1742, 1400, -1177, 631, -370, -201, 588, -922, +1523, -1424, 2176, -1695, 2432, -1668, 2295, -1388, +1797, -1011, 1010, -616, 67, -202, -857, 244, +-1546, 688, -1876, 1110, -1933, 1473, -1774, 1708, +-1404, 1738, -823, 1512, -198, 948, 290, 101, +674, -855, 1077, -1734, 1434, -2374, 1543, -2619, +1413, -2318, 1215, -1504, 966, -393, 506, 754, +-116, 1759, -662, 2412, -1075, 2533, -1449, 2113, +-1750, 1339, -1822, 411, -1587, -466, -1098, -1125, +-438, -1505, 335, -1604, 1134, -1460, 1790, -1132, +2139, -742, 2157, -344, 1883, 65, 1320, 444, +505, 751, -379, 994, -1168, 1105, -1811, 1011, +-2256, 739, -2366, 373, -2021, 26, -1344, -225, +-543, -331, 310, -334, 1228, -306, 1994, -302, +2296, -378, 2093, -593, 1626, -880, 1028, -1082, +272, -1036, -532, -635, -1149, 66, -1437, 916, +-1478, 1695, -1414, 2200, -1269, 2266, -959, 1797, +-517, 839, -89, -337, 273, -1414, 665, -2210, +1099, -2603, 1372, -2435, 1375, -1692, 1213, -655, +976, 383, 621, 1278, 132, 1936, -418, 2181, +-906, 1979, -1295, 1468, -1594, 795, -1705, 71, +-1505, -590, -986, -1103, -282, -1437, 467, -1563, +1200, -1468, 1845, -1156, 2194, -707, 2083, -163, +1534, 422, 714, 924, -199, 1275, -1086, 1482, +-1823, 1491, -2178, 1220, -2043, 707, -1564, 108, +-871, -468, -54, -1017, 787, -1436, 1445, -1589, +1778, -1426, 1793, -1007, 1571, -435, 1107, 186, +427, 754, -312, 1155, -946, 1306, -1356, 1188, +-1553, 837, -1525, 398, -1235, -11, -747, -345, +-159, -583, 448, -643, 943, -526, 1235, -359, +1337, -258, 1243, -223, 933, -209, 477, -252, +-22, -359, -496, -422, -893, -285, -1096, 58, +-1012, 494, -771, 893, -512, 1217, -272, 1350, +-46, 1122, 116, 538, 183, -229, 235, -981, +339, -1564, 488, -1836, 632, -1681, 827, -1102, +980, -325, 887, 442, 504, 1077, -18, 1458, +-565, 1469, -1155, 1139, -1671, 678, -1847, 235, +-1575, -180, -1011, -537, -303, -743, 510, -780, +1315, -666, 1906, -497, 2090, -344, 1856, -166, +1326, 86, 592, 289, -250, 334, -1056, 279, +-1609, 200, -1748, 124, -1542, 36, -1177, -25, +-752, -2, -254, 126, 226, 271, 568, 342, +740, 310, 870, 211, 1034, 49, 1141, -164, +1135, -349, 1016, -489, 748, -548, 241, -480, +-416, -337, -1059, -197, -1595, -27, -1931, 169, +-1891, 349, -1345, 510, -440, 657, 509, 734, +1281, 679, 1776, 531, 1907, 298, 1611, -66, +967, -527, 197, -916, -482, -1119, -947, -1114, +-1162, -900, -1098, -453, -783, 167, -313, 777, +147, 1197, 414, 1356, 443, 1242, 320, 824, +124, 184, -149, -494, -405, -993, -503, -1185, +-351, -1060, 18, -695, 430, -181, 732, 340, +884, 689, 871, 770, 599, 602, 80, 290, +-482, -38, -856, -240, -1041, -298, -1077, -261, +-893, -163, -463, -33, 52, 46, 431, 13, +611, -106, 705, -216, 763, -216, 668, -101, +393, 67, 70, 205, -176, 325, -356, 401, +-490, 351, -516, 164, -377, -43, -163, -161, +-6, -204, 76, -245, 113, -280, 85, -227, +-44, -156, -158, -206, -134, -348, -22, -409, +80, -352, 201, -250, 332, -101, 364, 192, +270, 609, 134, 986, 33, 1209, -48, 1235, +-125, 1044, -153, 577, -121, -158, -121, -993, +-202, -1649, -330, -2016, -416, -2091, -388, -1804, +-231, -1114, 49, -150, 421, 806, 784, 1563, +991, 2099, 936, 2373, 585, 2263, 90, 1812, +-374, 1130, -737, 291, -969, -651, -985, -1593, +-722, -2360, -289, -2783, 101, -2763, 379, -2285, +610, -1394, 751, -198, 731, 1119, 580, 2213, +370, 2817, 135, 2889, -142, 2502, -439, 1731, +-643, 719, -701, -294, -650, -1086, -505, -1554, +-252, -1766, 70, -1780, 346, -1600, 534, -1248, +659, -822, 704, -370, 601, 112, 397, 620, +169, 1066, -95, 1336, -424, 1402, -798, 1299, +-1091, 1061, -1167, 674, -950, 214, -521, -169, +33, -417, 651, -603, 1218, -713, 1555, -705, +1522, -637, 1130, -587, 495, -561, -230, -528, +-916, -480, -1444, -371, -1673, -159, -1527, 152, +-1071, 534, -457, 982, 168, 1379, 700, 1545, +1064, 1375, 1225, 894, 1144, 181, 855, -655, +496, -1405, 186, -1854, -55, -1860, -281, -1410, +-446, -608, -525, 300, -584, 1058, -702, 1482, +-801, 1470, -775, 1024, -663, 297, -498, -469, +-196, -1078, 323, -1341, 912, -1160, 1385, -617, +1668, 85, 1713, 797, 1438, 1338, 823, 1497, +-7, 1224, -867, 678, -1599, 5, -2092, -687, +-2254, -1242, -1993, -1527, -1319, -1493, -406, -1205, +539, -757, 1395, -274, 2091, 181, 2442, 604, +2290, 984, 1714, 1246, 959, 1349, 138, 1315, +-719, 1136, -1451, 753, -1879, 152, -1976, -522, +-1854, -1136, -1536, -1635, -997, -1914, -322, -1805, +337, -1315, 955, -613, 1533, 172, 1950, 962, +2068, 1579, 1828, 1817, 1268, 1657, 469, 1222, +-425, 640, -1215, -35, -1761, -671, -1998, -1056, +-1867, -1085, -1405, -927, -792, -746, -194, -477, +335, -86, 793, 233, 1125, 320, 1252, 315, +1203, 377, 1092, 453, 915, 422, 584, 358, +102, 333, -383, 278, -772, 116, -1085, -107, +-1305, -320, -1336, -507, -1098, -622, -650, -602, +-143, -419, 311, -119, 708, 221, 985, 480, +1040, 632, 926, 693, 775, 606, 561, 368, +237, 135, -78, 5, -273, -94, -415, -179, +-614, -210, -815, -221, -913, -318, -886, -475, +-771, -613, -539, -668, -137, -579, 421, -323, +973, 54, 1339, 528, 1488, 1037, 1429, 1375, +1116, 1403, 512, 1141, -271, 676, -1005, 51, +-1500, -626, -1721, -1172, -1653, -1419, -1236, -1364, +-525, -1113, 254, -715, 867, -229, 1260, 204, +1493, 454, 1533, 562, 1296, 612, 847, 642, +308, 642, -245, 629, -759, 574, -1156, 465, +-1380, 310, -1402, 63, -1197, -272, -787, -569, +-242, -729, 346, -789, 873, -761, 1184, -647, +1238, -472, 1122, -304, 899, -177, 565, -84, +198, 33, -88, 217, -308, 436, -546, 630, +-805, 764, -1016, 860, -1159, 848, -1217, 650, +-1105, 289, -738, -94, -171, -425, 453, -696, +1051, -895, 1558, -980, 1850, -928, 1799, -770, +1382, -538, 695, -289, -97, -38, -845, 215, +-1438, 453, -1803, 608, -1897, 688, -1728, 696, +-1329, 608, -760, 480, -98, 380, 573, 289, +1178, 195, 1634, 143, 1871, 75, 1874, -86, +1565, -343, 913, -631, 70, -933, -712, -1207, +-1322, -1329, -1745, -1188, -1865, -790, -1591, -207, +-1025, 494, -398, 1197, 160, 1772, 624, 2047, +968, 1935, 1104, 1492, 1003, 821, 806, 2, +657, -814, 518, -1425, 301, -1665, 53, -1521, +-131, -1156, -277, -699, -471, -207, -698, 202, +-840, 364, -796, 314, -627, 210, -411, 193, +-135, 294, 218, 500, 526, 757, 661, 972, +678, 1062, 694, 947, 694, 602, 554, 122, +309, -329, 75, -709, -107, -983, -307, -1078, +-519, -998, -634, -853, -616, -700, -541, -510, +-453, -264, -294, 3, -55, 264, 177, 569, +315, 890, 375, 1143, 424, 1263, 481, 1221, +523, 999, 524, 637, 432, 157, 220, -426, +-107, -968, -498, -1300, -830, -1425, -981, -1426, +-915, -1218, -683, -749, -295, -175, 185, 293, +629, 628, 937, 867, 1051, 989, 902, 957, +468, 764, -110, 492, -620, 259, -907, 78, +-962, -148, -838, -389, -560, -541, -123, -582, +334, -576, 603, -534, 639, -412, 559, -197, +422, 18, 206, 135, -46, 165, -234, 134, +-274, 55, -214, -46, -153, -86, -124, -34, +-81, 98, -77, 236, -195, 300, -349, 266, +-366, 171, -249, 24, -107, -192, 96, -344, +402, -298, 701, -148, 816, -43, 718, 75, +502, 208, 213, 232, -159, 112, -507, -48, +-683, -164, -677, -246, -581, -308, -451, -351, +-278, -357, -86, -289, 81, -109, 211, 113, +354, 348, 516, 619, 647, 878, 680, 972, +610, 829, 443, 518, 162, 107, -175, -363, +-460, -800, -619, -1058, -650, -1112, -557, -994, +-378, -740, -158, -371, 53, 50, 200, 474, +242, 845, 200, 1106, 153, 1230, 124, 1184, +94, 933, 61, 481, 75, -80, 170, -649, +311, -1068, 399, -1212, 373, -1050, 237, -665, +12, -157, -306, 362, -662, 743, -917, 854, +-973, 663, -835, 302, -552, -85, -150, -383, +297, -524, 690, -451, 952, -192, 1033, 156, +848, 474, 447, 676, 52, 687, -203, 490, +-358, 191, -472, -147, -486, -490, -415, -742, +-383, -812, -456, -712, -519, -471, -444, -139, +-274, 232, -115, 575, 77, 802, 400, 854, +736, 725, 884, 466, 806, 91, 591, -365, +287, -795, -74, -1051, -427, -1117, -656, -996, +-678, -641, -524, -77, -322, 546, -161, 1058, +-23, 1348, 92, 1353, 132, 1057, 76, 475, +1, -232, -7, -846, 90, -1214, 218, -1295, +342, -1110, 476, -731, 565, -280, 499, 84, +266, 280, -21, 352, -289, 349, -512, 335, +-641, 345, -599, 419, -411, 527, -176, 557, +14, 416, 143, 154, 250, -131, 315, -385, +287, -588, 220, -709, 204, -664, 205, -473, +152, -266, 82, -155, 98, -67, 156, 64, +128, 184, 6, 250, -94, 345, -149, 502, +-248, 599, -392, 532, -463, 355, -406, 188, +-324, 11, -254, -233, -110, -483, 141, -583, +340, -522, 397, -421, 405, -328, 431, -157, +411, 128, 309, 386, 188, 526, 68, 584, +-78, 583, -253, 434, -420, 113, -560, -260, +-611, -524, -556, -655, -457, -624, -323, -354, +-102, 100, 168, 582, 359, 952, 427, 1102, +417, 946, 370, 514, 260, -90, 104, -690, +-17, -1151, -35, -1369, -9, -1277, -26, -865, +-56, -211, -45, 518, -43, 1120, -126, 1465, +-259, 1513, -366, 1224, -412, 670, -402, -7, +-291, -653, -57, -1113, 212, -1256, 395, -1070, +492, -628, 570, -91, 596, 357, 468, 628, +160, 678, -190, 519, -446, 215, -558, -111, +-549, -364, -412, -465, -143, -405, 178, -222, +422, -8, 544, 177, 556, 346, 436, 471, +215, 517, -49, 479, -320, 352, -551, 120, +-620, -176, -505, -492, -313, -760, -106, -922, +142, -938, 398, -800, 547, -527, 540, -149, +426, 250, 301, 580, 199, 791, 94, 942, +-30, 1054, -122, 1052, -148, 842, -171, 461, +-294, -17, -493, -580, -626, -1181, -597, -1662, +-448, -1801, -250, -1538, 44, -966, 425, -236, +742, 558, 827, 1243, 726, 1582, 555, 1464, +314, 1029, -29, 491, -377, -38, -575, -470, +-631, -684, -637, -618, -607, -375, -446, -84, +-173, 138, 84, 258, 234, 258, 318, 115, +405, -117, 461, -318, 388, -490, 203, -662, +19, -739, -151, -641, -337, -383, -472, -67, +-440, 286, -273, 679, -86, 1049, 82, 1290, +258, 1335, 397, 1166, 417, 843, 299, 406, +96, -139, -142, -677, -388, -1114, -541, -1429, +-528, -1596, -369, -1513, -95, -1152, 251, -595, +525, 32, 640, 642, 656, 1158, 578, 1452, +297, 1456, -152, 1234, -501, 887, -634, 477, +-689, 101, -719, -159, -566, -281, -188, -363, +221, -455, 483, -533, 681, -583, 945, -597, +1113, -553, 961, -443, 549, -290, 82, -119, +-418, 7, -983, 86, -1432, 130, -1508, 170, +-1201, 245, -686, 417, -75, 684, 584, 935, +1143, 1032, 1400, 903, 1302, 549, 977, 2, +602, -608, 249, -1109, -58, -1355, -300, -1302, +-467, -945, -603, -363, -745, 217, -869, 553, +-912, 586, -860, 395, -720, 62, -438, -296, +-23, -517, 451, -427, 883, -40, 1194, 493, +1318, 979, 1236, 1281, 940, 1302, 445, 985, +-136, 351, -650, -443, -1021, -1136, -1249, -1586, +-1267, -1755, -1027, -1637, -611, -1204, -160, -526, +252, 200, 566, 742, 717, 1067, 664, 1206, +440, 1113, 166, 808, -31, 412, -117, 75, +-137, -146, -105, -250, 11, -258, 174, -204, +237, -171, 169, -194, 81, -278, 39, -376, +-38, -417, -206, -410, -357, -356, -397, -215, +-383, -31, -384, 85, -316, 154, -108, 212, +164, 258, 342, 290, 413, 350, 468, 440, +456, 502, 258, 472, -53, 318, -264, 54, +-287, -268, -168, -534, 43, -698, 314, -708, +551, -529, 611, -208, 415, 146, 50, 460, +-315, 641, -618, 624, -865, 442, -977, 188, +-844, -41, -502, -239, -78, -370, 354, -379, +765, -259, 1062, -100, 1143, 18, 970, 89, +616, 162, 182, 222, -257, 213, -612, 164, +-766, 131, -674, 140, -436, 152, -164, 155, +68, 166, 204, 204, 160, 228, -73, 162, +-368, -34, -535, -288, -497, -513, -315, -706, +1, -818, 452, -733, 895, -412, 1114, 21, +1050, 465, 779, 850, 370, 1075, -150, 1033, +-686, 751, -1081, 337, -1248, -125, -1220, -525, +-1033, -761, -670, -783, -156, -593, 392, -258, +830, 65, 1114, 317, 1218, 464, 1107, 427, +773, 169, 301, -198, -159, -504, -528, -664, +-815, -642, -990, -416, -948, -52, -704, 315, +-398, 627, -151, 757, 64, 616, 288, 305, +463, -11, 528, -263, 530, -395, 537, -349, +493, -156, 326, 59, 126, 156, -2, 112, +-123, -56, -284, -282, -388, -486, -383, -573, +-358, -484, -362, -221, -347, 104, -256, 369, +-95, 528, 85, 522, 252, 360, 384, 143, +479, -22, 510, -120, 442, -131, 283, -71, +137, 6, 67, 30, 6, -14, -134, -107, +-305, -238, -397, -321, -437, -286, -474, -162, +-446, -22, -255, 116, 45, 211, 329, 261, +534, 257, 678, 203, 725, 143, 574, 126, +234, 135, -160, 93, -493, 6, -729, -79, +-827, -182, -769, -328, -544, -406, -188, -371, +210, -273, 555, -140, 819, 73, 987, 338, +962, 561, 689, 715, 273, 781, -164, 719, +-606, 493, -980, 125, -1157, -341, -1094, -761, +-855, -1019, -501, -1086, -79, -926, 354, -504, +709, 54, 919, 539, 962, 843, 856, 935, +647, 817, 361, 526, 46, 181, -244, -112, +-458, -269, -585, -246, -637, -99, -627, 31, +-553, 98, -435, 116, -330, 33, -227, -149, +-100, -364, 69, -509, 262, -549, 456, -504, +642, -389, 809, -171, 898, 112, 824, 394, +553, 626, 136, 786, -317, 865, -721, 794, +-1032, 545, -1187, 179, -1099, -226, -773, -640, +-337, -958, 84, -1072, 471, -942, 833, -638, +1082, -268, 1099, 113, 900, 457, 592, 674, +232, 682, -178, 524, -588, 309, -834, 120, +-847, -69, -702, -231, -489, -294, -210, -264, +105, -198, 343, -106, 429, -8, 392, 47, +340, 49, 314, 5, 283, -70, 233, -160, +201, -204, 163, -173, 33, -88, -190, 24, +-412, 140, -570, 186, -662, 126, -663, 1, +-511, -133, -181, -205, 224, -157, 554, 31, +781, 279, 927, 494, 903, 590, 626, 503, +185, 217, -237, -210, -568, -662, -808, -987, +-911, -1035, -806, -787, -502, -351, -143, 138, +127, 614, 272, 965, 357, 1044, 357, 821, +233, 442, 76, 41, 34, -310, 122, -532, +217, -561, 286, -391, 359, -103, 393, 193, +258, 380, -33, 413, -337, 290, -582, 49, +-780, -281, -871, -602, -765, -748, -497, -650, +-150, -354, 249, 37, 635, 452, 898, 827, +977, 1047, 891, 986, 679, 666, 335, 211, +-118, -228, -564, -556, -840, -742, -903, -761, +-828, -595, -627, -301, -256, -15, 208, 195, +555, 348, 706, 478, 731, 519, 677, 450, +493, 333, 191, 180, -106, -66, -309, -379, +-455, -642, -589, -767, -641, -710, -550, -497, +-356, -157, -146, 250, 86, 613, 369, 793, +621, 761, 727, 593, 694, 361, 576, 94, +379, -121, 122, -184, -147, -171, -384, -182, +-552, -218, -599, -264, -541, -358, -443, -462, +-307, -515, -101, -492, 92, -395, 180, -221, +196, -18, 199, 133, 191, 231, 161, 318, +143, 394, 193, 456, 322, 537, 419, 606, +406, 608, 301, 499, 132, 277, -144, -48, +-523, -422, -851, -752, -980, -960, -888, -966, +-626, -772, -230, -461, 236, -129, 673, 172, +951, 363, 999, 382, 850, 266, 547, 111, +124, -33, -307, -135, -623, -132, -777, -11, +-770, 168, -621, 338, -377, 499, -98, 621, +164, 653, 354, 571, 440, 392, 443, 131, +397, -204, 315, -574, 226, -873, 164, -1017, +120, -1031, 65, -915, -22, -653, -162, -292, +-364, 60, -592, 345, -803, 557, -899, 680, +-772, 712, -399, 724, 136, 742, 698, 721, +1188, 653, 1489, 531, 1459, 343, 1049, 70, +406, -266, -270, -634, -844, -944, -1241, -1088, +-1372, -1037, -1166, -818, -720, -443, -228, 35, +193, 467, 528, 745, 721, 846, 691, 764, +484, 499, 275, 148, 150, -174, 49, -377, +-58, -403, -101, -278, -44, -92, 31, 108, +34, 318, -14, 471, -39, 505, -74, 444, +-181, 352, -308, 219, -325, 32, -236, -182, +-137, -398, -60, -605, 49, -778, 204, -858, +321, -788, 337, -558, 289, -226, 268, 145, +230, 511, 97, 815, -92, 942, -219, 862, +-267, 652, -326, 374, -407, 59, -423, -224, +-301, -384, -102, -408, 60, -350, 190, -269, +371, -181, 541, -101, 537, -67, 360, -101, +167, -178, 17, -248, -153, -266, -364, -221, +-502, -135, -466, -26, -346, 97, -266, 253, +-175, 389, 43, 419, 279, 332, 366, 213, +354, 79, 369, -88, 321, -243, 102, -314, +-155, -288, -274, -216, -259, -122, -217, -18, +-162, 71, -63, 109, 56, 101, 94, 80, +32, 76, -34, 38, -43, -57, -13, -142, +49, -199, 176, -272, 337, -340, 428, -309, +382, -165, 210, 23, -44, 209, -315, 400, +-545, 547, -688, 590, -699, 521, -567, 371, +-338, 169, -71, -55, 220, -274, 522, -492, +768, -668, 891, -761, 895, -738, 782, -594, +542, -335, 199, 24, -199, 448, -611, 837, +-953, 1070, -1133, 1090, -1137, 900, -964, 541, +-619, 70, -151, -391, 309, -723, 665, -864, +909, -815, 1043, -609, 1012, -329, 806, -68, +504, 114, 191, 195, -111, 206, -402, 195, +-611, 213, -703, 288, -726, 432, -691, 567, +-566, 599, -391, 498, -218, 281, -35, -47, +151, -446, 322, -784, 500, -928, 671, -849, +754, -589, 715, -182, 584, 271, 365, 638, +40, 843, -331, 863, -636, 673, -786, 322, +-766, -57, -636, -358, -462, -530, -250, -552, +-6, -426, 198, -220, 324, -5, 383, 147, +409, 193, 411, 124, 372, 3, 283, -106, +190, -160, 121, -123, 26, 6, -118, 181, +-250, 329, -306, 395, -327, 355, -350, 236, +-339, 55, -239, -153, -59, -317, 141, -384, +321, -368, 456, -303, 493, -206, 367, -109, +98, -44, -224, -19, -514, -14, -700, -30, +-701, -44, -464, -35, -42, 1, 419, 60, +801, 147, 1031, 248, 1054, 339, 830, 410, +374, 449, -196, 423, -706, 281, -1045, 29, +-1197, -280, -1124, -584, -807, -848, -333, -1011, +137, -997, 520, -758, 805, -339, 945, 143, +908, 594, 720, 934, 441, 1095, 114, 1022, +-189, 749, -411, 365, -546, -29, -603, -370, +-562, -604, -410, -692, -200, -633, -14, -463, +118, -250, 226, -40, 298, 142, 272, 275, +149, 317, 31, 267, -18, 157, -25, 28, +-24, -99, -4, -183, 69, -204, 181, -177, +223, -107, 128, -2, -26, 116, -167, 222, +-318, 323, -460, 409, -448, 461, -241, 455, +26, 366, 236, 160, 376, -158, 444, -510, +399, -796, 231, -945, -2, -914, -192, -668, +-278, -233, -284, 270, -246, 684, -181, 916, +-110, 939, -51, 769, 0, 449, 63, 89, +166, -179, 308, -285, 432, -248, 466, -145, +390, -14, 218, 98, -55, 114, -397, 11, +-673, -143, -775, -295, -711, -426, -532, -499, +-233, -482, 155, -395, 504, -283, 700, -137, +735, 63, 653, 295, 459, 508, 180, 696, +-99, 844, -284, 889, -350, 794, -332, 577, +-256, 261, -137, -123, -16, -496, 51, -784, +32, -963, -71, -1035, -210, -958, -325, -740, +-374, -457, -325, -154, -174, 178, 58, 491, +340, 694, 626, 747, 831, 688, 858, 564, +698, 384, 420, 177, 36, 0, -438, -83, +-864, -86, -1090, -70, -1121, -84, -994, -134, +-665, -220, -128, -340, 489, -443, 999, -483, +1292, -449, 1331, -348, 1102, -172, 592, 40, +-107, 236, -779, 374, -1224, 441, -1385, 431, +-1251, 350, -807, 220, -162, 58, 462, -110, +902, -239, 1128, -283, 1127, -237, 885, -106, +450, 74, -43, 248, -461, 348, -750, 332, +-894, 202, -854, -16, -608, -277, -231, -517, +160, -653, 474, -642, 656, -496, 673, -272, +514, -8, 199, 255, -171, 472, -447, 611, +-547, 675, -473, 673, -257, 597, 47, 452, +333, 253, 501, 26, 517, -221, 407, -478, +209, -703, -36, -809, -296, -781, -504, -667, +-593, -490, -562, -235, -455, 59, -264, 294, +21, 450, 309, 568, 522, 653, 664, 671, +735, 633, 644, 552, 358, 435, 4, 277, +-295, 76, -532, -149, -706, -369, -725, -557, +-541, -713, -237, -823, 70, -863, 322, -815, +479, -661, 497, -368, 373, 25, 172, 437, +-37, 838, -208, 1188, -306, 1345, -310, 1212, +-225, 865, -79, 403, 91, -143, 233, -694, +314, -1069, 334, -1193, 292, -1110, 164, -863, +-20, -457, -184, 40, -292, 493, -334, 804, +-303, 944, -232, 899, -173, 647, -106, 232, +-11, -230, 80, -600, 131, -800, 166, -784, +208, -562, 225, -212, 188, 145, 96, 396, +-36, 466, -158, 366, -200, 193, -121, 35, +61, -54, 276, -27, 436, 141, 481, 363, +344, 489, 11, 439, -401, 223, -741, -103, +-940, -464, -964, -756, -741, -892, -272, -828, +258, -606, 668, -304, 913, 13, 1007, 303, +922, 493, 652, 552, 287, 557, -29, 578, +-253, 564, -443, 469, -605, 351, -667, 227, +-595, 30, -463, -231, -326, -447, -161, -581, +32, -653, 188, -641, 284, -513, 380, -313, +465, -104, 435, 85, 262, 245, 70, 361, +-44, 416, -125, 415, -204, 358, -210, 250, +-129, 102, -44, -45, 14, -150, 89, -201, +175, -199, 199, -124, 122, 12, -38, 138, +-221, 209, -364, 217, -435, 163, -442, 32, +-358, -157, -143, -336, 140, -448, 362, -486, +508, -437, 622, -277, 637, -15, 466, 275, +170, 492, -99, 591, -284, 544, -411, 342, +-463, 29, -387, -280, -211, -473, -54, -491, +7, -330, 21, -41, 36, 275, -2, 505, +-129, 566, -240, 429, -188, 153, 14, -153, +232, -395, 395, -520, 530, -507, 603, -399, +498, -274, 203, -176, -116, -118, -330, -105, +-476, -111, -586, -37, -582, 159, -406, 411, +-165, 644, 4, 822, 110, 866, 260, 715, +416, 392, 442, -26, 345, -456, 245, -806, +152, -996, -24, -1009, -239, -846, -351, -545, +-324, -188, -240, 137, -155, 412, -62, 619, +46, 702, 129, 640, 123, 474, 48, 258, +15, 31, 70, -165, 125, -299, 120, -318, +119, -202, 167, 0, 182, 189, 77, 311, +-90, 339, -209, 235, -282, -10, -358, -310, +-396, -543, -319, -642, -135, -596, 59, -410, +210, -95, 327, 261, 399, 522, 383, 624, +268, 588, 102, 432, -48, 180, -157, -71, +-222, -230, -230, -275, -177, -207, -79, -38, +24, 152, 92, 260, 105, 264, 78, 185, +17, 8, -67, -223, -139, -402, -178, -483, +-185, -489, -173, -413, -109, -234, 26, -16, +178, 178, 295, 359, 365, 531, 379, 641, +310, 660, 147, 585, -77, 397, -303, 115, +-479, -206, -547, -515, -468, -746, -275, -803, +-18, -676, 258, -446, 460, -171, 516, 122, +446, 350, 296, 455, 81, 465, -132, 430, +-241, 356, -246, 248, -224, 133, -218, 8, +-205, -137, -176, -305, -133, -452, -59, -520, +46, -458, 164, -287, 281, -64, 358, 178, +335, 407, 211, 539, 57, 503, -82, 333, +-211, 110, -286, -110, -250, -316, -152, -448, +-76, -439, -4, -306, 93, -146, 158, -9, +152, 116, 114, 195, 59, 177, -29, 67, +-110, -60, -148, -152, -167, -182, -164, -129, +-77, -5, 70, 153, 169, 318, 178, 433, +138, 420, 61, 265, -45, 31, -105, -221, +-76, -446, -12, -576, 44, -555, 118, -387, +188, -142, 169, 110, 35, 315, -138, 428, +-265, 416, -314, 284, -281, 98, -174, -60, +-23, -183, 125, -290, 208, -321, 196, -243, +134, -108, 79, 33, 34, 201, -8, 380, +-14, 487, 21, 478, 46, 363, 30, 156, +0, -108, -13, -343, -18, -483, -24, -497, +-20, -386, 7, -185, 26, 17, -6, 146, +-95, 181, -200, 138, -266, 62, -257, 9, +-158, 24, 26, 102, 239, 211, 380, 297, +399, 317, 318, 251, 179, 127, 22, -15, +-108, -137, -189, -214, -226, -231, -197, -207, +-101, -175, -7, -136, 15, -87, 5, -31, +30, 34, 56, 129, 14, 230, -58, 274, +-80, 239, -59, 169, -69, 76, -89, -53, +-23, -172, 124, -225, 237, -216, 253, -183, +215, -136, 152, -93, 36, -70, -122, -49, +-236, 7, -251, 86, -212, 165, -170, 261, +-105, 351, 2, 380, 120, 342, 214, 264, +273, 132, 282, -45, 220, -229, 90, -407, +-85, -583, -273, -726, -431, -784, -514, -739, +-491, -559, -321, -220, -11, 226, 326, 677, +560, 1064, 663, 1290, 655, 1240, 507, 916, +217, 421, -116, -152, -370, -705, -514, -1104, +-580, -1256, -582, -1173, -502, -926, -326, -564, +-103, -156, 111, 224, 322, 530, 554, 751, +728, 872, 718, 870, 513, 729, 216, 478, +-125, 171, -516, -159, -850, -458, -944, -649, +-743, -703, -362, -657, 79, -541, 511, -374, +838, -188, 943, -23, 786, 116, 449, 260, +63, 407, -285, 521, -562, 555, -723, 497, +-721, 375, -573, 211, -362, 16, -111, -150, +198, -231, 489, -245, 628, -244, 604, -251, +512, -289, 346, -374, 56, -445, -249, -432, +-403, -309, -409, -81, -367, 250, -266, 603, +-79, 835, 111, 874, 198, 739, 165, 441, +80, 19, -2, -403, -76, -682, -144, -762, +-171, -655, -97, -387, 77, -16, 265, 370, +392, 663, 461, 765, 453, 657, 288, 387, +-56, 4, -459, -417, -763, -745, -923, -884, +-908, -817, -649, -566, -156, -157, 411, 300, +885, 666, 1192, 880, 1268, 928, 1040, 786, +537, 498, -92, 173, -665, -133, -1064, -396, +-1252, -566, -1201, -609, -890, -565, -395, -463, +113, -299, 527, -80, 846, 142, 1046, 324, +1019, 435, 725, 441, 303, 328, -74, 117, +-356, -121, -587, -308, -722, -379, -658, -313, +-420, -122, -155, 132, 55, 362, 224, 481, +340, 433, 338, 232, 198, -54, 7, -335, +-117, -540, -124, -614, -65, -532, 4, -322, +102, -46, 236, 247, 309, 484, 246, 599, +108, 576, -15, 429, -145, 161, -317, -198, +-456, -532, -457, -739, -315, -785, -90, -664, +165, -359, 400, 55, 546, 436, 539, 691, +360, 779, 71, 680, -212, 430, -404, 130, +-475, -138, -401, -340, -180, -459, 109, -496, +318, -492, 369, -471, 298, -421, 159, -326, +-37, -167, -242, 77, -350, 370, -307, 634, +-157, 799, 21, 805, 178, 622, 282, 280, +322, -131, 294, -527, 182, -828, 16, -953, +-122, -847, -215, -561, -290, -194, -310, 193, +-217, 550, -51, 796, 82, 863, 136, 757, +135, 534, 107, 234, 33, -111, -87, -415, +-187, -609, -193, -671, -112, -599, -9, -421, +103, -188, 232, 43, 335, 231, 369, 335, +339, 341, 263, 284, 146, 224, -5, 188, +-165, 185, -330, 221, -496, 264, -624, 267, +-665, 209, -595, 79, -416, -137, -123, -385, +245, -587, 577, -698, 769, -713, 820, -601, +747, -344, 532, 6, 213, 376, -103, 724, +-327, 986, -434, 1093, -425, 1027, -339, 774, +-252, 351, -204, -156, -181, -630, -157, -995, +-116, -1178, -30, -1128, 97, -860, 225, -454, +316, 8, 340, 431, 265, 709, 103, 810, +-62, 745, -167, 544, -221, 262, -237, 0, +-185, -177, -63, -251, 83, -210, 199, -80, +264, 58, 281, 127, 253, 101, 176, -20, +65, -201, -42, -382, -118, -496, -170, -487, +-212, -333, -244, -81, -247, 181, -208, 376, +-163, 458, -157, 421, -155, 282, -82, 90, +50, -85, 179, -184, 301, -201, 422, -168, +482, -125, 417, -71, 252, -15, 60, 10, +-117, 15, -269, 43, -366, 94, -352, 121, +-251, 97, -160, 29, -101, -61, -26, -168, +52, -269, 66, -329, 31, -304, 19, -183, +49, -11, 80, 156, 79, 300, 67, 384, +75, 353, 81, 243, 25, 122, -62, -5, +-93, -142, -83, -244, -99, -285, -118, -292, +-71, -281, 30, -239, 121, -158, 176, -38, +201, 133, 200, 323, 183, 461, 124, 521, +-4, 495, -165, 357, -280, 122, -335, -148, +-363, -396, -339, -578, -208, -652, -5, -602, +160, -460, 263, -252, 359, 0, 453, 252, +468, 452, 373, 587, 211, 643, 11, 590, +-229, 427, -488, 198, -681, -36, -714, -237, +-564, -363, -288, -387, 51, -314, 417, -193, +738, -63, 901, 47, 845, 99, 619, 67, +300, -22, -78, -116, -441, -175, -676, -187, +-760, -145, -751, -33, -667, 135, -470, 318, +-181, 453, 121, 498, 376, 441, 570, 287, +678, 39, 665, -257, 515, -499, 277, -604, +33, -560, -170, -383, -307, -100, -344, 226, +-271, 505, -145, 655, -17, 619, 72, 399, +64, 79, -41, -255, -170, -551, -273, -741, +-345, -744, -347, -553, -227, -254, 7, 84, +267, 419, 474, 679, 605, 792, 638, 743, +517, 564, 221, 299, -143, -21, -433, -351, +-605, -620, -670, -762, -602, -751, -402, -607, +-118, -371, 190, -84, 456, 206, 630, 426, +680, 522, 575, 506, 324, 427, 11, 323, +-272, 211, -498, 103, -645, 8, -661, -87, +-535, -218, -318, -391, -49, -555, 234, -630, +470, -575, 606, -394, 613, -103, 496, 262, +296, 593, 64, 767, -159, 748, -350, 571, +-469, 293, -476, -32, -373, -318, -206, -491, +-23, -546, 150, -507, 290, -398, 365, -266, +359, -142, 293, -8, 198, 144, 80, 285, +-70, 396, -228, 474, -334, 489, -363, 417, +-340, 268, -289, 65, -193, -175, -47, -407, +101, -568, 213, -639, 302, -620, 387, -504, +435, -296, 407, -35, 321, 254, 224, 530, +93, 729, -106, 807, -331, 764, -514, 596, +-610, 299, -598, -73, -485, -428, -298, -700, +-63, -846, 162, -819, 319, -621, 412, -319, +470, 10, 477, 315, 413, 536, 316, 623, +210, 575, 85, 429, -56, 235, -198, 25, +-328, -169, -427, -303, -488, -347, -520, -318, +-490, -237, -349, -120, -124, 14, 113, 126, +341, 183, 556, 176, 710, 125, 736, 68, +615, 23, 383, 4, 88, 20, -256, 66, +-606, 98, -844, 85, -891, 29, -765, -58, +-511, -158, -143, -237, 303, -279, 716, -291, +966, -247, 980, -136, 779, -4, 431, 115, +-8, 245, -461, 390, -800, 486, -923, 484, +-844, 401, -613, 241, -257, -9, 167, -288, +527, -501, 718, -604, 743, -605, 644, -504, +433, -307, 138, -63, -152, 157, -353, 317, +-449, 423, -463, 489, -387, 517, -226, 492, +-44, 405, 84, 247, 142, 14, 156, -272, +133, -550, 58, -754, -34, -840, -80, -774, +-54, -543, 11, -188, 70, 205, 128, 551, +212, 786, 294, 876, 294, 810, 199, 615, +80, 339, -50, 45, -229, -216, -400, -416, +-460, -541, -419, -585, -349, -554, -251, -467, +-92, -356, 92, -242, 222, -125, 289, -10, +350, 85, 419, 167, 431, 277, 347, 421, +225, 548, 114, 620, -20, 637, -207, 571, +-395, 367, -505, 21, -508, -381, -441, -730, +-326, -964, -138, -1045, 93, -937, 260, -637, +320, -221, 336, 207, 330, 569, 250, 829, +120, 958, 40, 935, 46, 781, 81, 540, +91, 245, 64, -88, 3, -421, -110, -701, +-295, -878, -490, -929, -588, -856, -553, -673, +-418, -389, -197, -35, 125, 320, 495, 606, +777, 807, 877, 921, 819, 910, 648, 757, +347, 486, -74, 153, -487, -184, -755, -479, +-855, -682, -823, -756, -650, -699, -334, -562, +43, -405, 361, -257, 544, -126, 586, -13, +515, 102, 351, 252, 130, 452, -63, 656, +-158, 787, -162, 791, -134, 648, -106, 358, +-49, -49, 21, -479, 40, -799, -8, -927, +-52, -860, -54, -630, -47, -294, -51, 70, +-31, 365, 30, 530, 79, 561, 62, 490, +6, 368, -23, 233, -41, 114, -103, 28, +-181, -36, -181, -112, -92, -207, 17, -293, +115, -350, 215, -387, 311, -389, 351, -323, +293, -191, 160, -21, 13, 169, -130, 372, +-268, 550, -358, 666, -337, 683, -237, 582, +-126, 361, -34, 43, 27, -326, 39, -669, +8, -886, -26, -908, -22, -739, 37, -428, +130, -40, 219, 332, 278, 599, 282, 702, +218, 636, 104, 440, -21, 189, -135, -41, +-208, -205, -207, -285, -161, -270, -128, -179, +-124, -66, -133, 30, -139, 93, -139, 101, +-112, 48, -19, -44, 133, -138, 262, -191, +309, -166, 307, -74, 274, 55, 170, 183, +1, 268, -143, 269, -205, 168, -203, -13, +-161, -221, -92, -393, -15, -466, 38, -414, +51, -255, 23, -22, -28, 238, -75, 457, +-91, 579, -82, 591, -52, 500, 22, 322, +137, 95, 232, -140, 265, -338, 243, -473, +176, -550, 66, -576, -66, -544, -193, -454, +-292, -322, -338, -152, -329, 72, -281, 341, +-186, 599, -23, 791, 170, 882, 318, 833, +401, 623, 443, 251, 428, -225, 313, -675, +118, -976, -90, -1079, -278, -975, -452, -656, +-562, -165, -530, 358, -371, 753, -173, 938, +24, 892, 214, 624, 354, 203, 402, -239, +365, -568, 290, -701, 212, -626, 146, -379, +78, -29, 12, 315, -33, 530, -104, 557, +-241, 427, -380, 194, -445, -87, -440, -341, +-388, -487, -263, -489, -53, -373, 192, -184, +384, 39, 489, 249, 536, 400, 527, 462, +427, 424, 258, 304, 90, 144, -56, -18, +-215, -164, -381, -276, -515, -327, -583, -309, +-575, -256, -490, -199, -339, -132, -122, -56, +138, 4, 379, 41, 568, 78, 697, 136, +741, 198, 662, 239, 466, 270, 183, 303, +-139, 324, -441, 301, -662, 209, -760, 47, +-726, -150, -575, -336, -342, -491, -56, -586, +226, -573, 441, -443, 559, -232, 573, 9, +488, 226, 340, 365, 162, 396, -27, 343, +-197, 256, -304, 169, -339, 106, -320, 87, +-255, 110, -141, 155, -3, 173, 100, 110, +138, -33, 139, -203, 142, -361, 122, -484, +54, -519, -18, -423, -50, -221, -55, 4, +-63, 187, -73, 293, -74, 308, -60, 234, +-49, 116, -41, 26, 8, 20, 106, 107, +194, 241, 223, 352, 208, 367, 145, 236, +30, -38, -102, -392, -217, -714, -298, -889, +-331, -847, -289, -586, -167, -152, -18, 367, +112, 823, 206, 1062, 266, 1031, 265, 766, +191, 345, 98, -131, 35, -540, -12, -779, +-60, -813, -82, -671, -66, -423, -32, -150, +-9, 76, -18, 210, -53, 244, -83, 210, +-107, 171, -143, 154, -155, 145, -96, 141, +9, 156, 100, 188, 161, 208, 200, 188, +203, 137, 156, 69, 83, -20, 31, -143, +16, -291, 10, -418, -8, -485, -35, -476, +-79, -381, -140, -194, -202, 37, -244, 236, +-240, 362, -176, 405, -79, 372, 22, 286, +140, 189, 269, 116, 359, 84, 375, 82, +342, 83, 275, 59, 157, 5, -20, -73, +-210, -172, -366, -270, -481, -338, -552, -365, +-526, -363, -356, -337, -96, -285, 158, -183, +361, -8, 507, 222, 572, 473, 531, 708, +388, 880, 200, 915, 42, 756, -81, 413, +-220, -56, -372, -570, -478, -1019, -524, -1292, +-533, -1316, -499, -1084, -362, -645, -88, -95, +263, 460, 576, 922, 806, 1203, 936, 1264, +884, 1125, 594, 828, 150, 433, -294, 15, +-658, -360, -907, -658, -994, -858, -873, -941, +-565, -899, -183, -757, 156, -555, 426, -323, +632, -79, 717, 158, 650, 379, 493, 575, +321, 738, 133, 854, -70, 882, -238, 786, +-327, 575, -356, 274, -364, -96, -344, -487, +-266, -813, -151, -999, -52, -1024, 34, -904, +114, -670, 162, -363, 158, -26, 125, 306, +88, 590, 60, 789, 48, 886, 60, 861, +106, 706, 173, 445, 220, 123, 196, -210, +97, -507, -51, -713, -212, -782, -359, -716, +-456, -558, -462, -347, -337, -103, -107, 148, +152, 369, 388, 534, 565, 639, 613, 666, +472, 577, 182, 376, -153, 106, -435, -187, +-625, -468, -685, -679, -564, -759, -267, -684, +103, -481, 433, -206, 675, 84, 787, 347, +720, 541, 478, 634, 151, 617, -176, 522, +-443, 382, -630, 204, -725, -14, -704, -243, +-573, -434, -378, -563, -145, -630, 143, -615, +443, -483, 677, -232, 804, 75, 817, 363, +700, 586, 445, 705, 79, 681, -314, 499, +-647, 212, -863, -96, -930, -375, -805, -579, +-500, -635, -118, -509, 236, -250, 502, 49, +658, 321, 684, 516, 580, 570, 376, 437, +148, 156, -26, -155, -142, -392, -224, -496, +-252, -440, -213, -241, -167, 29, -164, 259, +-199, 358, -232, 296, -246, 118, -246, -85, +-208, -226, -86, -251, 120, -134, 329, 90, +484, 314, 574, 425, 582, 387, 480, 216, +280, -34, 17, -291, -246, -469, -442, -493, +-550, -373, -585, -184, -542, 8, -411, 164, +-223, 253, -22, 252, 169, 179, 355, 82, +509, 4, 578, -38, 529, -33, 384, 9, +167, 58, -106, 93, -366, 101, -514, 75, +-516, 22, -413, -50, -230, -139, 14, -223, +259, -260, 424, -227, 453, -136, 353, -30, +181, 76, -19, 173, -214, 234, -341, 226, +-356, 152, -290, 46, -199, -56, -96, -129, +32, -166, 168, -160, 250, -114, 257, -44, +240, 26, 240, 88, 219, 137, 137, 159, +26, 152, -82, 122, -202, 66, -341, -27, +-452, -140, -479, -221, -393, -247, -219, -223, +0, -142, 248, -10, 497, 131, 658, 215, +665, 211, 526, 134, 294, 19, 14, -86, +-284, -131, -534, -101, -655, -19, -616, 82, +-479, 160, -292, 170, -57, 98, 183, -19, +350, -126, 422, -178, 435, -151, 399, -50, +305, 73, 157, 148, 8, 144, -107, 72, +-192, -42, -262, -162, -294, -237, -263, -233, +-187, -153, -119, -21, -71, 128, -9, 254, +79, 322, 176, 318, 247, 251, 295, 147, +336, 29, 325, -101, 200, -233, -5, -324, +-198, -337, -360, -290, -498, -206, -557, -85, +-463, 64, -236, 189, 32, 255, 248, 264, +402, 232, 497, 163, 499, 81, 401, 20, +263, -8, 154, -2, 66, 20, -41, 30, +-170, 8, -279, -42, -355, -121, -436, -223, +-533, -315, -558, -361, -447, -337, -239, -249, +17, -114, 304, 61, 575, 248, 756, 404, +808, 500, 713, 545, 493, 546, 193, 485, +-133, 343, -442, 134, -676, -107, -778, -360, +-713, -614, -510, -823, -243, -926, 34, -884, +302, -690, 517, -364, 601, 56, 541, 505, +377, 878, 134, 1082, -169, 1076, -447, 861, +-597, 478, -571, 19, -389, -391, -122, -641, +189, -684, 496, -543, 702, -287, 730, -18, +591, 164, 325, 193, -35, 53, -407, -183, +-667, -398, -745, -504, -660, -456, -465, -251, +-215, 72, 44, 434, 257, 723, 376, 847, +392, 785, 347, 572, 283, 251, 215, -121, +134, -467, 52, -708, 6, -801, -5, -743, +-34, -545, -102, -237, -149, 104, -154, 393, +-159, 578, -189, 636, -193, 562, -138, 369, +-58, 105, 8, -160, 67, -361, 151, -458, +233, -448, 239, -355, 164, -208, 86, -27, +41, 154, -12, 287, -80, 352, -102, 347, +-66, 274, -36, 143, -75, -17, -152, -162, +-207, -268, -232, -322, -224, -306, -124, -205, +107, -40, 375, 139, 567, 295, 628, 408, +557, 446, 348, 373, 16, 197, -362, -36, +-674, -274, -825, -472, -806, -608, -645, -635, +-348, -525, 46, -309, 412, -34, 643, 251, +731, 500, 728, 667, 625, 723, 380, 661, +49, 486, -236, 231, -416, -38, -551, -272, +-617, -441, -511, -524, -260, -520, -16, -455, +148, -359, 270, -240, 360, -111, 348, -10, +209, 60, 40, 132, -53, 215, -68, 285, +-71, 324, -62, 338, -1, 338, 74, 332, +70, 303, -16, 234, -103, 125, -153, -27, +-190, -228, -227, -457, -206, -656, -84, -767, +86, -756, 225, -591, 336, -280, 420, 106, +429, 474, 336, 752, 171, 882, -21, 842, +-199, 656, -340, 369, -437, 47, -476, -243, +-444, -454, -349, -576, -230, -611, -100, -553, +62, -415, 249, -228, 409, -29, 514, 158, +597, 306, 643, 382, 554, 368, 293, 273, +-34, 128, -333, -35, -605, -177, -817, -248, +-860, -217, -690, -106, -388, 45, -73, 204, +219, 327, 488, 363, 671, 292, 689, 124, +553, -102, 357, -324, 156, -481, -48, -539, +-226, -484, -322, -320, -328, -83, -285, 173, +-249, 394, -228, 540, -192, 563, -149, 451, +-107, 252, -39, 23, 81, -191, 217, -351, +343, -418, 434, -374, 441, -246, 328, -95, +121, 20, -126, 82, -346, 104, -471, 105, +-461, 106, -318, 142, -96, 234, 127, 332, +269, 363, 294, 287, 212, 102, 74, -173, +-59, -470, -141, -691, -139, -754, -48, -623, +86, -319, 173, 83, 174, 471, 96, 736, +-37, 800, -184, 658, -275, 368, -266, 25, +-154, -281, 16, -471, 180, -493, 289, -363, +323, -145, 270, 71, 135, 207, -28, 233, +-153, 152, -217, -11, -221, -184, -170, -282, +-89, -264, -3, -139, 67, 51, 101, 250, +102, 399, 83, 437, 46, 338, -19, 131, +-91, -115, -133, -330, -122, -473, -72, -514, +-12, -431, 52, -237, 134, 12, 204, 251, +208, 439, 168, 546, 124, 537, 63, 406, +-36, 195, -136, -34, -192, -247, -207, -412, +-210, -482, -192, -432, -128, -290, -31, -103, +54, 79, 115, 215, 163, 272, 178, 232, +134, 110, 52, -49, -15, -194, -48, -283, +-52, -290, -37, -203, 4, -23, 64, 205, +101, 405, 77, 521, 16, 539, -27, 461, +-53, 287, -91, 42, -118, -220, -108, -443, +-88, -590, -88, -651, -101, -616, -93, -487, +-43, -290, 37, -62, 132, 158, 234, 335, +318, 439, 343, 456, 289, 412, 158, 356, +-23, 311, -203, 269, -336, 221, -421, 153, +-444, 40, -368, -142, -213, -369, -32, -574, +143, -690, 293, -666, 399, -495, 450, -217, +415, 102, 290, 380, 105, 535, -98, 533, +-283, 395, -403, 192, -409, 6, -296, -110, +-100, -130, 110, -56, 282, 76, 378, 197, +362, 260, 205, 242, -45, 132, -286, -59, +-455, -295, -531, -501, -486, -621, -298, -635, +-6, -531, 309, -302, 571, 22, 731, 363, +748, 644, 602, 805, 304, 804, -67, 635, +-421, 338, -690, -11, -809, -337, -741, -560, +-507, -624, -172, -529, 190, -315, 480, -48, +621, 196, 600, 347, 438, 368, 185, 264, +-77, 74, -285, -144, -408, -333, -431, -449, +-367, -461, -247, -355, -88, -152, 91, 107, +251, 385, 376, 629, 461, 779, 477, 786, +396, 632, 218, 327, -17, -69, -264, -468, +-491, -780, -662, -929, -707, -875, -575, -635, +-307, -280, 4, 86, 305, 376, 565, 544, +714, 579, 700, 497, 532, 335, 267, 147, +-35, -21, -321, -141, -531, -209, -604, -225, +-526, -186, -341, -114, -102, -25, 155, 63, +359, 121, 442, 123, 396, 76, 248, 5, +32, -62, -183, -99, -317, -92, -325, -48, +-219, 5, -47, 50, 145, 62, 311, 23, +394, -59, 350, -147, 198, -198, -3, -197, +-213, -139, -394, -35, -504, 83, -502, 188, +-377, 263, -164, 292, 64, 273, 266, 215, +427, 130, 526, 20, 534, -99, 452, -206, +311, -282, 129, -311, -72, -290, -257, -223, +-391, -133, -467, -45, -492, 20, -473, 48, +-395, 45, -236, 44, -12, 74, 232, 142, +449, 242, 581, 343, 581, 404, 454, 373, +236, 230, -29, -2, -273, -267, -426, -492, +-461, -605, -374, -568, -193, -393, 14, -139, +178, 115, 240, 294, 175, 352, 33, 300, +-89, 194, -144, 95, -116, 44, -8, 53, +146, 97, 293, 134, 378, 122, 355, 42, +229, -88, 30, -223, -224, -316, -476, -330, +-639, -261, -674, -130, -585, 27, -369, 163, +-48, 256, 305, 304, 612, 303, 835, 253, +924, 169, 823, 55, 540, -83, 151, -221, +-257, -324, -622, -364, -863, -333, -905, -228, +-754, -70, -499, 89, -206, 218, 103, 301, +380, 322, 548, 290, 594, 241, 574, 201, +491, 160, 329, 104, 122, 24, -83, -88, +-274, -224, -436, -359, -541, -457, -530, -495, +-373, -452, -136, -324, 97, -127, 296, 94, +444, 299, 475, 468, 375, 579, 195, 615, +10, 563, -134, 429, -237, 228, -288, -16, +-256, -280, -167, -525, -87, -692, -42, -739, +-9, -649, 33, -444, 74, -148, 108, 182, +129, 468, 145, 648, 150, 690, 131, 588, +79, 374, 8, 113, -49, -144, -85, -365, +-112, -508, -135, -540, -146, -473, -133, -341, +-116, -157, -129, 58, -150, 243, -126, 359, +-48, 403, 56, 370, 181, 261, 324, 118, +442, 0, 493, -66, 449, -76, 304, -48, +86, -27, -187, -65, -490, -172, -731, -323, +-822, -464, -747, -535, -532, -487, -214, -306, +145, -14, 469, 326, 696, 622, 782, 794, +739, 814, 589, 689, 346, 446, 51, 145, +-215, -164, -406, -449, -504, -669, -511, -776, +-452, -753, -336, -620, -180, -396, -24, -103, +96, 199, 181, 430, 230, 555, 225, 565, +151, 477, 55, 333, 0, 193, -1, 100, +24, 53, 58, 22, 107, -25, 146, -104, +133, -225, 54, -374, -44, -509, -131, -566, +-225, -501, -311, -317, -325, -53, -231, 239, +-62, 509, 120, 700, 271, 764, 387, 684, +442, 488, 379, 222, 202, -70, -10, -359, +-205, -597, -376, -722, -498, -711, -523, -575, +-415, -335, -198, -28, 32, 286, 224, 531, +388, 644, 498, 613, 494, 457, 383, 224, +240, -23, 92, -208, -79, -279, -260, -250, +-382, -179, -398, -112, -347, -77, -277, -87, +-169, -117, -10, -137, 138, -110, 218, -18, +238, 122, 227, 250, 168, 315, 47, 303, +-78, 221, -146, 92, -146, -35, -103, -101, +-30, -116, 74, -116, 190, -118, 244, -141, +197, -205, 94, -291, -26, -346, -171, -304, +-318, -148, -401, 98, -354, 377, -184, 612, +26, 741, 215, 707, 375, 488, 459, 126, +393, -289, 203, -669, -30, -934, -247, -1009, +-400, -857, -456, -511, -387, -51, -190, 419, +67, 796, 285, 996, 419, 965, 471, 714, +427, 319, 276, -108, 50, -472, -176, -719, +-339, -810, -444, -730, -505, -523, -475, -271, +-329, -26, -118, 192, 89, 371, 292, 485, +495, 524, 628, 500, 606, 416, 450, 262, +236, 52, -5, -176, -260, -374, -476, -494, +-583, -512, -558, -429, -449, -269, -297, -77, +-90, 80, 145, 151, 309, 138, 365, 83, +367, 23, 343, -1, 273, 57, 161, 203, +51, 383, -18, 515, -81, 537, -171, 414, +-234, 156, -222, -183, -201, -526, -202, -790, +-167, -903, -72, -840, 39, -621, 134, -287, +200, 105, 225, 484, 194, 785, 92, 966, +-36, 988, -118, 844, -124, 553, -67, 164, +23, -253, 124, -612, 208, -831, 226, -882, +128, -772, -64, -524, -279, -202, -447, 105, +-517, 350, -446, 516, -208, 580, 138, 534, +452, 417, 635, 273, 672, 108, 557, -71, +292, -225, -55, -304, -373, -307, -575, -251, +-622, -157, -541, -36, -343, 83, -48, 155, +234, 165, 392, 135, 425, 82, 372, 24, +252, -19, 90, -48, -86, -57, -219, -52, +-261, -35, -234, -16, -175, 4, -74, 36, +50, 77, 146, 92, 190, 65, 186, 13, +164, -46, 142, -101, 89, -134, -14, -121, +-117, -50, -196, 56, -270, 145, -322, 184, +-299, 159, -185, 66, -7, -79, 185, -215, +357, -276, 484, -253, 503, -151, 371, 12, +123, 182, -149, 280, -371, 279, -504, 195, +-513, 57, -371, -93, -129, -193, 114, -215, +304, -188, 401, -145, 369, -117, 225, -133, +31, -179, -155, -192, -265, -134, -265, 8, +-169, 221, -16, 456, 134, 622, 216, 632, +223, 455, 154, 124, 4, -275, -166, -637, +-284, -860, -312, -885, -236, -691, -69, -341, +132, 48, 302, 384, 383, 611, 335, 676, +189, 567, 2, 341, -181, 89, -313, -118, +-349, -241, -282, -259, -148, -190, -6, -76, +97, 29, 143, 70, 133, 24, 84, -79, +40, -191, 50, -272, 122, -277, 208, -178, +238, 2, 195, 186, 99, 312, -57, 359, +-257, 321, -424, 201, -491, 46, -445, -87, +-307, -156, -101, -156, 154, -116, 400, -65, +536, -26, 536, -9, 446, -12, 286, -11, +77, 13, -133, 68, -314, 134, -443, 178, +-477, 180, -409, 124, -255, 15, -43, -121, +165, -236, 321, -285, 388, -231, 340, -88, +212, 97, 67, 262, -84, 368, -217, 378, +-274, 273, -239, 94, -151, -86, -46, -208, +64, -256, 165, -218, 224, -101, 207, 39, +145, 132, 84, 162, 10, 134, -105, 48, +-223, -70, -270, -166, -231, -204, -142, -180, +-17, -94, 153, 35, 306, 173, 344, 279, +260, 319, 110, 264, -68, 138, -253, -21, +-397, -171, -418, -269, -280, -276, -59, -183, +152, -28, 328, 129, 448, 223, 444, 224, +309, 138, 110, -12, -77, -182, -221, -311, +-338, -358, -414, -317, -395, -217, -292, -91, +-176, 47, -57, 171, 92, 263, 247, 313, +357, 330, 397, 318, 377, 273, 338, 181, +266, 54, 125, -79, -43, -201, -188, -303, +-311, -379, -420, -423, -496, -442, -501, -432, +-412, -393, -253, -307, -54, -163, 175, 37, +409, 268, 582, 487, 632, 650, 554, 713, +407, 647, 218, 468, -18, 226, -242, -45, +-366, -295, -385, -469, -371, -547, -354, -560, +-310, -528, -227, -460, -142, -376, -77, -284, +21, -163, 170, -3, 296, 177, 350, 362, +360, 521, 339, 601, 279, 570, 174, 448, +42, 261, -60, 47, -112, -137, -161, -240, +-213, -257, -237, -228, -251, -196, -273, -194, +-279, -219, -256, -259, -179, -296, -44, -292, +114, -189, 273, 0, 422, 201, 521, 374, +521, 497, 420, 525, 244, 430, 14, 262, +-249, 87, -492, -64, -628, -171, -606, -212, +-460, -201, -236, -167, 33, -124, 288, -89, +448, -81, 463, -88, 372, -74, 229, -27, +50, 54, -115, 167, -191, 300, -177, 396, +-137, 400, -92, 285, -48, 66, -30, -205, +-43, -453, -65, -607, -49, -593, 26, -386, +107, -45, 155, 328, 196, 626, 204, 776, +136, 730, 23, 504, -81, 182, -165, -142, +-220, -398, -238, -540, -216, -550, -156, -462, +-82, -325, -15, -179, 50, -44, 110, 67, +162, 155, 215, 225, 254, 278, 245, 297, +191, 284, 116, 245, 26, 174, -65, 88, +-132, 7, -148, -56, -133, -110, -133, -157, +-155, -197, -175, -235, -197, -281, -219, -313, +-213, -302, -153, -242, -29, -137, 124, 3, +268, 151, 409, 275, 525, 355, 550, 375, +459, 344, 279, 282, 43, 199, -210, 87, +-447, -53, -624, -204, -677, -360, -597, -515, +-429, -629, -192, -645, 88, -531, 336, -283, +496, 49, 537, 393, 466, 674, 340, 832, +194, 816, 22, 618, -130, 301, -208, -57, +-237, -407, -254, -698, -251, -863, -207, -873, +-124, -738, -26, -479, 60, -114, 142, 292, +205, 646, 205, 871, 140, 913, 38, 751, +-70, 420, -159, 11, -192, -373, -143, -640, +-26, -731, 108, -639, 220, -420, 281, -157, +257, 71, 152, 221, -4, 275, -190, 250, +-371, 193, -482, 139, -489, 110, -383, 102, +-177, 111, 87, 125, 378, 122, 643, 99, +779, 61, 735, -4, 540, -93, 216, -191, +-188, -281, -565, -339, -819, -334, -894, -256, +-766, -109, -477, 100, -102, 328, 272, 503, +540, 576, 638, 539, 578, 398, 404, 175, +188, -64, 4, -260, -115, -382, -165, -424, +-149, -386, -100, -303, -55, -200, -34, -82, +-36, 35, -55, 141, -93, 257, -141, 380, +-161, 460, -140, 467, -91, 395, -16, 246, +78, 25, 166, -207, 228, -397, 248, -508, +227, -513, 181, -405, 99, -233, -35, -48, +-179, 134, -278, 283, -310, 362, -270, 370, +-181, 345, -63, 287, 81, 188, 210, 73, +285, -35, 318, -125, 311, -186, 233, -220, +90, -245, -76, -271, -226, -299, -330, -326, +-381, -334, -372, -268, -274, -112, -120, 125, +17, 405, 127, 662, 222, 797, 272, 749, +263, 520, 221, 156, 186, -259, 177, -618, +166, -825, 116, -861, 29, -745, -72, -520, +-196, -243, -332, 17, -418, 218, -400, 360, +-302, 457, -185, 505, -51, 495, 110, 434, +247, 317, 298, 143, 273, -63, 230, -247, +206, -387, 192, -471, 173, -483, 159, -421, +129, -315, 26, -194, -145, -66, -317, 61, +-446, 180, -505, 279, -477, 350, -352, 368, +-123, 321, 159, 210, 393, 49, 542, -128, +609, -266, 553, -339, 361, -341, 94, -266, +-182, -145, -419, -18, -567, 88, -600, 163, +-495, 198, -269, 214, 16, 234, 301, 247, +524, 222, 607, 148, 530, 21, 340, -166, +75, -376, -213, -532, -448, -571, -554, -476, +-513, -246, -359, 76, -127, 407, 136, 658, +350, 769, 444, 712, 419, 510, 320, 226, +174, -70, 7, -323, -146, -493, -249, -553, +-295, -510, -294, -390, -232, -223, -121, -27, +-12, 163, 66, 307, 125, 383, 162, 385, +162, 323, 143, 211, 110, 83, 60, -22, +1, -84, -50, -107, -73, -95, -54, -59, +-17, -16, 16, 20, 52, 47, 59, 62, +11, 51, -59, 10, -126, -64, -192, -149, +-242, -222, -239, -250, -159, -202, -3, -50, +177, 178, 327, 412, 419, 579, 413, 622, +296, 499, 113, 217, -87, -143, -261, -496, +-371, -753, -397, -837, -332, -722, -197, -460, +-27, -113, 135, 258, 230, 572, 232, 752, +178, 780, 111, 685, 35, 472, -29, 163, +-55, -181, -58, -485, -56, -703, -49, -793, +-32, -726, -12, -516, -8, -205, -26, 141, +-30, 428, -12, 586, 6, 595, 32, 460, +78, 216, 103, -62, 82, -280, 32, -395, +-28, -400, -81, -306, -113, -151, -126, 7, +-111, 135, -65, 213, -6, 220, 62, 171, +129, 90, 159, -7, 144, -111, 103, -198, +50, -250, -2, -256, -38, -210, -57, -108, +-65, 18, -87, 120, -130, 171, -166, 151, +-186, 70, -188, -41, -153, -132, -67, -160, +60, -104, 206, 26, 338, 187, 429, 315, +457, 368, 391, 326, 238, 188, 42, -15, +-179, -229, -386, -398, -530, -506, -588, -535, +-555, -475, -434, -327, -248, -123, -20, 96, +219, 311, 408, 499, 518, 615, 558, 630, +514, 548, 386, 388, 210, 179, 12, -52, +-170, -263, -301, -428, -381, -520, -403, -533, +-358, -477, -267, -353, -151, -170, -12, 47, +131, 260, 239, 433, 294, 525, 294, 524, +241, 434, 132, 270, -27, 53, -198, -150, +-325, -282, -380, -335, -355, -314, -233, -211, +-23, -50, 220, 99, 421, 197, 541, 241, +568, 227, 475, 141, 265, 10, 1, -117, +-251, -203, -456, -228, -583, -176, -603, -54, +-506, 98, -321, 248, -118, 351, 56, 372, +206, 291, 317, 129, 356, -79, 342, -273, +318, -405, 286, -449, 228, -388, 143, -241, +52, -47, -19, 148, -98, 309, -205, 401, +-302, 409, -351, 340, -348, 222, -303, 75, +-221, -82, -104, -227, 43, -331, 178, -377, +257, -359, 298, -273, 322, -132, 309, 34, +234, 170, 124, 252, 16, 263, -85, 191, +-194, 59, -287, -79, -315, -177, -284, -212, +-238, -179, -172, -92, -53, 16, 106, 102, +252, 152, 336, 153, 364, 104, 344, 31, +250, -38, 75, -113, -128, -191, -296, -240, +-402, -247, -444, -219, -402, -152, -236, -38, +19, 101, 251, 229, 396, 302, 459, 295, +422, 202, 267, 56, 31, -106, -217, -248, +-390, -329, -449, -320, -409, -230, -268, -103, +-32, 40, 221, 171, 410, 257, 493, 284, +454, 258, 303, 177, 81, 64, -159, -52, +-359, -171, -468, -288, -481, -363, -408, -368, +-256, -324, -39, -225, 187, -60, 362, 146, +454, 347, 460, 516, 387, 622, 245, 622, +55, 502, -141, 282, -291, -6, -385, -315, +-422, -571, -371, -721, -221, -734, -30, -612, +146, -379, 282, -95, 363, 179, 355, 389, +257, 505, 106, 525, -47, 478, -165, 402, +-241, 319, -261, 258, -205, 212, -101, 168, +-4, 94, 73, -27, 122, -196, 118, -387, +71, -555, 21, -659, -8, -667, -16, -570, +-18, -359, 0, -70, 50, 240, 97, 517, +111, 742, 103, 885, 78, 911, 15, 802, +-82, 576, -177, 258, -252, -130, -302, -530, +-300, -858, -212, -1043, -51, -1052, 136, -859, +309, -500, 442, -49, 493, 399, 435, 767, +278, 976, 53, 976, -187, 788, -385, 460, +-486, 60, -471, -335, -362, -632, -196, -785, +-2, -773, 178, -600, 287, -314, 305, 1, +259, 274, 166, 458, 42, 513, -72, 441, +-132, 287, -116, 114, -67, -45, -13, -152, +51, -200, 108, -206, 108, -204, 58, -203, +5, -201, -35, -192, -71, -151, -91, -69, +-81, 39, -54, 151, -34, 235, -43, 243, +-64, 165, -90, 24, -116, -135, -117, -263, +-60, -309, 53, -258, 185, -123, 292, 58, +336, 231, 310, 342, 218, 347, 81, 256, +-81, 100, -225, -84, -310, -266, -322, -385, +-282, -413, -197, -364, -74, -259, 43, -116, +120, 44, 155, 173, 165, 253, 148, 276, +97, 251, 13, 174, -67, 70, -115, -38, +-137, -122, -129, -156, -61, -123, 62, -43, +188, 52, 276, 148, 306, 219, 273, 235, +175, 171, 26, 46, -139, -114, -274, -263, +-358, -373, -390, -424, -369, -398, -304, -283, +-203, -94, -87, 121, 31, 333, 151, 502, +280, 593, 394, 578, 457, 473, 458, 297, +406, 77, 297, -135, 134, -286, -66, -373, +-259, -407, -404, -377, -487, -299, -500, -208, +-444, -123, -323, -21, -165, 84, 7, 186, +166, 272, 287, 332, 346, 352, 347, 327, +304, 265, 221, 166, 121, 51, 35, -48, +-19, -112, -37, -157, -23, -175, -8, -169, +-19, -151, -68, -138, -150, -131, -255, -130, +-353, -116, -397, -74, -354, -7, -208, 88, +12, 205, 260, 338, 480, 442, 621, 485, +643, 430, 540, 273, 333, 35, 41, -243, +-288, -510, -582, -715, -772, -799, -813, -735, +-685, -527, -414, -216, -57, 151, 321, 505, +648, 784, 856, 927, 904, 907, 768, 726, +471, 408, 81, 1, -316, -413, -650, -742, +-871, -938, -922, -961, -786, -815, -499, -528, +-144, -175, 214, 170, 530, 439, 756, 581, +827, 576, 720, 462, 485, 295, 188, 115, +-116, -24, -383, -95, -541, -105, -563, -92, +-472, -75, -328, -84, -163, -124, 9, -193, +158, -260, 235, -292, 231, -273, 200, -205, +169, -117, 128, -17, 63, 78, -8, 153, +-60, 196, -90, 233, -107, 272, -93, 293, +-34, 276, 45, 214, 96, 101, 105, -68, +83, -262, 28, -441, -53, -554, -140, -561, +-192, -434, -184, -208, -118, 68, -17, 344, +94, 565, 182, 674, 217, 638, 179, 474, +83, 217, -25, -66, -113, -322, -169, -489, +-191, -544, -160, -481, -78, -333, 24, -141, +111, 46, 186, 187, 249, 266, 252, 285, +173, 262, 47, 216, -79, 176, -201, 144, +-298, 128, -335, 104, -277, 67, -139, 17, +23, -33, 164, -77, 266, -111, 307, -124, +267, -114, 161, -87, 21, -66, -111, -48, +-215, -38, -270, -26, -268, -15, -203, 7, +-90, 34, 39, 72, 167, 136, 281, 207, +362, 261, 378, 287, 317, 297, 175, 262, +-24, 177, -238, 38, -422, -127, -533, -296, +-535, -429, -426, -499, -236, -483, -16, -362, +196, -158, 369, 78, 467, 286, 487, 439, +423, 502, 300, 459, 138, 314, -29, 127, +-166, -58, -252, -195, -290, -253, -285, -242, +-231, -185, -145, -104, -52, -25, 22, 7, +70, -1, 75, -51, 39, -119, -16, -179, +-55, -188, -65, -147, -47, -60, -3, 72, +69, 225, 160, 346, 240, 383, 290, 330, +289, 181, 222, -43, 87, -296, -80, -499, +-249, -602, -390, -568, -471, -399, -454, -136, +-331, 155, -137, 406, 94, 565, 313, 577, +471, 451, 511, 220, 420, -48, 232, -305, +5, -499, -214, -595, -371, -567, -429, -422, +-392, -204, -280, 45, -125, 270, 54, 434, +226, 494, 371, 445, 463, 293, 475, 92, +381, -109, 198, -264, -29, -348, -263, -341, +-478, -255, -629, -125, -653, 12, -526, 121, +-277, 183, 18, 182, 306, 144, 524, 71, +618, -17, 565, -108, 408, -167, 206, -179, +6, -142, -155, -51, -252, 71, -269, 205, +-226, 320, -164, 390, -112, 365, -70, 250, +-46, 74, -43, -121, -64, -307, -97, -430, +-113, -449, -87, -367, -24, -198, 58, 13, +149, 211, 234, 346, 294, 415, 303, 407, +264, 331, 184, 208, 76, 94, -46, -3, +-153, -90, -220, -160, -259, -204, -279, -215, +-289, -196, -281, -135, -247, -50, -185, 65, +-86, 186, 65, 278, 245, 303, 409, 261, +511, 158, 527, 9, 445, -149, 265, -283, +18, -350, -235, -325, -428, -192, -536, 7, +-546, 223, -453, 395, -263, 491, -30, 476, +179, 331, 320, 87, 393, -185, 401, -408, +325, -535, 176, -536, 3, -426, -135, -224, +-229, 17, -260, 239, -216, 377, -110, 425, +12, 398, 96, 321, 122, 197, 94, 37, +33, -113, -46, -244, -108, -350, -137, -435, +-116, -456, -45, -404, 59, -273, 156, -92, +223, 112, 245, 301, 208, 441, 108, 496, +-36, 431, -177, 277, -295, 69, -371, -140, +-378, -323, -291, -438, -122, -478, 99, -432, +319, -314, 485, -149, 550, 7, 486, 119, +308, 201, 52, 242, -221, 231, -444, 166, +-551, 84, -521, -5, -385, -79, -200, -126, +0, -144, 175, -139, 289, -92, 326, -18, +293, 40, 221, 75, 131, 76, 56, 50, +8, -15, -6, -94, -4, -168, 5, -190, +2, -153, -23, -68, -74, 43, -142, 155, +-215, 244, -274, 272, -293, 218, -257, 93, +-150, -53, 0, -193, 160, -280, 291, -287, +377, -204, 396, -61, 334, 118, 207, 283, +72, 384, -26, 405, -98, 332, -155, 192, +-199, 16, -218, -152, -228, -294, -240, -370, +-247, -377, -211, -312, -126, -193, -11, -38, +116, 133, 244, 287, 343, 394, 361, 421, +302, 383, 203, 297, 103, 194, -1, 75, +-100, -29, -180, -94, -231, -119, -252, -137, +-243, -170, -194, -210, -115, -252, -24, -262, +64, -234, 136, -155, 160, -30, 141, 147, +101, 314, 60, 432, 26, 482, 10, 464, +29, 378, 78, 237, 128, 76, 145, -85, +112, -215, 18, -319, -115, -394, -250, -443, +-339, -442, -373, -394, -351, -292, -275, -146, +-140, 32, 32, 229, 208, 417, 373, 565, +510, 630, 590, 595, 568, 452, 443, 242, +233, -25, -29, -317, -314, -586, -563, -762, +-713, -808, -737, -713, -635, -490, -436, -186, +-167, 161, 127, 473, 399, 677, 588, 719, +670, 618, 646, 398, 537, 117, 349, -179, +95, -419, -178, -546, -407, -557, -537, -473, +-560, -341, -488, -178, -334, -23, -122, 113, +90, 195, 249, 230, 333, 240, 355, 245, +323, 228, 244, 177, 153, 100, 77, 7, +8, -86, -91, -191, -213, -294, -320, -383, +-372, -426, -369, -419, -310, -352, -185, -230, +7, -60, 221, 147, 392, 357, 479, 524, +472, 615, 387, 628, 243, 541, 78, 376, +-80, 139, -213, -144, -322, -430, -387, -657, +-395, -808, -349, -858, -265, -777, -156, -555, +-31, -215, 93, 175, 206, 556, 280, 851, +313, 1023, 306, 1031, 272, 882, 215, 587, +142, 209, 55, -181, -37, -525, -127, -789, +-210, -941, -270, -937, -299, -795, -287, -533, +-234, -193, -132, 191, -7, 557, 111, 851, +184, 1001, 211, 985, 209, 816, 197, 521, +182, 156, 145, -223, 84, -544, 2, -758, +-78, -817, -156, -741, -216, -549, -238, -279, +-204, 42, -131, 358, -41, 601, 51, 719, +124, 704, 153, 581, 128, 363, 78, 95, +38, -170, 33, -367, 44, -468, 60, -457, +59, -376, 41, -259, -3, -133, -77, -18, +-155, 81, -191, 159, -157, 233, -77, 311, +19, 402, 95, 443, 145, 402, 148, 264, +98, 47, 15, -226, -58, -492, -100, -681, +-119, -735, -118, -623, -90, -388, -31, -87, +31, 202, 78, 436, 115, 571, 167, 602, +204, 524, 199, 386, 144, 227, 56, 65, +-55, -97, -174, -257, -258, -398, -287, -506, +-255, -553, -191, -556, -116, -497, -45, -374, +18, -190, 65, 14, 115, 218, 177, 397, +250, 537, 319, 631, 344, 641, 304, 548, +191, 346, 21, 79, -185, -236, -379, -551, +-515, -814, -545, -942, -455, -889, -267, -669, +-23, -337, 227, 45, 423, 409, 513, 679, +500, 821, 404, 787, 258, 608, 71, 348, +-128, 78, -294, -185, -378, -396, -380, -520, +-327, -557, -243, -523, -145, -449, -53, -340, +4, -201, 42, -28, 92, 147, 185, 325, +294, 479, 391, 596, 456, 642, 465, 584, +371, 403, 147, 130, -162, -184, -468, -491, +-690, -724, -784, -840, -708, -788, -467, -563, +-107, -199, 257, 202, 526, 572, 648, 846, +629, 971, 489, 920, 264, 696, 10, 351, +-214, -40, -349, -400, -386, -692, -340, -860, +-237, -892, -86, -762, 70, -489, 189, -121, +241, 266, 235, 621, 182, 890, 76, 1002, +-52, 934, -150, 701, -175, 372, -153, 6, +-104, -333, -43, -617, 19, -787, 32, -819, +-11, -730, -66, -561, -83, -332, -52, -52, +13, 254, 109, 551, 204, 773, 267, 896, +261, 885, 196, 736, 92, 451, -12, 77, +-103, -328, -166, -677, -191, -903, -185, -980, +-170, -889, -176, -648, -192, -291, -188, 107, +-129, 488, -35, 762, 78, 902, 201, 886, +326, 719, 404, 421, 393, 55, 297, -305, +152, -583, -4, -727, -160, -753, -285, -662, +-362, -488, -377, -266, -343, -61, -266, 104, +-144, 220, 24, 318, 195, 411, 311, 472, +349, 490, 329, 458, 269, 371, 159, 205, +25, -29, -92, -305, -153, -537, -177, -692, +-194, -751, -204, -705, -193, -552, -173, -330, +-162, -78, -133, 177, -50, 386, 90, 547, +235, 653, 350, 696, 407, 636, 391, 485, +277, 252, 93, -30, -101, -334, -257, -619, +-358, -826, -405, -905, -385, -827, -310, -621, +-187, -308, -49, 47, 87, 408, 209, 709, +312, 897, 379, 923, 393, 790, 345, 515, +240, 145, 89, -245, -101, -601, -288, -830, +-422, -871, -465, -727, -438, -467, -364, -131, +-243, 198, -64, 454, 141, 581, 328, 575, +471, 478, 561, 342, 570, 205, 464, 75, +271, -28, 33, -117, -206, -185, -435, -254, +-607, -320, -672, -360, -606, -318, -440, -202, +-214, -44, 38, 141, 284, 309, 487, 431, +600, 472, 612, 418, 527, 267, 370, 93, +152, -67, -87, -187, -304, -256, -450, -260, +-507, -203, -478, -105, -376, -10, -219, 45, +-42, 81, 94, 92, 183, 102, 238, 117, +288, 156, 317, 194, 310, 236, 261, 245, +187, 184, 82, 50, -72, -149, -255, -363, +-406, -541, -453, -616, -400, -556, -272, -327, +-91, 28, 120, 429, 291, 767, 367, 969, +351, 978, 280, 783, 169, 406, 25, -80, +-100, -550, -158, -918, -151, -1118, -143, -1132, +-147, -951, -142, -621, -108, -177, -52, 298, +15, 720, 72, 1032, 112, 1187, 134, 1149, +121, 903, 79, 491, 12, -31, -57, -547, +-111, -974, -127, -1231, -102, -1268, -33, -1069, +41, -682, 81, -182, 88, 323, 81, 729, +61, 984, 10, 1040, -49, 895, -86, 573, +-79, 163, -56, -258, -27, -585, 19, -778, +86, -819, 137, -703, 145, -457, 109, -154, +45, 126, -34, 338, -129, 450, -205, 489, +-237, 450, -221, 352, -181, 214, -113, 72, +-9, -78, 120, -230, 223, -377, 262, -510, +255, -587, 230, -576, 196, -469, 136, -274, +62, 13, -24, 336, -103, 644, -175, 858, +-227, 936, -249, 866, -243, 658, -216, 322, +-176, -103, -126, -532, -71, -902, 8, -1137, +98, -1206, 177, -1096, 237, -811, 298, -361, +336, 169, 319, 693, 247, 1121, 150, 1384, +40, 1448, -98, 1297, -245, 936, -360, 405, +-409, -182, -410, -744, -369, -1193, -275, -1464, +-113, -1489, 79, -1252, 261, -782, 409, -184, +501, 429, 507, 965, 403, 1314, 216, 1422, +-10, 1260, -216, 886, -373, 400, -451, -69, +-435, -477, -326, -772, -169, -918, -15, -925, +105, -822, 183, -641, 223, -398, 226, -100, +205, 264, 175, 639, 155, 962, 127, 1157, +79, 1170, 4, 962, -81, 550, -162, -16, +-231, -616, -277, -1101, -275, -1383, -209, -1402, +-115, -1159, -22, -704, 65, -147, 157, 422, +218, 882, 234, 1176, 217, 1283, 193, 1202, +157, 952, 88, 574, -1, 118, -79, -361, +-137, -777, -198, -1096, -251, -1268, -267, -1262, +-209, -1051, -97, -670, 34, -167, 164, 367, +276, 855, 335, 1227, 309, 1399, 205, 1328, +57, 1020, -99, 528, -257, -80, -380, -686, +-426, -1201, -372, -1525, -244, -1591, -73, -1387, +110, -965, 280, -383, 407, 279, 472, 907, +482, 1412, 438, 1702, 348, 1740, 191, 1507, +-25, 1028, -269, 342, -488, -438, -657, -1202, +-762, -1825, -770, -2178, -642, -2186, -379, -1826, +-33, -1141, 345, -229, 702, 745, 976, 1617, +1082, 2206, 1006, 2410, 765, 2203, 398, 1635, +-54, 802, -519, -134, -904, -1014, -1146, -1701, +-1208, -2079, -1078, -2119, -759, -1831, -306, -1278, +203, -551, 676, 217, 1039, 922, 1228, 1457, +1215, 1757, 1001, 1793, 622, 1560, 134, 1090, +-382, 468, -826, -201, -1132, -842, -1240, -1346, +-1136, -1651, -841, -1691, -419, -1450, 66, -953, +537, -293, 919, 425, 1135, 1086, 1142, 1575, +962, 1810, 649, 1732, 269, 1359, -135, 768, +-501, 77, -791, -626, -964, -1220, -1005, -1623, +-920, -1783, -734, -1681, -452, -1326, -82, -769, +321, -82, 705, 656, 1014, 1327, 1205, 1831, +1225, 2076, 1047, 2014, 679, 1628, 184, 965, +-380, 103, -937, -808, -1382, -1609, -1606, -2170, +-1548, -2384, -1219, -2209, -671, -1650, 11, -786, +733, 247, 1362, 1247, 1772, 2054, 1869, 2516, +1642, 2535, 1124, 2092, 394, 1275, -420, 227, +-1162, -858, -1686, -1762, -1909, -2329, -1798, -2447, +-1389, -2120, -748, -1425, -2, -523, 709, 421, +1268, 1230, 1610, 1790, 1680, 2028, 1462, 1921, +1015, 1521, 437, 911, -165, 190, -700, -547, +-1094, -1184, -1300, -1646, -1288, -1845, -1092, -1748, +-764, -1375, -355, -791, 84, -78, 482, 639, +776, 1238, 944, 1632, 996, 1747, 941, 1579, +753, 1168, 452, 591, 92, -78, -260, -721, +-582, -1254, -841, -1596, -982, -1716, -966, -1598, +-809, -1239, -544, -672, -193, 18, 214, 717, +613, 1339, 909, 1761, 1064, 1910, 1068, 1737, +920, 1265, 606, 552, 158, -272, -342, -1075, +-790, -1723, -1113, -2081, -1265, -2090, -1202, -1735, +-920, -1074, -459, -211, 80, 699, 594, 1502, +994, 2033, 1232, 2211, 1273, 2010, 1109, 1461, +762, 652, 290, -269, -223, -1136, -708, -1814, +-1088, -2176, -1283, -2166, -1241, -1777, -999, -1075, +-610, -171, -129, 759, 388, 1561, 830, 2087, +1103, 2232, 1181, 1972, 1078, 1355, 806, 505, +405, -413, -27, -1224, -417, -1799, -720, -2017, +-920, -1872, -972, -1404, -875, -720, -667, 54, +-387, 784, -61, 1361, 287, 1692, 591, 1720, +790, 1476, 853, 998, 787, 368, 607, -314, +363, -917, 91, -1344, -174, -1511, -408, -1410, +-574, -1069, -654, -548, -648, 52, -571, 610, +-442, 1029, -257, 1261, -45, 1269, 175, 1081, +377, 724, 547, 267, 652, -215, 675, -649, +598, -994, 425, -1187, 186, -1186, -94, -993, +-379, -620, -618, -127, -748, 424, -753, 931, +-635, 1294, -409, 1426, -100, 1312, 224, 955, +495, 406, 656, -237, 685, -857, 595, -1341, +414, -1593, 196, -1552, -19, -1242, -203, -693, +-344, -6, -423, 690, -455, 1259, -451, 1596, +-419, 1622, -348, 1353, -213, 848, -7, 190, +241, -482, 470, -1043, 632, -1395, 687, -1502, +616, -1344, 407, -967, 112, -421, -193, 190, +-438, 755, -589, 1181, -643, 1398, -591, 1352, +-434, 1045, -227, 531, -32, -118, 146, -759, +304, -1259, 427, -1514, 488, -1469, 495, -1112, +450, -526, 355, 175, 190, 837, -31, 1316, +-257, 1529, -449, 1450, -571, 1107, -603, 564, +-530, -60, -372, -671, -143, -1156, 120, -1457, +367, -1526, 551, -1342, 657, -924, 661, -354, +535, 284, 299, 908, 3, 1391, -286, 1649, +-533, 1615, -705, 1294, -758, 734, -658, 41, +-448, -694, -184, -1321, 102, -1699, 392, -1762, +643, -1507, 792, -977, 818, -260, 730, 511, +539, 1199, 239, 1650, -128, 1801, -495, 1633, +-785, 1179, -973, 508, -1013, -253, -867, -977, +-552, -1528, -138, -1801, 288, -1774, 665, -1448, +930, -875, 1046, -131, 985, 662, 774, 1383, +450, 1882, 60, 2083, -345, 1948, -702, 1465, +-961, 683, -1077, -270, -1015, -1216, -775, -1976, +-380, -2391, 96, -2395, 565, -1950, 935, -1117, +1151, -46, 1172, 1048, 984, 1971, 604, 2544, +107, 2666, -409, 2309, -854, 1517, -1169, 430, +-1312, -751, -1226, -1799, -918, -2532, -437, -2802, +136, -2563, 718, -1833, 1203, -744, 1500, 491, +1529, 1636, 1274, 2489, 794, 2886, 173, 2734, +-483, 2072, -1072, 1023, -1485, -200, -1643, -1384, +-1513, -2318, -1143, -2840, -608, -2835, 22, -2331, +664, -1436, 1206, -289, 1555, 919, 1667, 1972, +1515, 2680, 1110, 2929, 504, 2681, -197, 1993, +-876, 943, -1405, -292, -1697, -1492, -1700, -2452, +-1406, -3019, -875, -3086, -204, -2627, 494, -1704, +1104, -453, 1527, 893, 1701, 2106, 1585, 2968, +1202, 3317, 616, 3057, -76, 2245, -772, 1020, +-1346, -397, -1679, -1744, -1716, -2764, -1450, -3258, +-918, -3150, -210, -2479, 528, -1392, 1162, -82, +1574, 1190, 1702, 2203, 1530, 2796, 1098, 2889, +484, 2485, -202, 1678, -853, 611, -1361, -540, +-1628, -1574, -1623, -2327, -1344, -2664, -820, -2539, +-137, -1973, 567, -1086, 1175, -9, 1584, 1066, +1711, 1942, 1515, 2455, 1044, 2529, 411, 2172, +-268, 1444, -893, 463, -1375, -608, -1611, -1557, +-1556, -2232, -1251, -2512, -778, -2362, -177, -1805, +460, -932, 1020, 138, 1413, 1206, 1578, 2062, +1498, 2561, 1177, 2609, 652, 2194, 8, 1362, +-628, 258, -1164, -922, -1513, -1913, -1628, -2536, +-1480, -2696, -1079, -2375, -485, -1606, 190, -517, +833, 666, 1358, 1699, 1687, 2391, 1742, 2650, +1477, 2411, 940, 1710, 221, 682, -540, -442, +-1208, -1433, -1667, -2084, -1826, -2297, -1640, -2070, +-1162, -1469, -502, -643, 219, 226, 863, 959, +1330, 1443, 1551, 1628, 1521, 1553, 1274, 1261, +849, 812, 294, 274, -281, -255, -759, -706, +-1086, -1052, -1269, -1266, -1294, -1307, -1113, -1125, +-754, -743, -303, -227, 145, 325, 556, 842, +886, 1221, 1079, 1380, 1082, 1256, 930, 877, +696, 354, 395, -196, 39, -671, -329, -1007, +-639, -1148, -845, -1078, -939, -816, -936, -453, +-795, -70, -515, 271, -165, 558, 172, 756, +464, 826, 703, 765, 858, 609, 889, 400, +785, 148, 597, -123, 354, -384, 69, -574, +-257, -687, -563, -718, -794, -664, -930, -514, +-952, -279, -837, 12, -578, 314, -209, 564, +183, 722, 516, 750, 796, 650, 989, 422, +1035, 113, 922, -213, 703, -462, 415, -590, +68, -605, -333, -531, -720, -387, -1010, -188, +-1186, 9, -1233, 159, -1100, 236, -745, 280, +-222, 312, 374, 327, 947, 313, 1409, 299, +1643, 283, 1581, 245, 1220, 146, 623, -41, +-99, -287, -835, -552, -1448, -772, -1802, -911, +-1826, -903, -1522, -713, -929, -322, -152, 202, +669, 752, 1384, 1225, 1853, 1536, 1990, 1609, +1758, 1386, 1190, 873, 403, 132, -447, -684, +-1230, -1423, -1823, -1953, -2107, -2189, -1992, -2051, +-1516, -1529, -788, -689, 99, 322, 1013, 1321, +1769, 2149, 2198, 2661, 2225, 2736, 1860, 2287, +1165, 1368, 210, 137, -822, -1158, -1698, -2283, +-2258, -3033, -2416, -3226, -2111, -2773, -1366, -1756, +-330, -394, 764, 1057, 1680, 2327, 2273, 3204, +2434, 3498, 2122, 3123, 1376, 2140, 352, 768, +-733, -750, -1663, -2173, -2266, -3257, -2430, -3776, +-2120, -3592, -1393, -2733, -378, -1354, 698, 308, +1635, 2000, 2270, 3397, 2467, 4213, 2183, 4255, +1486, 3493, 499, 2064, -590, 220, -1574, -1729, +-2276, -3434, -2546, -4539, -2327, -4828, -1663, -4221, +-687, -2823, 420, -877, 1453, 1283, 2245, 3295, +2626, 4740, 2497, 5302, 1881, 4861, 930, 3501, +-160, 1477, -1245, -861, -2150, -3092, -2675, -4778, +-2697, -5541, -2216, -5254, -1317, -4002, -167, -2037, +1049, 307, 2092, 2619, 2752, 4474, 2926, 5489, +2580, 5478, 1731, 4497, 531, 2733, -759, 475, +-1913, -1916, -2750, -4000, -3132, -5375, -2926, -5753, +-2135, -5107, -945, -3572, 373, -1382, 1615, 1126, +2619, 3469, 3186, 5156, 3141, 5857, 2487, 5484, +1412, 4160, 99, 2082, -1272, -401, -2468, -2812, +-3204, -4656, -3295, -5602, -2765, -5522, -1766, -4496, +-432, -2699, 1026, -406, 2310, 1963, 3156, 3943, +3401, 5150, 3018, 5396, 2086, 4685, 759, 3160, +-747, 1029, -2148, -1315, -3177, -3377, -3615, -4735, +-3377, -5178, -2521, -4685, -1182, -3365, 420, -1437, +1996, 770, 3220, 2790, 3859, 4224, 3815, 4847, +3080, 4609, 1735, 3561, 35, 1866, -1673, -202, +-3084, -2229, -3964, -3779, -4153, -4581, -3570, -4545, +-2303, -3709, -633, -2189, 1110, -231, 2674, 1778, +3804, 3376, 4261, 4267, 3909, 4365, 2826, 3687, +1254, 2313, -526, 473, -2220, -1431, -3514, -2959, +-4127, -3805, -3944, -3912, -3033, -3305, -1613, -2079, +71, -457, 1725, 1179, 3039, 2478, 3767, 3214, +3775, 3330, 3088, 2857, 1876, 1855, 345, 498, +-1260, -917, -2615, -2073, -3451, -2776, -3614, -2930, +-3115, -2565, -2070, -1714, -642, -504, 929, 799, +2301, 1893, 3191, 2594, 3460, 2825, 3090, 2552, +2152, 1788, 809, 620, -655, -700, -1957, -1873, +-2858, -2661, -3207, -2947, -2954, -2662, -2174, -1846, +-1019, -625, 284, 740, 1523, 1917, 2494, 2673, +2983, 2909, 2897, 2618, 2271, 1823, 1230, 658, +-26, -649, -1264, -1779, -2280, -2513, -2843, -2776, +-2819, -2561, -2238, -1844, -1246, -719, -44, 559, +1153, 1679, 2118, 2407, 2646, 2673, 2628, 2453, +2095, 1737, 1167, 602, 38, -666, -1081, -1748, +-1952, -2420, -2398, -2606, -2366, -2303, -1882, -1524, +-1036, -381, -11, 851, 984, 1839, 1754, 2392, +2122, 2453, 2054, 2066, 1607, 1280, 889, 199, +36, -944, -800, -1835, -1456, -2304, -1781, -2349, +-1748, -2001, -1433, -1287, -909, -268, -229, 840, +524, 1751, 1178, 2266, 1587, 2365, 1701, 2054, +1540, 1344, 1110, 302, 428, -846, -401, -1787, +-1146, -2308, -1627, -2377, -1813, -2043, -1671, -1317, +-1184, -290, -431, 832, 405, 1745, 1128, 2246, +1616, 2303, 1826, 1979, 1685, 1290, 1195, 293, +500, -791, -250, -1677, -943, -2166, -1475, -2241, +-1730, -1945, -1660, -1300, -1306, -348, -750, 699, +-53, 1570, 678, 2070, 1300, 2163, 1673, 1880, +1714, 1237, 1454, 295, 951, -736, 283, -1532, +-436, -1914, -1066, -1871, -1480, -1476, -1580, -776, +-1416, 113, -1062, 960, -529, 1476, 130, 1559, +752, 1291, 1169, 772, 1330, 89, 1289, -629, +1095, -1168, 712, -1361, 182, -1168, -371, -716, +-815, -128, -1109, 500, -1236, 1054, -1154, 1383, +-834, 1389, -340, 1082, 219, 557, 727, -59, +1070, -694, 1200, -1238, 1091, -1569, 776, -1572, +312, -1255, -238, -693, -755, -4, -1067, 718, +-1123, 1353, -973, 1742, -663, 1774, -235, 1423, +252, 774, 647, -40, 834, -840, 854, -1476, +806, -1792, 681, -1693, 442, -1181, 121, -402, +-176, 430, -408, 1117, -613, 1539, -794, 1627, +-899, 1322, -852, 690, -645, -84, -344, -784, +-7, -1297, 378, -1554, 769, -1505, 1079, -1105, +1201, -440, 1063, 292, 730, 934, 304, 1410, +-173, 1653, -652, 1568, -1033, 1144, -1234, 468, +-1201, -287, -967, -1003, -597, -1569, -132, -1860, +388, -1767, 877, -1293, 1229, -542, 1354, 334, +1232, 1153, 901, 1757, 417, 1989, -140, 1785, +-726, 1187, -1244, 347, -1572, -579, -1620, -1403, +-1358, -1957, -826, -2104, -123, -1786, 661, -1069, +1390, -117, 1872, 888, 2010, 1769, 1791, 2301, +1252, 2337, 465, 1846, -439, 950, -1291, -168, +-1931, -1294, -2265, -2209, -2216, -2682, -1755, -2585, +-979, -1965, -47, -960, 882, 237, 1702, 1425, +2286, 2370, 2482, 2872, 2227, 2809, 1606, 2226, +717, 1233, -316, -21, -1346, -1320, -2178, -2410, +-2591, -3058, -2517, -3119, -2024, -2570, -1185, -1530, +-91, -173, 1046, 1248, 1972, 2458, 2488, 3181, +2542, 3253, 2158, 2670, 1368, 1579, 298, 182, +-814, -1279, -1729, -2476, -2296, -3133, -2419, -3121, +-2059, -2492, -1281, -1382, -301, -4, 690, 1393, +1533, 2484, 2059, 3016, 2150, 2913, 1800, 2236, +1127, 1116, 306, -248, -543, -1574, -1306, -2562, +-1782, -2961, -1872, -2720, -1597, -1912, -1048, -705, +-336, 667, 429, 1884, 1119, 2675, 1564, 2872, +1667, 2464, 1447, 1580, 969, 389, 325, -882, +-391, -1971, -1021, -2634, -1413, -2770, -1483, -2357, +-1252, -1488, -793, -297, -193, 1000, 461, 2133, +1013, 2848, 1310, 2985, 1317, 2514, 1047, 1499, +566, 136, -35, -1321, -664, -2548, -1186, -3252, +-1422, -3261, -1319, -2578, -919, -1327, -296, 242, +446, 1804, 1153, 3025, 1612, 3603, 1678, 3407, +1356, 2506, 737, 1098, -84, -567, -948, -2150, +-1637, -3304, -1944, -3768, -1831, -3473, -1362, -2511, +-597, -1061, 334, 641, 1222, 2259, 1848, 3412, +2077, 3870, 1901, 3559, 1398, 2556, 605, 1029, +-357, -739, -1273, -2379, -1929, -3507, -2185, -3897, +-2012, -3509, -1466, -2426, -617, -856, 397, 894, +1341, 2436, 2004, 3432, 2247, 3695, 2050, 3254, +1455, 2193, 578, 684, -422, -984, -1350, -2428, +-2018, -3346, -2283, -3603, -2110, -3202, -1556, -2200, +-708, -708, 276, 959, 1247, 2417, 2024, 3364, +2440, 3675, 2408, 3294, 1922, 2261, 1026, 721, +-99, -1001, -1228, -2496, -2143, -3463, -2642, -3754, +-2633, -3330, -2120, -2228, -1200, -641, -37, 1096, +1134, 2544, 2079, 3407, 2599, 3591, 2616, 3117, +2128, 2023, 1225, 483, 97, -1154, -1011, -2478, +-1858, -3226, -2303, -3364, -2320, -2898, -1914, -1833, +-1132, -317, -150, 1260, 825, 2515, 1587, 3211, +1994, 3289, 2006, 2742, 1626, 1597, 914, 68, +47, -1454, -757, -2600, -1341, -3181, -1628, -3135, +-1613, -2493, -1288, -1336, -702, 134, 14, 1560, +694, 2577, 1205, 3036, 1469, 2931, 1436, 2290, +1080, 1190, 469, -181, -229, -1487, -855, -2414, +-1274, -2827, -1434, -2741, -1314, -2141, -890, -1083, +-238, 226, 469, 1467, 1085, 2364, 1492, 2789, +1599, 2697, 1370, 2075, 820, 991, 74, -301, +-683, -1508, -1301, -2382, -1684, -2774, -1764, -2620, +-1530, -1952, -1001, -880, -249, 367, 585, 1495, +1324, 2288, 1819, 2621, 2018, 2468, 1876, 1859, +1350, 900, 534, -212, -358, -1202, -1148, -1907, +-1740, -2263, -2092, -2229, -2101, -1784, -1675, -1017, +-918, -123, -29, 707, 841, 1364, 1588, 1807, +2084, 1925, 2193, 1672, 1829, 1128, 1115, 442, +251, -282, -617, -940, -1398, -1424, -1949, -1622, +-2096, -1486, -1784, -1078, -1134, -512, -330, 90, +509, 628, 1257, 995, 1774, 1149, 1907, 1063, +1642, 790, 1104, 426, 409, 59, -357, -265, +-1068, -511, -1592, -660, -1805, -708, -1648, -658, +-1206, -550, -580, -394, 143, -186, 867, 67, +1459, 310, 1772, 526, 1713, 680, 1341, 731, +778, 648, 102, 429, -617, 134, -1244, -178, +-1600, -462, -1612, -684, -1351, -764, -926, -685, +-380, -495, 248, -260, 844, -6, 1214, 254, +1295, 487, 1179, 611, 931, 592, 568, 496, +105, 370, -362, 202, -689, -43, -830, -306, +-853, -491, -779, -534, -602, -500, -335, -426, +-28, -253, 224, 39, 373, 346, 453, 526, +500, 544, 487, 453, 386, 306, 223, 62, +95, -259, 0, -524, -111, -604, -236, -515, +-321, -333, -332, -95, -308, 201, -284, 516, +-225, 719, -97, 738, 47, 596, 182, 365, +293, 55, 375, -305, 409, -649, 370, -865, +246, -894, 54, -760, -174, -492, -378, -97, +-492, 376, -519, 801, -461, 1085, -317, 1175, +-73, 1049, 212, 671, 452, 92, 589, -536, +617, -1038, 529, -1334, 328, -1383, 39, -1117, +-268, -545, -480, 188, -570, 866, -558, 1355, +-451, 1586, -273, 1512, -81, 1061, 117, 311, +281, -531, 366, -1258, 389, -1739, 369, -1874, +328, -1591, 258, -918, 144, 18, 14, 992, +-87, 1788, -183, 2216, -304, 2184, -436, 1684, +-499, 787, -459, -366, -365, -1514, -238, -2357, +-60, -2709, 187, -2509, 463, -1776, 676, -592, +781, 811, 814, 2082, 726, 2895, 451, 3102, +0, 2672, -521, 1653, -963, 213, -1241, -1315, +-1331, -2561, -1164, -3268, -694, -3306, -45, -2662, +612, -1436, 1152, 108, 1521, 1642, 1630, 2843, +1397, 3465, 870, 3357, 191, 2550, -517, 1230, +-1157, -372, -1615, -1954, -1779, -3170, -1606, -3718, +-1164, -3490, -506, -2557, 307, -1104, 1122, 656, +1746, 2373, 2064, 3605, 1999, 4035, 1520, 3598, +679, 2420, -365, 701, -1333, -1248, -2025, -2999, +-2346, -4078, -2222, -4225, -1602, -3468, -600, -2022, +531, -143, 1512, 1830, 2203, 3460, 2517, 4310, +2329, 4181, 1601, 3185, 497, 1583, -663, -363, +-1637, -2344, -2323, -3877, -2624, -4529, -2378, -4142, +-1597, -2918, -483, -1154, 683, 895, 1686, 2889, +2420, 4292, 2742, 4678, 2470, 4030, 1614, 2625, +439, 744, -739, -1373, -1737, -3294, -2480, -4464, +-2796, -4567, -2491, -3727, -1612, -2228, -451, -304, +718, 1735, 1778, 3406, 2602, 4260, 2914, 4160, +2517, 3254, 1546, 1770, 326, -63, -881, -1872, +-1954, -3207, -2727, -3765, -2923, -3498, -2406, -2519, +-1361, -1040, -112, 626, 1115, 2084, 2170, 2980, +2857, 3161, 2911, 2637, 2256, 1553, 1122, 160, +-173, -1186, -1425, -2174, -2450, -2617, -3009, -2458, +-2893, -1748, -2111, -643, -899, 572, 474, 1584, +1764, 2189, 2740, 2317, 3159, 1936, 2880, 1126, +1962, 80, 660, -913, -748, -1628, -1995, -1957, +-2861, -1884, -3177, -1423, -2825, -672, -1887, 157, +-608, 865, 747, 1312, 1968, 1444, 2863, 1264, +3240, 851, 2940, 319, 2028, -181, 747, -539, +-659, -696, -1976, -650, -2977, -462, -3403, -244, +-3092, -86, -2133, -3, -790, -1, 701, -63, +2104, -166, 3140, -227, 3512, -158, 3099, 57, +2053, 321, 636, 529, -905, 648, -2287, 661, +-3207, 509, -3423, 129, -2877, -390, -1753, -814, +-311, -977, 1179, -928, 2431, -720, 3149, -298, +3142, 329, 2419, 901, 1204, 1125, -206, 989, +-1537, 685, -2527, 272, -2944, -320, -2653, -930, +-1736, -1216, -456, -1056, 874, -652, 1972, -172, +2600, 387, 2624, 970, 2012, 1302, 875, 1159, +-490, 640, -1730, -23, -2540, -694, -2743, -1284, +-2278, -1593, -1192, -1434, 282, -802, 1712, 105, +2704, 1044, 3052, 1789, 2688, 2120, 1644, 1896, +94, 1145, -1563, 24, -2846, -1255, -3430, -2336, +-3217, -2839, -2251, -2583, -707, -1684, 1090, -357, +2650, 1170, 3557, 2573, 3650, 3378, 2950, 3250, +1599, 2285, -139, 830, -1902, -807, -3258, -2354, +-3868, -3391, -3642, -3530, -2651, -2713, -1118, -1284, +646, 326, 2283, 1800, 3440, 2861, 3872, 3203, +3534, 2687, 2553, 1520, 1114, 137, -560, -1044, +-2157, -1816, -3298, -2117, -3770, -1909, -3587, -1234, +-2833, -383, -1549, 282, 101, 601, 1741, 686, +2998, 676, 3737, 582, 3922, 434, 3417, 379, +2157, 513, 380, 655, -1461, 571, -2987, 221, +-4004, -251, -4339, -749, -3786, -1226, -2365, -1530, +-440, -1411, 1526, -799, 3183, 79, 4266, 955, +4509, 1658, 3761, 2027, 2176, 1874, 171, 1180, +-1817, 161, -3407, -869, -4282, -1692, -4230, -2145, +-3267, -2064, -1690, -1435, 137, -479, 1866, 505, +3156, 1342, 3758, 1890, 3598, 1995, 2749, 1597, +1430, 851, -98, 11, -1522, -744, -2551, -1320, +-3055, -1591, -3010, -1476, -2438, -1053, -1431, -477, +-191, 120, 1040, 665, 2051, 1061, 2713, 1219, +2864, 1106, 2395, 787, 1364, 323, 33, -237, +-1249, -790, -2227, -1168, -2732, -1256, -2617, -1046, +-1858, -581, -666, 66, 640, 772, 1737, 1309, +2405, 1478, 2491, 1233, 1933, 671, 878, -97, +-345, -916, -1401, -1544, -2045, -1740, -2146, -1417, +-1692, -709, -815, 172, 236, 1026, 1173, 1651, +1760, 1830, 1877, 1484, 1511, 721, 743, -220, +-252, -1091, -1206, -1698, -1842, -1914, -1993, -1688, +-1619, -1067, -797, -210, 295, 693, 1374, 1453, +2114, 1928, 2308, 2035, 1965, 1751, 1163, 1105, +22, 206, -1211, -790, -2193, -1700, -2613, -2320, +-2393, -2488, -1659, -2152, -551, -1375, 770, -260, +1961, 998, 2617, 2115, 2544, 2770, 1889, 2793, +900, 2223, -270, 1194, -1425, -131, -2246, -1475, +-2442, -2448, -1983, -2763, -1113, -2402, -87, -1556, +946, -430, 1774, 764, 2161, 1734, 1984, 2184, +1331, 2047, 464, 1478, -397, 696, -1158, -133, +-1705, -849, -1890, -1291, -1666, -1398, -1124, -1232, +-419, -895, 335, -452, 1037, -2, 1595, 377, +1900, 692, 1848, 985, 1423, 1192, 724, 1192, +-97, 968, -928, 581, -1692, 40, -2226, -679, +-2288, -1412, -1829, -1843, -1021, -1770, -36, -1266, +1015, -462, 1950, 547, 2521, 1565, 2566, 2213, +2083, 2183, 1203, 1510, 77, 483, -1104, -616, +-2068, -1586, -2605, -2144, -2653, -2040, -2186, -1287, +-1262, -201, -66, 843, 1143, 1593, 2123, 1910, +2690, 1723, 2702, 1073, 2120, 159, 1052, -742, +-275, -1368, -1574, -1621, -2511, -1561, -2849, -1281, +-2499, -767, -1545, -32, -175, 750, 1327, 1384, +2515, 1833, 3009, 2115, 2725, 2044, 1756, 1372, +274, 141, -1374, -1272, -2704, -2516, -3284, -3365, +-3025, -3558, -2047, -2805, -506, -1113, 1263, 1070, +2711, 3080, 3420, 4386, 3325, 4696, 2554, 3880, +1203, 2021, -518, -466, -2129, -2878, -3177, -4543, +-3489, -5097, -3123, -4528, -2173, -2999, -735, -816, +928, 1509, 2377, 3388, 3265, 4437, 3495, 4565, +3087, 3820, 2058, 2366, 516, 495, -1212, -1416, +-2669, -3025, -3501, -4056, -3600, -4301, -2980, -3681, +-1705, -2338, 17, -542, 1774, 1399, 3100, 3098, +3684, 4125, 3436, 4204, 2439, 3343, 879, 1747, +-902, -237, -2473, -2162, -3433, -3568, -3555, -4128, +-2844, -3729, -1476, -2454, 213, -599, 1838, 1359, +3026, 2927, 3493, 3794, 3136, 3803, 2039, 2931, +432, 1341, -1241, -555, -2554, -2254, -3282, -3368, +-3307, -3717, -2573, -3253, -1197, -2047, 433, -381, +1859, 1301, 2837, 2593, 3294, 3280, 3080, 3278, +2094, 2606, 537, 1397, -1075, -61, -2332, -1434, +-3111, -2473, -3288, -3021, -2705, -2961, -1417, -2295, +225, -1178, 1750, 198, 2837, 1623, 3347, 2801, +3124, 3377, 2106, 3179, 507, 2282, -1199, 864, +-2534, -890, -3247, -2594, -3280, -3689, -2606, -3808, +-1280, -2995, 383, -1500, 1902, 401, 2922, 2293, +3313, 3601, 3038, 3902, 2136, 3202, 744, 1819, +-869, 114, -2296, -1556, -3161, -2788, -3325, -3249, +-2851, -2852, -1822, -1795, -350, -467, 1299, 776, +2680, 1724, 3393, 2279, 3328, 2312, 2631, 1761, +1396, 810, -272, -161, -1975, -903, -3159, -1438, +-3496, -1764, -3065, -1686, -2076, -1113, -599, -309, +1175, 400, 2650, 943, 3323, 1376, 3158, 1555, +2392, 1292, 1152, 687, -443, 63, -1961, -430, +-2866, -843, -2963, -1117, -2375, -1100, -1277, -802, +111, -436, 1412, -148, 2209, 81, 2360, 281, +1928, 414, 1034, 455, -57, 454, -1006, 460, +-1582, 477, -1674, 482, -1303, 424, -624, 251, +131, -10, 715, -309, 1017, -624, 1015, -937, +731, -1125, 286, -1040, -135, -675, -394, -166, +-472, 384, -415, 936, -252, 1357, -43, 1453, +97, 1150, 115, 565, 49, -127, -47, -779, +-182, -1285, -320, -1524, -345, -1418, -189, -995, +79, -360, 370, 348, 654, 964, 877, 1356, +912, 1485, 658, 1346, 166, 933, -439, 278, +-1026, -471, -1486, -1108, -1642, -1517, -1313, -1673, +-556, -1517, 354, -985, 1193, -176, 1859, 654, +2185, 1296, 1911, 1672, 1000, 1722, -185, 1373, +-1259, 667, -2020, -163, -2358, -861, -2136, -1287, +-1300, -1399, -104, -1207, 1042, -777, 1874, -233, +2273, 288, 2160, 651, 1515, 798, 422, 780, +-776, 662, -1660, 436, -2024, 120, -1924, -165, +-1477, -318, -685, -386, 370, -442, 1312, -400, +1771, -174, 1729, 108, 1363, 245, 746, 262, +-123, 274, -979, 243, -1462, 64, -1505, -175, +-1235, -287, -733, -243, -61, -152, 645, -44, +1164, 131, 1335, 319, 1175, 410, 774, 356, +231, 197, -361, 3, -877, -166, -1189, -305, +-1182, -435, -853, -514, -366, -430, 130, -165, +601, 137, 985, 367, 1107, 572, 887, 782, +473, 843, 79, 622, -291, 186, -669, -310, +-872, -752, -750, -1038, -454, -1071, -224, -833, +-55, -387, 167, 161, 379, 676, 425, 974, +333, 943, 290, 659, 396, 292, 462, -54, +300, -311, 36, -400, -170, -304, -374, -112, +-653, 37, -889, 56, -855, -67, -533, -263, +-124, -427, 317, -482, 796, -398, 1156, -147, +1196, 258, 921, 678, 471, 889, -120, 790, +-792, 471, -1272, 40, -1347, -436, -1102, -842, +-690, -1017, -130, -879, 560, -477, 1112, 57, +1287, 565, 1163, 896, 865, 965, 374, 791, +-240, 437, -757, -30, -1006, -503, -974, -837, +-778, -969, -494, -910, -141, -675, 230, -303, +486, 92, 559, 409, 534, 645, 518, 837, +501, 940, 375, 849, 110, 563, -181, 190, +-390, -203, -558, -642, -697, -1099, -704, -1405, +-468, -1356, -73, -931, 286, -296, 551, 401, +759, 1106, 827, 1686, 609, 1869, 155, 1480, +-297, 664, -597, -245, -746, -1052, -694, -1714, +-430, -2082, -64, -1881, 270, -1086, 471, -47, +510, 866, 407, 1550, 216, 2001, 39, 2060, +-100, 1566, -257, 666, -357, -288, -292, -1099, +-93, -1731, 55, -2065, 75, -1938, 105, -1372, +185, -561, 183, 341, 74, 1234, -20, 1930, +-33, 2195, -14, 1968, -48, 1344, -90, 446, +-76, -575, -30, -1477, -27, -2032, -109, -2132, +-201, -1770, -190, -1017, -94, -30, 0, 950, +99, 1692, 293, 2049, 566, 1964, 692, 1438, +533, 583, 203, -388, -146, -1245, -503, -1807, +-859, -1959, -1031, -1658, -858, -952, -456, -8, +-22, 898, 437, 1535, 892, 1833, 1119, 1778, +975, 1313, 638, 489, 256, -433, -187, -1135, +-627, -1507, -906, -1600, -954, -1419, -821, -922, +-545, -207, -119, 489, 382, 1000, 750, 1289, +918, 1377, 940, 1251, 790, 904, 385, 384, +-185, -209, -683, -774, -987, -1234, -1093, -1507, +-920, -1509, -425, -1180, 218, -574, 733, 178, +992, 931, 1056, 1535, 854, 1815, 306, 1678, +-337, 1159, -766, 357, -926, -572, -872, -1382, +-609, -1825, -157, -1836, 337, -1480, 652, -818, +772, 95, 766, 1028, 578, 1646, 175, 1783, +-261, 1526, -534, 998, -660, 247, -683, -607, +-534, -1318, -251, -1650, 1, -1569, 188, -1190, +362, -629, 517, 62, 537, 758, 393, 1254, +239, 1409, 165, 1274, 75, 991, -87, 574, +-243, -33, -335, -697, -406, -1142, -535, -1288, +-653, -1282, -611, -1176, -339, -813, 70, -153, +545, 565, 1018, 1079, 1276, 1359, 1169, 1458, +773, 1296, 198, 789, -482, 45, -1118, -678, +-1507, -1185, -1520, -1420, -1188, -1385, -597, -1062, +150, -470, 877, 229, 1376, 791, 1534, 1087, +1391, 1159, 1024, 1065, 446, 751, -253, 197, +-874, -390, -1289, -781, -1453, -962, -1395, -1034, +-1115, -940, -552, -556, 211, 30, 954, 571, +1479, 950, 1674, 1202, 1533, 1252, 1066, 922, +290, 267, -595, -416, -1294, -953, -1615, -1344, +-1590, -1501, -1306, -1228, -741, -524, 71, 322, +909, 1014, 1482, 1456, 1636, 1616, 1443, 1399, +1019, 797, 336, -5, -516, -757, -1237, -1293, +-1581, -1512, -1563, -1380, -1276, -957, -702, -366, +110, 273, 910, 853, 1441, 1237, 1620, 1332, +1476, 1176, 1041, 864, 337, 429, -471, -113, +-1125, -662, -1447, -1064, -1457, -1244, -1257, -1217, +-864, -992, -275, -559, 410, 32, 1015, 639, +1393, 1112, 1505, 1330, 1367, 1241, 947, 886, +273, 381, -510, -166, -1172, -668, -1535, -1007, +-1565, -1067, -1255, -849, -620, -475, 147, -83, +790, 251, 1193, 499, 1298, 625, 1070, 616, +583, 478, 53, 247, -358, 6, -633, -161, +-740, -273, -617, -400, -330, -493, -88, -429, +-30, -221, -29, -32, 80, 94, 184, 269, +191, 484, 211, 534, 320, 342, 404, 87, +299, -82, 44, -234, -142, -439, -206, -558, +-289, -459, -418, -218, -446, 0, -259, 181, +14, 363, 153, 496, 129, 481, 134, 319, +263, 93, 328, -154, 211, -406, 96, -611, +107, -675, 111, -560, -26, -292, -232, 57, +-308, 410, -252, 689, -259, 837, -341, 796, +-261, 550, 37, 164, 295, -252, 346, -614, +306, -864, 323, -931, 359, -803, 253, -552, +-49, -259, -339, 94, -428, 511, -369, 859, +-329, 981, -314, 904, -128, 742, 241, 478, +465, 29, 394, -527, 275, -947, 236, -1091, +119, -1007, -154, -764, -348, -352, -301, 185, +-152, 663, -82, 910, -82, 904, -25, 727, +110, 444, 174, 88, 94, -268, -7, -490, +-2, -524, 121, -445, 191, -367, 76, -279, +-84, -117, -126, 87, -116, 230, -167, 318, +-217, 427, -131, 504, 44, 413, 148, 150, +182, -125, 210, -330, 195, -495, 85, -588, +-44, -462, -80, -81, -30, 347, 18, 587, +11, 598, -64, 457, -177, 175, -270, -231, +-327, -623, -312, -766, -182, -557, 79, -119, +408, 356, 671, 765, 739, 1015, 583, 942, +269, 464, -135, -239, -554, -843, -837, -1168, +-830, -1225, -575, -990, -215, -387, 148, 452, +473, 1145, 650, 1391, 569, 1213, 308, 793, +42, 212, -126, -480, -189, -1061, -169, -1216, +-68, -901, 71, -387, 78, 77, -94, 463, +-286, 738, -350, 724, -302, 344, -228, -157, +-61, -443, 305, -454, 704, -323, 841, -93, +655, 257, 313, 591, -55, 679, -507, 446, +-1001, 25, -1253, -424, -1077, -786, -595, -926, +-38, -736, 543, -297, 1155, 173, 1557, 538, +1481, 762, 1036, 788, 453, 552, -208, 129, +-983, -259, -1691, -438, -1949, -416, -1587, -287, +-862, -102, -76, 92, 721, 196, 1472, 125, +1910, -86, 1783, -318, 1180, -459, 379, -475, +-417, -359, -1133, -97, -1598, 283, -1590, 658, +-1135, 866, -489, 814, 150, 558, 714, 238, +1108, -100, 1202, -489, 961, -855, 534, -1003, +84, -850, -322, -525, -640, -200, -774, 108, +-716, 439, -576, 713, -377, 785, -88, 621, +201, 348, 398, 93, 523, -107, 585, -251, +600, -291, 529, -193, 310, -25, -24, 58, +-393, -21, -701, -202, -860, -387, -853, -538, +-667, -628, -254, -533, 336, -141, 895, 483, +1166, 1089, 1098, 1446, 778, 1451, 254, 1088, +-447, 360, -1133, -624, -1438, -1584, -1197, -2187, +-646, -2216, -41, -1634, 611, -518, 1211, 861, +1466, 2087, 1166, 2777, 490, 2752, -154, 2006, +-591, 670, -922, -943, -1112, -2343, -952, -3085, +-470, -2990, 2, -2100, 227, -620, 312, 1042, +423, 2367, 534, 3001, 509, 2847, 417, 1981, +435, 595, 498, -930, 356, -2124, -39, -2651, +-477, -2441, -808, -1633, -1051, -468, -1187, 742, +-1024, 1701, -489, 2204, 247, 2138, 941, 1502, +1450, 498, 1652, -544, 1445, -1381, 868, -1899, +69, -1980, -770, -1515, -1427, -610, -1724, 413, +-1621, 1264, -1140, 1825, -393, 1971, 432, 1563, +1107, 652, 1452, -435, 1448, -1328, 1167, -1833, +666, -1874, 43, -1421, -525, -532, -869, 515, +-950, 1364, -901, 1776, -788, 1691, -584, 1141, +-308, 264, -27, -674, 234, -1355, 527, -1604, +850, -1438, 1065, -937, 1054, -197, 849, 604, +503, 1211, 7, 1459, -644, 1329, -1255, 908, +-1553, 306, -1468, -356, -1080, -969, -465, -1405, +277, -1509, 961, -1208, 1395, -601, 1517, 93, +1360, 732, 933, 1261, 332, 1543, -261, 1373, +-747, 785, -1126, 59, -1336, -569, -1272, -1046, +-966, -1333, -530, -1269, 0, -796, 613, -120, +1172, 461, 1448, 841, 1332, 1021, 957, 952, +414, 588, -291, 46, -1004, -475, -1431, -844, +-1442, -1001, -1104, -887, -485, -509, 322, -11, +1058, 472, 1409, 896, 1316, 1197, 936, 1200, +386, 839, -318, 276, -981, -306, -1288, -866, +-1195, -1336, -894, -1510, -463, -1273, 114, -761, +703, -174, 1048, 445, 1068, 1046, 942, 1420, +706, 1409, 229, 1133, -368, 777, -752, 344, +-854, -217, -865, -756, -813, -1057, -539, -1133, +-60, -1118, 380, -1004, 641, -676, 774, -160, +807, 370, 623, 789, 222, 1105, -163, 1317, +-372, 1319, -466, 1027, -505, 503, -462, -113, +-316, -715, -125, -1233, 2, -1574, 67, -1618, +116, -1299, 160, -661, 193, 144, 242, 935, +315, 1580, 384, 1969, 423, 1974, 381, 1509, +210, 664, -83, -334, -445, -1259, -796, -1974, +-1000, -2317, -986, -2140, -750, -1460, -298, -475, +307, 584, 911, 1543, 1322, 2217, 1409, 2412, +1177, 2069, 705, 1346, 41, 424, -731, -573, +-1375, -1491, -1601, -2113, -1362, -2296, -834, -2032, +-175, -1423, 525, -582, 1117, 372, 1374, 1283, +1206, 1984, 775, 2295, 258, 2141, -300, 1590, +-776, 773, -1011, -214, -948, -1224, -662, -2023, +-268, -2378, 130, -2222, 435, -1649, 581, -766, +580, 306, 480, 1345, 295, 2065, 75, 2292, +-97, 2001, -155, 1306, -179, 385, -241, -541, +-270, -1298, -208, -1757, -138, -1807, -144, -1432, +-169, -814, -106, -211, 38, 277, 150, 681, +215, 971, 290, 1040, 378, 916, 388, 765, +290, 658, 165, 494, 46, 191, -148, -217, +-428, -649, -637, -1043, -665, -1348, -587, -1458, +-494, -1279, -294, -794, 122, -77, 646, 734, +1020, 1440, 1133, 1866, 1051, 1928, 783, 1622, +265, 980, -425, 81, -1050, -885, -1411, -1674, +-1461, -2106, -1233, -2129, -713, -1758, 22, -1030, +749, -31, 1262, 1007, 1495, 1810, 1447, 2207, +1116, 2158, 542, 1685, -160, 856, -819, -155, +-1269, -1102, -1442, -1772, -1383, -2059, -1106, -1914, +-581, -1393, 137, -646, 871, 151, 1385, 858, +1583, 1367, 1526, 1607, 1203, 1585, 549, 1361, +-307, 986, -1077, 472, -1539, -123, -1669, -728, +-1519, -1305, -1074, -1782, -357, -2018, 426, -1880, +1009, -1348, 1291, -510, 1353, 526, 1247, 1623, +909, 2498, 377, 2875, -142, 2650, -454, 1891, +-640, 725, -856, -650, -996, -1955, -895, -2885, +-672, -3215, -510, -2883, -326, -1980, 44, -721, +514, 634, 833, 1833, 990, 2675, 1120, 3012, +1138, 2778, 828, 2024, 258, 972, -313, -137, +-809, -1171, -1250, -2036, -1511, -2591, -1401, -2667, +-939, -2239, -322, -1474, 328, -542, 986, 517, +1483, 1591, 1611, 2418, 1363, 2756, 868, 2561, +193, 1934, -580, 960, -1226, -274, -1529, -1532, +-1472, -2467, -1175, -2868, -685, -2692, -12, -1999, +724, -888, 1237, 422, 1385, 1625, 1265, 2460, +968, 2782, 500, 2524, -74, 1743, -588, 645, +-882, -495, -954, -1475, -944, -2199, -872, -2528, +-655, -2333, -296, -1672, 67, -782, 340, 171, +604, 1107, 920, 1899, 1149, 2336, 1132, 2300, +884, 1853, 482, 1094, -77, 128, -771, -876, +-1369, -1700, -1624, -2177, -1516, -2215, -1126, -1817, +-456, -1083, 431, -201, 1257, 644, 1719, 1330, +1737, 1704, 1398, 1635, 763, 1204, -68, 660, +-884, 155, -1458, -299, -1671, -674, -1501, -826, +-1003, -694, -294, -444, 464, -276, 1101, -208, +1484, -153, 1520, -101, 1209, -102, 671, -134, +21, -80, -675, 94, -1260, 328, -1540, 530, +-1453, 644, -1052, 634, -436, 478, 253, 191, +864, -163, 1299, -516, 1505, -784, 1396, -827, +893, -619, 151, -301, -531, -4, -976, 291, +-1244, 600, -1350, 770, -1126, 626, -544, 286, +133, 35, 659, -95, 995, -246, 1142, -404, +1031, -395, 612, -211, 49, -56, -406, -47, +-661, -84, -762, -94, -722, -110, -506, -143, +-158, -123, 140, 38, 248, 313, 236, 571, +232, 717, 265, 754, 274, 685, 289, 474, +396, 58, 519, -497, 445, -979, 117, -1257, +-325, -1359, -769, -1295, -1177, -967, -1426, -357, +-1287, 378, -695, 1075, 152, 1680, 1006, 2076, +1738, 2095, 2191, 1689, 2122, 960, 1443, 19, +390, -1053, -757, -2078, -1844, -2761, -2647, -2909, +-2833, -2519, -2254, -1617, -1115, -278, 249, 1239, +1577, 2561, 2656, 3412, 3208, 3653, 2956, 3187, +1927, 1986, 445, 265, -1117, -1535, -2444, -3025, +-3255, -3940, -3323, -4103, -2546, -3426, -1128, -2017, +477, -171, 1880, 1721, 2875, 3279, 3272, 4182, +2887, 4253, 1786, 3493, 341, 2026, -1042, 148, +-2126, -1734, -2773, -3248, -2851, -4146, -2264, -4267, +-1183, -3537, 47, -2033, 1174, -127, 2061, 1684, +2536, 3078, 2432, 3896, 1740, 3966, 690, 3171, +-396, 1686, -1350, -55, -2052, -1617, -2263, -2745, +-1811, -3251, -889, -3040, 108, -2195, 936, -991, +1527, 230, 1749, 1211, 1441, 1813, 693, 1931, +-164, 1577, -852, 979, -1286, 380, -1361, -84, +-970, -375, -246, -466, 467, -369, 962, -208, +1229, -155, 1242, -238, 911, -383, 261, -559, +-487, -744, -1115, -849, -1511, -733, -1626, -375, +-1372, 116, -746, 617, 110, 1071, 984, 1417, +1699, 1581, 2145, 1484, 2191, 1084, 1693, 427, +684, -381, -539, -1174, -1635, -1837, -2415, -2302, +-2796, -2436, -2592, -2076, -1671, -1246, -262, -105, +1171, 1159, 2296, 2336, 2975, 3183, 3054, 3460, +2382, 3034, 1091, 1959, -384, 427, -1674, -1308, +-2595, -2899, -3004, -3982, -2729, -4253, -1777, -3621, +-448, -2235, 854, -375, 1841, 1609, 2363, 3314, +2409, 4357, 2027, 4468, 1247, 3636, 196, 2135, +-813, 272, -1439, -1652, -1658, -3238, -1686, -4075, +-1572, -4025, -1149, -3267, -450, -2038, 214, -461, +681, 1237, 1076, 2619, 1462, 3349, 1611, 3405, +1373, 2973, 921, 2149, 428, 943, -196, -469, +-980, -1710, -1637, -2495, -1857, -2804, -1640, -2745, +-1173, -2324, -540, -1471, 269, -331, 1130, 774, +1737, 1634, 1889, 2251, 1644, 2621, 1142, 2603, +415, 2056, -475, 1124, -1286, 79, -1740, -999, +-1761, -2047, -1471, -2802, -936, -2983, -149, -2536, +723, -1590, 1348, -320, 1592, 1070, 1530, 2286, +1195, 3027, 576, 3109, -192, 2501, -844, 1362, +-1209, -28, -1314, -1362, -1198, -2366, -814, -2832, +-237, -2672, 302, -1932, 648, -854, 854, 285, +967, 1300, 911, 2024, 648, 2282, 288, 2037, +-48, 1430, -337, 631, -590, -250, -778, -1087, +-846, -1663, -797, -1859, -624, -1698, -307, -1219, +105, -476, 486, 365, 780, 1098, 988, 1567, +1063, 1711, 923, 1509, 570, 949, 108, 144, +-395, -688, -874, -1334, -1218, -1688, -1319, -1719, +-1176, -1403, -829, -731, -302, 125, 375, 918, +1054, 1524, 1499, 1865, 1605, 1836, 1415, 1407, +981, 704, 313, -94, -489, -858, -1232, -1531, +-1721, -1981, -1852, -2043, -1623, -1700, -1071, -1111, +-251, -394, 650, 462, 1378, 1379, 1800, 2092, +1920, 2405, 1747, 2303, 1226, 1797, 372, 929, +-626, -208, -1430, -1404, -1846, -2351, -1959, -2802, +-1832, -2696, -1338, -2081, -472, -1053, 484, 223, +1218, 1452, 1650, 2288, 1868, 2600, 1815, 2461, +1345, 1932, 582, 1057, -138, 17, -693, -919, +-1192, -1588, -1578, -2014, -1635, -2200, -1363, -2036, +-978, -1506, -546, -753, 16, 86, 681, 982, +1226, 1833, 1517, 2377, 1631, 2421, 1570, 2035, +1178, 1324, 490, 326, -234, -784, -874, -1712, +-1460, -2239, -1880, -2340, -1927, -2067, -1606, -1465, +-1085, -618, -425, 264, 407, 1013, 1262, 1581, +1858, 1944, 2118, 2028, 2163, 1774, 1936, 1255, +1218, 573, 115, -227, -971, -1039, -1825, -1658, +-2463, -1986, -2767, -1980, -2495, -1596, -1626, -895, +-454, -80, 713, 645, 1750, 1182, 2528, 1514, +2773, 1579, 2382, 1332, 1589, 912, 646, 485, +-319, 95, -1198, -297, -1855, -650, -2193, -892, +-2130, -1027, -1670, -1102, -977, -1050, -262, -800, +408, -434, 1074, -60, 1655, 299, 1929, 677, +1758, 1009, 1301, 1179, 764, 1190, 149, 1107, +-541, 917, -1125, 594, -1451, 127, -1527, -482, +-1432, -1144, -1194, -1716, -783, -2058, -253, -2070, +291, -1695, 805, -919, 1295, 185, 1681, 1356, +1833, 2294, 1682, 2833, 1227, 2889, 463, 2365, +-510, 1256, -1433, -149, -2074, -1429, -2347, -2370, +-2250, -2949, -1725, -3039, -748, -2510, 460, -1458, +1486, -203, 2113, 958, 2371, 1913, 2267, 2584, +1722, 2787, 789, 2449, -256, 1729, -1139, 797, +-1752, -251, -2083, -1310, -2046, -2146, -1586, -2557, +-824, -2514, -4, -2090, 713, -1324, 1300, -284, +1712, 869, 1811, 1894, 1504, 2542, 890, 2688, +176, 2295, -484, 1442, -1052, 297, -1457, -930, +-1583, -1984, -1370, -2572, -886, -2568, -243, -2013, +459, -1040, 1077, 131, 1428, 1223, 1418, 1944, +1101, 2133, 556, 1853, -112, 1248, -722, 413, +-1083, -454, -1125, -1079, -903, -1330, -483, -1278, +57, -1022, 516, -606, 685, -138, 588, 216, +374, 404, 114, 519, -169, 604, -345, 607, +-261, 476, 22, 312, 271, 233, 372, 158, +350, -39, 206, -307, -103, -503, -516, -574, +-815, -589, -834, -614, -578, -532, -162, -222, +319, 212, 779, 555, 1120, 769, 1207, 944, +940, 1020, 382, 790, -259, 260, -810, -291, +-1214, -687, -1385, -964, -1207, -1147, -704, -1086, +-98, -696, 454, -171, 932, 235, 1267, 520, +1292, 751, 965, 865, 482, 797, 38, 619, +-346, 482, -661, 411, -803, 297, -786, 71, +-722, -232, -619, -591, -416, -990, -174, -1377, +-4, -1614, 133, -1533, 372, -1064, 682, -247, +894, 787, 968, 1836, 963, 2649, 818, 2982, +402, 2681, -180, 1766, -692, 361, -1076, -1269, +-1398, -2723, -1556, -3654, -1375, -3870, -861, -3293, +-181, -1995, 498, -245, 1120, 1566, 1618, 3004, +1850, 3812, 1691, 3894, 1173, 3239, 448, 1965, +-309, 387, -967, -1118, -1445, -2299, -1650, -3031, +-1493, -3223, -1041, -2837, -519, -2036, -37, -1062, +426, -56, 790, 931, 881, 1784, 754, 2294, +632, 2357, 606, 2129, 565, 1756, 431, 1180, +283, 367, 168, -497, -22, -1132, -367, -1508, +-724, -1780, -973, -1967, -1135, -1891, -1190, -1531, +-1033, -1040, -640, -495, -96, 198, 500, 1078, +1071, 1933, 1556, 2515, 1849, 2724, 1823, 2542, +1432, 1896, 766, 778, -83, -636, -1011, -1991, +-1829, -2976, -2344, -3414, -2439, -3209, -2052, -2394, +-1261, -1135, -241, 332, 851, 1686, 1797, 2617, +2365, 3010, 2465, 2875, 2153, 2270, 1525, 1314, +694, 243, -230, -702, -1091, -1405, -1714, -1873, +-2043, -2091, -2140, -2013, -1995, -1687, -1519, -1231, +-784, -712, 38, -92, 867, 619, 1683, 1300, +2333, 1849, 2600, 2211, 2373, 2272, 1729, 1948, +812, 1266, -331, 317, -1555, -740, -2495, -1730, +-2876, -2426, -2741, -2649, -2191, -2384, -1233, -1731, +49, -776, 1344, 299, 2260, 1233, 2613, 1828, +2498, 2051, 2046, 1964, 1263, 1608, 229, 1060, +-768, 449, -1424, -111, -1688, -582, -1696, -943, +-1549, -1208, -1194, -1381, -641, -1445, -131, -1323, +144, -957, 338, -423, 660, 146, 993, 724, +1131, 1287, 1103, 1625, 1089, 1567, 1063, 1179, +794, 681, 238, 181, -349, -343, -814, -814, +-1233, -1022, -1598, -928, -1724, -740, -1512, -601, +-1086, -458, -526, -241, 177, -38, 928, 93, +1511, 222, 1824, 402, 1912, 570, 1791, 671, +1338, 693, 560, 655, -269, 521, -947, 248, +-1503, -52, -1944, -288, -2085, -510, -1807, -754, +-1238, -904, -613, -868, 13, -700, 713, -510, +1424, -256, 1911, 155, 2043, 621, 1918, 955, +1629, 1102, 1108, 1132, 281, 1030, -688, 716, +-1525, 194, -2101, -373, -2448, -861, -2515, -1204, +-2106, -1346, -1182, -1257, -21, -947, 1088, -465, +2051, 108, 2773, 651, 3020, 1034, 2596, 1182, +1620, 1130, 414, 883, -799, 449, -1900, -43, +-2649, -429, -2798, -661, -2335, -747, -1494, -665, +-505, -420, 519, -112, 1408, 109, 1917, 196, +1934, 165, 1591, 49, 1115, -104, 619, -230, +65, -249, -514, -105, -951, 130, -1121, 343, +-1087, 493, -1020, 550, -917, 502, -627, 319, +-128, 10, 372, -297, 701, -432, 879, -428, +1001, -418, 1008, -410, 773, -308, 352, -131, +-51, -23, -329, -20, -556, -16, -783, 68, +-890, 206, -758, 351, -504, 479, -305, 592, +-125, 654, 169, 594, 517, 367, 724, -9, +743, -452, 693, -884, 593, -1234, 350, -1367, +27, -1174, -213, -713, -354, -85, -492, 631, +-602, 1305, -575, 1748, -450, 1807, -360, 1483, +-278, 909, -92, 176, 151, -662, 343, -1405, +498, -1817, 671, -1842, 763, -1589, 648, -1106, +391, -386, 121, 444, -173, 1154, -511, 1624, +-795, 1805, -911, 1658, -846, 1222, -652, 574, +-310, -178, 156, -885, 566, -1390, 811, -1598, +968, -1464, 1012, -1019, 796, -387, 325, 254, +-190, 752, -589, 1044, -880, 1092, -1033, 859, +-939, 389, -622, -126, -253, -457, 110, -542, +509, -492, 822, -345, 831, -49, 608, 326, +449, 558, 366, 519, 132, 309, -249, 65, +-516, -209, -566, -525, -548, -760, -576, -796, +-508, -610, -213, -290, 152, 60, 377, 424, +474, 785, 525, 1005, 516, 960, 387, 696, +111, 324, -193, -82, -357, -479, -346, -782, +-288, -923, -234, -868, -126, -620, 32, -266, +118, 54, 84, 276, 28, 413, 52, 467, +121, 443, 90, 333, -2, 193, 7, 119, +98, 125, 134, 129, 81, 112, -7, 90, +-53, 12, -59, -169, -132, -395, -277, -554, +-342, -642, -266, -649, -156, -484, -57, -132, +124, 255, 401, 567, 597, 794, 584, 890, +429, 732, 254, 330, 31, -97, -318, -388, +-639, -568, -717, -663, -590, -584, -421, -301, +-218, 68, 27, 322, 272, 397, 466, 363, +557, 244, 537, 35, 444, -187, 287, -337, +83, -397, -115, -356, -298, -205, -455, 29, +-537, 262, -495, 439, -328, 521, -65, 497, +217, 401, 405, 257, 450, 32, 391, -264, +235, -536, -10, -710, -247, -748, -395, -655, +-408, -446, -288, -125, -97, 281, 115, 667, +322, 921, 453, 981, 471, 854, 395, 574, +229, 181, 20, -232, -161, -576, -314, -798, +-476, -891, -596, -864, -602, -751, -518, -552, +-397, -266, -196, 61, 122, 372, 485, 666, +792, 969, 981, 1219, 1049, 1301, 974, 1155, +700, 800, 250, 267, -276, -382, -829, -1067, +-1335, -1663, -1660, -2021, -1687, -2051, -1371, -1733, +-770, -1062, -15, -116, 787, 885, 1554, 1741, +2113, 2360, 2256, 2673, 1915, 2541, 1229, 1931, +355, 1001, -607, -67, -1501, -1164, -2107, -2165, +-2305, -2882, -2123, -3145, -1613, -2899, -818, -2210, +119, -1143, 949, 209, 1562, 1623, 1999, 2797, +2196, 3507, 1994, 3638, 1406, 3140, 637, 2055, +-152, 594, -935, -943, -1646, -2308, -2075, -3264, +-2100, -3598, -1784, -3266, -1238, -2417, -509, -1244, +319, 69, 1068, 1313, 1589, 2260, 1874, 2758, +1909, 2777, 1620, 2381, 1043, 1680, 327, 769, +-394, -229, -1055, -1121, -1580, -1739, -1826, -2051, +-1688, -2055, -1250, -1744, -638, -1164, 71, -421, +769, 326, 1291, 913, 1488, 1258, 1339, 1372, +913, 1240, 330, 861, -242, 356, -644, -74, +-827, -352, -813, -505, -608, -514, -222, -365, +216, -137, 487, 44, 530, 105, 450, 55, +287, -50, -17, -191, -400, -362, -674, -506, +-720, -522, -621, -373, -478, -122, -227, 157, +197, 441, 649, 703, 939, 871, 1046, 886, +1041, 718, 918, 424, 602, 106, 99, -202, +-482, -533, -1011, -839, -1401, -1022, -1574, -1041, +-1503, -946, -1202, -757, -679, -425, 39, 54, +825, 608, 1463, 1099, 1859, 1414, 2027, 1515, +1905, 1376, 1391, 938, 555, 263, -368, -451, +-1176, -1048, -1823, -1456, -2274, -1594, -2355, -1407, +-1968, -957, -1229, -373, -334, 210, 589, 668, +1447, 917, 2104, 976, 2405, 892, 2285, 694, +1800, 451, 1066, 266, 183, 159, -741, 83, +-1529, 3, -2047, -109, -2268, -276, -2174, -529, +-1720, -828, -976, -1057, -94, -1100, 769, -941, +1495, -608, 1994, -100, 2156, 559, 1933, 1188, +1429, 1577, 789, 1696, 58, 1559, -683, 1126, +-1282, 437, -1626, -318, -1705, -955, -1563, -1403, +-1265, -1637, -861, -1609, -360, -1322, 205, -860, +750, -343, 1187, 135, 1473, 555, 1610, 918, +1599, 1182, 1346, 1324, 777, 1370, 47, 1286, +-618, 1012, -1187, 559, -1664, -4, -1933, -623, +-1852, -1220, -1386, -1673, -690, -1867, 46, -1738, +747, -1313, 1365, -697, 1768, -35, 1856, 599, +1625, 1154, 1133, 1523, 479, 1647, -218, 1584, +-863, 1395, -1364, 1069, -1610, 596, -1597, 14, +-1382, -602, -946, -1187, -295, -1678, 413, -2002, +1013, -2041, 1418, -1718, 1591, -1096, 1526, -314, +1184, 541, 573, 1383, -157, 2018, -844, 2283, +-1393, 2175, -1690, 1754, -1615, 1082, -1182, 237, +-551, -637, 111, -1364, 717, -1836, 1239, -2038, +1562, -1972, 1526, -1619, 1158, -1000, 663, -243, +167, 498, -357, 1134, -856, 1586, -1225, 1756, +-1414, 1631, -1424, 1266, -1228, 719, -793, 90, +-180, -469, 462, -839, 1012, -1017, 1465, -1045, +1757, -938, 1723, -719, 1307, -450, 645, -213, +-95, -59, -811, 58, -1409, 217, -1749, 386, +-1729, 494, -1405, 571, -926, 676, -359, 758, +286, 712, 898, 522, 1283, 262, 1378, -36, +1283, -382, 1066, -756, 744, -1064, 330, -1216, +-123, -1180, -517, -967, -777, -565, -889, -8, +-887, 564, -812, 1059, -717, 1459, -597, 1683, +-417, 1596, -181, 1188, 65, 593, 301, -78, +554, -797, 842, -1467, 1124, -1900, 1269, -1970, +1210, -1697, 983, -1176, 601, -467, 29, 370, +-664, 1176, -1288, 1740, -1708, 1968, -1901, 1899, +-1855, 1578, -1516, 1016, -848, 278, 30, -485, +880, -1139, 1556, -1604, 2041, -1829, 2281, -1786, +2140, -1486, 1607, -959, 843, -283, 29, 425, +-788, 1066, -1558, 1545, -2095, 1756, -2239, 1668, +-2037, 1346, -1648, 864, -1067, 264, -262, -379, +611, -936, 1299, -1309, 1726, -1488, 1951, -1494, +1978, -1325, 1720, -957, 1166, -418, 496, 167, +-118, 702, -659, 1185, -1152, 1561, -1534, 1687, +-1716, 1492, -1693, 1034, -1519, 419, -1230, -277, +-802, -963, -196, -1487, 528, -1709, 1241, -1595, +1851, -1215, 2280, -663, 2407, -13, 2128, 625, +1455, 1097, 497, 1310, -588, 1290, -1649, 1092, +-2491, 742, -2889, 281, -2746, -196, -2166, -596, +-1287, -873, -180, -980, 992, -887, 1978, -644, +2571, -337, 2733, -18, 2495, 257, 1864, 434, +900, 486, -177, 410, -1121, 270, -1856, 164, +-2340, 118, -2438, 94, -2063, 83, -1327, 94, +-452, 79, 394, -15, 1125, -168, 1670, -308, +1910, -373, 1772, -356, 1340, -300, 779, -215, +197, -60, -360, 144, -843, 284, -1181, 305, +-1295, 256, -1203, 206, -995, 171, -666, 133, +-211, 64, 273, -28, 680, -103, 965, -132, +1092, -142, 1046, -172, 833, -181, 457, -129, +-20, -52, -490, 7, -836, 73, -1008, 133, +-1009, 129, -859, 41, -544, -54, -85, -86, +388, -59, 771, -11, 1049, 53, 1157, 162, +1008, 293, 637, 346, 156, 271, -349, 112, +-793, -114, -1123, -387, -1278, -605, -1149, -676, +-740, -593, -236, -365, 197, -6, 569, 397, +918, 727, 1153, 927, 1110, 958, 826, 750, +535, 321, 305, -199, -24, -644, -459, -897, +-757, -953, -844, -864, -909, -615, -1008, -203, +-955, 240, -616, 544, -155, 674, 219, 689, +548, 615, 969, 461, 1322, 275, 1348, 101, +1089, -78, 728, -281, 289, -461, -278, -560, +-866, -564, -1269, -492, -1413, -357, -1353, -147, +-1110, 120, -633, 355, -8, 491, 561, 535, +968, 498, 1222, 366, 1305, 193, 1174, 67, +870, -27, 427, -154, -87, -300, -534, -420, +-849, -491, -1060, -488, -1155, -424, -1051, -328, +-749, -156, -332, 119, 87, 397, 440, 580, +748, 679, 974, 702, 1025, 609, 854, 395, +561, 121, 252, -159, -51, -432, -367, -701, +-654, -919, -791, -961, -746, -776, -610, -475, +-445, -130, -204, 287, 113, 718, 385, 1006, +529, 1070, 529, 932, 436, 627, 312, 213, +146, -189, -73, -467, -251, -607, -282, -661, +-211, -650, -135, -573, -79, -458, 15, -353, +161, -273, 244, -150, 204, 88, 110, 416, +34, 749, -86, 1003, -268, 1104, -380, 965, +-388, 565, -355, 8, -268, -572, -58, -1076, +209, -1376, 424, -1367, 560, -1039, 629, -461, +608, 218, 409, 813, 69, 1201, -230, 1329, +-395, 1152, -526, 696, -671, 103, -678, -479, +-486, -946, -207, -1175, 27, -1081, 232, -716, +427, -214, 563, 288, 586, 665, 485, 851, +296, 835, 23, 613, -259, 260, -420, -65, +-432, -250, -327, -306, -132, -271, 111, -189, +293, -128, 377, -138, 351, -222, 179, -325, +-94, -379, -369, -353, -543, -242, -580, -39, +-475, 234, -277, 485, -55, 623, 151, 653, +319, 624, 484, 551, 628, 413, 658, 214, +551, -7, 422, -250, 317, -541, 141, -843, +-124, -1050, -433, -1105, -718, -989, -900, -691, +-941, -228, -873, 337, -715, 891, -424, 1276, +-32, 1402, 384, 1315, 758, 1094, 1074, 746, +1317, 259, 1357, -276, 1111, -722, 665, -1022, +178, -1228, -350, -1368, -946, -1355, -1472, -1108, +-1726, -678, -1616, -156, -1237, 435, -682, 1022, +14, 1450, 765, 1620, 1350, 1541, 1625, 1249, +1644, 768, 1419, 152, 918, -478, 225, -977, +-457, -1284, -951, -1395, -1203, -1291, -1260, -997, +-1169, -604, -865, -168, -379, 277, 107, 635, +430, 790, 564, 732, 582, 552, 541, 359, +473, 227, 380, 178, 302, 226, 288, 374, +287, 536, 229, 570, 83, 413, -113, 56, +-340, -470, -571, -1039, -766, -1472, -843, -1639, +-744, -1493, -520, -1062, -232, -448, 76, 225, +377, 863, 630, 1381, 790, 1688, 842, 1748, +806, 1587, 704, 1263, 483, 812, 171, 248, +-121, -401, -378, -1038, -664, -1552, -925, -1885, +-995, -1979, -860, -1776, -626, -1279, -356, -600, +-56, 127, 272, 821, 554, 1414, 704, 1791, +728, 1880, 705, 1712, 658, 1347, 560, 826, +413, 221, 229, -374, 34, -907, -194, -1332, +-497, -1577, -853, -1574, -1112, -1327, -1152, -910, +-1009, -418, -727, 92, -276, 568, 318, 894, +881, 990, 1243, 924, 1366, 786, 1267, 568, +966, 315, 525, 136, 69, 61, -343, 47, +-689, 38, -882, -26, -900, -155, -844, -301, +-781, -463, -668, -666, -504, -848, -325, -896, +-100, -763, 229, -484, 639, -115, 1009, 306, +1229, 737, 1285, 1091, 1191, 1239, 861, 1143, +260, 883, -409, 499, -915, -8, -1242, -517, +-1433, -844, -1382, -948, -1049, -905, -564, -747, +-63, -453, 386, -78, 736, 248, 911, 442, +904, 516, 808, 486, 711, 343, 582, 113, +382, -127, 168, -292, -32, -371, -259, -375, +-522, -263, -764, -2, -939, 297, -1008, 490, +-905, 559, -625, 539, -220, 425, 232, 207, +647, -63, 945, -321, 1070, -502, 1022, -584, +853, -606, 588, -569, 237, -426, -106, -215, +-345, -5, -532, 221, -748, 477, -951, 676, +-1048, 713, -990, 569, -772, 295, -452, -8, +-45, -267, 485, -469, 1020, -555, 1347, -431, +1453, -146, 1433, 145, 1179, 361, 572, 464, +-222, 381, -913, 111, -1366, -202, -1617, -418, +-1675, -499, -1442, -476, -876, -366, -144, -164, +559, 81, 1142, 253, 1517, 291, 1600, 251, +1394, 211, 974, 204, 392, 252, -258, 358, +-845, 438, -1241, 403, -1364, 254, -1234, 36, +-911, -246, -458, -581, 32, -855, 479, -956, +862, -877, 1100, -667, 1066, -334, 841, 72, +590, 449, 311, 718, -64, 867, -445, 932, +-695, 923, -821, 786, -909, 497, -964, 144, +-850, -192, -527, -483, -163, -703, 166, -820, +576, -836, 1057, -727, 1377, -484, 1437, -205, +1260, -10, 848, 92, 242, 136, -424, 132, +-1005, 114, -1427, 122, -1609, 183, -1501, 320, +-1118, 534, -584, 760, -49, 935, 430, 999, +832, 882, 1096, 553, 1170, 49, 1103, -562, +971, -1188, 771, -1696, 480, -1968, 92, -1944, +-302, -1599, -621, -944, -859, -84, -1039, 804, +-1134, 1554, -1094, 2049, -895, 2237, -550, 2103, +-171, 1661, 194, 991, 600, 250, 1014, -439, +1306, -1002, 1398, -1388, 1327, -1560, 1071, -1539, +610, -1391, 1, -1169, -650, -884, -1203, -550, +-1565, -207, -1695, 134, -1572, 493, -1132, 869, +-437, 1228, 287, 1507, 871, 1635, 1274, 1570, +1480, 1313, 1412, 888, 1085, 318, 634, -339, +170, -980, -277, -1498, -686, -1810, -903, -1895, +-875, -1767, -727, -1443, -612, -955, -484, -383, +-250, 215, 22, 801, 218, 1305, 319, 1681, +408, 1914, 485, 1964, 500, 1776, 453, 1350, +349, 712, 193, -84, -19, -925, -207, -1661, +-307, -2174, -307, -2360, -237, -2161, -165, -1615, +-106, -830, -57, 52, -13, 873, -24, 1501, +-92, 1843, -162, 1824, -180, 1489, -87, 1005, +89, 490, 262, -42, 344, -519, 336, -820, +274, -899, 177, -822, 84, -683, -46, -511, +-192, -301, -265, -71, -207, 115, -112, 225, +-72, 275, -62, 266, -72, 186, -88, 65, +-85, -36, -40, -98, 15, -120, 38, -88, +90, 16, 177, 174, 240, 336, 211, 415, +145, 361, 61, 203, -83, 16, -221, -162, +-269, -323, -211, -411, -125, -372, -37, -222, +66, -48, 181, 94, 296, 170, 308, 171, +180, 86, -21, -75, -184, -241, -269, -314, +-315, -277, -335, -197, -287, -75, -80, 135, +186, 388, 351, 570, 391, 649, 364, 616, +283, 466, 105, 234, -117, -35, -288, -326, +-337, -588, -312, -755, -286, -799, -195, -698, +3, -472, 240, -198, 367, 62, 370, 311, +292, 527, 180, 651, 49, 665, -141, 580, +-329, 398, -422, 172, -390, -26, -285, -203, +-135, -369, 59, -466, 257, -450, 404, -343, +412, -170, 329, 33, 236, 208, 114, 296, +-67, 274, -228, 171, -294, 34, -336, -126, +-357, -306, -330, -425, -273, -373, -157, -175, +51, 36, 300, 216, 469, 389, 554, 511, +590, 494, 582, 363, 462, 226, 152, 94, +-241, -87, -563, -280, -774, -383, -935, -386, +-991, -365, -832, -380, -460, -378, 4, -265, +406, -65, 750, 104, 1066, 222, 1243, 347, +1167, 446, 895, 453, 552, 376, 123, 254, +-379, 101, -857, -69, -1176, -238, -1273, -357, +-1200, -351, -1001, -233, -670, -115, -213, -24, +238, 104, 604, 241, 907, 287, 1090, 195, +1081, 3, 910, -207, 689, -364, 455, -454, +177, -467, -155, -364, -475, -143, -674, 138, +-757, 419, -771, 654, -728, 782, -637, 770, +-520, 621, -353, 365, -109, 42, 131, -293, +314, -599, 468, -845, 629, -986, 786, -983, +887, -824, 869, -524, 694, -122, 422, 313, +95, 713, -263, 1017, -622, 1177, -920, 1155, +-1087, 914, -1111, 483, -990, -22, -703, -481, +-269, -828, 180, -1014, 509, -1010, 752, -811, +962, -471, 1072, -110, 970, 160, 688, 314, +345, 368, 28, 326, -259, 218, -533, 129, +-711, 127, -732, 209, -652, 335, -528, 445, +-332, 498, -87, 462, 75, 298, 134, 5, +178, -332, 251, -637, 321, -863, 360, -952, +366, -869, 314, -642, 207, -319, 73, 39, +-35, 369, -116, 626, -214, 783, -303, 831, +-309, 776, -209, 642, -74, 441, 21, 198, +65, -44, 90, -267, 127, -449, 147, -550, +138, -561, 125, -508, 90, -381, -6, -199, +-116, -45, -190, 27, -263, 28, -348, -24, +-376, -105, -287, -178, -108, -205, 100, -139, +312, 51, 510, 330, 631, 633, 627, 899, +538, 1044, 407, 1000, 177, 765, -152, 378, +-454, -114, -640, -632, -721, -1063, -714, -1344, +-608, -1431, -412, -1308, -160, -1005, 83, -600, +263, -167, 390, 249, 447, 631, 382, 956, +256, 1192, 223, 1320, 300, 1324, 350, 1187, +313, 899, 269, 478, 253, -26, 150, -541, +-105, -1001, -389, -1319, -574, -1402, -678, -1231, +-746, -902, -726, -530, -576, -161, -337, 148, +-92, 328, 121, 382, 349, 379, 617, 366, +867, 399, 1006, 509, 1000, 661, 829, 801, +507, 868, 105, 769, -358, 495, -852, 127, +-1227, -288, -1302, -706, -1064, -1033, -648, -1181, +-150, -1141, 365, -937, 810, -621, 1033, -287, +958, 7, 656, 248, 244, 397, -173, 458, +-500, 513, -638, 591, -570, 657, -337, 705, +-36, 749, 212, 761, 351, 678, 377, 435, +308, 44, 149, -410, -51, -840, -195, -1204, +-205, -1444, -94, -1452, 24, -1186, 107, -730, +147, -194, 103, 375, -49, 902, -241, 1249, +-385, 1333, -455, 1195, -427, 922, -287, 568, +-52, 172, 211, -200, 425, -473, 573, -591, +665, -566, 680, -472, 558, -344, 343, -205, +119, -129, -106, -153, -366, -235, -643, -348, +-847, -462, -930, -482, -882, -344, -716, -42, +-423, 379, 9, 822, 470, 1151, 834, 1282, +1034, 1171, 1099, 798, 1022, 243, 747, -335, +326, -837, -87, -1205, -395, -1324, -669, -1152, +-892, -792, -929, -384, -762, -2, -524, 331, +-309, 601, -68, 753, 194, 755, 399, 670, +477, 550, 460, 370, 435, 116, 388, -131, +262, -309, 73, -431, -43, -511, -57, -485, +-49, -312, -57, -63, -44, 141, 23, 240, +66, 251, 21, 192, -101, 69, -225, -95, +-327, -251, -462, -335, -578, -297, -558, -152, +-341, 44, -30, 240, 270, 388, 554, 462, +824, 464, 1001, 388, 940, 249, 660, 88, +300, -95, -54, -310, -410, -499, -759, -591, +-976, -607, -986, -596, -814, -530, -568, -340, +-283, -23, 69, 351, 427, 684, 684, 922, +766, 1055, 746, 1025, 649, 763, 424, 308, +85, -227, -229, -754, -380, -1168, -423, -1355, +-433, -1251, -344, -865, -97, -298, 150, 294, +219, 776, 177, 1065, 92, 1115, -51, 922, +-261, 549, -428, 97, -453, -306, -335, -540, +-117, -583, 128, -516, 389, -404, 632, -255, +768, -83, 715, 73, 490, 181, 197, 223, +-114, 233, -407, 243, -641, 222, -722, 135, +-621, -8, -445, -169, -271, -292, -89, -339, +114, -312, 241, -200, 236, 4, 156, 260, +112, 458, 153, 526, 201, 470, 245, 321, +332, 94, 444, -186, 477, -450, 364, -610, +152, -636, -115, -566, -371, -417, -600, -188, +-782, 92, -856, 371, -764, 606, -549, 767, +-307, 841, -29, 793, 290, 579, 604, 221, +827, -214, 887, -647, 847, -991, 762, -1168, +599, -1133, 312, -868, -13, -402, -310, 162, +-586, 691, -810, 1087, -928, 1263, -914, 1151, +-809, 794, -644, 309, -443, -212, -187, -683, +171, -994, 566, -1077, 886, -905, 1073, -520, +1177, -40, 1191, 412, 992, 765, 539, 948, +-30, 905, -545, 669, -1007, 313, -1375, -116, +-1502, -561, -1315, -896, -890, -1021, -360, -939, +207, -716, 730, -402, 1101, 1, 1219, 460, +1083, 852, 782, 1061, 373, 1083, -53, 947, +-413, 649, -655, 221, -772, -240, -711, -624, +-458, -888, -147, -1011, 115, -934, 323, -638, +494, -221, 571, 180, 505, 483, 335, 663, +100, 704, -170, 579, -444, 291, -627, -74, +-690, -398, -657, -603, -523, -659, -292, -542, +10, -265, 321, 77, 599, 388, 800, 621, +864, 721, 778, 655, 584, 453, 341, 167, +59, -121, -218, -302, -439, -328, -585, -239, +-658, -105, -660, 2, -575, 20, -466, -63, +-367, -245, -233, -530, -46, -833, 128, -981, +259, -876, 410, -540, 582, -30, 679, 580, +652, 1161, 561, 1569, 458, 1723, 289, 1590, +28, 1187, -247, 576, -435, -134, -551, -789, +-645, -1261, -692, -1516, -621, -1556, -428, -1388, +-195, -1034, 44, -564, 278, -85, 467, 325, +561, 604, 541, 729, 444, 729, 292, 659, +106, 549, -97, 436, -276, 370, -358, 363, +-336, 366, -273, 323, -198, 219, -76, 42, +68, -206, 171, -476, 232, -689, 280, -768, +303, -675, 260, -461, 153, -213, 15, 34, +-134, 243, -272, 338, -378, 277, -444, 103, +-457, -88, -385, -216, -223, -248, -23, -181, +151, -22, 286, 209, 403, 440, 472, 594, +462, 648, 397, 604, 306, 453, 192, 218, +51, -39, -76, -275, -168, -454, -254, -547, +-342, -551, -393, -484, -401, -373, -388, -252, +-330, -145, -204, -71, -50, -46, 73, -61, +179, -84, 314, -72, 426, 1, 423, 138, +316, 315, 199, 489, 105, 615, -4, 660, +-121, 616, -181, 491, -161, 292, -126, 43, +-111, -195, -82, -367, -37, -473, -17, -531, +-36, -541, -45, -512, -17, -476, 39, -447, +94, -403, 99, -315, 52, -194, 6, -64, +-29, 102, -94, 336, -161, 592, -165, 782, +-126, 861, -81, 851, -4, 741, 126, 508, +235, 183, 249, -158, 204, -457, 163, -678, +126, -786, 68, -754, 14, -598, -39, -396, +-112, -210, -172, -49, -181, 76, -177, 151, +-222, 189, -253, 197, -194, 181, -95, 154, +-22, 134, 56, 139, 198, 158, 343, 165, +401, 156, 382, 183, 334, 246, 224, 277, +10, 224, -226, 102, -390, -59, -473, -239, +-490, -407, -416, -531, -244, -568, -21, -494, +199, -348, 370, -187, 452, -20, 415, 139, +290, 254, 156, 304, 52, 322, -32, 365, +-93, 448, -96, 519, -78, 501, -119, 377, +-187, 185, -237, -59, -283, -362, -348, -665, +-366, -863, -274, -890, -83, -753, 146, -493, +371, -144, 567, 238, 675, 564, 665, 758, +540, 815, 320, 764, 33, 621, -274, 385, +-531, 86, -695, -218, -742, -458, -676, -607, +-520, -657, -285, -595, 4, -428, 296, -179, +516, 103, 636, 347, 662, 479, 596, 472, +438, 335, 206, 106, -52, -149, -288, -349, +-485, -448, -621, -439, -642, -306, -524, -64, +-324, 222, -88, 475, 158, 636, 402, 668, +595, 561, 688, 329, 655, 17, 500, -297, +270, -547, -3, -710, -305, -764, -581, -667, +-746, -426, -767, -121, -687, 160, -523, 381, +-244, 537, 131, 623, 476, 624, 702, 534, +811, 365, 797, 144, 625, -118, 302, -389, +-56, -620, -354, -779, -576, -822, -694, -706, +-651, -403, -432, 53, -141, 548, 132, 946, +347, 1153, 461, 1117, 439, 831, 295, 357, +101, -197, -107, -704, -285, -1051, -373, -1164, +-319, -1022, -148, -679, 70, -238, 280, 186, +427, 505, 469, 686, 371, 739, 133, 676, +-188, 502, -495, 240, -699, -46, -769, -274, +-670, -396, -383, -428, 28, -387, 445, -261, +779, -61, 987, 150, 1012, 295, 811, 327, +409, 240, -52, 54, -429, -170, -708, -326, +-882, -339, -890, -217, -686, -24, -368, 190, +-70, 393, 178, 508, 392, 449, 521, 215, +492, -106, 345, -414, 176, -636, 48, -724, +-45, -637, -123, -398, -159, -97, -129, 202, +-37, 496, 72, 750, 152, 874, 188, 826, +167, 645, 75, 390, -59, 79, -182, -273, +-291, -618, -384, -889, -410, -1040, -324, -1038, +-149, -845, 31, -471, 196, -14, 368, 413, +493, 778, 486, 1060, 362, 1189, 233, 1098, +129, 795, -6, 364, -170, -98, -258, -521, +-257, -855, -270, -1060, -332, -1109, -367, -995, +-324, -744, -260, -399, -209, -21, -111, 339, +85, 653, 327, 901, 509, 1056, 598, 1099, +607, 1023, 533, 810, 346, 432, 79, -73, +-172, -590, -350, -1015, -433, -1294, -445, -1392, +-411, -1254, -323, -865, -181, -305, -56, 287, +-42, 768, -103, 1056, -129, 1131, -90, 1009, +-55, 732, -15, 375, 124, 9, 340, -305, +508, -515, 561, -596, 564, -584, 542, -518, +421, -388, 165, -192, -138, 17, -379, 192, +-549, 327, -683, 425, -772, 468, -747, 419, +-586, 287, -358, 139, -109, 31, 153, -71, +397, -213, 576, -368, 668, -485, 671, -569, +588, -645, 429, -670, 224, -560, 28, -276, +-119, 136, -217, 592, -270, 1005, -295, 1307, +-305, 1416, -317, 1253, -309, 820, -266, 210, +-227, -442, -192, -1016, -119, -1416, 2, -1581, +129, -1500, 247, -1194, 343, -704, 379, -131, +327, 398, 223, 806, 121, 1066, 32, 1169, +-45, 1127, -86, 960, -68, 701, -25, 406, +7, 122, 27, -139, 14, -374, -76, -570, +-224, -729, -351, -859, -414, -933, -417, -891, +-352, -711, -202, -421, 39, -67, 311, 291, +527, 610, 662, 846, 703, 957, 625, 914, +426, 729, 158, 444, -130, 126, -392, -146, +-593, -336, -714, -466, -721, -551, -588, -552, +-346, -437, -78, -243, 170, -39, 395, 125, +560, 212, 604, 207, 513, 114, 323, -48, +85, -246, -138, -436, -292, -528, -345, -426, +-299, -115, -178, 317, -12, 729, 142, 1016, +230, 1137, 240, 1047, 167, 726, 10, 228, +-192, -330, -352, -840, -408, -1217, -368, -1371, +-274, -1263, -137, -949, 64, -542, 291, -114, +462, 310, 533, 710, 536, 1008, 464, 1105, +290, 993, 55, 755, -161, 456, -336, 128, +-493, -182, -591, -430, -565, -588, -414, -621, +-197, -510, 32, -293, 247, -48, 404, 136, +455, 221, 414, 210, 313, 128, 153, -13, +-59, -216, -251, -447, -347, -613, -345, -610, +-286, -407, -192, -65, -70, 316, 63, 655, +212, 903, 356, 1020, 438, 956, 424, 686, +339, 280, 219, -142, 54, -480, -152, -662, +-359, -675, -523, -576, -627, -441, -615, -320, +-444, -235, -158, -183, 149, -155, 399, -152, +558, -164, 597, -140, 501, -38, 279, 127, +-20, 308, -312, 463, -504, 565, -524, 630, +-365, 701, -95, 756, 191, 694, 424, 461, +558, 108, 552, -294, 390, -703, 115, -1084, +-197, -1351, -458, -1394, -606, -1169, -606, -735, +-481, -187, -285, 400, -75, 924, 126, 1247, +312, 1308, 453, 1173, 504, 931, 454, 606, +365, 201, 275, -221, 145, -568, -54, -796, +-262, -922, -428, -966, -563, -907, -643, -696, +-562, -346, -294, 78, 26, 506, 285, 864, +489, 1060, 642, 1035, 660, 804, 491, 411, +186, -83, -150, -581, -430, -964, -579, -1139, +-548, -1062, -359, -745, -96, -262, 173, 281, +397, 771, 504, 1097, 465, 1181, 322, 1030, +125, 695, -115, 231, -341, -272, -464, -693, +-459, -945, -379, -1001, -270, -875, -127, -629, +27, -325, 143, -3, 219, 289, 293, 488, +344, 578, 324, 579, 245, 505, 158, 355, +66, 163, -56, -12, -188, -143, -266, -232, +-241, -276, -153, -256, -63, -165, 22, -36, +120, 63, 204, 104, 225, 109, 142, 102, +-22, 73, -185, 29, -296, 6, -370, 3, +-414, -26, -357, -91, -183, -165, 18, -218, +184, -243, 360, -252, 570, -236, 715, -156, +693, 15, 532, 211, 324, 336, 77, 367, +-244, 338, -582, 279, -833, 199, -949, 116, +-932, 42, -775, -6, -461, -19, -29, -20, +406, -35, 732, -72, 912, -130, 970, -215, +903, -297, 673, -339, 299, -335, -105, -308, +-421, -285, -618, -258, -725, -196, -709, -67, +-532, 134, -284, 373, -72, 612, 123, 814, +324, 937, 442, 945, 404, 790, 280, 440, +167, -66, 63, -609, -62, -1061, -177, -1356, +-236, -1465, -243, -1345, -220, -996, -158, -478, +-58, 136, 33, 762, 106, 1279, 179, 1566, +238, 1571, 259, 1314, 242, 866, 186, 299, +60, -314, -107, -861, -236, -1204, -296, -1271, +-314, -1103, -298, -777, -202, -370, -10, 23, +209, 322, 365, 514, 435, 608, 417, 606, +294, 524, 90, 375, -136, 184, -332, -3, +-467, -162, -512, -308, -464, -438, -338, -500, +-152, -434, 55, -229, 228, 64, 342, 346, +387, 536, 376, 611, 352, 575, 332, 417, +269, 152, 142, -149, -3, -410, -108, -583, +-178, -634, -266, -554, -356, -386, -380, -190, +-310, 4, -200, 178, -98, 300, -3, 353, +81, 341, 131, 266, 124, 141, 84, 11, +58, -66, 69, -50, 76, 45, 68, 147, +88, 204, 146, 225, 186, 209, 156, 100, +78, -109, 9, -333, -27, -485, -64, -530, +-123, -462, -174, -304, -204, -111, -240, 57, +-269, 161, -242, 207, -159, 235, -66, 275, +34, 316, 183, 342, 369, 363, 500, 362, +493, 296, 371, 137, 194, -113, -24, -401, +-274, -619, -470, -677, -519, -574, -444, -370, +-312, -106, -134, 172, 93, 386, 303, 478, +401, 457, 360, 354, 227, 180, 67, -36, +-62, -223, -137, -317, -178, -310, -191, -248, +-142, -168, -20, -49, 93, 136, 120, 345, +96, 484, 74, 497, 45, 382, -4, 160, +-38, -110, -30, -358, -27, -550, -60, -661, +-92, -638, -77, -450, -43, -142, -35, 194, +-31, 468, 2, 629, 66, 657, 138, 558, +188, 359, 176, 109, 102, -149, 2, -411, +-92, -646, -168, -747, -208, -650, -199, -416, +-154, -141, -89, 146, 6, 440, 142, 692, +266, 823, 304, 774, 257, 561, 186, 251, +114, -71, 14, -335, -125, -507, -260, -591, +-339, -607, -346, -553, -302, -421, -213, -237, +-65, -52, 102, 106, 217, 236, 257, 329, +262, 382, 250, 402, 185, 371, 51, 255, +-80, 78, -109, -84, -45, -178, 18, -198, +31, -174, 40, -141, 62, -103, 56, -49, +-4, 22, -91, 82, -164, 108, -211, 94, +-225, 59, -181, 47, -71, 71, 56, 76, +131, 18, 142, -69, 140, -133, 151, -167, +139, -182, 61, -180, -58, -162, -149, -130, +-163, -79, -113, 2, -38, 107, 37, 205, +91, 259, 124, 258, 125, 220, 102, 160, +70, 62, 21, -74, -57, -200, -112, -253, +-78, -204, 12, -73, 79, 92, 85, 230, +52, 295, -23, 267, -129, 153, -223, -11, +-258, -167, -238, -276, -192, -331, -95, -308, +87, -192, 287, -43, 383, 44, 352, 26, +252, -51, 119, -123, -39, -153, -192, -132, +-290, -45, -298, 124, -219, 340, -77, 528, +91, 630, 228, 627, 291, 502, 276, 260, +193, -36, 54, -323, -91, -561, -217, -716, +-310, -761, -343, -708, -274, -572, -118, -353, +41, -72, 151, 222, 214, 470, 249, 639, +248, 718, 189, 698, 85, 571, -10, 347, +-85, 77, -167, -183, -212, -401, -178, -551, +-113, -592, -86, -511, -79, -358, -15, -180, +100, 17, 189, 224, 205, 385, 180, 443, +153, 389, 107, 250, 20, 58, -88, -147, +-178, -321, -227, -416, -221, -394, -166, -260, +-79, -42, 54, 223, 198, 477, 288, 624, +282, 606, 216, 436, 130, 151, 15, -189, +-158, -496, -350, -697, -443, -760, -411, -668, +-313, -420, -176, -71, 19, 292, 235, 559, +397, 658, 476, 604, 473, 457, 389, 243, +233, -23, 26, -272, -174, -412, -309, -423, +-368, -351, -385, -242, -359, -116, -263, 8, +-120, 103, 29, 160, 159, 211, 277, 290, +370, 377, 396, 412, 335, 370, 209, 265, +52, 105, -141, -131, -349, -435, -504, -723, +-540, -886, -443, -859, -237, -648, 27, -310, +289, 85, 505, 472, 618, 780, 592, 937, +430, 907, 172, 713, -125, 408, -388, 68, +-552, -226, -593, -420, -511, -501, -348, -493, +-153, -424, 69, -309, 270, -165, 391, -26, +435, 62, 426, 84, 359, 63, 232, 24, +83, -9, -58, -16, -177, 10, -285, 60, +-358, 128, -350, 216, -241, 303, -75, 337, +65, 268, 165, 97, 243, -121, 281, -318, +232, -450, 94, -492, -85, -431, -237, -263, +-328, -25, -348, 218, -280, 404, -144, 476, +12, 403, 163, 214, 282, 0, 353, -161, +370, -245, 324, -251, 217, -161, 81, 6, +-26, 184, -81, 291, -118, 281, -173, 161, +-229, -43, -235, -291, -184, -510, -129, -597, +-102, -513, -50, -302, 33, -23, 87, 289, +90, 578, 70, 760, 34, 757, -39, 559, +-141, 247, -203, -82, -153, -364, -23, -564, +103, -642, 211, -578, 345, -403, 480, -181, +508, 37, 391, 207, 192, 300, -34, 318, +-269, 284, -480, 237, -604, 210, -615, 197, +-548, 170, -414, 119, -198, 54, 75, -28, +322, -153, 491, -316, 553, -458, 517, -530, +414, -525, 255, -440, 51, -265, -174, -14, +-354, 260, -441, 499, -413, 677, -308, 777, +-153, 774, 30, 635, 194, 375, 304, 63, +365, -247, 389, -523, 323, -724, 141, -811, +-69, -779, -227, -632, -334, -383, -415, -84, +-456, 190, -427, 389, -312, 499, -117, 526, +120, 478, 327, 367, 439, 226, 463, 94, +443, -12, 374, -93, 243, -134, 61, -133, +-112, -118, -232, -116, -279, -108, -250, -72, +-170, -23, -94, 11, -76, 18, -92, -5, +-96, -55, -88, -116, -112, -170, -153, -208, +-144, -212, -65, -154, 67, -28, 225, 139, +368, 292, 438, 379, 414, 378, 329, 295, +213, 149, 63, -18, -150, -144, -398, -207, +-575, -216, -624, -174, -564, -67, -420, 71, +-184, 151, 117, 134, 422, 66, 674, 0, +824, -64, 828, -132, 649, -191, 314, -214, +-112, -202, -507, -177, -804, -140, -977, -60, +-981, 43, -789, 124, -412, 190, 54, 269, +482, 347, 790, 370, 941, 315, 910, 197, +710, 69, 399, -45, 29, -155, -344, -268, +-644, -357, -795, -400, -752, -397, -549, -345, +-259, -238, 43, -78, 329, 104, 579, 284, +714, 439, 673, 553, 469, 571, 163, 449, +-174, 206, -459, -72, -650, -314, -714, -493, +-632, -595, -456, -595, -216, -481, 80, -293, +373, -80, 561, 124, 604, 301, 549, 426, +456, 492, 332, 515, 169, 511, 4, 462, +-133, 331, -238, 118, -319, -129, -371, -351, +-380, -532, -373, -655, -356, -685, -288, -594, +-156, -402, 23, -158, 207, 98, 339, 316, +404, 452, 420, 492, 366, 463, 226, 406, +36, 335, -163, 240, -305, 131, -353, 30, +-313, -53, -210, -135, -62, -236, 123, -356, +282, -468, 363, -532, 360, -527, 286, -444, +160, -278, 0, -35, -180, 256, -325, 544, +-380, 778, -380, 917, -356, 912, -280, 727, +-150, 381, -9, -44, 105, -454, 181, -799, +236, -1033, 280, -1096, 311, -947, 315, -631, +295, -226, 242, 190, 159, 550, 49, 785, +-82, 845, -235, 739, -384, 524, -469, 258, +-483, -20, -405, -256, -232, -388, -7, -371, +225, -235, 427, -46, 550, 138, 567, 269, +477, 307, 268, 228, -15, 47, -276, -197, +-475, -439, -609, -618, -645, -677, -546, -582, +-333, -333, -64, 0, 208, 324, 442, 570, +610, 704, 675, 717, 617, 601, 460, 373, +237, 85, -34, -179, -313, -352, -514, -415, +-611, -392, -605, -300, -511, -160, -345, -14, +-123, 98, 125, 164, 347, 176, 482, 111, +526, -20, 480, -166, 360, -255, 193, -263, +4, -204, -166, -100, -292, 50, -375, 224, +-404, 371, -350, 440, -234, 399, -123, 247, +-35, 16, 60, -221, 167, -397, 252, -472, +304, -445, 330, -330, 315, -136, 256, 119, +147, 378, 17, 556, -113, 590, -268, 477, +-416, 265, -471, 4, -400, -263, -277, -492, +-127, -639, 45, -668, 234, -549, 391, -293, +461, 35, 448, 339, 362, 548, 222, 636, +45, 602, -135, 466, -270, 237, -359, -48, +-415, -313, -423, -479, -361, -523, -229, -459, +-42, -310, 144, -112, 292, 90, 411, 256, +480, 363, 482, 400, 395, 360, 200, 223, +-50, 15, -286, -187, -463, -308, -559, -339, +-547, -308, -434, -226, -244, -83, 3, 103, +269, 263, 490, 331, 585, 294, 552, 195, +412, 67, 219, -54, 18, -137, -195, -162, +-374, -161, -466, -162, -468, -166, -392, -155, +-244, -128, -54, -100, 136, -55, 287, 36, +368, 185, 391, 344, 357, 457, 230, 472, +14, 371, -233, 165, -413, -95, -479, -328, +-442, -473, -316, -505, -119, -433, 140, -276, +403, -74, 582, 114, 612, 218, 502, 214, +267, 124, -29, 11, -295, -65, -469, -73, +-494, -9, -398, 112, -244, 262, -56, 386, +147, 432, 284, 369, 273, 198, 128, -66, +-66, -378, -231, -654, -315, -809, -284, -789, +-139, -599, 69, -276, 278, 135, 431, 567, +512, 911, 490, 1082, 318, 1027, 57, 759, +-197, 323, -380, -190, -480, -657, -489, -983, +-419, -1130, -299, -1088, -158, -854, -23, -459, +122, 23, 252, 480, 343, 835, 397, 1048, +432, 1101, 424, 976, 340, 684, 189, 278, +-32, -172, -288, -597, -510, -920, -648, -1059, +-665, -980, -556, -717, -347, -350, -83, 42, +210, 389, 482, 639, 657, 741, 710, 675, +649, 475, 495, 228, 282, 10, 55, -147, +-173, -233, -398, -260, -585, -244, -719, -212, +-753, -173, -675, -134, -501, -95, -241, -64, +94, -42, 456, -16, 775, 36, 990, 115, +1028, 190, 868, 237, 533, 243, 97, 212, +-349, 148, -720, 59, -947, -63, -1014, -211, +-908, -349, -626, -426, -242, -398, 160, -272, +496, -84, 702, 117, 785, 305, 761, 458, +620, 543, 388, 521, 116, 391, -179, 189, +-451, -39, -654, -254, -749, -419, -720, -520, +-589, -567, -374, -558, -93, -483, 247, -319, +579, -82, 798, 179, 862, 404, 797, 571, +610, 672, 323, 687, -3, 594, -341, 406, +-622, 170, -788, -72, -838, -276, -750, -420, +-548, -494, -290, -520, -15, -523, 242, -517, +451, -468, 606, -336, 682, -129, 636, 107, +482, 325, 284, 515, 95, 669, -89, 746, +-266, 681, -390, 464, -459, 162, -444, -126, +-355, -342, -236, -474, -102, -525, 10, -499, +71, -411, 109, -292, 146, -159, 151, -31, +141, 78, 129, 154, 129, 213, 163, 281, +209, 361, 231, 414, 193, 401, 106, 317, +-1, 176, -126, -4, -252, -200, -363, -390, +-440, -566, -441, -694, -364, -724, -234, -596, +-45, -324, 167, 23, 324, 382, 419, 707, +459, 946, 445, 1035, 378, 940, 223, 668, +20, 269, -157, -186, -265, -592, -325, -871, +-335, -988, -285, -968, -200, -844, -103, -625, +-8, -323, 79, 21, 130, 347, 141, 620, +108, 817, 52, 921, 29, 909, 29, 767, +23, 496, 21, 130, 26, -264, 31, -594, +36, -783, 44, -810, 32, -692, 5, -480, +-23, -225, -56, 17, -79, 209, -87, 322, +-84, 352, -85, 313, -76, 242, -57, 183, +-34, 148, 5, 119, 44, 68, 89, 3, +130, -60, 162, -101, 180, -118, 184, -108, +154, -92, 73, -86, -36, -100, -158, -127, +-273, -150, -349, -162, -354, -147, -287, -85, +-153, 40, 35, 210, 228, 383, 400, 497, +517, 512, 504, 400, 364, 190, 138, -66, +-131, -319, -392, -529, -586, -663, -670, -678, +-606, -565, -380, -347, -57, -72, 286, 228, +572, 496, 766, 677, 795, 738, 627, 681, +318, 514, -58, 244, -400, -97, -659, -436, +-807, -663, -766, -732, -513, -641, -159, -430, +180, -142, 443, 162, 588, 421, 599, 572, +456, 581, 197, 446, -65, 207, -260, -65, +-350, -306, -322, -456, -185, -498, 11, -432, +174, -290, 252, -91, 226, 137, 106, 356, +-63, 510, -235, 551, -382, 476, -427, 314, +-330, 111, -147, -106, 94, -308, 318, -463, +473, -538, 548, -516, 512, -387, 367, -181, +157, 34, -82, 198, -327, 286, -520, 315, +-605, 296, -570, 231, -450, 121, -269, 7, +-21, -61, 249, -51, 493, 18, 653, 107, +676, 165, 576, 162, 351, 101, 38, -7, +-269, -139, -516, -285, -668, -414, -681, -483, +-545, -449, -291, -311, 41, -95, 335, 126, +518, 289, 568, 379, 487, 422, 317, 425, +90, 379, -125, 293, -292, 184, -374, 80, +-341, -17, -220, -106, -67, -209, 81, -333, +179, -467, 205, -552, 189, -522, 134, -366, +44, -133, -40, 114, -120, 352, -182, 551, +-199, 665, -176, 644, -124, 485, -52, 216, +43, -94, 140, -364, 233, -538, 307, -587, +327, -526, 266, -394, 130, -221, -48, -8, +-244, 216, -400, 388, -502, 445, -515, 403, +-399, 308, -174, 206, 118, 111, 402, 11, +603, -90, 680, -179, 634, -229, 466, -242, +191, -223, -125, -198, -417, -173, -629, -133, +-720, -46, -676, 91, -525, 229, -291, 306, +-14, 297, 229, 217, 420, 88, 549, -66, +581, -226, 517, -345, 370, -381, 177, -312, +-24, -152, -191, 78, -310, 320, -365, 480, +-344, 507, -258, 422, -124, 279, 30, 110, +164, -73, 213, -264, 191, -409, 116, -460, +-18, -411, -163, -316, -280, -222, -336, -130, +-294, -24, -160, 93, 26, 198, 234, 276, +411, 312, 502, 301, 490, 241, 369, 164, +164, 94, -75, 37, -290, -28, -434, -99, +-492, -142, -428, -146, -259, -137, -59, -146, +153, -167, 327, -186, 406, -173, 374, -114, +241, -15, 37, 90, -155, 177, -310, 234, +-413, 264, -412, 267, -312, 232, -131, 150, +93, 25, 305, -98, 455, -193, 497, -252, +436, -295, 295, -324, 101, -328, -98, -287, +-281, -192, -424, -50, -461, 121, -385, 294, +-255, 443, -82, 538, 85, 568, 202, 525, +277, 398, 285, 176, 253, -93, 191, -346, +82, -539, -40, -655, -123, -691, -159, -641, +-170, -517, -164, -329, -150, -97, -127, 157, +-95, 384, -16, 555, 87, 660, 158, 717, +213, 722, 246, 629, 258, 422, 257, 137, +191, -162, 58, -444, -93, -684, -248, -844, +-373, -873, -419, -765, -409, -548, -364, -275, +-269, 23, -114, 316, 91, 547, 280, 670, +412, 689, 486, 650, 497, 570, 459, 446, +355, 257, 209, 30, 38, -187, -171, -360, +-379, -500, -501, -603, -532, -638, -499, -585, +-403, -455, -270, -283, -85, -85, 144, 107, +353, 266, 483, 367, 501, 436, 423, 493, +296, 528, 156, 509, 3, 428, -165, 301, +-297, 142, -358, -55, -356, -285, -286, -502, +-160, -657, -46, -719, 16, -676, 63, -518, +112, -273, 168, 4, 186, 256, 146, 455, +97, 600, 87, 672, 111, 646, 133, 518, +148, 332, 131, 121, 79, -88, 2, -285, +-87, -442, -195, -544, -324, -587, -451, -560, +-534, -446, -506, -263, -356, -74, -127, 90, +145, 226, 400, 360, 601, 478, 732, 549, +751, 547, 622, 485, 356, 379, 25, 227, +-292, 32, -527, -192, -638, -419, -626, -625, +-523, -745, -350, -732, -124, -580, 106, -333, +309, -50, 396, 218, 352, 448, 261, 608, +161, 650, 57, 556, -52, 364, -148, 162, +-201, -1, -185, -122, -115, -206, -12, -240, +91, -239, 156, -231, 174, -227, 143, -210, +95, -168, 25, -113, -86, -55, -195, 16, +-274, 128, -292, 247, -214, 313, -75, 298, +74, 238, 207, 158, 305, 72, 366, -17, +380, -115, 296, -221, 130, -322, -66, -390, +-265, -416, -402, -391, -458, -314, -425, -166, +-333, 65, -192, 367, 0, 659, 206, 849, +366, 877, 440, 731, 412, 435, 292, 33, +145, -397, -10, -771, -139, -993, -203, -1016, +-233, -843, -205, -527, -103, -132, 20, 252, +120, 539, 153, 686, 106, 696, 8, 602, +-109, 423, -220, 190, -293, -52, -307, -236, +-252, -332, -135, -349, 17, -319, 207, -249, +380, -141, 484, -10, 506, 119, 430, 229, +311, 307, 173, 327, 0, 296, -191, 218, +-360, 95, -496, -87, -570, -306, -561, -517, +-487, -658, -338, -682, -140, -575, 75, -338, +298, -3, 504, 382, 656, 730, 676, 962, +556, 1017, 354, 880, 113, 572, -136, 155, +-366, -284, -542, -658, -603, -900, -528, -980, +-368, -896, -147, -671, 111, -336, 317, 34, +434, 370, 445, 620, 377, 767, 255, 794, +80, 690, -138, 463, -344, 156, -451, -168, +-431, -453, -309, -642, -136, -708, 52, -638, +230, -451, 385, -183, 479, 105, 462, 363, +342, 541, 138, 606, -108, 549, -310, 392, +-430, 174, -471, -69, -445, -296, -359, -469, +-211, -538, -5, -490, 215, -336, 372, -119, +446, 116, 446, 318, 380, 427, 268, 415, +143, 295, 1, 107, -163, -105, -285, -266, +-337, -312, -308, -221, -234, -36, -161, 161, +-100, 296, -46, 335, 3, 259, 40, 67, +67, -202, 76, -467, 66, -623, 71, -622, +118, -464, 180, -187, 210, 150, 197, 471, +129, 709, 40, 812, -20, 768, -81, 594, +-143, 314, -190, -25, -221, -356, -201, -612, +-133, -753, -60, -763, -17, -653, 3, -437, +16, -154, 55, 145, 118, 396, 173, 547, +193, 565, 171, 456, 142, 270, 91, 57, +20, -129, -73, -269, -205, -337, -319, -323, +-350, -216, -294, -46, -162, 129, 20, 274, +194, 380, 340, 436, 444, 415, 467, 301, +404, 94, 235, -166, -25, -435, -296, -660, +-503, -785, -596, -763, -581, -586, -471, -287, +-267, 81, 1, 452, 295, 758, 550, 929, +680, 930, 655, 752, 509, 450, 263, 87, +-13, -273, -265, -577, -480, -782, -599, -857, +-593, -790, -467, -592, -238, -291, 25, 63, +234, 403, 354, 676, 392, 837, 375, 862, +302, 729, 171, 461, 20, 99, -115, -287, +-194, -619, -206, -837, -188, -912, -145, -843, +-100, -637, -82, -337, -58, 8, -11, 346, +50, 628, 106, 812, 145, 880, 160, 816, +177, 638, 194, 388, 175, 95, 97, -207, +-40, -480, -186, -677, -305, -773, -372, -757, +-375, -646, -318, -460, -190, -234, -8, 12, +199, 253, 403, 453, 553, 577, 579, 613, +470, 576, 267, 468, 13, 303, -242, 105, +-466, -78, -616, -217, -640, -313, -529, -375, +-309, -397, -27, -369, 261, -304, 479, -228, +582, -151, 576, -54, 470, 70, 296, 214, +75, 341, -155, 416, -356, 417, -468, 349, +-485, 214, -428, 35, -309, -152, -164, -309, +-4, -395, 154, -396, 291, -303, 379, -147, +400, 28, 352, 175, 237, 262, 96, 281, +-37, 251, -164, 181, -272, 72, -326, -60, +-307, -181, -222, -253, -87, -273, 50, -239, +164, -163, 243, -57, 252, 61, 208, 181, +123, 278, 20, 323, -93, 293, -198, 193, +-247, 62, -227, -55, -155, -128, -75, -167, +2, -179, 75, -172, 147, -152, 183, -131, +187, -124, 182, -136, 147, -154, 88, -149, +20, -89, -48, 43, -97, 223, -142, 402, +-186, 524, -193, 558, -150, 494, -77, 343, +4, 112, 65, -184, 93, -495, 98, -744, +75, -864, 40, -826, -7, -656, -42, -397, +-24, -69, 27, 300, 117, 658, 217, 929, +273, 1057, 263, 1008, 172, 797, -3, 463, +-213, 51, -423, -380, -609, -773, -681, -1065, +-604, -1191, -372, -1111, -18, -837, 376, -414, +736, 76, 971, 538, 1016, 884, 856, 1065, +519, 1067, 65, 886, -424, 551, -852, 133, +-1107, -259, -1115, -533, -902, -652, -530, -638, +-84, -532, 346, -379, 705, -208, 901, -50, +898, 62, 735, 109, 460, 103, 144, 92, +-155, 117, -383, 191, -518, 275, -552, 329, +-515, 324, -418, 271, -275, 174, -108, 34, +55, -135, 180, -297, 284, -412, 361, -450, +387, -395, 367, -267, 285, -97, 146, 67, +-12, 194, -158, 274, -273, 308, -324, 292, +-307, 224, -245, 118, -148, 4, -37, -84, +76, -130, 167, -135, 198, -129, 177, -115, +125, -96, 84, -61, 51, -9, 23, 45, +-2, 87, -37, 111, -79, 122, -109, 123, +-120, 116, -130, 78, -120, 1, -100, -94, +-53, -169, 28, -213, 107, -212, 157, -177, +159, -125, 124, -64, 61, 7, -9, 85, +-55, 153, -81, 201, -80, 221, -53, 220, +-8, 212, 50, 203, 102, 164, 117, 78, +83, -43, 32, -169, -17, -268, -49, -320, +-68, -310, -92, -240, -118, -132, -145, -26, +-152, 50, -146, 86, -120, 76, -83, 7, +-34, -90, 46, -147, 157, -113, 286, 13, +390, 192, 423, 382, 355, 533, 224, 600, +68, 543, -113, 371, -300, 112, -468, -189, +-559, -494, -529, -737, -399, -849, -204, -824, +25, -697, 247, -500, 403, -229, 472, 94, +484, 425, 443, 707, 326, 900, 140, 970, +-53, 901, -210, 692, -301, 376, -345, 4, +-382, -376, -378, -703, -333, -910, -244, -944, +-115, -810, 37, -551, 179, -236, 302, 73, +395, 328, 451, 503, 457, 582, 383, 563, +241, 456, 50, 291, -151, 116, -308, -30, +-413, -124, -457, -178, -443, -212, -372, -233, +-231, -224, -56, -176, 108, -107, 230, -46, +297, -8, 309, 31, 297, 84, 260, 132, +186, 152, 90, 134, -19, 72, -84, -16, +-101, -104, -97, -158, -93, -166, -100, -137, +-102, -81, -110, 6, -123, 116, -124, 213, +-117, 264, -128, 238, -122, 145, -60, 26, +53, -72, 191, -130, 288, -152, 324, -159, +319, -151, 269, -116, 165, -60, 17, -6, +-147, 19, -290, 15, -372, -3, -359, -10, +-261, 5, -121, 34, 10, 45, 121, 33, +195, 28, 227, 57, 217, 111, 150, 156, +48, 175, -57, 154, -106, 99, -99, 11, +-87, -93, -89, -204, -83, -307, -53, -374, +-16, -361, 22, -240, 61, -40, 106, 171, +138, 328, 134, 409, 121, 414, 104, 350, +51, 216, -63, 19, -193, -207, -265, -388, +-266, -470, -212, -435, -123, -306, -13, -128, +101, 68, 200, 249, 271, 395, 284, 478, +237, 468, 134, 346, 17, 144, -82, -70, +-147, -234, -179, -331, -191, -383, -179, -400, +-151, -369, -93, -283, -17, -153, 41, 8, +59, 168, 52, 301, 60, 389, 87, 443, +114, 465, 121, 414, 112, 248, 80, -16, +22, -292, -35, -505, -85, -619, -126, -633, +-163, -526, -174, -303, -114, -5, 8, 307, +143, 582, 229, 760, 251, 774, 219, 610, +128, 320, -11, -5, -163, -311, -282, -579, +-355, -771, -349, -822, -257, -689, -96, -405, +90, -48, 227, 296, 293, 560, 294, 702, +253, 705, 187, 573, 95, 341, -6, 50, +-80, -240, -103, -455, -97, -529, -90, -451, +-105, -275, -133, -76, -164, 105, -189, 253, +-161, 349, -68, 359, 64, 262, 192, 81, +279, -130, 330, -315, 322, -431, 222, -451, +26, -377, -204, -227, -403, -28, -509, 206, +-479, 446, -321, 620, -68, 659, 196, 543, +425, 318, 573, 47, 599, -222, 492, -463, +254, -638, -43, -712, -315, -661, -511, -479, +-601, -198, -566, 116, -427, 400, -220, 613, +31, 730, 267, 748, 441, 653, 508, 433, +461, 103, 338, -272, 168, -601, -10, -810, +-174, -871, -309, -793, -377, -592, -349, -296, +-233, 60, -77, 415, 72, 703, 174, 865, +220, 867, 196, 724, 127, 495, 57, 224, +-15, -68, -79, -360, -133, -607, -148, -747, +-96, -752, -15, -632, 45, -429, 67, -190, +79, 47, 91, 256, 96, 422, 83, 526, +51, 543, 5, 464, -57, 313, -116, 141, +-166, -6, -189, -124, -177, -222, -148, -302, +-82, -344, 27, -326, 162, -241, 268, -116, +305, 0, 280, 81, 216, 136, 133, 187, +12, 232, -130, 255, -261, 234, -324, 171, +-311, 83, -240, -11, -124, -100, 8, -195, +120, -305, 180, -404, 197, -431, 190, -340, +146, -156, 58, 54, -51, 244, -130, 393, +-161, 483, -142, 497, -93, 431, -33, 292, +36, 104, 103, -95, 169, -249, 221, -318, +233, -324, 187, -319, 83, -332, -34, -334, +-154, -288, -261, -192, -338, -73, -361, 47, +-319, 165, -199, 289, -8, 409, 191, 500, +350, 530, 432, 463, 433, 304, 354, 99, +204, -103, 20, -277, -173, -430, -338, -566, +-445, -642, -464, -602, -368, -439, -199, -203, +-22, 47, 138, 272, 283, 451, 389, 569, +423, 606, 373, 553, 257, 406, 101, 175, +-74, -81, -214, -280, -289, -381, -312, -412, +-295, -414, -240, -377, -143, -273, -37, -108, +52, 68, 109, 208, 131, 289, 128, 311, +123, 282, 132, 227, 141, 158, 138, 66, +114, -54, 77, -172, 37, -242, -32, -249, +-117, -221, -201, -189, -273, -164, -313, -121, +-283, -37, -160, 91, 10, 230, 166, 334, +284, 376, 374, 358, 409, 299, 353, 195, +212, 42, 12, -151, -193, -340, -375, -464, +-476, -478, -447, -383, -320, -236, -153, -96, +16, 21, 183, 128, 326, 216, 406, 260, +385, 246, 285, 199, 145, 147, -1, 118, +-109, 124, -183, 151, -231, 149, -249, 83, +-227, -30, -159, -144, -81, -237, -7, -323, +64, -393, 117, -411, 145, -340, 150, -179, +138, 44, 104, 266, 41, 419, -45, 468, +-98, 420, -88, 319, -59, 185, -35, 19, +-15, -162, 12, -301, 31, -356, 42, -326, +48, -243, 37, -149, 6, -73, -24, -15, +-18, 57, 14, 165, 41, 282, 41, 352, +19, 354, -24, 299, -95, 205, -157, 61, +-182, -135, -178, -356, -156, -547, -91, -645, +52, -601, 232, -409, 374, -123, 440, 183, +433, 447, 348, 643, 169, 752, -69, 742, +-314, 586, -514, 299, -638, -54, -639, -383, +-500, -619, -263, -739, 21, -750, 285, -658, +498, -461, 620, -179, 631, 143, 540, 432, +358, 622, 111, 676, -139, 604, -313, 455, +-389, 269, -395, 59, -356, -160, -266, -343, +-133, -443, -17, -437, 56, -353, 86, -231, +76, -114, 32, -29, -23, 28, -40, 83, +-9, 139, 47, 167, 103, 146, 158, 107, +211, 100, 235, 134, 216, 171, 147, 175, +60, 135, -42, 61, -140, -24, -199, -108, +-217, -187, -211, -260, -205, -326, -183, -357, +-134, -310, -69, -186, 3, -31, 61, 108, +92, 220, 106, 317, 127, 403, 145, 461, +147, 450, 137, 353, 118, 190, 100, -1, +77, -190, 49, -362, 20, -506, -31, -602, +-118, -625, -224, -550, -284, -366, -271, -105, +-218, 169, -162, 398, -76, 560, 58, 671, +192, 728, 276, 690, 284, 530, 252, 280, +189, -4, 100, -279, 12, -515, -53, -684, +-95, -772, -130, -776, -155, -672, -168, -444, +-162, -129, -141, 185, -121, 426, -88, 574, +-31, 641, 80, 631, 225, 540, 339, 387, +377, 197, 321, -1, 208, -166, 43, -266, +-170, -308, -385, -330, -546, -350, -607, -348, +-542, -296, -331, -192, -16, -72, 333, 34, +610, 117, 753, 180, 761, 225, 635, 245, +388, 225, 39, 152, -336, 41, -637, -69, +-798, -136, -781, -145, -612, -108, -350, -50, +-49, 20, 256, 102, 501, 193, 630, 252, +617, 233, 472, 123, 247, -48, -10, -221, +-230, -350, -357, -406, -383, -391, -322, -310, +-199, -163, -32, 41, 137, 257, 250, 414, +257, 462, 158, 397, 6, 259, -148, 94, +-255, -57, -292, -175, -246, -244, -136, -261, +15, -221, 197, -123, 355, 5, 435, 109, +408, 140, 282, 103, 100, 39, -91, -24, +-247, -87, -354, -144, -401, -174, -391, -165, +-314, -112, -176, -16, -7, 103, 151, 193, +260, 221, 324, 198, 341, 167, 316, 149, +258, 121, 163, 68, 38, 4, -111, -50, +-236, -90, -310, -136, -333, -194, -318, -261, +-272, -321, -186, -339, -63, -283, 85, -151, +222, 19, 313, 183, 334, 318, 296, 419, +228, 476, 140, 469, 53, 372, -27, 196, +-94, -16, -129, -208, -131, -346, -111, -423, +-101, -444, -123, -406, -179, -303, -234, -143, +-249, 47, -218, 224, -140, 338, -24, 359, +129, 306, 296, 225, 438, 135, 519, 29, +489, -89, 346, -182, 123, -227, -127, -230, +-351, -212, -508, -180, -570, -135, -524, -77, +-370, 6, -136, 129, 143, 278, 398, 395, +555, 422, 577, 356, 466, 230, 278, 67, +59, -132, -166, -340, -376, -493, -533, -543, +-580, -484, -498, -330, -316, -121, -94, 86, +119, 245, 295, 341, 430, 386, 517, 388, +526, 340, 461, 242, 320, 116, 123, 0, +-93, -80, -288, -137, -434, -189, -533, -240, +-587, -280, -577, -290, -458, -259, -241, -196, +14, -111, 250, -14, 451, 99, 627, 228, +733, 361, 732, 456, 607, 465, 373, 367, +80, 191, -228, -14, -499, -216, -692, -394, +-777, -518, -752, -559, -625, -500, -409, -346, +-124, -136, 183, 78, 429, 249, 565, 358, +595, 422, 554, 456, 482, 449, 366, 385, +201, 272, 17, 123, -130, -45, -228, -210, +-295, -348, -341, -449, -368, -509, -378, -505, +-368, -415, -303, -250, -183, -54, -36, 131, +118, 278, 257, 385, 379, 445, 466, 452, +493, 399, 436, 281, 296, 109, 109, -79, +-82, -228, -237, -309, -350, -338, -425, -326, +-450, -263, -403, -151, -288, -24, -146, 81, +8, 140, 146, 151, 251, 132, 322, 114, +367, 117, 389, 136, 350, 147, 239, 119, +82, 44, -75, -57, -212, -164, -324, -263, +-388, -337, -394, -356, -336, -297, -226, -155, +-81, 44, 74, 240, 197, 382, 266, 447, +283, 433, 285, 358, 276, 240, 242, 93, +185, -73, 116, -241, 36, -377, -63, -445, +-173, -437, -294, -371, -408, -265, -481, -115, +-487, 73, -398, 259, -212, 382, 49, 412, +318, 359, 534, 247, 657, 100, 668, -37, +573, -129, 366, -171, 62, -177, -272, -156, +-534, -97, -664, -18, -672, 42, -570, 51, +-375, 25, -112, -2, 149, -18, 355, -33, +490, -50, 541, -56, 501, -45, 370, -16, +190, 30, 13, 88, -138, 131, -253, 129, +-338, 78, -363, 9, -321, -51, -233, -92, +-137, -114, -51, -108, 23, -54, 83, 42, +136, 134, 154, 181, 144, 165, 132, 85, +136, -42, 147, -172, 140, -254, 125, -271, +95, -232, 27, -145, -83, -13, -202, 148, +-277, 285, -291, 355, -255, 339, -193, 256, +-81, 125, 72, -34, 225, -192, 331, -310, +353, -367, 298, -355, 182, -256, 30, -71, +-120, 143, -231, 308, -271, 383, -253, 365, +-191, 266, -108, 95, -14, -111, 68, -300, +104, -429, 85, -456, 28, -379, -24, -216, +-54, -9, -45, 193, 9, 358, 102, 472, +223, 525, 321, 508, 352, 406, 300, 220, +179, -31, -11, -296, -245, -515, -463, -646, +-612, -675, -654, -593, -577, -393, -381, -99, +-92, 218, 225, 476, 505, 616, 681, 614, +729, 486, 646, 277, 450, 49, 185, -148, +-85, -284, -302, -347, -445, -327, -489, -233, +-447, -104, -335, 18, -190, 103, -44, 146, +67, 154, 109, 137, 106, 104, 92, 52, +87, -17, 84, -90, 83, -144, 100, -165, +120, -155, 133, -129, 126, -93, 100, -44, +51, 22, -20, 97, -93, 167, -148, 217, +-168, 235, -173, 218, -173, 169, -151, 87, +-101, -28, -27, -158, 55, -260, 139, -302, +204, -269, 241, -165, 252, -13, 219, 141, +128, 240, -20, 263, -184, 218, -328, 114, +-408, -34, -398, -187, -304, -290, -138, -303, +56, -227, 243, -97, 390, 52, 475, 187, +474, 275, 362, 303, 168, 281, -51, 220, +-230, 122, -352, 1, -414, -122, -415, -214, +-358, -258, -242, -256, -88, -219, 80, -148, +218, -47, 302, 65, 343, 159, 344, 204, +305, 197, 217, 139, 86, 39, -67, -68, +-208, -145, -311, -176, -351, -163, -324, -115, +-260, -27, -170, 92, -50, 204, 97, 271, +228, 278, 282, 233, 261, 138, 189, 1, +105, -154, 42, -286, 5, -367, -19, -381, +-34, -317, -36, -173, -35, 23, -38, 203, +-64, 319, -127, 359, -208, 329, -271, 230, +-263, 80, -177, -76, -21, -189, 161, -239, +308, -227, 402, -163, 441, -71, 411, 19, +281, 86, 64, 128, -178, 148, -370, 149, +-480, 123, -504, 73, -437, -2, -298, -86, +-111, -160, 96, -210, 282, -227, 416, -201, +461, -128, 401, -24, 269, 91, 116, 182, +-27, 235, -147, 241, -240, 203, -298, 140, +-297, 78, -227, 39, -98, 12, 33, -20, +113, -53, 141, -86, 134, -129, 118, -192, +89, -257, 44, -294, -12, -293, -69, -241, +-105, -134, -100, 20, -53, 192, -5, 349, +15, 471, 13, 539, 20, 534, 49, 434, +73, 246, 78, 2, 61, -254, 30, -488, +-2, -647, -26, -692, -39, -617, -63, -436, +-94, -183, -98, 103, -53, 359, 25, 530, +98, 583, 146, 525, 152, 387, 113, 209, +36, 28, -60, -129, -156, -235, -242, -286, +-285, -284, -245, -238, -101, -170, 103, -98, +294, -28, 409, 37, 420, 90, 338, 121, +188, 132, 2, 119, -205, 79, -399, 22, +-510, -31, -483, -68, -322, -83, -94, -79, +131, -63, 305, -28, 401, 20, 419, 69, +359, 96, 231, 92, 47, 64, -155, 23, +-322, -14, -395, -42, -355, -52, -244, -37, +-104, 0, 37, 45, 178, 83, 305, 96, +387, 62, 382, -29, 271, -154, 101, -262, +-67, -316, -199, -295, -296, -196, -351, -21, +-346, 192, -283, 389, -169, 514, -18, 530, +137, 426, 249, 217, 284, -55, 255, -318, +200, -501, 149, -571, 85, -531, -2, -394, +-85, -185, -134, 51, -129, 267, -91, 419, +-46, 488, -26, 470, -34, 377, -42, 232, +-26, 59, 3, -117, 18, -281, 18, -408, +1, -469, -10, -451, -2, -362, 19, -222, +33, -54, 14, 124, -15, 288, -13, 415, +35, 486, 87, 485, 96, 410, 60, 277, +13, 105, -16, -81, -39, -251, -61, -386, +-84, -468, -108, -486, -105, -425, -61, -291, +17, -118, 85, 47, 105, 179, 76, 266, +27, 295, -8, 273, -26, 211, -41, 133, +-70, 61, -87, 12, -63, -1, 8, 29, +95, 84, 141, 120, 134, 119, 93, 84, +42, 16, -10, -89, -63, -226, -112, -366, +-153, -465, -170, -490, -138, -421, -53, -260, +46, -34, 113, 212, 134, 431, 117, 587, +89, 649, 52, 596, -4, 424, -86, 177, +-171, -87, -209, -305, -173, -436, -82, -471, +20, -421, 106, -314, 168, -181, 215, -45, +250, 68, 248, 139, 198, 170, 76, 167, +-79, 149, -206, 131, -270, 116, -286, 79, +-288, 10, -275, -77, -231, -153, -141, -193, +-17, -190, 104, -136, 182, -39, 214, 87, +233, 212, 254, 310, 269, 346, 256, 293, +196, 150, 91, -40, -26, -219, -121, -344, +-194, -393, -258, -364, -314, -265, -347, -120, +-330, 43, -249, 182, -120, 253, 1, 237, +85, 153, 155, 44, 238, -41, 324, -74, +370, -49, 353, 26, 272, 129, 150, 228, +15, 281, -118, 261, -246, 149, -361, -44, +-446, -273, -465, -464, -377, -559, -193, -546, +28, -433, 229, -238, 380, 14, 475, 279, +513, 501, 471, 637, 322, 660, 69, 567, +-220, 378, -463, 135, -606, -121, -635, -359, +-565, -552, -407, -663, -175, -659, 120, -531, +428, -304, 678, -31, 798, 232, 760, 448, +587, 584, 330, 621, 34, 546, -281, 370, +-579, 133, -797, -111, -882, -310, -801, -429, +-570, -455, -247, -403, 91, -297, 391, -164, +631, -23, 783, 100, 810, 177, 691, 184, +450, 136, 143, 76, -159, 40, -392, 37, +-533, 64, -583, 120, -561, 191, -458, 249, +-277, 259, -47, 206, 167, 88, 305, -90, +365, -295, 361, -464, 310, -549, 226, -535, +123, -437, 2, -279, -119, -80, -199, 134, +-207, 330, -150, 480, -76, 568, -10, 587, +38, 547, 76, 456, 109, 310, 127, 111, +113, -137, 57, -407, -22, -647, -90, -796, +-117, -814, -102, -697, -85, -461, -75, -131, +-56, 240, -7, 579, 64, 812, 124, 886, +158, 791, 146, 550, 112, 220, 74, -126, +56, -422, 43, -622, 18, -704, -20, -658, +-54, -494, -65, -249, -70, 11, -77, 225, +-96, 361, -121, 418, -125, 408, -85, 351, +3, 267, 98, 173, 169, 77, 214, -11, +244, -87, 248, -155, 203, -228, 110, -308, +-20, -375, -159, -397, -264, -346, -304, -225, +-274, -55, -212, 128, -128, 291, -27, 407, +94, 460, 221, 433, 319, 330, 357, 186, +318, 39, 231, -80, 123, -153, 20, -182, +-96, -187, -223, -190, -341, -201, -401, -215, +-371, -222, -273, -218, -127, -209, 37, -179, +197, -101, 339, 28, 449, 189, 498, 346, +447, 465, 300, 517, 92, 491, -129, 388, +-315, 217, -441, -9, -496, -261, -476, -485, +-380, -620, -212, -627, 9, -512, 232, -307, +387, -58, 446, 187, 424, 384, 356, 500, +240, 509, 78, 406, -98, 215, -243, -12, +-322, -208, -332, -335, -266, -375, -150, -333, +-18, -220, 89, -56, 158, 134, 194, 302, +197, 396, 148, 385, 48, 272, -59, 99, +-127, -89, -134, -254, -97, -366, -49, -401, +-15, -352, 6, -237, 18, -87, 18, 60, +-4, 167, -44, 217, -81, 221, -85, 214, +-41, 226, 40, 246, 134, 244, 199, 199, +208, 111, 162, -18, 87, -179, -2, -350, +-105, -485, -220, -537, -304, -477, -321, -297, +-266, -33, -159, 245, -36, 463, 74, 575, +146, 570, 189, 463, 210, 280, 207, 59, +160, -161, 85, -335, 10, -428, -47, -434, +-75, -372, -92, -272, -111, -154, -136, -33, +-151, 88, -146, 198, -119, 280, -79, 318, +-42, 307, -6, 255, 34, 190, 76, 127, +104, 54, 107, -37, 80, -133, 27, -213, +-33, -275, -69, -319, -71, -342, -54, -331, +-35, -280, -9, -177, 25, -20, 64, 169, +85, 349, 63, 478, -6, 536, -96, 520, +-164, 432, -195, 272, -177, 56, -132, -179, +-62, -388, 24, -531, 125, -582, 203, -546, +218, -441, 165, -288, 54, -103, -78, 92, +-203, 269, -270, 395, -263, 451, -193, 449, +-80, 401, 58, 325, 204, 227, 307, 102, +323, -53, 243, -214, 92, -345, -79, -423, +-226, -435, -313, -384, -331, -270, -282, -108, +-180, 70, -39, 225, 106, 322, 198, 334, +218, 257, 165, 124, 74, -13, -22, -112, +-93, -155, -115, -142, -98, -82, -46, 15, +19, 121, 100, 202, 163, 230, 176, 200, +120, 118, 6, 4, -115, -118, -214, -228, +-269, -314, -279, -370, -241, -370, -158, -297, +-44, -150, 92, 43, 214, 238, 286, 394, +288, 479, 245, 479, 177, 393, 96, 236, +18, 33, -55, -168, -110, -316, -143, -379, +-146, -356, -128, -268, -113, -153, -110, -42, +-125, 47, -139, 109, -135, 141, -99, 140, +-32, 103, 55, 47, 156, 1, 249, -22, +337, -23, 384, -11, 369, 13, 270, 42, +114, 72, -57, 96, -219, 99, -341, 60, +-410, -22, -405, -122, -331, -202, -197, -230, +-33, -198, 123, -119, 246, -10, 310, 110, +322, 220, 293, 292, 239, 295, 161, 221, +66, 92, -23, -58, -100, -190, -150, -279, +-178, -311, -185, -288, -171, -220, -137, -112, +-73, 27, 11, 170, 107, 277, 190, 315, +238, 289, 241, 218, 204, 116, 147, 0, +59, -110, -39, -196, -135, -241, -190, -231, +-194, -172, -146, -86, -62, -7, 29, 45, +116, 75, 168, 95, 185, 107, 166, 102, +118, 76, 47, 33, -32, -12, -81, -45, +-84, -64, -47, -69, 8, -65, 57, -50, +92, -14, 99, 38, 70, 87, 5, 109, +-74, 91, -143, 49, -175, 3, -155, -29, +-78, -50, 53, -68, 199, -84, 321, -90, +385, -83, 376, -61, 293, -31, 141, 1, +-51, 40, -250, 88, -399, 135, -467, 166, +-434, 165, -329, 110, -175, 7, 3, -111, +180, -203, 333, -244, 426, -223, 454, -151, +417, -39, 337, 103, 218, 241, 78, 332, +-68, 342, -214, 258, -335, 101, -413, -82, +-432, -249, -391, -363, -289, -411, -131, -389, +52, -287, 227, -113, 362, 102, 449, 295, +466, 417, 399, 444, 265, 386, 100, 267, +-54, 114, -181, -46, -274, -182, -328, -267, +-333, -289, -287, -253, -221, -185, -143, -115, +-69, -68, 17, -45, 106, -23, 192, 18, +259, 78, 295, 139, 301, 185, 259, 202, +171, 186, 47, 134, -76, 49, -186, -47, +-269, -130, -313, -167, -303, -138, -236, -52, +-143, 50, -50, 119, 26, 123, 81, 70, +121, -20, 146, -122, 162, -210, 173, -261, +177, -249, 161, -159, 119, -17, 51, 136, +-50, 255, -172, 311, -289, 301, -364, 242, +-372, 161, -307, 69, -169, -25, 10, -110, +198, -175, 338, -211, 407, -217, 379, -207, +264, -191, 83, -168, -129, -119, -309, -38, +-418, 64, -422, 163, -347, 237, -207, 277, +-41, 274, 124, 232, 250, 156, 300, 52, +270, -63, 181, -167, 70, -232, -41, -236, +-135, -188, -192, -118, -205, -50, -181, 3, +-141, 38, -88, 56, -36, 59, -3, 44, +13, 23, 11, 14, 4, 29, -7, 56, +-18, 75, -30, 72, -37, 41, -30, -2, +-21, -37, 3, -49, 34, -38, 75, -12, +94, 22, 96, 56, 89, 77, 59, 75, +5, 40, -84, -27, -182, -105, -269, -172, +-310, -208, -304, -208, -254, -179, -161, -126, +-44, -56, 91, 32, 212, 137, 296, 244, +323, 328, 292, 370, 214, 366, 102, 316, +-1, 210, -85, 59, -148, -119, -200, -296, +-231, -438, -236, -514, -231, -515, -218, -445, +-208, -321, -185, -164, -135, 16, -47, 205, +80, 383, 215, 518, 344, 588, 423, 577, +443, 494, 382, 341, 249, 126, 58, -126, +-169, -373, -371, -568, -503, -667, -527, -644, +-463, -508, -324, -291, -151, -39, 21, 198, +167, 379, 258, 484, 291, 493, 271, 409, +218, 263, 155, 105, 117, -28, 117, -124, +129, -175, 124, -189, 74, -180, -6, -161, +-107, -144, -223, -126, -331, -111, -407, -98, +-407, -76, -322, -28, -160, 55, 50, 160, +261, 249, 431, 294, 511, 280, 501, 215, +400, 113, 237, -12, 25, -144, -192, -252, +-364, -304, -452, -290, -429, -223, -325, -128, +-163, -34, 21, 43, 201, 102, 338, 146, +409, 177, 399, 194, 299, 194, 132, 171, +-60, 123, -221, 50, -317, -45, -329, -156, +-258, -253, -127, -299, 45, -277, 228, -179, +376, -22, 431, 146, 370, 273, 212, 327, +3, 295, -197, 191, -351, 34, -420, -140, +-388, -278, -259, -339, -50, -306, 187, -193, +399, -35, 517, 115, 519, 223, 402, 270, +211, 259, -11, 202, -224, 105, -378, -5, +-452, -98, -425, -147, -309, -152, -120, -128, +90, -88, 274, -47, 391, -15, 427, 9, +404, 22, 332, 28, 222, 22, 73, 6, +-84, -8, -204, -12, -267, -4, -278, 7, +-263, 15, -228, 19, -170, 29, -83, 49, +24, 74, 132, 86, 230, 77, 297, 47, +339, 1, 352, -53, 333, -102, 272, -129, +155, -129, -5, -92, -186, -24, -334, 56, +-425, 116, -438, 128, -385, 81, -279, -10, +-118, -115, 79, -202, 286, -234, 439, -199, +512, -93, 487, 70, 395, 250, 267, 394, +116, 461, -47, 421, -207, 282, -321, 82, +-376, -133, -367, -321, -314, -452, -236, -506, +-145, -481, -54, -381, 44, -230, 148, -57, +251, 110, 324, 254, 338, 367, 309, 441, +253, 465, 187, 429, 97, 331, -25, 179, +-160, 0, -270, -180, -312, -329, -294, -425, +-235, -452, -173, -407, -104, -296, -24, -141, +60, 24, 134, 163, 168, 254, 170, 286, +139, 261, 116, 194, 99, 109, 88, 33, +64, -23, 15, -46, -40, -32, -92, 7, +-122, 44, -143, 50, -166, 16, -187, -54, +-190, -142, -148, -223, -64, -273, 42, -265, +126, -191, 177, -60, 202, 105, 210, 259, +193, 361, 124, 386, 6, 332, -134, 214, +-242, 57, -283, -102, -266, -235, -197, -319, +-108, -341, -8, -301, 79, -207, 155, -89, +196, 29, 173, 137, 89, 222, -34, 274, +-128, 286, -184, 248, -185, 162, -162, 40, +-122, -96, -67, -217, 6, -300, 87, -328, +138, -290, 141, -191, 95, -50, 38, 110, +-12, 257, -47, 353, -69, 370, -96, 318, +-127, 210, -149, 67, -138, -89, -103, -232, +-75, -337, -66, -381, -66, -355, -41, -272, +13, -147, 76, -9, 125, 124, 137, 236, +126, 313, 97, 344, 67, 324, 18, 253, +-50, 142, -135, 12, -218, -111, -258, -212, +-247, -285, -189, -314, -125, -288, -60, -203, +3, -83, 84, 44, 165, 146, 212, 203, +214, 201, 166, 154, 97, 82, 28, 5, +-32, -51, -88, -70, -153, -44, -213, 17, +-249, 79, -235, 109, -175, 91, -103, 27, +-47, -61, -1, -145, 63, -195, 140, -198, +203, -157, 218, -78, 178, 21, 105, 117, +22, 181, -47, 201, -109, 183, -158, 142, +-200, 101, -210, 64, -162, 25, -67, -24, +37, -84, 101, -153, 120, -221, 97, -269, +73, -286, 44, -262, 4, -176, -57, -29, +-116, 155, -134, 336, -95, 471, -11, 522, +74, 470, 134, 327, 161, 114, 165, -138, +153, -382, 108, -569, 24, -654, -95, -606, +-209, -427, -275, -162, -269, 133, -200, 401, +-110, 590, -12, 662, 88, 596, 186, 407, +268, 135, 300, -158, 270, -402, 173, -548, +57, -569, -40, -478, -89, -310, -112, -102, +-138, 110, -153, 290, -139, 404, -76, 438, +-5, 394, 54, 295, 73, 170, 68, 41, +63, -87, 75, -203, 88, -292, 77, -341, +47, -342, 3, -297, -23, -210, -26, -105, +-9, 5, 12, 114, 17, 215, 20, 289, +38, 320, 81, 298, 120, 234, 117, 149, +65, 59, -3, -29, -44, -113, -62, -178, +-67, -220, -71, -230, -70, -208, -32, -164, +35, -112, 117, -54, 159, 6, 151, 66, +108, 117, 53, 149, 15, 151, -9, 119, +-21, 73, -39, 28, -41, -8, -21, -31, +37, -41, 103, -34, 137, -11, 122, 19, +69, 43, 17, 45, -29, 22, -71, -14, +-120, -46, -166, -55, -178, -49, -124, -41, +2, -38, 147, -44, 271, -62, 346, -83, +373, -96, 358, -91, 285, -54, 142, 21, +-64, 123, -276, 225, -435, 298, -509, 308, +-480, 238, -373, 101, -207, -62, -9, -211, +210, -310, 419, -342, 572, -303, 626, -201, +549, -66, 386, 62, 177, 147, -22, 179, +-211, 168, -374, 137, -492, 103, -526, 82, +-451, 71, -292, 58, -94, 31, 78, -10, +208, -59, 292, -118, 338, -174, 340, -215, +287, -215, 190, -162, 70, -65, -24, 57, +-67, 172, -68, 256, -52, 297, -53, 291, +-68, 236, -88, 144, -106, 19, -124, -123, +-154, -252, -184, -342, -190, -377, -130, -356, +-12, -283, 129, -165, 244, -9, 303, 165, +319, 319, 293, 418, 230, 444, 120, 392, +-15, 276, -162, 118, -276, -53, -332, -211, +-322, -329, -275, -390, -220, -379, -153, -298, +-71, -173, 43, -41, 162, 71, 256, 157, +297, 213, 283, 234, 237, 215, 165, 167, +67, 106, -59, 44, -201, -9, -310, -51, +-352, -87, -312, -123, -217, -151, -101, -159, +17, -138, 115, -89, 193, -22, 237, 51, +231, 120, 162, 181, 50, 219, -65, 218, +-150, 171, -200, 84, -232, -30, -233, -154, +-209, -260, -146, -324, -58, -343, 54, -310, +152, -216, 206, -64, 222, 121, 210, 300, +175, 434, 101, 490, 0, 460, -116, 348, +-216, 173, -284, -36, -305, -238, -273, -396, +-211, -471, -143, -452, -75, -352, -8, -207, +62, -57, 118, 69, 144, 155, 149, 201, +151, 203, 165, 176, 176, 137, 170, 109, +127, 101, 50, 114, -54, 134, -166, 140, +-274, 117, -364, 59, -411, -25, -409, -126, +-344, -232, -227, -325, -59, -381, 113, -377, +256, -296, 342, -149, 381, 28, 380, 198, +330, 337, 233, 426, 93, 448, -49, 395, +-181, 276, -282, 120, -341, -42, -357, -176, +-336, -268, -287, -311, -207, -309, -98, -280, +21, -229, 118, -153, 173, -60, 200, 29, +221, 108, 234, 171, 229, 219, 194, 243, +135, 240, 55, 201, -33, 128, -125, 33, +-214, -63, -288, -134, -336, -170, -337, -178, +-277, -164, -150, -128, 5, -72, 158, -9, +257, 43, 315, 76, 322, 86, 275, 76, +175, 54, 35, 30, -93, 6, -182, -16, +-208, -30, -182, -31, -122, -14, -57, 11, +-4, 29, 35, 28, 56, 14, 57, -7, +37, -30, 8, -39, -7, -29, 1, 0, +33, 47, 68, 102, 82, 146, 65, 153, +15, 105, -39, 9, -80, -119, -98, -246, +-97, -339, -66, -367, 1, -319, 96, -193, +183, 0, 224, 219, 209, 418, 128, 545, +28, 566, -77, 470, -156, 282, -204, 38, +-205, -221, -150, -437, -57, -565, 56, -586, +152, -500, 222, -324, 237, -94, 195, 142, +118, 328, 37, 436, -31, 453, -87, 385, +-119, 250, -116, 76, -78, -97, -8, -229, +64, -291, 107, -277, 115, -198, 87, -82, +43, 49, -8, 160, -51, 217, -80, 206, +-85, 135, -57, 26, 16, -95, 113, -193, +206, -238, 260, -213, 256, -132, 211, -20, +121, 92, 19, 178, -104, 213, -219, 196, +-302, 133, -325, 47, -274, -38, -169, -102, +-26, -128, 116, -114, 235, -77, 316, -38, +355, -2, 344, 23, 283, 34, 181, 32, +63, 28, -37, 27, -101, 30, -139, 32, +-160, 27, -170, 16, -174, -8, -159, -39, +-129, -69, -82, -84, -28, -81, 22, -50, +74, -4, 136, 38, 193, 71, 230, 88, +227, 81, 191, 51, 137, 11, 81, -27, +47, -42, 8, -27, -30, 9, -81, 52, +-119, 83, -142, 86, -156, 56, -165, -6, +-171, -87, -148, -172, -100, -235, -10, -246, +100, -197, 199, -100, 259, 22, 274, 150, +252, 253, 203, 306, 118, 302, 9, 241, +-101, 139, -184, 21, -215, -89, -198, -171, +-142, -213, -74, -210, -17, -172, 21, -112, +43, -48, 50, 4, 43, 41, 17, 57, +-8, 51, -16, 24, 3, -9, 50, -33, +94, -41, 121, -27, 105, 1, 69, 47, +9, 107, -50, 165, -111, 200, -167, 198, +-194, 152, -191, 64, -137, -49, -54, -167, +36, -267, 111, -329, 156, -331, 173, -264, +172, -144, 145, 6, 85, 157, -11, 271, +-113, 319, -185, 295, -221, 211, -208, 90, +-168, -40, -116, -149, -52, -213, 26, -212, +107, -152, 160, -52, 157, 56, 107, 144, +37, 189, -17, 188, -52, 141, -78, 63, +-107, -33, -136, -136, -133, -216, -112, -255, +-67, -244, -39, -195, -18, -117, 10, -18, +52, 91, 106, 195, 138, 274, 139, 312, +96, 297, 10, 230, -96, 124, -188, -2, +-259, -122, -288, -213, -282, -263, -217, -268, +-90, -229, 72, -154, 228, -61, 326, 17, +345, 67, 277, 88, 151, 95, 2, 95, +-151, 95, -292, 94, -386, 92, -398, 90, +-316, 84, -165, 65, 9, 35, 144, -9, +218, -64, 233, -109, 198, -129, 140, -127, +37, -116, -79, -96, -194, -69, -254, -41, +-227, -14, -141, 19, -34, 64, 54, 115, +123, 161, 179, 200, 219, 220, 211, 196, +137, 118, -12, -8, -179, -155, -310, -287, +-375, -368, -381, -372, -346, -290, -263, -139, +-118, 48, 89, 239, 297, 388, 452, 454, +505, 409, 455, 276, 339, 90, 182, -102, +2, -261, -193, -360, -386, -384, -513, -333, +-548, -222, -478, -77, -322, 73, -143, 189, +45, 251, 205, 258, 346, 224, 439, 159, +450, 70, 365, -25, 201, -110, 14, -168, +-143, -178, -242, -133, -287, -52, -279, 40, +-232, 117, -135, 166, -9, 178, 114, 136, +177, 35, 171, -101, 108, -233, 20, -319, +-55, -332, -111, -265, -125, -130, -111, 43, +-61, 219, 26, 359, 138, 435, 246, 427, +294, 337, 250, 181, 142, -5, 0, -180, +-124, -311, -220, -378, -295, -384, -323, -340, +-288, -255, -159, -134, 18, 0, 197, 118, +323, 202, 375, 256, 358, 279, 288, 274, +175, 237, 32, 164, -122, 63, -264, -50, +-344, -145, -333, -208, -229, -231, -87, -216, +62, -159, 186, -74, 292, 17, 355, 89, +342, 128, 255, 124, 98, 76, -64, -2, +-198, -75, -279, -106, -283, -92, -228, -42, +-132, 34, -12, 116, 112, 176, 238, 194, +316, 156, 330, 63, 279, -60, 179, -172, +82, -234, -11, -231, -90, -164, -164, -56, +-215, 70, -230, 175, -196, 227, -129, 209, +-45, 128, 35, 6, 90, -125, 126, -228, +164, -273, 205, -246, 226, -162, 218, -37, +174, 100, 145, 222, 123, 305, 96, 345, +50, 335, -30, 270, -110, 159, -193, 20, +-253, -125, -274, -270, -266, -402, -229, -500, +-163, -533, -58, -481, 95, -338, 250, -118, +381, 150, 456, 416, 467, 635, 427, 760, +335, 757, 195, 622, 3, 369, -204, 42, +-390, -297, -501, -585, -526, -767, -462, -809, +-326, -713, -147, -511, 58, -241, 276, 59, +464, 344, 577, 561, 578, 671, 458, 670, +277, 571, 55, 394, -157, 164, -349, -86, +-488, -317, -526, -494, -462, -588, -294, -580, +-71, -469, 150, -281, 323, -57, 417, 168, +433, 359, 387, 481, 282, 517, 139, 471, +-21, 349, -159, 171, -249, -20, -284, -190, +-277, -317, -253, -401, -218, -442, -185, -427, +-121, -356, -30, -235, 86, -77, 195, 96, +269, 263, 318, 400, 348, 494, 347, 525, +296, 470, 167, 325, -20, 118, -198, -102, +-340, -299, -412, -440, -452, -502, -446, -480, +-375, -392, -240, -261, -48, -107, 148, 47, +304, 171, 393, 245, 416, 278, 393, 292, +335, 296, 229, 287, 69, 258, -118, 196, +-276, 94, -377, -36, -413, -171, -406, -295, +-348, -395, -236, -443, -86, -408, 98, -278, +253, -77, 355, 141, 380, 325, 324, 440, +205, 465, 45, 396, -125, 247, -270, 48, +-385, -161, -427, -337, -378, -434, -257, -435, +-79, -350, 81, -201, 213, -16, 292, 167, +320, 317, 296, 418, 219, 460, 103, 426, +-36, 310, -171, 137, -275, -58, -312, -241, +-297, -396, -261, -505, -217, -545, -156, -499, +-69, -370, 37, -175, 113, 51, 162, 270, +180, 445, 186, 559, 197, 601, 173, 555, +126, 419, 37, 216, -76, -18, -187, -241, +-281, -420, -339, -532, -348, -561, -318, -507, +-232, -384, -99, -212, 66, -17, 225, 172, +314, 316, 340, 394, 299, 404, 225, 362, +116, 280, -12, 179, -146, 69, -260, -42, +-327, -144, -344, -219, -302, -258, -237, -270, +-170, -262, -96, -227, -11, -156, 98, -60, +215, 42, 293, 140, 339, 224, 342, 279, +324, 296, 268, 273, 137, 213, -45, 118, +-264, 0, -459, -125, -597, -244, -661, -337, +-626, -386, -478, -374, -237, -301, 74, -180, +385, -22, 645, 157, 799, 327, 809, 443, +680, 485, 426, 448, 104, 343, -245, 184, +-540, -2, -745, -178, -806, -320, -729, -410, +-545, -439, -272, -409, 29, -332, 316, -223, +529, -93, 628, 53, 618, 196, 508, 319, +322, 410, 104, 454, -135, 429, -323, 321, +-435, 146, -460, -61, -399, -265, -290, -430, +-143, -515, 14, -490, 160, -354, 272, -132, +330, 124, 324, 355, 278, 501, 203, 526, +118, 437, 19, 254, -77, 10, -153, -242, +-195, -439, -207, -539, -204, -531, -177, -425, +-147, -248, -93, -28, -41, 182, 17, 349, +83, 464, 139, 526, 207, 520, 275, 441, +326, 304, 355, 129, 338, -62, 271, -252, +154, -423, -21, -557, -203, -636, -385, -635, +-524, -532, -592, -339, -578, -90, -459, 178, +-251, 437, 27, 654, 330, 787, 606, 809, +798, 703, 880, 479, 825, 169, 639, -173, +340, -495, -26, -743, -400, -879, -702, -880, +-887, -734, -918, -458, -787, -97, -532, 282, +-170, 614, 203, 831, 541, 896, 785, 808, +891, 590, 866, 270, 704, -106, 435, -465, +115, -725, -207, -838, -469, -802, -646, -633, +-729, -366, -680, -44, -518, 278, -261, 551, +24, 727, 293, 776, 512, 694, 655, 509, +701, 261, 636, -17, 470, -295, 220, -533, +-53, -696, -300, -769, -476, -731, -568, -575, +-576, -322, -500, -13, -325, 302, -87, 580, +184, 788, 410, 881, 547, 817, 609, 598, +568, 268, 451, -107, 250, -457, 4, -713, +-233, -841, -416, -825, -506, -667, -500, -383, +-414, -39, -253, 283, -54, 521, 143, 643, +316, 646, 424, 541, 462, 361, 412, 145, +294, -70, 134, -257, -22, -389, -164, -445, +-264, -431, -306, -361, -302, -249, -243, -106, +-156, 50, -43, 208, 73, 345, 150, 434, +182, 448, 189, 373, 178, 224, 177, 38, +138, -161, 65, -350, -16, -490, -86, -535, +-106, -459, -121, -286, -134, -53, -138, 187, +-117, 394, -62, 526, 1, 557, 40, 478, +54, 302, 49, 62, 44, -186, 53, -384, +70, -503, 86, -525, 89, -445, 85, -283, +72, -81, 56, 115, -2, 277, -94, 392, +-199, 438, -280, 401, -298, 295, -271, 160, +-189, 25, -60, -100, 92, -206, 242, -283, +349, -323, 388, -324, 363, -286, 248, -222, +85, -142, -110, -43, -291, 73, -407, 198, +-459, 316, -428, 408, -335, 461, -184, 460, +-3, 379, 177, 218, 310, 2, 377, -237, +364, -472, 280, -666, 152, -769, 9, -742, +-128, -575, -243, -293, -317, 63, -330, 436, +-264, 761, -161, 978, -38, 1048, 58, 940, +131, 656, 172, 244, 146, -224, 78, -678, +-19, -1045, -124, -1259, -196, -1273, -217, -1073, +-165, -687, -51, -163, 70, 423, 187, 970, +262, 1373, 285, 1555, 234, 1475, 99, 1135, +-82, 580, -270, -97, -415, -772, -494, -1335, +-471, -1674, -362, -1712, -179, -1437, 34, -907, +241, -225, 411, 483, 510, 1100, 516, 1518, +420, 1661, 227, 1514, -15, 1113, -249, 541, +-458, -97, -592, -687, -648, -1141, -575, -1396, +-389, -1423, -140, -1225, 140, -839, 390, -333, +580, 210, 673, 711, 632, 1094, 477, 1292, +243, 1283, -43, 1082, -325, 715, -566, 220, +-711, -325, -750, -820, -671, -1178, -493, -1341, +-245, -1289, 37, -1032, 316, -605, 566, -69, +729, 496, 797, 995, 740, 1336, 569, 1459, +311, 1346, 1, 1022, -320, 532, -617, -56, +-861, -656, -980, -1170, -942, -1513, -748, -1629, +-424, -1484, -50, -1091, 352, -509, 713, 164, +971, 826, 1079, 1388, 1003, 1757, 763, 1851, +401, 1635, -27, 1137, -435, 441, -758, -338, +-962, -1074, -1024, -1647, -947, -1970, -723, -1980, +-391, -1665, -1, -1061, 370, -269, 684, 567, +900, 1308, 999, 1846, 965, 2093, 779, 2002, +479, 1581, 82, 892, -339, 48, -714, -815, +-979, -1548, -1082, -2023, -1020, -2159, -814, -1936, +-463, -1385, -18, -601, 458, 284, 868, 1118, +1109, 1759, 1176, 2096, 1061, 2063, 802, 1677, +416, 1028, -54, 235, -521, -577, -895, -1284, +-1117, -1760, -1159, -1923, -1022, -1769, -730, -1351, +-331, -747, 113, -59, 553, 615, 921, 1181, +1148, 1559, 1185, 1700, 1051, 1589, 762, 1250, +378, 738, -69, 126, -521, -512, -884, -1089, +-1117, -1512, -1163, -1718, -1023, -1672, -721, -1365, +-293, -825, 185, -130, 630, 605, 983, 1258, +1178, 1723, 1198, 1920, 1028, 1800, 684, 1367, +233, 690, -258, -121, -685, -925, -996, -1573, +-1148, -1955, -1122, -2017, -910, -1744, -543, -1172, +-66, -390, 437, 459, 863, 1225, 1140, 1786, +1228, 2053, 1133, 1982, 868, 1579, 448, 918, +-67, 106, -564, -723, -955, -1435, -1159, -1909, +-1175, -2068, -1007, -1892, -670, -1412, -229, -703, +265, 119, 718, 913, 1051, 1556, 1210, 1952, +1166, 2042, 942, 1799, 590, 1261, 150, 523, +-310, -295, -731, -1068, -1027, -1676, -1140, -2012, +-1063, -2011, -821, -1671, -466, -1052, -41, -257, +390, 577, 772, 1310, 1020, 1815, 1111, 2004, +1028, 1843, 782, 1365, 427, 661, 17, -135, +-383, -886, -711, -1483, -927, -1816, -996, -1819, +-907, -1504, -680, -953, -338, -268, 26, 445, +378, 1075, 665, 1515, 851, 1692, 924, 1585, +852, 1224, 657, 668, 368, 8, 31, -646, +-302, -1200, -583, -1558, -786, -1658, -872, -1476, +-829, -1045, -653, -429, -374, 280, -34, 956, +309, 1467, 592, 1710, 767, 1650, 818, 1300, +761, 713, 575, -15, 299, -747, -29, -1337, +-330, -1667, -543, -1681, -663, -1390, -679, -857, +-593, -177, -420, 530, -180, 1135, 71, 1529, +290, 1633, 458, 1440, 526, 1001, 497, 394, +377, -287, 210, -920, 29, -1391, -151, -1616, +-298, -1556, -382, -1213, -382, -636, -307, 72, +-186, 774, -59, 1337, 55, 1658, 140, 1678, +197, 1389, 215, 839, 194, 131, 135, -604, +67, -1224, 6, -1605, -31, -1676, -47, -1442, +-70, -970, -90, -345, -129, 334, -169, 937, +-199, 1345, -219, 1490, -217, 1371, -186, 1038, +-112, 555, 21, 5, 182, -518, 337, -935, +457, -1179, 497, -1216, 447, -1045, 296, -712, +82, -280, -169, 189, -427, 616, -648, 918, +-768, 1044, -757, 983, -618, 748, -376, 369, +-77, -85, 248, -513, 544, -818, 770, -942, +885, -879, 866, -646, 698, -279, 415, 151, +52, 546, -319, 823, -652, 925, -905, 833, +-1025, 570, -1007, 194, -826, -222, -513, -607, +-121, -889, 286, -1004, 637, -923, 889, -665, +1029, -276, 1022, 182, 862, 632, 560, 980, +160, 1159, -259, 1138, -650, 909, -948, 496, +-1117, -40, -1122, -597, -968, -1061, -661, -1344, +-245, -1392, 226, -1192, 667, -767, 991, -181, +1164, 468, 1159, 1056, 978, 1475, 628, 1634, +156, 1498, -359, 1084, -816, 466, -1154, -261, +-1297, -969, -1223, -1526, -940, -1820, -495, -1783, +25, -1422, 556, -799, 999, -17, 1267, 789, +1300, 1474, 1094, 1906, 697, 2002, 191, 1743, +-353, 1173, -835, 387, -1178, -487, -1317, -1290, +-1222, -1866, -919, -2111, -455, -1991, 84, -1535, +606, -807, 1014, 78, 1256, 957, 1281, 1667, +1100, 2084, 729, 2145, 221, 1849, -325, 1240, +-816, 418, -1161, -484, -1311, -1311, -1253, -1922, +-995, -2212, -579, -2133, -65, -1699, 483, -971, +944, -54, 1250, 896, 1353, 1702, 1237, 2227, +920, 2380, 434, 2128, -122, 1494, -664, 573, +-1118, -467, -1399, -1435, -1421, -2158, -1177, -2508, +-720, -2419, -156, -1892, 440, -1020, 986, 35, +1373, 1090, 1503, 1951, 1348, 2459, 950, 2526, +373, 2150, -272, 1401, -877, 401, -1304, -668, +-1492, -1607, -1417, -2251, -1073, -2503, -508, -2319, +185, -1726, 843, -826, 1322, 217, 1550, 1215, +1491, 1996, 1151, 2421, 601, 2415, -74, 1977, +-732, 1188, -1264, 183, -1566, -856, -1561, -1734, +-1253, -2289, -709, -2428, -46, -2134, 628, -1453, +1209, -513, 1601, 515, 1700, 1433, 1479, 2072, +982, 2327, 313, 2166, -411, 1625, -1068, 805, +-1539, -137, -1730, -1030, -1613, -1717, -1211, -2086, +-594, -2086, 121, -1730, 825, -1091, 1368, -284, +1667, 548, 1685, 1259, 1434, 1740, 970, 1923, +358, 1782, -308, 1340, -916, 673, -1365, -85, +-1590, -801, -1562, -1367, -1297, -1700, -824, -1740, +-227, -1471, 405, -948, 974, -272, 1396, 433, +1596, 1044, 1536, 1457, 1228, 1603, 736, 1455, +156, 1047, -434, 465, -947, -174, -1316, -757, +-1467, -1185, -1367, -1386, -1037, -1323, -561, -1016, +-24, -541, 485, -1, 904, 509, 1165, 912, +1223, 1145, 1094, 1159, 792, 949, 392, 579, +-33, 136, -394, -306, -637, -679, -766, -920, +-795, -987, -714, -872, -537, -600, -308, -225, +-80, 167, 112, 498, 282, 727, 422, 825, +532, 764, 583, 554, 565, 251, 481, -75, +353, -368, 186, -587, -10, -690, -218, -651, +-421, -486, -582, -242, -684, 28, -691, 269, +-580, 448, -369, 541, -97, 529, 202, 411, +490, 219, 742, 8, 892, -174, 895, -304, +743, -377, 452, -376, 88, -295, -300, -155, +-649, -4, -908, 105, -1028, 156, -988, 161, +-790, 128, -472, 62, -70, -14, 354, -64, +738, -58, 1034, 10, 1188, 120, 1173, 232, +970, 303, 603, 306, 102, 226, -460, 54, +-995, -192, -1387, -448, -1561, -641, -1494, -726, +-1175, -676, -630, -477, 93, -135, 860, 294, +1504, 715, 1895, 1035, 1964, 1183, 1684, 1120, +1091, 837, 260, 358, -651, -249, -1480, -872, +-2077, -1374, -2315, -1646, -2140, -1630, -1565, -1315, +-700, -728, 291, 43, 1230, 865, 1978, 1578, +2406, 2044, 2429, 2169, 2008, 1911, 1219, 1295, +235, 401, -771, -620, -1661, -1580, -2316, -2301, +-2607, -2659, -2461, -2573, -1881, -2021, -973, -1061, +120, 141, 1204, 1367, 2086, 2398, 2614, 3046, +2700, 3179, 2327, 2740, 1539, 1767, 465, 418, +-693, -1047, -1730, -2345, -2472, -3239, -2775, -3572, +-2589, -3257, -1934, -2312, -948, -912, 190, 661, +1287, 2121, 2150, 3213, 2628, 3726, 2634, 3540, +2160, 2682, 1281, 1327, 170, -265, -975, -1811, +-1934, -3043, -2542, -3728, -2691, -3719, -2343, -3022, +-1549, -1775, -448, -197, 735, 1433, 1768, 2822, +2460, 3715, 2697, 3946, 2423, 3469, 1698, 2350, +640, 771, -546, -977, -1644, -2577, -2444, -3748, +-2756, -4266, -2526, -4009, -1831, -3000, -820, -1423, +338, 449, 1454, 2288, 2310, 3754, 2696, 4543, +2541, 4485, 1893, 3598, 899, 2046, -255, 93, +-1354, -1920, -2192, -3609, -2605, -4636, -2509, -4797, +-1921, -4070, -957, -2598, 177, -641, 1278, 1469, +2130, 3340, 2570, 4592, 2498, 4977, 1934, 4449, +991, 3114, -158, 1194, -1307, -985, -2227, -3020, +-2718, -4495, -2685, -5118, -2119, -4793, -1136, -3598, +91, -1735, 1317, 487, 2314, 2662, 2896, 4336, +2938, 5172, 2417, 5042, 1429, 4009, 149, 2254, +-1194, 64, -2344, -2161, -3075, -3971, -3231, -5001, +-2794, -5093, -1836, -4283, -513, -2732, 949, -689, +2266, 1484, 3174, 3352, 3485, 4541, 3148, 4877, +2226, 4365, 873, 3102, -665, 1274, -2121, -783, +-3202, -2646, -3679, -3961, -3443, -4518, -2555, -4252, +-1192, -3221, 390, -1608, 1921, 284, 3115, 2086, +3745, 3440, 3695, 4091, 2952, 3950, 1646, 3085, +9, 1663, -1632, -63, -2965, -1750, -3751, -3039, +-3865, -3674, -3271, -3589, -2067, -2854, -472, -1598, +1208, -33, 2657, 1521, 3619, 2713, 3917, 3326, +3508, 3314, 2467, 2710, 984, 1593, -669, 148, +-2176, -1308, -3266, -2453, -3750, -3090, -3564, -3145, +-2746, -2616, -1438, -1580, 111, -227, 1630, 1160, +2843, 2277, 3537, 2907, 3578, 2961, 2960, 2444, +1796, 1431, 329, 108, -1171, -1219, -2426, -2238, +-3205, -2750, -3379, -2693, -2912, -2090, -1921, -1043, +-604, 236, 798, 1441, 2047, 2289, 2894, 2614, +3165, 2382, 2815, 1662, 1966, 597, 814, -606, +-449, -1674, -1620, -2359, -2487, -2533, -2860, -2192, +-2681, -1420, -2011, -363, -998, 777, 174, 1761, +1292, 2381, 2162, 2524, 2618, 2188, 2579, 1447, +2058, 424, 1161, -703, 77, -1704, -977, -2354, +-1801, -2539, -2265, -2259, -2304, -1569, -1928, -572, +-1189, 554, -244, 1565, 722, 2247, 1503, 2482, +1961, 2247, 2034, 1587, 1716, 621, 1086, -468, +275, -1451, -546, -2114, -1228, -2332, -1639, -2099, +-1709, -1471, -1430, -553, -880, 483, -177, 1399, +534, 1988, 1106, 2158, 1428, 1924, 1453, 1344, +1197, 498, 706, -464, 83, -1324, -534, -1879, +-1006, -2040, -1265, -1836, -1273, -1320, -1023, -541, +-569, 377, -11, 1227, 537, 1810, 984, 2034, +1252, 1884, 1257, 1374, 979, 577, 498, -357, +-70, -1226, -605, -1831, -1037, -2036, -1285, -1824, +-1278, -1267, -997, -462, -491, 460, 115, 1290, +703, 1799, 1169, 1876, 1426, 1575, 1396, 997, +1083, 234, 559, -581, -62, -1255, -677, -1609, +-1189, -1584, -1493, -1237, -1514, -680, -1258, -23, +-788, 619, -182, 1109, 463, 1326, 1038, 1241, +1424, 913, 1554, 427, 1407, -129, 1018, -642, +482, -992, -101, -1095, -653, -940, -1103, -586, +-1368, -125, -1382, 349, -1168, 748, -802, 976, +-328, 956, 187, 687, 656, 252, 973, -243, +1107, -701, 1083, -1022, 925, -1111, 638, -926, +254, -512, -140, 38, -479, 619, -730, 1104, +-892, 1374, -938, 1350, -849, 1030, -625, 477, +-314, -199, 29, -871, 360, -1408, 646, -1688, +850, -1640, 917, -1260, 824, -612, 581, 181, +249, 962, -123, 1585, -482, 1926, -762, 1915, +-900, 1526, -875, 810, -706, -91, -447, -993, +-135, -1724, 202, -2136, 522, -2115, 770, -1648, +887, -842, 869, 133, 716, 1095, 438, 1848, +47, 2210, -388, 2091, -782, 1532, -1060, 666, +-1169, -325, -1070, -1243, -742, -1889, -249, -2128, +320, -1914, 860, -1301, 1269, -426, 1442, 522, +1325, 1353, 924, 1909, 326, 2058, -358, 1758, +-981, 1094, -1422, 220, -1611, -699, -1511, -1502, +-1132, -2020, -516, -2108, 213, -1720, 911, -951, +1453, 12, 1743, 972, 1706, 1764, 1329, 2223, +691, 2206, -67, 1680, -813, 782, -1429, -269, +-1809, -1279, -1877, -2060, -1590, -2428, -999, -2262, +-226, -1601, 572, -614, 1275, 492, 1781, 1515, +1987, 2251, 1818, 2535, 1293, 2299, 549, 1591, +-277, 570, -1070, -565, -1710, -1605, -2051, -2356, +-2011, -2663, -1599, -2456, -905, -1769, -39, -720, +849, 502, 1583, 1658, 2015, 2511, 2051, 2893, +1710, 2724, 1075, 2024, 274, 901, -568, -443, +-1333, -1739, -1877, -2711, -2053, -3149, -1818, -2960, +-1256, -2182, -489, -954, 370, 485, 1186, 1835, +1775, 2804, 1993, 3204, 1812, 2970, 1300, 2146, +545, 888, -324, -541, -1147, -1830, -1725, -2719, +-1916, -3049, -1700, -2769, -1163, -1941, -438, -737, +362, 605, 1101, 1802, 1611, 2588, 1743, 2820, +1498, 2492, 985, 1681, 337, 525, -368, -748, +-1021, -1845, -1470, -2530, -1609, -2697, -1419, -2324, +-961, -1461, -313, -268, 402, 994, 1031, 2044, +1438, 2662, 1566, 2732, 1405, 2252, 975, 1309, +339, 59, -368, -1255, -982, -2328, -1379, -2906, +-1502, -2882, -1335, -2284, -896, -1219, -279, 133, +374, 1501, 914, 2572, 1265, 3101, 1358, 2988, +1155, 2274, 700, 1091, 118, -335, -450, -1717, +-892, -2741, -1124, -3180, -1098, -2961, -811, -2144, +-342, -883, 207, 584, 703, 1936, 1036, 2868, +1113, 3192, 917, 2856, 518, 1935, 5, 613, +-518, -844, -936, -2134, -1155, -2987, -1147, -3219, +-915, -2785, -483, -1774, 96, -385, 696, 1099, +1176, 2351, 1442, 3103, 1454, 3230, 1194, 2727, +684, 1671, 6, 240, -724, -1260, -1354, -2474, +-1743, -3151, -1778, -3202, -1468, -2647, -881, -1561, +-104, -114, 742, 1371, 1485, 2519, 1941, 3100, +2010, 3085, 1697, 2499, 1066, 1390, 222, -53, +-667, -1470, -1417, -2513, -1882, -3010, -2006, -2927, +-1767, -2287, -1187, -1164, -358, 239, 548, 1596, +1337, 2566, 1853, 2954, 2005, 2757, 1796, 2061, +1261, 953, 487, -404, -387, -1696, -1174, -2578, +-1722, -2886, -1949, -2649, -1829, -1939, -1356, -833, +-614, 478, 247, 1674, 1067, 2466, 1694, 2748, +2020, 2537, 1956, 1881, 1513, 852, 773, -360, +-120, -1468, -996, -2233, -1678, -2551, -2035, -2414, +-2010, -1846, -1598, -922, -848, 181, 89, 1226, +986, 2002, 1660, 2373, 2005, 2286, 1980, 1770, +1551, 926, 798, -100, -90, -1107, -901, -1872, +-1522, -2241, -1893, -2162, -1912, -1666, -1512, -828, +-766, 185, 109, 1135, 903, 1811, 1512, 2111, +1866, 2006, 1862, 1509, 1444, 697, 697, -236, +-149, -1071, -901, -1665, -1464, -1947, -1771, -1864, +-1738, -1402, -1317, -678, -620, 111, 148, 821, +826, 1391, 1336, 1731, 1603, 1727, 1548, 1367, +1157, 790, 538, 144, -129, -500, -728, -1074, +-1206, -1460, -1492, -1554, -1462, -1351, -1085, -921, +-467, -372, 200, 202, 802, 730, 1266, 1132, +1496, 1319, 1395, 1248, 957, 971, 334, 584, +-312, 132, -875, -347, -1296, -776, -1493, -1051, +-1385, -1118, -973, -1008, -384, -778, 229, -453, +754, -48, 1159, 383, 1399, 751, 1371, 978, +1055, 1046, 549, 976, 4, 768, -518, 424, +-994, -13, -1329, -457, -1382, -840, -1132, -1093, +-696, -1160, -199, -1017, 317, -700, 797, -256, +1127, 267, 1201, 777, 1019, 1147, 685, 1281, +272, 1172, -172, 854, -622, 359, -965, -244, +-1082, -827, -958, -1239, -681, -1383, -350, -1253, +33, -887, 455, -333, 806, 334, 951, 979, +874, 1437, 666, 1580, 388, 1381, 32, 902, +-363, 237, -685, -518, -829, -1237, -793, -1738, +-659, -1855, -472, -1555, -216, -934, 106, -125, +402, 760, 569, 1559, 601, 2061, 586, 2101, +554, 1670, 434, 896, 188, -57, -82, -1029, +-273, -1839, -403, -2273, -538, -2189, -653, -1610, +-647, -706, -509, 323, -299, 1305, -83, 2055, +141, 2362, 380, 2112, 594, 1378, 720, 361, +708, -722, 569, -1668, 349, -2279, 85, -2394, +-216, -1955, -508, -1063, -702, 61, -723, 1173, +-614, 2062, -450, 2539, -250, 2456, -1, 1792, +259, 711, 440, -519, 505, -1652, 491, -2474, +441, -2784, 350, -2460, 213, -1563, 58, -314, +-88, 1003, -226, 2122, -362, 2806, -481, 2876, +-538, 2277, -519, 1146, -427, -239, -257, -1569, +-12, -2572, 279, -3023, 537, -2777, 722, -1862, +807, -512, 772, 942, 590, 2195, 262, 3004, +-152, 3157, -570, 2559, -915, 1340, -1126, -179, +-1136, -1659, -913, -2817, -497, -3401, 15, -3230, +531, -2305, 968, -863, 1271, 754, 1359, 2227, +1176, 3277, 747, 3651, 182, 3219, -395, 2079, +-908, 510, -1273, -1169, -1399, -2626, -1260, -3547, +-919, -3706, -439, -3069, 141, -1787, 739, -146, +1197, 1516, 1418, 2858, 1415, 3588, 1209, 3533, +774, 2714, 129, 1354, -549, -242, -1092, -1776, +-1445, -2948, -1612, -3459, -1518, -3178, -1094, -2228, +-428, -890, 298, 585, 964, 1957, 1520, 2915, +1867, 3198, 1860, 2765, 1443, 1793, 738, 518, +-63, -845, -821, -2053, -1479, -2814, -1932, -2920, +-2017, -2379, -1648, -1376, -927, -141, -79, 1099, +754, 2104, 1485, 2630, 1979, 2550, 2058, 1909, +1680, 883, 986, -286, 153, -1338, -701, -2062, +-1453, -2333, -1939, -2097, -2017, -1380, -1672, -360, +-992, 662, -104, 1433, 803, 1866, 1567, 1940, +2049, 1600, 2149, 878, 1796, 1, 1032, -754, +46, -1258, -934, -1507, -1752, -1487, -2283, -1163, +-2378, -591, -1941, 36, -1054, 522, 48, 823, +1156, 979, 2097, 991, 2679, 827, 2699, 533, +2119, 233, 1106, 6, -115, -185, -1352, -387, +-2412, -554, -3025, -634, -2978, -658, -2267, -679, +-1074, -649, 345, -469, 1738, -138, 2828, 238, +3341, 605, 3151, 977, 2280, 1272, 899, 1297, +-712, 972, -2208, 425, -3232, -219, -3558, -933, +-3109, -1598, -1978, -1920, -381, -1727, 1336, -1127, +2777, -292, 3613, 700, 3670, 1687, 2931, 2325, +1521, 2348, -258, 1796, -1988, 854, -3270, -339, +-3846, -1574, -3601, -2483, -2562, -2751, -906, -2349, +971, -1442, 2596, -196, 3622, 1182, 3887, 2326, +3340, 2866, 2022, 2701, 219, 1961, -1590, 802, +-2968, -602, -3689, -1908, -3649, -2690, -2801, -2760, +-1276, -2220, 502, -1219, 2048, 110, 3060, 1448, +3431, 2343, 3089, 2561, 2050, 2168, 582, 1310, +-930, 119, -2157, -1136, -2894, -2037, -2986, -2296, +-2419, -1930, -1363, -1118, -95, -38, 1117, 1072, +2030, 1865, 2455, 2059, 2342, 1639, 1776, 806, +888, -195, -172, -1130, -1152, -1757, -1788, -1855, +-1968, -1383, -1777, -526, -1297, 407, -550, 1160, +328, 1582, 1063, 1588, 1466, 1142, 1557, 352, +1412, -473, 1010, -1028, 365, -1208, -351, -1087, +-955, -736, -1377, -205, -1582, 331, -1476, 605, +-1014, 528, -297, 276, 489, 53, 1196, -80, +1728, -110, 1939, 43, 1698, 393, 1008, 756, +32, 877, -1014, 625, -1911, 45, -2439, -695, +-2410, -1379, -1777, -1810, -666, -1817, 660, -1274, +1879, -225, 2709, 1039, 2941, 2099, 2512, 2639, +1484, 2539, 55, 1794, -1467, 526, -2695, -979, +-3291, -2296, -3138, -3008, -2313, -2914, -992, -2105, +584, -835, 2072, 626, 3097, 1957, 3413, 2786, +3006, 2844, 1995, 2187, 570, 1114, -1008, -96, +-2374, -1236, -3205, -2064, -3375, -2351, -2912, -2064, +-1899, -1374, -473, -506, 1073, 376, 2382, 1138, +3177, 1641, 3386, 1775, 3019, 1532, 2063, 1019, +605, 379, -1053, -298, -2513, -946, -3480, -1419, +-3817, -1565, -3416, -1362, -2251, -906, -549, -281, +1290, 431, 2872, 1080, 3894, 1475, 4115, 1520, +3414, 1227, 1915, 661, -12, -62, -1903, -773, +-3350, -1287, -4052, -1497, -3841, -1382, -2765, -963, +-1112, -309, 699, 411, 2250, 1004, 3218, 1344, +3433, 1401, 2908, 1173, 1782, 674, 327, 5, +-1063, -622, -2049, -1045, -2482, -1253, -2387, -1250, +-1824, -984, -902, -452, 122, 176, 930, 697, +1362, 1045, 1449, 1226, 1249, 1179, 799, 835, +221, 256, -272, -382, -546, -906, -605, -1237, +-509, -1330, -269, -1115, 45, -570, 273, 167, +294, 859, 146, 1318, -56, 1472, -245, 1290, +-395, 754, -459, -28, -373, -811, -139, -1362, +159, -1544, 422, -1318, 586, -761, 611, -43, +479, 651, 217, 1171, -69, 1379, -282, 1197, +-389, 709, -411, 125, -377, -389, -276, -784, +-145, -1005, -65, -980, -55, -725, -53, -374, +16, -46, 177, 232, 392, 501, 620, 754, +790, 916, 801, 927, 580, 787, 117, 506, +-518, 47, -1180, -594, -1650, -1293, -1749, -1795, +-1407, -1873, -667, -1456, 339, -597, 1399, 566, +2212, 1768, 2522, 2660, 2219, 2917, 1374, 2359, +201, 1089, -1047, -542, -2128, -2088, -2790, -3143, +-2821, -3404, -2181, -2760, -1066, -1356, 250, 384, +1536, 1932, 2557, 2884, 3056, 3066, 2880, 2523, +2086, 1443, 840, 108, -645, -1127, -2070, -1927, +-3072, -2192, -3385, -2054, -2927, -1656, -1766, -1013, +-104, -159, 1660, 725, 3040, 1457, 3698, 1996, +3503, 2293, 2458, 2155, 729, 1417, -1231, 155, +-2837, -1293, -3687, -2523, -3653, -3215, -2775, -3150, +-1215, -2195, 667, -455, 2357, 1572, 3407, 3196, +3604, 3928, 2999, 3642, 1787, 2392, 222, 416, +-1371, -1736, -2619, -3359, -3204, -4012, -3037, -3644, +-2259, -2415, -1090, -604, 280, 1310, 1635, 2796, +2640, 3548, 3000, 3496, 2674, 2684, 1828, 1302, +647, -293, -701, -1761, -1945, -2870, -2736, -3425, +-2885, -3243, -2413, -2339, -1420, -955, -80, 628, +1319, 2154, 2418, 3290, 2957, 3705, 2838, 3274, +2087, 2114, 832, 494, -649, -1255, -1978, -2762, +-2858, -3674, -3111, -3777, -2656, -3061, -1548, -1689, +-35, 45, 1467, 1768, 2583, 3123, 3101, 3840, +2922, 3770, 2040, 2879, 624, 1314, -930, -573, +-2181, -2331, -2877, -3575, -2951, -4059, -2364, -3637, +-1184, -2341, 280, -495, 1606, 1393, 2493, 2901, +2834, 3741, 2601, 3724, 1777, 2843, 501, 1374, +-868, -273, -1975, -1751, -2630, -2815, -2759, -3275, +-2297, -3038, -1264, -2224, 94, -1045, 1411, 317, +2387, 1674, 2850, 2739, 2701, 3229, 1922, 3024, +645, 2201, -814, 879, -2036, -763, -2730, -2341, +-2814, -3346, -2292, -3459, -1235, -2719, 131, -1367, +1452, 317, 2403, 1952, 2824, 2994, 2644, 3105, +1879, 2397, 698, 1197, -627, -192, -1790, -1423, +-2548, -2139, -2752, -2167, -2361, -1616, -1467, -751, +-261, 161, 1017, 886, 2083, 1275, 2652, 1296, +2578, 993, 1936, 461, 892, -131, -362, -603, +-1549, -882, -2324, -968, -2485, -819, -2081, -403, +-1228, 147, -79, 622, 1079, 914, 1910, 1013, +2217, 858, 1982, 397, 1259, -221, 193, -723, +-909, -961, -1731, -940, -2093, -688, -1915, -245, +-1214, 276, -166, 662, 913, 761, 1685, 616, +1947, 354, 1669, 21, 932, -317, -84, -522, +-1074, -503, -1716, -320, -1817, -87, -1385, 165, +-581, 400, 348, 507, 1110, 424, 1473, 243, +1368, 10, 844, -295, 95, -591, -601, -707, +-1022, -565, -1068, -254, -773, 112, -258, 488, +309, 809, 728, 919, 855, 728, 673, 276, +261, -274, -258, -734, -713, -983, -960, -1005, +-903, -795, -529, -367, 18, 168, 574, 633, +1073, 906, 1415, 997, 1419, 968, 963, 808, +155, 461, -713, -32, -1449, -554, -1961, -994, +-2070, -1310, -1601, -1464, -619, -1326, 564, -788, +1615, 55, 2340, 918, 2578, 1579, 2154, 1929, +1136, 1855, -154, 1279, -1372, 353, -2244, -610, +-2570, -1365, -2263, -1779, -1401, -1760, -262, -1330, +852, -665, 1712, 43, 2108, 661, 1960, 1076, +1381, 1218, 546, 1154, -353, 980, -1117, 703, +-1569, 283, -1607, -227, -1272, -691, -711, -1041, +-29, -1259, 633, -1263, 1079, -960, 1198, -408, +1009, 239, 636, 837, 184, 1258, -314, 1374, +-735, 1138, -903, 651, -777, 95, -484, -384, +-196, -721, 60, -873, 325, -826, 489, -613, +400, -347, 151, -131, -35, 12, -85, 125, +-118, 229, -198, 310, -148, 353, 109, 369, +294, 391, 222, 371, 92, 248, 79, 80, +47, -26, -179, -85, -422, -182, -416, -333, +-233, -430, -75, -432, 57, -429, 230, -423, +368, -297, 350, -18, 185, 301, -1, 563, +-132, 726, -216, 749, -223, 581, -93, 253, +149, -125, 390, -444, 499, -618, 463, -590, +306, -401, -16, -154, -432, 100, -741, 279, +-825, 271, -727, 72, -499, -164, -97, -313, +461, -334, 934, -212, 1110, 84, 1050, 481, +844, 788, 424, 875, -191, 741, -749, 389, +-1044, -181, -1099, -796, -968, -1212, -593, -1297, +-23, -1067, 519, -582, 851, 71, 930, 741, +779, 1223, 431, 1348, -11, 1104, -392, 618, +-600, 54, -589, -477, -359, -869, -42, -995, +197, -813, 297, -481, 277, -158, 128, 124, +-134, 344, -372, 470, -401, 491, -211, 432, +17, 345, 190, 259, 340, 129, 436, -64, +354, -346, 73, -665, -225, -832, -361, -746, +-343, -489, -255, -95, -143, 465, -2, 1052, +163, 1410, 228, 1328, 111, 853, -59, 188, +-101, -552, -13, -1292, 72, -1785, 66, -1757, +54, -1208, 117, -414, 135, 379, -2, 1135, +-166, 1750, -181, 1914, -63, 1509, 31, 792, +52, 24, 127, -725, 233, -1389, 209, -1760, +53, -1673, -101, -1209, -162, -547, -163, 220, +-161, 971, -119, 1478, 16, 1640, 183, 1498, +301, 1051, 336, 320, 311, -480, 256, -1123, +121, -1522, -113, -1641, -349, -1424, -539, -867, +-646, -120, -568, 623, -275, 1235, 185, 1625, +682, 1684, 1019, 1399, 1095, 815, 911, 22, +461, -787, -207, -1406, -912, -1736, -1395, -1744, +-1487, -1407, -1214, -748, -646, 125, 137, 947, +921, 1523, 1458, 1814, 1652, 1775, 1455, 1343, +882, 611, 95, -237, -679, -1015, -1288, -1570, +-1664, -1841, -1687, -1764, -1267, -1310, -551, -565, +200, 295, 887, 1069, 1436, 1595, 1687, 1843, +1484, 1770, 843, 1289, 8, 487, -737, -387, +-1262, -1133, -1483, -1653, -1299, -1859, -779, -1667, +-112, -1094, 497, -314, 907, 505, 1032, 1238, +833, 1725, 387, 1810, -96, 1485, -423, 851, +-544, 28, -495, -834, -323, -1518, -65, -1823, +175, -1726, 271, -1265, 228, -445, 148, 571, +41, 1413, -93, 1842, -163, 1868, -99, 1505, +32, 730, 122, -287, 167, -1200, 200, -1749, +173, -1858, 48, -1577, -108, -977, -249, -160, +-350, 680, -350, 1278, -204, 1506, 52, 1432, +362, 1171, 645, 768, 779, 224, 669, -367, +293, -857, -226, -1164, -723, -1316, -1084, -1326, +-1185, -1122, -921, -630, -316, 59, 480, 773, +1203, 1371, 1575, 1706, 1511, 1688, 1064, 1307, +296, 571, -629, -381, -1398, -1210, -1751, -1708, +-1636, -1860, -1162, -1653, -407, -1037, 495, -121, +1253, 785, 1637, 1435, 1601, 1789, 1213, 1820, +575, 1436, -209, 720, -976, -134, -1475, -950, +-1610, -1600, -1456, -1957, -1041, -1878, -361, -1308, +468, -435, 1185, 498, 1554, 1341, 1567, 1922, +1317, 2068, 794, 1702, 54, 896, -724, -95, +-1341, -988, -1636, -1653, -1587, -1960, -1278, -1781, +-726, -1155, 5, -318, 736, 470, 1310, 1109, +1616, 1574, 1606, 1707, 1287, 1369, 689, 734, +-99, 60, -881, -560, -1440, -1092, -1638, -1419, +-1509, -1413, -1123, -1061, -446, -489, 390, 128, +1082, 677, 1436, 1071, 1433, 1207, 1134, 1018, +642, 591, 48, 110, -498, -290, -863, -592, +-1005, -760, -910, -718, -635, -489, -288, -194, +95, 62, 475, 232, 734, 300, 828, 319, +754, 295, 511, 222, 153, 122, -255, -4, +-644, -116, -875, -147, -837, -177, -534, -254, +-89, -226, 339, -83, 678, 35, 877, 98, +869, 190, 612, 322, 163, 379, -296, 241, +-585, 16, -702, -128, -686, -221, -492, -334, +-196, -442, 9, -447, 71, -278, 135, -22, +280, 176, 388, 333, 352, 440, 275, 465, +252, 446, 231, 364, 121, 174, -108, -48, +-368, -244, -508, -418, -489, -540, -432, -637, +-368, -658, -200, -486, 54, -148, 208, 218, +208, 565, 243, 873, 422, 1036, 512, 912, +301, 491, 36, -38, 12, -504, 42, -848, +-189, -1019, -517, -929, -595, -582, -433, -90, +-293, 365, -214, 620, -35, 639, 235, 509, +418, 319, 446, 87, 418, -141, 420, -267, +423, -222, 288, -100, -1, -37, -319, -1, +-525, 98, -589, 165, -603, 130, -564, 88, +-319, 62, 143, -31, 599, -228, 859, -441, +876, -538, 715, -484, 405, -335, -46, -42, +-485, 380, -731, 769, -754, 989, -568, 955, +-264, 652, 12, 201, 269, -289, 502, -763, +572, -1072, 439, -1091, 255, -833, 158, -455, +114, -110, -21, 238, -184, 645, -240, 941, +-268, 993, -362, 876, -449, 676, -398, 380, +-187, -107, 59, -730, 241, -1232, 404, -1411, +521, -1238, 550, -727, 513, 10, 352, 792, +67, 1427, -218, 1671, -448, 1374, -640, 625, +-771, -282, -782, -1043, -593, -1464, -256, -1464, +126, -976, 567, -101, 979, 779, 1108, 1245, +872, 1187, 399, 791, -123, 191, -583, -550, +-976, -1149, -1165, -1243, -988, -813, -507, -107, +83, 622, 603, 1182, 888, 1382, 889, 1098, +658, 409, 308, -410, -23, -1092, -298, -1487, +-466, -1468, -467, -980, -372, -145, -278, 731, +-191, 1375, -153, 1614, -152, 1353, -111, 677, +24, -153, 282, -901, 566, -1388, 733, -1433, +778, -1015, 670, -280, 339, 519, -90, 1085, +-510, 1206, -934, 886, -1261, 289, -1221, -359, +-729, -861, -57, -1028, 515, -759, 1016, -162, +1465, 534, 1594, 1043, 1249, 1137, 573, 818, +-229, 229, -1034, -519, -1703, -1187, -1993, -1473, +-1688, -1260, -856, -651, 187, 108, 1142, 807, +1844, 1362, 2209, 1632, 2051, 1406, 1240, 737, +7, -100, -1163, -825, -1954, -1351, -2238, -1659, +-1981, -1581, -1247, -1001, -221, -138, 792, 717, +1529, 1418, 1861, 1823, 1718, 1797, 1095, 1248, +217, 285, -573, -757, -1067, -1561, -1247, -1969, +-1144, -1844, -776, -1177, -241, -178, 245, 854, +528, 1602, 608, 1834, 518, 1492, 313, 715, +84, -210, -71, -972, -112, -1368, -54, -1272, +24, -729, 41, 14, -49, 684, -250, 1095, +-494, 1076, -670, 567, -673, -187, -447, -831, +17, -1180, 629, -1179, 1156, -771, 1344, -19, +1188, 832, 762, 1438, 27, 1538, -861, 1127, +-1505, 390, -1686, -467, -1470, -1214, -918, -1598, +-91, -1467, 794, -808, 1400, 138, 1561, 1003, +1365, 1500, 907, 1490, 254, 1005, -408, 177, +-871, -786, -1028, -1504, -911, -1648, -690, -1259, +-432, -511, -109, 397, 213, 1187, 430, 1646, +573, 1652, 705, 1130, 766, 298, 656, -466, +407, -1023, 114, -1363, -251, -1419, -688, -1154, +-1041, -671, -1130, -148, -900, 354, -427, 861, +151, 1241, 761, 1373, 1259, 1288, 1411, 1002, +1170, 472, 638, -289, -117, -1105, -931, -1672, +-1492, -1811, -1590, -1567, -1240, -959, -602, -69, +194, 835, 970, 1465, 1455, 1712, 1515, 1565, +1220, 1073, 625, 399, -197, -246, -969, -709, +-1384, -958, -1357, -1007, -1047, -933, -608, -790, +-92, -606, 402, -384, 732, -65, 873, 374, +869, 821, 747, 1139, 527, 1269, 242, 1159, +-33, 783, -286, 144, -554, -618, -826, -1249, +-1016, -1541, -1008, -1432, -705, -990, -190, -384, +333, 267, 766, 879, 1085, 1262, 1209, 1305, +1033, 1075, 592, 695, 52, 222, -424, -305, +-780, -806, -961, -1120, -914, -1190, -700, -1055, +-447, -713, -183, -189, 88, 431, 302, 1026, +502, 1385, 744, 1330, 929, 923, 918, 321, +776, -313, 579, -876, 204, -1265, -434, -1323, +-1091, -978, -1457, -386, -1500, 220, -1300, 706, +-832, 1019, -62, 1128, 826, 986, 1519, 644, +1858, 199, 1884, -273, 1551, -712, 758, -1071, +-320, -1288, -1273, -1231, -1839, -865, -2041, -310, +-1905, 353, -1306, 1044, -284, 1603, 799, 1842, +1633, 1655, 2088, 1048, 2084, 166, 1599, -780, +711, -1557, -381, -2022, -1347, -2110, -1946, -1731, +-2100, -935, -1792, 39, -1087, 962, -102, 1699, +932, 2116, 1661, 2118, 1872, 1669, 1662, 892, +1180, -5, 482, -901, -372, -1648, -1135, -2035, +-1503, -2008, -1463, -1634, -1159, -941, -627, -51, +50, 800, 624, 1420, 908, 1774, 901, 1848, +748, 1582, 510, 994, 149, 243, -214, -491, +-412, -1111, -443, -1556, -379, -1764, -297, -1630, +-227, -1146, -113, -450, -11, 285, 42, 950, +137, 1455, 297, 1696, 443, 1563, 512, 1075, +475, 433, 322, -191, 42, -731, -343, -1161, +-699, -1374, -928, -1289, -959, -984, -695, -589, +-184, -133, 376, 335, 850, 759, 1158, 1114, +1243, 1283, 1063, 1192, 605, 918, 3, 513, +-597, -19, -1101, -599, -1368, -1129, -1304, -1448, +-964, -1458, -431, -1223, 184, -814, 764, -227, +1207, 483, 1385, 1170, 1283, 1658, 975, 1840, +461, 1733, -215, 1292, -832, 488, -1242, -543, +-1400, -1541, -1322, -2251, -1027, -2495, -511, -2217, +154, -1400, 792, -130, 1231, 1244, 1425, 2301, +1420, 2759, 1174, 2560, 587, 1766, -164, 543, +-794, -805, -1252, -1865, -1560, -2348, -1584, -2207, +-1186, -1561, -460, -623, 299, 346, 891, 1072, +1313, 1399, 1496, 1341, 1310, 1020, 767, 581, +93, 177, -474, -119, -888, -297, -1177, -384, +-1207, -425, -885, -459, -379, -554, 94, -681, +447, -675, 693, -467, 835, -166, 808, 191, +579, 600, 254, 952, -23, 1126, -224, 1067, +-421, 779, -573, 335, -539, -169, -359, -642, +-192, -1004, -93, -1194, -34, -1134, 11, -859, +55, -489, 80, -58, 123, 406, 222, 786, +373, 992, 539, 997, 638, 840, 596, 616, +400, 333, 68, -8, -376, -310, -824, -514, +-1106, -664, -1080, -757, -797, -775, -402, -714, +56, -555, 558, -282, 962, 63, 1086, 410, +927, 753, 641, 1034, 302, 1112, -126, 939, +-496, 612, -588, 172, -462, -329, -353, -775, +-325, -1082, -264, -1198, -129, -1082, -55, -753, +-101, -318, -103, 134, 38, 570, 241, 952, +405, 1151, 511, 1120, 586, 932, 579, 630, +355, 200, -55, -318, -457, -790, -726, -1064, +-838, -1154, -808, -1141, -617, -947, -253, -537, +207, -27, 611, 475, 817, 914, 783, 1221, +632, 1359, 435, 1288, 122, 968, -243, 423, +-499, -260, -607, -896, -631, -1346, -593, -1579, +-448, -1537, -165, -1137, 150, -457, 370, 291, +479, 904, 518, 1296, 502, 1455, 384, 1330, +131, 914, -155, 357, -341, -150, -405, -557, +-369, -884, -261, -1085, -82, -1070, 142, -894, +273, -659, 211, -314, 66, 201, -6, 746, +-36, 1113, -133, 1259, -222, 1203, -149, 876, +4, 235, 71, -511, 92, -1090, 166, -1376, +253, -1344, 279, -976, 227, -307, 135, 465, +47, 1025, -73, 1222, -253, 1110, -427, 710, +-489, 106, -427, -472, -315, -846, -171, -958, +84, -787, 380, -402, 533, 70, 531, 463, +492, 656, 440, 697, 329, 627, 195, 405, +77, 66, -103, -240, -419, -436, -768, -568, +-1030, -710, -1167, -756, -1131, -585, -822, -307, +-178, -23, 703, 338, 1581, 785, 2229, 1154, +2450, 1290, 2071, 1147, 1131, 784, -141, 217, +-1504, -522, -2695, -1257, -3371, -1775, -3275, -1962, +-2425, -1762, -1028, -1154, 683, -232, 2388, 806, +3600, 1725, 3974, 2334, 3477, 2473, 2259, 2089, +536, 1254, -1351, 128, -2985, -1075, -3953, -2086, +-4007, -2644, -3152, -2605, -1627, -2022, 208, -1077, +1958, 98, 3203, 1295, 3662, 2173, 3309, 2483, +2269, 2256, 743, 1630, -869, 696, -2133, -420, +-2816, -1397, -2856, -1922, -2259, -1952, -1172, -1596, +71, -958, 1143, -138, 1870, 686, 2177, 1277, +1977, 1452, 1272, 1252, 294, 797, -603, 198, +-1215, -383, -1537, -815, -1541, -1026, -1156, -949, +-462, -599, 274, -119, 841, 361, 1197, 726, +1322, 890, 1120, 838, 619, 609, 29, 225, +-485, -271, -901, -725, -1192, -955, -1240, -966, +-969, -849, -464, -541, 102, -36, 652, 490, +1122, 847, 1379, 998, 1323, 991, 961, 838, +366, 494, -336, 30, -982, -383, -1422, -650, +-1536, -775, -1265, -806, -661, -752, 39, -602, +628, -364, 1075, -98, 1345, 142, 1274, 349, +845, 586, 285, 826, -188, 929, -563, 868, +-866, 704, -948, 407, -753, -56, -473, -552, +-233, -931, 53, -1142, 370, -1200, 519, -1038, +432, -621, 289, -112, 211, 326, 119, 683, +-40, 943, -151, 1031, -109, 953, 30, 777, +160, 576, 231, 352, 227, 85, 118, -225, +-69, -571, -270, -924, -463, -1212, -602, -1365, +-614, -1342, -496, -1073, -303, -498, -42, 324, +292, 1149, 631, 1765, 842, 2117, 928, 2121, +973, 1643, 906, 763, 594, -267, 85, -1242, +-480, -1997, -1053, -2346, -1562, -2198, -1817, -1660, +-1648, -861, -1129, 95, -423, 998, 435, 1600, +1418, 1862, 2267, 1843, 2619, 1548, 2322, 991, +1537, 289, 488, -336, -731, -779, -1937, -1142, +-2797, -1437, -3051, -1477, -2624, -1253, -1625, -919, +-278, -506, 1212, 43, 2534, 672, 3262, 1221, +3171, 1572, 2364, 1670, 1094, 1454, -401, 910, +-1858, 153, -2876, -669, -3099, -1357, -2557, -1711, +-1507, -1664, -194, -1265, 1114, -585, 2096, 210, +2474, 906, 2176, 1331, 1405, 1366, 443, 1034, +-508, 490, -1255, -102, -1615, -621, -1506, -943, +-1051, -988, -475, -748, 81, -299, 554, 229, +851, 686, 917, 967, 762, 1030, 454, 832, +169, 375, 7, -243, -140, -841, -368, -1264, +-589, -1423, -669, -1291, -629, -851, -572, -144, +-455, 653, -147, 1284, 315, 1567, 767, 1526, +1091, 1269, 1255, 803, 1212, 134, 881, -510, +234, -909, -574, -1076, -1261, -1158, -1652, -1188, +-1747, -1052, -1567, -736, -1052, -399, -218, -92, +723, 317, 1484, 839, 1909, 1299, 2009, 1503, +1814, 1455, 1254, 1273, 374, 927, -578, 316, +-1392, -423, -1983, -1048, -2246, -1485, -2057, -1758, +-1462, -1836, -620, -1613, 331, -1082, 1271, -390, +1981, 359, 2265, 1167, 2109, 1882, 1595, 2244, +817, 2178, -101, 1785, -997, 1133, -1671, 219, +-1972, -796, -1918, -1618, -1618, -2101, -1121, -2278, +-414, -2139, 394, -1659, 1060, -910, 1454, -37, +1644, 845, 1670, 1631, 1465, 2199, 986, 2460, +319, 2346, -348, 1798, -893, 851, -1331, -271, +-1627, -1324, -1658, -2164, -1417, -2678, -1005, -2676, +-461, -2084, 201, -1127, 877, -97, 1419, 897, +1730, 1751, 1747, 2255, 1474, 2322, 1000, 2016, +393, 1453, -357, 718, -1158, -130, -1728, -995, +-1877, -1716, -1703, -2140, -1320, -2167, -680, -1810, +167, -1150, 943, -240, 1446, 779, 1701, 1625, +1718, 2054, 1385, 2025, 685, 1606, -135, 863, +-801, -81, -1253, -941, -1503, -1468, -1471, -1636, +-1088, -1465, -461, -957, 197, -249, 748, 462, +1126, 1055, 1237, 1392, 1066, 1346, 704, 948, +235, 381, -260, -248, -664, -914, -885, -1444, +-895, -1585, -754, -1283, -529, -701, -205, 5, +193, 741, 521, 1383, 683, 1727, 730, 1667, +738, 1285, 649, 707, 337, 9, -89, -692, +-371, -1263, -535, -1631, -756, -1741, -946, -1595, +-900, -1230, -622, -670, -251, 76, 155, 894, +606, 1587, 1011, 2024, 1223, 2154, 1217, 1894, +999, 1220, 543, 313, -87, -622, -749, -1463, +-1279, -2062, -1543, -2228, -1496, -1934, -1128, -1353, +-496, -653, 211, 133, 806, 921, 1210, 1498, +1380, 1746, 1291, 1733, 952, 1528, 431, 1077, +-118, 383, -570, -365, -876, -961, -1001, -1358, +-936, -1513, -699, -1352, -328, -899, 53, -297, +335, 285, 533, 692, 605, 802, 462, 629, +177, 322, -90, 11, -285, -260, -358, -365, +-223, -181, 116, 213, 465, 608, 636, 879, +645, 965, 534, 818, 217, 392, -307, -255, +-824, -903, -1121, -1398, -1135, -1694, -924, -1736, +-546, -1429, -65, -788, 394, 39, 753, 879, +1023, 1619, 1176, 2157, 1154, 2357, 984, 2150, +702, 1540, 283, 635, -266, -374, -821, -1348, +-1268, -2195, -1604, -2703, -1763, -2703, -1519, -2261, +-826, -1513, 36, -478, 842, 772, 1531, 1960, +1966, 2773, 1950, 3062, 1480, 2856, 736, 2172, +-95, 1020, -863, -430, -1403, -1781, -1564, -2667, +-1311, -2971, -764, -2698, -123, -1883, 411, -683, +716, 567, 765, 1519, 541, 1966, 71, 1901, +-486, 1434, -850, 739, -844, 4, -487, -561, +115, -767, 847, -600, 1516, -258, 1848, 61, +1665, 272, 1011, 331, 45, 202, -1069, -124, +-2060, -536, -2587, -829, -2492, -903, -1853, -795, +-830, -497, 360, -27, 1433, 470, 2164, 873, +2454, 1133, 2265, 1208, 1619, 1032, 706, 646, +-195, 192, -923, -252, -1411, -686, -1625, -962, +-1596, -948, -1371, -769, -968, -587, -438, -392, +125, -164, 590, -1, 893, 53, 1088, 88, +1169, 200, 1047, 377, 746, 632, 385, 966, +13, 1186, -381, 1084, -731, 706, -859, 199, +-718, -423, -503, -1119, -326, -1645, -89, -1766, +172, -1500, 293, -973, 244, -268, 122, 477, +-5, 1033, -134, 1301, -190, 1343, -56, 1189, +199, 866, 403, 501, 536, 205, 637, -66, +639, -329, 449, -524, 86, -667, -319, -861, +-675, -1074, -981, -1148, -1153, -981, -1077, -631, +-807, -207, -425, 296, 83, 875, 680, 1397, +1216, 1669, 1517, 1599, 1510, 1235, 1227, 682, +683, -9, -63, -740, -805, -1311, -1344, -1557, +-1562, -1477, -1400, -1176, -932, -717, -329, -139, +286, 389, 768, 648, 935, 655, 751, 564, +363, 466, -15, 375, -248, 320, -319, 354, +-208, 482, 107, 593, 510, 559, 794, 348, +791, -15, 498, -478, 42, -953, -466, -1310, +-960, -1464, -1323, -1385, -1437, -1045, -1242, -452, +-738, 260, -37, 944, 666, 1543, 1254, 1967, +1665, 2044, 1792, 1671, 1558, 941, 990, 58, +206, -836, -650, -1649, -1420, -2188, -1867, -2226, +-1836, -1735, -1408, -909, -712, 13, 124, 862, +869, 1460, 1324, 1667, 1429, 1498, 1192, 1078, +673, 515, 20, -49, -539, -452, -797, -628, +-750, -633, -551, -570, -272, -486, 72, -386, +372, -306, 483, -275, 397, -218, 259, -48, +157, 183, 26, 343, -144, 439, -262, 545, +-327, 586, -414, 446, -508, 182, -519, -65, +-376, -238, -89, -321, 247, -321, 568, -267, +845, -192, 1019, -94, 978, -6, 668, -4, +190, -110, -313, -244, -789, -331, -1176, -344, +-1318, -241, -1129, -2, -705, 351, -212, 744, +232, 1042, 628, 1150, 1000, 1052, 1199, 711, +1041, 101, 629, -685, 233, -1422, -84, -1873, +-428, -1965, -729, -1727, -773, -1127, -575, -154, +-366, 961, -216, 1863, 7, 2373, 262, 2499, +329, 2165, 180, 1273, 24, 64, -17, -1034, +-44, -1858, -126, -2395, -125, -2471, 30, -1980, +171, -1103, 229, -128, 337, 766, 472, 1450, +458, 1804, 294, 1792, 120, 1472, -62, 957, +-350, 371, -677, -195, -886, -691, -965, -1018, +-937, -1109, -694, -1020, -215, -864, 339, -637, +851, -282, 1291, 130, 1594, 431, 1608, 568, +1245, 639, 655, 661, 24, 554, -668, 343, +-1393, 185, -1899, 86, -1978, -76, -1695, -262, +-1247, -331, -668, -355, 149, -440, 1075, -487, +1766, -399, 2063, -213, 2045, 26, 1819, 299, +1342, 514, 518, 572, -492, 482, -1307, 311, +-1811, 57, -2122, -265, -2163, -515, -1726, -557, +-889, -378, -24, -72, 676, 239, 1302, 461, +1785, 556, 1830, 461, 1426, 175, 878, -215, +369, -585, -113, -797, -545, -746, -806, -463, +-833, -56, -734, 407, -642, 821, -560, 1003, +-478, 858, -401, 516, -297, 119, -137, -306, +80, -697, 359, -874, 661, -773, 878, -526, +911, -255, 754, 1, 528, 202, 280, 284, +-63, 282, -422, 288, -603, 321, -628, 341, +-633, 371, -604, 428, -470, 428, -261, 254, +-105, -54, -39, -368, 39, -667, 186, -914, +340, -971, 462, -788, 535, -442, 556, 26, +538, 544, 471, 925, 356, 1062, 183, 1027, +-116, 839, -499, 402, -800, -190, -948, -628, +-963, -804, -835, -863, -522, -804, -37, -514, +498, -67, 920, 297, 1129, 479, 1089, 533, +813, 461, 371, 226, -151, -61, -612, -233, +-831, -283, -756, -255, -489, -117, -144, 134, +179, 351, 418, 416, 513, 364, 360, 243, +-10, 15, -361, -285, -522, -516, -533, -603, +-462, -571, -238, -467, 199, -276, 645, 14, +815, 339, 707, 585, 517, 705, 296, 721, +-28, 658, -407, 494, -638, 205, -618, -163, +-480, -519, -362, -787, -205, -935, 38, -943, +232, -799, 271, -476, 241, -22, 231, 449, +209, 853, 139, 1136, 52, 1207, -23, 994, +-88, 557, -117, 36, -93, -479, -82, -934, +-69, -1185, 50, -1129, 194, -819, 183, -368, +63, 142, 10, 586, 21, 809, -61, 793, +-236, 635, -312, 376, -254, 39, -252, -243, +-313, -348, -234, -313, -7, -235, 203, -121, +370, 20, 597, 93, 843, 32, 887, -81, +658, -137, 302, -160, -155, -197, -719, -188, +-1180, -62, -1343, 143, -1222, 336, -882, 467, +-364, 537, 262, 511, 836, 343, 1179, 35, +1252, -355, 1103, -708, 789, -922, 407, -961, +30, -780, -299, -333, -504, 265, -588, 802, +-639, 1135, -666, 1216, -627, 1029, -525, 592, +-416, 5, -362, -567, -285, -970, -45, -1126, +301, -1024, 582, -730, 790, -332, 1002, 72, +1186, 391, 1183, 605, 898, 744, 406, 780, +-167, 673, -755, 493, -1296, 302, -1692, 66, +-1817, -249, -1565, -555, -1012, -771, -365, -874, +284, -840, 931, -651, 1456, -343, 1713, 28, +1702, 428, 1515, 790, 1167, 1016, 621, 1049, +-49, 902, -671, 607, -1164, 182, -1547, -326, +-1780, -792, -1766, -1100, -1442, -1194, -843, -1051, +-134, -675, 520, -138, 1070, 401, 1487, 813, +1687, 1022, 1593, 967, 1249, 680, 816, 308, +353, -70, -204, -405, -781, -549, -1178, -444, +-1358, -241, -1394, -66, -1282, 78, -956, 155, +-431, 98, 137, -66, 642, -212, 1062, -297, +1284, -325, 1215, -247, 941, -54, 539, 173, +28, 354, -454, 455, -739, 480, -802, 448, +-714, 333, -504, 131, -164, -81, 211, -228, +454, -319, 519, -384, 419, -410, 165, -366, +-147, -263, -403, -172, -552, -136, -565, -107, +-444, -3, -216, 133, 83, 219, 372, 297, +585, 454, 697, 613, 685, 643, 572, 545, +432, 376, 282, 152, 70, -154, -234, -523, +-584, -859, -884, -1050, -1096, -1074, -1186, -995, +-1054, -809, -672, -401, -153, 200, 441, 792, +1087, 1258, 1594, 1610, 1743, 1777, 1522, 1606, +1070, 1054, 472, 230, -235, -651, -920, -1436, +-1383, -2031, -1581, -2287, -1591, -2046, -1377, -1347, +-880, -438, -247, 471, 310, 1318, 759, 1956, +1156, 2147, 1420, 1864, 1403, 1298, 1136, 617, +755, -122, 282, -822, -250, -1317, -665, -1486, +-874, -1392, -959, -1153, -960, -790, -820, -324, +-534, 132, -221, 467, 22, 699, 211, 855, +361, 900, 436, 827, 464, 678, 469, 460, +432, 202, 371, -62, 294, -347, 199, -612, +123, -755, 70, -744, -12, -640, -145, -440, +-312, -130, -444, 201, -500, 401, -540, 442, +-581, 356, -539, 138, -380, -142, -154, -331, +82, -345, 308, -175, 548, 177, 765, 623, +895, 1000, 973, 1142, 978, 977, 786, 543, +376, -102, -135, -871, -670, -1538, -1192, -1853, +-1608, -1759, -1772, -1366, -1614, -753, -1182, 52, +-491, 891, 404, 1506, 1265, 1784, 1844, 1795, +2096, 1585, 2066, 1162, 1730, 582, 1032, -43, +88, -624, -814, -1114, -1515, -1462, -1999, -1632, +-2155, -1607, -1892, -1375, -1325, -937, -610, -374, +198, 222, 1003, 803, 1583, 1330, 1776, 1685, +1656, 1728, 1349, 1476, 846, 1045, 188, 467, +-418, -235, -821, -879, -1049, -1285, -1154, -1416, +-1098, -1293, -833, -913, -450, -373, -121, 94, +140, 356, 444, 452, 752, 382, 887, 143, +804, -99, 615, -167, 383, -28, 71, 262, +-298, 626, -596, 941, -727, 1060, -695, 893, +-528, 485, -247, -52, 93, -608, 409, -1054, +597, -1290, 598, -1278, 449, -1057, 234, -720, +-2, -361, -244, -14, -443, 308, -493, 603, +-368, 861, -197, 1060, -68, 1198, 46, 1232, +142, 1068, 188, 696, 192, 199, 173, -361, +139, -922, 96, -1359, 69, -1545, 81, -1477, +85, -1220, 22, -797, -58, -267, -90, 248, +-100, 683, -111, 1044, -96, 1291, -66, 1360, +-82, 1245, -192, 1000, -350, 640, -423, 150, +-350, -410, -184, -912, 45, -1248, 372, -1353, +791, -1223, 1128, -896, 1151, -407, 852, 145, +404, 594, -130, 844, -770, 874, -1372, 692, +-1680, 361, -1571, -12, -1129, -315, -511, -454, +171, -372, 834, -102, 1376, 233, 1677, 536, +1633, 769, 1287, 849, 792, 638, 199, 161, +-488, -396, -1107, -898, -1451, -1307, -1494, -1552, +-1334, -1506, -1010, -1115, -467, -491, 229, 218, +831, 944, 1170, 1595, 1261, 2009, 1140, 2063, +819, 1770, 357, 1195, -146, 403, -558, -477, +-787, -1288, -824, -1917, -682, -2241, -403, -2158, +-74, -1728, 203, -1079, 364, -292, 437, 539, +463, 1261, 370, 1739, 109, 1934, -194, 1860, +-394, 1527, -485, 980, -530, 334, -500, -305, +-304, -867, 47, -1289, 425, -1504, 744, -1465, +979, -1197, 1062, -804, 886, -350, 412, 124, +-235, 509, -826, 713, -1262, 753, -1562, 687, +-1606, 555, -1217, 392, -441, 258, 421, 198, +1098, 214, 1547, 261, 1780, 264, 1648, 175, +1086, 9, 338, -208, -324, -482, -840, -780, +-1216, -999, -1373, -1053, -1229, -918, -886, -637, +-547, -252, -254, 218, 61, 716, 383, 1138, +648, 1374, 842, 1392, 960, 1213, 985, 847, +903, 324, 707, -247, 382, -770, -76, -1172, +-570, -1379, -955, -1377, -1171, -1188, -1213, -807, +-1066, -296, -750, 195, -341, 589, 105, 911, +539, 1141, 893, 1178, 1086, 1002, 1103, 706, +991, 351, 766, -33, 435, -395, 72, -688, +-274, -868, -617, -887, -899, -770, -1009, -581, +-946, -338, -803, -49, -610, 229, -303, 417, +106, 519, 468, 611, 698, 663, 842, 556, +894, 308, 794, 59, 592, -141, 362, -355, +100, -557, -181, -602, -416, -441, -562, -201, +-637, 31, -670, 258, -637, 417, -534, 406, +-418, 233, -285, -7, -70, -221, 223, -350, +506, -367, 717, -270, 850, -74, 899, 176, +819, 391, 587, 487, 234, 445, -195, 296, +-622, 94, -934, -114, -1078, -297, -1067, -426, +-893, -474, -563, -422, -123, -281, 318, -106, +642, 73, 826, 253, 915, 383, 884, 409, +692, 362, 407, 273, 138, 120, -88, -68, +-325, -209, -571, -272, -718, -275, -739, -239, +-710, -170, -614, -80, -374, -9, -33, 31, +330, 82, 669, 156, 884, 218, 884, 250, +686, 249, 369, 198, -24, 71, -443, -107, +-735, -284, -750, -416, -549, -435, -276, -299, +57, -81, 421, 123, 628, 302, 561, 411, +319, 361, 53, 161, -205, -64, -457, -213, +-587, -266, -520, -209, -319, -40, -49, 185, +248, 368, 474, 409, 581, 274, 597, 49, +505, -177, 271, -401, -69, -582, -375, -603, +-541, -430, -608, -168, -615, 63, -477, 236, +-179, 394, 162, 513, 443, 514, 595, 414, +596, 309, 478, 222, 260, 103, -13, -59, +-247, -216, -413, -330, -517, -416, -556, -495, +-511, -532, -331, -464, -42, -298, 236, -111, +477, 77, 717, 293, 869, 493, 817, 608, +553, 604, 144, 484, -365, 271, -924, 22, +-1338, -206, -1382, -367, -1078, -409, -595, -317, +6, -134, 678, 48, 1247, 172, 1507, 205, +1406, 94, 1055, -148, 556, -413, -32, -577, +-583, -583, -965, -433, -1146, -139, -1141, 268, +-980, 655, -687, 886, -251, 949, 253, 853, +647, 576, 833, 172, 852, -233, 758, -551, +517, -751, 121, -826, -274, -781, -459, -632, +-402, -397, -214, -111, 40, 141, 301, 302, +440, 373, 351, 374, 61, 323, -315, 254, +-637, 196, -811, 189, -781, 256, -533, 358, +-134, 427, 297, 412, 633, 274, 765, 23, +694, -297, 523, -635, 333, -896, 153, -987, +14, -921, -51, -754, -46, -487, -31, -121, +-101, 256, -278, 548, -481, 764, -627, 950, +-673, 1073, -619, 1064, -456, 918, -171, 676, +180, 352, 494, -57, 718, -479, 829, -819, +814, -1054, 683, -1203, 434, -1254, 115, -1184, +-165, -996, -361, -700, -500, -309, -585, 181, +-595, 760, -502, 1357, -357, 1821, -257, 2015, +-205, 1885, -142, 1425, -44, 677, 81, -205, +219, -1030, 344, -1661, 477, -1959, 617, -1872, +696, -1504, 635, -982, 439, -407, 183, 95, +-59, 463, -290, 710, -528, 836, -710, 879, +-783, 907, -769, 910, -696, 828, -550, 684, +-297, 524, 39, 306, 348, -9, 574, -357, +756, -657, 897, -886, 916, -1049, 756, -1132, +491, -1069, 238, -809, 30, -420, -175, 6, +-380, 455, -571, 841, -743, 1012, -889, 955, +-979, 769, -951, 494, -746, 177, -389, -42, +50, -76, 555, 7, 1049, 115, 1391, 189, +1472, 146, 1288, -63, 905, -418, 425, -821, +-84, -1107, -572, -1168, -961, -1007, -1183, -654, +-1232, -148, -1137, 402, -912, 868, -578, 1152, +-188, 1202, 190, 1067, 552, 849, 888, 569, +1094, 226, 1088, -99, 908, -323, 640, -468, +331, -577, 0, -618, -316, -585, -564, -528, +-724, -493, -820, -502, -840, -532, -729, -514, +-492, -416, -229, -226, 10, 96, 297, 560, +627, 1086, 827, 1513, 803, 1684, 639, 1538, +414, 1107, 112, 434, -225, -388, -493, -1167, +-621, -1683, -600, -1841, -448, -1689, -206, -1283, +62, -694, 308, -58, 485, 468, 524, 804, +386, 962, 150, 1001, -116, 920, -410, 730, +-680, 523, -771, 349, -607, 157, -280, -43, +86, -185, 462, -287, 807, -384, 980, -440, +901, -431, 653, -413, 327, -406, -80, -371, +-487, -307, -720, -250, -762, -174, -740, -43, +-682, 120, -525, 275, -292, 414, -43, 558, +209, 666, 452, 665, 642, 556, 764, 381, +800, 137, 706, -163, 465, -445, 139, -639, +-206, -715, -520, -650, -709, -455, -712, -191, +-577, 67, -383, 240, -157, 277, 65, 174, +226, 3, 283, -164, 235, -269, 130, -233, +37, -27, -3, 282, 6, 595, 86, 826, +248, 896, 400, 771, 431, 459, 365, 16, +237, -459, -22, -872, -420, -1159, -773, -1260, +-911, -1141, -848, -831, -637, -374, -265, 174, +252, 708, 742, 1118, 1017, 1361, 1022, 1365, +804, 1073, 404, 559, -100, -38, -565, -616, +-849, -1034, -878, -1178, -676, -1065, -325, -735, +84, -254, 469, 222, 731, 550, 769, 705, +556, 684, 201, 501, -153, 223, -470, -59, +-742, -279, -859, -410, -720, -459, -384, -433, +34, -306, 463, -89, 820, 147, 977, 345, +888, 521, 610, 630, 226, 570, -210, 343, +-612, 37, -859, -300, -880, -600, -665, -749, +-295, -707, 80, -493, 344, -144, 489, 244, +496, 517, 345, 616, 96, 548, -123, 326, +-231, 20, -222, -267, -95, -459, 131, -479, +347, -306, 434, -57, 399, 189, 269, 405, +35, 519, -270, 460, -534, 268, -675, 20, +-685, -219, -584, -392, -355, -473, -34, -446, +240, -323, 399, -145, 529, 17, 669, 122, +722, 185, 641, 244, 474, 282, 271, 275, +16, 242, -290, 210, -578, 144, -804, -2, +-947, -202, -945, -383, -723, -474, -324, -452, +113, -295, 468, -12, 719, 342, 875, 648, +861, 789, 625, 704, 287, 390, -7, -81, +-241, -582, -426, -974, -501, -1139, -433, -1014, +-299, -641, -160, -115, -10, 453, 158, 925, +291, 1184, 334, 1202, 270, 1002, 113, 644, +-82, 193, -290, -296, -511, -711, -666, -969, +-623, -1087, -390, -1074, -56, -858, 345, -461, +772, -1, 1077, 431, 1111, 776, 881, 961, +522, 935, 104, 706, -392, 331, -868, -70, +-1142, -393, -1137, -565, -922, -553, -608, -373, +-262, -102, 101, 177, 416, 385, 607, 456, +682, 389, 682, 210, 624, -59, 505, -360, +336, -609, 176, -755, 87, -772, -8, -659, +-175, -396, -343, -4, -441, 415, -505, 781, +-583, 1075, -625, 1202, -571, 1072, -444, 757, +-280, 343, -37, -135, 272, -576, 586, -858, +863, -975, 1037, -960, 1038, -831, 900, -618, +635, -393, 175, -214, -397, -73, -868, 68, +-1127, 241, -1225, 436, -1150, 643, -832, 825, +-326, 953, 157, 993, 497, 904, 717, 659, +812, 283, 751, -155, 558, -596, 322, -973, +141, -1229, 35, -1324, -68, -1228, -172, -960, +-237, -615, -285, -212, -331, 237, -334, 614, +-279, 859, -182, 1020, -50, 1112, 73, 1114, +130, 1020, 118, 820, 88, 550, 52, 220, +-4, -192, -44, -647, 4, -1037, 104, -1305, +175, -1423, 196, -1351, 164, -1093, 80, -693, +-18, -212, -87, 272, -108, 686, -56, 1009, +14, 1229, 62, 1321, 91, 1262, 56, 1075, +-99, 777, -312, 357, -449, -157, -456, -650, +-362, -1008, -168, -1242, 162, -1295, 512, -1087, +706, -698, 737, -292, 662, 74, 434, 343, +75, 448, -281, 411, -538, 286, -676, 147, +-698, 87, -574, 154, -328, 323, -78, 546, +102, 747, 266, 867, 416, 856, 476, 658, +423, 261, 308, -265, 177, -823, 24, -1330, +-134, -1708, -241, -1855, -283, -1662, -297, -1132, +-254, -390, -124, 441, 50, 1267, 204, 1914, +288, 2212, 268, 2114, 170, 1654, 43, 936, +-106, 126, -258, -636, -360, -1251, -352, -1578, +-229, -1596, -52, -1402, 115, -1058, 273, -607, +397, -166, 423, 197, 332, 462, 179, 607, +30, 664, -112, 654, -280, 575, -436, 454, +-475, 363, -403, 304, -281, 268, -116, 240, +100, 206, 343, 140, 567, 7, 692, -193, +653, -426, 469, -661, 189, -876, -124, -992, +-424, -963, -687, -791, -847, -498, -821, -104, +-640, 343, -384, 791, -92, 1172, 212, 1396, +495, 1429, 699, 1263, 804, 898, 830, 374, +771, -218, 595, -780, 303, -1189, -91, -1388, +-487, -1397, -743, -1209, -863, -839, -916, -413, +-827, -26, -531, 301, -162, 543, 139, 735, +372, 885, 576, 949, 663, 933, 566, 870, +404, 690, 295, 358, 173, -59, -20, -488, +-208, -856, -305, -1081, -286, -1115, -202, -934, +-101, -550, 43, -96, 225, 294, 319, 567, +244, 690, 32, 623, -230, 411, -469, 137, +-657, -120, -739, -261, -597, -258, -224, -167, +197, -26, 520, 162, 735, 324, 883, 379, +885, 307, 658, 165, 331, -1, 97, -178, +-78, -319, -314, -381, -554, -364, -702, -283, +-769, -171, -798, -113, -752, -85, -565, -40, +-222, -34, 192, -56, 571, 13, 823, 154, +925, 305, 896, 475, 694, 601, 333, 601, +-9, 486, -196, 277, -312, -32, -429, -342, +-473, -562, -387, -678, -277, -676, -249, -551, +-228, -367, -108, -180, 39, -16, 106, 92, +128, 169, 122, 248, 48, 333, -87, 410, +-201, 472, -221, 494, -116, 455, 85, 312, +343, 54, 610, -222, 793, -430, 818, -559, +652, -579, 311, -443, -115, -185, -513, 106, +-832, 324, -1030, 422, -1067, 404, -957, 265, +-751, 12, -480, -258, -139, -450, 257, -539, +617, -500, 869, -339, 1059, -95, 1177, 175, +1127, 417, 875, 583, 499, 666, 78, 661, +-339, 559, -707, 393, -958, 204, -1053, -1, +-1016, -216, -871, -431, -649, -651, -392, -822, +-111, -907, 187, -907, 439, -791, 620, -514, +736, -115, 784, 350, 768, 801, 649, 1122, +397, 1274, 103, 1244, -99, 973, -225, 515, +-324, 56, -384, -339, -366, -635, -288, -766, +-235, -743, -269, -635, -352, -477, -412, -349, +-415, -342, -358, -401, -250, -429, -36, -390, +300, -279, 631, -49, 842, 324, 943, 776, +898, 1160, 646, 1364, 262, 1364, -111, 1150, +-402, 700, -606, 69, -696, -577, -655, -1092, +-519, -1404, -369, -1506, -226, -1356, -115, -982, +-70, -507, -55, -37, -4, 370, 114, 643, +274, 765, 410, 805, 481, 763, 487, 647, +402, 521, 251, 404, 125, 247, 47, 60, +-32, -134, -87, -312, -72, -454, -49, -547, +-136, -553, -347, -450, -564, -296, -705, -156, +-759, -5, -670, 125, -371, 169, 63, 154, +506, 135, 877, 97, 1100, 50, 1109, 7, +883, -44, 467, -58, -10, -14, -400, 43, +-663, 112, -792, 254, -779, 408, -634, 473, +-404, 422, -159, 266, 46, 17, 207, -287, +319, -585, 364, -785, 366, -791, 339, -614, +286, -341, 216, -38, 112, 272, -56, 496, +-214, 535, -288, 432, -301, 319, -317, 202, +-298, 59, -162, -27, 32, -23, 176, 3, +273, 9, 353, 10, 346, 9, 241, 21, +115, 29, 3, 13, -114, -14, -207, -76, +-240, -213, -237, -369, -236, -485, -212, -562, +-123, -518, -35, -284, 9, 59, 65, 405, +171, 731, 255, 933, 267, 916, 230, 719, +172, 400, 95, 8, -12, -349, -106, -579, +-119, -686, -73, -675, -44, -565, -50, -410, +-85, -262, -135, -108, -196, 51, -261, 190, +-288, 301, -215, 403, -41, 477, 158, 467, +340, 376, 483, 224, 524, 36, 399, -149, +183, -291, -2, -384, -145, -392, -295, -307, +-392, -185, -372, -64, -286, 70, -200, 201, +-126, 274, -38, 296, 57, 281, 129, 221, +182, 113, 259, -16, 324, -158, 287, -292, +141, -397, -18, -449, -105, -427, -158, -347, +-202, -200, -173, 19, -60, 266, 28, 481, +57, 658, 65, 749, 36, 696, -60, 509, +-157, 228, -181, -103, -131, -410, -46, -636, +46, -747, 149, -694, 223, -507, 235, -285, +207, -98, 178, 51, 109, 144, -9, 177, +-110, 167, -156, 158, -205, 202, -289, 301, +-329, 383, -262, 404, -115, 378, 47, 294, +196, 144, 315, -39, 389, -192, 378, -287, +253, -332, 70, -344, -56, -333, -107, -320, +-168, -318, -232, -294, -200, -237, -90, -145, +-58, -13, -135, 151, -203, 300, -172, 398, +-86, 430, -2, 415, 102, 381, 248, 331, +385, 275, 414, 231, 302, 171, 116, 25, +-54, -197, -199, -453, -316, -696, -363, -863, +-278, -871, -71, -687, 129, -336, 226, 105, +271, 514, 286, 809, 171, 936, -76, 856, +-305, 598, -429, 285, -498, -12, -503, -269, +-365, -451, -98, -523, 191, -517, 443, -477, +645, -407, 738, -270, 699, -37, 560, 231, +336, 469, 47, 647, -229, 724, -451, 619, +-622, 326, -726, -91, -727, -522, -635, -844, +-474, -975, -252, -884, 5, -590, 266, -146, +501, 329, 662, 713, 708, 919, 670, 925, +564, 749, 363, 446, 99, 86, -130, -260, +-307, -515, -454, -619, -526, -591, -497, -487, +-393, -299, -251, -47, -75, 166, 116, 263, +278, 284, 343, 231, 271, 93, 97, -67, +-76, -183, -186, -232, -258, -180, -271, -36, +-140, 114, 129, 235, 385, 323, 525, 331, +545, 216, 446, 38, 212, -124, -103, -232, +-401, -279, -583, -245, -612, -127, -537, 39, +-399, 200, -216, 288, -10, 297, 181, 223, +337, 59, 441, -169, 507, -372, 556, -496, +551, -535, 409, -467, 114, -282, -231, -28, +-549, 207, -810, 385, -934, 486, -816, 500, +-488, 444, -69, 363, 355, 289, 721, 246, +917, 218, 876, 157, 649, 31, 323, -179, +-12, -451, -265, -721, -386, -916, -424, -987, +-427, -853, -393, -504, -327, -43, -293, 397, +-283, 765, -212, 1002, -64, 1020, 113, 844, +294, 585, 471, 315, 589, 34, 586, -208, +444, -368, 218, -459, -31, -528, -251, -572, +-389, -550, -415, -429, -336, -229, -179, -12, +-11, 186, 93, 345, 130, 429, 100, 372, +-20, 198, -208, 6, -364, -121, -399, -174, +-297, -154, -118, -63, 111, 67, 404, 181, +688, 217, 827, 172, 776, 93, 602, 28, +336, -27, -26, -53, -420, -55, -708, -55, +-836, -77, -853, -118, -768, -175, -568, -239, +-298, -254, -15, -180, 242, -51, 435, 61, +557, 157, 609, 236, 584, 253, 480, 180, +352, 79, 235, 18, 110, -6, -26, -10, +-110, 19, -125, 78, -157, 122, -223, 131, +-293, 98, -376, 40, -471, -39, -514, -139, +-493, -251, -434, -352, -310, -423, -83, -436, +206, -364, 461, -208, 646, 10, 773, 251, +832, 482, 770, 636, 583, 663, 328, 559, +59, 363, -225, 118, -518, -121, -749, -291, +-840, -377, -813, -391, -719, -360, -532, -301, +-262, -250, 10, -220, 217, -188, 376, -125, +493, -32, 552, 95, 538, 232, 463, 337, +378, 381, 313, 349, 245, 251, 138, 124, +24, 25, -71, -27, -186, -30, -362, -2, +-510, 44, -550, 66, -531, 8, -508, -137, +-439, -317, -275, -477, -49, -585, 179, -594, +368, -479, 521, -237, 611, 83, 614, 418, +555, 697, 466, 874, 333, 915, 148, 804, +-61, 552, -237, 206, -359, -153, -462, -471, +-551, -712, -569, -845, -491, -828, -361, -682, +-201, -460, -29, -215, 135, 27, 255, 230, +294, 369, 273, 429, 244, 401, 234, 329, +218, 267, 192, 222, 185, 163, 227, 124, +262, 124, 207, 127, 72, 98, -64, 50, +-185, -1, -311, -59, -420, -117, -467, -173, +-451, -230, -419, -280, -374, -329, -283, -414, +-145, -504, 2, -537, 157, -485, 332, -353, +530, -108, 711, 261, 791, 661, 734, 976, +544, 1144, 239, 1120, -129, 859, -472, 417, +-747, -99, -896, -550, -859, -815, -636, -835, +-298, -648, 67, -321, 390, 30, 610, 259, +660, 289, 519, 112, 268, -219, -5, -594, +-245, -862, -405, -926, -445, -749, -354, -354, +-156, 183, 75, 738, 268, 1180, 403, 1436, +453, 1466, 392, 1270, 257, 877, 107, 371, +-53, -163, -221, -651, -364, -1059, -444, -1331, +-458, -1409, -403, -1282, -264, -979, -72, -539, +123, -15, 311, 488, 475, 864, 534, 1040, +463, 1007, 306, 770, 116, 383, -88, -60, +-268, -439, -376, -648, -394, -638, -353, -435, +-293, -96, -214, 316, -117, 677, 3, 887, +132, 880, 245, 656, 323, 256, 399, -235, +454, -722, 404, -1090, 232, -1256, 14, -1192, +-177, -910, -334, -469, -442, 56, -443, 564, +-318, 955, -171, 1142, -62, 1120, 34, 920, +110, 593, 117, 186, 63, -210, 20, -507, +28, -667, 57, -689, 67, -598, 71, -418, +79, -208, 88, -25, 87, 83, 99, 140, +142, 164, 210, 162, 261, 153, 241, 168, +130, 217, -58, 260, -292, 267, -541, 215, +-750, 107, -816, -52, -657, -215, -347, -346, +6, -405, 376, -367, 734, -253, 954, -112, +941, 33, 746, 158, 465, 201, 133, 162, +-238, 103, -550, 73, -690, 61, -669, 78, +-581, 129, -453, 183, -249, 189, 11, 138, +211, 45, 281, -72, 297, -175, 319, -230, +295, -218, 210, -153, 136, -64, 105, -1, +84, 13, 31, -32, -57, -108, -134, -169, +-166, -179, -187, -129, -218, -18, -209, 150, +-125, 321, -4, 430, 77, 438, 121, 380, +135, 266, 88, 116, -2, -41, -74, -179, +-122, -303, -145, -419, -103, -519, -12, -595, +80, -609, 164, -531, 273, -333, 372, -16, +379, 401, 286, 833, 163, 1162, 17, 1294, +-200, 1183, -458, 823, -652, 256, -698, -395, +-607, -972, -415, -1345, -128, -1473, 238, -1335, +558, -961, 712, -452, 692, 42, 547, 420, +298, 647, -11, 726, -285, 679, -417, 575, +-372, 504, -223, 483, -56, 504, 84, 550, +182, 566, 199, 458, 114, 216, -30, -122, +-151, -521, -232, -924, -283, -1221, -271, -1322, +-168, -1226, -17, -952, 107, -548, 183, -61, +232, 415, 270, 799, 272, 1026, 208, 1108, +87, 1076, -44, 928, -153, 672, -236, 372, +-273, 82, -227, -196, -96, -426, 46, -583, +156, -657, 240, -662, 283, -593, 248, -475, +137, -336, -13, -186, -140, -41, -209, 69, +-236, 154, -242, 252, -233, 340, -190, 387, +-109, 387, -12, 364, 63, 305, 140, 200, +235, 41, 307, -125, 310, -259, 234, -354, +117, -397, -8, -380, -138, -282, -261, -117, +-295, 91, -199, 283, -47, 433, 66, 521, +139, 518, 198, 366, 191, 77, 67, -242, +-97, -518, -189, -725, -221, -818, -241, -713, +-217, -424, -103, -40, 43, 339, 131, 661, +151, 859, 172, 882, 207, 742, 208, 504, +185, 226, 183, -69, 187, -343, 130, -560, +10, -692, -131, -765, -266, -776, -407, -698, +-515, -511, -527, -233, -429, 98, -240, 435, +24, 716, 309, 884, 541, 884, 687, 736, +714, 491, 610, 209, 415, -50, 174, -222, +-93, -299, -342, -289, -513, -228, -590, -189, +-593, -229, -541, -352, -441, -511, -309, -674, +-152, -784, 39, -773, 243, -591, 417, -248, +550, 225, 623, 745, 602, 1209, 481, 1529, +283, 1618, 36, 1431, -208, 1001, -389, 404, +-462, -281, -410, -922, -277, -1400, -120, -1633, +25, -1595, 140, -1308, 190, -868, 130, -369, +-25, 128, -193, 546, -318, 810, -397, 912, +-394, 908, -269, 795, -45, 595, 213, 370, +452, 170, 620, -11, 708, -154, 704, -240, +555, -262, 256, -233, -67, -191, -281, -161, +-411, -154, -522, -156, -563, -181, -480, -221, +-373, -248, -347, -243, -356, -210, -310, -140, +-211, -35, -68, 96, 154, 249, 457, 398, +766, 518, 968, 589, 991, 589, 811, 466, +453, 212, -23, -142, -506, -513, -875, -822, +-1042, -988, -976, -939, -722, -662, -366, -199, +-1, 342, 298, 832, 476, 1142, 527, 1211, +486, 1005, 407, 567, 309, 23, 211, -481, +127, -872, 33, -1113, -102, -1151, -247, -982, +-357, -665, -434, -283, -451, 117, -357, 493, +-161, 819, 53, 1045, 245, 1115, 409, 999, +491, 737, 429, 368, 269, -87, 89, -538, +-101, -867, -273, -1013, -364, -1001, -370, -833, +-329, -527, -226, -144, -60, 209, 111, 461, +237, 589, 332, 617, 382, 554, 340, 400, +227, 209, 102, 39, -42, -89, -228, -181, +-368, -199, -389, -168, -319, -114, -219, -50, +-90, 9, 64, 16, 194, -18, 251, -48, +220, -100, 135, -187, 35, -245, -72, -215, +-176, -150, -212, -92, -126, -16, 29, 108, +156, 237, 256, 321, 361, 361, 413, 385, +340, 383, 169, 315, -18, 198, -199, 63, +-376, -75, -523, -233, -585, -388, -552, -516, +-465, -597, -337, -620, -141, -569, 111, -442, +369, -228, 582, 82, 712, 429, 743, 738, +672, 927, 509, 946, 246, 774, -84, 452, +-381, 23, -557, -411, -633, -711, -644, -808, +-547, -712, -343, -466, -115, -126, 79, 189, +239, 382, 365, 423, 437, 344, 421, 183, +312, 4, 144, -143, -23, -239, -177, -283, +-337, -282, -439, -250, -394, -213, -219, -154, +-10, -40, 212, 152, 433, 379, 569, 593, +542, 737, 379, 748, 157, 577, -83, 257, +-320, -140, -507, -547, -587, -858, -535, -991, +-390, -926, -233, -703, -82, -365, 98, 7, +278, 337, 369, 580, 391, 727, 418, 750, +415, 654, 320, 488, 177, 268, 56, 5, +-75, -253, -242, -435, -384, -524, -446, -505, +-461, -389, -438, -193, -338, 24, -162, 196, +45, 266, 255, 236, 448, 147, 577, 20, +606, -107, 522, -189, 330, -198, 55, -165, +-225, -99, -446, -21, -584, 61, -613, 145, +-494, 220, -253, 284, 8, 346, 231, 385, +401, 335, 481, 187, 419, -26, 244, -248, +25, -452, -188, -591, -357, -603, -420, -467, +-353, -236, -195, 12, 22, 224, 283, 362, +500, 404, 562, 340, 477, 209, 300, 63, +33, -48, -289, -126, -531, -187, -604, -222, +-542, -192, -391, -95, -147, 34, 123, 191, +308, 384, 391, 569, 395, 640, 312, 555, +174, 321, 77, -41, 20, -485, -65, -897, +-158, -1157, -206, -1207, -239, -1028, -291, -654, +-287, -152, -181, 374, -11, 834, 185, 1147, +386, 1272, 519, 1193, 522, 965, 399, 637, +171, 227, -131, -212, -403, -588, -548, -860, +-575, -1018, -507, -1022, -334, -862, -89, -586, +127, -263, 276, 64, 372, 327, 400, 495, +342, 567, 248, 541, 154, 435, 26, 305, +-138, 193, -280, 82, -348, -22, -336, -104, +-236, -150, -59, -154, 158, -103, 356, -27, +488, 56, 510, 127, 382, 148, 110, 77, +-233, -89, -547, -292, -758, -486, -808, -608, +-670, -604, -366, -435, 24, -129, 417, 250, +743, 593, 939, 827, 942, 913, 738, 813, +377, 541, -45, 175, -417, -186, -685, -490, +-834, -670, -828, -702, -636, -600, -336, -408, +-38, -168, 224, 49, 448, 202, 566, 284, +545, 280, 468, 197, 393, 81, 283, 3, +103, -32, -100, -33, -298, -12, -480, 41, +-608, 99, -642, 108, -569, 57, -360, 14, +-12, 10, 380, 12, 690, 30, 857, 85, +851, 150, 617, 138, 198, 33, -249, -135, +-603, -316, -825, -470, -861, -537, -667, -467, +-302, -259, 105, 43, 445, 346, 650, 570, +679, 657, 552, 594, 316, 395, 18, 129, +-260, -138, -426, -342, -471, -441, -439, -429, +-316, -334, -95, -196, 124, -38, 251, 114, +318, 233, 356, 294, 319, 312, 193, 285, +53, 204, -69, 56, -214, -112, -343, -252, +-372, -372, -327, -451, -276, -430, -179, -314, +3, -167, 201, 4, 338, 183, 433, 335, +494, 427, 459, 466, 304, 446, 101, 371, +-102, 251, -297, 104, -441, -53, -491, -199, +-460, -299, -366, -342, -206, -316, -19, -245, +130, -154, 231, -91, 303, -80, 321, -118, +270, -179, 192, -240, 119, -263, 30, -185, +-58, -11, -96, 219, -98, 458, -88, 670, +-43, 772, 33, 726, 65, 553, 33, 293, +-3, -31, -30, -360, -102, -611, -198, -758, +-232, -794, -201, -704, -146, -488, -62, -213, +64, 74, 180, 324, 247, 504, 279, 576, +284, 517, 252, 348, 178, 129, 63, -78, +-84, -247, -234, -339, -349, -334, -399, -238, +-390, -96, -308, 56, -140, 177, 86, 272, +318, 333, 510, 334, 603, 274, 545, 181, +346, 70, 74, -84, -212, -253, -474, -401, +-649, -485, -681, -483, -568, -390, -356, -248, +-88, -72, 197, 120, 440, 279, 583, 371, +597, 401, 513, 400, 380, 369, 214, 301, +-4, 189, -228, 59, -379, -104, -435, -306, +-442, -508, -396, -622, -261, -599, -81, -440, +78, -163, 211, 182, 318, 510, 349, 714, +292, 738, 190, 564, 70, 258, -61, -79, +-147, -354, -169, -512, -163, -497, -146, -318, +-91, -95, 1, 67, 69, 133, 89, 112, +77, -1, 51, -164, 13, -304, -25, -326, +-64, -205, -97, 5, -110, 233, -94, 440, +-47, 577, 36, 587, 145, 479, 243, 278, +302, 37, 301, -191, 232, -361, 99, -477, +-66, -502, -236, -434, -394, -314, -502, -179, +-502, -42, -379, 80, -209, 152, -46, 179, +127, 161, 310, 119, 435, 93, 468, 115, +464, 151, 463, 195, 391, 244, 204, 255, +-9, 182, -192, 39, -390, -132, -595, -315, +-692, -462, -625, -518, -453, -441, -232, -264, +45, -44, 335, 164, 530, 334, 582, 430, +532, 421, 416, 337, 252, 225, 74, 111, +-85, 7, -185, -55, -225, -98, -245, -151, +-272, -223, -280, -296, -251, -372, -202, -417, +-149, -385, -66, -275, 43, -99, 139, 131, +215, 375, 266, 566, 272, 676, 237, 666, +211, 537, 176, 323, 81, 77, -41, -170, +-119, -395, -169, -562, -237, -643, -281, -626, +-236, -533, -131, -389, -44, -209, 31, -5, +113, 183, 159, 345, 125, 471, 40, 530, +-35, 507, -68, 423, -63, 298, -32, 133, +21, -43, 78, -195, 105, -288, 84, -325, +44, -305, 17, -230, 14, -107, 25, 10, +69, 76, 148, 83, 203, 55, 177, -4, +70, -109, -81, -216, -257, -281, -427, -261, +-541, -168, -548, -24, -445, 140, -259, 319, +-19, 470, 243, 540, 476, 528, 640, 443, +714, 277, 685, 51, 556, -169, 344, -366, +70, -523, -242, -611, -530, -609, -730, -536, +-817, -383, -785, -159, -614, 75, -311, 287, +45, 474, 379, 610, 657, 639, 821, 557, +803, 379, 620, 141, 321, -130, -37, -394, +-386, -597, -651, -669, -779, -596, -737, -421, +-517, -177, -173, 112, 193, 401, 500, 610, +703, 685, 731, 613, 563, 454, 277, 237, +-37, -41, -343, -337, -581, -556, -650, -669, +-541, -690, -326, -591, -62, -366, 220, -68, +452, 235, 576, 505, 582, 668, 473, 675, +238, 520, -72, 245, -356, -91, -568, -391, +-698, -548, -701, -528, -534, -342, -241, -53, +95, 257, 413, 482, 665, 542, 775, 401, +697, 109, 483, -233, 218, -518, -47, -663, +-268, -621, -400, -399, -446, -66, -412, 283, +-317, 543, -210, 682, -136, 681, -85, 537, +-22, 286, 49, 25, 113, -199, 188, -398, +268, -556, 284, -634, 215, -635, 107, -577, +-9, -436, -136, -207, -247, 84, -301, 383, +-270, 647, -159, 829, -2, 890, 147, 802, +268, 571, 362, 252, 407, -104, 369, -438, +246, -683, 77, -789, -127, -783, -352, -675, +-543, -465, -648, -198, -645, 51, -520, 251, +-289, 387, -2, 439, 297, 422, 563, 352, +735, 247, 746, 131, 604, 52, 378, 5, +112, -23, -184, -32, -446, -27, -595, -33, +-606, -52, -506, -71, -331, -93, -93, -118, +170, -146, 386, -166, 492, -185, 477, -191, +348, -175, 142, -110, -95, -1, -308, 127, +-444, 262, -449, 394, -323, 466, -140, 418, +46, 273, 224, 58, 352, -188, 352, -412, +221, -551, 46, -573, -96, -469, -198, -261, +-246, -7, -203, 237, -80, 440, 77, 563, +218, 564, 302, 468, 306, 306, 239, 87, +97, -172, -98, -401, -275, -547, -359, -585, +-370, -510, -346, -316, -252, -35, -68, 255, +115, 480, 201, 573, 214, 504, 184, 280, +101, -20, -6, -325, -65, -555, -52, -624, +15, -484, 111, -201, 211, 128, 282, 438, +286, 657, 201, 719, 17, 599, -201, 350, +-363, 34, -436, -271, -435, -509, -342, -638, +-165, -634, 20, -494, 156, -269, 245, -23, +281, 215, 231, 395, 120, 463, 6, 393, +-68, 221, -100, -11, -78, -239, -16, -404, +42, -449, 83, -334, 134, -70, 172, 255, +130, 544, 26, 740, -64, 766, -120, 578, +-190, 219, -253, -206, -240, -603, -149, -874, +-61, -953, 3, -835, 81, -549, 159, -149, +183, 245, 147, 519, 90, 650, 26, 647, +-25, 525, -55, 316, -73, 109, -63, -36, +-10, -96, 52, -88, 71, -53, 58, -29, +50, -46, 11, -125, -81, -270, -156, -424, +-180, -523, -190, -508, -174, -366, -78, -114, +56, 206, 156, 539, 228, 789, 284, 875, +273, 783, 172, 547, 54, 212, -41, -155, +-139, -453, -218, -641, -224, -718, -188, -691, +-160, -581, -132, -448, -102, -317, -97, -176, +-113, -17, -107, 161, -58, 360, 34, 585, +167, 783, 338, 893, 490, 866, 559, 699, +517, 388, 354, -26, 79, -455, -246, -816, +-543, -1053, -761, -1115, -839, -967, -731, -658, +-452, -248, -92, 191, 266, 578, 551, 833, +695, 933, 656, 864, 460, 631, 172, 296, +-122, -52, -336, -349, -429, -543, -395, -591, +-244, -504, -9, -322, 215, -103, 345, 90, +352, 197, 269, 205, 124, 128, -56, 4, +-235, -114, -350, -171, -364, -147, -315, -50, +-242, 113, -149, 295, -32, 443, 65, 507, +117, 479, 160, 357, 232, 155, 302, -113, +325, -402, 292, -643, 212, -801, 95, -865, +-50, -812, -215, -593, -359, -250, -407, 139, +-357, 516, -262, 843, -145, 1043, 2, 1070, +140, 922, 201, 622, 187, 239, 160, -156, +147, -491, 129, -724, 109, -820, 89, -776, +58, -611, 3, -385, -93, -153, -224, 54, +-333, 209, -370, 279, -332, 259, -212, 197, +-5, 138, 225, 96, 396, 80, 483, 115, +470, 195, 338, 280, 108, 321, -134, 301, +-328, 207, -455, 36, -481, -180, -391, -390, +-231, -534, -50, -590, 130, -551, 261, -425, +314, -216, 301, 31, 237, 254, 121, 409, +-9, 500, -99, 527, -151, 481, -180, 370, +-175, 224, -114, 74, -28, -74, 46, -192, +92, -272, 109, -324, 90, -356, 43, -359, +-20, -359, -93, -364, -162, -342, -209, -267, +-219, -140, -190, 37, -115, 279, 18, 547, +205, 783, 376, 916, 471, 896, 490, 700, +440, 361, 273, -71, -15, -528, -333, -915, +-585, -1140, -741, -1159, -785, -984, -666, -652, +-403, -232, -75, 202, 247, 570, 514, 822, +669, 938, 694, 914, 617, 755, 461, 502, +257, 214, 50, -70, -131, -314, -299, -490, +-434, -575, -498, -575, -490, -492, -439, -352, +-336, -196, -174, -52, 3, 75, 147, 162, +256, 194, 317, 192, 298, 172, 209, 130, +94, 62, 4, 1, -47, -28, -41, -7, +14, 60, 82, 169, 135, 297, 159, 408, +131, 453, 28, 375, -126, 158, -290, -175, +-422, -556, -492, -899, -481, -1107, -377, -1106, +-174, -858, 83, -405, 325, 167, 510, 742, +625, 1195, 643, 1422, 527, 1376, 298, 1088, +28, 615, -226, 64, -458, -461, -625, -868, +-671, -1113, -583, -1175, -407, -1059, -187, -799, +56, -454, 297, -89, 484, 259, 549, 553, +488, 760, 338, 847, 140, 814, -80, 664, +-259, 432, -341, 178, -319, -57, -229, -261, +-99, -406, 48, -464, 155, -463, 173, -444, +102, -412, -12, -357, -126, -288, -192, -191, +-184, -54, -109, 129, -15, 335, 56, 529, +94, 658, 91, 678, 39, 581, -45, 377, +-98, 88, -87, -235, -10, -499, 114, -651, +256, -673, 358, -575, 365, -378, 253, -128, +57, 104, -186, 264, -435, 341, -628, 342, +-721, 270, -673, 165, -479, 74, -170, 38, +183, 42, 514, 77, 771, 119, 894, 136, +837, 109, 605, 27, 249, -112, -167, -278, +-563, -413, -829, -485, -895, -466, -774, -353, +-503, -162, -137, 73, 230, 312, 501, 500, +627, 601, 592, 608, 404, 530, 126, 370, +-138, 143, -318, -104, -410, -332, -391, -517, +-253, -651, -49, -693, 136, -612, 264, -416, +325, -141, 294, 174, 152, 474, -50, 686, +-233, 762, -356, 685, -400, 461, -352, 131, +-202, -207, 17, -474, 239, -612, 398, -597, +448, -443, 376, -196, 215, 74, 8, 301, +-199, 434, -349, 448, -404, 348, -366, 174, +-274, -42, -153, -245, -31, -402, 65, -482, +124, -468, 170, -357, 210, -169, 233, 76, +252, 347, 267, 578, 236, 718, 121, 727, +-44, 598, -215, 339, -367, -1, -486, -367, +-517, -677, -419, -858, -236, -874, -34, -737, +153, -484, 305, -153, 397, 184, 410, 471, +346, 668, 241, 757, 117, 724, -8, 585, +-106, 358, -165, 79, -200, -210, -225, -461, +-237, -625, -230, -669, -203, -580, -163, -362, +-104, -51, -38, 266, 20, 515, 71, 635, +119, 589, 155, 376, 182, 59, 194, -267, +181, -521, 148, -640, 115, -583, 84, -357, +20, -48, -80, 258, -181, 480, -260, 566, +-330, 497, -368, 305, -337, 51, -235, -193, +-94, -359, 60, -406, 215, -339, 341, -194, +388, -12, 341, 154, 239, 270, 106, 312, +-27, 282, -120, 196, -160, 75, -167, -59, +-163, -187, -146, -294, -130, -371, -134, -390, +-140, -344, -110, -240, -57, -80, 6, 134, +86, 351, 167, 516, 195, 596, 157, 568, +75, 418, -25, 179, -121, -94, -171, -349, +-145, -535, -74, -613, 21, -564, 114, -422, +156, -224, 116, -8, 31, 195, -66, 346, +-152, 422, -199, 428, -181, 380, -99, 289, +6, 157, 110, 6, 189, -141, 199, -252, +125, -311, 3, -315, -138, -263, -271, -154, +-363, -18, -367, 96, -257, 150, -79, 138, +133, 76, 354, -24, 535, -118, 596, -173, +509, -164, 304, -80, 26, 67, -287, 227, +-558, 352, -701, 422, -688, 419, -542, 323, +-302, 148, -34, -64, 187, -272, 340, -442, +405, -554, 378, -578, 297, -507, 219, -369, +161, -186, 109, 31, 68, 247, 38, 409, +-22, 509, -142, 549, -270, 523, -373, 427, +-433, 287, -426, 116, -334, -61, -187, -221, +-17, -356, 150, -460, 285, -501, 356, -469, +358, -378, 313, -239, 228, -69, 125, 116, +25, 271, -56, 370, -118, 402, -174, 379, +-227, 313, -242, 226, -213, 134, -183, 47, +-162, -28, -122, -102, -62, -184, -11, -276, +19, -368, 46, -439, 78, -456, 93, -400, +97, -254, 117, -28, 166, 237, 229, 488, +261, 682, 234, 773, 168, 719, 69, 530, +-88, 248, -292, -82, -482, -408, -598, -662, +-626, -805, -558, -816, -376, -693, -98, -473, +210, -198, 469, 92, 633, 355, 687, 538, +645, 620, 497, 610, 263, 536, 7, 415, +-221, 263, -412, 113, -548, -17, -598, -138, +-556, -254, -438, -358, -260, -448, -55, -514, +124, -532, 269, -477, 372, -351, 385, -160, +293, 74, 167, 315, 55, 511, -47, 624, +-132, 647, -164, 578, -131, 432, -86, 231, +-61, 16, -36, -184, 1, -344, 24, -462, +25, -535, 17, -559, 16, -524, 6, -426, +-41, -270, -110, -66, -173, 154, -212, 366, +-207, 539, -136, 636, -16, 623, 123, 514, +235, 330, 293, 106, 276, -119, 186, -316, +61, -445, -75, -477, -198, -426, -255, -336, +-238, -218, -193, -85, -121, 32, -31, 102, +40, 127, 65, 127, 74, 116, 87, 98, +80, 81, 42, 82, 7, 105, -13, 142, +-56, 173, -103, 194, -125, 191, -116, 153, +-73, 70, 1, -46, 73, -179, 115, -304, +106, -407, 49, -462, -29, -440, -111, -338, +-163, -168, -169, 39, -130, 261, -49, 461, +55, 596, 157, 627, 235, 547, 243, 369, +175, 123, 61, -144, -77, -396, -208, -590, +-304, -678, -350, -635, -343, -491, -270, -269, +-145, 2, 7, 281, 153, 504, 277, 621, +356, 612, 357, 490, 300, 285, 219, 34, +99, -200, -61, -363, -207, -417, -311, -359, +-379, -225, -424, -68, -410, 74, -308, 157, +-142, 144, 48, 51, 241, -73, 417, -189, +534, -259, 545, -243, 424, -144, 212, 6, +-48, 166, -315, 308, -539, 390, -670, 397, +-671, 334, -536, 220, -310, 87, -47, -47, +217, -164, 449, -256, 604, -313, 630, -330, +529, -303, 355, -240, 143, -138, -100, -7, +-323, 125, -473, 220, -521, 262, -459, 244, +-319, 167, -137, 42, 43, -98, 169, -199, +198, -230, 133, -187, 21, -86, -76, 51, +-146, 187, -181, 290, -141, 328, -20, 282, +132, 171, 270, 37, 371, -99, 412, -218, +370, -284, 243, -284, 71, -236, -117, -168, +-307, -91, -475, -17, -584, 37, -602, 60, +-525, 62, -367, 65, -145, 69, 114, 69, +338, 72, 491, 88, 541, 101, 478, 104, +325, 94, 137, 78, -42, 60, -184, 37, +-265, 3, -268, -42, -207, -92, -123, -144, +-24, -186, 58, -212, 88, -202, 69, -149, +25, -58, -47, 45, -140, 140, -223, 209, +-275, 228, -281, 190, -234, 109, -114, 13, +59, -69, 232, -104, 365, -90, 440, -39, +426, 24, 316, 72, 127, 79, -87, 32, +-261, -54, -373, -143, -412, -205, -368, -214, +-256, -153, -133, -48, -23, 69, 60, 174, +118, 248, 141, 264, 132, 227, 116, 160, +92, 83, 66, 17, 49, -43, 28, -114, +-11, -194, -36, -261, -47, -315, -60, -342, +-85, -317, -105, -205, -112, -9, -114, 219, +-107, 425, -77, 565, -43, 598, -12, 490, +31, 257, 59, -47, 62, -342, 53, -558, +35, -640, 7, -576, -17, -377, -9, -92, +45, 199, 105, 419, 125, 518, 103, 485, +48, 345, -32, 141, -135, -84, -232, -265, +-288, -359, -298, -350, -281, -264, -216, -136, +-98, -3, 25, 110, 124, 182, 198, 194, +250, 160, 280, 109, 290, 57, 273, 7, +216, -21, 105, -30, -25, -31, -161, -38, +-299, -49, -397, -58, -429, -70, -400, -81, +-299, -80, -133, -50, 52, -7, 225, 39, +345, 85, 391, 130, 345, 153, 211, 146, +19, 98, -188, 20, -362, -68, -444, -161, +-404, -235, -260, -259, -37, -214, 210, -109, +414, 39, 504, 184, 455, 288, 297, 327, +77, 290, -178, 174, -405, 13, -513, -137, +-482, -237, -359, -263, -204, -216, -27, -107, +137, 15, 219, 104, 196, 137, 129, 119, +66, 57, 27, -32, 9, -117, 8, -163, +40, -157, 82, -119, 97, -76, 70, -27, +21, 56, -31, 149, -95, 223, -171, 294, +-209, 371, -184, 402, -129, 337, -62, 172, +7, -65, 66, -336, 96, -596, 87, -774, +39, -804, -28, -652, -95, -354, -136, 23, +-142, 393, -115, 677, -51, 819, 38, 796, +123, 622, 188, 360, 219, 93, 197, -126, +146, -270, 74, -336, -12, -338, -97, -313, +-172, -290, -250, -286, -327, -299, -373, -301, +-354, -265, -267, -174, -130, -26, 54, 162, +245, 354, 395, 507, 470, 575, 456, 547, +348, 420, 157, 211, -78, -31, -285, -246, +-400, -396, -414, -465, -345, -437, -214, -321, +-49, -147, 90, 29, 163, 161, 175, 227, +147, 230, 69, 166, -40, 46, -128, -89, +-172, -194, -172, -243, -135, -235, -68, -169, +24, -53, 137, 100, 239, 248, 299, 350, +299, 386, 251, 361, 142, 279, -41, 147, +-243, -15, -400, -167, -499, -276, -529, -336, +-455, -341, -285, -300, -56, -227, 176, -147, +374, -74, 502, -24, 522, 7, 429, 31, +260, 52, 55, 76, -137, 118, -271, 184, +-330, 247, -309, 299, -230, 330, -115, 337, +-1, 302, 61, 213, 44, 75, -25, -89, +-117, -270, -210, -456, -249, -614, -191, -697, +-40, -671, 145, -541, 307, -324, 423, -41, +471, 278, 412, 570, 244, 769, 10, 842, +-216, 798, -381, 651, -478, 408, -504, 111, +-441, -182, -308, -432, -169, -627, -63, -746, +35, -765, 156, -672, 262, -485, 329, -225, +382, 69, 424, 352, 421, 573, 338, 683, +171, 658, -41, 505, -259, 269, -461, 11, +-605, -199, -659, -321, -606, -343, -454, -286, +-240, -184, -2, -83, 227, -25, 413, -22, +530, -60, 563, -98, 504, -92, 394, -21, +257, 91, 89, 214, -88, 306, -231, 334, +-328, 273, -383, 125, -400, -62, -377, -218, +-318, -307, -244, -328, -159, -283, -73, -182, +15, -61, 112, 27, 209, 69, 276, 83, +322, 98, 347, 121, 320, 153, 234, 193, +108, 224, -24, 231, -152, 183, -268, 78, +-350, -54, -367, -181, -317, -291, -219, -349, +-110, -337, 2, -269, 111, -174, 176, -62, +185, 56, 174, 159, 153, 235, 103, 279, +40, 293, -22, 265, -79, 199, -133, 98, +-166, -16, -170, -120, -156, -192, -121, -219, +-57, -203, 15, -159, 78, -110, 137, -64, +174, -40, 173, -37, 138, -32, 84, 8, +25, 88, -24, 189, -63, 285, -98, 350, +-139, 346, -182, 235, -218, 33, -253, -205, +-256, -414, -195, -545, -89, -558, 35, -438, +168, -211, 293, 59, 374, 306, 373, 466, +280, 514, 131, 453, -37, 306, -185, 118, +-271, -59, -270, -182, -203, -238, -116, -221, +-47, -151, -1, -63, 1, 1, -58, 25, +-134, 7, -176, -61, -165, -152, -96, -227, +40, -244, 213, -192, 354, -67, 410, 108, +387, 288, 289, 421, 124, 469, -84, 412, +-296, 250, -455, 27, -520, -191, -500, -341, +-417, -409, -254, -385, -35, -273, 181, -109, +346, 40, 459, 134, 513, 167, 477, 163, +335, 134, 128, 87, -90, 42, -281, 17, +-405, 9, -451, -14, -410, -48, -298, -84, +-154, -109, -16, -125, 96, -117, 165, -75, +190, -9, 179, 63, 149, 127, 106, 183, +56, 219, 20, 226, -12, 202, -51, 150, +-92, 58, -115, -74, -122, -236, -109, -389, +-68, -491, -13, -505, 38, -401, 77, -187, +100, 106, 97, 412, 71, 656, 40, 759, +4, 689, -46, 456, -103, 110, -157, -270, +-203, -598, -224, -794, -207, -805, -150, -633, +-42, -337, 109, 20, 249, 366, 338, 633, +356, 756, 301, 717, 157, 538, -43, 268, +-230, -43, -348, -333, -363, -541, -273, -629, +-103, -589, 90, -448, 249, -237, 301, -8, +224, 184, 56, 303, -145, 358, -335, 357, +-455, 313, -443, 252, -288, 189, -47, 125, +209, 44, 424, -60, 540, -185, 519, -303, +375, -384, 166, -402, -56, -343, -240, -202, +-358, -4, -391, 194, -336, 328, -230, 368, +-129, 324, -72, 212, -43, 70, -26, -62, +-9, -136, 22, -141, 88, -85, 178, -9, +259, 54, 300, 86, 287, 79, 224, 29, +106, -58, -64, -152, -253, -224, -396, -264, +-462, -279, -442, -248, -342, -163, -174, -24, +28, 143, 224, 312, 389, 457, 486, 545, +489, 541, 397, 431, 224, 235, -14, -14, +-257, -265, -434, -469, -504, -583, -474, -596, +-354, -518, -157, -381, 78, -207, 262, -21, +339, 146, 319, 275, 227, 367, 93, 428, +-59, 438, -165, 390, -169, 286, -88, 151, +10, 0, 89, -141, 143, -249, 148, -299, +76, -284, -59, -221, -184, -143, -252, -84, +-260, -43, -216, -26, -116, -26, 33, -35, +185, -25, 277, 19, 302, 82, 273, 148, +184, 199, 37, 223, -126, 214, -254, 172, +-330, 96, -340, 4, -280, -90, -147, -177, +16, -255, 158, -302, 238, -301, 244, -254, +193, -163, 104, -31, 1, 128, -77, 274, +-94, 364, -52, 376, 23, 326, 92, 215, +124, 65, 99, -91, 15, -209, -114, -272, +-248, -291, -324, -273, -308, -230, -229, -172, +-120, -116, 17, -62, 162, -5, 259, 67, +274, 154, 245, 242, 211, 310, 170, 345, +109, 342, 43, 290, -7, 178, -56, 14, +-130, -173, -233, -352, -315, -492, -339, -576, +-303, -571, -218, -454, -64, -235, 138, 47, +323, 345, 434, 592, 452, 727, 379, 714, +219, 549, 6, 277, -221, -45, -405, -340, +-495, -549, -455, -631, -304, -584, -80, -431, +164, -224, 366, -12, 471, 163, 452, 273, +315, 324, 101, 322, -120, 277, -301, 192, +-395, 84, -371, -31, -224, -124, -19, -181, +169, -194, 296, -152, 329, -57, 251, 58, +81, 143, -118, 167, -296, 114, -393, 2, +-377, -144, -250, -273, -48, -330, 189, -281, +401, -140, 509, 49, 482, 235, 342, 363, +123, 385, -146, 290, -388, 115, -531, -86, +-536, -253, -423, -350, -222, -344, 18, -244, +248, -84, 401, 85, 437, 228, 364, 320, +218, 338, 50, 284, -101, 171, -194, 25, +-215, -134, -172, -274, -98, -376, -16, -417, +43, -391, 58, -288, 26, -126, -42, 46, +-117, 194, -162, 299, -144, 354, -73, 345, +28, 286, 137, 198, 244, 116, 320, 50, +343, -3, 294, -58, 177, -121, 22, -198, +-139, -287, -281, -360, -368, -394, -360, -369, +-274, -279, -156, -123, -29, 68, 103, 259, +192, 412, 204, 500, 164, 494, 117, 392, +81, 224, 64, 28, 77, -162, 105, -326, +128, -434, 114, -471, 51, -424, -55, -313, +-163, -161, -245, 6, -273, 173, -223, 318, +-101, 415, 50, 448, 180, 404, 262, 283, +262, 96, 178, -119, 44, -330, -88, -497, +-195, -585, -248, -552, -222, -392, -127, -136, +-10, 157, 89, 422, 160, 592, 195, 608, +191, 469, 155, 222, 110, -56, 77, -300, +56, -441, 20, -443, -27, -314, -74, -119, +-138, 58, -220, 152, -289, 135, -298, 31, +-245, -112, -144, -220, -2, -240, 169, -142, +321, 48, 413, 272, 432, 448, 383, 507, +269, 418, 107, 208, -74, -61, -228, -314, +-310, -481, -326, -524, -296, -441, -224, -288, +-113, -114, -8, 23, 63, 92, 115, 93, +161, 58, 193, 31, 205, 43, 208, 117, +202, 231, 177, 352, 112, 424, 19, 407, +-71, 282, -148, 72, -216, -194, -245, -463, +-201, -663, -91, -735, 37, -663, 147, -470, +231, -188, 266, 122, 244, 397, 171, 573, +69, 626, -43, 546, -141, 355, -205, 110, +-221, -126, -189, -304, -112, -389, -2, -375, +106, -281, 190, -126, 243, 39, 271, 173, +258, 240, 191, 227, 79, 142, -39, 6, +-142, -154, -227, -295, -285, -382, -282, -396, +-212, -325, -109, -178, 7, 21, 127, 229, +237, 404, 293, 497, 278, 495, 214, 402, +127, 244, 27, 46, -75, -161, -144, -334, +-150, -445, -110, -486, -60, -476, 1, -423, +62, -331, 92, -200, 70, -43, 20, 134, +-43, 312, -97, 465, -114, 556, -79, 551, +-7, 443, 77, 246, 175, -7, 255, -265, +283, -464, 251, -566, 183, -546, 92, -422, +-14, -237, -122, -42, -200, 115, -225, 208, +-208, 229, -170, 191, -120, 115, -38, 41, +62, -15, 148, -43, 201, -41, 237, -16, +244, 20, 211, 60, 151, 96, 91, 116, +58, 98, 45, 34, 40, -57, 33, -164, +28, -265, 18, -341, -17, -353, -84, -291, +-150, -159, -203, 7, -252, 165, -270, 275, +-222, 309, -120, 268, 9, 166, 161, 50, +324, -41, 472, -83, 565, -79, 592, -41, +539, -5, 407, 2, 206, -33, -57, -111, +-351, -204, -610, -277, -768, -296, -822, -259, +-750, -168, -533, -48, -195, 77, 182, 176, +532, 246, 795, 275, 922, 264, 880, 223, +684, 160, 391, 77, 64, -23, -225, -134, +-431, -251, -522, -339, -507, -376, -403, -347, +-253, -264, -105, -133, 8, 18, 74, 154, +100, 239, 109, 249, 114, 198, 121, 104, +155, -12, 211, -121, 251, -179, 257, -177, +255, -125, 231, -42, 168, 59, 77, 152, +-12, 212, -86, 218, -152, 155, -203, 30, +-231, -135, -234, -296, -212, -423, -141, -480, +-26, -448, 122, -323, 266, -131, 370, 87, +414, 279, 389, 400, 287, 434, 142, 382, +15, 270, -72, 132, -112, 9, -116, -84, +-72, -145, -4, -186, 35, -217, 12, -259, +-49, -304, -102, -332, -132, -331, -118, -279, +-36, -168, 110, 1, 264, 179, 369, 319, +400, 384, 345, 368, 195, 267, -6, 99, +-187, -98, -300, -266, -325, -353, -255, -350, +-87, -256, 115, -103, 277, 72, 353, 211, +331, 283, 215, 268, 46, 167, -131, -3, +-254, -191, -279, -344, -206, -426, -72, -415, +79, -318, 219, -161, 311, 6, 321, 148, +245, 225, 126, 234, 4, 181, -82, 101, +-114, 29, -92, -9, -24, -2, 65, 30, +140, 72, 166, 88, 141, 64, 63, -9, +-42, -108, -136, -215, -178, -306, -166, -365, +-93, -373, 32, -329, 173, -251, 292, -155, +375, -45, 419, 80, 387, 201, 288, 308, +160, 376, 33, 400, -102, 368, -216, 283, +-271, 150, -268, -12, -227, -177, -157, -317, +-60, -412, 49, -466, 151, -474, 222, -442, +269, -372, 313, -275, 361, -143, 375, 17, +350, 198, 303, 368, 226, 483, 90, 512, +-92, 443, -260, 281, -376, 49, -426, -188, +-396, -372, -270, -452, -87, -424, 104, -301, +268, -137, 391, 4, 456, 76, 444, 71, +364, 2, 252, -103, 138, -190, 22, -216, +-71, -159, -126, -45, -148, 93, -161, 210, +-156, 277, -116, 267, -58, 183, 0, 51, +68, -98, 138, -232, 170, -332, 171, -381, +163, -376, 154, -308, 122, -192, 84, -37, +67, 135, 59, 299, 36, 420, 0, 464, +-31, 404, -45, 230, -37, -22, -8, -301, +62, -547, 163, -714, 257, -753, 300, -656, +277, -429, 190, -128, 56, 184, -99, 447, +-225, 617, -264, 675, -209, 618, -82, 472, +84, 260, 263, 20, 402, -217, 450, -411, +383, -553, 246, -627, 85, -624, -66, -545, +-172, -405, -210, -229, -161, -37, -37, 137, +120, 278, 249, 361, 332, 380, 356, 340, +309, 268, 178, 172, 11, 71, -124, -21, +-199, -95, -216, -145, -178, -174, -94, -194, +21, -224, 146, -254, 247, -278, 313, -288, +336, -285, 319, -248, 266, -174, 191, -66, +110, 55, 30, 162, -41, 239, -93, 265, +-119, 242, -134, 177, -128, 100, -96, 20, +-39, -43, 23, -90, 88, -119, 141, -150, +175, -192, 197, -240, 211, -288, 198, -314, +154, -302, 124, -228, 116, -101, 94, 53, +50, 191, 30, 281, 36, 292, 34, 222, +6, 88, -19, -79, -18, -234, -9, -329, +-13, -335, -30, -260, -23, -127, 14, 10, +69, 125, 131, 191, 222, 199, 314, 146, +359, 57, 349, -43, 297, -133, 204, -199, +71, -236, -61, -238, -156, -226, -198, -209, +-192, -192, -130, -163, -34, -125, 69, -71, +151, -5, 212, 68, 265, 144, 298, 211, +296, 255, 259, 254, 222, 209, 181, 112, +134, -13, 93, -139, 71, -246, 47, -330, +4, -371, -43, -362, -74, -320, -106, -263, +-145, -206, -150, -151, -102, -102, -9, -41, +120, 38, 288, 142, 454, 254, 570, 355, +601, 410, 539, 393, 376, 286, 131, 95, +-138, -142, -367, -385, -507, -579, -533, -678, +-439, -642, -242, -491, 22, -261, 275, -3, +457, 235, 539, 399, 507, 453, 373, 394, +178, 241, -19, 41, -158, -163, -207, -326, +-163, -420, -33, -422, 143, -340, 321, -190, +434, -3, 445, 175, 345, 293, 151, 326, +-87, 277, -288, 159, -390, -4, -398, -183, +-304, -330, -127, -425, 89, -452, 264, -416, +365, -327, 396, -210, 375, -75, 323, 64, +273, 191, 250, 298, 243, 366, 243, 385, +214, 329, 147, 204, 47, 20, -68, -186, +-179, -382, -252, -526, -264, -587, -207, -538, +-98, -388, 41, -184, 183, 26, 285, 195, +342, 298, 357, 312, 345, 254, 321, 148, +294, 27, 250, -78, 201, -141, 157, -160, +88, -148, -10, -126, -100, -115, -140, -112, +-141, -114, -112, -111, -38, -114, 66, -110, +149, -97, 202, -85, 233, -84, 221, -80, +162, -68, 100, -54, 77, -29, 96, 17, +140, 86, 182, 158, 205, 202, 193, 187, +139, 110, 40, -32, -65, -208, -133, -383, +-159, -521, -147, -578, -79, -527, 53, -364, +202, -128, 324, 132, 384, 358, 376, 515, +299, 565, 181, 503, 47, 345, -72, 128, +-145, -113, -153, -338, -107, -509, -33, -610, +56, -637, 134, -601, 190, -499, 221, -336, +228, -127, 203, 94, 168, 304, 131, 466, +94, 554, 57, 547, 30, 451, 25, 284, +31, 62, 63, -166, 117, -360, 164, -477, +187, -520, 211, -494, 218, -420, 185, -317, +130, -213, 88, -124, 64, -56, 31, -20, +-14, 4, -41, 29, -30, 68, -1, 117, +45, 188, 112, 264, 220, 333, 346, 377, +434, 373, 452, 288, 395, 112, 267, -142, +74, -447, -149, -742, -342, -965, -425, -1051, +-379, -970, -228, -708, 4, -298, 296, 188, +575, 654, 738, 1002, 733, 1156, 590, 1091, +356, 830, 55, 423, -235, -44, -432, -485, +-497, -818, -451, -1002, -318, -1013, -122, -880, +99, -650, 289, -371, 409, -81, 457, 177, +442, 371, 370, 492, 258, 531, 153, 494, +80, 386, 46, 238, 46, 59, 73, -120, +94, -274, 81, -375, 22, -412, -79, -386, +-191, -305, -277, -204, -300, -106, -240, -33, +-81, 10, 154, 17, 406, 0, 592, -37, +680, -67, 651, -70, 501, -40, 280, 9, +48, 55, -159, 84, -286, 87, -287, 68, +-199, 24, -84, -35, 28, -111, 138, -179, +201, -232, 170, -262, 97, -272, 59, -266, +60, -236, 81, -174, 138, -75, 238, 49, +358, 186, 430, 307, 425, 382, 356, 375, +245, 281, 100, 97, -49, -152, -163, -414, +-226, -631, -242, -746, -209, -729, -116, -570, +14, -308, 144, 1, 261, 294, 356, 528, +402, 655, 403, 655, 362, 531, 293, 318, +214, 66, 133, -180, 61, -391, -7, -548, +-61, -627, -95, -629, -110, -553, -116, -419, +-100, -246, -66, -68, -11, 94, 68, 221, +157, 299, 238, 321, 308, 292, 364, 228, +365, 140, 295, 50, 188, -31, 89, -92, +-18, -138, -116, -171, -148, -200, -100, -210, +-5, -199, 103, -184, 203, -174, 265, -169, +253, -169, 152, -185, 15, -205, -106, -222, +-174, -214, -174, -170, -97, -67, 63, 90, +261, 277, 421, 447, 502, 553, 507, 566, +424, 457, 264, 231, 60, -89, -125, -434, +-233, -741, -247, -936, -195, -980, -92, -848, +50, -571, 196, -213, 291, 160, 310, 485, +282, 706, 231, 778, 162, 708, 92, 516, +62, 257, 68, -27, 93, -278, 113, -465, +120, -574, 116, -607, 96, -558, 65, -438, +45, -283, 54, -119, 101, 33, 188, 164, +287, 256, 367, 294, 391, 263, 336, 177, +195, 55, -15, -73, -242, -182, -411, -250, +-480, -259, -428, -214, -241, -119, 36, -4, +342, 96, 598, 144, 754, 128, 774, 42, +660, -90, 445, -229, 188, -339, -61, -396, +-252, -385, -349, -296, -377, -146, -345, 47, +-267, 229, -166, 360, -58, 416, 64, 386, +191, 269, 296, 90, 360, -120, 403, -329, +430, -496, 394, -586, 296, -572, 180, -467, +70, -293, -37, -86, -117, 127, -143, 305, +-100, 420, -21, 447, 50, 384, 105, 248, +143, 67, 150, -117, 115, -283, 65, -404, +28, -467, 21, -454, 41, -377, 99, -250, +171, -105, 230, 35, 273, 146, 297, 207, +284, 216, 221, 181, 137, 110, 53, 8, +-12, -92, -58, -163, -69, -187, -45, -177, +18, -137, 107, -78, 186, -9, 225, 42, +238, 55, 233, 27, 186, -42, 111, -130, +43, -223, 2, -283, -14, -295, 7, -253, +65, -168, 135, -37, 194, 112, 239, 235, +248, 299, 205, 283, 136, 193, 64, 49, +5, -110, -42, -251, -59, -339, -34, -356, +37, -300, 120, -189, 180, -53, 197, 58, +183, 116, 155, 111, 104, 51, 47, -36, +12, -120, 11, -169, 22, -182, 45, -146, +83, -72, 139, 23, 188, 99, 203, 126, +197, 100, 180, 35, 136, -42, 55, -118, +-38, -174, -110, -203, -148, -193, -158, -154, +-110, -101, -6, -50, 123, -13, 249, 1, +352, 4, 412, 14, 407, 27, 335, 38, +219, 38, 99, 24, -10, -11, -92, -64, +-133, -136, -131, -208, -97, -271, -46, -295, +5, -257, 48, -158, 76, -21, 97, 119, +129, 235, 172, 295, 228, 291, 297, 211, +358, 74, 377, -93, 345, -244, 271, -350, +171, -384, 50, -349, -84, -268, -190, -160, +-233, -52, -210, 44, -153, 98, -69, 106, +50, 81, 184, 44, 272, 10, 304, -5, +316, 1, 306, 17, 249, 26, 162, 17, +103, -7, 85, -52, 77, -108, 54, -172, +45, -216, 48, -231, 49, -203, 32, -142, +12, -68, 10, -7, 16, 24, 12, 29, +11, 11, 34, -21, 68, -55, 102, -63, +133, -36, 180, 25, 219, 99, 233, 156, +216, 161, 171, 102, 110, -6, 46, -146, +-22, -288, -92, -400, -122, -440, -96, -394, +-40, -266, 22, -92, 98, 94, 177, 248, +238, 337, 252, 344, 236, 283, 206, 166, +161, 13, 114, -142, 58, -273, 12, -350, +-6, -368, -6, -328, -19, -251, -42, -145, +-49, -28, -26, 82, 7, 167, 52, 209, +119, 199, 202, 139, 285, 55, 348, -33, +382, -102, 370, -152, 312, -172, 211, -162, +88, -130, -40, -96, -169, -78, -286, -87, +-353, -116, -345, -140, -263, -144, -123, -115, +54, -58, 270, 28, 469, 122, 603, 204, +643, 242, 600, 223, 488, 148, 302, 30, +67, -101, -150, -214, -291, -286, -361, -318, +-367, -312, -309, -281, -181, -224, -27, -157, +109, -93, 199, -33, 260, 30, 295, 100, +300, 176, 293, 244, 278, 275, 259, 256, +228, 176, 177, 56, 110, -86, 35, -226, +-44, -338, -110, -392, -164, -372, -188, -288, +-164, -173, -106, -53, -41, 46, 17, 99, +90, 106, 177, 86, 250, 60, 293, 32, +316, 14, 309, 11, 258, 19, 165, 22, +63, 8, -22, -26, -77, -78, -103, -128, +-99, -157, -40, -154, 50, -133, 115, -102, +133, -72, 130, -51, 115, -48, 70, -54, +10, -62, -11, -57, 15, -29, 63, 24, +120, 92, 177, 142, 223, 149, 223, 100, +178, 16, 117, -93, 80, -199, 73, -274, +69, -291, 68, -238, 84, -142, 99, -32, +72, 64, 0, 126, -72, 128, -107, 85, +-113, 24, -74, -29, 18, -69, 149, -91, +273, -95, 358, -85, 392, -75, 371, -78, +304, -81, 194, -77, 63, -56, -40, -19, +-94, 40, -118, 96, -119, 125, -113, 102, +-105, 34, -100, -72, -85, -200, -44, -316, +7, -388, 88, -379, 200, -285, 321, -117, +423, 84, 482, 282, 473, 433, 376, 504, +202, 476, 2, 345, -194, 129, -362, -133, +-466, -387, -472, -594, -373, -709, -214, -704, +-22, -580, 187, -364, 384, -86, 522, 211, +571, 470, 542, 631, 453, 665, 293, 571, +91, 371, -93, 113, -219, -155, -277, -377, +-280, -516, -212, -541, -92, -464, 35, -307, +129, -123, 173, 30, 173, 120, 126, 134, +49, 83, -13, -10, -24, -106, 20, -169, +98, -158, 188, -74, 294, 62, 373, 204, +377, 314, 291, 351, 151, 299, 8, 169, +-129, -9, -233, -193, -266, -351, -221, -450, +-125, -473, -5, -413, 117, -299, 224, -157, +284, -19, 303, 100, 283, 194, 225, 254, +150, 269, 79, 233, 23, 162, -36, 63, +-71, -45, -60, -149, -24, -224, 20, -255, +69, -225, 117, -140, 154, -17, 163, 103, +152, 176, 129, 179, 93, 107, 60, -11, +19, -157, -11, -285, -26, -366, -37, -367, +-47, -283, -46, -135, -21, 41, 16, 202, +44, 309, 87, 340, 149, 306, 202, 216, +232, 91, 233, -44, 219, -158, 165, -232, +83, -253, 8, -245, -44, -217, -62, -178, +-57, -138, -35, -97, 4, -54, 43, -9, +58, 27, 35, 62, -12, 92, -51, 115, +-82, 113, -81, 85, -34, 32, 49, -29, +157, -87, 262, -129, 342, -142, 379, -126, +365, -84, 306, -32, 204, 25, 87, 68, +-17, 89, -112, 74, -192, 26, -249, -47, +-271, -127, -265, -196, -240, -249, -172, -277, +-67, -268, 74, -203, 247, -89, 422, 60, +559, 214, 631, 348, 624, 437, 526, 455, +329, 380, 81, 217, -166, -4, -378, -248, +-518, -464, -572, -610, -520, -658, -387, -611, +-204, -471, 4, -264, 211, -18, 402, 220, +541, 414, 595, 543, 571, 594, 482, 561, +333, 440, 144, 254, -44, 18, -183, -231, +-285, -456, -343, -603, -327, -654, -233, -600, +-94, -453, 39, -241, 147, -1, 227, 215, +261, 364, 243, 415, 179, 379, 106, 274, +57, 142, 22, 15, 6, -79, 12, -131, +38, -138, 66, -122, 74, -101, 82, -91, +82, -106, 57, -136, 23, -175, 5, -195, +8, -181, 15, -126, 21, -50, 41, 38, +49, 122, 31, 184, -1, 204, -33, 176, +-50, 117, -48, 36, -5, -42, 78, -102, +179, -125, 284, -122, 362, -104, 377, -90, +323, -78, 200, -77, 41, -94, -130, -119, +-276, -136, -348, -121, -335, -77, -226, -4, +-69, 77, 88, 149, 226, 186, 323, 186, +352, 143, 304, 64, 210, -37, 120, -137, +38, -204, -28, -224, -58, -199, -51, -147, +-17, -77, 5, -8, 18, 49, 30, 75, +42, 77, 56, 56, 72, 22, 105, -16, +144, -51, 156, -73, 131, -86, 78, -90, +3, -98, -89, -94, -171, -74, -181, -37, +-125, 7, -23, 56, 125, 104, 291, 140, +425, 147, 475, 106, 424, 27, 284, -76, +79, -173, -137, -245, -318, -265, -440, -230, +-467, -144, -400, -40, -255, 58, -67, 127, +133, 139, 312, 91, 428, 3, 479, -81, +465, -134, 387, -135, 273, -82, 141, 14, +3, 115, -125, 187, -225, 208, -270, 171, +-274, 80, -245, -47, -162, -176, -43, -273, +82, -315, 174, -308, 230, -261, 255, -194, +251, -109, 224, -15, 176, 76, 120, 148, +75, 204, 30, 242, -4, 255, -12, 239, +0, 186, 19, 102, 20, -9, 20, -122, +6, -223, -34, -290, -82, -323, -126, -321, +-149, -289, -137, -230, -80, -147, 36, -58, +185, 33, 337, 123, 461, 215, 513, 287, +491, 327, 368, 318, 151, 260, -106, 149, +-328, -1, -458, -159, -500, -296, -442, -386, +-276, -423, -47, -391, 190, -297, 383, -154, +497, -3, 515, 130, 426, 221, 260, 264, +56, 256, -133, 197, -257, 108, -306, 7, +-281, -82, -188, -141, -41, -156, 125, -138, +256, -92, 332, -41, 349, 3, 292, 26, +172, 15, 3, -31, -173, -97, -306, -161, +-360, -201, -312, -192, -191, -124, -12, -5, +194, 124, 375, 236, 491, 301, 519, 300, +447, 217, 269, 61, 21, -132, -204, -308, +-357, -414, -425, -428, -382, -345, -240, -183, +-21, 28, 197, 226, 348, 360, 411, 392, +385, 320, 273, 159, 84, -46, -120, -235, +-245, -359, -280, -394, -256, -344, -172, -218, +-19, -56, 164, 109, 283, 230, 320, 282, +306, 265, 249, 197, 160, 98, 47, -12, +-49, -106, -106, -171, -131, -203, -126, -214, +-91, -196, -26, -158, 50, -105, 86, -54, +100, -5, 114, 51, 126, 102, 116, 131, +83, 132, 56, 111, 25, 73, -5, 27, +-15, -28, -10, -74, 6, -107, 37, -115, +69, -100, 86, -67, 79, -26, 68, 4, +48, 14, 3, 3, -32, -18, -49, -46, +-54, -73, -65, -99, -65, -105, -24, -90, +44, -53, 107, -10, 147, 32, 162, 72, +182, 105, 189, 127, 161, 136, 121, 136, +74, 115, 13, 69, -87, -11, -176, -101, +-198, -197, -177, -284, -131, -344, -55, -351, +60, -283, 186, -154, 262, 3, 274, 151, +237, 265, 162, 315, 62, 295, -63, 212, +-158, 103, -185, -5, -152, -86, -74, -119, +32, -99, 143, -52, 201, -14, 169, -8, +93, -42, 14, -102, -54, -177, -93, -237, +-98, -260, -46, -228, 38, -148, 130, -34, +207, 85, 236, 179, 220, 232, 151, 238, +43, 215, -63, 174, -132, 131, -142, 85, +-110, 40, -55, -7, 29, -60, 111, -130, +160, -211, 148, -294, 89, -360, 33, -374, +-17, -328, -61, -220, -97, -75, -100, 88, +-46, 236, 35, 344, 110, 387, 170, 365, +200, 282, 195, 160, 141, 35, 62, -70, +-3, -142, -59, -186, -101, -199, -134, -197, +-126, -195, -69, -199, 1, -200, 57, -194, +95, -179, 126, -140, 141, -68, 115, 35, +82, 136, 71, 216, 62, 268, 50, 297, +47, 287, 66, 240, 64, 161, 21, 66, +-29, -34, -76, -131, -120, -219, -161, -295, +-187, -351, -163, -386, -85, -381, 31, -326, +149, -216, 235, -73, 299, 88, 311, 247, +262, 380, 186, 460, 101, 468, 15, 394, +-79, 254, -149, 76, -179, -112, -179, -267, +-156, -371, -125, -405, -98, -378, -56, -301, +4, -195, 85, -81, 162, 11, 232, 67, +301, 99, 333, 119, 312, 138, 230, 147, +103, 148, -37, 143, -162, 126, -253, 79, +-300, 9, -295, -71, -235, -139, -156, -176, +-57, -178, 71, -136, 184, -68, 251, 5, +261, 46, 245, 51, 205, 18, 139, -40, +74, -108, 11, -157, -48, -158, -84, -103, +-88, -4, -55, 112, -4, 217, 43, 269, +73, 257, 69, 176, 45, 53, -19, -89, +-111, -219, -161, -304, -148, -318, -87, -258, +0, -147, 116, -15, 243, 103, 318, 189, +327, 219, 284, 195, 176, 114, 16, 8, +-167, -98, -307, -173, -369, -200, -348, -169, +-251, -92, -112, -3, 41, 78, 177, 135, +271, 157, 323, 129, 323, 69, 266, -14, +169, -88, 57, -134, -43, -153, -141, -149, +-213, -125, -224, -86, -180, -40, -98, 10, +-5, 60, 99, 111, 200, 145, 257, 164, +265, 157, 226, 121, 133, 49, 0, -55, +-147, -167, -257, -258, -301, -301, -279, -291, +-189, -223, -67, -110, 72, 30, 193, 165, +278, 270, 324, 318, 322, 303, 271, 227, +176, 116, 69, 3, -31, -101, -138, -185, +-237, -249, -294, -272, -316, -257, -296, -211, +-233, -150, -105, -74, 67, 9, 236, 93, +384, 163, 475, 212, 474, 232, 379, 202, +213, 132, 19, 38, -164, -51, -307, -121, +-374, -163, -364, -174, -269, -143, -126, -79, +20, -8, 153, 40, 236, 57, 244, 52, +177, 24, 75, -13, -22, -52, -109, -77, +-166, -91, -166, -87, -117, -72, -18, -40, +105, 2, 227, 46, 323, 88, 358, 128, +323, 169, 200, 183, 18, 157, -174, 88, +-348, -7, -467, -120, -490, -222, -415, -288, +-259, -291, -53, -235, 188, -132, 408, 1, +542, 127, 583, 210, 520, 219, 364, 163, +145, 69, -75, -27, -249, -103, -371, -135, +-427, -113, -414, -41, -350, 57, -237, 143, +-101, 189, 33, 176, 154, 111, 245, 8, +298, -99, 287, -189, 242, -238, 186, -247, +110, -216, 33, -153, -29, -72, -69, 5, +-92, 58, -90, 96, -49, 122, -4, 146, +10, 163, 0, 177, -36, 175, -85, 155, +-136, 106, -154, 32, -114, -54, -40, -145, +51, -224, 138, -273, 218, -270, 282, -216, +291, -122, 243, -23, 166, 68, 68, 133, +-54, 164, -190, 154, -293, 110, -345, 50, +-360, -7, -322, -37, -234, -38, -106, -11, +44, 27, 211, 60, 373, 80, 483, 87, +509, 67, 442, 24, 281, -33, 66, -91, +-162, -143, -361, -179, -479, -192, -501, -184, +-420, -152, -266, -105, -58, -31, 167, 62, +334, 164, 413, 244, 411, 289, 326, 297, +173, 260, -10, 173, -161, 41, -260, -105, +-308, -233, -278, -317, -183, -348, -52, -312, +66, -218, 156, -83, 221, 59, 226, 181, +162, 263, 54, 287, -59, 251, -139, 157, +-184, 40, -187, -76, -129, -165, -31, -222, +77, -224, 160, -172, 218, -77, 243, 31, +200, 130, 99, 204, -27, 231, -138, 199, +-214, 109, -256, -8, -249, -133, -186, -239, +-87, -297, 34, -271, 141, -163, 224, -6, +278, 155, 289, 288, 256, 364, 167, 351, +44, 250, -97, 77, -235, -112, -337, -281, +-387, -386, -376, -407, -299, -338, -170, -198, +-4, -26, 170, 142, 332, 279, 441, 367, +450, 387, 377, 337, 253, 232, 104, 98, +-59, -46, -204, -186, -293, -305, -337, -372, +-342, -367, -293, -292, -203, -165, -87, -11, +33, 141, 134, 252, 221, 301, 272, 282, +281, 211, 231, 101, 150, -20, 68, -116, +-26, -154, -128, -133, -204, -79, -223, -13, +-189, 43, -130, 79, -48, 79, 41, 50, +88, 2, 85, -46, 40, -86, -13, -109, +-54, -111, -82, -91, -86, -57, -61, -18, +7, 35, 97, 96, 169, 164, 219, 213, +239, 229, 204, 201, 114, 127, -18, 16, +-154, -111, -275, -231, -353, -312, -359, -328, +-305, -264, -189, -132, -33, 31, 131, 190, +272, 307, 369, 361, 401, 332, 338, 230, +191, 80, 17, -82, -149, -218, -274, -299, +-330, -310, -317, -257, -239, -152, -132, -28, +-14, 97, 84, 192, 145, 250, 172, 254, +149, 214, 87, 145, 28, 68, -7, -5, +-26, -73, -38, -131, -30, -173, 3, -185, +23, -173, 15, -129, -13, -62, -29, 20, +-19, 94, -12, 148, -13, 175, -12, 166, +-11, 122, -22, 46, -50, -33, -61, -87, +-47, -102, -43, -88, -50, -47, -40, 11, +5, 71, 53, 109, 78, 112, 86, 77, +81, 19, 63, -45, 28, -95, -9, -109, +-30, -97, -47, -62, -73, -21, -100, 23, +-126, 62, -138, 87, -140, 84, -118, 61, +-47, 35, 55, 16, 164, 5, 248, -5, +289, -6, 275, -5, 194, -1, 63, 0, +-98, 7, -258, 19, -364, 35, -390, 44, +-329, 48, -205, 56, -52, 55, 104, 28, +205, -29, 235, -87, 220, -137, 189, -166, +134, -168, 51, -134, -17, -60, -42, 49, +-56, 172, -80, 275, -110, 332, -133, 321, +-151, 245, -179, 120, -184, -15, -141, -135, +-41, -223, 76, -269, 168, -257, 233, -201, +256, -128, 212, -60, 112, -7, 1, 38, +-84, 75, -143, 116, -177, 155, -166, 195, +-125, 221, -69, 227, -16, 197, 16, 134, +23, 42, -7, -69, -56, -171, -95, -239, +-97, -252, -50, -214, 20, -144, 88, -64, +145, 24, 166, 98, 151, 149, 101, 168, +32, 159, -48, 134, -132, 103, -187, 73, +-205, 47, -182, 33, -119, 19, -39, -4, +20, -40, 50, -83, 59, -130, 51, -166, +28, -175, 22, -141, 42, -61, 63, 43, +81, 149, 88, 229, 81, 274, 52, 272, +-3, 223, -80, 132, -171, 17, -245, -97, +-274, -175, -253, -204, -179, -190, -70, -142, +50, -84, 153, -35, 214, -8, 234, 4, +211, 11, 157, 27, 79, 61, -15, 120, +-98, 197, -156, 269, -190, 302, -200, 270, +-176, 172, -123, 25, -63, -135, -18, -275, +22, -366, 55, -388, 82, -327, 99, -195, +108, -19, 106, 155, 78, 282, 36, 339, +-10, 321, -63, 248, -118, 146, -163, 36, +-178, -67, -150, -130, -92, -145, -16, -106, +53, -37, 104, 36, 123, 89, 98, 114, +51, 110, -9, 65, -80, -6, -148, -80, +-187, -135, -178, -165, -130, -155, -50, -112, +55, -43, 150, 35, 211, 113, 227, 191, +204, 258, 140, 290, 27, 266, -109, 194, +-233, 88, -317, -27, -353, -136, -328, -214, +-238, -247, -105, -234, 36, -189, 167, -120, +269, -32, 320, 61, 313, 143, 250, 199, +156, 237, 30, 247, -111, 215, -237, 135, +-319, 34, -349, -63, -338, -136, -285, -180, +-191, -190, -80, -158, 29, -91, 134, 0, +228, 91, 294, 168, 304, 211, 260, 224, +175, 199, 70, 139, -43, 60, -160, -24, +-262, -107, -337, -173, -369, -199, -343, -184, +-257, -136, -123, -73, 35, 2, 184, 79, +300, 151, 355, 202, 335, 229, 244, 230, +111, 203, -39, 147, -189, 69, -306, -13, +-363, -96, -359, -168, -297, -218, -177, -223, +-22, -185, 124, -115, 219, -27, 258, 71, +242, 163, 185, 231, 98, 255, -21, 231, +-138, 162, -223, 64, -254, -31, -230, -106, +-155, -139, -47, -129, 50, -82, 111, -16, +135, 53, 126, 108, 93, 129, 40, 110, +-30, 64, -98, 13, -154, -35, -181, -70, +-183, -92, -157, -92, -95, -63, -9, -2, +73, 76, 134, 149, 164, 201, 156, 213, +112, 185, 43, 118, -46, 33, -153, -58, +-242, -138, -284, -193, -264, -203, -189, -165, +-69, -88, 67, 9, 164, 110, 196, 195, +168, 239, 94, 233, -3, 178, -83, 93, +-131, -1, -138, -68, -117, -95, -68, -75, +-9, -29, 39, 19, 60, 51, 35, 47, +-21, 11, -88, -47, -153, -100, -191, -120, +-177, -91, -110, -12, -15, 102, 70, 215, +136, 293, 167, 312, 144, 260, 69, 148, +-27, -1, -108, -142, -170, -232, -211, -261, +-213, -244, -173, -186, -104, -102, -21, -4, +65, 85, 136, 157, 166, 213, 147, 259, +90, 287, 19, 276, -48, 223, -124, 125, +-194, -1, -236, -141, -241, -254, -207, -311, +-134, -294, -27, -210, 92, -81, 188, 66, +240, 196, 238, 276, 179, 286, 79, 239, +-47, 151, -170, 50, -266, -44, -313, -99, +-317, -103, -282, -66, -202, -17, -84, 30, +50, 74, 166, 105, 243, 111, 270, 85, +232, 37, 141, -24, 35, -79, -80, -116, +-197, -127, -294, -102, -344, -40, -326, 42, +-238, 131, -97, 210, 54, 252, 174, 240, +239, 171, 237, 69, 168, -31, 65, -102, +-53, -145, -165, -153, -243, -123, -263, -61, +-233, 21, -172, 94, -82, 134, 13, 133, +91, 101, 145, 47, 170, 1, 138, -21, +52, -19, -52, -3, -152, 32, -236, 73, +-280, 93, -268, 79, -200, 34, -94, -13, +22, -37, 128, -30, 191, -1, 198, 46, +158, 98, 92, 141, 15, 156, -71, 136, +-164, 74, -237, -23, -261, -124, -236, -195, +-187, -209, -124, -165, -40, -72, 33, 49, +92, 177, 145, 269, 175, 303, 148, 275, +61, 199, -52, 100, -170, -6, -265, -106, +-291, -175, -232, -182, -121, -133, -1, -52, +87, 30, 131, 89, 132, 107, 93, 94, +18, 65, -71, 32, -140, 13, -187, 11, +-207, 30, -185, 59, -126, 90, -56, 103, +7, 93, 51, 64, 68, 26, 56, -10, +30, -33, 0, -43, -41, -37, -87, -8, +-122, 35, -125, 77, -112, 93, -94, 72, +-62, 25, -16, -13, 18, -26, 21, -10, +-5, 28, -49, 64, -99, 83, -138, 84, +-155, 67, -145, 33, -103, 1, -53, -19, +-12, -15, 31, 11, 66, 51, 78, 84, +70, 97, 39, 88, -31, 60, -125, 16, +-195, -34, -217, -69, -201, -70, -153, -24, +-97, 38, -43, 99, -2, 140, 28, 147, +47, 110, 55, 46, 56, -27, 54, -74, +45, -73, 15, -44, -33, 2, -92, 48, +-153, 85, -219, 106, -276, 123, -300, 123, +-275, 92, -207, 37, -104, -27, 32, -69, +174, -74, 282, -57, 315, -32, 278, 17, +200, 85, 88, 151, -62, 189, -213, 189, +-341, 137, -449, 47, -522, -54, -518, -147, +-416, -195, -240, -184, -19, -121, 199, -22, +369, 100, 459, 204, 455, 268, 358, 285, +200, 262, 16, 216, -168, 155, -329, 64, +-429, -53, -448, -168, -403, -261, -320, -306, +-234, -290, -155, -214, -81, -100, -13, 36, +42, 166, 84, 268, 126, 335, 169, 353, +189, 323, 164, 272, 113, 210, 59, 129, +-13, 37, -107, -63, -185, -154, -245, -227, +-309, -279, -365, -314, -380, -301, -347, -226, +-283, -104, -189, 52, -59, 214, 96, 350, +251, 437, 377, 458, 436, 401, 416, 285, +291, 132, 71, -32, -184, -166, -404, -243, +-554, -266, -625, -245, -590, -180, -459, -90, +-267, 6, -49, 88, 164, 136, 328, 152, +404, 156, 382, 140, 282, 107, 123, 78, +-62, 59, -228, 42, -347, 35, -407, 40, +-398, 55, -312, 83, -172, 107, -23, 108, +98, 82, 161, 36, 146, -31, 65, -102, +-48, -161, -157, -200, -226, -198, -244, -144, +-221, -42, -162, 102, -66, 264, 34, 399, +102, 473, 140, 463, 143, 356, 88, 162, +-11, -74, -117, -301, -221, -460, -311, -505, +-358, -436, -357, -269, -317, -38, -232, 199, +-107, 378, 42, 474, 184, 477, 279, 403, +293, 288, 228, 154, 106, 10, -48, -125, +-201, -229, -316, -298, -379, -310, -393, -261, +-365, -159, -296, -21, -184, 122, -46, 229, +88, 294, 190, 320, 233, 294, 204, 222, +109, 120, -17, 4, -143, -102, -247, -168, +-301, -189, -307, -152, -288, -59, -234, 59, +-137, 162, -16, 236, 92, 257, 149, 217, +133, 136, 53, 24, -38, -92, -114, -187, +-171, -248, -210, -260, -234, -191, -252, -57, +-243, 98, -185, 239, -89, 341, 17, 390, +90, 380, 102, 314, 57, 202, -3, 82, +-51, -36, -76, -152, -84, -247, -92, -290, +-114, -284, -151, -232, -191, -139, -208, -35, +-196, 74, -173, 174, -154, 244, -136, 286, +-117, 316, -98, 313, -54, 269, 11, 196, +60, 95, 70, -33, 42, -157, -9, -245, +-60, -266, -86, -205, -99, -96, -118, 18, +-139, 130, -158, 229, -193, 279, -224, 265, +-232, 185, -221, 52, -185, -88, -130, -193, +-81, -238, -48, -198, -8, -78, 44, 70, +89, 205, 112, 293, 93, 316, 10, 275, +-111, 191, -222, 84, -284, -12, -278, -79, +-214, -127, -128, -141, -64, -108, -41, -38, +-48, 38, -65, 108, -94, 141, -149, 130, +-210, 89, -240, 29, -217, -38, -140, -86, +-30, -112, 71, -117, 129, -77, 118, 12, +40, 129, -70, 245, -152, 339, -188, 385, +-196, 384, -179, 327, -141, 205, -105, 49, +-84, -106, -77, -251, -96, -373, -141, -449, +-180, -469, -194, -400, -198, -242, -183, -31, +-135, 183, -70, 368, -8, 492, 30, 552, +37, 556, 22, 503, 7, 399, -5, 256, +-21, 90, -56, -84, -111, -239, -191, -375, +-270, -467, -328, -477, -348, -405, -318, -277, +-242, -120, -134, 28, -13, 151, 102, 272, +181, 379, 198, 446, 139, 462, 15, 429, +-128, 339, -254, 220, -348, 92, -375, -38, +-324, -143, -240, -212, -165, -256, -95, -271, +-24, -240, 31, -185, 74, -114, 96, -32, +75, 55, 25, 134, -31, 206, -95, 259, +-159, 290, -226, 308, -309, 291, -386, 230, +-417, 143, -391, 42, -315, -68, -179, -159, +-7, -215, 143, -223, 230, -181, 247, -114, +195, -39, 96, 58, -12, 166, -98, 245, +-159, 287, -220, 285, -285, 234, -333, 151, +-334, 63, -299, -22, -250, -72, -204, -90, +-176, -114, -151, -134, -110, -120, -57, -74, +-10, -11, 27, 51, 55, 98, 62, 142, +46, 184, 22, 197, -10, 186, -45, 177, +-81, 165, -134, 150, -194, 134, -242, 94, +-284, 21, -315, -63, -311, -138, -276, -185, +-246, -189, -225, -178, -187, -166, -132, -130, +-67, -56, 9, 38, 98, 147, 193, 268, +265, 394, 268, 508, 177, 553, 6, 477, +-206, 290, -402, 40, -525, -225, -563, -433, +-542, -538, -461, -534, -316, -425, -133, -227, +49, 9, 187, 239, 248, 420, 215, 495, +113, 464, -12, 364, -97, 224, -130, 64, +-160, -75, -205, -167, -240, -188, -255, -132, +-253, -31, -225, 75, -183, 156, -143, 181, +-114, 138, -102, 63, -116, -14, -130, -82, +-114, -126, -82, -138, -60, -117, -55, -48, +-65, 57, -70, 157, -57, 243, -42, 305, +-41, 325, -52, 297, -86, 223, -170, 94, +-267, -56, -321, -177, -310, -249, -251, -259, +-183, -203, -140, -106, -121, 2, -93, 110, +-45, 199, 11, 257, 52, 277, 46, 247, +-1, 175, -56, 97, -108, 35, -148, -9, +-167, -33, -187, -48, -230, -64, -277, -67, +-289, -53, -255, -34, -189, -14, -113, -2, +-57, 9, -9, 59, 31, 158, 20, 259, +-43, 317, -115, 302, -168, 211, -195, 83, +-190, -56, -162, -184, -128, -263, -81, -249, +-37, -157, -40, -24, -94, 106, -173, 184, +-252, 200, -301, 171, -288, 118, -210, 76, +-103, 82, -8, 126, 44, 184, 33, 235, +-22, 231, -101, 128, -182, -58, -237, -272, +-253, -431, -235, -457, -185, -331, -109, -80, +-26, 238, 38, 527, 54, 667, 13, 619, +-71, 409, -164, 117, -247, -156, -310, -332, +-350, -385, -371, -316, -348, -169, -251, -22, +-91, 88, 81, 155, 222, 183, 285, 181, +235, 180, 87, 183, -100, 192, -292, 183, +-446, 125, -524, 25, -509, -76, -395, -149, +-205, -183, -3, -154, 142, -70, 208, 45, +182, 161, 67, 233, -91, 227, -239, 159, +-339, 52, -361, -49, -310, -82, -230, -35, +-148, 58, -64, 150, 19, 204, 79, 194, +96, 130, 54, 26, -32, -89, -133, -169, +-231, -177, -305, -122, -328, -18, -304, 115, +-258, 233, -208, 302, -169, 289, -143, 180, +-121, 20, -91, -115, -62, -194, -26, -200, +27, -137, 54, -25, 33, 114, -13, 259, +-56, 371, -87, 400, -119, 328, -171, 166, +-245, -36, -312, -209, -344, -314, -353, -338, +-336, -261, -287, -102, -228, 83, -174, 225, +-105, 265, -8, 204, 102, 116, 198, 78, +236, 98, 197, 154, 98, 194, -34, 178, +-173, 105, -289, 11, -378, -65, -441, -90, +-460, -53, -429, 12, -361, 66, -253, 75, +-106, 21, 27, -92, 102, -197, 110, -235, +71, -160, 21, 23, -16, 238, -56, 403, +-112, 481, -165, 457, -193, 332, -191, 146, +-157, -55, -114, -222, -97, -315, -114, -308, +-169, -208, -256, -48, -320, 107, -305, 201, +-238, 217, -175, 171, -121, 87, -47, -3, +52, -58, 146, -57, 193, 5, 168, 97, +76, 180, -86, 234, -297, 249, -478, 195, +-554, 66, -521, -96, -410, -223, -249, -253, +-69, -171, 86, -14, 187, 157, 219, 299, +179, 355, 78, 294, -47, 139, -155, -52, +-219, -209, -243, -268, -239, -203, -214, -41, +-201, 151, -230, 286, -286, 316, -338, 250, +-368, 116, -345, -62, -235, -215, -66, -266, +112, -183, 260, -2, 343, 197, 345, 331, +263, 367, 103, 321, -111, 209, -329, 78, +-506, -32, -617, -111, -630, -168, -539, -199, +-395, -204, -233, -190, -69, -149, 59, -83, +120, 17, 126, 154, 109, 298, 88, 392, +75, 419, 68, 376, 58, 280, 25, 162, +-60, 50, -189, -48, -304, -131, -373, -203, +-409, -272, -408, -315, -353, -306, -253, -234, +-148, -100, -70, 88, -34, 279, -34, 418, +-47, 456, -55, 372, -40, 207, 7, 35, +63, -79, 96, -103, 91, -32, 37, 94, +-53, 197, -148, 206, -233, 93, -329, -108, +-411, -298, -422, -386, -366, -325, -302, -124, +-264, 133, -234, 341, -180, 412, -68, 322, +105, 121, 293, -65, 421, -136, 423, -59, +260, 125, -18, 315, -311, 397, -545, 317, +-652, 96, -600, -184, -433, -401, -233, -464, +-57, -337, 49, -71, 68, 228, 17, 417, +-50, 413, -94, 232, -110, -29, -103, -243, +-73, -311, -3, -200, 77, 50, 93, 351, +13, 570, -129, 601, -294, 418, -410, 83, +-419, -288, -326, -552, -178, -602, -34, -416, +38, -70, 3, 276, -101, 472, -201, 458, +-229, 275, -170, 10, -72, -203, -3, -264, +21, -152, 16, 68, -6, 287, -5, 404, +37, 377, 57, 231, -25, 27, -203, -146, +-392, -230, -510, -229, -520, -187, -426, -125, +-265, -45, -98, 50, 18, 145, 65, 220, +94, 261, 151, 261, 209, 213, 216, 112, +141, -16, -20, -133, -209, -186, -342, -151, +-377, -40, -338, 104, -288, 217, -275, 233, +-282, 138, -254, -13, -163, -139, -34, -172, +74, -78, 104, 106, 34, 277, -75, 350, +-142, 274, -132, 67, -55, -170, 43, -306, +91, -283, 46, -118, -61, 116, -181, 299, +-282, 343, -342, 233, -355, 33, -348, -157, +-324, -240, -264, -176, -160, 4, -22, 216, +111, 357, 184, 350, 185, 203, 126, 11, +21, -135, -106, -187, -210, -158, -244, -88, +-220, -8, -171, 71, -129, 129, -118, 141, +-145, 109, -202, 64, -267, 38, -292, 42, +-262, 67, -207, 60, -120, 2, 16, -68, +169, -90, 272, -35, 254, 92, 98, 225, +-120, 296, -278, 281, -316, 183, -283, 34, +-231, -115, -180, -203, -166, -200, -178, -110, +-184, 1, -178, 59, -162, 23, -138, -78, +-107, -157, -34, -129, 88, 32, 186, 270, +176, 491, 57, 581, -104, 492, -238, 266, +-280, -8, -233, -247, -173, -377, -157, -386, +-173, -288, -189, -123, -183, 24, -165, 92, +-152, 74, -126, -3, -68, -71, 4, -38, +67, 116, 107, 335, 68, 505, -57, 523, +-186, 368, -232, 127, -180, -105, -92, -276, +-65, -349, -140, -321, -243, -225, -269, -101, +-195, 11, -80, 67, -7, 69, -25, 61, +-90, 99, -123, 206, -107, 332, -69, 377, +-21, 280, 8, 89, -14, -95, -62, -203, +-107, -230, -142, -197, -176, -133, -201, -27, +-200, 106, -162, 200, -107, 218, -65, 162, +-50, 61, -56, -7, -86, 5, -145, 48, +-197, 75, -204, 65, -144, 29, -23, -2, +118, -9, 204, -21, 172, -56, 20, -72, +-188, -46, -366, 15, -455, 89, -428, 154, +-294, 192, -113, 210, 28, 190, 93, 120, +87, 22, 28, -83, -48, -162, -89, -174, +-84, -120, -54, -5, -14, 142, 18, 255, +8, 284, -72, 201, -190, 24, -305, -184, +-359, -317, -336, -308, -268, -179, -178, 2, +-85, 178, 3, 316, 95, 400, 173, 411, +189, 338, 123, 211, 9, 59, -85, -66, +-157, -140, -233, -203, -297, -278, -331, -338, +-322, -359, -249, -282, -124, -78, 12, 165, +100, 347, 104, 434, 58, 443, -16, 373, +-121, 251, -234, 117, -309, -19, -309, -134, +-217, -179, -52, -169, 128, -144, 238, -94, +238, -27, 177, 43, 89, 110, -32, 149, +-215, 111, -462, 13, -671, -75, -729, -118, +-609, -115, -327, -52, 48, 54, 370, 164, +510, 268, 468, 319, 350, 287, 211, 196, +58, 85, -96, -13, -262, -84, -424, -137, +-528, -161, -550, -164, -477, -156, -322, -131, +-146, -99, 11, -47, 144, 43, 243, 176, +271, 315, 217, 382, 106, 334, -61, 196, +-258, 12, -402, -126, -422, -180, -307, -184, +-103, -136, 109, -48, 249, 45, 257, 108, +135, 133, -56, 108, -237, 53, -361, 34, +-403, 73, -359, 101, -261, 82, -161, 6, +-70, -111, 20, -167, 72, -136, 77, -57, +63, 57, 54, 173, 65, 240, 70, 260, +21, 222, -75, 123, -200, -11, -335, -134, +-398, -179, -325, -133, -155, -39, -11, 33, +59, 58, 79, 62, 37, 72, -48, 90, +-124, 108, -183, 96, -194, 57, -135, 4, +-33, -56, 62, -67, 67, -25, -58, 25, +-232, 75, -321, 92, -256, 54, -96, -2, +64, -52, 168, -52, 184, 32, 125, 160, +25, 262, -127, 277, -298, 189, -423, 15, +-438, -178, -309, -296, -82, -296, 106, -197, +150, -48, 69, 57, -50, 94, -126, 132, +-117, 190, -55, 254, -12, 296, -18, 277, +-51, 182, -64, 42, -40, -92, -15, -195, +-66, -259, -196, -264, -302, -238, -285, -166, +-137, 0, 55, 187, 172, 326, 144, 404, +-14, 380, -206, 243, -297, 60, -246, -133, +-159, -265, -140, -286, -166, -219, -168, -110, +-104, 10, 33, 94, 183, 114, 281, 134, +286, 195, 180, 259, -12, 280, -220, 225, +-383, 74, -477, -88, -479, -214, -372, -299, +-227, -296, -120, -210, -41, -79, 43, 92, +142, 268, 213, 369, 216, 356, 166, 232, +73, 76, -39, -36, -119, -81, -178, -84, +-253, -84, -353, -100, -446, -135, -450, -146, +-296, -101, -15, -5, 246, 134, 357, 270, +291, 333, 111, 324, -74, 218, -170, 23, +-172, -147, -145, -227, -172, -216, -287, -118, +-404, -5, -397, 21, -216, -20, 50, -64, +254, -48, 316, 77, 266, 277, 154, 417, +-5, 408, -164, 255, -268, -23, -337, -307, +-393, -444, -389, -403, -295, -218, -128, 51, +72, 260, 250, 349, 341, 342, 301, 246, +101, 92, -165, -49, -318, -134, -313, -160, +-240, -124, -173, -50, -159, 6, -221, 12, +-279, -6, -216, -38, -17, -34, 215, 56, +340, 193, 268, 301, 78, 349, -81, 309, +-183, 145, -217, -97, -181, -294, -136, -370, +-128, -332, -173, -208, -247, -81, -267, 13, +-189, 114, -50, 227, 55, 320, 84, 362, +57, 312, -11, 172, -45, -3, -6, -155, +35, -231, -1, -236, -122, -189, -249, -89, +-270, 48, -160, 151, 8, 170, 113, 131, +77, 77, -61, 58, -197, 101, -231, 146, +-147, 114, -49, 30, -42, -68, -107, -154, +-183, -205, -225, -226, -178, -206, -52, -123, +66, 15, 134, 187, 171, 353, 142, 433, +31, 405, -87, 285, -170, 102, -239, -89, +-246, -218, -181, -269, -107, -241, -62, -134, +-67, -47, -103, -62, -121, -108, -106, -83, +-82, 6, -68, 140, -64, 253, -37, 267, +30, 206, 89, 142, 62, 66, -38, -30, +-142, -105, -209, -146, -160, -104, -34, 43, +11, 182, -43, 204, -107, 138, -129, 37, +-76, -32, -4, -36, -24, -55, -128, -138, +-187, -187, -154, -152, -91, -84, -35, -24, +-64, -22, -198, -77, -267, -54, -152, 141, +67, 392, 253, 548, 273, 527, 122, 332, +-63, 92, -169, -79, -140, -192, -53, -296, +-71, -382, -202, -393, -286, -300, -259, -154, +-191, -16, -142, 72, -132, 119, -152, 167, +-132, 234, -16, 288, 131, 262, 218, 157, +180, 41, 25, -28, -74, -35, -1, 2, +90, 29, 62, 54, -107, 87, -363, 96, +-529, 58, -475, -17, -242, -108, 12, -202, +122, -255, 72, -239, 14, -178, 55, -86, +116, 32, 68, 124, -64, 207, -193, 298, +-242, 340, -171, 328, -75, 257, -14, 79, +17, -123, -23, -200, -103, -146, -119, -12, +-85, 121, -53, 140, -23, 24, 16, -111, +33, -195, 10, -221, -71, -187, -214, -144, +-303, -90, -276, 31, -221, 149, -180, 177, +-142, 137, -83, 64, 78, 83, 297, 276, +431, 491, 396, 553, 157, 395, -196, 33, +-433, -379, -435, -647, -326, -717, -250, -599, +-246, -330, -278, 18, -247, 326, -64, 493, +187, 479, 374, 317, 430, 112, 267, -18, +-46, 1, -256, 90, -294, 90, -274, -20, +-240, -147, -202, -238, -158, -219, -104, -99, +-75, 29, -89, 147, -100, 211, -28, 166, +126, 94, 272, 72, 325, 67, 212, 35, +-57, -45, -349, -125, -535, -179, -521, -196, +-336, -126, -139, 22, -11, 150, 67, 192, +126, 167, 176, 124, 180, 109, 98, 106, +-62, 59, -237, -28, -311, -73, -236, -96, +-64, -111, 74, -66, 65, -1, -46, 82, +-109, 205, -85, 238, -41, 130, 15, -36, +87, -225, 50, -304, -144, -175, -348, 24, +-454, 128, -444, 109, -293, 8, -21, -76, +262, -20, 428, 134, 404, 243, 196, 281, +-53, 267, -179, 168, -188, 49, -183, -56, +-209, -164, -267, -231, -297, -235, -228, -198, +-88, -137, 53, -77, 120, -12, 85, 69, +-25, 137, -134, 179, -175, 142, -112, 69, +-11, 62, 56, 120, 78, 205, 1, 259, +-161, 208, -244, 55, -142, -145, 44, -288, +146, -286, 87, -202, -117, -116, -374, -57, +-475, -32, -291, -21, 76, 14, 389, 131, +402, 297, 84, 398, -298, 371, -453, 182, +-291, -88, 22, -264, 197, -330, 104, -293, +-177, -138, -410, 47, -371, 172, -78, 216, +212, 182, 288, 88, 154, -60, -50, -167, +-126, -127, -16, -5, 70, 134, -28, 231, +-197, 232, -333, 142, -370, -8, -242, -167, +-54, -293, 16, -342, -25, -225, -51, 25, +-40, 261, -4, 414, 74, 385, 121, 164, +90, -60, 51, -141, -2, -115, -110, -65, +-243, 7, -314, 49, -251, -37, -115, -135, +4, -145, 94, -112, 74, 38, -83, 239, +-183, 299, -143, 233, -56, 83, 12, -103, +0, -177, -118, -127, -204, -45, -92, 7, +142, -16, 291, -53, 258, -16, 6, 82, +-365, 156, -522, 186, -389, 170, -193, 60, +-24, -51, 51, -95, -18, -160, -51, -152, +87, -24, 274, 49, 305, 91, 132, 129, +-98, 82, -287, 18, -368, -11, -284, -46, +-142, -45, -96, 10, -175, 86, -245, 145, +-184, 157, -55, 104, 58, -68, 130, -249, +128, -273, 106, -136, 85, 82, 62, 273, +85, 322, 107, 220, 8, 43, -189, -90, +-359, -147, -421, -144, -350, -37, -183, 34, +-27, -3, 40, -18, 31, -43, -26, -102, +-99, -57, -136, 62, -124, 173, -64, 256, +46, 252, 175, 143, 286, -26, 318, -138, +209, -154, 27, -130, -166, -85, -369, -58, +-494, -90, -480, -98, -372, -21, -205, 138, +-17, 312, 110, 376, 109, 305, 34, 84, +-25, -202, -28, -343, 88, -309, 219, -190, +174, -19, 10, 107, -136, 123, -170, 57, +-34, -1, 76, 20, -23, 79, -233, 177, +-406, 263, -419, 222, -234, 118, 38, 4, +209, -178, 146, -308, -73, -307, -253, -231, +-256, -78, -56, 93, 187, 182, 309, 184, +286, 162, 90, 132, -156, 121, -225, 146, +-134, 94, -43, -97, -55, -257, -207, -301, +-415, -244, -484, -37, -279, 187, 127, 281, +435, 302, 426, 277, 150, 204, -202, 123, +-392, -4, -286, -191, -38, -385, 116, -478, +104, -393, -10, -196, -122, 16, -134, 206, +-14, 337, 124, 394, 156, 442, 63, 486, +-176, 389, -458, 102, -537, -211, -370, -486, +-108, -678, 137, -606, 260, -327, 210, -23, +91, 301, 60, 537, 132, 507, 211, 322, +169, 106, -38, -126, -304, -230, -506, -100, +-565, 78, -440, 112, -206, 42, 33, -109, +208, -289, 250, -297, 190, -104, 110, 119, +75, 287, 82, 327, 87, 219, 41, 78, +-103, -32, -296, -124, -407, -162, -348, -127, +-133, -54, 79, 48, 107, 155, -9, 187, +-141, 58, -180, -162, -24, -284, 245, -185, +344, 73, 155, 279, -185, 299, -474, 176, +-472, -33, -125, -217, 252, -189, 339, -6, +149, 128, -148, 126, -330, 34, -232, -59, +49, -73, 203, -14, 56, 61, -234, 160, +-405, 259, -322, 199, -44, -50, 191, -260, +209, -342, 93, -322, -8, -122, -41, 159, +-26, 261, -10, 150, -47, -24, -147, -95, +-168, 20, -24, 226, 79, 372, -11, 369, +-144, 215, -216, -58, -216, -340, -106, -444, +14, -345, 28, -150, -43, 99, -123, 283, +-80, 272, 110, 69, 270, -246, 258, -411, +82, -271, -121, 16, -269, 303, -331, 521, +-230, 519, -60, 264, 44, -60, 79, -217, +11, -154, -109, 4, -201, 121, -250, 76, +-155, -117, 36, -337, 157, -475, 215, -394, +208, -91, 103, 211, -26, 370, -138, 356, +-223, 222, -219, 88, -117, -33, -31, -57, +-54, 81, -111, 222, -149, 254, -135, 160, +33, -77, 266, -323, 319, -427, 160, -365, +-130, -198, -421, -14, -471, 141, -245, 218, +58, 249, 273, 263, 290, 168, 84, 0, +-167, -124, -234, -193, -94, -106, 80, 126, +152, 252, 78, 183, -122, 0, -295, -179, +-297, -259, -113, -168, 80, 75, 81, 263, +-59, 249, -174, 102, -157, -151, 38, -354, +284, -309, 376, -131, 235, 90, -65, 305, +-328, 352, -421, 220, -336, 70, -146, -13, +30, -47, 136, -79, 120, -83, -4, -70, +-76, -85, -68, -103, -25, -120, 56, -100, +84, -28, 53, 52, 24, 170, -29, 287, +-89, 299, -165, 223, -291, 66, -342, -87, +-205, -151, 67, -213, 298, -234, 339, -183, +211, -133, 13, -31, -140, 83, -162, 103, +-123, 119, -107, 128, -136, 93, -215, 112, +-202, 182, -36, 203, 70, 141, 51, 23, +16, -165, 15, -345, 60, -362, 130, -258, +203, -86, 219, 195, 75, 403, -126, 396, +-236, 193, -298, -152, -373, -379, -434, -361, +-361, -222, -129, 55, 128, 366, 338, 436, +468, 309, 441, 119, 249, -102, -14, -230, +-152, -196, -93, -110, -42, -15, -137, 110, +-306, 116, -453, -41, -479, -125, -257, -109, +148, -133, 429, -114, 382, -52, 107, -15, +-143, 53, -199, 145, -55, 248, 164, 345, +247, 338, 96, 244, -164, 155, -335, 45, +-274, -117, -26, -307, 192, -448, 215, -510, +44, -469, -206, -314, -361, -114, -306, 120, +-91, 346, 135, 432, 223, 425, 122, 423, +-74, 355, -169, 260, -66, 193, 164, 78, +373, -122, 376, -354, 111, -517, -234, -502, +-428, -319, -448, -145, -337, -99, -115, -126, +55, -136, 47, -43, -27, 223, -77, 521, +-72, 696, 51, 711, 257, 473, 417, 65, +411, -257, 206, -455, -117, -538, -386, -442, +-444, -264, -278, -73, -26, 111, 141, 174, +98, 114, -151, 56, -399, -24, -376, -143, +-48, -131, 323, 50, 457, 236, 301, 314, +6, 229, -245, 15, -245, -114, 25, -74, +241, 48, 202, 174, 14, 203, -180, 73, +-241, -125, -127, -273, 22, -334, 56, -337, +-68, -306, -202, -193, -207, 0, -139, 197, +-58, 334, -1, 393, 1, 368, 45, 293, +188, 201, 354, 55, 407, -146, 263, -291, +19, -271, -224, -145, -392, -57, -386, -87, +-281, -188, -169, -278, -31, -211, 32, 86, +-25, 442, -46, 648, 30, 575, 145, 199, +244, -270, 285, -560, 244, -649, 92, -516, +-126, -105, -260, 391, -278, 630, -243, 503, +-192, 168, -128, -184, -31, -377, 67, -319, +168, -47, 256, 302, 229, 483, 102, 316, +-64, -64, -251, -440, -269, -700, -75, -744, +93, -444, 129, 192, 89, 805, -7, 983, +-144, 723, -171, 259, -19, -253, 138, -616, +134, -674, -29, -395, -226, 76, -261, 410, +-111, 383, 64, 88, 163, -242, 164, -489, +100, -518, 38, -142, 53, 460, 148, 772, +163, 625, -23, 233, -289, -172, -423, -459, +-320, -571, -84, -475, 116, -192, 197, 164, +120, 404, -33, 391, -101, 233, -14, 58, +185, -195, 314, -345, 180, -202, -81, 41, +-232, 200, -253, 241, -196, 166, -98, 55, +12, -87, 91, -281, 109, -330, 127, -135, +167, 117, 117, 240, -75, 241, -332, 115, +-398, -104, -137, -261, 198, -291, 375, -164, +336, 122, 91, 358, -211, 435, -379, 437, +-313, 222, -57, -250, 156, -669, 216, -757, +159, -435, 18, 132, -118, 592, -197, 717, +-148, 455, 111, -113, 412, -680, 475, -843, +231, -436, -184, 258, -530, 849, -631, 1049, +-432, 674, -16, -128, 355, -891, 422, -1165, +173, -744, -181, 96, -360, 782, -218, 939, +139, 524, 498, -174, 650, -758, 447, -927, +-29, -525, -465, 251, -580, 901, -383, 1041, +-130, 623, -17, -126, -41, -835, -88, -1088, +-15, -685, 174, 55, 317, 659, 282, 851, +104, 524, -46, -61, -44, -434, 50, -463, +98, -276, -2, 25, -227, 281, -375, 314, +-299, 115, -88, -133, 107, -328, 239, -407, +272, -278, 223, -4, 192, 282, 177, 508, +82, 556, -119, 373, -359, 54, -532, -277, +-490, -491, -187, -565, 206, -460, 447, -122, +458, 275, 248, 473, -53, 405, -183, 132, +-73, -217, 104, -432, 199, -362, 132, -51, +-84, 316, -268, 551, -277, 478, -168, 127, +-48, -263, 51, -543, 122, -592, 152, -305, +111, 152, 25, 483, -33, 523, -65, 252, +-62, -179, 20, -512, 143, -564, 190, -348, +128, 42, -5, 463, -196, 660, -348, 501, +-264, 148, 36, -232, 328, -523, 475, -549, +370, -305, -2, 58, -423, 361, -600, 467, +-389, 304, 39, -44, 339, -369, 385, -531, +244, -502, -2, -216, -200, 273, -211, 642, +-28, 633, 183, 326, 242, -54, 171, -374, +78, -439, -42, -169, -192, 151, -284, 272, +-217, 186, -62, -105, -3, -432, 26, -540, +165, -467, 285, -265, 237, 136, 76, 592, +-79, 774, -152, 610, -153, 253, -54, -151, +132, -410, 200, -357, 53, -98, -172, 127, +-304, 146, -248, -99, -56, -432, 147, -629, +306, -541, 403, -160, 368, 298, 141, 610, +-143, 679, -292, 446, -350, 59, -329, -165, +-99, -133, 208, 33, 306, 158, 166, 52, +-37, -320, -135, -650, -88, -655, 25, -350, +101, 181, 91, 667, 21, 687, -44, 267, +-23, -241, 84, -615, 156, -589, 92, -84, +-28, 548, -51, 887, 52, 738, 130, 137, +84, -600, -44, -1023, -236, -893, -414, -373, +-394, 228, -137, 666, 176, 718, 385, 404, +422, -11, 293, -308, 90, -424, -39, -348, +-62, -90, -38, 224, 29, 362, 53, 247, +-39, -23, -143, -304, -161, -419, -94, -297, +15, 26, 104, 372, 179, 505, 191, 366, +59, 24, -139, -378, -287, -620, -316, -624, +-175, -374, 132, 122, 493, 607, 620, 801, +339, 622, -108, 166, -427, -346, -468, -675, +-180, -671, 262, -345, 547, 78, 475, 350, +80, 364, -377, 170, -602, -83, -462, -281, +-68, -262, 285, -26, 405, 204, 239, 299, +-89, 237, -238, -2, -46, -275, 305, -414, +543, -329, 479, -5, 78, 338, -416, 463, +-645, 323, -469, -14, -65, -439, 312, -691, +496, -490, 361, 81, -20, 625, -335, 815, +-376, 460, -168, -282, 172, -900, 492, -1043, +636, -583, 446, 307, -61, 1028, -568, 1091, +-752, 582, -550, -121, -90, -694, 390, -917, +645, -669, 550, -105, 187, 421, -181, 697, +-308, 627, -190, 242, -35, -278, 53, -754, +106, -936, 151, -639, 176, -54, 181, 515, +146, 879, 6, 910, -253, 617, -439, 91, +-291, -505, 116, -916, 424, -935, 388, -594, +106, -38, -181, 604, -318, 1001, -231, 798, +73, 173, 381, -486, 391, -924, 138, -881, +-30, -375, 39, 275, 136, 743, 87, 779, +-63, 368, -202, -206, -277, -631, -253, -705, +-74, -416, 163, 75, 210, 528, 42, 666, +-86, 458, -31, 78, 136, -290, 319, -473, +427, -403, 361, -175, 108, 44, -227, 95, +-432, -27, -335, -195, -9, -250, 283, -111, +339, 111, 181, 301, -76, 366, -310, 235, +-355, 12, -155, -157, 122, -250, 315, -224, +359, -65, 262, 151, 131, 281, 20, 218, +-106, 15, -189, -308, -109, -627, 82, -622, +212, -283, 207, 114, 163, 432, 102, 558, +-50, 427, -220, 164, -277, -82, -250, -266, +-175, -334, 44, -196, 378, 19, 576, 170, +457, 277, 91, 205, -324, -140, -501, -441, +-253, -460, 227, -254, 567, 27, 532, 205, +121, 231, -387, 155, -618, 11, -410, -118, +99, -108, 504, 28, 523, 137, 226, 128, +-145, 87, -328, 30, -192, -70, 160, -167, +465, -235, 471, -193, 135, -69, -308, 10, +-557, 34, -454, 23, -118, -70, 225, -222, +433, -313, 450, -123, 298, 334, 115, 707, +27, 742, 16, 359, 6, -312, -45, -896, +-97, -1023, -117, -563, -82, 204, -6, 715, +49, 705, 50, 261, 37, -338, 41, -672, +33, -563, 28, -156, 106, 362, 237, 769, +264, 724, 196, 185, 128, -417, 14, -751, +-176, -784, -294, -447, -228, 95, -53, 464, +139, 525, 340, 307, 465, 6, 363, -122, +79, -87, -191, -14, -290, 38, -213, 5, +-52, -93, 109, -245, 180, -381, 106, -359, +-33, -219, -128, -64, -108, 94, 59, 257, +290, 353, 464, 320, 497, 209, 379, 136, +140, 98, -165, 35, -403, -87, -451, -233, +-317, -351, -67, -457, 182, -467, 291, -319, +239, -121, 46, 71, -157, 240, -126, 302, +209, 307, 576, 296, 638, 197, 341, 0, +-140, -181, -592, -213, -731, -127, -363, -8, +270, 76, 701, 43, 700, -70, 377, -171, +-31, -261, -361, -249, -495, -133, -313, -48, +83, 5, 408, 94, 504, 209, 352, 224, +28, 83, -295, -69, -447, -134, -366, -171, +-36, -153, 432, -59, 749, 60, 729, 136, +462, 142, 58, 138, -394, 123, -679, 21, +-622, -189, -263, -392, 151, -423, 403, -269, +464, -67, 365, 103, 135, 193, -74, 182, +-121, 88, -14, -16, 156, 19, 266, 167, +273, 200, 238, 33, 166, -204, -7, -370, +-191, -387, -259, -249, -267, 36, -236, 323, +-58, 383, 240, 159, 468, -184, 486, -367, +283, -313, -15, -144, -212, 135, -199, 410, +-38, 339, 200, -38, 448, -392, 523, -522, +295, -326, -96, 105, -411, 454, -524, 514, +-385, 286, -16, -213, 419, -713, 645, -750, +495, -289, 120, 277, -181, 692, -308, 792, +-264, 440, -69, -238, 160, -829, 342, -943, +455, -584, 421, 14, 265, 632, 132, 948, +-8, 733, -191, 126, -257, -563, -172, -964, +-83, -855, 6, -365, 105, 247, 122, 679, +58, 669, -10, 285, -10, -149, 122, -403, +345, -396, 490, -194, 425, 21, 191, 127, +-13, 189, -42, 198, 21, 99, 40, -3, +3, -120, -95, -325, -244, -455, -289, -363, +-128, -123, 137, 151, 327, 334, 352, 364, +248, 218, 131, -58, 94, -306, 110, -386, +107, -249, 145, 26, 238, 274, 242, 358, +176, 246, 158, 26, 125, -192, -33, -340, +-267, -300, -448, -131, -435, -60, -192, -92, +125, -141, 370, -148, 527, -29, 573, 161, +451, 312, 233, 394, 32, 273, -107, -79, +-164, -436, -83, -559, 162, -422, 412, -130, +384, 226, 31, 506, -371, 551, -578, 297, +-476, -171, -65, -596, 475, -718, 837, -555, +801, -209, 393, 249, -114, 653, -410, 744, +-377, 402, -136, -101, 147, -468, 420, -669, +558, -617, 409, -245, 51, 211, -250, 471, +-335, 388, -238, 76, -64, -219, 166, -376, +409, -313, 475, -64, 255, 194, -47, 375, +-131, 396, -7, 174, 167, -108, 312, -303, +371, -448, 289, -495, 87, -299, -145, 23, +-258, 175, -216, 132, -130, 41, -21, -32, +154, -26, 319, 87, 357, 201, 250, 196, +98, 30, 61, -189, 178, -353, 310, -384, +353, -161, 348, 184, 269, 397, 7, 459, +-357, 347, -583, -39, -539, -535, -304, -814, +32, -702, 499, -341, 963, 105, 969, 515, +381, 638, -264, 390, -501, -17, -385, -356, +-91, -453, 312, -275, 637, -5, 615, 262, +229, 475, -201, 483, -366, 196, -254, -187, +-47, -416, 205, -520, 483, -566, 574, -480, +332, -232, -67, 83, -326, 323, -330, 411, +-182, 399, 12, 243, 228, -97, 350, -399, +283, -409, 190, -148, 267, 145, 428, 307, +451, 302, 318, 110, 124, -174, -95, -342, +-256, -305, -248, -112, -112, 29, 15, -12, +28, -87, -41, -89, -24, -67, 156, -12, +358, 76, 413, 121, 317, 35, 151, -198, +32, -378, 68, -321, 265, -53, 459, 291, +446, 581, 193, 656, -132, 386, -377, -109, +-495, -532, -365, -742, 27, -746, 407, -516, +554, -146, 507, 187, 299, 405, 26, 546, +-93, 534, 5, 281, 175, -75, 257, -389, +186, -581, 35, -501, -43, -154, 15, 201, +134, 376, 211, 296, 225, 4, 197, -352, +133, -520, 37, -324, -17, 65, 25, 389, +128, 555, 235, 414, 236, -16, 72, -395, +-107, -554, -104, -497, 93, -193, 360, 202, +536, 378, 490, 268, 172, -23, -223, -328, +-346, -386, -155, -186, 53, 12, 129, 121, +190, 114, 266, -64, 307, -121, 331, 106, +358, 330, 327, 339, 165, 155, -74, -147, +-166, -421, -29, -506, 103, -357, 82, -86, +-6, 132, -86, 219, -133, 149, -47, -11, +202, -161, 501, -256, 629, -283, 445, -212, +142, -23, 33, 186, 157, 276, 290, 302, +266, 334, 99, 236, -112, 1, -298, -243, +-357, -394, -214, -377, 41, -236, 219, -94, +282, 0, 350, 12, 437, -84, 393, -200, +186, -227, 22, -154, 17, -40, 118, 145, +277, 355, 426, 449, 435, 366, 293, 139, +55, -127, -253, -315, -469, -377, -463, -322, +-281, -217, 24, -116, 396, 24, 651, 115, +641, 81, 390, -18, 96, -158, -37, -251, +-3, -188, 111, -22, 290, 170, 454, 304, +404, 274, 120, 120, -207, -83, -397, -249, +-352, -309, -76, -280, 278, -157, 544, 87, +563, 283, 291, 223, -41, 7, -191, -162, +-129, -285, 76, -304, 331, -114, 493, 94, +472, 176, 281, 171, 22, 56, -180, -127, +-219, -265, -71, -335, 147, -276, 302, -10, +339, 333, 250, 477, 90, 336, -28, 82, +-46, -242, 54, -529, 229, -487, 336, -154, +295, 139, 195, 241, 132, 149, 117, -86, +154, -304, 208, -307, 176, -17, 3, 345, +-213, 490, -304, 305, -130, -129, 252, -556, +558, -673, 554, -415, 300, 24, 34, 405, +-104, 537, -62, 297, 197, -153, 532, -441, +612, -457, 354, -211, -2, 228, -260, 549, +-382, 523, -307, 179, -19, -350, 274, -767, +355, -796, 242, -449, 114, 65, 92, 454, +170, 552, 271, 356, 324, 5, 298, -248, +241, -238, 197, -44, 185, 136, 225, 171, +233, 64, 98, -120, -82, -264, -130, -255, +-102, -199, -138, -162, -180, -138, -93, -176, +71, -159, 267, 83, 549, 381, 769, 487, +657, 394, 281, 146, -12, -207, -77, -484, +5, -498, 158, -323, 280, -63, 192, 206, +-80, 303, -308, 176, -355, -36, -172, -281, +175, -485, 408, -451, 379, -139, 272, 231, +252, 436, 322, 469, 453, 307, 568, -5, +477, -218, 103, -244, -340, -182, -571, -64, +-473, -31, -104, -157, 373, -245, 721, -235, +747, -176, 410, -53, -137, 104, -584, 192, +-607, 144, -174, -24, 444, -165, 945, -138, +1079, 9, 735, 171, 120, 340, -381, 420, +-556, 241, -393, -93, -14, -412, 354, -633, +486, -680, 370, -556, 147, -298, -68, 41, +-199, 321, -157, 479, 81, 501, 339, 349, +447, 137, 465, -65, 473, -221, 378, -199, +148, -31, -84, 72, -193, 29, -178, -122, +-66, -334, 165, -527, 386, -532, 360, -246, +103, 159, -100, 437, -75, 457, 102, 244, +258, -41, 372, -228, 463, -215, 358, -17, +10, 199, -265, 275, -216, 142, 58, -133, +364, -345, 566, -388, 551, -243, 252, -7, +-188, 133, -437, 66, -282, -175, 129, -397, +472, -354, 571, -66, 432, 313, 139, 614, +-168, 567, -298, 168, -138, -269, 209, -500, +465, -439, 519, -88, 439, 306, 229, 385, +-42, 115, -147, -251, -23, -559, 159, -642, +250, -349, 202, 57, 65, 286, -47, 326, +-29, 201, 107, 14, 251, -29, 325, 64, +327, 161, 231, 167, 37, 35, -113, -167, +-77, -319, 161, -365, 461, -302, 571, -95, +367, 146, 49, 238, -164, 167, -198, -18, +-10, -270, 326, -388, 521, -277, 360, -36, +-49, 257, -396, 454, -442, 398, -204, 84, +178, -299, 556, -517, 756, -478, 641, -209, +319, 205, 92, 515, 102, 491, 206, 159, +253, -251, 195, -458, -43, -432, -401, -295, +-598, -84, -388, 105, 139, 127, 637, 26, +814, -74, 631, -120, 237, -126, -156, -75, +-305, 81, -56, 294, 428, 424, 746, 347, +666, 107, 222, -156, -331, -333, -621, -423, +-496, -494, -103, -517, 351, -358, 643, -88, +621, 172, 392, 447, 165, 575, 53, 393, +41, 49, 58, -239, 71, -355, 111, -252, +141, -48, 103, 109, 29, 136, -5, 15, +57, -155, 185, -272, 294, -277, 323, -164, +268, 7, 146, 109, 35, 116, 57, 120, +197, 172, 286, 190, 244, 96, 128, -101, +-25, -332, -161, -503, -161, -509, 14, -234, +277, 230, 513, 572, 596, 565, 454, 223, +163, -224, -100, -513, -231, -561, -204, -315, +-40, 168, 141, 514, 233, 462, 261, 141, +275, -207, 264, -424, 261, -416, 258, -237, +194, -27, 99, 132, 62, 157, 73, 16, +85, -104, 101, -100, 136, -85, 152, -39, +73, 76, -59, 167, -110, 201, -5, 163, +195, 23, 382, -89, 501, -142, 525, -231, +417, -291, 200, -254, -2, -185, -103, -99, +-133, 27, -151, 86, -109, 55, 36, -3, +205, -58, 303, -13, 338, 193, 324, 392, +223, 417, 48, 219, -76, -181, -34, -585, +163, -797, 412, -712, 575, -278, 540, 314, +274, 685, -97, 670, -364, 346, -380, -113, +-143, -499, 176, -610, 367, -354, 361, 88, +238, 407, 72, 399, -76, 98, -77, -296, +142, -569, 412, -566, 523, -200, 444, 354, +246, 717, 74, 683, 80, 316, 200, -188, +245, -569, 160, -612, -87, -381, -419, -74, +-537, 165, -237, 173, 284, -85, 650, -316, +668, -312, 404, -136, 62, 147, -145, 444, +-100, 581, 186, 443, 579, 97, 793, -263, +642, -466, 213, -473, -258, -315, -555, -120, +-596, 33, -379, 127, 58, 85, 473, -64, +577, -165, 414, -143, 205, -61, 55, 67, +-16, 252, 57, 397, 291, 331, 513, 38, +511, -353, 297, -659, 53, -679, -98, -384, +-158, 85, -153, 526, -59, 724, 89, 534, +193, 79, 214, -329, 205, -495, 191, -446, +171, -223, 167, 55, 216, 195, 301, 165, +279, -9, 75, -237, -149, -325, -150, -232, +87, -65, 400, 170, 582, 380, 467, 380, +98, 190, -230, -37, -286, -235, -75, -333, +238, -260, 400, -119, 292, 10, 49, 156, +-130, 206, -147, 78, 16, -58, 284, -157, +520, -274, 595, -333, 454, -290, 180, -173, +-41, 10, -92, 224, -14, 404, 91, 462, +110, 287, 23, -38, -92, -306, -130, -415, +-31, -347, 166, -82, 348, 218, 468, 308, +524, 167, 483, -77, 356, -313, 151, -429, +-98, -368, -271, -180, -245, 55, -76, 205, +100, 193, 239, 68, 342, -48, 334, -45, +204, 88, 93, 254, 65, 327, 75, 201, +135, -109, 250, -401, 323, -482, 288, -275, +156, 57, -5, 231, -101, 154, -86, -111, +-6, -463, 104, -629, 246, -371, 342, 144, +332, 597, 255, 804, 140, 675, 27, 234, +16, -279, 84, -621, 129, -688, 129, -470, +120, -88, 142, 254, 182, 431, 189, 402, +171, 154, 169, -205, 161, -511, 131, -617, +111, -483, 115, -128, 102, 354, 79, 710, +125, 736, 233, 475, 275, 26, 170, -495, +-14, -803, -134, -730, -102, -380, 35, 64, +215, 426, 385, 504, 448, 284, 372, -37, +267, -271, 216, -312, 193, -110, 164, 194, +83, 338, -73, 260, -239, 28, -290, -270, +-167, -481, 108, -461, 391, -250, 481, -6, +336, 141, 98, 167, -48, 133, 53, 98, +391, 97, 692, 138, 685, 198, 316, 158, +-222, -55, -606, -303, -603, -419, -245, -412, +271, -271, 688, 17, 772, 284, 508, 368, +92, 277, -266, 82, -422, -173, -265, -349, +115, -346, 455, -192, 576, 32, 473, 233, +207, 316, -80, 244, -186, 27, -43, -244, +236, -408, 466, -398, 514, -191, 347, 160, +70, 440, -149, 466, -215, 264, -152, -87, +-16, -420, 93, -516, 85, -350, 39, -86, +116, 140, 330, 267, 517, 242, 571, 90, +459, -95, 174, -224, -146, -268, -234, -216, +-33, -68, 230, 150, 349, 317, 297, 300, +147, 127, -21, -74, -122, -208, -134, -248, +-70, -172, 51, -47, 194, 17, 319, -15, +407, -66, 418, -88, 308, -76, 116, -40, +-21, -15, 6, 7, 158, 23, 315, 24, +371, 30, 260, 69, 6, 111, -210, 115, +-229, 49, -74, -54, 131, -150, 258, -211, +219, -189, 67, -91, 7, 9, 139, 55, +379, 38, 582, -51, 620, -131, 417, -119, +53, -36, -291, 58, -441, 136, -339, 151, +-55, 88, 305, -5, 587, -88, 616, -124, +334, -117, -61, -103, -269, -97, -170, -82, +101, -63, 375, -2, 510, 101, 407, 160, +140, 151, -82, 84, -118, -49, -23, -189, +53, -219, 70, -155, 98, -71, 161, -25, +249, -23, 367, -54, 466, -89, 423, -61, +184, 71, -109, 232, -254, 281, -160, 216, +87, 70, 319, -140, 412, -305, 300, -320, +19, -251, -180, -119, -138, 80, 19, 201, +153, 153, 248, 36, 286, -76, 289, -174, +345, -180, 423, -82, 399, 68, 217, 164, +-28, 123, -219, -5, -273, -88, -134, -102, +146, -60, 389, 48, 431, 154, 251, 171, +-17, 54, -170, -149, -104, -316, 141, -345, +384, -245, 458, -45, 325, 155, 79, 233, +-94, 176, -55, 13, 148, -184, 341, -235, +410, -72, 336, 115, 158, 246, -33, 336, +-103, 273, -32, -5, 92, -320, 181, -504, +185, -510, 94, -330, -27, -17, -79, 301, +-10, 466, 176, 403, 373, 109, 461, -256, +417, -432, 304, -323, 162, -79, 45, 191, +-14, 398, -4, 359, 63, 56, 135, -266, +193, -407, 220, -358, 170, -149, 29, 105, +-106, 263, -141, 281, -56, 159, 112, -101, +302, -330, 424, -353, 411, -216, 305, -16, +198, 193, 146, 327, 130, 269, 107, 52, +78, -155, 86, -189, 103, -82, 90, 21, +70, 37, 54, -18, 19, -108, -17, -178, +24, -151, 147, -57, 251, 40, 256, 78, +224, 21, 212, -60, 213, -23, 213, 96, +223, 174, 229, 176, 182, 116, 72, 1, +-38, -171, -102, -323, -84, -327, 49, -186, +233, -53, 383, 39, 421, 134, 273, 174, +-1, 81, -191, -17, -170, -12, 9, 19, +244, 41, 421, 68, 443, 67, 303, 15, +128, -49, 18, -135, -10, -224, 8, -244, +15, -174, 3, -96, 76, -20, 263, 117, +413, 245, 415, 227, 270, 76, 33, -60, +-200, -136, -254, -156, -42, -73, 296, 130, +511, 285, 483, 239, 230, 0, -113, -320, +-306, -532, -224, -504, 57, -238, 368, 137, +549, 428, 500, 469, 292, 263, 91, -65, +0, -312, -25, -345, -40, -199, -38, 4, +-20, 176, 57, 283, 244, 278, 445, 180, +469, 60, 257, -51, -74, -215, -287, -408, +-236, -516, 22, -456, 294, -248, 428, 57, +411, 365, 290, 535, 137, 502, 56, 254, +93, -121, 143, -400, 135, -394, 100, -164, +92, 155, 105, 413, 91, 434, 52, 160, +26, -269, 35, -612, 75, -679, 121, -445, +159, -61, 222, 287, 261, 467, 247, 448, +244, 246, 265, -23, 221, -204, 100, -228, +-14, -153, -55, -59, -38, 46, 11, 136, +105, 165, 199, 126, 247, 66, 258, -48, +235, -231, 157, -393, 72, -385, 37, -177, +44, 115, 86, 339, 158, 349, 202, 103, +146, -234, 66, -383, 76, -254, 144, 75, +182, 417, 178, 567, 144, 391, 116, 12, +148, -315, 232, -482, 289, -479, 233, -307, +57, -60, -149, 89, -250, 118, -165, 91, +75, 38, 332, -24, 513, 5, 533, 131, +334, 222, 21, 207, -208, 84, -219, -132, +6, -324, 353, -316, 590, -117, 541, 143, +182, 293, -265, 219, -505, -63, -395, -383, +-1, -532, 417, -370, 592, 45, 467, 443, +174, 601, -70, 471, -75, 122, 134, -295, +360, -518, 422, -443, 310, -181, 150, 99, +29, 275, -65, 273, -147, 99, -216, -114, +-221, -222, -75, -205, 205, -119, 486, 14, +586, 100, 439, 106, 171, 83, -20, 57, +-20, -1, 137, -47, 274, -45, 245, -43, +75, -49, -98, -25, -123, 4, -10, -39, +118, -117, 172, -158, 153, -109, 107, 20, +108, 176, 169, 284, 263, 273, 319, 104, +245, -177, 87, -442, -47, -546, -94, -387, +-25, -35, 154, 367, 356, 644, 456, 616, +367, 248, 122, -234, -130, -549, -269, -565, +-257, -293, -93, 101, 187, 348, 423, 284, +428, 6, 237, -285, 76, -377, 32, -202, +58, 110, 142, 362, 252, 423, 273, 242, +172, -64, 61, -281, 27, -316, 27, -172, +17, 50, 22, 185, 28, 141, 38, 5, +85, -152, 154, -289, 203, -312, 219, -164, +202, 55, 173, 228, 164, 351, 154, 382, +127, 262, 94, 12, 82, -226, 68, -381, +42, -416, 60, -281, 125, -26, 160, 189, +159, 292, 136, 268, 60, 74, -11, -193, +20, -347, 163, -288, 284, -80, 277, 192, +154, 395, -27, 396, -178, 152, -144, -187, +118, -400, 432, -392, 583, -196, 453, 87, +116, 323, -220, 336, -358, 112, -232, -188, +74, -385, 364, -395, 462, -200, 324, 94, +76, 312, -112, 348, -166, 205, -57, -6, +162, -161, 345, -169, 392, -52, 313, 85, +144, 123, -46, 50, -170, -99, -153, -270, +3, -345, 183, -230, 297, 3, 330, 214, +274, 321, 152, 237, 71, 11, 75, -198, +85, -243, 4, -109, -131, 113, -210, 252, +-141, 206, 96, 9, 394, -217, 560, -298, +475, -181, 182, 43, -128, 225, -193, 261, +8, 113, 244, -97, 315, -259, 206, -345, +21, -308, -127, -136, -174, 69, -93, 210, +52, 291, 151, 297, 232, 237, 324, 118, +363, -40, 270, -194, 58, -267, -158, -268, +-219, -203, -60, -57, 232, 94, 462, 164, +478, 122, 291, 12, 5, -77, -204, -59, +-221, -16, -129, 0, -41, 17, 30, -10, +70, -119, 98, -167, 176, -55, 304, 78, +379, 136, 335, 157, 235, 147, 143, 48, +72, -79, 31, -133, 9, -99, -38, -39, +-82, 28, -74, 53, -21, -10, 47, -89, +73, -150, 57, -209, 47, -188, 86, -10, +178, 154, 279, 175, 329, 121, 330, 65, +270, -20, 153, -90, 30, -55, -80, 65, +-164, 149, -162, 116, -31, 36, 165, -36, +295, -93, 263, -138, 114, -145, -74, -143, +-211, -154, -192, -169, -6, -154, 224, -67, +370, 71, 396, 194, 336, 238, 223, 218, +64, 147, -54, 54, -51, -52, 29, -99, +100, -37, 156, 62, 174, 89, 61, 32, +-179, -78, -346, -246, -274, -391, -43, -404, +209, -241, 413, 6, 511, 230, 430, 340, +226, 317, 76, 198, 63, 51, 75, -62, +24, -97, -56, -39, -95, 43, -57, 66, +-5, 9, 6, -51, 16, -116, 40, -205, +27, -256, 16, -198, 85, -84, 218, 38, +304, 154, 287, 215, 245, 201, 202, 95, +122, -74, 6, -199, -84, -155, -88, -16, +-25, 106, -7, 181, -37, 190, -30, 70, +22, -159, 80, -348, 129, -358, 185, -167, +215, 102, 153, 340, 53, 430, 56, 270, +133, -103, 167, -442, 127, -535, 67, -348, +38, 23, 41, 376, 48, 495, 21, 321, +-50, 7, -126, -280, -152, -380, -86, -228, +96, 59, 274, 259, 306, 293, 238, 185, +201, -43, 201, -289, 148, -383, 30, -278, +-50, -110, -29, 51, 13, 189, 29, 265, +19, 225, -52, 125, -177, 8, -230, -129, +-92, -228, 187, -208, 400, -101, 401, 0, +250, 76, 94, 115, 39, 107, 79, 44, +157, -8, 199, -16, 110, -16, -94, -55, +-256, -108, -276, -126, -174, -100, -21, -30, +100, 32, 163, 50, 170, 30, 155, 17, +171, -5, 214, -25, 209, 2, 149, 69, +84, 91, 62, 60, 81, 43, 70, 9, +5, -76, -89, -167, -179, -208, -224, -231, +-183, -208, -59, -89, 119, 119, 300, 308, +436, 379, 441, 310, 248, 145, -55, -71, +-318, -272, -405, -354, -228, -301, 146, -155, +460, -14, 515, 63, 304, 85, -22, 95, +-287, 58, -366, -13, -220, -29, 46, 19, +266, 88, 327, 160, 205, 224, -4, 208, +-148, 86, -181, -147, -88, -403, 94, -548, +243, -508, 270, -299, 209, 30, 128, 356, +25, 513, -108, 464, -180, 288, -94, 88, +61, -88, 176, -194, 201, -226, 100, -192, +-85, -124, -199, -66, -156, -55, 2, -66, +185, -49, 284, -31, 230, -14, 62, 47, +-45, 138, -27, 131, 33, 56, 97, 18, +158, -6, 116, -43, -50, -31, -213, 0, +-253, -27, -145, -52, 29, -53, 169, -78, +223, -102, 221, -52, 182, 20, 112, 79, +50, 134, 21, 142, -44, 26, -119, -139, +-66, -216, 77, -212, 140, -166, 32, -51, +-143, 126, -218, 249, -138, 309, 48, 315, +284, 210, 420, -16, 327, -262, 47, -439, +-253, -488, -361, -369, -200, -130, 80, 136, +286, 297, 345, 308, 244, 214, 32, 83, +-191, -31, -280, -37, -189, 50, -34, 120, +72, 119, 97, 34, 75, -149, 70, -349, +90, -421, 96, -337, 117, -113, 123, 164, +41, 363, -104, 401, -179, 260, -109, -26, +49, -294, 190, -351, 250, -172, 187, 119, +-16, 326, -249, 319, -343, 110, -225, -152, +-10, -349, 145, -358, 207, -131, 203, 173, +136, 329, 32, 282, -41, 92, -29, -165, +36, -349, 57, -361, 56, -188, 101, 47, +126, 187, 37, 178, -123, 89, -261, -5, +-317, -43, -272, 20, -120, 141, 122, 236, +339, 234, 408, 135, 313, -13, 127, -148, +-67, -293, -173, -433, -173, -460, -109, -319, +-28, -109, 48, 63, 103, 182, 90, 253, +30, 271, -30, 228, -82, 211, -114, 231, +-84, 214, -8, 114, 77, -20, 106, -167, +38, -299, -52, -370, -87, -374, -61, -311, +8, -172, 109, 4, 201, 123, 228, 207, +170, 274, 69, 256, -52, 142, -167, 43, +-227, -39, -225, -151, -188, -206, -148, -124, +-128, 11, -91, 93, 24, 167, 201, 214, +364, 164, 399, 12, 292, -169, 128, -320, +-27, -353, -146, -236, -216, -56, -259, 92, +-273, 151, -218, 105, -102, 5, 38, -26, +136, 38, 137, 132, 41, 179, -70, 157, +-84, 91, 23, 13, 154, -87, 237, -171, +243, -186, 165, -165, 33, -108, -141, -1, +-298, 89, -338, 76, -250, -17, -112, -117, +55, -144, 213, -83, 244, 14, 87, 89, +-135, 102, -213, 64, -132, 34, 11, 69, +177, 131, 299, 174, 227, 134, -25, -41, +-252, -271, -283, -391, -157, -352, 21, -169, +201, 123, 286, 363, 192, 410, -53, 245, +-316, -46, -455, -341, -370, -484, -128, -425, +104, -186, 231, 153, 250, 443, 201, 527, +135, 372, 130, 95, 158, -173, 74, -314, +-135, -292, -299, -144, -323, 16, -219, 86, +-81, 39, -4, -53, -2, -116, -18, -110, +13, -43, 83, 30, 125, 102, 114, 144, +65, 111, -21, 21, -77, -45, -70, -90, +-60, -113, -64, -96, -42, -54, -1, -19, +32, 30, 24, 114, -43, 184, -109, 195, +-97, 104, -5, -59, 72, -195, 92, -213, +54, -147, -61, -78, -222, -46, -292, -50, +-206, -106, -36, -147, 131, -55, 239, 124, +262, 271, 186, 336, 60, 310, -45, 180, +-102, 21, -154, -137, -236, -287, -309, -357, +-271, -310, -106, -194, 90, -44, 211, 139, +192, 287, 78, 323, -28, 209, -77, 5, +-88, -201, -69, -330, -50, -319, -55, -140, +-57, 84, -20, 220, 64, 257, 125, 196, +92, 72, 5, -31, -86, -65, -187, -66, +-255, -31, -242, 14, -136, 14, 20, -46, +142, -121, 166, -182, 103, -197, 16, -122, +-49, 16, -90, 131, -98, 142, -52, 63, +-8, -32, -13, -67, -23, -21, -2, 110, +-6, 253, -70, 295, -118, 198, -80, 3, +-9, -210, 20, -363, 16, -384, -28, -281, +-115, -121, -194, 16, -168, 86, -32, 96, +111, 102, 175, 133, 144, 174, 31, 205, +-94, 201, -134, 128, -99, -32, -54, -198, +-66, -296, -131, -301, -156, -223, -74, -65, +50, 97, 122, 192, 88, 215, -34, 175, +-155, 113, -188, 48, -89, -43, 34, -176, +52, -265, -7, -257, -40, -160, -43, -1, +-35, 178, -33, 272, -61, 217, -108, 76, +-109, -51, -19, -93, 94, -45, 127, 56, +49, 118, -71, 92, -159, -27, -174, -203, +-156, -359, -148, -372, -143, -206, -118, 48, +-49, 291, 62, 433, 188, 380, 252, 150, +204, -88, 63, -222, -101, -228, -240, -119, +-304, 53, -266, 159, -162, 127, -44, -17, +53, -226, 86, -363, 22, -296, -89, -36, +-160, 256, -155, 435, -102, 407, 16, 169, +181, -165, 286, -381, 240, -348, 49, -144, +-179, 89, -311, 259, -307, 285, -223, 133, +-109, -89, -36, -254, -59, -291, -131, -182, +-123, 37, -7, 229, 113, 305, 151, 234, +146, 22, 125, -214, 48, -321, -50, -257, +-118, -105, -146, 67, -166, 204, -181, 245, +-168, 140, -132, -9, -96, -73, -62, -52, +-25, 2, 10, 46, 49, 37, 69, -43, +40, -138, -22, -198, -74, -184, -116, -105, +-108, 0, -27, 101, 91, 200, 147, 259, +73, 234, -93, 123, -251, -45, -305, -175, +-255, -210, -149, -190, -35, -143, 27, -62, +22, -23, 20, -13, 53, 67, 75, 183, +44, 229, -10, 204, -41, 122, -55, -28, +-60, -172, -45, -259, -24, -264, -51, -180, +-118, -40, -208, 70, -294, 121, -291, 119, +-157, 75, 52, 36, 214, 38, 244, 99, +154, 175, 1, 177, -158, 69, -214, -81, +-125, -234, 18, -349, 109, -357, 127, -223, +72, 11, -96, 226, -374, 310, -588, 266, +-536, 144, -233, -35, 175, -167, 509, -163, +586, -60, 332, 49, -76, 126, -370, 132, +-423, 77, -262, 10, 9, -63, 219, -127, +206, -137, -17, -95, -303, -63, -481, -48, +-459, -36, -219, -16, 129, -10, 375, -18, +375, 12, 175, 99, -79, 181, -254, 223, +-260, 223, -127, 148, 49, 6, 141, -135, +89, -208, -51, -221, -199, -197, -314, -180, +-349, -180, -276, -151, -116, -54, 57, 85, +165, 214, 195, 317, 172, 351, 104, 264, +-6, 90, -96, -22, -133, -46, -136, -65, +-144, -114, -185, -163, -209, -226, -155, -302, +-48, -309, 24, -213, 34, -53, 3, 112, +-36, 264, -71, 375, -60, 426, 18, 392, +79, 270, 13, 84, -120, -118, -186, -302, +-174, -448, -144, -506, -114, -441, -48, -263, +37, -38, 89, 209, 107, 435, 127, 534, +83, 444, -84, 250, -277, 47, -363, -142, +-341, -291, -255, -367, -106, -353, 63, -273, +178, -145, 188, 17, 125, 199, 47, 346, +4, 400, -4, 324, -20, 152, -88, -48, +-174, -231, -229, -348, -281, -356, -302, -260, +-217, -141, -32, -24, 148, 109, 237, 236, +211, 304, 91, 316, -106, 269, -266, 151, +-243, -31, -75, -260, 69, -430, 57, -417, +-94, -252, -241, -53, -239, 151, -94, 312, +99, 361, 222, 307, 170, 191, -44, 25, +-266, -154, -335, -305, -235, -403, -58, -367, +94, -172, 167, 81, 153, 280, 64, 391, +-96, 365, -262, 200, -354, -23, -332, -207, +-198, -311, 8, -323, 225, -218, 346, -29, +286, 189, 63, 378, -185, 457, -323, 342, +-306, 72, -199, -266, -81, -568, -13, -685, +-46, -545, -142, -218, -173, 191, -51, 560, +150, 747, 259, 712, 172, 456, -27, 61, +-240, -299, -390, -506, -357, -585, -122, -535, +146, -360, 281, -136, 253, 109, 96, 354, +-129, 507, -336, 496, -420, 310, -342, -1, +-152, -264, 34, -367, 142, -323, 171, -152, +150, 73, 82, 225, -20, 278, -113, 224, +-202, 21, -286, -215, -297, -346, -165, -351, +49, -214, 222, 63, 258, 328, 120, 449, +-119, 410, -308, 219, -351, -63, -262, -308, +-98, -418, 62, -367, 136, -193, 90, 21, +8, 219, -35, 312, -67, 259, -104, 136, +-97, 9, -55, -121, -29, -197, -34, -175, +-95, -107, -212, -15, -292, 60, -228, 71, +-25, 51, 210, 71, 334, 100, 273, 93, +35, 55, -264, 8, -443, -35, -413, -65, +-219, -75, 9, -77, 179, -83, 232, -83, +154, -42, -44, 13, -274, 59, -391, 77, +-323, 49, -123, 15, 119, 35, 272, 79, +242, 104, 84, 112, -87, 53, -206, -61, +-259, -143, -220, -168, -110, -157, -10, -83, +18, 18, 0, 88, -55, 123, -141, 87, +-159, -21, -79, -76, 11, -2, 37, 113, +12, 185, -48, 156, -103, 22, -96, -147, +-32, -274, 7, -318, -15, -237, -62, -57, +-86, 119, -85, 243, -89, 301, -78, 297, +-45, 246, -34, 184, -84, 81, -161, -63, +-197, -220, -145, -389, -26, -526, 106, -512, +165, -308, 67, -15, -113, 289, -200, 546, +-153, 670, -54, 566, 38, 259, 60, -124, +-17, -404, -139, -465, -184, -305, -122, -25, +-66, 226, -58, 300, -50, 137, -45, -159, +-86, -422, -146, -529, -167, -423, -120, -116, +-18, 292, 119, 673, 228, 867, 217, 739, +57, 319, -155, -218, -288, -690, -310, -934, +-229, -788, -70, -307, 46, 263, -22, 674, +-195, 764, -313, 470, -286, -57, -97, -517, +196, -658, 463, -422, 525, 42, 322, 493, +-44, 700, -423, 558, -665, 132, -647, -339, +-398, -638, -54, -667, 257, -431, 417, -50, +319, 291, 15, 497, -289, 543, -408, 411, +-291, 162, -56, -93, 155, -253, 232, -305, +156, -279, -10, -222, -149, -147, -176, -67, +-154, 29, -175, 163, -203, 283, -167, 317, +-106, 251, -70, 112, -1, -76, 100, -225, +96, -250, -11, -149, -108, -6, -141, 94, +-130, 105, -92, -1, -28, -199, 38, -339, +76, -267, 64, -6, 28, 352, -29, 659, +-123, 735, -252, 541, -382, 167, -437, -334, +-344, -819, -128, -1038, 101, -893, 239, -449, +300, 169, 320, 737, 239, 995, 84, 870, +-50, 472, -145, 9, -292, -345, -446, -516, +-469, -491, -364, -306, -223, -87, -54, 69, +160, 144, 309, 115, 278, 41, 99, 17, +-89, 35, -187, 59, -182, 101, -107, 97, +1, 19, 80, -48, 65, -70, -77, -79, +-236, -74, -280, -61, -255, -56, -205, -5, +-105, 101, 40, 206, 141, 250, 132, 196, +56, 14, -6, -227, -39, -405, -88, -424, +-158, -247, -189, 43, -149, 315, -92, 470, +-69, 468, -58, 310, -43, 100, -93, -84, +-153, -263, -100, -468, 65, -590, 208, -502, +208, -209, 87, 195, -104, 572, -304, 786, +-426, 709, -392, 338, -216, -174, -25, -586, +113, -752, 198, -633, 179, -264, 37, 210, +-141, 556, -233, 617, -186, 423, -42, 92, +117, -208, 181, -357, 95, -339, -112, -227, +-309, -81, -391, 32, -315, 81, -109, 117, +60, 152, 106, 137, 67, 101, 6, 123, +-34, 129, -35, 43, -34, -80, -80, -193, +-172, -305, -227, -344, -188, -238, -47, -22, +134, 237, 265, 461, 284, 557, 143, 484, +-114, 278, -382, -37, -558, -393, -621, -695, +-556, -837, -324, -734, 24, -394, 372, 98, +623, 654, 725, 1084, 621, 1146, 282, 834, +-187, 289, -655, -373, -974, -941, -964, -1126, +-648, -888, -181, -391, 274, 175, 604, 606, +715, 741, 536, 595, 173, 293, -188, -65, +-452, -347, -597, -445, -548, -367, -302, -226, +-32, -54, 112, 144, 119, 294, 67, 354, +32, 377, 37, 378, 82, 294, 124, 84, +92, -239, -50, -539, -264, -681, -420, -636, +-457, -405, -348, -14, -121, 377, 116, 617, +252, 682, 218, 559, 55, 269, -135, -72, +-220, -350, -145, -528, -12, -548, 56, -378, +33, -68, -64, 269, -185, 543, -207, 651, +-71, 470, 62, 54, 49, -321, -97, -524, +-263, -631, -299, -560, -174, -239, 39, 165, +174, 498, 115, 716, -84, 691, -275, 382, +-314, -75, -172, -513, 60, -755, 232, -666, +231, -279, 109, 219, -13, 625, -104, 760, +-185, 592, -278, 174, -339, -326, -352, -645, +-291, -674, -139, -514, 55, -199, 224, 218, +294, 522, 232, 641, 47, 615, -172, 375, +-360, -76, -484, -522, -425, -774, -126, -727, +290, -365, 607, 173, 635, 646, 339, 831, +-187, 654, -735, 232, -1018, -229, -900, -551, +-473, -602, 16, -412, 376, -115, 546, 171, +566, 322, 464, 297, 237, 209, -51, 102, +-328, -42, -516, -120, -534, -109, -391, -82, +-196, -70, -66, -113, 9, -195, 72, -134, +128, 104, 208, 362, 237, 566, 98, 622, +-192, 367, -451, -134, -525, -605, -450, -892, +-240, -898, 60, -563, 296, 5, 399, 555, +389, 862, 263, 823, 40, 512, -201, 120, +-412, -164, -553, -236, -532, -187, -368, -183, +-157, -291, 71, -440, 282, -497, 379, -320, +259, 60, 19, 453, -220, 677, -402, 651, +-414, 372, -233, -76, 34, -478, 262, -595, +394, -346, 352, 86, 79, 469, -284, 624, +-563, 424, -686, -83, -601, -611, -282, -897, +163, -817, 456, -353, 446, 282, 239, 759, +-13, 911, -222, 755, -318, 346, -212, -114, +-17, -399, 66, -437, -1, -300, -97, -124, +-133, -35, -209, -47, -329, -86, -321, -123, +-158, -119, 52, -33, 245, 139, 372, 336, +318, 463, 43, 384, -278, 69, -485, -314, +-517, -549, -365, -522, -105, -246, 118, 156, +211, 491, 235, 653, 187, 584, 27, 263, +-180, -211, -319, -612, -328, -791, -248, -674, +-100, -231, 75, 354, 163, 749, 101, 786, +-55, 501, -175, -28, -226, -562, -233, -816, +-138, -701, -6, -296, 71, 292, 95, 810, +69, 990, -38, 785, -194, 281, -278, -367, +-254, -879, -117, -1005, 95, -748, 259, -219, +256, 397, 65, 830, -209, 858, -458, 492, +-584, -81, -514, -627, -289, -896, 61, -729, +456, -188, 694, 467, 643, 979, 299, 1133, +-215, 827, -741, 193, -994, -516, -775, -1110, +-269, -1348, 228, -1046, 542, -354, 577, 437, +290, 1111, -150, 1423, -429, 1154, -436, 407, +-258, -496, 0, -1177, 198, -1315, 206, -820, +60, 23, -86, 780, -246, 1123, -421, 922, +-470, 261, -357, -570, -104, -1105, 219, -1054, +497, -487, 591, 361, 412, 1177, 16, 1507, +-434, 1122, -704, 237, -684, -778, -494, -1540, +-223, -1663, 88, -1057, 299, -88, 306, 803, +207, 1308, 106, 1261, -30, 728, -125, 50, +-118, -465, -90, -683, -93, -571, -78, -232, +-55, 92, -136, 255, -267, 272, -353, 105, +-353, -196, -193, -385, 93, -327, 331, -133, +359, 143, 179, 441, -49, 576, -211, 496, +-236, 279, -149, -75, -76, -476, -74, -689, +-126, -647, -170, -403, -192, -5, -176, 387, +-146, 578, -85, 582, 81, 440, 273, 150, +339, -140, 212, -274, -37, -290, -325, -279, +-600, -222, -667, -122, -417, -29, -28, 48, +299, 153, 486, 268, 522, 295, 358, 187, +53, -10, -270, -239, -567, -415, -725, -382, +-662, -135, -385, 141, 4, 324, 352, 433, +530, 430, 492, 301, 312, 114, 82, -107, +-147, -330, -343, -449, -482, -424, -507, -326, +-422, -172, -262, 38, -38, 214, 153, 278, +226, 288, 168, 282, 132, 196, 198, 40, +214, -63, 96, -86, -119, -84, -355, -21, +-546, 85, -614, 92, -504, -44, -241, -206, +111, -317, 418, -297, 565, -106, 535, 148, +307, 332, -78, 400, -454, 326, -642, 99, +-602, -185, -428, -400, -198, -438, 27, -293, +284, -28, 519, 282, 546, 542, 321, 614, +-59, 433, -451, 82, -747, -292, -809, -563, +-535, -687, -69, -625, 359, -346, 612, 88, +616, 499, 387, 755, 1, 742, -395, 412, +-627, -77, -539, -459, -195, -558, 134, -378, +247, -77, 76, 144, -251, 225, -511, 174, +-450, 44, -26, -82, 422, -133, 572, -104, +402, -11, 75, 103, -254, 191, -455, 244, +-412, 201, -229, 22, -108, -200, -102, -325, +-150, -334, -102, -216, 70, 19, 212, 261, +193, 395, 67, 378, -68, 209, -224, -69, +-342, -312, -324, -395, -162, -312, 40, -117, +183, 152, 252, 342, 221, 317, 64, 168, +-197, 39, -445, -65, -467, -107, -271, -70, +-33, -53, 166, -72, 258, -83, 202, -105, +29, -108, -129, -14, -226, 97, -274, 165, +-271, 200, -237, 138, -116, -30, 111, -173, +320, -194, 345, -84, 166, 88, -102, 178, +-343, 192, -414, 179, -267, 85, -56, -49, +57, -107, 34, -139, -29, -186, -82, -179, +-122, -158, -88, -161, -26, -92, -24, 78, +-102, 241, -167, 337, -118, 351, 24, 258, +183, 62, 264, -134, 188, -202, -11, -140, +-196, -40, -269, 33, -261, 0, -236, -161, +-217, -269, -213, -226, -196, -95, -156, 104, +-29, 333, 146, 424, 224, 319, 190, 89, +139, -192, 134, -381, 123, -363, 79, -184, +-35, 37, -280, 233, -534, 378, -629, 449, +-511, 344, -203, 22, 185, -346, 483, -570, +523, -564, 284, -294, -92, 116, -390, 423, +-431, 520, -257, 387, -3, 77, 190, -242, +198, -424, 6, -426, -185, -219, -170, 104, +-73, 367, -44, 496, -54, 444, -97, 194, +-161, -100, -155, -275, -30, -329, 103, -254, +109, -82, 25, 67, -89, 139, -165, 120, +-157, -37, -103, -263, -83, -399, -140, -342, +-161, -40, -43, 364, 181, 626, 357, 656, +357, 479, 154, 139, -194, -155, -520, -270, +-676, -358, -632, -470, -395, -449, 11, -300, +485, -135, 784, 108, 722, 389, 360, 504, +-169, 417, -649, 215, -866, -131, -724, -511, +-313, -627, 111, -403, 397, -4, 527, 447, +495, 807, 279, 814, -60, 450, -402, -37, +-627, -470, -602, -749, -314, -732, 67, -439, +376, -79, 482, 190, 347, 331, 70, 330, +-202, 198, -409, 31, -573, -51, -559, -7, +-292, 86, 113, 166, 463, 215, 606, 172, +493, -6, 165, -219, -191, -327, -385, -262, +-403, -61, -346, 122, -296, 178, -240, 120, +-137, 1, -7, -130, 133, -181, 242, -152, +241, -85, 121, 25, 18, 150, -24, 234, +-95, 271, -156, 231, -220, 61, -320, -119, +-310, -177, -56, -134, 235, -50, 276, 62, +169, 116, 108, 44, 29, -49, -114, -75, +-257, -118, -417, -236, -584, -273, -554, -144, +-176, 27, 339, 160, 713, 306, 780, 407, +484, 395, -44, 302, -498, 122, -658, -141, +-566, -351, -303, -424, 36, -414, 295, -272, +353, 16, 201, 275, -76, 338, -360, 221, +-498, -11, -366, -255, -59, -337, 257, -179, +435, 93, 357, 314, 81, 445, -222, 437, +-390, 255, -344, -51, -81, -357, 224, -524, +355, -450, 264, -188, -12, 126, -366, 393, +-586, 457, -543, 198, -335, -210, -77, -466, +203, -479, 391, -247, 416, 158, 378, 493, +257, 593, -25, 498, -335, 248, -459, -85, +-428, -338, -345, -459, -121, -481, 201, -374, +403, -138, 354, 115, 71, 311, -308, 407, +-554, 370, -493, 198, -195, -59, 137, -274, +372, -312, 439, -161, 302, 72, 28, 269, +-194, 288, -276, 98, -301, -155, -279, -330, +-199, -384, -111, -254, -58, 62, 14, 374, +145, 503, 237, 438, 260, 219, 226, -85, +65, -306, -225, -353, -497, -297, -590, -233, +-447, -159, -124, -57, 252, 76, 509, 209, +533, 294, 312, 312, -52, 262, -354, 143, +-455, -21, -350, -127, -157, -161, 13, -190, +90, -209, 88, -142, 59, -38, 11, -3, +-26, -25, -36, -43, -35, -24, -45, 80, +-88, 241, -124, 330, -93, 326, -22, 222, +65, -23, 161, -303, 201, -415, 46, -358, +-285, -216, -546, 3, -531, 209, -228, 266, +196, 166, 524, 21, 585, -85, 376, -103, +16, -23, -346, 121, -514, 226, -411, 223, +-176, 129, 16, -28, 87, -227, 23, -373, +-118, -358, -169, -179, -56, 101, 86, 329, +190, 362, 242, 225, 198, 20, 52, -188, +-115, -297, -209, -244, -237, -84, -234, 136, +-213, 320, -175, 331, -96, 169, 66, -16, +231, -131, 250, -147, 135, -102, -15, -59, +-174, -44, -270, -65, -218, -130, -82, -170, +13, -118, 59, -17, 124, 106, 138, 221, +70, 275, -25, 247, -139, 176, -250, 82, +-245, -13, -87, -67, 81, -68, 149, -61, +110, -140, -46, -291, -218, -371, -237, -269, +-124, -13, 5, 296, 128, 485, 224, 426, +201, 150, 82, -170, -56, -356, -188, -368, +-286, -236, -319, 45, -230, 381, -52, 533, +138, 438, 270, 186, 279, -167, 161, -492, +-30, -591, -231, -455, -350, -145, -282, 248, +-54, 474, 112, 420, 76, 210, -22, -75, +-31, -368, 9, -453, 31, -277, 85, 19, +124, 316, 15, 516, -161, 505, -228, 264, +-178, -71, -79, -315, 83, -361, 207, -250, +129, -52, -106, 110, -322, 104, -369, -67, +-185, -273, 106, -397, 316, -319, 325, -15, +144, 368, -76, 650, -171, 680, -114, 423, +-28, 62, 2, -204, -79, -365, -250, -398, +-365, -300, -264, -183, 8, -110, 255, -33, +392, 62, 409, 142, 239, 188, -100, 177, +-403, 119, -494, -1, -393, -153, -188, -224, +71, -136, 249, 71, 280, 306, 222, 396, +108, 251, -40, 12, -159, -223, -189, -400, +-179, -358, -121, -86, 19, 131, 107, 188, +5, 153, -138, 31, -139, -161, -76, -298, +-11, -249, 100, 6, 155, 350, 65, 607, +-58, 636, -113, 315, -76, -259, 49, -750, +190, -908, 147, -665, -118, -51, -394, 613, +-480, 915, -283, 790, 115, 340, 444, -294, +443, -768, 114, -770, -290, -415, -491, 44, +-346, 413, 107, 539, 571, 404, 670, 167, +299, -44, -293, -203, -776, -289, -909, -262, +-601, -107, -26, 77, 489, 181, 676, 167, +546, 64, 288, -65, 60, -119, -103, -89, +-242, -33, -362, 66, -452, 187, -467, 210, +-291, 95, 67, -65, 393, -221, 512, -325, +393, -286, 111, -64, -211, 224, -380, 426, +-322, 435, -150, 213, 38, -120, 201, -335, +233, -335, 48, -241, -191, -121, -304, 13, +-269, 120, -106, 182, 122, 222, 261, 186, +236, 87, 128, 44, 43, 30, -34, -48, +-153, -144, -270, -202, -290, -262, -152, -238, +88, -66, 295, 139, 288, 252, -5, 276, +-407, 197, -616, 36, -432, -71, 102, -81, +679, -90, 895, -100, 599, -21, 4, 69, +-517, 79, -748, 58, -696, 29, -444, -82, +-96, -192, 242, -166, 519, -69, 603, 50, +371, 218, -42, 304, -424, 164, -629, -37, +-508, -174, -50, -316, 407, -374, 579, -160, +496, 201, 233, 482, -167, 622, -520, 525, +-646, 105, -550, -458, -259, -836, 155, -863, +477, -494, 537, 154, 397, 744, 168, 907, +-107, 598, -331, 54, -365, -459, -259, -695, +-163, -521, -76, -98, 23, 277, 113, 496, +173, 496, 162, 218, 55, -202, -86, -475, +-178, -455, -151, -168, 25, 231, 260, 517, +349, 546, 156, 278, -216, -198, -524, -644, +-577, -819, -335, -668, 86, -225, 402, 376, +430, 901, 230, 1110, -34, 873, -202, 246, +-171, -519, -25, -1075, 50, -1159, 78, -720, +132, -14, 70, 653, -127, 1072, -235, 1030, +-200, 448, -146, -323, -95, -875, 12, -1074, +150, -841, 227, -176, 186, 608, 25, 1084, +-178, 1052, -305, 527, -266, -235, -101, -836, +112, -994, 287, -719, 316, -168, 208, 474, +92, 939, 6, 930, -143, 451, -352, -161, +-485, -643, -451, -851, -249, -679, 93, -223, +427, 231, 566, 562, 449, 701, 157, 517, +-214, 67, -545, -391, -624, -649, -348, -634, +143, -341, 612, 117, 836, 552, 599, 787, +-67, 759, -762, 447, -1049, -98, -823, -636, +-278, -913, 355, -906, 821, -635, 833, -54, +437, 607, 22, 979, -250, 937, -477, 561, +-569, -44, -367, -646, -44, -954, 192, -788, +347, -214, 379, 463, 221, 913, -35, 896, +-269, 360, -409, -405, -368, -896, -138, -891, +143, -443, 303, 248, 295, 795, 190, 859, +67, 495, -55, -63, -185, -585, -298, -773, +-316, -549, -194, -130, -12, 252, 193, 486, +395, 459, 458, 229, 268, -2, -90, -100, +-418, -95, -556, -56, -430, -14, -118, -14, +189, -90, 339, -205, 278, -257, 56, -190, +-124, 38, -117, 335, 15, 483, 123, 367, +137, 84, 48, -254, -77, -497, -128, -445, +-97, -159, -79, 136, -122, 358, -135, 468, +-107, 327, -96, 25, -38, -236, 109, -425, +221, -518, 238, -348, 212, 53, 137, 415, +-29, 639, -250, 675, -404, 359, -384, -219, +-126, -632, 285, -758, 590, -695, 516, -336, +72, 283, -457, 732, -785, 796, -720, 606, +-239, 206, 358, -321, 660, -683, 584, -708, +257, -476, -134, -39, -300, 471, -144, 769, +27, 684, 30, 299, -25, -241, -85, -730, +-171, -870, -203, -584, -114, -109, 0, 345, +102, 721, 216, 828, 234, 592, 66, 187, +-112, -268, -150, -679, -152, -768, -148, -463, +-45, -82, 75, 197, 86, 395, 73, 410, +97, 220, 92, 47, 46, -58, -15, -168, +-116, -179, -177, -21, -125, 112, -65, 133, +-71, 147, -33, 112, 110, -46, 198, -197, +162, -256, 86, -319, -67, -286, -305, -21, +-410, 282, -263, 409, 26, 416, 340, 295, +520, -27, 383, -337, 22, -378, -275, -201, +-391, 21, -314, 225, -53, 311, 252, 209, +333, -3, 113, -192, -220, -313, -453, -325, +-457, -189, -192, 13, 229, 157, 513, 217, +487, 240, 244, 216, -57, 171, -279, 81, +-285, -98, -154, -254, -56, -200, -11, -20, +-15, 66, -69, 36, -31, -27, 174, -81, +335, -102, 251, -39, -51, 60, -385, 125, +-548, 111, -404, 33, -33, -40, 339, -10, +563, 104, 554, 175, 246, 143, -225, 29, +-538, -183, -565, -472, -406, -574, -120, -305, +282, 191, 602, 624, 615, 804, 332, 605, +-58, 77, -398, -457, -623, -706, -625, -646, +-322, -366, 150, 71, 520, 455, 673, 599, +542, 476, 100, 156, -419, -252, -669, -520, +-544, -471, -193, -201, 177, 72, 402, 248, +389, 287, 189, 140, -6, -27, -93, -23, +-106, 83, -86, 113, -19, 110, 60, 116, +92, 12, 45, -213, -80, -397, -190, -428, +-203, -276, -185, 47, -197, 359, -147, 481, +-24, 393, 117, 193, 320, -73, 523, -346, +514, -513, 271, -477, -41, -232, -329, 173, +-557, 624, -620, 837, -371, 667, 87, 295, +454, -113, 537, -597, 323, -989, -146, -999, +-643, -648, -772, -127, -375, 491, 268, 999, +772, 1058, 920, 626, 610, -12, -32, -509, +-599, -686, -752, -551, -541, -221, -156, 186, +281, 517, 573, 605, 510, 390, 152, -15, +-265, -416, -574, -688, -632, -702, -405, -391, +-31, 93, 317, 487, 552, 699, 618, 667, +464, 341, 125, -126, -234, -514, -488, -734, +-600, -675, -440, -238, 46, 369, 548, 807, +702, 885, 469, 609, -38, 92, -627, -444, +-977, -801, -843, -900, -276, -734, 473, -289, +1045, 318, 1110, 801, 667, 975, -9, 797, +-642, 270, -1038, -427, -1025, -921, -531, -1038, +236, -740, 890, -37, 1163, 748, 921, 1157, +197, 1071, -648, 586, -1148, -177, -1096, -902, +-552, -1253, 253, -1056, 883, -385, 994, 428, +608, 976, -13, 1094, -589, 774, -873, 122, +-722, -592, -213, -1083, 402, -1098, 833, -561, +903, 210, 607, 801, 84, 1104, -474, 1026, +-830, 493, -852, -223, -589, -750, -181, -980, +272, -907, 625, -517, 667, 77, 425, 644, +91, 923, -236, 820, -471, 407, -430, -191, +-138, -783, 202, -1074, 464, -896, 547, -254, +342, 644, -97, 1340, -549, 1436, -793, 857, +-717, -175, -329, -1183, 230, -1608, 660, -1295, +747, -472, 554, 487, 242, 1172, -151, 1324, +-507, 965, -582, 243, -360, -570, -38, -1072, +261, -1071, 462, -618, 430, 70, 167, 680, +-176, 908, -462, 693, -604, 211, -490, -255, +-120, -537, 294, -595, 564, -399, 674, -48, +580, 253, 180, 426, -336, 478, -637, 283, +-610, -91, -351, -365, 18, -414, 317, -312, +374, -123, 214, 117, 24, 321, -88, 380, +-151, 269, -177, 106, -132, -68, 11, -246, +191, -312, 296, -222, 246, -142, 59, -100, +-166, 11, -307, 154, -291, 281, -143, 392, +19, 338, 94, 24, 116, -324, 161, -489, +223, -431, 171, -161, -15, 248, -150, 573, +-163, 632, -189, 359, -200, -190, -91, -749, +21, -954, 65, -654, 164, -44, 314, 596, +316, 991, 149, 928, -53, 428, -240, -207, +-403, -684, -427, -859, -243, -663, 8, -173, +191, 397, 341, 802, 428, 853, 296, 469, +41, -180, -101, -767, -164, -1000, -267, -773, +-310, -197, -225, 422, -71, 796, 134, 824, +321, 533, 308, 39, 69, -435, -154, -620, +-200, -456, -104, -74, 42, 299, 133, 456, +84, 333, -20, 52, -57, -253, -64, -455, +-60, -418, 24, -189, 131, 79, 98, 294, +-36, 374, -129, 240, -179, 18, -181, -116, +-42, -126, 170, -65, 257, 9, 154, 34, +-29, 6, -167, -17, -169, -11, 15, 38, +235, 89, 284, 93, 151, 22, -64, -77, +-298, -146, -409, -173, -312, -184, -117, -141, +97, -16, 304, 106, 383, 204, 249, 297, +31, 298, -131, 134, -217, -70, -236, -209, +-135, -250, 60, -175, 228, -28, 276, 86, +201, 132, 42, 117, -183, 15, -383, -118, +-432, -179, -268, -146, 60, -73, 369, 58, +465, 224, 364, 260, 170, 121, -87, 2, +-328, -9, -413, -11, -337, -15, -181, -44, +34, -206, 229, -416, 316, -417, 334, -171, +350, 213, 240, 635, -50, 902, -339, 759, +-502, 220, -533, -442, -363, -975, 16, -1193, +385, -927, 540, -171, 444, 685, 152, 1181, +-192, 1136, -383, 605, -335, -192, -115, -814, +156, -929, 329, -573, 304, 14, 131, 492, +-89, 595, -293, 342, -370, -35, -263, -331, +-51, -383, 133, -171, 242, 136, 278, 354, +214, 378, 63, 165, -108, -177, -246, -445, +-294, -533, -176, -399, 31, -51, 190, 409, +242, 760, 185, 793, 13, 448, -173, -107, +-203, -639, -40, -961, 155, -923, 180, -484, +55, 206, -44, 855, -79, 1209, -154, 1088, +-190, 460, -97, -473, -29, -1237, -38, -1412, +52, -939, 238, -77, 316, 780, 240, 1243, +109, 1117, -54, 543, -215, -172, -263, -709, +-235, -905, -210, -740, -128, -313, 35, 193, +167, 569, 213, 699, 241, 556, 238, 188, +131, -202, -51, -436, -211, -524, -296, -493, +-242, -270, -57, 121, 113, 504, 169, 663, +151, 512, 75, 118, -65, -363, -163, -720, +-137, -749, -65, -414, 12, 124, 198, 677, +387, 979, 330, 807, 41, 248, -255, -381, +-450, -840, -509, -934, -359, -598, -33, -48, +304, 446, 504, 738, 526, 717, 387, 342, +106, -196, -259, -632, -517, -779, -521, -584, +-292, -66, 40, 588, 337, 1006, 436, 896, +261, 344, -37, -328, -278, -859, -367, -1045, +-249, -769, 77, -114, 442, 598, 579, 1040, +398, 1016, 32, 492, -368, -310, -657, -971, +-656, -1184, -370, -893, 6, -164, 349, 706, +580, 1202, 551, 1069, 297, 514, 13, -201, +-192, -783, -319, -882, -303, -471, -145, 84, +-9, 457, 63, 518, 141, 250, 193, -171, +141, -457, -20, -441, -228, -210, -354, 79, +-268, 291, 18, 325, 312, 199, 456, 72, +387, 28, 96, 7, -277, 14, -508, 17, +-469, -90, -172, -240, 261, -228, 597, -70, +642, 128, 334, 266, -208, 215, -682, -6, +-820, -226, -554, -345, -33, -293, 490, -7, +789, 316, 738, 434, 345, 333, -189, 101, +-584, -209, -672, -446, -499, -451, -162, -208, +237, 178, 522, 517, 590, 612, 449, 382, +142, -61, -242, -488, -534, -685, -644, -582, +-539, -207, -179, 260, 340, 572, 712, 615, +717, 401, 438, 15, 18, -346, -433, -500, +-690, -443, -588, -226, -267, 77, 75, 314, +346, 388, 465, 352, 376, 223, 201, 3, +30, -238, -178, -424, -331, -468, -284, -293, +-115, 77, 43, 475, 198, 665, 278, 499, +136, 80, -150, -388, -329, -723, -297, -766, +-92, -434, 169, 148, 313, 679, 272, 890, +135, 679, -16, 163, -160, -419, -205, -784, +-129, -777, -36, -416, 35, 163, 123, 704, +183, 877, 122, 597, -28, 85, -146, -469, +-161, -893, -107, -912, -38, -449, 22, 195, +46, 694, 18, 865, -17, 622, -8, 81, +47, -419, 98, -627, 131, -521, 126, -180, +47, 242, -47, 520, -87, 494, -65, 209, +-31, -162, -11, -440, 9, -474, -21, -234, +-128, 82, -194, 266, -162, 276, -93, 140, +20, -68, 201, -190, 355, -141, 353, -34, +222, 34, 41, 85, -138, 155, -247, 205, +-244, 221, -189, 185, -137, 42, -87, -216, +-31, -480, 52, -584, 141, -455, 177, -116, +118, 340, 12, 735, -33, 825, -31, 533, +-51, 30, -34, -435, 35, -692, 74, -663, +65, -391, 43, -40, -18, 270, -144, 457, +-216, 435, -148, 240, -15, 18, 125, -138, +267, -189, 289, -111, 95, 51, -163, 172, +-293, 138, -280, -53, -181, -267, -25, -380, +127, -359, 197, -148, 190, 224, 188, 508, +220, 515, 207, 300, 47, -37, -213, -350, +-414, -439, -456, -280, -301, -13, -36, 217, +195, 316, 314, 247, 318, 75, 238, -115, +119, -256, -16, -290, -167, -205, -275, -56, +-265, 85, -155, 185, 37, 235, 267, 207, +356, 88, 214, -52, -23, -155, -185, -224, +-257, -194, -245, 8, -122, 255, 48, 362, +170, 280, 204, 45, 155, -265, 43, -501, +-100, -478, -236, -188, -271, 176, -110, 445, +157, 510, 304, 280, 290, -154, 182, -495, +-32, -521, -261, -267, -265, 158, -77, 593, +22, 763, 10, 546, 31, 80, 58, -388, +11, -698, -19, -758, -10, -516, -110, -63, +-247, 318, -190, 464, 48, 439, 316, 280, +528, 27, 552, -137, 266, -113, -224, -17, +-619, 45, -746, 41, -572, -57, -145, -196, +344, -242, 654, -124, 655, 123, 348, 370, +-113, 447, -467, 281, -559, -106, -399, -527, +-109, -705, 192, -553, 410, -162, 447, 356, +330, 769, 181, 815, -7, 484, -272, -32, +-496, -527, -517, -786, -324, -642, -12, -199, +340, 284, 548, 600, 440, 645, 98, 424, +-258, 43, -463, -336, -416, -545, -113, -527, +267, -329, 482, -40, 432, 206, 171, 310, +-189, 287, -447, 224, -433, 162, -213, 94, +37, 23, 232, -60, 299, -187, 189, -309, +8, -306, -91, -160, -88, 53, -73, 230, +-75, 304, -80, 262, -66, 131, 24, -45, +183, -207, 272, -264, 190, -173, 9, -30, +-171, 78, -291, 136, -281, 96, -129, -14, +36, -83, 111, -66, 112, -21, 82, 17, +54, 76, 72, 119, 108, 107, 94, 98, +42, 91, -27, 35, -115, -46, -190, -103, +-171, -162, -66, -240, 9, -238, 12, -126, +2, 5, -10, 114, -10, 221, 55, 255, +142, 171, 169, 68, 137, 5, 62, -47, +-49, -80, -116, -30, -97, 51, -51, 56, +-33, -35, -54, -169, -117, -285, -163, -295, +-98, -142, 39, 113, 178, 322, 275, 371, +235, 311, 39, 163, -170, -89, -250, -327, +-175, -392, 15, -280, 229, -74, 272, 195, +74, 416, -154, 395, -260, 157, -255, -96, +-101, -260, 155, -341, 263, -313, 133, -132, +-46, 100, -140, 235, -171, 269, -121, 219, +58, 41, 220, -179, 210, -249, 102, -148, +10, -6, -93, 134, -216, 246, -238, 235, +-100, 109, 55, -26, 137, -135, 160, -229, +106, -252, -26, -183, -158, -77, -178, 43, +-69, 175, 56, 259, 109, 214, 115, 102, +89, -1, 15, -114, -61, -173, -72, -99, +-42, 27, -30, 97, -37, 87, -31, 11, +-32, -88, -66, -138, -58, -118, 41, -63, +164, 42, 196, 183, 110, 254, -48, 224, +-199, 103, -234, -106, -98, -324, 135, -421, +270, -334, 150, -111, -149, 175, -362, 409, +-330, 463, -83, 338, 303, 130, 619, -112, +562, -332, 113, -409, -388, -286, -663, -56, +-678, 163, -406, 295, 128, 256, 587, 56, +664, -162, 438, -277, 85, -263, -285, -133, +-492, 70, -407, 262, -138, 374, 129, 361, +324, 232, 383, 39, 227, -174, -52, -349, +-294, -461, -429, -465, -417, -330, -212, -71, +107, 259, 347, 539, 398, 660, 318, 562, +159, 236, -34, -205, -130, -551, -122, -635, +-139, -470, -176, -164, -146, 200, -64, 462, +-11, 458, 35, 238, 111, -57, 98, -305, +-39, -400, -119, -296, -54, -30, 73, 266, +172, 437, 221, 392, 156, 179, -49, -91, +-255, -330, -329, -426, -274, -315, -113, -69, +127, 191, 348, 369, 417, 375, 278, 198, +12, -51, -256, -273, -439, -388, -452, -350, +-254, -182, 73, 47, 365, 253, 447, 371, +294, 333, 47, 119, -169, -130, -294, -258, +-279, -234, -90, -79, 149, 152, 254, 349, +205, 351, 65, 138, -127, -152, -282, -414, +-280, -539, -123, -469, 72, -237, 234, 81, +295, 365, 175, 521, -45, 499, -205, 334, +-261, 108, -223, -131, -79, -314, 100, -362, +217, -278, 276, -119, 250, 68, 106, 204, +-55, 225, -165, 162, -298, 63, -398, -76, +-310, -211, -63, -270, 198, -255, 407, -173, +498, 7, 365, 213, 39, 332, -298, 355, +-527, 273, -560, 86, -296, -114, 135, -253, +482, -273, 620, -175, 501, -8, 127, 180, +-344, 271, -636, 161, -640, -118, -420, -375, +-31, -458, 383, -343, 595, -38, 547, 331, +321, 557, 22, 562, -260, 363, -433, 19, +-432, -330, -295, -506, -72, -396, 204, -97, +411, 183, 418, 319, 214, 247, -140, 9, +-456, -231, -538, -310, -359, -247, -16, -121, +337, 60, 570, 230, 586, 298, 376, 259, +57, 155, -288, 2, -584, -123, -668, -151, +-472, -126, -87, -86, 302, -35, 544, 20, +546, 69, 271, 95, -123, 70, -406, -36, +-480, -181, -311, -262, 45, -233, 370, -80, +501, 163, 411, 346, 121, 397, -253, 318, +-486, 122, -442, -145, -221, -348, 9, -347, +168, -207, 201, 1, 127, 208, 73, 266, +105, 159, 156, -18, 101, -190, -78, -297, +-276, -271, -382, -115, -308, 82, -46, 252, +291, 343, 508, 299, 438, 127, 136, -51, +-184, -147, -376, -154, -382, -125, -211, -95, +37, -86, 210, -78, 213, -32, 89, 39, +-69, 94, -174, 108, -174, 90, -74, 31, +77, -6, 200, -21, 242, -79, 201, -101, +71, -30, -107, 58, -243, 91, -289, 82, +-228, 40, -84, -68, 90, -141, 240, -99, +279, -20, 155, 58, -56, 141, -196, 198, +-185, 159, -111, -5, -12, -184, 138, -288, +215, -277, 113, -94, -65, 165, -164, 288, +-183, 209, -175, 44, -63, -100, 123, -177, +190, -99, 146, 89, 97, 203, 24, 176, +-62, 56, -85, -135, -28, -335, 16, -338, +-31, -91, -123, 210, -193, 364, -182, 362, +-66, 193, 89, -143, 241, -398, 327, -348, +234, -112, 22, 130, -164, 302, -260, 315, +-252, 137, -135, -137, 53, -336, 168, -362, +116, -208, 9, 49, -66, 252, -61, 326, +54, 234, 163, 55, 153, -16, 3, 15, +-186, 41, -248, 4, -158, -97, -13, -224, +98, -317, 115, -278, 55, -122, -43, 48, +-103, 202, -42, 321, 88, 333, 192, 214, +201, 59, 93, -95, -63, -241, -183, -258, +-210, -97, -125, 53, -20, 100, 36, 116, +24, 92, -58, -14, -127, -129, -97, -181, +47, -160, 197, -35, 231, 118, 178, 215, +71, 206, -109, 91, -249, -54, -193, -150, +13, -121, 170, -6, 204, 83, 133, 102, +-90, 46, -366, -47, -453, -155, -290, -195, +-16, -94, 266, 70, 495, 218, 549, 274, +349, 156, 10, -71, -299, -290, -505, -376, +-513, -205, -286, 137, 47, 413, 286, 462, +338, 284, 271, -77, 153, -469, 1, -632, +-161, -476, -297, -72, -316, 410, -162, 713, +96, 683, 361, 330, 488, -197, 363, -658, +-7, -780, -435, -543, -650, -111, -598, 336, +-349, 632, 103, 663, 588, 411, 799, 4, +643, -373, 251, -592, -203, -542, -556, -193, +-605, 238, -338, 513, -20, 546, 183, 346, +269, -55, 196, -470, -8, -646, -211, -596, +-283, -362, -184, 67, 1, 510, 225, 769, +413, 751, 432, 474, 271, 12, -21, -468, +-325, -722, -468, -666, -406, -373, -173, 39, +123, 386, 327, 491, 336, 338, 96, 80, +-231, -158, -394, -306, -340, -292, -132, -133, +159, 67, 421, 248, 521, 345, 393, 298, +138, 136, -157, -98, -464, -346, -599, -452, +-435, -323, -91, -84, 238, 202, 430, 449, +460, 504, 307, 294, -9, -66, -305, -366, +-429, -538, -388, -501, -219, -209, 35, 189, +316, 465, 461, 495, 352, 309, 103, -15, +-130, -330, -256, -387, -241, -202, -115, 29, +37, 244, 112, 352, 87, 239, -7, -23, +-155, -249, -255, -348, -207, -354, -11, -216, +257, 67, 419, 353, 375, 493, 194, 415, +-60, 181, -344, -123, -519, -401, -459, -542, +-234, -490, 9, -246, 257, 95, 462, 397, +472, 539, 294, 511, 66, 295, -129, -56, +-259, -308, -281, -339, -190, -211, -84, -32, +-27, 107, -4, 101, -37, -58, -88, -243, +-94, -316, -45, -255, 61, -48, 152, 217, +162, 389, 167, 441, 232, 350, 285, 145, +227, -89, 94, -194, -56, -134, -306, -107, +-589, -131, -691, -126, -550, -172, -214, -260, +242, -220, 653, -20, 778, 163, 523, 279, +96, 366, -256, 327, -425, 139, -349, -50, +-121, -176, 73, -249, 156, -210, 138, -63, +88, 47, 36, 52, -33, 61, -91, 99, +-138, 76, -140, 11, -70, -21, -7, -60, +21, -130, 26, -120, 3, -64, -38, -30, +-76, -12, -49, 0, 43, 18, 132, 45, +212, 130, 244, 220, 196, 268, 125, 248, +7, 119, -167, -73, -308, -273, -354, -431, +-308, -435, -206, -277, -44, -50, 134, 166, +198, 285, 157, 277, 99, 159, 38, 13, +21, -68, 74, -74, 149, -5, 170, 103, +96, 198, -30, 197, -177, 75, -289, -64, +-267, -182, -114, -264, 82, -261, 200, -188, +149, -117, -10, -41, -166, 92, -237, 228, +-168, 289, 8, 231, 208, 67, 330, -104, +296, -183, 121, -118, -115, 20, -301, 121, +-348, 154, -225, 113, 26, -15, 258, -158, +348, -229, 284, -194, 98, -90, -131, 83, +-297, 248, -364, 232, -331, 81, -188, -115, +49, -252, 263, -238, 332, -75, 277, 143, +130, 251, -96, 218, -269, 122, -254, 0, +-68, -100, 145, -118, 274, -58, 279, -18, +125, -21, -118, -9, -283, -15, -301, -50, +-235, -27, -170, 26, -81, 15, 90, -20, +258, -17, 335, -1, 302, 11, 111, 59, +-195, 120, -417, 126, -375, 67, -96, -5, +236, -74, 488, -155, 521, -156, 239, -92, +-214, -44, -609, 22, -752, 98, -531, 120, +-29, 58, 500, 42, 771, 67, 664, 36, +259, -15, -267, -62, -637, -99, -650, -78, +-368, -11, 42, 55, 386, 75, 527, 21, +447, -51, 184, -123, -132, -156, -350, -106, +-432, 18, -377, 163, -203, 274, 54, 333, +331, 257, 501, 27, 467, -227, 188, -397, +-249, -405, -598, -251, -685, -27, -454, 171, +50, 298, 571, 305, 810, 197, 662, 62, +241, -80, -268, -207, -681, -245, -753, -188, +-432, -82, 21, 46, 379, 181, 532, 260, +386, 196, 20, 19, -302, -137, -380, -205, +-243, -172, -19, -34, 224, 164, 377, 263, +333, 200, 135, 88, -113, -98, -319, -300, +-408, -395, -321, -355, -77, -198, 174, 61, +312, 373, 320, 542, 185, 458, -44, 218, +-238, -68, -288, -314, -191, -403, -22, -283, +154, -65, 268, 99, 238, 198, 85, 216, +-92, 82, -214, -92, -265, -173, -244, -200, +-110, -181, 110, -68, 295, 81, 345, 179, +242, 240, 12, 245, -251, 175, -379, 58, +-288, -98, -87, -238, 109, -279, 251, -186, +254, -29, 113, 116, -57, 224, -170, 204, +-197, 59, -115, -132, 62, -262, 196, -281, +190, -194, 106, 13, -14, 232, -147, 345, +-210, 382, -178, 307, -100, 64, -8, -184, +101, -348, 193, -432, 202, -359, 120, -63, +-41, 245, -232, 344, -310, 304, -214, 136, +0, -144, 260, -334, 401, -290, 293, -76, +25, 157, -203, 324, -287, 335, -233, 145, +-62, -138, 133, -319, 158, -311, 3, -165, +-137, 59, -157, 227, -80, 232, 37, 127, +156, 17, 193, -53, 78, -69, -69, -51, +-102, -47, -39, -81, 70, -112, 163, -103, +165, -46, 32, 45, -175, 88, -305, 79, +-286, 79, -145, 52, 72, 57, 242, 97, +263, 132, 149, 119, -44, 13, -206, -143, +-223, -284, -109, -316, 49, -224, 188, -56, +290, 130, 274, 246, 105, 229, -96, 132, +-253, 35, -368, -15, -355, -40, -168, -62, +77, -60, 263, -69, 352, -79, 301, -22, +60, 57, -214, 83, -305, 76, -227, 67, +-90, 8, 78, -45, 222, -38, 248, -16, +166, -3, 76, -15, -1, -66, -119, -150, +-241, -168, -268, -72, -192, 54, -70, 169, +77, 235, 208, 225, 226, 120, 122, -30, +12, -114, -48, -144, -85, -142, -84, -81, +-34, -8, 7, 22, 6, 47, 10, 49, +45, 20, 72, -15, 62, -6, -1, 4, +-101, -28, -172, -46, -149, -48, -37, -14, +83, 52, 129, 113, 83, 141, -28, 103, +-128, 2, -126, -109, 5, -165, 192, -157, +297, -85, 230, 39, 4, 161, -274, 238, +-427, 222, -343, 99, -81, -89, 219, -257, +406, -324, 358, -269, 100, -143, -180, 0, +-301, 142, -259, 270, -148, 327, -26, 282, +60, 161, 113, -33, 187, -239, 266, -343, +283, -293, 172, -102, -69, 111, -326, 278, +-473, 323, -440, 170, -231, -91, 72, -315, +353, -391, 489, -288, 424, 6, 197, 348, +-133, 515, -433, 428, -521, 138, -337, -253, +8, -540, 332, -560, 468, -330, 366, 72, +108, 488, -164, 695, -324, 550, -319, 153, +-170, -291, 3, -615, 106, -679, 169, -443, +177, -18, 89, 382, -35, 609, -128, 584, +-185, 298, -188, -90, -85, -420, 92, -578, +213, -483, 237, -136, 197, 277, 86, 518, +-79, 545, -210, 332, -230, -102, -145, -499, +-28, -623, 73, -444, 144, -55, 124, 384, +-10, 646, -159, 569, -191, 208, -90, -225, +61, -535, 189, -581, 238, -379, 172, -46, +45, 287, -61, 473, -124, 462, -157, 264, +-180, -7, -172, -232, -85, -359, 74, -351, +226, -210, 285, -4, 217, 184, 41, 311, +-161, 325, -278, 187, -273, -48, -197, -292, +-87, -423, 57, -335, 198, -62, 283, 249, +292, 468, 204, 498, 38, 294, -123, -47, +-226, -347, -272, -514, -244, -496, -120, -277, +45, 20, 172, 271, 224, 393, 158, 379, +-14, 261, -165, 74, -174, -86, -59, -192, +108, -254, 239, -240, 223, -139, 31, 28, +-208, 171, -321, 233, -267, 180, -91, 19, +144, -174, 311, -299, 305, -265, 153, -63, +-46, 184, -188, 359, -217, 403, -143, 254, +-41, -31, 20, -286, 51, -409, 65, -410, +50, -273, 37, -19, 42, 226, 8, 370, +-58, 388, -80, 277, -49, 64, 6, -141, +96, -243, 180, -263, 148, -201, -6, -65, +-155, 68, -236, 117, -231, 93, -109, 55, +69, -15, 201, -65, 231, -24, 149, 47, +17, 93, -76, 97, -97, 29, -100, -81, +-103, -134, -56, -96, 3, -20, 20, 47, +36, 87, 69, 62, 76, -4, 48, -51, +16, -56, -9, 13, -40, 96, -56, 149, +-37, 134, -19, 31, -28, -132, -41, -269, +-49, -287, -36, -180, 10, 2, 67, 169, +109, 254, 106, 236, 64, 148, 19, 50, +-17, -17, -50, -43, -105, -42, -171, -59, +-183, -117, -116, -159, -2, -146, 123, -89, +225, 17, 247, 158, 163, 231, 40, 178, +-60, 80, -137, -40, -173, -157, -137, -194, +-79, -129, -53, -10, -21, 92, 34, 146, +62, 114, 66, 2, 82, -94, 78, -119, +15, -56, -48, 57, -55, 152, -21, 164, +48, 74, 114, -54, 92, -151, -17, -188, +-129, -138, -195, -15, -180, 95, -53, 144, +109, 106, 182, 20, 150, -49, 71, -81, +-23, -96, -101, -71, -127, 2, -123, 55, +-105, 98, -28, 157, 102, 169, 206, 96, +233, -6, 159, -120, -7, -248, -184, -274, +-259, -136, -197, 69, -50, 227, 125, 269, +241, 161, 212, -65, 49, -258, -162, -279, +-332, -155, -364, 18, -193, 179, 126, 235, +416, 161, 495, 47, 314, -17, -18, -36, +-303, -27, -366, 39, -197, 91, 66, 49, +255, -59, 235, -192, 26, -269, -206, -254, +-306, -147, -248, 20, -104, 189, 67, 291, +191, 297, 205, 242, 154, 102, 94, -113, +27, -293, -30, -326, -35, -199, -7, 25, +-6, 254, -25, 358, -31, 255, -54, 17, +-88, -202, -62, -312, -11, -291, -13, -138, +-44, 80, -59, 219, -51, 212, -14, 91, +70, -91, 161, -212, 186, -181, 149, -19, +80, 182, -16, 314, -101, 316, -143, 161, +-137, -86, -89, -294, -24, -369, 36, -278, +60, -77, 35, 149, -13, 297, -64, 278, +-101, 114, -88, -106, -14, -282, 70, -339, +130, -246, 185, -27, 216, 242, 157, 447, +12, 496, -141, 341, -263, 20, -316, -328, +-228, -522, -25, -474, 179, -243, 274, 55, +208, 291, 29, 365, -129, 249, -162, 12, +-85, -217, 41, -314, 148, -218, 152, 9, +47, 250, -78, 375, -139, 307, -121, 95, +-41, -160, 52, -342, 97, -350, 95, -197, +69, 11, 13, 181, -58, 269, -106, 225, +-115, 52, -86, -129, -20, -220, 65, -204, +118, -83, 101, 96, 26, 227, -49, 228, +-73, 130, -37, 9, 22, -130, 69, -231, +91, -217, 79, -114, 44, 14, -13, 145, +-96, 242, -170, 224, -193, 111, -142, -42, +-34, -205, 85, -318, 173, -301, 195, -152, +158, 78, 83, 319, -24, 449, -112, 384, +-141, 149, -111, -148, -25, -381, 86, -437, +145, -294, 88, -39, -40, 195, -131, 312, +-154, 275, -116, 98, -28, -120, 45, -266, +62, -281, 60, -152, 70, 58, 85, 252, +95, 334, 91, 282, 57, 136, -19, -55, +-98, -210, -129, -266, -98, -216, -22, -97, +20, 20, -19, 77, -107, 62, -181, -15, +-152, -111, 24, -139, 261, -47, 415, 126, +381, 296, 170, 386, -125, 316, -363, 72, +-419, -231, -295, -426, -73, -407, 166, -202, +310, 87, 264, 305, 72, 336, -121, 163, +-214, -114, -205, -351, -120, -429, 23, -284, +157, 2, 229, 297, 258, 491, 240, 485, +114, 279, -128, -12, -372, -253, -481, -361, +-396, -306, -120, -134, 239, 52, 486, 161, +509, 150, 320, 43, -7, -72, -347, -120, +-514, -105, -419, -28, -153, 67, 153, 90, +382, 26, 415, -47, 250, -53, 34, 11, +-139, 130, -260, 250, -287, 245, -183, 79, +-9, -140, 156, -288, 256, -331, 220, -226, +43, 2, -161, 195, -272, 237, -246, 160, +-113, 17, 60, -155, 210, -233, 278, -159, +251, -16, 152, 109, 9, 200, -134, 218, +-223, 144, -204, 35, -97, -51, -5, -107, +39, -130, 42, -91, -10, -23, -70, 24, +-82, 34, -30, 3, 57, -41, 160, -59, +241, -34, 219, 8, 73, 44, -119, 53, +-262, 15, -279, -18, -158, 2, 28, 48, +192, 107, 252, 164, 173, 147, -4, 8, +-200, -186, -325, -327, -291, -340, -91, -192, +183, 82, 385, 349, 406, 454, 224, 343, +-77, 67, -312, -253, -361, -462, -249, -439, +-36, -220, 195, 76, 337, 341, 313, 472, +131, 382, -117, 113, -331, -169, -410, -352, +-297, -375, -58, -225, 193, 7, 362, 168, +388, 186, 268, 119, 57, 36, -157, -39, +-305, -58, -338, 8, -211, 96, 30, 124, +245, 79, 320, -4, 220, -109, -6, -198, +-237, -207, -359, -135, -317, -20, -129, 95, +122, 163, 342, 176, 449, 154, 397, 105, +185, 18, -134, -92, -422, -175, -542, -198, +-436, -146, -141, -31, 211, 106, 468, 194, +513, 205, 313, 152, -46, 43, -381, -87, +-519, -191, -393, -238, -66, -220, 310, -118, +550, 35, 512, 173, 180, 273, -265, 312, +-546, 223, -524, 21, -263, -179, 102, -303, +408, -321, 476, -200, 302, 30, 53, 221, +-146, 270, -268, 196, -293, 42, -235, -131, +-149, -235, -16, -211, 168, -90, 287, 66, +274, 206, 171, 254, 16, 181, -155, 54, +-239, -61, -164, -122, -15, -105, 108, -46, +174, -18, 134, -39, -25, -91, -205, -154, +-281, -177, -217, -128, -54, -14, 137, 149, +281, 325, 305, 404, 199, 328, 28, 148, +-117, -62, -186, -228, -185, -270, -118, -205, +-10, -132, 71, -95, 97, -83, 83, -83, +30, -96, -27, -51, -50, 82, -47, 225, +-29, 311, -2, 309, 18, 180, 1, -57, +-52, -257, -100, -295, -111, -185, -47, -8, +89, 159, 227, 227, 304, 177, 273, 70, +105, -44, -141, -143, -333, -217, -385, -237, +-298, -164, -113, -22, 100, 110, 246, 168, +272, 149, 191, 75, 30, -24, -138, -79, +-223, -51, -191, 31, -36, 125, 190, 210, +352, 232, 346, 129, 171, -61, -114, -240, +-405, -342, -535, -346, -399, -227, -83, -39, +249, 120, 478, 216, 511, 250, 315, 210, +-21, 98, -333, -45, -483, -154, -422, -185, +-189, -128, 112, 3, 353, 152, 446, 247, +350, 239, 105, 132, -175, -38, -362, -226, +-381, -341, -240, -321, -1, -187, 254, 6, +423, 180, 401, 277, 171, 272, -166, 192, +-448, 62, -567, -96, -450, -229, -99, -258, +321, -171, 586, -24, 590, 125, 360, 219, +-2, 196, -323, 73, -450, -56, -371, -133, +-172, -157, 75, -107, 255, -2, 261, 94, +125, 135, -47, 112, -159, 34, -172, -54, +-88, -103, 24, -98, 85, -31, 94, 39, +102, 61, 120, 28, 113, -28, 22, -84, +-147, -125, -305, -112, -345, -51, -201, 28, +97, 124, 397, 233, 529, 298, 427, 270, +138, 160, -212, -12, -483, -237, -562, -420, +-421, -451, -129, -346, 191, -151, 389, 103, +407, 328, 293, 420, 121, 365, -45, 216, +-173, 9, -253, -204, -261, -342, -174, -351, +2, -227, 204, -16, 338, 229, 317, 424, +122, 458, -157, 273, -373, -59, -425, -384, +-289, -562, -22, -502, 239, -213, 374, 182, +332, 490, 151, 558, -54, 380, -168, 40, +-154, -323, -83, -540, -32, -506, -14, -255, +0, 103, 45, 410, 107, 537, 105, 432, +10, 164, -115, -138, -189, -356, -163, -398, +-44, -271, 111, -57, 199, 146, 168, 253, +68, 226, -14, 78, -64, -121, -99, -243, +-99, -216, -39, -80, 49, 89, 105, 222, +114, 248, 70, 143, -38, -14, -161, -131, +-219, -195, -190, -199, -87, -107, 72, 45, +235, 161, 314, 208, 250, 211, 80, 139, +-98, -9, -205, -138, -228, -200, -174, -237, +-64, -219, 49, -115, 118, -4, 147, 86, +128, 180, 41, 240, -75, 208, -130, 111, +-108, 2, -64, -118, -5, -200, 51, -181, +78, -79, 92, 51, 112, 165, 91, 205, +-4, 141, -112, 4, -160, -141, -141, -249, +-64, -263, 32, -139, 79, 59, 70, 238, +61, 330, 61, 266, 35, 50, 0, -186, +-21, -320, -52, -333, -90, -212, -91, 30, +-50, 257, 7, 349, 85, 317, 150, 185, +142, -30, 61, -219, -42, -273, -120, -201, +-137, -61, -66, 77, 38, 130, 78, 52, +36, -88, -37, -182, -89, -192, -84, -97, +-28, 80, 62, 240, 154, 301, 195, 273, +133, 158, -8, -18, -138, -174, -193, -238, +-159, -211, -52, -126, 75, -19, 146, 42, +125, 44, 29, 24, -84, 8, -140, 18, +-110, 43, -22, 49, 84, 22, 164, -21, +166, -49, 66, -45, -77, -1, -168, 69, +-168, 121, -94, 114, 17, 57, 127, -25, +176, -105, 120, -142, -3, -90, -130, 19, +-208, 89, -169, 71, 10, -24, 210, -157, +280, -250, 182, -205, -19, -22, -225, 207, +-311, 377, -216, 414, -29, 282, 130, 12, +220, -249, 221, -358, 131, -298, 19, -118, +-55, 90, -104, 195, -136, 111, -126, -71, +-76, -201, -10, -223, 62, -122, 116, 85, +118, 280, 61, 339, -28, 246, -117, 64, +-151, -131, -76, -259, 74, -233, 185, -68, +187, 126, 95, 232, -42, 175, -180, -23, +-252, -242, -195, -350, -34, -301, 146, -117, +260, 134, 268, 333, 169, 390, -10, 300, +-191, 106, -276, -133, -231, -300, -115, -311, +3, -182, 93, 11, 137, 174, 137, 238, +126, 195, 110, 83, 64, -55, -8, -179, +-65, -240, -97, -219, -110, -125, -106, 29, +-92, 201, -68, 298, -30, 258, 12, 103, +58, -89, 112, -241, 146, -285, 121, -159, +58, 72, 19, 271, -2, 339, -36, 221, +-86, -51, -135, -340, -163, -474, -141, -378, +-48, -110, 84, 204, 195, 430, 224, 473, +149, 323, 11, 44, -106, -238, -146, -394, +-114, -355, -56, -143, -10, 130, 20, 299, +37, 273, 41, 99, 34, -109, 26, -245, +10, -246, -15, -125, -23, 41, 12, 158, +55, 192, 60, 146, 17, 26, -42, -99, +-79, -137, -78, -73, -27, 37, 43, 124, +63, 137, 7, 52, -62, -72, -76, -150, +-47, -150, 6, -98, 87, -35, 155, 25, +161, 81, 88, 106, -46, 93, -165, 67, +-182, 34, -94, 0, 25, -35, 110, -58, +111, -66, -6, -56, -161, -17, -189, 36, +-55, 77, 119, 72, 217, 20, 195, -50, +72, -102, -94, -99, -202, -35, -186, 47, +-54, 107, 117, 124, 218, 82, 182, -1, +40, -72, -111, -101, -195, -88, -169, -31, +-60, 37, 55, 57, 99, 20, 49, -22, +-40, -29, -88, -7, -67, 27, 11, 61, +101, 72, 162, 46, 171, -7, 120, -45, +24, -53, -86, -49, -170, -24, -193, 12, +-142, 34, -49, 4, 37, -59, 82, -110, +73, -118, 14, -59, -50, 76, -50, 232, +13, 307, 96, 264, 157, 113, 150, -120, +45, -346, -99, -433, -188, -343, -184, -130, +-105, 132, 18, 338, 149, 396, 224, 290, +201, 84, 76, -134, -100, -279, -261, -297, +-334, -189, -248, -5, -26, 170, 209, 271, +335, 268, 301, 155, 144, -35, -52, -231, +-196, -351, -233, -346, -162, -213, -17, 20, +138, 277, 222, 446, 195, 426, 73, 227, +-89, -60, -206, -335, -227, -465, -179, -358, +-112, -76, -26, 232, 84, 430, 184, 419, +245, 185, 240, -164, 143, -443, -18, -533, +-162, -393, -219, -63, -161, 312, -36, 554, +69, 552, 108, 307, 83, -74, 5, -406, +-103, -511, -167, -352, -133, -40, -23, 275, +120, 459, 235, 414, 239, 166, 118, -156, +-60, -416, -210, -511, -269, -401, -201, -133, +-25, 168, 147, 365, 225, 392, 207, 274, +115, 87, -23, -69, -153, -123, -203, -88, +-153, -27, -54, 23, 54, 55, 150, 46, +174, -7, 111, -76, -5, -150, -139, -201, +-236, -198, -229, -134, -112, -19, 68, 132, +257, 268, 387, 329, 356, 289, 144, 143, +-129, -68, -343, -252, -424, -323, -314, -259, +-63, -86, 193, 118, 325, 243, 283, 216, +111, 61, -97, -110, -229, -216, -236, -208, +-134, -64, 31, 130, 169, 240, 205, 222, +145, 107, 41, -73, -53, -230, -95, -267, +-74, -175, -11, -6, 55, 172, 96, 273, +80, 231, -3, 83, -106, -89, -198, -226, +-256, -262, -222, -167, -66, -2, 156, 145, +343, 238, 405, 265, 304, 183, 64, 10, +-204, -160, -360, -280, -328, -318, -135, -224, +103, -33, 253, 155, 249, 281, 128, 318, +-21, 221, -139, 15, -205, -190, -216, -312, +-175, -297, -92, -128, 24, 116, 156, 301, +268, 343, 284, 239, 173, 24, 1, -209, +-140, -338, -196, -297, -142, -126, 3, 80, +148, 229, 181, 243, 62, 122, -146, -47, +-331, -166, -358, -178, -188, -79, 90, 58, +348, 149, 455, 162, 334, 105, 44, 0, +-244, -105, -379, -156, -327, -144, -119, -83, +145, 11, 305, 102, 294, 175, 173, 208, +19, 175, -117, 68, -201, -96, -220, -267, +-176, -364, -84, -304, 36, -101, 150, 144, +202, 316, 144, 347, -3, 223, -142, 5, +-205, -195, -177, -278, -43, -219, 147, -53, +284, 163, 321, 321, 253, 334, 81, 188, +-143, -42, -320, -250, -373, -356, -297, -339, +-117, -224, 90, -41, 218, 135, 243, 231, +186, 232, 53, 141, -105, -5, -198, -117, +-183, -117, -64, -18, 114, 104, 271, 180, +308, 165, 194, 74, -14, -33, -219, -117, +-311, -163, -249, -167, -88, -134, 82, -89, +185, -47, 177, -6, 71, 33, -76, 66, +-184, 117, -192, 179, -98, 191, 32, 122, +119, 7, 149, -113, 147, -201, 116, -199, +69, -108, 37, 20, 18, 134, -9, 187, +-56, 142, -99, 20, -111, -109, -103, -184, +-92, -167, -88, -61, -76, 83, -39, 184, +19, 192, 86, 103, 139, -52, 150, -205, +99, -277, 5, -222, -57, -50, -34, 180, +46, 357, 120, 388, 129, 255, 59, 10, +-60, -237, -182, -376, -238, -347, -197, -188, +-101, 21, -8, 215, 58, 306, 87, 241, +75, 62, 45, -127, 32, -244, 46, -251, +76, -148, 108, 12, 108, 153, 64, 226, +3, 227, -55, 163, -89, 46, -85, -88, +-49, -186, -17, -222, -32, -177, -80, -56, +-112, 76, -95, 163, -26, 172, 61, 101, +137, -18, 163, -129, 106, -176, 11, -145, +-45, -43, -38, 92, 3, 193, 38, 200, +42, 114, 20, -16, -15, -129, -54, -175, +-82, -122, -65, 3, -6, 115, 37, 153, +35, 119, 2, 26, -53, -109, -111, -223, +-121, -250, -56, -176, 54, -21, 146, 158, +187, 289, 167, 318, 93, 234, -11, 78, +-114, -93, -156, -213, -108, -246, -5, -191, +103, -73, 141, 46, 57, 120, -87, 113, +-188, 38, -191, -62, -105, -130, 25, -122, +124, -41, 144, 73, 103, 173, 46, 223, +-5, 189, -28, 87, -20, -37, -14, -136, +-8, -178, 10, -146, 26, -68, 30, -6, +36, 21, 44, 14, 18, -23, -40, -56, +-102, -49, -143, -3, -137, 56, -81, 111, +-3, 132, 81, 113, 146, 75, 163, 41, +134, 9, 78, -33, 7, -81, -61, -137, +-96, -184, -95, -173, -81, -90, -53, 21, +5, 115, 73, 166, 115, 160, 104, 104, +34, 30, -68, -32, -146, -71, -149, -80, +-88, -68, -18, -43, 46, -7, 104, 25, +137, 60, 129, 88, 77, 91, -13, 43, +-125, -46, -186, -130, -117, -160, 55, -114, +218, -20, 270, 74, 172, 117, -29, 98, +-234, 51, -353, 10, -339, -7, -193, -4, +46, 3, 266, -1, 358, -16, 305, -32, +151, -44, -47, -41, -196, -14, -212, 19, +-122, 42, -30, 44, 23, 5, 57, -53, +69, -88, 61, -79, 48, -30, 20, 41, +-22, 111, -47, 143, -50, 121, -49, 65, +-40, -11, -10, -94, 21, -156, 31, -158, +33, -109, 23, -36, -1, 52, -5, 127, +20, 150, 55, 107, 74, 29, 49, -55, +-23, -115, -86, -126, -92, -73, -51, 13, +0, 86, 52, 119, 78, 107, 49, 54, +-21, -27, -95, -88, -124, -111, -97, -99, +-33, -57, 58, -9, 160, 20, 218, 31, +186, 60, 82, 93, -46, 96, -167, 64, +-240, 8, -202, -64, -53, -129, 120, -137, +208, -76, 163, 18, 36, 109, -91, 158, +-156, 126, -131, 28, -46, -77, 30, -150, +62, -161, 67, -85, 57, 39, 31, 126, +16, 142, 24, 95, 26, 3, 23, -79, +30, -112, 18, -86, -15, -21, -32, 55, +-31, 101, -50, 93, -98, 46, -138, -27, +-135, -96, -60, -128, 77, -109, 197, -57, +233, 10, 179, 79, 63, 118, -57, 123, +-115, 101, -96, 51, -42, -24, 3, -85, +34, -99, 34, -74, -4, -13, -56, 65, +-94, 101, -99, 52, -63, -49, -1, -163, +66, -231, 113, -191, 115, -49, 61, 133, +-20, 279, -76, 333, -78, 256, -19, 89, +73, -89, 129, -216, 103, -235, 19, -142, +-74, -3, -127, 91, -115, 99, -57, 24, +-4, -101, 12, -196, 9, -199, 3, -109, +4, 27, 28, 174, 71, 284, 104, 319, +114, 256, 85, 103, 5, -90, -101, -256, +-171, -332, -159, -296, -76, -151, 52, 49, +168, 215, 202, 270, 125, 187, -21, 11, +-164, -180, -230, -288, -175, -258, -19, -98, +163, 125, 265, 294, 221, 337, 51, 239, +-148, 49, -265, -146, -238, -242, -89, -194, +87, -57, 199, 76, 216, 132, 139, 82, +10, -52, -85, -185, -103, -233, -63, -168, +-4, -13, 45, 174, 58, 308, 21, 315, +-40, 201, -86, 22, -99, -142, -85, -225, +-60, -204, -24, -110, 33, -13, 85, 52, +102, 64, 88, 35, 59, -2, 27, -15, +8, -7, 11, 4, 25, 19, 32, 32, +18, 32, -26, 12, -86, -13, -127, -32, +-140, -37, -109, -19, -25, 31, 76, 94, +127, 124, 107, 93, 45, -7, -11, -147, +-16, -260, 28, -279, 73, -166, 76, 39, +40, 250, -19, 359, -69, 314, -77, 135, +-32, -99, 26, -270, 53, -294, 27, -167, +-53, 37, -152, 204, -212, 244, -182, 148, +-58, -17, 110, -165, 225, -215, 233, -149, +159, -18, 58, 92, -14, 136, -26, 108, +1, 27, 9, -51, -29, -70, -89, -26, +-127, 28, -127, 58, -90, 56, -30, 22, +26, -26, 71, -50, 107, -36, 128, -8, +115, 16, 57, 27, -27, 22, -113, 13, +-163, -1, -126, -23, -7, -58, 126, -80, +193, -84, 156, -70, 27, -40, -121, 11, +-188, 83, -141, 151, -25, 183, 95, 152, +162, 72, 127, -32, 18, -114, -93, -151, +-153, -147, -145, -104, -68, -30, 51, 47, +147, 89, 170, 92, 130, 48, 49, -48, +-40, -142, -85, -172, -72, -109, -26, 18, +20, 172, 46, 280, 34, 276, -18, 156, +-74, -28, -100, -201, -81, -280, -23, -213, +35, -52, 59, 113, 56, 206, 42, 182, +22, 36, 16, -155, 27, -288, 18, -299, +-12, -174, -17, 39, 7, 252, 20, 368, +10, 333, -6, 173, -23, -28, -20, -169, +1, -214, 4, -160, -17, -51, -34, 39, +-34, 60, -14, 16, 30, -59, 65, -133, +53, -145, 24, -62, 26, 68, 41, 173, +31, 222, -10, 194, -54, 80, -77, -51, +-62, -135, -22, -169, 10, -151, 17, -82, +5, 2, -8, 66, -19, 114, -22, 122, +-20, 75, -1, -1, 37, -56, 82, -82, +116, -81, 104, -45, 38, 9, -42, 47, +-87, 38, -87, -5, -51, -53, 5, -75, +53, -45, 51, 19, -5, 79, -72, 92, +-91, 62, -21, 22, 108, 9, 198, 25, +176, 47, 44, 46, -131, -17, -241, -130, +-212, -236, -70, -267, 81, -188, 156, 1, +132, 230, 47, 380, -34, 373, -77, 198, +-66, -55, 6, -259, 98, -328, 130, -244, +64, -52, -59, 155, -167, 259, -191, 226, +-92, 85, 68, -96, 171, -238, 167, -274, +80, -191, -32, -38, -97, 121, -74, 222, +-3, 239, 51, 170, 70, 57, 61, -54, +16, -126, -43, -131, -79, -75, -76, 6, +-32, 64, 24, 84, 53, 62, 44, 6, +8, -55, -53, -106, -119, -135, -144, -135, +-103, -89, -16, -4, 101, 96, 212, 175, +246, 201, 170, 170, 31, 86, -87, -10, +-127, -68, -94, -73, -37, -55, 5, -36, +23, -29, 13, -56, -19, -119, -46, -180, +-39, -184, -23, -108, -15, 25, -3, 170, +3, 268, -2, 272, 26, 177, 105, 40, +194, -79, 219, -135, 138, -123, -24, -71, +-187, -22, -262, -1, -220, -2, -115, -30, +-18, -66, 51, -74, 103, -35, 130, 19, +108, 54, 43, 75, -43, 65, -115, 25, +-120, -20, -43, -39, 73, -36, 155, -14, +175, 33, 135, 67, 64, 74, 1, 58, +-41, 33, -79, -8, -91, -49, -57, -81, +-16, -106, -8, -114, -38, -104, -82, -67, +-119, -4, -108, 82, -33, 147, 70, 162, +154, 137, 196, 73, 182, -21, 115, -110, +13, -146, -95, -118, -170, -47, -186, 38, +-125, 96, -7, 99, 118, 41, 184, -34, +167, -81, 81, -69, -46, -18, -171, 36, +-215, 74, -144, 74, -18, 38, 85, -18, +130, -74, 118, -120, 61, -127, 9, -85, +10, -21, 55, 54, 92, 126, 83, 170, +22, 161, -56, 110, -103, 20, -109, -90, +-71, -151, -3, -135, 48, -59, 24, 29, +-65, 89, -147, 60, -159, -56, -94, -183, +24, -235, 149, -176, 226, -16, 220, 196, +139, 360, 36, 391, -47, 257, -89, 27, +-82, -181, -36, -282, 14, -255, 40, -137, +17, 6, -50, 89, -107, 70, -92, -7, +-7, -90, 77, -135, 103, -105, 65, 5, +-19, 125, -101, 201, -118, 213, -40, 150, +84, 25, 171, -88, 182, -142, 123, -153, +26, -120, -79, -52, -154, 20, -159, 76, +-112, 112, -59, 120, -21, 72, 9, -14, +41, -109, 69, -177, 78, -193, 59, -138, +20, -10, -13, 132, -15, 233, 15, 255, +71, 195, 112, 62, 88, -85, 5, -176, +-82, -183, -134, -124, -124, -35, -47, 49, +50, 90, 106, 70, 96, 7, 33, -62, +-62, -97, -127, -84, -122, -36, -69, 16, +-6, 76, 66, 128, 135, 144, 166, 118, +132, 55, 39, -34, -80, -125, -176, -157, +-185, -124, -89, -54, 67, 16, 184, 55, +179, 47, 68, 9, -60, -12, -137, -6, +-141, 22, -71, 57, 24, 76, 89, 56, +113, -4, 116, -66, 100, -96, 65, -72, +9, -5, -71, 65, -148, 89, -166, 56, +-107, -9, 2, -72, 116, -94, 165, -50, +115, 46, -9, 124, -128, 134, -190, 62, +-160, -65, -44, -185, 91, -238, 178, -178, +192, -25, 136, 158, 32, 294, -81, 317, +-140, 216, -112, 27, -38, -165, 27, -289, +66, -290, 85, -172, 75, 4, 32, 157, +-23, 212, -77, 152, -117, 21, -107, -114, +-14, -199, 122, -186, 215, -66, 194, 95, +50, 220, -134, 269, -238, 225, -202, 85, +-58, -87, 114, -213, 224, -255, 202, -199, +62, -72, -108, 60, -225, 129, -228, 125, +-113, 51, 54, -61, 176, -140, 196, -128, +111, -42, -23, 74, -107, 185, -90, 236, +-16, 196, 54, 87, 93, -43, 87, -155, +40, -204, 1, -177, -10, -106, -6, -12, +7, 67, 12, 89, -20, 45, -73, -15, +-105, -52, -112, -62, -89, -23, 2, 43, +119, 108, 168, 147, 127, 147, 44, 94, +-43, -2, -111, -101, -121, -172, -70, -184, +9, -142, 76, -63, 98, 38, 64, 134, +16, 180, -7, 146, -3, 65, 14, -40, +24, -145, 2, -195, -53, -145, -99, -28, +-105, 86, -65, 163, 14, 150, 100, 54, +153, -59, 165, -117, 128, -98, 44, 2, +-41, 134, -77, 198, -55, 165, -8, 58, +12, -95, -35, -246, -132, -313, -206, -259, +-188, -123, -76, 48, 79, 193, 201, 264, +236, 239, 185, 148, 91, 35, -6, -56, +-89, -89, -136, -70, -123, -21, -60, 21, +4, 26, 45, -19, 64, -82, 68, -128, +56, -139, 39, -92, 25, 4, -13, 94, +-64, 128, -80, 108, -45, 49, 16, -19, +85, -42, 134, -7, 124, 65, 51, 117, +-48, 111, -147, 29, -208, -94, -172, -194, +-43, -237, 113, -195, 222, -65, 226, 109, +112, 240, -63, 275, -218, 195, -286, 21, +-238, -173, -73, -287, 154, -259, 338, -104, +392, 115, 280, 281, 44, 304, -205, 174, +-336, -45, -289, -245, -107, -328, 96, -237, +213, -23, 214, 201, 122, 316, -31, 263, +-180, 72, -234, -162, -162, -310, 5, -299, +199, -146, 324, 64, 283, 233, 94, 287, +-132, 205, -281, 56, -295, -79, -179, -148, +-3, -144, 129, -80, 171, 1, 139, 40, +55, 33, -52, 8, -133, -3, -148, -13, +-91, -35, 13, -67, 133, -82, 215, -60, +212, 9, 123, 122, -25, 231, -162, 275, +-212, 209, -139, 37, 22, -186, 182, -363, +243, -394, 169, -257, -11, -7, -200, 236, +-288, 343, -241, 255, -98, 30, 74, -193, +212, -294, 254, -209, 184, 25, 40, 287, +-121, 422, -243, 354, -253, 100, -125, -227, +85, -458, 271, -477, 341, -277, 267, 28, +78, 291, -146, 400, -315, 316, -352, 86, +-253, -186, -84, -363, 89, -364, 225, -194, +282, 64, 252, 316, 173, 456, 66, 410, +-63, 208, -173, -67, -207, -311, -156, -443, +-43, -410, 92, -241, 177, 2, 153, 232, +39, 349, -98, 308, -179, 142, -154, -63, +-42, -223, 72, -255, 121, -155, 95, 6, +6, 160, -93, 237, -123, 202, -64, 72, +28, -66, 101, -156, 127, -178, 92, -117, +30, -13, -13, 60, -21, 70, -8, 41, +6, -14, 0, -58, -17, -46, -21, 7, +-10, 60, 2, 92, 8, 88, -5, 29, +-34, -49, -42, -90, -13, -76, 29, -22, +65, 40, 94, 78, 98, 59, 56, -5, +-20, -88, -97, -141, -147, -127, -143, -44, +-76, 78, 24, 184, 103, 228, 115, 163, +74, 19, 26, -125, -6, -203, -28, -184, +-41, -89, -51, 29, -56, 98, -37, 99, +23, 47, 101, -37, 151, -100, 146, -91, +74, -19, -29, 67, -118, 135, -164, 143, +-147, 89, -39, 15, 116, -45, 226, -78, +238, -76, 142, -53, -43, -55, -244, -76, +-348, -85, -313, -63, -174, -3, 28, 86, +234, 169, 351, 193, 331, 136, 189, 12, +-24, -128, -221, -206, -315, -181, -267, -73, +-112, 62, 90, 167, 244, 178, 285, 96, +209, -26, 54, -119, -135, -148, -267, -102, +-252, 1, -91, 98, 134, 145, 318, 124, +362, 48, 218, -58, -48, -137, -309, -166, +-454, -155, -411, -104, -187, -29, 114, 64, +357, 165, 454, 245, 376, 256, 155, 178, +-119, 40, -324, -126, -386, -262, -286, -296, +-75, -207, 139, -53, 265, 93, 267, 171, +146, 148, -50, 43, -212, -75, -251, -122, +-155, -75, 19, 46, 207, 178, 331, 237, +331, 191, 188, 61, -36, -92, -236, -220, +-347, -267, -340, -217, -209, -111, -3, -3, +172, 74, 255, 128, 238, 148, 155, 146, +41, 130, -65, 96, -138, 35, -165, -46, +-136, -121, -68, -163, 7, -149, 74, -80, +116, 20, 104, 109, 54, 147, 5, 115, +-26, 32, -44, -64, -46, -135, -35, -135, +-20, -61, 2, 40, 26, 111, 34, 127, +25, 79, 11, -22, -4, -108, 2, -131, +46, -85, 103, 7, 137, 98, 121, 137, +46, 106, -67, 26, -163, -80, -206, -162, +-192, -163, -115, -82, 3, 35, 92, 138, +121, 188, 108, 144, 77, 31, 36, -96, +13, -174, 20, -171, 30, -84, 24, 50, +4, 162, -28, 207, -55, 153, -63, 25, +-66, -114, -70, -192, -61, -196, -30, -131, +20, -24, 91, 66, 166, 110, 197, 111, +154, 86, 45, 42, -90, -3, -190, -33, +-194, -45, -106, -38, 20, -10, 114, 37, +133, 90, 79, 120, -4, 82, -59, -31, +-68, -169, -39, -271, -2, -278, 22, -156, +36, 61, 46, 261, 31, 355, -15, 306, +-75, 126, -117, -96, -118, -243, -70, -252, +28, -139, 139, 34, 214, 172, 207, 184, +108, 79, -43, -77, -170, -198, -206, -225, +-123, -138, 35, 9, 180, 131, 217, 185, +123, 158, -35, 85, -163, 16, -201, -17, +-150, -19, -35, 1, 82, 10, 144, -11, +125, -51, 52, -86, -34, -97, -103, -81, +-123, -40, -86, -7, -17, 6, 49, 25, +93, 55, 104, 95, 100, 134, 93, 156, +60, 118, -26, 12, -130, -121, -193, -231, +-189, -264, -104, -190, 41, -32, 177, 134, +231, 234, 182, 228, 65, 122, -49, -13, +-104, -104, -86, -113, -26, -58, 46, 23, +93, 74, 70, 58, -8, -11, -87, -92, +-129, -135, -137, -120, -107, -47, -47, 33, +24, 91, 79, 112, 104, 104, 93, 86, +63, 71, 40, 63, 22, 41, 11, -6, +9, -76, -3, -151, -48, -200, -105, -202, +-129, -146, -97, -45, -22, 67, 81, 159, +175, 205, 214, 192, 180, 134, 80, 63, +-37, 0, -124, -47, -143, -69, -98, -57, +-32, -34, 9, -34, 9, -58, -32, -90, +-83, -113, -91, -110, -43, -64, 32, 27, +99, 117, 147, 167, 156, 157, 108, 100, +19, 15, -79, -57, -158, -85, -173, -62, +-106, -8, 11, 51, 118, 75, 171, 26, +142, -65, 36, -143, -81, -162, -154, -122, +-153, -31, -72, 64, 61, 123, 173, 133, +213, 107, 167, 63, 49, 19, -88, -4, +-165, -12, -147, -8, -75, -2, 16, -3, +85, -11, 90, -26, 27, -51, -67, -88, +-149, -116, -172, -121, -115, -89, -1, 0, +131, 126, 232, 226, 251, 253, 153, 192, +-1, 50, -124, -127, -177, -251, -145, -267, +-34, -174, 87, -24, 139, 113, 88, 166, +-38, 121, -160, 30, -193, -49, -109, -65, +35, -16, 164, 64, 220, 111, 190, 94, +114, 15, 43, -81, -10, -138, -59, -122, +-119, -45, -179, 44, -191, 100, -148, 83, +-71, 4, 7, -77, 77, -101, 131, -56, +147, 40, 119, 140, 63, 170, -4, 105, +-48, -19, -39, -147, 1, -217, 30, -185, +16, -67, -35, 69, -86, 161, -77, 171, +-10, 99, 54, -15, 73, -108, 56, -128, +10, -72, -43, 21, -61, 100, -31, 128, +30, 99, 87, 38, 116, -16, 98, -39, +42, -40, -30, -43, -82, -50, -93, -69, +-71, -100, -46, -119, -31, -102, -19, -47, +-9, 27, 0, 118, 10, 190, 16, 214, +17, 186, 27, 126, 48, 28, 57, -92, +38, -187, -6, -235, -55, -220, -79, -151, +-63, -42, -21, 57, 36, 112, 94, 110, +122, 67, 102, 30, 49, 32, -9, 75, +-54, 141, -63, 194, -28, 181, 10, 75, +17, -90, 5, -258, -15, -369, -26, -369, +-25, -247, -33, -60, -65, 116, -87, 233, +-61, 257, 10, 192, 100, 89, 164, 11, +163, -16, 85, -1, -30, 38, -142, 62, +-205, 39, -180, -36, -79, -128, 51, -198, +162, -207, 203, -134, 141, 2, 21, 160, +-65, 279, -75, 311, -30, 221, 43, 31, +93, -192, 84, -354, 27, -389, -41, -278, +-99, -57, -120, 187, -88, 356, -28, 376, +28, 249, 63, 34, 60, -179, 6, -303, +-58, -279, -84, -122, -64, 77, -12, 224, +51, 263, 97, 180, 96, 10, 43, -166, +-34, -268, -90, -263, -98, -146, -52, 41, +24, 216, 93, 298, 122, 255, 105, 106, +58, -85, -1, -230, -52, -257, -79, -153, +-75, 26, -38, 179, 35, 221, 103, 118, +114, -76, 52, -260, -40, -323, -117, -223, +-144, 2, -101, 250, -24, 402, 38, 383, +71, 205, 74, -29, 47, -220, 10, -296, +-26, -235, -48, -77, -50, 75, -14, 138, +38, 90, 65, -37, 47, -174, -11, -237, +-66, -178, -78, -19, -37, 176, 16, 336, +57, 393, 71, 316, 65, 133, 58, -93, +62, -282, 54, -364, 24, -323, -13, -196, +-45, -36, -62, 87, -50, 127, -15, 96, +-6, 42, -29, 3, -56, 11, -61, 80, +-52, 167, -16, 211, 45, 175, 85, 66, +70, -80, 11, -208, -42, -259, -52, -228, +-16, -142, 31, -51, 56, 10, 32, 23, +-26, 23, -86, 50, -95, 117, -24, 206, +88, 267, 171, 254, 177, 143, 109, -41, +-7, -239, -129, -368, -202, -376, -167, -264, +-47, -68, 88, 147, 175, 303, 182, 345, +108, 280, -14, 146, -115, -20, -146, -166, +-105, -250, -43, -262, -3, -220, 4, -137, +-7, -32, -29, 64, -44, 124, -28, 146, +22, 143, 84, 124, 123, 108, 133, 104, +111, 105, 65, 91, -4, 38, -83, -45, +-149, -140, -171, -220, -142, -259, -64, -232, +54, -158, 165, -65, 214, 38, 183, 128, +99, 192, -7, 224, -103, 234, -168, 199, +-178, 117, -122, 4, -13, -117, 95, -219, +145, -271, 116, -252, 20, -180, -94, -81, +-164, 23, -142, 107, -43, 160, 83, 191, +171, 207, 193, 207, 148, 185, 59, 135, +-46, 49, -128, -67, -161, -183, -158, -263, +-133, -281, -86, -227, -24, -124, 37, -17, +104, 65, 160, 104, 165, 108, 117, 104, +53, 115, -12, 129, -74, 122, -99, 84, +-77, 5, -21, -104, 41, -204, 85, -237, +69, -192, -2, -90, -76, 35, -107, 142, +-78, 196, 7, 198, 92, 180, 113, 157, +67, 132, -7, 94, -68, 32, -112, -68, +-127, -185, -107, -282, -54, -316, -3, -271, +20, -157, 15, -11, -8, 111, -32, 170, +-27, 162, 40, 121, 148, 71, 245, 36, +273, 30, 218, 46, 100, 60, -40, 57, +-166, 34, -236, -3, -220, -44, -134, -75, +-32, -79, 37, -59, 66, -17, 43, 37, +-27, 75, -106, 63, -141, 4, -120, -75, +-55, -143, 28, -166, 107, -114, 176, 5, +206, 135, 179, 221, 116, 221, 50, 144, +-34, 10, -126, -123, -195, -202, -216, -196, +-186, -136, -99, -62, 18, -2, 119, 26, +192, 29, 223, 32, 197, 72, 130, 145, +76, 216, 19, 239, -53, 193, -97, 71, +-92, -90, -92, -225, -122, -282, -165, -249, +-204, -164, -208, -68, -134, -2, 18, 24, +181, 24, 291, 32, 299, 63, 203, 112, +56, 151, -71, 155, -135, 111, -131, 32, +-77, -41, -9, -84, 32, -95, 27, -78, +-9, -49, -49, -34, -52, -31, -10, -22, +63, 11, 134, 53, 158, 93, 117, 115, +36, 88, -57, 12, -142, -76, -184, -132, +-167, -148, -110, -113, -43, -40, 25, 39, +64, 78, 63, 73, 50, 42, 52, 4, +77, -24, 113, -38, 131, -23, 96, 8, +12, 37, -93, 64, -179, 96, -200, 112, +-125, 94, 7, 55, 125, 2, 177, -64, +136, -113, 23, -125, -93, -111, -140, -88, +-106, -66, -17, -54, 72, -60, 102, -57, +68, -26, 13, 30, -45, 93, -88, 147, +-81, 161, -30, 119, 19, 43, 45, -29, +62, -71, 67, -74, 68, -34, 71, 18, +70, 55, 45, 59, 9, 44, -28, 25, +-60, 10, -64, 0, -48, -1, -53, 1, +-92, -22, -116, -70, -102, -129, -56, -173, +-3, -194, 47, -178, 79, -118, 88, -32, +71, 61, 40, 153, 27, 233, 35, 272, +54, 259, 75, 198, 96, 106, 79, 1, +12, -85, -79, -124, -150, -108, -170, -64, +-130, -26, -50, -16, 33, -45, 103, -101, +127, -152, 93, -154, 37, -93, 3, 19, +-18, 137, -32, 211, -51, 203, -86, 118, +-136, -20, -158, -166, -109, -256, 0, -256, +118, -175, 178, -54, 153, 76, 66, 173, +-23, 220, -67, 219, -34, 201, 63, 180, +160, 147, 201, 96, 163, 32, 47, -39, +-107, -116, -228, -179, -273, -214, -230, -225, +-127, -226, -5, -207, 79, -154, 109, -66, +109, 44, 92, 155, 62, 235, 38, 247, +22, 184, -2, 75, -27, -34, -50, -105, +-71, -114, -88, -66, -81, 5, -43, 61, +15, 82, 77, 78, 128, 65, 149, 48, +128, 35, 78, 27, 13, 12, -45, -18, +-80, -64, -77, -111, -53, -152, -39, -171, +-53, -158, -87, -112, -120, -41, -108, 42, +-29, 111, 76, 145, 146, 139, 148, 96, +108, 37, 49, -10, 1, -5, -2, 48, +25, 116, 27, 155, -17, 125, -83, 19, +-141, -131, -156, -263, -116, -310, -24, -244, +84, -100, 169, 76, 188, 219, 136, 273, +52, 228, -18, 118, -54, -11, -54, -131, +-44, -215, -64, -243, -124, -212, -190, -136, +-194, -29, -106, 93, 57, 201, 222, 258, +320, 249, 313, 189, 211, 108, 54, 33, +-91, -14, -162, -31, -169, -47, -143, -93, +-107, -173, -67, -260, -35, -321, -3, -307, +34, -197, 60, -19, 51, 168, 13, 302, +-22, 333, -32, 256, -10, 128, 29, 7, +62, -63, 66, -65, 46, -9, 9, 51, +-38, 76, -78, 47, -72, -30, -23, -125, +45, -192, 121, -193, 172, -123, 157, -6, +67, 116, -41, 202, -130, 211, -179, 137, +-168, -1, -97, -155, -12, -267, 41, -300, +30, -243, -52, -113, -144, 37, -159, 153, +-57, 219, 132, 243, 340, 240, 442, 226, +347, 205, 80, 159, -234, 66, -452, -70, +-475, -209, -285, -313, 32, -346, 324, -295, +441, -174, 337, -23, 89, 93, -157, 146, +-293, 133, -281, 89, -151, 45, 18, 27, +144, 48, 192, 95, 168, 131, 75, 123, +-63, 66, -201, -33, -273, -140, -238, -210, +-97, -201, 86, -113, 230, 29, 286, 171, +240, 247, 115, 218, -23, 95, -113, -68, +-131, -213, -84, -269, -16, -207, 20, -67, +-22, 67, -119, 134, -211, 103, -216, -6, +-91, -117, 120, -137, 321, -32, 425, 152, +378, 335, 183, 427, -76, 369, -301, 154, +-406, -132, -365, -373, -198, -476, -5, -417, +124, -224, 159, 10, 109, 172, 18, 203, +-56, 119, -73, -7, -44, -104, 32, -110, +146, -23, 242, 104, 251, 186, 167, 177, +9, 77, -178, -59, -309, -155, -319, -155, +-216, -47, -60, 114, 96, 256, 201, 310, +236, 253, 187, 112, 73, -57, -61, -209, +-150, -310, -169, -345, -122, -324, -37, -263, +41, -169, 75, -45, 53, 78, 1, 165, +-52, 198, -58, 180, -5, 125, 87, 74, +186, 67, 254, 116, 220, 185, 61, 224, +-152, 203, -331, 104, -406, -61, -336, -235, +-130, -333, 110, -316, 281, -192, 320, -26, +224, 112, 44, 151, -129, 76, -227, -65, +-219, -195, -102, -242, 61, -183, 179, -34, +207, 140, 158, 265, 45, 286, -71, 214, +-134, 97, -114, 1, -23, -34, 90, 6, +158, 91, 138, 146, 51, 128, -80, 21, +-216, -146, -284, -316, -246, -412, -141, -388, +-12, -249, 117, -36, 210, 176, 227, 306, +189, 321, 128, 236, 54, 92, -14, -53, +-76, -138, -148, -126, -222, -43, -246, 60, +-200, 137, -90, 156, 62, 106, 212, 15, +302, -63, 307, -87, 251, -66, 164, -37, +56, -25, -70, -54, -189, -121, -277, -201, +-306, -232, -265, -184, -165, -59, -46, 111, +51, 266, 119, 349, 156, 329, 161, 226, +141, 78, 106, -66, 45, -169, -36, -207, +-114, -187, -161, -130, -171, -60, -121, 9, +-14, 64, 91, 97, 150, 113, 146, 107, +95, 70, 26, -3, -12, -87, -8, -153, +10, -176, 9, -149, -14, -77, -50, 11, +-79, 81, -77, 117, -41, 112, 18, 77, +63, 42, 51, 36, -22, 62, -109, 101, +-165, 119, -154, 90, -74, -4, 42, -139, +118, -262, 120, -314, 80, -266, 27, -121, +-6, 83, -9, 266, 2, 359, -1, 328, +0, 201, 11, 23, 15, -128, 1, -197, +-11, -168, -21, -87, -36, -17, -29, 16, +3, -6, 29, -62, 28, -119, 21, -136, +8, -106, -24, -49, -80, 18, -130, 78, +-149, 126, -120, 159, -46, 181, 40, 194, +105, 183, 133, 130, 132, 46, 108, -50, +86, -131, 70, -165, 44, -146, -19, -101, +-102, -57, -171, -42, -202, -68, -179, -123, +-93, -162, 34, -147, 128, -75, 149, 41, +96, 164, 7, 258, -75, 272, -109, 207, +-94, 89, -56, -39, -15, -136, 23, -165, +62, -110, 110, 2, 171, 131, 206, 224, +175, 249, 63, 178, -101, 19, -255, -180, +-328, -347, -287, -429, -142, -395, 33, -254, +150, -58, 167, 119, 98, 223, 2, 243, +-78, 187, -100, 107, -67, 52, -10, 57, +35, 120, 59, 195, 57, 226, 35, 177, +22, 54, 33, -100, 69, -219, 98, -254, +95, -209, 39, -128, -55, -71, -155, -79, +-217, -151, -217, -239, -161, -273, -75, -206, +20, -33, 101, 197, 147, 399, 152, 498, +107, 467, 30, 340, -51, 162, -94, 0, +-93, -102, -51, -135, 18, -129, 85, -122, +121, -137, 125, -177, 108, -217, 48, -228, +-51, -191, -157, -119, -229, -34, -258, 40, +-233, 86, -156, 92, -54, 66, 24, 50, +58, 62, 69, 94, 88, 140, 132, 187, +185, 206, 228, 178, 224, 112, 173, 34, +84, -46, -24, -116, -136, -159, -227, -176, +-269, -183, -257, -176, -190, -141, -71, -88, +60, -30, 133, 20, 123, 40, 41, 21, +-69, -18, -155, -53, -160, -52, -80, 12, +40, 138, 148, 282, 189, 380, 145, 382, +48, 270, -47, 80, -120, -136, -140, -304, +-90, -383, 6, -364, 89, -283, 132, -178, +127, -77, 80, -2, 18, 50, -40, 98, +-86, 152, -118, 187, -134, 188, -142, 153, +-133, 89, -119, 3, -120, -66, -136, -82, +-121, -44, -33, 25, 134, 93, 338, 135, +478, 134, 459, 87, 269, 12, -12, -66, +-279, -142, -424, -209, -410, -255, -288, -268, +-149, -247, -52, -188, -24, -92, -55, 28, +-81, 147, -45, 240, 61, 297, 193, 307, +302, 280, 319, 217, 232, 136, 87, 43, +-49, -49, -132, -122, -143, -161, -87, -155, +-12, -111, 32, -49, 17, -20, -39, -41, +-115, -105, -195, -180, -261, -243, -272, -255, +-220, -196, -123, -79, 13, 67, 166, 212, +286, 332, 322, 392, 268, 383, 133, 317, +-27, 209, -138, 70, -161, -72, -117, -194, +-27, -278, 74, -308, 132, -279, 120, -189, +50, -61, -58, 65, -176, 148, -261, 158, +-291, 82, -263, -54, -185, -187, -75, -250, +31, -205, 124, -50, 205, 162, 246, 348, +229, 428, 174, 369, 114, 193, 51, -37, +-7, -224, -63, -303, -107, -257, -142, -123, +-156, 35, -150, 140, -122, 158, -78, 93, +-58, -24, -68, -140, -81, -220, -75, -237, +-58, -195, -23, -104, 33, 6, 92, 102, +130, 166, 152, 193, 159, 193, 144, 182, +103, 175, 29, 160, -66, 130, -151, 73, +-185, -18, -159, -133, -81, -243, 10, -309, +66, -305, 37, -228, -59, -91, -165, 60, +-220, 174, -188, 217, -85, 186, 54, 100, +166, -11, 204, -107, 159, -157, 75, -137, +-12, -59, -60, 50, -58, 158, -30, 228, +-10, 231, -2, 166, 11, 59, 8, -61, +-7, -156, -34, -191, -84, -153, -159, -77, +-198, 3, -171, 52, -92, 47, 3, -13, +80, -89, 112, -134, 99, -123, 71, -45, +41, 65, 29, 158, 42, 191, 67, 155, +72, 67, 61, -30, 29, -91, -30, -91, +-104, -38, -174, 28, -219, 71, -223, 70, +-175, 35, -98, -16, -11, -56, 60, -62, +90, -40, 68, -21, 22, -17, -23, -34, +-47, -76, -39, -128, 2, -148, 66, -104, +131, 3, 191, 154, 205, 293, 152, 364, +38, 324, -96, 186, -221, -15, -284, -205, +-264, -317, -192, -312, -130, -207, -105, -60, +-87, 58, -64, 91, -20, 45, 51, -48, +151, -126, 234, -135, 260, -62, 210, 58, +101, 171, -39, 230, -151, 207, -188, 115, +-155, 5, -72, -66, 8, -79, 43, -39, +17, 20, -33, 59, -91, 53, -154, 11, +-195, -43, -178, -88, -103, -105, 3, -88, +122, -59, 207, -45, 221, -55, 151, -89, +35, -129, -87, -141, -164, -97, -162, 4, +-87, 138, 19, 260, 116, 338, 157, 340, +118, 255, 28, 111, -77, -49, -158, -184, +-211, -266, -231, -265, -225, -193, -180, -79, +-90, 27, 28, 97, 139, 108, 208, 52, +208, -45, 125, -140, -2, -183, -122, -157, +-179, -57, -159, 89, -65, 224, 65, 295, +174, 280, 203, 186, 137, 36, 8, -112, +-136, -208, -243, -228, -282, -175, -238, -75, +-135, 30, -7, 104, 96, 128, 143, 103, +129, 45, 77, -19, 15, -66, -27, -84, +-44, -79, -51, -63, -55, -44, -62, -23, +-61, 3, -65, 33, -67, 64, -64, 89, +-63, 99, -54, 85, -22, 49, 25, -1, +62, -54, 75, -89, 62, -93, 37, -60, +3, -3, -24, 70, -45, 122, -49, 124, +-42, 64, -37, -43, -36, -162, -30, -241, +-21, -236, -10, -134, 7, 40, -3, 215, +-53, 316, -131, 291, -191, 148, -208, -58, +-157, -246, -60, -341, 40, -303, 105, -143, +131, 77, 126, 271, 102, 370, 93, 342, +100, 200, 104, 1, 79, -186, 38, -302, +-42, -316, -152, -232, -249, -83, -293, 84, +-269, 203, -169, 232, -21, 170, 105, 41, +165, -103, 133, -202, 17, -211, -145, -131, +-261, 2, -264, 122, -142, 182, 53, 157, +245, 62, 354, -52, 336, -123, 208, -117, +18, -39, -158, 84, -273, 185, -289, 213, +-211, 150, -67, 29, 70, -104, 129, -193, +80, -207, -49, -153, -185, -66, -262, 10, +-244, 49, -141, 36, 11, -6, 144, -46, +214, -62, 203, -40, 133, 12, 29, 79, +-67, 132, -114, 152, -101, 134, -52, 76, +-5, -2, 20, -71, 2, -105, -56, -90, +-143, -39, -208, 17, -221, 45, -168, 33, +-49, -18, 110, -77, 248, -111, 298, -96, +240, -34, 96, 45, -77, 114, -216, 146, +-262, 134, -227, 86, -141, 26, -43, -37, +33, -94, 51, -132, 11, -144, -57, -130, +-135, -89, -179, -22, -159, 47, -79, 99, +27, 113, 147, 98, 233, 72, 240, 55, +174, 54, 69, 64, -47, 65, -135, 34, +-147, -26, -101, -98, -53, -154, -44, -167, +-81, -124, -147, -42, -179, 40, -143, 87, +-57, 83, 21, 36, 46, -29, 1, -77, +-90, -78, -157, -29, -156, 52, -77, 128, +61, 162, 211, 144, 295, 79, 286, -6, +200, -82, 64, -119, -90, -106, -207, -64, +-255, -21, -245, 2, -178, 4, -74, -9, +25, -19, 55, -21, 0, -15, -119, -28, +-239, -53, -293, -72, -226, -60, -48, -1, +173, 102, 354, 220, 416, 294, 334, 278, +144, 153, -64, -41, -230, -228, -309, -329, +-290, -301, -203, -166, -117, 13, -61, 153, +-26, 198, -21, 134, -24, 1, -15, -134, +10, -207, 26, -189, 40, -92, 46, 39, +37, 147, 6, 190, -24, 170, -37, 116, +-37, 65, -10, 44, 29, 51, 64, 65, +72, 59, 38, 17, -57, -54, -187, -121, +-310, -161, -370, -158, -335, -125, -194, -89, +7, -76, 176, -84, 259, -83, 238, -51, +145, 23, 28, 113, -42, 195, -46, 222, +10, 188, 90, 111, 142, 37, 117, -4, +18, -7, -119, 12, -248, 19, -307, -2, +-283, -52, -204, -102, -120, -128, -49, -117, +-21, -82, -35, -58, -61, -63, -60, -98, +-26, -135, 37, -137, 120, -76, 183, 43, +200, 177, 168, 275, 124, 295, 75, 237, +37, 128, 5, 22, -29, -35, -86, -29, +-151, 23, -202, 69, -244, 66, -269, -10, +-286, -150, -289, -296, -274, -388, -213, -378, +-108, -264, 27, -83, 172, 96, 304, 212, +379, 229, 381, 158, 330, 51, 237, -28, +115, -28, -9, 63, -110, 220, -208, 367, +-293, 435, -346, 376, -347, 195, -298, -59, +-202, -306, -91, -463, -15, -495, 10, -405, +-6, -244, -27, -86, -31, 4, 4, 2, +51, -66, 86, -141, 105, -155, 116, -74, +117, 95, 131, 295, 156, 456, 146, 532, +73, 510, -58, 412, -204, 269, -321, 104, +-346, -71, -275, -246, -153, -409, -50, -539, +-1, -587, -13, -526, -55, -354, -79, -111, +-73, 124, -40, 278, 0, 305, 51, 219, +106, 75, 172, -38, 230, -59, 241, 42, +169, 220, 24, 393, -152, 480, -299, 424, +-353, 228, -296, -48, -158, -306, -31, -469, +30, -501, 5, -425, -64, -295, -122, -172, +-109, -92, -15, -50, 110, -18, 200, 41, +206, 140, 133, 256, 15, 344, -87, 366, +-139, 311, -133, 197, -99, 70, -78, -30, +-99, -81, -148, -84, -193, -65, -193, -57, +-123, -81, -7, -137, 109, -206, 188, -256, +225, -257, 196, -201, 108, -98, -19, 23, +-148, 129, -251, 194, -281, 205, -214, 165, +-85, 100, 53, 45, 142, 33, 156, 81, +90, 162, -7, 235, -118, 242, -216, 158, +-257, -16, -224, -225, -146, -402, -43, -491, +69, -449, 137, -286, 133, -51, 84, 171, +29, 313, -32, 326, -61, 213, -30, 34, +48, -130, 117, -204, 144, -141, 91, 48, +-46, 288, -205, 472, -319, 509, -348, 364, +-297, 69, -191, -278, -95, -557, -31, -681, +4, -615, 30, -386, 54, -76, 105, 212, +181, 391, 242, 423, 247, 322, 172, 148, +34, -23, -130, -139, -244, -157, -279, -80, +-236, 65, -156, 217, -71, 318, -14, 320, +1, 206, -22, -3, -69, -250, -110, -450, +-121, -542, -79, -488, -5, -299, 83, -31, +141, 220, 149, 375, 101, 389, 22, 269, +-59, 87, -121, -71, -132, -138, -84, -93, +0, 31, 56, 156, 52, 212, -37, 164, +-180, 29, -305, -138, -335, -266, -256, -296, +-102, -217, 76, -65, 219, 100, 287, 209, +268, 219, 187, 132, 57, -17, -64, -167, +-135, -255, -146, -241, -121, -123, -98, 67, +-114, 255, -161, 368, -179, 361, -133, 240, +-38, 49, 60, -143, 126, -268, 100, -301, +-16, -247, -170, -151, -274, -55, -279, -3, +-154, 7, 71, -3, 290, -4, 400, 35, +351, 97, 169, 161, -63, 195, -236, 189, +-306, 140, -280, 70, -194, 4, -91, -34, +-22, -39, 1, -35, -6, -53, -46, -110, +-103, -201, -142, -292, -133, -333, -82, -287, +7, -144, 107, 70, 182, 290, 192, 446, +142, 475, 43, 364, -70, 159, -143, -69, +-142, -238, -74, -291, -4, -224, 19, -79, +-45, 72, -168, 170, -269, 171, -276, 74, +-187, -78, -37, -217, 117, -293, 209, -279, +209, -182, 138, -43, 36, 87, -85, 169, +-175, 197, -198, 176, -143, 145, -43, 129, +78, 142, 175, 165, 201, 169, 138, 126, +5, 21, -161, -126, -316, -274, -390, -374, +-354, -397, -217, -331, -48, -198, 90, -40, +143, 92, 127, 169, 96, 193, 90, 183, +120, 173, 155, 173, 148, 175, 67, 159, +-53, 111, -162, 34, -221, -38, -227, -69, +-179, -49, -114, 6, -65, 51, -45, 30, +-53, -85, -80, -268, -115, -438, -126, -508, +-102, -420, -28, -177, 66, 137, 156, 408, +214, 538, 226, 498, 174, 319, 65, 87, +-67, -97, -186, -168, -259, -117, -250, 12, +-138, 154, 16, 233, 136, 213, 156, 82, +67, -120, -107, -337, -286, -502, -387, -562, +-370, -494, -252, -306, -81, -56, 96, 188, +227, 364, 298, 440, 304, 415, 264, 327, +186, 221, 98, 136, -5, 90, -124, 83, +-237, 89, -315, 70, -334, 7, -286, -96, +-168, -219, -34, -334, 61, -418, 87, -447, +50, -409, -48, -305, -159, -147, -215, 33, +-178, 202, -46, 329, 148, 396, 331, 400, +413, 354, 370, 276, 212, 189, 2, 115, +-197, 58, -322, 21, -370, -14, -350, -60, +-279, -125, -190, -202, -121, -276, -91, -331, +-78, -352, -70, -343, -28, -291, 56, -200, +155, -65, 213, 98, 211, 263, 156, 389, +73, 441, -4, 401, -40, 271, -31, 101, +0, -38, 32, -86, 22, -33, -40, 78, +-153, 173, -272, 175, -351, 55, -355, -162, +-294, -397, -200, -566, -99, -601, 0, -480, +96, -240, 180, 54, 249, 315, 280, 473, +262, 500, 184, 407, 83, 238, -20, 52, +-111, -89, -172, -150, -184, -119, -150, -21, +-110, 95, -88, 173, -102, 172, -138, 95, +-188, -50, -211, -217, -187, -370, -116, -460, +-24, -462, 73, -361, 162, -157, 222, 111, +239, 379, 200, 564, 126, 605, 29, 475, +-67, 221, -151, -70, -203, -292, -220, -368, +-202, -283, -165, -84, -119, 127, -70, 252, +-24, 238, 25, 94, 54, -125, 53, -332, +7, -449, -76, -438, -152, -305, -154, -97, +-78, 126, 43, 303, 163, 399, 234, 411, +219, 351, 129, 250, 16, 131, -105, 16, +-202, -86, -241, -166, -214, -208, -164, -216, +-113, -186, -83, -131, -94, -67, -124, -20, +-125, -12, -80, -44, -17, -95, 55, -128, +118, -112, 171, -29, 213, 96, 240, 226, +217, 313, 137, 333, 11, 282, -133, 175, +-258, 49, -331, -70, -335, -158, -291, -206, +-200, -214, -83, -198, 30, -168, 90, -133, +97, -99, 61, -70, 0, -42, -61, 2, +-99, 58, -98, 110, -63, 143, 2, 146, +81, 121, 158, 83, 185, 57, 162, 56, +107, 77, 47, 109, -20, 124, -98, 102, +-184, 41, -267, -44, -327, -135, -345, -219, +-294, -280, -188, -310, -56, -295, 62, -238, +154, -126, 200, 28, 191, 192, 138, 313, +73, 359, 24, 321, 1, 209, 8, 67, +15, -55, 11, -102, -15, -69, -50, 20, +-95, 116, -141, 168, -182, 129, -207, -11, +-201, -209, -157, -394, -95, -492, -51, -464, +-24, -307, -11, -70, 6, 165, 39, 329, +110, 392, 186, 367, 241, 296, 261, 227, +223, 183, 101, 147, -83, 83, -273, -36, +-417, -194, -456, -345, -379, -421, -215, -382, +-39, -241, 103, -56, 172, 96, 170, 161, +122, 125, 59, 33, 1, -45, -39, -51, +-51, 27, -53, 153, -39, 269, -9, 317, +37, 272, 64, 142, 71, -15, 52, -150, +2, -224, -72, -223, -145, -159, -199, -72, +-242, -14, -255, -6, -230, -60, -161, -146, +-64, -214, 54, -216, 167, -133, 262, 25, +312, 224, 297, 397, 202, 470, 42, 410, +-141, 239, -311, 6, -403, -220, -383, -363, +-257, -378, -87, -267, 87, -75, 223, 126, +283, 260, 237, 277, 100, 173, -90, -14, +-290, -217, -419, -366, -417, -401, -276, -311, +-50, -124, 200, 115, 392, 342, 468, 492, +403, 509, 221, 389, -26, 167, -257, -95, +-391, -319, -399, -432, -288, -397, -120, -239, +28, -20, 86, 172, 62, 267, -13, 226, +-94, 76, -145, -115, -143, -268, -91, -324, +-10, -260, 80, -89, 146, 125, 182, 319, +181, 431, 156, 431, 103, 316, 34, 120, +-49, -99, -136, -285, -220, -382, -275, -358, +-284, -226, -245, -38, -158, 130, -53, 211, +48, 175, 111, 42, 132, -126, 93, -250, +15, -275, -59, -180, -94, 16, -74, 243, +10, 411, 131, 453, 223, 350, 238, 130, +151, -131, -2, -331, -178, -402, -308, -327, +-359, -147, -324, 61, -214, 203, -62, 228, +80, 145, 162, 5, 157, -116, 66, -165, +-65, -131, -174, -51, -199, 31, -140, 69, +-13, 59, 136, 23, 251, -2, 281, 6, +222, 49, 102, 112, -42, 153, -154, 147, +-207, 94, -206, 21, -192, -54, -183, -110, +-191, -138, -194, -147, -171, -147, -112, -135, +-28, -107, 68, -69, 158, -22, 211, 29, +216, 67, 172, 77, 93, 67, -7, 51, +-75, 46, -76, 73, -23, 133, 33, 212, +55, 267, 20, 253, -69, 151, -183, -27, +-294, -239, -361, -423, -356, -523, -254, -503, +-84, -366, 117, -140, 276, 109, 334, 314, +276, 428, 151, 441, 38, 362, -26, 213, +-39, 47, -28, -88, -21, -168, -34, -194, +-62, -171, -113, -115, -172, -52, -224, -10, +-227, 6, -162, 0, -47, -20, 75, -35, +144, -29, 140, 6, 78, 71, 11, 150, +-34, 210, -48, 207, -52, 125, -47, -32, +-40, -225, -48, -393, -68, -476, -84, -424, +-74, -226, -29, 78, 54, 402, 144, 653, +197, 751, 166, 656, 58, 382, -99, -3, +-246, -395, -340, -698, -357, -843, -282, -796, +-143, -563, 22, -207, 153, 173, 226, 489, +232, 683, 195, 737, 129, 642, 62, 435, +4, 176, -48, -83, -103, -312, -148, -488, +-164, -584, -165, -585, -153, -479, -126, -275, +-68, -6, -6, 270, 48, 484, 82, 580, +82, 538, 39, 374, -26, 125, -79, -148, +-97, -381, -69, -530, -8, -580, 73, -517, +137, -320, 161, -10, 118, 353, 25, 693, +-70, 917, -131, 929, -156, 681, -147, 206, +-119, -389, -104, -938, -119, -1279, -155, -1296, +-161, -967, -131, -374, -59, 320, 55, 918, +196, 1254, 312, 1243, 340, 907, 254, 359, +92, -236, -84, -705, -218, -919, -268, -840, +-240, -530, -154, -105, -58, 303, 15, 573, +48, 631, 48, 485, 23, 205, -20, -120, +-82, -399, -143, -570, -169, -601, -150, -488, +-71, -251, 51, 56, 186, 370, 262, 621, +232, 738, 95, 667, -88, 408, -242, 34, +-308, -347, -248, -628, -76, -728, 141, -610, +307, -309, 363, 70, 278, 403, 80, 585, +-176, 573, -398, 382, -521, 70, -512, -268, +-380, -521, -168, -613, 91, -526, 332, -283, +490, 44, 532, 359, 472, 573, 303, 626, +54, 508, -221, 254, -442, -50, -572, -324, +-592, -498, -470, -518, -225, -393, 79, -166, +358, 94, 533, 318, 554, 434, 420, 410, +162, 255, -125, 24, -349, -221, -452, -419, +-442, -502, -342, -434, -165, -234, 43, 36, +228, 309, 337, 518, 342, 605, 234, 531, +62, 305, -119, -12, -247, -344, -299, -596, +-272, -680, -184, -566, -81, -285, 12, 89, +82, 439, 124, 642, 138, 623, 135, 389, +118, 33, 87, -317, 29, -528, -41, -521, +-102, -312, -125, 2, -111, 288, -93, 447, +-88, 419, -102, 219, -112, -63, -108, -295, +-54, -384, 50, -331, 151, -182, 187, 6, +142, 170, 33, 259, -96, 259, -197, 196, +-222, 102, -151, -3, -26, -114, 124, -207, +247, -248, 289, -217, 219, -118, 52, 31, +-162, 199, -338, 316, -419, 315, -372, 188, +-208, -13, 14, -211, 238, -336, 374, -332, +393, -199, 280, 14, 51, 224, -220, 343, +-424, 310, -486, 131, -391, -120, -181, -337, +95, -428, 371, -346, 540, -94, 547, 255, +371, 569, 60, 700, -302, 579, -596, 240, +-716, -227, -611, -690, -319, -976, 62, -950, +406, -609, 607, -62, 623, 534, 441, 996, +135, 1160, -203, 957, -463, 459, -581, -186, +-529, -781, -326, -1117, -15, -1071, 317, -673, +558, -67, 621, 547, 477, 962, 161, 1039, +-260, 757, -646, 221, -855, -385, -792, -864, +-485, -1049, -26, -876, 465, -421, 844, 160, +980, 694, 804, 1015, 372, 1014, -172, 692, +-653, 149, -937, -435, -929, -867, -640, -1000, +-171, -806, 306, -360, 654, 198, 801, 696, +697, 955, 366, 875, -73, 498, -470, -46, +-716, -587, -749, -956, -578, -1026, -245, -760, +128, -241, 435, 385, 601, 918, 591, 1172, +432, 1061, 169, 624, -107, -8, -305, -629, +-377, -1023, -331, -1062, -202, -756, -70, -239, +14, 306, 10, 691, -53, 777, -109, 549, +-120, 124, -69, -309, 23, -593, 124, -627, +208, -393, 252, 14, 238, 429, 163, 702, +23, 747, -134, 548, -265, 171, -324, -253, +-281, -587, -141, -735, 54, -665, 227, -396, +310, -24, 250, 317, 61, 510, -197, 502, +-418, 310, -506, 11, -408, -282, -156, -438, +164, -387, 437, -167, 572, 134, 535, 407, +333, 540, 44, 464, -248, 223, -445, -65, +-481, -300, -342, -424, -96, -399, 152, -239, +290, -28, 268, 134, 86, 184, -189, 116, +-408, -31, -475, -189, -351, -279, -97, -243, +198, -72, 462, 182, 616, 425, 592, 571, +396, 555, 82, 360, -245, 51, -491, -249, +-613, -452, -563, -528, -373, -478, -105, -327, +158, -129, 342, 45, 413, 168, 359, 254, +181, 309, -47, 308, -231, 237, -310, 104, +-283, -79, -206, -266, -88, -386, 53, -387, +184, -269, 256, -53, 253, 219, 203, 458, +140, 569, 54, 522, -58, 351, -176, 90, +-271, -220, -311, -491, -285, -628, -174, -596, +-10, -414, 129, -119, 188, 214, 176, 473, +112, 551, 18, 415, -84, 111, -161, -259, +-182, -569, -141, -684, -40, -516, 98, -102, +242, 421, 338, 880, 356, 1119, 276, 1034, +112, 623, -102, 5, -321, -646, -476, -1137, +-530, -1309, -481, -1118, -335, -648, -112, -55, +123, 485, 316, 812, 412, 847, 430, 623, +385, 263, 283, -81, 151, -267, 10, -232, +-124, -31, -246, 209, -358, 349, -424, 298, +-412, 44, -344, -316, -198, -630, 15, -750, +277, -596, 516, -191, 629, 343, 580, 815, +384, 1032, 83, 890, -273, 412, -614, -284, +-822, -978, -804, -1423, -593, -1439, -245, -976, +152, -130, 512, 853, 741, 1640, 772, 1960, +636, 1716, 420, 966, 183, -86, -58, -1094, +-288, -1717, -488, -1810, -629, -1423, -730, -708, +-753, 90, -631, 706, -329, 986, 108, 948, +578, 705, 982, 400, 1205, 162, 1145, 42, +756, -1, 122, -44, -595, -134, -1205, -294, +-1544, -493, -1483, -647, -1003, -641, -201, -416, +703, -22, 1441, 429, 1785, 798, 1602, 957, +949, 815, 1, 397, -965, -163, -1653, -686, +-1850, -1011, -1502, -1033, -720, -729, 227, -184, +1055, 421, 1535, 890, 1546, 1092, 1137, 986, +452, 591, -271, 20, -828, -538, -1112, -904, +-1081, -998, -783, -822, -348, -428, 105, 51, +456, 445, 645, 641, 661, 621, 514, 432, +275, 161, -8, -76, -259, -194, -406, -177, +-440, -76, -387, 34, -265, 80, -106, 32, +69, -88, 212, -209, 303, -253, 360, -183, +352, -22, 271, 167, 118, 318, -75, 349, +-272, 209, -433, -68, -506, -356, -441, -547, +-248, -570, 21, -378, 280, 4, 453, 457, +512, 813, 415, 951, 174, 809, -124, 388, +-360, -200, -495, -757, -500, -1092, -349, -1107, +-58, -788, 270, -207, 508, 456, 587, 950, +496, 1097, 248, 874, -108, 363, -448, -271, +-658, -804, -649, -1025, -457, -853, -163, -371, +160, 237, 429, 748, 570, 975, 537, 834, +351, 397, 106, -155, -126, -615, -311, -811, +-394, -679, -364, -289, -233, 177, -74, 520, +47, 604, 145, 410, 215, 28, 234, -381, +193, -634, 89, -613, -46, -318, -185, 129, +-319, 549, -373, 753, -311, 651, -124, 284, +148, -199, 412, -592, 582, -720, 578, -514, +371, -46, 34, 489, -327, 845, -613, 832, +-738, 422, -657, -236, -353, -890, 75, -1266, +480, -1178, 738, -629, 751, 182, 481, 956, +13, 1410, -450, 1371, -726, 859, -738, 82, +-497, -677, -59, -1161, 420, -1198, 746, -793, +787, -135, 546, 502, 105, 897, -385, 922, +-746, 572, -835, -21, -604, -610, -162, -947, +305, -906, 626, -499, 715, 122, 552, 727, +194, 1066, -227, 996, -523, 554, -600, -75, +-468, -641, -178, -932, 160, -846, 425, -451, +491, 61, 336, 452, 75, 574, -159, 413, +-299, 94, -308, -208, -211, -357, -36, -290, +136, -56, 210, 205, 190, 352, 96, 316, +-18, 116, -115, -143, -180, -321, -169, -338, +-70, -212, 26, 9, 61, 239, 30, 346, +8, 262, 34, 70, 66, -111, 112, -221, +163, -229, 180, -104, 116, 92, -31, 212, +-210, 167, -350, -20, -417, -256, -358, -442, +-171, -468, 85, -266, 326, 115, 446, 529, +405, 800, 235, 822, 25, 567, -159, 102, +-265, -445, -274, -887, -177, -1055, -19, -868, +134, -385, 221, 239, 202, 816, 85, 1150, +-84, 1103, -252, 647, -379, -80, -371, -835, +-206, -1352, 56, -1417, 301, -973, 450, -165, +474, 739, 348, 1443, 87, 1678, -207, 1324, +-425, 510, -503, -450, -398, -1235, -158, -1581, +148, -1357, 391, -651, 473, 235, 360, 970, +82, 1325, -235, 1196, -441, 621, -479, -189, +-347, -920, -65, -1314, 269, -1262, 531, -801, +585, -61, 432, 733, 139, 1320, -232, 1494, +-566, 1203, -745, 549, -693, -267, -394, -989, +49, -1388, 491, -1341, 802, -877, 861, -159, +649, 557, 209, 1040, -307, 1150, -713, 884, +-899, 355, -810, -254, -442, -751, 82, -992, +553, -903, 800, -525, 769, 8, 511, 527, +83, 871, -373, 941, -686, 724, -753, 295, +-575, -213, -220, -639, 198, -843, 533, -769, +665, -477, 565, -86, 298, 296, -41, 571, +-340, 669, -509, 573, -501, 325, -334, 9, +-67, -290, 190, -496, 345, -563, 364, -474, +251, -247, 56, 49, -163, 331, -317, 510, +-351, 523, -272, 360, -112, 93, 93, -185, +259, -394, 347, -470, 343, -380, 251, -153, +103, 121, -85, 346, -253, 434, -362, 355, +-404, 129, -358, -168, -213, -425, 16, -531, +316, -420, 565, -119, 634, 272, 458, 617, +83, 774, -336, 652, -682, 268, -842, -259, +-714, -748, -328, -1007, 178, -919, 658, -513, +960, 72, 981, 651, 656, 1017, 87, 1008, +-500, 625, -922, 51, -1043, -483, -835, -807, +-366, -803, 209, -460, 696, 51, 913, 474, +797, 643, 392, 536, -117, 199, -532, -241, +-716, -571, -617, -632, -311, -431, 72, -90, +389, 266, 542, 498, 482, 509, 265, 318, +-6, 55, -227, -144, -354, -182, -371, -61, +-264, 101, -69, 155, 116, 41, 215, -199, +222, -481, 136, -647, 5, -521, -130, -78, +-215, 501, -220, 947, -154, 1036, -32, 678, +117, -17, 246, -768, 331, -1263, 329, -1271, +207, -720, 14, 207, -188, 1102, -316, 1573, +-363, 1443, -328, 745, -182, -299, 35, -1274, +220, -1742, 305, -1525, 263, -744, 128, 308, +-52, 1247, -242, 1694, -345, 1444, -334, 627, +-197, -386, 36, -1187, 274, -1493, 451, -1195, +513, -433, 409, 467, 149, 1130, -198, 1280, +-501, 878, -631, 139, -546, -588, -234, -1023, +186, -1010, 531, -549, 664, 169, 546, 807, +214, 1067, -219, 846, -608, 242, -808, -489, +-746, -1052, -438, -1225, 59, -936, 579, -274, +921, 511, 956, 1108, 684, 1321, 190, 1122, +-368, 588, -789, -121, -929, -752, -747, -1086, +-319, -1074, 211, -778, 625, -290, 751, 248, +561, 662, 159, 822, -305, 695, -622, 349, +-659, -63, -405, -388, 35, -541, 474, -489, +741, -240, 701, 105, 353, 363, -166, 407, +-666, 251, -955, -9, -877, -262, -437, -388, +227, -302, 865, -25, 1218, 313, 1156, 570, +672, 617, -68, 384, -816, -69, -1346, -564, +-1460, -900, -1095, -947, -397, -644, 408, -80, +1064, 531, 1395, 976, 1288, 1104, 760, 836, +49, 232, -581, -458, -950, -956, -970, -1090, +-655, -820, -143, -212, 346, 521, 591, 1082, +547, 1241, 274, 931, -97, 239, -412, -586, +-575, -1212, -518, -1397, -244, -1091, 151, -397, +498, 451, 669, 1130, 607, 1354, 352, 1029, +-28, 316, -392, -484, -602, -1080, -593, -1257, +-372, -922, -14, -179, 358, 681, 595, 1327, +609, 1509, 388, 1157, 11, 378, -399, -561, +-682, -1344, -733, -1699, -556, -1503, -213, -815, +211, 127, 579, 980, 763, 1446, 728, 1379, +473, 835, 80, 31, -341, -718, -640, -1122, +-728, -1044, -614, -543, -328, 159, 74, 780, +447, 1066, 676, 913, 707, 413, 528, -208, +202, -705, -185, -887, -499, -705, -660, -274, +-640, 201, -449, 521, -163, 542, 112, 262, +335, -167, 472, -546, 503, -726, 418, -597, +228, -153, 17, 419, -175, 878, -314, 1088, +-368, 995, -321, 567, -173, -86, 37, -707, +213, -1071, 291, -1100, 246, -810, 98, -282, +-90, 293, -266, 719, -334, 881, -254, 755, +-80, 391, 103, -64, 250, -447, 335, -670, +322, -700, 185, -542, -21, -250, -197, 93, +-284, 420, -256, 661, -140, 743, 15, 647, +149, 405, 236, 65, 240, -311, 147, -616, +-5, -734, -153, -630, -264, -360, -339, -23, +-330, 256, -195, 377, 25, 326, 238, 161, +400, -42, 468, -179, 426, -148, 264, 48, +20, 279, -239, 398, -450, 341, -522, 117, +-434, -209, -225, -500, 65, -603, 341, -450, +465, -59, 408, 428, 221, 770, 0, 769, +-199, 417, -325, -157, -317, -757, -197, -1128, +-24, -1060, 152, -533, 259, 248, 247, 996, +143, 1396, -6, 1235, -128, 558, -182, -329, +-126, -1081, 24, -1407, 165, -1133, 217, -349, +154, 583, -8, 1251, -209, 1396, -351, 941, +-357, 39, -214, -913, 0, -1475, 231, -1424, +409, -804, 448, 147, 330, 1042, 105, 1496, +-140, 1341, -317, 675, -358, -223, -266, -970, +-89, -1245, 109, -982, 276, -389, 321, 282, +207, 788, -13, 897, -242, 558, -400, 16, +-410, -418, -235, -605, 45, -513, 312, -180, +460, 215, 456, 430, 306, 375, 69, 116, +-161, -201, -313, -400, -345, -354, -228, -81, +-17, 293, 166, 603, 249, 657, 215, 362, +96, -154, -98, -619, -294, -858, -371, -802, +-283, -429, -83, 161, 173, 708, 403, 947, +513, 787, 442, 316, 199, -250, -108, -672, +-377, -810, -491, -636, -398, -208, -161, 300, +127, 650, 366, 692, 428, 464, 268, 98, +-47, -275, -353, -521, -490, -522, -405, -289, +-112, 36, 275, 316, 596, 469, 704, 435, +524, 194, 96, -167, -409, -498, -769, -672, +-817, -628, -539, -370, -33, 51, 535, 536, +912, 934, 910, 1062, 532, 843, -58, 345, +-641, -289, -997, -919, -977, -1341, -574, -1332, +45, -845, 643, -53, 1018, 790, 1016, 1432, +643, 1623, 61, 1225, -503, 349, -860, -704, +-870, -1575, -543, -1944, -30, -1626, 460, -699, +751, 532, 756, 1654, 473, 2253, 17, 2079, +-423, 1188, -711, -113, -761, -1392, -528, -2222, +-114, -2294, 305, -1575, 593, -347, 706, 938, +639, 1861, 387, 2129, 29, 1654, -319, 621, +-558, -583, -616, -1538, -474, -1944, -193, -1679, +157, -836, 471, 306, 646, 1340, 582, 1894, +286, 1788, -112, 1095, -503, 72, -772, -958, +-774, -1659, -465, -1776, 47, -1263, 578, -367, +928, 544, 990, 1162, 714, 1327, 168, 1031, +-443, 416, -889, -262, -1006, -738, -758, -840, +-249, -592, 328, -169, 771, 235, 916, 471, +731, 456, 279, 234, -268, -38, -681, -211, +-818, -229, -674, -91, -321, 142, 129, 302, +526, 245, 746, -12, 737, -335, 520, -588, +165, -636, -205, -414, -485, 14, -619, 493, +-596, 834, -418, 854, -139, 517, 170, 3, +452, -455, 640, -718, 669, -699, 487, -359, +136, 155, -270, 569, -625, 705, -827, 546, +-770, 138, -432, -381, 105, -775, 659, -859, +1028, -614, 1073, -158, 735, 347, 122, 731, +-564, 856, -1084, 666, -1226, 240, -910, -249, +-264, -603, 491, -691, 1101, -507, 1353, -139, +1118, 309, 454, 686, -366, 802, -1066, 583, +-1420, 121, -1285, -425, -669, -904, 213, -1137, +1036, -982, 1487, -462, 1420, 248, 873, 930, +47, 1352, -753, 1333, -1274, 870, -1333, 117, +-909, -709, -195, -1333, 511, -1471, 991, -1076, +1116, -336, 844, 509, 275, 1221, -325, 1508, +-711, 1210, -802, 476, -621, -397, -245, -1132, +176, -1490, 461, -1312, 553, -672, 464, 164, +246, 920, 28, 1347, -71, 1296, -70, 836, +-61, 176, -75, -484, -137, -949, -274, -1064, +-413, -841, -406, -443, -201, 5, 142, 419, +503, 664, 754, 664, 754, 530, 460, 373, +-25, 153, -542, -132, -897, -376, -900, -534, +-514, -636, 105, -629, 734, -427, 1128, -45, +1126, 418, 688, 852, -47, 1078, -784, 932, +-1245, 426, -1266, -266, -819, -947, -74, -1382, +676, -1327, 1158, -752, 1191, 119, 785, 989, +119, 1569, -524, 1589, -907, 992, -903, 17, +-513, -963, 105, -1616, 675, -1698, 926, -1129, +763, -124, 294, 909, -268, 1574, -712, 1644, +-846, 1084, -616, 111, -128, -884, 391, -1520, +727, -1560, 783, -971, 548, 11, 100, 954, +-388, 1484, -715, 1455, -758, 896, -496, -29, +-64, -965, 379, -1498, 718, -1433, 856, -863, +700, -17, 298, 817, -162, 1337, -529, 1362, +-746, 904, -764, 149, -518, -617, -81, -1105, +359, -1182, 652, -864, 747, -263, 606, 421, +269, 912, -150, 1039, -515, 816, -689, 322, +-586, -312, -231, -827, 220, -987, 618, -798, +845, -364, 775, 210, 364, 738, -204, 967, +-675, 796, -917, 342, -884, -185, -533, -594, +60, -771, 629, -692, 954, -384, 945, 71, +610, 459, 67, 586, -453, 487, -756, 332, +-754, 143, -452, -104, 46, -305, 518, -374, +760, -379, 720, -374, 413, -284, -63, -58, +-523, 245, -761, 515, -687, 674, -359, 641, +89, 357, 524, -135, 775, -657, 716, -982, +367, -945, -131, -535, -569, 97, -778, 728, +-662, 1115, -250, 1074, 291, 569, 757, -190, +986, -839, 849, -1093, 391, -897, -159, -348, +-605, 375, -843, 954, -810, 1067, -509, 638, +-71, -86, 334, -753, 579, -1079, 623, -938, +482, -364, 228, 419, -64, 1058, -305, 1228, +-407, 826, -335, 52, -148, -745, 59, -1252, +263, -1282, 432, -774, 499, 106, 413, 974, +194, 1459, -100, 1407, -390, 873, -606, 38, +-692, -827, -554, -1419, -170, -1523, 321, -1144, +730, -462, 922, 310, 814, 980, 428, 1346, +-160, 1292, -740, 863, -1012, 223, -847, -454, +-340, -1000, 321, -1227, 932, -1027, 1286, -475, +1161, 238, 512, 901, -365, 1269, -1113, 1172, +-1489, 623, -1351, -193, -724, -1005, 182, -1509, +1049, -1481, 1538, -920, 1454, -30, 877, 887, +78, 1525, -635, 1618, -1063, 1145, -1094, 343, +-733, -498, -157, -1145, 364, -1357, 678, -1058, +758, -447, 607, 197, 291, 687, -44, 909, +-272, 807, -372, 483, -349, 95, -258, -261, +-162, -526, -68, -632, 53, -600, 178, -497, +245, -300, 255, 21, 272, 370, 274, 640, +179, 797, 28, 776, -106, 500, -183, 22, +-172, -482, -94, -844, -7, -940, 77, -717, +138, -232, 128, 349, 31, 819, -100, 1001, +-169, 790, -182, 256, -161, -394, -42, -939, +162, -1195, 313, -1015, 366, -435, 364, 313, +327, 955, 206, 1297, -8, 1220, -227, 711, +-379, -49, -423, -744, -343, -1125, -186, -1122, +24, -743, 295, -99, 520, 562, 560, 960, +404, 968, 151, 631, -151, 82, -480, -503, +-680, -952, -598, -1100, -277, -849, 145, -258, +583, 419, 903, 938, 940, 1195, 631, 1133, +123, 656, -378, -129, -759, -866, -916, -1264, +-764, -1240, -360, -777, 148, 40, 619, 891, +872, 1421, 789, 1416, 443, 834, 23, -158, +-389, -1150, -715, -1724, -755, -1687, -442, -1029, +30, 97, 476, 1262, 814, 1911, 898, 1816, +631, 1091, 141, -34, -326, -1193, -649, -1844, +-754, -1675, -553, -844, -155, 255, 189, 1240, +391, 1750, 455, 1514, 338, 613, 81, -541, +-148, -1462, -164, -1784, -6, -1382, 172, -468, +305, 579, 317, 1411, 118, 1697, -193, 1249, +-435, 298, -495, -635, -278, -1222, 165, -1364, +601, -987, 799, -152, 723, 727, 408, 1201, +-155, 1168, -797, 753, -1133, 84, -997, -609, +-560, -1026, 39, -1040, 709, -718, 1204, -206, +1272, 312, 914, 635, 302, 692, -354, 528, +-862, 243, -1066, -54, -888, -260, -376, -346, +262, -339, 771, -222, 993, -2, 895, 218, +536, 347, -14, 417, -590, 399, -921, 190, +-877, -185, -585, -530, -176, -692, 286, -653, +674, -421, 819, -12, 657, 439, 348, 690, +49, 626, -226, 327, -414, -48, -406, -325, +-231, -369, 39, -182, 309, 132, 470, 413, +492, 472, 369, 225, 63, -192, -368, -547, +-727, -717, -842, -645, -683, -281, -319, 266, +231, 674, 861, 740, 1284, 529, 1270, 172, +838, -240, 151, -547, -616, -605, -1250, -421, +-1506, -91, -1217, 247, -451, 446, 533, 459, +1389, 377, 1802, 242, 1604, 32, 867, -198, +-193, -329, -1264, -375, -1922, -424, -1866, -398, +-1151, -183, -64, 143, 1073, 410, 1848, 547, +1931, 518, 1344, 296, 369, -82, -676, -478, +-1427, -701, -1565, -608, -1083, -219, -274, 284, +571, 689, 1224, 866, 1384, 736, 968, 262, +243, -379, -492, -847, -1041, -953, -1193, -740, +-869, -288, -238, 292, 445, 762, 980, 890, +1178, 633, 930, 154, 403, -354, -163, -729, +-654, -829, -920, -579, -778, -84, -322, 444, +175, 814, 560, 926, 787, 750, 743, 308, +375, -284, -101, -813, -441, -1075, -598, -985, +-583, -563, -383, 41, -67, 627, 259, 1027, +479, 1099, 553, 759, 533, 116, 436, -566, +250, -1046, -5, -1152, -265, -820, -450, -162, +-510, 546, -441, 1055, -203, 1200, 174, 907, +524, 262, 680, -445, 591, -933, 291, -1076, +-139, -822, -580, -254, -837, 341, -732, 689, +-320, 725, 231, 474, 775, 38, 1140, -356, +1130, -508, 688, -402, -4, -138, -649, 158, +-1043, 353, -1109, 361, -807, 208, -191, 2, +491, -156, 921, -167, 1018, -18, 832, 148, +405, 176, -143, 70, -621, -111, -867, -317, +-794, -456, -454, -435, 20, -225, 499, 104, +847, 426, 967, 605, 776, 575, 332, 318, +-142, -77, -546, -431, -855, -598, -901, -549, +-617, -295, -127, 135, 414, 588, 816, 836, +953, 756, 813, 385, 420, -190, -136, -799, +-644, -1178, -887, -1145, -790, -686, -432, 96, +84, 915, 634, 1385, 972, 1343, 949, 851, +628, 0, 140, -980, -382, -1598, -751, -1499, +-832, -777, -624, 221, -229, 1170, 216, 1719, +572, 1581, 720, 809, 621, -267, 326, -1270, +-31, -1801, -320, -1584, -464, -785, -427, 192, +-258, 1036, -29, 1487, 283, 1321, 596, 629, +693, -178, 538, -768, 261, -1020, -71, -865, +-463, -344, -790, 228, -816, 559, -507, 635, +-51, 512, 442, 174, 832, -214, 933, -371, +717, -276, 270, -123, -274, -27, -701, 23, +-810, 20, -550, -62, -54, -177, 467, -206, +853, -83, 929, 164, 610, 405, 58, 496, +-491, 403, -869, 167, -949, -185, -659, -537, +-96, -672, 466, -501, 797, -138, 868, 265, +651, 623, 184, 809, -296, 644, -543, 140, +-510, -411, -276, -782, 76, -944, 452, -814, +666, -321, 574, 327, 265, 791, -98, 969, +-382, 887, -518, 517, -504, -85, -351, -642, +-88, -914, 192, -869, 388, -535, 439, 12, +363, 547, 252, 853, 123, 864, -38, 552, +-181, -9, -222, -563, -156, -888, -38, -921, +128, -631, 329, -76, 439, 488, 367, 805, +154, 826, -117, 589, -353, 134, -474, -339, +-405, -576, -149, -530, 158, -312, 383, 29, +457, 373, 316, 499, 12, 346, -283, 24, +-421, -342, -313, -617, -25, -649, 321, -416, +639, -8, 790, 448, 646, 803, 273, 870, +-175, 572, -523, 45, -678, -500, -664, -889, +-448, -956, -39, -611, 376, 20, 604, 683, +577, 1104, 339, 1080, 20, 587, -296, -182, +-518, -936, -509, -1372, -220, -1275, 251, -637, +696, 287, 934, 1082, 877, 1448, 500, 1293, +-112, 663, -706, -257, -1035, -1067, -1004, -1391, +-623, -1143, 39, -507, 721, 263, 1076, 932, +1000, 1269, 610, 1107, 11, 510, -642, -232, +-1055, -863, -988, -1225, -475, -1219, 209, -820, +839, -128, 1230, 659, 1190, 1281, 727, 1525, +14, 1304, -724, 643, -1183, -318, -1170, -1306, +-764, -1931, -84, -1882, 676, -1138, 1196, 47, +1236, 1334, 841, 2261, 218, 2372, -476, 1583, +-1055, 211, -1222, -1289, -902, -2404, -323, -2637, +348, -1847, 956, -405, 1260, 1085, 1150, 2137, +719, 2415, 114, 1798, -471, 549, -863, -787, +-994, -1707, -840, -1928, -388, -1443, 203, -540, +628, 431, 806, 1172, 847, 1444, 682, 1179, +190, 597, -416, -29, -794, -554, -878, -907, +-762, -1006, -399, -832, 240, -475, 901, -47, +1295, 374, 1306, 721, 943, 894, 261, 814, +-587, 473, -1328, -16, -1639, -501, -1347, -855, +-551, -917, 417, -585, 1222, 7, 1680, 572, +1610, 926, 896, 959, -182, 622, -1098, 13, +-1562, -633, -1527, -1086, -976, -1152, -10, -792, +1010, -175, 1689, 441, 1830, 891, 1365, 1079, +433, 907, -598, 444, -1388, -65, -1736, -460, +-1486, -724, -716, -762, 253, -538, 1094, -193, +1577, 146, 1530, 438, 916, 591, -37, 521, +-942, 288, -1476, -22, -1452, -341, -869, -571, +41, -587, 1014, -373, 1756, -8, 1875, 385, +1246, 639, 187, 596, -870, 298, -1614, -79, +-1827, -449, -1404, -687, -446, -600, 659, -191, +1473, 301, 1721, 680, 1364, 820, 593, 628, +-325, 148, -1137, -387, -1534, -746, -1330, -846, +-668, -674, 176, -272, 972, 179, 1510, 464, +1595, 561, 1201, 533, 482, 404, -356, 220, +-1109, 60, -1543, -81, -1497, -254, -999, -459, +-217, -647, 644, -710, 1356, -516, 1634, -9, +1358, 658, 669, 1177, -208, 1306, -1017, 993, +-1480, 249, -1413, -770, -809, -1650, 91, -1935, +921, -1457, 1424, -390, 1460, 894, 1059, 1914, +374, 2223, -436, 1673, -1076, 513, -1213, -831, +-903, -1884, -421, -2186, 103, -1604, 588, -491, +835, 680, 688, 1552, 311, 1792, -8, 1300, +-225, 383, -351, -511, -249, -1101, 38, -1205, +284, -793, 356, -148, 233, 359, -28, 621, +-275, 642, -367, 349, -276, -102, -34, -352, +331, -310, 690, -150, 771, 81, 487, 304, +10, 300, -484, 48, -897, -230, -1058, -402, +-779, -452, -158, -304, 503, 72, 1020, 494, +1287, 711, 1139, 654, 589, 363, -113, -63, +-683, -473, -1011, -724, -1060, -723, -754, -425, +-177, 41, 415, 389, 844, 487, 1002, 407, +832, 207, 458, -96, -3, -377, -498, -426, +-881, -172, -941, 181, -641, 424, -160, 517, +350, 428, 848, 110, 1135, -318, 998, -613, +548, -665, 5, -485, -513, -98, -912, 395, +-1016, 757, -735, 811, -216, 572, 318, 102, +750, -506, 949, -988, 812, -1099, 426, -850, +-69, -322, -533, 397, -799, 1057, -745, 1368, +-409, 1232, 55, 687, 552, -113, 964, -884, +1039, -1346, 719, -1359, 202, -911, -391, -103, +-945, 747, -1220, 1241, -1046, 1255, -491, 892, +255, 189, 989, -681, 1463, -1257, 1419, -1247, +877, -785, 57, -116, -839, 580, -1493, 1052, +-1557, 1068, -995, 636, -95, 13, 847, -524, +1575, -781, 1774, -680, 1244, -287, 243, 210, +-755, 615, -1448, 730, -1638, 472, -1206, 24, +-283, -371, 728, -625, 1411, -709, 1558, -545, +1168, -176, 394, 202, -455, 404, -1121, 440, +-1388, 397, -1071, 274, -334, 80, 400, -70, +916, -99, 1184, -90, 1095, -111, 588, -130, +-133, -95, -655, -15, -823, 71, -737, 147, +-429, 199, 31, 158, 457, 7, 667, -209, +578, -438, 299, -573, 24, -526, -208, -303, +-369, 51, -363, 469, -169, 781, 80, 859, +225, 731, 270, 451, 283, 24, 210, -457, +32, -794, -103, -895, -109, -804, -63, -528, +-40, -42, 13, 498, 104, 854, 150, 933, +107, 739, 23, 288, -34, -305, -18, -859, +23, -1167, 27, -1031, 27, -463, 54, 282, +68, 932, 9, 1327, -31, 1324, 56, 826, +159, -4, 136, -780, 77, -1233, 49, -1313, +-26, -1005, -151, -367, -242, 354, -202, 855, +-22, 986, 198, 781, 365, 414, 453, 1, +442, -390, 300, -607, 3, -534, -326, -301, +-494, -85, -496, 98, -392, 253, -154, 313, +206, 244, 538, 148, 673, 133, 565, 158, +331, 109, 59, -46, -274, -244, -621, -415, +-776, -556, -585, -627, -204, -445, 170, 41, +559, 596, 940, 983, 1064, 1104, 814, 834, +340, 147, -182, -681, -697, -1284, -1089, -1434, +-1148, -1019, -833, -102, -274, 945, 374, 1631, +920, 1671, 1213, 1067, 1177, -32, 721, -1237, +-23, -1966, -696, -1856, -1037, -995, -1014, 262, +-691, 1413, -91, 1969, 608, 1724, 1026, 805, +992, -424, 671, -1464, 207, -1852, -284, -1431, +-642, -452, -713, 621, -504, 1399, -200, 1609, +76, 1150, 318, 266, 446, -608, 380, -1187, +217, -1335, 88, -971, 25, -251, -30, 446, +-71, 850, -72, 932, -75, 729, -102, 269, +-107, -281, -68, -642, 54, -697, 243, -524, +349, -183, 346, 237, 302, 571, 167, 711, +-135, 619, -453, 275, -549, -219, -418, -624, +-251, -764, -37, -658, 327, -371, 655, 85, +747, 559, 619, 758, 359, 579, 4, 187, +-413, -268, -747, -658, -793, -748, -561, -436, +-173, 111, 287, 655, 692, 997, 927, 955, +887, 461, 534, -272, -6, -904, -498, -1224, +-798, -1105, -888, -479, -743, 397, -297, 1052, +292, 1232, 718, 906, 870, 143, 812, -764, +578, -1344, 188, -1312, -237, -705, -532, 267, +-631, 1236, -570, 1738, -384, 1522, -133, 697, +176, -414, 500, -1399, 682, -1809, 667, -1450, +503, -591, 186, 383, -243, 1208, -622, 1551, +-800, 1178, -684, 323, -308, -524, 202, -1072, +675, -1256, 924, -1012, 843, -366, 446, 374, +-117, 880, -592, 1081, -792, 1030, -692, 754, +-298, 303, 260, -230, 692, -725, 800, -1043, +604, -1108, 199, -925, -311, -472, -715, 225, +-774, 926, -488, 1310, -59, 1230, 387, 729, +736, -68, 817, -946, 551, -1517, 115, -1448, +-254, -796, -470, 141, -524, 1069, -373, 1671, +-58, 1655, 279, 987, 467, -30, 385, -970, +166, -1542, -19, -1592, -157, -1082, -254, -210, +-245, 647, -88, 1173, 123, 1226, 194, 851, +151, 238, 138, -388, 105, -850, 27, -972, +-20, -681, 40, -159, 181, 307, 252, 603, +181, 735, 78, 658, -39, 321, -205, -96, +-366, -333, -434, -413, -308, -448, -35, -391, +231, -236, 432, -101, 551, -6, 515, 106, +286, 231, -88, 329, -400, 381, -491, 322, +-409, 101, -194, -174, 131, -359, 462, -431, +672, -346, 665, -13, 419, 406, 24, 611, +-438, 536, -806, 235, -906, -287, -703, -808, +-240, -977, 357, -703, 893, -110, 1153, 632, +992, 1218, 482, 1296, -157, 774, -773, -118, +-1120, -1047, -980, -1658, -437, -1608, 253, -830, +848, 361, 1134, 1495, 989, 2125, 488, 1964, +-158, 1034, -728, -349, -1026, -1697, -856, -2465, +-330, -2302, 227, -1284, 635, 174, 807, 1573, +619, 2428, 142, 2424, -313, 1527, -537, 27, +-520, -1458, -249, -2329, 232, -2364, 608, -1611, +666, -269, 507, 1240, 215, 2321, -195, 2513, +-536, 1811, -618, 541, -468, -896, -190, -2055, +149, -2525, 428, -2120, 445, -980, 282, 461, +137, 1645, -55, 2197, -285, 2019, -284, 1165, +-40, -97, 185, -1248, 280, -1828, 329, -1717, +344, -1038, 206, -8, -37, 1035, -220, 1640, +-285, 1574, -262, 986, -197, 117, -135, -826, +-15, -1488, 158, -1567, 224, -1110, 142, -353, +91, 482, 161, 1162, 167, 1436, 52, 1198, +-15, 561, 19, -233, 25, -910, -33, -1253, +-78, -1181, -54, -715, -4, 23, 43, 784, +137, 1268, 205, 1297, 167, 927, 66, 294, +-57, -450, -169, -1073, -228, -1344, -246, -1166, +-162, -646, 16, -25, 140, 551, 168, 969, +164, 1061, 181, 812, 208, 384, 179, -71, +164, -453, 257, -674, 245, -696, 15, -540, +-255, -248, -422, 114, -478, 426, -459, 596, +-303, 635, 101, 526, 596, 212, 823, -228, +685, -574, 337, -749, -38, -783, -444, -576, +-844, -82, -905, 444, -475, 737, 142, 801, +636, 694, 915, 334, 971, -248, 767, -706, +240, -799, -406, -595, -827, -203, -871, 272, +-657, 643, -332, 790, 110, 641, 599, 169, +801, -402, 591, -700, 242, -661, -71, -486, +-352, -185, -573, 259, -561, 572, -240, 496, +181, 150, 439, -181, 531, -369, 527, -388, +395, -187, 102, 170, -240, 493, -383, 621, +-285, 469, -111, 115, 45, -251, 197, -501, +266, -540, 140, -334, -176, -29, -471, 181, +-535, 188, -387, 17, -122, -183, 244, -284, +698, -218, 1028, 57, 979, 488, 564, 803, +16, 734, -550, 315, -1038, -241, -1227, -797, +-935, -1163, -260, -1052, 466, -395, 1057, 482, +1410, 1160, 1303, 1435, 650, 1201, -250, 448, +-1044, -568, -1507, -1424, -1543, -1775, -1072, -1465, +-140, -611, 882, 485, 1576, 1440, 1755, 1873, +1439, 1604, 718, 755, -247, -302, -1175, -1193, +-1652, -1670, -1490, -1549, -871, -801, -59, 244, +790, 1063, 1424, 1381, 1495, 1246, 967, 706, +195, -140, -488, -911, -1037, -1224, -1363, -1009, +-1195, -485, -474, 108, 372, 635, 948, 923, +1236, 798, 1240, 332, 840, -205, 91, -552, +-660, -605, -1049, -448, -980, -127, -631, 305, +-117, 648, 443, 668, 829, 341, 839, -120, +458, -515, -47, -792, -392, -845, -590, -503, +-638, 154, -399, 757, -16, 1027, 285, 946, +439, 524, 487, -189, 472, -902, 370, -1250, +194, -1061, 51, -396, -82, 470, -234, 1178, +-342, 1429, -459, 1094, -508, 271, -341, -748, +-9, -1503, 329, -1622, 593, -1086, 717, -128, +599, 936, 188, 1678, -301, 1721, -640, 1052, +-826, 5, -726, -1013, -231, -1645, 409, -1619, +861, -940, 1057, 74, 962, 990, 511, 1503, +-164, 1450, -717, 804, -991, -151, -1014, -946, +-688, -1340, -80, -1284, 475, -748, 798, 103, +898, 917, 695, 1352, 228, 1294, -285, 804, +-649, 7, -811, -851, -703, -1443, -242, -1534, +391, -1040, 887, -115, 1114, 861, 1008, 1584, +500, 1860, -216, 1482, -873, 397, -1277, -952, +-1299, -1930, -851, -2248, -37, -1881, 789, -806, +1299, 727, 1401, 2078, 1078, 2661, 364, 2310, +-491, 1211, -1169, -327, -1407, -1800, -1138, -2641, +-488, -2540, 323, -1554, 1031, -87, 1435, 1294, +1410, 2181, 917, 2367, 139, 1760, -649, 559, +-1272, -747, -1506, -1688, -1244, -2068, -592, -1841, +227, -1064, 972, 27, 1432, 1075, 1466, 1771, +1053, 1960, 311, 1619, -569, 831, -1321, -239, +-1599, -1308, -1336, -2003, -688, -2048, 225, -1517, +1208, -566, 1841, 659, 1844, 1762, 1278, 2262, +330, 2008, -802, 1135, -1776, -115, -2145, -1390, +-1750, -2220, -796, -2267, 363, -1580, 1449, -425, +2140, 856, 2094, 1860, 1262, 2266, 5, 1970, +-1171, 1071, -1900, -150, -2024, -1274, -1491, -1951, +-338, -2033, 1013, -1512, 1971, -492, 2189, 656, +1682, 1536, 667, 1930, -571, 1703, -1707, 857, +-2257, -328, -1933, -1405, -952, -1984, 287, -1862, +1394, -1045, 2051, 184, 2051, 1323, 1309, 2013, +64, 2050, -1090, 1331, -1778, 76, -1891, -1165, +-1379, -1899, -386, -1915, 773, -1243, 1667, -157, +1977, 903, 1671, 1539, 857, 1559, -252, 975, +-1256, 23, -1895, -899, -1976, -1400, -1385, -1358, +-349, -862, 741, -38, 1602, 812, 2025, 1299, +1837, 1337, 1043, 1050, -46, 474, -1009, -288, +-1691, -939, -1917, -1223, -1489, -1198, -535, -926, +545, -318, 1415, 445, 1902, 978, 1855, 1171, +1168, 1081, 62, 639, -1004, -105, -1776, -834, +-2047, -1235, -1649, -1242, -673, -831, 523, -75, +1530, 712, 2047, 1222, 1934, 1325, 1221, 1021, +170, 409, -873, -281, -1671, -776, -1916, -971, +-1469, -938, -568, -650, 411, -212, 1254, 86, +1746, 172, 1624, 250, 867, 396, -114, 479, +-875, 478, -1321, 487, -1409, 423, -995, 98, +-162, -363, 638, -724, 1061, -888, 1104, -789, +862, -357, 359, 272, -235, 850, -644, 1169, +-758, 1023, -582, 407, -243, -373, 83, -989, +338, -1299, 538, -1171, 547, -530, 283, 392, +-43, 1106, -159, 1341, -191, 1157, -343, 585, +-378, -281, -178, -1049, -22, -1313, 21, -1062, +172, -520, 368, 141, 403, 771, 297, 1101, +212, 1007, 93, 603, -110, 45, -216, -497, +-190, -804, -167, -785, -135, -571, -31, -270, +27, 145, 4, 527, 0, 602, 36, 417, +43, 147, 94, -163, 166, -427, 133, -488, +74, -308, 64, -9, 15, 347, -111, 702, +-140, 775, 6, 409, 151, -54, 165, -400, +202, -752, 223, -998, 56, -824, -196, -297, +-385, 232, -440, 629, -317, 898, -72, 925, +192, 661, 438, 229, 557, -299, 499, -773, +254, -953, -94, -810, -353, -504, -446, -25, +-413, 636, -237, 1111, 65, 1097, 350, 691, +474, 74, 371, -655, 188, -1277, 37, -1452, +-145, -985, -327, -85, -331, 835, -186, 1482, +-41, 1658, 60, 1195, 117, 156, 147, -995, +130, -1744, 113, -1847, 138, -1255, 191, -132, +223, 1059, 169, 1876, -13, 2044, -188, 1458, +-280, 273, -350, -1033, -345, -1921, -197, -2172, +95, -1741, 388, -668, 525, 668, 479, 1724, +297, 2220, 24, 2009, -239, 1143, -455, -62, +-531, -1258, -363, -2105, -61, -2263, 251, -1591, +493, -383, 562, 869, 413, 1855, 137, 2337, +-155, 1976, -397, 809, -538, -646, -421, -1858, +-61, -2489, 266, -2256, 452, -1116, 556, 476, +510, 1901, 195, 2693, -243, 2547, -556, 1432, +-657, -222, -563, -1785, -265, -2732, 110, -2725, +427, -1711, 657, -109, 728, 1416, 550, 2398, +229, 2552, -26, 1796, -254, 477, -518, -804, +-665, -1693, -550, -2027, -326, -1708, -102, -867, +207, 91, 540, 860, 699, 1311, 655, 1392, +466, 1183, 101, 774, -338, 187, -670, -509, +-770, -1120, -625, -1447, -257, -1431, 263, -1083, +740, -324, 937, 708, 826, 1571, 455, 1932, +-125, 1691, -669, 898, -950, -280, -883, -1485, +-530, -2190, -9, -2062, 524, -1224, 891, 10, +932, 1260, 658, 2107, 190, 2228, -346, 1525, +-775, 291, -906, -968, -683, -1858, -243, -2150, +289, -1708, 759, -659, 1002, 571, 915, 1516, +485, 1929, -160, 1702, -742, 932, -1042, -74, +-964, -1039, -549, -1688, 24, -1730, 651, -1161, +1097, -307, 1078, 567, 631, 1290, 11, 1599, +-577, 1349, -951, 739, -1021, -24, -706, -840, +-49, -1404, 620, -1413, 1021, -972, 1046, -339, +747, 397, 254, 1030, -314, 1280, -796, 1109, +-955, 611, -771, -120, -385, -802, 90, -1144, +495, -1095, 673, -737, 639, -178, 516, 468, +278, 978, -93, 1117, -420, 886, -520, 458, +-496, -51, -413, -541, -151, -895, 240, -947, +537, -684, 665, -321, 648, 52, 427, 413, +43, 650, -341, 692, -616, 582, -776, 354, +-684, 49, -296, -256, 137, -474, 449, -585, +692, -593, 770, -469, 553, -224, 163, 122, +-208, 489, -467, 739, -629, 785, -589, 624, +-286, 272, 96, -182, 419, -628, 676, -913, +773, -907, 609, -597, 215, -67, -259, 485, +-648, 818, -954, 839, -1065, 608, -781, 143, +-138, -448, 564, -872, 1101, -883, 1409, -555, +1363, -75, 809, 490, -62, 1009, -861, 1190, +-1433, 886, -1635, 292, -1288, -397, -414, -1015, +627, -1334, 1447, -1256, 1831, -809, 1634, -49, +848, 776, -216, 1322, -1225, 1407, -1932, 1033, +-1989, 328, -1302, -534, -194, -1226, 930, -1421, +1805, -1084, 2124, -387, 1691, 500, 731, 1300, +-321, 1630, -1221, 1273, -1794, 420, -1757, -521, +-1069, -1267, -107, -1602, 727, -1371, 1318, -640, +1517, 309, 1205, 1105, 517, 1431, -249, 1202, +-820, 572, -1100, -181, -1120, -835, -834, -1181, +-255, -1019, 361, -484, 808, 119, 1015, 628, +1011, 932, 779, 906, 308, 590, -259, 126, +-682, -316, -892, -579, -895, -613, -626, -487, +-158, -299, 296, -108, 613, 23, 776, 76, +713, 68, 412, 53, -26, 75, -377, 189, +-532, 392, -558, 548, -409, 525, -65, 339, +294, 13, 528, -440, 586, -854, 425, -1048, +179, -874, -76, -350, -332, 306, -517, 903, +-518, 1324, -294, 1336, 4, 784, 225, -121, +422, -965, 578, -1489, 499, -1603, 167, -1190, +-232, -332, -469, 634, -531, 1379, -480, 1709, +-242, 1511, 212, 835, 657, -61, 796, -829, +596, -1277, 279, -1390, -71, -1150, -496, -621, +-793, 33, -739, 604, -369, 960, 63, 1102, +398, 1039, 612, 708, 638, 175, 412, -417, +6, -927, -384, -1219, -557, -1256, -426, -965, +-139, -276, 122, 612, 335, 1302, 531, 1595, +534, 1491, 287, 986, 7, 114, -205, -860, +-409, -1549, -544, -1753, -497, -1481, -325, -819, +-119, 66, 165, 889, 533, 1411, 738, 1492, +691, 1178, 484, 656, 114, 30, -358, -625, +-719, -1058, -829, -1097, -692, -895, -309, -624, +260, -245, 760, 282, 941, 712, 836, 856, +490, 818, -60, 696, -618, 399, -932, -81, +-872, -514, -513, -701, -6, -717, 474, -651, +736, -418, 732, -66, 536, 229, 150, 389, +-237, 483, -386, 539, -358, 483, -328, 341, +-275, 216, -86, 24, 156, -288, 277, -580, +299, -762, 369, -761, 417, -541, 284, -152, +-27, 338, -358, 834, -580, 1129, -627, 1042, +-525, 594, -274, -34, 226, -692, 778, -1237, +977, -1394, 767, -1028, 383, -323, -75, 464, +-564, 1186, -909, 1616, -813, 1521, -324, 868, +173, -128, 493, -1108, 632, -1745, 571, -1869, +305, -1434, -89, -471, -400, 736, -385, 1720, +-147, 2113, 48, 1865, 138, 1033, 196, -211, +132, -1409, -137, -2078, -397, -2056, -403, -1390, +-183, -226, 104, 1022, 448, 1832, 800, 1971, +901, 1504, 582, 507, 29, -724, -528, -1617, +-908, -1827, -991, -1397, -789, -527, -340, 486, +235, 1269, 704, 1532, 881, 1215, 766, 498, +491, -365, 145, -1008, -284, -1156, -611, -841, +-635, -252, -434, 385, -163, 790, 103, 831, +341, 565, 472, 67, 445, -464, 305, -782, +93, -750, -152, -434, -322, -3, -380, 384, +-299, 632, -116, 679, 35, 500, 128, 141, +191, -256, 198, -488, 98, -504, -59, -397, +-140, -227, -80, 67, 40, 415, 199, 576, +351, 430, 347, 153, 149, -96, -99, -383, +-270, -664, -397, -666, -426, -326, -224, 101, +133, 477, 343, 778, 308, 825, 170, 472, +-4, -75, -238, -542, -363, -838, -218, -860, +72, -523, 374, 79, 606, 705, 618, 1077, +302, 1021, -171, 587, -558, -96, -749, -798, +-673, -1266, -252, -1329, 308, -914, 684, -132, +797, 701, 665, 1253, 255, 1381, -337, 1105, +-755, 466, -795, -412, -598, -1093, -256, -1251, +229, -972, 621, -413, 748, 307, 674, 903, +457, 1114, 114, 889, -259, 287, -452, -456, +-466, -972, -442, -1057, -288, -823, 37, -334, +239, 369, 245, 970, 274, 1114, 311, 809, +158, 281, -105, -284, -215, -723, -185, -899, +-163, -727, -127, -248, 16, 314, 188, 663, +300, 700, 325, 496, 225, 120, 18, -311, +-129, -562, -182, -518, -243, -275, -206, 72, +-49, 368, 69, 398, 105, 146, 158, -184, +214, -450, 118, -536, -133, -339, -256, 140, +-218, 708, -229, 1051, -184, 991, 86, 541, +436, -168, 611, -894, 593, -1346, 439, -1346, +113, -851, -351, -68, -750, 708, -951, 1260, +-875, 1366, -443, 937, 228, 194, 817, -509, +1113, -966, 1127, -1102, 772, -876, 22, -306, +-776, 328, -1246, 727, -1318, 854, -972, 760, +-196, 446, 754, 16, 1398, -336, 1501, -527, +1198, -584, 503, -544, -538, -437, -1446, -295, +-1682, -68, -1285, 200, -578, 427, 307, 660, +1207, 873, 1685, 818, 1476, 402, 721, -143, +-271, -653, -1131, -1132, -1566, -1437, -1452, -1233, +-844, -468, 107, 504, 1088, 1318, 1634, 1811, +1550, 1841, 1068, 1298, 310, 263, -686, -958, +-1519, -1951, -1762, -2399, -1388, -2134, -676, -1224, +192, 25, 1095, 1281, 1735, 2269, 1795, 2624, +1247, 2194, 321, 1198, -668, -93, -1478, -1396, +-1895, -2302, -1695, -2508, -888, -2050, 246, -1104, +1279, 143, 1898, 1351, 1959, 2070, 1422, 2163, +420, 1727, -710, 865, -1597, -189, -1963, -1093, +-1725, -1604, -1011, -1666, -12, -1338, 1004, -725, +1725, 16, 1888, 634, 1465, 995, 666, 1171, +-275, 1210, -1125, 971, -1625, 438, -1636, -116, +-1194, -559, -409, -1011, 566, -1374, 1448, -1344, +1820, -896, 1574, -217, 901, 521, -29, 1154, +-991, 1494, -1682, 1430, -1867, 948, -1406, 177, +-422, -600, 707, -1136, 1580, -1331, 1906, -1158, +1629, -633, 819, 8, -312, 502, -1321, 812, +-1806, 950, -1673, 814, -1005, 444, 10, 39, +1025, -259, 1657, -452, 1678, -632, 1141, -719, +261, -550, -690, -208, -1397, 74, -1546, 277, +-1116, 498, -383, 688, 399, 657, 1013, 371, +1213, 17, 952, -255, 412, -401, -197, -456, +-690, -446, -909, -326, -727, -112, -267, 32, +216, 61, 580, 86, 727, 162, 578, 232, +208, 294, -220, 383, -546, 381, -648, 191, +-520, -97, -240, -368, 90, -595, 427, -680, +619, -527, 503, -156, 169, 273, -156, 609, +-338, 766, -395, 674, -369, 392, -154, 65, +286, -263, 626, -572, 573, -679, 234, -565, +-93, -444, -389, -371, -763, -175, -943, 173, +-577, 510, 122, 767, 675, 981, 983, 1041, +1142, 733, 1009, 116, 376, -604, -509, -1257, +-1170, -1623, -1411, -1488, -1331, -870, -953, 17, +-188, 930, 796, 1617, 1578, 1799, 1856, 1376, +1624, 571, 1025, -338, 159, -1128, -900, -1550, +-1812, -1469, -2188, -986, -1956, -290, -1278, 425, +-275, 967, 953, 1192, 2075, 1102, 2619, 786, +2400, 295, 1572, -216, 327, -579, -1093, -789, +-2313, -879, -2890, -783, -2606, -505, -1591, -152, +-120, 181, 1448, 457, 2633, 673, 3007, 785, +2472, 751, 1280, 548, -204, 240, -1667, -92, +-2671, -459, -2832, -869, -2111, -1100, -837, -998, +575, -661, 1787, -167, 2491, 490, 2448, 1167, +1667, 1564, 467, 1471, -737, 898, -1605, 57, +-1968, -832, -1801, -1561, -1175, -1906, -251, -1658, +635, -828, 1188, 242, 1380, 1164, 1246, 1758, +794, 1908, 165, 1509, -385, 657, -697, -366, +-822, -1201, -844, -1634, -670, -1679, -337, -1351, +-26, -628, 264, 284, 576, 1046, 815, 1511, +876, 1659, 751, 1403, 476, 708, 34, -205, +-570, -1086, -1118, -1747, -1378, -1966, -1253, -1600, +-774, -733, -42, 415, 816, 1539, 1562, 2273, +1867, 2328, 1554, 1665, 775, 505, -232, -899, +-1272, -2153, -2037, -2755, -2131, -2457, -1493, -1428, +-416, 18, 768, 1505, 1783, 2591, 2290, 2871, +2015, 2208, 1067, 886, -161, -623, -1319, -1911, +-2092, -2655, -2159, -2592, -1501, -1725, -426, -373, +711, 966, 1605, 1910, 1938, 2317, 1590, 2126, +809, 1352, -94, 258, -903, -740, -1366, -1413, +-1324, -1776, -905, -1811, -327, -1395, 278, -657, +767, 80, 906, 702, 709, 1280, 447, 1700, +168, 1717, -186, 1298, -464, 612, -485, -175, +-341, -968, -250, -1609, -196, -1907, 15, -1709, +277, -1050, 357, -155, 314, 739, 308, 1428, +300, 1747, 157, 1667, -102, 1218, -350, 444, +-456, -412, -395, -1073, -246, -1436, -83, -1508, +138, -1258, 380, -708, 457, -2, 300, 657, +112, 1108, 17, 1288, -136, 1212, -353, 895, +-396, 310, -218, -343, -34, -780, 65, -961, +186, -952, 378, -695, 518, -247, 509, 148, +313, 346, -63, 406, -454, 352, -737, 139, +-923, -78, -908, -82, -484, 106, 256, 319, +928, 493, 1298, 544, 1363, 376, 1002, -5, +180, -516, -771, -991, -1476, -1188, -1716, -983, +-1393, -498, -594, 124, 433, 827, 1381, 1439, +1897, 1612, 1731, 1228, 961, 499, -44, -349, +-999, -1167, -1741, -1740, -1954, -1829, -1393, -1353, +-331, -449, 678, 614, 1382, 1571, 1699, 2124, +1434, 2025, 586, 1259, -421, 127, -1133, -1032, +-1387, -2002, -1197, -2440, -565, -2000, 331, -826, +1070, 542, 1355, 1678, 1072, 2341, 315, 2353, +-509, 1541, -1034, 86, -1237, -1372, -1081, -2244, +-461, -2416, 432, -1951, 1092, -842, 1222, 664, +995, 1911, 560, 2389, -100, 2185, -761, 1496, +-1035, 332, -891, -1046, -604, -2004, -291, -2223, +120, -1882, 523, -1140, 690, -39, 657, 1148, +601, 1925, 513, 2038, 297, 1597, -24, 808, +-389, -230, -779, -1291, -1091, -1951, -1129, -1918, +-842, -1301, -323, -359, 349, 683, 1084, 1513, +1665, 1860, 1799, 1645, 1385, 929, 590, -86, +-358, -983, -1303, -1479, -2001, -1551, -2163, -1229, +-1728, -543, -849, 260, 277, 835, 1383, 1108, +2163, 1133, 2398, 891, 2018, 472, 1130, 62, +-83, -316, -1366, -679, -2350, -956, -2705, -1039, +-2330, -921, -1357, -652, -43, -200, 1365, 484, +2532, 1217, 3024, 1688, 2660, 1743, 1600, 1327, +146, 436, -1377, -749, -2616, -1815, -3155, -2448, +-2748, -2451, -1622, -1661, -234, -262, 1137, 1201, +2289, 2319, 2872, 2887, 2630, 2625, 1739, 1497, +549, -65, -722, -1467, -1848, -2376, -2512, -2638, +-2570, -2188, -2079, -1136, -1110, 144, 184, 1219, +1445, 1853, 2345, 2005, 2738, 1700, 2494, 1014, +1581, 169, 195, -583, -1296, -1114, -2481, -1457, +-2995, -1574, -2693, -1325, -1711, -713, -290, 36, +1280, 726, 2478, 1310, 2849, 1666, 2443, 1589, +1533, 1043, 277, 223, -1104, -629, -2109, -1310, +-2384, -1669, -2079, -1572, -1452, -1052, -524, -312, +570, 445, 1455, 1047, 1876, 1369, 1840, 1375, +1469, 1083, 852, 556, 68, -45, -757, -574, +-1457, -955, -1833, -1191, -1746, -1226, -1265, -966, +-524, -469, 433, 115, 1379, 717, 1919, 1246, +1897, 1470, 1450, 1294, 670, 790, -361, 52, +-1372, -800, -1979, -1492, -2011, -1780, -1524, -1580, +-589, -897, 601, 139, 1605, 1213, 2093, 1960, +2002, 2178, 1309, 1802, 129, 849, -1149, -509, +-2005, -1789, -2156, -2517, -1614, -2546, -519, -1937, +811, -721, 1862, 887, 2257, 2313, 1890, 2981, +842, 2732, -518, 1815, -1663, 448, -2230, -1171, +-2078, -2547, -1206, -3092, 120, -2687, 1337, -1597, +2021, -135, 2106, 1352, 1578, 2473, 500, 2898, +-696, 2485, -1530, 1394, -1861, 48, -1719, -1212, +-1109, -2167, -205, -2555, 682, -2222, 1343, -1382, +1651, -306, 1491, 832, 971, 1697, 303, 2032, +-454, 1909, -1160, 1427, -1494, 590, -1388, -343, +-1033, -1033, -447, -1413, 356, -1520, 1087, -1243, +1447, -639, 1403, -21, 1039, 439, 355, 759, +-536, 912, -1274, 838, -1583, 550, -1451, 163, +-914, -96, -63, -166, 855, -222, 1507, -353, +1660, -372, 1317, -227, 587, -159, -352, -286, +-1200, -379, -1697, -207, -1710, 81, -1170, 256, +-243, 410, 704, 696, 1422, 898, 1786, 751, +1605, 345, 840, -91, -157, -536, -975, -1022, +-1543, -1357, -1818, -1295, -1528, -830, -645, -197, +384, 469, 1115, 1135, 1493, 1619, 1538, 1651, +1117, 1223, 274, 540, -602, -224, -1157, -994, +-1314, -1622, -1068, -1791, -492, -1389, 161, -690, +648, 36, 858, 770, 729, 1424, 361, 1715, +-3, 1460, -234, 811, -353, 44, -343, -697, +-196, -1317, -63, -1640, -37, -1494, -13, -932, +46, -143, 39, 680, 33, 1366, 137, 1726, +238, 1649, 165, 1103, -54, 204, -249, -748, +-326, -1479, -323, -1859, -206, -1791, 132, -1177, +578, -171, 853, 862, 793, 1641, 425, 2018, +-105, 1806, -669, 1001, -1151, -98, -1328, -1154, +-1044, -1916, -424, -2111, 296, -1622, 991, -644, +1557, 529, 1764, 1599, 1451, 2227, 734, 2128, +-157, 1356, -1084, 240, -1852, -913, -2209, -1912, +-2013, -2417, -1245, -2071, -64, -1094, 1210, -25, +2250, 971, 2780, 1910, 2608, 2379, 1746, 2013, +358, 1113, -1243, 173, -2591, -791, -3248, -1785, +-3053, -2343, -2123, -2126, -651, -1418, 1087, -565, +2622, 521, 3485, 1755, 3474, 2561, 2633, 2566, +1180, 1956, -619, 930, -2387, -411, -3616, -1805, +-3973, -2827, -3406, -3108, -1988, -2538, 12, -1315, +2079, 223, 3664, 1793, 4382, 3019, 4018, 3458, +2548, 2972, 355, 1809, -1887, 215, -3642, -1530, +-4540, -2927, -4258, -3532, -2776, -3273, -558, -2281, +1676, -697, 3342, 1098, 4151, 2567, 3910, 3355, +2567, 3355, 580, 2525, -1345, 1034, -2806, -682, +-3572, -2139, -3359, -3024, -2187, -3176, -584, -2514, +872, -1195, 1960, 364, 2561, 1701, 2438, 2571, +1560, 2817, 336, 2340, -684, 1259, -1221, -75, +-1359, -1255, -1195, -1992, -674, -2219, 53, -2001, +510, -1330, 397, -312, -61, 645, -436, 1189, +-585, 1417, -565, 1508, -200, 1320, 649, 758, +1575, 187, 1964, -154, 1644, -523, 795, -1006, +-481, -1252, -1975, -1145, -3081, -968, -3187, -733, +-2224, -209, -545, 536, 1414, 1126, 3165, 1375, +4100, 1368, 3771, 1167, 2214, 646, -23, -157, +-2224, -879, -3802, -1286, -4327, -1430, -3600, -1315, +-1808, -872, 472, -224, 2514, 443, 3773, 1015, +4015, 1374, 3185, 1426, 1498, 1202, -463, 711, +-2134, -34, -3204, -811, -3466, -1377, -2808, -1668, +-1449, -1637, 115, -1130, 1495, -225, 2525, 748, +2982, 1537, 2702, 2008, 1809, 1963, 531, 1301, +-832, 225, -1927, -923, -2567, -1815, -2692, -2213, +-2177, -1995, -1053, -1196, 341, -10, 1579, 1192, +2439, 2017, 2782, 2205, 2418, 1747, 1373, 823, +-11, -297, -1341, -1276, -2294, -1804, -2636, -1747, +-2346, -1240, -1515, -477, -257, 301, 1100, 804, +2058, 933, 2364, 844, 2106, 639, 1433, 400, +430, 335, -664, 466, -1506, 502, -1942, 221, +-1963, -285, -1582, -924, -868, -1599, 39, -2013, +936, -1809, 1600, -947, 1913, 331, 1831, 1707, +1323, 2785, 446, 3102, -541, 2453, -1325, 1078, +-1842, -605, -2073, -2135, -1771, -3078, -890, -3162, +151, -2386, 965, -1000, 1525, 545, 1835, 1800, +1680, 2500, 1020, 2548, 212, 2002, -493, 1049, +-1106, -26, -1533, -970, -1576, -1602, -1223, -1874, +-634, -1755, -1, -1239, 605, -479, 1158, 281, +1464, 940, 1298, 1437, 743, 1559, 93, 1214, +-533, 602, -1131, -12, -1447, -582, -1157, -1022, +-446, -1082, 221, -720, 701, -268, 1041, 38, +1034, 241, 479, 354, -335, 255, -877, -47, +-982, -297, -811, -281, -344, -8, 487, 340, +1280, 641, 1470, 862, 1015, 925, 274, 678, +-551, 112, -1356, -576, -1818, -1192, -1628, -1629, +-854, -1741, 185, -1345, 1133, -513, 1713, 522, +1851, 1534, 1555, 2278, 771, 2477, -292, 2045, +-1116, 1021, -1481, -431, -1584, -1869, -1441, -2808, +-841, -3026, 27, -2479, 687, -1203, 1063, 432, +1327, 1934, 1368, 2969, 1057, 3282, 560, 2710, +41, 1449, -503, -101, -1011, -1625, -1316, -2803, +-1305, -3301, -1025, -3010, -573, -2069, 48, -637, +768, 1016, 1364, 2479, 1625, 3402, 1501, 3569, +1054, 2839, 347, 1317, -562, -586, -1447, -2400, +-1955, -3691, -1902, -4040, -1346, -3237, -443, -1532, +662, 603, 1689, 2653, 2193, 4026, 2010, 4231, +1361, 3202, 383, 1313, -820, -901, -1839, -2899, +-2241, -4151, -1963, -4229, -1190, -3113, -92, -1184, +1074, 1019, 1890, 2961, 2062, 4139, 1654, 4250, +858, 3255, -179, 1376, -1241, -896, -1948, -2918, +-2023, -4170, -1518, -4383, -639, -3458, 394, -1548, +1311, 847, 1851, 3007, 1904, 4331, 1445, 4487, +577, 3430, -432, 1395, -1328, -1059, -1937, -3164, +-2060, -4299, -1577, -4242, -698, -3080, 247, -1059, +1108, 1247, 1736, 3023, 1879, 3756, 1503, 3507, +823, 2471, 25, 820, -754, -947, -1338, -2164, +-1584, -2588, -1452, -2412, -1024, -1806, -440, -867, +191, 164, 710, 881, 964, 1164, 958, 1256, +828, 1298, 658, 1132, 395, 730, 26, 306, +-281, -60, -419, -486, -524, -948, -705, -1209, +-860, -1202, -842, -1020, -682, -663, -458, -60, +-70, 612, 534, 1051, 1144, 1212, 1550, 1262, +1671, 1180, 1425, 779, 766, 101, -208, -598, +-1267, -1148, -2127, -1563, -2508, -1755, -2257, -1550, +-1436, -908, -249, 46, 1086, 1105, 2294, 1954, +2998, 2339, 2906, 2194, 2076, 1495, 796, 305, +-725, -1035, -2205, -2039, -3137, -2506, -3175, -2436, +-2434, -1793, -1193, -624, 348, 695, 1868, 1716, +2912, 2307, 3203, 2461, 2717, 2043, 1588, 1076, +98, -84, -1382, -1147, -2481, -2028, -2912, -2545, +-2598, -2409, -1708, -1630, -516, -477, 727, 799, +1779, 1931, 2383, 2607, 2395, 2630, 1888, 1994, +1052, 806, 62, -631, -925, -1844, -1700, -2469, +-2071, -2491, -2006, -1968, -1591, -925, -859, 385, +104, 1495, 1084, 2126, 1871, 2261, 2246, 1907, +2050, 1072, 1348, -49, 342, -1090, -781, -1833, +-1739, -2178, -2238, -2000, -2140, -1252, -1504, -143, +-520, 1007, 568, 1908, 1467, 2300, 1932, 2053, +1860, 1224, 1311, 21, 507, -1230, -311, -2073, +-1054, -2247, -1592, -1812, -1700, -929, -1365, 240, +-798, 1379, -61, 2053, 846, 2029, 1608, 1459, +1820, 681, 1481, -166, 792, -1042, -225, -1692, +-1390, -1811, -2179, -1495, -2224, -1000, -1591, -347, +-463, 505, 978, 1328, 2270, 1852, 2852, 2024, +2503, 1816, 1315, 1152, -405, 97, -2080, -1084, +-3154, -2099, -3356, -2648, -2591, -2567, -963, -1883, +989, -700, 2533, 758, 3292, 2073, 3259, 2865, +2403, 3027, 799, 2544, -1027, 1439, -2420, -56, +-3081, -1522, -3011, -2627, -2236, -3158, -890, -3026, +626, -2241, 1812, -897, 2419, 725, 2469, 2160, +1999, 3059, 1035, 3315, -186, 2848, -1232, 1637, +-1816, -27, -1939, -1568, -1648, -2626, -958, -3106, +-73, -2882, 664, -1898, 1095, -474, 1224, 887, +1025, 1881, 584, 2395, 153, 2369, -138, 1816, +-334, 919, -414, -45, -321, -827, -174, -1336, +-126, -1590, -157, -1596, -214, -1301, -327, -767, +-429, -212, -338, 277, -37, 801, 294, 1312, +585, 1516, 886, 1361, 1064, 1059, 886, 626, +381, -71, -220, -856, -805, -1391, -1318, -1595, +-1556, -1557, -1349, -1258, -753, -597, 88, 309, +1023, 1125, 1772, 1610, 2046, 1800, 1754, 1687, +962, 1127, -173, 164, -1352, -830, -2182, -1518, +-2412, -1868, -1990, -1868, -993, -1368, 344, -399, +1625, 659, 2492, 1428, 2699, 1792, 2125, 1786, +878, 1330, -656, 449, -1994, -507, -2775, -1150, +-2794, -1418, -2018, -1392, -685, -1025, 819, -367, +2121, 281, 2840, 667, 2722, 825, 1837, 800, +461, 594, -1074, 300, -2351, 63, -2934, -51, +-2657, -92, -1696, -131, -333, -201, 1151, -307, +2357, -435, 2882, -507, 2585, -475, 1585, -298, +131, 68, -1398, 550, -2534, 939, -2912, 1062, +-2475, 846, -1432, 311, -60, -401, 1296, -1083, +2235, -1522, 2500, -1509, 2136, -911, 1306, 116, +186, 1203, -931, 1997, -1700, 2245, -2027, 1775, +-1990, 622, -1560, -876, -759, -2219, 133, -2937, +845, -2769, 1385, -1701, 1771, 1, 1807, 1827, +1370, 3162, 616, 3576, -222, 2929, -971, 1390, +-1547, -599, -1904, -2398, -1859, -3456, -1299, -3574, +-468, -2747, 308, -1120, 992, 779, 1623, 2259, +1934, 3042, 1669, 3136, 1056, 2483, 395, 1175, +-367, -289, -1224, -1450, -1833, -2197, -1916, -2473, +-1578, -2183, -1020, -1422, -224, -434, 748, 589, +1499, 1407, 1728, 1824, 1553, 1849, 1178, 1559, +576, 927, -252, 75, -986, -653, -1284, -1099, +-1190, -1331, -968, -1310, -684, -950, -231, -460, +276, -89, 507, 216, 470, 569, 479, 815, +562, 820, 515, 778, 387, 832, 356, 752, +355, 382, 163, -75, -243, -493, -667, -940, +-984, -1333, -1186, -1456, -1219, -1255, -938, -761, +-300, -30, 482, 771, 1161, 1443, 1675, 1904, +1939, 2066, 1753, 1742, 1058, 921, 6, -149, +-1157, -1209, -2141, -2136, -2682, -2727, -2626, -2694, +-1905, -1937, -602, -666, 967, 831, 2378, 2289, +3260, 3320, 3341, 3560, 2511, 2893, 931, 1467, +-1015, -396, -2770, -2234, -3744, -3572, -3640, -4049, +-2603, -3508, -947, -2032, 981, -23, 2665, 1945, +3523, 3418, 3309, 4074, 2214, 3684, 613, 2339, +-1067, 496, -2352, -1346, -2873, -2807, -2554, -3557, +-1613, -3393, -398, -2413, 734, -921, 1488, 725, +1707, 2101, 1443, 2838, 879, 2859, 239, 2302, +-274, 1245, -561, -137, -654, -1382, -626, -2045, +-519, -2123, -413, -1826, -377, -1197, -337, -287, +-208, 602, -28, 1146, 168, 1304, 395, 1214, +624, 988, 720, 646, 559, 241, 181, -132, +-260, -409, -622, -619, -781, -781, -679, -847, +-358, -724, 66, -412, 411, -34, 525, 340, +387, 670, 62, 822, -325, 682, -620, 314, +-711, -117, -519, -457, -42, -580, 566, -416, +1020, -18, 1102, 450, 807, 777, 229, 788, +-523, 472, -1210, -74, -1497, -742, -1278, -1313, +-754, -1463, -107, -1067, 602, -287, 1190, 607, +1383, 1394, 1130, 1875, 644, 1856, 118, 1289, +-420, 345, -879, -692, -1076, -1551, -992, -2004, +-756, -1949, -451, -1431, -102, -610, 259, 330, +555, 1179, 717, 1715, 754, 1846, 699, 1636, +583, 1147, 368, 427, 8, -351, -417, -999, +-792, -1429, -1082, -1607, -1217, -1480, -1071, -1081, +-606, -518, 28, 132, 626, 778, 1130, 1255, +1471, 1423, 1451, 1317, 1001, 1038, 267, 607, +-554, 69, -1268, -409, -1677, -737, -1619, -947, +-1121, -1002, -399, -848, 346, -628, 959, -461, +1289, -230, 1263, 107, 893, 403, 326, 634, +-216, 917, -623, 1207, -862, 1307, -863, 1131, +-633, 719, -311, 54, -60, -849, 48, -1762, +37, -2349, -12, -2391, -3, -1841, 135, -750, +369, 703, 584, 2161, 661, 3161, 544, 3367, +243, 2698, -236, 1325, -809, -423, -1223, -2124, +-1263, -3299, -937, -3587, -366, -2942, 333, -1618, +984, 40, 1309, 1681, 1144, 2861, 615, 3197, +-40, 2707, -677, 1707, -1151, 424, -1222, -942, +-798, -1981, -129, -2319, 483, -2027, 901, -1393, +982, -566, 620, 334, -17, 1005, -651, 1235, +-1096, 1112, -1209, 819, -878, 471, -178, 169, +620, -2, 1255, -57, 1519, -76, 1268, -131, +554, -273, -382, -522, -1246, -754, -1803, -781, +-1893, -557, -1391, -190, -422, 279, 575, 819, +1289, 1190, 1675, 1123, 1644, 660, 1089, 88, +198, -428, -593, -834, -1068, -995, -1292, -753, +-1211, -168, -759, 436, -174, 747, 264, 742, +457, 516, 445, 42, 326, -612, 147, -1093, +-43, -1062, -121, -563, 7, 117, 274, 833, +433, 1523, 358, 1862, 203, 1457, -20, 443, +-499, -643, -1082, -1552, -1323, -2267, -1112, -2418, +-708, -1631, -136, -259, 723, 1033, 1567, 2056, +1892, 2749, 1643, 2711, 1013, 1723, 59, 236, +-1077, -1143, -2006, -2186, -2376, -2773, -2096, -2646, +-1260, -1688, -94, -230, 1077, 1191, 1926, 2209, +2215, 2694, 1857, 2508, 1005, 1560, -27, 114, +-978, -1260, -1652, -2151, -1834, -2469, -1487, -2165, +-850, -1160, -157, 296, 494, 1578, 942, 2219, +999, 2202, 727, 1646, 371, 602, 35, -687, +-297, -1698, -487, -2032, -389, -1726, -136, -1019, +63, -41, 147, 998, 115, 1667, -77, 1679, +-434, 1203, -793, 534, -915, -219, -745, -939, +-362, -1345, 213, -1258, 933, -789, 1579, -180, +1786, 401, 1341, 888, 420, 1167, -670, 1063, +-1755, 583, -2584, 17, -2749, -425, -2050, -811, +-728, -1103, 785, -996, 2182, -434, 3141, 177, +3247, 587, 2368, 908, 803, 1108, -1004, 931, +-2620, 395, -3610, -203, -3638, -678, -2688, -982, +-1085, -1025, 780, -755, 2483, -242, 3518, 391, +3558, 926, 2661, 1125, 1101, 964, -785, 596, +-2501, 61, -3459, -620, -3415, -1157, -2537, -1187, +-1074, -752, 658, -171, 2143, 414, 2892, 983, +2722, 1286, 1800, 1048, 467, 383, -890, -350, +-1908, -915, -2292, -1196, -1940, -1060, -1041, -498, +18, 282, 907, 1001, 1413, 1390, 1427, 1261, +966, 700, 187, -21, -576, -749, -1039, -1352, +-1175, -1537, -1050, -1131, -636, -402, -7, 267, +520, 823, 728, 1301, 797, 1466, 823, 1149, +575, 617, 47, 160, -418, -315, -661, -893, +-858, -1282, -1067, -1285, -994, -1085, -520, -765, +10, -169, 384, 628, 725, 1288, 1015, 1589, +1045, 1517, 744, 1085, 265, 360, -254, -459, +-805, -1133, -1269, -1467, -1433, -1361, -1239, -883, +-763, -246, -118, 354, 564, 792, 1134, 961, +1397, 842, 1270, 578, 862, 325, 261, 122, +-485, -36, -1192, -128, -1587, -179, -1507, -276, +-1049, -453, -416, -625, 283, -673, 928, -543, +1280, -256, 1157, 143, 653, 592, 27, 949, +-588, 1061, -1107, 915, -1245, 583, -848, 126, +-174, -357, 446, -691, 888, -788, 1047, -733, +740, -595, -11, -349, -850, -61, -1385, 129, +-1451, 210, -1073, 277, -346, 390, 581, 527, +1438, 635, 1840, 676, 1554, 638, 727, 477, +-339, 100, -1434, -475, -2248, -1038, -2336, -1388, +-1622, -1472, -496, -1238, 685, -585, 1715, 410, +2297, 1422, 2176, 2128, 1445, 2363, 363, 2056, +-884, 1208, -1974, -64, -2456, -1481, -2258, -2634, +-1628, -3148, -695, -2878, 445, -1902, 1462, -390, +1986, 1370, 1964, 2920, 1612, 3801, 1006, 3755, +112, 2774, -864, 1088, -1555, -915, -1810, -2758, +-1803, -3961, -1658, -4179, -1165, -3359, -271, -1741, +613, 264, 1190, 2213, 1596, 3658, 1885, 4228, +1753, 3770, 1060, 2438, 179, 622, -555, -1239, +-1238, -2795, -1903, -3734, -2253, -3769, -2036, -2865, +-1363, -1370, -558, 244, 238, 1724, 1070, 2896, +1818, 3397, 2209, 2989, 2116, 1967, 1617, 811, +813, -335, -248, -1474, -1408, -2328, -2356, -2559, +-2817, -2245, -2680, -1705, -1974, -1002, -815, -35, +589, 1059, 1882, 1943, 2696, 2442, 2845, 2562, +2294, 2221, 1122, 1301, -365, -41, -1670, -1398, +-2441, -2410, -2582, -2859, -2109, -2621, -1121, -1670, +88, -201, 1058, 1307, 1473, 2299, 1372, 2533, +924, 2133, 271, 1238, -363, -11, -725, -1164, +-700, -1678, -335, -1485, 135, -926, 410, -219, +390, 512, 174, 947, -196, 834, -731, 320, +-1203, -278, -1263, -743, -940, -890, -432, -611, +258, -22, 1023, 670, 1504, 1301, 1512, 1611, +1148, 1348, 560, 616, -201, -251, -1010, -1066, +-1594, -1734, -1804, -2016, -1677, -1706, -1239, -901, +-508, 97, 372, 1036, 1135, 1759, 1560, 2127, +1615, 1998, 1326, 1353, 731, 414, -16, -528, +-738, -1325, -1275, -1869, -1489, -1949, -1387, -1487, +-1067, -723, -593, 52, -54, 776, 404, 1387, +653, 1640, 702, 1413, 682, 923, 663, 436, +607, -32, 471, -533, 247, -917, -81, -995, +-550, -872, -1096, -775, -1497, -668, -1586, -369, +-1356, 65, -809, 451, 52, 785, 1036, 1137, +1790, 1404, 2078, 1372, 1887, 952, 1252, 255, +227, -512, -958, -1230, -1922, -1845, -2451, -2102, +-2523, -1657, -2035, -661, -955, 366, 373, 1253, +1500, 2059, 2222, 2418, 2476, 1923, 2158, 898, +1255, -84, 48, -954, -1082, -1742, -1947, -2065, +-2421, -1688, -2380, -941, -1791, -202, -772, 477, +345, 1083, 1214, 1451, 1729, 1475, 1927, 1231, +1759, 846, 1124, 391, 145, -134, -760, -728, +-1365, -1262, -1772, -1550, -1936, -1529, -1615, -1223, +-804, -611, 138, 283, 878, 1219, 1390, 1852, +1631, 2002, 1389, 1699, 687, 1016, -153, 52, +-872, -937, -1352, -1580, -1464, -1692, -1109, -1383, +-451, -815, 143, -96, 512, 569, 692, 913, +623, 869, 271, 618, -217, 330, -587, 65, +-649, -100, -417, -50, -67, 196, 250, 422, +484, 427, 594, 206, 470, -127, 95, -490, +-331, -831, -660, -1021, -954, -878, -1195, -403, +-1148, 172, -684, 621, -12, 906, 571, 1046, +1010, 954, 1352, 597, 1462, 209, 1128, 13, +398, -105, -444, -339, -1214, -579, -1845, -667, +-2146, -757, -1875, -974, -1090, -1034, -132, -642, +775, 39, 1578, 728, 2098, 1401, 2087, 2015, +1509, 2233, 558, 1786, -484, 810, -1429, -378, +-2145, -1552, -2422, -2511, -2104, -2982, -1287, -2716, +-255, -1691, 756, -200, 1640, 1306, 2179, 2503, +2094, 3219, 1431, 3255, 485, 2450, -506, 989, +-1360, -597, -1876, -1868, -1911, -2677, -1492, -2909, +-788, -2413, 23, -1322, 706, -78, 1071, 931, +1123, 1564, 872, 1796, 350, 1661, -183, 1252, +-472, 726, -531, 288, -470, 54, -300, -105, +-55, -390, 93, -772, 51, -1086, -111, -1298, +-337, -1389, -521, -1180, -513, -554, -372, 311, +-210, 1144, 54, 1769, 407, 2026, 618, 1799, +606, 1156, 545, 292, 474, -575, 194, -1225, +-292, -1534, -719, -1544, -1024, -1335, -1311, -925, +-1404, -392, -1037, 95, -325, 489, 413, 903, +1054, 1338, 1565, 1619, 1743, 1621, 1405, 1353, +670, 805, -183, -42, -976, -1044, -1606, -1913, +-1946, -2390, -1854, -2332, -1314, -1701, -563, -601, +123, 695, 725, 1850, 1253, 2564, 1523, 2639, +1407, 2059, 1030, 1022, 571, -179, 47, -1270, +-575, -1984, -1143, -2114, -1446, -1675, -1495, -894, +-1414, -40, -1197, 698, -714, 1181, 35, 1299, +820, 1023, 1429, 491, 1759, -26, 1720, -339, +1289, -447, 510, -427, -496, -255, -1419, 88, +-1984, 402, -2144, 458, -1857, 315, -1050, 155, +86, -36, 1066, -344, 1549, -641, 1589, -721, +1287, -580, 635, -370, -170, -130, -802, 236, +-1116, 706, -1110, 1069, -824, 1169, -358, 1061, +106, 809, 393, 348, 444, -339, 270, -1064, +-74, -1562, -393, -1701, -524, -1495, -488, -957, +-331, -99, -47, 906, 309, 1731, 589, 2119, +685, 2011, 563, 1473, 237, 590, -188, -469, +-568, -1396, -837, -1908, -968, -1931, -904, -1553, +-652, -879, -285, -20, 123, 815, 477, 1370, +665, 1530, 712, 1373, 722, 1021, 635, 546, +360, 10, -13, -467, -356, -739, -694, -791, +-1071, -755, -1337, -712, -1277, -590, -898, -367, +-349, -153, 292, 42, 978, 349, 1539, 749, +1705, 1043, 1370, 1143, 700, 1076, -133, 784, +-998, 204, -1666, -513, -1942, -1120, -1784, -1507, +-1273, -1635, -513, -1359, 388, -625, 1200, 324, +1667, 1145, 1742, 1699, 1480, 1956, 888, 1777, +15, 1054, -923, -1, -1614, -1012, -1926, -1750, +-1891, -2086, -1432, -1884, -572, -1155, 378, -113, +1155, 973, 1691, 1827, 1892, 2187, 1602, 1973, +839, 1268, -141, 212, -1101, -921, -1895, -1761, +-2247, -2094, -1970, -1896, -1209, -1193, -223, -156, +784, 870, 1623, 1633, 2091, 2048, 2007, 1977, +1349, 1328, 318, 352, -761, -565, -1618, -1311, +-2148, -1864, -2254, -2023, -1776, -1637, -826, -842, +182, 110, 1002, 1045, 1642, 1824, 2004, 2266, +1875, 2178, 1244, 1526, 341, 517, -571, -580, +-1327, -1591, -1854, -2299, -2078, -2412, -1881, -1862, +-1252, -899, -399, 196, 451, 1240, 1226, 1983, +1808, 2178, 1979, 1816, 1659, 1091, 955, 235, +29, -556, -908, -1127, -1665, -1373, -2117, -1261, +-2112, -889, -1538, -458, -518, -64, 569, 302, +1356, 567, 1722, 637, 1641, 586, 1058, 509, +151, 389, -687, 233, -1171, 98, -1278, 0, +-1072, -28, -533, 26, 222, 26, 762, -131, +762, -324, 356, -468, -140, -668, -562, -862, +-875, -746, -939, -256, -578, 345, 67, 898, +663, 1414, 1029, 1716, 1133, 1531, 958, 869, +488, -3, -227, -856, -986, -1555, -1500, -1964, +-1598, -1942, -1321, -1429, -809, -567, -114, 355, +659, 1123, 1242, 1693, 1474, 2007, 1391, 1910, +1027, 1370, 408, 606, -347, -135, -1049, -833, +-1516, -1507, -1625, -1931, -1389, -1887, -904, -1483, +-236, -941, 525, -239, 1143, 677, 1427, 1566, +1405, 2098, 1135, 2228, 582, 2050, -149, 1496, +-821, 480, -1322, -790, -1668, -1911, -1788, -2627, +-1506, -2857, -766, -2502, 224, -1468, 1140, 66, +1799, 1642, 2149, 2828, 2077, 3398, 1389, 3213, +170, 2192, -1100, 546, -2026, -1190, -2542, -2521, +-2549, -3234, -1887, -3246, -723, -2449, 493, -985, +1436, 592, 2010, 1772, 2135, 2478, 1743, 2746, +997, 2437, 194, 1556, -517, 473, -1080, -440, +-1453, -1150, -1633, -1753, -1609, -2136, -1388, -2085, +-1001, -1620, -428, -960, 325, -203, 1141, 725, +1812, 1756, 2147, 2507, 2090, 2645, 1572, 2201, +526, 1360, -796, 173, -1941, -1215, -2654, -2377, +-2864, -2914, -2492, -2762, -1497, -2023, -103, -810, +1228, 625, 2176, 1862, 2654, 2587, 2580, 2721, +1913, 2302, 836, 1400, -310, 211, -1301, -934, +-2070, -1767, -2476, -2191, -2329, -2185, -1674, -1735, +-771, -924, 148, 37, 961, 908, 1570, 1538, +1834, 1864, 1677, 1861, 1211, 1502, 616, 827, +-41, 7, -697, -742, -1183, -1306, -1366, -1641, +-1296, -1663, -1095, -1326, -825, -715, -477, 37, +-60, 812, 384, 1433, 796, 1705, 1074, 1576, +1146, 1112, 1011, 392, 689, -447, 227, -1163, +-283, -1529, -774, -1461, -1144, -1010, -1279, -300, +-1134, 494, -756, 1140, -278, 1419, 196, 1224, +598, 645, 778, -81, 666, -742, 433, -1205, +252, -1313, 132, -936, 8, -180, -71, 637, +-20, 1253, 40, 1548, -80, 1441, -359, 865, +-658, -70, -887, -1024, -991, -1684, -887, -1922, +-492, -1680, 125, -941, 760, 131, 1231, 1215, +1434, 2020, 1356, 2351, 999, 2107, 320, 1337, +-557, 220, -1303, -993, -1721, -1996, -1847, -2527, +-1685, -2498, -1097, -1926, -158, -856, 769, 510, +1445, 1768, 1871, 2589, 1950, 2865, 1537, 2558, +714, 1634, -271, 258, -1182, -1187, -1830, -2316, +-2056, -2891, -1829, -2821, -1257, -2116, -461, -909, +419, 509, 1150, 1765, 1570, 2557, 1663, 2744, +1417, 2340, 855, 1451, 140, 258, -514, -956, +-1010, -1855, -1337, -2258, -1465, -2181, -1346, -1676, +-986, -791, -457, 258, 137, 1129, 696, 1630, +1131, 1790, 1362, 1622, 1317, 1086, 992, 318, +476, -376, -140, -813, -770, -1038, -1291, -1088, +-1563, -907, -1508, -551, -1137, -223, -547, -40, +127, 100, 745, 286, 1179, 432, 1349, 514, +1204, 679, 804, 925, 323, 981, -165, 725, +-666, 305, -1039, -207, -1127, -846, -1005, -1422, +-846, -1623, -618, -1400, -182, -880, 341, -121, +702, 761, 860, 1462, 897, 1728, 792, 1546, +482, 1043, 27, 358, -376, -350, -643, -912, +-829, -1171, -868, -1044, -633, -642, -210, -217, +164, 95, 343, 321, 344, 412, 234, 253, +21, -68, -225, -269, -347, -212, -226, -7, +61, 245, 321, 591, 511, 982, 676, 1134, +683, 849, 325, 250, -297, -436, -869, -1117, +-1239, -1678, -1420, -1870, -1333, -1537, -859, -763, +-74, 227, 738, 1189, 1350, 1899, 1732, 2205, +1834, 2023, 1513, 1352, 727, 376, -310, -592, +-1270, -1367, -1955, -1881, -2310, -2013, -2189, -1692, +-1488, -1061, -419, -304, 652, 498, 1535, 1233, +2171, 1719, 2357, 1836, 1903, 1595, 966, 1064, +-117, 325, -1144, -493, -1958, -1203, -2346, -1604, +-2162, -1594, -1455, -1239, -455, -663, 563, 32, +1402, 692, 1937, 1111, 2037, 1208, 1616, 1053, +785, 721, -170, 269, -1034, -186, -1689, -532, +-1988, -736, -1820, -775, -1227, -636, -385, -381, +497, -76, 1257, 269, 1724, 589, 1753, 739, +1342, 665, 636, 437, -158, 111, -872, -289, +-1404, -632, -1632, -749, -1460, -607, -981, -305, +-398, 57, 155, 419, 634, 678, 999, 703, +1142, 472, 1028, 130, 783, -174, 534, -368, +235, -408, -203, -288, -710, -79, -1096, 125, +-1301, 246, -1381, 193, -1272, -45, -856, -317, +-178, -451, 573, -432, 1245, -289, 1731, 47, +1907, 565, 1663, 1010, 1014, 1130, 114, 932, +-810, 540, -1540, -26, -1958, -738, -2060, -1371, +-1867, -1655, -1351, -1517, -560, -1052, 317, -366, +1102, 462, 1752, 1279, 2241, 1852, 2410, 2024, +2065, 1802, 1246, 1254, 149, 418, -1115, -590, +-2366, -1527, -3241, -2179, -3406, -2429, -2783, -2215, +-1511, -1501, 171, -391, 1899, 865, 3209, 1991, +3758, 2743, 3390, 2923, 2169, 2433, 471, 1357, +-1232, -72, -2579, -1519, -3272, -2619, -3115, -3094, +-2217, -2836, -960, -1884, 270, -452, 1277, 1083, +1906, 2309, 2015, 2930, 1648, 2806, 1039, 1972, +412, 651, -143, -784, -609, -1943, -911, -2530, +-987, -2416, -943, -1673, -878, -523, -756, 718, +-484, 1695, -70, 2121, 337, 1914, 622, 1200, +783, 225, 821, -723, 665, -1385, 354, -1596, +34, -1305, -207, -634, -422, 144, -599, 778, +-616, 1119, -471, 1094, -309, 723, -206, 171, +-66, -336, 150, -674, 313, -794, 323, -673, +256, -364, 184, -11, 64, 256, -132, 410, +-299, 483, -307, 509, -145, 491, 85, 405, +269, 256, 370, 59, 348, -224, 95, -617, +-366, -991, -770, -1160, -925, -1030, -853, -594, +-549, 103, 38, 922, 736, 1626, 1221, 1989, +1357, 1843, 1171, 1150, 635, 75, -215, -1081, +-1093, -2027, -1667, -2512, -1784, -2357, -1458, -1568, +-772, -366, 129, 917, 1026, 1952, 1663, 2500, +1829, 2448, 1473, 1823, 787, 807, -2, -320, +-817, -1269, -1508, -1847, -1800, -1981, -1579, -1706, +-1023, -1146, -334, -440, 403, 281, 1058, 858, +1424, 1191, 1413, 1301, 1078, 1237, 508, 989, +-115, 565, -655, 62, -1052, -401, -1227, -755, +-1091, -956, -711, -987, -270, -837, 136, -493, +503, -52, 787, 298, 884, 490, 786, 610, +542, 658, 201, 520, -193, 244, -559, 24, +-820, -102, -918, -249, -827, -393, -557, -391, +-175, -248, 232, -89, 609, 64, 864, 265, +906, 441, 730, 432, 414, 224, 12, -48, +-421, -312, -771, -576, -967, -733, -1007, -621, +-880, -242, -535, 238, 2, 671, 564, 985, +973, 1106, 1180, 926, 1150, 423, 816, -235, +222, -805, -445, -1162, -1000, -1300, -1336, -1168, +-1369, -711, -1036, -47, -403, 586, 321, 1027, +905, 1242, 1170, 1228, 1099, 976, 784, 507, +278, -56, -324, -545, -763, -871, -848, -1057, +-670, -1081, -414, -858, -118, -438, 222, 11, +420, 415, 350, 762, 121, 942, -73, 872, +-176, 612, -229, 261, -272, -121, -235, -430, +-49, -561, 173, -516, 277, -344, 287, -89, +348, 151, 410, 252, 303, 207, 30, 86, +-260, -99, -564, -320, -891, -455, -1115, -412, +-1076, -216, -697, 66, -22, 389, 792, 707, +1494, 938, 1885, 982, 1843, 782, 1302, 374, +283, -171, -972, -783, -2064, -1352, -2664, -1718, +-2614, -1731, -1902, -1329, -639, -568, 882, 407, +2206, 1425, 2907, 2278, 2822, 2703, 2047, 2498, +811, 1672, -599, 418, -1844, -1007, -2595, -2304, +-2667, -3162, -2102, -3331, -1142, -2718, -62, -1447, +937, 146, 1675, 1664, 1968, 2816, 1798, 3398, +1371, 3234, 862, 2347, 241, 1040, -470, -336, +-1095, -1590, -1502, -2551, -1703, -2995, -1703, -2844, +-1422, -2239, -837, -1356, -44, -260, 789, 965, +1536, 2085, 2064, 2814, 2232, 3053, 1906, 2858, +1145, 2190, 173, 957, -852, -631, -1828, -2093, +-2526, -3122, -2674, -3690, -2255, -3648, -1437, -2732, +-379, -1085, 852, 742, 2007, 2351, 2723, 3612, +2821, 4253, 2401, 3910, 1620, 2606, 504, 803, +-866, -1053, -2126, -2689, -2852, -3797, -2987, -4040, +-2655, -3333, -1866, -1940, -589, -288, 897, 1258, +2108, 2445, 2797, 3057, 2986, 2954, 2663, 2237, +1756, 1232, 396, 212, -1042, -719, -2153, -1428, +-2749, -1747, -2819, -1700, -2333, -1466, -1304, -1124, +-19, -655, 1076, -118, 1761, 357, 2068, 726, +1976, 1018, 1433, 1212, 638, 1231, -75, 1029, +-562, 643, -879, 178, -1045, -278, -1024, -703, +-865, -1034, -709, -1138, -576, -968, -334, -635, +34, -263, 362, 116, 578, 466, 752, 676, +846, 683, 739, 550, 449, 379, 163, 211, +-38, 55, -204, -55, -347, -94, -416, -85, +-426, -88, -476, -142, -609, -240, -731, -354, +-665, -451, -407, -507, -60, -485, 338, -347, +820, -71, 1254, 310, 1397, 703, 1179, 1008, +726, 1147, 121, 1059, -621, 718, -1298, 141, +-1673, -558, -1646, -1170, -1293, -1523, -724, -1563, +-65, -1288, 592, -714, 1137, 34, 1435, 733, +1430, 1220, 1188, 1448, 817, 1409, 333, 1123, +-207, 685, -706, 197, -1103, -287, -1355, -721, +-1403, -1061, -1250, -1272, -918, -1316, -391, -1153, +294, -772, 975, -195, 1476, 513, 1743, 1188, +1718, 1612, 1320, 1673, 573, 1385, -362, 776, +-1278, -72, -1937, -924, -2136, -1506, -1846, -1680, +-1167, -1451, -199, -891, 883, -123, 1727, 639, +2032, 1164, 1802, 1319, 1215, 1122, 365, 670, +-611, 78, -1392, -495, -1672, -853, -1471, -887, +-982, -661, -337, -300, 357, 112, 906, 479, +1124, 653, 1029, 561, 735, 290, 348, -26, +-84, -312, -493, -517, -812, -556, -929, -401, +-818, -135, -548, 122, -170, 306, 251, 402, +606, 393, 758, 283, 734, 135, 610, 24, +398, -19, 71, -23, -242, -27, -434, -52, +-526, -121, -557, -262, -549, -439, -519, -548, +-471, -513, -345, -331, -124, -31, 173, 355, +518, 733, 909, 957, 1200, 941, 1201, 695, +894, 280, 361, -209, -326, -639, -1064, -910, +-1634, -975, -1825, -819, -1566, -500, -948, -134, +-127, 199, 721, 468, 1445, 632, 1872, 653, +1808, 559, 1272, 403, 520, 199, -242, -51, +-941, -292, -1427, -427, -1476, -404, -1083, -271, +-540, -104, -81, 80, 274, 247, 501, 262, +487, 20, 263, -352, 42, -618, 1, -691, +135, -571, 346, -193, 587, 451, 795, 1138, +854, 1526, 598, 1447, -11, 975, -793, 212, +-1434, -752, -1782, -1647, -1807, -2074, -1408, -1874, +-552, -1233, 529, -344, 1464, 684, 2081, 1591, +2315, 2007, 2097, 1825, 1359, 1247, 252, 491, +-921, -331, -1857, -1079, -2373, -1522, -2384, -1526, +-1862, -1192, -928, -717, 152, -185, 1087, 391, +1763, 891, 2083, 1130, 1942, 1105, 1350, 957, +527, 696, -290, 245, -991, -287, -1495, -683, +-1652, -895, -1397, -998, -895, -974, -311, -750, +278, -382, 793, -3, 1072, 327, 1017, 621, +739, 867, 431, 1017, 170, 1022, -67, 848, +-269, 502, -366, 38, -328, -483, -267, -1007, +-301, -1408, -399, -1507, -486, -1226, -509, -670, +-404, 15, -112, 724, 338, 1314, 766, 1587, +992, 1453, 978, 997, 747, 361, 314, -314, +-227, -885, -706, -1218, -1011, -1254, -1073, -1025, +-856, -608, -392, -86, 140, 423, 579, 767, +852, 874, 868, 793, 579, 559, 137, 177, +-224, -235, -448, -476, -524, -493, -430, -396, +-183, -222, 72, 44, 230, 273, 264, 287, +205, 107, 102, -109, -10, -281, -100, -389, +-162, -365, -133, -174, -55, 111, 5, 381, +19, 538, 33, 531, 31, 391, 0, 179, +-18, -63, -2, -271, 39, -364, 74, -351, +114, -326, 129, -305, 97, -216, 33, -98, +-27, -62, -115, -56, -256, 71, -387, 269, +-388, 358, -220, 340, 14, 353, 245, 373, +465, 256, 625, 31, 620, -147, 415, -239, +92, -318, -248, -405, -552, -452, -758, -417, +-772, -317, -556, -203, -174, -83, 234, 106, +539, 359, 718, 557, 752, 626, 556, 595, +156, 474, -261, 233, -540, -82, -667, -368, +-607, -554, -301, -602, 160, -505, 542, -322, +701, -147, 606, -18, 250, 71, -245, 101, +-681, 61, -884, 36, -776, 126, -346, 316, +250, 500, 762, 596, 1012, 577, 946, 403, +603, 39, 82, -448, -424, -879, -767, -1107, +-835, -1078, -652, -787, -342, -268, -53, 352, +189, 859, 340, 1106, 319, 1094, 207, 867, +186, 440, 294, -88, 359, -492, 336, -653, +277, -667, 164, -623, -121, -481, -508, -262, +-785, -117, -848, -93, -722, -75, -439, 29, +15, 203, 555, 398, 985, 597, 1133, 767, +1022, 839, 741, 731, 308, 392, -268, -121, +-854, -663, -1245, -1116, -1349, -1404, -1182, -1433, +-731, -1134, -40, -535, 690, 235, 1262, 998, +1562, 1564, 1535, 1800, 1152, 1655, 453, 1124, +-385, 280, -1125, -650, -1583, -1381, -1641, -1763, +-1297, -1770, -667, -1367, 78, -588, 773, 312, +1287, 1005, 1480, 1364, 1306, 1426, 865, 1187, +316, 643, -272, -31, -806, -558, -1143, -822, +-1185, -917, -948, -901, -571, -712, -143, -364, +306, -21, 739, 212, 974, 415, 917, 676, +686, 892, 483, 881, 241, 657, -150, 366, +-499, 2, -611, -535, -601, -1112, -668, -1406, +-679, -1294, -469, -924, -126, -374, 157, 390, +409, 1212, 711, 1746, 973, 1794, 1003, 1403, +724, 681, 247, -262, -255, -1208, -675, -1893, +-976, -2122, -1019, -1793, -698, -954, -137, 149, +379, 1186, 687, 1919, 773, 2205, 616, 1919, +209, 1053, -319, -131, -733, -1238, -855, -1976, +-640, -2189, -161, -1802, 455, -901, 1064, 237, +1456, 1294, 1433, 1994, 963, 2102, 187, 1562, +-724, 589, -1603, -483, -2189, -1416, -2211, -2014, +-1638, -2063, -659, -1487, 546, -492, 1807, 580, +2758, 1461, 3000, 1996, 2419, 2056, 1264, 1581, +-143, 677, -1529, -388, -2580, -1305, -2977, -1857, +-2603, -1969, -1631, -1650, -364, -948, 861, -28, +1802, 824, 2259, 1346, 2157, 1469, 1596, 1275, +838, 855, 95, 292, -566, -238, -1078, -528, +-1310, -526, -1192, -376, -885, -244, -523, -176, +-176, -186, 125, -326, 311, -567, 377, -744, +369, -698, 345, -400, 368, 89, 448, 665, +548, 1184, 608, 1490, 629, 1485, 514, 1142, +125, 512, -497, -279, -1065, -1037, -1380, -1582, +-1440, -1809, -1226, -1690, -651, -1242, 212, -539, +1051, 281, 1590, 1014, 1762, 1477, 1588, 1611, +1069, 1455, 277, 1044, -569, 439, -1180, -171, +-1390, -610, -1269, -865, -963, -981, -524, -931, +13, -729, 499, -522, 746, -395, 748, -232, +640, 44, 461, 315, 202, 524, -43, 757, +-146, 981, -101, 997, -3, 733, 60, 319, +88, -138, 83, -609, 5, -1007, -175, -1175, +-442, -1039, -634, -676, -622, -224, -410, 235, +-78, 632, 354, 875, 785, 894, 1015, 708, +944, 392, 659, 16, 282, -350, -190, -622, +-654, -726, -899, -647, -782, -394, -455, -12, +-128, 403, 121, 721, 314, 826, 382, 671, +225, 288, -34, -229, -172, -771, -100, -1191, +69, -1312, 279, -1019, 538, -402, 801, 323, +859, 1013, 568, 1582, 31, 1827, -545, 1562, +-1047, 872, -1410, 33, -1464, -783, -1095, -1511, +-419, -1986, 323, -2003, 987, -1563, 1487, -864, +1704, -60, 1553, 772, 1080, 1490, 433, 1905, +-229, 1930, -780, 1612, -1144, 1022, -1281, 247, +-1194, -563, -958, -1234, -656, -1635, -309, -1717, +89, -1512, 465, -1065, 738, -461, 935, 145, +1085, 643, 1133, 1016, 1043, 1249, 835, 1280, +482, 1099, -45, 797, -653, 438, -1186, -2, +-1541, -505, -1669, -936, -1495, -1186, -1038, -1249, +-366, -1143, 444, -864, 1229, -422, 1788, 116, +2021, 630, 1952, 1017, 1537, 1247, 784, 1319, +-130, 1185, -921, 797, -1501, 224, -1894, -388, +-2042, -945, -1829, -1393, -1253, -1621, -500, -1504, +279, -1060, 1057, -421, 1831, 310, 2369, 1034, +2456, 1575, 2088, 1765, 1382, 1594, 361, 1143, +-916, 452, -2116, -415, -2850, -1252, -2955, -1807, +-2489, -1974, -1504, -1761, -128, -1160, 1327, -202, +2431, 892, 2917, 1784, 2771, 2223, 2095, 2126, +1034, 1520, -168, 491, -1203, -732, -1873, -1784, +-2126, -2326, -1990, -2239, -1513, -1606, -790, -603, +23, 543, 760, 1536, 1312, 2093, 1630, 2091, +1670, 1602, 1387, 788, 834, -172, 154, -1053, +-517, -1652, -1078, -1887, -1384, -1747, -1343, -1246, +-1032, -495, -567, 308, -25, 1006, 512, 1533, +910, 1794, 1130, 1675, 1204, 1191, 1100, 506, +768, -233, 263, -955, -297, -1555, -859, -1879, +-1331, -1815, -1572, -1395, -1436, -739, -926, 50, +-146, 900, 750, 1662, 1592, 2095, 2139, 2056, +2133, 1607, 1530, 868, 537, -103, -552, -1171, +-1570, -2025, -2265, -2379, -2337, -2195, -1713, -1583, +-668, -628, 475, 522, 1498, 1551, 2159, 2146, +2234, 2213, 1689, 1814, 754, 1033, -277, 22, +-1137, -920, -1662, -1526, -1739, -1740, -1349, -1617, +-615, -1180, 184, -515, 801, 155, 1168, 642, +1263, 925, 1041, 1053, 547, 1016, 22, 804, +-329, 492, -478, 168, -487, -149, -389, -457, +-239, -732, -134, -920, -114, -951, -139, -793, +-167, -478, -165, -78, -71, 355, 147, 755, +437, 1007, 710, 1015, 886, 795, 865, 425, +595, -30, 139, -507, -370, -879, -823, -1027, +-1112, -949, -1123, -712, -846, -343, -379, 120, +172, 568, 714, 874, 1069, 978, 1116, 907, +912, 684, 595, 309, 194, -178, -269, -641, +-660, -955, -840, -1100, -787, -1096, -572, -888, +-222, -440, 196, 137, 583, 665, 793, 1063, +752, 1307, 495, 1314, 151, 1005, -205, 448, +-538, -176, -726, -733, -655, -1170, -328, -1404, +105, -1340, 519, -993, 797, -490, 831, 44, +582, 541, 176, 938, -236, 1163, -538, 1175, +-664, 976, -613, 621, -397, 182, -71, -286, +290, -726, 560, -1054, 660, -1189, 586, -1118, +400, -854, 144, -413, -131, 139, -343, 661, +-442, 1043, -429, 1258, -313, 1253, -99, 938, +134, 360, 275, -269, 301, -811, 281, -1240, +233, -1467, 146, -1335, 70, -838, 46, -178, +42, 447, 31, 961, 9, 1311, -23, 1373, +-70, 1083, -143, 557, -221, -5, -244, -483, +-160, -846, 5, -1069, 192, -1092, 360, -893, +498, -560, 537, -205, 428, 143, 224, 489, +-7, 768, -251, 894, -507, 848, -666, 648, +-660, 302, -498, -114, -226, -480, 178, -709, +651, -759, 1005, -606, 1111, -286, 976, 72, +661, 336, 189, 428, -377, 324, -931, 58, +-1284, -253, -1322, -483, -1033, -549, -505, -392, +167, -28, 864, 406, 1368, 740, 1499, 887, +1262, 812, 808, 481, 235, -53, -357, -603, +-833, -975, -1040, -1081, -962, -922, -697, -542, +-346, -45, -14, 432, 224, 749, 369, 813, +459, 636, 480, 317, 457, -11, 443, -263, +437, -392, 372, -383, 232, -252, 64, -77, +-128, 36, -354, 33, -535, -54, -601, -145, +-561, -184, -423, -153, -194, -47, 75, 154, +346, 400, 621, 544, 868, 493, 1001, 285, +917, -22, 581, -398, 57, -749, -511, -930, +-984, -873, -1275, -604, -1286, -183, -924, 304, +-237, 735, 516, 1003, 1146, 1062, 1560, 910, +1634, 588, 1250, 165, 529, -282, -239, -687, +-859, -983, -1290, -1124, -1465, -1111, -1249, -960, +-730, -657, -107, -205, 458, 325, 922, 827, +1218, 1216, 1258, 1435, 1054, 1430, 734, 1147, +376, 598, -37, -110, -484, -828, -886, -1421, +-1108, -1792, -1114, -1853, -932, -1542, -604, -911, +-120, -104, 458, 726, 987, 1454, 1334, 1935, +1451, 2027, 1320, 1682, 893, 977, 249, 66, +-424, -870, -983, -1640, -1354, -2050, -1428, -1994, +-1161, -1505, -658, -708, -93, 214, 451, 1024, +939, 1516, 1254, 1606, 1288, 1322, 1082, 769, +783, 113, 450, -465, 38, -816, -444, -892, +-832, -748, -1011, -493, -1059, -221, -1030, -6, +-800, 90, -299, 50, 316, -50, 847, -87, +1242, -6, 1492, 160, 1465, 352, 1060, 520, +358, 596, -405, 497, -1040, 199, -1443, -211, +-1525, -594, -1170, -854, -422, -927, 420, -757, +1092, -368, 1489, 88, 1545, 473, 1141, 739, +363, 840, -474, 709, -1072, 389, -1350, 36, +-1263, -244, -761, -461, 1, -603, 714, -611, +1141, -500, 1260, -353, 1109, -212, 726, -41, +176, 167, -333, 370, -627, 524, -686, 606, +-603, 587, -463, 436, -277, 171, -85, -169, +39, -520, 98, -791, 179, -898, 299, -816, +439, -576, 549, -222, 612, 192, 609, 584, +489, 857, 248, 949, -54, 856, -348, 612, +-578, 244, -664, -202, -570, -632, -354, -937, +-134, -1056, 63, -978, 253, -733, 383, -366, +401, 59, 375, 456, 379, 734, 395, 857, +384, 848, 336, 739, 265, 544, 163, 281, +-5, -27, -251, -352, -465, -666, -553, -939, +-517, -1118, -420, -1137, -259, -935, -12, -513, +232, 49, 399, 628, 535, 1115, 692, 1409, +783, 1411, 761, 1119, 626, 614, 404, 0, +75, -612, -355, -1076, -795, -1304, -1111, -1327, +-1191, -1176, -997, -831, -561, -328, 34, 184, +709, 603, 1251, 925, 1498, 1123, 1451, 1104, +1188, 849, 718, 458, 108, 46, -467, -328, +-878, -618, -1119, -767, -1215, -765, -1113, -657, +-828, -511, -428, -355, 27, -197, 533, -43, +1045, 110, 1454, 289, 1620, 489, 1483, 647, +1077, 687, 433, 577, -352, 331, -1085, -18, +-1547, -403, -1629, -719, -1346, -857, -783, -761, +-45, -457, 673, -47, 1145, 350, 1269, 634, +1118, 729, 830, 590, 480, 239, 140, -207, +-93, -592, -178, -806, -218, -822, -292, -632, +-380, -250, -446, 226, -491, 645, -468, 888, +-299, 911, 27, 722, 415, 371, 737, -77, +915, -516, 880, -826, 638, -921, 268, -803, +-100, -541, -357, -217, -447, 110, -412, 367, +-291, 471, -96, 393, 84, 205, 141, 41, +53, -28, -48, -18, -66, 36, -9, 153, +106, 302, 322, 358, 588, 224, 776, -49, +780, -337, 570, -571, 213, -747, -199, -823, +-590, -716, -899, -424, -998, -48, -815, 285, +-400, 544, 85, 752, 550, 899, 944, 906, +1153, 720, 1089, 405, 800, 43, 413, -363, +7, -815, -358, -1208, -621, -1393, -729, -1304, +-691, -954, -519, -375, -250, 346, 57, 1049, +367, 1564, 663, 1773, 864, 1602, 858, 1036, +647, 185, 291, -749, -127, -1550, -514, -2032, +-739, -2069, -726, -1636, -489, -803, -105, 242, +343, 1213, 735, 1844, 932, 2018, 898, 1748, +678, 1079, 337, 141, -72, -787, -444, -1403, +-666, -1608, -676, -1475, -556, -1088, -387, -518, +-160, 79, 142, 500, 462, 662, 697, 642, +828, 562, 894, 465, 874, 361, 657, 284, +249, 265, -233, 237, -655, 104, -985, -173, +-1176, -527, -1095, -846, -657, -1043, 22, -1051, +715, -811, 1270, -327, 1604, 278, 1654, 833, +1317, 1200, 625, 1276, -190, 1003, -876, 454, +-1356, -180, -1602, -720, -1506, -1058, -999, -1110, +-239, -852, 479, -380, 1057, 122, 1520, 491, +1790, 661, 1693, 627, 1231, 413, 586, 73, +-86, -274, -767, -491, -1395, -524, -1752, -426, +-1671, -255, -1204, -38, -537, 191, 235, 372, +1037, 450, 1680, 414, 1914, 291, 1728, 122, +1280, -81, 635, -299, -172, -490, -930, -609, +-1370, -625, -1429, -525, -1176, -324, -668, -78, +23, 181, 661, 445, 1033, 669, 1103, 752, +934, 651, 585, 446, 153, 211, -218, -82, +-390, -446, -335, -752, -154, -870, 67, -824, +243, -700, 318, -491, 247, -169, 72, 197, +-111, 480, -203, 644, -188, 708, -71, 674, +139, 546, 356, 350, 505, 117, 553, -126, +501, -341, 327, -503, 69, -626, -183, -728, +-334, -765, -406, -674, -422, -453, -335, -169, +-127, 131, 138, 458, 383, 790, 575, 1003, +703, 979, 762, 748, 679, 418, 466, 39, +200, -402, -52, -829, -291, -1094, -538, -1138, +-721, -1014, -732, -779, -577, -419, -334, 52, +1, 538, 418, 927, 840, 1161, 1128, 1203, +1206, 1034, 1083, 656, 798, 112, 366, -498, +-153, -1024, -643, -1341, -993, -1390, -1129, -1175, +-1047, -751, -735, -202, -231, 365, 341, 831, +831, 1099, 1182, 1120, 1337, 932, 1229, 629, +848, 261, 304, -169, -217, -600, -630, -897, +-887, -987, -906, -922, -642, -754, -204, -455, +248, -15, 579, 443, 755, 735, 740, 793, +509, 693, 168, 488, -111, 161, -246, -226, +-260, -512, -170, -592, 11, -514, 271, -360, +492, -162, 567, 50, 486, 203, 315, 232, +89, 154, -178, 36, -403, -65, -470, -129, +-368, -151, -224, -125, -63, -50, 157, 43, +423, 108, 632, 112, 734, 58, 738, -27, +656, -117, 458, -182, 147, -195, -192, -156, +-482, -83, -664, 15, -722, 114, -619, 154, +-333, 97, 82, -26, 488, -146, 814, -230, +992, -277, 947, -254, 704, -114, 380, 116, +62, 320, -247, 392, -489, 325, -550, 157, +-416, -98, -238, -410, -75, -652, 91, -683, +239, -473, 328, -113, 368, 295, 402, 657, +448, 844, 484, 752, 459, 394, 363, -112, +194, -630, -21, -1016, -270, -1141, -514, -956, +-648, -530, -576, 5, -300, 533, 129, 940, +606, 1111, 983, 1001, 1159, 697, 1063, 312, +699, -90, 143, -472, -456, -785, -901, -977, +-1024, -1024, -845, -941, -475, -752, 15, -467, +547, -92, 973, 346, 1110, 763, 970, 1062, +713, 1192, 423, 1145, 57, 903, -335, 471, +-623, -81, -707, -643, -628, -1108, -483, -1401, +-244, -1473, 154, -1297, 622, -862, 937, -243, +1019, 407, 937, 939, 743, 1282, 356, 1385, +-190, 1197, -649, 741, -829, 165, -756, -368, +-521, -790, -172, -1063, 238, -1125, 594, -960, +757, -657, 732, -317, 600, 37, 421, 394, +218, 684, 51, 844, -26, 875, -31, 782, +-50, 521, -108, 87, -156, -413, -225, -848, +-299, -1133, -260, -1246, -46, -1136, 221, -743, +448, -124, 643, 502, 786, 958, 755, 1235, +504, 1345, 173, 1201, -124, 755, -367, 154, +-517, -402, -493, -860, -280, -1248, 39, -1491, +304, -1452, 448, -1115, 497, -616, 468, -67, +342, 507, 122, 1051, -93, 1411, -179, 1460, +-111, 1218, 37, 794, 229, 282, 408, -260, +497, -752, 425, -1102, 186, -1255, -131, -1227, +-384, -1071, -484, -807, -415, -429, -177, 39, +202, 532, 655, 974, 994, 1290, 1058, 1411, +832, 1269, 425, 842, -79, 186, -590, -558, +-967, -1219, -1054, -1636, -807, -1707, -359, -1420, +159, -829, 663, -68, 1069, 669, 1262, 1201, +1186, 1440, 888, 1372, 502, 1033, 100, 499, +-310, -95, -661, -609, -838, -961, -799, -1135, +-621, -1123, -382, -934, -87, -611, 258, -200, +536, 236, 702, 607, 795, 836, 829, 921, +762, 877, 582, 672, 340, 311, 87, -108, +-163, -480, -383, -759, -491, -928, -473, -947, +-371, -794, -237, -504, -50, -132, 206, 260, +446, 597, 552, 800, 521, 825, 431, 670, +292, 367, 107, -17, -58, -393, -81, -648, +37, -702, 182, -571, 269, -334, 309, -56, +282, 194, 172, 323, 12, 266, -140, 74, +-216, -122, -183, -246, -41, -292, 130, -246, +247, -74, 285, 154, 293, 302, 247, 325, +129, 285, 12, 202, -14, 41, 55, -161, +156, -311, 236, -384, 284, -428, 317, -441, +293, -370, 197, -206, 68, 1, 2, 220, +27, 435, 66, 584, 44, 582, -10, 401, +-58, 91, -118, -281, -191, -631, -241, -864, +-170, -893, 45, -692, 339, -297, 619, 201, +851, 680, 1000, 1014, 997, 1109, 754, 920, +281, 471, -283, -137, -809, -760, -1192, -1251, +-1341, -1497, -1173, -1418, -659, -1011, 110, -350, +889, 418, 1464, 1111, 1742, 1564, 1704, 1674, +1333, 1430, 654, 880, -166, 118, -885, -693, +-1332, -1358, -1459, -1738, -1258, -1781, -785, -1493, +-122, -912, 576, -152, 1126, 618, 1416, 1230, +1427, 1568, 1187, 1577, 730, 1267, 139, 718, +-451, 38, -868, -631, -1042, -1134, -978, -1351, +-697, -1279, -225, -983, 345, -540, 850, -39, +1131, 406, 1145, 696, 941, 802, 540, 750, +22, 569, -468, 300, -767, 2, -804, -265, +-606, -465, -281, -577, 102, -595, 480, -515, +755, -330, 835, -69, 714, 193, 521, 395, +332, 509, 112, 510, -143, 370, -314, 113, +-384, -179, -415, -419, -425, -567, -344, -607, +-132, -501, 155, -261, 458, 0, 727, 188, +896, 314, 893, 388, 720, 354, 388, 195, +-19, 26, -387, -62, -618, -113, -654, -172, +-518, -169, -290, -53, -14, 75, 276, 96, +475, 16, 524, -103, 471, -268, 415, -507, +335, -727, 211, -757, 125, -527, 145, -94, +173, 447, 127, 1000, 53, 1414, -28, 1493, +-133, 1129, -254, 389, -313, -528, -268, -1386, +-146, -1953, 14, -2046, 228, -1611, 458, -769, +638, 253, 719, 1194, 683, 1795, 553, 1884, +334, 1470, 51, 732, -224, -113, -422, -864, +-572, -1338, -680, -1403, -679, -1093, -484, -569, +-114, -7, 308, 446, 714, 678, 1073, 640, +1288, 400, 1242, 88, 933, -171, 433, -296, +-136, -257, -692, -90, -1124, 119, -1304, 260, +-1162, 265, -753, 110, -186, -162, 423, -434, +935, -583, 1251, -556, 1311, -380, 1139, -103, +779, 210, 332, 458, -68, 542, -344, 453, +-533, 268, -644, 75, -652, -87, -557, -213, +-384, -293, -182, -319, 51, -316, 326, -339, +613, -373, 811, -345, 866, -210, 786, -3, +606, 228, 315, 452, -62, 608, -392, 608, +-563, 428, -568, 141, -452, -165, -251, -449, +-20, -665, 208, -732, 367, -627, 430, -419, +430, -186, 431, 66, 439, 326, 397, 531, +278, 622, 125, 596, -37, 475, -226, 241, +-390, -95, -463, -457, -392, -734, -169, -845, +142, -766, 410, -521, 572, -154, 629, 255, +580, 586, 398, 733, 122, 673, -90, 463, +-176, 165, -177, -144, -125, -381, -23, -488, +71, -472, 99, -383, 39, -270, -62, -156, +-109, -55, -53, 20, 106, 79, 314, 123, +498, 167, 587, 204, 531, 205, 309, 138, +10, 28, -270, -71, -450, -136, -468, -169, +-316, -156, -32, -78, 298, 23, 565, 64, +672, 7, 598, -112, 351, -250, 33, -370, +-248, -421, -420, -351, -458, -157, -363, 113, +-158, 389, 113, 590, 377, 658, 558, 567, +639, 329, 599, -4, 456, -339, 235, -599, +-5, -756, -204, -796, -319, -679, -357, -411, +-311, -69, -173, 262, 4, 534, 160, 702, +240, 708, 252, 540, 225, 246, 182, -98, +153, -418, 180, -623, 233, -642, 271, -491, +273, -249, 226, 18, 130, 258, -7, 387, +-145, 344, -225, 172, -201, -17, -107, -168, +16, -283, 116, -323, 179, -231, 179, -55, +100, 85, 0, 139, -28, 152, 41, 129, +169, 33, 334, -100, 481, -186, 548, -180, +458, -124, 225, -43, -73, 69, -351, 195, +-529, 264, -536, 214, -379, 59, -131, -145, +140, -356, 349, -541, 447, -620, 431, -520, +374, -246, 307, 112, 215, 466, 127, 747, +122, 867, 155, 745, 114, 398, -2, -64, +-130, -522, -232, -880, -324, -1043, -364, -938, +-274, -612, -23, -173, 277, 274, 496, 638, +596, 824, 618, 787, 560, 573, 364, 263, +56, -53, -227, -303, -395, -462, -485, -540, +-498, -540, -388, -461, -123, -348, 205, -248, +462, -131, 616, 51, 698, 273, 682, 473, +515, 611, 222, 663, -102, 584, -361, 350, +-543, -10, -630, -420, -588, -777, -404, -986, +-116, -1004, 230, -827, 559, -472, 796, 6, +892, 489, 824, 854, 601, 1046, 246, 1046, +-131, 843, -431, 442, -614, -66, -701, -549, +-669, -906, -481, -1107, -159, -1116, 204, -887, +498, -459, 694, 33, 786, 462, 749, 771, +570, 919, 307, 869, 26, 634, -221, 309, +-417, -22, -525, -315, -514, -531, -388, -636, +-183, -642, 46, -590, 252, -483, 401, -315, +496, -93, 511, 146, 453, 380, 343, 585, +208, 708, 63, 677, -84, 487, -227, 196, +-343, -140, -399, -476, -373, -736, -240, -823, +-31, -718, 223, -491, 469, -215, 642, 87, +691, 362, 603, 523, 372, 533, 38, 454, +-304, 346, -562, 190, -666, -6, -591, -165, +-326, -235, 54, -267, 410, -300, 620, -307, +660, -273, 548, -245, 335, -247, 82, -231, +-135, -151, -229, -26, -169, 127, -34, 312, +67, 504, 116, 633, 111, 629, 29, 481, +-149, 198, -315, -185, -340, -590, -220, -912, +-19, -1054, 233, -979, 516, -706, 746, -276, +829, 244, 707, 742, 445, 1090, 106, 1202, +-261, 1060, -622, 683, -870, 138, -913, -450, +-754, -943, -452, -1243, -47, -1288, 414, -1046, +807, -559, 1037, 37, 1069, 573, 926, 944, +625, 1096, 224, 997, -196, 664, -537, 215, +-742, -199, -807, -500, -728, -684, -515, -743, +-199, -676, 131, -537, 407, -387, 592, -232, +691, -26, 682, 238, 566, 518, 366, 753, +125, 876, -108, 825, -308, 561, -443, 108, +-455, -421, -322, -860, -109, -1082, 122, -1030, +317, -732, 442, -272, 436, 192, 289, 498, +76, 559, -130, 408, -287, 155, -333, -71, +-227, -154, -26, -50, 206, 214, 389, 510, +468, 699, 432, 664, 307, 377, 106, -107, +-130, -655, -308, -1123, -353, -1390, -289, -1369, +-175, -1054, -4, -512, 198, 132, 347, 764, +380, 1268, 331, 1562, 239, 1587, 120, 1334, +-32, 833, -177, 164, -256, -557, -243, -1191, +-152, -1612, -19, -1749, 138, -1568, 271, -1096, +328, -427, 287, 278, 208, 883, 128, 1285, +53, 1424, 3, 1289, -5, 932, -8, 458, +-59, -29, -149, -450, -243, -761, -281, -916, +-237, -905, -82, -751, 163, -524, 442, -266, +670, 11, 748, 275, 604, 448, 270, 494, +-164, 454, -601, 362, -902, 211, -942, 16, +-647, -134, -99, -185, 520, -155, 1013, -92, +1252, -18, 1148, 38, 694, 23, 18, -77, +-659, -218, -1113, -335, -1222, -389, -973, -345, +-464, -180, 159, 72, 721, 307, 1068, 453, +1077, 495, 792, 425, 381, 244, -26, 11, +-377, -179, -598, -283, -580, -325, -344, -332, +-61, -303, 127, -253, 247, -215, 317, -191, +292, -126, 157, 16, 7, 212, -82, 396, +-132, 527, -181, 574, -195, 484, -112, 240, +45, -94, 231, -414, 392, -663, 498, -792, +497, -747, 367, -525, 136, -212, -117, 106, +-333, 390, -465, 599, -477, 673, -394, 601, +-241, 447, -43, 256, 169, 34, 331, -205, +422, -383, 449, -464, 430, -478, 348, -465, +212, -409, 72, -299, -73, -175, -222, -64, +-337, 39, -372, 177, -327, 345, -197, 517, +4, 634, 221, 670, 369, 591, 419, 361, +382, -28, 255, -508, 62, -940, -123, -1204, +-233, -1201, -265, -903, -221, -337, -118, 363, +27, 1007, 174, 1403, 284, 1441, 316, 1091, +264, 423, 158, -377, 35, -1065, -80, -1441, +-170, -1415, -200, -1005, -166, -345, -80, 371, +12, 932, 95, 1187, 160, 1085, 198, 701, +189, 187, 130, -298, 48, -616, -28, -696, +-61, -554, -41, -302, 29, -62, 107, 77, +156, 87, 137, -22, 62, -184, -47, -295, +-148, -265, -210, -83, -205, 198, -102, 492, +75, 704, 260, 752, 374, 596, 390, 273, +302, -131, 144, -507, -55, -750, -228, -806, +-303, -681, -270, -425, -175, -125, -67, 126, +44, 257, 133, 255, 174, 168, 163, 59, +168, -7, 205, 28, 241, 183, 247, 394, +222, 562, 130, 616, -51, 514, -276, 229, +-464, -195, -531, -645, -451, -1001, -232, -1165, +70, -1086, 390, -761, 640, -265, 740, 282, +656, 757, 435, 1064, 142, 1134, -162, 962, +-404, 612, -534, 184, -524, -235, -405, -570, +-240, -740, -94, -730, 18, -593, 102, -404, +177, -193, 243, 11, 333, 169, 458, 252, +575, 280, 625, 305, 554, 328, 352, 323, +21, 243, -390, 100, -805, -92, -1106, -317, +-1190, -543, -1014, -675, -604, -630, -8, -400, +674, -37, 1264, 391, 1602, 794, 1615, 1026, +1317, 1003, 735, 722, -11, 267, -747, -284, +-1309, -797, -1598, -1125, -1560, -1189, -1224, -1025, +-669, -699, 8, -259, 660, 197, 1153, 576, +1406, 812, 1415, 930, 1168, 931, 704, 809, +132, 568, -410, 263, -844, -65, -1095, -398, +-1110, -696, -896, -893, -513, -928, -74, -806, +329, -559, 649, -246, 873, 91, 927, 388, +784, 590, 505, 669, 175, 633, -192, 504, +-572, 307, -852, 78, -942, -155, -831, -349, +-544, -464, -85, -460, 477, -329, 1008, -95, +1342, 184, 1353, 418, 1003, 519, 381, 428, +-360, 137, -1051, -276, -1511, -682, -1588, -952, +-1235, -981, -583, -721, 183, -203, 894, 436, +1406, 1013, 1569, 1374, 1330, 1418, 784, 1117, +130, 535, -464, -179, -904, -848, -1099, -1323, +-1005, -1506, -670, -1357, -246, -915, 150, -298, +448, 338, 624, 867, 640, 1184, 505, 1218, +280, 965, 46, 513, -136, -3, -252, -451, +-288, -737, -244, -816, -128, -680, -6, -392, +90, -68, 149, 162, 186, 269, 195, 274, +170, 202, 137, 86, 90, 7, -9, 34, +-153, 114, -265, 163, -312, 137, -299, 63, +-218, -72, -31, -247, 217, -380, 421, -370, +515, -214, 507, 10, 396, 227, 159, 373, +-161, 385, -455, 226, -605, -30, -590, -274, +-419, -398, -108, -372, 277, -185, 590, 107, +723, 390, 669, 532, 459, 475, 113, 250, +-298, -86, -633, -431, -808, -672, -798, -696, +-599, -512, -212, -188, 273, 166, 730, 472, +1036, 644, 1088, 626, 864, 450, 439, 201, +-94, -33, -624, -219, -984, -327, -1067, -340, +-886, -284, -539, -230, -84, -199, 380, -182, +713, -151, 824, -91, 718, 11, 461, 163, +135, 319, -161, 430, -347, 452, -369, 367, +-255, 171, -82, -84, 60, -310, 137, -436, +133, -445, 68, -345, -13, -152, -72, 73, +-99, 234, -81, 272, -6, 208, 62, 90, +62, -51, 0, -179, -63, -236, -138, -188, +-199, -62, -165, 77, 18, 183, 286, 242, +521, 246, 654, 190, 649, 87, 474, -26, +107, -114, -354, -166, -754, -190, -965, -189, +-967, -169, -763, -133, -368, -93, 128, -49, +556, 2, 809, 61, 895, 123, 834, 169, +651, 187, 374, 171, 85, 135, -161, 79, +-342, 13, -498, -56, -633, -101, -694, -120, +-634, -129, -471, -136, -252, -140, 38, -124, +368, -92, 647, -34, 787, 39, 782, 130, +644, 205, 399, 240, 85, 203, -236, 96, +-493, -48, -638, -179, -659, -243, -578, -228, +-407, -132, -187, 2, 44, 139, 262, 207, +455, 180, 561, 58, 543, -99, 436, -222, +288, -255, 104, -177, -100, -6, -250, 227, +-307, 422, -291, 493, -263, 393, -234, 173, +-203, -125, -181, -439, -197, -694, -213, -787, +-147, -676, 29, -410, 281, -55, 560, 332, +814, 710, 941, 971, 846, 1035, 501, 882, +-18, 564, -592, 121, -1095, -393, -1406, -866, +-1422, -1164, -1110, -1201, -541, -990, 156, -589, +821, -77, 1337, 443, 1592, 821, 1519, 970, +1131, 888, 539, 643, -137, 318, -772, 9, +-1255, -199, -1480, -275, -1392, -248, -1036, -177, +-505, -117, 90, -122, 654, -212, 1058, -341, +1218, -436, 1112, -447, 804, -360, 375, -170, +-86, 104, -483, 396, -737, 618, -813, 728, +-727, 720, -528, 589, -284, 349, -30, 50, +192, -251, 362, -521, 452, -720, 463, -793, +416, -718, 340, -512, 223, -209, 63, 148, +-84, 480, -183, 692, -256, 730, -358, 606, +-443, 366, -453, 50, -389, -257, -277, -459, +-97, -492, 160, -384, 440, -205, 659, -10, +747, 156, 689, 250, 501, 224, 211, 107, +-173, -32, -558, -117, -807, -145, -852, -109, +-734, -22, -477, 98, -103, 198, 272, 222, +501, 158, 541, 21, 458, -131, 314, -266, +166, -336, 49, -323, 16, -196, 76, 16, +158, 258, 158, 441, 60, 513, -105, 465, +-342, 284, -616, -7, -803, -341, -783, -591, +-562, -698, -167, -625, 340, -389, 839, -12, +1159, 396, 1206, 707, 961, 828, 476, 724, +-129, 420, -708, -17, -1119, -443, -1258, -741, +-1074, -825, -645, -692, -103, -361, 437, 68, +861, 450, 1021, 655, 874, 646, 518, 468, +77, 182, -342, -129, -637, -363, -695, -427, +-515, -327, -196, -132, 121, 61, 360, 200, +477, 246, 425, 180, 187, 25, -133, -144, +-377, -237, -494, -222, -492, -121, -335, 18, +-20, 168, 296, 277, 468, 277, 474, 151, +372, -35, 175, -202, -65, -311, -240, -332, +-280, -229, -205, -13, -90, 236, 12, 429, +57, 512, 21, 456, -118, 258, -300, -41, +-424, -358, -403, -598, -222, -695, 93, -620, +478, -387, 805, -48, 943, 304, 820, 572, +457, 691, -68, 631, -621, 419, -1063, 121, +-1266, -169, -1179, -376, -813, -451, -259, -390, +351, -214, 882, 7, 1208, 177, 1261, 240, +1033, 189, 595, 61, 45, -106, -494, -254, +-905, -322, -1083, -257, -1023, -98, -772, 97, +-386, 276, 51, 396, 414, 414, 610, 315, +650, 151, 568, -32, 382, -185, 125, -289, +-93, -302, -214, -244, -255, -150, -239, -59, +-163, 28, -52, 92, 31, 104, 45, 83, +-2, 56, -64, 44, -140, 13, -228, -23, +-302, -43, -291, -22, -184, -1, -19, 12, +178, 45, 398, 115, 579, 180, 626, 185, +520, 145, 291, 70, -16, -33, -357, -182, +-641, -325, -802, -412, -796, -401, -632, -302, +-357, -133, -38, 85, 267, 304, 504, 471, +623, 531, 633, 482, 557, 333, 408, 126, +197, -89, -17, -246, -207, -331, -373, -350, +-503, -299, -559, -198, -537, -108, -454, -76, +-321, -68, -148, -46, 63, -12, 272, 24, +440, 92, 533, 203, 552, 316, 471, 377, +282, 366, 38, 295, -192, 179, -390, 35, +-545, -118, -588, -255, -498, -358, -327, -421, +-123, -446, 119, -431, 344, -365, 460, -232, +421, -32, 278, 210, 97, 446, -87, 624, +-239, 701, -319, 652, -287, 467, -186, 181, +-86, -133, -4, -396, 92, -563, 159, -624, +144, -584, 75, -457, 14, -267, -34, -64, +-97, 123, -147, 295, -151, 444, -101, 538, +-39, 527, 12, 405, 48, 190, 89, -61, +96, -306, 25, -478, -98, -508, -200, -364, +-247, -107, -240, 152, -157, 335, 11, 376, +229, 257, 394, 11, 439, -245, 356, -410, +172, -406, -90, -235, -370, 54, -566, 358, +-604, 560, -504, 590, -333, 436, -95, 155, +165, -182, 354, -455, 424, -599, 424, -581, +370, -446, 250, -236, 84, -1, -68, 218, +-186, 379, -287, 462, -355, 481, -377, 436, +-341, 335, -255, 165, -123, -42, 24, -261, +160, -433, 231, -528, 217, -518, 136, -397, +36, -190, -36, 49, -46, 248, 9, 375, +84, 399, 143, 343, 142, 223, 68, 82, +-89, -40, -275, -107, -426, -121, -498, -107, +-459, -77, -287, -41, -16, -11, 249, -18, +429, -55, 483, -92, 412, -102, 226, -85, +-10, -42, -206, 30, -295, 128, -280, 220, +-193, 252, -80, 205, 12, 98, 54, -47, +21, -203, -71, -320, -190, -344, -285, -259, +-318, -92, -249, 109, -83, 296, 156, 413, +407, 428, 572, 348, 574, 194, 399, -1, +96, -186, -269, -319, -595, -395, -785, -432, +-769, -426, -567, -356, -233, -223, 158, -48, +513, 163, 724, 403, 722, 623, 524, 738, +189, 698, -184, 506, -503, 186, -670, -197, +-660, -559, -506, -782, -269, -803, 1, -625, +241, -314, 403, 36, 471, 322, 437, 459, +305, 424, 106, 258, -108, 54, -315, -112, +-466, -164, -508, -83, -417, 104, -240, 294, +-22, 403, 199, 376, 363, 215, 407, -45, +307, -329, 107, -522, -131, -557, -333, -419, +-456, -186, -457, 75, -323, 279, -86, 358, +151, 264, 322, 52, 412, -168, 405, -302, +297, -291, 126, -129, -56, 159, -232, 466, +-365, 690, -442, 725, -470, 550, -461, 193, +-392, -239, -257, -625, -80, -865, 132, -891, +369, -704, 575, -363, 675, 10, 648, 319, +474, 491, 170, 525, -192, 435, -515, 286, +-741, 148, -813, 78, -706, 94, -474, 155, +-206, 198, 38, 163, 225, 43, 315, -157, +321, -393, 277, -594, 245, -662, 249, -553, +286, -291, 292, 54, 231, 398, 102, 647, +-118, 716, -419, 577, -706, 278, -853, -84, +-827, -403, -638, -577, -301, -552, 139, -337, +556, -2, 838, 350, 923, 614, 799, 712, +506, 605, 116, 311, -284, -81, -621, -468, +-810, -761, -825, -895, -688, -823, -449, -560, +-145, -182, 159, 213, 392, 555, 503, 786, +479, 861, 362, 759, 205, 530, 44, 262, +-105, 8, -201, -206, -226, -364, -204, -438, +-183, -445, -171, -430, -170, -429, -180, -418, +-212, -371, -242, -272, -208, -110, -84, 119, +90, 398, 239, 660, 344, 839, 404, 862, +390, 709, 254, 389, 35, -24, -180, -437, +-354, -752, -487, -887, -558, -792, -505, -493, +-320, -109, -71, 255, 143, 502, 300, 571, +397, 417, 392, 114, 249, -213, 29, -440, +-172, -504, -307, -377, -377, -76, -358, 302, +-210, 635, 17, 810, 217, 797, 307, 585, +289, 230, 170, -173, -29, -517, -252, -747, +-399, -832, -426, -775, -359, -602, -222, -351, +-44, -81, 137, 184, 261, 412, 314, 590, +292, 680, 211, 675, 82, 579, -72, 418, +-222, 206, -338, -35, -393, -249, -390, -397, +-320, -466, -175, -479, 16, -438, 192, -349, +324, -224, 383, -92, 356, 35, 237, 155, +57, 262, -129, 334, -276, 353, -355, 322, +-372, 252, -339, 159, -287, 51, -237, -49, +-216, -126, -192, -171, -117, -193, 28, -196, +220, -182, 437, -144, 625, -70, 702, 32, +615, 134, 358, 216, -16, 270, -441, 261, +-817, 170, -1054, 18, -1080, -138, -887, -255, +-521, -314, -74, -305, 356, -226, 685, -99, +845, 29, 817, 126, 629, 191, 360, 245, +91, 300, -121, 355, -285, 388, -385, 378, +-408, 291, -383, 108, -380, -166, -408, -472, +-417, -722, -385, -838, -312, -778, -176, -544, +64, -172, 364, 244, 637, 605, 781, 831, +747, 896, 535, 797, 176, 576, -268, 291, +-690, -4, -949, -273, -970, -506, -760, -671, +-385, -747, 77, -710, 498, -561, 746, -288, +740, 75, 521, 452, 187, 740, -151, 865, +-416, 798, -558, 544, -537, 158, -393, -268, +-214, -593, -75, -740, 28, -681, 99, -457, +137, -120, 157, 224, 191, 476, 234, 575, +255, 508, 232, 314, 137, 58, -32, -171, +-244, -321, -440, -354, -578, -278, -607, -113, +-510, 69, -310, 205, -63, 251, 174, 204, +354, 85, 458, -72, 483, -212, 420, -279, +293, -237, 133, -107, -32, 75, -212, 249, +-375, 378, -469, 422, -482, 357, -445, 195, +-356, -17, -213, -220, -58, -373, 72, -442, +166, -415, 236, -291, 272, -108, 281, 96, +258, 276, 196, 387, 107, 402, 10, 327, +-102, 189, -224, 20, -318, -132, -368, -219, +-371, -221, -332, -165, -254, -82, -162, -4, +-76, 44, 0, 42, 82, 12, 166, -8, +244, 22, 313, 106, 358, 213, 358, 294, +282, 295, 118, 187, -116, -38, -366, -323, +-588, -577, -721, -690, -725, -599, -581, -300, +-321, 129, -7, 573, 290, 909, 515, 1025, +627, 870, 600, 486, 463, -5, 254, -474, +30, -807, -172, -933, -317, -823, -399, -538, +-433, -190, -429, 123, -400, 350, -361, 464, +-308, 454, -212, 368, -66, 270, 119, 214, +315, 192, 491, 190, 601, 178, 603, 133, +471, 21, 214, -159, -126, -362, -480, -529, +-770, -606, -918, -568, -867, -400, -632, -129, +-269, 197, 138, 487, 504, 679, 728, 727, +762, 626, 630, 398, 374, 105, 47, -170, +-276, -371, -507, -463, -598, -442, -541, -315, +-388, -139, -194, 32, -13, 149, 114, 203, +145, 180, 86, 89, 4, -33, -44, -137, +-57, -183, -58, -156, -21, -48, 58, 106, +149, 282, 205, 423, 206, 478, 159, 408, +73, 230, -56, -6, -223, -242, -393, -421, +-507, -491, -541, -432, -520, -284, -424, -107, +-225, 29, 58, 90, 356, 67, 604, 1, +748, -42, 738, 1, 555, 162, 236, 414, +-145, 678, -493, 838, -727, 800, -817, 531, +-755, 72, -557, -485, -271, -994, 12, -1304, +229, -1311, 347, -1008, 365, -485, 312, 112, +232, 650, 160, 1022, 102, 1156, 67, 1055, +36, 796, -7, 482, -77, 172, -164, -96, +-269, -312, -379, -475, -463, -606, -488, -711, +-434, -755, -293, -691, -73, -495, 187, -180, +447, 230, 651, 651, 743, 976, 673, 1093, +442, 971, 72, 626, -370, 118, -789, -447, +-1074, -912, -1143, -1143, -965, -1090, -564, -762, +-26, -229, 530, 395, 959, 933, 1161, 1239, +1082, 1233, 751, 927, 254, 388, -279, -256, +-718, -833, -965, -1183, -982, -1218, -796, -948, +-478, -447, -128, 141, 164, 662, 334, 973, +367, 1016, 290, 795, 170, 400, 70, -47, +29, -416, 58, -610, 135, -596, 206, -399, +211, -109, 125, 189, -62, 402, -305, 481, +-525, 401, -644, 212, -640, -21, -506, -234, +-260, -376, 35, -411, 300, -332, 471, -176, +522, 13, 452, 179, 296, 288, 107, 309, +-57, 252, -166, 144, -217, 41, -240, -13, +-262, -1, -293, 67, -328, 158, -343, 228, +-318, 219, -220, 103, -52, -110, 149, -350, +330, -542, 448, -610, 467, -507, 372, -228, +183, 156, -51, 531, -276, 783, -450, 827, +-532, 646, -508, 279, -406, -163, -268, -544, +-113, -743, 40, -710, 172, -451, 274, -52, +359, 360, 412, 661, 391, 765, 276, 650, +88, 350, -142, -41, -377, -400, -551, -627, +-625, -683, -583, -575, -435, -337, -206, -30, +44, 250, 258, 435, 396, 514, 437, 503, +380, 417, 251, 284, 99, 147, -46, 26, +-160, -77, -246, -172, -296, -249, -304, -303, +-272, -322, -213, -302, -143, -233, -67, -109, +-3, 51, 33, 209, 30, 326, 12, 386, +-2, 377, -1, 306, 16, 187, 63, 52, +128, -74, 172, -170, 144, -227, 36, -242, +-119, -219, -283, -163, -408, -71, -457, 36, +-397, 140, -241, 210, -28, 246, 179, 231, +330, 159, 388, 49, 349, -52, 222, -114, +41, -126, -133, -81, -258, -1, -325, 76, +-345, 109, -311, 88, -242, 12, -171, -84, +-105, -160, -25, -167, 55, -87, 116, 60, +166, 228, 191, 364, 180, 419, 139, 349, +87, 174, 18, -67, -54, -300, -117, -465, +-185, -514, -275, -437, -359, -243, -396, 23, +-368, 290, -276, 503, -123, 619, 81, 607, +284, 457, 422, 217, 444, -69, 357, -342, +181, -539, -48, -600, -271, -517, -416, -324, +-443, -63, -358, 205, -209, 410, -61, 501, +56, 476, 112, 359, 99, 207, 26, 61, +-54, -38, -90, -80, -74, -86, -32, -87, +20, -111, 68, -165, 77, -240, 23, -306, +-81, -328, -183, -266, -250, -112, -256, 114, +-203, 360, -85, 575, 68, 700, 206, 690, +274, 538, 245, 270, 141, -59, -18, -386, +-204, -632, -369, -741, -443, -690, -409, -494, +-287, -190, -115, 139, 84, 399, 251, 531, +320, 532, 281, 413, 165, 220, 13, 29, +-150, -90, -273, -100, -312, -32, -260, 73, +-158, 159, -36, 168, 83, 80, 172, -70, +191, -230, 136, -342, 40, -353, -68, -244, +-176, -46, -281, 166, -350, 324, -355, 367, +-300, 292, -214, 128, -99, -61, 45, -206, +200, -247, 330, -165, 409, 8, 423, 213, +349, 377, 186, 449, -39, 393, -275, 227, +-474, 0, -590, -220, -604, -378, -520, -437, +-360, -399, -158, -291, 39, -148, 184, -7, +266, 106, 298, 173, 301, 217, 282, 260, +260, 320, 235, 376, 191, 412, 95, 391, +-69, 292, -277, 96, -496, -176, -685, -459, +-788, -676, -742, -751, -529, -644, -184, -351, +221, 69, 604, 515, 877, 859, 959, 1015, +809, 922, 459, 581, 0, 79, -465, -447, +-846, -854, -1061, -1046, -1031, -965, -768, -629, +-362, -123, 64, 406, 435, 827, 674, 1043, +723, 1007, 585, 738, 336, 321, 62, -125, +-178, -490, -333, -688, -377, -696, -326, -539, +-240, -282, -176, -4, -166, 215, -206, 328, +-274, 331, -316, 250, -287, 121, -171, -2, +18, -72, 245, -68, 465, 1, 617, 109, +641, 229, 500, 317, 229, 336, -111, 265, +-457, 114, -744, -90, -898, -300, -873, -460, +-692, -522, -411, -458, -73, -270, 275, 2, +549, 274, 683, 472, 663, 550, 523, 495, +296, 324, 31, 102, -213, -84, -379, -175, +-444, -158, -422, -59, -344, 69, -250, 142, +-163, 105, -120, -43, -136, -247, -178, -433, +-188, -509, -137, -417, -23, -152, 154, 224, +365, 601, 535, 864, 587, 929, 499, 771, +273, 418, -68, -37, -465, -479, -799, -794, +-981, -917, -973, -832, -769, -571, -394, -209, +80, 161, 537, 467, 863, 666, 982, 724, +878, 653, 573, 484, 140, 267, -327, 37, +-715, -166, -934, -304, -946, -359, -763, -341, +-438, -268, -58, -156, 279, -36, 495, 62, +553, 123, 473, 154, 291, 151, 71, 130, +-119, 101, -234, 75, -273, 52, -250, 31, +-191, 12, -134, -5, -109, -11, -118, -7, +-141, 14, -168, 52, -181, 106, -147, 153, +-62, 177, 36, 167, 133, 129, 215, 62, +256, -22, 231, -107, 149, -185, 34, -241, +-113, -264, -273, -242, -408, -188, -478, -99, +-473, 32, -384, 196, -219, 349, -11, 456, +194, 501, 348, 477, 413, 369, 384, 189, +270, -11, 88, -189, -116, -317, -285, -379, +-371, -371, -378, -316, -323, -239, -230, -162, +-131, -92, -70, -30, -57, 40, -53, 143, +-20, 280, 35, 428, 89, 541, 141, 578, +179, 514, 171, 344, 94, 83, -32, -216, +-171, -464, -285, -591, -339, -585, -311, -465, +-203, -260, -56, -25, 74, 177, 139, 306, +126, 368, 47, 379, -69, 358, -188, 317, +-270, 259, -286, 165, -225, 19, -98, -157, +62, -326, 196, -434, 262, -431, 262, -287, +205, -27, 100, 285, -50, 547, -205, 665, +-324, 584, -399, 323, -430, -37, -391, -388, +-276, -618, -126, -652, 11, -484, 117, -189, +198, 136, 236, 388, 228, 502, 185, 467, +121, 340, 42, 188, -36, 67, -108, 17, +-173, 33, -221, 64, -257, 50, -278, -22, +-282, -152, -259, -299, -220, -411, -164, -425, +-87, -326, 4, -125, 94, 133, 178, 383, +266, 565, 332, 638, 330, 604, 240, 471, +85, 266, -128, 22, -384, -221, -615, -438, +-725, -597, -669, -668, -462, -626, -144, -460, +221, -177, 530, 181, 672, 536, 615, 812, +384, 935, 40, 878, -329, 637, -598, 267, +-680, -150, -562, -514, -311, -742, -13, -797, +244, -698, 381, -498, 354, -236, 182, 36, +-42, 259, -226, 408, -330, 508, -343, 572, +-253, 593, -98, 559, 40, 462, 93, 300, +68, 77, 14, -187, -52, -453, -107, -654, +-111, -740, -40, -681, 60, -491, 122, -195, +104, 153, 18, 472, -119, 684, -277, 755, +-405, 678, -444, 465, -367, 175, -202, -116, +4, -329, 206, -433, 363, -409, 420, -266, +357, -48, 201, 166, 8, 313, -187, 341, +-350, 239, -446, 38, -461, -198, -406, -394, +-303, -480, -151, -394, 30, -145, 190, 197, +288, 531, 315, 764, 269, 813, 149, 639, +-31, 278, -220, -169, -363, -581, -432, -838, +-407, -850, -281, -616, -71, -207, 161, 256, +334, 644, 386, 843, 304, 808, 113, 551, +-137, 160, -393, -238, -576, -518, -610, -604, +-481, -503, -230, -257, 77, 48, 361, 311, +528, 435, 519, 408, 342, 261, 69, 62, +-218, -117, -446, -208, -555, -183, -519, -68, +-347, 86, -94, 213, 156, 261, 312, 198, +333, 59, 230, -104, 37, -235, -186, -288, +-359, -231, -425, -74, -376, 132, -233, 315, +-28, 415, 185, 411, 329, 304, 360, 124, +276, -88, 96, -267, -144, -373, -371, -386, +-513, -317, -533, -179, -428, -4, -219, 169, +45, 315, 294, 410, 450, 445, 456, 405, +318, 304, 88, 163, -169, 5, -397, -152, +-533, -272, -535, -325, -418, -315, -231, -259, +-19, -174, 172, -67, 291, 31, 308, 104, +243, 156, 138, 198, 17, 230, -101, 256, +-188, 270, -227, 263, -244, 224, -256, 147, +-243, 38, -189, -85, -118, -192, -58, -259, +6, -265, 72, -208, 113, -100, 104, 24, +66, 128, 25, 184, -17, 182, -69, 127, +-118, 35, -136, -52, -133, -103, -137, -95, +-150, -18, -140, 109, -98, 238, -55, 326, +-39, 350, -23, 297, 5, 156, 5, -33, +-32, -208, -66, -327, -65, -360, -51, -303, +-42, -169, -17, -4, 24, 146, 33, 240, +-12, 261, -95, 211, -179, 127, -245, 46, +-275, -7, -234, -20, -110, 1, 47, 50, +164, 91, 210, 103, 189, 72, 103, 14, +-40, -41, -189, -63, -276, -44, -275, 10, +-209, 88, -108, 162, 7, 191, 84, 145, +75, 30, -15, -132, -125, -284, -209, -374, +-243, -359, -208, -226, -91, 8, 66, 291, +199, 540, 269, 678, 261, 658, 166, 495, +-11, 226, -219, -84, -390, -354, -483, -513, +-480, -541, -372, -453, -189, -298, 25, -129, +226, 6, 370, 91, 422, 147, 361, 194, +191, 254, -48, 334, -287, 422, -471, 476, +-550, 451, -502, 318, -326, 92, -70, -180, +179, -429, 354, -594, 421, -632, 360, -521, +166, -292, -100, -4, -343, 268, -472, 473, +-461, 567, -330, 543, -121, 425, 92, 251, +229, 54, 244, -123, 146, -239, -24, -284, +-202, -265, -320, -197, -319, -90, -197, 26, +-3, 118, 186, 165, 302, 166, 301, 134, +179, 93, -31, 61, -260, 50, -424, 59, +-481, 75, -426, 79, -280, 48, -77, -19, +105, -106, 207, -177, 213, -204, 157, -166, +70, -67, -16, 75, -61, 227, -51, 345, +-11, 392, 20, 362, 22, 276, -26, 151, +-116, 1, -234, -152, -341, -279, -396, -375, +-369, -434, -255, -438, -81, -360, 101, -191, +247, 52, 335, 337, 344, 604, 275, 787, +144, 814, -7, 666, -149, 362, -256, -34, +-318, -431, -329, -728, -304, -853, -250, -782, +-174, -541, -97, -195, -28, 176, 34, 483, +87, 666, 112, 696, 110, 594, 96, 394, +81, 155, 58, -68, 29, -228, -10, -313, +-71, -330, -140, -287, -205, -203, -266, -105, +-314, -18, -314, 61, -245, 125, -116, 169, +38, 192, 186, 206, 296, 208, 329, 185, +256, 139, 94, 73, -104, -11, -282, -102, +-399, -170, -429, -199, -353, -175, -193, -103, +-10, 6, 143, 121, 232, 216, 236, 265, +156, 238, 22, 145, -116, 22, -204, -96, +-227, -185, -191, -207, -113, -145, -18, -16, +44, 128, 47, 244, 1, 294, -69, 255, +-157, 131, -242, -41, -263, -204, -192, -304, +-57, -292, 91, -163, 229, 41, 323, 252, +331, 415, 229, 473, 46, 390, -165, 176, +-368, -97, -529, -342, -609, -493, -560, -500, +-380, -360, -125, -112, 139, 176, 379, 427, +544, 565, 584, 556, 477, 411, 264, 181, +-5, -73, -288, -286, -521, -406, -631, -409, +-593, -299, -443, -114, -218, 93, 28, 264, +234, 364, 342, 371, 328, 279, 217, 109, +59, -90, -108, -265, -240, -363, -288, -350, +-243, -226, -128, -18, 1, 214, 109, 420, +173, 528, 176, 492, 102, 317, -28, 65, +-163, -197, -262, -401, -312, -480, -310, -406, +-243, -201, -130, 52, -17, 274, 69, 393, +136, 379, 178, 240, 177, 35, 124, -166, +45, -286, -35, -276, -108, -144, -169, 56, +-207, 250, -208, 370, -183, 364, -140, 238, +-87, 37, -14, -165, 57, -300, 90, -309, +75, -184, 36, 18, -10, 224, -63, 361, +-119, 374, -157, 240, -159, -1, -142, -273, +-109, -479, -63, -550, -11, -443, 25, -174, +46, 178, 68, 519, 91, 762, 99, 839, +75, 710, 26, 402, -47, -4, -144, -400, +-251, -700, -331, -835, -358, -775, -312, -533, +-214, -181, -83, 182, 76, 470, 234, 630, +341, 642, 359, 519, 307, 315, 202, 101, +55, -65, -122, -162, -277, -183, -382, -152, +-439, -120, -446, -124, -393, -163, -271, -208, +-99, -227, 85, -190, 252, -76, 380, 115, +430, 336, 377, 516, 224, 589, 17, 527, +-196, 325, -376, 24, -480, -294, -471, -540, +-355, -647, -178, -583, 13, -365, 167, -51, +259, 273, 260, 515, 182, 619, 67, 563, +-42, 372, -132, 101, -192, -172, -204, -364, +-175, -430, -128, -367, -91, -205, -53, 6, +-13, 201, 18, 322, 35, 338, 44, 265, +46, 125, 36, -32, 10, -154, -30, -211, +-74, -193, -114, -108, -146, 17, -162, 136, +-155, 213, -128, 228, -88, 183, -46, 86, +-3, -30, 37, -141, 68, -217, 90, -233, +98, -179, 83, -66, 38, 76, -22, 222, +-80, 343, -128, 407, -167, 378, -185, 261, +-182, 75, -170, -139, -155, -338, -133, -472, +-95, -505, -34, -430, 43, -247, 130, 9, +217, 279, 278, 496, 271, 614, 182, 603, +25, 464, -179, 224, -379, -60, -511, -319, +-517, -483, -388, -514, -166, -411, 88, -212, +315, 28, 449, 244, 431, 363, 262, 356, +5, 240, -248, 66, -428, -108, -485, -220, +-384, -232, -158, -139, 90, 29, 276, 211, +362, 345, 329, 380, 184, 302, -37, 139, +-250, -60, -381, -245, -397, -363, -309, -382, +-150, -304, 28, -160, 161, 4, 193, 151, +127, 250, 23, 291, -79, 274, -153, 216, +-173, 142, -114, 71, 14, 5, 149, -53, +222, -93, 213, -113, 121, -114, -47, -95, +-245, -53, -401, 2, -456, 53, -403, 93, +-255, 113, -38, 94, 197, 44, 363, -14, +403, -55, 323, -69, 151, -56, -65, -22, +-264, 26, -387, 72, -391, 94, -277, 89, +-94, 69, 103, 55, 259, 58, 331, 77, +290, 107, 141, 129, -66, 115, -273, 45, +-438, -72, -516, -205, -467, -318, -301, -366, +-63, -313, 184, -159, 389, 61, 507, 288, +507, 468, 381, 544, 164, 486, -88, 304, +-323, 55, -494, -186, -564, -365, -510, -432, +-360, -375, -158, -218, 59, -13, 250, 181, +367, 305, 388, 329, 315, 254, 175, 108, +5, -62, -171, -213, -307, -300, -363, -298, +-338, -200, -246, -35, -95, 150, 78, 309, +216, 404, 264, 417, 212, 337, 98, 176, +-45, -22, -181, -206, -259, -336, -243, -388, +-151, -360, -20, -256, 95, -111, 156, 45, +138, 178, 41, 262, -104, 291, -244, 277, +-316, 229, -293, 158, -184, 77, -7, -7, +197, -79, 347, -131, 393, -159, 337, -164, +200, -140, 3, -87, -212, -17, -395, 49, +-495, 97, -497, 123, -424, 126, -284, 111, +-99, 80, 105, 49, 286, 26, 410, 15, +461, 12, 433, 3, 305, -21, 101, -56, +-117, -85, -302, -96, -417, -80, -453, -32, +-411, 48, -300, 137, -142, 204, 4, 217, +114, 166, 178, 56, 192, -79, 161, -205, +101, -283, 55, -273, 36, -167, 19, 8, +-12, 192, -41, 334, -75, 388, -114, 334, +-148, 185, -161, -6, -144, -175, -107, -271, +-68, -269, -23, -179, 11, -47, 23, 64, +17, 111, -7, 81, -18, -12, -14, -127, +-4, -190, 11, -155, 39, -14, 71, 198, +86, 416, 75, 561, 31, 570, -37, 420, +-130, 130, -228, -224, -294, -549, -305, -756, +-250, -791, -132, -636, 21, -333, 188, 38, +320, 391, 369, 661, 320, 787, 179, 739, +-18, 544, -220, 261, -364, -47, -403, -331, +-324, -526, -168, -590, 13, -520, 171, -347, +249, -119, 217, 112, 94, 299, -67, 396, +-205, 386, -277, 289, -258, 142, -132, -12, +51, -135, 210, -187, 294, -170, 279, -115, +172, -50, -2, 7, -196, 46, -332, 57, +-363, 49, -300, 52, -168, 77, 3, 106, +163, 122, 247, 111, 221, 65, 105, -18, +-32, -125, -144, -218, -202, -262, -181, -233, +-83, -129, 63, 22, 185, 177, 223, 297, +171, 349, 46, 319, -135, 219, -311, 80, +-407, -61, -381, -170, -244, -226, -45, -231, +168, -204, 341, -157, 414, -93, 355, -21, +192, 48, -24, 110, -223, 164, -352, 202, +-384, 211, -305, 179, -154, 114, 4, 32, +125, -42, 186, -84, 171, -87, 90, -57, +-22, -9, -107, 29, -135, 25, -119, -29, +-72, -122, 10, -218, 96, -270, 144, -241, +132, -121, 67, 71, -22, 296, -126, 490, +-219, 583, -263, 536, -241, 360, -170, 95, +-77, -194, 21, -444, 117, -595, 196, -615, +226, -512, 202, -311, 142, -62, 70, 180, +-4, 373, -87, 495, -177, 529, -235, 471, +-265, 339, -267, 160, -224, -39, -134, -224, +-14, -358, 110, -417, 214, -391, 280, -286, +286, -132, 212, 27, 77, 161, -80, 244, +-205, 265, -263, 234, -254, 173, -186, 106, +-72, 45, 37, -2, 100, -37, 105, -66, +47, -97, -52, -124, -143, -133, -177, -118, +-130, -79, -25, -17, 100, 58, 216, 122, +274, 146, 247, 130, 137, 83, -35, 25, +-210, -24, -336, -53, -382, -46, -335, -15, +-204, 21, -35, 42, 120, 36, 219, 4, +242, -40, 202, -78, 117, -91, 16, -64, +-47, -8, -57, 56, -26, 113, 16, 150, +34, 144, 19, 96, -38, 29, -140, -39, +-253, -102, -329, -150, -339, -172, -263, -162, +-98, -120, 108, -50, 312, 40, 457, 143, +509, 241, 454, 308, 287, 319, 45, 256, +-210, 120, -426, -61, -548, -241, -555, -370, +-463, -414, -291, -359, -77, -216, 129, -26, +288, 153, 375, 264, 375, 288, 304, 238, +182, 141, 46, 43, -57, -8, -120, 11, +-141, 80, -134, 152, -117, 179, -93, 129, +-83, -2, -108, -181, -147, -352, -171, -458, +-161, -452, -125, -323, -71, -103, 20, 139, +142, 334, 250, 437, 308, 434, 319, 351, +270, 222, 157, 91, -8, -3, -189, -46, +-324, -57, -397, -72, -410, -118, -348, -193, +-215, -277, -39, -344, 129, -357, 235, -283, +281, -123, 275, 84, 205, 292, 96, 448, +3, 510, -48, 471, -67, 346, -65, 172, +-48, -18, -31, -188, -62, -302, -152, -351, +-244, -347, -285, -307, -259, -234, -171, -129, +-30, -7, 170, 112, 363, 209, 458, 274, +440, 295, 332, 261, 147, 182, -106, 85, +-360, -9, -521, -82, -541, -126, -459, -141, +-313, -135, -109, -121, 118, -108, 306, -92, +400, -67, 403, -29, 365, 34, 280, 123, +131, 208, -30, 256, -167, 245, -276, 168, +-365, 32, -421, -134, -396, -285, -285, -374, +-133, -353, 30, -220, 201, -11, 347, 220, +426, 409, 409, 496, 302, 443, 143, 259, +-48, -8, -249, -285, -385, -493, -420, -560, +-361, -462, -234, -233, -70, 57, 108, 327, +245, 505, 294, 532, 252, 405, 157, 175, +42, -78, -75, -283, -160, -391, -188, -381, +-148, -269, -83, -102, -35, 60, 7, 167, +36, 200, 40, 176, 27, 121, 15, 69, +38, 40, 70, 38, 76, 49, 59, 47, +22, 12, -44, -58, -139, -147, -230, -218, +-265, -233, -212, -180, -91, -67, 57, 83, +205, 233, 305, 329, 317, 331, 240, 239, +90, 77, -75, -108, -218, -271, -309, -360, +-305, -343, -224, -225, -97, -40, 28, 165, +109, 333, 144, 411, 137, 373, 96, 233, +47, 30, 24, -190, 26, -370, 39, -459, +50, -423, 32, -276, -25, -64, -126, 156, +-242, 336, -298, 436, -278, 429, -182, 318, +-10, 146, 189, -34, 370, -184, 469, -279, +439, -312, 292, -284, 56, -213, -222, -111, +-462, 0, -585, 104, -558, 188, -393, 248, +-138, 271, 141, 239, 386, 143, 519, -2, +497, -157, 347, -276, 120, -327, -100, -294, +-264, -169, -338, 24, -302, 225, -191, 367, +-59, 407, 55, 330, 116, 156, 101, -62, +19, -256, -78, -369, -136, -377, -124, -281, +-60, -119, 40, 52, 166, 177, 253, 235, +262, 226, 181, 163, 31, 71, -127, -12, +-265, -56, -334, -61, -293, -38, -168, -5, +-7, 31, 136, 62, 224, 74, 250, 52, +200, 3, 70, -63, -92, -137, -209, -208, +-247, -251, -201, -239, -93, -155, 39, 2, +179, 202, 259, 394, 245, 515, 156, 515, +13, 380, -133, 128, -245, -188, -289, -482, +-246, -661, -134, -662, -1, -489, 113, -192, +183, 151, 199, 440, 164, 599, 88, 588, +-7, 423, -65, 167, -85, -97, -81, -294, +-57, -381, -44, -350, -37, -232, -45, -78, +-73, 60, -89, 145, -69, 161, -4, 118, +90, 51, 176, -3, 230, -34, 219, -42, +120, -24, -45, 12, -211, 46, -327, 57, +-374, 49, -316, 29, -156, 3, 79, -26, +306, -54, 434, -79, 453, -96, 360, -97, +165, -77, -88, -29, -325, 41, -464, 116, +-479, 173, -391, 191, -212, 156, 19, 68, +230, -52, 349, -161, 362, -227, 293, -228, +186, -157, 59, -26, -79, 125, -163, 239, +-176, 277, -147, 227, -101, 105, -63, -58, +-23, -210, -5, -304, -42, -307, -87, -221, +-103, -80, -78, 79, -20, 213, 60, 287, +163, 294, 252, 245, 279, 159, 222, 51, +118, -59, -13, -150, -158, -211, -276, -244, +-333, -254, -299, -233, -200, -164, -86, -55, +43, 68, 157, 182, 217, 274, 215, 321, +161, 302, 98, 216, 37, 84, -22, -65, +-58, -200, -54, -290, -32, -317, -29, -277, +-37, -174, -51, -33, -60, 109, -70, 219, +-90, 274, -80, 265, -39, 192, 5, 76, +45, -55, 78, -166, 115, -227, 137, -218, +110, -152, 56, -54, -1, 52, -56, 138, +-117, 176, -157, 157, -150, 93, -98, 8, +-30, -67, 35, -115, 109, -126, 170, -104, +176, -60, 130, 4, 42, 76, -59, 134, +-155, 161, -238, 157, -255, 118, -196, 44, +-82, -64, 60, -180, 202, -265, 304, -290, +324, -241, 254, -129, 117, 31, -39, 203, +-194, 326, -317, 354, -352, 286, -299, 148, +-178, -18, -20, -156, 127, -221, 248, -199, +307, -113, 282, -1, 208, 89, 97, 113, +-29, 57, -152, -54, -245, -166, -285, -231, +-272, -224, -218, -138, -133, 7, 1, 168, +158, 293, 292, 347, 368, 322, 363, 233, +291, 116, 141, -6, -75, -110, -277, -186, +-423, -234, -475, -262, -420, -273, -270, -259, +-41, -218, 194, -139, 367, -21, 450, 122, +439, 263, 324, 372, 128, 424, -86, 407, +-259, 309, -342, 143, -333, -50, -250, -233, +-102, -376, 41, -454, 135, -447, 175, -357, +154, -203, 92, -16, -1, 168, -82, 311, +-104, 386, -68, 385, 3, 311, 74, 184, +122, 35, 128, -105, 89, -206, 13, -253, +-76, -252, -135, -208, -155, -134, -124, -46, +-33, 37, 62, 98, 128, 135, 134, 148, +82, 132, 12, 85, -73, 19, -139, -44, +-156, -86, -124, -97, -53, -70, 38, -15, +123, 50, 175, 103, 180, 126, 141, 105, +80, 40, 25, -53, -33, -140, -84, -184, +-115, -178, -129, -130, -121, -54, -123, 37, +-123, 112, -101, 148, -63, 151, -10, 138, +55, 120, 130, 95, 202, 62, 246, 23, +248, -31, 212, -110, 141, -196, 22, -262, +-121, -280, -239, -227, -316, -97, -330, 82, +-289, 260, -192, 386, -43, 413, 100, 328, +210, 148, 260, -78, 248, -285, 194, -402, +111, -395, 39, -276, 5, -91, -4, 101, +-11, 243, -25, 296, -48, 251, -94, 131, +-151, -5, -203, -110, -209, -153, -143, -133, +-43, -68, 78, 5, 189, 59, 251, 75, +252, 46, 183, -14, 75, -70, -36, -92, +-126, -72, -167, -24, -150, 31, -85, 81, +-2, 114, 60, 116, 82, 84, 65, 28, +37, -27, -2, -72, -36, -108, -52, -130, +-55, -129, -34, -104, -21, -53, -13, 17, +2, 97, 18, 171, 39, 220, 57, 224, +65, 168, 66, 55, 48, -88, 15, -212, +-26, -281, -60, -278, -78, -202, -73, -66, +-44, 94, -6, 227, 41, 288, 74, 258, +78, 152, 63, 12, 17, -123, -33, -219, +-77, -250, -113, -208, -112, -113, -74, 1, +-5, 104, 79, 177, 154, 213, 212, 212, +227, 177, 180, 112, 74, 24, -62, -69, +-205, -157, -330, -232, -384, -272, -346, -257, +-200, -183, 18, -70, 244, 56, 440, 165, +536, 232, 493, 240, 322, 198, 64, 127, +-201, 50, -415, -1, -540, -11, -536, 6, +-396, 25, -162, 12, 87, -39, 299, -120, +430, -207, 462, -276, 389, -298, 227, -246, +52, -126, -99, 28, -206, 173, -248, 282, +-232, 344, -164, 358, -95, 327, -60, 264, +-38, 174, -14, 61, 10, -79, 34, -240, +71, -402, 132, -525, 193, -563, 220, -488, +191, -293, 128, -10, 24, 301, -112, 561, +-224, 701, -281, 679, -254, 497, -153, 203, +-21, -116, 126, -373, 239, -519, 272, -534, +216, -431, 89, -250, -54, -56, -174, 93, +-240, 180, -235, 216, -150, 212, -14, 188, +126, 165, 240, 146, 291, 124, 269, 85, +177, 25, 34, -59, -106, -161, -217, -256, +-279, -319, -271, -326, -203, -266, -83, -144, +49, 32, 155, 231, 228, 403, 253, 505, +225, 507, 148, 400, 52, 185, -50, -98, +-139, -380, -193, -585, -203, -659, -161, -578, +-94, -352, -26, -42, 51, 267, 114, 498, +159, 601, 183, 554, 168, 381, 133, 142, +77, -88, 11, -251, -61, -323, -132, -312, +-189, -241, -217, -145, -197, -66, -138, -22, +-46, -7, 55, 7, 150, 37, 233, 86, +269, 144, 249, 196, 190, 216, 86, 190, +-31, 115, -141, 2, -215, -119, -226, -216, +-193, -260, -127, -239, -40, -165, 56, -62, +129, 52, 153, 149, 135, 201, 101, 197, +68, 147, 22, 71, -26, -12, -45, -90, +-48, -145, -38, -157, -31, -127, -24, -64, +7, 7, 30, 73, 46, 124, 67, 149, +87, 140, 94, 99, 56, 33, -7, -43, +-63, -112, -103, -162, -140, -180, -161, -166, +-132, -117, -59, -36, 29, 60, 111, 145, +177, 206, 232, 234, 245, 219, 211, 155, +150, 52, 63, -65, -46, -168, -179, -237, +-295, -265, -349, -244, -328, -177, -242, -77, +-100, 35, 94, 138, 291, 216, 429, 259, +468, 260, 403, 221, 260, 147, 53, 40, +-173, -84, -343, -194, -433, -271, -421, -304, +-328, -282, -180, -195, 11, -66, 193, 72, +324, 190, 393, 261, 409, 275, 363, 237, +244, 151, 75, 45, -107, -53, -269, -123, +-388, -156, -440, -156, -391, -132, -254, -101, +-58, -74, 150, -52, 318, -33, 419, -11, +415, 21, 310, 71, 149, 135, -19, 190, +-150, 213, -228, 194, -235, 136, -174, 36, +-74, -97, 27, -227, 96, -319, 121, -347, +94, -299, 33, -187, -27, -33, -75, 135, +-81, 287, -56, 390, -4, 414, 65, 355, +117, 229, 146, 57, 135, -137, 89, -318, +25, -447, -42, -496, -87, -449, -97, -311, +-69, -103, -11, 143, 56, 386, 107, 568, +117, 635, 82, 568, 7, 373, -86, 80, +-157, -250, -192, -543, -158, -727, -63, -752, +54, -610, 176, -334, 265, 15, 302, 358, +273, 614, 182, 737, 62, 708, -63, 537, +-171, 272, -249, -22, -278, -284, -247, -476, +-173, -580, -69, -589, 44, -510, 161, -362, +260, -176, 301, 24, 287, 225, 220, 402, +113, 524, -16, 569, -150, 522, -242, 389, +-271, 184, -241, -61, -154, -298, -26, -481, +114, -574, 219, -554, 272, -431, 269, -240, +217, -25, 129, 170, 13, 313, -86, 384, +-152, 378, -185, 308, -184, 204, -160, 95, +-107, 1, -41, -70, 19, -123, 72, -151, +111, -157, 137, -155, 157, -149, 172, -136, +186, -110, 189, -72, 167, -20, 103, 37, +12, 89, -100, 131, -221, 160, -312, 170, +-357, 153, -322, 114, -208, 63, -48, 10, +131, -50, 281, -118, 372, -182, 392, -227, +330, -239, 216, -209, 80, -131, -34, -7, +-92, 145, -96, 293, -69, 398, -49, 423, +-52, 346, -103, 173, -189, -65, -276, -322, +-322, -535, -281, -642, -155, -600, 49, -409, +306, -116, 545, 219, 700, 525, 704, 733, +549, 785, 273, 658, -84, 387, -447, 35, +-730, -325, -847, -619, -767, -778, -514, -765, +-146, -590, 250, -296, 589, 43, 774, 348, +770, 551, 599, 608, 302, 519, -34, 324, +-321, 83, -488, -134, -490, -266, -361, -286, +-161, -206, 50, -80, 206, 39, 266, 106, +211, 94, 85, 1, -49, -135, -132, -246, +-133, -282, -51, -219, 95, -69, 234, 125, +305, 305, 284, 409, 169, 401, -5, 281, +-200, 84, -350, -134, -390, -302, -320, -372, +-157, -335, 44, -214, 237, -51, 379, 102, +428, 200, 378, 217, 248, 166, 88, 79, +-73, -12, -199, -77, -264, -103, -270, -89, +-226, -50, -163, -10, -96, 6, -10, -4, +77, -26, 158, -38, 230, -19, 281, 34, +301, 114, 269, 183, 190, 208, 70, 164, +-74, 41, -221, -140, -330, -319, -363, -437, +-313, -443, -187, -316, -12, -73, 180, 231, +349, 508, 440, 669, 424, 653, 308, 458, +115, 130, -99, -249, -287, -580, -396, -767, +-395, -759, -287, -560, -98, -230, 120, 142, +318, 465, 439, 659, 445, 691, 342, 564, +157, 323, -55, 34, -248, -233, -377, -419, +-397, -497, -314, -471, -153, -360, 36, -192, +204, -8, 323, 156, 355, 272, 306, 326, +205, 315, 83, 250, -33, 143, -122, 13, +-158, -116, -142, -220, -93, -277, -42, -279, +-1, -225, 30, -130, 38, -7, 31, 120, +26, 225, 31, 285, 56, 285, 79, 225, +101, 117, 119, -22, 114, -163, 83, -270, +23, -321, -33, -311, -71, -246, -92, -133, +-94, 2, -69, 132, -18, 234, 32, 296, +71, 305, 102, 268, 119, 196, 119, 94, +95, -24, 56, -147, 26, -262, 0, -345, +-19, -375, -39, -342, -49, -242, -43, -81, +-36, 116, -27, 301, -8, 420, 22, 447, +55, 375, 85, 215, 118, 1, 145, -206, +152, -342, 132, -380, 85, -321, 24, -183, +-58, -18, -134, 119, -183, 191, -198, 184, +-154, 105, -63, -10, 56, -106, 174, -150, +258, -122, 291, -33, 262, 88, 174, 201, +44, 270, -96, 264, -201, 175, -245, 21, +-219, -154, -130, -301, 5, -387, 151, -384, +260, -287, 312, -115, 279, 79, 167, 247, +9, 347, -162, 358, -289, 280, -337, 140, +-287, -17, -144, -148, 57, -214, 266, -202, +423, -127, 482, -30, 426, 50, 258, 81, +22, 53, -218, -21, -389, -108, -454, -164, +-403, -160, -245, -83, -29, 39, 193, 169, +349, 264, 395, 290, 347, 224, 239, 83, +105, -85, -25, -232, -122, -317, -157, -316, +-139, -230, -93, -86, -40, 71, 8, 199, +44, 273, 57, 279, 56, 219, 52, 112, +58, -12, 66, -125, 64, -210, 59, -260, +46, -264, 24, -219, -1, -138, -22, -35, +-22, 76, 2, 184, 42, 270, 88, 316, +120, 308, 119, 247, 80, 133, 21, -22, +-48, -189, -116, -333, -162, -426, -164, -446, +-98, -375, 12, -222, 136, -16, 247, 199, +314, 379, 315, 485, 239, 484, 101, 369, +-59, 174, -200, -50, -286, -246, -292, -369, +-221, -389, -88, -311, 62, -167, 190, -9, +262, 110, 272, 163, 223, 144, 128, 70, +22, -19, -71, -84, -115, -95, -103, -51, +-51, 34, 21, 125, 88, 187, 133, 188, +144, 131, 105, 36, 33, -69, -55, -161, +-128, -211, -166, -204, -158, -153, -99, -81, +4, -14, 133, 40, 250, 71, 326, 82, +332, 83, 258, 84, 118, 86, -62, 82, +-229, 60, -326, 19, -333, -34, -248, -91, +-89, -136, 106, -148, 292, -111, 399, -37, +399, 54, 294, 133, 124, 172, -70, 146, +-240, 62, -338, -51, -336, -159, -233, -226, +-64, -227, 124, -153, 293, -27, 398, 112, +404, 220, 316, 265, 163, 229, -7, 127, +-162, -9, -269, -136, -301, -219, -255, -237, +-152, -188, -33, -93, 85, 13, 180, 94, +242, 130, 256, 125, 231, 92, 190, 40, +128, -10, 49, -42, -34, -54, -107, -57, +-157, -62, -185, -59, -181, -48, -119, -24, +-14, 11, 108, 58, 215, 99, 287, 119, +295, 104, 219, 45, 85, -45, -61, -139, +-174, -198, -235, -194, -226, -121, -134, -5, +12, 122, 157, 216, 248, 238, 261, 175, +207, 43, 98, -115, -28, -238, -124, -282, +-153, -230, -103, -91, -9, 89, 101, 245, +194, 314, 234, 274, 195, 135, 89, -60, +-44, -245, -164, -357, -232, -360, -227, -249, +-157, -58, -30, 149, 117, 306, 243, 367, +317, 322, 316, 183, 251, 3, 139, -167, +18, -281, -81, -310, -148, -246, -172, -121, +-145, 21, -83, 139, -20, 203, 33, 201, +66, 135, 83, 28, 88, -89, 86, -176, +83, -213, 84, -188, 79, -109, 66, 3, +44, 120, 19, 212, 6, 254, 4, 231, +20, 153, 50, 43, 90, -74, 120, -172, +116, -230, 65, -240, -25, -205, -124, -147, +-198, -88, -223, -31, -186, 20, -78, 68, +91, 114, 274, 164, 401, 211, 442, 239, +377, 225, 221, 159, 8, 43, -207, -101, +-354, -238, -398, -328, -329, -341, -170, -273, +41, -143, 244, 13, 379, 155, 405, 236, +331, 232, 187, 158, 14, 58, -149, -31, +-257, -84, -291, -82, -244, -35, -131, 31, +3, 74, 134, 68, 235, 12, 295, -68, +311, -142, 286, -178, 226, -156, 140, -75, +35, 40, -77, 149, -179, 211, -255, 204, +-297, 133, -294, 14, -234, -115, -118, -214, +35, -255, 193, -225, 333, -130, 430, -4, +469, 113, 442, 195, 343, 224, 184, 196, +-12, 117, -214, 10, -382, -96, -478, -171, +-485, -194, -398, -156, -227, -72, 7, 32, +257, 124, 465, 174, 578, 159, 575, 76, +461, -53, 258, -186, 16, -271, -210, -280, +-359, -204, -403, -55, -349, 131, -221, 293, +-54, 375, 102, 350, 208, 229, 251, 45, +245, -147, 207, -288, 149, -340, 95, -294, +51, -174, 24, -24, 0, 97, -26, 155, +-57, 136, -92, 61, -116, -28, -120, -88, +-87, -91, -19, -31, 75, 73, 177, 179, +262, 246, 299, 238, 272, 147, 179, -11, +44, -193, -103, -353, -222, -440, -275, -421, +-243, -295, -137, -86, 15, 153, 180, 368, +307, 501, 355, 520, 299, 418, 159, 215, +-11, -45, -161, -295, -248, -477, -245, -542, +-154, -479, -7, -312, 146, -84, 259, 142, +305, 315, 273, 392, 177, 365, 57, 255, +-39, 108, -97, -39, -115, -147, -102, -193, +-81, -181, -59, -133, -47, -80, -39, -34, +-15, -8, 34, 3, 106, 7, 191, 20, +268, 44, 310, 70, 287, 87, 193, 80, +55, 42, -95, -22, -223, -97, -298, -156, +-294, -176, -211, -153, -72, -82, 75, 23, +202, 132, 289, 212, 310, 246, 262, 226, +167, 156, 56, 49, -41, -79, -112, -196, +-145, -278, -128, -308, -70, -289, 12, -223, +90, -117, 146, 10, 172, 142, 163, 258, +129, 332, 82, 347, 36, 298, -7, 192, +-36, 48, -53, -112, -72, -258, -94, -358, +-112, -388, -108, -347, -64, -247, 13, -105, +119, 57, 243, 204, 346, 305, 394, 346, +362, 320, 255, 244, 87, 133, -108, 3, +-285, -125, -386, -227, -386, -288, -298, -301, +-154, -270, 10, -207, 156, -116, 255, -7, +288, 103, 266, 191, 222, 248, 175, 270, +144, 259, 123, 210, 105, 124, 82, 14, +42, -104, -18, -209, -95, -283, -173, -315, +-232, -296, -248, -225, -214, -114, -132, 19, +-10, 141, 126, 230, 247, 272, 326, 257, +347, 194, 316, 102, 240, 4, 135, -72, +31, -113, -54, -124, -103, -113, -116, -92, +-107, -75, -91, -78, -83, -97, -80, -117, +-71, -114, -51, -71, -19, 12, 35, 118, +116, 214, 201, 273, 257, 264, 263, 173, +212, 23, 120, -141, 5, -269, -93, -320, +-136, -271, -115, -131, -49, 59, 31, 231, +99, 322, 129, 294, 100, 153, 14, -64, +-85, -282, -145, -427, -139, -445, -64, -324, +59, -87, 187, 200, 281, 448, 304, 577, +245, 547, 122, 369, -32, 91, -162, -212, +-225, -460, -197, -583, -90, -557, 54, -395, +189, -155, 273, 95, 275, 295, 187, 407, +39, 408, -117, 306, -232, 146, -267, -25, +-205, -164, -62, -240, 115, -241, 268, -188, +361, -100, 368, -2, 278, 76, 120, 113, +-63, 110, -211, 84, -277, 44, -250, 4, +-135, -26, 26, -42, 176, -46, 267, -44, +271, -45, 196, -57, 73, -76, -58, -86, +-157, -72, -186, -31, -137, 30, -36, 96, +81, 153, 169, 180, 208, 166, 198, 100, +149, 4, 88, -88, 34, -153, 1, -178, +-2, -157, 12, -99, 13, -28, -14, 27, +-68, 43, -129, 22, -170, -25, -164, -73, +-99, -94, 34, -67, 203, 7, 362, 114, +462, 226, 464, 300, 364, 305, 166, 219, +-89, 53, -329, -157, -491, -357, -535, -496, +-450, -534, -247, -447, 33, -242, 323, 38, +544, 324, 635, 544, 575, 640, 388, 584, +120, 382, -159, 85, -379, -233, -481, -487, +-442, -614, -276, -583, -40, -407, 186, -143, +347, 130, 410, 334, 358, 419, 215, 371, +31, 224, -130, 39, -212, -115, -207, -192, +-127, -171, -2, -69, 131, 66, 219, 172, +229, 195, 171, 115, 80, -49, -10, -239, +-85, -388, -123, -434, -110, -352, -61, -150, +4, 118, 66, 376, 109, 542, 132, 561, +138, 423, 133, 169, 124, -132, 110, -400, +83, -556, 43, -554, -2, -398, -56, -144, +-111, 131, -148, 345, -151, 444, -114, 407, +-49, 253, 44, 38, 153, -166, 252, -296, +316, -321, 321, -247, 272, -111, 180, 36, +48, 143, -105, 182, -246, 148, -334, 61, +-346, -35, -284, -96, -159, -102, 15, -58, +208, 18, 367, 97, 453, 145, 446, 136, +349, 69, 185, -37, -9, -144, -187, -221, +-297, -249, -319, -218, -259, -131, -142, -5, +-1, 127, 134, 227, 224, 273, 245, 261, +199, 194, 115, 84, 25, -46, -46, -162, +-86, -236, -84, -253, -38, -214, 31, -133, +101, -33, 156, 61, 179, 135, 165, 166, +123, 149, 61, 94, -1, 31, -63, -22, +-118, -54, -155, -62, -162, -52, -140, -36, +-94, -29, -26, -34, 61, -59, 171, -92, +279, -111, 362, -95, 397, -44, 365, 40, +252, 134, 78, 208, -123, 239, -311, 206, +-449, 107, -494, -33, -418, -170, -235, -271, +12, -309, 258, -269, 447, -156, 537, -5, +512, 140, 380, 233, 187, 252, -12, 198, +-175, 89, -266, -38, -276, -141, -219, -190, +-130, -173, -47, -97, 9, 6, 47, 99, +68, 148, 86, 148, 115, 99, 158, 20, +212, -65, 250, -130, 244, -149, 176, -121, +54, -66, -97, -8, -233, 37, -321, 58, +-328, 51, -248, 19, -95, -18, 100, -46, +286, -49, 420, -26, 465, 9, 413, 54, +262, 93, 52, 115, -162, 108, -330, 72, +-418, 11, -404, -56, -288, -113, -91, -150, +139, -162, 341, -144, 464, -97, 481, -32, +384, 33, 194, 75, -45, 94, -271, 89, +-420, 65, -447, 31, -340, 6, -126, -5, +136, 5, 379, 34, 540, 66, 573, 82, +459, 70, 225, 29, -68, -39, -342, -123, +-532, -207, -590, -262, -498, -264, -277, -204, +12, -91, 292, 55, 505, 209, 612, 327, +593, 378, 448, 341, 229, 222, 0, 48, +-188, -132, -310, -276, -361, -351, -341, -338, +-268, -242, -172, -96, -76, 46, 14, 147, +95, 180, 168, 150, 234, 77, 289, -2, +319, -58, 315, -68, 262, -30, 160, 36, +21, 91, -120, 106, -230, 79, -284, 22, +-266, -45, -193, -96, -82, -114, 37, -102, +130, -69, 166, -40, 152, -36, 117, -62, +86, -97, 73, -110, 85, -79, 121, 12, +155, 148, 157, 288, 108, 377, 15, 370, +-105, 245, -211, 25, -265, -230, -244, -445, +-140, -550, 20, -514, 192, -343, 327, -81, +380, 191, 332, 390, 199, 462, 15, 403, +-165, 248, -288, 51, -321, -118, -257, -211, +-120, -213, 45, -145, 195, -50, 293, 27, +319, 50, 268, 22, 154, -42, 23, -106, +-80, -139, -139, -115, -147, -39, -106, 71, +-37, 174, 33, 229, 75, 211, 78, 127, +52, 3, 10, -130, -29, -231, -48, -270, +-30, -227, 16, -119, 74, 21, 124, 148, +153, 236, 155, 258, 127, 208, 79, 107, +24, -19, -22, -135, -43, -214, -45, -230, +-41, -190, -36, -114, -44, -24, -63, 57, +-82, 105, -86, 115, -65, 89, -13, 46, +70, 11, 165, -9, 251, -5, 302, 20, +301, 51, 240, 71, 127, 64, -12, 19, +-144, -54, -248, -132, -303, -185, -301, -197, +-238, -157, -127, -75, 6, 30, 141, 133, +248, 198, 314, 207, 326, 159, 285, 76, +195, -17, 74, -91, -55, -127, -161, -123, +-219, -88, -227, -39, -186, 7, -101, 29, +10, 29, 119, 21, 204, 19, 246, 24, +237, 40, 170, 53, 64, 48, -54, 12, +-160, -54, -233, -135, -254, -201, -206, -212, +-89, -157, 75, -34, 235, 129, 352, 287, +400, 386, 360, 387, 233, 278, 48, 84, +-153, -141, -315, -338, -400, -451, -388, -457, +-276, -354, -101, -175, 95, 33, 258, 208, +356, 316, 369, 341, 305, 291, 190, 192, +54, 77, -74, -25, -167, -98, -206, -132, +-195, -134, -148, -111, -79, -86, 9, -65, +100, -50, 174, -39, 208, -34, 199, -26, +153, -5, 74, 26, -21, 62, -115, 95, +-185, 112, -206, 102, -171, 65, -89, 1, +30, -69, 153, -124, 248, -140, 293, -108, +279, -32, 204, 63, 85, 140, -46, 170, +-160, 134, -233, 40, -256, -90, -218, -204, +-132, -258, -21, -226, 89, -114, 178, 48, +232, 206, 241, 304, 203, 305, 131, 202, +55, 25, -7, -169, -51, -315, -76, -368, +-79, -309, -69, -157, -60, 45, -62, 227, +-59, 340, -41, 354, -9, 271, 43, 119, +109, -56, 175, -200, 217, -285, 217, -298, +169, -247, 80, -149, -34, -38, -147, 58, +-231, 119, -257, 144, -213, 139, -109, 111, +31, 75, 171, 43, 273, 30, 307, 31, +273, 41, 179, 43, 53, 28, -77, -15, +-178, -84, -226, -169, -212, -246, -148, -280, +-59, -251, 40, -155, 125, -8, 173, 167, +175, 325, 146, 424, 95, 430, 42, 340, +-1, 166, -27, -46, -36, -248, -39, -394, +-39, -450, -45, -411, -49, -287, -45, -121, +-26, 50, 12, 187, 63, 269, 120, 291, +167, 260, 180, 194, 147, 113, 69, 32, +-34, -40, -135, -98, -207, -143, -224, -169, +-173, -173, -61, -155, 82, -117, 218, -57, +304, 12, 314, 74, 242, 114, 106, 121, +-56, 98, -198, 55, -283, 9, -291, -31, +-221, -41, -91, -27, 68, 2, 206, 28, +291, 40, 297, 25, 230, -11, 112, -58, +-22, -95, -129, -99, -182, -69, -173, -7, +-117, 58, -35, 105, 48, 106, 102, 58, +117, -29, 97, -123, 55, -188, 14, -192, +-17, -123, -29, 7, -17, 160, 6, 286, +37, 343, 57, 301, 59, 171, 40, -17, +10, -208, -21, -348, -40, -397, -45, -341, +-42, -196, -32, -8, -13, 165, 7, 280, +28, 305, 56, 243, 82, 114, 104, -31, +112, -152, 101, -205, 67, -181, 19, -91, +-36, 30, -91, 140, -132, 206, -147, 195, +-127, 115, -78, -11, -12, -139, 63, -231, +135, -252, 190, -197, 209, -81, 182, 57, +123, 169, 47, 219, -37, 190, -115, 97, +-171, -26, -186, -128, -162, -174, -105, -144, +-28, -55, 56, 67, 127, 174, 172, 222, +181, 187, 156, 83, 109, -53, 46, -184, +-16, -262, -60, -267, -82, -193, -86, -71, +-78, 65, -68, 169, -51, 217, -26, 200, +9, 132, 49, 37, 87, -52, 115, -109, +126, -126, 119, -100, 89, -51, 39, 11, +-26, 58, -88, 82, -133, 71, -147, 34, +-126, -17, -70, -65, 11, -95, 99, -96, +167, -59, 196, -3, 191, 61, 142, 107, +57, 129, -49, 102, -141, 32, -197, -64, +-209, -151, -167, -202, -77, -194, 37, -121, +147, -2, 225, 135, 248, 247, 215, 301, +138, 276, 34, 184, -74, 42, -156, -116, +-199, -255, -197, -341, -154, -357, -85, -303, +-10, -191, 62, -49, 129, 101, 176, 232, +201, 328, 202, 366, 176, 350, 114, 275, +21, 152, -86, -5, -187, -175, -256, -325, +-272, -422, -230, -438, -130, -366, 15, -215, +165, -19, 283, 186, 336, 348, 313, 433, +218, 417, 74, 308, -83, 137, -217, -50, +-288, -212, -279, -310, -211, -315, -102, -241, +30, -115, 147, 17, 224, 116, 250, 149, +224, 122, 152, 49, 58, -37, -38, -100, +-114, -118, -150, -77, -149, 7, -126, 108, +-87, 182, -33, 205, 23, 164, 65, 79, +91, -39, 104, -152, 100, -228, 86, -245, +64, -201, 40, -115, 21, -12, 3, 80, +-20, 153, -49, 185, -68, 178, -77, 131, +-72, 70, -52, 10, -26, -41, 2, -81, +28, -105, 50, -109, 63, -97, 67, -72, +62, -49, 54, -22, 42, 5, 29, 35, +16, 60, 8, 85, 4, 106, -4, 123, +-24, 119, -48, 82, -58, 13, -61, -84, +-54, -178, -38, -245, -11, -251, 21, -192, +52, -68, 72, 86, 79, 237, 74, 330, +58, 329, 33, 230, 7, 60, -8, -125, +-19, -278, -25, -343, -26, -304, -20, -168, +-13, 9, -3, 171, 4, 261, 1, 260, +-3, 178, -8, 47, -9, -85, -2, -175, +11, -188, 20, -136, 24, -43, 23, 43, +14, 97, 0, 97, -4, 50, 5, -20, +19, -76, 30, -87, 44, -47, 56, 32, +56, 116, 45, 174, 16, 175, -29, 120, +-71, 7, -101, -125, -114, -239, -99, -300, +-59, -283, -13, -189, 26, -44, 54, 112, +75, 243, 96, 308, 126, 304, 150, 227, +159, 106, 148, -26, 107, -131, 24, -194, +-85, -210, -197, -181, -294, -124, -346, -59, +-321, -10, -220, 20, -57, 31, 141, 42, +319, 60, 427, 94, 440, 124, 355, 146, +193, 137, -2, 91, -182, 12, -309, -90, +-354, -182, -313, -240, -219, -228, -106, -155, +8, -36, 102, 92, 154, 200, 167, 251, +162, 230, 142, 143, 116, 19, 87, -105, +51, -195, 10, -226, -33, -200, -83, -116, +-134, -11, -162, 88, -154, 148, -116, 165, +-50, 139, 40, 85, 128, 21, 185, -38, +198, -78, 155, -91, 71, -75, -30, -52, +-120, -28, -178, -20, -182, -17, -133, -14, +-49, -6, 54, 5, 154, 26, 208, 59, +193, 90, 123, 109, 11, 97, -110, 56, +-196, -11, -220, -79, -185, -139, -102, -165, +6, -152, 106, -96, 179, -11, 209, 79, +184, 148, 121, 172, 46, 156, -36, 99, +-106, 19, -146, -72, -144, -136, -116, -164, +-74, -146, -29, -93, 13, -23, 50, 46, +81, 97, 98, 123, 95, 111, 87, 74, +71, 21, 43, -24, 14, -61, -8, -78, +-34, -77, -65, -55, -96, -25, -124, 0, +-140, 13, -128, 16, -78, 20, 5, 23, +115, 39, 221, 58, 281, 81, 270, 90, +182, 74, 26, 16, -159, -69, -315, -160, +-396, -224, -375, -234, -235, -180, -13, -60, +220, 98, 401, 255, 481, 351, 431, 355, +258, 251, 18, 72, -228, -135, -410, -307, +-473, -394, -412, -375, -251, -253, -32, -68, +177, 125, 314, 258, 362, 308, 323, 264, +216, 159, 73, 29, -61, -81, -161, -140, +-203, -136, -184, -86, -124, -24, -51, 23, +11, 32, 45, 12, 37, -28, 3, -60, +-30, -70, -47, -46, -39, 3, 6, 64, +69, 102, 125, 95, 164, 50, 166, -18, +119, -75, 37, -109, -58, -92, -149, -30, +-197, 64, -188, 149, -144, 193, -81, 166, +-5, 71, 55, -64, 75, -202, 69, -297, +55, -316, 47, -237, 55, -86, 74, 102, +87, 264, 94, 360, 88, 358, 47, 267, +-18, 115, -84, -53, -139, -187, -174, -261, +-174, -261, -139, -211, -85, -138, -25, -72, +37, -16, 85, 19, 122, 46, 148, 73, +159, 116, 149, 172, 124, 224, 84, 241, +23, 195, -42, 93, -101, -54, -157, -202, +-199, -320, -204, -371, -170, -342, -110, -225, +-32, -58, 51, 112, 130, 248, 192, 327, +221, 341, 211, 283, 167, 175, 92, 42, +-17, -85, -135, -189, -223, -250, -260, -272, +-235, -249, -146, -181, -14, -73, 116, 53, +210, 170, 244, 260, 202, 297, 106, 276, +-19, 183, -143, 44, -228, -112, -245, -240, +-192, -318, -90, -329, 38, -266, 152, -140, +216, 23, 227, 182, 190, 308, 112, 361, +18, 341, -71, 249, -147, 110, -202, -53, +-219, -204, -197, -308, -142, -340, -47, -304, +73, -218, 179, -94, 246, 33, 266, 140, +217, 199, 100, 215, -44, 185, -177, 138, +-269, 86, -284, 40, -217, 6, -85, -20, +79, -39, 219, -56, 286, -79, 266, -112, +177, -136, 23, -146, -144, -130, -259, -96, +-289, -40, -233, 29, -106, 105, 61, 170, +202, 207, 276, 205, 264, 158, 164, 79, +10, -28, -142, -138, -258, -231, -299, -262, +-240, -223, -101, -113, 70, 36, 231, 187, +333, 295, 328, 319, 217, 243, 41, 76, +-151, -126, -299, -308, -358, -403, -319, -384, +-198, -246, -29, -31, 129, 203, 224, 382, +251, 451, 219, 388, 129, 218, 18, 3, +-59, -200, -81, -329, -62, -357, -14, -278, +30, -131, 37, 40, 0, 171, -77, 228, +-166, 204, -219, 115, -202, -1, -129, -108, +-16, -166, 125, -163, 248, -95, 299, 4, +279, 96, 196, 145, 66, 145, -75, 97, +-185, 20, -246, -56, -243, -98, -179, -84, +-91, -25, 1, 57, 80, 115, 123, 127, +115, 71, 74, -37, 22, -176, -24, -293, +-46, -336, -30, -274, 10, -110, 56, 109, +96, 329, 99, 476, 57, 508, -15, 397, +-99, 176, -176, -101, -204, -345, -166, -491, +-75, -495, 51, -365, 179, -149, 260, 88, +254, 274, 161, 361, 5, 322, -163, 182, +-283, -3, -316, -160, -253, -249, -100, -241, +98, -143, 263, 14, 349, 176, 339, 283, +222, 298, 32, 210, -165, 58, -315, -121, +-372, -269, -313, -349, -160, -326, 27, -212, +193, -38, 288, 139, 284, 265, 190, 310, +44, 262, -107, 144, -220, -10, -246, -146, +-187, -225, -71, -215, 67, -131, 195, -2, +255, 119, 224, 197, 123, 206, -20, 140, +-160, 21, -249, -116, -262, -221, -200, -262, +-80, -220, 48, -117, 134, 26, 165, 165, +143, 263, 73, 290, -16, 238, -71, 124, +-70, -20, -18, -151, 65, -240, 144, -263, +175, -218, 138, -111, 27, 19, -129, 136, +-272, 201, -352, 206, -352, 151, -257, 54, +-71, -50, 145, -132, 320, -163, 415, -142, +416, -78, 312, 0, 136, 76, -61, 120, +-229, 129, -327, 101, -342, 53, -287, 2, +-176, -41, -28, -62, 104, -69, 183, -63, +206, -60, 178, -54, 95, -53, -10, -43, +-92, -27, -132, -1, -120, 35, -58, 74, +31, 108, 115, 124, 176, 118, 181, 87, +116, 45, 4, -6, -125, -55, -243, -100, +-303, -129, -268, -140, -153, -131, 5, -104, +164, -61, 272, -4, 296, 53, 240, 99, +123, 118, -20, 115, -136, 89, -190, 63, +-186, 35, -123, 15, -22, 5, 65, 3, +104, -1, 93, -22, 36, -64, -49, -115, +-119, -154, -144, -170, -113, -144, -40, -76, +59, 26, 148, 128, 205, 199, 211, 221, +157, 190, 53, 119, -63, 31, -166, -46, +-240, -98, -257, -113, -211, -106, -124, -86, +-22, -74, 84, -73, 164, -78, 199, -71, +198, -40, 167, 19, 108, 103, 44, 187, +-13, 245, -71, 247, -116, 184, -152, 56, +-187, -98, -211, -241, -198, -331, -141, -342, +-49, -269, 77, -128, 212, 40, 314, 194, +356, 291, 321, 317, 199, 270, 20, 172, +-178, 48, -354, -65, -454, -151, -433, -193, +-306, -183, -113, -138, 109, -74, 305, -14, +415, 29, 413, 47, 316, 41, 153, 12, +-30, -19, -191, -44, -300, -45, -331, -17, +-272, 37, -158, 106, -27, 169, 100, 205, +192, 192, 215, 122, 166, -4, 81, -154, +-16, -293, -96, -379, -133, -379, -118, -276, +-55, -88, 40, 147, 127, 365, 161, 501, +136, 511, 53, 379, -79, 142, -218, -146, +-298, -400, -296, -551, -205, -547, -39, -393, +162, -133, 335, 157, 425, 396, 401, 521, +264, 495, 57, 342, -169, 113, -363, -119, +-469, -295, -448, -373, -320, -357, -133, -262, +76, -127, 258, 8, 361, 112, 371, 171, +303, 188, 178, 176, 32, 149, -100, 113, +-191, 67, -224, 5, -198, -59, -144, -119, +-89, -160, -39, -171, -4, -141, 5, -74, +1, 15, 8, 100, 24, 150, 52, 160, +94, 122, 138, 54, 163, -25, 158, -88, +107, -117, 14, -107, -98, -64, -202, -4, +-269, 44, -270, 68, -199, 62, -87, 30, +41, -9, 156, -45, 230, -56, 238, -41, +189, 0, 110, 43, 15, 76, -75, 88, +-132, 66, -153, 16, -138, -52, -97, -114, +-59, -149, -26, -136, 6, -78, 32, 15, +50, 110, 76, 182, 106, 208, 114, 174, +93, 86, 53, -38, -4, -156, -75, -234, +-142, -246, -190, -198, -198, -98, -155, 21, +-75, 131, 22, 201, 128, 219, 212, 191, +239, 134, 211, 66, 143, 0, 43, -51, +-74, -91, -172, -120, -227, -142, -230, -156, +-181, -162, -94, -143, -1, -93, 81, -16, +130, 76, 129, 165, 90, 230, 47, 250, +7, 224, -30, 149, -37, 46, -13, -66, +18, -154, 36, -204, 40, -210, 21, -179, +-15, -117, -59, -39, -102, 35, -120, 93, +-101, 117, -59, 112, -17, 86, 19, 49, +46, 8, 59, -23, 62, -37, 70, -28, +74, -5, 74, 22, 65, 42, 33, 45, +-12, 30, -62, -4, -110, -42, -152, -75, +-162, -91, -126, -84, -62, -49, 17, -2, +95, 43, 143, 77, 146, 90, 112, 78, +50, 49, -21, 13, -69, -22, -82, -44, +-71, -48, -39, -34, -4, -13, 15, 9, +11, 24, -7, 20, -32, -5, -56, -41, +-55, -72, -26, -88, 21, -75, 72, -32, +109, 40, 112, 120, 78, 186, 18, 210, +-59, 182, -127, 102, -160, -16, -156, -141, +-116, -246, -42, -299, 41, -288, 104, -210, +136, -87, 129, 53, 82, 175, 23, 259, +-27, 298, -57, 291, -59, 239, -35, 156, +-2, 62, 16, -40, 15, -146, -11, -248, +-60, -324, -115, -357, -143, -331, -141, -247, +-93, -103, 3, 79, 112, 264, 201, 406, +246, 467, 234, 432, 159, 303, 52, 112, +-63, -99, -161, -276, -219, -387, -229, -409, +-207, -345, -156, -219, -89, -65, -22, 78, +32, 178, 80, 228, 125, 236, 156, 207, +180, 157, 190, 103, 170, 52, 115, 0, +24, -54, -93, -110, -203, -159, -276, -189, +-297, -192, -261, -158, -168, -85, -39, 17, +84, 123, 184, 204, 242, 231, 248, 199, +198, 112, 115, -4, 22, -112, -60, -177, +-113, -176, -134, -108, -128, 4, -100, 117, +-62, 187, -40, 186, -28, 107, -21, -34, +-20, -187, -24, -306, -13, -342, 16, -272, +51, -107, 87, 111, 110, 319, 112, 461, +87, 491, 41, 395, -20, 195, -78, -60, +-116, -298, -132, -458, -124, -507, -84, -435, +-29, -265, 18, -44, 49, 169, 53, 317, +33, 368, 1, 323, -22, 205, -29, 55, +-5, -77, 40, -155, 91, -160, 125, -98, +125, 0, 88, 84, 10, 118, -92, 88, +-195, -3, -269, -119, -288, -219, -227, -260, +-103, -218, 57, -96, 216, 69, 333, 225, +368, 325, 316, 334, 190, 251, 17, 104, +-157, -62, -297, -195, -372, -254, -367, -236, +-278, -158, -136, -59, 19, 21, 160, 55, +262, 42, 298, 7, 274, -19, 211, -9, +119, 46, 19, 135, -80, 218, -167, 255, +-234, 212, -264, 82, -257, -102, -209, -287, +-125, -419, -11, -446, 112, -345, 221, -139, +297, 117, 312, 348, 258, 489, 143, 499, +-10, 379, -169, 162, -284, -92, -335, -306, +-310, -419, -212, -410, -69, -293, 79, -112, +197, 78, 260, 220, 249, 279, 177, 248, +65, 148, -51, 27, -139, -77, -176, -135, +-161, -133, -112, -82, -45, -9, 23, 52, +69, 81, 80, 70, 62, 25, 24, -37, +-17, -90, -43, -113, -44, -96, -24, -43, +12, 34, 45, 112, 58, 171, 44, 192, +8, 164, -38, 92, -82, -7, -113, -114, +-123, -209, -105, -267, -57, -269, 17, -208, +94, -95, 155, 50, 185, 189, 170, 292, +109, 330, 16, 289, -86, 179, -174, 30, +-221, -115, -223, -219, -178, -254, -89, -219, +20, -131, 120, -23, 187, 63, 205, 100, +169, 81, 86, 23, -12, -42, -91, -83, +-138, -76, -141, -16, -106, 74, -48, 165, +16, 214, 69, 199, 86, 122, 70, 3, +31, -123, -24, -220, -75, -263, -98, -240, +-88, -157, -58, -35, -15, 86, 28, 171, +69, 206, 95, 193, 99, 143, 80, 74, +43, 2, 2, -61, -43, -103, -87, -121, +-119, -125, -126, -120, -115, -101, -84, -64, +-35, -13, 23, 47, 82, 111, 131, 167, +152, 200, 142, 193, 101, 140, 31, 52, +-47, -58, -117, -168, -163, -248, -182, -279, +-167, -247, -117, -161, -39, -37, 47, 97, +123, 207, 175, 266, 186, 262, 155, 204, +89, 106, 8, -4, -67, -102, -125, -161, +-164, -173, -170, -145, -147, -90, -98, -25, +-33, 32, 32, 69, 88, 80, 119, 67, +120, 39, 97, 4, 62, -30, 20, -59, +-17, -73, -54, -65, -81, -36, -87, 8, +-74, 60, -42, 107, 3, 137, 40, 140, +54, 107, 47, 37, 21, -55, -12, -145, +-48, -207, -73, -222, -81, -182, -67, -96, +-36, 18, 3, 131, 45, 208, 84, 230, +107, 200, 96, 129, 65, 38, 24, -50, +-21, -116, -67, -154, -97, -159, -114, -139, +-112, -103, -93, -62, -63, -17, -14, 32, +41, 82, 87, 137, 108, 185, 103, 209, +73, 195, 21, 128, -45, 12, -100, -131, +-127, -262, -122, -342, -78, -344, -2, -257, +82, -94, 143, 110, 161, 302, 128, 422, +61, 437, -30, 339, -127, 152, -204, -70, +-237, -270, -220, -399, -149, -423, -41, -336, +79, -170, 191, 19, 261, 185, 272, 288, +228, 311, 145, 259, 30, 156, -94, 36, +-204, -72, -272, -143, -290, -165, -257, -150, +-164, -114, -35, -64, 92, -15, 187, 22, +234, 47, 219, 60, 161, 61, 73, 52, +-19, 37, -91, 20, -129, 5, -130, -3, +-98, -1, -44, 12, 5, 28, 32, 36, +19, 29, -17, 4, -59, -41, -85, -96, +-79, -138, -38, -146, 32, -110, 110, -32, +161, 74, 168, 177, 134, 245, 54, 254, +-53, 191, -159, 64, -229, -89, -238, -229, +-187, -314, -90, -316, 32, -231, 145, -79, +218, 100, 231, 256, 180, 346, 84, 343, +-30, 244, -135, 79, -203, -104, -217, -253, +-179, -329, -101, -312, -12, -206, 67, -47, +125, 114, 152, 234, 142, 285, 108, 252, +60, 148, -2, 6, -63, -128, -119, -215, +-148, -232, -148, -180, -127, -77, -80, 43, +-13, 147, 57, 209, 111, 211, 144, 158, +146, 62, 113, -41, 38, -129, -60, -185, +-139, -197, -173, -165, -161, -101, -100, -23, +-11, 52, 81, 111, 149, 148, 163, 161, +129, 153, 59, 126, -31, 86, -120, 31, +-184, -31, -205, -96, -164, -163, -80, -215, +17, -236, 115, -215, 188, -143, 214, -25, +193, 118, 135, 255, 51, 349, -40, 371, +-138, 303, -217, 153, -251, -49, -237, -251, +-177, -398, -78, -449, 43, -386, 159, -223, +241, -4, 264, 207, 232, 361, 144, 413, +18, 357, -114, 214, -219, 36, -262, -131, +-235, -240, -161, -267, -49, -222, 79, -131, +180, -31, 224, 46, 201, 83, 124, 81, +16, 50, -103, 16, -205, -5, -246, 1, +-217, 30, -138, 69, -30, 97, 82, 97, +182, 70, 237, 20, 229, -39, 170, -97, +85, -137, -24, -147, -135, -130, -217, -88, +-246, -29, -221, 36, -162, 99, -84, 144, +8, 164, 95, 154, 150, 115, 174, 55, +175, -20, 156, -91, 99, -140, 9, -157, +-79, -140, -138, -93, -169, -30, -170, 30, +-135, 78, -75, 105, -6, 108, 41, 91, +69, 61, 92, 27, 98, 1, 69, -17, +30, -30, -1, -41, -13, -47, -17, -53, +-24, -58, -29, -53, -38, -38, -62, -13, +-98, 18, -114, 49, -98, 69, -50, 77, +8, 73, 74, 54, 145, 27, 186, 4, +170, -12, 110, -21, 29, -30, -63, -43, +-146, -60, -204, -77, -206, -84, -158, -78, +-86, -50, -9, 1, 64, 68, 120, 132, +138, 171, 112, 168, 59, 118, 11, 34, +-34, -67, -63, -156, -62, -202, -29, -185, +13, -109, 44, -1, 50, 106, 43, 175, +21, 184, -31, 127, -93, 21, -138, -97, +-145, -182, -117, -200, -60, -143, 16, -26, +96, 109, 139, 207, 134, 237, 95, 182, +40, 61, -9, -83, -43, -200, -48, -246, +-20, -202, 16, -77, 28, 77, 16, 204, +-16, 254, -72, 205, -138, 67, -189, -110, +-194, -256, -130, -317, -13, -269, 122, -115, +243, 97, 309, 290, 294, 398, 187, 383, +19, 245, -149, 24, -272, -214, -333, -390, +-306, -447, -194, -370, -31, -182, 138, 56, +251, 268, 285, 394, 239, 398, 122, 285, +-37, 96, -173, -103, -250, -253, -248, -315, +-170, -285, -53, -176, 74, -29, 167, 104, +196, 188, 159, 200, 77, 155, -18, 73, +-92, -12, -129, -70, -118, -90, -62, -70, +2, -29, 46, 11, 65, 36, 47, 40, +-2, 23, -61, -4, -116, -29, -131, -40, +-98, -38, -33, -25, 49, -6, 128, 11, +176, 23, 173, 29, 113, 31, 29, 31, +-43, 31, -110, 29, -160, 22, -182, 3, +-168, -20, -122, -47, -57, -72, 13, -85, +93, -73, 164, -35, 191, 22, 174, 85, +126, 133, 62, 152, -22, 133, -121, 73, +-205, -19, -241, -120, -230, -205, -172, -246, +-66, -227, 65, -150, 187, -26, 258, 120, +259, 253, 211, 335, 126, 343, 1, 270, +-124, 130, -218, -52, -265, -232, -265, -366, +-219, -420, -120, -377, 18, -245, 145, -53, +224, 159, 253, 335, 235, 431, 168, 423, +50, 311, -84, 127, -188, -84, -248, -266, +-266, -379, -218, -393, -108, -305, 30, -141, +158, 51, 239, 216, 265, 315, 236, 325, +135, 251, -16, 118, -159, -34, -264, -157, +-308, -222, -287, -225, -193, -173, -43, -91, +108, -6, 220, 58, 281, 88, 283, 91, +222, 75, 113, 65, -24, 68, -140, 83, +-207, 94, -231, 85, -210, 45, -143, -28, +-62, -118, -5, -202, 26, -247, 44, -234, +65, -150, 77, -15, 80, 134, 84, 256, +94, 311, 94, 283, 79, 181, 47, 37, +5, -105, -45, -206, -116, -242, -183, -202, +-216, -113, -208, -11, -158, 72, -75, 109, +17, 97, 108, 50, 172, -8, 197, -47, +194, -52, 163, -24, 105, 30, 30, 88, +-47, 130, -105, 132, -131, 93, -140, 25, +-130, -52, -108, -125, -93, -171, -91, -176, +-90, -143, -79, -83, -43, -13, 20, 55, +93, 109, 180, 140, 255, 143, 289, 127, +264, 94, 180, 55, 44, 18, -121, -12, +-284, -34, -399, -54, -429, -76, -373, -102, +-238, -125, -58, -140, 124, -138, 275, -112, +361, -56, 359, 25, 288, 122, 171, 214, +41, 275, -59, 284, -127, 229, -162, 118, +-163, -30, -151, -181, -138, -300, -127, -357, +-117, -338, -89, -242, -52, -89, -6, 85, +62, 234, 141, 325, 210, 335, 241, 266, +210, 142, 116, -7, -12, -139, -148, -229, +-244, -253, -263, -210, -211, -118, -105, -6, +29, 91, 144, 155, 208, 174, 198, 144, +115, 75, -2, -7, -132, -82, -233, -133, +-261, -149, -200, -123, -65, -63, 100, 18, +225, 102, 282, 171, 265, 205, 165, 187, +13, 121, -138, 15, -245, -109, -280, -224, +-244, -295, -150, -299, -10, -226, 130, -88, +218, 86, 233, 247, 179, 352, 76, 368, +-48, 287, -159, 134, -219, -45, -207, -198, +-146, -287, -46, -286, 65, -204, 146, -73, +177, 56, 153, 136, 85, 143, 7, 84, +-64, -10, -120, -99, -125, -141, -85, -111, +-31, -13, 12, 118, 35, 234, 41, 286, +23, 254, -25, 146, -76, -10, -95, -166, +-76, -276, -24, -308, 40, -262, 98, -159, +137, -38, 134, 61, 82, 117, 13, 131, +-57, 110, -111, 77, -137, 56, -132, 58, +-89, 84, -28, 113, 29, 125, 72, 96, +86, 27, 60, -71, 9, -169, -48, -238, +-82, -254, -75, -212, -40, -120, 8, 0, +63, 115, 98, 193, 94, 221, 64, 199, +13, 137, -44, 57, -101, -13, -147, -56, +-157, -73, -117, -67, -45, -51, 40, -35, +116, -26, 160, -26, 162, -31, 114, -37, +36, -33, -50, -17, -131, 5, -185, 25, +-194, 44, -164, 56, -93, 59, 10, 56, +112, 51, 189, 48, 222, 37, 200, 17, +127, -11, 18, -46, -107, -88, -205, -125, +-253, -140, -234, -126, -153, -80, -40, -1, +81, 89, 184, 169, 228, 220, 198, 225, +115, 178, 1, 84, -106, -33, -182, -148, +-208, -231, -164, -266, -66, -242, 41, -168, +129, -64, 176, 51, 160, 153, 90, 223, +-6, 247, -88, 227, -138, 169, -149, 82, +-121, -17, -65, -104, -9, -169, 42, -205, +73, -203, 78, -162, 67, -92, 36, -7, +-8, 78, -30, 141, -21, 170, -5, 159, +7, 111, 9, 37, 2, -36, -17, -96, +-44, -124, -60, -110, -52, -62, -26, 0, +0, 58, 15, 98, 25, 101, 37, 71, +26, 18, -3, -37, -24, -79, -33, -95, +-34, -82, -16, -40, 13, 12, 46, 50, +68, 66, 50, 52, 8, 18, -43, -24, +-96, -50, -135, -49, -130, -21, -77, 25, +9, 72, 89, 107, 151, 112, 186, 82, +162, 22, 81, -51, -27, -120, -128, -164, +-201, -171, -230, -138, -210, -75, -130, 3, +-10, 82, 100, 144, 179, 181, 219, 186, +208, 160, 143, 105, 46, 31, -53, -53, +-119, -131, -155, -192, -162, -218, -135, -201, +-90, -138, -40, -40, 6, 71, 34, 175, +50, 246, 51, 259, 33, 206, 24, 101, +32, -32, 50, -160, 76, -252, 95, -277, +86, -227, 45, -120, -29, 16, -113, 147, +-177, 238, -208, 261, -194, 215, -139, 111, +-46, -18, 71, -137, 177, -213, 236, -227, +246, -180, 195, -86, 83, 26, -49, 120, +-160, 170, -219, 167, -217, 122, -166, 49, +-85, -30, 8, -88, 79, -114, 120, -102, +129, -63, 106, -6, 62, 43, 13, 67, +-24, 65, -39, 39, -42, 4, -48, -32, +-45, -55, -47, -63, -60, -47, -73, -15, +-74, 25, -46, 62, 15, 85, 80, 88, +139, 69, 177, 33, 168, -19, 105, -71, +0, -115, -117, -134, -214, -121, -265, -78, +-251, -15, -160, 57, -23, 119, 122, 155, +242, 153, 298, 113, 279, 47, 181, -27, +23, -89, -143, -132, -258, -144, -307, -124, +-273, -78, -154, -23, 8, 27, 154, 68, +237, 97, 245, 107, 195, 99, 90, 76, +-43, 43, -154, 4, -217, -36, -211, -72, +-151, -95, -55, -97, 59, -79, 155, -46, +188, -7, 156, 29, 85, 55, -8, 62, +-84, 54, -130, 35, -133, 23, -94, 15, +-36, 16, 15, 28, 53, 39, 65, 31, +51, 3, 9, -41, -41, -91, -68, -127, +-68, -137, -35, -110, 31, -48, 105, 42, +142, 125, 132, 182, 75, 193, -14, 155, +-106, 80, -184, -15, -218, -100, -188, -153, +-108, -159, -10, -126, 84, -68, 156, -12, +193, 27, 174, 42, 103, 39, 21, 26, +-45, 14, -84, 22, -88, 52, -61, 86, +-16, 108, 30, 105, 35, 66, 3, -6, +-48, -97, -105, -183, -146, -234, -143, -225, +-96, -153, -13, -34, 86, 101, 167, 218, +220, 284, 224, 276, 172, 198, 82, 72, +-26, -68, -129, -186, -199, -247, -228, -240, +-201, -168, -127, -59, -42, 52, 35, 134, +92, 164, 112, 145, 95, 82, 64, 1, +31, -74, 6, -115, -10, -112, -17, -66, +-11, 9, 3, 87, 16, 141, 24, 154, +15, 119, -12, 48, -46, -41, -79, -127, +-87, -182, -69, -191, -42, -149, -10, -65, +27, 33, 55, 114, 72, 161, 75, 165, +65, 128, 42, 64, -2, -9, -50, -68, +-85, -99, -95, -94, -85, -68, -54, -32, +-2, -1, 57, 20, 95, 27, 106, 18, +101, 10, 78, 13, 25, 27, -40, 43, +-98, 52, -138, 41, -151, 11, -144, -38, +-110, -92, -43, -131, 36, -135, 101, -96, +154, -20, 191, 76, 195, 162, 156, 213, +76, 209, -14, 149, -110, 43, -208, -77, +-278, -177, -288, -227, -229, -213, -114, -139, +26, -29, 170, 85, 291, 172, 338, 203, +292, 171, 176, 86, 26, -20, -137, -117, +-279, -174, -361, -178, -343, -125, -232, -32, +-66, 72, 118, 159, 282, 202, 378, 192, +360, 138, 231, 52, 41, -51, -142, -139, +-301, -195, -391, -203, -372, -168, -253, -100, +-73, -10, 115, 81, 275, 154, 374, 191, +378, 187, 263, 139, 84, 62, -101, -30, +-246, -111, -330, -166, -334, -175, -247, -133, +-105, -51, 34, 41, 144, 115, 220, 158, +242, 155, 204, 105, 120, 31, 20, -45, +-56, -103, -101, -123, -131, -104, -131, -62, +-100, -18, -70, 11, -57, 18, -53, 1, +-32, -22, 4, -31, 43, -5, 91, 53, +148, 128, 188, 191, 183, 217, 121, 185, +22, 83, -88, -66, -199, -223, -284, -340, +-299, -380, -231, -325, -108, -189, 47, 3, +197, 197, 308, 344, 342, 408, 279, 372, +142, 252, -29, 86, -185, -84, -289, -218, +-317, -285, -264, -280, -143, -216, -3, -118, +113, -12, 190, 73, 219, 120, 194, 130, +125, 123, 26, 104, -64, 79, -111, 52, +-123, 27, -104, 5, -64, -21, -21, -54, +4, -93, 3, -121, -16, -128, -29, -108, +-29, -65, -12, -1, 24, 73, 69, 139, +108, 184, 126, 188, 112, 154, 68, 86, +5, -2, -82, -96, -164, -173, -212, -216, +-206, -216, -147, -169, -58, -80, 46, 26, +146, 124, 215, 199, 220, 233, 171, 214, +90, 141, -2, 35, -94, -79, -165, -171, +-189, -218, -161, -204, -101, -136, -27, -31, +48, 82, 105, 167, 127, 201, 100, 173, +43, 94, -10, -13, -45, -110, -69, -167, +-64, -172, -23, -126, 34, -45, 70, 40, +70, 98, 50, 117, 12, 96, -48, 47, +-112, -6, -140, -38, -122, -37, -64, -2, +9, 44, 87, 77, 159, 78, 184, 37, +141, -39, 57, -129, -26, -192, -98, -202, +-146, -143, -155, -31, -109, 102, -36, 213, +22, 266, 51, 240, 67, 140, 66, -7, +39, -154, -6, -250, -36, -263, -24, -193, +8, -65, 40, 88, 72, 214, 93, 272, +73, 241, 4, 132, -82, -19, -147, -164, +-173, -261, -161, -288, -104, -233, -8, -110, +91, 45, 156, 182, 175, 267, 154, 279, +101, 224, 13, 122, -83, 1, -141, -107, +-142, -178, -99, -196, -29, -168, 47, -107, +107, -39, 122, 20, 66, 57, -25, 66, +-111, 51, -166, 25, -178, 3, -132, -1, +-27, 18, 109, 50, 224, 86, 275, 112, +263, 108, 189, 68, 54, 2, -118, -84, +-263, -169, -335, -222, -327, -222, -254, -170, +-122, -73, 44, 48, 188, 161, 272, 239, +287, 254, 251, 210, 178, 121, 79, 14, +-23, -86, -95, -155, -138, -176, -165, -151, +-177, -102, -167, -46, -136, -4, -99, 16, +-61, 21, -9, 22, 65, 31, 138, 55, +196, 92, 231, 123, 229, 131, 177, 100, +72, 29, -60, -69, -174, -166, -242, -225, +-261, -223, -221, -151, -131, -28, -14, 117, +90, 231, 157, 274, 179, 227, 154, 105, +86, -53, 3, -197, -65, -275, -96, -260, +-74, -158, -15, -1, 51, 159, 98, 261, +109, 273, 71, 192, -5, 45, -91, -120, +-153, -243, -170, -283, -139, -229, -70, -98, +21, 61, 111, 196, 167, 265, 167, 250, +114, 158, 40, 25, -46, -107, -117, -197, +-140, -219, -106, -177, -31, -88, 46, 11, +105, 87, 138, 118, 126, 110, 60, 71, +-34, 21, -115, -18, -159, -35, -167, -31, +-135, -10, -63, 13, 31, 30, 113, 36, +159, 25, 171, 4, 145, -22, 80, -46, +-8, -67, -87, -78, -126, -81, -122, -68, +-92, -35, -42, 18, 19, 79, 68, 134, +85, 166, 71, 158, 40, 106, -1, 15, +-47, -92, -88, -188, -99, -236, -73, -218, +-21, -132, 36, 1, 84, 142, 118, 241, +124, 266, 89, 204, 29, 71, -28, -89, +-74, -225, -101, -291, -109, -266, -88, -148, +-42, 23, 7, 194, 43, 309, 64, 325, +73, 237, 56, 73, 13, -114, -32, -263, +-51, -333, -42, -304, -16, -184, 18, -9, +61, 159, 90, 265, 84, 282, 44, 212, +-8, 83, -58, -59, -109, -167, -145, -207, +-135, -173, -79, -82, -7, 28, 65, 116, +128, 149, 172, 119, 169, 44, 111, -45, +29, -116, -47, -141, -109, -105, -152, -25, +-154, 66, -116, 131, -55, 152, 6, 113, +64, 30, 110, -66, 128, -137, 111, -162, +70, -127, 18, -45, -32, 49, -68, 128, +-88, 169, -81, 155, -54, 85, -20, -15, +8, -112, 27, -175, 36, -182, 36, -135, +28, -52, 21, 41, 18, 126, 12, 178, +8, 180, 6, 133, 3, 54, -3, -32, +-12, -104, -35, -145, -60, -150, -69, -120, +-53, -63, -19, 2, 21, 56, 63, 88, +93, 92, 97, 77, 67, 48, 18, 17, +-29, -7, -64, -13, -86, -2, -85, 13, +-56, 23, -11, 17, 33, -11, 65, -53, +77, -99, 63, -135, 28, -141, -21, -102, +-61, -21, -77, 77, -64, 170, -30, 231, +15, 244, 57, 194, 81, 90, 77, -41, +47, -165, 11, -250, -26, -275, -60, -231, +-76, -135, -67, -13, -40, 106, -3, 189, +28, 214, 45, 185, 48, 113, 34, 24, +3, -53, -29, -100, -40, -109, -22, -84, +15, -39, 51, 4, 83, 33, 95, 38, +71, 25, 16, -4, -48, -39, -98, -62, +-133, -63, -148, -40, -129, -3, -68, 36, +16, 66, 94, 84, 148, 84, 178, 68, +171, 34, 118, -6, 41, -42, -26, -73, +-72, -87, -109, -84, -132, -62, -128, -30, +-96, 9, -64, 44, -35, 67, 3, 70, +50, 54, 79, 24, 86, -9, 89, -35, +90, -44, 80, -29, 52, 2, 19, 37, +-11, 59, -47, 62, -89, 36, -113, -14, +-105, -74, -72, -123, -29, -138, 17, -110, +63, -44, 91, 40, 91, 115, 71, 159, +40, 163, -3, 123, -43, 48, -70, -36, +-73, -104, -50, -136, -6, -131, 43, -96, +81, -41, 94, 16, 77, 58, 35, 72, +-21, 63, -70, 43, -99, 20, -104, 5, +-88, -2, -57, -5, -11, -11, 39, -19, +76, -29, 95, -36, 99, -35, 89, -22, +58, 7, 14, 43, -26, 73, -53, 84, +-69, 70, -78, 29, -70, -28, -44, -84, +-16, -122, 7, -123, 25, -84, 39, -16, +41, 52, 26, 100, 4, 115, -10, 99, +-16, 52, -10, -9, 12, -57, 44, -69, +70, -47, 77, -2, 58, 48, 20, 79, +-27, 71, -81, 24, -131, -48, -159, -125, +-154, -174, -114, -172, -41, -112, 54, -6, +151, 113, 225, 217, 250, 274, 218, 258, +140, 169, 31, 34, -94, -109, -201, -226, +-263, -291, -266, -286, -210, -213, -115, -93, +2, 41, 120, 156, 213, 228, 249, 244, +218, 211, 143, 136, 48, 39, -49, -58, +-127, -135, -161, -176, -138, -178, -83, -142, +-25, -79, 28, -5, 73, 65, 89, 116, +62, 132, 12, 114, -38, 71, -76, 18, +-97, -37, -82, -78, -26, -89, 54, -72, +121, -36, 153, 6, 152, 39, 113, 50, +36, 41, -63, 18, -145, -8, -186, -31, +-184, -40, -149, -23, -75, 12, 24, 44, +119, 63, 176, 65, 184, 46, 159, 5, +100, -45, 14, -84, -69, -103, -119, -98, +-133, -66, -123, -17, -97, 34, -52, 77, +2, 104, 49, 108, 84, 86, 106, 50, +113, 9, 96, -27, 55, -56, 0, -79, +-48, -91, -85, -92, -103, -77, -103, -51, +-80, -10, -32, 38, 23, 87, 69, 129, +98, 145, 109, 128, 91, 77, 39, -3, +-28, -91, -80, -167, -107, -211, -104, -206, +-74, -144, -15, -35, 58, 89, 111, 198, +133, 267, 128, 274, 99, 213, 37, 92, +-43, -56, -115, -198, -154, -295, -165, -324, +-144, -280, -85, -173, 4, -26, 92, 125, +150, 242, 176, 301, 174, 291, 139, 217, +72, 103, -7, -23, -79, -131, -130, -200, +-162, -214, -163, -173, -129, -97, -71, -10, +-6, 63, 47, 104, 86, 108, 103, 76, +101, 19, 85, -38, 62, -67, 38, -65, +19, -39, 6, 5, -8, 54, -24, 90, +-38, 97, -54, 74, -77, 29, -98, -22, +-102, -64, -78, -85, -32, -84, 32, -59, +99, -21, 155, 16, 172, 35, 141, 31, +74, 13, -5, -10, -84, -22, -146, -17, +-164, 3, -129, 35, -64, 68, 4, 81, +66, 66, 110, 25, 116, -29, 74, -80, +8, -107, -48, -101, -81, -61, -87, 3, +-64, 71, -7, 123, 61, 135, 101, 105, +98, 42, 69, -35, 24, -103, -31, -140, +-82, -140, -103, -99, -90, -31, -62, 36, +-26, 80, 12, 96, 48, 85, 68, 57, +67, 25, 55, 4, 43, 3, 28, 19, +16, 36, 8, 40, 2, 23, -7, -18, +-30, -74, -61, -125, -86, -155, -88, -151, +-70, -106, -33, -29, 19, 59, 76, 133, +119, 176, 128, 183, 99, 155, 51, 99, +-2, 31, -60, -31, -111, -76, -132, -100, +-111, -105, -66, -96, -15, -80, 37, -60, +83, -36, 107, -10, 96, 17, 63, 45, +34, 66, 16, 76, -6, 73, -32, 55, +-49, 23, -60, -7, -81, -32, -103, -48, +-99, -50, -63, -42, -6, -25, 59, -3, +131, 19, 198, 31, 229, 34, 201, 34, +123, 28, 11, 16, -123, -2, -256, -26, +-336, -50, -330, -69, -248, -77, -106, -71, +71, -47, 244, -3, 364, 48, 393, 92, +331, 114, 202, 112, 31, 84, -145, 32, +-281, -28, -342, -78, -318, -99, -225, -85, +-90, -47, 54, -1, 168, 39, 225, 54, +221, 35, 162, -11, 79, -65, -1, -102, +-57, -106, -85, -68, -83, 4, -57, 85, +-22, 151, 5, 182, 9, 163, 5, 93, +-1, -9, -12, -103, -27, -158, -27, -161, +-2, -120, 31, -48, 52, 30, 59, 88, +53, 104, 24, 72, -21, 10, -59, -58, +-66, -103, -51, -115, -24, -82, 9, -18, +50, 59, 82, 124, 82, 157, 55, 154, +18, 117, -23, 60, -66, -3, -97, -60, +-96, -106, -61, -138, -18, -157, 24, -160, +59, -147, 83, -116, 86, -55, 63, 36, +33, 138, 14, 228, 1, 284, -16, 282, +-24, 211, -25, 80, -29, -80, -42, -234, +-48, -339, -46, -364, -34, -296, -17, -152, +1, 29, 26, 197, 55, 311, 78, 345, +81, 290, 65, 165, 38, 7, 11, -138, +-23, -239, -52, -270, -62, -233, -53, -144, +-39, -28, -35, 79, -29, 151, -13, 173, +2, 154, 7, 103, 17, 35, 38, -30, +58, -72, 62, -88, 56, -74, 52, -40, +41, -2, 9, 31, -38, 49, -75, 43, +-98, 16, -105, -28, -93, -71, -47, -94, +20, -89, 81, -55, 115, 1, 135, 68, +134, 127, 97, 156, 34, 141, -37, 86, +-96, 5, -136, -87, -153, -162, -134, -194, +-77, -177, -2, -110, 67, -15, 120, 82, +156, 153, 162, 180, 135, 157, 86, 92, +25, 12, -40, -64, -105, -119, -154, -134, +-178, -119, -164, -81, -119, -36, -51, 5, +31, 42, 111, 69, 170, 87, 196, 97, +181, 102, 130, 95, 60, 64, -19, 7, +-93, -67, -149, -143, -165, -196, -145, -210, +-102, -170, -44, -77, 22, 49, 76, 177, +98, 264, 91, 279, 70, 216, 50, 92, +24, -56, -1, -187, -13, -265, -5, -259, +1, -177, -3, -45, -9, 93, -17, 189, +-29, 215, -49, 162, -57, 53, -40, -72, +-6, -161, 28, -186, 62, -142, 94, -43, +99, 75, 61, 170, 0, 205, -58, 168, +-97, 68, -110, -61, -94, -171, -45, -224, +24, -205, 90, -121, 130, 2, 138, 124, +111, 209, 50, 231, -31, 177, -99, 69, +-136, -54, -139, -153, -108, -204, -59, -195, +-1, -131, 51, -38, 85, 61, 92, 136, +84, 167, 71, 155, 53, 111, 30, 47, +6, -19, -13, -74, -27, -110, -43, -120, +-61, -112, -65, -85, -57, -49, -45, -2, +-33, 47, -15, 89, 15, 115, 45, 112, +62, 87, 71, 45, 75, -3, 62, -46, +33, -77, -3, -84, -25, -69, -36, -45, +-45, -16, -55, 5, -50, 12, -30, 5, +-14, -6, -2, -12, 19, -6, 43, 16, +49, 50, 39, 81, 28, 92, 22, 79, +10, 38, -4, -22, -13, -85, -16, -127, +-21, -139, -30, -118, -26, -66, -10, -3, +11, 54, 27, 88, 38, 97, 46, 88, +42, 64, 25, 37, 4, 18, -23, 13, +-52, 12, -77, 2, -90, -21, -78, -57, +-37, -95, 24, -122, 87, -127, 143, -98, +171, -32, 157, 50, 103, 124, 14, 168, +-86, 162, -167, 110, -217, 31, -223, -51, +-167, -115, -59, -136, 67, -102, 167, -33, +220, 47, 217, 105, 154, 118, 47, 81, +-64, 4, -137, -83, -156, -143, -126, -153, +-63, -104, 19, -14, 88, 84, 114, 158, +83, 179, 17, 143, -54, 57, -113, -49, +-143, -134, -121, -170, -47, -142, 48, -64, +135, 37, 190, 128, 198, 178, 150, 167, +57, 97, -49, -9, -133, -117, -181, -193, +-186, -214, -148, -180, -77, -102, 7, 0, +77, 92, 127, 160, 149, 192, 143, 181, +108, 137, 58, 74, 3, 5, -46, -57, +-83, -109, -105, -144, -110, -157, -97, -147, +-68, -109, -30, -55, 21, 11, 76, 83, +118, 144, 138, 174, 125, 166, 78, 121, +12, 47, -57, -39, -116, -113, -154, -158, +-155, -163, -110, -125, -43, -58, 29, 21, +98, 89, 150, 134, 162, 145, 129, 117, +72, 62, 11, -7, -47, -68, -92, -106, +-114, -121, -101, -111, -68, -77, -41, -28, +-17, 26, 10, 63, 37, 82, 51, 84, +55, 68, 64, 42, 73, 8, 64, -21, +39, -36, 8, -38, -25, -26, -59, -14, +-87, -1, -91, 9, -67, 4, -23, -6, +24, -18, 66, -25, 96, -21, 94, -11, +60, 3, 7, 7, -45, 1, -87, -9, +-104, -25, -81, -41, -23, -37, 45, -7, +106, 50, 138, 115, 131, 168, 89, 183, +16, 143, -69, 51, -143, -81, -182, -221, +-169, -326, -109, -357, -21, -294, 78, -148, +160, 47, 199, 243, 179, 385, 116, 434, +34, 373, -49, 221, -113, 22, -144, -171, +-131, -305, -83, -356, -23, -318, 30, -209, +68, -74, 81, 51, 60, 134, 17, 157, +-15, 134, -26, 92, -20, 53, 2, 35, +33, 40, 61, 61, 63, 76, 35, 63, +-5, 10, -44, -72, -78, -156, -98, -213, +-91, -218, -56, -160, -8, -56, 41, 71, +84, 185, 108, 252, 107, 253, 82, 183, +46, 72, 7, -47, -30, -145, -59, -193, +-82, -184, -95, -130, -94, -56, -80, 5, +-52, 45, -12, 60, 34, 53, 86, 41, +131, 32, 156, 41, 150, 62, 110, 79, +42, 79, -42, 49, -124, -7, -180, -77, +-194, -139, -165, -170, -98, -158, -8, -101, +89, -9, 156, 86, 181, 160, 164, 184, +110, 159, 32, 95, -52, 7, -105, -73, +-117, -130, -94, -144, -50, -117, 1, -63, +45, 4, 66, 62, 54, 93, 24, 100, +-10, 78, -37, 43, -53, 0, -54, -38, +-29, -60, 4, -75, 35, -76, 55, -69, +62, -51, 55, -18, 34, 22, 10, 62, +-3, 96, -10, 113, -13, 111, -18, 85, +-25, 35, -28, -23, -41, -80, -54, -116, +-62, -130, -57, -118, -36, -83, -3, -37, +42, 17, 91, 63, 129, 91, 146, 104, +134, 97, 89, 82, 21, 58, -61, 19, +-130, -22, -181, -64, -193, -94, -159, -110, +-92, -102, -7, -65, 79, -13, 150, 48, +185, 101, 171, 126, 121, 119, 54, 71, +-16, -6, -70, -79, -107, -133, -107, -145, +-77, -111, -43, -37, -10, 56, 12, 133, +15, 176, 0, 167, -20, 106, -26, 10, +-8, -91, 20, -161, 54, -177, 83, -145, +106, -73, 101, 9, 63, 81, 4, 122, +-64, 114, -118, 74, -152, 16, -145, -32, +-90, -54, -14, -42, 59, -3, 117, 43, +141, 73, 124, 73, 72, 30, 7, -38, +-54, -106, -97, -149, -106, -146, -82, -96, +-32, -4, 25, 100, 71, 184, 88, 221, +76, 189, 41, 102, -9, -14, -60, -132, +-84, -214, -82, -239, -59, -197, -12, -100, +35, 19, 76, 137, 91, 215, 81, 236, +52, 194, 7, 102, -33, -10, -60, -116, +-75, -188, -67, -207, -42, -180, -6, -113, +28, -24, 47, 61, 59, 128, 56, 157, +40, 153, 12, 115, -16, 56, -30, -3, +-34, -52, -34, -81, -27, -88, -13, -76, +-3, -51, -3, -26, -4, -10, 1, 4, +3, 8, 11, 15, 27, 24, 42, 35, +57, 51, 56, 62, 35, 63, 5, 39, +-29, -6, -64, -53, -93, -94, -100, -108, +-78, -85, -44, -40, 10, 25, 69, 83, +114, 121, 135, 123, 120, 80, 84, 13, +29, -66, -30, -128, -74, -155, -101, -137, +-104, -75, -85, 10, -57, 86, -20, 136, +14, 143, 40, 115, 58, 59, 64, -6, +69, -55, 65, -85, 54, -82, 37, -59, +9, -31, -25, -5, -55, 1, -77, -7, +-87, -16, -79, -22, -45, -12, 0, 12, +45, 42, 85, 70, 104, 78, 96, 70, +57, 37, 5, -7, -44, -49, -80, -82, +-92, -88, -80, -70, -48, -32, 1, 15, +45, 45, 74, 54, 92, 45, 81, 24, +48, 5, 2, -15, -35, -20, -61, -10, +-78, 2, -74, 14, -58, 14, -34, 5, +-4, -9, 22, -24, 48, -28, 71, -24, +83, -7, 85, 22, 67, 42, 43, 56, +7, 47, -41, 22, -83, -9, -113, -44, +-119, -66, -102, -70, -66, -52, -13, -22, +48, 7, 100, 30, 136, 42, 144, 35, +130, 30, 89, 25, 29, 25, -31, 32, +-92, 35, -134, 36, -152, 15, -146, -19, +-112, -63, -55, -106, 18, -121, 86, -106, +140, -61, 173, 10, 168, 82, 126, 143, +53, 167, -35, 139, -101, 74, -146, -12, +-157, -86, -127, -132, -64, -141, 13, -106, +78, -47, 114, 18, 119, 65, 82, 76, +23, 64, -37, 30, -76, -9, -74, -30, +-47, -31, 0, -5, 51, 26, 84, 49, +87, 56, 49, 35, -9, -1, -69, -41, +-121, -73, -133, -81, -99, -68, -29, -30, +58, 14, 135, 43, 186, 58, 180, 48, +118, 30, 23, 9, -83, -12, -165, -14, +-202, -7, -187, 7, -121, 21, -23, 17, +86, 5, 164, -13, 191, -31, 173, -38, +105, -40, 14, -25, -72, -7, -130, 7, +-142, 22, -115, 25, -54, 24, 14, 19, +65, 17, 94, 27, 79, 33, 29, 31, +-19, 20, -63, -7, -83, -35, -67, -67, +-18, -83, 49, -72, 106, -42, 143, 8, +134, 56, 78, 91, -6, 99, -103, 70, +-183, 19, -212, -42, -179, -90, -95, -101, +14, -75, 131, -13, 217, 56, 237, 106, +202, 126, 113, 93, -3, 25, -112, -60, +-189, -131, -214, -156, -183, -134, -104, -66, +-3, 24, 79, 105, 137, 157, 151, 155, +113, 101, 62, 18, 13, -70, -25, -120, +-44, -126, -35, -89, -11, -22, 2, 44, +7, 88, -3, 88, -35, 46, -63, -16, +-76, -84, -64, -122, -20, -110, 40, -56, +107, 34, 146, 116, 151, 172, 114, 175, +32, 114, -56, 19, -131, -88, -181, -167, +-177, -198, -119, -177, -27, -105, 69, -10, +149, 83, 193, 151, 170, 166, 108, 138, +24, 75, -71, 6, -141, -49, -169, -88, +-146, -91, -85, -72, -3, -45, 80, -16, +129, 0, 147, 8, 130, 13, 68, 8, +3, 7, -50, 4, -88, 10, -99, 21, +-87, 26, -50, 38, -13, 40, 19, 37, +43, 29, 47, 7, 40, -18, 27, -49, +8, -81, 1, -100, 2, -103, 8, -76, +12, -24, 8, 42, 5, 115, -15, 164, +-35, 181, -47, 156, -51, 89, -36, -2, +-4, -97, 31, -169, 65, -197, 81, -185, +79, -129, 47, -58, -7, 9, -53, 62, +-91, 86, -100, 98, -74, 98, -19, 100, +52, 111, 110, 115, 141, 108, 129, 73, +74, 4, -3, -88, -93, -191, -158, -267, +-174, -288, -152, -244, -82, -126, 12, 27, +108, 186, 178, 303, 193, 340, 160, 299, +88, 180, -2, 25, -82, -122, -135, -227, +-141, -256, -106, -217, -57, -131, 6, -26, +54, 54, 80, 101, 76, 97, 47, 56, +15, 11, -19, -28, -33, -37, -29, -18, +-14, 15, 16, 48, 42, 58, 49, 48, +42, 19, 23, -22, 3, -46, -24, -49, +-38, -24, -38, 22, -45, 59, -41, 76, +-35, 50, -33, -11, -24, -90, -10, -163, +12, -192, 41, -163, 74, -74, 109, 59, +117, 186, 109, 279, 81, 299, 19, 235, +-52, 111, -125, -52, -179, -199, -199, -294, +-172, -314, -100, -250, -10, -134, 93, 6, +187, 128, 229, 202, 225, 222, 176, 186, +84, 116, -24, 40, -127, -29, -187, -70, +-207, -91, -177, -87, -106, -68, -24, -58, +63, -50, 130, -45, 146, -35, 123, -12, +80, 16, 23, 53, -35, 92, -69, 107, +-58, 107, -34, 75, -1, 31, 38, -23, +50, -78, 39, -117, 9, -140, -33, -131, +-74, -94, -94, -38, -74, 29, -31, 90, +29, 133, 103, 150, 142, 134, 139, 97, +100, 36, 29, -37, -56, -95, -133, -132, +-169, -136, -162, -113, -115, -63, -28, 4, +55, 56, 123, 85, 173, 86, 170, 60, +126, 29, 58, -6, -11, -24, -74, -19, +-122, -5, -132, 22, -125, 36, -103, 31, +-57, 8, -14, -32, 26, -67, 74, -88, +112, -81, 131, -39, 130, 14, 123, 70, +89, 106, 20, 106, -42, 71, -102, 3, +-150, -65, -170, -116, -154, -133, -103, -102, +-35, -37, 43, 45, 112, 116, 148, 154, +161, 155, 138, 107, 86, 25, 38, -60, +-14, -133, -61, -166, -97, -162, -110, -119, +-105, -47, -95, 26, -61, 90, -13, 127, +32, 137, 80, 123, 111, 84, 118, 34, +106, -17, 63, -67, 4, -101, -65, -126, +-114, -123, -133, -92, -127, -43, -74, 26, +8, 88, 89, 136, 154, 158, 174, 138, +145, 84, 76, 3, -18, -84, -107, -151, +-177, -189, -194, -173, -165, -116, -101, -33, +-4, 61, 87, 132, 157, 172, 188, 167, +174, 130, 130, 72, 61, 6, -5, -46, +-58, -80, -103, -98, -116, -98, -116, -100, +-111, -93, -91, -80, -66, -63, -27, -23, +13, 28, 60, 90, 112, 148, 147, 179, +164, 178, 152, 131, 103, 44, 39, -56, +-46, -151, -127, -208, -178, -212, -197, -164, +-167, -69, -108, 31, -19, 119, 73, 165, +137, 162, 171, 123, 162, 52, 116, -20, +58, -73, -9, -102, -65, -93, -99, -68, +-100, -39, -75, -8, -47, 8, 1, 18, +39, 21, 52, 31, 53, 49, 34, 65, +7, 77, -13, 70, -23, 39, -20, -9, +-13, -67, 2, -116, 18, -145, 19, -148, +26, -106, 21, -44, 8, 31, 2, 99, +-6, 143, -11, 164, -14, 146, -9, 106, +-8, 51, -19, -10, -18, -62, -17, -103, +-19, -128, 5, -132, 39, -119, 70, -83, +87, -39, 88, 8, 68, 51, 10, 74, +-53, 86, -115, 80, -166, 58, -164, 34, +-117, 10, -40, -1, 73, 1, 184, 7, +256, 19, 257, 18, 198, 2, 85, -29, +-74, -79, -207, -119, -289, -142, -307, -128, +-243, -74, -114, 1, 43, 92, 181, 169, +274, 209, 299, 204, 233, 143, 122, 51, +-5, -52, -140, -142, -218, -189, -225, -191, +-174, -143, -85, -63, 24, 22, 118, 90, +159, 120, 156, 112, 114, 73, 32, 16, +-45, -29, -99, -54, -134, -50, -130, -20, +-88, 13, -19, 42, 44, 46, 102, 27, +149, -9, 149, -50, 120, -71, 71, -69, +0, -42, -67, 10, -120, 62, -155, 97, +-162, 96, -136, 59, -75, 4, -13, -67, +61, -118, 140, -135, 180, -113, 184, -47, +156, 32, 95, 106, 13, 155, -70, 158, +-134, 120, -174, 46, -178, -41, -135, -110, +-80, -150, -5, -144, 82, -106, 143, -44, +169, 28, 155, 82, 111, 111, 35, 101, +-49, 62, -105, 8, -136, -48, -131, -84, +-81, -85, -18, -57, 53, -2, 112, 54, +139, 94, 124, 103, 66, 74, -6, 19, +-89, -55, -145, -117, -149, -145, -113, -129, +-41, -68, 52, 18, 129, 103, 167, 164, +153, 166, 100, 117, 14, 27, -81, -80, +-137, -158, -160, -191, -132, -154, -60, -61, +24, 58, 101, 164, 143, 219, 137, 207, +86, 125, 8, -4, -63, -133, -113, -225, +-126, -249, -84, -192, -27, -84, 41, 49, +93, 160, 112, 216, 97, 204, 46, 128, +-14, 23, -69, -82, -100, -151, -92, -160, +-60, -112, -9, -27, 53, 64, 91, 122, +105, 138, 85, 101, 41, 30, -13, -55, +-61, -125, -85, -151, -94, -135, -81, -77, +-51, 2, -21, 75, 15, 123, 51, 132, +71, 105, 85, 58, 88, -1, 84, -43, +64, -61, 33, -54, 2, -21, -46, 10, +-88, 28, -115, 22, -132, -4, -129, -38, +-99, -75, -44, -99, 23, -96, 90, -65, +151, -6, 175, 61, 170, 121, 148, 159, +90, 161, 20, 131, -53, 68, -120, -6, +-173, -79, -199, -138, -185, -166, -144, -161, +-79, -124, 8, -62, 85, 5, 153, 66, +209, 107, 225, 122, 200, 114, 139, 78, +60, 32, -43, -15, -146, -52, -211, -71, +-243, -69, -228, -46, -159, -14, -64, 19, +40, 45, 140, 55, 208, 46, 230, 21, +205, -17, 151, -49, 58, -74, -51, -74, +-137, -52, -196, -23, -207, 16, -168, 54, +-92, 77, 1, 79, 91, 62, 160, 34, +183, 0, 157, -35, 113, -58, 36, -72, +-46, -69, -102, -48, -134, -15, -136, 21, +-106, 48, -44, 63, 15, 57, 58, 34, +91, 2, 94, -30, 73, -58, 57, -66, +33, -55, 3, -23, -20, 15, -33, 47, +-46, 66, -61, 60, -53, 39, -42, 7, +-34, -23, -7, -39, 20, -32, 31, -7, +46, 23, 53, 38, 49, 36, 27, 11, +3, -29, -19, -71, -41, -103, -33, -102, +-12, -68, 4, -3, 25, 73, 37, 135, +26, 169, -2, 157, -27, 102, -47, 22, +-65, -61, -59, -123, -33, -153, -5, -149, +35, -109, 68, -57, 87, -7, 87, 32, +73, 61, 42, 74, 2, 75, -24, 76, +-45, 81, -69, 78, -73, 61, -65, 26, +-65, -24, -60, -77, -46, -129, -14, -155, +22, -148, 70, -100, 120, -19, 138, 73, +136, 151, 109, 189, 49, 177, -22, 115, +-90, 22, -143, -75, -166, -149, -152, -181, +-96, -156, -32, -89, 41, -2, 108, 75, +133, 119, 130, 123, 99, 84, 48, 25, +-3, -37, -42, -76, -57, -81, -54, -53, +-36, -3, -7, 53, 9, 88, 20, 92, +27, 57, 12, -1, -11, -60, -39, -110, +-61, -127, -70, -114, -59, -71, -23, -13, +24, 45, 72, 94, 114, 124, 132, 124, +130, 103, 102, 63, 45, 22, -29, -19, +-103, -61, -154, -94, -179, -117, -160, -118, +-105, -103, -29, -71, 58, -27, 129, 22, +162, 70, 157, 106, 112, 120, 48, 111, +-17, 85, -67, 49, -89, 17, -91, -17, +-59, -38, -18, -56, 15, -71, 39, -80, +32, -88, 7, -90, -20, -78, -47, -45, +-51, 8, -34, 69, 4, 123, 57, 155, +85, 151, 99, 112, 81, 36, 35, -53, +-15, -130, -62, -172, -93, -163, -101, -109, +-79, -24, -32, 63, 20, 126, 66, 148, +96, 125, 87, 61, 62, -18, 26, -90, +-21, -125, -57, -119, -69, -77, -62, -16, +-43, 34, -6, 66, 26, 70, 40, 54, +46, 25, 44, 4, 26, -8, 9, 0, +-2, 19, -11, 37, -16, 39, -8, 18, +1, -19, -6, -68, -10, -107, -16, -127, +-30, -111, -35, -59, -24, 13, -5, 90, +15, 151, 37, 172, 61, 152, 61, 90, +52, 6, 38, -75, 1, -137, -31, -156, +-55, -137, -69, -85, -64, -15, -43, 55, +-8, 104, 19, 119, 39, 99, 56, 54, +38, 1, 6, -44, -16, -73, -35, -80, +-39, -60, -21, -29, 15, 5, 46, 32, +68, 51, 74, 53, 48, 42, 2, 25, +-42, 8, -87, -6, -112, -14, -96, -14, +-54, -18, 6, -22, 67, -32, 114, -43, +120, -53, 91, -56, 43, -46, -15, -21, +-67, 22, -91, 74, -83, 123, -56, 147, +-7, 138, 42, 92, 66, 18, 60, -76, +46, -164, 10, -221, -31, -225, -53, -174, +-52, -76, -31, 50, -1, 170, 37, 255, +51, 274, 45, 223, 30, 113, -4, -23, +-39, -153, -48, -235, -48, -253, -29, -206, +5, -110, 38, 8, 56, 115, 49, 176, +38, 184, 8, 146, -34, 79, -53, 1, +-54, -63, -41, -96, -9, -98, 21, -74, +44, -36, 48, -6, 36, 12, 14, 18, +-21, 14, -39, 11, -42, 11, -36, 22, +-11, 34, 20, 45, 39, 47, 44, 37, +36, 16, 14, -12, -18, -36, -44, -56, +-54, -65, -54, -63, -36, -46, -4, -24, +28, 4, 56, 27, 76, 52, 69, 70, +43, 78, 11, 74, -29, 51, -60, 14, +-72, -32, -71, -72, -55, -102, -23, -107, +12, -83, 44, -30, 62, 32, 69, 88, +57, 120, 29, 115, 1, 75, -30, 10, +-48, -56, -46, -108, -36, -121, -16, -93, +2, -33, 8, 36, 15, 97, 7, 124, +-1, 112, -4, 60, -4, -12, 5, -77, +14, -118, 27, -118, 40, -86, 40, -26, +27, 33, 5, 76, -24, 87, -43, 71, +-58, 37, -52, -2, -29, -32, -2, -43, +33, -33, 51, -14, 54, 6, 48, 11, +31, 1, 1, -20, -22, -39, -40, -49, +-46, -37, -40, -2, -21, 46, -2, 89, +15, 111, 33, 100, 38, 54, 33, -9, +22, -79, 11, -125, -9, -138, -24, -111, +-33, -54, -47, 17, -52, 79, -43, 113, +-24, 114, 5, 79, 42, 29, 74, -15, +88, -40, 79, -46, 64, -27, 21, 1, +-36, 25, -80, 27, -113, 6, -121, -30, +-100, -64, -56, -80, 0, -76, 53, -43, +98, 8, 117, 63, 103, 102, 81, 121, +39, 112, -17, 77, -49, 22, -64, -36, +-67, -83, -60, -105, -50, -99, -40, -81, +-31, -52, -13, -18, 3, 17, 15, 44, +41, 67, 66, 78, 78, 79, 84, 67, +73, 39, 41, 0, -4, -46, -53, -78, +-97, -94, -124, -88, -121, -59, -87, -7, +-42, 48, 14, 90, 75, 106, 118, 95, +128, 59, 115, 5, 81, -51, 24, -93, +-24, -106, -64, -93, -91, -55, -101, -14, +-80, 24, -52, 48, -25, 56, 10, 50, +41, 36, 51, 24, 58, 17, 62, 19, +49, 24, 40, 27, 27, 15, 15, -9, +-4, -43, -24, -71, -48, -92, -72, -93, +-86, -69, -82, -27, -66, 22, -29, 66, +28, 97, 79, 103, 127, 87, 145, 51, +141, 10, 96, -29, 21, -48, -63, -56, +-139, -52, -185, -38, -185, -21, -140, -7, +-68, -5, 30, -10, 118, -18, 174, -19, +188, -14, 165, 6, 103, 31, 20, 61, +-59, 86, -125, 97, -160, 84, -153, 42, +-117, -15, -72, -81, -21, -133, 22, -159, +54, -147, 85, -101, 113, -22, 132, 69, +136, 152, 115, 203, 72, 205, 8, 156, +-73, 59, -146, -57, -198, -164, -220, -224, +-191, -234, -113, -180, -3, -83, 113, 34, +209, 136, 259, 197, 244, 202, 177, 156, +73, 79, -48, -9, -140, -76, -187, -109, +-193, -102, -153, -70, -91, -27, -30, 0, +24, -1, 58, -24, 72, -54, 70, -71, +65, -61, 65, -11, 64, 66, 68, 147, +63, 198, 39, 201, -8, 141, -70, 29, +-122, -109, -142, -225, -135, -277, -90, -249, +-13, -148, 65, -4, 133, 140, 166, 234, +152, 255, 92, 188, 14, 66, -74, -73, +-137, -177, -156, -213, -129, -170, -65, -65, +14, 63, 88, 168, 128, 205, 134, 169, +99, 66, 41, -61, -29, -171, -77, -220, +-103, -197, -92, -105, -56, 23, -10, 138, +40, 204, 67, 201, 71, 136, 47, 27, +7, -87, -38, -170, -59, -193, -63, -157, +-41, -71, 1, 32, 45, 120, 73, 166, +83, 159, 77, 106, 40, 28, -4, -45, +-45, -100, -85, -115, -103, -101, -89, -59, +-58, -11, -18, 25, 28, 42, 60, 38, +68, 22, 62, 2, 47, -13, 28, -20, +12, -6, 0, 18, -9, 47, -13, 64, +-10, 64, -5, 44, -9, 11, -18, -30, +-27, -66, -34, -92, -36, -101, -25, -89, +0, -63, 25, -27, 43, 12, 56, 50, +45, 73, 20, 84, 2, 78, -19, 65, +-34, 51, -28, 36, -16, 24, -5, 5, +12, -13, 24, -38, 18, -63, 4, -93, +-8, -112, -30, -114, -44, -88, -37, -40, +-20, 27, 5, 96, 35, 145, 49, 166, +42, 146, 25, 94, -2, 14, -17, -65, +-31, -126, -31, -144, -17, -120, -1, -61, +15, 9, 35, 65, 39, 91, 24, 72, +5, 25, -22, -36, -44, -82, -57, -96, +-40, -68, -25, -6, 0, 73, 26, 136, +38, 159, 35, 128, 32, 50, 24, -50, +3, -144, 1, -193, -5, -190, -5, -128, +-2, -27, 2, 85, -3, 171, -6, 205, +-10, 177, -20, 105, -32, 9, -34, -86, +-21, -151, -5, -173, 15, -144, 19, -85, +18, -13, 14, 44, 5, 86, 8, 103, +13, 96, 17, 77, 30, 55, 31, 34, +19, 16, 7, -2, -15, -31, -44, -60, +-64, -89, -73, -104, -66, -101, -42, -74, +2, -29, 41, 27, 64, 80, 78, 116, +64, 125, 33, 103, 5, 63, -27, 15, +-52, -27, -49, -60, -36, -67, -14, -59, +10, -39, 25, -20, 32, -2, 22, 8, +3, 6, -16, 4, -37, -3, -52, -6, +-50, -8, -32, -5, -8, -1, 17, 12, +41, 26, 61, 39, 70, 46, 80, 50, +70, 47, 31, 27, -9, -5, -58, -49, +-105, -85, -125, -110, -115, -109, -85, -79, +-25, -20, 40, 46, 104, 104, 149, 136, +157, 131, 125, 90, 49, 19, -34, -55, +-114, -114, -164, -133, -168, -114, -126, -58, +-57, 13, 35, 76, 105, 113, 151, 115, +161, 84, 116, 30, 58, -23, -17, -63, +-86, -78, -124, -74, -126, -50, -112, -26, +-68, -8, -13, -2, 34, -1, 61, 1, +74, 9, 79, 28, 63, 55, 54, 84, +40, 95, 19, 81, -2, 41, -29, -13, +-63, -76, -73, -123, -74, -141, -66, -122, +-43, -68, -22, -1, 12, 64, 43, 105, +65, 112, 78, 83, 72, 35, 49, -21, +21, -57, -7, -62, -30, -38, -46, 1, +-50, 44, -45, 73, -44, 71, -25, 42, +2, -5, 8, -53, 25, -92, 35, -105, +22, -90, 12, -51, 5, -7, -6, 35, +-6, 63, 2, 72, 14, 68, 23, 56, +22, 45, 15, 32, -7, 22, -27, 3, +-41, -18, -55, -48, -52, -76, -35, -99, +-3, -103, 43, -79, 77, -30, 97, 37, +96, 97, 57, 139, 11, 136, -30, 95, +-75, 20, -94, -62, -98, -134, -86, -171, +-58, -158, -15, -95, 33, -1, 68, 102, +96, 187, 103, 222, 84, 202, 60, 119, +41, 6, -8, -113, -48, -205, -82, -253, +-113, -240, -117, -168, -96, -62, -53, 58, +6, 157, 67, 219, 109, 228, 132, 188, +112, 107, 74, 16, 8, -70, -55, -127, +-95, -149, -108, -134, -84, -93, -42, -42, +11, 8, 55, 37, 72, 46, 60, 33, +39, 14, -17, -5, -54, -6, -60, 8, +-52, 37, -12, 68, 38, 85, 65, 79, +70, 38, 54, -23, 12, -91, -39, -140, +-80, -160, -90, -134, -80, -66, -35, 28, +40, 116, 100, 178, 140, 189, 139, 144, +89, 58, 15, -49, -69, -142, -138, -197, +-168, -191, -165, -135, -117, -41, -33, 60, +47, 141, 123, 177, 167, 165, 161, 110, +125, 31, 64, -45, -1, -100, -61, -117, +-98, -101, -103, -59, -98, -16, -75, 24, +-39, 42, -23, 33, 0, 9, 27, -11, +29, -20, 45, -15, 61, 5, 60, 29, +57, 52, 44, 55, 26, 43, 5, 12, +-22, -20, -47, -47, -66, -56, -75, -44, +-61, -21, -34, 3, 4, 18, 35, 21, +43, 8, 52, -11, 39, -33, 27, -40, +21, -33, 1, -7, -17, 26, -16, 51, +-24, 65, -24, 61, -13, 39, -16, 2, +-8, -32, -7, -51, 3, -49, 15, -37, +37, -12, 54, 11, 55, 25, 46, 18, +32, -7, -6, -37, -50, -61, -79, -63, +-114, -46, -109, -8, -84, 37, -38, 81, +26, 110, 88, 115, 139, 88, 180, 43, +174, -13, 126, -66, 52, -102, -49, -120, +-134, -109, -199, -82, -218, -42, -194, -2, +-138, 35, -45, 58, 53, 70, 139, 72, +208, 70, 216, 60, 178, 47, 117, 36, +22, 23, -65, 11, -124, -13, -163, -39, +-163, -73, -138, -101, -91, -116, -33, -112, +25, -84, 80, -30, 112, 42, 121, 113, +117, 165, 90, 180, 50, 157, 0, 89, +-63, 1, -101, -97, -124, -170, -125, -196, +-84, -169, -34, -94, 25, 7, 92, 103, +127, 161, 124, 170, 93, 123, 27, 41, +-44, -53, -98, -119, -118, -142, -103, -113, +-63, -44, 3, 41, 53, 115, 79, 143, +91, 117, 56, 48, -3, -38, -53, -116, +-88, -154, -85, -140, -37, -74, 20, 19, +82, 112, 111, 165, 103, 165, 71, 114, +0, 25, -70, -68, -127, -138, -155, -157, +-144, -129, -85, -66, -3, 5, 83, 65, +137, 90, 169, 80, 151, 43, 93, 0, +36, -22, -43, -22, -104, 7, -130, 47, +-132, 82, -113, 79, -59, 42, -9, -27, +37, -106, 76, -169, 96, -188, 96, -154, +68, -69, 37, 43, -3, 144, -36, 211, +-48, 216, -46, 164, -40, 70, -23, -31, +-18, -113, -5, -155, 9, -148, 2, -99, +4, -33, -3, 24, -10, 60, 4, 63, +14, 41, 23, 1, 36, -29, 27, -45, +5, -31, -17, 1, -29, 39, -33, 69, +-34, 80, -17, 71, -3, 37, 4, -5, +24, -49, 21, -76, 7, -88, 0, -74, +-17, -50, -26, -17, -12, 20, 0, 49, +15, 65, 28, 64, 29, 51, 24, 26, +-2, 3, -27, -21, -42, -40, -44, -53, +-22, -51, 4, -43, 30, -25, 49, -9, +46, 5, 35, 23, 12, 34, -21, 44, +-32, 46, -42, 49, -48, 44, -20, 31, +2, 3, 20, -36, 35, -82, 26, -120, +-1, -135, -23, -121, -26, -75, -13, 0, +12, 96, 39, 176, 59, 223, 51, 217, +40, 152, 2, 42, -47, -84, -85, -197, +-113, -261, -110, -256, -72, -185, -18, -66, +45, 64, 105, 171, 123, 222, 127, 212, +89, 141, 35, 43, -20, -51, -70, -112, +-99, -125, -103, -97, -79, -43, -49, 12, +-24, 49, -2, 50, 17, 25, 13, -20, +23, -51, 21, -58, 16, -33, 35, 13, +54, 66, 65, 106, 70, 108, 50, 69, +6, -1, -44, -78, -95, -139, -120, -159, +-122, -131, -98, -56, -50, 35, 8, 122, +71, 172, 114, 169, 131, 122, 114, 36, +59, -55, -2, -129, -57, -161, -99, -148, +-105, -91, -81, -15, -53, 62, -3, 112, +42, 127, 63, 103, 70, 51, 53, -7, +16, -60, -27, -87, -54, -93, -66, -69, +-63, -26, -41, 24, -6, 65, 19, 93, +45, 92, 57, 69, 43, 26, 26, -29, +2, -76, -19, -110, -28, -116, -35, -98, +-28, -51, -13, 10, -5, 75, 8, 121, +16, 141, 8, 124, -7, 77, -25, 9, +-38, -62, -41, -113, -31, -140, -11, -126, +-1, -85, 20, -20, 38, 44, 43, 94, +50, 120, 52, 115, 27, 84, 4, 41, +-21, -2, -55, -45, -67, -78, -80, -95, +-82, -92, -79, -82, -52, -56, -14, -24, +32, 18, 74, 60, 111, 95, 123, 119, +107, 121, 72, 96, 12, 46, -42, -18, +-102, -82, -130, -128, -131, -152, -107, -138, +-55, -100, 9, -39, 55, 26, 93, 78, +109, 112, 79, 120, 36, 107, -18, 77, +-64, 45, -91, 10, -76, -21, -45, -49, +-12, -67, 28, -85, 61, -96, 70, -93, +70, -77, 53, -36, 5, 17, -37, 72, +-71, 111, -93, 128, -92, 114, -78, 71, +-53, 8, -22, -54, 11, -102, 50, -121, +87, -107, 110, -65, 112, -2, 87, 56, +36, 95, -26, 100, -84, 78, -127, 32, +-149, -18, -131, -57, -84, -72, -26, -65, +40, -39, 92, -6, 107, 20, 101, 31, +78, 24, 25, 15, -27, 0, -61, -6, +-76, -3, -68, 12, -38, 30, -5, 40, +13, 40, 17, 24, 6, -10, -10, -49, +-17, -77, -19, -89, -16, -74, -5, -39, +12, 11, 21, 56, 30, 89, 26, 96, +11, 74, -8, 36, -38, -8, -55, -45, +-50, -68, -39, -65, -26, -46, 0, -17, +19, 5, 37, 23, 44, 28, 45, 19, +30, 5, 10, -11, -10, -18, -41, -13, +-59, 4, -70, 20, -69, 31, -56, 30, +-23, 22, 5, 0, 39, -24, 62, -44, +64, -47, 52, -35, 25, -12, -6, 18, +-37, 43, -57, 62, -70, 59, -58, 34, +-33, -4, -3, -40, 19, -69, 30, -79, +20, -68, 4, -35, -5, 7, -21, 50, +-28, 83, -22, 90, -14, 76, -6, 40, +12, -5, 18, -50, 16, -78, 8, -84, +-12, -67, -28, -33, -34, 7, -32, 40, +-25, 60, -18, 62, -8, 45, -4, 21, +-2, -10, 4, -32, 5, -43, 7, -37, +4, -22, -2, -7, 1, 6, -4, 15, +-14, 17, -17, 14, -25, 15, -29, 18, +-24, 25, -22, 22, -14, 13, 2, -3, +11, -22, 5, -42, 1, -61, -3, -64, +-18, -46, -32, -9, -32, 41, -28, 89, +-16, 116, 2, 114, 8, 77, 15, 16, +18, -56, 11, -113, -8, -138, -29, -128, +-46, -81, -60, -13, -54, 57, -33, 106, +1, 123, 28, 104, 47, 60, 52, -1, +46, -51, 24, -80, -4, -78, -35, -50, +-65, -13, -81, 20, -78, 32, -57, 24, +-29, -4, 14, -36, 44, -55, 56, -46, +57, -11, 43, 41, 15, 89, -8, 119, +-31, 112, -51, 65, -51, -12, -46, -98, +-40, -161, -33, -184, -18, -152, -11, -75, +-5, 30, 1, 129, 7, 191, 14, 199, +22, 154, 31, 67, 29, -38, 17, -121, +-12, -165, -45, -155, -71, -108, -83, -33, +-78, 41, -57, 94, -30, 111, 7, 92, +42, 48, 60, -3, 71, -46, 60, -67, +26, -60, -15, -38, -48, -7, -72, 19, +-82, 38, -73, 44, -59, 41, -44, 32, +-15, 21, 11, 9, 27, -4, 40, -13, +37, -28, 26, -45, 19, -62, 6, -66, +-11, -60, -28, -32, -45, 8, -51, 55, +-52, 95, -44, 113, -29, 110, -15, 79, +0, 29, 8, -34, 20, -92, 22, -130, +8, -131, -14, -104, -32, -54, -43, 1, +-32, 53, -16, 93, 1, 108, 23, 103, +31, 70, 28, 25, 14, -19, -9, -52, +-49, -73, -79, -73, -96, -55, -90, -28, +-60, -3, -9, 19, 41, 31, 75, 27, +95, 15, 84, -4, 51, -12, -4, -10, +-61, 5, -104, 22, -117, 42, -108, 53, +-76, 49, -30, 25, 16, -16, 54, -59, +69, -93, 61, -102, 32, -88, 3, -45, +-31, 14, -52, 76, -62, 118, -64, 133, +-60, 114, -47, 64, -33, 2, -21, -58, +4, -99, 29, -112, 45, -92, 49, -52, +44, -5, 26, 29, 1, 43, -31, 38, +-70, 22, -100, 2, -115, -6, -109, 4, +-75, 24, -24, 49, 25, 68, 61, 70, +78, 41, 82, -9, 72, -70, 44, -117, +9, -142, -25, -131, -50, -82, -71, -8, +-85, 74, -83, 134, -79, 158, -65, 138, +-45, 82, -25, 5, 1, -65, 32, -116, +48, -133, 61, -113, 64, -64, 46, 1, +21, 59, -11, 98, -36, 107, -62, 89, +-80, 45, -79, -6, -71, -53, -53, -84, +-35, -96, -22, -79, -8, -44, 3, -2, +7, 38, 14, 67, 14, 82, 14, 75, +19, 56, 10, 23, 10, -11, 3, -37, +-12, -50, -27, -52, -36, -45, -43, -34, +-54, -21, -62, -11, -63, -6, -61, -4, +-48, -4, -15, 4, 2, 18, 35, 43, +55, 65, 61, 75, 57, 64, 37, 36, +1, -4, -43, -53, -80, -97, -102, -119, +-98, -107, -83, -69, -46, -9, -15, 52, +23, 99, 50, 112, 57, 92, 45, 51, +14, -1, -22, -46, -54, -70, -75, -64, +-78, -34, -59, 6, -49, 41, -27, 62, +-3, 49, 19, 14, 31, -30, 29, -65, +21, -82, 8, -76, -1, -36, -18, 19, +-35, 72, -46, 101, -54, 104, -70, 74, +-73, 21, -62, -39, -46, -85, -21, -107, +4, -98, 27, -63, 45, -13, 53, 39, +50, 74, 38, 86, 19, 71, -13, 42, +-47, 6, -73, -24, -89, -42, -97, -43, +-96, -34, -83, -19, -56, -4, -24, 1, +1, -1, 33, -11, 60, -16, 71, -21, +68, -13, 54, 10, 24, 39, -9, 60, +-36, 71, -61, 69, -83, 46, -95, 6, +-100, -39, -101, -78, -81, -108, -54, -116, +-23, -99, 12, -55, 42, 2, 67, 63, +75, 112, 73, 135, 58, 126, 29, 88, +-8, 35, -55, -23, -90, -72, -110, -100, +-114, -97, -108, -73, -90, -36, -69, 0, +-29, 26, 6, 30, 36, 15, 68, -3, +75, -19, 76, -21, 64, -5, 43, 31, +7, 73, -41, 103, -90, 101, -123, 74, +-148, 19, -141, -56, -114, -126, -66, -167, +7, -166, 64, -126, 114, -46, 132, 46, +119, 123, 70, 164, -1, 165, -86, 122, +-145, 51, -180, -23, -176, -78, -132, -102, +-62, -98, 26, -67, 92, -26, 142, 11, +145, 29, 105, 28, 32, 13, -57, -4, +-133, -17, -171, -11, -182, 13, -156, 40, +-89, 59, -15, 64, 55, 49, 102, 9, +120, -40, 108, -80, 70, -96, 11, -86, +-48, -46, -98, 9, -121, 64, -131, 99, +-120, 104, -84, 79, -53, 28, -14, -34, +25, -85, 55, -106, 75, -98, 73, -61, +53, -3, 21, 59, -23, 101, -70, 112, +-104, 91, -122, 43, -113, -18, -86, -74, +-49, -106, 0, -110, 41, -81, 68, -29, +65, 32, 38, 82, 6, 111, -38, 111, +-68, 82, -80, 34, -86, -22, -74, -70, +-54, -105, -25, -116, 6, -102, 24, -59, +29, -7, 17, 44, 4, 84, -5, 106, +-18, 105, -28, 79, -35, 40, -40, -7, +-42, -50, -52, -81, -62, -87, -56, -80, +-45, -62, -31, -37, -13, -2, 1, 31, +21, 53, 31, 65, 32, 67, 23, 63, +-2, 48, -32, 30, -65, 4, -77, -25, +-82, -51, -82, -69, -67, -80, -37, -77, +-6, -58, 17, -22, 26, 22, 26, 58, +22, 85, 0, 96, -27, 88, -53, 55, +-58, 13, -57, -29, -47, -64, -27, -85, +-7, -85, 7, -62, 9, -27, -4, 6, +-20, 31, -36, 49, -67, 51, -74, 41, +-73, 21, -48, 1, -19, -17, 10, -25, +36, -20, 47, -8, 44, 7, 17, 22, +-19, 32, -49, 28, -73, 15, -103, -6, +-104, -23, -89, -42, -61, -55, -23, -58, +10, -47, 39, -22, 59, 11, 56, 45, +44, 72, 20, 81, -20, 72, -58, 51, +-100, 17, -111, -21, -109, -58, -92, -75, +-60, -75, -25, -61, 22, -36, 57, -7, +69, 19, 66, 34, 42, 40, -4, 38, +-47, 30, -89, 20, -109, 14, -101, 10, +-86, 7, -57, -2, -24, -14, 11, -27, +38, -44, 42, -51, 38, -45, 16, -21, +-22, 8, -46, 40, -64, 65, -68, 72, +-60, 48, -49, 10, -30, -32, -12, -70, +0, -89, 4, -78, -2, -35, -11, 21, +-22, 75, -43, 107, -50, 107, -47, 71, +-42, 9, -30, -59, -23, -111, -11, -133, +-4, -113, -5, -57, 3, 15, -4, 85, +-14, 124, -22, 129, -38, 93, -48, 34, +-57, -29, -64, -79, -65, -101, -58, -91, +-37, -55, -16, -7, 3, 35, 24, 53, +37, 53, 30, 31, 9, 3, -31, -17, +-65, -18, -86, -2, -98, 23, -90, 50, +-68, 66, -29, 55, 14, 15, 46, -36, +62, -88, 49, -124, 8, -131, -41, -98, +-87, -36, -108, 39, -114, 106, -95, 152, +-51, 162, -1, 124, 48, 61, 73, -13, +76, -80, 55, -128, 18, -138, -41, -114, +-86, -67, -114, -13, -120, 38, -110, 70, +-91, 72, -56, 48, -22, 12, 16, -17, +43, -32, 55, -22, 57, 12, 47, 55, +24, 85, 4, 99, -32, 82, -72, 33, +-113, -43, -142, -121, -144, -172, -131, -189, +-91, -156, -35, -77, 36, 34, 93, 137, +128, 207, 123, 234, 89, 210, 19, 130, +-63, 16, -132, -96, -188, -178, -189, -215, +-157, -200, -92, -133, -5, -43, 67, 45, +109, 112, 112, 145, 81, 134, 32, 92, +-40, 39, -100, -9, -130, -43, -133, -56, +-103, -46, -63, -26, -16, -8, 30, -6, +51, -10, 43, -22, 20, -33, -14, -34, +-35, -16, -51, 16, -64, 46, -57, 70, +-50, 79, -36, 65, -28, 23, -23, -27, +-15, -75, -28, -103, -31, -106, -26, -75, +-17, -20, -1, 44, 0, 99, -2, 126, +-4, 122, -22, 83, -52, 23, -70, -42, +-80, -99, -72, -138, -59, -138, -41, -101, +-6, -40, 24, 26, 44, 89, 43, 134, +17, 143, -10, 118, -50, 67, -83, 5, +-98, -58, -105, -108, -85, -129, -55, -117, +-19, -81, 23, -26, 47, 30, 54, 70, +45, 87, 20, 82, -19, 62, -63, 27, +-92, -7, -104, -27, -99, -32, -81, -29, +-51, -17, -24, -4, 13, 1, 33, -7, +31, -22, 25, -28, -1, -27, -17, -17, +-36, 3, -42, 38, -44, 65, -50, 76, +-55, 66, -55, 35, -55, -8, -56, -55, +-55, -90, -43, -97, -21, -78, -5, -43, +18, 10, 26, 59, 30, 91, 20, 93, +-6, 71, -41, 33, -59, -10, -69, -39, +-69, -49, -60, -42, -51, -27, -37, -8, +-42, 4, -35, 1, -41, -20, -37, -41, +-28, -51, -18, -41, 8, -14, 43, 31, +68, 83, 68, 121, 44, 133, -7, 110, +-71, 54, -142, -26, -184, -106, -187, -164, +-155, -181, -92, -162, -13, -99, 66, -5, +129, 87, 149, 153, 130, 180, 73, 169, +-6, 114, -74, 39, -136, -37, -157, -94, +-145, -130, -116, -131, -69, -103, -24, -57, +17, -11, 35, 27, 33, 56, 23, 66, +5, 61, -11, 46, -24, 33, -30, 20, +-28, 5, -18, -7, -27, -17, -37, -31, +-45, -40, -57, -42, -57, -38, -61, -27, +-52, -9, -39, 20, -28, 46, -10, 62, +0, 62, 10, 48, 12, 18, 2, -23, +-5, -58, -16, -79, -27, -82, -39, -63, +-54, -23, -59, 25, -64, 70, -72, 97, +-65, 104, -41, 83, -19, 37, 2, -20, +10, -69, 15, -102, 18, -114, 5, -98, +-6, -57, -29, -1, -48, 50, -56, 93, +-70, 116, -59, 113, -51, 78, -42, 31, +-36, -18, -34, -65, -27, -97, -22, -106, +-14, -90, -2, -62, 18, -23, 26, 18, +28, 59, 10, 84, -10, 92, -40, 86, +-88, 65, -124, 28, -142, -13, -127, -45, +-88, -69, -37, -83, 30, -81, 90, -57, +112, -23, 117, 11, 82, 41, 25, 66, +-55, 71, -129, 57, -171, 29, -179, -2, +-147, -32, -96, -52, -22, -51, 45, -38, +96, -19, 103, 6, 88, 29, 49, 38, +-4, 33, -60, 18, -112, -3, -125, -26, +-113, -41, -84, -40, -44, -25, -9, -1, +18, 20, 33, 36, 30, 42, 23, 37, +-2, 22, -24, 4, -47, -15, -67, -33, +-70, -40, -71, -37, -61, -30, -44, -23, +-19, -7, -5, 10, 6, 29, 9, 44, +16, 56, 19, 58, 5, 45, -14, 21, +-46, -6, -67, -39, -79, -77, -86, -100, +-74, -98, -61, -75, -30, -40, 1, 17, +23, 76, 43, 119, 41, 133, 22, 120, +-8, 86, -43, 27, -70, -38, -88, -89, +-87, -117, -68, -124, -41, -105, -18, -65, +2, -14, 11, 30, 14, 61, -2, 80, +-33, 82, -49, 70, -55, 48, -44, 27, +-22, 5, -6, -11, 12, -26, 14, -37, +4, -47, -17, -55, -47, -58, -69, -49, +-90, -30, -94, -6, -71, 22, -35, 47, +5, 65, 39, 66, 63, 58, 60, 36, +35, 1, -12, -30, -47, -51, -79, -66, +-100, -65, -101, -44, -96, -12, -59, 17, +-20, 38, 11, 54, 29, 53, 33, 35, +28, 6, 6, -16, -19, -30, -33, -36, +-49, -31, -51, -14, -47, 8, -45, 26, +-40, 37, -44, 36, -42, 20, -40, -11, +-32, -37, -31, -54, -15, -53, 3, -37, +28, -7, 39, 31, 23, 63, 0, 84, +-42, 81, -71, 54, -100, 8, -110, -37, +-99, -70, -75, -85, -31, -83, 19, -58, +58, -17, 75, 24, 62, 54, 26, 66, +-19, 62, -65, 41, -96, 11, -105, -13, +-85, -26, -52, -31, -19, -21, 5, -3, +26, 14, 22, 20, 1, 14, -28, -1, +-59, -21, -63, -38, -62, -47, -37, -41, +-5, -26, 21, -2, 37, 28, 26, 56, +5, 71, -25, 68, -58, 53, -83, 29, +-95, -3, -84, -39, -61, -62, -32, -73, +-6, -69, 18, -54, 24, -28, 18, 0, +6, 27, -9, 49, -9, 62, -13, 62, +-18, 47, -19, 26, -26, 2, -33, -19, +-53, -39, -67, -49, -75, -46, -84, -33, +-76, -16, -56, 4, -18, 21, 24, 31, +53, 34, 73, 31, 72, 23, 47, 7, +4, -7, -42, -21, -83, -33, -108, -44, +-120, -44, -113, -30, -80, -7, -40, 19, +5, 46, 31, 67, 45, 74, 52, 63, +29, 39, 6, 6, -28, -41, -46, -87, +-52, -114, -58, -111, -51, -86, -40, -40, +-28, 23, -24, 78, -23, 117, -23, 132, +-22, 120, -20, 78, -9, 22, 3, -34, +6, -75, -2, -102, -18, -108, -35, -91, +-48, -64, -66, -37, -71, -8, -66, 27, +-54, 55, -14, 73, 16, 84, 50, 89, +63, 83, 56, 65, 25, 36, -19, -6, +-55, -55, -96, -97, -122, -126, -124, -135, +-98, -116, -66, -72, -21, -6, 22, 63, +60, 117, 84, 146, 77, 151, 45, 129, +6, 77, -31, 5, -59, -65, -88, -117, +-103, -148, -93, -143, -78, -106, -47, -47, +-24, 19, 5, 82, 17, 123, 15, 130, +13, 103, -2, 53, -11, -4, -21, -62, +-25, -98, -25, -101, -17, -76, -12, -32, +-6, 23, -1, 66, -8, 85, -27, 73, +-56, 36, -74, -11, -78, -58, -74, -90, +-49, -90, -19, -55, 17, -2, 50, 57, +61, 99, 60, 113, 33, 91, -6, 38, +-52, -26, -94, -86, -113, -121, -108, -126, +-77, -94, -34, -35, 14, 31, 51, 88, +66, 123, 58, 120, 32, 83, -5, 29, +-55, -25, -88, -67, -104, -88, -94, -81, +-61, -57, -30, -28, 11, -2, 43, 17, +55, 27, 49, 24, 24, 17, -1, 14, +-36, 13, -60, 19, -72, 31, -77, 41, +-65, 42, -49, 24, -31, -2, -15, -34, +0, -63, 3, -80, 4, -74, 4, -50, +1, -16, -1, 22, -12, 58, -15, 80, +-14, 80, -17, 63, -20, 29, -28, -11, +-29, -48, -31, -67, -37, -66, -36, -49, +-39, -22, -34, 11, -34, 39, -31, 49, +-20, 47, -16, 34, -2, 8, 10, -24, +26, -40, 19, -41, 14, -28, 5, -13, +-5, 10, -20, 32, -49, 42, -71, 37, +-86, 18, -78, -3, -67, -23, -52, -32, +-28, -30, -2, -17, 31, -6, 55, 5, +64, 11, 64, 12, 39, 8, 5, -2, +-33, -7, -68, -6, -87, 1, -99, 12, +-88, 24, -71, 26, -44, 19, -18, 0, +12, -22, 31, -43, 37, -54, 33, -47, +15, -24, 7, 12, -5, 44, -11, 70, +-20, 79, -39, 64, -50, 29, -62, -17, +-65, -59, -60, -85, -48, -84, -26, -56, +-6, -16, 20, 27, 35, 64, 39, 79, +33, 67, 9, 34, -21, -6, -53, -43, +-71, -62, -78, -60, -58, -37, -24, -2, +4, 34, 27, 55, 32, 54, 31, 35, +10, -2, -17, -38, -42, -63, -62, -67, +-61, -49, -51, -12, -29, 31, -1, 64, +16, 78, 22, 70, 10, 41, -9, -4, +-27, -48, -41, -77, -40, -82, -28, -68, +-3, -36, 14, 6, 28, 46, 26, 69, +11, 69, -21, 56, -62, 26, -83, -13, +-86, -44, -62, -60, -34, -60, 5, -42, +43, -16, 63, 13, 67, 31, 46, 38, +9, 36, -32, 21, -66, 1, -81, -18, +-78, -28, -52, -31, -20, -24, 5, -9, +18, 10, 12, 22, 2, 29, -17, 30, +-29, 26, -40, 16, -42, 1, -31, -12, +-13, -25, 19, -36, 31, -44, 36, -40, +19, -28, -11, -10, -35, 8, -55, 33, +-61, 57, -57, 70, -37, 68, -17, 51, +-7, 24, 1, -15, 3, -54, -1, -87, +-7, -99, -17, -89, -24, -60, -21, -19, +-4, 30, 9, 76, 24, 105, 29, 108, +15, 88, -8, 56, -46, 14, -69, -26, +-90, -60, -90, -79, -73, -82, -46, -72, +-7, -55, 29, -33, 64, -10, 83, 9, +80, 27, 59, 47, 22, 64, -18, 73, +-54, 75, -80, 69, -96, 51, -97, 15, +-85, -31, -67, -76, -34, -109, -1, -125, +28, -114, 48, -76, 59, -20, 67, 43, +53, 98, 36, 133, 1, 139, -34, 119, +-65, 74, -92, 14, -99, -45, -98, -90, +-78, -112, -44, -115, -1, -96, 41, -62, +71, -17, 87, 26, 80, 56, 57, 74, +16, 82, -31, 75, -67, 55, -90, 30, +-100, 2, -101, -23, -83, -47, -49, -62, +-8, -62, 37, -50, 62, -32, 79, -3, +73, 30, 50, 52, 19, 58, -14, 49, +-39, 24, -64, -7, -78, -35, -89, -52, +-84, -51, -60, -39, -27, -14, 11, 19, +38, 46, 56, 61, 58, 58, 52, 37, +37, 7, 10, -24, -15, -48, -46, -58, +-71, -54, -77, -36, -74, -9, -52, 18, +-28, 36, 1, 43, 17, 39, 25, 26, +26, 8, 16, -7, 13, -17, -2, -17, +-11, -11, -19, -4, -16, 4, -14, 9, +-12, 10, -6, 4, -13, -3, -26, -12, +-39, -25, -47, -31, -39, -30, -26, -25, +-7, -9, 15, 12, 37, 32, 55, 48, +52, 55, 40, 54, 4, 40, -31, 16, +-61, -17, -85, -51, -87, -73, -79, -81, +-49, -73, -18, -47, 18, -9, 41, 30, +57, 64, 63, 86, 47, 91, 24, 75, +2, 43, -13, 5, -25, -29, -35, -58, +-47, -75, -61, -77, -67, -72, -66, -58, +-52, -38, -29, -12, -6, 16, 32, 45, +59, 73, 78, 90, 86, 93, 76, 84, +49, 61, -6, 21, -56, -29, -107, -81, +-129, -121, -120, -142, -90, -130, -46, -90, +2, -28, 45, 44, 68, 109, 77, 153, +65, 164, 38, 138, 13, 78, -15, 2, +-32, -72, -40, -129, -36, -155, -22, -142, +-20, -93, -23, -27, -34, 41, -38, 93, +-33, 114, -25, 106, -6, 76, 8, 27, +26, -24, 38, -66, 43, -85, 32, -81, +16, -55, -3, -17, -33, 22, -49, 51, +-53, 62, -44, 59, -23, 42, -6, 15, +10, -11, 17, -28, 18, -38, 10, -42, +-4, -38, -13, -31, -25, -23, -23, -16, +-13, -8, -4, 4, 4, 22, 5, 40, +5, 54, -4, 60, -6, 55, -15, 40, +-11, 14, -5, -17, -7, -45, -7, -67, +-10, -76, -8, -66, -15, -45, -24, -15, +-35, 14, -41, 35, -29, 49, -12, 55, +9, 52, 35, 44, 51, 33, 55, 20, +44, 6, 19, -11, -12, -29, -36, -50, +-54, -64, -74, -71, -74, -66, -64, -48, +-31, -19, 6, 22, 34, 64, 51, 94, +53, 104, 47, 90, 24, 55, 8, 7, +-10, -42, -26, -80, -31, -101, -34, -100, +-34, -73, -34, -31, -25, 14, -15, 48, +-6, 65, 5, 67, 5, 54, 15, 33, +24, 9, 26, -12, 28, -26, 18, -30, +3, -26, -23, -18, -43, -14, -52, -15, +-47, -17, -27, -20, -7, -20, 21, -14, +46, -4, 61, 12, 55, 31, 32, 43, +-3, 48, -41, 46, -69, 35, -90, 11, +-86, -16, -58, -41, -22, -59, 27, -67, +66, -62, 88, -46, 89, -22, 70, 11, +32, 44, -13, 65, -41, 72, -63, 68, +-70, 49, -63, 19, -55, -13, -41, -41, +-25, -59, -2, -64, 5, -57, 17, -40, +23, -16, 32, 9, 51, 29, 62, 41, +65, 44, 53, 38, 24, 26, -20, 11, +-68, -2, -104, -13, -120, -17, -106, -16, +-77, -14, -38, -9, 15, -7, 64, -8, +109, -13, 129, -17, 117, -16, 73, -11, +15, -3, -36, 8, -86, 20, -101, 35, +-101, 43, -78, 40, -44, 28, -14, 11, +15, -12, 40, -38, 63, -56, 63, -64, +48, -58, 26, -39, -3, -8, -21, 25, +-33, 55, -39, 72, -33, 69, -24, 53, +-15, 25, -6, -11, 13, -46, 24, -69, +34, -76, 37, -66, 13, -38, -4, -3, +-23, 28, -33, 53, -40, 67, -40, 66, +-35, 52, -22, 28, 2, -1, 15, -29, +32, -51, 44, -61, 46, -60, 38, -49, +21, -28, 0, -4, -24, 19, -32, 36, +-38, 47, -40, 49, -29, 46, -22, 35, +-13, 17, -4, -3, -1, -23, 9, -40, +21, -50, 34, -50, 29, -41, 25, -24, +15, -3, 4, 16, 2, 27, -6, 31, +-14, 31, -22, 25, -25, 16, -32, 6, +-26, -1, -13, -5, -5, -5, 11, -6, +11, -8, 3, -8, 2, -13, 6, -19, +12, -21, 12, -20, 12, -15, 6, -7, +5, 3, 9, 14, 3, 24, 5, 31, +-1, 31, -9, 27, -24, 20, -37, 11, +-38, -3, -30, -16, -12, -27, -10, -34, +-5, -36, 1, -36, 10, -31, 28, -20, +42, -2, 47, 25, 43, 49, 33, 69, +14, 77, -11, 71, -29, 49, -52, 11, +-69, -32, -82, -73, -87, -102, -65, -110, +-28, -97, 23, -60, 64, -8, 98, 50, +115, 99, 104, 131, 80, 138, 26, 116, +-26, 69, -74, 3, -103, -65, -113, -122, +-96, -154, -62, -150, -24, -114, 24, -60, +53, 6, 67, 69, 74, 115, 62, 138, +40, 133, 14, 100, -5, 51, -17, -4, +-20, -54, -18, -89, -28, -103, -29, -97, +-33, -74, -37, -41, -32, -5, -26, 26, +-5, 47, 19, 55, 48, 54, 60, 46, +69, 32, 64, 18, 38, 6, 2, -8, +-44, -21, -81, -28, -99, -32, -88, -34, +-57, -30, -17, -20, 32, -6, 68, 9, +95, 22, 101, 32, 76, 36, 41, 36, +-8, 28, -59, 10, -94, -12, -105, -30, +-95, -38, -64, -40, -16, -36, 21, -23, +56, -4, 79, 17, 89, 36, 81, 51, +57, 58, 24, 56, -21, 42, -53, 18, +-81, -14, -91, -47, -76, -73, -57, -85, +-24, -83, 9, -59, 38, -21, 67, 24, +84, 68, 78, 100, 52, 111, 24, 95, +-11, 58, -42, 9, -60, -44, -71, -86, +-56, -113, -29, -114, 7, -87, 28, -39, +44, 13, 49, 59, 31, 91, 11, 100, +-21, 86, -38, 54, -37, 12, -25, -27, +-6, -55, 12, -67, 35, -63, 48, -47, +51, -27, 37, -7, 3, 11, -25, 22, +-50, 25, -60, 26, -52, 26, -35, 24, +-5, 21, 20, 18, 37, 15, 31, 9, +32, -6, 28, -21, 12, -33, -2, -41, +-18, -42, -20, -32, -14, -14, 2, 6, +9, 26, 12, 40, 7, 46, -13, 41, +-23, 27, -30, 11, -30, -6, -15, -19, +2, -24, 12, -21, 16, -13, 25, -6, +31, 2, 26, 7, 13, 10, -15, 6, +-27, -2, -31, -9, -22, -14, -4, -14, +14, -7, 27, 2, 25, 10, 19, 18, +-6, 25, -25, 29, -37, 29, -50, 26, +-47, 14, -28, -4, 2, -18, 34, -29, +65, -41, 79, -47, 72, -46, 52, -38, +15, -22, -28, 2, -65, 31, -87, 54, +-82, 67, -59, 72, -29, 66, -3, 45, +32, 13, 54, -23, 55, -55, 55, -78, +35, -87, 22, -76, 7, -52, -6, -16, +-19, 24, -26, 55, -20, 71, -18, 71, +-19, 57, -29, 36, -39, 10, -35, -13, +-20, -24, 1, -28, 27, -20, 51, -8, +62, 0, 62, 1, 45, -4, 12, -14, +-13, -30, -39, -43, -63, -44, -76, -30, +-72, -6, -39, 26, 0, 59, 42, 84, +64, 93, 68, 87, 56, 62, 23, 21, +-3, -28, -25, -73, -37, -109, -36, -125, +-31, -117, -28, -84, -19, -36, 2, 18, +15, 72, 19, 113, 14, 132, 3, 125, +6, 96, 14, 54, 25, 1, 32, -50, +33, -87, 17, -104, -19, -104, -41, -92, +-63, -65, -63, -33, -47, -1, -25, 31, +3, 56, 35, 75, 70, 85, 88, 85, +92, 74, 63, 52, 20, 17, -22, -28, +-62, -72, -86, -105, -89, -120, -74, -109, +-45, -74, -9, -23, 28, 36, 55, 91, +77, 127, 80, 134, 60, 111, 36, 58, +1, -11, -23, -75, -46, -119, -56, -132, +-58, -113, -43, -64, -15, 0, 1, 60, +21, 103, 29, 115, 33, 95, 34, 49, +28, -8, 13, -58, 0, -88, -9, -90, +-18, -66, -19, -25, -15, 23, -12, 61, +0, 78, 6, 67, 6, 37, 4, -2, +2, -39, 7, -62, 5, -67, 9, -53, +1, -23, -4, 11, -2, 37, -7, 52, +-4, 53, -5, 45, -5, 27, -9, 5, +-5, -15, -3, -30, 8, -33, 25, -32, +28, -25, 24, -17, 10, -13, -8, -7, +-19, -1, -26, 7, -30, 19, -34, 29, +-23, 34, -10, 34, 3, 25, 25, 13, +36, -4, 47, -23, 45, -38, 28, -46, +10, -42, -5, -29, -15, -4, -30, 23, +-36, 40, -41, 42, -35, 32, -19, 12, +0, -14, 20, -37, 35, -45, 45, -37, +38, -19, 27, 7, 14, 32, -5, 46, +-10, 46, -21, 34, -33, 13, -33, -11, +-25, -34, -6, -44, 9, -37, 19, -17, +22, 5, 26, 21, 28, 27, 13, 18, +3, 0, -14, -21, -24, -38, -31, -44, +-27, -33, -18, -6, -1, 33, 17, 71, +22, 93, 32, 87, 36, 59, 30, 12, +21, -46, 6, -98, -15, -126, -36, -124, +-46, -90, -46, -36, -38, 26, -18, 81, +-2, 118, 17, 126, 36, 102, 46, 54, +54, 3, 48, -42, 36, -72, 10, -87, +-9, -80, -33, -57, -45, -25, -47, 5, +-49, 24, -40, 31, -27, 29, -4, 21, +18, 16, 40, 15, 54, 17, 55, 21, +51, 23, 31, 17, 4, 5, -14, -15, +-32, -34, -45, -47, -53, -50, -52, -45, +-34, -31, -4, -9, 31, 18, 48, 43, +60, 58, 51, 58, 33, 46, 8, 24, +-21, -4, -40, -34, -45, -55, -35, -58, +-26, -50, -2, -31, 22, -8, 37, 15, +49, 33, 36, 42, 16, 38, -2, 25, +-18, 7, -29, -10, -35, -23, -25, -29, +-10, -29, 13, -22, 32, -10, 33, 0, +30, 9, 19, 14, 2, 16, -17, 15, +-26, 11, -27, 4, -15, -3, -1, -7, +3, -10, 15, -11, 20, -10, 19, -6, +8, 1, -15, 11, -33, 18, -41, 20, +-28, 21, -10, 20, 6, 17, 26, 8, +32, -6, 34, -19, 28, -28, 9, -31, +-5, -27, -14, -17, -25, -1, -38, 16, +-37, 31, -29, 36, -5, 29, 21, 16, +27, 1, 31, -14, 27, -26, 27, -24, +16, -15, 11, -1, 6, 11, -7, 18, +-16, 18, -33, 11, -46, -2, -43, -17, +-35, -27, -17, -30, 2, -21, 23, -2, +46, 20, 69, 36, 80, 46, 66, 45, +36, 31, -11, 4, -54, -25, -87, -48, +-102, -60, -92, -57, -60, -38, -7, -9, +34, 23, 76, 50, 97, 63, 99, 57, +82, 37, 43, 13, -7, -10, -51, -29, +-76, -38, -89, -34, -78, -24, -47, -13, +-13, -2, 19, 5, 39, 8, 40, 6, +40, -1, 36, -5, 28, 2, 17, 15, +15, 27, 10, 40, 0, 45, -9, 34, +-23, 8, -28, -23, -39, -52, -45, -70, +-46, -74, -35, -57, -13, -22, 16, 20, +56, 58, 77, 85, 84, 90, 74, 70, +42, 34, 1, -11, -37, -57, -64, -88, +-77, -93, -74, -76, -62, -40, -38, 4, +1, 43, 41, 71, 70, 82, 80, 71, +71, 42, 52, 7, 26, -28, 5, -51, +-23, -59, -38, -56, -47, -48, -55, -31, +-53, -7, -50, 13, -29, 27, 4, 38, +29, 50, 46, 56, 54, 52, 61, 39, +57, 17, 46, -12, 22, -40, -14, -68, +-45, -86, -66, -87, -74, -65, -67, -26, +-40, 18, -6, 60, 28, 89, 54, 100, +59, 87, 60, 54, 47, 9, 27, -37, +4, -70, -22, -83, -36, -77, -40, -56, +-32, -26, -21, 2, -7, 22, 4, 32, +7, 30, 8, 18, 12, 8, 15, 5, +17, 10, 22, 21, 23, 30, 22, 28, +23, 16, 10, -5, -8, -35, -24, -66, +-38, -88, -38, -89, -35, -68, -19, -26, +-1, 29, 18, 83, 36, 121, 41, 131, +42, 109, 29, 58, 14, -8, -4, -73, +-20, -121, -31, -141, -29, -127, -21, -84, +-13, -21, -4, 40, -2, 86, 4, 109, +15, 103, 22, 74, 27, 30, 29, -16, +29, -48, 25, -60, 9, -52, -3, -32, +-21, -10, -32, 8, -41, 15, -47, 10, +-35, -1, -15, -14, 17, -20, 42, -14, +58, 2, 56, 21, 44, 44, 22, 59, +-7, 56, -26, 31, -44, 3, -55, -24, +-50, -46, -30, -55, -7, -48, 17, -27, +40, -1, 45, 24, 38, 38, 25, 38, +6, 26, -4, 10, -14, -5, -19, -13, +-18, -12, -12, 1, -2, 21, 1, 34, +5, 36, -2, 24, -7, 1, -8, -28, +-11, -51, -7, -61, 5, -55, 17, -28, +24, 10, 28, 44, 26, 67, 21, 72, +12, 57, -5, 31, -22, -5, -32, -40, +-30, -64, -19, -67, -6, -51, 8, -26, +14, 1, 20, 23, 19, 34, 12, 29, +12, 16, 8, 2, 7, -3, 4, 0, +-2, 11, -4, 24, -5, 29, -4, 24, +-8, 5, -17, -23, -27, -54, -26, -78, +-13, -85, 7, -71, 29, -33, 40, 21, +46, 74, 40, 108, 26, 113, 9, 88, +-18, 39, -36, -24, -51, -86, -54, -128, +-38, -135, -16, -109, 16, -56, 42, 8, +58, 67, 55, 106, 42, 116, 22, 93, +-1, 44, -22, -11, -44, -56, -54, -82, +-50, -86, -35, -65, -16, -30, 7, 8, +33, 37, 46, 50, 52, 44, 51, 22, +39, -4, 25, -26, 2, -37, -23, -32, +-46, -14, -60, 11, -62, 35, -54, 44, +-26, 38, 4, 21, 39, -3, 67, -28, +81, -46, 78, -53, 58, -46, 26, -25, +-19, 4, -52, 32, -77, 47, -78, 53, +-61, 48, -37, 36, -3, 18, 30, -2, +58, -16, 72, -24, 68, -27, 50, -24, +19, -16, -9, -8, -29, -3, -39, 1, +-36, 9, -33, 20, -27, 29, -19, 37, +-9, 41, 3, 40, 17, 34, 25, 23, +24, 6, 28, -14, 24, -32, 21, -41, +15, -43, 8, -38, -2, -27, -15, -6, +-24, 18, -32, 41, -28, 60, -15, 68, +-5, 65, 9, 45, 15, 17, 21, -14, +25, -42, 26, -63, 23, -69, 13, -62, +6, -42, -1, -14, -7, 21, -9, 52, +-13, 68, -13, 72, -14, 60, -18, 39, +-22, 10, -16, -23, -2, -50, 17, -65, +32, -65, 32, -54, 33, -38, 31, -16, +21, 8, 7, 27, -14, 41, -28, 48, +-36, 44, -31, 31, -23, 14, -13, -7, +4, -30, 20, -52, 29, -63, 27, -65, +20, -59, 15, -39, 10, -10, 3, 21, +-3, 42, -1, 51, 1, 45, 8, 26, +7, -3, -1, -33, -6, -54, -11, -60, +-14, -48, -20, -25, -20, 1, -11, 20, +3, 30, 22, 23, 32, 5, 36, -18, +33, -37, 23, -44, 9, -38, -8, -19, +-18, 9, -22, 38, -20, 55, -18, 50, +-19, 27, -12, -9, -2, -47, 13, -75, +22, -83, 27, -66, 27, -31, 26, 13, +28, 53, 20, 78, 10, 83, -3, 62, +-18, 24, -28, -20, -37, -52, -35, -65, +-20, -54, 1, -23, 17, 17, 24, 51, +27, 68, 25, 67, 18, 46, 5, 9, +-9, -28, -20, -50, -25, -53, -19, -33, +-12, 0, 5, 40, 17, 74, 23, 90, +22, 83, 3, 57, -13, 21, -23, -18, +-25, -46, -21, -59, -15, -50, -1, -28, +15, 4, 31, 32, 35, 50, 29, 55, +18, 47, 1, 32, -15, 19, -31, 10, +-33, 1, -21, 1, 0, 6, 16, 12, +20, 11, 22, 4, 21, -11, 17, -23, +2, -27, -17, -25, -24, -14, -18, 4, +-1, 27, 13, 45, 25, 53, 32, 47, +31, 29, 24, 0, 2, -28, -22, -47, +-39, -56, -42, -53, -32, -36, -20, -9, +0, 18, 27, 34, 55, 38, 63, 34, +49, 20, 29, -1, 7, -23, -13, -34, +-34, -41, -47, -41, -48, -36, -35, -30, +-11, -23, 8, -21, 27, -16, 36, -12, +40, -4, 41, 5, 31, 16, 20, 27, +8, 36, -1, 32, -10, 11, -21, -21, +-27, -58, -29, -88, -24, -107, -18, -104, +-14, -81, -6, -39, 10, 12, 30, 59, +47, 90, 58, 99, 53, 84, 41, 48, +19, 0, -13, -49, -37, -87, -55, -109, +-57, -105, -50, -82, -35, -43, -13, -3, +15, 28, 45, 46, 61, 51, 61, 43, +49, 25, 31, 9, 12, -1, -7, -4, +-22, 0, -34, 11, -36, 16, -32, 16, +-26, 8, -15, -10, -2, -33, 12, -52, +19, -57, 20, -48, 21, -22, 22, 13, +21, 56, 15, 93, 7, 112, -2, 108, +-9, 85, -13, 47, -15, 0, -10, -47, +-4, -77, -1, -85, 0, -73, 4, -44, +10, -8, 13, 32, 12, 64, 2, 85, +-3, 86, -4, 74, 1, 52, 12, 30, +17, 12, 21, -1, 19, -8, 13, -9, +5, -3, -10, -2, -20, -3, -25, -9, +-24, -13, -19, -12, -7, -5, 11, 9, +29, 30, 37, 48, 35, 60, 27, 60, +14, 45, 3, 24, -9, -1, -22, -24, +-22, -42, -17, -48, -6, -39, 5, -19, +11, 5, 16, 24, 13, 34, 6, 35, +-7, 26, -15, 5, -13, -12, -10, -24, +2, -28, 15, -25, 26, -14, 34, -3, +30, 7, 19, 13, -1, 6, -23, -4, +-38, -17, -46, -28, -41, -35, -21, -37, +8, -36, 34, -25, 55, -13, 61, -9, +58, -8, 42, -10, 12, -17, -15, -26, +-41, -29, -53, -28, -50, -22, -35, -16, +-12, -9, 11, -5, 31, -3, 40, -7, +40, -13, 32, -22, 21, -32, 10, -37, +-2, -37, -14, -27, -22, -17, -22, -5, +-15, 0, -11, 1, -9, -5, -10, -12, +-4, -20, 9, -26, 22, -23, 31, -15, +35, -4, 36, 8, 28, 20, 16, 22, +-1, 16, -17, 1, -27, -17, -35, -33, +-39, -43, -32, -46, -10, -35, 16, -14, +36, 13, 44, 38, 40, 51, 34, 55, +29, 48, 20, 34, 6, 14, -8, -3, +-15, -14, -19, -16, -21, -10, -23, -3, +-22, 3, -16, 9, -13, 13, -5, 10, +3, 6, 19, 8, 40, 19, 55, 37, +58, 58, 43, 76, 21, 84, -4, 77, +-28, 55, -51, 21, -70, -17, -71, -50, +-50, -74, -13, -76, 23, -53, 50, -12, +70, 35, 81, 75, 76, 104, 46, 115, +7, 106, -26, 78, -49, 41, -58, -1, +-59, -35, -47, -53, -24, -59, 6, -54, +29, -38, 38, -17, 38, 7, 36, 25, +38, 35, 33, 44, 20, 48, 7, 47, +0, 39, -8, 28, -20, 8, -30, -13, +-37, -36, -33, -55, -22, -63, -12, -56, +6, -39, 29, -13, 52, 14, 62, 32, +55, 43, 35, 39, 8, 22, -12, -6, +-33, -35, -49, -58, -53, -69, -45, -62, +-23, -46, 3, -23, 29, -1, 44, 16, +51, 21, 44, 14, 27, -3, 9, -24, +-3, -44, -8, -55, -11, -57, -15, -51, +-15, -39, -8, -30, 6, -22, 12, -15, +12, -15, 12, -16, 7, -12, 3, -7, +1, -4, 1, -1, 3, 1, 5, -5, +6, -18, 4, -34, 3, -49, 7, -58, +17, -58, 17, -44, 13, -23, 8, 1, +3, 26, -1, 40, -9, 40, -15, 26, +-20, 3, -17, -24, -4, -44, 6, -50, +15, -37, 25, -16, 36, 10, 39, 35, +26, 51, 8, 51, -7, 36, -16, 13, +-27, -12, -35, -32, -35, -38, -26, -29, +-7, -5, 10, 23, 21, 49, 25, 69, +31, 73, 34, 65, 29, 44, 18, 19, +6, -4, 2, -24, 1, -36, -4, -32, +-15, -12, -25, 9, -24, 29, -19, 45, +-17, 56, -13, 58, 2, 56, 26, 47, +43, 37, 50, 26, 43, 16, 34, 9, +25, 2, 8, 1, -14, 3, -38, 9, +-49, 14, -48, 21, -42, 24, -29, 26, +-13, 24, 11, 18, 35, 11, 51, 3, +57, 2, 57, 5, 56, 13, 43, 25, +18, 31, -12, 27, -37, 20, -53, 7, +-62, -10, -57, -28, -47, -39, -25, -39, +5, -28, 33, -9, 58, 9, 71, 23, +74, 29, 60, 28, 33, 16, 1, -3, +-27, -24, -45, -37, -51, -42, -46, -39, +-40, -28, -25, -17, -3, -11, 19, -10, +33, -12, 35, -19, 33, -27, 30, -32, +26, -30, 24, -23, 20, -12, 10, -2, +-1, -1, -12, -12, -21, -30, -30, -50, +-31, -66, -27, -69, -18, -58, -5, -34, +14, -5, 36, 21, 55, 38, 61, 42, +50, 28, 32, -6, 6, -47, -18, -80, +-38, -97, -48, -97, -44, -78, -33, -44, +-15, -2, 6, 35, 24, 60, 39, 66, +45, 51, 42, 27, 29, 1, 14, -23, +2, -41, -5, -48, -12, -44, -18, -32, +-24, -22, -27, -11, -26, -5, -21, 0, +-9, 4, 8, 9, 24, 19, 40, 30, +50, 42, 55, 48, 53, 48, 34, 39, +5, 25, -29, 5, -54, -15, -66, -27, +-66, -30, -50, -23, -20, -10, 16, 9, +47, 27, 68, 41, 77, 47, 68, 49, +44, 46, 12, 43, -20, 41, -46, 42, +-61, 44, -59, 44, -47, 38, -27, 26, +-6, 9, 12, -11, 29, -28, 40, -44, +47, -42, 46, -25, 37, 7, 27, 42, +18, 75, 6, 100, -9, 105, -26, 92, +-40, 58, -45, 14, -40, -30, -26, -64, +-5, -80, 16, -72, 38, -49, 56, -15, +64, 24, 57, 57, 36, 75, 8, 76, +-24, 62, -48, 31, -59, -1, -53, -28, +-33, -44, -6, -51, 18, -46, 34, -35, +44, -20, 48, -5, 41, 9, 22, 19, +-2, 21, -18, 18, -23, 8, -19, -3, +-12, -18, -2, -34, 8, -50, 13, -59, +9, -62, 1, -56, -3, -41, 1, -18, +9, 10, 15, 34, 13, 50, 14, 46, +18, 24, 23, -11, 14, -52, -3, -92, +-18, -118, -25, -122, -21, -99, -15, -52, +-6, -1, 14, 47, 35, 83, 42, 97, +35, 80, 20, 40, 3, -16, -12, -71, +-22, -114, -34, -134, -39, -121, -27, -88, +0, -40, 27, 17, 39, 66, 44, 94, +42, 97, 38, 79, 21, 44, -7, 1, +-29, -42, -41, -77, -40, -93, -37, -94, +-28, -78, -8, -49, 17, -12, 41, 30, +53, 66, 54, 95, 47, 107, 37, 105, +17, 87, -13, 48, -40, -1, -58, -50, +-62, -90, -53, -113, -35, -110, -12, -82, +19, -29, 56, 35, 76, 98, 80, 145, +68, 164, 44, 150, 12, 106, -22, 44, +-52, -20, -70, -72, -65, -104, -46, -103, +-24, -75, -2, -28, 22, 23, 44, 63, +56, 85, 52, 88, 37, 74, 18, 56, +6, 35, 0, 19, -2, 19, -7, 27, +-12, 35, -13, 33, -21, 21, -29, -3, +-30, -37, -21, -65, -10, -77, 3, -70, +20, -38, 39, 11, 60, 65, 67, 112, +56, 132, 33, 121, 7, 80, -20, 20, +-43, -41, -56, -88, -57, -109, -43, -100, +-20, -70, 3, -27, 26, 14, 42, 42, +53, 50, 53, 34, 39, 9, 20, -14, +-1, -24, -10, -18, -15, -2, -15, 16, +-9, 27, -1, 28, 6, 12, 2, -19, +-4, -58, -12, -88, -14, -103, -10, -95, +-3, -64, 7, -17, 24, 29, 45, 66, +56, 82, 50, 69, 33, 33, 12, -15, +-8, -57, -29, -86, -46, -96, -54, -84, +-47, -53, -23, -18, 5, 10, 29, 27, +44, 31, 53, 20, 57, 0, 48, -18, +28, -30, 6, -33, -5, -30, -13, -19, +-23, -7, -35, 1, -37, 2, -27, -4, +-12, -12, 1, -16, 11, -16, 25, -8, +39, 7, 47, 19, 48, 22, 39, 16, +25, 4, 9, -15, -9, -32, -24, -41, +-35, -37, -36, -18, -27, 10, -13, 38, +5, 56, 22, 61, 39, 48, 51, 22, +50, -9, 34, -34, 15, -47, 1, -46, +-6, -27, -11, 8, -19, 48, -21, 78, +-18, 90, -12, 78, -2, 47, 4, 4, +11, -35, 18, -64, 25, -70, 32, -53, +32, -12, 30, 36, 24, 76, 15, 99, +0, 99, -19, 79, -32, 41, -39, -1, +-34, -39, -21, -61, 0, -63, 24, -45, +47, -14, 61, 23, 62, 52, 47, 65, +19, 63, -12, 44, -37, 15, -46, -12, +-43, -27, -29, -29, -7, -19, 20, -4, +45, 13, 60, 25, 58, 28, 42, 20, +18, 5, -10, -10, -35, -24, -45, -31, +-37, -31, -17, -22, 10, -9, 30, 5, +43, 13, 46, 15, 40, 11, 29, 4, +9, 0, -12, -1, -27, 0, -28, -1, +-16, -5, -1, -11, 12, -19, 19, -34, +24, -49, 21, -58, 11, -56, 3, -42, +1, -16, 4, 18, 7, 50, 12, 72, +16, 74, 18, 56, 18, 16, 13, -33, +3, -82, -9, -114, -15, -124, -12, -110, +-2, -69, 10, -13, 20, 45, 29, 87, +30, 105, 26, 95, 14, 62, 2, 11, +-7, -38, -13, -77, -11, -96, -2, -90, +10, -67, 23, -34, 35, 0, 35, 27, +25, 44, 11, 45, -2, 34, -14, 22, +-20, 9, -19, 0, -6, -6, 11, -9, +28, -13, 42, -18, 46, -22, 36, -24, +17, -20, 2, -13, -8, 3, -13, 25, +-14, 51, -12, 65, -3, 64, 8, 45, +19, 10, 24, -29, 22, -64, 16, -78, +11, -73, 10, -44, 14, 0, 21, 56, +27, 103, 29, 127, 24, 115, 12, 75, +-3, 16, -16, -48, -23, -95, -26, -116, +-23, -105, -8, -63, 13, -1, 37, 61, +56, 106, 65, 122, 60, 110, 44, 73, +19, 24, -13, -25, -38, -61, -49, -76, +-47, -67, -34, -40, -16, -7, 5, 23, +29, 44, 52, 48, 66, 40, 64, 27, +46, 14, 25, 3, 10, -4, -6, -6, +-23, -6, -30, -9, -29, -16, -18, -25, +-8, -32, 5, -36, 22, -30, 40, -15, +52, 6, 57, 29, 51, 50, 35, 59, +22, 49, 7, 25, -13, -12, -32, -48, +-43, -81, -37, -97, -20, -94, -1, -68, +21, -28, 44, 18, 64, 58, 76, 82, +72, 86, 56, 71, 30, 41, 1, 0, +-29, -43, -52, -78, -63, -97, -57, -98, +-35, -80, -8, -51, 22, -16, 52, 19, +76, 47, 88, 62, 84, 61, 64, 54, +31, 40, -4, 18, -33, -4, -56, -21, +-68, -38, -59, -51, -34, -57, -6, -53, +23, -43, 48, -30, 68, -15, 76, 2, +70, 22, 51, 40, 24, 55, 4, 59, +-12, 55, -25, 43, -32, 22, -29, -5, +-16, -35, -1, -55, 12, -66, 19, -61, +27, -47, 29, -20, 28, 11, 26, 39, +27, 58, 29, 66, 27, 64, 20, 52, +10, 32, 1, 9, -4, -10, -7, -27, +-12, -35, -10, -39, -5, -35, 7, -25, +18, -11, 25, 7, 31, 26, 34, 42, +31, 58, 21, 68, 12, 64, 7, 50, +6, 23, 8, -9, 7, -43, 5, -66, +2, -75, 5, -69, 8, -42, 7, -2, +6, 40, 14, 74, 26, 95, 31, 97, +35, 74, 34, 32, 31, -18, 26, -66, +16, -95, 3, -99, -11, -76, -15, -37, +-11, 12, -5, 57, 2, 84, 14, 86, +30, 65, 40, 32, 38, -6, 26, -39, +19, -63, 17, -65, 15, -50, 14, -22, +12, 8, 12, 28, 15, 35, 12, 28, +2, 14, -9, -9, -15, -29, -10, -39, +-4, -32, 8, -15, 24, 7, 45, 26, +64, 34, 71, 30, 59, 16, 35, -7, +9, -32, -18, -48, -38, -53, -52, -43, +-48, -25, -28, -4, 5, 13, 41, 25, +66, 29, 77, 23, 77, 8, 66, -8, +42, -16, 10, -17, -14, -12, -27, -8, +-29, -3, -24, -2, -14, -3, -1, -9, +13, -16, 24, -21, 28, -17, 28, -5, +28, 6, 36, 19, 43, 30, 43, 37, +39, 30, 31, 15, 16, -6, -3, -24, +-23, -35, -34, -38, -35, -29, -26, -10, +-6, 12, 22, 29, 51, 44, 68, 46, +75, 35, 70, 14, 48, -6, 15, -22, +-15, -30, -34, -28, -40, -18, -30, 2, +-13, 22, 10, 37, 37, 41, 53, 37, +60, 26, 52, 12, 36, -9, 18, -23, +5, -30, -1, -29, 0, -19, 4, -2, +8, 13, 18, 20, 21, 27, 20, 31, +13, 33, 8, 29, 11, 23, 16, 15, +26, 7, 35, -3, 43, -16, 48, -28, +42, -39, 23, -40, -4, -34, -26, -20, +-34, 1, -29, 30, -14, 60, 10, 81, +40, 83, 68, 66, 82, 34, 77, -10, +57, -58, 29, -97, -1, -116, -25, -112, +-36, -77, -35, -23, -18, 39, 6, 90, +32, 122, 48, 122, 55, 92, 53, 43, +39, -14, 21, -66, 5, -103, -1, -113, +0, -99, 12, -66, 26, -24, 32, 21, +33, 52, 25, 64, 14, 60, -1, 45, +-12, 27, -13, 8, -5, -8, 16, -20, +36, -26, 53, -31, 62, -35, 60, -41, +44, -43, 22, -43, -2, -35, -20, -16, +-23, 7, -15, 35, 2, 58, 19, 69, +36, 61, 48, 35, 50, -2, 39, -35, +21, -64, 5, -80, -4, -75, -8, -50, +2, -16, 21, 18, 36, 50, 44, 66, +44, 60, 38, 34, 27, 5, 8, -23, +-5, -38, -11, -40, -8, -29, 2, -11, +21, 7, 41, 21, 55, 24, 61, 19, +49, 6, 32, -9, 9, -20, -6, -20, +-17, -11, -16, 6, -6, 22, 11, 34, +29, 39, 41, 32, 51, 15, 53, -6, +46, -21, 32, -29, 18, -27, 4, -15, +-8, 5, -7, 21, -1, 36, 6, 39, +12, 31, 21, 15, 31, -3, 39, -16, +45, -21, 43, -17, 42, -9, 37, 6, +29, 20, 17, 27, 8, 28, -4, 25, +-15, 18, -17, 5, -12, -6, 0, -11, +18, -11, 42, -11, 63, -6, 73, -1, +66, 8, 53, 10, 35, 9, 14, 7, +-7, 8, -27, 11, -32, 10, -22, 7, +-1, 4, 22, 0, 43, -8, 62, -14, +65, -18, 61, -19, 49, -21, 36, -13, +19, 1, 6, 13, -2, 22, -6, 27, +-1, 25, 6, 13, 18, -3, 21, -21, +23, -34, 25, -46, 29, -46, 38, -36, +45, -17, 51, 7, 52, 30, 48, 47, +35, 53, 17, 44, -1, 22, -17, -7, +-27, -42, -26, -71, -11, -84, 10, -78, +40, -57, 69, -21, 84, 21, 86, 57, +76, 79, 53, 80, 25, 63, -3, 29, +-26, -11, -35, -52, -33, -79, -19, -86, +-1, -72, 24, -49, 49, -19, 62, 12, +66, 34, 59, 47, 53, 45, 42, 36, +34, 20, 27, 5, 19, -4, 12, -6, +2, -10, -2, -15, -7, -21, -8, -30, +-3, -40, 6, -45, 22, -39, 39, -25, +65, -1, 82, 28, 86, 58, 71, 75, +47, 75, 20, 55, -7, 21, -29, -19, +-42, -52, -42, -70, -26, -69, 5, -49, +35, -14, 61, 26, 74, 53, 79, 64, +69, 55, 47, 33, 23, 4, 6, -21, +-3, -30, -8, -26, -3, -10, 7, 11, +22, 30, 35, 38, 38, 33, 32, 17, +18, -8, 12, -35, 12, -49, 19, -43, +25, -18, 34, 19, 44, 50, 51, 69, +56, 67, 45, 49, 33, 16, 17, -24, +4, -59, -8, -73, -14, -66, -9, -40, +5, -2, 27, 36, 42, 63, 54, 72, +62, 61, 65, 33, 58, 4, 44, -25, +28, -40, 11, -45, -2, -37, -10, -22, +-11, -6, -6, 6, 6, 9, 20, 10, +32, 5, 46, 3, 56, 9, 60, 22, +56, 33, 49, 38, 35, 33, 20, 18, +5, -9, -6, -39, -11, -65, -11, -78, +-2, -71, 10, -46, 28, -4, 40, 42, +56, 77, 65, 91, 63, 84, 53, 52, +36, 7, 23, -40, 8, -78, 0, -96, +-5, -91, -2, -62, 7, -24, 20, 16, +38, 46, 49, 60, 57, 56, 53, 38, +44, 13, 29, -11, 17, -31, 12, -40, +8, -36, 10, -27, 11, -14, 23, -4, +34, 1, 47, 3, 51, 2, 47, -1, +36, 0, 23, 2, 13, 7, 2, 12, +-1, 13, 1, 10, 9, 0, 21, -11, +34, -21, 46, -25, 55, -25, 61, -17, +59, -5, 46, 12, 28, 26, 16, 31, +8, 26, 5, 10, 5, -5, 1, -20, +5, -30, 13, -35, 28, -31, 40, -18, +51, 2, 54, 21, 57, 34, 57, 41, +46, 40, 36, 30, 22, 12, 12, -7, +-4, -24, -12, -33, -14, -36, -3, -30, +15, -19, 31, -5, 49, 11, 60, 25, +67, 32, 69, 32, 62, 29, 45, 24, +22, 18, 3, 11, -13, 5, -15, -5, +-9, -12, 5, -18, 16, -21, 29, -24, +42, -27, 51, -22, 57, -10, 54, 8, +51, 25, 41, 45, 31, 61, 18, 67, +14, 55, 10, 31, 4, 2, -2, -33, +-3, -63, 6, -80, 18, -78, 37, -59, +52, -21, 64, 22, 68, 58, 67, 79, +59, 84, 39, 69, 17, 39, -8, 3, +-25, -31, -32, -54, -20, -64, 7, -58, +36, -40, 66, -15, 81, 7, 88, 21, +78, 23, 61, 22, 32, 16, 4, 10, +-16, 6, -28, 8, -20, 14, -4, 14, +25, 9, 49, 0, 61, -13, 62, -32, +58, -49, 47, -56, 33, -46, 19, -21, +7, 12, 5, 42, 10, 63, 22, 69, +32, 57, 38, 30, 40, -7, 33, -44, +24, -70, 15, -75, 14, -62, 19, -37, +32, -6, 41, 25, 46, 46, 48, 52, +39, 48, 26, 30, 10, 4, 6, -20, +0, -30, 3, -32, 17, -26, 41, -17, +63, -7, 74, 0, 73, 2, 52, 0, +29, -8, 3, -10, -15, -8, -25, -1, +-21, 9, -3, 22, 21, 29, 52, 30, +74, 23, 83, 9, 75, -9, 55, -26, +29, -35, 1, -37, -11, -28, -16, -13, +-7, 5, 6, 19, 23, 29, 37, 31, +48, 24, 52, 14, 45, 4, 37, -4, +28, -8, 26, -4, 26, 1, 35, 7, +39, 6, 43, -1, 37, -13, 24, -23, +8, -30, -5, -31, -9, -21, -6, -2, +9, 24, 29, 48, 55, 68, 77, 70, +87, 57, 86, 26, 63, -9, 30, -45, +-6, -72, -28, -84, -39, -76, -32, -48, +-7, -12, 20, 32, 51, 67, 70, 89, +85, 88, 83, 69, 67, 40, 37, 7, +10, -30, -1, -57, -3, -68, 5, -63, +16, -46, 27, -23, 30, 4, 33, 21, +32, 32, 30, 33, 30, 32, 27, 29, +29, 26, 32, 22, 39, 17, 47, 7, +51, -7, 48, -21, 34, -36, 19, -42, +4, -42, 4, -33, 7, -14, 15, 14, +21, 36, 34, 49, 46, 49, 52, 34, +51, 9, 42, -20, 34, -41, 21, -51, +21, -48, 25, -31, 36, 1, 43, 33, +43, 54, 38, 54, 26, 34, 17, 1, +9, -34, 3, -59, 2, -71, 11, -61, +27, -32, 45, 10, 67, 45, 74, 71, +74, 72, 60, 50, 41, 14, 16, -25, +-7, -57, -14, -71, -18, -60, -10, -32, +3, 1, 23, 30, 38, 51, 56, 48, +66, 29, 70, -1, 63, -30, 51, -44, +38, -42, 26, -26, 20, -1, 9, 26, +3, 41, -4, 42, -9, 28, -6, 3, +4, -27, 23, -45, 41, -48, 59, -37, +72, -14, 81, 15, 79, 38, 65, 44, +44, 37, 10, 17, -16, -7, -37, -32, +-32, -47, -15, -47, 11, -26, 34, 2, +55, 29, 70, 45, 72, 42, 71, 26, +57, 1, 41, -23, 22, -39, 11, -41, +7, -31, 13, -10, 23, 12, 25, 28, +26, 32, 21, 23, 17, 6, 13, -12, +10, -21, 16, -23, 27, -13, 46, 3, +61, 23, 72, 35, 72, 36, 65, 20, +47, -5, 22, -31, -1, -51, -18, -54, +-20, -41, -16, -14, 2, 15, 20, 42, +42, 57, 60, 56, 72, 38, 73, 14, +63, -12, 49, -30, 32, -35, 19, -31, +10, -17, 9, -1, 6, 15, 6, 19, +5, 15, 4, 5, 12, -7, 23, -16, +38, -11, 44, 6, 47, 25, 52, 38, +57, 40, 58, 36, 44, 20, 29, -1, +6, -23, -8, -38, -17, -44, -11, -34, +-1, -15, 16, 8, 37, 26, 50, 31, +64, 26, 65, 14, 59, 4, 46, -10, +36, -17, 23, -13, 10, 5, 4, 22, +6, 32, 16, 32, 21, 21, 24, 1, +25, -27, 28, -49, 30, -63, 31, -60, +38, -43, 40, -14, 44, 19, 42, 49, +41, 67, 38, 71, 32, 63, 21, 43, +8, 15, 3, -16, -1, -39, 5, -55, +10, -62, 25, -66, 36, -60, 46, -44, +50, -22, 52, 4, 51, 34, 41, 60, +35, 76, 25, 82, 17, 73, 8, 49, +7, 11, 9, -33, 9, -72, 14, -96, +17, -104, 26, -89, 35, -56, 43, -9, +48, 35, 50, 67, 49, 85, 42, 78, +39, 57, 30, 27, 22, -6, 10, -33, +3, -46, -3, -51, 6, -49, 20, -40, +30, -27, 41, -14, 44, -2, 45, 12, +39, 22, 35, 33, 28, 39, 25, 41, +20, 39, 14, 30, 15, 8, 19, -19, +27, -43, 27, -57, 26, -60, 21, -49, +19, -25, 24, 5, 27, 39, 35, 61, +37, 70, 40, 62, 37, 39, 37, 5, +33, -28, 24, -50, 17, -60, 7, -51, +6, -34, 6, -10, 20, 11, 32, 29, +43, 42, 43, 44, 41, 35, 38, 21, +33, 8, 27, 1, 19, -2, 16, -3, +14, -5, 17, -7, 24, -11, 29, -17, +36, -24, 38, -26, 34, -17, 24, -3, +18, 15, 14, 33, 16, 46, 21, 53, +26, 46, 37, 29, 40, 8, 42, -10, +38, -31, 35, -42, 23, -42, 13, -33, +7, -20, 7, -2, 13, 14, 22, 23, +36, 28, 40, 28, 45, 24, 42, 16, +39, 10, 33, 2, 26, -4, 19, -10, +13, -11, 16, -12, 20, -13, 30, -15, +40, -19, 44, -16, 43, -10, 29, 2, +17, 8, 7, 13, 5, 15, 4, 16, +8, 16, 16, 13, 29, 6, 49, -1, +62, -6, 70, -11, 61, -11, 42, -11, +17, -12, 1, -15, -13, -17, -20, -19, +-16, -18, -3, -14, 18, -7, 41, 3, +60, 13, 69, 26, 72, 29, 61, 28, +44, 18, 24, 4, 7, -11, -4, -24, +-10, -35, -5, -42, 3, -42, 16, -35, +30, -20, 37, -2, 41, 16, 36, 25, +37, 26, 38, 19, 44, 11, 46, 1, +49, -7, 46, -14, 40, -17, 31, -18, +14, -19, -2, -15, -18, -13, -21, -12, +-14, -15, 1, -12, 19, -6, 48, -1, +78, 6, 93, 17, 92, 23, 77, 22, +53, 18, 20, 9, -13, -2, -39, -15, +-50, -25, -41, -34, -17, -32, 15, -23, +47, -9, 77, 6, 91, 22, 87, 31, +71, 30, 46, 25, 22, 14, -1, 2, +-9, -9, -17, -12, -12, -13, -2, -9, +15, -2, 27, 4, 32, 8, 36, 10, +33, 7, 34, 1, 36, -4, 40, -2, +43, 2, 45, 7, 43, 13, 33, 17, +22, 17, 7, 16, -7, 9, -17, 0, +-14, -7, -4, -13, 13, -10, 34, -3, +48, 5, 66, 12, 67, 13, 61, 10, +43, 3, 24, -1, 4, -5, -7, -7, +-7, -1, -4, 8, 9, 19, 20, 25, +31, 29, 36, 21, 41, 2, 40, -22, +34, -39, 25, -47, 19, -41, 20, -28, +26, -6, 34, 20, 34, 44, 33, 59, +25, 57, 14, 43, 8, 16, 2, -12, +3, -39, 4, -51, 12, -50, 21, -39, +33, -20, 43, -2, 46, 12, 47, 20, +36, 24, 24, 24, 11, 19, 7, 11, +6, 3, 14, -4, 25, -9, 32, -13, +35, -17, 33, -24, 30, -30, 21, -31, +9, -28, -2, -18, -4, -6, 8, 11, +21, 24, 38, 34, 49, 33, 59, 27, +59, 16, 44, 1, 23, -13, 1, -29, +-12, -39, -19, -44, -18, -39, -8, -30, +12, -18, 29, -3, 45, 11, 53, 20, +61, 25, 61, 29, 51, 30, 37, 27, +21, 18, 11, 4, -1, -14, -7, -33, +-7, -51, -3, -61, 0, -57, 4, -40, +12, -15, 25, 13, 43, 41, 55, 63, +64, 73, 68, 65, 61, 46, 46, 14, +23, -19, 1, -50, -22, -68, -34, -71, +-39, -59, -30, -37, -7, -9, 21, 21, +54, 44, 78, 58, 89, 63, 84, 57, +68, 41, 43, 24, 15, 1, -12, -21, +-34, -35, -42, -43, -36, -46, -19, -41, +1, -25, 25, -7, 48, 13, 64, 33, +68, 51, 64, 59, 60, 59, 43, 47, +25, 27, 6, 1, -6, -23, -15, -40, +-23, -47, -22, -44, -16, -33, 2, -15, +20, 5, 40, 27, 51, 43, 64, 49, +69, 42, 62, 33, 43, 19, 24, 3, +3, -10, -20, -19, -28, -25, -27, -29, +-12, -25, 3, -19, 23, -5, 42, 6, +53, 15, 59, 20, 53, 22, 40, 21, +24, 16, 10, 7, 4, -4, -2, -9, +-3, -14, 3, -20, 15, -20, 23, -10, +26, 0, 23, 9, 18, 15, 11, 16, +10, 12, 13, 2, 18, -9, 30, -21, +39, -25, 43, -25, 38, -20, 31, -9, +21, 5, 8, 14, -4, 19, -13, 20, +-11, 15, -3, 5, 10, -7, 26, -18, +40, -24, 50, -27, 49, -26, 39, -18, +25, -9, 15, -1, 6, 6, 3, 8, +0, 7, 7, 3, 18, 0, 22, -3, +26, -4, 28, -5, 28, -3, 13, 2, +1, 6, -3, 4, 5, 0, 16, -8, +27, -16, 37, -21, 43, -22, 47, -22, +44, -15, 34, -1, 12, 12, -5, 22, +-19, 27, -23, 27, -18, 20, -4, 7, +16, -6, 33, -15, 47, -19, 57, -21, +58, -15, 50, -4, 32, 10, 14, 17, +-5, 18, -18, 13, -21, 5, -15, -5, +-3, -12, 10, -10, 23, 0, 34, 10, +40, 18, 41, 27, 42, 29, 33, 26, +24, 12, 11, -6, 4, -25, 7, -36, +10, -37, 16, -30, 19, -12, 21, 11, +20, 32, 13, 43, 11, 45, 11, 35, +17, 17, 18, -6, 19, -23, 26, -34, +38, -33, 41, -21, 36, -6, 27, 9, +17, 22, 5, 28, -5, 25, -5, 18, +-5, 6, 6, -2, 13, -5, 19, -3, +24, -3, 30, -4, 35, -6, 31, -9, +26, -11, 20, -13, 14, -10, 12, -5, +18, 6, 24, 18, 27, 29, 24, 30, +19, 25, 9, 14, -5, -6, -10, -28, +-10, -45, -4, -51, 3, -47, 14, -30, +37, -9, 59, 13, 75, 28, 72, 39, +55, 40, 31, 32, 4, 15, -19, -2, +-41, -14, -49, -24, -42, -30, -28, -31, +-7, -28, 22, -28, 54, -26, 73, -23, +74, -14, 72, -6, 68, 9, 47, 32, +15, 51, -13, 58, -26, 52, -37, 32, +-47, -1, -42, -34, -33, -65, -11, -83, +13, -84, 36, -62, 57, -28, 75, 11, +85, 49, 79, 74, 62, 82, 37, 69, +5, 42, -33, 4, -57, -32, -67, -58, +-56, -65, -42, -58, -14, -41, 22, -17, +52, 7, 79, 21, 93, 26, 95, 26, +74, 21, 41, 15, 12, 9, -14, 6, +-34, 3, -48, 5, -51, 3, -38, -7, +-15, -21, 9, -28, 30, -28, 46, -24, +61, -10, 65, 8, 58, 29, 49, 42, +38, 44, 27, 33, 3, 16, -14, -9, +-17, -33, -21, -49, -25, -51, -24, -37, +-6, -13, 16, 16, 29, 41, 41, 59, +49, 62, 54, 49, 51, 22, 42, -6, +27, -28, 6, -43, -10, -48, -19, -43, +-22, -27, -15, -5, -4, 17, 3, 34, +12, 43, 22, 42, 37, 37, 35, 26, +28, 13, 25, 1, 18, -10, 12, -20, +4, -29, 7, -29, 7, -25, 5, -12, +5, 2, 8, 17, 9, 28, 7, 36, +2, 37, 2, 29, 3, 14, 7, -7, +15, -25, 15, -36, 21, -34, 25, -27, +31, -11, 35, 6, 29, 24, 20, 35, +6, 32, -3, 19, -3, 2, -7, -15, +-13, -31, -12, -41, 5, -40, 22, -26, +25, -10, 31, 8, 40, 19, 41, 28, +32, 26, 17, 17, 9, 6, 2, -6, +-5, -14, -8, -17, -12, -14, -7, -13, +3, -11, 10, -13, 15, -13, 23, -15, +36, -13, 30, -6, 17, 1, 14, 9, +18, 15, 19, 22, 11, 20, 8, 13, +8, -1, 5, -14, 0, -25, 2, -30, +2, -29, 4, -21, 3, -7, 10, 5, +20, 14, 29, 15, 41, 13, 38, 5, +30, -3, 17, -11, 8, -14, -5, -9, +-20, 4, -26, 15, -24, 20, -16, 22, +3, 15, 28, 3, 40, -7, 44, -16, +48, -24, 51, -24, 28, -14, 0, 0, +-17, 14, -25, 24, -27, 23, -25, 18, +-11, 11, 5, 1, 21, -5, 40, -9, +48, -6, 51, 1, 42, 9, 21, 16, +-1, 19, -17, 12, -12, -2, -8, -16, +-14, -23, -7, -24, 9, -18, 23, -4, +25, 13, 22, 31, 23, 40, 15, 39, +6, 29, 4, 15, 10, -4, 20, -21, +20, -29, 21, -27, 20, -20, 13, -10, +6, 3, -9, 12, -17, 13, -18, 9, +-12, 8, -3, 7, 8, 6, 29, 10, +50, 19, 53, 23, 49, 18, 40, 9, +17, -3, -10, -19, -28, -38, -26, -48, +-32, -44, -31, -28, -15, -3, 10, 25, +35, 48, 45, 61, 51, 59, 45, 41, +27, 14, 9, -19, -1, -47, -2, -66, +-1, -66, -5, -52, 1, -27, 7, 0, +16, 24, 21, 36, 9, 35, 1, 29, +-1, 16, -1, 3, -1, -9, 5, -13, +29, -11, 44, -6, 43, -6, 39, -10, +30, -16, 16, -27, -9, -35, -29, -37, +-33, -29, -33, -12, -23, 14, -9, 42, +13, 60, 40, 60, 60, 48, 61, 21, +43, -14, 24, -48, 14, -71, -3, -77, +-18, -65, -26, -37, -23, -5, -12, 28, +-5, 50, 16, 58, 27, 49, 25, 32, +18, 11, 14, -9, 16, -23, 10, -26, +11, -20, 19, -14, 20, -8, 14, -2, +9, -1, 3, -10, 0, -18, -9, -21, +-11, -12, -12, 3, -6, 22, 8, 40, +13, 54, 18, 58, 27, 44, 34, 17, +26, -16, 7, -41, 4, -59, 4, -61, +-2, -49, -4, -25, 0, 5, 9, 29, +9, 44, 8, 48, 18, 42, 17, 27, +9, 11, -2, -4, -4, -12, 6, -15, +15, -12, 23, -8, 20, -5, 19, -7, +26, -13, 21, -16, 8, -16, -5, -8, +-9, 3, -11, 19, -23, 35, -15, 43, +3, 40, 14, 27, 23, 7, 30, -12, +36, -32, 31, -45, 23, -44, 16, -30, +7, -8, -1, 10, -1, 28, -6, 35, +-9, 33, -15, 24, -9, 9, 1, -9, +7, -22, 14, -24, 13, -18, 19, -8, +26, 3, 35, 10, 36, 7, 23, 5, +14, -2, 7, -8, -7, -14, -18, -15, +-18, -9, -13, 1, -17, 12, -22, 17, +1, 15, 22, 5, 34, -3, 35, -10, +34, -14, 38, -16, 32, -12, 19, -3, +1, 8, -15, 13, -16, 10, -19, 2, +-27, -10, -26, -19, -9, -26, 14, -23, +21, -11, 27, 8, 39, 22, 39, 32, +30, 35, 21, 26, 18, 8, 7, -15, +-14, -36, -21, -51, -19, -52, -15, -43, +-3, -21, 6, 4, 14, 28, 14, 43, +21, 49, 24, 47, 16, 32, 15, 10, +11, -9, 6, -23, -1, -30, 0, -30, +5, -27, 2, -20, -1, -12, 6, -4, +-1, 6, -11, 15, -12, 20, -2, 23, +9, 25, 8, 24, 27, 21, 39, 13, +37, 6, 24, -1, 15, -11, 11, -22, +-6, -26, -26, -25, -36, -22, -32, -14, +-12, -4, 7, 8, 18, 17, 30, 25, +38, 32, 44, 36, 31, 34, 12, 29, +5, 23, -12, 12, -30, -2, -34, -16, +-18, -29, 4, -40, 11, -45, 20, -40, +29, -26, 26, -4, 19, 19, 6, 37, +0, 52, -8, 61, -10, 57, 3, 42, +6, 24, 14, 5, 22, -16, 24, -33, +15, -45, -1, -51, -9, -51, -20, -44, +-28, -31, -12, -14, 6, 7, 20, 31, +31, 55, 42, 74, 48, 81, 32, 73, +20, 50, 2, 15, -26, -27, -47, -69, +-46, -98, -25, -108, -6, -96, 11, -64, +32, -17, 46, 36, 52, 82, 46, 112, +22, 117, 2, 93, -16, 46, -18, -7, +-21, -54, -23, -87, -2, -101, 16, -93, +21, -66, 20, -34, 25, 2, 28, 35, +8, 55, -8, 62, -4, 58, -2, 44, +1, 26, 2, 6, 12, -12, 25, -30, +28, -42, 27, -48, 9, -51, -5, -47, +-9, -37, -11, -17, -8, 7, -5, 31, +9, 51, 17, 62, 14, 58, 22, 42, +27, 17, 22, -16, 9, -48, 1, -71, +5, -76, 1, -64, 6, -37, 12, -2, +12, 29, 7, 49, 3, 60, 5, 55, +0, 37, -10, 14, -6, -12, 3, -27, +6, -33, 16, -30, 20, -22, 30, -10, +30, -1, 31, 6, 22, 7, -2, 6, +-13, 4, -17, 2, -20, 5, -24, 11, +-15, 16, 6, 15, 12, 12, 13, 6, +31, -2, 45, -12, 44, -17, 26, -18, +14, -10, 10, 2, -3, 12, -5, 20, +-13, 22, -23, 20, -24, 5, -20, -13, +-8, -30, 6, -37, 25, -32, 42, -14, +38, 11, 35, 39, 35, 59, 28, 62, +10, 52, -12, 28, -18, -2, -27, -35, +-34, -61, -21, -72, -7, -64, 9, -42, +24, -12, 36, 20, 40, 44, 26, 58, +21, 55, 20, 42, 12, 23, 3, 4, +-7, -13, -4, -21, -7, -22, -1, -19, +6, -15, 0, -14, -3, -18, -4, -22, +-1, -23, -1, -19, 8, -10, 27, 3, +31, 23, 20, 41, 27, 49, 33, 48, +25, 36, 3, 12, -11, -17, -11, -44, +-20, -63, -19, -68, -11, -56, 1, -32, +14, -1, 19, 28, 19, 48, 15, 54, +15, 43, 20, 26, 10, 4, 5, -16, +11, -25, 8, -24, 1, -14, -6, -5, +6, 6, 13, 11, -2, 10, -13, 2, +-16, -12, -10, -22, -5, -26, 4, -25, +21, -15, 23, 5, 24, 26, 30, 41, +30, 41, 28, 34, 16, 17, 3, -3, +-13, -22, -24, -37, -20, -41, -18, -34, +-17, -21, -8, -3, 2, 15, 12, 25, +20, 28, 32, 23, 41, 14, 33, 2, +34, -5, 30, -8, 17, -5, -5, 2, +-22, 6, -21, 8, -28, 3, -32, -6, +-26, -14, -10, -19, 14, -22, 33, -16, +48, -3, 52, 15, 44, 30, 38, 38, +18, 40, -5, 32, -16, 17, -29, -5, +-37, -23, -43, -34, -22, -37, 7, -30, +20, -15, 28, 3, 32, 22, 34, 37, +24, 43, 10, 39, 5, 30, -5, 19, +-14, 5, -8, -9, -2, -22, 8, -27, +12, -30, 15, -27, 10, -19, -3, -8, +-7, 7, -13, 20, -16, 33, -7, 41, +10, 44, 29, 39, 32, 30, 32, 12, +34, -9, 19, -33, 6, -52, -7, -60, +-20, -57, -31, -41, -32, -14, -11, 18, +8, 44, 22, 66, 30, 74, 32, 68, +29, 46, 16, 16, 5, -17, -2, -44, +-15, -62, -16, -67, -10, -57, -2, -37, +18, -11, 24, 16, 25, 36, 13, 44, +9, 48, 6, 45, -13, 35, -25, 18, +-18, -2, 2, -16, 14, -25, 14, -29, +25, -31, 34, -28, 23, -18, 13, -6, +-5, 4, -18, 18, -29, 28, -29, 33, +-16, 33, -2, 24, 22, 12, 35, -1, +32, -14, 29, -28, 24, -33, 17, -30, +-3, -19, -26, -2, -28, 18, -26, 32, +-17, 39, 3, 36, 23, 23, 33, 8, +28, -11, 28, -27, 24, -38, 6, -38, +-7, -27, -14, -9, -17, 12, -20, 35, +-17, 47, 0, 45, 10, 35, 18, 19, +23, 2, 20, -19, 21, -32, 13, -37, +11, -30, 4, -17, 1, 2, 3, 21, +-6, 32, -18, 36, -19, 31, -10, 21, +-4, 7, -5, -6, 3, -16, 19, -18, +23, -10, 28, 3, 29, 12, 31, 18, +23, 19, 3, 17, -10, 11, -23, 2, +-27, -6, -26, -13, -26, -13, -18, -7, +-2, 2, 19, 10, 32, 17, 31, 22, +41, 21, 42, 13, 30, 5, 15, 1, +-3, 0, -14, 1, -31, 2, -38, 7, +-38, 9, -36, 7, -24, 4, -6, 0, +16, -4, 36, -7, 48, -4, 55, 4, +45, 15, 28, 24, 13, 33, -10, 33, +-31, 25, -50, 11, -57, -3, -51, -18, +-31, -28, 2, -29, 26, -20, 39, -4, +49, 15, 52, 32, 47, 39, 24, 38, +-2, 28, -17, 8, -31, -16, -33, -32, +-30, -35, -17, -26, -3, -12, 8, 5, +22, 25, 23, 39, 22, 44, 18, 35, +9, 18, 1, -3, -2, -20, -6, -30, +-11, -31, -16, -26, -4, -12, 8, 6, +8, 24, 2, 39, -3, 42, 5, 37, +3, 25, 3, 13, 7, 0, 4, -11, +-3, -18, -10, -19, -11, -17, -5, -15, +-5, -7, -2, 2, 0, 8, 5, 14, +19, 23, 24, 32, 23, 38, 11, 36, +1, 28, -9, 16, -24, 1, -29, -17, +-27, -32, -23, -37, -14, -32, -3, -16, +13, 3, 24, 21, 31, 36, 43, 45, +36, 46, 21, 39, 2, 23, -13, 5, +-24, -12, -36, -25, -34, -29, -26, -25, +-20, -12, -15, 6, -5, 21, 8, 31, +23, 34, 33, 28, 36, 22, 25, 15, +18, 10, 11, 8, -4, 7, -21, 7, +-38, 9, -43, 8, -45, 1, -38, -3, +-18, -7, 4, -6, 20, -1, 31, 7, +42, 13, 51, 21, 41, 31, 19, 35, +-4, 30, -30, 18, -40, 3, -47, -13, +-41, -20, -31, -19, -13, -11, 12, 3, +24, 20, 28, 31, 30, 35, 23, 31, +9, 20, -3, 2, -10, -16, -16, -21, +-23, -16, -17, -1, -10, 17, -1, 34, +3, 46, 1, 48, -3, 40, -13, 19, +-13, -9, -5, -36, -1, -49, 2, -47, +6, -30, 10, -2, 17, 29, 13, 56, +4, 74, -13, 73, -25, 56, -28, 31, +-33, 2, -29, -22, -22, -37, -7, -36, +4, -24, 8, -8, 13, 10, 17, 23, +12, 26, 4, 25, -5, 20, -9, 13, +-15, 11, -18, 14, -15, 22, -17, 30, +-9, 36, -11, 33, -10, 21, -13, 1, +-13, -17, -6, -33, -4, -40, -1, -36, +4, -20, 9, 7, 11, 35, 10, 60, +5, 72, -1, 70, -21, 56, -34, 33, +-40, 1, -37, -24, -32, -37, -24, -38, +-8, -29, 6, -13, 22, 4, 33, 19, +31, 34, 20, 38, 5, 37, -11, 29, +-25, 20, -39, 15, -44, 12, -42, 10, +-32, 9, -15, 9, -2, 5, 10, 0, +16, -3, 20, -4, 19, -3, 10, 1, +-2, 11, -13, 24, -28, 34, -36, 41, +-39, 42, -33, 35, -24, 22, -19, 6, +-7, -6, 2, -16, 15, -17, 17, -11, +13, 0, 5, 11, -6, 23, -13, 32, +-23, 34, -31, 32, -31, 25, -28, 19, +-24, 15, -18, 11, -11, 6, 2, 6, +3, 6, 4, 7, 1, 7, -3, 6, +-7, 6, -14, 7, -15, 10, -18, 15, +-19, 22, -18, 26, -20, 30, -23, 29, +-22, 26, -18, 18, -11, 9, -11, 2, +-7, 0, -5, 3, -6, 8, -1, 13, +-5, 19, -10, 23, -21, 24, -31, 23, +-32, 15, -32, 9, -30, 5, -21, 5, +-13, 11, -6, 19, 1, 27, 9, 34, +6, 38, -6, 34, -16, 24, -30, 10, +-35, -8, -36, -22, -32, -28, -24, -25, +-13, -13, 2, 6, 7, 32, 2, 55, +-2, 65, -7, 64, -17, 54, -29, 36, +-41, 12, -41, -10, -38, -27, -28, -34, +-14, -31, -2, -18, 9, -2, 7, 17, +3, 34, -2, 41, -11, 44, -24, 41, +-37, 33, -47, 24, -46, 20, -43, 19, +-34, 19, -25, 15, -11, 9, 3, 5, +4, 1, 6, -4, 1, -7, -6, -6, +-16, -4, -26, 6, -36, 21, -44, 37, +-47, 46, -42, 51, -37, 48, -30, 40, +-21, 27, -12, 10, -1, -1, -1, -6, +-1, -4, -6, 0, -10, 7, -20, 13, +-33, 19, -44, 22, -49, 19, -46, 13, +-41, 8, -36, 8, -24, 10, -9, 23, +0, 39, 2, 52, -1, 55, -1, 48, +-13, 37, -27, 17, -37, -11, -41, -34, +-41, -45, -46, -43, -44, -29, -34, -6, +-20, 24, -11, 54, -6, 78, -7, 86, +-5, 81, -9, 63, -15, 36, -24, 7, +-32, -20, -36, -36, -44, -42, -47, -38, +-47, -26, -40, -5, -34, 19, -28, 41, +-18, 53, -5, 60, 0, 65, -4, 65, +-13, 56, -21, 39, -30, 20, -46, 2, +-56, -18, -64, -33, -56, -39, -46, -33, +-34, -15, -18, 8, -9, 34, 0, 60, +2, 79, -6, 87, -19, 79, -34, 54, +-46, 20, -52, -10, -57, -36, -52, -47, +-48, -44, -35, -27, -24, 0, -21, 31, +-18, 56, -16, 70, -17, 73, -24, 62, +-31, 44, -35, 22, -36, 3, -37, -13, +-36, -20, -36, -19, -31, -11, -31, 1, +-36, 14, -42, 26, -45, 33, -39, 39, +-37, 39, -30, 38, -23, 34, -16, 31, +-14, 25, -19, 19, -26, 11, -32, 1, +-42, -5, -56, -7, -62, -5, -59, 0, +-46, 12, -36, 27, -25, 39, -21, 49, +-15, 53, -18, 47, -24, 34, -33, 18, +-43, 3, -50, -6, -57, -6, -57, 0, +-50, 8, -40, 20, -33, 33, -28, 43, +-30, 41, -31, 35, -38, 25, -44, 13, +-47, 3, -48, 0, -46, 4, -42, 12, +-34, 22, -30, 33, -30, 44, -33, 47, +-37, 43, -46, 31, -52, 14, -57, 1, +-52, -6, -50, -5, -48, -1, -40, 7, +-35, 18, -28, 30, -31, 38, -35, 43, +-41, 43, -44, 40, -49, 32, -54, 27, +-58, 24, -54, 22, -51, 20, -52, 19, +-52, 14, -47, 5, -36, 1, -37, 1, +-39, 5, -40, 11, -37, 22, -37, 32, +-42, 43, -48, 51, -54, 54, -56, 47, +-57, 32, -54, 17, -51, 3, -46, -6, +-41, -12, -33, -8, -32, 3, -34, 17, +-44, 31, -55, 40, -62, 39, -65, 34, +-62, 30, -60, 24, -54, 20, -45, 19, +-36, 24, -31, 31, -30, 37, -38, 37, +-45, 31, -57, 20, -66, 10, -72, -3, +-74, -14, -66, -15, -56, -5, -45, 14, +-41, 34, -37, 55, -34, 68, -35, 72, +-41, 61, -51, 44, -61, 24, -65, 3, +-67, -15, -68, -23, -66, -18, -62, -7, +-53, 12, -56, 31, -59, 47, -58, 54, +-51, 55, -46, 46, -45, 35, -43, 23, +-39, 15, -38, 13, -47, 15, -58, 18, +-66, 18, -72, 18, -83, 16, -86, 16, +-83, 11, -68, 8, -52, 10, -40, 16, +-31, 30, -27, 43, -26, 51, -33, 53, +-47, 51, -65, 41, -81, 28, -95, 13, +-100, -1, -97, -13, -80, -15, -63, -8, +-49, 8, -35, 26, -30, 42, -29, 56, +-36, 59, -43, 56, -59, 47, -74, 33, +-82, 16, -84, 5, -85, -2, -81, -2, +-73, 5, -67, 17, -65, 27, -62, 30, +-54, 33, -50, 35, -47, 34, -53, 32, +-59, 30, -63, 29, -63, 31, -70, 33, +-78, 32, -80, 27, -78, 24, -77, 18, +-78, 11, -73, 10, -66, 11, -57, 13, +-57, 19, -60, 32, -61, 39, -58, 43, +-62, 47, -73, 46, -77, 39, -76, 31, +-75, 23, -79, 14, -75, 8, -69, 3, +-61, 5, -60, 6, -59, 11, -63, 20, +-66, 31, -70, 37, -73, 42, -72, 46, +-76, 48, -75, 45, -75, 37, -69, 26, +-67, 14, -66, 3, -66, -5, -65, -7, +-69, -1, -75, 12, -75, 28, -74, 43, +-76, 58, -82, 63, -82, 61, -79, 49, +-73, 31, -72, 14, -71, 1, -69, -5, +-66, -2, -66, 8, -71, 23, -73, 38, +-76, 49, -80, 50, -86, 42, -89, 32, +-90, 20, -83, 10, -82, 5, -76, 13, +-68, 24, -60, 37, -59, 50, -66, 58, +-69, 55, -74, 39, -78, 17, -88, -5, +-91, -19, -89, -24, -83, -13, -81, 8, +-77, 34, -71, 57, -64, 70, -65, 76, +-76, 71, -81, 53, -84, 27, -82, 1, +-86, -13, -85, -12, -82, -5, -73, 5, +-68, 21, -69, 36, -76, 43, -83, 41, +-89, 32, -95, 22, -95, 18, -97, 18, +-89, 28, -80, 39, -69, 52, -63, 60, +-62, 59, -62, 46, -68, 24, -81, 1, +-99, -18, -109, -30, -112, -29, -108, -12, +-102, 15, -89, 48, -76, 78, -66, 97, +-66, 98, -67, 83, -69, 55, -74, 21, +-86, -9, -101, -30, -99, -37, -96, -28, +-95, -4, -96, 21, -89, 44, -84, 62, +-83, 70, -87, 62, -85, 46, -80, 28, +-78, 15, -81, 11, -88, 12, -84, 19, +-81, 26, -81, 36, -90, 42, -96, 43, +-100, 36, -103, 24, -106, 11, -103, 4, +-94, 3, -86, 8, -79, 18, -74, 30, +-69, 45, -74, 55, -78, 61, -91, 60, +-104, 55, -112, 38, -114, 23, -113, 13, +-110, 6, -100, 3, -88, 1, -77, 8, +-72, 16, -70, 26, -74, 34, -78, 41, +-85, 44, -93, 47, -108, 50, -118, 49, +-118, 43, -112, 33, -104, 24, -98, 18, +-86, 12, -77, 8, -71, 7, -72, 8, +-71, 12, -74, 18, -84, 28, -103, 39, +-118, 48, -123, 52, -122, 50, -117, 47, +-111, 41, -93, 31, -76, 21, -66, 16, +-67, 10, -69, 7, -71, 5, -82, 5, +-101, 11, -117, 21, -123, 35, -125, 47, +-123, 56, -114, 59, -97, 58, -85, 50, +-76, 38, -74, 24, -73, 9, -79, -1, +-90, -6, -102, -6, -109, 2, -109, 18, +-112, 38, -112, 56, -111, 65, -104, 67, +-101, 59, -96, 46, -93, 26, -87, 9, +-85, -1, -85, -5, -85, 0, -88, 11, +-93, 26, -103, 40, -109, 48, -116, 47, +-121, 43, -127, 34, -119, 23, -104, 15, +-90, 18, -83, 28, -75, 37, -65, 41, +-66, 44, -78, 44, -99, 37, -113, 22, +-127, 4, -138, -8, -143, -16, -130, -11, +-109, 7, -91, 31, -76, 53, -63, 74, +-56, 85, -63, 81, -81, 66, -102, 39, +-115, 12, -133, -11, -143, -27, -143, -32, +-129, -21, -111, 0, -95, 24, -80, 44, +-68, 58, -64, 67, -73, 66, -85, 58, +-101, 46, -112, 37, -124, 27, -130, 21, +-133, 19, -126, 19, -116, 16, -106, 11, +-95, 7, -90, 4, -86, 4, -86, 7, +-85, 16, -88, 34, -92, 54, -103, 70, +-111, 79, -119, 78, -125, 68, -127, 46, +-126, 18, -118, -7, -113, -25, -104, -30, +-94, -25, -80, -5, -75, 21, -78, 46, +-84, 64, -93, 73, -105, 72, -121, 64, +-135, 47, -138, 27, -131, 12, -124, 3, +-112, 1, -100, 8, -82, 21, -77, 31, +-79, 38, -87, 37, -93, 34, -101, 26, +-113, 19, -122, 18, -126, 20, -120, 25, +-117, 32, -114, 41, -109, 44, -98, 44, +-93, 40, -93, 32, -97, 22, -98, 16, +-98, 15, -104, 17, -108, 24, -111, 32, +-115, 40, -120, 40, -120, 35, -117, 26, +-109, 19, -105, 15, -101, 15, -97, 21, +-94, 32, -96, 45, -101, 57, -107, 65, +-118, 61, -123, 48, -128, 29, -125, 10, +-118, -6, -106, -14, -97, -13, -86, -1, +-80, 18, -84, 40, -94, 59, -108, 67, +-117, 67, -127, 57, -133, 43, -134, 26, +-122, 11, -110, 4, -99, 6, -90, 10, +-81, 16, -80, 23, -92, 31, -107, 37, +-121, 40, -129, 40, -135, 37, -136, 37, +-129, 35, -110, 34, -97, 34, -89, 31, +-85, 27, -81, 20, -86, 12, -99, 7, +-109, 7, -117, 10, -117, 19, -122, 30, +-124, 44, -121, 53, -112, 56, -107, 51, +-104, 42, -105, 32, -104, 20, -102, 9, +-101, -1, -96, 0, -97, 10, -99, 24, +-105, 34, -110, 44, -118, 48, -124, 48, +-127, 44, -126, 37, -121, 31, -112, 25, +-100, 20, -90, 15, -79, 13, -77, 14, +-81, 16, -95, 17, -108, 21, -124, 24, +-136, 32, -144, 41, -140, 47, -126, 51, +-114, 50, -96, 43, -79, 31, -67, 20, +-71, 8, -80, -1, -94, -4, -107, -1, +-125, 10, -137, 25, -140, 39, -134, 52, +-122, 57, -112, 54, -97, 45, -84, 30, +-73, 17, -77, 8, -84, 7, -94, 10, +-104, 19, -117, 28, -130, 35, -136, 40, +-133, 38, -125, 30, -118, 19, -106, 13, +-92, 9, -80, 13, -76, 22, -74, 34, +-79, 48, -92, 57, -110, 56, -128, 47, +-137, 28, -137, 5, -130, -10, -125, -14, +-115, -6, -102, 10, -87, 30, -78, 48, +-70, 60, -73, 64, -84, 60, -102, 45, +-119, 25, -130, 8, -141, 0, -142, 0, +-136, 8, -122, 23, -109, 37, -94, 49, +-81, 50, -70, 41, -70, 29, -79, 14, +-91, 3, -104, -1, -118, 7, -133, 22, +-136, 39, -134, 56, -129, 67, -125, 65, +-115, 55, -104, 36, -89, 11, -78, -14, +-71, -28, -69, -24, -73, -7, -83, 16, +-100, 41, -115, 66, -133, 79, -146, 75, +-151, 57, -145, 35, -128, 10, -105, -9, +-84, -17, -67, -12, -54, 3, -51, 20, +-59, 36, -78, 45, -101, 52, -130, 50, +-151, 41, -164, 26, -160, 15, -143, 10, +-116, 12, -90, 19, -67, 27, -52, 37, +-50, 39, -56, 34, -73, 25, -94, 18, +-120, 9, -139, 6, -149, 8, -146, 16, +-133, 27, -116, 40, -100, 52, -86, 55, +-75, 48, -72, 36, -72, 21, -77, 6, +-86, -4, -99, -10, -107, -7, -111, 4, +-114, 22, -118, 40, -121, 52, -119, 57, +-112, 53, -102, 43, -97, 28, -86, 16, +-77, 6, -74, 3, -81, 3, -85, 7, +-92, 13, -103, 24, -116, 33, -126, 40, +-127, 43, -124, 39, -114, 33, -103, 24, +-85, 19, -71, 15, -66, 14, -73, 16, +-81, 17, -91, 21, -105, 28, -119, 33, +-128, 33, -125, 32, -119, 28, -108, 24, +-99, 18, -84, 15, -74, 14, -71, 16, +-77, 20, -84, 25, -93, 31, -102, 37, +-110, 41, -119, 39, -118, 33, -117, 25, +-111, 19, -107, 14, -99, 11, -93, 11, +-84, 16, -79, 21, -78, 30, -81, 38, +-91, 45, -97, 45, -104, 34, -109, 27, +-119, 19, -119, 13, -116, 8, -107, 10, +-97, 14, -85, 22, -75, 31, -72, 35, +-74, 36, -81, 34, -88, 27, -99, 18, +-109, 12, -120, 10, -120, 15, -114, 21, +-103, 30, -93, 37, -82, 40, -72, 40, +-74, 34, -78, 21, -84, 7, -90, -2, +-100, -5, -109, -1, -113, 11, -108, 27, +-101, 43, -94, 55, -93, 62, -90, 58, +-86, 43, -87, 23, -90, 4, -94, -8, +-93, -10, -94, -7, -93, 7, -94, 24, +-92, 38, -91, 49, -93, 51, -98, 44, +-99, 31, -100, 17, -101, 4, -96, 1, +-94, 8, -84, 20, -81, 33, -77, 45, +-81, 52, -88, 50, -96, 39, -103, 19, +-106, -4, -106, -20, -102, -27, -95, -19, +-84, 1, -77, 29, -73, 56, -76, 72, +-73, 79, -83, 74, -96, 56, -104, 26, +-105, -2, -103, -20, -105, -28, -98, -26, +-90, -15, -79, 7, -74, 27, -74, 44, +-77, 53, -83, 57, -93, 54, -101, 44, +-105, 32, -103, 25, -96, 21, -91, 18, +-83, 18, -82, 17, -78, 14, -77, 7, +-80, 1, -86, -3, -89, -4, -93, 2, +-96, 15, -97, 34, -94, 54, -92, 66, +-88, 69, -83, 65, -83, 49, -77, 25, +-76, 0, -76, -19, -83, -29, -87, -28, +-91, -16, -95, 3, -97, 24, -96, 42, +-92, 54, -88, 60, -80, 57, -75, 44, +-69, 32, -71, 20, -69, 10, -73, 3, +-80, 0, -92, 2, -98, 5, -100, 10, +-106, 15, -102, 21, -97, 26, -86, 33, +-81, 36, -74, 40, -67, 39, -62, 39, +-67, 35, -75, 26, -85, 15, -90, 8, +-93, 1, -98, -2, -97, 1, -97, 6, +-86, 17, -82, 27, -80, 35, -76, 38, +-71, 37, -68, 33, -71, 27, -74, 18, +-71, 10, -71, 9, -80, 12, -87, 14, +-92, 15, -90, 16, -96, 16, -95, 18, +-93, 18, -86, 20, -74, 22, -68, 23, +-59, 24, -54, 27, -51, 29, -60, 25, +-72, 22, -87, 18, -101, 13, -113, 6, +-111, 2, -104, 5, -90, 11, -73, 21, +-60, 30, -50, 37, -49, 39, -48, 34, +-59, 26, -72, 17, -89, 7, -102, 2, +-108, 2, -102, 7, -96, 14, -84, 23, +-68, 29, -58, 33, -55, 32, -57, 22, +-55, 13, -66, 5, -74, 3, -84, 6, +-89, 12, -89, 21, -86, 30, -81, 36, +-80, 39, -77, 35, -73, 24, -74, 14, +-77, 5, -74, -1, -72, -2, -64, 5, +-65, 15, -66, 25, -69, 31, -69, 35, +-74, 34, -86, 29, -89, 19, -93, 9, +-89, 6, -82, 6, -73, 15, -66, 26, +-58, 33, -56, 34, -54, 33, -61, 26, +-68, 14, -80, 3, -91, -7, -88, -8, +-95, 1, -94, 16, -89, 30, -73, 43, +-63, 50, -54, 50, -49, 42, -50, 30, +-57, 15, -65, -3, -72, -15, -76, -16, +-82, -10, -91, -2, -86, 9, -82, 21, +-72, 33, -70, 39, -65, 40, -59, 35, +-55, 28, -52, 26, -60, 24, -66, 18, +-66, 12, -69, 9, -78, 5, -82, 1, +-84, -2, -76, -4, -75, -3, -69, 7, +-67, 17, -63, 27, -55, 39, -59, 47, +-60, 50, -64, 45, -66, 37, -73, 21, +-78, 4, -75, -10, -69, -17, -68, -17, +-67, -11, -68, -1, -61, 11, -55, 24, +-64, 38, -70, 46, -73, 44, -66, 36, +-69, 26, -65, 16, -60, 6, -57, -1, +-54, -3, -54, 0, -61, 4, -69, 7, +-73, 12, -76, 16, -76, 19, -76, 21, +-68, 23, -65, 22, -54, 21, -49, 21, +-47, 22, -48, 21, -57, 17, -67, 13, +-78, 10, -78, 8, -78, 4, -75, 1, +-67, 3, -56, 10, -52, 20, -49, 28, +-55, 32, -59, 33, -61, 28, -65, 20, +-71, 13, -78, 6, -69, 0, -68, -2, +-61, 1, -54, 9, -51, 18, -53, 25, +-54, 28, -58, 28, -62, 23, -62, 15, +-61, 6, -64, 1, -68, 1, -61, 3, +-57, 3, -48, 8, -54, 17, -59, 24, +-57, 24, -56, 22, -61, 20, -67, 16, +-61, 11, -59, 7, -60, 7, -59, 8, +-54, 11, -56, 13, -56, 15, -58, 15, +-55, 14, -59, 15, -62, 18, -66, 17, +-64, 15, -52, 12, -54, 13, -56, 15, +-53, 11, -48, 10, -52, 9, -56, 10, +-60, 12, -63, 15, -66, 16, -63, 17, +-64, 21, -63, 22, -57, 22, -58, 20, +-54, 18, -54, 11, -49, 7, -51, 7, +-52, 8, -53, 8, -57, 11, -59, 17, +-63, 20, -69, 19, -63, 16, -55, 16, +-58, 16, -57, 14, -51, 11, -39, 13, +-42, 14, -44, 14, -48, 13, -54, 12, +-57, 10, -64, 6, -66, 3, -65, 3, +-61, 9, -58, 15, -53, 25, -50, 33, +-47, 36, -51, 33, -49, 29, -55, 18, +-57, 5, -58, -5, -63, -14, -55, -16, +-51, -9, -44, 6, -46, 18, -47, 32, +-49, 39, -55, 42, -56, 35, -54, 20, +-62, 6, -62, -4, -52, -12, -41, -16, +-37, -9, -41, 3, -35, 17, -42, 24, +-49, 29, -59, 26, -62, 17, -59, 7, +-62, 2, -59, -2, -47, -4, -35, 4, +-34, 14, -37, 23, -38, 29, -41, 31, +-57, 23, -59, 10, -65, -3, -63, -10, +-56, -14, -48, -10, -41, 2, -40, 14, +-31, 28, -34, 36, -41, 37, -52, 32, +-60, 23, -66, 8, -65, -2, -67, -7, +-61, -8, -47, -4, -30, 4, -26, 14, +-28, 24, -23, 28, -37, 25, -51, 20, +-64, 11, -67, 2, -67, -6, -68, -6, +-61, -1, -46, 6, -28, 17, -22, 28, +-28, 34, -28, 30, -28, 21, -41, 8, +-50, -4, -60, -12, -64, -14, -69, -11, +-61, -2, -52, 10, -48, 24, -37, 35, +-33, 42, -32, 41, -32, 32, -36, 19, +-41, 3, -43, -10, -49, -18, -48, -18, +-53, -13, -51, -1, -56, 11, -55, 23, +-40, 32, -41, 36, -43, 36, -44, 26, +-35, 17, -34, 7, -37, -2, -39, -7, +-42, -8, -41, -8, -37, -5, -42, 1, +-41, 10, -41, 16, -47, 20, -46, 20, +-47, 17, -42, 16, -50, 13, -48, 11, +-41, 10, -37, 9, -31, 11, -32, 15, +-37, 17, -39, 14, -37, 10, -42, 8, +-53, 7, -63, 1, -59, -2, -54, 0, +-42, 7, -42, 13, -36, 21, -21, 26, +-18, 28, -21, 26, -31, 20, -35, 14, +-48, 3, -61, -7, -61, -13, -57, -12, +-53, -8, -41, -1, -34, 9, -20, 19, +-12, 25, -17, 27, -29, 26, -41, 22, +-40, 14, -54, 4, -58, -2, -55, -3, +-50, 0, -41, 6, -33, 11, -29, 15, +-27, 15, -26, 11, -27, 7, -35, 2, +-42, -1, -42, 0, -49, 6, -42, 17, +-44, 25, -41, 32, -33, 30, -28, 24, +-30, 15, -38, 2, -32, -13, -34, -25, +-45, -26, -45, -20, -35, -6, -33, 13, +-32, 31, -34, 43, -26, 49, -25, 46, +-29, 34, -39, 18, -48, -2, -42, -23, +-46, -34, -45, -33, -39, -24, -34, -9, +-31, 10, -24, 26, -19, 39, -22, 48, +-29, 43, -28, 29, -33, 14, -38, 1, +-37, -10, -43, -19, -40, -21, -41, -15, +-36, -5, -31, 1, -23, 7, -24, 13, +-33, 21, -27, 24, -23, 22, -32, 18, +-33, 13, -28, 13, -28, 13, -33, 14, +-40, 10, -35, 4, -36, -6, -32, -14, +-32, -16, -34, -15, -25, -12, -26, -6, +-27, 10, -26, 27, -22, 38, -25, 43, +-32, 43, -32, 34, -30, 19, -37, 3, +-37, -12, -45, -24, -47, -29, -38, -25, +-33, -13, -27, 3, -28, 18, -16, 32, +-13, 40, -12, 40, -13, 31, -25, 20, +-32, 9, -39, -2, -53, -9, -57, -12, +-50, -10, -42, -6, -35, 2, -23, 7, +2, 10, 5, 14, 4, 15, -5, 10, +-12, 6, -18, 3, -36, 2, -55, 2, +-59, 1, -48, 2, -39, 3, -33, 6, +-18, 7, -4, 8, -4, 8, 2, 10, +-9, 12, -23, 11, -33, 7, -39, 6, +-42, 7, -50, 8, -44, 9, -37, 6, +-26, 3, -15, 2, -11, 5, -10, 4, +-10, 5, -21, 7, -25, 7, -21, 6, +-18, 7, -28, 9, -35, 9, -20, 8, +-20, 5, -22, 3, -29, 1, -31, -3, +-28, -3, -30, 1, -34, 5, -30, 7, +-16, 10, -8, 16, -12, 22, -5, 21, +-3, 19, -20, 15, -30, 8, -39, -4, +-39, -12, -45, -13, -48, -8, -43, 0, +-37, 9, -15, 17, 0, 24, 3, 28, +4, 28, 0, 24, -6, 14, -15, 3, +-34, -8, -47, -15, -49, -19, -40, -14, +-42, -5, -36, 2, -10, 11, 0, 18, +6, 23, 9, 22, 9, 19, 1, 14, +-19, 9, -35, 4, -42, -1, -45, -4, +-46, -4, -50, -2, -34, 1, -13, 6, +-6, 7, 1, 11, 2, 13, 6, 16, +-2, 16, -10, 16, -21, 13, -36, 9, +-36, 4, -33, -2, -32, -6, -26, -8, +-18, -10, -9, -7, -5, 2, -7, 7, +-5, 14, -12, 19, -12, 25, -21, 23, +-27, 19, -17, 10, -16, 0, -18, -7, +-18, -11, -9, -10, -10, -6, -21, -3, +-23, 0, -21, 7, -19, 13, -15, 16, +-22, 17, -18, 16, -8, 14, -7, 12, +-7, 12, -11, 9, -10, 8, -21, 6, +-26, 5, -26, 2, -30, -1, -27, -2, +-23, -1, -19, -2, -6, -2, 2, 3, +4, 11, -3, 17, -8, 19, -8, 21, +-18, 18, -18, 9, -24, -2, -26, -8, +-15, -12, -6, -13, -6, -10, -12, -2, +-7, 9, -6, 16, -14, 19, -14, 17, +-16, 14, -18, 9, -14, 5, -19, 1, +-12, -2, -7, 0, -7, 5, -12, 10, +-15, 17, -9, 20, -21, 19, -25, 13, +-19, 3, -16, -1, -13, -5, -8, -11, +-3, -10, -1, -4, 1, 3, 7, 12, +-5, 19, -17, 24, -21, 24, -26, 16, +-18, 7, -18, 1, -19, -3, -12, -4, +-3, -4, 2, -1, 2, 4, 5, 9, +2, 13, -13, 12, -16, 8, -13, 4, +-19, 3, -26, 5, -31, 5, -17, 6, +-4, 9, 2, 14, 1, 19, 0, 20, +11, 17, 5, 11, -8, 3, -13, -7, +-16, -13, -21, -15, -23, -12, -18, -7, +-14, 4, -15, 18, -4, 29, -1, 36, +0, 38, 1, 32, -2, 18, -1, 3, +-4, -12, -5, -19, -9, -23, -12, -21, +-13, -14, -14, -2, -5, 11, -2, 24, +-15, 33, -17, 34, -8, 28, -1, 18, +-3, 8, -8, -1, 1, -7, 5, -12, +10, -10, 6, -6, -3, 0, -1, 6, +-9, 10, -20, 11, -21, 9, -19, 8, +-20, 7, -18, 7, -1, 6, 13, 9, +18, 13, 25, 17, 16, 18, 8, 14, +3, 8, -11, 0, -27, -9, -38, -16, +-34, -17, -25, -13, -11, -4, 4, 8, +12, 22, 26, 34, 35, 43, 22, 39, +8, 28, -1, 11, -12, -7, -26, -22, +-34, -32, -24, -34, -18, -29, -4, -13, +4, 9, 11, 30, 23, 40, 22, 44, +13, 40, 5, 29, 3, 12, -2, -5, +-18, -15, -21, -22, -12, -23, -7, -18, +5, -7, 7, 1, 9, 11, 10, 19, +10, 20, 7, 17, -2, 10, -1, 4, +-1, 2, -2, 4, 2, 7, 3, 11, +4, 14, 8, 15, 5, 9, 3, 2, +0, -4, -3, -11, -14, -15, -16, -16, +-1, -11, 4, 1, 5, 17, 7, 31, +13, 41, 19, 44, 17, 36, 9, 22, +-2, 6, -6, -14, -5, -30, -11, -38, +-9, -35, -4, -21, -5, -3, 4, 17, +12, 31, 19, 39, 19, 40, 18, 33, +16, 19, 7, 6, 4, -5, -4, -14, +-13, -16, -10, -13, -4, -6, 1, 1, +5, 11, 4, 14, 8, 14, 14, 8, +23, 2, 14, 1, 1, 2, 6, 4, +8, 9, 5, 15, 3, 19, 5, 20, +10, 14, 10, 5, 10, -4, 7, -13, +4, -19, 3, -19, -6, -14, -2, -4, +9, 7, 12, 18, 13, 30, 16, 33, +24, 30, 23, 21, 17, 8, 10, -8, +1, -17, 0, -19, -4, -17, -10, -12, +-9, -1, -2, 11, 11, 18, 19, 22, +23, 21, 26, 16, 23, 9, 24, 2, +15, -4, 2, -3, -2, -2, -4, 0, +-6, 6, -7, 12, 3, 15, 11, 13, +12, 9, 17, 3, 20, 0, 22, -6, +22, -8, 12, -8, 10, -3, 13, 7, +11, 15, 6, 19, 2, 21, 5, 25, +1, 21, 2, 13, 5, 2, 3, -8, +10, -18, 20, -20, 22, -14, 23, -7, +24, 3, 25, 13, 18, 22, 11, 29, +7, 31, -3, 26, -6, 18, -10, 6, +-6, -4, 6, -11, 15, -12, 18, -10, +20, -7, 33, 0, 37, 8, 25, 14, +17, 13, 11, 14, 4, 13, 2, 11, +-5, 8, -5, 6, 0, 5, 11, 6, +19, 5, 24, 2, 33, 2, 29, 1, +23, -2, 22, -5, 16, -4, 9, -1, +2, 4, -1, 10, 0, 19, 3, 24, +12, 25, 13, 21, 17, 13, 27, 4, +28, -8, 27, -12, 17, -15, 10, -14, +11, -11, 12, 0, 10, 13, 2, 24, +7, 29, 16, 29, 16, 24, 20, 13, +23, 3, 21, -8, 18, -16, 16, -18, +16, -14, 14, -9, 17, -2, 17, 8, +15, 18, 23, 23, 22, 24, 16, 19, +15, 11, 14, 6, 12, 1, 7, -3, +6, -6, 8, -5, 12, -3, 23, 0, +27, 1, 30, 2, 37, 3, 33, 5, +27, 7, 20, 7, 13, 8, 5, 9, +-1, 8, 3, 5, 7, 4, 16, 0, +25, 0, 24, -2, 30, -5, 39, -5, +40, -4, 29, 3, 15, 10, 9, 18, +0, 21, -1, 21, 0, 14, 3, 7, +16, 0, 28, -8, 34, -11, 34, -9, +33, -5, 32, 1, 21, 9, 15, 16, +10, 18, 7, 16, 11, 15, 10, 10, +13, 5, 20, 1, 23, 0, 20, -2, +18, -3, 24, 0, 24, 3, 16, 9, +13, 13, 11, 15, 18, 13, 24, 13, +21, 12, 18, 12, 18, 8, 24, 3, +21, -2, 15, -5, 17, -7, 16, -9, +20, -7, 24, -4, 24, 1, 28, 6, +32, 10, 35, 12, 30, 16, 25, 21, +19, 22, 7, 15, 8, 2, 14, -7, +16, -14, 21, -18, 22, -18, 24, -9, +29, -2, 34, 6, 33, 13, 27, 19, +28, 21, 28, 21, 20, 19, 14, 14, +7, 7, 8, -3, 16, -12, 22, -18, +26, -16, 28, -12, 34, -5, 33, 1, +31, 8, 34, 14, 27, 16, 21, 16, +19, 12, 16, 10, 16, 7, 13, 5, +12, 3, 13, 1, 22, -2, 31, -3, +27, -1, 27, -1, 31, -1, 31, 1, +31, 3, 28, 1, 25, 5, 19, 10, +17, 12, 17, 13, 11, 15, 13, 12, +15, 7, 16, 2, 26, -2, 32, -5, +34, -6, 34, -7, 35, -6, 36, -1, +31, 3, 25, 9, 14, 13, 7, 15, +10, 16, 11, 12, 12, 7, 16, 4, +23, 0, 31, -4, 36, -3, 38, -1, +32, 2, 28, 4, 28, 10, 21, 13, +15, 12, 13, 9, 14, 5, 15, 2, +16, 1, 23, 1, 25, -1, 28, -2, +34, -1, 35, 4, 36, 8, 34, 10, +25, 9, 20, 9, 19, 6, 21, 1, +20, -3, 19, -6, 22, -2, 21, 2, +27, 8, 28, 12, 21, 12, 26, 7, +33, 2, 35, 0, 29, -3, 28, -6, +30, -7, 29, -5, 28, 1, 27, 10, +24, 14, 22, 14, 17, 12, 15, 12, +19, 6, 24, -3, 25, -9, 25, -11, +33, -9, 41, -4, 40, 3, 38, 7, +31, 13, 31, 12, 30, 10, 20, 7, +10, 3, 10, -3, 14, -6, 15, -5, +21, -3, 33, 1, 37, 6, 39, 12, +40, 15, 39, 15, 37, 10, 25, 2, +17, -5, 13, -10, 17, -16, 21, -16, +20, -9, 25, 1, 30, 11, 35, 18, +40, 21, 40, 17, 37, 12, 31, 6, +28, 0, 21, -6, 12, -11, 15, -12, +17, -9, 18, -1, 24, 5, 30, 8, +35, 11, 35, 13, 33, 13, 31, 10, +28, 3, 28, -1, 22, -2, 21, -1, +27, -1, 28, -2, 27, 2, 29, 3, +31, 1, 30, -3, 31, -6, 33, -7, +26, -3, 20, 0, 24, 2, 29, 2, +34, 5, 33, 12, 31, 16, 31, 15, +32, 9, 30, 1, 26, -8, 28, -12, +27, -13, 19, -12, 18, -11, 25, -7, +28, 0, 29, 8, 34, 12, 41, 14, +42, 16, 36, 15, 31, 11, 29, 4, +26, -2, 19, -9, 13, -13, 18, -12, +22, -8, 24, -7, 28, -3, 37, 5, +42, 12, 37, 17, 33, 17, 29, 15, +28, 7, 23, 4, 19, 0, 22, -4, +21, -4, 20, -4, 26, -6, 38, -9, +42, -5, 38, -4, 36, -1, 34, 4, +28, 6, 29, 3, 32, 3, 28, 8, +22, 12, 24, 11, 28, 7, 29, 0, +30, -9, 32, -11, 32, -11, 33, -11, +31, -11, 30, -3, 30, 5, 29, 12, +27, 18, 26, 19, 28, 15, 28, 8, +26, 2, 32, -9, 38, -19, 39, -23, +37, -20, 33, -16, 32, -6, 31, 3, +28, 8, 24, 13, 25, 16, 30, 15, +30, 10, 32, 5, 35, -3, 35, -9, +36, -16, 39, -16, 38, -13, 29, -7, +23, -3, 23, 2, 22, 9, 24, 12, +24, 8, 27, 2, 36, 3, 39, 3, +36, 0, 37, -3, 40, -1, 32, 1, +22, 4, 21, 2, 24, -4, 20, -7, +19, -6, 24, -5, 31, -8, 37, -5, +41, 0, 41, 8, 37, 14, 34, 17, +32, 11, 30, 4, 25, -3, 21, -10, +23, -14, 25, -14, 27, -11, 28, -8, +32, 0, 39, 6, 39, 9, 37, 10, +36, 10, 32, 6, 26, -1, 24, -6, +28, -8, 27, -6, 24, -1, 24, 1, +31, -1, 39, -3, 43, 0, 37, 4, +33, -2, 33, -5, 33, -4, 30, -4, +26, -4, 25, -2, 28, 2, 30, 3, +31, 5, 33, 3, 38, 1, 38, -1, +35, -3, 35, -6, 34, -2, 27, 2, +20, 0, 20, -3, 26, -2, 33, 0, +35, 1, 32, 3, 35, 1, 41, 0, +41, 0, 34, 1, 30, -3, 29, -7, +27, -4, 21, 1, 20, 3, 25, 3, +30, 5, 36, 0, 42, -3, 49, -2, +46, 0, 34, -6, 27, -8, 30, -9, +26, -5, 14, 5, 12, 7, 22, 7, +29, 7, 32, 11, 40, 7, 48, 0, +45, -5, 37, -7, 34, -10, 33, -9, +27, -8, 16, -7, 17, -3, 27, 1, +29, 6, 27, 7, 35, 9, 43, 3, +45, -4, 45, -4, 43, -1, 36, -6, +27, -12, 25, -11, 26, -9, 23, -6, +22, -3, 27, -1, 34, 0, 40, 6, +44, 7, 44, 5, 42, 2, 33, 2, +26, -3, 25, -6, 22, -4, 13, -5, +16, -7, 29, -5, 38, 2, 38, 2, +42, 3, 49, 2, 46, 1, 37, -2, +29, -1, 25, -4, 25, -11, 22, -9, +20, -6, 29, -4, 39, -3, 38, -1, +36, 0, 43, 2, 49, 2, 40, 0, +27, -1, 26, 3, 26, 7, 16, 3, +9, -2, 22, -7, 39, -10, 41, -13, +38, -9, 47, -6, 57, -1, 46, 2, +31, 7, 31, 8, 27, 10, 14, 6, +8, -7, 21, -13, 31, -10, 30, -7, +32, -9, 45, -2, 53, 7, 45, 10, +36, 11, 35, 7, 32, 1, 23, -2, +15, -4, 20, -11, 26, -16, 30, -14, +39, -6, 47, -5, 48, -2, 47, 1, +46, 1, 43, -1, 36, 0, 28, 0, +23, -2, 21, -2, 23, -1, 26, -1, +30, 1, 35, 1, 38, -8, 44, -10, +45, -5, 41, -1, 34, -4, 28, -3, +28, 1, 27, 3, 26, 6, 28, 4, +29, 1, 33, 0, 37, 1, 40, -3, +42, -8, 40, -8, 33, -7, 29, -9, +32, -9, 33, -6, 27, -8, 27, -5, +38, 0, 46, 6, 40, 9, 34, 14, +37, 9, 36, 1, 27, -2, 21, -5, +25, -13, 26, -19, 20, -13, 23, -6, +40, -2, 50, 1, 45, 2, 44, 2, +50, 9, 46, 8, 32, -3, 24, -7, +21, -4, 16, -2, 14, -3, 19, -2, +29, -2, 35, -4, 41, -7, 51, -8, +58, -11, 56, -9, 46, -7, 35, -5, +28, -1, 25, 6, 21, 7, 13, 4, +11, 4, 22, 2, 39, -5, 49, -15, +51, -13, 51, -10, 51, -5, 44, -2, +33, -2, 27, -1, 20, 3, 12, 6, +13, 1, 26, -1, 37, -1, 40, 0, +42, -2, 48, -1, 55, -5, 51, -10, +39, -10, 31, -11, 27, -11, 25, -8, +24, -3, 25, -2, 26, 4, 31, 9, +41, 6, 49, -6, 51, -8, 49, -7, +44, -10, 39, -10, 37, -8, 34, -8, +28, -5, 25, 2, 26, 1, 31, -4, +34, -6, 41, -6, 46, -10, 44, -6, +42, -1, 45, -3, 46, -3, 35, 4, +23, 8, 24, 2, 30, -4, 33, -14, +35, -17, 44, -12, 48, -4, 41, -3, +36, 0, 39, 8, 35, 10, 22, 3, +21, -2, 30, -3, 32, -5, 29, -3, +37, -6, 49, -7, 52, -4, 45, 0, +44, -2, 43, -4, 29, 0, 18, -3, +22, -9, 28, -5, 23, 5, 21, 3, +39, -3, 55, -5, 55, -4, 52, -6, +53, -5, 48, -7, 34, -10, 23, -1, +19, 7, 15, 3, 15, -3, 20, 1, +32, -1, 46, -5, 51, -8, 51, -8, +53, -8, 54, -2, 43, 6, 28, 5, +22, 3, 19, 2, 18, -3, 21, -11, +30, -7, 38, -6, 41, -11, 45, -8, +55, 0, 58, 0, 48, -2, 37, -3, +35, -6, 33, -7, 23, -7, 23, -9, +34, -14, 39, -7, 36, 2, 40, 4, +55, 0, 53, -2, 37, -6, 36, -11, +45, -14, 42, -15, 25, -15, 25, -9, +41, -3, 41, 1, 33, 6, 42, 5, +55, -1, 48, -8, 35, -5, 38, -3, +41, -7, 29, -10, 19, -8, 23, -2, +34, 0, 35, 0, 32, -6, 41, -7, +55, -3, 56, -2, 50, -7, 47, -3, +44, 5, 31, 3, 19, -1, 19, -2, +23, -7, 27, -13, 29, -11, 39, -11, +53, -8, 61, -1, 54, 5, 45, 3, +42, 7, 36, 10, 25, -1, 19, -9, +24, -10, 26, -6, 30, -7, 40, -8, +53, -8, 55, -6, 52, -2, 50, -2, +46, -9, 38, -10, 30, -3, 27, -1, +26, -1, 25, 3, 32, 5, 44, 1, +48, -2, 44, -5, 47, -11, 52, -13, +46, -12, 35, -12, 32, -7, 34, 4, +27, 7, 22, 4, 30, 5, 38, 8, +36, -3, 38, -10, 49, -11, 55, -6, +43, -1, 32, -1, 40, -4, 46, -9, +36, -4, 28, -2, 33, -10, 39, -13, +36, -8, 38, -6, 46, -3, 47, 4, +40, 5, 37, 1, 41, -3, 44, -6, +37, -8, 29, -9, 29, -10, 42, -12, +47, -10, 41, 4, 38, 6, 43, -3, +47, -3, 37, 2, 29, 0, 30, -5, +28, -5, 25, -6, 26, -2, 38, 3, +47, 2, 42, -4, 41, -2, 53, -3, +58, -9, 46, -12, 34, -8, 32, -5, +29, -4, 22, 0, 21, 0, 28, -3, +36, -6, 41, -6, 50, -10, 60, -6, +60, -1, 54, -4, 44, -4, 37, 3, +33, 5, 24, -4, 13, -7, 13, -10, +27, -10, 43, -9, 46, -4, 48, -4, +57, 0, 63, 5, 54, 4, 40, -3, +36, -7, 32, -8, 21, -15, 18, -13, +31, -3, 35, 4, 31, 2, 37, 3, +53, 1, 60, -3, 52, -8, 46, -15, +43, -17, 40, -11, 33, -1, 29, 0, +29, 2, 27, 8, 28, 10, 36, 0, +46, -9, 47, -15, 46, -17, 49, -12, +45, -5, 38, -2, 37, -1, 38, 7, +33, 5, 27, 1, 33, 0, 38, -2, +36, -10, 36, -12, 43, -7, 49, -3, +46, -4, 41, -7, 43, -7, 41, -5, +35, -1, 31, -6, 36, -11, 42, -6, +41, 3, 40, 2, 44, -1, 47, 0, +42, 0, 33, -4, 29, -9, 34, -13, +38, -17, 35, -10, 35, -3, 45, 2, +47, 7, 39, 10, 41, 3, 49, -6, +45, -7, 31, -8, 27, -11, 34, -10, +32, -1, 22, 5, 25, 7, 43, 1, +52, -6, 46, -9, 47, -6, 55, -9, +48, -15, 31, -7, 29, 6, 32, 9, +23, 7, 16, 8, 27, 0, 45, -8, +49, -13, 45, -14, 52, -18, 59, -14, +50, -8, 41, -6, 40, 1, 34, 8, +22, 6, 19, -2, 29, 0, 35, 1, +33, -5, 38, -10, 51, -9, 55, -6, +47, 0, 41, 1, 38, -6, 36, -7, +31, -1, 28, 0, 33, -8, 36, -4, +32, 4, 33, 4, 40, 0, 44, 0, +38, -4, 33, -8, 41, -8, 45, -7, +38, -3, 32, 3, 32, 8, 35, 3, +32, 2, 33, 2, 39, -6, 43, -17, +39, -16, 37, -9, 45, -4, 47, 0, +36, -1, 33, -1, 42, 2, 44, 0, +38, -11, 36, -14, 41, -8, 41, -4, +38, -6, 43, -4, 49, -3, 47, -7, +39, -8, 38, -6, 39, -6, 33, -11, +30, -10, 36, -9, 43, -3, 43, 8, +41, 12, 44, 4, 44, -1, 37, 0, +34, -4, 34, -13, 30, -17, 26, -13, +29, -6, 40, 1, 45, 1, 46, 2, +45, 8, 45, 9, 43, -1, 39, -10, +39, -11, 36, -11, 29, -10, 26, -6, +32, -1, 39, -3, 42, -2, 42, -3, +44, -5, 48, -2, 46, 2, 40, -1, +33, -3, 34, 5, 35, 5, 32, -5, +31, -13, 40, -13, 45, -15, 41, -16, +41, -11, 46, -4, 46, 3, 37, 10, +33, 9, 42, 3, 43, 3, 32, 2, +28, -9, 38, -20, 47, -17, 41, -14, +37, -9, 42, -4, 43, 1, 39, 0, +38, -2, 44, -3, 44, -6, 35, 0, +33, 2, 37, -4, 41, -6, 41, 2, +38, 1, 39, -6, 39, -10, 41, -11, +40, -12, 35, -10, 36, -7, 42, -10, +42, -3, 37, 7, 38, 8, 44, 1, +41, -1, 39, -5, 45, -12, 50, -13, +42, -8, 29, -3, 30, -3, 35, -2, +31, -1, 27, 0, 33, -3, 43, -6, +44, -10, 44, -4, 50, 4, 51, 0, +46, -5, 39, -1, 35, 2, 32, -4, +27, -9, 22, -13, 29, -15, 39, -12, +47, -4, 49, -2, 48, 3, 51, 7, +52, 2, 47, -4, 37, -7, 33, -9, +30, -15, 27, -15, 28, -8, 34, 0, +42, 1, 43, 2, 43, -1, 51, -4, +54, -3, 47, -8, 38, -15, 35, -10, +34, 0, 31, 2, 30, 1, 31, 2, +33, 3, 37, -2, 41, -6, 46, -12, +45, -13, 44, -9, 45, -7, 44, -5, +41, 0, 39, 5, 40, 1, 34, -7, +31, -8, 41, -6, 44, -10, 34, -12, +34, -7, 44, -1, 48, 2, 41, 2, +36, -3, 42, -7, 45, -4, 37, -6, +33, -11, 41, -12, 47, -5, 38, -1, +33, 1, 42, 4, 44, 2, 33, -3, +31, -8, 42, -10, 44, -13, 39, -8, +38, -5, 42, -4, 45, -2, 43, 5, +38, 2, 40, -5, 43, -6, 37, -4, +31, -2, 32, -3, 35, -1, 33, 0, +29, 5, 34, 2, 46, -9, 51, -16, +46, -8, 44, -4, 45, -7, 41, -4, +36, 2, 34, 4, 34, 5, 29, 3, +30, -8, 42, -14, 50, -14, 46, -13, +45, -12, 48, -5, 48, -1, 42, -3, +38, -2, 36, 3, 31, 2, 27, -5, +31, -7, 40, -7, 44, -6, 45, -6, +49, -3, 49, -2, 43, 1, 35, 1, +34, -7, 34, -14, 30, -11, 30, -3, +35, 0, 36, 7, 35, 8, 40, 7, +51, 3, 48, -1, 39, -9, 38, -13, +37, -13, 34, -14, 29, -8, 27, 5, +33, 10, 36, 3, 39, 3, 43, 5, +47, 5, 41, -3, 34, -9, 37, -11, +39, -7, 37, 1, 30, 2, 28, 1, +32, 1, 36, 4, 37, -4, 38, -9, +41, -7, 42, 0, 36, 1, 36, 4, +40, 8, 39, 5, 35, 2, 32, -3, +35, -10, 41, -15, 39, -13, 38, -16, +42, -13, 46, -1, 43, 9, 40, 6, +42, 2, 41, 2, 37, -2, 38, -7, +40, -10, 39, -13, 36, -13, 41, -2, +44, 2, 39, -3, 40, -6, 48, -7, +49, -10, 39, -9, 33, 0, 34, 3, +30, 3, 28, 5, 33, 8, 38, 6, +44, 2, 43, -6, 43, -11, 45, -11, +44, -6, 38, -9, 34, -11, 35, -1, +31, 6, 28, 5, 35, 2, 38, 2, +37, 0, 41, 0, 45, -2, 46, -4, +45, -5, 43, 0, 39, -1, 34, -6, +34, -5, 34, -5, 33, -10, 36, -12, +39, -5, 43, -1, 45, 0, 44, 2, +42, 4, 42, 4, 40, 2, 38, -4, +40, -11, 39, -9, 35, -4, 38, -4, +39, -6, 39, -3, 41, -1, 40, -4, +37, -7, 38, -7, 43, -10, 44, -8, +43, -3, 44, -2, 45, 4, 43, 7, +39, 3, 40, -6, 40, -7, 35, -9, +34, -16, 38, -19, 43, -13, 43, -4, +36, 4, 38, 9, 44, 5, 43, 3, +39, 2, 39, -3, 46, -14, 45, -15, +38, -7, 41, -6, 42, -6, 35, -2, +34, -2, 39, -4, 39, -2, 34, -5, +35, -7, 41, -6, 48, -3, 51, -3, +47, 0, 45, 5, 44, 3, 39, -4, +32, -5, 28, -6, 28, -12, 28, -11, +31, -6, 34, 2, 35, 8, 44, 10, +50, 2, 50, -3, 54, -2, 50, -2, +40, -6, 29, -8, 24, -2, 25, -2, +28, 0, 27, 3, 27, 2, 38, -3, +50, -2, 50, -4, 50, -9, 55, -7, +51, -1, 41, -1, 35, -2, 35, 0, +36, -4, 34, -7, 29, -6, 29, -2, +38, -3, 41, -1, 39, 0, 43, -3, +51, -2, 55, 0, 46, -4, 39, -8, +40, -4, 39, -4, 33, -6, 32, -6, +39, 1, 39, 2, 33, 2, 37, 2, +45, -3, 46, -8, 45, -9, 41, -8, +43, -9, 46, -3, 40, 0, 36, -1, +43, -4, 43, 2, 36, 3, 35, -1, +38, -1, 34, -2, 35, -1, 37, 0, +38, 0, 42, -5, 43, -4, 43, -4, +45, -7, 46, -9, 41, -3, 38, 0, +40, -3, 39, -1, 38, 6, 37, 7, +31, 1, 34, -2, 42, -9, 44, -15, +44, -15, 49, -11, 50, -9, 45, 1, +42, 7, 43, 5, 39, 3, 34, 5, +29, 5, 23, -3, 29, -7, 40, -13, +41, -10, 43, -4, 52, -1, 54, -3, +49, -1, 47, 0, 45, -5, 41, -9, +34, -9, 31, -8, 37, -9, 39, 0, +35, 6, 34, 7, 42, 2, 51, -4, +50, -12, 45, -16, 48, -15, 48, -13, +39, -7, 31, 4, 31, 13, 36, 13, +34, 10, 35, 2, 45, -4, 47, -8, +40, -10, 37, -18, 44, -20, 47, -10, +41, -4, 38, -1, 41, 4, 42, 10, +41, 5, 45, -1, 46, -1, 40, -3, +41, -7, 42, -5, 36, -4, 33, -5, +35, -2, 35, -2, 34, -6, 40, -7, +44, 1, 41, 1, 44, 0, 45, 5, +41, 10, 44, 6, 44, 2, 33, 1, +31, -4, 34, -4, 29, -5, 28, -10, +37, -12, 41, -3, 42, 0, 47, 1, +51, 3, 52, 6, 49, 3, 47, -3, +46, -5, 45, -8, 38, -11, 31, -14, +35, -14, 39, -14, 40, -10, 46, -7, +48, -6, 51, -2, 57, 6, 53, 6, +49, 0, 51, -2, 46, -5, 36, -10, +34, -16, 42, -18, 39, -18, 33, -10, +37, -1, 43, 4, 44, 7, 45, 11, +46, 10, 47, 3, 49, -3, 46, -7, +45, -11, 44, -15, 38, -10, 34, -5, +34, -1, 33, 0, 36, -1, 37, 0, +37, 2, 45, -1, 52, -8, 51, -4, +49, 5, 48, 6, 44, -1, 42, -3, +47, -8, 42, -12, 30, -14, 32, -13, +37, -11, 33, -8, 39, 0, 47, 7, +45, 11, 49, 13, 54, 10, 50, -1, +48, -7, 44, -10, 36, -15, 33, -17, +33, -11, 30, -3, 28, 5, 32, 12, +39, 11, 41, 10, 44, 5, 49, 1, +50, -10, 56, -15, 53, -14, 45, -10, +46, -7, 40, -4, 31, 1, 32, 0, +33, 1, 30, -2, 35, -1, 37, 1, +39, 5, 46, 2, 52, 0, 53, 1, +53, 0, 53, -6, 47, -11, 38, -11, +37, -13, 32, -10, 25, -8, 32, -3, +37, 7, 32, 17, 38, 15, 49, 8, +53, 5, 51, -1, 51, -10, 54, -18, +45, -18, 37, -18, 41, -14, 37, -8, +33, -1, 38, 3, 41, 8, 43, 8, +47, 6, 47, 3, 49, -4, 51, -10, +49, -14, 43, -10, 41, -10, 42, -11, +41, -10, 39, -2, 41, 5, 40, 8, +40, 4, 44, 3, 42, 0, 43, -4, +51, -10, 47, -15, 46, -11, 50, -7, +42, -4, 41, -3, 47, 0, 43, 1, +39, 0, 43, -3, 46, -6, 41, -6, +44, -1, 43, 3, 31, 2, 39, 3, +50, 2, 39, 1, 36, -8, 49, -12, +49, -16, 46, -16, 52, -11, 47, -5, +43, 4, 46, 12, 41, 15, 39, 6, +44, 0, 43, -6, 38, -14, 38, -23, +44, -20, 42, -13, 42, -6, 44, 3, +43, 16, 47, 24, 46, 19, 38, 11, +43, -1, 44, -8, 33, -14, 34, -17, +36, -21, 36, -14, 41, -2, 43, 5, +43, 7, 52, 6, 55, 6, 47, 2, +46, -4, 53, -12, 50, -11, 40, -11, +42, -8, 45, -6, 38, -3, 36, -1, +40, -3, 40, -8, 42, -10, 43, -4, +43, 0, 45, 5, 42, 8, 46, 12, +50, 11, 44, 8, 45, -2, 45, -11, +36, -15, 34, -19, 38, -21, 35, -16, +33, -5, 41, 3, 49, 10, 49, 13, +54, 17, 59, 12, 51, 4, 48, -6, +48, -14, 37, -18, 31, -18, 33, -14, +25, -7, 26, 2, 36, 7, 42, 10, +49, 10, 53, 10, 55, 4, 59, -2, +53, -7, 48, -11, 44, -11, 37, -10, +36, -11, 37, -11, 35, -1, 36, 2, +37, 2, 41, 2, 42, 2, 46, 0, +56, -1, 50, 2, 41, 4, 49, 4, +50, 1, 40, -2, 38, -6, 39, -7, +37, -11, 35, -14, 34, -15, 44, -8, +48, -2, 44, 5, 50, 12, 52, 15, +51, 14, 50, 5, 46, -6, 45, -18, +44, -20, 40, -20, 31, -15, 29, -11, +46, -4, 50, 7, 41, 13, 52, 15, +55, 11, 43, 5, 48, -10, 53, -19, +43, -22, 43, -17, 42, -9, 32, 1, +34, 10, 40, 17, 36, 18, 36, 10, +42, 3, 44, -4, 40, -9, 46, -14, +47, -12, 40, -4, 44, 6, 41, 10, +36, 9, 45, 5, 40, 2, 33, -1, +43, -8, 39, -13, 36, -10, 48, -3, +48, 0, 41, 6, 49, 9, 53, 8, +40, 3, 38, -5, 48, -13, 39, -15, +31, -11, 42, -8, 40, 1, 33, 9, +46, 17, 47, 17, 37, 15, 44, 7, +43, -4, 38, -17, 48, -26, 49, -25, +41, -17, 41, -6, 46, 2, 49, 9, +46, 12, 48, 15, 48, 10, 42, 1, +41, -8, 39, -12, 37, -16, 41, -19, +40, -13, 42, -2, 45, 8, 43, 8, +47, 9, 50, 8, 44, 3, 48, -5, +51, -11, 41, -13, 40, -9, 42, -7, +40, -6, 40, -1, 39, 3, 44, 7, +42, 2, 40, -4, 51, -9, 54, -8, +48, -10, 52, -8, 52, 0, 44, 8, +38, 12, 37, 9, 36, 5, 29, 0, +33, -8, 41, -18, 37, -17, 40, -10, +48, -1, 45, 3, 52, 10, 60, 19, +48, 22, 40, 18, 42, 5, 36, -8, +31, -20, 32, -22, 31, -22, 29, -14, +33, -2, 46, 10, 51, 16, 51, 20, +58, 19, 56, 9, 54, -3, 52, -13, +40, -17, 37, -20, 33, -15, 27, -8, +34, 2, 34, 8, 35, 11, 48, 9, +49, 4, 48, -4, 60, -12, 62, -13, +52, -11, 46, -5, 47, 2, 40, 9, +30, 11, 30, 9, 29, 3, 26, -1, +35, -9, 40, -16, 41, -15, 55, -11, +58, -1, 54, 8, 55, 15, 55, 16, +}; \ No newline at end of file diff --git a/project/realtek_ameba1_va0_example/example_sources/i2s/src/birds_8000_2ch_16b.c b/project/realtek_ameba1_va0_example/example_sources/i2s/src/birds_8000_2ch_16b.c new file mode 100644 index 0000000..111f294 --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/i2s/src/birds_8000_2ch_16b.c @@ -0,0 +1,5836 @@ +#include +int sample_size=23320; + +SECTION(".sdram.data") +short sample[]={ +0, 0, -1, 1, -1, 1, 0, 0, +1, 0, -1, 1, 0, 0, 2, -3, +2, -2, 0, 0, -1, 0, 0, 0, +-1, 1, 1, -1, 1, -1, 0, 0, +2, -2, 1, 0, 0, 0, 1, -2, +1, -1, -1, 1, -1, 1, 0, 0, +0, 0, 3, -3, 0, 1, -1, 1, +0, 1, 1, -1, 1, -1, -2, 1, +2, -2, 0, 1, -1, 0, 0, 0, +-2, 2, 0, 0, -1, 2, -1, 1, +0, 1, 1, -1, 1, -1, 1, -1, +0, 0, -1, 0, -1, 1, -3, 3, +0, 0, -3, 3, -1, 0, 1, 0, +0, 0, 0, 0, -1, 1, 1, -1, +1, 0, -1, 1, -2, 2, -3, 2, +1, -2, -1, 1, -2, 2, 0, 0, +0, 1, 1, -1, 2, -2, 1, 0, +-1, 1, 0, 0, 1, 0, -2, 2, +-2, 2, -4, 4, -3, 2, -4, 3, +1, -2, 3, -3, 0, 0, 0, 1, +-3, 3, 1, -1, 1, 0, 1, 0, +0, 0, 1, 0, 0, 0, -1, 1, +0, 0, 2, -2, 1, -1, 2, -3, +2, -2, -3, 3, 0, 0, 2, -1, +0, 1, -1, 2, 0, 0, -1, 1, +0, 0, 0, 0, 0, -1, -3, 2, +-1, 0, -1, 1, -1, 0, 4, -4, +-2, 2, 1, -1, 2, -1, 1, 0, +1, 0, 0, 1, 0, -1, 1, -1, +-2, 1, 2, -2, -1, 0, -1, 0, +1, -1, -1, 1, 1, -1, 1, -1, +2, -1, 2, -1, 4, -3, 1, 0, +0, 0, 2, -2, -1, 1, -1, 1, +-1, 1, -2, 2, 0, -1, 3, -3, +-1, 1, 0, 0, -1, 2, 2, -1, +3, -2, 2, -1, 0, 1, -2, 2, +0, 0, -1, 0, 0, -1, 1, -1, +-2, 1, -1, 0, 0, 0, 0, 0, +-1, 2, 0, 1, 1, 0, 1, -1, +1, 0, -1, 1, -1, 1, 0, 0, +1, -1, -1, 1, -2, 2, -2, 1, +1, -2, 2, -1, -1, 1, -1, 1, +1, 0, -2, 2, -2, 2, 1, -1, +0, 0, -2, 2, -3, 2, 0, -1, +3, -4, 0, 0, 0, 0, 0, 0, +1, -1, 2, -1, -1, 2, 1, -1, +1, -1, 1, -1, -1, 1, 2, -2, +0, 1, -5, 4, 1, -1, 0, 0, +0, 0, -1, 0, 1, -1, 0, 0, +1, -1, 2, -2, 0, 0, -1, 1, +0, 0, 0, 1, -4, 3, 3, -4, +0, 1, -2, 1, 0, 0, -3, 2, +3, -4, 2, -1, -2, 2, -1, 1, +1, -1, 2, -2, -2, 2, -1, 0, +0, 0, -3, 2, -1, 0, 0, 0, +0, -1, -1, 1, -3, 3, 1, -2, +2, -2, 0, 0, 1, -1, 1, 0, +-1, 1, 2, -2, 0, 1, 0, 0, +0, 0, -1, 1, 0, -1, 1, -1, +0, 0, 0, 0, 0, 0, -1, 1, +-1, 1, 1, -1, 0, 0, -1, 1, +0, 0, -1, 0, -1, 1, 1, -1, +2, -2, 1, -1, 0, -1, 2, -2, +1, -1, -1, 2, -1, 1, 2, -2, +0, 0, 0, 0, -2, 2, 2, -2, +2, -1, -4, 3, -1, 0, 1, -1, +0, 0, 0, 0, 0, -1, 0, 1, +-1, 1, 1, -1, 2, -2, -1, 1, +-1, 0, 0, 0, -3, 2, 1, -1, +1, -1, 1, -1, -1, 1, -1, 1, +0, 0, 1, -1, 1, -1, 0, 0, +-2, 2, 0, 0, 0, 0, -1, 0, +1, -1, 0, 0, -3, 3, -3, 2, +0, 0, -1, 1, 3, -3, 3, -2, +1, 0, -3, 4, -1, 1, 0, 1, +-3, 3, -1, 0, -2, 2, -1, 0, +2, -2, 0, 0, 0, 0, -1, 1, +-1, 2, -2, 2, 1, -1, 1, -1, +1, -1, 2, -2, 1, -1, 0, 0, +1, -1, -1, 1, -2, 1, 0, 0, +-2, 2, 1, -1, 2, -1, 0, 0, +0, 0, 1, -1, 2, -1, 1, -1, +1, 0, 0, 0, 0, 0, -1, 1, +-1, 1, 1, -1, -1, 1, -1, 1, +0, -1, 2, -2, -1, 1, 0, 0, +1, -1, -1, 1, -3, 3, 0, 0, +1, -1, -1, 1, -1, 1, -1, 1, +2, -3, 3, -3, 1, 0, -1, 1, +0, 0, -2, 2, 0, 0, 1, -1, +2, -2, 1, -1, -3, 3, 1, -1, +0, 0, 1, -1, 0, 0, -2, 1, +0, 0, -1, 1, 1, -1, 0, 1, +-1, 1, 0, 0, 0, 0, 0, 0, +-2, 1, 2, -2, 0, 0, 1, -1, +1, -1, -1, 1, 1, -1, 0, 0, +0, 1, -2, 2, 0, 0, 0, 0, +1, -2, 2, -1, 1, -1, 1, -1, +-1, 1, 0, 0, -3, 3, -1, 1, +-1, 1, 0, 0, 1, 0, 0, -1, +2, -2, 0, 0, 1, -1, 0, 0, +2, -2, 0, 0, 1, -1, 2, -3, +3, -3, 0, 1, 2, -2, 1, 0, +-1, 1, 0, 0, 1, -2, 1, -1, +-2, 2, 0, 0, -1, 1, 1, -1, +-1, 1, 0, 0, 0, 0, -1, 1, +0, 0, 0, 0, 2, -2, 0, 0, +-1, 1, -2, 2, -1, 1, 0, 0, +-1, 1, 2, -2, -1, 1, -1, 1, +0, 0, -1, 1, -2, 1, 1, -2, +1, -1, 1, -1, -1, 1, 1, -1, +1, -1, 1, -1, 0, 0, 0, 0, +1, -1, 0, 0, -2, 2, 1, -1, +-1, 1, 0, 0, 0, 0, 0, -1, +0, 1, -1, 0, 1, -1, 1, -1, +0, 0, 0, 0, 0, 0, 1, 0, +-1, 1, 1, -1, 0, 1, -1, 0, +1, -1, 0, 0, 0, 0, -2, 2, +0, 0, -1, 1, 0, 0, -2, 2, +-1, 0, -1, 1, 0, 0, 2, -2, +0, 0, 1, 0, -3, 3, 0, -1, +0, 0, -2, 2, 0, 0, -1, 1, +-1, 1, 0, 0, 1, -1, -2, 2, +1, -1, -2, 2, 0, 0, 1, -1, +1, -1, 2, -2, -1, 1, 1, -1, +0, 0, -1, 2, -2, 2, 1, -1, +-1, 1, -2, 1, 0, 0, -1, 1, +2, -2, 2, -2, 0, 0, 0, 0, +0, 0, -3, 2, 0, 0, 1, -1, +0, 0, -3, 3, 1, -1, -1, 2, +-2, 2, 1, -1, 1, 0, -1, 0, +0, 0, -1, 1, 0, 0, -1, 1, +2, -3, 1, -1, 1, -1, 2, -2, +1, -1, 0, 0, 0, 0, 2, -2, +1, -1, 0, 0, 1, -1, -1, 1, +-1, 1, -2, 2, 0, -1, 1, -1, +-1, 1, -2, 2, -2, 1, 0, 0, +-2, 2, 0, 0, 1, 0, -1, 1, +-1, 1, 0, 0, 0, 0, 0, 0, +0, 0, 2, -1, -2, 2, 2, -2, +0, 1, -1, 0, 2, -2, 0, 0, +1, -1, -1, 1, -1, 1, 1, -1, +1, -1, 2, -3, 2, -1, 0, 0, +3, -2, 0, 1, 0, 0, -1, 1, +1, -1, 2, -2, 1, -1, -1, 1, +1, -1, 0, 0, -1, 1, 0, 0, +0, -1, 0, 0, -2, 2, 1, -1, +-1, 1, 0, -1, -1, 1, -3, 3, +2, -2, 2, -2, 0, 0, 2, -2, +-1, 1, -1, 1, 2, -2, 0, 1, +0, 0, 0, 0, 0, 0, 1, -1, +0, 0, 0, 0, -1, 1, 0, 1, +-1, 1, 0, 0, 2, -2, 2, -2, +2, -2, 0, 0, 0, -1, 1, -1, +-1, 1, 1, -1, 0, 1, 1, -1, +-1, 1, 0, 0, 2, -2, 2, -2, +-1, 1, -1, 1, 0, 0, 1, -1, +-1, 1, 0, 0, 0, 0, 1, -1, +3, -3, 0, 1, 1, -1, -1, 1, +-1, 1, -1, 1, 0, 0, 2, -2, +-2, 2, 0, 0, 2, -2, 0, 0, +2, -2, 1, 0, -1, 1, 2, -2, +-2, 2, -2, 2, 0, 0, 0, 0, +0, 1, -1, 1, 1, -1, -2, 2, +0, 0, 0, 0, 2, -2, 1, -1, +1, -1, -2, 2, 0, 0, 1, -1, +-1, 1, -2, 2, -4, 3, 0, 0, +3, -3, 1, -1, 1, -1, -1, 1, +-3, 3, -1, 1, 2, -2, 1, 0, +-1, 1, 0, 0, 1, -1, 0, 1, +-1, 0, -1, 1, 0, -1, 2, -2, +-1, 1, -2, 2, -2, 1, 0, 0, +-3, 3, -2, 1, 0, 0, 0, 0, +1, -1, 0, 0, 1, -1, 2, -2, +3, -3, -1, 1, 1, -1, 3, -2, +2, -2, 1, -1, -1, 1, 0, 0, +-2, 2, 0, 0, 1, -1, -1, 0, +1, -1, -1, 1, -2, 2, -1, 2, +-3, 2, 0, 0, 0, 0, -1, 1, +2, -2, 1, -1, 0, 0, 0, -1, +0, 0, -3, 3, -1, 0, 2, -1, +-2, 1, -2, 2, -1, 1, 1, -1, +0, 0, 0, -1, 0, 0, 3, -3, +-2, 3, 0, 0, -2, 1, 0, 1, +-1, 0, -2, 2, 0, 0, -1, 0, +0, 1, -1, -1, 4, -3, -2, 2, +0, -1, 2, -1, -3, 2, 1, 1, +-3, 1, 0, 0, 1, 0, -3, 1, +0, 2, -4, 2, 3, -2, -1, 1, +-3, 2, 0, 2, -3, 1, -1, 3, +-4, 2, 1, -1, -2, 3, -1, -2, +3, 0, -4, 2, -2, 2, 0, 0, +-3, 1, 3, -1, -3, 0, 3, -2, +0, 0, -2, 1, 1, 2, -3, 0, +4, -1, -3, 1, -2, 2, 1, 1, +-2, -1, 4, 0, -3, 1, 2, 0, +0, 0, -2, -1, 4, -1, -4, 0, +3, -1, 0, -1, 0, -1, 2, 1, +-5, 1, 4, 0, -2, -1, 0, 0, +4, -2, -2, -1, 5, -1, -2, -1, +1, 1, 0, 0, -2, -1, 4, 1, +-2, -2, 3, 1, -3, 0, -1, 1, +2, 1, -4, -1, 4, 0, -3, -1, +2, -1, 0, 2, -5, 1, 7, -2, +-3, -2, 5, -1, -1, 0, 0, -3, +6, -1, -3, -3, 3, 2, -4, 2, +-2, 1, 3, 0, -6, 1, 5, 0, +-7, 3, 2, -1, 1, 0, -5, 0, +7, -1, -9, 3, 5, -2, 1, -1, +-4, 1, 5, 0, -5, -1, 5, 0, +-3, 0, 0, 0, 3, -1, -4, -1, +6, 0, -5, -1, 3, 0, -1, 1, +-4, 1, 4, 1, -5, -1, 3, 1, +-4, 2, -3, 1, 5, 0, -5, -1, +5, 0, -4, 0, 1, 0, 3, -1, +-3, -2, 6, 1, -6, 0, 1, 2, +0, -1, -1, -1, 4, 2, -5, -1, +5, 0, -4, 2, 1, -2, 6, -2, +-6, 0, 7, -1, -5, 1, 2, -1, +0, 2, -4, 0, 7, -1, -5, -1, +2, 1, -3, 1, 0, -3, 7, -2, +-6, 1, 5, 0, -3, 1, -1, 1, +3, -1, -7, 1, 4, 1, -7, 3, +0, 3, 0, 1, -3, 0, 4, 0, +-5, -1, 5, -2, 1, -2, -2, 2, +7, -2, -4, 0, 3, 1, -2, -1, +1, -1, 2, -1, -4, 1, 4, 1, +1, -4, 4, -1, -2, 1, 1, -4, +3, 0, -3, -1, 2, 2, -2, 1, +2, -1, 3, 0, -4, 0, 2, 1, +-3, -1, 0, 1, 2, -1, -1, -1, +2, 2, -3, 1, 1, 0, 1, -2, +-3, 0, 2, -1, -2, -1, 4, 0, +0, 0, 2, -1, 1, 1, -5, 1, +1, -1, -4, 1, 0, 1, 2, 0, +-2, 3, 4, 0, -2, 0, -2, 1, +-5, 2, -3, 0, 3, -1, 2, -1, +7, -2, 2, -1, 1, -2, -3, 1, +-6, 0, -2, 1, -1, 1, 4, 1, +4, 2, 0, 1, -2, 2, -7, 0, +-3, -3, -3, 2, 0, 2, 8, 0, +6, -1, 1, 1, -4, -1, -9, 1, +-6, 0, -2, 0, 5, 2, 9, -1, +7, -1, -1, 1, -10, 0, -10, 1, +-9, 2, 1, 1, 10, 1, 9, 1, +8, -1, -5, 0, -14, 2, -8, -3, +-4, -1, 8, 1, 10, 1, 13, -1, +1, 1, -9, -2, -11, -2, -13, -1, +4, -2, 10, 0, 16, -1, 13, -2, +-4, -1, -11, 0, -19, 0, -5, -2, +8, -2, 18, -3, 19, 1, 3, 0, +-6, 0, -21, 2, -18, 1, -2, 0, +8, 1, 23, 0, 13, 0, 1, 0, +-13, -1, -23, 0, -10, 0, -2, 1, +21, -2, 21, 0, 9, 1, -3, -1, +-24, 1, -19, 2, -11, 1, 11, 0, +23, 0, 17, -1, 9, -1, -15, -2, +-19, -1, -17, -1, -2, 0, 16, 3, +19, 0, 18, 1, -7, 2, -18, -1, +-21, 0, -15, 0, 9, 2, 18, -1, +24, 0, 8, 1, -12, 0, -19, 0, +-23, -2, -1, 0, 10, 1, 24, -1, +21, -1, -2, 0, -14, 2, -25, -1, +-14, 1, 4, -2, 18, -1, 26, 0, +9, 0, -3, 0, -21, 0, -21, 0, +-9, 2, 8, -3, 26, -1, 16, 0, +7, 0, -11, -1, -22, -1, -14, 0, +-3, -3, 17, 0, 21, -2, 13, 1, +1, 0, -18, -1, -15, -1, -13, -1, +5, 0, 17, 0, 17, -2, 12, -1, +-10, 0, -15, 1, -19, 2, -8, 2, +8, 4, 12, 1, 16, 1, -3, 3, +-8, -2, -13, -2, -13, 0, 4, 0, +10, -2, 19, -1, 8, 0, -2, -1, +-9, -1, -14, -3, -5, 2, -2, 4, +12, 1, 12, 0, 1, 1, -1, -2, +-14, 0, -7, -1, -1, -2, 5, 1, +14, -1, 6, -1, 3, 0, -10, 0, +-6, -4, -5, -1, 0, -1, 11, -1, +6, 0, 9, -3, -1, -2, -8, 1, +-9, 3, -6, 1, 6, -1, 6, -1, +5, 2, 2, 0, -3, -1, -4, 0, +-7, 0, 0, 1, 6, -4, 6, -1, +5, 0, 2, -4, -1, 0, -8, 2, +-4, 2, -1, 1, 3, -1, 4, 1, +2, -1, 1, 1, -7, 3, -1, -3, +-1, 0, 0, -1, 5, -1, 3, -1, +2, 0, 0, -1, -5, 2, -2, 0, +-3, 1, 1, 0, -1, 2, 2, 0, +6, -4, 1, -2, 0, 0, -3, 1, +-2, 1, 1, -1, 1, 0, 2, 0, +2, -2, -1, 2, -2, 0, 0, -1, +-1, 0, 2, -2, -1, 3, 1, 1, +0, 2, -1, 1, -2, 0, -4, 2, +-1, -1, 2, -1, 1, 0, 4, -2, +2, 0, 1, -1, -1, 0, -2, -1, +1, -2, 1, 0, 5, -3, 1, 2, +0, 0, 1, -2, -2, 0, 1, -2, +-1, 0, 2, 0, 2, 0, 2, -1, +1, -1, -3, 1, -2, 0, -1, -1, +0, 0, 3, -1, 3, 0, 1, 0, +-1, 0, -4, 2, -4, 1, -1, 0, +1, 1, 2, 0, 3, 1, -2, 2, +0, -2, -3, 0, -3, 0, 0, 1, +2, 0, 5, -1, 3, -1, 0, 0, +-4, 1, -5, 1, 0, -1, 3, -2, +5, -1, 4, -1, 2, -1, -1, 0, +-4, -1, -2, 0, 0, -1, 2, 1, +4, 0, 2, 0, 0, 1, -5, 1, +-4, 0, -3, 0, 1, 0, 6, -1, +3, 0, 1, 1, -2, 0, -4, 0, +-3, -1, 1, -2, 2, 1, 5, -1, +4, 0, 1, 0, -2, -1, -2, -1, +-3, 0, 0, 0, 3, 0, 6, -1, +2, 1, -2, 0, -2, -1, -4, 0, +-2, 1, -1, 3, 5, -2, 5, 0, +1, -1, -3, 1, -4, -1, -1, -2, +1, 0, 0, 3, 7, -2, 1, 1, +-3, 2, -2, -1, -4, 0, -2, 1, +0, 1, 4, 0, 3, 1, -1, 3, +-3, 1, -4, 1, -5, 2, -2, 1, +3, -1, 3, 1, 1, 2, -1, 1, +-4, 0, -2, -1, -2, 0, 3, -2, +1, 2, 3, -1, 3, -1, -3, 1, +-4, 1, -2, -2, -2, 2, 2, 0, +4, 0, 0, 3, -1, 0, -2, 0, +-4, 0, 0, -1, 2, -1, 1, 1, +2, 1, 0, 0, -1, -1, -2, 0, +-2, -1, 1, 0, 1, -1, 6, -3, +1, 1, 0, 0, 0, -1, -2, 0, +-2, 1, 1, 0, 2, 1, 3, -1, +2, -1, 1, -2, -2, -1, -1, -1, +0, -1, 4, -2, 3, 0, -1, 1, +2, -2, -3, 1, -3, 1, -3, 2, +2, -1, 2, 1, 1, 0, 2, -1, +-2, 0, -1, -1, 0, -2, 0, -1, +2, 0, 1, 0, 1, 0, 0, 0, +-3, 1, -4, 3, -2, 0, 1, 0, +1, 0, 4, -2, 1, 0, 1, -2, +-1, 0, -2, 0, -1, 2, 1, 0, +1, 1, 1, 0, 2, -3, 1, -1, +-3, 1, -2, 1, 0, 1, 2, -1, +5, -2, 0, 0, 1, -2, -3, 2, +-3, 1, 2, -1, -1, 2, 1, 1, +0, 1, -1, 0, 0, -1, -1, -2, +3, -2, 0, 0, 3, -1, 0, 1, +1, -1, 1, -1, -1, -1, 1, -1, +1, -1, 0, 1, 1, 0, 1, 0, +0, 0, -2, 0, 1, -2, -1, 1, +1, -1, 2, 0, 1, -1, 2, -1, +-2, 1, 1, -2, -1, 1, -2, 2, +0, 1, 4, -4, 0, 1, -1, 1, +-1, 0, -1, 0, -1, 1, 2, -1, +1, 0, -1, 2, 0, 0, -2, 1, +1, -2, 0, 0, 0, 0, 0, 1, +0, 1, 2, -2, -3, 2, -2, 0, +-1, 0, 1, -1, 0, 2, 0, 1, +2, 0, -3, 2, 0, -1, 0, -2, +-1, 0, 3, -2, 3, -1, 2, -1, +1, -1, -3, 2, -1, 0, -2, 1, +0, 0, 1, 0, 2, 0, 3, -2, +1, -2, -4, 3, -3, 1, -2, 2, +2, -1, 3, -1, 1, 0, 1, -1, +-2, 1, -2, 0, -2, 1, 0, 0, +1, 0, 0, 1, 2, -1, -1, 1, +-2, 0, -1, -1, -1, 0, 3, -2, +1, 1, 0, 1, -2, 2, -1, 0, +-1, 0, -1, 0, -1, 1, 1, 0, +6, -4, 2, 0, -1, 0, -1, 0, +-1, 0, -3, 2, 0, 1, 2, -1, +1, 1, -1, 1, -2, 1, -4, 2, +0, -2, 3, -3, 3, -2, 3, -1, +1, 0, -1, 1, -2, 0, 0, -1, +1, -1, 2, -2, 3, -1, 0, 2, +-2, 2, 0, -1, -2, 0, -1, 0, +0, -1, 2, -1, 1, 0, 3, -2, +1, 0, -2, 1, -4, 2, -1, -1, +1, 0, 3, -1, 2, 0, 3, -2, +-4, 3, -4, 2, -2, 1, 0, 0, +0, 1, 3, -2, 1, 1, -1, 1, +0, -1, -2, 0, -1, 0, -1, 1, +2, -1, 0, 1, 1, 0, -2, 1, +0, -1, -1, -1, 1, -2, 0, 1, +1, 0, 2, -1, 1, -1, -2, 1, +-1, 0, -1, 0, -1, 1, 0, 1, +3, -2, -1, 1, 0, 0, -2, 1, +-3, 2, 0, 0, -1, 1, 3, -2, +2, -1, 1, 0, 0, -1, -1, 0, +-2, 2, -1, 1, 1, 0, 1, -1, +3, -2, 1, 0, 1, -2, -1, 0, +-2, 2, 0, 0, 2, -2, 1, 0, +1, 0, 0, 0, -2, 1, 2, -2, +0, 0, -1, 1, 2, -1, 2, -2, +1, -1, 0, 0, 1, -1, 2, -3, +2, -1, 1, 0, 0, 0, -2, 2, +-1, 0, -2, 2, -1, 0, 2, -1, +0, 1, 3, -3, 2, -2, 0, 0, +2, -2, 2, -3, 0, 0, -1, 1, +0, 1, 1, -1, -1, 1, -1, 1, +0, -1, -2, 2, 0, 0, -1, 1, +1, -1, 1, -1, 0, 0, 0, 0, +0, 0, -2, 3, 0, -1, 1, 0, +-2, 1, 1, -1, -2, 2, 1, -1, +0, 1, 1, -1, 2, -1, 1, -1, +1, 0, 0, 1, -1, 1, 1, 0, +-1, 2, 0, 2, -1, 2, 2, -2, +3, -2, 1, 0, 2, 0, 1, 0, +2, -1, 1, 1, 1, 0, 3, -1, +0, 2, 0, 2, 3, 0, 4, -1, +4, -1, 3, 0, 3, 1, 2, 1, +3, 0, 5, -1, 4, 0, 7, -3, +7, -3, 7, -2, 5, 0, 5, 0, +4, 1, 4, 1, 5, 1, 6, -1, +5, 1, 5, 1, 7, -1, 4, 2, +9, -3, 9, -1, 7, 0, 7, 0, +5, 2, 8, 0, 7, 1, 10, -3, +10, -1, 9, 1, 10, -1, 8, 1, +8, 1, 10, 0, 10, 0, 9, 1, +11, 1, 11, 1, 9, 1, 14, -4, +11, 2, 10, 2, 14, -2, 11, 1, +12, 2, 12, 1, 14, -2, 13, 0, +14, 1, 14, 1, 15, -1, 13, 2, +13, 3, 16, -1, 13, 1, 15, 1, +17, 1, 14, 2, 16, -1, 20, -2, +16, 3, 17, -2, 19, -3, 17, 3, +15, 5, 18, -1, 21, -3, 20, 1, +19, 0, 21, -4, 20, -1, 20, 3, +20, 1, 21, -3, 21, 0, 21, 2, +19, 2, 19, -1, 21, 2, 24, 1, +25, -3, 21, 0, 23, 1, 23, 2, +25, -5, 26, -4, 23, 4, 27, -1, +25, -3, 24, -1, 25, 3, 24, 2, +23, -2, 25, -1, 26, 4, 26, 1, +28, -5, 27, 0, 28, 3, 24, 1, +27, -4, 27, 3, 28, 3, 28, -2, +27, -3, 30, 2, 26, 5, 31, -7, +28, -2, 27, 5, 31, 0, 28, -3, +28, 0, 30, 4, 30, 0, 27, -3, +29, 0, 33, 3, 29, 1, 31, -6, +29, 4, 27, 7, 29, -1, 28, -2, +31, 3, 29, 6, 31, -4, 34, -6, +31, 5, 31, 3, 31, -5, 31, -2, +32, 5, 32, 1, 34, -8, 32, 0, +33, 5, 33, -1, 31, -5, 31, 2, +31, 7, 33, -3, 35, -7, 30, 6, +32, 5, 32, -4, 32, -4, 33, 4, +34, 2, 34, -6, 33, -3, 32, 7, +31, 3, 32, -6, 33, -2, 32, 7, +30, 3, 32, -6, 35, -2, 32, 7, +31, -2, 31, -5, 31, 3, 33, 5, +31, -2, 35, -8, 31, 6, 30, 5, +32, -6, 29, -1, 32, 5, 31, 4, +31, -5, 29, -1, 33, 4, 31, 1, +29, -6, 31, 0, 30, 6, 31, -1, +30, -5, 29, 2, 31, 5, 28, 0, +29, -7, 31, 4, 29, 5, 32, -7, +31, -5, 29, 3, 28, 4, 28, -4, +25, -1, 30, 6, 29, 1, 27, -7, +31, -1, 26, 6, 27, -1, 29, -6, +25, 0, 28, 7, 28, -2, 25, -6, +28, 4, 25, 5, 24, -3, 29, -5, +23, 3, 27, 3, 26, -2, 21, -5, +27, 5, 24, 2, 22, -5, 27, -3, +22, 6, 21, 0, 29, -4, 17, -3, +23, 9, 17, 3, 20, -4, 23, 0, +23, 7, 17, -4, 24, 4, 16, -3, +23, 5, 24, -5, 19, -4, 24, -2, +20, 7, 16, -10, 25, 3, 14, 1, +17, 1, 22, -1, 16, -3, 16, 4, +21, 2, 10, -5, 24, 1, 12, 5, +13, -5, 19, 4, 11, 2, 13, 1, +22, 1, 5, -2, 18, 6, 12, 5, +9, -9, 22, 2, 11, 4, 12, -6, +18, 3, 11, -5, 12, 4, 17, 4, +0, -11, 23, 6, 4, 8, 13, -10, +15, -1, 8, 7, 7, -4, 21, 7, +-2, -16, 20, 10, 7, 5, 4, -8, +16, -3, 7, 10, 4, -9, 21, 4, +-5, -9, 15, 5, 10, 11, -1, -16, +15, 2, 7, 9, 1, -8, 19, 1, +-2, -3, 9, -3, 14, 16, -7, -19, +15, 3, 5, 10, 1, -10, 15, -3, +0, 5, -2, -8, 20, 19, -12, -20, +18, 0, -1, 15, -2, -7, 8, -4, +8, 7, -8, -12, 20, 20, -11, -17, +9, -2, 6, 16, -6, -10, 9, -3, +4, 9, -7, -12, 15, 16, -5, -8, +1, -12, 10, 22, -10, -10, 7, -2, +6, 8, -12, -10, 14, 13, -3, -3, +-2, -16, 13, 17, -7, -6, 2, -8, +7, 13, -10, -14, 10, 12, 4, 0, +-14, -17, 19, 19, -13, -3, 9, -10, +2, 6, -3, -2, -2, 1, 13, 14, +-19, -32, 21, 28, -12, -9, 6, -5, +5, -1, -4, 5, 0, -4, 8, 15, +-12, -25, 8, 19, 2, 8, -10, -20, +18, 13, -15, -7, 7, 11, 1, -2, +-2, -8, 1, -2, 7, 26, -14, -30, +14, 19, -7, -8, 0, 6, 10, 2, +-9, -14, 5, 9, -1, 14, -2, -15, +2, 1, 4, 12, -13, -7, 12, 18, +-15, -16, 6, 8, 2, 13, -9, -13, +4, 5, -5, 9, -5, 1, 3, 2, +-6, 4, -6, -10, 6, 33, -17, -22, +5, 14, -5, 1, -9, 8, 5, -2, +-11, 7, -4, -4, -4, 22, -3, -7, +-13, -2, 11, 19, -29, -4, 14, 16, +-23, -7, 4, 9, -14, 9, 1, 6, +-19, -9, 8, 20, -24, 1, 1, 3, +-10, 11, -17, -8, -1, 33, -20, -16, +-5, 19, -18, -6, -6, 34, -30, -20, +7, 39, -40, -27, 7, 48, -34, -20, +-6, 25, -24, -4, -11, 32, -27, -17, +-3, 31, -35, -14, -9, 35, -28, -2, +-22, 14, -14, -1, -27, 33, -26, -17, +-15, 38, -39, -14, -17, 40, -31, -8, +-29, 28, -29, -8, -24, 46, -44, -23, +-8, 44, -56, -15, -14, 40, -45, -6, +-31, 32, -39, -10, -27, 45, -47, -20, +-22, 38, -49, -4, -42, 34, -36, 10, +-51, 16, -33, 11, -55, 31, -38, 8, +-54, 15, -32, 27, -70, 3, -23, 38, +-75, 0, -33, 26, -60, 20, -48, 16, +-54, 11, -48, 30, -68, 8, -43, 31, +-66, 11, -57, 18, -54, 29, -71, 19, +-57, 11, -59, 38, -75, 3, -51, 40, +-73, 9, -68, 23, -57, 24, -77, 25, +-70, 13, -53, 30, -96, 15, -43, 24, +-95, 29, -60, 5, -77, 42, -76, 13, +-73, 19, -69, 28, -87, 21, -70, 23, +-79, 30, -88, 12, -62, 31, -95, 25, +-73, 15, -82, 31, -82, 20, -84, 20, +-79, 38, -96, 8, -76, 41, -90, 19, +-86, 17, -78, 32, -100, 22, -72, 23, +-99, 26, -74, 24, -108, 21, -64, 40, +-118, 4, -64, 43, -108, 20, -84, 22, +-83, 29, -96, 15, -86, 30, -89, 28, +-102, 23, -85, 25, -87, 33, -107, 12, +-68, 39, -119, 19, -68, 24, -106, 34, +-83, 12, -97, 31, -83, 31, -110, 17, +-74, 34, -103, 20, -92, 28, -75, 24, +-116, 27, -63, 16, -113, 43, -76, 3, +-99, 45, -82, 13, -97, 27, -75, 27, +-110, 28, -69, 18, -103, 39, -83, 12, +-87, 36, -90, 18, -82, 29, -96, 21, +-74, 36, -105, 8, -62, 50, -112, 1, +-58, 45, -106, 10, -63, 32, -100, 17, +-62, 32, -100, 10, -56, 32, -98, 14, +-64, 28, -88, 24, -70, 19, -85, 24, +-67, 30, -90, 11, -62, 37, -84, 12, +-70, 29, -68, 18, -80, 23, -66, 21, +-72, 24, -73, 15, -61, 24, -76, 25, +-66, 11, -62, 33, -76, 6, -54, 32, +-76, 12, -57, 25, -67, 14, -62, 31, +-70, 7, -51, 32, -73, 6, -45, 27, +-74, 13, -49, 23, -63, 11, -54, 30, +-63, 3, -51, 34, -62, 2, -48, 28, +-60, 8, -47, 19, -54, 13, -54, 19, +-48, 10, -57, 21, -45, 13, -53, 11, +-46, 19, -50, 10, -46, 17, -47, 10, +-45, 11, -50, 19, -46, 13, -48, 15, +-42, 9, -44, 18, -48, 7, -35, 16, +-54, 9, -34, 18, -51, 10, -33, 8, +-50, 19, -35, 6, -45, 17, -36, 5, +-39, 11, -34, 5, -37, 13, -40, 2, +-35, 19, -46, 6, -25, 10, -50, 11, +-24, 6, -45, 12, -24, 2, -47, 14, +-23, 1, -42, 15, -29, -3, -31, 16, +-39, -7, -17, 21, -54, -9, -6, 21, +-57, -11, -1, 21, -58, -14, -2, 26, +-57, -18, 3, 25, -62, -15, 0, 25, +-53, -16, -8, 25, -42, -19, -17, 27, +-36, -19, -23, 28, -24, -26, -27, 28, +-18, -27, -35, 36, -17, -32, -29, 38, +-21, -40, -19, 43, -33, -40, -9, 44, +-42, -40, 4, 41, -52, -39, 11, 44, +-59, -39, 19, 40, -59, -36, 19, 34, +-52, -36, 14, 33, -47, -34, 6, 37, +-37, -38, -5, 38, -22, -35, -22, 34, +0, -35, -35, 30, 9, -28, -39, 23, +16, -26, -43, 18, 19, -14, -45, 6, +18, 0, -42, -4, 16, 7, -31, -16, +6, 19, -26, -24, 11, 23, -29, -28, +11, 27, -26, -27, 8, 22, -15, -27, +2, 20, -14, -21, 6, 15, -18, -15, +8, 10, -12, -13, 8, 4, -10, -5, +3, 4, -6, -8, 4, 7, -3, -12, +-5, 15, 10, -20, -12, 20, 21, -32, +-11, 31, 14, -42, -1, 43, 7, -54, +6, 53, 0, -59, 14, 60, -8, -66, +34, 60, -29, -65, 52, 61, -40, -64, +63, 53, -45, -53, 67, 42, -46, -43, +74, 28, -50, -29, 70, 17, -34, -17, +55, -4, -9, 0, 26, -17, 15, 19, +5, -31, 37, 28, -13, -43, 60, 41, +-35, -56, 80, 51, -45, -67, 84, 62, +-45, -71, 82, 60, -38, -70, 80, 57, +-30, -67, 66, 51, -8, -58, 42, 38, +20, -42, 16, 19, 39, -19, -1, 2, +56, -7, -12, -13, 70, 4, -21, -24, +75, 13, -18, -31, 68, 12, -3, -24, +55, -4, 12, -9, 40, -20, 27, 10, +22, -38, 48, 30, -2, -58, 76, 49, +-20, -82, 90, 66, -30, -91, 95, 70, +-34, -87, 98, 61, -31, -80, 96, 48, +-18, -67, 79, 27, -1, -37, 51, 4, +25, -13, 40, -31, 40, 14, 24, -53, +58, 32, 7, -71, 74, 46, -2, -80, +75, 49, 3, -75, 62, 38, 19, -58, +55, 10, 34, -39, 38, -8, 46, -14, +23, -32, 65, 4, 6, -48, 73, 17, +3, -50, 75, 5, 13, -37, 71, -18, +16, -10, 61, -43, 27, 17, 46, -72, +48, 48, 23, -104, 69, 74, 7, -124, +78, 88, 4, -131, 82, 86, 3, -128, +87, 78, 4, -122, 77, 72, 17, -111, +60, 62, 31, -102, 55, 51, 33, -100, +64, 49, 24, -102, 65, 57, 21, -107, +70, 62, 14, -113, 86, 64, -5, -118, +110, 66, -24, -117, 120, 60, -26, -109, +120, 47, -28, -88, 120, 23, -16, -70, +102, 3, 13, -47, 61, -23, 56, -17, +21, -54, 92, 11, -11, -76, 120, 27, +-34, -89, 143, 34, -53, -93, 151, 35, +-47, -89, 131, 26, -20, -72, 100, 3, +15, -46, 67, -25, 55, -22, 21, -48, +112, -2, -37, -71, 167, 16, -83, -84, +192, 33, -96, -95, 199, 35, -101, -89, +197, 29, -88, -86, 175, 22, -52, -80, +132, 15, -4, -75, 90, 7, 28, -63, +59, 1, 58, -61, 30, -2, 91, -61, +-1, 2, 112, -66, -5, 2, 106, -69, +6, 10, 88, -76, 27, 16, 67, -84, +51, 27, 30, -89, 90, 30, -10, -89, +121, 31, -26, -94, 128, 35, -30, -95, +133, 34, -39, -92, 142, 29, -41, -90, +130, 33, -21, -95, 106, 36, 4, -99, +82, 42, 23, -101, 60, 43, 50, -102, +25, 45, 87, -104, -7, 44, 106, -99, +-12, 32, 100, -80, -7, 13, 102, -68, +-10, 2, 99, -52, -5, -12, 85, -39, +10, -19, 66, -33, 28, -23, 52, -37, +39, -11, 35, -51, 61, 4, 8, -65, +80, 19, -2, -75, 78, 25, 13, -83, +56, 33, 24, -81, 49, 26, 27, -69, +41, 15, 46, -63, 17, 8, 61, -49, +7, -7, 61, -29, 12, -29, 59, -11, +4, -44, 71, 7, -19, -56, 93, 13, +-30, -63, 91, 25, -21, -79, 75, 49, +-15, -99, 73, 67, -14, -113, 71, 72, +-7, -111, 56, 69, 0, -100, 54, 56, +-1, -89, 58, 41, -3, -67, 39, 26, +28, -56, 12, 10, 43, -34, 2, -7, +45, -20, 6, -24, 43, -2, -3, -37, +47, 12, -7, -41, 43, 8, 8, -33, +25, -3, 22, -24, 17, -7, 16, -15, +15, -11, 30, -10, -4, -28, 58, 7, +-34, -38, 72, 14, -31, -40, 50, 21, +-18, -41, 43, 29, -17, -55, 50, 29, +-16, -39, 28, -2, 24, 8, -23, -53, +67, 55, -53, -85, 77, 73, -49, -96, +63, 92, -40, -119, 63, 116, -45, -137, +68, 116, -50, -111, 59, 80, -28, -74, +30, 43, 8, -42, -13, 17, 48, -15, +-52, -5, 73, 3, -59, -11, 66, -10, +-43, 14, 41, -26, -22, 17, 32, -21, +-24, 18, 25, -36, -2, 61, -16, -100, +47, 129, -63, -145, 81, 128, -71, -108, +74, 75, -68, -66, 85, 70, -107, -93, +129, 121, -145, -128, 141, 117, -117, -84, +80, 48, -41, -19, 10, 13, 4, -19, +-7, 33, 3, -39, -7, 35, 20, -17, +-50, -3, 78, 25, -110, -37, 121, 50, +-124, -56, 100, 70, -85, -69, 54, 73, +-47, -55, 29, 45, -31, -28, 21, 26, +-22, -25, 3, 38, 6, -37, -38, 40, +43, -16, -68, 1, 65, 23, -73, -26, +58, 27, -64, -8, 46, 9, -61, 0, +58, 12, -77, -17, 70, 30, -78, -26, +53, 25, -45, -11, 11, 10, -12, 6, +-12, -3, 1, 17, -17, -21, 6, 44, +-32, -52, 32, 64, -59, -52, 42, 48, +-42, -32, 4, 29, 3, -24, -29, 36, +7, -43, -1, 58, -49, -47, 56, 35, +-82, 2, 43, -25, -25, 54, -33, -55, +42, 48, -68, -12, 36, -18, -19, 42, +-35, -38, 37, 26, -69, 14, 37, -36, +-45, 55, 5, -38, -12, 11, -18, 31, +0, -54, -28, 66, 6, -44, -32, 25, +5, 3, -25, -6, -19, 11, 14, 8, +-66, -9, 57, 17, -95, -6, 57, 11, +-59, -9, -6, 24, 17, -30, -78, 42, +66, -34, -91, 29, 32, -5, -27, -4, +-42, 22, 31, -16, -63, 15, 13, 4, +-28, -13, -26, 48, -13, -58, -9, 76, +-47, -64, 25, 43, -57, 15, -1, -61, +-9, 105, -51, -103, 16, 87, -37, -27, +-37, -20, 36, 56, -99, -46, 62, 29, +-80, 8, 6, -23, -14, 26, -55, 19, +26, -52, -67, 80, 19, -69, -61, 48, +21, 11, -74, -49, 40, 72, -90, -46, +46, 3, -77, 70, 10, -128, -25, 166, +-54, -150, 30, 129, -100, -66, 61, 15, +-109, 28, 56, -16, -101, -5, 48, 63, +-101, -113, 51, 168, -105, -159, 40, 137, +-75, -75, -2, 18, -35, 61, -26, -94, +-35, 115, -5, -109, -56, 118, -10, -100, +-16, 111, -80, -124, 70, 146, -161, -122, +115, 105, -158, -62, 74, 22, -102, 37, +19, -48, -62, 61, -9, -54, -39, 62, +-42, -36, -1, 47, -80, -41, 27, 44, +-81, -16, -1, 21, -35, -8, -44, 3, +-12, 13, -46, 10, -33, -5, -10, 9, +-67, -7, 11, 21, -66, 2, -20, -14, +-17, 42, -84, -50, 49, 92, -134, -93, +73, 90, -135, -63, 56, 62, -109, -28, +39, 17, -100, -13, 25, 27, -74, 4, +-30, -14, 8, 50, -130, -76, 92, 142, +-176, -150, 96, 163, -132, -152, 24, 143, +-60, -84, -25, 43, -37, 2, -32, -32, +-40, 80, -36, -71, -20, 65, -67, -41, +6, 36, -75, 8, -10, -15, -31, 19, +-74, -7, 30, 21, -101, -3, 11, 3, +-42, 1, -86, 18, 65, 13, -174, -18, +117, 40, -175, -58, 62, 111, -86, -102, +-43, 96, 24, -61, -138, 34, 96, 28, +-171, -48, 85, 51, -116, -23, -15, 23, +9, 16, -139, -22, 104, 23, -173, -3, +72, 30, -84, -37, -50, 60, 38, -69, +-139, 95, 74, -59, -121, 25, 14, 25, +-37, -50, -71, 101, 32, -107, -101, 94, +14, -46, -48, 15, -50, 65, 8, -127, +-72, 181, -15, -181, -11, 182, -94, -114, +49, 39, -110, 44, 22, -66, -59, 86, +-23, -49, -28, -6, -28, 70, -34, -61, +-33, 38, 10, 15, -98, -58, 64, 91, +-110, -39, -10, -21, 32, 87, -158, -97, +129, 80, -143, -8, -2, -56, 55, 86, +-172, -29, 136, -44, -132, 128, 18, -159, +-7, 133, -56, -25, -25, -57, 12, 95, +-84, -51, 5, -13, 13, 88, -127, -95, +107, 41, -110, 62, 2, -113, 44, 116, +-119, -54, 76, -17, -67, 73, -27, -38, +6, -48, -39, 142, -49, -173, 17, 171, +-38, -102, -43, 37, 54, -2, -79, 38, +26, -73, 16, 83, -79, -31, 50, -56, +-24, 158, -102, -174, 113, 102, -154, 39, +50, -143, -5, 175, -68, -104, 46, -25, +-6, 147, -55, -163, 68, 104, -28, 9, +-68, -104, 120, 149, -155, -109, 55, 23, +-2, 53, -116, -66, 101, 33, -81, 45, +-10, -112, 89, 135, -103, -94, 93, 47, +-30, -31, 8, 63, -30, -115, 49, 155, +-102, -135, 46, 61, -33, 24, -71, -59, +111, 42, -129, 11, 99, -62, -9, 87, +-15, -49, 62, -14, -26, 77, 22, -121, +-34, 145, 27, -130, -78, 88, 43, -41, +-58, 4, -10, 25, 50, -36, -48, 37, +42, -30, 50, 31, -29, -1, 48, -47, +37, 83, -85, -95, 99, 79, -110, -42, +6, 5, 42, 6, -120, 3, 88, 5, +1, -31, -52, 71, 147, -101, -77, 124, +81, -124, 24, 112, -49, -92, 58, 55, +-31, -7, -63, -49, 48, 70, -51, -43, +-26, -9, 90, 63, -91, -78, 157, 30, +-64, 42, 87, -99, 24, 96, -19, -36, +33, -63, -33, 161, 0, -216, -39, 189, +0, -101, -13, -27, 16, 136, 3, -176, +53, 110, 32, 9, 37, -125, 33, 170, +31, -148, -16, 76, 27, -4, -71, -16, +50, -11, -80, 50, 8, -76, 41, 68, +-60, -33, 120, -23, -48, 57, 93, -55, +41, 27, -38, 2, 109, -23, -74, 2, +12, 37, 10, -61, -93, 42, 81, 3, +-88, -43, 39, 48, 77, -10, -86, -50, +178, 73, -73, -35, 90, -34, 20, 76, +-40, -65, 53, -16, -38, 116, -62, -180, +77, 153, -103, -60, 64, -58, 0, 139, +13, -144, 58, 66, 35, 46, 0, -124, +92, 121, -42, -60, -5, -30, 62, 93, +-126, -84, 71, 12, -35, 65, -48, -125, +118, 144, -106, -134, 128, 95, 8, -49, +-5, -9, 92, 72, -33, -129, 26, 137, +-7, -94, -16, 21, -5, 43, -16, -89, +-1, 87, -10, -45, 50, -5, -16, 46, +49, -80, 58, 87, -40, -67, 84, 33, +-22, -14, -14, 9, 37, -24, -57, 44, +3, -48, 45, 14, -95, 35, 111, -67, +-24, 74, -15, -51, 132, 4, -93, 39, +85, -56, 27, 40, -107, -7, 151, -36, +-151, 79, 64, -93, 15, 57, -69, 6, +96, -79, -27, 120, 21, -123, 67, 86, +-31, -43, 48, 15, 13, -3, -39, -3, +36, 4, -28, -7, -19, 6, 20, 1, +-22, -17, 21, 28, 40, -36, -17, 32, +84, -44, -24, 42, 50, -31, -9, 6, +5, 29, -3, -48, -32, 32, 15, 19, +-37, -72, 14, 92, -7, -63, 25, 10, +15, 37, 54, -57, -17, 20, 101, 31, +-74, -74, 83, 86, -47, -67, -4, 18, +1, 23, -38, -37, 1, 10, 16, 28, +-42, -64, 83, 86, -28, -92, 66, 83, +17, -95, 37, 103, -5, -101, 40, 67, +-52, -7, 33, -61, -51, 104, 1, -105, +-18, 58, 1, -1, -5, -39, 35, 40, +15, -18, 26, -23, 49, 43, -1, -36, +37, 4, 11, 25, -38, -48, 48, 44, +-79, -19, 27, -14, -33, 30, -6, -22, +13, -13, 7, 47, 32, -80, 10, 69, +64, -42, -31, 10, 78, 3, -29, 3, +-4, -31, 48, 60, -97, -73, 61, 63, +-41, -44, -47, 21, 101, 0, -120, -21, +127, 28, -33, -40, 12, 39, 80, -26, +-49, -4, 63, 28, -16, -38, -4, 30, +6, -4, -11, -39, -23, 66, 21, -74, +-36, 58, 33, -32, -19, -6, 48, 34, +-35, -52, 80, 65, -48, -73, 64, 70, +-12, -50, -11, 22, 44, 13, -59, -45, +48, 61, -53, -48, 38, 17, -49, 23, +59, -68, -55, 98, 66, -111, -26, 91, +24, -52, 34, -4, -26, 56, 52, -85, +-17, 77, 8, -46, 22, 10, -45, 13, +55, -12, -74, -17, 70, 51, -71, -75, +61, 63, -34, -32, 26, -22, 27, 62, +-26, -74, 71, 46, -41, 6, 58, -62, +-22, 96, 19, -89, -12, 41, 7, 21, +-30, -66, 24, 70, -38, -33, 24, -34, +-10, 89, 14, -107, 11, 77, 28, -19, +-11, -37, 66, 67, -46, -63, 57, 29, +-19, 6, -24, -34, 50, 43, -102, -38, +96, 23, -104, -20, 81, 17, -56, -16, +59, 13, -20, -18, 46, 23, 3, -24, +12, 15, 31, 10, -38, -44, 49, 81, +-65, -93, 39, 73, -50, -22, 15, -41, +-19, 97, 10, -123, 1, 117, 12, -80, +21, 40, 9, -3, 26, -20, 7, 22, +3, -15, 13, 6, -24, -8, 14, 16, +-26, -43, 10, 59, -28, -68, 20, 59, +-8, -32, -3, -8, 54, 59, -65, -102, +117, 133, -95, -135, 90, 100, -31, -30, +-24, -59, 60, 137, -86, -177, 57, 156, +-31, -94, -20, 3, 50, 67, -59, -98, +60, 88, -22, -54, 26, 17, 3, 0, +17, 6, -4, -26, 10, 38, 2, -34, +-19, 9, 19, 25, -40, -45, 29, 48, +-34, -37, 31, 21, -31, -15, 45, 17, +-38, -20, 49, 26, -18, -29, 24, 24, +-5, -15, 10, 8, -13, 2, 14, -18, +-14, 30, -11, -42, 20, 46, -46, -36, +38, 26, -25, -14, 13, 7, 2, 4, +19, -5, -23, -2, 66, 10, -71, -18, +67, 25, -34, -18, -24, 11, 62, 5, +-98, -22, 86, 26, -66, -19, 11, 9, +33, 4, -60, -1, 75, -21, -31, 50, +3, -90, 64, 112, -87, -110, 96, 77, +-70, -20, 15, -37, 29, 71, -79, -74, +79, 52, -79, -14, 49, -11, -19, 5, +22, 22, -19, -68, 54, 111, -58, -133, +75, 118, -51, -78, 21, 23, 11, 27, +-47, -62, 54, 72, -67, -68, 43, 62, +-32, -54, 14, 44, 9, -37, -9, 31, +25, -37, -1, 48, -1, -64, 24, 73, +-23, -67, 17, 38, -3, -7, -18, -21, +9, 22, -2, 4, -33, -50, 68, 81, +-78, -90, 69, 60, -13, 3, -40, -76, +107, 141, -133, -164, 131, 150, -92, -102, +37, 43, 7, 3, -42, -32, 32, 39, +-11, -40, -19, 28, 35, -16, -25, 8, +3, -3, 41, 2, -52, -7, 63, 5, +-28, -2, -17, -5, 66, 8, -101, 0, +96, -23, -76, 57, 29, -96, 9, 123, +-33, -137, 46, 119, -37, -80, 31, 34, +-24, 19, 31, -49, -30, 57, 35, -42, +-19, 10, 4, 12, 18, -34, -37, 37, +40, -31, -43, 18, 39, -4, -41, -12, +35, 40, -29, -61, 23, 74, -1, -73, +-15, 58, 34, -32, -31, 1, 20, 22, +-3, -26, -22, 29, 34, -25, -29, 18, +13, -26, 6, 38, -28, -47, 44, 48, +-47, -49, 54, 43, -54, -43, 53, 55, +-42, -64, 35, 56, -8, -29, -19, -11, +46, 56, -57, -85, 50, 77, -24, -37, +-15, -27, 47, 86, -69, -121, 64, 117, +-36, -82, -2, 36, 33, 9, -33, -34, +23, 32, 17, -21, -46, 5, 65, -2, +-52, 4, 7, -3, 36, 2, -79, 5, +83, -11, -65, 10, 23, -2, 15, -2, +-41, 7, 45, 2, -25, -9, 0, 21, +32, -28, -46, 22, 53, -11, -47, -7, +30, 19, -21, -24, 6, 16, -10, 5, +4, -26, -2, 50, -4, -73, 24, 93, +-42, -100, 68, 93, -67, -71, 55, 31, +-28, 19, -13, -54, 37, 64, -53, -46, +32, 8, -2, 27, -40, -47, 67, 42, +-72, -16, 52, -4, -19, 24, -5, -23, +29, 5, -28, 21, 20, -53, -4, 72, +-23, -81, 35, 76, -52, -59, 46, 30, +-37, 6, 14, -44, 15, 64, -29, -58, +34, 19, -10, 41, -21, -94, 60, 112, +-81, -79, 68, 9, -43, 78, -10, -136, +39, 147, -60, -108, 54, 33, -43, 43, +33, -93, -28, 108, 30, -90, -23, 63, +13, -44, 17, 34, -45, -28, 50, 22, +-38, -3, -6, -21, 40, 39, -75, -31, +68, -3, -35, 49, -23, -87, 76, 106, +-104, -97, 102, 71, -69, -34, 20, 5, +25, 22, -58, -45, 69, 64, -65, -80, +34, 82, -4, -65, -34, 23, 61, 23, +-72, -68, 71, 83, -49, -73, 30, 38, +-17, 5, 13, -24, -22, 20, 32, 4, +-37, -28, 18, 39, 7, -28, -51, 5, +71, 23, -83, -35, 61, 30, -28, -9, +-11, -15, 43, 32, -60, -32, 63, 24, +-54, -6, 43, -13, -26, 25, 7, -30, +4, 28, -23, -14, 21, -6, -18, 30, +-2, -58, 16, 76, -25, -77, 16, 59, +5, -25, -28, -10, 50, 34, -58, -31, +51, 10, -31, 17, 3, -37, 15, 34, +-30, -17, 24, -11, -23, 35, 7, -45, +0, 43, -14, -29, 23, 18, -26, -14, +35, 13, -32, -14, 28, 9, -13, 1, +-5, -15, 17, 26, -35, -26, 37, 16, +-46, -3, 43, -14, -40, 19, 25, -12, +-14, 5, 1, 5, 26, -26, -37, 40, +52, -56, -55, 68, 45, -62, -41, 47, +28, -20, -20, -16, -3, 52, 16, -74, +-43, 78, 64, -66, -81, 43, 81, -16, +-57, -9, 24, 24, 16, -26, -55, 31, +67, -18, -72, 13, 47, 3, -29, -11, +4, 8, 9, -1, -23, -19, 29, 38, +-33, -52, 31, 46, -19, -20, 2, -21, +28, 60, -54, -87, 72, 94, -79, -76, +63, 50, -45, -19, 14, -2, 4, 16, +-29, -21, 35, 30, -42, -37, 39, 44, +-31, -45, 18, 36, 1, -22, -17, 8, +26, 1, -24, -5, 14, 7, -11, -15, +18, 29, -33, -57, 52, 76, -67, -73, +56, 43, -26, 12, -26, -70, 72, 109, +-97, -114, 88, 76, -48, -12, -8, -53, +58, 98, -87, -107, 78, 91, -46, -52, +-4, 13, 51, 16, -82, -35, 90, 41, +-82, -35, 49, 27, -14, -12, -22, -6, +35, 26, -34, -31, 13, 21, 13, 10, +-37, -46, 49, 72, -41, -74, 18, 49, +3, -2, -24, -43, 21, 73, -11, -79, +-9, 58, 16, -26, -20, 2, 1, 16, +22, -18, -38, 10, 48, -2, -41, -6, +36, 8, -24, -13, 14, 18, -5, -24, +-6, 16, 15, 2, -32, -31, 44, 54, +-51, -66, 45, 53, -22, -27, 4, -18, +21, 58, -39, -78, 45, 81, -44, -60, +33, 30, -21, 2, 5, -32, 8, 46, +-23, -50, 20, 47, -19, -32, 1, 19, +13, -7, -20, 4, 13, -6, 11, 13, +-29, -20, 45, 15, -37, -2, 19, -28, +8, 53, -33, -66, 29, 64, -21, -39, +1, -2, 15, 32, -26, -44, 14, 41, +6, -19, -20, -11, 26, 40, -17, -54, +6, 51, 15, -41, -28, 16, 32, 11, +-35, -37, 22, 57, -15, -62, -6, 54, +19, -30, -30, 3, 30, 19, -19, -19, +-3, 10, 28, 11, -38, -31, 42, 32, +-29, -25, 7, 15, 0, -10, 0, 24, +-27, -41, 42, 63, -55, -64, 46, 32, +-9, 19, -35, -79, 80, 121, -101, -131, +100, 105, -76, -52, 36, 3, 1, 31, +-32, -39, 46, 27, -46, -16, 36, 8, +-25, -10, 7, 18, 10, -27, -19, 27, +24, -22, -11, 9, 2, -4, 14, -3, +-18, 7, 10, -11, 0, 20, -14, -27, +11, 29, -2, -18, -19, -5, 38, 29, +-51, -43, 47, 41, -32, -21, 9, -2, +10, 23, -17, -33, 18, 30, -11, -21, +7, 11, 0, -14, -1, 17, 0, -23, +-5, 27, 7, -30, -3, 25, -9, -24, +22, 31, -37, -35, 39, 43, -31, -39, +17, 20, 0, 9, -15, -35, 20, 51, +-22, -49, 20, 29, -26, 3, 23, -26, +-25, 45, 11, -44, 7, 34, -25, -24, +41, 13, -45, -6, 40, 3, -26, -3, +18, 0, -11, -3, 16, 1, -28, 8, +24, -10, -21, 19, 1, -18, 15, 12, +-29, 6, 27, -24, -20, 41, 9, -48, +-1, 40, 2, -22, -3, 3, 2, 9, +9, -9, -19, -4, 31, 16, -31, -19, +16, 13, -4, 11, -10, -31, 11, 40, +-1, -31, -17, 6, 26, 25, -23, -47, +7, 50, 21, -38, -42, 14, 48, 14, +-36, -36, 20, 38, -5, -26, -5, 10, +-2, 11, 10, -21, -16, 15, 18, 4, +-18, -29, 12, 59, -14, -72, 19, 63, +-23, -29, 23, -19, -11, 60, -4, -79, +14, 69, -16, -30, 8, -20, 3, 58, +-10, -66, 4, 42, 17, -2, -42, -35, +57, 54, -59, -45, 45, 17, -23, 12, +0, -22, 13, 13, -13, 9, 10, -34, +-6, 45, 9, -40, -13, 21, 17, 0, +-16, -12, 16, 8, -7, -4, 7, -2, +-5, -6, 9, 21, -11, -34, 14, 36, +-8, -29, 3, 10, 5, 7, -1, -22, +-3, 24, 10, -20, -16, 13, 13, -2, +-12, 0, 11, 2, -12, -3, 14, 5, +-8, -11, 5, 3, 8, 9, -24, -22, +36, 33, -41, -33, 37, 21, -27, -2, +20, -19, -16, 28, 12, -19, -11, 2, +13, 13, -10, -21, 0, 21, 5, -7, +-13, -7, 21, 15, -25, -17, 31, 9, +-28, -5, 24, -4, -5, 2, -16, 0, +33, 1, -52, 7, 45, -1, -35, 2, +15, 2, 4, -11, -5, 17, -1, -30, +22, 35, -34, -36, 32, 34, -18, -21, +-3, 2, 22, 17, -38, -27, 33, 39, +-30, -36, 16, 38, -12, -28, 6, 20, +-2, -8, 0, -9, 3, 25, -4, -34, +0, 32, 7, -18, -13, -4, 12, 27, +-1, -43, -17, 44, 36, -37, -42, 22, +31, -5, -8, -6, -15, 10, 32, -15, +-23, 11, 7, -18, 19, 23, -29, -32, +27, 36, -12, -27, -13, 15, 34, 2, +-40, -23, 37, 35, -23, -40, 8, 35, +0, -16, -3, -7, 8, 26, -7, -38, +11, 33, -10, -16, 7, -6, -5, 30, +0, -39, -1, 32, 10, -15, -25, -2, +37, 12, -37, -13, 30, 1, -13, 11, +-6, -11, 16, 0, -16, 23, 8, -42, +0, 50, -2, -41, -2, 16, 17, 9, +-28, -28, 33, 30, -30, -17, 19, -2, +-2, 13, -8, -16, 9, 16, -11, -7, +8, 6, -7, -9, 8, 13, -13, -8, +16, -7, -14, 30, 5, -50, 5, 60, +-15, -52, 19, 29, -15, 0, 5, -26, +8, 42, -22, -43, 30, 38, -29, -32, +24, 24, -16, -13, 4, 1, 8, 13, +-17, -27, 20, 37, -16, -37, 6, 28, +5, -9, -11, -13, 15, 29, -15, -32, +7, 31, 2, -26, -7, 23, 2, -19, +5, 16, -16, -7, 22, -7, -21, 27, +13, -47, 0, 61, -20, -54, 32, 36, +-34, -9, 26, -19, -8, 39, -10, -49, +27, 45, -33, -35, 28, 23, -19, -8, +2, 3, 7, 5, -7, -15, 1, 24, +7, -30, -15, 34, 18, -30, -8, 14, +0, 3, 9, -18, -18, 32, 17, -30, +-17, 24, 10, -6, -8, -7, 0, 20, +8, -23, -12, 12, 23, -1, -25, -15, +25, 23, -17, -25, 9, 16, -1, -3, +-4, -7, 2, 13, -1, -7, 2, -5, +-4, 15, 14, -22, -21, 14, 24, 3, +-22, -19, 14, 28, 1, -25, -21, 15, +33, 7, -34, -31, 30, 44, -19, -44, +9, 25, 3, 3, -11, -35, 19, 55, +-24, -59, 22, 45, -18, -15, 8, -18, +6, 42, -22, -46, 30, 37, -31, -17, +21, 4, -10, -1, 3, 9, -2, -26, +6, 38, -14, -33, 13, 17, -8, 12, +-5, -36, 20, 45, -27, -35, 25, 12, +-13, 16, 0, -36, 13, 38, -16, -27, +12, 9, -4, 6, -4, -11, 4, 13, +-3, -7, -1, 5, 6, -9, -1, 6, +3, -9, -3, 3, 9, 5, -14, -15, +19, 19, -22, -12, 15, 4, -7, 9, +-4, -16, 16, 10, -13, -8, 10, 0, +-2, 2, -2, -4, 4, 4, -2, -6, +1, 11, 1, -19, 5, 19, -7, -17, +11, 8, -12, 4, 11, -14, -4, 11, +1, -4, 1, -5, -5, 14, 7, -12, +-7, 0, 6, 14, -12, -15, 10, 10, +-7, 10, -2, -28, 11, 39, -16, -35, +17, 14, -15, 19, 4, -42, 7, 52, +-12, -47, 11, 27, -5, -3, 5, -22, +5, 25, -4, -18, 0, 3, 6, 13, +-13, -18, 16, 14, -10, -5, 5, -9, +5, 14, -14, -9, 17, -1, -15, 12, +15, -22, -11, 19, 5, -3, -6, -12, +7, 28, -3, -39, 1, 36, 0, -20, +-5, 2, 7, 17, -10, -27, 10, 32, +-10, -29, 12, 19, -11, -11, 10, 3, +-8, 3, 3, -4, 0, 6, -1, -8, +5, 5, -3, -4, 1, 2, 4, 0, +-4, -8, 5, 17, -3, -29, -1, 42, +0, -45, 2, 35, -5, -14, 4, -12, +2, 34, -4, -51, 9, 50, -14, -35, +9, 19, 0, -7, -4, 0, 11, -5, +-11, 11, 8, -8, -4, -6, 5, 27, +-2, -56, 8, 69, -11, -64, 11, 42, +-9, -6, 1, -25, 8, 44, -12, -45, +12, 33, -6, -18, 2, 5, 3, -2, +-5, 7, 1, -8, -2, 9, 0, 0, +-1, -13, 4, 23, -6, -28, 7, 22, +-3, -13, 5, -2, -6, 14, 7, -18, +-9, 17, 12, -13, -9, 4, 6, 6, +-1, -15, 2, 17, 0, -20, 1, 18, +-3, -8, 3, -3, 2, 11, -4, -16, +6, 14, -8, -3, 2, -4, 4, 7, +-3, -8, 6, -3, -7, 17, 1, -22, +-2, 23, -2, -8, -2, -6, 4, 20, +-7, -23, 15, 7, -11, 7, 8, -21, +-5, 26, 1, -15, -3, -1, 5, 17, +-6, -25, 5, 23, -3, -9, 2, -6, +4, 11, -7, -2, 7, -14, -5, 30, +4, -42, 2, 35, -2, -17, 6, -11, +-3, 31, 2, -41, 0, 37, -2, -21, +2, 6, -2, 7, 5, -13, -3, 10, +5, -4, 2, -2, 0, 0, 7, 2, +-4, -9, 9, 13, -6, -11, 9, 9, +-4, -2, 8, -4, -7, 12, 10, -11, +-2, 8, 3, 0, 7, -6, -7, 16, +15, -21, -4, 16, 10, -10, 2, 1, +5, 10, 9, -18, 1, 17, 6, -9, +6, 0, 6, 6, 9, -5, 5, -5, +8, 16, 7, -27, 9, 24, 4, -9, +10, -8, 11, 23, 6, -32, 9, 27, +12, -18, 4, 5, 18, 5, 1, -2, +14, -3, 8, 9, 7, -9, 13, 3, +12, 11, 12, -25, 16, 29, 1, -21, +16, 10, 10, 5, 13, -10, 16, 9, +12, 4, 8, -18, 18, 26, 6, -26, +26, 13, 11, 3, 18, -19, 14, 26, +9, -28, 18, 20, 13, -9, 20, -2, +16, 10, 13, -16, 12, 17, 11, -16, +19, 14, 14, -7, 24, 2, 11, -3, +15, -2, 9, 0, 18, 1, 16, 2, +21, -5, 13, 7, 10, -9, 10, 7, +16, -2, 17, -11, 24, 19, 11, -29, +15, 25, 4, -17, 16, 0, 16, 11, +14, -17, 17, 20, 2, -14, 10, 6, +-1, 3, 19, -3, 12, 0, 14, 5, +6, -5, -2, 2, 8, 6, 2, -13, +22, 16, 3, -15, 7, 9, -4, 1, +-5, -10, 9, 16, 0, -16, 19, 10, +-8, -6, 1, 1, -13, 3, -2, -3, +2, 6, 3, -5, 2, 6, -16, -8, +-11, 12, -13, -11, 0, 5, 1, 0, +-7, -12, -9, 20, -30, -25, -5, 26, +-26, -20, 10, 12, -23, -2, -9, -6, +-28, 10, -23, -17, -14, 17, -22, -13, +-2, 7, -34, -3, -19, -4, -41, 6, +-22, -7, -19, 7, -22, -9, -19, 7, +-49, -6, -27, 7, -49, -6, -12, 4, +-36, -5, -22, 2, -46, -2, -50, 8, +-39, -6, -43, 7, -22, -4, -48, 3, +-37, 5, -61, -7, -48, 10, -40, -10, +-42, 2, -29, 4, -62, -11, -45, 17, +-68, -18, -44, 17, -44, -15, -49, 11, +-49, 0, -70, -3, -53, 10, -74, -10, +-33, 13, -61, -17, -47, 15, -70, -6, +-68, -4, -56, 10, -69, -19, -39, 24, +-72, -24, -53, 19, -82, -14, -66, 8, +-63, 2, -63, -9, -50, 14, -84, -15, +-56, 14, -92, -12, -54, 9, -74, 0, +-59, -2, -68, 5, -80, -10, -73, 13, +-78, -16, -56, 15, -73, -17, -60, 12, +-83, -8, -77, -2, -72, 10, -76, -19, +-56, 26, -86, -20, -65, 18, -91, -7, +-68, -4, -73, 10, -67, -18, -64, 19, +-85, -18, -70, 16, -91, -10, -64, 7, +-70, -3, -67, -7, -66, 10, -88, -18, +-69, 23, -86, -18, -58, 14, -79, -4, +-63, -5, -83, 13, -73, -18, -73, 20, +-72, -18, -55, 10, -78, -8, -63, 2, +-84, 3, -63, -11, -71, 14, -59, -20, +-65, 18, -75, -15, -65, 10, -80, -2, +-57, -2, -70, 9, -59, -9, -68, 11, +-71, -7, -63, 3, -69, 1, -55, -2, +-66, 7, -58, -5, -69, 6, -62, -3, +-63, 3, -56, -1, -56, 1, -58, -2, +-56, -1, -65, 1, -55, -1, -56, 1, +-52, -1, -53, 2, -59, 0, -51, -1, +-61, 2, -43, -4, -53, 1, -44, -2, +-53, 2, -51, -4, -48, 3, -50, -8, +-37, 5, -48, -9, -44, 6, -53, 1, +-45, -4, -46, 9, -43, -6, -38, 2, +-40, -3, -41, -5, -44, 4, -37, -4, +-43, 2, -30, 1, -41, -6, -35, 4, +-39, -4, -40, -1, -30, 5, -33, -13, +-33, 13, -35, -11, -35, 4, -38, 5, +-34, -5, -30, 9, -30, -8, -31, 5, +-34, 1, -32, -4, -30, 8, -30, -4, +-27, 7, -28, -2, -27, 0, -28, 1, +-25, -2, -22, -3, -21, -2, -25, 2, +-25, -4, -23, 5, -23, -10, -19, 6, +-22, -3, -20, -3, -20, 8, -25, -12, +-21, 13, -21, -8, -17, 2, -19, 6, +-19, -7, -22, 9, -21, 0, -18, -4, +-17, 10, -17, -5, -16, 3, -16, 3, +-16, -11, -16, 13, -12, -11, -14, 6, +-12, 3, -13, -10, -13, 9, -10, -10, +-14, 3, -9, 6, -11, -10, -12, 12, +-16, -4, -10, -1, -10, 6, -6, -10, +-7, 8, -10, -3, -8, -1, -10, 2, +-7, -2, -10, 3, -3, 1, -8, -4, +-5, 3, -5, -4, -6, -4, -2, 7, +-4, -11, -4, 12, -7, -6, -5, 2, +-5, 3, 0, -7, -3, 5, -1, 2, +-2, -8, -1, 8, -3, -8, -2, 2, +1, 6, -1, -13, 0, 17, -1, -14, +0, 5, 2, 3, 1, -14, 4, 18, +-3, -12, 4, 6, -4, 3, 2, -6, +3, 6, 0, 0, 4, -2, 0, 9, +1, -7, 1, 8, 3, 0, 5, -7, +4, 11, 2, -10, 3, 6, 5, -2, +4, -7, 7, 12, 1, -11, 6, 12, +0, -4, 5, -1, 3, 8, 4, -11, +9, 11, 2, -9, 8, 4, 3, -2, +7, -4, 6, 4, 4, -6, 7, 6, +3, -7, 5, 8, 4, -8, 7, 6, +4, -4, 6, 2, 1, 6, 7, -9, +5, 7, 5, -9, 6, 2, 5, 1, +4, -4, 2, 9, 4, -6, 3, 2, +6, 1, 1, -3, 5, 6, 4, -3, +-1, 4, 3, 2, -1, 1, 5, -1, +4, 4, 3, -8, 3, 9, -1, -5, +3, 3, 0, 5, 5, -12, 4, 11, +3, -14, 1, 10, 3, -7, 1, 0, +2, 5, 2, -7, 0, 6, 1, -4, +-2, 3, 2, -1, 1, 0, 2, -3, +-1, 5, -2, -3, 4, -1, -3, 2, +4, -5, 1, 2, 2, -5, 0, -1, +-2, 6, 0, -9, -2, 13, 0, -11, +1, 6, -1, -1, -3, -4, 1, 8, +-1, -12, 0, 10, 0, -7, 0, 0, +2, 1, -6, -2, 0, 3, -4, 1, +0, -2, 0, 4, 1, -6, 0, 1, +-3, 3, 0, -7, 1, 4, -4, -1, +0, 2, -2, 2, -2, -3, 0, 1, +-1, 0, -1, -3, -1, 7, 0, -10, +-1, 10, -3, -6, 1, 3, 1, -3, +2, -3, 2, 2, 1, -5, 1, 3, +-3, -2, 3, 2, -2, -1, 1, 4, +0, -4, 1, 5, -2, -4, 2, 6, +0, -7, 4, 8, 3, -13, 1, 12, +1, -10, 3, 6, 3, -5, 3, -1, +1, 5, 3, -7, -1, 8, 6, -8, +-3, 7, 6, -3, 0, 2, 3, 0, +2, 2, 4, -6, 1, 8, 3, -5, +3, 2, 3, 3, 5, -8, 3, 9, +5, -9, 5, 2, 5, 2, 2, -5, +2, 9, 3, -3, 4, -2, 2, 12, +2, -13, 3, 20, 4, -16, 2, 12, +9, -6, -1, 0, 6, 10, 2, -11, +9, 11, 6, -14, 7, 10, 6, -12, +6, 11, 6, -10, 6, 9, 4, -6, +9, 1, 6, -1, 7, -1, 3, 5, +7, -1, 3, 1, 9, 1, 1, -4, +7, 8, -1, -4, 7, 5, 5, -4, +4, -2, 5, 7, 3, -12, 9, 15, +6, -20, 11, 19, 6, -17, 12, 12, +5, -6, 11, 4, 7, 5, 9, -5, +5, 15, 5, -9, 6, 14, 3, -8, +4, 9, 7, -6, 2, -1, 6, 2, +-1, -8, 11, -1, 0, -7, 8, 2, +6, -6, 11, -3, 6, 3, 11, -5, +12, 9, 12, -6, 14, 12, 11, -1, +10, 7, 8, 12, 6, -5, 6, 23, +1, -14, 4, 20, -1, -14, 2, 5, +-2, -5, 1, -10, 3, -1, 2, -19, +7, 1, 5, -20, 13, 3, 9, -13, +19, 5, 12, -3, 19, 7, 15, 6, +15, 10, 16, 12, 13, 8, 9, 17, +6, 8, 3, 9, -3, 12, -7, -1, +-3, 7, -3, -19, -4, 0, -8, -17, +-2, -13, -2, -12, 4, -21, 11, -8, +16, -22, 16, 0, 22, -10, 24, 2, +22, 10, 23, 9, 22, 19, 16, 16, +14, 23, 8, 15, 6, 18, -5, 13, +-7, 9, -12, 4, -14, -5, -13, -9, +-15, -15, -9, -20, -7, -20, 2, -30, +5, -18, 14, -31, 17, -6, 26, -22, +27, 9, 27, -3, 30, 19, 25, 15, +26, 23, 15, 32, 12, 23, 3, 36, +-3, 14, -12, 28, -16, 3, -19, 7, +-21, -7, -19, -19, -14, -20, -13, -38, +-6, -22, 3, -46, 13, -24, 18, -34, +25, -18, 30, -13, 34, -4, 34, 10, +33, 16, 26, 29, 25, 29, 11, 41, +5, 36, -5, 36, -11, 31, -19, 17, +-21, 18, -27, -8, -25, -1, -26, -28, +-15, -26, -10, -41, -1, -40, 4, -37, +18, -41, 18, -26, 31, -25, 33, -12, +38, -1, 33, 12, 32, 22, 22, 33, +19, 35, 6, 46, -2, 40, -10, 42, +-23, 33, -25, 25, -28, 9, -25, -4, +-24, -14, -21, -27, -16, -28, -6, -48, +0, -35, 11, -51, 20, -32, 28, -40, +31, -18, 33, -12, 33, 0, 32, 17, +26, 15, 17, 45, 10, 28, 2, 50, +-11, 36, -16, 42, -26, 34, -27, 19, +-29, 17, -28, -8, -25, -5, -19, -31, +-13, -25, -3, -41, 4, -40, 14, -36, +21, -44, 30, -25, 28, -29, 29, 1, +29, -9, 27, 21, 17, 15, 10, 39, +3, 30, -4, 42, -14, 39, -19, 33, +-27, 35, -27, 16, -29, 15, -25, -1, +-19, -14, -13, -18, -9, -32, 4, -33, +11, -45, 19, -36, 20, -37, 28, -27, +27, -24, 26, -6, 20, -3, 20, 14, +13, 10, 8, 33, -5, 25, -8, 41, +-18, 29, -21, 37, -24, 25, -26, 22, +-23, 10, -22, 2, -17, -8, -11, -16, +-5, -25, 6, -32, 11, -34, 16, -33, +17, -31, 21, -23, 19, -20, 19, -4, +17, -7, 12, 14, 5, 14, -3, 28, +-6, 29, -10, 28, -11, 31, -18, 24, +-18, 25, -22, 15, -21, 13, -14, -2, +-9, -10, -6, -14, -3, -24, 4, -24, +11, -37, 14, -26, 15, -32, 12, -13, +18, -23, 13, -3, 11, -1, 6, 10, +4, 17, -2, 19, -7, 32, -11, 24, +-14, 30, -14, 21, -16, 21, -16, 12, +-14, 7, -11, -3, -11, -7, -5, -17, +0, -22, 6, -26, 7, -27, 9, -24, +13, -26, 14, -17, 10, -11, 10, 0, +7, 3, 3, 17, 2, 13, -3, 26, +-8, 24, -9, 27, -12, 25, -13, 20, +-13, 16, -12, 5, -11, 3, -7, -11, +-5, -10, -3, -21, 2, -20, 4, -27, +6, -22, 8, -21, 12, -19, 14, -13, +8, -4, 9, 2, 8, 6, 2, 17, +-1, 21, -2, 22, -8, 25, -9, 23, +-11, 18, -13, 19, -11, 5, -9, 4, +-8, -9, -5, -11, -4, -18, -1, -20, +3, -23, 5, -22, 8, -19, 6, -15, +9, -7, 6, -5, 6, 10, 7, 2, +5, 20, 2, 12, -2, 26, -6, 20, +-5, 19, -7, 17, -7, 8, -9, 8, +-10, -1, -10, -3, -6, -13, -4, -14, +-4, -18, 2, -19, 3, -21, 3, -14, +7, -14, 8, -7, 10, -5, 6, 6, +5, 8, 3, 16, 1, 16, 1, 17, +-3, 21, -4, 12, -4, 15, -7, 2, +-8, 11, -11, -6, -5, -1, -7, -17, +-3, -9, -6, -19, 2, -15, 2, -19, +4, -11, 4, -8, 7, -8, 7, 2, +7, -1, 7, 14, 3, 9, 1, 23, +-2, 13, 1, 17, -3, 10, -2, 11, +-3, 3, -7, 4, -5, -4, -6, -9, +-4, -10, -8, -13, -5, -8, -2, -18, +0, -6, 1, -14, 0, 2, 3, -7, +5, 7, 5, 1, 5, 14, 5, 8, +2, 16, 1, 13, 1, 11, 0, 12, +1, 1, -3, 9, -5, -2, -7, 2, +-7, -9, -2, -8, -7, -12, -3, -7, +-5, -13, -2, -5, -1, -10, 3, -3, +3, -2, 4, 2, 5, 6, 1, 9, +2, 14, 4, 6, 8, 11, 1, 5, +3, 13, -2, 0, 2, 7, -1, -9, +-2, 4, -3, -12, -3, -3, -4, -11, +-5, -6, -3, -7, -2, -11, 0, -1, +-3, -7, 5, 4, -3, -2, 3, 13, +1, -1, 7, 14, 3, 1, 5, 14, +3, 2, 7, 4, 4, 0, 0, 2, +1, 1, 0, -8, 1, -2, -3, -13, +2, -4, -5, -13, 1, -2, -8, -8, +2, -1, -4, -5, 1, 4, -3, 0, +4, 3, 3, 3, 1, 6, 6, 7, +1, 3, 7, 10, -3, 1, 7, 9, +-4, -3, 5, 6, -4, -7, 4, 0, +-5, -8, 1, -2, -5, -6, -3, -3, +-3, -4, -3, -4, 0, 0, -6, -2, +2, 4, -4, -1, 4, 7, -5, 3, +7, 7, -2, 3, 9, 5, 0, 2, +6, 5, 1, 0, 5, 0, -2, 3, +-1, -4, 3, 0, -4, -8, 3, 1, +-7, -10, 2, 3, -6, -11, 3, 3, +-8, -5, 5, 1, -3, -3, 4, 2, +-1, 4, 5, -2, 1, 10, 3, -4, +6, 11, 2, -7, 7, 10, -2, -6, +9, 4, -5, -4, 7, 0, -6, -3, +4, -4, -6, -1, 2, -7, -5, 2, +-2, -7, -4, 6, -3, -8, 1, 8, +-2, -8, 6, 8, -2, -6, 5, 12, +-3, -3, 11, 6, -2, 0, 8, 4, +-3, 4, 6, -2, 0, 4, 4, -8, +0, 6, -3, -9, -3, 10, -5, -12, +0, 10, -6, -14, 2, 9, -7, -10, +4, 7, -7, -4, 6, 3, -3, 0, +7, -1, 0, 4, 6, -3, 5, 5, +2, -3, 5, 9, 3, -11, 5, 12, +-1, -12, 6, 11, -6, -11, 3, 10, +-6, -9, 1, 7, -6, -5, 1, 2, +-4, -1, 0, -3, 0, 3, -1, -6, +2, 9, 1, -13, 5, 13, -1, -13, +9, 12, 2, -16, 11, 9, 2, -13, +8, 8, -2, -6, 4, 6, 0, -4, +1, 2, -1, 2, -2, -1, -3, 7, +-4, -6, -2, 12, -6, -9, 1, 13, +-4, -13, 4, 11, 0, -15, 5, 10, +3, -15, 7, 6, -1, -6, 7, -1, +2, -1, 0, 1, 4, 4, 1, -6, +3, 11, -2, -8, 1, 14, -4, -9, +-2, 18, -7, -8, 0, 15, -2, -11, +0, 11, -3, -5, 1, 1, 3, -4, +0, -4, 3, 1, 1, -8, 4, 4, +1, -11, 6, 6, 3, -13, 5, 10, +1, -10, 2, 10, 1, -5, 0, 8, +2, -1, -3, 7, -2, 4, -1, 3, +-2, 5, -2, -1, 2, 2, -3, -4, +3, 2, 0, -8, 2, 2, 4, -12, +1, 3, 5, -14, 5, 2, 2, -8, +4, 1, 6, -6, -1, 3, 3, 3, +-2, 1, -2, 11, -3, 1, -4, 12, +-2, -1, -1, 9, -3, -2, 0, 4, +0, -2, -1, -3, 6, -2, -2, -7, +5, -2, 0, -5, 3, -5, 7, -5, +-1, -2, 1, 1, 4, -4, -1, 4, +2, -1, 2, 4, -5, 5, 4, 0, +-3, 7, 1, -2, -2, 11, -3, -3, +0, 4, 2, -2, -4, -2, 5, 1, +-1, -7, -1, 3, 7, -11, -2, 2, +7, -10, 4, -2, 1, -1, 2, -3, +2, 6, -3, -7, 7, 9, -5, -5, +3, 7, -2, 4, -8, 4, 3, 6, +-1, -7, -4, 12, 0, -7, -2, 8, +-1, -8, 7, -1, -10, 3, 7, -8, +-2, 6, 2, -13, 5, 7, 0, -10, +1, 5, 4, -1, -4, 0, 1, 7, +3, -6, -9, 12, 10, -10, -6, 8, +2, -4, -1, 4, -3, 1, 2, -7, +0, 8, -6, -9, 7, 5, -5, -4, +-2, 1, 8, -1, -7, -4, 7, 5, +1, -10, 2, 6, 4, -7, -2, 8, +-3, -1, 8, -1, -8, 8, 3, -7, +-1, 11, -7, -8, 1, 11, -6, -5, +-3, 3, 1, 0, -4, -6, -3, 7, +5, -11, -7, 7, 8, -9, -6, 7, +0, -2, 2, 1, -2, 3, 1, -4, +5, 6, -4, -5, 3, 6, 0, -2, +-6, 1, 6, 2, -11, -3, 1, 5, +-3, -7, -8, 7, -2, -6, -2, 1, +-11, 1, 3, -4, -6, 3, -3, -5, +2, 5, -7, -6, 4, 3, -6, 1, +-2, 0, -1, 5, -2, -4, -5, 5, +1, -2, -10, 3, 0, -1, -9, 2, +-10, 3, -4, -4, -10, 3, -9, -6, +-4, 2, -11, -5, -9, 1, -4, -1, +-15, -3, 2, 2, -11, -6, -5, 7, +-6, -3, -8, 5, -7, -1, -5, 4, +-11, -1, -6, 3, -7, -1, -16, 3, +-5, 1, -16, -3, -9, 2, -16, 0, +-15, 0, -13, -2, -12, -1, -16, -4, +-7, -1, -18, -3, -13, 3, -9, -5, +-19, 5, -9, -1, -16, 4, -12, -1, +-11, 2, -14, 2, -15, -1, -10, 4, +-23, 0, -12, 4, -20, -2, -17, 0, +-15, -3, -20, -2, -17, -5, -17, -2, +-22, -2, -19, -1, -15, -5, -24, 0, +-15, 0, -22, -1, -18, 1, -19, 0, +-23, 5, -20, 1, -19, 5, -25, 1, +-19, 4, -22, -2, -23, 1, -18, -3, +-29, 2, -21, -1, -25, -3, -25, -1, +-24, -4, -24, -2, -26, -3, -21, -3, +-27, -1, -27, 1, -26, 3, -29, -1, +-23, 4, -24, -5, -26, 3, -26, 1, +-26, -1, -30, 5, -23, -5, -34, 7, +-27, -3, -31, 4, -31, -4, -28, 3, +-31, -5, -27, -1, -30, -2, -33, 2, +-30, -2, -29, -1, -31, -3, -29, 3, +-35, 0, -29, 2, -32, 1, -32, 1, +-31, 2, -32, -1, -31, 2, -31, -4, +-33, 7, -34, -8, -28, 5, -38, -7, +-30, 6, -37, -5, -33, 3, -32, -4, +-35, 1, -33, -1, -32, -2, -36, 3, +-35, -1, -34, 4, -36, -2, -34, 5, +-37, -1, -34, 2, -31, -4, -35, 1, +-36, -1, -35, 2, -36, -5, -33, 2, +-38, -4, -37, 5, -35, -4, -36, 1, +-34, -3, -39, 4, -36, 0, -35, -2, +-36, 4, -38, -4, -35, 7, -41, -1, +-35, 5, -37, -3, -38, 4, -36, -1, +-36, 0, -36, 0, -34, -3, -34, -1, +-35, -3, -34, 0, -37, -2, -33, -1, +-38, 1, -36, 1, -37, 1, -36, 2, +-38, 2, -37, 5, -36, -3, -32, 2, +-34, -5, -36, 5, -34, -4, -35, 2, +-33, -3, -37, 3, -32, -2, -33, -4, +-34, 3, -33, -7, -33, 5, -36, -3, +-33, 4, -33, -4, -34, 4, -33, -1, +-34, 3, -32, 0, -32, 0, -30, -2, +-35, 4, -30, -2, -34, 2, -32, 0, +-33, 2, -30, -3, -30, -1, -31, -1, +-32, 0, -31, 0, -29, -3, -29, 0, +-27, -5, -30, 3, -29, -2, -31, 4, +-27, -2, -29, 2, -25, -3, -28, 2, +-28, 0, -28, 2, -30, 2, -27, 0, +-27, -1, -26, 0, -26, -2, -25, -1, +-29, 1, -26, 0, -24, -3, -25, 0, +-25, 0, -27, 1, -23, 1, -21, -5, +-22, 3, -24, -2, -22, 5, -25, -3, +-20, 5, -25, -4, -18, 4, -25, -3, +-22, 6, -22, -5, -19, 3, -22, -5, +-21, 4, -22, -3, -21, 2, -17, -3, +-17, -4, -19, 3, -19, -2, -18, 3, +-18, -3, -17, 5, -20, -2, -14, 3, +-19, -2, -14, 4, -16, -4, -17, 5, +-17, -3, -13, 2, -18, -2, -11, -1, +-17, -3, -11, -1, -16, -2, -10, -3, +-14, -2, -11, 0, -17, -1, -6, -1, +-14, -4, -9, 5, -19, -1, -5, 3, +-13, -7, -6, 8, -15, -7, -4, 7, +-16, -6, -7, 8, -16, -4, -7, 5, +-12, -5, -5, 1, -12, -2, -5, -1, +-10, -2, -6, -2, -8, 0, -7, -2, +-11, 5, -9, 0, -7, 2, -6, -3, +-5, 3, -7, -4, 0, 1, -11, -1, +-2, 3, -13, 2, -5, 6, -9, -3, +1, 0, -10, -2, -1, 3, -12, -1, +3, -1, -11, -2, 2, 0, -10, -4, +4, 1, -9, -5, 6, 2, -9, -5, +1, 8, -11, -3, 4, 4, -9, -4, +6, 2, -9, -3, 3, 4, -6, -5, +3, 2, -6, -4, 2, 2, -7, -3, +3, 2, -8, -2, 3, 0, -5, -3, +-3, 5, -7, 1, -1, 0, -3, 0, +1, -2, -2, 1, 1, -4, -3, 4, +-2, -2, 2, 1, -4, -1, -1, 5, +-6, 0, 5, -3, -6, 0, 2, 1, +-3, -4, 5, -2, -6, -2, 1, 2, +-6, -1, 1, 2, -5, -1, 1, 2, +-7, 1, 5, -2, -7, 2, 4, -2, +-5, 1, 1, 0, -4, 0, 1, 0, +-4, -1, 3, -1, -4, -3, 3, -1, +-4, -3, 0, 2, -3, -4, 1, 1, +-5, -3, 4, -2, -6, 0, 2, -1, +-2, -4, 3, -2, -3, -2, 2, 0, +-1, -4, 2, 0, -1, -4, 3, -2, +1, -4, 0, -1, 2, -5, 1, -3, +2, -4, 0, -3, 3, -4, 3, -7, +2, -2, 2, -5, 3, -4, 3, -4, +6, -8, 2, -1, 2, -5, 2, 0, +5, -8, 6, -4, 6, -9, 3, -1, +6, -8, 5, -3, 6, -6, 8, -8, +10, -8, 5, -6, 8, -6, 5, -6, +9, -6, 10, -11, 11, -6, 9, -11, +14, -7, 8, -9, 12, -4, 10, -11, +16, -8, 10, -9, 17, -8, 11, -8, +16, -8, 16, -12, 18, -10, 14, -8, +19, -12, 19, -11, 22, -14, 20, -11, +19, -10, 23, -14, 19, -8, 23, -14, +24, -11, 25, -15, 25, -10, 26, -15, +28, -11, 27, -15, 31, -14, 30, -15, +30, -13, 32, -16, 32, -13, 31, -13, +36, -16, 38, -19, 37, -16, 37, -16, +37, -16, 37, -14, 35, -13, 39, -14, +39, -16, 40, -13, 41, -18, 50, -20, +45, -20, 46, -14, 45, -18, 49, -16, +46, -18, 54, -20, 51, -19, 54, -18, +51, -17, 55, -19, 51, -14, 53, -16, +54, -17, 60, -23, 58, -19, 61, -22, +60, -18, 59, -19, 62, -18, 62, -21, +65, -19, 65, -23, 66, -19, 66, -21, +67, -18, 69, -22, 70, -20, 70, -21, +69, -19, 71, -19, 75, -24, 75, -21, +75, -24, 76, -21, 78, -26, 79, -22, +76, -23, 80, -23, 79, -24, 80, -22, +81, -24, 83, -25, 84, -24, 83, -23, +84, -23, 82, -22, 87, -24, 85, -24, +88, -23, 86, -25, 88, -22, 87, -24, +88, -22, 89, -25, 89, -23, 88, -24, +91, -25, 87, -21, 88, -23, 89, -22, +92, -28, 89, -19, 88, -25, 93, -24, +91, -26, 92, -23, 90, -23, 90, -23, +92, -23, 93, -26, 95, -25, 92, -25, +94, -23, 90, -24, 93, -23, 93, -26, +92, -22, 95, -28, 93, -24, 89, -23, +92, -25, 91, -24, 90, -24, 91, -24, +88, -23, 92, -25, 89, -24, 87, -20, +89, -25, 90, -23, 89, -26, 88, -20, +85, -23, 89, -22, 85, -23, 88, -22, +85, -23, 85, -22, 85, -24, 82, -20, +83, -23, 83, -21, 80, -21, 84, -25, +79, -19, 82, -23, 79, -20, 79, -21, +79, -21, 77, -21, 77, -21, 75, -20, +76, -20, 74, -20, 75, -20, 75, -22, +74, -21, 75, -22, 71, -19, 72, -20, +70, -19, 71, -20, 70, -20, 68, -17, +68, -19, 67, -18, 68, -21, 67, -20, +63, -18, 61, -17, 62, -18, 63, -20, +61, -17, 59, -16, 59, -15, 60, -17, +62, -17, 61, -18, 61, -16, 59, -16, +60, -17, 57, -16, 57, -18, 54, -16, +52, -16, 49, -13, 51, -19, 50, -15, +49, -18, 46, -10, 48, -17, 48, -9, +50, -17, 52, -11, 51, -17, 51, -10, +48, -14, 51, -14, 46, -15, 47, -15, +42, -14, 39, -12, 35, -11, 37, -13, +34, -9, 37, -12, 38, -9, 43, -15, +45, -11, 43, -11, 44, -8, 45, -12, +41, -7, 41, -12, 39, -11, 33, -9, +31, -10, 28, -8, 24, -8, 25, -8, +28, -12, 27, -5, 31, -10, 35, -7, +35, -7, 41, -9, 39, -5, 44, -13, +35, -1, 35, -11, 29, -1, 25, -12, +22, -1, 18, -13, 16, 0, 14, -11, +16, 1, 19, -10, 24, -1, 28, -10, +31, 0, 36, -9, 35, -1, 36, -6, +31, 0, 29, -6, 25, -4, 17, -4, +13, -5, 9, -5, 7, -5, 4, -2, +10, -7, 12, -2, 18, -4, 26, -6, +27, -1, 31, -4, 33, -1, 33, -6, +28, 0, 22, -5, 16, 1, 8, -4, +4, -1, -4, -2, -5, -1, -3, -3, +-2, -1, 3, 1, 11, -4, 16, 2, +25, -6, 26, 3, 31, -8, 25, 4, +24, -6, 17, 1, 7, -3, -3, 6, +-5, -6, -8, -1, -13, -5, -13, 2, +-8, -5, -5, 3, 4, -3, 11, 0, +17, -2, 21, 0, 22, -1, 20, 0, +14, 0, 8, 0, -2, -1, -8, 1, +-15, -4, -20, 4, -21, -6, -22, 6, +-14, -9, -10, 7, -2, -9, 6, 6, +13, -10, 13, 8, 13, -6, 12, 7, +6, -7, 1, 4, -9, -5, -16, 2, +-25, 0, -28, 1, -29, -1, -26, -2, +-22, 2, -15, -5, -11, 8, -1, -6, +7, 4, 8, -6, 8, 6, 4, -5, +-2, 7, -9, -4, -16, 4, -23, -3, +-31, 2, -31, -4, -36, 3, -33, 0, +-25, -1, -23, 4, -12, -2, -5, 2, +-3, -2, 4, 2, 1, -3, -3, 5, +-6, -3, -18, 4, -23, 4, -27, -5, +-35, 4, -36, -3, -35, 1, -38, -5, +-25, 11, -32, -13, -16, 22, -15, -16, +-4, 10, -7, -4, -3, 6, -15, -5, +-12, 15, -25, -12, -23, 9, -38, 1, +-40, -1, -40, 3, -44, 6, -36, -9, +-34, 9, -31, 0, -27, 0, -17, 8, +-17, -4, -11, -1, -20, 13, -20, -5, +-25, 8, -32, 7, -35, -3, -39, 1, +-46, 13, -45, -17, -49, 24, -42, -13, +-39, 7, -39, 3, -34, 10, -29, -9, +-32, 26, -24, -16, -25, 9, -33, 7, +-35, -2, -35, 3, -50, 9, -44, -4, +-55, 4, -54, 16, -55, -18, -47, 26, +-57, -16, -33, 16, -59, -4, -26, 10, +-46, -5, -42, 13, -32, 2, -56, -3, +-38, 19, -55, -10, -59, 13, -57, 3, +-64, 9, -70, -8, -56, 34, -73, -31, +-54, 39, -66, -14, -54, 10, -59, 9, +-51, 3, -59, -1, -56, 17, -60, 0, +-61, -5, -64, 29, -67, -32, -73, 40, +-71, -22, -78, 25, -75, -7, -79, 25, +-72, -16, -76, 30, -69, -11, -71, 10, +-66, 14, -79, -16, -59, 41, -90, -48, +-54, 76, -106, -83, -48, 109, -116, -116, +-43, 136, -133, -130, -31, 139, -141, -117, +-29, 103, -139, -49, -31, 6, -125, 59, +-47, -109, -108, 178, -75, -217, -80, 260, +-101, -247, -79, 209, -74, -103, -151, -2, +17, 115, -231, -153, 39, 143, -180, -46, +-75, -42, -46, 121, -175, -102, -18, 37, +-133, 95, -97, -179, -62, 225, -123, -166, +-83, 74, -89, 45, -96, -88, -130, 83, +-12, 23, -225, -135, 58, 252, -240, -290, +22, 280, -182, -183, -26, 79, -166, 53, +-18, -126, -167, 176, -43, -153, -102, 118, +-126, -53, -31, 24, -159, 4, -46, 21, +-102, -33, -122, 58, -24, -30, -189, -15, +33, 108, -239, -174, 59, 243, -229, -236, +15, 205, -147, -123, -67, 56, -88, 9, +-90, -8, -88, -3, -81, 46, -60, -50, +-165, 45, 80, 26, -322, -112, 227, 234, +-437, -327, 295, 424, -461, -461, 281, 469, +-394, -398, 139, 292, -158, -117, -163, -50, +165, 211, -414, -272, 274, 266, -334, -146, +50, 9, -41, 127, -202, -159, 82, 123, +-164, 3, -76, -112, 18, 195, -187, -173, +16, 99, -82, 22, -118, -86, 6, 94, +-77, 3, -158, -129, 178, 277, -401, -354, +334, 374, -413, -290, 204, 169, -182, -2, +-70, -137, 85, 255, -307, -304, 277, 333, +-458, -316, 392, 321, -517, -324, 399, 372, +-459, -402, 312, 427, -346, -390, 218, 318, +-274, -199, 170, 107, -241, -35, 135, 38, +-193, -71, 62, 138, -99, -173, -58, 191, +43, -159, -199, 127, 170, -97, -267, 116, +170, -165, -184, 276, 40, -386, -39, 514, +-55, -598, -9, 648, -26, -630, -74, 585, +20, -498, -87, 435, 4, -382, -70, 368, +9, -345, -100, 315, 52, -230, -107, 118, +22, 26, -31, -142, -56, 240, 24, -292, +-56, 338, -12, -385, -19, 459, -24, -532, +-60, 600, 37, -602, -89, 528, -15, -366, +49, 161, -196, 58, 223, -239, -306, 382, +261, -460, -272, 497, 222, -495, -266, 472, +258, -398, -313, 278, 273, -91, -269, -132, +153, 376, -110, -572, -13, 693, 26, -685, +-113, 565, 126, -353, -235, 113, 293, 100, +-401, -234, 411, 260, -383, -181, 224, 10, +-45, 225, -206, -458, 369, 642, -508, -698, +470, 593, -375, -290, 104, -177, 184, 749, +-583, -1310, 917, 1753, -1239, -1979, 1389, 1944, +-1421, -1652, 1252, 1163, -986, -580, 627, 29, +-324, 392, 82, -604, 9, 588, -24, -391, +-48, 110, 59, 122, -22, -181, -180, -8, +474, 431, -888, -1005, 1290, 1575, -1661, -1969, +1871, 2075, -1908, -1857, 1733, 1374, -1393, -764, +925, 196, -418, 201, -69, -375, 454, 368, +-746, -277, 896, 238, -965, -321, 927, 545, +-836, -837, 673, 1071, -471, -1113, 230, 875, +34, -369, -294, -301, 548, 959, -746, -1420, +893, 1556, -955, -1323, 927, 829, -785, -244, +543, -236, -208, 491, -178, -502, 582, 370, +-947, -238, 1218, 254, -1317, -445, 1225, 732, +-885, -926, 360, 849, 320, -385, -976, -400, +1522, 1290, -1751, -1981, 1658, 2180, -1183, -1757, +506, 783, 249, 448, -807, -1545, 1077, 2122, +-921, -1984, 469, 1167, 195, 33, -775, -1188, +1147, 1894, -1102, -1894, 724, 1197, -16, -68, +-719, -1102, 1380, 1902, -1697, -2075, 1691, 1598, +-1302, -658, 748, -410, -92, 1262, -410, -1662, +742, 1565, -771, -1083, 632, 445, -307, 123, +13, -449, 268, 495, -337, -325, 297, 70, +-47, 139, -206, -217, 482, 163, -558, -25, +501, -94, -206, 110, -109, 25, 426, -293, +-477, 612, 342, -885, 84, 997, -537, -875, +973, 526, -1091, -36, 973, -461, -509, 802, +-6, -891, 546, 706, -830, -321, 933, -96, +-755, 393, 534, -461, -233, 294, 70, -2, +92, -252, -143, 305, 292, -90, -407, -362, +630, 881, -737, -1262, 796, 1325, -600, -983, +309, 291, 170, 551, -561, -1293, 902, 1696, +-947, -1649, 849, 1192, -520, -517, 242, -111, +11, 461, 3, -440, -110, 110, 376, 314, +-503, -578, 522, 503, -241, -58, -137, -589, +619, 1170, -881, -1424, 962, 1224, -687, -636, +323, -123, 149, 734, -399, -974, 522, 764, +-354, -254, 174, -315, 65, 663, -94, -648, +75, 279, 105, 255, -173, -713, 213, 886, +-36, -695, -152, 224, 425, 334, -521, -755, +549, 880, -337, -674, 117, 222, 205, 293, +-363, -695, 480, 854, -380, -737, 269, 424, +-30, -58, -94, -218, 232, 313, -180, -237, +148, 57, 15, 94, -53, -144, 131, 48, +-45, 121, 9, -256, 115, 260, -99, -93, +120, -191, -6, 471, -4, -619, 62, 548, +44, -279, -98, -84, 239, 398, -202, -552, +158, 492, 86, -273, -273, 1, 526, 205, +-565, -279, 570, 210, -341, -70, 157, -63, +119, 110, -189, -67, 239, -47, -48, 141, +-102, -161, 343, 70, -368, 103, 342, -300, +-39, 424, -256, -413, 652, 247, -798, 23, +833, -309, -521, 499, 163, -514, 327, 325, +-556, 2, 650, -372, -356, 652, 1, -754, +505, 630, -755, -327, 876, -66, -609, 421, +271, -648, 241, 688, -546, -557, 787, 306, +-690, -35, 552, -196, -202, 316, -13, -326, +271, 240, -296, -111, 344, -16, -204, 91, +175, -103, -55, 59, 110, 1, -75, -52, +166, 49, -95, 9, 62, -105, 164, 200, +-297, -263, 512, 258, -492, -198, 451, 94, +-157, -5, -59, -51, 348, 40, -379, 26, +360, -121, -86, 207, -109, -263, 365, 267, +-370, -228, 339, 165, -89, -103, -53, 46, +246, -19, -195, 0, 144, 14, 90, -47, +-196, 112, 348, -226, -260, 355, 185, -481, +69, 549, -198, -540, 375, 435, -336, -268, +310, 83, -104, 46, 12, -106, 140, 80, +-95, -25, 90, -11, 62, -34, -75, 160, +137, -344, -13, 512, -57, -579, 222, 512, +-234, -296, 265, -2, -118, 286, 47, -468, +98, 488, -71, -355, 60, 131, 109, 71, +-182, -165, 298, 95, -215, 109, 130, -371, +129, 563, -295, -597, 502, 429, -495, -112, +448, -249, -198, 516, -11, -582, 281, 401, +-343, -43, 340, -383, -94, 712, -149, -844, +476, 716, -603, -387, 645, -40, -415, 417, +159, -641, 203, 649, -387, -467, 492, 180, +-346, 103, 177, -293, 73, 340, -154, -249, +172, 68, 26, 119, -216, -253, 464, 290, +-529, -243, 529, 139, -308, -39, 83, -37, +237, 71, -435, -83, 616, 104, -621, -151, +619, 203, -472, -245, 355, 229, -158, -133, +35, -26, 132, 186, -188, -281, 242, 265, +-170, -122, 125, -110, 9, 342, -64, -489, +147, 494, -122, -350, 117, 111, -29, 142, +18, -342, 45, 411, -17, -358, 22, 216, +53, -54, -79, -74, 162, 128, -182, -107, +236, 44, -202, 22, 184, -57, -59, 44, +-40, -6, 206, -29, -289, 33, 373, -3, +-325, -43, 249, 71, -62, -45, -89, -54, +287, 179, -379, -297, 447, 348, -381, -303, +305, 155, -134, 49, 4, -247, 170, 367, +-253, -389, 345, 311, -329, -191, 326, 67, +-236, 12, 166, -38, -26, 26, -77, -19, +224, 42, -301, -105, 378, 181, -346, -227, +291, 201, -129, -94, -8, -76, 177, 246, +-240, -351, 266, 343, -163, -214, 53, 6, +111, 206, -186, -338, 219, 342, -119, -204, +-1, -35, 189, 292, -310, -473, 402, 518, +-357, -415, 275, 192, -89, 63, -63, -269, +221, 368, -267, -339, 279, 213, -184, -56, +110, -66, -8, 98, 3, -33, -20, -104, +128, 254, -200, -364, 283, 386, -254, -313, +198, 164, -41, 5, -71, -158, 182, 263, +-171, -315, 133, 319, -3, -311, -72, 297, +142, -291, -98, 283, 47, -267, 68, 218, +-111, -138, 134, 27, -44, 91, -47, -201, +184, 275, -236, -297, 252, 263, -143, -179, +15, 65, 173, 55, -284, -156, 369, 213, +-321, -230, 241, 209, -77, -183, -37, 167, +139, -177, -135, 216, 110, -261, -20, 286, +-15, -262, 34, 188, 49, -70, -136, -61, +256, 176, -276, -248, 248, 254, -90, -202, +-82, 114, 283, -15, -378, -63, 397, 106, +-270, -104, 100, 72, 116, -31, -243, 2, +307, 0, -233, 29, 117, -76, 55, 120, +-154, -139, 197, 128, -118, -78, 0, 11, +174, 55, -289, -105, 370, 129, -334, -135, +260, 132, -111, -146, -4, 174, 121, -211, +-162, 239, 183, -232, -141, 187, 117, -100, +-71, -2, 66, 88, -32, -128, 11, 117, +58, -57, -118, -27, 217, 107, -274, -159, +317, 169, -265, -151, 186, 104, -45, -48, +-77, -15, 210, 78, -276, -142, 307, 215, +-268, -276, 229, 314, -151, -319, 94, 278, +-13, -199, -19, 86, 48, 32, -32, -130, +17, 199, 27, -227, -52, 222, 85, -201, +-68, 177, 35, -153, 28, 141, -65, -127, +92, 120, -71, -103, 33, 80, 43, -43, +-94, 0, 128, 40, -104, -64, 66, 72, +1, -57, -47, 29, 82, 5, -48, -35, +-21, 48, 128, -42, -201, 17, 246, 15, +-223, -33, 148, 36, -5, -16, -138, -26, +264, 73, -301, -122, 290, 147, -209, -146, +106, 117, 15, -64, -86, -12, 119, 87, +-92, -156, 60, 207, -24, -227, 7, 217, +7, -181, 12, 118, -29, -45, 34, -22, +5, 69, -54, -84, 105, 64, -126, -13, +126, -48, -82, 98, 4, -117, 89, 99, +-156, -38, 178, -40, -147, 104, 104, -134, +-54, 120, 19, -57, -18, -25, 62, 103, +-114, -152, 139, 157, -101, -126, 24, 75, +76, -33, -156, 9, 190, -21, -140, 68, +-5, -124, 183, 179, -322, -215, 379, 211, +-330, -170, 187, 92, 21, 6, -229, -104, +360, 180, -380, -213, 304, 199, -184, -148, +63, 82, 20, -32, -39, 24, -26, -55, +121, 116, -196, -169, 204, 171, -148, -102, +46, -44, 87, 220, -209, -389, 275, 484, +-263, -472, 189, 347, -109, -140, 39, -79, +-15, 261, 26, -352, -93, 347, 172, -262, +-224, 139, 203, -28, -124, -46, 3, 73, +117, -70, -226, 63, 264, -68, -220, 93, +93, -121, 40, 135, -147, -115, 177, 66, +-155, 11, 50, -80, 72, 126, -181, -131, +199, 95, -141, -44, 22, -5, 93, 30, +-197, -33, 226, 28, -194, -33, 84, 64, +16, -124, -87, 191, 83, -245, -51, 253, +-32, -200, 107, 91, -176, 40, 158, -155, +-117, 228, 15, -221, 45, 150, -108, -43, +112, -61, -103, 122, 29, -123, 25, 63, +-93, 40, 88, -134, -100, 192, 65, -188, +-57, 132, -4, -33, 14, -58, -39, 101, +21, -84, -46, 2, 36, 102, -70, -179, +56, 201, -97, -149, 86, 45, -89, 74, +1, -159, 48, 201, -146, -179, 176, 106, +-229, -4, 185, -102, -142, 177, 20, -200, +19, 165, -70, -73, 2, -42, 52, 148, +-205, -196, 280, 181, -356, -92, 269, -45, +-159, 199, -65, -326, 206, 407, -360, -411, +350, 333, -298, -191, 104, 11, 30, 154, +-194, -260, 198, 292, -201, -253, 64, 174, +17, -92, -145, 37, 107, -8, -71, 9, +-97, -20, 177, 34, -292, -44, 247, 39, +-200, -21, 7, -10, 88, 56, -222, -86, +179, 94, -160, -69, 9, 21, 48, 22, +-157, -44, 97, 40, -74, -24, -72, 30, +96, -93, -151, 216, 39, -393, 31, 580, +-211, -733, 247, 791, -301, -720, 175, 497, +-115, -156, -48, -224, 54, 545, -111, -708, +-8, 669, 49, -435, -209, 94, 226, 238, +-303, -454, 209, 488, -173, -355, -12, 121, +80, 102, -210, -230, 143, 220, -135, -97, +-15, -53, 8, 139, -63, -102, -73, -26, +100, 158, -200, -193, 84, 67, -4, 177, +-224, -429, 259, 559, -310, -472, 114, 183, +15, 202, -257, -530, 271, 681, -288, -607, +65, 346, 71, 10, -316, -356, 343, 614, +-408, -725, 238, 692, -137, -538, -124, 320, +237, -115, -427, -20, 405, 46, -440, 44, +248, -188, -131, 331, -152, -426, 302, 445, +-553, -427, 616, 408, -770, -420, 735, 480, +-798, -570, 689, 635, -667, -639, 452, 545, +-332, -350, 39, 87, 116, 191, -392, -435, +491, 612, -701, -724, 751, 780, -927, -793, +916, 759, -968, -659, 759, 485, -597, -233, +229, -37, -20, 263, -244, -387, 256, 387, +-321, -295, 212, 172, -277, -60, 234, -8, +-339, 60, 250, -128, -219, 245, -43, -380, +186, 481, -407, -486, 347, 365, -283, -135, +-8, -134, 137, 340, -285, -412, 132, 322, +10, -126, -311, -82, 373, 182, -389, -85, +75, -226, 225, 693, -663, -1216, 864, 1661, +-1051, -1922, 951, 1950, -893, -1747, 661, 1380, +-560, -944, 329, 540, -233, -230, 15, 36, +44, 82, -170, -197, 105, 369, -121, -619, +0, 911, -42, -1155, 2, 1271, -113, -1218, +91, 1031, -151, -790, 41, 592, -31, -477, +-98, 426, 89, -363, -177, 196, 136, 109, +-191, -534, 107, 979, -104, -1330, -48, 1494, +86, -1425, -200, 1151, 129, -735, -106, 270, +-44, 169, 45, -537, -72, 814, -83, -1007, +145, 1139, -255, -1206, 142, 1197, -1, -1081, +-315, 821, 524, -416, -752, -81, 754, 568, +-732, -895, 518, 951, -343, -681, 44, 152, +184, 481, -515, -1017, 749, 1283, -1022, -1190, +1088, 762, -1054, -112, 725, -614, -297, 1268, +-306, -1742, 786, 1959, -1168, -1875, 1195, 1488, +-1026, -823, 570, -11, -110, 856, -386, -1506, +664, 1808, -840, -1689, 798, 1227, -733, -638, +594, 181, -601, -66, 666, 391, -956, -1055, +1314, 1826, -1790, -2405, 2127, 2556, -2307, -2192, +2109, 1410, -1638, -447, 841, -381, 3, 845, +-829, -859, 1383, 545, -1723, -145, 1780, -62, +-1746, -104, 1605, 635, -1504, -1326, 1326, 1864, +-1114, -1956, 724, 1470, -257, -495, -310, -670, +775, 1649, -1120, -2139, 1225, 2024, -1187, -1456, +1003, 755, -841, -262, 666, 182, -520, -475, +252, 872, 159, -1019, -788, 643, 1478, 269, +-2095, -1443, 2341, 2409, -2096, -2709, 1268, 2103, +-64, -704, -1253, -1057, 2273, 2576, -2760, -3337, +2553, 3096, -1794, -1982, 708, 420, 325, 1051, +-1073, -1981, 1356, 2166, -1228, -1675, 770, 785, +-185, 172, -409, -914, 856, 1293, -1096, -1278, +1026, 920, -633, -302, -96, -460, 1008, 1227, +-1905, -1817, 2483, 2039, -2536, -1776, 1981, 1025, +-985, 35, -157, -1087, 1027, 1800, -1366, -1942, +1092, 1501, -402, -698, -372, -108, 856, 585, +-855, -574, 374, 156, 338, 388, -963, -724, +1195, 636, -939, -136, 292, -537, 468, 1027, +-1030, -1044, 1156, 510, -817, 414, 143, -1349, +578, 1894, -1078, -1781, 1181, 1008, -892, 142, +361, -1231, 180, 1826, -537, -1709, 625, 966, +-524, 46, 392, -845, -409, 1065, 627, -617, +-948, -260, 1150, 1093, -1020, -1404, 439, 961, +473, 122, -1428, -1384, 2041, 2261, -2042, -2337, +1402, 1553, -378, -226, -621, -1082, 1197, 1856, +-1172, -1858, 666, 1222, -23, -363, -372, -245, +308, 312, 159, 133, -731, -793, 1068, 1269, +-954, -1274, 442, 773, 219, 12, -668, -757, +722, 1162, -397, -1114, -43, 709, 317, -183, +-212, -227, -203, 373, 722, -276, -1002, 64, +865, 91, -281, -82, -483, -112, 1142, 393, +-1386, -628, 1173, 691, -586, -535, -65, 193, +568, 201, -706, -520, 549, 654, -199, -568, +-101, 324, 254, -26, -185, -192, 31, 253, +152, -157, -186, -27, 108, 194, 88, -233, +-232, 110, 307, 143, -209, -422, 60, 603, +130, -591, -196, 380, 179, -32, -20, -323, +-95, 550, 175, -584, -59, 421, -116, -151, +349, -109, -408, 275, 317, -330, 41, 313, +-427, -309, 784, 370, -815, -496, 593, 610, +-81, -617, -374, 444, 678, -108, -546, -292, +151, 601, 453, -675, -846, 454, 974, 2, +-657, -520, 199, 911, 291, -1015, -430, 804, +304, -372, 149, -104, -515, 435, 744, -528, +-548, 398, 187, -173, 332, -8, -615, 60, +723, 11, -497, -89, 269, 46, 15, 163, +-64, -471, 93, 713, 24, -712, 5, 386, +23, 181, 52, -761, 55, 1097, -151, -1010, +404, 505, -450, 213, 404, -850, 4, 1147, +-432, -1012, 926, 539, -1045, 35, 939, -453, +-433, 569, -28, -395, 468, 78, -484, 181, +351, -247, 33, 103, -198, 160, 260, -383, +44, 455, -318, -326, 631, 61, -545, 218, +327, -416, 192, 480, -531, -432, 809, 338, +-668, -269, 463, 261, -45, -309, -128, 357, +279, -365, -123, 301, 57, -170, 117, 0, +-19, 162, -28, -278, 269, 322, -304, -287, +392, 182, -210, -42, 130, -89, 104, 157, +-115, -122, 208, -23, -78, 246, 95, -482, +42, 652, 5, -694, 113, 598, -83, -402, +262, 165, -280, 30, 432, -138, -327, 155, +291, -118, -1, 81, -127, -92, 349, 185, +-275, -343, 257, 532, -19, -683, 2, 739, +75, -649, 131, 417, -199, -80, 369, -271, +-215, 541, 84, -638, 277, 542, -377, -289, +452, -15, -123, 245, -151, -310, 560, 183, +-572, 71, 466, -324, 43, 456, -419, -379, +800, 107, -683, 260, 425, -570, 187, 682, +-564, -537, 873, 169, -670, 288, 377, -660, +193, 805, -482, -681, 722, 349, -546, 52, +398, -366, -46, 490, -45, -422, 188, 248, +-71, -70, 104, -23, 10, 20, 82, 37, +-4, -71, 73, 34, 66, 65, -36, -162, +126, 195, 41, -116, -108, -55, 358, 249, +-357, -380, 374, 393, -68, -273, -154, 65, +524, 154, -604, -305, 680, 346, -445, -271, +308, 124, -32, 39, 3, -150, 100, 181, +-1, -123, 89, 7, -70, 118, 256, -200, +-275, 217, 381, -163, -222, 69, 145, 24, +100, -85, -110, 109, 147, -112, 82, 137, +-198, -207, 411, 320, -338, -434, 256, 493, +93, -437, -317, 253, 620, 24, -625, -313, +619, 501, -333, -508, 123, 316, 226, 15, +-361, -360, 536, 576, -454, -571, 412, 350, +-157, -7, 26, -324, 230, 505, -299, -481, +439, 295, -385, -54, 412, -117, -276, 162, +251, -93, -80, -8, 19, 59, 176, -6, +-237, -124, 386, 250, -342, -283, 346, 163, +-148, 75, 25, -343, 222, 524, -301, -542, +422, 377, -327, -101, 263, -177, -31, 354, +-99, -378, 309, 270, -333, -105, 372, -36, +-207, 97, 91, -89, 148, 43, -235, -16, +337, 27, -223, -57, 125, 53, 105, 24, +-201, -167, 305, 328, -190, -442, 90, 432, +132, -290, -216, 64, 288, 168, -164, -306, +66, 301, 121, -164, -155, -36, 187, 204, +-56, -258, -27, 174, 172, 20, -179, -244, +203, 409, -92, -457, 45, 371, 81, -197, +-105, 4, 170, 145, -123, -200, 115, 171, +-5, -100, -25, 34, 89, -14, -9, 42, +-71, -100, 269, 142, -372, -137, 444, 74, +-303, 27, 111, -141, 200, 220, -387, -237, +483, 186, -323, -84, 76, -39, 276, 142, +-487, -194, 593, 177, -455, -109, 257, 22, +10, 40, -132, -36, 170, -47, -37, 192, +-90, -339, 221, 428, -187, -410, 89, 274, +136, -52, -316, -181, 473, 366, -473, -452, +422, 435, -253, -347, 116, 239, 42, -142, +-99, 74, 146, -24, -94, -25, 63, 77, +34, -136, -68, 166, 124, -153, -84, 76, +56, 31, 46, -139, -97, 202, 164, -204, +-140, 157, 108, -90, 1, 52, -59, -77, +138, 151, -125, -240, 121, 292, -48, -280, +26, 197, 26, -82, -12, -22, 34, 75, +-4, -83, 36, 47, -27, -12, 55, -4, +-19, 3, -8, 6, 105, -1, -174, -16, +273, 38, -289, -46, 295, 28, -210, 19, +137, -77, -14, 135, -56, -180, 152, 213, +-179, -246, 232, 273, -213, -293, 217, 281, +-145, -231, 89, 142, 16, -21, -71, -99, +137, 206, -127, -282, 120, 337, -59, -358, +34, 353, 10, -294, 2, 189, 21, -45, +-1, -108, 32, 229, -36, -272, 72, 252, +-68, -167, 93, 77, -75, -7, 91, -11, +-67, 4, 71, 13, -19, 6, -25, -51, +119, 128, -180, -172, 224, 199, -181, -155, +100, 98, 38, -17, -132, -20, 183, 44, +-109, -38, 0, 42, 150, -41, -224, 68, +233, -61, -134, 41, 23, 40, 90, -121, +-104, 193, 79, -177, 6, 84, -32, 98, +11, -268, 100, 399, -220, -385, 314, 281, +-300, -79, 211, -94, -50, 228, -89, -227, +166, 180, -138, -74, 60, 18, 38, 21, +-78, 17, 54, -42, 40, 86, -129, -72, +169, 69, -125, -3, 5, -45, 154, 141, +-289, -206, 351, 301, -321, -323, 215, 317, +-74, -204, -62, 82, 141, 91, -163, -178, +115, 227, -53, -135, -25, 22, 65, 154, +-99, -238, 93, 275, -96, -158, 59, 6, +-26, 227, -75, -368, 175, 466, -311, -398, +367, 296, -377, -114, 251, 26, -102, 18, +-79, 88, 137, -210, -134, 403, -26, -484, +164, 536, -308, -443, 279, 353, -199, -193, +-16, 129, 144, -61, -256, 103, 176, -98, +-105, 136, -57, -50, 55, -32, -43, 215, +-129, -312, 188, 388, -236, -269, 24, 99, +197, 201, -549, -371, 666, 457, -675, -279, +339, 11, 11, 369, -467, -578, 626, 654, +-691, -432, 421, 138, -219, 239, -82, -409, +100, 451, -144, -230, -38, 9, 41, 229, +-124, -234, -39, 114, 90, 219, -309, -510, +312, 790, -446, -821, 355, 740, -423, -441, +286, 164, -323, 146, 134, -262, -118, 309, +-116, -155, 130, 20, -324, 184, 242, -226, +-327, 247, 127, -94, -113, -7, -156, 137, +192, -57, -449, -88, 427, 424, -590, -687, +429, 932, -464, -888, 206, 717, -207, -324, +-3, 2, -118, 274, 23, -249, -218, 109, +109, 221, -212, -431, -40, 569, 66, -406, +-402, 132, 455, 339, -778, -734, 784, 1109, +-1031, -1220, 886, 1193, -893, -867, 437, 464, +-156, 80, -458, -461, 663, 718, -955, -617, +675, 355, -494, 100, -65, -404, 221, 564, +-480, -350, 182, 4, -45, 483, -431, -753, +458, 854, -604, -604, 238, 278, -119, 136, +-261, -323, 134, 380, -117, -155, -383, -100, +589, 443, -1025, -619, 946, 760, -1004, -700, +600, 642, -473, -468, 28, 383, 39, -234, +-396, 183, 385, -38, -666, -67, 564, 322, +-717, -576, 491, 951, -576, -1229, 363, 1503, +-523, -1567, 408, 1557, -638, -1335, 518, 1129, +-661, -871, 430, 770, -487, -691, 219, 740, +-263, -691, -24, 606, 14, -281, -331, -130, +321, 698, -584, -1146, 451, 1521, -554, -1591, +282, 1512, -288, -1204, 7, 901, -81, -543, +-71, 295, -152, -2, 130, -240, -424, 587, +411, -888, -639, 1187, 533, -1254, -694, 1139, +591, -705, -824, 164, 811, 466, -1073, -880, +957, 1086, -948, -918, 467, 549, -92, 14, +-628, -506, 1029, 935, -1540, -1102, 1558, 1103, +-1592, -814, 1132, 376, -768, 306, 59, -1039, +396, 1791, -1002, -2262, 1163, 2365, -1307, -1867, +902, 907, -473, 417, -353, -1673, 940, 2604, +-1597, -2859, 1712, 2512, -1724, -1644, 1246, 705, +-897, 16, 429, -172, -452, -178, 570, 941, +-1130, -1700, 1531, 2187, -1987, -2106, 1917, 1545, +-1712, -617, 1023, -263, -406, 876, -398, -996, +887, 769, -1449, -364, 1707, 179, -2091, -357, +2194, 995, -2359, -1794, 2124, 2468, -1852, -2587, +1189, 2074, -651, -942, 8, -369, 242, 1496, +-447, -2014, 322, 1902, -381, -1284, 419, 605, +-835, -189, 1179, 310, -1604, -814, 1539, 1433, +-1190, -1681, 241, 1333, 754, -292, -1833, -1071, +2358, 2348, -2479, -3007, 1883, 2854, -1073, -1881, +-5, 486, 780, 939, -1405, -1920, 1526, 2303, +-1512, -2031, 1134, 1343, -767, -421, 164, -463, +340, 1194, -948, -1616, 1240, 1719, -1366, -1415, +968, 797, -387, 55, -444, -853, 936, 1385, +-1099, -1379, 545, 836, 344, 138, -1519, -1165, +2328, 1910, -2703, -2053, 2279, 1577, -1427, -631, +225, -403, 712, 1193, -1332, -1456, 1280, 1208, +-886, -589, 169, -74, 357, 535, -673, -607, +466, 366, -33, 44, -635, -333, 1051, 362, +-1224, -47, 876, -440, -321, 883, -395, -992, +806, 665, -923, 73, 549, -920, -46, 1559, +-510, -1641, 696, 1112, -614, -91, 199, -1010, +152, 1798, -386, -1945, 259, 1471, -38, -611, +-201, -168, 67, 531, 356, -300, -1062, -326, +1582, 1004, -1731, -1287, 1214, 993, -270, -172, +-866, -814, 1656, 1567, -1918, -1761, 1523, 1370, +-821, -575, 72, -251, 317, 853, -383, -1067, +180, 1005, -76, -820, 188, 712, -601, -728, +1048, 826, -1332, -859, 1196, 749, -734, -460, +91, 97, 362, 257, -493, -485, 243, 592, +131, -601, -397, 596, 288, -579, 152, 569, +-781, -513, 1272, 394, -1426, -197, 1123, -14, +-524, 217, -169, -358, 681, 449, -899, -497, +797, 534, -523, -541, 212, 508, 3, -400, +-102, 231, 120, -48, -123, -81, 160, 102, +-216, -18, 263, -111, -238, 171, 131, -90, +50, -150, -233, 454, 374, -680, -401, 670, +344, -394, -209, -99, 87, 608, -18, -932, +67, 914, -163, -574, 280, 28, -271, 467, +119, -741, 206, 678, -545, -359, 788, -74, +-708, 396, 329, -528, 302, 432, -881, -249, +1217, 72, -1060, -40, 539, 114, 200, -260, +-747, 324, 920, -276, -574, 79, -13, 136, +648, -309, -928, 319, 836, -211, -380, 9, +-76, 129, 402, -188, -332, 100, 87, 17, +255, -133, -358, 140, 258, -118, 120, 70, +-421, -147, 649, 305, -566, -550, 416, 666, +-192, -596, 185, 213, -198, 314, 344, -871, +-241, 1133, 33, -1053, 409, 560, -689, 65, +843, -652, -519, 880, 86, -764, 476, 297, +-650, 201, 532, -603, 67, 682, -603, -547, +1094, 211, -1039, 72, 730, -295, -77, 311, +-332, -296, 638, 202, -427, -216, 233, 216, +78, -297, 12, 290, -179, -298, 661, 201, +-806, -156, 869, 54, -390, -36, -101, -52, +762, 89, -943, -225, 1030, 283, -586, -373, +283, 322, 146, -276, -146, 123, 191, -47, +99, -57, -34, 47, 92, -102, 233, 106, +-329, -219, 559, 275, -301, -368, 177, 297, +314, -201, -417, -36, 576, 191, -236, -325, +72, 235, 412, -84, -398, -231, 516, 456, +-177, -677, 112, 685, 196, -649, -5, 433, +89, -264, 210, 10, -85, 114, 173, -261, +155, 252, -86, -276, 314, 193, -14, -232, +21, 260, 279, -453, -90, 599, 135, -776, +301, 719, -235, -559, 389, 145, 45, 228, +-214, -589, 706, 646, -538, -553, 524, 220, +126, 12, -379, -168, 819, -4, -532, 265, +383, -636, 344, 761, -508, -705, 819, 296, +-404, 151, 191, -633, 476, 800, -509, -780, +764, 444, -358, -115, 289, -240, 137, 343, +4, -381, 203, 230, 106, -160, 97, 50, +46, -80, 276, 36, -147, -53, 374, -70, +-13, 134, 57, -258, 316, 221, -158, -183, +281, -8, 119, 123, -39, -278, 324, 259, +-6, -235, -6, 50, 446, 84, -377, -294, +598, 363, -191, -426, 129, 294, 371, -153, +-404, -122, 728, 287, -506, -432, 643, 351, +-285, -215, 321, -71, 46, 243, -25, -388, +404, 304, -323, -196, 618, -8, -420, 52, +530, -46, -215, -152, 273, 296, 38, -443, +125, 379, 68, -271, 146, 44, -13, 50, +220, -90, -32, -72, 213, 208, 23, -356, +76, 277, 205, -113, -179, -210, 493, 420, +-389, -538, 555, 378, -247, -126, 160, -225, +289, 398, -374, -457, 689, 260, -510, -27, +525, -248, -140, 348, 37, -389, 307, 286, +-256, -248, 438, 201, -242, -265, 315, 267, +-111, -254, 172, 81, 49, 110, -2, -347, +267, 427, -249, -410, 464, 189, -355, 33, +409, -280, -103, 361, 8, -372, 357, 249, +-417, -173, 603, 77, -430, -85, 372, 62, +-3, -65, -119, -31, 395, 103, -330, -212, +347, 193, -74, -118, 5, -75, 221, 234, +-144, -358, 157, 324, 61, -225, -79, 36, +216, 77, -60, -135, 27, 43, 205, 68, +-235, -208, 356, 231, -232, -195, 227, 51, +-31, 66, 19, -179, 109, 175, -59, -127, +123, -8, -7, 124, 22, -261, 127, 335, +-137, -406, 243, 403, -174, -378, 177, 267, +-7, -137, -39, -42, 164, 180, -118, -302, +124, 341, -13, -351, 59, 296, -44, -266, +175, 213, -211, -164, 257, 66, -96, 40, +-69, -192, 355, 308, -488, -385, 561, 350, +-396, -244, 184, 61, 144, 88, -331, -195, +479, 184, -431, -118, 360, 13, -214, 30, +169, -9, -124, -111, 189, 242, -212, -344, +241, 331, -159, -216, 52, -1, 140, 222, +-291, -402, 440, 471, -481, -465, 473, 387, +-362, -329, 238, 293, -78, -313, -35, 337, +119, -345, -136, 284, 114, -176, -43, 23, +-26, 102, 96, -177, -135, 159, 146, -89, +-124, -23, 72, 108, -8, -150, -67, 126, +119, -64, -159, -19, 144, 75, -107, -107, +24, 93, 53, -74, -126, 42, 124, -31, +-95, 32, -13, -58, 108, 84, -211, -120, +234, 131, -219, -144, 118, 114, -31, -70, +-93, -4, 146, 78, -203, -153, 184, 189, +-205, -187, 165, 137, -181, -64, 137, -30, +-131, 103, 36, -162, 21, 198, -167, -229, +242, 262, -357, -321, 369, 374, -401, -418, +319, 403, -277, -323, 139, 157, -66, 56, +-69, -290, 111, 463, -196, -549, 164, 501, +-176, -355, 81, 146, -69, 53, -4, -195, +-41, 241, 33, -213, -125, 138, 98, -57, +-119, 11, -7, -1, 78, 8, -223, -21, +218, 13, -213, 8, 37, -36, 85, 41, +-269, -23, 269, -20, -252, 62, 66, -90, +55, 77, -208, -40, 170, -7, -121, 23, +-85, 2, 180, -55, -300, 105, 241, -110, +-207, 49, 73, 63, -65, -183, 15, 249, +-87, -222, 52, 104, -49, 54, -105, -182, +204, 224, -357, -165, 354, 38, -344, 99, +183, -185, -102, 194, -31, -139, 19, 67, +-46, -16, -8, 31, -48, -86, 71, 163, +-198, -213, 206, 220, -227, -175, 85, 106, +41, -20, -226, -56, 291, 135, -330, -218, +216, 321, -150, -409, 24, 456, -20, -413, +-3, 269, -38, -41, 3, -192, 26, 359, +-132, -382, 143, 261, -153, -36, 1, -190, +148, 326, -321, -308, 361, 157, -287, 79, +33, -282, 205, 410, -468, -402, 516, 315, +-464, -185, 251, 109, -51, -99, -103, 178, +100, -272, -43, 345, -115, -318, 160, 205, +-166, -23, 47, -153, 74, 284, -165, -308, +143, 270, -71, -176, -84, 110, 128, -86, +-140, 138, -1, -219, 170, 326, -321, -395, +379, 442, -342, -433, 184, 404, -66, -349, +-73, 306, 81, -249, -50, 198, 0, -102, +22, -25, 12, 212, -116, -389, 161, 515, +-204, -487, 84, 306, 75, 33, -276, -366, +413, 603, -422, -590, 267, 359, -56, 37, +-239, -402, 391, 621, -473, -584, 416, 362, +-282, -39, 164, -213, -107, 348, 67, -298, +-125, 167, 88, 0, -66, -84, -42, 96, +162, 8, -238, -142, 256, 299, -238, -388, +130, 415, -117, -318, 67, 162, -96, 51, +120, -222, -105, 350, 50, -368, 29, 343, +-168, -260, 192, 211, -233, -166, 130, 161, +7, -118, -160, 56, 323, 62, -440, -166, +446, 258, -445, -264, 276, 240, -147, -176, +2, 156, 62, -184, 4, 308, -175, -444, +368, 590, -588, -639, 589, 624, -513, -485, +240, 305, 76, -62, -354, -176, 557, 445, +-675, -691, 686, 935, -763, -1081, 749, 1117, +-759, -966, 642, 674, -390, -276, 53, -68, +294, 280, -545, -268, 511, 105, -350, 138, +-13, -259, 297, 197, -416, 93, 339, -468, +-106, 804, -161, -906, 248, 763, -236, -411, +22, 36, 146, 214, -202, -211, 85, -5, +195, 356, -512, -659, 694, 842, -778, -838, +616, 738, -418, -599, 173, 526, 24, -484, +-167, 483, 300, -422, -486, 326, 624, -167, +-819, 51, 858, 1, -817, 67, 650, -191, +-416, 346, 221, -432, -131, 443, 99, -342, +-228, 205, 289, -19, -359, -147, 317, 327, +-190, -495, 35, 683, 95, -842, -204, 994, +170, -1078, -140, 1111, 5, -1055, 98, 949, +-173, -782, 210, 593, -199, -354, 136, 99, +-119, 210, 44, -537, -46, 884, -2, -1166, +57, 1341, -136, -1313, 229, 1080, -299, -642, +262, 95, -196, 468, 0, -912, 134, 1192, +-221, -1242, 175, 1106, 8, -791, -290, 380, +554, 93, -809, -523, 865, 860, -830, -976, +612, 830, -298, -387, -95, -229, 493, 878, +-850, -1313, 1015, 1378, -1011, -975, 697, 194, +-196, 763, -437, -1610, 1027, 2107, -1414, -2102, +1482, 1648, -1289, -881, 845, 78, -420, 539, +76, -787, 14, 649, 110, -200, -360, -350, +586, 778, -674, -874, 486, 548, -105, 161, +-486, -1053, 1103, 1862, -1667, -2341, 2085, 2380, +-2346, -2025, 2436, 1520, -2445, -1126, 2312, 1056, +-2123, -1302, 1760, 1672, -1254, -1827, 570, 1498, +212, -593, -1004, -686, 1617, 1963, -2008, -2785, +2041, 2885, -1852, -2254, 1493, 1194, -1121, -149, +810, -495, -564, 595, 275, -295, 115, -45, +-719, 58, 1397, 445, -2045, -1342, 2407, 2275, +-2337, -2805, 1785, 2645, -903, -1760, -138, 427, +1029, 948, -1677, -1956, 1952, 2382, -1935, -2202, +1647, 1577, -1157, -708, 477, -201, 311, 1002, +-1126, -1560, 1717, 1755, -1939, -1498, 1614, 806, +-821, 170, -210, -1137, 1103, 1775, -1548, -1818, +1341, 1218, -600, -156, -443, -1019, 1373, 1909, +-1884, -2223, 1807, 1862, -1195, -924, 229, -303, +781, 1475, -1606, -2247, 2013, 2399, -1965, -1893, +1486, 909, -768, 219, 43, -1083, 423, 1403, +-479, -1121, 108, 449, 472, 226, -992, -530, +1138, 300, -821, 348, 143, -1028, 580, 1328, +-1006, -1005, 911, 147, -384, 870, -325, -1532, +812, 1472, -841, -636, 398, -642, 256, 1825, +-763, -2402, 847, 2131, -510, -1160, -26, -65, +387, 1020, -342, -1339, -107, 1005, 673, -298, +-976, -328, 739, 527, 14, -214, -982, -411, +1703, 972, -1849, -1144, 1348, 817, -447, -138, +-426, -600, 917, 1114, -922, -1267, 593, 1117, +-263, -833, 193, 574, -439, -408, 830, 287, +-1062, -123, 904, -131, -355, 466, -392, -792, +1013, 1024, -1269, -1112, 1100, 1078, -672, -947, +237, 768, -30, -545, 126, 282, -427, 2, +731, -248, -853, 411, 694, -456, -282, 418, +-263, -365, 787, 378, -1149, -478, 1272, 607, +-1137, -652, 788, 517, -323, -182, -114, -262, +403, 649, -458, -817, 306, 685, -44, -311, +-166, -149, 223, 491, -88, -588, -127, 417, +289, -98, -286, -175, 113, 235, 121, -24, +-247, -374, 174, 749, 89, -873, -384, 598, +545, 37, -472, -821, 223, 1436, 43, -1625, +-129, 1284, -41, -541, 381, -297, -678, 902, +729, -1058, -466, 775, 10, -253, 379, -214, +-477, 415, 225, -323, 251, 69, -637, 101, +698, -25, -355, -299, -237, 710, 773, -977, +-972, 924, 737, -547, -183, 6, -393, 455, +734, -638, -713, 495, 418, -147, -69, -201, +-122, 365, 85, -295, 108, 77, -271, 115, +290, -148, -139, -13, -57, 264, 134, -430, +-24, 377, -212, -89, 386, -305, -316, 609, +-37, -652, 562, 373, -975, 116, 1028, -614, +-639, 914, -52, -906, 736, 614, -1078, -181, +923, -210, -335, 420, -396, -402, 925, 210, +-1022, 47, 668, -263, -66, 379, -479, -396, +757, 330, -675, -236, 367, 132, -38, -44, +-122, -21, 47, 45, 180, -18, -399, -46, +456, 125, -272, -174, -78, 142, 472, -32, +-730, -144, 763, 307, -571, -389, 258, 333, +51, -158, -218, -83, 230, 293, -116, -413, +-7, 422, 47, -366, 43, 310, -218, -309, +389, 365, -442, -441, 347, 473, -134, -420, +-81, 279, 184, -88, -127, -91, -24, 194, +174, -222, -183, 181, 24, -106, 259, 23, +-515, 53, 614, -118, -478, 145, 185, -132, +134, 54, -305, 78, 261, -234, -14, 354, +-272, -418, 468, 404, -460, -365, 285, 344, +-41, -386, -105, 463, 98, -523, 74, 461, +-271, -235, 371, -134, -277, 540, 26, -843, +283, 915, -463, -749, 433, 430, -181, -122, +-142, -27, 377, -55, -365, 300, 111, -566, +297, 666, -640, -507, 773, 102, -603, 395, +231, -798, 190, 941, -463, -777, 510, 361, +-331, 138, 66, -564, 170, 792, -264, -802, +255, 629, -184, -386, 168, 143, -221, 32, +321, -136, -375, 196, 319, -244, -104, 295, +-185, -348, 463, 370, -601, -327, 560, 193, +-339, 8, 59, -242, 186, 431, -279, -514, +221, 448, -37, -259, -149, -7, 262, 244, +-239, -384, 114, 378, 61, -258, -178, 80, +210, 52, -131, -82, 1, -12, 138, 174, +-216, -343, 252, 410, -249, -332, 252, 107, +-236, 188, 202, -452, -114, 604, -33, -588, +215, 433, -354, -230, 416, 72, -355, -24, +227, 80, -61, -174, -61, 202, 136, -106, +-159, -116, 176, 366, -191, -518, 198, 460, +-146, -178, 22, -246, 173, 634, -361, -830, +448, 737, -363, -395, 104, -62, 245, 455, +-556, -643, 720, 576, -661, -337, 420, 46, +-90, 165, -200, -240, 364, 202, -362, -123, +253, 74, -75, -85, -63, 123, 159, -127, +-180, 49, 189, 106, -181, -287, 212, 394, +-222, -374, 230, 199, -153, 59, 24, -322, +164, 492, -362, -516, 509, 403, -574, -207, +522, -11, -376, 187, 142, -305, 105, 367, +-351, -396, 502, 408, -584, -393, 526, 345, +-401, -243, 213, 90, -41, 83, -84, -233, +130, 315, -115, -304, 86, 197, -64, -37, +100, -129, -137, 250, 200, -293, -183, 265, +147, -186, -26, 99, -61, -40, 162, 23, +-173, -36, 171, 55, -101, -37, 47, -34, +46, 147, -128, -264, 208, 335, -255, -319, +223, 193, -116, 14, -97, -263, 302, 492, +-489, -658, 509, 720, -431, -684, 182, 562, +33, -382, -240, 180, 277, 0, -239, -136, +108, 214, -25, -249, 4, 268, -79, -305, +205, 362, -296, -425, 338, 448, -245, -392, +126, 257, 76, -75, -178, -78, 275, 149, +-222, -106, 178, -3, -39, 112, -14, -146, +104, 76, -99, 63, 121, -185, -111, 203, +150, -77, -233, -165, 347, 438, -488, -651, +563, 717, -604, -627, 478, 418, -328, -166, +36, -56, 160, 211, -384, -294, 431, 323, +-470, -332, 361, 345, -290, -350, 156, 333, +-69, -285, -21, 195, 64, -97, -50, 25, +6, -34, 136, 120, -242, -261, 389, 396, +-371, -468, 344, 427, -126, -292, -32, 104, +251, 76, -292, -187, 312, 223, -166, -188, +52, 122, 90, -43, -139, -35, 152, 106, +-128, -168, 86, 211, -93, -214, 70, 167, +-122, -69, 77, -42, -100, 130, 2, -159, +11, 113, -132, -5, 130, -116, -187, 210, +112, -246, -64, 217, -77, -151, 165, 90, +-254, -72, 269, 108, -212, -189, 123, 273, +27, -305, -109, 248, 216, -94, -208, -109, +250, 298, -183, -404, 210, 395, -134, -297, +154, 164, -79, -71, 87, 50, -43, -91, +76, 140, -84, -147, 100, 88, -81, 24, +-1, -134, 77, 201, -182, -192, 165, 119, +-121, -27, -76, -52, 207, 82, -368, -60, +321, 5, -237, 54, 1, -100, 145, 115, +-265, -109, 201, 99, -85, -96, -94, 115, +213, -130, -241, 109, 212, -37, -120, -89, +86, 225, -31, -313, 69, 282, -27, -130, +23, -100, 86, 313, -124, -411, 196, 343, +-138, -135, 77, -111, 62, 273, -136, -280, +173, 137, -127, 82, 32, -254, 52, 304, +-115, -219, 83, 60, -40, 76, -65, -115, +91, 35, -118, 115, 18, -245, 61, 282, +-195, -198, 218, 32, -201, 136, 67, -238, +66, 228, -186, -124, 189, -20, -92, 144, +-76, -194, 237, 158, -281, -62, 214, -57, +-17, 150, -166, -172, 303, 117, -256, -15, +120, -77, 102, 92, -213, -4, 211, -172, +-40, 377, -168, -514, 341, 521, -349, -390, +205, 175, 25, 42, -229, -185, 296, 227, +-233, -188, 66, 125, 69, -100, -127, 140, +27, -228, 131, 326, -314, -388, 382, 387, +-343, -317, 183, 194, 0, -55, -158, -76, +216, 178, -188, -255, 109, 305, -34, -344, +12, 373, -59, -365, 153, 308, -224, -193, +245, 28, -179, 163, 52, -319, 110, 394, +-218, -388, 274, 301, -239, -197, 177, 117, +-119, -92, 101, 136, -125, -212, 164, 274, +-174, -281, 124, 205, -21, -49, -116, -142, +229, 314, -285, -410, 261, 391, -169, -266, +31, 74, 100, 129, -195, -291, 230, 380, +-215, -386, 165, 328, -117, -218, 96, 75, +-113, 95, 151, -269, -185, 426, 197, -540, +-185, 587, 145, -525, -121, 367, 115, -125, +-132, -146, 152, 364, -146, -462, 89, 402, +9, -214, -121, -22, 217, 177, -263, -183, +242, 40, -181, 170, 95, -316, -26, 316, +-16, -170, 38, -28, -57, 137, 106, -69, +-185, -181, 291, 492, -381, -710, 413, 711, +-356, -452, 211, 13, -10, 470, -181, -839, +313, 986, -353, -863, 296, 527, -168, -81, +18, -338, 108, 617, -164, -705, 145, 601, +-50, -390, -82, 165, 205, -20, -284, 0, +278, -91, -207, 249, 81, -409, 31, 532, +-111, -590, 131, 579, -119, -505, 86, 382, +-67, -229, 44, 76, -1, 55, -98, -152, +247, 240, -426, -347, 595, 513, -721, -744, +815, 1008, -879, -1252, 960, 1387, -1030, -1351, +1070, 1109, -997, -682, 794, 148, -458, 360, +99, -706, 180, 787, -262, -596, 139, 227, +109, 156, -338, -377, 411, 338, -276, -73, +-19, -270, 315, 502, -474, -483, 393, 197, +-115, 230, -236, -619, 470, 810, -489, -746, +273, 490, 46, -196, -308, 18, 362, -44, +-188, 263, -137, -561, 442, 808, -579, -883, +485, 750, -205, -445, -139, 77, 435, 243, +-605, -430, 683, 466, -705, -383, 760, 236, +-825, -87, 871, -24, -812, 95, 620, -128, +-311, 148, -30, -156, 308, 156, -457, -136, +462, 85, -369, 10, 228, -163, -92, 369, +-31, -620, 120, 887, -204, -1120, 252, 1268, +-281, -1281, 262, 1152, -230, -904, 185, 597, +-172, -294, 174, 50, -187, 130, 163, -265, +-96, 418, -26, -611, 162, 868, -266, -1147, +314, 1380, -283, -1499, 228, 1434, -161, -1174, +122, 755, -100, -234, 100, -307, -96, 798, +114, -1174, -168, 1392, 290, -1413, -475, 1233, +689, -867, -859, 371, 912, 174, -817, -666, +573, 1023, -260, -1172, -69, 1094, 340, -800, +-562, 351, 739, 161, -917, -621, 1075, 905, +-1179, -922, 1125, 640, -856, -97, 363, -610, +269, 1324, -902, -1872, 1365, 2111, -1523, -1970, +1372, 1427, -968, -578, 448, -402, 62, 1290, +-462, -1868, 727, 2008, -867, -1716, 937, 1156, +-975, -602, 1046, 318, -1176, -483, 1405, 1089, +-1742, -1924, 2147, 2679, -2521, -3044, 2733, 2842, +-2653, -2113, 2219, 1083, -1486, -77, 579, -614, +307, 871, -1051, -787, 1580, 638, -1944, -715, +2194, 1192, -2383, -1989, 2466, 2785, -2356, -3170, +1962, 2824, -1287, -1711, 439, 136, 381, 1382, +-981, -2350, 1273, 2514, -1306, -2005, 1239, 1245, +-1247, -713, 1393, 720, -1591, -1200, 1637, 1795, +-1320, -2020, 562, 1548, 530, -381, -1665, -1142, +2509, 2502, -2808, -3241, 2507, 3145, -1741, -2303, +750, 1035, 220, 280, -1010, -1337, 1561, 1968, +-1858, -2131, 1885, 1853, -1596, -1201, 975, 271, +-90, 765, -863, -1657, 1583, 2136, -1795, -2005, +1382, 1237, -467, -53, -601, -1159, 1392, 1963, +-1567, -2068, 1050, 1431, -25, -297, -1125, -915, +2004, 1779, -2353, -2021, 2118, 1616, -1450, -757, +596, -232, 177, 1045, -699, -1456, 878, 1402, +-733, -969, 353, 354, 96, 206, -424, -517, +461, 498, -151, -221, -411, -116, 984, 263, +-1282, -64, 1108, -445, -487, 1020, -327, -1314, +953, 1063, -1094, -236, 684, -885, 57, 1828, +-723, -2163, 978, 1709, -715, -653, 137, -537, +379, 1351, -494, -1493, 143, 1013, 434, -256, +-825, -323, 691, 438, 11, -93, -978, -428, +1708, 756, -1791, -640, 1127, 84, -1, 661, +-1088, -1253, 1674, 1442, -1595, -1192, 1029, 670, +-393, -120, 46, -267, -120, 461, 436, -564, +-649, 700, 491, -936, 59, 1194, -744, -1338, +1197, 1233, -1171, -854, 674, 321, 16, 179, +-517, -496, 586, 587, -249, -530, -232, 476, +508, -509, -373, 629, -131, -714, 726, 659, +-1100, -405, 1066, 26, -668, 328, 134, -510, +283, 475, -450, -303, 416, 143, -349, -117, +392, 234, -568, -389, 746, 427, -768, -247, +530, -113, -92, 480, -363, -654, 629, 503, +-595, -83, 314, -421, 50, 744, -318, -717, +390, 344, -297, 191, 143, -606, -41, 679, +33, -345, -93, -249, 168, 832, -221, -1120, +262, 966, -305, -414, 356, -328, -348, 968, +221, -1286, 58, 1193, -413, -774, 689, 215, +-717, 282, 416, -572, 103, 646, -596, -573, +789, 455, -533, -364, -90, 294, 806, -211, +-1244, 42, 1191, 191, -644, -440, -149, 601, +812, -586, -1080, 394, 900, -117, -453, -115, +27, 195, 149, -116, -41, -20, -205, 70, +376, 56, -331, -331, 102, 597, 139, -650, +-221, 380, 101, 146, 98, -695, -166, 993, +-50, -861, 517, 339, -992, 327, 1178, -816, +-876, 888, 164, -529, 641, -61, -1125, 583, +1034, -813, -396, 696, -468, -344, 1090, -20, +-1149, 246, 591, -280, 306, 210, -1120, -151, +1486, 184, -1306, -276, 732, 344, -114, -277, +-276, 63, 318, 233, -125, -476, -72, 540, +78, -387, 157, 78, -507, 227, 782, -386, +-822, 312, 599, -46, -235, -258, -105, 421, +294, -330, -321, 9, 266, 395, -243, -680, +311, 706, -443, -471, 560, 99, -556, 205, +402, -296, -140, 154, -116, 95, 269, -277, +-272, 267, 151, -57, 7, -238, -98, 454, +57, -479, 121, 310, -372, -40, 591, -196, +-665, 287, 551, -225, -263, 49, -95, 166, +361, -345, -414, 459, 218, -506, 136, 490, +-477, -409, 605, 273, -452, -84, 63, -117, +360, 282, -602, -380, 534, 410, -211, -402, +-183, 411, 412, -480, -335, 595, -12, -693, +432, 691, -680, -524, 607, 194, -223, 203, +-275, -532, 638, 670, -680, -574, 392, 313, +82, -38, -492, -104, 656, 32, -508, 203, +160, -455, 201, 556, -386, -406, 322, 36, +-62, 410, -244, -743, 438, 834, -436, -671, +282, 338, -82, 9, -34, -258, 2, 372, +129, -394, -242, 387, 214, -406, -6, 434, +-325, -416, 623, 295, -742, -69, 610, -207, +-291, 436, -55, -537, 259, 474, -242, -264, +36, -14, 218, 276, -359, -455, 297, 525, +-47, -490, -258, 359, 487, -162, -546, -62, +438, 279, -239, -427, 51, 466, 77, -378, +-142, 193, 192, 28, -263, -198, 364, 246, +-444, -161, 454, -19, -350, 192, 160, -268, +32, 210, -150, -34, 142, -180, -18, 322, +-150, -328, 261, 197, -257, -3, 114, -141, +89, 168, -273, -69, 356, -90, -317, 191, +195, -161, -68, -5, -3, 218, 1, -349, +26, 300, -5, -63, -115, -258, 312, 512, +-496, -564, 550, 378, -406, -21, 92, -359, +283, 610, -547, -657, 592, 521, -401, -289, +77, 75, 224, 66, -370, -143, 330, 217, +-173, -343, 27, 521, 8, -680, 74, 727, +-196, -590, 238, 279, -123, 109, -126, -447, +412, 604, -596, -547, 596, 312, -403, -18, +103, -241, 195, 404, -418, -478, 535, 518, +-584, -558, 593, 591, -569, -574, 480, 447, +-290, -193, 10, -151, 313, 468, -570, -649, +677, 611, -586, -377, 352, 39, -78, 272, +-120, -441, 190, 424, -138, -272, 52, 80, +-8, 46, 52, -40, -172, -61, 289, 194, +-332, -255, 261, 182, -89, 12, -115, -257, +270, 453, -322, -515, 257, 412, -98, -191, +-103, -63, 284, 268, -423, -359, 474, 359, +-443, -304, 329, 248, -153, -224, -46, 208, +222, -155, -336, 19, 369, 206, -339, -472, +280, 699, -237, -814, 242, 778, -288, -619, +346, 409, -368, -226, 327, 116, -224, -60, +81, 22, 57, 52, -160, -162, 206, 286, +-206, -351, 169, 326, -103, -212, 19, 58, +81, 72, -194, -132, 306, 134, -406, -122, +473, 163, -492, -280, 465, 432, -394, -529, +271, 497, -116, -290, -71, -33, 257, 372, +-414, -604, 507, 662, -525, -552, 475, 348, +-375, -153, 247, 49, -125, -33, 15, 67, +79, -93, -148, 69, 178, -8, -161, -39, +91, 22, 15, 69, -126, -198, 191, 298, +-180, -312, 105, 213, 5, -41, -84, -138, +100, 254, -34, -277, -61, 218, 151, -133, +-167, 58, 121, -24, -29, 1, -51, 40, +76, -123, -52, 230, -14, -302, 41, 289, +-28, -155, -55, -59, 148, 279, -218, -402, +233, 370, -172, -205, 92, -22, -5, 212, +-40, -282, 70, 228, -86, -96, 123, -28, +-168, 81, 191, -56, -167, -4, 38, 33, +135, 28, -349, -176, 474, 373, -506, -531, +403, 582, -214, -506, 19, 332, 134, -125, +-156, -59, 124, 171, -17, -219, -32, 228, +53, -246, 11, 283, -100, -330, 167, 362, +-216, -339, 182, 256, -146, -132, 43, 8, +33, 74, -140, -99, 220, 62, -275, 4, +280, -60, -189, 76, 90, -49, 54, -8, +-88, 78, 79, -138, 64, 165, -224, -150, +360, 109, -424, -50, 348, -3, -241, 47, +33, -78, 109, 106, -279, -142, 348, 182, +-394, -208, 360, 198, -253, -133, 135, 25, +37, 102, -100, -198, 174, 226, -128, -167, +115, 67, -80, 26, 101, -59, -157, 9, +169, 94, -198, -197, 90, 243, -37, -185, +-112, 54, 155, 110, -201, -241, 183, 290, +-124, -254, 92, 162, 16, -73, -35, 29, +143, -47, -127, 100, 149, -142, -60, 127, +-42, -35, 135, -106, -227, 246, 166, -319, +-121, 293, -68, -178, 133, 23, -210, 98, +137, -136, -39, 66, -38, 83, 88, -251, +38, 358, -116, -354, 276, 233, -221, -26, +140, -201, 97, 368, -284, -430, 375, 365, +-377, -217, 201, 49, -115, 79, -22, -141, +-71, 159, 140, -185, -297, 272, 342, -430, +-277, 618, 171, -758, 36, 769, -79, -615, +139, 344, 15, -47, -71, -177, 134, 258, +-21, -206, -201, 80, 408, 14, -596, -3, +487, -138, -299, 354, -132, -553, 420, 648, +-632, -589, 588, 393, -390, -138, 194, -77, +-2, 169, 70, -122, -122, -30, 318, 210, +-310, -330, 258, 325, -52, -186, -171, -51, +280, 325, -348, -555, 190, 685, -99, -679, +-106, 546, 136, -335, -169, 114, 96, 38, +-23, -60, 5, -32, 30, 202, 92, -361, +-115, 430, 250, -384, -214, 244, 194, -91, +-62, 1, -94, -6, 205, 77, -339, -153, +303, 177, -328, -130, 209, 56, -223, -21, +220, 76, -347, -230, 528, 435, -696, -622, +894, 730, -918, -741, 945, 703, -762, -661, +617, 640, -364, -613, 141, 514, 110, -276, +-408, -123, 642, 603, -923, -1015, 972, 1198, +-944, -1052, 622, 602, -233, -28, -199, -453, +493, 635, -524, -473, 395, 72, -56, 341, +-149, -536, 297, 413, -161, -23, -31, -435, +237, 755, -291, -786, 114, 551, 146, -178, +-502, -150, 639, 299, -678, -221, 448, -29, +-176, 348, -137, -676, 393, 972, -556, -1239, +740, 1477, -821, -1685, 961, 1798, -940, -1765, +878, 1578, -632, -1270, 335, 920, -47, -619, +-171, 432, 172, -331, -104, 251, -134, -86, +266, -219, -369, 673, 291, -1178, -125, 1588, +-82, -1800, 286, 1775, -339, -1575, 373, 1299, +-250, -1095, 207, 971, -123, -902, 152, 758, +-196, -453, 231, -70, -238, 723, 111, -1335, +-11, 1752, -159, -1839, 137, 1608, -37, -1105, +-245, 506, 560, 82, -802, -575, 918, 940, +-769, -1172, 520, 1286, -110, -1263, -206, 1019, +523, -565, -726, -99, 909, 843, -1084, -1527, +1188, 1900, -1243, -1838, 1027, 1336, -674, -489, +51, -455, 548, 1267, -1085, -1680, 1341, 1677, +-1277, -1225, 962, 457, -397, 496, -155, -1451, +763, 2257, -1179, -2808, 1518, 2915, -1621, -2573, +1569, 1757, -1334, -703, 932, -403, -539, 1188, +136, -1451, 18, 1152, -49, -446, -170, -315, +375, 821, -484, -719, 322, 83, 209, 946, +-940, -1958, 1839, 2638, -2502, -2739, 2934, 2319, +-2884, -1693, 2539, 1128, -1939, -919, 1247, 1010, +-589, -1249, -119, 1184, 744, -654, -1447, -365, +1958, 1579, -2338, -2536, 2332, 2874, -2033, -2408, +1488, 1492, -871, -425, 428, -267, -96, 464, +-16, -205, 260, -86, -601, 53, 1233, 431, +-1928, -1317, 2493, 2184, -2678, -2730, 2263, 2580, +-1421, -1892, 207, 787, 899, 361, -1827, -1299, +2269, 1878, -2355, -2043, 2101, 1921, -1592, -1400, +952, 652, -111, 323, -672, -1232, 1409, 1920, +-1717, -2048, 1623, 1537, -1016, -605, 192, -468, +519, 1189, -865, -1382, 613, 859, -21, -27, +-800, -868, 1358, 1457, -1623, -1631, 1439, 1385, +-972, -821, 330, 172, 433, 611, -1154, -1265, +1833, 1760, -2119, -1763, 1988, 1309, -1229, -389, +170, -653, 845, 1314, -1301, -1322, 922, 593, +61, 357, -1254, -1112, 1863, 1067, -1670, -308, +610, -777, 628, 1460, -1436, -1282, 1336, 279, +-400, 1141, -749, -2070, 1516, 2070, -1327, -964, +432, -615, 760, 2044, -1439, -2613, 1307, 2158, +-443, -1034, -601, -202, 1115, 933, -854, -1061, +-147, 564, 1164, 26, -1684, -445, 1249, 433, +-123, -132, -1165, -262, 1957, 540, -1840, -479, +1007, 222, 153, 216, -948, -562, 1170, 898, +-789, -1080, 288, 1215, -39, -1287, 232, 1223, +-732, -974, 1072, 444, -1018, 149, 385, -773, +446, 1080, -1157, -1075, 1340, 748, -1021, -411, +445, 262, 31, -346, -124, 632, -48, -757, +334, 593, -359, -5, 134, -629, 272, 1082, +-512, -1057, 436, 584, -90, 31, -296, -435, +356, 331, -58, 75, -517, -589, 907, 748, +-869, -482, 296, -135, 494, 675, -1051, -822, +1058, 526, -460, 84, -322, -561, 881, 679, +-804, -268, 200, -341, 600, 906, -1084, -1101, +969, 873, -371, -347, -355, -267, 718, 689, +-599, -918, 76, 858, 401, -662, -530, 319, +210, 16, 308, -317, -628, 467, 536, -355, +-57, 49, -405, 378, 536, -656, -141, 718, +-528, -423, 1063, -27, -1069, 437, 474, -601, +388, 491, -1054, -263, 1112, 62, -596, -117, +-201, 332, 753, -592, -766, 626, 280, -420, +365, 24, -731, 322, 645, -378, -190, 118, +-221, 344, 298, -699, 80, 814, -654, -585, +1040, 225, -961, 53, 414, -65, 241, -150, +-615, 393, 410, -480, 222, 246, -917, 192, +1176, -661, -759, 881, -176, -800, 1180, 443, +-1681, -3, 1437, -330, -535, 481, -517, -451, +1196, 376, -1161, -266, 488, 177, 416, -26, +-1079, -199, 1172, 493, -778, -724, 190, 749, +207, -554, -241, 158, -4, 233, 254, -474, +-259, 441, -15, -217, 410, -52, -634, 195, +549, -108, -180, -163, -226, 495, 426, -672, +-343, 646, 95, -383, 44, 32, 80, 280, +-473, -403, 869, 325, -1007, -101, 710, -169, +-79, 350, -602, -402, 1036, 312, -1049, -205, +750, 129, -336, -183, 68, 346, -11, -555, +121, 698, -232, -692, 246, 541, -175, -268, +84, 2, -82, 204, 140, -282, -201, 277, +153, -208, 5, 125, -202, -43, 311, -43, +-245, 98, 70, -112, 95, 0, -79, 226, +-160, -519, 522, 755, -800, -805, 799, 605, +-472, -211, -63, -196, 539, 457, -746, -441, +563, 229, -119, 37, -372, -124, 643, -50, +-592, 449, 254, -856, 162, 1046, -423, -895, +399, 428, -108, 134, -281, -574, 570, 699, +-622, -523, 427, 178, -132, 131, -119, -251, +197, 149, -120, 96, -46, -314, 159, 401, +-164, -304, 82, 79, 0, 190, -17, -399, +-46, 507, 111, -508, -85, 419, -95, -272, +365, 84, -626, 103, 710, -265, -586, 351, +268, -354, 81, 267, -349, -143, 421, 32, +-351, 47, 181, -74, -55, 120, 0, -210, +-37, 366, 95, -511, -156, 570, 172, -449, +-202, 159, 226, 227, -286, -567, 304, 725, +-288, -659, 165, 404, 5, -101, -216, -136, +353, 216, -405, -174, 328, 73, -177, -16, +-21, 45, 190, -155, -308, 279, 343, -353, +-319, 342, 231, -259, -152, 155, 53, -80, +-20, 84, -31, -149, 45, 230, -113, -288, +173, 257, -266, -135, 286, -61, -259, 250, +127, -364, 12, 340, -125, -180, 113, -63, +-7, 278, -179, -351, 278, 254, -254, -11, +24, -258, 253, 426, -515, -399, 534, 191, +-375, 111, 21, -376, 249, 505, -374, -482, +219, 364, 34, -251, -279, 195, 291, -200, +-107, 201, -213, -114, 401, -85, -359, 348, +37, -583, 353, 678, -649, -588, 608, 348, +-342, -48, -96, -190, 368, 300, -462, -266, +262, 141, -38, 12, -155, -142, 134, 231, +-53, -290, -38, 322, -49, -331, 249, 296, +-503, -199, 576, 40, -448, 163, 76, -365, +301, 517, -613, -574, 639, 533, -552, -398, +337, 229, -271, -83, 278, -5, -446, 16, +518, 27, -510, -76, 290, 83, -22, -53, +-256, 17, 354, -29, -320, 137, 129, -317, +43, 489, -178, -566, 147, 491, -94, -274, +-33, 5, 44, 186, -55, -230, -49, 124, +70, 32, -116, -136, 46, 99, -39, 81, +8, -323, -78, 519, 119, -590, -160, 518, +76, -341, 42, 142, -208, 18, 244, -102, +-197, 124, -10, -115, 161, 111, -276, -137, +152, 182, 24, -228, -299, 242, 393, -215, +-395, 138, 200, -50, -55, -10, -71, 36, +18, -22, 63, 9, -161, -28, 118, 100, +1, -193, -221, 259, 365, -236, -477, 104, +457, 101, -472, -316, 438, 451, -490, -484, +432, 411, -360, -282, 102, 144, 157, -38, +-442, -55, 551, 145, -552, -238, 395, 322, +-244, -365, 112, 346, -97, -257, 105, 131, +-150, -7, 101, -73, -47, 101, -82, -80, +126, 29, -170, 22, 90, -70, -43, 109, +-52, -154, 53, 194, -62, -232, 2, 233, +29, -182, -90, 81, 107, 50, -127, -146, +86, 164, -23, -58, -101, -139, 208, 350, +-309, -467, 292, 423, -226, -202, 44, -105, +104, 369, -251, -481, 275, 397, -254, -181, +157, -63, -80, 218, -3, -242, 60, 169, +-125, -94, 199, 77, -274, -141, 309, 244, +-278, -303, 160, 271, 4, -138, -180, -47, +278, 239, -296, -379, 204, 454, -91, -449, +-39, 384, 112, -263, -143, 100, 143, 63, +-124, -208, 106, 299, -69, -327, 34, 298, +28, -232, -64, 155, 99, -79, -77, 16, +39, 42, 20, -77, -46, 94, 51, -82, +-9, 47, -17, -7, 46, -49, -10, 102, +-40, -152, 125, 176, -146, -158, 129, 64, +9, 96, -171, -284, 392, 424, -519, -451, +585, 346, -486, -136, 326, -84, -82, 236, +-84, -276, 207, 220, -194, -106, 156, -2, +-57, 73, 39, -96, -33, 76, 123, -2, +-165, -127, 233, 285, -171, -427, 106, 475, +60, -372, -149, 129, 253, 176, -221, -411, +197, 493, -83, -397, 45, 218, 21, -45, +5, -21, 38, 0, -32, 53, 117, -42, +-118, -47, 143, 180, -16, -269, -69, 252, +215, -141, -175, -1, 95, 87, 164, -84, +-332, 29, 476, 19, -358, -9, 211, -68, +57, 157, -140, -203, 175, 185, -6, -118, +-85, 69, 192, -62, -74, 97, -20, -145, +223, 167, -248, -164, 289, 162, -180, -185, +182, 241, -122, -281, 199, 245, -138, -122, +124, -68, 53, 251, -151, -329, 311, 290, +-284, -166, 296, 55, -162, -30, 147, 115, +-45, -230, 59, 293, 71, -213, -109, -17, +280, 322, -296, -588, 364, 717, -253, -670, +236, 486, -132, -248, 193, 48, -174, 64, +264, -97, -185, 90, 156, -91, 32, 128, +-86, -192, 207, 259, -144, -283, 166, 263, +-69, -187, 132, 85, -88, 22, 159, -124, +-51, 217, -13, -293, 241, 355, -333, -397, +476, 392, -394, -344, 341, 253, -117, -153, +31, 61, 119, 4, -78, -32, 110, 46, +2, -58, 41, 79, -5, -101, 149, 120, +-195, -114, 363, 74, -351, -5, 382, -81, +-200, 149, 83, -168, 160, 104, -216, 29, +286, -192, -124, 306, 28, -304, 179, 150, +-169, 105, 182, -368, 27, 530, -114, -545, +286, 448, -237, -340, 264, 328, -134, -462, +179, 673, -136, -852, 269, 849, -236, -646, +277, 269, -99, 135, 11, -470, 229, 633, +-275, -657, 376, 569, -233, -437, 154, 267, +131, -83, -269, -115, 529, 253, -542, -309, +604, 230, -395, -85, 292, -76, -21, 100, +-16, 3, 118, -234, 20, 433, -20, -517, +134, 383, -10, -108, -23, -222, 230, 423, +-207, -443, 244, 230, -3, 103, -129, -441, +417, 604, -426, -532, 472, 161, -195, 384, +12, -982, 357, 1380, -457, -1478, 594, 1171, +-395, -620, 279, -22, 43, 450, -99, -587, +206, 388, 7, -71, -91, -214, 342, 249, +-277, -95, 282, -204, 2, 419, -79, -507, +294, 384, -201, -216, 263, 58, -147, -63, +345, 145, -444, -314, 785, 396, -826, -411, +883, 266, -491, -94, 155, -143, 424, 313, +-661, -509, 945, 639, -840, -834, 914, 984, +-809, -1135, 1008, 1134, -973, -1021, 1061, 686, +-717, -294, 435, -123, 117, 327, -281, -345, +402, 107, -31, 153, -184, -380, 507, 340, +-303, -145, 84, -211, 461, 447, -606, -541, +691, 360, -250, -95, -17, -223, 400, 336, +-249, -310, 125, 83, 276, 117, -232, -258, +142, 144, 438, 96, -804, -471, 1247, 709, +-1134, -798, 1019, 542, -496, -113, 251, -524, +186, 1093, -290, -1611, 665, 1887, -799, -2048, +1218, 1988, -1293, -1877, 1516, 1609, -1307, -1366, +1275, 1038, -931, -786, 882, 477, -570, -218, +523, -176, -164, 581, 80, -1098, 227, 1470, +-119, -1713, 145, 1588, 222, -1256, -305, 676, +585, -160, -449, -306, 514, 531, -285, -703, +403, 776, -282, -973, 450, 1139, -237, -1339, +190, 1298, 250, -1079, -403, 519, 760, 129, +-681, -853, 757, 1324, -458, -1563, 426, 1366, +-82, -935, 0, 217, 455, 478, -674, -1162, +1178, 1549, -1241, -1708, 1342, 1437, -833, -913, +367, 77, 500, 746, -971, -1499, 1469, 1821, +-1312, -1725, 1115, 1040, -389, -57, -117, -1126, +855, 2028, -1118, -2541, 1449, 2367, -1255, -1727, +1191, 709, -758, 185, 659, -781, -386, 740, +595, -258, -673, -571, 1130, 1251, -1240, -1616, +1446, 1369, -1055, -727, 637, -228, 329, 1035, +-1098, -1615, 2077, 1726, -2540, -1605, 2990, 1317, +-2872, -1241, 2831, 1363, -2369, -1800, 2092, 2188, +-1413, -2370, 879, 1933, 72, -975, -769, -443, +1611, 1740, -1875, -2605, 2056, 2628, -1669, -2044, +1470, 1087, -1099, -422, 1207, 231, -1166, -648, +1268, 1187, -756, -1469, 71, 997, 1170, 107, +-2112, -1604, 2923, 2787, -2845, -3330, 2414, 2938, +-1345, -1943, 462, 617, 506, 505, -965, -1336, +1453, 1707, -1524, -1821, 1655, 1606, -1286, -1178, +840, 409, 94, 470, -815, -1327, 1472, 1721, +-1356, -1543, 900, 705, 121, 369, -858, -1333, +1401, 1685, -1148, -1406, 657, 541, 243, 422, +-842, -1229, 1397, 1583, -1452, -1604, 1482, 1286, +-1078, -858, 665, 232, 170, 426, -899, -1087, +1661, 1417, -1763, -1293, 1447, 591, -459, 323, +-392, -1083, 981, 1186, -633, -645, -173, -291, +1300, 945, -1761, -938, 1534, 133, -391, 923, +-749, -1609, 1509, 1305, -1144, -87, 109, -1558, +1286, 2703, -1967, -2805, 1827, 1708, -714, -37, +-414, -1471, 1128, 2082, -762, -1744, -162, 791, +1236, 63, -1444, -390, 766, 19, 751, 674, +-2068, -1273, 2682, 1338, -2019, -866, 636, 33, +967, 713, -1788, -1142, 1740, 1085, -818, -740, +-125, 260, 709, 114, -471, -398, -117, 584, +734, -792, -719, 974, 168, -1082, 793, 968, +-1444, -660, 1572, 208, -960, 163, 121, -344, +634, 261, -810, -75, 564, -48, -45, -85, +-221, 430, 187, -845, 200, 1024, -505, -827, +574, 291, -230, 290, -206, -596, 540, 425, +-460, 81, 152, -576, 196, 660, -169, -213, +-209, -576, 811, 1235, -1121, -1375, 917, 861, +-117, 27, -812, -843, 1440, 1154, -1326, -880, +605, 237, 355, 353, -925, -582, 855, 370, +-174, 56, -586, -395, 993, 408, -751, -113, +108, -316, 549, 638, -756, -761, 489, 721, +8, -637, -269, 571, 71, -467, 487, 215, +-937, 225, 867, -746, -122, 1122, -948, -1158, +1773, 827, -1814, -313, 1026, -133, 204, 325, +-1159, -273, 1339, 121, -635, -43, -495, 79, +1409, -105, -1587, -38, 997, 414, -7, -898, +-799, 1228, 1041, -1167, -695, 688, 101, -15, +338, -482, -394, 536, 175, -154, 39, -376, +34, 651, -405, -435, 845, -180, -992, 812, +676, -1039, -2, 687, -636, 77, 823, -813, +-379, 1132, -494, -877, 1317, 244, -1602, 414, +1145, -763, -148, 702, -880, -342, 1417, -70, +-1202, 328, 410, -377, 498, 298, -1023, -197, +911, 145, -275, -85, -494, -77, 992, 396, +-1026, -774, 700, 1026, -304, -964, 111, 564, +-198, 21, 411, -494, -509, 637, 331, -403, +58, -13, -449, 345, 610, -388, -481, 141, +179, 250, 31, -530, 9, 557, -291, -297, +574, -91, -613, 441, 249, -563, 369, 461, +-971, -189, 1220, -51, -1038, 177, 521, -109, +-3, -36, -280, 176, 216, -166, 11, 34, +-190, 212, 112, -430, 176, 592, -519, -610, +685, 554, -619, -413, 382, 321, -186, -266, +172, 305, -331, -330, 491, 334, -465, -194, +180, -2, 267, 238, -637, -347, 738, 369, +-541, -268, 225, 232, -11, -276, 92, 482, +-396, -665, 736, 779, -808, -652, 546, 409, +-10, -104, -457, 3, 648, -109, -386, 451, +-104, -731, 595, 827, -736, -493, 517, -94, +21, 803, -496, -1246, 746, 1364, -590, -1052, +239, 627, 184, -225, -370, 130, 351, -211, +-99, 433, -111, -481, 259, 369, -195, -9, +102, -319, 30, 570, -28, -518, -4, 332, +96, 18, -97, -272, 78, 512, -13, -590, +38, 682, -139, -637, 329, 588, -497, -342, +587, 59, -537, 341, 386, -599, -220, 780, +75, -686, -18, 539, -53, -275, 124, 153, +-316, -34, 478, 50, -669, 51, 649, -125, +-589, 327, 353, -393, -282, 431, 202, -240, +-399, 88, 467, 116, -613, -90, 386, 31, +-193, 205, -274, -319, 425, 454, -645, -384, +438, 341, -425, -159, 137, 98, -232, 40, +56, -25, -204, 87, -65, -13, 10, 43, +-315, 50, 108, -33, -174, 143, -270, -149, +249, 273, -550, -259, 216, 310, -242, -172, +-232, 73, 105, 189, -352, -302, -50, 419, +-29, -249, -433, 55, 283, 311, -641, -472, +350, 572, -568, -353, 102, 137, -161, 197, +-425, -296, 342, 386, -760, -256, 389, 248, +-540, -154, 34, 229, -246, -158, -62, 131, +-354, 128, 101, -306, -380, 560, -119, -535, +46, 444, -560, -74, 279, -207, -447, 534, +-127, -576, 63, 585, -496, -360, 145, 246, +-296, -24, -182, -20, 17, 164, -374, -168, +135, 284, -484, -234, 286, 252, -581, -68, +191, -40, -157, 297, -508, -388, 629, 527, +-1041, -438, 697, 379, -596, -140, -30, 39, +85, 138, -360, -103, 31, 137, -83, -17, +-140, 56, -212, -15, 315, 136, -734, -110, +614, 134, -574, 62, 38, -184, 203, 393, +-596, -352, 486, 272, -475, 55, 130, -276, +-93, 532, -89, -504, -57, 455, 8, -202, +-161, 86, 84, 67, -187, -10, 86, 24, +-146, 81, -32, -10, 106, 7, -385, 152, +462, -185, -566, 303, 359, -261, -170, 293, +-162, -188, 233, 192, -250, -80, -9, 85, +168, 16, -345, -4, 223, 112, -98, -125, +-154, 266, 151, -284, -91, 368, -213, -277, +373, 237, -515, -69, 333, 48, -159, 19, +-155, 75, 225, -56, -290, 74, 134, 87, +-118, -188, 14, 333, -108, -236, 22, 76, +-5, 276, -269, -502, 397, 679, -602, -585, +472, 461, -372, -238, 42, 198, 23, -164, +-138, 251, -58, -169, 59, 51, -166, 242, +-74, -403, 174, 484, -433, -275, 320, 10, +-252, 321, -131, -429, 248, 428, -461, -216, +278, 72, -244, 73, -35, -37, 1, 26, +-129, 29, -40, 62, -39, -123, -116, 224, +2, -147, -142, 29, 23, 205, -145, -289, +-47, 278, 43, -32, -327, -231, 338, 487, +-516, -512, 317, 406, -271, -120, -70, -108, +116, 303, -330, -306, 193, 263, -247, -111, +34, 19, -87, 100, -99, -120, 41, 165, +-243, -144, 216, 179, -416, -174, 332, 236, +-409, -252, 184, 283, -130, -194, -155, 35, +200, 268, -410, -562, 349, 823, -442, -857, +282, 707, -295, -338, 107, -39, -132, 341, +12, -390, -135, 246, 125, 67, -311, -337, +289, 501, -358, -423, 168, 166, -66, 266, +-219, -708, 325, 1105, -525, -1289, 504, 1261, +-559, -954, 411, 498, -347, 54, 117, -527, +-1, 888, -220, -1066, 274, 1154, -399, -1150, +367, 1138, -424, -1024, 353, 804, -341, -387, +182, -147, -68, 730, -139, -1162, 203, 1378, +-232, -1309, 63, 1073, 108, -741, -331, 455, +387, -208, -352, 18, 152, 176, 39, -354, +-222, 525, 261, -611, -240, 623, 161, -563, +-163, 529, 216, -541, -343, 650, 420, -758, +-419, 798, 294, -641, -127, 286, 1, 239, +-10, -773, 151, 1209, -325, -1427, 390, 1443, +-221, -1267, -174, 1007, 687, -705, -1071, 446, +1156, -232, -828, 93, 225, 31, 461, -170, +-917, 394, 1045, -674, -827, 979, 515, -1172, +-295, 1203, 363, -1006, -626, 661, 986, -240, +-1161, -148, 1118, 481, -805, -721, 408, 903, +37, -977, -409, 927, 826, -695, -1253, 334, +1745, 100, -2126, -435, 2294, 614, -2054, -570, +1463, 401, -568, -172, -359, 17, 1181, 73, +-1706, -88, 1992, 126, -2026, -198, 1993, 309, +-1875, -359, 1764, 301, -1536, -74, 1231, -262, +-724, 619, 123, -861, 605, 936, -1304, -817, +1976, 589, -2461, -318, 2768, 100, -2763, 52, +2532, -139, -2024, 214, 1413, -299, -688, 433, +13, -606, 681, 817, -1289, -1000, 1896, 1122, +-2368, -1114, 2744, 989, -2855, -747, 2750, 448, +-2313, -86, 1686, -314, -851, 779, 38, -1239, +759, 1632, -1342, -1861, 1830, 1919, -2131, -1834, +2457, 1693, -2681, -1515, 2917, 1274, -2885, -882, +2642, 299, -1949, 452, 1046, -1237, 113, 1917, +-1136, -2369, 2083, 2568, -2633, -2572, 3014, 2437, +-3023, -2192, 2953, 1840, -2603, -1350, 2254, 737, +-1643, -47, 1057, -661, -241, 1325, -469, -1892, +1285, 2317, -1814, -2582, 2330, 2679, -2508, -2664, +2716, 2610, -2688, -2523, 2750, 2360, -2516, -2007, +2238, 1396, -1526, -550, 755, -389, 280, 1253, +-1060, -1916, 1816, 2334, -2153, -2575, 2483, 2722, +-2514, -2840, 2643, 2921, -2487, -2909, 2357, 2715, +-1846, -2320, 1328, 1743, -527, -1053, -98, 314, +807, 436, -1234, -1198, 1758, 1937, -2075, -2629, +2520, 3164, -2690, -3486, 2786, 3541, -2431, -3346, +1929, 2952, -1108, -2438, 423, 1835, 278, -1189, +-672, 497, 1060, 180, -1252, -801, 1554, 1290, +-1748, -1675, 2032, 1998, -2157, -2350, 2286, 2695, +-2193, -2942, 2016, 2925, -1578, -2576, 1057, 1903, +-358, -1097, -305, 317, 978, 276, -1486, -688, +1898, 967, -2140, -1234, 2316, 1533, -2388, -1869, +2435, 2087, -2369, -2081, 2179, 1752, -1786, -1195, +1207, 552, -506, 1, -197, -434, 787, 764, +-1185, -1107, 1376, 1466, -1445, -1809, 1478, 2028, +-1580, -2111, 1740, 2069, -1925, -1992, 1985, 1906, +-1842, -1836, 1455, 1715, -941, -1519, 461, 1189, +-160, -790, 63, 351, -81, 20, 70, -324, +72, 530, -305, -713, 544, 863, -642, -1011, +611, 1084, -455, -1097, 344, 1001, -262, -878, +293, 735, -295, -639, 315, 563, -220, -537, +214, 489, -228, -459, 461, 440, -702, -478, +1011, 526, -1058, -549, 1006, 449, -667, -265, +447, 8, -197, 212, 221, -402, -133, 561, +105, -755, 279, 927, -632, -1057, 1179, 1078, +-1391, -1071, 1588, 1081, -1417, -1183, 1418, 1302, +-1280, -1393, 1477, 1383, -1500, -1323, 1689, 1220, +-1461, -1103, 1298, 873, -786, -541, 595, 116, +-310, 223, 474, -417, -393, 392, 436, -291, +50, 219, -438, -303, 1098, 463, -1250, -616, +1389, 584, -1025, -375, 944, 25, -732, 272, +1005, -424, -1073, 367, 1335, -221, -1096, 92, +937, -127, -411, 298, 220, -543, 100, 686, +-8, -655, 127, 393, 0, -11, 182, -395, +-119, 687, 256, -870, -59, 945, 34, -1007, +218, 1047, -149, -1086, 179, 1049, 104, -939, +-191, 725, 419, -473, -371, 202, 433, 31, +-288, -230, 326, 356, -216, -440, 271, 467, +-146, -478, 121, 450, 64, -395, -139, 283, +317, -146, -370, -24, 507, 186, -528, -339, +617, 444, -581, -514, 564, 528, -432, -545, +318, 568, -148, -619, 26, 650, 132, -634, +-225, 526, 310, -383, -301, 246, 219, -183, +-79, 146, -54, -91, 97, -64, -16, 304, +-142, -581, 294, 765, -355, -806, 243, 684, +-66, -491, -141, 295, 201, -178, -119, 110, +-94, -61, 289, -45, -412, 206, 344, -394, +-235, 515, 79, -518, -87, 374, 190, -146, +-395, -91, 546, 234, -616, -255, 518, 175, +-406, -88, 255, 61, -247, -132, 282, 257, +-371, -359, 419, 340, -379, -194, 217, -59, +-27, 324, -224, -530, 393, 626, -536, -643, +615, 641, -652, -675, 681, 743, -684, -792, +631, 756, -551, -623, 397, 416, -218, -235, +45, 96, 181, -5, -391, -110, 675, 286, +-941, -498, 1134, 664, -1194, -695, 1103, 550, +-886, -301, 707, 73, -492, 10, 400, 63, +-254, -218, 102, 313, 101, -265, -278, 67, +437, 185, -448, -403, 513, 522, -485, -556, +590, 547, -680, -520, 802, 468, -812, -382, +734, 250, -451, -95, 210, -52, 124, 153, +-244, -197, 339, 195, -335, -173, 392, 158, +-471, -150, 655, 126, -678, -72, 704, -19, +-473, 124, 281, -224, -37, 291, -77, -337, +151, 356, -107, -362, 151, 333, -82, -257, +141, 144, -75, -14, 54, -72, 10, 79, +-17, 20, 20, -213, 66, 477, -1, -761, +-22, 1002, 237, -1145, -393, 1162, 546, -1051, +-594, 820, 598, -469, -551, 9, 640, 539, +-648, -1133, 734, 1680, -625, -2066, 406, 2186, +-50, -1982, -339, 1452, 702, -682, -893, -193, +1052, 1000, -1006, -1600, 963, 1883, -802, -1818, +548, 1411, -173, -734, -334, -115, 948, 967, +-1468, -1639, 1896, 1946, -1990, -1756, 1798, 1073, +-1322, -40, 621, -1073, 105, 1940, -722, -2287, +1111, 1960, -1108, -1006, 824, -337, -296, 1734, +-284, -2837, 692, 3383, -902, -3242, 784, 2461, +-400, -1234, -111, -120, 674, 1223, -1033, -1768, +1047, 1623, -678, -891, -107, -120, 998, 998, +-1762, -1371, 2127, 1042, -1908, -75, 1199, -1190, +-171, 2285, -933, -2805, 1786, 2607, -2337, -1877, +2531, 1007, -2487, -446, 2394, 452, -2280, -986, +2189, 1725, -2026, -2229, 1660, 2139, -1176, -1350, +584, 68, -51, 1292, -303, -2278, 550, 2566, +-689, -2114, 857, 1173, -1120, -211, 1411, -291, +-1711, 92, 1857, 688, -1682, -1584, 1166, 2005, +-242, -1527, -854, 131, 1833, 1732, -2408, -3268, +2291, 3709, -1470, -2699, 185, 522, 1226, 1968, +-2196, -3755, 2477, 4132, -1957, -3026, 877, 977, +315, 1150, -1233, -2584, 1671, 2947, -1573, -2370, +1190, 1322, -631, -312, 71, -354, 470, 679, +-1010, -841, 1479, 966, -1746, -1013, 1655, 801, +-1000, -184, -64, -784, 1272, 1776, -2113, -2326, +2168, 2054, -1403, -902, 104, -739, 1151, 2208, +-1768, -2868, 1534, 2454, -532, -1180, -779, -329, +1801, 1371, -2138, -1469, 1617, 633, -481, 650, +-780, -1669, 1702, 1878, -1957, -1196, 1575, 32, +-840, 975, 57, -1319, 456, 845, -603, 193, +391, -1324, 105, 2045, -691, -2064, 1163, 1392, +-1337, -300, 1049, -846, -402, 1729, -447, -2159, +1149, 2048, -1447, -1395, 1252, 367, -713, 666, +191, -1254, -100, 1064, 546, -158, -1343, -1015, +1921, 1783, -1751, -1610, 647, 429, 1029, 1274, +-2512, -2623, 2950, 2848, -2068, -1716, 182, -219, +1714, 1915, -2612, -2438, 2031, 1533, -315, 206, +-1469, -1723, 2183, 2145, -1375, -1291, -515, -229, +2265, 1431, -2765, -1550, 1650, 557, 453, 874, +-2264, -1817, 2696, 1741, -1520, -816, -526, -239, +2139, 683, -2313, -240, 929, -726, 1192, 1464, +-2730, -1339, 2764, 257, -1279, 1231, -851, -2235, +2340, 2161, -2389, -1094, 1107, -222, 605, 935, +-1602, -650, 1306, -283, -5, 1096, -1349, -1130, +1789, 293, -1027, 908, -383, -1687, 1484, 1491, +-1501, -426, 492, -765, 786, 1184, -1391, -405, +845, -1140, 475, 2424, -1665, -2512, 1877, 1235, +-909, 700, -656, -2156, 1854, 2319, -1946, -1166, +851, -550, 735, 1827, -1882, -2012, 1939, 1152, +-962, 105, -374, -995, 1241, 1131, -1232, -684, +500, 166, 315, 14, -703, 177, 501, -457, +-39, 502, -269, -222, 141, -159, 267, 352, +-634, -226, 541, -66, 54, 247, -970, -169, +1674, -42, -1726, 121, 904, 73, 454, -405, +-1701, 598, 2047, -526, -1238, 345, -441, -308, +2034, 516, -2650, -755, 1817, 690, -5, -144, +-1806, -662, 2466, 1246, -1667, -1179, -106, 446, +1542, 497, -1704, -1008, 430, 766, 1270, -36, +-2120, -559, 1368, 594, 440, -212, -1993, -25, +2008, -234, -431, 775, -1701, -914, 2781, 198, +-2033, 1125, -227, -2206, 2568, 2273, -3704, -1235, +3007, -257, -1053, 1216, -1036, -1070, 2125, 15, +-1790, 1062, 372, -1298, 1209, 466, -2048, 856, +1555, -1684, 5, 1452, -1863, -371, 2848, -608, +-2393, 697, 678, 179, 1216, -1298, -2104, 1747, +1441, -1098, 226, -365, -1573, 1705, 1550, -2120, +-180, 1347, -1451, -20, 2041, -984, -1186, 1006, +-489, -117, 1667, -975, -1601, 1492, 376, -996, +1040, -131, -1704, 1284, 1327, -1824, -210, 1580, +-916, -703, 1593, -302, -1546, 804, 845, -574, +116, -216, -853, 896, 789, -1051, 8, 535, +-1081, 173, 1574, -534, -1053, 344, -174, 96, +1306, -195, -1524, -113, 899, 663, 5, -927, +-404, 835, 137, -448, 343, 110, -578, 56, +296, -175, 90, 182, -295, 4, 124, -547, +184, 833, -256, -332, 69, -1072, 367, 2388, +-668, -2450, 804, 999, -704, 1002, 430, -1848, +-36, 1114, -550, 368, 1010, -941, -1147, 320, +609, 653, 346, -982, -1149, 648, 1211, -517, +-227, 855, -1153, -1380, 2146, 1126, -1868, -120, +497, -1034, 1037, 1423, -1754, -972, 1182, 296, +-49, 240, -903, -395, 959, 369, -269, 126, +-664, -708, 1321, 957, -1234, -390, 595, -556, +427, 892, -1169, -325, 1218, -596, -414, 591, +-878, 176, 1606, -811, -1289, 289, -82, 657, +1326, -719, -1607, -348, 820, 1444, 299, -1131, +-709, -35, 354, 820, 402, -147, -695, -936, +393, 1082, 129, -18, -544, -1063, 573, 961, +-550, -224, 300, -337, 19, 114, -390, 97, +473, -112, -79, 82, -397, -399, 655, 873, +-320, -770, -135, 177, 256, 586, 106, -633, +-645, 310, 594, 26, -107, 75, -547, -351, +604, 569, -173, -869, -287, 931, 370, -704, +42, -76, -321, 564, 258, -470, 142, -152, +-282, 602, -86, -538, 458, 343, -471, -203, +-58, 391, 287, -274, -100, -66, -295, 584, +419, -690, -230, 423, 185, -286, -99, 519, +-97, -1092, 492, 1099, -631, -458, 253, -585, +244, 892, -585, -424, 467, 17, -346, -479, +265, 1372, -331, -1206, 417, 59, -359, 967, +173, -562, 393, -377, -980, 623, 1198, 72, +-595, -571, -512, 9, 1098, 745, -815, -765, +1, -209, 267, 795, -2, -516, -220, -167, +42, 303, 148, 99, 193, -309, -557, 343, +463, -226, 131, 156, -426, 273, 18, -567, +630, 397, -977, 70, 601, -230, 73, -54, +-657, 60, 704, 167, -225, -388, -258, 128, +404, 124, -60, -123, -293, -105, 546, 355, +-710, -405, 754, 325, -509, 135, -184, -508, +747, 537, -729, -19, 14, -376, 723, 185, +-845, 375, 363, -759, 341, 543, -681, -223, +677, 7, -358, -118, -104, 119, 481, 102, +-517, -402, 43, 422, 430, -31, -466, -158, +-25, -8, 547, 433, -733, -521, 721, 510, +-529, -516, 186, 324, 311, 180, -475, -470, +103, -100, 406, 646, -538, -431, 144, -251, +300, 138, -614, 383, 688, -134, -417, -764, +-212, 940, 847, 61, -874, -726, 368, 559, +127, -223, -154, 481, -114, -503, 322, -120, +-325, 597, 97, -365, 174, -143, -349, 85, +285, 131, -112, -225, -80, 164, 343, -363, +-494, 561, 233, -379, 478, -148, -1021, 712, +819, -724, -20, 303, -671, 313, 629, -519, +-25, 422, -535, -117, 533, -173, -140, 251, +-131, -77, 170, -142, -295, -125, 680, 486, +-894, -446, 608, -203, -42, 698, -307, -648, +231, 355, 21, -303, -192, 510, 189, -382, +-141, -103, 58, 495, 170, -176, -453, -269, +472, 18, -95, 764, -239, -933, 72, 146, +470, 478, -905, -269, 978, -278, -816, 306, +529, -94, -187, 160, -66, -459, 87, 374, +60, 249, -141, -712, -18, 366, 313, 543, +-454, -895, 335, 265, -205, 620, 258, -883, +-332, 653, 179, -389, -33, 73, 235, 342, +-620, -394, 616, -176, -88, 708, -426, -520, +444, -54, -182, 250, 121, -41, -325, -19, +368, -208, -49, 270, -263, -151, 167, 230, +195, -571, -387, 516, 278, 111, -57, -647, +-149, 499, 265, -33, -215, -11, -10, -239, +154, 289, -84, 13, -56, -87, 17, -226, +150, 619, -298, -607, 362, 239, -311, 92, +146, -276, 41, 276, -103, -217, 70, -40, +-88, 179, 110, -96, -36, -97, -90, 112, +79, -71, 34, 251, -40, -333, -101, 176, +191, 150, -85, -162, -30, 53, -8, 90, +139, -216, -217, 215, 279, 142, -414, -783, +463, 957, -301, -504, -17, -309, 274, 756, +-428, -699, 550, 153, -563, 405, 406, -456, +-108, 61, -127, 343, 161, -309, 46, 340, +-435, -535, 786, 725, -866, -470, 559, 105, +-82, -11, -244, 137, 254, -291, -42, 275, +-97, -304, 112, 129, -25, 168, -35, -583, +43, 763, 35, -695, -84, 418, -39, 17, +115, -345, 140, 431, -574, 3, 587, -557, +-103, 861, -276, -481, 265, -185, -155, 497, +186, -244, -49, -147, -256, 156, 321, -49, +-43, 7, -187, -72, 130, -54, -34, 231, +-23, -402, 177, 517, -385, -418, 479, 56, +-380, 317, 149, -205, 268, -120, -617, 266, +544, -111, -95, 13, -191, 38, 31, -251, +260, 560, -440, -710, 517, 495, -520, -85, +348, -353, -59, 535, -135, -458, 289, 160, +-428, 243, 404, -625, -43, 728, -392, -398, +434, -56, -30, 302, -491, -281, 735, 182, +-638, 7, 347, -229, -4, 258, -283, 9, +477, -405, -419, 661, 164, -622, 30, 183, +104, 403, -406, -610, 454, 142, -139, 534, +-237, -795, 279, 414, 44, 313, -468, -877, +610, 803, -303, -91, -155, -609, 368, 663, +-255, -141, 131, -366, -131, 544, 58, -373, +139, -45, -210, 497, -7, -596, 202, 275, +-116, 80, -125, -161, 205, 81, -57, -33, +-73, -162, 54, 518, 114, -686, -299, 328, +369, 263, -231, -576, -91, 492, 368, -295, +-359, 216, -12, -249, 459, 325, -572, -238, +198, -76, 371, 363, -648, -212, 487, -225, +-136, 365, -82, -45, 121, -247, -141, 84, +196, 308, -191, -560, 40, 483, 121, -142, +-114, -282, -28, 373, 118, -29, -4, -292, +-215, 154, 337, 219, -199, -206, -169, -275, +543, 809, -677, -855, 446, 256, 58, 631, +-545, -1058, 668, 552, -352, 406, -36, -905, +105, 539, 133, 169, -331, -652, 382, 716, +-426, -480, 481, 38, -319, 424, -132, -623, +593, 497, -745, -222, 482, 67, 8, 15, +-339, -111, 225, 202, 215, -119, -529, -75, +488, 130, -255, -6, 102, -134, -23, 115, +-108, -82, 315, 88, -489, -73, 473, -22, +-210, 78, -153, -42, 386, 41, -367, -133, +206, 238, 38, -188, -308, 17, 447, 144, +-205, -42, -341, -328, 713, 578, -603, -277, +283, -408, -154, 694, 142, -277, 66, -262, +-390, 247, 466, 161, -202, -460, -47, 494, +72, -430, 72, 350, -280, -280, 496, 310, +-534, -281, 261, -24, 141, 455, -340, -503, +288, 38, -103, 435, -99, -384, 233, -148, +-78, 602, -332, -598, 655, 269, -560, -85, +113, 192, 316, -315, -455, 214, 274, 25, +-3, -236, -149, 413, 157, -450, -104, 239, +46, 80, 45, -210, -66, 135, 10, 9, +3, -173, 115, 311, -203, -261, 132, 60, +-34, -87, 72, 367, -207, -434, 256, -17, +-114, 509, -120, -492, 258, 66, -187, 163, +113, 100, -258, -481, 522, 490, -574, -161, +419, 17, -323, -215, 287, 346, -118, -34, +-194, -392, 397, 468, -374, -272, 226, 137, +-94, -90, 128, -61, -341, 151, 545, -9, +-447, -263, 101, 278, 167, 11, -207, -290, +59, 288, 222, -64, -510, -128, 523, 231, +-139, -219, -343, 75, 576, 269, -517, -515, +353, 355, -167, 122, -9, -495, 109, 520, +-62, -353, -187, 59, 471, 265, -497, -453, +108, 183, 361, 341, -456, -618, 174, 369, +93, 183, -118, -543, 20, 508, 130, -105, +-327, -269, 439, 428, -321, -270, 80, 12, +4, 234, 87, -321, -190, 154, 206, 183, +-212, -566, 263, 712, -248, -658, 58, 338, +271, 40, -498, -316, 451, 185, -198, 294, +-16, -701, 23, 666, 131, -144, -288, -332, +308, 511, -176, -329, 11, 165, 64, -65, +-47, 42, 72, -31, -174, 23, 270, -85, +-258, 153, 152, -349, -40, 407, -34, -278, +38, -105, 20, 332, -163, -262, 328, 16, +-364, 138, 210, -93, 35, 83, -176, -40, +172, 45, -119, 82, 103, -89, -99, 23, +96, 70, -141, -29, 261, -23, -387, -167, +355, 314, -61, -165, -345, -396, 527, 576, +-279, -182, -142, -441, 314, 470, -63, 6, +-309, -321, 427, 173, -226, 234, -75, -331, +234, 308, -246, -173, 213, 68, -124, 233, +-54, -441, 169, 347, -4, -10, -300, -257, +360, 73, -23, 290, -380, -666, 481, 648, +-312, -411, 131, -43, -99, 381, 210, -492, +-366, 321, 391, 40, -144, -235, -231, 249, +402, 65, -235, -308, -30, 471, 149, -315, +-116, 19, 39, 307, 100, -430, -288, 156, +317, 290, -65, -665, -260, 477, 302, -53, +-15, -364, -316, 370, 451, -226, -409, 49, +323, 162, -228, -400, 126, 579, 0, -384, +-120, 118, 144, 105, -28, 26, -131, -196, +146, 326, -7, -218, -138, -87, 165, 403, +-128, -583, 86, 420, -49, -267, -10, 129, +113, -139, -211, -8, 138, 75, 187, 89, +-524, -437, 505, 595, -162, -278, -114, -97, +165, 328, -233, -198, 431, 105, -451, -41, +108, 155, 280, -287, -316, 350, 24, -284, +264, 85, -365, -59, 312, 71, -201, -174, +81, 98, -19, -60, -3, -22, 84, 109, +-235, -324, 358, 563, -349, -444, 251, -4, +-119, 514, -6, -344, 83, -287, -30, 887, +-151, -818, 317, 327, -294, 150, 109, -435, +30, 469, -10, -421, -23, 207, -100, -187, +262, 193, -236, -204, 75, 5, -39, 75, +131, 53, -46, -105, -298, -93, 518, 477, +-301, -450, -109, 168, 233, 177, 40, -100, +-389, -180, 498, 500, -335, -560, -6, 209, +408, 318, -713, -719, 726, 511, -442, -110, +96, -192, 50, 11, -2, 274, -64, -468, +61, 434, -71, -160, 108, -120, -85, 310, +2, -102, 46, -43, -94, 28, 259, 288, +-458, -380, 423, 182, -136, 99, -64, -196, +-45, -18, 258, 190, -274, -382, 108, 356, +35, -344, -136, 145, 315, 13, -505, -87, +455, 23, -138, 70, -112, 79, 18, -237, +253, 420, -314, -309, 46, 267, 288, -199, +-397, 216, 264, -109, -66, -101, -53, 296, +47, -498, 51, 430, -200, -292, 327, -28, +-313, 83, 101, -55, 158, -65, -197, 77, +-48, -57, 284, 92, -228, 58, -59, -213, +268, 402, -221, -173, 31, -137, 85, 385, +35, -153, -339, -322, 525, 637, -313, -585, +-177, 135, 533, 186, -533, -442, 325, 344, +-67, -149, -212, -313, 397, 597, -293, -432, +-54, -196, 308, 883, -239, -973, -15, 597, +187, 138, -176, -534, 47, 673, 78, -435, +-106, 129, 66, 238, -76, -516, 110, 411, +-12, -17, -224, -561, 359, 637, -237, -333, +-47, -307, 325, 649, -453, -651, 317, 280, +67, 243, -408, -619, 428, 841, -244, -612, +115, 194, -49, 494, -72, -888, 165, 901, +-25, -412, -229, -218, 311, 640, -129, -713, +-136, 254, 295, 292, -280, -691, 81, 387, +194, 202, -376, -758, 335, 810, -110, -467, +-235, 14, 534, 370, -561, -397, 247, 274, +190, 59, -448, -206, 422, 376, -210, -375, +-38, 204, 183, 308, -191, -923, 105, 1154, +-55, -899, 37, 211, -31, 289, 80, -611, +-180, 634, 146, -564, 88, 149, -269, 580, +116, -1174, 241, 1102, -414, -193, 266, -760, +29, 1281, -257, -1064, 305, 515, -148, 309, +-105, -1032, 241, 1271, -180, -808, 52, -144, +73, 1008, -295, -1616, 581, 1502, -580, -589, +53, -968, 705, 2070, -1152, -1994, 983, 875, +-327, 489, -479, -1419, 1058, 1761, -1084, -1212, +461, -36, 544, 1554, -1411, -2310, 1634, 1955, +-1017, -704, -131, -723, 1120, 1705, -1378, -1934, +848, 1252, 47, -51, -794, -1249, 1074, 1915, +-787, -1733, 56, 721, 751, 613, -1201, -1693, +1040, 2100, -368, -1654, -400, 683, 800, 438, +-603, -1158, 9, 1412, 521, -1169, -646, 591, +353, 268, 110, -1119, -490, 1531, 585, -1369, +-330, 782, -131, -157, 504, -538, -581, 1193, +371, -1625, 21, 1457, -497, -714, 859, -294, +-795, 1265, 243, -1917, 495, 2044, -1015, -1352, +1149, 59, -870, 1407, 169, -2441, 797, 2760, +-1554, -2226, 1611, 870, -897, 939, -200, -2566, +1178, 3183, -1659, -2572, 1520, 997, -838, 754, +-145, -2094, 1095, 2662, -1636, -2385, 1502, 1386, +-713, 56, -383, -1390, 1312, 2172, -1645, -2089, +1200, 1335, -181, -276, -804, -619, 1137, 1105, +-695, -1073, -141, 569, 763, 100, -742, -583, +51, 580, 869, -258, -1352, -194, 1057, 501, +-162, -452, -899, -193, 1760, 1305, -2144, -2190, +1834, 2212, -908, -1176, -264, -451, 1307, 2236, +-2063, -3667, 2417, 4261, -2226, -3502, 1422, 1403, +-136, 1397, -1327, -4008, 2571, 5520, -3121, -5384, +2663, 3442, -1332, -378, -400, -2697, 2085, 4681, +-3372, -5170, 3850, 4226, -3084, -2244, 1142, -148, +1217, 2208, -3030, -3295, 3767, 3418, -3419, -2866, +2243, 1992, -603, -819, -1027, -519, 2199, 1733, +-2675, -2467, 2475, 2585, -1762, -2275, 782, 1640, +220, -797, -1043, -257, 1590, 1249, -1787, -1995, +1573, 2296, -916, -2128, -30, 1497, 958, -637, +-1479, 14, 1412, 200, -892, -256, 260, 641, +284, -1222, -730, 1599, 986, -1534, -810, 1318, +144, -1166, 677, 894, -1194, -337, 1234, -429, +-813, 1078, -60, -1647, 1250, 2170, -2241, -2551, +2376, 2361, -1473, -1434, 44, -1, 1230, 1397, +-1943, -2322, 2075, 2740, -1745, -2745, 1136, 2501, +-453, -1945, -88, 1139, 417, -91, -702, -1093, +1132, 2314, -1652, -3307, 1949, 3663, -1801, -3257, +1226, 2209, -358, -870, -709, -662, 1791, 2104, +-2475, -3141, 2417, 3461, -1680, -3114, 676, 2339, +204, -1249, -767, -1, 1077, 1226, -1300, -2101, +1562, 2594, -1697, -2606, 1333, 2085, -345, -999, +-873, -289, 1733, 1210, -1962, -1483, 1680, 1148, +-1055, -570, 174, -83, 771, 540, -1371, -699, +1277, 492, -617, -149, -103, -91, 451, 201, +-397, -322, 163, 641, 78, -974, -291, 1200, +417, -1157, -363, 1009, 84, -735, 315, 307, +-636, 407, 641, -1350, -212, 2286, -552, -3005, +1346, 3260, -1832, -3073, 1831, 2379, -1359, -1342, +538, 44, 483, 1294, -1517, -2548, 2316, 3548, +-2685, -3950, 2537, 3577, -1964, -2509, 1133, 1367, +-169, -490, -886, -77, 1954, 672, -2839, -1199, +3266, 1359, -3051, -1014, 2241, 405, -1091, 38, +-50, -256, 863, 273, -1241, -282, 1325, 311, +-1439, -547, 1797, 958, -2347, -1462, 2894, 1797, +-3200, -1737, 2948, 1248, -1867, -369, 73, -525, +1878, 1198, -3340, -1454, 3987, 1497, -3777, -1338, +2810, 988, -1381, -481, 6, 57, 876, 108, +-1234, -155, 1228, 178, -1021, -300, 795, 454, +-808, -895, 1150, 1542, -1556, -2126, 1731, 2183, +-1687, -1678, 1595, 979, -1444, -325, 1035, -194, +-233, 721, -831, -1064, 1828, 1211, -2378, -1183, +2349, 1332, -2013, -1731, 1815, 2257, -1873, -2675, +1908, 2693, -1569, -2143, 763, 870, 283, 698, +-1227, -2068, 1851, 2753, -2190, -2997, 2432, 3075, +-2651, -3087, 2726, 2853, -2569, -2310, 2277, 1680, +-1931, -942, 1442, 158, -711, 685, -171, -1207, +983, 1421, -1580, -1438, 1877, 1435, -1827, -1214, +1486, 582, -1055, 213, 669, -856, -269, 1063, +-235, -1062, 754, 834, -1079, -463, 1116, -126, +-918, 657, 586, -880, -225, 753, -79, -418, +282, 183, -414, -36, 538, 76, -685, -178, +839, 440, -929, -606, 881, 531, -661, -160, +316, -251, 76, 451, -446, -577, 738, 691, +-854, -904, 762, 878, -529, -640, 272, 191, +-61, 248, -96, -725, 187, 1246, -229, -1670, +296, 1859, -432, -1667, 547, 1328, -472, -887, +211, 494, 84, 9, -284, -538, 398, 1062, +-449, -1441, 453, 1557, -453, -1461, 518, 1182, +-642, -902, 693, 472, -546, 45, 185, -672, +315, 1088, -838, -1219, 1239, 1117, -1401, -977, +1301, 917, -1028, -818, 696, 689, -371, -377, +17, -8, 406, 541, -855, -954, 1174, 1114, +-1207, -931, 934, 628, -519, -401, 125, 233, +172, -143, -337, 35, 337, 5, -193, -176, +-9, 456, 158, -802, -230, 927, 237, -750, +-197, 395, 127, -42, -53, -125, -32, 201, +161, -129, -302, 18, 362, 186, -248, -291, +11, 254, 238, -53, -440, -178, 643, 296, +-878, -263, 1013, 30, -892, 203, 513, -326, +-61, 108, -279, 255, 489, -532, -627, 414, +713, 42, -730, -579, 701, 996, -698, -1190, +734, 1263, -713, -1136, 501, 921, -75, -629, +-446, 444, 904, -332, -1177, 280, 1212, -236, +-985, 214, 509, -278, 135, 351, -785, -401, +1216, 264, -1275, -72, 1015, -56, -688, -52, +487, 181, -379, -30, 197, -505, 95, 1177, +-402, -1544, 629, 1508, -750, -1080, 701, 471, +-403, 347, -85, -1200, 526, 1917, -733, -2186, +710, 1888, -569, -1120, 356, 110, -59, 809, +-287, -1472, 575, 1647, -688, -1317, 533, 492, +-119, 507, -430, -1362, 916, 1809, -1232, -1776, +1332, 1276, -1123, -295, 513, -977, 361, 2207, +-1095, -2784, 1322, 2410, -1027, -1139, 454, -422, +165, 1713, -746, -2406, 1209, 2500, -1396, -2071, +1197, 1115, -683, 107, 71, -1126, 416, 1389, +-746, -925, 981, 196, -1146, 237, 1141, -283, +-910, 129, 529, 118, -129, -395, -294, 524, +821, -95, -1397, -922, 1801, 2138, -1849, -2843, +1545, 2684, -988, -1653, 262, 49, 520, 1682, +-1161, -2962, 1451, 3243, -1317, -2476, 909, 1065, +-530, 206, 495, -763, -902, 299, 1543, 926, +-2047, -2286, 2137, 3018, -1755, -2661, 990, 1287, +-9, 669, -951, -2477, 1618, 3501, -1814, -3337, +1577, 2165, -1058, -518, 433, -964, 160, 1936, +-654, -2275, 1014, 2057, -1192, -1534, 1097, 977, +-685, -522, 35, -57, 692, 911, -1342, -1885, +1717, 2423, -1589, -2143, 860, 1079, 258, 355, +-1326, -1644, 1895, 2356, -1701, -2134, 699, 1058, +755, 372, -1975, -1349, 2297, 1411, -1586, -578, +251, -623, 1070, 1525, -1859, -1553, 1800, 546, +-902, 1039, -409, -2405, 1488, 2837, -1886, -2277, +1614, 1100, -976, 109, 292, -1000, 239, 1398, +-523, -1342, 570, 958, -415, -427, 110, -112, +308, 563, -712, -732, 885, 427, -625, 464, +-81, -1626, 919, 2470, -1365, -2343, 1045, 1026, +-99, 975, -829, -2574, 1047, 2726, -361, -1296, +-795, -854, 1652, 2350, -1586, -2368, 503, 966, +1084, 965, -2333, -2311, 2558, 2311, -1628, -985, +35, -773, 1376, 1827, -1813, -1559, 1037, 420, +395, 642, -1425, -879, 1249, 331, 53, 485, +-1623, -937, 2400, 710, -1857, 29, 309, -757, +1306, 931, -2112, -542, 1858, 26, -956, 107, +-15, 169, 659, -501, -801, 476, 448, 35, +176, -829, -646, 1491, 689, -1580, -348, 1023, +-139, -135, 567, -478, -800, 521, 752, -170, +-452, -92, 82, -36, 163, 430, -232, -718, +162, 572, -3, -83, -225, -381, 416, 453, +-419, -240, 197, 75, 95, -162, -254, 368, +230, -409, -212, 152, 420, 409, -806, -1020, +973, 1255, -514, -585, -557, -941, 1698, 2523, +-2165, -2980, 1564, 1744, -147, 542, -1277, -2473, +1931, 2870, -1566, -1808, 674, 313, -3, 460, +-70, -286, -154, -237, 51, 317, 670, 254, +-1599, -1027, 1947, 1315, -1215, -784, -337, -199, +1797, 922, -2243, -772, 1389, -157, 204, 1176, +-1505, -1377, 1701, 460, -738, 939, -661, -1670, +1594, 1008, -1648, 616, 1027, -1950, -167, 1912, +-683, -593, 1369, -926, -1644, 1502, 1223, -914, +-187, -143, -888, 762, 1265, -483, -641, -471, +-524, 1463, 1246, -1736, -770, 997, -691, 400, +1973, -1563, -1909, 1791, 402, -989, 1386, -294, +-1993, 1275, 889, -1460, 1084, 881, -2459, -59, +2339, -498, -947, 520, -685, -193, 1597, -135, +-1524, 205, 873, -68, -181, -44, -368, -9, +813, 232, -1047, -469, 786, 557, 21, -350, +-912, -65, 1255, 477, -817, -631, -95, 467, +920, -66, -1193, -398, 814, 645, -116, -458, +-380, -148, 422, 780, -239, -994, 204, 619, +-395, 36, 544, -539, -394, 715, 19, -688, +222, 563, -143, -218, 20, -282, -265, 513, +751, -27, -814, -875, 73, 1327, 978, -724, +-1491, -530, 1103, 1376, -163, -1104, -643, 52, +785, 588, -219, -32, -512, -1163, 668, 1535, +-57, -405, -720, -1287, 868, 1930, -190, -1024, +-729, -349, 1058, 766, -433, -20, -641, -793, +1205, 706, -745, 38, -289, -479, 952, 347, +-715, -204, -159, 430, 941, -656, -996, 465, +220, -102, 847, 14, -1463, -137, 1293, -12, +-602, 519, -198, -849, 876, 455, -1223, 359, +919, -617, 57, -85, -1046, 787, 1174, -223, +-254, -1294, -942, 1980, 1381, -768, -720, -1063, +-429, 1351, 1134, 263, -972, -1831, 294, 1465, +209, 454, -203, -1889, -69, 1594, 177, -373, +-11, -317, -192, 152, 215, 97, -144, 15, +132, -107, -154, -135, 118, 320, -43, -4, +-12, -525, 74, 679, -197, -379, 358, 130, +-506, -189, 558, 245, -288, 25, -408, -416, +1116, 491, -1094, -269, 190, 170, 751, -355, +-753, 411, -137, 38, 877, -742, -637, 1027, +-292, -591, 902, -152, -647, 439, -12, 40, +328, -710, -197, 728, 24, -60, 68, -324, +-311, -133, 581, 618, -381, -40, -210, -1162, +404, 1376, 167, -175, -767, -916, 557, 532, +238, 557, -727, -666, 609, -374, -315, 1019, +169, -311, 3, -848, -289, 1021, 327, -165, +187, -461, -866, 55, 986, 789, -376, -1023, +-331, 492, 434, 131, -26, -287, -172, 114, +-223, -100, 800, 435, -881, -841, 390, 858, +118, -369, -149, -294, -161, 659, 287, -628, +36, 453, -445, -392, 356, 453, 223, -433, +-592, 143, 163, 427, 694, -935, -1026, 1039, +352, -811, 739, 628, -1248, -481, 878, 48, +-268, 547, -2, -730, 141, 475, -530, -344, +813, 342, -392, 90, -401, -664, 594, 281, +4, 935, -554, -1365, 499, 371, -201, 605, +31, -377, 142, -170, -412, -14, 377, 332, +86, 64, -418, -478, 210, 55, 137, 440, +-170, 9, 67, -669, -65, 309, 4, 564, +194, -618, -268, -17, 79, 205, 191, 170, +-328, -259, 251, -225, 51, 660, -386, -511, +393, -89, 40, 587, -546, -599, 711, 349, +-541, -328, 223, 509, 209, -445, -622, 45, +700, 389, -437, -719, 170, 918, -104, -780, +238, 309, -492, 77, 569, -128, -207, 2, +-271, 177, 359, -389, -124, 363, 18, 142, +-217, -822, 464, 1138, -394, -819, -45, -61, +416, 981, -253, -1174, -231, 530, 269, 212, +300, -517, -700, 558, 320, -379, 343, -286, +-454, 1089, 60, -1106, 157, 87, 84, 976, +-335, -1006, 140, 115, 355, 593, -625, -463, +456, 76, -154, -282, 96, 910, -290, -1012, +375, 271, -114, 475, -240, -424, 360, 23, +-397, -211, 519, 740, -478, -565, 187, -183, +-27, 259, 86, 605, -33, -1195, -243, 691, +521, 338, -605, -956, 452, 1003, -244, -846, +187, 603, -137, -87, -109, -491, 316, 618, +-256, -349, 206, 197, -435, -156, 636, -97, +-343, 280, -357, -23, 820, -203, -672, -247, +278, 985, -53, -1049, -73, 174, 205, 858, +-270, -1157, 327, 759, -357, -360, 117, 191, +287, 76, -353, -378, 64, 299, 55, 40, +146, -48, -313, -330, 191, 556, 77, -331, +-243, -27, 232, 133, -155, -112, 131, 260, +-154, -494, 158, 585, -125, -569, 72, 391, +69, 76, -228, -505, 198, 447, 7, -144, +-67, 14, -48, 68, 81, -193, -50, 131, +77, 22, -27, 19, -143, -9, 190, -212, +-122, 150, 136, 383, -178, -744, 127, 476, +-29, 47, -73, -317, 163, 275, -197, -228, +252, 387, -364, -541, 337, 445, -105, -225, +-140, 16, 301, 349, -426, -719, 490, 592, +-428, -19, 194, -316, 101, 153, -207, 115, +172, -194, -264, 70, 379, 99, -208, -90, +-9, -167, -81, 408, 159, -373, 150, 93, +-529, 291, 531, -530, -319, 313, 188, 317, +-53, -713, -227, 460, 391, -4, -173, -52, +-144, -125, 128, 55, 191, 141, -539, -102, +768, 14, -745, -189, 383, 370, 67, -195, +-311, -181, 455, 455, -639, -531, 599, 293, +-153, 224, -300, -538, 336, 283, -185, 286, +157, -619, -57, 431, -267, 203, 441, -749, +-229, 653, -108, -168, 361, 89, -560, -429, +555, 500, -253, -160, -148, -28, 404, -118, +-429, 259, 231, -279, 88, 288, -347, -211, +415, -28, -266, 263, -27, -353, 319, 343, +-500, -318, 524, 312, -373, -294, 175, 162, +-86, 95, -8, -200, 193, -40, -230, 384, +16, -481, 139, 232, 5, 269, -324, -807, +544, 1055, -510, -789, 161, 219, 388, 226, +-818, -335, 797, 189, -289, 33, -335, -253, +721, 427, -821, -352, 603, -107, -28, 617, +-558, -597, 658, 18, -267, 477, -143, -416, +175, -10, 132, 433, -384, -635, 263, 398, +81, 303, -260, -949, 175, 916, -52, -277, +65, -277, -180, 315, 258, -38, -196, -184, +34, 168, 150, 117, -345, -504, 502, 686, +-490, -541, 276, 308, -35, -190, -36, 92, +-131, 145, 393, -372, -532, 294, 453, 12, +-213, -110, -51, -198, 204, 513, -204, -410, +161, 1, -209, 349, 344, -484, -490, 391, +543, -111, -362, -124, -54, 179, 357, -230, +-286, 366, 98, -301, -158, -44, 341, 270, +-337, -151, 248, -101, -272, 228, 301, -151, +-158, -175, -59, 542, 192, -482, -260, -134, +286, 738, -132, -676, -244, -11, 528, 609, +-387, -510, -11, -141, 279, 590, -290, -352, +83, -254, 186, 616, -180, -423, -232, -154, +608, 608, -526, -497, 196, -40, -29, 402, +58, -295, -110, -26, 77, 293, 84, -435, +-289, 266, 334, 275, -165, -734, 41, 671, +-213, -334, 482, 161, -386, 6, -100, -458, +501, 890, -532, -825, 383, 352, -284, 115, +211, -386, -43, 462, -218, -386, 414, 199, +-316, -14, 19, -10, 113, -268, 37, 645, +-216, -660, 219, 299, -110, -58, -44, 88, +258, 56, -467, -531, 512, 880, -335, -785, +43, 413, 183, 98, -280, -659, 284, 896, +-184, -493, -50, -222, 334, 566, -505, -331, +481, -104, -275, 325, -29, -283, 253, 174, +-288, -116, 247, 28, -235, 144, 186, -238, +-54, 34, -24, 433, -66, -813, 284, 685, +-390, -18, 157, -710, 355, 922, -781, -513, +814, -60, -494, 316, 60, -163, 234, -120, +-280, 235, 172, -176, -38, 105, -78, -17, +92, -164, -40, 285, 74, -127, -152, -88, +31, -77, 278, 469, -447, -425, 303, -239, +56, 860, -397, -806, 463, 235, -173, 224, +-188, -287, 274, 166, -54, -130, -169, 132, +125, -33, 99, -64, -233, -14, 204, 172, +-152, -171, 122, 7, -48, 165, -89, -307, +203, 447, -199, -456, 63, 243, 61, 93, +-93, -409, 136, 642, -213, -680, 151, 451, +55, -132, -236, 25, 305, -64, -344, -46, +344, 369, -210, -679, -40, 784, 234, -583, +-273, 65, 208, 529, -161, -730, 178, 420, +-228, 27, 197, -260, -35, 297, -123, -194, +140, -79, -128, 366, 234, -341, -344, -76, +313, 492, -156, -469, -59, 31, 258, 379, +-303, -449, 134, 280, 108, -61, -262, -164, +272, 331, -159, -246, -30, -79, 206, 288, +-246, -134, 146, -196, -24, 358, -32, -298, +95, 128, -193, 135, 191, -477, 38, 687, +-374, -547, 520, 99, -288, 315, -50, -405, +79, 174, 135, 110, -174, -156, -46, -105, +186, 464, -56, -548, -166, 149, 208, 492, +-53, -750, -156, 334, 352, 276, -518, -447, +536, 199, -281, -42, -85, 115, 276, -121, +-210, -77, 49, 238, -12, -185, 172, 58, +-359, -103, 408, 229, -269, -144, 1, -192, +205, 421, -105, -286, -229, -14, 407, 219, +-296, -322, 84, 348, 137, -173, -405, -164, +604, 377, -519, -266, 65, -56, 510, 349, +-700, -425, 304, 154, 274, 301, -465, -518, +176, 281, 248, 104, -425, -275, 260, 218, +72, -62, -316, -182, 308, 396, -5, -352, +-396, 72, 562, 153, -397, -133, 44, 18, +279, 28, -369, -24, 166, 79, 103, -185, +-203, 231, 147, -174, -16, 105, -109, -77, +57, -58, 233, 376, -490, -600, 364, 476, +55, -181, -315, 23, 197, 19, 53, -128, +-146, 247, 74, -219, 55, 152, -242, -181, +404, 212, -406, -101, 213, -25, 41, 21, +-219, 16, 193, 80, 11, -225, -236, 259, +294, -189, -140, 148, -127, -138, 310, 28, +-294, 179, 183, -226, -124, -55, 106, 457, +-79, -556, 83, 249, -98, 121, 61, -232, +80, 141, -226, -61, 297, 27, -304, 47, +323, -92, -258, -36, 68, 279, 117, -448, +-124, 444, 37, -271, -13, -62, 58, 407, +-74, -455, 37, 144, -35, 101, 77, 80, +-112, -406, 88, 357, -120, 37, 147, -310, +-27, 283, -239, -221, 288, 242, -23, -173, +-298, -23, 279, 74, 10, 161, -327, -443, +509, 428, -580, -103, 429, -290, 23, 497, +-555, -411, 773, 102, -525, 123, 126, 35, +117, -461, -111, 642, 98, -280, -110, -320, +121, 660, 21, -600, -128, 274, 163, 126, +-14, -369, -164, 234, 357, 141, -382, -296, +253, 7, 51, 404, -317, -493, 389, 277, +-243, -84, 84, 30, 1, 61, -77, -275, +73, 446, 26, -361, -206, 63, 197, 250, +-79, -383, -90, 267, 49, 59, -3, -363, +-22, 333, -70, 68, 61, -491, -104, 516, +130, -163, -167, -156, 48, 162, 29, -28, +-11, 89, -145, -311, 197, 395, -28, -204, +-202, -23, 220, 58, 74, 46, -303, -136, +338, 161, -130, -120, -8, -9, 141, 160, +-101, -218, 96, 159, 24, -102, -37, 94, +30, -75, 205, 9, -382, 66, 400, -124, +-83, 215, -256, -314, 425, 288, -263, -72, +-54, -155, 254, 185, -205, -56, -55, 10, +241, -138, -323, 251, 194, -160, -93, -80, +-91, 233, 138, -158, -196, -9, 47, 66, +-34, -19, 84, 49, -265, -176, 143, 133, +104, 214, -351, -545, 214, 447, 107, 30, +-344, -421, 188, 416, 186, -138, -382, -133, +285, 219, -20, -99, -117, -104, 206, 228, +-158, -229, 228, 179, -251, -149, 376, 98, +-330, 6, 279, -71, 17, 19, -244, 54, +422, -41, -234, 24, -66, -123, 395, 215, +-368, -57, 85, -304, 233, 510, -245, -341, +17, 6, 157, 148, -171, -24, -1, -185, +112, 258, -190, -157, 106, -17, -129, 164, +63, -276, -41, 354, -132, -328, 127, 133, +-82, 118, -140, -232, 200, 149, -178, -11, +-44, -22, 147, -70, -170, 236, 83, -350, +-77, 277, 141, -2, -159, -311, 64, 481, +126, -484, -158, 346, 134, -70, -46, -228, +102, 316, -56, -125, 69, -103, 12, 125, +68, -32, -56, 35, 45, -107, 229, 56, +-448, 117, 523, -221, -206, 154, -141, 8, +290, -174, -101, 285, -136, -254, 167, 24, +33, 252, -295, -343, 326, 195, -221, 11, +11, -146, 64, 240, -204, -292, 218, 170, +-178, 127, -120, -327, 228, 190, -112, 131, +-280, -238, 351, 8, -136, 301, -238, -366, +295, 162, -104, 66, -173, -116, 238, 29, +-122, 45, -1, -79, 65, 159, -73, -224, +139, 108, -108, 191, 97, -412, 11, 370, +14, -194, -24, 105, 164, -117, -88, 111, +-61, -56, 305, 11, -212, 7, 6, -27, +182, 16, -28, 67, -163, -136, 221, 51, +-53, 123, -80, -158, 58, 24, 42, 41, +-139, 91, 117, -250, -63, 231, -87, -130, +124, 130, -203, -177, 162, 85, -176, 126, +11, -233, 94, 129, -247, 45, 188, -86, +-204, -30, 226, 200, -378, -306, 287, 304, +-20, -186, -319, 19, 387, 75, -249, -36, +95, -11, -77, -105, 200, 326, -255, -411, +256, 243, -106, 0, 28, -93, 118, 13, +-159, 66, 296, -55, -225, 25, 89, -49, +190, 12, -110, 236, -161, -572, 491, 641, +-395, -271, 107, -273, 246, 604, -392, -588, +402, 345, -208, 9, -110, -354, 358, 468, +-309, -220, -63, -206, 355, 420, -441, -279, +253, 0, -120, 203, -117, -343, 240, 468, +-346, -420, 139, 64, 55, 388, -282, -533, +211, 273, -56, 93, -281, -284, 442, 239, +-364, -22, -126, -274, 589, 446, -733, -295, +464, -82, -87, 366, -176, -410, 302, 361, +-191, -291, -61, 48, 359, 410, -239, -720, +-202, 517, 773, 101, -821, -654, 477, 825, +171, -634, -553, 210, 736, 331, -513, -764, +207, 801, 209, -414, -393, -117, 435, 466, +-251, -547, 54, 455, 102, -265, -109, 17, +-4, 231, 143, -390, -241, 382, 133, -164, +49, -193, -305, 510, 335, -520, -285, 86, +104, 646, -143, -1276, 214, 1368, -356, -761, +205, -270, 16, 1170, -397, -1486, 631, 1140, +-713, -354, 335, -596, 297, 1369, -891, -1546, +918, 876, -361, 412, -445, -1626, 1002, 2078, +-990, -1522, 455, 254, 410, 1089, -1046, -1848, +1156, 1651, -545, -622, -282, -710, 1015, 1691, +-1164, -1871, 853, 1150, -69, 163, -675, -1462, +1172, 2084, -1011, -1708, 394, 583, 443, 690, +-923, -1562, 892, 1767, -342, -1297, -325, 378, +721, 632, -647, -1361, 276, 1628, 39, -1411, +-213, 780, 198, 135, -92, -1009, -206, 1440, +421, -1249, -405, 684, -104, -130, 703, -260, +-1025, 593, 622, -956, 179, 1202, -982, -1089, +1195, 508, -838, 423, 53, -1381, 697, 1956, +-1212, -1810, 1252, 897, -793, 465, -63, -1734, +925, 2401, -1409, -2158, 1374, 1080, -884, 403, +199, -1708, 581, 2379, -1234, -2231, 1645, 1350, +-1477, -52, 743, -1171, 414, 1842, -1341, -1751, +1614, 1069, -983, -177, -22, -558, 793, 960, +-826, -994, 337, 746, 320, -389, -636, 45, +454, 186, 172, -226, -899, 57, 1316, 187, +-1107, -248, 227, -87, 986, 810, -2054, -1635, +2367, 2075, -1688, -1644, 134, 239, 1517, 1629, +-2586, -3124, 2658, 3617, -1973, -2981, 763, 1409, +581, 755, -1805, -2957, 2484, 4436, -2567, -4591, +2113, 3332, -1309, -1041, 85, -1647, 1416, 3952, +-2777, -5055, 3449, 4502, -3145, -2615, 1907, 293, +22, 1645, -2057, -2866, 3503, 3350, -3764, -3102, +2854, 2247, -1152, -1151, -616, 168, 2018, 662, +-2683, -1495, 2594, 2248, -1775, -2562, 683, 2220, +309, -1398, -909, 436, 1223, 492, -1303, -1282, +1251, 1785, -1054, -1865, 690, 1564, -41, -1041, +-794, 482, 1396, -53, -1334, -161, 598, 253, +298, -486, -866, 1003, 855, -1612, -450, 1922, +-171, -1709, 735, 1074, -1156, -298, 1223, -428, +-922, 1057, 183, -1604, 739, 2042, -1615, -2277, +2012, 2171, -1762, -1620, 885, 599, 221, 718, +-1181, -1979, 1704, 2780, -1772, -2900, 1484, 2476, +-996, -1796, 393, 1008, 298, -61, -836, -1051, +1069, 2084, -1018, -2755, 1043, 2983, -1165, -2796, +1203, 2184, -779, -1137, -43, -143, 1045, 1332, +-1751, -2200, 2020, 2697, -1763, -2783, 1135, 2338, +-197, -1360, -748, 157, 1465, 887, -1791, -1584, +1767, 1922, -1385, -1863, 743, 1329, -70, -434, +-497, -499, 970, 1125, -1371, -1252, 1421, 869, +-1035, -148, 332, -595, 280, 1112, -721, -1370, +870, 1455, -779, -1355, 344, 960, 193, -288, +-612, -457, 581, 1074, -187, -1588, -316, 2044, +562, -2368, -492, 2416, 105, -2231, 467, 1935, +-1007, -1480, 1174, 676, -810, 461, 86, -1625, +796, 2470, -1544, -2854, 1893, 2798, -1577, -2351, +821, 1621, 117, -811, -946, 47, 1721, 643, +-2322, -1204, 2678, 1436, -2528, -1189, 1932, 562, +-984, 169, -20, -802, 1061, 1302, -1994, -1639, +2709, 1712, -2999, -1468, 2857, 1042, -2343, -645, +1566, 409, -759, -310, 76, 234, 408, -34, +-845, -382, 1312, 945, -1869, -1446, 2391, 1672, +-2731, -1548, 2647, 1117, -2113, -504, 1068, -131, +241, 635, -1626, -949, 2585, 1128, -2969, -1238, +2636, 1268, -1794, -1179, 754, 1000, -15, -812, +-156, 654, -74, -486, 380, 275, -539, -57, +493, -191, -143, 547, -557, -1069, 1395, 1649, +-2083, -2064, 2438, 2174, -2419, -2032, 2234, 1812, +-1875, -1610, 1443, 1391, -745, -1076, 33, 595, +624, 75, -1142, -912, 1605, 1831, -1988, -2651, +2194, 3186, -2290, -3295, 2291, 2978, -2151, -2336, +1901, 1500, -1505, -598, 1050, -220, -409, 738, +-257, -831, 753, 626, -989, -406, 925, 337, +-841, -334, 679, 240, -607, -35, 427, -197, +-160, 420, -258, -648, 767, 803, -1102, -697, +1103, 253, -690, 369, 124, -904, 299, 1195, +-585, -1212, 669, 930, -709, -383, 518, -210, +-288, 531, 147, -416, -178, 44, 334, 255, +-243, -232, -8, -94, 399, 511, -554, -754, +467, 704, -260, -470, 14, 257, 83, -146, +-130, 12, 84, 303, -65, -752, 152, 1156, +-192, -1389, 326, 1458, -337, -1392, 345, 1163, +-175, -723, -122, 103, 460, 582, -829, -1200, +928, 1595, -881, -1675, 618, 1500, -397, -1238, +267, 983, -137, -670, 79, 179, 108, 457, +-315, -1050, 612, 1430, -890, -1586, 1051, 1570, +-1241, -1390, 1209, 1052, -1072, -599, 618, 102, +-59, 367, -443, -715, 760, 856, -736, -766, +679, 568, -579, -427, 610, 384, -570, -352, +322, 209, 0, 77, -378, -406, 471, 611, +-368, -565, 70, 312, 254, -65, -419, 72, +548, -350, -470, 666, 407, -773, -183, 607, +-118, -302, 434, -13, -687, 244, 662, -337, +-581, 263, 381, -66, -160, -129, -165, 242, +588, -227, -851, 69, 1051, 196, -1079, -466, +1076, 622, -887, -640, 470, 556, -65, -372, +-315, 80, 516, 250, -795, -453, 1007, 426, +-1034, -296, 833, 282, -451, -433, 144, 586, +176, -540, -393, 221, 546, 305, -685, -890, +803, 1334, -987, -1463, 964, 1240, -738, -797, +244, 303, 367, 132, -922, -471, 1349, 702, +-1387, -854, 1098, 1046, -530, -1316, -29, 1513, +487, -1361, -909, 759, 1157, 153, -1205, -1061, +987, 1661, -749, -1772, 606, 1376, -427, -632, +131, -220, 361, 987, -818, -1534, 1199, 1739, +-1353, -1495, 1187, 854, -739, -52, 128, -635, +338, 1073, -649, -1206, 766, 954, -650, -320, +241, -441, 329, 905, -617, -801, 449, 218, +59, 502, -506, -1024, 644, 1142, -517, -783, +197, 45, 128, 777, -388, -1317, 439, 1376, +-311, -1033, 165, 523, -145, -63, 313, -217, +-501, 306, 504, -309, -104, 433, -746, -836, +1803, 1406, -2622, -1825, 2772, 1724, -2185, -1048, +1130, 80, -63, 708, -622, -1014, 874, 891, +-861, -657, 878, 613, -989, -805, 1145, 965, +-1193, -797, 1019, 212, -636, 540, 185, -1011, +34, 826, 188, 37, -729, -1130, 1154, 1786, +-991, -1559, 216, 548, 853, 679, -1743, -1502, +2161, 1610, -2043, -1142, 1520, 549, -905, -259, +420, 356, -55, -489, -394, 180, 1035, 642, +-1621, -1450, 1786, 1501, -1290, -525, 240, -969, +970, 2064, -1840, -2065, 1889, 951, -1054, 697, +-281, -2038, 1362, 2459, -1699, -1897, 1299, 871, +-578, -39, -60, -308, 501, 438, -793, -810, +1016, 1499, -1110, -2024, 914, 1791, -379, -728, +-326, -586, 790, 1341, -755, -1145, 315, 348, +86, 197, 20, 176, -650, -1331, 1351, 2361, +-1476, -2314, 850, 1050, 34, 629, -408, -1617, +-87, 1434, 956, -527, -1328, -187, 717, 129, +455, 526, -1326, -1021, 1358, 753, -699, 184, +57, -1075, 39, 1185, 441, -380, -970, -727, +983, 1251, -402, -774, -297, -268, 447, 903, +99, -503, -894, -610, 1240, 1515, -888, -1554, +245, 825, 156, 59, -144, -555, 87, 498, +-338, -87, 806, -234, -1091, 61, 857, 688, +-314, -1563, -84, 1897, -1, -1350, 355, 212, +-429, 823, -148, -1223, 1199, 947, -1939, -402, +1694, 16, -469, 70, -923, 30, 1507, -112, +-1001, 15, 3, 282, 546, -637, -268, 762, +-427, -484, 787, -40, -485, 447, -116, -486, +461, 227, -298, 33, -36, -44, 122, -251, +112, 673, -362, -923, 361, 787, -231, -334, +253, -146, -495, 390, 657, -331, -384, 61, +-285, 287, 876, -588, -762, 690, -118, -514, +1068, 91, -1154, 445, 100, -884, 1295, 1002, +-1854, -710, 1099, 166, 277, 277, -1165, -334, +1081, 58, -509, 200, 196, -88, -334, -348, +424, 643, 29, -308, -902, -635, 1505, 1546, +-1238, -1719, 211, 968, 800, 228, -1028, -1119, +460, 1207, 187, -636, -161, 74, -545, -155, +1163, 797, -923, -1148, -235, 488, 1518, 883, +-1971, -1812, 1355, 1463, -224, -258, -588, -592, +794, 350, -619, 501, 425, -835, -287, 95, +108, 1099, 28, -1562, 70, 831, -490, 363, +893, -899, -810, 531, 106, -65, 830, 358, +-1337, -1300, 1207, 1854, -728, -1186, 421, -374, +-480, 1570, 598, -1458, -364, 375, -353, 425, +1118, -131, -1392, -796, 884, 1237, 119, -642, +-937, -448, 1013, 1107, -298, -953, -555, 343, +839, 132, -350, -210, -460, 62, 855, 9, +-539, 113, -251, -299, 861, 379, -902, -324, +510, 217, -116, -91, 34, -34, -114, 60, +137, 107, 8, -311, -208, 249, 352, 154, +-544, -512, 815, 428, -1063, -34, 942, -125, +-356, -217, -314, 623, 545, -490, -193, -134, +-183, 492, 73, -37, 452, -714, -708, 645, +286, 495, 376, -1510, -563, 1099, 19, 467, +573, -1518, -477, 985, -296, 360, 890, -911, +-508, 201, -531, 627, 1216, -421, -798, -512, +-289, 821, 1026, 10, -905, -908, 244, 607, +226, 646, -280, -1391, 211, 842, -407, 199, +771, -482, -799, -107, 333, 587, 269, -335, +-429, -133, 75, -1, 387, 664, -531, -1039, +303, 670, -53, 17, 8, -383, -83, 352, +5, -292, 255, 385, -415, -438, 281, 306, +80, -174, -271, 255, -8, -429, 596, 476, +-943, -423, 691, 475, -228, -554, 84, 340, +-237, 242, 130, -758, 418, 750, -869, -372, +646, 264, 136, -647, -692, 871, 438, -275, +382, -712, -923, 892, 691, 85, -79, -1068, +-245, 758, 143, 600, -19, -1441, 156, 777, +-345, 539, 284, -936, 66, 110, -396, 598, +448, -4, -299, -1330, 210, 1848, -265, -927, +324, -389, -286, 697, 137, 107, 218, -791, +-722, 315, 933, 887, -512, -1425, -174, 705, +441, 394, -186, -763, 41, 368, -392, -23, +816, 137, -655, -261, -71, -51, 634, 475, +-513, -377, 89, -192, -144, 547, 633, -375, +-668, 164, -203, -262, 1106, 240, -959, 347, +-29, -983, 611, 745, -179, 256, -483, -784, +398, 84, 299, 990, -633, -1046, 197, 38, +299, 759, -104, -588, -543, 89, 803, -84, +-411, 329, -135, -169, 387, -274, -375, 360, +281, -28, -107, -98, -106, -281, 179, 687, +-5, -557, -246, 26, 288, 355, -79, -391, +-169, 322, 233, -240, -100, -74, -48, 522, +46, -545, 99, 23, -243, 375, 278, -132, +-114, -310, -141, 183, 253, 424, -169, -733, +140, 406, -371, 115, 505, -401, -110, 536, +-546, -686, 770, 630, -383, -260, 16, -86, +-66, 81, 273, 43, -220, -12, -113, 43, +475, -285, -707, 274, 654, 305, -263, -847, +-240, 597, 422, 159, -167, -519, -92, 306, +-93, -97, 589, 173, -698, -213, 142, 28, +430, 74, -246, 122, -440, -297, 601, 55, +70, 391, -709, -482, 491, 131, 231, 156, +-453, 48, -72, -523, 610, 614, -415, -64, +-178, -559, 287, 508, 159, -13, -343, 56, +-182, -673, 724, 760, -639, -57, 226, -173, +-62, -580, 99, 955, 39, -72, -303, -912, +477, 842, -462, -431, 239, 654, 111, -1031, +-291, 714, 120, 29, 18, -458, 241, 399, +-619, -95, 554, -161, -46, 149, -404, 63, +467, -96, -239, -132, 61, 246, -125, 43, +208, -605, -3, 999, -363, -657, 425, -368, +-157, 927, -4, -156, -104, -945, 206, 841, +-178, 193, 201, -672, -232, 242, 100, 247, +81, -377, -92, 427, 26, -468, -124, 220, +338, 347, -374, -823, 66, 623, 450, 153, +-696, -482, 373, -337, 143, 1359, -197, -1146, +-82, -70, -10, 730, 504, -332, -608, -127, +-10, -65, 665, 532, -707, -813, 264, 896, +177, -688, -391, 44, 405, 712, -336, -949, +246, 552, -87, -51, -79, -58, 48, -143, +95, 140, 66, 307, -547, -725, 743, 538, +-348, 16, -127, -279, 257, 225, -260, -367, +402, 725, -468, -741, 195, 249, 250, 276, +-535, -384, 511, 219, -256, -229, 13, 455, +19, -463, 38, 171, 75, -47, -292, 143, +410, 141, -432, -893, 448, 1215, -348, -580, +86, -286, 88, 478, -90, -124, 174, 12, +-491, -376, 773, 674, -732, -459, 406, 29, +-4, 104, -333, 1, 525, 78, -556, -359, +470, 463, -357, -323, 276, 205, -201, -120, +19, -152, 282, 404, -454, -190, 312, -246, +-61, 153, 47, 436, -219, -693, 279, 393, +-167, -124, -15, 87, 247, 110, -505, -453, +578, 538, -358, -321, 70, 17, 95, 235, +-101, -269, 38, -33, -26, 314, 204, -157, +-464, -225, 461, 309, -81, -42, -367, -244, +496, 310, -253, -95, -102, -324, 249, 588, +-93, -341, -103, -239, 103, 512, -61, -271, +211, 31, -315, -211, -16, 403, 568, -106, +-821, -429, 649, 676, -372, -615, 151, 441, +13, -146, -109, -196, 227, 290, -472, -145, +639, 35, -448, -142, 52, 454, 140, -782, +-222, 723, 420, -122, -573, -462, 339, 438, +62, -57, -255, -54, 245, -178, -229, 411, +145, -492, -25, 434, 51, -238, -204, 60, +126, -77, 129, 117, -201, 53, 2, -233, +85, 108, 28, 69, -102, 123, -1, -511, +76, 571, -43, -192, -60, -292, 76, 484, +55, -126, -337, -597, 426, 978, -154, -584, +-258, -139, 331, 513, -185, -397, 157, 58, +-327, 150, 324, 116, -83, -728, -207, 932, +301, -366, -281, -281, 129, 280, 48, 158, +-222, -361, 240, 86, -179, 357, 119, -485, +-246, 19, 461, 694, -515, -939, 139, 423, +351, 315, -521, -560, 219, 255, 46, -38, +27, 377, -384, -931, 541, 957, -386, -243, +-3, -609, 242, 882, -264, -448, 152, -210, +-213, 523, 299, -320, -202, -85, -223, 258, +557, -40, -592, -361, 330, 566, -157, -376, +95, -44, -180, 358, 222, -402, -243, 365, +72, -499, 176, 718, -410, -646, 327, 183, +-60, 278, -206, -405, 119, 353, 128, -352, +-316, 342, 167, -280, 69, 298, -198, -415, +76, 377, 5, -80, -43, -265, 16, 408, +-61, -285, -65, 63, 295, -60, -491, 334, +280, -494, 102, 202, -392, 300, 239, -470, +40, 189, -193, 247, -39, -486, 263, 326, +-199, 186, -280, -647, 606, 581, -534, -9, +107, -493, 102, 434, -99, 98, 7, -572, +-119, 552, 186, -114, -199, -225, 87, 116, +-76, 192, 34, -215, -95, -119, 147, 484, +-234, -602, 89, 408, 146, -69, -431, -91, +529, -86, -523, 268, 223, -124, 112, -109, +-284, 111, 34, -47, 119, 159, 70, -243, +-468, 77, 446, 98, -186, -31, 31, -122, +-221, 120, 270, 1, -122, -81, -153, 19, +190, 180, -123, -387, -32, 416, -9, -247, +91, 39, -123, 100, -152, -188, 369, 226, +-369, -194, 123, 121, -54, -40, 2, -54, +94, 139, -292, -120, 211, 41, -34, -118, +-93, 388, 18, -520, -98, 199, 209, 362, +-248, -566, -15, 217, 220, 219, -267, -277, +103, 108, -114, -140, 255, 303, -422, -197, +260, -138, 16, 156, -188, 293, -18, -610, +260, 266, -317, 425, -34, -745, 425, 478, +-576, -24, 188, -213, 289, 192, -438, -32, +70, -170, 251, 254, -280, -102, 43, -162, +78, 264, -180, -124, 184, -110, -106, 286, +-145, -311, 209, 130, -61, 135, -193, -199, +181, -20, 35, 221, -347, -183, 433, 11, +-300, 103, -3, -205, 135, 354, -171, -413, +161, 266, -210, 12, 105, -299, 20, 527, +-42, -597, -106, 424, 66, -99, 154, -161, +-384, 187, 311, -23, -90, -83, -182, -115, +312, 461, -292, -513, 96, 128, 66, 255, +-109, -248, 20, -28, 66, 183, -164, -102, +126, -109, 19, 269, -152, -261, 34, -13, +214, 365, -364, -532, 319, 359, -197, -10, +89, -278, 0, 274, -3, -103, -98, -35, +178, -11, -148, 55, -2, -77, 147, 157, +-183, -334, 55, 292, 165, 28, -180, -388, +16, 392, 187, -157, -177, -144, 103, 327, +-73, -429, 47, 333, 119, -131, -289, -128, +279, 171, -1, 4, -213, -317, 305, 304, +-150, 36, 72, -448, 45, 437, -92, -240, +228, 118, -244, -278, 178, 289, -3, -56, +-24, -391, -18, 534, 205, -370, -149, 0, +51, 70, 158, 40, 34, -192, -271, 28, +372, 134, 110, -178, -611, -109, 751, 270, +-263, -270, -136, 15, 257, 9, 104, 42, +-191, -112, 171, -186, 184, 398, -196, -407, +191, 43, 28, 82, 4, -108, 45, 44, +11, -242, 125, 169, 0, 19, -37, -235, +261, -93, 0, 406, -162, -476, 465, -10, +-172, 253, -65, -245, 371, -97, -179, 108, +77, -92, 134, -155, -33, 306, 199, -642, +-97, 532, 237, -170, -15, -422, 185, 386, +-67, -99, 152, -257, 174, 0, -159, 201, +195, -324, 101, 20, 6, 16, 6, -133, +294, 102, -69, -298, 74, 65, 296, 129, +-79, -304, 10, -128, 451, 384, -326, -507, +251, 147, 65, -79, 183, -81, -135, 84, +145, -428, 369, 441, -215, -403, 160, -18, +301, 97, -49, -171, 56, -92, 220, 18, +10, 27, 35, -435, 238, 512, -97, -509, +244, -70, 1, 369, 226, -437, -4, -145, +159, 290, 216, -40, -163, -778, 495, 953, +-292, -647, 220, -190, 285, 445, -202, -430, +138, 26, 351, -70, -135, 88, 108, -371, +311, 292, 13, -238, -43, -278, 425, 537, +-133, -656, 86, 119, 226, 119, 26, -156, +57, -246, 74, 56, 296, 315, -127, -831, +264, 585, 62, -200, 117, -318, 258, 245, +-303, -215, 570, 65, -110, -334, -108, 375, +419, -461, -61, 106, 73, 85, 116, -370, +207, 198, 4, -147, 167, -12, 75, -208, +150, 172, 35, -198, 120, -32, 62, -59, +161, 17, -89, -157, 264, 31, 96, -70, +-110, -158, 339, 189, 88, -290, -97, 19, +274, 47, 91, -128, 1, -101, 93, 16, +170, 51, -52, -319, 166, 236, 123, -197, +-93, -73, 330, 107, 43, -193, -198, -53, +564, 138, -195, -203, 2, -141, 355, 257, +-91, -281, -22, -32, 269, 67, -10, -81, +53, -118, 84, 44, 160, -26, 43, -162, +-16, 116, 283, -201, 10, 162, -154, -303, +470, 166, -225, 40, 16, -478, 384, 529, +-196, -356, 83, -51, 166, 13, 121, 169, +-121, -392, 286, 178, -61, -54, 144, -21, +24, -117, -14, -35, 201, 179, 16, -314, +-20, 108, 31, -28, 325, -52, -188, 13, +-35, -259, 573, 423, -480, -434, 212, -33, +320, 415, -288, -582, 228, 253, 23, 29, +63, -197, 23, 8, -21, 86, 293, -112, +-171, -98, 111, 138, 150, -146, -75, 10, +190, -39, -157, -42, 369, 67, -250, -152, +68, 9, 325, 18, -303, 26, 247, -258, +47, 204, 44, 15, -165, -344, 455, 294, +-284, -78, 160, -215, 77, 172, -24, -57, +103, -114, -103, 30, 308, 46, -241, -185, +258, 181, -167, -254, 257, 223, -101, -198, +97, 9, 29, 66, 53, -93, -20, -4, +39, -85, 153, 184, -141, -239, 162, -1, +-19, 157, 18, -123, 55, -138, 77, 130, +-7, 95, 27, -358, 24, 200, 96, 100, +-70, -261, 98, -16, 74, 271, -129, -237, +107, -178, 157, 408, -237, -312, 240, -39, +49, 154, -203, -85, 227, -55, -9, -26, +0, 125, -52, -194, 236, 117, -266, -105, +218, 89, -23, -130, -18, 74, 131, 7, +-228, -190, 385, 285, -327, -262, 172, 46, +132, 94, -201, -115, 131, 31, -64, -86, +245, 172, -415, -185, 459, 39, -180, 13, +-135, 58, 264, -133, -80, -21, -46, 214, +21, -232, 211, 50, -414, 28, 425, 59, +-185, -134, -41, -10, 169, 227, -179, -311, +144, 233, -117, -152, 180, 129, -250, -136, +299, 134, -247, -71, 11, -74, 278, 257, +-374, -340, 257, 252, -72, -99, -31, 65, +-54, -135, 176, 208, -164, -150, -14, 39, +175, 94, -249, -186, 162, 258, -58, -210, +21, 107, -56, -10, 7, 29, 65, -33, +-172, 17, 184, 31, -91, 4, -122, 29, +220, -126, -216, 250, 55, -146, 72, -63, +-111, 237, -26, -140, 77, -23, -56, 165, +-85, -115, 129, 9, -88, 166, -117, -164, +184, 36, -172, 221, 19, -273, 65, 174, +-139, 17, 88, 17, -151, -79, 180, 93, +-196, 113, -6, -224, 191, 261, -382, -135, +273, 79, -88, 77, -197, -171, 283, 269, +-325, -145, 177, 24, -110, 107, 7, -44, +-30, 41, -63, -11, 63, 124, -165, -124, +80, 133, -52, 27, -74, -87, 1, 148, +-15, 17, -106, -143, 110, 305, -243, -218, +226, 126, -264, 35, 67, 25, 8, -37, +-180, 86, 143, 50, -222, -66, 141, 121, +-243, -47, 158, 116, -166, -42, -19, 9, +-1, 153, -108, -102, 22, 83, -132, 46, +38, 13, -101, 27, -33, 30, -90, 47, +36, 19, -172, 36, 49, 27, -44, 37, +-256, 34, 303, 24, -387, 67, 5, -78, +199, 261, -417, -221, 60, 100, 130, 278, +-363, -349, 28, 250, 174, 117, -510, -178, +326, 160, -282, 42, 7, 59, -145, -157, +57, 394, -203, -337, -87, 261, 110, 54, +-372, -167, 193, 293, -277, -157, 36, 217, +-140, -205, -110, 283, 31, -1, -210, -191, +-87, 373, 20, -179, -166, 138, -158, -52, +39, 125, -148, 48, -140, -4, -87, -4, +-26, 111, -136, 220, -159, -447, -45, 479, +-25, 74, -303, -390, 106, 390, -253, 105, +-60, -260, -2, 236, -383, 107, 153, -163, +-141, 251, -287, -54, 6, -15, -14, 192, +-261, 31, -194, -228, 214, 471, -439, -213, +-37, -11, 14, 251, -272, -68, -85, 33, +-68, 38, -124, 195, -242, -194, 45, 260, +-205, -45, -155, -8, -57, 209, -141, -120, +-164, 102, -91, 169, -154, -214, -42, 337, +-305, -158, 96, 121, -294, 96, -45, -75, +-163, 166, -81, -9, -121, 51, -260, 46, +47, 41, -144, 139, -347, -133, 132, 176, +-171, 95, -311, -91, 54, 71, -122, 201, +-246, -145, -50, 132, -54, 59, -341, 25, +135, 47, -253, 57, -276, 1, 232, 118, +-383, 58, -204, -175, 186, 402, -313, -186, +-194, -18, 26, 261, -51, -55, -430, -53, +188, 166, -184, 68, -294, -86, 95, 98, +-194, 134, -153, -84, -139, 57, 68, 161, +-343, -87, -56, 88, 66, 73, -348, -16, +-37, 98, 3, 10, -242, 18, -139, 104, +64, -1, -263, 41, -123, 34, 51, 89, +-248, 42, -114, -128, 34, 320, -230, -127, +-99, -68, -13, 335, -189, -207, -95, 84, +-56, 152, -120, -123, -149, 182, -16, -75, +-127, 95, -185, 28, 101, 64, -293, -67, +-10, 132, -49, 118, -175, -263, -86, 358, +-42, -117, -45, 35, -371, -10, 354, 223, +-483, -186, 101, 131, -135, 68, -12, -40, +-221, 90, -11, -46, -24, 148, -220, -86, +27, 120, -182, -51, 37, 101, -178, 26, +-87, -102, 7, 271, -163, -232, -6, 241, +-232, -124, 159, 120, -273, 25, -80, -65, +104, 204, -351, -192, 194, 267, -332, -193, +132, 186, -221, -51, -4, 48, -71, 46, +-192, -61, 144, 221, -291, -245, 30, 266, +-84, -123, -61, 94, -130, 30, -61, -115, +18, 292, -193, -236, -26, 122, -49, 38, +-77, 56, -85, -62, -125, -43, 65, 328, +-153, -311, -170, 117, 142, 115, -216, 17, +-75, -156, 12, 164, -156, 80, 56, -77, +-280, -110, 169, 355, -197, -241, -104, 24, +93, 178, -291, -153, 182, 167, -285, -138, +51, 151, -115, -43, 10, 64, -210, -90, +53, 127, -61, 56, -169, -180, 23, 198, +-82, 21, -97, -146, -13, 194, -140, -84, +15, 27, -67, 70, -170, -88, 70, 145, +-120, -91, -90, 77, -10, -15, -64, 23, +-144, 39, 115, -41, -278, 94, 50, -69, +20, 114, -220, -92, -38, 85, 128, 8, +-268, -48, -27, 139, 85, -179, -164, 245, +-120, -187, 112, 141, -160, -87, -60, 144, +-36, -109, 17, 20, -201, 176, 62, -261, +-26, 294, -231, -203, 204, 140, -257, -33, +54, -5, -76, 48, -20, -20, -106, 86, +-9, -120, -12, 117, -133, 51, -2, -134, +20, 77, -164, 143, 34, -202, -29, 85, +-95, 140, 16, -192, -93, 129, 47, -10, +-161, 30, 84, -77, -96, 130, -48, -91, +41, 45, -157, 71, 125, -149, -213, 196, +128, -106, -78, 19, -156, 23, 236, 57, +-293, -77, 111, -26, -30, 266, -48, -358, +-93, 184, 140, 215, -168, -474, -34, 411, +160, -85, -231, -124, 59, 79, 27, 118, +-33, -159, -155, 3, 215, 214, -186, -280, +0, 238, 86, -190, -150, 190, 94, -144, +-59, 24, -16, 126, -24, -198, 77, 185, +-150, -125, 106, 61, -57, 3, -4, -35, +-1, 10, -21, 57, -14, -102, 93, 59, +-200, 36, 174, -113, -39, 114, -128, -92, +192, 83, -189, -94, 180, 53, -177, 30, +117, -123, 2, 120, -83, -62, 96, -29, +-47, 23, 54, 19, -84, -93, 109, 61, +-48, 57, -10, -242, 78, 286, -94, -165, +125, -110, -71, 276, 24, -284, 28, 106, +60, 31, -132, -111, 142, 75, -4, -55, +-31, 19, 15, -68, 78, 83, 8, -128, +-82, 68, 187, -50, -113, 6, 84, -47, +27, -12, -40, 70, 102, -161, -4, 93, +0, -34, 29, -44, 129, -9, -136, -29, +130, 70, 72, -166, -66, 59, 69, 52, +80, -169, -5, 60, -7, 38, 138, -119, +-61, 0, 102, 68, 21, -127, -10, -5, +183, 93, -134, -205, 174, 156, -15, -167, +97, 85, 9, -54, 10, -160, 231, 282, +-191, -343, 234, 108, -25, 60, 105, -163, +-3, 21, 91, -12, 121, 26, -105, -157, +254, 100, -35, -79, 27, -31, 176, -3, +5, -53, 46, -2, 90, -43, 170, -2, +-120, -82, 202, 30, 138, -26, -100, -97, +182, 13, 190, 17, -150, -118, 239, 1, +123, 10, -63, -86, 211, -1, 69, -33, +51, -88, 123, 103, 159, -186, -94, 33, +345, -6, -59, -14, 78, -152, 217, 64, +24, 45, 158, -238, -38, 114, 347, -55, +-50, -25, 45, -135, 336, 94, -86, -59, +186, -130, 117, 109, 124, -181, 83, 93, +158, -93, 87, -74, 122, 28, 213, -5, +-95, -139, 369, -16, 34, 117, -12, -221, +343, -17, 66, 128, -29, -208, 345, 12, +36, 10, 86, -72, 200, -14, 118, -88, +84, 64, 199, -128, 112, 25, 48, -61, +293, -48, 40, 55, 54, -206, 313, 153, +72, -135, -35, -73, 436, 107, -70, -167, +127, -18, 313, 65, -27, -127, 158, -96, +253, 202, 28, -294, 130, 51, 261, 117, +16, -293, 190, 128, 141, -3, 150, -151, +93, -8, 185, 103, 151, -214, 89, 17, +160, 72, 191, -174, 112, 29, 19, -47, +411, 25, -120, -126, 245, -36, 208, 144, +-8, -310, 305, 185, -4, -116, 240, -46, +93, 19, 151, -102, 162, 32, 69, -46, +275, -89, -32, 26, 274, 23, 116, -226, +44, 202, 269, -187, 108, 30, 30, -42, +264, -69, 176, 117, -80, -290, 353, 227, +132, -159, -56, -47, 360, 50, 47, -124, +106, 99, 181, -183, 153, 68, 106, -9, +87, -89, 309, -53, -87, 78, 314, -80, +78, -127, 98, 114, 224, -30, 48, -186, +193, 144, 113, -59, 146, -135, 165, 124, +32, -150, 313, 38, 5, -1, 112, -153, +295, 151, -12, -164, 198, 45, 89, -58, +268, -2, -41, -13, 222, -75, 209, 6, +20, 15, 147, -96, 259, -10, 1, 53, +153, -113, 242, 7, 2, 3, 241, -68, +71, 47, 153, -133, 201, 102, 17, -86, +199, -26, 190, -9, 37, 29, 169, -107, +169, 9, 157, 48, 23, -138, 237, 66, +161, -43, 23, -18, 194, -56, 209, 53, +5, -72, 197, -35, 169, 79, 80, -152, +145, 84, 155, -28, 114, -105, 161, 100, +83, -70, 181, -61, 132, 39, 110, 33, +116, -188, 208, 142, 69, -30, 112, -132, +216, 89, 44, -10, 188, -72, 78, -35, +182, 127, 102, -186, 91, 60, 227, 35, +29, -116, 135, 52, 246, -14, -62, -66, +268, 43, 97, -53, 67, 10, 170, -44, +140, 8, 70, 10, 121, -108, 198, 125, +5, -121, 182, 16, 113, 39, 103, -97, +98, 38, 137, -1, 118, -50, 71, -21, +155, 66, 72, -119, 163, 44, 3, -11, +217, 8, 40, -103, 80, 108, 149, -75, +116, -7, -30, -23, 265, 24, 10, -4, +26, -90, 233, 50, 20, 37, 39, -128, +155, 17, 132, 124, -93, -195, 261, 49, +38, 89, -32, -150, 234, 44, 3, 12, +27, -38, 165, -4, 31, -35, -5, 63, +213, -99, -51, 45, 43, -34, 224, 13, +-136, -44, 149, -9, 115, 52, -75, -138, +137, 154, 36, -173, 45, 92, 12, 17, +91, -180, 37, 226, -15, -205, 122, 81, +-22, -22, 27, -6, 100, -43, -55, 26, +78, 19, 37, -149, -10, 203, 29, -192, +53, 65, -3, 6, -38, -22, 131, -11, +-86, -77, 16, 208, 78, -277, -44, 99, +-1, 136, 14, -263, 87, 144, -199, -17, +220, 1, -116, -115, -58, 125, 149, -35, +-132, -92, 25, 59, 1, 3, 36, -32, +-144, -57, 127, 80, -66, -43, -74, -42, +72, 31, -76, -25, 14, 51, -92, -159, +91, 182, -130, -122, 4, 20, 0, -24, +-50, 53, -54, -41, 11, -95, -41, 184, +-56, -167, -24, 23, -8, 77, -85, -112, +1, 88, -74, -116, 17, 152, -114, -169, +2, 93, -3, 3, -163, -87, 86, 92, +-91, -75, -118, 48, 93, -59, -145, 46, +-45, -14, 17, -59, -83, 101, -98, -129, +57, 137, -120, -160, -87, 141, 79, -68, +-191, -38, 5, 74, 11, -22, -186, -73, +60, 72, -63, 44, -155, -218, 92, 318, +-170, -268, 1, 90, -83, 110, -20, -239, +-75, 259, -100, -225, 67, 192, -201, -181, +55, 151, -110, -103, -40, 56, -39, -30, +-104, -22, 11, 103, -102, -165, -64, 138, +-7, -28, -95, -102, -55, 175, -41, -172, +-58, 126, -83, -67, -13, 27, -102, -17, +-30, 18, -55, 23, -103, -81, -3, 127, +-80, -111, -78, 66, -33, -14, -48, -55, +-95, 178, -41, -285, -38, 283, -77, -121, +-105, -89, 67, 225, -215, -215, 42, 134, +-55, -33, -153, -48, 49, 133, -118, -192, +-70, 254, -48, -280, 7, 279, -246, -179, +164, 36, -208, 106, -64, -146, 60, 112, +-213, -37, 49, -3, -125, 30, -45, -11, +-25, -16, -156, 45, 48, -16, -127, -31, +-59, 80, -66, -110, 32, 183, -292, -239, +231, 229, -329, -84, 122, -47, -207, 65, +52, 73, -144, -158, -70, 133, -3, -21, +-112, -5, -89, -25, -22, 72, -56, -39, +-147, 15, -9, -6, 2, 28, -264, -8, +140, 18, -188, -63, -35, 179, -107, -235, +35, 208, -186, -63, -33, -112, 26, 273, +-229, -306, 59, 209, -113, -7, -92, -111, +-22, 110, -117, -23, -29, 24, -93, -65, +-82, 76, -5, 41, -157, -150, 0, 163, +-77, -34, -130, -89, 53, 196, -242, -260, +154, 337, -308, -322, 135, 216, -165, -36, +-88, -84, 31, 157, -176, -177, 25, 189, +-138, -125, 20, 32, -187, 30, 100, 55, +-259, -181, 142, 245, -252, -155, 80, 55, +-151, -27, -1, 108, -140, -172, 75, 184, +-249, -124, 123, 75, -174, -23, -34, 11, +-47, 0, -64, 30, -69, -13, -66, -26, +-23, 71, -68, -10, -124, -99, 60, 183, +-110, -127, -153, 24, 165, 38, -278, 7, +73, -24, -87, -21, -49, 94, -67, -23, +-52, -136, -2, 252, -143, -161, 56, -12, +-140, 78, 33, 50, -109, -195, -50, 208, +40, -65, -176, -36, 49, 9, -70, 97, +-39, -92, -114, -27, 91, 173, -154, -171, +-38, 50, 37, 82, -96, -76, -99, -31, +106, 153, -182, -176, 25, 141, -36, -70, +-76, 22, 7, 62, -104, -148, 55, 228, +-142, -227, 63, 163, -111, -45, -11, -51, +17, 116, -167, -89, 126, 27, -156, 24, +23, 31, -53, -135, 0, 194, -93, -104, +29, -29, -65, 90, -14, -23, -41, -33, +-31, -22, 17, 161, -124, -209, 90, 99, +-130, 94, 36, -166, -64, 96, -9, 40, +-10, -90, -92, 49, 96, 18, -162, -33, +84, 16, -66, 14, -58, -18, 74, 27, +-154, -29, 118, 50, -152, -68, 78, 92, +-56, -85, -73, 47, 102, 11, -146, -21, +38, -17, 15, 70, -112, -63, 100, 23, +-143, -3, 94, 52, -80, -85, -39, 55, +65, 29, -81, -69, -14, 48, 15, -18, +-1, 35, -111, -39, 116, -18, -94, 117, +-18, -164, 52, 126, -92, -55, 50, 31, +-65, -34, 54, 14, -83, 40, 22, -76, +26, 85, -104, -71, 63, 59, -2, -25, +-98, -24, 69, 84, -18, -106, -55, 81, +29, -19, -20, -54, 1, 121, -37, -127, +-8, 68, 52, 35, -111, -79, 60, 44, +-14, 43, -35, -95, 4, 110, -15, -87, +14, 56, -35, -7, 19, -36, -50, 25, +112, 23, -177, -33, 106, -43, 32, 145, +-155, -129, 107, -10, 9, 148, -89, -142, +13, 42, 98, 12, -147, 37, 81, -96, +-22, 67, 22, 2, -60, -12, 20, -46, +87, 75, -184, -15, 165, -89, -60, 140, +-77, -102, 128, 41, -90, -9, -14, 6, +93, 2, -129, -16, 101, 41, -63, -72, +38, 86, -41, -54, 46, -17, -48, 63, +25, -18, 2, -74, -36, 115, 47, -52, +-30, -34, -20, 50, 51, 4, -34, -34, +-32, -13, 83, 99, -89, -142, 63, 138, +-65, -116, 88, 102, -98, -63, 52, 4, +13, 45, -58, -38, 52, 16, -57, 4, +82, -1, -115, 11, 118, -35, -88, 53, +38, -42, 9, 40, -57, -67, 99, 96, +-132, -66, 149, -11, -143, 52, 126, -21, +-70, -31, -13, 9, 86, 88, -96, -152, +48, 111, 3, -13, -7, -32, -23, 4, +46, 28, -43, -10, 27, -21, -17, 25, +-2, -12, 38, 23, -73, -36, 66, 15, +-25, 39, 10, -64, -49, 26, 103, 21, +-91, -13, 1, -59, 102, 131, -152, -144, +115, 131, -62, -104, 40, 72, -65, -6, +75, -70, -39, 108, -23, -81, 57, 21, +-46, 2, 22, 41, -40, -89, 75, 67, +-86, 39, 26, -128, 47, 123, -74, -42, +25, -13, 38, -8, -57, 46, 10, -19, +29, -44, -38, 86, 2, -80, 35, 67, +-52, -74, 20, 63, 33, 16, -102, -116, +125, 157, -87, -112, 9, 27, 38, 19, +-38, -5, -4, -20, 20, 8, -15, 51, +-27, -93, 39, 101, -52, -67, 35, 48, +-26, -42, 7, 17, 10, 50, -58, -125, +97, 172, -121, -159, 71, 102, 5, -16, +-74, -57, 68, 86, -48, -58, 26, 46, +-44, -93, 50, 147, -38, -114, -6, -2, +9, 100, 5, -77, -36, -18, 33, 54, +-14, 23, -38, -125, 64, 144, -64, -59, +0, -47, 74, 73, -123, -10, 85, -66, +-20, 65, -36, 19, 25, -91, -18, 80, +33, -10, -80, -46, 88, 53, -72, -44, +29, 49, -8, -52, -32, 34, 58, 3, +-91, -28, 75, 59, -62, -93, 44, 100, +-42, -46, -2, -46, 56, 107, -105, -90, +65, 35, 9, 15, -93, -23, 106, 9, +-87, 9, 38, -22, 8, 35, -84, -64, +139, 104, -146, -118, 55, 56, 62, 51, +-139, -124, 98, 122, -32, -79, -5, 64, +-35, -89, 81, 89, -101, -57, 74, 30, +-64, -19, 22, -19, 62, 127, -214, -245, +302, 261, -248, -148, 66, -6, 54, 85, +-50, -56, -31, 5, 10, -35, 108, 139, +-216, -202, 159, 136, -26, 21, -74, -121, +44, 94, -3, -5, 9, -27, -76, -5, +68, 37, -2, -6, -81, -44, 70, 65, +-13, -45, -49, 7, 45, 41, -34, -86, +22, 108, -55, -80, 63, 36, -41, -21, +-26, 20, 65, 17, -78, -91, 45, 129, +-22, -84, -4, -3, 7, 50, -30, -13, +34, -62, -30, 95, -7, -56, 4, -7, +25, 40, -66, -43, 44, 59, 16, -106, +-70, 131, 44, -93, 12, 19, -56, 20, +23, -7, 25, -1, -48, -39, 13, 85, +24, -83, -38, 46, -3, -21, 20, 34, +-12, -27, -30, -29, 50, 81, -42, -77, +-5, 46, 18, -26, -10, 39, -13, -48, +-16, 44, 60, -31, -88, 22, 63, -16, +-30, 0, 21, 25, -51, -56, 59, 86, +-36, -94, -11, 63, 31, -2, -40, -54, +48, 88, -66, -108, 72, 108, -59, -88, +35, 50, -28, -20, 20, 5, -17, 26, +-5, -72, 24, 109, -61, -93, 89, 58, +-105, -33, 74, 24, -25, 3, -10, -35, +-2, 38, 11, -2, 15, -9, -64, -40, +72, 87, -10, -63, -72, -17, 86, 61, +-22, -24, -58, -20, 63, 5, 4, 53, +-76, -73, 80, 20, -29, 63, -26, -96, +44, 55, -29, 6, 20, -40, -40, 34, +60, -12, -47, 6, -3, -25, 45, 50, +-41, -43, -15, -13, 78, 82, -98, -97, +55, 26, 18, 78, -78, -109, 91, 33, +-61, 63, 19, -67, -11, -4, 20, 57, +-15, -24, -28, -40, 86, 39, -100, 24, +47, -65, 18, 51, -48, -7, 19, -8, +20, -11, -18, 35, -22, -50, 66, 47, +-77, -22, 46, -14, 5, 31, -47, -17, +56, -7, -51, 18, 51, 1, -68, -42, +68, 82, -38, -61, -21, -40, 54, 166, +-40, -204, 11, 120, -33, -8, 88, 4, +-123, -74, 88, 89, -15, 3, -29, -100, +34, 88, -36, -4, 65, -45, -92, 28, +79, -3, -24, -12, -20, 29, 32, -42, +-35, -1, 58, 90, -88, -137, 81, 94, +-30, -23, -25, 4, 36, -22, -3, 5, +-28, 44, 26, -68, 10, 43, -46, -27, +50, 51, -18, -73, -16, 35, 29, 28, +-25, -48, 12, 39, -12, -52, 22, 93, +-17, -104, -4, 33, 35, 55, -46, -89, +34, 46, -17, 5, 1, 12, 11, -82, +-27, 124, 48, -81, -55, -25, 50, 98, +-42, -83, 50, 8, -59, 38, 52, -20, +-22, -22, -28, 37, 68, -8, -79, -42, +70, 64, -58, -42, 45, -6, -15, 29, +-22, -18, 48, -17, -39, 38, 2, -25, +10, 5, 15, 16, -54, -32, 52, 45, +-2, -36, -54, 1, 59, 45, -22, -73, +2, 65, -25, -26, 58, -25, -44, 48, +-16, -24, 73, -26, -77, 37, 43, 23, +-16, -90, 8, 75, -1, 32, -30, -124, +62, 122, -45, -60, 0, 6, 19, 10, +23, -15, -72, 12, 64, 5, 2, -22, +-50, 10, 17, 24, 60, -32, -97, 14, +58, 0, -12, 6, 21, 8, -60, -54, +53, 69, 22, -5, -86, -80, 69, 76, +4, 20, -26, -102, -32, 97, 86, -43, +-43, 17, -61, -20, 101, 7, -25, 37, +-79, -54, 88, 20, 8, 20, -79, -24, +54, -3, 14, 16, -24, 15, -31, -63, +62, 82, -21, -39, -32, -39, 22, 87, +32, -52, -51, -37, 15, 98, 32, -88, +-28, 30, -2, 13, 1, -9, 47, -15, +-82, 20, 66, 4, -20, -34, 4, 37, +-10, -15, 15, -15, 16, 23, -46, -12, +48, -10, -8, 18, -10, -10, -15, 2, +51, -4, -36, 14, -21, -31, 76, 28, +-60, 16, 1, -80, 30, 102, -2, -37, +-36, -65, 53, 108, -24, -64, 7, -21, +2, 44, -11, 12, 39, -80, -30, 100, +-33, -57, 81, 0, -51, 20, -11, 2, +46, -42, 8, 54, -89, -18, 83, -12, +-2, 16, -54, 0, 59, 9, -31, -52, +27, 59, -36, -9, 42, -50, 3, 39, +-38, 33, 24, -72, 15, 17, -15, 72, +2, -112, 27, 83, -32, -35, -2, 9, +49, -2, -42, -32, 42, 71, -32, -89, +15, 56, 4, 8, -14, -45, 30, 27, +-7, 29, -28, -40, -2, -18, 73, 107, +-70, -141, 26, 64, 52, 33, -66, -70, +11, 23, 47, 18, 15, -2, -83, -49, +77, 70, -21, -53, 3, 37, -22, -34, +72, 1, -32, 66, -62, -119, 89, 91, +-8, 8, -30, -93, 15, 88, 40, -31, +-68, -2, 41, -25, 27, 67, -23, -58, +-13, 2, 23, 51, -3, -63, -6, 38, +34, -12, -15, 8, -24, -6, 25, -15, +11, 55, -11, -73, 20, 36, -4, 31, +-9, -66, -7, 23, 43, 58, -4, -89, +-28, 47, 20, 20, -2, -46, 19, 35, +-38, -46, 100, 86, -110, -97, 47, 39, +15, 56, -18, -103, 37, 64, -19, 5, +3, -43, -26, 33, 71, -17, -45, 13, +22, -26, 20, 22, -47, 13, 21, -65, +34, 93, -2, -63, -22, -13, -4, 69, +52, -53, -67, -22, 70, 69, -7, -48, +-20, -13, -6, 44, 12, -20, 35, -16, +-37, 25, 37, -7, -20, -24, -9, 50, +25, -55, 0, 22, 40, 31, -66, -64, +34, 57, -1, -32, 6, 21, 40, -6, +-75, -42, 85, 100, -84, -120, 66, 84, +10, -7, -48, -61, 46, 88, -42, -62, +44, 28, -42, -18, 95, 11, -93, -12, +36, 4, 32, 13, -63, -19, 86, -16, +-51, 61, 31, -70, -26, 25, -1, 38, +45, -69, -20, 41, 0, 32, -20, -84, +40, 87, -36, -60, 32, 23, 33, 28, +-88, -80, 74, 118, -37, -109, 27, 29, +38, 73, -85, -113, 69, 64, -27, 14, +6, -60, 24, 31, 10, 45, -61, -95, +53, 87, 14, -55, -62, 13, 110, 31, +-94, -48, 18, 42, 43, -30, -41, 1, +25, 18, 27, 22, -44, -98, 9, 129, +9, -87, 7, -17, 39, 150, -61, -218, +36, 144, -21, -29, 10, -15, 48, 23, +-46, -48, -1, 68, -1, -52, 12, 18, +20, 25, 2, -64, -28, 46, 12, 39, +-2, -131, -4, 152, 59, -74, -56, -65, +4, 184, -1, -207, 10, 135, 17, -29, +0, -36, -2, 67, -49, -148, 83, 235, +-61, -202, 57, 59, -30, 76, -23, -183, +64, 246, -79, -167, 40, 8, 33, 82, +-44, -134, 42, 220, -89, -188, 35, 14, +104, 85, -73, -20, -75, -31, 102, 9, +-35, 23, -26, -92, 146, 189, -214, -178, +122, 42, -6, 63, -29, -65, 73, 51, +-118, -54, 92, 10, -18, 43, -17, 12, +21, -117, -31, 92, 48, -10, 15, 42, +-89, -74, 36, -75, 67, 209, -68, -98, +39, -41, -44, 46, -18, -111, 124, 236, +-96, -147, -6, -81, 42, 120, -57, -31, +107, 66, -99, -128, 13, 28, 69, 118, +-101, -129, 119, 81, -120, -100, 75, 89, +40, 66, -109, -242, 82, 200, -48, -21, +82, -49, -58, 35, -53, -133, 106, 246, +-65, -156, 37, -52, -18, 145, -57, -101, +116, 84, -118, -120, 68, 84, 27, 84, +-150, -189, 173, 106, -91, -36, 18, 145, +-4, -185, -27, -48, 99, 233, -141, -98, +82, -63, -48, -39, 96, 189, -113, -103, +27, -89, 40, 107, -104, 14, 206, -33, +-235, -107, 125, 194, -65, -135, 39, 85, +16, -116, -40, 106, -42, -9, 43, -80, +-11, 143, 18, -123, -57, -26, -2, 146, +65, -40, -79, -132, -7, 96, 35, 39, +22, 21, -93, -192, 15, 143, 38, 117, +-3, -191, -82, -83, 46, 300, 27, -123, +-46, -154, -130, 104, 218, 115, -101, -85, +-81, -125, 40, 133, -15, 107, 47, -260, +-54, 152, -125, 5, 247, 74, -244, -234, +9, 122, 156, 144, -92, -130, -131, -153, +87, 234, 54, 3, -88, -159, -114, 46, +179, 82, -75, -7, -126, -94, 70, -9, +55, 195, -102, -184, -46, 28, 53, 10, +1, 75, -95, -64, -8, -41, 100, 67, +-117, -7, -60, 4, 43, -96, 87, 166, +-206, -85, 36, -80, 97, 104, -124, 4, +-27, -8, 19, -137, 34, 150, -95, 29, +-49, -129, 45, 38, 0, 65, -102, -46, +37, 5, -44, -22, -49, 37, 40, 6, +-36, -44, -41, 25, -104, -25, 150, 64, +-92, -58, -96, 8, -1, -15, 73, 38, +-78, 27, -97, -94, 58, 30, -9, 56, +-121, -38, 81, -22, -58, 67, -116, -99, +66, 77, 23, 20, -120, -83, -68, 37, +66, 28, 38, -7, -208, -74, 53, 79, +59, 26, -171, -77, 26, -8, 18, 73, +-44, 44, -166, -167, 135, 78, 0, 87, +-184, -57, -28, -116, 129, 106, -11, 117, +-332, -186, 189, -68, 120, 221, -296, 47, +-16, -308, 109, 52, -3, 378, -213, -321, +24, -119, 106, 275, -151, 41, -77, -337, +124, 200, -173, 138, 4, -179, 21, -76, +-82, 191, -35, 15, -80, -199, 118, 80, +-128, 177, -157, -214, 186, -11, -120, 189, +-92, -76, 5, -155, 48, 190, -157, -49, +-11, -24, 76, -41, -136, 105, -54, -48, +19, -115, 35, 214, -171, -102, -2, -125, +72, 191, -130, -44, -40, -78, 7, -28, +17, 229, -151, -238, -6, -14, 117, 202, +-213, -58, -8, -203, 44, 148, -5, 155, +-168, -229, -11, -92, 139, 361, -198, -145, +-85, -282, 149, 288, -62, 135, -239, -312, +132, -22, 63, 303, -204, -89, -97, -241, +205, 189, -130, 121, -171, -219, 129, -2, +-33, 200, -137, -88, -2, -161, 37, 187, +-31, 47, -220, -209, 202, 73, -73, 159, +-150, -165, -6, -41, 72, 134, -32, 55, +-235, -215, 157, 71, -12, 175, -143, -138, +-63, -160, 199, 337, -256, -193, 28, -88, +11, 154, 22, 52, -220, -209, 158, 99, +-93, 86, -36, -68, -81, -81, 78, 114, +-37, 21, -171, -135, 102, 69, 18, 93, +-166, -119, -4, -29, 96, 138, -107, -85, +-88, 2, 20, -23, 90, 85, -203, -16, +-17, -127, 138, 102, -105, 126, -166, -295, +171, 189, -59, 46, -135, -195, 90, 274, +-118, -370, 111, 437, -188, -340, 51, 82, +47, 221, -148, -397, 32, 399, 6, -412, +8, 553, -186, -660, 146, 505, -25, -194, +-133, 38, 63, -120, -90, 202, 149, -124, +-256, 14, 142, -41, -25, 102, -132, -61, +152, -25, -190, 11, 135, 77, -187, -141, +173, 139, -158, -82, 14, 14, 7, 16, +-10, -29, -39, 47, -37, -56, 33, 14, +-39, 88, -39, -190, 6, 209, 45, -125, +-179, 26, 170, -5, -138, 38, 66, -11, +-133, -83, 105, 145, -10, -51, -182, -134, +192, 201, -112, -58, -9, -96, -73, 68, +164, 61, -163, -47, -61, -154, 208, 322, +-220, -261, 83, 100, -80, -73, 123, 134, +-135, -61, 10, -78, -31, -37, 201, 397, +-404, -579, 354, 343, -179, 15, -45, -145, +226, 151, -514, -346, 768, 727, -896, -961, +787, 853, -624, -551, 451, 302, -345, -198, +186, 161, -18, -75, -134, -96, 139, 219, +-131, -161, 134, 24, -170, -17, 106, 152, +-30, -235, -21, 169, -36, -82, 89, 96, +-98, -132, -1, 47, 65, 84, -57, -70, +-34, -101, 50, 236, -22, -197, -26, 27, +24, 111, -28, -124, 23, 26, -17, 44, +-43, -64, 105, 105, -140, -197, 55, 222, +56, -133, -109, 56, 29, -97, 54, 149, +-103, -51, 83, -139, -49, 186, -28, -49, +77, -57, -106, 18, 78, 61, -84, -73, +103, 58, -142, -43, 91, 26, -34, 15, +0, -81, -15, 159, -32, -188, 103, 121, +-169, 24, 139, -140, -93, 133, 81, -29, +-128, -47, 98, 16, 0, 51, -66, -54, +-10, 13, 62, 13, -24, -34, -15, 105, +-86, -247, 210, 375, -262, -363, 212, 243, +-175, -157, 146, 130, -60, -57, -153, -78, +350, 135, -372, -54, 204, 6, -87, -125, +122, 257, -196, -158, 165, -91, -112, 172, +112, -38, -105, 9, 5, -233, 127, 426, +-171, -354, 109, 204, -56, -225, 96, 338, +-152, -298, 126, 84, -22, 70, -50, -42, +65, -30, -55, -18, 92, 121, -131, -147, +123, 82, -27, 1, -49, -26, 36, -14, +73, 36, -99, 9, 39, -83, 76, 101, +-114, -95, 93, 153, -26, -246, 29, 263, +-51, -166, 64, 70, 27, -97, -65, 189, +38, -188, 64, 61, -52, 36, -8, 14, +77, -131, -19, 169, -38, -104, 67, 85, +4, -175, -12, 242, 19, -148, 15, 3, +23, -10, 4, 161, -21, -252, 95, 184, +-66, -66, 43, 35, 16, -87, 53, 148, +-90, -156, 100, 140, 23, -128, -12, 122, +-56, -111, 168, 116, -107, -130, 102, 112, +-84, -62, 159, -5, -101, 46, 49, -37, +83, 0, -43, 17, -9, -23, 125, 39, +-58, -62, 57, 89, -54, -133, 174, 161, +-79, -158, -23, 138, 148, -155, -43, 211, +6, -204, 8, 70, 173, 102, -202, -131, +196, -8, -39, 126, 51, -94, -5, 26, +4, -74, 182, 158, -202, -120, 190, -21, +-3, 64, 20, 44, -17, -137, 100, 70, +32, 33, -44, 2, 57, -115, 128, 116, +-121, 4, 121, -78, -10, 24, 138, 39, +-156, 9, 165, -102, 25, 70, 30, 78, +-54, -137, 86, 2, 178, 176, -263, -201, +301, 100, -147, -39, 215, 84, -193, -121, +219, 63, -18, 16, -15, 8, 83, -106, +54, 133, 0, -50, 1, -27, 124, 9, +16, 40, -69, -8, 170, -81, -15, 102, +9, -6, 44, -64, 96, -6, -34, 116, +57, -107, 43, 12, 77, 12, -46, 70, +80, -134, 100, 85, -68, 0, 68, -11, +114, -39, -28, 46, -22, 24, 153, -66, +40, 17, -89, 38, 131, -8, 56, -79, +42, 99, -82, -1, 139, -117, 134, 121, +-168, -46, 124, 6, 132, -56, -65, 139, +16, -169, 128, 130, 3, -93, 41, 82, +-25, -55, 155, -21, -2, 68, -56, -29, +166, -27, 22, -18, -40, 130, 71, -158, +90, 34, 38, 120, -118, -168, 245, 148, +-57, -170, 51, 227, -66, -222, 282, 149, +-195, -103, 160, 115, -70, -142, 248, 144, +-221, -126, 221, 99, -81, -65, 192, 45, +-174, -67, 203, 104, -18, -60, 23, -54, +18, 115, 117, -66, -30, 30, 7, -110, +161, 207, -95, -195, 111, 129, 3, -149, +69, 225, 9, -193, 48, 35, 12, 36, +111, 97, -56, -281, 102, 264, -12, -78, +95, -33, -46, -43, 135, 172, -95, -181, +192, 75, -107, -8, 162, 50, -155, -101, +305, 64, -211, 16, 142, -24, 8, -18, +74, 28, -24, 19, 53, -55, 53, 5, +37, 73, -36, -56, 137, -50, -67, 94, +138, 13, -112, -148, 210, 125, -133, 18, +170, -70, -103, -61, 174, 187, -83, -124, +68, -28, 59, 48, 23, 66, -17, -139, +83, 60, 67, 27, -70, 8, 72, -134, +101, 199, -62, -155, 42, 99, 65, -118, +28, 172, 13, -166, -30, 80, 175, -16, +-95, 76, 17, -199, 140, 222, -36, -113, +-24, 19, 114, -46, -3, 90, 39, 0, +-90, -144, 243, 180, -161, -95, 125, 44, +-67, -100, 196, 133, -150, -65, 110, 17, +-37, -113, 226, 265, -316, -283, 326, 167, +-141, -74, 155, 101, -175, -164, 237, 149, +-77, -79, 26, 48, -6, -76, 120, 93, +-26, -41, -72, -29, 185, 47, -50, 2, +-17, -60, 36, 108, 98, -128, -36, 132, +-71, -125, 222, 134, -128, -137, 66, 92, +-6, -8, 114, -32, -76, -26, 51, 108, +9, -119, 117, 96, -144, -128, 143, 179, +-9, -135, 34, 16, -47, 14, 107, 98, +13, -184, -73, 89, 138, 81, -39, -121, +43, 25, -46, -1, 154, 150, -120, -321, +131, 323, -87, -190, 139, 79, -60, -44, +-2, 32, 111, -22, -20, 65, -51, -186, +129, 280, -13, -242, -39, 94, 91, 37, +-14, -80, 51, 72, -62, -84, 147, 118, +-103, -125, 93, 68, -10, 33, 5, -118, +107, 136, -154, -87, 214, 19, -109, 22, +43, -28, 38, 47, 15, -74, 8, 77, +-2, -48, 70, 26, -14, -23, 20, 3, +2, 27, 91, -19, -66, -41, 44, 78, +42, -31, 18, -50, -24, 95, 15, -122, +153, 187, -202, -247, 206, 171, -86, 8, +123, -110, -170, 36, 236, 100, -144, -110, +120, 59, -112, -105, 219, 243, -172, -304, +111, 200, 12, -65, 17, 48, -6, -112, +22, 111, 66, -36, -29, -8, -37, -30, +169, 70, -142, -7, 104, -145, -21, 286, +53, -361, -28, 405, 44, -435, 6, 427, +69, -357, -116, 255, 202, -159, -169, 120, +217, -145, -230, 191, 267, -203, -130, 168, +5, -155, 100, 184, -66, -190, 87, 114, +-134, -6, 224, -31, -150, 4, 33, -9, +83, 93, -28, -147, 36, 67, -61, 81, +190, -140, -169, 79, 128, -10, -48, 19, +114, -21, -150, -71, 142, 208, -16, -232, +-51, 124, 71, -12, -37, 0, 86, -65, +-132, 109, 164, -151, -88, 276, 54, -506, +-26, 745, 66, -876, -6, 898, -26, -875, +91, 854, -40, -816, 36, 719, -3, -570, +7, 446, 46, -371, -73, 307, 66, -191, +1, 41, -32, 73, -26, -129, 160, 210, +-284, -379, 423, 572, -562, -676, 758, 678, +-869, -659, 919, 680, -825, -694, 746, 658, +-640, -587, 581, 528, -456, -486, 341, 431, +-281, -349, 309, 305, -343, -348, 328, 448, +-293, -544, 267, 620, -248, -714, 220, 832, +-145, -898, 78, 803, -9, -536, 18, 174, +23, 184, -69, -528, 117, 829, -46, -993, +-61, 940, 132, -714, -165, 463, 219, -284, +-304, 166, 310, -86, -224, 73, 76, -155, +74, 244, -227, -254, 436, 214, -700, -219, +978, 297, -1132, -402, 1216, 513, -1275, -658, +1332, 842, -1299, -981, 1154, 1007, -993, -909, +792, 747, -589, -574, 340, 413, -127, -274, +-119, 132, 318, 12, -457, -99, 518, 58, +-501, 66, 416, -137, -219, 79, 38, 65, +137, -234, -247, 463, 310, -785, -278, 1101, +184, -1239, -158, 1163, 137, -980, -196, 740, +225, -404, -339, -13, 313, 381, -248, -538, +102, 514, 59, -452, -298, 424, 606, -368, +-826, 233, 971, -89, -943, 46, 842, -128, +-598, 268, 262, -441, 202, 705, -800, -1087, +1325, 1522, -1788, -1836, 2027, 1924, -2190, -1843, +2048, 1689, -1770, -1480, 1305, 1141, -859, -653, +388, 128, 67, 283, -438, -546, 794, 714, +-1042, -837, 1282, 916, -1387, -991, 1479, 1113, +-1494, -1290, 1464, 1424, -1444, -1376, 1350, 1057, +-1221, -503, 836, -135, -463, 685, -6, -1038, +305, 1193, -561, -1137, 598, 809, -480, -245, +221, -383, 134, 898, -456, -1269, 759, 1564, +-864, -1762, 925, 1773, -870, -1622, 794, 1496, +-685, -1503, 587, 1572, -645, -1569, 739, 1512, +-982, -1436, 1030, 1280, -982, -901, 592, 338, +-112, 244, -540, -721, 1163, 1116, -1677, -1445, +1956, 1675, -1950, -1728, 1790, 1638, -1436, -1442, +1038, 1191, -554, -896, 115, 636, 224, -453, +-437, 393, 414, -405, -322, 502, -8, -579, +260, 559, -498, -294, 357, -228, -61, 945, +-441, -1628, 850, 2120, -1183, -2271, 1321, 2128, +-1266, -1713, 1057, 1138, -759, -466, 505, -125, +-319, 578, 176, -842, -88, 1002, -19, -1018, +19, 918, -115, -704, 151, 565, -398, -556, +630, 731, -1069, -958, 1371, 1221, -1653, -1340, +1617, 1254, -1381, -847, 829, 282, -185, 379, +-512, -988, 1079, 1557, -1505, -1917, 1617, 2051, +-1525, -1862, 1146, 1455, -722, -809, 141, 71, +275, 671, -715, -1190, 857, 1507, -953, -1545, +671, 1369, -366, -875, -96, 282, 303, 243, +-438, -426, 269, 347, -67, 30, -324, -553, +630, 1158, -974, -1474, 1025, 1357, -1009, -700, +698, -158, -455, 1045, 9, -1658, 218, 1977, +-461, -1814, 302, 1325, -178, -569, -179, -106, +324, 604, -510, -706, 275, 551, -13, -110, +-495, -315, 762, 678, -1035, -782, 912, 738, +-768, -482, 262, 245, 129, -10, -729, -43, +982, 95, -1274, -72, 1139, 120, -1064, -69, +597, 54, -266, 20, -317, 24, 594, -21, +-952, 104, 844, -165, -718, 369, 249, -490, +-105, 528, -106, -268, -90, -52, 111, 452, +-465, -676, 506, 873, -705, -816, 412, 578, +-261, 1, -239, -595, 410, 1185, -844, -1525, +981, 1789, -1324, -1784, 1197, 1572, -1071, -934, +359, 129, 303, 857, -1311, -1680, 1780, 2358, +-2092, -2517, 1570, 2275, -1016, -1540, 19, 743, +480, 91, -962, -625, 673, 930, -377, -741, +-427, 289, 871, 405, -1449, -933, 1418, 1364, +-1412, -1478, 844, 1428, -418, -1015, -390, 534, +801, 63, -1330, -491, 1266, 952, -1289, -1206, +792, 1304, -528, -932, -141, 361, 379, 341, +-755, -690, 446, 715, -222, -228, -491, -455, +828, 1315, -1349, -1873, 1249, 2034, -1151, -1475, +479, 545, -72, 606, -534, -1412, 578, 1838, +-628, -1619, 25, 1030, 471, -87, -1302, -706, +1508, 1230, -1630, -1118, 997, 671, -522, -32, +-255, -241, 417, 163, -572, 371, 79, -906, +211, 1370, -732, -1422, 698, 1218, -681, -634, +127, 32, 232, 589, -834, -909, 1004, 1112, +-1326, -1089, 1246, 1115, -1440, -1061, 1321, 1155, +-1491, -1172, 1195, 1172, -996, -820, 273, 298, +161, 403, -753, -837, 750, 1001, -727, -653, +157, 50, 254, 805, -850, -1473, 971, 1865, +-1132, -1668, 904, 1117, -835, -222, 338, -638, +133, 1502, -1020, -2110, 1594, 2533, -2193, -2491, +2123, 2112, -1855, -1322, 891, 465, 28, 418, +-1107, -1018, 1516, 1403, -1616, -1372, 988, 1117, +-327, -632, -498, 271, 768, -53, -785, 184, +196, -491, 376, 1024, -1107, -1501, 1392, 1877, +-1581, -1855, 1238, 1544, -868, -908, 132, 229, +394, 499, -1003, -1012, 1110, 1278, -1070, -1048, +531, 500, -97, 230, -386, -659, 355, 661, +-103, -116, -611, -618, 1170, 1302, -1632, -1526, +1533, 1328, -1321, -757, 830, 211, -499, 191, +-36, -307, 448, 360, -1074, -387, 1468, 533, +-1822, -612, 1575, 565, -944, -165, -288, -497, +1433, 1316, -2355, -1872, 2457, 2004, -2034, -1644, +1063, 1121, -205, -600, -511, 277, 650, -75, +-538, 76, 95, -209, 174, 463, -398, -629, +276, 614, -135, -280, -238, -290, 499, 981, +-854, -1433, 961, 1465, -1049, -1059, 906, 560, +-847, -224, 646, 218, -515, -392, 205, 592, +16, -591, -293, 354, 322, 61, -251, -395, +-125, 454, 458, -148, -774, -333, 702, 709, +-427, -640, -206, 29, 849, 1025, -1564, -2148, +2015, 2945, -2261, -3082, 1969, 2441, -1235, -1119, +-8, -549, 1254, 2062, -2248, -2890, 2502, 2758, +-2112, -1803, 1103, 554, -49, 402, -768, -727, +875, 477, -446, 69, -369, -601, 1002, 829, +-1274, -579, 920, -95, -206, 849, -686, -1297, +1262, 1269, -1462, -907, 1230, 459, -915, -148, +604, 48, -454, -131, 239, 208, 72, -104, +-591, -209, 1005, 517, -1146, -571, 770, 276, +-69, 169, -723, -476, 1135, 388, -972, 41, +224, -586, 672, 973, -1342, -1170, 1515, 1177, +-1274, -987, 718, 503, -91, 159, -435, -748, +646, 982, -563, -864, 326, 506, -141, -141, +68, -119, -82, 131, 97, 68, -62, -332, +-47, 368, 196, -112, -275, -292, 221, 480, +-51, -306, -96, -135, 131, 500, 32, -604, +-301, 342, 616, 144, -824, -714, 924, 1071, +-854, -1028, 649, 542, -270, 82, -134, -589, +528, 849, -791, -1009, 964, 1117, -903, -1176, +635, 1103, -198, -931, -27, 674, -91, -469, +651, 350, -1226, -386, 1544, 386, -1259, -175, +547, -363, 408, 944, -1073, -1210, 1258, 848, +-808, -12, 99, -890, 593, 1294, -808, -1041, +613, 326, -91, 327, -254, -640, 339, 551, +-13, -365, -361, 339, 655, -685, -429, 1176, +-174, -1436, 983, 1051, -1256, -132, 833, -918, +301, 1518, -1380, -1515, 1986, 944, -1626, -144, +587, -660, 850, 1192, -1912, -1458, 2365, 1476, +-1998, -1444, 1335, 1340, -548, -1189, 41, 792, +460, -186, -798, -624, 1179, 1319, -1256, -1758, +1245, 1743, -967, -1413, 730, 807, -268, -188, +-157, -384, 648, 716, -747, -932, 656, 998, +-304, -988, 175, 664, -72, -95, 178, -635, +-136, 1105, 204, -1282, -77, 1112, 24, -821, +221, 345, -322, 159, 554, -624, -592, 692, +683, -436, -403, -14, 56, 168, 542, -41, +-815, -289, 912, 429, -507, -481, 121, 391, +415, -287, -687, -119, 1041, 694, -1062, -1317, +1030, 1432, -509, -1033, -30, 140, 804, 674, +-1202, -1220, 1462, 1187, -1108, -840, 673, 252, +-24, 177, -161, -496, 334, 530, -294, -496, +632, 237, -735, 49, 770, -489, -222, 793, +-156, -974, 461, 688, -66, -123, -341, -691, +916, 1157, -867, -1154, 618, 484, 255, 252, +-897, -777, 1444, 700, -1139, -452, 656, 215, +182, -319, -445, 308, 596, -155, -130, -265, +-163, 348, 662, -71, -573, -601, 465, 1010, +95, -1078, -225, 617, 485, -69, -372, -621, +707, 1079, -780, -1374, 1112, 1106, -900, -589, +822, -105, -190, 400, -268, -464, 1113, 246, +-1350, -243, 1484, 307, -817, -593, 407, 595, +197, -373, -156, -262, 330, 696, 14, -824, +-110, 298, 705, 363, -786, -1026, 928, 1141, +-288, -921, -64, 256, 638, 277, -446, -686, +420, 617, 42, -481, 114, 196, -84, -154, +600, 74, -587, -168, 775, 92, -296, -125, +168, 2, 371, 41, -364, -408, 726, 796, +-567, -1180, 780, 900, -439, -211, 467, -718, +33, 1108, -100, -1164, 584, 832, -440, -539, +529, -93, -15, 763, 7, -1417, 315, 1332, +-34, -742, 142, -282, 330, 962, -440, -1350, +960, 1173, -681, -846, 472, 220, 319, 246, +-331, -654, 411, 581, 104, -382, 49, -13, +103, 74, 132, -51, 253, -212, -105, 300, +101, -548, 647, 742, -911, -1135, 1318, 1213, +-919, -1052, 785, 367, -183, 249, 125, -749, +276, 725, -187, -636, 578, 398, -527, -326, +790, 7, -369, 259, 207, -523, 369, 257, +-286, 188, 333, -760, 270, 880, -534, -783, +1065, 363, -837, -72, 603, -258, 243, 289, +-545, -268, 874, -52, -471, 276, 331, -557, +173, 561, -201, -562, 485, 314, -222, -132, +232, -158, 108, 148, 34, -45, 155, -293, +-60, 354, 399, -279, -276, -93, 292, 258, +123, -347, -46, 192, 67, -191, 322, 95, +-224, -41, 197, -255, 264, 447, -332, -623, +558, 484, -364, -302, 418, -109, -79, 453, +-71, -848, 554, 904, -631, -756, 765, 263, +-409, 169, 241, -578, 167, 647, -212, -555, +430, 138, -290, 231, 284, -546, 112, 447, +-305, -145, 596, -386, -333, 735, 13, -957, +591, 837, -697, -620, 670, 169, -246, 234, +155, -539, -33, 279, 211, 350, -135, -1057, +236, 1083, -153, -456, 287, -526, -168, 1048, +169, -986, 25, 439, -8, -22, 204, -140, +-263, -65, 434, 275, -245, -450, 122, 352, +66, -124, 137, -302, -271, 605, 456, -690, +-302, 343, 236, 126, -68, -538, 104, 656, +5, -681, -5, 577, 150, -377, -110, -56, +150, 358, 4, -296, -66, -205, 277, 560, +-314, -431, 350, -184, -54, 668, -318, -778, +844, 562, -995, -410, 774, 220, -22, 166, +-695, -776, 1196, 1093, -1166, -852, 1015, 241, +-783, 78, 693, 48, -408, -306, 51, 175, +403, 284, -551, -746, 530, 845, -324, -672, +290, 375, -286, -161, 362, 35, -321, -52, +380, 145, -457, -282, 588, 289, -474, -131, +218, -140, 86, 291, -112, -250, 48, 87, +-58, -39, 385, 128, -708, -232, 780, 174, +-395, -29, -122, -72, 519, 44, -542, 46, +288, -168, 167, 295, -563, -338, 702, 129, +-385, 329, -261, -729, 903, 692, -1163, -189, +980, -376, -531, 545, 51, -250, 331, -168, +-537, 372, 472, -330, -121, 197, -343, -82, +595, -26, -466, 151, 31, -260, 393, 315, +-584, -310, 481, 229, -283, -91, 126, -6, +-178, 34, 319, -58, -456, 177, 354, -310, +-51, 283, -409, -70, 704, -110, -752, 90, +443, 67, -88, -130, -147, 44, -3, 43, +313, 41, -617, -238, 525, 339, -176, -166, +-316, -154, 497, 329, -458, -114, 194, -320, +-68, 603, -41, -492, 15, 156, -65, 113, +-53, -137, 165, -12, -350, 202, 264, -299, +-93, 232, -206, 2, 236, -246, -146, 326, +-131, -196, 155, 33, -75, 84, -233, -170, +343, 324, -413, -419, 270, 276, -232, 106, +68, -397, -29, 346, -90, -47, -10, -74, +-24, -112, 78, 318, -430, -143, 571, -302, +-516, 580, -16, -405, 430, 82, -691, 36, +434, 88, -125, -45, -312, -311, 413, 747, +-417, -747, 74, 278, 126, 263, -300, -345, +136, 59, -102, 118, 20, 201, -187, -641, +185, 695, -295, -221, 184, -243, -98, 347, +-335, -128, 589, -32, -642, 147, 75, -305, +441, 495, -759, -365, 443, -86, -109, 590, +-259, -723, 296, 561, -461, -273, 420, 101, +-377, 45, -38, -84, 291, 51, -462, 131, +154, -251, 111, 280, -379, -178, 152, 129, +135, -17, -538, -168, 458, 486, -202, -605, +-341, 411, 558, 84, -637, -424, 297, 443, +-46, -124, -247, -91, 101, 79, 102, 161, +-443, -155, 304, -177, -18, 703, -460, -778, +464, 306, -282, 473, -230, -884, 506, 906, +-754, -691, 546, 589, -246, -374, -306, 115, +443, 156, -359, -129, -123, 94, 315, -151, +-388, 407, 64, -441, 144, 325, -458, -121, +436, 139, -376, -86, -12, -54, 177, 366, +-309, -440, 51, 363, 65, -88, -259, -42, +141, 142, -89, -70, -211, 22, 273, 164, +-327, -263, 11, 378, 124, -270, -292, 111, +137, 238, -158, -438, 26, 472, -53, -100, +-135, -236, 72, 394, -119, -142, 32, -14, +-284, 44, 341, 93, -322, 88, -177, -364, +492, 611, -695, -476, 350, 311, -40, -54, +-429, -112, 504, 415, -503, -447, 21, 309, +313, 43, -580, -84, 232, -48, 124, 361, +-536, -393, 377, 268, -122, 157, -396, -454, +534, 604, -633, -325, 301, 104, -105, 47, +-242, 40, 200, 112, -188, -253, -153, 307, +239, 92, -381, -402, 131, 456, -74, -25, +-85, -275, -109, 426, 43, -283, -36, 291, +-282, -212, 237, 134, -166, 215, -254, -430, +332, 551, -414, -276, 118, -69, -62, 571, +-132, -766, 28, 702, -169, -181, 139, -215, +-370, 391, 293, -106, -316, -84, 52, 165, +-82, 50, -24, -137, -125, 275, -32, -231, +-5, 258, -133, -123, -45, 83, 20, 105, +-202, -206, 122, 365, -242, -189, 65, -38, +-56, 294, -186, -153, 115, 28, -178, 44, +-34, 178, -20, -191, -93, 139, -72, 36, +26, 34, -175, 28, 5, -138, 6, 442, +-234, -414, 162, 180, -246, 277, 87, -419, +-141, 385, -66, -85, 37, -42, -137, 203, +-114, -206, 156, 267, -271, -48, -16, -224, +139, 582, -326, -595, 107, 448, -15, -79, +-223, -100, 129, 234, -169, -128, -30, 98, +26, 19, -223, 9, 142, 53, -133, 38, +-192, -65, 281, 187, -394, -116, 150, 97, +-106, -43, 9, 173, -196, -164, 142, 156, +-182, -39, 13, 108, -74, -71, -60, -29, +89, 361, -341, -507, 319, 483, -292, -161, +-33, -89, 140, 322, -297, -312, 182, 275, +-207, -110, 61, 68, -77, 29, -111, 1, +123, -6, -213, 186, 14, -292, 68, 363, +-230, -183, 123, 32, -149, 76, 78, 68, +-191, -167, 82, 216, -34, -67, -151, 17, +78, 16, -83, 19, 20, 128, -221, -241, +285, 297, -359, -141, 174, 77, -105, -93, +-45, 221, 40, -168, -148, 39, 42, 165, +61, -194, -338, 184, 367, -77, -309, 48, +18, 16, 82, -42, -131, 163, -47, -180, +69, 84, -82, 232, -93, -470, 129, 522, +-163, -303, 20, 93, -5, 58, -25, -77, +-98, 142, 101, -194, -122, 258, -16, -173, +54, 42, -126, 114, 24, -65, 32, -126, +-149, 382, 82, -417, -8, 258, -165, 34, +172, -212, -144, 268, -23, -169, 69, 63, +-79, 38, -87, -52, 199, 56, -271, -12, +96, -56, 127, 190, -348, -236, 278, 129, +-76, 130, -186, -257, 179, 136, -33, 187, +-208, -367, 245, 269, -156, 49, -95, -283, +275, 323, -409, -182, 330, 55, -171, 38, +-95, -78, 238, 150, -300, -207, 222, 256, +-177, -262, 117, 249, -99, -183, -3, 117, +90, -60, -202, 55, 231, -24, -246, -56, +168, 172, -60, -220, -123, 205, 224, -161, +-247, 165, 127, -144, -22, 53, -44, 97, +2, -166, 12, 97, -5, 83, -70, -234, +116, 280, -165, -207, 172, 94, -194, 11, +181, -70, -134, 85, -3, -70, 140, 82, +-224, -113, 157, 110, -11, -9, -130, -140, +140, 238, -50, -234, -69, 173, 110, -102, +-114, 54, 114, -37, -151, 75, 167, -130, +-148, 114, 82, 13, -21, -114, -70, 55, +173, 168, -275, -349, 291, 316, -208, -82, +75, -174, 12, 291, -21, -248, 11, 132, +-52, -51, 111, 68, -91, -141, -48, 185, +210, -141, -242, 34, 102, 76, 96, -138, +-179, 143, 131, -115, -30, 64, 1, -3, +-26, -60, 45, 121, -33, -131, 43, 112, +-89, -114, 173, 143, -220, -112, 208, -26, +-94, 180, -69, -162, 243, -77, -309, 359, +262, -434, -130, 239, 61, 73, -54, -308, +87, 398, -45, -362, -20, 223, 108, 2, +-158, -232, 217, 372, -220, -340, 166, 188, +-19, -18, -76, -82, 122, 101, -93, -98, +133, 124, -186, -173, 235, 199, -146, -153, +8, 31, 181, 118, -294, -221, 384, 212, +-323, -100, 190, -67, 14, 226, -82, -322, +83, 312, -19, -197, 71, -4, -100, 247, +110, -497, 37, 644, -144, -589, 237, 288, +-202, 107, 202, -374, -96, 343, -26, -105, +213, -128, -197, 204, 27, -145, 274, 21, +-329, 138, 156, -349, 227, 512, -431, -486, +450, 230, -215, 70, 20, -209, 158, 134, +-160, 8, 140, -98, 39, 108, -169, -135, +325, 206, -302, -313, 278, 383, -173, -363, +171, 217, -80, -14, 26, -164, 131, 242, +-141, -290, 155, 322, -27, -351, -7, 278, +107, -111, -86, -103, 121, 217, -12, -191, +-18, 38, 107, 89, -48, -101, 84, -27, +-76, 146, 213, -171, -228, 78, 258, 27, +-119, -117, 84, 181, -3, -270, 89, 303, +-83, -233, 142, 26, -27, 163, -7, -221, +100, 98, 11, 42, -57, -98, 178, 36, +-120, 15, 152, -18, -92, -23, 148, 11, +-34, 14, -3, -52, 150, 37, -123, -25, +165, 9, -72, -13, 82, -10, 57, 29, +-49, -75, 86, 76, 70, -54, -66, 12, +91, -55, 62, 122, -17, -138, -7, -2, +186, 165, -170, -234, 238, 143, -209, -35, +332, -38, -219, 43, 76, -73, 284, 55, +-401, -13, 449, -39, -207, -17, 78, 106, +131, -153, -142, 61, 231, 91, -131, -255, +159, 304, -71, -261, 157, 97, -61, 40, +23, -124, 193, 125, -198, -168, 236, 230, +-98, -271, 150, 157, -58, 32, 21, -240, +235, 326, -260, -298, 211, 118, 120, 94, +-206, -256, 194, 226, 98, -83, -146, -83, +142, 111, 73, -55, -59, 7, 77, -90, +46, 214, 47, -293, -22, 224, 94, -133, +25, 64, 18, -49, 25, -14, 63, 76, +69, -79, -139, -65, 347, 220, -319, -299, +318, 204, -117, -31, 73, -171, 43, 262, +40, -224, -14, 47, 120, 94, -26, -170, +-7, 149, 219, -131, -265, 77, 339, -2, +-167, -112, 104, 150, -4, -115, 136, 18, +-125, 52, 123, -138, 152, 155, -293, -123, +419, 27, -251, 13, 130, -13, 106, -5, +-166, -52, 297, 78, -248, -39, 277, -53, +-201, 36, 301, 76, -281, -206, 267, 180, +19, -57, -217, -78, 375, 74, -194, 16, +31, -125, 176, 94, -137, 41, 147, -212, +-50, 259, 50, -188, 77, 59, -70, 14, +77, -62, 68, 91, -36, -118, -34, 59, +260, 39, -283, -129, 249, 121, -70, -78, +46, 50, 6, -61, 3, 12, 142, 118, +-208, -258, 279, 271, -193, -162, 189, 28, +-143, 9, 181, 17, -79, -49, -2, 36, +166, -33, -178, -1, 207, 57, -100, -167, +53, 201, 73, -113, -109, -88, 176, 259, +-140, -299, 161, 165, -104, 13, 111, -139, +-32, 130, 7, -74, 79, 45, -66, -82, +77, 75, -8, 16, -22, -112, 85, 107, +-45, -35, -1, -2, 115, -37, -151, 64, +174, -27, -95, -45, 47, 53, 40, -11, +-69, -38, 134, 67, -148, -127, 197, 196, +-178, -213, 156, 97, -46, 99, -48, -263, +151, 288, -175, -184, 200, 26, -147, 51, +91, -27, 15, -64, -57, 137, 54, -166, +24, 149, -50, -104, 35, 31, 30, 35, +-31, -80, 18, 95, -1, -116, 46, 132, +-48, -105, -18, -7, 178, 136, -274, -202, +236, 174, -62, -92, -107, 17, 204, 26, +-181, -67, 129, 100, -80, -124, 75, 115, +-79, -75, 72, 22, -9, 17, -65, -56, +149, 80, -192, -106, 197, 139, -178, -161, +150, 140, -79, -78, -20, -19, 126, 91, +-172, -102, 124, 57, -7, -30, -81, 65, +57, -152, 59, 220, -156, -205, 134, 80, +4, 99, -146, -251, 194, 300, -160, -255, +110, 183, -116, -108, 129, 12, -116, 129, +62, -252, -12, 246, -5, -112, 4, -54, +1, 119, -26, -103, 65, 98, -103, -138, +59, 165, 49, -120, -160, 51, 160, -35, +-67, 64, -55, -41, 107, -77, -96, 191, +61, -185, -58, 67, 55, 32, -33, -31, +-17, -29, 25, 55, 3, -9, -39, -56, +-11, 87, 120, -68, -218, 33, 192, -20, +-75, 33, -55, -28, 80, -32, -19, 110, +-63, -121, 67, 28, -4, 82, -74, -111, +94, 24, -50, 102, -69, -180, 183, 190, +-270, -129, 260, 16, -183, 97, 52, -122, +63, 16, -130, 133, 113, -228, -43, 235, +-78, -193, 171, 136, -213, -50, 142, -53, +-7, 130, -146, -146, 197, 124, -151, -90, +32, 50, 62, -8, -124, -37, 144, 85, +-159, -137, 116, 159, -39, -93, -63, -46, +81, 164, -36, -161, -54, 69, 70, 16, +-33, -22, -49, -8, 81, 23, -81, 2, +43, -69, -9, 153, -50, -191, 60, 118, +-27, 83, -82, -298, 159, 386, -155, -301, +14, 125, 135, 41, -230, -110, 171, 78, +-50, 22, -72, -94, 75, 60, -17, 82, +-62, -211, 46, 212, 33, -79, -166, -68, +246, 127, -273, -75, 196, -39, -78, 162, +-79, -236, 173, 229, -213, -140, 160, 33, +-100, 50, 21, -98, 28, 121, -91, -84, +100, -18, -80, 127, 3, -139, 34, 41, +-36, 83, -16, -142, 36, 130, -34, -84, +-27, 19, 79, 77, -142, -170, 155, 192, +-146, -123, 70, 53, -18, -53, -3, 110, +-41, -154, 49, 144, -33, -84, -21, 4, +11, 94, -1, -180, -4, 237, -82, -231, +166, 167, -207, -66, 126, -32, -19, 98, +-91, -102, 112, 62, -102, -2, 46, -47, +-19, 86, -34, -94, 55, 85, -92, -68, +75, 92, -66, -156, 50, 227, -95, -248, +149, 194, -201, -85, 172, -40, -128, 142, +80, -179, -100, 139, 92, -36, -59, -58, +-50, 104, 120, -76, -164, 19, 127, 48, +-84, -83, -8, 80, 73, -25, -116, -40, +60, 75, -1, -57, -23, 19, -52, -5, +101, 16, -89, -12, -15, -31, 88, 85, +-117, -114, 83, 111, -76, -87, 52, 49, +-29, 7, -58, -42, 114, 50, -148, -36, +112, 16, -70, 24, -11, -102, 80, 202, +-157, -262, 170, 254, -178, -192, 166, 131, +-192, -73, 168, 2, -97, 92, -52, -163, +146, 172, -153, -104, 15, 10, 117, 57, +-173, -34, 38, -59, 160, 158, -306, -164, +245, 55, -60, 97, -124, -196, 152, 194, +-97, -126, 21, 68, -40, -53, 64, 95, +-85, -148, 58, 149, -71, -55, 68, -67, +-66, 116, 2, -21, 29, -125, -28, 182, +-34, -87, 54, -52, -65, 118, 31, -62, +-27, -24, -14, 77, 41, -59, -78, -10, +62, 107, -52, -187, 34, 208, -61, -138, +56, 36, -39, 26, -8, -32, 15, 31, +-18, -54, -16, 78, 46, -49, -106, -30, +124, 119, -109, -160, 8, 156, 91, -128, +-152, 92, 122, -58, -64, 21, -11, 12, +55, -33, -107, 30, 132, 2, -148, -52, +123, 86, -93, -94, 49, 66, -36, -12, +15, -46, -4, 82, -43, -67, 74, 5, +-83, 76, 13, -130, 70, 127, -102, -70, +25, -15, 74, 84, -121, -90, 54, 40, +22, 21, -65, -28, 42, -14, -30, 57, +18, -72, 6, 78, -88, -99, 169, 115, +-230, -82, 209, 48, -182, -45, 148, 86, +-144, -97, 108, 68, -63, -18, -19, -6, +95, 38, -177, -111, 215, 202, -212, -220, +149, 126, -76, 30, -19, -141, 84, 190, +-138, -183, 136, 144, -94, -64, 7, -22, +56, 81, -85, -92, 58, 91, -13, -108, +-36, 124, 51, -98, -34, 39, -18, -2, +64, 7, -79, -17, 33, -11, 17, 86, +-37, -136, -18, 107, 114, 0, -203, -113, +212, 159, -120, -124, -36, 45, 152, 23, +-163, -52, 79, 45, 15, -29, -42, 13, +8, -11, 15, 30, 10, -67, -50, 86, +50, -64, -10, 6, -16, 39, 4, -49, +25, 32, -24, -28, -12, 49, 53, -79, +-57, 86, 25, -70, 23, 43, -60, -26, +79, 18, -77, -9, 63, -15, -38, 54, +6, -88, 18, 97, -22, -56, 13, -28, +-4, 113, 12, -140, -31, 93, 42, -17, +-3, -37, -64, 32, 124, 4, -119, -30, +49, 19, 33, 23, -63, -64, 47, 64, +-16, -33, 23, -5, -53, 21, 67, -17, +-38, 26, -13, -47, 40, 53, -3, -12, +-82, -65, 158, 139, -163, -163, 100, 121, +-8, -49, -37, -12, 19, 43, 43, -51, +-94, 46, 111, -18, -92, -34, 69, 87, +-38, -118, 19, 127, -16, -126, 37, 108, +-27, -59, -16, -38, 91, 129, -145, -136, +130, 76, -51, -20, -32, 21, 75, -52, +-61, 64, 22, -45, 0, 40, 11, -30, +-44, -12, 77, 82, -72, -113, 37, 54, +7, 58, -55, -109, 107, 80, -156, -36, +198, 23, -173, -24, 84, -11, 52, 50, +-144, -42, 166, -22, -117, 62, 65, -36, +-32, -7, 28, -19, -11, 116, -18, -201, +56, 191, -53, -109, 17, 9, 39, 64, +-64, -102, 48, 105, 2, -61, -48, -11, +99, 61, -122, -83, 140, 70, -104, -59, +29, 39, 69, 1, -118, -58, 109, 96, +-52, -91, 15, 43, 7, 3, -16, -32, +47, 48, -80, -56, 84, 60, -35, -45, +-29, 5, 67, 47, -54, -81, 30, 68, +-1, -19, 1, -51, 10, 91, -36, -73, +86, 6, -103, 46, 70, -40, -3, 11, +-47, 3, 44, 12, 15, -5, -69, -60, +113, 131, -119, -156, 112, 126, -94, -76, +65, 43, -8, -18, -40, -21, 68, 49, +-52, -43, 30, 16, -13, -39, 34, 125, +-64, -215, 87, 216, -60, -114, 17, -40, +38, 150, -66, -176, 68, 132, -29, -51, +-30, -37, 98, 99, -124, -118, 104, 96, +-47, -62, 12, 46, -14, -45, 47, 27, +-52, 27, 6, -83, 77, 104, -124, -83, +108, 55, -34, -44, -43, 57, 82, -56, +-63, 22, 24, 37, 3, -81, -4, 106, +-8, -108, 23, 102, -20, -83, 17, 40, +-4, 19, -19, -60, 54, 73, -79, -64, +86, 57, -44, -70, -7, 71, 56, -44, +-69, -8, 69, 44, -59, -45, 63, 26, +-67, -6, 58, -4, -14, 22, -46, -49, +110, 63, -132, -45, 107, -1, -40, 44, +-16, -64, 49, 52, -46, -17, 28, -14, +10, 17, -42, 6, 62, -30, -49, 38, +10, -18, 47, -4, -85, 11, 93, 5, +-62, -20, 13, 14, 50, 10, -83, -49, +103, 64, -89, -52, 74, 12, -51, 30, +41, -60, -14, 52, -14, -9, 35, -53, +-39, 118, 38, -139, -28, 71, 48, 59, +-71, -178, 87, 206, -58, -143, 25, 45, +3, -12, 19, 45, -70, -75, 114, 41, +-92, 47, 23, -135, 64, 167, -104, -143, +94, 84, -37, -17, -12, -52, 56, 96, +-82, -94, 95, 53, -72, -3, 14, -23, +78, 23, -141, -33, 158, 66, -115, -102, +66, 111, -32, -96, 27, 76, -8, -52, +-41, 2, 121, 77, -172, -148, 163, 162, +-82, -116, -5, 48, 61, -1, -55, -37, +34, 80, -8, -122, 9, 115, -19, -43, +58, -54, -96, 81, 145, -25, -155, -66, +126, 113, -70, -84, 42, 22, -51, 20, +90, -31, -95, 32, 60, -46, 11, 55, +-59, -41, 74, 0, -46, 28, 27, -32, +-17, 20, 23, -18, -22, 32, 17, -34, +-3, 6, -6, 24, 28, -21, -49, -11, +50, 27, 6, 14, -99, -83, 185, 110, +-191, -65, 114, -10, 17, 45, -121, -25, +167, -3, -154, 0, 131, 16, -91, -29, +56, 24, -9, -26, -25, 44, 32, -45, +-7, 7, -18, 64, 15, -119, 37, 122, +-97, -79, 123, 24, -81, 18, 16, -44, +37, 38, -23, -2, -31, -49, 83, 67, +-66, -31, 5, -51, 56, 122, -70, -125, +42, 68, 1, -6, -18, -29, 30, 35, +-30, -57, 36, 87, -28, -94, 8, 56, +20, 1, -26, -37, 3, 49, 26, -55, +-32, 77, 22, -108, 3, 108, -12, -69, +13, 1, -10, 66, 8, -105, -2, 114, +-4, -99, 8, 73, -10, -27, 2, -17, +16, 45, -32, -46, 39, 36, -32, -24, +11, 28, 18, -42, -26, 44, 31, -43, +-29, 28, 32, 5, -43, -40, 46, 63, +-29, -41, -18, -9, 67, 63, -95, -80, +83, 64, -37, -37, -23, 23, 75, -7, +-91, -31, 79, 66, -36, -66, -20, 18, +82, 39, -125, -65, 142, 45, -126, 9, +68, -64, 28, 106, -125, -131, 182, 122, +-162, -69, 86, -13, 0, 78, -46, -91, +57, 51, -50, -6, 46, -16, -31, 11, +5, -10, 22, 8, -20, 10, -13, -42, +47, 52, -41, -17, 17, -56, 7, 93, +-10, -52, -3, -25, 5, 71, 6, -50, +-10, -8, -4, 53, 19, -69, -10, 67, +-19, -52, 31, 21, -13, 35, -19, -82, +22, 90, -4, -38, -21, -13, 13, 25, +24, 5, -60, -43, 80, 56, -88, -53, +90, 63, -87, -76, 60, 64, -11, -16, +-38, -30, 56, 30, -39, 16, 3, -52, +25, 40, -34, 3, 29, -40, 3, 41, +-45, -49, 81, 89, -86, -140, 58, 142, +-16, -76, -17, -14, 33, 74, -42, -90, +60, 74, -55, -60, 16, 37, 46, 3, +-90, -41, 84, 46, -38, -18, -8, -10, +37, 2, -50, 19, 73, -20, -84, -23, +63, 62, 10, -52, -103, -14, 156, 94, +-156, -118, 109, 80, -55, -17, 11, -21, +14, 29, -34, -12, 30, -8, -5, 34, +-41, -53, 77, 41, -83, 9, 55, -73, +-14, 98, -19, -62, 23, 1, -16, 38, +0, -29, 3, -3, -4, 27, 4, -57, +3, 85, -20, -116, 41, 109, -52, -57, +24, -19, 24, 78, -82, -94, 88, 86, +-54, -74, -3, 53, 29, -29, -34, 10, +13, -9, -16, 27, 14, -45, -11, 43, +-27, -22, 39, -1, -34, 34, -23, -76, +68, 115, -84, -133, 52, 100, -40, -32, +44, -36, -81, 64, 80, -61, -60, 53, +-3, -48, 32, 37, -54, -10, 34, -25, +-29, 43, 1, -41, 8, 21, -40, -7, +31, 2, -31, 4, -3, -18, -1, 33, +-13, -38, -12, 35, 2, -33, -16, 39, +-10, -44, -8, 47, -9, -25, -19, -9, +19, 42, -50, -73, 38, 82, -45, -72, +-1, 41, 8, 0, -56, -20, 46, 18, +-68, -1, 23, 6, -17, -36, -21, 72, +-10, -86, 10, 67, -51, -29, 26, -14, +-33, 42, -17, -42, 4, 17, -49, 31, +46, -71, -99, 80, 67, -49, -46, -4, +-43, 33, 49, -39, -63, 39, -19, -49, +26, 66, -48, -68, -23, 37, 29, 8, +-70, -41, 27, 40, -57, -8, 17, -19, +-31, 28, -44, -23, 50, 6, -89, 17, +5, -47, 29, 65, -105, -55, 40, 9, +-2, 48, -111, -74, 104, 45, -121, 18, +37, -75, -36, 88, -34, -58, 17, 17, +-89, 15, 74, -23, -129, 21, 76, -19, +-92, 22, 17, -29, -36, 47, -27, -71, +8, 84, -72, -80, 31, 53, -61, -10, +-11, -32, -21, 58, -18, -55, -49, 28, +20, 0, -69, -2, 7, -25, -26, 55, +-50, -63, 23, 42, -77, -17, 23, 1, +-57, -3, -4, 7, -45, -4, 6, -10, +-67, 32, 14, -52, -60, 71, 4, -60, +-58, 16, 15, 36, -52, -64, -37, 35, +32, 40, -127, -101, 83, 118, -120, -74, +36, 9, -62, 46, -10, -71, -26, 73, +-41, -71, 1, 72, -66, -67, 19, 49, +-76, -13, 20, -27, -62, 55, -17, -58, +-10, 48, -66, -23, 6, -9, -26, 46, +-75, -73, 54, 65, -99, -16, -8, -48, +16, 95, -101, -107, 42, 84, -61, -52, +-30, 32, -5, -21, -44, 10, -34, 12, +9, -38, -83, 67, 31, -85, -63, 86, +-34, -61, 26, 28, -103, -8, 56, 0, +-93, -11, 25, 23, -69, -35, 10, 39, +-48, -27, -25, -14, -8, 68, -54, -99, +-6, 90, -23, -46, -51, -3, 16, 27, +-63, -30, -6, 18, -21, 0, -53, -13, +19, 16, -76, 2, 14, -23, -40, 31, +-30, -14, -12, -20, -21, 47, -54, -44, +19, 17, -46, 10, -45, -23, 37, 26, +-91, -37, 22, 61, -37, -84, -29, 82, +-6, -40, -56, -30, 34, 99, -91, -129, +31, 109, -37, -53, -49, 4, 16, 22, +-35, -22, -39, 3, 16, 18, -58, -35, +14, 36, -53, -19, 14, -17, -45, 52, +-21, -60, 2, 43, -34, -19, -33, 5, +19, -3, -52, 7, -21, -9, 31, 4, +-88, 5, 38, -14, -42, 25, -25, -24, +4, 15, -35, -2, 2, -14, -36, 20, +2, -21, -17, 11, -32, -7, 16, -1, +-37, -5, -15, 17, -4, -25, -16, 18, +-32, 10, 8, -50, -17, 87, -52, -89, +62, 48, -90, 19, 27, -78, -5, 110, +-67, -93, 70, 47, -100, -1, 55, -17, +-41, 13, -23, -6, 31, 10, -61, -18, +20, 20, -11, -5, -34, -20, 29, 29, +-43, -16, -7, -19, 33, 63, -82, -103, +69, 107, -52, -71, -21, 11, 42, 45, +-59, -71, 17, 66, -2, -55, -22, 52, +5, -56, -16, 40, 7, 4, -35, -48, +22, 70, -11, -57, -31, 14, 41, 29, +-52, -55, 30, 51, -24, -31, 12, -9, +-13, 39, -20, -50, 50, 34, -84, -3, +64, -25, -22, 35, -46, -23, 77, -5, +-81, 32, 47, -46, -25, 40, 11, -30, +-14, 13, -6, 11, 25, -37, -42, 51, +29, -48, -5, 21, -16, 4, 8, -14, +8, -2, -19, 32, -11, -56, 46, 70, +-78, -53, 59, 14, -9, 44, -47, -96, +73, 114, -66, -87, 37, 34, -6, 13, +-26, -35, 50, 44, -74, -47, 78, 52, +-68, -36, 36, 3, -2, 36, -15, -65, +10, 72, 6, -61, -10, 32, -3, 2, +19, -25, -25, 30, 11, -12, -3, 2, +7, -7, -28, 33, 40, -50, -30, 41, +-2, -2, 36, -35, -55, 46, 43, -11, +-20, -34, -7, 58, 25, -27, -41, -41, +48, 106, -44, -125, 27, 88, 8, -29, +-38, -25, 55, 53, -49, -58, 33, 47, +-13, -33, 3, 23, 3, -25, -9, 36, +19, -41, -29, 31, 34, -13, -18, -5, +2, 5, 16, -4, -20, 15, 22, -30, +-24, 28, 35, 3, -42, -46, 37, 71, +-11, -64, -18, 30, 37, 9, -37, -36, +31, 39, -18, -32, 14, 15, -5, -8, +5, 0, 1, 1, -11, 3, 6, 8, +1, -14, -14, 14, 34, -3, -50, -8, +58, 16, -47, -13, 20, 0, 17, 23, +-49, -39, 63, 45, -52, -31, 22, 10, +21, 12, -50, -32, 68, 46, -58, -61, +32, 67, 5, -53, -32, 16, 46, 26, +-37, -61, 25, 59, 3, -40, -20, -5, +32, 48, -28, -74, 25, 64, -4, -32, +-12, -1, 27, 25, -31, -13, 28, -1, +-12, 24, -3, -20, 16, 7, -6, 14, +-3, -40, 20, 52, -29, -52, 34, 24, +-23, -2, 15, -32, 1, 40, -17, -41, +39, 20, -52, -1, 62, -12, -51, 15, +34, 10, -4, -23, -19, 54, 34, -41, +-26, 31, 14, 7, 10, -32, -21, 54, +24, -62, -8, 42, -4, -34, 20, -9, +-9, 7, -4, -28, 23, 7, -23, -5, +22, -16, 1, 16, -11, 2, 12, 6, +-7, 18, -2, 22, 3, -15, 4, 46, +-4, -21, 10, 13, 2, 10, -10, -28, +30, 26, -31, -56, 35, 25, -12, -29, +-9, -40, 41, 47, -46, -71, 44, 25, +-15, 20, -7, -43, 20, 57, -11, 7, +4, -22, 12, 75, -4, -33, 1, 27, +14, 18, -8, -15, 1, 11, 16, -12, +-22, -11, 33, -27, -16, -13, 7, -19, +13, -18, -22, -17, 37, 3, -26, -16, +18, 2, 18, 35, -35, -24, 49, 54, +-36, 22, 17, -25, 20, 89, -39, -55, +57, 43, -41, -7, 28, -23, 2, 8, +-15, -42, 30, 2, -13, -57, 12, 11, +1, -41, 12, -5, -13, -7, 26, 8, +-20, 0, 8, 32, 22, 11, -31, 12, +40, 47, -18, 0, -10, 21, 51, 15, +-57, -6, 49, -6, -9, 0, -18, -39, +45, 1, -35, -53, 27, 5, 6, -43, +-21, -16, 42, 23, -41, -46, 41, 40, +-11, 11, -11, -8, 42, 55, -55, 20, +58, -15, -28, 76, 10, -51, 20, 52, +-27, -32, 36, 9, -20, -30, 17, -17, +3, -7, -2, -64, 15, 48, -16, -99, +34, 84, -36, -92, 47, 76, -35, -17, +20, -10, 18, 92, -39, -72, 55, 91, +-35, -2, 12, -23, 28, 64, -32, -41, +30, -8, 5, 27, -18, -65, 36, 16, +-11, -27, -3, -25, 38, 1, -38, -21, +44, 10, -10, -16, 2, 22, 30, -5, +-30, 34, 41, -12, -20, 49, 18, -19, +7, 28, 0, -4, 17, 5, -4, -22, +22, 26, -12, -52, 24, 19, -3, -15, +13, -45, 6, 51, 13, -75, 4, 58, +13, -47, 13, 45, -6, -27, 37, 31, +-17, 5, 27, -11, 11, 51, -17, -47, +52, 57, -35, -57, 58, 40, -24, -36, +31, -13, 21, 32, -28, -77, 70, 64, +-52, -42, 56, -12, -2, 50, -2, -57, +38, 51, -8, -9, 17, -6, 19, 48, +0, -50, 26, 61, 13, -48, 0, 32, +36, -12, -5, -10, 16, 6, 34, -8, +-22, -18, 60, 14, -21, -19, 28, 5, +27, 6, -16, -8, 51, 19, -15, -9, +38, 27, 8, -27, 15, 50, 32, -41, +-8, 34, 48, 0, -4, -42, 26, 68, +25, -86, 2, 63, 33, -42, 14, -6, +14, 25, 25, -40, 16, 29, 19, -16, +27, 4, 6, 12, 39, -2, -5, 12, +49, -1, -3, 16, 29, -6, 31, 10, +-2, -3, 57, -7, -12, 10, 50, -28, +15, 31, 9, -56, 61, 47, -23, -43, +61, 5, 13, 20, 9, -47, 61, 46, +-19, -21, 48, 7, 20, 20, 10, -14, +41, 19, 21, -2, 14, -7, 53, 28, +-9, -42, 56, 50, 3, -42, 30, 17, +35, 2, 13, -34, 39, 33, 18, -40, +34, 25, 10, -20, 54, 10, -3, -9, +53, 2, 18, 16, 16, -27, 56, 42, +-11, -27, 62, 11, 3, 28, 35, -47, +37, 54, 5, -39, 60, 9, -3, 15, +52, -37, 13, 38, 34, -36, 26, 14, +26, 0, 39, -20, 7, 21, 52, -9, +2, -6, 44, 23, 28, -22, 12, 9, +58, 26, -6, -48, 54, 66, 18, -51, +24, 26, 42, 5, 19, -19, 30, 15, +42, -10, 14, 0, 39, -9, 37, 12, +1, -19, 70, 11, -12, -7, 52, -1, +29, -1, 6, -3, 62, 3, 5, -9, +30, 11, 52, -4, -2, -10, 55, 24, +20, -19, 14, 13, 53, 11, -3, -9, +50, 0, 23, 21, 18, -31, 47, 13, +9, 26, 33, -68, 37, 79, 6, -63, +49, 15, 18, 20, 24, -49, 36, 55, +14, -46, 37, 31, 23, -8, 24, -10, +33, 35, 21, -34, 28, 29, 28, 3, +23, -19, 29, 27, 32, -16, 20, -4, +25, 13, 39, -11, 2, -14, 54, 21, +5, -28, 29, 1, 51, 6, -14, -27, +69, 18, -2, -10, 30, -5, 45, 16, +-11, -9, 60, 10, 2, 5, 26, 3, +37, -2, 5, 18, 40, -26, 19, 27, +17, -13, 28, -9, 27, 19, 13, -37, +31, 24, 22, -12, 6, -24, 58, 38, +-20, -53, 56, 40, 11, -13, 5, -18, +62, 51, -33, -54, 70, 55, -12, -21, +27, 5, 35, 23, -7, -26, 47, 22, +2, -13, 20, 7, 28, -14, 7, 8, +24, -12, 24, -8, 7, 8, 26, -14, +23, 0, 0, 8, 41, -5, -6, 2, +29, 17, 20, -15, 9, 15, 30, -2, +13, 1, 11, 11, 27, -18, 18, 25, +-4, -33, 57, 15, -27, 1, 39, -38, +27, 50, -38, -54, 85, 30, -50, -4, +49, -25, 22, 35, -25, -35, 70, 33, +-28, -29, 34, 30, 19, -14, -5, 5, +29, 19, 6, -20, 3, 27, 24, -21, +8, 16, 6, -25, 29, 19, -8, -17, +25, -3, 12, 7, 1, -16, 32, 4, +-14, 5, 31, -2, -2, 0, 13, 11, +20, -4, -7, 0, 30, 19, -1, -20, +7, 19, 27, -1, -14, -17, 27, 31, +10, -41, -3, 21, 33, -6, -9, -26, +14, 35, 21, -39, -12, 15, 30, 10, +-3, -30, 7, 37, 15, -14, 5, -9, +7, 30, 19, -30, -5, 24, 15, -4, +16, -8, -13, 14, 34, -14, -10, 5, +7, -5, 25, 4, -21, -15, 32, 19, +-3, -26, 3, 13, 20, 8, -12, -23, +20, 33, 5, -17, -3, -3, 19, 34, +-8, -29, 14, 10, 8, 38, -5, -68, +24, 75, -11, -44, 14, -4, 10, 45, +0, -77, 15, 73, 5, -61, 6, 26, +11, -1, 12, -29, -6, 39, 25, -34, +-7, 23, 9, -9, 23, 11, -21, -15, +37, 21, -14, -3, 12, -23, 19, 44, +-13, -44, 21, 20, 9, 5, -5, -29, +16, 26, 5, -9, -8, -10, 27, 14, +-7, -6, 0, -8, 33, 19, -28, -19, +37, 14, -10, 6, 2, -13, 19, 36, +-10, -37, 12, 42, 10, -22, -3, -4, +12, 39, 5, -54, 0, 52, 12, -31, +-5, 15, 11, 1, 1, -4, 6, 11, +7, -12, -4, 24, 22, -18, -21, 22, +29, -5, -11, 10, 0, -3, 29, 18, +-40, -7, 46, 16, -31, 5, 14, 1, +11, 8, -14, -2, 20, 13, -14, -11, +13, 32, -13, -27, 19, 35, -20, -9, +12, 5, 9, 22, -29, -15, 37, 34, +-39, -8, 21, 16, -3, 8, -16, 8, +19, 4, -20, 22, 5, -7, 0, 16, +-18, 26, 2, -21, -4, 44, -21, -9, +14, 6, -26, 38, -2, -22, 3, 35, +-29, 3, 16, 6, -35, 30, 9, -7, +-19, 28, -14, 8, -1, 10, -28, 21, +0, 13, -27, 10, -8, 25, -19, 8, +-11, 3, -20, 43, -16, -22, -12, 40, +-36, 14, 4, -1, -47, 34, -2, 17, +-35, 1, -22, 35, -12, 17, -42, -15, +-1, 70, -48, -39, -11, 56, -37, 11, +-32, -3, -18, 59, -48, -28, -16, 61, +-41, -14, -32, 32, -26, 21, -45, 3, +-28, 38, -43, 7, -40, 27, -37, 15, +-44, 31, -43, 3, -39, 42, -55, 14, +-36, 14, -53, 38, -40, 5, -55, 24, +-43, 37, -57, 0, -50, 37, -48, 26, +-71, 5, -34, 48, -75, 3, -49, 28, +-55, 35, -78, 3, -36, 44, -86, 13, +-51, 24, -69, 38, -73, 10, -60, 39, +-76, 22, -63, 14, -74, 44, -66, 4, +-80, 43, -68, 21, -80, 22, -77, 35, +-71, 23, -82, 14, -76, 47, -77, 8, +-88, 27, -73, 48, -90, -8, -87, 60, +-77, 14, -100, 19, -73, 43, -99, 19, +-87, 22, -87, 45, -104, 17, -74, 25, +-114, 47, -72, 1, -111, 50, -83, 19, +-96, 20, -106, 49, -80, 5, -120, 48, +-74, 19, -121, 23, -84, 43, -105, 12, +-105, 27, -85, 49, -126, -9, -73, 62, +-132, 17, -81, 11, -116, 66, -107, -6, +-90, 44, -127, 33, -83, 16, -122, 37, +-94, 27, -112, 31, -105, 20, -110, 50, +-108, 6, -102, 41, -115, 30, -98, 18, +-123, 47, -87, 6, -126, 45, -95, 20, +-114, 27, -110, 37, -95, 10, -127, 48, +-80, 10, -131, 31, -82, 33, -126, 16, +-92, 34, -108, 27, -114, 20, -86, 36, +-136, 26, -70, 19, -140, 43, -81, 13, +-110, 30, -117, 31, -73, 13, -144, 41, +-61, 12, -136, 31, -82, 28, -102, 12, +-111, 39, -81, 11, -122, 33, -76, 21, +-119, 26, -82, 22, -108, 30, -99, 21, +-90, 29, -110, 24, -79, 20, -111, 31, +-80, 15, -104, 27, -91, 29, -92, 16, +-98, 27, -86, 32, -99, 4, -81, 39, +-98, 20, -84, 5, -95, 57, -83, -11, +-93, 38, -81, 32, -90, -6, -81, 51, +-82, 0, -96, 30, -68, 28, -99, 6, +-68, 34, -85, 10, -84, 22, -65, 21, +-98, 14, -58, 25, -93, 15, -65, 17, +-78, 20, -81, 20, -63, 15, -89, 23, +-60, 21, -86, 9, -66, 35, -68, 2, +-78, 19, -58, 32, -79, -9, -62, 43, +-69, 5, -68, 11, -60, 31, -67, -4, +-63, 29, -62, 9, -66, 15, -61, 19, +-64, 10, -57, 18, -60, 7, -58, 19, +-59, 9, -59, 17, -54, 10, -63, 17, +-54, 17, -58, 9, -55, 21, -50, 4, +-61, 21, -51, 16, -53, 5, -52, 22, +-47, 1, -52, 14, -46, 13, -51, 5, +-45, 16, -55, 11, -38, 9, -58, 10, +-33, 15, -56, 0, -41, 27, -43, -4, +-51, 21, -33, 8, -46, 1, -41, 21, +-40, 7, -50, 9, -30, 18, -49, 0, +-29, 12, -46, 15, -35, -2, -38, 23, +-39, 0, -32, 7, -38, 23, -36, -15, +-27, 34, -39, -14, -27, 16, -31, 16, +-35, -15, -21, 34, -45, -8, -17, 12, +-39, 16, -26, -6, -17, 13, -38, -1, +-13, 13, -40, 3, -13, 7, -25, 7, +-30, 0, -10, 18, -42, -5, -7, 20, +-31, -2, -15, 5, -16, 14, -32, -4, +-3, 19, -32, -8, -7, 14, -20, 5, +-17, -2, -12, 20, -22, -2, -12, 8, +-10, 7, -15, -1, -10, 9, -15, 9, +-14, 4, -5, 5, -18, 11, -2, 1, +-18, 7, -2, 15, -11, -8, -12, 24, +1, -3, -17, 5, 3, 17, -7, -9, +-9, 16, 8, 6, -20, -5, 16, 26, +-17, -17, 9, 22, -4, 1, 0, -5, +7, 21, -3, -7, 2, 9, 7, 18, +-5, -16, 14, 25, -2, -3, 6, 1, +11, 17, 2, -9, 11, 11, 11, 6, +0, -2, 20, 11, -2, 5, 18, 0, +9, 13, 4, 2, 24, 1, -4, 19, +25, -9, 6, 17, 16, -1, 16, 3, +8, 16, 20, -9, 9, 20, 19, -7, +19, 9, 9, 8, 27, -5, 13, 13, +22, -6, 18, 13, 13, 1, 26, 5, +10, 9, 23, 1, 17, 17, 20, -11, +28, 15, 15, 0, 28, -2, 19, 17, +22, -12, 30, 13, 12, 4, 34, -3, +14, 13, 27, -3, 26, 5, 15, 7, +32, 2, 14, 7, 31, 2, 24, 5, +21, 4, 33, 0, 20, 7, 28, 0, +31, 4, 17, 3, 36, 6, 19, -5, +35, 10, 21, -2, 27, 5, 29, 6, +26, -6, 30, 6, 29, 3, 26, -8, +35, 13, 21, -8, 33, 7, 24, 5, +33, -9, 29, 12, 30, -9, 29, 8, +32, -2, 31, -7, 31, 10, 31, -12, +28, 8, 33, -1, 24, -4, 37, 6, +24, -6, 35, 2, 27, 1, 35, -4, +29, 1, 34, -1, 27, 0, 36, -1, +26, 1, 38, -3, 24, 0, 36, 4, +28, -8, 35, 5, 32, -10, 34, 2, +29, -2, 33, -1, 32, -2, 34, -5, +30, 3, 32, -7, 36, 2, 26, -4, +38, 3, 28, -8, 43, -3, 26, 0, +38, -6, 30, 4, 35, -7, 35, -3, +32, 4, 30, -9, 42, 3, 21, -4, +49, -7, 22, 2, 44, -8, 25, 1, +41, -3, 32, -7, 38, 0, 38, -8, +34, -4, 39, -2, 36, -6, 31, 1, +40, -4, 30, -3, 41, -3, 34, -3, +33, -2, 40, -2, 29, -3, 46, -7, +32, -3, 43, -8, 37, -6, 39, -2, +33, -7, 45, 0, 29, -7, 46, 0, +29, -3, 47, -8, 32, 1, 44, -8, +32, 0, 41, -2, 38, -8, 39, -2, +39, -6, 41, -3, 30, -1, 47, -4, +29, -5, 49, -4, 31, -3, 42, -5, +40, -3, 35, -5, 46, -5, 32, -3, +45, -6, 33, 0, 42, -8, 40, -2, +37, -5, 41, -5, 36, 0, 38, -6, +40, -1, 34, -4, 47, -8, 29, 1, +45, -7, 31, 0, 40, -3, 35, 0, +39, -6, 40, -4, 41, -6, 39, -7, +39, 1, 35, -7, 42, 1, 35, -8, +41, 0, 37, -6, 41, -6, 38, 1, +40, -12, 39, 2, 39, -7, 38, -5, +44, -2, 32, -7, 44, 0, 35, -6, +42, -4, 40, -4, 37, -6, 43, -3, +33, -4, 46, -6, 36, -5, 41, -5, +40, -5, 37, -3, 43, -6, 36, 0, +38, -5, 41, -3, 39, -5, 43, -7, +37, -1, 41, -7, 35, 1, 40, -5, +34, -1, 39, 0, 34, -4, 39, 3, +37, -8, 42, -3, 39, -4, 42, -8, +35, 4, 41, -6, 34, -1, 41, 1, +37, -7, 40, -1, 40, -2, 38, -7, +44, -1, 39, -8, 39, -3, 44, -3, +35, -7, 47, 0, 32, -5, 41, 0, +39, -2, 33, -2, 49, -4, 31, -3, +47, -3, 37, -3, 40, -3, 43, -5, +34, 2, 44, -6, 37, 1, 42, -6, +42, -1, 34, -1, 48, -8, 36, 0, +46, -9, 38, 3, 40, -8, 44, -2, +39, -1, 38, -6, 43, 6, 32, -8, +49, 3, 39, -12, 47, -3, 46, -7, +37, -5, 49, 2, 33, -10, 48, 5, +40, -12, 40, 2, 47, -5, 29, -1, +53, -1, 34, -8, 43, 7, 45, -12, +33, 7, 50, -8, 37, -4, 48, -1, +41, -8, 44, 2, 46, -11, 41, 5, +42, -8, 47, -1, 41, -5, 43, -2, +41, 3, 39, -10, 51, 3, 38, -14, +45, 8, 41, -8, 40, -3, 51, 2, +31, -8, 53, 7, 38, -13, 44, 7, +45, -6, 38, -3, 51, 0, 38, -8, +50, 1, 39, -6, 40, 6, 43, -4, +39, 3, 46, -5, 39, 1, 42, 1, +45, -8, 45, 3, 40, -7, 48, 3, +39, -7, 49, 0, 40, -2, 39, -2, +48, 5, 31, -7, 55, 5, 34, -8, +48, 0, 46, -1, 31, -2, 61, -1, +}; \ No newline at end of file diff --git a/project/realtek_ameba1_va0_example/example_sources/i2s/src/main.c b/project/realtek_ameba1_va0_example/example_sources/i2s/src/main.c new file mode 100644 index 0000000..f12c454 --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/i2s/src/main.c @@ -0,0 +1,326 @@ +#include "FreeRTOS.h" +#include "task.h" +#include "diag.h" +#include "main.h" + +#include "i2s_api.h" + +/** + * @brief Main program. + * @param None + * @retval None + */ +#include "alc5651.c" +/* +extern void alc5651_init(void); +extern void alc5651_init_interface2(void); +extern void alc5651_reg_dump(void); +extern void alc5651_index_dump(void); +extern void alc5651_set_word_len(int len_idx); +*/ +i2s_t i2s_obj; + +#define I2S_DMA_PAGE_SIZE 768 // 2 ~ 4096 +#define I2S_DMA_PAGE_NUM 4 // Vaild number is 2~4 + +u8 i2s_tx_buf[I2S_DMA_PAGE_SIZE*I2S_DMA_PAGE_NUM]; +u8 i2s_rx_buf[I2S_DMA_PAGE_SIZE*I2S_DMA_PAGE_NUM]; + +#define SAMPLE_FILE +#define SAMPLE_FILE_RATE 44100 +#define SAMPLE_FILE_CHNUM 2 + +#define I2S_SCLK_PIN PC_1 +#define I2S_WS_PIN PC_0 +#define I2S_SD_PIN PC_2 + +#if defined(SAMPLE_FILE) +// no sample +// SR_96KHZ, +// SR_7p35KHZ, +// SR_29p4KHZ, +// SR_88p2KHZ +#if SAMPLE_FILE_RATE==8000 + #if SAMPLE_FILE_CHNUM==2 + #include "birds_8000_2ch_16b.c" + #undef SAMPLE_FILE_RATE + #define SAMPLE_FILE_RATE SR_8KHZ + #endif +#elif SAMPLE_FILE_RATE==11025 + #if SAMPLE_FILE_CHNUM==2 + #include "birds_11025_2ch_16b.c" + #undef SAMPLE_FILE_RATE + #define SAMPLE_FILE_RATE SR_11p02KHZ + #endif +#elif SAMPLE_FILE_RATE==16000 + #if SAMPLE_FILE_CHNUM==2 + #include "birds_16000_2ch_16b.c" + #undef SAMPLE_FILE_RATE + #define SAMPLE_FILE_RATE SR_16KHZ + #endif +#elif SAMPLE_FILE_RATE==22050 + #if SAMPLE_FILE_CHNUM==2 + #include "birds_22050_2ch_16b.c" + #undef SAMPLE_FILE_RATE + #define SAMPLE_FILE_RATE SR_22p05KHZ + #endif +#elif SAMPLE_FILE_RATE==24000 + #if SAMPLE_FILE_CHNUM==2 + #include "birds_24000_2ch_16b.c" + #undef SAMPLE_FILE_RATE + #define SAMPLE_FILE_RATE SR_24KHZ + #endif +#elif SAMPLE_FILE_RATE==32000 + #if SAMPLE_FILE_CHNUM==2 + #include "birds_32000_2ch_16b.c" + #undef SAMPLE_FILE_RATE + #define SAMPLE_FILE_RATE SR_32KHZ + #endif +#elif SAMPLE_FILE_RATE==44100 + #if SAMPLE_FILE_CHNUM==2 + #include "birds_44100_2ch_16b.c" + #undef SAMPLE_FILE_RATE + #define SAMPLE_FILE_RATE SR_44p1KHZ + #endif +#elif SAMPLE_FILE_RATE==48000 + #if SAMPLE_FILE_CHNUM==2 + #include "birds_48000_2ch_16b.c" + #undef SAMPLE_FILE_RATE + #define SAMPLE_FILE_RATE SR_48KHZ + #endif +#endif + +#if SAMPLE_FILE_CHNUM==2 + #undef SAMPLE_FILE_CHNUM + #define SAMPLE_FILE_CHNUM CH_STEREO +#endif + +int curr_cnt=0; +#else + +short test_sine16[16]={0, 12539/4, 23170/4, 30273/4, 32767/4, 30273/4, 23170/4, 12539/4, + 0, -12539/4, -23170/4, -30273/4, -32767/4, -30273/4, -23170/4, -12539/4}; +int test_sine24[16]={0, 12539*256/4, 23170*256/4, 30273*256/4, 32767*256/4, 30273*256/4, 23170*256/4, 12539*256/4, + 0, -12539*256/4, -23170*256/4, -30273*256/4, -32767*256/4, -30273*256/4, -23170*256/4, -12539*256/4}; + +extern void wait_ms(u32); + +#include +short remap_level_to_signed_16_bit(float val) +{ + val*=32767; + if(val>32767) val=32767; + if(val<-32768) val=-32768; + + return val; +} + +void generate_freq_16bit(short *buffer, int count, float freq, float sampling_rate) +{ + int pos; // sample number we're on + + for (pos = 0; pos < count; pos++) { + float a = 2 * 3.14159f * freq * pos / sampling_rate; + // convert from [-1.0,1.0] to [-32767,32767]: + buffer[pos] = remap_level_to_signed_16_bit(a); + } +} + +void gen_sound_sample16(short *buf, int buf_size, int channel_num) +{ + int i; + for (i = 0 ; i < buf_size ; i+=channel_num){ + buf[i] = test_sine16[(i/channel_num)%16]; + if(channel_num>=2) + buf[i+1] = test_sine16[(i/channel_num)%16]; + } +} + +void gen_sound_sample24(int *buf, int buf_size, int channel_num) +{ + int i; + for (i = 0 ; i < buf_size ; i+=channel_num){ + buf[i] = test_sine24[(i/channel_num)%16]&0xFFFFFF; + if(channel_num>=2) + //buf[i+1] = test_sine24[(i/channel_num)%16]&0xFFFFFF; + buf[i+1] = test_sine24[(i/channel_num)%16]&0xFFFFFF; + } +} + +#if 0 +void test_delay(int sec) +{ + for(int i=0;i<166*1000*100*sec;i++) + asm(" nop"); +} +#endif + +int test_rate_list[12] = { + SR_8KHZ, + SR_16KHZ, + SR_24KHZ, + SR_32KHZ, + SR_48KHZ, + SR_96KHZ, + SR_7p35KHZ, + SR_11p02KHZ, + SR_22p05KHZ, + SR_29p4KHZ, + SR_44p1KHZ, + SR_88p2KHZ +}; +#endif + +void test_tx_complete(void *data, char *pbuf) +{ + int *ptx_buf; + + i2s_t *obj = (i2s_t *)data; + static u32 count=0; + //DBG_8195A_I2S_LVL(VERI_I2S_LVL, "I2S%d %s\n",pI2SDemoHnd->DevNum,__func__); + count++; + if ((count&1023) == 1023) + { + DBG_8195A_I2S_LVL(VERI_I2S_LVL, ",\n"); + } + + ptx_buf = i2s_get_tx_page(obj); + //ptx_buf = (int*)pbuf; +#if defined(SAMPLE_FILE) + _memcpy((void*)ptx_buf, (void*)&sample[curr_cnt], I2S_DMA_PAGE_SIZE); + curr_cnt+=(I2S_DMA_PAGE_SIZE/sizeof(short)); + if(curr_cnt >= sample_size*(obj->channel_num==CH_MONO?1:2)) { + curr_cnt = 0; + } +#else + if(obj->word_length == WL_16b){ + gen_sound_sample16((short*)ptx_buf, I2S_DMA_PAGE_SIZE/sizeof(short), obj->channel_num==CH_MONO?1:2); + }else{ + gen_sound_sample24((int*)ptx_buf, I2S_DMA_PAGE_SIZE/sizeof(int), obj->channel_num==CH_MONO?1:2); + } +#endif + i2s_send_page(obj, (uint32_t*)ptx_buf); +} + +void test_rx_complete(void *data, char* pbuf) +{ + i2s_t *obj = (i2s_t *)data; + int *ptx_buf; + + static u32 count=0; + count++; + if ((count&1023) == 1023) + { + DBG_8195A_I2S_LVL(VERI_I2S_LVL, ".\n"); + } + + ptx_buf = i2s_get_tx_page(obj); + _memcpy((void*)ptx_buf, (void*)pbuf, I2S_DMA_PAGE_SIZE); + i2s_recv_page(obj); // submit a new page for receive + i2s_send_page(obj, (uint32_t*)ptx_buf); // loopback +} + +void main(void) +{ + int *ptx_buf; + int i,j; + + alc5651_init(); + alc5651_init_interface2(); // connect to ALC interface 2 + + // dump register + //alc5651_reg_dump(); + //alc5651_index_dump(); + + // I2S init + i2s_obj.channel_num = CH_MONO;//CH_STEREO; + i2s_obj.sampling_rate = SR_44p1KHZ; + i2s_obj.word_length = WL_16b; + i2s_obj.direction = I2S_DIR_TXRX; + i2s_init(&i2s_obj, I2S_SCLK_PIN, I2S_WS_PIN, I2S_SD_PIN); + i2s_set_dma_buffer(&i2s_obj, (char*)i2s_tx_buf, (char*)i2s_rx_buf, \ + I2S_DMA_PAGE_NUM, I2S_DMA_PAGE_SIZE); + i2s_tx_irq_handler(&i2s_obj, (i2s_irq_handler)test_tx_complete, (uint32_t)&i2s_obj); + i2s_rx_irq_handler(&i2s_obj, (i2s_irq_handler)test_rx_complete, (uint32_t)&i2s_obj); + +#if defined(SAMPLE_FILE) + i2s_set_param(&i2s_obj,SAMPLE_FILE_CHNUM,SAMPLE_FILE_RATE,WL_16b); + for (i=0;i= sample_size*(i2s_obj.channel_num==CH_MONO?1:2)) { + curr_cnt = 0; + } + } + } +#else + // output freq, @ sampling rate + // 6kHz @ 96kHz + // 3kHz @ 48kHz + // 2kHz @ 32kHz + // 1.5kHz @ 24kHz + // 1kHz @ 16kHz + // 500Hz @ 8kHz + // 5512.5 Hz @ 88200Hz + // 2756.25 Hz @ 44100Hz + // 1837.5 Hz @ 29400Hz + // 1378.125 Hz @ 22050Hz + // 459.375 Hz @ 7350Hz + + // Stereo, 16bit + for(i=0;i<12;i++){ + i2s_set_param(&i2s_obj,CH_STEREO,test_rate_list[i],WL_16b); + // Start with fill all pages of DMA buffer + for (j=0;j> 0); + uid[1] = (unsigned char)((nfc_tag_content[0] & 0x0000FF00) >> 8); + uid[2] = (unsigned char)((nfc_tag_content[0] & 0x00FF0000) >> 16); + bcc[0] = (unsigned char)((nfc_tag_content[0] & 0xFF000000) >> 24); + uid[3] = (unsigned char)((nfc_tag_content[1] & 0x000000FF) >> 0); + uid[4] = (unsigned char)((nfc_tag_content[1] & 0x0000FF00) >> 8); + uid[5] = (unsigned char)((nfc_tag_content[1] & 0x00FF0000) >> 16); + uid[6] = (unsigned char)((nfc_tag_content[1] & 0xFF000000) >> 24); + bcc[1] = (unsigned char)((nfc_tag_content[2] & 0x000000FF) >> 0); + + // verify Block Check Character + if (bcc[0] != (0x88 ^ uid[0] ^ uid[1] ^ uid[2])) { + valid_content = 0; + } + if (bcc[1] != (uid[3] ^ uid[4] ^ uid[5] ^ uid[6])) { + valid_content = 0; + } + + return valid_content; +} + +unsigned int generate_default_tag_content() { + unsigned int page_size = 0; + + memset(nfc_tag_content, 0, NFC_MAX_PAGE_NUM * sizeof(unsigned int)); + + // calculate Block Check Character + unsigned char bcc[2]; + bcc[0] = 0x88 ^ nfc_default_uid[0] ^ nfc_default_uid[1] ^ nfc_default_uid[2]; + bcc[1] = nfc_default_uid[3] ^ nfc_default_uid[4] ^ nfc_default_uid[5] ^ nfc_default_uid[6]; + + // generate header + nfc_tag_content[page_size++] = ((unsigned int)nfc_default_uid[0]) << 0 | + ((unsigned int)nfc_default_uid[1]) << 8 | + ((unsigned int)nfc_default_uid[2]) << 16 | + ((unsigned int) bcc[0]) << 24; + nfc_tag_content[page_size++] = ((unsigned int)nfc_default_uid[3]) << 0 | + ((unsigned int)nfc_default_uid[4]) << 8 | + ((unsigned int)nfc_default_uid[5]) << 16 | + ((unsigned int)nfc_default_uid[6]) << 24; + nfc_tag_content[page_size++] = ((unsigned int) bcc[1]) << 0; + nfc_tag_content[page_size++] = 0x001211E1; + + // Init tag content as NDEF will-known text message "HELLO WORLD!" in little endian + nfc_tag_content[page_size++] = 0x01d11303; + nfc_tag_content[page_size++] = 0x6502540f; + nfc_tag_content[page_size++] = 0x4c45486e; + nfc_tag_content[page_size++] = 0x57204f4c; + nfc_tag_content[page_size++] = 0x444c524f; + nfc_tag_content[page_size++] = 0x0000fe21; + + return page_size; +} + +void nfc_load_tag_content_from_flash() { + int i, address, page_size; + + memset(nfc_tag_content, 0, NFC_MAX_PAGE_NUM * sizeof(unsigned int)); + memset(nfc_tag_dirty, 0, NFC_MAX_PAGE_NUM); + + for (i = 0, address = FLASH_APP_NFC_BASE; i < NFC_MAX_PAGE_NUM; i++, address+=4) { + flash_read_word(&flash_nfc, address, &nfc_tag_content[i]); + } + + if (!is_valid_nfc_uid() || NFC_RESTORE_DEFAULT) { + DiagPrintf("Invalid tag content, restore to default value\r\n"); + page_size = generate_default_tag_content(); + + // update to flash + flash_erase_sector(&flash_nfc, FLASH_APP_NFC_BASE); + for (i = 0, address = FLASH_APP_NFC_BASE; i < page_size; i++, address += 4) { + flash_write_word(&flash_nfc, address, nfc_tag_content[i]); + } + } +} + +void nfc_store_tag_content_to_flash() { + int i, address; + int modified_page_count; + + // dump the modified tag content + modified_page_count = 4; // 4 for tag header + for (i = 4; i < NFC_MAX_PAGE_NUM && nfc_tag_dirty[i]; i++) { + modified_page_count++; + DiagPrintf("page:%02d data:%08x\r\n", i, nfc_tag_content[i]); + } + + flash_erase_sector(&flash_nfc, FLASH_APP_NFC_BASE); + for (i = 0, address = FLASH_APP_NFC_BASE; i < modified_page_count; i++, address += 4) { + flash_write_word(&flash_nfc, address, nfc_tag_content[i]); + } +} + +void nfc_task(void const *arg) { + int i; + osEvent evt; + + nfc_load_tag_content_from_flash(); + + nfc_init(&nfctag, nfc_tag_content); + nfc_event(&nfctag, nfc_event_listener, NULL, 0xFF); + nfc_write(&nfctag, nfc_write_listener, NULL); + + osSignalClear(nfc_tid, NFC_EV_WRITE); + + while(1) { + evt = osSignalWait (0, 0xFFFFFFFF); // wait for any signal with max timeout + if (evt.status == osEventSignal && (evt.value.signals & NFC_EV_WRITE)) { + osDelay(300); + + nfc_store_tag_content_to_flash(); + + memset(nfc_tag_dirty, 0, NFC_MAX_PAGE_NUM); + osSignalClear(nfc_tid, NFC_EV_WRITE); + } + } +} + +/** + * @brief Main program. + * @param None + * @retval None + */ +void main(void) +{ + osThreadDef(nfc_task, osPriorityRealtime, 1, 1024); + nfc_tid = osThreadCreate (osThread (nfc_task), NULL); + + DBG_INFO_MSG_OFF(_DBG_SPI_FLASH_); + + //3 3)Enable Schedule, Start Kernel +#if defined(CONFIG_KERNEL) && !TASK_SCHEDULER_DISABLED + #ifdef PLATFORM_FREERTOS + vTaskStartScheduler(); + #endif +#else + RtlConsolTaskRom(NULL); +#endif + + while(1); +} + diff --git a/project/realtek_ameba1_va0_example/example_sources/pm_deepsleep/readme.txt b/project/realtek_ameba1_va0_example/example_sources/pm_deepsleep/readme.txt new file mode 100644 index 0000000..41af518 --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/pm_deepsleep/readme.txt @@ -0,0 +1,18 @@ +Example Description + +This example describes how to use deep sleep api. + +Requirement Components: + a LED + a push button + +Pin name PC_4 and PC_5 map to GPIOC_4 and GPIOC_5: + - PC_4 as input with internal pull-high, connect a push button to this pin and ground. + - PC_5 as output, connect a LED to this pin and ground. + +In this example, LED is turned on after device initialize. +User push the button to turn off LED and trigger device enter deep sleep mode for 10s. +If user press any key before sleep timeout, the system will resume. +LED is turned on again after device initialize. + +It can be easily measure power consumption in normal mode and deep sleep mode before/after push the putton. diff --git a/project/realtek_ameba1_va0_example/example_sources/pm_deepsleep/src/main.c b/project/realtek_ameba1_va0_example/example_sources/pm_deepsleep/src/main.c new file mode 100644 index 0000000..88de348 --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/pm_deepsleep/src/main.c @@ -0,0 +1,67 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2015 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#include "device.h" +#include "gpio_api.h" // mbed +#include "gpio_irq_api.h" // mbed +#include "sleep_ex_api.h" +#include "sys_api.h" +#include "diag.h" +#include "main.h" + +#define GPIO_LED_PIN PC_5 +#define GPIO_IRQ_PIN PC_4 + +// deep sleep can only be waked up by GPIOB_1 and GTimer +#define GPIO_WAKE_PIN PB_1 + +void gpio_demo_irq_handler (uint32_t id, gpio_irq_event event) +{ + gpio_t *gpio_led; + gpio_led = (gpio_t *)id; + + printf("Enter deep sleep...Wait 10s or give rising edge at PB_1 to wakeup system.\r\n\r\n"); + + // turn off led + gpio_write(gpio_led, 0); + + // turn off log uart + sys_log_uart_off(); + + // initialize wakeup pin at PB_1 + gpio_t gpio_wake; + gpio_init(&gpio_wake, GPIO_WAKE_PIN); + gpio_dir(&gpio_wake, PIN_INPUT); + gpio_mode(&gpio_wake, PullDown); + + // enter deep sleep + deepsleep_ex(DSLEEP_WAKEUP_BY_GPIO | DSLEEP_WAKEUP_BY_TIMER, 10000); +} + +void main(void) +{ + gpio_t gpio_led; + gpio_irq_t gpio_btn; + + // Init LED control pin + gpio_init(&gpio_led, GPIO_LED_PIN); + gpio_dir(&gpio_led, PIN_OUTPUT); // Direction: Output + gpio_mode(&gpio_led, PullNone); // No pull + + // Initial Push Button pin as interrupt source + gpio_irq_init(&gpio_btn, GPIO_IRQ_PIN, gpio_demo_irq_handler, (uint32_t)(&gpio_led)); + gpio_irq_set(&gpio_btn, IRQ_FALL, 1); // Falling Edge Trigger + gpio_irq_enable(&gpio_btn); + + // led on means system is in run mode + gpio_write(&gpio_led, 1); + printf("\r\nPush button at PC_4 to enter deep sleep\r\n"); + + while(1); +} diff --git a/project/realtek_ameba1_va0_example/example_sources/pm_deepstandby/readme.txt b/project/realtek_ameba1_va0_example/example_sources/pm_deepstandby/readme.txt new file mode 100644 index 0000000..554b71d --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/pm_deepstandby/readme.txt @@ -0,0 +1,18 @@ +Example Description + +This example describes how to use deep standby api. + +Requirement Components: + a LED + a push button + +Pin name PA_5 and PC_5 map to GPIOA_5 and GPIOC_5: + - PA_5 as input, connect a push button to this pin and 3v3. + - PC_5 as output, connect a LED to this pin and ground. + +In this example, LED is turned on after device initialize. +User push the button to turn off LED and trigger device enter deep standby mode for 10s. +If user press button before sleep timeout, the system will resume. +LED is turned on again after device initialize. + +It can be easily measure power consumption in normal mode and deep standby mode before/after push the putton. diff --git a/project/realtek_ameba1_va0_example/example_sources/pm_deepstandby/src/main.c b/project/realtek_ameba1_va0_example/example_sources/pm_deepstandby/src/main.c new file mode 100644 index 0000000..89e8a95 --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/pm_deepstandby/src/main.c @@ -0,0 +1,61 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2015 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#include "device.h" +#include "gpio_api.h" // mbed +#include "sleep_ex_api.h" +#include "diag.h" +#include "main.h" + +#define GPIO_LED_PIN PC_5 +#define GPIO_PUSHBT_PIN PA_5 + +/** + * @brief Main program. + * @param None + * @retval None + */ +void main(void) +{ + gpio_t gpio_led, gpio_btn; + int old_btn_state, new_btn_state; + + DBG_INFO_MSG_OFF(_DBG_GPIO_); + + // Init LED control pin + gpio_init(&gpio_led, GPIO_LED_PIN); + gpio_dir(&gpio_led, PIN_OUTPUT); // Direction: Output + gpio_mode(&gpio_led, PullNone); // No pull + + // Initial Push Button pin + gpio_init(&gpio_btn, GPIO_PUSHBT_PIN); + gpio_dir(&gpio_btn, PIN_INPUT); // Direction: Input + gpio_mode(&gpio_btn, PullDown); + + old_btn_state = new_btn_state = 0; + gpio_write(&gpio_led, 1); + + DiagPrintf("Push button to sleep...\r\n"); + while(1){ + new_btn_state = gpio_read(&gpio_btn); + + if (old_btn_state == 1 && new_btn_state == 0) { + gpio_write(&gpio_led, 0); + gpio_mode(&gpio_btn, PullUp); + + DiagPrintf("Sleep 8s... (Or wakeup by pushing button)\r\n"); + standby_wakeup_event_add(STANDBY_WAKEUP_BY_STIMER, 8000, 0); + standby_wakeup_event_add(STANDBY_WAKEUP_BY_PA5, 0, 1); + deepstandby_ex(); + DiagPrintf("This line should not be printed\r\n"); + } + old_btn_state = new_btn_state; + } +} + diff --git a/project/realtek_ameba1_va0_example/example_sources/pm_sleep/readme.txt b/project/realtek_ameba1_va0_example/example_sources/pm_sleep/readme.txt new file mode 100644 index 0000000..f3ece4e --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/pm_sleep/readme.txt @@ -0,0 +1,18 @@ +Example Description + +This example describes how to use sleep api. + +Requirement Components: + a LED + a push button + +Pin name PC_4 and PC_5 map to GPIOC_4 and GPIOC_5: + - PC_4 as input with internal pull-high, connect a push button to this pin and ground. + - PC_5 as output, connect a LED to this pin and ground. + +In this example, LED is turned on after device initialize. +User push the button to turn off LED and trigger device enter sleep mode for 10s. +If user push button before sleep timeout, the system will resume. +LED is turned on again after system resume without restart PC. + +It can be easily measure power consumption in normal mode and sleep mode before/after push the putton. diff --git a/project/realtek_ameba1_va0_example/example_sources/pm_sleep/src/main.c b/project/realtek_ameba1_va0_example/example_sources/pm_sleep/src/main.c new file mode 100644 index 0000000..947701c --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/pm_sleep/src/main.c @@ -0,0 +1,81 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2015 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#include "device.h" +#include "gpio_api.h" // mbed +#include "gpio_irq_api.h" // mbed +#include "sleep_ex_api.h" +#include "sys_api.h" +#include "diag.h" +#include "main.h" + +#define GPIO_LED_PIN PC_5 +#define GPIO_IRQ_PIN PC_4 + +int led_ctrl = 0; +gpio_t gpio_led; + +int put_to_sleep = 0; + +void gpio_demo_irq_handler (uint32_t id, gpio_irq_event event) +{ + gpio_t *gpio_led; + + gpio_led = (gpio_t *)id; + + if (led_ctrl == 1) { + led_ctrl = 0; + gpio_write(gpio_led, led_ctrl); + put_to_sleep = 1; + } else { + led_ctrl = 1; + gpio_write(gpio_led, led_ctrl); + } +} + +/** + * @brief Main program. + * @param None + * @retval None + */ +void main(void) +{ + gpio_irq_t gpio_btn; + + DBG_INFO_MSG_OFF(_DBG_GPIO_); + + // Init LED control pin + gpio_init(&gpio_led, GPIO_LED_PIN); + gpio_dir(&gpio_led, PIN_OUTPUT); // Direction: Output + gpio_mode(&gpio_led, PullNone); // No pull + + // Initial Push Button pin as interrupt source + gpio_irq_init(&gpio_btn, GPIO_IRQ_PIN, gpio_demo_irq_handler, (uint32_t)(&gpio_led)); + gpio_irq_set(&gpio_btn, IRQ_FALL, 1); + gpio_irq_enable(&gpio_btn); + + led_ctrl = 1; + gpio_write(&gpio_led, led_ctrl); + DBG_8195A("Push button to enter sleep\r\n"); + + put_to_sleep = 0; + while(1) { + if (put_to_sleep) { + DBG_8195A("Sleep 8s or push button to resume system...\r\n"); + sys_log_uart_off(); + sleep_ex(SLP_GPIO | SLEEP_WAKEUP_BY_STIMER, 8000); // sleep_ex can't be put in irq handler + sys_log_uart_on(); + DBG_8195A("System resume\r\n"); + + put_to_sleep = 0; + led_ctrl = 1; + gpio_write(&gpio_led, led_ctrl); + } + } +} diff --git a/project/realtek_ameba1_va0_example/example_sources/pwm-buzzer/readme.txt b/project/realtek_ameba1_va0_example/example_sources/pwm-buzzer/readme.txt new file mode 100644 index 0000000..f7d022d --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/pwm-buzzer/readme.txt @@ -0,0 +1,10 @@ +Example Description + +This example describes how to use pwm buzzer on extend board + +Requirement Components: + extend board, buzzer + +Connect extend board to 2v0 dap board, and connect buzzer on the extend board's buzzer pin, then the buzzer would play sound from Do to higher Do. + + \ No newline at end of file diff --git a/project/realtek_ameba1_va0_example/example_sources/pwm-buzzer/src/main.c b/project/realtek_ameba1_va0_example/example_sources/pwm-buzzer/src/main.c new file mode 100644 index 0000000..3f6cf4e --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/pwm-buzzer/src/main.c @@ -0,0 +1,63 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#include "device.h" +#include "pwmout_api.h" // mbed +#include "main.h" +#include "os_support.h" + +#define PWM_1 PC_0 +#define PWM_2 PC_1 +#define PWM_3 PC_2 +#define PWM_4 PC_3 + + + +pwmout_t pwm_led[4]; +PinName pwm_led_pin[4] = {PWM_1, PWM_2, PWM_3, PWM_4}; +float period[8] = {1.0/523, 1.0/587, 1.0/659, 1.0/698, 1.0/784, 1.0/880, 1.0/988, 1.0/1047}; + +extern void RtlMsleepOS(u32 ms); + +void pwm_delay(void) +{ + for(int i=0;i<1000000;i++) + asm(" nop"); +} + +/** + * @brief Main program. + * @param None + * @retval None + */ +//int main_app(IN u16 argc, IN u8 *argv[]) +void main(void) +{ + int i; + + + pwmout_init(&pwm_led[3], pwm_led_pin[3]); + + + + while (1) { + + for(i=0; i<8; i++){ + pwmout_period(&pwm_led[3], period[i]); + pwmout_pulsewidth(&pwm_led[3], period[i]/2); + Mdelay(1000); + } + + +// wait_ms(20); +// RtlMsleepOS(25); + pwm_delay(); + } +} + diff --git a/project/realtek_ameba1_va0_example/example_sources/pwm/readme.txt b/project/realtek_ameba1_va0_example/example_sources/pwm/readme.txt new file mode 100644 index 0000000..1848241 --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/pwm/readme.txt @@ -0,0 +1,13 @@ +Example Description + +This example describes how to use pwm + +Requirement Components: + extend board + +Connect LED to below PWM pins and ground, then the LED would gradually become brighter and then darker with different speed. + - connect a LED to PC_0 and ground + - connect a LED to PC_1 and ground + - connect a LED to PC_2 and ground + - connect a LED to PC_3 and ground + \ No newline at end of file diff --git a/project/realtek_ameba1_va0_example/example_sources/pwm/src/main.c b/project/realtek_ameba1_va0_example/example_sources/pwm/src/main.c new file mode 100644 index 0000000..98b01ee --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/pwm/src/main.c @@ -0,0 +1,94 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#include "device.h" +#include "pwmout_api.h" // mbed +#include "main.h" + +#define PWM_1 PC_0 +#define PWM_2 PC_1 +#define PWM_3 PC_2 +#define PWM_4 PC_3 +#define PWM_PERIOD 20000 +#define USE_FLOAT 0 + +#if USE_FLOAT +#define PWM_STEP (1.0/20.0) +float pwms[4]={0.0, 0.25, 0.5, 0.75}; +float steps[4]={PWM_STEP, PWM_STEP, PWM_STEP, PWM_STEP}; +#else +#define PWM_STEP (PWM_PERIOD/20) +int pwms[4]={0, PWM_PERIOD/4, PWM_PERIOD/2, PWM_PERIOD/4*3}; +int steps[4]={PWM_STEP,PWM_STEP,PWM_STEP,PWM_STEP}; +#endif + +pwmout_t pwm_led[4]; +PinName pwm_led_pin[4] = {PWM_1, PWM_2, PWM_3, PWM_4}; + +extern void RtlMsleepOS(u32 ms); + +void pwm_delay(void) +{ + for(int i=0;i<1000000;i++) + asm(" nop"); +} + +/** + * @brief Main program. + * @param None + * @retval None + */ +//int main_app(IN u16 argc, IN u8 *argv[]) +void main(void) +{ + int i; + + for (i=0; i<4; i++) { + pwmout_init(&pwm_led[i], pwm_led_pin[i]); + pwmout_period_us(&pwm_led[i], PWM_PERIOD); + } + + while (1) { +#if USE_FLOAT + for (i=0; i<4; i++) { + pwmout_write(&pwm_led[i], pwms[i]); + + pwms[i] += steps[i]; + if (pwms[i] >= 1.0) { + steps[i] = -PWM_STEP; + pwms[i] = 1.0; + } + + if (pwms[i] <= 0.0) { + steps[i] = PWM_STEP; + pwms[i] = 0.0; + } + } +#else + for (i=0; i<4; i++) { + pwmout_pulsewidth_us(&pwm_led[i], pwms[i]); + + pwms[i] += steps[i]; + if (pwms[i] >= PWM_PERIOD) { + steps[i] = -PWM_STEP; + pwms[i] = PWM_PERIOD; + } + + if (pwms[i] <= 0) { + steps[i] = PWM_STEP; + pwms[i] = 0; + } + } +#endif +// wait_ms(20); +// RtlMsleepOS(25); + pwm_delay(); + } +} + diff --git a/project/realtek_ameba1_va0_example/example_sources/spi/readme.txt b/project/realtek_ameba1_va0_example/example_sources/spi/readme.txt new file mode 100644 index 0000000..7a3541c --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/spi/readme.txt @@ -0,0 +1,23 @@ +Example Description + +This example describes how to use SPI read/write by mbed api. + + +The SPI Interface provides a "Serial Peripheral Interface" Master. + +This interface can be used for communication with SPI slave devices, +such as FLASH memory, LCD screens and other modules or integrated circuits. + +In this example, it use 2 sets of SPI. One is master, the other is slave. +By default it use SPI0 as slave, and use SPI2 as master. +So we connect them as below: + Connect SPI0_MOSI (PC_2) to SPI2_MOSI (PA_1) + Connect SPI0_MISO (PC_3) to SPI2_MISO (PA_0) + Connect SPI0_SCLK (PC_1) to SPI2_SCLK (PA_2) + Connect SPI0_CS (PC_0) to SPI2_CS (PA_4) + +Because some GPIOA are used as SDIO purpose which has higher priority. +So we need pull high PA_7 when device boot up. + Connect PA_7 to 3V3 + +After boot up, the master will send data to slave and shows result on LOG_OUT. \ No newline at end of file diff --git a/project/realtek_ameba1_va0_example/example_sources/spi/src/main.c b/project/realtek_ameba1_va0_example/example_sources/spi/src/main.c new file mode 100644 index 0000000..459e752 --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/spi/src/main.c @@ -0,0 +1,127 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2014 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#include "device.h" +#include "diag.h" +#include "main.h" +#include "spi_api.h" + +#define FakeMbedAPI 1 + +// SPI0 (S0) +#define SPI0_MOSI PC_2 +#define SPI0_MISO PC_3 +#define SPI0_SCLK PC_1 +#define SPI0_CS PC_0 + +// SPI1 (S1) +#define SPI1_MOSI PB_6 +#define SPI1_MISO PB_7 +#define SPI1_SCLK PB_5 +#define SPI1_CS PB_4 + +#if 1 +// SPI2 (S2) for DEV 3V0 +// Please note that PA_7 need pull high before using GPIOA group +#define SPI2_MOSI PA_1 +#define SPI2_MISO PA_0 +#define SPI2_SCLK PA_2 +#define SPI2_CS PA_4 +#else +// SPI2 (S2) +#define SPI2_MOSI PD_2 +#define SPI2_MISO PD_3 +#define SPI2_SCLK PD_1 +#define SPI2_CS PD_0 +#endif + +/** + * @brief Main program. + * @param None + * @retval None + */ +spi_t spi_master; +spi_t spi_slave; + +void main(void) +{ +#if FakeMbedAPI + + /* SPI0 is as Slave */ + //SPI0_IS_AS_SLAVE = 1; + + spi_init(&spi_master, SPI2_MOSI, SPI2_MISO, SPI2_SCLK, SPI2_CS); + spi_format(&spi_master, 8, 0, 0); + spi_frequency(&spi_master, 200000); + spi_init(&spi_slave, SPI0_MOSI, SPI0_MISO, SPI0_SCLK, SPI0_CS); + spi_format(&spi_slave, 8, 0, 1); + + int TestingTimes = 10; + int Counter = 0; + int TestData = 0; + int ReadData = 0; + + int result = 1; + + /** + * Master read/write, Slave read/write + */ + DBG_SSI_INFO("--------------------------------------------------------\n"); + for(Counter = 0, TestData=0x01; Counter < TestingTimes; Counter++) + { + ReadData = spi_master_write(&spi_master, TestData); + DBG_SSI_INFO("Master write: %02X, read: %02X\n", TestData, ReadData); + if (TestData - 1 != ReadData) { + result = 0; + } + + TestData++; + + spi_slave_write(&spi_slave, TestData); + ReadData = spi_slave_read(&spi_slave); + DBG_SSI_INFO(ANSI_COLOR_CYAN"Slave write: %02X, read: %02X\n"ANSI_COLOR_RESET, TestData, ReadData); + if (TestData - 1 != ReadData) { + result = 0; + } + + TestData++; + } + + /** + * Master write, Slave read + */ + DBG_SSI_INFO("--------------------------------------------------------\n"); + for(Counter = 0, TestData=0xFF; Counter < TestingTimes; Counter++) + { + spi_master_write(&spi_master, TestData); + ReadData = spi_slave_read(&spi_slave); + DBG_SSI_INFO("Master write: %02X\n", TestData); + DBG_SSI_INFO(ANSI_COLOR_CYAN"Slave read : %02X\n"ANSI_COLOR_RESET, ReadData); + if (TestData != ReadData) { + result = 0; + } + + TestData--; + } + + spi_free(&spi_master); + spi_free(&spi_slave); + + DBG_SSI_INFO("SPI Demo finished.\n"); + + printf("\r\nResult is %s\r\n", (result) ? "success" : "fail"); + + for(;;); + +#else // mbed SPI API emulation + +#endif + +} + diff --git a/project/realtek_ameba1_va0_example/example_sources/spi_pl7223/readme.txt b/project/realtek_ameba1_va0_example/example_sources/spi_pl7223/readme.txt new file mode 100644 index 0000000..6cf866e --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/spi_pl7223/readme.txt @@ -0,0 +1,19 @@ +Example Description + +This example describes how to get data from pl7223 by SPI conneciton + +The SPI Interface provides a "Serial Peripheral Interface" Master. + +Hardware connection: + Connect SPI0_MOSI (PC_2) to PL7223 MOSI + Connect SPI0_MISO (PC_3) to PL7223 MISO + Connect SPI0_SCLK (PC_1) to PL7223 SCLK + Connect GPIOB_5 (PB_5) to PL7223 CS + Connect GPIOB_4 (PB_4) to PL7223 RESET + Connect GROUND together + + Connect to LOG UART with configuration 38400 8bits, 1 stopbit, no parity + + +After boot up, the ameba will reset pl7223 into MCU mode and get data from pl7223. +After Gatherin and calculating, program will show information to UART. \ No newline at end of file diff --git a/project/realtek_ameba1_va0_example/example_sources/spi_pl7223/src/main.c b/project/realtek_ameba1_va0_example/example_sources/spi_pl7223/src/main.c new file mode 100644 index 0000000..e21411b --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/spi_pl7223/src/main.c @@ -0,0 +1,298 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2015 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ +#include +#include +#include "device.h" +#include "main.h" +#include "spi_api.h" +#include "gpio_api.h" + +// SPI0 +#define SPI0_MOSI PC_2 +#define SPI0_MISO PC_3 +#define SPI0_SCLK PC_1 +#define SPI0_CS PC_0 + +#define GPIO_RESET PB_4 +#define GPIO_CS PB_5 + +//-------------------------------------------------------------------------------------------- + +#define READ_PL7223 0x4000 +#define WRITE_PL7223 0x8000 +#define DSPSTATUS_PL7223 0xF000 +#define DUM_PL7223 0x00 //Dummy Data + +unsigned char SPDAT; // simulate example code +unsigned char DSP_STATUS=0; +unsigned char Read_Data_PL7223[146]; // Read_Data; 256Bytes=1Page +unsigned char Write_Data_PL7223[146]; // Write_Data; 256Bytes=1Page +unsigned char Cmd_RD=0; + + +long EE_Temp = 0; +float VA_rms=0; +float IA_rms=0; +float PA=0; +float SA=0; +float QA=0; +float PF_A=0; +float Theta_A=0; +float Frequency=0; +int Sample_cnt0=0; +int ZCC_cnt=0; +int ZCC_Start=0; +int ZCC_Stop=0; + +void Initial_SPI_PL7223(void); +void SPI_PL7223_SEND(unsigned char); +void SPI__PL7223_Read_Status(void); +void SPI_PL7223_DELY(int); +void SPI_PL7223_Reset(void); +void SPI_PL7223_Read(unsigned char*, unsigned int, unsigned int); +void SPI_PL7223_Write(unsigned char*, unsigned int, unsigned int); +void SPI_PL7223_Masurement(void); +void SPI_PL7223_RelayControl(int); + +static spi_t spi0_master; +static gpio_t gpio_reset; +static gpio_t gpio_cs; + +/** + * @brief Main program. + * @param None + * @retval None + */ +void main(void) +{ + + gpio_init(&gpio_reset, GPIO_RESET); + gpio_mode(&gpio_reset, PullUp); + gpio_dir(&gpio_reset, PIN_OUTPUT); + + gpio_init(&gpio_cs, GPIO_CS); + gpio_mode(&gpio_cs, PullUp); + gpio_dir(&gpio_cs, PIN_OUTPUT); + + spi_init(&spi0_master, SPI0_MOSI, SPI0_MISO, SPI0_SCLK, SPI0_CS); + spi_format(&spi0_master, 8, 3, 0); + spi_frequency(&spi0_master, 800000); + + do + { + SPI_PL7223_Reset(); + SPI_PL7223_Read(&Read_Data_PL7223[0],0x3860,1);//DSP version :20130322 ver02, 0x3860=0x04 + //DSP version :20141009 ver01, 0x3860=0x03 + }while( ((Read_Data_PL7223[0]) != 0x04) && ((Read_Data_PL7223[0]) != 0x03) ); + + SPI_PL7223_DELY(120000); + SPI_PL7223_RelayControl(0); // OFF + SPI_PL7223_DELY(120000); + + do{ + // As below is read DSP buffer process every time (144 byte) + SPI__PL7223_Read_Status(); + SPI_PL7223_Read(&Read_Data_PL7223[0],0x3000,144); // 0x3000~0x308F //144 byte + SPI_PL7223_Read(&Read_Data_PL7223[144],0x3809,2); // Sample_cnt0 + SPI_PL7223_Masurement(); + + SPI_PL7223_DELY(600000); + SPI_PL7223_RelayControl(1); // ON + SPI_PL7223_DELY(120000); + + SPI__PL7223_Read_Status(); + SPI_PL7223_Read(&Read_Data_PL7223[0],0x3000,144); // 0x3000~0x308F //144 byte + SPI_PL7223_Read(&Read_Data_PL7223[144],0x3809,2); // Sample_cnt0 + SPI_PL7223_Masurement(); + + SPI_PL7223_DELY(600000); + SPI_PL7223_RelayControl(0); // OFF + SPI_PL7223_DELY(120000); + }while(1); +} + +//--------------------------------------------------------------------------------------------// +void SPI_PL7223_RelayControl(int sw) +{ + #define RELAY_MASK (1<<5) + SPI_PL7223_Read(&Read_Data_PL7223[0],0x380F,1); + if(!sw) + Read_Data_PL7223[0] &= (~RELAY_MASK); + else + Read_Data_PL7223[0] |= RELAY_MASK; + SPI_PL7223_Write(&Read_Data_PL7223[0],0x380F,1); +} + +//--------------------------------------------------------------------------------------------// +void SPI_PL7223_Reset(void) +{ + gpio_write(&gpio_cs, 0); + SPI_PL7223_DELY(500); //need delay 10ms + gpio_write(&gpio_reset, 1); + SPI_PL7223_DELY(500); //need delay 10ms + gpio_write(&gpio_reset, 0); + SPI_PL7223_DELY(500); //need delay 10ms + gpio_write(&gpio_reset, 1); + SPI_PL7223_DELY(500); //need delay 10ms + gpio_write(&gpio_cs, 1); + SPI_PL7223_DELY(300); +} + +//--------------------------------------------------------------------------------------------// +void SPI__PL7223_Read_Status(void) +{ + gpio_write(&gpio_cs, 0); + SPI_PL7223_SEND((unsigned char)(DSPSTATUS_PL7223 >> 8)& 0xFF); // RDSR command + SPI_PL7223_SEND((unsigned char)(DSPSTATUS_PL7223& 0x00FF)); // RDSR command + + //check DSP flag state (byte) + do + { + SPI_PL7223_SEND(DUM_PL7223); + DSP_STATUS=SPDAT; + }while((DSP_STATUS & 0x80) == 0x00); // Bit7=1 is Ready + gpio_write(&gpio_cs, 1); +} + +//--------------------------------------------------------------------------------------------// +void SPI_PL7223_Write(unsigned char* buf, unsigned int addr, unsigned int len) +{ + unsigned int i; + gpio_write(&gpio_cs, 0); + addr |= WRITE_PL7223; // Write command + SPI_PL7223_SEND((unsigned char)(addr >> 8)& 0xFF); // Write middle byte address + SPI_PL7223_SEND((unsigned char)(addr & 0xFF));// Write low byte address + for (i = 0; i < len ; i++){ + SPI_PL7223_SEND(buf[i]); + } + gpio_write(&gpio_cs, 1); + SPI_PL7223_DELY(3); // for CS:Hi to Low need 100nsec, Delay-Time 27usec + +} +//--------------------------------------------------------------------------------------------// + +void SPI_PL7223_Read(unsigned char* buf, unsigned int addr, unsigned int len) +{ + static unsigned int i; + + gpio_write(&gpio_cs, 0); + + addr |= READ_PL7223; // Read command + SPI_PL7223_SEND((unsigned char)(addr >> 8)& 0xFF); // Write middle byte address + SPI_PL7223_SEND((unsigned char)(addr & 0x00FF)); // Write low byte address + + for(i=0;i> 8)& 0xFF); // RDSR command + SPI_PL7223_SEND((unsigned char)(DSPSTATUS_PL7223& 0x00FF)); // RDSR command + + do + { + SPI_PL7223_SEND(DUM_PL7223); + DSP_STATUS=SPDAT; + }while((DSP_STATUS & 0x80) == 0x00); // Bit7=1 is Ready + + gpio_write(&gpio_cs, 1); + +} + +//--------------------------------------------------------------------------------------------// + +void SPI_PL7223_Masurement(void) +{ + + //Vrms address : 0x3002~0x3003 + // VA_rms = (Read_Data_PL7223[3]*256+Read_Data_PL7223[2])/64; + EE_Temp = Read_Data_PL7223[3]; + EE_Temp = EE_Temp << 8; + EE_Temp += Read_Data_PL7223[2]; + VA_rms = (float)EE_Temp/64.00; + + + //Irms address : 0x3008~0x3009 + // IA_rms = Read_Data_PL7223[3]+Read_Data_PL7223[2]/256; + EE_Temp = Read_Data_PL7223[8]; + IA_rms = (float)EE_Temp/256.00; + EE_Temp = Read_Data_PL7223[9]; + IA_rms = IA_rms + (float)EE_Temp; + + + //Active address : 0x3078~0x307D + // PA = Read_Data_PL7223[124]*256+Read_Data_PL7223[123]; + EE_Temp = Read_Data_PL7223[124]; + EE_Temp = EE_Temp << 8; + EE_Temp += Read_Data_PL7223[123]; + PA = (float)EE_Temp; + + //PF Calculate + // SA = VA_rms*IA_rms; + SA = VA_rms*IA_rms; + // PF_A = PA/SA + PF_A = SA==0? 0: PA/SA; + Theta_A = acos(PF_A); + QA = SA * sin(Theta_A); + if(IA_rms==0) + Theta_A = 0; + else + Theta_A = Theta_A * (180.00/(3.141592653589)); + + /** Frequency = [Sample_cnt0/(ZCC_STOP-ZCC_START)]*[(ZCC_CNT-1)/2] */ + Sample_cnt0 = Read_Data_PL7223[145]; // Sample_cnt01 + Sample_cnt0 = Sample_cnt0 <<8; + Sample_cnt0 += Read_Data_PL7223[144]; // Sample_cnt00 + + ZCC_cnt = Read_Data_PL7223[91]; // ZCC_cnt1 + ZCC_cnt = ZCC_cnt <<8; + ZCC_cnt += Read_Data_PL7223[90]; // ZCC_cnt0 + + ZCC_Stop = Read_Data_PL7223[97]; // ZCC_STOP1 + ZCC_Stop = ZCC_Stop <<8; + ZCC_Stop += Read_Data_PL7223[96]; // ZCC_STOP0 + + ZCC_Start = Read_Data_PL7223[103]; // ZCC_START1 + ZCC_Start = ZCC_Start <<8; + ZCC_Start += Read_Data_PL7223[102]; // ZCC_START0 + + Frequency = (float)((float)Sample_cnt0 / (ZCC_Stop - ZCC_Start)) * (((float)ZCC_cnt - 1.0) / 2); + +#define UART_Display(name) printf(#name" %d.%d\n\r", (int)(name*1000)/1000, (int)(name*1000)%1000) + UART_Display(VA_rms); + UART_Display(IA_rms); + UART_Display(Frequency); + UART_Display(PA); + UART_Display(QA); + UART_Display(SA); + UART_Display(PF_A); + UART_Display(Theta_A); +} +//--------------------------------------------------------------------------------------------// +void SPI_PL7223_DELY(int dely_cnt) // MCUCLK 4MHz, Delay-Time 9usec/clock +{ + HalDelayUs(dely_cnt*20); +} + +//--------------------------------------------------------------------------------------------// +void SPI_PL7223_SEND(unsigned char spicmd) +{ + SPDAT = (char)spi_master_write(&spi0_master, (int)spicmd); +} +//--------------------------------------------------------------------------------------------// + + diff --git a/project/realtek_ameba1_va0_example/example_sources/spi_stream_twoboard/readme.txt b/project/realtek_ameba1_va0_example/example_sources/spi_stream_twoboard/readme.txt new file mode 100644 index 0000000..a570408 --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/spi_stream_twoboard/readme.txt @@ -0,0 +1,24 @@ +Example Description + +This example describes how to use SPI stream read/write by mbed api. + + +The SPI Interface provides a "Serial Peripheral Interface" Master. + +This interface can be used for communication with SPI slave devices, +such as FLASH memory, LCD screens and other modules or integrated circuits. + + +In this example, we use config SPI_IS_AS_MASTER to decide if device is master or slave. + If SPI_IS_AS_MASTER is 1, then device is master. + If SPI_IS_AS_MASTER is 0, then device is slave. + +We connect wires as below: + master's MOSI (PC_2) connect to slave's MOSI (PC_2) + master's MISO (PC_3) connect to slave's MISO (PC_3) + master's SCLK (PC_1) connect to slave's SCLK (PC_1) + master's CS (PC_0) connect to slave's CS (PC_0) + +This example shows master sends data to slave. +We bootup slave first, and then bootup master. +Then log will presents that master sending data to slave. \ No newline at end of file diff --git a/project/realtek_ameba1_va0_example/example_sources/spi_stream_twoboard/src/main.c b/project/realtek_ameba1_va0_example/example_sources/spi_stream_twoboard/src/main.c new file mode 100644 index 0000000..a530fa6 --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/spi_stream_twoboard/src/main.c @@ -0,0 +1,176 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2014 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#include "device.h" +#include "main.h" +#include "spi_api.h" +#include "spi_ex_api.h" + +#define SPI_IS_AS_MASTER 1 +#define TEST_BUF_SIZE 2048 +#define SCLK_FREQ 1000000 +#define SPI_DMA_DEMO 0 +#define TEST_LOOP 100 + +// SPI0 +#define SPI0_MOSI PC_2 +#define SPI0_MISO PC_3 +#define SPI0_SCLK PC_1 +#define SPI0_CS PC_0 + +_LONG_CALL_ extern +void __rtl_memDump_v1_00(const u8 *start, u32 size, char * strHeader); +extern void wait_ms(u32); + +char TestBuf[TEST_BUF_SIZE]; +volatile int TrDone; + +void master_tr_done_callback(void *pdata, SpiIrq event) +{ + TrDone = 1; +} + +void slave_tr_done_callback(void *pdata, SpiIrq event) +{ + TrDone = 1; +} + +#if SPI_IS_AS_MASTER +spi_t spi_master; +#else +spi_t spi_slave; +#endif +/** + * @brief Main program. + * @param None + * @retval None + */ +void main(void) +{ + int Counter = 0; + int i; + +#if SPI_IS_AS_MASTER + spi_init(&spi_master, SPI0_MOSI, SPI0_MISO, SPI0_SCLK, SPI0_CS); + spi_frequency(&spi_master, SCLK_FREQ); + spi_format(&spi_master, 16, (SPI_SCLK_IDLE_LOW|SPI_CS_TOGGLE_EVERY_FRAME) , 0); + // wait Slave ready + wait_ms(1000); + + while (Counter < TEST_LOOP) { + DBG_8195A("======= Test Loop %d =======\r\n", Counter); + + for (i=0;i\r\n"); + TrDone = 0; +#if SPI_DMA_DEMO + spi_master_write_stream_dma(&spi_master, TestBuf, TEST_BUF_SIZE); +#else + spi_master_write_stream(&spi_master, TestBuf, TEST_BUF_SIZE); +#endif + i=0; + DBG_8195A("SPI Master Wait Write Done...\r\n"); + while(TrDone == 0) { + wait_ms(10); + i++; + } + DBG_8195A("SPI Master Write Done!!\r\n"); + + DBG_8195A("SPI Master Read Test==>\r\n"); + DBG_8195A("Wait 5 sec for SPI Slave get ready...\r\n"); + for (i=0;i<5;i++) { + wait_ms(1000); + } + + _memset(TestBuf, 0, TEST_BUF_SIZE); + spi_flush_rx_fifo(&spi_master); + + TrDone = 0; +#if SPI_DMA_DEMO + spi_master_read_stream_dma(&spi_master, TestBuf, TEST_BUF_SIZE); +#else + spi_master_read_stream(&spi_master, TestBuf, TEST_BUF_SIZE); +#endif + i=0; + DBG_8195A("SPI Master Wait Read Done...\r\n"); + while(TrDone == 0) { + wait_ms(10); + i++; + } + DBG_8195A("SPI Master Read Done!!\r\n"); + __rtl_memDump_v1_00(TestBuf, TEST_BUF_SIZE, "SPI Master Read Data:"); + Counter++; + } + spi_free(&spi_master); + DBG_8195A("SPI Master Test <==\r\n"); + +#else + spi_init(&spi_slave, SPI0_MOSI, SPI0_MISO, SPI0_SCLK, SPI0_CS); + spi_format(&spi_slave, 16, (SPI_SCLK_IDLE_LOW|SPI_CS_TOGGLE_EVERY_FRAME) , 1); + + while (spi_busy(&spi_slave)) { + DBG_8195A("Wait SPI Bus Ready...\r\n"); + wait_ms(1000); + } + + while (Counter < TEST_LOOP) { + DBG_8195A("======= Test Loop %d =======\r\n", Counter); + _memset(TestBuf, 0, TEST_BUF_SIZE); + DBG_8195A("SPI Slave Read Test ==>\r\n"); + spi_irq_hook(&spi_slave, slave_tr_done_callback, (uint32_t)&spi_slave); + TrDone = 0; + spi_flush_rx_fifo(&spi_slave); +#if SPI_DMA_DEMO + spi_slave_read_stream_dma(&spi_slave, TestBuf, TEST_BUF_SIZE); +#else + spi_slave_read_stream(&spi_slave, TestBuf, TEST_BUF_SIZE); +#endif + i=0; + DBG_8195A("SPI Slave Wait Read Done...\r\n"); + while(TrDone == 0) { + wait_ms(100); + i++; + if (i>150) { + DBG_8195A("SPI Slave Wait Timeout\r\n"); + break; + } + } + __rtl_memDump_v1_00(TestBuf, TEST_BUF_SIZE, "SPI Slave Read Data:"); + + // Slave Write Test + DBG_8195A("SPI Slave Write Test ==>\r\n"); + TrDone = 0; +#if SPI_DMA_DEMO + spi_slave_write_stream_dma(&spi_slave, TestBuf, TEST_BUF_SIZE); +#else + spi_slave_write_stream(&spi_slave, TestBuf, TEST_BUF_SIZE); +#endif + i=0; + DBG_8195A("SPI Slave Wait Write Done...\r\n"); + while(TrDone == 0) { + wait_ms(100); + i++; + if (i> 200) { + DBG_8195A("SPI Slave Write Timeout...\r\n"); + break; + } + } + DBG_8195A("SPI Slave Write Done!!\r\n"); + Counter++; + } + spi_free(&spi_slave); +#endif + + DBG_8195A("SPI Demo finished.\n"); + for(;;); +} diff --git a/project/realtek_ameba1_va0_example/example_sources/spi_twoboard/readme.txt b/project/realtek_ameba1_va0_example/example_sources/spi_twoboard/readme.txt new file mode 100644 index 0000000..1232a3e --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/spi_twoboard/readme.txt @@ -0,0 +1,24 @@ +Example Description + +This example describes how to use SPI read/write by mbed api. + + +The SPI Interface provides a "Serial Peripheral Interface" Master. + +This interface can be used for communication with SPI slave devices, +such as FLASH memory, LCD screens and other modules or integrated circuits. + + +In this example, we use config SPI_IS_AS_MASTER to decide if device is master or slave. + If SPI_IS_AS_MASTER is 1, then device is master. + If SPI_IS_AS_MASTER is 0, then device is slave. + +We connect wires as below: + master's MOSI (PC_2) connect to slave's MOSI (PC_2) + master's MISO (PC_3) connect to slave's MISO (PC_3) + master's SCLK (PC_1) connect to slave's SCLK (PC_1) + master's CS (PC_0) connect to slave's CS (PC_0) + +This example shows master sends data to slave. +We bootup slave first, and then bootup master. +Then log will presents that master sending data to slave. \ No newline at end of file diff --git a/project/realtek_ameba1_va0_example/example_sources/spi_twoboard/src/main.c b/project/realtek_ameba1_va0_example/example_sources/spi_twoboard/src/main.c new file mode 100644 index 0000000..8b15fa0 --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/spi_twoboard/src/main.c @@ -0,0 +1,64 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2014 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#include "device.h" +#include "main.h" +#include "spi_api.h" + +#define SPI_IS_AS_MASTER 1 + +// SPI0 +#define SPI0_MOSI PC_2 +#define SPI0_MISO PC_3 +#define SPI0_SCLK PC_1 +#define SPI0_CS PC_0 + +/** + * @brief Main program. + * @param None + * @retval None + */ +void main(void) +{ + int TestingTimes = 10; + int Counter = 0; + int TestData = 0; + +#if SPI_IS_AS_MASTER + spi_t spi_master; + + SPI0_IS_AS_SLAVE = 0; + spi_init(&spi_master, SPI0_MOSI, SPI0_MISO, SPI0_SCLK, SPI0_CS); + + DBG_SSI_INFO("--------------------------------------------------------\n"); + for(Counter = 0, TestData=0xFF; Counter < TestingTimes; Counter++) { + spi_master_write(&spi_master, TestData); + DBG_SSI_INFO("Master write: %02X\n", TestData); + TestData--; + } + spi_free(&spi_master); + +#else + spi_t spi_slave; + + SPI0_IS_AS_SLAVE = 1; + spi_init(&spi_slave, SPI0_MOSI, SPI0_MISO, SPI0_SCLK, SPI0_CS); + + DBG_SSI_INFO("--------------------------------------------------------\n"); + for(Counter = 0, TestData=0xFF; Counter < TestingTimes; Counter++) { + DBG_SSI_INFO(ANSI_COLOR_CYAN"Slave read : %02X\n"ANSI_COLOR_RESET, + spi_slave_read(&spi_slave)); + TestData--; + } + spi_free(&spi_slave); +#endif + + DBG_SSI_INFO("SPI Demo finished.\n"); + for(;;); +} diff --git a/project/realtek_ameba1_va0_example/example_sources/uart/readme.txt b/project/realtek_ameba1_va0_example/example_sources/uart/readme.txt new file mode 100644 index 0000000..f4ac25f --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/uart/readme.txt @@ -0,0 +1,19 @@ +Example Description + +This example describes how to use UART to communicate with PC. + +Required Components: + USBtoTTL adapter + +Connect to PC + - Connect Ground: connect to GND pin via USBtoTTL adapter + - Use UART1 + GPIOA_6 as UART1_RX connect to TX of USBtoTTL adapter + GPIOA_7 as UART1_TX connect to RX of USBtoTTL adapter + +Open Super terminal or teraterm and +set baud rate to 38400, 1 stopbit, no parity, no flow contorl. + +This example shows: +User input will be received by demo board, and demo board will loopback the received character with a prompt string "8195a$". + diff --git a/project/realtek_ameba1_va0_example/example_sources/uart/src/main.c b/project/realtek_ameba1_va0_example/example_sources/uart/src/main.c new file mode 100644 index 0000000..be4cb57 --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/uart/src/main.c @@ -0,0 +1,46 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#include "device.h" +#include "serial_api.h" +#include "main.h" + +#define UART_TX PA_7 +#define UART_RX PA_6 + +void uart_send_string(serial_t *sobj, char *pstr) +{ + unsigned int i=0; + + while (*(pstr+i) != 0) { + serial_putc(sobj, *(pstr+i)); + i++; + } +} + +void main(void) +{ + // sample text + char rc; + serial_t sobj; + + // mbed uart test + serial_init(&sobj,UART_TX,UART_RX); + serial_baud(&sobj,38400); + serial_format(&sobj, 8, ParityNone, 1); + + uart_send_string(&sobj, "UART API Demo...\r\n"); + uart_send_string(&sobj, "Hello World!!\r\n"); + while(1){ + uart_send_string(&sobj, "\r\n8195a$"); + rc = serial_getc(&sobj); + serial_putc(&sobj, rc); + } +} + diff --git a/project/realtek_ameba1_va0_example/example_sources/uart_clock/readme.txt b/project/realtek_ameba1_va0_example/example_sources/uart_clock/readme.txt new file mode 100644 index 0000000..b37c1db --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/uart_clock/readme.txt @@ -0,0 +1,16 @@ +Example Description + +This example describes how to use UART TX to simulate clock source + +Required Components: + Oscilloscope + +Connect to PC + - Connect Ground: connect to GND of oscilloscope + - Use UART1 + GPIOA_6 as UART1_RX connect NOTHING + GPIOA_7 as UART1_TX connect to probe of oscilloscope + + +This example shows: +1. Clock signal output from UART1_TX to oscilloscope diff --git a/project/realtek_ameba1_va0_example/example_sources/uart_clock/src/main.c b/project/realtek_ameba1_va0_example/example_sources/uart_clock/src/main.c new file mode 100644 index 0000000..1a5d2e2 --- /dev/null +++ b/project/realtek_ameba1_va0_example/example_sources/uart_clock/src/main.c @@ -0,0 +1,94 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2015 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ + +#include "device.h" +#include "serial_api.h" +#include "serial_ex_api.h" +#include "main.h" + +#define UART_TX PA_7 +#define UART_RX PA_6 + +/* 100 bytes data, 500 clocks, provide buadrate/2 frequency */ +#define SREAM_LEN 128 +char sim_clock[SREAM_LEN+1]; + + +volatile uint32_t is_stop = 0; +static serial_t sobj_clk; + +void uart_clock_send_string(serial_t *sobj, char *pstr) +{ + int32_t ret=0; + + ret = serial_send_stream_dma(sobj, pstr, _strlen(pstr)); + if (ret != 0) { + DBG_8195A("%s Error(%d)\n", __FUNCTION__, ret); + } +} + +void uart_clock_send_string_done(uint32_t id) +{ + serial_t *sobj = (void*)id; + if(!is_stop) + uart_clock_send_string(sobj, sim_clock); +} + +void uart_clock_deinit(void) +{ + is_stop = 1; + serial_free(&sobj_clk); +} + +void uart_clock_init(int rate) +{ + //serial_t sobj; + int ret; + int i; + + for (i=0;i + +extern void wlan_netowrk(void); +extern void console_init(void); + + +void user_wifi_beacon_hdl( char* buf, int buf_len, int flags, void* userdata) +{ + //printf("Beacon!\n"); +} + + +/** + * @brief Main program. + * @param None + * @retval None + */ +void main(void) +{ + if ( rtl_cryptoEngine_init() != 0 ) { + DiagPrintf("crypto engine init failed\r\n"); + } + + /* Initialize log uart and at command service */ + console_init(); + + /* pre-processor of application example */ + pre_example_entry(); + + /* wlan intialization */ +#if defined(CONFIG_WIFI_NORMAL) && defined(CONFIG_NETWORK) + wlan_network(); +#endif + + /* Execute application example */ + example_entry(); + + /*Enable Schedule, Start Kernel*/ +#if defined(CONFIG_KERNEL) && !TASK_SCHEDULER_DISABLED + #ifdef PLATFORM_FREERTOS + vTaskStartScheduler(); + #endif +#else + RtlConsolTaskRom(NULL); +#endif +} diff --git a/project/realtek_ameba1_va0_example/inc/FreeRTOSConfig.h b/project/realtek_ameba1_va0_example/inc/FreeRTOSConfig.h new file mode 100644 index 0000000..0c68cc5 --- /dev/null +++ b/project/realtek_ameba1_va0_example/inc/FreeRTOSConfig.h @@ -0,0 +1,191 @@ +/* + FreeRTOS V7.3.0 - Copyright (C) 2012 Real Time Engineers Ltd. + + FEATURES AND PORTS ARE ADDED TO FREERTOS ALL THE TIME. PLEASE VISIT + http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS tutorial books are available in pdf and paperback. * + * Complete, revised, and edited pdf reference manuals are also * + * available. * + * * + * Purchasing FreeRTOS documentation will not only help you, by * + * ensuring you get running as quickly as possible and with an * + * in-depth knowledge of how to use FreeRTOS, it will also help * + * the FreeRTOS project to continue with its mission of providing * + * professional grade, cross platform, de facto standard solutions * + * for microcontrollers - completely free of charge! * + * * + * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * + * * + * Thank you for using FreeRTOS, and thank you for your support! * + * * + *************************************************************************** + + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation AND MODIFIED BY the FreeRTOS exception. + >>>NOTE<<< The modification to the GPL is included to allow you to + distribute a combined work that includes FreeRTOS without being obliged to + provide the source code for proprietary components outside of the FreeRTOS + kernel. FreeRTOS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. You should have received a copy of the GNU General Public + License and the FreeRTOS license exception along with FreeRTOS; if not it + can be viewed here: http://www.freertos.org/a00114.html and also obtained + by writing to Richard Barry, contact details for whom are available on the + FreeRTOS WEB site. + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + + http://www.FreeRTOS.org - Documentation, training, latest versions, license + and contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool. + + Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell + the code with commercial support, indemnification, and middleware, under + the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also + provide a safety engineered and independently SIL3 certified version under + the SafeRTOS brand: http://www.SafeRTOS.com. +*/ + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H +#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__) +#include +extern uint32_t SystemCoreClock; +#endif + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html. + *----------------------------------------------------------*/ + +#define configUSE_PREEMPTION 1 +#define configUSE_IDLE_HOOK 1 +#define configUSE_TICK_HOOK 0 +#define configCPU_CLOCK_HZ ( SystemCoreClock ) +#define configTICK_RATE_HZ ( ( uint32_t ) 1000 ) +#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 70 ) +#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 75 * 1024 ) ) +#define configMAX_TASK_NAME_LEN ( 10 ) +#define configUSE_TRACE_FACILITY 0 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 0 +#define configUSE_CO_ROUTINES 1 +#define configUSE_MUTEXES 1 +#define configUSE_TIMERS 1 + +#define configMAX_PRIORITIES ( 11 ) +#define PRIORITIE_OFFSET ( 4 ) + +#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) + +#define configUSE_COUNTING_SEMAPHORES 1 +#define configUSE_ALTERNATIVE_API 0 +#define configCHECK_FOR_STACK_OVERFLOW 2 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configQUEUE_REGISTRY_SIZE 0 +#define configGENERATE_RUN_TIME_STATS 0 + +#define configTIMER_TASK_PRIORITY ( 1 ) +#define configTIMER_QUEUE_LENGTH ( 10 ) +#define configTIMER_TASK_STACK_DEPTH ( 512 ) // 512*4=2K + +#if (__IASMARM__ != 1) + +extern void freertos_pre_sleep_processing(unsigned int *expected_idle_time); +extern int freertos_ready_to_sleep(); + +/* Enable tickless power saving. */ +#define configUSE_TICKLESS_IDLE 1 + +/* In wlan usage, this value is suggested to use value less than 100 milliseconds */ +#define configEXPECTED_IDLE_TIME_BEFORE_SLEEP 100 + +/* It's magic trick that let us can use our own sleep function */ +#define configPRE_SLEEP_PROCESSING( x ) ( freertos_pre_sleep_processing(&x) ) + +/* It's magic trick that let us can enable/disable tickless dynamically */ +#define traceLOW_POWER_IDLE_BEGIN(); do { \ + if (!freertos_ready_to_sleep()) { \ + mtCOVERAGE_TEST_MARKER(); \ + break; \ + } + + // portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ); + +#define traceLOW_POWER_IDLE_END(); } while (0); + +/* It's FreeRTOS related feature but it's not included in FreeRTOS design. */ +#define configUSE_WAKELOCK_PMU 1 + +#endif // #if (__IASMARM__ != 1) + +/* Set the following definitions to 1 to include the API function, or zero +to exclude the API function. */ +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskCleanUpResources 0 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_pcTaskGetTaskName 1 +#define INCLUDE_xTimerPendFunctionCall 1 + +/* Cortex-M specific definitions. */ +#ifdef __NVIC_PRIO_BITS + /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */ + #define configPRIO_BITS __NVIC_PRIO_BITS +#else + #define configPRIO_BITS 4 /* 15 priority levels */ +#endif + + +/* The lowest interrupt priority that can be used in a call to a "set priority" +function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0x0f + +/* The highest interrupt priority that can be used by any interrupt service +routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL +INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER +PRIORITY THAN THIS! (higher priorities are lower numeric values. */ +#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5 + + +/* Interrupt priorities used by the kernel port layer itself. These are generic +to all Cortex-M ports, and do not rely on any particular library functions. */ +#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) +/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!! +See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ +#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) + +//#define RTK_MODE_TIMER + + +#endif /* FREERTOS_CONFIG_H */ diff --git a/project/realtek_ameba1_va0_example/inc/build_info.h b/project/realtek_ameba1_va0_example/inc/build_info.h new file mode 100644 index 0000000..6677a76 --- /dev/null +++ b/project/realtek_ameba1_va0_example/inc/build_info.h @@ -0,0 +1,6 @@ +#define UTS_VERSION "2015/11/17- 9:52:33" +#define RTL8195AFW_COMPILE_TIME "2015/11/17- 9:52:33" +#define RTL8195AFW_COMPILE_BY "JEFFREY" +#define RTL8195AFW_COMPILE_HOST "PCI-JEFFREY" +#define RTL8195AFW_COMPILE_DOMAIN +#define RTL195AFW_COMPILER "IAR compiler" diff --git a/project/realtek_ameba1_va0_example/inc/main.h b/project/realtek_ameba1_va0_example/inc/main.h new file mode 100644 index 0000000..9f7bceb --- /dev/null +++ b/project/realtek_ameba1_va0_example/inc/main.h @@ -0,0 +1,65 @@ +#ifndef MAIN_H +#define MAIN_H + +#include + +#ifndef CONFIG_WLAN +#define CONFIG_WLAN 1 +#endif + +/* Header file declaration*/ +void wlan_network(); +void user_wifi_beacon_hdl( char* buf, int buf_len, int flags, void* userdata); + + +/* Interactive Mode */ +#define SERIAL_DEBUG_RX 1 + +/* WLAN and Netork */ +#define STA_MODE_SSID "ap" /* Set SSID here */ +#define AP_MODE_SSID "wlan_ap_ssid" /* Set SSID here */ +#define AP_DEFAULT_CH 6 +#define WLAN0_NAME "wlan0" +#define WLAN1_NAME "wlan1" +#define WPA_PASSPHRASE "1234567890" /* Max 32 cahracters */ +#define WEP40_KEY {0x12, 0x34, 0x56, 0x78, 0x90} + +/*Static IP ADDRESS*/ +#define IP_ADDR0 192 +#define IP_ADDR1 168 +#define IP_ADDR2 1 +#define IP_ADDR3 80 + +/*NETMASK*/ +#define NETMASK_ADDR0 255 +#define NETMASK_ADDR1 255 +#define NETMASK_ADDR2 255 +#define NETMASK_ADDR3 0 + +/*Gateway Address*/ +#define GW_ADDR0 192 +#define GW_ADDR1 168 +#define GW_ADDR2 1 +#define GW_ADDR3 1 + +/*******************************************/ + +/*Static IP ADDRESS*/ +#define AP_IP_ADDR0 192 +#define AP_IP_ADDR1 168 +#define AP_IP_ADDR2 43 +#define AP_IP_ADDR3 1 + +/*NETMASK*/ +#define AP_NETMASK_ADDR0 255 +#define AP_NETMASK_ADDR1 255 +#define AP_NETMASK_ADDR2 255 +#define AP_NETMASK_ADDR3 0 + +/*Gateway Address*/ +#define AP_GW_ADDR0 192 +#define AP_GW_ADDR1 168 +#define AP_GW_ADDR2 43 +#define AP_GW_ADDR3 1 + +#endif diff --git a/project/realtek_ameba1_va0_example/inc/platform_autoconf.h b/project/realtek_ameba1_va0_example/inc/platform_autoconf.h new file mode 100644 index 0000000..71801f8 --- /dev/null +++ b/project/realtek_ameba1_va0_example/inc/platform_autoconf.h @@ -0,0 +1,174 @@ +/* + * Automatically generated by make menuconfig: don't edit + */ +#define AUTOCONF_INCLUDED + +/* + * Target Platform Selection + */ +#define CONFIG_WITHOUT_MONITOR 1 +#define CONFIG_BOOT_TO_UPGRADE_IMG2 1 + +#define CONFIG_RTL8195A 1 +#undef CONFIG_FPGA +#undef CONFIG_RTL_SIM +#undef CONFIG_POST_SIM +#undef CONFIG_MP +#define RTL8195A 1 +#define CONFIG_CPU_CLK 1 +#define CONFIG_CPU_166_6MHZ 1 +#undef CONFIG_CPU_83_3MHZ +#undef CONFIG_CPU_41_6MHZ +#undef CONFIG_CPU_20_8MHZ +#undef CONFIG_CPU_10_4MHZ +#undef CONFIG_CPU_4MHZ +#undef CONFIG_FPGA_CLK +#define PLATFORM_CLOCK (166666666) +#define CPU_CLOCK_SEL_VALUE (0) +#define CONFIG_SDR_CLK 1 +#undef CONFIG_SDR_100MHZ +#define CONFIG_SDR_50MHZ 1 +#undef CONFIG_SDR_25MHZ +#undef CONFIG_SDR_12_5MHZ +#define SDR_CLOCK_SEL_VALUE (1) +#define CONFIG_BOOT_PROCEDURE 1 +#define CONFIG_BOOT_FROM_JTAG 1 +#undef CONFIG_ALIGNMENT_EXCEPTION_ENABLE +#define CONFIG_KERNEL 1 +#define PLATFORM_FREERTOS 1 +#undef PLATFORM_UCOSII +#undef PLATFORM_ECOS +#undef CONFIG_TASK_SCHEDUL_DIS +#define TASK_SCHEDULER_DISABLED (0) +#define CONFIG_NORMALL_MODE 1 +#undef CONFIG_MEMORY_VERIFY_MODE +#define CONFIG_TIMER_EN 1 +#define CONFIG_TIMER_NORMAL 1 +#undef CONFIG_TIMER_TEST +#define CONFIG_TIMER_MODULE 1 +#define CONFIG_WDG 1 +#undef CONFIG_WDG_NON +#define CONFIG_WDG_NORMAL 1 +#define CONFIG_GDMA_EN 1 +#define CONFIG_GDMA_NORMAL 1 +#undef CONFIG_GDMA_TEST +#define CONFIG_GDMA_MODULE 1 +#define CONFIG_WIFI_EN 1 +#define CONFIG_WIFI_NORMAL 1 +#undef CONFIG_WIFI_TEST +#define CONFIG_WIFI_MODULE 1 +#define CONFIG_GPIO_EN 1 +#define CONFIG_GPIO_NORMAL 1 +#undef CONFIG_GPIO_TEST +#define CONFIG_GPIO_MODULE 1 +#undef CONFIG_SDIO_DEVICE_EN +#undef CONFIG_SDIO_HOST_EN +#undef CONFIG_USB_EN +#define CONFIG_SPI_COM_EN 1 +#define CONFIG_SPI_COM_NORMAL 1 +#undef CONFIG_SPI_COM_TEST +#define CONFIG_SPI_COM_MODULE 1 +#define CONFIG_UART_EN 1 +#define CONFIG_UART_NORMAL 1 +#undef CONFIG_UART_TEST +#define CONFIG_UART_MODULE 1 +#define CONFIG_I2C_EN 1 +#define CONFIG_I2C_NORMAL 1 +#undef CONFIG_I2C_TEST +#define CONFIG_I2C_MODULE 1 +#undef CONFIG_DEBUG_LOG_I2C_HAL +#undef CONFIG_PCM_EN +#define CONFIG_I2S_EN 1 +#define CONFIG_I2S_NORMAL 1 +#undef CONFIG_I2S_TEST +#define CONFIG_I2S_MODULE 1 +#undef CONFIG_DEBUG_LOG_I2S_HAL +#define CONFIG_NFC_EN 1 +#define CONFIG_NFC_NORMAL 1 +#undef CONFIG_NFC_TEST +#define CONFIG_NFC_MODULE 1 +#define CONFIG_SOC_PS_EN 1 +#define CONFIG_SOC_PS_NORMAL 1 +#undef CONFIG_SOC_PS_TEST +#define CONFIG_SOC_PS_MODULE 1 +#define CONFIG_CRYPTO_EN 1 +#define CONFIG_CRYPTO_NORMAL 1 +#undef CONFIG_CRYPTO_TEST +#define CONFIG_CRYPTO_MODULE 1 +#undef CONFIG_MII_EN +#define CONFIG_PWM_EN 1 +#define CONFIG_PWM_NORMAL 1 +#undef CONFIG_PWM_TEST +#define CONFIG_PWM_MODULE 1 +#define CONFIG_EFUSE_EN 1 +#define CONFIG_EFUSE_NORMAL 1 +#undef CONFIG_EFUSE_TEST +#define CONFIG_EFUSE_MODULE 1 +#define CONFIG_SDR_EN 1 +#define CONFIG_SDR_NORMAL 1 +#undef CONFIG_SDR_TEST +#define CONFIG_SDR_MODULE 1 +#define CONFIG_SPIC_EN 1 +#define CONFIG_SPIC_NORMAL 1 +#undef CONFIG_SPIC_TEST +#define CONFIG_SPIC_MODULE 1 +#define CONFIG_ADC_EN 1 +#define CONFIG_DAC_EN 1 +#define CONFIG_NOR_FLASH 1 +#undef CONFIG_SPI_FLASH +#undef CONFIG_NAND_FLASH +#undef CONFIG_NONE_FLASH + +/* + * Engineer Mode Config + */ +#undef CONFIG_JTAG +#undef CONFIG_COMPILE_FLASH_DOWNLOAD_CODE +#undef CONIFG_COMPILE_EXTERNAL_SRAM_CALIBRATE +#undef CONFIG_CMSIS_MATH_LIB_EN + +/* + * < Application Config + */ +#define CONFIG_NETWORK 1 +#define CONFIG_RTLIB_EN 1 +#define CONFIG_RTLIB_NORMAL 1 +#undef CONFIG_RTLIB_TEST +#define CONFIG_RTLIB_MODULE 1 + +/* + * < System Debug Message Config + */ +#define CONFIG_UART_LOG_HISTORY 1 +#undef CONFIG_CONSOLE_NORMALL_MODE +#define CONFIG_CONSOLE_VERIFY_MODE 1 +#define CONFIG_DEBUG_LOG 1 +#define CONFIG_DEBUG_ERR_MSG 1 +#undef CONFIG_DEBUG_WARN_MSG +#undef CONFIG_DEBUG_INFO_MSG + +/* + * < SDK Option Config + */ +#undef CONFIG_MBED_ENABLED +#undef CONFIG_APP_DEMO + +/* + * < Select Chip Version + */ +#undef CONFIG_CHIP_A_CUT +#define CONFIG_CHIP_B_CUT 1 +#undef CONFIG_CHIP_C_CUT + +/* + * < Build Option + */ +#define CONFIG_LINK_ROM_LIB 1 +#undef CONFIG_LINK_ROM_SYMB +#undef CONFIG_NORMAL_BUILD +#undef CONFIG_RELEASE_BUILD +#undef CONFIG_RELEASE_BUILD_LIBRARIES +#undef CONFIG_LIB_BUILD_RAM +#define CONFIG_RELEASE_BUILD_RAM_ALL 1 +#undef CONFIG_IMAGE_ALL +#define CONFIG_IMAGE_SEPARATE 1 diff --git a/project/realtek_ameba1_va0_example/inc/platform_opts.h b/project/realtek_ameba1_va0_example/inc/platform_opts.h new file mode 100644 index 0000000..4405eaa --- /dev/null +++ b/project/realtek_ameba1_va0_example/inc/platform_opts.h @@ -0,0 +1,102 @@ +/** + ****************************************************************************** + *This file contains general configurations for ameba platform + ****************************************************************************** +*/ + +#ifndef __PLATFORM_OPTS_H__ +#define __PLATFORM_OPTS_H__ + +/*For MP mode setting*/ +#define SUPPORT_MP_MODE 1 + +/** + * For AT cmd Log service configurations + */ +#define SUPPORT_LOG_SERVICE 1 +#if SUPPORT_LOG_SERVICE +#define LOG_SERVICE_BUFLEN 100 //can't larger than UART_LOG_CMD_BUFLEN(127) +#define CONFIG_LOG_HISTORY 0 +#if CONFIG_LOG_HISTORY +#define LOG_HISTORY_LEN 5 +#endif +#define SUPPORT_INTERACTIVE_MODE 0//on/off wifi_interactive_mode +#endif + +/** + * For interactive mode configurations, depents on log service + */ +#if SUPPORT_INTERACTIVE_MODE +#define CONFIG_INTERACTIVE_MODE 1 +#define CONFIG_INTERACTIVE_EXT 0 +#else +#define CONFIG_INTERACTIVE_MODE 0 +#define CONFIG_INTERACTIVE_EXT 0 +#endif +/******************************************************************************/ + + +/** + * For Wlan configurations + */ +#define CONFIG_WLAN 1 +#if CONFIG_WLAN +#define CONFIG_LWIP_LAYER 1 +#define CONFIG_INIT_NET 1 //init lwip layer when start up + +//on/off relative commands in log service +#define CONFIG_SSL_CLIENT 0 +#define CONFIG_WEBSERVER 1 +#define CONFIG_OTA_UPDATE 1 +#define CONFIG_BSD_TCP 0 +#define CONFIG_ENABLE_P2P 0//on/off p2p cmd in log_service or interactive mode + +/* For WPS and P2P */ +#define CONFIG_WPS +#if defined(CONFIG_WPS) +#define CONFIG_ENABLE_WPS 1 +#endif + +/* For Simple Link */ +#define CONFIG_INCLUDE_SIMPLE_CONFIG 1 + +/*For fast reconnection*/ +#define CONFIG_EXAMPLE_WLAN_FAST_CONNECT 1 + +#endif //end of #if CONFIG_WLAN +/*******************************************************************************/ + +/** + * For iNIC configurations + */ +#define CONFIG_INIC_EN 0//enable iNIC mode +#if CONFIG_INIC_EN +#undef CONFIG_LWIP_LAYER +#define CONFIG_LWIP_LAYER 0 +#define CONFIG_INIC_SDIO_HCI 1 //for SDIO or USB iNIC +#define CONFIG_INIC_USB_HCI 0 +#endif + + +/*For google nest example, make sure the TCP is open*/ +#define CONFIG_EXAMPLE_GOOGLE_NEST 0 + +/* For mDNS example */ +#define CONFIG_EXAMPLE_MDNS 0 + +/* For multicast example */ +#define CONFIG_EXAMPLE_MCAST 0 + +/* For uart adapter example */ +/* Please also configure LWIP_IGMP to 1 and LWIP_TCP_DELAY_DISABLE to 1 +in lwip_opt.h for support uart adapter*/ +#define CONFIG_EXAMPLE_UART_ADAPTER 0 +#if CONFIG_EXAMPLE_UART_ADAPTER +#undef CONFIG_EXAMPLE_WLAN_FAST_CONNECT +#define CONFIG_EXAMPLE_WLAN_FAST_CONNECT 1 +#undef CONFIG_EXAMPLE_MDNS +#define CONFIG_EXAMPLE_MDNS 1 +#define LWIP_IGMP 1 +#endif + +#endif diff --git a/project/realtek_ameba1_va0_example/inc/ws2812b.h b/project/realtek_ameba1_va0_example/inc/ws2812b.h new file mode 100644 index 0000000..a6dd2bc --- /dev/null +++ b/project/realtek_ameba1_va0_example/inc/ws2812b.h @@ -0,0 +1,22 @@ + + + +#ifndef __WS2812B_H__ +#define __WS2812B_H__ + + + +typedef struct { + void (*init)(void); +} ws2812b_t; + + + +extern ws2812b_t ws2812b; + + + +#endif + + + diff --git a/project/realtek_ameba1_va0_example/src/main.c b/project/realtek_ameba1_va0_example/src/main.c new file mode 100644 index 0000000..ace32d5 --- /dev/null +++ b/project/realtek_ameba1_va0_example/src/main.c @@ -0,0 +1,16 @@ + + + +#include "ws2812b.h" + + + +int main() { + + ws2812b.init(); + + return 0; +} + + + diff --git a/project/realtek_ameba1_va0_example/src/ws2812b.c b/project/realtek_ameba1_va0_example/src/ws2812b.c new file mode 100644 index 0000000..25aa001 --- /dev/null +++ b/project/realtek_ameba1_va0_example/src/ws2812b.c @@ -0,0 +1,287 @@ + + + +#include +#include +#include +#include +#include + +#include "ws2812b.h" + + + +#define GPIO_WS2811_PIN PA_0 +#define NUM_LEDS 60 + + + +extern wlan_init_done_ptr p_wlan_init_done_callback; + + + +gpio_t gpio_ws2811; + + + + + + +int _wlan_init_done_callback() { printf("%s()\n", __FUNCTION__); + + /* Wlan Set Access Point SSID */ + fATW3("ameba_smart_lighting"); + + /* Set Access Point Security Key */ + fATW4("proscendameba"); + + /* Wlan Set Access Point Channel */ + fATW5("1"); + + /* Wlan Activate Access Point */ + fATWA(); + + /* Wlan Start Web Server */ + fATWE(); + + return 0; +} + + + + + + + + + + + + + + +u8 _r, _g, _b; + + + +/* +** data reansfer time(TH + TL = 1.25us +- 600ns) +** +** +-----+---------------------------+------------+---------+ +** | T0H | 0 code, high voltage time | 0.4us | +-150ns | +** +-----+---------------------------+------------+---------+ +** | T1H | 1 code, high voltage time | 0.8us | +-150ns | +** +-----+---------------------------+------------+---------+ +** | T0L | 0 code, low voltage time | 0.85us | +-150ns | +** +-----+---------------------------+------------+---------+ +** | T1L | 1 code, low voltage time | 0.45us | +-150ns | +** +-----+---------------------------+------------+---------+ +** | RES | low voltage time | Above 50us | | +** +-----+---------------------------+------------+---------+ +** +*/ + + + +void Ai_WS2811_sendByte(u8 b) { + + u8 i = 8; + + do { + if ( (b & 0x80) == 0) { /* send a '0', T0H + T0L */ + /* T0H, 0 code, high voltage time, 0.4us +- 150ns */ + HAL_WRITE32(GPIO_REG_BASE, GPIO_PORTA_DR, 0x00000001); // 96ns + HAL_WRITE32(GPIO_REG_BASE, GPIO_PORTA_DR, 0x00000001); // 96ns + HAL_WRITE32(GPIO_REG_BASE, GPIO_PORTA_DR, 0x00000001); // 96ns + HAL_WRITE32(GPIO_REG_BASE, GPIO_PORTA_DR, 0x00000001); // 96ns + /* T0L, 0 code, low voltage time, 0.85us +-150ns */ + HAL_WRITE32(GPIO_REG_BASE, GPIO_PORTA_DR, 0x00000000); // 96ns + HAL_WRITE32(GPIO_REG_BASE, GPIO_PORTA_DR, 0x00000000); // 96ns + HAL_WRITE32(GPIO_REG_BASE, GPIO_PORTA_DR, 0x00000000); // 96ns + HAL_WRITE32(GPIO_REG_BASE, GPIO_PORTA_DR, 0x00000000); // 96ns + HAL_WRITE32(GPIO_REG_BASE, GPIO_PORTA_DR, 0x00000000); // 96ns + HAL_WRITE32(GPIO_REG_BASE, GPIO_PORTA_DR, 0x00000000); // 96ns + HAL_WRITE32(GPIO_REG_BASE, GPIO_PORTA_DR, 0x00000000); // 96ns + HAL_WRITE32(GPIO_REG_BASE, GPIO_PORTA_DR, 0x00000000); // 96ns + HAL_WRITE32(GPIO_REG_BASE, GPIO_PORTA_DR, 0x00000000); // 96ns + } else { /* send a '1', T1H + T1L */ + /* T1H, 1 code, high voltage time, 0.8us +- 150ns */ + HAL_WRITE32(GPIO_REG_BASE, GPIO_PORTA_DR, 0x00000001); // 96ns + HAL_WRITE32(GPIO_REG_BASE, GPIO_PORTA_DR, 0x00000001); // 96ns + HAL_WRITE32(GPIO_REG_BASE, GPIO_PORTA_DR, 0x00000001); // 96ns + HAL_WRITE32(GPIO_REG_BASE, GPIO_PORTA_DR, 0x00000001); // 96ns + HAL_WRITE32(GPIO_REG_BASE, GPIO_PORTA_DR, 0x00000001); // 96ns + HAL_WRITE32(GPIO_REG_BASE, GPIO_PORTA_DR, 0x00000001); // 96ns + HAL_WRITE32(GPIO_REG_BASE, GPIO_PORTA_DR, 0x00000001); // 96ns + HAL_WRITE32(GPIO_REG_BASE, GPIO_PORTA_DR, 0x00000001); // 96ns + /* T1L, 1 code, low voltage time, 0.45us +-150ns */ + HAL_WRITE32(GPIO_REG_BASE, GPIO_PORTA_DR, 0x00000000); // 96ns + HAL_WRITE32(GPIO_REG_BASE, GPIO_PORTA_DR, 0x00000000); // 96ns + HAL_WRITE32(GPIO_REG_BASE, GPIO_PORTA_DR, 0x00000000); // 96ns + HAL_WRITE32(GPIO_REG_BASE, GPIO_PORTA_DR, 0x00000000); // 96ns + HAL_WRITE32(GPIO_REG_BASE, GPIO_PORTA_DR, 0x00000000); // 96ns + } + b = b + b; + } while (-- i != 0); +} + + + +void Ai_WS2811_send() { + Ai_WS2811_sendByte(_g); + Ai_WS2811_sendByte(_r); + Ai_WS2811_sendByte(_b); +} + + + +void Ai_WS2811_setColor(u8 r, u8 g, u8 b) { + printf("%s: (r,g,b) = (%d,%d,%d)\n", __FUNCTION__, r,g,b); + + _r = r; + _g = g; + _b = b; +} + + + + + + +void sendLEDs() { + u8 i; + taskENTER_CRITICAL(); + for (i = 0; i < NUM_LEDS; ++ i) { + Ai_WS2811_send(); + } + taskEXIT_CRITICAL(); +} + + + + + + + + + + +u16 Blink_ms = 500; +u8 IsBlink = 0; + +u8 IsMeteor = 0; + +u8 Config_r, Config_g, Config_b; + +u8 BackgroudColor[NUM_LEDS][3] = { + {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, + {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, + {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, + {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, + {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, + {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, +}; + + + + + + +void vTaskFunction(void *pvParameters) { + + static int i = 0; + + static int meteorIdx = 0; + + int meteor_length = 8; + int meteor_head_idx = 0; + int meteor_tail_idx = meteor_head_idx - (meteor_length - 1); + + static int blinking = 0; + + portTickType xLastWakeTime = xTaskGetTickCount(); + + for( ;; ) { + + + + if (IsBlink) { + if (blinking) { + Ai_WS2811_setColor(Config_r, Config_g, Config_b); + sendLEDs(); + } else { + Ai_WS2811_setColor(0, 0, 0); + sendLEDs(); + } + blinking ^= 1; + } else if (IsMeteor) { + + taskENTER_CRITICAL(); + + for (i = 0; i < NUM_LEDS; ++ i) { + + if ( (i <= meteor_head_idx) && (i >= meteor_tail_idx)) { + Ai_WS2811_sendByte(Config_g - (meteor_head_idx - i) * (Config_g /meteor_length)); + Ai_WS2811_sendByte(Config_r - (meteor_head_idx - i) * (Config_r /meteor_length)); + Ai_WS2811_sendByte(Config_b - (meteor_head_idx - i) * (Config_b /meteor_length)); + } else { + Ai_WS2811_sendByte(BackgroudColor[i][0]); + Ai_WS2811_sendByte(BackgroudColor[i][1]); + Ai_WS2811_sendByte(BackgroudColor[i][2]); + } + + } + + taskEXIT_CRITICAL(); + + //meteorIdx = (meteorIdx + 1) % NUM_LEDS; + meteor_head_idx = (meteor_head_idx + 1) % (NUM_LEDS + (meteor_length - 1)); + meteor_tail_idx = meteor_head_idx - (meteor_length - 1); + + } + + + vTaskDelayUntil( &xLastWakeTime, ( Blink_ms / portTICK_RATE_MS ) ); + } + +} + + + + + + + + + +void _init(void) { printf("%s\n", __FUNCTION__); + + gpio_init(&gpio_ws2811, GPIO_WS2811_PIN); + gpio_dir(&gpio_ws2811, PIN_OUTPUT); + gpio_mode(&gpio_ws2811, PullNone); + + + + /* Call back from wlan driver after wlan init done */ + p_wlan_init_done_callback = _wlan_init_done_callback; + + /* wlan intialization */ + wlan_network(); + + + + xTaskCreate( vTaskFunction, "Task", 1000, (void*)vTaskFunction, 1, NULL ); + + /* Start the scheduler so the tasks start executing. */ + vTaskStartScheduler(); + + + +} + + + +ws2812b_t ws2812b = { + .init = _init, +}; +